am 76b1be8b: am 39cc8f80: am 4233c939: Merge "Doc Update: param name change" into jb-dev-docs

* commit '76b1be8b78bbb1bdfaf78a848c20b77cb7b0dedf':
  Doc Update: param name change
diff --git a/Android.mk b/Android.mk
index b9157fe..d38150f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -74,10 +74,12 @@
 	core/java/android/app/ISearchManager.aidl \
 	core/java/android/app/ISearchManagerCallback.aidl \
 	core/java/android/app/IServiceConnection.aidl \
+	core/java/android/app/IStopUserCallback.aidl \
 	core/java/android/app/IThumbnailReceiver.aidl \
 	core/java/android/app/IThumbnailRetriever.aidl \
 	core/java/android/app/ITransientNotification.aidl \
 	core/java/android/app/IUiModeManager.aidl \
+    core/java/android/app/IUserSwitchObserver.aidl \
 	core/java/android/app/IWallpaperManager.aidl \
 	core/java/android/app/IWallpaperManagerCallback.aidl \
 	core/java/android/app/admin/IDevicePolicyManager.aidl \
@@ -89,7 +91,13 @@
 	core/java/android/bluetooth/IBluetoothA2dp.aidl \
 	core/java/android/bluetooth/IBluetoothCallback.aidl \
 	core/java/android/bluetooth/IBluetoothHeadset.aidl \
+	core/java/android/bluetooth/IBluetoothHeadsetPhone.aidl \
+	core/java/android/bluetooth/IBluetoothHealth.aidl \
 	core/java/android/bluetooth/IBluetoothHealthCallback.aidl \
+	core/java/android/bluetooth/IBluetoothInputDevice.aidl \
+	core/java/android/bluetooth/IBluetoothPan.aidl \
+	core/java/android/bluetooth/IBluetoothManager.aidl \
+	core/java/android/bluetooth/IBluetoothManagerCallback.aidl \
 	core/java/android/bluetooth/IBluetoothPbap.aidl \
 	core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \
 	core/java/android/content/IClipboard.aidl \
@@ -108,6 +116,8 @@
 	core/java/android/content/pm/IPackageStatsObserver.aidl \
 	core/java/android/database/IContentObserver.aidl \
 	core/java/android/hardware/ISerialManager.aidl \
+	core/java/android/hardware/display/IDisplayManager.aidl \
+	core/java/android/hardware/display/IDisplayManagerCallback.aidl \
 	core/java/android/hardware/input/IInputManager.aidl \
 	core/java/android/hardware/input/IInputDevicesChangedListener.aidl \
 	core/java/android/hardware/usb/IUsbManager.aidl \
@@ -132,6 +142,7 @@
 	core/java/android/os/IRemoteCallback.aidl \
 	core/java/android/os/ISchedulingPolicyService.aidl \
 	core/java/android/os/IUpdateLock.aidl \
+        core/java/android/os/IUserManager.aidl \
 	core/java/android/os/IVibratorService.aidl \
 	core/java/android/service/dreams/IDreamManager.aidl \
 	core/java/android/service/dreams/IDreamService.aidl \
@@ -143,6 +154,9 @@
 	core/java/android/view/accessibility/IAccessibilityManager.aidl \
 	core/java/android/view/accessibility/IAccessibilityManagerClient.aidl \
 	core/java/android/view/IApplicationToken.aidl \
+	core/java/android/view/IDisplayContentChangeListener.aidl \
+	core/java/android/view/IInputFilter.aidl \
+	core/java/android/view/IInputFilterHost.aidl \
 	core/java/android/view/IOnKeyguardExitResult.aidl \
 	core/java/android/view/IRotationWatcher.aidl \
 	core/java/android/view/IWindow.aidl \
@@ -188,8 +202,8 @@
 	location/java/android/location/IGpsStatusProvider.aidl \
 	location/java/android/location/ILocationListener.aidl \
 	location/java/android/location/ILocationManager.aidl \
-	location/java/android/location/ILocationProvider.aidl \
 	location/java/android/location/INetInitiatedListener.aidl \
+	location/java/com/android/internal/location/ILocationProvider.aidl \
 	media/java/android/media/IAudioService.aidl \
 	media/java/android/media/IAudioFocusDispatcher.aidl \
 	media/java/android/media/IAudioRoutesObserver.aidl \
@@ -227,9 +241,6 @@
 LOCAL_MODULE := framework
 LOCAL_MODULE_CLASS := JAVA_LIBRARIES
 
-LOCAL_NO_EMMA_INSTRUMENT := true
-LOCAL_NO_EMMA_COMPILE := true
-
 # List of classes and interfaces which should be loaded by the Zygote.
 LOCAL_JAVA_RESOURCE_FILES += $(LOCAL_PATH)/preloaded-classes
 
@@ -297,7 +308,11 @@
 	frameworks/base/graphics/java/android/graphics/Rect.aidl \
 	frameworks/base/graphics/java/android/graphics/Region.aidl \
 	frameworks/base/location/java/android/location/Criteria.aidl \
+	frameworks/base/location/java/android/location/Geofence.aidl \
 	frameworks/base/location/java/android/location/Location.aidl \
+	frameworks/base/location/java/android/location/LocationRequest.aidl \
+	frameworks/base/location/java/com/android/internal/location/ProviderProperties.aidl \
+	frameworks/base/location/java/com/android/internal/location/ProviderRequest.aidl \
 	frameworks/base/telephony/java/android/telephony/ServiceState.aidl \
 	frameworks/base/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
 	frameworks/base/telephony/java/com/android/internal/telephony/ITelephony.aidl \
@@ -414,6 +429,7 @@
     -since ./frameworks/base/api/14.txt 14 \
     -since ./frameworks/base/api/15.txt 15 \
     -since ./frameworks/base/api/16.txt 16 \
+    -since ./frameworks/base/api/17.txt 17 \
 		-werror -hide 113 \
 		-overview $(LOCAL_PATH)/core/java/overview.html
 
@@ -524,7 +540,7 @@
 
 ## SDK version identifiers used in the published docs
   # major[.minor] version for current SDK. (full releases only)
-framework_docs_SDK_VERSION:=4.1
+framework_docs_SDK_VERSION:=4.2
   # release version (ie "Release x")  (full releases only)
 framework_docs_SDK_REL_ID:=1
 
@@ -711,9 +727,6 @@
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE := ext
 
-LOCAL_NO_EMMA_INSTRUMENT := true
-LOCAL_NO_EMMA_COMPILE := true
-
 LOCAL_DX_FLAGS := --core-library
 
 include $(BUILD_JAVA_LIBRARY)
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 61e5b4c..14b3681 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -134,6 +134,9 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/accessibilityservice/IAccessibilityServiceClient.P)
 $(call add-clean-step, rm -f $(PRODUCT_OUT)/system/media/video/Disco*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing2_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing_intermediates)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/api/16.txt b/api/16.txt
index bc97e81..984b844 100644
--- a/api/16.txt
+++ b/api/16.txt
@@ -7324,7 +7324,6 @@
     method public void prepareForInsert();
     method public void prepareForReplace();
     method public long replace(android.content.ContentValues);
-    field public static final int TABLE_INFO_PRAGMA_DEFAULT_INDEX = 4; // 0x4
   }
 
   public final class DefaultDatabaseErrorHandler implements android.database.DatabaseErrorHandler {
@@ -15991,7 +15990,7 @@
     field public static final int PATTERN_SIMPLE_GLOB = 2; // 0x2
   }
 
-  public class PowerManager {
+  public final class PowerManager {
     method public void goToSleep(long);
     method public boolean isScreenOn();
     method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
@@ -16005,7 +16004,7 @@
     field public static final int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
   }
 
-  public class PowerManager.WakeLock {
+  public final class PowerManager.WakeLock {
     method public void acquire();
     method public void acquire(long);
     method public boolean isHeld();
@@ -22893,7 +22892,7 @@
     method protected void onApplyThemeResource(android.content.res.Resources.Theme, int, boolean);
   }
 
-  public class Display {
+  public final class Display {
     method public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point);
     method public int getDisplayId();
     method public deprecated int getHeight();
diff --git a/api/17.txt b/api/17.txt
new file mode 100644
index 0000000..6b893d5
--- /dev/null
+++ b/api/17.txt
@@ -0,0 +1,48901 @@
+package android {
+
+  public final class Manifest {
+    ctor public Manifest();
+  }
+
+  public static final class Manifest.permission {
+    ctor public Manifest.permission();
+    field public static final java.lang.String ACCESS_CHECKIN_PROPERTIES = "android.permission.ACCESS_CHECKIN_PROPERTIES";
+    field public static final java.lang.String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
+    field public static final java.lang.String ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION";
+    field public static final java.lang.String ACCESS_LOCATION_EXTRA_COMMANDS = "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS";
+    field public static final java.lang.String ACCESS_MOCK_LOCATION = "android.permission.ACCESS_MOCK_LOCATION";
+    field public static final java.lang.String ACCESS_NETWORK_STATE = "android.permission.ACCESS_NETWORK_STATE";
+    field public static final java.lang.String ACCESS_SURFACE_FLINGER = "android.permission.ACCESS_SURFACE_FLINGER";
+    field public static final java.lang.String ACCESS_WIFI_STATE = "android.permission.ACCESS_WIFI_STATE";
+    field public static final java.lang.String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER";
+    field public static final java.lang.String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL";
+    field public static final java.lang.String AUTHENTICATE_ACCOUNTS = "android.permission.AUTHENTICATE_ACCOUNTS";
+    field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
+    field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
+    field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
+    field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
+    field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
+    field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+    field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
+    field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
+    field public static final java.lang.String BIND_WALLPAPER = "android.permission.BIND_WALLPAPER";
+    field public static final java.lang.String BLUETOOTH = "android.permission.BLUETOOTH";
+    field public static final java.lang.String BLUETOOTH_ADMIN = "android.permission.BLUETOOTH_ADMIN";
+    field public static final java.lang.String BRICK = "android.permission.BRICK";
+    field public static final java.lang.String BROADCAST_PACKAGE_REMOVED = "android.permission.BROADCAST_PACKAGE_REMOVED";
+    field public static final java.lang.String BROADCAST_SMS = "android.permission.BROADCAST_SMS";
+    field public static final java.lang.String BROADCAST_STICKY = "android.permission.BROADCAST_STICKY";
+    field public static final java.lang.String BROADCAST_WAP_PUSH = "android.permission.BROADCAST_WAP_PUSH";
+    field public static final java.lang.String CALL_PHONE = "android.permission.CALL_PHONE";
+    field public static final java.lang.String CALL_PRIVILEGED = "android.permission.CALL_PRIVILEGED";
+    field public static final java.lang.String CAMERA = "android.permission.CAMERA";
+    field public static final java.lang.String CHANGE_COMPONENT_ENABLED_STATE = "android.permission.CHANGE_COMPONENT_ENABLED_STATE";
+    field public static final java.lang.String CHANGE_CONFIGURATION = "android.permission.CHANGE_CONFIGURATION";
+    field public static final java.lang.String CHANGE_NETWORK_STATE = "android.permission.CHANGE_NETWORK_STATE";
+    field public static final java.lang.String CHANGE_WIFI_MULTICAST_STATE = "android.permission.CHANGE_WIFI_MULTICAST_STATE";
+    field public static final java.lang.String CHANGE_WIFI_STATE = "android.permission.CHANGE_WIFI_STATE";
+    field public static final java.lang.String CLEAR_APP_CACHE = "android.permission.CLEAR_APP_CACHE";
+    field public static final java.lang.String CLEAR_APP_USER_DATA = "android.permission.CLEAR_APP_USER_DATA";
+    field public static final java.lang.String CONTROL_LOCATION_UPDATES = "android.permission.CONTROL_LOCATION_UPDATES";
+    field public static final java.lang.String DELETE_CACHE_FILES = "android.permission.DELETE_CACHE_FILES";
+    field public static final java.lang.String DELETE_PACKAGES = "android.permission.DELETE_PACKAGES";
+    field public static final java.lang.String DEVICE_POWER = "android.permission.DEVICE_POWER";
+    field public static final java.lang.String DIAGNOSTIC = "android.permission.DIAGNOSTIC";
+    field public static final java.lang.String DISABLE_KEYGUARD = "android.permission.DISABLE_KEYGUARD";
+    field public static final java.lang.String DUMP = "android.permission.DUMP";
+    field public static final java.lang.String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR";
+    field public static final java.lang.String FACTORY_TEST = "android.permission.FACTORY_TEST";
+    field public static final java.lang.String FLASHLIGHT = "android.permission.FLASHLIGHT";
+    field public static final java.lang.String FORCE_BACK = "android.permission.FORCE_BACK";
+    field public static final java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
+    field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
+    field public static final java.lang.String GET_TASKS = "android.permission.GET_TASKS";
+    field public static final java.lang.String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH";
+    field public static final java.lang.String HARDWARE_TEST = "android.permission.HARDWARE_TEST";
+    field public static final java.lang.String INJECT_EVENTS = "android.permission.INJECT_EVENTS";
+    field public static final java.lang.String INSTALL_LOCATION_PROVIDER = "android.permission.INSTALL_LOCATION_PROVIDER";
+    field public static final java.lang.String INSTALL_PACKAGES = "android.permission.INSTALL_PACKAGES";
+    field public static final java.lang.String INTERNAL_SYSTEM_WINDOW = "android.permission.INTERNAL_SYSTEM_WINDOW";
+    field public static final java.lang.String INTERNET = "android.permission.INTERNET";
+    field public static final java.lang.String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
+    field public static final java.lang.String MANAGE_ACCOUNTS = "android.permission.MANAGE_ACCOUNTS";
+    field public static final java.lang.String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
+    field public static final java.lang.String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
+    field public static final java.lang.String MODIFY_AUDIO_SETTINGS = "android.permission.MODIFY_AUDIO_SETTINGS";
+    field public static final java.lang.String MODIFY_PHONE_STATE = "android.permission.MODIFY_PHONE_STATE";
+    field public static final java.lang.String MOUNT_FORMAT_FILESYSTEMS = "android.permission.MOUNT_FORMAT_FILESYSTEMS";
+    field public static final java.lang.String MOUNT_UNMOUNT_FILESYSTEMS = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS";
+    field public static final java.lang.String NFC = "android.permission.NFC";
+    field public static final deprecated java.lang.String PERSISTENT_ACTIVITY = "android.permission.PERSISTENT_ACTIVITY";
+    field public static final java.lang.String PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS";
+    field public static final java.lang.String READ_CALENDAR = "android.permission.READ_CALENDAR";
+    field public static final java.lang.String READ_CALL_LOG = "android.permission.READ_CALL_LOG";
+    field public static final java.lang.String READ_CONTACTS = "android.permission.READ_CONTACTS";
+    field public static final java.lang.String READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE";
+    field public static final java.lang.String READ_FRAME_BUFFER = "android.permission.READ_FRAME_BUFFER";
+    field public static final java.lang.String READ_HISTORY_BOOKMARKS = "com.android.browser.permission.READ_HISTORY_BOOKMARKS";
+    field public static final deprecated java.lang.String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE";
+    field public static final java.lang.String READ_LOGS = "android.permission.READ_LOGS";
+    field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
+    field public static final java.lang.String READ_PROFILE = "android.permission.READ_PROFILE";
+    field public static final java.lang.String READ_SMS = "android.permission.READ_SMS";
+    field public static final java.lang.String READ_SOCIAL_STREAM = "android.permission.READ_SOCIAL_STREAM";
+    field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
+    field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
+    field public static final java.lang.String READ_USER_DICTIONARY = "android.permission.READ_USER_DICTIONARY";
+    field public static final java.lang.String REBOOT = "android.permission.REBOOT";
+    field public static final java.lang.String RECEIVE_BOOT_COMPLETED = "android.permission.RECEIVE_BOOT_COMPLETED";
+    field public static final java.lang.String RECEIVE_MMS = "android.permission.RECEIVE_MMS";
+    field public static final java.lang.String RECEIVE_SMS = "android.permission.RECEIVE_SMS";
+    field public static final java.lang.String RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH";
+    field public static final java.lang.String RECORD_AUDIO = "android.permission.RECORD_AUDIO";
+    field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS";
+    field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
+    field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
+    field public static final java.lang.String SET_ACTIVITY_WATCHER = "android.permission.SET_ACTIVITY_WATCHER";
+    field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM";
+    field public static final java.lang.String SET_ALWAYS_FINISH = "android.permission.SET_ALWAYS_FINISH";
+    field public static final java.lang.String SET_ANIMATION_SCALE = "android.permission.SET_ANIMATION_SCALE";
+    field public static final java.lang.String SET_DEBUG_APP = "android.permission.SET_DEBUG_APP";
+    field public static final java.lang.String SET_ORIENTATION = "android.permission.SET_ORIENTATION";
+    field public static final java.lang.String SET_POINTER_SPEED = "android.permission.SET_POINTER_SPEED";
+    field public static final deprecated java.lang.String SET_PREFERRED_APPLICATIONS = "android.permission.SET_PREFERRED_APPLICATIONS";
+    field public static final java.lang.String SET_PROCESS_LIMIT = "android.permission.SET_PROCESS_LIMIT";
+    field public static final java.lang.String SET_TIME = "android.permission.SET_TIME";
+    field public static final java.lang.String SET_TIME_ZONE = "android.permission.SET_TIME_ZONE";
+    field public static final java.lang.String SET_WALLPAPER = "android.permission.SET_WALLPAPER";
+    field public static final java.lang.String SET_WALLPAPER_HINTS = "android.permission.SET_WALLPAPER_HINTS";
+    field public static final java.lang.String SIGNAL_PERSISTENT_PROCESSES = "android.permission.SIGNAL_PERSISTENT_PROCESSES";
+    field public static final java.lang.String STATUS_BAR = "android.permission.STATUS_BAR";
+    field public static final java.lang.String SUBSCRIBED_FEEDS_READ = "android.permission.SUBSCRIBED_FEEDS_READ";
+    field public static final java.lang.String SUBSCRIBED_FEEDS_WRITE = "android.permission.SUBSCRIBED_FEEDS_WRITE";
+    field public static final java.lang.String SYSTEM_ALERT_WINDOW = "android.permission.SYSTEM_ALERT_WINDOW";
+    field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
+    field public static final java.lang.String USE_CREDENTIALS = "android.permission.USE_CREDENTIALS";
+    field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
+    field public static final java.lang.String VIBRATE = "android.permission.VIBRATE";
+    field public static final java.lang.String WAKE_LOCK = "android.permission.WAKE_LOCK";
+    field public static final java.lang.String WRITE_APN_SETTINGS = "android.permission.WRITE_APN_SETTINGS";
+    field public static final java.lang.String WRITE_CALENDAR = "android.permission.WRITE_CALENDAR";
+    field public static final java.lang.String WRITE_CALL_LOG = "android.permission.WRITE_CALL_LOG";
+    field public static final java.lang.String WRITE_CONTACTS = "android.permission.WRITE_CONTACTS";
+    field public static final java.lang.String WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE";
+    field public static final java.lang.String WRITE_GSERVICES = "android.permission.WRITE_GSERVICES";
+    field public static final java.lang.String WRITE_HISTORY_BOOKMARKS = "com.android.browser.permission.WRITE_HISTORY_BOOKMARKS";
+    field public static final java.lang.String WRITE_PROFILE = "android.permission.WRITE_PROFILE";
+    field public static final java.lang.String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS";
+    field public static final java.lang.String WRITE_SETTINGS = "android.permission.WRITE_SETTINGS";
+    field public static final java.lang.String WRITE_SMS = "android.permission.WRITE_SMS";
+    field public static final java.lang.String WRITE_SOCIAL_STREAM = "android.permission.WRITE_SOCIAL_STREAM";
+    field public static final java.lang.String WRITE_SYNC_SETTINGS = "android.permission.WRITE_SYNC_SETTINGS";
+    field public static final java.lang.String WRITE_USER_DICTIONARY = "android.permission.WRITE_USER_DICTIONARY";
+  }
+
+  public static final class Manifest.permission_group {
+    ctor public Manifest.permission_group();
+    field public static final java.lang.String ACCOUNTS = "android.permission-group.ACCOUNTS";
+    field public static final java.lang.String AFFECTS_BATTERY = "android.permission-group.AFFECTS_BATTERY";
+    field public static final java.lang.String APP_INFO = "android.permission-group.APP_INFO";
+    field public static final java.lang.String AUDIO_SETTINGS = "android.permission-group.AUDIO_SETTINGS";
+    field public static final java.lang.String BLUETOOTH_NETWORK = "android.permission-group.BLUETOOTH_NETWORK";
+    field public static final java.lang.String BOOKMARKS = "android.permission-group.BOOKMARKS";
+    field public static final java.lang.String CALENDAR = "android.permission-group.CALENDAR";
+    field public static final java.lang.String CAMERA = "android.permission-group.CAMERA";
+    field public static final java.lang.String COST_MONEY = "android.permission-group.COST_MONEY";
+    field public static final java.lang.String DEVELOPMENT_TOOLS = "android.permission-group.DEVELOPMENT_TOOLS";
+    field public static final java.lang.String DEVICE_ALARMS = "android.permission-group.DEVICE_ALARMS";
+    field public static final java.lang.String DISPLAY = "android.permission-group.DISPLAY";
+    field public static final java.lang.String HARDWARE_CONTROLS = "android.permission-group.HARDWARE_CONTROLS";
+    field public static final java.lang.String LOCATION = "android.permission-group.LOCATION";
+    field public static final java.lang.String MESSAGES = "android.permission-group.MESSAGES";
+    field public static final java.lang.String MICROPHONE = "android.permission-group.MICROPHONE";
+    field public static final java.lang.String NETWORK = "android.permission-group.NETWORK";
+    field public static final java.lang.String PERSONAL_INFO = "android.permission-group.PERSONAL_INFO";
+    field public static final java.lang.String PHONE_CALLS = "android.permission-group.PHONE_CALLS";
+    field public static final java.lang.String SCREENLOCK = "android.permission-group.SCREENLOCK";
+    field public static final java.lang.String SOCIAL_INFO = "android.permission-group.SOCIAL_INFO";
+    field public static final java.lang.String STATUS_BAR = "android.permission-group.STATUS_BAR";
+    field public static final java.lang.String STORAGE = "android.permission-group.STORAGE";
+    field public static final java.lang.String SYNC_SETTINGS = "android.permission-group.SYNC_SETTINGS";
+    field public static final java.lang.String SYSTEM_CLOCK = "android.permission-group.SYSTEM_CLOCK";
+    field public static final java.lang.String SYSTEM_TOOLS = "android.permission-group.SYSTEM_TOOLS";
+    field public static final java.lang.String USER_DICTIONARY = "android.permission-group.USER_DICTIONARY";
+    field public static final java.lang.String VOICEMAIL = "android.permission-group.VOICEMAIL";
+    field public static final java.lang.String WALLPAPER = "android.permission-group.WALLPAPER";
+    field public static final java.lang.String WRITE_USER_DICTIONARY = "android.permission-group.WRITE_USER_DICTIONARY";
+  }
+
+  public final class R {
+    ctor public R();
+  }
+
+  public static final class R.anim {
+    ctor public R.anim();
+    field public static final int accelerate_decelerate_interpolator = 17432580; // 0x10a0004
+    field public static final int accelerate_interpolator = 17432581; // 0x10a0005
+    field public static final int anticipate_interpolator = 17432583; // 0x10a0007
+    field public static final int anticipate_overshoot_interpolator = 17432585; // 0x10a0009
+    field public static final int bounce_interpolator = 17432586; // 0x10a000a
+    field public static final int cycle_interpolator = 17432588; // 0x10a000c
+    field public static final int decelerate_interpolator = 17432582; // 0x10a0006
+    field public static final int fade_in = 17432576; // 0x10a0000
+    field public static final int fade_out = 17432577; // 0x10a0001
+    field public static final int linear_interpolator = 17432587; // 0x10a000b
+    field public static final int overshoot_interpolator = 17432584; // 0x10a0008
+    field public static final int slide_in_left = 17432578; // 0x10a0002
+    field public static final int slide_out_right = 17432579; // 0x10a0003
+  }
+
+  public static final class R.animator {
+    ctor public R.animator();
+    field public static final int fade_in = 17498112; // 0x10b0000
+    field public static final int fade_out = 17498113; // 0x10b0001
+  }
+
+  public static final class R.array {
+    ctor public R.array();
+    field public static final int emailAddressTypes = 17235968; // 0x1070000
+    field public static final int imProtocols = 17235969; // 0x1070001
+    field public static final int organizationTypes = 17235970; // 0x1070002
+    field public static final int phoneTypes = 17235971; // 0x1070003
+    field public static final int postalAddressTypes = 17235972; // 0x1070004
+  }
+
+  public static final class R.attr {
+    ctor public R.attr();
+    field public static final int absListViewStyle = 16842858; // 0x101006a
+    field public static final int accessibilityEventTypes = 16843648; // 0x1010380
+    field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
+    field public static final int accessibilityFlags = 16843652; // 0x1010384
+    field public static final int accountPreferences = 16843423; // 0x101029f
+    field public static final int accountType = 16843407; // 0x101028f
+    field public static final int action = 16842797; // 0x101002d
+    field public static final int actionBarDivider = 16843675; // 0x101039b
+    field public static final int actionBarItemBackground = 16843676; // 0x101039c
+    field public static final int actionBarSize = 16843499; // 0x10102eb
+    field public static final int actionBarSplitStyle = 16843656; // 0x1010388
+    field public static final int actionBarStyle = 16843470; // 0x10102ce
+    field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4
+    field public static final int actionBarTabStyle = 16843507; // 0x10102f3
+    field public static final int actionBarTabTextStyle = 16843509; // 0x10102f5
+    field public static final int actionBarWidgetTheme = 16843671; // 0x1010397
+    field public static final int actionButtonStyle = 16843480; // 0x10102d8
+    field public static final int actionDropDownStyle = 16843479; // 0x10102d7
+    field public static final int actionLayout = 16843515; // 0x10102fb
+    field public static final int actionMenuTextAppearance = 16843616; // 0x1010360
+    field public static final int actionMenuTextColor = 16843617; // 0x1010361
+    field public static final int actionModeBackground = 16843483; // 0x10102db
+    field public static final int actionModeCloseButtonStyle = 16843511; // 0x10102f7
+    field public static final int actionModeCloseDrawable = 16843484; // 0x10102dc
+    field public static final int actionModeCopyDrawable = 16843538; // 0x1010312
+    field public static final int actionModeCutDrawable = 16843537; // 0x1010311
+    field public static final int actionModePasteDrawable = 16843539; // 0x1010313
+    field public static final int actionModeSelectAllDrawable = 16843646; // 0x101037e
+    field public static final int actionModeSplitBackground = 16843677; // 0x101039d
+    field public static final int actionModeStyle = 16843668; // 0x1010394
+    field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6
+    field public static final int actionProviderClass = 16843657; // 0x1010389
+    field public static final int actionViewClass = 16843516; // 0x10102fc
+    field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
+    field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
+    field public static final int activityCloseExitAnimation = 16842939; // 0x10100bb
+    field public static final int activityOpenEnterAnimation = 16842936; // 0x10100b8
+    field public static final int activityOpenExitAnimation = 16842937; // 0x10100b9
+    field public static final int addStatesFromChildren = 16842992; // 0x10100f0
+    field public static final int adjustViewBounds = 16843038; // 0x101011e
+    field public static final int alertDialogIcon = 16843605; // 0x1010355
+    field public static final int alertDialogStyle = 16842845; // 0x101005d
+    field public static final int alertDialogTheme = 16843529; // 0x1010309
+    field public static final int alignmentMode = 16843642; // 0x101037a
+    field public static final int allContactsName = 16843468; // 0x10102cc
+    field public static final int allowBackup = 16843392; // 0x1010280
+    field public static final int allowClearUserData = 16842757; // 0x1010005
+    field public static final int allowParallelSyncs = 16843570; // 0x1010332
+    field public static final int allowSingleTap = 16843353; // 0x1010259
+    field public static final int allowTaskReparenting = 16843268; // 0x1010204
+    field public static final int alpha = 16843551; // 0x101031f
+    field public static final int alphabeticShortcut = 16843235; // 0x10101e3
+    field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
+    field public static final int alwaysRetainTaskState = 16843267; // 0x1010203
+    field public static final int angle = 16843168; // 0x10101a0
+    field public static final int animateFirstView = 16843477; // 0x10102d5
+    field public static final int animateLayoutChanges = 16843506; // 0x10102f2
+    field public static final int animateOnClick = 16843356; // 0x101025c
+    field public static final int animation = 16843213; // 0x10101cd
+    field public static final int animationCache = 16842989; // 0x10100ed
+    field public static final int animationDuration = 16843026; // 0x1010112
+    field public static final int animationOrder = 16843214; // 0x10101ce
+    field public static final deprecated int animationResolution = 16843546; // 0x101031a
+    field public static final int antialias = 16843034; // 0x101011a
+    field public static final int anyDensity = 16843372; // 0x101026c
+    field public static final int apiKey = 16843281; // 0x1010211
+    field public static final int author = 16843444; // 0x10102b4
+    field public static final int authorities = 16842776; // 0x1010018
+    field public static final int autoAdvanceViewId = 16843535; // 0x101030f
+    field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b
+    field public static final int autoLink = 16842928; // 0x10100b0
+    field public static final int autoStart = 16843445; // 0x10102b5
+    field public static final deprecated int autoText = 16843114; // 0x101016a
+    field public static final int autoUrlDetect = 16843404; // 0x101028c
+    field public static final int background = 16842964; // 0x10100d4
+    field public static final int backgroundDimAmount = 16842802; // 0x1010032
+    field public static final int backgroundDimEnabled = 16843295; // 0x101021f
+    field public static final int backgroundSplit = 16843659; // 0x101038b
+    field public static final int backgroundStacked = 16843658; // 0x101038a
+    field public static final int backupAgent = 16843391; // 0x101027f
+    field public static final int baseline = 16843548; // 0x101031c
+    field public static final int baselineAlignBottom = 16843042; // 0x1010122
+    field public static final int baselineAligned = 16843046; // 0x1010126
+    field public static final int baselineAlignedChildIndex = 16843047; // 0x1010127
+    field public static final int borderlessButtonStyle = 16843563; // 0x101032b
+    field public static final int bottom = 16843184; // 0x10101b0
+    field public static final int bottomBright = 16842957; // 0x10100cd
+    field public static final int bottomDark = 16842953; // 0x10100c9
+    field public static final int bottomLeftRadius = 16843179; // 0x10101ab
+    field public static final int bottomMedium = 16842958; // 0x10100ce
+    field public static final int bottomOffset = 16843351; // 0x1010257
+    field public static final int bottomRightRadius = 16843180; // 0x10101ac
+    field public static final int breadCrumbShortTitle = 16843524; // 0x1010304
+    field public static final int breadCrumbTitle = 16843523; // 0x1010303
+    field public static final int bufferType = 16843086; // 0x101014e
+    field public static final int button = 16843015; // 0x1010107
+    field public static final int buttonBarButtonStyle = 16843567; // 0x101032f
+    field public static final int buttonBarStyle = 16843566; // 0x101032e
+    field public static final int buttonStyle = 16842824; // 0x1010048
+    field public static final int buttonStyleInset = 16842826; // 0x101004a
+    field public static final int buttonStyleSmall = 16842825; // 0x1010049
+    field public static final int buttonStyleToggle = 16842827; // 0x101004b
+    field public static final int cacheColorHint = 16843009; // 0x1010101
+    field public static final int calendarViewShown = 16843596; // 0x101034c
+    field public static final int calendarViewStyle = 16843613; // 0x101035d
+    field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
+    field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
+    field public static final deprecated int capitalize = 16843113; // 0x1010169
+    field public static final int centerBright = 16842956; // 0x10100cc
+    field public static final int centerColor = 16843275; // 0x101020b
+    field public static final int centerDark = 16842952; // 0x10100c8
+    field public static final int centerMedium = 16842959; // 0x10100cf
+    field public static final int centerX = 16843170; // 0x10101a2
+    field public static final int centerY = 16843171; // 0x10101a3
+    field public static final int checkBoxPreferenceStyle = 16842895; // 0x101008f
+    field public static final int checkMark = 16843016; // 0x1010108
+    field public static final int checkable = 16843237; // 0x10101e5
+    field public static final int checkableBehavior = 16843232; // 0x10101e0
+    field public static final int checkboxStyle = 16842860; // 0x101006c
+    field public static final int checked = 16843014; // 0x1010106
+    field public static final int checkedButton = 16843080; // 0x1010148
+    field public static final int checkedTextViewStyle = 16843720; // 0x10103c8
+    field public static final int childDivider = 16843025; // 0x1010111
+    field public static final int childIndicator = 16843020; // 0x101010c
+    field public static final int childIndicatorLeft = 16843023; // 0x101010f
+    field public static final int childIndicatorRight = 16843024; // 0x1010110
+    field public static final int choiceMode = 16843051; // 0x101012b
+    field public static final int clearTaskOnLaunch = 16842773; // 0x1010015
+    field public static final int clickable = 16842981; // 0x10100e5
+    field public static final int clipChildren = 16842986; // 0x10100ea
+    field public static final int clipOrientation = 16843274; // 0x101020a
+    field public static final int clipToPadding = 16842987; // 0x10100eb
+    field public static final int codes = 16843330; // 0x1010242
+    field public static final int collapseColumns = 16843083; // 0x101014b
+    field public static final int color = 16843173; // 0x10101a5
+    field public static final int colorActivatedHighlight = 16843664; // 0x1010390
+    field public static final int colorBackground = 16842801; // 0x1010031
+    field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
+    field public static final int colorFocusedHighlight = 16843663; // 0x101038f
+    field public static final int colorForeground = 16842800; // 0x1010030
+    field public static final int colorForegroundInverse = 16843270; // 0x1010206
+    field public static final int colorLongPressedHighlight = 16843662; // 0x101038e
+    field public static final int colorMultiSelectHighlight = 16843665; // 0x1010391
+    field public static final int colorPressedHighlight = 16843661; // 0x101038d
+    field public static final int columnCount = 16843639; // 0x1010377
+    field public static final int columnDelay = 16843215; // 0x10101cf
+    field public static final int columnOrderPreserved = 16843640; // 0x1010378
+    field public static final int columnWidth = 16843031; // 0x1010117
+    field public static final int compatibleWidthLimitDp = 16843621; // 0x1010365
+    field public static final int completionHint = 16843122; // 0x1010172
+    field public static final int completionHintView = 16843123; // 0x1010173
+    field public static final int completionThreshold = 16843124; // 0x1010174
+    field public static final int configChanges = 16842783; // 0x101001f
+    field public static final int configure = 16843357; // 0x101025d
+    field public static final int constantSize = 16843158; // 0x1010196
+    field public static final int content = 16843355; // 0x101025b
+    field public static final int contentAuthority = 16843408; // 0x1010290
+    field public static final int contentDescription = 16843379; // 0x1010273
+    field public static final int cropToPadding = 16843043; // 0x1010123
+    field public static final int cursorVisible = 16843090; // 0x1010152
+    field public static final int customNavigationLayout = 16843474; // 0x10102d2
+    field public static final int customTokens = 16843579; // 0x101033b
+    field public static final int cycles = 16843220; // 0x10101d4
+    field public static final int dashGap = 16843175; // 0x10101a7
+    field public static final int dashWidth = 16843174; // 0x10101a6
+    field public static final int data = 16842798; // 0x101002e
+    field public static final int datePickerStyle = 16843612; // 0x101035c
+    field public static final int dateTextAppearance = 16843593; // 0x1010349
+    field public static final int debuggable = 16842767; // 0x101000f
+    field public static final int defaultValue = 16843245; // 0x10101ed
+    field public static final int delay = 16843212; // 0x10101cc
+    field public static final int dependency = 16843244; // 0x10101ec
+    field public static final int descendantFocusability = 16842993; // 0x10100f1
+    field public static final int description = 16842784; // 0x1010020
+    field public static final int detachWallpaper = 16843430; // 0x10102a6
+    field public static final int detailColumn = 16843427; // 0x10102a3
+    field public static final int detailSocialSummary = 16843428; // 0x10102a4
+    field public static final int detailsElementBackground = 16843598; // 0x101034e
+    field public static final int dial = 16843010; // 0x1010102
+    field public static final int dialogIcon = 16843252; // 0x10101f4
+    field public static final int dialogLayout = 16843255; // 0x10101f7
+    field public static final int dialogMessage = 16843251; // 0x10101f3
+    field public static final int dialogPreferenceStyle = 16842897; // 0x1010091
+    field public static final int dialogTheme = 16843528; // 0x1010308
+    field public static final int dialogTitle = 16843250; // 0x10101f2
+    field public static final int digits = 16843110; // 0x1010166
+    field public static final int direction = 16843217; // 0x10101d1
+    field public static final int directionDescriptions = 16843681; // 0x10103a1
+    field public static final int directionPriority = 16843218; // 0x10101d2
+    field public static final int disableDependentsState = 16843249; // 0x10101f1
+    field public static final int disabledAlpha = 16842803; // 0x1010033
+    field public static final int displayOptions = 16843472; // 0x10102d0
+    field public static final int dither = 16843036; // 0x101011c
+    field public static final int divider = 16843049; // 0x1010129
+    field public static final int dividerHeight = 16843050; // 0x101012a
+    field public static final int dividerHorizontal = 16843564; // 0x101032c
+    field public static final int dividerPadding = 16843562; // 0x101032a
+    field public static final int dividerVertical = 16843530; // 0x101030a
+    field public static final int drawSelectorOnTop = 16843004; // 0x10100fc
+    field public static final int drawable = 16843161; // 0x1010199
+    field public static final int drawableBottom = 16843118; // 0x101016e
+    field public static final int drawableEnd = 16843667; // 0x1010393
+    field public static final int drawableLeft = 16843119; // 0x101016f
+    field public static final int drawablePadding = 16843121; // 0x1010171
+    field public static final int drawableRight = 16843120; // 0x1010170
+    field public static final int drawableStart = 16843666; // 0x1010392
+    field public static final int drawableTop = 16843117; // 0x101016d
+    field public static final int drawingCacheQuality = 16842984; // 0x10100e8
+    field public static final int dropDownAnchor = 16843363; // 0x1010263
+    field public static final int dropDownHeight = 16843395; // 0x1010283
+    field public static final int dropDownHintAppearance = 16842888; // 0x1010088
+    field public static final int dropDownHorizontalOffset = 16843436; // 0x10102ac
+    field public static final int dropDownItemStyle = 16842886; // 0x1010086
+    field public static final int dropDownListViewStyle = 16842861; // 0x101006d
+    field public static final int dropDownSelector = 16843125; // 0x1010175
+    field public static final int dropDownSpinnerStyle = 16843478; // 0x10102d6
+    field public static final int dropDownVerticalOffset = 16843437; // 0x10102ad
+    field public static final int dropDownWidth = 16843362; // 0x1010262
+    field public static final int duplicateParentState = 16842985; // 0x10100e9
+    field public static final int duration = 16843160; // 0x1010198
+    field public static final int editTextBackground = 16843602; // 0x1010352
+    field public static final int editTextColor = 16843601; // 0x1010351
+    field public static final int editTextPreferenceStyle = 16842898; // 0x1010092
+    field public static final int editTextStyle = 16842862; // 0x101006e
+    field public static final deprecated int editable = 16843115; // 0x101016b
+    field public static final int editorExtras = 16843300; // 0x1010224
+    field public static final int ellipsize = 16842923; // 0x10100ab
+    field public static final int ems = 16843096; // 0x1010158
+    field public static final int enabled = 16842766; // 0x101000e
+    field public static final int endColor = 16843166; // 0x101019e
+    field public static final deprecated int endYear = 16843133; // 0x101017d
+    field public static final int enterFadeDuration = 16843532; // 0x101030c
+    field public static final int entries = 16842930; // 0x10100b2
+    field public static final int entryValues = 16843256; // 0x10101f8
+    field public static final int eventsInterceptionEnabled = 16843389; // 0x101027d
+    field public static final int excludeFromRecents = 16842775; // 0x1010017
+    field public static final int exitFadeDuration = 16843533; // 0x101030d
+    field public static final int expandableListPreferredChildIndicatorLeft = 16842834; // 0x1010052
+    field public static final int expandableListPreferredChildIndicatorRight = 16842835; // 0x1010053
+    field public static final int expandableListPreferredChildPaddingLeft = 16842831; // 0x101004f
+    field public static final int expandableListPreferredItemIndicatorLeft = 16842832; // 0x1010050
+    field public static final int expandableListPreferredItemIndicatorRight = 16842833; // 0x1010051
+    field public static final int expandableListPreferredItemPaddingLeft = 16842830; // 0x101004e
+    field public static final int expandableListViewStyle = 16842863; // 0x101006f
+    field public static final int expandableListViewWhiteStyle = 16843446; // 0x10102b6
+    field public static final int exported = 16842768; // 0x1010010
+    field public static final int extraTension = 16843371; // 0x101026b
+    field public static final int factor = 16843219; // 0x10101d3
+    field public static final int fadeDuration = 16843384; // 0x1010278
+    field public static final int fadeEnabled = 16843390; // 0x101027e
+    field public static final int fadeOffset = 16843383; // 0x1010277
+    field public static final int fadeScrollbars = 16843434; // 0x10102aa
+    field public static final int fadingEdge = 16842975; // 0x10100df
+    field public static final int fadingEdgeLength = 16842976; // 0x10100e0
+    field public static final int fastScrollAlwaysVisible = 16843573; // 0x1010335
+    field public static final int fastScrollEnabled = 16843302; // 0x1010226
+    field public static final int fastScrollOverlayPosition = 16843578; // 0x101033a
+    field public static final int fastScrollPreviewBackgroundLeft = 16843575; // 0x1010337
+    field public static final int fastScrollPreviewBackgroundRight = 16843576; // 0x1010338
+    field public static final int fastScrollTextColor = 16843609; // 0x1010359
+    field public static final int fastScrollThumbDrawable = 16843574; // 0x1010336
+    field public static final int fastScrollTrackDrawable = 16843577; // 0x1010339
+    field public static final int fillAfter = 16843197; // 0x10101bd
+    field public static final int fillBefore = 16843196; // 0x10101bc
+    field public static final int fillEnabled = 16843343; // 0x101024f
+    field public static final int fillViewport = 16843130; // 0x101017a
+    field public static final int filter = 16843035; // 0x101011b
+    field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
+    field public static final int finishOnCloseSystemDialogs = 16843431; // 0x10102a7
+    field public static final int finishOnTaskLaunch = 16842772; // 0x1010014
+    field public static final int firstDayOfWeek = 16843581; // 0x101033d
+    field public static final int fitsSystemWindows = 16842973; // 0x10100dd
+    field public static final int flipInterval = 16843129; // 0x1010179
+    field public static final int focusable = 16842970; // 0x10100da
+    field public static final int focusableInTouchMode = 16842971; // 0x10100db
+    field public static final int focusedMonthDateColor = 16843587; // 0x1010343
+    field public static final int fontFamily = 16843692; // 0x10103ac
+    field public static final int footerDividersEnabled = 16843311; // 0x101022f
+    field public static final int foreground = 16843017; // 0x1010109
+    field public static final int foregroundGravity = 16843264; // 0x1010200
+    field public static final int format = 16843013; // 0x1010105
+    field public static final int format12Hour = 16843722; // 0x10103ca
+    field public static final int format24Hour = 16843723; // 0x10103cb
+    field public static final int fragment = 16843491; // 0x10102e3
+    field public static final int fragmentCloseEnterAnimation = 16843495; // 0x10102e7
+    field public static final int fragmentCloseExitAnimation = 16843496; // 0x10102e8
+    field public static final int fragmentFadeEnterAnimation = 16843497; // 0x10102e9
+    field public static final int fragmentFadeExitAnimation = 16843498; // 0x10102ea
+    field public static final int fragmentOpenEnterAnimation = 16843493; // 0x10102e5
+    field public static final int fragmentOpenExitAnimation = 16843494; // 0x10102e6
+    field public static final int freezesText = 16843116; // 0x101016c
+    field public static final int fromAlpha = 16843210; // 0x10101ca
+    field public static final int fromDegrees = 16843187; // 0x10101b3
+    field public static final int fromXDelta = 16843206; // 0x10101c6
+    field public static final int fromXScale = 16843202; // 0x10101c2
+    field public static final int fromYDelta = 16843208; // 0x10101c8
+    field public static final int fromYScale = 16843204; // 0x10101c4
+    field public static final int fullBright = 16842954; // 0x10100ca
+    field public static final int fullDark = 16842950; // 0x10100c6
+    field public static final int functionalTest = 16842787; // 0x1010023
+    field public static final int galleryItemBackground = 16842828; // 0x101004c
+    field public static final int galleryStyle = 16842864; // 0x1010070
+    field public static final int gestureColor = 16843381; // 0x1010275
+    field public static final int gestureStrokeAngleThreshold = 16843388; // 0x101027c
+    field public static final int gestureStrokeLengthThreshold = 16843386; // 0x101027a
+    field public static final int gestureStrokeSquarenessThreshold = 16843387; // 0x101027b
+    field public static final int gestureStrokeType = 16843385; // 0x1010279
+    field public static final int gestureStrokeWidth = 16843380; // 0x1010274
+    field public static final int glEsVersion = 16843393; // 0x1010281
+    field public static final int gradientRadius = 16843172; // 0x10101a4
+    field public static final int grantUriPermissions = 16842779; // 0x101001b
+    field public static final int gravity = 16842927; // 0x10100af
+    field public static final int gridViewStyle = 16842865; // 0x1010071
+    field public static final int groupIndicator = 16843019; // 0x101010b
+    field public static final int hand_hour = 16843011; // 0x1010103
+    field public static final int hand_minute = 16843012; // 0x1010104
+    field public static final int handle = 16843354; // 0x101025a
+    field public static final int handleProfiling = 16842786; // 0x1010022
+    field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
+    field public static final int hardwareAccelerated = 16843475; // 0x10102d3
+    field public static final int hasCode = 16842764; // 0x101000c
+    field public static final int headerBackground = 16843055; // 0x101012f
+    field public static final int headerDividersEnabled = 16843310; // 0x101022e
+    field public static final int height = 16843093; // 0x1010155
+    field public static final int hint = 16843088; // 0x1010150
+    field public static final int homeAsUpIndicator = 16843531; // 0x101030b
+    field public static final int homeLayout = 16843549; // 0x101031d
+    field public static final int horizontalDivider = 16843053; // 0x101012d
+    field public static final int horizontalGap = 16843327; // 0x101023f
+    field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
+    field public static final int horizontalSpacing = 16843028; // 0x1010114
+    field public static final int host = 16842792; // 0x1010028
+    field public static final int icon = 16842754; // 0x1010002
+    field public static final int iconPreview = 16843337; // 0x1010249
+    field public static final int iconifiedByDefault = 16843514; // 0x10102fa
+    field public static final int id = 16842960; // 0x10100d0
+    field public static final int ignoreGravity = 16843263; // 0x10101ff
+    field public static final int imageButtonStyle = 16842866; // 0x1010072
+    field public static final int imageWellStyle = 16842867; // 0x1010073
+    field public static final int imeActionId = 16843366; // 0x1010266
+    field public static final int imeActionLabel = 16843365; // 0x1010265
+    field public static final int imeExtractEnterAnimation = 16843368; // 0x1010268
+    field public static final int imeExtractExitAnimation = 16843369; // 0x1010269
+    field public static final int imeFullscreenBackground = 16843308; // 0x101022c
+    field public static final int imeOptions = 16843364; // 0x1010264
+    field public static final int imeSubtypeExtraValue = 16843502; // 0x10102ee
+    field public static final int imeSubtypeLocale = 16843500; // 0x10102ec
+    field public static final int imeSubtypeMode = 16843501; // 0x10102ed
+    field public static final int immersive = 16843456; // 0x10102c0
+    field public static final int importantForAccessibility = 16843690; // 0x10103aa
+    field public static final int inAnimation = 16843127; // 0x1010177
+    field public static final int includeFontPadding = 16843103; // 0x101015f
+    field public static final int includeInGlobalSearch = 16843374; // 0x101026e
+    field public static final int indeterminate = 16843065; // 0x1010139
+    field public static final int indeterminateBehavior = 16843070; // 0x101013e
+    field public static final int indeterminateDrawable = 16843067; // 0x101013b
+    field public static final int indeterminateDuration = 16843069; // 0x101013d
+    field public static final int indeterminateOnly = 16843066; // 0x101013a
+    field public static final int indeterminateProgressStyle = 16843544; // 0x1010318
+    field public static final int indicatorLeft = 16843021; // 0x101010d
+    field public static final int indicatorRight = 16843022; // 0x101010e
+    field public static final int inflatedId = 16842995; // 0x10100f3
+    field public static final int initOrder = 16842778; // 0x101001a
+    field public static final int initialKeyguardLayout = 16843714; // 0x10103c2
+    field public static final int initialLayout = 16843345; // 0x1010251
+    field public static final int innerRadius = 16843359; // 0x101025f
+    field public static final int innerRadiusRatio = 16843163; // 0x101019b
+    field public static final deprecated int inputMethod = 16843112; // 0x1010168
+    field public static final int inputType = 16843296; // 0x1010220
+    field public static final int insetBottom = 16843194; // 0x10101ba
+    field public static final int insetLeft = 16843191; // 0x10101b7
+    field public static final int insetRight = 16843192; // 0x10101b8
+    field public static final int insetTop = 16843193; // 0x10101b9
+    field public static final int installLocation = 16843447; // 0x10102b7
+    field public static final int interpolator = 16843073; // 0x1010141
+    field public static final int isAlwaysSyncable = 16843571; // 0x1010333
+    field public static final int isAuxiliary = 16843647; // 0x101037f
+    field public static final int isDefault = 16843297; // 0x1010221
+    field public static final int isIndicator = 16843079; // 0x1010147
+    field public static final int isModifier = 16843334; // 0x1010246
+    field public static final int isRepeatable = 16843336; // 0x1010248
+    field public static final int isScrollContainer = 16843342; // 0x101024e
+    field public static final int isSticky = 16843335; // 0x1010247
+    field public static final int isolatedProcess = 16843689; // 0x10103a9
+    field public static final int itemBackground = 16843056; // 0x1010130
+    field public static final int itemIconDisabledAlpha = 16843057; // 0x1010131
+    field public static final int itemPadding = 16843565; // 0x101032d
+    field public static final int itemTextAppearance = 16843052; // 0x101012c
+    field public static final int keepScreenOn = 16843286; // 0x1010216
+    field public static final int key = 16843240; // 0x10101e8
+    field public static final int keyBackground = 16843315; // 0x1010233
+    field public static final int keyEdgeFlags = 16843333; // 0x1010245
+    field public static final int keyHeight = 16843326; // 0x101023e
+    field public static final int keyIcon = 16843340; // 0x101024c
+    field public static final int keyLabel = 16843339; // 0x101024b
+    field public static final int keyOutputText = 16843338; // 0x101024a
+    field public static final int keyPreviewHeight = 16843321; // 0x1010239
+    field public static final int keyPreviewLayout = 16843319; // 0x1010237
+    field public static final int keyPreviewOffset = 16843320; // 0x1010238
+    field public static final int keyTextColor = 16843318; // 0x1010236
+    field public static final int keyTextSize = 16843316; // 0x1010234
+    field public static final int keyWidth = 16843325; // 0x101023d
+    field public static final int keyboardLayout = 16843691; // 0x10103ab
+    field public static final int keyboardMode = 16843341; // 0x101024d
+    field public static final int keycode = 16842949; // 0x10100c5
+    field public static final int killAfterRestore = 16843420; // 0x101029c
+    field public static final int label = 16842753; // 0x1010001
+    field public static final int labelFor = 16843718; // 0x10103c6
+    field public static final int labelTextSize = 16843317; // 0x1010235
+    field public static final int largeHeap = 16843610; // 0x101035a
+    field public static final int largeScreens = 16843398; // 0x1010286
+    field public static final int largestWidthLimitDp = 16843622; // 0x1010366
+    field public static final int launchMode = 16842781; // 0x101001d
+    field public static final int layerType = 16843604; // 0x1010354
+    field public static final int layout = 16842994; // 0x10100f2
+    field public static final int layoutAnimation = 16842988; // 0x10100ec
+    field public static final int layoutDirection = 16843698; // 0x10103b2
+    field public static final int layout_above = 16843140; // 0x1010184
+    field public static final int layout_alignBaseline = 16843142; // 0x1010186
+    field public static final int layout_alignBottom = 16843146; // 0x101018a
+    field public static final int layout_alignEnd = 16843706; // 0x10103ba
+    field public static final int layout_alignLeft = 16843143; // 0x1010187
+    field public static final int layout_alignParentBottom = 16843150; // 0x101018e
+    field public static final int layout_alignParentEnd = 16843708; // 0x10103bc
+    field public static final int layout_alignParentLeft = 16843147; // 0x101018b
+    field public static final int layout_alignParentRight = 16843149; // 0x101018d
+    field public static final int layout_alignParentStart = 16843707; // 0x10103bb
+    field public static final int layout_alignParentTop = 16843148; // 0x101018c
+    field public static final int layout_alignRight = 16843145; // 0x1010189
+    field public static final int layout_alignStart = 16843705; // 0x10103b9
+    field public static final int layout_alignTop = 16843144; // 0x1010188
+    field public static final int layout_alignWithParentIfMissing = 16843154; // 0x1010192
+    field public static final int layout_below = 16843141; // 0x1010185
+    field public static final int layout_centerHorizontal = 16843152; // 0x1010190
+    field public static final int layout_centerInParent = 16843151; // 0x101018f
+    field public static final int layout_centerVertical = 16843153; // 0x1010191
+    field public static final int layout_column = 16843084; // 0x101014c
+    field public static final int layout_columnSpan = 16843645; // 0x101037d
+    field public static final int layout_gravity = 16842931; // 0x10100b3
+    field public static final int layout_height = 16842997; // 0x10100f5
+    field public static final int layout_margin = 16842998; // 0x10100f6
+    field public static final int layout_marginBottom = 16843002; // 0x10100fa
+    field public static final int layout_marginEnd = 16843702; // 0x10103b6
+    field public static final int layout_marginLeft = 16842999; // 0x10100f7
+    field public static final int layout_marginRight = 16843001; // 0x10100f9
+    field public static final int layout_marginStart = 16843701; // 0x10103b5
+    field public static final int layout_marginTop = 16843000; // 0x10100f8
+    field public static final int layout_row = 16843643; // 0x101037b
+    field public static final int layout_rowSpan = 16843644; // 0x101037c
+    field public static final int layout_scale = 16843155; // 0x1010193
+    field public static final int layout_span = 16843085; // 0x101014d
+    field public static final int layout_toEndOf = 16843704; // 0x10103b8
+    field public static final int layout_toLeftOf = 16843138; // 0x1010182
+    field public static final int layout_toRightOf = 16843139; // 0x1010183
+    field public static final int layout_toStartOf = 16843703; // 0x10103b7
+    field public static final int layout_weight = 16843137; // 0x1010181
+    field public static final int layout_width = 16842996; // 0x10100f4
+    field public static final int layout_x = 16843135; // 0x101017f
+    field public static final int layout_y = 16843136; // 0x1010180
+    field public static final int left = 16843181; // 0x10101ad
+    field public static final int lineSpacingExtra = 16843287; // 0x1010217
+    field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
+    field public static final int lines = 16843092; // 0x1010154
+    field public static final int linksClickable = 16842929; // 0x10100b1
+    field public static final int listChoiceBackgroundIndicator = 16843504; // 0x10102f0
+    field public static final int listChoiceIndicatorMultiple = 16843290; // 0x101021a
+    field public static final int listChoiceIndicatorSingle = 16843289; // 0x1010219
+    field public static final int listDivider = 16843284; // 0x1010214
+    field public static final int listDividerAlertDialog = 16843525; // 0x1010305
+    field public static final int listPopupWindowStyle = 16843519; // 0x10102ff
+    field public static final int listPreferredItemHeight = 16842829; // 0x101004d
+    field public static final int listPreferredItemHeightLarge = 16843654; // 0x1010386
+    field public static final int listPreferredItemHeightSmall = 16843655; // 0x1010387
+    field public static final int listPreferredItemPaddingEnd = 16843710; // 0x10103be
+    field public static final int listPreferredItemPaddingLeft = 16843683; // 0x10103a3
+    field public static final int listPreferredItemPaddingRight = 16843684; // 0x10103a4
+    field public static final int listPreferredItemPaddingStart = 16843709; // 0x10103bd
+    field public static final int listSelector = 16843003; // 0x10100fb
+    field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208
+    field public static final int listViewStyle = 16842868; // 0x1010074
+    field public static final int listViewWhiteStyle = 16842869; // 0x1010075
+    field public static final int logo = 16843454; // 0x10102be
+    field public static final int longClickable = 16842982; // 0x10100e6
+    field public static final int loopViews = 16843527; // 0x1010307
+    field public static final int manageSpaceActivity = 16842756; // 0x1010004
+    field public static final int mapViewStyle = 16842890; // 0x101008a
+    field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
+    field public static final int max = 16843062; // 0x1010136
+    field public static final int maxDate = 16843584; // 0x1010340
+    field public static final int maxEms = 16843095; // 0x1010157
+    field public static final int maxHeight = 16843040; // 0x1010120
+    field public static final int maxItemsPerRow = 16843060; // 0x1010134
+    field public static final int maxLength = 16843104; // 0x1010160
+    field public static final int maxLevel = 16843186; // 0x10101b2
+    field public static final int maxLines = 16843091; // 0x1010153
+    field public static final int maxRows = 16843059; // 0x1010133
+    field public static final int maxSdkVersion = 16843377; // 0x1010271
+    field public static final int maxWidth = 16843039; // 0x101011f
+    field public static final int measureAllChildren = 16843018; // 0x101010a
+    field public static final int measureWithLargestChild = 16843476; // 0x10102d4
+    field public static final int mediaRouteButtonStyle = 16843693; // 0x10103ad
+    field public static final int mediaRouteTypes = 16843694; // 0x10103ae
+    field public static final int menuCategory = 16843230; // 0x10101de
+    field public static final int mimeType = 16842790; // 0x1010026
+    field public static final int minDate = 16843583; // 0x101033f
+    field public static final int minEms = 16843098; // 0x101015a
+    field public static final int minHeight = 16843072; // 0x1010140
+    field public static final int minLevel = 16843185; // 0x10101b1
+    field public static final int minLines = 16843094; // 0x1010156
+    field public static final int minResizeHeight = 16843670; // 0x1010396
+    field public static final int minResizeWidth = 16843669; // 0x1010395
+    field public static final int minSdkVersion = 16843276; // 0x101020c
+    field public static final int minWidth = 16843071; // 0x101013f
+    field public static final int mode = 16843134; // 0x101017e
+    field public static final int moreIcon = 16843061; // 0x1010135
+    field public static final int multiprocess = 16842771; // 0x1010013
+    field public static final int name = 16842755; // 0x1010003
+    field public static final int navigationMode = 16843471; // 0x10102cf
+    field public static final int negativeButtonText = 16843254; // 0x10101f6
+    field public static final int nextFocusDown = 16842980; // 0x10100e4
+    field public static final int nextFocusForward = 16843580; // 0x101033c
+    field public static final int nextFocusLeft = 16842977; // 0x10100e1
+    field public static final int nextFocusRight = 16842978; // 0x10100e2
+    field public static final int nextFocusUp = 16842979; // 0x10100e3
+    field public static final int noHistory = 16843309; // 0x101022d
+    field public static final int normalScreens = 16843397; // 0x1010285
+    field public static final int notificationTimeout = 16843651; // 0x1010383
+    field public static final int numColumns = 16843032; // 0x1010118
+    field public static final int numStars = 16843076; // 0x1010144
+    field public static final deprecated int numeric = 16843109; // 0x1010165
+    field public static final int numericShortcut = 16843236; // 0x10101e4
+    field public static final int onClick = 16843375; // 0x101026f
+    field public static final int oneshot = 16843159; // 0x1010197
+    field public static final int opacity = 16843550; // 0x101031e
+    field public static final int order = 16843242; // 0x10101ea
+    field public static final int orderInCategory = 16843231; // 0x10101df
+    field public static final int ordering = 16843490; // 0x10102e2
+    field public static final int orderingFromXml = 16843239; // 0x10101e7
+    field public static final int orientation = 16842948; // 0x10100c4
+    field public static final int outAnimation = 16843128; // 0x1010178
+    field public static final int overScrollFooter = 16843459; // 0x10102c3
+    field public static final int overScrollHeader = 16843458; // 0x10102c2
+    field public static final int overScrollMode = 16843457; // 0x10102c1
+    field public static final int overridesImplicitlyEnabledSubtype = 16843682; // 0x10103a2
+    field public static final int packageNames = 16843649; // 0x1010381
+    field public static final int padding = 16842965; // 0x10100d5
+    field public static final int paddingBottom = 16842969; // 0x10100d9
+    field public static final int paddingEnd = 16843700; // 0x10103b4
+    field public static final int paddingLeft = 16842966; // 0x10100d6
+    field public static final int paddingRight = 16842968; // 0x10100d8
+    field public static final int paddingStart = 16843699; // 0x10103b3
+    field public static final int paddingTop = 16842967; // 0x10100d7
+    field public static final int panelBackground = 16842846; // 0x101005e
+    field public static final int panelColorBackground = 16842849; // 0x1010061
+    field public static final int panelColorForeground = 16842848; // 0x1010060
+    field public static final int panelFullBackground = 16842847; // 0x101005f
+    field public static final int panelTextAppearance = 16842850; // 0x1010062
+    field public static final int parentActivityName = 16843687; // 0x10103a7
+    field public static final deprecated int password = 16843100; // 0x101015c
+    field public static final int path = 16842794; // 0x101002a
+    field public static final int pathPattern = 16842796; // 0x101002c
+    field public static final int pathPrefix = 16842795; // 0x101002b
+    field public static final int permission = 16842758; // 0x1010006
+    field public static final int permissionFlags = 16843719; // 0x10103c7
+    field public static final int permissionGroup = 16842762; // 0x101000a
+    field public static final int permissionGroupFlags = 16843717; // 0x10103c5
+    field public static final int persistent = 16842765; // 0x101000d
+    field public static final int persistentDrawingCache = 16842990; // 0x10100ee
+    field public static final deprecated int phoneNumber = 16843111; // 0x1010167
+    field public static final int pivotX = 16843189; // 0x10101b5
+    field public static final int pivotY = 16843190; // 0x10101b6
+    field public static final int popupAnimationStyle = 16843465; // 0x10102c9
+    field public static final int popupBackground = 16843126; // 0x1010176
+    field public static final int popupCharacters = 16843332; // 0x1010244
+    field public static final int popupKeyboard = 16843331; // 0x1010243
+    field public static final int popupLayout = 16843323; // 0x101023b
+    field public static final int popupMenuStyle = 16843520; // 0x1010300
+    field public static final int popupWindowStyle = 16842870; // 0x1010076
+    field public static final int port = 16842793; // 0x1010029
+    field public static final int positiveButtonText = 16843253; // 0x10101f5
+    field public static final int preferenceCategoryStyle = 16842892; // 0x101008c
+    field public static final int preferenceInformationStyle = 16842893; // 0x101008d
+    field public static final int preferenceLayoutChild = 16842900; // 0x1010094
+    field public static final int preferenceScreenStyle = 16842891; // 0x101008b
+    field public static final int preferenceStyle = 16842894; // 0x101008e
+    field public static final int presentationTheme = 16843712; // 0x10103c0
+    field public static final int previewImage = 16843482; // 0x10102da
+    field public static final int priority = 16842780; // 0x101001c
+    field public static final int privateImeOptions = 16843299; // 0x1010223
+    field public static final int process = 16842769; // 0x1010011
+    field public static final int progress = 16843063; // 0x1010137
+    field public static final int progressBarPadding = 16843545; // 0x1010319
+    field public static final int progressBarStyle = 16842871; // 0x1010077
+    field public static final int progressBarStyleHorizontal = 16842872; // 0x1010078
+    field public static final int progressBarStyleInverse = 16843399; // 0x1010287
+    field public static final int progressBarStyleLarge = 16842874; // 0x101007a
+    field public static final int progressBarStyleLargeInverse = 16843401; // 0x1010289
+    field public static final int progressBarStyleSmall = 16842873; // 0x1010079
+    field public static final int progressBarStyleSmallInverse = 16843400; // 0x1010288
+    field public static final int progressBarStyleSmallTitle = 16843279; // 0x101020f
+    field public static final int progressDrawable = 16843068; // 0x101013c
+    field public static final int prompt = 16843131; // 0x101017b
+    field public static final int propertyName = 16843489; // 0x10102e1
+    field public static final int protectionLevel = 16842761; // 0x1010009
+    field public static final int publicKey = 16843686; // 0x10103a6
+    field public static final int queryActionMsg = 16843227; // 0x10101db
+    field public static final int queryAfterZeroResults = 16843394; // 0x1010282
+    field public static final int queryHint = 16843608; // 0x1010358
+    field public static final int quickContactBadgeStyleSmallWindowLarge = 16843443; // 0x10102b3
+    field public static final int quickContactBadgeStyleSmallWindowMedium = 16843442; // 0x10102b2
+    field public static final int quickContactBadgeStyleSmallWindowSmall = 16843441; // 0x10102b1
+    field public static final int quickContactBadgeStyleWindowLarge = 16843440; // 0x10102b0
+    field public static final int quickContactBadgeStyleWindowMedium = 16843439; // 0x10102af
+    field public static final int quickContactBadgeStyleWindowSmall = 16843438; // 0x10102ae
+    field public static final int radioButtonStyle = 16842878; // 0x101007e
+    field public static final int radius = 16843176; // 0x10101a8
+    field public static final int rating = 16843077; // 0x1010145
+    field public static final int ratingBarStyle = 16842876; // 0x101007c
+    field public static final int ratingBarStyleIndicator = 16843280; // 0x1010210
+    field public static final int ratingBarStyleSmall = 16842877; // 0x101007d
+    field public static final int readPermission = 16842759; // 0x1010007
+    field public static final int repeatCount = 16843199; // 0x10101bf
+    field public static final int repeatMode = 16843200; // 0x10101c0
+    field public static final int reqFiveWayNav = 16843314; // 0x1010232
+    field public static final int reqHardKeyboard = 16843305; // 0x1010229
+    field public static final int reqKeyboardType = 16843304; // 0x1010228
+    field public static final int reqNavigation = 16843306; // 0x101022a
+    field public static final int reqTouchScreen = 16843303; // 0x1010227
+    field public static final int required = 16843406; // 0x101028e
+    field public static final int requiresFadingEdge = 16843685; // 0x10103a5
+    field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
+    field public static final int resizeMode = 16843619; // 0x1010363
+    field public static final int resizeable = 16843405; // 0x101028d
+    field public static final int resource = 16842789; // 0x1010025
+    field public static final int restoreAnyVersion = 16843450; // 0x10102ba
+    field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
+    field public static final int right = 16843183; // 0x10101af
+    field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
+    field public static final int ringtoneType = 16843257; // 0x10101f9
+    field public static final int rotation = 16843558; // 0x1010326
+    field public static final int rotationX = 16843559; // 0x1010327
+    field public static final int rotationY = 16843560; // 0x1010328
+    field public static final int rowCount = 16843637; // 0x1010375
+    field public static final int rowDelay = 16843216; // 0x10101d0
+    field public static final int rowEdgeFlags = 16843329; // 0x1010241
+    field public static final int rowHeight = 16843058; // 0x1010132
+    field public static final int rowOrderPreserved = 16843638; // 0x1010376
+    field public static final int saveEnabled = 16842983; // 0x10100e7
+    field public static final int scaleGravity = 16843262; // 0x10101fe
+    field public static final int scaleHeight = 16843261; // 0x10101fd
+    field public static final int scaleType = 16843037; // 0x101011d
+    field public static final int scaleWidth = 16843260; // 0x10101fc
+    field public static final int scaleX = 16843556; // 0x1010324
+    field public static final int scaleY = 16843557; // 0x1010325
+    field public static final int scheme = 16842791; // 0x1010027
+    field public static final int screenDensity = 16843467; // 0x10102cb
+    field public static final int screenOrientation = 16842782; // 0x101001e
+    field public static final int screenSize = 16843466; // 0x10102ca
+    field public static final int scrollHorizontally = 16843099; // 0x101015b
+    field public static final int scrollViewStyle = 16842880; // 0x1010080
+    field public static final int scrollX = 16842962; // 0x10100d2
+    field public static final int scrollY = 16842963; // 0x10100d3
+    field public static final int scrollbarAlwaysDrawHorizontalTrack = 16842856; // 0x1010068
+    field public static final int scrollbarAlwaysDrawVerticalTrack = 16842857; // 0x1010069
+    field public static final int scrollbarDefaultDelayBeforeFade = 16843433; // 0x10102a9
+    field public static final int scrollbarFadeDuration = 16843432; // 0x10102a8
+    field public static final int scrollbarSize = 16842851; // 0x1010063
+    field public static final int scrollbarStyle = 16842879; // 0x101007f
+    field public static final int scrollbarThumbHorizontal = 16842852; // 0x1010064
+    field public static final int scrollbarThumbVertical = 16842853; // 0x1010065
+    field public static final int scrollbarTrackHorizontal = 16842854; // 0x1010066
+    field public static final int scrollbarTrackVertical = 16842855; // 0x1010067
+    field public static final int scrollbars = 16842974; // 0x10100de
+    field public static final int scrollingCache = 16843006; // 0x10100fe
+    field public static final deprecated int searchButtonText = 16843269; // 0x1010205
+    field public static final int searchMode = 16843221; // 0x10101d5
+    field public static final int searchSettingsDescription = 16843402; // 0x101028a
+    field public static final int searchSuggestAuthority = 16843222; // 0x10101d6
+    field public static final int searchSuggestIntentAction = 16843225; // 0x10101d9
+    field public static final int searchSuggestIntentData = 16843226; // 0x10101da
+    field public static final int searchSuggestPath = 16843223; // 0x10101d7
+    field public static final int searchSuggestSelection = 16843224; // 0x10101d8
+    field public static final int searchSuggestThreshold = 16843373; // 0x101026d
+    field public static final int secondaryProgress = 16843064; // 0x1010138
+    field public static final int seekBarStyle = 16842875; // 0x101007b
+    field public static final int segmentedButtonStyle = 16843568; // 0x1010330
+    field public static final int selectAllOnFocus = 16843102; // 0x101015e
+    field public static final int selectable = 16843238; // 0x10101e6
+    field public static final int selectableItemBackground = 16843534; // 0x101030e
+    field public static final int selectedDateVerticalBar = 16843591; // 0x1010347
+    field public static final int selectedWeekBackgroundColor = 16843586; // 0x1010342
+    field public static final int settingsActivity = 16843301; // 0x1010225
+    field public static final int shadowColor = 16843105; // 0x1010161
+    field public static final int shadowDx = 16843106; // 0x1010162
+    field public static final int shadowDy = 16843107; // 0x1010163
+    field public static final int shadowRadius = 16843108; // 0x1010164
+    field public static final int shape = 16843162; // 0x101019a
+    field public static final int shareInterpolator = 16843195; // 0x10101bb
+    field public static final int sharedUserId = 16842763; // 0x101000b
+    field public static final int sharedUserLabel = 16843361; // 0x1010261
+    field public static final int shouldDisableView = 16843246; // 0x10101ee
+    field public static final int showAsAction = 16843481; // 0x10102d9
+    field public static final int showDefault = 16843258; // 0x10101fa
+    field public static final int showDividers = 16843561; // 0x1010329
+    field public static final int showOnLockScreen = 16843721; // 0x10103c9
+    field public static final int showSilent = 16843259; // 0x10101fb
+    field public static final int showWeekNumber = 16843582; // 0x101033e
+    field public static final int shownWeekCount = 16843585; // 0x1010341
+    field public static final int shrinkColumns = 16843082; // 0x101014a
+    field public static final deprecated int singleLine = 16843101; // 0x101015d
+    field public static final int singleUser = 16843711; // 0x10103bf
+    field public static final int smallIcon = 16843422; // 0x101029e
+    field public static final int smallScreens = 16843396; // 0x1010284
+    field public static final int smoothScrollbar = 16843313; // 0x1010231
+    field public static final int soundEffectsEnabled = 16843285; // 0x1010215
+    field public static final int spacing = 16843027; // 0x1010113
+    field public static final int spinnerDropDownItemStyle = 16842887; // 0x1010087
+    field public static final int spinnerItemStyle = 16842889; // 0x1010089
+    field public static final int spinnerMode = 16843505; // 0x10102f1
+    field public static final int spinnerStyle = 16842881; // 0x1010081
+    field public static final int spinnersShown = 16843595; // 0x101034b
+    field public static final int splitMotionEvents = 16843503; // 0x10102ef
+    field public static final int src = 16843033; // 0x1010119
+    field public static final int stackFromBottom = 16843005; // 0x10100fd
+    field public static final int starStyle = 16842882; // 0x1010082
+    field public static final int startColor = 16843165; // 0x101019d
+    field public static final int startOffset = 16843198; // 0x10101be
+    field public static final deprecated int startYear = 16843132; // 0x101017c
+    field public static final int stateNotNeeded = 16842774; // 0x1010016
+    field public static final int state_above_anchor = 16842922; // 0x10100aa
+    field public static final int state_accelerated = 16843547; // 0x101031b
+    field public static final int state_activated = 16843518; // 0x10102fe
+    field public static final int state_active = 16842914; // 0x10100a2
+    field public static final int state_checkable = 16842911; // 0x101009f
+    field public static final int state_checked = 16842912; // 0x10100a0
+    field public static final int state_drag_can_accept = 16843624; // 0x1010368
+    field public static final int state_drag_hovered = 16843625; // 0x1010369
+    field public static final int state_empty = 16842921; // 0x10100a9
+    field public static final int state_enabled = 16842910; // 0x101009e
+    field public static final int state_expanded = 16842920; // 0x10100a8
+    field public static final int state_first = 16842916; // 0x10100a4
+    field public static final int state_focused = 16842908; // 0x101009c
+    field public static final int state_hovered = 16843623; // 0x1010367
+    field public static final int state_last = 16842918; // 0x10100a6
+    field public static final int state_long_pressable = 16843324; // 0x101023c
+    field public static final int state_middle = 16842917; // 0x10100a5
+    field public static final int state_multiline = 16843597; // 0x101034d
+    field public static final int state_pressed = 16842919; // 0x10100a7
+    field public static final int state_selected = 16842913; // 0x10100a1
+    field public static final int state_single = 16842915; // 0x10100a3
+    field public static final int state_window_focused = 16842909; // 0x101009d
+    field public static final int staticWallpaperPreview = 16843569; // 0x1010331
+    field public static final int stepSize = 16843078; // 0x1010146
+    field public static final int stopWithTask = 16843626; // 0x101036a
+    field public static final int streamType = 16843273; // 0x1010209
+    field public static final int stretchColumns = 16843081; // 0x1010149
+    field public static final int stretchMode = 16843030; // 0x1010116
+    field public static final int subtitle = 16843473; // 0x10102d1
+    field public static final int subtitleTextStyle = 16843513; // 0x10102f9
+    field public static final int subtypeExtraValue = 16843674; // 0x101039a
+    field public static final int subtypeId = 16843713; // 0x10103c1
+    field public static final int subtypeLocale = 16843673; // 0x1010399
+    field public static final int suggestActionMsg = 16843228; // 0x10101dc
+    field public static final int suggestActionMsgColumn = 16843229; // 0x10101dd
+    field public static final int summary = 16843241; // 0x10101e9
+    field public static final int summaryColumn = 16843426; // 0x10102a2
+    field public static final int summaryOff = 16843248; // 0x10101f0
+    field public static final int summaryOn = 16843247; // 0x10101ef
+    field public static final int supportsRtl = 16843695; // 0x10103af
+    field public static final int supportsUploading = 16843419; // 0x101029b
+    field public static final int switchMinWidth = 16843632; // 0x1010370
+    field public static final int switchPadding = 16843633; // 0x1010371
+    field public static final int switchPreferenceStyle = 16843629; // 0x101036d
+    field public static final int switchTextAppearance = 16843630; // 0x101036e
+    field public static final int switchTextOff = 16843628; // 0x101036c
+    field public static final int switchTextOn = 16843627; // 0x101036b
+    field public static final int syncable = 16842777; // 0x1010019
+    field public static final int tabStripEnabled = 16843453; // 0x10102bd
+    field public static final int tabStripLeft = 16843451; // 0x10102bb
+    field public static final int tabStripRight = 16843452; // 0x10102bc
+    field public static final int tabWidgetStyle = 16842883; // 0x1010083
+    field public static final int tag = 16842961; // 0x10100d1
+    field public static final int targetActivity = 16843266; // 0x1010202
+    field public static final int targetClass = 16842799; // 0x101002f
+    field public static final int targetDescriptions = 16843680; // 0x10103a0
+    field public static final int targetPackage = 16842785; // 0x1010021
+    field public static final int targetSdkVersion = 16843376; // 0x1010270
+    field public static final int taskAffinity = 16842770; // 0x1010012
+    field public static final int taskCloseEnterAnimation = 16842942; // 0x10100be
+    field public static final int taskCloseExitAnimation = 16842943; // 0x10100bf
+    field public static final int taskOpenEnterAnimation = 16842940; // 0x10100bc
+    field public static final int taskOpenExitAnimation = 16842941; // 0x10100bd
+    field public static final int taskToBackEnterAnimation = 16842946; // 0x10100c2
+    field public static final int taskToBackExitAnimation = 16842947; // 0x10100c3
+    field public static final int taskToFrontEnterAnimation = 16842944; // 0x10100c0
+    field public static final int taskToFrontExitAnimation = 16842945; // 0x10100c1
+    field public static final int tension = 16843370; // 0x101026a
+    field public static final int testOnly = 16843378; // 0x1010272
+    field public static final int text = 16843087; // 0x101014f
+    field public static final int textAlignment = 16843697; // 0x10103b1
+    field public static final int textAllCaps = 16843660; // 0x101038c
+    field public static final int textAppearance = 16842804; // 0x1010034
+    field public static final int textAppearanceButton = 16843271; // 0x1010207
+    field public static final int textAppearanceInverse = 16842805; // 0x1010035
+    field public static final int textAppearanceLarge = 16842816; // 0x1010040
+    field public static final int textAppearanceLargeInverse = 16842819; // 0x1010043
+    field public static final int textAppearanceLargePopupMenu = 16843521; // 0x1010301
+    field public static final int textAppearanceListItem = 16843678; // 0x101039e
+    field public static final int textAppearanceListItemSmall = 16843679; // 0x101039f
+    field public static final int textAppearanceMedium = 16842817; // 0x1010041
+    field public static final int textAppearanceMediumInverse = 16842820; // 0x1010044
+    field public static final int textAppearanceSearchResultSubtitle = 16843424; // 0x10102a0
+    field public static final int textAppearanceSearchResultTitle = 16843425; // 0x10102a1
+    field public static final int textAppearanceSmall = 16842818; // 0x1010042
+    field public static final int textAppearanceSmallInverse = 16842821; // 0x1010045
+    field public static final int textAppearanceSmallPopupMenu = 16843522; // 0x1010302
+    field public static final int textCheckMark = 16842822; // 0x1010046
+    field public static final int textCheckMarkInverse = 16842823; // 0x1010047
+    field public static final int textColor = 16842904; // 0x1010098
+    field public static final int textColorAlertDialogListItem = 16843526; // 0x1010306
+    field public static final int textColorHighlight = 16842905; // 0x1010099
+    field public static final int textColorHighlightInverse = 16843599; // 0x101034f
+    field public static final int textColorHint = 16842906; // 0x101009a
+    field public static final int textColorHintInverse = 16842815; // 0x101003f
+    field public static final int textColorLink = 16842907; // 0x101009b
+    field public static final int textColorLinkInverse = 16843600; // 0x1010350
+    field public static final int textColorPrimary = 16842806; // 0x1010036
+    field public static final int textColorPrimaryDisableOnly = 16842807; // 0x1010037
+    field public static final int textColorPrimaryInverse = 16842809; // 0x1010039
+    field public static final int textColorPrimaryInverseDisableOnly = 16843403; // 0x101028b
+    field public static final int textColorPrimaryInverseNoDisable = 16842813; // 0x101003d
+    field public static final int textColorPrimaryNoDisable = 16842811; // 0x101003b
+    field public static final int textColorSecondary = 16842808; // 0x1010038
+    field public static final int textColorSecondaryInverse = 16842810; // 0x101003a
+    field public static final int textColorSecondaryInverseNoDisable = 16842814; // 0x101003e
+    field public static final int textColorSecondaryNoDisable = 16842812; // 0x101003c
+    field public static final int textColorTertiary = 16843282; // 0x1010212
+    field public static final int textColorTertiaryInverse = 16843283; // 0x1010213
+    field public static final int textCursorDrawable = 16843618; // 0x1010362
+    field public static final int textDirection = 16843696; // 0x10103b0
+    field public static final int textEditNoPasteWindowLayout = 16843541; // 0x1010315
+    field public static final int textEditPasteWindowLayout = 16843540; // 0x1010314
+    field public static final int textEditSideNoPasteWindowLayout = 16843615; // 0x101035f
+    field public static final int textEditSidePasteWindowLayout = 16843614; // 0x101035e
+    field public static final int textEditSuggestionItemLayout = 16843636; // 0x1010374
+    field public static final int textFilterEnabled = 16843007; // 0x10100ff
+    field public static final int textIsSelectable = 16843542; // 0x1010316
+    field public static final int textOff = 16843045; // 0x1010125
+    field public static final int textOn = 16843044; // 0x1010124
+    field public static final int textScaleX = 16843089; // 0x1010151
+    field public static final int textSelectHandle = 16843463; // 0x10102c7
+    field public static final int textSelectHandleLeft = 16843461; // 0x10102c5
+    field public static final int textSelectHandleRight = 16843462; // 0x10102c6
+    field public static final int textSelectHandleWindowStyle = 16843464; // 0x10102c8
+    field public static final int textSize = 16842901; // 0x1010095
+    field public static final int textStyle = 16842903; // 0x1010097
+    field public static final int textSuggestionsWindowStyle = 16843635; // 0x1010373
+    field public static final int textViewStyle = 16842884; // 0x1010084
+    field public static final int theme = 16842752; // 0x1010000
+    field public static final int thickness = 16843360; // 0x1010260
+    field public static final int thicknessRatio = 16843164; // 0x101019c
+    field public static final int thumb = 16843074; // 0x1010142
+    field public static final int thumbOffset = 16843075; // 0x1010143
+    field public static final int thumbTextPadding = 16843634; // 0x1010372
+    field public static final int thumbnail = 16843429; // 0x10102a5
+    field public static final int tileMode = 16843265; // 0x1010201
+    field public static final int timeZone = 16843724; // 0x10103cc
+    field public static final int tint = 16843041; // 0x1010121
+    field public static final int title = 16843233; // 0x10101e1
+    field public static final int titleCondensed = 16843234; // 0x10101e2
+    field public static final int titleTextStyle = 16843512; // 0x10102f8
+    field public static final int toAlpha = 16843211; // 0x10101cb
+    field public static final int toDegrees = 16843188; // 0x10101b4
+    field public static final int toXDelta = 16843207; // 0x10101c7
+    field public static final int toXScale = 16843203; // 0x10101c3
+    field public static final int toYDelta = 16843209; // 0x10101c9
+    field public static final int toYScale = 16843205; // 0x10101c5
+    field public static final int top = 16843182; // 0x10101ae
+    field public static final int topBright = 16842955; // 0x10100cb
+    field public static final int topDark = 16842951; // 0x10100c7
+    field public static final int topLeftRadius = 16843177; // 0x10101a9
+    field public static final int topOffset = 16843352; // 0x1010258
+    field public static final int topRightRadius = 16843178; // 0x10101aa
+    field public static final int track = 16843631; // 0x101036f
+    field public static final int transcriptMode = 16843008; // 0x1010100
+    field public static final int transformPivotX = 16843552; // 0x1010320
+    field public static final int transformPivotY = 16843553; // 0x1010321
+    field public static final int translationX = 16843554; // 0x1010322
+    field public static final int translationY = 16843555; // 0x1010323
+    field public static final int type = 16843169; // 0x10101a1
+    field public static final int typeface = 16842902; // 0x1010096
+    field public static final int uiOptions = 16843672; // 0x1010398
+    field public static final int uncertainGestureColor = 16843382; // 0x1010276
+    field public static final int unfocusedMonthDateColor = 16843588; // 0x1010344
+    field public static final int unselectedAlpha = 16843278; // 0x101020e
+    field public static final int updatePeriodMillis = 16843344; // 0x1010250
+    field public static final int useDefaultMargins = 16843641; // 0x1010379
+    field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
+    field public static final int useLevel = 16843167; // 0x101019f
+    field public static final int userVisible = 16843409; // 0x1010291
+    field public static final int value = 16842788; // 0x1010024
+    field public static final int valueFrom = 16843486; // 0x10102de
+    field public static final int valueTo = 16843487; // 0x10102df
+    field public static final int valueType = 16843488; // 0x10102e0
+    field public static final int variablePadding = 16843157; // 0x1010195
+    field public static final int versionCode = 16843291; // 0x101021b
+    field public static final int versionName = 16843292; // 0x101021c
+    field public static final int verticalCorrection = 16843322; // 0x101023a
+    field public static final int verticalDivider = 16843054; // 0x101012e
+    field public static final int verticalGap = 16843328; // 0x1010240
+    field public static final int verticalScrollbarPosition = 16843572; // 0x1010334
+    field public static final int verticalSpacing = 16843029; // 0x1010115
+    field public static final int visibility = 16842972; // 0x10100dc
+    field public static final int visible = 16843156; // 0x1010194
+    field public static final int vmSafeMode = 16843448; // 0x10102b8
+    field public static final int voiceLanguage = 16843349; // 0x1010255
+    field public static final int voiceLanguageModel = 16843347; // 0x1010253
+    field public static final int voiceMaxResults = 16843350; // 0x1010256
+    field public static final int voicePromptText = 16843348; // 0x1010254
+    field public static final int voiceSearchMode = 16843346; // 0x1010252
+    field public static final int wallpaperCloseEnterAnimation = 16843413; // 0x1010295
+    field public static final int wallpaperCloseExitAnimation = 16843414; // 0x1010296
+    field public static final int wallpaperIntraCloseEnterAnimation = 16843417; // 0x1010299
+    field public static final int wallpaperIntraCloseExitAnimation = 16843418; // 0x101029a
+    field public static final int wallpaperIntraOpenEnterAnimation = 16843415; // 0x1010297
+    field public static final int wallpaperIntraOpenExitAnimation = 16843416; // 0x1010298
+    field public static final int wallpaperOpenEnterAnimation = 16843411; // 0x1010293
+    field public static final int wallpaperOpenExitAnimation = 16843412; // 0x1010294
+    field public static final int webTextViewStyle = 16843449; // 0x10102b9
+    field public static final int webViewStyle = 16842885; // 0x1010085
+    field public static final int weekDayTextAppearance = 16843592; // 0x1010348
+    field public static final int weekNumberColor = 16843589; // 0x1010345
+    field public static final int weekSeparatorLineColor = 16843590; // 0x1010346
+    field public static final int weightSum = 16843048; // 0x1010128
+    field public static final int widgetCategory = 16843716; // 0x10103c4
+    field public static final int widgetLayout = 16843243; // 0x10101eb
+    field public static final int width = 16843097; // 0x1010159
+    field public static final int windowActionBar = 16843469; // 0x10102cd
+    field public static final int windowActionBarOverlay = 16843492; // 0x10102e4
+    field public static final int windowActionModeOverlay = 16843485; // 0x10102dd
+    field public static final int windowAnimationStyle = 16842926; // 0x10100ae
+    field public static final int windowBackground = 16842836; // 0x1010054
+    field public static final int windowCloseOnTouchOutside = 16843611; // 0x101035b
+    field public static final int windowContentOverlay = 16842841; // 0x1010059
+    field public static final int windowDisablePreview = 16843298; // 0x1010222
+    field public static final int windowEnableSplitTouch = 16843543; // 0x1010317
+    field public static final int windowEnterAnimation = 16842932; // 0x10100b4
+    field public static final int windowExitAnimation = 16842933; // 0x10100b5
+    field public static final int windowFrame = 16842837; // 0x1010055
+    field public static final int windowFullscreen = 16843277; // 0x101020d
+    field public static final int windowHideAnimation = 16842935; // 0x10100b7
+    field public static final int windowIsFloating = 16842839; // 0x1010057
+    field public static final int windowIsTranslucent = 16842840; // 0x1010058
+    field public static final int windowMinWidthMajor = 16843606; // 0x1010356
+    field public static final int windowMinWidthMinor = 16843607; // 0x1010357
+    field public static final int windowNoDisplay = 16843294; // 0x101021e
+    field public static final int windowNoTitle = 16842838; // 0x1010056
+    field public static final int windowShowAnimation = 16842934; // 0x10100b6
+    field public static final int windowShowWallpaper = 16843410; // 0x1010292
+    field public static final int windowSoftInputMode = 16843307; // 0x101022b
+    field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
+    field public static final int windowTitleSize = 16842842; // 0x101005a
+    field public static final int windowTitleStyle = 16842843; // 0x101005b
+    field public static final int writePermission = 16842760; // 0x1010008
+    field public static final int x = 16842924; // 0x10100ac
+    field public static final int xlargeScreens = 16843455; // 0x10102bf
+    field public static final int y = 16842925; // 0x10100ad
+    field public static final int yesNoPreferenceStyle = 16842896; // 0x1010090
+    field public static final int zAdjustment = 16843201; // 0x10101c1
+  }
+
+  public static final class R.bool {
+    ctor public R.bool();
+  }
+
+  public static final class R.color {
+    ctor public R.color();
+    field public static final int background_dark = 17170446; // 0x106000e
+    field public static final int background_light = 17170447; // 0x106000f
+    field public static final int black = 17170444; // 0x106000c
+    field public static final int darker_gray = 17170432; // 0x1060000
+    field public static final int holo_blue_bright = 17170459; // 0x106001b
+    field public static final int holo_blue_dark = 17170451; // 0x1060013
+    field public static final int holo_blue_light = 17170450; // 0x1060012
+    field public static final int holo_green_dark = 17170453; // 0x1060015
+    field public static final int holo_green_light = 17170452; // 0x1060014
+    field public static final int holo_orange_dark = 17170457; // 0x1060019
+    field public static final int holo_orange_light = 17170456; // 0x1060018
+    field public static final int holo_purple = 17170458; // 0x106001a
+    field public static final int holo_red_dark = 17170455; // 0x1060017
+    field public static final int holo_red_light = 17170454; // 0x1060016
+    field public static final int primary_text_dark = 17170433; // 0x1060001
+    field public static final int primary_text_dark_nodisable = 17170434; // 0x1060002
+    field public static final int primary_text_light = 17170435; // 0x1060003
+    field public static final int primary_text_light_nodisable = 17170436; // 0x1060004
+    field public static final int secondary_text_dark = 17170437; // 0x1060005
+    field public static final int secondary_text_dark_nodisable = 17170438; // 0x1060006
+    field public static final int secondary_text_light = 17170439; // 0x1060007
+    field public static final int secondary_text_light_nodisable = 17170440; // 0x1060008
+    field public static final int tab_indicator_text = 17170441; // 0x1060009
+    field public static final int tertiary_text_dark = 17170448; // 0x1060010
+    field public static final int tertiary_text_light = 17170449; // 0x1060011
+    field public static final int transparent = 17170445; // 0x106000d
+    field public static final int white = 17170443; // 0x106000b
+    field public static final int widget_edittext_dark = 17170442; // 0x106000a
+  }
+
+  public static final class R.dimen {
+    ctor public R.dimen();
+    field public static final int app_icon_size = 17104896; // 0x1050000
+    field public static final int dialog_min_width_major = 17104899; // 0x1050003
+    field public static final int dialog_min_width_minor = 17104900; // 0x1050004
+    field public static final int notification_large_icon_height = 17104902; // 0x1050006
+    field public static final int notification_large_icon_width = 17104901; // 0x1050005
+    field public static final int thumbnail_height = 17104897; // 0x1050001
+    field public static final int thumbnail_width = 17104898; // 0x1050002
+  }
+
+  public static final class R.drawable {
+    ctor public R.drawable();
+    field public static final int alert_dark_frame = 17301504; // 0x1080000
+    field public static final int alert_light_frame = 17301505; // 0x1080001
+    field public static final int arrow_down_float = 17301506; // 0x1080002
+    field public static final int arrow_up_float = 17301507; // 0x1080003
+    field public static final int bottom_bar = 17301658; // 0x108009a
+    field public static final int btn_default = 17301508; // 0x1080004
+    field public static final int btn_default_small = 17301509; // 0x1080005
+    field public static final int btn_dialog = 17301527; // 0x1080017
+    field public static final int btn_dropdown = 17301510; // 0x1080006
+    field public static final int btn_minus = 17301511; // 0x1080007
+    field public static final int btn_plus = 17301512; // 0x1080008
+    field public static final int btn_radio = 17301513; // 0x1080009
+    field public static final int btn_star = 17301514; // 0x108000a
+    field public static final int btn_star_big_off = 17301515; // 0x108000b
+    field public static final int btn_star_big_on = 17301516; // 0x108000c
+    field public static final int button_onoff_indicator_off = 17301518; // 0x108000e
+    field public static final int button_onoff_indicator_on = 17301517; // 0x108000d
+    field public static final int checkbox_off_background = 17301519; // 0x108000f
+    field public static final int checkbox_on_background = 17301520; // 0x1080010
+    field public static final int dark_header = 17301669; // 0x10800a5
+    field public static final int dialog_frame = 17301521; // 0x1080011
+    field public static final int dialog_holo_dark_frame = 17301682; // 0x10800b2
+    field public static final int dialog_holo_light_frame = 17301683; // 0x10800b3
+    field public static final int divider_horizontal_bright = 17301522; // 0x1080012
+    field public static final int divider_horizontal_dark = 17301524; // 0x1080014
+    field public static final int divider_horizontal_dim_dark = 17301525; // 0x1080015
+    field public static final int divider_horizontal_textfield = 17301523; // 0x1080013
+    field public static final int edit_text = 17301526; // 0x1080016
+    field public static final int editbox_background = 17301528; // 0x1080018
+    field public static final int editbox_background_normal = 17301529; // 0x1080019
+    field public static final int editbox_dropdown_dark_frame = 17301530; // 0x108001a
+    field public static final int editbox_dropdown_light_frame = 17301531; // 0x108001b
+    field public static final int gallery_thumb = 17301532; // 0x108001c
+    field public static final int ic_btn_speak_now = 17301668; // 0x10800a4
+    field public static final int ic_delete = 17301533; // 0x108001d
+    field public static final int ic_dialog_alert = 17301543; // 0x1080027
+    field public static final int ic_dialog_dialer = 17301544; // 0x1080028
+    field public static final int ic_dialog_email = 17301545; // 0x1080029
+    field public static final int ic_dialog_info = 17301659; // 0x108009b
+    field public static final int ic_dialog_map = 17301546; // 0x108002a
+    field public static final int ic_input_add = 17301547; // 0x108002b
+    field public static final int ic_input_delete = 17301548; // 0x108002c
+    field public static final int ic_input_get = 17301549; // 0x108002d
+    field public static final int ic_lock_idle_alarm = 17301550; // 0x108002e
+    field public static final int ic_lock_idle_charging = 17301534; // 0x108001e
+    field public static final int ic_lock_idle_lock = 17301535; // 0x108001f
+    field public static final int ic_lock_idle_low_battery = 17301536; // 0x1080020
+    field public static final int ic_lock_lock = 17301551; // 0x108002f
+    field public static final int ic_lock_power_off = 17301552; // 0x1080030
+    field public static final int ic_lock_silent_mode = 17301553; // 0x1080031
+    field public static final int ic_lock_silent_mode_off = 17301554; // 0x1080032
+    field public static final int ic_media_ff = 17301537; // 0x1080021
+    field public static final int ic_media_next = 17301538; // 0x1080022
+    field public static final int ic_media_pause = 17301539; // 0x1080023
+    field public static final int ic_media_play = 17301540; // 0x1080024
+    field public static final int ic_media_previous = 17301541; // 0x1080025
+    field public static final int ic_media_rew = 17301542; // 0x1080026
+    field public static final int ic_menu_add = 17301555; // 0x1080033
+    field public static final int ic_menu_agenda = 17301556; // 0x1080034
+    field public static final int ic_menu_always_landscape_portrait = 17301557; // 0x1080035
+    field public static final int ic_menu_call = 17301558; // 0x1080036
+    field public static final int ic_menu_camera = 17301559; // 0x1080037
+    field public static final int ic_menu_close_clear_cancel = 17301560; // 0x1080038
+    field public static final int ic_menu_compass = 17301561; // 0x1080039
+    field public static final int ic_menu_crop = 17301562; // 0x108003a
+    field public static final int ic_menu_day = 17301563; // 0x108003b
+    field public static final int ic_menu_delete = 17301564; // 0x108003c
+    field public static final int ic_menu_directions = 17301565; // 0x108003d
+    field public static final int ic_menu_edit = 17301566; // 0x108003e
+    field public static final int ic_menu_gallery = 17301567; // 0x108003f
+    field public static final int ic_menu_help = 17301568; // 0x1080040
+    field public static final int ic_menu_info_details = 17301569; // 0x1080041
+    field public static final int ic_menu_manage = 17301570; // 0x1080042
+    field public static final int ic_menu_mapmode = 17301571; // 0x1080043
+    field public static final int ic_menu_month = 17301572; // 0x1080044
+    field public static final int ic_menu_more = 17301573; // 0x1080045
+    field public static final int ic_menu_my_calendar = 17301574; // 0x1080046
+    field public static final int ic_menu_mylocation = 17301575; // 0x1080047
+    field public static final int ic_menu_myplaces = 17301576; // 0x1080048
+    field public static final int ic_menu_preferences = 17301577; // 0x1080049
+    field public static final int ic_menu_recent_history = 17301578; // 0x108004a
+    field public static final int ic_menu_report_image = 17301579; // 0x108004b
+    field public static final int ic_menu_revert = 17301580; // 0x108004c
+    field public static final int ic_menu_rotate = 17301581; // 0x108004d
+    field public static final int ic_menu_save = 17301582; // 0x108004e
+    field public static final int ic_menu_search = 17301583; // 0x108004f
+    field public static final int ic_menu_send = 17301584; // 0x1080050
+    field public static final int ic_menu_set_as = 17301585; // 0x1080051
+    field public static final int ic_menu_share = 17301586; // 0x1080052
+    field public static final int ic_menu_slideshow = 17301587; // 0x1080053
+    field public static final int ic_menu_sort_alphabetically = 17301660; // 0x108009c
+    field public static final int ic_menu_sort_by_size = 17301661; // 0x108009d
+    field public static final int ic_menu_today = 17301588; // 0x1080054
+    field public static final int ic_menu_upload = 17301589; // 0x1080055
+    field public static final int ic_menu_upload_you_tube = 17301590; // 0x1080056
+    field public static final int ic_menu_view = 17301591; // 0x1080057
+    field public static final int ic_menu_week = 17301592; // 0x1080058
+    field public static final int ic_menu_zoom = 17301593; // 0x1080059
+    field public static final int ic_notification_clear_all = 17301594; // 0x108005a
+    field public static final int ic_notification_overlay = 17301595; // 0x108005b
+    field public static final int ic_partial_secure = 17301596; // 0x108005c
+    field public static final int ic_popup_disk_full = 17301597; // 0x108005d
+    field public static final int ic_popup_reminder = 17301598; // 0x108005e
+    field public static final int ic_popup_sync = 17301599; // 0x108005f
+    field public static final int ic_search_category_default = 17301600; // 0x1080060
+    field public static final int ic_secure = 17301601; // 0x1080061
+    field public static final int list_selector_background = 17301602; // 0x1080062
+    field public static final int menu_frame = 17301603; // 0x1080063
+    field public static final int menu_full_frame = 17301604; // 0x1080064
+    field public static final int menuitem_background = 17301605; // 0x1080065
+    field public static final int picture_frame = 17301606; // 0x1080066
+    field public static final int presence_audio_away = 17301679; // 0x10800af
+    field public static final int presence_audio_busy = 17301680; // 0x10800b0
+    field public static final int presence_audio_online = 17301681; // 0x10800b1
+    field public static final int presence_away = 17301607; // 0x1080067
+    field public static final int presence_busy = 17301608; // 0x1080068
+    field public static final int presence_invisible = 17301609; // 0x1080069
+    field public static final int presence_offline = 17301610; // 0x108006a
+    field public static final int presence_online = 17301611; // 0x108006b
+    field public static final int presence_video_away = 17301676; // 0x10800ac
+    field public static final int presence_video_busy = 17301677; // 0x10800ad
+    field public static final int presence_video_online = 17301678; // 0x10800ae
+    field public static final int progress_horizontal = 17301612; // 0x108006c
+    field public static final int progress_indeterminate_horizontal = 17301613; // 0x108006d
+    field public static final int radiobutton_off_background = 17301614; // 0x108006e
+    field public static final int radiobutton_on_background = 17301615; // 0x108006f
+    field public static final int screen_background_dark = 17301656; // 0x1080098
+    field public static final int screen_background_dark_transparent = 17301673; // 0x10800a9
+    field public static final int screen_background_light = 17301657; // 0x1080099
+    field public static final int screen_background_light_transparent = 17301674; // 0x10800aa
+    field public static final int spinner_background = 17301616; // 0x1080070
+    field public static final int spinner_dropdown_background = 17301617; // 0x1080071
+    field public static final int star_big_off = 17301619; // 0x1080073
+    field public static final int star_big_on = 17301618; // 0x1080072
+    field public static final int star_off = 17301621; // 0x1080075
+    field public static final int star_on = 17301620; // 0x1080074
+    field public static final int stat_notify_call_mute = 17301622; // 0x1080076
+    field public static final int stat_notify_chat = 17301623; // 0x1080077
+    field public static final int stat_notify_error = 17301624; // 0x1080078
+    field public static final int stat_notify_missed_call = 17301631; // 0x108007f
+    field public static final int stat_notify_more = 17301625; // 0x1080079
+    field public static final int stat_notify_sdcard = 17301626; // 0x108007a
+    field public static final int stat_notify_sdcard_prepare = 17301675; // 0x10800ab
+    field public static final int stat_notify_sdcard_usb = 17301627; // 0x108007b
+    field public static final int stat_notify_sync = 17301628; // 0x108007c
+    field public static final int stat_notify_sync_noanim = 17301629; // 0x108007d
+    field public static final int stat_notify_voicemail = 17301630; // 0x108007e
+    field public static final int stat_sys_data_bluetooth = 17301632; // 0x1080080
+    field public static final int stat_sys_download = 17301633; // 0x1080081
+    field public static final int stat_sys_download_done = 17301634; // 0x1080082
+    field public static final int stat_sys_headset = 17301635; // 0x1080083
+    field public static final deprecated int stat_sys_phone_call = 17301636; // 0x1080084
+    field public static final deprecated int stat_sys_phone_call_forward = 17301637; // 0x1080085
+    field public static final deprecated int stat_sys_phone_call_on_hold = 17301638; // 0x1080086
+    field public static final int stat_sys_speakerphone = 17301639; // 0x1080087
+    field public static final int stat_sys_upload = 17301640; // 0x1080088
+    field public static final int stat_sys_upload_done = 17301641; // 0x1080089
+    field public static final deprecated int stat_sys_vp_phone_call = 17301671; // 0x10800a7
+    field public static final deprecated int stat_sys_vp_phone_call_on_hold = 17301672; // 0x10800a8
+    field public static final int stat_sys_warning = 17301642; // 0x108008a
+    field public static final int status_bar_item_app_background = 17301643; // 0x108008b
+    field public static final int status_bar_item_background = 17301644; // 0x108008c
+    field public static final int sym_action_call = 17301645; // 0x108008d
+    field public static final int sym_action_chat = 17301646; // 0x108008e
+    field public static final int sym_action_email = 17301647; // 0x108008f
+    field public static final int sym_call_incoming = 17301648; // 0x1080090
+    field public static final int sym_call_missed = 17301649; // 0x1080091
+    field public static final int sym_call_outgoing = 17301650; // 0x1080092
+    field public static final int sym_contact_card = 17301652; // 0x1080094
+    field public static final int sym_def_app_icon = 17301651; // 0x1080093
+    field public static final int title_bar = 17301653; // 0x1080095
+    field public static final int title_bar_tall = 17301670; // 0x10800a6
+    field public static final int toast_frame = 17301654; // 0x1080096
+    field public static final int zoom_plate = 17301655; // 0x1080097
+  }
+
+  public static final class R.fraction {
+    ctor public R.fraction();
+  }
+
+  public static final class R.id {
+    ctor public R.id();
+    field public static final int addToDictionary = 16908330; // 0x102002a
+    field public static final int background = 16908288; // 0x1020000
+    field public static final int button1 = 16908313; // 0x1020019
+    field public static final int button2 = 16908314; // 0x102001a
+    field public static final int button3 = 16908315; // 0x102001b
+    field public static final int candidatesArea = 16908317; // 0x102001d
+    field public static final int checkbox = 16908289; // 0x1020001
+    field public static final int closeButton = 16908327; // 0x1020027
+    field public static final int content = 16908290; // 0x1020002
+    field public static final int copy = 16908321; // 0x1020021
+    field public static final int copyUrl = 16908323; // 0x1020023
+    field public static final int custom = 16908331; // 0x102002b
+    field public static final int cut = 16908320; // 0x1020020
+    field public static final int edit = 16908291; // 0x1020003
+    field public static final int empty = 16908292; // 0x1020004
+    field public static final int extractArea = 16908316; // 0x102001c
+    field public static final int hint = 16908293; // 0x1020005
+    field public static final int home = 16908332; // 0x102002c
+    field public static final int icon = 16908294; // 0x1020006
+    field public static final int icon1 = 16908295; // 0x1020007
+    field public static final int icon2 = 16908296; // 0x1020008
+    field public static final int input = 16908297; // 0x1020009
+    field public static final int inputArea = 16908318; // 0x102001e
+    field public static final int inputExtractEditText = 16908325; // 0x1020025
+    field public static final int keyboardView = 16908326; // 0x1020026
+    field public static final int list = 16908298; // 0x102000a
+    field public static final int message = 16908299; // 0x102000b
+    field public static final int paste = 16908322; // 0x1020022
+    field public static final int primary = 16908300; // 0x102000c
+    field public static final int progress = 16908301; // 0x102000d
+    field public static final int secondaryProgress = 16908303; // 0x102000f
+    field public static final int selectAll = 16908319; // 0x102001f
+    field public static final int selectTextMode = 16908333; // 0x102002d
+    field public static final int selectedIcon = 16908302; // 0x102000e
+    field public static final int startSelectingText = 16908328; // 0x1020028
+    field public static final int stopSelectingText = 16908329; // 0x1020029
+    field public static final int summary = 16908304; // 0x1020010
+    field public static final int switchInputMethod = 16908324; // 0x1020024
+    field public static final int tabcontent = 16908305; // 0x1020011
+    field public static final int tabhost = 16908306; // 0x1020012
+    field public static final int tabs = 16908307; // 0x1020013
+    field public static final int text1 = 16908308; // 0x1020014
+    field public static final int text2 = 16908309; // 0x1020015
+    field public static final int title = 16908310; // 0x1020016
+    field public static final int toggle = 16908311; // 0x1020017
+    field public static final int widget_frame = 16908312; // 0x1020018
+  }
+
+  public static final class R.integer {
+    ctor public R.integer();
+    field public static final int config_longAnimTime = 17694722; // 0x10e0002
+    field public static final int config_mediumAnimTime = 17694721; // 0x10e0001
+    field public static final int config_shortAnimTime = 17694720; // 0x10e0000
+    field public static final int status_bar_notification_info_maxnum = 17694723; // 0x10e0003
+  }
+
+  public static final class R.interpolator {
+    ctor public R.interpolator();
+    field public static final int accelerate_cubic = 17563650; // 0x10c0002
+    field public static final int accelerate_decelerate = 17563654; // 0x10c0006
+    field public static final int accelerate_quad = 17563648; // 0x10c0000
+    field public static final int accelerate_quint = 17563652; // 0x10c0004
+    field public static final int anticipate = 17563655; // 0x10c0007
+    field public static final int anticipate_overshoot = 17563657; // 0x10c0009
+    field public static final int bounce = 17563658; // 0x10c000a
+    field public static final int cycle = 17563660; // 0x10c000c
+    field public static final int decelerate_cubic = 17563651; // 0x10c0003
+    field public static final int decelerate_quad = 17563649; // 0x10c0001
+    field public static final int decelerate_quint = 17563653; // 0x10c0005
+    field public static final int linear = 17563659; // 0x10c000b
+    field public static final int overshoot = 17563656; // 0x10c0008
+  }
+
+  public static final class R.layout {
+    ctor public R.layout();
+    field public static final int activity_list_item = 17367040; // 0x1090000
+    field public static final int browser_link_context_header = 17367054; // 0x109000e
+    field public static final int expandable_list_content = 17367041; // 0x1090001
+    field public static final int list_content = 17367060; // 0x1090014
+    field public static final int preference_category = 17367042; // 0x1090002
+    field public static final int select_dialog_item = 17367057; // 0x1090011
+    field public static final int select_dialog_multichoice = 17367059; // 0x1090013
+    field public static final int select_dialog_singlechoice = 17367058; // 0x1090012
+    field public static final int simple_dropdown_item_1line = 17367050; // 0x109000a
+    field public static final int simple_expandable_list_item_1 = 17367046; // 0x1090006
+    field public static final int simple_expandable_list_item_2 = 17367047; // 0x1090007
+    field public static final int simple_gallery_item = 17367051; // 0x109000b
+    field public static final int simple_list_item_1 = 17367043; // 0x1090003
+    field public static final int simple_list_item_2 = 17367044; // 0x1090004
+    field public static final int simple_list_item_activated_1 = 17367062; // 0x1090016
+    field public static final int simple_list_item_activated_2 = 17367063; // 0x1090017
+    field public static final int simple_list_item_checked = 17367045; // 0x1090005
+    field public static final int simple_list_item_multiple_choice = 17367056; // 0x1090010
+    field public static final int simple_list_item_single_choice = 17367055; // 0x109000f
+    field public static final int simple_selectable_list_item = 17367061; // 0x1090015
+    field public static final int simple_spinner_dropdown_item = 17367049; // 0x1090009
+    field public static final int simple_spinner_item = 17367048; // 0x1090008
+    field public static final int test_list_item = 17367052; // 0x109000c
+    field public static final int two_line_list_item = 17367053; // 0x109000d
+  }
+
+  public static final class R.menu {
+    ctor public R.menu();
+  }
+
+  public static final class R.mipmap {
+    ctor public R.mipmap();
+    field public static final int sym_def_app_icon = 17629184; // 0x10d0000
+  }
+
+  public static final class R.plurals {
+    ctor public R.plurals();
+  }
+
+  public static final class R.raw {
+    ctor public R.raw();
+  }
+
+  public static final class R.string {
+    ctor public R.string();
+    field public static final int VideoView_error_button = 17039376; // 0x1040010
+    field public static final int VideoView_error_text_invalid_progressive_playback = 17039381; // 0x1040015
+    field public static final int VideoView_error_text_unknown = 17039377; // 0x1040011
+    field public static final int VideoView_error_title = 17039378; // 0x1040012
+    field public static final int cancel = 17039360; // 0x1040000
+    field public static final int copy = 17039361; // 0x1040001
+    field public static final int copyUrl = 17039362; // 0x1040002
+    field public static final int cut = 17039363; // 0x1040003
+    field public static final int defaultMsisdnAlphaTag = 17039365; // 0x1040005
+    field public static final int defaultVoiceMailAlphaTag = 17039364; // 0x1040004
+    field public static final int dialog_alert_title = 17039380; // 0x1040014
+    field public static final int emptyPhoneNumber = 17039366; // 0x1040006
+    field public static final int httpErrorBadUrl = 17039367; // 0x1040007
+    field public static final int httpErrorUnsupportedScheme = 17039368; // 0x1040008
+    field public static final int no = 17039369; // 0x1040009
+    field public static final int ok = 17039370; // 0x104000a
+    field public static final int paste = 17039371; // 0x104000b
+    field public static final int search_go = 17039372; // 0x104000c
+    field public static final int selectAll = 17039373; // 0x104000d
+    field public static final int selectTextMode = 17039382; // 0x1040016
+    field public static final int status_bar_notification_info_overflow = 17039383; // 0x1040017
+    field public static final int unknownName = 17039374; // 0x104000e
+    field public static final int untitled = 17039375; // 0x104000f
+    field public static final int yes = 17039379; // 0x1040013
+  }
+
+  public static final class R.style {
+    ctor public R.style();
+    field public static final int Animation = 16973824; // 0x1030000
+    field public static final int Animation_Activity = 16973825; // 0x1030001
+    field public static final int Animation_Dialog = 16973826; // 0x1030002
+    field public static final int Animation_InputMethod = 16973910; // 0x1030056
+    field public static final int Animation_Toast = 16973828; // 0x1030004
+    field public static final int Animation_Translucent = 16973827; // 0x1030003
+    field public static final int DeviceDefault_ButtonBar = 16974287; // 0x10301cf
+    field public static final int DeviceDefault_ButtonBar_AlertDialog = 16974288; // 0x10301d0
+    field public static final int DeviceDefault_Light_ButtonBar = 16974290; // 0x10301d2
+    field public static final int DeviceDefault_Light_ButtonBar_AlertDialog = 16974291; // 0x10301d3
+    field public static final int DeviceDefault_Light_SegmentedButton = 16974292; // 0x10301d4
+    field public static final int DeviceDefault_SegmentedButton = 16974289; // 0x10301d1
+    field public static final int Holo_ButtonBar = 16974053; // 0x10300e5
+    field public static final int Holo_ButtonBar_AlertDialog = 16974055; // 0x10300e7
+    field public static final int Holo_Light_ButtonBar = 16974054; // 0x10300e6
+    field public static final int Holo_Light_ButtonBar_AlertDialog = 16974056; // 0x10300e8
+    field public static final int Holo_Light_SegmentedButton = 16974058; // 0x10300ea
+    field public static final int Holo_SegmentedButton = 16974057; // 0x10300e9
+    field public static final int MediaButton = 16973879; // 0x1030037
+    field public static final int MediaButton_Ffwd = 16973883; // 0x103003b
+    field public static final int MediaButton_Next = 16973881; // 0x1030039
+    field public static final int MediaButton_Pause = 16973885; // 0x103003d
+    field public static final int MediaButton_Play = 16973882; // 0x103003a
+    field public static final int MediaButton_Previous = 16973880; // 0x1030038
+    field public static final int MediaButton_Rew = 16973884; // 0x103003c
+    field public static final int TextAppearance = 16973886; // 0x103003e
+    field public static final int TextAppearance_DeviceDefault = 16974253; // 0x10301ad
+    field public static final int TextAppearance_DeviceDefault_DialogWindowTitle = 16974264; // 0x10301b8
+    field public static final int TextAppearance_DeviceDefault_Inverse = 16974254; // 0x10301ae
+    field public static final int TextAppearance_DeviceDefault_Large = 16974255; // 0x10301af
+    field public static final int TextAppearance_DeviceDefault_Large_Inverse = 16974256; // 0x10301b0
+    field public static final int TextAppearance_DeviceDefault_Medium = 16974257; // 0x10301b1
+    field public static final int TextAppearance_DeviceDefault_Medium_Inverse = 16974258; // 0x10301b2
+    field public static final int TextAppearance_DeviceDefault_SearchResult_Subtitle = 16974262; // 0x10301b6
+    field public static final int TextAppearance_DeviceDefault_SearchResult_Title = 16974261; // 0x10301b5
+    field public static final int TextAppearance_DeviceDefault_Small = 16974259; // 0x10301b3
+    field public static final int TextAppearance_DeviceDefault_Small_Inverse = 16974260; // 0x10301b4
+    field public static final int TextAppearance_DeviceDefault_Widget = 16974265; // 0x10301b9
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Menu = 16974286; // 0x10301ce
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Subtitle = 16974279; // 0x10301c7
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Subtitle_Inverse = 16974283; // 0x10301cb
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Title = 16974278; // 0x10301c6
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Title_Inverse = 16974282; // 0x10301ca
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Subtitle = 16974281; // 0x10301c9
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Subtitle_Inverse = 16974285; // 0x10301cd
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Title = 16974280; // 0x10301c8
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Title_Inverse = 16974284; // 0x10301cc
+    field public static final int TextAppearance_DeviceDefault_Widget_Button = 16974266; // 0x10301ba
+    field public static final int TextAppearance_DeviceDefault_Widget_DropDownHint = 16974271; // 0x10301bf
+    field public static final int TextAppearance_DeviceDefault_Widget_DropDownItem = 16974272; // 0x10301c0
+    field public static final int TextAppearance_DeviceDefault_Widget_EditText = 16974274; // 0x10301c2
+    field public static final int TextAppearance_DeviceDefault_Widget_IconMenu_Item = 16974267; // 0x10301bb
+    field public static final int TextAppearance_DeviceDefault_Widget_PopupMenu = 16974275; // 0x10301c3
+    field public static final int TextAppearance_DeviceDefault_Widget_PopupMenu_Large = 16974276; // 0x10301c4
+    field public static final int TextAppearance_DeviceDefault_Widget_PopupMenu_Small = 16974277; // 0x10301c5
+    field public static final int TextAppearance_DeviceDefault_Widget_TabWidget = 16974268; // 0x10301bc
+    field public static final int TextAppearance_DeviceDefault_Widget_TextView = 16974269; // 0x10301bd
+    field public static final int TextAppearance_DeviceDefault_Widget_TextView_PopupMenu = 16974270; // 0x10301be
+    field public static final int TextAppearance_DeviceDefault_Widget_TextView_SpinnerItem = 16974273; // 0x10301c1
+    field public static final int TextAppearance_DeviceDefault_WindowTitle = 16974263; // 0x10301b7
+    field public static final int TextAppearance_DialogWindowTitle = 16973889; // 0x1030041
+    field public static final int TextAppearance_Holo = 16974075; // 0x10300fb
+    field public static final int TextAppearance_Holo_DialogWindowTitle = 16974103; // 0x1030117
+    field public static final int TextAppearance_Holo_Inverse = 16974076; // 0x10300fc
+    field public static final int TextAppearance_Holo_Large = 16974077; // 0x10300fd
+    field public static final int TextAppearance_Holo_Large_Inverse = 16974078; // 0x10300fe
+    field public static final int TextAppearance_Holo_Medium = 16974079; // 0x10300ff
+    field public static final int TextAppearance_Holo_Medium_Inverse = 16974080; // 0x1030100
+    field public static final int TextAppearance_Holo_SearchResult_Subtitle = 16974084; // 0x1030104
+    field public static final int TextAppearance_Holo_SearchResult_Title = 16974083; // 0x1030103
+    field public static final int TextAppearance_Holo_Small = 16974081; // 0x1030101
+    field public static final int TextAppearance_Holo_Small_Inverse = 16974082; // 0x1030102
+    field public static final int TextAppearance_Holo_Widget = 16974085; // 0x1030105
+    field public static final int TextAppearance_Holo_Widget_ActionBar_Menu = 16974112; // 0x1030120
+    field public static final int TextAppearance_Holo_Widget_ActionBar_Subtitle = 16974099; // 0x1030113
+    field public static final int TextAppearance_Holo_Widget_ActionBar_Subtitle_Inverse = 16974109; // 0x103011d
+    field public static final int TextAppearance_Holo_Widget_ActionBar_Title = 16974098; // 0x1030112
+    field public static final int TextAppearance_Holo_Widget_ActionBar_Title_Inverse = 16974108; // 0x103011c
+    field public static final int TextAppearance_Holo_Widget_ActionMode_Subtitle = 16974101; // 0x1030115
+    field public static final int TextAppearance_Holo_Widget_ActionMode_Subtitle_Inverse = 16974111; // 0x103011f
+    field public static final int TextAppearance_Holo_Widget_ActionMode_Title = 16974100; // 0x1030114
+    field public static final int TextAppearance_Holo_Widget_ActionMode_Title_Inverse = 16974110; // 0x103011e
+    field public static final int TextAppearance_Holo_Widget_Button = 16974086; // 0x1030106
+    field public static final int TextAppearance_Holo_Widget_DropDownHint = 16974091; // 0x103010b
+    field public static final int TextAppearance_Holo_Widget_DropDownItem = 16974092; // 0x103010c
+    field public static final int TextAppearance_Holo_Widget_EditText = 16974094; // 0x103010e
+    field public static final int TextAppearance_Holo_Widget_IconMenu_Item = 16974087; // 0x1030107
+    field public static final int TextAppearance_Holo_Widget_PopupMenu = 16974095; // 0x103010f
+    field public static final int TextAppearance_Holo_Widget_PopupMenu_Large = 16974096; // 0x1030110
+    field public static final int TextAppearance_Holo_Widget_PopupMenu_Small = 16974097; // 0x1030111
+    field public static final int TextAppearance_Holo_Widget_TabWidget = 16974088; // 0x1030108
+    field public static final int TextAppearance_Holo_Widget_TextView = 16974089; // 0x1030109
+    field public static final int TextAppearance_Holo_Widget_TextView_PopupMenu = 16974090; // 0x103010a
+    field public static final int TextAppearance_Holo_Widget_TextView_SpinnerItem = 16974093; // 0x103010d
+    field public static final int TextAppearance_Holo_WindowTitle = 16974102; // 0x1030116
+    field public static final int TextAppearance_Inverse = 16973887; // 0x103003f
+    field public static final int TextAppearance_Large = 16973890; // 0x1030042
+    field public static final int TextAppearance_Large_Inverse = 16973891; // 0x1030043
+    field public static final int TextAppearance_Medium = 16973892; // 0x1030044
+    field public static final int TextAppearance_Medium_Inverse = 16973893; // 0x1030045
+    field public static final int TextAppearance_Small = 16973894; // 0x1030046
+    field public static final int TextAppearance_Small_Inverse = 16973895; // 0x1030047
+    field public static final int TextAppearance_StatusBar_EventContent = 16973927; // 0x1030067
+    field public static final int TextAppearance_StatusBar_EventContent_Title = 16973928; // 0x1030068
+    field public static final int TextAppearance_StatusBar_Icon = 16973926; // 0x1030066
+    field public static final int TextAppearance_StatusBar_Title = 16973925; // 0x1030065
+    field public static final int TextAppearance_SuggestionHighlight = 16974104; // 0x1030118
+    field public static final int TextAppearance_Theme = 16973888; // 0x1030040
+    field public static final int TextAppearance_Theme_Dialog = 16973896; // 0x1030048
+    field public static final int TextAppearance_Widget = 16973897; // 0x1030049
+    field public static final int TextAppearance_Widget_Button = 16973898; // 0x103004a
+    field public static final int TextAppearance_Widget_DropDownHint = 16973904; // 0x1030050
+    field public static final int TextAppearance_Widget_DropDownItem = 16973905; // 0x1030051
+    field public static final int TextAppearance_Widget_EditText = 16973900; // 0x103004c
+    field public static final int TextAppearance_Widget_IconMenu_Item = 16973899; // 0x103004b
+    field public static final int TextAppearance_Widget_PopupMenu_Large = 16973952; // 0x1030080
+    field public static final int TextAppearance_Widget_PopupMenu_Small = 16973953; // 0x1030081
+    field public static final int TextAppearance_Widget_TabWidget = 16973901; // 0x103004d
+    field public static final int TextAppearance_Widget_TextView = 16973902; // 0x103004e
+    field public static final int TextAppearance_Widget_TextView_PopupMenu = 16973903; // 0x103004f
+    field public static final int TextAppearance_Widget_TextView_SpinnerItem = 16973906; // 0x1030052
+    field public static final int TextAppearance_WindowTitle = 16973907; // 0x1030053
+    field public static final int Theme = 16973829; // 0x1030005
+    field public static final int Theme_Black = 16973832; // 0x1030008
+    field public static final int Theme_Black_NoTitleBar = 16973833; // 0x1030009
+    field public static final int Theme_Black_NoTitleBar_Fullscreen = 16973834; // 0x103000a
+    field public static final int Theme_DeviceDefault = 16974120; // 0x1030128
+    field public static final int Theme_DeviceDefault_Dialog = 16974126; // 0x103012e
+    field public static final int Theme_DeviceDefault_DialogWhenLarge = 16974134; // 0x1030136
+    field public static final int Theme_DeviceDefault_DialogWhenLarge_NoActionBar = 16974135; // 0x1030137
+    field public static final int Theme_DeviceDefault_Dialog_MinWidth = 16974127; // 0x103012f
+    field public static final int Theme_DeviceDefault_Dialog_NoActionBar = 16974128; // 0x1030130
+    field public static final int Theme_DeviceDefault_Dialog_NoActionBar_MinWidth = 16974129; // 0x1030131
+    field public static final int Theme_DeviceDefault_InputMethod = 16974142; // 0x103013e
+    field public static final int Theme_DeviceDefault_Light = 16974123; // 0x103012b
+    field public static final int Theme_DeviceDefault_Light_DarkActionBar = 16974143; // 0x103013f
+    field public static final int Theme_DeviceDefault_Light_Dialog = 16974130; // 0x1030132
+    field public static final int Theme_DeviceDefault_Light_DialogWhenLarge = 16974136; // 0x1030138
+    field public static final int Theme_DeviceDefault_Light_DialogWhenLarge_NoActionBar = 16974137; // 0x1030139
+    field public static final int Theme_DeviceDefault_Light_Dialog_MinWidth = 16974131; // 0x1030133
+    field public static final int Theme_DeviceDefault_Light_Dialog_NoActionBar = 16974132; // 0x1030134
+    field public static final int Theme_DeviceDefault_Light_Dialog_NoActionBar_MinWidth = 16974133; // 0x1030135
+    field public static final int Theme_DeviceDefault_Light_NoActionBar = 16974124; // 0x103012c
+    field public static final int Theme_DeviceDefault_Light_NoActionBar_Fullscreen = 16974125; // 0x103012d
+    field public static final int Theme_DeviceDefault_Light_Panel = 16974139; // 0x103013b
+    field public static final int Theme_DeviceDefault_NoActionBar = 16974121; // 0x1030129
+    field public static final int Theme_DeviceDefault_NoActionBar_Fullscreen = 16974122; // 0x103012a
+    field public static final int Theme_DeviceDefault_Panel = 16974138; // 0x103013a
+    field public static final int Theme_DeviceDefault_Wallpaper = 16974140; // 0x103013c
+    field public static final int Theme_DeviceDefault_Wallpaper_NoTitleBar = 16974141; // 0x103013d
+    field public static final int Theme_Dialog = 16973835; // 0x103000b
+    field public static final int Theme_Holo = 16973931; // 0x103006b
+    field public static final int Theme_Holo_Dialog = 16973935; // 0x103006f
+    field public static final int Theme_Holo_DialogWhenLarge = 16973943; // 0x1030077
+    field public static final int Theme_Holo_DialogWhenLarge_NoActionBar = 16973944; // 0x1030078
+    field public static final int Theme_Holo_Dialog_MinWidth = 16973936; // 0x1030070
+    field public static final int Theme_Holo_Dialog_NoActionBar = 16973937; // 0x1030071
+    field public static final int Theme_Holo_Dialog_NoActionBar_MinWidth = 16973938; // 0x1030072
+    field public static final int Theme_Holo_InputMethod = 16973951; // 0x103007f
+    field public static final int Theme_Holo_Light = 16973934; // 0x103006e
+    field public static final int Theme_Holo_Light_DarkActionBar = 16974105; // 0x1030119
+    field public static final int Theme_Holo_Light_Dialog = 16973939; // 0x1030073
+    field public static final int Theme_Holo_Light_DialogWhenLarge = 16973945; // 0x1030079
+    field public static final int Theme_Holo_Light_DialogWhenLarge_NoActionBar = 16973946; // 0x103007a
+    field public static final int Theme_Holo_Light_Dialog_MinWidth = 16973940; // 0x1030074
+    field public static final int Theme_Holo_Light_Dialog_NoActionBar = 16973941; // 0x1030075
+    field public static final int Theme_Holo_Light_Dialog_NoActionBar_MinWidth = 16973942; // 0x1030076
+    field public static final int Theme_Holo_Light_NoActionBar = 16974064; // 0x10300f0
+    field public static final int Theme_Holo_Light_NoActionBar_Fullscreen = 16974065; // 0x10300f1
+    field public static final int Theme_Holo_Light_Panel = 16973948; // 0x103007c
+    field public static final int Theme_Holo_NoActionBar = 16973932; // 0x103006c
+    field public static final int Theme_Holo_NoActionBar_Fullscreen = 16973933; // 0x103006d
+    field public static final int Theme_Holo_Panel = 16973947; // 0x103007b
+    field public static final int Theme_Holo_Wallpaper = 16973949; // 0x103007d
+    field public static final int Theme_Holo_Wallpaper_NoTitleBar = 16973950; // 0x103007e
+    field public static final int Theme_InputMethod = 16973908; // 0x1030054
+    field public static final int Theme_Light = 16973836; // 0x103000c
+    field public static final int Theme_Light_NoTitleBar = 16973837; // 0x103000d
+    field public static final int Theme_Light_NoTitleBar_Fullscreen = 16973838; // 0x103000e
+    field public static final int Theme_Light_Panel = 16973914; // 0x103005a
+    field public static final int Theme_Light_WallpaperSettings = 16973922; // 0x1030062
+    field public static final int Theme_NoDisplay = 16973909; // 0x1030055
+    field public static final int Theme_NoTitleBar = 16973830; // 0x1030006
+    field public static final int Theme_NoTitleBar_Fullscreen = 16973831; // 0x1030007
+    field public static final int Theme_NoTitleBar_OverlayActionModes = 16973930; // 0x103006a
+    field public static final int Theme_Panel = 16973913; // 0x1030059
+    field public static final int Theme_Translucent = 16973839; // 0x103000f
+    field public static final int Theme_Translucent_NoTitleBar = 16973840; // 0x1030010
+    field public static final int Theme_Translucent_NoTitleBar_Fullscreen = 16973841; // 0x1030011
+    field public static final int Theme_Wallpaper = 16973918; // 0x103005e
+    field public static final int Theme_WallpaperSettings = 16973921; // 0x1030061
+    field public static final int Theme_Wallpaper_NoTitleBar = 16973919; // 0x103005f
+    field public static final int Theme_Wallpaper_NoTitleBar_Fullscreen = 16973920; // 0x1030060
+    field public static final int Theme_WithActionBar = 16973929; // 0x1030069
+    field public static final int Widget = 16973842; // 0x1030012
+    field public static final int Widget_AbsListView = 16973843; // 0x1030013
+    field public static final int Widget_ActionBar = 16973954; // 0x1030082
+    field public static final int Widget_ActionBar_TabBar = 16974068; // 0x10300f4
+    field public static final int Widget_ActionBar_TabText = 16974067; // 0x10300f3
+    field public static final int Widget_ActionBar_TabView = 16974066; // 0x10300f2
+    field public static final int Widget_ActionButton = 16973956; // 0x1030084
+    field public static final int Widget_ActionButton_CloseMode = 16973960; // 0x1030088
+    field public static final int Widget_ActionButton_Overflow = 16973959; // 0x1030087
+    field public static final int Widget_AutoCompleteTextView = 16973863; // 0x1030027
+    field public static final int Widget_Button = 16973844; // 0x1030014
+    field public static final int Widget_Button_Inset = 16973845; // 0x1030015
+    field public static final int Widget_Button_Small = 16973846; // 0x1030016
+    field public static final int Widget_Button_Toggle = 16973847; // 0x1030017
+    field public static final int Widget_CalendarView = 16974059; // 0x10300eb
+    field public static final int Widget_CompoundButton = 16973848; // 0x1030018
+    field public static final int Widget_CompoundButton_CheckBox = 16973849; // 0x1030019
+    field public static final int Widget_CompoundButton_RadioButton = 16973850; // 0x103001a
+    field public static final int Widget_CompoundButton_Star = 16973851; // 0x103001b
+    field public static final int Widget_DatePicker = 16974062; // 0x10300ee
+    field public static final int Widget_DeviceDefault = 16974144; // 0x1030140
+    field public static final int Widget_DeviceDefault_ActionBar = 16974187; // 0x103016b
+    field public static final int Widget_DeviceDefault_ActionBar_Solid = 16974195; // 0x1030173
+    field public static final int Widget_DeviceDefault_ActionBar_TabBar = 16974194; // 0x1030172
+    field public static final int Widget_DeviceDefault_ActionBar_TabText = 16974193; // 0x1030171
+    field public static final int Widget_DeviceDefault_ActionBar_TabView = 16974192; // 0x1030170
+    field public static final int Widget_DeviceDefault_ActionButton = 16974182; // 0x1030166
+    field public static final int Widget_DeviceDefault_ActionButton_CloseMode = 16974186; // 0x103016a
+    field public static final int Widget_DeviceDefault_ActionButton_Overflow = 16974183; // 0x1030167
+    field public static final int Widget_DeviceDefault_ActionButton_TextButton = 16974184; // 0x1030168
+    field public static final int Widget_DeviceDefault_ActionMode = 16974185; // 0x1030169
+    field public static final int Widget_DeviceDefault_AutoCompleteTextView = 16974151; // 0x1030147
+    field public static final int Widget_DeviceDefault_Button = 16974145; // 0x1030141
+    field public static final int Widget_DeviceDefault_Button_Borderless = 16974188; // 0x103016c
+    field public static final int Widget_DeviceDefault_Button_Borderless_Small = 16974149; // 0x1030145
+    field public static final int Widget_DeviceDefault_Button_Inset = 16974147; // 0x1030143
+    field public static final int Widget_DeviceDefault_Button_Small = 16974146; // 0x1030142
+    field public static final int Widget_DeviceDefault_Button_Toggle = 16974148; // 0x1030144
+    field public static final int Widget_DeviceDefault_CalendarView = 16974190; // 0x103016e
+    field public static final int Widget_DeviceDefault_CheckedTextView = 16974299; // 0x10301db
+    field public static final int Widget_DeviceDefault_CompoundButton_CheckBox = 16974152; // 0x1030148
+    field public static final int Widget_DeviceDefault_CompoundButton_RadioButton = 16974169; // 0x1030159
+    field public static final int Widget_DeviceDefault_CompoundButton_Star = 16974173; // 0x103015d
+    field public static final int Widget_DeviceDefault_DatePicker = 16974191; // 0x103016f
+    field public static final int Widget_DeviceDefault_DropDownItem = 16974177; // 0x1030161
+    field public static final int Widget_DeviceDefault_DropDownItem_Spinner = 16974178; // 0x1030162
+    field public static final int Widget_DeviceDefault_EditText = 16974154; // 0x103014a
+    field public static final int Widget_DeviceDefault_ExpandableListView = 16974155; // 0x103014b
+    field public static final int Widget_DeviceDefault_GridView = 16974156; // 0x103014c
+    field public static final int Widget_DeviceDefault_HorizontalScrollView = 16974171; // 0x103015b
+    field public static final int Widget_DeviceDefault_ImageButton = 16974157; // 0x103014d
+    field public static final int Widget_DeviceDefault_Light = 16974196; // 0x1030174
+    field public static final int Widget_DeviceDefault_Light_ActionBar = 16974243; // 0x10301a3
+    field public static final int Widget_DeviceDefault_Light_ActionBar_Solid = 16974247; // 0x10301a7
+    field public static final int Widget_DeviceDefault_Light_ActionBar_Solid_Inverse = 16974248; // 0x10301a8
+    field public static final int Widget_DeviceDefault_Light_ActionBar_TabBar = 16974246; // 0x10301a6
+    field public static final int Widget_DeviceDefault_Light_ActionBar_TabBar_Inverse = 16974249; // 0x10301a9
+    field public static final int Widget_DeviceDefault_Light_ActionBar_TabText = 16974245; // 0x10301a5
+    field public static final int Widget_DeviceDefault_Light_ActionBar_TabText_Inverse = 16974251; // 0x10301ab
+    field public static final int Widget_DeviceDefault_Light_ActionBar_TabView = 16974244; // 0x10301a4
+    field public static final int Widget_DeviceDefault_Light_ActionBar_TabView_Inverse = 16974250; // 0x10301aa
+    field public static final int Widget_DeviceDefault_Light_ActionButton = 16974239; // 0x103019f
+    field public static final int Widget_DeviceDefault_Light_ActionButton_CloseMode = 16974242; // 0x10301a2
+    field public static final int Widget_DeviceDefault_Light_ActionButton_Overflow = 16974240; // 0x10301a0
+    field public static final int Widget_DeviceDefault_Light_ActionMode = 16974241; // 0x10301a1
+    field public static final int Widget_DeviceDefault_Light_ActionMode_Inverse = 16974252; // 0x10301ac
+    field public static final int Widget_DeviceDefault_Light_AutoCompleteTextView = 16974203; // 0x103017b
+    field public static final int Widget_DeviceDefault_Light_Button = 16974197; // 0x1030175
+    field public static final int Widget_DeviceDefault_Light_Button_Borderless_Small = 16974201; // 0x1030179
+    field public static final int Widget_DeviceDefault_Light_Button_Inset = 16974199; // 0x1030177
+    field public static final int Widget_DeviceDefault_Light_Button_Small = 16974198; // 0x1030176
+    field public static final int Widget_DeviceDefault_Light_Button_Toggle = 16974200; // 0x1030178
+    field public static final int Widget_DeviceDefault_Light_CalendarView = 16974238; // 0x103019e
+    field public static final int Widget_DeviceDefault_Light_CheckedTextView = 16974300; // 0x10301dc
+    field public static final int Widget_DeviceDefault_Light_CompoundButton_CheckBox = 16974204; // 0x103017c
+    field public static final int Widget_DeviceDefault_Light_CompoundButton_RadioButton = 16974224; // 0x1030190
+    field public static final int Widget_DeviceDefault_Light_CompoundButton_Star = 16974228; // 0x1030194
+    field public static final int Widget_DeviceDefault_Light_DropDownItem = 16974232; // 0x1030198
+    field public static final int Widget_DeviceDefault_Light_DropDownItem_Spinner = 16974233; // 0x1030199
+    field public static final int Widget_DeviceDefault_Light_EditText = 16974206; // 0x103017e
+    field public static final int Widget_DeviceDefault_Light_ExpandableListView = 16974207; // 0x103017f
+    field public static final int Widget_DeviceDefault_Light_GridView = 16974208; // 0x1030180
+    field public static final int Widget_DeviceDefault_Light_HorizontalScrollView = 16974226; // 0x1030192
+    field public static final int Widget_DeviceDefault_Light_ImageButton = 16974209; // 0x1030181
+    field public static final int Widget_DeviceDefault_Light_ListPopupWindow = 16974235; // 0x103019b
+    field public static final int Widget_DeviceDefault_Light_ListView = 16974210; // 0x1030182
+    field public static final int Widget_DeviceDefault_Light_ListView_DropDown = 16974205; // 0x103017d
+    field public static final int Widget_DeviceDefault_Light_MediaRouteButton = 16974296; // 0x10301d8
+    field public static final int Widget_DeviceDefault_Light_PopupMenu = 16974236; // 0x103019c
+    field public static final int Widget_DeviceDefault_Light_PopupWindow = 16974211; // 0x1030183
+    field public static final int Widget_DeviceDefault_Light_ProgressBar = 16974212; // 0x1030184
+    field public static final int Widget_DeviceDefault_Light_ProgressBar_Horizontal = 16974213; // 0x1030185
+    field public static final int Widget_DeviceDefault_Light_ProgressBar_Inverse = 16974217; // 0x1030189
+    field public static final int Widget_DeviceDefault_Light_ProgressBar_Large = 16974216; // 0x1030188
+    field public static final int Widget_DeviceDefault_Light_ProgressBar_Large_Inverse = 16974219; // 0x103018b
+    field public static final int Widget_DeviceDefault_Light_ProgressBar_Small = 16974214; // 0x1030186
+    field public static final int Widget_DeviceDefault_Light_ProgressBar_Small_Inverse = 16974218; // 0x103018a
+    field public static final int Widget_DeviceDefault_Light_ProgressBar_Small_Title = 16974215; // 0x1030187
+    field public static final int Widget_DeviceDefault_Light_RatingBar = 16974221; // 0x103018d
+    field public static final int Widget_DeviceDefault_Light_RatingBar_Indicator = 16974222; // 0x103018e
+    field public static final int Widget_DeviceDefault_Light_RatingBar_Small = 16974223; // 0x103018f
+    field public static final int Widget_DeviceDefault_Light_ScrollView = 16974225; // 0x1030191
+    field public static final int Widget_DeviceDefault_Light_SeekBar = 16974220; // 0x103018c
+    field public static final int Widget_DeviceDefault_Light_Spinner = 16974227; // 0x1030193
+    field public static final int Widget_DeviceDefault_Light_Tab = 16974237; // 0x103019d
+    field public static final int Widget_DeviceDefault_Light_TabWidget = 16974229; // 0x1030195
+    field public static final int Widget_DeviceDefault_Light_TextView = 16974202; // 0x103017a
+    field public static final int Widget_DeviceDefault_Light_TextView_SpinnerItem = 16974234; // 0x103019a
+    field public static final int Widget_DeviceDefault_Light_WebTextView = 16974230; // 0x1030196
+    field public static final int Widget_DeviceDefault_Light_WebView = 16974231; // 0x1030197
+    field public static final int Widget_DeviceDefault_ListPopupWindow = 16974180; // 0x1030164
+    field public static final int Widget_DeviceDefault_ListView = 16974158; // 0x103014e
+    field public static final int Widget_DeviceDefault_ListView_DropDown = 16974153; // 0x1030149
+    field public static final int Widget_DeviceDefault_MediaRouteButton = 16974295; // 0x10301d7
+    field public static final int Widget_DeviceDefault_PopupMenu = 16974181; // 0x1030165
+    field public static final int Widget_DeviceDefault_PopupWindow = 16974159; // 0x103014f
+    field public static final int Widget_DeviceDefault_ProgressBar = 16974160; // 0x1030150
+    field public static final int Widget_DeviceDefault_ProgressBar_Horizontal = 16974161; // 0x1030151
+    field public static final int Widget_DeviceDefault_ProgressBar_Large = 16974164; // 0x1030154
+    field public static final int Widget_DeviceDefault_ProgressBar_Small = 16974162; // 0x1030152
+    field public static final int Widget_DeviceDefault_ProgressBar_Small_Title = 16974163; // 0x1030153
+    field public static final int Widget_DeviceDefault_RatingBar = 16974166; // 0x1030156
+    field public static final int Widget_DeviceDefault_RatingBar_Indicator = 16974167; // 0x1030157
+    field public static final int Widget_DeviceDefault_RatingBar_Small = 16974168; // 0x1030158
+    field public static final int Widget_DeviceDefault_ScrollView = 16974170; // 0x103015a
+    field public static final int Widget_DeviceDefault_SeekBar = 16974165; // 0x1030155
+    field public static final int Widget_DeviceDefault_Spinner = 16974172; // 0x103015c
+    field public static final int Widget_DeviceDefault_Tab = 16974189; // 0x103016d
+    field public static final int Widget_DeviceDefault_TabWidget = 16974174; // 0x103015e
+    field public static final int Widget_DeviceDefault_TextView = 16974150; // 0x1030146
+    field public static final int Widget_DeviceDefault_TextView_SpinnerItem = 16974179; // 0x1030163
+    field public static final int Widget_DeviceDefault_WebTextView = 16974175; // 0x103015f
+    field public static final int Widget_DeviceDefault_WebView = 16974176; // 0x1030160
+    field public static final int Widget_DropDownItem = 16973867; // 0x103002b
+    field public static final int Widget_DropDownItem_Spinner = 16973868; // 0x103002c
+    field public static final int Widget_EditText = 16973859; // 0x1030023
+    field public static final int Widget_ExpandableListView = 16973860; // 0x1030024
+    field public static final int Widget_FragmentBreadCrumbs = 16973961; // 0x1030089
+    field public static final int Widget_Gallery = 16973877; // 0x1030035
+    field public static final int Widget_GridView = 16973874; // 0x1030032
+    field public static final int Widget_Holo = 16973962; // 0x103008a
+    field public static final int Widget_Holo_ActionBar = 16974004; // 0x10300b4
+    field public static final int Widget_Holo_ActionBar_Solid = 16974113; // 0x1030121
+    field public static final int Widget_Holo_ActionBar_TabBar = 16974071; // 0x10300f7
+    field public static final int Widget_Holo_ActionBar_TabText = 16974070; // 0x10300f6
+    field public static final int Widget_Holo_ActionBar_TabView = 16974069; // 0x10300f5
+    field public static final int Widget_Holo_ActionButton = 16973999; // 0x10300af
+    field public static final int Widget_Holo_ActionButton_CloseMode = 16974003; // 0x10300b3
+    field public static final int Widget_Holo_ActionButton_Overflow = 16974000; // 0x10300b0
+    field public static final int Widget_Holo_ActionButton_TextButton = 16974001; // 0x10300b1
+    field public static final int Widget_Holo_ActionMode = 16974002; // 0x10300b2
+    field public static final int Widget_Holo_AutoCompleteTextView = 16973968; // 0x1030090
+    field public static final int Widget_Holo_Button = 16973963; // 0x103008b
+    field public static final int Widget_Holo_Button_Borderless = 16974050; // 0x10300e2
+    field public static final int Widget_Holo_Button_Borderless_Small = 16974106; // 0x103011a
+    field public static final int Widget_Holo_Button_Inset = 16973965; // 0x103008d
+    field public static final int Widget_Holo_Button_Small = 16973964; // 0x103008c
+    field public static final int Widget_Holo_Button_Toggle = 16973966; // 0x103008e
+    field public static final int Widget_Holo_CalendarView = 16974060; // 0x10300ec
+    field public static final int Widget_Holo_CheckedTextView = 16974297; // 0x10301d9
+    field public static final int Widget_Holo_CompoundButton_CheckBox = 16973969; // 0x1030091
+    field public static final int Widget_Holo_CompoundButton_RadioButton = 16973986; // 0x10300a2
+    field public static final int Widget_Holo_CompoundButton_Star = 16973990; // 0x10300a6
+    field public static final int Widget_Holo_DatePicker = 16974063; // 0x10300ef
+    field public static final int Widget_Holo_DropDownItem = 16973994; // 0x10300aa
+    field public static final int Widget_Holo_DropDownItem_Spinner = 16973995; // 0x10300ab
+    field public static final int Widget_Holo_EditText = 16973971; // 0x1030093
+    field public static final int Widget_Holo_ExpandableListView = 16973972; // 0x1030094
+    field public static final int Widget_Holo_GridView = 16973973; // 0x1030095
+    field public static final int Widget_Holo_HorizontalScrollView = 16973988; // 0x10300a4
+    field public static final int Widget_Holo_ImageButton = 16973974; // 0x1030096
+    field public static final int Widget_Holo_Light = 16974005; // 0x10300b5
+    field public static final int Widget_Holo_Light_ActionBar = 16974049; // 0x10300e1
+    field public static final int Widget_Holo_Light_ActionBar_Solid = 16974114; // 0x1030122
+    field public static final int Widget_Holo_Light_ActionBar_Solid_Inverse = 16974115; // 0x1030123
+    field public static final int Widget_Holo_Light_ActionBar_TabBar = 16974074; // 0x10300fa
+    field public static final int Widget_Holo_Light_ActionBar_TabBar_Inverse = 16974116; // 0x1030124
+    field public static final int Widget_Holo_Light_ActionBar_TabText = 16974073; // 0x10300f9
+    field public static final int Widget_Holo_Light_ActionBar_TabText_Inverse = 16974118; // 0x1030126
+    field public static final int Widget_Holo_Light_ActionBar_TabView = 16974072; // 0x10300f8
+    field public static final int Widget_Holo_Light_ActionBar_TabView_Inverse = 16974117; // 0x1030125
+    field public static final int Widget_Holo_Light_ActionButton = 16974045; // 0x10300dd
+    field public static final int Widget_Holo_Light_ActionButton_CloseMode = 16974048; // 0x10300e0
+    field public static final int Widget_Holo_Light_ActionButton_Overflow = 16974046; // 0x10300de
+    field public static final int Widget_Holo_Light_ActionMode = 16974047; // 0x10300df
+    field public static final int Widget_Holo_Light_ActionMode_Inverse = 16974119; // 0x1030127
+    field public static final int Widget_Holo_Light_AutoCompleteTextView = 16974011; // 0x10300bb
+    field public static final int Widget_Holo_Light_Button = 16974006; // 0x10300b6
+    field public static final int Widget_Holo_Light_Button_Borderless_Small = 16974107; // 0x103011b
+    field public static final int Widget_Holo_Light_Button_Inset = 16974008; // 0x10300b8
+    field public static final int Widget_Holo_Light_Button_Small = 16974007; // 0x10300b7
+    field public static final int Widget_Holo_Light_Button_Toggle = 16974009; // 0x10300b9
+    field public static final int Widget_Holo_Light_CalendarView = 16974061; // 0x10300ed
+    field public static final int Widget_Holo_Light_CheckedTextView = 16974298; // 0x10301da
+    field public static final int Widget_Holo_Light_CompoundButton_CheckBox = 16974012; // 0x10300bc
+    field public static final int Widget_Holo_Light_CompoundButton_RadioButton = 16974032; // 0x10300d0
+    field public static final int Widget_Holo_Light_CompoundButton_Star = 16974036; // 0x10300d4
+    field public static final int Widget_Holo_Light_DropDownItem = 16974040; // 0x10300d8
+    field public static final int Widget_Holo_Light_DropDownItem_Spinner = 16974041; // 0x10300d9
+    field public static final int Widget_Holo_Light_EditText = 16974014; // 0x10300be
+    field public static final int Widget_Holo_Light_ExpandableListView = 16974015; // 0x10300bf
+    field public static final int Widget_Holo_Light_GridView = 16974016; // 0x10300c0
+    field public static final int Widget_Holo_Light_HorizontalScrollView = 16974034; // 0x10300d2
+    field public static final int Widget_Holo_Light_ImageButton = 16974017; // 0x10300c1
+    field public static final int Widget_Holo_Light_ListPopupWindow = 16974043; // 0x10300db
+    field public static final int Widget_Holo_Light_ListView = 16974018; // 0x10300c2
+    field public static final int Widget_Holo_Light_ListView_DropDown = 16974013; // 0x10300bd
+    field public static final int Widget_Holo_Light_MediaRouteButton = 16974294; // 0x10301d6
+    field public static final int Widget_Holo_Light_PopupMenu = 16974044; // 0x10300dc
+    field public static final int Widget_Holo_Light_PopupWindow = 16974019; // 0x10300c3
+    field public static final int Widget_Holo_Light_ProgressBar = 16974020; // 0x10300c4
+    field public static final int Widget_Holo_Light_ProgressBar_Horizontal = 16974021; // 0x10300c5
+    field public static final int Widget_Holo_Light_ProgressBar_Inverse = 16974025; // 0x10300c9
+    field public static final int Widget_Holo_Light_ProgressBar_Large = 16974024; // 0x10300c8
+    field public static final int Widget_Holo_Light_ProgressBar_Large_Inverse = 16974027; // 0x10300cb
+    field public static final int Widget_Holo_Light_ProgressBar_Small = 16974022; // 0x10300c6
+    field public static final int Widget_Holo_Light_ProgressBar_Small_Inverse = 16974026; // 0x10300ca
+    field public static final int Widget_Holo_Light_ProgressBar_Small_Title = 16974023; // 0x10300c7
+    field public static final int Widget_Holo_Light_RatingBar = 16974029; // 0x10300cd
+    field public static final int Widget_Holo_Light_RatingBar_Indicator = 16974030; // 0x10300ce
+    field public static final int Widget_Holo_Light_RatingBar_Small = 16974031; // 0x10300cf
+    field public static final int Widget_Holo_Light_ScrollView = 16974033; // 0x10300d1
+    field public static final int Widget_Holo_Light_SeekBar = 16974028; // 0x10300cc
+    field public static final int Widget_Holo_Light_Spinner = 16974035; // 0x10300d3
+    field public static final int Widget_Holo_Light_Tab = 16974052; // 0x10300e4
+    field public static final int Widget_Holo_Light_TabWidget = 16974037; // 0x10300d5
+    field public static final int Widget_Holo_Light_TextView = 16974010; // 0x10300ba
+    field public static final int Widget_Holo_Light_TextView_SpinnerItem = 16974042; // 0x10300da
+    field public static final int Widget_Holo_Light_WebTextView = 16974038; // 0x10300d6
+    field public static final int Widget_Holo_Light_WebView = 16974039; // 0x10300d7
+    field public static final int Widget_Holo_ListPopupWindow = 16973997; // 0x10300ad
+    field public static final int Widget_Holo_ListView = 16973975; // 0x1030097
+    field public static final int Widget_Holo_ListView_DropDown = 16973970; // 0x1030092
+    field public static final int Widget_Holo_MediaRouteButton = 16974293; // 0x10301d5
+    field public static final int Widget_Holo_PopupMenu = 16973998; // 0x10300ae
+    field public static final int Widget_Holo_PopupWindow = 16973976; // 0x1030098
+    field public static final int Widget_Holo_ProgressBar = 16973977; // 0x1030099
+    field public static final int Widget_Holo_ProgressBar_Horizontal = 16973978; // 0x103009a
+    field public static final int Widget_Holo_ProgressBar_Large = 16973981; // 0x103009d
+    field public static final int Widget_Holo_ProgressBar_Small = 16973979; // 0x103009b
+    field public static final int Widget_Holo_ProgressBar_Small_Title = 16973980; // 0x103009c
+    field public static final int Widget_Holo_RatingBar = 16973983; // 0x103009f
+    field public static final int Widget_Holo_RatingBar_Indicator = 16973984; // 0x10300a0
+    field public static final int Widget_Holo_RatingBar_Small = 16973985; // 0x10300a1
+    field public static final int Widget_Holo_ScrollView = 16973987; // 0x10300a3
+    field public static final int Widget_Holo_SeekBar = 16973982; // 0x103009e
+    field public static final int Widget_Holo_Spinner = 16973989; // 0x10300a5
+    field public static final int Widget_Holo_Tab = 16974051; // 0x10300e3
+    field public static final int Widget_Holo_TabWidget = 16973991; // 0x10300a7
+    field public static final int Widget_Holo_TextView = 16973967; // 0x103008f
+    field public static final int Widget_Holo_TextView_SpinnerItem = 16973996; // 0x10300ac
+    field public static final int Widget_Holo_WebTextView = 16973992; // 0x10300a8
+    field public static final int Widget_Holo_WebView = 16973993; // 0x10300a9
+    field public static final int Widget_ImageButton = 16973862; // 0x1030026
+    field public static final int Widget_ImageWell = 16973861; // 0x1030025
+    field public static final int Widget_KeyboardView = 16973911; // 0x1030057
+    field public static final int Widget_ListPopupWindow = 16973957; // 0x1030085
+    field public static final int Widget_ListView = 16973870; // 0x103002e
+    field public static final int Widget_ListView_DropDown = 16973872; // 0x1030030
+    field public static final int Widget_ListView_Menu = 16973873; // 0x1030031
+    field public static final int Widget_ListView_White = 16973871; // 0x103002f
+    field public static final int Widget_PopupMenu = 16973958; // 0x1030086
+    field public static final int Widget_PopupWindow = 16973878; // 0x1030036
+    field public static final int Widget_ProgressBar = 16973852; // 0x103001c
+    field public static final int Widget_ProgressBar_Horizontal = 16973855; // 0x103001f
+    field public static final int Widget_ProgressBar_Inverse = 16973915; // 0x103005b
+    field public static final int Widget_ProgressBar_Large = 16973853; // 0x103001d
+    field public static final int Widget_ProgressBar_Large_Inverse = 16973916; // 0x103005c
+    field public static final int Widget_ProgressBar_Small = 16973854; // 0x103001e
+    field public static final int Widget_ProgressBar_Small_Inverse = 16973917; // 0x103005d
+    field public static final int Widget_RatingBar = 16973857; // 0x1030021
+    field public static final int Widget_ScrollView = 16973869; // 0x103002d
+    field public static final int Widget_SeekBar = 16973856; // 0x1030020
+    field public static final int Widget_Spinner = 16973864; // 0x1030028
+    field public static final int Widget_Spinner_DropDown = 16973955; // 0x1030083
+    field public static final int Widget_TabWidget = 16973876; // 0x1030034
+    field public static final int Widget_TextView = 16973858; // 0x1030022
+    field public static final int Widget_TextView_PopupMenu = 16973865; // 0x1030029
+    field public static final int Widget_TextView_SpinnerItem = 16973866; // 0x103002a
+    field public static final int Widget_WebView = 16973875; // 0x1030033
+  }
+
+  public static final class R.xml {
+    ctor public R.xml();
+  }
+
+}
+
+package android.accessibilityservice {
+
+  public abstract class AccessibilityService extends android.app.Service {
+    ctor public AccessibilityService();
+    method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
+    method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
+    method public abstract void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method protected boolean onGesture(int);
+    method public abstract void onInterrupt();
+    method protected void onServiceConnected();
+    method public final boolean performGlobalAction(int);
+    method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
+    field public static final int GESTURE_SWIPE_DOWN = 2; // 0x2
+    field public static final int GESTURE_SWIPE_DOWN_AND_LEFT = 15; // 0xf
+    field public static final int GESTURE_SWIPE_DOWN_AND_RIGHT = 16; // 0x10
+    field public static final int GESTURE_SWIPE_DOWN_AND_UP = 8; // 0x8
+    field public static final int GESTURE_SWIPE_LEFT = 3; // 0x3
+    field public static final int GESTURE_SWIPE_LEFT_AND_DOWN = 10; // 0xa
+    field public static final int GESTURE_SWIPE_LEFT_AND_RIGHT = 5; // 0x5
+    field public static final int GESTURE_SWIPE_LEFT_AND_UP = 9; // 0x9
+    field public static final int GESTURE_SWIPE_RIGHT = 4; // 0x4
+    field public static final int GESTURE_SWIPE_RIGHT_AND_DOWN = 12; // 0xc
+    field public static final int GESTURE_SWIPE_RIGHT_AND_LEFT = 6; // 0x6
+    field public static final int GESTURE_SWIPE_RIGHT_AND_UP = 11; // 0xb
+    field public static final int GESTURE_SWIPE_UP = 1; // 0x1
+    field public static final int GESTURE_SWIPE_UP_AND_DOWN = 7; // 0x7
+    field public static final int GESTURE_SWIPE_UP_AND_LEFT = 13; // 0xd
+    field public static final int GESTURE_SWIPE_UP_AND_RIGHT = 14; // 0xe
+    field public static final int GLOBAL_ACTION_BACK = 1; // 0x1
+    field public static final int GLOBAL_ACTION_HOME = 2; // 0x2
+    field public static final int GLOBAL_ACTION_NOTIFICATIONS = 4; // 0x4
+    field public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5; // 0x5
+    field public static final int GLOBAL_ACTION_RECENTS = 3; // 0x3
+    field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
+    field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
+  }
+
+  public class AccessibilityServiceInfo implements android.os.Parcelable {
+    ctor public AccessibilityServiceInfo();
+    method public int describeContents();
+    method public static java.lang.String feedbackTypeToString(int);
+    method public static java.lang.String flagToString(int);
+    method public boolean getCanRetrieveWindowContent();
+    method public deprecated java.lang.String getDescription();
+    method public java.lang.String getId();
+    method public android.content.pm.ResolveInfo getResolveInfo();
+    method public java.lang.String getSettingsActivityName();
+    method public java.lang.String loadDescription(android.content.pm.PackageManager);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int DEFAULT = 1; // 0x1
+    field public static final int FEEDBACK_ALL_MASK = -1; // 0xffffffff
+    field public static final int FEEDBACK_AUDIBLE = 4; // 0x4
+    field public static final int FEEDBACK_BRAILLE = 32; // 0x20
+    field public static final int FEEDBACK_GENERIC = 16; // 0x10
+    field public static final int FEEDBACK_HAPTIC = 2; // 0x2
+    field public static final int FEEDBACK_SPOKEN = 1; // 0x1
+    field public static final int FEEDBACK_VISUAL = 8; // 0x8
+    field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
+    field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
+    field public int eventTypes;
+    field public int feedbackType;
+    field public int flags;
+    field public long notificationTimeout;
+    field public java.lang.String[] packageNames;
+  }
+
+}
+
+package android.accounts {
+
+  public abstract class AbstractAccountAuthenticator {
+    ctor public AbstractAccountAuthenticator(android.content.Context);
+    method public abstract android.os.Bundle addAccount(android.accounts.AccountAuthenticatorResponse, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle) throws android.accounts.NetworkErrorException;
+    method public abstract android.os.Bundle confirmCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, android.os.Bundle) throws android.accounts.NetworkErrorException;
+    method public abstract android.os.Bundle editProperties(android.accounts.AccountAuthenticatorResponse, java.lang.String);
+    method public android.os.Bundle getAccountRemovalAllowed(android.accounts.AccountAuthenticatorResponse, android.accounts.Account) throws android.accounts.NetworkErrorException;
+    method public abstract android.os.Bundle getAuthToken(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
+    method public abstract java.lang.String getAuthTokenLabel(java.lang.String);
+    method public final android.os.IBinder getIBinder();
+    method public abstract android.os.Bundle hasFeatures(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String[]) throws android.accounts.NetworkErrorException;
+    method public abstract android.os.Bundle updateCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
+  }
+
+  public class Account implements android.os.Parcelable {
+    ctor public Account(java.lang.String, java.lang.String);
+    ctor public Account(android.os.Parcel);
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public final java.lang.String name;
+    field public final java.lang.String type;
+  }
+
+  public class AccountAuthenticatorActivity extends android.app.Activity {
+    ctor public AccountAuthenticatorActivity();
+    method public final void setAccountAuthenticatorResult(android.os.Bundle);
+  }
+
+  public class AccountAuthenticatorResponse implements android.os.Parcelable {
+    ctor public AccountAuthenticatorResponse(android.os.Parcel);
+    method public int describeContents();
+    method public void onError(int, java.lang.String);
+    method public void onRequestContinued();
+    method public void onResult(android.os.Bundle);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class AccountManager {
+    method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+    method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle);
+    method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean);
+    method public java.lang.String blockingGetAuthToken(android.accounts.Account, java.lang.String, boolean) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
+    method public void clearPassword(android.accounts.Account);
+    method public android.accounts.AccountManagerFuture<android.os.Bundle> confirmCredentials(android.accounts.Account, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+    method public android.accounts.AccountManagerFuture<android.os.Bundle> editProperties(java.lang.String, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+    method public static android.accounts.AccountManager get(android.content.Context);
+    method public android.accounts.Account[] getAccounts();
+    method public android.accounts.Account[] getAccountsByType(java.lang.String);
+    method public android.accounts.AccountManagerFuture<android.accounts.Account[]> getAccountsByTypeAndFeatures(java.lang.String, java.lang.String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler);
+    method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+    method public deprecated android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, java.lang.String, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+    method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, java.lang.String, android.os.Bundle, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+    method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthTokenByFeatures(java.lang.String, java.lang.String, java.lang.String[], android.app.Activity, android.os.Bundle, android.os.Bundle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+    method public android.accounts.AuthenticatorDescription[] getAuthenticatorTypes();
+    method public java.lang.String getPassword(android.accounts.Account);
+    method public java.lang.String getUserData(android.accounts.Account, java.lang.String);
+    method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
+    method public void invalidateAuthToken(java.lang.String, java.lang.String);
+    method public static android.content.Intent newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, java.lang.String[], boolean, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle);
+    method public java.lang.String peekAuthToken(android.accounts.Account, java.lang.String);
+    method public android.accounts.AccountManagerFuture<java.lang.Boolean> removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
+    method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener);
+    method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String);
+    method public void setPassword(android.accounts.Account, java.lang.String);
+    method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String);
+    method public android.accounts.AccountManagerFuture<android.os.Bundle> updateCredentials(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+    field public static final java.lang.String ACTION_AUTHENTICATOR_INTENT = "android.accounts.AccountAuthenticator";
+    field public static final java.lang.String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";
+    field public static final java.lang.String AUTHENTICATOR_META_DATA_NAME = "android.accounts.AccountAuthenticator";
+    field public static final int ERROR_CODE_BAD_ARGUMENTS = 7; // 0x7
+    field public static final int ERROR_CODE_BAD_REQUEST = 8; // 0x8
+    field public static final int ERROR_CODE_CANCELED = 4; // 0x4
+    field public static final int ERROR_CODE_INVALID_RESPONSE = 5; // 0x5
+    field public static final int ERROR_CODE_NETWORK_ERROR = 3; // 0x3
+    field public static final int ERROR_CODE_REMOTE_EXCEPTION = 1; // 0x1
+    field public static final int ERROR_CODE_UNSUPPORTED_OPERATION = 6; // 0x6
+    field public static final java.lang.String KEY_ACCOUNTS = "accounts";
+    field public static final java.lang.String KEY_ACCOUNT_AUTHENTICATOR_RESPONSE = "accountAuthenticatorResponse";
+    field public static final java.lang.String KEY_ACCOUNT_MANAGER_RESPONSE = "accountManagerResponse";
+    field public static final java.lang.String KEY_ACCOUNT_NAME = "authAccount";
+    field public static final java.lang.String KEY_ACCOUNT_TYPE = "accountType";
+    field public static final java.lang.String KEY_ANDROID_PACKAGE_NAME = "androidPackageName";
+    field public static final java.lang.String KEY_AUTHENTICATOR_TYPES = "authenticator_types";
+    field public static final java.lang.String KEY_AUTHTOKEN = "authtoken";
+    field public static final java.lang.String KEY_AUTH_FAILED_MESSAGE = "authFailedMessage";
+    field public static final java.lang.String KEY_AUTH_TOKEN_LABEL = "authTokenLabelKey";
+    field public static final java.lang.String KEY_BOOLEAN_RESULT = "booleanResult";
+    field public static final java.lang.String KEY_CALLER_PID = "callerPid";
+    field public static final java.lang.String KEY_CALLER_UID = "callerUid";
+    field public static final java.lang.String KEY_ERROR_CODE = "errorCode";
+    field public static final java.lang.String KEY_ERROR_MESSAGE = "errorMessage";
+    field public static final java.lang.String KEY_INTENT = "intent";
+    field public static final java.lang.String KEY_PASSWORD = "password";
+    field public static final java.lang.String KEY_USERDATA = "userdata";
+    field public static final java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
+  }
+
+  public abstract interface AccountManagerCallback {
+    method public abstract void run(android.accounts.AccountManagerFuture<V>);
+  }
+
+  public abstract interface AccountManagerFuture {
+    method public abstract boolean cancel(boolean);
+    method public abstract V getResult() throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
+    method public abstract V getResult(long, java.util.concurrent.TimeUnit) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
+    method public abstract boolean isCancelled();
+    method public abstract boolean isDone();
+  }
+
+  public class AccountsException extends java.lang.Exception {
+    ctor public AccountsException();
+    ctor public AccountsException(java.lang.String);
+    ctor public AccountsException(java.lang.String, java.lang.Throwable);
+    ctor public AccountsException(java.lang.Throwable);
+  }
+
+  public class AuthenticatorDescription implements android.os.Parcelable {
+    ctor public AuthenticatorDescription(java.lang.String, java.lang.String, int, int, int, int, boolean);
+    ctor public AuthenticatorDescription(java.lang.String, java.lang.String, int, int, int, int);
+    method public int describeContents();
+    method public static android.accounts.AuthenticatorDescription newKey(java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public final int accountPreferencesId;
+    field public final boolean customTokens;
+    field public final int iconId;
+    field public final int labelId;
+    field public final java.lang.String packageName;
+    field public final int smallIconId;
+    field public final java.lang.String type;
+  }
+
+  public class AuthenticatorException extends android.accounts.AccountsException {
+    ctor public AuthenticatorException();
+    ctor public AuthenticatorException(java.lang.String);
+    ctor public AuthenticatorException(java.lang.String, java.lang.Throwable);
+    ctor public AuthenticatorException(java.lang.Throwable);
+  }
+
+  public class NetworkErrorException extends android.accounts.AccountsException {
+    ctor public NetworkErrorException();
+    ctor public NetworkErrorException(java.lang.String);
+    ctor public NetworkErrorException(java.lang.String, java.lang.Throwable);
+    ctor public NetworkErrorException(java.lang.Throwable);
+  }
+
+  public abstract interface OnAccountsUpdateListener {
+    method public abstract void onAccountsUpdated(android.accounts.Account[]);
+  }
+
+  public class OperationCanceledException extends android.accounts.AccountsException {
+    ctor public OperationCanceledException();
+    ctor public OperationCanceledException(java.lang.String);
+    ctor public OperationCanceledException(java.lang.String, java.lang.Throwable);
+    ctor public OperationCanceledException(java.lang.Throwable);
+  }
+
+}
+
+package android.animation {
+
+  public abstract class Animator implements java.lang.Cloneable {
+    ctor public Animator();
+    method public void addListener(android.animation.Animator.AnimatorListener);
+    method public void cancel();
+    method public android.animation.Animator clone();
+    method public void end();
+    method public abstract long getDuration();
+    method public java.util.ArrayList<android.animation.Animator.AnimatorListener> getListeners();
+    method public abstract long getStartDelay();
+    method public abstract boolean isRunning();
+    method public boolean isStarted();
+    method public void removeAllListeners();
+    method public void removeListener(android.animation.Animator.AnimatorListener);
+    method public abstract android.animation.Animator setDuration(long);
+    method public abstract void setInterpolator(android.animation.TimeInterpolator);
+    method public abstract void setStartDelay(long);
+    method public void setTarget(java.lang.Object);
+    method public void setupEndValues();
+    method public void setupStartValues();
+    method public void start();
+  }
+
+  public static abstract interface Animator.AnimatorListener {
+    method public abstract void onAnimationCancel(android.animation.Animator);
+    method public abstract void onAnimationEnd(android.animation.Animator);
+    method public abstract void onAnimationRepeat(android.animation.Animator);
+    method public abstract void onAnimationStart(android.animation.Animator);
+  }
+
+  public class AnimatorInflater {
+    ctor public AnimatorInflater();
+    method public static android.animation.Animator loadAnimator(android.content.Context, int) throws android.content.res.Resources.NotFoundException;
+  }
+
+  public abstract class AnimatorListenerAdapter implements android.animation.Animator.AnimatorListener {
+    ctor public AnimatorListenerAdapter();
+    method public void onAnimationCancel(android.animation.Animator);
+    method public void onAnimationEnd(android.animation.Animator);
+    method public void onAnimationRepeat(android.animation.Animator);
+    method public void onAnimationStart(android.animation.Animator);
+  }
+
+  public final class AnimatorSet extends android.animation.Animator {
+    ctor public AnimatorSet();
+    method public java.util.ArrayList<android.animation.Animator> getChildAnimations();
+    method public long getDuration();
+    method public long getStartDelay();
+    method public boolean isRunning();
+    method public android.animation.AnimatorSet.Builder play(android.animation.Animator);
+    method public void playSequentially(android.animation.Animator...);
+    method public void playSequentially(java.util.List<android.animation.Animator>);
+    method public void playTogether(android.animation.Animator...);
+    method public void playTogether(java.util.Collection<android.animation.Animator>);
+    method public android.animation.AnimatorSet setDuration(long);
+    method public void setInterpolator(android.animation.TimeInterpolator);
+    method public void setStartDelay(long);
+  }
+
+  public class AnimatorSet.Builder {
+    method public android.animation.AnimatorSet.Builder after(android.animation.Animator);
+    method public android.animation.AnimatorSet.Builder after(long);
+    method public android.animation.AnimatorSet.Builder before(android.animation.Animator);
+    method public android.animation.AnimatorSet.Builder with(android.animation.Animator);
+  }
+
+  public class ArgbEvaluator implements android.animation.TypeEvaluator {
+    ctor public ArgbEvaluator();
+    method public java.lang.Object evaluate(float, java.lang.Object, java.lang.Object);
+  }
+
+  public class FloatEvaluator implements android.animation.TypeEvaluator {
+    ctor public FloatEvaluator();
+    method public java.lang.Float evaluate(float, java.lang.Number, java.lang.Number);
+  }
+
+  public class IntEvaluator implements android.animation.TypeEvaluator {
+    ctor public IntEvaluator();
+    method public java.lang.Integer evaluate(float, java.lang.Integer, java.lang.Integer);
+  }
+
+  public abstract class Keyframe implements java.lang.Cloneable {
+    ctor public Keyframe();
+    method public abstract android.animation.Keyframe clone();
+    method public float getFraction();
+    method public android.animation.TimeInterpolator getInterpolator();
+    method public java.lang.Class getType();
+    method public abstract java.lang.Object getValue();
+    method public boolean hasValue();
+    method public static android.animation.Keyframe ofFloat(float, float);
+    method public static android.animation.Keyframe ofFloat(float);
+    method public static android.animation.Keyframe ofInt(float, int);
+    method public static android.animation.Keyframe ofInt(float);
+    method public static android.animation.Keyframe ofObject(float, java.lang.Object);
+    method public static android.animation.Keyframe ofObject(float);
+    method public void setFraction(float);
+    method public void setInterpolator(android.animation.TimeInterpolator);
+    method public abstract void setValue(java.lang.Object);
+  }
+
+  public class LayoutTransition {
+    ctor public LayoutTransition();
+    method public void addChild(android.view.ViewGroup, android.view.View);
+    method public void addTransitionListener(android.animation.LayoutTransition.TransitionListener);
+    method public void disableTransitionType(int);
+    method public void enableTransitionType(int);
+    method public android.animation.Animator getAnimator(int);
+    method public long getDuration(int);
+    method public android.animation.TimeInterpolator getInterpolator(int);
+    method public long getStagger(int);
+    method public long getStartDelay(int);
+    method public java.util.List<android.animation.LayoutTransition.TransitionListener> getTransitionListeners();
+    method public deprecated void hideChild(android.view.ViewGroup, android.view.View);
+    method public void hideChild(android.view.ViewGroup, android.view.View, int);
+    method public boolean isChangingLayout();
+    method public boolean isRunning();
+    method public boolean isTransitionTypeEnabled(int);
+    method public void removeChild(android.view.ViewGroup, android.view.View);
+    method public void removeTransitionListener(android.animation.LayoutTransition.TransitionListener);
+    method public void setAnimateParentHierarchy(boolean);
+    method public void setAnimator(int, android.animation.Animator);
+    method public void setDuration(long);
+    method public void setDuration(int, long);
+    method public void setInterpolator(int, android.animation.TimeInterpolator);
+    method public void setStagger(int, long);
+    method public void setStartDelay(int, long);
+    method public deprecated void showChild(android.view.ViewGroup, android.view.View);
+    method public void showChild(android.view.ViewGroup, android.view.View, int);
+    field public static final int APPEARING = 2; // 0x2
+    field public static final int CHANGE_APPEARING = 0; // 0x0
+    field public static final int CHANGE_DISAPPEARING = 1; // 0x1
+    field public static final int CHANGING = 4; // 0x4
+    field public static final int DISAPPEARING = 3; // 0x3
+  }
+
+  public static abstract interface LayoutTransition.TransitionListener {
+    method public abstract void endTransition(android.animation.LayoutTransition, android.view.ViewGroup, android.view.View, int);
+    method public abstract void startTransition(android.animation.LayoutTransition, android.view.ViewGroup, android.view.View, int);
+  }
+
+  public final class ObjectAnimator extends android.animation.ValueAnimator {
+    ctor public ObjectAnimator();
+    method public java.lang.String getPropertyName();
+    method public java.lang.Object getTarget();
+    method public static android.animation.ObjectAnimator ofFloat(java.lang.Object, java.lang.String, float...);
+    method public static android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, float...);
+    method public static android.animation.ObjectAnimator ofInt(java.lang.Object, java.lang.String, int...);
+    method public static android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, int...);
+    method public static android.animation.ObjectAnimator ofObject(java.lang.Object, java.lang.String, android.animation.TypeEvaluator, java.lang.Object...);
+    method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeEvaluator<V>, V...);
+    method public static android.animation.ObjectAnimator ofPropertyValuesHolder(java.lang.Object, android.animation.PropertyValuesHolder...);
+    method public void setProperty(android.util.Property);
+    method public void setPropertyName(java.lang.String);
+  }
+
+  public class PropertyValuesHolder implements java.lang.Cloneable {
+    method public android.animation.PropertyValuesHolder clone();
+    method public java.lang.String getPropertyName();
+    method public static android.animation.PropertyValuesHolder ofFloat(java.lang.String, float...);
+    method public static android.animation.PropertyValuesHolder ofFloat(android.util.Property<?, java.lang.Float>, float...);
+    method public static android.animation.PropertyValuesHolder ofInt(java.lang.String, int...);
+    method public static android.animation.PropertyValuesHolder ofInt(android.util.Property<?, java.lang.Integer>, int...);
+    method public static android.animation.PropertyValuesHolder ofKeyframe(java.lang.String, android.animation.Keyframe...);
+    method public static android.animation.PropertyValuesHolder ofKeyframe(android.util.Property, android.animation.Keyframe...);
+    method public static android.animation.PropertyValuesHolder ofObject(java.lang.String, android.animation.TypeEvaluator, java.lang.Object...);
+    method public static android.animation.PropertyValuesHolder ofObject(android.util.Property, android.animation.TypeEvaluator<V>, V...);
+    method public void setEvaluator(android.animation.TypeEvaluator);
+    method public void setFloatValues(float...);
+    method public void setIntValues(int...);
+    method public void setKeyframes(android.animation.Keyframe...);
+    method public void setObjectValues(java.lang.Object...);
+    method public void setProperty(android.util.Property);
+    method public void setPropertyName(java.lang.String);
+  }
+
+  public class TimeAnimator extends android.animation.ValueAnimator {
+    ctor public TimeAnimator();
+    method public void setTimeListener(android.animation.TimeAnimator.TimeListener);
+  }
+
+  public static abstract interface TimeAnimator.TimeListener {
+    method public abstract void onTimeUpdate(android.animation.TimeAnimator, long, long);
+  }
+
+  public abstract interface TimeInterpolator {
+    method public abstract float getInterpolation(float);
+  }
+
+  public abstract interface TypeEvaluator {
+    method public abstract T evaluate(float, T, T);
+  }
+
+  public class ValueAnimator extends android.animation.Animator {
+    ctor public ValueAnimator();
+    method public void addUpdateListener(android.animation.ValueAnimator.AnimatorUpdateListener);
+    method public float getAnimatedFraction();
+    method public java.lang.Object getAnimatedValue();
+    method public java.lang.Object getAnimatedValue(java.lang.String);
+    method public long getCurrentPlayTime();
+    method public long getDuration();
+    method public static long getFrameDelay();
+    method public android.animation.TimeInterpolator getInterpolator();
+    method public int getRepeatCount();
+    method public int getRepeatMode();
+    method public long getStartDelay();
+    method public android.animation.PropertyValuesHolder[] getValues();
+    method public boolean isRunning();
+    method public static android.animation.ValueAnimator ofFloat(float...);
+    method public static android.animation.ValueAnimator ofInt(int...);
+    method public static android.animation.ValueAnimator ofObject(android.animation.TypeEvaluator, java.lang.Object...);
+    method public static android.animation.ValueAnimator ofPropertyValuesHolder(android.animation.PropertyValuesHolder...);
+    method public void removeAllUpdateListeners();
+    method public void removeUpdateListener(android.animation.ValueAnimator.AnimatorUpdateListener);
+    method public void reverse();
+    method public void setCurrentPlayTime(long);
+    method public android.animation.ValueAnimator setDuration(long);
+    method public void setEvaluator(android.animation.TypeEvaluator);
+    method public void setFloatValues(float...);
+    method public static void setFrameDelay(long);
+    method public void setIntValues(int...);
+    method public void setInterpolator(android.animation.TimeInterpolator);
+    method public void setObjectValues(java.lang.Object...);
+    method public void setRepeatCount(int);
+    method public void setRepeatMode(int);
+    method public void setStartDelay(long);
+    method public void setValues(android.animation.PropertyValuesHolder...);
+    field public static final int INFINITE = -1; // 0xffffffff
+    field public static final int RESTART = 1; // 0x1
+    field public static final int REVERSE = 2; // 0x2
+  }
+
+  public static abstract interface ValueAnimator.AnimatorUpdateListener {
+    method public abstract void onAnimationUpdate(android.animation.ValueAnimator);
+  }
+
+}
+
+package android.annotation {
+
+  public abstract class SuppressLint implements java.lang.annotation.Annotation {
+  }
+
+  public abstract class TargetApi implements java.lang.annotation.Annotation {
+  }
+
+}
+
+package android.app {
+
+  public abstract class ActionBar {
+    ctor public ActionBar();
+    method public abstract void addOnMenuVisibilityListener(android.app.ActionBar.OnMenuVisibilityListener);
+    method public abstract void addTab(android.app.ActionBar.Tab);
+    method public abstract void addTab(android.app.ActionBar.Tab, boolean);
+    method public abstract void addTab(android.app.ActionBar.Tab, int);
+    method public abstract void addTab(android.app.ActionBar.Tab, int, boolean);
+    method public abstract android.view.View getCustomView();
+    method public abstract int getDisplayOptions();
+    method public abstract int getHeight();
+    method public abstract int getNavigationItemCount();
+    method public abstract int getNavigationMode();
+    method public abstract int getSelectedNavigationIndex();
+    method public abstract android.app.ActionBar.Tab getSelectedTab();
+    method public abstract java.lang.CharSequence getSubtitle();
+    method public abstract android.app.ActionBar.Tab getTabAt(int);
+    method public abstract int getTabCount();
+    method public android.content.Context getThemedContext();
+    method public abstract java.lang.CharSequence getTitle();
+    method public abstract void hide();
+    method public abstract boolean isShowing();
+    method public abstract android.app.ActionBar.Tab newTab();
+    method public abstract void removeAllTabs();
+    method public abstract void removeOnMenuVisibilityListener(android.app.ActionBar.OnMenuVisibilityListener);
+    method public abstract void removeTab(android.app.ActionBar.Tab);
+    method public abstract void removeTabAt(int);
+    method public abstract void selectTab(android.app.ActionBar.Tab);
+    method public abstract void setBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public abstract void setCustomView(android.view.View);
+    method public abstract void setCustomView(android.view.View, android.app.ActionBar.LayoutParams);
+    method public abstract void setCustomView(int);
+    method public abstract void setDisplayHomeAsUpEnabled(boolean);
+    method public abstract void setDisplayOptions(int);
+    method public abstract void setDisplayOptions(int, int);
+    method public abstract void setDisplayShowCustomEnabled(boolean);
+    method public abstract void setDisplayShowHomeEnabled(boolean);
+    method public abstract void setDisplayShowTitleEnabled(boolean);
+    method public abstract void setDisplayUseLogoEnabled(boolean);
+    method public void setHomeButtonEnabled(boolean);
+    method public abstract void setIcon(int);
+    method public abstract void setIcon(android.graphics.drawable.Drawable);
+    method public abstract void setListNavigationCallbacks(android.widget.SpinnerAdapter, android.app.ActionBar.OnNavigationListener);
+    method public abstract void setLogo(int);
+    method public abstract void setLogo(android.graphics.drawable.Drawable);
+    method public abstract void setNavigationMode(int);
+    method public abstract void setSelectedNavigationItem(int);
+    method public void setSplitBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public void setStackedBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public abstract void setSubtitle(java.lang.CharSequence);
+    method public abstract void setSubtitle(int);
+    method public abstract void setTitle(java.lang.CharSequence);
+    method public abstract void setTitle(int);
+    method public abstract void show();
+    field public static final int DISPLAY_HOME_AS_UP = 4; // 0x4
+    field public static final int DISPLAY_SHOW_CUSTOM = 16; // 0x10
+    field public static final int DISPLAY_SHOW_HOME = 2; // 0x2
+    field public static final int DISPLAY_SHOW_TITLE = 8; // 0x8
+    field public static final int DISPLAY_USE_LOGO = 1; // 0x1
+    field public static final int NAVIGATION_MODE_LIST = 1; // 0x1
+    field public static final int NAVIGATION_MODE_STANDARD = 0; // 0x0
+    field public static final int NAVIGATION_MODE_TABS = 2; // 0x2
+  }
+
+  public static class ActionBar.LayoutParams extends android.view.ViewGroup.MarginLayoutParams {
+    ctor public ActionBar.LayoutParams(android.content.Context, android.util.AttributeSet);
+    ctor public ActionBar.LayoutParams(int, int);
+    ctor public ActionBar.LayoutParams(int, int, int);
+    ctor public ActionBar.LayoutParams(int);
+    ctor public ActionBar.LayoutParams(android.app.ActionBar.LayoutParams);
+    ctor public ActionBar.LayoutParams(android.view.ViewGroup.LayoutParams);
+    field public int gravity;
+  }
+
+  public static abstract interface ActionBar.OnMenuVisibilityListener {
+    method public abstract void onMenuVisibilityChanged(boolean);
+  }
+
+  public static abstract interface ActionBar.OnNavigationListener {
+    method public abstract boolean onNavigationItemSelected(int, long);
+  }
+
+  public static abstract class ActionBar.Tab {
+    ctor public ActionBar.Tab();
+    method public abstract java.lang.CharSequence getContentDescription();
+    method public abstract android.view.View getCustomView();
+    method public abstract android.graphics.drawable.Drawable getIcon();
+    method public abstract int getPosition();
+    method public abstract java.lang.Object getTag();
+    method public abstract java.lang.CharSequence getText();
+    method public abstract void select();
+    method public abstract android.app.ActionBar.Tab setContentDescription(int);
+    method public abstract android.app.ActionBar.Tab setContentDescription(java.lang.CharSequence);
+    method public abstract android.app.ActionBar.Tab setCustomView(android.view.View);
+    method public abstract android.app.ActionBar.Tab setCustomView(int);
+    method public abstract android.app.ActionBar.Tab setIcon(android.graphics.drawable.Drawable);
+    method public abstract android.app.ActionBar.Tab setIcon(int);
+    method public abstract android.app.ActionBar.Tab setTabListener(android.app.ActionBar.TabListener);
+    method public abstract android.app.ActionBar.Tab setTag(java.lang.Object);
+    method public abstract android.app.ActionBar.Tab setText(java.lang.CharSequence);
+    method public abstract android.app.ActionBar.Tab setText(int);
+    field public static final int INVALID_POSITION = -1; // 0xffffffff
+  }
+
+  public static abstract interface ActionBar.TabListener {
+    method public abstract void onTabReselected(android.app.ActionBar.Tab, android.app.FragmentTransaction);
+    method public abstract void onTabSelected(android.app.ActionBar.Tab, android.app.FragmentTransaction);
+    method public abstract void onTabUnselected(android.app.ActionBar.Tab, android.app.FragmentTransaction);
+  }
+
+  public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
+    ctor public Activity();
+    method public void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
+    method public void closeContextMenu();
+    method public void closeOptionsMenu();
+    method public android.app.PendingIntent createPendingResult(int, android.content.Intent, int);
+    method public final deprecated void dismissDialog(int);
+    method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
+    method public boolean dispatchKeyEvent(android.view.KeyEvent);
+    method public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
+    method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+    method public boolean dispatchTouchEvent(android.view.MotionEvent);
+    method public boolean dispatchTrackballEvent(android.view.MotionEvent);
+    method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public android.view.View findViewById(int);
+    method public void finish();
+    method public void finishActivity(int);
+    method public void finishActivityFromChild(android.app.Activity, int);
+    method public void finishAffinity();
+    method public void finishFromChild(android.app.Activity);
+    method public android.app.ActionBar getActionBar();
+    method public final android.app.Application getApplication();
+    method public android.content.ComponentName getCallingActivity();
+    method public java.lang.String getCallingPackage();
+    method public int getChangingConfigurations();
+    method public android.content.ComponentName getComponentName();
+    method public android.view.View getCurrentFocus();
+    method public android.app.FragmentManager getFragmentManager();
+    method public android.content.Intent getIntent();
+    method public deprecated java.lang.Object getLastNonConfigurationInstance();
+    method public android.view.LayoutInflater getLayoutInflater();
+    method public android.app.LoaderManager getLoaderManager();
+    method public java.lang.String getLocalClassName();
+    method public android.view.MenuInflater getMenuInflater();
+    method public final android.app.Activity getParent();
+    method public android.content.Intent getParentActivityIntent();
+    method public android.content.SharedPreferences getPreferences(int);
+    method public int getRequestedOrientation();
+    method public int getTaskId();
+    method public final java.lang.CharSequence getTitle();
+    method public final int getTitleColor();
+    method public final int getVolumeControlStream();
+    method public android.view.Window getWindow();
+    method public android.view.WindowManager getWindowManager();
+    method public boolean hasWindowFocus();
+    method public void invalidateOptionsMenu();
+    method public boolean isChangingConfigurations();
+    method public final boolean isChild();
+    method public boolean isDestroyed();
+    method public boolean isFinishing();
+    method public boolean isTaskRoot();
+    method public final deprecated android.database.Cursor managedQuery(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
+    method public boolean moveTaskToBack(boolean);
+    method public boolean navigateUpTo(android.content.Intent);
+    method public boolean navigateUpToFromChild(android.app.Activity, android.content.Intent);
+    method public void onActionModeFinished(android.view.ActionMode);
+    method public void onActionModeStarted(android.view.ActionMode);
+    method protected void onActivityResult(int, int, android.content.Intent);
+    method public void onAttachFragment(android.app.Fragment);
+    method public void onAttachedToWindow();
+    method public void onBackPressed();
+    method protected void onChildTitleChanged(android.app.Activity, java.lang.CharSequence);
+    method public void onConfigurationChanged(android.content.res.Configuration);
+    method public void onContentChanged();
+    method public boolean onContextItemSelected(android.view.MenuItem);
+    method public void onContextMenuClosed(android.view.Menu);
+    method protected void onCreate(android.os.Bundle);
+    method public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo);
+    method public java.lang.CharSequence onCreateDescription();
+    method protected deprecated android.app.Dialog onCreateDialog(int);
+    method protected deprecated android.app.Dialog onCreateDialog(int, android.os.Bundle);
+    method public void onCreateNavigateUpTaskStack(android.app.TaskStackBuilder);
+    method public boolean onCreateOptionsMenu(android.view.Menu);
+    method public boolean onCreatePanelMenu(int, android.view.Menu);
+    method public android.view.View onCreatePanelView(int);
+    method public boolean onCreateThumbnail(android.graphics.Bitmap, android.graphics.Canvas);
+    method public android.view.View onCreateView(java.lang.String, android.content.Context, android.util.AttributeSet);
+    method public android.view.View onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet);
+    method protected void onDestroy();
+    method public void onDetachedFromWindow();
+    method public boolean onGenericMotionEvent(android.view.MotionEvent);
+    method public boolean onKeyDown(int, android.view.KeyEvent);
+    method public boolean onKeyLongPress(int, android.view.KeyEvent);
+    method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
+    method public boolean onKeyShortcut(int, android.view.KeyEvent);
+    method public boolean onKeyUp(int, android.view.KeyEvent);
+    method public void onLowMemory();
+    method public boolean onMenuItemSelected(int, android.view.MenuItem);
+    method public boolean onMenuOpened(int, android.view.Menu);
+    method public boolean onNavigateUp();
+    method public boolean onNavigateUpFromChild(android.app.Activity);
+    method protected void onNewIntent(android.content.Intent);
+    method public boolean onOptionsItemSelected(android.view.MenuItem);
+    method public void onOptionsMenuClosed(android.view.Menu);
+    method public void onPanelClosed(int, android.view.Menu);
+    method protected void onPause();
+    method protected void onPostCreate(android.os.Bundle);
+    method protected void onPostResume();
+    method protected deprecated void onPrepareDialog(int, android.app.Dialog);
+    method protected deprecated void onPrepareDialog(int, android.app.Dialog, android.os.Bundle);
+    method public void onPrepareNavigateUpTaskStack(android.app.TaskStackBuilder);
+    method public boolean onPrepareOptionsMenu(android.view.Menu);
+    method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+    method protected void onRestart();
+    method protected void onRestoreInstanceState(android.os.Bundle);
+    method protected void onResume();
+    method public deprecated java.lang.Object onRetainNonConfigurationInstance();
+    method protected void onSaveInstanceState(android.os.Bundle);
+    method public boolean onSearchRequested();
+    method protected void onStart();
+    method protected void onStop();
+    method protected void onTitleChanged(java.lang.CharSequence, int);
+    method public boolean onTouchEvent(android.view.MotionEvent);
+    method public boolean onTrackballEvent(android.view.MotionEvent);
+    method public void onTrimMemory(int);
+    method public void onUserInteraction();
+    method protected void onUserLeaveHint();
+    method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
+    method public void onWindowFocusChanged(boolean);
+    method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
+    method public void openContextMenu(android.view.View);
+    method public void openOptionsMenu();
+    method public void overridePendingTransition(int, int);
+    method public void recreate();
+    method public void registerForContextMenu(android.view.View);
+    method public final deprecated void removeDialog(int);
+    method public final boolean requestWindowFeature(int);
+    method public final void runOnUiThread(java.lang.Runnable);
+    method public void setContentView(int);
+    method public void setContentView(android.view.View);
+    method public void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
+    method public final void setDefaultKeyMode(int);
+    method public final void setFeatureDrawable(int, android.graphics.drawable.Drawable);
+    method public final void setFeatureDrawableAlpha(int, int);
+    method public final void setFeatureDrawableResource(int, int);
+    method public final void setFeatureDrawableUri(int, android.net.Uri);
+    method public void setFinishOnTouchOutside(boolean);
+    method public void setIntent(android.content.Intent);
+    method public final void setProgress(int);
+    method public final void setProgressBarIndeterminate(boolean);
+    method public final void setProgressBarIndeterminateVisibility(boolean);
+    method public final void setProgressBarVisibility(boolean);
+    method public void setRequestedOrientation(int);
+    method public final void setResult(int);
+    method public final void setResult(int, android.content.Intent);
+    method public final void setSecondaryProgress(int);
+    method public void setTitle(java.lang.CharSequence);
+    method public void setTitle(int);
+    method public void setTitleColor(int);
+    method public void setVisible(boolean);
+    method public final void setVolumeControlStream(int);
+    method public boolean shouldUpRecreateTask(android.content.Intent);
+    method public final deprecated void showDialog(int);
+    method public final deprecated boolean showDialog(int, android.os.Bundle);
+    method public android.view.ActionMode startActionMode(android.view.ActionMode.Callback);
+    method public void startActivityForResult(android.content.Intent, int);
+    method public void startActivityForResult(android.content.Intent, int, android.os.Bundle);
+    method public void startActivityFromChild(android.app.Activity, android.content.Intent, int);
+    method public void startActivityFromChild(android.app.Activity, android.content.Intent, int, android.os.Bundle);
+    method public void startActivityFromFragment(android.app.Fragment, android.content.Intent, int);
+    method public void startActivityFromFragment(android.app.Fragment, android.content.Intent, int, android.os.Bundle);
+    method public boolean startActivityIfNeeded(android.content.Intent, int);
+    method public boolean startActivityIfNeeded(android.content.Intent, int, android.os.Bundle);
+    method public void startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
+    method public void startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
+    method public void startIntentSenderFromChild(android.app.Activity, android.content.IntentSender, int, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
+    method public void startIntentSenderFromChild(android.app.Activity, android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
+    method public deprecated void startManagingCursor(android.database.Cursor);
+    method public boolean startNextMatchingActivity(android.content.Intent);
+    method public boolean startNextMatchingActivity(android.content.Intent, android.os.Bundle);
+    method public void startSearch(java.lang.String, boolean, android.os.Bundle, boolean);
+    method public deprecated void stopManagingCursor(android.database.Cursor);
+    method public void takeKeyEvents(boolean);
+    method public void triggerSearch(java.lang.String, android.os.Bundle);
+    method public void unregisterForContextMenu(android.view.View);
+    field public static final int DEFAULT_KEYS_DIALER = 1; // 0x1
+    field public static final int DEFAULT_KEYS_DISABLE = 0; // 0x0
+    field public static final int DEFAULT_KEYS_SEARCH_GLOBAL = 4; // 0x4
+    field public static final int DEFAULT_KEYS_SEARCH_LOCAL = 3; // 0x3
+    field public static final int DEFAULT_KEYS_SHORTCUT = 2; // 0x2
+    field protected static final int[] FOCUSED_STATE_SET;
+    field public static final int RESULT_CANCELED = 0; // 0x0
+    field public static final int RESULT_FIRST_USER = 1; // 0x1
+    field public static final int RESULT_OK = -1; // 0xffffffff
+  }
+
+  public deprecated class ActivityGroup extends android.app.Activity {
+    ctor public ActivityGroup();
+    ctor public ActivityGroup(boolean);
+    method public android.app.Activity getCurrentActivity();
+    method public final android.app.LocalActivityManager getLocalActivityManager();
+  }
+
+  public class ActivityManager {
+    method public android.content.pm.ConfigurationInfo getDeviceConfigurationInfo();
+    method public int getLargeMemoryClass();
+    method public int getLauncherLargeIconDensity();
+    method public int getLauncherLargeIconSize();
+    method public int getMemoryClass();
+    method public void getMemoryInfo(android.app.ActivityManager.MemoryInfo);
+    method public static void getMyMemoryState(android.app.ActivityManager.RunningAppProcessInfo);
+    method public android.os.Debug.MemoryInfo[] getProcessMemoryInfo(int[]);
+    method public java.util.List<android.app.ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState();
+    method public java.util.List<android.app.ActivityManager.RecentTaskInfo> getRecentTasks(int, int) throws java.lang.SecurityException;
+    method public java.util.List<android.app.ActivityManager.RunningAppProcessInfo> getRunningAppProcesses();
+    method public android.app.PendingIntent getRunningServiceControlPanel(android.content.ComponentName) throws java.lang.SecurityException;
+    method public java.util.List<android.app.ActivityManager.RunningServiceInfo> getRunningServices(int) throws java.lang.SecurityException;
+    method public java.util.List<android.app.ActivityManager.RunningTaskInfo> getRunningTasks(int) throws java.lang.SecurityException;
+    method public static boolean isRunningInTestHarness();
+    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
+    field public static final int RECENT_IGNORE_UNAVAILABLE = 2; // 0x2
+    field public static final int RECENT_WITH_EXCLUDED = 1; // 0x1
+  }
+
+  public static class ActivityManager.MemoryInfo implements android.os.Parcelable {
+    ctor public ActivityManager.MemoryInfo();
+    method public int describeContents();
+    method public void readFromParcel(android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public long availMem;
+    field public boolean lowMemory;
+    field public long threshold;
+    field public long totalMem;
+  }
+
+  public static class ActivityManager.ProcessErrorStateInfo implements android.os.Parcelable {
+    ctor public ActivityManager.ProcessErrorStateInfo();
+    method public int describeContents();
+    method public void readFromParcel(android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CRASHED = 1; // 0x1
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int NOT_RESPONDING = 2; // 0x2
+    field public static final int NO_ERROR = 0; // 0x0
+    field public int condition;
+    field public byte[] crashData;
+    field public java.lang.String longMsg;
+    field public int pid;
+    field public java.lang.String processName;
+    field public java.lang.String shortMsg;
+    field public java.lang.String stackTrace;
+    field public java.lang.String tag;
+    field public int uid;
+  }
+
+  public static class ActivityManager.RecentTaskInfo implements android.os.Parcelable {
+    ctor public ActivityManager.RecentTaskInfo();
+    method public int describeContents();
+    method public void readFromParcel(android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public android.content.Intent baseIntent;
+    field public java.lang.CharSequence description;
+    field public int id;
+    field public android.content.ComponentName origActivity;
+    field public int persistentId;
+  }
+
+  public static class ActivityManager.RunningAppProcessInfo implements android.os.Parcelable {
+    ctor public ActivityManager.RunningAppProcessInfo();
+    ctor public ActivityManager.RunningAppProcessInfo(java.lang.String, int, java.lang.String[]);
+    method public int describeContents();
+    method public void readFromParcel(android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int IMPORTANCE_BACKGROUND = 400; // 0x190
+    field public static final int IMPORTANCE_EMPTY = 500; // 0x1f4
+    field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64
+    field public static final int IMPORTANCE_PERCEPTIBLE = 130; // 0x82
+    field public static final int IMPORTANCE_SERVICE = 300; // 0x12c
+    field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8
+    field public static final int REASON_PROVIDER_IN_USE = 1; // 0x1
+    field public static final int REASON_SERVICE_IN_USE = 2; // 0x2
+    field public static final int REASON_UNKNOWN = 0; // 0x0
+    field public int importance;
+    field public int importanceReasonCode;
+    field public android.content.ComponentName importanceReasonComponent;
+    field public int importanceReasonPid;
+    field public int lastTrimLevel;
+    field public int lru;
+    field public int pid;
+    field public java.lang.String[] pkgList;
+    field public java.lang.String processName;
+    field public int uid;
+  }
+
+  public static class ActivityManager.RunningServiceInfo implements android.os.Parcelable {
+    ctor public ActivityManager.RunningServiceInfo();
+    method public int describeContents();
+    method public void readFromParcel(android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_FOREGROUND = 2; // 0x2
+    field public static final int FLAG_PERSISTENT_PROCESS = 8; // 0x8
+    field public static final int FLAG_STARTED = 1; // 0x1
+    field public static final int FLAG_SYSTEM_PROCESS = 4; // 0x4
+    field public long activeSince;
+    field public int clientCount;
+    field public int clientLabel;
+    field public java.lang.String clientPackage;
+    field public int crashCount;
+    field public int flags;
+    field public boolean foreground;
+    field public long lastActivityTime;
+    field public int pid;
+    field public java.lang.String process;
+    field public long restarting;
+    field public android.content.ComponentName service;
+    field public boolean started;
+    field public int uid;
+  }
+
+  public static class ActivityManager.RunningTaskInfo implements android.os.Parcelable {
+    ctor public ActivityManager.RunningTaskInfo();
+    method public int describeContents();
+    method public void readFromParcel(android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public android.content.ComponentName baseActivity;
+    field public java.lang.CharSequence description;
+    field public int id;
+    field public int numActivities;
+    field public int numRunning;
+    field public android.graphics.Bitmap thumbnail;
+    field public android.content.ComponentName topActivity;
+  }
+
+  public class ActivityOptions {
+    method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
+    method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
+    method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
+    method public android.os.Bundle toBundle();
+    method public void update(android.app.ActivityOptions);
+  }
+
+  public class AlarmManager {
+    method public void cancel(android.app.PendingIntent);
+    method public void set(int, long, android.app.PendingIntent);
+    method public void setInexactRepeating(int, long, long, android.app.PendingIntent);
+    method public void setRepeating(int, long, long, android.app.PendingIntent);
+    method public void setTime(long);
+    method public void setTimeZone(java.lang.String);
+    field public static final int ELAPSED_REALTIME = 3; // 0x3
+    field public static final int ELAPSED_REALTIME_WAKEUP = 2; // 0x2
+    field public static final long INTERVAL_DAY = 86400000L; // 0x5265c00L
+    field public static final long INTERVAL_FIFTEEN_MINUTES = 900000L; // 0xdbba0L
+    field public static final long INTERVAL_HALF_DAY = 43200000L; // 0x2932e00L
+    field public static final long INTERVAL_HALF_HOUR = 1800000L; // 0x1b7740L
+    field public static final long INTERVAL_HOUR = 3600000L; // 0x36ee80L
+    field public static final int RTC = 1; // 0x1
+    field public static final int RTC_WAKEUP = 0; // 0x0
+  }
+
+  public class AlertDialog extends android.app.Dialog implements android.content.DialogInterface {
+    ctor protected AlertDialog(android.content.Context);
+    ctor protected AlertDialog(android.content.Context, int);
+    ctor protected AlertDialog(android.content.Context, boolean, android.content.DialogInterface.OnCancelListener);
+    method public android.widget.Button getButton(int);
+    method public android.widget.ListView getListView();
+    method public void setButton(int, java.lang.CharSequence, android.os.Message);
+    method public void setButton(int, java.lang.CharSequence, android.content.DialogInterface.OnClickListener);
+    method public deprecated void setButton(java.lang.CharSequence, android.os.Message);
+    method public deprecated void setButton(java.lang.CharSequence, android.content.DialogInterface.OnClickListener);
+    method public deprecated void setButton2(java.lang.CharSequence, android.os.Message);
+    method public deprecated void setButton2(java.lang.CharSequence, android.content.DialogInterface.OnClickListener);
+    method public deprecated void setButton3(java.lang.CharSequence, android.os.Message);
+    method public deprecated void setButton3(java.lang.CharSequence, android.content.DialogInterface.OnClickListener);
+    method public void setCustomTitle(android.view.View);
+    method public void setIcon(int);
+    method public void setIcon(android.graphics.drawable.Drawable);
+    method public void setIconAttribute(int);
+    method public void setInverseBackgroundForced(boolean);
+    method public void setMessage(java.lang.CharSequence);
+    method public void setView(android.view.View);
+    method public void setView(android.view.View, int, int, int, int);
+    field public static final int THEME_DEVICE_DEFAULT_DARK = 4; // 0x4
+    field public static final int THEME_DEVICE_DEFAULT_LIGHT = 5; // 0x5
+    field public static final int THEME_HOLO_DARK = 2; // 0x2
+    field public static final int THEME_HOLO_LIGHT = 3; // 0x3
+    field public static final int THEME_TRADITIONAL = 1; // 0x1
+  }
+
+  public static class AlertDialog.Builder {
+    ctor public AlertDialog.Builder(android.content.Context);
+    ctor public AlertDialog.Builder(android.content.Context, int);
+    method public android.app.AlertDialog create();
+    method public android.content.Context getContext();
+    method public android.app.AlertDialog.Builder setAdapter(android.widget.ListAdapter, android.content.DialogInterface.OnClickListener);
+    method public android.app.AlertDialog.Builder setCancelable(boolean);
+    method public android.app.AlertDialog.Builder setCursor(android.database.Cursor, android.content.DialogInterface.OnClickListener, java.lang.String);
+    method public android.app.AlertDialog.Builder setCustomTitle(android.view.View);
+    method public android.app.AlertDialog.Builder setIcon(int);
+    method public android.app.AlertDialog.Builder setIcon(android.graphics.drawable.Drawable);
+    method public android.app.AlertDialog.Builder setIconAttribute(int);
+    method public android.app.AlertDialog.Builder setInverseBackgroundForced(boolean);
+    method public android.app.AlertDialog.Builder setItems(int, android.content.DialogInterface.OnClickListener);
+    method public android.app.AlertDialog.Builder setItems(java.lang.CharSequence[], android.content.DialogInterface.OnClickListener);
+    method public android.app.AlertDialog.Builder setMessage(int);
+    method public android.app.AlertDialog.Builder setMessage(java.lang.CharSequence);
+    method public android.app.AlertDialog.Builder setMultiChoiceItems(int, boolean[], android.content.DialogInterface.OnMultiChoiceClickListener);
+    method public android.app.AlertDialog.Builder setMultiChoiceItems(java.lang.CharSequence[], boolean[], android.content.DialogInterface.OnMultiChoiceClickListener);
+    method public android.app.AlertDialog.Builder setMultiChoiceItems(android.database.Cursor, java.lang.String, java.lang.String, android.content.DialogInterface.OnMultiChoiceClickListener);
+    method public android.app.AlertDialog.Builder setNegativeButton(int, android.content.DialogInterface.OnClickListener);
+    method public android.app.AlertDialog.Builder setNegativeButton(java.lang.CharSequence, android.content.DialogInterface.OnClickListener);
+    method public android.app.AlertDialog.Builder setNeutralButton(int, android.content.DialogInterface.OnClickListener);
+    method public android.app.AlertDialog.Builder setNeutralButton(java.lang.CharSequence, android.content.DialogInterface.OnClickListener);
+    method public android.app.AlertDialog.Builder setOnCancelListener(android.content.DialogInterface.OnCancelListener);
+    method public android.app.AlertDialog.Builder setOnDismissListener(android.content.DialogInterface.OnDismissListener);
+    method public android.app.AlertDialog.Builder setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener);
+    method public android.app.AlertDialog.Builder setOnKeyListener(android.content.DialogInterface.OnKeyListener);
+    method public android.app.AlertDialog.Builder setPositiveButton(int, android.content.DialogInterface.OnClickListener);
+    method public android.app.AlertDialog.Builder setPositiveButton(java.lang.CharSequence, android.content.DialogInterface.OnClickListener);
+    method public android.app.AlertDialog.Builder setSingleChoiceItems(int, int, android.content.DialogInterface.OnClickListener);
+    method public android.app.AlertDialog.Builder setSingleChoiceItems(android.database.Cursor, int, java.lang.String, android.content.DialogInterface.OnClickListener);
+    method public android.app.AlertDialog.Builder setSingleChoiceItems(java.lang.CharSequence[], int, android.content.DialogInterface.OnClickListener);
+    method public android.app.AlertDialog.Builder setSingleChoiceItems(android.widget.ListAdapter, int, android.content.DialogInterface.OnClickListener);
+    method public android.app.AlertDialog.Builder setTitle(int);
+    method public android.app.AlertDialog.Builder setTitle(java.lang.CharSequence);
+    method public android.app.AlertDialog.Builder setView(android.view.View);
+    method public android.app.AlertDialog show();
+  }
+
+  public class AliasActivity extends android.app.Activity {
+    ctor public AliasActivity();
+  }
+
+  public class Application extends android.content.ContextWrapper implements android.content.ComponentCallbacks2 {
+    ctor public Application();
+    method public void onConfigurationChanged(android.content.res.Configuration);
+    method public void onCreate();
+    method public void onLowMemory();
+    method public void onTerminate();
+    method public void onTrimMemory(int);
+    method public void registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
+    method public void unregisterActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
+  }
+
+  public static abstract interface Application.ActivityLifecycleCallbacks {
+    method public abstract void onActivityCreated(android.app.Activity, android.os.Bundle);
+    method public abstract void onActivityDestroyed(android.app.Activity);
+    method public abstract void onActivityPaused(android.app.Activity);
+    method public abstract void onActivityResumed(android.app.Activity);
+    method public abstract void onActivitySaveInstanceState(android.app.Activity, android.os.Bundle);
+    method public abstract void onActivityStarted(android.app.Activity);
+    method public abstract void onActivityStopped(android.app.Activity);
+  }
+
+  public class ApplicationErrorReport implements android.os.Parcelable {
+    ctor public ApplicationErrorReport();
+    method public int describeContents();
+    method public void dump(android.util.Printer, java.lang.String);
+    method public static android.content.ComponentName getErrorReportReceiver(android.content.Context, java.lang.String, int);
+    method public void readFromParcel(android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int TYPE_ANR = 2; // 0x2
+    field public static final int TYPE_BATTERY = 3; // 0x3
+    field public static final int TYPE_CRASH = 1; // 0x1
+    field public static final int TYPE_NONE = 0; // 0x0
+    field public static final int TYPE_RUNNING_SERVICE = 5; // 0x5
+    field public android.app.ApplicationErrorReport.AnrInfo anrInfo;
+    field public android.app.ApplicationErrorReport.BatteryInfo batteryInfo;
+    field public android.app.ApplicationErrorReport.CrashInfo crashInfo;
+    field public java.lang.String installerPackageName;
+    field public java.lang.String packageName;
+    field public java.lang.String processName;
+    field public android.app.ApplicationErrorReport.RunningServiceInfo runningServiceInfo;
+    field public boolean systemApp;
+    field public long time;
+    field public int type;
+  }
+
+  public static class ApplicationErrorReport.AnrInfo {
+    ctor public ApplicationErrorReport.AnrInfo();
+    ctor public ApplicationErrorReport.AnrInfo(android.os.Parcel);
+    method public void dump(android.util.Printer, java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public java.lang.String activity;
+    field public java.lang.String cause;
+    field public java.lang.String info;
+  }
+
+  public static class ApplicationErrorReport.BatteryInfo {
+    ctor public ApplicationErrorReport.BatteryInfo();
+    ctor public ApplicationErrorReport.BatteryInfo(android.os.Parcel);
+    method public void dump(android.util.Printer, java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public java.lang.String checkinDetails;
+    field public long durationMicros;
+    field public java.lang.String usageDetails;
+    field public int usagePercent;
+  }
+
+  public static class ApplicationErrorReport.CrashInfo {
+    ctor public ApplicationErrorReport.CrashInfo();
+    ctor public ApplicationErrorReport.CrashInfo(java.lang.Throwable);
+    ctor public ApplicationErrorReport.CrashInfo(android.os.Parcel);
+    method public void dump(android.util.Printer, java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public java.lang.String exceptionClassName;
+    field public java.lang.String exceptionMessage;
+    field public java.lang.String stackTrace;
+    field public java.lang.String throwClassName;
+    field public java.lang.String throwFileName;
+    field public int throwLineNumber;
+    field public java.lang.String throwMethodName;
+  }
+
+  public static class ApplicationErrorReport.RunningServiceInfo {
+    ctor public ApplicationErrorReport.RunningServiceInfo();
+    ctor public ApplicationErrorReport.RunningServiceInfo(android.os.Parcel);
+    method public void dump(android.util.Printer, java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public long durationMillis;
+    field public java.lang.String serviceDetails;
+  }
+
+  public class DatePickerDialog extends android.app.AlertDialog implements android.widget.DatePicker.OnDateChangedListener android.content.DialogInterface.OnClickListener {
+    ctor public DatePickerDialog(android.content.Context, android.app.DatePickerDialog.OnDateSetListener, int, int, int);
+    ctor public DatePickerDialog(android.content.Context, int, android.app.DatePickerDialog.OnDateSetListener, int, int, int);
+    method public android.widget.DatePicker getDatePicker();
+    method public void onClick(android.content.DialogInterface, int);
+    method public void onDateChanged(android.widget.DatePicker, int, int, int);
+    method public void updateDate(int, int, int);
+  }
+
+  public static abstract interface DatePickerDialog.OnDateSetListener {
+    method public abstract void onDateSet(android.widget.DatePicker, int, int, int);
+  }
+
+  public class Dialog implements android.content.DialogInterface android.view.KeyEvent.Callback android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
+    ctor public Dialog(android.content.Context);
+    ctor public Dialog(android.content.Context, int);
+    ctor protected Dialog(android.content.Context, boolean, android.content.DialogInterface.OnCancelListener);
+    method public void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
+    method public void cancel();
+    method public void closeOptionsMenu();
+    method public void dismiss();
+    method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
+    method public boolean dispatchKeyEvent(android.view.KeyEvent);
+    method public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
+    method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+    method public boolean dispatchTouchEvent(android.view.MotionEvent);
+    method public boolean dispatchTrackballEvent(android.view.MotionEvent);
+    method public android.view.View findViewById(int);
+    method public android.app.ActionBar getActionBar();
+    method public final android.content.Context getContext();
+    method public android.view.View getCurrentFocus();
+    method public android.view.LayoutInflater getLayoutInflater();
+    method public final android.app.Activity getOwnerActivity();
+    method public final int getVolumeControlStream();
+    method public android.view.Window getWindow();
+    method public void hide();
+    method public void invalidateOptionsMenu();
+    method public boolean isShowing();
+    method public void onActionModeFinished(android.view.ActionMode);
+    method public void onActionModeStarted(android.view.ActionMode);
+    method public void onAttachedToWindow();
+    method public void onBackPressed();
+    method public void onContentChanged();
+    method public boolean onContextItemSelected(android.view.MenuItem);
+    method public void onContextMenuClosed(android.view.Menu);
+    method protected void onCreate(android.os.Bundle);
+    method public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo);
+    method public boolean onCreateOptionsMenu(android.view.Menu);
+    method public boolean onCreatePanelMenu(int, android.view.Menu);
+    method public android.view.View onCreatePanelView(int);
+    method public void onDetachedFromWindow();
+    method public boolean onGenericMotionEvent(android.view.MotionEvent);
+    method public boolean onKeyDown(int, android.view.KeyEvent);
+    method public boolean onKeyLongPress(int, android.view.KeyEvent);
+    method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
+    method public boolean onKeyShortcut(int, android.view.KeyEvent);
+    method public boolean onKeyUp(int, android.view.KeyEvent);
+    method public boolean onMenuItemSelected(int, android.view.MenuItem);
+    method public boolean onMenuOpened(int, android.view.Menu);
+    method public boolean onOptionsItemSelected(android.view.MenuItem);
+    method public void onOptionsMenuClosed(android.view.Menu);
+    method public void onPanelClosed(int, android.view.Menu);
+    method public boolean onPrepareOptionsMenu(android.view.Menu);
+    method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+    method public void onRestoreInstanceState(android.os.Bundle);
+    method public android.os.Bundle onSaveInstanceState();
+    method public boolean onSearchRequested();
+    method protected void onStart();
+    method protected void onStop();
+    method public boolean onTouchEvent(android.view.MotionEvent);
+    method public boolean onTrackballEvent(android.view.MotionEvent);
+    method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
+    method public void onWindowFocusChanged(boolean);
+    method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
+    method public void openContextMenu(android.view.View);
+    method public void openOptionsMenu();
+    method public void registerForContextMenu(android.view.View);
+    method public final boolean requestWindowFeature(int);
+    method public void setCancelMessage(android.os.Message);
+    method public void setCancelable(boolean);
+    method public void setCanceledOnTouchOutside(boolean);
+    method public void setContentView(int);
+    method public void setContentView(android.view.View);
+    method public void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
+    method public void setDismissMessage(android.os.Message);
+    method public final void setFeatureDrawable(int, android.graphics.drawable.Drawable);
+    method public final void setFeatureDrawableAlpha(int, int);
+    method public final void setFeatureDrawableResource(int, int);
+    method public final void setFeatureDrawableUri(int, android.net.Uri);
+    method public void setOnCancelListener(android.content.DialogInterface.OnCancelListener);
+    method public void setOnDismissListener(android.content.DialogInterface.OnDismissListener);
+    method public void setOnKeyListener(android.content.DialogInterface.OnKeyListener);
+    method public void setOnShowListener(android.content.DialogInterface.OnShowListener);
+    method public final void setOwnerActivity(android.app.Activity);
+    method public void setTitle(java.lang.CharSequence);
+    method public void setTitle(int);
+    method public final void setVolumeControlStream(int);
+    method public void show();
+    method public void takeKeyEvents(boolean);
+    method public void unregisterForContextMenu(android.view.View);
+  }
+
+  public class DialogFragment extends android.app.Fragment implements android.content.DialogInterface.OnCancelListener android.content.DialogInterface.OnDismissListener {
+    ctor public DialogFragment();
+    method public void dismiss();
+    method public void dismissAllowingStateLoss();
+    method public android.app.Dialog getDialog();
+    method public boolean getShowsDialog();
+    method public int getTheme();
+    method public boolean isCancelable();
+    method public void onCancel(android.content.DialogInterface);
+    method public android.app.Dialog onCreateDialog(android.os.Bundle);
+    method public void onDismiss(android.content.DialogInterface);
+    method public void setCancelable(boolean);
+    method public void setShowsDialog(boolean);
+    method public void setStyle(int, int);
+    method public void show(android.app.FragmentManager, java.lang.String);
+    method public int show(android.app.FragmentTransaction, java.lang.String);
+    field public static final int STYLE_NORMAL = 0; // 0x0
+    field public static final int STYLE_NO_FRAME = 2; // 0x2
+    field public static final int STYLE_NO_INPUT = 3; // 0x3
+    field public static final int STYLE_NO_TITLE = 1; // 0x1
+  }
+
+  public class DownloadManager {
+    method public long addCompletedDownload(java.lang.String, java.lang.String, boolean, java.lang.String, java.lang.String, long, boolean);
+    method public long enqueue(android.app.DownloadManager.Request);
+    method public static java.lang.Long getMaxBytesOverMobile(android.content.Context);
+    method public java.lang.String getMimeTypeForDownloadedFile(long);
+    method public static java.lang.Long getRecommendedMaxBytesOverMobile(android.content.Context);
+    method public android.net.Uri getUriForDownloadedFile(long);
+    method public android.os.ParcelFileDescriptor openDownloadedFile(long) throws java.io.FileNotFoundException;
+    method public android.database.Cursor query(android.app.DownloadManager.Query);
+    method public int remove(long...);
+    field public static final java.lang.String ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE";
+    field public static final java.lang.String ACTION_NOTIFICATION_CLICKED = "android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED";
+    field public static final java.lang.String ACTION_VIEW_DOWNLOADS = "android.intent.action.VIEW_DOWNLOADS";
+    field public static final java.lang.String COLUMN_BYTES_DOWNLOADED_SO_FAR = "bytes_so_far";
+    field public static final java.lang.String COLUMN_DESCRIPTION = "description";
+    field public static final java.lang.String COLUMN_ID = "_id";
+    field public static final java.lang.String COLUMN_LAST_MODIFIED_TIMESTAMP = "last_modified_timestamp";
+    field public static final java.lang.String COLUMN_LOCAL_FILENAME = "local_filename";
+    field public static final java.lang.String COLUMN_LOCAL_URI = "local_uri";
+    field public static final java.lang.String COLUMN_MEDIAPROVIDER_URI = "mediaprovider_uri";
+    field public static final java.lang.String COLUMN_MEDIA_TYPE = "media_type";
+    field public static final java.lang.String COLUMN_REASON = "reason";
+    field public static final java.lang.String COLUMN_STATUS = "status";
+    field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final java.lang.String COLUMN_TOTAL_SIZE_BYTES = "total_size";
+    field public static final java.lang.String COLUMN_URI = "uri";
+    field public static final int ERROR_CANNOT_RESUME = 1008; // 0x3f0
+    field public static final int ERROR_DEVICE_NOT_FOUND = 1007; // 0x3ef
+    field public static final int ERROR_FILE_ALREADY_EXISTS = 1009; // 0x3f1
+    field public static final int ERROR_FILE_ERROR = 1001; // 0x3e9
+    field public static final int ERROR_HTTP_DATA_ERROR = 1004; // 0x3ec
+    field public static final int ERROR_INSUFFICIENT_SPACE = 1006; // 0x3ee
+    field public static final int ERROR_TOO_MANY_REDIRECTS = 1005; // 0x3ed
+    field public static final int ERROR_UNHANDLED_HTTP_CODE = 1002; // 0x3ea
+    field public static final int ERROR_UNKNOWN = 1000; // 0x3e8
+    field public static final java.lang.String EXTRA_DOWNLOAD_ID = "extra_download_id";
+    field public static final java.lang.String EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS = "extra_click_download_ids";
+    field public static final java.lang.String INTENT_EXTRAS_SORT_BY_SIZE = "android.app.DownloadManager.extra_sortBySize";
+    field public static final int PAUSED_QUEUED_FOR_WIFI = 3; // 0x3
+    field public static final int PAUSED_UNKNOWN = 4; // 0x4
+    field public static final int PAUSED_WAITING_FOR_NETWORK = 2; // 0x2
+    field public static final int PAUSED_WAITING_TO_RETRY = 1; // 0x1
+    field public static final int STATUS_FAILED = 16; // 0x10
+    field public static final int STATUS_PAUSED = 4; // 0x4
+    field public static final int STATUS_PENDING = 1; // 0x1
+    field public static final int STATUS_RUNNING = 2; // 0x2
+    field public static final int STATUS_SUCCESSFUL = 8; // 0x8
+  }
+
+  public static class DownloadManager.Query {
+    ctor public DownloadManager.Query();
+    method public android.app.DownloadManager.Query setFilterById(long...);
+    method public android.app.DownloadManager.Query setFilterByStatus(int);
+  }
+
+  public static class DownloadManager.Request {
+    ctor public DownloadManager.Request(android.net.Uri);
+    method public android.app.DownloadManager.Request addRequestHeader(java.lang.String, java.lang.String);
+    method public void allowScanningByMediaScanner();
+    method public android.app.DownloadManager.Request setAllowedNetworkTypes(int);
+    method public android.app.DownloadManager.Request setAllowedOverMetered(boolean);
+    method public android.app.DownloadManager.Request setAllowedOverRoaming(boolean);
+    method public android.app.DownloadManager.Request setDescription(java.lang.CharSequence);
+    method public android.app.DownloadManager.Request setDestinationInExternalFilesDir(android.content.Context, java.lang.String, java.lang.String);
+    method public android.app.DownloadManager.Request setDestinationInExternalPublicDir(java.lang.String, java.lang.String);
+    method public android.app.DownloadManager.Request setDestinationUri(android.net.Uri);
+    method public android.app.DownloadManager.Request setMimeType(java.lang.String);
+    method public android.app.DownloadManager.Request setNotificationVisibility(int);
+    method public deprecated android.app.DownloadManager.Request setShowRunningNotification(boolean);
+    method public android.app.DownloadManager.Request setTitle(java.lang.CharSequence);
+    method public android.app.DownloadManager.Request setVisibleInDownloadsUi(boolean);
+    field public static final int NETWORK_MOBILE = 1; // 0x1
+    field public static final int NETWORK_WIFI = 2; // 0x2
+    field public static final int VISIBILITY_HIDDEN = 2; // 0x2
+    field public static final int VISIBILITY_VISIBLE = 0; // 0x0
+    field public static final int VISIBILITY_VISIBLE_NOTIFY_COMPLETED = 1; // 0x1
+    field public static final int VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION = 3; // 0x3
+  }
+
+  public class ExpandableListActivity extends android.app.Activity implements android.widget.ExpandableListView.OnChildClickListener android.widget.ExpandableListView.OnGroupCollapseListener android.widget.ExpandableListView.OnGroupExpandListener android.view.View.OnCreateContextMenuListener {
+    ctor public ExpandableListActivity();
+    method public android.widget.ExpandableListAdapter getExpandableListAdapter();
+    method public android.widget.ExpandableListView getExpandableListView();
+    method public long getSelectedId();
+    method public long getSelectedPosition();
+    method public boolean onChildClick(android.widget.ExpandableListView, android.view.View, int, int, long);
+    method public void onGroupCollapse(int);
+    method public void onGroupExpand(int);
+    method public void setListAdapter(android.widget.ExpandableListAdapter);
+    method public boolean setSelectedChild(int, int, boolean);
+    method public void setSelectedGroup(int);
+  }
+
+  public class Fragment implements android.content.ComponentCallbacks2 android.view.View.OnCreateContextMenuListener {
+    ctor public Fragment();
+    method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public final boolean equals(java.lang.Object);
+    method public final android.app.Activity getActivity();
+    method public final android.os.Bundle getArguments();
+    method public final android.app.FragmentManager getChildFragmentManager();
+    method public final android.app.FragmentManager getFragmentManager();
+    method public final int getId();
+    method public android.app.LoaderManager getLoaderManager();
+    method public final android.app.Fragment getParentFragment();
+    method public final android.content.res.Resources getResources();
+    method public final boolean getRetainInstance();
+    method public final java.lang.String getString(int);
+    method public final java.lang.String getString(int, java.lang.Object...);
+    method public final java.lang.String getTag();
+    method public final android.app.Fragment getTargetFragment();
+    method public final int getTargetRequestCode();
+    method public final java.lang.CharSequence getText(int);
+    method public boolean getUserVisibleHint();
+    method public android.view.View getView();
+    method public final int hashCode();
+    method public static android.app.Fragment instantiate(android.content.Context, java.lang.String);
+    method public static android.app.Fragment instantiate(android.content.Context, java.lang.String, android.os.Bundle);
+    method public final boolean isAdded();
+    method public final boolean isDetached();
+    method public final boolean isHidden();
+    method public final boolean isInLayout();
+    method public final boolean isRemoving();
+    method public final boolean isResumed();
+    method public final boolean isVisible();
+    method public void onActivityCreated(android.os.Bundle);
+    method public void onActivityResult(int, int, android.content.Intent);
+    method public void onAttach(android.app.Activity);
+    method public void onConfigurationChanged(android.content.res.Configuration);
+    method public boolean onContextItemSelected(android.view.MenuItem);
+    method public void onCreate(android.os.Bundle);
+    method public android.animation.Animator onCreateAnimator(int, boolean, int);
+    method public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo);
+    method public void onCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+    method public android.view.View onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
+    method public void onDestroy();
+    method public void onDestroyOptionsMenu();
+    method public void onDestroyView();
+    method public void onDetach();
+    method public void onHiddenChanged(boolean);
+    method public deprecated void onInflate(android.util.AttributeSet, android.os.Bundle);
+    method public void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
+    method public void onLowMemory();
+    method public boolean onOptionsItemSelected(android.view.MenuItem);
+    method public void onOptionsMenuClosed(android.view.Menu);
+    method public void onPause();
+    method public void onPrepareOptionsMenu(android.view.Menu);
+    method public void onResume();
+    method public void onSaveInstanceState(android.os.Bundle);
+    method public void onStart();
+    method public void onStop();
+    method public void onTrimMemory(int);
+    method public void onViewCreated(android.view.View, android.os.Bundle);
+    method public void onViewStateRestored(android.os.Bundle);
+    method public void registerForContextMenu(android.view.View);
+    method public void setArguments(android.os.Bundle);
+    method public void setHasOptionsMenu(boolean);
+    method public void setInitialSavedState(android.app.Fragment.SavedState);
+    method public void setMenuVisibility(boolean);
+    method public void setRetainInstance(boolean);
+    method public void setTargetFragment(android.app.Fragment, int);
+    method public void setUserVisibleHint(boolean);
+    method public void startActivity(android.content.Intent);
+    method public void startActivity(android.content.Intent, android.os.Bundle);
+    method public void startActivityForResult(android.content.Intent, int);
+    method public void startActivityForResult(android.content.Intent, int, android.os.Bundle);
+    method public void unregisterForContextMenu(android.view.View);
+  }
+
+  public static class Fragment.InstantiationException extends android.util.AndroidRuntimeException {
+    ctor public Fragment.InstantiationException(java.lang.String, java.lang.Exception);
+  }
+
+  public static class Fragment.SavedState implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.ClassLoaderCreator CREATOR;
+  }
+
+  public class FragmentBreadCrumbs extends android.view.ViewGroup implements android.app.FragmentManager.OnBackStackChangedListener {
+    ctor public FragmentBreadCrumbs(android.content.Context);
+    ctor public FragmentBreadCrumbs(android.content.Context, android.util.AttributeSet);
+    ctor public FragmentBreadCrumbs(android.content.Context, android.util.AttributeSet, int);
+    method public void onBackStackChanged();
+    method protected void onLayout(boolean, int, int, int, int);
+    method public void setActivity(android.app.Activity);
+    method public void setMaxVisible(int);
+    method public void setOnBreadCrumbClickListener(android.app.FragmentBreadCrumbs.OnBreadCrumbClickListener);
+    method public void setParentTitle(java.lang.CharSequence, java.lang.CharSequence, android.view.View.OnClickListener);
+    method public void setTitle(java.lang.CharSequence, java.lang.CharSequence);
+  }
+
+  public static abstract interface FragmentBreadCrumbs.OnBreadCrumbClickListener {
+    method public abstract boolean onBreadCrumbClick(android.app.FragmentManager.BackStackEntry, int);
+  }
+
+  public abstract class FragmentManager {
+    ctor public FragmentManager();
+    method public abstract void addOnBackStackChangedListener(android.app.FragmentManager.OnBackStackChangedListener);
+    method public abstract android.app.FragmentTransaction beginTransaction();
+    method public abstract void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public static void enableDebugLogging(boolean);
+    method public abstract boolean executePendingTransactions();
+    method public abstract android.app.Fragment findFragmentById(int);
+    method public abstract android.app.Fragment findFragmentByTag(java.lang.String);
+    method public abstract android.app.FragmentManager.BackStackEntry getBackStackEntryAt(int);
+    method public abstract int getBackStackEntryCount();
+    method public abstract android.app.Fragment getFragment(android.os.Bundle, java.lang.String);
+    method public void invalidateOptionsMenu();
+    method public abstract boolean isDestroyed();
+    method public abstract void popBackStack();
+    method public abstract void popBackStack(java.lang.String, int);
+    method public abstract void popBackStack(int, int);
+    method public abstract boolean popBackStackImmediate();
+    method public abstract boolean popBackStackImmediate(java.lang.String, int);
+    method public abstract boolean popBackStackImmediate(int, int);
+    method public abstract void putFragment(android.os.Bundle, java.lang.String, android.app.Fragment);
+    method public abstract void removeOnBackStackChangedListener(android.app.FragmentManager.OnBackStackChangedListener);
+    method public abstract android.app.Fragment.SavedState saveFragmentInstanceState(android.app.Fragment);
+    field public static final int POP_BACK_STACK_INCLUSIVE = 1; // 0x1
+  }
+
+  public static abstract interface FragmentManager.BackStackEntry {
+    method public abstract java.lang.CharSequence getBreadCrumbShortTitle();
+    method public abstract int getBreadCrumbShortTitleRes();
+    method public abstract java.lang.CharSequence getBreadCrumbTitle();
+    method public abstract int getBreadCrumbTitleRes();
+    method public abstract int getId();
+    method public abstract java.lang.String getName();
+  }
+
+  public static abstract interface FragmentManager.OnBackStackChangedListener {
+    method public abstract void onBackStackChanged();
+  }
+
+  public abstract class FragmentTransaction {
+    ctor public FragmentTransaction();
+    method public abstract android.app.FragmentTransaction add(android.app.Fragment, java.lang.String);
+    method public abstract android.app.FragmentTransaction add(int, android.app.Fragment);
+    method public abstract android.app.FragmentTransaction add(int, android.app.Fragment, java.lang.String);
+    method public abstract android.app.FragmentTransaction addToBackStack(java.lang.String);
+    method public abstract android.app.FragmentTransaction attach(android.app.Fragment);
+    method public abstract int commit();
+    method public abstract int commitAllowingStateLoss();
+    method public abstract android.app.FragmentTransaction detach(android.app.Fragment);
+    method public abstract android.app.FragmentTransaction disallowAddToBackStack();
+    method public abstract android.app.FragmentTransaction hide(android.app.Fragment);
+    method public abstract boolean isAddToBackStackAllowed();
+    method public abstract boolean isEmpty();
+    method public abstract android.app.FragmentTransaction remove(android.app.Fragment);
+    method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment);
+    method public abstract android.app.FragmentTransaction replace(int, android.app.Fragment, java.lang.String);
+    method public abstract android.app.FragmentTransaction setBreadCrumbShortTitle(int);
+    method public abstract android.app.FragmentTransaction setBreadCrumbShortTitle(java.lang.CharSequence);
+    method public abstract android.app.FragmentTransaction setBreadCrumbTitle(int);
+    method public abstract android.app.FragmentTransaction setBreadCrumbTitle(java.lang.CharSequence);
+    method public abstract android.app.FragmentTransaction setCustomAnimations(int, int);
+    method public abstract android.app.FragmentTransaction setCustomAnimations(int, int, int, int);
+    method public abstract android.app.FragmentTransaction setTransition(int);
+    method public abstract android.app.FragmentTransaction setTransitionStyle(int);
+    method public abstract android.app.FragmentTransaction show(android.app.Fragment);
+    field public static final int TRANSIT_ENTER_MASK = 4096; // 0x1000
+    field public static final int TRANSIT_EXIT_MASK = 8192; // 0x2000
+    field public static final int TRANSIT_FRAGMENT_CLOSE = 8194; // 0x2002
+    field public static final int TRANSIT_FRAGMENT_FADE = 4099; // 0x1003
+    field public static final int TRANSIT_FRAGMENT_OPEN = 4097; // 0x1001
+    field public static final int TRANSIT_NONE = 0; // 0x0
+    field public static final int TRANSIT_UNSET = -1; // 0xffffffff
+  }
+
+  public class Instrumentation {
+    ctor public Instrumentation();
+    method public void addMonitor(android.app.Instrumentation.ActivityMonitor);
+    method public android.app.Instrumentation.ActivityMonitor addMonitor(android.content.IntentFilter, android.app.Instrumentation.ActivityResult, boolean);
+    method public android.app.Instrumentation.ActivityMonitor addMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean);
+    method public void callActivityOnCreate(android.app.Activity, android.os.Bundle);
+    method public void callActivityOnDestroy(android.app.Activity);
+    method public void callActivityOnNewIntent(android.app.Activity, android.content.Intent);
+    method public void callActivityOnPause(android.app.Activity);
+    method public void callActivityOnPostCreate(android.app.Activity, android.os.Bundle);
+    method public void callActivityOnRestart(android.app.Activity);
+    method public void callActivityOnRestoreInstanceState(android.app.Activity, android.os.Bundle);
+    method public void callActivityOnResume(android.app.Activity);
+    method public void callActivityOnSaveInstanceState(android.app.Activity, android.os.Bundle);
+    method public void callActivityOnStart(android.app.Activity);
+    method public void callActivityOnStop(android.app.Activity);
+    method public void callActivityOnUserLeaving(android.app.Activity);
+    method public void callApplicationOnCreate(android.app.Application);
+    method public boolean checkMonitorHit(android.app.Instrumentation.ActivityMonitor, int);
+    method public void endPerformanceSnapshot();
+    method public void finish(int, android.os.Bundle);
+    method public android.os.Bundle getAllocCounts();
+    method public android.os.Bundle getBinderCounts();
+    method public android.content.ComponentName getComponentName();
+    method public android.content.Context getContext();
+    method public android.content.Context getTargetContext();
+    method public boolean invokeContextMenuAction(android.app.Activity, int, int);
+    method public boolean invokeMenuActionSync(android.app.Activity, int, int);
+    method public boolean isProfiling();
+    method public android.app.Activity newActivity(java.lang.Class<?>, android.content.Context, android.os.IBinder, android.app.Application, android.content.Intent, android.content.pm.ActivityInfo, java.lang.CharSequence, android.app.Activity, java.lang.String, java.lang.Object) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public android.app.Activity newActivity(java.lang.ClassLoader, java.lang.String, android.content.Intent) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public android.app.Application newApplication(java.lang.ClassLoader, java.lang.String, android.content.Context) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public static android.app.Application newApplication(java.lang.Class<?>, android.content.Context) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public void onCreate(android.os.Bundle);
+    method public void onDestroy();
+    method public boolean onException(java.lang.Object, java.lang.Throwable);
+    method public void onStart();
+    method public void removeMonitor(android.app.Instrumentation.ActivityMonitor);
+    method public void runOnMainSync(java.lang.Runnable);
+    method public void sendCharacterSync(int);
+    method public void sendKeyDownUpSync(int);
+    method public void sendKeySync(android.view.KeyEvent);
+    method public void sendPointerSync(android.view.MotionEvent);
+    method public void sendStatus(int, android.os.Bundle);
+    method public void sendStringSync(java.lang.String);
+    method public void sendTrackballEventSync(android.view.MotionEvent);
+    method public void setAutomaticPerformanceSnapshots();
+    method public void setInTouchMode(boolean);
+    method public void start();
+    method public android.app.Activity startActivitySync(android.content.Intent);
+    method public void startAllocCounting();
+    method public void startPerformanceSnapshot();
+    method public void startProfiling();
+    method public void stopAllocCounting();
+    method public void stopProfiling();
+    method public void waitForIdle(java.lang.Runnable);
+    method public void waitForIdleSync();
+    method public android.app.Activity waitForMonitor(android.app.Instrumentation.ActivityMonitor);
+    method public android.app.Activity waitForMonitorWithTimeout(android.app.Instrumentation.ActivityMonitor, long);
+    field public static final java.lang.String REPORT_KEY_IDENTIFIER = "id";
+    field public static final java.lang.String REPORT_KEY_STREAMRESULT = "stream";
+  }
+
+  public static class Instrumentation.ActivityMonitor {
+    ctor public Instrumentation.ActivityMonitor(android.content.IntentFilter, android.app.Instrumentation.ActivityResult, boolean);
+    ctor public Instrumentation.ActivityMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean);
+    method public final android.content.IntentFilter getFilter();
+    method public final int getHits();
+    method public final android.app.Activity getLastActivity();
+    method public final android.app.Instrumentation.ActivityResult getResult();
+    method public final boolean isBlocking();
+    method public final android.app.Activity waitForActivity();
+    method public final android.app.Activity waitForActivityWithTimeout(long);
+  }
+
+  public static final class Instrumentation.ActivityResult {
+    ctor public Instrumentation.ActivityResult(int, android.content.Intent);
+    method public int getResultCode();
+    method public android.content.Intent getResultData();
+  }
+
+  public abstract class IntentService extends android.app.Service {
+    ctor public IntentService(java.lang.String);
+    method public android.os.IBinder onBind(android.content.Intent);
+    method protected abstract void onHandleIntent(android.content.Intent);
+    method public void setIntentRedelivery(boolean);
+  }
+
+  public class KeyguardManager {
+    method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult);
+    method public boolean inKeyguardRestrictedInputMode();
+    method public boolean isKeyguardLocked();
+    method public boolean isKeyguardSecure();
+    method public deprecated android.app.KeyguardManager.KeyguardLock newKeyguardLock(java.lang.String);
+  }
+
+  public deprecated class KeyguardManager.KeyguardLock {
+    method public void disableKeyguard();
+    method public void reenableKeyguard();
+  }
+
+  public static abstract interface KeyguardManager.OnKeyguardExitResult {
+    method public abstract void onKeyguardExitResult(boolean);
+  }
+
+  public abstract class LauncherActivity extends android.app.ListActivity {
+    ctor public LauncherActivity();
+    method protected android.content.Intent getTargetIntent();
+    method protected android.content.Intent intentForPosition(int);
+    method protected android.app.LauncherActivity.ListItem itemForPosition(int);
+    method public java.util.List<android.app.LauncherActivity.ListItem> makeListItems();
+    method protected java.util.List<android.content.pm.ResolveInfo> onQueryPackageManager(android.content.Intent);
+    method protected void onSetContentView();
+  }
+
+  public class LauncherActivity.IconResizer {
+    ctor public LauncherActivity.IconResizer();
+    method public android.graphics.drawable.Drawable createIconThumbnail(android.graphics.drawable.Drawable);
+  }
+
+  public static class LauncherActivity.ListItem {
+    ctor public LauncherActivity.ListItem();
+    field public java.lang.String className;
+    field public android.os.Bundle extras;
+    field public android.graphics.drawable.Drawable icon;
+    field public java.lang.CharSequence label;
+    field public java.lang.String packageName;
+    field public android.content.pm.ResolveInfo resolveInfo;
+  }
+
+  public class ListActivity extends android.app.Activity {
+    ctor public ListActivity();
+    method public android.widget.ListAdapter getListAdapter();
+    method public android.widget.ListView getListView();
+    method public long getSelectedItemId();
+    method public int getSelectedItemPosition();
+    method protected void onListItemClick(android.widget.ListView, android.view.View, int, long);
+    method public void setListAdapter(android.widget.ListAdapter);
+    method public void setSelection(int);
+  }
+
+  public class ListFragment extends android.app.Fragment {
+    ctor public ListFragment();
+    method public android.widget.ListAdapter getListAdapter();
+    method public android.widget.ListView getListView();
+    method public long getSelectedItemId();
+    method public int getSelectedItemPosition();
+    method public void onListItemClick(android.widget.ListView, android.view.View, int, long);
+    method public void setEmptyText(java.lang.CharSequence);
+    method public void setListAdapter(android.widget.ListAdapter);
+    method public void setListShown(boolean);
+    method public void setListShownNoAnimation(boolean);
+    method public void setSelection(int);
+  }
+
+  public abstract class LoaderManager {
+    ctor public LoaderManager();
+    method public abstract void destroyLoader(int);
+    method public abstract void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public static void enableDebugLogging(boolean);
+    method public abstract android.content.Loader<D> getLoader(int);
+    method public abstract android.content.Loader<D> initLoader(int, android.os.Bundle, android.app.LoaderManager.LoaderCallbacks<D>);
+    method public abstract android.content.Loader<D> restartLoader(int, android.os.Bundle, android.app.LoaderManager.LoaderCallbacks<D>);
+  }
+
+  public static abstract interface LoaderManager.LoaderCallbacks {
+    method public abstract android.content.Loader<D> onCreateLoader(int, android.os.Bundle);
+    method public abstract void onLoadFinished(android.content.Loader<D>, D);
+    method public abstract void onLoaderReset(android.content.Loader<D>);
+  }
+
+  public deprecated class LocalActivityManager {
+    ctor public LocalActivityManager(android.app.Activity, boolean);
+    method public android.view.Window destroyActivity(java.lang.String, boolean);
+    method public void dispatchCreate(android.os.Bundle);
+    method public void dispatchDestroy(boolean);
+    method public void dispatchPause(boolean);
+    method public void dispatchResume();
+    method public void dispatchStop();
+    method public android.app.Activity getActivity(java.lang.String);
+    method public android.app.Activity getCurrentActivity();
+    method public java.lang.String getCurrentId();
+    method public void removeAllActivities();
+    method public android.os.Bundle saveInstanceState();
+    method public android.view.Window startActivity(java.lang.String, android.content.Intent);
+  }
+
+  public class MediaRouteActionProvider extends android.view.ActionProvider {
+    ctor public MediaRouteActionProvider(android.content.Context);
+    method public android.view.View onCreateActionView();
+    method public void setExtendedSettingsClickListener(android.view.View.OnClickListener);
+    method public void setRouteTypes(int);
+  }
+
+  public class MediaRouteButton extends android.view.View {
+    ctor public MediaRouteButton(android.content.Context);
+    ctor public MediaRouteButton(android.content.Context, android.util.AttributeSet);
+    ctor public MediaRouteButton(android.content.Context, android.util.AttributeSet, int);
+    method public int getRouteTypes();
+    method public void onAttachedToWindow();
+    method public void onDetachedFromWindow();
+    method public void setExtendedSettingsClickListener(android.view.View.OnClickListener);
+    method public void setRouteTypes(int);
+    method public void showDialog();
+  }
+
+  public class NativeActivity extends android.app.Activity implements android.view.InputQueue.Callback android.view.SurfaceHolder.Callback2 android.view.ViewTreeObserver.OnGlobalLayoutListener {
+    ctor public NativeActivity();
+    method public void onGlobalLayout();
+    method public void onInputQueueCreated(android.view.InputQueue);
+    method public void onInputQueueDestroyed(android.view.InputQueue);
+    method public void surfaceChanged(android.view.SurfaceHolder, int, int, int);
+    method public void surfaceCreated(android.view.SurfaceHolder);
+    method public void surfaceDestroyed(android.view.SurfaceHolder);
+    method public void surfaceRedrawNeeded(android.view.SurfaceHolder);
+    field public static final java.lang.String META_DATA_FUNC_NAME = "android.app.func_name";
+    field public static final java.lang.String META_DATA_LIB_NAME = "android.app.lib_name";
+  }
+
+  public class Notification implements android.os.Parcelable {
+    ctor public Notification();
+    ctor public deprecated Notification(int, java.lang.CharSequence, long);
+    ctor public Notification(android.os.Parcel);
+    method public android.app.Notification clone();
+    method public int describeContents();
+    method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int DEFAULT_ALL = -1; // 0xffffffff
+    field public static final int DEFAULT_LIGHTS = 4; // 0x4
+    field public static final int DEFAULT_SOUND = 1; // 0x1
+    field public static final int DEFAULT_VIBRATE = 2; // 0x2
+    field public static final int FLAG_AUTO_CANCEL = 16; // 0x10
+    field public static final int FLAG_FOREGROUND_SERVICE = 64; // 0x40
+    field public static final deprecated int FLAG_HIGH_PRIORITY = 128; // 0x80
+    field public static final int FLAG_INSISTENT = 4; // 0x4
+    field public static final int FLAG_NO_CLEAR = 32; // 0x20
+    field public static final int FLAG_ONGOING_EVENT = 2; // 0x2
+    field public static final int FLAG_ONLY_ALERT_ONCE = 8; // 0x8
+    field public static final int FLAG_SHOW_LIGHTS = 1; // 0x1
+    field public static final int PRIORITY_DEFAULT = 0; // 0x0
+    field public static final int PRIORITY_HIGH = 1; // 0x1
+    field public static final int PRIORITY_LOW = -1; // 0xffffffff
+    field public static final int PRIORITY_MAX = 2; // 0x2
+    field public static final int PRIORITY_MIN = -2; // 0xfffffffe
+    field public static final int STREAM_DEFAULT = -1; // 0xffffffff
+    field public int audioStreamType;
+    field public android.widget.RemoteViews bigContentView;
+    field public android.app.PendingIntent contentIntent;
+    field public android.widget.RemoteViews contentView;
+    field public int defaults;
+    field public android.app.PendingIntent deleteIntent;
+    field public int flags;
+    field public android.app.PendingIntent fullScreenIntent;
+    field public int icon;
+    field public int iconLevel;
+    field public android.graphics.Bitmap largeIcon;
+    field public int ledARGB;
+    field public int ledOffMS;
+    field public int ledOnMS;
+    field public int number;
+    field public int priority;
+    field public android.net.Uri sound;
+    field public java.lang.CharSequence tickerText;
+    field public android.widget.RemoteViews tickerView;
+    field public long[] vibrate;
+    field public long when;
+  }
+
+  public static class Notification.BigPictureStyle extends android.app.Notification.Style {
+    ctor public Notification.BigPictureStyle();
+    ctor public Notification.BigPictureStyle(android.app.Notification.Builder);
+    method public android.app.Notification.BigPictureStyle bigLargeIcon(android.graphics.Bitmap);
+    method public android.app.Notification.BigPictureStyle bigPicture(android.graphics.Bitmap);
+    method public android.app.Notification build();
+    method public android.app.Notification.BigPictureStyle setBigContentTitle(java.lang.CharSequence);
+    method public android.app.Notification.BigPictureStyle setSummaryText(java.lang.CharSequence);
+  }
+
+  public static class Notification.BigTextStyle extends android.app.Notification.Style {
+    ctor public Notification.BigTextStyle();
+    ctor public Notification.BigTextStyle(android.app.Notification.Builder);
+    method public android.app.Notification.BigTextStyle bigText(java.lang.CharSequence);
+    method public android.app.Notification build();
+    method public android.app.Notification.BigTextStyle setBigContentTitle(java.lang.CharSequence);
+    method public android.app.Notification.BigTextStyle setSummaryText(java.lang.CharSequence);
+  }
+
+  public static class Notification.Builder {
+    ctor public Notification.Builder(android.content.Context);
+    method public android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent);
+    method public android.app.Notification build();
+    method public deprecated android.app.Notification getNotification();
+    method public android.app.Notification.Builder setAutoCancel(boolean);
+    method public android.app.Notification.Builder setContent(android.widget.RemoteViews);
+    method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
+    method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent);
+    method public android.app.Notification.Builder setContentText(java.lang.CharSequence);
+    method public android.app.Notification.Builder setContentTitle(java.lang.CharSequence);
+    method public android.app.Notification.Builder setDefaults(int);
+    method public android.app.Notification.Builder setDeleteIntent(android.app.PendingIntent);
+    method public android.app.Notification.Builder setFullScreenIntent(android.app.PendingIntent, boolean);
+    method public android.app.Notification.Builder setLargeIcon(android.graphics.Bitmap);
+    method public android.app.Notification.Builder setLights(int, int, int);
+    method public android.app.Notification.Builder setNumber(int);
+    method public android.app.Notification.Builder setOngoing(boolean);
+    method public android.app.Notification.Builder setOnlyAlertOnce(boolean);
+    method public android.app.Notification.Builder setPriority(int);
+    method public android.app.Notification.Builder setProgress(int, int, boolean);
+    method public android.app.Notification.Builder setShowWhen(boolean);
+    method public android.app.Notification.Builder setSmallIcon(int);
+    method public android.app.Notification.Builder setSmallIcon(int, int);
+    method public android.app.Notification.Builder setSound(android.net.Uri);
+    method public android.app.Notification.Builder setSound(android.net.Uri, int);
+    method public android.app.Notification.Builder setStyle(android.app.Notification.Style);
+    method public android.app.Notification.Builder setSubText(java.lang.CharSequence);
+    method public android.app.Notification.Builder setTicker(java.lang.CharSequence);
+    method public android.app.Notification.Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews);
+    method public android.app.Notification.Builder setUsesChronometer(boolean);
+    method public android.app.Notification.Builder setVibrate(long[]);
+    method public android.app.Notification.Builder setWhen(long);
+  }
+
+  public static class Notification.InboxStyle extends android.app.Notification.Style {
+    ctor public Notification.InboxStyle();
+    ctor public Notification.InboxStyle(android.app.Notification.Builder);
+    method public android.app.Notification.InboxStyle addLine(java.lang.CharSequence);
+    method public android.app.Notification build();
+    method public android.app.Notification.InboxStyle setBigContentTitle(java.lang.CharSequence);
+    method public android.app.Notification.InboxStyle setSummaryText(java.lang.CharSequence);
+  }
+
+  public static abstract class Notification.Style {
+    ctor public Notification.Style();
+    method public abstract android.app.Notification build();
+    method protected void checkBuilder();
+    method protected android.widget.RemoteViews getStandardView(int);
+    method protected void internalSetBigContentTitle(java.lang.CharSequence);
+    method protected void internalSetSummaryText(java.lang.CharSequence);
+    method public void setBuilder(android.app.Notification.Builder);
+    field protected android.app.Notification.Builder mBuilder;
+  }
+
+  public class NotificationManager {
+    method public void cancel(int);
+    method public void cancel(java.lang.String, int);
+    method public void cancelAll();
+    method public void notify(int, android.app.Notification);
+    method public void notify(java.lang.String, int, android.app.Notification);
+  }
+
+  public final class PendingIntent implements android.os.Parcelable {
+    method public void cancel();
+    method public int describeContents();
+    method public static android.app.PendingIntent getActivities(android.content.Context, int, android.content.Intent[], int);
+    method public static android.app.PendingIntent getActivities(android.content.Context, int, android.content.Intent[], int, android.os.Bundle);
+    method public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int);
+    method public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int, android.os.Bundle);
+    method public static android.app.PendingIntent getBroadcast(android.content.Context, int, android.content.Intent, int);
+    method public java.lang.String getCreatorPackage();
+    method public int getCreatorUid();
+    method public android.os.UserHandle getCreatorUserHandle();
+    method public android.content.IntentSender getIntentSender();
+    method public static android.app.PendingIntent getService(android.content.Context, int, android.content.Intent, int);
+    method public deprecated java.lang.String getTargetPackage();
+    method public static android.app.PendingIntent readPendingIntentOrNullFromParcel(android.os.Parcel);
+    method public void send() throws android.app.PendingIntent.CanceledException;
+    method public void send(int) throws android.app.PendingIntent.CanceledException;
+    method public void send(android.content.Context, int, android.content.Intent) throws android.app.PendingIntent.CanceledException;
+    method public void send(int, android.app.PendingIntent.OnFinished, android.os.Handler) throws android.app.PendingIntent.CanceledException;
+    method public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler) throws android.app.PendingIntent.CanceledException;
+    method public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler, java.lang.String) throws android.app.PendingIntent.CanceledException;
+    method public static void writePendingIntentOrNullToParcel(android.app.PendingIntent, android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_CANCEL_CURRENT = 268435456; // 0x10000000
+    field public static final int FLAG_NO_CREATE = 536870912; // 0x20000000
+    field public static final int FLAG_ONE_SHOT = 1073741824; // 0x40000000
+    field public static final int FLAG_UPDATE_CURRENT = 134217728; // 0x8000000
+  }
+
+  public static class PendingIntent.CanceledException extends android.util.AndroidException {
+    ctor public PendingIntent.CanceledException();
+    ctor public PendingIntent.CanceledException(java.lang.String);
+    ctor public PendingIntent.CanceledException(java.lang.Exception);
+  }
+
+  public static abstract interface PendingIntent.OnFinished {
+    method public abstract void onSendFinished(android.app.PendingIntent, android.content.Intent, int, java.lang.String, android.os.Bundle);
+  }
+
+  public class Presentation extends android.app.Dialog {
+    ctor public Presentation(android.content.Context, android.view.Display);
+    ctor public Presentation(android.content.Context, android.view.Display, int);
+    method public android.view.Display getDisplay();
+    method public android.content.res.Resources getResources();
+    method public void onDisplayChanged();
+    method public void onDisplayRemoved();
+  }
+
+  public class ProgressDialog extends android.app.AlertDialog {
+    ctor public ProgressDialog(android.content.Context);
+    ctor public ProgressDialog(android.content.Context, int);
+    method public int getMax();
+    method public int getProgress();
+    method public int getSecondaryProgress();
+    method public void incrementProgressBy(int);
+    method public void incrementSecondaryProgressBy(int);
+    method public boolean isIndeterminate();
+    method public void onStart();
+    method public void setIndeterminate(boolean);
+    method public void setIndeterminateDrawable(android.graphics.drawable.Drawable);
+    method public void setMax(int);
+    method public void setProgress(int);
+    method public void setProgressDrawable(android.graphics.drawable.Drawable);
+    method public void setProgressNumberFormat(java.lang.String);
+    method public void setProgressPercentFormat(java.text.NumberFormat);
+    method public void setProgressStyle(int);
+    method public void setSecondaryProgress(int);
+    method public static android.app.ProgressDialog show(android.content.Context, java.lang.CharSequence, java.lang.CharSequence);
+    method public static android.app.ProgressDialog show(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, boolean);
+    method public static android.app.ProgressDialog show(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, boolean, boolean);
+    method public static android.app.ProgressDialog show(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, boolean, boolean, android.content.DialogInterface.OnCancelListener);
+    field public static final int STYLE_HORIZONTAL = 1; // 0x1
+    field public static final int STYLE_SPINNER = 0; // 0x0
+  }
+
+  public class SearchManager implements android.content.DialogInterface.OnCancelListener android.content.DialogInterface.OnDismissListener {
+    method public android.content.ComponentName getGlobalSearchActivity();
+    method public android.app.SearchableInfo getSearchableInfo(android.content.ComponentName);
+    method public java.util.List<android.app.SearchableInfo> getSearchablesInGlobalSearch();
+    method public deprecated void onCancel(android.content.DialogInterface);
+    method public deprecated void onDismiss(android.content.DialogInterface);
+    method public void setOnCancelListener(android.app.SearchManager.OnCancelListener);
+    method public void setOnDismissListener(android.app.SearchManager.OnDismissListener);
+    method public void startSearch(java.lang.String, boolean, android.content.ComponentName, android.os.Bundle, boolean);
+    method public void stopSearch();
+    method public void triggerSearch(java.lang.String, android.content.ComponentName, android.os.Bundle);
+    field public static final java.lang.String ACTION_KEY = "action_key";
+    field public static final java.lang.String ACTION_MSG = "action_msg";
+    field public static final java.lang.String APP_DATA = "app_data";
+    field public static final java.lang.String CURSOR_EXTRA_KEY_IN_PROGRESS = "in_progress";
+    field public static final java.lang.String EXTRA_DATA_KEY = "intent_extra_data_key";
+    field public static final java.lang.String EXTRA_NEW_SEARCH = "new_search";
+    field public static final java.lang.String EXTRA_SELECT_QUERY = "select_query";
+    field public static final java.lang.String EXTRA_WEB_SEARCH_PENDINGINTENT = "web_search_pendingintent";
+    field public static final int FLAG_QUERY_REFINEMENT = 1; // 0x1
+    field public static final java.lang.String INTENT_ACTION_GLOBAL_SEARCH = "android.search.action.GLOBAL_SEARCH";
+    field public static final java.lang.String INTENT_ACTION_SEARCHABLES_CHANGED = "android.search.action.SEARCHABLES_CHANGED";
+    field public static final java.lang.String INTENT_ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
+    field public static final java.lang.String INTENT_ACTION_SEARCH_SETTINGS_CHANGED = "android.search.action.SETTINGS_CHANGED";
+    field public static final java.lang.String INTENT_ACTION_WEB_SEARCH_SETTINGS = "android.search.action.WEB_SEARCH_SETTINGS";
+    field public static final java.lang.String INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED = "android.search.action.GLOBAL_SEARCH_ACTIVITY_CHANGED";
+    field public static final char MENU_KEY = 115; // 0x0073 's'
+    field public static final int MENU_KEYCODE = 47; // 0x2f
+    field public static final java.lang.String QUERY = "query";
+    field public static final java.lang.String SHORTCUT_MIME_TYPE = "vnd.android.cursor.item/vnd.android.search.suggest";
+    field public static final java.lang.String SUGGEST_COLUMN_FLAGS = "suggest_flags";
+    field public static final java.lang.String SUGGEST_COLUMN_FORMAT = "suggest_format";
+    field public static final java.lang.String SUGGEST_COLUMN_ICON_1 = "suggest_icon_1";
+    field public static final java.lang.String SUGGEST_COLUMN_ICON_2 = "suggest_icon_2";
+    field public static final java.lang.String SUGGEST_COLUMN_INTENT_ACTION = "suggest_intent_action";
+    field public static final java.lang.String SUGGEST_COLUMN_INTENT_DATA = "suggest_intent_data";
+    field public static final java.lang.String SUGGEST_COLUMN_INTENT_DATA_ID = "suggest_intent_data_id";
+    field public static final java.lang.String SUGGEST_COLUMN_INTENT_EXTRA_DATA = "suggest_intent_extra_data";
+    field public static final java.lang.String SUGGEST_COLUMN_LAST_ACCESS_HINT = "suggest_last_access_hint";
+    field public static final java.lang.String SUGGEST_COLUMN_QUERY = "suggest_intent_query";
+    field public static final java.lang.String SUGGEST_COLUMN_SHORTCUT_ID = "suggest_shortcut_id";
+    field public static final java.lang.String SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING = "suggest_spinner_while_refreshing";
+    field public static final java.lang.String SUGGEST_COLUMN_TEXT_1 = "suggest_text_1";
+    field public static final java.lang.String SUGGEST_COLUMN_TEXT_2 = "suggest_text_2";
+    field public static final java.lang.String SUGGEST_COLUMN_TEXT_2_URL = "suggest_text_2_url";
+    field public static final java.lang.String SUGGEST_MIME_TYPE = "vnd.android.cursor.dir/vnd.android.search.suggest";
+    field public static final java.lang.String SUGGEST_NEVER_MAKE_SHORTCUT = "_-1";
+    field public static final java.lang.String SUGGEST_PARAMETER_LIMIT = "limit";
+    field public static final java.lang.String SUGGEST_URI_PATH_QUERY = "search_suggest_query";
+    field public static final java.lang.String SUGGEST_URI_PATH_SHORTCUT = "search_suggest_shortcut";
+    field public static final java.lang.String USER_QUERY = "user_query";
+  }
+
+  public static abstract interface SearchManager.OnCancelListener {
+    method public abstract void onCancel();
+  }
+
+  public static abstract interface SearchManager.OnDismissListener {
+    method public abstract void onDismiss();
+  }
+
+  public final class SearchableInfo implements android.os.Parcelable {
+    method public boolean autoUrlDetect();
+    method public int describeContents();
+    method public int getHintId();
+    method public int getImeOptions();
+    method public int getInputType();
+    method public android.content.ComponentName getSearchActivity();
+    method public int getSettingsDescriptionId();
+    method public java.lang.String getSuggestAuthority();
+    method public java.lang.String getSuggestIntentAction();
+    method public java.lang.String getSuggestIntentData();
+    method public java.lang.String getSuggestPackage();
+    method public java.lang.String getSuggestPath();
+    method public java.lang.String getSuggestSelection();
+    method public int getSuggestThreshold();
+    method public int getVoiceLanguageId();
+    method public int getVoiceLanguageModeId();
+    method public int getVoiceMaxResults();
+    method public int getVoicePromptTextId();
+    method public boolean getVoiceSearchEnabled();
+    method public boolean getVoiceSearchLaunchRecognizer();
+    method public boolean getVoiceSearchLaunchWebSearch();
+    method public boolean queryAfterZeroResults();
+    method public boolean shouldIncludeInGlobalSearch();
+    method public boolean shouldRewriteQueryFromData();
+    method public boolean shouldRewriteQueryFromText();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public abstract class Service extends android.content.ContextWrapper implements android.content.ComponentCallbacks2 {
+    ctor public Service();
+    method protected void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public final android.app.Application getApplication();
+    method public abstract android.os.IBinder onBind(android.content.Intent);
+    method public void onConfigurationChanged(android.content.res.Configuration);
+    method public void onCreate();
+    method public void onDestroy();
+    method public void onLowMemory();
+    method public void onRebind(android.content.Intent);
+    method public deprecated void onStart(android.content.Intent, int);
+    method public int onStartCommand(android.content.Intent, int, int);
+    method public void onTaskRemoved(android.content.Intent);
+    method public void onTrimMemory(int);
+    method public boolean onUnbind(android.content.Intent);
+    method public final void startForeground(int, android.app.Notification);
+    method public final void stopForeground(boolean);
+    method public final void stopSelf();
+    method public final void stopSelf(int);
+    method public final boolean stopSelfResult(int);
+    field public static final int START_CONTINUATION_MASK = 15; // 0xf
+    field public static final int START_FLAG_REDELIVERY = 1; // 0x1
+    field public static final int START_FLAG_RETRY = 2; // 0x2
+    field public static final int START_NOT_STICKY = 2; // 0x2
+    field public static final int START_REDELIVER_INTENT = 3; // 0x3
+    field public static final int START_STICKY = 1; // 0x1
+    field public static final int START_STICKY_COMPATIBILITY = 0; // 0x0
+  }
+
+  public deprecated class TabActivity extends android.app.ActivityGroup {
+    ctor public TabActivity();
+    method public android.widget.TabHost getTabHost();
+    method public android.widget.TabWidget getTabWidget();
+    method public void setDefaultTab(java.lang.String);
+    method public void setDefaultTab(int);
+  }
+
+  public class TaskStackBuilder {
+    method public android.app.TaskStackBuilder addNextIntent(android.content.Intent);
+    method public android.app.TaskStackBuilder addNextIntentWithParentStack(android.content.Intent);
+    method public android.app.TaskStackBuilder addParentStack(android.app.Activity);
+    method public android.app.TaskStackBuilder addParentStack(java.lang.Class<?>);
+    method public android.app.TaskStackBuilder addParentStack(android.content.ComponentName);
+    method public static android.app.TaskStackBuilder create(android.content.Context);
+    method public android.content.Intent editIntentAt(int);
+    method public int getIntentCount();
+    method public android.content.Intent[] getIntents();
+    method public android.app.PendingIntent getPendingIntent(int, int);
+    method public android.app.PendingIntent getPendingIntent(int, int, android.os.Bundle);
+    method public void startActivities();
+    method public void startActivities(android.os.Bundle);
+  }
+
+  public class TimePickerDialog extends android.app.AlertDialog implements android.content.DialogInterface.OnClickListener android.widget.TimePicker.OnTimeChangedListener {
+    ctor public TimePickerDialog(android.content.Context, android.app.TimePickerDialog.OnTimeSetListener, int, int, boolean);
+    ctor public TimePickerDialog(android.content.Context, int, android.app.TimePickerDialog.OnTimeSetListener, int, int, boolean);
+    method public void onClick(android.content.DialogInterface, int);
+    method public void onTimeChanged(android.widget.TimePicker, int, int);
+    method public void updateTime(int, int);
+  }
+
+  public static abstract interface TimePickerDialog.OnTimeSetListener {
+    method public abstract void onTimeSet(android.widget.TimePicker, int, int);
+  }
+
+  public class UiModeManager {
+    method public void disableCarMode(int);
+    method public void enableCarMode(int);
+    method public int getCurrentModeType();
+    method public int getNightMode();
+    method public void setNightMode(int);
+    field public static java.lang.String ACTION_ENTER_CAR_MODE;
+    field public static java.lang.String ACTION_ENTER_DESK_MODE;
+    field public static java.lang.String ACTION_EXIT_CAR_MODE;
+    field public static java.lang.String ACTION_EXIT_DESK_MODE;
+    field public static final int DISABLE_CAR_MODE_GO_HOME = 1; // 0x1
+    field public static final int ENABLE_CAR_MODE_GO_CAR_HOME = 1; // 0x1
+    field public static final int MODE_NIGHT_AUTO = 0; // 0x0
+    field public static final int MODE_NIGHT_NO = 1; // 0x1
+    field public static final int MODE_NIGHT_YES = 2; // 0x2
+  }
+
+  public final class WallpaperInfo implements android.os.Parcelable {
+    ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public int describeContents();
+    method public void dump(android.util.Printer, java.lang.String);
+    method public android.content.ComponentName getComponent();
+    method public java.lang.String getPackageName();
+    method public android.content.pm.ServiceInfo getServiceInfo();
+    method public java.lang.String getServiceName();
+    method public java.lang.String getSettingsActivity();
+    method public java.lang.CharSequence loadAuthor(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException;
+    method public java.lang.CharSequence loadDescription(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException;
+    method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
+    method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
+    method public android.graphics.drawable.Drawable loadThumbnail(android.content.pm.PackageManager);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class WallpaperManager {
+    method public void clear() throws java.io.IOException;
+    method public void clearWallpaperOffsets(android.os.IBinder);
+    method public void forgetLoadedWallpaper();
+    method public int getDesiredMinimumHeight();
+    method public int getDesiredMinimumWidth();
+    method public android.graphics.drawable.Drawable getDrawable();
+    method public android.graphics.drawable.Drawable getFastDrawable();
+    method public static android.app.WallpaperManager getInstance(android.content.Context);
+    method public android.app.WallpaperInfo getWallpaperInfo();
+    method public boolean hasResourceWallpaper(int);
+    method public android.graphics.drawable.Drawable peekDrawable();
+    method public android.graphics.drawable.Drawable peekFastDrawable();
+    method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle);
+    method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException;
+    method public void setResource(int) throws java.io.IOException;
+    method public void setStream(java.io.InputStream) throws java.io.IOException;
+    method public void setWallpaperOffsetSteps(float, float);
+    method public void setWallpaperOffsets(android.os.IBinder, float, float);
+    method public void suggestDesiredDimensions(int, int);
+    field public static final java.lang.String ACTION_CHANGE_LIVE_WALLPAPER = "android.service.wallpaper.CHANGE_LIVE_WALLPAPER";
+    field public static final java.lang.String ACTION_LIVE_WALLPAPER_CHOOSER = "android.service.wallpaper.LIVE_WALLPAPER_CHOOSER";
+    field public static final java.lang.String COMMAND_DROP = "android.home.drop";
+    field public static final java.lang.String COMMAND_SECONDARY_TAP = "android.wallpaper.secondaryTap";
+    field public static final java.lang.String COMMAND_TAP = "android.wallpaper.tap";
+    field public static final java.lang.String EXTRA_LIVE_WALLPAPER_COMPONENT = "android.service.wallpaper.extra.LIVE_WALLPAPER_COMPONENT";
+    field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview";
+  }
+
+}
+
+package android.app.admin {
+
+  public final class DeviceAdminInfo implements android.os.Parcelable {
+    ctor public DeviceAdminInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public int describeContents();
+    method public void dump(android.util.Printer, java.lang.String);
+    method public android.content.pm.ActivityInfo getActivityInfo();
+    method public android.content.ComponentName getComponent();
+    method public java.lang.String getPackageName();
+    method public java.lang.String getReceiverName();
+    method public java.lang.String getTagForPolicy(int);
+    method public boolean isVisible();
+    method public java.lang.CharSequence loadDescription(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException;
+    method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
+    method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
+    method public boolean usesPolicy(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int USES_ENCRYPTED_STORAGE = 7; // 0x7
+    field public static final int USES_POLICY_DISABLE_CAMERA = 8; // 0x8
+    field public static final int USES_POLICY_DISABLE_KEYGUARD_FEATURES = 9; // 0x9
+    field public static final int USES_POLICY_EXPIRE_PASSWORD = 6; // 0x6
+    field public static final int USES_POLICY_FORCE_LOCK = 3; // 0x3
+    field public static final int USES_POLICY_LIMIT_PASSWORD = 0; // 0x0
+    field public static final int USES_POLICY_RESET_PASSWORD = 2; // 0x2
+    field public static final int USES_POLICY_WATCH_LOGIN = 1; // 0x1
+    field public static final int USES_POLICY_WIPE_DATA = 4; // 0x4
+  }
+
+  public class DeviceAdminReceiver extends android.content.BroadcastReceiver {
+    ctor public DeviceAdminReceiver();
+    method public android.app.admin.DevicePolicyManager getManager(android.content.Context);
+    method public android.content.ComponentName getWho(android.content.Context);
+    method public java.lang.CharSequence onDisableRequested(android.content.Context, android.content.Intent);
+    method public void onDisabled(android.content.Context, android.content.Intent);
+    method public void onEnabled(android.content.Context, android.content.Intent);
+    method public void onPasswordChanged(android.content.Context, android.content.Intent);
+    method public void onPasswordExpiring(android.content.Context, android.content.Intent);
+    method public void onPasswordFailed(android.content.Context, android.content.Intent);
+    method public void onPasswordSucceeded(android.content.Context, android.content.Intent);
+    method public void onReceive(android.content.Context, android.content.Intent);
+    field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED";
+    field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED";
+    field public static final java.lang.String ACTION_DEVICE_ADMIN_ENABLED = "android.app.action.DEVICE_ADMIN_ENABLED";
+    field public static final java.lang.String ACTION_PASSWORD_CHANGED = "android.app.action.ACTION_PASSWORD_CHANGED";
+    field public static final java.lang.String ACTION_PASSWORD_EXPIRING = "android.app.action.ACTION_PASSWORD_EXPIRING";
+    field public static final java.lang.String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED";
+    field public static final java.lang.String ACTION_PASSWORD_SUCCEEDED = "android.app.action.ACTION_PASSWORD_SUCCEEDED";
+    field public static final java.lang.String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
+    field public static final java.lang.String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING";
+  }
+
+  public class DevicePolicyManager {
+    method public java.util.List<android.content.ComponentName> getActiveAdmins();
+    method public boolean getCameraDisabled(android.content.ComponentName);
+    method public int getCurrentFailedPasswordAttempts();
+    method public int getKeyguardDisabledFeatures(android.content.ComponentName);
+    method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
+    method public long getMaximumTimeToLock(android.content.ComponentName);
+    method public long getPasswordExpiration(android.content.ComponentName);
+    method public long getPasswordExpirationTimeout(android.content.ComponentName);
+    method public int getPasswordHistoryLength(android.content.ComponentName);
+    method public int getPasswordMaximumLength(int);
+    method public int getPasswordMinimumLength(android.content.ComponentName);
+    method public int getPasswordMinimumLetters(android.content.ComponentName);
+    method public int getPasswordMinimumLowerCase(android.content.ComponentName);
+    method public int getPasswordMinimumNonLetter(android.content.ComponentName);
+    method public int getPasswordMinimumNumeric(android.content.ComponentName);
+    method public int getPasswordMinimumSymbols(android.content.ComponentName);
+    method public int getPasswordMinimumUpperCase(android.content.ComponentName);
+    method public int getPasswordQuality(android.content.ComponentName);
+    method public boolean getStorageEncryption(android.content.ComponentName);
+    method public int getStorageEncryptionStatus();
+    method public boolean hasGrantedPolicy(android.content.ComponentName, int);
+    method public boolean isActivePasswordSufficient();
+    method public boolean isAdminActive(android.content.ComponentName);
+    method public void lockNow();
+    method public void removeActiveAdmin(android.content.ComponentName);
+    method public boolean resetPassword(java.lang.String, int);
+    method public void setCameraDisabled(android.content.ComponentName, boolean);
+    method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
+    method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
+    method public void setMaximumTimeToLock(android.content.ComponentName, long);
+    method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
+    method public void setPasswordHistoryLength(android.content.ComponentName, int);
+    method public void setPasswordMinimumLength(android.content.ComponentName, int);
+    method public void setPasswordMinimumLetters(android.content.ComponentName, int);
+    method public void setPasswordMinimumLowerCase(android.content.ComponentName, int);
+    method public void setPasswordMinimumNonLetter(android.content.ComponentName, int);
+    method public void setPasswordMinimumNumeric(android.content.ComponentName, int);
+    method public void setPasswordMinimumSymbols(android.content.ComponentName, int);
+    method public void setPasswordMinimumUpperCase(android.content.ComponentName, int);
+    method public void setPasswordQuality(android.content.ComponentName, int);
+    method public int setStorageEncryption(android.content.ComponentName, boolean);
+    method public void wipeData(int);
+    field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
+    field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD";
+    field public static final java.lang.String ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION";
+    field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
+    field public static final int ENCRYPTION_STATUS_ACTIVE = 3; // 0x3
+    field public static final int ENCRYPTION_STATUS_INACTIVE = 1; // 0x1
+    field public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0; // 0x0
+    field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
+    field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
+    field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff
+    field public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0; // 0x0
+    field public static final int KEYGUARD_DISABLE_SECURE_CAMERA = 2; // 0x2
+    field public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1; // 0x1
+    field public static final int PASSWORD_QUALITY_ALPHABETIC = 262144; // 0x40000
+    field public static final int PASSWORD_QUALITY_ALPHANUMERIC = 327680; // 0x50000
+    field public static final int PASSWORD_QUALITY_BIOMETRIC_WEAK = 32768; // 0x8000
+    field public static final int PASSWORD_QUALITY_COMPLEX = 393216; // 0x60000
+    field public static final int PASSWORD_QUALITY_NUMERIC = 131072; // 0x20000
+    field public static final int PASSWORD_QUALITY_SOMETHING = 65536; // 0x10000
+    field public static final int PASSWORD_QUALITY_UNSPECIFIED = 0; // 0x0
+    field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
+    field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1
+  }
+
+}
+
+package android.app.backup {
+
+  public abstract class BackupAgent extends android.content.ContextWrapper {
+    ctor public BackupAgent();
+    method public final void fullBackupFile(java.io.File, android.app.backup.FullBackupDataOutput);
+    method public abstract void onBackup(android.os.ParcelFileDescriptor, android.app.backup.BackupDataOutput, android.os.ParcelFileDescriptor) throws java.io.IOException;
+    method public void onCreate();
+    method public void onDestroy();
+    method public void onFullBackup(android.app.backup.FullBackupDataOutput) throws java.io.IOException;
+    method public abstract void onRestore(android.app.backup.BackupDataInput, int, android.os.ParcelFileDescriptor) throws java.io.IOException;
+    method public void onRestoreFile(android.os.ParcelFileDescriptor, long, java.io.File, int, long, long) throws java.io.IOException;
+    field public static final int TYPE_DIRECTORY = 2; // 0x2
+    field public static final int TYPE_FILE = 1; // 0x1
+  }
+
+  public class BackupAgentHelper extends android.app.backup.BackupAgent {
+    ctor public BackupAgentHelper();
+    method public void addHelper(java.lang.String, android.app.backup.BackupHelper);
+    method public void onBackup(android.os.ParcelFileDescriptor, android.app.backup.BackupDataOutput, android.os.ParcelFileDescriptor) throws java.io.IOException;
+    method public void onRestore(android.app.backup.BackupDataInput, int, android.os.ParcelFileDescriptor) throws java.io.IOException;
+  }
+
+  public class BackupDataInput {
+    method public int getDataSize();
+    method public java.lang.String getKey();
+    method public int readEntityData(byte[], int, int) throws java.io.IOException;
+    method public boolean readNextHeader() throws java.io.IOException;
+    method public void skipEntityData() throws java.io.IOException;
+  }
+
+  public class BackupDataInputStream extends java.io.InputStream {
+    method public java.lang.String getKey();
+    method public int read() throws java.io.IOException;
+    method public int size();
+  }
+
+  public class BackupDataOutput {
+    method public int writeEntityData(byte[], int) throws java.io.IOException;
+    method public int writeEntityHeader(java.lang.String, int) throws java.io.IOException;
+  }
+
+  public abstract interface BackupHelper {
+    method public abstract void performBackup(android.os.ParcelFileDescriptor, android.app.backup.BackupDataOutput, android.os.ParcelFileDescriptor);
+    method public abstract void restoreEntity(android.app.backup.BackupDataInputStream);
+    method public abstract void writeNewStateDescription(android.os.ParcelFileDescriptor);
+  }
+
+  public class BackupManager {
+    ctor public BackupManager(android.content.Context);
+    method public void dataChanged();
+    method public static void dataChanged(java.lang.String);
+    method public int requestRestore(android.app.backup.RestoreObserver);
+  }
+
+  public class FileBackupHelper extends android.app.backup.FileBackupHelperBase implements android.app.backup.BackupHelper {
+    ctor public FileBackupHelper(android.content.Context, java.lang.String...);
+    method public void performBackup(android.os.ParcelFileDescriptor, android.app.backup.BackupDataOutput, android.os.ParcelFileDescriptor);
+    method public void restoreEntity(android.app.backup.BackupDataInputStream);
+  }
+
+   class FileBackupHelperBase {
+    method public void writeNewStateDescription(android.os.ParcelFileDescriptor);
+  }
+
+  public class FullBackupDataOutput {
+  }
+
+  public abstract class RestoreObserver {
+    ctor public RestoreObserver();
+    method public void onUpdate(int, java.lang.String);
+    method public void restoreFinished(int);
+    method public void restoreStarting(int);
+  }
+
+  public class SharedPreferencesBackupHelper extends android.app.backup.FileBackupHelperBase implements android.app.backup.BackupHelper {
+    ctor public SharedPreferencesBackupHelper(android.content.Context, java.lang.String...);
+    method public void performBackup(android.os.ParcelFileDescriptor, android.app.backup.BackupDataOutput, android.os.ParcelFileDescriptor);
+    method public void restoreEntity(android.app.backup.BackupDataInputStream);
+  }
+
+}
+
+package android.appwidget {
+
+  public class AppWidgetHost {
+    ctor public AppWidgetHost(android.content.Context, int);
+    method public int allocateAppWidgetId();
+    method protected void clearViews();
+    method public final android.appwidget.AppWidgetHostView createView(android.content.Context, int, android.appwidget.AppWidgetProviderInfo);
+    method public static void deleteAllHosts();
+    method public void deleteAppWidgetId(int);
+    method public void deleteHost();
+    method protected android.appwidget.AppWidgetHostView onCreateView(android.content.Context, int, android.appwidget.AppWidgetProviderInfo);
+    method protected void onProviderChanged(int, android.appwidget.AppWidgetProviderInfo);
+    method protected void onProvidersChanged();
+    method public void startListening();
+    method public void stopListening();
+  }
+
+  public class AppWidgetHostView extends android.widget.FrameLayout {
+    ctor public AppWidgetHostView(android.content.Context);
+    ctor public AppWidgetHostView(android.content.Context, int, int);
+    method public int getAppWidgetId();
+    method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo();
+    method public static android.graphics.Rect getDefaultPaddingForWidget(android.content.Context, android.content.ComponentName, android.graphics.Rect);
+    method protected android.view.View getDefaultView();
+    method protected android.view.View getErrorView();
+    method protected void prepareView(android.view.View);
+    method public void setAppWidget(int, android.appwidget.AppWidgetProviderInfo);
+    method public void updateAppWidget(android.widget.RemoteViews);
+    method public void updateAppWidgetOptions(android.os.Bundle);
+    method public void updateAppWidgetSize(android.os.Bundle, int, int, int, int);
+  }
+
+  public class AppWidgetManager {
+    method public boolean bindAppWidgetIdIfAllowed(int, android.content.ComponentName);
+    method public boolean bindAppWidgetIdIfAllowed(int, android.content.ComponentName, android.os.Bundle);
+    method public int[] getAppWidgetIds(android.content.ComponentName);
+    method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
+    method public android.os.Bundle getAppWidgetOptions(int);
+    method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
+    method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
+    method public void notifyAppWidgetViewDataChanged(int[], int);
+    method public void notifyAppWidgetViewDataChanged(int, int);
+    method public void partiallyUpdateAppWidget(int[], android.widget.RemoteViews);
+    method public void partiallyUpdateAppWidget(int, android.widget.RemoteViews);
+    method public void updateAppWidget(int[], android.widget.RemoteViews);
+    method public void updateAppWidget(int, android.widget.RemoteViews);
+    method public void updateAppWidget(android.content.ComponentName, android.widget.RemoteViews);
+    method public void updateAppWidgetOptions(int, android.os.Bundle);
+    field public static final java.lang.String ACTION_APPWIDGET_BIND = "android.appwidget.action.APPWIDGET_BIND";
+    field public static final java.lang.String ACTION_APPWIDGET_CONFIGURE = "android.appwidget.action.APPWIDGET_CONFIGURE";
+    field public static final java.lang.String ACTION_APPWIDGET_DELETED = "android.appwidget.action.APPWIDGET_DELETED";
+    field public static final java.lang.String ACTION_APPWIDGET_DISABLED = "android.appwidget.action.APPWIDGET_DISABLED";
+    field public static final java.lang.String ACTION_APPWIDGET_ENABLED = "android.appwidget.action.APPWIDGET_ENABLED";
+    field public static final java.lang.String ACTION_APPWIDGET_OPTIONS_CHANGED = "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS";
+    field public static final java.lang.String ACTION_APPWIDGET_PICK = "android.appwidget.action.APPWIDGET_PICK";
+    field public static final java.lang.String ACTION_APPWIDGET_UPDATE = "android.appwidget.action.APPWIDGET_UPDATE";
+    field public static final java.lang.String EXTRA_APPWIDGET_ID = "appWidgetId";
+    field public static final java.lang.String EXTRA_APPWIDGET_IDS = "appWidgetIds";
+    field public static final java.lang.String EXTRA_APPWIDGET_OPTIONS = "appWidgetOptions";
+    field public static final java.lang.String EXTRA_APPWIDGET_PROVIDER = "appWidgetProvider";
+    field public static final java.lang.String EXTRA_CUSTOM_EXTRAS = "customExtras";
+    field public static final java.lang.String EXTRA_CUSTOM_INFO = "customInfo";
+    field public static final int INVALID_APPWIDGET_ID = 0; // 0x0
+    field public static final java.lang.String META_DATA_APPWIDGET_PROVIDER = "android.appwidget.provider";
+    field public static final java.lang.String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory";
+    field public static final java.lang.String OPTION_APPWIDGET_MAX_HEIGHT = "appWidgetMaxHeight";
+    field public static final java.lang.String OPTION_APPWIDGET_MAX_WIDTH = "appWidgetMaxWidth";
+    field public static final java.lang.String OPTION_APPWIDGET_MIN_HEIGHT = "appWidgetMinHeight";
+    field public static final java.lang.String OPTION_APPWIDGET_MIN_WIDTH = "appWidgetMinWidth";
+  }
+
+  public class AppWidgetProvider extends android.content.BroadcastReceiver {
+    ctor public AppWidgetProvider();
+    method public void onAppWidgetOptionsChanged(android.content.Context, android.appwidget.AppWidgetManager, int, android.os.Bundle);
+    method public void onDeleted(android.content.Context, int[]);
+    method public void onDisabled(android.content.Context);
+    method public void onEnabled(android.content.Context);
+    method public void onReceive(android.content.Context, android.content.Intent);
+    method public void onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]);
+  }
+
+  public class AppWidgetProviderInfo implements android.os.Parcelable {
+    ctor public AppWidgetProviderInfo();
+    ctor public AppWidgetProviderInfo(android.os.Parcel);
+    method public android.appwidget.AppWidgetProviderInfo clone();
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int RESIZE_BOTH = 3; // 0x3
+    field public static final int RESIZE_HORIZONTAL = 1; // 0x1
+    field public static final int RESIZE_NONE = 0; // 0x0
+    field public static final int RESIZE_VERTICAL = 2; // 0x2
+    field public static final int WIDGET_CATEGORY_HOME_SCREEN = 1; // 0x1
+    field public static final int WIDGET_CATEGORY_KEYGUARD = 2; // 0x2
+    field public int autoAdvanceViewId;
+    field public android.content.ComponentName configure;
+    field public int icon;
+    field public int initialKeyguardLayout;
+    field public int initialLayout;
+    field public java.lang.String label;
+    field public int minHeight;
+    field public int minResizeHeight;
+    field public int minResizeWidth;
+    field public int minWidth;
+    field public int previewImage;
+    field public android.content.ComponentName provider;
+    field public int resizeMode;
+    field public int updatePeriodMillis;
+    field public int widgetCategory;
+  }
+
+}
+
+package android.bluetooth {
+
+  public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
+    method public void finalize();
+    method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+    method public int getConnectionState(android.bluetooth.BluetoothDevice);
+    method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
+    method public boolean isA2dpPlaying(android.bluetooth.BluetoothDevice);
+    field public static final java.lang.String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED";
+    field public static final java.lang.String ACTION_PLAYING_STATE_CHANGED = "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED";
+    field public static final int STATE_NOT_PLAYING = 11; // 0xb
+    field public static final int STATE_PLAYING = 10; // 0xa
+  }
+
+  public final class BluetoothAdapter {
+    method public boolean cancelDiscovery();
+    method public static boolean checkBluetoothAddress(java.lang.String);
+    method public void closeProfileProxy(int, android.bluetooth.BluetoothProfile);
+    method public boolean disable();
+    method public boolean enable();
+    method public java.lang.String getAddress();
+    method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
+    method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
+    method public java.lang.String getName();
+    method public int getProfileConnectionState(int);
+    method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
+    method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
+    method public android.bluetooth.BluetoothDevice getRemoteDevice(byte[]);
+    method public int getScanMode();
+    method public int getState();
+    method public boolean isDiscovering();
+    method public boolean isEnabled();
+    method public android.bluetooth.BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(java.lang.String, java.util.UUID) throws java.io.IOException;
+    method public android.bluetooth.BluetoothServerSocket listenUsingRfcommWithServiceRecord(java.lang.String, java.util.UUID) throws java.io.IOException;
+    method public boolean setName(java.lang.String);
+    method public boolean startDiscovery();
+    field public static final java.lang.String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
+    field public static final java.lang.String ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
+    field public static final java.lang.String ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";
+    field public static final java.lang.String ACTION_LOCAL_NAME_CHANGED = "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
+    field public static final java.lang.String ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
+    field public static final java.lang.String ACTION_REQUEST_ENABLE = "android.bluetooth.adapter.action.REQUEST_ENABLE";
+    field public static final java.lang.String ACTION_SCAN_MODE_CHANGED = "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
+    field public static final java.lang.String ACTION_STATE_CHANGED = "android.bluetooth.adapter.action.STATE_CHANGED";
+    field public static final int ERROR = -2147483648; // 0x80000000
+    field public static final java.lang.String EXTRA_CONNECTION_STATE = "android.bluetooth.adapter.extra.CONNECTION_STATE";
+    field public static final java.lang.String EXTRA_DISCOVERABLE_DURATION = "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
+    field public static final java.lang.String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
+    field public static final java.lang.String EXTRA_PREVIOUS_CONNECTION_STATE = "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE";
+    field public static final java.lang.String EXTRA_PREVIOUS_SCAN_MODE = "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
+    field public static final java.lang.String EXTRA_PREVIOUS_STATE = "android.bluetooth.adapter.extra.PREVIOUS_STATE";
+    field public static final java.lang.String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
+    field public static final java.lang.String EXTRA_STATE = "android.bluetooth.adapter.extra.STATE";
+    field public static final int SCAN_MODE_CONNECTABLE = 21; // 0x15
+    field public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23; // 0x17
+    field public static final int SCAN_MODE_NONE = 20; // 0x14
+    field public static final int STATE_CONNECTED = 2; // 0x2
+    field public static final int STATE_CONNECTING = 1; // 0x1
+    field public static final int STATE_DISCONNECTED = 0; // 0x0
+    field public static final int STATE_DISCONNECTING = 3; // 0x3
+    field public static final int STATE_OFF = 10; // 0xa
+    field public static final int STATE_ON = 12; // 0xc
+    field public static final int STATE_TURNING_OFF = 13; // 0xd
+    field public static final int STATE_TURNING_ON = 11; // 0xb
+  }
+
+  public class BluetoothAssignedNumbers {
+    field public static final int ACCEL_SEMICONDUCTOR = 74; // 0x4a
+    field public static final int ALCATEL = 36; // 0x24
+    field public static final int APPLE = 76; // 0x4c
+    field public static final int APT_LICENSING = 79; // 0x4f
+    field public static final int ATHEROS_COMMUNICATIONS = 69; // 0x45
+    field public static final int ATMEL = 19; // 0x13
+    field public static final int AVAGO = 78; // 0x4e
+    field public static final int AVM_BERLIN = 31; // 0x1f
+    field public static final int BANDSPEED = 32; // 0x20
+    field public static final int BELKIN_INTERNATIONAL = 92; // 0x5c
+    field public static final int BLUEGIGA = 71; // 0x47
+    field public static final int BLUETOOTH_SIG = 63; // 0x3f
+    field public static final int BROADCOM = 15; // 0xf
+    field public static final int CAMBRIDGE_SILICON_RADIO = 10; // 0xa
+    field public static final int CATC = 52; // 0x34
+    field public static final int COMMIL = 51; // 0x33
+    field public static final int CONEXANT_SYSTEMS = 28; // 0x1c
+    field public static final int CONTINENTAL_AUTOMOTIVE = 75; // 0x4b
+    field public static final int CONWISE_TECHNOLOGY = 66; // 0x42
+    field public static final int C_TECHNOLOGIES = 38; // 0x26
+    field public static final int DIGIANSWER = 12; // 0xc
+    field public static final int ECLIPSE = 53; // 0x35
+    field public static final int EM_MICROELECTRONIC_MARIN = 90; // 0x5a
+    field public static final int ERICSSON_TECHNOLOGY = 0; // 0x0
+    field public static final int FREE2MOVE = 83; // 0x53
+    field public static final int GCT_SEMICONDUCTOR = 45; // 0x2d
+    field public static final int GENNUM = 59; // 0x3b
+    field public static final int HARMAN_INTERNATIONAL = 87; // 0x57
+    field public static final int HITACHI = 41; // 0x29
+    field public static final int IBM = 3; // 0x3
+    field public static final int INFINEON_TECHNOLOGIES = 9; // 0x9
+    field public static final int INTEGRATED_SILICON_SOLUTION = 65; // 0x41
+    field public static final int INTEGRATED_SYSTEM_SOLUTION = 57; // 0x39
+    field public static final int INTEL = 2; // 0x2
+    field public static final int INVENTEL = 30; // 0x1e
+    field public static final int IPEXTREME = 61; // 0x3d
+    field public static final int J_AND_M = 82; // 0x52
+    field public static final int KC_TECHNOLOGY = 22; // 0x16
+    field public static final int LUCENT = 7; // 0x7
+    field public static final int MACRONIX = 44; // 0x2c
+    field public static final int MANSELLA = 33; // 0x21
+    field public static final int MARVELL = 72; // 0x48
+    field public static final int MATSUSHITA_ELECTRIC = 58; // 0x3a
+    field public static final int MEDIATEK = 70; // 0x46
+    field public static final int MEWTEL_TECHNOLOGY = 47; // 0x2f
+    field public static final int MICROSOFT = 6; // 0x6
+    field public static final int MITEL_SEMICONDUCTOR = 16; // 0x10
+    field public static final int MITSUBISHI_ELECTRIC = 20; // 0x14
+    field public static final int MOBILIAN_CORPORATION = 55; // 0x37
+    field public static final int MOTOROLA = 8; // 0x8
+    field public static final int NEC = 34; // 0x22
+    field public static final int NEWLOGIC = 23; // 0x17
+    field public static final int NOKIA_MOBILE_PHONES = 1; // 0x1
+    field public static final int NORDIC_SEMICONDUCTOR = 89; // 0x59
+    field public static final int NORWOOD_SYSTEMS = 46; // 0x2e
+    field public static final int OPEN_INTERFACE = 39; // 0x27
+    field public static final int PARROT = 67; // 0x43
+    field public static final int PARTHUS_TECHNOLOGIES = 14; // 0xe
+    field public static final int PHILIPS_SEMICONDUCTORS = 37; // 0x25
+    field public static final int PLANTRONICS = 85; // 0x55
+    field public static final int QUALCOMM = 29; // 0x1d
+    field public static final int RALINK_TECHNOLOGY = 91; // 0x5b
+    field public static final int REALTEK_SEMICONDUCTOR = 93; // 0x5d
+    field public static final int RED_M = 50; // 0x32
+    field public static final int RENESAS_TECHNOLOGY = 54; // 0x36
+    field public static final int RESEARCH_IN_MOTION = 60; // 0x3c
+    field public static final int RF_MICRO_DEVICES = 40; // 0x28
+    field public static final int RIVIERAWAVES = 96; // 0x60
+    field public static final int ROHDE_AND_SCHWARZ = 25; // 0x19
+    field public static final int RTX_TELECOM = 21; // 0x15
+    field public static final int SEIKO_EPSON = 64; // 0x40
+    field public static final int SIGNIA_TECHNOLOGIES = 27; // 0x1b
+    field public static final int SILICON_WAVE = 11; // 0xb
+    field public static final int SIRF_TECHNOLOGY = 80; // 0x50
+    field public static final int SOCKET_MOBILE = 68; // 0x44
+    field public static final int SONY_ERICSSON = 86; // 0x56
+    field public static final int STACCATO_COMMUNICATIONS = 77; // 0x4d
+    field public static final int STONESTREET_ONE = 94; // 0x5e
+    field public static final int ST_MICROELECTRONICS = 48; // 0x30
+    field public static final int SYMBOL_TECHNOLOGIES = 42; // 0x2a
+    field public static final int SYNOPSYS = 49; // 0x31
+    field public static final int SYSTEMS_AND_CHIPS = 62; // 0x3e
+    field public static final int TENOVIS = 43; // 0x2b
+    field public static final int TERAX = 56; // 0x38
+    field public static final int TEXAS_INSTRUMENTS = 13; // 0xd
+    field public static final int THREECOM = 5; // 0x5
+    field public static final int THREE_DIJOY = 84; // 0x54
+    field public static final int THREE_DSP = 73; // 0x49
+    field public static final int TOSHIBA = 4; // 0x4
+    field public static final int TRANSILICA = 24; // 0x18
+    field public static final int TTPCOM = 26; // 0x1a
+    field public static final int TZERO_TECHNOLOGIES = 81; // 0x51
+    field public static final int VIZIO = 88; // 0x58
+    field public static final int WAVEPLUS_TECHNOLOGY = 35; // 0x23
+    field public static final int WICENTRIC = 95; // 0x5f
+    field public static final int WIDCOMM = 17; // 0x11
+    field public static final int ZEEVO = 18; // 0x12
+  }
+
+  public final class BluetoothClass implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getDeviceClass();
+    method public int getMajorDeviceClass();
+    method public boolean hasService(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static class BluetoothClass.Device {
+    ctor public BluetoothClass.Device();
+    field public static final int AUDIO_VIDEO_CAMCORDER = 1076; // 0x434
+    field public static final int AUDIO_VIDEO_CAR_AUDIO = 1056; // 0x420
+    field public static final int AUDIO_VIDEO_HANDSFREE = 1032; // 0x408
+    field public static final int AUDIO_VIDEO_HEADPHONES = 1048; // 0x418
+    field public static final int AUDIO_VIDEO_HIFI_AUDIO = 1064; // 0x428
+    field public static final int AUDIO_VIDEO_LOUDSPEAKER = 1044; // 0x414
+    field public static final int AUDIO_VIDEO_MICROPHONE = 1040; // 0x410
+    field public static final int AUDIO_VIDEO_PORTABLE_AUDIO = 1052; // 0x41c
+    field public static final int AUDIO_VIDEO_SET_TOP_BOX = 1060; // 0x424
+    field public static final int AUDIO_VIDEO_UNCATEGORIZED = 1024; // 0x400
+    field public static final int AUDIO_VIDEO_VCR = 1068; // 0x42c
+    field public static final int AUDIO_VIDEO_VIDEO_CAMERA = 1072; // 0x430
+    field public static final int AUDIO_VIDEO_VIDEO_CONFERENCING = 1088; // 0x440
+    field public static final int AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER = 1084; // 0x43c
+    field public static final int AUDIO_VIDEO_VIDEO_GAMING_TOY = 1096; // 0x448
+    field public static final int AUDIO_VIDEO_VIDEO_MONITOR = 1080; // 0x438
+    field public static final int AUDIO_VIDEO_WEARABLE_HEADSET = 1028; // 0x404
+    field public static final int COMPUTER_DESKTOP = 260; // 0x104
+    field public static final int COMPUTER_HANDHELD_PC_PDA = 272; // 0x110
+    field public static final int COMPUTER_LAPTOP = 268; // 0x10c
+    field public static final int COMPUTER_PALM_SIZE_PC_PDA = 276; // 0x114
+    field public static final int COMPUTER_SERVER = 264; // 0x108
+    field public static final int COMPUTER_UNCATEGORIZED = 256; // 0x100
+    field public static final int COMPUTER_WEARABLE = 280; // 0x118
+    field public static final int HEALTH_BLOOD_PRESSURE = 2308; // 0x904
+    field public static final int HEALTH_DATA_DISPLAY = 2332; // 0x91c
+    field public static final int HEALTH_GLUCOSE = 2320; // 0x910
+    field public static final int HEALTH_PULSE_OXIMETER = 2324; // 0x914
+    field public static final int HEALTH_PULSE_RATE = 2328; // 0x918
+    field public static final int HEALTH_THERMOMETER = 2312; // 0x908
+    field public static final int HEALTH_UNCATEGORIZED = 2304; // 0x900
+    field public static final int HEALTH_WEIGHING = 2316; // 0x90c
+    field public static final int PHONE_CELLULAR = 516; // 0x204
+    field public static final int PHONE_CORDLESS = 520; // 0x208
+    field public static final int PHONE_ISDN = 532; // 0x214
+    field public static final int PHONE_MODEM_OR_GATEWAY = 528; // 0x210
+    field public static final int PHONE_SMART = 524; // 0x20c
+    field public static final int PHONE_UNCATEGORIZED = 512; // 0x200
+    field public static final int TOY_CONTROLLER = 2064; // 0x810
+    field public static final int TOY_DOLL_ACTION_FIGURE = 2060; // 0x80c
+    field public static final int TOY_GAME = 2068; // 0x814
+    field public static final int TOY_ROBOT = 2052; // 0x804
+    field public static final int TOY_UNCATEGORIZED = 2048; // 0x800
+    field public static final int TOY_VEHICLE = 2056; // 0x808
+    field public static final int WEARABLE_GLASSES = 1812; // 0x714
+    field public static final int WEARABLE_HELMET = 1808; // 0x710
+    field public static final int WEARABLE_JACKET = 1804; // 0x70c
+    field public static final int WEARABLE_PAGER = 1800; // 0x708
+    field public static final int WEARABLE_UNCATEGORIZED = 1792; // 0x700
+    field public static final int WEARABLE_WRIST_WATCH = 1796; // 0x704
+  }
+
+  public static class BluetoothClass.Device.Major {
+    ctor public BluetoothClass.Device.Major();
+    field public static final int AUDIO_VIDEO = 1024; // 0x400
+    field public static final int COMPUTER = 256; // 0x100
+    field public static final int HEALTH = 2304; // 0x900
+    field public static final int IMAGING = 1536; // 0x600
+    field public static final int MISC = 0; // 0x0
+    field public static final int NETWORKING = 768; // 0x300
+    field public static final int PERIPHERAL = 1280; // 0x500
+    field public static final int PHONE = 512; // 0x200
+    field public static final int TOY = 2048; // 0x800
+    field public static final int UNCATEGORIZED = 7936; // 0x1f00
+    field public static final int WEARABLE = 1792; // 0x700
+  }
+
+  public static final class BluetoothClass.Service {
+    ctor public BluetoothClass.Service();
+    field public static final int AUDIO = 2097152; // 0x200000
+    field public static final int CAPTURE = 524288; // 0x80000
+    field public static final int INFORMATION = 8388608; // 0x800000
+    field public static final int LIMITED_DISCOVERABILITY = 8192; // 0x2000
+    field public static final int NETWORKING = 131072; // 0x20000
+    field public static final int OBJECT_TRANSFER = 1048576; // 0x100000
+    field public static final int POSITIONING = 65536; // 0x10000
+    field public static final int RENDER = 262144; // 0x40000
+    field public static final int TELEPHONY = 4194304; // 0x400000
+  }
+
+  public final class BluetoothDevice implements android.os.Parcelable {
+    method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
+    method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
+    method public int describeContents();
+    method public boolean fetchUuidsWithSdp();
+    method public java.lang.String getAddress();
+    method public android.bluetooth.BluetoothClass getBluetoothClass();
+    method public int getBondState();
+    method public java.lang.String getName();
+    method public android.os.ParcelUuid[] getUuids();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final java.lang.String ACTION_ACL_CONNECTED = "android.bluetooth.device.action.ACL_CONNECTED";
+    field public static final java.lang.String ACTION_ACL_DISCONNECTED = "android.bluetooth.device.action.ACL_DISCONNECTED";
+    field public static final java.lang.String ACTION_ACL_DISCONNECT_REQUESTED = "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED";
+    field public static final java.lang.String ACTION_BOND_STATE_CHANGED = "android.bluetooth.device.action.BOND_STATE_CHANGED";
+    field public static final java.lang.String ACTION_CLASS_CHANGED = "android.bluetooth.device.action.CLASS_CHANGED";
+    field public static final java.lang.String ACTION_FOUND = "android.bluetooth.device.action.FOUND";
+    field public static final java.lang.String ACTION_NAME_CHANGED = "android.bluetooth.device.action.NAME_CHANGED";
+    field public static final java.lang.String ACTION_UUID = "android.bluetooth.device.action.UUID";
+    field public static final int BOND_BONDED = 12; // 0xc
+    field public static final int BOND_BONDING = 11; // 0xb
+    field public static final int BOND_NONE = 10; // 0xa
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int ERROR = -2147483648; // 0x80000000
+    field public static final java.lang.String EXTRA_BOND_STATE = "android.bluetooth.device.extra.BOND_STATE";
+    field public static final java.lang.String EXTRA_CLASS = "android.bluetooth.device.extra.CLASS";
+    field public static final java.lang.String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE";
+    field public static final java.lang.String EXTRA_NAME = "android.bluetooth.device.extra.NAME";
+    field public static final java.lang.String EXTRA_PREVIOUS_BOND_STATE = "android.bluetooth.device.extra.PREVIOUS_BOND_STATE";
+    field public static final java.lang.String EXTRA_RSSI = "android.bluetooth.device.extra.RSSI";
+    field public static final java.lang.String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
+  }
+
+  public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
+    method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+    method public int getConnectionState(android.bluetooth.BluetoothDevice);
+    method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
+    method public boolean isAudioConnected(android.bluetooth.BluetoothDevice);
+    method public boolean startVoiceRecognition(android.bluetooth.BluetoothDevice);
+    method public boolean stopVoiceRecognition(android.bluetooth.BluetoothDevice);
+    field public static final java.lang.String ACTION_AUDIO_STATE_CHANGED = "android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED";
+    field public static final java.lang.String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED";
+    field public static final java.lang.String ACTION_VENDOR_SPECIFIC_HEADSET_EVENT = "android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT";
+    field public static final int AT_CMD_TYPE_ACTION = 4; // 0x4
+    field public static final int AT_CMD_TYPE_BASIC = 3; // 0x3
+    field public static final int AT_CMD_TYPE_READ = 0; // 0x0
+    field public static final int AT_CMD_TYPE_SET = 2; // 0x2
+    field public static final int AT_CMD_TYPE_TEST = 1; // 0x1
+    field public static final java.lang.String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_ARGS";
+    field public static final java.lang.String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD";
+    field public static final java.lang.String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE";
+    field public static final int STATE_AUDIO_CONNECTED = 12; // 0xc
+    field public static final int STATE_AUDIO_CONNECTING = 11; // 0xb
+    field public static final int STATE_AUDIO_DISCONNECTED = 10; // 0xa
+    field public static final java.lang.String VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY = "android.bluetooth.headset.intent.category.companyid";
+  }
+
+  public final class BluetoothHealth implements android.bluetooth.BluetoothProfile {
+    method public boolean connectChannelToSource(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration);
+    method public boolean disconnectChannel(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration, int);
+    method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+    method public int getConnectionState(android.bluetooth.BluetoothDevice);
+    method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
+    method public android.os.ParcelFileDescriptor getMainChannelFd(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration);
+    method public boolean registerSinkAppConfiguration(java.lang.String, int, android.bluetooth.BluetoothHealthCallback);
+    method public boolean unregisterAppConfiguration(android.bluetooth.BluetoothHealthAppConfiguration);
+    field public static final int APP_CONFIG_REGISTRATION_FAILURE = 1; // 0x1
+    field public static final int APP_CONFIG_REGISTRATION_SUCCESS = 0; // 0x0
+    field public static final int APP_CONFIG_UNREGISTRATION_FAILURE = 3; // 0x3
+    field public static final int APP_CONFIG_UNREGISTRATION_SUCCESS = 2; // 0x2
+    field public static final int CHANNEL_TYPE_RELIABLE = 10; // 0xa
+    field public static final int CHANNEL_TYPE_STREAMING = 11; // 0xb
+    field public static final int SINK_ROLE = 2; // 0x2
+    field public static final int SOURCE_ROLE = 1; // 0x1
+    field public static final int STATE_CHANNEL_CONNECTED = 2; // 0x2
+    field public static final int STATE_CHANNEL_CONNECTING = 1; // 0x1
+    field public static final int STATE_CHANNEL_DISCONNECTED = 0; // 0x0
+    field public static final int STATE_CHANNEL_DISCONNECTING = 3; // 0x3
+  }
+
+  public final class BluetoothHealthAppConfiguration implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getDataType();
+    method public java.lang.String getName();
+    method public int getRole();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public abstract class BluetoothHealthCallback {
+    ctor public BluetoothHealthCallback();
+    method public void onHealthAppConfigurationStatusChange(android.bluetooth.BluetoothHealthAppConfiguration, int);
+    method public void onHealthChannelStateChange(android.bluetooth.BluetoothHealthAppConfiguration, android.bluetooth.BluetoothDevice, int, int, android.os.ParcelFileDescriptor, int);
+  }
+
+  public abstract interface BluetoothProfile {
+    method public abstract java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+    method public abstract int getConnectionState(android.bluetooth.BluetoothDevice);
+    method public abstract java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
+    field public static final int A2DP = 2; // 0x2
+    field public static final java.lang.String EXTRA_PREVIOUS_STATE = "android.bluetooth.profile.extra.PREVIOUS_STATE";
+    field public static final java.lang.String EXTRA_STATE = "android.bluetooth.profile.extra.STATE";
+    field public static final int HEADSET = 1; // 0x1
+    field public static final int HEALTH = 3; // 0x3
+    field public static final int STATE_CONNECTED = 2; // 0x2
+    field public static final int STATE_CONNECTING = 1; // 0x1
+    field public static final int STATE_DISCONNECTED = 0; // 0x0
+    field public static final int STATE_DISCONNECTING = 3; // 0x3
+  }
+
+  public static abstract interface BluetoothProfile.ServiceListener {
+    method public abstract void onServiceConnected(int, android.bluetooth.BluetoothProfile);
+    method public abstract void onServiceDisconnected(int);
+  }
+
+  public final class BluetoothServerSocket implements java.io.Closeable {
+    method public android.bluetooth.BluetoothSocket accept() throws java.io.IOException;
+    method public android.bluetooth.BluetoothSocket accept(int) throws java.io.IOException;
+    method public void close() throws java.io.IOException;
+  }
+
+  public final class BluetoothSocket implements java.io.Closeable {
+    method public void close() throws java.io.IOException;
+    method public void connect() throws java.io.IOException;
+    method public java.io.InputStream getInputStream() throws java.io.IOException;
+    method public java.io.OutputStream getOutputStream() throws java.io.IOException;
+    method public android.bluetooth.BluetoothDevice getRemoteDevice();
+    method public boolean isConnected();
+  }
+
+}
+
+package android.content {
+
+  public abstract class AbstractThreadedSyncAdapter {
+    ctor public AbstractThreadedSyncAdapter(android.content.Context, boolean);
+    ctor public AbstractThreadedSyncAdapter(android.content.Context, boolean, boolean);
+    method public android.content.Context getContext();
+    method public final android.os.IBinder getSyncAdapterBinder();
+    method public abstract void onPerformSync(android.accounts.Account, android.os.Bundle, java.lang.String, android.content.ContentProviderClient, android.content.SyncResult);
+    method public void onSyncCanceled();
+    method public void onSyncCanceled(java.lang.Thread);
+    field public static final deprecated int LOG_SYNC_DETAILS = 2743; // 0xab7
+  }
+
+  public class ActivityNotFoundException extends java.lang.RuntimeException {
+    ctor public ActivityNotFoundException();
+    ctor public ActivityNotFoundException(java.lang.String);
+  }
+
+  public abstract class AsyncQueryHandler extends android.os.Handler {
+    ctor public AsyncQueryHandler(android.content.ContentResolver);
+    method public final void cancelOperation(int);
+    method protected android.os.Handler createHandler(android.os.Looper);
+    method protected void onDeleteComplete(int, java.lang.Object, int);
+    method protected void onInsertComplete(int, java.lang.Object, android.net.Uri);
+    method protected void onQueryComplete(int, java.lang.Object, android.database.Cursor);
+    method protected void onUpdateComplete(int, java.lang.Object, int);
+    method public final void startDelete(int, java.lang.Object, android.net.Uri, java.lang.String, java.lang.String[]);
+    method public final void startInsert(int, java.lang.Object, android.net.Uri, android.content.ContentValues);
+    method public void startQuery(int, java.lang.Object, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
+    method public final void startUpdate(int, java.lang.Object, android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
+  }
+
+  protected static final class AsyncQueryHandler.WorkerArgs {
+    ctor protected AsyncQueryHandler.WorkerArgs();
+    field public java.lang.Object cookie;
+    field public android.os.Handler handler;
+    field public java.lang.String orderBy;
+    field public java.lang.String[] projection;
+    field public java.lang.Object result;
+    field public java.lang.String selection;
+    field public java.lang.String[] selectionArgs;
+    field public android.net.Uri uri;
+    field public android.content.ContentValues values;
+  }
+
+  protected class AsyncQueryHandler.WorkerHandler extends android.os.Handler {
+    ctor public AsyncQueryHandler.WorkerHandler(android.os.Looper);
+  }
+
+  public abstract class AsyncTaskLoader extends android.content.Loader {
+    ctor public AsyncTaskLoader(android.content.Context);
+    method public void cancelLoadInBackground();
+    method public boolean isLoadInBackgroundCanceled();
+    method public abstract D loadInBackground();
+    method public void onCanceled(D);
+    method protected D onLoadInBackground();
+    method public void setUpdateThrottle(long);
+  }
+
+  public abstract class BroadcastReceiver {
+    ctor public BroadcastReceiver();
+    method public final void abortBroadcast();
+    method public final void clearAbortBroadcast();
+    method public final boolean getAbortBroadcast();
+    method public final boolean getDebugUnregister();
+    method public final int getResultCode();
+    method public final java.lang.String getResultData();
+    method public final android.os.Bundle getResultExtras(boolean);
+    method public final android.content.BroadcastReceiver.PendingResult goAsync();
+    method public final boolean isInitialStickyBroadcast();
+    method public final boolean isOrderedBroadcast();
+    method public abstract void onReceive(android.content.Context, android.content.Intent);
+    method public android.os.IBinder peekService(android.content.Context, android.content.Intent);
+    method public final void setDebugUnregister(boolean);
+    method public final void setOrderedHint(boolean);
+    method public final void setResult(int, java.lang.String, android.os.Bundle);
+    method public final void setResultCode(int);
+    method public final void setResultData(java.lang.String);
+    method public final void setResultExtras(android.os.Bundle);
+  }
+
+  public static class BroadcastReceiver.PendingResult {
+    method public final void abortBroadcast();
+    method public final void clearAbortBroadcast();
+    method public final void finish();
+    method public final boolean getAbortBroadcast();
+    method public final int getResultCode();
+    method public final java.lang.String getResultData();
+    method public final android.os.Bundle getResultExtras(boolean);
+    method public final void setResult(int, java.lang.String, android.os.Bundle);
+    method public final void setResultCode(int);
+    method public final void setResultData(java.lang.String);
+    method public final void setResultExtras(android.os.Bundle);
+  }
+
+  public class ClipData implements android.os.Parcelable {
+    ctor public ClipData(java.lang.CharSequence, java.lang.String[], android.content.ClipData.Item);
+    ctor public ClipData(android.content.ClipDescription, android.content.ClipData.Item);
+    ctor public ClipData(android.content.ClipData);
+    method public void addItem(android.content.ClipData.Item);
+    method public int describeContents();
+    method public android.content.ClipDescription getDescription();
+    method public android.content.ClipData.Item getItemAt(int);
+    method public int getItemCount();
+    method public static android.content.ClipData newHtmlText(java.lang.CharSequence, java.lang.CharSequence, java.lang.String);
+    method public static android.content.ClipData newIntent(java.lang.CharSequence, android.content.Intent);
+    method public static android.content.ClipData newPlainText(java.lang.CharSequence, java.lang.CharSequence);
+    method public static android.content.ClipData newRawUri(java.lang.CharSequence, android.net.Uri);
+    method public static android.content.ClipData newUri(android.content.ContentResolver, java.lang.CharSequence, android.net.Uri);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static class ClipData.Item {
+    ctor public ClipData.Item(java.lang.CharSequence);
+    ctor public ClipData.Item(java.lang.CharSequence, java.lang.String);
+    ctor public ClipData.Item(android.content.Intent);
+    ctor public ClipData.Item(android.net.Uri);
+    ctor public ClipData.Item(java.lang.CharSequence, android.content.Intent, android.net.Uri);
+    ctor public ClipData.Item(java.lang.CharSequence, java.lang.String, android.content.Intent, android.net.Uri);
+    method public java.lang.String coerceToHtmlText(android.content.Context);
+    method public java.lang.CharSequence coerceToStyledText(android.content.Context);
+    method public java.lang.CharSequence coerceToText(android.content.Context);
+    method public java.lang.String getHtmlText();
+    method public android.content.Intent getIntent();
+    method public java.lang.CharSequence getText();
+    method public android.net.Uri getUri();
+  }
+
+  public class ClipDescription implements android.os.Parcelable {
+    ctor public ClipDescription(java.lang.CharSequence, java.lang.String[]);
+    ctor public ClipDescription(android.content.ClipDescription);
+    method public static boolean compareMimeTypes(java.lang.String, java.lang.String);
+    method public int describeContents();
+    method public java.lang.String[] filterMimeTypes(java.lang.String);
+    method public java.lang.CharSequence getLabel();
+    method public java.lang.String getMimeType(int);
+    method public int getMimeTypeCount();
+    method public boolean hasMimeType(java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final java.lang.String MIMETYPE_TEXT_HTML = "text/html";
+    field public static final java.lang.String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent";
+    field public static final java.lang.String MIMETYPE_TEXT_PLAIN = "text/plain";
+    field public static final java.lang.String MIMETYPE_TEXT_URILIST = "text/uri-list";
+  }
+
+  public class ClipboardManager extends android.text.ClipboardManager {
+    method public void addPrimaryClipChangedListener(android.content.ClipboardManager.OnPrimaryClipChangedListener);
+    method public android.content.ClipData getPrimaryClip();
+    method public android.content.ClipDescription getPrimaryClipDescription();
+    method public deprecated java.lang.CharSequence getText();
+    method public boolean hasPrimaryClip();
+    method public deprecated boolean hasText();
+    method public void removePrimaryClipChangedListener(android.content.ClipboardManager.OnPrimaryClipChangedListener);
+    method public void setPrimaryClip(android.content.ClipData);
+    method public deprecated void setText(java.lang.CharSequence);
+  }
+
+  public static abstract interface ClipboardManager.OnPrimaryClipChangedListener {
+    method public abstract void onPrimaryClipChanged();
+  }
+
+  public abstract interface ComponentCallbacks {
+    method public abstract void onConfigurationChanged(android.content.res.Configuration);
+    method public abstract void onLowMemory();
+  }
+
+  public abstract interface ComponentCallbacks2 implements android.content.ComponentCallbacks {
+    method public abstract void onTrimMemory(int);
+    field public static final int TRIM_MEMORY_BACKGROUND = 40; // 0x28
+    field public static final int TRIM_MEMORY_COMPLETE = 80; // 0x50
+    field public static final int TRIM_MEMORY_MODERATE = 60; // 0x3c
+    field public static final int TRIM_MEMORY_RUNNING_CRITICAL = 15; // 0xf
+    field public static final int TRIM_MEMORY_RUNNING_LOW = 10; // 0xa
+    field public static final int TRIM_MEMORY_RUNNING_MODERATE = 5; // 0x5
+    field public static final int TRIM_MEMORY_UI_HIDDEN = 20; // 0x14
+  }
+
+  public final class ComponentName implements java.lang.Cloneable java.lang.Comparable android.os.Parcelable {
+    ctor public ComponentName(java.lang.String, java.lang.String);
+    ctor public ComponentName(android.content.Context, java.lang.String);
+    ctor public ComponentName(android.content.Context, java.lang.Class<?>);
+    ctor public ComponentName(android.os.Parcel);
+    method public android.content.ComponentName clone();
+    method public int compareTo(android.content.ComponentName);
+    method public int describeContents();
+    method public java.lang.String flattenToShortString();
+    method public java.lang.String flattenToString();
+    method public java.lang.String getClassName();
+    method public java.lang.String getPackageName();
+    method public java.lang.String getShortClassName();
+    method public static android.content.ComponentName readFromParcel(android.os.Parcel);
+    method public java.lang.String toShortString();
+    method public static android.content.ComponentName unflattenFromString(java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    method public static void writeToParcel(android.content.ComponentName, android.os.Parcel);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public abstract class ContentProvider implements android.content.ComponentCallbacks2 {
+    ctor public ContentProvider();
+    method public android.content.ContentProviderResult[] applyBatch(java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException;
+    method public void attachInfo(android.content.Context, android.content.pm.ProviderInfo);
+    method public int bulkInsert(android.net.Uri, android.content.ContentValues[]);
+    method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle);
+    method public abstract int delete(android.net.Uri, java.lang.String, java.lang.String[]);
+    method public final android.content.Context getContext();
+    method public final android.content.pm.PathPermission[] getPathPermissions();
+    method public final java.lang.String getReadPermission();
+    method public java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String);
+    method public abstract java.lang.String getType(android.net.Uri);
+    method public final java.lang.String getWritePermission();
+    method public abstract android.net.Uri insert(android.net.Uri, android.content.ContentValues);
+    method protected boolean isTemporary();
+    method public void onConfigurationChanged(android.content.res.Configuration);
+    method public abstract boolean onCreate();
+    method public void onLowMemory();
+    method public void onTrimMemory(int);
+    method public android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
+    method public android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
+    method protected final android.os.ParcelFileDescriptor openFileHelper(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
+    method public android.os.ParcelFileDescriptor openPipeHelper(android.net.Uri, java.lang.String, android.os.Bundle, T, android.content.ContentProvider.PipeDataWriter<T>) throws java.io.FileNotFoundException;
+    method public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle) throws java.io.FileNotFoundException;
+    method public abstract android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
+    method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+    method protected final void setPathPermissions(android.content.pm.PathPermission[]);
+    method protected final void setReadPermission(java.lang.String);
+    method protected final void setWritePermission(java.lang.String);
+    method public void shutdown();
+    method public abstract int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
+  }
+
+  public static abstract interface ContentProvider.PipeDataWriter {
+    method public abstract void writeDataToPipe(android.os.ParcelFileDescriptor, android.net.Uri, java.lang.String, android.os.Bundle, T);
+  }
+
+  public class ContentProviderClient {
+    method public android.content.ContentProviderResult[] applyBatch(java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException;
+    method public int bulkInsert(android.net.Uri, android.content.ContentValues[]) throws android.os.RemoteException;
+    method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle) throws android.os.RemoteException;
+    method public int delete(android.net.Uri, java.lang.String, java.lang.String[]) throws android.os.RemoteException;
+    method public android.content.ContentProvider getLocalContentProvider();
+    method public java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String) throws android.os.RemoteException;
+    method public java.lang.String getType(android.net.Uri) throws android.os.RemoteException;
+    method public android.net.Uri insert(android.net.Uri, android.content.ContentValues) throws android.os.RemoteException;
+    method public android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException, android.os.RemoteException;
+    method public android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException, android.os.RemoteException;
+    method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle) throws java.io.FileNotFoundException, android.os.RemoteException;
+    method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String) throws android.os.RemoteException;
+    method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal) throws android.os.RemoteException;
+    method public boolean release();
+    method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]) throws android.os.RemoteException;
+  }
+
+  public class ContentProviderOperation implements android.os.Parcelable {
+    method public android.content.ContentProviderResult apply(android.content.ContentProvider, android.content.ContentProviderResult[], int) throws android.content.OperationApplicationException;
+    method public int describeContents();
+    method public android.net.Uri getUri();
+    method public boolean isReadOperation();
+    method public boolean isWriteOperation();
+    method public boolean isYieldAllowed();
+    method public static android.content.ContentProviderOperation.Builder newAssertQuery(android.net.Uri);
+    method public static android.content.ContentProviderOperation.Builder newDelete(android.net.Uri);
+    method public static android.content.ContentProviderOperation.Builder newInsert(android.net.Uri);
+    method public static android.content.ContentProviderOperation.Builder newUpdate(android.net.Uri);
+    method public java.lang.String[] resolveSelectionArgsBackReferences(android.content.ContentProviderResult[], int);
+    method public android.content.ContentValues resolveValueBackReferences(android.content.ContentProviderResult[], int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static class ContentProviderOperation.Builder {
+    method public android.content.ContentProviderOperation build();
+    method public android.content.ContentProviderOperation.Builder withExpectedCount(int);
+    method public android.content.ContentProviderOperation.Builder withSelection(java.lang.String, java.lang.String[]);
+    method public android.content.ContentProviderOperation.Builder withSelectionBackReference(int, int);
+    method public android.content.ContentProviderOperation.Builder withValue(java.lang.String, java.lang.Object);
+    method public android.content.ContentProviderOperation.Builder withValueBackReference(java.lang.String, int);
+    method public android.content.ContentProviderOperation.Builder withValueBackReferences(android.content.ContentValues);
+    method public android.content.ContentProviderOperation.Builder withValues(android.content.ContentValues);
+    method public android.content.ContentProviderOperation.Builder withYieldAllowed(boolean);
+  }
+
+  public class ContentProviderResult implements android.os.Parcelable {
+    ctor public ContentProviderResult(android.net.Uri);
+    ctor public ContentProviderResult(int);
+    ctor public ContentProviderResult(android.os.Parcel);
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public final java.lang.Integer count;
+    field public final android.net.Uri uri;
+  }
+
+  public class ContentQueryMap extends java.util.Observable {
+    ctor public ContentQueryMap(android.database.Cursor, java.lang.String, boolean, android.os.Handler);
+    method public synchronized void close();
+    method public synchronized java.util.Map<java.lang.String, android.content.ContentValues> getRows();
+    method public synchronized android.content.ContentValues getValues(java.lang.String);
+    method public void requery();
+    method public void setKeepUpdated(boolean);
+  }
+
+  public abstract class ContentResolver {
+    ctor public ContentResolver(android.content.Context);
+    method public final android.content.ContentProviderClient acquireContentProviderClient(android.net.Uri);
+    method public final android.content.ContentProviderClient acquireContentProviderClient(java.lang.String);
+    method public final android.content.ContentProviderClient acquireUnstableContentProviderClient(android.net.Uri);
+    method public final android.content.ContentProviderClient acquireUnstableContentProviderClient(java.lang.String);
+    method public static void addPeriodicSync(android.accounts.Account, java.lang.String, android.os.Bundle, long);
+    method public static java.lang.Object addStatusChangeListener(int, android.content.SyncStatusObserver);
+    method public android.content.ContentProviderResult[] applyBatch(java.lang.String, java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException;
+    method public final int bulkInsert(android.net.Uri, android.content.ContentValues[]);
+    method public final android.os.Bundle call(android.net.Uri, java.lang.String, java.lang.String, android.os.Bundle);
+    method public deprecated void cancelSync(android.net.Uri);
+    method public static void cancelSync(android.accounts.Account, java.lang.String);
+    method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
+    method public static deprecated android.content.SyncInfo getCurrentSync();
+    method public static java.util.List<android.content.SyncInfo> getCurrentSyncs();
+    method public static int getIsSyncable(android.accounts.Account, java.lang.String);
+    method public static boolean getMasterSyncAutomatically();
+    method public static java.util.List<android.content.PeriodicSync> getPeriodicSyncs(android.accounts.Account, java.lang.String);
+    method public java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String);
+    method public static android.content.SyncAdapterType[] getSyncAdapterTypes();
+    method public static boolean getSyncAutomatically(android.accounts.Account, java.lang.String);
+    method public final java.lang.String getType(android.net.Uri);
+    method public final android.net.Uri insert(android.net.Uri, android.content.ContentValues);
+    method public static boolean isSyncActive(android.accounts.Account, java.lang.String);
+    method public static boolean isSyncPending(android.accounts.Account, java.lang.String);
+    method public void notifyChange(android.net.Uri, android.database.ContentObserver);
+    method public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean);
+    method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
+    method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
+    method public final java.io.InputStream openInputStream(android.net.Uri) throws java.io.FileNotFoundException;
+    method public final java.io.OutputStream openOutputStream(android.net.Uri) throws java.io.FileNotFoundException;
+    method public final java.io.OutputStream openOutputStream(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
+    method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle) throws java.io.FileNotFoundException;
+    method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
+    method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+    method public final void registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver);
+    method public static void removePeriodicSync(android.accounts.Account, java.lang.String, android.os.Bundle);
+    method public static void removeStatusChangeListener(java.lang.Object);
+    method public static void requestSync(android.accounts.Account, java.lang.String, android.os.Bundle);
+    method public static void setIsSyncable(android.accounts.Account, java.lang.String, int);
+    method public static void setMasterSyncAutomatically(boolean);
+    method public static void setSyncAutomatically(android.accounts.Account, java.lang.String, boolean);
+    method public deprecated void startSync(android.net.Uri, android.os.Bundle);
+    method public final void unregisterContentObserver(android.database.ContentObserver);
+    method public final int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
+    method public static void validateSyncExtrasBundle(android.os.Bundle);
+    field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
+    field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
+    field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
+    field public static final java.lang.String SCHEME_CONTENT = "content";
+    field public static final java.lang.String SCHEME_FILE = "file";
+    field public static final deprecated java.lang.String SYNC_EXTRAS_ACCOUNT = "account";
+    field public static final java.lang.String SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS = "discard_deletions";
+    field public static final java.lang.String SYNC_EXTRAS_DO_NOT_RETRY = "do_not_retry";
+    field public static final java.lang.String SYNC_EXTRAS_EXPEDITED = "expedited";
+    field public static final deprecated java.lang.String SYNC_EXTRAS_FORCE = "force";
+    field public static final java.lang.String SYNC_EXTRAS_IGNORE_BACKOFF = "ignore_backoff";
+    field public static final java.lang.String SYNC_EXTRAS_IGNORE_SETTINGS = "ignore_settings";
+    field public static final java.lang.String SYNC_EXTRAS_INITIALIZE = "initialize";
+    field public static final java.lang.String SYNC_EXTRAS_MANUAL = "force";
+    field public static final java.lang.String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override";
+    field public static final java.lang.String SYNC_EXTRAS_UPLOAD = "upload";
+    field public static final int SYNC_OBSERVER_TYPE_ACTIVE = 4; // 0x4
+    field public static final int SYNC_OBSERVER_TYPE_PENDING = 2; // 0x2
+    field public static final int SYNC_OBSERVER_TYPE_SETTINGS = 1; // 0x1
+  }
+
+  public class ContentUris {
+    ctor public ContentUris();
+    method public static android.net.Uri.Builder appendId(android.net.Uri.Builder, long);
+    method public static long parseId(android.net.Uri);
+    method public static android.net.Uri withAppendedId(android.net.Uri, long);
+  }
+
+  public final class ContentValues implements android.os.Parcelable {
+    ctor public ContentValues();
+    ctor public ContentValues(int);
+    ctor public ContentValues(android.content.ContentValues);
+    method public void clear();
+    method public boolean containsKey(java.lang.String);
+    method public int describeContents();
+    method public java.lang.Object get(java.lang.String);
+    method public java.lang.Boolean getAsBoolean(java.lang.String);
+    method public java.lang.Byte getAsByte(java.lang.String);
+    method public byte[] getAsByteArray(java.lang.String);
+    method public java.lang.Double getAsDouble(java.lang.String);
+    method public java.lang.Float getAsFloat(java.lang.String);
+    method public java.lang.Integer getAsInteger(java.lang.String);
+    method public java.lang.Long getAsLong(java.lang.String);
+    method public java.lang.Short getAsShort(java.lang.String);
+    method public java.lang.String getAsString(java.lang.String);
+    method public java.util.Set<java.lang.String> keySet();
+    method public void put(java.lang.String, java.lang.String);
+    method public void put(java.lang.String, java.lang.Byte);
+    method public void put(java.lang.String, java.lang.Short);
+    method public void put(java.lang.String, java.lang.Integer);
+    method public void put(java.lang.String, java.lang.Long);
+    method public void put(java.lang.String, java.lang.Float);
+    method public void put(java.lang.String, java.lang.Double);
+    method public void put(java.lang.String, java.lang.Boolean);
+    method public void put(java.lang.String, byte[]);
+    method public void putAll(android.content.ContentValues);
+    method public void putNull(java.lang.String);
+    method public void remove(java.lang.String);
+    method public int size();
+    method public java.util.Set<java.util.Map.Entry<java.lang.String, java.lang.Object>> valueSet();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final java.lang.String TAG = "ContentValues";
+  }
+
+  public abstract class Context {
+    ctor public Context();
+    method public abstract boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
+    method public abstract int checkCallingOrSelfPermission(java.lang.String);
+    method public abstract int checkCallingOrSelfUriPermission(android.net.Uri, int);
+    method public abstract int checkCallingPermission(java.lang.String);
+    method public abstract int checkCallingUriPermission(android.net.Uri, int);
+    method public abstract int checkPermission(java.lang.String, int, int);
+    method public abstract int checkUriPermission(android.net.Uri, int, int, int);
+    method public abstract int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
+    method public abstract deprecated void clearWallpaper() throws java.io.IOException;
+    method public abstract android.content.Context createConfigurationContext(android.content.res.Configuration);
+    method public abstract android.content.Context createDisplayContext(android.view.Display);
+    method public abstract android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract java.lang.String[] databaseList();
+    method public abstract boolean deleteDatabase(java.lang.String);
+    method public abstract boolean deleteFile(java.lang.String);
+    method public abstract void enforceCallingOrSelfPermission(java.lang.String, java.lang.String);
+    method public abstract void enforceCallingOrSelfUriPermission(android.net.Uri, int, java.lang.String);
+    method public abstract void enforceCallingPermission(java.lang.String, java.lang.String);
+    method public abstract void enforceCallingUriPermission(android.net.Uri, int, java.lang.String);
+    method public abstract void enforcePermission(java.lang.String, int, int, java.lang.String);
+    method public abstract void enforceUriPermission(android.net.Uri, int, int, int, java.lang.String);
+    method public abstract void enforceUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int, java.lang.String);
+    method public abstract java.lang.String[] fileList();
+    method public abstract android.content.Context getApplicationContext();
+    method public abstract android.content.pm.ApplicationInfo getApplicationInfo();
+    method public abstract android.content.res.AssetManager getAssets();
+    method public abstract java.io.File getCacheDir();
+    method public abstract java.lang.ClassLoader getClassLoader();
+    method public abstract android.content.ContentResolver getContentResolver();
+    method public abstract java.io.File getDatabasePath(java.lang.String);
+    method public abstract java.io.File getDir(java.lang.String, int);
+    method public abstract java.io.File getExternalCacheDir();
+    method public abstract java.io.File getExternalFilesDir(java.lang.String);
+    method public abstract java.io.File getFileStreamPath(java.lang.String);
+    method public abstract java.io.File getFilesDir();
+    method public abstract android.os.Looper getMainLooper();
+    method public abstract java.io.File getObbDir();
+    method public abstract java.lang.String getPackageCodePath();
+    method public abstract android.content.pm.PackageManager getPackageManager();
+    method public abstract java.lang.String getPackageName();
+    method public abstract java.lang.String getPackageResourcePath();
+    method public abstract android.content.res.Resources getResources();
+    method public abstract android.content.SharedPreferences getSharedPreferences(java.lang.String, int);
+    method public final java.lang.String getString(int);
+    method public final java.lang.String getString(int, java.lang.Object...);
+    method public abstract java.lang.Object getSystemService(java.lang.String);
+    method public final java.lang.CharSequence getText(int);
+    method public abstract android.content.res.Resources.Theme getTheme();
+    method public abstract deprecated android.graphics.drawable.Drawable getWallpaper();
+    method public abstract deprecated int getWallpaperDesiredMinimumHeight();
+    method public abstract deprecated int getWallpaperDesiredMinimumWidth();
+    method public abstract void grantUriPermission(java.lang.String, android.net.Uri, int);
+    method public boolean isRestricted();
+    method public final android.content.res.TypedArray obtainStyledAttributes(int[]);
+    method public final android.content.res.TypedArray obtainStyledAttributes(int, int[]) throws android.content.res.Resources.NotFoundException;
+    method public final android.content.res.TypedArray obtainStyledAttributes(android.util.AttributeSet, int[]);
+    method public final android.content.res.TypedArray obtainStyledAttributes(android.util.AttributeSet, int[], int, int);
+    method public abstract java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
+    method public abstract java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
+    method public abstract android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
+    method public abstract android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory, android.database.DatabaseErrorHandler);
+    method public abstract deprecated android.graphics.drawable.Drawable peekWallpaper();
+    method public void registerComponentCallbacks(android.content.ComponentCallbacks);
+    method public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter);
+    method public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler);
+    method public abstract void removeStickyBroadcast(android.content.Intent);
+    method public abstract void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+    method public abstract void revokeUriPermission(android.net.Uri, int);
+    method public abstract void sendBroadcast(android.content.Intent);
+    method public abstract void sendBroadcast(android.content.Intent, java.lang.String);
+    method public abstract void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+    method public abstract void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String);
+    method public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String);
+    method public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public abstract void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public abstract void sendStickyBroadcast(android.content.Intent);
+    method public abstract void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+    method public abstract void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public abstract void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public abstract void setTheme(int);
+    method public abstract deprecated void setWallpaper(android.graphics.Bitmap) throws java.io.IOException;
+    method public abstract deprecated void setWallpaper(java.io.InputStream) throws java.io.IOException;
+    method public abstract void startActivities(android.content.Intent[]);
+    method public abstract void startActivities(android.content.Intent[], android.os.Bundle);
+    method public abstract void startActivity(android.content.Intent);
+    method public abstract void startActivity(android.content.Intent, android.os.Bundle);
+    method public abstract boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
+    method public abstract void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
+    method public abstract void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
+    method public abstract android.content.ComponentName startService(android.content.Intent);
+    method public abstract boolean stopService(android.content.Intent);
+    method public abstract void unbindService(android.content.ServiceConnection);
+    method public void unregisterComponentCallbacks(android.content.ComponentCallbacks);
+    method public abstract void unregisterReceiver(android.content.BroadcastReceiver);
+    field public static final java.lang.String ACCESSIBILITY_SERVICE = "accessibility";
+    field public static final java.lang.String ACCOUNT_SERVICE = "account";
+    field public static final java.lang.String ACTIVITY_SERVICE = "activity";
+    field public static final java.lang.String ALARM_SERVICE = "alarm";
+    field public static final java.lang.String AUDIO_SERVICE = "audio";
+    field public static final int BIND_ABOVE_CLIENT = 8; // 0x8
+    field public static final int BIND_ADJUST_WITH_ACTIVITY = 128; // 0x80
+    field public static final int BIND_ALLOW_OOM_MANAGEMENT = 16; // 0x10
+    field public static final int BIND_AUTO_CREATE = 1; // 0x1
+    field public static final int BIND_DEBUG_UNBIND = 2; // 0x2
+    field public static final int BIND_IMPORTANT = 64; // 0x40
+    field public static final int BIND_NOT_FOREGROUND = 4; // 0x4
+    field public static final int BIND_WAIVE_PRIORITY = 32; // 0x20
+    field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
+    field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
+    field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
+    field public static final int CONTEXT_INCLUDE_CODE = 1; // 0x1
+    field public static final int CONTEXT_RESTRICTED = 4; // 0x4
+    field public static final java.lang.String DEVICE_POLICY_SERVICE = "device_policy";
+    field public static final java.lang.String DISPLAY_SERVICE = "display";
+    field public static final java.lang.String DOWNLOAD_SERVICE = "download";
+    field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
+    field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
+    field public static final java.lang.String INPUT_SERVICE = "input";
+    field public static final java.lang.String KEYGUARD_SERVICE = "keyguard";
+    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 java.lang.String MEDIA_ROUTER_SERVICE = "media_router";
+    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 deprecated int MODE_WORLD_READABLE = 1; // 0x1
+    field public static final deprecated int MODE_WORLD_WRITEABLE = 2; // 0x2
+    field public static final java.lang.String NFC_SERVICE = "nfc";
+    field public static final java.lang.String NOTIFICATION_SERVICE = "notification";
+    field public static final java.lang.String NSD_SERVICE = "servicediscovery";
+    field public static final java.lang.String POWER_SERVICE = "power";
+    field public static final java.lang.String SEARCH_SERVICE = "search";
+    field public static final java.lang.String SENSOR_SERVICE = "sensor";
+    field public static final java.lang.String STORAGE_SERVICE = "storage";
+    field public static final java.lang.String TELEPHONY_SERVICE = "phone";
+    field public static final java.lang.String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
+    field public static final java.lang.String UI_MODE_SERVICE = "uimode";
+    field public static final java.lang.String USB_SERVICE = "usb";
+    field public static final java.lang.String USER_SERVICE = "user";
+    field public static final java.lang.String VIBRATOR_SERVICE = "vibrator";
+    field public static final java.lang.String WALLPAPER_SERVICE = "wallpaper";
+    field public static final java.lang.String WIFI_P2P_SERVICE = "wifip2p";
+    field public static final java.lang.String WIFI_SERVICE = "wifi";
+    field public static final java.lang.String WINDOW_SERVICE = "window";
+  }
+
+  public class ContextWrapper extends android.content.Context {
+    ctor public ContextWrapper(android.content.Context);
+    method protected void attachBaseContext(android.content.Context);
+    method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
+    method public int checkCallingOrSelfPermission(java.lang.String);
+    method public int checkCallingOrSelfUriPermission(android.net.Uri, int);
+    method public int checkCallingPermission(java.lang.String);
+    method public int checkCallingUriPermission(android.net.Uri, int);
+    method public int checkPermission(java.lang.String, int, int);
+    method public int checkUriPermission(android.net.Uri, int, int, int);
+    method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
+    method public void clearWallpaper() throws java.io.IOException;
+    method public android.content.Context createConfigurationContext(android.content.res.Configuration);
+    method public android.content.Context createDisplayContext(android.view.Display);
+    method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public java.lang.String[] databaseList();
+    method public boolean deleteDatabase(java.lang.String);
+    method public boolean deleteFile(java.lang.String);
+    method public void enforceCallingOrSelfPermission(java.lang.String, java.lang.String);
+    method public void enforceCallingOrSelfUriPermission(android.net.Uri, int, java.lang.String);
+    method public void enforceCallingPermission(java.lang.String, java.lang.String);
+    method public void enforceCallingUriPermission(android.net.Uri, int, java.lang.String);
+    method public void enforcePermission(java.lang.String, int, int, java.lang.String);
+    method public void enforceUriPermission(android.net.Uri, int, int, int, java.lang.String);
+    method public void enforceUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int, java.lang.String);
+    method public java.lang.String[] fileList();
+    method public android.content.Context getApplicationContext();
+    method public android.content.pm.ApplicationInfo getApplicationInfo();
+    method public android.content.res.AssetManager getAssets();
+    method public android.content.Context getBaseContext();
+    method public java.io.File getCacheDir();
+    method public java.lang.ClassLoader getClassLoader();
+    method public android.content.ContentResolver getContentResolver();
+    method public java.io.File getDatabasePath(java.lang.String);
+    method public java.io.File getDir(java.lang.String, int);
+    method public java.io.File getExternalCacheDir();
+    method public java.io.File getExternalFilesDir(java.lang.String);
+    method public java.io.File getFileStreamPath(java.lang.String);
+    method public java.io.File getFilesDir();
+    method public android.os.Looper getMainLooper();
+    method public java.io.File getObbDir();
+    method public java.lang.String getPackageCodePath();
+    method public android.content.pm.PackageManager getPackageManager();
+    method public java.lang.String getPackageName();
+    method public java.lang.String getPackageResourcePath();
+    method public android.content.res.Resources getResources();
+    method public android.content.SharedPreferences getSharedPreferences(java.lang.String, int);
+    method public java.lang.Object getSystemService(java.lang.String);
+    method public android.content.res.Resources.Theme getTheme();
+    method public android.graphics.drawable.Drawable getWallpaper();
+    method public int getWallpaperDesiredMinimumHeight();
+    method public int getWallpaperDesiredMinimumWidth();
+    method public void grantUriPermission(java.lang.String, android.net.Uri, int);
+    method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
+    method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
+    method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
+    method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory, android.database.DatabaseErrorHandler);
+    method public android.graphics.drawable.Drawable peekWallpaper();
+    method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter);
+    method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler);
+    method public void removeStickyBroadcast(android.content.Intent);
+    method public void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+    method public void revokeUriPermission(android.net.Uri, int);
+    method public void sendBroadcast(android.content.Intent);
+    method public void sendBroadcast(android.content.Intent, java.lang.String);
+    method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+    method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String);
+    method public void sendOrderedBroadcast(android.content.Intent, java.lang.String);
+    method public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public void sendStickyBroadcast(android.content.Intent);
+    method public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+    method public void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public void setTheme(int);
+    method public void setWallpaper(android.graphics.Bitmap) throws java.io.IOException;
+    method public void setWallpaper(java.io.InputStream) throws java.io.IOException;
+    method public void startActivities(android.content.Intent[]);
+    method public void startActivities(android.content.Intent[], android.os.Bundle);
+    method public void startActivity(android.content.Intent);
+    method public void startActivity(android.content.Intent, android.os.Bundle);
+    method public boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
+    method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
+    method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
+    method public android.content.ComponentName startService(android.content.Intent);
+    method public boolean stopService(android.content.Intent);
+    method public void unbindService(android.content.ServiceConnection);
+    method public void unregisterReceiver(android.content.BroadcastReceiver);
+  }
+
+  public class CursorLoader extends android.content.AsyncTaskLoader {
+    ctor public CursorLoader(android.content.Context);
+    ctor public CursorLoader(android.content.Context, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
+    method public void deliverResult(android.database.Cursor);
+    method public java.lang.String[] getProjection();
+    method public java.lang.String getSelection();
+    method public java.lang.String[] getSelectionArgs();
+    method public java.lang.String getSortOrder();
+    method public android.net.Uri getUri();
+    method public android.database.Cursor loadInBackground();
+    method public void onCanceled(android.database.Cursor);
+    method public void setProjection(java.lang.String[]);
+    method public void setSelection(java.lang.String);
+    method public void setSelectionArgs(java.lang.String[]);
+    method public void setSortOrder(java.lang.String);
+    method public void setUri(android.net.Uri);
+  }
+
+  public abstract interface DialogInterface {
+    method public abstract void cancel();
+    method public abstract void dismiss();
+    field public static final deprecated int BUTTON1 = -1; // 0xffffffff
+    field public static final deprecated int BUTTON2 = -2; // 0xfffffffe
+    field public static final deprecated int BUTTON3 = -3; // 0xfffffffd
+    field public static final int BUTTON_NEGATIVE = -2; // 0xfffffffe
+    field public static final int BUTTON_NEUTRAL = -3; // 0xfffffffd
+    field public static final int BUTTON_POSITIVE = -1; // 0xffffffff
+  }
+
+  public static abstract interface DialogInterface.OnCancelListener {
+    method public abstract void onCancel(android.content.DialogInterface);
+  }
+
+  public static abstract interface DialogInterface.OnClickListener {
+    method public abstract void onClick(android.content.DialogInterface, int);
+  }
+
+  public static abstract interface DialogInterface.OnDismissListener {
+    method public abstract void onDismiss(android.content.DialogInterface);
+  }
+
+  public static abstract interface DialogInterface.OnKeyListener {
+    method public abstract boolean onKey(android.content.DialogInterface, int, android.view.KeyEvent);
+  }
+
+  public static abstract interface DialogInterface.OnMultiChoiceClickListener {
+    method public abstract void onClick(android.content.DialogInterface, int, boolean);
+  }
+
+  public static abstract interface DialogInterface.OnShowListener {
+    method public abstract void onShow(android.content.DialogInterface);
+  }
+
+  public final class Entity {
+    ctor public Entity(android.content.ContentValues);
+    method public void addSubValue(android.net.Uri, android.content.ContentValues);
+    method public android.content.ContentValues getEntityValues();
+    method public java.util.ArrayList<android.content.Entity.NamedContentValues> getSubValues();
+  }
+
+  public static class Entity.NamedContentValues {
+    ctor public Entity.NamedContentValues(android.net.Uri, android.content.ContentValues);
+    field public final android.net.Uri uri;
+    field public final android.content.ContentValues values;
+  }
+
+  public abstract interface EntityIterator implements java.util.Iterator {
+    method public abstract void close();
+    method public abstract void reset();
+  }
+
+  public class Intent implements java.lang.Cloneable android.os.Parcelable {
+    ctor public Intent();
+    ctor public Intent(android.content.Intent);
+    ctor public Intent(java.lang.String);
+    ctor public Intent(java.lang.String, android.net.Uri);
+    ctor public Intent(android.content.Context, java.lang.Class<?>);
+    ctor public Intent(java.lang.String, android.net.Uri, android.content.Context, java.lang.Class<?>);
+    method public android.content.Intent addCategory(java.lang.String);
+    method public android.content.Intent addFlags(int);
+    method public java.lang.Object clone();
+    method public android.content.Intent cloneFilter();
+    method public static android.content.Intent createChooser(android.content.Intent, java.lang.CharSequence);
+    method public int describeContents();
+    method public int fillIn(android.content.Intent, int);
+    method public boolean filterEquals(android.content.Intent);
+    method public int filterHashCode();
+    method public java.lang.String getAction();
+    method public boolean[] getBooleanArrayExtra(java.lang.String);
+    method public boolean getBooleanExtra(java.lang.String, boolean);
+    method public android.os.Bundle getBundleExtra(java.lang.String);
+    method public byte[] getByteArrayExtra(java.lang.String);
+    method public byte getByteExtra(java.lang.String, byte);
+    method public java.util.Set<java.lang.String> getCategories();
+    method public char[] getCharArrayExtra(java.lang.String);
+    method public char getCharExtra(java.lang.String, char);
+    method public java.lang.CharSequence[] getCharSequenceArrayExtra(java.lang.String);
+    method public java.util.ArrayList<java.lang.CharSequence> getCharSequenceArrayListExtra(java.lang.String);
+    method public java.lang.CharSequence getCharSequenceExtra(java.lang.String);
+    method public android.content.ClipData getClipData();
+    method public android.content.ComponentName getComponent();
+    method public android.net.Uri getData();
+    method public java.lang.String getDataString();
+    method public double[] getDoubleArrayExtra(java.lang.String);
+    method public double getDoubleExtra(java.lang.String, double);
+    method public android.os.Bundle getExtras();
+    method public int getFlags();
+    method public float[] getFloatArrayExtra(java.lang.String);
+    method public float getFloatExtra(java.lang.String, float);
+    method public int[] getIntArrayExtra(java.lang.String);
+    method public int getIntExtra(java.lang.String, int);
+    method public java.util.ArrayList<java.lang.Integer> getIntegerArrayListExtra(java.lang.String);
+    method public static deprecated android.content.Intent getIntent(java.lang.String) throws java.net.URISyntaxException;
+    method public static android.content.Intent getIntentOld(java.lang.String) throws java.net.URISyntaxException;
+    method public long[] getLongArrayExtra(java.lang.String);
+    method public long getLongExtra(java.lang.String, long);
+    method public java.lang.String getPackage();
+    method public android.os.Parcelable[] getParcelableArrayExtra(java.lang.String);
+    method public java.util.ArrayList<T> getParcelableArrayListExtra(java.lang.String);
+    method public T getParcelableExtra(java.lang.String);
+    method public java.lang.String getScheme();
+    method public android.content.Intent getSelector();
+    method public java.io.Serializable getSerializableExtra(java.lang.String);
+    method public short[] getShortArrayExtra(java.lang.String);
+    method public short getShortExtra(java.lang.String, short);
+    method public android.graphics.Rect getSourceBounds();
+    method public java.lang.String[] getStringArrayExtra(java.lang.String);
+    method public java.util.ArrayList<java.lang.String> getStringArrayListExtra(java.lang.String);
+    method public java.lang.String getStringExtra(java.lang.String);
+    method public java.lang.String getType();
+    method public boolean hasCategory(java.lang.String);
+    method public boolean hasExtra(java.lang.String);
+    method public boolean hasFileDescriptors();
+    method public static android.content.Intent makeMainActivity(android.content.ComponentName);
+    method public static android.content.Intent makeMainSelectorActivity(java.lang.String, java.lang.String);
+    method public static android.content.Intent makeRestartActivityTask(android.content.ComponentName);
+    method public static java.lang.String normalizeMimeType(java.lang.String);
+    method public static android.content.Intent parseIntent(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static android.content.Intent parseUri(java.lang.String, int) throws java.net.URISyntaxException;
+    method public android.content.Intent putCharSequenceArrayListExtra(java.lang.String, java.util.ArrayList<java.lang.CharSequence>);
+    method public android.content.Intent putExtra(java.lang.String, boolean);
+    method public android.content.Intent putExtra(java.lang.String, byte);
+    method public android.content.Intent putExtra(java.lang.String, char);
+    method public android.content.Intent putExtra(java.lang.String, short);
+    method public android.content.Intent putExtra(java.lang.String, int);
+    method public android.content.Intent putExtra(java.lang.String, long);
+    method public android.content.Intent putExtra(java.lang.String, float);
+    method public android.content.Intent putExtra(java.lang.String, double);
+    method public android.content.Intent putExtra(java.lang.String, java.lang.String);
+    method public android.content.Intent putExtra(java.lang.String, java.lang.CharSequence);
+    method public android.content.Intent putExtra(java.lang.String, android.os.Parcelable);
+    method public android.content.Intent putExtra(java.lang.String, android.os.Parcelable[]);
+    method public android.content.Intent putExtra(java.lang.String, java.io.Serializable);
+    method public android.content.Intent putExtra(java.lang.String, boolean[]);
+    method public android.content.Intent putExtra(java.lang.String, byte[]);
+    method public android.content.Intent putExtra(java.lang.String, short[]);
+    method public android.content.Intent putExtra(java.lang.String, char[]);
+    method public android.content.Intent putExtra(java.lang.String, int[]);
+    method public android.content.Intent putExtra(java.lang.String, long[]);
+    method public android.content.Intent putExtra(java.lang.String, float[]);
+    method public android.content.Intent putExtra(java.lang.String, double[]);
+    method public android.content.Intent putExtra(java.lang.String, java.lang.String[]);
+    method public android.content.Intent putExtra(java.lang.String, java.lang.CharSequence[]);
+    method public android.content.Intent putExtra(java.lang.String, android.os.Bundle);
+    method public android.content.Intent putExtras(android.content.Intent);
+    method public android.content.Intent putExtras(android.os.Bundle);
+    method public android.content.Intent putIntegerArrayListExtra(java.lang.String, java.util.ArrayList<java.lang.Integer>);
+    method public android.content.Intent putParcelableArrayListExtra(java.lang.String, java.util.ArrayList<? extends android.os.Parcelable>);
+    method public android.content.Intent putStringArrayListExtra(java.lang.String, java.util.ArrayList<java.lang.String>);
+    method public void readFromParcel(android.os.Parcel);
+    method public void removeCategory(java.lang.String);
+    method public void removeExtra(java.lang.String);
+    method public android.content.Intent replaceExtras(android.content.Intent);
+    method public android.content.Intent replaceExtras(android.os.Bundle);
+    method public android.content.ComponentName resolveActivity(android.content.pm.PackageManager);
+    method public android.content.pm.ActivityInfo resolveActivityInfo(android.content.pm.PackageManager, int);
+    method public java.lang.String resolveType(android.content.Context);
+    method public java.lang.String resolveType(android.content.ContentResolver);
+    method public java.lang.String resolveTypeIfNeeded(android.content.ContentResolver);
+    method public android.content.Intent setAction(java.lang.String);
+    method public android.content.Intent setClass(android.content.Context, java.lang.Class<?>);
+    method public android.content.Intent setClassName(android.content.Context, java.lang.String);
+    method public android.content.Intent setClassName(java.lang.String, java.lang.String);
+    method public void setClipData(android.content.ClipData);
+    method public android.content.Intent setComponent(android.content.ComponentName);
+    method public android.content.Intent setData(android.net.Uri);
+    method public android.content.Intent setDataAndNormalize(android.net.Uri);
+    method public android.content.Intent setDataAndType(android.net.Uri, java.lang.String);
+    method public android.content.Intent setDataAndTypeAndNormalize(android.net.Uri, java.lang.String);
+    method public void setExtrasClassLoader(java.lang.ClassLoader);
+    method public android.content.Intent setFlags(int);
+    method public android.content.Intent setPackage(java.lang.String);
+    method public void setSelector(android.content.Intent);
+    method public void setSourceBounds(android.graphics.Rect);
+    method public android.content.Intent setType(java.lang.String);
+    method public android.content.Intent setTypeAndNormalize(java.lang.String);
+    method public deprecated java.lang.String toURI();
+    method public java.lang.String toUri(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final java.lang.String ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE";
+    field public static final java.lang.String ACTION_ALL_APPS = "android.intent.action.ALL_APPS";
+    field public static final java.lang.String ACTION_ANSWER = "android.intent.action.ANSWER";
+    field public static final java.lang.String ACTION_APP_ERROR = "android.intent.action.APP_ERROR";
+    field public static final java.lang.String ACTION_ASSIST = "android.intent.action.ASSIST";
+    field public static final java.lang.String ACTION_ATTACH_DATA = "android.intent.action.ATTACH_DATA";
+    field public static final java.lang.String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";
+    field public static final java.lang.String ACTION_BATTERY_LOW = "android.intent.action.BATTERY_LOW";
+    field public static final java.lang.String ACTION_BATTERY_OKAY = "android.intent.action.BATTERY_OKAY";
+    field public static final java.lang.String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
+    field public static final java.lang.String ACTION_BUG_REPORT = "android.intent.action.BUG_REPORT";
+    field public static final java.lang.String ACTION_CALL = "android.intent.action.CALL";
+    field public static final java.lang.String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON";
+    field public static final java.lang.String ACTION_CAMERA_BUTTON = "android.intent.action.CAMERA_BUTTON";
+    field public static final java.lang.String ACTION_CHOOSER = "android.intent.action.CHOOSER";
+    field public static final java.lang.String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
+    field public static final java.lang.String ACTION_CONFIGURATION_CHANGED = "android.intent.action.CONFIGURATION_CHANGED";
+    field public static final java.lang.String ACTION_CREATE_SHORTCUT = "android.intent.action.CREATE_SHORTCUT";
+    field public static final java.lang.String ACTION_DATE_CHANGED = "android.intent.action.DATE_CHANGED";
+    field public static final java.lang.String ACTION_DEFAULT = "android.intent.action.VIEW";
+    field public static final java.lang.String ACTION_DELETE = "android.intent.action.DELETE";
+    field public static final java.lang.String ACTION_DEVICE_STORAGE_LOW = "android.intent.action.DEVICE_STORAGE_LOW";
+    field public static final java.lang.String ACTION_DEVICE_STORAGE_OK = "android.intent.action.DEVICE_STORAGE_OK";
+    field public static final java.lang.String ACTION_DIAL = "android.intent.action.DIAL";
+    field public static final java.lang.String ACTION_DOCK_EVENT = "android.intent.action.DOCK_EVENT";
+    field public static final java.lang.String ACTION_DREAMING_STARTED = "android.intent.action.DREAMING_STARTED";
+    field public static final java.lang.String ACTION_DREAMING_STOPPED = "android.intent.action.DREAMING_STOPPED";
+    field public static final java.lang.String ACTION_EDIT = "android.intent.action.EDIT";
+    field public static final java.lang.String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE";
+    field public static final java.lang.String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE";
+    field public static final java.lang.String ACTION_FACTORY_TEST = "android.intent.action.FACTORY_TEST";
+    field public static final java.lang.String ACTION_GET_CONTENT = "android.intent.action.GET_CONTENT";
+    field public static final java.lang.String ACTION_GTALK_SERVICE_CONNECTED = "android.intent.action.GTALK_CONNECTED";
+    field public static final java.lang.String ACTION_GTALK_SERVICE_DISCONNECTED = "android.intent.action.GTALK_DISCONNECTED";
+    field public static final java.lang.String ACTION_HEADSET_PLUG = "android.intent.action.HEADSET_PLUG";
+    field public static final java.lang.String ACTION_INPUT_METHOD_CHANGED = "android.intent.action.INPUT_METHOD_CHANGED";
+    field public static final java.lang.String ACTION_INSERT = "android.intent.action.INSERT";
+    field public static final java.lang.String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT";
+    field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
+    field public static final java.lang.String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
+    field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN";
+    field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
+    field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
+    field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
+    field public static final java.lang.String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
+    field public static final java.lang.String ACTION_MEDIA_CHECKING = "android.intent.action.MEDIA_CHECKING";
+    field public static final java.lang.String ACTION_MEDIA_EJECT = "android.intent.action.MEDIA_EJECT";
+    field public static final java.lang.String ACTION_MEDIA_MOUNTED = "android.intent.action.MEDIA_MOUNTED";
+    field public static final java.lang.String ACTION_MEDIA_NOFS = "android.intent.action.MEDIA_NOFS";
+    field public static final java.lang.String ACTION_MEDIA_REMOVED = "android.intent.action.MEDIA_REMOVED";
+    field public static final java.lang.String ACTION_MEDIA_SCANNER_FINISHED = "android.intent.action.MEDIA_SCANNER_FINISHED";
+    field public static final java.lang.String ACTION_MEDIA_SCANNER_SCAN_FILE = "android.intent.action.MEDIA_SCANNER_SCAN_FILE";
+    field public static final java.lang.String ACTION_MEDIA_SCANNER_STARTED = "android.intent.action.MEDIA_SCANNER_STARTED";
+    field public static final java.lang.String ACTION_MEDIA_SHARED = "android.intent.action.MEDIA_SHARED";
+    field public static final java.lang.String ACTION_MEDIA_UNMOUNTABLE = "android.intent.action.MEDIA_UNMOUNTABLE";
+    field public static final java.lang.String ACTION_MEDIA_UNMOUNTED = "android.intent.action.MEDIA_UNMOUNTED";
+    field public static final java.lang.String ACTION_MY_PACKAGE_REPLACED = "android.intent.action.MY_PACKAGE_REPLACED";
+    field public static final java.lang.String ACTION_NEW_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL";
+    field public static final java.lang.String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
+    field public static final java.lang.String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
+    field public static final java.lang.String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
+    field public static final java.lang.String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
+    field public static final java.lang.String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
+    field public static final deprecated java.lang.String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
+    field public static final java.lang.String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION";
+    field public static final java.lang.String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED";
+    field public static final java.lang.String ACTION_PACKAGE_REPLACED = "android.intent.action.PACKAGE_REPLACED";
+    field public static final java.lang.String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED";
+    field public static final java.lang.String ACTION_PACKAGE_VERIFIED = "android.intent.action.PACKAGE_VERIFIED";
+    field public static final java.lang.String ACTION_PASTE = "android.intent.action.PASTE";
+    field public static final java.lang.String ACTION_PICK = "android.intent.action.PICK";
+    field public static final java.lang.String ACTION_PICK_ACTIVITY = "android.intent.action.PICK_ACTIVITY";
+    field public static final java.lang.String ACTION_POWER_CONNECTED = "android.intent.action.ACTION_POWER_CONNECTED";
+    field public static final java.lang.String ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED";
+    field public static final java.lang.String ACTION_POWER_USAGE_SUMMARY = "android.intent.action.POWER_USAGE_SUMMARY";
+    field public static final java.lang.String ACTION_PROVIDER_CHANGED = "android.intent.action.PROVIDER_CHANGED";
+    field public static final java.lang.String ACTION_QUICK_CLOCK = "android.intent.action.QUICK_CLOCK";
+    field public static final java.lang.String ACTION_REBOOT = "android.intent.action.REBOOT";
+    field public static final java.lang.String ACTION_RUN = "android.intent.action.RUN";
+    field public static final java.lang.String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF";
+    field public static final java.lang.String ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON";
+    field public static final java.lang.String ACTION_SEARCH = "android.intent.action.SEARCH";
+    field public static final java.lang.String ACTION_SEARCH_LONG_PRESS = "android.intent.action.SEARCH_LONG_PRESS";
+    field public static final java.lang.String ACTION_SEND = "android.intent.action.SEND";
+    field public static final java.lang.String ACTION_SENDTO = "android.intent.action.SENDTO";
+    field public static final java.lang.String ACTION_SEND_MULTIPLE = "android.intent.action.SEND_MULTIPLE";
+    field public static final java.lang.String ACTION_SET_WALLPAPER = "android.intent.action.SET_WALLPAPER";
+    field public static final java.lang.String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";
+    field public static final java.lang.String ACTION_SYNC = "android.intent.action.SYNC";
+    field public static final java.lang.String ACTION_SYSTEM_TUTORIAL = "android.intent.action.SYSTEM_TUTORIAL";
+    field public static final java.lang.String ACTION_TIMEZONE_CHANGED = "android.intent.action.TIMEZONE_CHANGED";
+    field public static final java.lang.String ACTION_TIME_CHANGED = "android.intent.action.TIME_SET";
+    field public static final java.lang.String ACTION_TIME_TICK = "android.intent.action.TIME_TICK";
+    field public static final java.lang.String ACTION_UID_REMOVED = "android.intent.action.UID_REMOVED";
+    field public static final deprecated java.lang.String ACTION_UMS_CONNECTED = "android.intent.action.UMS_CONNECTED";
+    field public static final deprecated java.lang.String ACTION_UMS_DISCONNECTED = "android.intent.action.UMS_DISCONNECTED";
+    field public static final java.lang.String ACTION_UNINSTALL_PACKAGE = "android.intent.action.UNINSTALL_PACKAGE";
+    field public static final java.lang.String ACTION_USER_BACKGROUND = "android.intent.action.USER_BACKGROUND";
+    field public static final java.lang.String ACTION_USER_FOREGROUND = "android.intent.action.USER_FOREGROUND";
+    field public static final java.lang.String ACTION_USER_INITIALIZE = "android.intent.action.USER_INITIALIZE";
+    field public static final java.lang.String ACTION_USER_PRESENT = "android.intent.action.USER_PRESENT";
+    field public static final java.lang.String ACTION_VIEW = "android.intent.action.VIEW";
+    field public static final java.lang.String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND";
+    field public static final deprecated java.lang.String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED";
+    field public static final java.lang.String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
+    field public static final java.lang.String CATEGORY_ALTERNATIVE = "android.intent.category.ALTERNATIVE";
+    field public static final java.lang.String CATEGORY_APP_BROWSER = "android.intent.category.APP_BROWSER";
+    field public static final java.lang.String CATEGORY_APP_CALCULATOR = "android.intent.category.APP_CALCULATOR";
+    field public static final java.lang.String CATEGORY_APP_CALENDAR = "android.intent.category.APP_CALENDAR";
+    field public static final java.lang.String CATEGORY_APP_CONTACTS = "android.intent.category.APP_CONTACTS";
+    field public static final java.lang.String CATEGORY_APP_EMAIL = "android.intent.category.APP_EMAIL";
+    field public static final java.lang.String CATEGORY_APP_GALLERY = "android.intent.category.APP_GALLERY";
+    field public static final java.lang.String CATEGORY_APP_MAPS = "android.intent.category.APP_MAPS";
+    field public static final java.lang.String CATEGORY_APP_MARKET = "android.intent.category.APP_MARKET";
+    field public static final java.lang.String CATEGORY_APP_MESSAGING = "android.intent.category.APP_MESSAGING";
+    field public static final java.lang.String CATEGORY_APP_MUSIC = "android.intent.category.APP_MUSIC";
+    field public static final java.lang.String CATEGORY_BROWSABLE = "android.intent.category.BROWSABLE";
+    field public static final java.lang.String CATEGORY_CAR_DOCK = "android.intent.category.CAR_DOCK";
+    field public static final java.lang.String CATEGORY_CAR_MODE = "android.intent.category.CAR_MODE";
+    field public static final java.lang.String CATEGORY_DEFAULT = "android.intent.category.DEFAULT";
+    field public static final java.lang.String CATEGORY_DESK_DOCK = "android.intent.category.DESK_DOCK";
+    field public static final java.lang.String CATEGORY_DEVELOPMENT_PREFERENCE = "android.intent.category.DEVELOPMENT_PREFERENCE";
+    field public static final java.lang.String CATEGORY_EMBED = "android.intent.category.EMBED";
+    field public static final java.lang.String CATEGORY_FRAMEWORK_INSTRUMENTATION_TEST = "android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST";
+    field public static final java.lang.String CATEGORY_HE_DESK_DOCK = "android.intent.category.HE_DESK_DOCK";
+    field public static final java.lang.String CATEGORY_HOME = "android.intent.category.HOME";
+    field public static final java.lang.String CATEGORY_INFO = "android.intent.category.INFO";
+    field public static final java.lang.String CATEGORY_LAUNCHER = "android.intent.category.LAUNCHER";
+    field public static final java.lang.String CATEGORY_LE_DESK_DOCK = "android.intent.category.LE_DESK_DOCK";
+    field public static final java.lang.String CATEGORY_MONKEY = "android.intent.category.MONKEY";
+    field public static final java.lang.String CATEGORY_OPENABLE = "android.intent.category.OPENABLE";
+    field public static final java.lang.String CATEGORY_PREFERENCE = "android.intent.category.PREFERENCE";
+    field public static final java.lang.String CATEGORY_SAMPLE_CODE = "android.intent.category.SAMPLE_CODE";
+    field public static final java.lang.String CATEGORY_SELECTED_ALTERNATIVE = "android.intent.category.SELECTED_ALTERNATIVE";
+    field public static final java.lang.String CATEGORY_TAB = "android.intent.category.TAB";
+    field public static final java.lang.String CATEGORY_TEST = "android.intent.category.TEST";
+    field public static final java.lang.String CATEGORY_UNIT_TEST = "android.intent.category.UNIT_TEST";
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final java.lang.String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
+    field public static final deprecated java.lang.String EXTRA_ALLOW_REPLACE = "android.intent.extra.ALLOW_REPLACE";
+    field public static final java.lang.String EXTRA_BCC = "android.intent.extra.BCC";
+    field public static final java.lang.String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
+    field public static final java.lang.String EXTRA_CC = "android.intent.extra.CC";
+    field public static final deprecated java.lang.String EXTRA_CHANGED_COMPONENT_NAME = "android.intent.extra.changed_component_name";
+    field public static final java.lang.String EXTRA_CHANGED_COMPONENT_NAME_LIST = "android.intent.extra.changed_component_name_list";
+    field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
+    field public static final java.lang.String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list";
+    field public static final java.lang.String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED";
+    field public static final java.lang.String EXTRA_DOCK_STATE = "android.intent.extra.DOCK_STATE";
+    field public static final int EXTRA_DOCK_STATE_CAR = 2; // 0x2
+    field public static final int EXTRA_DOCK_STATE_DESK = 1; // 0x1
+    field public static final int EXTRA_DOCK_STATE_HE_DESK = 4; // 0x4
+    field public static final int EXTRA_DOCK_STATE_LE_DESK = 3; // 0x3
+    field public static final int EXTRA_DOCK_STATE_UNDOCKED = 0; // 0x0
+    field public static final java.lang.String EXTRA_DONT_KILL_APP = "android.intent.extra.DONT_KILL_APP";
+    field public static final java.lang.String EXTRA_EMAIL = "android.intent.extra.EMAIL";
+    field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
+    field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
+    field public static final java.lang.String EXTRA_INSTALLER_PACKAGE_NAME = "android.intent.extra.INSTALLER_PACKAGE_NAME";
+    field public static final java.lang.String EXTRA_INTENT = "android.intent.extra.INTENT";
+    field public static final java.lang.String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT";
+    field public static final java.lang.String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY";
+    field public static final java.lang.String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
+    field public static final java.lang.String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI";
+    field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
+    field public static final java.lang.String EXTRA_REFERRER = "android.intent.extra.REFERRER";
+    field public static final java.lang.String EXTRA_REMOTE_INTENT_TOKEN = "android.intent.extra.remote_intent_token";
+    field public static final java.lang.String EXTRA_REPLACING = "android.intent.extra.REPLACING";
+    field public static final java.lang.String EXTRA_RETURN_RESULT = "android.intent.extra.RETURN_RESULT";
+    field public static final java.lang.String EXTRA_SHORTCUT_ICON = "android.intent.extra.shortcut.ICON";
+    field public static final java.lang.String EXTRA_SHORTCUT_ICON_RESOURCE = "android.intent.extra.shortcut.ICON_RESOURCE";
+    field public static final java.lang.String EXTRA_SHORTCUT_INTENT = "android.intent.extra.shortcut.INTENT";
+    field public static final java.lang.String EXTRA_SHORTCUT_NAME = "android.intent.extra.shortcut.NAME";
+    field public static final java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
+    field public static final java.lang.String EXTRA_SUBJECT = "android.intent.extra.SUBJECT";
+    field public static final java.lang.String EXTRA_TEMPLATE = "android.intent.extra.TEMPLATE";
+    field public static final java.lang.String EXTRA_TEXT = "android.intent.extra.TEXT";
+    field public static final java.lang.String EXTRA_TITLE = "android.intent.extra.TITLE";
+    field public static final java.lang.String EXTRA_UID = "android.intent.extra.UID";
+    field public static final int FILL_IN_ACTION = 1; // 0x1
+    field public static final int FILL_IN_CATEGORIES = 4; // 0x4
+    field public static final int FILL_IN_CLIP_DATA = 128; // 0x80
+    field public static final int FILL_IN_COMPONENT = 8; // 0x8
+    field public static final int FILL_IN_DATA = 2; // 0x2
+    field public static final int FILL_IN_PACKAGE = 16; // 0x10
+    field public static final int FILL_IN_SELECTOR = 64; // 0x40
+    field public static final int FILL_IN_SOURCE_BOUNDS = 32; // 0x20
+    field public static final int FLAG_ACTIVITY_BROUGHT_TO_FRONT = 4194304; // 0x400000
+    field public static final int FLAG_ACTIVITY_CLEAR_TASK = 32768; // 0x8000
+    field public static final int FLAG_ACTIVITY_CLEAR_TOP = 67108864; // 0x4000000
+    field public static final int FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET = 524288; // 0x80000
+    field public static final int FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS = 8388608; // 0x800000
+    field public static final int FLAG_ACTIVITY_FORWARD_RESULT = 33554432; // 0x2000000
+    field public static final int FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY = 1048576; // 0x100000
+    field public static final int FLAG_ACTIVITY_MULTIPLE_TASK = 134217728; // 0x8000000
+    field public static final int FLAG_ACTIVITY_NEW_TASK = 268435456; // 0x10000000
+    field public static final int FLAG_ACTIVITY_NO_ANIMATION = 65536; // 0x10000
+    field public static final int FLAG_ACTIVITY_NO_HISTORY = 1073741824; // 0x40000000
+    field public static final int FLAG_ACTIVITY_NO_USER_ACTION = 262144; // 0x40000
+    field public static final int FLAG_ACTIVITY_PREVIOUS_IS_TOP = 16777216; // 0x1000000
+    field public static final int FLAG_ACTIVITY_REORDER_TO_FRONT = 131072; // 0x20000
+    field public static final int FLAG_ACTIVITY_RESET_TASK_IF_NEEDED = 2097152; // 0x200000
+    field public static final int FLAG_ACTIVITY_SINGLE_TOP = 536870912; // 0x20000000
+    field public static final int FLAG_ACTIVITY_TASK_ON_HOME = 16384; // 0x4000
+    field public static final int FLAG_DEBUG_LOG_RESOLUTION = 8; // 0x8
+    field public static final int FLAG_EXCLUDE_STOPPED_PACKAGES = 16; // 0x10
+    field public static final int FLAG_FROM_BACKGROUND = 4; // 0x4
+    field public static final int FLAG_GRANT_READ_URI_PERMISSION = 1; // 0x1
+    field public static final int FLAG_GRANT_WRITE_URI_PERMISSION = 2; // 0x2
+    field public static final int FLAG_INCLUDE_STOPPED_PACKAGES = 32; // 0x20
+    field public static final int FLAG_RECEIVER_FOREGROUND = 268435456; // 0x10000000
+    field public static final int FLAG_RECEIVER_REGISTERED_ONLY = 1073741824; // 0x40000000
+    field public static final int FLAG_RECEIVER_REPLACE_PENDING = 536870912; // 0x20000000
+    field public static final java.lang.String METADATA_DOCK_HOME = "android.dock_home";
+    field public static final int URI_INTENT_SCHEME = 1; // 0x1
+  }
+
+  public static final class Intent.FilterComparison {
+    ctor public Intent.FilterComparison(android.content.Intent);
+    method public android.content.Intent getIntent();
+  }
+
+  public static class Intent.ShortcutIconResource implements android.os.Parcelable {
+    ctor public Intent.ShortcutIconResource();
+    method public int describeContents();
+    method public static android.content.Intent.ShortcutIconResource fromContext(android.content.Context, int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public java.lang.String packageName;
+    field public java.lang.String resourceName;
+  }
+
+  public class IntentFilter implements android.os.Parcelable {
+    ctor public IntentFilter();
+    ctor public IntentFilter(java.lang.String);
+    ctor public IntentFilter(java.lang.String, java.lang.String) throws android.content.IntentFilter.MalformedMimeTypeException;
+    ctor public IntentFilter(android.content.IntentFilter);
+    method public final java.util.Iterator<java.lang.String> actionsIterator();
+    method public final void addAction(java.lang.String);
+    method public final void addCategory(java.lang.String);
+    method public final void addDataAuthority(java.lang.String, java.lang.String);
+    method public final void addDataPath(java.lang.String, int);
+    method public final void addDataScheme(java.lang.String);
+    method public final void addDataType(java.lang.String) throws android.content.IntentFilter.MalformedMimeTypeException;
+    method public final java.util.Iterator<android.content.IntentFilter.AuthorityEntry> authoritiesIterator();
+    method public final java.util.Iterator<java.lang.String> categoriesIterator();
+    method public final int countActions();
+    method public final int countCategories();
+    method public final int countDataAuthorities();
+    method public final int countDataPaths();
+    method public final int countDataSchemes();
+    method public final int countDataTypes();
+    method public static android.content.IntentFilter create(java.lang.String, java.lang.String);
+    method public final int describeContents();
+    method public void dump(android.util.Printer, java.lang.String);
+    method public final java.lang.String getAction(int);
+    method public final java.lang.String getCategory(int);
+    method public final android.content.IntentFilter.AuthorityEntry getDataAuthority(int);
+    method public final android.os.PatternMatcher getDataPath(int);
+    method public final java.lang.String getDataScheme(int);
+    method public final java.lang.String getDataType(int);
+    method public final int getPriority();
+    method public final boolean hasAction(java.lang.String);
+    method public final boolean hasCategory(java.lang.String);
+    method public final boolean hasDataAuthority(android.net.Uri);
+    method public final boolean hasDataPath(java.lang.String);
+    method public final boolean hasDataScheme(java.lang.String);
+    method public final boolean hasDataType(java.lang.String);
+    method public final int match(android.content.ContentResolver, android.content.Intent, boolean, java.lang.String);
+    method public final int match(java.lang.String, java.lang.String, java.lang.String, android.net.Uri, java.util.Set<java.lang.String>, java.lang.String);
+    method public final boolean matchAction(java.lang.String);
+    method public final java.lang.String matchCategories(java.util.Set<java.lang.String>);
+    method public final int matchData(java.lang.String, java.lang.String, android.net.Uri);
+    method public final int matchDataAuthority(android.net.Uri);
+    method public final java.util.Iterator<android.os.PatternMatcher> pathsIterator();
+    method public void readFromXml(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public final java.util.Iterator<java.lang.String> schemesIterator();
+    method public final void setPriority(int);
+    method public final java.util.Iterator<java.lang.String> typesIterator();
+    method public final void writeToParcel(android.os.Parcel, int);
+    method public void writeToXml(org.xmlpull.v1.XmlSerializer) throws java.io.IOException;
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int MATCH_ADJUSTMENT_MASK = 65535; // 0xffff
+    field public static final int MATCH_ADJUSTMENT_NORMAL = 32768; // 0x8000
+    field public static final int MATCH_CATEGORY_EMPTY = 1048576; // 0x100000
+    field public static final int MATCH_CATEGORY_HOST = 3145728; // 0x300000
+    field public static final int MATCH_CATEGORY_MASK = 268369920; // 0xfff0000
+    field public static final int MATCH_CATEGORY_PATH = 5242880; // 0x500000
+    field public static final int MATCH_CATEGORY_PORT = 4194304; // 0x400000
+    field public static final int MATCH_CATEGORY_SCHEME = 2097152; // 0x200000
+    field public static final int MATCH_CATEGORY_TYPE = 6291456; // 0x600000
+    field public static final int NO_MATCH_ACTION = -3; // 0xfffffffd
+    field public static final int NO_MATCH_CATEGORY = -4; // 0xfffffffc
+    field public static final int NO_MATCH_DATA = -2; // 0xfffffffe
+    field public static final int NO_MATCH_TYPE = -1; // 0xffffffff
+    field public static final int SYSTEM_HIGH_PRIORITY = 1000; // 0x3e8
+    field public static final int SYSTEM_LOW_PRIORITY = -1000; // 0xfffffc18
+  }
+
+  public static final class IntentFilter.AuthorityEntry {
+    ctor public IntentFilter.AuthorityEntry(java.lang.String, java.lang.String);
+    method public java.lang.String getHost();
+    method public int getPort();
+    method public int match(android.net.Uri);
+  }
+
+  public static class IntentFilter.MalformedMimeTypeException extends android.util.AndroidException {
+    ctor public IntentFilter.MalformedMimeTypeException();
+    ctor public IntentFilter.MalformedMimeTypeException(java.lang.String);
+  }
+
+  public class IntentSender implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.String getCreatorPackage();
+    method public int getCreatorUid();
+    method public android.os.UserHandle getCreatorUserHandle();
+    method public deprecated java.lang.String getTargetPackage();
+    method public static android.content.IntentSender readIntentSenderOrNullFromParcel(android.os.Parcel);
+    method public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender.OnFinished, android.os.Handler) throws android.content.IntentSender.SendIntentException;
+    method public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender.OnFinished, android.os.Handler, java.lang.String) throws android.content.IntentSender.SendIntentException;
+    method public static void writeIntentSenderOrNullToParcel(android.content.IntentSender, android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static abstract interface IntentSender.OnFinished {
+    method public abstract void onSendFinished(android.content.IntentSender, android.content.Intent, int, java.lang.String, android.os.Bundle);
+  }
+
+  public static class IntentSender.SendIntentException extends android.util.AndroidException {
+    ctor public IntentSender.SendIntentException();
+    ctor public IntentSender.SendIntentException(java.lang.String);
+    ctor public IntentSender.SendIntentException(java.lang.Exception);
+  }
+
+  public class Loader {
+    ctor public Loader(android.content.Context);
+    method public void abandon();
+    method public boolean cancelLoad();
+    method public java.lang.String dataToString(D);
+    method public void deliverCancellation();
+    method public void deliverResult(D);
+    method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public void forceLoad();
+    method public android.content.Context getContext();
+    method public int getId();
+    method public boolean isAbandoned();
+    method public boolean isReset();
+    method public boolean isStarted();
+    method protected void onAbandon();
+    method protected boolean onCancelLoad();
+    method public void onContentChanged();
+    method protected void onForceLoad();
+    method protected void onReset();
+    method protected void onStartLoading();
+    method protected void onStopLoading();
+    method public void registerListener(int, android.content.Loader.OnLoadCompleteListener<D>);
+    method public void registerOnLoadCanceledListener(android.content.Loader.OnLoadCanceledListener<D>);
+    method public void reset();
+    method public final void startLoading();
+    method public void stopLoading();
+    method public boolean takeContentChanged();
+    method public void unregisterListener(android.content.Loader.OnLoadCompleteListener<D>);
+    method public void unregisterOnLoadCanceledListener(android.content.Loader.OnLoadCanceledListener<D>);
+  }
+
+  public final class Loader.ForceLoadContentObserver extends android.database.ContentObserver {
+    ctor public Loader.ForceLoadContentObserver();
+  }
+
+  public static abstract interface Loader.OnLoadCanceledListener {
+    method public abstract void onLoadCanceled(android.content.Loader<D>);
+  }
+
+  public static abstract interface Loader.OnLoadCompleteListener {
+    method public abstract void onLoadComplete(android.content.Loader<D>, D);
+  }
+
+  public class MutableContextWrapper extends android.content.ContextWrapper {
+    ctor public MutableContextWrapper(android.content.Context);
+    method public void setBaseContext(android.content.Context);
+  }
+
+  public class OperationApplicationException extends java.lang.Exception {
+    ctor public OperationApplicationException();
+    ctor public OperationApplicationException(java.lang.String);
+    ctor public OperationApplicationException(java.lang.String, java.lang.Throwable);
+    ctor public OperationApplicationException(java.lang.Throwable);
+    ctor public OperationApplicationException(int);
+    ctor public OperationApplicationException(java.lang.String, int);
+    method public int getNumSuccessfulYieldPoints();
+  }
+
+  public class PeriodicSync implements android.os.Parcelable {
+    ctor public PeriodicSync(android.accounts.Account, java.lang.String, android.os.Bundle, long);
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public final android.accounts.Account account;
+    field public final java.lang.String authority;
+    field public final android.os.Bundle extras;
+    field public final long period;
+  }
+
+  public class ReceiverCallNotAllowedException extends android.util.AndroidRuntimeException {
+    ctor public ReceiverCallNotAllowedException(java.lang.String);
+  }
+
+  public class SearchRecentSuggestionsProvider extends android.content.ContentProvider {
+    ctor public SearchRecentSuggestionsProvider();
+    method public int delete(android.net.Uri, java.lang.String, java.lang.String[]);
+    method public java.lang.String getType(android.net.Uri);
+    method public android.net.Uri insert(android.net.Uri, android.content.ContentValues);
+    method public boolean onCreate();
+    method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
+    method protected void setupSuggestions(java.lang.String, int);
+    method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
+    field public static final int DATABASE_MODE_2LINES = 2; // 0x2
+    field public static final int DATABASE_MODE_QUERIES = 1; // 0x1
+  }
+
+  public abstract interface ServiceConnection {
+    method public abstract void onServiceConnected(android.content.ComponentName, android.os.IBinder);
+    method public abstract void onServiceDisconnected(android.content.ComponentName);
+  }
+
+  public abstract interface SharedPreferences {
+    method public abstract boolean contains(java.lang.String);
+    method public abstract android.content.SharedPreferences.Editor edit();
+    method public abstract java.util.Map<java.lang.String, ?> getAll();
+    method public abstract boolean getBoolean(java.lang.String, boolean);
+    method public abstract float getFloat(java.lang.String, float);
+    method public abstract int getInt(java.lang.String, int);
+    method public abstract long getLong(java.lang.String, long);
+    method public abstract java.lang.String getString(java.lang.String, java.lang.String);
+    method public abstract java.util.Set<java.lang.String> getStringSet(java.lang.String, java.util.Set<java.lang.String>);
+    method public abstract void registerOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener);
+    method public abstract void unregisterOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener);
+  }
+
+  public static abstract interface SharedPreferences.Editor {
+    method public abstract void apply();
+    method public abstract android.content.SharedPreferences.Editor clear();
+    method public abstract boolean commit();
+    method public abstract android.content.SharedPreferences.Editor putBoolean(java.lang.String, boolean);
+    method public abstract android.content.SharedPreferences.Editor putFloat(java.lang.String, float);
+    method public abstract android.content.SharedPreferences.Editor putInt(java.lang.String, int);
+    method public abstract android.content.SharedPreferences.Editor putLong(java.lang.String, long);
+    method public abstract android.content.SharedPreferences.Editor putString(java.lang.String, java.lang.String);
+    method public abstract android.content.SharedPreferences.Editor putStringSet(java.lang.String, java.util.Set<java.lang.String>);
+    method public abstract android.content.SharedPreferences.Editor remove(java.lang.String);
+  }
+
+  public static abstract interface SharedPreferences.OnSharedPreferenceChangeListener {
+    method public abstract void onSharedPreferenceChanged(android.content.SharedPreferences, java.lang.String);
+  }
+
+  public class SyncAdapterType implements android.os.Parcelable {
+    ctor public SyncAdapterType(java.lang.String, java.lang.String, boolean, boolean);
+    ctor public SyncAdapterType(android.os.Parcel);
+    method public boolean allowParallelSyncs();
+    method public int describeContents();
+    method public java.lang.String getSettingsActivity();
+    method public boolean isAlwaysSyncable();
+    method public boolean isUserVisible();
+    method public static android.content.SyncAdapterType newKey(java.lang.String, java.lang.String);
+    method public boolean supportsUploading();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public final java.lang.String accountType;
+    field public final java.lang.String authority;
+    field public final boolean isKey;
+  }
+
+  public class SyncContext {
+    method public android.os.IBinder getSyncContextBinder();
+    method public void onFinished(android.content.SyncResult);
+  }
+
+  public class SyncInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public final android.accounts.Account account;
+    field public final java.lang.String authority;
+    field public final long startTime;
+  }
+
+  public final class SyncResult implements android.os.Parcelable {
+    ctor public SyncResult();
+    method public void clear();
+    method public int describeContents();
+    method public boolean hasError();
+    method public boolean hasHardError();
+    method public boolean hasSoftError();
+    method public boolean madeSomeProgress();
+    method public java.lang.String toDebugString();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.content.SyncResult ALREADY_IN_PROGRESS;
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public boolean databaseError;
+    field public long delayUntil;
+    field public boolean fullSyncRequested;
+    field public boolean moreRecordsToGet;
+    field public boolean partialSyncUnavailable;
+    field public final android.content.SyncStats stats;
+    field public final boolean syncAlreadyInProgress;
+    field public boolean tooManyDeletions;
+    field public boolean tooManyRetries;
+  }
+
+  public class SyncStats implements android.os.Parcelable {
+    ctor public SyncStats();
+    ctor public SyncStats(android.os.Parcel);
+    method public void clear();
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public long numAuthExceptions;
+    field public long numConflictDetectedExceptions;
+    field public long numDeletes;
+    field public long numEntries;
+    field public long numInserts;
+    field public long numIoExceptions;
+    field public long numParseExceptions;
+    field public long numSkippedEntries;
+    field public long numUpdates;
+  }
+
+  public abstract interface SyncStatusObserver {
+    method public abstract void onStatusChanged(int);
+  }
+
+  public class UriMatcher {
+    ctor public UriMatcher(int);
+    method public void addURI(java.lang.String, java.lang.String, int);
+    method public int match(android.net.Uri);
+    field public static final int NO_MATCH = -1; // 0xffffffff
+  }
+
+}
+
+package android.content.pm {
+
+  public class ActivityInfo extends android.content.pm.ComponentInfo implements android.os.Parcelable {
+    ctor public ActivityInfo();
+    ctor public ActivityInfo(android.content.pm.ActivityInfo);
+    method public int describeContents();
+    method public void dump(android.util.Printer, java.lang.String);
+    method public final int getThemeResource();
+    field public static final int CONFIG_DENSITY = 4096; // 0x1000
+    field public static final int CONFIG_FONT_SCALE = 1073741824; // 0x40000000
+    field public static final int CONFIG_KEYBOARD = 16; // 0x10
+    field public static final int CONFIG_KEYBOARD_HIDDEN = 32; // 0x20
+    field public static final int CONFIG_LAYOUT_DIRECTION = 8192; // 0x2000
+    field public static final int CONFIG_LOCALE = 4; // 0x4
+    field public static final int CONFIG_MCC = 1; // 0x1
+    field public static final int CONFIG_MNC = 2; // 0x2
+    field public static final int CONFIG_NAVIGATION = 64; // 0x40
+    field public static final int CONFIG_ORIENTATION = 128; // 0x80
+    field public static final int CONFIG_SCREEN_LAYOUT = 256; // 0x100
+    field public static final int CONFIG_SCREEN_SIZE = 1024; // 0x400
+    field public static final int CONFIG_SMALLEST_SCREEN_SIZE = 2048; // 0x800
+    field public static final int CONFIG_TOUCHSCREEN = 8; // 0x8
+    field public static final int CONFIG_UI_MODE = 512; // 0x200
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_ALLOW_TASK_REPARENTING = 64; // 0x40
+    field public static final int FLAG_ALWAYS_RETAIN_TASK_STATE = 8; // 0x8
+    field public static final int FLAG_CLEAR_TASK_ON_LAUNCH = 4; // 0x4
+    field public static final int FLAG_EXCLUDE_FROM_RECENTS = 32; // 0x20
+    field public static final int FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS = 256; // 0x100
+    field public static final int FLAG_FINISH_ON_TASK_LAUNCH = 2; // 0x2
+    field public static final int FLAG_HARDWARE_ACCELERATED = 512; // 0x200
+    field public static final int FLAG_MULTIPROCESS = 1; // 0x1
+    field public static final int FLAG_NO_HISTORY = 128; // 0x80
+    field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000
+    field public static final int FLAG_STATE_NOT_NEEDED = 16; // 0x10
+    field public static final int LAUNCH_MULTIPLE = 0; // 0x0
+    field public static final int LAUNCH_SINGLE_INSTANCE = 3; // 0x3
+    field public static final int LAUNCH_SINGLE_TASK = 2; // 0x2
+    field public static final int LAUNCH_SINGLE_TOP = 1; // 0x1
+    field public static final int SCREEN_ORIENTATION_BEHIND = 3; // 0x3
+    field public static final int SCREEN_ORIENTATION_FULL_SENSOR = 10; // 0xa
+    field public static final int SCREEN_ORIENTATION_LANDSCAPE = 0; // 0x0
+    field public static final int SCREEN_ORIENTATION_NOSENSOR = 5; // 0x5
+    field public static final int SCREEN_ORIENTATION_PORTRAIT = 1; // 0x1
+    field public static final int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8; // 0x8
+    field public static final int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9; // 0x9
+    field public static final int SCREEN_ORIENTATION_SENSOR = 4; // 0x4
+    field public static final int SCREEN_ORIENTATION_SENSOR_LANDSCAPE = 6; // 0x6
+    field public static final int SCREEN_ORIENTATION_SENSOR_PORTRAIT = 7; // 0x7
+    field public static final int SCREEN_ORIENTATION_UNSPECIFIED = -1; // 0xffffffff
+    field public static final int SCREEN_ORIENTATION_USER = 2; // 0x2
+    field public static final int UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW = 1; // 0x1
+    field public int configChanges;
+    field public int flags;
+    field public int launchMode;
+    field public java.lang.String parentActivityName;
+    field public java.lang.String permission;
+    field public int screenOrientation;
+    field public int softInputMode;
+    field public java.lang.String targetActivity;
+    field public java.lang.String taskAffinity;
+    field public int theme;
+    field public int uiOptions;
+  }
+
+  public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    ctor public ApplicationInfo();
+    ctor public ApplicationInfo(android.content.pm.ApplicationInfo);
+    method public int describeContents();
+    method public void dump(android.util.Printer, java.lang.String);
+    method public java.lang.CharSequence loadDescription(android.content.pm.PackageManager);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_ALLOW_BACKUP = 32768; // 0x8000
+    field public static final int FLAG_ALLOW_CLEAR_USER_DATA = 64; // 0x40
+    field public static final int FLAG_ALLOW_TASK_REPARENTING = 32; // 0x20
+    field public static final int FLAG_DEBUGGABLE = 2; // 0x2
+    field public static final int FLAG_EXTERNAL_STORAGE = 262144; // 0x40000
+    field public static final int FLAG_FACTORY_TEST = 16; // 0x10
+    field public static final int FLAG_HAS_CODE = 4; // 0x4
+    field public static final int FLAG_INSTALLED = 8388608; // 0x800000
+    field public static final int FLAG_IS_DATA_ONLY = 16777216; // 0x1000000
+    field public static final int FLAG_KILL_AFTER_RESTORE = 65536; // 0x10000
+    field public static final int FLAG_LARGE_HEAP = 1048576; // 0x100000
+    field public static final int FLAG_PERSISTENT = 8; // 0x8
+    field public static final int FLAG_RESIZEABLE_FOR_SCREENS = 4096; // 0x1000
+    field public static final int FLAG_RESTORE_ANY_VERSION = 131072; // 0x20000
+    field public static final int FLAG_STOPPED = 2097152; // 0x200000
+    field public static final int FLAG_SUPPORTS_LARGE_SCREENS = 2048; // 0x800
+    field public static final int FLAG_SUPPORTS_NORMAL_SCREENS = 1024; // 0x400
+    field public static final int FLAG_SUPPORTS_RTL = 4194304; // 0x400000
+    field public static final int FLAG_SUPPORTS_SCREEN_DENSITIES = 8192; // 0x2000
+    field public static final int FLAG_SUPPORTS_SMALL_SCREENS = 512; // 0x200
+    field public static final int FLAG_SUPPORTS_XLARGE_SCREENS = 524288; // 0x80000
+    field public static final int FLAG_SYSTEM = 1; // 0x1
+    field public static final int FLAG_TEST_ONLY = 256; // 0x100
+    field public static final int FLAG_UPDATED_SYSTEM_APP = 128; // 0x80
+    field public static final int FLAG_VM_SAFE_MODE = 16384; // 0x4000
+    field public java.lang.String backupAgentName;
+    field public java.lang.String className;
+    field public int compatibleWidthLimitDp;
+    field public java.lang.String dataDir;
+    field public int descriptionRes;
+    field public boolean enabled;
+    field public int flags;
+    field public int largestWidthLimitDp;
+    field public java.lang.String manageSpaceActivityName;
+    field public java.lang.String nativeLibraryDir;
+    field public java.lang.String permission;
+    field public java.lang.String processName;
+    field public java.lang.String publicSourceDir;
+    field public int requiresSmallestWidthDp;
+    field public java.lang.String[] sharedLibraryFiles;
+    field public java.lang.String sourceDir;
+    field public int targetSdkVersion;
+    field public java.lang.String taskAffinity;
+    field public int theme;
+    field public int uiOptions;
+    field public int uid;
+  }
+
+  public static class ApplicationInfo.DisplayNameComparator implements java.util.Comparator {
+    ctor public ApplicationInfo.DisplayNameComparator(android.content.pm.PackageManager);
+    method public final int compare(android.content.pm.ApplicationInfo, android.content.pm.ApplicationInfo);
+  }
+
+  public class ComponentInfo extends android.content.pm.PackageItemInfo {
+    ctor public ComponentInfo();
+    ctor public ComponentInfo(android.content.pm.ComponentInfo);
+    ctor protected ComponentInfo(android.os.Parcel);
+    method public final int getIconResource();
+    method public boolean isEnabled();
+    field public android.content.pm.ApplicationInfo applicationInfo;
+    field public int descriptionRes;
+    field public boolean enabled;
+    field public boolean exported;
+    field public java.lang.String processName;
+  }
+
+  public class ConfigurationInfo implements android.os.Parcelable {
+    ctor public ConfigurationInfo();
+    ctor public ConfigurationInfo(android.content.pm.ConfigurationInfo);
+    method public int describeContents();
+    method public java.lang.String getGlEsVersion();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int GL_ES_VERSION_UNDEFINED = 0; // 0x0
+    field public static final int INPUT_FEATURE_FIVE_WAY_NAV = 2; // 0x2
+    field public static final int INPUT_FEATURE_HARD_KEYBOARD = 1; // 0x1
+    field public int reqGlEsVersion;
+    field public int reqInputFeatures;
+    field public int reqKeyboardType;
+    field public int reqNavigation;
+    field public int reqTouchScreen;
+  }
+
+  public class FeatureInfo implements android.os.Parcelable {
+    ctor public FeatureInfo();
+    ctor public FeatureInfo(android.content.pm.FeatureInfo);
+    method public int describeContents();
+    method public java.lang.String getGlEsVersion();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_REQUIRED = 1; // 0x1
+    field public static final int GL_ES_VERSION_UNDEFINED = 0; // 0x0
+    field public int flags;
+    field public java.lang.String name;
+    field public int reqGlEsVersion;
+  }
+
+  public class InstrumentationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    ctor public InstrumentationInfo();
+    ctor public InstrumentationInfo(android.content.pm.InstrumentationInfo);
+    method public int describeContents();
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public java.lang.String dataDir;
+    field public boolean functionalTest;
+    field public boolean handleProfiling;
+    field public java.lang.String publicSourceDir;
+    field public java.lang.String sourceDir;
+    field public java.lang.String targetPackage;
+  }
+
+  public class LabeledIntent extends android.content.Intent {
+    ctor public LabeledIntent(android.content.Intent, java.lang.String, int, int);
+    ctor public LabeledIntent(android.content.Intent, java.lang.String, java.lang.CharSequence, int);
+    ctor public LabeledIntent(java.lang.String, int, int);
+    ctor public LabeledIntent(java.lang.String, java.lang.CharSequence, int);
+    method public int getIconResource();
+    method public int getLabelResource();
+    method public java.lang.CharSequence getNonLocalizedLabel();
+    method public java.lang.String getSourcePackage();
+    method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
+    method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class PackageInfo implements android.os.Parcelable {
+    ctor public PackageInfo();
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int REQUESTED_PERMISSION_GRANTED = 2; // 0x2
+    field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
+    field public android.content.pm.ActivityInfo[] activities;
+    field public android.content.pm.ApplicationInfo applicationInfo;
+    field public android.content.pm.ConfigurationInfo[] configPreferences;
+    field public long firstInstallTime;
+    field public int[] gids;
+    field public android.content.pm.InstrumentationInfo[] instrumentation;
+    field public long lastUpdateTime;
+    field public java.lang.String packageName;
+    field public android.content.pm.PermissionInfo[] permissions;
+    field public android.content.pm.ProviderInfo[] providers;
+    field public android.content.pm.ActivityInfo[] receivers;
+    field public android.content.pm.FeatureInfo[] reqFeatures;
+    field public java.lang.String[] requestedPermissions;
+    field public int[] requestedPermissionsFlags;
+    field public android.content.pm.ServiceInfo[] services;
+    field public java.lang.String sharedUserId;
+    field public int sharedUserLabel;
+    field public android.content.pm.Signature[] signatures;
+    field public int versionCode;
+    field public java.lang.String versionName;
+  }
+
+  public class PackageItemInfo {
+    ctor public PackageItemInfo();
+    ctor public PackageItemInfo(android.content.pm.PackageItemInfo);
+    ctor protected PackageItemInfo(android.os.Parcel);
+    method protected void dumpBack(android.util.Printer, java.lang.String);
+    method protected void dumpFront(android.util.Printer, java.lang.String);
+    method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
+    method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
+    method public android.graphics.drawable.Drawable loadLogo(android.content.pm.PackageManager);
+    method public android.content.res.XmlResourceParser loadXmlMetaData(android.content.pm.PackageManager, java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public int icon;
+    field public int labelRes;
+    field public int logo;
+    field public android.os.Bundle metaData;
+    field public java.lang.String name;
+    field public java.lang.CharSequence nonLocalizedLabel;
+    field public java.lang.String packageName;
+  }
+
+  public static class PackageItemInfo.DisplayNameComparator implements java.util.Comparator {
+    ctor public PackageItemInfo.DisplayNameComparator(android.content.pm.PackageManager);
+    method public final int compare(android.content.pm.PackageItemInfo, android.content.pm.PackageItemInfo);
+  }
+
+  public abstract class PackageManager {
+    ctor public PackageManager();
+    method public abstract deprecated void addPackageToPreferred(java.lang.String);
+    method public abstract boolean addPermission(android.content.pm.PermissionInfo);
+    method public abstract boolean addPermissionAsync(android.content.pm.PermissionInfo);
+    method public abstract deprecated void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+    method public abstract java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
+    method public abstract int checkPermission(java.lang.String, java.lang.String);
+    method public abstract int checkSignatures(java.lang.String, java.lang.String);
+    method public abstract int checkSignatures(int, int);
+    method public abstract void clearPackagePreferredActivities(java.lang.String);
+    method public abstract java.lang.String[] currentToCanonicalPackageNames(java.lang.String[]);
+    method public abstract void extendVerificationTimeout(int, int, long);
+    method public abstract android.graphics.drawable.Drawable getActivityIcon(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.graphics.drawable.Drawable getActivityIcon(android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.pm.ActivityInfo getActivityInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.graphics.drawable.Drawable getActivityLogo(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.graphics.drawable.Drawable getActivityLogo(android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract java.util.List<android.content.pm.PermissionGroupInfo> getAllPermissionGroups(int);
+    method public abstract int getApplicationEnabledSetting(java.lang.String);
+    method public abstract android.graphics.drawable.Drawable getApplicationIcon(android.content.pm.ApplicationInfo);
+    method public abstract android.graphics.drawable.Drawable getApplicationIcon(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract java.lang.CharSequence getApplicationLabel(android.content.pm.ApplicationInfo);
+    method public abstract android.graphics.drawable.Drawable getApplicationLogo(android.content.pm.ApplicationInfo);
+    method public abstract android.graphics.drawable.Drawable getApplicationLogo(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract int getComponentEnabledSetting(android.content.ComponentName);
+    method public abstract android.graphics.drawable.Drawable getDefaultActivityIcon();
+    method public abstract android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
+    method public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
+    method public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
+    method public abstract java.lang.String getInstallerPackageName(java.lang.String);
+    method public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.Intent getLaunchIntentForPackage(java.lang.String);
+    method public abstract java.lang.String getNameForUid(int);
+    method public android.content.pm.PackageInfo getPackageArchiveInfo(java.lang.String, int);
+    method public abstract int[] getPackageGids(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.pm.PackageInfo getPackageInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract java.lang.String[] getPackagesForUid(int);
+    method public abstract android.content.pm.PermissionGroupInfo getPermissionGroupInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.pm.PermissionInfo getPermissionInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract int getPreferredActivities(java.util.List<android.content.IntentFilter>, java.util.List<android.content.ComponentName>, java.lang.String);
+    method public abstract java.util.List<android.content.pm.PackageInfo> getPreferredPackages(int);
+    method public abstract android.content.pm.ProviderInfo getProviderInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.pm.ActivityInfo getReceiverInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.res.Resources getResourcesForActivity(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.res.Resources getResourcesForApplication(android.content.pm.ApplicationInfo) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.res.Resources getResourcesForApplication(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
+    method public abstract java.lang.String[] getSystemSharedLibraryNames();
+    method public abstract java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
+    method public abstract android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
+    method public abstract boolean hasSystemFeature(java.lang.String);
+    method public abstract boolean isSafeMode();
+    method public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
+    method public abstract java.util.List<android.content.pm.ProviderInfo> queryContentProviders(java.lang.String, int, int);
+    method public abstract java.util.List<android.content.pm.InstrumentationInfo> queryInstrumentation(java.lang.String, int);
+    method public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(android.content.Intent, int);
+    method public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivityOptions(android.content.ComponentName, android.content.Intent[], android.content.Intent, int);
+    method public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentServices(android.content.Intent, int);
+    method public abstract java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract deprecated void removePackageFromPreferred(java.lang.String);
+    method public abstract void removePermission(java.lang.String);
+    method public abstract android.content.pm.ResolveInfo resolveActivity(android.content.Intent, int);
+    method public abstract android.content.pm.ProviderInfo resolveContentProvider(java.lang.String, int);
+    method public abstract android.content.pm.ResolveInfo resolveService(android.content.Intent, int);
+    method public abstract void setApplicationEnabledSetting(java.lang.String, int, int);
+    method public abstract void setComponentEnabledSetting(android.content.ComponentName, int, int);
+    method public abstract void setInstallerPackageName(java.lang.String, java.lang.String);
+    method public abstract void verifyPendingInstall(int, int);
+    field public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0; // 0x0
+    field public static final int COMPONENT_ENABLED_STATE_DISABLED = 2; // 0x2
+    field public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3; // 0x3
+    field public static final int COMPONENT_ENABLED_STATE_ENABLED = 1; // 0x1
+    field public static final int DONT_KILL_APP = 1; // 0x1
+    field public static final java.lang.String EXTRA_VERIFICATION_ID = "android.content.pm.extra.VERIFICATION_ID";
+    field public static final java.lang.String EXTRA_VERIFICATION_RESULT = "android.content.pm.extra.VERIFICATION_RESULT";
+    field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency";
+    field public static final java.lang.String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
+    field public static final java.lang.String FEATURE_CAMERA = "android.hardware.camera";
+    field public static final java.lang.String FEATURE_CAMERA_ANY = "android.hardware.camera.any";
+    field public static final java.lang.String FEATURE_CAMERA_AUTOFOCUS = "android.hardware.camera.autofocus";
+    field public static final java.lang.String FEATURE_CAMERA_FLASH = "android.hardware.camera.flash";
+    field public static final java.lang.String FEATURE_CAMERA_FRONT = "android.hardware.camera.front";
+    field public static final java.lang.String FEATURE_FAKETOUCH = "android.hardware.faketouch";
+    field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT = "android.hardware.faketouch.multitouch.distinct";
+    field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = "android.hardware.faketouch.multitouch.jazzhand";
+    field public static final java.lang.String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
+    field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location";
+    field public static final java.lang.String FEATURE_LOCATION_GPS = "android.hardware.location.gps";
+    field public static final java.lang.String FEATURE_LOCATION_NETWORK = "android.hardware.location.network";
+    field public static final java.lang.String FEATURE_MICROPHONE = "android.hardware.microphone";
+    field public static final java.lang.String FEATURE_NFC = "android.hardware.nfc";
+    field public static final java.lang.String FEATURE_SCREEN_LANDSCAPE = "android.hardware.screen.landscape";
+    field public static final java.lang.String FEATURE_SCREEN_PORTRAIT = "android.hardware.screen.portrait";
+    field public static final java.lang.String FEATURE_SENSOR_ACCELEROMETER = "android.hardware.sensor.accelerometer";
+    field public static final java.lang.String FEATURE_SENSOR_BAROMETER = "android.hardware.sensor.barometer";
+    field public static final java.lang.String FEATURE_SENSOR_COMPASS = "android.hardware.sensor.compass";
+    field public static final java.lang.String FEATURE_SENSOR_GYROSCOPE = "android.hardware.sensor.gyroscope";
+    field public static final java.lang.String FEATURE_SENSOR_LIGHT = "android.hardware.sensor.light";
+    field public static final java.lang.String FEATURE_SENSOR_PROXIMITY = "android.hardware.sensor.proximity";
+    field public static final java.lang.String FEATURE_SIP = "android.software.sip";
+    field public static final java.lang.String FEATURE_SIP_VOIP = "android.software.sip.voip";
+    field public static final java.lang.String FEATURE_TELEPHONY = "android.hardware.telephony";
+    field public static final java.lang.String FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
+    field public static final java.lang.String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
+    field public static final java.lang.String FEATURE_TELEVISION = "android.hardware.type.television";
+    field public static final java.lang.String FEATURE_TOUCHSCREEN = "android.hardware.touchscreen";
+    field public static final java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH = "android.hardware.touchscreen.multitouch";
+    field public static final java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT = "android.hardware.touchscreen.multitouch.distinct";
+    field public static final java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH_JAZZHAND = "android.hardware.touchscreen.multitouch.jazzhand";
+    field public static final java.lang.String FEATURE_USB_ACCESSORY = "android.hardware.usb.accessory";
+    field public static final java.lang.String FEATURE_USB_HOST = "android.hardware.usb.host";
+    field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
+    field public static final java.lang.String FEATURE_WIFI_DIRECT = "android.hardware.wifi.direct";
+    field public static final int GET_ACTIVITIES = 1; // 0x1
+    field public static final int GET_CONFIGURATIONS = 16384; // 0x4000
+    field public static final int GET_DISABLED_COMPONENTS = 512; // 0x200
+    field public static final int GET_GIDS = 256; // 0x100
+    field public static final int GET_INSTRUMENTATION = 16; // 0x10
+    field public static final int GET_INTENT_FILTERS = 32; // 0x20
+    field public static final int GET_META_DATA = 128; // 0x80
+    field public static final int GET_PERMISSIONS = 4096; // 0x1000
+    field public static final int GET_PROVIDERS = 8; // 0x8
+    field public static final int GET_RECEIVERS = 2; // 0x2
+    field public static final int GET_RESOLVED_FILTER = 64; // 0x40
+    field public static final int GET_SERVICES = 4; // 0x4
+    field public static final int GET_SHARED_LIBRARY_FILES = 1024; // 0x400
+    field public static final int GET_SIGNATURES = 64; // 0x40
+    field public static final int GET_UNINSTALLED_PACKAGES = 8192; // 0x2000
+    field public static final int GET_URI_PERMISSION_PATTERNS = 2048; // 0x800
+    field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
+    field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L
+    field public static final int PERMISSION_DENIED = -1; // 0xffffffff
+    field public static final int PERMISSION_GRANTED = 0; // 0x0
+    field public static final int SIGNATURE_FIRST_NOT_SIGNED = -1; // 0xffffffff
+    field public static final int SIGNATURE_MATCH = 0; // 0x0
+    field public static final int SIGNATURE_NEITHER_SIGNED = 1; // 0x1
+    field public static final int SIGNATURE_NO_MATCH = -3; // 0xfffffffd
+    field public static final int SIGNATURE_SECOND_NOT_SIGNED = -2; // 0xfffffffe
+    field public static final int SIGNATURE_UNKNOWN_PACKAGE = -4; // 0xfffffffc
+    field public static final int VERIFICATION_ALLOW = 1; // 0x1
+    field public static final int VERIFICATION_REJECT = -1; // 0xffffffff
+  }
+
+  public static class PackageManager.NameNotFoundException extends android.util.AndroidException {
+    ctor public PackageManager.NameNotFoundException();
+    ctor public PackageManager.NameNotFoundException(java.lang.String);
+  }
+
+  public class PackageStats implements android.os.Parcelable {
+    ctor public PackageStats(java.lang.String);
+    ctor public PackageStats(android.os.Parcel);
+    ctor public PackageStats(android.content.pm.PackageStats);
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public long cacheSize;
+    field public long codeSize;
+    field public long dataSize;
+    field public long externalCacheSize;
+    field public long externalCodeSize;
+    field public long externalDataSize;
+    field public long externalMediaSize;
+    field public long externalObbSize;
+    field public java.lang.String packageName;
+  }
+
+  public class PathPermission extends android.os.PatternMatcher {
+    ctor public PathPermission(java.lang.String, int, java.lang.String, java.lang.String);
+    ctor public PathPermission(android.os.Parcel);
+    method public java.lang.String getReadPermission();
+    method public java.lang.String getWritePermission();
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class PermissionGroupInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    ctor public PermissionGroupInfo();
+    ctor public PermissionGroupInfo(android.content.pm.PermissionGroupInfo);
+    method public int describeContents();
+    method public java.lang.CharSequence loadDescription(android.content.pm.PackageManager);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_PERSONAL_INFO = 1; // 0x1
+    field public int descriptionRes;
+    field public int flags;
+    field public java.lang.CharSequence nonLocalizedDescription;
+    field public int priority;
+  }
+
+  public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    ctor public PermissionInfo();
+    ctor public PermissionInfo(android.content.pm.PermissionInfo);
+    method public int describeContents();
+    method public java.lang.CharSequence loadDescription(android.content.pm.PackageManager);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_COSTS_MONEY = 1; // 0x1
+    field public static final int PROTECTION_DANGEROUS = 1; // 0x1
+    field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20
+    field public static final int PROTECTION_FLAG_SYSTEM = 16; // 0x10
+    field public static final int PROTECTION_MASK_BASE = 15; // 0xf
+    field public static final int PROTECTION_MASK_FLAGS = 240; // 0xf0
+    field public static final int PROTECTION_NORMAL = 0; // 0x0
+    field public static final int PROTECTION_SIGNATURE = 2; // 0x2
+    field public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3; // 0x3
+    field public int descriptionRes;
+    field public int flags;
+    field public java.lang.String group;
+    field public java.lang.CharSequence nonLocalizedDescription;
+    field public int protectionLevel;
+  }
+
+  public final class ProviderInfo extends android.content.pm.ComponentInfo implements android.os.Parcelable {
+    ctor public ProviderInfo();
+    ctor public ProviderInfo(android.content.pm.ProviderInfo);
+    method public int describeContents();
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000
+    field public java.lang.String authority;
+    field public int flags;
+    field public boolean grantUriPermissions;
+    field public int initOrder;
+    field public deprecated boolean isSyncable;
+    field public boolean multiprocess;
+    field public android.content.pm.PathPermission[] pathPermissions;
+    field public java.lang.String readPermission;
+    field public android.os.PatternMatcher[] uriPermissionPatterns;
+    field public java.lang.String writePermission;
+  }
+
+  public class ResolveInfo implements android.os.Parcelable {
+    ctor public ResolveInfo();
+    ctor public ResolveInfo(android.content.pm.ResolveInfo);
+    method public int describeContents();
+    method public void dump(android.util.Printer, java.lang.String);
+    method public final int getIconResource();
+    method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
+    method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public android.content.pm.ActivityInfo activityInfo;
+    field public android.content.IntentFilter filter;
+    field public int icon;
+    field public boolean isDefault;
+    field public int labelRes;
+    field public int match;
+    field public java.lang.CharSequence nonLocalizedLabel;
+    field public int preferredOrder;
+    field public int priority;
+    field public java.lang.String resolvePackageName;
+    field public android.content.pm.ServiceInfo serviceInfo;
+    field public int specificIndex;
+  }
+
+  public static class ResolveInfo.DisplayNameComparator implements java.util.Comparator {
+    ctor public ResolveInfo.DisplayNameComparator(android.content.pm.PackageManager);
+    method public final int compare(android.content.pm.ResolveInfo, android.content.pm.ResolveInfo);
+  }
+
+  public class ServiceInfo extends android.content.pm.ComponentInfo implements android.os.Parcelable {
+    ctor public ServiceInfo();
+    ctor public ServiceInfo(android.content.pm.ServiceInfo);
+    method public int describeContents();
+    method public void dump(android.util.Printer, java.lang.String);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_ISOLATED_PROCESS = 2; // 0x2
+    field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000
+    field public static final int FLAG_STOP_WITH_TASK = 1; // 0x1
+    field public int flags;
+    field public java.lang.String permission;
+  }
+
+  public class Signature implements android.os.Parcelable {
+    ctor public Signature(byte[]);
+    ctor public Signature(java.lang.String);
+    method public int describeContents();
+    method public byte[] toByteArray();
+    method public char[] toChars();
+    method public char[] toChars(char[], int[]);
+    method public java.lang.String toCharsString();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+}
+
+package android.content.res {
+
+  public class AssetFileDescriptor implements android.os.Parcelable {
+    ctor public AssetFileDescriptor(android.os.ParcelFileDescriptor, long, long);
+    method public void close() throws java.io.IOException;
+    method public java.io.FileInputStream createInputStream() throws java.io.IOException;
+    method public java.io.FileOutputStream createOutputStream() throws java.io.IOException;
+    method public int describeContents();
+    method public long getDeclaredLength();
+    method public java.io.FileDescriptor getFileDescriptor();
+    method public long getLength();
+    method public android.os.ParcelFileDescriptor getParcelFileDescriptor();
+    method public long getStartOffset();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final long UNKNOWN_LENGTH = -1L; // 0xffffffffffffffffL
+  }
+
+  public static class AssetFileDescriptor.AutoCloseInputStream extends android.os.ParcelFileDescriptor.AutoCloseInputStream {
+    ctor public AssetFileDescriptor.AutoCloseInputStream(android.content.res.AssetFileDescriptor) throws java.io.IOException;
+  }
+
+  public static class AssetFileDescriptor.AutoCloseOutputStream extends android.os.ParcelFileDescriptor.AutoCloseOutputStream {
+    ctor public AssetFileDescriptor.AutoCloseOutputStream(android.content.res.AssetFileDescriptor) throws java.io.IOException;
+  }
+
+  public final class AssetManager {
+    method public void close();
+    method public final java.lang.String[] getLocales();
+    method public final java.lang.String[] list(java.lang.String) throws java.io.IOException;
+    method public final java.io.InputStream open(java.lang.String) throws java.io.IOException;
+    method public final java.io.InputStream open(java.lang.String, int) throws java.io.IOException;
+    method public final android.content.res.AssetFileDescriptor openFd(java.lang.String) throws java.io.IOException;
+    method public final android.content.res.AssetFileDescriptor openNonAssetFd(java.lang.String) throws java.io.IOException;
+    method public final android.content.res.AssetFileDescriptor openNonAssetFd(int, java.lang.String) throws java.io.IOException;
+    method public final android.content.res.XmlResourceParser openXmlResourceParser(java.lang.String) throws java.io.IOException;
+    method public final android.content.res.XmlResourceParser openXmlResourceParser(int, java.lang.String) throws java.io.IOException;
+    field public static final int ACCESS_BUFFER = 3; // 0x3
+    field public static final int ACCESS_RANDOM = 1; // 0x1
+    field public static final int ACCESS_STREAMING = 2; // 0x2
+    field public static final int ACCESS_UNKNOWN = 0; // 0x0
+  }
+
+  public final class AssetManager.AssetInputStream extends java.io.InputStream {
+    method public final int available() throws java.io.IOException;
+    method public final void close() throws java.io.IOException;
+    method public final int getAssetInt();
+    method public final void mark(int);
+    method public final boolean markSupported();
+    method public final int read() throws java.io.IOException;
+    method public final int read(byte[]) throws java.io.IOException;
+    method public final int read(byte[], int, int) throws java.io.IOException;
+    method public final void reset() throws java.io.IOException;
+    method public final long skip(long) throws java.io.IOException;
+  }
+
+  public class ColorStateList implements android.os.Parcelable {
+    ctor public ColorStateList(int[][], int[]);
+    method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public int describeContents();
+    method public int getColorForState(int[], int);
+    method public int getDefaultColor();
+    method public boolean isStateful();
+    method public static android.content.res.ColorStateList valueOf(int);
+    method public android.content.res.ColorStateList withAlpha(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class Configuration implements java.lang.Comparable android.os.Parcelable {
+    ctor public Configuration();
+    ctor public Configuration(android.content.res.Configuration);
+    method public int compareTo(android.content.res.Configuration);
+    method public int describeContents();
+    method public int diff(android.content.res.Configuration);
+    method public boolean equals(android.content.res.Configuration);
+    method public int getLayoutDirection();
+    method public boolean isLayoutSizeAtLeast(int);
+    method public static boolean needNewResources(int, int);
+    method public void readFromParcel(android.os.Parcel);
+    method public void setLayoutDirection(java.util.Locale);
+    method public void setLocale(java.util.Locale);
+    method public void setTo(android.content.res.Configuration);
+    method public void setToDefaults();
+    method public int updateFrom(android.content.res.Configuration);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int DENSITY_DPI_UNDEFINED = 0; // 0x0
+    field public static final int HARDKEYBOARDHIDDEN_NO = 1; // 0x1
+    field public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0; // 0x0
+    field public static final int HARDKEYBOARDHIDDEN_YES = 2; // 0x2
+    field public static final int KEYBOARDHIDDEN_NO = 1; // 0x1
+    field public static final int KEYBOARDHIDDEN_UNDEFINED = 0; // 0x0
+    field public static final int KEYBOARDHIDDEN_YES = 2; // 0x2
+    field public static final int KEYBOARD_12KEY = 3; // 0x3
+    field public static final int KEYBOARD_NOKEYS = 1; // 0x1
+    field public static final int KEYBOARD_QWERTY = 2; // 0x2
+    field public static final int KEYBOARD_UNDEFINED = 0; // 0x0
+    field public static final int NAVIGATIONHIDDEN_NO = 1; // 0x1
+    field public static final int NAVIGATIONHIDDEN_UNDEFINED = 0; // 0x0
+    field public static final int NAVIGATIONHIDDEN_YES = 2; // 0x2
+    field public static final int NAVIGATION_DPAD = 2; // 0x2
+    field public static final int NAVIGATION_NONAV = 1; // 0x1
+    field public static final int NAVIGATION_TRACKBALL = 3; // 0x3
+    field public static final int NAVIGATION_UNDEFINED = 0; // 0x0
+    field public static final int NAVIGATION_WHEEL = 4; // 0x4
+    field public static final int ORIENTATION_LANDSCAPE = 2; // 0x2
+    field public static final int ORIENTATION_PORTRAIT = 1; // 0x1
+    field public static final deprecated int ORIENTATION_SQUARE = 3; // 0x3
+    field public static final int ORIENTATION_UNDEFINED = 0; // 0x0
+    field public static final int SCREENLAYOUT_LAYOUTDIR_LTR = 64; // 0x40
+    field public static final int SCREENLAYOUT_LAYOUTDIR_MASK = 192; // 0xc0
+    field public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 128; // 0x80
+    field public static final int SCREENLAYOUT_LAYOUTDIR_SHIFT = 6; // 0x6
+    field public static final int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0; // 0x0
+    field public static final int SCREENLAYOUT_LONG_MASK = 48; // 0x30
+    field public static final int SCREENLAYOUT_LONG_NO = 16; // 0x10
+    field public static final int SCREENLAYOUT_LONG_UNDEFINED = 0; // 0x0
+    field public static final int SCREENLAYOUT_LONG_YES = 32; // 0x20
+    field public static final int SCREENLAYOUT_SIZE_LARGE = 3; // 0x3
+    field public static final int SCREENLAYOUT_SIZE_MASK = 15; // 0xf
+    field public static final int SCREENLAYOUT_SIZE_NORMAL = 2; // 0x2
+    field public static final int SCREENLAYOUT_SIZE_SMALL = 1; // 0x1
+    field public static final int SCREENLAYOUT_SIZE_UNDEFINED = 0; // 0x0
+    field public static final int SCREENLAYOUT_SIZE_XLARGE = 4; // 0x4
+    field public static final int SCREENLAYOUT_UNDEFINED = 0; // 0x0
+    field public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0; // 0x0
+    field public static final int SCREEN_WIDTH_DP_UNDEFINED = 0; // 0x0
+    field public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0; // 0x0
+    field public static final int TOUCHSCREEN_FINGER = 3; // 0x3
+    field public static final int TOUCHSCREEN_NOTOUCH = 1; // 0x1
+    field public static final deprecated int TOUCHSCREEN_STYLUS = 2; // 0x2
+    field public static final int TOUCHSCREEN_UNDEFINED = 0; // 0x0
+    field public static final int UI_MODE_NIGHT_MASK = 48; // 0x30
+    field public static final int UI_MODE_NIGHT_NO = 16; // 0x10
+    field public static final int UI_MODE_NIGHT_UNDEFINED = 0; // 0x0
+    field public static final int UI_MODE_NIGHT_YES = 32; // 0x20
+    field public static final int UI_MODE_TYPE_APPLIANCE = 5; // 0x5
+    field public static final int UI_MODE_TYPE_CAR = 3; // 0x3
+    field public static final int UI_MODE_TYPE_DESK = 2; // 0x2
+    field public static final int UI_MODE_TYPE_MASK = 15; // 0xf
+    field public static final int UI_MODE_TYPE_NORMAL = 1; // 0x1
+    field public static final int UI_MODE_TYPE_TELEVISION = 4; // 0x4
+    field public static final int UI_MODE_TYPE_UNDEFINED = 0; // 0x0
+    field public int densityDpi;
+    field public float fontScale;
+    field public int hardKeyboardHidden;
+    field public int keyboard;
+    field public int keyboardHidden;
+    field public java.util.Locale locale;
+    field public int mcc;
+    field public int mnc;
+    field public int navigation;
+    field public int navigationHidden;
+    field public int orientation;
+    field public int screenHeightDp;
+    field public int screenLayout;
+    field public int screenWidthDp;
+    field public int smallestScreenWidthDp;
+    field public int touchscreen;
+    field public int uiMode;
+  }
+
+  public class ObbInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int OBB_OVERLAY = 1; // 0x1
+    field public java.lang.String filename;
+    field public int flags;
+    field public java.lang.String packageName;
+    field public int version;
+  }
+
+  public class ObbScanner {
+    method public static android.content.res.ObbInfo getObbInfo(java.lang.String) throws java.io.IOException;
+  }
+
+  public class Resources {
+    ctor public Resources(android.content.res.AssetManager, android.util.DisplayMetrics, android.content.res.Configuration);
+    method public final void finishPreloading();
+    method public final void flushLayoutCache();
+    method public android.content.res.XmlResourceParser getAnimation(int) throws android.content.res.Resources.NotFoundException;
+    method public final android.content.res.AssetManager getAssets();
+    method public boolean getBoolean(int) throws android.content.res.Resources.NotFoundException;
+    method public int getColor(int) throws android.content.res.Resources.NotFoundException;
+    method public android.content.res.ColorStateList getColorStateList(int) throws android.content.res.Resources.NotFoundException;
+    method public android.content.res.Configuration getConfiguration();
+    method public float getDimension(int) throws android.content.res.Resources.NotFoundException;
+    method public int getDimensionPixelOffset(int) throws android.content.res.Resources.NotFoundException;
+    method public int getDimensionPixelSize(int) throws android.content.res.Resources.NotFoundException;
+    method public android.util.DisplayMetrics getDisplayMetrics();
+    method public android.graphics.drawable.Drawable getDrawable(int) throws android.content.res.Resources.NotFoundException;
+    method public android.graphics.drawable.Drawable getDrawableForDensity(int, int) throws android.content.res.Resources.NotFoundException;
+    method public float getFraction(int, int, int);
+    method public int getIdentifier(java.lang.String, java.lang.String, java.lang.String);
+    method public int[] getIntArray(int) throws android.content.res.Resources.NotFoundException;
+    method public int getInteger(int) throws android.content.res.Resources.NotFoundException;
+    method public android.content.res.XmlResourceParser getLayout(int) throws android.content.res.Resources.NotFoundException;
+    method public android.graphics.Movie getMovie(int) throws android.content.res.Resources.NotFoundException;
+    method public java.lang.String getQuantityString(int, int, java.lang.Object...) throws android.content.res.Resources.NotFoundException;
+    method public java.lang.String getQuantityString(int, int) throws android.content.res.Resources.NotFoundException;
+    method public java.lang.CharSequence getQuantityText(int, int) throws android.content.res.Resources.NotFoundException;
+    method public java.lang.String getResourceEntryName(int) throws android.content.res.Resources.NotFoundException;
+    method public java.lang.String getResourceName(int) throws android.content.res.Resources.NotFoundException;
+    method public java.lang.String getResourcePackageName(int) throws android.content.res.Resources.NotFoundException;
+    method public java.lang.String getResourceTypeName(int) throws android.content.res.Resources.NotFoundException;
+    method public java.lang.String getString(int) throws android.content.res.Resources.NotFoundException;
+    method public java.lang.String getString(int, java.lang.Object...) throws android.content.res.Resources.NotFoundException;
+    method public java.lang.String[] getStringArray(int) throws android.content.res.Resources.NotFoundException;
+    method public static android.content.res.Resources getSystem();
+    method public java.lang.CharSequence getText(int) throws android.content.res.Resources.NotFoundException;
+    method public java.lang.CharSequence getText(int, java.lang.CharSequence);
+    method public java.lang.CharSequence[] getTextArray(int) throws android.content.res.Resources.NotFoundException;
+    method public void getValue(int, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException;
+    method public void getValue(java.lang.String, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException;
+    method public void getValueForDensity(int, int, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException;
+    method public android.content.res.XmlResourceParser getXml(int) throws android.content.res.Resources.NotFoundException;
+    method public final android.content.res.Resources.Theme newTheme();
+    method public android.content.res.TypedArray obtainAttributes(android.util.AttributeSet, int[]);
+    method public android.content.res.TypedArray obtainTypedArray(int) throws android.content.res.Resources.NotFoundException;
+    method public java.io.InputStream openRawResource(int) throws android.content.res.Resources.NotFoundException;
+    method public java.io.InputStream openRawResource(int, android.util.TypedValue) throws android.content.res.Resources.NotFoundException;
+    method public android.content.res.AssetFileDescriptor openRawResourceFd(int) throws android.content.res.Resources.NotFoundException;
+    method public void parseBundleExtra(java.lang.String, android.util.AttributeSet, android.os.Bundle) throws org.xmlpull.v1.XmlPullParserException;
+    method public void parseBundleExtras(android.content.res.XmlResourceParser, android.os.Bundle) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics);
+  }
+
+  public static class Resources.NotFoundException extends java.lang.RuntimeException {
+    ctor public Resources.NotFoundException();
+    ctor public Resources.NotFoundException(java.lang.String);
+  }
+
+  public final class Resources.Theme {
+    method public void applyStyle(int, boolean);
+    method public void dump(int, java.lang.String, java.lang.String);
+    method public android.content.res.TypedArray obtainStyledAttributes(int[]);
+    method public android.content.res.TypedArray obtainStyledAttributes(int, int[]) throws android.content.res.Resources.NotFoundException;
+    method public android.content.res.TypedArray obtainStyledAttributes(android.util.AttributeSet, int[], int, int);
+    method public boolean resolveAttribute(int, android.util.TypedValue, boolean);
+    method public void setTo(android.content.res.Resources.Theme);
+  }
+
+  public class TypedArray {
+    method public boolean getBoolean(int, boolean);
+    method public int getColor(int, int);
+    method public android.content.res.ColorStateList getColorStateList(int);
+    method public float getDimension(int, float);
+    method public int getDimensionPixelOffset(int, int);
+    method public int getDimensionPixelSize(int, int);
+    method public android.graphics.drawable.Drawable getDrawable(int);
+    method public float getFloat(int, float);
+    method public float getFraction(int, int, int, float);
+    method public int getIndex(int);
+    method public int getIndexCount();
+    method public int getInt(int, int);
+    method public int getInteger(int, int);
+    method public int getLayoutDimension(int, java.lang.String);
+    method public int getLayoutDimension(int, int);
+    method public java.lang.String getNonResourceString(int);
+    method public java.lang.String getPositionDescription();
+    method public int getResourceId(int, int);
+    method public android.content.res.Resources getResources();
+    method public java.lang.String getString(int);
+    method public java.lang.CharSequence getText(int);
+    method public java.lang.CharSequence[] getTextArray(int);
+    method public boolean getValue(int, android.util.TypedValue);
+    method public boolean hasValue(int);
+    method public int length();
+    method public android.util.TypedValue peekValue(int);
+    method public void recycle();
+  }
+
+  public abstract interface XmlResourceParser implements android.util.AttributeSet org.xmlpull.v1.XmlPullParser {
+    method public abstract void close();
+  }
+
+}
+
+package android.database {
+
+  public abstract class AbstractCursor implements android.database.CrossProcessCursor {
+    ctor public AbstractCursor();
+    method protected void checkPosition();
+    method public void close();
+    method public void copyStringToBuffer(int, android.database.CharArrayBuffer);
+    method public void deactivate();
+    method public void fillWindow(int, android.database.CursorWindow);
+    method public byte[] getBlob(int);
+    method public int getColumnCount();
+    method public int getColumnIndex(java.lang.String);
+    method public int getColumnIndexOrThrow(java.lang.String);
+    method public java.lang.String getColumnName(int);
+    method public abstract java.lang.String[] getColumnNames();
+    method public abstract int getCount();
+    method public abstract double getDouble(int);
+    method public android.os.Bundle getExtras();
+    method public abstract float getFloat(int);
+    method public abstract int getInt(int);
+    method public abstract long getLong(int);
+    method public android.net.Uri getNotificationUri();
+    method public final int getPosition();
+    method public abstract short getShort(int);
+    method public abstract java.lang.String getString(int);
+    method public int getType(int);
+    method protected deprecated java.lang.Object getUpdatedField(int);
+    method public boolean getWantsAllOnMoveCalls();
+    method public android.database.CursorWindow getWindow();
+    method public final boolean isAfterLast();
+    method public final boolean isBeforeFirst();
+    method public boolean isClosed();
+    method protected deprecated boolean isFieldUpdated(int);
+    method public final boolean isFirst();
+    method public final boolean isLast();
+    method public abstract boolean isNull(int);
+    method public final boolean move(int);
+    method public final boolean moveToFirst();
+    method public final boolean moveToLast();
+    method public final boolean moveToNext();
+    method public final boolean moveToPosition(int);
+    method public final boolean moveToPrevious();
+    method protected void onChange(boolean);
+    method public boolean onMove(int, int);
+    method public void registerContentObserver(android.database.ContentObserver);
+    method public void registerDataSetObserver(android.database.DataSetObserver);
+    method public boolean requery();
+    method public android.os.Bundle respond(android.os.Bundle);
+    method public void setNotificationUri(android.content.ContentResolver, android.net.Uri);
+    method public void unregisterContentObserver(android.database.ContentObserver);
+    method public void unregisterDataSetObserver(android.database.DataSetObserver);
+    field protected boolean mClosed;
+    field protected android.content.ContentResolver mContentResolver;
+    field protected deprecated java.lang.Long mCurrentRowID;
+    field protected int mPos;
+    field protected deprecated int mRowIdColumnIndex;
+    field protected deprecated java.util.HashMap mUpdatedRows;
+  }
+
+  protected static class AbstractCursor.SelfContentObserver extends android.database.ContentObserver {
+    ctor public AbstractCursor.SelfContentObserver(android.database.AbstractCursor);
+  }
+
+  public abstract class AbstractWindowedCursor extends android.database.AbstractCursor {
+    ctor public AbstractWindowedCursor();
+    method public double getDouble(int);
+    method public float getFloat(int);
+    method public int getInt(int);
+    method public long getLong(int);
+    method public short getShort(int);
+    method public java.lang.String getString(int);
+    method public boolean hasWindow();
+    method public deprecated boolean isBlob(int);
+    method public deprecated boolean isFloat(int);
+    method public deprecated boolean isLong(int);
+    method public boolean isNull(int);
+    method public deprecated boolean isString(int);
+    method public void setWindow(android.database.CursorWindow);
+    field protected android.database.CursorWindow mWindow;
+  }
+
+  public final class CharArrayBuffer {
+    ctor public CharArrayBuffer(int);
+    ctor public CharArrayBuffer(char[]);
+    field public char[] data;
+    field public int sizeCopied;
+  }
+
+  public class ContentObservable extends android.database.Observable {
+    ctor public ContentObservable();
+    method public deprecated void dispatchChange(boolean);
+    method public void dispatchChange(boolean, android.net.Uri);
+    method public deprecated void notifyChange(boolean);
+    method public void registerObserver(android.database.ContentObserver);
+  }
+
+  public abstract class ContentObserver {
+    ctor public ContentObserver(android.os.Handler);
+    method public boolean deliverSelfNotifications();
+    method public final deprecated void dispatchChange(boolean);
+    method public final void dispatchChange(boolean, android.net.Uri);
+    method public void onChange(boolean);
+    method public void onChange(boolean, android.net.Uri);
+  }
+
+  public abstract interface CrossProcessCursor implements android.database.Cursor {
+    method public abstract void fillWindow(int, android.database.CursorWindow);
+    method public abstract android.database.CursorWindow getWindow();
+    method public abstract boolean onMove(int, int);
+  }
+
+  public class CrossProcessCursorWrapper extends android.database.CursorWrapper implements android.database.CrossProcessCursor {
+    ctor public CrossProcessCursorWrapper(android.database.Cursor);
+    method public void fillWindow(int, android.database.CursorWindow);
+    method public android.database.CursorWindow getWindow();
+    method public boolean onMove(int, int);
+  }
+
+  public abstract interface Cursor implements java.io.Closeable {
+    method public abstract void close();
+    method public abstract void copyStringToBuffer(int, android.database.CharArrayBuffer);
+    method public abstract deprecated void deactivate();
+    method public abstract byte[] getBlob(int);
+    method public abstract int getColumnCount();
+    method public abstract int getColumnIndex(java.lang.String);
+    method public abstract int getColumnIndexOrThrow(java.lang.String) throws java.lang.IllegalArgumentException;
+    method public abstract java.lang.String getColumnName(int);
+    method public abstract java.lang.String[] getColumnNames();
+    method public abstract int getCount();
+    method public abstract double getDouble(int);
+    method public abstract android.os.Bundle getExtras();
+    method public abstract float getFloat(int);
+    method public abstract int getInt(int);
+    method public abstract long getLong(int);
+    method public abstract int getPosition();
+    method public abstract short getShort(int);
+    method public abstract java.lang.String getString(int);
+    method public abstract int getType(int);
+    method public abstract boolean getWantsAllOnMoveCalls();
+    method public abstract boolean isAfterLast();
+    method public abstract boolean isBeforeFirst();
+    method public abstract boolean isClosed();
+    method public abstract boolean isFirst();
+    method public abstract boolean isLast();
+    method public abstract boolean isNull(int);
+    method public abstract boolean move(int);
+    method public abstract boolean moveToFirst();
+    method public abstract boolean moveToLast();
+    method public abstract boolean moveToNext();
+    method public abstract boolean moveToPosition(int);
+    method public abstract boolean moveToPrevious();
+    method public abstract void registerContentObserver(android.database.ContentObserver);
+    method public abstract void registerDataSetObserver(android.database.DataSetObserver);
+    method public abstract deprecated boolean requery();
+    method public abstract android.os.Bundle respond(android.os.Bundle);
+    method public abstract void setNotificationUri(android.content.ContentResolver, android.net.Uri);
+    method public abstract void unregisterContentObserver(android.database.ContentObserver);
+    method public abstract void unregisterDataSetObserver(android.database.DataSetObserver);
+    field public static final int FIELD_TYPE_BLOB = 4; // 0x4
+    field public static final int FIELD_TYPE_FLOAT = 2; // 0x2
+    field public static final int FIELD_TYPE_INTEGER = 1; // 0x1
+    field public static final int FIELD_TYPE_NULL = 0; // 0x0
+    field public static final int FIELD_TYPE_STRING = 3; // 0x3
+  }
+
+  public class CursorIndexOutOfBoundsException extends java.lang.IndexOutOfBoundsException {
+    ctor public CursorIndexOutOfBoundsException(int, int);
+    ctor public CursorIndexOutOfBoundsException(java.lang.String);
+  }
+
+  public final class CursorJoiner implements java.lang.Iterable java.util.Iterator {
+    ctor public CursorJoiner(android.database.Cursor, java.lang.String[], android.database.Cursor, java.lang.String[]);
+    method public boolean hasNext();
+    method public java.util.Iterator<android.database.CursorJoiner.Result> iterator();
+    method public android.database.CursorJoiner.Result next();
+    method public void remove();
+  }
+
+  public static final class CursorJoiner.Result extends java.lang.Enum {
+    method public static android.database.CursorJoiner.Result valueOf(java.lang.String);
+    method public static final android.database.CursorJoiner.Result[] values();
+    enum_constant public static final android.database.CursorJoiner.Result BOTH;
+    enum_constant public static final android.database.CursorJoiner.Result LEFT;
+    enum_constant public static final android.database.CursorJoiner.Result RIGHT;
+  }
+
+  public class CursorWindow extends android.database.sqlite.SQLiteClosable implements android.os.Parcelable {
+    ctor public CursorWindow(java.lang.String);
+    ctor public deprecated CursorWindow(boolean);
+    method public boolean allocRow();
+    method public void clear();
+    method public void copyStringToBuffer(int, int, android.database.CharArrayBuffer);
+    method public int describeContents();
+    method public void freeLastRow();
+    method public byte[] getBlob(int, int);
+    method public double getDouble(int, int);
+    method public float getFloat(int, int);
+    method public int getInt(int, int);
+    method public long getLong(int, int);
+    method public int getNumRows();
+    method public short getShort(int, int);
+    method public int getStartPosition();
+    method public java.lang.String getString(int, int);
+    method public int getType(int, int);
+    method public deprecated boolean isBlob(int, int);
+    method public deprecated boolean isFloat(int, int);
+    method public deprecated boolean isLong(int, int);
+    method public deprecated boolean isNull(int, int);
+    method public deprecated boolean isString(int, int);
+    method public static android.database.CursorWindow newFromParcel(android.os.Parcel);
+    method protected void onAllReferencesReleased();
+    method public boolean putBlob(byte[], int, int);
+    method public boolean putDouble(double, int, int);
+    method public boolean putLong(long, int, int);
+    method public boolean putNull(int, int);
+    method public boolean putString(java.lang.String, int, int);
+    method public boolean setNumColumns(int);
+    method public void setStartPosition(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class CursorWrapper implements android.database.Cursor {
+    ctor public CursorWrapper(android.database.Cursor);
+    method public void close();
+    method public void copyStringToBuffer(int, android.database.CharArrayBuffer);
+    method public void deactivate();
+    method public byte[] getBlob(int);
+    method public int getColumnCount();
+    method public int getColumnIndex(java.lang.String);
+    method public int getColumnIndexOrThrow(java.lang.String) throws java.lang.IllegalArgumentException;
+    method public java.lang.String getColumnName(int);
+    method public java.lang.String[] getColumnNames();
+    method public int getCount();
+    method public double getDouble(int);
+    method public android.os.Bundle getExtras();
+    method public float getFloat(int);
+    method public int getInt(int);
+    method public long getLong(int);
+    method public int getPosition();
+    method public short getShort(int);
+    method public java.lang.String getString(int);
+    method public int getType(int);
+    method public boolean getWantsAllOnMoveCalls();
+    method public android.database.Cursor getWrappedCursor();
+    method public boolean isAfterLast();
+    method public boolean isBeforeFirst();
+    method public boolean isClosed();
+    method public boolean isFirst();
+    method public boolean isLast();
+    method public boolean isNull(int);
+    method public boolean move(int);
+    method public boolean moveToFirst();
+    method public boolean moveToLast();
+    method public boolean moveToNext();
+    method public boolean moveToPosition(int);
+    method public boolean moveToPrevious();
+    method public void registerContentObserver(android.database.ContentObserver);
+    method public void registerDataSetObserver(android.database.DataSetObserver);
+    method public boolean requery();
+    method public android.os.Bundle respond(android.os.Bundle);
+    method public void setNotificationUri(android.content.ContentResolver, android.net.Uri);
+    method public void unregisterContentObserver(android.database.ContentObserver);
+    method public void unregisterDataSetObserver(android.database.DataSetObserver);
+  }
+
+  public class DataSetObservable extends android.database.Observable {
+    ctor public DataSetObservable();
+    method public void notifyChanged();
+    method public void notifyInvalidated();
+  }
+
+  public abstract class DataSetObserver {
+    ctor public DataSetObserver();
+    method public void onChanged();
+    method public void onInvalidated();
+  }
+
+  public abstract interface DatabaseErrorHandler {
+    method public abstract void onCorruption(android.database.sqlite.SQLiteDatabase);
+  }
+
+  public class DatabaseUtils {
+    ctor public DatabaseUtils();
+    method public static void appendEscapedSQLString(java.lang.StringBuilder, java.lang.String);
+    method public static java.lang.String[] appendSelectionArgs(java.lang.String[], java.lang.String[]);
+    method public static final void appendValueToSql(java.lang.StringBuilder, java.lang.Object);
+    method public static void bindObjectToProgram(android.database.sqlite.SQLiteProgram, int, java.lang.Object);
+    method public static android.os.ParcelFileDescriptor blobFileDescriptorForQuery(android.database.sqlite.SQLiteDatabase, java.lang.String, java.lang.String[]);
+    method public static android.os.ParcelFileDescriptor blobFileDescriptorForQuery(android.database.sqlite.SQLiteStatement, java.lang.String[]);
+    method public static java.lang.String concatenateWhere(java.lang.String, java.lang.String);
+    method public static void createDbFromSqlStatements(android.content.Context, java.lang.String, int, java.lang.String);
+    method public static void cursorDoubleToContentValues(android.database.Cursor, java.lang.String, android.content.ContentValues, java.lang.String);
+    method public static void cursorDoubleToContentValuesIfPresent(android.database.Cursor, android.content.ContentValues, java.lang.String);
+    method public static void cursorDoubleToCursorValues(android.database.Cursor, java.lang.String, android.content.ContentValues);
+    method public static void cursorFloatToContentValuesIfPresent(android.database.Cursor, android.content.ContentValues, java.lang.String);
+    method public static void cursorIntToContentValues(android.database.Cursor, java.lang.String, android.content.ContentValues);
+    method public static void cursorIntToContentValues(android.database.Cursor, java.lang.String, android.content.ContentValues, java.lang.String);
+    method public static void cursorIntToContentValuesIfPresent(android.database.Cursor, android.content.ContentValues, java.lang.String);
+    method public static void cursorLongToContentValues(android.database.Cursor, java.lang.String, android.content.ContentValues);
+    method public static void cursorLongToContentValues(android.database.Cursor, java.lang.String, android.content.ContentValues, java.lang.String);
+    method public static void cursorLongToContentValuesIfPresent(android.database.Cursor, android.content.ContentValues, java.lang.String);
+    method public static void cursorRowToContentValues(android.database.Cursor, android.content.ContentValues);
+    method public static void cursorShortToContentValuesIfPresent(android.database.Cursor, android.content.ContentValues, java.lang.String);
+    method public static void cursorStringToContentValues(android.database.Cursor, java.lang.String, android.content.ContentValues);
+    method public static void cursorStringToContentValues(android.database.Cursor, java.lang.String, android.content.ContentValues, java.lang.String);
+    method public static void cursorStringToContentValuesIfPresent(android.database.Cursor, android.content.ContentValues, java.lang.String);
+    method public static void cursorStringToInsertHelper(android.database.Cursor, java.lang.String, android.database.DatabaseUtils.InsertHelper, int);
+    method public static void dumpCurrentRow(android.database.Cursor);
+    method public static void dumpCurrentRow(android.database.Cursor, java.io.PrintStream);
+    method public static void dumpCurrentRow(android.database.Cursor, java.lang.StringBuilder);
+    method public static java.lang.String dumpCurrentRowToString(android.database.Cursor);
+    method public static void dumpCursor(android.database.Cursor);
+    method public static void dumpCursor(android.database.Cursor, java.io.PrintStream);
+    method public static void dumpCursor(android.database.Cursor, java.lang.StringBuilder);
+    method public static java.lang.String dumpCursorToString(android.database.Cursor);
+    method public static java.lang.String getCollationKey(java.lang.String);
+    method public static java.lang.String getHexCollationKey(java.lang.String);
+    method public static int getSqlStatementType(java.lang.String);
+    method public static long longForQuery(android.database.sqlite.SQLiteDatabase, java.lang.String, java.lang.String[]);
+    method public static long longForQuery(android.database.sqlite.SQLiteStatement, java.lang.String[]);
+    method public static long queryNumEntries(android.database.sqlite.SQLiteDatabase, java.lang.String);
+    method public static long queryNumEntries(android.database.sqlite.SQLiteDatabase, java.lang.String, java.lang.String);
+    method public static long queryNumEntries(android.database.sqlite.SQLiteDatabase, java.lang.String, java.lang.String, java.lang.String[]);
+    method public static final void readExceptionFromParcel(android.os.Parcel);
+    method public static void readExceptionWithFileNotFoundExceptionFromParcel(android.os.Parcel) throws java.io.FileNotFoundException;
+    method public static void readExceptionWithOperationApplicationExceptionFromParcel(android.os.Parcel) throws android.content.OperationApplicationException;
+    method public static java.lang.String sqlEscapeString(java.lang.String);
+    method public static java.lang.String stringForQuery(android.database.sqlite.SQLiteDatabase, java.lang.String, java.lang.String[]);
+    method public static java.lang.String stringForQuery(android.database.sqlite.SQLiteStatement, java.lang.String[]);
+    method public static final void writeExceptionToParcel(android.os.Parcel, java.lang.Exception);
+    field public static final int STATEMENT_ABORT = 6; // 0x6
+    field public static final int STATEMENT_ATTACH = 3; // 0x3
+    field public static final int STATEMENT_BEGIN = 4; // 0x4
+    field public static final int STATEMENT_COMMIT = 5; // 0x5
+    field public static final int STATEMENT_DDL = 8; // 0x8
+    field public static final int STATEMENT_OTHER = 99; // 0x63
+    field public static final int STATEMENT_PRAGMA = 7; // 0x7
+    field public static final int STATEMENT_SELECT = 1; // 0x1
+    field public static final int STATEMENT_UNPREPARED = 9; // 0x9
+    field public static final int STATEMENT_UPDATE = 2; // 0x2
+  }
+
+  public static deprecated class DatabaseUtils.InsertHelper {
+    ctor public DatabaseUtils.InsertHelper(android.database.sqlite.SQLiteDatabase, java.lang.String);
+    method public void bind(int, double);
+    method public void bind(int, float);
+    method public void bind(int, long);
+    method public void bind(int, int);
+    method public void bind(int, boolean);
+    method public void bind(int, byte[]);
+    method public void bind(int, java.lang.String);
+    method public void bindNull(int);
+    method public void close();
+    method public long execute();
+    method public int getColumnIndex(java.lang.String);
+    method public long insert(android.content.ContentValues);
+    method public void prepareForInsert();
+    method public void prepareForReplace();
+    method public long replace(android.content.ContentValues);
+  }
+
+  public final class DefaultDatabaseErrorHandler implements android.database.DatabaseErrorHandler {
+    ctor public DefaultDatabaseErrorHandler();
+    method public void onCorruption(android.database.sqlite.SQLiteDatabase);
+  }
+
+  public class MatrixCursor extends android.database.AbstractCursor {
+    ctor public MatrixCursor(java.lang.String[], int);
+    ctor public MatrixCursor(java.lang.String[]);
+    method public void addRow(java.lang.Object[]);
+    method public void addRow(java.lang.Iterable<?>);
+    method public java.lang.String[] getColumnNames();
+    method public int getCount();
+    method public double getDouble(int);
+    method public float getFloat(int);
+    method public int getInt(int);
+    method public long getLong(int);
+    method public short getShort(int);
+    method public java.lang.String getString(int);
+    method public boolean isNull(int);
+    method public android.database.MatrixCursor.RowBuilder newRow();
+  }
+
+  public class MatrixCursor.RowBuilder {
+    method public android.database.MatrixCursor.RowBuilder add(java.lang.Object);
+  }
+
+  public class MergeCursor extends android.database.AbstractCursor {
+    ctor public MergeCursor(android.database.Cursor[]);
+    method public java.lang.String[] getColumnNames();
+    method public int getCount();
+    method public double getDouble(int);
+    method public float getFloat(int);
+    method public int getInt(int);
+    method public long getLong(int);
+    method public short getShort(int);
+    method public java.lang.String getString(int);
+    method public boolean isNull(int);
+  }
+
+  public abstract class Observable {
+    ctor public Observable();
+    method public void registerObserver(T);
+    method public void unregisterAll();
+    method public void unregisterObserver(T);
+    field protected final java.util.ArrayList mObservers;
+  }
+
+  public class SQLException extends java.lang.RuntimeException {
+    ctor public SQLException();
+    ctor public SQLException(java.lang.String);
+    ctor public SQLException(java.lang.String, java.lang.Throwable);
+  }
+
+  public class StaleDataException extends java.lang.RuntimeException {
+    ctor public StaleDataException();
+    ctor public StaleDataException(java.lang.String);
+  }
+
+}
+
+package android.database.sqlite {
+
+  public class SQLiteAbortException extends android.database.sqlite.SQLiteException {
+    ctor public SQLiteAbortException();
+    ctor public SQLiteAbortException(java.lang.String);
+  }
+
+  public class SQLiteAccessPermException extends android.database.sqlite.SQLiteException {
+    ctor public SQLiteAccessPermException();
+    ctor public SQLiteAccessPermException(java.lang.String);
+  }
+
+  public class SQLiteBindOrColumnIndexOutOfRangeException extends android.database.sqlite.SQLiteException {
+    ctor public SQLiteBindOrColumnIndexOutOfRangeException();
+    ctor public SQLiteBindOrColumnIndexOutOfRangeException(java.lang.String);
+  }
+
+  public class SQLiteBlobTooBigException extends android.database.sqlite.SQLiteException {
+    ctor public SQLiteBlobTooBigException();
+    ctor public SQLiteBlobTooBigException(java.lang.String);
+  }
+
+  public class SQLiteCantOpenDatabaseException extends android.database.sqlite.SQLiteException {
+    ctor public SQLiteCantOpenDatabaseException();
+    ctor public SQLiteCantOpenDatabaseException(java.lang.String);
+  }
+
+  public abstract class SQLiteClosable implements java.io.Closeable {
+    ctor public SQLiteClosable();
+    method public void acquireReference();
+    method public void close();
+    method protected abstract void onAllReferencesReleased();
+    method protected deprecated void onAllReferencesReleasedFromContainer();
+    method public void releaseReference();
+    method public deprecated void releaseReferenceFromContainer();
+  }
+
+  public class SQLiteConstraintException extends android.database.sqlite.SQLiteException {
+    ctor public SQLiteConstraintException();
+    ctor public SQLiteConstraintException(java.lang.String);
+  }
+
+  public class SQLiteCursor extends android.database.AbstractWindowedCursor {
+    ctor public deprecated SQLiteCursor(android.database.sqlite.SQLiteDatabase, android.database.sqlite.SQLiteCursorDriver, java.lang.String, android.database.sqlite.SQLiteQuery);
+    ctor public SQLiteCursor(android.database.sqlite.SQLiteCursorDriver, java.lang.String, android.database.sqlite.SQLiteQuery);
+    method public java.lang.String[] getColumnNames();
+    method public int getCount();
+    method public android.database.sqlite.SQLiteDatabase getDatabase();
+    method public void setSelectionArguments(java.lang.String[]);
+  }
+
+  public abstract interface SQLiteCursorDriver {
+    method public abstract void cursorClosed();
+    method public abstract void cursorDeactivated();
+    method public abstract void cursorRequeried(android.database.Cursor);
+    method public abstract android.database.Cursor query(android.database.sqlite.SQLiteDatabase.CursorFactory, java.lang.String[]);
+    method public abstract void setBindArguments(java.lang.String[]);
+  }
+
+  public final class SQLiteDatabase extends android.database.sqlite.SQLiteClosable {
+    method public void beginTransaction();
+    method public void beginTransactionNonExclusive();
+    method public void beginTransactionWithListener(android.database.sqlite.SQLiteTransactionListener);
+    method public void beginTransactionWithListenerNonExclusive(android.database.sqlite.SQLiteTransactionListener);
+    method public android.database.sqlite.SQLiteStatement compileStatement(java.lang.String) throws android.database.SQLException;
+    method public static android.database.sqlite.SQLiteDatabase create(android.database.sqlite.SQLiteDatabase.CursorFactory);
+    method public int delete(java.lang.String, java.lang.String, java.lang.String[]);
+    method public static boolean deleteDatabase(java.io.File);
+    method public void disableWriteAheadLogging();
+    method public boolean enableWriteAheadLogging();
+    method public void endTransaction();
+    method public void execSQL(java.lang.String) throws android.database.SQLException;
+    method public void execSQL(java.lang.String, java.lang.Object[]) throws android.database.SQLException;
+    method public static java.lang.String findEditTable(java.lang.String);
+    method public java.util.List<android.util.Pair<java.lang.String, java.lang.String>> getAttachedDbs();
+    method public long getMaximumSize();
+    method public long getPageSize();
+    method public final java.lang.String getPath();
+    method public deprecated java.util.Map<java.lang.String, java.lang.String> getSyncedTables();
+    method public int getVersion();
+    method public boolean inTransaction();
+    method public long insert(java.lang.String, java.lang.String, android.content.ContentValues);
+    method public long insertOrThrow(java.lang.String, java.lang.String, android.content.ContentValues) throws android.database.SQLException;
+    method public long insertWithOnConflict(java.lang.String, java.lang.String, android.content.ContentValues, int);
+    method public boolean isDatabaseIntegrityOk();
+    method public boolean isDbLockedByCurrentThread();
+    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);
+    method protected void onAllReferencesReleased();
+    method public static android.database.sqlite.SQLiteDatabase openDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory, int);
+    method public static android.database.sqlite.SQLiteDatabase openDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory, int, android.database.DatabaseErrorHandler);
+    method public static android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.io.File, android.database.sqlite.SQLiteDatabase.CursorFactory);
+    method public static android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory);
+    method public static android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory, android.database.DatabaseErrorHandler);
+    method public android.database.Cursor query(boolean, java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public android.database.Cursor query(boolean, java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String, android.os.CancellationSignal);
+    method public android.database.Cursor query(java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String);
+    method public android.database.Cursor query(java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public android.database.Cursor queryWithFactory(android.database.sqlite.SQLiteDatabase.CursorFactory, boolean, java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public android.database.Cursor queryWithFactory(android.database.sqlite.SQLiteDatabase.CursorFactory, boolean, java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String, android.os.CancellationSignal);
+    method public android.database.Cursor rawQuery(java.lang.String, java.lang.String[]);
+    method public android.database.Cursor rawQuery(java.lang.String, java.lang.String[], android.os.CancellationSignal);
+    method public android.database.Cursor rawQueryWithFactory(android.database.sqlite.SQLiteDatabase.CursorFactory, java.lang.String, java.lang.String[], java.lang.String);
+    method public android.database.Cursor rawQueryWithFactory(android.database.sqlite.SQLiteDatabase.CursorFactory, java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+    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);
+    method public long setMaximumSize(long);
+    method public void setPageSize(long);
+    method public void setTransactionSuccessful();
+    method public void setVersion(int);
+    method public int update(java.lang.String, android.content.ContentValues, java.lang.String, java.lang.String[]);
+    method public int updateWithOnConflict(java.lang.String, android.content.ContentValues, java.lang.String, java.lang.String[], int);
+    method public deprecated boolean yieldIfContended();
+    method public boolean yieldIfContendedSafely();
+    method public boolean yieldIfContendedSafely(long);
+    field public static final int CONFLICT_ABORT = 2; // 0x2
+    field public static final int CONFLICT_FAIL = 3; // 0x3
+    field public static final int CONFLICT_IGNORE = 4; // 0x4
+    field public static final int CONFLICT_NONE = 0; // 0x0
+    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
+    field public static final int OPEN_READWRITE = 0; // 0x0
+    field public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000; // 0xc350
+  }
+
+  public static abstract interface SQLiteDatabase.CursorFactory {
+    method public abstract android.database.Cursor newCursor(android.database.sqlite.SQLiteDatabase, android.database.sqlite.SQLiteCursorDriver, java.lang.String, android.database.sqlite.SQLiteQuery);
+  }
+
+  public class SQLiteDatabaseCorruptException extends android.database.sqlite.SQLiteException {
+    ctor public SQLiteDatabaseCorruptException();
+    ctor public SQLiteDatabaseCorruptException(java.lang.String);
+  }
+
+  public class SQLiteDatabaseLockedException extends android.database.sqlite.SQLiteException {
+    ctor public SQLiteDatabaseLockedException();
+    ctor public SQLiteDatabaseLockedException(java.lang.String);
+  }
+
+  public class SQLiteDatatypeMismatchException extends android.database.sqlite.SQLiteException {
+    ctor public SQLiteDatatypeMismatchException();
+    ctor public SQLiteDatatypeMismatchException(java.lang.String);
+  }
+
+  public class SQLiteDiskIOException extends android.database.sqlite.SQLiteException {
+    ctor public SQLiteDiskIOException();
+    ctor public SQLiteDiskIOException(java.lang.String);
+  }
+
+  public class SQLiteDoneException extends android.database.sqlite.SQLiteException {
+    ctor public SQLiteDoneException();
+    ctor public SQLiteDoneException(java.lang.String);
+  }
+
+  public class SQLiteException extends android.database.SQLException {
+    ctor public SQLiteException();
+    ctor public SQLiteException(java.lang.String);
+    ctor public SQLiteException(java.lang.String, java.lang.Throwable);
+  }
+
+  public class SQLiteFullException extends android.database.sqlite.SQLiteException {
+    ctor public SQLiteFullException();
+    ctor public SQLiteFullException(java.lang.String);
+  }
+
+  public class SQLiteMisuseException extends android.database.sqlite.SQLiteException {
+    ctor public SQLiteMisuseException();
+    ctor public SQLiteMisuseException(java.lang.String);
+  }
+
+  public abstract class SQLiteOpenHelper {
+    ctor public SQLiteOpenHelper(android.content.Context, java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory, int);
+    ctor public SQLiteOpenHelper(android.content.Context, java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory, int, android.database.DatabaseErrorHandler);
+    method public synchronized void close();
+    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 {
+    ctor public SQLiteOutOfMemoryException();
+    ctor public SQLiteOutOfMemoryException(java.lang.String);
+  }
+
+  public abstract class SQLiteProgram extends android.database.sqlite.SQLiteClosable {
+    method public void bindAllArgsAsStrings(java.lang.String[]);
+    method public void bindBlob(int, byte[]);
+    method public void bindDouble(int, double);
+    method public void bindLong(int, long);
+    method public void bindNull(int);
+    method public void bindString(int, java.lang.String);
+    method public void clearBindings();
+    method public final deprecated int getUniqueId();
+    method protected void onAllReferencesReleased();
+  }
+
+  public final class SQLiteQuery extends android.database.sqlite.SQLiteProgram {
+  }
+
+  public class SQLiteQueryBuilder {
+    ctor public SQLiteQueryBuilder();
+    method public static void appendColumns(java.lang.StringBuilder, java.lang.String[]);
+    method public void appendWhere(java.lang.CharSequence);
+    method public void appendWhereEscapeString(java.lang.String);
+    method public java.lang.String buildQuery(java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public deprecated java.lang.String buildQuery(java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public static java.lang.String buildQueryString(boolean, java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public java.lang.String buildUnionQuery(java.lang.String[], java.lang.String, java.lang.String);
+    method public java.lang.String buildUnionSubQuery(java.lang.String, java.lang.String[], java.util.Set<java.lang.String>, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public deprecated java.lang.String buildUnionSubQuery(java.lang.String, java.lang.String[], java.util.Set<java.lang.String>, int, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, java.lang.String);
+    method public java.lang.String getTables();
+    method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String);
+    method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String, android.os.CancellationSignal);
+    method public void setCursorFactory(android.database.sqlite.SQLiteDatabase.CursorFactory);
+    method public void setDistinct(boolean);
+    method public void setProjectionMap(java.util.Map<java.lang.String, java.lang.String>);
+    method public void setStrict(boolean);
+    method public void setTables(java.lang.String);
+  }
+
+  public class SQLiteReadOnlyDatabaseException extends android.database.sqlite.SQLiteException {
+    ctor public SQLiteReadOnlyDatabaseException();
+    ctor public SQLiteReadOnlyDatabaseException(java.lang.String);
+  }
+
+  public final class SQLiteStatement extends android.database.sqlite.SQLiteProgram {
+    method public void execute();
+    method public long executeInsert();
+    method public int executeUpdateDelete();
+    method public android.os.ParcelFileDescriptor simpleQueryForBlobFileDescriptor();
+    method public long simpleQueryForLong();
+    method public java.lang.String simpleQueryForString();
+  }
+
+  public class SQLiteTableLockedException extends android.database.sqlite.SQLiteException {
+    ctor public SQLiteTableLockedException();
+    ctor public SQLiteTableLockedException(java.lang.String);
+  }
+
+  public abstract interface SQLiteTransactionListener {
+    method public abstract void onBegin();
+    method public abstract void onCommit();
+    method public abstract void onRollback();
+  }
+
+}
+
+package android.drm {
+
+  public class DrmConvertedStatus {
+    ctor public DrmConvertedStatus(int, byte[], int);
+    field public static final int STATUS_ERROR = 3; // 0x3
+    field public static final int STATUS_INPUTDATA_ERROR = 2; // 0x2
+    field public static final int STATUS_OK = 1; // 0x1
+    field public final byte[] convertedData;
+    field public final int offset;
+    field public final int statusCode;
+  }
+
+  public class DrmErrorEvent extends android.drm.DrmEvent {
+    ctor public DrmErrorEvent(int, int, java.lang.String);
+    ctor public DrmErrorEvent(int, int, java.lang.String, java.util.HashMap<java.lang.String, java.lang.Object>);
+    field public static final int TYPE_ACQUIRE_DRM_INFO_FAILED = 2008; // 0x7d8
+    field public static final int TYPE_NOT_SUPPORTED = 2003; // 0x7d3
+    field public static final int TYPE_NO_INTERNET_CONNECTION = 2005; // 0x7d5
+    field public static final int TYPE_OUT_OF_MEMORY = 2004; // 0x7d4
+    field public static final int TYPE_PROCESS_DRM_INFO_FAILED = 2006; // 0x7d6
+    field public static final int TYPE_REMOVE_ALL_RIGHTS_FAILED = 2007; // 0x7d7
+    field public static final int TYPE_RIGHTS_NOT_INSTALLED = 2001; // 0x7d1
+    field public static final int TYPE_RIGHTS_RENEWAL_NOT_ALLOWED = 2002; // 0x7d2
+  }
+
+  public class DrmEvent {
+    ctor protected DrmEvent(int, int, java.lang.String, java.util.HashMap<java.lang.String, java.lang.Object>);
+    ctor protected DrmEvent(int, int, java.lang.String);
+    method public java.lang.Object getAttribute(java.lang.String);
+    method public java.lang.String getMessage();
+    method public int getType();
+    method public int getUniqueId();
+    field public static final java.lang.String DRM_INFO_OBJECT = "drm_info_object";
+    field public static final java.lang.String DRM_INFO_STATUS_OBJECT = "drm_info_status_object";
+    field public static final int TYPE_ALL_RIGHTS_REMOVED = 1001; // 0x3e9
+    field public static final int TYPE_DRM_INFO_PROCESSED = 1002; // 0x3ea
+  }
+
+  public class DrmInfo {
+    ctor public DrmInfo(int, byte[], java.lang.String);
+    ctor public DrmInfo(int, java.lang.String, java.lang.String);
+    method public java.lang.Object get(java.lang.String);
+    method public byte[] getData();
+    method public int getInfoType();
+    method public java.lang.String getMimeType();
+    method public java.util.Iterator<java.lang.Object> iterator();
+    method public java.util.Iterator<java.lang.String> keyIterator();
+    method public void put(java.lang.String, java.lang.Object);
+  }
+
+  public class DrmInfoEvent extends android.drm.DrmEvent {
+    ctor public DrmInfoEvent(int, int, java.lang.String);
+    ctor public DrmInfoEvent(int, int, java.lang.String, java.util.HashMap<java.lang.String, java.lang.Object>);
+    field public static final int TYPE_ACCOUNT_ALREADY_REGISTERED = 5; // 0x5
+    field public static final int TYPE_ALREADY_REGISTERED_BY_ANOTHER_ACCOUNT = 1; // 0x1
+    field public static final int TYPE_REMOVE_RIGHTS = 2; // 0x2
+    field public static final int TYPE_RIGHTS_INSTALLED = 3; // 0x3
+    field public static final int TYPE_RIGHTS_REMOVED = 6; // 0x6
+    field public static final int TYPE_WAIT_FOR_RIGHTS = 4; // 0x4
+  }
+
+  public class DrmInfoRequest {
+    ctor public DrmInfoRequest(int, java.lang.String);
+    method public java.lang.Object get(java.lang.String);
+    method public int getInfoType();
+    method public java.lang.String getMimeType();
+    method public java.util.Iterator<java.lang.Object> iterator();
+    method public java.util.Iterator<java.lang.String> keyIterator();
+    method public void put(java.lang.String, java.lang.Object);
+    field public static final java.lang.String ACCOUNT_ID = "account_id";
+    field public static final java.lang.String SUBSCRIPTION_ID = "subscription_id";
+    field public static final int TYPE_REGISTRATION_INFO = 1; // 0x1
+    field public static final int TYPE_RIGHTS_ACQUISITION_INFO = 3; // 0x3
+    field public static final int TYPE_RIGHTS_ACQUISITION_PROGRESS_INFO = 4; // 0x4
+    field public static final int TYPE_UNREGISTRATION_INFO = 2; // 0x2
+  }
+
+  public class DrmInfoStatus {
+    ctor public DrmInfoStatus(int, int, android.drm.ProcessedData, java.lang.String);
+    field public static final int STATUS_ERROR = 2; // 0x2
+    field public static final int STATUS_OK = 1; // 0x1
+    field public final android.drm.ProcessedData data;
+    field public final int infoType;
+    field public final java.lang.String mimeType;
+    field public final int statusCode;
+  }
+
+  public class DrmManagerClient {
+    ctor public DrmManagerClient(android.content.Context);
+    method public android.drm.DrmInfo acquireDrmInfo(android.drm.DrmInfoRequest);
+    method public int acquireRights(android.drm.DrmInfoRequest);
+    method public boolean canHandle(java.lang.String, java.lang.String);
+    method public boolean canHandle(android.net.Uri, java.lang.String);
+    method public int checkRightsStatus(java.lang.String);
+    method public int checkRightsStatus(android.net.Uri);
+    method public int checkRightsStatus(java.lang.String, int);
+    method public int checkRightsStatus(android.net.Uri, int);
+    method public android.drm.DrmConvertedStatus closeConvertSession(int);
+    method public android.drm.DrmConvertedStatus convertData(int, byte[]);
+    method public java.lang.String[] getAvailableDrmEngines();
+    method public android.content.ContentValues getConstraints(java.lang.String, int);
+    method public android.content.ContentValues getConstraints(android.net.Uri, int);
+    method public int getDrmObjectType(java.lang.String, java.lang.String);
+    method public int getDrmObjectType(android.net.Uri, java.lang.String);
+    method public android.content.ContentValues getMetadata(java.lang.String);
+    method public android.content.ContentValues getMetadata(android.net.Uri);
+    method public java.lang.String getOriginalMimeType(java.lang.String);
+    method public java.lang.String getOriginalMimeType(android.net.Uri);
+    method public int openConvertSession(java.lang.String);
+    method public int processDrmInfo(android.drm.DrmInfo);
+    method public void release();
+    method public int removeAllRights();
+    method public int removeRights(java.lang.String);
+    method public int removeRights(android.net.Uri);
+    method public int saveRights(android.drm.DrmRights, java.lang.String, java.lang.String) throws java.io.IOException;
+    method public synchronized void setOnErrorListener(android.drm.DrmManagerClient.OnErrorListener);
+    method public synchronized void setOnEventListener(android.drm.DrmManagerClient.OnEventListener);
+    method public synchronized void setOnInfoListener(android.drm.DrmManagerClient.OnInfoListener);
+    field public static final int ERROR_NONE = 0; // 0x0
+    field public static final int ERROR_UNKNOWN = -2000; // 0xfffff830
+  }
+
+  public static abstract interface DrmManagerClient.OnErrorListener {
+    method public abstract void onError(android.drm.DrmManagerClient, android.drm.DrmErrorEvent);
+  }
+
+  public static abstract interface DrmManagerClient.OnEventListener {
+    method public abstract void onEvent(android.drm.DrmManagerClient, android.drm.DrmEvent);
+  }
+
+  public static abstract interface DrmManagerClient.OnInfoListener {
+    method public abstract void onInfo(android.drm.DrmManagerClient, android.drm.DrmInfoEvent);
+  }
+
+  public class DrmRights {
+    ctor public DrmRights(java.lang.String, java.lang.String);
+    ctor public DrmRights(java.lang.String, java.lang.String, java.lang.String);
+    ctor public DrmRights(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    ctor public DrmRights(java.io.File, java.lang.String);
+    ctor public DrmRights(android.drm.ProcessedData, java.lang.String);
+    method public java.lang.String getAccountId();
+    method public byte[] getData();
+    method public java.lang.String getMimeType();
+    method public java.lang.String getSubscriptionId();
+  }
+
+  public class DrmStore {
+    ctor public deprecated DrmStore();
+  }
+
+  public static class DrmStore.Action {
+    ctor public deprecated DrmStore.Action();
+    field public static final int DEFAULT = 0; // 0x0
+    field public static final int DISPLAY = 7; // 0x7
+    field public static final int EXECUTE = 6; // 0x6
+    field public static final int OUTPUT = 4; // 0x4
+    field public static final int PLAY = 1; // 0x1
+    field public static final int PREVIEW = 5; // 0x5
+    field public static final int RINGTONE = 2; // 0x2
+    field public static final int TRANSFER = 3; // 0x3
+  }
+
+  public static abstract interface DrmStore.ConstraintsColumns {
+    field public static final java.lang.String EXTENDED_METADATA = "extended_metadata";
+    field public static final java.lang.String LICENSE_AVAILABLE_TIME = "license_available_time";
+    field public static final java.lang.String LICENSE_EXPIRY_TIME = "license_expiry_time";
+    field public static final java.lang.String LICENSE_START_TIME = "license_start_time";
+    field public static final java.lang.String MAX_REPEAT_COUNT = "max_repeat_count";
+    field public static final java.lang.String REMAINING_REPEAT_COUNT = "remaining_repeat_count";
+  }
+
+  public static class DrmStore.DrmObjectType {
+    ctor public deprecated DrmStore.DrmObjectType();
+    field public static final int CONTENT = 1; // 0x1
+    field public static final int RIGHTS_OBJECT = 2; // 0x2
+    field public static final int TRIGGER_OBJECT = 3; // 0x3
+    field public static final int UNKNOWN = 0; // 0x0
+  }
+
+  public static class DrmStore.Playback {
+    ctor public deprecated DrmStore.Playback();
+    field public static final int PAUSE = 2; // 0x2
+    field public static final int RESUME = 3; // 0x3
+    field public static final int START = 0; // 0x0
+    field public static final int STOP = 1; // 0x1
+  }
+
+  public static class DrmStore.RightsStatus {
+    ctor public deprecated DrmStore.RightsStatus();
+    field public static final int RIGHTS_EXPIRED = 2; // 0x2
+    field public static final int RIGHTS_INVALID = 1; // 0x1
+    field public static final int RIGHTS_NOT_ACQUIRED = 3; // 0x3
+    field public static final int RIGHTS_VALID = 0; // 0x0
+  }
+
+  public class DrmSupportInfo {
+    ctor public DrmSupportInfo();
+    method public void addFileSuffix(java.lang.String);
+    method public void addMimeType(java.lang.String);
+    method public deprecated java.lang.String getDescriprition();
+    method public java.lang.String getDescription();
+    method public java.util.Iterator<java.lang.String> getFileSuffixIterator();
+    method public java.util.Iterator<java.lang.String> getMimeTypeIterator();
+    method public void setDescription(java.lang.String);
+  }
+
+  public class DrmUtils {
+    ctor public DrmUtils();
+    method public static android.drm.DrmUtils.ExtendedMetadataParser getExtendedMetadataParser(byte[]);
+  }
+
+  public static class DrmUtils.ExtendedMetadataParser {
+    method public java.lang.String get(java.lang.String);
+    method public java.util.Iterator<java.lang.String> iterator();
+    method public java.util.Iterator<java.lang.String> keyIterator();
+  }
+
+  public class ProcessedData {
+    method public java.lang.String getAccountId();
+    method public byte[] getData();
+    method public java.lang.String getSubscriptionId();
+  }
+
+}
+
+package android.gesture {
+
+  public class Gesture implements android.os.Parcelable {
+    ctor public Gesture();
+    method public void addStroke(android.gesture.GestureStroke);
+    method public java.lang.Object clone();
+    method public int describeContents();
+    method public android.graphics.RectF getBoundingBox();
+    method public long getID();
+    method public float getLength();
+    method public java.util.ArrayList<android.gesture.GestureStroke> getStrokes();
+    method public int getStrokesCount();
+    method public android.graphics.Bitmap toBitmap(int, int, int, int, int);
+    method public android.graphics.Bitmap toBitmap(int, int, int, int);
+    method public android.graphics.Path toPath();
+    method public android.graphics.Path toPath(android.graphics.Path);
+    method public android.graphics.Path toPath(int, int, int, int);
+    method public android.graphics.Path toPath(android.graphics.Path, int, int, int, int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class GestureLibraries {
+    method public static android.gesture.GestureLibrary fromFile(java.lang.String);
+    method public static android.gesture.GestureLibrary fromFile(java.io.File);
+    method public static android.gesture.GestureLibrary fromPrivateFile(android.content.Context, java.lang.String);
+    method public static android.gesture.GestureLibrary fromRawResource(android.content.Context, int);
+  }
+
+  public abstract class GestureLibrary {
+    ctor protected GestureLibrary();
+    method public void addGesture(java.lang.String, android.gesture.Gesture);
+    method public java.util.Set<java.lang.String> getGestureEntries();
+    method public java.util.ArrayList<android.gesture.Gesture> getGestures(java.lang.String);
+    method public int getOrientationStyle();
+    method public int getSequenceType();
+    method public boolean isReadOnly();
+    method public abstract boolean load();
+    method public java.util.ArrayList<android.gesture.Prediction> recognize(android.gesture.Gesture);
+    method public void removeEntry(java.lang.String);
+    method public void removeGesture(java.lang.String, android.gesture.Gesture);
+    method public abstract boolean save();
+    method public void setOrientationStyle(int);
+    method public void setSequenceType(int);
+    field protected final android.gesture.GestureStore mStore;
+  }
+
+  public class GestureOverlayView extends android.widget.FrameLayout {
+    ctor public GestureOverlayView(android.content.Context);
+    ctor public GestureOverlayView(android.content.Context, android.util.AttributeSet);
+    ctor public GestureOverlayView(android.content.Context, android.util.AttributeSet, int);
+    method public void addOnGestureListener(android.gesture.GestureOverlayView.OnGestureListener);
+    method public void addOnGesturePerformedListener(android.gesture.GestureOverlayView.OnGesturePerformedListener);
+    method public void addOnGesturingListener(android.gesture.GestureOverlayView.OnGesturingListener);
+    method public void cancelClearAnimation();
+    method public void cancelGesture();
+    method public void clear(boolean);
+    method public java.util.ArrayList<android.gesture.GesturePoint> getCurrentStroke();
+    method public long getFadeOffset();
+    method public android.gesture.Gesture getGesture();
+    method public int getGestureColor();
+    method public android.graphics.Path getGesturePath();
+    method public android.graphics.Path getGesturePath(android.graphics.Path);
+    method public float getGestureStrokeAngleThreshold();
+    method public float getGestureStrokeLengthThreshold();
+    method public float getGestureStrokeSquarenessTreshold();
+    method public int getGestureStrokeType();
+    method public float getGestureStrokeWidth();
+    method public int getOrientation();
+    method public int getUncertainGestureColor();
+    method public boolean isEventsInterceptionEnabled();
+    method public boolean isFadeEnabled();
+    method public boolean isGestureVisible();
+    method public boolean isGesturing();
+    method public void removeAllOnGestureListeners();
+    method public void removeAllOnGesturePerformedListeners();
+    method public void removeAllOnGesturingListeners();
+    method public void removeOnGestureListener(android.gesture.GestureOverlayView.OnGestureListener);
+    method public void removeOnGesturePerformedListener(android.gesture.GestureOverlayView.OnGesturePerformedListener);
+    method public void removeOnGesturingListener(android.gesture.GestureOverlayView.OnGesturingListener);
+    method public void setEventsInterceptionEnabled(boolean);
+    method public void setFadeEnabled(boolean);
+    method public void setFadeOffset(long);
+    method public void setGesture(android.gesture.Gesture);
+    method public void setGestureColor(int);
+    method public void setGestureStrokeAngleThreshold(float);
+    method public void setGestureStrokeLengthThreshold(float);
+    method public void setGestureStrokeSquarenessTreshold(float);
+    method public void setGestureStrokeType(int);
+    method public void setGestureStrokeWidth(float);
+    method public void setGestureVisible(boolean);
+    method public void setOrientation(int);
+    method public void setUncertainGestureColor(int);
+    field public static final int GESTURE_STROKE_TYPE_MULTIPLE = 1; // 0x1
+    field public static final int GESTURE_STROKE_TYPE_SINGLE = 0; // 0x0
+    field public static final int ORIENTATION_HORIZONTAL = 0; // 0x0
+    field public static final int ORIENTATION_VERTICAL = 1; // 0x1
+  }
+
+  public static abstract interface GestureOverlayView.OnGestureListener {
+    method public abstract void onGesture(android.gesture.GestureOverlayView, android.view.MotionEvent);
+    method public abstract void onGestureCancelled(android.gesture.GestureOverlayView, android.view.MotionEvent);
+    method public abstract void onGestureEnded(android.gesture.GestureOverlayView, android.view.MotionEvent);
+    method public abstract void onGestureStarted(android.gesture.GestureOverlayView, android.view.MotionEvent);
+  }
+
+  public static abstract interface GestureOverlayView.OnGesturePerformedListener {
+    method public abstract void onGesturePerformed(android.gesture.GestureOverlayView, android.gesture.Gesture);
+  }
+
+  public static abstract interface GestureOverlayView.OnGesturingListener {
+    method public abstract void onGesturingEnded(android.gesture.GestureOverlayView);
+    method public abstract void onGesturingStarted(android.gesture.GestureOverlayView);
+  }
+
+  public class GesturePoint {
+    ctor public GesturePoint(float, float, long);
+    method public java.lang.Object clone();
+    field public final long timestamp;
+    field public final float x;
+    field public final float y;
+  }
+
+  public class GestureStore {
+    ctor public GestureStore();
+    method public void addGesture(java.lang.String, android.gesture.Gesture);
+    method public java.util.Set<java.lang.String> getGestureEntries();
+    method public java.util.ArrayList<android.gesture.Gesture> getGestures(java.lang.String);
+    method public int getOrientationStyle();
+    method public int getSequenceType();
+    method public boolean hasChanged();
+    method public void load(java.io.InputStream) throws java.io.IOException;
+    method public void load(java.io.InputStream, boolean) throws java.io.IOException;
+    method public java.util.ArrayList<android.gesture.Prediction> recognize(android.gesture.Gesture);
+    method public void removeEntry(java.lang.String);
+    method public void removeGesture(java.lang.String, android.gesture.Gesture);
+    method public void save(java.io.OutputStream) throws java.io.IOException;
+    method public void save(java.io.OutputStream, boolean) throws java.io.IOException;
+    method public void setOrientationStyle(int);
+    method public void setSequenceType(int);
+    field public static final int ORIENTATION_INVARIANT = 1; // 0x1
+    field public static final int ORIENTATION_SENSITIVE = 2; // 0x2
+    field public static final int SEQUENCE_INVARIANT = 1; // 0x1
+    field public static final int SEQUENCE_SENSITIVE = 2; // 0x2
+  }
+
+  public class GestureStroke {
+    ctor public GestureStroke(java.util.ArrayList<android.gesture.GesturePoint>);
+    method public void clearPath();
+    method public java.lang.Object clone();
+    method public android.gesture.OrientedBoundingBox computeOrientedBoundingBox();
+    method public android.graphics.Path getPath();
+    method public android.graphics.Path toPath(float, float, int);
+    field public final android.graphics.RectF boundingBox;
+    field public final float length;
+    field public final float[] points;
+  }
+
+  public final class GestureUtils {
+    method public static android.gesture.OrientedBoundingBox computeOrientedBoundingBox(java.util.ArrayList<android.gesture.GesturePoint>);
+    method public static android.gesture.OrientedBoundingBox computeOrientedBoundingBox(float[]);
+    method public static float[] spatialSampling(android.gesture.Gesture, int);
+    method public static float[] spatialSampling(android.gesture.Gesture, int, boolean);
+    method public static float[] temporalSampling(android.gesture.GestureStroke, int);
+  }
+
+  public class OrientedBoundingBox {
+    field public final float centerX;
+    field public final float centerY;
+    field public final float height;
+    field public final float orientation;
+    field public final float squareness;
+    field public final float width;
+  }
+
+  public class Prediction {
+    field public final java.lang.String name;
+    field public double score;
+  }
+
+}
+
+package android.graphics {
+
+  public deprecated class AvoidXfermode extends android.graphics.Xfermode {
+    ctor public AvoidXfermode(int, int, android.graphics.AvoidXfermode.Mode);
+  }
+
+  public static final class AvoidXfermode.Mode extends java.lang.Enum {
+    method public static android.graphics.AvoidXfermode.Mode valueOf(java.lang.String);
+    method public static final android.graphics.AvoidXfermode.Mode[] values();
+    enum_constant public static final android.graphics.AvoidXfermode.Mode AVOID;
+    enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET;
+  }
+
+  public final class Bitmap implements android.os.Parcelable {
+    method public boolean compress(android.graphics.Bitmap.CompressFormat, int, java.io.OutputStream);
+    method public android.graphics.Bitmap copy(android.graphics.Bitmap.Config, boolean);
+    method public void copyPixelsFromBuffer(java.nio.Buffer);
+    method public void copyPixelsToBuffer(java.nio.Buffer);
+    method public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap);
+    method public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap, int, int, int, int);
+    method public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap, int, int, int, int, android.graphics.Matrix, boolean);
+    method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config);
+    method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config);
+    method public static android.graphics.Bitmap createBitmap(int[], int, int, int, int, android.graphics.Bitmap.Config);
+    method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int[], int, int, int, int, android.graphics.Bitmap.Config);
+    method public static android.graphics.Bitmap createBitmap(int[], int, int, android.graphics.Bitmap.Config);
+    method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int[], int, int, android.graphics.Bitmap.Config);
+    method public static android.graphics.Bitmap createScaledBitmap(android.graphics.Bitmap, int, int, boolean);
+    method public int describeContents();
+    method public void eraseColor(int);
+    method public android.graphics.Bitmap extractAlpha();
+    method public android.graphics.Bitmap extractAlpha(android.graphics.Paint, int[]);
+    method public final int getByteCount();
+    method public final android.graphics.Bitmap.Config getConfig();
+    method public int getDensity();
+    method public int getGenerationId();
+    method public final int getHeight();
+    method public byte[] getNinePatchChunk();
+    method public int getPixel(int, int);
+    method public void getPixels(int[], int, int, int, int, int, int);
+    method public final int getRowBytes();
+    method public int getScaledHeight(android.graphics.Canvas);
+    method public int getScaledHeight(android.util.DisplayMetrics);
+    method public int getScaledHeight(int);
+    method public int getScaledWidth(android.graphics.Canvas);
+    method public int getScaledWidth(android.util.DisplayMetrics);
+    method public int getScaledWidth(int);
+    method public final int getWidth();
+    method public final boolean hasAlpha();
+    method public final boolean hasMipMap();
+    method public final boolean isMutable();
+    method public final boolean isPremultiplied();
+    method public final boolean isRecycled();
+    method public void prepareToDraw();
+    method public void recycle();
+    method public boolean sameAs(android.graphics.Bitmap);
+    method public void setDensity(int);
+    method public void setHasAlpha(boolean);
+    method public final void setHasMipMap(boolean);
+    method public void setPixel(int, int, int);
+    method public void setPixels(int[], int, int, int, int, int, int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int DENSITY_NONE = 0; // 0x0
+  }
+
+  public static final class Bitmap.CompressFormat extends java.lang.Enum {
+    method public static android.graphics.Bitmap.CompressFormat valueOf(java.lang.String);
+    method public static final android.graphics.Bitmap.CompressFormat[] values();
+    enum_constant public static final android.graphics.Bitmap.CompressFormat JPEG;
+    enum_constant public static final android.graphics.Bitmap.CompressFormat PNG;
+    enum_constant public static final android.graphics.Bitmap.CompressFormat WEBP;
+  }
+
+  public static final class Bitmap.Config extends java.lang.Enum {
+    method public static android.graphics.Bitmap.Config valueOf(java.lang.String);
+    method public static final android.graphics.Bitmap.Config[] values();
+    enum_constant public static final android.graphics.Bitmap.Config ALPHA_8;
+    enum_constant public static final deprecated android.graphics.Bitmap.Config ARGB_4444;
+    enum_constant public static final android.graphics.Bitmap.Config ARGB_8888;
+    enum_constant public static final android.graphics.Bitmap.Config RGB_565;
+  }
+
+  public class BitmapFactory {
+    ctor public BitmapFactory();
+    method public static android.graphics.Bitmap decodeByteArray(byte[], int, int, android.graphics.BitmapFactory.Options);
+    method public static android.graphics.Bitmap decodeByteArray(byte[], int, int);
+    method public static android.graphics.Bitmap decodeFile(java.lang.String, android.graphics.BitmapFactory.Options);
+    method public static android.graphics.Bitmap decodeFile(java.lang.String);
+    method public static android.graphics.Bitmap decodeFileDescriptor(java.io.FileDescriptor, android.graphics.Rect, android.graphics.BitmapFactory.Options);
+    method public static android.graphics.Bitmap decodeFileDescriptor(java.io.FileDescriptor);
+    method public static android.graphics.Bitmap decodeResource(android.content.res.Resources, int, android.graphics.BitmapFactory.Options);
+    method public static android.graphics.Bitmap decodeResource(android.content.res.Resources, int);
+    method public static android.graphics.Bitmap decodeResourceStream(android.content.res.Resources, android.util.TypedValue, java.io.InputStream, android.graphics.Rect, android.graphics.BitmapFactory.Options);
+    method public static android.graphics.Bitmap decodeStream(java.io.InputStream, android.graphics.Rect, android.graphics.BitmapFactory.Options);
+    method public static android.graphics.Bitmap decodeStream(java.io.InputStream);
+  }
+
+  public static class BitmapFactory.Options {
+    ctor public BitmapFactory.Options();
+    method public void requestCancelDecode();
+    field public android.graphics.Bitmap inBitmap;
+    field public int inDensity;
+    field public boolean inDither;
+    field public boolean inInputShareable;
+    field public boolean inJustDecodeBounds;
+    field public boolean inMutable;
+    field public boolean inPreferQualityOverSpeed;
+    field public android.graphics.Bitmap.Config inPreferredConfig;
+    field public boolean inPurgeable;
+    field public int inSampleSize;
+    field public boolean inScaled;
+    field public int inScreenDensity;
+    field public int inTargetDensity;
+    field public byte[] inTempStorage;
+    field public boolean mCancel;
+    field public int outHeight;
+    field public java.lang.String outMimeType;
+    field public int outWidth;
+  }
+
+  public final class BitmapRegionDecoder {
+    method public android.graphics.Bitmap decodeRegion(android.graphics.Rect, android.graphics.BitmapFactory.Options);
+    method public int getHeight();
+    method public int getWidth();
+    method public final boolean isRecycled();
+    method public static android.graphics.BitmapRegionDecoder newInstance(byte[], int, int, boolean) throws java.io.IOException;
+    method public static android.graphics.BitmapRegionDecoder newInstance(java.io.FileDescriptor, boolean) throws java.io.IOException;
+    method public static android.graphics.BitmapRegionDecoder newInstance(java.io.InputStream, boolean) throws java.io.IOException;
+    method public static android.graphics.BitmapRegionDecoder newInstance(java.lang.String, boolean) throws java.io.IOException;
+    method public void recycle();
+  }
+
+  public class BitmapShader extends android.graphics.Shader {
+    ctor public BitmapShader(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
+  }
+
+  public class BlurMaskFilter extends android.graphics.MaskFilter {
+    ctor public BlurMaskFilter(float, android.graphics.BlurMaskFilter.Blur);
+  }
+
+  public static final class BlurMaskFilter.Blur extends java.lang.Enum {
+    method public static android.graphics.BlurMaskFilter.Blur valueOf(java.lang.String);
+    method public static final android.graphics.BlurMaskFilter.Blur[] values();
+    enum_constant public static final android.graphics.BlurMaskFilter.Blur INNER;
+    enum_constant public static final android.graphics.BlurMaskFilter.Blur NORMAL;
+    enum_constant public static final android.graphics.BlurMaskFilter.Blur OUTER;
+    enum_constant public static final android.graphics.BlurMaskFilter.Blur SOLID;
+  }
+
+  public class Camera {
+    ctor public Camera();
+    method public void applyToCanvas(android.graphics.Canvas);
+    method public float dotWithNormal(float, float, float);
+    method public float getLocationX();
+    method public float getLocationY();
+    method public float getLocationZ();
+    method public void getMatrix(android.graphics.Matrix);
+    method public void restore();
+    method public void rotate(float, float, float);
+    method public void rotateX(float);
+    method public void rotateY(float);
+    method public void rotateZ(float);
+    method public void save();
+    method public void setLocation(float, float, float);
+    method public void translate(float, float, float);
+  }
+
+  public class Canvas {
+    ctor public Canvas();
+    ctor public Canvas(android.graphics.Bitmap);
+    method public boolean clipPath(android.graphics.Path, android.graphics.Region.Op);
+    method public boolean clipPath(android.graphics.Path);
+    method public boolean clipRect(android.graphics.RectF, android.graphics.Region.Op);
+    method public boolean clipRect(android.graphics.Rect, android.graphics.Region.Op);
+    method public boolean clipRect(android.graphics.RectF);
+    method public boolean clipRect(android.graphics.Rect);
+    method public boolean clipRect(float, float, float, float, android.graphics.Region.Op);
+    method public boolean clipRect(float, float, float, float);
+    method public boolean clipRect(int, int, int, int);
+    method public boolean clipRegion(android.graphics.Region, android.graphics.Region.Op);
+    method public boolean clipRegion(android.graphics.Region);
+    method public void concat(android.graphics.Matrix);
+    method public void drawARGB(int, int, int, int);
+    method public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint);
+    method public void drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint);
+    method public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.RectF, android.graphics.Paint);
+    method public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.Rect, android.graphics.Paint);
+    method public void drawBitmap(int[], int, int, float, float, int, int, boolean, android.graphics.Paint);
+    method public void drawBitmap(int[], int, int, int, int, int, int, boolean, android.graphics.Paint);
+    method public void drawBitmap(android.graphics.Bitmap, android.graphics.Matrix, android.graphics.Paint);
+    method public void drawBitmapMesh(android.graphics.Bitmap, int, int, float[], int, int[], int, android.graphics.Paint);
+    method public void drawCircle(float, float, float, android.graphics.Paint);
+    method public void drawColor(int);
+    method public void drawColor(int, android.graphics.PorterDuff.Mode);
+    method public void drawLine(float, float, float, float, android.graphics.Paint);
+    method public void drawLines(float[], int, int, android.graphics.Paint);
+    method public void drawLines(float[], android.graphics.Paint);
+    method public void drawOval(android.graphics.RectF, android.graphics.Paint);
+    method public void drawPaint(android.graphics.Paint);
+    method public void drawPath(android.graphics.Path, android.graphics.Paint);
+    method public void drawPicture(android.graphics.Picture);
+    method public void drawPicture(android.graphics.Picture, android.graphics.RectF);
+    method public void drawPicture(android.graphics.Picture, android.graphics.Rect);
+    method public void drawPoint(float, float, android.graphics.Paint);
+    method public void drawPoints(float[], int, int, android.graphics.Paint);
+    method public void drawPoints(float[], android.graphics.Paint);
+    method public deprecated void drawPosText(char[], int, int, float[], android.graphics.Paint);
+    method public deprecated void drawPosText(java.lang.String, float[], android.graphics.Paint);
+    method public void drawRGB(int, int, int);
+    method public void drawRect(android.graphics.RectF, android.graphics.Paint);
+    method public void drawRect(android.graphics.Rect, android.graphics.Paint);
+    method public void drawRect(float, float, float, float, android.graphics.Paint);
+    method public void drawRoundRect(android.graphics.RectF, float, float, android.graphics.Paint);
+    method public void drawText(char[], int, int, float, float, android.graphics.Paint);
+    method public void drawText(java.lang.String, float, float, android.graphics.Paint);
+    method public void drawText(java.lang.String, int, int, float, float, android.graphics.Paint);
+    method public void drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint);
+    method public void drawTextOnPath(char[], int, int, android.graphics.Path, float, float, android.graphics.Paint);
+    method public void drawTextOnPath(java.lang.String, android.graphics.Path, float, float, android.graphics.Paint);
+    method public void drawVertices(android.graphics.Canvas.VertexMode, int, float[], int, float[], int, int[], int, short[], int, int, android.graphics.Paint);
+    method public boolean getClipBounds(android.graphics.Rect);
+    method public final android.graphics.Rect getClipBounds();
+    method public int getDensity();
+    method public android.graphics.DrawFilter getDrawFilter();
+    method public int getHeight();
+    method public deprecated void getMatrix(android.graphics.Matrix);
+    method public final deprecated android.graphics.Matrix getMatrix();
+    method public int getMaximumBitmapHeight();
+    method public int getMaximumBitmapWidth();
+    method public int getSaveCount();
+    method public int getWidth();
+    method public boolean isHardwareAccelerated();
+    method public boolean isOpaque();
+    method public boolean quickReject(android.graphics.RectF, android.graphics.Canvas.EdgeType);
+    method public boolean quickReject(android.graphics.Path, android.graphics.Canvas.EdgeType);
+    method public boolean quickReject(float, float, float, float, android.graphics.Canvas.EdgeType);
+    method public void restore();
+    method public void restoreToCount(int);
+    method public void rotate(float);
+    method public final void rotate(float, float, float);
+    method public int save();
+    method public int save(int);
+    method public int saveLayer(android.graphics.RectF, android.graphics.Paint, int);
+    method public int saveLayer(float, float, float, float, android.graphics.Paint, int);
+    method public int saveLayerAlpha(android.graphics.RectF, int, int);
+    method public int saveLayerAlpha(float, float, float, float, int, int);
+    method public void scale(float, float);
+    method public final void scale(float, float, float, float);
+    method public void setBitmap(android.graphics.Bitmap);
+    method public void setDensity(int);
+    method public void setDrawFilter(android.graphics.DrawFilter);
+    method public void setMatrix(android.graphics.Matrix);
+    method public void skew(float, float);
+    method public void translate(float, float);
+    field public static final int ALL_SAVE_FLAG = 31; // 0x1f
+    field public static final int CLIP_SAVE_FLAG = 2; // 0x2
+    field public static final int CLIP_TO_LAYER_SAVE_FLAG = 16; // 0x10
+    field public static final int FULL_COLOR_LAYER_SAVE_FLAG = 8; // 0x8
+    field public static final int HAS_ALPHA_LAYER_SAVE_FLAG = 4; // 0x4
+    field public static final int MATRIX_SAVE_FLAG = 1; // 0x1
+  }
+
+  public static final class Canvas.EdgeType extends java.lang.Enum {
+    method public static android.graphics.Canvas.EdgeType valueOf(java.lang.String);
+    method public static final android.graphics.Canvas.EdgeType[] values();
+    enum_constant public static final android.graphics.Canvas.EdgeType AA;
+    enum_constant public static final android.graphics.Canvas.EdgeType BW;
+  }
+
+  public static final class Canvas.VertexMode extends java.lang.Enum {
+    method public static android.graphics.Canvas.VertexMode valueOf(java.lang.String);
+    method public static final android.graphics.Canvas.VertexMode[] values();
+    enum_constant public static final android.graphics.Canvas.VertexMode TRIANGLES;
+    enum_constant public static final android.graphics.Canvas.VertexMode TRIANGLE_FAN;
+    enum_constant public static final android.graphics.Canvas.VertexMode TRIANGLE_STRIP;
+  }
+
+  public class Color {
+    ctor public Color();
+    method public static int HSVToColor(float[]);
+    method public static int HSVToColor(int, float[]);
+    method public static void RGBToHSV(int, int, int, float[]);
+    method public static int alpha(int);
+    method public static int argb(int, int, int, int);
+    method public static int blue(int);
+    method public static void colorToHSV(int, float[]);
+    method public static int green(int);
+    method public static int parseColor(java.lang.String);
+    method public static int red(int);
+    method public static int rgb(int, int, int);
+    field public static final int BLACK = -16777216; // 0xff000000
+    field public static final int BLUE = -16776961; // 0xff0000ff
+    field public static final int CYAN = -16711681; // 0xff00ffff
+    field public static final int DKGRAY = -12303292; // 0xff444444
+    field public static final int GRAY = -7829368; // 0xff888888
+    field public static final int GREEN = -16711936; // 0xff00ff00
+    field public static final int LTGRAY = -3355444; // 0xffcccccc
+    field public static final int MAGENTA = -65281; // 0xffff00ff
+    field public static final int RED = -65536; // 0xffff0000
+    field public static final int TRANSPARENT = 0; // 0x0
+    field public static final int WHITE = -1; // 0xffffffff
+    field public static final int YELLOW = -256; // 0xffffff00
+  }
+
+  public class ColorFilter {
+    ctor public ColorFilter();
+  }
+
+  public class ColorMatrix {
+    ctor public ColorMatrix();
+    ctor public ColorMatrix(float[]);
+    ctor public ColorMatrix(android.graphics.ColorMatrix);
+    method public final float[] getArray();
+    method public void postConcat(android.graphics.ColorMatrix);
+    method public void preConcat(android.graphics.ColorMatrix);
+    method public void reset();
+    method public void set(android.graphics.ColorMatrix);
+    method public void set(float[]);
+    method public void setConcat(android.graphics.ColorMatrix, android.graphics.ColorMatrix);
+    method public void setRGB2YUV();
+    method public void setRotate(int, float);
+    method public void setSaturation(float);
+    method public void setScale(float, float, float, float);
+    method public void setYUV2RGB();
+  }
+
+  public class ColorMatrixColorFilter extends android.graphics.ColorFilter {
+    ctor public ColorMatrixColorFilter(android.graphics.ColorMatrix);
+    ctor public ColorMatrixColorFilter(float[]);
+  }
+
+  public class ComposePathEffect extends android.graphics.PathEffect {
+    ctor public ComposePathEffect(android.graphics.PathEffect, android.graphics.PathEffect);
+  }
+
+  public class ComposeShader extends android.graphics.Shader {
+    ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
+    ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
+  }
+
+  public class CornerPathEffect extends android.graphics.PathEffect {
+    ctor public CornerPathEffect(float);
+  }
+
+  public class DashPathEffect extends android.graphics.PathEffect {
+    ctor public DashPathEffect(float[], float);
+  }
+
+  public class DiscretePathEffect extends android.graphics.PathEffect {
+    ctor public DiscretePathEffect(float, float);
+  }
+
+  public class DrawFilter {
+    ctor public DrawFilter();
+  }
+
+  public class EmbossMaskFilter extends android.graphics.MaskFilter {
+    ctor public EmbossMaskFilter(float[], float, float, float);
+  }
+
+  public class ImageFormat {
+    ctor public ImageFormat();
+    method public static int getBitsPerPixel(int);
+    field public static final int JPEG = 256; // 0x100
+    field public static final int NV16 = 16; // 0x10
+    field public static final int NV21 = 17; // 0x11
+    field public static final int RGB_565 = 4; // 0x4
+    field public static final int UNKNOWN = 0; // 0x0
+    field public static final int YUY2 = 20; // 0x14
+    field public static final int YV12 = 842094169; // 0x32315659
+  }
+
+  public class Interpolator {
+    ctor public Interpolator(int);
+    ctor public Interpolator(int, int);
+    method public final int getKeyFrameCount();
+    method public final int getValueCount();
+    method public void reset(int);
+    method public void reset(int, int);
+    method public void setKeyFrame(int, int, float[]);
+    method public void setKeyFrame(int, int, float[], float[]);
+    method public void setRepeatMirror(float, boolean);
+    method public android.graphics.Interpolator.Result timeToValues(float[]);
+    method public android.graphics.Interpolator.Result timeToValues(int, float[]);
+  }
+
+  public static final class Interpolator.Result extends java.lang.Enum {
+    method public static android.graphics.Interpolator.Result valueOf(java.lang.String);
+    method public static final android.graphics.Interpolator.Result[] values();
+    enum_constant public static final android.graphics.Interpolator.Result FREEZE_END;
+    enum_constant public static final android.graphics.Interpolator.Result FREEZE_START;
+    enum_constant public static final android.graphics.Interpolator.Result NORMAL;
+  }
+
+  public class LayerRasterizer extends android.graphics.Rasterizer {
+    ctor public LayerRasterizer();
+    method public void addLayer(android.graphics.Paint, float, float);
+    method public void addLayer(android.graphics.Paint);
+  }
+
+  public class LightingColorFilter extends android.graphics.ColorFilter {
+    ctor public LightingColorFilter(int, int);
+  }
+
+  public class LinearGradient extends android.graphics.Shader {
+    ctor public LinearGradient(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
+    ctor public LinearGradient(float, float, float, float, int, int, android.graphics.Shader.TileMode);
+  }
+
+  public class MaskFilter {
+    ctor public MaskFilter();
+  }
+
+  public class Matrix {
+    ctor public Matrix();
+    ctor public Matrix(android.graphics.Matrix);
+    method public void getValues(float[]);
+    method public boolean invert(android.graphics.Matrix);
+    method public boolean isIdentity();
+    method public void mapPoints(float[], int, float[], int, int);
+    method public void mapPoints(float[], float[]);
+    method public void mapPoints(float[]);
+    method public float mapRadius(float);
+    method public boolean mapRect(android.graphics.RectF, android.graphics.RectF);
+    method public boolean mapRect(android.graphics.RectF);
+    method public void mapVectors(float[], int, float[], int, int);
+    method public void mapVectors(float[], float[]);
+    method public void mapVectors(float[]);
+    method public boolean postConcat(android.graphics.Matrix);
+    method public boolean postRotate(float, float, float);
+    method public boolean postRotate(float);
+    method public boolean postScale(float, float, float, float);
+    method public boolean postScale(float, float);
+    method public boolean postSkew(float, float, float, float);
+    method public boolean postSkew(float, float);
+    method public boolean postTranslate(float, float);
+    method public boolean preConcat(android.graphics.Matrix);
+    method public boolean preRotate(float, float, float);
+    method public boolean preRotate(float);
+    method public boolean preScale(float, float, float, float);
+    method public boolean preScale(float, float);
+    method public boolean preSkew(float, float, float, float);
+    method public boolean preSkew(float, float);
+    method public boolean preTranslate(float, float);
+    method public boolean rectStaysRect();
+    method public void reset();
+    method public void set(android.graphics.Matrix);
+    method public boolean setConcat(android.graphics.Matrix, android.graphics.Matrix);
+    method public boolean setPolyToPoly(float[], int, float[], int, int);
+    method public boolean setRectToRect(android.graphics.RectF, android.graphics.RectF, android.graphics.Matrix.ScaleToFit);
+    method public void setRotate(float, float, float);
+    method public void setRotate(float);
+    method public void setScale(float, float, float, float);
+    method public void setScale(float, float);
+    method public void setSinCos(float, float, float, float);
+    method public void setSinCos(float, float);
+    method public void setSkew(float, float, float, float);
+    method public void setSkew(float, float);
+    method public void setTranslate(float, float);
+    method public void setValues(float[]);
+    method public java.lang.String toShortString();
+    field public static final int MPERSP_0 = 6; // 0x6
+    field public static final int MPERSP_1 = 7; // 0x7
+    field public static final int MPERSP_2 = 8; // 0x8
+    field public static final int MSCALE_X = 0; // 0x0
+    field public static final int MSCALE_Y = 4; // 0x4
+    field public static final int MSKEW_X = 1; // 0x1
+    field public static final int MSKEW_Y = 3; // 0x3
+    field public static final int MTRANS_X = 2; // 0x2
+    field public static final int MTRANS_Y = 5; // 0x5
+  }
+
+  public static final class Matrix.ScaleToFit extends java.lang.Enum {
+    method public static android.graphics.Matrix.ScaleToFit valueOf(java.lang.String);
+    method public static final android.graphics.Matrix.ScaleToFit[] values();
+    enum_constant public static final android.graphics.Matrix.ScaleToFit CENTER;
+    enum_constant public static final android.graphics.Matrix.ScaleToFit END;
+    enum_constant public static final android.graphics.Matrix.ScaleToFit FILL;
+    enum_constant public static final android.graphics.Matrix.ScaleToFit START;
+  }
+
+  public class Movie {
+    method public static android.graphics.Movie decodeByteArray(byte[], int, int);
+    method public static android.graphics.Movie decodeFile(java.lang.String);
+    method public static android.graphics.Movie decodeStream(java.io.InputStream);
+    method public void draw(android.graphics.Canvas, float, float, android.graphics.Paint);
+    method public void draw(android.graphics.Canvas, float, float);
+    method public int duration();
+    method public int height();
+    method public boolean isOpaque();
+    method public boolean setTime(int);
+    method public int width();
+  }
+
+  public class NinePatch {
+    ctor public NinePatch(android.graphics.Bitmap, byte[], java.lang.String);
+    method public void draw(android.graphics.Canvas, android.graphics.RectF);
+    method public void draw(android.graphics.Canvas, android.graphics.Rect);
+    method public void draw(android.graphics.Canvas, android.graphics.Rect, android.graphics.Paint);
+    method public int getDensity();
+    method public int getHeight();
+    method public final android.graphics.Region getTransparentRegion(android.graphics.Rect);
+    method public int getWidth();
+    method public final boolean hasAlpha();
+    method public static boolean isNinePatchChunk(byte[]);
+    method public void setPaint(android.graphics.Paint);
+  }
+
+  public class Paint {
+    ctor public Paint();
+    ctor public Paint(int);
+    ctor public Paint(android.graphics.Paint);
+    method public float ascent();
+    method public int breakText(char[], int, int, float, float[]);
+    method public int breakText(java.lang.CharSequence, int, int, boolean, float, float[]);
+    method public int breakText(java.lang.String, boolean, float, float[]);
+    method public void clearShadowLayer();
+    method public float descent();
+    method public int getAlpha();
+    method public int getColor();
+    method public android.graphics.ColorFilter getColorFilter();
+    method public boolean getFillPath(android.graphics.Path, android.graphics.Path);
+    method public int getFlags();
+    method public float getFontMetrics(android.graphics.Paint.FontMetrics);
+    method public android.graphics.Paint.FontMetrics getFontMetrics();
+    method public int getFontMetricsInt(android.graphics.Paint.FontMetricsInt);
+    method public android.graphics.Paint.FontMetricsInt getFontMetricsInt();
+    method public float getFontSpacing();
+    method public int getHinting();
+    method public android.graphics.MaskFilter getMaskFilter();
+    method public android.graphics.PathEffect getPathEffect();
+    method public android.graphics.Rasterizer getRasterizer();
+    method public android.graphics.Shader getShader();
+    method public android.graphics.Paint.Cap getStrokeCap();
+    method public android.graphics.Paint.Join getStrokeJoin();
+    method public float getStrokeMiter();
+    method public float getStrokeWidth();
+    method public android.graphics.Paint.Style getStyle();
+    method public android.graphics.Paint.Align getTextAlign();
+    method public void getTextBounds(java.lang.String, int, int, android.graphics.Rect);
+    method public void getTextBounds(char[], int, int, android.graphics.Rect);
+    method public java.util.Locale getTextLocale();
+    method public void getTextPath(char[], int, int, float, float, android.graphics.Path);
+    method public void getTextPath(java.lang.String, int, int, float, float, android.graphics.Path);
+    method public float getTextScaleX();
+    method public float getTextSize();
+    method public float getTextSkewX();
+    method public int getTextWidths(char[], int, int, float[]);
+    method public int getTextWidths(java.lang.CharSequence, int, int, float[]);
+    method public int getTextWidths(java.lang.String, int, int, float[]);
+    method public int getTextWidths(java.lang.String, float[]);
+    method public android.graphics.Typeface getTypeface();
+    method public android.graphics.Xfermode getXfermode();
+    method public final boolean isAntiAlias();
+    method public final boolean isDither();
+    method public final boolean isFakeBoldText();
+    method public final boolean isFilterBitmap();
+    method public final deprecated boolean isLinearText();
+    method public final boolean isStrikeThruText();
+    method public final boolean isSubpixelText();
+    method public final boolean isUnderlineText();
+    method public float measureText(char[], int, int);
+    method public float measureText(java.lang.String, int, int);
+    method public float measureText(java.lang.String);
+    method public float measureText(java.lang.CharSequence, int, int);
+    method public void reset();
+    method public void set(android.graphics.Paint);
+    method public void setARGB(int, int, int, int);
+    method public void setAlpha(int);
+    method public void setAntiAlias(boolean);
+    method public void setColor(int);
+    method public android.graphics.ColorFilter setColorFilter(android.graphics.ColorFilter);
+    method public void setDither(boolean);
+    method public void setFakeBoldText(boolean);
+    method public void setFilterBitmap(boolean);
+    method public void setFlags(int);
+    method public void setHinting(int);
+    method public deprecated void setLinearText(boolean);
+    method public android.graphics.MaskFilter setMaskFilter(android.graphics.MaskFilter);
+    method public android.graphics.PathEffect setPathEffect(android.graphics.PathEffect);
+    method public android.graphics.Rasterizer setRasterizer(android.graphics.Rasterizer);
+    method public android.graphics.Shader setShader(android.graphics.Shader);
+    method public void setShadowLayer(float, float, float, int);
+    method public void setStrikeThruText(boolean);
+    method public void setStrokeCap(android.graphics.Paint.Cap);
+    method public void setStrokeJoin(android.graphics.Paint.Join);
+    method public void setStrokeMiter(float);
+    method public void setStrokeWidth(float);
+    method public void setStyle(android.graphics.Paint.Style);
+    method public void setSubpixelText(boolean);
+    method public void setTextAlign(android.graphics.Paint.Align);
+    method public void setTextLocale(java.util.Locale);
+    method public void setTextScaleX(float);
+    method public void setTextSize(float);
+    method public void setTextSkewX(float);
+    method public android.graphics.Typeface setTypeface(android.graphics.Typeface);
+    method public void setUnderlineText(boolean);
+    method public android.graphics.Xfermode setXfermode(android.graphics.Xfermode);
+    field public static final int ANTI_ALIAS_FLAG = 1; // 0x1
+    field public static final int DEV_KERN_TEXT_FLAG = 256; // 0x100
+    field public static final int DITHER_FLAG = 4; // 0x4
+    field public static final int FAKE_BOLD_TEXT_FLAG = 32; // 0x20
+    field public static final int FILTER_BITMAP_FLAG = 2; // 0x2
+    field public static final int HINTING_OFF = 0; // 0x0
+    field public static final int HINTING_ON = 1; // 0x1
+    field public static final int LINEAR_TEXT_FLAG = 64; // 0x40
+    field public static final int STRIKE_THRU_TEXT_FLAG = 16; // 0x10
+    field public static final int SUBPIXEL_TEXT_FLAG = 128; // 0x80
+    field public static final int UNDERLINE_TEXT_FLAG = 8; // 0x8
+  }
+
+  public static final class Paint.Align extends java.lang.Enum {
+    method public static android.graphics.Paint.Align valueOf(java.lang.String);
+    method public static final android.graphics.Paint.Align[] values();
+    enum_constant public static final android.graphics.Paint.Align CENTER;
+    enum_constant public static final android.graphics.Paint.Align LEFT;
+    enum_constant public static final android.graphics.Paint.Align RIGHT;
+  }
+
+  public static final class Paint.Cap extends java.lang.Enum {
+    method public static android.graphics.Paint.Cap valueOf(java.lang.String);
+    method public static final android.graphics.Paint.Cap[] values();
+    enum_constant public static final android.graphics.Paint.Cap BUTT;
+    enum_constant public static final android.graphics.Paint.Cap ROUND;
+    enum_constant public static final android.graphics.Paint.Cap SQUARE;
+  }
+
+  public static class Paint.FontMetrics {
+    ctor public Paint.FontMetrics();
+    field public float ascent;
+    field public float bottom;
+    field public float descent;
+    field public float leading;
+    field public float top;
+  }
+
+  public static class Paint.FontMetricsInt {
+    ctor public Paint.FontMetricsInt();
+    field public int ascent;
+    field public int bottom;
+    field public int descent;
+    field public int leading;
+    field public int top;
+  }
+
+  public static final class Paint.Join extends java.lang.Enum {
+    method public static android.graphics.Paint.Join valueOf(java.lang.String);
+    method public static final android.graphics.Paint.Join[] values();
+    enum_constant public static final android.graphics.Paint.Join BEVEL;
+    enum_constant public static final android.graphics.Paint.Join MITER;
+    enum_constant public static final android.graphics.Paint.Join ROUND;
+  }
+
+  public static final class Paint.Style extends java.lang.Enum {
+    method public static android.graphics.Paint.Style valueOf(java.lang.String);
+    method public static final android.graphics.Paint.Style[] values();
+    enum_constant public static final android.graphics.Paint.Style FILL;
+    enum_constant public static final android.graphics.Paint.Style FILL_AND_STROKE;
+    enum_constant public static final android.graphics.Paint.Style STROKE;
+  }
+
+  public class PaintFlagsDrawFilter extends android.graphics.DrawFilter {
+    ctor public PaintFlagsDrawFilter(int, int);
+  }
+
+  public class Path {
+    ctor public Path();
+    ctor public Path(android.graphics.Path);
+    method public void addArc(android.graphics.RectF, float, float);
+    method public void addCircle(float, float, float, android.graphics.Path.Direction);
+    method public void addOval(android.graphics.RectF, android.graphics.Path.Direction);
+    method public void addPath(android.graphics.Path, float, float);
+    method public void addPath(android.graphics.Path);
+    method public void addPath(android.graphics.Path, android.graphics.Matrix);
+    method public void addRect(android.graphics.RectF, android.graphics.Path.Direction);
+    method public void addRect(float, float, float, float, android.graphics.Path.Direction);
+    method public void addRoundRect(android.graphics.RectF, float, float, android.graphics.Path.Direction);
+    method public void addRoundRect(android.graphics.RectF, float[], android.graphics.Path.Direction);
+    method public void arcTo(android.graphics.RectF, float, float, boolean);
+    method public void arcTo(android.graphics.RectF, float, float);
+    method public void close();
+    method public void computeBounds(android.graphics.RectF, boolean);
+    method public void cubicTo(float, float, float, float, float, float);
+    method public android.graphics.Path.FillType getFillType();
+    method public void incReserve(int);
+    method public boolean isEmpty();
+    method public boolean isInverseFillType();
+    method public boolean isRect(android.graphics.RectF);
+    method public void lineTo(float, float);
+    method public void moveTo(float, float);
+    method public void offset(float, float, android.graphics.Path);
+    method public void offset(float, float);
+    method public void quadTo(float, float, float, float);
+    method public void rCubicTo(float, float, float, float, float, float);
+    method public void rLineTo(float, float);
+    method public void rMoveTo(float, float);
+    method public void rQuadTo(float, float, float, float);
+    method public void reset();
+    method public void rewind();
+    method public void set(android.graphics.Path);
+    method public void setFillType(android.graphics.Path.FillType);
+    method public void setLastPoint(float, float);
+    method public void toggleInverseFillType();
+    method public void transform(android.graphics.Matrix, android.graphics.Path);
+    method public void transform(android.graphics.Matrix);
+  }
+
+  public static final class Path.Direction extends java.lang.Enum {
+    method public static android.graphics.Path.Direction valueOf(java.lang.String);
+    method public static final android.graphics.Path.Direction[] values();
+    enum_constant public static final android.graphics.Path.Direction CCW;
+    enum_constant public static final android.graphics.Path.Direction CW;
+  }
+
+  public static final class Path.FillType extends java.lang.Enum {
+    method public static android.graphics.Path.FillType valueOf(java.lang.String);
+    method public static final android.graphics.Path.FillType[] values();
+    enum_constant public static final android.graphics.Path.FillType EVEN_ODD;
+    enum_constant public static final android.graphics.Path.FillType INVERSE_EVEN_ODD;
+    enum_constant public static final android.graphics.Path.FillType INVERSE_WINDING;
+    enum_constant public static final android.graphics.Path.FillType WINDING;
+  }
+
+  public class PathDashPathEffect extends android.graphics.PathEffect {
+    ctor public PathDashPathEffect(android.graphics.Path, float, float, android.graphics.PathDashPathEffect.Style);
+  }
+
+  public static final class PathDashPathEffect.Style extends java.lang.Enum {
+    method public static android.graphics.PathDashPathEffect.Style valueOf(java.lang.String);
+    method public static final android.graphics.PathDashPathEffect.Style[] values();
+    enum_constant public static final android.graphics.PathDashPathEffect.Style MORPH;
+    enum_constant public static final android.graphics.PathDashPathEffect.Style ROTATE;
+    enum_constant public static final android.graphics.PathDashPathEffect.Style TRANSLATE;
+  }
+
+  public class PathEffect {
+    ctor public PathEffect();
+  }
+
+  public class PathMeasure {
+    ctor public PathMeasure();
+    ctor public PathMeasure(android.graphics.Path, boolean);
+    method public float getLength();
+    method public boolean getMatrix(float, android.graphics.Matrix, int);
+    method public boolean getPosTan(float, float[], float[]);
+    method public boolean getSegment(float, float, android.graphics.Path, boolean);
+    method public boolean isClosed();
+    method public boolean nextContour();
+    method public void setPath(android.graphics.Path, boolean);
+    field public static final int POSITION_MATRIX_FLAG = 1; // 0x1
+    field public static final int TANGENT_MATRIX_FLAG = 2; // 0x2
+  }
+
+  public class Picture {
+    ctor public Picture();
+    ctor public Picture(android.graphics.Picture);
+    method public android.graphics.Canvas beginRecording(int, int);
+    method public static android.graphics.Picture createFromStream(java.io.InputStream);
+    method public void draw(android.graphics.Canvas);
+    method public void endRecording();
+    method public int getHeight();
+    method public int getWidth();
+    method public void writeToStream(java.io.OutputStream);
+  }
+
+  public class PixelFormat {
+    ctor public PixelFormat();
+    method public static boolean formatHasAlpha(int);
+    method public static void getPixelFormatInfo(int, android.graphics.PixelFormat);
+    field public static final int A_8 = 8; // 0x8
+    field public static final deprecated int JPEG = 256; // 0x100
+    field public static final deprecated int LA_88 = 10; // 0xa
+    field public static final int L_8 = 9; // 0x9
+    field public static final int OPAQUE = -1; // 0xffffffff
+    field public static final deprecated int RGBA_4444 = 7; // 0x7
+    field public static final deprecated int RGBA_5551 = 6; // 0x6
+    field public static final int RGBA_8888 = 1; // 0x1
+    field public static final int RGBX_8888 = 2; // 0x2
+    field public static final deprecated int RGB_332 = 11; // 0xb
+    field public static final int RGB_565 = 4; // 0x4
+    field public static final int RGB_888 = 3; // 0x3
+    field public static final int TRANSLUCENT = -3; // 0xfffffffd
+    field public static final int TRANSPARENT = -2; // 0xfffffffe
+    field public static final int UNKNOWN = 0; // 0x0
+    field public static final deprecated int YCbCr_420_SP = 17; // 0x11
+    field public static final deprecated int YCbCr_422_I = 20; // 0x14
+    field public static final deprecated int YCbCr_422_SP = 16; // 0x10
+    field public int bitsPerPixel;
+    field public int bytesPerPixel;
+  }
+
+  public deprecated class PixelXorXfermode extends android.graphics.Xfermode {
+    ctor public PixelXorXfermode(int);
+  }
+
+  public class Point implements android.os.Parcelable {
+    ctor public Point();
+    ctor public Point(int, int);
+    ctor public Point(android.graphics.Point);
+    method public int describeContents();
+    method public final boolean equals(int, int);
+    method public final void negate();
+    method public final void offset(int, int);
+    method public void readFromParcel(android.os.Parcel);
+    method public void set(int, int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public int x;
+    field public int y;
+  }
+
+  public class PointF implements android.os.Parcelable {
+    ctor public PointF();
+    ctor public PointF(float, float);
+    ctor public PointF(android.graphics.Point);
+    method public int describeContents();
+    method public final boolean equals(float, float);
+    method public final float length();
+    method public static float length(float, float);
+    method public final void negate();
+    method public final void offset(float, float);
+    method public void readFromParcel(android.os.Parcel);
+    method public final void set(float, float);
+    method public final void set(android.graphics.PointF);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public float x;
+    field public float y;
+  }
+
+  public class PorterDuff {
+    ctor public PorterDuff();
+  }
+
+  public static final class PorterDuff.Mode extends java.lang.Enum {
+    method public static android.graphics.PorterDuff.Mode valueOf(java.lang.String);
+    method public static final android.graphics.PorterDuff.Mode[] values();
+    enum_constant public static final android.graphics.PorterDuff.Mode ADD;
+    enum_constant public static final android.graphics.PorterDuff.Mode CLEAR;
+    enum_constant public static final android.graphics.PorterDuff.Mode DARKEN;
+    enum_constant public static final android.graphics.PorterDuff.Mode DST;
+    enum_constant public static final android.graphics.PorterDuff.Mode DST_ATOP;
+    enum_constant public static final android.graphics.PorterDuff.Mode DST_IN;
+    enum_constant public static final android.graphics.PorterDuff.Mode DST_OUT;
+    enum_constant public static final android.graphics.PorterDuff.Mode DST_OVER;
+    enum_constant public static final android.graphics.PorterDuff.Mode LIGHTEN;
+    enum_constant public static final android.graphics.PorterDuff.Mode MULTIPLY;
+    enum_constant public static final android.graphics.PorterDuff.Mode OVERLAY;
+    enum_constant public static final android.graphics.PorterDuff.Mode SCREEN;
+    enum_constant public static final android.graphics.PorterDuff.Mode SRC;
+    enum_constant public static final android.graphics.PorterDuff.Mode SRC_ATOP;
+    enum_constant public static final android.graphics.PorterDuff.Mode SRC_IN;
+    enum_constant public static final android.graphics.PorterDuff.Mode SRC_OUT;
+    enum_constant public static final android.graphics.PorterDuff.Mode SRC_OVER;
+    enum_constant public static final android.graphics.PorterDuff.Mode XOR;
+  }
+
+  public class PorterDuffColorFilter extends android.graphics.ColorFilter {
+    ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
+  }
+
+  public class PorterDuffXfermode extends android.graphics.Xfermode {
+    ctor public PorterDuffXfermode(android.graphics.PorterDuff.Mode);
+  }
+
+  public class RadialGradient extends android.graphics.Shader {
+    ctor public RadialGradient(float, float, float, int[], float[], android.graphics.Shader.TileMode);
+    ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode);
+  }
+
+  public class Rasterizer {
+    ctor public Rasterizer();
+  }
+
+  public final class Rect implements android.os.Parcelable {
+    ctor public Rect();
+    ctor public Rect(int, int, int, int);
+    ctor public Rect(android.graphics.Rect);
+    method public final int centerX();
+    method public final int centerY();
+    method public boolean contains(int, int);
+    method public boolean contains(int, int, int, int);
+    method public boolean contains(android.graphics.Rect);
+    method public int describeContents();
+    method public final float exactCenterX();
+    method public final float exactCenterY();
+    method public java.lang.String flattenToString();
+    method public final int height();
+    method public void inset(int, int);
+    method public boolean intersect(int, int, int, int);
+    method public boolean intersect(android.graphics.Rect);
+    method public boolean intersects(int, int, int, int);
+    method public static boolean intersects(android.graphics.Rect, android.graphics.Rect);
+    method public final boolean isEmpty();
+    method public void offset(int, int);
+    method public void offsetTo(int, int);
+    method public void readFromParcel(android.os.Parcel);
+    method public void set(int, int, int, int);
+    method public void set(android.graphics.Rect);
+    method public void setEmpty();
+    method public boolean setIntersect(android.graphics.Rect, android.graphics.Rect);
+    method public void sort();
+    method public java.lang.String toShortString();
+    method public static android.graphics.Rect unflattenFromString(java.lang.String);
+    method public void union(int, int, int, int);
+    method public void union(android.graphics.Rect);
+    method public void union(int, int);
+    method public final int width();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public int bottom;
+    field public int left;
+    field public int right;
+    field public int top;
+  }
+
+  public class RectF implements android.os.Parcelable {
+    ctor public RectF();
+    ctor public RectF(float, float, float, float);
+    ctor public RectF(android.graphics.RectF);
+    ctor public RectF(android.graphics.Rect);
+    method public final float centerX();
+    method public final float centerY();
+    method public boolean contains(float, float);
+    method public boolean contains(float, float, float, float);
+    method public boolean contains(android.graphics.RectF);
+    method public int describeContents();
+    method public final float height();
+    method public void inset(float, float);
+    method public boolean intersect(float, float, float, float);
+    method public boolean intersect(android.graphics.RectF);
+    method public boolean intersects(float, float, float, float);
+    method public static boolean intersects(android.graphics.RectF, android.graphics.RectF);
+    method public final boolean isEmpty();
+    method public void offset(float, float);
+    method public void offsetTo(float, float);
+    method public void readFromParcel(android.os.Parcel);
+    method public void round(android.graphics.Rect);
+    method public void roundOut(android.graphics.Rect);
+    method public void set(float, float, float, float);
+    method public void set(android.graphics.RectF);
+    method public void set(android.graphics.Rect);
+    method public void setEmpty();
+    method public boolean setIntersect(android.graphics.RectF, android.graphics.RectF);
+    method public void sort();
+    method public java.lang.String toShortString();
+    method public void union(float, float, float, float);
+    method public void union(android.graphics.RectF);
+    method public void union(float, float);
+    method public final float width();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public float bottom;
+    field public float left;
+    field public float right;
+    field public float top;
+  }
+
+  public class Region implements android.os.Parcelable {
+    ctor public Region();
+    ctor public Region(android.graphics.Region);
+    ctor public Region(android.graphics.Rect);
+    ctor public Region(int, int, int, int);
+    method public boolean contains(int, int);
+    method public int describeContents();
+    method public android.graphics.Path getBoundaryPath();
+    method public boolean getBoundaryPath(android.graphics.Path);
+    method public android.graphics.Rect getBounds();
+    method public boolean getBounds(android.graphics.Rect);
+    method public boolean isComplex();
+    method public boolean isEmpty();
+    method public boolean isRect();
+    method public boolean op(android.graphics.Rect, android.graphics.Region.Op);
+    method public boolean op(int, int, int, int, android.graphics.Region.Op);
+    method public boolean op(android.graphics.Region, android.graphics.Region.Op);
+    method public boolean op(android.graphics.Rect, android.graphics.Region, android.graphics.Region.Op);
+    method public boolean op(android.graphics.Region, android.graphics.Region, android.graphics.Region.Op);
+    method public boolean quickContains(android.graphics.Rect);
+    method public boolean quickContains(int, int, int, int);
+    method public boolean quickReject(android.graphics.Rect);
+    method public boolean quickReject(int, int, int, int);
+    method public boolean quickReject(android.graphics.Region);
+    method public boolean set(android.graphics.Region);
+    method public boolean set(android.graphics.Rect);
+    method public boolean set(int, int, int, int);
+    method public void setEmpty();
+    method public boolean setPath(android.graphics.Path, android.graphics.Region);
+    method public void translate(int, int);
+    method public void translate(int, int, android.graphics.Region);
+    method public final boolean union(android.graphics.Rect);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static final class Region.Op extends java.lang.Enum {
+    method public static android.graphics.Region.Op valueOf(java.lang.String);
+    method public static final android.graphics.Region.Op[] values();
+    enum_constant public static final android.graphics.Region.Op DIFFERENCE;
+    enum_constant public static final android.graphics.Region.Op INTERSECT;
+    enum_constant public static final android.graphics.Region.Op REPLACE;
+    enum_constant public static final android.graphics.Region.Op REVERSE_DIFFERENCE;
+    enum_constant public static final android.graphics.Region.Op UNION;
+    enum_constant public static final android.graphics.Region.Op XOR;
+  }
+
+  public class RegionIterator {
+    ctor public RegionIterator(android.graphics.Region);
+    method public final boolean next(android.graphics.Rect);
+  }
+
+  public class Shader {
+    ctor public Shader();
+    method public boolean getLocalMatrix(android.graphics.Matrix);
+    method public void setLocalMatrix(android.graphics.Matrix);
+  }
+
+  public static final class Shader.TileMode extends java.lang.Enum {
+    method public static android.graphics.Shader.TileMode valueOf(java.lang.String);
+    method public static final android.graphics.Shader.TileMode[] values();
+    enum_constant public static final android.graphics.Shader.TileMode CLAMP;
+    enum_constant public static final android.graphics.Shader.TileMode MIRROR;
+    enum_constant public static final android.graphics.Shader.TileMode REPEAT;
+  }
+
+  public class SumPathEffect extends android.graphics.PathEffect {
+    ctor public SumPathEffect(android.graphics.PathEffect, android.graphics.PathEffect);
+  }
+
+  public class SurfaceTexture {
+    ctor public SurfaceTexture(int);
+    method public void attachToGLContext(int);
+    method public void detachFromGLContext();
+    method public long getTimestamp();
+    method public void getTransformMatrix(float[]);
+    method public void release();
+    method public void setDefaultBufferSize(int, int);
+    method public void setOnFrameAvailableListener(android.graphics.SurfaceTexture.OnFrameAvailableListener);
+    method public void updateTexImage();
+  }
+
+  public static abstract interface SurfaceTexture.OnFrameAvailableListener {
+    method public abstract void onFrameAvailable(android.graphics.SurfaceTexture);
+  }
+
+  public static class SurfaceTexture.OutOfResourcesException extends java.lang.Exception {
+    ctor public SurfaceTexture.OutOfResourcesException();
+    ctor public SurfaceTexture.OutOfResourcesException(java.lang.String);
+  }
+
+  public class SweepGradient extends android.graphics.Shader {
+    ctor public SweepGradient(float, float, int[], float[]);
+    ctor public SweepGradient(float, float, int, int);
+  }
+
+  public class Typeface {
+    method public static android.graphics.Typeface create(java.lang.String, int);
+    method public static android.graphics.Typeface create(android.graphics.Typeface, int);
+    method public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String);
+    method public static android.graphics.Typeface createFromFile(java.io.File);
+    method public static android.graphics.Typeface createFromFile(java.lang.String);
+    method public static android.graphics.Typeface defaultFromStyle(int);
+    method public int getStyle();
+    method public final boolean isBold();
+    method public final boolean isItalic();
+    field public static final int BOLD = 1; // 0x1
+    field public static final int BOLD_ITALIC = 3; // 0x3
+    field public static final android.graphics.Typeface DEFAULT;
+    field public static final android.graphics.Typeface DEFAULT_BOLD;
+    field public static final int ITALIC = 2; // 0x2
+    field public static final android.graphics.Typeface MONOSPACE;
+    field public static final int NORMAL = 0; // 0x0
+    field public static final android.graphics.Typeface SANS_SERIF;
+    field public static final android.graphics.Typeface SERIF;
+  }
+
+  public class Xfermode {
+    ctor public Xfermode();
+  }
+
+  public class YuvImage {
+    ctor public YuvImage(byte[], int, int, int, int[]);
+    method public boolean compressToJpeg(android.graphics.Rect, int, java.io.OutputStream);
+    method public int getHeight();
+    method public int[] getStrides();
+    method public int getWidth();
+    method public byte[] getYuvData();
+    method public int getYuvFormat();
+  }
+
+}
+
+package android.graphics.drawable {
+
+  public abstract interface Animatable {
+    method public abstract boolean isRunning();
+    method public abstract void start();
+    method public abstract void stop();
+  }
+
+  public class AnimationDrawable extends android.graphics.drawable.DrawableContainer implements android.graphics.drawable.Animatable java.lang.Runnable {
+    ctor public AnimationDrawable();
+    method public void addFrame(android.graphics.drawable.Drawable, int);
+    method public int getDuration(int);
+    method public android.graphics.drawable.Drawable getFrame(int);
+    method public int getNumberOfFrames();
+    method public boolean isOneShot();
+    method public boolean isRunning();
+    method public void run();
+    method public void setOneShot(boolean);
+    method public void start();
+    method public void stop();
+  }
+
+  public class BitmapDrawable extends android.graphics.drawable.Drawable {
+    ctor public deprecated BitmapDrawable();
+    ctor public BitmapDrawable(android.content.res.Resources);
+    ctor public deprecated BitmapDrawable(android.graphics.Bitmap);
+    ctor public BitmapDrawable(android.content.res.Resources, android.graphics.Bitmap);
+    ctor public deprecated BitmapDrawable(java.lang.String);
+    ctor public BitmapDrawable(android.content.res.Resources, java.lang.String);
+    ctor public deprecated BitmapDrawable(java.io.InputStream);
+    ctor public BitmapDrawable(android.content.res.Resources, java.io.InputStream);
+    method public void draw(android.graphics.Canvas);
+    method public final android.graphics.Bitmap getBitmap();
+    method public final android.graphics.drawable.Drawable.ConstantState getConstantState();
+    method public int getGravity();
+    method public int getOpacity();
+    method public final android.graphics.Paint getPaint();
+    method public android.graphics.Shader.TileMode getTileModeX();
+    method public android.graphics.Shader.TileMode getTileModeY();
+    method public void setAlpha(int);
+    method public void setAntiAlias(boolean);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void setGravity(int);
+    method public void setTargetDensity(android.graphics.Canvas);
+    method public void setTargetDensity(android.util.DisplayMetrics);
+    method public void setTargetDensity(int);
+    method public void setTileModeX(android.graphics.Shader.TileMode);
+    method public void setTileModeXY(android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
+    method public final void setTileModeY(android.graphics.Shader.TileMode);
+  }
+
+  public class ClipDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+    ctor public ClipDrawable(android.graphics.drawable.Drawable, int, int);
+    method public void draw(android.graphics.Canvas);
+    method public int getOpacity();
+    method public void invalidateDrawable(android.graphics.drawable.Drawable);
+    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+    method public void setAlpha(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+    field public static final int HORIZONTAL = 1; // 0x1
+    field public static final int VERTICAL = 2; // 0x2
+  }
+
+  public class ColorDrawable extends android.graphics.drawable.Drawable {
+    ctor public ColorDrawable();
+    ctor public ColorDrawable(int);
+    method public void draw(android.graphics.Canvas);
+    method public int getAlpha();
+    method public int getColor();
+    method public int getOpacity();
+    method public void setAlpha(int);
+    method public void setColor(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+  }
+
+  public abstract class Drawable {
+    ctor public Drawable();
+    method public void clearColorFilter();
+    method public final void copyBounds(android.graphics.Rect);
+    method public final android.graphics.Rect copyBounds();
+    method public static android.graphics.drawable.Drawable createFromPath(java.lang.String);
+    method public static android.graphics.drawable.Drawable createFromResourceStream(android.content.res.Resources, android.util.TypedValue, java.io.InputStream, java.lang.String);
+    method public static android.graphics.drawable.Drawable createFromResourceStream(android.content.res.Resources, android.util.TypedValue, java.io.InputStream, java.lang.String, android.graphics.BitmapFactory.Options);
+    method public static android.graphics.drawable.Drawable createFromStream(java.io.InputStream, java.lang.String);
+    method public static android.graphics.drawable.Drawable createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static android.graphics.drawable.Drawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public abstract void draw(android.graphics.Canvas);
+    method public final android.graphics.Rect getBounds();
+    method public android.graphics.drawable.Drawable.Callback getCallback();
+    method public int getChangingConfigurations();
+    method public android.graphics.drawable.Drawable.ConstantState getConstantState();
+    method public android.graphics.drawable.Drawable getCurrent();
+    method public int getIntrinsicHeight();
+    method public int getIntrinsicWidth();
+    method public final int getLevel();
+    method public int getMinimumHeight();
+    method public int getMinimumWidth();
+    method public abstract int getOpacity();
+    method public boolean getPadding(android.graphics.Rect);
+    method public int[] getState();
+    method public android.graphics.Region getTransparentRegion();
+    method public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public void invalidateSelf();
+    method public boolean isStateful();
+    method public final boolean isVisible();
+    method public void jumpToCurrentState();
+    method public android.graphics.drawable.Drawable mutate();
+    method protected void onBoundsChange(android.graphics.Rect);
+    method protected boolean onLevelChange(int);
+    method protected boolean onStateChange(int[]);
+    method public static int resolveOpacity(int, int);
+    method public void scheduleSelf(java.lang.Runnable, long);
+    method public abstract void setAlpha(int);
+    method public void setBounds(int, int, int, int);
+    method public void setBounds(android.graphics.Rect);
+    method public final void setCallback(android.graphics.drawable.Drawable.Callback);
+    method public void setChangingConfigurations(int);
+    method public abstract void setColorFilter(android.graphics.ColorFilter);
+    method public void setColorFilter(int, android.graphics.PorterDuff.Mode);
+    method public void setDither(boolean);
+    method public void setFilterBitmap(boolean);
+    method public final boolean setLevel(int);
+    method public boolean setState(int[]);
+    method public boolean setVisible(boolean, boolean);
+    method public void unscheduleSelf(java.lang.Runnable);
+  }
+
+  public static abstract interface Drawable.Callback {
+    method public abstract void invalidateDrawable(android.graphics.drawable.Drawable);
+    method public abstract void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+    method public abstract void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+  }
+
+  public static abstract class Drawable.ConstantState {
+    ctor public Drawable.ConstantState();
+    method public abstract int getChangingConfigurations();
+    method public abstract android.graphics.drawable.Drawable newDrawable();
+    method public android.graphics.drawable.Drawable newDrawable(android.content.res.Resources);
+  }
+
+  public class DrawableContainer extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+    ctor public DrawableContainer();
+    method public void draw(android.graphics.Canvas);
+    method public int getOpacity();
+    method public void invalidateDrawable(android.graphics.drawable.Drawable);
+    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+    method public boolean selectDrawable(int);
+    method public void setAlpha(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method protected void setConstantState(android.graphics.drawable.DrawableContainer.DrawableContainerState);
+    method public void setEnterFadeDuration(int);
+    method public void setExitFadeDuration(int);
+    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+  }
+
+  public static abstract class DrawableContainer.DrawableContainerState extends android.graphics.drawable.Drawable.ConstantState {
+    method public final int addChild(android.graphics.drawable.Drawable);
+    method public synchronized boolean canConstantState();
+    method protected void computeConstantSize();
+    method public int getChangingConfigurations();
+    method public final int getChildCount();
+    method public final android.graphics.drawable.Drawable[] getChildren();
+    method public final int getConstantHeight();
+    method public final int getConstantMinimumHeight();
+    method public final int getConstantMinimumWidth();
+    method public final android.graphics.Rect getConstantPadding();
+    method public final int getConstantWidth();
+    method public final int getEnterFadeDuration();
+    method public final int getExitFadeDuration();
+    method public final int getOpacity();
+    method public void growArray(int, int);
+    method public final boolean isConstantSize();
+    method public final boolean isStateful();
+    method public final void setConstantSize(boolean);
+    method public final void setEnterFadeDuration(int);
+    method public final void setExitFadeDuration(int);
+    method public final void setVariablePadding(boolean);
+  }
+
+  public class GradientDrawable extends android.graphics.drawable.Drawable {
+    ctor public GradientDrawable();
+    ctor public GradientDrawable(android.graphics.drawable.GradientDrawable.Orientation, int[]);
+    method public void draw(android.graphics.Canvas);
+    method public int getOpacity();
+    method public android.graphics.drawable.GradientDrawable.Orientation getOrientation();
+    method public void setAlpha(int);
+    method public void setColor(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void setColors(int[]);
+    method public void setCornerRadii(float[]);
+    method public void setCornerRadius(float);
+    method public void setGradientCenter(float, float);
+    method public void setGradientRadius(float);
+    method public void setGradientType(int);
+    method public void setOrientation(android.graphics.drawable.GradientDrawable.Orientation);
+    method public void setShape(int);
+    method public void setSize(int, int);
+    method public void setStroke(int, int);
+    method public void setStroke(int, int, float, float);
+    method public void setUseLevel(boolean);
+    field public static final int LINE = 2; // 0x2
+    field public static final int LINEAR_GRADIENT = 0; // 0x0
+    field public static final int OVAL = 1; // 0x1
+    field public static final int RADIAL_GRADIENT = 1; // 0x1
+    field public static final int RECTANGLE = 0; // 0x0
+    field public static final int RING = 3; // 0x3
+    field public static final int SWEEP_GRADIENT = 2; // 0x2
+  }
+
+  public static final class GradientDrawable.Orientation extends java.lang.Enum {
+    method public static android.graphics.drawable.GradientDrawable.Orientation valueOf(java.lang.String);
+    method public static final android.graphics.drawable.GradientDrawable.Orientation[] values();
+    enum_constant public static final android.graphics.drawable.GradientDrawable.Orientation BL_TR;
+    enum_constant public static final android.graphics.drawable.GradientDrawable.Orientation BOTTOM_TOP;
+    enum_constant public static final android.graphics.drawable.GradientDrawable.Orientation BR_TL;
+    enum_constant public static final android.graphics.drawable.GradientDrawable.Orientation LEFT_RIGHT;
+    enum_constant public static final android.graphics.drawable.GradientDrawable.Orientation RIGHT_LEFT;
+    enum_constant public static final android.graphics.drawable.GradientDrawable.Orientation TL_BR;
+    enum_constant public static final android.graphics.drawable.GradientDrawable.Orientation TOP_BOTTOM;
+    enum_constant public static final android.graphics.drawable.GradientDrawable.Orientation TR_BL;
+  }
+
+  public class InsetDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+    ctor public InsetDrawable(android.graphics.drawable.Drawable, int);
+    ctor public InsetDrawable(android.graphics.drawable.Drawable, int, int, int, int);
+    method public void draw(android.graphics.Canvas);
+    method public int getOpacity();
+    method public void invalidateDrawable(android.graphics.drawable.Drawable);
+    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+    method public void setAlpha(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+  }
+
+  public class LayerDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+    ctor public LayerDrawable(android.graphics.drawable.Drawable[]);
+    method public void draw(android.graphics.Canvas);
+    method public android.graphics.drawable.Drawable findDrawableByLayerId(int);
+    method public android.graphics.drawable.Drawable getDrawable(int);
+    method public int getId(int);
+    method public int getNumberOfLayers();
+    method public int getOpacity();
+    method public void invalidateDrawable(android.graphics.drawable.Drawable);
+    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+    method public void setAlpha(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public boolean setDrawableByLayerId(int, android.graphics.drawable.Drawable);
+    method public void setId(int, int);
+    method public void setLayerInset(int, int, int, int, int);
+    method public void setOpacity(int);
+    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+  }
+
+  public class LevelListDrawable extends android.graphics.drawable.DrawableContainer {
+    ctor public LevelListDrawable();
+    method public void addLevel(int, int, android.graphics.drawable.Drawable);
+  }
+
+  public class NinePatchDrawable extends android.graphics.drawable.Drawable {
+    ctor public deprecated NinePatchDrawable(android.graphics.Bitmap, byte[], android.graphics.Rect, java.lang.String);
+    ctor public NinePatchDrawable(android.content.res.Resources, android.graphics.Bitmap, byte[], android.graphics.Rect, java.lang.String);
+    ctor public deprecated NinePatchDrawable(android.graphics.NinePatch);
+    ctor public NinePatchDrawable(android.content.res.Resources, android.graphics.NinePatch);
+    method public void draw(android.graphics.Canvas);
+    method public int getOpacity();
+    method public android.graphics.Paint getPaint();
+    method public void setAlpha(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void setTargetDensity(android.graphics.Canvas);
+    method public void setTargetDensity(android.util.DisplayMetrics);
+    method public void setTargetDensity(int);
+  }
+
+  public class PaintDrawable extends android.graphics.drawable.ShapeDrawable {
+    ctor public PaintDrawable();
+    ctor public PaintDrawable(int);
+    method public void setCornerRadii(float[]);
+    method public void setCornerRadius(float);
+  }
+
+  public class PictureDrawable extends android.graphics.drawable.Drawable {
+    ctor public PictureDrawable(android.graphics.Picture);
+    method public void draw(android.graphics.Canvas);
+    method public int getOpacity();
+    method public android.graphics.Picture getPicture();
+    method public void setAlpha(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void setPicture(android.graphics.Picture);
+  }
+
+  public class RotateDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+    ctor public RotateDrawable();
+    method public void draw(android.graphics.Canvas);
+    method public android.graphics.drawable.Drawable getDrawable();
+    method public int getOpacity();
+    method public void invalidateDrawable(android.graphics.drawable.Drawable);
+    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+    method public void setAlpha(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+  }
+
+  public class ScaleDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+    ctor public ScaleDrawable(android.graphics.drawable.Drawable, int, float, float);
+    method public void draw(android.graphics.Canvas);
+    method public android.graphics.drawable.Drawable getDrawable();
+    method public int getOpacity();
+    method public void invalidateDrawable(android.graphics.drawable.Drawable);
+    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+    method public void setAlpha(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+  }
+
+  public class ShapeDrawable extends android.graphics.drawable.Drawable {
+    ctor public ShapeDrawable();
+    ctor public ShapeDrawable(android.graphics.drawable.shapes.Shape);
+    method public void draw(android.graphics.Canvas);
+    method public int getOpacity();
+    method public android.graphics.Paint getPaint();
+    method public android.graphics.drawable.ShapeDrawable.ShaderFactory getShaderFactory();
+    method public android.graphics.drawable.shapes.Shape getShape();
+    method protected boolean inflateTag(java.lang.String, android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet);
+    method protected void onDraw(android.graphics.drawable.shapes.Shape, android.graphics.Canvas, android.graphics.Paint);
+    method public void setAlpha(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void setIntrinsicHeight(int);
+    method public void setIntrinsicWidth(int);
+    method public void setPadding(int, int, int, int);
+    method public void setPadding(android.graphics.Rect);
+    method public void setShaderFactory(android.graphics.drawable.ShapeDrawable.ShaderFactory);
+    method public void setShape(android.graphics.drawable.shapes.Shape);
+  }
+
+  public static abstract class ShapeDrawable.ShaderFactory {
+    ctor public ShapeDrawable.ShaderFactory();
+    method public abstract android.graphics.Shader resize(int, int);
+  }
+
+  public class StateListDrawable extends android.graphics.drawable.DrawableContainer {
+    ctor public StateListDrawable();
+    method public void addState(int[], android.graphics.drawable.Drawable);
+  }
+
+  public class TransitionDrawable extends android.graphics.drawable.LayerDrawable implements android.graphics.drawable.Drawable.Callback {
+    ctor public TransitionDrawable(android.graphics.drawable.Drawable[]);
+    method public boolean isCrossFadeEnabled();
+    method public void resetTransition();
+    method public void reverseTransition(int);
+    method public void setCrossFadeEnabled(boolean);
+    method public void startTransition(int);
+  }
+
+}
+
+package android.graphics.drawable.shapes {
+
+  public class ArcShape extends android.graphics.drawable.shapes.RectShape {
+    ctor public ArcShape(float, float);
+  }
+
+  public class OvalShape extends android.graphics.drawable.shapes.RectShape {
+    ctor public OvalShape();
+  }
+
+  public class PathShape extends android.graphics.drawable.shapes.Shape {
+    ctor public PathShape(android.graphics.Path, float, float);
+    method public void draw(android.graphics.Canvas, android.graphics.Paint);
+  }
+
+  public class RectShape extends android.graphics.drawable.shapes.Shape {
+    ctor public RectShape();
+    method public void draw(android.graphics.Canvas, android.graphics.Paint);
+    method protected final android.graphics.RectF rect();
+  }
+
+  public class RoundRectShape extends android.graphics.drawable.shapes.RectShape {
+    ctor public RoundRectShape(float[], android.graphics.RectF, float[]);
+  }
+
+  public abstract class Shape implements java.lang.Cloneable {
+    ctor public Shape();
+    method public android.graphics.drawable.shapes.Shape clone() throws java.lang.CloneNotSupportedException;
+    method public abstract void draw(android.graphics.Canvas, android.graphics.Paint);
+    method public final float getHeight();
+    method public final float getWidth();
+    method public boolean hasAlpha();
+    method protected void onResize(float, float);
+    method public final void resize(float, float);
+  }
+
+}
+
+package android.hardware {
+
+  public class Camera {
+    method public final void addCallbackBuffer(byte[]);
+    method public final void autoFocus(android.hardware.Camera.AutoFocusCallback);
+    method public final void cancelAutoFocus();
+    method public final boolean enableShutterSound(boolean);
+    method public static void getCameraInfo(int, android.hardware.Camera.CameraInfo);
+    method public static int getNumberOfCameras();
+    method public android.hardware.Camera.Parameters getParameters();
+    method public final void lock();
+    method public static android.hardware.Camera open(int);
+    method public static android.hardware.Camera open();
+    method public final void reconnect() throws java.io.IOException;
+    method public final void release();
+    method public void setAutoFocusMoveCallback(android.hardware.Camera.AutoFocusMoveCallback);
+    method public final void setDisplayOrientation(int);
+    method public final void setErrorCallback(android.hardware.Camera.ErrorCallback);
+    method public final void setFaceDetectionListener(android.hardware.Camera.FaceDetectionListener);
+    method public final void setOneShotPreviewCallback(android.hardware.Camera.PreviewCallback);
+    method public void setParameters(android.hardware.Camera.Parameters);
+    method public final void setPreviewCallback(android.hardware.Camera.PreviewCallback);
+    method public final void setPreviewCallbackWithBuffer(android.hardware.Camera.PreviewCallback);
+    method public final void setPreviewDisplay(android.view.SurfaceHolder) throws java.io.IOException;
+    method public final void setPreviewTexture(android.graphics.SurfaceTexture) throws java.io.IOException;
+    method public final void setZoomChangeListener(android.hardware.Camera.OnZoomChangeListener);
+    method public final void startFaceDetection();
+    method public final void startPreview();
+    method public final void startSmoothZoom(int);
+    method public final void stopFaceDetection();
+    method public final void stopPreview();
+    method public final void stopSmoothZoom();
+    method public final void takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback);
+    method public final void takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback);
+    method public final void unlock();
+    field public static final java.lang.String ACTION_NEW_PICTURE = "android.hardware.action.NEW_PICTURE";
+    field public static final java.lang.String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO";
+    field public static final int CAMERA_ERROR_SERVER_DIED = 100; // 0x64
+    field public static final int CAMERA_ERROR_UNKNOWN = 1; // 0x1
+  }
+
+  public static class Camera.Area {
+    ctor public Camera.Area(android.graphics.Rect, int);
+    field public android.graphics.Rect rect;
+    field public int weight;
+  }
+
+  public static abstract interface Camera.AutoFocusCallback {
+    method public abstract void onAutoFocus(boolean, android.hardware.Camera);
+  }
+
+  public static abstract interface Camera.AutoFocusMoveCallback {
+    method public abstract void onAutoFocusMoving(boolean, android.hardware.Camera);
+  }
+
+  public static class Camera.CameraInfo {
+    ctor public Camera.CameraInfo();
+    field public static final int CAMERA_FACING_BACK = 0; // 0x0
+    field public static final int CAMERA_FACING_FRONT = 1; // 0x1
+    field public boolean canDisableShutterSound;
+    field public int facing;
+    field public int orientation;
+  }
+
+  public static abstract interface Camera.ErrorCallback {
+    method public abstract void onError(int, android.hardware.Camera);
+  }
+
+  public static class Camera.Face {
+    ctor public Camera.Face();
+    field public int id;
+    field public android.graphics.Point leftEye;
+    field public android.graphics.Point mouth;
+    field public android.graphics.Rect rect;
+    field public android.graphics.Point rightEye;
+    field public int score;
+  }
+
+  public static abstract interface Camera.FaceDetectionListener {
+    method public abstract void onFaceDetection(android.hardware.Camera.Face[], android.hardware.Camera);
+  }
+
+  public static abstract interface Camera.OnZoomChangeListener {
+    method public abstract void onZoomChange(int, boolean, android.hardware.Camera);
+  }
+
+  public class Camera.Parameters {
+    method public java.lang.String flatten();
+    method public java.lang.String get(java.lang.String);
+    method public java.lang.String getAntibanding();
+    method public boolean getAutoExposureLock();
+    method public boolean getAutoWhiteBalanceLock();
+    method public java.lang.String getColorEffect();
+    method public int getExposureCompensation();
+    method public float getExposureCompensationStep();
+    method public java.lang.String getFlashMode();
+    method public float getFocalLength();
+    method public java.util.List<android.hardware.Camera.Area> getFocusAreas();
+    method public void getFocusDistances(float[]);
+    method public java.lang.String getFocusMode();
+    method public float getHorizontalViewAngle();
+    method public int getInt(java.lang.String);
+    method public int getJpegQuality();
+    method public int getJpegThumbnailQuality();
+    method public android.hardware.Camera.Size getJpegThumbnailSize();
+    method public int getMaxExposureCompensation();
+    method public int getMaxNumDetectedFaces();
+    method public int getMaxNumFocusAreas();
+    method public int getMaxNumMeteringAreas();
+    method public int getMaxZoom();
+    method public java.util.List<android.hardware.Camera.Area> getMeteringAreas();
+    method public int getMinExposureCompensation();
+    method public int getPictureFormat();
+    method public android.hardware.Camera.Size getPictureSize();
+    method public android.hardware.Camera.Size getPreferredPreviewSizeForVideo();
+    method public int getPreviewFormat();
+    method public void getPreviewFpsRange(int[]);
+    method public deprecated int getPreviewFrameRate();
+    method public android.hardware.Camera.Size getPreviewSize();
+    method public java.lang.String getSceneMode();
+    method public java.util.List<java.lang.String> getSupportedAntibanding();
+    method public java.util.List<java.lang.String> getSupportedColorEffects();
+    method public java.util.List<java.lang.String> getSupportedFlashModes();
+    method public java.util.List<java.lang.String> getSupportedFocusModes();
+    method public java.util.List<android.hardware.Camera.Size> getSupportedJpegThumbnailSizes();
+    method public java.util.List<java.lang.Integer> getSupportedPictureFormats();
+    method public java.util.List<android.hardware.Camera.Size> getSupportedPictureSizes();
+    method public java.util.List<java.lang.Integer> getSupportedPreviewFormats();
+    method public java.util.List<int[]> getSupportedPreviewFpsRange();
+    method public deprecated java.util.List<java.lang.Integer> getSupportedPreviewFrameRates();
+    method public java.util.List<android.hardware.Camera.Size> getSupportedPreviewSizes();
+    method public java.util.List<java.lang.String> getSupportedSceneModes();
+    method public java.util.List<android.hardware.Camera.Size> getSupportedVideoSizes();
+    method public java.util.List<java.lang.String> getSupportedWhiteBalance();
+    method public float getVerticalViewAngle();
+    method public boolean getVideoStabilization();
+    method public java.lang.String getWhiteBalance();
+    method public int getZoom();
+    method public java.util.List<java.lang.Integer> getZoomRatios();
+    method public boolean isAutoExposureLockSupported();
+    method public boolean isAutoWhiteBalanceLockSupported();
+    method public boolean isSmoothZoomSupported();
+    method public boolean isVideoSnapshotSupported();
+    method public boolean isVideoStabilizationSupported();
+    method public boolean isZoomSupported();
+    method public void remove(java.lang.String);
+    method public void removeGpsData();
+    method public void set(java.lang.String, java.lang.String);
+    method public void set(java.lang.String, int);
+    method public void setAntibanding(java.lang.String);
+    method public void setAutoExposureLock(boolean);
+    method public void setAutoWhiteBalanceLock(boolean);
+    method public void setColorEffect(java.lang.String);
+    method public void setExposureCompensation(int);
+    method public void setFlashMode(java.lang.String);
+    method public void setFocusAreas(java.util.List<android.hardware.Camera.Area>);
+    method public void setFocusMode(java.lang.String);
+    method public void setGpsAltitude(double);
+    method public void setGpsLatitude(double);
+    method public void setGpsLongitude(double);
+    method public void setGpsProcessingMethod(java.lang.String);
+    method public void setGpsTimestamp(long);
+    method public void setJpegQuality(int);
+    method public void setJpegThumbnailQuality(int);
+    method public void setJpegThumbnailSize(int, int);
+    method public void setMeteringAreas(java.util.List<android.hardware.Camera.Area>);
+    method public void setPictureFormat(int);
+    method public void setPictureSize(int, int);
+    method public void setPreviewFormat(int);
+    method public void setPreviewFpsRange(int, int);
+    method public deprecated void setPreviewFrameRate(int);
+    method public void setPreviewSize(int, int);
+    method public void setRecordingHint(boolean);
+    method public void setRotation(int);
+    method public void setSceneMode(java.lang.String);
+    method public void setVideoStabilization(boolean);
+    method public void setWhiteBalance(java.lang.String);
+    method public void setZoom(int);
+    method public void unflatten(java.lang.String);
+    field public static final java.lang.String ANTIBANDING_50HZ = "50hz";
+    field public static final java.lang.String ANTIBANDING_60HZ = "60hz";
+    field public static final java.lang.String ANTIBANDING_AUTO = "auto";
+    field public static final java.lang.String ANTIBANDING_OFF = "off";
+    field public static final java.lang.String EFFECT_AQUA = "aqua";
+    field public static final java.lang.String EFFECT_BLACKBOARD = "blackboard";
+    field public static final java.lang.String EFFECT_MONO = "mono";
+    field public static final java.lang.String EFFECT_NEGATIVE = "negative";
+    field public static final java.lang.String EFFECT_NONE = "none";
+    field public static final java.lang.String EFFECT_POSTERIZE = "posterize";
+    field public static final java.lang.String EFFECT_SEPIA = "sepia";
+    field public static final java.lang.String EFFECT_SOLARIZE = "solarize";
+    field public static final java.lang.String EFFECT_WHITEBOARD = "whiteboard";
+    field public static final java.lang.String FLASH_MODE_AUTO = "auto";
+    field public static final java.lang.String FLASH_MODE_OFF = "off";
+    field public static final java.lang.String FLASH_MODE_ON = "on";
+    field public static final java.lang.String FLASH_MODE_RED_EYE = "red-eye";
+    field public static final java.lang.String FLASH_MODE_TORCH = "torch";
+    field public static final int FOCUS_DISTANCE_FAR_INDEX = 2; // 0x2
+    field public static final int FOCUS_DISTANCE_NEAR_INDEX = 0; // 0x0
+    field public static final int FOCUS_DISTANCE_OPTIMAL_INDEX = 1; // 0x1
+    field public static final java.lang.String FOCUS_MODE_AUTO = "auto";
+    field public static final java.lang.String FOCUS_MODE_CONTINUOUS_PICTURE = "continuous-picture";
+    field public static final java.lang.String FOCUS_MODE_CONTINUOUS_VIDEO = "continuous-video";
+    field public static final java.lang.String FOCUS_MODE_EDOF = "edof";
+    field public static final java.lang.String FOCUS_MODE_FIXED = "fixed";
+    field public static final java.lang.String FOCUS_MODE_INFINITY = "infinity";
+    field public static final java.lang.String FOCUS_MODE_MACRO = "macro";
+    field public static final int PREVIEW_FPS_MAX_INDEX = 1; // 0x1
+    field public static final int PREVIEW_FPS_MIN_INDEX = 0; // 0x0
+    field public static final java.lang.String SCENE_MODE_ACTION = "action";
+    field public static final java.lang.String SCENE_MODE_AUTO = "auto";
+    field public static final java.lang.String SCENE_MODE_BARCODE = "barcode";
+    field public static final java.lang.String SCENE_MODE_BEACH = "beach";
+    field public static final java.lang.String SCENE_MODE_CANDLELIGHT = "candlelight";
+    field public static final java.lang.String SCENE_MODE_FIREWORKS = "fireworks";
+    field public static final java.lang.String SCENE_MODE_HDR = "hdr";
+    field public static final java.lang.String SCENE_MODE_LANDSCAPE = "landscape";
+    field public static final java.lang.String SCENE_MODE_NIGHT = "night";
+    field public static final java.lang.String SCENE_MODE_NIGHT_PORTRAIT = "night-portrait";
+    field public static final java.lang.String SCENE_MODE_PARTY = "party";
+    field public static final java.lang.String SCENE_MODE_PORTRAIT = "portrait";
+    field public static final java.lang.String SCENE_MODE_SNOW = "snow";
+    field public static final java.lang.String SCENE_MODE_SPORTS = "sports";
+    field public static final java.lang.String SCENE_MODE_STEADYPHOTO = "steadyphoto";
+    field public static final java.lang.String SCENE_MODE_SUNSET = "sunset";
+    field public static final java.lang.String SCENE_MODE_THEATRE = "theatre";
+    field public static final java.lang.String WHITE_BALANCE_AUTO = "auto";
+    field public static final java.lang.String WHITE_BALANCE_CLOUDY_DAYLIGHT = "cloudy-daylight";
+    field public static final java.lang.String WHITE_BALANCE_DAYLIGHT = "daylight";
+    field public static final java.lang.String WHITE_BALANCE_FLUORESCENT = "fluorescent";
+    field public static final java.lang.String WHITE_BALANCE_INCANDESCENT = "incandescent";
+    field public static final java.lang.String WHITE_BALANCE_SHADE = "shade";
+    field public static final java.lang.String WHITE_BALANCE_TWILIGHT = "twilight";
+    field public static final java.lang.String WHITE_BALANCE_WARM_FLUORESCENT = "warm-fluorescent";
+  }
+
+  public static abstract interface Camera.PictureCallback {
+    method public abstract void onPictureTaken(byte[], android.hardware.Camera);
+  }
+
+  public static abstract interface Camera.PreviewCallback {
+    method public abstract void onPreviewFrame(byte[], android.hardware.Camera);
+  }
+
+  public static abstract interface Camera.ShutterCallback {
+    method public abstract void onShutter();
+  }
+
+  public class Camera.Size {
+    ctor public Camera.Size(int, int);
+    field public int height;
+    field public int width;
+  }
+
+  public class GeomagneticField {
+    ctor public GeomagneticField(float, float, float, long);
+    method public float getDeclination();
+    method public float getFieldStrength();
+    method public float getHorizontalStrength();
+    method public float getInclination();
+    method public float getX();
+    method public float getY();
+    method public float getZ();
+  }
+
+  public final class Sensor {
+    method public float getMaximumRange();
+    method public int getMinDelay();
+    method public java.lang.String getName();
+    method public float getPower();
+    method public float getResolution();
+    method public int getType();
+    method public java.lang.String getVendor();
+    method public int getVersion();
+    field public static final int TYPE_ACCELEROMETER = 1; // 0x1
+    field public static final int TYPE_ALL = -1; // 0xffffffff
+    field public static final int TYPE_AMBIENT_TEMPERATURE = 13; // 0xd
+    field public static final int TYPE_GRAVITY = 9; // 0x9
+    field public static final int TYPE_GYROSCOPE = 4; // 0x4
+    field public static final int TYPE_LIGHT = 5; // 0x5
+    field public static final int TYPE_LINEAR_ACCELERATION = 10; // 0xa
+    field public static final int TYPE_MAGNETIC_FIELD = 2; // 0x2
+    field public static final deprecated int TYPE_ORIENTATION = 3; // 0x3
+    field public static final int TYPE_PRESSURE = 6; // 0x6
+    field public static final int TYPE_PROXIMITY = 8; // 0x8
+    field public static final int TYPE_RELATIVE_HUMIDITY = 12; // 0xc
+    field public static final int TYPE_ROTATION_VECTOR = 11; // 0xb
+    field public static final deprecated int TYPE_TEMPERATURE = 7; // 0x7
+  }
+
+  public class SensorEvent {
+    field public int accuracy;
+    field public android.hardware.Sensor sensor;
+    field public long timestamp;
+    field public final float[] values;
+  }
+
+  public abstract interface SensorEventListener {
+    method public abstract void onAccuracyChanged(android.hardware.Sensor, int);
+    method public abstract void onSensorChanged(android.hardware.SensorEvent);
+  }
+
+  public abstract deprecated interface SensorListener {
+    method public abstract void onAccuracyChanged(int, int);
+    method public abstract void onSensorChanged(int, float[]);
+  }
+
+  public abstract class SensorManager {
+    method public static float getAltitude(float, float);
+    method public static void getAngleChange(float[], float[], float[]);
+    method public android.hardware.Sensor getDefaultSensor(int);
+    method public static float getInclination(float[]);
+    method public static float[] getOrientation(float[], float[]);
+    method public static void getQuaternionFromVector(float[], float[]);
+    method public static boolean getRotationMatrix(float[], float[], float[], float[]);
+    method public static void getRotationMatrixFromVector(float[], float[]);
+    method public java.util.List<android.hardware.Sensor> getSensorList(int);
+    method public deprecated int getSensors();
+    method public deprecated boolean registerListener(android.hardware.SensorListener, int);
+    method public deprecated boolean registerListener(android.hardware.SensorListener, int, int);
+    method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int);
+    method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, android.os.Handler);
+    method public static boolean remapCoordinateSystem(float[], int, int, float[]);
+    method public deprecated void unregisterListener(android.hardware.SensorListener);
+    method public deprecated void unregisterListener(android.hardware.SensorListener, int);
+    method public void unregisterListener(android.hardware.SensorEventListener, android.hardware.Sensor);
+    method public void unregisterListener(android.hardware.SensorEventListener);
+    field public static final int AXIS_MINUS_X = 129; // 0x81
+    field public static final int AXIS_MINUS_Y = 130; // 0x82
+    field public static final int AXIS_MINUS_Z = 131; // 0x83
+    field public static final int AXIS_X = 1; // 0x1
+    field public static final int AXIS_Y = 2; // 0x2
+    field public static final int AXIS_Z = 3; // 0x3
+    field public static final deprecated int DATA_X = 0; // 0x0
+    field public static final deprecated int DATA_Y = 1; // 0x1
+    field public static final deprecated int DATA_Z = 2; // 0x2
+    field public static final float GRAVITY_DEATH_STAR_I = 3.5303614E-7f;
+    field public static final float GRAVITY_EARTH = 9.80665f;
+    field public static final float GRAVITY_JUPITER = 23.12f;
+    field public static final float GRAVITY_MARS = 3.71f;
+    field public static final float GRAVITY_MERCURY = 3.7f;
+    field public static final float GRAVITY_MOON = 1.6f;
+    field public static final float GRAVITY_NEPTUNE = 11.0f;
+    field public static final float GRAVITY_PLUTO = 0.6f;
+    field public static final float GRAVITY_SATURN = 8.96f;
+    field public static final float GRAVITY_SUN = 275.0f;
+    field public static final float GRAVITY_THE_ISLAND = 4.815162f;
+    field public static final float GRAVITY_URANUS = 8.69f;
+    field public static final float GRAVITY_VENUS = 8.87f;
+    field public static final float LIGHT_CLOUDY = 100.0f;
+    field public static final float LIGHT_FULLMOON = 0.25f;
+    field public static final float LIGHT_NO_MOON = 0.001f;
+    field public static final float LIGHT_OVERCAST = 10000.0f;
+    field public static final float LIGHT_SHADE = 20000.0f;
+    field public static final float LIGHT_SUNLIGHT = 110000.0f;
+    field public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
+    field public static final float LIGHT_SUNRISE = 400.0f;
+    field public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f;
+    field public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f;
+    field public static final float PRESSURE_STANDARD_ATMOSPHERE = 1013.25f;
+    field public static final deprecated int RAW_DATA_INDEX = 3; // 0x3
+    field public static final deprecated int RAW_DATA_X = 3; // 0x3
+    field public static final deprecated int RAW_DATA_Y = 4; // 0x4
+    field public static final deprecated int RAW_DATA_Z = 5; // 0x5
+    field public static final deprecated int SENSOR_ACCELEROMETER = 2; // 0x2
+    field public static final deprecated int SENSOR_ALL = 127; // 0x7f
+    field public static final int SENSOR_DELAY_FASTEST = 0; // 0x0
+    field public static final int SENSOR_DELAY_GAME = 1; // 0x1
+    field public static final int SENSOR_DELAY_NORMAL = 3; // 0x3
+    field public static final int SENSOR_DELAY_UI = 2; // 0x2
+    field public static final deprecated int SENSOR_LIGHT = 16; // 0x10
+    field public static final deprecated int SENSOR_MAGNETIC_FIELD = 8; // 0x8
+    field public static final deprecated int SENSOR_MAX = 64; // 0x40
+    field public static final deprecated int SENSOR_MIN = 1; // 0x1
+    field public static final deprecated int SENSOR_ORIENTATION = 1; // 0x1
+    field public static final deprecated int SENSOR_ORIENTATION_RAW = 128; // 0x80
+    field public static final deprecated int SENSOR_PROXIMITY = 32; // 0x20
+    field public static final int SENSOR_STATUS_ACCURACY_HIGH = 3; // 0x3
+    field public static final int SENSOR_STATUS_ACCURACY_LOW = 1; // 0x1
+    field public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2; // 0x2
+    field public static final int SENSOR_STATUS_UNRELIABLE = 0; // 0x0
+    field public static final deprecated int SENSOR_TEMPERATURE = 4; // 0x4
+    field public static final deprecated int SENSOR_TRICORDER = 64; // 0x40
+    field public static final float STANDARD_GRAVITY = 9.80665f;
+  }
+
+}
+
+package android.hardware.display {
+
+  public final class DisplayManager {
+    method public android.view.Display getDisplay(int);
+    method public android.view.Display[] getDisplays();
+    method public android.view.Display[] getDisplays(java.lang.String);
+    method public void registerDisplayListener(android.hardware.display.DisplayManager.DisplayListener, android.os.Handler);
+    method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
+    field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
+  }
+
+  public static abstract interface DisplayManager.DisplayListener {
+    method public abstract void onDisplayAdded(int);
+    method public abstract void onDisplayChanged(int);
+    method public abstract void onDisplayRemoved(int);
+  }
+
+}
+
+package android.hardware.input {
+
+  public final class InputManager {
+    method public android.view.InputDevice getInputDevice(int);
+    method public int[] getInputDeviceIds();
+    method public void registerInputDeviceListener(android.hardware.input.InputManager.InputDeviceListener, android.os.Handler);
+    method public void unregisterInputDeviceListener(android.hardware.input.InputManager.InputDeviceListener);
+    field public static final java.lang.String ACTION_QUERY_KEYBOARD_LAYOUTS = "android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS";
+    field public static final java.lang.String META_DATA_KEYBOARD_LAYOUTS = "android.hardware.input.metadata.KEYBOARD_LAYOUTS";
+  }
+
+  public static abstract interface InputManager.InputDeviceListener {
+    method public abstract void onInputDeviceAdded(int);
+    method public abstract void onInputDeviceChanged(int);
+    method public abstract void onInputDeviceRemoved(int);
+  }
+
+}
+
+package android.hardware.usb {
+
+  public class UsbAccessory implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.String getDescription();
+    method public java.lang.String getManufacturer();
+    method public java.lang.String getModel();
+    method public java.lang.String getSerial();
+    method public java.lang.String getUri();
+    method public java.lang.String getVersion();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class UsbConstants {
+    ctor public UsbConstants();
+    field public static final int USB_CLASS_APP_SPEC = 254; // 0xfe
+    field public static final int USB_CLASS_AUDIO = 1; // 0x1
+    field public static final int USB_CLASS_CDC_DATA = 10; // 0xa
+    field public static final int USB_CLASS_COMM = 2; // 0x2
+    field public static final int USB_CLASS_CONTENT_SEC = 13; // 0xd
+    field public static final int USB_CLASS_CSCID = 11; // 0xb
+    field public static final int USB_CLASS_HID = 3; // 0x3
+    field public static final int USB_CLASS_HUB = 9; // 0x9
+    field public static final int USB_CLASS_MASS_STORAGE = 8; // 0x8
+    field public static final int USB_CLASS_MISC = 239; // 0xef
+    field public static final int USB_CLASS_PER_INTERFACE = 0; // 0x0
+    field public static final int USB_CLASS_PHYSICA = 5; // 0x5
+    field public static final int USB_CLASS_PRINTER = 7; // 0x7
+    field public static final int USB_CLASS_STILL_IMAGE = 6; // 0x6
+    field public static final int USB_CLASS_VENDOR_SPEC = 255; // 0xff
+    field public static final int USB_CLASS_VIDEO = 14; // 0xe
+    field public static final int USB_CLASS_WIRELESS_CONTROLLER = 224; // 0xe0
+    field public static final int USB_DIR_IN = 128; // 0x80
+    field public static final int USB_DIR_OUT = 0; // 0x0
+    field public static final int USB_ENDPOINT_DIR_MASK = 128; // 0x80
+    field public static final int USB_ENDPOINT_NUMBER_MASK = 15; // 0xf
+    field public static final int USB_ENDPOINT_XFERTYPE_MASK = 3; // 0x3
+    field public static final int USB_ENDPOINT_XFER_BULK = 2; // 0x2
+    field public static final int USB_ENDPOINT_XFER_CONTROL = 0; // 0x0
+    field public static final int USB_ENDPOINT_XFER_INT = 3; // 0x3
+    field public static final int USB_ENDPOINT_XFER_ISOC = 1; // 0x1
+    field public static final int USB_INTERFACE_SUBCLASS_BOOT = 1; // 0x1
+    field public static final int USB_SUBCLASS_VENDOR_SPEC = 255; // 0xff
+    field public static final int USB_TYPE_CLASS = 32; // 0x20
+    field public static final int USB_TYPE_MASK = 96; // 0x60
+    field public static final int USB_TYPE_RESERVED = 96; // 0x60
+    field public static final int USB_TYPE_STANDARD = 0; // 0x0
+    field public static final int USB_TYPE_VENDOR = 64; // 0x40
+  }
+
+  public class UsbDevice implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getDeviceClass();
+    method public int getDeviceId();
+    method public static int getDeviceId(java.lang.String);
+    method public java.lang.String getDeviceName();
+    method public static java.lang.String getDeviceName(int);
+    method public int getDeviceProtocol();
+    method public int getDeviceSubclass();
+    method public android.hardware.usb.UsbInterface getInterface(int);
+    method public int getInterfaceCount();
+    method public int getProductId();
+    method public int getVendorId();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class UsbDeviceConnection {
+    method public int bulkTransfer(android.hardware.usb.UsbEndpoint, byte[], int, int);
+    method public boolean claimInterface(android.hardware.usb.UsbInterface, boolean);
+    method public void close();
+    method public int controlTransfer(int, int, int, int, byte[], int, int);
+    method public int getFileDescriptor();
+    method public byte[] getRawDescriptors();
+    method public java.lang.String getSerial();
+    method public boolean releaseInterface(android.hardware.usb.UsbInterface);
+    method public android.hardware.usb.UsbRequest requestWait();
+  }
+
+  public class UsbEndpoint implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getAddress();
+    method public int getAttributes();
+    method public int getDirection();
+    method public int getEndpointNumber();
+    method public int getInterval();
+    method public int getMaxPacketSize();
+    method public int getType();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class UsbInterface implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.hardware.usb.UsbEndpoint getEndpoint(int);
+    method public int getEndpointCount();
+    method public int getId();
+    method public int getInterfaceClass();
+    method public int getInterfaceProtocol();
+    method public int getInterfaceSubclass();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class UsbManager {
+    method public android.hardware.usb.UsbAccessory[] getAccessoryList();
+    method public java.util.HashMap<java.lang.String, android.hardware.usb.UsbDevice> getDeviceList();
+    method public boolean hasPermission(android.hardware.usb.UsbDevice);
+    method public boolean hasPermission(android.hardware.usb.UsbAccessory);
+    method public android.os.ParcelFileDescriptor openAccessory(android.hardware.usb.UsbAccessory);
+    method public android.hardware.usb.UsbDeviceConnection openDevice(android.hardware.usb.UsbDevice);
+    method public void requestPermission(android.hardware.usb.UsbDevice, android.app.PendingIntent);
+    method public void requestPermission(android.hardware.usb.UsbAccessory, android.app.PendingIntent);
+    field public static final java.lang.String ACTION_USB_ACCESSORY_ATTACHED = "android.hardware.usb.action.USB_ACCESSORY_ATTACHED";
+    field public static final java.lang.String ACTION_USB_ACCESSORY_DETACHED = "android.hardware.usb.action.USB_ACCESSORY_DETACHED";
+    field public static final java.lang.String ACTION_USB_DEVICE_ATTACHED = "android.hardware.usb.action.USB_DEVICE_ATTACHED";
+    field public static final java.lang.String ACTION_USB_DEVICE_DETACHED = "android.hardware.usb.action.USB_DEVICE_DETACHED";
+    field public static final java.lang.String EXTRA_ACCESSORY = "accessory";
+    field public static final java.lang.String EXTRA_DEVICE = "device";
+    field public static final java.lang.String EXTRA_PERMISSION_GRANTED = "permission";
+  }
+
+  public class UsbRequest {
+    ctor public UsbRequest();
+    method public boolean cancel();
+    method public void close();
+    method public java.lang.Object getClientData();
+    method public android.hardware.usb.UsbEndpoint getEndpoint();
+    method public boolean initialize(android.hardware.usb.UsbDeviceConnection, android.hardware.usb.UsbEndpoint);
+    method public boolean queue(java.nio.ByteBuffer, int);
+    method public void setClientData(java.lang.Object);
+  }
+
+}
+
+package android.inputmethodservice {
+
+  public abstract class AbstractInputMethodService extends android.app.Service implements android.view.KeyEvent.Callback {
+    ctor public AbstractInputMethodService();
+    method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public abstract android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodImpl onCreateInputMethodInterface();
+    method public abstract android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface();
+    method public boolean onGenericMotionEvent(android.view.MotionEvent);
+    method public boolean onTrackballEvent(android.view.MotionEvent);
+  }
+
+  public abstract class AbstractInputMethodService.AbstractInputMethodImpl implements android.view.inputmethod.InputMethod {
+    ctor public AbstractInputMethodService.AbstractInputMethodImpl();
+    method public void createSession(android.view.inputmethod.InputMethod.SessionCallback);
+    method public void revokeSession(android.view.inputmethod.InputMethodSession);
+    method public void setSessionEnabled(android.view.inputmethod.InputMethodSession, boolean);
+  }
+
+  public abstract class AbstractInputMethodService.AbstractInputMethodSessionImpl implements android.view.inputmethod.InputMethodSession {
+    ctor public AbstractInputMethodService.AbstractInputMethodSessionImpl();
+    method public void dispatchGenericMotionEvent(int, android.view.MotionEvent, android.view.inputmethod.InputMethodSession.EventCallback);
+    method public void dispatchKeyEvent(int, android.view.KeyEvent, android.view.inputmethod.InputMethodSession.EventCallback);
+    method public void dispatchTrackballEvent(int, android.view.MotionEvent, android.view.inputmethod.InputMethodSession.EventCallback);
+    method public boolean isEnabled();
+    method public boolean isRevoked();
+    method public void revokeSelf();
+    method public void setEnabled(boolean);
+  }
+
+  public class ExtractEditText extends android.widget.EditText {
+    ctor public ExtractEditText(android.content.Context);
+    ctor public ExtractEditText(android.content.Context, android.util.AttributeSet);
+    ctor public ExtractEditText(android.content.Context, android.util.AttributeSet, int);
+    method public void finishInternalChanges();
+    method public boolean hasVerticalScrollBar();
+    method public void startInternalChanges();
+  }
+
+  public class InputMethodService extends android.inputmethodservice.AbstractInputMethodService {
+    ctor public InputMethodService();
+    method public boolean enableHardwareAcceleration();
+    method public int getBackDisposition();
+    method public int getCandidatesHiddenVisibility();
+    method public android.view.inputmethod.InputBinding getCurrentInputBinding();
+    method public android.view.inputmethod.InputConnection getCurrentInputConnection();
+    method public android.view.inputmethod.EditorInfo getCurrentInputEditorInfo();
+    method public boolean getCurrentInputStarted();
+    method public android.view.LayoutInflater getLayoutInflater();
+    method public int getMaxWidth();
+    method public java.lang.CharSequence getTextForImeAction(int);
+    method public android.app.Dialog getWindow();
+    method public void hideStatusIcon();
+    method public void hideWindow();
+    method public boolean isExtractViewShown();
+    method public boolean isFullscreenMode();
+    method public boolean isInputViewShown();
+    method public boolean isShowInputRequested();
+    method public void onAppPrivateCommand(java.lang.String, android.os.Bundle);
+    method public void onBindInput();
+    method public void onComputeInsets(android.inputmethodservice.InputMethodService.Insets);
+    method public void onConfigureWindow(android.view.Window, boolean, boolean);
+    method public android.view.View onCreateCandidatesView();
+    method public android.view.View onCreateExtractTextView();
+    method public android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodImpl onCreateInputMethodInterface();
+    method public android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface();
+    method public android.view.View onCreateInputView();
+    method protected void onCurrentInputMethodSubtypeChanged(android.view.inputmethod.InputMethodSubtype);
+    method public void onDisplayCompletions(android.view.inputmethod.CompletionInfo[]);
+    method public boolean onEvaluateFullscreenMode();
+    method public boolean onEvaluateInputViewShown();
+    method public boolean onExtractTextContextMenuItem(int);
+    method public void onExtractedCursorMovement(int, int);
+    method public void onExtractedSelectionChanged(int, int);
+    method public void onExtractedTextClicked();
+    method public void onExtractingInputChanged(android.view.inputmethod.EditorInfo);
+    method public void onFinishCandidatesView(boolean);
+    method public void onFinishInput();
+    method public void onFinishInputView(boolean);
+    method public void onInitializeInterface();
+    method public boolean onKeyDown(int, android.view.KeyEvent);
+    method public boolean onKeyLongPress(int, android.view.KeyEvent);
+    method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
+    method public boolean onKeyUp(int, android.view.KeyEvent);
+    method public boolean onShowInputRequested(int, boolean);
+    method public void onStartCandidatesView(android.view.inputmethod.EditorInfo, boolean);
+    method public void onStartInput(android.view.inputmethod.EditorInfo, boolean);
+    method public void onStartInputView(android.view.inputmethod.EditorInfo, boolean);
+    method public void onUnbindInput();
+    method public void onUpdateCursor(android.graphics.Rect);
+    method public void onUpdateExtractedText(int, android.view.inputmethod.ExtractedText);
+    method public void onUpdateExtractingViews(android.view.inputmethod.EditorInfo);
+    method public void onUpdateExtractingVisibility(android.view.inputmethod.EditorInfo);
+    method public void onUpdateSelection(int, int, int, int, int, int);
+    method public void onViewClicked(boolean);
+    method public void onWindowHidden();
+    method public void onWindowShown();
+    method public void requestHideSelf(int);
+    method public boolean sendDefaultEditorAction(boolean);
+    method public void sendDownUpKeyEvents(int);
+    method public void sendKeyChar(char);
+    method public void setBackDisposition(int);
+    method public void setCandidatesView(android.view.View);
+    method public void setCandidatesViewShown(boolean);
+    method public void setExtractView(android.view.View);
+    method public void setExtractViewShown(boolean);
+    method public void setInputView(android.view.View);
+    method public void showStatusIcon(int);
+    method public void showWindow(boolean);
+    method public void switchInputMethod(java.lang.String);
+    method public void updateFullscreenMode();
+    method public void updateInputViewShown();
+    field public static final int BACK_DISPOSITION_DEFAULT = 0; // 0x0
+    field public static final int BACK_DISPOSITION_WILL_DISMISS = 2; // 0x2
+    field public static final int BACK_DISPOSITION_WILL_NOT_DISMISS = 1; // 0x1
+  }
+
+  public class InputMethodService.InputMethodImpl extends android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodImpl {
+    ctor public InputMethodService.InputMethodImpl();
+    method public void attachToken(android.os.IBinder);
+    method public void bindInput(android.view.inputmethod.InputBinding);
+    method public void changeInputMethodSubtype(android.view.inputmethod.InputMethodSubtype);
+    method public void hideSoftInput(int, android.os.ResultReceiver);
+    method public void restartInput(android.view.inputmethod.InputConnection, android.view.inputmethod.EditorInfo);
+    method public void showSoftInput(int, android.os.ResultReceiver);
+    method public void startInput(android.view.inputmethod.InputConnection, android.view.inputmethod.EditorInfo);
+    method public void unbindInput();
+  }
+
+  public class InputMethodService.InputMethodSessionImpl extends android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodSessionImpl {
+    ctor public InputMethodService.InputMethodSessionImpl();
+    method public void appPrivateCommand(java.lang.String, android.os.Bundle);
+    method public void displayCompletions(android.view.inputmethod.CompletionInfo[]);
+    method public void finishInput();
+    method public void toggleSoftInput(int, int);
+    method public void updateCursor(android.graphics.Rect);
+    method public void updateExtractedText(int, android.view.inputmethod.ExtractedText);
+    method public void updateSelection(int, int, int, int, int, int);
+    method public void viewClicked(boolean);
+  }
+
+  public static final class InputMethodService.Insets {
+    ctor public InputMethodService.Insets();
+    field public static final int TOUCHABLE_INSETS_CONTENT = 1; // 0x1
+    field public static final int TOUCHABLE_INSETS_FRAME = 0; // 0x0
+    field public static final int TOUCHABLE_INSETS_REGION = 3; // 0x3
+    field public static final int TOUCHABLE_INSETS_VISIBLE = 2; // 0x2
+    field public int contentTopInsets;
+    field public int touchableInsets;
+    field public final android.graphics.Region touchableRegion;
+    field public int visibleTopInsets;
+  }
+
+  public class Keyboard {
+    ctor public Keyboard(android.content.Context, int);
+    ctor public Keyboard(android.content.Context, int, int, int, int);
+    ctor public Keyboard(android.content.Context, int, int);
+    ctor public Keyboard(android.content.Context, int, java.lang.CharSequence, int, int);
+    method protected android.inputmethodservice.Keyboard.Key createKeyFromXml(android.content.res.Resources, android.inputmethodservice.Keyboard.Row, int, int, android.content.res.XmlResourceParser);
+    method protected android.inputmethodservice.Keyboard.Row createRowFromXml(android.content.res.Resources, android.content.res.XmlResourceParser);
+    method public int getHeight();
+    method protected int getHorizontalGap();
+    method protected int getKeyHeight();
+    method protected int getKeyWidth();
+    method public java.util.List<android.inputmethodservice.Keyboard.Key> getKeys();
+    method public int getMinWidth();
+    method public java.util.List<android.inputmethodservice.Keyboard.Key> getModifierKeys();
+    method public int[] getNearestKeys(int, int);
+    method public int getShiftKeyIndex();
+    method protected int getVerticalGap();
+    method public boolean isShifted();
+    method protected void setHorizontalGap(int);
+    method protected void setKeyHeight(int);
+    method protected void setKeyWidth(int);
+    method public boolean setShifted(boolean);
+    method protected void setVerticalGap(int);
+    field public static final int EDGE_BOTTOM = 8; // 0x8
+    field public static final int EDGE_LEFT = 1; // 0x1
+    field public static final int EDGE_RIGHT = 2; // 0x2
+    field public static final int EDGE_TOP = 4; // 0x4
+    field public static final int KEYCODE_ALT = -6; // 0xfffffffa
+    field public static final int KEYCODE_CANCEL = -3; // 0xfffffffd
+    field public static final int KEYCODE_DELETE = -5; // 0xfffffffb
+    field public static final int KEYCODE_DONE = -4; // 0xfffffffc
+    field public static final int KEYCODE_MODE_CHANGE = -2; // 0xfffffffe
+    field public static final int KEYCODE_SHIFT = -1; // 0xffffffff
+  }
+
+  public static class Keyboard.Key {
+    ctor public Keyboard.Key(android.inputmethodservice.Keyboard.Row);
+    ctor public Keyboard.Key(android.content.res.Resources, android.inputmethodservice.Keyboard.Row, int, int, android.content.res.XmlResourceParser);
+    method public int[] getCurrentDrawableState();
+    method public boolean isInside(int, int);
+    method public void onPressed();
+    method public void onReleased(boolean);
+    method public int squaredDistanceFrom(int, int);
+    field public int[] codes;
+    field public int edgeFlags;
+    field public int gap;
+    field public int height;
+    field public android.graphics.drawable.Drawable icon;
+    field public android.graphics.drawable.Drawable iconPreview;
+    field public java.lang.CharSequence label;
+    field public boolean modifier;
+    field public boolean on;
+    field public java.lang.CharSequence popupCharacters;
+    field public int popupResId;
+    field public boolean pressed;
+    field public boolean repeatable;
+    field public boolean sticky;
+    field public java.lang.CharSequence text;
+    field public int width;
+    field public int x;
+    field public int y;
+  }
+
+  public static class Keyboard.Row {
+    ctor public Keyboard.Row(android.inputmethodservice.Keyboard);
+    ctor public Keyboard.Row(android.content.res.Resources, android.inputmethodservice.Keyboard, android.content.res.XmlResourceParser);
+    field public int defaultHeight;
+    field public int defaultHorizontalGap;
+    field public int defaultWidth;
+    field public int mode;
+    field public int rowEdgeFlags;
+    field public int verticalGap;
+  }
+
+  public class KeyboardView extends android.view.View implements android.view.View.OnClickListener {
+    ctor public KeyboardView(android.content.Context, android.util.AttributeSet);
+    ctor public KeyboardView(android.content.Context, android.util.AttributeSet, int);
+    method public void closing();
+    method public android.inputmethodservice.Keyboard getKeyboard();
+    method protected android.inputmethodservice.KeyboardView.OnKeyboardActionListener getOnKeyboardActionListener();
+    method public boolean handleBack();
+    method public void invalidateAllKeys();
+    method public void invalidateKey(int);
+    method public boolean isPreviewEnabled();
+    method public boolean isProximityCorrectionEnabled();
+    method public boolean isShifted();
+    method public void onClick(android.view.View);
+    method public void onDetachedFromWindow();
+    method public void onDraw(android.graphics.Canvas);
+    method protected boolean onLongPress(android.inputmethodservice.Keyboard.Key);
+    method public void onMeasure(int, int);
+    method public void onSizeChanged(int, int, int, int);
+    method public void setKeyboard(android.inputmethodservice.Keyboard);
+    method public void setOnKeyboardActionListener(android.inputmethodservice.KeyboardView.OnKeyboardActionListener);
+    method public void setPopupOffset(int, int);
+    method public void setPopupParent(android.view.View);
+    method public void setPreviewEnabled(boolean);
+    method public void setProximityCorrectionEnabled(boolean);
+    method public boolean setShifted(boolean);
+    method public void setVerticalCorrection(int);
+    method protected void swipeDown();
+    method protected void swipeLeft();
+    method protected void swipeRight();
+    method protected void swipeUp();
+  }
+
+  public static abstract interface KeyboardView.OnKeyboardActionListener {
+    method public abstract void onKey(int, int[]);
+    method public abstract void onPress(int);
+    method public abstract void onRelease(int);
+    method public abstract void onText(java.lang.CharSequence);
+    method public abstract void swipeDown();
+    method public abstract void swipeLeft();
+    method public abstract void swipeRight();
+    method public abstract void swipeUp();
+  }
+
+}
+
+package android.location {
+
+  public class Address implements android.os.Parcelable {
+    ctor public Address(java.util.Locale);
+    method public void clearLatitude();
+    method public void clearLongitude();
+    method public int describeContents();
+    method public java.lang.String getAddressLine(int);
+    method public java.lang.String getAdminArea();
+    method public java.lang.String getCountryCode();
+    method public java.lang.String getCountryName();
+    method public android.os.Bundle getExtras();
+    method public java.lang.String getFeatureName();
+    method public double getLatitude();
+    method public java.util.Locale getLocale();
+    method public java.lang.String getLocality();
+    method public double getLongitude();
+    method public int getMaxAddressLineIndex();
+    method public java.lang.String getPhone();
+    method public java.lang.String getPostalCode();
+    method public java.lang.String getPremises();
+    method public java.lang.String getSubAdminArea();
+    method public java.lang.String getSubLocality();
+    method public java.lang.String getSubThoroughfare();
+    method public java.lang.String getThoroughfare();
+    method public java.lang.String getUrl();
+    method public boolean hasLatitude();
+    method public boolean hasLongitude();
+    method public void setAddressLine(int, java.lang.String);
+    method public void setAdminArea(java.lang.String);
+    method public void setCountryCode(java.lang.String);
+    method public void setCountryName(java.lang.String);
+    method public void setExtras(android.os.Bundle);
+    method public void setFeatureName(java.lang.String);
+    method public void setLatitude(double);
+    method public void setLocality(java.lang.String);
+    method public void setLongitude(double);
+    method public void setPhone(java.lang.String);
+    method public void setPostalCode(java.lang.String);
+    method public void setPremises(java.lang.String);
+    method public void setSubAdminArea(java.lang.String);
+    method public void setSubLocality(java.lang.String);
+    method public void setSubThoroughfare(java.lang.String);
+    method public void setThoroughfare(java.lang.String);
+    method public void setUrl(java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class Criteria implements android.os.Parcelable {
+    ctor public Criteria();
+    ctor public Criteria(android.location.Criteria);
+    method public int describeContents();
+    method public int getAccuracy();
+    method public int getBearingAccuracy();
+    method public int getHorizontalAccuracy();
+    method public int getPowerRequirement();
+    method public int getSpeedAccuracy();
+    method public int getVerticalAccuracy();
+    method public boolean isAltitudeRequired();
+    method public boolean isBearingRequired();
+    method public boolean isCostAllowed();
+    method public boolean isSpeedRequired();
+    method public void setAccuracy(int);
+    method public void setAltitudeRequired(boolean);
+    method public void setBearingAccuracy(int);
+    method public void setBearingRequired(boolean);
+    method public void setCostAllowed(boolean);
+    method public void setHorizontalAccuracy(int);
+    method public void setPowerRequirement(int);
+    method public void setSpeedAccuracy(int);
+    method public void setSpeedRequired(boolean);
+    method public void setVerticalAccuracy(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ACCURACY_COARSE = 2; // 0x2
+    field public static final int ACCURACY_FINE = 1; // 0x1
+    field public static final int ACCURACY_HIGH = 3; // 0x3
+    field public static final int ACCURACY_LOW = 1; // 0x1
+    field public static final int ACCURACY_MEDIUM = 2; // 0x2
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int NO_REQUIREMENT = 0; // 0x0
+    field public static final int POWER_HIGH = 3; // 0x3
+    field public static final int POWER_LOW = 1; // 0x1
+    field public static final int POWER_MEDIUM = 2; // 0x2
+  }
+
+  public final class Geocoder {
+    ctor public Geocoder(android.content.Context, java.util.Locale);
+    ctor public Geocoder(android.content.Context);
+    method public java.util.List<android.location.Address> getFromLocation(double, double, int) throws java.io.IOException;
+    method public java.util.List<android.location.Address> getFromLocationName(java.lang.String, int) throws java.io.IOException;
+    method public java.util.List<android.location.Address> getFromLocationName(java.lang.String, int, double, double, double, double) throws java.io.IOException;
+    method public static boolean isPresent();
+  }
+
+  public final class GpsSatellite {
+    method public float getAzimuth();
+    method public float getElevation();
+    method public int getPrn();
+    method public float getSnr();
+    method public boolean hasAlmanac();
+    method public boolean hasEphemeris();
+    method public boolean usedInFix();
+  }
+
+  public final class GpsStatus {
+    method public int getMaxSatellites();
+    method public java.lang.Iterable<android.location.GpsSatellite> getSatellites();
+    method public int getTimeToFirstFix();
+    field public static final int GPS_EVENT_FIRST_FIX = 3; // 0x3
+    field public static final int GPS_EVENT_SATELLITE_STATUS = 4; // 0x4
+    field public static final int GPS_EVENT_STARTED = 1; // 0x1
+    field public static final int GPS_EVENT_STOPPED = 2; // 0x2
+  }
+
+  public static abstract interface GpsStatus.Listener {
+    method public abstract void onGpsStatusChanged(int);
+  }
+
+  public static abstract interface GpsStatus.NmeaListener {
+    method public abstract void onNmeaReceived(long, java.lang.String);
+  }
+
+  public class Location implements android.os.Parcelable {
+    ctor public Location(java.lang.String);
+    ctor public Location(android.location.Location);
+    method public float bearingTo(android.location.Location);
+    method public static java.lang.String convert(double, int);
+    method public static double convert(java.lang.String);
+    method public int describeContents();
+    method public static void distanceBetween(double, double, double, double, float[]);
+    method public float distanceTo(android.location.Location);
+    method public void dump(android.util.Printer, java.lang.String);
+    method public float getAccuracy();
+    method public double getAltitude();
+    method public float getBearing();
+    method public long getElapsedRealtimeNanos();
+    method public android.os.Bundle getExtras();
+    method public double getLatitude();
+    method public double getLongitude();
+    method public java.lang.String getProvider();
+    method public float getSpeed();
+    method public long getTime();
+    method public boolean hasAccuracy();
+    method public boolean hasAltitude();
+    method public boolean hasBearing();
+    method public boolean hasSpeed();
+    method public void removeAccuracy();
+    method public void removeAltitude();
+    method public void removeBearing();
+    method public void removeSpeed();
+    method public void reset();
+    method public void set(android.location.Location);
+    method public void setAccuracy(float);
+    method public void setAltitude(double);
+    method public void setBearing(float);
+    method public void setElapsedRealtimeNanos(long);
+    method public void setExtras(android.os.Bundle);
+    method public void setLatitude(double);
+    method public void setLongitude(double);
+    method public void setProvider(java.lang.String);
+    method public void setSpeed(float);
+    method public void setTime(long);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FORMAT_DEGREES = 0; // 0x0
+    field public static final int FORMAT_MINUTES = 1; // 0x1
+    field public static final int FORMAT_SECONDS = 2; // 0x2
+  }
+
+  public abstract interface LocationListener {
+    method public abstract void onLocationChanged(android.location.Location);
+    method public abstract void onProviderDisabled(java.lang.String);
+    method public abstract void onProviderEnabled(java.lang.String);
+    method public abstract void onStatusChanged(java.lang.String, int, android.os.Bundle);
+  }
+
+  public class LocationManager {
+    method public boolean addGpsStatusListener(android.location.GpsStatus.Listener);
+    method public boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
+    method public void addProximityAlert(double, double, float, long, android.app.PendingIntent);
+    method public void addTestProvider(java.lang.String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
+    method public void clearTestProviderEnabled(java.lang.String);
+    method public void clearTestProviderLocation(java.lang.String);
+    method public void clearTestProviderStatus(java.lang.String);
+    method public java.util.List<java.lang.String> getAllProviders();
+    method public java.lang.String getBestProvider(android.location.Criteria, boolean);
+    method public android.location.GpsStatus getGpsStatus(android.location.GpsStatus);
+    method public android.location.Location getLastKnownLocation(java.lang.String);
+    method public android.location.LocationProvider getProvider(java.lang.String);
+    method public java.util.List<java.lang.String> getProviders(boolean);
+    method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
+    method public boolean isProviderEnabled(java.lang.String);
+    method public void removeGpsStatusListener(android.location.GpsStatus.Listener);
+    method public void removeNmeaListener(android.location.GpsStatus.NmeaListener);
+    method public void removeProximityAlert(android.app.PendingIntent);
+    method public void removeTestProvider(java.lang.String);
+    method public void removeUpdates(android.location.LocationListener);
+    method public void removeUpdates(android.app.PendingIntent);
+    method public void requestLocationUpdates(java.lang.String, long, float, android.location.LocationListener);
+    method public void requestLocationUpdates(java.lang.String, long, float, android.location.LocationListener, android.os.Looper);
+    method public void requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper);
+    method public void requestLocationUpdates(java.lang.String, long, float, android.app.PendingIntent);
+    method public void requestLocationUpdates(long, float, android.location.Criteria, android.app.PendingIntent);
+    method public void requestSingleUpdate(java.lang.String, android.location.LocationListener, android.os.Looper);
+    method public void requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper);
+    method public void requestSingleUpdate(java.lang.String, android.app.PendingIntent);
+    method public void requestSingleUpdate(android.location.Criteria, android.app.PendingIntent);
+    method public boolean sendExtraCommand(java.lang.String, java.lang.String, android.os.Bundle);
+    method public void setTestProviderEnabled(java.lang.String, boolean);
+    method public void setTestProviderLocation(java.lang.String, android.location.Location);
+    method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
+    field public static final java.lang.String GPS_PROVIDER = "gps";
+    field public static final java.lang.String KEY_LOCATION_CHANGED = "location";
+    field public static final java.lang.String KEY_PROVIDER_ENABLED = "providerEnabled";
+    field public static final java.lang.String KEY_PROXIMITY_ENTERING = "entering";
+    field public static final java.lang.String KEY_STATUS_CHANGED = "status";
+    field public static final java.lang.String NETWORK_PROVIDER = "network";
+    field public static final java.lang.String PASSIVE_PROVIDER = "passive";
+    field public static final java.lang.String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";
+  }
+
+  public class LocationProvider {
+    method public int getAccuracy();
+    method public java.lang.String getName();
+    method public int getPowerRequirement();
+    method public boolean hasMonetaryCost();
+    method public boolean meetsCriteria(android.location.Criteria);
+    method public boolean requiresCell();
+    method public boolean requiresNetwork();
+    method public boolean requiresSatellite();
+    method public boolean supportsAltitude();
+    method public boolean supportsBearing();
+    method public boolean supportsSpeed();
+    field public static final int AVAILABLE = 2; // 0x2
+    field public static final int OUT_OF_SERVICE = 0; // 0x0
+    field public static final int TEMPORARILY_UNAVAILABLE = 1; // 0x1
+  }
+
+}
+
+package android.media {
+
+  public class AsyncPlayer {
+    ctor public AsyncPlayer(java.lang.String);
+    method public void play(android.content.Context, android.net.Uri, boolean, int);
+    method public void stop();
+  }
+
+  public class AudioFormat {
+    ctor public AudioFormat();
+    field public static final deprecated int CHANNEL_CONFIGURATION_DEFAULT = 1; // 0x1
+    field public static final deprecated int CHANNEL_CONFIGURATION_INVALID = 0; // 0x0
+    field public static final deprecated int CHANNEL_CONFIGURATION_MONO = 2; // 0x2
+    field public static final deprecated int CHANNEL_CONFIGURATION_STEREO = 3; // 0x3
+    field public static final int CHANNEL_INVALID = 0; // 0x0
+    field public static final int CHANNEL_IN_BACK = 32; // 0x20
+    field public static final int CHANNEL_IN_BACK_PROCESSED = 512; // 0x200
+    field public static final int CHANNEL_IN_DEFAULT = 1; // 0x1
+    field public static final int CHANNEL_IN_FRONT = 16; // 0x10
+    field public static final int CHANNEL_IN_FRONT_PROCESSED = 256; // 0x100
+    field public static final int CHANNEL_IN_LEFT = 4; // 0x4
+    field public static final int CHANNEL_IN_LEFT_PROCESSED = 64; // 0x40
+    field public static final int CHANNEL_IN_MONO = 16; // 0x10
+    field public static final int CHANNEL_IN_PRESSURE = 1024; // 0x400
+    field public static final int CHANNEL_IN_RIGHT = 8; // 0x8
+    field public static final int CHANNEL_IN_RIGHT_PROCESSED = 128; // 0x80
+    field public static final int CHANNEL_IN_STEREO = 12; // 0xc
+    field public static final int CHANNEL_IN_VOICE_DNLINK = 32768; // 0x8000
+    field public static final int CHANNEL_IN_VOICE_UPLINK = 16384; // 0x4000
+    field public static final int CHANNEL_IN_X_AXIS = 2048; // 0x800
+    field public static final int CHANNEL_IN_Y_AXIS = 4096; // 0x1000
+    field public static final int CHANNEL_IN_Z_AXIS = 8192; // 0x2000
+    field public static final int CHANNEL_OUT_5POINT1 = 252; // 0xfc
+    field public static final int CHANNEL_OUT_7POINT1 = 1020; // 0x3fc
+    field public static final int CHANNEL_OUT_BACK_CENTER = 1024; // 0x400
+    field public static final int CHANNEL_OUT_BACK_LEFT = 64; // 0x40
+    field public static final int CHANNEL_OUT_BACK_RIGHT = 128; // 0x80
+    field public static final int CHANNEL_OUT_DEFAULT = 1; // 0x1
+    field public static final int CHANNEL_OUT_FRONT_CENTER = 16; // 0x10
+    field public static final int CHANNEL_OUT_FRONT_LEFT = 4; // 0x4
+    field public static final int CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 256; // 0x100
+    field public static final int CHANNEL_OUT_FRONT_RIGHT = 8; // 0x8
+    field public static final int CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 512; // 0x200
+    field public static final int CHANNEL_OUT_LOW_FREQUENCY = 32; // 0x20
+    field public static final int CHANNEL_OUT_MONO = 4; // 0x4
+    field public static final int CHANNEL_OUT_QUAD = 204; // 0xcc
+    field public static final int CHANNEL_OUT_STEREO = 12; // 0xc
+    field public static final int CHANNEL_OUT_SURROUND = 1052; // 0x41c
+    field public static final int ENCODING_DEFAULT = 1; // 0x1
+    field public static final int ENCODING_INVALID = 0; // 0x0
+    field public static final int ENCODING_PCM_16BIT = 2; // 0x2
+    field public static final int ENCODING_PCM_8BIT = 3; // 0x3
+  }
+
+  public class AudioManager {
+    method public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
+    method public void adjustStreamVolume(int, int, int);
+    method public void adjustSuggestedStreamVolume(int, int, int);
+    method public void adjustVolume(int, int);
+    method public int getMode();
+    method public java.lang.String getParameters(java.lang.String);
+    method public java.lang.String getProperty(java.lang.String);
+    method public int getRingerMode();
+    method public deprecated int getRouting(int);
+    method public int getStreamMaxVolume(int);
+    method public int getStreamVolume(int);
+    method public deprecated int getVibrateSetting(int);
+    method public boolean isBluetoothA2dpOn();
+    method public boolean isBluetoothScoAvailableOffCall();
+    method public boolean isBluetoothScoOn();
+    method public boolean isMicrophoneMute();
+    method public boolean isMusicActive();
+    method public boolean isSpeakerphoneOn();
+    method public deprecated boolean isWiredHeadsetOn();
+    method public void loadSoundEffects();
+    method public void playSoundEffect(int);
+    method public void playSoundEffect(int, float);
+    method public void registerMediaButtonEventReceiver(android.content.ComponentName);
+    method public void registerRemoteControlClient(android.media.RemoteControlClient);
+    method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
+    method public deprecated void setBluetoothA2dpOn(boolean);
+    method public void setBluetoothScoOn(boolean);
+    method public void setMicrophoneMute(boolean);
+    method public void setMode(int);
+    method public void setParameters(java.lang.String);
+    method public void setRingerMode(int);
+    method public deprecated void setRouting(int, int, int);
+    method public void setSpeakerphoneOn(boolean);
+    method public void setStreamMute(int, boolean);
+    method public void setStreamSolo(int, boolean);
+    method public void setStreamVolume(int, int, int);
+    method public deprecated void setVibrateSetting(int, int);
+    method public deprecated void setWiredHeadsetOn(boolean);
+    method public deprecated boolean shouldVibrate(int);
+    method public void startBluetoothSco();
+    method public void stopBluetoothSco();
+    method public void unloadSoundEffects();
+    method public void unregisterMediaButtonEventReceiver(android.content.ComponentName);
+    method public void unregisterRemoteControlClient(android.media.RemoteControlClient);
+    field public static final java.lang.String ACTION_AUDIO_BECOMING_NOISY = "android.media.AUDIO_BECOMING_NOISY";
+    field public static final deprecated java.lang.String ACTION_SCO_AUDIO_STATE_CHANGED = "android.media.SCO_AUDIO_STATE_CHANGED";
+    field public static final java.lang.String ACTION_SCO_AUDIO_STATE_UPDATED = "android.media.ACTION_SCO_AUDIO_STATE_UPDATED";
+    field public static final int ADJUST_LOWER = -1; // 0xffffffff
+    field public static final int ADJUST_RAISE = 1; // 0x1
+    field public static final int ADJUST_SAME = 0; // 0x0
+    field public static final int AUDIOFOCUS_GAIN = 1; // 0x1
+    field public static final int AUDIOFOCUS_GAIN_TRANSIENT = 2; // 0x2
+    field public static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK = 3; // 0x3
+    field public static final int AUDIOFOCUS_LOSS = -1; // 0xffffffff
+    field public static final int AUDIOFOCUS_LOSS_TRANSIENT = -2; // 0xfffffffe
+    field public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = -3; // 0xfffffffd
+    field public static final int AUDIOFOCUS_REQUEST_FAILED = 0; // 0x0
+    field public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; // 0x1
+    field public static final java.lang.String EXTRA_RINGER_MODE = "android.media.EXTRA_RINGER_MODE";
+    field public static final java.lang.String EXTRA_SCO_AUDIO_PREVIOUS_STATE = "android.media.extra.SCO_AUDIO_PREVIOUS_STATE";
+    field public static final java.lang.String EXTRA_SCO_AUDIO_STATE = "android.media.extra.SCO_AUDIO_STATE";
+    field public static final deprecated java.lang.String EXTRA_VIBRATE_SETTING = "android.media.EXTRA_VIBRATE_SETTING";
+    field public static final deprecated java.lang.String EXTRA_VIBRATE_TYPE = "android.media.EXTRA_VIBRATE_TYPE";
+    field public static final int FLAG_ALLOW_RINGER_MODES = 2; // 0x2
+    field public static final int FLAG_PLAY_SOUND = 4; // 0x4
+    field public static final int FLAG_REMOVE_SOUND_AND_VIBRATE = 8; // 0x8
+    field public static final int FLAG_SHOW_UI = 1; // 0x1
+    field public static final int FLAG_VIBRATE = 16; // 0x10
+    field public static final int FX_FOCUS_NAVIGATION_DOWN = 2; // 0x2
+    field public static final int FX_FOCUS_NAVIGATION_LEFT = 3; // 0x3
+    field public static final int FX_FOCUS_NAVIGATION_RIGHT = 4; // 0x4
+    field public static final int FX_FOCUS_NAVIGATION_UP = 1; // 0x1
+    field public static final int FX_KEYPRESS_DELETE = 7; // 0x7
+    field public static final int FX_KEYPRESS_RETURN = 8; // 0x8
+    field public static final int FX_KEYPRESS_SPACEBAR = 6; // 0x6
+    field public static final int FX_KEYPRESS_STANDARD = 5; // 0x5
+    field public static final int FX_KEY_CLICK = 0; // 0x0
+    field public static final int MODE_CURRENT = -1; // 0xffffffff
+    field public static final int MODE_INVALID = -2; // 0xfffffffe
+    field public static final int MODE_IN_CALL = 2; // 0x2
+    field public static final int MODE_IN_COMMUNICATION = 3; // 0x3
+    field public static final int MODE_NORMAL = 0; // 0x0
+    field public static final int MODE_RINGTONE = 1; // 0x1
+    field public static final deprecated int NUM_STREAMS = 5; // 0x5
+    field public static final java.lang.String PROPERTY_OUTPUT_FRAMES_PER_BUFFER = "android.media.property.OUTPUT_FRAMES_PER_BUFFER";
+    field public static final java.lang.String PROPERTY_OUTPUT_SAMPLE_RATE = "android.media.property.OUTPUT_SAMPLE_RATE";
+    field public static final java.lang.String RINGER_MODE_CHANGED_ACTION = "android.media.RINGER_MODE_CHANGED";
+    field public static final int RINGER_MODE_NORMAL = 2; // 0x2
+    field public static final int RINGER_MODE_SILENT = 0; // 0x0
+    field public static final int RINGER_MODE_VIBRATE = 1; // 0x1
+    field public static final deprecated int ROUTE_ALL = -1; // 0xffffffff
+    field public static final deprecated int ROUTE_BLUETOOTH = 4; // 0x4
+    field public static final deprecated int ROUTE_BLUETOOTH_A2DP = 16; // 0x10
+    field public static final deprecated int ROUTE_BLUETOOTH_SCO = 4; // 0x4
+    field public static final deprecated int ROUTE_EARPIECE = 1; // 0x1
+    field public static final deprecated int ROUTE_HEADSET = 8; // 0x8
+    field public static final deprecated int ROUTE_SPEAKER = 2; // 0x2
+    field public static final int SCO_AUDIO_STATE_CONNECTED = 1; // 0x1
+    field public static final int SCO_AUDIO_STATE_CONNECTING = 2; // 0x2
+    field public static final int SCO_AUDIO_STATE_DISCONNECTED = 0; // 0x0
+    field public static final int SCO_AUDIO_STATE_ERROR = -1; // 0xffffffff
+    field public static final int STREAM_ALARM = 4; // 0x4
+    field public static final int STREAM_DTMF = 8; // 0x8
+    field public static final int STREAM_MUSIC = 3; // 0x3
+    field public static final int STREAM_NOTIFICATION = 5; // 0x5
+    field public static final int STREAM_RING = 2; // 0x2
+    field public static final int STREAM_SYSTEM = 1; // 0x1
+    field public static final int STREAM_VOICE_CALL = 0; // 0x0
+    field public static final int USE_DEFAULT_STREAM_TYPE = -2147483648; // 0x80000000
+    field public static final deprecated java.lang.String VIBRATE_SETTING_CHANGED_ACTION = "android.media.VIBRATE_SETTING_CHANGED";
+    field public static final deprecated int VIBRATE_SETTING_OFF = 0; // 0x0
+    field public static final deprecated int VIBRATE_SETTING_ON = 1; // 0x1
+    field public static final deprecated int VIBRATE_SETTING_ONLY_SILENT = 2; // 0x2
+    field public static final deprecated int VIBRATE_TYPE_NOTIFICATION = 1; // 0x1
+    field public static final deprecated int VIBRATE_TYPE_RINGER = 0; // 0x0
+  }
+
+  public static abstract interface AudioManager.OnAudioFocusChangeListener {
+    method public abstract void onAudioFocusChange(int);
+  }
+
+  public class AudioRecord {
+    ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException;
+    method public int getAudioFormat();
+    method public int getAudioSessionId();
+    method public int getAudioSource();
+    method public int getChannelConfiguration();
+    method public int getChannelCount();
+    method public static int getMinBufferSize(int, int, int);
+    method public int getNotificationMarkerPosition();
+    method public int getPositionNotificationPeriod();
+    method public int getRecordingState();
+    method public int getSampleRate();
+    method public int getState();
+    method public int read(byte[], int, int);
+    method public int read(short[], int, int);
+    method public int read(java.nio.ByteBuffer, int);
+    method public void release();
+    method public int setNotificationMarkerPosition(int);
+    method public int setPositionNotificationPeriod(int);
+    method public void setRecordPositionUpdateListener(android.media.AudioRecord.OnRecordPositionUpdateListener);
+    method public void setRecordPositionUpdateListener(android.media.AudioRecord.OnRecordPositionUpdateListener, android.os.Handler);
+    method public void startRecording() throws java.lang.IllegalStateException;
+    method public void startRecording(android.media.MediaSyncEvent) throws java.lang.IllegalStateException;
+    method public void stop() throws java.lang.IllegalStateException;
+    field public static final int ERROR = -1; // 0xffffffff
+    field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
+    field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
+    field public static final int RECORDSTATE_RECORDING = 3; // 0x3
+    field public static final int RECORDSTATE_STOPPED = 1; // 0x1
+    field public static final int STATE_INITIALIZED = 1; // 0x1
+    field public static final int STATE_UNINITIALIZED = 0; // 0x0
+    field public static final int SUCCESS = 0; // 0x0
+  }
+
+  public static abstract interface AudioRecord.OnRecordPositionUpdateListener {
+    method public abstract void onMarkerReached(android.media.AudioRecord);
+    method public abstract void onPeriodicNotification(android.media.AudioRecord);
+  }
+
+  public class AudioTrack {
+    ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+    ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+    method public int attachAuxEffect(int);
+    method public void flush();
+    method public int getAudioFormat();
+    method public int getAudioSessionId();
+    method public int getChannelConfiguration();
+    method public int getChannelCount();
+    method public static float getMaxVolume();
+    method public static int getMinBufferSize(int, int, int);
+    method public static float getMinVolume();
+    method protected int getNativeFrameCount();
+    method public static int getNativeOutputSampleRate(int);
+    method public int getNotificationMarkerPosition();
+    method public int getPlayState();
+    method public int getPlaybackHeadPosition();
+    method public int getPlaybackRate();
+    method public int getPositionNotificationPeriod();
+    method public int getSampleRate();
+    method public int getState();
+    method public int getStreamType();
+    method public void pause() throws java.lang.IllegalStateException;
+    method public void play() throws java.lang.IllegalStateException;
+    method public void release();
+    method public int reloadStaticData();
+    method public int setAuxEffectSendLevel(float);
+    method public int setLoopPoints(int, int, int);
+    method public int setNotificationMarkerPosition(int);
+    method public int setPlaybackHeadPosition(int);
+    method public void setPlaybackPositionUpdateListener(android.media.AudioTrack.OnPlaybackPositionUpdateListener);
+    method public void setPlaybackPositionUpdateListener(android.media.AudioTrack.OnPlaybackPositionUpdateListener, android.os.Handler);
+    method public int setPlaybackRate(int);
+    method public int setPositionNotificationPeriod(int);
+    method protected void setState(int);
+    method public int setStereoVolume(float, float);
+    method public void stop() throws java.lang.IllegalStateException;
+    method public int write(byte[], int, int);
+    method public int write(short[], int, int);
+    field public static final int ERROR = -1; // 0xffffffff
+    field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
+    field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
+    field public static final int MODE_STATIC = 0; // 0x0
+    field public static final int MODE_STREAM = 1; // 0x1
+    field public static final int PLAYSTATE_PAUSED = 2; // 0x2
+    field public static final int PLAYSTATE_PLAYING = 3; // 0x3
+    field public static final int PLAYSTATE_STOPPED = 1; // 0x1
+    field public static final int STATE_INITIALIZED = 1; // 0x1
+    field public static final int STATE_NO_STATIC_DATA = 2; // 0x2
+    field public static final int STATE_UNINITIALIZED = 0; // 0x0
+    field public static final int SUCCESS = 0; // 0x0
+  }
+
+  public static abstract interface AudioTrack.OnPlaybackPositionUpdateListener {
+    method public abstract void onMarkerReached(android.media.AudioTrack);
+    method public abstract void onPeriodicNotification(android.media.AudioTrack);
+  }
+
+  public class CamcorderProfile {
+    method public static android.media.CamcorderProfile get(int);
+    method public static android.media.CamcorderProfile get(int, int);
+    method public static boolean hasProfile(int);
+    method public static boolean hasProfile(int, int);
+    field public static final int QUALITY_1080P = 6; // 0x6
+    field public static final int QUALITY_480P = 4; // 0x4
+    field public static final int QUALITY_720P = 5; // 0x5
+    field public static final int QUALITY_CIF = 3; // 0x3
+    field public static final int QUALITY_HIGH = 1; // 0x1
+    field public static final int QUALITY_LOW = 0; // 0x0
+    field public static final int QUALITY_QCIF = 2; // 0x2
+    field public static final int QUALITY_QVGA = 7; // 0x7
+    field public static final int QUALITY_TIME_LAPSE_1080P = 1006; // 0x3ee
+    field public static final int QUALITY_TIME_LAPSE_480P = 1004; // 0x3ec
+    field public static final int QUALITY_TIME_LAPSE_720P = 1005; // 0x3ed
+    field public static final int QUALITY_TIME_LAPSE_CIF = 1003; // 0x3eb
+    field public static final int QUALITY_TIME_LAPSE_HIGH = 1001; // 0x3e9
+    field public static final int QUALITY_TIME_LAPSE_LOW = 1000; // 0x3e8
+    field public static final int QUALITY_TIME_LAPSE_QCIF = 1002; // 0x3ea
+    field public static final int QUALITY_TIME_LAPSE_QVGA = 1007; // 0x3ef
+    field public int audioBitRate;
+    field public int audioChannels;
+    field public int audioCodec;
+    field public int audioSampleRate;
+    field public int duration;
+    field public int fileFormat;
+    field public int quality;
+    field public int videoBitRate;
+    field public int videoCodec;
+    field public int videoFrameHeight;
+    field public int videoFrameRate;
+    field public int videoFrameWidth;
+  }
+
+  public class CameraProfile {
+    ctor public CameraProfile();
+    method public static int getJpegEncodingQualityParameter(int);
+    method public static int getJpegEncodingQualityParameter(int, int);
+    field public static final int QUALITY_HIGH = 2; // 0x2
+    field public static final int QUALITY_LOW = 0; // 0x0
+    field public static final int QUALITY_MEDIUM = 1; // 0x1
+  }
+
+  public class ExifInterface {
+    ctor public ExifInterface(java.lang.String) throws java.io.IOException;
+    method public double getAltitude(double);
+    method public java.lang.String getAttribute(java.lang.String);
+    method public double getAttributeDouble(java.lang.String, double);
+    method public int getAttributeInt(java.lang.String, int);
+    method public boolean getLatLong(float[]);
+    method public byte[] getThumbnail();
+    method public boolean hasThumbnail();
+    method public void saveAttributes() throws java.io.IOException;
+    method public void setAttribute(java.lang.String, java.lang.String);
+    field public static final int ORIENTATION_FLIP_HORIZONTAL = 2; // 0x2
+    field public static final int ORIENTATION_FLIP_VERTICAL = 4; // 0x4
+    field public static final int ORIENTATION_NORMAL = 1; // 0x1
+    field public static final int ORIENTATION_ROTATE_180 = 3; // 0x3
+    field public static final int ORIENTATION_ROTATE_270 = 8; // 0x8
+    field public static final int ORIENTATION_ROTATE_90 = 6; // 0x6
+    field public static final int ORIENTATION_TRANSPOSE = 5; // 0x5
+    field public static final int ORIENTATION_TRANSVERSE = 7; // 0x7
+    field public static final int ORIENTATION_UNDEFINED = 0; // 0x0
+    field public static final java.lang.String TAG_APERTURE = "FNumber";
+    field public static final java.lang.String TAG_DATETIME = "DateTime";
+    field public static final java.lang.String TAG_EXPOSURE_TIME = "ExposureTime";
+    field public static final java.lang.String TAG_FLASH = "Flash";
+    field public static final java.lang.String TAG_FOCAL_LENGTH = "FocalLength";
+    field public static final java.lang.String TAG_GPS_ALTITUDE = "GPSAltitude";
+    field public static final java.lang.String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
+    field public static final java.lang.String TAG_GPS_DATESTAMP = "GPSDateStamp";
+    field public static final java.lang.String TAG_GPS_LATITUDE = "GPSLatitude";
+    field public static final java.lang.String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
+    field public static final java.lang.String TAG_GPS_LONGITUDE = "GPSLongitude";
+    field public static final java.lang.String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
+    field public static final java.lang.String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod";
+    field public static final java.lang.String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
+    field public static final java.lang.String TAG_IMAGE_LENGTH = "ImageLength";
+    field public static final java.lang.String TAG_IMAGE_WIDTH = "ImageWidth";
+    field public static final java.lang.String TAG_ISO = "ISOSpeedRatings";
+    field public static final java.lang.String TAG_MAKE = "Make";
+    field public static final java.lang.String TAG_MODEL = "Model";
+    field public static final java.lang.String TAG_ORIENTATION = "Orientation";
+    field public static final java.lang.String TAG_WHITE_BALANCE = "WhiteBalance";
+    field public static final int WHITEBALANCE_AUTO = 0; // 0x0
+    field public static final int WHITEBALANCE_MANUAL = 1; // 0x1
+  }
+
+  public class FaceDetector {
+    ctor public FaceDetector(int, int, int);
+    method public int findFaces(android.graphics.Bitmap, android.media.FaceDetector.Face[]);
+  }
+
+  public class FaceDetector.Face {
+    method public float confidence();
+    method public float eyesDistance();
+    method public void getMidPoint(android.graphics.PointF);
+    method public float pose(int);
+    field public static final float CONFIDENCE_THRESHOLD = 0.4f;
+    field public static final int EULER_X = 0; // 0x0
+    field public static final int EULER_Y = 1; // 0x1
+    field public static final int EULER_Z = 2; // 0x2
+  }
+
+  public class JetPlayer {
+    method public boolean clearQueue();
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public boolean closeJetFile();
+    method public static android.media.JetPlayer getJetPlayer();
+    method public static int getMaxTracks();
+    method public boolean loadJetFile(java.lang.String);
+    method public boolean loadJetFile(android.content.res.AssetFileDescriptor);
+    method public boolean pause();
+    method public boolean play();
+    method public boolean queueJetSegment(int, int, int, int, int, byte);
+    method public boolean queueJetSegmentMuteArray(int, int, int, int, boolean[], byte);
+    method public void release();
+    method public void setEventListener(android.media.JetPlayer.OnJetEventListener);
+    method public void setEventListener(android.media.JetPlayer.OnJetEventListener, android.os.Handler);
+    method public boolean setMuteArray(boolean[], boolean);
+    method public boolean setMuteFlag(int, boolean, boolean);
+    method public boolean setMuteFlags(int, boolean);
+    method public boolean triggerClip(int);
+  }
+
+  public static abstract interface JetPlayer.OnJetEventListener {
+    method public abstract void onJetEvent(android.media.JetPlayer, short, byte, byte, byte, byte);
+    method public abstract void onJetNumQueuedSegmentUpdate(android.media.JetPlayer, int);
+    method public abstract void onJetPauseUpdate(android.media.JetPlayer, int);
+    method public abstract void onJetUserIdUpdate(android.media.JetPlayer, int, int);
+  }
+
+  public class MediaActionSound {
+    ctor public MediaActionSound();
+    method public synchronized void load(int);
+    method public synchronized void play(int);
+    method public void release();
+    field public static final int FOCUS_COMPLETE = 1; // 0x1
+    field public static final int SHUTTER_CLICK = 0; // 0x0
+    field public static final int START_VIDEO_RECORDING = 2; // 0x2
+    field public static final int STOP_VIDEO_RECORDING = 3; // 0x3
+  }
+
+  public final class MediaCodec {
+    method public void configure(android.media.MediaFormat, android.view.Surface, android.media.MediaCrypto, int);
+    method public static android.media.MediaCodec createByCodecName(java.lang.String);
+    method public static android.media.MediaCodec createDecoderByType(java.lang.String);
+    method public static android.media.MediaCodec createEncoderByType(java.lang.String);
+    method public final int dequeueInputBuffer(long);
+    method public final int dequeueOutputBuffer(android.media.MediaCodec.BufferInfo, long);
+    method public final void flush();
+    method public java.nio.ByteBuffer[] getInputBuffers();
+    method public java.nio.ByteBuffer[] getOutputBuffers();
+    method public final android.media.MediaFormat getOutputFormat();
+    method public final void queueInputBuffer(int, int, int, long, int) throws android.media.MediaCodec.CryptoException;
+    method public final void queueSecureInputBuffer(int, int, android.media.MediaCodec.CryptoInfo, long, int) throws android.media.MediaCodec.CryptoException;
+    method public final void release();
+    method public final void releaseOutputBuffer(int, boolean);
+    method public final void setVideoScalingMode(int);
+    method public final void start();
+    method public final void stop();
+    field public static final int BUFFER_FLAG_CODEC_CONFIG = 2; // 0x2
+    field public static final int BUFFER_FLAG_END_OF_STREAM = 4; // 0x4
+    field public static final int BUFFER_FLAG_SYNC_FRAME = 1; // 0x1
+    field public static final int CONFIGURE_FLAG_ENCODE = 1; // 0x1
+    field public static final int CRYPTO_MODE_AES_CTR = 1; // 0x1
+    field public static final int CRYPTO_MODE_UNENCRYPTED = 0; // 0x0
+    field public static final int INFO_OUTPUT_BUFFERS_CHANGED = -3; // 0xfffffffd
+    field public static final int INFO_OUTPUT_FORMAT_CHANGED = -2; // 0xfffffffe
+    field public static final int INFO_TRY_AGAIN_LATER = -1; // 0xffffffff
+    field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT = 1; // 0x1
+    field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2; // 0x2
+  }
+
+  public static final class MediaCodec.BufferInfo {
+    ctor public MediaCodec.BufferInfo();
+    method public void set(int, int, long, int);
+    field public int flags;
+    field public int offset;
+    field public long presentationTimeUs;
+    field public int size;
+  }
+
+  public static final class MediaCodec.CryptoException extends java.lang.RuntimeException {
+    ctor public MediaCodec.CryptoException(int, java.lang.String);
+    method public int getErrorCode();
+  }
+
+  public static final class MediaCodec.CryptoInfo {
+    ctor public MediaCodec.CryptoInfo();
+    method public void set(int, int[], int[], byte[], byte[], int);
+    field public byte[] iv;
+    field public byte[] key;
+    field public int mode;
+    field public int[] numBytesOfClearData;
+    field public int[] numBytesOfEncryptedData;
+    field public int numSubSamples;
+  }
+
+  public final class MediaCodecInfo {
+    method public final android.media.MediaCodecInfo.CodecCapabilities getCapabilitiesForType(java.lang.String);
+    method public final java.lang.String getName();
+    method public final java.lang.String[] getSupportedTypes();
+    method public final boolean isEncoder();
+  }
+
+  public static final class MediaCodecInfo.CodecCapabilities {
+    ctor public MediaCodecInfo.CodecCapabilities();
+    field public static final int COLOR_Format12bitRGB444 = 3; // 0x3
+    field public static final int COLOR_Format16bitARGB1555 = 5; // 0x5
+    field public static final int COLOR_Format16bitARGB4444 = 4; // 0x4
+    field public static final int COLOR_Format16bitBGR565 = 7; // 0x7
+    field public static final int COLOR_Format16bitRGB565 = 6; // 0x6
+    field public static final int COLOR_Format18BitBGR666 = 41; // 0x29
+    field public static final int COLOR_Format18bitARGB1665 = 9; // 0x9
+    field public static final int COLOR_Format18bitRGB666 = 8; // 0x8
+    field public static final int COLOR_Format19bitARGB1666 = 10; // 0xa
+    field public static final int COLOR_Format24BitABGR6666 = 43; // 0x2b
+    field public static final int COLOR_Format24BitARGB6666 = 42; // 0x2a
+    field public static final int COLOR_Format24bitARGB1887 = 13; // 0xd
+    field public static final int COLOR_Format24bitBGR888 = 12; // 0xc
+    field public static final int COLOR_Format24bitRGB888 = 11; // 0xb
+    field public static final int COLOR_Format25bitARGB1888 = 14; // 0xe
+    field public static final int COLOR_Format32bitARGB8888 = 16; // 0x10
+    field public static final int COLOR_Format32bitBGRA8888 = 15; // 0xf
+    field public static final int COLOR_Format8bitRGB332 = 2; // 0x2
+    field public static final int COLOR_FormatCbYCrY = 27; // 0x1b
+    field public static final int COLOR_FormatCrYCbY = 28; // 0x1c
+    field public static final int COLOR_FormatL16 = 36; // 0x24
+    field public static final int COLOR_FormatL2 = 33; // 0x21
+    field public static final int COLOR_FormatL24 = 37; // 0x25
+    field public static final int COLOR_FormatL32 = 38; // 0x26
+    field public static final int COLOR_FormatL4 = 34; // 0x22
+    field public static final int COLOR_FormatL8 = 35; // 0x23
+    field public static final int COLOR_FormatMonochrome = 1; // 0x1
+    field public static final int COLOR_FormatRawBayer10bit = 31; // 0x1f
+    field public static final int COLOR_FormatRawBayer8bit = 30; // 0x1e
+    field public static final int COLOR_FormatRawBayer8bitcompressed = 32; // 0x20
+    field public static final int COLOR_FormatYCbYCr = 25; // 0x19
+    field public static final int COLOR_FormatYCrYCb = 26; // 0x1a
+    field public static final int COLOR_FormatYUV411PackedPlanar = 18; // 0x12
+    field public static final int COLOR_FormatYUV411Planar = 17; // 0x11
+    field public static final int COLOR_FormatYUV420PackedPlanar = 20; // 0x14
+    field public static final int COLOR_FormatYUV420PackedSemiPlanar = 39; // 0x27
+    field public static final int COLOR_FormatYUV420Planar = 19; // 0x13
+    field public static final int COLOR_FormatYUV420SemiPlanar = 21; // 0x15
+    field public static final int COLOR_FormatYUV422PackedPlanar = 23; // 0x17
+    field public static final int COLOR_FormatYUV422PackedSemiPlanar = 40; // 0x28
+    field public static final int COLOR_FormatYUV422Planar = 22; // 0x16
+    field public static final int COLOR_FormatYUV422SemiPlanar = 24; // 0x18
+    field public static final int COLOR_FormatYUV444Interleaved = 29; // 0x1d
+    field public static final int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00
+    field public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
+    field public int[] colorFormats;
+    field public android.media.MediaCodecInfo.CodecProfileLevel[] profileLevels;
+  }
+
+  public static final class MediaCodecInfo.CodecProfileLevel {
+    ctor public MediaCodecInfo.CodecProfileLevel();
+    field public static final int AACObjectELD = 39; // 0x27
+    field public static final int AACObjectERLC = 17; // 0x11
+    field public static final int AACObjectHE = 5; // 0x5
+    field public static final int AACObjectHE_PS = 29; // 0x1d
+    field public static final int AACObjectLC = 2; // 0x2
+    field public static final int AACObjectLD = 23; // 0x17
+    field public static final int AACObjectLTP = 4; // 0x4
+    field public static final int AACObjectMain = 1; // 0x1
+    field public static final int AACObjectSSR = 3; // 0x3
+    field public static final int AACObjectScalable = 6; // 0x6
+    field public static final int AVCLevel1 = 1; // 0x1
+    field public static final int AVCLevel11 = 4; // 0x4
+    field public static final int AVCLevel12 = 8; // 0x8
+    field public static final int AVCLevel13 = 16; // 0x10
+    field public static final int AVCLevel1b = 2; // 0x2
+    field public static final int AVCLevel2 = 32; // 0x20
+    field public static final int AVCLevel21 = 64; // 0x40
+    field public static final int AVCLevel22 = 128; // 0x80
+    field public static final int AVCLevel3 = 256; // 0x100
+    field public static final int AVCLevel31 = 512; // 0x200
+    field public static final int AVCLevel32 = 1024; // 0x400
+    field public static final int AVCLevel4 = 2048; // 0x800
+    field public static final int AVCLevel41 = 4096; // 0x1000
+    field public static final int AVCLevel42 = 8192; // 0x2000
+    field public static final int AVCLevel5 = 16384; // 0x4000
+    field public static final int AVCLevel51 = 32768; // 0x8000
+    field public static final int AVCProfileBaseline = 1; // 0x1
+    field public static final int AVCProfileExtended = 4; // 0x4
+    field public static final int AVCProfileHigh = 8; // 0x8
+    field public static final int AVCProfileHigh10 = 16; // 0x10
+    field public static final int AVCProfileHigh422 = 32; // 0x20
+    field public static final int AVCProfileHigh444 = 64; // 0x40
+    field public static final int AVCProfileMain = 2; // 0x2
+    field public static final int H263Level10 = 1; // 0x1
+    field public static final int H263Level20 = 2; // 0x2
+    field public static final int H263Level30 = 4; // 0x4
+    field public static final int H263Level40 = 8; // 0x8
+    field public static final int H263Level45 = 16; // 0x10
+    field public static final int H263Level50 = 32; // 0x20
+    field public static final int H263Level60 = 64; // 0x40
+    field public static final int H263Level70 = 128; // 0x80
+    field public static final int H263ProfileBackwardCompatible = 4; // 0x4
+    field public static final int H263ProfileBaseline = 1; // 0x1
+    field public static final int H263ProfileH320Coding = 2; // 0x2
+    field public static final int H263ProfileHighCompression = 32; // 0x20
+    field public static final int H263ProfileHighLatency = 256; // 0x100
+    field public static final int H263ProfileISWV2 = 8; // 0x8
+    field public static final int H263ProfileISWV3 = 16; // 0x10
+    field public static final int H263ProfileInterlace = 128; // 0x80
+    field public static final int H263ProfileInternet = 64; // 0x40
+    field public static final int MPEG4Level0 = 1; // 0x1
+    field public static final int MPEG4Level0b = 2; // 0x2
+    field public static final int MPEG4Level1 = 4; // 0x4
+    field public static final int MPEG4Level2 = 8; // 0x8
+    field public static final int MPEG4Level3 = 16; // 0x10
+    field public static final int MPEG4Level4 = 32; // 0x20
+    field public static final int MPEG4Level4a = 64; // 0x40
+    field public static final int MPEG4Level5 = 128; // 0x80
+    field public static final int MPEG4ProfileAdvancedCoding = 4096; // 0x1000
+    field public static final int MPEG4ProfileAdvancedCore = 8192; // 0x2000
+    field public static final int MPEG4ProfileAdvancedRealTime = 1024; // 0x400
+    field public static final int MPEG4ProfileAdvancedScalable = 16384; // 0x4000
+    field public static final int MPEG4ProfileAdvancedSimple = 32768; // 0x8000
+    field public static final int MPEG4ProfileBasicAnimated = 256; // 0x100
+    field public static final int MPEG4ProfileCore = 4; // 0x4
+    field public static final int MPEG4ProfileCoreScalable = 2048; // 0x800
+    field public static final int MPEG4ProfileHybrid = 512; // 0x200
+    field public static final int MPEG4ProfileMain = 8; // 0x8
+    field public static final int MPEG4ProfileNbit = 16; // 0x10
+    field public static final int MPEG4ProfileScalableTexture = 32; // 0x20
+    field public static final int MPEG4ProfileSimple = 1; // 0x1
+    field public static final int MPEG4ProfileSimpleFBA = 128; // 0x80
+    field public static final int MPEG4ProfileSimpleFace = 64; // 0x40
+    field public static final int MPEG4ProfileSimpleScalable = 2; // 0x2
+    field public int level;
+    field public int profile;
+  }
+
+  public final class MediaCodecList {
+    method public static final int getCodecCount();
+    method public static final android.media.MediaCodecInfo getCodecInfoAt(int);
+  }
+
+  public final class MediaCrypto {
+    ctor public MediaCrypto(java.util.UUID, byte[]) throws android.media.MediaCryptoException;
+    method public static final boolean isCryptoSchemeSupported(java.util.UUID);
+    method public final void release();
+    method public final boolean requiresSecureDecoderComponent(java.lang.String);
+  }
+
+  public final class MediaCryptoException extends java.lang.Exception {
+    ctor public MediaCryptoException(java.lang.String);
+  }
+
+  public final class MediaExtractor {
+    ctor public MediaExtractor();
+    method public boolean advance();
+    method public long getCachedDuration();
+    method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
+    method public int getSampleFlags();
+    method public long getSampleTime();
+    method public int getSampleTrackIndex();
+    method public final int getTrackCount();
+    method public android.media.MediaFormat getTrackFormat(int);
+    method public boolean hasCacheReachedEndOfStream();
+    method public int readSampleData(java.nio.ByteBuffer, int);
+    method public final void release();
+    method public void seekTo(long, int);
+    method public void selectTrack(int);
+    method public final void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
+    method public final void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>);
+    method public final void setDataSource(java.lang.String);
+    method public final void setDataSource(java.io.FileDescriptor);
+    method public final void setDataSource(java.io.FileDescriptor, long, long);
+    method public void unselectTrack(int);
+    field public static final int SAMPLE_FLAG_ENCRYPTED = 2; // 0x2
+    field public static final int SAMPLE_FLAG_SYNC = 1; // 0x1
+    field public static final int SEEK_TO_CLOSEST_SYNC = 2; // 0x2
+    field public static final int SEEK_TO_NEXT_SYNC = 1; // 0x1
+    field public static final int SEEK_TO_PREVIOUS_SYNC = 0; // 0x0
+  }
+
+  public final class MediaFormat {
+    ctor public MediaFormat();
+    method public final boolean containsKey(java.lang.String);
+    method public static final android.media.MediaFormat createAudioFormat(java.lang.String, int, int);
+    method public static final android.media.MediaFormat createVideoFormat(java.lang.String, int, int);
+    method public final java.nio.ByteBuffer getByteBuffer(java.lang.String);
+    method public final float getFloat(java.lang.String);
+    method public final int getInteger(java.lang.String);
+    method public final long getLong(java.lang.String);
+    method public final java.lang.String getString(java.lang.String);
+    method public final void setByteBuffer(java.lang.String, java.nio.ByteBuffer);
+    method public final void setFloat(java.lang.String, float);
+    method public final void setInteger(java.lang.String, int);
+    method public final void setLong(java.lang.String, long);
+    method public final void setString(java.lang.String, java.lang.String);
+    field public static final java.lang.String KEY_AAC_PROFILE = "aac-profile";
+    field public static final java.lang.String KEY_BIT_RATE = "bitrate";
+    field public static final java.lang.String KEY_CHANNEL_COUNT = "channel-count";
+    field public static final java.lang.String KEY_CHANNEL_MASK = "channel-mask";
+    field public static final java.lang.String KEY_COLOR_FORMAT = "color-format";
+    field public static final java.lang.String KEY_DURATION = "durationUs";
+    field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
+    field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
+    field public static final java.lang.String KEY_HEIGHT = "height";
+    field public static final java.lang.String KEY_IS_ADTS = "is-adts";
+    field public static final java.lang.String KEY_I_FRAME_INTERVAL = "i-frame-interval";
+    field public static final java.lang.String KEY_MAX_INPUT_SIZE = "max-input-size";
+    field public static final java.lang.String KEY_MIME = "mime";
+    field public static final java.lang.String KEY_SAMPLE_RATE = "sample-rate";
+    field public static final java.lang.String KEY_WIDTH = "width";
+  }
+
+  public class MediaMetadataRetriever {
+    ctor public MediaMetadataRetriever();
+    method public java.lang.String extractMetadata(int);
+    method public byte[] getEmbeddedPicture();
+    method public android.graphics.Bitmap getFrameAtTime(long, int);
+    method public android.graphics.Bitmap getFrameAtTime(long);
+    method public android.graphics.Bitmap getFrameAtTime();
+    method public void release();
+    method public void setDataSource(java.lang.String) throws java.lang.IllegalArgumentException;
+    method public void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>) throws java.lang.IllegalArgumentException;
+    method public void setDataSource(java.io.FileDescriptor, long, long) throws java.lang.IllegalArgumentException;
+    method public void setDataSource(java.io.FileDescriptor) throws java.lang.IllegalArgumentException;
+    method public void setDataSource(android.content.Context, android.net.Uri) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
+    field public static final int METADATA_KEY_ALBUM = 1; // 0x1
+    field public static final int METADATA_KEY_ALBUMARTIST = 13; // 0xd
+    field public static final int METADATA_KEY_ARTIST = 2; // 0x2
+    field public static final int METADATA_KEY_AUTHOR = 3; // 0x3
+    field public static final int METADATA_KEY_BITRATE = 20; // 0x14
+    field public static final int METADATA_KEY_CD_TRACK_NUMBER = 0; // 0x0
+    field public static final int METADATA_KEY_COMPILATION = 15; // 0xf
+    field public static final int METADATA_KEY_COMPOSER = 4; // 0x4
+    field public static final int METADATA_KEY_DATE = 5; // 0x5
+    field public static final int METADATA_KEY_DISC_NUMBER = 14; // 0xe
+    field public static final int METADATA_KEY_DURATION = 9; // 0x9
+    field public static final int METADATA_KEY_GENRE = 6; // 0x6
+    field public static final int METADATA_KEY_HAS_AUDIO = 16; // 0x10
+    field public static final int METADATA_KEY_HAS_VIDEO = 17; // 0x11
+    field public static final int METADATA_KEY_LOCATION = 23; // 0x17
+    field public static final int METADATA_KEY_MIMETYPE = 12; // 0xc
+    field public static final int METADATA_KEY_NUM_TRACKS = 10; // 0xa
+    field public static final int METADATA_KEY_TITLE = 7; // 0x7
+    field public static final int METADATA_KEY_VIDEO_HEIGHT = 19; // 0x13
+    field public static final int METADATA_KEY_VIDEO_ROTATION = 24; // 0x18
+    field public static final int METADATA_KEY_VIDEO_WIDTH = 18; // 0x12
+    field public static final int METADATA_KEY_WRITER = 11; // 0xb
+    field public static final int METADATA_KEY_YEAR = 8; // 0x8
+    field public static final int OPTION_CLOSEST = 3; // 0x3
+    field public static final int OPTION_CLOSEST_SYNC = 2; // 0x2
+    field public static final int OPTION_NEXT_SYNC = 1; // 0x1
+    field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0
+  }
+
+  public class MediaPlayer {
+    ctor public MediaPlayer();
+    method public void addTimedTextSource(java.lang.String, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public void addTimedTextSource(android.content.Context, android.net.Uri, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public void addTimedTextSource(java.io.FileDescriptor, java.lang.String) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public void addTimedTextSource(java.io.FileDescriptor, long, long, java.lang.String) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public void attachAuxEffect(int);
+    method public static android.media.MediaPlayer create(android.content.Context, android.net.Uri);
+    method public static android.media.MediaPlayer create(android.content.Context, android.net.Uri, android.view.SurfaceHolder);
+    method public static android.media.MediaPlayer create(android.content.Context, int);
+    method public void deselectTrack(int) throws java.lang.IllegalStateException;
+    method public int getAudioSessionId();
+    method public int getCurrentPosition();
+    method public int getDuration();
+    method public android.media.MediaPlayer.TrackInfo[] getTrackInfo() throws java.lang.IllegalStateException;
+    method public int getVideoHeight();
+    method public int getVideoWidth();
+    method public boolean isLooping();
+    method public boolean isPlaying();
+    method public void pause() throws java.lang.IllegalStateException;
+    method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
+    method public void prepareAsync() throws java.lang.IllegalStateException;
+    method public void release();
+    method public void reset();
+    method public void seekTo(int) throws java.lang.IllegalStateException;
+    method public void selectTrack(int) throws java.lang.IllegalStateException;
+    method public void setAudioSessionId(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public void setAudioStreamType(int);
+    method public void setAuxEffectSendLevel(float);
+    method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
+    method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
+    method public void setDataSource(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
+    method public void setDataSource(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public void setDisplay(android.view.SurfaceHolder);
+    method public void setLooping(boolean);
+    method public void setNextMediaPlayer(android.media.MediaPlayer);
+    method public void setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener);
+    method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
+    method public void setOnErrorListener(android.media.MediaPlayer.OnErrorListener);
+    method public void setOnInfoListener(android.media.MediaPlayer.OnInfoListener);
+    method public void setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener);
+    method public void setOnSeekCompleteListener(android.media.MediaPlayer.OnSeekCompleteListener);
+    method public void setOnTimedTextListener(android.media.MediaPlayer.OnTimedTextListener);
+    method public void setOnVideoSizeChangedListener(android.media.MediaPlayer.OnVideoSizeChangedListener);
+    method public void setScreenOnWhilePlaying(boolean);
+    method public void setSurface(android.view.Surface);
+    method public void setVideoScalingMode(int);
+    method public void setVolume(float, float);
+    method public void setWakeMode(android.content.Context, int);
+    method public void start() throws java.lang.IllegalStateException;
+    method public void stop() throws java.lang.IllegalStateException;
+    field public static final int MEDIA_ERROR_IO = -1004; // 0xfffffc14
+    field public static final int MEDIA_ERROR_MALFORMED = -1007; // 0xfffffc11
+    field public static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200; // 0xc8
+    field public static final int MEDIA_ERROR_SERVER_DIED = 100; // 0x64
+    field public static final int MEDIA_ERROR_TIMED_OUT = -110; // 0xffffff92
+    field public static final int MEDIA_ERROR_UNKNOWN = 1; // 0x1
+    field public static final int MEDIA_ERROR_UNSUPPORTED = -1010; // 0xfffffc0e
+    field public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; // 0x320
+    field public static final int MEDIA_INFO_BUFFERING_END = 702; // 0x2be
+    field public static final int MEDIA_INFO_BUFFERING_START = 701; // 0x2bd
+    field public static final int MEDIA_INFO_METADATA_UPDATE = 802; // 0x322
+    field public static final int MEDIA_INFO_NOT_SEEKABLE = 801; // 0x321
+    field public static final int MEDIA_INFO_UNKNOWN = 1; // 0x1
+    field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
+    field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
+    field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
+    field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT = 1; // 0x1
+    field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2; // 0x2
+  }
+
+  public static abstract interface MediaPlayer.OnBufferingUpdateListener {
+    method public abstract void onBufferingUpdate(android.media.MediaPlayer, int);
+  }
+
+  public static abstract interface MediaPlayer.OnCompletionListener {
+    method public abstract void onCompletion(android.media.MediaPlayer);
+  }
+
+  public static abstract interface MediaPlayer.OnErrorListener {
+    method public abstract boolean onError(android.media.MediaPlayer, int, int);
+  }
+
+  public static abstract interface MediaPlayer.OnInfoListener {
+    method public abstract boolean onInfo(android.media.MediaPlayer, int, int);
+  }
+
+  public static abstract interface MediaPlayer.OnPreparedListener {
+    method public abstract void onPrepared(android.media.MediaPlayer);
+  }
+
+  public static abstract interface MediaPlayer.OnSeekCompleteListener {
+    method public abstract void onSeekComplete(android.media.MediaPlayer);
+  }
+
+  public static abstract interface MediaPlayer.OnTimedTextListener {
+    method public abstract void onTimedText(android.media.MediaPlayer, android.media.TimedText);
+  }
+
+  public static abstract interface MediaPlayer.OnVideoSizeChangedListener {
+    method public abstract void onVideoSizeChanged(android.media.MediaPlayer, int, int);
+  }
+
+  public static class MediaPlayer.TrackInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.String getLanguage();
+    method public int getTrackType();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int MEDIA_TRACK_TYPE_AUDIO = 2; // 0x2
+    field public static final int MEDIA_TRACK_TYPE_TIMEDTEXT = 3; // 0x3
+    field public static final int MEDIA_TRACK_TYPE_UNKNOWN = 0; // 0x0
+    field public static final int MEDIA_TRACK_TYPE_VIDEO = 1; // 0x1
+  }
+
+  public class MediaRecorder {
+    ctor public MediaRecorder();
+    method public static final int getAudioSourceMax();
+    method public int getMaxAmplitude() throws java.lang.IllegalStateException;
+    method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
+    method public void release();
+    method public void reset();
+    method public void setAudioChannels(int);
+    method public void setAudioEncoder(int) throws java.lang.IllegalStateException;
+    method public void setAudioEncodingBitRate(int);
+    method public void setAudioSamplingRate(int);
+    method public void setAudioSource(int) throws java.lang.IllegalStateException;
+    method public void setCamera(android.hardware.Camera);
+    method public void setCaptureRate(double);
+    method public void setLocation(float, float);
+    method public void setMaxDuration(int) throws java.lang.IllegalArgumentException;
+    method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException;
+    method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener);
+    method public void setOnInfoListener(android.media.MediaRecorder.OnInfoListener);
+    method public void setOrientationHint(int);
+    method public void setOutputFile(java.io.FileDescriptor) throws java.lang.IllegalStateException;
+    method public void setOutputFile(java.lang.String) throws java.lang.IllegalStateException;
+    method public void setOutputFormat(int) throws java.lang.IllegalStateException;
+    method public void setPreviewDisplay(android.view.Surface);
+    method public void setProfile(android.media.CamcorderProfile);
+    method public void setVideoEncoder(int) throws java.lang.IllegalStateException;
+    method public void setVideoEncodingBitRate(int);
+    method public void setVideoFrameRate(int) throws java.lang.IllegalStateException;
+    method public void setVideoSize(int, int) throws java.lang.IllegalStateException;
+    method public void setVideoSource(int) throws java.lang.IllegalStateException;
+    method public void start() throws java.lang.IllegalStateException;
+    method public void stop() throws java.lang.IllegalStateException;
+    field public static final int MEDIA_ERROR_SERVER_DIED = 100; // 0x64
+    field public static final int MEDIA_RECORDER_ERROR_UNKNOWN = 1; // 0x1
+    field public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800; // 0x320
+    field public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801; // 0x321
+    field public static final int MEDIA_RECORDER_INFO_UNKNOWN = 1; // 0x1
+  }
+
+  public final class MediaRecorder.AudioEncoder {
+    field public static final int AAC = 3; // 0x3
+    field public static final int AAC_ELD = 5; // 0x5
+    field public static final int AMR_NB = 1; // 0x1
+    field public static final int AMR_WB = 2; // 0x2
+    field public static final int DEFAULT = 0; // 0x0
+    field public static final int HE_AAC = 4; // 0x4
+  }
+
+  public final class MediaRecorder.AudioSource {
+    field public static final int CAMCORDER = 5; // 0x5
+    field public static final int DEFAULT = 0; // 0x0
+    field public static final int MIC = 1; // 0x1
+    field public static final int VOICE_CALL = 4; // 0x4
+    field public static final int VOICE_COMMUNICATION = 7; // 0x7
+    field public static final int VOICE_DOWNLINK = 3; // 0x3
+    field public static final int VOICE_RECOGNITION = 6; // 0x6
+    field public static final int VOICE_UPLINK = 2; // 0x2
+  }
+
+  public static abstract interface MediaRecorder.OnErrorListener {
+    method public abstract void onError(android.media.MediaRecorder, int, int);
+  }
+
+  public static abstract interface MediaRecorder.OnInfoListener {
+    method public abstract void onInfo(android.media.MediaRecorder, int, int);
+  }
+
+  public final class MediaRecorder.OutputFormat {
+    field public static final int AAC_ADTS = 6; // 0x6
+    field public static final int AMR_NB = 3; // 0x3
+    field public static final int AMR_WB = 4; // 0x4
+    field public static final int DEFAULT = 0; // 0x0
+    field public static final int MPEG_4 = 2; // 0x2
+    field public static final deprecated int RAW_AMR = 3; // 0x3
+    field public static final int THREE_GPP = 1; // 0x1
+  }
+
+  public final class MediaRecorder.VideoEncoder {
+    field public static final int DEFAULT = 0; // 0x0
+    field public static final int H263 = 1; // 0x1
+    field public static final int H264 = 2; // 0x2
+    field public static final int MPEG_4_SP = 3; // 0x3
+  }
+
+  public final class MediaRecorder.VideoSource {
+    field public static final int CAMERA = 1; // 0x1
+    field public static final int DEFAULT = 0; // 0x0
+  }
+
+  public class MediaRouter {
+    method public void addCallback(int, android.media.MediaRouter.Callback);
+    method public void addUserRoute(android.media.MediaRouter.UserRouteInfo);
+    method public void clearUserRoutes();
+    method public android.media.MediaRouter.RouteCategory createRouteCategory(java.lang.CharSequence, boolean);
+    method public android.media.MediaRouter.RouteCategory createRouteCategory(int, boolean);
+    method public android.media.MediaRouter.UserRouteInfo createUserRoute(android.media.MediaRouter.RouteCategory);
+    method public android.media.MediaRouter.RouteCategory getCategoryAt(int);
+    method public int getCategoryCount();
+    method public android.media.MediaRouter.RouteInfo getRouteAt(int);
+    method public int getRouteCount();
+    method public android.media.MediaRouter.RouteInfo getSelectedRoute(int);
+    method public void removeCallback(android.media.MediaRouter.Callback);
+    method public void removeUserRoute(android.media.MediaRouter.UserRouteInfo);
+    method public void selectRoute(int, android.media.MediaRouter.RouteInfo);
+    field public static final int ROUTE_TYPE_LIVE_AUDIO = 1; // 0x1
+    field public static final int ROUTE_TYPE_LIVE_VIDEO = 2; // 0x2
+    field public static final int ROUTE_TYPE_USER = 8388608; // 0x800000
+  }
+
+  public static abstract class MediaRouter.Callback {
+    ctor public MediaRouter.Callback();
+    method public abstract void onRouteAdded(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public abstract void onRouteChanged(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public abstract void onRouteGrouped(android.media.MediaRouter, android.media.MediaRouter.RouteInfo, android.media.MediaRouter.RouteGroup, int);
+    method public void onRoutePresentationDisplayChanged(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public abstract void onRouteRemoved(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public abstract void onRouteSelected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo);
+    method public abstract void onRouteUngrouped(android.media.MediaRouter, android.media.MediaRouter.RouteInfo, android.media.MediaRouter.RouteGroup);
+    method public abstract void onRouteUnselected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo);
+    method public abstract void onRouteVolumeChanged(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+  }
+
+  public static class MediaRouter.RouteCategory {
+    method public java.lang.CharSequence getName();
+    method public java.lang.CharSequence getName(android.content.Context);
+    method public java.util.List<android.media.MediaRouter.RouteInfo> getRoutes(java.util.List<android.media.MediaRouter.RouteInfo>);
+    method public int getSupportedTypes();
+    method public boolean isGroupable();
+  }
+
+  public static class MediaRouter.RouteGroup extends android.media.MediaRouter.RouteInfo {
+    method public void addRoute(android.media.MediaRouter.RouteInfo);
+    method public void addRoute(android.media.MediaRouter.RouteInfo, int);
+    method public android.media.MediaRouter.RouteInfo getRouteAt(int);
+    method public int getRouteCount();
+    method public void removeRoute(android.media.MediaRouter.RouteInfo);
+    method public void removeRoute(int);
+    method public void setIconDrawable(android.graphics.drawable.Drawable);
+    method public void setIconResource(int);
+  }
+
+  public static class MediaRouter.RouteInfo {
+    method public android.media.MediaRouter.RouteCategory getCategory();
+    method public android.media.MediaRouter.RouteGroup getGroup();
+    method public android.graphics.drawable.Drawable getIconDrawable();
+    method public java.lang.CharSequence getName();
+    method public java.lang.CharSequence getName(android.content.Context);
+    method public int getPlaybackStream();
+    method public int getPlaybackType();
+    method public android.view.Display getPresentationDisplay();
+    method public java.lang.CharSequence getStatus();
+    method public int getSupportedTypes();
+    method public java.lang.Object getTag();
+    method public int getVolume();
+    method public int getVolumeHandling();
+    method public int getVolumeMax();
+    method public boolean isEnabled();
+    method public void requestSetVolume(int);
+    method public void requestUpdateVolume(int);
+    method public void setTag(java.lang.Object);
+    field public static final int PLAYBACK_TYPE_LOCAL = 0; // 0x0
+    field public static final int PLAYBACK_TYPE_REMOTE = 1; // 0x1
+    field public static final int PLAYBACK_VOLUME_FIXED = 0; // 0x0
+    field public static final int PLAYBACK_VOLUME_VARIABLE = 1; // 0x1
+  }
+
+  public static class MediaRouter.SimpleCallback extends android.media.MediaRouter.Callback {
+    ctor public MediaRouter.SimpleCallback();
+    method public void onRouteAdded(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public void onRouteChanged(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public void onRouteGrouped(android.media.MediaRouter, android.media.MediaRouter.RouteInfo, android.media.MediaRouter.RouteGroup, int);
+    method public void onRouteRemoved(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+    method public void onRouteSelected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo);
+    method public void onRouteUngrouped(android.media.MediaRouter, android.media.MediaRouter.RouteInfo, android.media.MediaRouter.RouteGroup);
+    method public void onRouteUnselected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo);
+    method public void onRouteVolumeChanged(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
+  }
+
+  public static class MediaRouter.UserRouteInfo extends android.media.MediaRouter.RouteInfo {
+    method public android.media.RemoteControlClient getRemoteControlClient();
+    method public void setIconDrawable(android.graphics.drawable.Drawable);
+    method public void setIconResource(int);
+    method public void setName(java.lang.CharSequence);
+    method public void setName(int);
+    method public void setPlaybackStream(int);
+    method public void setPlaybackType(int);
+    method public void setRemoteControlClient(android.media.RemoteControlClient);
+    method public void setStatus(java.lang.CharSequence);
+    method public void setVolume(int);
+    method public void setVolumeCallback(android.media.MediaRouter.VolumeCallback);
+    method public void setVolumeHandling(int);
+    method public void setVolumeMax(int);
+  }
+
+  public static abstract class MediaRouter.VolumeCallback {
+    ctor public MediaRouter.VolumeCallback();
+    method public abstract void onVolumeSetRequest(android.media.MediaRouter.RouteInfo, int);
+    method public abstract void onVolumeUpdateRequest(android.media.MediaRouter.RouteInfo, int);
+  }
+
+  public class MediaScannerConnection implements android.content.ServiceConnection {
+    ctor public MediaScannerConnection(android.content.Context, android.media.MediaScannerConnection.MediaScannerConnectionClient);
+    method public void connect();
+    method public void disconnect();
+    method public synchronized boolean isConnected();
+    method public void onServiceConnected(android.content.ComponentName, android.os.IBinder);
+    method public void onServiceDisconnected(android.content.ComponentName);
+    method public void scanFile(java.lang.String, java.lang.String);
+    method public static void scanFile(android.content.Context, java.lang.String[], java.lang.String[], android.media.MediaScannerConnection.OnScanCompletedListener);
+  }
+
+  public static abstract interface MediaScannerConnection.MediaScannerConnectionClient implements android.media.MediaScannerConnection.OnScanCompletedListener {
+    method public abstract void onMediaScannerConnected();
+    method public abstract void onScanCompleted(java.lang.String, android.net.Uri);
+  }
+
+  public static abstract interface MediaScannerConnection.OnScanCompletedListener {
+    method public abstract void onScanCompleted(java.lang.String, android.net.Uri);
+  }
+
+  public class MediaSyncEvent {
+    method public static android.media.MediaSyncEvent createEvent(int) throws java.lang.IllegalArgumentException;
+    method public int getAudioSessionId();
+    method public int getType();
+    method public android.media.MediaSyncEvent setAudioSessionId(int) throws java.lang.IllegalArgumentException;
+    field public static final int SYNC_EVENT_NONE = 0; // 0x0
+    field public static final int SYNC_EVENT_PRESENTATION_COMPLETE = 1; // 0x1
+  }
+
+  public class RemoteControlClient {
+    ctor public RemoteControlClient(android.app.PendingIntent);
+    ctor public RemoteControlClient(android.app.PendingIntent, android.os.Looper);
+    method public android.media.RemoteControlClient.MetadataEditor editMetadata(boolean);
+    method public void setPlaybackState(int);
+    method public void setTransportControlFlags(int);
+    field public static final int FLAG_KEY_MEDIA_FAST_FORWARD = 64; // 0x40
+    field public static final int FLAG_KEY_MEDIA_NEXT = 128; // 0x80
+    field public static final int FLAG_KEY_MEDIA_PAUSE = 16; // 0x10
+    field public static final int FLAG_KEY_MEDIA_PLAY = 4; // 0x4
+    field public static final int FLAG_KEY_MEDIA_PLAY_PAUSE = 8; // 0x8
+    field public static final int FLAG_KEY_MEDIA_PREVIOUS = 1; // 0x1
+    field public static final int FLAG_KEY_MEDIA_REWIND = 2; // 0x2
+    field public static final int FLAG_KEY_MEDIA_STOP = 32; // 0x20
+    field public static final int PLAYSTATE_BUFFERING = 8; // 0x8
+    field public static final int PLAYSTATE_ERROR = 9; // 0x9
+    field public static final int PLAYSTATE_FAST_FORWARDING = 4; // 0x4
+    field public static final int PLAYSTATE_PAUSED = 2; // 0x2
+    field public static final int PLAYSTATE_PLAYING = 3; // 0x3
+    field public static final int PLAYSTATE_REWINDING = 5; // 0x5
+    field public static final int PLAYSTATE_SKIPPING_BACKWARDS = 7; // 0x7
+    field public static final int PLAYSTATE_SKIPPING_FORWARDS = 6; // 0x6
+    field public static final int PLAYSTATE_STOPPED = 1; // 0x1
+  }
+
+  public class RemoteControlClient.MetadataEditor {
+    method public synchronized void apply();
+    method public synchronized void clear();
+    method public synchronized android.media.RemoteControlClient.MetadataEditor putBitmap(int, android.graphics.Bitmap) throws java.lang.IllegalArgumentException;
+    method public synchronized android.media.RemoteControlClient.MetadataEditor putLong(int, long) throws java.lang.IllegalArgumentException;
+    method public synchronized android.media.RemoteControlClient.MetadataEditor putString(int, java.lang.String) throws java.lang.IllegalArgumentException;
+    field public static final int BITMAP_KEY_ARTWORK = 100; // 0x64
+  }
+
+  public class Ringtone {
+    method public int getStreamType();
+    method public java.lang.String getTitle(android.content.Context);
+    method public boolean isPlaying();
+    method public void play();
+    method public void setStreamType(int);
+    method public void stop();
+  }
+
+  public class RingtoneManager {
+    ctor public RingtoneManager(android.app.Activity);
+    ctor public RingtoneManager(android.content.Context);
+    method public static android.net.Uri getActualDefaultRingtoneUri(android.content.Context, int);
+    method public android.database.Cursor getCursor();
+    method public static int getDefaultType(android.net.Uri);
+    method public static android.net.Uri getDefaultUri(int);
+    method public boolean getIncludeDrm();
+    method public android.media.Ringtone getRingtone(int);
+    method public static android.media.Ringtone getRingtone(android.content.Context, android.net.Uri);
+    method public int getRingtonePosition(android.net.Uri);
+    method public android.net.Uri getRingtoneUri(int);
+    method public boolean getStopPreviousRingtone();
+    method public static android.net.Uri getValidRingtoneUri(android.content.Context);
+    method public int inferStreamType();
+    method public static boolean isDefault(android.net.Uri);
+    method public static void setActualDefaultRingtoneUri(android.content.Context, int, android.net.Uri);
+    method public void setIncludeDrm(boolean);
+    method public void setStopPreviousRingtone(boolean);
+    method public void setType(int);
+    method public void stopPreviousRingtone();
+    field public static final java.lang.String ACTION_RINGTONE_PICKER = "android.intent.action.RINGTONE_PICKER";
+    field public static final java.lang.String EXTRA_RINGTONE_DEFAULT_URI = "android.intent.extra.ringtone.DEFAULT_URI";
+    field public static final java.lang.String EXTRA_RINGTONE_EXISTING_URI = "android.intent.extra.ringtone.EXISTING_URI";
+    field public static final java.lang.String EXTRA_RINGTONE_INCLUDE_DRM = "android.intent.extra.ringtone.INCLUDE_DRM";
+    field public static final java.lang.String EXTRA_RINGTONE_PICKED_URI = "android.intent.extra.ringtone.PICKED_URI";
+    field public static final java.lang.String EXTRA_RINGTONE_SHOW_DEFAULT = "android.intent.extra.ringtone.SHOW_DEFAULT";
+    field public static final java.lang.String EXTRA_RINGTONE_SHOW_SILENT = "android.intent.extra.ringtone.SHOW_SILENT";
+    field public static final java.lang.String EXTRA_RINGTONE_TITLE = "android.intent.extra.ringtone.TITLE";
+    field public static final java.lang.String EXTRA_RINGTONE_TYPE = "android.intent.extra.ringtone.TYPE";
+    field public static final int ID_COLUMN_INDEX = 0; // 0x0
+    field public static final int TITLE_COLUMN_INDEX = 1; // 0x1
+    field public static final int TYPE_ALARM = 4; // 0x4
+    field public static final int TYPE_ALL = 7; // 0x7
+    field public static final int TYPE_NOTIFICATION = 2; // 0x2
+    field public static final int TYPE_RINGTONE = 1; // 0x1
+    field public static final int URI_COLUMN_INDEX = 2; // 0x2
+  }
+
+  public class SoundPool {
+    ctor public SoundPool(int, int, int);
+    method public final void autoPause();
+    method public final void autoResume();
+    method public int load(java.lang.String, int);
+    method public int load(android.content.Context, int, int);
+    method public int load(android.content.res.AssetFileDescriptor, int);
+    method public int load(java.io.FileDescriptor, long, long, int);
+    method public final void pause(int);
+    method public final int play(int, float, float, int, int, float);
+    method public final void release();
+    method public final void resume(int);
+    method public final void setLoop(int, int);
+    method public void setOnLoadCompleteListener(android.media.SoundPool.OnLoadCompleteListener);
+    method public final void setPriority(int, int);
+    method public final void setRate(int, float);
+    method public final void setVolume(int, float, float);
+    method public final void stop(int);
+    method public final boolean unload(int);
+  }
+
+  public static abstract interface SoundPool.OnLoadCompleteListener {
+    method public abstract void onLoadComplete(android.media.SoundPool, int, int);
+  }
+
+  public class ThumbnailUtils {
+    ctor public ThumbnailUtils();
+    method public static android.graphics.Bitmap createVideoThumbnail(java.lang.String, int);
+    method public static android.graphics.Bitmap extractThumbnail(android.graphics.Bitmap, int, int);
+    method public static android.graphics.Bitmap extractThumbnail(android.graphics.Bitmap, int, int, int);
+    field public static final int OPTIONS_RECYCLE_INPUT = 2; // 0x2
+  }
+
+  public final class TimedText {
+    method public android.graphics.Rect getBounds();
+    method public java.lang.String getText();
+  }
+
+  public class ToneGenerator {
+    ctor public ToneGenerator(int, int);
+    method public final int getAudioSessionId();
+    method public void release();
+    method public boolean startTone(int);
+    method public boolean startTone(int, int);
+    method public void stopTone();
+    field public static final int MAX_VOLUME = 100; // 0x64
+    field public static final int MIN_VOLUME = 0; // 0x0
+    field public static final int TONE_CDMA_ABBR_ALERT = 97; // 0x61
+    field public static final int TONE_CDMA_ABBR_INTERCEPT = 37; // 0x25
+    field public static final int TONE_CDMA_ABBR_REORDER = 39; // 0x27
+    field public static final int TONE_CDMA_ALERT_AUTOREDIAL_LITE = 87; // 0x57
+    field public static final int TONE_CDMA_ALERT_CALL_GUARD = 93; // 0x5d
+    field public static final int TONE_CDMA_ALERT_INCALL_LITE = 91; // 0x5b
+    field public static final int TONE_CDMA_ALERT_NETWORK_LITE = 86; // 0x56
+    field public static final int TONE_CDMA_ANSWER = 42; // 0x2a
+    field public static final int TONE_CDMA_CALLDROP_LITE = 95; // 0x5f
+    field public static final int TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP = 46; // 0x2e
+    field public static final int TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL = 45; // 0x2d
+    field public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PAT3 = 48; // 0x30
+    field public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PAT5 = 50; // 0x32
+    field public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PAT6 = 51; // 0x33
+    field public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PAT7 = 52; // 0x34
+    field public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PING_RING = 49; // 0x31
+    field public static final int TONE_CDMA_CALL_SIGNAL_ISDN_SP_PRI = 47; // 0x2f
+    field public static final int TONE_CDMA_CONFIRM = 41; // 0x29
+    field public static final int TONE_CDMA_DIAL_TONE_LITE = 34; // 0x22
+    field public static final int TONE_CDMA_EMERGENCY_RINGBACK = 92; // 0x5c
+    field public static final int TONE_CDMA_HIGH_L = 53; // 0x35
+    field public static final int TONE_CDMA_HIGH_PBX_L = 71; // 0x47
+    field public static final int TONE_CDMA_HIGH_PBX_SLS = 80; // 0x50
+    field public static final int TONE_CDMA_HIGH_PBX_SS = 74; // 0x4a
+    field public static final int TONE_CDMA_HIGH_PBX_SSL = 77; // 0x4d
+    field public static final int TONE_CDMA_HIGH_PBX_S_X4 = 83; // 0x53
+    field public static final int TONE_CDMA_HIGH_SLS = 65; // 0x41
+    field public static final int TONE_CDMA_HIGH_SS = 56; // 0x38
+    field public static final int TONE_CDMA_HIGH_SSL = 59; // 0x3b
+    field public static final int TONE_CDMA_HIGH_SS_2 = 62; // 0x3e
+    field public static final int TONE_CDMA_HIGH_S_X4 = 68; // 0x44
+    field public static final int TONE_CDMA_INTERCEPT = 36; // 0x24
+    field public static final int TONE_CDMA_KEYPAD_VOLUME_KEY_LITE = 89; // 0x59
+    field public static final int TONE_CDMA_LOW_L = 55; // 0x37
+    field public static final int TONE_CDMA_LOW_PBX_L = 73; // 0x49
+    field public static final int TONE_CDMA_LOW_PBX_SLS = 82; // 0x52
+    field public static final int TONE_CDMA_LOW_PBX_SS = 76; // 0x4c
+    field public static final int TONE_CDMA_LOW_PBX_SSL = 79; // 0x4f
+    field public static final int TONE_CDMA_LOW_PBX_S_X4 = 85; // 0x55
+    field public static final int TONE_CDMA_LOW_SLS = 67; // 0x43
+    field public static final int TONE_CDMA_LOW_SS = 58; // 0x3a
+    field public static final int TONE_CDMA_LOW_SSL = 61; // 0x3d
+    field public static final int TONE_CDMA_LOW_SS_2 = 64; // 0x40
+    field public static final int TONE_CDMA_LOW_S_X4 = 70; // 0x46
+    field public static final int TONE_CDMA_MED_L = 54; // 0x36
+    field public static final int TONE_CDMA_MED_PBX_L = 72; // 0x48
+    field public static final int TONE_CDMA_MED_PBX_SLS = 81; // 0x51
+    field public static final int TONE_CDMA_MED_PBX_SS = 75; // 0x4b
+    field public static final int TONE_CDMA_MED_PBX_SSL = 78; // 0x4e
+    field public static final int TONE_CDMA_MED_PBX_S_X4 = 84; // 0x54
+    field public static final int TONE_CDMA_MED_SLS = 66; // 0x42
+    field public static final int TONE_CDMA_MED_SS = 57; // 0x39
+    field public static final int TONE_CDMA_MED_SSL = 60; // 0x3c
+    field public static final int TONE_CDMA_MED_SS_2 = 63; // 0x3f
+    field public static final int TONE_CDMA_MED_S_X4 = 69; // 0x45
+    field public static final int TONE_CDMA_NETWORK_BUSY = 40; // 0x28
+    field public static final int TONE_CDMA_NETWORK_BUSY_ONE_SHOT = 96; // 0x60
+    field public static final int TONE_CDMA_NETWORK_CALLWAITING = 43; // 0x2b
+    field public static final int TONE_CDMA_NETWORK_USA_RINGBACK = 35; // 0x23
+    field public static final int TONE_CDMA_ONE_MIN_BEEP = 88; // 0x58
+    field public static final int TONE_CDMA_PIP = 44; // 0x2c
+    field public static final int TONE_CDMA_PRESSHOLDKEY_LITE = 90; // 0x5a
+    field public static final int TONE_CDMA_REORDER = 38; // 0x26
+    field public static final int TONE_CDMA_SIGNAL_OFF = 98; // 0x62
+    field public static final int TONE_CDMA_SOFT_ERROR_LITE = 94; // 0x5e
+    field public static final int TONE_DTMF_0 = 0; // 0x0
+    field public static final int TONE_DTMF_1 = 1; // 0x1
+    field public static final int TONE_DTMF_2 = 2; // 0x2
+    field public static final int TONE_DTMF_3 = 3; // 0x3
+    field public static final int TONE_DTMF_4 = 4; // 0x4
+    field public static final int TONE_DTMF_5 = 5; // 0x5
+    field public static final int TONE_DTMF_6 = 6; // 0x6
+    field public static final int TONE_DTMF_7 = 7; // 0x7
+    field public static final int TONE_DTMF_8 = 8; // 0x8
+    field public static final int TONE_DTMF_9 = 9; // 0x9
+    field public static final int TONE_DTMF_A = 12; // 0xc
+    field public static final int TONE_DTMF_B = 13; // 0xd
+    field public static final int TONE_DTMF_C = 14; // 0xe
+    field public static final int TONE_DTMF_D = 15; // 0xf
+    field public static final int TONE_DTMF_P = 11; // 0xb
+    field public static final int TONE_DTMF_S = 10; // 0xa
+    field public static final int TONE_PROP_ACK = 25; // 0x19
+    field public static final int TONE_PROP_BEEP = 24; // 0x18
+    field public static final int TONE_PROP_BEEP2 = 28; // 0x1c
+    field public static final int TONE_PROP_NACK = 26; // 0x1a
+    field public static final int TONE_PROP_PROMPT = 27; // 0x1b
+    field public static final int TONE_SUP_BUSY = 17; // 0x11
+    field public static final int TONE_SUP_CALL_WAITING = 22; // 0x16
+    field public static final int TONE_SUP_CONFIRM = 32; // 0x20
+    field public static final int TONE_SUP_CONGESTION = 18; // 0x12
+    field public static final int TONE_SUP_CONGESTION_ABBREV = 31; // 0x1f
+    field public static final int TONE_SUP_DIAL = 16; // 0x10
+    field public static final int TONE_SUP_ERROR = 21; // 0x15
+    field public static final int TONE_SUP_INTERCEPT = 29; // 0x1d
+    field public static final int TONE_SUP_INTERCEPT_ABBREV = 30; // 0x1e
+    field public static final int TONE_SUP_PIP = 33; // 0x21
+    field public static final int TONE_SUP_RADIO_ACK = 19; // 0x13
+    field public static final int TONE_SUP_RADIO_NOTAVAIL = 20; // 0x14
+    field public static final int TONE_SUP_RINGTONE = 23; // 0x17
+  }
+
+}
+
+package android.media.audiofx {
+
+  public class AcousticEchoCanceler extends android.media.audiofx.AudioEffect {
+    method public static android.media.audiofx.AcousticEchoCanceler create(int);
+    method public static boolean isAvailable();
+  }
+
+  public class AudioEffect {
+    method public android.media.audiofx.AudioEffect.Descriptor getDescriptor() throws java.lang.IllegalStateException;
+    method public boolean getEnabled() throws java.lang.IllegalStateException;
+    method public int getId() throws java.lang.IllegalStateException;
+    method public boolean hasControl() throws java.lang.IllegalStateException;
+    method public static android.media.audiofx.AudioEffect.Descriptor[] queryEffects();
+    method public void release();
+    method public void setControlStatusListener(android.media.audiofx.AudioEffect.OnControlStatusChangeListener);
+    method public void setEnableStatusListener(android.media.audiofx.AudioEffect.OnEnableStatusChangeListener);
+    method public int setEnabled(boolean) throws java.lang.IllegalStateException;
+    field public static final java.lang.String ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION = "android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION";
+    field public static final java.lang.String ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL = "android.media.action.DISPLAY_AUDIO_EFFECT_CONTROL_PANEL";
+    field public static final java.lang.String ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION = "android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION";
+    field public static final int ALREADY_EXISTS = -2; // 0xfffffffe
+    field public static final int CONTENT_TYPE_GAME = 2; // 0x2
+    field public static final int CONTENT_TYPE_MOVIE = 1; // 0x1
+    field public static final int CONTENT_TYPE_MUSIC = 0; // 0x0
+    field public static final int CONTENT_TYPE_VOICE = 3; // 0x3
+    field public static final java.lang.String EFFECT_AUXILIARY = "Auxiliary";
+    field public static final java.lang.String EFFECT_INSERT = "Insert";
+    field public static final int ERROR = -1; // 0xffffffff
+    field public static final int ERROR_BAD_VALUE = -4; // 0xfffffffc
+    field public static final int ERROR_DEAD_OBJECT = -7; // 0xfffffff9
+    field public static final int ERROR_INVALID_OPERATION = -5; // 0xfffffffb
+    field public static final int ERROR_NO_INIT = -3; // 0xfffffffd
+    field public static final int ERROR_NO_MEMORY = -6; // 0xfffffffa
+    field public static final java.lang.String EXTRA_AUDIO_SESSION = "android.media.extra.AUDIO_SESSION";
+    field public static final java.lang.String EXTRA_CONTENT_TYPE = "android.media.extra.CONTENT_TYPE";
+    field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.extra.PACKAGE_NAME";
+    field public static final int SUCCESS = 0; // 0x0
+  }
+
+  public static class AudioEffect.Descriptor {
+    ctor public AudioEffect.Descriptor();
+    ctor public AudioEffect.Descriptor(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    field public java.lang.String connectMode;
+    field public java.lang.String implementor;
+    field public java.lang.String name;
+    field public java.util.UUID type;
+    field public java.util.UUID uuid;
+  }
+
+  public static abstract interface AudioEffect.OnControlStatusChangeListener {
+    method public abstract void onControlStatusChange(android.media.audiofx.AudioEffect, boolean);
+  }
+
+  public static abstract interface AudioEffect.OnEnableStatusChangeListener {
+    method public abstract void onEnableStatusChange(android.media.audiofx.AudioEffect, boolean);
+  }
+
+  public class AutomaticGainControl extends android.media.audiofx.AudioEffect {
+    method public static android.media.audiofx.AutomaticGainControl create(int);
+    method public static boolean isAvailable();
+  }
+
+  public class BassBoost extends android.media.audiofx.AudioEffect {
+    ctor public BassBoost(int, int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.RuntimeException, java.lang.UnsupportedOperationException;
+    method public android.media.audiofx.BassBoost.Settings getProperties() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public short getRoundedStrength() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public boolean getStrengthSupported();
+    method public void setParameterListener(android.media.audiofx.BassBoost.OnParameterChangeListener);
+    method public void setProperties(android.media.audiofx.BassBoost.Settings) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setStrength(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    field public static final int PARAM_STRENGTH = 1; // 0x1
+    field public static final int PARAM_STRENGTH_SUPPORTED = 0; // 0x0
+  }
+
+  public static abstract interface BassBoost.OnParameterChangeListener {
+    method public abstract void onParameterChange(android.media.audiofx.BassBoost, int, int, short);
+  }
+
+  public static class BassBoost.Settings {
+    ctor public BassBoost.Settings();
+    ctor public BassBoost.Settings(java.lang.String);
+    field public short strength;
+  }
+
+  public class EnvironmentalReverb extends android.media.audiofx.AudioEffect {
+    ctor public EnvironmentalReverb(int, int) throws java.lang.IllegalArgumentException, java.lang.RuntimeException, java.lang.UnsupportedOperationException;
+    method public short getDecayHFRatio() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public int getDecayTime() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public short getDensity() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public short getDiffusion() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public android.media.audiofx.EnvironmentalReverb.Settings getProperties() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public int getReflectionsDelay() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public short getReflectionsLevel() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public int getReverbDelay() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public short getReverbLevel() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public short getRoomHFLevel() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public short getRoomLevel() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setDecayHFRatio(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setDecayTime(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setDensity(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setDiffusion(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setParameterListener(android.media.audiofx.EnvironmentalReverb.OnParameterChangeListener);
+    method public void setProperties(android.media.audiofx.EnvironmentalReverb.Settings) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setReflectionsDelay(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setReflectionsLevel(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setReverbDelay(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setReverbLevel(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setRoomHFLevel(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setRoomLevel(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    field public static final int PARAM_DECAY_HF_RATIO = 3; // 0x3
+    field public static final int PARAM_DECAY_TIME = 2; // 0x2
+    field public static final int PARAM_DENSITY = 9; // 0x9
+    field public static final int PARAM_DIFFUSION = 8; // 0x8
+    field public static final int PARAM_REFLECTIONS_DELAY = 5; // 0x5
+    field public static final int PARAM_REFLECTIONS_LEVEL = 4; // 0x4
+    field public static final int PARAM_REVERB_DELAY = 7; // 0x7
+    field public static final int PARAM_REVERB_LEVEL = 6; // 0x6
+    field public static final int PARAM_ROOM_HF_LEVEL = 1; // 0x1
+    field public static final int PARAM_ROOM_LEVEL = 0; // 0x0
+  }
+
+  public static abstract interface EnvironmentalReverb.OnParameterChangeListener {
+    method public abstract void onParameterChange(android.media.audiofx.EnvironmentalReverb, int, int, int);
+  }
+
+  public static class EnvironmentalReverb.Settings {
+    ctor public EnvironmentalReverb.Settings();
+    ctor public EnvironmentalReverb.Settings(java.lang.String);
+    field public short decayHFRatio;
+    field public int decayTime;
+    field public short density;
+    field public short diffusion;
+    field public int reflectionsDelay;
+    field public short reflectionsLevel;
+    field public int reverbDelay;
+    field public short reverbLevel;
+    field public short roomHFLevel;
+    field public short roomLevel;
+  }
+
+  public class Equalizer extends android.media.audiofx.AudioEffect {
+    ctor public Equalizer(int, int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.RuntimeException, java.lang.UnsupportedOperationException;
+    method public short getBand(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public int[] getBandFreqRange(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public short getBandLevel(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public short[] getBandLevelRange() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public int getCenterFreq(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public short getCurrentPreset() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public short getNumberOfBands() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public short getNumberOfPresets() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public java.lang.String getPresetName(short);
+    method public android.media.audiofx.Equalizer.Settings getProperties() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setBandLevel(short, short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setParameterListener(android.media.audiofx.Equalizer.OnParameterChangeListener);
+    method public void setProperties(android.media.audiofx.Equalizer.Settings) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void usePreset(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    field public static final int PARAM_BAND_FREQ_RANGE = 4; // 0x4
+    field public static final int PARAM_BAND_LEVEL = 2; // 0x2
+    field public static final int PARAM_CENTER_FREQ = 3; // 0x3
+    field public static final int PARAM_CURRENT_PRESET = 6; // 0x6
+    field public static final int PARAM_GET_BAND = 5; // 0x5
+    field public static final int PARAM_GET_NUM_OF_PRESETS = 7; // 0x7
+    field public static final int PARAM_GET_PRESET_NAME = 8; // 0x8
+    field public static final int PARAM_LEVEL_RANGE = 1; // 0x1
+    field public static final int PARAM_NUM_BANDS = 0; // 0x0
+    field public static final int PARAM_STRING_SIZE_MAX = 32; // 0x20
+  }
+
+  public static abstract interface Equalizer.OnParameterChangeListener {
+    method public abstract void onParameterChange(android.media.audiofx.Equalizer, int, int, int, int);
+  }
+
+  public static class Equalizer.Settings {
+    ctor public Equalizer.Settings();
+    ctor public Equalizer.Settings(java.lang.String);
+    field public short[] bandLevels;
+    field public short curPreset;
+    field public short numBands;
+  }
+
+  public class NoiseSuppressor extends android.media.audiofx.AudioEffect {
+    method public static android.media.audiofx.NoiseSuppressor create(int);
+    method public static boolean isAvailable();
+  }
+
+  public class PresetReverb extends android.media.audiofx.AudioEffect {
+    ctor public PresetReverb(int, int) throws java.lang.IllegalArgumentException, java.lang.RuntimeException, java.lang.UnsupportedOperationException;
+    method public short getPreset() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public android.media.audiofx.PresetReverb.Settings getProperties() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setParameterListener(android.media.audiofx.PresetReverb.OnParameterChangeListener);
+    method public void setPreset(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setProperties(android.media.audiofx.PresetReverb.Settings) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    field public static final int PARAM_PRESET = 0; // 0x0
+    field public static final short PRESET_LARGEHALL = 5; // 0x5
+    field public static final short PRESET_LARGEROOM = 3; // 0x3
+    field public static final short PRESET_MEDIUMHALL = 4; // 0x4
+    field public static final short PRESET_MEDIUMROOM = 2; // 0x2
+    field public static final short PRESET_NONE = 0; // 0x0
+    field public static final short PRESET_PLATE = 6; // 0x6
+    field public static final short PRESET_SMALLROOM = 1; // 0x1
+  }
+
+  public static abstract interface PresetReverb.OnParameterChangeListener {
+    method public abstract void onParameterChange(android.media.audiofx.PresetReverb, int, int, short);
+  }
+
+  public static class PresetReverb.Settings {
+    ctor public PresetReverb.Settings();
+    ctor public PresetReverb.Settings(java.lang.String);
+    field public short preset;
+  }
+
+  public class Virtualizer extends android.media.audiofx.AudioEffect {
+    ctor public Virtualizer(int, int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.RuntimeException, java.lang.UnsupportedOperationException;
+    method public android.media.audiofx.Virtualizer.Settings getProperties() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public short getRoundedStrength() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public boolean getStrengthSupported();
+    method public void setParameterListener(android.media.audiofx.Virtualizer.OnParameterChangeListener);
+    method public void setProperties(android.media.audiofx.Virtualizer.Settings) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    method public void setStrength(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+    field public static final int PARAM_STRENGTH = 1; // 0x1
+    field public static final int PARAM_STRENGTH_SUPPORTED = 0; // 0x0
+  }
+
+  public static abstract interface Virtualizer.OnParameterChangeListener {
+    method public abstract void onParameterChange(android.media.audiofx.Virtualizer, int, int, short);
+  }
+
+  public static class Virtualizer.Settings {
+    ctor public Virtualizer.Settings();
+    ctor public Virtualizer.Settings(java.lang.String);
+    field public short strength;
+  }
+
+  public class Visualizer {
+    ctor public Visualizer(int) throws java.lang.RuntimeException, java.lang.UnsupportedOperationException;
+    method public int getCaptureSize() throws java.lang.IllegalStateException;
+    method public static int[] getCaptureSizeRange();
+    method public boolean getEnabled();
+    method public int getFft(byte[]) throws java.lang.IllegalStateException;
+    method public static int getMaxCaptureRate();
+    method public int getSamplingRate() throws java.lang.IllegalStateException;
+    method public int getScalingMode() throws java.lang.IllegalStateException;
+    method public int getWaveForm(byte[]) throws java.lang.IllegalStateException;
+    method public void release();
+    method public int setCaptureSize(int) throws java.lang.IllegalStateException;
+    method public int setDataCaptureListener(android.media.audiofx.Visualizer.OnDataCaptureListener, int, boolean, boolean);
+    method public int setEnabled(boolean) throws java.lang.IllegalStateException;
+    method public int setScalingMode(int) throws java.lang.IllegalStateException;
+    field public static final int ALREADY_EXISTS = -2; // 0xfffffffe
+    field public static final int ERROR = -1; // 0xffffffff
+    field public static final int ERROR_BAD_VALUE = -4; // 0xfffffffc
+    field public static final int ERROR_DEAD_OBJECT = -7; // 0xfffffff9
+    field public static final int ERROR_INVALID_OPERATION = -5; // 0xfffffffb
+    field public static final int ERROR_NO_INIT = -3; // 0xfffffffd
+    field public static final int ERROR_NO_MEMORY = -6; // 0xfffffffa
+    field public static final int SCALING_MODE_AS_PLAYED = 1; // 0x1
+    field public static final int SCALING_MODE_NORMALIZED = 0; // 0x0
+    field public static final int STATE_ENABLED = 2; // 0x2
+    field public static final int STATE_INITIALIZED = 1; // 0x1
+    field public static final int STATE_UNINITIALIZED = 0; // 0x0
+    field public static final int SUCCESS = 0; // 0x0
+  }
+
+  public static abstract interface Visualizer.OnDataCaptureListener {
+    method public abstract void onFftDataCapture(android.media.audiofx.Visualizer, byte[], int);
+    method public abstract void onWaveFormDataCapture(android.media.audiofx.Visualizer, byte[], int);
+  }
+
+}
+
+package android.media.effect {
+
+  public abstract class Effect {
+    ctor public Effect();
+    method public abstract void apply(int, int, int, int);
+    method public abstract java.lang.String getName();
+    method public abstract void release();
+    method public abstract void setParameter(java.lang.String, java.lang.Object);
+    method public void setUpdateListener(android.media.effect.EffectUpdateListener);
+  }
+
+  public class EffectContext {
+    method public static android.media.effect.EffectContext createWithCurrentGlContext();
+    method public android.media.effect.EffectFactory getFactory();
+    method public void release();
+  }
+
+  public class EffectFactory {
+    method public android.media.effect.Effect createEffect(java.lang.String);
+    method public static boolean isEffectSupported(java.lang.String);
+    field public static final java.lang.String EFFECT_AUTOFIX = "android.media.effect.effects.AutoFixEffect";
+    field public static final java.lang.String EFFECT_BACKDROPPER = "android.media.effect.effects.BackDropperEffect";
+    field public static final java.lang.String EFFECT_BITMAPOVERLAY = "android.media.effect.effects.BitmapOverlayEffect";
+    field public static final java.lang.String EFFECT_BLACKWHITE = "android.media.effect.effects.BlackWhiteEffect";
+    field public static final java.lang.String EFFECT_BRIGHTNESS = "android.media.effect.effects.BrightnessEffect";
+    field public static final java.lang.String EFFECT_CONTRAST = "android.media.effect.effects.ContrastEffect";
+    field public static final java.lang.String EFFECT_CROP = "android.media.effect.effects.CropEffect";
+    field public static final java.lang.String EFFECT_CROSSPROCESS = "android.media.effect.effects.CrossProcessEffect";
+    field public static final java.lang.String EFFECT_DOCUMENTARY = "android.media.effect.effects.DocumentaryEffect";
+    field public static final java.lang.String EFFECT_DUOTONE = "android.media.effect.effects.DuotoneEffect";
+    field public static final java.lang.String EFFECT_FILLLIGHT = "android.media.effect.effects.FillLightEffect";
+    field public static final java.lang.String EFFECT_FISHEYE = "android.media.effect.effects.FisheyeEffect";
+    field public static final java.lang.String EFFECT_FLIP = "android.media.effect.effects.FlipEffect";
+    field public static final java.lang.String EFFECT_GRAIN = "android.media.effect.effects.GrainEffect";
+    field public static final java.lang.String EFFECT_GRAYSCALE = "android.media.effect.effects.GrayscaleEffect";
+    field public static final java.lang.String EFFECT_LOMOISH = "android.media.effect.effects.LomoishEffect";
+    field public static final java.lang.String EFFECT_NEGATIVE = "android.media.effect.effects.NegativeEffect";
+    field public static final java.lang.String EFFECT_POSTERIZE = "android.media.effect.effects.PosterizeEffect";
+    field public static final java.lang.String EFFECT_REDEYE = "android.media.effect.effects.RedEyeEffect";
+    field public static final java.lang.String EFFECT_ROTATE = "android.media.effect.effects.RotateEffect";
+    field public static final java.lang.String EFFECT_SATURATE = "android.media.effect.effects.SaturateEffect";
+    field public static final java.lang.String EFFECT_SEPIA = "android.media.effect.effects.SepiaEffect";
+    field public static final java.lang.String EFFECT_SHARPEN = "android.media.effect.effects.SharpenEffect";
+    field public static final java.lang.String EFFECT_STRAIGHTEN = "android.media.effect.effects.StraightenEffect";
+    field public static final java.lang.String EFFECT_TEMPERATURE = "android.media.effect.effects.ColorTemperatureEffect";
+    field public static final java.lang.String EFFECT_TINT = "android.media.effect.effects.TintEffect";
+    field public static final java.lang.String EFFECT_VIGNETTE = "android.media.effect.effects.VignetteEffect";
+  }
+
+  public abstract interface EffectUpdateListener {
+    method public abstract void onEffectUpdated(android.media.effect.Effect, java.lang.Object);
+  }
+
+}
+
+package android.mtp {
+
+  public final class MtpConstants {
+    ctor public MtpConstants();
+    method public static boolean isAbstractObject(int);
+    field public static final int ASSOCIATION_TYPE_GENERIC_FOLDER = 1; // 0x1
+    field public static final int FORMAT_3GP_CONTAINER = 47492; // 0xb984
+    field public static final int FORMAT_AAC = 47363; // 0xb903
+    field public static final int FORMAT_ABSTRACT_AUDIO_ALBUM = 47619; // 0xba03
+    field public static final int FORMAT_ABSTRACT_AUDIO_PLAYLIST = 47625; // 0xba09
+    field public static final int FORMAT_ABSTRACT_AV_PLAYLIST = 47621; // 0xba05
+    field public static final int FORMAT_ABSTRACT_DOCUMENT = 47745; // 0xba81
+    field public static final int FORMAT_ABSTRACT_IMAGE_ALBUM = 47618; // 0xba02
+    field public static final int FORMAT_ABSTRACT_MEDIACAST = 47627; // 0xba0b
+    field public static final int FORMAT_ABSTRACT_MULTIMEDIA_ALBUM = 47617; // 0xba01
+    field public static final int FORMAT_ABSTRACT_VIDEO_ALBUM = 47620; // 0xba04
+    field public static final int FORMAT_ABSTRACT_VIDEO_PLAYLIST = 47626; // 0xba0a
+    field public static final int FORMAT_AIFF = 12295; // 0x3007
+    field public static final int FORMAT_ASF = 12300; // 0x300c
+    field public static final int FORMAT_ASSOCIATION = 12289; // 0x3001
+    field public static final int FORMAT_ASX_PLAYLIST = 47635; // 0xba13
+    field public static final int FORMAT_AUDIBLE = 47364; // 0xb904
+    field public static final int FORMAT_AVI = 12298; // 0x300a
+    field public static final int FORMAT_BMP = 14340; // 0x3804
+    field public static final int FORMAT_DPOF = 12294; // 0x3006
+    field public static final int FORMAT_EXECUTABLE = 12291; // 0x3003
+    field public static final int FORMAT_EXIF_JPEG = 14337; // 0x3801
+    field public static final int FORMAT_FLAC = 47366; // 0xb906
+    field public static final int FORMAT_GIF = 14343; // 0x3807
+    field public static final int FORMAT_HTML = 12293; // 0x3005
+    field public static final int FORMAT_JFIF = 14344; // 0x3808
+    field public static final int FORMAT_JP2 = 14351; // 0x380f
+    field public static final int FORMAT_JPX = 14352; // 0x3810
+    field public static final int FORMAT_M3U_PLAYLIST = 47633; // 0xba11
+    field public static final int FORMAT_MP2 = 47491; // 0xb983
+    field public static final int FORMAT_MP3 = 12297; // 0x3009
+    field public static final int FORMAT_MP4_CONTAINER = 47490; // 0xb982
+    field public static final int FORMAT_MPEG = 12299; // 0x300b
+    field public static final int FORMAT_MPL_PLAYLIST = 47634; // 0xba12
+    field public static final int FORMAT_MS_EXCEL_SPREADSHEET = 47749; // 0xba85
+    field public static final int FORMAT_MS_POWERPOINT_PRESENTATION = 47750; // 0xba86
+    field public static final int FORMAT_MS_WORD_DOCUMENT = 47747; // 0xba83
+    field public static final int FORMAT_OGG = 47362; // 0xb902
+    field public static final int FORMAT_PICT = 14346; // 0x380a
+    field public static final int FORMAT_PLS_PLAYLIST = 47636; // 0xba14
+    field public static final int FORMAT_PNG = 14347; // 0x380b
+    field public static final int FORMAT_SCRIPT = 12290; // 0x3002
+    field public static final int FORMAT_TEXT = 12292; // 0x3004
+    field public static final int FORMAT_TIFF = 14349; // 0x380d
+    field public static final int FORMAT_TIFF_EP = 14338; // 0x3802
+    field public static final int FORMAT_UNDEFINED = 12288; // 0x3000
+    field public static final int FORMAT_UNDEFINED_AUDIO = 47360; // 0xb900
+    field public static final int FORMAT_UNDEFINED_COLLECTION = 47616; // 0xba00
+    field public static final int FORMAT_UNDEFINED_DOCUMENT = 47744; // 0xba80
+    field public static final int FORMAT_UNDEFINED_FIRMWARE = 47106; // 0xb802
+    field public static final int FORMAT_UNDEFINED_VIDEO = 47488; // 0xb980
+    field public static final int FORMAT_WAV = 12296; // 0x3008
+    field public static final int FORMAT_WINDOWS_IMAGE_FORMAT = 47233; // 0xb881
+    field public static final int FORMAT_WMA = 47361; // 0xb901
+    field public static final int FORMAT_WMV = 47489; // 0xb981
+    field public static final int FORMAT_WPL_PLAYLIST = 47632; // 0xba10
+    field public static final int FORMAT_XML_DOCUMENT = 47746; // 0xba82
+    field public static final int PROTECTION_STATUS_NONE = 0; // 0x0
+    field public static final int PROTECTION_STATUS_NON_TRANSFERABLE_DATA = 32771; // 0x8003
+    field public static final int PROTECTION_STATUS_READ_ONLY = 32769; // 0x8001
+    field public static final int PROTECTION_STATUS_READ_ONLY_DATA = 32770; // 0x8002
+  }
+
+  public final class MtpDevice {
+    ctor public MtpDevice(android.hardware.usb.UsbDevice);
+    method public void close();
+    method public boolean deleteObject(int);
+    method public int getDeviceId();
+    method public android.mtp.MtpDeviceInfo getDeviceInfo();
+    method public java.lang.String getDeviceName();
+    method public byte[] getObject(int, int);
+    method public int[] getObjectHandles(int, int, int);
+    method public android.mtp.MtpObjectInfo getObjectInfo(int);
+    method public long getParent(int);
+    method public long getStorageId(int);
+    method public int[] getStorageIds();
+    method public android.mtp.MtpStorageInfo getStorageInfo(int);
+    method public byte[] getThumbnail(int);
+    method public boolean importFile(int, java.lang.String);
+    method public boolean open(android.hardware.usb.UsbDeviceConnection);
+  }
+
+  public class MtpDeviceInfo {
+    method public final java.lang.String getManufacturer();
+    method public final java.lang.String getModel();
+    method public final java.lang.String getSerialNumber();
+    method public final java.lang.String getVersion();
+  }
+
+  public final class MtpObjectInfo {
+    method public final int getAssociationDesc();
+    method public final int getAssociationType();
+    method public final int getCompressedSize();
+    method public final long getDateCreated();
+    method public final long getDateModified();
+    method public final int getFormat();
+    method public final int getImagePixDepth();
+    method public final int getImagePixHeight();
+    method public final int getImagePixWidth();
+    method public final java.lang.String getKeywords();
+    method public final java.lang.String getName();
+    method public final int getObjectHandle();
+    method public final int getParent();
+    method public final int getProtectionStatus();
+    method public final int getSequenceNumber();
+    method public final int getStorageId();
+    method public final int getThumbCompressedSize();
+    method public final int getThumbFormat();
+    method public final int getThumbPixHeight();
+    method public final int getThumbPixWidth();
+  }
+
+  public final class MtpStorageInfo {
+    method public final java.lang.String getDescription();
+    method public final long getFreeSpace();
+    method public final long getMaxCapacity();
+    method public final int getStorageId();
+    method public final java.lang.String getVolumeIdentifier();
+  }
+
+}
+
+package android.net {
+
+  public class ConnectivityManager {
+    method public android.net.NetworkInfo getActiveNetworkInfo();
+    method public android.net.NetworkInfo[] getAllNetworkInfo();
+    method public deprecated boolean getBackgroundDataSetting();
+    method public android.net.NetworkInfo getNetworkInfo(int);
+    method public int getNetworkPreference();
+    method public boolean isActiveNetworkMetered();
+    method public static boolean isNetworkTypeValid(int);
+    method public boolean requestRouteToHost(int, int);
+    method public void setNetworkPreference(int);
+    method public int startUsingNetworkFeature(int, java.lang.String);
+    method public int stopUsingNetworkFeature(int, java.lang.String);
+    field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
+    field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
+    field public static final int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
+    field public static final java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
+    field public static final java.lang.String EXTRA_IS_FAILOVER = "isFailover";
+    field public static final deprecated java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
+    field public static final java.lang.String EXTRA_NETWORK_TYPE = "networkType";
+    field public static final java.lang.String EXTRA_NO_CONNECTIVITY = "noConnectivity";
+    field public static final java.lang.String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
+    field public static final java.lang.String EXTRA_REASON = "reason";
+    field public static final int TYPE_BLUETOOTH = 7; // 0x7
+    field public static final int TYPE_DUMMY = 8; // 0x8
+    field public static final int TYPE_ETHERNET = 9; // 0x9
+    field public static final int TYPE_MOBILE = 0; // 0x0
+    field public static final int TYPE_MOBILE_DUN = 4; // 0x4
+    field public static final int TYPE_MOBILE_HIPRI = 5; // 0x5
+    field public static final int TYPE_MOBILE_MMS = 2; // 0x2
+    field public static final int TYPE_MOBILE_SUPL = 3; // 0x3
+    field public static final int TYPE_WIFI = 1; // 0x1
+    field public static final int TYPE_WIMAX = 6; // 0x6
+  }
+
+  public class Credentials {
+    ctor public Credentials(int, int, int);
+    method public int getGid();
+    method public int getPid();
+    method public int getUid();
+  }
+
+  public class DhcpInfo implements android.os.Parcelable {
+    ctor public DhcpInfo();
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public int dns1;
+    field public int dns2;
+    field public int gateway;
+    field public int ipAddress;
+    field public int leaseDuration;
+    field public int netmask;
+    field public int serverAddress;
+  }
+
+  public class LocalServerSocket {
+    ctor public LocalServerSocket(java.lang.String) throws java.io.IOException;
+    ctor public LocalServerSocket(java.io.FileDescriptor) throws java.io.IOException;
+    method public android.net.LocalSocket accept() throws java.io.IOException;
+    method public void close() throws java.io.IOException;
+    method public java.io.FileDescriptor getFileDescriptor();
+    method public android.net.LocalSocketAddress getLocalSocketAddress();
+  }
+
+  public class LocalSocket implements java.io.Closeable {
+    ctor public LocalSocket();
+    method public void bind(android.net.LocalSocketAddress) throws java.io.IOException;
+    method public void close() throws java.io.IOException;
+    method public void connect(android.net.LocalSocketAddress) throws java.io.IOException;
+    method public void connect(android.net.LocalSocketAddress, int) throws java.io.IOException;
+    method public java.io.FileDescriptor[] getAncillaryFileDescriptors() throws java.io.IOException;
+    method public java.io.FileDescriptor getFileDescriptor();
+    method public java.io.InputStream getInputStream() throws java.io.IOException;
+    method public android.net.LocalSocketAddress getLocalSocketAddress();
+    method public java.io.OutputStream getOutputStream() throws java.io.IOException;
+    method public android.net.Credentials getPeerCredentials() throws java.io.IOException;
+    method public int getReceiveBufferSize() throws java.io.IOException;
+    method public android.net.LocalSocketAddress getRemoteSocketAddress();
+    method public int getSendBufferSize() throws java.io.IOException;
+    method public int getSoTimeout() throws java.io.IOException;
+    method public synchronized boolean isBound();
+    method public boolean isClosed();
+    method public synchronized boolean isConnected();
+    method public boolean isInputShutdown();
+    method public boolean isOutputShutdown();
+    method public void setFileDescriptorsForSend(java.io.FileDescriptor[]);
+    method public void setReceiveBufferSize(int) throws java.io.IOException;
+    method public void setSendBufferSize(int) throws java.io.IOException;
+    method public void setSoTimeout(int) throws java.io.IOException;
+    method public void shutdownInput() throws java.io.IOException;
+    method public void shutdownOutput() throws java.io.IOException;
+  }
+
+  public class LocalSocketAddress {
+    ctor public LocalSocketAddress(java.lang.String, android.net.LocalSocketAddress.Namespace);
+    ctor public LocalSocketAddress(java.lang.String);
+    method public java.lang.String getName();
+    method public android.net.LocalSocketAddress.Namespace getNamespace();
+  }
+
+  public static final class LocalSocketAddress.Namespace extends java.lang.Enum {
+    method public static android.net.LocalSocketAddress.Namespace valueOf(java.lang.String);
+    method public static final android.net.LocalSocketAddress.Namespace[] values();
+    enum_constant public static final android.net.LocalSocketAddress.Namespace ABSTRACT;
+    enum_constant public static final android.net.LocalSocketAddress.Namespace FILESYSTEM;
+    enum_constant public static final android.net.LocalSocketAddress.Namespace RESERVED;
+  }
+
+  public class MailTo {
+    method public java.lang.String getBody();
+    method public java.lang.String getCc();
+    method public java.util.Map<java.lang.String, java.lang.String> getHeaders();
+    method public java.lang.String getSubject();
+    method public java.lang.String getTo();
+    method public static boolean isMailTo(java.lang.String);
+    method public static android.net.MailTo parse(java.lang.String) throws android.net.ParseException;
+    field public static final java.lang.String MAILTO_SCHEME = "mailto:";
+  }
+
+  public class NetworkInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.net.NetworkInfo.DetailedState getDetailedState();
+    method public java.lang.String getExtraInfo();
+    method public java.lang.String getReason();
+    method public android.net.NetworkInfo.State getState();
+    method public int getSubtype();
+    method public java.lang.String getSubtypeName();
+    method public int getType();
+    method public java.lang.String getTypeName();
+    method public boolean isAvailable();
+    method public boolean isConnected();
+    method public boolean isConnectedOrConnecting();
+    method public boolean isFailover();
+    method public boolean isRoaming();
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public static final class NetworkInfo.DetailedState extends java.lang.Enum {
+    method public static android.net.NetworkInfo.DetailedState valueOf(java.lang.String);
+    method public static final android.net.NetworkInfo.DetailedState[] values();
+    enum_constant public static final android.net.NetworkInfo.DetailedState AUTHENTICATING;
+    enum_constant public static final android.net.NetworkInfo.DetailedState BLOCKED;
+    enum_constant public static final android.net.NetworkInfo.DetailedState CAPTIVE_PORTAL_CHECK;
+    enum_constant public static final android.net.NetworkInfo.DetailedState CONNECTED;
+    enum_constant public static final android.net.NetworkInfo.DetailedState CONNECTING;
+    enum_constant public static final android.net.NetworkInfo.DetailedState DISCONNECTED;
+    enum_constant public static final android.net.NetworkInfo.DetailedState DISCONNECTING;
+    enum_constant public static final android.net.NetworkInfo.DetailedState FAILED;
+    enum_constant public static final android.net.NetworkInfo.DetailedState IDLE;
+    enum_constant public static final android.net.NetworkInfo.DetailedState OBTAINING_IPADDR;
+    enum_constant public static final android.net.NetworkInfo.DetailedState SCANNING;
+    enum_constant public static final android.net.NetworkInfo.DetailedState SUSPENDED;
+    enum_constant public static final android.net.NetworkInfo.DetailedState VERIFYING_POOR_LINK;
+  }
+
+  public static final class NetworkInfo.State extends java.lang.Enum {
+    method public static android.net.NetworkInfo.State valueOf(java.lang.String);
+    method public static final android.net.NetworkInfo.State[] values();
+    enum_constant public static final android.net.NetworkInfo.State CONNECTED;
+    enum_constant public static final android.net.NetworkInfo.State CONNECTING;
+    enum_constant public static final android.net.NetworkInfo.State DISCONNECTED;
+    enum_constant public static final android.net.NetworkInfo.State DISCONNECTING;
+    enum_constant public static final android.net.NetworkInfo.State SUSPENDED;
+    enum_constant public static final android.net.NetworkInfo.State UNKNOWN;
+  }
+
+  public class ParseException extends java.lang.RuntimeException {
+    field public java.lang.String response;
+  }
+
+  public final class Proxy {
+    ctor public Proxy();
+    method public static final deprecated java.lang.String getDefaultHost();
+    method public static final deprecated int getDefaultPort();
+    method public static final deprecated java.lang.String getHost(android.content.Context);
+    method public static final deprecated int getPort(android.content.Context);
+    field public static final java.lang.String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE";
+  }
+
+  public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
+    ctor public deprecated SSLCertificateSocketFactory(int);
+    method public java.net.Socket createSocket(java.net.Socket, java.lang.String, int, boolean) throws java.io.IOException;
+    method public java.net.Socket createSocket(java.net.InetAddress, int, java.net.InetAddress, int) throws java.io.IOException;
+    method public java.net.Socket createSocket(java.net.InetAddress, int) throws java.io.IOException;
+    method public java.net.Socket createSocket(java.lang.String, int, java.net.InetAddress, int) throws java.io.IOException;
+    method public java.net.Socket createSocket(java.lang.String, int) throws java.io.IOException;
+    method public static javax.net.SocketFactory getDefault(int);
+    method public static javax.net.ssl.SSLSocketFactory getDefault(int, android.net.SSLSessionCache);
+    method public java.lang.String[] getDefaultCipherSuites();
+    method public static org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
+    method public static javax.net.ssl.SSLSocketFactory getInsecure(int, android.net.SSLSessionCache);
+    method public byte[] getNpnSelectedProtocol(java.net.Socket);
+    method public java.lang.String[] getSupportedCipherSuites();
+    method public void setHostname(java.net.Socket, java.lang.String);
+    method public void setKeyManagers(javax.net.ssl.KeyManager[]);
+    method public void setNpnProtocols(byte[][]);
+    method public void setTrustManagers(javax.net.ssl.TrustManager[]);
+    method public void setUseSessionTickets(java.net.Socket, boolean);
+  }
+
+  public final class SSLSessionCache {
+    ctor public SSLSessionCache(java.io.File) throws java.io.IOException;
+    ctor public SSLSessionCache(android.content.Context);
+  }
+
+  public class TrafficStats {
+    ctor public TrafficStats();
+    method public static void clearThreadStatsTag();
+    method public static long getMobileRxBytes();
+    method public static long getMobileRxPackets();
+    method public static long getMobileTxBytes();
+    method public static long getMobileTxPackets();
+    method public static int getThreadStatsTag();
+    method public static long getTotalRxBytes();
+    method public static long getTotalRxPackets();
+    method public static long getTotalTxBytes();
+    method public static long getTotalTxPackets();
+    method public static long getUidRxBytes(int);
+    method public static long getUidRxPackets(int);
+    method public static long getUidTcpRxBytes(int);
+    method public static long getUidTcpRxSegments(int);
+    method public static long getUidTcpTxBytes(int);
+    method public static long getUidTcpTxSegments(int);
+    method public static long getUidTxBytes(int);
+    method public static long getUidTxPackets(int);
+    method public static long getUidUdpRxBytes(int);
+    method public static long getUidUdpRxPackets(int);
+    method public static long getUidUdpTxBytes(int);
+    method public static long getUidUdpTxPackets(int);
+    method public static void incrementOperationCount(int);
+    method public static void incrementOperationCount(int, int);
+    method public static void setThreadStatsTag(int);
+    method public static void tagSocket(java.net.Socket) throws java.net.SocketException;
+    method public static void untagSocket(java.net.Socket) throws java.net.SocketException;
+    field public static final int UNSUPPORTED = -1; // 0xffffffff
+  }
+
+  public abstract class Uri implements java.lang.Comparable android.os.Parcelable {
+    method public abstract android.net.Uri.Builder buildUpon();
+    method public int compareTo(android.net.Uri);
+    method public static java.lang.String decode(java.lang.String);
+    method public static java.lang.String encode(java.lang.String);
+    method public static java.lang.String encode(java.lang.String, java.lang.String);
+    method public static android.net.Uri fromFile(java.io.File);
+    method public static android.net.Uri fromParts(java.lang.String, java.lang.String, java.lang.String);
+    method public abstract java.lang.String getAuthority();
+    method public boolean getBooleanQueryParameter(java.lang.String, boolean);
+    method public abstract java.lang.String getEncodedAuthority();
+    method public abstract java.lang.String getEncodedFragment();
+    method public abstract java.lang.String getEncodedPath();
+    method public abstract java.lang.String getEncodedQuery();
+    method public abstract java.lang.String getEncodedSchemeSpecificPart();
+    method public abstract java.lang.String getEncodedUserInfo();
+    method public abstract java.lang.String getFragment();
+    method public abstract java.lang.String getHost();
+    method public abstract java.lang.String getLastPathSegment();
+    method public abstract java.lang.String getPath();
+    method public abstract java.util.List<java.lang.String> getPathSegments();
+    method public abstract int getPort();
+    method public abstract java.lang.String getQuery();
+    method public java.lang.String getQueryParameter(java.lang.String);
+    method public java.util.Set<java.lang.String> getQueryParameterNames();
+    method public java.util.List<java.lang.String> getQueryParameters(java.lang.String);
+    method public abstract java.lang.String getScheme();
+    method public abstract java.lang.String getSchemeSpecificPart();
+    method public abstract java.lang.String getUserInfo();
+    method public boolean isAbsolute();
+    method public abstract boolean isHierarchical();
+    method public boolean isOpaque();
+    method public abstract boolean isRelative();
+    method public android.net.Uri normalizeScheme();
+    method public static android.net.Uri parse(java.lang.String);
+    method public abstract java.lang.String toString();
+    method public static android.net.Uri withAppendedPath(android.net.Uri, java.lang.String);
+    method public static void writeToParcel(android.os.Parcel, android.net.Uri);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final android.net.Uri EMPTY;
+  }
+
+  public static final class Uri.Builder {
+    ctor public Uri.Builder();
+    method public android.net.Uri.Builder appendEncodedPath(java.lang.String);
+    method public android.net.Uri.Builder appendPath(java.lang.String);
+    method public android.net.Uri.Builder appendQueryParameter(java.lang.String, java.lang.String);
+    method public android.net.Uri.Builder authority(java.lang.String);
+    method public android.net.Uri build();
+    method public android.net.Uri.Builder clearQuery();
+    method public android.net.Uri.Builder encodedAuthority(java.lang.String);
+    method public android.net.Uri.Builder encodedFragment(java.lang.String);
+    method public android.net.Uri.Builder encodedOpaquePart(java.lang.String);
+    method public android.net.Uri.Builder encodedPath(java.lang.String);
+    method public android.net.Uri.Builder encodedQuery(java.lang.String);
+    method public android.net.Uri.Builder fragment(java.lang.String);
+    method public android.net.Uri.Builder opaquePart(java.lang.String);
+    method public android.net.Uri.Builder path(java.lang.String);
+    method public android.net.Uri.Builder query(java.lang.String);
+    method public android.net.Uri.Builder scheme(java.lang.String);
+  }
+
+  public class UrlQuerySanitizer {
+    ctor public UrlQuerySanitizer();
+    ctor public UrlQuerySanitizer(java.lang.String);
+    method protected void addSanitizedEntry(java.lang.String, java.lang.String);
+    method protected void clear();
+    method protected int decodeHexDigit(char);
+    method public static final android.net.UrlQuerySanitizer.ValueSanitizer getAllButNulAndAngleBracketsLegal();
+    method public static final android.net.UrlQuerySanitizer.ValueSanitizer getAllButNulLegal();
+    method public static final android.net.UrlQuerySanitizer.ValueSanitizer getAllButWhitespaceLegal();
+    method public static final android.net.UrlQuerySanitizer.ValueSanitizer getAllIllegal();
+    method public boolean getAllowUnregisteredParamaters();
+    method public static final android.net.UrlQuerySanitizer.ValueSanitizer getAmpAndSpaceLegal();
+    method public static final android.net.UrlQuerySanitizer.ValueSanitizer getAmpLegal();
+    method public android.net.UrlQuerySanitizer.ValueSanitizer getEffectiveValueSanitizer(java.lang.String);
+    method public java.util.List<android.net.UrlQuerySanitizer.ParameterValuePair> getParameterList();
+    method public java.util.Set<java.lang.String> getParameterSet();
+    method public boolean getPreferFirstRepeatedParameter();
+    method public static final android.net.UrlQuerySanitizer.ValueSanitizer getSpaceLegal();
+    method public android.net.UrlQuerySanitizer.ValueSanitizer getUnregisteredParameterValueSanitizer();
+    method public static final android.net.UrlQuerySanitizer.ValueSanitizer getUrlAndSpaceLegal();
+    method public static final android.net.UrlQuerySanitizer.ValueSanitizer getUrlLegal();
+    method public java.lang.String getValue(java.lang.String);
+    method public android.net.UrlQuerySanitizer.ValueSanitizer getValueSanitizer(java.lang.String);
+    method public boolean hasParameter(java.lang.String);
+    method protected boolean isHexDigit(char);
+    method protected void parseEntry(java.lang.String, java.lang.String);
+    method public void parseQuery(java.lang.String);
+    method public void parseUrl(java.lang.String);
+    method public void registerParameter(java.lang.String, android.net.UrlQuerySanitizer.ValueSanitizer);
+    method public void registerParameters(java.lang.String[], android.net.UrlQuerySanitizer.ValueSanitizer);
+    method public void setAllowUnregisteredParamaters(boolean);
+    method public void setPreferFirstRepeatedParameter(boolean);
+    method public void setUnregisteredParameterValueSanitizer(android.net.UrlQuerySanitizer.ValueSanitizer);
+    method public java.lang.String unescape(java.lang.String);
+  }
+
+  public static class UrlQuerySanitizer.IllegalCharacterValueSanitizer implements android.net.UrlQuerySanitizer.ValueSanitizer {
+    ctor public UrlQuerySanitizer.IllegalCharacterValueSanitizer(int);
+    method public java.lang.String sanitize(java.lang.String);
+    field public static final int ALL_BUT_NUL_AND_ANGLE_BRACKETS_LEGAL = 1439; // 0x59f
+    field public static final int ALL_BUT_NUL_LEGAL = 1535; // 0x5ff
+    field public static final int ALL_BUT_WHITESPACE_LEGAL = 1532; // 0x5fc
+    field public static final int ALL_ILLEGAL = 0; // 0x0
+    field public static final int ALL_OK = 2047; // 0x7ff
+    field public static final int ALL_WHITESPACE_OK = 3; // 0x3
+    field public static final int AMP_AND_SPACE_LEGAL = 129; // 0x81
+    field public static final int AMP_LEGAL = 128; // 0x80
+    field public static final int AMP_OK = 128; // 0x80
+    field public static final int DQUOTE_OK = 8; // 0x8
+    field public static final int GT_OK = 64; // 0x40
+    field public static final int LT_OK = 32; // 0x20
+    field public static final int NON_7_BIT_ASCII_OK = 4; // 0x4
+    field public static final int NUL_OK = 512; // 0x200
+    field public static final int OTHER_WHITESPACE_OK = 2; // 0x2
+    field public static final int PCT_OK = 256; // 0x100
+    field public static final int SCRIPT_URL_OK = 1024; // 0x400
+    field public static final int SPACE_LEGAL = 1; // 0x1
+    field public static final int SPACE_OK = 1; // 0x1
+    field public static final int SQUOTE_OK = 16; // 0x10
+    field public static final int URL_AND_SPACE_LEGAL = 405; // 0x195
+    field public static final int URL_LEGAL = 404; // 0x194
+  }
+
+  public class UrlQuerySanitizer.ParameterValuePair {
+    ctor public UrlQuerySanitizer.ParameterValuePair(java.lang.String, java.lang.String);
+    field public java.lang.String mParameter;
+    field public java.lang.String mValue;
+  }
+
+  public static abstract interface UrlQuerySanitizer.ValueSanitizer {
+    method public abstract java.lang.String sanitize(java.lang.String);
+  }
+
+  public class VpnService extends android.app.Service {
+    ctor public VpnService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public void onRevoke();
+    method public static android.content.Intent prepare(android.content.Context);
+    method public boolean protect(int);
+    method public boolean protect(java.net.Socket);
+    method public boolean protect(java.net.DatagramSocket);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.net.VpnService";
+  }
+
+  public class VpnService.Builder {
+    ctor public VpnService.Builder();
+    method public android.net.VpnService.Builder addAddress(java.net.InetAddress, int);
+    method public android.net.VpnService.Builder addAddress(java.lang.String, int);
+    method public android.net.VpnService.Builder addDnsServer(java.net.InetAddress);
+    method public android.net.VpnService.Builder addDnsServer(java.lang.String);
+    method public android.net.VpnService.Builder addRoute(java.net.InetAddress, int);
+    method public android.net.VpnService.Builder addRoute(java.lang.String, int);
+    method public android.net.VpnService.Builder addSearchDomain(java.lang.String);
+    method public android.os.ParcelFileDescriptor establish();
+    method public android.net.VpnService.Builder setConfigureIntent(android.app.PendingIntent);
+    method public android.net.VpnService.Builder setMtu(int);
+    method public android.net.VpnService.Builder setSession(java.lang.String);
+  }
+
+}
+
+package android.net.http {
+
+  public final class AndroidHttpClient implements org.apache.http.client.HttpClient {
+    method public void close();
+    method public void disableCurlLogging();
+    method public void enableCurlLogging(java.lang.String, int);
+    method public org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest) throws java.io.IOException;
+    method public org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.protocol.HttpContext) throws java.io.IOException;
+    method public org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest) throws java.io.IOException;
+    method public org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws java.io.IOException;
+    method public T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public static org.apache.http.entity.AbstractHttpEntity getCompressedEntity(byte[], android.content.ContentResolver) throws java.io.IOException;
+    method public org.apache.http.conn.ClientConnectionManager getConnectionManager();
+    method public static long getMinGzipSize(android.content.ContentResolver);
+    method public org.apache.http.params.HttpParams getParams();
+    method public static java.io.InputStream getUngzippedContent(org.apache.http.HttpEntity) throws java.io.IOException;
+    method public static void modifyRequestToAcceptGzipResponse(org.apache.http.HttpRequest);
+    method public static android.net.http.AndroidHttpClient newInstance(java.lang.String, android.content.Context);
+    method public static android.net.http.AndroidHttpClient newInstance(java.lang.String);
+    method public static long parseDate(java.lang.String);
+    field public static long DEFAULT_SYNC_MIN_GZIP_BYTES;
+  }
+
+  public final class HttpResponseCache extends java.net.ResponseCache implements java.io.Closeable {
+    method public void close() throws java.io.IOException;
+    method public void delete() throws java.io.IOException;
+    method public void flush();
+    method public java.net.CacheResponse get(java.net.URI, java.lang.String, java.util.Map<java.lang.String, java.util.List<java.lang.String>>) throws java.io.IOException;
+    method public int getHitCount();
+    method public static android.net.http.HttpResponseCache getInstalled();
+    method public int getNetworkCount();
+    method public int getRequestCount();
+    method public static android.net.http.HttpResponseCache install(java.io.File, long) throws java.io.IOException;
+    method public long maxSize();
+    method public java.net.CacheRequest put(java.net.URI, java.net.URLConnection) throws java.io.IOException;
+    method public long size();
+  }
+
+  public class SslCertificate {
+    ctor public deprecated SslCertificate(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    ctor public deprecated SslCertificate(java.lang.String, java.lang.String, java.util.Date, java.util.Date);
+    ctor public SslCertificate(java.security.cert.X509Certificate);
+    method public android.net.http.SslCertificate.DName getIssuedBy();
+    method public android.net.http.SslCertificate.DName getIssuedTo();
+    method public deprecated java.lang.String getValidNotAfter();
+    method public java.util.Date getValidNotAfterDate();
+    method public deprecated java.lang.String getValidNotBefore();
+    method public java.util.Date getValidNotBeforeDate();
+    method public static android.net.http.SslCertificate restoreState(android.os.Bundle);
+    method public static android.os.Bundle saveState(android.net.http.SslCertificate);
+  }
+
+  public class SslCertificate.DName {
+    ctor public SslCertificate.DName(java.lang.String);
+    method public java.lang.String getCName();
+    method public java.lang.String getDName();
+    method public java.lang.String getOName();
+    method public java.lang.String getUName();
+  }
+
+  public class SslError {
+    ctor public deprecated SslError(int, android.net.http.SslCertificate);
+    ctor public deprecated SslError(int, java.security.cert.X509Certificate);
+    ctor public SslError(int, android.net.http.SslCertificate, java.lang.String);
+    ctor public SslError(int, java.security.cert.X509Certificate, java.lang.String);
+    method public boolean addError(int);
+    method public android.net.http.SslCertificate getCertificate();
+    method public int getPrimaryError();
+    method public java.lang.String getUrl();
+    method public boolean hasError(int);
+    field public static final int SSL_DATE_INVALID = 4; // 0x4
+    field public static final int SSL_EXPIRED = 1; // 0x1
+    field public static final int SSL_IDMISMATCH = 2; // 0x2
+    field public static final int SSL_INVALID = 5; // 0x5
+    field public static final deprecated int SSL_MAX_ERROR = 6; // 0x6
+    field public static final int SSL_NOTYETVALID = 0; // 0x0
+    field public static final int SSL_UNTRUSTED = 3; // 0x3
+  }
+
+  public class X509TrustManagerExtensions {
+    ctor public X509TrustManagerExtensions(javax.net.ssl.X509TrustManager) throws java.lang.IllegalArgumentException;
+    method public java.util.List<java.security.cert.X509Certificate> checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String, java.lang.String) throws java.security.cert.CertificateException;
+  }
+
+}
+
+package android.net.nsd {
+
+  public final class NsdManager {
+    method public void discoverServices(java.lang.String, int, android.net.nsd.NsdManager.DiscoveryListener);
+    method public void registerService(android.net.nsd.NsdServiceInfo, int, android.net.nsd.NsdManager.RegistrationListener);
+    method public void resolveService(android.net.nsd.NsdServiceInfo, android.net.nsd.NsdManager.ResolveListener);
+    method public void stopServiceDiscovery(android.net.nsd.NsdManager.DiscoveryListener);
+    method public void unregisterService(android.net.nsd.NsdManager.RegistrationListener);
+    field public static final java.lang.String ACTION_NSD_STATE_CHANGED = "android.net.nsd.STATE_CHANGED";
+    field public static final java.lang.String EXTRA_NSD_STATE = "nsd_state";
+    field public static final int FAILURE_ALREADY_ACTIVE = 3; // 0x3
+    field public static final int FAILURE_INTERNAL_ERROR = 0; // 0x0
+    field public static final int FAILURE_MAX_LIMIT = 4; // 0x4
+    field public static final int NSD_STATE_DISABLED = 1; // 0x1
+    field public static final int NSD_STATE_ENABLED = 2; // 0x2
+    field public static final int PROTOCOL_DNS_SD = 1; // 0x1
+  }
+
+  public static abstract interface NsdManager.DiscoveryListener {
+    method public abstract void onDiscoveryStarted(java.lang.String);
+    method public abstract void onDiscoveryStopped(java.lang.String);
+    method public abstract void onServiceFound(android.net.nsd.NsdServiceInfo);
+    method public abstract void onServiceLost(android.net.nsd.NsdServiceInfo);
+    method public abstract void onStartDiscoveryFailed(java.lang.String, int);
+    method public abstract void onStopDiscoveryFailed(java.lang.String, int);
+  }
+
+  public static abstract interface NsdManager.RegistrationListener {
+    method public abstract void onRegistrationFailed(android.net.nsd.NsdServiceInfo, int);
+    method public abstract void onServiceRegistered(android.net.nsd.NsdServiceInfo);
+    method public abstract void onServiceUnregistered(android.net.nsd.NsdServiceInfo);
+    method public abstract void onUnregistrationFailed(android.net.nsd.NsdServiceInfo, int);
+  }
+
+  public static abstract interface NsdManager.ResolveListener {
+    method public abstract void onResolveFailed(android.net.nsd.NsdServiceInfo, int);
+    method public abstract void onServiceResolved(android.net.nsd.NsdServiceInfo);
+  }
+
+  public final class NsdServiceInfo implements android.os.Parcelable {
+    ctor public NsdServiceInfo();
+    method public int describeContents();
+    method public java.net.InetAddress getHost();
+    method public int getPort();
+    method public java.lang.String getServiceName();
+    method public java.lang.String getServiceType();
+    method public void setHost(java.net.InetAddress);
+    method public void setPort(int);
+    method public void setServiceName(java.lang.String);
+    method public void setServiceType(java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+}
+
+package android.net.rtp {
+
+  public class AudioCodec {
+    method public static android.net.rtp.AudioCodec getCodec(int, java.lang.String, java.lang.String);
+    method public static android.net.rtp.AudioCodec[] getCodecs();
+    field public static final android.net.rtp.AudioCodec AMR;
+    field public static final android.net.rtp.AudioCodec GSM;
+    field public static final android.net.rtp.AudioCodec GSM_EFR;
+    field public static final android.net.rtp.AudioCodec PCMA;
+    field public static final android.net.rtp.AudioCodec PCMU;
+    field public final java.lang.String fmtp;
+    field public final java.lang.String rtpmap;
+    field public final int type;
+  }
+
+  public class AudioGroup {
+    ctor public AudioGroup();
+    method public void clear();
+    method public int getMode();
+    method public android.net.rtp.AudioStream[] getStreams();
+    method public void sendDtmf(int);
+    method public void setMode(int);
+    field public static final int MODE_ECHO_SUPPRESSION = 3; // 0x3
+    field public static final int MODE_MUTED = 1; // 0x1
+    field public static final int MODE_NORMAL = 2; // 0x2
+    field public static final int MODE_ON_HOLD = 0; // 0x0
+  }
+
+  public class AudioStream extends android.net.rtp.RtpStream {
+    ctor public AudioStream(java.net.InetAddress) throws java.net.SocketException;
+    method public android.net.rtp.AudioCodec getCodec();
+    method public int getDtmfType();
+    method public android.net.rtp.AudioGroup getGroup();
+    method public final boolean isBusy();
+    method public void join(android.net.rtp.AudioGroup);
+    method public void setCodec(android.net.rtp.AudioCodec);
+    method public void setDtmfType(int);
+  }
+
+  public class RtpStream {
+    method public void associate(java.net.InetAddress, int);
+    method public java.net.InetAddress getLocalAddress();
+    method public int getLocalPort();
+    method public int getMode();
+    method public java.net.InetAddress getRemoteAddress();
+    method public int getRemotePort();
+    method public boolean isBusy();
+    method public void release();
+    method public void setMode(int);
+    field public static final int MODE_NORMAL = 0; // 0x0
+    field public static final int MODE_RECEIVE_ONLY = 2; // 0x2
+    field public static final int MODE_SEND_ONLY = 1; // 0x1
+  }
+
+}
+
+package android.net.sip {
+
+  public class SipAudioCall {
+    ctor public SipAudioCall(android.content.Context, android.net.sip.SipProfile);
+    method public void answerCall(int) throws android.net.sip.SipException;
+    method public void attachCall(android.net.sip.SipSession, java.lang.String) throws android.net.sip.SipException;
+    method public void close();
+    method public void continueCall(int) throws android.net.sip.SipException;
+    method public void endCall() throws android.net.sip.SipException;
+    method public android.net.sip.SipProfile getLocalProfile();
+    method public android.net.sip.SipProfile getPeerProfile();
+    method public int getState();
+    method public void holdCall(int) throws android.net.sip.SipException;
+    method public boolean isInCall();
+    method public boolean isMuted();
+    method public boolean isOnHold();
+    method public void makeCall(android.net.sip.SipProfile, android.net.sip.SipSession, int) throws android.net.sip.SipException;
+    method public void sendDtmf(int);
+    method public void sendDtmf(int, android.os.Message);
+    method public void setListener(android.net.sip.SipAudioCall.Listener);
+    method public void setListener(android.net.sip.SipAudioCall.Listener, boolean);
+    method public void setSpeakerMode(boolean);
+    method public void startAudio();
+    method public void toggleMute();
+  }
+
+  public static class SipAudioCall.Listener {
+    ctor public SipAudioCall.Listener();
+    method public void onCallBusy(android.net.sip.SipAudioCall);
+    method public void onCallEnded(android.net.sip.SipAudioCall);
+    method public void onCallEstablished(android.net.sip.SipAudioCall);
+    method public void onCallHeld(android.net.sip.SipAudioCall);
+    method public void onCalling(android.net.sip.SipAudioCall);
+    method public void onChanged(android.net.sip.SipAudioCall);
+    method public void onError(android.net.sip.SipAudioCall, int, java.lang.String);
+    method public void onReadyToCall(android.net.sip.SipAudioCall);
+    method public void onRinging(android.net.sip.SipAudioCall, android.net.sip.SipProfile);
+    method public void onRingingBack(android.net.sip.SipAudioCall);
+  }
+
+  public class SipErrorCode {
+    method public static java.lang.String toString(int);
+    field public static final int CLIENT_ERROR = -4; // 0xfffffffc
+    field public static final int CROSS_DOMAIN_AUTHENTICATION = -11; // 0xfffffff5
+    field public static final int DATA_CONNECTION_LOST = -10; // 0xfffffff6
+    field public static final int INVALID_CREDENTIALS = -8; // 0xfffffff8
+    field public static final int INVALID_REMOTE_URI = -6; // 0xfffffffa
+    field public static final int IN_PROGRESS = -9; // 0xfffffff7
+    field public static final int NO_ERROR = 0; // 0x0
+    field public static final int PEER_NOT_REACHABLE = -7; // 0xfffffff9
+    field public static final int SERVER_ERROR = -2; // 0xfffffffe
+    field public static final int SERVER_UNREACHABLE = -12; // 0xfffffff4
+    field public static final int SOCKET_ERROR = -1; // 0xffffffff
+    field public static final int TIME_OUT = -5; // 0xfffffffb
+    field public static final int TRANSACTION_TERMINTED = -3; // 0xfffffffd
+  }
+
+  public class SipException extends java.lang.Exception {
+    ctor public SipException();
+    ctor public SipException(java.lang.String);
+    ctor public SipException(java.lang.String, java.lang.Throwable);
+  }
+
+  public class SipManager {
+    method public void close(java.lang.String) throws android.net.sip.SipException;
+    method public android.net.sip.SipSession createSipSession(android.net.sip.SipProfile, android.net.sip.SipSession.Listener) throws android.net.sip.SipException;
+    method public static java.lang.String getCallId(android.content.Intent);
+    method public static java.lang.String getOfferSessionDescription(android.content.Intent);
+    method public android.net.sip.SipSession getSessionFor(android.content.Intent) throws android.net.sip.SipException;
+    method public static boolean isApiSupported(android.content.Context);
+    method public static boolean isIncomingCallIntent(android.content.Intent);
+    method public boolean isOpened(java.lang.String) throws android.net.sip.SipException;
+    method public boolean isRegistered(java.lang.String) throws android.net.sip.SipException;
+    method public static boolean isSipWifiOnly(android.content.Context);
+    method public static boolean isVoipSupported(android.content.Context);
+    method public android.net.sip.SipAudioCall makeAudioCall(android.net.sip.SipProfile, android.net.sip.SipProfile, android.net.sip.SipAudioCall.Listener, int) throws android.net.sip.SipException;
+    method public android.net.sip.SipAudioCall makeAudioCall(java.lang.String, java.lang.String, android.net.sip.SipAudioCall.Listener, int) throws android.net.sip.SipException;
+    method public static android.net.sip.SipManager newInstance(android.content.Context);
+    method public void open(android.net.sip.SipProfile) throws android.net.sip.SipException;
+    method public void open(android.net.sip.SipProfile, android.app.PendingIntent, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException;
+    method public void register(android.net.sip.SipProfile, int, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException;
+    method public void setRegistrationListener(java.lang.String, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException;
+    method public android.net.sip.SipAudioCall takeAudioCall(android.content.Intent, android.net.sip.SipAudioCall.Listener) throws android.net.sip.SipException;
+    method public void unregister(android.net.sip.SipProfile, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException;
+    field public static final java.lang.String EXTRA_CALL_ID = "android:sipCallID";
+    field public static final java.lang.String EXTRA_OFFER_SD = "android:sipOfferSD";
+    field public static final int INCOMING_CALL_RESULT_CODE = 101; // 0x65
+  }
+
+  public class SipProfile implements java.lang.Cloneable android.os.Parcelable java.io.Serializable {
+    method public int describeContents();
+    method public java.lang.String getAuthUserName();
+    method public boolean getAutoRegistration();
+    method public java.lang.String getDisplayName();
+    method public java.lang.String getPassword();
+    method public int getPort();
+    method public java.lang.String getProfileName();
+    method public java.lang.String getProtocol();
+    method public java.lang.String getProxyAddress();
+    method public boolean getSendKeepAlive();
+    method public java.lang.String getSipDomain();
+    method public java.lang.String getUriString();
+    method public java.lang.String getUserName();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static class SipProfile.Builder {
+    ctor public SipProfile.Builder(android.net.sip.SipProfile);
+    ctor public SipProfile.Builder(java.lang.String) throws java.text.ParseException;
+    ctor public SipProfile.Builder(java.lang.String, java.lang.String) throws java.text.ParseException;
+    method public android.net.sip.SipProfile build();
+    method public android.net.sip.SipProfile.Builder setAuthUserName(java.lang.String);
+    method public android.net.sip.SipProfile.Builder setAutoRegistration(boolean);
+    method public android.net.sip.SipProfile.Builder setDisplayName(java.lang.String);
+    method public android.net.sip.SipProfile.Builder setOutboundProxy(java.lang.String);
+    method public android.net.sip.SipProfile.Builder setPassword(java.lang.String);
+    method public android.net.sip.SipProfile.Builder setPort(int) throws java.lang.IllegalArgumentException;
+    method public android.net.sip.SipProfile.Builder setProfileName(java.lang.String);
+    method public android.net.sip.SipProfile.Builder setProtocol(java.lang.String) throws java.lang.IllegalArgumentException;
+    method public android.net.sip.SipProfile.Builder setSendKeepAlive(boolean);
+  }
+
+  public abstract interface SipRegistrationListener {
+    method public abstract void onRegistering(java.lang.String);
+    method public abstract void onRegistrationDone(java.lang.String, long);
+    method public abstract void onRegistrationFailed(java.lang.String, int, java.lang.String);
+  }
+
+  public final class SipSession {
+    method public void answerCall(java.lang.String, int);
+    method public void changeCall(java.lang.String, int);
+    method public void endCall();
+    method public java.lang.String getCallId();
+    method public java.lang.String getLocalIp();
+    method public android.net.sip.SipProfile getLocalProfile();
+    method public android.net.sip.SipProfile getPeerProfile();
+    method public int getState();
+    method public boolean isInCall();
+    method public void makeCall(android.net.sip.SipProfile, java.lang.String, int);
+    method public void register(int);
+    method public void setListener(android.net.sip.SipSession.Listener);
+    method public void unregister();
+  }
+
+  public static class SipSession.Listener {
+    ctor public SipSession.Listener();
+    method public void onCallBusy(android.net.sip.SipSession);
+    method public void onCallChangeFailed(android.net.sip.SipSession, int, java.lang.String);
+    method public void onCallEnded(android.net.sip.SipSession);
+    method public void onCallEstablished(android.net.sip.SipSession, java.lang.String);
+    method public void onCalling(android.net.sip.SipSession);
+    method public void onError(android.net.sip.SipSession, int, java.lang.String);
+    method public void onRegistering(android.net.sip.SipSession);
+    method public void onRegistrationDone(android.net.sip.SipSession, int);
+    method public void onRegistrationFailed(android.net.sip.SipSession, int, java.lang.String);
+    method public void onRegistrationTimeout(android.net.sip.SipSession);
+    method public void onRinging(android.net.sip.SipSession, android.net.sip.SipProfile, java.lang.String);
+    method public void onRingingBack(android.net.sip.SipSession);
+  }
+
+  public static class SipSession.State {
+    method public static java.lang.String toString(int);
+    field public static final int DEREGISTERING = 2; // 0x2
+    field public static final int INCOMING_CALL = 3; // 0x3
+    field public static final int INCOMING_CALL_ANSWERING = 4; // 0x4
+    field public static final int IN_CALL = 8; // 0x8
+    field public static final int NOT_DEFINED = 101; // 0x65
+    field public static final int OUTGOING_CALL = 5; // 0x5
+    field public static final int OUTGOING_CALL_CANCELING = 7; // 0x7
+    field public static final int OUTGOING_CALL_RING_BACK = 6; // 0x6
+    field public static final int PINGING = 9; // 0x9
+    field public static final int READY_TO_CALL = 0; // 0x0
+    field public static final int REGISTERING = 1; // 0x1
+  }
+
+}
+
+package android.net.wifi {
+
+  public class ScanResult implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public java.lang.String BSSID;
+    field public java.lang.String SSID;
+    field public java.lang.String capabilities;
+    field public int frequency;
+    field public int level;
+    field public long timestamp;
+  }
+
+  public final class SupplicantState extends java.lang.Enum implements android.os.Parcelable {
+    method public int describeContents();
+    method public static boolean isValidState(android.net.wifi.SupplicantState);
+    method public static android.net.wifi.SupplicantState valueOf(java.lang.String);
+    method public static final android.net.wifi.SupplicantState[] values();
+    method public void writeToParcel(android.os.Parcel, int);
+    enum_constant public static final android.net.wifi.SupplicantState ASSOCIATED;
+    enum_constant public static final android.net.wifi.SupplicantState ASSOCIATING;
+    enum_constant public static final android.net.wifi.SupplicantState AUTHENTICATING;
+    enum_constant public static final android.net.wifi.SupplicantState COMPLETED;
+    enum_constant public static final android.net.wifi.SupplicantState DISCONNECTED;
+    enum_constant public static final android.net.wifi.SupplicantState DORMANT;
+    enum_constant public static final android.net.wifi.SupplicantState FOUR_WAY_HANDSHAKE;
+    enum_constant public static final android.net.wifi.SupplicantState GROUP_HANDSHAKE;
+    enum_constant public static final android.net.wifi.SupplicantState INACTIVE;
+    enum_constant public static final android.net.wifi.SupplicantState INTERFACE_DISABLED;
+    enum_constant public static final android.net.wifi.SupplicantState INVALID;
+    enum_constant public static final android.net.wifi.SupplicantState SCANNING;
+    enum_constant public static final android.net.wifi.SupplicantState UNINITIALIZED;
+  }
+
+  public class WifiConfiguration implements android.os.Parcelable {
+    ctor public WifiConfiguration();
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public java.lang.String BSSID;
+    field public java.lang.String SSID;
+    field public java.util.BitSet allowedAuthAlgorithms;
+    field public java.util.BitSet allowedGroupCiphers;
+    field public java.util.BitSet allowedKeyManagement;
+    field public java.util.BitSet allowedPairwiseCiphers;
+    field public java.util.BitSet allowedProtocols;
+    field public boolean hiddenSSID;
+    field public int networkId;
+    field public java.lang.String preSharedKey;
+    field public int priority;
+    field public int status;
+    field public java.lang.String[] wepKeys;
+    field public int wepTxKeyIndex;
+  }
+
+  public static class WifiConfiguration.AuthAlgorithm {
+    field public static final int LEAP = 2; // 0x2
+    field public static final int OPEN = 0; // 0x0
+    field public static final int SHARED = 1; // 0x1
+    field public static final java.lang.String[] strings;
+    field public static final java.lang.String varName = "auth_alg";
+  }
+
+  public static class WifiConfiguration.GroupCipher {
+    field public static final int CCMP = 3; // 0x3
+    field public static final int TKIP = 2; // 0x2
+    field public static final int WEP104 = 1; // 0x1
+    field public static final int WEP40 = 0; // 0x0
+    field public static final java.lang.String[] strings;
+    field public static final java.lang.String varName = "group";
+  }
+
+  public static class WifiConfiguration.KeyMgmt {
+    field public static final int IEEE8021X = 3; // 0x3
+    field public static final int NONE = 0; // 0x0
+    field public static final int WPA_EAP = 2; // 0x2
+    field public static final int WPA_PSK = 1; // 0x1
+    field public static final java.lang.String[] strings;
+    field public static final java.lang.String varName = "key_mgmt";
+  }
+
+  public static class WifiConfiguration.PairwiseCipher {
+    field public static final int CCMP = 2; // 0x2
+    field public static final int NONE = 0; // 0x0
+    field public static final int TKIP = 1; // 0x1
+    field public static final java.lang.String[] strings;
+    field public static final java.lang.String varName = "pairwise";
+  }
+
+  public static class WifiConfiguration.Protocol {
+    field public static final int RSN = 1; // 0x1
+    field public static final int WPA = 0; // 0x0
+    field public static final java.lang.String[] strings;
+    field public static final java.lang.String varName = "proto";
+  }
+
+  public static class WifiConfiguration.Status {
+    field public static final int CURRENT = 0; // 0x0
+    field public static final int DISABLED = 1; // 0x1
+    field public static final int ENABLED = 2; // 0x2
+    field public static final java.lang.String[] strings;
+  }
+
+  public class WifiInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.String getBSSID();
+    method public static android.net.NetworkInfo.DetailedState getDetailedStateOf(android.net.wifi.SupplicantState);
+    method public boolean getHiddenSSID();
+    method public int getIpAddress();
+    method public int getLinkSpeed();
+    method public java.lang.String getMacAddress();
+    method public int getNetworkId();
+    method public int getRssi();
+    method public java.lang.String getSSID();
+    method public android.net.wifi.SupplicantState getSupplicantState();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final java.lang.String LINK_SPEED_UNITS = "Mbps";
+  }
+
+  public class WifiManager {
+    method public int addNetwork(android.net.wifi.WifiConfiguration);
+    method public static int calculateSignalLevel(int, int);
+    method public static int compareSignalLevel(int, int);
+    method public android.net.wifi.WifiManager.MulticastLock createMulticastLock(java.lang.String);
+    method public android.net.wifi.WifiManager.WifiLock createWifiLock(int, java.lang.String);
+    method public android.net.wifi.WifiManager.WifiLock createWifiLock(java.lang.String);
+    method public boolean disableNetwork(int);
+    method public boolean disconnect();
+    method public boolean enableNetwork(int, boolean);
+    method public java.util.List<android.net.wifi.WifiConfiguration> getConfiguredNetworks();
+    method public android.net.wifi.WifiInfo getConnectionInfo();
+    method public android.net.DhcpInfo getDhcpInfo();
+    method public java.util.List<android.net.wifi.ScanResult> getScanResults();
+    method public int getWifiState();
+    method public boolean isWifiEnabled();
+    method public boolean pingSupplicant();
+    method public boolean reassociate();
+    method public boolean reconnect();
+    method public boolean removeNetwork(int);
+    method public boolean saveConfiguration();
+    method public boolean setWifiEnabled(boolean);
+    method public boolean startScan();
+    method public int updateNetwork(android.net.wifi.WifiConfiguration);
+    field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
+    field public static final int ERROR_AUTHENTICATING = 1; // 0x1
+    field public static final java.lang.String EXTRA_BSSID = "bssid";
+    field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
+    field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
+    field public static final java.lang.String EXTRA_NEW_STATE = "newState";
+    field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
+    field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
+    field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
+    field public static final java.lang.String EXTRA_WIFI_INFO = "wifiInfo";
+    field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state";
+    field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
+    field public static final java.lang.String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
+    field public static final java.lang.String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED";
+    field public static final java.lang.String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS";
+    field public static final java.lang.String SUPPLICANT_CONNECTION_CHANGE_ACTION = "android.net.wifi.supplicant.CONNECTION_CHANGE";
+    field public static final java.lang.String SUPPLICANT_STATE_CHANGED_ACTION = "android.net.wifi.supplicant.STATE_CHANGE";
+    field public static final int WIFI_MODE_FULL = 1; // 0x1
+    field public static final int WIFI_MODE_FULL_HIGH_PERF = 3; // 0x3
+    field public static final int WIFI_MODE_SCAN_ONLY = 2; // 0x2
+    field public static final java.lang.String WIFI_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_STATE_CHANGED";
+    field public static final int WIFI_STATE_DISABLED = 1; // 0x1
+    field public static final int WIFI_STATE_DISABLING = 0; // 0x0
+    field public static final int WIFI_STATE_ENABLED = 3; // 0x3
+    field public static final int WIFI_STATE_ENABLING = 2; // 0x2
+    field public static final int WIFI_STATE_UNKNOWN = 4; // 0x4
+  }
+
+  public class WifiManager.MulticastLock {
+    method public void acquire();
+    method public boolean isHeld();
+    method public void release();
+    method public void setReferenceCounted(boolean);
+  }
+
+  public class WifiManager.WifiLock {
+    method public void acquire();
+    method public boolean isHeld();
+    method public void release();
+    method public void setReferenceCounted(boolean);
+    method public void setWorkSource(android.os.WorkSource);
+  }
+
+  public class WpsInfo implements android.os.Parcelable {
+    ctor public WpsInfo();
+    ctor public WpsInfo(android.net.wifi.WpsInfo);
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int DISPLAY = 1; // 0x1
+    field public static final int INVALID = 4; // 0x4
+    field public static final int KEYPAD = 2; // 0x2
+    field public static final int LABEL = 3; // 0x3
+    field public static final int PBC = 0; // 0x0
+    field public java.lang.String pin;
+    field public int setup;
+  }
+
+}
+
+package android.net.wifi.p2p {
+
+  public class WifiP2pConfig implements android.os.Parcelable {
+    ctor public WifiP2pConfig();
+    ctor public WifiP2pConfig(android.net.wifi.p2p.WifiP2pConfig);
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public java.lang.String deviceAddress;
+    field public int groupOwnerIntent;
+    field public android.net.wifi.WpsInfo wps;
+  }
+
+  public class WifiP2pDevice implements android.os.Parcelable {
+    ctor public WifiP2pDevice();
+    ctor public WifiP2pDevice(android.net.wifi.p2p.WifiP2pDevice);
+    method public int describeContents();
+    method public boolean isGroupOwner();
+    method public boolean isServiceDiscoveryCapable();
+    method public boolean wpsDisplaySupported();
+    method public boolean wpsKeypadSupported();
+    method public boolean wpsPbcSupported();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int AVAILABLE = 3; // 0x3
+    field public static final int CONNECTED = 0; // 0x0
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FAILED = 2; // 0x2
+    field public static final int INVITED = 1; // 0x1
+    field public static final int UNAVAILABLE = 4; // 0x4
+    field public java.lang.String deviceAddress;
+    field public java.lang.String deviceName;
+    field public java.lang.String primaryDeviceType;
+    field public java.lang.String secondaryDeviceType;
+    field public int status;
+  }
+
+  public class WifiP2pDeviceList implements android.os.Parcelable {
+    ctor public WifiP2pDeviceList();
+    ctor public WifiP2pDeviceList(android.net.wifi.p2p.WifiP2pDeviceList);
+    method public int describeContents();
+    method public java.util.Collection<android.net.wifi.p2p.WifiP2pDevice> getDeviceList();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class WifiP2pGroup implements android.os.Parcelable {
+    ctor public WifiP2pGroup();
+    ctor public WifiP2pGroup(android.net.wifi.p2p.WifiP2pGroup);
+    method public int describeContents();
+    method public java.util.Collection<android.net.wifi.p2p.WifiP2pDevice> getClientList();
+    method public java.lang.String getInterface();
+    method public java.lang.String getNetworkName();
+    method public android.net.wifi.p2p.WifiP2pDevice getOwner();
+    method public java.lang.String getPassphrase();
+    method public boolean isGroupOwner();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class WifiP2pInfo implements android.os.Parcelable {
+    ctor public WifiP2pInfo();
+    ctor public WifiP2pInfo(android.net.wifi.p2p.WifiP2pInfo);
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public boolean groupFormed;
+    field public java.net.InetAddress groupOwnerAddress;
+    field public boolean isGroupOwner;
+  }
+
+  public class WifiP2pManager {
+    method public void addLocalService(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.nsd.WifiP2pServiceInfo, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void addServiceRequest(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.nsd.WifiP2pServiceRequest, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void cancelConnect(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void clearLocalServices(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void clearServiceRequests(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void connect(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pConfig, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void createGroup(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void discoverPeers(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void discoverServices(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public android.net.wifi.p2p.WifiP2pManager.Channel initialize(android.content.Context, android.os.Looper, android.net.wifi.p2p.WifiP2pManager.ChannelListener);
+    method public void removeGroup(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void removeLocalService(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.nsd.WifiP2pServiceInfo, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void removeServiceRequest(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.nsd.WifiP2pServiceRequest, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    method public void requestConnectionInfo(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ConnectionInfoListener);
+    method public void requestGroupInfo(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.GroupInfoListener);
+    method public void requestPeers(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.PeerListListener);
+    method public void setDnsSdResponseListeners(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.DnsSdServiceResponseListener, android.net.wifi.p2p.WifiP2pManager.DnsSdTxtRecordListener);
+    method public void setServiceResponseListener(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ServiceResponseListener);
+    method public void setUpnpServiceResponseListener(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.UpnpServiceResponseListener);
+    method public void stopPeerDiscovery(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+    field public static final int BUSY = 2; // 0x2
+    field public static final int ERROR = 0; // 0x0
+    field public static final java.lang.String EXTRA_DISCOVERY_STATE = "discoveryState";
+    field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
+    field public static final java.lang.String EXTRA_WIFI_P2P_DEVICE = "wifiP2pDevice";
+    field public static final java.lang.String EXTRA_WIFI_P2P_INFO = "wifiP2pInfo";
+    field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_p2p_state";
+    field public static final int NO_SERVICE_REQUESTS = 3; // 0x3
+    field public static final int P2P_UNSUPPORTED = 1; // 0x1
+    field public static final java.lang.String WIFI_P2P_CONNECTION_CHANGED_ACTION = "android.net.wifi.p2p.CONNECTION_STATE_CHANGE";
+    field public static final java.lang.String WIFI_P2P_DISCOVERY_CHANGED_ACTION = "android.net.wifi.p2p.DISCOVERY_STATE_CHANGE";
+    field public static final int WIFI_P2P_DISCOVERY_STARTED = 2; // 0x2
+    field public static final int WIFI_P2P_DISCOVERY_STOPPED = 1; // 0x1
+    field public static final java.lang.String WIFI_P2P_PEERS_CHANGED_ACTION = "android.net.wifi.p2p.PEERS_CHANGED";
+    field public static final java.lang.String WIFI_P2P_STATE_CHANGED_ACTION = "android.net.wifi.p2p.STATE_CHANGED";
+    field public static final int WIFI_P2P_STATE_DISABLED = 1; // 0x1
+    field public static final int WIFI_P2P_STATE_ENABLED = 2; // 0x2
+    field public static final java.lang.String WIFI_P2P_THIS_DEVICE_CHANGED_ACTION = "android.net.wifi.p2p.THIS_DEVICE_CHANGED";
+  }
+
+  public static abstract interface WifiP2pManager.ActionListener {
+    method public abstract void onFailure(int);
+    method public abstract void onSuccess();
+  }
+
+  public static class WifiP2pManager.Channel {
+  }
+
+  public static abstract interface WifiP2pManager.ChannelListener {
+    method public abstract void onChannelDisconnected();
+  }
+
+  public static abstract interface WifiP2pManager.ConnectionInfoListener {
+    method public abstract void onConnectionInfoAvailable(android.net.wifi.p2p.WifiP2pInfo);
+  }
+
+  public static abstract interface WifiP2pManager.DnsSdServiceResponseListener {
+    method public abstract void onDnsSdServiceAvailable(java.lang.String, java.lang.String, android.net.wifi.p2p.WifiP2pDevice);
+  }
+
+  public static abstract interface WifiP2pManager.DnsSdTxtRecordListener {
+    method public abstract void onDnsSdTxtRecordAvailable(java.lang.String, java.util.Map<java.lang.String, java.lang.String>, android.net.wifi.p2p.WifiP2pDevice);
+  }
+
+  public static abstract interface WifiP2pManager.GroupInfoListener {
+    method public abstract void onGroupInfoAvailable(android.net.wifi.p2p.WifiP2pGroup);
+  }
+
+  public static abstract interface WifiP2pManager.PeerListListener {
+    method public abstract void onPeersAvailable(android.net.wifi.p2p.WifiP2pDeviceList);
+  }
+
+  public static abstract interface WifiP2pManager.ServiceResponseListener {
+    method public abstract void onServiceAvailable(int, byte[], android.net.wifi.p2p.WifiP2pDevice);
+  }
+
+  public static abstract interface WifiP2pManager.UpnpServiceResponseListener {
+    method public abstract void onUpnpServiceAvailable(java.util.List<java.lang.String>, android.net.wifi.p2p.WifiP2pDevice);
+  }
+
+}
+
+package android.net.wifi.p2p.nsd {
+
+  public class WifiP2pDnsSdServiceInfo extends android.net.wifi.p2p.nsd.WifiP2pServiceInfo {
+    method public static android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo newInstance(java.lang.String, java.lang.String, java.util.Map<java.lang.String, java.lang.String>);
+  }
+
+  public class WifiP2pDnsSdServiceRequest extends android.net.wifi.p2p.nsd.WifiP2pServiceRequest {
+    method public static android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceRequest newInstance();
+    method public static android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceRequest newInstance(java.lang.String);
+    method public static android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceRequest newInstance(java.lang.String, java.lang.String);
+  }
+
+  public class WifiP2pServiceInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int SERVICE_TYPE_ALL = 0; // 0x0
+    field public static final int SERVICE_TYPE_BONJOUR = 1; // 0x1
+    field public static final int SERVICE_TYPE_UPNP = 2; // 0x2
+    field public static final int SERVICE_TYPE_VENDOR_SPECIFIC = 255; // 0xff
+  }
+
+  public class WifiP2pServiceRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public static android.net.wifi.p2p.nsd.WifiP2pServiceRequest newInstance(int, java.lang.String);
+    method public static android.net.wifi.p2p.nsd.WifiP2pServiceRequest newInstance(int);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class WifiP2pUpnpServiceInfo extends android.net.wifi.p2p.nsd.WifiP2pServiceInfo {
+    method public static android.net.wifi.p2p.nsd.WifiP2pUpnpServiceInfo newInstance(java.lang.String, java.lang.String, java.util.List<java.lang.String>);
+  }
+
+  public class WifiP2pUpnpServiceRequest extends android.net.wifi.p2p.nsd.WifiP2pServiceRequest {
+    method public static android.net.wifi.p2p.nsd.WifiP2pUpnpServiceRequest newInstance();
+    method public static android.net.wifi.p2p.nsd.WifiP2pUpnpServiceRequest newInstance(java.lang.String);
+  }
+
+}
+
+package android.nfc {
+
+  public class FormatException extends java.lang.Exception {
+    ctor public FormatException();
+    ctor public FormatException(java.lang.String);
+    ctor public FormatException(java.lang.String, java.lang.Throwable);
+  }
+
+  public final class NdefMessage implements android.os.Parcelable {
+    ctor public NdefMessage(byte[]) throws android.nfc.FormatException;
+    ctor public NdefMessage(android.nfc.NdefRecord, android.nfc.NdefRecord...);
+    ctor public NdefMessage(android.nfc.NdefRecord[]);
+    method public int describeContents();
+    method public int getByteArrayLength();
+    method public android.nfc.NdefRecord[] getRecords();
+    method public byte[] toByteArray();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class NdefRecord implements android.os.Parcelable {
+    ctor public NdefRecord(short, byte[], byte[], byte[]);
+    ctor public deprecated NdefRecord(byte[]) throws android.nfc.FormatException;
+    method public static android.nfc.NdefRecord createApplicationRecord(java.lang.String);
+    method public static android.nfc.NdefRecord createExternal(java.lang.String, java.lang.String, byte[]);
+    method public static android.nfc.NdefRecord createMime(java.lang.String, byte[]);
+    method public static android.nfc.NdefRecord createUri(android.net.Uri);
+    method public static android.nfc.NdefRecord createUri(java.lang.String);
+    method public int describeContents();
+    method public byte[] getId();
+    method public byte[] getPayload();
+    method public short getTnf();
+    method public byte[] getType();
+    method public deprecated byte[] toByteArray();
+    method public java.lang.String toMimeType();
+    method public android.net.Uri toUri();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final byte[] RTD_ALTERNATIVE_CARRIER;
+    field public static final byte[] RTD_HANDOVER_CARRIER;
+    field public static final byte[] RTD_HANDOVER_REQUEST;
+    field public static final byte[] RTD_HANDOVER_SELECT;
+    field public static final byte[] RTD_SMART_POSTER;
+    field public static final byte[] RTD_TEXT;
+    field public static final byte[] RTD_URI;
+    field public static final short TNF_ABSOLUTE_URI = 3; // 0x3
+    field public static final short TNF_EMPTY = 0; // 0x0
+    field public static final short TNF_EXTERNAL_TYPE = 4; // 0x4
+    field public static final short TNF_MIME_MEDIA = 2; // 0x2
+    field public static final short TNF_UNCHANGED = 6; // 0x6
+    field public static final short TNF_UNKNOWN = 5; // 0x5
+    field public static final short TNF_WELL_KNOWN = 1; // 0x1
+  }
+
+  public final class NfcAdapter {
+    method public void disableForegroundDispatch(android.app.Activity);
+    method public deprecated void disableForegroundNdefPush(android.app.Activity);
+    method public void enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], java.lang.String[][]);
+    method public deprecated void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage);
+    method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context);
+    method public boolean isEnabled();
+    method public boolean isNdefPushEnabled();
+    method public void setBeamPushUris(android.net.Uri[], android.app.Activity);
+    method public void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity);
+    method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...);
+    method public void setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...);
+    method public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...);
+    field public static final java.lang.String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
+    field public static final java.lang.String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
+    field public static final java.lang.String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED";
+    field public static final java.lang.String EXTRA_ID = "android.nfc.extra.ID";
+    field public static final java.lang.String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES";
+    field public static final java.lang.String EXTRA_TAG = "android.nfc.extra.TAG";
+  }
+
+  public static abstract interface NfcAdapter.CreateBeamUrisCallback {
+    method public abstract android.net.Uri[] createBeamUris(android.nfc.NfcEvent);
+  }
+
+  public static abstract interface NfcAdapter.CreateNdefMessageCallback {
+    method public abstract android.nfc.NdefMessage createNdefMessage(android.nfc.NfcEvent);
+  }
+
+  public static abstract interface NfcAdapter.OnNdefPushCompleteCallback {
+    method public abstract void onNdefPushComplete(android.nfc.NfcEvent);
+  }
+
+  public final class NfcEvent {
+    field public final android.nfc.NfcAdapter nfcAdapter;
+  }
+
+  public final class NfcManager {
+    method public android.nfc.NfcAdapter getDefaultAdapter();
+  }
+
+  public final class Tag implements android.os.Parcelable {
+    method public int describeContents();
+    method public byte[] getId();
+    method public java.lang.String[] getTechList();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class TagLostException extends java.io.IOException {
+    ctor public TagLostException();
+    ctor public TagLostException(java.lang.String);
+  }
+
+}
+
+package android.nfc.tech {
+
+   abstract class BasicTagTechnology implements android.nfc.tech.TagTechnology {
+    method public void close() throws java.io.IOException;
+    method public void connect() throws java.io.IOException;
+    method public android.nfc.Tag getTag();
+    method public boolean isConnected();
+  }
+
+  public final class IsoDep extends android.nfc.tech.BasicTagTechnology {
+    method public static android.nfc.tech.IsoDep get(android.nfc.Tag);
+    method public byte[] getHiLayerResponse();
+    method public byte[] getHistoricalBytes();
+    method public int getMaxTransceiveLength();
+    method public int getTimeout();
+    method public boolean isExtendedLengthApduSupported();
+    method public void setTimeout(int);
+    method public byte[] transceive(byte[]) throws java.io.IOException;
+  }
+
+  public final class MifareClassic extends android.nfc.tech.BasicTagTechnology {
+    method public boolean authenticateSectorWithKeyA(int, byte[]) throws java.io.IOException;
+    method public boolean authenticateSectorWithKeyB(int, byte[]) throws java.io.IOException;
+    method public int blockToSector(int);
+    method public void decrement(int, int) throws java.io.IOException;
+    method public static android.nfc.tech.MifareClassic get(android.nfc.Tag);
+    method public int getBlockCount();
+    method public int getBlockCountInSector(int);
+    method public int getMaxTransceiveLength();
+    method public int getSectorCount();
+    method public int getSize();
+    method public int getTimeout();
+    method public int getType();
+    method public void increment(int, int) throws java.io.IOException;
+    method public byte[] readBlock(int) throws java.io.IOException;
+    method public void restore(int) throws java.io.IOException;
+    method public int sectorToBlock(int);
+    method public void setTimeout(int);
+    method public byte[] transceive(byte[]) throws java.io.IOException;
+    method public void transfer(int) throws java.io.IOException;
+    method public void writeBlock(int, byte[]) throws java.io.IOException;
+    field public static final int BLOCK_SIZE = 16; // 0x10
+    field public static final byte[] KEY_DEFAULT;
+    field public static final byte[] KEY_MIFARE_APPLICATION_DIRECTORY;
+    field public static final byte[] KEY_NFC_FORUM;
+    field public static final int SIZE_1K = 1024; // 0x400
+    field public static final int SIZE_2K = 2048; // 0x800
+    field public static final int SIZE_4K = 4096; // 0x1000
+    field public static final int SIZE_MINI = 320; // 0x140
+    field public static final int TYPE_CLASSIC = 0; // 0x0
+    field public static final int TYPE_PLUS = 1; // 0x1
+    field public static final int TYPE_PRO = 2; // 0x2
+    field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
+  }
+
+  public final class MifareUltralight extends android.nfc.tech.BasicTagTechnology {
+    method public static android.nfc.tech.MifareUltralight get(android.nfc.Tag);
+    method public int getMaxTransceiveLength();
+    method public int getTimeout();
+    method public int getType();
+    method public byte[] readPages(int) throws java.io.IOException;
+    method public void setTimeout(int);
+    method public byte[] transceive(byte[]) throws java.io.IOException;
+    method public void writePage(int, byte[]) throws java.io.IOException;
+    field public static final int PAGE_SIZE = 4; // 0x4
+    field public static final int TYPE_ULTRALIGHT = 1; // 0x1
+    field public static final int TYPE_ULTRALIGHT_C = 2; // 0x2
+    field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
+  }
+
+  public final class Ndef extends android.nfc.tech.BasicTagTechnology {
+    method public boolean canMakeReadOnly();
+    method public static android.nfc.tech.Ndef get(android.nfc.Tag);
+    method public android.nfc.NdefMessage getCachedNdefMessage();
+    method public int getMaxSize();
+    method public android.nfc.NdefMessage getNdefMessage() throws android.nfc.FormatException, java.io.IOException;
+    method public java.lang.String getType();
+    method public boolean isWritable();
+    method public boolean makeReadOnly() throws java.io.IOException;
+    method public void writeNdefMessage(android.nfc.NdefMessage) throws android.nfc.FormatException, java.io.IOException;
+    field public static final java.lang.String MIFARE_CLASSIC = "com.nxp.ndef.mifareclassic";
+    field public static final java.lang.String NFC_FORUM_TYPE_1 = "org.nfcforum.ndef.type1";
+    field public static final java.lang.String NFC_FORUM_TYPE_2 = "org.nfcforum.ndef.type2";
+    field public static final java.lang.String NFC_FORUM_TYPE_3 = "org.nfcforum.ndef.type3";
+    field public static final java.lang.String NFC_FORUM_TYPE_4 = "org.nfcforum.ndef.type4";
+  }
+
+  public final class NdefFormatable extends android.nfc.tech.BasicTagTechnology {
+    method public void format(android.nfc.NdefMessage) throws android.nfc.FormatException, java.io.IOException;
+    method public void formatReadOnly(android.nfc.NdefMessage) throws android.nfc.FormatException, java.io.IOException;
+    method public static android.nfc.tech.NdefFormatable get(android.nfc.Tag);
+  }
+
+  public final class NfcA extends android.nfc.tech.BasicTagTechnology {
+    method public static android.nfc.tech.NfcA get(android.nfc.Tag);
+    method public byte[] getAtqa();
+    method public int getMaxTransceiveLength();
+    method public short getSak();
+    method public int getTimeout();
+    method public void setTimeout(int);
+    method public byte[] transceive(byte[]) throws java.io.IOException;
+  }
+
+  public final class NfcB extends android.nfc.tech.BasicTagTechnology {
+    method public static android.nfc.tech.NfcB get(android.nfc.Tag);
+    method public byte[] getApplicationData();
+    method public int getMaxTransceiveLength();
+    method public byte[] getProtocolInfo();
+    method public byte[] transceive(byte[]) throws java.io.IOException;
+  }
+
+  public final class NfcBarcode extends android.nfc.tech.BasicTagTechnology {
+    method public static android.nfc.tech.NfcBarcode get(android.nfc.Tag);
+    method public byte[] getBarcode();
+    method public int getType();
+    field public static final int TYPE_KOVIO = 1; // 0x1
+    field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
+  }
+
+  public final class NfcF extends android.nfc.tech.BasicTagTechnology {
+    method public static android.nfc.tech.NfcF get(android.nfc.Tag);
+    method public byte[] getManufacturer();
+    method public int getMaxTransceiveLength();
+    method public byte[] getSystemCode();
+    method public int getTimeout();
+    method public void setTimeout(int);
+    method public byte[] transceive(byte[]) throws java.io.IOException;
+  }
+
+  public final class NfcV extends android.nfc.tech.BasicTagTechnology {
+    method public static android.nfc.tech.NfcV get(android.nfc.Tag);
+    method public byte getDsfId();
+    method public int getMaxTransceiveLength();
+    method public byte getResponseFlags();
+    method public byte[] transceive(byte[]) throws java.io.IOException;
+  }
+
+  public abstract interface TagTechnology implements java.io.Closeable {
+    method public abstract void close() throws java.io.IOException;
+    method public abstract void connect() throws java.io.IOException;
+    method public abstract android.nfc.Tag getTag();
+    method public abstract boolean isConnected();
+  }
+
+}
+
+package android.opengl {
+
+  public class EGL14 {
+    ctor public EGL14();
+    method public static boolean eglBindAPI(int);
+    method public static boolean eglBindTexImage(android.opengl.EGLDisplay, android.opengl.EGLSurface, int);
+    method public static boolean eglChooseConfig(android.opengl.EGLDisplay, int[], int, android.opengl.EGLConfig[], int, int, int[], int);
+    method public static boolean eglCopyBuffers(android.opengl.EGLDisplay, android.opengl.EGLSurface, int);
+    method public static android.opengl.EGLContext eglCreateContext(android.opengl.EGLDisplay, android.opengl.EGLConfig, android.opengl.EGLContext, int[], int);
+    method public static android.opengl.EGLSurface eglCreatePbufferFromClientBuffer(android.opengl.EGLDisplay, int, int, android.opengl.EGLConfig, int[], int);
+    method public static android.opengl.EGLSurface eglCreatePbufferSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, int[], int);
+    method public static android.opengl.EGLSurface eglCreatePixmapSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, int, int[], int);
+    method public static android.opengl.EGLSurface eglCreateWindowSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, java.lang.Object, int[], int);
+    method public static boolean eglDestroyContext(android.opengl.EGLDisplay, android.opengl.EGLContext);
+    method public static boolean eglDestroySurface(android.opengl.EGLDisplay, android.opengl.EGLSurface);
+    method public static boolean eglGetConfigAttrib(android.opengl.EGLDisplay, android.opengl.EGLConfig, int, int[], int);
+    method public static boolean eglGetConfigs(android.opengl.EGLDisplay, android.opengl.EGLConfig[], int, int, int[], int);
+    method public static android.opengl.EGLContext eglGetCurrentContext();
+    method public static android.opengl.EGLDisplay eglGetCurrentDisplay();
+    method public static android.opengl.EGLSurface eglGetCurrentSurface(int);
+    method public static android.opengl.EGLDisplay eglGetDisplay(int);
+    method public static int eglGetError();
+    method public static boolean eglInitialize(android.opengl.EGLDisplay, int[], int, int[], int);
+    method public static boolean eglMakeCurrent(android.opengl.EGLDisplay, android.opengl.EGLSurface, android.opengl.EGLSurface, android.opengl.EGLContext);
+    method public static int eglQueryAPI();
+    method public static boolean eglQueryContext(android.opengl.EGLDisplay, android.opengl.EGLContext, int, int[], int);
+    method public static java.lang.String eglQueryString(android.opengl.EGLDisplay, int);
+    method public static boolean eglQuerySurface(android.opengl.EGLDisplay, android.opengl.EGLSurface, int, int[], int);
+    method public static boolean eglReleaseTexImage(android.opengl.EGLDisplay, android.opengl.EGLSurface, int);
+    method public static boolean eglReleaseThread();
+    method public static boolean eglSurfaceAttrib(android.opengl.EGLDisplay, android.opengl.EGLSurface, int, int);
+    method public static boolean eglSwapBuffers(android.opengl.EGLDisplay, android.opengl.EGLSurface);
+    method public static boolean eglSwapInterval(android.opengl.EGLDisplay, int);
+    method public static boolean eglTerminate(android.opengl.EGLDisplay);
+    method public static boolean eglWaitClient();
+    method public static boolean eglWaitGL();
+    method public static boolean eglWaitNative(int);
+    field public static final int EGL_ALPHA_MASK_SIZE = 12350; // 0x303e
+    field public static final int EGL_ALPHA_SIZE = 12321; // 0x3021
+    field public static final int EGL_BACK_BUFFER = 12420; // 0x3084
+    field public static final int EGL_BAD_ACCESS = 12290; // 0x3002
+    field public static final int EGL_BAD_ALLOC = 12291; // 0x3003
+    field public static final int EGL_BAD_ATTRIBUTE = 12292; // 0x3004
+    field public static final int EGL_BAD_CONFIG = 12293; // 0x3005
+    field public static final int EGL_BAD_CONTEXT = 12294; // 0x3006
+    field public static final int EGL_BAD_CURRENT_SURFACE = 12295; // 0x3007
+    field public static final int EGL_BAD_DISPLAY = 12296; // 0x3008
+    field public static final int EGL_BAD_MATCH = 12297; // 0x3009
+    field public static final int EGL_BAD_NATIVE_PIXMAP = 12298; // 0x300a
+    field public static final int EGL_BAD_NATIVE_WINDOW = 12299; // 0x300b
+    field public static final int EGL_BAD_PARAMETER = 12300; // 0x300c
+    field public static final int EGL_BAD_SURFACE = 12301; // 0x300d
+    field public static final int EGL_BIND_TO_TEXTURE_RGB = 12345; // 0x3039
+    field public static final int EGL_BIND_TO_TEXTURE_RGBA = 12346; // 0x303a
+    field public static final int EGL_BLUE_SIZE = 12322; // 0x3022
+    field public static final int EGL_BUFFER_DESTROYED = 12437; // 0x3095
+    field public static final int EGL_BUFFER_PRESERVED = 12436; // 0x3094
+    field public static final int EGL_BUFFER_SIZE = 12320; // 0x3020
+    field public static final int EGL_CLIENT_APIS = 12429; // 0x308d
+    field public static final int EGL_COLOR_BUFFER_TYPE = 12351; // 0x303f
+    field public static final int EGL_CONFIG_CAVEAT = 12327; // 0x3027
+    field public static final int EGL_CONFIG_ID = 12328; // 0x3028
+    field public static final int EGL_CONFORMANT = 12354; // 0x3042
+    field public static final int EGL_CONTEXT_CLIENT_TYPE = 12439; // 0x3097
+    field public static final int EGL_CONTEXT_CLIENT_VERSION = 12440; // 0x3098
+    field public static final int EGL_CONTEXT_LOST = 12302; // 0x300e
+    field public static final int EGL_CORE_NATIVE_ENGINE = 12379; // 0x305b
+    field public static final int EGL_DEFAULT_DISPLAY = 0; // 0x0
+    field public static final int EGL_DEPTH_SIZE = 12325; // 0x3025
+    field public static final int EGL_DISPLAY_SCALING = 10000; // 0x2710
+    field public static final int EGL_DRAW = 12377; // 0x3059
+    field public static final int EGL_EXTENSIONS = 12373; // 0x3055
+    field public static final int EGL_FALSE = 0; // 0x0
+    field public static final int EGL_GREEN_SIZE = 12323; // 0x3023
+    field public static final int EGL_HEIGHT = 12374; // 0x3056
+    field public static final int EGL_HORIZONTAL_RESOLUTION = 12432; // 0x3090
+    field public static final int EGL_LARGEST_PBUFFER = 12376; // 0x3058
+    field public static final int EGL_LEVEL = 12329; // 0x3029
+    field public static final int EGL_LUMINANCE_BUFFER = 12431; // 0x308f
+    field public static final int EGL_LUMINANCE_SIZE = 12349; // 0x303d
+    field public static final int EGL_MATCH_NATIVE_PIXMAP = 12353; // 0x3041
+    field public static final int EGL_MAX_PBUFFER_HEIGHT = 12330; // 0x302a
+    field public static final int EGL_MAX_PBUFFER_PIXELS = 12331; // 0x302b
+    field public static final int EGL_MAX_PBUFFER_WIDTH = 12332; // 0x302c
+    field public static final int EGL_MAX_SWAP_INTERVAL = 12348; // 0x303c
+    field public static final int EGL_MIN_SWAP_INTERVAL = 12347; // 0x303b
+    field public static final int EGL_MIPMAP_LEVEL = 12419; // 0x3083
+    field public static final int EGL_MIPMAP_TEXTURE = 12418; // 0x3082
+    field public static final int EGL_MULTISAMPLE_RESOLVE = 12441; // 0x3099
+    field public static final int EGL_MULTISAMPLE_RESOLVE_BOX = 12443; // 0x309b
+    field public static final int EGL_MULTISAMPLE_RESOLVE_BOX_BIT = 512; // 0x200
+    field public static final int EGL_MULTISAMPLE_RESOLVE_DEFAULT = 12442; // 0x309a
+    field public static final int EGL_NATIVE_RENDERABLE = 12333; // 0x302d
+    field public static final int EGL_NATIVE_VISUAL_ID = 12334; // 0x302e
+    field public static final int EGL_NATIVE_VISUAL_TYPE = 12335; // 0x302f
+    field public static final int EGL_NONE = 12344; // 0x3038
+    field public static final int EGL_NON_CONFORMANT_CONFIG = 12369; // 0x3051
+    field public static final int EGL_NOT_INITIALIZED = 12289; // 0x3001
+    field public static android.opengl.EGLContext EGL_NO_CONTEXT;
+    field public static android.opengl.EGLDisplay EGL_NO_DISPLAY;
+    field public static android.opengl.EGLSurface EGL_NO_SURFACE;
+    field public static final int EGL_NO_TEXTURE = 12380; // 0x305c
+    field public static final int EGL_OPENGL_API = 12450; // 0x30a2
+    field public static final int EGL_OPENGL_BIT = 8; // 0x8
+    field public static final int EGL_OPENGL_ES2_BIT = 4; // 0x4
+    field public static final int EGL_OPENGL_ES_API = 12448; // 0x30a0
+    field public static final int EGL_OPENGL_ES_BIT = 1; // 0x1
+    field public static final int EGL_OPENVG_API = 12449; // 0x30a1
+    field public static final int EGL_OPENVG_BIT = 2; // 0x2
+    field public static final int EGL_OPENVG_IMAGE = 12438; // 0x3096
+    field public static final int EGL_PBUFFER_BIT = 1; // 0x1
+    field public static final int EGL_PIXEL_ASPECT_RATIO = 12434; // 0x3092
+    field public static final int EGL_PIXMAP_BIT = 2; // 0x2
+    field public static final int EGL_READ = 12378; // 0x305a
+    field public static final int EGL_RED_SIZE = 12324; // 0x3024
+    field public static final int EGL_RENDERABLE_TYPE = 12352; // 0x3040
+    field public static final int EGL_RENDER_BUFFER = 12422; // 0x3086
+    field public static final int EGL_RGB_BUFFER = 12430; // 0x308e
+    field public static final int EGL_SAMPLES = 12337; // 0x3031
+    field public static final int EGL_SAMPLE_BUFFERS = 12338; // 0x3032
+    field public static final int EGL_SINGLE_BUFFER = 12421; // 0x3085
+    field public static final int EGL_SLOW_CONFIG = 12368; // 0x3050
+    field public static final int EGL_STENCIL_SIZE = 12326; // 0x3026
+    field public static final int EGL_SUCCESS = 12288; // 0x3000
+    field public static final int EGL_SURFACE_TYPE = 12339; // 0x3033
+    field public static final int EGL_SWAP_BEHAVIOR = 12435; // 0x3093
+    field public static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 1024; // 0x400
+    field public static final int EGL_TEXTURE_2D = 12383; // 0x305f
+    field public static final int EGL_TEXTURE_FORMAT = 12416; // 0x3080
+    field public static final int EGL_TEXTURE_RGB = 12381; // 0x305d
+    field public static final int EGL_TEXTURE_RGBA = 12382; // 0x305e
+    field public static final int EGL_TEXTURE_TARGET = 12417; // 0x3081
+    field public static final int EGL_TRANSPARENT_BLUE_VALUE = 12341; // 0x3035
+    field public static final int EGL_TRANSPARENT_GREEN_VALUE = 12342; // 0x3036
+    field public static final int EGL_TRANSPARENT_RED_VALUE = 12343; // 0x3037
+    field public static final int EGL_TRANSPARENT_RGB = 12370; // 0x3052
+    field public static final int EGL_TRANSPARENT_TYPE = 12340; // 0x3034
+    field public static final int EGL_TRUE = 1; // 0x1
+    field public static final int EGL_VENDOR = 12371; // 0x3053
+    field public static final int EGL_VERSION = 12372; // 0x3054
+    field public static final int EGL_VERTICAL_RESOLUTION = 12433; // 0x3091
+    field public static final int EGL_VG_ALPHA_FORMAT = 12424; // 0x3088
+    field public static final int EGL_VG_ALPHA_FORMAT_NONPRE = 12427; // 0x308b
+    field public static final int EGL_VG_ALPHA_FORMAT_PRE = 12428; // 0x308c
+    field public static final int EGL_VG_ALPHA_FORMAT_PRE_BIT = 64; // 0x40
+    field public static final int EGL_VG_COLORSPACE = 12423; // 0x3087
+    field public static final int EGL_VG_COLORSPACE_LINEAR = 12426; // 0x308a
+    field public static final int EGL_VG_COLORSPACE_LINEAR_BIT = 32; // 0x20
+    field public static final int EGL_VG_COLORSPACE_sRGB = 12425; // 0x3089
+    field public static final int EGL_WIDTH = 12375; // 0x3057
+    field public static final int EGL_WINDOW_BIT = 4; // 0x4
+  }
+
+  public class EGLConfig extends android.opengl.EGLObjectHandle {
+  }
+
+  public class EGLContext extends android.opengl.EGLObjectHandle {
+  }
+
+  public class EGLDisplay extends android.opengl.EGLObjectHandle {
+  }
+
+  public abstract class EGLObjectHandle {
+    ctor protected EGLObjectHandle(int);
+    method public int getHandle();
+  }
+
+  public class EGLSurface extends android.opengl.EGLObjectHandle {
+  }
+
+  public class ETC1 {
+    ctor public ETC1();
+    method public static void decodeBlock(java.nio.Buffer, java.nio.Buffer);
+    method public static void decodeImage(java.nio.Buffer, java.nio.Buffer, int, int, int, int);
+    method public static void encodeBlock(java.nio.Buffer, int, java.nio.Buffer);
+    method public static void encodeImage(java.nio.Buffer, int, int, int, int, java.nio.Buffer);
+    method public static void formatHeader(java.nio.Buffer, int, int);
+    method public static int getEncodedDataSize(int, int);
+    method public static int getHeight(java.nio.Buffer);
+    method public static int getWidth(java.nio.Buffer);
+    method public static boolean isValid(java.nio.Buffer);
+    field public static final int DECODED_BLOCK_SIZE = 48; // 0x30
+    field public static final int ENCODED_BLOCK_SIZE = 8; // 0x8
+    field public static final int ETC1_RGB8_OES = 36196; // 0x8d64
+    field public static final int ETC_PKM_HEADER_SIZE = 16; // 0x10
+  }
+
+  public class ETC1Util {
+    ctor public ETC1Util();
+    method public static android.opengl.ETC1Util.ETC1Texture compressTexture(java.nio.Buffer, int, int, int, int);
+    method public static android.opengl.ETC1Util.ETC1Texture createTexture(java.io.InputStream) throws java.io.IOException;
+    method public static boolean isETC1Supported();
+    method public static void loadTexture(int, int, int, int, int, java.io.InputStream) throws java.io.IOException;
+    method public static void loadTexture(int, int, int, int, int, android.opengl.ETC1Util.ETC1Texture);
+    method public static void writeTexture(android.opengl.ETC1Util.ETC1Texture, java.io.OutputStream) throws java.io.IOException;
+  }
+
+  public static class ETC1Util.ETC1Texture {
+    ctor public ETC1Util.ETC1Texture(int, int, java.nio.ByteBuffer);
+    method public java.nio.ByteBuffer getData();
+    method public int getHeight();
+    method public int getWidth();
+  }
+
+  public class GLDebugHelper {
+    ctor public GLDebugHelper();
+    method public static javax.microedition.khronos.opengles.GL wrap(javax.microedition.khronos.opengles.GL, int, java.io.Writer);
+    method public static javax.microedition.khronos.egl.EGL wrap(javax.microedition.khronos.egl.EGL, int, java.io.Writer);
+    field public static final int CONFIG_CHECK_GL_ERROR = 1; // 0x1
+    field public static final int CONFIG_CHECK_THREAD = 2; // 0x2
+    field public static final int CONFIG_LOG_ARGUMENT_NAMES = 4; // 0x4
+    field public static final int ERROR_WRONG_THREAD = 28672; // 0x7000
+  }
+
+  public class GLES10 {
+    ctor public GLES10();
+    method public static void glActiveTexture(int);
+    method public static void glAlphaFunc(int, float);
+    method public static void glAlphaFuncx(int, int);
+    method public static void glBindTexture(int, int);
+    method public static void glBlendFunc(int, int);
+    method public static void glClear(int);
+    method public static void glClearColor(float, float, float, float);
+    method public static void glClearColorx(int, int, int, int);
+    method public static void glClearDepthf(float);
+    method public static void glClearDepthx(int);
+    method public static void glClearStencil(int);
+    method public static void glClientActiveTexture(int);
+    method public static void glColor4f(float, float, float, float);
+    method public static void glColor4x(int, int, int, int);
+    method public static void glColorMask(boolean, boolean, boolean, boolean);
+    method public static void glColorPointer(int, int, int, java.nio.Buffer);
+    method public static void glCompressedTexImage2D(int, int, int, int, int, int, int, java.nio.Buffer);
+    method public static void glCompressedTexSubImage2D(int, int, int, int, int, int, int, int, java.nio.Buffer);
+    method public static void glCopyTexImage2D(int, int, int, int, int, int, int, int);
+    method public static void glCopyTexSubImage2D(int, int, int, int, int, int, int, int);
+    method public static void glCullFace(int);
+    method public static void glDeleteTextures(int, int[], int);
+    method public static void glDeleteTextures(int, java.nio.IntBuffer);
+    method public static void glDepthFunc(int);
+    method public static void glDepthMask(boolean);
+    method public static void glDepthRangef(float, float);
+    method public static void glDepthRangex(int, int);
+    method public static void glDisable(int);
+    method public static void glDisableClientState(int);
+    method public static void glDrawArrays(int, int, int);
+    method public static void glDrawElements(int, int, int, java.nio.Buffer);
+    method public static void glEnable(int);
+    method public static void glEnableClientState(int);
+    method public static void glFinish();
+    method public static void glFlush();
+    method public static void glFogf(int, float);
+    method public static void glFogfv(int, float[], int);
+    method public static void glFogfv(int, java.nio.FloatBuffer);
+    method public static void glFogx(int, int);
+    method public static void glFogxv(int, int[], int);
+    method public static void glFogxv(int, java.nio.IntBuffer);
+    method public static void glFrontFace(int);
+    method public static void glFrustumf(float, float, float, float, float, float);
+    method public static void glFrustumx(int, int, int, int, int, int);
+    method public static void glGenTextures(int, int[], int);
+    method public static void glGenTextures(int, java.nio.IntBuffer);
+    method public static int glGetError();
+    method public static void glGetIntegerv(int, int[], int);
+    method public static void glGetIntegerv(int, java.nio.IntBuffer);
+    method public static java.lang.String glGetString(int);
+    method public static void glHint(int, int);
+    method public static void glLightModelf(int, float);
+    method public static void glLightModelfv(int, float[], int);
+    method public static void glLightModelfv(int, java.nio.FloatBuffer);
+    method public static void glLightModelx(int, int);
+    method public static void glLightModelxv(int, int[], int);
+    method public static void glLightModelxv(int, java.nio.IntBuffer);
+    method public static void glLightf(int, int, float);
+    method public static void glLightfv(int, int, float[], int);
+    method public static void glLightfv(int, int, java.nio.FloatBuffer);
+    method public static void glLightx(int, int, int);
+    method public static void glLightxv(int, int, int[], int);
+    method public static void glLightxv(int, int, java.nio.IntBuffer);
+    method public static void glLineWidth(float);
+    method public static void glLineWidthx(int);
+    method public static void glLoadIdentity();
+    method public static void glLoadMatrixf(float[], int);
+    method public static void glLoadMatrixf(java.nio.FloatBuffer);
+    method public static void glLoadMatrixx(int[], int);
+    method public static void glLoadMatrixx(java.nio.IntBuffer);
+    method public static void glLogicOp(int);
+    method public static void glMaterialf(int, int, float);
+    method public static void glMaterialfv(int, int, float[], int);
+    method public static void glMaterialfv(int, int, java.nio.FloatBuffer);
+    method public static void glMaterialx(int, int, int);
+    method public static void glMaterialxv(int, int, int[], int);
+    method public static void glMaterialxv(int, int, java.nio.IntBuffer);
+    method public static void glMatrixMode(int);
+    method public static void glMultMatrixf(float[], int);
+    method public static void glMultMatrixf(java.nio.FloatBuffer);
+    method public static void glMultMatrixx(int[], int);
+    method public static void glMultMatrixx(java.nio.IntBuffer);
+    method public static void glMultiTexCoord4f(int, float, float, float, float);
+    method public static void glMultiTexCoord4x(int, int, int, int, int);
+    method public static void glNormal3f(float, float, float);
+    method public static void glNormal3x(int, int, int);
+    method public static void glNormalPointer(int, int, java.nio.Buffer);
+    method public static void glOrthof(float, float, float, float, float, float);
+    method public static void glOrthox(int, int, int, int, int, int);
+    method public static void glPixelStorei(int, int);
+    method public static void glPointSize(float);
+    method public static void glPointSizex(int);
+    method public static void glPolygonOffset(float, float);
+    method public static void glPolygonOffsetx(int, int);
+    method public static void glPopMatrix();
+    method public static void glPushMatrix();
+    method public static void glReadPixels(int, int, int, int, int, int, java.nio.Buffer);
+    method public static void glRotatef(float, float, float, float);
+    method public static void glRotatex(int, int, int, int);
+    method public static void glSampleCoverage(float, boolean);
+    method public static void glSampleCoveragex(int, boolean);
+    method public static void glScalef(float, float, float);
+    method public static void glScalex(int, int, int);
+    method public static void glScissor(int, int, int, int);
+    method public static void glShadeModel(int);
+    method public static void glStencilFunc(int, int, int);
+    method public static void glStencilMask(int);
+    method public static void glStencilOp(int, int, int);
+    method public static void glTexCoordPointer(int, int, int, java.nio.Buffer);
+    method public static void glTexEnvf(int, int, float);
+    method public static void glTexEnvfv(int, int, float[], int);
+    method public static void glTexEnvfv(int, int, java.nio.FloatBuffer);
+    method public static void glTexEnvx(int, int, int);
+    method public static void glTexEnvxv(int, int, int[], int);
+    method public static void glTexEnvxv(int, int, java.nio.IntBuffer);
+    method public static void glTexImage2D(int, int, int, int, int, int, int, int, java.nio.Buffer);
+    method public static void glTexParameterf(int, int, float);
+    method public static void glTexParameterx(int, int, int);
+    method public static void glTexSubImage2D(int, int, int, int, int, int, int, int, java.nio.Buffer);
+    method public static void glTranslatef(float, float, float);
+    method public static void glTranslatex(int, int, int);
+    method public static void glVertexPointer(int, int, int, java.nio.Buffer);
+    method public static void glViewport(int, int, int, int);
+    field public static final int GL_ADD = 260; // 0x104
+    field public static final int GL_ALIASED_LINE_WIDTH_RANGE = 33902; // 0x846e
+    field public static final int GL_ALIASED_POINT_SIZE_RANGE = 33901; // 0x846d
+    field public static final int GL_ALPHA = 6406; // 0x1906
+    field public static final int GL_ALPHA_BITS = 3413; // 0xd55
+    field public static final int GL_ALPHA_TEST = 3008; // 0xbc0
+    field public static final int GL_ALWAYS = 519; // 0x207
+    field public static final int GL_AMBIENT = 4608; // 0x1200
+    field public static final int GL_AMBIENT_AND_DIFFUSE = 5634; // 0x1602
+    field public static final int GL_AND = 5377; // 0x1501
+    field public static final int GL_AND_INVERTED = 5380; // 0x1504
+    field public static final int GL_AND_REVERSE = 5378; // 0x1502
+    field public static final int GL_BACK = 1029; // 0x405
+    field public static final int GL_BLEND = 3042; // 0xbe2
+    field public static final int GL_BLUE_BITS = 3412; // 0xd54
+    field public static final int GL_BYTE = 5120; // 0x1400
+    field public static final int GL_CCW = 2305; // 0x901
+    field public static final int GL_CLAMP_TO_EDGE = 33071; // 0x812f
+    field public static final int GL_CLEAR = 5376; // 0x1500
+    field public static final int GL_COLOR_ARRAY = 32886; // 0x8076
+    field public static final int GL_COLOR_BUFFER_BIT = 16384; // 0x4000
+    field public static final int GL_COLOR_LOGIC_OP = 3058; // 0xbf2
+    field public static final int GL_COLOR_MATERIAL = 2903; // 0xb57
+    field public static final int GL_COMPRESSED_TEXTURE_FORMATS = 34467; // 0x86a3
+    field public static final int GL_CONSTANT_ATTENUATION = 4615; // 0x1207
+    field public static final int GL_COPY = 5379; // 0x1503
+    field public static final int GL_COPY_INVERTED = 5388; // 0x150c
+    field public static final int GL_CULL_FACE = 2884; // 0xb44
+    field public static final int GL_CW = 2304; // 0x900
+    field public static final int GL_DECAL = 8449; // 0x2101
+    field public static final int GL_DECR = 7683; // 0x1e03
+    field public static final int GL_DEPTH_BITS = 3414; // 0xd56
+    field public static final int GL_DEPTH_BUFFER_BIT = 256; // 0x100
+    field public static final int GL_DEPTH_TEST = 2929; // 0xb71
+    field public static final int GL_DIFFUSE = 4609; // 0x1201
+    field public static final int GL_DITHER = 3024; // 0xbd0
+    field public static final int GL_DONT_CARE = 4352; // 0x1100
+    field public static final int GL_DST_ALPHA = 772; // 0x304
+    field public static final int GL_DST_COLOR = 774; // 0x306
+    field public static final int GL_EMISSION = 5632; // 0x1600
+    field public static final int GL_EQUAL = 514; // 0x202
+    field public static final int GL_EQUIV = 5385; // 0x1509
+    field public static final int GL_EXP = 2048; // 0x800
+    field public static final int GL_EXP2 = 2049; // 0x801
+    field public static final int GL_EXTENSIONS = 7939; // 0x1f03
+    field public static final int GL_FALSE = 0; // 0x0
+    field public static final int GL_FASTEST = 4353; // 0x1101
+    field public static final int GL_FIXED = 5132; // 0x140c
+    field public static final int GL_FLAT = 7424; // 0x1d00
+    field public static final int GL_FLOAT = 5126; // 0x1406
+    field public static final int GL_FOG = 2912; // 0xb60
+    field public static final int GL_FOG_COLOR = 2918; // 0xb66
+    field public static final int GL_FOG_DENSITY = 2914; // 0xb62
+    field public static final int GL_FOG_END = 2916; // 0xb64
+    field public static final int GL_FOG_HINT = 3156; // 0xc54
+    field public static final int GL_FOG_MODE = 2917; // 0xb65
+    field public static final int GL_FOG_START = 2915; // 0xb63
+    field public static final int GL_FRONT = 1028; // 0x404
+    field public static final int GL_FRONT_AND_BACK = 1032; // 0x408
+    field public static final int GL_GEQUAL = 518; // 0x206
+    field public static final int GL_GREATER = 516; // 0x204
+    field public static final int GL_GREEN_BITS = 3411; // 0xd53
+    field public static final int GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES = 35739; // 0x8b9b
+    field public static final int GL_IMPLEMENTATION_COLOR_READ_TYPE_OES = 35738; // 0x8b9a
+    field public static final int GL_INCR = 7682; // 0x1e02
+    field public static final int GL_INVALID_ENUM = 1280; // 0x500
+    field public static final int GL_INVALID_OPERATION = 1282; // 0x502
+    field public static final int GL_INVALID_VALUE = 1281; // 0x501
+    field public static final int GL_INVERT = 5386; // 0x150a
+    field public static final int GL_KEEP = 7680; // 0x1e00
+    field public static final int GL_LEQUAL = 515; // 0x203
+    field public static final int GL_LESS = 513; // 0x201
+    field public static final int GL_LIGHT0 = 16384; // 0x4000
+    field public static final int GL_LIGHT1 = 16385; // 0x4001
+    field public static final int GL_LIGHT2 = 16386; // 0x4002
+    field public static final int GL_LIGHT3 = 16387; // 0x4003
+    field public static final int GL_LIGHT4 = 16388; // 0x4004
+    field public static final int GL_LIGHT5 = 16389; // 0x4005
+    field public static final int GL_LIGHT6 = 16390; // 0x4006
+    field public static final int GL_LIGHT7 = 16391; // 0x4007
+    field public static final int GL_LIGHTING = 2896; // 0xb50
+    field public static final int GL_LIGHT_MODEL_AMBIENT = 2899; // 0xb53
+    field public static final int GL_LIGHT_MODEL_TWO_SIDE = 2898; // 0xb52
+    field public static final int GL_LINEAR = 9729; // 0x2601
+    field public static final int GL_LINEAR_ATTENUATION = 4616; // 0x1208
+    field public static final int GL_LINEAR_MIPMAP_LINEAR = 9987; // 0x2703
+    field public static final int GL_LINEAR_MIPMAP_NEAREST = 9985; // 0x2701
+    field public static final int GL_LINES = 1; // 0x1
+    field public static final int GL_LINE_LOOP = 2; // 0x2
+    field public static final int GL_LINE_SMOOTH = 2848; // 0xb20
+    field public static final int GL_LINE_SMOOTH_HINT = 3154; // 0xc52
+    field public static final int GL_LINE_STRIP = 3; // 0x3
+    field public static final int GL_LUMINANCE = 6409; // 0x1909
+    field public static final int GL_LUMINANCE_ALPHA = 6410; // 0x190a
+    field public static final int GL_MAX_ELEMENTS_INDICES = 33001; // 0x80e9
+    field public static final int GL_MAX_ELEMENTS_VERTICES = 33000; // 0x80e8
+    field public static final int GL_MAX_LIGHTS = 3377; // 0xd31
+    field public static final int GL_MAX_MODELVIEW_STACK_DEPTH = 3382; // 0xd36
+    field public static final int GL_MAX_PROJECTION_STACK_DEPTH = 3384; // 0xd38
+    field public static final int GL_MAX_TEXTURE_SIZE = 3379; // 0xd33
+    field public static final int GL_MAX_TEXTURE_STACK_DEPTH = 3385; // 0xd39
+    field public static final int GL_MAX_TEXTURE_UNITS = 34018; // 0x84e2
+    field public static final int GL_MAX_VIEWPORT_DIMS = 3386; // 0xd3a
+    field public static final int GL_MODELVIEW = 5888; // 0x1700
+    field public static final int GL_MODULATE = 8448; // 0x2100
+    field public static final int GL_MULTISAMPLE = 32925; // 0x809d
+    field public static final int GL_NAND = 5390; // 0x150e
+    field public static final int GL_NEAREST = 9728; // 0x2600
+    field public static final int GL_NEAREST_MIPMAP_LINEAR = 9986; // 0x2702
+    field public static final int GL_NEAREST_MIPMAP_NEAREST = 9984; // 0x2700
+    field public static final int GL_NEVER = 512; // 0x200
+    field public static final int GL_NICEST = 4354; // 0x1102
+    field public static final int GL_NOOP = 5381; // 0x1505
+    field public static final int GL_NOR = 5384; // 0x1508
+    field public static final int GL_NORMALIZE = 2977; // 0xba1
+    field public static final int GL_NORMAL_ARRAY = 32885; // 0x8075
+    field public static final int GL_NOTEQUAL = 517; // 0x205
+    field public static final int GL_NO_ERROR = 0; // 0x0
+    field public static final int GL_NUM_COMPRESSED_TEXTURE_FORMATS = 34466; // 0x86a2
+    field public static final int GL_ONE = 1; // 0x1
+    field public static final int GL_ONE_MINUS_DST_ALPHA = 773; // 0x305
+    field public static final int GL_ONE_MINUS_DST_COLOR = 775; // 0x307
+    field public static final int GL_ONE_MINUS_SRC_ALPHA = 771; // 0x303
+    field public static final int GL_ONE_MINUS_SRC_COLOR = 769; // 0x301
+    field public static final int GL_OR = 5383; // 0x1507
+    field public static final int GL_OR_INVERTED = 5389; // 0x150d
+    field public static final int GL_OR_REVERSE = 5387; // 0x150b
+    field public static final int GL_OUT_OF_MEMORY = 1285; // 0x505
+    field public static final int GL_PACK_ALIGNMENT = 3333; // 0xd05
+    field public static final int GL_PALETTE4_R5_G6_B5_OES = 35730; // 0x8b92
+    field public static final int GL_PALETTE4_RGB5_A1_OES = 35732; // 0x8b94
+    field public static final int GL_PALETTE4_RGB8_OES = 35728; // 0x8b90
+    field public static final int GL_PALETTE4_RGBA4_OES = 35731; // 0x8b93
+    field public static final int GL_PALETTE4_RGBA8_OES = 35729; // 0x8b91
+    field public static final int GL_PALETTE8_R5_G6_B5_OES = 35735; // 0x8b97
+    field public static final int GL_PALETTE8_RGB5_A1_OES = 35737; // 0x8b99
+    field public static final int GL_PALETTE8_RGB8_OES = 35733; // 0x8b95
+    field public static final int GL_PALETTE8_RGBA4_OES = 35736; // 0x8b98
+    field public static final int GL_PALETTE8_RGBA8_OES = 35734; // 0x8b96
+    field public static final int GL_PERSPECTIVE_CORRECTION_HINT = 3152; // 0xc50
+    field public static final int GL_POINTS = 0; // 0x0
+    field public static final int GL_POINT_FADE_THRESHOLD_SIZE = 33064; // 0x8128
+    field public static final int GL_POINT_SIZE = 2833; // 0xb11
+    field public static final int GL_POINT_SMOOTH = 2832; // 0xb10
+    field public static final int GL_POINT_SMOOTH_HINT = 3153; // 0xc51
+    field public static final int GL_POLYGON_OFFSET_FILL = 32823; // 0x8037
+    field public static final int GL_POLYGON_SMOOTH_HINT = 3155; // 0xc53
+    field public static final int GL_POSITION = 4611; // 0x1203
+    field public static final int GL_PROJECTION = 5889; // 0x1701
+    field public static final int GL_QUADRATIC_ATTENUATION = 4617; // 0x1209
+    field public static final int GL_RED_BITS = 3410; // 0xd52
+    field public static final int GL_RENDERER = 7937; // 0x1f01
+    field public static final int GL_REPEAT = 10497; // 0x2901
+    field public static final int GL_REPLACE = 7681; // 0x1e01
+    field public static final int GL_RESCALE_NORMAL = 32826; // 0x803a
+    field public static final int GL_RGB = 6407; // 0x1907
+    field public static final int GL_RGBA = 6408; // 0x1908
+    field public static final int GL_SAMPLE_ALPHA_TO_COVERAGE = 32926; // 0x809e
+    field public static final int GL_SAMPLE_ALPHA_TO_ONE = 32927; // 0x809f
+    field public static final int GL_SAMPLE_COVERAGE = 32928; // 0x80a0
+    field public static final int GL_SCISSOR_TEST = 3089; // 0xc11
+    field public static final int GL_SET = 5391; // 0x150f
+    field public static final int GL_SHININESS = 5633; // 0x1601
+    field public static final int GL_SHORT = 5122; // 0x1402
+    field public static final int GL_SMOOTH = 7425; // 0x1d01
+    field public static final int GL_SMOOTH_LINE_WIDTH_RANGE = 2850; // 0xb22
+    field public static final int GL_SMOOTH_POINT_SIZE_RANGE = 2834; // 0xb12
+    field public static final int GL_SPECULAR = 4610; // 0x1202
+    field public static final int GL_SPOT_CUTOFF = 4614; // 0x1206
+    field public static final int GL_SPOT_DIRECTION = 4612; // 0x1204
+    field public static final int GL_SPOT_EXPONENT = 4613; // 0x1205
+    field public static final int GL_SRC_ALPHA = 770; // 0x302
+    field public static final int GL_SRC_ALPHA_SATURATE = 776; // 0x308
+    field public static final int GL_SRC_COLOR = 768; // 0x300
+    field public static final int GL_STACK_OVERFLOW = 1283; // 0x503
+    field public static final int GL_STACK_UNDERFLOW = 1284; // 0x504
+    field public static final int GL_STENCIL_BITS = 3415; // 0xd57
+    field public static final int GL_STENCIL_BUFFER_BIT = 1024; // 0x400
+    field public static final int GL_STENCIL_TEST = 2960; // 0xb90
+    field public static final int GL_SUBPIXEL_BITS = 3408; // 0xd50
+    field public static final int GL_TEXTURE = 5890; // 0x1702
+    field public static final int GL_TEXTURE0 = 33984; // 0x84c0
+    field public static final int GL_TEXTURE1 = 33985; // 0x84c1
+    field public static final int GL_TEXTURE10 = 33994; // 0x84ca
+    field public static final int GL_TEXTURE11 = 33995; // 0x84cb
+    field public static final int GL_TEXTURE12 = 33996; // 0x84cc
+    field public static final int GL_TEXTURE13 = 33997; // 0x84cd
+    field public static final int GL_TEXTURE14 = 33998; // 0x84ce
+    field public static final int GL_TEXTURE15 = 33999; // 0x84cf
+    field public static final int GL_TEXTURE16 = 34000; // 0x84d0
+    field public static final int GL_TEXTURE17 = 34001; // 0x84d1
+    field public static final int GL_TEXTURE18 = 34002; // 0x84d2
+    field public static final int GL_TEXTURE19 = 34003; // 0x84d3
+    field public static final int GL_TEXTURE2 = 33986; // 0x84c2
+    field public static final int GL_TEXTURE20 = 34004; // 0x84d4
+    field public static final int GL_TEXTURE21 = 34005; // 0x84d5
+    field public static final int GL_TEXTURE22 = 34006; // 0x84d6
+    field public static final int GL_TEXTURE23 = 34007; // 0x84d7
+    field public static final int GL_TEXTURE24 = 34008; // 0x84d8
+    field public static final int GL_TEXTURE25 = 34009; // 0x84d9
+    field public static final int GL_TEXTURE26 = 34010; // 0x84da
+    field public static final int GL_TEXTURE27 = 34011; // 0x84db
+    field public static final int GL_TEXTURE28 = 34012; // 0x84dc
+    field public static final int GL_TEXTURE29 = 34013; // 0x84dd
+    field public static final int GL_TEXTURE3 = 33987; // 0x84c3
+    field public static final int GL_TEXTURE30 = 34014; // 0x84de
+    field public static final int GL_TEXTURE31 = 34015; // 0x84df
+    field public static final int GL_TEXTURE4 = 33988; // 0x84c4
+    field public static final int GL_TEXTURE5 = 33989; // 0x84c5
+    field public static final int GL_TEXTURE6 = 33990; // 0x84c6
+    field public static final int GL_TEXTURE7 = 33991; // 0x84c7
+    field public static final int GL_TEXTURE8 = 33992; // 0x84c8
+    field public static final int GL_TEXTURE9 = 33993; // 0x84c9
+    field public static final int GL_TEXTURE_2D = 3553; // 0xde1
+    field public static final int GL_TEXTURE_COORD_ARRAY = 32888; // 0x8078
+    field public static final int GL_TEXTURE_ENV = 8960; // 0x2300
+    field public static final int GL_TEXTURE_ENV_COLOR = 8705; // 0x2201
+    field public static final int GL_TEXTURE_ENV_MODE = 8704; // 0x2200
+    field public static final int GL_TEXTURE_MAG_FILTER = 10240; // 0x2800
+    field public static final int GL_TEXTURE_MIN_FILTER = 10241; // 0x2801
+    field public static final int GL_TEXTURE_WRAP_S = 10242; // 0x2802
+    field public static final int GL_TEXTURE_WRAP_T = 10243; // 0x2803
+    field public static final int GL_TRIANGLES = 4; // 0x4
+    field public static final int GL_TRIANGLE_FAN = 6; // 0x6
+    field public static final int GL_TRIANGLE_STRIP = 5; // 0x5
+    field public static final int GL_TRUE = 1; // 0x1
+    field public static final int GL_UNPACK_ALIGNMENT = 3317; // 0xcf5
+    field public static final int GL_UNSIGNED_BYTE = 5121; // 0x1401
+    field public static final int GL_UNSIGNED_SHORT = 5123; // 0x1403
+    field public static final int GL_UNSIGNED_SHORT_4_4_4_4 = 32819; // 0x8033
+    field public static final int GL_UNSIGNED_SHORT_5_5_5_1 = 32820; // 0x8034
+    field public static final int GL_UNSIGNED_SHORT_5_6_5 = 33635; // 0x8363
+    field public static final int GL_VENDOR = 7936; // 0x1f00
+    field public static final int GL_VERSION = 7938; // 0x1f02
+    field public static final int GL_VERTEX_ARRAY = 32884; // 0x8074
+    field public static final int GL_XOR = 5382; // 0x1506
+    field public static final int GL_ZERO = 0; // 0x0
+  }
+
+  public class GLES10Ext {
+    ctor public GLES10Ext();
+    method public static int glQueryMatrixxOES(int[], int, int[], int);
+    method public static int glQueryMatrixxOES(java.nio.IntBuffer, java.nio.IntBuffer);
+  }
+
+  public class GLES11 extends android.opengl.GLES10 {
+    ctor public GLES11();
+    method public static void glBindBuffer(int, int);
+    method public static void glBufferData(int, int, java.nio.Buffer, int);
+    method public static void glBufferSubData(int, int, int, java.nio.Buffer);
+    method public static void glClipPlanef(int, float[], int);
+    method public static void glClipPlanef(int, java.nio.FloatBuffer);
+    method public static void glClipPlanex(int, int[], int);
+    method public static void glClipPlanex(int, java.nio.IntBuffer);
+    method public static void glColor4ub(byte, byte, byte, byte);
+    method public static void glColorPointer(int, int, int, int);
+    method public static void glDeleteBuffers(int, int[], int);
+    method public static void glDeleteBuffers(int, java.nio.IntBuffer);
+    method public static void glDrawElements(int, int, int, int);
+    method public static void glGenBuffers(int, int[], int);
+    method public static void glGenBuffers(int, java.nio.IntBuffer);
+    method public static void glGetBooleanv(int, boolean[], int);
+    method public static void glGetBooleanv(int, java.nio.IntBuffer);
+    method public static void glGetBufferParameteriv(int, int, int[], int);
+    method public static void glGetBufferParameteriv(int, int, java.nio.IntBuffer);
+    method public static void glGetClipPlanef(int, float[], int);
+    method public static void glGetClipPlanef(int, java.nio.FloatBuffer);
+    method public static void glGetClipPlanex(int, int[], int);
+    method public static void glGetClipPlanex(int, java.nio.IntBuffer);
+    method public static void glGetFixedv(int, int[], int);
+    method public static void glGetFixedv(int, java.nio.IntBuffer);
+    method public static void glGetFloatv(int, float[], int);
+    method public static void glGetFloatv(int, java.nio.FloatBuffer);
+    method public static void glGetLightfv(int, int, float[], int);
+    method public static void glGetLightfv(int, int, java.nio.FloatBuffer);
+    method public static void glGetLightxv(int, int, int[], int);
+    method public static void glGetLightxv(int, int, java.nio.IntBuffer);
+    method public static void glGetMaterialfv(int, int, float[], int);
+    method public static void glGetMaterialfv(int, int, java.nio.FloatBuffer);
+    method public static void glGetMaterialxv(int, int, int[], int);
+    method public static void glGetMaterialxv(int, int, java.nio.IntBuffer);
+    method public static void glGetTexEnvfv(int, int, float[], int);
+    method public static void glGetTexEnvfv(int, int, java.nio.FloatBuffer);
+    method public static void glGetTexEnviv(int, int, int[], int);
+    method public static void glGetTexEnviv(int, int, java.nio.IntBuffer);
+    method public static void glGetTexEnvxv(int, int, int[], int);
+    method public static void glGetTexEnvxv(int, int, java.nio.IntBuffer);
+    method public static void glGetTexParameterfv(int, int, float[], int);
+    method public static void glGetTexParameterfv(int, int, java.nio.FloatBuffer);
+    method public static void glGetTexParameteriv(int, int, int[], int);
+    method public static void glGetTexParameteriv(int, int, java.nio.IntBuffer);
+    method public static void glGetTexParameterxv(int, int, int[], int);
+    method public static void glGetTexParameterxv(int, int, java.nio.IntBuffer);
+    method public static boolean glIsBuffer(int);
+    method public static boolean glIsEnabled(int);
+    method public static boolean glIsTexture(int);
+    method public static void glNormalPointer(int, int, int);
+    method public static void glPointParameterf(int, float);
+    method public static void glPointParameterfv(int, float[], int);
+    method public static void glPointParameterfv(int, java.nio.FloatBuffer);
+    method public static void glPointParameterx(int, int);
+    method public static void glPointParameterxv(int, int[], int);
+    method public static void glPointParameterxv(int, java.nio.IntBuffer);
+    method public static void glPointSizePointerOES(int, int, java.nio.Buffer);
+    method public static void glTexCoordPointer(int, int, int, int);
+    method public static void glTexEnvi(int, int, int);
+    method public static void glTexEnviv(int, int, int[], int);
+    method public static void glTexEnviv(int, int, java.nio.IntBuffer);
+    method public static void glTexParameterfv(int, int, float[], int);
+    method public static void glTexParameterfv(int, int, java.nio.FloatBuffer);
+    method public static void glTexParameteri(int, int, int);
+    method public static void glTexParameteriv(int, int, int[], int);
+    method public static void glTexParameteriv(int, int, java.nio.IntBuffer);
+    method public static void glTexParameterxv(int, int, int[], int);
+    method public static void glTexParameterxv(int, int, java.nio.IntBuffer);
+    method public static void glVertexPointer(int, int, int, int);
+    field public static final int GL_ACTIVE_TEXTURE = 34016; // 0x84e0
+    field public static final int GL_ADD_SIGNED = 34164; // 0x8574
+    field public static final int GL_ALPHA_SCALE = 3356; // 0xd1c
+    field public static final int GL_ALPHA_TEST_FUNC = 3009; // 0xbc1
+    field public static final int GL_ALPHA_TEST_REF = 3010; // 0xbc2
+    field public static final int GL_ARRAY_BUFFER = 34962; // 0x8892
+    field public static final int GL_ARRAY_BUFFER_BINDING = 34964; // 0x8894
+    field public static final int GL_BLEND_DST = 3040; // 0xbe0
+    field public static final int GL_BLEND_SRC = 3041; // 0xbe1
+    field public static final int GL_BUFFER_ACCESS = 35003; // 0x88bb
+    field public static final int GL_BUFFER_SIZE = 34660; // 0x8764
+    field public static final int GL_BUFFER_USAGE = 34661; // 0x8765
+    field public static final int GL_CLIENT_ACTIVE_TEXTURE = 34017; // 0x84e1
+    field public static final int GL_CLIP_PLANE0 = 12288; // 0x3000
+    field public static final int GL_CLIP_PLANE1 = 12289; // 0x3001
+    field public static final int GL_CLIP_PLANE2 = 12290; // 0x3002
+    field public static final int GL_CLIP_PLANE3 = 12291; // 0x3003
+    field public static final int GL_CLIP_PLANE4 = 12292; // 0x3004
+    field public static final int GL_CLIP_PLANE5 = 12293; // 0x3005
+    field public static final int GL_COLOR_ARRAY_BUFFER_BINDING = 34968; // 0x8898
+    field public static final int GL_COLOR_ARRAY_POINTER = 32912; // 0x8090
+    field public static final int GL_COLOR_ARRAY_SIZE = 32897; // 0x8081
+    field public static final int GL_COLOR_ARRAY_STRIDE = 32899; // 0x8083
+    field public static final int GL_COLOR_ARRAY_TYPE = 32898; // 0x8082
+    field public static final int GL_COLOR_CLEAR_VALUE = 3106; // 0xc22
+    field public static final int GL_COLOR_WRITEMASK = 3107; // 0xc23
+    field public static final int GL_COMBINE = 34160; // 0x8570
+    field public static final int GL_COMBINE_ALPHA = 34162; // 0x8572
+    field public static final int GL_COMBINE_RGB = 34161; // 0x8571
+    field public static final int GL_CONSTANT = 34166; // 0x8576
+    field public static final int GL_COORD_REPLACE_OES = 34914; // 0x8862
+    field public static final int GL_CULL_FACE_MODE = 2885; // 0xb45
+    field public static final int GL_CURRENT_COLOR = 2816; // 0xb00
+    field public static final int GL_CURRENT_NORMAL = 2818; // 0xb02
+    field public static final int GL_CURRENT_TEXTURE_COORDS = 2819; // 0xb03
+    field public static final int GL_DEPTH_CLEAR_VALUE = 2931; // 0xb73
+    field public static final int GL_DEPTH_FUNC = 2932; // 0xb74
+    field public static final int GL_DEPTH_RANGE = 2928; // 0xb70
+    field public static final int GL_DEPTH_WRITEMASK = 2930; // 0xb72
+    field public static final int GL_DOT3_RGB = 34478; // 0x86ae
+    field public static final int GL_DOT3_RGBA = 34479; // 0x86af
+    field public static final int GL_DYNAMIC_DRAW = 35048; // 0x88e8
+    field public static final int GL_ELEMENT_ARRAY_BUFFER = 34963; // 0x8893
+    field public static final int GL_ELEMENT_ARRAY_BUFFER_BINDING = 34965; // 0x8895
+    field public static final int GL_FRONT_FACE = 2886; // 0xb46
+    field public static final int GL_GENERATE_MIPMAP = 33169; // 0x8191
+    field public static final int GL_GENERATE_MIPMAP_HINT = 33170; // 0x8192
+    field public static final int GL_INTERPOLATE = 34165; // 0x8575
+    field public static final int GL_LINE_WIDTH = 2849; // 0xb21
+    field public static final int GL_LOGIC_OP_MODE = 3056; // 0xbf0
+    field public static final int GL_MATRIX_MODE = 2976; // 0xba0
+    field public static final int GL_MAX_CLIP_PLANES = 3378; // 0xd32
+    field public static final int GL_MODELVIEW_MATRIX = 2982; // 0xba6
+    field public static final int GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES = 35213; // 0x898d
+    field public static final int GL_MODELVIEW_STACK_DEPTH = 2979; // 0xba3
+    field public static final int GL_NORMAL_ARRAY_BUFFER_BINDING = 34967; // 0x8897
+    field public static final int GL_NORMAL_ARRAY_POINTER = 32911; // 0x808f
+    field public static final int GL_NORMAL_ARRAY_STRIDE = 32895; // 0x807f
+    field public static final int GL_NORMAL_ARRAY_TYPE = 32894; // 0x807e
+    field public static final int GL_OPERAND0_ALPHA = 34200; // 0x8598
+    field public static final int GL_OPERAND0_RGB = 34192; // 0x8590
+    field public static final int GL_OPERAND1_ALPHA = 34201; // 0x8599
+    field public static final int GL_OPERAND1_RGB = 34193; // 0x8591
+    field public static final int GL_OPERAND2_ALPHA = 34202; // 0x859a
+    field public static final int GL_OPERAND2_RGB = 34194; // 0x8592
+    field public static final int GL_POINT_DISTANCE_ATTENUATION = 33065; // 0x8129
+    field public static final int GL_POINT_FADE_THRESHOLD_SIZE = 33064; // 0x8128
+    field public static final int GL_POINT_SIZE = 2833; // 0xb11
+    field public static final int GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES = 35743; // 0x8b9f
+    field public static final int GL_POINT_SIZE_ARRAY_OES = 35740; // 0x8b9c
+    field public static final int GL_POINT_SIZE_ARRAY_POINTER_OES = 35212; // 0x898c
+    field public static final int GL_POINT_SIZE_ARRAY_STRIDE_OES = 35211; // 0x898b
+    field public static final int GL_POINT_SIZE_ARRAY_TYPE_OES = 35210; // 0x898a
+    field public static final int GL_POINT_SIZE_MAX = 33063; // 0x8127
+    field public static final int GL_POINT_SIZE_MIN = 33062; // 0x8126
+    field public static final int GL_POINT_SPRITE_OES = 34913; // 0x8861
+    field public static final int GL_POLYGON_OFFSET_FACTOR = 32824; // 0x8038
+    field public static final int GL_POLYGON_OFFSET_UNITS = 10752; // 0x2a00
+    field public static final int GL_PREVIOUS = 34168; // 0x8578
+    field public static final int GL_PRIMARY_COLOR = 34167; // 0x8577
+    field public static final int GL_PROJECTION_MATRIX = 2983; // 0xba7
+    field public static final int GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES = 35214; // 0x898e
+    field public static final int GL_PROJECTION_STACK_DEPTH = 2980; // 0xba4
+    field public static final int GL_RGB_SCALE = 34163; // 0x8573
+    field public static final int GL_SAMPLES = 32937; // 0x80a9
+    field public static final int GL_SAMPLE_BUFFERS = 32936; // 0x80a8
+    field public static final int GL_SAMPLE_COVERAGE_INVERT = 32939; // 0x80ab
+    field public static final int GL_SAMPLE_COVERAGE_VALUE = 32938; // 0x80aa
+    field public static final int GL_SCISSOR_BOX = 3088; // 0xc10
+    field public static final int GL_SHADE_MODEL = 2900; // 0xb54
+    field public static final int GL_SRC0_ALPHA = 34184; // 0x8588
+    field public static final int GL_SRC0_RGB = 34176; // 0x8580
+    field public static final int GL_SRC1_ALPHA = 34185; // 0x8589
+    field public static final int GL_SRC1_RGB = 34177; // 0x8581
+    field public static final int GL_SRC2_ALPHA = 34186; // 0x858a
+    field public static final int GL_SRC2_RGB = 34178; // 0x8582
+    field public static final int GL_STATIC_DRAW = 35044; // 0x88e4
+    field public static final int GL_STENCIL_CLEAR_VALUE = 2961; // 0xb91
+    field public static final int GL_STENCIL_FAIL = 2964; // 0xb94
+    field public static final int GL_STENCIL_FUNC = 2962; // 0xb92
+    field public static final int GL_STENCIL_PASS_DEPTH_FAIL = 2965; // 0xb95
+    field public static final int GL_STENCIL_PASS_DEPTH_PASS = 2966; // 0xb96
+    field public static final int GL_STENCIL_REF = 2967; // 0xb97
+    field public static final int GL_STENCIL_VALUE_MASK = 2963; // 0xb93
+    field public static final int GL_STENCIL_WRITEMASK = 2968; // 0xb98
+    field public static final int GL_SUBTRACT = 34023; // 0x84e7
+    field public static final int GL_TEXTURE_BINDING_2D = 32873; // 0x8069
+    field public static final int GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING = 34970; // 0x889a
+    field public static final int GL_TEXTURE_COORD_ARRAY_POINTER = 32914; // 0x8092
+    field public static final int GL_TEXTURE_COORD_ARRAY_SIZE = 32904; // 0x8088
+    field public static final int GL_TEXTURE_COORD_ARRAY_STRIDE = 32906; // 0x808a
+    field public static final int GL_TEXTURE_COORD_ARRAY_TYPE = 32905; // 0x8089
+    field public static final int GL_TEXTURE_MATRIX = 2984; // 0xba8
+    field public static final int GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES = 35215; // 0x898f
+    field public static final int GL_TEXTURE_STACK_DEPTH = 2981; // 0xba5
+    field public static final int GL_VERTEX_ARRAY_BUFFER_BINDING = 34966; // 0x8896
+    field public static final int GL_VERTEX_ARRAY_POINTER = 32910; // 0x808e
+    field public static final int GL_VERTEX_ARRAY_SIZE = 32890; // 0x807a
+    field public static final int GL_VERTEX_ARRAY_STRIDE = 32892; // 0x807c
+    field public static final int GL_VERTEX_ARRAY_TYPE = 32891; // 0x807b
+    field public static final int GL_VIEWPORT = 2978; // 0xba2
+    field public static final int GL_WRITE_ONLY = 35001; // 0x88b9
+  }
+
+  public class GLES11Ext {
+    ctor public GLES11Ext();
+    method public static void glAlphaFuncxOES(int, int);
+    method public static void glBindFramebufferOES(int, int);
+    method public static void glBindRenderbufferOES(int, int);
+    method public static void glBlendEquationOES(int);
+    method public static void glBlendEquationSeparateOES(int, int);
+    method public static void glBlendFuncSeparateOES(int, int, int, int);
+    method public static int glCheckFramebufferStatusOES(int);
+    method public static void glClearColorxOES(int, int, int, int);
+    method public static void glClearDepthfOES(float);
+    method public static void glClearDepthxOES(int);
+    method public static void glClipPlanefOES(int, float[], int);
+    method public static void glClipPlanefOES(int, java.nio.FloatBuffer);
+    method public static void glClipPlanexOES(int, int[], int);
+    method public static void glClipPlanexOES(int, java.nio.IntBuffer);
+    method public static void glColor4xOES(int, int, int, int);
+    method public static void glCurrentPaletteMatrixOES(int);
+    method public static void glDeleteFramebuffersOES(int, int[], int);
+    method public static void glDeleteFramebuffersOES(int, java.nio.IntBuffer);
+    method public static void glDeleteRenderbuffersOES(int, int[], int);
+    method public static void glDeleteRenderbuffersOES(int, java.nio.IntBuffer);
+    method public static void glDepthRangefOES(float, float);
+    method public static void glDepthRangexOES(int, int);
+    method public static void glDrawTexfOES(float, float, float, float, float);
+    method public static void glDrawTexfvOES(float[], int);
+    method public static void glDrawTexfvOES(java.nio.FloatBuffer);
+    method public static void glDrawTexiOES(int, int, int, int, int);
+    method public static void glDrawTexivOES(int[], int);
+    method public static void glDrawTexivOES(java.nio.IntBuffer);
+    method public static void glDrawTexsOES(short, short, short, short, short);
+    method public static void glDrawTexsvOES(short[], int);
+    method public static void glDrawTexsvOES(java.nio.ShortBuffer);
+    method public static void glDrawTexxOES(int, int, int, int, int);
+    method public static void glDrawTexxvOES(int[], int);
+    method public static void glDrawTexxvOES(java.nio.IntBuffer);
+    method public static void glEGLImageTargetRenderbufferStorageOES(int, java.nio.Buffer);
+    method public static void glEGLImageTargetTexture2DOES(int, java.nio.Buffer);
+    method public static void glFogxOES(int, int);
+    method public static void glFogxvOES(int, int[], int);
+    method public static void glFogxvOES(int, java.nio.IntBuffer);
+    method public static void glFramebufferRenderbufferOES(int, int, int, int);
+    method public static void glFramebufferTexture2DOES(int, int, int, int, int);
+    method public static void glFrustumfOES(float, float, float, float, float, float);
+    method public static void glFrustumxOES(int, int, int, int, int, int);
+    method public static void glGenFramebuffersOES(int, int[], int);
+    method public static void glGenFramebuffersOES(int, java.nio.IntBuffer);
+    method public static void glGenRenderbuffersOES(int, int[], int);
+    method public static void glGenRenderbuffersOES(int, java.nio.IntBuffer);
+    method public static void glGenerateMipmapOES(int);
+    method public static void glGetClipPlanefOES(int, float[], int);
+    method public static void glGetClipPlanefOES(int, java.nio.FloatBuffer);
+    method public static void glGetClipPlanexOES(int, int[], int);
+    method public static void glGetClipPlanexOES(int, java.nio.IntBuffer);
+    method public static void glGetFixedvOES(int, int[], int);
+    method public static void glGetFixedvOES(int, java.nio.IntBuffer);
+    method public static void glGetFramebufferAttachmentParameterivOES(int, int, int, int[], int);
+    method public static void glGetFramebufferAttachmentParameterivOES(int, int, int, java.nio.IntBuffer);
+    method public static void glGetLightxvOES(int, int, int[], int);
+    method public static void glGetLightxvOES(int, int, java.nio.IntBuffer);
+    method public static void glGetMaterialxvOES(int, int, int[], int);
+    method public static void glGetMaterialxvOES(int, int, java.nio.IntBuffer);
+    method public static void glGetRenderbufferParameterivOES(int, int, int[], int);
+    method public static void glGetRenderbufferParameterivOES(int, int, java.nio.IntBuffer);
+    method public static void glGetTexEnvxvOES(int, int, int[], int);
+    method public static void glGetTexEnvxvOES(int, int, java.nio.IntBuffer);
+    method public static void glGetTexGenfvOES(int, int, float[], int);
+    method public static void glGetTexGenfvOES(int, int, java.nio.FloatBuffer);
+    method public static void glGetTexGenivOES(int, int, int[], int);
+    method public static void glGetTexGenivOES(int, int, java.nio.IntBuffer);
+    method public static void glGetTexGenxvOES(int, int, int[], int);
+    method public static void glGetTexGenxvOES(int, int, java.nio.IntBuffer);
+    method public static void glGetTexParameterxvOES(int, int, int[], int);
+    method public static void glGetTexParameterxvOES(int, int, java.nio.IntBuffer);
+    method public static boolean glIsFramebufferOES(int);
+    method public static boolean glIsRenderbufferOES(int);
+    method public static void glLightModelxOES(int, int);
+    method public static void glLightModelxvOES(int, int[], int);
+    method public static void glLightModelxvOES(int, java.nio.IntBuffer);
+    method public static void glLightxOES(int, int, int);
+    method public static void glLightxvOES(int, int, int[], int);
+    method public static void glLightxvOES(int, int, java.nio.IntBuffer);
+    method public static void glLineWidthxOES(int);
+    method public static void glLoadMatrixxOES(int[], int);
+    method public static void glLoadMatrixxOES(java.nio.IntBuffer);
+    method public static void glLoadPaletteFromModelViewMatrixOES();
+    method public static void glMaterialxOES(int, int, int);
+    method public static void glMaterialxvOES(int, int, int[], int);
+    method public static void glMaterialxvOES(int, int, java.nio.IntBuffer);
+    method public static void glMatrixIndexPointerOES(int, int, int, java.nio.Buffer);
+    method public static void glMultMatrixxOES(int[], int);
+    method public static void glMultMatrixxOES(java.nio.IntBuffer);
+    method public static void glMultiTexCoord4xOES(int, int, int, int, int);
+    method public static void glNormal3xOES(int, int, int);
+    method public static void glOrthofOES(float, float, float, float, float, float);
+    method public static void glOrthoxOES(int, int, int, int, int, int);
+    method public static void glPointParameterxOES(int, int);
+    method public static void glPointParameterxvOES(int, int[], int);
+    method public static void glPointParameterxvOES(int, java.nio.IntBuffer);
+    method public static void glPointSizexOES(int);
+    method public static void glPolygonOffsetxOES(int, int);
+    method public static void glRenderbufferStorageOES(int, int, int, int);
+    method public static void glRotatexOES(int, int, int, int);
+    method public static void glSampleCoveragexOES(int, boolean);
+    method public static void glScalexOES(int, int, int);
+    method public static void glTexEnvxOES(int, int, int);
+    method public static void glTexEnvxvOES(int, int, int[], int);
+    method public static void glTexEnvxvOES(int, int, java.nio.IntBuffer);
+    method public static void glTexGenfOES(int, int, float);
+    method public static void glTexGenfvOES(int, int, float[], int);
+    method public static void glTexGenfvOES(int, int, java.nio.FloatBuffer);
+    method public static void glTexGeniOES(int, int, int);
+    method public static void glTexGenivOES(int, int, int[], int);
+    method public static void glTexGenivOES(int, int, java.nio.IntBuffer);
+    method public static void glTexGenxOES(int, int, int);
+    method public static void glTexGenxvOES(int, int, int[], int);
+    method public static void glTexGenxvOES(int, int, java.nio.IntBuffer);
+    method public static void glTexParameterxOES(int, int, int);
+    method public static void glTexParameterxvOES(int, int, int[], int);
+    method public static void glTexParameterxvOES(int, int, java.nio.IntBuffer);
+    method public static void glTranslatexOES(int, int, int);
+    method public static void glWeightPointerOES(int, int, int, java.nio.Buffer);
+    field public static final int GL_3DC_XY_AMD = 34810; // 0x87fa
+    field public static final int GL_3DC_X_AMD = 34809; // 0x87f9
+    field public static final int GL_ATC_RGBA_EXPLICIT_ALPHA_AMD = 35987; // 0x8c93
+    field public static final int GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD = 34798; // 0x87ee
+    field public static final int GL_ATC_RGB_AMD = 35986; // 0x8c92
+    field public static final int GL_BGRA = 32993; // 0x80e1
+    field public static final int GL_BLEND_DST_ALPHA_OES = 32970; // 0x80ca
+    field public static final int GL_BLEND_DST_RGB_OES = 32968; // 0x80c8
+    field public static final int GL_BLEND_EQUATION_ALPHA_OES = 34877; // 0x883d
+    field public static final int GL_BLEND_EQUATION_OES = 32777; // 0x8009
+    field public static final int GL_BLEND_EQUATION_RGB_OES = 32777; // 0x8009
+    field public static final int GL_BLEND_SRC_ALPHA_OES = 32971; // 0x80cb
+    field public static final int GL_BLEND_SRC_RGB_OES = 32969; // 0x80c9
+    field public static final int GL_BUFFER_ACCESS_OES = 35003; // 0x88bb
+    field public static final int GL_BUFFER_MAPPED_OES = 35004; // 0x88bc
+    field public static final int GL_BUFFER_MAP_POINTER_OES = 35005; // 0x88bd
+    field public static final int GL_COLOR_ATTACHMENT0_OES = 36064; // 0x8ce0
+    field public static final int GL_CURRENT_PALETTE_MATRIX_OES = 34883; // 0x8843
+    field public static final int GL_DECR_WRAP_OES = 34056; // 0x8508
+    field public static final int GL_DEPTH24_STENCIL8_OES = 35056; // 0x88f0
+    field public static final int GL_DEPTH_ATTACHMENT_OES = 36096; // 0x8d00
+    field public static final int GL_DEPTH_COMPONENT16_OES = 33189; // 0x81a5
+    field public static final int GL_DEPTH_COMPONENT24_OES = 33190; // 0x81a6
+    field public static final int GL_DEPTH_COMPONENT32_OES = 33191; // 0x81a7
+    field public static final int GL_DEPTH_STENCIL_OES = 34041; // 0x84f9
+    field public static final int GL_ETC1_RGB8_OES = 36196; // 0x8d64
+    field public static final int GL_FIXED_OES = 5132; // 0x140c
+    field public static final int GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES = 36049; // 0x8cd1
+    field public static final int GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES = 36048; // 0x8cd0
+    field public static final int GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES = 36051; // 0x8cd3
+    field public static final int GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES = 36050; // 0x8cd2
+    field public static final int GL_FRAMEBUFFER_BINDING_OES = 36006; // 0x8ca6
+    field public static final int GL_FRAMEBUFFER_COMPLETE_OES = 36053; // 0x8cd5
+    field public static final int GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES = 36054; // 0x8cd6
+    field public static final int GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES = 36057; // 0x8cd9
+    field public static final int GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES = 36058; // 0x8cda
+    field public static final int GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES = 36055; // 0x8cd7
+    field public static final int GL_FRAMEBUFFER_OES = 36160; // 0x8d40
+    field public static final int GL_FRAMEBUFFER_UNSUPPORTED_OES = 36061; // 0x8cdd
+    field public static final int GL_FUNC_ADD_OES = 32774; // 0x8006
+    field public static final int GL_FUNC_REVERSE_SUBTRACT_OES = 32779; // 0x800b
+    field public static final int GL_FUNC_SUBTRACT_OES = 32778; // 0x800a
+    field public static final int GL_INCR_WRAP_OES = 34055; // 0x8507
+    field public static final int GL_INVALID_FRAMEBUFFER_OPERATION_OES = 1286; // 0x506
+    field public static final int GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES = 35742; // 0x8b9e
+    field public static final int GL_MATRIX_INDEX_ARRAY_OES = 34884; // 0x8844
+    field public static final int GL_MATRIX_INDEX_ARRAY_POINTER_OES = 34889; // 0x8849
+    field public static final int GL_MATRIX_INDEX_ARRAY_SIZE_OES = 34886; // 0x8846
+    field public static final int GL_MATRIX_INDEX_ARRAY_STRIDE_OES = 34888; // 0x8848
+    field public static final int GL_MATRIX_INDEX_ARRAY_TYPE_OES = 34887; // 0x8847
+    field public static final int GL_MATRIX_PALETTE_OES = 34880; // 0x8840
+    field public static final int GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES = 34076; // 0x851c
+    field public static final int GL_MAX_PALETTE_MATRICES_OES = 34882; // 0x8842
+    field public static final int GL_MAX_RENDERBUFFER_SIZE_OES = 34024; // 0x84e8
+    field public static final int GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = 34047; // 0x84ff
+    field public static final int GL_MAX_VERTEX_UNITS_OES = 34468; // 0x86a4
+    field public static final int GL_MIRRORED_REPEAT_OES = 33648; // 0x8370
+    field public static final int GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES = 35213; // 0x898d
+    field public static final int GL_NONE_OES = 0; // 0x0
+    field public static final int GL_NORMAL_MAP_OES = 34065; // 0x8511
+    field public static final int GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES = 35214; // 0x898e
+    field public static final int GL_REFLECTION_MAP_OES = 34066; // 0x8512
+    field public static final int GL_RENDERBUFFER_ALPHA_SIZE_OES = 36179; // 0x8d53
+    field public static final int GL_RENDERBUFFER_BINDING_OES = 36007; // 0x8ca7
+    field public static final int GL_RENDERBUFFER_BLUE_SIZE_OES = 36178; // 0x8d52
+    field public static final int GL_RENDERBUFFER_DEPTH_SIZE_OES = 36180; // 0x8d54
+    field public static final int GL_RENDERBUFFER_GREEN_SIZE_OES = 36177; // 0x8d51
+    field public static final int GL_RENDERBUFFER_HEIGHT_OES = 36163; // 0x8d43
+    field public static final int GL_RENDERBUFFER_INTERNAL_FORMAT_OES = 36164; // 0x8d44
+    field public static final int GL_RENDERBUFFER_OES = 36161; // 0x8d41
+    field public static final int GL_RENDERBUFFER_RED_SIZE_OES = 36176; // 0x8d50
+    field public static final int GL_RENDERBUFFER_STENCIL_SIZE_OES = 36181; // 0x8d55
+    field public static final int GL_RENDERBUFFER_WIDTH_OES = 36162; // 0x8d42
+    field public static final int GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES = 36200; // 0x8d68
+    field public static final int GL_RGB565_OES = 36194; // 0x8d62
+    field public static final int GL_RGB5_A1_OES = 32855; // 0x8057
+    field public static final int GL_RGB8_OES = 32849; // 0x8051
+    field public static final int GL_RGBA4_OES = 32854; // 0x8056
+    field public static final int GL_RGBA8_OES = 32856; // 0x8058
+    field public static final int GL_SAMPLER_EXTERNAL_OES = 36198; // 0x8d66
+    field public static final int GL_STENCIL_ATTACHMENT_OES = 36128; // 0x8d20
+    field public static final int GL_STENCIL_INDEX1_OES = 36166; // 0x8d46
+    field public static final int GL_STENCIL_INDEX4_OES = 36167; // 0x8d47
+    field public static final int GL_STENCIL_INDEX8_OES = 36168; // 0x8d48
+    field public static final int GL_TEXTURE_BINDING_CUBE_MAP_OES = 34068; // 0x8514
+    field public static final int GL_TEXTURE_BINDING_EXTERNAL_OES = 36199; // 0x8d67
+    field public static final int GL_TEXTURE_CROP_RECT_OES = 35741; // 0x8b9d
+    field public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES = 34070; // 0x8516
+    field public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES = 34072; // 0x8518
+    field public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES = 34074; // 0x851a
+    field public static final int GL_TEXTURE_CUBE_MAP_OES = 34067; // 0x8513
+    field public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES = 34069; // 0x8515
+    field public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES = 34071; // 0x8517
+    field public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES = 34073; // 0x8519
+    field public static final int GL_TEXTURE_EXTERNAL_OES = 36197; // 0x8d65
+    field public static final int GL_TEXTURE_GEN_MODE_OES = 9472; // 0x2500
+    field public static final int GL_TEXTURE_GEN_STR_OES = 36192; // 0x8d60
+    field public static final int GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES = 35215; // 0x898f
+    field public static final int GL_TEXTURE_MAX_ANISOTROPY_EXT = 34046; // 0x84fe
+    field public static final int GL_UNSIGNED_INT_24_8_OES = 34042; // 0x84fa
+    field public static final int GL_WEIGHT_ARRAY_BUFFER_BINDING_OES = 34974; // 0x889e
+    field public static final int GL_WEIGHT_ARRAY_OES = 34477; // 0x86ad
+    field public static final int GL_WEIGHT_ARRAY_POINTER_OES = 34476; // 0x86ac
+    field public static final int GL_WEIGHT_ARRAY_SIZE_OES = 34475; // 0x86ab
+    field public static final int GL_WEIGHT_ARRAY_STRIDE_OES = 34474; // 0x86aa
+    field public static final int GL_WEIGHT_ARRAY_TYPE_OES = 34473; // 0x86a9
+    field public static final int GL_WRITE_ONLY_OES = 35001; // 0x88b9
+  }
+
+  public class GLES20 {
+    ctor public GLES20();
+    method public static void glActiveTexture(int);
+    method public static void glAttachShader(int, int);
+    method public static void glBindAttribLocation(int, int, java.lang.String);
+    method public static void glBindBuffer(int, int);
+    method public static void glBindFramebuffer(int, int);
+    method public static void glBindRenderbuffer(int, int);
+    method public static void glBindTexture(int, int);
+    method public static void glBlendColor(float, float, float, float);
+    method public static void glBlendEquation(int);
+    method public static void glBlendEquationSeparate(int, int);
+    method public static void glBlendFunc(int, int);
+    method public static void glBlendFuncSeparate(int, int, int, int);
+    method public static void glBufferData(int, int, java.nio.Buffer, int);
+    method public static void glBufferSubData(int, int, int, java.nio.Buffer);
+    method public static int glCheckFramebufferStatus(int);
+    method public static void glClear(int);
+    method public static void glClearColor(float, float, float, float);
+    method public static void glClearDepthf(float);
+    method public static void glClearStencil(int);
+    method public static void glColorMask(boolean, boolean, boolean, boolean);
+    method public static void glCompileShader(int);
+    method public static void glCompressedTexImage2D(int, int, int, int, int, int, int, java.nio.Buffer);
+    method public static void glCompressedTexSubImage2D(int, int, int, int, int, int, int, int, java.nio.Buffer);
+    method public static void glCopyTexImage2D(int, int, int, int, int, int, int, int);
+    method public static void glCopyTexSubImage2D(int, int, int, int, int, int, int, int);
+    method public static int glCreateProgram();
+    method public static int glCreateShader(int);
+    method public static void glCullFace(int);
+    method public static void glDeleteBuffers(int, int[], int);
+    method public static void glDeleteBuffers(int, java.nio.IntBuffer);
+    method public static void glDeleteFramebuffers(int, int[], int);
+    method public static void glDeleteFramebuffers(int, java.nio.IntBuffer);
+    method public static void glDeleteProgram(int);
+    method public static void glDeleteRenderbuffers(int, int[], int);
+    method public static void glDeleteRenderbuffers(int, java.nio.IntBuffer);
+    method public static void glDeleteShader(int);
+    method public static void glDeleteTextures(int, int[], int);
+    method public static void glDeleteTextures(int, java.nio.IntBuffer);
+    method public static void glDepthFunc(int);
+    method public static void glDepthMask(boolean);
+    method public static void glDepthRangef(float, float);
+    method public static void glDetachShader(int, int);
+    method public static void glDisable(int);
+    method public static void glDisableVertexAttribArray(int);
+    method public static void glDrawArrays(int, int, int);
+    method public static void glDrawElements(int, int, int, int);
+    method public static void glDrawElements(int, int, int, java.nio.Buffer);
+    method public static void glEnable(int);
+    method public static void glEnableVertexAttribArray(int);
+    method public static void glFinish();
+    method public static void glFlush();
+    method public static void glFramebufferRenderbuffer(int, int, int, int);
+    method public static void glFramebufferTexture2D(int, int, int, int, int);
+    method public static void glFrontFace(int);
+    method public static void glGenBuffers(int, int[], int);
+    method public static void glGenBuffers(int, java.nio.IntBuffer);
+    method public static void glGenFramebuffers(int, int[], int);
+    method public static void glGenFramebuffers(int, java.nio.IntBuffer);
+    method public static void glGenRenderbuffers(int, int[], int);
+    method public static void glGenRenderbuffers(int, java.nio.IntBuffer);
+    method public static void glGenTextures(int, int[], int);
+    method public static void glGenTextures(int, java.nio.IntBuffer);
+    method public static void glGenerateMipmap(int);
+    method public static void glGetActiveAttrib(int, int, int, int[], int, int[], int, int[], int, byte[], int);
+    method public static void glGetActiveAttrib(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static java.lang.String glGetActiveAttrib(int, int, int[], int, int[], int);
+    method public static java.lang.String glGetActiveAttrib(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
+    method public static void glGetActiveUniform(int, int, int, int[], int, int[], int, int[], int, byte[], int);
+    method public static void glGetActiveUniform(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static java.lang.String glGetActiveUniform(int, int, int[], int, int[], int);
+    method public static java.lang.String glGetActiveUniform(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
+    method public static void glGetAttachedShaders(int, int, int[], int, int[], int);
+    method public static void glGetAttachedShaders(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
+    method public static int glGetAttribLocation(int, java.lang.String);
+    method public static void glGetBooleanv(int, boolean[], int);
+    method public static void glGetBooleanv(int, java.nio.IntBuffer);
+    method public static void glGetBufferParameteriv(int, int, int[], int);
+    method public static void glGetBufferParameteriv(int, int, java.nio.IntBuffer);
+    method public static int glGetError();
+    method public static void glGetFloatv(int, float[], int);
+    method public static void glGetFloatv(int, java.nio.FloatBuffer);
+    method public static void glGetFramebufferAttachmentParameteriv(int, int, int, int[], int);
+    method public static void glGetFramebufferAttachmentParameteriv(int, int, int, java.nio.IntBuffer);
+    method public static void glGetIntegerv(int, int[], int);
+    method public static void glGetIntegerv(int, java.nio.IntBuffer);
+    method public static java.lang.String glGetProgramInfoLog(int);
+    method public static void glGetProgramiv(int, int, int[], int);
+    method public static void glGetProgramiv(int, int, java.nio.IntBuffer);
+    method public static void glGetRenderbufferParameteriv(int, int, int[], int);
+    method public static void glGetRenderbufferParameteriv(int, int, java.nio.IntBuffer);
+    method public static java.lang.String glGetShaderInfoLog(int);
+    method public static void glGetShaderPrecisionFormat(int, int, int[], int, int[], int);
+    method public static void glGetShaderPrecisionFormat(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
+    method public static void glGetShaderSource(int, int, int[], int, byte[], int);
+    method public static void glGetShaderSource(int, int, java.nio.IntBuffer, byte);
+    method public static java.lang.String glGetShaderSource(int);
+    method public static void glGetShaderiv(int, int, int[], int);
+    method public static void glGetShaderiv(int, int, java.nio.IntBuffer);
+    method public static java.lang.String glGetString(int);
+    method public static void glGetTexParameterfv(int, int, float[], int);
+    method public static void glGetTexParameterfv(int, int, java.nio.FloatBuffer);
+    method public static void glGetTexParameteriv(int, int, int[], int);
+    method public static void glGetTexParameteriv(int, int, java.nio.IntBuffer);
+    method public static int glGetUniformLocation(int, java.lang.String);
+    method public static void glGetUniformfv(int, int, float[], int);
+    method public static void glGetUniformfv(int, int, java.nio.FloatBuffer);
+    method public static void glGetUniformiv(int, int, int[], int);
+    method public static void glGetUniformiv(int, int, java.nio.IntBuffer);
+    method public static void glGetVertexAttribfv(int, int, float[], int);
+    method public static void glGetVertexAttribfv(int, int, java.nio.FloatBuffer);
+    method public static void glGetVertexAttribiv(int, int, int[], int);
+    method public static void glGetVertexAttribiv(int, int, java.nio.IntBuffer);
+    method public static void glHint(int, int);
+    method public static boolean glIsBuffer(int);
+    method public static boolean glIsEnabled(int);
+    method public static boolean glIsFramebuffer(int);
+    method public static boolean glIsProgram(int);
+    method public static boolean glIsRenderbuffer(int);
+    method public static boolean glIsShader(int);
+    method public static boolean glIsTexture(int);
+    method public static void glLineWidth(float);
+    method public static void glLinkProgram(int);
+    method public static void glPixelStorei(int, int);
+    method public static void glPolygonOffset(float, float);
+    method public static void glReadPixels(int, int, int, int, int, int, java.nio.Buffer);
+    method public static void glReleaseShaderCompiler();
+    method public static void glRenderbufferStorage(int, int, int, int);
+    method public static void glSampleCoverage(float, boolean);
+    method public static void glScissor(int, int, int, int);
+    method public static void glShaderBinary(int, int[], int, int, java.nio.Buffer, int);
+    method public static void glShaderBinary(int, java.nio.IntBuffer, int, java.nio.Buffer, int);
+    method public static void glShaderSource(int, java.lang.String);
+    method public static void glStencilFunc(int, int, int);
+    method public static void glStencilFuncSeparate(int, int, int, int);
+    method public static void glStencilMask(int);
+    method public static void glStencilMaskSeparate(int, int);
+    method public static void glStencilOp(int, int, int);
+    method public static void glStencilOpSeparate(int, int, int, int);
+    method public static void glTexImage2D(int, int, int, int, int, int, int, int, java.nio.Buffer);
+    method public static void glTexParameterf(int, int, float);
+    method public static void glTexParameterfv(int, int, float[], int);
+    method public static void glTexParameterfv(int, int, java.nio.FloatBuffer);
+    method public static void glTexParameteri(int, int, int);
+    method public static void glTexParameteriv(int, int, int[], int);
+    method public static void glTexParameteriv(int, int, java.nio.IntBuffer);
+    method public static void glTexSubImage2D(int, int, int, int, int, int, int, int, java.nio.Buffer);
+    method public static void glUniform1f(int, float);
+    method public static void glUniform1fv(int, int, float[], int);
+    method public static void glUniform1fv(int, int, java.nio.FloatBuffer);
+    method public static void glUniform1i(int, int);
+    method public static void glUniform1iv(int, int, int[], int);
+    method public static void glUniform1iv(int, int, java.nio.IntBuffer);
+    method public static void glUniform2f(int, float, float);
+    method public static void glUniform2fv(int, int, float[], int);
+    method public static void glUniform2fv(int, int, java.nio.FloatBuffer);
+    method public static void glUniform2i(int, int, int);
+    method public static void glUniform2iv(int, int, int[], int);
+    method public static void glUniform2iv(int, int, java.nio.IntBuffer);
+    method public static void glUniform3f(int, float, float, float);
+    method public static void glUniform3fv(int, int, float[], int);
+    method public static void glUniform3fv(int, int, java.nio.FloatBuffer);
+    method public static void glUniform3i(int, int, int, int);
+    method public static void glUniform3iv(int, int, int[], int);
+    method public static void glUniform3iv(int, int, java.nio.IntBuffer);
+    method public static void glUniform4f(int, float, float, float, float);
+    method public static void glUniform4fv(int, int, float[], int);
+    method public static void glUniform4fv(int, int, java.nio.FloatBuffer);
+    method public static void glUniform4i(int, int, int, int, int);
+    method public static void glUniform4iv(int, int, int[], int);
+    method public static void glUniform4iv(int, int, java.nio.IntBuffer);
+    method public static void glUniformMatrix2fv(int, int, boolean, float[], int);
+    method public static void glUniformMatrix2fv(int, int, boolean, java.nio.FloatBuffer);
+    method public static void glUniformMatrix3fv(int, int, boolean, float[], int);
+    method public static void glUniformMatrix3fv(int, int, boolean, java.nio.FloatBuffer);
+    method public static void glUniformMatrix4fv(int, int, boolean, float[], int);
+    method public static void glUniformMatrix4fv(int, int, boolean, java.nio.FloatBuffer);
+    method public static void glUseProgram(int);
+    method public static void glValidateProgram(int);
+    method public static void glVertexAttrib1f(int, float);
+    method public static void glVertexAttrib1fv(int, float[], int);
+    method public static void glVertexAttrib1fv(int, java.nio.FloatBuffer);
+    method public static void glVertexAttrib2f(int, float, float);
+    method public static void glVertexAttrib2fv(int, float[], int);
+    method public static void glVertexAttrib2fv(int, java.nio.FloatBuffer);
+    method public static void glVertexAttrib3f(int, float, float, float);
+    method public static void glVertexAttrib3fv(int, float[], int);
+    method public static void glVertexAttrib3fv(int, java.nio.FloatBuffer);
+    method public static void glVertexAttrib4f(int, float, float, float, float);
+    method public static void glVertexAttrib4fv(int, float[], int);
+    method public static void glVertexAttrib4fv(int, java.nio.FloatBuffer);
+    method public static void glVertexAttribPointer(int, int, int, boolean, int, int);
+    method public static void glVertexAttribPointer(int, int, int, boolean, int, java.nio.Buffer);
+    method public static void glViewport(int, int, int, int);
+    field public static final int GL_ACTIVE_ATTRIBUTES = 35721; // 0x8b89
+    field public static final int GL_ACTIVE_ATTRIBUTE_MAX_LENGTH = 35722; // 0x8b8a
+    field public static final int GL_ACTIVE_TEXTURE = 34016; // 0x84e0
+    field public static final int GL_ACTIVE_UNIFORMS = 35718; // 0x8b86
+    field public static final int GL_ACTIVE_UNIFORM_MAX_LENGTH = 35719; // 0x8b87
+    field public static final int GL_ALIASED_LINE_WIDTH_RANGE = 33902; // 0x846e
+    field public static final int GL_ALIASED_POINT_SIZE_RANGE = 33901; // 0x846d
+    field public static final int GL_ALPHA = 6406; // 0x1906
+    field public static final int GL_ALPHA_BITS = 3413; // 0xd55
+    field public static final int GL_ALWAYS = 519; // 0x207
+    field public static final int GL_ARRAY_BUFFER = 34962; // 0x8892
+    field public static final int GL_ARRAY_BUFFER_BINDING = 34964; // 0x8894
+    field public static final int GL_ATTACHED_SHADERS = 35717; // 0x8b85
+    field public static final int GL_BACK = 1029; // 0x405
+    field public static final int GL_BLEND = 3042; // 0xbe2
+    field public static final int GL_BLEND_COLOR = 32773; // 0x8005
+    field public static final int GL_BLEND_DST_ALPHA = 32970; // 0x80ca
+    field public static final int GL_BLEND_DST_RGB = 32968; // 0x80c8
+    field public static final int GL_BLEND_EQUATION = 32777; // 0x8009
+    field public static final int GL_BLEND_EQUATION_ALPHA = 34877; // 0x883d
+    field public static final int GL_BLEND_EQUATION_RGB = 32777; // 0x8009
+    field public static final int GL_BLEND_SRC_ALPHA = 32971; // 0x80cb
+    field public static final int GL_BLEND_SRC_RGB = 32969; // 0x80c9
+    field public static final int GL_BLUE_BITS = 3412; // 0xd54
+    field public static final int GL_BOOL = 35670; // 0x8b56
+    field public static final int GL_BOOL_VEC2 = 35671; // 0x8b57
+    field public static final int GL_BOOL_VEC3 = 35672; // 0x8b58
+    field public static final int GL_BOOL_VEC4 = 35673; // 0x8b59
+    field public static final int GL_BUFFER_SIZE = 34660; // 0x8764
+    field public static final int GL_BUFFER_USAGE = 34661; // 0x8765
+    field public static final int GL_BYTE = 5120; // 0x1400
+    field public static final int GL_CCW = 2305; // 0x901
+    field public static final int GL_CLAMP_TO_EDGE = 33071; // 0x812f
+    field public static final int GL_COLOR_ATTACHMENT0 = 36064; // 0x8ce0
+    field public static final int GL_COLOR_BUFFER_BIT = 16384; // 0x4000
+    field public static final int GL_COLOR_CLEAR_VALUE = 3106; // 0xc22
+    field public static final int GL_COLOR_WRITEMASK = 3107; // 0xc23
+    field public static final int GL_COMPILE_STATUS = 35713; // 0x8b81
+    field public static final int GL_COMPRESSED_TEXTURE_FORMATS = 34467; // 0x86a3
+    field public static final int GL_CONSTANT_ALPHA = 32771; // 0x8003
+    field public static final int GL_CONSTANT_COLOR = 32769; // 0x8001
+    field public static final int GL_CULL_FACE = 2884; // 0xb44
+    field public static final int GL_CULL_FACE_MODE = 2885; // 0xb45
+    field public static final int GL_CURRENT_PROGRAM = 35725; // 0x8b8d
+    field public static final int GL_CURRENT_VERTEX_ATTRIB = 34342; // 0x8626
+    field public static final int GL_CW = 2304; // 0x900
+    field public static final int GL_DECR = 7683; // 0x1e03
+    field public static final int GL_DECR_WRAP = 34056; // 0x8508
+    field public static final int GL_DELETE_STATUS = 35712; // 0x8b80
+    field public static final int GL_DEPTH_ATTACHMENT = 36096; // 0x8d00
+    field public static final int GL_DEPTH_BITS = 3414; // 0xd56
+    field public static final int GL_DEPTH_BUFFER_BIT = 256; // 0x100
+    field public static final int GL_DEPTH_CLEAR_VALUE = 2931; // 0xb73
+    field public static final int GL_DEPTH_COMPONENT = 6402; // 0x1902
+    field public static final int GL_DEPTH_COMPONENT16 = 33189; // 0x81a5
+    field public static final int GL_DEPTH_FUNC = 2932; // 0xb74
+    field public static final int GL_DEPTH_RANGE = 2928; // 0xb70
+    field public static final int GL_DEPTH_TEST = 2929; // 0xb71
+    field public static final int GL_DEPTH_WRITEMASK = 2930; // 0xb72
+    field public static final int GL_DITHER = 3024; // 0xbd0
+    field public static final int GL_DONT_CARE = 4352; // 0x1100
+    field public static final int GL_DST_ALPHA = 772; // 0x304
+    field public static final int GL_DST_COLOR = 774; // 0x306
+    field public static final int GL_DYNAMIC_DRAW = 35048; // 0x88e8
+    field public static final int GL_ELEMENT_ARRAY_BUFFER = 34963; // 0x8893
+    field public static final int GL_ELEMENT_ARRAY_BUFFER_BINDING = 34965; // 0x8895
+    field public static final int GL_EQUAL = 514; // 0x202
+    field public static final int GL_EXTENSIONS = 7939; // 0x1f03
+    field public static final int GL_FALSE = 0; // 0x0
+    field public static final int GL_FASTEST = 4353; // 0x1101
+    field public static final int GL_FIXED = 5132; // 0x140c
+    field public static final int GL_FLOAT = 5126; // 0x1406
+    field public static final int GL_FLOAT_MAT2 = 35674; // 0x8b5a
+    field public static final int GL_FLOAT_MAT3 = 35675; // 0x8b5b
+    field public static final int GL_FLOAT_MAT4 = 35676; // 0x8b5c
+    field public static final int GL_FLOAT_VEC2 = 35664; // 0x8b50
+    field public static final int GL_FLOAT_VEC3 = 35665; // 0x8b51
+    field public static final int GL_FLOAT_VEC4 = 35666; // 0x8b52
+    field public static final int GL_FRAGMENT_SHADER = 35632; // 0x8b30
+    field public static final int GL_FRAMEBUFFER = 36160; // 0x8d40
+    field public static final int GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 36049; // 0x8cd1
+    field public static final int GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 36048; // 0x8cd0
+    field public static final int GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 36051; // 0x8cd3
+    field public static final int GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 36050; // 0x8cd2
+    field public static final int GL_FRAMEBUFFER_BINDING = 36006; // 0x8ca6
+    field public static final int GL_FRAMEBUFFER_COMPLETE = 36053; // 0x8cd5
+    field public static final int GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 36054; // 0x8cd6
+    field public static final int GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 36057; // 0x8cd9
+    field public static final int GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 36055; // 0x8cd7
+    field public static final int GL_FRAMEBUFFER_UNSUPPORTED = 36061; // 0x8cdd
+    field public static final int GL_FRONT = 1028; // 0x404
+    field public static final int GL_FRONT_AND_BACK = 1032; // 0x408
+    field public static final int GL_FRONT_FACE = 2886; // 0xb46
+    field public static final int GL_FUNC_ADD = 32774; // 0x8006
+    field public static final int GL_FUNC_REVERSE_SUBTRACT = 32779; // 0x800b
+    field public static final int GL_FUNC_SUBTRACT = 32778; // 0x800a
+    field public static final int GL_GENERATE_MIPMAP_HINT = 33170; // 0x8192
+    field public static final int GL_GEQUAL = 518; // 0x206
+    field public static final int GL_GREATER = 516; // 0x204
+    field public static final int GL_GREEN_BITS = 3411; // 0xd53
+    field public static final int GL_HIGH_FLOAT = 36338; // 0x8df2
+    field public static final int GL_HIGH_INT = 36341; // 0x8df5
+    field public static final int GL_IMPLEMENTATION_COLOR_READ_FORMAT = 35739; // 0x8b9b
+    field public static final int GL_IMPLEMENTATION_COLOR_READ_TYPE = 35738; // 0x8b9a
+    field public static final int GL_INCR = 7682; // 0x1e02
+    field public static final int GL_INCR_WRAP = 34055; // 0x8507
+    field public static final int GL_INFO_LOG_LENGTH = 35716; // 0x8b84
+    field public static final int GL_INT = 5124; // 0x1404
+    field public static final int GL_INT_VEC2 = 35667; // 0x8b53
+    field public static final int GL_INT_VEC3 = 35668; // 0x8b54
+    field public static final int GL_INT_VEC4 = 35669; // 0x8b55
+    field public static final int GL_INVALID_ENUM = 1280; // 0x500
+    field public static final int GL_INVALID_FRAMEBUFFER_OPERATION = 1286; // 0x506
+    field public static final int GL_INVALID_OPERATION = 1282; // 0x502
+    field public static final int GL_INVALID_VALUE = 1281; // 0x501
+    field public static final int GL_INVERT = 5386; // 0x150a
+    field public static final int GL_KEEP = 7680; // 0x1e00
+    field public static final int GL_LEQUAL = 515; // 0x203
+    field public static final int GL_LESS = 513; // 0x201
+    field public static final int GL_LINEAR = 9729; // 0x2601
+    field public static final int GL_LINEAR_MIPMAP_LINEAR = 9987; // 0x2703
+    field public static final int GL_LINEAR_MIPMAP_NEAREST = 9985; // 0x2701
+    field public static final int GL_LINES = 1; // 0x1
+    field public static final int GL_LINE_LOOP = 2; // 0x2
+    field public static final int GL_LINE_STRIP = 3; // 0x3
+    field public static final int GL_LINE_WIDTH = 2849; // 0xb21
+    field public static final int GL_LINK_STATUS = 35714; // 0x8b82
+    field public static final int GL_LOW_FLOAT = 36336; // 0x8df0
+    field public static final int GL_LOW_INT = 36339; // 0x8df3
+    field public static final int GL_LUMINANCE = 6409; // 0x1909
+    field public static final int GL_LUMINANCE_ALPHA = 6410; // 0x190a
+    field public static final int GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = 35661; // 0x8b4d
+    field public static final int GL_MAX_CUBE_MAP_TEXTURE_SIZE = 34076; // 0x851c
+    field public static final int GL_MAX_FRAGMENT_UNIFORM_VECTORS = 36349; // 0x8dfd
+    field public static final int GL_MAX_RENDERBUFFER_SIZE = 34024; // 0x84e8
+    field public static final int GL_MAX_TEXTURE_IMAGE_UNITS = 34930; // 0x8872
+    field public static final int GL_MAX_TEXTURE_SIZE = 3379; // 0xd33
+    field public static final int GL_MAX_VARYING_VECTORS = 36348; // 0x8dfc
+    field public static final int GL_MAX_VERTEX_ATTRIBS = 34921; // 0x8869
+    field public static final int GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS = 35660; // 0x8b4c
+    field public static final int GL_MAX_VERTEX_UNIFORM_VECTORS = 36347; // 0x8dfb
+    field public static final int GL_MAX_VIEWPORT_DIMS = 3386; // 0xd3a
+    field public static final int GL_MEDIUM_FLOAT = 36337; // 0x8df1
+    field public static final int GL_MEDIUM_INT = 36340; // 0x8df4
+    field public static final int GL_MIRRORED_REPEAT = 33648; // 0x8370
+    field public static final int GL_NEAREST = 9728; // 0x2600
+    field public static final int GL_NEAREST_MIPMAP_LINEAR = 9986; // 0x2702
+    field public static final int GL_NEAREST_MIPMAP_NEAREST = 9984; // 0x2700
+    field public static final int GL_NEVER = 512; // 0x200
+    field public static final int GL_NICEST = 4354; // 0x1102
+    field public static final int GL_NONE = 0; // 0x0
+    field public static final int GL_NOTEQUAL = 517; // 0x205
+    field public static final int GL_NO_ERROR = 0; // 0x0
+    field public static final int GL_NUM_COMPRESSED_TEXTURE_FORMATS = 34466; // 0x86a2
+    field public static final int GL_NUM_SHADER_BINARY_FORMATS = 36345; // 0x8df9
+    field public static final int GL_ONE = 1; // 0x1
+    field public static final int GL_ONE_MINUS_CONSTANT_ALPHA = 32772; // 0x8004
+    field public static final int GL_ONE_MINUS_CONSTANT_COLOR = 32770; // 0x8002
+    field public static final int GL_ONE_MINUS_DST_ALPHA = 773; // 0x305
+    field public static final int GL_ONE_MINUS_DST_COLOR = 775; // 0x307
+    field public static final int GL_ONE_MINUS_SRC_ALPHA = 771; // 0x303
+    field public static final int GL_ONE_MINUS_SRC_COLOR = 769; // 0x301
+    field public static final int GL_OUT_OF_MEMORY = 1285; // 0x505
+    field public static final int GL_PACK_ALIGNMENT = 3333; // 0xd05
+    field public static final int GL_POINTS = 0; // 0x0
+    field public static final int GL_POLYGON_OFFSET_FACTOR = 32824; // 0x8038
+    field public static final int GL_POLYGON_OFFSET_FILL = 32823; // 0x8037
+    field public static final int GL_POLYGON_OFFSET_UNITS = 10752; // 0x2a00
+    field public static final int GL_RED_BITS = 3410; // 0xd52
+    field public static final int GL_RENDERBUFFER = 36161; // 0x8d41
+    field public static final int GL_RENDERBUFFER_ALPHA_SIZE = 36179; // 0x8d53
+    field public static final int GL_RENDERBUFFER_BINDING = 36007; // 0x8ca7
+    field public static final int GL_RENDERBUFFER_BLUE_SIZE = 36178; // 0x8d52
+    field public static final int GL_RENDERBUFFER_DEPTH_SIZE = 36180; // 0x8d54
+    field public static final int GL_RENDERBUFFER_GREEN_SIZE = 36177; // 0x8d51
+    field public static final int GL_RENDERBUFFER_HEIGHT = 36163; // 0x8d43
+    field public static final int GL_RENDERBUFFER_INTERNAL_FORMAT = 36164; // 0x8d44
+    field public static final int GL_RENDERBUFFER_RED_SIZE = 36176; // 0x8d50
+    field public static final int GL_RENDERBUFFER_STENCIL_SIZE = 36181; // 0x8d55
+    field public static final int GL_RENDERBUFFER_WIDTH = 36162; // 0x8d42
+    field public static final int GL_RENDERER = 7937; // 0x1f01
+    field public static final int GL_REPEAT = 10497; // 0x2901
+    field public static final int GL_REPLACE = 7681; // 0x1e01
+    field public static final int GL_RGB = 6407; // 0x1907
+    field public static final int GL_RGB565 = 36194; // 0x8d62
+    field public static final int GL_RGB5_A1 = 32855; // 0x8057
+    field public static final int GL_RGBA = 6408; // 0x1908
+    field public static final int GL_RGBA4 = 32854; // 0x8056
+    field public static final int GL_SAMPLER_2D = 35678; // 0x8b5e
+    field public static final int GL_SAMPLER_CUBE = 35680; // 0x8b60
+    field public static final int GL_SAMPLES = 32937; // 0x80a9
+    field public static final int GL_SAMPLE_ALPHA_TO_COVERAGE = 32926; // 0x809e
+    field public static final int GL_SAMPLE_BUFFERS = 32936; // 0x80a8
+    field public static final int GL_SAMPLE_COVERAGE = 32928; // 0x80a0
+    field public static final int GL_SAMPLE_COVERAGE_INVERT = 32939; // 0x80ab
+    field public static final int GL_SAMPLE_COVERAGE_VALUE = 32938; // 0x80aa
+    field public static final int GL_SCISSOR_BOX = 3088; // 0xc10
+    field public static final int GL_SCISSOR_TEST = 3089; // 0xc11
+    field public static final int GL_SHADER_BINARY_FORMATS = 36344; // 0x8df8
+    field public static final int GL_SHADER_COMPILER = 36346; // 0x8dfa
+    field public static final int GL_SHADER_SOURCE_LENGTH = 35720; // 0x8b88
+    field public static final int GL_SHADER_TYPE = 35663; // 0x8b4f
+    field public static final int GL_SHADING_LANGUAGE_VERSION = 35724; // 0x8b8c
+    field public static final int GL_SHORT = 5122; // 0x1402
+    field public static final int GL_SRC_ALPHA = 770; // 0x302
+    field public static final int GL_SRC_ALPHA_SATURATE = 776; // 0x308
+    field public static final int GL_SRC_COLOR = 768; // 0x300
+    field public static final int GL_STATIC_DRAW = 35044; // 0x88e4
+    field public static final int GL_STENCIL_ATTACHMENT = 36128; // 0x8d20
+    field public static final int GL_STENCIL_BACK_FAIL = 34817; // 0x8801
+    field public static final int GL_STENCIL_BACK_FUNC = 34816; // 0x8800
+    field public static final int GL_STENCIL_BACK_PASS_DEPTH_FAIL = 34818; // 0x8802
+    field public static final int GL_STENCIL_BACK_PASS_DEPTH_PASS = 34819; // 0x8803
+    field public static final int GL_STENCIL_BACK_REF = 36003; // 0x8ca3
+    field public static final int GL_STENCIL_BACK_VALUE_MASK = 36004; // 0x8ca4
+    field public static final int GL_STENCIL_BACK_WRITEMASK = 36005; // 0x8ca5
+    field public static final int GL_STENCIL_BITS = 3415; // 0xd57
+    field public static final int GL_STENCIL_BUFFER_BIT = 1024; // 0x400
+    field public static final int GL_STENCIL_CLEAR_VALUE = 2961; // 0xb91
+    field public static final int GL_STENCIL_FAIL = 2964; // 0xb94
+    field public static final int GL_STENCIL_FUNC = 2962; // 0xb92
+    field public static final int GL_STENCIL_INDEX = 6401; // 0x1901
+    field public static final int GL_STENCIL_INDEX8 = 36168; // 0x8d48
+    field public static final int GL_STENCIL_PASS_DEPTH_FAIL = 2965; // 0xb95
+    field public static final int GL_STENCIL_PASS_DEPTH_PASS = 2966; // 0xb96
+    field public static final int GL_STENCIL_REF = 2967; // 0xb97
+    field public static final int GL_STENCIL_TEST = 2960; // 0xb90
+    field public static final int GL_STENCIL_VALUE_MASK = 2963; // 0xb93
+    field public static final int GL_STENCIL_WRITEMASK = 2968; // 0xb98
+    field public static final int GL_STREAM_DRAW = 35040; // 0x88e0
+    field public static final int GL_SUBPIXEL_BITS = 3408; // 0xd50
+    field public static final int GL_TEXTURE = 5890; // 0x1702
+    field public static final int GL_TEXTURE0 = 33984; // 0x84c0
+    field public static final int GL_TEXTURE1 = 33985; // 0x84c1
+    field public static final int GL_TEXTURE10 = 33994; // 0x84ca
+    field public static final int GL_TEXTURE11 = 33995; // 0x84cb
+    field public static final int GL_TEXTURE12 = 33996; // 0x84cc
+    field public static final int GL_TEXTURE13 = 33997; // 0x84cd
+    field public static final int GL_TEXTURE14 = 33998; // 0x84ce
+    field public static final int GL_TEXTURE15 = 33999; // 0x84cf
+    field public static final int GL_TEXTURE16 = 34000; // 0x84d0
+    field public static final int GL_TEXTURE17 = 34001; // 0x84d1
+    field public static final int GL_TEXTURE18 = 34002; // 0x84d2
+    field public static final int GL_TEXTURE19 = 34003; // 0x84d3
+    field public static final int GL_TEXTURE2 = 33986; // 0x84c2
+    field public static final int GL_TEXTURE20 = 34004; // 0x84d4
+    field public static final int GL_TEXTURE21 = 34005; // 0x84d5
+    field public static final int GL_TEXTURE22 = 34006; // 0x84d6
+    field public static final int GL_TEXTURE23 = 34007; // 0x84d7
+    field public static final int GL_TEXTURE24 = 34008; // 0x84d8
+    field public static final int GL_TEXTURE25 = 34009; // 0x84d9
+    field public static final int GL_TEXTURE26 = 34010; // 0x84da
+    field public static final int GL_TEXTURE27 = 34011; // 0x84db
+    field public static final int GL_TEXTURE28 = 34012; // 0x84dc
+    field public static final int GL_TEXTURE29 = 34013; // 0x84dd
+    field public static final int GL_TEXTURE3 = 33987; // 0x84c3
+    field public static final int GL_TEXTURE30 = 34014; // 0x84de
+    field public static final int GL_TEXTURE31 = 34015; // 0x84df
+    field public static final int GL_TEXTURE4 = 33988; // 0x84c4
+    field public static final int GL_TEXTURE5 = 33989; // 0x84c5
+    field public static final int GL_TEXTURE6 = 33990; // 0x84c6
+    field public static final int GL_TEXTURE7 = 33991; // 0x84c7
+    field public static final int GL_TEXTURE8 = 33992; // 0x84c8
+    field public static final int GL_TEXTURE9 = 33993; // 0x84c9
+    field public static final int GL_TEXTURE_2D = 3553; // 0xde1
+    field public static final int GL_TEXTURE_BINDING_2D = 32873; // 0x8069
+    field public static final int GL_TEXTURE_BINDING_CUBE_MAP = 34068; // 0x8514
+    field public static final int GL_TEXTURE_CUBE_MAP = 34067; // 0x8513
+    field public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 34070; // 0x8516
+    field public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 34072; // 0x8518
+    field public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 34074; // 0x851a
+    field public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_X = 34069; // 0x8515
+    field public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 34071; // 0x8517
+    field public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 34073; // 0x8519
+    field public static final int GL_TEXTURE_MAG_FILTER = 10240; // 0x2800
+    field public static final int GL_TEXTURE_MIN_FILTER = 10241; // 0x2801
+    field public static final int GL_TEXTURE_WRAP_S = 10242; // 0x2802
+    field public static final int GL_TEXTURE_WRAP_T = 10243; // 0x2803
+    field public static final int GL_TRIANGLES = 4; // 0x4
+    field public static final int GL_TRIANGLE_FAN = 6; // 0x6
+    field public static final int GL_TRIANGLE_STRIP = 5; // 0x5
+    field public static final int GL_TRUE = 1; // 0x1
+    field public static final int GL_UNPACK_ALIGNMENT = 3317; // 0xcf5
+    field public static final int GL_UNSIGNED_BYTE = 5121; // 0x1401
+    field public static final int GL_UNSIGNED_INT = 5125; // 0x1405
+    field public static final int GL_UNSIGNED_SHORT = 5123; // 0x1403
+    field public static final int GL_UNSIGNED_SHORT_4_4_4_4 = 32819; // 0x8033
+    field public static final int GL_UNSIGNED_SHORT_5_5_5_1 = 32820; // 0x8034
+    field public static final int GL_UNSIGNED_SHORT_5_6_5 = 33635; // 0x8363
+    field public static final int GL_VALIDATE_STATUS = 35715; // 0x8b83
+    field public static final int GL_VENDOR = 7936; // 0x1f00
+    field public static final int GL_VERSION = 7938; // 0x1f02
+    field public static final int GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 34975; // 0x889f
+    field public static final int GL_VERTEX_ATTRIB_ARRAY_ENABLED = 34338; // 0x8622
+    field public static final int GL_VERTEX_ATTRIB_ARRAY_NORMALIZED = 34922; // 0x886a
+    field public static final int GL_VERTEX_ATTRIB_ARRAY_POINTER = 34373; // 0x8645
+    field public static final int GL_VERTEX_ATTRIB_ARRAY_SIZE = 34339; // 0x8623
+    field public static final int GL_VERTEX_ATTRIB_ARRAY_STRIDE = 34340; // 0x8624
+    field public static final int GL_VERTEX_ATTRIB_ARRAY_TYPE = 34341; // 0x8625
+    field public static final int GL_VERTEX_SHADER = 35633; // 0x8b31
+    field public static final int GL_VIEWPORT = 2978; // 0xba2
+    field public static final int GL_ZERO = 0; // 0x0
+  }
+
+  public class GLException extends java.lang.RuntimeException {
+    ctor public GLException(int);
+    ctor public GLException(int, java.lang.String);
+  }
+
+  public class GLSurfaceView extends android.view.SurfaceView implements android.view.SurfaceHolder.Callback {
+    ctor public GLSurfaceView(android.content.Context);
+    ctor public GLSurfaceView(android.content.Context, android.util.AttributeSet);
+    method public int getDebugFlags();
+    method public boolean getPreserveEGLContextOnPause();
+    method public int getRenderMode();
+    method public void onPause();
+    method public void onResume();
+    method public void queueEvent(java.lang.Runnable);
+    method public void requestRender();
+    method public void setDebugFlags(int);
+    method public void setEGLConfigChooser(android.opengl.GLSurfaceView.EGLConfigChooser);
+    method public void setEGLConfigChooser(boolean);
+    method public void setEGLConfigChooser(int, int, int, int, int, int);
+    method public void setEGLContextClientVersion(int);
+    method public void setEGLContextFactory(android.opengl.GLSurfaceView.EGLContextFactory);
+    method public void setEGLWindowSurfaceFactory(android.opengl.GLSurfaceView.EGLWindowSurfaceFactory);
+    method public void setGLWrapper(android.opengl.GLSurfaceView.GLWrapper);
+    method public void setPreserveEGLContextOnPause(boolean);
+    method public void setRenderMode(int);
+    method public void setRenderer(android.opengl.GLSurfaceView.Renderer);
+    method public void surfaceChanged(android.view.SurfaceHolder, int, int, int);
+    method public void surfaceCreated(android.view.SurfaceHolder);
+    method public void surfaceDestroyed(android.view.SurfaceHolder);
+    field public static final int DEBUG_CHECK_GL_ERROR = 1; // 0x1
+    field public static final int DEBUG_LOG_GL_CALLS = 2; // 0x2
+    field public static final int RENDERMODE_CONTINUOUSLY = 1; // 0x1
+    field public static final int RENDERMODE_WHEN_DIRTY = 0; // 0x0
+  }
+
+  public static abstract interface GLSurfaceView.EGLConfigChooser {
+    method public abstract javax.microedition.khronos.egl.EGLConfig chooseConfig(javax.microedition.khronos.egl.EGL10, javax.microedition.khronos.egl.EGLDisplay);
+  }
+
+  public static abstract interface GLSurfaceView.EGLContextFactory {
+    method public abstract javax.microedition.khronos.egl.EGLContext createContext(javax.microedition.khronos.egl.EGL10, javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig);
+    method public abstract void destroyContext(javax.microedition.khronos.egl.EGL10, javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLContext);
+  }
+
+  public static abstract interface GLSurfaceView.EGLWindowSurfaceFactory {
+    method public abstract javax.microedition.khronos.egl.EGLSurface createWindowSurface(javax.microedition.khronos.egl.EGL10, javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig, java.lang.Object);
+    method public abstract void destroySurface(javax.microedition.khronos.egl.EGL10, javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLSurface);
+  }
+
+  public static abstract interface GLSurfaceView.GLWrapper {
+    method public abstract javax.microedition.khronos.opengles.GL wrap(javax.microedition.khronos.opengles.GL);
+  }
+
+  public static abstract interface GLSurfaceView.Renderer {
+    method public abstract void onDrawFrame(javax.microedition.khronos.opengles.GL10);
+    method public abstract void onSurfaceChanged(javax.microedition.khronos.opengles.GL10, int, int);
+    method public abstract void onSurfaceCreated(javax.microedition.khronos.opengles.GL10, javax.microedition.khronos.egl.EGLConfig);
+  }
+
+  public class GLU {
+    ctor public GLU();
+    method public static java.lang.String gluErrorString(int);
+    method public static void gluLookAt(javax.microedition.khronos.opengles.GL10, float, float, float, float, float, float, float, float, float);
+    method public static void gluOrtho2D(javax.microedition.khronos.opengles.GL10, float, float, float, float);
+    method public static void gluPerspective(javax.microedition.khronos.opengles.GL10, float, float, float, float);
+    method public static int gluProject(float, float, float, float[], int, float[], int, int[], int, float[], int);
+    method public static int gluUnProject(float, float, float, float[], int, float[], int, int[], int, float[], int);
+  }
+
+  public final class GLUtils {
+    method public static java.lang.String getEGLErrorString(int);
+    method public static int getInternalFormat(android.graphics.Bitmap);
+    method public static int getType(android.graphics.Bitmap);
+    method public static void texImage2D(int, int, int, android.graphics.Bitmap, int);
+    method public static void texImage2D(int, int, int, android.graphics.Bitmap, int, int);
+    method public static void texImage2D(int, int, android.graphics.Bitmap, int);
+    method public static void texSubImage2D(int, int, int, int, android.graphics.Bitmap);
+    method public static void texSubImage2D(int, int, int, int, android.graphics.Bitmap, int, int);
+  }
+
+  public class Matrix {
+    ctor public Matrix();
+    method public static void frustumM(float[], int, float, float, float, float, float, float);
+    method public static boolean invertM(float[], int, float[], int);
+    method public static float length(float, float, float);
+    method public static void multiplyMM(float[], int, float[], int, float[], int);
+    method public static void multiplyMV(float[], int, float[], int, float[], int);
+    method public static void orthoM(float[], int, float, float, float, float, float, float);
+    method public static void perspectiveM(float[], int, float, float, float, float);
+    method public static void rotateM(float[], int, float[], int, float, float, float, float);
+    method public static void rotateM(float[], int, float, float, float, float);
+    method public static void scaleM(float[], int, float[], int, float, float, float);
+    method public static void scaleM(float[], int, float, float, float);
+    method public static void setIdentityM(float[], int);
+    method public static void setLookAtM(float[], int, float, float, float, float, float, float, float, float, float);
+    method public static void setRotateEulerM(float[], int, float, float, float);
+    method public static void setRotateM(float[], int, float, float, float, float);
+    method public static void translateM(float[], int, float[], int, float, float, float);
+    method public static void translateM(float[], int, float, float, float);
+    method public static void transposeM(float[], int, float[], int);
+  }
+
+  public class Visibility {
+    ctor public Visibility();
+    method public static void computeBoundingSphere(float[], int, int, float[], int);
+    method public static int frustumCullSpheres(float[], int, float[], int, int, int[], int, int);
+    method public static int visibilityTest(float[], int, float[], int, char[], int, int);
+  }
+
+}
+
+package android.os {
+
+  public abstract class AsyncTask {
+    ctor public AsyncTask();
+    method public final boolean cancel(boolean);
+    method protected abstract Result doInBackground(Params...);
+    method public final android.os.AsyncTask<Params, Progress, Result> execute(Params...);
+    method public static void execute(java.lang.Runnable);
+    method public final android.os.AsyncTask<Params, Progress, Result> executeOnExecutor(java.util.concurrent.Executor, Params...);
+    method public final Result get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public final Result get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method public final android.os.AsyncTask.Status getStatus();
+    method public final boolean isCancelled();
+    method protected void onCancelled(Result);
+    method protected void onCancelled();
+    method protected void onPostExecute(Result);
+    method protected void onPreExecute();
+    method protected void onProgressUpdate(Progress...);
+    method protected final void publishProgress(Progress...);
+    field public static final java.util.concurrent.Executor SERIAL_EXECUTOR;
+    field public static final java.util.concurrent.Executor THREAD_POOL_EXECUTOR;
+  }
+
+  public static final class AsyncTask.Status extends java.lang.Enum {
+    method public static android.os.AsyncTask.Status valueOf(java.lang.String);
+    method public static final android.os.AsyncTask.Status[] values();
+    enum_constant public static final android.os.AsyncTask.Status FINISHED;
+    enum_constant public static final android.os.AsyncTask.Status PENDING;
+    enum_constant public static final android.os.AsyncTask.Status RUNNING;
+  }
+
+  public class BadParcelableException extends android.util.AndroidRuntimeException {
+    ctor public BadParcelableException(java.lang.String);
+    ctor public BadParcelableException(java.lang.Exception);
+  }
+
+  public class BatteryManager {
+    ctor public BatteryManager();
+    field public static final int BATTERY_HEALTH_COLD = 7; // 0x7
+    field public static final int BATTERY_HEALTH_DEAD = 4; // 0x4
+    field public static final int BATTERY_HEALTH_GOOD = 2; // 0x2
+    field public static final int BATTERY_HEALTH_OVERHEAT = 3; // 0x3
+    field public static final int BATTERY_HEALTH_OVER_VOLTAGE = 5; // 0x5
+    field public static final int BATTERY_HEALTH_UNKNOWN = 1; // 0x1
+    field public static final int BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6; // 0x6
+    field public static final int BATTERY_PLUGGED_AC = 1; // 0x1
+    field public static final int BATTERY_PLUGGED_USB = 2; // 0x2
+    field public static final int BATTERY_PLUGGED_WIRELESS = 4; // 0x4
+    field public static final int BATTERY_STATUS_CHARGING = 2; // 0x2
+    field public static final int BATTERY_STATUS_DISCHARGING = 3; // 0x3
+    field public static final int BATTERY_STATUS_FULL = 5; // 0x5
+    field public static final int BATTERY_STATUS_NOT_CHARGING = 4; // 0x4
+    field public static final int BATTERY_STATUS_UNKNOWN = 1; // 0x1
+    field public static final java.lang.String EXTRA_HEALTH = "health";
+    field public static final java.lang.String EXTRA_ICON_SMALL = "icon-small";
+    field public static final java.lang.String EXTRA_LEVEL = "level";
+    field public static final java.lang.String EXTRA_PLUGGED = "plugged";
+    field public static final java.lang.String EXTRA_PRESENT = "present";
+    field public static final java.lang.String EXTRA_SCALE = "scale";
+    field public static final java.lang.String EXTRA_STATUS = "status";
+    field public static final java.lang.String EXTRA_TECHNOLOGY = "technology";
+    field public static final java.lang.String EXTRA_TEMPERATURE = "temperature";
+    field public static final java.lang.String EXTRA_VOLTAGE = "voltage";
+  }
+
+  public class Binder implements android.os.IBinder {
+    ctor public Binder();
+    method public void attachInterface(android.os.IInterface, java.lang.String);
+    method public static final long clearCallingIdentity();
+    method public void dump(java.io.FileDescriptor, java.lang.String[]);
+    method protected void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public void dumpAsync(java.io.FileDescriptor, java.lang.String[]);
+    method public static final void flushPendingCommands();
+    method public static final int getCallingPid();
+    method public static final int getCallingUid();
+    method public static final android.os.UserHandle getCallingUserHandle();
+    method public java.lang.String getInterfaceDescriptor();
+    method public boolean isBinderAlive();
+    method public static final void joinThreadPool();
+    method public void linkToDeath(android.os.IBinder.DeathRecipient, int);
+    method protected boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
+    method public boolean pingBinder();
+    method public android.os.IInterface queryLocalInterface(java.lang.String);
+    method public static final void restoreCallingIdentity(long);
+    method public final boolean transact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
+    method public boolean unlinkToDeath(android.os.IBinder.DeathRecipient, int);
+  }
+
+  public class Build {
+    ctor public Build();
+    method public static java.lang.String getRadioVersion();
+    field public static final java.lang.String BOARD;
+    field public static final java.lang.String BOOTLOADER;
+    field public static final java.lang.String BRAND;
+    field public static final java.lang.String CPU_ABI;
+    field public static final java.lang.String CPU_ABI2;
+    field public static final java.lang.String DEVICE;
+    field public static final java.lang.String DISPLAY;
+    field public static final java.lang.String FINGERPRINT;
+    field public static final java.lang.String HARDWARE;
+    field public static final java.lang.String HOST;
+    field public static final java.lang.String ID;
+    field public static final java.lang.String MANUFACTURER;
+    field public static final java.lang.String MODEL;
+    field public static final java.lang.String PRODUCT;
+    field public static final deprecated java.lang.String RADIO;
+    field public static final java.lang.String SERIAL;
+    field public static final java.lang.String TAGS;
+    field public static final long TIME;
+    field public static final java.lang.String TYPE;
+    field public static final java.lang.String UNKNOWN = "unknown";
+    field public static final java.lang.String USER;
+  }
+
+  public static class Build.VERSION {
+    ctor public Build.VERSION();
+    field public static final java.lang.String CODENAME;
+    field public static final java.lang.String INCREMENTAL;
+    field public static final java.lang.String RELEASE;
+    field public static final deprecated java.lang.String SDK;
+    field public static final int SDK_INT;
+  }
+
+  public static class Build.VERSION_CODES {
+    ctor public Build.VERSION_CODES();
+    field public static final int BASE = 1; // 0x1
+    field public static final int BASE_1_1 = 2; // 0x2
+    field public static final int CUPCAKE = 3; // 0x3
+    field public static final int CUR_DEVELOPMENT = 10000; // 0x2710
+    field public static final int DONUT = 4; // 0x4
+    field public static final int ECLAIR = 5; // 0x5
+    field public static final int ECLAIR_0_1 = 6; // 0x6
+    field public static final int ECLAIR_MR1 = 7; // 0x7
+    field public static final int FROYO = 8; // 0x8
+    field public static final int GINGERBREAD = 9; // 0x9
+    field public static final int GINGERBREAD_MR1 = 10; // 0xa
+    field public static final int HONEYCOMB = 11; // 0xb
+    field public static final int HONEYCOMB_MR1 = 12; // 0xc
+    field public static final int HONEYCOMB_MR2 = 13; // 0xd
+    field public static final int ICE_CREAM_SANDWICH = 14; // 0xe
+    field public static final int ICE_CREAM_SANDWICH_MR1 = 15; // 0xf
+    field public static final int JELLY_BEAN = 16; // 0x10
+    field public static final int JELLY_BEAN_MR1 = 17; // 0x11
+  }
+
+  public final class Bundle implements java.lang.Cloneable android.os.Parcelable {
+    ctor public Bundle();
+    ctor public Bundle(java.lang.ClassLoader);
+    ctor public Bundle(int);
+    ctor public Bundle(android.os.Bundle);
+    method public void clear();
+    method public java.lang.Object clone();
+    method public boolean containsKey(java.lang.String);
+    method public int describeContents();
+    method public java.lang.Object get(java.lang.String);
+    method public boolean getBoolean(java.lang.String);
+    method public boolean getBoolean(java.lang.String, boolean);
+    method public boolean[] getBooleanArray(java.lang.String);
+    method public android.os.Bundle getBundle(java.lang.String);
+    method public byte getByte(java.lang.String);
+    method public java.lang.Byte getByte(java.lang.String, byte);
+    method public byte[] getByteArray(java.lang.String);
+    method public char getChar(java.lang.String);
+    method public char getChar(java.lang.String, char);
+    method public char[] getCharArray(java.lang.String);
+    method public java.lang.CharSequence getCharSequence(java.lang.String);
+    method public java.lang.CharSequence getCharSequence(java.lang.String, java.lang.CharSequence);
+    method public java.lang.CharSequence[] getCharSequenceArray(java.lang.String);
+    method public java.util.ArrayList<java.lang.CharSequence> getCharSequenceArrayList(java.lang.String);
+    method public java.lang.ClassLoader getClassLoader();
+    method public double getDouble(java.lang.String);
+    method public double getDouble(java.lang.String, double);
+    method public double[] getDoubleArray(java.lang.String);
+    method public float getFloat(java.lang.String);
+    method public float getFloat(java.lang.String, float);
+    method public float[] getFloatArray(java.lang.String);
+    method public int getInt(java.lang.String);
+    method public int getInt(java.lang.String, int);
+    method public int[] getIntArray(java.lang.String);
+    method public java.util.ArrayList<java.lang.Integer> getIntegerArrayList(java.lang.String);
+    method public long getLong(java.lang.String);
+    method public long getLong(java.lang.String, long);
+    method public long[] getLongArray(java.lang.String);
+    method public T getParcelable(java.lang.String);
+    method public android.os.Parcelable[] getParcelableArray(java.lang.String);
+    method public java.util.ArrayList<T> getParcelableArrayList(java.lang.String);
+    method public java.io.Serializable getSerializable(java.lang.String);
+    method public short getShort(java.lang.String);
+    method public short getShort(java.lang.String, short);
+    method public short[] getShortArray(java.lang.String);
+    method public android.util.SparseArray<T> getSparseParcelableArray(java.lang.String);
+    method public java.lang.String getString(java.lang.String);
+    method public java.lang.String getString(java.lang.String, java.lang.String);
+    method public java.lang.String[] getStringArray(java.lang.String);
+    method public java.util.ArrayList<java.lang.String> getStringArrayList(java.lang.String);
+    method public boolean hasFileDescriptors();
+    method public boolean isEmpty();
+    method public java.util.Set<java.lang.String> keySet();
+    method public void putAll(android.os.Bundle);
+    method public void putBoolean(java.lang.String, boolean);
+    method public void putBooleanArray(java.lang.String, boolean[]);
+    method public void putBundle(java.lang.String, android.os.Bundle);
+    method public void putByte(java.lang.String, byte);
+    method public void putByteArray(java.lang.String, byte[]);
+    method public void putChar(java.lang.String, char);
+    method public void putCharArray(java.lang.String, char[]);
+    method public void putCharSequence(java.lang.String, java.lang.CharSequence);
+    method public void putCharSequenceArray(java.lang.String, java.lang.CharSequence[]);
+    method public void putCharSequenceArrayList(java.lang.String, java.util.ArrayList<java.lang.CharSequence>);
+    method public void putDouble(java.lang.String, double);
+    method public void putDoubleArray(java.lang.String, double[]);
+    method public void putFloat(java.lang.String, float);
+    method public void putFloatArray(java.lang.String, float[]);
+    method public void putInt(java.lang.String, int);
+    method public void putIntArray(java.lang.String, int[]);
+    method public void putIntegerArrayList(java.lang.String, java.util.ArrayList<java.lang.Integer>);
+    method public void putLong(java.lang.String, long);
+    method public void putLongArray(java.lang.String, long[]);
+    method public void putParcelable(java.lang.String, android.os.Parcelable);
+    method public void putParcelableArray(java.lang.String, android.os.Parcelable[]);
+    method public void putParcelableArrayList(java.lang.String, java.util.ArrayList<? extends android.os.Parcelable>);
+    method public void putSerializable(java.lang.String, java.io.Serializable);
+    method public void putShort(java.lang.String, short);
+    method public void putShortArray(java.lang.String, short[]);
+    method public void putSparseParcelableArray(java.lang.String, android.util.SparseArray<? extends android.os.Parcelable>);
+    method public void putString(java.lang.String, java.lang.String);
+    method public void putStringArray(java.lang.String, java.lang.String[]);
+    method public void putStringArrayList(java.lang.String, java.util.ArrayList<java.lang.String>);
+    method public void readFromParcel(android.os.Parcel);
+    method public void remove(java.lang.String);
+    method public void setClassLoader(java.lang.ClassLoader);
+    method public int size();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final android.os.Bundle EMPTY;
+  }
+
+  public final class CancellationSignal {
+    ctor public CancellationSignal();
+    method public void cancel();
+    method public boolean isCanceled();
+    method public void setOnCancelListener(android.os.CancellationSignal.OnCancelListener);
+    method public void throwIfCanceled();
+  }
+
+  public static abstract interface CancellationSignal.OnCancelListener {
+    method public abstract void onCancel();
+  }
+
+  public class ConditionVariable {
+    ctor public ConditionVariable();
+    ctor public ConditionVariable(boolean);
+    method public void block();
+    method public boolean block(long);
+    method public void close();
+    method public void open();
+  }
+
+  public abstract class CountDownTimer {
+    ctor public CountDownTimer(long, long);
+    method public final void cancel();
+    method public abstract void onFinish();
+    method public abstract void onTick(long);
+    method public final synchronized android.os.CountDownTimer start();
+  }
+
+  public class DeadObjectException extends android.os.RemoteException {
+    ctor public DeadObjectException();
+  }
+
+  public final class Debug {
+    method public static deprecated void changeDebugPort(int);
+    method public static void dumpHprofData(java.lang.String) throws java.io.IOException;
+    method public static boolean dumpService(java.lang.String, java.io.FileDescriptor, java.lang.String[]);
+    method public static void enableEmulatorTraceOutput();
+    method public static final int getBinderDeathObjectCount();
+    method public static final int getBinderLocalObjectCount();
+    method public static final int getBinderProxyObjectCount();
+    method public static int getBinderReceivedTransactions();
+    method public static int getBinderSentTransactions();
+    method public static int getGlobalAllocCount();
+    method public static int getGlobalAllocSize();
+    method public static int getGlobalClassInitCount();
+    method public static int getGlobalClassInitTime();
+    method public static deprecated int getGlobalExternalAllocCount();
+    method public static deprecated int getGlobalExternalAllocSize();
+    method public static deprecated int getGlobalExternalFreedCount();
+    method public static deprecated int getGlobalExternalFreedSize();
+    method public static int getGlobalFreedCount();
+    method public static int getGlobalFreedSize();
+    method public static int getGlobalGcInvocationCount();
+    method public static int getLoadedClassCount();
+    method public static void getMemoryInfo(android.os.Debug.MemoryInfo);
+    method public static long getNativeHeapAllocatedSize();
+    method public static long getNativeHeapFreeSize();
+    method public static long getNativeHeapSize();
+    method public static long getPss();
+    method public static int getThreadAllocCount();
+    method public static int getThreadAllocSize();
+    method public static deprecated int getThreadExternalAllocCount();
+    method public static deprecated int getThreadExternalAllocSize();
+    method public static int getThreadGcInvocationCount();
+    method public static boolean isDebuggerConnected();
+    method public static void printLoadedClasses(int);
+    method public static void resetAllCounts();
+    method public static void resetGlobalAllocCount();
+    method public static void resetGlobalAllocSize();
+    method public static void resetGlobalClassInitCount();
+    method public static void resetGlobalClassInitTime();
+    method public static deprecated void resetGlobalExternalAllocCount();
+    method public static deprecated void resetGlobalExternalAllocSize();
+    method public static deprecated void resetGlobalExternalFreedCount();
+    method public static deprecated void resetGlobalExternalFreedSize();
+    method public static void resetGlobalFreedCount();
+    method public static void resetGlobalFreedSize();
+    method public static void resetGlobalGcInvocationCount();
+    method public static void resetThreadAllocCount();
+    method public static void resetThreadAllocSize();
+    method public static deprecated void resetThreadExternalAllocCount();
+    method public static deprecated void resetThreadExternalAllocSize();
+    method public static void resetThreadGcInvocationCount();
+    method public static deprecated int setAllocationLimit(int);
+    method public static deprecated int setGlobalAllocationLimit(int);
+    method public static void startAllocCounting();
+    method public static void startMethodTracing();
+    method public static void startMethodTracing(java.lang.String);
+    method public static void startMethodTracing(java.lang.String, int);
+    method public static void startMethodTracing(java.lang.String, int, int);
+    method public static void startNativeTracing();
+    method public static void stopAllocCounting();
+    method public static void stopMethodTracing();
+    method public static void stopNativeTracing();
+    method public static long threadCpuTimeNanos();
+    method public static void waitForDebugger();
+    method public static boolean waitingForDebugger();
+    field public static final int SHOW_CLASSLOADER = 2; // 0x2
+    field public static final int SHOW_FULL_DETAIL = 1; // 0x1
+    field public static final int SHOW_INITIALIZED = 4; // 0x4
+    field public static final int TRACE_COUNT_ALLOCS = 1; // 0x1
+  }
+
+  public static class Debug.InstructionCount {
+    ctor public Debug.InstructionCount();
+    method public boolean collect();
+    method public int globalMethodInvocations();
+    method public int globalTotal();
+    method public boolean resetAndStart();
+  }
+
+  public static class Debug.MemoryInfo implements android.os.Parcelable {
+    ctor public Debug.MemoryInfo();
+    method public int describeContents();
+    method public static java.lang.String getOtherLabel(int);
+    method public int getOtherPrivateDirty(int);
+    method public int getOtherPss(int);
+    method public int getOtherSharedDirty(int);
+    method public int getTotalPrivateDirty();
+    method public int getTotalPss();
+    method public int getTotalSharedDirty();
+    method public void readFromParcel(android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public int dalvikPrivateDirty;
+    field public int dalvikPss;
+    field public int dalvikSharedDirty;
+    field public int nativePrivateDirty;
+    field public int nativePss;
+    field public int nativeSharedDirty;
+    field public int otherPrivateDirty;
+    field public int otherPss;
+    field public int otherSharedDirty;
+  }
+
+  public class DropBoxManager {
+    ctor protected DropBoxManager();
+    method public void addData(java.lang.String, byte[], int);
+    method public void addFile(java.lang.String, java.io.File, int) throws java.io.IOException;
+    method public void addText(java.lang.String, java.lang.String);
+    method public android.os.DropBoxManager.Entry getNextEntry(java.lang.String, long);
+    method public boolean isTagEnabled(java.lang.String);
+    field public static final java.lang.String ACTION_DROPBOX_ENTRY_ADDED = "android.intent.action.DROPBOX_ENTRY_ADDED";
+    field public static final java.lang.String EXTRA_TAG = "tag";
+    field public static final java.lang.String EXTRA_TIME = "time";
+    field public static final int IS_EMPTY = 1; // 0x1
+    field public static final int IS_GZIPPED = 4; // 0x4
+    field public static final int IS_TEXT = 2; // 0x2
+  }
+
+  public static class DropBoxManager.Entry implements java.io.Closeable android.os.Parcelable {
+    ctor public DropBoxManager.Entry(java.lang.String, long);
+    ctor public DropBoxManager.Entry(java.lang.String, long, java.lang.String);
+    ctor public DropBoxManager.Entry(java.lang.String, long, byte[], int);
+    ctor public DropBoxManager.Entry(java.lang.String, long, android.os.ParcelFileDescriptor, int);
+    ctor public DropBoxManager.Entry(java.lang.String, long, java.io.File, int) throws java.io.IOException;
+    method public void close();
+    method public int describeContents();
+    method public int getFlags();
+    method public java.io.InputStream getInputStream() throws java.io.IOException;
+    method public java.lang.String getTag();
+    method public java.lang.String getText(int);
+    method public long getTimeMillis();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class Environment {
+    ctor public Environment();
+    method public static java.io.File getDataDirectory();
+    method public static java.io.File getDownloadCacheDirectory();
+    method public static java.io.File getExternalStorageDirectory();
+    method public static java.io.File getExternalStoragePublicDirectory(java.lang.String);
+    method public static java.lang.String getExternalStorageState();
+    method public static java.io.File getRootDirectory();
+    method public static boolean isExternalStorageEmulated();
+    method public static boolean isExternalStorageRemovable();
+    field public static java.lang.String DIRECTORY_ALARMS;
+    field public static java.lang.String DIRECTORY_DCIM;
+    field public static java.lang.String DIRECTORY_DOWNLOADS;
+    field public static java.lang.String DIRECTORY_MOVIES;
+    field public static java.lang.String DIRECTORY_MUSIC;
+    field public static java.lang.String DIRECTORY_NOTIFICATIONS;
+    field public static java.lang.String DIRECTORY_PICTURES;
+    field public static java.lang.String DIRECTORY_PODCASTS;
+    field public static java.lang.String DIRECTORY_RINGTONES;
+    field public static final java.lang.String MEDIA_BAD_REMOVAL = "bad_removal";
+    field public static final java.lang.String MEDIA_CHECKING = "checking";
+    field public static final java.lang.String MEDIA_MOUNTED = "mounted";
+    field public static final java.lang.String MEDIA_MOUNTED_READ_ONLY = "mounted_ro";
+    field public static final java.lang.String MEDIA_NOFS = "nofs";
+    field public static final java.lang.String MEDIA_REMOVED = "removed";
+    field public static final java.lang.String MEDIA_SHARED = "shared";
+    field public static final java.lang.String MEDIA_UNMOUNTABLE = "unmountable";
+    field public static final java.lang.String MEDIA_UNMOUNTED = "unmounted";
+  }
+
+  public abstract class FileObserver {
+    ctor public FileObserver(java.lang.String);
+    ctor public FileObserver(java.lang.String, int);
+    method public abstract void onEvent(int, java.lang.String);
+    method public void startWatching();
+    method public void stopWatching();
+    field public static final int ACCESS = 1; // 0x1
+    field public static final int ALL_EVENTS = 4095; // 0xfff
+    field public static final int ATTRIB = 4; // 0x4
+    field public static final int CLOSE_NOWRITE = 16; // 0x10
+    field public static final int CLOSE_WRITE = 8; // 0x8
+    field public static final int CREATE = 256; // 0x100
+    field public static final int DELETE = 512; // 0x200
+    field public static final int DELETE_SELF = 1024; // 0x400
+    field public static final int MODIFY = 2; // 0x2
+    field public static final int MOVED_FROM = 64; // 0x40
+    field public static final int MOVED_TO = 128; // 0x80
+    field public static final int MOVE_SELF = 2048; // 0x800
+    field public static final int OPEN = 32; // 0x20
+  }
+
+  public class Handler {
+    ctor public Handler();
+    ctor public Handler(android.os.Handler.Callback);
+    ctor public Handler(android.os.Looper);
+    ctor public Handler(android.os.Looper, android.os.Handler.Callback);
+    method public void dispatchMessage(android.os.Message);
+    method public final void dump(android.util.Printer, java.lang.String);
+    method public final android.os.Looper getLooper();
+    method public java.lang.String getMessageName(android.os.Message);
+    method public void handleMessage(android.os.Message);
+    method public final boolean hasMessages(int);
+    method public final boolean hasMessages(int, java.lang.Object);
+    method public final android.os.Message obtainMessage();
+    method public final android.os.Message obtainMessage(int);
+    method public final android.os.Message obtainMessage(int, java.lang.Object);
+    method public final android.os.Message obtainMessage(int, int, int);
+    method public final android.os.Message obtainMessage(int, int, int, java.lang.Object);
+    method public final boolean post(java.lang.Runnable);
+    method public final boolean postAtFrontOfQueue(java.lang.Runnable);
+    method public final boolean postAtTime(java.lang.Runnable, long);
+    method public final boolean postAtTime(java.lang.Runnable, java.lang.Object, long);
+    method public final boolean postDelayed(java.lang.Runnable, long);
+    method public final void removeCallbacks(java.lang.Runnable);
+    method public final void removeCallbacks(java.lang.Runnable, java.lang.Object);
+    method public final void removeCallbacksAndMessages(java.lang.Object);
+    method public final void removeMessages(int);
+    method public final void removeMessages(int, java.lang.Object);
+    method public final boolean sendEmptyMessage(int);
+    method public final boolean sendEmptyMessageAtTime(int, long);
+    method public final boolean sendEmptyMessageDelayed(int, long);
+    method public final boolean sendMessage(android.os.Message);
+    method public final boolean sendMessageAtFrontOfQueue(android.os.Message);
+    method public boolean sendMessageAtTime(android.os.Message, long);
+    method public final boolean sendMessageDelayed(android.os.Message, long);
+  }
+
+  public static abstract interface Handler.Callback {
+    method public abstract boolean handleMessage(android.os.Message);
+  }
+
+  public class HandlerThread extends java.lang.Thread {
+    ctor public HandlerThread(java.lang.String);
+    ctor public HandlerThread(java.lang.String, int);
+    method public android.os.Looper getLooper();
+    method public int getThreadId();
+    method protected void onLooperPrepared();
+    method public boolean quit();
+  }
+
+  public abstract interface IBinder {
+    method public abstract void dump(java.io.FileDescriptor, java.lang.String[]) throws android.os.RemoteException;
+    method public abstract void dumpAsync(java.io.FileDescriptor, java.lang.String[]) throws android.os.RemoteException;
+    method public abstract java.lang.String getInterfaceDescriptor() throws android.os.RemoteException;
+    method public abstract boolean isBinderAlive();
+    method public abstract void linkToDeath(android.os.IBinder.DeathRecipient, int) throws android.os.RemoteException;
+    method public abstract boolean pingBinder();
+    method public abstract android.os.IInterface queryLocalInterface(java.lang.String);
+    method public abstract boolean transact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
+    method public abstract boolean unlinkToDeath(android.os.IBinder.DeathRecipient, int);
+    field public static final int DUMP_TRANSACTION = 1598311760; // 0x5f444d50
+    field public static final int FIRST_CALL_TRANSACTION = 1; // 0x1
+    field public static final int FLAG_ONEWAY = 1; // 0x1
+    field public static final int INTERFACE_TRANSACTION = 1598968902; // 0x5f4e5446
+    field public static final int LAST_CALL_TRANSACTION = 16777215; // 0xffffff
+    field public static final int LIKE_TRANSACTION = 1598835019; // 0x5f4c494b
+    field public static final int PING_TRANSACTION = 1599098439; // 0x5f504e47
+    field public static final int TWEET_TRANSACTION = 1599362900; // 0x5f545754
+  }
+
+  public static abstract interface IBinder.DeathRecipient {
+    method public abstract void binderDied();
+  }
+
+  public abstract interface IInterface {
+    method public abstract android.os.IBinder asBinder();
+  }
+
+  public class Looper {
+    method public void dump(android.util.Printer, java.lang.String);
+    method public static android.os.Looper getMainLooper();
+    method public java.lang.Thread getThread();
+    method public static void loop();
+    method public static android.os.Looper myLooper();
+    method public static android.os.MessageQueue myQueue();
+    method public static void prepare();
+    method public static void prepareMainLooper();
+    method public void quit();
+    method public void setMessageLogging(android.util.Printer);
+  }
+
+  public class MemoryFile {
+    ctor public MemoryFile(java.lang.String, int) throws java.io.IOException;
+    method public synchronized boolean allowPurging(boolean) throws java.io.IOException;
+    method public void close();
+    method public java.io.InputStream getInputStream();
+    method public java.io.OutputStream getOutputStream();
+    method public boolean isPurgingAllowed();
+    method public int length();
+    method public int readBytes(byte[], int, int, int) throws java.io.IOException;
+    method public void writeBytes(byte[], int, int, int) throws java.io.IOException;
+  }
+
+  public final class Message implements android.os.Parcelable {
+    ctor public Message();
+    method public void copyFrom(android.os.Message);
+    method public int describeContents();
+    method public java.lang.Runnable getCallback();
+    method public android.os.Bundle getData();
+    method public android.os.Handler getTarget();
+    method public long getWhen();
+    method public static android.os.Message obtain();
+    method public static android.os.Message obtain(android.os.Message);
+    method public static android.os.Message obtain(android.os.Handler);
+    method public static android.os.Message obtain(android.os.Handler, java.lang.Runnable);
+    method public static android.os.Message obtain(android.os.Handler, int);
+    method public static android.os.Message obtain(android.os.Handler, int, java.lang.Object);
+    method public static android.os.Message obtain(android.os.Handler, int, int, int);
+    method public static android.os.Message obtain(android.os.Handler, int, int, int, java.lang.Object);
+    method public android.os.Bundle peekData();
+    method public void recycle();
+    method public void sendToTarget();
+    method public void setData(android.os.Bundle);
+    method public void setTarget(android.os.Handler);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public int arg1;
+    field public int arg2;
+    field public java.lang.Object obj;
+    field public android.os.Messenger replyTo;
+    field public int what;
+  }
+
+  public class MessageQueue {
+    method public final void addIdleHandler(android.os.MessageQueue.IdleHandler);
+    method public final void removeIdleHandler(android.os.MessageQueue.IdleHandler);
+  }
+
+  public static abstract interface MessageQueue.IdleHandler {
+    method public abstract boolean queueIdle();
+  }
+
+  public final class Messenger implements android.os.Parcelable {
+    ctor public Messenger(android.os.Handler);
+    ctor public Messenger(android.os.IBinder);
+    method public int describeContents();
+    method public android.os.IBinder getBinder();
+    method public static android.os.Messenger readMessengerOrNullFromParcel(android.os.Parcel);
+    method public void send(android.os.Message) throws android.os.RemoteException;
+    method public static void writeMessengerOrNullToParcel(android.os.Messenger, android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class NetworkOnMainThreadException extends java.lang.RuntimeException {
+    ctor public NetworkOnMainThreadException();
+  }
+
+  public class OperationCanceledException extends java.lang.RuntimeException {
+    ctor public OperationCanceledException();
+    ctor public OperationCanceledException(java.lang.String);
+  }
+
+  public final class Parcel {
+    method public final void appendFrom(android.os.Parcel, int, int);
+    method public final android.os.IBinder[] createBinderArray();
+    method public final java.util.ArrayList<android.os.IBinder> createBinderArrayList();
+    method public final boolean[] createBooleanArray();
+    method public final byte[] createByteArray();
+    method public final char[] createCharArray();
+    method public final double[] createDoubleArray();
+    method public final float[] createFloatArray();
+    method public final int[] createIntArray();
+    method public final long[] createLongArray();
+    method public final java.lang.String[] createStringArray();
+    method public final java.util.ArrayList<java.lang.String> createStringArrayList();
+    method public final T[] createTypedArray(android.os.Parcelable.Creator<T>);
+    method public final java.util.ArrayList<T> createTypedArrayList(android.os.Parcelable.Creator<T>);
+    method public final int dataAvail();
+    method public final int dataCapacity();
+    method public final int dataPosition();
+    method public final int dataSize();
+    method public final void enforceInterface(java.lang.String);
+    method public final boolean hasFileDescriptors();
+    method public final byte[] marshall();
+    method public static android.os.Parcel obtain();
+    method protected static final android.os.Parcel obtain(int);
+    method public final java.lang.Object[] readArray(java.lang.ClassLoader);
+    method public final java.util.ArrayList readArrayList(java.lang.ClassLoader);
+    method public final void readBinderArray(android.os.IBinder[]);
+    method public final void readBinderList(java.util.List<android.os.IBinder>);
+    method public final void readBooleanArray(boolean[]);
+    method public final android.os.Bundle readBundle();
+    method public final android.os.Bundle readBundle(java.lang.ClassLoader);
+    method public final byte readByte();
+    method public final void readByteArray(byte[]);
+    method public final void readCharArray(char[]);
+    method public final double readDouble();
+    method public final void readDoubleArray(double[]);
+    method public final void readException();
+    method public final void readException(int, java.lang.String);
+    method public final android.os.ParcelFileDescriptor readFileDescriptor();
+    method public final float readFloat();
+    method public final void readFloatArray(float[]);
+    method public final java.util.HashMap readHashMap(java.lang.ClassLoader);
+    method public final int readInt();
+    method public final void readIntArray(int[]);
+    method public final void readList(java.util.List, java.lang.ClassLoader);
+    method public final long readLong();
+    method public final void readLongArray(long[]);
+    method public final void readMap(java.util.Map, java.lang.ClassLoader);
+    method public final T readParcelable(java.lang.ClassLoader);
+    method public final android.os.Parcelable[] readParcelableArray(java.lang.ClassLoader);
+    method public final java.io.Serializable readSerializable();
+    method public final android.util.SparseArray readSparseArray(java.lang.ClassLoader);
+    method public final android.util.SparseBooleanArray readSparseBooleanArray();
+    method public final java.lang.String readString();
+    method public final void readStringArray(java.lang.String[]);
+    method public final void readStringList(java.util.List<java.lang.String>);
+    method public final android.os.IBinder readStrongBinder();
+    method public final void readTypedArray(T[], android.os.Parcelable.Creator<T>);
+    method public final void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
+    method public final java.lang.Object readValue(java.lang.ClassLoader);
+    method public final void recycle();
+    method public final void setDataCapacity(int);
+    method public final void setDataPosition(int);
+    method public final void setDataSize(int);
+    method public final void unmarshall(byte[], int, int);
+    method public final void writeArray(java.lang.Object[]);
+    method public final void writeBinderArray(android.os.IBinder[]);
+    method public final void writeBinderList(java.util.List<android.os.IBinder>);
+    method public final void writeBooleanArray(boolean[]);
+    method public final void writeBundle(android.os.Bundle);
+    method public final void writeByte(byte);
+    method public final void writeByteArray(byte[]);
+    method public final void writeByteArray(byte[], int, int);
+    method public final void writeCharArray(char[]);
+    method public final void writeDouble(double);
+    method public final void writeDoubleArray(double[]);
+    method public final void writeException(java.lang.Exception);
+    method public final void writeFileDescriptor(java.io.FileDescriptor);
+    method public final void writeFloat(float);
+    method public final void writeFloatArray(float[]);
+    method public final void writeInt(int);
+    method public final void writeIntArray(int[]);
+    method public final void writeInterfaceToken(java.lang.String);
+    method public final void writeList(java.util.List);
+    method public final void writeLong(long);
+    method public final void writeLongArray(long[]);
+    method public final void writeMap(java.util.Map);
+    method public final void writeNoException();
+    method public final void writeParcelable(android.os.Parcelable, int);
+    method public final void writeParcelableArray(T[], int);
+    method public final void writeSerializable(java.io.Serializable);
+    method public final void writeSparseArray(android.util.SparseArray<java.lang.Object>);
+    method public final void writeSparseBooleanArray(android.util.SparseBooleanArray);
+    method public final void writeString(java.lang.String);
+    method public final void writeStringArray(java.lang.String[]);
+    method public final void writeStringList(java.util.List<java.lang.String>);
+    method public final void writeStrongBinder(android.os.IBinder);
+    method public final void writeStrongInterface(android.os.IInterface);
+    method public final void writeTypedArray(T[], int);
+    method public final void writeTypedList(java.util.List<T>);
+    method public final void writeValue(java.lang.Object);
+    field public static final android.os.Parcelable.Creator STRING_CREATOR;
+  }
+
+  public class ParcelFileDescriptor implements java.io.Closeable android.os.Parcelable {
+    ctor public ParcelFileDescriptor(android.os.ParcelFileDescriptor);
+    method public static android.os.ParcelFileDescriptor adoptFd(int);
+    method public void close() throws java.io.IOException;
+    method public static android.os.ParcelFileDescriptor[] createPipe() throws java.io.IOException;
+    method public int describeContents();
+    method public int detachFd();
+    method public static android.os.ParcelFileDescriptor dup(java.io.FileDescriptor) throws java.io.IOException;
+    method public android.os.ParcelFileDescriptor dup() throws java.io.IOException;
+    method public static android.os.ParcelFileDescriptor fromDatagramSocket(java.net.DatagramSocket);
+    method public static android.os.ParcelFileDescriptor fromFd(int) throws java.io.IOException;
+    method public static android.os.ParcelFileDescriptor fromSocket(java.net.Socket);
+    method public int getFd();
+    method public java.io.FileDescriptor getFileDescriptor();
+    method public long getStatSize();
+    method public static android.os.ParcelFileDescriptor open(java.io.File, int) throws java.io.FileNotFoundException;
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int MODE_APPEND = 33554432; // 0x2000000
+    field public static final int MODE_CREATE = 134217728; // 0x8000000
+    field public static final int MODE_READ_ONLY = 268435456; // 0x10000000
+    field public static final int MODE_READ_WRITE = 805306368; // 0x30000000
+    field public static final int MODE_TRUNCATE = 67108864; // 0x4000000
+    field public static final int MODE_WORLD_READABLE = 1; // 0x1
+    field public static final int MODE_WORLD_WRITEABLE = 2; // 0x2
+    field public static final int MODE_WRITE_ONLY = 536870912; // 0x20000000
+  }
+
+  public static class ParcelFileDescriptor.AutoCloseInputStream extends java.io.FileInputStream {
+    ctor public ParcelFileDescriptor.AutoCloseInputStream(android.os.ParcelFileDescriptor);
+  }
+
+  public static class ParcelFileDescriptor.AutoCloseOutputStream extends java.io.FileOutputStream {
+    ctor public ParcelFileDescriptor.AutoCloseOutputStream(android.os.ParcelFileDescriptor);
+  }
+
+  public class ParcelFormatException extends java.lang.RuntimeException {
+    ctor public ParcelFormatException();
+    ctor public ParcelFormatException(java.lang.String);
+  }
+
+  public final class ParcelUuid implements android.os.Parcelable {
+    ctor public ParcelUuid(java.util.UUID);
+    method public int describeContents();
+    method public static android.os.ParcelUuid fromString(java.lang.String);
+    method public java.util.UUID getUuid();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public abstract interface Parcelable {
+    method public abstract int describeContents();
+    method public abstract void writeToParcel(android.os.Parcel, int);
+    field public static final int CONTENTS_FILE_DESCRIPTOR = 1; // 0x1
+    field public static final int PARCELABLE_WRITE_RETURN_VALUE = 1; // 0x1
+  }
+
+  public static abstract interface Parcelable.ClassLoaderCreator implements android.os.Parcelable.Creator {
+    method public abstract T createFromParcel(android.os.Parcel, java.lang.ClassLoader);
+  }
+
+  public static abstract interface Parcelable.Creator {
+    method public abstract T createFromParcel(android.os.Parcel);
+    method public abstract T[] newArray(int);
+  }
+
+  public class PatternMatcher implements android.os.Parcelable {
+    ctor public PatternMatcher(java.lang.String, int);
+    ctor public PatternMatcher(android.os.Parcel);
+    method public int describeContents();
+    method public final java.lang.String getPath();
+    method public final int getType();
+    method public boolean match(java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int PATTERN_LITERAL = 0; // 0x0
+    field public static final int PATTERN_PREFIX = 1; // 0x1
+    field public static final int PATTERN_SIMPLE_GLOB = 2; // 0x2
+  }
+
+  public final class PowerManager {
+    method public void goToSleep(long);
+    method public boolean isScreenOn();
+    method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
+    method public void reboot(java.lang.String);
+    method public void userActivity(long, boolean);
+    method public void wakeUp(long);
+    field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
+    field public static final deprecated int FULL_WAKE_LOCK = 26; // 0x1a
+    field public static final int ON_AFTER_RELEASE = 536870912; // 0x20000000
+    field public static final int PARTIAL_WAKE_LOCK = 1; // 0x1
+    field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
+    field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
+  }
+
+  public final class PowerManager.WakeLock {
+    method public void acquire();
+    method public void acquire(long);
+    method public boolean isHeld();
+    method public void release();
+    method public void setReferenceCounted(boolean);
+    method public void setWorkSource(android.os.WorkSource);
+  }
+
+  public class Process {
+    ctor public Process();
+    method public static final long getElapsedCpuTime();
+    method public static final int getGidForName(java.lang.String);
+    method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException;
+    method public static final int getUidForName(java.lang.String);
+    method public static final void killProcess(int);
+    method public static final int myPid();
+    method public static final int myTid();
+    method public static final int myUid();
+    method public static final android.os.UserHandle myUserHandle();
+    method public static final void sendSignal(int, int);
+    method public static final void setThreadPriority(int, int) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
+    method public static final void setThreadPriority(int) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
+    method public static final deprecated boolean supportsProcesses();
+    field public static final int BLUETOOTH_GID = 2000; // 0x7d0
+    field public static final int FIRST_APPLICATION_UID = 10000; // 0x2710
+    field public static final int LAST_APPLICATION_UID = 19999; // 0x4e1f
+    field public static final int PHONE_UID = 1001; // 0x3e9
+    field public static final int SIGNAL_KILL = 9; // 0x9
+    field public static final int SIGNAL_QUIT = 3; // 0x3
+    field public static final int SIGNAL_USR1 = 10; // 0xa
+    field public static final int SYSTEM_UID = 1000; // 0x3e8
+    field public static final int THREAD_PRIORITY_AUDIO = -16; // 0xfffffff0
+    field public static final int THREAD_PRIORITY_BACKGROUND = 10; // 0xa
+    field public static final int THREAD_PRIORITY_DEFAULT = 0; // 0x0
+    field public static final int THREAD_PRIORITY_DISPLAY = -4; // 0xfffffffc
+    field public static final int THREAD_PRIORITY_FOREGROUND = -2; // 0xfffffffe
+    field public static final int THREAD_PRIORITY_LESS_FAVORABLE = 1; // 0x1
+    field public static final int THREAD_PRIORITY_LOWEST = 19; // 0x13
+    field public static final int THREAD_PRIORITY_MORE_FAVORABLE = -1; // 0xffffffff
+    field public static final int THREAD_PRIORITY_URGENT_AUDIO = -19; // 0xffffffed
+    field public static final int THREAD_PRIORITY_URGENT_DISPLAY = -8; // 0xfffffff8
+  }
+
+  public class RecoverySystem {
+    ctor public RecoverySystem();
+    method public static void installPackage(android.content.Context, java.io.File) throws java.io.IOException;
+    method public static void rebootWipeCache(android.content.Context) throws java.io.IOException;
+    method public static void rebootWipeUserData(android.content.Context) throws java.io.IOException;
+    method public static void verifyPackage(java.io.File, android.os.RecoverySystem.ProgressListener, java.io.File) throws java.security.GeneralSecurityException, java.io.IOException;
+  }
+
+  public static abstract interface RecoverySystem.ProgressListener {
+    method public abstract void onProgress(int);
+  }
+
+  public class RemoteCallbackList {
+    ctor public RemoteCallbackList();
+    method public int beginBroadcast();
+    method public void finishBroadcast();
+    method public java.lang.Object getBroadcastCookie(int);
+    method public E getBroadcastItem(int);
+    method public int getRegisteredCallbackCount();
+    method public void kill();
+    method public void onCallbackDied(E);
+    method public void onCallbackDied(E, java.lang.Object);
+    method public boolean register(E);
+    method public boolean register(E, java.lang.Object);
+    method public boolean unregister(E);
+  }
+
+  public class RemoteException extends android.util.AndroidException {
+    ctor public RemoteException();
+    ctor public RemoteException(java.lang.String);
+  }
+
+  public class ResultReceiver implements android.os.Parcelable {
+    ctor public ResultReceiver(android.os.Handler);
+    method public int describeContents();
+    method protected void onReceiveResult(int, android.os.Bundle);
+    method public void send(int, android.os.Bundle);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class StatFs {
+    ctor public StatFs(java.lang.String);
+    method public int getAvailableBlocks();
+    method public int getBlockCount();
+    method public int getBlockSize();
+    method public int getFreeBlocks();
+    method public void restat(java.lang.String);
+  }
+
+  public final class StrictMode {
+    method public static android.os.StrictMode.ThreadPolicy allowThreadDiskReads();
+    method public static android.os.StrictMode.ThreadPolicy allowThreadDiskWrites();
+    method public static void enableDefaults();
+    method public static android.os.StrictMode.ThreadPolicy getThreadPolicy();
+    method public static android.os.StrictMode.VmPolicy getVmPolicy();
+    method public static void noteSlowCall(java.lang.String);
+    method public static void setThreadPolicy(android.os.StrictMode.ThreadPolicy);
+    method public static void setVmPolicy(android.os.StrictMode.VmPolicy);
+  }
+
+  public static final class StrictMode.ThreadPolicy {
+    field public static final android.os.StrictMode.ThreadPolicy LAX;
+  }
+
+  public static final class StrictMode.ThreadPolicy.Builder {
+    ctor public StrictMode.ThreadPolicy.Builder();
+    ctor public StrictMode.ThreadPolicy.Builder(android.os.StrictMode.ThreadPolicy);
+    method public android.os.StrictMode.ThreadPolicy build();
+    method public android.os.StrictMode.ThreadPolicy.Builder detectAll();
+    method public android.os.StrictMode.ThreadPolicy.Builder detectCustomSlowCalls();
+    method public android.os.StrictMode.ThreadPolicy.Builder detectDiskReads();
+    method public android.os.StrictMode.ThreadPolicy.Builder detectDiskWrites();
+    method public android.os.StrictMode.ThreadPolicy.Builder detectNetwork();
+    method public android.os.StrictMode.ThreadPolicy.Builder penaltyDeath();
+    method public android.os.StrictMode.ThreadPolicy.Builder penaltyDeathOnNetwork();
+    method public android.os.StrictMode.ThreadPolicy.Builder penaltyDialog();
+    method public android.os.StrictMode.ThreadPolicy.Builder penaltyDropBox();
+    method public android.os.StrictMode.ThreadPolicy.Builder penaltyFlashScreen();
+    method public android.os.StrictMode.ThreadPolicy.Builder penaltyLog();
+    method public android.os.StrictMode.ThreadPolicy.Builder permitAll();
+    method public android.os.StrictMode.ThreadPolicy.Builder permitCustomSlowCalls();
+    method public android.os.StrictMode.ThreadPolicy.Builder permitDiskReads();
+    method public android.os.StrictMode.ThreadPolicy.Builder permitDiskWrites();
+    method public android.os.StrictMode.ThreadPolicy.Builder permitNetwork();
+  }
+
+  public static final class StrictMode.VmPolicy {
+    field public static final android.os.StrictMode.VmPolicy LAX;
+  }
+
+  public static final class StrictMode.VmPolicy.Builder {
+    ctor public StrictMode.VmPolicy.Builder();
+    ctor public StrictMode.VmPolicy.Builder(android.os.StrictMode.VmPolicy);
+    method public android.os.StrictMode.VmPolicy build();
+    method public android.os.StrictMode.VmPolicy.Builder detectActivityLeaks();
+    method public android.os.StrictMode.VmPolicy.Builder detectAll();
+    method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects();
+    method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects();
+    method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects();
+    method public android.os.StrictMode.VmPolicy.Builder penaltyDeath();
+    method public android.os.StrictMode.VmPolicy.Builder penaltyDropBox();
+    method public android.os.StrictMode.VmPolicy.Builder penaltyLog();
+    method public android.os.StrictMode.VmPolicy.Builder setClassInstanceLimit(java.lang.Class, int);
+  }
+
+  public final class SystemClock {
+    method public static long currentThreadTimeMillis();
+    method public static long elapsedRealtime();
+    method public static long elapsedRealtimeNanos();
+    method public static boolean setCurrentTimeMillis(long);
+    method public static void sleep(long);
+    method public static long uptimeMillis();
+  }
+
+  public abstract class TokenWatcher {
+    ctor public TokenWatcher(android.os.Handler, java.lang.String);
+    method public void acquire(android.os.IBinder, java.lang.String);
+    method public abstract void acquired();
+    method public void cleanup(android.os.IBinder, boolean);
+    method public void dump();
+    method public void dump(java.io.PrintWriter);
+    method public boolean isAcquired();
+    method public void release(android.os.IBinder);
+    method public abstract void released();
+  }
+
+  public class TransactionTooLargeException extends android.os.RemoteException {
+    ctor public TransactionTooLargeException();
+  }
+
+  public final class UserHandle implements android.os.Parcelable {
+    ctor public UserHandle(android.os.Parcel);
+    method public int describeContents();
+    method public static android.os.UserHandle readFromParcel(android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    method public static void writeToParcel(android.os.UserHandle, android.os.Parcel);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class UserManager {
+    method public long getSerialNumberForUser(android.os.UserHandle);
+    method public int getUserCount();
+    method public android.os.UserHandle getUserForSerialNumber(long);
+    method public java.lang.String getUserName();
+    method public boolean isUserAGoat();
+    method public boolean isUserRunning(android.os.UserHandle);
+    method public boolean isUserRunningOrStopping(android.os.UserHandle);
+  }
+
+  public abstract class Vibrator {
+    method public abstract void cancel();
+    method public abstract boolean hasVibrator();
+    method public abstract void vibrate(long);
+    method public abstract void vibrate(long[], int);
+  }
+
+  public class WorkSource implements android.os.Parcelable {
+    ctor public WorkSource();
+    ctor public WorkSource(android.os.WorkSource);
+    method public boolean add(android.os.WorkSource);
+    method public void clear();
+    method public int describeContents();
+    method public boolean diff(android.os.WorkSource);
+    method public boolean remove(android.os.WorkSource);
+    method public void set(android.os.WorkSource);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+}
+
+package android.os.storage {
+
+  public abstract class OnObbStateChangeListener {
+    ctor public OnObbStateChangeListener();
+    method public void onObbStateChange(java.lang.String, int);
+    field public static final int ERROR_ALREADY_MOUNTED = 24; // 0x18
+    field public static final int ERROR_COULD_NOT_MOUNT = 21; // 0x15
+    field public static final int ERROR_COULD_NOT_UNMOUNT = 22; // 0x16
+    field public static final int ERROR_INTERNAL = 20; // 0x14
+    field public static final int ERROR_NOT_MOUNTED = 23; // 0x17
+    field public static final int ERROR_PERMISSION_DENIED = 25; // 0x19
+    field public static final int MOUNTED = 1; // 0x1
+    field public static final int UNMOUNTED = 2; // 0x2
+  }
+
+  public class StorageManager {
+    method public java.lang.String getMountedObbPath(java.lang.String);
+    method public boolean isObbMounted(java.lang.String);
+    method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener);
+    method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
+  }
+
+}
+
+package android.preference {
+
+  public class CheckBoxPreference extends android.preference.TwoStatePreference {
+    ctor public CheckBoxPreference(android.content.Context, android.util.AttributeSet, int);
+    ctor public CheckBoxPreference(android.content.Context, android.util.AttributeSet);
+    ctor public CheckBoxPreference(android.content.Context);
+  }
+
+  public abstract class DialogPreference extends android.preference.Preference implements android.content.DialogInterface.OnClickListener android.content.DialogInterface.OnDismissListener android.preference.PreferenceManager.OnActivityDestroyListener {
+    ctor public DialogPreference(android.content.Context, android.util.AttributeSet, int);
+    ctor public DialogPreference(android.content.Context, android.util.AttributeSet);
+    method public android.app.Dialog getDialog();
+    method public android.graphics.drawable.Drawable getDialogIcon();
+    method public int getDialogLayoutResource();
+    method public java.lang.CharSequence getDialogMessage();
+    method public java.lang.CharSequence getDialogTitle();
+    method public java.lang.CharSequence getNegativeButtonText();
+    method public java.lang.CharSequence getPositiveButtonText();
+    method public void onActivityDestroy();
+    method protected void onBindDialogView(android.view.View);
+    method public void onClick(android.content.DialogInterface, int);
+    method protected android.view.View onCreateDialogView();
+    method protected void onDialogClosed(boolean);
+    method public void onDismiss(android.content.DialogInterface);
+    method protected void onPrepareDialogBuilder(android.app.AlertDialog.Builder);
+    method public void setDialogIcon(android.graphics.drawable.Drawable);
+    method public void setDialogIcon(int);
+    method public void setDialogLayoutResource(int);
+    method public void setDialogMessage(java.lang.CharSequence);
+    method public void setDialogMessage(int);
+    method public void setDialogTitle(java.lang.CharSequence);
+    method public void setDialogTitle(int);
+    method public void setNegativeButtonText(java.lang.CharSequence);
+    method public void setNegativeButtonText(int);
+    method public void setPositiveButtonText(java.lang.CharSequence);
+    method public void setPositiveButtonText(int);
+    method protected void showDialog(android.os.Bundle);
+  }
+
+  public class EditTextPreference extends android.preference.DialogPreference {
+    ctor public EditTextPreference(android.content.Context, android.util.AttributeSet, int);
+    ctor public EditTextPreference(android.content.Context, android.util.AttributeSet);
+    ctor public EditTextPreference(android.content.Context);
+    method public android.widget.EditText getEditText();
+    method public java.lang.String getText();
+    method protected void onAddEditTextToDialogView(android.view.View, android.widget.EditText);
+    method public void setText(java.lang.String);
+  }
+
+  public class ListPreference extends android.preference.DialogPreference {
+    ctor public ListPreference(android.content.Context, android.util.AttributeSet);
+    ctor public ListPreference(android.content.Context);
+    method public int findIndexOfValue(java.lang.String);
+    method public java.lang.CharSequence[] getEntries();
+    method public java.lang.CharSequence getEntry();
+    method public java.lang.CharSequence[] getEntryValues();
+    method public java.lang.String getValue();
+    method public void setEntries(java.lang.CharSequence[]);
+    method public void setEntries(int);
+    method public void setEntryValues(java.lang.CharSequence[]);
+    method public void setEntryValues(int);
+    method public void setValue(java.lang.String);
+    method public void setValueIndex(int);
+  }
+
+  public class MultiSelectListPreference extends android.preference.DialogPreference {
+    ctor public MultiSelectListPreference(android.content.Context, android.util.AttributeSet);
+    ctor public MultiSelectListPreference(android.content.Context);
+    method public int findIndexOfValue(java.lang.String);
+    method public java.lang.CharSequence[] getEntries();
+    method public java.lang.CharSequence[] getEntryValues();
+    method public java.util.Set<java.lang.String> getValues();
+    method public void setEntries(java.lang.CharSequence[]);
+    method public void setEntries(int);
+    method public void setEntryValues(java.lang.CharSequence[]);
+    method public void setEntryValues(int);
+    method public void setValues(java.util.Set<java.lang.String>);
+  }
+
+  public class Preference implements java.lang.Comparable {
+    ctor public Preference(android.content.Context, android.util.AttributeSet, int);
+    ctor public Preference(android.content.Context, android.util.AttributeSet);
+    ctor public Preference(android.content.Context);
+    method protected boolean callChangeListener(java.lang.Object);
+    method public int compareTo(android.preference.Preference);
+    method protected android.preference.Preference findPreferenceInHierarchy(java.lang.String);
+    method public android.content.Context getContext();
+    method public java.lang.String getDependency();
+    method public android.content.SharedPreferences.Editor getEditor();
+    method public android.os.Bundle getExtras();
+    method public java.lang.String getFragment();
+    method public android.graphics.drawable.Drawable getIcon();
+    method public android.content.Intent getIntent();
+    method public java.lang.String getKey();
+    method public int getLayoutResource();
+    method public android.preference.Preference.OnPreferenceChangeListener getOnPreferenceChangeListener();
+    method public android.preference.Preference.OnPreferenceClickListener getOnPreferenceClickListener();
+    method public int getOrder();
+    method protected boolean getPersistedBoolean(boolean);
+    method protected float getPersistedFloat(float);
+    method protected int getPersistedInt(int);
+    method protected long getPersistedLong(long);
+    method protected java.lang.String getPersistedString(java.lang.String);
+    method public android.preference.PreferenceManager getPreferenceManager();
+    method public android.content.SharedPreferences getSharedPreferences();
+    method public boolean getShouldDisableView();
+    method public java.lang.CharSequence getSummary();
+    method public java.lang.CharSequence getTitle();
+    method public int getTitleRes();
+    method public android.view.View getView(android.view.View, android.view.ViewGroup);
+    method public int getWidgetLayoutResource();
+    method public boolean hasKey();
+    method public boolean isEnabled();
+    method public boolean isPersistent();
+    method public boolean isSelectable();
+    method protected void notifyChanged();
+    method public void notifyDependencyChange(boolean);
+    method protected void notifyHierarchyChanged();
+    method protected void onAttachedToActivity();
+    method protected void onAttachedToHierarchy(android.preference.PreferenceManager);
+    method protected void onBindView(android.view.View);
+    method protected void onClick();
+    method protected android.view.View onCreateView(android.view.ViewGroup);
+    method public void onDependencyChanged(android.preference.Preference, boolean);
+    method protected java.lang.Object onGetDefaultValue(android.content.res.TypedArray, int);
+    method protected void onPrepareForRemoval();
+    method protected void onRestoreInstanceState(android.os.Parcelable);
+    method protected android.os.Parcelable onSaveInstanceState();
+    method protected void onSetInitialValue(boolean, java.lang.Object);
+    method public android.os.Bundle peekExtras();
+    method protected boolean persistBoolean(boolean);
+    method protected boolean persistFloat(float);
+    method protected boolean persistInt(int);
+    method protected boolean persistLong(long);
+    method protected boolean persistString(java.lang.String);
+    method public void restoreHierarchyState(android.os.Bundle);
+    method public void saveHierarchyState(android.os.Bundle);
+    method public void setDefaultValue(java.lang.Object);
+    method public void setDependency(java.lang.String);
+    method public void setEnabled(boolean);
+    method public void setFragment(java.lang.String);
+    method public void setIcon(android.graphics.drawable.Drawable);
+    method public void setIcon(int);
+    method public void setIntent(android.content.Intent);
+    method public void setKey(java.lang.String);
+    method public void setLayoutResource(int);
+    method public void setOnPreferenceChangeListener(android.preference.Preference.OnPreferenceChangeListener);
+    method public void setOnPreferenceClickListener(android.preference.Preference.OnPreferenceClickListener);
+    method public void setOrder(int);
+    method public void setPersistent(boolean);
+    method public void setSelectable(boolean);
+    method public void setShouldDisableView(boolean);
+    method public void setSummary(java.lang.CharSequence);
+    method public void setSummary(int);
+    method public void setTitle(java.lang.CharSequence);
+    method public void setTitle(int);
+    method public void setWidgetLayoutResource(int);
+    method public boolean shouldCommit();
+    method public boolean shouldDisableDependents();
+    method protected boolean shouldPersist();
+    field public static final int DEFAULT_ORDER = 2147483647; // 0x7fffffff
+  }
+
+  public static class Preference.BaseSavedState extends android.view.AbsSavedState {
+    ctor public Preference.BaseSavedState(android.os.Parcel);
+    ctor public Preference.BaseSavedState(android.os.Parcelable);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static abstract interface Preference.OnPreferenceChangeListener {
+    method public abstract boolean onPreferenceChange(android.preference.Preference, java.lang.Object);
+  }
+
+  public static abstract interface Preference.OnPreferenceClickListener {
+    method public abstract boolean onPreferenceClick(android.preference.Preference);
+  }
+
+  public abstract class PreferenceActivity extends android.app.ListActivity implements android.preference.PreferenceFragment.OnPreferenceStartFragmentCallback {
+    ctor public PreferenceActivity();
+    method public deprecated void addPreferencesFromIntent(android.content.Intent);
+    method public deprecated void addPreferencesFromResource(int);
+    method public deprecated android.preference.Preference findPreference(java.lang.CharSequence);
+    method public void finishPreferencePanel(android.app.Fragment, int, android.content.Intent);
+    method public deprecated android.preference.PreferenceManager getPreferenceManager();
+    method public deprecated android.preference.PreferenceScreen getPreferenceScreen();
+    method public boolean hasHeaders();
+    method public void invalidateHeaders();
+    method public boolean isMultiPane();
+    method public void loadHeadersFromResource(int, java.util.List<android.preference.PreferenceActivity.Header>);
+    method public void onBuildHeaders(java.util.List<android.preference.PreferenceActivity.Header>);
+    method public android.content.Intent onBuildStartFragmentIntent(java.lang.String, android.os.Bundle, int, int);
+    method public android.preference.PreferenceActivity.Header onGetInitialHeader();
+    method public android.preference.PreferenceActivity.Header onGetNewHeader();
+    method public void onHeaderClick(android.preference.PreferenceActivity.Header, int);
+    method public boolean onIsHidingHeaders();
+    method public boolean onIsMultiPane();
+    method public boolean onPreferenceStartFragment(android.preference.PreferenceFragment, android.preference.Preference);
+    method public deprecated boolean onPreferenceTreeClick(android.preference.PreferenceScreen, android.preference.Preference);
+    method public void setListFooter(android.view.View);
+    method public void setParentTitle(java.lang.CharSequence, java.lang.CharSequence, android.view.View.OnClickListener);
+    method public deprecated void setPreferenceScreen(android.preference.PreferenceScreen);
+    method public void showBreadCrumbs(java.lang.CharSequence, java.lang.CharSequence);
+    method public void startPreferenceFragment(android.app.Fragment, boolean);
+    method public void startPreferencePanel(java.lang.String, android.os.Bundle, int, java.lang.CharSequence, android.app.Fragment, int);
+    method public void startWithFragment(java.lang.String, android.os.Bundle, android.app.Fragment, int);
+    method public void startWithFragment(java.lang.String, android.os.Bundle, android.app.Fragment, int, int, int);
+    method public void switchToHeader(java.lang.String, android.os.Bundle);
+    method public void switchToHeader(android.preference.PreferenceActivity.Header);
+    field public static final java.lang.String EXTRA_NO_HEADERS = ":android:no_headers";
+    field public static final java.lang.String EXTRA_SHOW_FRAGMENT = ":android:show_fragment";
+    field public static final java.lang.String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":android:show_fragment_args";
+    field public static final java.lang.String EXTRA_SHOW_FRAGMENT_SHORT_TITLE = ":android:show_fragment_short_title";
+    field public static final java.lang.String EXTRA_SHOW_FRAGMENT_TITLE = ":android:show_fragment_title";
+    field public static final long HEADER_ID_UNDEFINED = -1L; // 0xffffffffffffffffL
+  }
+
+  public static final class PreferenceActivity.Header implements android.os.Parcelable {
+    ctor public PreferenceActivity.Header();
+    method public int describeContents();
+    method public java.lang.CharSequence getBreadCrumbShortTitle(android.content.res.Resources);
+    method public java.lang.CharSequence getBreadCrumbTitle(android.content.res.Resources);
+    method public java.lang.CharSequence getSummary(android.content.res.Resources);
+    method public java.lang.CharSequence getTitle(android.content.res.Resources);
+    method public void readFromParcel(android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public java.lang.CharSequence breadCrumbShortTitle;
+    field public int breadCrumbShortTitleRes;
+    field public java.lang.CharSequence breadCrumbTitle;
+    field public int breadCrumbTitleRes;
+    field public android.os.Bundle extras;
+    field public java.lang.String fragment;
+    field public android.os.Bundle fragmentArguments;
+    field public int iconRes;
+    field public long id;
+    field public android.content.Intent intent;
+    field public java.lang.CharSequence summary;
+    field public int summaryRes;
+    field public java.lang.CharSequence title;
+    field public int titleRes;
+  }
+
+  public class PreferenceCategory extends android.preference.PreferenceGroup {
+    ctor public PreferenceCategory(android.content.Context, android.util.AttributeSet, int);
+    ctor public PreferenceCategory(android.content.Context, android.util.AttributeSet);
+    ctor public PreferenceCategory(android.content.Context);
+  }
+
+  public abstract class PreferenceFragment extends android.app.Fragment {
+    ctor public PreferenceFragment();
+    method public void addPreferencesFromIntent(android.content.Intent);
+    method public void addPreferencesFromResource(int);
+    method public android.preference.Preference findPreference(java.lang.CharSequence);
+    method public android.preference.PreferenceManager getPreferenceManager();
+    method public android.preference.PreferenceScreen getPreferenceScreen();
+    method public boolean onPreferenceTreeClick(android.preference.PreferenceScreen, android.preference.Preference);
+    method public void setPreferenceScreen(android.preference.PreferenceScreen);
+  }
+
+  public static abstract interface PreferenceFragment.OnPreferenceStartFragmentCallback {
+    method public abstract boolean onPreferenceStartFragment(android.preference.PreferenceFragment, android.preference.Preference);
+  }
+
+  public abstract class PreferenceGroup extends android.preference.Preference {
+    ctor public PreferenceGroup(android.content.Context, android.util.AttributeSet, int);
+    ctor public PreferenceGroup(android.content.Context, android.util.AttributeSet);
+    method public void addItemFromInflater(android.preference.Preference);
+    method public boolean addPreference(android.preference.Preference);
+    method protected void dispatchRestoreInstanceState(android.os.Bundle);
+    method protected void dispatchSaveInstanceState(android.os.Bundle);
+    method public android.preference.Preference findPreference(java.lang.CharSequence);
+    method public android.preference.Preference getPreference(int);
+    method public int getPreferenceCount();
+    method protected boolean isOnSameScreenAsChildren();
+    method public boolean isOrderingAsAdded();
+    method protected boolean onPrepareAddPreference(android.preference.Preference);
+    method public void removeAll();
+    method public boolean removePreference(android.preference.Preference);
+    method public void setOrderingAsAdded(boolean);
+  }
+
+  public class PreferenceManager {
+    method public android.preference.PreferenceScreen createPreferenceScreen(android.content.Context);
+    method public android.preference.Preference findPreference(java.lang.CharSequence);
+    method public static android.content.SharedPreferences getDefaultSharedPreferences(android.content.Context);
+    method public android.content.SharedPreferences getSharedPreferences();
+    method public int getSharedPreferencesMode();
+    method public java.lang.String getSharedPreferencesName();
+    method public static void setDefaultValues(android.content.Context, int, boolean);
+    method public static void setDefaultValues(android.content.Context, java.lang.String, int, int, boolean);
+    method public void setSharedPreferencesMode(int);
+    method public void setSharedPreferencesName(java.lang.String);
+    field public static final java.lang.String KEY_HAS_SET_DEFAULT_VALUES = "_has_set_default_values";
+    field public static final java.lang.String METADATA_KEY_PREFERENCES = "android.preference";
+  }
+
+  public static abstract interface PreferenceManager.OnActivityDestroyListener {
+    method public abstract void onActivityDestroy();
+  }
+
+  public static abstract interface PreferenceManager.OnActivityResultListener {
+    method public abstract boolean onActivityResult(int, int, android.content.Intent);
+  }
+
+  public static abstract interface PreferenceManager.OnActivityStopListener {
+    method public abstract void onActivityStop();
+  }
+
+  public final class PreferenceScreen extends android.preference.PreferenceGroup implements android.widget.AdapterView.OnItemClickListener android.content.DialogInterface.OnDismissListener {
+    method public void bind(android.widget.ListView);
+    method public android.app.Dialog getDialog();
+    method public android.widget.ListAdapter getRootAdapter();
+    method protected android.widget.ListAdapter onCreateRootAdapter();
+    method public void onDismiss(android.content.DialogInterface);
+    method public void onItemClick(android.widget.AdapterView, android.view.View, int, long);
+  }
+
+  public class RingtonePreference extends android.preference.Preference implements android.preference.PreferenceManager.OnActivityResultListener {
+    ctor public RingtonePreference(android.content.Context, android.util.AttributeSet, int);
+    ctor public RingtonePreference(android.content.Context, android.util.AttributeSet);
+    ctor public RingtonePreference(android.content.Context);
+    method public int getRingtoneType();
+    method public boolean getShowDefault();
+    method public boolean getShowSilent();
+    method public boolean onActivityResult(int, int, android.content.Intent);
+    method protected void onPrepareRingtonePickerIntent(android.content.Intent);
+    method protected android.net.Uri onRestoreRingtone();
+    method protected void onSaveRingtone(android.net.Uri);
+    method public void setRingtoneType(int);
+    method public void setShowDefault(boolean);
+    method public void setShowSilent(boolean);
+  }
+
+  public class SwitchPreference extends android.preference.TwoStatePreference {
+    ctor public SwitchPreference(android.content.Context, android.util.AttributeSet, int);
+    ctor public SwitchPreference(android.content.Context, android.util.AttributeSet);
+    ctor public SwitchPreference(android.content.Context);
+    method public java.lang.CharSequence getSwitchTextOff();
+    method public java.lang.CharSequence getSwitchTextOn();
+    method public void setSwitchTextOff(java.lang.CharSequence);
+    method public void setSwitchTextOff(int);
+    method public void setSwitchTextOn(java.lang.CharSequence);
+    method public void setSwitchTextOn(int);
+  }
+
+  public abstract class TwoStatePreference extends android.preference.Preference {
+    ctor public TwoStatePreference(android.content.Context, android.util.AttributeSet, int);
+    ctor public TwoStatePreference(android.content.Context, android.util.AttributeSet);
+    ctor public TwoStatePreference(android.content.Context);
+    method public boolean getDisableDependentsState();
+    method public java.lang.CharSequence getSummaryOff();
+    method public java.lang.CharSequence getSummaryOn();
+    method public boolean isChecked();
+    method public void setChecked(boolean);
+    method public void setDisableDependentsState(boolean);
+    method public void setSummaryOff(java.lang.CharSequence);
+    method public void setSummaryOff(int);
+    method public void setSummaryOn(java.lang.CharSequence);
+    method public void setSummaryOn(int);
+  }
+
+}
+
+package android.provider {
+
+  public final class AlarmClock {
+    ctor public AlarmClock();
+    field public static final java.lang.String ACTION_SET_ALARM = "android.intent.action.SET_ALARM";
+    field public static final java.lang.String EXTRA_HOUR = "android.intent.extra.alarm.HOUR";
+    field public static final java.lang.String EXTRA_MESSAGE = "android.intent.extra.alarm.MESSAGE";
+    field public static final java.lang.String EXTRA_MINUTES = "android.intent.extra.alarm.MINUTES";
+    field public static final java.lang.String EXTRA_SKIP_UI = "android.intent.extra.alarm.SKIP_UI";
+  }
+
+  public abstract interface BaseColumns {
+    field public static final java.lang.String _COUNT = "_count";
+    field public static final java.lang.String _ID = "_id";
+  }
+
+  public class Browser {
+    ctor public Browser();
+    method public static final void addSearchUrl(android.content.ContentResolver, java.lang.String);
+    method public static final boolean canClearHistory(android.content.ContentResolver);
+    method public static final void clearHistory(android.content.ContentResolver);
+    method public static final void clearSearches(android.content.ContentResolver);
+    method public static final void deleteFromHistory(android.content.ContentResolver, java.lang.String);
+    method public static final void deleteHistoryTimeFrame(android.content.ContentResolver, long, long);
+    method public static final android.database.Cursor getAllBookmarks(android.content.ContentResolver) throws java.lang.IllegalStateException;
+    method public static final android.database.Cursor getAllVisitedUrls(android.content.ContentResolver) throws java.lang.IllegalStateException;
+    method public static final void requestAllIcons(android.content.ContentResolver, java.lang.String, android.webkit.WebIconDatabase.IconListener);
+    method public static final void saveBookmark(android.content.Context, java.lang.String, java.lang.String);
+    method public static final void sendString(android.content.Context, java.lang.String);
+    method public static final void truncateHistory(android.content.ContentResolver);
+    method public static final void updateVisitedHistory(android.content.ContentResolver, java.lang.String, boolean);
+    field public static final android.net.Uri BOOKMARKS_URI;
+    field public static final java.lang.String EXTRA_APPLICATION_ID = "com.android.browser.application_id";
+    field public static final java.lang.String EXTRA_CREATE_NEW_TAB = "create_new_tab";
+    field public static final java.lang.String EXTRA_HEADERS = "com.android.browser.headers";
+    field public static final java.lang.String[] HISTORY_PROJECTION;
+    field public static final int HISTORY_PROJECTION_BOOKMARK_INDEX = 4; // 0x4
+    field public static final int HISTORY_PROJECTION_DATE_INDEX = 3; // 0x3
+    field public static final int HISTORY_PROJECTION_FAVICON_INDEX = 6; // 0x6
+    field public static final int HISTORY_PROJECTION_ID_INDEX = 0; // 0x0
+    field public static final int HISTORY_PROJECTION_TITLE_INDEX = 5; // 0x5
+    field public static final int HISTORY_PROJECTION_URL_INDEX = 1; // 0x1
+    field public static final int HISTORY_PROJECTION_VISITS_INDEX = 2; // 0x2
+    field public static final java.lang.String INITIAL_ZOOM_LEVEL = "browser.initialZoomLevel";
+    field public static final java.lang.String[] SEARCHES_PROJECTION;
+    field public static final int SEARCHES_PROJECTION_DATE_INDEX = 2; // 0x2
+    field public static final int SEARCHES_PROJECTION_SEARCH_INDEX = 1; // 0x1
+    field public static final android.net.Uri SEARCHES_URI;
+    field public static final java.lang.String[] TRUNCATE_HISTORY_PROJECTION;
+    field public static final int TRUNCATE_HISTORY_PROJECTION_ID_INDEX = 0; // 0x0
+    field public static final int TRUNCATE_N_OLDEST = 5; // 0x5
+  }
+
+  public static class Browser.BookmarkColumns implements android.provider.BaseColumns {
+    ctor public Browser.BookmarkColumns();
+    field public static final java.lang.String BOOKMARK = "bookmark";
+    field public static final java.lang.String CREATED = "created";
+    field public static final java.lang.String DATE = "date";
+    field public static final java.lang.String FAVICON = "favicon";
+    field public static final java.lang.String TITLE = "title";
+    field public static final java.lang.String URL = "url";
+    field public static final java.lang.String VISITS = "visits";
+  }
+
+  public static class Browser.SearchColumns implements android.provider.BaseColumns {
+    ctor public Browser.SearchColumns();
+    field public static final java.lang.String DATE = "date";
+    field public static final java.lang.String SEARCH = "search";
+    field public static final deprecated java.lang.String URL = "url";
+  }
+
+  public final class CalendarContract {
+    field public static final java.lang.String ACCOUNT_TYPE_LOCAL = "LOCAL";
+    field public static final java.lang.String ACTION_EVENT_REMINDER = "android.intent.action.EVENT_REMINDER";
+    field public static final java.lang.String ACTION_HANDLE_CUSTOM_EVENT = "android.provider.calendar.action.HANDLE_CUSTOM_EVENT";
+    field public static final java.lang.String AUTHORITY = "com.android.calendar";
+    field public static final java.lang.String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String EXTRA_CUSTOM_APP_URI = "customAppUri";
+    field public static final java.lang.String EXTRA_EVENT_ALL_DAY = "allDay";
+    field public static final java.lang.String EXTRA_EVENT_BEGIN_TIME = "beginTime";
+    field public static final java.lang.String EXTRA_EVENT_END_TIME = "endTime";
+  }
+
+  public static final class CalendarContract.Attendees implements android.provider.BaseColumns android.provider.CalendarContract.AttendeesColumns android.provider.CalendarContract.EventsColumns {
+    method public static final android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]);
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.AttendeesColumns {
+    field public static final java.lang.String ATTENDEE_EMAIL = "attendeeEmail";
+    field public static final java.lang.String ATTENDEE_IDENTITY = "attendeeIdentity";
+    field public static final java.lang.String ATTENDEE_ID_NAMESPACE = "attendeeIdNamespace";
+    field public static final java.lang.String ATTENDEE_NAME = "attendeeName";
+    field public static final java.lang.String ATTENDEE_RELATIONSHIP = "attendeeRelationship";
+    field public static final java.lang.String ATTENDEE_STATUS = "attendeeStatus";
+    field public static final int ATTENDEE_STATUS_ACCEPTED = 1; // 0x1
+    field public static final int ATTENDEE_STATUS_DECLINED = 2; // 0x2
+    field public static final int ATTENDEE_STATUS_INVITED = 3; // 0x3
+    field public static final int ATTENDEE_STATUS_NONE = 0; // 0x0
+    field public static final int ATTENDEE_STATUS_TENTATIVE = 4; // 0x4
+    field public static final java.lang.String ATTENDEE_TYPE = "attendeeType";
+    field public static final java.lang.String EVENT_ID = "event_id";
+    field public static final int RELATIONSHIP_ATTENDEE = 1; // 0x1
+    field public static final int RELATIONSHIP_NONE = 0; // 0x0
+    field public static final int RELATIONSHIP_ORGANIZER = 2; // 0x2
+    field public static final int RELATIONSHIP_PERFORMER = 3; // 0x3
+    field public static final int RELATIONSHIP_SPEAKER = 4; // 0x4
+    field public static final int TYPE_NONE = 0; // 0x0
+    field public static final int TYPE_OPTIONAL = 2; // 0x2
+    field public static final int TYPE_REQUIRED = 1; // 0x1
+    field public static final int TYPE_RESOURCE = 3; // 0x3
+  }
+
+  public static final class CalendarContract.CalendarAlerts implements android.provider.BaseColumns android.provider.CalendarContract.CalendarAlertsColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.EventsColumns {
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final android.net.Uri CONTENT_URI_BY_INSTANCE;
+  }
+
+  protected static abstract interface CalendarContract.CalendarAlertsColumns {
+    field public static final java.lang.String ALARM_TIME = "alarmTime";
+    field public static final java.lang.String BEGIN = "begin";
+    field public static final java.lang.String CREATION_TIME = "creationTime";
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "begin ASC,title ASC";
+    field public static final java.lang.String END = "end";
+    field public static final java.lang.String EVENT_ID = "event_id";
+    field public static final java.lang.String MINUTES = "minutes";
+    field public static final java.lang.String NOTIFY_TIME = "notifyTime";
+    field public static final java.lang.String RECEIVED_TIME = "receivedTime";
+    field public static final java.lang.String STATE = "state";
+    field public static final int STATE_DISMISSED = 2; // 0x2
+    field public static final int STATE_FIRED = 1; // 0x1
+    field public static final int STATE_SCHEDULED = 0; // 0x0
+  }
+
+  public static final class CalendarContract.CalendarCache implements android.provider.CalendarContract.CalendarCacheColumns {
+    field public static final java.lang.String KEY_TIMEZONE_INSTANCES = "timezoneInstances";
+    field public static final java.lang.String KEY_TIMEZONE_INSTANCES_PREVIOUS = "timezoneInstancesPrevious";
+    field public static final java.lang.String KEY_TIMEZONE_TYPE = "timezoneType";
+    field public static final java.lang.String TIMEZONE_TYPE_AUTO = "auto";
+    field public static final java.lang.String TIMEZONE_TYPE_HOME = "home";
+    field public static final android.net.Uri URI;
+  }
+
+  protected static abstract interface CalendarContract.CalendarCacheColumns {
+    field public static final java.lang.String KEY = "key";
+    field public static final java.lang.String VALUE = "value";
+  }
+
+  protected static abstract interface CalendarContract.CalendarColumns {
+    field public static final java.lang.String ALLOWED_ATTENDEE_TYPES = "allowedAttendeeTypes";
+    field public static final java.lang.String ALLOWED_AVAILABILITY = "allowedAvailability";
+    field public static final java.lang.String ALLOWED_REMINDERS = "allowedReminders";
+    field public static final java.lang.String CALENDAR_ACCESS_LEVEL = "calendar_access_level";
+    field public static final java.lang.String CALENDAR_COLOR = "calendar_color";
+    field public static final java.lang.String CALENDAR_COLOR_KEY = "calendar_color_index";
+    field public static final java.lang.String CALENDAR_DISPLAY_NAME = "calendar_displayName";
+    field public static final java.lang.String CALENDAR_TIME_ZONE = "calendar_timezone";
+    field public static final int CAL_ACCESS_CONTRIBUTOR = 500; // 0x1f4
+    field public static final int CAL_ACCESS_EDITOR = 600; // 0x258
+    field public static final int CAL_ACCESS_FREEBUSY = 100; // 0x64
+    field public static final int CAL_ACCESS_NONE = 0; // 0x0
+    field public static final int CAL_ACCESS_OVERRIDE = 400; // 0x190
+    field public static final int CAL_ACCESS_OWNER = 700; // 0x2bc
+    field public static final int CAL_ACCESS_READ = 200; // 0xc8
+    field public static final int CAL_ACCESS_RESPOND = 300; // 0x12c
+    field public static final int CAL_ACCESS_ROOT = 800; // 0x320
+    field public static final java.lang.String CAN_MODIFY_TIME_ZONE = "canModifyTimeZone";
+    field public static final java.lang.String CAN_ORGANIZER_RESPOND = "canOrganizerRespond";
+    field public static final java.lang.String IS_PRIMARY = "isPrimary";
+    field public static final java.lang.String MAX_REMINDERS = "maxReminders";
+    field public static final java.lang.String OWNER_ACCOUNT = "ownerAccount";
+    field public static final java.lang.String SYNC_EVENTS = "sync_events";
+    field public static final java.lang.String VISIBLE = "visible";
+  }
+
+  public static final class CalendarContract.CalendarEntity implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.SyncColumns {
+    method public static android.content.EntityIterator newEntityIterator(android.database.Cursor);
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.CalendarSyncColumns {
+    field public static final java.lang.String CAL_SYNC1 = "cal_sync1";
+    field public static final java.lang.String CAL_SYNC10 = "cal_sync10";
+    field public static final java.lang.String CAL_SYNC2 = "cal_sync2";
+    field public static final java.lang.String CAL_SYNC3 = "cal_sync3";
+    field public static final java.lang.String CAL_SYNC4 = "cal_sync4";
+    field public static final java.lang.String CAL_SYNC5 = "cal_sync5";
+    field public static final java.lang.String CAL_SYNC6 = "cal_sync6";
+    field public static final java.lang.String CAL_SYNC7 = "cal_sync7";
+    field public static final java.lang.String CAL_SYNC8 = "cal_sync8";
+    field public static final java.lang.String CAL_SYNC9 = "cal_sync9";
+  }
+
+  public static final class CalendarContract.Calendars implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.SyncColumns {
+    field public static final java.lang.String CALENDAR_LOCATION = "calendar_location";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "calendar_displayName";
+    field public static final java.lang.String NAME = "name";
+  }
+
+  public static final class CalendarContract.Colors implements android.provider.CalendarContract.ColorsColumns {
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.ColorsColumns implements android.provider.SyncStateContract.Columns {
+    field public static final java.lang.String COLOR = "color";
+    field public static final java.lang.String COLOR_KEY = "color_index";
+    field public static final java.lang.String COLOR_TYPE = "color_type";
+    field public static final int TYPE_CALENDAR = 0; // 0x0
+    field public static final int TYPE_EVENT = 1; // 0x1
+  }
+
+  public static final class CalendarContract.EventDays implements android.provider.CalendarContract.EventDaysColumns {
+    method public static final android.database.Cursor query(android.content.ContentResolver, int, int, java.lang.String[]);
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.EventDaysColumns {
+    field public static final java.lang.String ENDDAY = "endDay";
+    field public static final java.lang.String STARTDAY = "startDay";
+  }
+
+  public static final class CalendarContract.Events implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.SyncColumns {
+    field public static final android.net.Uri CONTENT_EXCEPTION_URI;
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.EventsColumns {
+    field public static final int ACCESS_CONFIDENTIAL = 1; // 0x1
+    field public static final int ACCESS_DEFAULT = 0; // 0x0
+    field public static final java.lang.String ACCESS_LEVEL = "accessLevel";
+    field public static final int ACCESS_PRIVATE = 2; // 0x2
+    field public static final int ACCESS_PUBLIC = 3; // 0x3
+    field public static final java.lang.String ALL_DAY = "allDay";
+    field public static final java.lang.String AVAILABILITY = "availability";
+    field public static final int AVAILABILITY_BUSY = 0; // 0x0
+    field public static final int AVAILABILITY_FREE = 1; // 0x1
+    field public static final int AVAILABILITY_TENTATIVE = 2; // 0x2
+    field public static final java.lang.String CALENDAR_ID = "calendar_id";
+    field public static final java.lang.String CAN_INVITE_OTHERS = "canInviteOthers";
+    field public static final java.lang.String CUSTOM_APP_PACKAGE = "customAppPackage";
+    field public static final java.lang.String CUSTOM_APP_URI = "customAppUri";
+    field public static final java.lang.String DESCRIPTION = "description";
+    field public static final java.lang.String DISPLAY_COLOR = "displayColor";
+    field public static final java.lang.String DTEND = "dtend";
+    field public static final java.lang.String DTSTART = "dtstart";
+    field public static final java.lang.String DURATION = "duration";
+    field public static final java.lang.String EVENT_COLOR = "eventColor";
+    field public static final java.lang.String EVENT_COLOR_KEY = "eventColor_index";
+    field public static final java.lang.String EVENT_END_TIMEZONE = "eventEndTimezone";
+    field public static final java.lang.String EVENT_LOCATION = "eventLocation";
+    field public static final java.lang.String EVENT_TIMEZONE = "eventTimezone";
+    field public static final java.lang.String EXDATE = "exdate";
+    field public static final java.lang.String EXRULE = "exrule";
+    field public static final java.lang.String GUESTS_CAN_INVITE_OTHERS = "guestsCanInviteOthers";
+    field public static final java.lang.String GUESTS_CAN_MODIFY = "guestsCanModify";
+    field public static final java.lang.String GUESTS_CAN_SEE_GUESTS = "guestsCanSeeGuests";
+    field public static final java.lang.String HAS_ALARM = "hasAlarm";
+    field public static final java.lang.String HAS_ATTENDEE_DATA = "hasAttendeeData";
+    field public static final java.lang.String HAS_EXTENDED_PROPERTIES = "hasExtendedProperties";
+    field public static final java.lang.String IS_ORGANIZER = "isOrganizer";
+    field public static final java.lang.String LAST_DATE = "lastDate";
+    field public static final java.lang.String LAST_SYNCED = "lastSynced";
+    field public static final java.lang.String ORGANIZER = "organizer";
+    field public static final java.lang.String ORIGINAL_ALL_DAY = "originalAllDay";
+    field public static final java.lang.String ORIGINAL_ID = "original_id";
+    field public static final java.lang.String ORIGINAL_INSTANCE_TIME = "originalInstanceTime";
+    field public static final java.lang.String ORIGINAL_SYNC_ID = "original_sync_id";
+    field public static final java.lang.String RDATE = "rdate";
+    field public static final java.lang.String RRULE = "rrule";
+    field public static final java.lang.String SELF_ATTENDEE_STATUS = "selfAttendeeStatus";
+    field public static final java.lang.String STATUS = "eventStatus";
+    field public static final int STATUS_CANCELED = 2; // 0x2
+    field public static final int STATUS_CONFIRMED = 1; // 0x1
+    field public static final int STATUS_TENTATIVE = 0; // 0x0
+    field public static final java.lang.String SYNC_DATA1 = "sync_data1";
+    field public static final java.lang.String SYNC_DATA10 = "sync_data10";
+    field public static final java.lang.String SYNC_DATA2 = "sync_data2";
+    field public static final java.lang.String SYNC_DATA3 = "sync_data3";
+    field public static final java.lang.String SYNC_DATA4 = "sync_data4";
+    field public static final java.lang.String SYNC_DATA5 = "sync_data5";
+    field public static final java.lang.String SYNC_DATA6 = "sync_data6";
+    field public static final java.lang.String SYNC_DATA7 = "sync_data7";
+    field public static final java.lang.String SYNC_DATA8 = "sync_data8";
+    field public static final java.lang.String SYNC_DATA9 = "sync_data9";
+    field public static final java.lang.String TITLE = "title";
+    field public static final java.lang.String UID_2445 = "uid2445";
+  }
+
+  public static final class CalendarContract.EventsEntity implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.SyncColumns {
+    method public static android.content.EntityIterator newEntityIterator(android.database.Cursor, android.content.ContentResolver);
+    method public static android.content.EntityIterator newEntityIterator(android.database.Cursor, android.content.ContentProviderClient);
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  public static final class CalendarContract.ExtendedProperties implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.ExtendedPropertiesColumns {
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.ExtendedPropertiesColumns {
+    field public static final java.lang.String EVENT_ID = "event_id";
+    field public static final java.lang.String NAME = "name";
+    field public static final java.lang.String VALUE = "value";
+  }
+
+  public static final class CalendarContract.Instances implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.EventsColumns {
+    method public static final android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long);
+    method public static final android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long, java.lang.String);
+    field public static final java.lang.String BEGIN = "begin";
+    field public static final android.net.Uri CONTENT_BY_DAY_URI;
+    field public static final android.net.Uri CONTENT_SEARCH_BY_DAY_URI;
+    field public static final android.net.Uri CONTENT_SEARCH_URI;
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String END = "end";
+    field public static final java.lang.String END_DAY = "endDay";
+    field public static final java.lang.String END_MINUTE = "endMinute";
+    field public static final java.lang.String EVENT_ID = "event_id";
+    field public static final java.lang.String START_DAY = "startDay";
+    field public static final java.lang.String START_MINUTE = "startMinute";
+  }
+
+  public static final class CalendarContract.Reminders implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.RemindersColumns {
+    method public static final android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]);
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.RemindersColumns {
+    field public static final java.lang.String EVENT_ID = "event_id";
+    field public static final java.lang.String METHOD = "method";
+    field public static final int METHOD_ALARM = 4; // 0x4
+    field public static final int METHOD_ALERT = 1; // 0x1
+    field public static final int METHOD_DEFAULT = 0; // 0x0
+    field public static final int METHOD_EMAIL = 2; // 0x2
+    field public static final int METHOD_SMS = 3; // 0x3
+    field public static final java.lang.String MINUTES = "minutes";
+    field public static final int MINUTES_DEFAULT = -1; // 0xffffffff
+  }
+
+  protected static abstract interface CalendarContract.SyncColumns implements android.provider.CalendarContract.CalendarSyncColumns {
+    field public static final java.lang.String ACCOUNT_NAME = "account_name";
+    field public static final java.lang.String ACCOUNT_TYPE = "account_type";
+    field public static final java.lang.String CAN_PARTIALLY_UPDATE = "canPartiallyUpdate";
+    field public static final java.lang.String DELETED = "deleted";
+    field public static final java.lang.String DIRTY = "dirty";
+    field public static final java.lang.String _SYNC_ID = "_sync_id";
+  }
+
+  public static final class CalendarContract.SyncState implements android.provider.SyncStateContract.Columns {
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  public class CallLog {
+    ctor public CallLog();
+    field public static final java.lang.String AUTHORITY = "call_log";
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  public static class CallLog.Calls implements android.provider.BaseColumns {
+    ctor public CallLog.Calls();
+    method public static java.lang.String getLastOutgoingCall(android.content.Context);
+    field public static final java.lang.String CACHED_NAME = "name";
+    field public static final java.lang.String CACHED_NUMBER_LABEL = "numberlabel";
+    field public static final java.lang.String CACHED_NUMBER_TYPE = "numbertype";
+    field public static final android.net.Uri CONTENT_FILTER_URI;
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/calls";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/calls";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DATE = "date";
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "date DESC";
+    field public static final java.lang.String DURATION = "duration";
+    field public static final int INCOMING_TYPE = 1; // 0x1
+    field public static final java.lang.String IS_READ = "is_read";
+    field public static final java.lang.String LIMIT_PARAM_KEY = "limit";
+    field public static final int MISSED_TYPE = 3; // 0x3
+    field public static final java.lang.String NEW = "new";
+    field public static final java.lang.String NUMBER = "number";
+    field public static final java.lang.String OFFSET_PARAM_KEY = "offset";
+    field public static final int OUTGOING_TYPE = 2; // 0x2
+    field public static final java.lang.String TYPE = "type";
+  }
+
+  public deprecated class Contacts {
+    field public static final deprecated java.lang.String AUTHORITY = "contacts";
+    field public static final deprecated android.net.Uri CONTENT_URI;
+    field public static final deprecated int KIND_EMAIL = 1; // 0x1
+    field public static final deprecated int KIND_IM = 3; // 0x3
+    field public static final deprecated int KIND_ORGANIZATION = 4; // 0x4
+    field public static final deprecated int KIND_PHONE = 5; // 0x5
+    field public static final deprecated int KIND_POSTAL = 2; // 0x2
+  }
+
+  public static final deprecated class Contacts.ContactMethods implements android.provider.BaseColumns android.provider.Contacts.ContactMethodsColumns android.provider.Contacts.PeopleColumns {
+    method public deprecated void addPostalLocation(android.content.Context, long, double, double);
+    method public static deprecated java.lang.Object decodeImProtocol(java.lang.String);
+    method public static deprecated java.lang.String encodeCustomImProtocol(java.lang.String);
+    method public static deprecated java.lang.String encodePredefinedImProtocol(int);
+    method public static final deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, int, java.lang.CharSequence);
+    field public static final deprecated java.lang.String CONTENT_EMAIL_ITEM_TYPE = "vnd.android.cursor.item/email";
+    field public static final deprecated java.lang.String CONTENT_EMAIL_TYPE = "vnd.android.cursor.dir/email";
+    field public static final deprecated android.net.Uri CONTENT_EMAIL_URI;
+    field public static final deprecated java.lang.String CONTENT_IM_ITEM_TYPE = "vnd.android.cursor.item/jabber-im";
+    field public static final deprecated java.lang.String CONTENT_POSTAL_ITEM_TYPE = "vnd.android.cursor.item/postal-address";
+    field public static final deprecated java.lang.String CONTENT_POSTAL_TYPE = "vnd.android.cursor.dir/postal-address";
+    field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/contact-methods";
+    field public static final deprecated android.net.Uri CONTENT_URI;
+    field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "name ASC";
+    field public static final deprecated java.lang.String PERSON_ID = "person";
+    field public static final deprecated java.lang.String POSTAL_LOCATION_LATITUDE = "data";
+    field public static final deprecated java.lang.String POSTAL_LOCATION_LONGITUDE = "aux_data";
+    field public static final deprecated int PROTOCOL_AIM = 0; // 0x0
+    field public static final deprecated int PROTOCOL_GOOGLE_TALK = 5; // 0x5
+    field public static final deprecated int PROTOCOL_ICQ = 6; // 0x6
+    field public static final deprecated int PROTOCOL_JABBER = 7; // 0x7
+    field public static final deprecated int PROTOCOL_MSN = 1; // 0x1
+    field public static final deprecated int PROTOCOL_QQ = 4; // 0x4
+    field public static final deprecated int PROTOCOL_SKYPE = 3; // 0x3
+    field public static final deprecated int PROTOCOL_YAHOO = 2; // 0x2
+  }
+
+  public static abstract deprecated interface Contacts.ContactMethodsColumns {
+    field public static final deprecated java.lang.String AUX_DATA = "aux_data";
+    field public static final deprecated java.lang.String DATA = "data";
+    field public static final deprecated java.lang.String ISPRIMARY = "isprimary";
+    field public static final deprecated java.lang.String KIND = "kind";
+    field public static final deprecated java.lang.String LABEL = "label";
+    field public static final deprecated java.lang.String TYPE = "type";
+    field public static final deprecated int TYPE_CUSTOM = 0; // 0x0
+    field public static final deprecated int TYPE_HOME = 1; // 0x1
+    field public static final deprecated int TYPE_OTHER = 3; // 0x3
+    field public static final deprecated int TYPE_WORK = 2; // 0x2
+  }
+
+  public static final deprecated class Contacts.Extensions implements android.provider.BaseColumns android.provider.Contacts.ExtensionsColumns {
+    field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_extensions";
+    field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/contact_extensions";
+    field public static final deprecated android.net.Uri CONTENT_URI;
+    field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "person, name ASC";
+    field public static final deprecated java.lang.String PERSON_ID = "person";
+  }
+
+  public static abstract deprecated interface Contacts.ExtensionsColumns {
+    field public static final deprecated java.lang.String NAME = "name";
+    field public static final deprecated java.lang.String VALUE = "value";
+  }
+
+  public static final deprecated class Contacts.GroupMembership implements android.provider.BaseColumns android.provider.Contacts.GroupsColumns {
+    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "groupmembership";
+    field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contactsgroupmembership";
+    field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/contactsgroupmembership";
+    field public static final deprecated android.net.Uri CONTENT_URI;
+    field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "group_id ASC";
+    field public static final deprecated java.lang.String GROUP_ID = "group_id";
+    field public static final deprecated java.lang.String GROUP_SYNC_ACCOUNT = "group_sync_account";
+    field public static final deprecated java.lang.String GROUP_SYNC_ACCOUNT_TYPE = "group_sync_account_type";
+    field public static final deprecated java.lang.String GROUP_SYNC_ID = "group_sync_id";
+    field public static final deprecated java.lang.String PERSON_ID = "person";
+    field public static final deprecated android.net.Uri RAW_CONTENT_URI;
+  }
+
+  public static final deprecated class Contacts.Groups implements android.provider.BaseColumns android.provider.Contacts.GroupsColumns {
+    field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contactsgroup";
+    field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/contactsgroup";
+    field public static final deprecated android.net.Uri CONTENT_URI;
+    field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "name ASC";
+    field public static final deprecated android.net.Uri DELETED_CONTENT_URI;
+    field public static final deprecated java.lang.String GROUP_ANDROID_STARRED = "Starred in Android";
+    field public static final deprecated java.lang.String GROUP_MY_CONTACTS = "Contacts";
+  }
+
+  public static abstract deprecated interface Contacts.GroupsColumns {
+    field public static final deprecated java.lang.String NAME = "name";
+    field public static final deprecated java.lang.String NOTES = "notes";
+    field public static final deprecated java.lang.String SHOULD_SYNC = "should_sync";
+    field public static final deprecated java.lang.String SYSTEM_ID = "system_id";
+  }
+
+  public static final deprecated class Contacts.Intents {
+    ctor public deprecated Contacts.Intents();
+    field public static final deprecated java.lang.String ATTACH_IMAGE = "com.android.contacts.action.ATTACH_IMAGE";
+    field public static final deprecated java.lang.String EXTRA_CREATE_DESCRIPTION = "com.android.contacts.action.CREATE_DESCRIPTION";
+    field public static final deprecated java.lang.String EXTRA_FORCE_CREATE = "com.android.contacts.action.FORCE_CREATE";
+    field public static final deprecated java.lang.String SEARCH_SUGGESTION_CLICKED = "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED";
+    field public static final deprecated java.lang.String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED = "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED";
+    field public static final deprecated java.lang.String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED = "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED";
+    field public static final deprecated java.lang.String SHOW_OR_CREATE_CONTACT = "com.android.contacts.action.SHOW_OR_CREATE_CONTACT";
+  }
+
+  public static final deprecated class Contacts.Intents.Insert {
+    ctor public deprecated Contacts.Intents.Insert();
+    field public static final deprecated java.lang.String ACTION = "android.intent.action.INSERT";
+    field public static final deprecated java.lang.String COMPANY = "company";
+    field public static final deprecated java.lang.String EMAIL = "email";
+    field public static final deprecated java.lang.String EMAIL_ISPRIMARY = "email_isprimary";
+    field public static final deprecated java.lang.String EMAIL_TYPE = "email_type";
+    field public static final deprecated java.lang.String FULL_MODE = "full_mode";
+    field public static final deprecated java.lang.String IM_HANDLE = "im_handle";
+    field public static final deprecated java.lang.String IM_ISPRIMARY = "im_isprimary";
+    field public static final deprecated java.lang.String IM_PROTOCOL = "im_protocol";
+    field public static final deprecated java.lang.String JOB_TITLE = "job_title";
+    field public static final deprecated java.lang.String NAME = "name";
+    field public static final deprecated java.lang.String NOTES = "notes";
+    field public static final deprecated java.lang.String PHONE = "phone";
+    field public static final deprecated java.lang.String PHONETIC_NAME = "phonetic_name";
+    field public static final deprecated java.lang.String PHONE_ISPRIMARY = "phone_isprimary";
+    field public static final deprecated java.lang.String PHONE_TYPE = "phone_type";
+    field public static final deprecated java.lang.String POSTAL = "postal";
+    field public static final deprecated java.lang.String POSTAL_ISPRIMARY = "postal_isprimary";
+    field public static final deprecated java.lang.String POSTAL_TYPE = "postal_type";
+    field public static final deprecated java.lang.String SECONDARY_EMAIL = "secondary_email";
+    field public static final deprecated java.lang.String SECONDARY_EMAIL_TYPE = "secondary_email_type";
+    field public static final deprecated java.lang.String SECONDARY_PHONE = "secondary_phone";
+    field public static final deprecated java.lang.String SECONDARY_PHONE_TYPE = "secondary_phone_type";
+    field public static final deprecated java.lang.String TERTIARY_EMAIL = "tertiary_email";
+    field public static final deprecated java.lang.String TERTIARY_EMAIL_TYPE = "tertiary_email_type";
+    field public static final deprecated java.lang.String TERTIARY_PHONE = "tertiary_phone";
+    field public static final deprecated java.lang.String TERTIARY_PHONE_TYPE = "tertiary_phone_type";
+  }
+
+  public static final deprecated class Contacts.Intents.UI {
+    ctor public deprecated Contacts.Intents.UI();
+    field public static final deprecated java.lang.String FILTER_CONTACTS_ACTION = "com.android.contacts.action.FILTER_CONTACTS";
+    field public static final deprecated java.lang.String FILTER_TEXT_EXTRA_KEY = "com.android.contacts.extra.FILTER_TEXT";
+    field public static final deprecated java.lang.String GROUP_NAME_EXTRA_KEY = "com.android.contacts.extra.GROUP";
+    field public static final deprecated java.lang.String LIST_ALL_CONTACTS_ACTION = "com.android.contacts.action.LIST_ALL_CONTACTS";
+    field public static final deprecated java.lang.String LIST_CONTACTS_WITH_PHONES_ACTION = "com.android.contacts.action.LIST_CONTACTS_WITH_PHONES";
+    field public static final deprecated java.lang.String LIST_DEFAULT = "com.android.contacts.action.LIST_DEFAULT";
+    field public static final deprecated java.lang.String LIST_FREQUENT_ACTION = "com.android.contacts.action.LIST_FREQUENT";
+    field public static final deprecated java.lang.String LIST_GROUP_ACTION = "com.android.contacts.action.LIST_GROUP";
+    field public static final deprecated java.lang.String LIST_STARRED_ACTION = "com.android.contacts.action.LIST_STARRED";
+    field public static final deprecated java.lang.String LIST_STREQUENT_ACTION = "com.android.contacts.action.LIST_STREQUENT";
+    field public static final deprecated java.lang.String TITLE_EXTRA_KEY = "com.android.contacts.extra.TITLE_EXTRA";
+  }
+
+  public static abstract deprecated interface Contacts.OrganizationColumns {
+    field public static final deprecated java.lang.String COMPANY = "company";
+    field public static final deprecated java.lang.String ISPRIMARY = "isprimary";
+    field public static final deprecated java.lang.String LABEL = "label";
+    field public static final deprecated java.lang.String PERSON_ID = "person";
+    field public static final deprecated java.lang.String TITLE = "title";
+    field public static final deprecated java.lang.String TYPE = "type";
+    field public static final deprecated int TYPE_CUSTOM = 0; // 0x0
+    field public static final deprecated int TYPE_OTHER = 2; // 0x2
+    field public static final deprecated int TYPE_WORK = 1; // 0x1
+  }
+
+  public static final deprecated class Contacts.Organizations implements android.provider.BaseColumns android.provider.Contacts.OrganizationColumns {
+    method public static final deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence);
+    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "organizations";
+    field public static final deprecated android.net.Uri CONTENT_URI;
+    field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "company, title, isprimary ASC";
+  }
+
+  public static final deprecated class Contacts.People implements android.provider.BaseColumns android.provider.Contacts.PeopleColumns android.provider.Contacts.PhonesColumns android.provider.Contacts.PresenceColumns {
+    method public static deprecated android.net.Uri addToGroup(android.content.ContentResolver, long, java.lang.String);
+    method public static deprecated android.net.Uri addToGroup(android.content.ContentResolver, long, long);
+    method public static deprecated android.net.Uri addToMyContactsGroup(android.content.ContentResolver, long);
+    method public static deprecated android.net.Uri createPersonInMyContactsGroup(android.content.ContentResolver, android.content.ContentValues);
+    method public static deprecated android.graphics.Bitmap loadContactPhoto(android.content.Context, android.net.Uri, int, android.graphics.BitmapFactory.Options);
+    method public static deprecated void markAsContacted(android.content.ContentResolver, long);
+    method public static deprecated java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri);
+    method public static deprecated android.database.Cursor queryGroups(android.content.ContentResolver, long);
+    method public static deprecated void setPhotoData(android.content.ContentResolver, android.net.Uri, byte[]);
+    field public static final deprecated android.net.Uri CONTENT_FILTER_URI;
+    field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/person";
+    field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/person";
+    field public static final deprecated android.net.Uri CONTENT_URI;
+    field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "name ASC";
+    field public static final deprecated android.net.Uri DELETED_CONTENT_URI;
+    field public static final deprecated java.lang.String PRIMARY_EMAIL_ID = "primary_email";
+    field public static final deprecated java.lang.String PRIMARY_ORGANIZATION_ID = "primary_organization";
+    field public static final deprecated java.lang.String PRIMARY_PHONE_ID = "primary_phone";
+  }
+
+  public static final deprecated class Contacts.People.ContactMethods implements android.provider.BaseColumns android.provider.Contacts.ContactMethodsColumns android.provider.Contacts.PeopleColumns {
+    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "contact_methods";
+    field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "data ASC";
+  }
+
+  public static deprecated class Contacts.People.Extensions implements android.provider.BaseColumns android.provider.Contacts.ExtensionsColumns {
+    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "extensions";
+    field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "name ASC";
+    field public static final deprecated java.lang.String PERSON_ID = "person";
+  }
+
+  public static final deprecated class Contacts.People.Phones implements android.provider.BaseColumns android.provider.Contacts.PeopleColumns android.provider.Contacts.PhonesColumns {
+    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "phones";
+    field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "number ASC";
+  }
+
+  public static abstract deprecated interface Contacts.PeopleColumns {
+    field public static final deprecated java.lang.String CUSTOM_RINGTONE = "custom_ringtone";
+    field public static final deprecated java.lang.String DISPLAY_NAME = "display_name";
+    field public static final deprecated java.lang.String LAST_TIME_CONTACTED = "last_time_contacted";
+    field public static final deprecated java.lang.String NAME = "name";
+    field public static final deprecated java.lang.String NOTES = "notes";
+    field public static final deprecated java.lang.String PHONETIC_NAME = "phonetic_name";
+    field public static final deprecated java.lang.String PHOTO_VERSION = "photo_version";
+    field public static final deprecated java.lang.String SEND_TO_VOICEMAIL = "send_to_voicemail";
+    field public static final deprecated java.lang.String STARRED = "starred";
+    field public static final deprecated java.lang.String TIMES_CONTACTED = "times_contacted";
+  }
+
+  public static final deprecated class Contacts.Phones implements android.provider.BaseColumns android.provider.Contacts.PeopleColumns android.provider.Contacts.PhonesColumns {
+    method public static final deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence, java.lang.CharSequence[]);
+    method public static final deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence);
+    field public static final deprecated android.net.Uri CONTENT_FILTER_URL;
+    field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone";
+    field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/phone";
+    field public static final deprecated android.net.Uri CONTENT_URI;
+    field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "name ASC";
+    field public static final deprecated java.lang.String PERSON_ID = "person";
+  }
+
+  public static abstract deprecated interface Contacts.PhonesColumns {
+    field public static final deprecated java.lang.String ISPRIMARY = "isprimary";
+    field public static final deprecated java.lang.String LABEL = "label";
+    field public static final deprecated java.lang.String NUMBER = "number";
+    field public static final deprecated java.lang.String NUMBER_KEY = "number_key";
+    field public static final deprecated java.lang.String TYPE = "type";
+    field public static final deprecated int TYPE_CUSTOM = 0; // 0x0
+    field public static final deprecated int TYPE_FAX_HOME = 5; // 0x5
+    field public static final deprecated int TYPE_FAX_WORK = 4; // 0x4
+    field public static final deprecated int TYPE_HOME = 1; // 0x1
+    field public static final deprecated int TYPE_MOBILE = 2; // 0x2
+    field public static final deprecated int TYPE_OTHER = 7; // 0x7
+    field public static final deprecated int TYPE_PAGER = 6; // 0x6
+    field public static final deprecated int TYPE_WORK = 3; // 0x3
+  }
+
+  public static final deprecated class Contacts.Photos implements android.provider.BaseColumns android.provider.Contacts.PhotosColumns {
+    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "photo";
+    field public static final deprecated android.net.Uri CONTENT_URI;
+    field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "person ASC";
+  }
+
+  public static abstract deprecated interface Contacts.PhotosColumns {
+    field public static final deprecated java.lang.String DATA = "data";
+    field public static final deprecated java.lang.String DOWNLOAD_REQUIRED = "download_required";
+    field public static final deprecated java.lang.String EXISTS_ON_SERVER = "exists_on_server";
+    field public static final deprecated java.lang.String LOCAL_VERSION = "local_version";
+    field public static final deprecated java.lang.String PERSON_ID = "person";
+    field public static final deprecated java.lang.String SYNC_ERROR = "sync_error";
+  }
+
+  public static abstract deprecated interface Contacts.PresenceColumns {
+    field public static final int AVAILABLE = 5; // 0x5
+    field public static final int AWAY = 2; // 0x2
+    field public static final int DO_NOT_DISTURB = 4; // 0x4
+    field public static final int IDLE = 3; // 0x3
+    field public static final deprecated java.lang.String IM_ACCOUNT = "im_account";
+    field public static final deprecated java.lang.String IM_HANDLE = "im_handle";
+    field public static final deprecated java.lang.String IM_PROTOCOL = "im_protocol";
+    field public static final int INVISIBLE = 1; // 0x1
+    field public static final int OFFLINE = 0; // 0x0
+    field public static final java.lang.String PRESENCE_CUSTOM_STATUS = "status";
+    field public static final java.lang.String PRESENCE_STATUS = "mode";
+    field public static final java.lang.String PRIORITY = "priority";
+  }
+
+  public static final deprecated class Contacts.Settings implements android.provider.BaseColumns android.provider.Contacts.SettingsColumns {
+    method public static deprecated java.lang.String getSetting(android.content.ContentResolver, java.lang.String, java.lang.String);
+    method public static deprecated void setSetting(android.content.ContentResolver, java.lang.String, java.lang.String, java.lang.String);
+    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "settings";
+    field public static final deprecated android.net.Uri CONTENT_URI;
+    field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "key ASC";
+    field public static final deprecated java.lang.String SYNC_EVERYTHING = "syncEverything";
+  }
+
+  public static abstract deprecated interface Contacts.SettingsColumns {
+    field public static final deprecated java.lang.String KEY = "key";
+    field public static final deprecated java.lang.String VALUE = "value";
+    field public static final deprecated java.lang.String _SYNC_ACCOUNT = "_sync_account";
+    field public static final deprecated java.lang.String _SYNC_ACCOUNT_TYPE = "_sync_account_type";
+  }
+
+  public final class ContactsContract {
+    ctor public ContactsContract();
+    method public static boolean isProfileId(long);
+    field public static final java.lang.String AUTHORITY = "com.android.contacts";
+    field public static final android.net.Uri AUTHORITY_URI;
+    field public static final java.lang.String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
+    field public static final java.lang.String DIRECTORY_PARAM_KEY = "directory";
+    field public static final java.lang.String LIMIT_PARAM_KEY = "limit";
+    field public static final java.lang.String PRIMARY_ACCOUNT_NAME = "name_for_primary_account";
+    field public static final java.lang.String PRIMARY_ACCOUNT_TYPE = "type_for_primary_account";
+  }
+
+  public static final class ContactsContract.AggregationExceptions implements android.provider.BaseColumns {
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/aggregation_exception";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/aggregation_exception";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String RAW_CONTACT_ID1 = "raw_contact_id1";
+    field public static final java.lang.String RAW_CONTACT_ID2 = "raw_contact_id2";
+    field public static final java.lang.String TYPE = "type";
+    field public static final int TYPE_AUTOMATIC = 0; // 0x0
+    field public static final int TYPE_KEEP_SEPARATE = 2; // 0x2
+    field public static final int TYPE_KEEP_TOGETHER = 1; // 0x1
+  }
+
+  protected static abstract interface ContactsContract.BaseSyncColumns {
+    field public static final java.lang.String SYNC1 = "sync1";
+    field public static final java.lang.String SYNC2 = "sync2";
+    field public static final java.lang.String SYNC3 = "sync3";
+    field public static final java.lang.String SYNC4 = "sync4";
+  }
+
+  public static final class ContactsContract.CommonDataKinds {
+  }
+
+  public static abstract interface ContactsContract.CommonDataKinds.BaseTypes {
+    field public static final int TYPE_CUSTOM = 0; // 0x0
+  }
+
+  protected static abstract interface ContactsContract.CommonDataKinds.CommonColumns implements android.provider.ContactsContract.CommonDataKinds.BaseTypes {
+    field public static final java.lang.String DATA = "data1";
+    field public static final java.lang.String LABEL = "data3";
+    field public static final java.lang.String TYPE = "data2";
+  }
+
+  public static final class ContactsContract.CommonDataKinds.Email implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
+    method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+    method public static final int getTypeLabelResource(int);
+    field public static final java.lang.String ADDRESS = "data1";
+    field public static final android.net.Uri CONTENT_FILTER_URI;
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/email_v2";
+    field public static final android.net.Uri CONTENT_LOOKUP_URI;
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/email_v2";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DISPLAY_NAME = "data4";
+    field public static final int TYPE_HOME = 1; // 0x1
+    field public static final int TYPE_MOBILE = 4; // 0x4
+    field public static final int TYPE_OTHER = 3; // 0x3
+    field public static final int TYPE_WORK = 2; // 0x2
+  }
+
+  public static final class ContactsContract.CommonDataKinds.Event implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
+    method public static int getTypeResource(java.lang.Integer);
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_event";
+    field public static final java.lang.String START_DATE = "data1";
+    field public static final int TYPE_ANNIVERSARY = 1; // 0x1
+    field public static final int TYPE_BIRTHDAY = 3; // 0x3
+    field public static final int TYPE_OTHER = 2; // 0x2
+  }
+
+  public static final class ContactsContract.CommonDataKinds.GroupMembership implements android.provider.ContactsContract.DataColumnsWithJoins {
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/group_membership";
+    field public static final java.lang.String GROUP_ROW_ID = "data1";
+    field public static final java.lang.String GROUP_SOURCE_ID = "group_sourceid";
+  }
+
+  public static final class ContactsContract.CommonDataKinds.Identity implements android.provider.ContactsContract.DataColumnsWithJoins {
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/identity";
+    field public static final java.lang.String IDENTITY = "data1";
+    field public static final java.lang.String NAMESPACE = "data2";
+  }
+
+  public static final class ContactsContract.CommonDataKinds.Im implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
+    method public static final java.lang.CharSequence getProtocolLabel(android.content.res.Resources, int, java.lang.CharSequence);
+    method public static final int getProtocolLabelResource(int);
+    method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+    method public static final int getTypeLabelResource(int);
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im";
+    field public static final java.lang.String CUSTOM_PROTOCOL = "data6";
+    field public static final java.lang.String PROTOCOL = "data5";
+    field public static final int PROTOCOL_AIM = 0; // 0x0
+    field public static final int PROTOCOL_CUSTOM = -1; // 0xffffffff
+    field public static final int PROTOCOL_GOOGLE_TALK = 5; // 0x5
+    field public static final int PROTOCOL_ICQ = 6; // 0x6
+    field public static final int PROTOCOL_JABBER = 7; // 0x7
+    field public static final int PROTOCOL_MSN = 1; // 0x1
+    field public static final int PROTOCOL_NETMEETING = 8; // 0x8
+    field public static final int PROTOCOL_QQ = 4; // 0x4
+    field public static final int PROTOCOL_SKYPE = 3; // 0x3
+    field public static final int PROTOCOL_YAHOO = 2; // 0x2
+    field public static final int TYPE_HOME = 1; // 0x1
+    field public static final int TYPE_OTHER = 3; // 0x3
+    field public static final int TYPE_WORK = 2; // 0x2
+  }
+
+  public static final class ContactsContract.CommonDataKinds.Nickname implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/nickname";
+    field public static final java.lang.String NAME = "data1";
+    field public static final int TYPE_DEFAULT = 1; // 0x1
+    field public static final int TYPE_INITIALS = 5; // 0x5
+    field public static final int TYPE_MAIDEN_NAME = 3; // 0x3
+    field public static final deprecated int TYPE_MAINDEN_NAME = 3; // 0x3
+    field public static final int TYPE_OTHER_NAME = 2; // 0x2
+    field public static final int TYPE_SHORT_NAME = 4; // 0x4
+  }
+
+  public static final class ContactsContract.CommonDataKinds.Note implements android.provider.ContactsContract.DataColumnsWithJoins {
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/note";
+    field public static final java.lang.String NOTE = "data1";
+  }
+
+  public static final class ContactsContract.CommonDataKinds.Organization implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
+    method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+    method public static final int getTypeLabelResource(int);
+    field public static final java.lang.String COMPANY = "data1";
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/organization";
+    field public static final java.lang.String DEPARTMENT = "data5";
+    field public static final java.lang.String JOB_DESCRIPTION = "data6";
+    field public static final java.lang.String OFFICE_LOCATION = "data9";
+    field public static final java.lang.String PHONETIC_NAME = "data8";
+    field public static final java.lang.String SYMBOL = "data7";
+    field public static final java.lang.String TITLE = "data4";
+    field public static final int TYPE_OTHER = 2; // 0x2
+    field public static final int TYPE_WORK = 1; // 0x1
+  }
+
+  public static final class ContactsContract.CommonDataKinds.Phone implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
+    method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+    method public static final int getTypeLabelResource(int);
+    field public static final android.net.Uri CONTENT_FILTER_URI;
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone_v2";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/phone_v2";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String NORMALIZED_NUMBER = "data4";
+    field public static final java.lang.String NUMBER = "data1";
+    field public static final java.lang.String SEARCH_DISPLAY_NAME_KEY = "search_display_name";
+    field public static final java.lang.String SEARCH_PHONE_NUMBER_KEY = "search_phone_number";
+    field public static final int TYPE_ASSISTANT = 19; // 0x13
+    field public static final int TYPE_CALLBACK = 8; // 0x8
+    field public static final int TYPE_CAR = 9; // 0x9
+    field public static final int TYPE_COMPANY_MAIN = 10; // 0xa
+    field public static final int TYPE_FAX_HOME = 5; // 0x5
+    field public static final int TYPE_FAX_WORK = 4; // 0x4
+    field public static final int TYPE_HOME = 1; // 0x1
+    field public static final int TYPE_ISDN = 11; // 0xb
+    field public static final int TYPE_MAIN = 12; // 0xc
+    field public static final int TYPE_MMS = 20; // 0x14
+    field public static final int TYPE_MOBILE = 2; // 0x2
+    field public static final int TYPE_OTHER = 7; // 0x7
+    field public static final int TYPE_OTHER_FAX = 13; // 0xd
+    field public static final int TYPE_PAGER = 6; // 0x6
+    field public static final int TYPE_RADIO = 14; // 0xe
+    field public static final int TYPE_TELEX = 15; // 0xf
+    field public static final int TYPE_TTY_TDD = 16; // 0x10
+    field public static final int TYPE_WORK = 3; // 0x3
+    field public static final int TYPE_WORK_MOBILE = 17; // 0x11
+    field public static final int TYPE_WORK_PAGER = 18; // 0x12
+  }
+
+  public static final class ContactsContract.CommonDataKinds.Photo implements android.provider.ContactsContract.DataColumnsWithJoins {
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo";
+    field public static final java.lang.String PHOTO = "data15";
+    field public static final java.lang.String PHOTO_FILE_ID = "data14";
+  }
+
+  public static final class ContactsContract.CommonDataKinds.Relation implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
+    method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+    method public static final int getTypeLabelResource(int);
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/relation";
+    field public static final java.lang.String NAME = "data1";
+    field public static final int TYPE_ASSISTANT = 1; // 0x1
+    field public static final int TYPE_BROTHER = 2; // 0x2
+    field public static final int TYPE_CHILD = 3; // 0x3
+    field public static final int TYPE_DOMESTIC_PARTNER = 4; // 0x4
+    field public static final int TYPE_FATHER = 5; // 0x5
+    field public static final int TYPE_FRIEND = 6; // 0x6
+    field public static final int TYPE_MANAGER = 7; // 0x7
+    field public static final int TYPE_MOTHER = 8; // 0x8
+    field public static final int TYPE_PARENT = 9; // 0x9
+    field public static final int TYPE_PARTNER = 10; // 0xa
+    field public static final int TYPE_REFERRED_BY = 11; // 0xb
+    field public static final int TYPE_RELATIVE = 12; // 0xc
+    field public static final int TYPE_SISTER = 13; // 0xd
+    field public static final int TYPE_SPOUSE = 14; // 0xe
+  }
+
+  public static final class ContactsContract.CommonDataKinds.SipAddress implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
+    method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+    method public static final int getTypeLabelResource(int);
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/sip_address";
+    field public static final java.lang.String SIP_ADDRESS = "data1";
+    field public static final int TYPE_HOME = 1; // 0x1
+    field public static final int TYPE_OTHER = 3; // 0x3
+    field public static final int TYPE_WORK = 2; // 0x2
+  }
+
+  public static final class ContactsContract.CommonDataKinds.StructuredName implements android.provider.ContactsContract.DataColumnsWithJoins {
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/name";
+    field public static final java.lang.String DISPLAY_NAME = "data1";
+    field public static final java.lang.String FAMILY_NAME = "data3";
+    field public static final java.lang.String GIVEN_NAME = "data2";
+    field public static final java.lang.String MIDDLE_NAME = "data5";
+    field public static final java.lang.String PHONETIC_FAMILY_NAME = "data9";
+    field public static final java.lang.String PHONETIC_GIVEN_NAME = "data7";
+    field public static final java.lang.String PHONETIC_MIDDLE_NAME = "data8";
+    field public static final java.lang.String PREFIX = "data4";
+    field public static final java.lang.String SUFFIX = "data6";
+  }
+
+  public static final class ContactsContract.CommonDataKinds.StructuredPostal implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
+    method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+    method public static final int getTypeLabelResource(int);
+    field public static final java.lang.String CITY = "data7";
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/postal-address_v2";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/postal-address_v2";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String COUNTRY = "data10";
+    field public static final java.lang.String FORMATTED_ADDRESS = "data1";
+    field public static final java.lang.String NEIGHBORHOOD = "data6";
+    field public static final java.lang.String POBOX = "data5";
+    field public static final java.lang.String POSTCODE = "data9";
+    field public static final java.lang.String REGION = "data8";
+    field public static final java.lang.String STREET = "data4";
+    field public static final int TYPE_HOME = 1; // 0x1
+    field public static final int TYPE_OTHER = 3; // 0x3
+    field public static final int TYPE_WORK = 2; // 0x2
+  }
+
+  public static final class ContactsContract.CommonDataKinds.Website implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/website";
+    field public static final int TYPE_BLOG = 2; // 0x2
+    field public static final int TYPE_FTP = 6; // 0x6
+    field public static final int TYPE_HOME = 4; // 0x4
+    field public static final int TYPE_HOMEPAGE = 1; // 0x1
+    field public static final int TYPE_OTHER = 7; // 0x7
+    field public static final int TYPE_PROFILE = 3; // 0x3
+    field public static final int TYPE_WORK = 5; // 0x5
+    field public static final java.lang.String URL = "data1";
+  }
+
+  protected static abstract interface ContactsContract.ContactNameColumns {
+    field public static final java.lang.String DISPLAY_NAME_ALTERNATIVE = "display_name_alt";
+    field public static final java.lang.String DISPLAY_NAME_PRIMARY = "display_name";
+    field public static final java.lang.String DISPLAY_NAME_SOURCE = "display_name_source";
+    field public static final java.lang.String PHONETIC_NAME = "phonetic_name";
+    field public static final java.lang.String PHONETIC_NAME_STYLE = "phonetic_name_style";
+    field public static final java.lang.String SORT_KEY_ALTERNATIVE = "sort_key_alt";
+    field public static final java.lang.String SORT_KEY_PRIMARY = "sort_key";
+  }
+
+  protected static abstract interface ContactsContract.ContactOptionsColumns {
+    field public static final java.lang.String CUSTOM_RINGTONE = "custom_ringtone";
+    field public static final java.lang.String LAST_TIME_CONTACTED = "last_time_contacted";
+    field public static final java.lang.String SEND_TO_VOICEMAIL = "send_to_voicemail";
+    field public static final java.lang.String STARRED = "starred";
+    field public static final java.lang.String TIMES_CONTACTED = "times_contacted";
+  }
+
+  protected static abstract interface ContactsContract.ContactStatusColumns {
+    field public static final java.lang.String CONTACT_CHAT_CAPABILITY = "contact_chat_capability";
+    field public static final java.lang.String CONTACT_PRESENCE = "contact_presence";
+    field public static final java.lang.String CONTACT_STATUS = "contact_status";
+    field public static final java.lang.String CONTACT_STATUS_ICON = "contact_status_icon";
+    field public static final java.lang.String CONTACT_STATUS_LABEL = "contact_status_label";
+    field public static final java.lang.String CONTACT_STATUS_RES_PACKAGE = "contact_status_res_package";
+    field public static final java.lang.String CONTACT_STATUS_TIMESTAMP = "contact_status_ts";
+  }
+
+  public static class ContactsContract.Contacts implements android.provider.BaseColumns android.provider.ContactsContract.ContactNameColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns {
+    method public static android.net.Uri getLookupUri(android.content.ContentResolver, android.net.Uri);
+    method public static android.net.Uri getLookupUri(long, java.lang.String);
+    method public static android.net.Uri lookupContact(android.content.ContentResolver, android.net.Uri);
+    method public static deprecated void markAsContacted(android.content.ContentResolver, long);
+    method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri, boolean);
+    method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri);
+    field public static final android.net.Uri CONTENT_FILTER_URI;
+    field public static final android.net.Uri CONTENT_GROUP_URI;
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact";
+    field public static final android.net.Uri CONTENT_LOOKUP_URI;
+    field public static final android.net.Uri CONTENT_STREQUENT_FILTER_URI;
+    field public static final android.net.Uri CONTENT_STREQUENT_URI;
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/contact";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String CONTENT_VCARD_TYPE = "text/x-vcard";
+    field public static final android.net.Uri CONTENT_VCARD_URI;
+  }
+
+  public static final class ContactsContract.Contacts.AggregationSuggestions implements android.provider.BaseColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns {
+    field public static final java.lang.String CONTENT_DIRECTORY = "suggestions";
+  }
+
+  public static final class ContactsContract.Contacts.Data implements android.provider.BaseColumns android.provider.ContactsContract.DataColumns {
+    field public static final java.lang.String CONTENT_DIRECTORY = "data";
+  }
+
+  public static final class ContactsContract.Contacts.Entity implements android.provider.BaseColumns android.provider.ContactsContract.BaseSyncColumns android.provider.ContactsContract.ContactNameColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns android.provider.ContactsContract.DataColumns android.provider.ContactsContract.RawContactsColumns android.provider.ContactsContract.StatusColumns android.provider.ContactsContract.SyncColumns {
+    field public static final java.lang.String CONTENT_DIRECTORY = "entities";
+    field public static final java.lang.String DATA_ID = "data_id";
+    field public static final java.lang.String RAW_CONTACT_ID = "raw_contact_id";
+  }
+
+  public static final class ContactsContract.Contacts.Photo implements android.provider.BaseColumns android.provider.ContactsContract.DataColumnsWithJoins {
+    field public static final java.lang.String CONTENT_DIRECTORY = "photo";
+    field public static final java.lang.String DISPLAY_PHOTO = "display_photo";
+    field public static final java.lang.String PHOTO = "data15";
+    field public static final java.lang.String PHOTO_FILE_ID = "data14";
+  }
+
+  public static final class ContactsContract.Contacts.StreamItems implements android.provider.ContactsContract.StreamItemsColumns {
+    field public static final java.lang.String CONTENT_DIRECTORY = "stream_items";
+  }
+
+  protected static abstract interface ContactsContract.ContactsColumns {
+    field public static final java.lang.String DISPLAY_NAME = "display_name";
+    field public static final java.lang.String HAS_PHONE_NUMBER = "has_phone_number";
+    field public static final java.lang.String IN_VISIBLE_GROUP = "in_visible_group";
+    field public static final java.lang.String IS_USER_PROFILE = "is_user_profile";
+    field public static final java.lang.String LOOKUP_KEY = "lookup";
+    field public static final java.lang.String PHOTO_FILE_ID = "photo_file_id";
+    field public static final java.lang.String PHOTO_ID = "photo_id";
+    field public static final java.lang.String PHOTO_THUMBNAIL_URI = "photo_thumb_uri";
+    field public static final java.lang.String PHOTO_URI = "photo_uri";
+  }
+
+  public static final class ContactsContract.Data implements android.provider.ContactsContract.DataColumnsWithJoins {
+    method public static android.net.Uri getContactLookupUri(android.content.ContentResolver, android.net.Uri);
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/data";
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface ContactsContract.DataColumns {
+    field public static final java.lang.String DATA1 = "data1";
+    field public static final java.lang.String DATA10 = "data10";
+    field public static final java.lang.String DATA11 = "data11";
+    field public static final java.lang.String DATA12 = "data12";
+    field public static final java.lang.String DATA13 = "data13";
+    field public static final java.lang.String DATA14 = "data14";
+    field public static final java.lang.String DATA15 = "data15";
+    field public static final java.lang.String DATA2 = "data2";
+    field public static final java.lang.String DATA3 = "data3";
+    field public static final java.lang.String DATA4 = "data4";
+    field public static final java.lang.String DATA5 = "data5";
+    field public static final java.lang.String DATA6 = "data6";
+    field public static final java.lang.String DATA7 = "data7";
+    field public static final java.lang.String DATA8 = "data8";
+    field public static final java.lang.String DATA9 = "data9";
+    field public static final java.lang.String DATA_VERSION = "data_version";
+    field public static final java.lang.String IS_PRIMARY = "is_primary";
+    field public static final java.lang.String IS_READ_ONLY = "is_read_only";
+    field public static final java.lang.String IS_SUPER_PRIMARY = "is_super_primary";
+    field public static final java.lang.String MIMETYPE = "mimetype";
+    field public static final java.lang.String RAW_CONTACT_ID = "raw_contact_id";
+    field public static final java.lang.String SYNC1 = "data_sync1";
+    field public static final java.lang.String SYNC2 = "data_sync2";
+    field public static final java.lang.String SYNC3 = "data_sync3";
+    field public static final java.lang.String SYNC4 = "data_sync4";
+  }
+
+  protected static abstract interface ContactsContract.DataColumnsWithJoins implements android.provider.BaseColumns android.provider.ContactsContract.ContactNameColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns android.provider.ContactsContract.DataColumns android.provider.ContactsContract.RawContactsColumns android.provider.ContactsContract.StatusColumns {
+  }
+
+  public static final class ContactsContract.DataUsageFeedback {
+    ctor public ContactsContract.DataUsageFeedback();
+    field public static final android.net.Uri DELETE_USAGE_URI;
+    field public static final android.net.Uri FEEDBACK_URI;
+    field public static final java.lang.String USAGE_TYPE = "type";
+    field public static final java.lang.String USAGE_TYPE_CALL = "call";
+    field public static final java.lang.String USAGE_TYPE_LONG_TEXT = "long_text";
+    field public static final java.lang.String USAGE_TYPE_SHORT_TEXT = "short_text";
+  }
+
+  public static final class ContactsContract.Directory implements android.provider.BaseColumns {
+    method public static void notifyDirectoryChange(android.content.ContentResolver);
+    field public static final java.lang.String ACCOUNT_NAME = "accountName";
+    field public static final java.lang.String ACCOUNT_TYPE = "accountType";
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_directory";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/contact_directories";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final long DEFAULT = 0L; // 0x0L
+    field public static final java.lang.String DIRECTORY_AUTHORITY = "authority";
+    field public static final java.lang.String DISPLAY_NAME = "displayName";
+    field public static final java.lang.String EXPORT_SUPPORT = "exportSupport";
+    field public static final int EXPORT_SUPPORT_ANY_ACCOUNT = 2; // 0x2
+    field public static final int EXPORT_SUPPORT_NONE = 0; // 0x0
+    field public static final int EXPORT_SUPPORT_SAME_ACCOUNT_ONLY = 1; // 0x1
+    field public static final long LOCAL_INVISIBLE = 1L; // 0x1L
+    field public static final java.lang.String PACKAGE_NAME = "packageName";
+    field public static final java.lang.String PHOTO_SUPPORT = "photoSupport";
+    field public static final int PHOTO_SUPPORT_FULL = 3; // 0x3
+    field public static final int PHOTO_SUPPORT_FULL_SIZE_ONLY = 2; // 0x2
+    field public static final int PHOTO_SUPPORT_NONE = 0; // 0x0
+    field public static final int PHOTO_SUPPORT_THUMBNAIL_ONLY = 1; // 0x1
+    field public static final java.lang.String SHORTCUT_SUPPORT = "shortcutSupport";
+    field public static final int SHORTCUT_SUPPORT_DATA_ITEMS_ONLY = 1; // 0x1
+    field public static final int SHORTCUT_SUPPORT_FULL = 2; // 0x2
+    field public static final int SHORTCUT_SUPPORT_NONE = 0; // 0x0
+    field public static final java.lang.String TYPE_RESOURCE_ID = "typeResourceId";
+  }
+
+  public static abstract interface ContactsContract.DisplayNameSources {
+    field public static final int EMAIL = 10; // 0xa
+    field public static final int NICKNAME = 35; // 0x23
+    field public static final int ORGANIZATION = 30; // 0x1e
+    field public static final int PHONE = 20; // 0x14
+    field public static final int STRUCTURED_NAME = 40; // 0x28
+    field public static final int UNDEFINED = 0; // 0x0
+  }
+
+  public static final class ContactsContract.DisplayPhoto {
+    field public static final android.net.Uri CONTENT_MAX_DIMENSIONS_URI;
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DISPLAY_MAX_DIM = "display_max_dim";
+    field public static final java.lang.String THUMBNAIL_MAX_DIM = "thumbnail_max_dim";
+  }
+
+  public static abstract interface ContactsContract.FullNameStyle {
+    field public static final int CHINESE = 3; // 0x3
+    field public static final int CJK = 2; // 0x2
+    field public static final int JAPANESE = 4; // 0x4
+    field public static final int KOREAN = 5; // 0x5
+    field public static final int UNDEFINED = 0; // 0x0
+    field public static final int WESTERN = 1; // 0x1
+  }
+
+  public static final class ContactsContract.Groups implements android.provider.BaseColumns android.provider.ContactsContract.GroupsColumns android.provider.ContactsContract.SyncColumns {
+    method public static android.content.EntityIterator newEntityIterator(android.database.Cursor);
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/group";
+    field public static final android.net.Uri CONTENT_SUMMARY_URI;
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/group";
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface ContactsContract.GroupsColumns {
+    field public static final java.lang.String AUTO_ADD = "auto_add";
+    field public static final java.lang.String DATA_SET = "data_set";
+    field public static final java.lang.String DELETED = "deleted";
+    field public static final java.lang.String FAVORITES = "favorites";
+    field public static final java.lang.String GROUP_IS_READ_ONLY = "group_is_read_only";
+    field public static final java.lang.String GROUP_VISIBLE = "group_visible";
+    field public static final java.lang.String NOTES = "notes";
+    field public static final java.lang.String SHOULD_SYNC = "should_sync";
+    field public static final java.lang.String SUMMARY_COUNT = "summ_count";
+    field public static final java.lang.String SUMMARY_WITH_PHONES = "summ_phones";
+    field public static final java.lang.String SYSTEM_ID = "system_id";
+    field public static final java.lang.String TITLE = "title";
+  }
+
+  public static final class ContactsContract.Intents {
+    ctor public ContactsContract.Intents();
+    field public static final java.lang.String ATTACH_IMAGE = "com.android.contacts.action.ATTACH_IMAGE";
+    field public static final java.lang.String EXTRA_CREATE_DESCRIPTION = "com.android.contacts.action.CREATE_DESCRIPTION";
+    field public static final java.lang.String EXTRA_FORCE_CREATE = "com.android.contacts.action.FORCE_CREATE";
+    field public static final java.lang.String INVITE_CONTACT = "com.android.contacts.action.INVITE_CONTACT";
+    field public static final java.lang.String SEARCH_SUGGESTION_CLICKED = "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED";
+    field public static final java.lang.String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED = "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED";
+    field public static final java.lang.String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED = "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED";
+    field public static final java.lang.String SHOW_OR_CREATE_CONTACT = "com.android.contacts.action.SHOW_OR_CREATE_CONTACT";
+  }
+
+  public static final class ContactsContract.Intents.Insert {
+    ctor public ContactsContract.Intents.Insert();
+    field public static final java.lang.String ACTION = "android.intent.action.INSERT";
+    field public static final java.lang.String COMPANY = "company";
+    field public static final java.lang.String DATA = "data";
+    field public static final java.lang.String EMAIL = "email";
+    field public static final java.lang.String EMAIL_ISPRIMARY = "email_isprimary";
+    field public static final java.lang.String EMAIL_TYPE = "email_type";
+    field public static final java.lang.String FULL_MODE = "full_mode";
+    field public static final java.lang.String IM_HANDLE = "im_handle";
+    field public static final java.lang.String IM_ISPRIMARY = "im_isprimary";
+    field public static final java.lang.String IM_PROTOCOL = "im_protocol";
+    field public static final java.lang.String JOB_TITLE = "job_title";
+    field public static final java.lang.String NAME = "name";
+    field public static final java.lang.String NOTES = "notes";
+    field public static final java.lang.String PHONE = "phone";
+    field public static final java.lang.String PHONETIC_NAME = "phonetic_name";
+    field public static final java.lang.String PHONE_ISPRIMARY = "phone_isprimary";
+    field public static final java.lang.String PHONE_TYPE = "phone_type";
+    field public static final java.lang.String POSTAL = "postal";
+    field public static final java.lang.String POSTAL_ISPRIMARY = "postal_isprimary";
+    field public static final java.lang.String POSTAL_TYPE = "postal_type";
+    field public static final java.lang.String SECONDARY_EMAIL = "secondary_email";
+    field public static final java.lang.String SECONDARY_EMAIL_TYPE = "secondary_email_type";
+    field public static final java.lang.String SECONDARY_PHONE = "secondary_phone";
+    field public static final java.lang.String SECONDARY_PHONE_TYPE = "secondary_phone_type";
+    field public static final java.lang.String TERTIARY_EMAIL = "tertiary_email";
+    field public static final java.lang.String TERTIARY_EMAIL_TYPE = "tertiary_email_type";
+    field public static final java.lang.String TERTIARY_PHONE = "tertiary_phone";
+    field public static final java.lang.String TERTIARY_PHONE_TYPE = "tertiary_phone_type";
+  }
+
+  public static final class ContactsContract.PhoneLookup implements android.provider.BaseColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactsColumns android.provider.ContactsContract.PhoneLookupColumns {
+    field public static final android.net.Uri CONTENT_FILTER_URI;
+  }
+
+  protected static abstract interface ContactsContract.PhoneLookupColumns {
+    field public static final java.lang.String LABEL = "label";
+    field public static final java.lang.String NORMALIZED_NUMBER = "normalized_number";
+    field public static final java.lang.String NUMBER = "number";
+    field public static final java.lang.String TYPE = "type";
+  }
+
+  public static abstract interface ContactsContract.PhoneticNameStyle {
+    field public static final int JAPANESE = 4; // 0x4
+    field public static final int KOREAN = 5; // 0x5
+    field public static final int PINYIN = 3; // 0x3
+    field public static final int UNDEFINED = 0; // 0x0
+  }
+
+  public static final deprecated class ContactsContract.Presence extends android.provider.ContactsContract.StatusUpdates {
+    ctor public ContactsContract.Presence();
+  }
+
+  protected static abstract interface ContactsContract.PresenceColumns {
+    field public static final java.lang.String CUSTOM_PROTOCOL = "custom_protocol";
+    field public static final java.lang.String DATA_ID = "presence_data_id";
+    field public static final java.lang.String IM_ACCOUNT = "im_account";
+    field public static final java.lang.String IM_HANDLE = "im_handle";
+    field public static final java.lang.String PROTOCOL = "protocol";
+  }
+
+  public static final class ContactsContract.Profile implements android.provider.BaseColumns android.provider.ContactsContract.ContactNameColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns {
+    field public static final android.net.Uri CONTENT_RAW_CONTACTS_URI;
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final android.net.Uri CONTENT_VCARD_URI;
+    field public static final long MIN_ID = 9223372034707292160L; // 0x7fffffff80000000L
+  }
+
+  public static final class ContactsContract.ProfileSyncState implements android.provider.SyncStateContract.Columns {
+    method public static byte[] get(android.content.ContentProviderClient, android.accounts.Account) throws android.os.RemoteException;
+    method public static android.util.Pair<android.net.Uri, byte[]> getWithUri(android.content.ContentProviderClient, android.accounts.Account) throws android.os.RemoteException;
+    method public static android.content.ContentProviderOperation newSetOperation(android.accounts.Account, byte[]);
+    method public static void set(android.content.ContentProviderClient, android.accounts.Account, byte[]) throws android.os.RemoteException;
+    field public static final java.lang.String CONTENT_DIRECTORY = "syncstate";
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  public static final class ContactsContract.QuickContact {
+    ctor public ContactsContract.QuickContact();
+    method public static void showQuickContact(android.content.Context, android.view.View, android.net.Uri, int, java.lang.String[]);
+    method public static void showQuickContact(android.content.Context, android.graphics.Rect, android.net.Uri, int, java.lang.String[]);
+    field public static final int MODE_LARGE = 3; // 0x3
+    field public static final int MODE_MEDIUM = 2; // 0x2
+    field public static final int MODE_SMALL = 1; // 0x1
+  }
+
+  public static final class ContactsContract.RawContacts implements android.provider.BaseColumns android.provider.ContactsContract.ContactNameColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.RawContactsColumns android.provider.ContactsContract.SyncColumns {
+    method public static android.net.Uri getContactLookupUri(android.content.ContentResolver, android.net.Uri);
+    method public static android.content.EntityIterator newEntityIterator(android.database.Cursor);
+    field public static final int AGGREGATION_MODE_DEFAULT = 0; // 0x0
+    field public static final int AGGREGATION_MODE_DISABLED = 3; // 0x3
+    field public static final deprecated int AGGREGATION_MODE_IMMEDIATE = 1; // 0x1
+    field public static final int AGGREGATION_MODE_SUSPENDED = 2; // 0x2
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/raw_contact";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/raw_contact";
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  public static final class ContactsContract.RawContacts.Data implements android.provider.BaseColumns android.provider.ContactsContract.DataColumns {
+    field public static final java.lang.String CONTENT_DIRECTORY = "data";
+  }
+
+  public static final class ContactsContract.RawContacts.DisplayPhoto {
+    field public static final java.lang.String CONTENT_DIRECTORY = "display_photo";
+  }
+
+  public static final class ContactsContract.RawContacts.Entity implements android.provider.BaseColumns android.provider.ContactsContract.DataColumns {
+    field public static final java.lang.String CONTENT_DIRECTORY = "entity";
+    field public static final java.lang.String DATA_ID = "data_id";
+  }
+
+  public static final class ContactsContract.RawContacts.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns {
+    field public static final java.lang.String CONTENT_DIRECTORY = "stream_items";
+  }
+
+  protected static abstract interface ContactsContract.RawContactsColumns {
+    field public static final java.lang.String AGGREGATION_MODE = "aggregation_mode";
+    field public static final java.lang.String CONTACT_ID = "contact_id";
+    field public static final java.lang.String DATA_SET = "data_set";
+    field public static final java.lang.String DELETED = "deleted";
+    field public static final java.lang.String RAW_CONTACT_IS_READ_ONLY = "raw_contact_is_read_only";
+    field public static final java.lang.String RAW_CONTACT_IS_USER_PROFILE = "raw_contact_is_user_profile";
+  }
+
+  public static final class ContactsContract.RawContactsEntity implements android.provider.BaseColumns android.provider.ContactsContract.DataColumns android.provider.ContactsContract.RawContactsColumns {
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/raw_contact_entity";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DATA_ID = "data_id";
+    field public static final android.net.Uri PROFILE_CONTENT_URI;
+  }
+
+  public static final class ContactsContract.Settings implements android.provider.ContactsContract.SettingsColumns {
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/setting";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/setting";
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface ContactsContract.SettingsColumns {
+    field public static final java.lang.String ACCOUNT_NAME = "account_name";
+    field public static final java.lang.String ACCOUNT_TYPE = "account_type";
+    field public static final java.lang.String ANY_UNSYNCED = "any_unsynced";
+    field public static final java.lang.String DATA_SET = "data_set";
+    field public static final java.lang.String SHOULD_SYNC = "should_sync";
+    field public static final java.lang.String UNGROUPED_COUNT = "summ_count";
+    field public static final java.lang.String UNGROUPED_VISIBLE = "ungrouped_visible";
+    field public static final java.lang.String UNGROUPED_WITH_PHONES = "summ_phones";
+  }
+
+  protected static abstract interface ContactsContract.StatusColumns {
+    field public static final int AVAILABLE = 5; // 0x5
+    field public static final int AWAY = 2; // 0x2
+    field public static final int CAPABILITY_HAS_CAMERA = 4; // 0x4
+    field public static final int CAPABILITY_HAS_VIDEO = 2; // 0x2
+    field public static final int CAPABILITY_HAS_VOICE = 1; // 0x1
+    field public static final java.lang.String CHAT_CAPABILITY = "chat_capability";
+    field public static final int DO_NOT_DISTURB = 4; // 0x4
+    field public static final int IDLE = 3; // 0x3
+    field public static final int INVISIBLE = 1; // 0x1
+    field public static final int OFFLINE = 0; // 0x0
+    field public static final java.lang.String PRESENCE = "mode";
+    field public static final deprecated java.lang.String PRESENCE_CUSTOM_STATUS = "status";
+    field public static final deprecated java.lang.String PRESENCE_STATUS = "mode";
+    field public static final java.lang.String STATUS = "status";
+    field public static final java.lang.String STATUS_ICON = "status_icon";
+    field public static final java.lang.String STATUS_LABEL = "status_label";
+    field public static final java.lang.String STATUS_RES_PACKAGE = "status_res_package";
+    field public static final java.lang.String STATUS_TIMESTAMP = "status_ts";
+  }
+
+  public static class ContactsContract.StatusUpdates implements android.provider.ContactsContract.PresenceColumns android.provider.ContactsContract.StatusColumns {
+    method public static final int getPresenceIconResourceId(int);
+    method public static final int getPresencePrecedence(int);
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/status-update";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/status-update";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final android.net.Uri PROFILE_CONTENT_URI;
+  }
+
+  public static final class ContactsContract.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
+    field public static final java.lang.String PHOTO = "photo";
+  }
+
+  protected static abstract interface ContactsContract.StreamItemPhotosColumns {
+    field public static final java.lang.String PHOTO_FILE_ID = "photo_file_id";
+    field public static final java.lang.String PHOTO_URI = "photo_uri";
+    field public static final java.lang.String SORT_INDEX = "sort_index";
+    field public static final java.lang.String STREAM_ITEM_ID = "stream_item_id";
+    field public static final java.lang.String SYNC1 = "stream_item_photo_sync1";
+    field public static final java.lang.String SYNC2 = "stream_item_photo_sync2";
+    field public static final java.lang.String SYNC3 = "stream_item_photo_sync3";
+    field public static final java.lang.String SYNC4 = "stream_item_photo_sync4";
+  }
+
+  public static final class ContactsContract.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns {
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item";
+    field public static final android.net.Uri CONTENT_LIMIT_URI;
+    field public static final android.net.Uri CONTENT_PHOTO_URI;
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String MAX_ITEMS = "max_items";
+  }
+
+  public static final class ContactsContract.StreamItems.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
+    field public static final java.lang.String CONTENT_DIRECTORY = "photo";
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item_photo";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item_photo";
+  }
+
+  protected static abstract interface ContactsContract.StreamItemsColumns {
+    field public static final java.lang.String ACCOUNT_NAME = "account_name";
+    field public static final java.lang.String ACCOUNT_TYPE = "account_type";
+    field public static final java.lang.String COMMENTS = "comments";
+    field public static final java.lang.String CONTACT_ID = "contact_id";
+    field public static final java.lang.String CONTACT_LOOKUP_KEY = "contact_lookup";
+    field public static final java.lang.String DATA_SET = "data_set";
+    field public static final java.lang.String RAW_CONTACT_ID = "raw_contact_id";
+    field public static final java.lang.String RAW_CONTACT_SOURCE_ID = "raw_contact_source_id";
+    field public static final java.lang.String RES_ICON = "icon";
+    field public static final java.lang.String RES_LABEL = "label";
+    field public static final java.lang.String RES_PACKAGE = "res_package";
+    field public static final java.lang.String SYNC1 = "stream_item_sync1";
+    field public static final java.lang.String SYNC2 = "stream_item_sync2";
+    field public static final java.lang.String SYNC3 = "stream_item_sync3";
+    field public static final java.lang.String SYNC4 = "stream_item_sync4";
+    field public static final java.lang.String TEXT = "text";
+    field public static final java.lang.String TIMESTAMP = "timestamp";
+  }
+
+  protected static abstract interface ContactsContract.SyncColumns implements android.provider.ContactsContract.BaseSyncColumns {
+    field public static final java.lang.String ACCOUNT_NAME = "account_name";
+    field public static final java.lang.String ACCOUNT_TYPE = "account_type";
+    field public static final java.lang.String DIRTY = "dirty";
+    field public static final java.lang.String SOURCE_ID = "sourceid";
+    field public static final java.lang.String VERSION = "version";
+  }
+
+  public static final class ContactsContract.SyncState implements android.provider.SyncStateContract.Columns {
+    method public static byte[] get(android.content.ContentProviderClient, android.accounts.Account) throws android.os.RemoteException;
+    method public static android.util.Pair<android.net.Uri, byte[]> getWithUri(android.content.ContentProviderClient, android.accounts.Account) throws android.os.RemoteException;
+    method public static android.content.ContentProviderOperation newSetOperation(android.accounts.Account, byte[]);
+    method public static void set(android.content.ContentProviderClient, android.accounts.Account, byte[]) throws android.os.RemoteException;
+    field public static final java.lang.String CONTENT_DIRECTORY = "syncstate";
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  public final deprecated class LiveFolders implements android.provider.BaseColumns {
+    field public static final java.lang.String ACTION_CREATE_LIVE_FOLDER = "android.intent.action.CREATE_LIVE_FOLDER";
+    field public static final java.lang.String DESCRIPTION = "description";
+    field public static final int DISPLAY_MODE_GRID = 1; // 0x1
+    field public static final int DISPLAY_MODE_LIST = 2; // 0x2
+    field public static final java.lang.String EXTRA_LIVE_FOLDER_BASE_INTENT = "android.intent.extra.livefolder.BASE_INTENT";
+    field public static final java.lang.String EXTRA_LIVE_FOLDER_DISPLAY_MODE = "android.intent.extra.livefolder.DISPLAY_MODE";
+    field public static final java.lang.String EXTRA_LIVE_FOLDER_ICON = "android.intent.extra.livefolder.ICON";
+    field public static final java.lang.String EXTRA_LIVE_FOLDER_NAME = "android.intent.extra.livefolder.NAME";
+    field public static final java.lang.String ICON_BITMAP = "icon_bitmap";
+    field public static final java.lang.String ICON_PACKAGE = "icon_package";
+    field public static final java.lang.String ICON_RESOURCE = "icon_resource";
+    field public static final java.lang.String INTENT = "intent";
+    field public static final java.lang.String NAME = "name";
+  }
+
+  public final class MediaStore {
+    ctor public MediaStore();
+    method public static android.net.Uri getMediaScannerUri();
+    method public static java.lang.String getVersion(android.content.Context);
+    field public static final java.lang.String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
+    field public static final java.lang.String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE";
+    field public static final java.lang.String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE";
+    field public static final java.lang.String AUTHORITY = "media";
+    field public static final java.lang.String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit";
+    field public static final java.lang.String EXTRA_FINISH_ON_COMPLETION = "android.intent.extra.finishOnCompletion";
+    field public static final java.lang.String EXTRA_FULL_SCREEN = "android.intent.extra.fullScreen";
+    field public static final java.lang.String EXTRA_MEDIA_ALBUM = "android.intent.extra.album";
+    field public static final java.lang.String EXTRA_MEDIA_ARTIST = "android.intent.extra.artist";
+    field public static final java.lang.String EXTRA_MEDIA_FOCUS = "android.intent.extra.focus";
+    field public static final java.lang.String EXTRA_MEDIA_TITLE = "android.intent.extra.title";
+    field public static final java.lang.String EXTRA_OUTPUT = "output";
+    field public static final java.lang.String EXTRA_SCREEN_ORIENTATION = "android.intent.extra.screenOrientation";
+    field public static final java.lang.String EXTRA_SHOW_ACTION_ICONS = "android.intent.extra.showActionIcons";
+    field public static final java.lang.String EXTRA_SIZE_LIMIT = "android.intent.extra.sizeLimit";
+    field public static final java.lang.String EXTRA_VIDEO_QUALITY = "android.intent.extra.videoQuality";
+    field public static final java.lang.String INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH = "android.media.action.MEDIA_PLAY_FROM_SEARCH";
+    field public static final java.lang.String INTENT_ACTION_MEDIA_SEARCH = "android.intent.action.MEDIA_SEARCH";
+    field public static final deprecated java.lang.String INTENT_ACTION_MUSIC_PLAYER = "android.intent.action.MUSIC_PLAYER";
+    field public static final java.lang.String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA";
+    field public static final java.lang.String INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE = "android.media.action.STILL_IMAGE_CAMERA_SECURE";
+    field public static final java.lang.String INTENT_ACTION_TEXT_OPEN_FROM_SEARCH = "android.media.action.TEXT_OPEN_FROM_SEARCH";
+    field public static final java.lang.String INTENT_ACTION_VIDEO_CAMERA = "android.media.action.VIDEO_CAMERA";
+    field public static final java.lang.String INTENT_ACTION_VIDEO_PLAY_FROM_SEARCH = "android.media.action.VIDEO_PLAY_FROM_SEARCH";
+    field public static final java.lang.String MEDIA_IGNORE_FILENAME = ".nomedia";
+    field public static final java.lang.String MEDIA_SCANNER_VOLUME = "volume";
+    field public static final java.lang.String UNKNOWN_STRING = "<unknown>";
+  }
+
+  public static final class MediaStore.Audio {
+    ctor public MediaStore.Audio();
+    method public static java.lang.String keyFor(java.lang.String);
+  }
+
+  public static abstract interface MediaStore.Audio.AlbumColumns {
+    field public static final java.lang.String ALBUM = "album";
+    field public static final java.lang.String ALBUM_ART = "album_art";
+    field public static final java.lang.String ALBUM_ID = "album_id";
+    field public static final java.lang.String ALBUM_KEY = "album_key";
+    field public static final java.lang.String ARTIST = "artist";
+    field public static final java.lang.String FIRST_YEAR = "minyear";
+    field public static final java.lang.String LAST_YEAR = "maxyear";
+    field public static final java.lang.String NUMBER_OF_SONGS = "numsongs";
+    field public static final java.lang.String NUMBER_OF_SONGS_FOR_ARTIST = "numsongs_by_artist";
+  }
+
+  public static final class MediaStore.Audio.Albums implements android.provider.BaseColumns android.provider.MediaStore.Audio.AlbumColumns {
+    ctor public MediaStore.Audio.Albums();
+    method public static android.net.Uri getContentUri(java.lang.String);
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/albums";
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "album_key";
+    field public static final java.lang.String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/album";
+    field public static final android.net.Uri EXTERNAL_CONTENT_URI;
+    field public static final android.net.Uri INTERNAL_CONTENT_URI;
+  }
+
+  public static abstract interface MediaStore.Audio.ArtistColumns {
+    field public static final java.lang.String ARTIST = "artist";
+    field public static final java.lang.String ARTIST_KEY = "artist_key";
+    field public static final java.lang.String NUMBER_OF_ALBUMS = "number_of_albums";
+    field public static final java.lang.String NUMBER_OF_TRACKS = "number_of_tracks";
+  }
+
+  public static final class MediaStore.Audio.Artists implements android.provider.BaseColumns android.provider.MediaStore.Audio.ArtistColumns {
+    ctor public MediaStore.Audio.Artists();
+    method public static android.net.Uri getContentUri(java.lang.String);
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/artists";
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "artist_key";
+    field public static final java.lang.String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/artist";
+    field public static final android.net.Uri EXTERNAL_CONTENT_URI;
+    field public static final android.net.Uri INTERNAL_CONTENT_URI;
+  }
+
+  public static final class MediaStore.Audio.Artists.Albums implements android.provider.MediaStore.Audio.AlbumColumns {
+    ctor public MediaStore.Audio.Artists.Albums();
+    method public static final android.net.Uri getContentUri(java.lang.String, long);
+  }
+
+  public static abstract interface MediaStore.Audio.AudioColumns implements android.provider.MediaStore.MediaColumns {
+    field public static final java.lang.String ALBUM = "album";
+    field public static final java.lang.String ALBUM_ID = "album_id";
+    field public static final java.lang.String ALBUM_KEY = "album_key";
+    field public static final java.lang.String ARTIST = "artist";
+    field public static final java.lang.String ARTIST_ID = "artist_id";
+    field public static final java.lang.String ARTIST_KEY = "artist_key";
+    field public static final java.lang.String BOOKMARK = "bookmark";
+    field public static final java.lang.String COMPOSER = "composer";
+    field public static final java.lang.String DURATION = "duration";
+    field public static final java.lang.String IS_ALARM = "is_alarm";
+    field public static final java.lang.String IS_MUSIC = "is_music";
+    field public static final java.lang.String IS_NOTIFICATION = "is_notification";
+    field public static final java.lang.String IS_PODCAST = "is_podcast";
+    field public static final java.lang.String IS_RINGTONE = "is_ringtone";
+    field public static final java.lang.String TITLE_KEY = "title_key";
+    field public static final java.lang.String TRACK = "track";
+    field public static final java.lang.String YEAR = "year";
+  }
+
+  public static final class MediaStore.Audio.Genres implements android.provider.BaseColumns android.provider.MediaStore.Audio.GenresColumns {
+    ctor public MediaStore.Audio.Genres();
+    method public static android.net.Uri getContentUri(java.lang.String);
+    method public static android.net.Uri getContentUriForAudioId(java.lang.String, int);
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/genre";
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "name";
+    field public static final java.lang.String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/genre";
+    field public static final android.net.Uri EXTERNAL_CONTENT_URI;
+    field public static final android.net.Uri INTERNAL_CONTENT_URI;
+  }
+
+  public static final class MediaStore.Audio.Genres.Members implements android.provider.MediaStore.Audio.AudioColumns {
+    ctor public MediaStore.Audio.Genres.Members();
+    method public static final android.net.Uri getContentUri(java.lang.String, long);
+    field public static final java.lang.String AUDIO_ID = "audio_id";
+    field public static final java.lang.String CONTENT_DIRECTORY = "members";
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "title_key";
+    field public static final java.lang.String GENRE_ID = "genre_id";
+  }
+
+  public static abstract interface MediaStore.Audio.GenresColumns {
+    field public static final java.lang.String NAME = "name";
+  }
+
+  public static final class MediaStore.Audio.Media implements android.provider.MediaStore.Audio.AudioColumns {
+    ctor public MediaStore.Audio.Media();
+    method public static android.net.Uri getContentUri(java.lang.String);
+    method public static android.net.Uri getContentUriForPath(java.lang.String);
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/audio";
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "title_key";
+    field public static final android.net.Uri EXTERNAL_CONTENT_URI;
+    field public static final java.lang.String EXTRA_MAX_BYTES = "android.provider.MediaStore.extra.MAX_BYTES";
+    field public static final android.net.Uri INTERNAL_CONTENT_URI;
+    field public static final java.lang.String RECORD_SOUND_ACTION = "android.provider.MediaStore.RECORD_SOUND";
+  }
+
+  public static final class MediaStore.Audio.Playlists implements android.provider.BaseColumns android.provider.MediaStore.Audio.PlaylistsColumns {
+    ctor public MediaStore.Audio.Playlists();
+    method public static android.net.Uri getContentUri(java.lang.String);
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/playlist";
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "name";
+    field public static final java.lang.String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/playlist";
+    field public static final android.net.Uri EXTERNAL_CONTENT_URI;
+    field public static final android.net.Uri INTERNAL_CONTENT_URI;
+  }
+
+  public static final class MediaStore.Audio.Playlists.Members implements android.provider.MediaStore.Audio.AudioColumns {
+    ctor public MediaStore.Audio.Playlists.Members();
+    method public static final android.net.Uri getContentUri(java.lang.String, long);
+    method public static final boolean moveItem(android.content.ContentResolver, long, int, int);
+    field public static final java.lang.String AUDIO_ID = "audio_id";
+    field public static final java.lang.String CONTENT_DIRECTORY = "members";
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "play_order";
+    field public static final java.lang.String PLAYLIST_ID = "playlist_id";
+    field public static final java.lang.String PLAY_ORDER = "play_order";
+    field public static final java.lang.String _ID = "_id";
+  }
+
+  public static abstract interface MediaStore.Audio.PlaylistsColumns {
+    field public static final java.lang.String DATA = "_data";
+    field public static final java.lang.String DATE_ADDED = "date_added";
+    field public static final java.lang.String DATE_MODIFIED = "date_modified";
+    field public static final java.lang.String NAME = "name";
+  }
+
+  public static final class MediaStore.Files {
+    ctor public MediaStore.Files();
+    method public static android.net.Uri getContentUri(java.lang.String);
+    method public static final android.net.Uri getContentUri(java.lang.String, long);
+  }
+
+  public static abstract interface MediaStore.Files.FileColumns implements android.provider.MediaStore.MediaColumns {
+    field public static final java.lang.String MEDIA_TYPE = "media_type";
+    field public static final int MEDIA_TYPE_AUDIO = 2; // 0x2
+    field public static final int MEDIA_TYPE_IMAGE = 1; // 0x1
+    field public static final int MEDIA_TYPE_NONE = 0; // 0x0
+    field public static final int MEDIA_TYPE_PLAYLIST = 4; // 0x4
+    field public static final int MEDIA_TYPE_VIDEO = 3; // 0x3
+    field public static final java.lang.String MIME_TYPE = "mime_type";
+    field public static final java.lang.String PARENT = "parent";
+    field public static final java.lang.String TITLE = "title";
+  }
+
+  public static final class MediaStore.Images {
+    ctor public MediaStore.Images();
+  }
+
+  public static abstract interface MediaStore.Images.ImageColumns implements android.provider.MediaStore.MediaColumns {
+    field public static final java.lang.String BUCKET_DISPLAY_NAME = "bucket_display_name";
+    field public static final java.lang.String BUCKET_ID = "bucket_id";
+    field public static final java.lang.String DATE_TAKEN = "datetaken";
+    field public static final java.lang.String DESCRIPTION = "description";
+    field public static final java.lang.String IS_PRIVATE = "isprivate";
+    field public static final java.lang.String LATITUDE = "latitude";
+    field public static final java.lang.String LONGITUDE = "longitude";
+    field public static final java.lang.String MINI_THUMB_MAGIC = "mini_thumb_magic";
+    field public static final java.lang.String ORIENTATION = "orientation";
+    field public static final java.lang.String PICASA_ID = "picasa_id";
+  }
+
+  public static final class MediaStore.Images.Media implements android.provider.MediaStore.Images.ImageColumns {
+    ctor public MediaStore.Images.Media();
+    method public static final android.graphics.Bitmap getBitmap(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException, java.io.IOException;
+    method public static android.net.Uri getContentUri(java.lang.String);
+    method public static final java.lang.String insertImage(android.content.ContentResolver, java.lang.String, java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
+    method public static final java.lang.String insertImage(android.content.ContentResolver, android.graphics.Bitmap, java.lang.String, java.lang.String);
+    method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[]);
+    method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String);
+    method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/image";
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "bucket_display_name";
+    field public static final android.net.Uri EXTERNAL_CONTENT_URI;
+    field public static final android.net.Uri INTERNAL_CONTENT_URI;
+  }
+
+  public static class MediaStore.Images.Thumbnails implements android.provider.BaseColumns {
+    ctor public MediaStore.Images.Thumbnails();
+    method public static void cancelThumbnailRequest(android.content.ContentResolver, long);
+    method public static void cancelThumbnailRequest(android.content.ContentResolver, long, long);
+    method public static android.net.Uri getContentUri(java.lang.String);
+    method public static android.graphics.Bitmap getThumbnail(android.content.ContentResolver, long, int, android.graphics.BitmapFactory.Options);
+    method public static android.graphics.Bitmap getThumbnail(android.content.ContentResolver, long, long, int, android.graphics.BitmapFactory.Options);
+    method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[]);
+    method public static final android.database.Cursor queryMiniThumbnail(android.content.ContentResolver, long, int, java.lang.String[]);
+    method public static final android.database.Cursor queryMiniThumbnails(android.content.ContentResolver, android.net.Uri, int, java.lang.String[]);
+    field public static final java.lang.String DATA = "_data";
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "image_id ASC";
+    field public static final android.net.Uri EXTERNAL_CONTENT_URI;
+    field public static final int FULL_SCREEN_KIND = 2; // 0x2
+    field public static final java.lang.String HEIGHT = "height";
+    field public static final java.lang.String IMAGE_ID = "image_id";
+    field public static final android.net.Uri INTERNAL_CONTENT_URI;
+    field public static final java.lang.String KIND = "kind";
+    field public static final int MICRO_KIND = 3; // 0x3
+    field public static final int MINI_KIND = 1; // 0x1
+    field public static final java.lang.String THUMB_DATA = "thumb_data";
+    field public static final java.lang.String WIDTH = "width";
+  }
+
+  public static abstract interface MediaStore.MediaColumns implements android.provider.BaseColumns {
+    field public static final java.lang.String DATA = "_data";
+    field public static final java.lang.String DATE_ADDED = "date_added";
+    field public static final java.lang.String DATE_MODIFIED = "date_modified";
+    field public static final java.lang.String DISPLAY_NAME = "_display_name";
+    field public static final java.lang.String HEIGHT = "height";
+    field public static final java.lang.String MIME_TYPE = "mime_type";
+    field public static final java.lang.String SIZE = "_size";
+    field public static final java.lang.String TITLE = "title";
+    field public static final java.lang.String WIDTH = "width";
+  }
+
+  public static final class MediaStore.Video {
+    ctor public MediaStore.Video();
+    method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[]);
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "_display_name";
+  }
+
+  public static final class MediaStore.Video.Media implements android.provider.MediaStore.Video.VideoColumns {
+    ctor public MediaStore.Video.Media();
+    method public static android.net.Uri getContentUri(java.lang.String);
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/video";
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "title";
+    field public static final android.net.Uri EXTERNAL_CONTENT_URI;
+    field public static final android.net.Uri INTERNAL_CONTENT_URI;
+  }
+
+  public static class MediaStore.Video.Thumbnails implements android.provider.BaseColumns {
+    ctor public MediaStore.Video.Thumbnails();
+    method public static void cancelThumbnailRequest(android.content.ContentResolver, long);
+    method public static void cancelThumbnailRequest(android.content.ContentResolver, long, long);
+    method public static android.net.Uri getContentUri(java.lang.String);
+    method public static android.graphics.Bitmap getThumbnail(android.content.ContentResolver, long, int, android.graphics.BitmapFactory.Options);
+    method public static android.graphics.Bitmap getThumbnail(android.content.ContentResolver, long, long, int, android.graphics.BitmapFactory.Options);
+    field public static final java.lang.String DATA = "_data";
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "video_id ASC";
+    field public static final android.net.Uri EXTERNAL_CONTENT_URI;
+    field public static final int FULL_SCREEN_KIND = 2; // 0x2
+    field public static final java.lang.String HEIGHT = "height";
+    field public static final android.net.Uri INTERNAL_CONTENT_URI;
+    field public static final java.lang.String KIND = "kind";
+    field public static final int MICRO_KIND = 3; // 0x3
+    field public static final int MINI_KIND = 1; // 0x1
+    field public static final java.lang.String VIDEO_ID = "video_id";
+    field public static final java.lang.String WIDTH = "width";
+  }
+
+  public static abstract interface MediaStore.Video.VideoColumns implements android.provider.MediaStore.MediaColumns {
+    field public static final java.lang.String ALBUM = "album";
+    field public static final java.lang.String ARTIST = "artist";
+    field public static final java.lang.String BOOKMARK = "bookmark";
+    field public static final java.lang.String BUCKET_DISPLAY_NAME = "bucket_display_name";
+    field public static final java.lang.String BUCKET_ID = "bucket_id";
+    field public static final java.lang.String CATEGORY = "category";
+    field public static final java.lang.String DATE_TAKEN = "datetaken";
+    field public static final java.lang.String DESCRIPTION = "description";
+    field public static final java.lang.String DURATION = "duration";
+    field public static final java.lang.String IS_PRIVATE = "isprivate";
+    field public static final java.lang.String LANGUAGE = "language";
+    field public static final java.lang.String LATITUDE = "latitude";
+    field public static final java.lang.String LONGITUDE = "longitude";
+    field public static final java.lang.String MINI_THUMB_MAGIC = "mini_thumb_magic";
+    field public static final java.lang.String RESOLUTION = "resolution";
+    field public static final java.lang.String TAGS = "tags";
+  }
+
+  public abstract interface OpenableColumns {
+    field public static final java.lang.String DISPLAY_NAME = "_display_name";
+    field public static final java.lang.String SIZE = "_size";
+  }
+
+  public class SearchRecentSuggestions {
+    ctor public SearchRecentSuggestions(android.content.Context, java.lang.String, int);
+    method public void clearHistory();
+    method public void saveRecentQuery(java.lang.String, java.lang.String);
+    method protected void truncateHistory(android.content.ContentResolver, int);
+    field public static final java.lang.String[] QUERIES_PROJECTION_1LINE;
+    field public static final java.lang.String[] QUERIES_PROJECTION_2LINE;
+    field public static final int QUERIES_PROJECTION_DATE_INDEX = 1; // 0x1
+    field public static final int QUERIES_PROJECTION_DISPLAY1_INDEX = 3; // 0x3
+    field public static final int QUERIES_PROJECTION_DISPLAY2_INDEX = 4; // 0x4
+    field public static final int QUERIES_PROJECTION_QUERY_INDEX = 2; // 0x2
+  }
+
+  public final class Settings {
+    ctor public Settings();
+    field public static final java.lang.String ACTION_ACCESSIBILITY_SETTINGS = "android.settings.ACCESSIBILITY_SETTINGS";
+    field public static final java.lang.String ACTION_ADD_ACCOUNT = "android.settings.ADD_ACCOUNT_SETTINGS";
+    field public static final java.lang.String ACTION_AIRPLANE_MODE_SETTINGS = "android.settings.AIRPLANE_MODE_SETTINGS";
+    field public static final java.lang.String ACTION_APN_SETTINGS = "android.settings.APN_SETTINGS";
+    field public static final java.lang.String ACTION_APPLICATION_DETAILS_SETTINGS = "android.settings.APPLICATION_DETAILS_SETTINGS";
+    field public static final java.lang.String ACTION_APPLICATION_DEVELOPMENT_SETTINGS = "android.settings.APPLICATION_DEVELOPMENT_SETTINGS";
+    field public static final java.lang.String ACTION_APPLICATION_SETTINGS = "android.settings.APPLICATION_SETTINGS";
+    field public static final java.lang.String ACTION_BLUETOOTH_SETTINGS = "android.settings.BLUETOOTH_SETTINGS";
+    field public static final java.lang.String ACTION_DATA_ROAMING_SETTINGS = "android.settings.DATA_ROAMING_SETTINGS";
+    field public static final java.lang.String ACTION_DATE_SETTINGS = "android.settings.DATE_SETTINGS";
+    field public static final java.lang.String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS";
+    field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
+    field public static final java.lang.String ACTION_INPUT_METHOD_SETTINGS = "android.settings.INPUT_METHOD_SETTINGS";
+    field public static final java.lang.String ACTION_INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
+    field public static final java.lang.String ACTION_INTERNAL_STORAGE_SETTINGS = "android.settings.INTERNAL_STORAGE_SETTINGS";
+    field public static final java.lang.String ACTION_LOCALE_SETTINGS = "android.settings.LOCALE_SETTINGS";
+    field public static final java.lang.String ACTION_LOCATION_SOURCE_SETTINGS = "android.settings.LOCATION_SOURCE_SETTINGS";
+    field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
+    field public static final java.lang.String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
+    field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
+    field public static final java.lang.String ACTION_NETWORK_OPERATOR_SETTINGS = "android.settings.NETWORK_OPERATOR_SETTINGS";
+    field public static final java.lang.String ACTION_NFCSHARING_SETTINGS = "android.settings.NFCSHARING_SETTINGS";
+    field public static final java.lang.String ACTION_NFC_SETTINGS = "android.settings.NFC_SETTINGS";
+    field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS";
+    field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS";
+    field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
+    field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS";
+    field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";
+    field public static final java.lang.String ACTION_SOUND_SETTINGS = "android.settings.SOUND_SETTINGS";
+    field public static final java.lang.String ACTION_SYNC_SETTINGS = "android.settings.SYNC_SETTINGS";
+    field public static final java.lang.String ACTION_USER_DICTIONARY_SETTINGS = "android.settings.USER_DICTIONARY_SETTINGS";
+    field public static final java.lang.String ACTION_WIFI_IP_SETTINGS = "android.settings.WIFI_IP_SETTINGS";
+    field public static final java.lang.String ACTION_WIFI_SETTINGS = "android.settings.WIFI_SETTINGS";
+    field public static final java.lang.String ACTION_WIRELESS_SETTINGS = "android.settings.WIRELESS_SETTINGS";
+    field public static final java.lang.String AUTHORITY = "settings";
+    field public static final java.lang.String EXTRA_AUTHORITIES = "authorities";
+    field public static final java.lang.String EXTRA_INPUT_METHOD_ID = "input_method_id";
+  }
+
+  public static final class Settings.Global extends android.provider.Settings.NameValueTable {
+    ctor public Settings.Global();
+    method public static float getFloat(android.content.ContentResolver, java.lang.String, float);
+    method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
+    method public static int getInt(android.content.ContentResolver, java.lang.String, int);
+    method public static int getInt(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
+    method public static long getLong(android.content.ContentResolver, java.lang.String, long);
+    method public static long getLong(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
+    method public static java.lang.String getString(android.content.ContentResolver, java.lang.String);
+    method public static android.net.Uri getUriFor(java.lang.String);
+    method public static boolean putFloat(android.content.ContentResolver, java.lang.String, float);
+    method public static boolean putInt(android.content.ContentResolver, java.lang.String, int);
+    method public static boolean putLong(android.content.ContentResolver, java.lang.String, long);
+    method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String);
+    field public static final java.lang.String ADB_ENABLED = "adb_enabled";
+    field public static final java.lang.String AIRPLANE_MODE_ON = "airplane_mode_on";
+    field public static final java.lang.String AIRPLANE_MODE_RADIOS = "airplane_mode_radios";
+    field public static final java.lang.String ALWAYS_FINISH_ACTIVITIES = "always_finish_activities";
+    field public static final java.lang.String ANIMATOR_DURATION_SCALE = "animator_duration_scale";
+    field public static final java.lang.String AUTO_TIME = "auto_time";
+    field public static final java.lang.String AUTO_TIME_ZONE = "auto_time_zone";
+    field public static final java.lang.String BLUETOOTH_ON = "bluetooth_on";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DATA_ROAMING = "data_roaming";
+    field public static final java.lang.String DEBUG_APP = "debug_app";
+    field public static final java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
+    field public static final java.lang.String DEVICE_PROVISIONED = "device_provisioned";
+    field public static final java.lang.String HTTP_PROXY = "http_proxy";
+    field public static final java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+    field public static final java.lang.String MODE_RINGER = "mode_ringer";
+    field public static final java.lang.String NETWORK_PREFERENCE = "network_preference";
+    field public static final java.lang.String RADIO_BLUETOOTH = "bluetooth";
+    field public static final java.lang.String RADIO_CELL = "cell";
+    field public static final java.lang.String RADIO_NFC = "nfc";
+    field public static final java.lang.String RADIO_WIFI = "wifi";
+    field public static final java.lang.String SHOW_PROCESSES = "show_processes";
+    field public static final java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
+    field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_global_version";
+    field public static final java.lang.String TRANSITION_ANIMATION_SCALE = "transition_animation_scale";
+    field public static final java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
+    field public static final java.lang.String USE_GOOGLE_MAIL = "use_google_mail";
+    field public static final java.lang.String WAIT_FOR_DEBUGGER = "wait_for_debugger";
+    field public static final java.lang.String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
+    field public static final java.lang.String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS = "wifi_mobile_data_transition_wakelock_timeout_ms";
+    field public static final java.lang.String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = "wifi_networks_available_notification_on";
+    field public static final java.lang.String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY = "wifi_networks_available_repeat_delay";
+    field public static final java.lang.String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
+    field public static final java.lang.String WIFI_ON = "wifi_on";
+    field public static final java.lang.String WIFI_SLEEP_POLICY = "wifi_sleep_policy";
+    field public static final int WIFI_SLEEP_POLICY_DEFAULT = 0; // 0x0
+    field public static final int WIFI_SLEEP_POLICY_NEVER = 2; // 0x2
+    field public static final int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED = 1; // 0x1
+    field public static final java.lang.String WIFI_WATCHDOG_ON = "wifi_watchdog_on";
+    field public static final java.lang.String WINDOW_ANIMATION_SCALE = "window_animation_scale";
+  }
+
+  public static class Settings.NameValueTable implements android.provider.BaseColumns {
+    ctor public Settings.NameValueTable();
+    method public static android.net.Uri getUriFor(android.net.Uri, java.lang.String);
+    method protected static boolean putString(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String);
+    field public static final java.lang.String NAME = "name";
+    field public static final java.lang.String VALUE = "value";
+  }
+
+  public static final class Settings.Secure extends android.provider.Settings.NameValueTable {
+    ctor public Settings.Secure();
+    method public static float getFloat(android.content.ContentResolver, java.lang.String, float);
+    method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
+    method public static int getInt(android.content.ContentResolver, java.lang.String, int);
+    method public static int getInt(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
+    method public static long getLong(android.content.ContentResolver, java.lang.String, long);
+    method public static long getLong(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
+    method public static java.lang.String getString(android.content.ContentResolver, java.lang.String);
+    method public static android.net.Uri getUriFor(java.lang.String);
+    method public static final boolean isLocationProviderEnabled(android.content.ContentResolver, java.lang.String);
+    method public static boolean putFloat(android.content.ContentResolver, java.lang.String, float);
+    method public static boolean putInt(android.content.ContentResolver, java.lang.String, int);
+    method public static boolean putLong(android.content.ContentResolver, java.lang.String, long);
+    method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String);
+    method public static final void setLocationProviderEnabled(android.content.ContentResolver, java.lang.String, boolean);
+    field public static final java.lang.String ACCESSIBILITY_ENABLED = "accessibility_enabled";
+    field public static final java.lang.String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
+    field public static final deprecated java.lang.String ADB_ENABLED = "adb_enabled";
+    field public static final java.lang.String ALLOWED_GEOLOCATION_ORIGINS = "allowed_geolocation_origins";
+    field public static final java.lang.String ALLOW_MOCK_LOCATION = "mock_location";
+    field public static final java.lang.String ANDROID_ID = "android_id";
+    field public static final deprecated java.lang.String BACKGROUND_DATA = "background_data";
+    field public static final deprecated java.lang.String BLUETOOTH_ON = "bluetooth_on";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final deprecated java.lang.String DATA_ROAMING = "data_roaming";
+    field public static final java.lang.String DEFAULT_INPUT_METHOD = "default_input_method";
+    field public static final deprecated java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
+    field public static final deprecated java.lang.String DEVICE_PROVISIONED = "device_provisioned";
+    field public static final java.lang.String ENABLED_ACCESSIBILITY_SERVICES = "enabled_accessibility_services";
+    field public static final java.lang.String ENABLED_INPUT_METHODS = "enabled_input_methods";
+    field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
+    field public static final java.lang.String INPUT_METHOD_SELECTOR_VISIBILITY = "input_method_selector_visibility";
+    field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+    field public static final java.lang.String LOCATION_PROVIDERS_ALLOWED = "location_providers_allowed";
+    field public static final java.lang.String LOCK_PATTERN_ENABLED = "lock_pattern_autolock";
+    field public static final deprecated java.lang.String LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED = "lock_pattern_tactile_feedback_enabled";
+    field public static final java.lang.String LOCK_PATTERN_VISIBLE = "lock_pattern_visible_pattern";
+    field public static final deprecated java.lang.String LOGGING_ID = "logging_id";
+    field public static final deprecated java.lang.String NETWORK_PREFERENCE = "network_preference";
+    field public static final java.lang.String PARENTAL_CONTROL_ENABLED = "parental_control_enabled";
+    field public static final java.lang.String PARENTAL_CONTROL_LAST_UPDATE = "parental_control_last_update";
+    field public static final java.lang.String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url";
+    field public static final java.lang.String SELECTED_INPUT_METHOD_SUBTYPE = "selected_input_method_subtype";
+    field public static final java.lang.String SETTINGS_CLASSNAME = "settings_classname";
+    field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version";
+    field public static final java.lang.String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled";
+    field public static final deprecated java.lang.String TTS_DEFAULT_COUNTRY = "tts_default_country";
+    field public static final deprecated java.lang.String TTS_DEFAULT_LANG = "tts_default_lang";
+    field public static final java.lang.String TTS_DEFAULT_PITCH = "tts_default_pitch";
+    field public static final java.lang.String TTS_DEFAULT_RATE = "tts_default_rate";
+    field public static final java.lang.String TTS_DEFAULT_SYNTH = "tts_default_synth";
+    field public static final deprecated java.lang.String TTS_DEFAULT_VARIANT = "tts_default_variant";
+    field public static final java.lang.String TTS_ENABLED_PLUGINS = "tts_enabled_plugins";
+    field public static final deprecated java.lang.String TTS_USE_DEFAULTS = "tts_use_defaults";
+    field public static final deprecated java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
+    field public static final deprecated java.lang.String USE_GOOGLE_MAIL = "use_google_mail";
+    field public static final deprecated java.lang.String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
+    field public static final deprecated java.lang.String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS = "wifi_mobile_data_transition_wakelock_timeout_ms";
+    field public static final deprecated java.lang.String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = "wifi_networks_available_notification_on";
+    field public static final deprecated java.lang.String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY = "wifi_networks_available_repeat_delay";
+    field public static final deprecated java.lang.String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
+    field public static final deprecated java.lang.String WIFI_ON = "wifi_on";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE = "wifi_watchdog_acceptable_packet_loss_percentage";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_AP_COUNT = "wifi_watchdog_ap_count";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS = "wifi_watchdog_background_check_delay_ms";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED = "wifi_watchdog_background_check_enabled";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS = "wifi_watchdog_background_check_timeout_ms";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT = "wifi_watchdog_initial_ignored_ping_count";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_MAX_AP_CHECKS = "wifi_watchdog_max_ap_checks";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_ON = "wifi_watchdog_on";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_COUNT = "wifi_watchdog_ping_count";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_DELAY_MS = "wifi_watchdog_ping_delay_ms";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_TIMEOUT_MS = "wifi_watchdog_ping_timeout_ms";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_WATCH_LIST = "wifi_watchdog_watch_list";
+  }
+
+  public static class Settings.SettingNotFoundException extends android.util.AndroidException {
+    ctor public Settings.SettingNotFoundException(java.lang.String);
+  }
+
+  public static final class Settings.System extends android.provider.Settings.NameValueTable {
+    ctor public Settings.System();
+    method public static void getConfiguration(android.content.ContentResolver, android.content.res.Configuration);
+    method public static float getFloat(android.content.ContentResolver, java.lang.String, float);
+    method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
+    method public static int getInt(android.content.ContentResolver, java.lang.String, int);
+    method public static int getInt(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
+    method public static long getLong(android.content.ContentResolver, java.lang.String, long);
+    method public static long getLong(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
+    method public static deprecated boolean getShowGTalkServiceStatus(android.content.ContentResolver);
+    method public static java.lang.String getString(android.content.ContentResolver, java.lang.String);
+    method public static android.net.Uri getUriFor(java.lang.String);
+    method public static boolean putConfiguration(android.content.ContentResolver, android.content.res.Configuration);
+    method public static boolean putFloat(android.content.ContentResolver, java.lang.String, float);
+    method public static boolean putInt(android.content.ContentResolver, java.lang.String, int);
+    method public static boolean putLong(android.content.ContentResolver, java.lang.String, long);
+    method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String);
+    method public static deprecated void setShowGTalkServiceStatus(android.content.ContentResolver, boolean);
+    field public static final java.lang.String ACCELEROMETER_ROTATION = "accelerometer_rotation";
+    field public static final deprecated java.lang.String ADB_ENABLED = "adb_enabled";
+    field public static final deprecated java.lang.String AIRPLANE_MODE_ON = "airplane_mode_on";
+    field public static final deprecated java.lang.String AIRPLANE_MODE_RADIOS = "airplane_mode_radios";
+    field public static final java.lang.String ALARM_ALERT = "alarm_alert";
+    field public static final deprecated java.lang.String ALWAYS_FINISH_ACTIVITIES = "always_finish_activities";
+    field public static final deprecated java.lang.String ANDROID_ID = "android_id";
+    field public static final deprecated java.lang.String ANIMATOR_DURATION_SCALE = "animator_duration_scale";
+    field public static final java.lang.String APPEND_FOR_LAST_AUDIBLE = "_last_audible";
+    field public static final deprecated java.lang.String AUTO_TIME = "auto_time";
+    field public static final deprecated java.lang.String AUTO_TIME_ZONE = "auto_time_zone";
+    field public static final java.lang.String BLUETOOTH_DISCOVERABILITY = "bluetooth_discoverability";
+    field public static final java.lang.String BLUETOOTH_DISCOVERABILITY_TIMEOUT = "bluetooth_discoverability_timeout";
+    field public static final deprecated java.lang.String BLUETOOTH_ON = "bluetooth_on";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final deprecated java.lang.String DATA_ROAMING = "data_roaming";
+    field public static final java.lang.String DATE_FORMAT = "date_format";
+    field public static final deprecated java.lang.String DEBUG_APP = "debug_app";
+    field public static final android.net.Uri DEFAULT_ALARM_ALERT_URI;
+    field public static final android.net.Uri DEFAULT_NOTIFICATION_URI;
+    field public static final android.net.Uri DEFAULT_RINGTONE_URI;
+    field public static final deprecated java.lang.String DEVICE_PROVISIONED = "device_provisioned";
+    field public static final deprecated java.lang.String DIM_SCREEN = "dim_screen";
+    field public static final java.lang.String DTMF_TONE_WHEN_DIALING = "dtmf_tone";
+    field public static final java.lang.String END_BUTTON_BEHAVIOR = "end_button_behavior";
+    field public static final java.lang.String FONT_SCALE = "font_scale";
+    field public static final java.lang.String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
+    field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
+    field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+    field public static final deprecated java.lang.String LOCATION_PROVIDERS_ALLOWED = "location_providers_allowed";
+    field public static final deprecated java.lang.String LOCK_PATTERN_ENABLED = "lock_pattern_autolock";
+    field public static final deprecated java.lang.String LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED = "lock_pattern_tactile_feedback_enabled";
+    field public static final deprecated java.lang.String LOCK_PATTERN_VISIBLE = "lock_pattern_visible_pattern";
+    field public static final deprecated java.lang.String LOGGING_ID = "logging_id";
+    field public static final deprecated java.lang.String MODE_RINGER = "mode_ringer";
+    field public static final java.lang.String MODE_RINGER_STREAMS_AFFECTED = "mode_ringer_streams_affected";
+    field public static final java.lang.String MUTE_STREAMS_AFFECTED = "mute_streams_affected";
+    field public static final deprecated java.lang.String NETWORK_PREFERENCE = "network_preference";
+    field public static final java.lang.String NEXT_ALARM_FORMATTED = "next_alarm_formatted";
+    field public static final java.lang.String NOTIFICATION_SOUND = "notification_sound";
+    field public static final deprecated java.lang.String PARENTAL_CONTROL_ENABLED = "parental_control_enabled";
+    field public static final deprecated java.lang.String PARENTAL_CONTROL_LAST_UPDATE = "parental_control_last_update";
+    field public static final deprecated java.lang.String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url";
+    field public static final deprecated java.lang.String RADIO_BLUETOOTH = "bluetooth";
+    field public static final deprecated java.lang.String RADIO_CELL = "cell";
+    field public static final deprecated java.lang.String RADIO_NFC = "nfc";
+    field public static final deprecated java.lang.String RADIO_WIFI = "wifi";
+    field public static final java.lang.String RINGTONE = "ringtone";
+    field public static final java.lang.String SCREEN_BRIGHTNESS = "screen_brightness";
+    field public static final java.lang.String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
+    field public static final int SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1; // 0x1
+    field public static final int SCREEN_BRIGHTNESS_MODE_MANUAL = 0; // 0x0
+    field public static final java.lang.String SCREEN_OFF_TIMEOUT = "screen_off_timeout";
+    field public static final deprecated java.lang.String SETTINGS_CLASSNAME = "settings_classname";
+    field public static final java.lang.String SETUP_WIZARD_HAS_RUN = "setup_wizard_has_run";
+    field public static final java.lang.String SHOW_GTALK_SERVICE_STATUS = "SHOW_GTALK_SERVICE_STATUS";
+    field public static final deprecated java.lang.String SHOW_PROCESSES = "show_processes";
+    field public static final deprecated java.lang.String SHOW_WEB_SUGGESTIONS = "show_web_suggestions";
+    field public static final java.lang.String SOUND_EFFECTS_ENABLED = "sound_effects_enabled";
+    field public static final deprecated java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
+    field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_system_version";
+    field public static final java.lang.String TEXT_AUTO_CAPS = "auto_caps";
+    field public static final java.lang.String TEXT_AUTO_PUNCTUATE = "auto_punctuate";
+    field public static final java.lang.String TEXT_AUTO_REPLACE = "auto_replace";
+    field public static final java.lang.String TEXT_SHOW_PASSWORD = "show_password";
+    field public static final java.lang.String TIME_12_24 = "time_12_24";
+    field public static final deprecated java.lang.String TRANSITION_ANIMATION_SCALE = "transition_animation_scale";
+    field public static final deprecated java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
+    field public static final java.lang.String USER_ROTATION = "user_rotation";
+    field public static final deprecated java.lang.String USE_GOOGLE_MAIL = "use_google_mail";
+    field public static final java.lang.String VIBRATE_ON = "vibrate_on";
+    field public static final java.lang.String VOLUME_ALARM = "volume_alarm";
+    field public static final java.lang.String VOLUME_BLUETOOTH_SCO = "volume_bluetooth_sco";
+    field public static final java.lang.String VOLUME_MUSIC = "volume_music";
+    field public static final java.lang.String VOLUME_NOTIFICATION = "volume_notification";
+    field public static final java.lang.String VOLUME_RING = "volume_ring";
+    field public static final java.lang.String[] VOLUME_SETTINGS;
+    field public static final java.lang.String VOLUME_SYSTEM = "volume_system";
+    field public static final java.lang.String VOLUME_VOICE = "volume_voice";
+    field public static final deprecated java.lang.String WAIT_FOR_DEBUGGER = "wait_for_debugger";
+    field public static final deprecated java.lang.String WALLPAPER_ACTIVITY = "wallpaper_activity";
+    field public static final deprecated java.lang.String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
+    field public static final deprecated java.lang.String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS = "wifi_mobile_data_transition_wakelock_timeout_ms";
+    field public static final deprecated java.lang.String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = "wifi_networks_available_notification_on";
+    field public static final deprecated java.lang.String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY = "wifi_networks_available_repeat_delay";
+    field public static final deprecated java.lang.String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
+    field public static final deprecated java.lang.String WIFI_ON = "wifi_on";
+    field public static final deprecated java.lang.String WIFI_SLEEP_POLICY = "wifi_sleep_policy";
+    field public static final deprecated int WIFI_SLEEP_POLICY_DEFAULT = 0; // 0x0
+    field public static final deprecated int WIFI_SLEEP_POLICY_NEVER = 2; // 0x2
+    field public static final deprecated int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED = 1; // 0x1
+    field public static final deprecated java.lang.String WIFI_STATIC_DNS1 = "wifi_static_dns1";
+    field public static final deprecated java.lang.String WIFI_STATIC_DNS2 = "wifi_static_dns2";
+    field public static final deprecated java.lang.String WIFI_STATIC_GATEWAY = "wifi_static_gateway";
+    field public static final deprecated java.lang.String WIFI_STATIC_IP = "wifi_static_ip";
+    field public static final deprecated java.lang.String WIFI_STATIC_NETMASK = "wifi_static_netmask";
+    field public static final deprecated java.lang.String WIFI_USE_STATIC_IP = "wifi_use_static_ip";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE = "wifi_watchdog_acceptable_packet_loss_percentage";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_AP_COUNT = "wifi_watchdog_ap_count";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS = "wifi_watchdog_background_check_delay_ms";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED = "wifi_watchdog_background_check_enabled";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS = "wifi_watchdog_background_check_timeout_ms";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT = "wifi_watchdog_initial_ignored_ping_count";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_MAX_AP_CHECKS = "wifi_watchdog_max_ap_checks";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_ON = "wifi_watchdog_on";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_COUNT = "wifi_watchdog_ping_count";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_DELAY_MS = "wifi_watchdog_ping_delay_ms";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_TIMEOUT_MS = "wifi_watchdog_ping_timeout_ms";
+    field public static final deprecated java.lang.String WINDOW_ANIMATION_SCALE = "window_animation_scale";
+  }
+
+  public class SyncStateContract {
+    ctor public SyncStateContract();
+  }
+
+  public static abstract interface SyncStateContract.Columns implements android.provider.BaseColumns {
+    field public static final java.lang.String ACCOUNT_NAME = "account_name";
+    field public static final java.lang.String ACCOUNT_TYPE = "account_type";
+    field public static final java.lang.String DATA = "data";
+  }
+
+  public static class SyncStateContract.Constants implements android.provider.SyncStateContract.Columns {
+    ctor public SyncStateContract.Constants();
+    field public static final java.lang.String CONTENT_DIRECTORY = "syncstate";
+  }
+
+  public static final class SyncStateContract.Helpers {
+    ctor public SyncStateContract.Helpers();
+    method public static byte[] get(android.content.ContentProviderClient, android.net.Uri, android.accounts.Account) throws android.os.RemoteException;
+    method public static android.util.Pair<android.net.Uri, byte[]> getWithUri(android.content.ContentProviderClient, android.net.Uri, android.accounts.Account) throws android.os.RemoteException;
+    method public static android.net.Uri insert(android.content.ContentProviderClient, android.net.Uri, android.accounts.Account, byte[]) throws android.os.RemoteException;
+    method public static android.content.ContentProviderOperation newSetOperation(android.net.Uri, android.accounts.Account, byte[]);
+    method public static android.content.ContentProviderOperation newUpdateOperation(android.net.Uri, byte[]);
+    method public static void set(android.content.ContentProviderClient, android.net.Uri, android.accounts.Account, byte[]) throws android.os.RemoteException;
+    method public static void update(android.content.ContentProviderClient, android.net.Uri, byte[]) throws android.os.RemoteException;
+  }
+
+  public class UserDictionary {
+    ctor public UserDictionary();
+    field public static final java.lang.String AUTHORITY = "user_dictionary";
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  public static class UserDictionary.Words implements android.provider.BaseColumns {
+    ctor public UserDictionary.Words();
+    method public static deprecated void addWord(android.content.Context, java.lang.String, int, int);
+    method public static void addWord(android.content.Context, java.lang.String, int, java.lang.String, java.util.Locale);
+    field public static final java.lang.String APP_ID = "appid";
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.google.userword";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.userword";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "frequency DESC";
+    field public static final java.lang.String FREQUENCY = "frequency";
+    field public static final java.lang.String LOCALE = "locale";
+    field public static final deprecated int LOCALE_TYPE_ALL = 0; // 0x0
+    field public static final deprecated int LOCALE_TYPE_CURRENT = 1; // 0x1
+    field public static final java.lang.String SHORTCUT = "shortcut";
+    field public static final java.lang.String WORD = "word";
+    field public static final java.lang.String _ID = "_id";
+  }
+
+  public class VoicemailContract {
+    field public static final java.lang.String ACTION_FETCH_VOICEMAIL = "android.intent.action.FETCH_VOICEMAIL";
+    field public static final java.lang.String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
+    field public static final java.lang.String AUTHORITY = "com.android.voicemail";
+    field public static final java.lang.String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
+    field public static final java.lang.String PARAM_KEY_SOURCE_PACKAGE = "source_package";
+  }
+
+  public static final class VoicemailContract.Status implements android.provider.BaseColumns {
+    method public static android.net.Uri buildSourceUri(java.lang.String);
+    field public static final java.lang.String CONFIGURATION_STATE = "configuration_state";
+    field public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2; // 0x2
+    field public static final int CONFIGURATION_STATE_NOT_CONFIGURED = 1; // 0x1
+    field public static final int CONFIGURATION_STATE_OK = 0; // 0x0
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DATA_CHANNEL_STATE = "data_channel_state";
+    field public static final int DATA_CHANNEL_STATE_NO_CONNECTION = 1; // 0x1
+    field public static final int DATA_CHANNEL_STATE_OK = 0; // 0x0
+    field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemail.source.status";
+    field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail.source.status";
+    field public static final java.lang.String NOTIFICATION_CHANNEL_STATE = "notification_channel_state";
+    field public static final int NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING = 2; // 0x2
+    field public static final int NOTIFICATION_CHANNEL_STATE_NO_CONNECTION = 1; // 0x1
+    field public static final int NOTIFICATION_CHANNEL_STATE_OK = 0; // 0x0
+    field public static final java.lang.String SETTINGS_URI = "settings_uri";
+    field public static final java.lang.String SOURCE_PACKAGE = "source_package";
+    field public static final java.lang.String VOICEMAIL_ACCESS_URI = "voicemail_access_uri";
+  }
+
+  public static final class VoicemailContract.Voicemails implements android.provider.BaseColumns android.provider.OpenableColumns {
+    method public static android.net.Uri buildSourceUri(java.lang.String);
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DATE = "date";
+    field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemails";
+    field public static final java.lang.String DURATION = "duration";
+    field public static final java.lang.String HAS_CONTENT = "has_content";
+    field public static final java.lang.String IS_READ = "is_read";
+    field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail";
+    field public static final java.lang.String MIME_TYPE = "mime_type";
+    field public static final java.lang.String NUMBER = "number";
+    field public static final java.lang.String SOURCE_DATA = "source_data";
+    field public static final java.lang.String SOURCE_PACKAGE = "source_package";
+  }
+
+}
+
+package android.renderscript {
+
+  public class Allocation extends android.renderscript.BaseObj {
+    method public void copy1DRangeFrom(int, int, int[]);
+    method public void copy1DRangeFrom(int, int, short[]);
+    method public void copy1DRangeFrom(int, int, byte[]);
+    method public void copy1DRangeFrom(int, int, float[]);
+    method public void copy1DRangeFrom(int, int, android.renderscript.Allocation, int);
+    method public void copy1DRangeFromUnchecked(int, int, int[]);
+    method public void copy1DRangeFromUnchecked(int, int, short[]);
+    method public void copy1DRangeFromUnchecked(int, int, byte[]);
+    method public void copy1DRangeFromUnchecked(int, int, float[]);
+    method public void copy2DRangeFrom(int, int, int, int, byte[]);
+    method public void copy2DRangeFrom(int, int, int, int, short[]);
+    method public void copy2DRangeFrom(int, int, int, int, int[]);
+    method public void copy2DRangeFrom(int, int, int, int, float[]);
+    method public void copy2DRangeFrom(int, int, int, int, android.renderscript.Allocation, int, int);
+    method public void copy2DRangeFrom(int, int, android.graphics.Bitmap);
+    method public void copyFrom(android.renderscript.BaseObj[]);
+    method public void copyFrom(int[]);
+    method public void copyFrom(short[]);
+    method public void copyFrom(byte[]);
+    method public void copyFrom(float[]);
+    method public void copyFrom(android.graphics.Bitmap);
+    method public void copyFromUnchecked(int[]);
+    method public void copyFromUnchecked(short[]);
+    method public void copyFromUnchecked(byte[]);
+    method public void copyFromUnchecked(float[]);
+    method public void copyTo(android.graphics.Bitmap);
+    method public void copyTo(byte[]);
+    method public void copyTo(short[]);
+    method public void copyTo(int[]);
+    method public void copyTo(float[]);
+    method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
+    method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap);
+    method public static android.renderscript.Allocation createCubemapFromCubeFaces(android.renderscript.RenderScript, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
+    method public static android.renderscript.Allocation createCubemapFromCubeFaces(android.renderscript.RenderScript, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap);
+    method public static android.renderscript.Allocation createFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
+    method public static android.renderscript.Allocation createFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap);
+    method public static android.renderscript.Allocation createFromBitmapResource(android.renderscript.RenderScript, android.content.res.Resources, int, android.renderscript.Allocation.MipmapControl, int);
+    method public static android.renderscript.Allocation createFromBitmapResource(android.renderscript.RenderScript, android.content.res.Resources, int);
+    method public static android.renderscript.Allocation createFromString(android.renderscript.RenderScript, java.lang.String, int);
+    method public static android.renderscript.Allocation createSized(android.renderscript.RenderScript, android.renderscript.Element, int, int);
+    method public static android.renderscript.Allocation createSized(android.renderscript.RenderScript, android.renderscript.Element, int);
+    method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type, android.renderscript.Allocation.MipmapControl, int);
+    method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type, int);
+    method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type);
+    method public void generateMipmaps();
+    method public int getBytesSize();
+    method public android.renderscript.Element getElement();
+    method public android.view.Surface getSurface();
+    method public android.renderscript.Type getType();
+    method public int getUsage();
+    method public void ioReceive();
+    method public void ioSend();
+    method public synchronized void resize(int);
+    method public void setFromFieldPacker(int, android.renderscript.FieldPacker);
+    method public void setFromFieldPacker(int, int, android.renderscript.FieldPacker);
+    method public void setSurface(android.view.Surface);
+    method public void syncAll(int);
+    field public static final int USAGE_GRAPHICS_CONSTANTS = 8; // 0x8
+    field public static final int USAGE_GRAPHICS_RENDER_TARGET = 16; // 0x10
+    field public static final int USAGE_GRAPHICS_TEXTURE = 2; // 0x2
+    field public static final int USAGE_GRAPHICS_VERTEX = 4; // 0x4
+    field public static final int USAGE_IO_INPUT = 32; // 0x20
+    field public static final int USAGE_IO_OUTPUT = 64; // 0x40
+    field public static final int USAGE_SCRIPT = 1; // 0x1
+  }
+
+  public static final class Allocation.MipmapControl extends java.lang.Enum {
+    method public static android.renderscript.Allocation.MipmapControl valueOf(java.lang.String);
+    method public static final android.renderscript.Allocation.MipmapControl[] values();
+    enum_constant public static final android.renderscript.Allocation.MipmapControl MIPMAP_FULL;
+    enum_constant public static final android.renderscript.Allocation.MipmapControl MIPMAP_NONE;
+    enum_constant public static final android.renderscript.Allocation.MipmapControl MIPMAP_ON_SYNC_TO_TEXTURE;
+  }
+
+  public class AllocationAdapter extends android.renderscript.Allocation {
+    method public static android.renderscript.AllocationAdapter create1D(android.renderscript.RenderScript, android.renderscript.Allocation);
+    method public static android.renderscript.AllocationAdapter create2D(android.renderscript.RenderScript, android.renderscript.Allocation);
+    method public void setFace(android.renderscript.Type.CubemapFace);
+    method public void setLOD(int);
+    method public void setY(int);
+    method public void setZ(int);
+  }
+
+  public class BaseObj {
+    method public synchronized void destroy();
+    method public java.lang.String getName();
+    method public void setName(java.lang.String);
+  }
+
+  public class Byte2 {
+    ctor public Byte2();
+    ctor public Byte2(byte, byte);
+    field public byte x;
+    field public byte y;
+  }
+
+  public class Byte3 {
+    ctor public Byte3();
+    ctor public Byte3(byte, byte, byte);
+    field public byte x;
+    field public byte y;
+    field public byte z;
+  }
+
+  public class Byte4 {
+    ctor public Byte4();
+    ctor public Byte4(byte, byte, byte, byte);
+    field public byte w;
+    field public byte x;
+    field public byte y;
+    field public byte z;
+  }
+
+  public class Double2 {
+    ctor public Double2();
+    ctor public Double2(double, double);
+    field public double x;
+    field public double y;
+  }
+
+  public class Double3 {
+    ctor public Double3();
+    ctor public Double3(double, double, double);
+    field public double x;
+    field public double y;
+    field public double z;
+  }
+
+  public class Double4 {
+    ctor public Double4();
+    ctor public Double4(double, double, double, double);
+    field public double w;
+    field public double x;
+    field public double y;
+    field public double z;
+  }
+
+  public class Element extends android.renderscript.BaseObj {
+    method public static android.renderscript.Element ALLOCATION(android.renderscript.RenderScript);
+    method public static android.renderscript.Element A_8(android.renderscript.RenderScript);
+    method public static android.renderscript.Element BOOLEAN(android.renderscript.RenderScript);
+    method public static android.renderscript.Element ELEMENT(android.renderscript.RenderScript);
+    method public static android.renderscript.Element F32(android.renderscript.RenderScript);
+    method public static android.renderscript.Element F32_2(android.renderscript.RenderScript);
+    method public static android.renderscript.Element F32_3(android.renderscript.RenderScript);
+    method public static android.renderscript.Element F32_4(android.renderscript.RenderScript);
+    method public static android.renderscript.Element F64(android.renderscript.RenderScript);
+    method public static android.renderscript.Element F64_2(android.renderscript.RenderScript);
+    method public static android.renderscript.Element F64_3(android.renderscript.RenderScript);
+    method public static android.renderscript.Element F64_4(android.renderscript.RenderScript);
+    method public static android.renderscript.Element FONT(android.renderscript.RenderScript);
+    method public static android.renderscript.Element I16(android.renderscript.RenderScript);
+    method public static android.renderscript.Element I16_2(android.renderscript.RenderScript);
+    method public static android.renderscript.Element I16_3(android.renderscript.RenderScript);
+    method public static android.renderscript.Element I16_4(android.renderscript.RenderScript);
+    method public static android.renderscript.Element I32(android.renderscript.RenderScript);
+    method public static android.renderscript.Element I32_2(android.renderscript.RenderScript);
+    method public static android.renderscript.Element I32_3(android.renderscript.RenderScript);
+    method public static android.renderscript.Element I32_4(android.renderscript.RenderScript);
+    method public static android.renderscript.Element I64(android.renderscript.RenderScript);
+    method public static android.renderscript.Element I64_2(android.renderscript.RenderScript);
+    method public static android.renderscript.Element I64_3(android.renderscript.RenderScript);
+    method public static android.renderscript.Element I64_4(android.renderscript.RenderScript);
+    method public static android.renderscript.Element I8(android.renderscript.RenderScript);
+    method public static android.renderscript.Element I8_2(android.renderscript.RenderScript);
+    method public static android.renderscript.Element I8_3(android.renderscript.RenderScript);
+    method public static android.renderscript.Element I8_4(android.renderscript.RenderScript);
+    method public static deprecated android.renderscript.Element MATRIX4X4(android.renderscript.RenderScript);
+    method public static android.renderscript.Element MATRIX_2X2(android.renderscript.RenderScript);
+    method public static android.renderscript.Element MATRIX_3X3(android.renderscript.RenderScript);
+    method public static android.renderscript.Element MATRIX_4X4(android.renderscript.RenderScript);
+    method public static android.renderscript.Element MESH(android.renderscript.RenderScript);
+    method public static android.renderscript.Element PROGRAM_FRAGMENT(android.renderscript.RenderScript);
+    method public static android.renderscript.Element PROGRAM_RASTER(android.renderscript.RenderScript);
+    method public static android.renderscript.Element PROGRAM_STORE(android.renderscript.RenderScript);
+    method public static android.renderscript.Element PROGRAM_VERTEX(android.renderscript.RenderScript);
+    method public static android.renderscript.Element RGBA_4444(android.renderscript.RenderScript);
+    method public static android.renderscript.Element RGBA_5551(android.renderscript.RenderScript);
+    method public static android.renderscript.Element RGBA_8888(android.renderscript.RenderScript);
+    method public static android.renderscript.Element RGB_565(android.renderscript.RenderScript);
+    method public static android.renderscript.Element RGB_888(android.renderscript.RenderScript);
+    method public static android.renderscript.Element SAMPLER(android.renderscript.RenderScript);
+    method public static android.renderscript.Element SCRIPT(android.renderscript.RenderScript);
+    method public static android.renderscript.Element TYPE(android.renderscript.RenderScript);
+    method public static android.renderscript.Element U16(android.renderscript.RenderScript);
+    method public static android.renderscript.Element U16_2(android.renderscript.RenderScript);
+    method public static android.renderscript.Element U16_3(android.renderscript.RenderScript);
+    method public static android.renderscript.Element U16_4(android.renderscript.RenderScript);
+    method public static android.renderscript.Element U32(android.renderscript.RenderScript);
+    method public static android.renderscript.Element U32_2(android.renderscript.RenderScript);
+    method public static android.renderscript.Element U32_3(android.renderscript.RenderScript);
+    method public static android.renderscript.Element U32_4(android.renderscript.RenderScript);
+    method public static android.renderscript.Element U64(android.renderscript.RenderScript);
+    method public static android.renderscript.Element U64_2(android.renderscript.RenderScript);
+    method public static android.renderscript.Element U64_3(android.renderscript.RenderScript);
+    method public static android.renderscript.Element U64_4(android.renderscript.RenderScript);
+    method public static android.renderscript.Element U8(android.renderscript.RenderScript);
+    method public static android.renderscript.Element U8_2(android.renderscript.RenderScript);
+    method public static android.renderscript.Element U8_3(android.renderscript.RenderScript);
+    method public static android.renderscript.Element U8_4(android.renderscript.RenderScript);
+    method public static android.renderscript.Element createPixel(android.renderscript.RenderScript, android.renderscript.Element.DataType, android.renderscript.Element.DataKind);
+    method public static android.renderscript.Element createVector(android.renderscript.RenderScript, android.renderscript.Element.DataType, int);
+    method public int getBytesSize();
+    method public android.renderscript.Element.DataKind getDataKind();
+    method public android.renderscript.Element.DataType getDataType();
+    method public android.renderscript.Element getSubElement(int);
+    method public int getSubElementArraySize(int);
+    method public int getSubElementCount();
+    method public java.lang.String getSubElementName(int);
+    method public int getSubElementOffsetBytes(int);
+    method public int getVectorSize();
+    method public boolean isCompatible(android.renderscript.Element);
+    method public boolean isComplex();
+  }
+
+  public static class Element.Builder {
+    ctor public Element.Builder(android.renderscript.RenderScript);
+    method public android.renderscript.Element.Builder add(android.renderscript.Element, java.lang.String, int);
+    method public android.renderscript.Element.Builder add(android.renderscript.Element, java.lang.String);
+    method public android.renderscript.Element create();
+  }
+
+  public static final class Element.DataKind extends java.lang.Enum {
+    method public static android.renderscript.Element.DataKind valueOf(java.lang.String);
+    method public static final android.renderscript.Element.DataKind[] values();
+    enum_constant public static final android.renderscript.Element.DataKind PIXEL_A;
+    enum_constant public static final android.renderscript.Element.DataKind PIXEL_DEPTH;
+    enum_constant public static final android.renderscript.Element.DataKind PIXEL_L;
+    enum_constant public static final android.renderscript.Element.DataKind PIXEL_LA;
+    enum_constant public static final android.renderscript.Element.DataKind PIXEL_RGB;
+    enum_constant public static final android.renderscript.Element.DataKind PIXEL_RGBA;
+    enum_constant public static final android.renderscript.Element.DataKind USER;
+  }
+
+  public static final class Element.DataType extends java.lang.Enum {
+    method public static android.renderscript.Element.DataType valueOf(java.lang.String);
+    method public static final android.renderscript.Element.DataType[] values();
+    enum_constant public static final android.renderscript.Element.DataType BOOLEAN;
+    enum_constant public static final android.renderscript.Element.DataType FLOAT_32;
+    enum_constant public static final android.renderscript.Element.DataType FLOAT_64;
+    enum_constant public static final android.renderscript.Element.DataType MATRIX_2X2;
+    enum_constant public static final android.renderscript.Element.DataType MATRIX_3X3;
+    enum_constant public static final android.renderscript.Element.DataType MATRIX_4X4;
+    enum_constant public static final android.renderscript.Element.DataType NONE;
+    enum_constant public static final android.renderscript.Element.DataType RS_ALLOCATION;
+    enum_constant public static final android.renderscript.Element.DataType RS_ELEMENT;
+    enum_constant public static final android.renderscript.Element.DataType RS_FONT;
+    enum_constant public static final android.renderscript.Element.DataType RS_MESH;
+    enum_constant public static final android.renderscript.Element.DataType RS_PROGRAM_FRAGMENT;
+    enum_constant public static final android.renderscript.Element.DataType RS_PROGRAM_RASTER;
+    enum_constant public static final android.renderscript.Element.DataType RS_PROGRAM_STORE;
+    enum_constant public static final android.renderscript.Element.DataType RS_PROGRAM_VERTEX;
+    enum_constant public static final android.renderscript.Element.DataType RS_SAMPLER;
+    enum_constant public static final android.renderscript.Element.DataType RS_SCRIPT;
+    enum_constant public static final android.renderscript.Element.DataType RS_TYPE;
+    enum_constant public static final android.renderscript.Element.DataType SIGNED_16;
+    enum_constant public static final android.renderscript.Element.DataType SIGNED_32;
+    enum_constant public static final android.renderscript.Element.DataType SIGNED_64;
+    enum_constant public static final android.renderscript.Element.DataType SIGNED_8;
+    enum_constant public static final android.renderscript.Element.DataType UNSIGNED_16;
+    enum_constant public static final android.renderscript.Element.DataType UNSIGNED_32;
+    enum_constant public static final android.renderscript.Element.DataType UNSIGNED_4_4_4_4;
+    enum_constant public static final android.renderscript.Element.DataType UNSIGNED_5_5_5_1;
+    enum_constant public static final android.renderscript.Element.DataType UNSIGNED_5_6_5;
+    enum_constant public static final android.renderscript.Element.DataType UNSIGNED_64;
+    enum_constant public static final android.renderscript.Element.DataType UNSIGNED_8;
+  }
+
+  public class FieldPacker {
+    ctor public FieldPacker(int);
+    method public void addBoolean(boolean);
+    method public void addF32(float);
+    method public void addF32(android.renderscript.Float2);
+    method public void addF32(android.renderscript.Float3);
+    method public void addF32(android.renderscript.Float4);
+    method public void addF64(double);
+    method public void addF64(android.renderscript.Double2);
+    method public void addF64(android.renderscript.Double3);
+    method public void addF64(android.renderscript.Double4);
+    method public void addI16(short);
+    method public void addI16(android.renderscript.Short2);
+    method public void addI16(android.renderscript.Short3);
+    method public void addI16(android.renderscript.Short4);
+    method public void addI32(int);
+    method public void addI32(android.renderscript.Int2);
+    method public void addI32(android.renderscript.Int3);
+    method public void addI32(android.renderscript.Int4);
+    method public void addI64(long);
+    method public void addI64(android.renderscript.Long2);
+    method public void addI64(android.renderscript.Long3);
+    method public void addI64(android.renderscript.Long4);
+    method public void addI8(byte);
+    method public void addI8(android.renderscript.Byte2);
+    method public void addI8(android.renderscript.Byte3);
+    method public void addI8(android.renderscript.Byte4);
+    method public void addMatrix(android.renderscript.Matrix4f);
+    method public void addMatrix(android.renderscript.Matrix3f);
+    method public void addMatrix(android.renderscript.Matrix2f);
+    method public void addObj(android.renderscript.BaseObj);
+    method public void addU16(int);
+    method public void addU16(android.renderscript.Int2);
+    method public void addU16(android.renderscript.Int3);
+    method public void addU16(android.renderscript.Int4);
+    method public void addU32(long);
+    method public void addU32(android.renderscript.Long2);
+    method public void addU32(android.renderscript.Long3);
+    method public void addU32(android.renderscript.Long4);
+    method public void addU64(long);
+    method public void addU64(android.renderscript.Long2);
+    method public void addU64(android.renderscript.Long3);
+    method public void addU64(android.renderscript.Long4);
+    method public void addU8(short);
+    method public void addU8(android.renderscript.Short2);
+    method public void addU8(android.renderscript.Short3);
+    method public void addU8(android.renderscript.Short4);
+    method public void align(int);
+    method public final byte[] getData();
+    method public void reset();
+    method public void reset(int);
+    method public void skip(int);
+  }
+
+  public deprecated class FileA3D extends android.renderscript.BaseObj {
+    method public static deprecated android.renderscript.FileA3D createFromAsset(android.renderscript.RenderScript, android.content.res.AssetManager, java.lang.String);
+    method public static deprecated android.renderscript.FileA3D createFromFile(android.renderscript.RenderScript, java.lang.String);
+    method public static deprecated android.renderscript.FileA3D createFromFile(android.renderscript.RenderScript, java.io.File);
+    method public static deprecated android.renderscript.FileA3D createFromResource(android.renderscript.RenderScript, android.content.res.Resources, int);
+    method public deprecated android.renderscript.FileA3D.IndexEntry getIndexEntry(int);
+    method public deprecated int getIndexEntryCount();
+  }
+
+  public static final deprecated class FileA3D.EntryType extends java.lang.Enum {
+    method public static android.renderscript.FileA3D.EntryType valueOf(java.lang.String);
+    method public static final android.renderscript.FileA3D.EntryType[] values();
+    enum_constant public static final deprecated android.renderscript.FileA3D.EntryType MESH;
+    enum_constant public static final deprecated android.renderscript.FileA3D.EntryType UNKNOWN;
+  }
+
+  public static deprecated class FileA3D.IndexEntry {
+    method public deprecated android.renderscript.FileA3D.EntryType getEntryType();
+    method public deprecated android.renderscript.Mesh getMesh();
+    method public deprecated java.lang.String getName();
+    method public deprecated android.renderscript.BaseObj getObject();
+  }
+
+  public class Float2 {
+    ctor public Float2();
+    ctor public Float2(float, float);
+    field public float x;
+    field public float y;
+  }
+
+  public class Float3 {
+    ctor public Float3();
+    ctor public Float3(float, float, float);
+    field public float x;
+    field public float y;
+    field public float z;
+  }
+
+  public class Float4 {
+    ctor public Float4();
+    ctor public Float4(float, float, float, float);
+    field public float w;
+    field public float x;
+    field public float y;
+    field public float z;
+  }
+
+  public deprecated class Font extends android.renderscript.BaseObj {
+    method public static deprecated android.renderscript.Font create(android.renderscript.RenderScript, android.content.res.Resources, java.lang.String, android.renderscript.Font.Style, float);
+    method public static deprecated android.renderscript.Font createFromAsset(android.renderscript.RenderScript, android.content.res.Resources, java.lang.String, float);
+    method public static deprecated android.renderscript.Font createFromFile(android.renderscript.RenderScript, android.content.res.Resources, java.lang.String, float);
+    method public static deprecated android.renderscript.Font createFromFile(android.renderscript.RenderScript, android.content.res.Resources, java.io.File, float);
+    method public static deprecated android.renderscript.Font createFromResource(android.renderscript.RenderScript, android.content.res.Resources, int, float);
+  }
+
+  public static final deprecated class Font.Style extends java.lang.Enum {
+    method public static android.renderscript.Font.Style valueOf(java.lang.String);
+    method public static final android.renderscript.Font.Style[] values();
+    enum_constant public static final deprecated android.renderscript.Font.Style BOLD;
+    enum_constant public static final deprecated android.renderscript.Font.Style BOLD_ITALIC;
+    enum_constant public static final deprecated android.renderscript.Font.Style ITALIC;
+    enum_constant public static final deprecated android.renderscript.Font.Style NORMAL;
+  }
+
+  public class Int2 {
+    ctor public Int2();
+    ctor public Int2(int, int);
+    field public int x;
+    field public int y;
+  }
+
+  public class Int3 {
+    ctor public Int3();
+    ctor public Int3(int, int, int);
+    field public int x;
+    field public int y;
+    field public int z;
+  }
+
+  public class Int4 {
+    ctor public Int4();
+    ctor public Int4(int, int, int, int);
+    field public int w;
+    field public int x;
+    field public int y;
+    field public int z;
+  }
+
+  public class Long2 {
+    ctor public Long2();
+    ctor public Long2(long, long);
+    field public long x;
+    field public long y;
+  }
+
+  public class Long3 {
+    ctor public Long3();
+    ctor public Long3(long, long, long);
+    field public long x;
+    field public long y;
+    field public long z;
+  }
+
+  public class Long4 {
+    ctor public Long4();
+    ctor public Long4(long, long, long, long);
+    field public long w;
+    field public long x;
+    field public long y;
+    field public long z;
+  }
+
+  public class Matrix2f {
+    ctor public Matrix2f();
+    ctor public Matrix2f(float[]);
+    method public float get(int, int);
+    method public float[] getArray();
+    method public void load(android.renderscript.Matrix2f);
+    method public void loadIdentity();
+    method public void loadMultiply(android.renderscript.Matrix2f, android.renderscript.Matrix2f);
+    method public void loadRotate(float);
+    method public void loadScale(float, float);
+    method public void multiply(android.renderscript.Matrix2f);
+    method public void rotate(float);
+    method public void scale(float, float);
+    method public void set(int, int, float);
+    method public void transpose();
+  }
+
+  public class Matrix3f {
+    ctor public Matrix3f();
+    ctor public Matrix3f(float[]);
+    method public float get(int, int);
+    method public float[] getArray();
+    method public void load(android.renderscript.Matrix3f);
+    method public void loadIdentity();
+    method public void loadMultiply(android.renderscript.Matrix3f, android.renderscript.Matrix3f);
+    method public void loadRotate(float, float, float, float);
+    method public void loadRotate(float);
+    method public void loadScale(float, float);
+    method public void loadScale(float, float, float);
+    method public void loadTranslate(float, float);
+    method public void multiply(android.renderscript.Matrix3f);
+    method public void rotate(float, float, float, float);
+    method public void rotate(float);
+    method public void scale(float, float);
+    method public void scale(float, float, float);
+    method public void set(int, int, float);
+    method public void translate(float, float);
+    method public void transpose();
+  }
+
+  public class Matrix4f {
+    ctor public Matrix4f();
+    ctor public Matrix4f(float[]);
+    method public float get(int, int);
+    method public float[] getArray();
+    method public boolean inverse();
+    method public boolean inverseTranspose();
+    method public void load(android.renderscript.Matrix4f);
+    method public void loadFrustum(float, float, float, float, float, float);
+    method public void loadIdentity();
+    method public void loadMultiply(android.renderscript.Matrix4f, android.renderscript.Matrix4f);
+    method public void loadOrtho(float, float, float, float, float, float);
+    method public void loadOrthoWindow(int, int);
+    method public void loadPerspective(float, float, float, float);
+    method public void loadProjectionNormalized(int, int);
+    method public void loadRotate(float, float, float, float);
+    method public void loadScale(float, float, float);
+    method public void loadTranslate(float, float, float);
+    method public void multiply(android.renderscript.Matrix4f);
+    method public void rotate(float, float, float, float);
+    method public void scale(float, float, float);
+    method public void set(int, int, float);
+    method public void translate(float, float, float);
+    method public void transpose();
+  }
+
+  public deprecated class Mesh extends android.renderscript.BaseObj {
+    method public deprecated android.renderscript.Allocation getIndexSetAllocation(int);
+    method public deprecated android.renderscript.Mesh.Primitive getPrimitive(int);
+    method public deprecated int getPrimitiveCount();
+    method public deprecated android.renderscript.Allocation getVertexAllocation(int);
+    method public deprecated int getVertexAllocationCount();
+  }
+
+  public static deprecated class Mesh.AllocationBuilder {
+    ctor public deprecated Mesh.AllocationBuilder(android.renderscript.RenderScript);
+    method public deprecated android.renderscript.Mesh.AllocationBuilder addIndexSetAllocation(android.renderscript.Allocation, android.renderscript.Mesh.Primitive);
+    method public deprecated android.renderscript.Mesh.AllocationBuilder addIndexSetType(android.renderscript.Mesh.Primitive);
+    method public deprecated android.renderscript.Mesh.AllocationBuilder addVertexAllocation(android.renderscript.Allocation) throws java.lang.IllegalStateException;
+    method public deprecated android.renderscript.Mesh create();
+    method public deprecated int getCurrentIndexSetIndex();
+    method public deprecated int getCurrentVertexTypeIndex();
+  }
+
+  public static deprecated class Mesh.Builder {
+    ctor public deprecated Mesh.Builder(android.renderscript.RenderScript, int);
+    method public deprecated android.renderscript.Mesh.Builder addIndexSetType(android.renderscript.Type, android.renderscript.Mesh.Primitive);
+    method public deprecated android.renderscript.Mesh.Builder addIndexSetType(android.renderscript.Mesh.Primitive);
+    method public deprecated android.renderscript.Mesh.Builder addIndexSetType(android.renderscript.Element, int, android.renderscript.Mesh.Primitive);
+    method public deprecated android.renderscript.Mesh.Builder addVertexType(android.renderscript.Type) throws java.lang.IllegalStateException;
+    method public deprecated android.renderscript.Mesh.Builder addVertexType(android.renderscript.Element, int) throws java.lang.IllegalStateException;
+    method public deprecated android.renderscript.Mesh create();
+    method public deprecated int getCurrentIndexSetIndex();
+    method public deprecated int getCurrentVertexTypeIndex();
+  }
+
+  public static final deprecated class Mesh.Primitive extends java.lang.Enum {
+    method public static android.renderscript.Mesh.Primitive valueOf(java.lang.String);
+    method public static final android.renderscript.Mesh.Primitive[] values();
+    enum_constant public static final deprecated android.renderscript.Mesh.Primitive LINE;
+    enum_constant public static final deprecated android.renderscript.Mesh.Primitive LINE_STRIP;
+    enum_constant public static final deprecated android.renderscript.Mesh.Primitive POINT;
+    enum_constant public static final deprecated android.renderscript.Mesh.Primitive TRIANGLE;
+    enum_constant public static final deprecated android.renderscript.Mesh.Primitive TRIANGLE_FAN;
+    enum_constant public static final deprecated android.renderscript.Mesh.Primitive TRIANGLE_STRIP;
+  }
+
+  public static deprecated class Mesh.TriangleMeshBuilder {
+    ctor public deprecated Mesh.TriangleMeshBuilder(android.renderscript.RenderScript, int, int);
+    method public deprecated android.renderscript.Mesh.TriangleMeshBuilder addTriangle(int, int, int);
+    method public deprecated android.renderscript.Mesh.TriangleMeshBuilder addVertex(float, float);
+    method public deprecated android.renderscript.Mesh.TriangleMeshBuilder addVertex(float, float, float);
+    method public deprecated android.renderscript.Mesh create(boolean);
+    method public deprecated android.renderscript.Mesh.TriangleMeshBuilder setColor(float, float, float, float);
+    method public deprecated android.renderscript.Mesh.TriangleMeshBuilder setNormal(float, float, float);
+    method public deprecated android.renderscript.Mesh.TriangleMeshBuilder setTexture(float, float);
+    field public static final deprecated int COLOR = 1; // 0x1
+    field public static final deprecated int NORMAL = 2; // 0x2
+    field public static final deprecated int TEXTURE_0 = 256; // 0x100
+  }
+
+  public class Program extends android.renderscript.BaseObj {
+    method public void bindConstants(android.renderscript.Allocation, int);
+    method public void bindSampler(android.renderscript.Sampler, int) throws java.lang.IllegalArgumentException;
+    method public void bindTexture(android.renderscript.Allocation, int) throws java.lang.IllegalArgumentException;
+    method public android.renderscript.Type getConstant(int);
+    method public int getConstantCount();
+    method public int getTextureCount();
+    method public java.lang.String getTextureName(int);
+    method public android.renderscript.Program.TextureType getTextureType(int);
+  }
+
+  public static class Program.BaseProgramBuilder {
+    ctor protected Program.BaseProgramBuilder(android.renderscript.RenderScript);
+    method public android.renderscript.Program.BaseProgramBuilder addConstant(android.renderscript.Type) throws java.lang.IllegalStateException;
+    method public android.renderscript.Program.BaseProgramBuilder addTexture(android.renderscript.Program.TextureType) throws java.lang.IllegalArgumentException;
+    method public android.renderscript.Program.BaseProgramBuilder addTexture(android.renderscript.Program.TextureType, java.lang.String) throws java.lang.IllegalArgumentException;
+    method public int getCurrentConstantIndex();
+    method public int getCurrentTextureIndex();
+    method protected void initProgram(android.renderscript.Program);
+    method public android.renderscript.Program.BaseProgramBuilder setShader(java.lang.String);
+    method public android.renderscript.Program.BaseProgramBuilder setShader(android.content.res.Resources, int);
+  }
+
+  public static final class Program.TextureType extends java.lang.Enum {
+    method public static android.renderscript.Program.TextureType valueOf(java.lang.String);
+    method public static final android.renderscript.Program.TextureType[] values();
+    enum_constant public static final android.renderscript.Program.TextureType TEXTURE_2D;
+    enum_constant public static final android.renderscript.Program.TextureType TEXTURE_CUBE;
+  }
+
+  public deprecated class ProgramFragment extends android.renderscript.Program {
+  }
+
+  public static deprecated class ProgramFragment.Builder extends android.renderscript.Program.BaseProgramBuilder {
+    ctor public deprecated ProgramFragment.Builder(android.renderscript.RenderScript);
+    method public deprecated android.renderscript.ProgramFragment create();
+  }
+
+  public deprecated class ProgramFragmentFixedFunction extends android.renderscript.ProgramFragment {
+  }
+
+  public static deprecated class ProgramFragmentFixedFunction.Builder {
+    ctor public deprecated ProgramFragmentFixedFunction.Builder(android.renderscript.RenderScript);
+    method public deprecated android.renderscript.ProgramFragmentFixedFunction create();
+    method public deprecated android.renderscript.ProgramFragmentFixedFunction.Builder setPointSpriteTexCoordinateReplacement(boolean);
+    method public deprecated android.renderscript.ProgramFragmentFixedFunction.Builder setTexture(android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode, android.renderscript.ProgramFragmentFixedFunction.Builder.Format, int) throws java.lang.IllegalArgumentException;
+    method public deprecated android.renderscript.ProgramFragmentFixedFunction.Builder setVaryingColor(boolean);
+    field public static final deprecated int MAX_TEXTURE = 2; // 0x2
+  }
+
+  public static final deprecated class ProgramFragmentFixedFunction.Builder.EnvMode extends java.lang.Enum {
+    method public static android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode valueOf(java.lang.String);
+    method public static final android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode[] values();
+    enum_constant public static final deprecated android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode DECAL;
+    enum_constant public static final deprecated android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode MODULATE;
+    enum_constant public static final deprecated android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode REPLACE;
+  }
+
+  public static final deprecated class ProgramFragmentFixedFunction.Builder.Format extends java.lang.Enum {
+    method public static android.renderscript.ProgramFragmentFixedFunction.Builder.Format valueOf(java.lang.String);
+    method public static final android.renderscript.ProgramFragmentFixedFunction.Builder.Format[] values();
+    enum_constant public static final deprecated android.renderscript.ProgramFragmentFixedFunction.Builder.Format ALPHA;
+    enum_constant public static final deprecated android.renderscript.ProgramFragmentFixedFunction.Builder.Format LUMINANCE_ALPHA;
+    enum_constant public static final deprecated android.renderscript.ProgramFragmentFixedFunction.Builder.Format RGB;
+    enum_constant public static final deprecated android.renderscript.ProgramFragmentFixedFunction.Builder.Format RGBA;
+  }
+
+  public deprecated class ProgramRaster extends android.renderscript.BaseObj {
+    method public static deprecated android.renderscript.ProgramRaster CULL_BACK(android.renderscript.RenderScript);
+    method public static deprecated android.renderscript.ProgramRaster CULL_FRONT(android.renderscript.RenderScript);
+    method public static deprecated android.renderscript.ProgramRaster CULL_NONE(android.renderscript.RenderScript);
+    method public deprecated android.renderscript.ProgramRaster.CullMode getCullMode();
+    method public deprecated boolean isPointSpriteEnabled();
+  }
+
+  public static deprecated class ProgramRaster.Builder {
+    ctor public deprecated ProgramRaster.Builder(android.renderscript.RenderScript);
+    method public deprecated android.renderscript.ProgramRaster create();
+    method public deprecated android.renderscript.ProgramRaster.Builder setCullMode(android.renderscript.ProgramRaster.CullMode);
+    method public deprecated android.renderscript.ProgramRaster.Builder setPointSpriteEnabled(boolean);
+  }
+
+  public static final deprecated class ProgramRaster.CullMode extends java.lang.Enum {
+    method public static android.renderscript.ProgramRaster.CullMode valueOf(java.lang.String);
+    method public static final android.renderscript.ProgramRaster.CullMode[] values();
+    enum_constant public static final deprecated android.renderscript.ProgramRaster.CullMode BACK;
+    enum_constant public static final deprecated android.renderscript.ProgramRaster.CullMode FRONT;
+    enum_constant public static final deprecated android.renderscript.ProgramRaster.CullMode NONE;
+  }
+
+  public class ProgramStore extends android.renderscript.BaseObj {
+    method public static android.renderscript.ProgramStore BLEND_ALPHA_DEPTH_NONE(android.renderscript.RenderScript);
+    method public static android.renderscript.ProgramStore BLEND_ALPHA_DEPTH_TEST(android.renderscript.RenderScript);
+    method public static android.renderscript.ProgramStore BLEND_NONE_DEPTH_NONE(android.renderscript.RenderScript);
+    method public static android.renderscript.ProgramStore BLEND_NONE_DEPTH_TEST(android.renderscript.RenderScript);
+    method public android.renderscript.ProgramStore.BlendDstFunc getBlendDstFunc();
+    method public android.renderscript.ProgramStore.BlendSrcFunc getBlendSrcFunc();
+    method public android.renderscript.ProgramStore.DepthFunc getDepthFunc();
+    method public boolean isColorMaskAlphaEnabled();
+    method public boolean isColorMaskBlueEnabled();
+    method public boolean isColorMaskGreenEnabled();
+    method public boolean isColorMaskRedEnabled();
+    method public boolean isDepthMaskEnabled();
+    method public boolean isDitherEnabled();
+  }
+
+  public static final class ProgramStore.BlendDstFunc extends java.lang.Enum {
+    method public static android.renderscript.ProgramStore.BlendDstFunc valueOf(java.lang.String);
+    method public static final android.renderscript.ProgramStore.BlendDstFunc[] values();
+    enum_constant public static final android.renderscript.ProgramStore.BlendDstFunc DST_ALPHA;
+    enum_constant public static final android.renderscript.ProgramStore.BlendDstFunc ONE;
+    enum_constant public static final android.renderscript.ProgramStore.BlendDstFunc ONE_MINUS_DST_ALPHA;
+    enum_constant public static final android.renderscript.ProgramStore.BlendDstFunc ONE_MINUS_SRC_ALPHA;
+    enum_constant public static final android.renderscript.ProgramStore.BlendDstFunc ONE_MINUS_SRC_COLOR;
+    enum_constant public static final android.renderscript.ProgramStore.BlendDstFunc SRC_ALPHA;
+    enum_constant public static final android.renderscript.ProgramStore.BlendDstFunc SRC_COLOR;
+    enum_constant public static final android.renderscript.ProgramStore.BlendDstFunc ZERO;
+  }
+
+  public static final class ProgramStore.BlendSrcFunc extends java.lang.Enum {
+    method public static android.renderscript.ProgramStore.BlendSrcFunc valueOf(java.lang.String);
+    method public static final android.renderscript.ProgramStore.BlendSrcFunc[] values();
+    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc DST_ALPHA;
+    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc DST_COLOR;
+    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc ONE;
+    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc ONE_MINUS_DST_ALPHA;
+    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc ONE_MINUS_DST_COLOR;
+    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc ONE_MINUS_SRC_ALPHA;
+    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc SRC_ALPHA;
+    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc SRC_ALPHA_SATURATE;
+    enum_constant public static final android.renderscript.ProgramStore.BlendSrcFunc ZERO;
+  }
+
+  public static class ProgramStore.Builder {
+    ctor public ProgramStore.Builder(android.renderscript.RenderScript);
+    method public android.renderscript.ProgramStore create();
+    method public android.renderscript.ProgramStore.Builder setBlendFunc(android.renderscript.ProgramStore.BlendSrcFunc, android.renderscript.ProgramStore.BlendDstFunc);
+    method public android.renderscript.ProgramStore.Builder setColorMaskEnabled(boolean, boolean, boolean, boolean);
+    method public android.renderscript.ProgramStore.Builder setDepthFunc(android.renderscript.ProgramStore.DepthFunc);
+    method public android.renderscript.ProgramStore.Builder setDepthMaskEnabled(boolean);
+    method public android.renderscript.ProgramStore.Builder setDitherEnabled(boolean);
+  }
+
+  public static final class ProgramStore.DepthFunc extends java.lang.Enum {
+    method public static android.renderscript.ProgramStore.DepthFunc valueOf(java.lang.String);
+    method public static final android.renderscript.ProgramStore.DepthFunc[] values();
+    enum_constant public static final android.renderscript.ProgramStore.DepthFunc ALWAYS;
+    enum_constant public static final android.renderscript.ProgramStore.DepthFunc EQUAL;
+    enum_constant public static final android.renderscript.ProgramStore.DepthFunc GREATER;
+    enum_constant public static final android.renderscript.ProgramStore.DepthFunc GREATER_OR_EQUAL;
+    enum_constant public static final android.renderscript.ProgramStore.DepthFunc LESS;
+    enum_constant public static final android.renderscript.ProgramStore.DepthFunc LESS_OR_EQUAL;
+    enum_constant public static final android.renderscript.ProgramStore.DepthFunc NOT_EQUAL;
+  }
+
+  public deprecated class ProgramVertex extends android.renderscript.Program {
+    method public deprecated android.renderscript.Element getInput(int);
+    method public deprecated int getInputCount();
+  }
+
+  public static deprecated class ProgramVertex.Builder extends android.renderscript.Program.BaseProgramBuilder {
+    ctor public deprecated ProgramVertex.Builder(android.renderscript.RenderScript);
+    method public deprecated android.renderscript.ProgramVertex.Builder addInput(android.renderscript.Element) throws java.lang.IllegalStateException;
+    method public deprecated android.renderscript.ProgramVertex create();
+  }
+
+  public deprecated class ProgramVertexFixedFunction extends android.renderscript.ProgramVertex {
+    method public deprecated void bindConstants(android.renderscript.ProgramVertexFixedFunction.Constants);
+  }
+
+  public static deprecated class ProgramVertexFixedFunction.Builder {
+    ctor public deprecated ProgramVertexFixedFunction.Builder(android.renderscript.RenderScript);
+    method public deprecated android.renderscript.ProgramVertexFixedFunction create();
+    method public deprecated android.renderscript.ProgramVertexFixedFunction.Builder setTextureMatrixEnable(boolean);
+  }
+
+  public static deprecated class ProgramVertexFixedFunction.Constants {
+    ctor public deprecated ProgramVertexFixedFunction.Constants(android.renderscript.RenderScript);
+    method public deprecated void destroy();
+    method public deprecated void setModelview(android.renderscript.Matrix4f);
+    method public deprecated void setProjection(android.renderscript.Matrix4f);
+    method public deprecated void setTexture(android.renderscript.Matrix4f);
+  }
+
+  public class RSDriverException extends android.renderscript.RSRuntimeException {
+    ctor public RSDriverException(java.lang.String);
+  }
+
+  public class RSIllegalArgumentException extends android.renderscript.RSRuntimeException {
+    ctor public RSIllegalArgumentException(java.lang.String);
+  }
+
+  public class RSInvalidStateException extends android.renderscript.RSRuntimeException {
+    ctor public RSInvalidStateException(java.lang.String);
+  }
+
+  public class RSRuntimeException extends java.lang.RuntimeException {
+    ctor public RSRuntimeException(java.lang.String);
+  }
+
+  public deprecated class RSSurfaceView extends android.view.SurfaceView implements android.view.SurfaceHolder.Callback {
+    ctor public deprecated RSSurfaceView(android.content.Context);
+    ctor public deprecated RSSurfaceView(android.content.Context, android.util.AttributeSet);
+    method public deprecated android.renderscript.RenderScriptGL createRenderScriptGL(android.renderscript.RenderScriptGL.SurfaceConfig);
+    method public deprecated void destroyRenderScriptGL();
+    method public deprecated android.renderscript.RenderScriptGL getRenderScriptGL();
+    method public deprecated void pause();
+    method public deprecated void resume();
+    method public deprecated void setRenderScriptGL(android.renderscript.RenderScriptGL);
+    method public deprecated void surfaceChanged(android.view.SurfaceHolder, int, int, int);
+    method public deprecated void surfaceCreated(android.view.SurfaceHolder);
+    method public deprecated void surfaceDestroyed(android.view.SurfaceHolder);
+  }
+
+  public deprecated class RSTextureView extends android.view.TextureView implements android.view.TextureView.SurfaceTextureListener {
+    ctor public deprecated RSTextureView(android.content.Context);
+    ctor public deprecated RSTextureView(android.content.Context, android.util.AttributeSet);
+    method public deprecated android.renderscript.RenderScriptGL createRenderScriptGL(android.renderscript.RenderScriptGL.SurfaceConfig);
+    method public deprecated void destroyRenderScriptGL();
+    method public deprecated android.renderscript.RenderScriptGL getRenderScriptGL();
+    method public deprecated void onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int);
+    method public deprecated boolean onSurfaceTextureDestroyed(android.graphics.SurfaceTexture);
+    method public deprecated void onSurfaceTextureSizeChanged(android.graphics.SurfaceTexture, int, int);
+    method public deprecated void onSurfaceTextureUpdated(android.graphics.SurfaceTexture);
+    method public deprecated void pause();
+    method public deprecated void resume();
+    method public deprecated void setRenderScriptGL(android.renderscript.RenderScriptGL);
+  }
+
+  public class RenderScript {
+    method public void contextDump();
+    method public static android.renderscript.RenderScript create(android.content.Context);
+    method public void destroy();
+    method public void finish();
+    method public final android.content.Context getApplicationContext();
+    method public android.renderscript.RenderScript.RSErrorHandler getErrorHandler();
+    method public android.renderscript.RenderScript.RSMessageHandler getMessageHandler();
+    method public void setErrorHandler(android.renderscript.RenderScript.RSErrorHandler);
+    method public void setMessageHandler(android.renderscript.RenderScript.RSMessageHandler);
+    method public void setPriority(android.renderscript.RenderScript.Priority);
+  }
+
+  public static final class RenderScript.Priority extends java.lang.Enum {
+    method public static android.renderscript.RenderScript.Priority valueOf(java.lang.String);
+    method public static final android.renderscript.RenderScript.Priority[] values();
+    enum_constant public static final android.renderscript.RenderScript.Priority LOW;
+    enum_constant public static final android.renderscript.RenderScript.Priority NORMAL;
+  }
+
+  public static class RenderScript.RSErrorHandler implements java.lang.Runnable {
+    ctor public RenderScript.RSErrorHandler();
+    method public void run();
+    field protected java.lang.String mErrorMessage;
+    field protected int mErrorNum;
+  }
+
+  public static class RenderScript.RSMessageHandler implements java.lang.Runnable {
+    ctor public RenderScript.RSMessageHandler();
+    method public void run();
+    field protected int[] mData;
+    field protected int mID;
+    field protected int mLength;
+  }
+
+  public deprecated class RenderScriptGL extends android.renderscript.RenderScript {
+    ctor public deprecated RenderScriptGL(android.content.Context, android.renderscript.RenderScriptGL.SurfaceConfig);
+    method public deprecated void bindProgramFragment(android.renderscript.ProgramFragment);
+    method public deprecated void bindProgramRaster(android.renderscript.ProgramRaster);
+    method public deprecated void bindProgramStore(android.renderscript.ProgramStore);
+    method public deprecated void bindProgramVertex(android.renderscript.ProgramVertex);
+    method public deprecated void bindRootScript(android.renderscript.Script);
+    method public deprecated int getHeight();
+    method public deprecated int getWidth();
+    method public deprecated void pause();
+    method public deprecated void resume();
+    method public deprecated void setSurface(android.view.SurfaceHolder, int, int);
+    method public deprecated void setSurfaceTexture(android.graphics.SurfaceTexture, int, int);
+  }
+
+  public static deprecated class RenderScriptGL.SurfaceConfig {
+    ctor public deprecated RenderScriptGL.SurfaceConfig();
+    ctor public deprecated RenderScriptGL.SurfaceConfig(android.renderscript.RenderScriptGL.SurfaceConfig);
+    method public deprecated void setAlpha(int, int);
+    method public deprecated void setColor(int, int);
+    method public deprecated void setDepth(int, int);
+    method public deprecated void setSamples(int, int, float);
+  }
+
+  public class Sampler extends android.renderscript.BaseObj {
+    method public static android.renderscript.Sampler CLAMP_LINEAR(android.renderscript.RenderScript);
+    method public static android.renderscript.Sampler CLAMP_LINEAR_MIP_LINEAR(android.renderscript.RenderScript);
+    method public static android.renderscript.Sampler CLAMP_NEAREST(android.renderscript.RenderScript);
+    method public static android.renderscript.Sampler WRAP_LINEAR(android.renderscript.RenderScript);
+    method public static android.renderscript.Sampler WRAP_LINEAR_MIP_LINEAR(android.renderscript.RenderScript);
+    method public static android.renderscript.Sampler WRAP_NEAREST(android.renderscript.RenderScript);
+    method public float getAnisotropy();
+    method public android.renderscript.Sampler.Value getMagnification();
+    method public android.renderscript.Sampler.Value getMinification();
+    method public android.renderscript.Sampler.Value getWrapS();
+    method public android.renderscript.Sampler.Value getWrapT();
+  }
+
+  public static class Sampler.Builder {
+    ctor public Sampler.Builder(android.renderscript.RenderScript);
+    method public android.renderscript.Sampler create();
+    method public void setAnisotropy(float);
+    method public void setMagnification(android.renderscript.Sampler.Value);
+    method public void setMinification(android.renderscript.Sampler.Value);
+    method public void setWrapS(android.renderscript.Sampler.Value);
+    method public void setWrapT(android.renderscript.Sampler.Value);
+  }
+
+  public static final class Sampler.Value extends java.lang.Enum {
+    method public static android.renderscript.Sampler.Value valueOf(java.lang.String);
+    method public static final android.renderscript.Sampler.Value[] values();
+    enum_constant public static final android.renderscript.Sampler.Value CLAMP;
+    enum_constant public static final android.renderscript.Sampler.Value LINEAR;
+    enum_constant public static final android.renderscript.Sampler.Value LINEAR_MIP_LINEAR;
+    enum_constant public static final android.renderscript.Sampler.Value LINEAR_MIP_NEAREST;
+    enum_constant public static final android.renderscript.Sampler.Value NEAREST;
+    enum_constant public static final android.renderscript.Sampler.Value WRAP;
+  }
+
+  public class Script extends android.renderscript.BaseObj {
+    method public void bindAllocation(android.renderscript.Allocation, int);
+    method protected android.renderscript.Script.FieldID createFieldID(int, android.renderscript.Element);
+    method protected android.renderscript.Script.KernelID createKernelID(int, int, android.renderscript.Element, android.renderscript.Element);
+    method protected void forEach(int, android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.FieldPacker);
+    method protected void invoke(int);
+    method protected void invoke(int, android.renderscript.FieldPacker);
+    method public void setTimeZone(java.lang.String);
+    method public void setVar(int, float);
+    method public void setVar(int, double);
+    method public void setVar(int, int);
+    method public void setVar(int, long);
+    method public void setVar(int, boolean);
+    method public void setVar(int, android.renderscript.BaseObj);
+    method public void setVar(int, android.renderscript.FieldPacker);
+    method public void setVar(int, android.renderscript.FieldPacker, android.renderscript.Element, int[]);
+  }
+
+  public static class Script.Builder {
+  }
+
+  public static class Script.FieldBase {
+    ctor protected Script.FieldBase();
+    method public android.renderscript.Allocation getAllocation();
+    method public android.renderscript.Element getElement();
+    method public android.renderscript.Type getType();
+    method protected void init(android.renderscript.RenderScript, int);
+    method protected void init(android.renderscript.RenderScript, int, int);
+    method public void updateAllocation();
+    field protected android.renderscript.Allocation mAllocation;
+    field protected android.renderscript.Element mElement;
+  }
+
+  public static final class Script.FieldID extends android.renderscript.BaseObj {
+  }
+
+  public static final class Script.KernelID extends android.renderscript.BaseObj {
+  }
+
+  public class ScriptC extends android.renderscript.Script {
+    ctor protected ScriptC(int, android.renderscript.RenderScript);
+    ctor protected ScriptC(android.renderscript.RenderScript, android.content.res.Resources, int);
+  }
+
+  public final class ScriptGroup extends android.renderscript.BaseObj {
+    method public void execute();
+    method public void setInput(android.renderscript.Script.KernelID, android.renderscript.Allocation);
+    method public void setOutput(android.renderscript.Script.KernelID, android.renderscript.Allocation);
+  }
+
+  public static final class ScriptGroup.Builder {
+    ctor public ScriptGroup.Builder(android.renderscript.RenderScript);
+    method public android.renderscript.ScriptGroup.Builder addConnection(android.renderscript.Type, android.renderscript.Script.KernelID, android.renderscript.Script.FieldID);
+    method public android.renderscript.ScriptGroup.Builder addConnection(android.renderscript.Type, android.renderscript.Script.KernelID, android.renderscript.Script.KernelID);
+    method public android.renderscript.ScriptGroup.Builder addKernel(android.renderscript.Script.KernelID);
+    method public android.renderscript.ScriptGroup create();
+  }
+
+  public abstract class ScriptIntrinsic extends android.renderscript.Script {
+  }
+
+  public class ScriptIntrinsicBlend extends android.renderscript.ScriptIntrinsic {
+    method public static android.renderscript.ScriptIntrinsicBlend create(android.renderscript.RenderScript, android.renderscript.Element);
+    method public void forEachAdd(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachClear(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachDst(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachDstAtop(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachDstIn(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachDstOut(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachDstOver(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachMultiply(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachSrc(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachSrcAtop(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachSrcIn(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachSrcOut(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachSrcOver(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachSubtract(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachXor(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public android.renderscript.Script.KernelID getKernelIDAdd();
+    method public android.renderscript.Script.KernelID getKernelIDClear();
+    method public android.renderscript.Script.KernelID getKernelIDDst();
+    method public android.renderscript.Script.KernelID getKernelIDDstAtop();
+    method public android.renderscript.Script.KernelID getKernelIDDstIn();
+    method public android.renderscript.Script.KernelID getKernelIDDstOut();
+    method public android.renderscript.Script.KernelID getKernelIDDstOver();
+    method public android.renderscript.Script.KernelID getKernelIDMultiply();
+    method public android.renderscript.Script.KernelID getKernelIDSrc();
+    method public android.renderscript.Script.KernelID getKernelIDSrcAtop();
+    method public android.renderscript.Script.KernelID getKernelIDSrcIn();
+    method public android.renderscript.Script.KernelID getKernelIDSrcOut();
+    method public android.renderscript.Script.KernelID getKernelIDSrcOver();
+    method public android.renderscript.Script.KernelID getKernelIDSubtract();
+    method public android.renderscript.Script.KernelID getKernelIDXor();
+  }
+
+  public final class ScriptIntrinsicBlur extends android.renderscript.ScriptIntrinsic {
+    method public static android.renderscript.ScriptIntrinsicBlur create(android.renderscript.RenderScript, android.renderscript.Element);
+    method public void forEach(android.renderscript.Allocation);
+    method public android.renderscript.Script.FieldID getFieldID_Input();
+    method public android.renderscript.Script.KernelID getKernelID();
+    method public void setInput(android.renderscript.Allocation);
+    method public void setRadius(float);
+  }
+
+  public final class ScriptIntrinsicColorMatrix extends android.renderscript.ScriptIntrinsic {
+    method public static android.renderscript.ScriptIntrinsicColorMatrix create(android.renderscript.RenderScript, android.renderscript.Element);
+    method public void forEach(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public android.renderscript.Script.KernelID getKernelID();
+    method public void setColorMatrix(android.renderscript.Matrix4f);
+    method public void setColorMatrix(android.renderscript.Matrix3f);
+    method public void setGreyscale();
+    method public void setRGBtoYUV();
+    method public void setYUVtoRGB();
+  }
+
+  public final class ScriptIntrinsicConvolve3x3 extends android.renderscript.ScriptIntrinsic {
+    method public static android.renderscript.ScriptIntrinsicConvolve3x3 create(android.renderscript.RenderScript, android.renderscript.Element);
+    method public void forEach(android.renderscript.Allocation);
+    method public android.renderscript.Script.FieldID getFieldID_Input();
+    method public android.renderscript.Script.KernelID getKernelID();
+    method public void setCoefficients(float[]);
+    method public void setInput(android.renderscript.Allocation);
+  }
+
+  public final class ScriptIntrinsicConvolve5x5 extends android.renderscript.ScriptIntrinsic {
+    method public static android.renderscript.ScriptIntrinsicConvolve5x5 create(android.renderscript.RenderScript, android.renderscript.Element);
+    method public void forEach(android.renderscript.Allocation);
+    method public android.renderscript.Script.FieldID getFieldID_Input();
+    method public android.renderscript.Script.KernelID getKernelID();
+    method public void setCoefficients(float[]);
+    method public void setInput(android.renderscript.Allocation);
+  }
+
+  public final class ScriptIntrinsicLUT extends android.renderscript.ScriptIntrinsic {
+    method public static android.renderscript.ScriptIntrinsicLUT create(android.renderscript.RenderScript, android.renderscript.Element);
+    method public void forEach(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public android.renderscript.Script.KernelID getKernelID();
+    method public void setAlpha(int, int);
+    method public void setBlue(int, int);
+    method public void setGreen(int, int);
+    method public void setRed(int, int);
+  }
+
+  public final class ScriptIntrinsicYuvToRGB extends android.renderscript.ScriptIntrinsic {
+    method public static android.renderscript.ScriptIntrinsicYuvToRGB create(android.renderscript.RenderScript, android.renderscript.Element);
+    method public void forEach(android.renderscript.Allocation);
+    method public android.renderscript.Script.FieldID getFieldID_Input();
+    method public android.renderscript.Script.KernelID getKernelID();
+    method public void setInput(android.renderscript.Allocation);
+  }
+
+  public class Short2 {
+    ctor public Short2();
+    ctor public Short2(short, short);
+    field public short x;
+    field public short y;
+  }
+
+  public class Short3 {
+    ctor public Short3();
+    ctor public Short3(short, short, short);
+    field public short x;
+    field public short y;
+    field public short z;
+  }
+
+  public class Short4 {
+    ctor public Short4();
+    ctor public Short4(short, short, short, short);
+    field public short w;
+    field public short x;
+    field public short y;
+    field public short z;
+  }
+
+  public class Type extends android.renderscript.BaseObj {
+    method public int getCount();
+    method public android.renderscript.Element getElement();
+    method public int getX();
+    method public int getY();
+    method public int getZ();
+    method public boolean hasFaces();
+    method public boolean hasMipmaps();
+  }
+
+  public static class Type.Builder {
+    ctor public Type.Builder(android.renderscript.RenderScript, android.renderscript.Element);
+    method public android.renderscript.Type create();
+    method public android.renderscript.Type.Builder setFaces(boolean);
+    method public android.renderscript.Type.Builder setMipmaps(boolean);
+    method public android.renderscript.Type.Builder setX(int);
+    method public android.renderscript.Type.Builder setY(int);
+  }
+
+  public static final class Type.CubemapFace extends java.lang.Enum {
+    method public static android.renderscript.Type.CubemapFace valueOf(java.lang.String);
+    method public static final android.renderscript.Type.CubemapFace[] values();
+    enum_constant public static final android.renderscript.Type.CubemapFace NEGATIVE_X;
+    enum_constant public static final android.renderscript.Type.CubemapFace NEGATIVE_Y;
+    enum_constant public static final android.renderscript.Type.CubemapFace NEGATIVE_Z;
+    enum_constant public static final android.renderscript.Type.CubemapFace POSITIVE_X;
+    enum_constant public static final android.renderscript.Type.CubemapFace POSITIVE_Y;
+    enum_constant public static final android.renderscript.Type.CubemapFace POSITIVE_Z;
+    enum_constant public static final deprecated android.renderscript.Type.CubemapFace POSITVE_X;
+    enum_constant public static final deprecated android.renderscript.Type.CubemapFace POSITVE_Y;
+    enum_constant public static final deprecated android.renderscript.Type.CubemapFace POSITVE_Z;
+  }
+
+}
+
+package android.sax {
+
+  public class Element {
+    method public android.sax.Element getChild(java.lang.String);
+    method public android.sax.Element getChild(java.lang.String, java.lang.String);
+    method public android.sax.Element requireChild(java.lang.String);
+    method public android.sax.Element requireChild(java.lang.String, java.lang.String);
+    method public void setElementListener(android.sax.ElementListener);
+    method public void setEndElementListener(android.sax.EndElementListener);
+    method public void setEndTextElementListener(android.sax.EndTextElementListener);
+    method public void setStartElementListener(android.sax.StartElementListener);
+    method public void setTextElementListener(android.sax.TextElementListener);
+  }
+
+  public abstract interface ElementListener implements android.sax.EndElementListener android.sax.StartElementListener {
+  }
+
+  public abstract interface EndElementListener {
+    method public abstract void end();
+  }
+
+  public abstract interface EndTextElementListener {
+    method public abstract void end(java.lang.String);
+  }
+
+  public class RootElement extends android.sax.Element {
+    ctor public RootElement(java.lang.String, java.lang.String);
+    ctor public RootElement(java.lang.String);
+    method public org.xml.sax.ContentHandler getContentHandler();
+  }
+
+  public abstract interface StartElementListener {
+    method public abstract void start(org.xml.sax.Attributes);
+  }
+
+  public abstract interface TextElementListener implements android.sax.EndTextElementListener android.sax.StartElementListener {
+  }
+
+}
+
+package android.security {
+
+  public final class KeyChain {
+    ctor public KeyChain();
+    method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String);
+    method public static android.content.Intent createInstallIntent();
+    method public static java.security.cert.X509Certificate[] getCertificateChain(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException;
+    method public static java.security.PrivateKey getPrivateKey(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException;
+    field public static final java.lang.String ACTION_STORAGE_CHANGED = "android.security.STORAGE_CHANGED";
+    field public static final java.lang.String EXTRA_CERTIFICATE = "CERT";
+    field public static final java.lang.String EXTRA_NAME = "name";
+    field public static final java.lang.String EXTRA_PKCS12 = "PKCS12";
+  }
+
+  public abstract interface KeyChainAliasCallback {
+    method public abstract void alias(java.lang.String);
+  }
+
+  public class KeyChainException extends java.lang.Exception {
+    ctor public KeyChainException();
+    ctor public KeyChainException(java.lang.String);
+    ctor public KeyChainException(java.lang.String, java.lang.Throwable);
+    ctor public KeyChainException(java.lang.Throwable);
+  }
+
+}
+
+package android.service.dreams {
+
+  public class DreamService extends android.app.Service implements android.view.Window.Callback {
+    ctor public DreamService();
+    method public void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
+    method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
+    method public boolean dispatchKeyEvent(android.view.KeyEvent);
+    method public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
+    method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+    method public boolean dispatchTouchEvent(android.view.MotionEvent);
+    method public boolean dispatchTrackballEvent(android.view.MotionEvent);
+    method public android.view.View findViewById(int);
+    method public final void finish();
+    method public android.view.Window getWindow();
+    method public android.view.WindowManager getWindowManager();
+    method public boolean isFullscreen();
+    method public boolean isInteractive();
+    method public boolean isScreenBright();
+    method public void onActionModeFinished(android.view.ActionMode);
+    method public void onActionModeStarted(android.view.ActionMode);
+    method public void onAttachedToWindow();
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public void onContentChanged();
+    method public boolean onCreatePanelMenu(int, android.view.Menu);
+    method public android.view.View onCreatePanelView(int);
+    method public void onDetachedFromWindow();
+    method public void onDreamingStarted();
+    method public void onDreamingStopped();
+    method public boolean onMenuItemSelected(int, android.view.MenuItem);
+    method public boolean onMenuOpened(int, android.view.Menu);
+    method public void onPanelClosed(int, android.view.Menu);
+    method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+    method public boolean onSearchRequested();
+    method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
+    method public void onWindowFocusChanged(boolean);
+    method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
+    method public void setContentView(int);
+    method public void setContentView(android.view.View);
+    method public void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
+    method public void setFullscreen(boolean);
+    method public void setInteractive(boolean);
+    method public void setScreenBright(boolean);
+    field public static final java.lang.String DREAM_META_DATA = "android.service.dream";
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.dreams.DreamService";
+  }
+
+}
+
+package android.service.textservice {
+
+  public abstract class SpellCheckerService extends android.app.Service {
+    ctor public SpellCheckerService();
+    method public abstract android.service.textservice.SpellCheckerService.Session createSession();
+    method public final android.os.IBinder onBind(android.content.Intent);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.textservice.SpellCheckerService";
+  }
+
+  public static abstract class SpellCheckerService.Session {
+    ctor public SpellCheckerService.Session();
+    method public android.os.Bundle getBundle();
+    method public java.lang.String getLocale();
+    method public void onCancel();
+    method public void onClose();
+    method public abstract void onCreate();
+    method public android.view.textservice.SentenceSuggestionsInfo[] onGetSentenceSuggestionsMultiple(android.view.textservice.TextInfo[], int);
+    method public abstract android.view.textservice.SuggestionsInfo onGetSuggestions(android.view.textservice.TextInfo, int);
+    method public android.view.textservice.SuggestionsInfo[] onGetSuggestionsMultiple(android.view.textservice.TextInfo[], int, boolean);
+  }
+
+}
+
+package android.service.wallpaper {
+
+  public abstract class WallpaperService extends android.app.Service {
+    ctor public WallpaperService();
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public abstract android.service.wallpaper.WallpaperService.Engine onCreateEngine();
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.wallpaper.WallpaperService";
+    field public static final java.lang.String SERVICE_META_DATA = "android.service.wallpaper";
+  }
+
+  public class WallpaperService.Engine {
+    ctor public WallpaperService.Engine();
+    method protected void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public int getDesiredMinimumHeight();
+    method public int getDesiredMinimumWidth();
+    method public android.view.SurfaceHolder getSurfaceHolder();
+    method public boolean isPreview();
+    method public boolean isVisible();
+    method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
+    method public void onCreate(android.view.SurfaceHolder);
+    method public void onDesiredSizeChanged(int, int);
+    method public void onDestroy();
+    method public void onOffsetsChanged(float, float, float, float, int, int);
+    method public void onSurfaceChanged(android.view.SurfaceHolder, int, int, int);
+    method public void onSurfaceCreated(android.view.SurfaceHolder);
+    method public void onSurfaceDestroyed(android.view.SurfaceHolder);
+    method public void onSurfaceRedrawNeeded(android.view.SurfaceHolder);
+    method public void onTouchEvent(android.view.MotionEvent);
+    method public void onVisibilityChanged(boolean);
+    method public void setOffsetNotificationsEnabled(boolean);
+    method public void setTouchEventsEnabled(boolean);
+  }
+
+}
+
+package android.speech {
+
+  public abstract interface RecognitionListener {
+    method public abstract void onBeginningOfSpeech();
+    method public abstract void onBufferReceived(byte[]);
+    method public abstract void onEndOfSpeech();
+    method public abstract void onError(int);
+    method public abstract void onEvent(int, android.os.Bundle);
+    method public abstract void onPartialResults(android.os.Bundle);
+    method public abstract void onReadyForSpeech(android.os.Bundle);
+    method public abstract void onResults(android.os.Bundle);
+    method public abstract void onRmsChanged(float);
+  }
+
+  public abstract class RecognitionService extends android.app.Service {
+    ctor public RecognitionService();
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method protected abstract void onCancel(android.speech.RecognitionService.Callback);
+    method protected abstract void onStartListening(android.content.Intent, android.speech.RecognitionService.Callback);
+    method protected abstract void onStopListening(android.speech.RecognitionService.Callback);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.speech.RecognitionService";
+    field public static final java.lang.String SERVICE_META_DATA = "android.speech";
+  }
+
+  public class RecognitionService.Callback {
+    method public void beginningOfSpeech() throws android.os.RemoteException;
+    method public void bufferReceived(byte[]) throws android.os.RemoteException;
+    method public void endOfSpeech() throws android.os.RemoteException;
+    method public void error(int) throws android.os.RemoteException;
+    method public void partialResults(android.os.Bundle) throws android.os.RemoteException;
+    method public void readyForSpeech(android.os.Bundle) throws android.os.RemoteException;
+    method public void results(android.os.Bundle) throws android.os.RemoteException;
+    method public void rmsChanged(float) throws android.os.RemoteException;
+  }
+
+  public class RecognizerIntent {
+    method public static final android.content.Intent getVoiceDetailsIntent(android.content.Context);
+    field public static final java.lang.String ACTION_GET_LANGUAGE_DETAILS = "android.speech.action.GET_LANGUAGE_DETAILS";
+    field public static final java.lang.String ACTION_RECOGNIZE_SPEECH = "android.speech.action.RECOGNIZE_SPEECH";
+    field public static final java.lang.String ACTION_VOICE_SEARCH_HANDS_FREE = "android.speech.action.VOICE_SEARCH_HANDS_FREE";
+    field public static final java.lang.String ACTION_WEB_SEARCH = "android.speech.action.WEB_SEARCH";
+    field public static final java.lang.String DETAILS_META_DATA = "android.speech.DETAILS";
+    field public static final java.lang.String EXTRA_CALLING_PACKAGE = "calling_package";
+    field public static final java.lang.String EXTRA_CONFIDENCE_SCORES = "android.speech.extra.CONFIDENCE_SCORES";
+    field public static final java.lang.String EXTRA_LANGUAGE = "android.speech.extra.LANGUAGE";
+    field public static final java.lang.String EXTRA_LANGUAGE_MODEL = "android.speech.extra.LANGUAGE_MODEL";
+    field public static final java.lang.String EXTRA_LANGUAGE_PREFERENCE = "android.speech.extra.LANGUAGE_PREFERENCE";
+    field public static final java.lang.String EXTRA_MAX_RESULTS = "android.speech.extra.MAX_RESULTS";
+    field public static final java.lang.String EXTRA_ONLY_RETURN_LANGUAGE_PREFERENCE = "android.speech.extra.ONLY_RETURN_LANGUAGE_PREFERENCE";
+    field public static final java.lang.String EXTRA_ORIGIN = "android.speech.extra.ORIGIN";
+    field public static final java.lang.String EXTRA_PARTIAL_RESULTS = "android.speech.extra.PARTIAL_RESULTS";
+    field public static final java.lang.String EXTRA_PROMPT = "android.speech.extra.PROMPT";
+    field public static final java.lang.String EXTRA_RESULTS = "android.speech.extra.RESULTS";
+    field public static final java.lang.String EXTRA_RESULTS_PENDINGINTENT = "android.speech.extra.RESULTS_PENDINGINTENT";
+    field public static final java.lang.String EXTRA_RESULTS_PENDINGINTENT_BUNDLE = "android.speech.extra.RESULTS_PENDINGINTENT_BUNDLE";
+    field public static final java.lang.String EXTRA_SECURE = "android.speech.extras.EXTRA_SECURE";
+    field public static final java.lang.String EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS = "android.speech.extras.SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS";
+    field public static final java.lang.String EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS = "android.speech.extras.SPEECH_INPUT_MINIMUM_LENGTH_MILLIS";
+    field public static final java.lang.String EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS = "android.speech.extras.SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS";
+    field public static final java.lang.String EXTRA_SUPPORTED_LANGUAGES = "android.speech.extra.SUPPORTED_LANGUAGES";
+    field public static final java.lang.String EXTRA_WEB_SEARCH_ONLY = "android.speech.extra.WEB_SEARCH_ONLY";
+    field public static final java.lang.String LANGUAGE_MODEL_FREE_FORM = "free_form";
+    field public static final java.lang.String LANGUAGE_MODEL_WEB_SEARCH = "web_search";
+    field public static final int RESULT_AUDIO_ERROR = 5; // 0x5
+    field public static final int RESULT_CLIENT_ERROR = 2; // 0x2
+    field public static final int RESULT_NETWORK_ERROR = 4; // 0x4
+    field public static final int RESULT_NO_MATCH = 1; // 0x1
+    field public static final int RESULT_SERVER_ERROR = 3; // 0x3
+  }
+
+  public class RecognizerResultsIntent {
+    field public static final java.lang.String ACTION_VOICE_SEARCH_RESULTS = "android.speech.action.VOICE_SEARCH_RESULTS";
+    field public static final java.lang.String EXTRA_VOICE_SEARCH_RESULT_HTML = "android.speech.extras.VOICE_SEARCH_RESULT_HTML";
+    field public static final java.lang.String EXTRA_VOICE_SEARCH_RESULT_HTML_BASE_URLS = "android.speech.extras.VOICE_SEARCH_RESULT_HTML_BASE_URLS";
+    field public static final java.lang.String EXTRA_VOICE_SEARCH_RESULT_HTTP_HEADERS = "android.speech.extras.EXTRA_VOICE_SEARCH_RESULT_HTTP_HEADERS";
+    field public static final java.lang.String EXTRA_VOICE_SEARCH_RESULT_STRINGS = "android.speech.extras.VOICE_SEARCH_RESULT_STRINGS";
+    field public static final java.lang.String EXTRA_VOICE_SEARCH_RESULT_URLS = "android.speech.extras.VOICE_SEARCH_RESULT_URLS";
+    field public static final java.lang.String URI_SCHEME_INLINE = "inline";
+  }
+
+  public class SpeechRecognizer {
+    method public void cancel();
+    method public static android.speech.SpeechRecognizer createSpeechRecognizer(android.content.Context);
+    method public static android.speech.SpeechRecognizer createSpeechRecognizer(android.content.Context, android.content.ComponentName);
+    method public void destroy();
+    method public static boolean isRecognitionAvailable(android.content.Context);
+    method public void setRecognitionListener(android.speech.RecognitionListener);
+    method public void startListening(android.content.Intent);
+    method public void stopListening();
+    field public static final java.lang.String CONFIDENCE_SCORES = "confidence_scores";
+    field public static final int ERROR_AUDIO = 3; // 0x3
+    field public static final int ERROR_CLIENT = 5; // 0x5
+    field public static final int ERROR_INSUFFICIENT_PERMISSIONS = 9; // 0x9
+    field public static final int ERROR_NETWORK = 2; // 0x2
+    field public static final int ERROR_NETWORK_TIMEOUT = 1; // 0x1
+    field public static final int ERROR_NO_MATCH = 7; // 0x7
+    field public static final int ERROR_RECOGNIZER_BUSY = 8; // 0x8
+    field public static final int ERROR_SERVER = 4; // 0x4
+    field public static final int ERROR_SPEECH_TIMEOUT = 6; // 0x6
+    field public static final java.lang.String RESULTS_RECOGNITION = "results_recognition";
+  }
+
+}
+
+package android.speech.tts {
+
+  public abstract interface SynthesisCallback {
+    method public abstract int audioAvailable(byte[], int, int);
+    method public abstract int done();
+    method public abstract void error();
+    method public abstract int getMaxBufferSize();
+    method public abstract int start(int, int, int);
+  }
+
+  public final class SynthesisRequest {
+    ctor public SynthesisRequest(java.lang.String, android.os.Bundle);
+    method public java.lang.String getCountry();
+    method public java.lang.String getLanguage();
+    method public android.os.Bundle getParams();
+    method public int getPitch();
+    method public int getSpeechRate();
+    method public java.lang.String getText();
+    method public java.lang.String getVariant();
+  }
+
+  public class TextToSpeech {
+    ctor public TextToSpeech(android.content.Context, android.speech.tts.TextToSpeech.OnInitListener);
+    ctor public TextToSpeech(android.content.Context, android.speech.tts.TextToSpeech.OnInitListener, java.lang.String);
+    method public int addEarcon(java.lang.String, java.lang.String, int);
+    method public int addEarcon(java.lang.String, java.lang.String);
+    method public int addSpeech(java.lang.String, java.lang.String, int);
+    method public int addSpeech(java.lang.String, java.lang.String);
+    method public boolean areDefaultsEnforced();
+    method public java.lang.String getDefaultEngine();
+    method public java.util.List<android.speech.tts.TextToSpeech.EngineInfo> getEngines();
+    method public java.util.Set<java.lang.String> getFeatures(java.util.Locale);
+    method public java.util.Locale getLanguage();
+    method public int isLanguageAvailable(java.util.Locale);
+    method public boolean isSpeaking();
+    method public int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>);
+    method public int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>);
+    method public deprecated int setEngineByPackageName(java.lang.String);
+    method public int setLanguage(java.util.Locale);
+    method public deprecated int setOnUtteranceCompletedListener(android.speech.tts.TextToSpeech.OnUtteranceCompletedListener);
+    method public int setOnUtteranceProgressListener(android.speech.tts.UtteranceProgressListener);
+    method public int setPitch(float);
+    method public int setSpeechRate(float);
+    method public void shutdown();
+    method public int speak(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>);
+    method public int stop();
+    method public int synthesizeToFile(java.lang.String, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String);
+    field public static final java.lang.String ACTION_TTS_QUEUE_PROCESSING_COMPLETED = "android.speech.tts.TTS_QUEUE_PROCESSING_COMPLETED";
+    field public static final int ERROR = -1; // 0xffffffff
+    field public static final int LANG_AVAILABLE = 0; // 0x0
+    field public static final int LANG_COUNTRY_AVAILABLE = 1; // 0x1
+    field public static final int LANG_COUNTRY_VAR_AVAILABLE = 2; // 0x2
+    field public static final int LANG_MISSING_DATA = -1; // 0xffffffff
+    field public static final int LANG_NOT_SUPPORTED = -2; // 0xfffffffe
+    field public static final int QUEUE_ADD = 1; // 0x1
+    field public static final int QUEUE_FLUSH = 0; // 0x0
+    field public static final int SUCCESS = 0; // 0x0
+  }
+
+  public class TextToSpeech.Engine {
+    ctor public TextToSpeech.Engine();
+    field public static final java.lang.String ACTION_CHECK_TTS_DATA = "android.speech.tts.engine.CHECK_TTS_DATA";
+    field public static final java.lang.String ACTION_INSTALL_TTS_DATA = "android.speech.tts.engine.INSTALL_TTS_DATA";
+    field public static final java.lang.String ACTION_TTS_DATA_INSTALLED = "android.speech.tts.engine.TTS_DATA_INSTALLED";
+    field public static final int CHECK_VOICE_DATA_BAD_DATA = -1; // 0xffffffff
+    field public static final int CHECK_VOICE_DATA_FAIL = 0; // 0x0
+    field public static final int CHECK_VOICE_DATA_MISSING_DATA = -2; // 0xfffffffe
+    field public static final int CHECK_VOICE_DATA_MISSING_VOLUME = -3; // 0xfffffffd
+    field public static final int CHECK_VOICE_DATA_PASS = 1; // 0x1
+    field public static final int DEFAULT_STREAM = 3; // 0x3
+    field public static final java.lang.String EXTRA_AVAILABLE_VOICES = "availableVoices";
+    field public static final java.lang.String EXTRA_CHECK_VOICE_DATA_FOR = "checkVoiceDataFor";
+    field public static final java.lang.String EXTRA_TTS_DATA_INSTALLED = "dataInstalled";
+    field public static final java.lang.String EXTRA_UNAVAILABLE_VOICES = "unavailableVoices";
+    field public static final java.lang.String EXTRA_VOICE_DATA_FILES = "dataFiles";
+    field public static final java.lang.String EXTRA_VOICE_DATA_FILES_INFO = "dataFilesInfo";
+    field public static final java.lang.String EXTRA_VOICE_DATA_ROOT_DIRECTORY = "dataRoot";
+    field public static final java.lang.String INTENT_ACTION_TTS_SERVICE = "android.intent.action.TTS_SERVICE";
+    field public static final java.lang.String KEY_FEATURE_EMBEDDED_SYNTHESIS = "embeddedTts";
+    field public static final java.lang.String KEY_FEATURE_NETWORK_SYNTHESIS = "networkTts";
+    field public static final java.lang.String KEY_PARAM_PAN = "pan";
+    field public static final java.lang.String KEY_PARAM_STREAM = "streamType";
+    field public static final java.lang.String KEY_PARAM_UTTERANCE_ID = "utteranceId";
+    field public static final java.lang.String KEY_PARAM_VOLUME = "volume";
+    field public static final java.lang.String SERVICE_META_DATA = "android.speech.tts";
+  }
+
+  public static class TextToSpeech.EngineInfo {
+    ctor public TextToSpeech.EngineInfo();
+    field public int icon;
+    field public java.lang.String label;
+    field public java.lang.String name;
+  }
+
+  public static abstract interface TextToSpeech.OnInitListener {
+    method public abstract void onInit(int);
+  }
+
+  public static abstract interface TextToSpeech.OnUtteranceCompletedListener {
+    method public abstract void onUtteranceCompleted(java.lang.String);
+  }
+
+  public abstract class TextToSpeechService extends android.app.Service {
+    ctor public TextToSpeechService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method protected java.util.Set<java.lang.String> onGetFeaturesForLanguage(java.lang.String, java.lang.String, java.lang.String);
+    method protected abstract java.lang.String[] onGetLanguage();
+    method protected abstract int onIsLanguageAvailable(java.lang.String, java.lang.String, java.lang.String);
+    method protected abstract int onLoadLanguage(java.lang.String, java.lang.String, java.lang.String);
+    method protected abstract void onStop();
+    method protected abstract void onSynthesizeText(android.speech.tts.SynthesisRequest, android.speech.tts.SynthesisCallback);
+  }
+
+  public abstract class UtteranceProgressListener {
+    ctor public UtteranceProgressListener();
+    method public abstract void onDone(java.lang.String);
+    method public abstract void onError(java.lang.String);
+    method public abstract void onStart(java.lang.String);
+  }
+
+}
+
+package android.telephony {
+
+  public final class CellIdentityCdma implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getBasestationId();
+    method public int getLatitude();
+    method public int getLongitude();
+    method public int getNetworkId();
+    method public int getSystemId();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellIdentityGsm implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getCid();
+    method public int getLac();
+    method public int getMcc();
+    method public int getMnc();
+    method public int getPsc();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellIdentityLte implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getCi();
+    method public int getMcc();
+    method public int getMnc();
+    method public int getPci();
+    method public int getTac();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public abstract class CellInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public long getTimeStamp();
+    method public boolean isRegistered();
+    method public abstract void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellInfoCdma extends android.telephony.CellInfo implements android.os.Parcelable {
+    method public android.telephony.CellIdentityCdma getCellIdentity();
+    method public android.telephony.CellSignalStrengthCdma getCellSignalStrength();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellInfoGsm extends android.telephony.CellInfo implements android.os.Parcelable {
+    method public android.telephony.CellIdentityGsm getCellIdentity();
+    method public android.telephony.CellSignalStrengthGsm getCellSignalStrength();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellInfoLte extends android.telephony.CellInfo implements android.os.Parcelable {
+    method public android.telephony.CellIdentityLte getCellIdentity();
+    method public android.telephony.CellSignalStrengthLte getCellSignalStrength();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public abstract class CellLocation {
+    ctor public CellLocation();
+    method public static android.telephony.CellLocation getEmpty();
+    method public static void requestLocationUpdate();
+  }
+
+  public abstract class CellSignalStrength {
+    method public abstract boolean equals(java.lang.Object);
+    method public abstract int getAsuLevel();
+    method public abstract int getDbm();
+    method public abstract int getLevel();
+    method public abstract int hashCode();
+  }
+
+  public final class CellSignalStrengthCdma extends android.telephony.CellSignalStrength implements android.os.Parcelable {
+    method public int describeContents();
+    method public boolean equals(java.lang.Object);
+    method public int getAsuLevel();
+    method public int getCdmaDbm();
+    method public int getCdmaEcio();
+    method public int getCdmaLevel();
+    method public int getDbm();
+    method public int getEvdoDbm();
+    method public int getEvdoEcio();
+    method public int getEvdoLevel();
+    method public int getEvdoSnr();
+    method public int getLevel();
+    method public int hashCode();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellSignalStrengthGsm extends android.telephony.CellSignalStrength implements android.os.Parcelable {
+    method public int describeContents();
+    method public boolean equals(java.lang.Object);
+    method public int getAsuLevel();
+    method public int getDbm();
+    method public int getLevel();
+    method public int hashCode();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellSignalStrengthLte extends android.telephony.CellSignalStrength implements android.os.Parcelable {
+    method public int describeContents();
+    method public boolean equals(java.lang.Object);
+    method public int getAsuLevel();
+    method public int getDbm();
+    method public int getLevel();
+    method public int getTimingAdvance();
+    method public int hashCode();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class NeighboringCellInfo implements android.os.Parcelable {
+    ctor public deprecated NeighboringCellInfo();
+    ctor public deprecated NeighboringCellInfo(int, int);
+    ctor public NeighboringCellInfo(int, java.lang.String, int);
+    ctor public NeighboringCellInfo(android.os.Parcel);
+    method public int describeContents();
+    method public int getCid();
+    method public int getLac();
+    method public int getNetworkType();
+    method public int getPsc();
+    method public int getRssi();
+    method public deprecated void setCid(int);
+    method public deprecated void setRssi(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int UNKNOWN_CID = -1; // 0xffffffff
+    field public static final int UNKNOWN_RSSI = 99; // 0x63
+  }
+
+  public class PhoneNumberFormattingTextWatcher implements android.text.TextWatcher {
+    ctor public PhoneNumberFormattingTextWatcher();
+    method public synchronized void afterTextChanged(android.text.Editable);
+    method public void beforeTextChanged(java.lang.CharSequence, int, int, int);
+    method public void onTextChanged(java.lang.CharSequence, int, int, int);
+  }
+
+  public class PhoneNumberUtils {
+    ctor public PhoneNumberUtils();
+    method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
+    method public static java.lang.String calledPartyBCDToString(byte[], int, int);
+    method public static boolean compare(java.lang.String, java.lang.String);
+    method public static boolean compare(android.content.Context, java.lang.String, java.lang.String);
+    method public static java.lang.String convertKeypadLettersToDigits(java.lang.String);
+    method public static java.lang.String extractNetworkPortion(java.lang.String);
+    method public static java.lang.String extractPostDialPortion(java.lang.String);
+    method public static void formatJapaneseNumber(android.text.Editable);
+    method public static void formatNanpNumber(android.text.Editable);
+    method public static java.lang.String formatNumber(java.lang.String);
+    method public static void formatNumber(android.text.Editable, int);
+    method public static int getFormatTypeForLocale(java.util.Locale);
+    method public static java.lang.String getNumberFromIntent(android.content.Intent, android.content.Context);
+    method public static java.lang.String getStrippedReversed(java.lang.String);
+    method public static final boolean is12Key(char);
+    method public static final boolean isDialable(char);
+    method public static boolean isEmergencyNumber(java.lang.String);
+    method public static boolean isGlobalPhoneNumber(java.lang.String);
+    method public static boolean isISODigit(char);
+    method public static final boolean isNonSeparator(char);
+    method public static final boolean isReallyDialable(char);
+    method public static final boolean isStartsPostDial(char);
+    method public static boolean isWellFormedSmsAddress(java.lang.String);
+    method public static byte[] networkPortionToCalledPartyBCD(java.lang.String);
+    method public static byte[] networkPortionToCalledPartyBCDWithLength(java.lang.String);
+    method public static byte[] numberToCalledPartyBCD(java.lang.String);
+    method public static java.lang.String stringFromStringAndTOA(java.lang.String, int);
+    method public static java.lang.String stripSeparators(java.lang.String);
+    method public static java.lang.String toCallerIDMinMatch(java.lang.String);
+    method public static int toaFromString(java.lang.String);
+    field public static final int FORMAT_JAPAN = 2; // 0x2
+    field public static final int FORMAT_NANP = 1; // 0x1
+    field public static final int FORMAT_UNKNOWN = 0; // 0x0
+    field public static final char PAUSE = 44; // 0x002c ','
+    field public static final int TOA_International = 145; // 0x91
+    field public static final int TOA_Unknown = 129; // 0x81
+    field public static final char WAIT = 59; // 0x003b ';'
+    field public static final char WILD = 78; // 0x004e 'N'
+  }
+
+  public class PhoneStateListener {
+    ctor public PhoneStateListener();
+    method public void onCallForwardingIndicatorChanged(boolean);
+    method public void onCallStateChanged(int, java.lang.String);
+    method public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>);
+    method public void onCellLocationChanged(android.telephony.CellLocation);
+    method public void onDataActivity(int);
+    method public void onDataConnectionStateChanged(int);
+    method public void onDataConnectionStateChanged(int, int);
+    method public void onMessageWaitingIndicatorChanged(boolean);
+    method public void onServiceStateChanged(android.telephony.ServiceState);
+    method public deprecated void onSignalStrengthChanged(int);
+    method public void onSignalStrengthsChanged(android.telephony.SignalStrength);
+    field public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8
+    field public static final int LISTEN_CALL_STATE = 32; // 0x20
+    field public static final int LISTEN_CELL_INFO = 1024; // 0x400
+    field public static final int LISTEN_CELL_LOCATION = 16; // 0x10
+    field public static final int LISTEN_DATA_ACTIVITY = 128; // 0x80
+    field public static final int LISTEN_DATA_CONNECTION_STATE = 64; // 0x40
+    field public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 4; // 0x4
+    field public static final int LISTEN_NONE = 0; // 0x0
+    field public static final int LISTEN_SERVICE_STATE = 1; // 0x1
+    field public static final deprecated int LISTEN_SIGNAL_STRENGTH = 2; // 0x2
+    field public static final int LISTEN_SIGNAL_STRENGTHS = 256; // 0x100
+  }
+
+  public class ServiceState implements android.os.Parcelable {
+    ctor public ServiceState();
+    ctor public ServiceState(android.telephony.ServiceState);
+    ctor public ServiceState(android.os.Parcel);
+    method protected void copyFrom(android.telephony.ServiceState);
+    method public int describeContents();
+    method public boolean getIsManualSelection();
+    method public java.lang.String getOperatorAlphaLong();
+    method public java.lang.String getOperatorAlphaShort();
+    method public java.lang.String getOperatorNumeric();
+    method public boolean getRoaming();
+    method public int getState();
+    method public void setIsManualSelection(boolean);
+    method public void setOperatorName(java.lang.String, java.lang.String, java.lang.String);
+    method public void setRoaming(boolean);
+    method public void setState(int);
+    method public void setStateOff();
+    method public void setStateOutOfService();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int STATE_EMERGENCY_ONLY = 2; // 0x2
+    field public static final int STATE_IN_SERVICE = 0; // 0x0
+    field public static final int STATE_OUT_OF_SERVICE = 1; // 0x1
+    field public static final int STATE_POWER_OFF = 3; // 0x3
+  }
+
+  public class SignalStrength implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getCdmaDbm();
+    method public int getCdmaEcio();
+    method public int getEvdoDbm();
+    method public int getEvdoEcio();
+    method public int getEvdoSnr();
+    method public int getGsmBitErrorRate();
+    method public int getGsmSignalStrength();
+    method public boolean isGsm();
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public final class SmsManager {
+    method public java.util.ArrayList<java.lang.String> divideMessage(java.lang.String);
+    method public static android.telephony.SmsManager getDefault();
+    method public void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
+    method public void sendMultipartTextMessage(java.lang.String, java.lang.String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
+    method public void sendTextMessage(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent);
+    field public static final int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1
+    field public static final int RESULT_ERROR_NO_SERVICE = 4; // 0x4
+    field public static final int RESULT_ERROR_NULL_PDU = 3; // 0x3
+    field public static final int RESULT_ERROR_RADIO_OFF = 2; // 0x2
+    field public static final int STATUS_ON_ICC_FREE = 0; // 0x0
+    field public static final int STATUS_ON_ICC_READ = 1; // 0x1
+    field public static final int STATUS_ON_ICC_SENT = 5; // 0x5
+    field public static final int STATUS_ON_ICC_UNREAD = 3; // 0x3
+    field public static final int STATUS_ON_ICC_UNSENT = 7; // 0x7
+  }
+
+  public class SmsMessage {
+    method public static int[] calculateLength(java.lang.CharSequence, boolean);
+    method public static int[] calculateLength(java.lang.String, boolean);
+    method public static android.telephony.SmsMessage createFromPdu(byte[]);
+    method public java.lang.String getDisplayMessageBody();
+    method public java.lang.String getDisplayOriginatingAddress();
+    method public java.lang.String getEmailBody();
+    method public java.lang.String getEmailFrom();
+    method public int getIndexOnIcc();
+    method public deprecated int getIndexOnSim();
+    method public java.lang.String getMessageBody();
+    method public android.telephony.SmsMessage.MessageClass getMessageClass();
+    method public java.lang.String getOriginatingAddress();
+    method public byte[] getPdu();
+    method public int getProtocolIdentifier();
+    method public java.lang.String getPseudoSubject();
+    method public java.lang.String getServiceCenterAddress();
+    method public int getStatus();
+    method public int getStatusOnIcc();
+    method public deprecated int getStatusOnSim();
+    method public static android.telephony.SmsMessage.SubmitPdu getSubmitPdu(java.lang.String, java.lang.String, java.lang.String, boolean);
+    method public static android.telephony.SmsMessage.SubmitPdu getSubmitPdu(java.lang.String, java.lang.String, short, byte[], boolean);
+    method public static int getTPLayerLengthForPDU(java.lang.String);
+    method public long getTimestampMillis();
+    method public byte[] getUserData();
+    method public boolean isCphsMwiMessage();
+    method public boolean isEmail();
+    method public boolean isMWIClearMessage();
+    method public boolean isMWISetMessage();
+    method public boolean isMwiDontStore();
+    method public boolean isReplace();
+    method public boolean isReplyPathPresent();
+    method public boolean isStatusReportMessage();
+    field public static final int ENCODING_16BIT = 3; // 0x3
+    field public static final int ENCODING_7BIT = 1; // 0x1
+    field public static final int ENCODING_8BIT = 2; // 0x2
+    field public static final int ENCODING_UNKNOWN = 0; // 0x0
+    field public static final int MAX_USER_DATA_BYTES = 140; // 0x8c
+    field public static final int MAX_USER_DATA_BYTES_WITH_HEADER = 134; // 0x86
+    field public static final int MAX_USER_DATA_SEPTETS = 160; // 0xa0
+    field public static final int MAX_USER_DATA_SEPTETS_WITH_HEADER = 153; // 0x99
+  }
+
+  public static final class SmsMessage.MessageClass extends java.lang.Enum {
+    method public static android.telephony.SmsMessage.MessageClass valueOf(java.lang.String);
+    method public static final android.telephony.SmsMessage.MessageClass[] values();
+    enum_constant public static final android.telephony.SmsMessage.MessageClass CLASS_0;
+    enum_constant public static final android.telephony.SmsMessage.MessageClass CLASS_1;
+    enum_constant public static final android.telephony.SmsMessage.MessageClass CLASS_2;
+    enum_constant public static final android.telephony.SmsMessage.MessageClass CLASS_3;
+    enum_constant public static final android.telephony.SmsMessage.MessageClass UNKNOWN;
+  }
+
+  public static class SmsMessage.SubmitPdu {
+    field public byte[] encodedMessage;
+    field public byte[] encodedScAddress;
+  }
+
+  public class TelephonyManager {
+    method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
+    method public int getCallState();
+    method public android.telephony.CellLocation getCellLocation();
+    method public int getDataActivity();
+    method public int getDataState();
+    method public java.lang.String getDeviceId();
+    method public java.lang.String getDeviceSoftwareVersion();
+    method public java.lang.String getLine1Number();
+    method public java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
+    method public java.lang.String getNetworkCountryIso();
+    method public java.lang.String getNetworkOperator();
+    method public java.lang.String getNetworkOperatorName();
+    method public int getNetworkType();
+    method public int getPhoneType();
+    method public java.lang.String getSimCountryIso();
+    method public java.lang.String getSimOperator();
+    method public java.lang.String getSimOperatorName();
+    method public java.lang.String getSimSerialNumber();
+    method public int getSimState();
+    method public java.lang.String getSubscriberId();
+    method public java.lang.String getVoiceMailAlphaTag();
+    method public java.lang.String getVoiceMailNumber();
+    method public boolean hasIccCard();
+    method public boolean isNetworkRoaming();
+    method public void listen(android.telephony.PhoneStateListener, int);
+    field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
+    field public static final int CALL_STATE_IDLE = 0; // 0x0
+    field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
+    field public static final int CALL_STATE_RINGING = 1; // 0x1
+    field public static final int DATA_ACTIVITY_DORMANT = 4; // 0x4
+    field public static final int DATA_ACTIVITY_IN = 1; // 0x1
+    field public static final int DATA_ACTIVITY_INOUT = 3; // 0x3
+    field public static final int DATA_ACTIVITY_NONE = 0; // 0x0
+    field public static final int DATA_ACTIVITY_OUT = 2; // 0x2
+    field public static final int DATA_CONNECTED = 2; // 0x2
+    field public static final int DATA_CONNECTING = 1; // 0x1
+    field public static final int DATA_DISCONNECTED = 0; // 0x0
+    field public static final int DATA_SUSPENDED = 3; // 0x3
+    field public static final java.lang.String EXTRA_INCOMING_NUMBER = "incoming_number";
+    field public static final java.lang.String EXTRA_STATE = "state";
+    field public static final java.lang.String EXTRA_STATE_IDLE;
+    field public static final java.lang.String EXTRA_STATE_OFFHOOK;
+    field public static final java.lang.String EXTRA_STATE_RINGING;
+    field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7
+    field public static final int NETWORK_TYPE_CDMA = 4; // 0x4
+    field public static final int NETWORK_TYPE_EDGE = 2; // 0x2
+    field public static final int NETWORK_TYPE_EHRPD = 14; // 0xe
+    field public static final int NETWORK_TYPE_EVDO_0 = 5; // 0x5
+    field public static final int NETWORK_TYPE_EVDO_A = 6; // 0x6
+    field public static final int NETWORK_TYPE_EVDO_B = 12; // 0xc
+    field public static final int NETWORK_TYPE_GPRS = 1; // 0x1
+    field public static final int NETWORK_TYPE_HSDPA = 8; // 0x8
+    field public static final int NETWORK_TYPE_HSPA = 10; // 0xa
+    field public static final int NETWORK_TYPE_HSPAP = 15; // 0xf
+    field public static final int NETWORK_TYPE_HSUPA = 9; // 0x9
+    field public static final int NETWORK_TYPE_IDEN = 11; // 0xb
+    field public static final int NETWORK_TYPE_LTE = 13; // 0xd
+    field public static final int NETWORK_TYPE_UMTS = 3; // 0x3
+    field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
+    field public static final int PHONE_TYPE_CDMA = 2; // 0x2
+    field public static final int PHONE_TYPE_GSM = 1; // 0x1
+    field public static final int PHONE_TYPE_NONE = 0; // 0x0
+    field public static final int PHONE_TYPE_SIP = 3; // 0x3
+    field public static final int SIM_STATE_ABSENT = 1; // 0x1
+    field public static final int SIM_STATE_NETWORK_LOCKED = 4; // 0x4
+    field public static final int SIM_STATE_PIN_REQUIRED = 2; // 0x2
+    field public static final int SIM_STATE_PUK_REQUIRED = 3; // 0x3
+    field public static final int SIM_STATE_READY = 5; // 0x5
+    field public static final int SIM_STATE_UNKNOWN = 0; // 0x0
+  }
+
+}
+
+package android.telephony.cdma {
+
+  public class CdmaCellLocation extends android.telephony.CellLocation {
+    ctor public CdmaCellLocation();
+    ctor public CdmaCellLocation(android.os.Bundle);
+    method public static double convertQuartSecToDecDegrees(int);
+    method public void fillInNotifierBundle(android.os.Bundle);
+    method public int getBaseStationId();
+    method public int getBaseStationLatitude();
+    method public int getBaseStationLongitude();
+    method public int getNetworkId();
+    method public int getSystemId();
+    method public void setCellLocationData(int, int, int);
+    method public void setCellLocationData(int, int, int, int, int);
+    method public void setStateInvalid();
+  }
+
+}
+
+package android.telephony.gsm {
+
+  public class GsmCellLocation extends android.telephony.CellLocation {
+    ctor public GsmCellLocation();
+    ctor public GsmCellLocation(android.os.Bundle);
+    method public void fillInNotifierBundle(android.os.Bundle);
+    method public int getCid();
+    method public int getLac();
+    method public int getPsc();
+    method public void setLacAndCid(int, int);
+    method public void setStateInvalid();
+  }
+
+  public final deprecated class SmsManager {
+    method public final deprecated java.util.ArrayList<java.lang.String> divideMessage(java.lang.String);
+    method public static final deprecated android.telephony.gsm.SmsManager getDefault();
+    method public final deprecated void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
+    method public final deprecated void sendMultipartTextMessage(java.lang.String, java.lang.String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
+    method public final deprecated void sendTextMessage(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent);
+    field public static final deprecated int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1
+    field public static final deprecated int RESULT_ERROR_NO_SERVICE = 4; // 0x4
+    field public static final deprecated int RESULT_ERROR_NULL_PDU = 3; // 0x3
+    field public static final deprecated int RESULT_ERROR_RADIO_OFF = 2; // 0x2
+    field public static final deprecated int STATUS_ON_SIM_FREE = 0; // 0x0
+    field public static final deprecated int STATUS_ON_SIM_READ = 1; // 0x1
+    field public static final deprecated int STATUS_ON_SIM_SENT = 5; // 0x5
+    field public static final deprecated int STATUS_ON_SIM_UNREAD = 3; // 0x3
+    field public static final deprecated int STATUS_ON_SIM_UNSENT = 7; // 0x7
+  }
+
+  public deprecated class SmsMessage {
+    ctor public deprecated SmsMessage();
+    method public static deprecated int[] calculateLength(java.lang.CharSequence, boolean);
+    method public static deprecated int[] calculateLength(java.lang.String, boolean);
+    method public static deprecated android.telephony.gsm.SmsMessage createFromPdu(byte[]);
+    method public deprecated java.lang.String getDisplayMessageBody();
+    method public deprecated java.lang.String getDisplayOriginatingAddress();
+    method public deprecated java.lang.String getEmailBody();
+    method public deprecated java.lang.String getEmailFrom();
+    method public deprecated int getIndexOnSim();
+    method public deprecated java.lang.String getMessageBody();
+    method public deprecated android.telephony.gsm.SmsMessage.MessageClass getMessageClass();
+    method public deprecated java.lang.String getOriginatingAddress();
+    method public deprecated byte[] getPdu();
+    method public deprecated int getProtocolIdentifier();
+    method public deprecated java.lang.String getPseudoSubject();
+    method public deprecated java.lang.String getServiceCenterAddress();
+    method public deprecated int getStatus();
+    method public deprecated int getStatusOnSim();
+    method public static deprecated android.telephony.gsm.SmsMessage.SubmitPdu getSubmitPdu(java.lang.String, java.lang.String, java.lang.String, boolean);
+    method public static deprecated android.telephony.gsm.SmsMessage.SubmitPdu getSubmitPdu(java.lang.String, java.lang.String, short, byte[], boolean);
+    method public static deprecated int getTPLayerLengthForPDU(java.lang.String);
+    method public deprecated long getTimestampMillis();
+    method public deprecated byte[] getUserData();
+    method public deprecated boolean isCphsMwiMessage();
+    method public deprecated boolean isEmail();
+    method public deprecated boolean isMWIClearMessage();
+    method public deprecated boolean isMWISetMessage();
+    method public deprecated boolean isMwiDontStore();
+    method public deprecated boolean isReplace();
+    method public deprecated boolean isReplyPathPresent();
+    method public deprecated boolean isStatusReportMessage();
+    field public static final deprecated int ENCODING_16BIT = 3; // 0x3
+    field public static final deprecated int ENCODING_7BIT = 1; // 0x1
+    field public static final deprecated int ENCODING_8BIT = 2; // 0x2
+    field public static final deprecated int ENCODING_UNKNOWN = 0; // 0x0
+    field public static final deprecated int MAX_USER_DATA_BYTES = 140; // 0x8c
+    field public static final deprecated int MAX_USER_DATA_SEPTETS = 160; // 0xa0
+    field public static final deprecated int MAX_USER_DATA_SEPTETS_WITH_HEADER = 153; // 0x99
+  }
+
+  public static final deprecated class SmsMessage.MessageClass extends java.lang.Enum {
+    method public static android.telephony.gsm.SmsMessage.MessageClass valueOf(java.lang.String);
+    method public static final android.telephony.gsm.SmsMessage.MessageClass[] values();
+    enum_constant public static final android.telephony.gsm.SmsMessage.MessageClass CLASS_0;
+    enum_constant public static final android.telephony.gsm.SmsMessage.MessageClass CLASS_1;
+    enum_constant public static final android.telephony.gsm.SmsMessage.MessageClass CLASS_2;
+    enum_constant public static final android.telephony.gsm.SmsMessage.MessageClass CLASS_3;
+    enum_constant public static final android.telephony.gsm.SmsMessage.MessageClass UNKNOWN;
+  }
+
+  public static deprecated class SmsMessage.SubmitPdu {
+    ctor public deprecated SmsMessage.SubmitPdu();
+    field public deprecated byte[] encodedMessage;
+    field public deprecated byte[] encodedScAddress;
+  }
+
+}
+
+package android.test {
+
+  public abstract deprecated class ActivityInstrumentationTestCase extends android.test.ActivityTestCase {
+    ctor public ActivityInstrumentationTestCase(java.lang.String, java.lang.Class<T>);
+    ctor public ActivityInstrumentationTestCase(java.lang.String, java.lang.Class<T>, boolean);
+    method public T getActivity();
+    method public void testActivityTestCaseSetUpProperly() throws java.lang.Exception;
+  }
+
+  public abstract class ActivityInstrumentationTestCase2 extends android.test.ActivityTestCase {
+    ctor public deprecated ActivityInstrumentationTestCase2(java.lang.String, java.lang.Class<T>);
+    ctor public ActivityInstrumentationTestCase2(java.lang.Class<T>);
+    method public T getActivity();
+    method public void setActivityInitialTouchMode(boolean);
+    method public void setActivityIntent(android.content.Intent);
+  }
+
+  public abstract class ActivityTestCase extends android.test.InstrumentationTestCase {
+    ctor public ActivityTestCase();
+    method protected android.app.Activity getActivity();
+    method protected void scrubClass(java.lang.Class<?>) throws java.lang.IllegalAccessException;
+    method protected void setActivity(android.app.Activity);
+  }
+
+  public abstract class ActivityUnitTestCase extends android.test.ActivityTestCase {
+    ctor public ActivityUnitTestCase(java.lang.Class<T>);
+    method public T getActivity();
+    method public int getFinishedActivityRequest();
+    method public int getRequestedOrientation();
+    method public android.content.Intent getStartedActivityIntent();
+    method public int getStartedActivityRequest();
+    method public boolean isFinishCalled();
+    method public void setActivityContext(android.content.Context);
+    method public void setApplication(android.app.Application);
+    method protected T startActivity(android.content.Intent, android.os.Bundle, java.lang.Object);
+  }
+
+  public class AndroidTestCase extends junit.framework.TestCase {
+    ctor public AndroidTestCase();
+    method public void assertActivityRequiresPermission(java.lang.String, java.lang.String, java.lang.String);
+    method public void assertReadingContentUriRequiresPermission(android.net.Uri, java.lang.String);
+    method public void assertWritingContentUriRequiresPermission(android.net.Uri, java.lang.String);
+    method public android.content.Context getContext();
+    method protected void scrubClass(java.lang.Class<?>) throws java.lang.IllegalAccessException;
+    method public void setContext(android.content.Context);
+    method public void testAndroidTestCaseSetupProperly();
+    field protected android.content.Context mContext;
+  }
+
+  public class AndroidTestRunner extends junit.runner.BaseTestRunner {
+    ctor public AndroidTestRunner();
+    method public void addTestListener(junit.framework.TestListener);
+    method public void clearTestListeners();
+    method protected junit.framework.TestResult createTestResult();
+    method public java.util.List<junit.framework.TestCase> getTestCases();
+    method public java.lang.String getTestClassName();
+    method public junit.framework.TestResult getTestResult();
+    method protected void runFailed(java.lang.String);
+    method public void runTest();
+    method public void runTest(junit.framework.TestResult);
+    method public void setContext(android.content.Context);
+    method public deprecated void setInstrumentaiton(android.app.Instrumentation);
+    method public void setInstrumentation(android.app.Instrumentation);
+    method public void setTest(junit.framework.Test);
+    method public void setTestClassName(java.lang.String, java.lang.String);
+    method public void testEnded(java.lang.String);
+    method public void testFailed(int, junit.framework.Test, java.lang.Throwable);
+    method public void testStarted(java.lang.String);
+  }
+
+  public abstract class ApplicationTestCase extends android.test.AndroidTestCase {
+    ctor public ApplicationTestCase(java.lang.Class<T>);
+    method protected final void createApplication();
+    method public T getApplication();
+    method public android.content.Context getSystemContext();
+    method protected final void terminateApplication();
+    method public final void testApplicationTestCaseSetUpProperly() throws java.lang.Exception;
+  }
+
+  public deprecated class AssertionFailedError extends java.lang.Error {
+    ctor public AssertionFailedError();
+    ctor public AssertionFailedError(java.lang.String);
+  }
+
+  public deprecated class ComparisonFailure extends android.test.AssertionFailedError {
+    ctor public ComparisonFailure(java.lang.String, java.lang.String, java.lang.String);
+  }
+
+  public abstract class FlakyTest implements java.lang.annotation.Annotation {
+  }
+
+  public class InstrumentationTestCase extends junit.framework.TestCase {
+    ctor public InstrumentationTestCase();
+    method public android.app.Instrumentation getInstrumentation();
+    method public deprecated void injectInsrumentation(android.app.Instrumentation);
+    method public void injectInstrumentation(android.app.Instrumentation);
+    method public final T launchActivity(java.lang.String, java.lang.Class<T>, android.os.Bundle);
+    method public final T launchActivityWithIntent(java.lang.String, java.lang.Class<T>, android.content.Intent);
+    method public void runTestOnUiThread(java.lang.Runnable) throws java.lang.Throwable;
+    method public void sendKeys(java.lang.String);
+    method public void sendKeys(int...);
+    method public void sendRepeatedKeys(int...);
+  }
+
+  public class InstrumentationTestRunner extends android.app.Instrumentation implements android.test.TestSuiteProvider {
+    ctor public InstrumentationTestRunner();
+    method public junit.framework.TestSuite getAllTests();
+    method protected android.test.AndroidTestRunner getAndroidTestRunner();
+    method public java.lang.ClassLoader getLoader();
+    method public junit.framework.TestSuite getTestSuite();
+    field public static final java.lang.String REPORT_KEY_NAME_CLASS = "class";
+    field public static final java.lang.String REPORT_KEY_NAME_TEST = "test";
+    field public static final java.lang.String REPORT_KEY_NUM_CURRENT = "current";
+    field public static final java.lang.String REPORT_KEY_NUM_TOTAL = "numtests";
+    field public static final java.lang.String REPORT_KEY_STACK = "stack";
+    field public static final java.lang.String REPORT_VALUE_ID = "InstrumentationTestRunner";
+    field public static final int REPORT_VALUE_RESULT_ERROR = -1; // 0xffffffff
+    field public static final int REPORT_VALUE_RESULT_FAILURE = -2; // 0xfffffffe
+    field public static final int REPORT_VALUE_RESULT_OK = 0; // 0x0
+    field public static final int REPORT_VALUE_RESULT_START = 1; // 0x1
+  }
+
+  public class InstrumentationTestSuite extends junit.framework.TestSuite {
+    ctor public InstrumentationTestSuite(android.app.Instrumentation);
+    ctor public InstrumentationTestSuite(java.lang.String, android.app.Instrumentation);
+    ctor public InstrumentationTestSuite(java.lang.Class, android.app.Instrumentation);
+    method public void addTestSuite(java.lang.Class);
+  }
+
+  public class IsolatedContext extends android.content.ContextWrapper {
+    ctor public IsolatedContext(android.content.ContentResolver, android.content.Context);
+    method public java.util.List<android.content.Intent> getAndClearBroadcastIntents();
+  }
+
+  public class LoaderTestCase extends android.test.AndroidTestCase {
+    ctor public LoaderTestCase();
+    method public T getLoaderResultSynchronously(android.content.Loader<T>);
+  }
+
+  public final class MoreAsserts {
+    method public static void assertAssignableFrom(java.lang.Class<?>, java.lang.Object);
+    method public static void assertAssignableFrom(java.lang.Class<?>, java.lang.Class<?>);
+    method public static java.util.regex.MatchResult assertContainsRegex(java.lang.String, java.lang.String, java.lang.String);
+    method public static java.util.regex.MatchResult assertContainsRegex(java.lang.String, java.lang.String);
+    method public static void assertContentsInAnyOrder(java.lang.String, java.lang.Iterable<?>, java.lang.Object...);
+    method public static void assertContentsInAnyOrder(java.lang.Iterable<?>, java.lang.Object...);
+    method public static void assertContentsInOrder(java.lang.String, java.lang.Iterable<?>, java.lang.Object...);
+    method public static void assertContentsInOrder(java.lang.Iterable<?>, java.lang.Object...);
+    method public static void assertEmpty(java.lang.String, java.lang.Iterable<?>);
+    method public static void assertEmpty(java.lang.Iterable<?>);
+    method public static void assertEmpty(java.lang.String, java.util.Map<?, ?>);
+    method public static void assertEmpty(java.util.Map<?, ?>);
+    method public static void assertEquals(java.lang.String, byte[], byte[]);
+    method public static void assertEquals(byte[], byte[]);
+    method public static void assertEquals(java.lang.String, int[], int[]);
+    method public static void assertEquals(int[], int[]);
+    method public static void assertEquals(java.lang.String, double[], double[]);
+    method public static void assertEquals(double[], double[]);
+    method public static void assertEquals(java.lang.String, java.lang.Object[], java.lang.Object[]);
+    method public static void assertEquals(java.lang.Object[], java.lang.Object[]);
+    method public static void assertEquals(java.lang.String, java.util.Set<? extends java.lang.Object>, java.util.Set<? extends java.lang.Object>);
+    method public static void assertEquals(java.util.Set<? extends java.lang.Object>, java.util.Set<? extends java.lang.Object>);
+    method public static java.util.regex.MatchResult assertMatchesRegex(java.lang.String, java.lang.String, java.lang.String);
+    method public static java.util.regex.MatchResult assertMatchesRegex(java.lang.String, java.lang.String);
+    method public static void assertNotContainsRegex(java.lang.String, java.lang.String, java.lang.String);
+    method public static void assertNotContainsRegex(java.lang.String, java.lang.String);
+    method public static void assertNotEmpty(java.lang.String, java.lang.Iterable<?>);
+    method public static void assertNotEmpty(java.lang.Iterable<?>);
+    method public static void assertNotEmpty(java.lang.String, java.util.Map<?, ?>);
+    method public static void assertNotEmpty(java.util.Map<?, ?>);
+    method public static void assertNotEqual(java.lang.String, java.lang.Object, java.lang.Object);
+    method public static void assertNotEqual(java.lang.Object, java.lang.Object);
+    method public static void assertNotMatchesRegex(java.lang.String, java.lang.String, java.lang.String);
+    method public static void assertNotMatchesRegex(java.lang.String, java.lang.String);
+    method public static void checkEqualsAndHashCodeMethods(java.lang.String, java.lang.Object, java.lang.Object, boolean);
+    method public static void checkEqualsAndHashCodeMethods(java.lang.Object, java.lang.Object, boolean);
+  }
+
+  public abstract interface PerformanceTestCase {
+    method public abstract boolean isPerformanceOnly();
+    method public abstract int startPerformance(android.test.PerformanceTestCase.Intermediates);
+  }
+
+  public static abstract interface PerformanceTestCase.Intermediates {
+    method public abstract void addIntermediate(java.lang.String);
+    method public abstract void addIntermediate(java.lang.String, long);
+    method public abstract void finishTiming(boolean);
+    method public abstract void setInternalIterations(int);
+    method public abstract void startTiming(boolean);
+  }
+
+  public abstract deprecated class ProviderTestCase extends android.test.InstrumentationTestCase {
+    ctor public ProviderTestCase(java.lang.Class<T>, java.lang.String);
+    method public android.test.mock.MockContentResolver getMockContentResolver();
+    method public android.test.IsolatedContext getMockContext();
+    method public T getProvider();
+    method public static android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+  }
+
+  public abstract class ProviderTestCase2 extends android.test.AndroidTestCase {
+    ctor public ProviderTestCase2(java.lang.Class<T>, java.lang.String);
+    method public android.test.mock.MockContentResolver getMockContentResolver();
+    method public android.test.IsolatedContext getMockContext();
+    method public T getProvider();
+    method public static android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.String, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+  }
+
+  public class RenamingDelegatingContext extends android.content.ContextWrapper {
+    ctor public RenamingDelegatingContext(android.content.Context, java.lang.String);
+    ctor public RenamingDelegatingContext(android.content.Context, android.content.Context, java.lang.String);
+    method public java.lang.String getDatabasePrefix();
+    method public void makeExistingFilesAndDbsAccessible();
+    method public static T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public static T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String, boolean) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+  }
+
+  public abstract class ServiceTestCase extends android.test.AndroidTestCase {
+    ctor public ServiceTestCase(java.lang.Class<T>);
+    method protected android.os.IBinder bindService(android.content.Intent);
+    method public android.app.Application getApplication();
+    method public T getService();
+    method public android.content.Context getSystemContext();
+    method public void setApplication(android.app.Application);
+    method protected void setupService();
+    method protected void shutdownService();
+    method protected void startService(android.content.Intent);
+    method public void testServiceTestCaseSetUpProperly() throws java.lang.Exception;
+  }
+
+  public abstract class SingleLaunchActivityTestCase extends android.test.InstrumentationTestCase {
+    ctor public SingleLaunchActivityTestCase(java.lang.String, java.lang.Class<T>);
+    method public T getActivity();
+    method public void testActivityTestCaseSetUpProperly() throws java.lang.Exception;
+  }
+
+  public class SyncBaseInstrumentation extends android.test.InstrumentationTestCase {
+    ctor public SyncBaseInstrumentation();
+    method protected void cancelSyncsandDisableAutoSync();
+    method protected void syncProvider(android.net.Uri, java.lang.String, java.lang.String) throws java.lang.Exception;
+  }
+
+  public abstract interface TestSuiteProvider {
+    method public abstract junit.framework.TestSuite getTestSuite();
+  }
+
+  public class TouchUtils {
+    ctor public TouchUtils();
+    method public static void clickView(android.test.InstrumentationTestCase, android.view.View);
+    method public static deprecated void drag(android.test.ActivityInstrumentationTestCase, float, float, float, float, int);
+    method public static void drag(android.test.InstrumentationTestCase, float, float, float, float, int);
+    method public static deprecated void dragQuarterScreenDown(android.test.ActivityInstrumentationTestCase);
+    method public static void dragQuarterScreenDown(android.test.InstrumentationTestCase, android.app.Activity);
+    method public static deprecated void dragQuarterScreenUp(android.test.ActivityInstrumentationTestCase);
+    method public static void dragQuarterScreenUp(android.test.InstrumentationTestCase, android.app.Activity);
+    method public static deprecated int dragViewBy(android.test.ActivityInstrumentationTestCase, android.view.View, int, int, int);
+    method public static deprecated int dragViewBy(android.test.InstrumentationTestCase, android.view.View, int, int, int);
+    method public static deprecated int dragViewTo(android.test.ActivityInstrumentationTestCase, android.view.View, int, int, int);
+    method public static int dragViewTo(android.test.InstrumentationTestCase, android.view.View, int, int, int);
+    method public static deprecated void dragViewToBottom(android.test.ActivityInstrumentationTestCase, android.view.View);
+    method public static void dragViewToBottom(android.test.InstrumentationTestCase, android.app.Activity, android.view.View);
+    method public static deprecated void dragViewToBottom(android.test.ActivityInstrumentationTestCase, android.view.View, int);
+    method public static void dragViewToBottom(android.test.InstrumentationTestCase, android.app.Activity, android.view.View, int);
+    method public static deprecated void dragViewToTop(android.test.ActivityInstrumentationTestCase, android.view.View);
+    method public static deprecated void dragViewToTop(android.test.ActivityInstrumentationTestCase, android.view.View, int);
+    method public static void dragViewToTop(android.test.InstrumentationTestCase, android.view.View);
+    method public static void dragViewToTop(android.test.InstrumentationTestCase, android.view.View, int);
+    method public static deprecated int dragViewToX(android.test.ActivityInstrumentationTestCase, android.view.View, int, int);
+    method public static int dragViewToX(android.test.InstrumentationTestCase, android.view.View, int, int);
+    method public static deprecated int dragViewToY(android.test.ActivityInstrumentationTestCase, android.view.View, int, int);
+    method public static int dragViewToY(android.test.InstrumentationTestCase, android.view.View, int, int);
+    method public static deprecated void longClickView(android.test.ActivityInstrumentationTestCase, android.view.View);
+    method public static void longClickView(android.test.InstrumentationTestCase, android.view.View);
+    method public static deprecated void scrollToBottom(android.test.ActivityInstrumentationTestCase, android.view.ViewGroup);
+    method public static void scrollToBottom(android.test.InstrumentationTestCase, android.app.Activity, android.view.ViewGroup);
+    method public static deprecated void scrollToTop(android.test.ActivityInstrumentationTestCase, android.view.ViewGroup);
+    method public static void scrollToTop(android.test.InstrumentationTestCase, android.app.Activity, android.view.ViewGroup);
+    method public static void tapView(android.test.InstrumentationTestCase, android.view.View);
+    method public static void touchAndCancelView(android.test.InstrumentationTestCase, android.view.View);
+  }
+
+  public abstract class UiThreadTest implements java.lang.annotation.Annotation {
+  }
+
+  public class ViewAsserts {
+    method public static void assertBaselineAligned(android.view.View, android.view.View);
+    method public static void assertBottomAligned(android.view.View, android.view.View);
+    method public static void assertBottomAligned(android.view.View, android.view.View, int);
+    method public static void assertGroupContains(android.view.ViewGroup, android.view.View);
+    method public static void assertGroupIntegrity(android.view.ViewGroup);
+    method public static void assertGroupNotContains(android.view.ViewGroup, android.view.View);
+    method public static void assertHasScreenCoordinates(android.view.View, android.view.View, int, int);
+    method public static void assertHorizontalCenterAligned(android.view.View, android.view.View);
+    method public static void assertLeftAligned(android.view.View, android.view.View);
+    method public static void assertLeftAligned(android.view.View, android.view.View, int);
+    method public static void assertOffScreenAbove(android.view.View, android.view.View);
+    method public static void assertOffScreenBelow(android.view.View, android.view.View);
+    method public static void assertOnScreen(android.view.View, android.view.View);
+    method public static void assertRightAligned(android.view.View, android.view.View);
+    method public static void assertRightAligned(android.view.View, android.view.View, int);
+    method public static void assertTopAligned(android.view.View, android.view.View);
+    method public static void assertTopAligned(android.view.View, android.view.View, int);
+    method public static void assertVerticalCenterAligned(android.view.View, android.view.View);
+  }
+
+}
+
+package android.test.mock {
+
+  public class MockApplication extends android.app.Application {
+    ctor public MockApplication();
+  }
+
+  public class MockContentProvider extends android.content.ContentProvider {
+    ctor protected MockContentProvider();
+    ctor public MockContentProvider(android.content.Context);
+    ctor public MockContentProvider(android.content.Context, java.lang.String, java.lang.String, android.content.pm.PathPermission[]);
+    method public int delete(android.net.Uri, java.lang.String, java.lang.String[]);
+    method public java.lang.String getType(android.net.Uri);
+    method public android.net.Uri insert(android.net.Uri, android.content.ContentValues);
+    method public boolean onCreate();
+    method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
+    method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
+  }
+
+  public class MockContentResolver extends android.content.ContentResolver {
+    ctor public MockContentResolver();
+    method public void addProvider(java.lang.String, android.content.ContentProvider);
+  }
+
+  public class MockContext extends android.content.Context {
+    ctor public MockContext();
+    method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
+    method public int checkCallingOrSelfPermission(java.lang.String);
+    method public int checkCallingOrSelfUriPermission(android.net.Uri, int);
+    method public int checkCallingPermission(java.lang.String);
+    method public int checkCallingUriPermission(android.net.Uri, int);
+    method public int checkPermission(java.lang.String, int, int);
+    method public int checkUriPermission(android.net.Uri, int, int, int);
+    method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
+    method public void clearWallpaper();
+    method public android.content.Context createConfigurationContext(android.content.res.Configuration);
+    method public android.content.Context createDisplayContext(android.view.Display);
+    method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public java.lang.String[] databaseList();
+    method public boolean deleteDatabase(java.lang.String);
+    method public boolean deleteFile(java.lang.String);
+    method public void enforceCallingOrSelfPermission(java.lang.String, java.lang.String);
+    method public void enforceCallingOrSelfUriPermission(android.net.Uri, int, java.lang.String);
+    method public void enforceCallingPermission(java.lang.String, java.lang.String);
+    method public void enforceCallingUriPermission(android.net.Uri, int, java.lang.String);
+    method public void enforcePermission(java.lang.String, int, int, java.lang.String);
+    method public void enforceUriPermission(android.net.Uri, int, int, int, java.lang.String);
+    method public void enforceUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int, java.lang.String);
+    method public java.lang.String[] fileList();
+    method public android.content.Context getApplicationContext();
+    method public android.content.pm.ApplicationInfo getApplicationInfo();
+    method public android.content.res.AssetManager getAssets();
+    method public java.io.File getCacheDir();
+    method public java.lang.ClassLoader getClassLoader();
+    method public android.content.ContentResolver getContentResolver();
+    method public java.io.File getDatabasePath(java.lang.String);
+    method public java.io.File getDir(java.lang.String, int);
+    method public java.io.File getExternalCacheDir();
+    method public java.io.File getExternalFilesDir(java.lang.String);
+    method public java.io.File getFileStreamPath(java.lang.String);
+    method public java.io.File getFilesDir();
+    method public android.os.Looper getMainLooper();
+    method public java.io.File getObbDir();
+    method public java.lang.String getPackageCodePath();
+    method public android.content.pm.PackageManager getPackageManager();
+    method public java.lang.String getPackageName();
+    method public java.lang.String getPackageResourcePath();
+    method public android.content.res.Resources getResources();
+    method public android.content.SharedPreferences getSharedPreferences(java.lang.String, int);
+    method public java.lang.Object getSystemService(java.lang.String);
+    method public android.content.res.Resources.Theme getTheme();
+    method public android.graphics.drawable.Drawable getWallpaper();
+    method public int getWallpaperDesiredMinimumHeight();
+    method public int getWallpaperDesiredMinimumWidth();
+    method public void grantUriPermission(java.lang.String, android.net.Uri, int);
+    method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
+    method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
+    method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
+    method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory, android.database.DatabaseErrorHandler);
+    method public android.graphics.drawable.Drawable peekWallpaper();
+    method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter);
+    method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler);
+    method public void removeStickyBroadcast(android.content.Intent);
+    method public void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+    method public void revokeUriPermission(android.net.Uri, int);
+    method public void sendBroadcast(android.content.Intent);
+    method public void sendBroadcast(android.content.Intent, java.lang.String);
+    method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+    method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String);
+    method public void sendOrderedBroadcast(android.content.Intent, java.lang.String);
+    method public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public void sendStickyBroadcast(android.content.Intent);
+    method public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+    method public void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public void setTheme(int);
+    method public void setWallpaper(android.graphics.Bitmap) throws java.io.IOException;
+    method public void setWallpaper(java.io.InputStream) throws java.io.IOException;
+    method public void startActivities(android.content.Intent[]);
+    method public void startActivities(android.content.Intent[], android.os.Bundle);
+    method public void startActivity(android.content.Intent);
+    method public void startActivity(android.content.Intent, android.os.Bundle);
+    method public boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
+    method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
+    method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
+    method public android.content.ComponentName startService(android.content.Intent);
+    method public boolean stopService(android.content.Intent);
+    method public void unbindService(android.content.ServiceConnection);
+    method public void unregisterReceiver(android.content.BroadcastReceiver);
+  }
+
+  public class MockCursor implements android.database.Cursor {
+    ctor public MockCursor();
+    method public void close();
+    method public void copyStringToBuffer(int, android.database.CharArrayBuffer);
+    method public void deactivate();
+    method public byte[] getBlob(int);
+    method public int getColumnCount();
+    method public int getColumnIndex(java.lang.String);
+    method public int getColumnIndexOrThrow(java.lang.String);
+    method public java.lang.String getColumnName(int);
+    method public java.lang.String[] getColumnNames();
+    method public int getCount();
+    method public double getDouble(int);
+    method public android.os.Bundle getExtras();
+    method public float getFloat(int);
+    method public int getInt(int);
+    method public long getLong(int);
+    method public int getPosition();
+    method public short getShort(int);
+    method public java.lang.String getString(int);
+    method public int getType(int);
+    method public boolean getWantsAllOnMoveCalls();
+    method public boolean isAfterLast();
+    method public boolean isBeforeFirst();
+    method public boolean isClosed();
+    method public boolean isFirst();
+    method public boolean isLast();
+    method public boolean isNull(int);
+    method public boolean move(int);
+    method public boolean moveToFirst();
+    method public boolean moveToLast();
+    method public boolean moveToNext();
+    method public boolean moveToPosition(int);
+    method public boolean moveToPrevious();
+    method public void registerContentObserver(android.database.ContentObserver);
+    method public void registerDataSetObserver(android.database.DataSetObserver);
+    method public boolean requery();
+    method public android.os.Bundle respond(android.os.Bundle);
+    method public void setNotificationUri(android.content.ContentResolver, android.net.Uri);
+    method public void unregisterContentObserver(android.database.ContentObserver);
+    method public void unregisterDataSetObserver(android.database.DataSetObserver);
+  }
+
+  public class MockDialogInterface implements android.content.DialogInterface {
+    ctor public MockDialogInterface();
+    method public void cancel();
+    method public void dismiss();
+  }
+
+  public class MockPackageManager extends android.content.pm.PackageManager {
+    ctor public MockPackageManager();
+    method public void addPackageToPreferred(java.lang.String);
+    method public boolean addPermission(android.content.pm.PermissionInfo);
+    method public boolean addPermissionAsync(android.content.pm.PermissionInfo);
+    method public void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+    method public java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
+    method public int checkPermission(java.lang.String, java.lang.String);
+    method public int checkSignatures(java.lang.String, java.lang.String);
+    method public int checkSignatures(int, int);
+    method public void clearPackagePreferredActivities(java.lang.String);
+    method public java.lang.String[] currentToCanonicalPackageNames(java.lang.String[]);
+    method public void extendVerificationTimeout(int, int, long);
+    method public android.graphics.drawable.Drawable getActivityIcon(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.graphics.drawable.Drawable getActivityIcon(android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.ActivityInfo getActivityInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.graphics.drawable.Drawable getActivityLogo(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.graphics.drawable.Drawable getActivityLogo(android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public java.util.List<android.content.pm.PermissionGroupInfo> getAllPermissionGroups(int);
+    method public int getApplicationEnabledSetting(java.lang.String);
+    method public android.graphics.drawable.Drawable getApplicationIcon(android.content.pm.ApplicationInfo);
+    method public android.graphics.drawable.Drawable getApplicationIcon(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public java.lang.CharSequence getApplicationLabel(android.content.pm.ApplicationInfo);
+    method public android.graphics.drawable.Drawable getApplicationLogo(android.content.pm.ApplicationInfo);
+    method public android.graphics.drawable.Drawable getApplicationLogo(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public int getComponentEnabledSetting(android.content.ComponentName);
+    method public android.graphics.drawable.Drawable getDefaultActivityIcon();
+    method public android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
+    method public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
+    method public java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
+    method public java.lang.String getInstallerPackageName(java.lang.String);
+    method public android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.Intent getLaunchIntentForPackage(java.lang.String);
+    method public java.lang.String getNameForUid(int);
+    method public int[] getPackageGids(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.PackageInfo getPackageInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public java.lang.String[] getPackagesForUid(int);
+    method public android.content.pm.PermissionGroupInfo getPermissionGroupInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.PermissionInfo getPermissionInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public int getPreferredActivities(java.util.List<android.content.IntentFilter>, java.util.List<android.content.ComponentName>, java.lang.String);
+    method public java.util.List<android.content.pm.PackageInfo> getPreferredPackages(int);
+    method public android.content.pm.ProviderInfo getProviderInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.ActivityInfo getReceiverInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.res.Resources getResourcesForActivity(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.res.Resources getResourcesForApplication(android.content.pm.ApplicationInfo);
+    method public android.content.res.Resources getResourcesForApplication(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
+    method public java.lang.String[] getSystemSharedLibraryNames();
+    method public java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
+    method public android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
+    method public boolean hasSystemFeature(java.lang.String);
+    method public boolean isSafeMode();
+    method public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
+    method public java.util.List<android.content.pm.ProviderInfo> queryContentProviders(java.lang.String, int, int);
+    method public java.util.List<android.content.pm.InstrumentationInfo> queryInstrumentation(java.lang.String, int);
+    method public java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(android.content.Intent, int);
+    method public java.util.List<android.content.pm.ResolveInfo> queryIntentActivityOptions(android.content.ComponentName, android.content.Intent[], android.content.Intent, int);
+    method public java.util.List<android.content.pm.ResolveInfo> queryIntentServices(android.content.Intent, int);
+    method public java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public void removePackageFromPreferred(java.lang.String);
+    method public void removePermission(java.lang.String);
+    method public android.content.pm.ResolveInfo resolveActivity(android.content.Intent, int);
+    method public android.content.pm.ProviderInfo resolveContentProvider(java.lang.String, int);
+    method public android.content.pm.ResolveInfo resolveService(android.content.Intent, int);
+    method public void setApplicationEnabledSetting(java.lang.String, int, int);
+    method public void setComponentEnabledSetting(android.content.ComponentName, int, int);
+    method public void setInstallerPackageName(java.lang.String, java.lang.String);
+    method public void verifyPendingInstall(int, int);
+  }
+
+  public class MockResources extends android.content.res.Resources {
+    ctor public MockResources();
+  }
+
+}
+
+package android.test.suitebuilder {
+
+  public class TestMethod {
+    ctor public TestMethod(java.lang.reflect.Method, java.lang.Class<? extends junit.framework.TestCase>);
+    ctor public TestMethod(java.lang.String, java.lang.Class<? extends junit.framework.TestCase>);
+    ctor public TestMethod(junit.framework.TestCase);
+    method public junit.framework.TestCase createTest() throws java.lang.IllegalAccessException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException;
+    method public T getAnnotation(java.lang.Class<T>);
+    method public java.lang.Class<? extends junit.framework.TestCase> getEnclosingClass();
+    method public java.lang.String getEnclosingClassname();
+    method public java.lang.String getName();
+  }
+
+  public class TestSuiteBuilder {
+    ctor public TestSuiteBuilder(java.lang.Class);
+    ctor public TestSuiteBuilder(java.lang.String, java.lang.ClassLoader);
+    method public android.test.suitebuilder.TestSuiteBuilder addRequirements(java.util.List<com.android.internal.util.Predicate<android.test.suitebuilder.TestMethod>>);
+    method public final android.test.suitebuilder.TestSuiteBuilder addRequirements(com.android.internal.util.Predicate<android.test.suitebuilder.TestMethod>...);
+    method public final junit.framework.TestSuite build();
+    method public android.test.suitebuilder.TestSuiteBuilder excludePackages(java.lang.String...);
+    method protected java.lang.String getSuiteName();
+    method public final android.test.suitebuilder.TestSuiteBuilder includeAllPackagesUnderHere();
+    method public android.test.suitebuilder.TestSuiteBuilder includePackages(java.lang.String...);
+    method public android.test.suitebuilder.TestSuiteBuilder named(java.lang.String);
+  }
+
+  public static class TestSuiteBuilder.FailedToCreateTests extends junit.framework.TestCase {
+    ctor public TestSuiteBuilder.FailedToCreateTests(java.lang.Exception);
+    method public void testSuiteConstructionFailed();
+  }
+
+}
+
+package android.test.suitebuilder.annotation {
+
+  public abstract class LargeTest implements java.lang.annotation.Annotation {
+  }
+
+  public abstract class MediumTest implements java.lang.annotation.Annotation {
+  }
+
+  public abstract class SmallTest implements java.lang.annotation.Annotation {
+  }
+
+  public abstract class Smoke implements java.lang.annotation.Annotation {
+  }
+
+  public abstract class Suppress implements java.lang.annotation.Annotation {
+  }
+
+}
+
+package android.text {
+
+  public class AlteredCharSequence implements java.lang.CharSequence android.text.GetChars {
+    method public char charAt(int);
+    method public void getChars(int, int, char[], int);
+    method public int length();
+    method public static android.text.AlteredCharSequence make(java.lang.CharSequence, char[], int, int);
+    method public java.lang.CharSequence subSequence(int, int);
+  }
+
+  public class AndroidCharacter {
+    ctor public AndroidCharacter();
+    method public static void getDirectionalities(char[], byte[], int);
+    method public static int getEastAsianWidth(char);
+    method public static void getEastAsianWidths(char[], int, int, byte[]);
+    method public static char getMirror(char);
+    method public static boolean mirror(char[], int, int);
+    field public static final int EAST_ASIAN_WIDTH_AMBIGUOUS = 1; // 0x1
+    field public static final int EAST_ASIAN_WIDTH_FULL_WIDTH = 3; // 0x3
+    field public static final int EAST_ASIAN_WIDTH_HALF_WIDTH = 2; // 0x2
+    field public static final int EAST_ASIAN_WIDTH_NARROW = 4; // 0x4
+    field public static final int EAST_ASIAN_WIDTH_NEUTRAL = 0; // 0x0
+    field public static final int EAST_ASIAN_WIDTH_WIDE = 5; // 0x5
+  }
+
+  public class Annotation implements android.text.ParcelableSpan {
+    ctor public Annotation(java.lang.String, java.lang.String);
+    ctor public Annotation(android.os.Parcel);
+    method public int describeContents();
+    method public java.lang.String getKey();
+    method public int getSpanTypeId();
+    method public java.lang.String getValue();
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class AutoText {
+    method public static java.lang.String get(java.lang.CharSequence, int, int, android.view.View);
+    method public static int getSize(android.view.View);
+  }
+
+  public class BoringLayout extends android.text.Layout implements android.text.TextUtils.EllipsizeCallback {
+    ctor public BoringLayout(java.lang.CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, android.text.BoringLayout.Metrics, boolean);
+    ctor public BoringLayout(java.lang.CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, android.text.BoringLayout.Metrics, boolean, android.text.TextUtils.TruncateAt, int);
+    method public void ellipsized(int, int);
+    method public int getBottomPadding();
+    method public int getEllipsisCount(int);
+    method public int getEllipsisStart(int);
+    method public boolean getLineContainsTab(int);
+    method public int getLineCount();
+    method public int getLineDescent(int);
+    method public final android.text.Layout.Directions getLineDirections(int);
+    method public int getLineStart(int);
+    method public int getLineTop(int);
+    method public int getParagraphDirection(int);
+    method public int getTopPadding();
+    method public static android.text.BoringLayout.Metrics isBoring(java.lang.CharSequence, android.text.TextPaint);
+    method public static android.text.BoringLayout.Metrics isBoring(java.lang.CharSequence, android.text.TextPaint, android.text.BoringLayout.Metrics);
+    method public static android.text.BoringLayout make(java.lang.CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, android.text.BoringLayout.Metrics, boolean);
+    method public static android.text.BoringLayout make(java.lang.CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, android.text.BoringLayout.Metrics, boolean, android.text.TextUtils.TruncateAt, int);
+    method public android.text.BoringLayout replaceOrMake(java.lang.CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, android.text.BoringLayout.Metrics, boolean);
+    method public android.text.BoringLayout replaceOrMake(java.lang.CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, android.text.BoringLayout.Metrics, boolean, android.text.TextUtils.TruncateAt, int);
+  }
+
+  public static class BoringLayout.Metrics extends android.graphics.Paint.FontMetricsInt {
+    ctor public BoringLayout.Metrics();
+    field public int width;
+  }
+
+  public abstract deprecated class ClipboardManager {
+    ctor public ClipboardManager();
+    method public abstract java.lang.CharSequence getText();
+    method public abstract boolean hasText();
+    method public abstract void setText(java.lang.CharSequence);
+  }
+
+  public class DynamicLayout extends android.text.Layout {
+    ctor public DynamicLayout(java.lang.CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, boolean);
+    ctor public DynamicLayout(java.lang.CharSequence, java.lang.CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, boolean);
+    ctor public DynamicLayout(java.lang.CharSequence, java.lang.CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, boolean, android.text.TextUtils.TruncateAt, int);
+    method public int getBottomPadding();
+    method public int getEllipsisCount(int);
+    method public int getEllipsisStart(int);
+    method public boolean getLineContainsTab(int);
+    method public int getLineCount();
+    method public int getLineDescent(int);
+    method public final android.text.Layout.Directions getLineDirections(int);
+    method public int getLineStart(int);
+    method public int getLineTop(int);
+    method public int getParagraphDirection(int);
+    method public int getTopPadding();
+  }
+
+  public abstract interface Editable implements java.lang.Appendable java.lang.CharSequence android.text.GetChars android.text.Spannable {
+    method public abstract android.text.Editable append(java.lang.CharSequence);
+    method public abstract android.text.Editable append(java.lang.CharSequence, int, int);
+    method public abstract android.text.Editable append(char);
+    method public abstract void clear();
+    method public abstract void clearSpans();
+    method public abstract android.text.Editable delete(int, int);
+    method public abstract android.text.InputFilter[] getFilters();
+    method public abstract android.text.Editable insert(int, java.lang.CharSequence, int, int);
+    method public abstract android.text.Editable insert(int, java.lang.CharSequence);
+    method public abstract android.text.Editable replace(int, int, java.lang.CharSequence, int, int);
+    method public abstract android.text.Editable replace(int, int, java.lang.CharSequence);
+    method public abstract void setFilters(android.text.InputFilter[]);
+  }
+
+  public static class Editable.Factory {
+    ctor public Editable.Factory();
+    method public static android.text.Editable.Factory getInstance();
+    method public android.text.Editable newEditable(java.lang.CharSequence);
+  }
+
+  public abstract interface GetChars implements java.lang.CharSequence {
+    method public abstract void getChars(int, int, char[], int);
+  }
+
+  public class Html {
+    method public static java.lang.String escapeHtml(java.lang.CharSequence);
+    method public static android.text.Spanned fromHtml(java.lang.String);
+    method public static android.text.Spanned fromHtml(java.lang.String, android.text.Html.ImageGetter, android.text.Html.TagHandler);
+    method public static java.lang.String toHtml(android.text.Spanned);
+  }
+
+  public static abstract interface Html.ImageGetter {
+    method public abstract android.graphics.drawable.Drawable getDrawable(java.lang.String);
+  }
+
+  public static abstract interface Html.TagHandler {
+    method public abstract void handleTag(boolean, java.lang.String, android.text.Editable, org.xml.sax.XMLReader);
+  }
+
+  public abstract interface InputFilter {
+    method public abstract java.lang.CharSequence filter(java.lang.CharSequence, int, int, android.text.Spanned, int, int);
+  }
+
+  public static class InputFilter.AllCaps implements android.text.InputFilter {
+    ctor public InputFilter.AllCaps();
+    method public java.lang.CharSequence filter(java.lang.CharSequence, int, int, android.text.Spanned, int, int);
+  }
+
+  public static class InputFilter.LengthFilter implements android.text.InputFilter {
+    ctor public InputFilter.LengthFilter(int);
+    method public java.lang.CharSequence filter(java.lang.CharSequence, int, int, android.text.Spanned, int, int);
+  }
+
+  public abstract interface InputType {
+    field public static final int TYPE_CLASS_DATETIME = 4; // 0x4
+    field public static final int TYPE_CLASS_NUMBER = 2; // 0x2
+    field public static final int TYPE_CLASS_PHONE = 3; // 0x3
+    field public static final int TYPE_CLASS_TEXT = 1; // 0x1
+    field public static final int TYPE_DATETIME_VARIATION_DATE = 16; // 0x10
+    field public static final int TYPE_DATETIME_VARIATION_NORMAL = 0; // 0x0
+    field public static final int TYPE_DATETIME_VARIATION_TIME = 32; // 0x20
+    field public static final int TYPE_MASK_CLASS = 15; // 0xf
+    field public static final int TYPE_MASK_FLAGS = 16773120; // 0xfff000
+    field public static final int TYPE_MASK_VARIATION = 4080; // 0xff0
+    field public static final int TYPE_NULL = 0; // 0x0
+    field public static final int TYPE_NUMBER_FLAG_DECIMAL = 8192; // 0x2000
+    field public static final int TYPE_NUMBER_FLAG_SIGNED = 4096; // 0x1000
+    field public static final int TYPE_NUMBER_VARIATION_NORMAL = 0; // 0x0
+    field public static final int TYPE_NUMBER_VARIATION_PASSWORD = 16; // 0x10
+    field public static final int TYPE_TEXT_FLAG_AUTO_COMPLETE = 65536; // 0x10000
+    field public static final int TYPE_TEXT_FLAG_AUTO_CORRECT = 32768; // 0x8000
+    field public static final int TYPE_TEXT_FLAG_CAP_CHARACTERS = 4096; // 0x1000
+    field public static final int TYPE_TEXT_FLAG_CAP_SENTENCES = 16384; // 0x4000
+    field public static final int TYPE_TEXT_FLAG_CAP_WORDS = 8192; // 0x2000
+    field public static final int TYPE_TEXT_FLAG_IME_MULTI_LINE = 262144; // 0x40000
+    field public static final int TYPE_TEXT_FLAG_MULTI_LINE = 131072; // 0x20000
+    field public static final int TYPE_TEXT_FLAG_NO_SUGGESTIONS = 524288; // 0x80000
+    field public static final int TYPE_TEXT_VARIATION_EMAIL_ADDRESS = 32; // 0x20
+    field public static final int TYPE_TEXT_VARIATION_EMAIL_SUBJECT = 48; // 0x30
+    field public static final int TYPE_TEXT_VARIATION_FILTER = 176; // 0xb0
+    field public static final int TYPE_TEXT_VARIATION_LONG_MESSAGE = 80; // 0x50
+    field public static final int TYPE_TEXT_VARIATION_NORMAL = 0; // 0x0
+    field public static final int TYPE_TEXT_VARIATION_PASSWORD = 128; // 0x80
+    field public static final int TYPE_TEXT_VARIATION_PERSON_NAME = 96; // 0x60
+    field public static final int TYPE_TEXT_VARIATION_PHONETIC = 192; // 0xc0
+    field public static final int TYPE_TEXT_VARIATION_POSTAL_ADDRESS = 112; // 0x70
+    field public static final int TYPE_TEXT_VARIATION_SHORT_MESSAGE = 64; // 0x40
+    field public static final int TYPE_TEXT_VARIATION_URI = 16; // 0x10
+    field public static final int TYPE_TEXT_VARIATION_VISIBLE_PASSWORD = 144; // 0x90
+    field public static final int TYPE_TEXT_VARIATION_WEB_EDIT_TEXT = 160; // 0xa0
+    field public static final int TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS = 208; // 0xd0
+    field public static final int TYPE_TEXT_VARIATION_WEB_PASSWORD = 224; // 0xe0
+  }
+
+  public abstract class Layout {
+    ctor protected Layout(java.lang.CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float);
+    method public void draw(android.graphics.Canvas);
+    method public void draw(android.graphics.Canvas, android.graphics.Path, android.graphics.Paint, int);
+    method public final android.text.Layout.Alignment getAlignment();
+    method public abstract int getBottomPadding();
+    method public void getCursorPath(int, android.graphics.Path, java.lang.CharSequence);
+    method public static float getDesiredWidth(java.lang.CharSequence, android.text.TextPaint);
+    method public static float getDesiredWidth(java.lang.CharSequence, int, int, android.text.TextPaint);
+    method public abstract int getEllipsisCount(int);
+    method public abstract int getEllipsisStart(int);
+    method public int getEllipsizedWidth();
+    method public int getHeight();
+    method public final int getLineAscent(int);
+    method public final int getLineBaseline(int);
+    method public final int getLineBottom(int);
+    method public int getLineBounds(int, android.graphics.Rect);
+    method public abstract boolean getLineContainsTab(int);
+    method public abstract int getLineCount();
+    method public abstract int getLineDescent(int);
+    method public abstract android.text.Layout.Directions getLineDirections(int);
+    method public final int getLineEnd(int);
+    method public int getLineForOffset(int);
+    method public int getLineForVertical(int);
+    method public float getLineLeft(int);
+    method public float getLineMax(int);
+    method public float getLineRight(int);
+    method public abstract int getLineStart(int);
+    method public abstract int getLineTop(int);
+    method public int getLineVisibleEnd(int);
+    method public float getLineWidth(int);
+    method public int getOffsetForHorizontal(int, float);
+    method public int getOffsetToLeftOf(int);
+    method public int getOffsetToRightOf(int);
+    method public final android.text.TextPaint getPaint();
+    method public final android.text.Layout.Alignment getParagraphAlignment(int);
+    method public abstract int getParagraphDirection(int);
+    method public final int getParagraphLeft(int);
+    method public final int getParagraphRight(int);
+    method public float getPrimaryHorizontal(int);
+    method public float getSecondaryHorizontal(int);
+    method public void getSelectionPath(int, int, android.graphics.Path);
+    method public final float getSpacingAdd();
+    method public final float getSpacingMultiplier();
+    method public final java.lang.CharSequence getText();
+    method public abstract int getTopPadding();
+    method public final int getWidth();
+    method public final void increaseWidthTo(int);
+    method public boolean isRtlCharAt(int);
+    method protected final boolean isSpanned();
+    field public static final int DIR_LEFT_TO_RIGHT = 1; // 0x1
+    field public static final int DIR_RIGHT_TO_LEFT = -1; // 0xffffffff
+  }
+
+  public static final class Layout.Alignment extends java.lang.Enum {
+    method public static android.text.Layout.Alignment valueOf(java.lang.String);
+    method public static final android.text.Layout.Alignment[] values();
+    enum_constant public static final android.text.Layout.Alignment ALIGN_CENTER;
+    enum_constant public static final android.text.Layout.Alignment ALIGN_NORMAL;
+    enum_constant public static final android.text.Layout.Alignment ALIGN_OPPOSITE;
+  }
+
+  public static class Layout.Directions {
+  }
+
+  public abstract class LoginFilter implements android.text.InputFilter {
+    method public java.lang.CharSequence filter(java.lang.CharSequence, int, int, android.text.Spanned, int, int);
+    method public abstract boolean isAllowed(char);
+    method public void onInvalidCharacter(char);
+    method public void onStart();
+    method public void onStop();
+  }
+
+  public static class LoginFilter.PasswordFilterGMail extends android.text.LoginFilter {
+    ctor public LoginFilter.PasswordFilterGMail();
+    ctor public LoginFilter.PasswordFilterGMail(boolean);
+    method public boolean isAllowed(char);
+  }
+
+  public static class LoginFilter.UsernameFilterGMail extends android.text.LoginFilter {
+    ctor public LoginFilter.UsernameFilterGMail();
+    ctor public LoginFilter.UsernameFilterGMail(boolean);
+    method public boolean isAllowed(char);
+  }
+
+  public static class LoginFilter.UsernameFilterGeneric extends android.text.LoginFilter {
+    ctor public LoginFilter.UsernameFilterGeneric();
+    ctor public LoginFilter.UsernameFilterGeneric(boolean);
+    method public boolean isAllowed(char);
+  }
+
+  public abstract interface NoCopySpan {
+  }
+
+  public static class NoCopySpan.Concrete implements android.text.NoCopySpan {
+    ctor public NoCopySpan.Concrete();
+  }
+
+  public abstract interface ParcelableSpan implements android.os.Parcelable {
+    method public abstract int getSpanTypeId();
+  }
+
+  public class Selection {
+    method public static boolean extendDown(android.text.Spannable, android.text.Layout);
+    method public static boolean extendLeft(android.text.Spannable, android.text.Layout);
+    method public static boolean extendRight(android.text.Spannable, android.text.Layout);
+    method public static final void extendSelection(android.text.Spannable, int);
+    method public static boolean extendToLeftEdge(android.text.Spannable, android.text.Layout);
+    method public static boolean extendToRightEdge(android.text.Spannable, android.text.Layout);
+    method public static boolean extendUp(android.text.Spannable, android.text.Layout);
+    method public static final int getSelectionEnd(java.lang.CharSequence);
+    method public static final int getSelectionStart(java.lang.CharSequence);
+    method public static boolean moveDown(android.text.Spannable, android.text.Layout);
+    method public static boolean moveLeft(android.text.Spannable, android.text.Layout);
+    method public static boolean moveRight(android.text.Spannable, android.text.Layout);
+    method public static boolean moveToLeftEdge(android.text.Spannable, android.text.Layout);
+    method public static boolean moveToRightEdge(android.text.Spannable, android.text.Layout);
+    method public static boolean moveUp(android.text.Spannable, android.text.Layout);
+    method public static final void removeSelection(android.text.Spannable);
+    method public static final void selectAll(android.text.Spannable);
+    method public static void setSelection(android.text.Spannable, int, int);
+    method public static final void setSelection(android.text.Spannable, int);
+    field public static final java.lang.Object SELECTION_END;
+    field public static final java.lang.Object SELECTION_START;
+  }
+
+  public abstract interface SpanWatcher implements android.text.NoCopySpan {
+    method public abstract void onSpanAdded(android.text.Spannable, java.lang.Object, int, int);
+    method public abstract void onSpanChanged(android.text.Spannable, java.lang.Object, int, int, int, int);
+    method public abstract void onSpanRemoved(android.text.Spannable, java.lang.Object, int, int);
+  }
+
+  public abstract interface Spannable implements android.text.Spanned {
+    method public abstract void removeSpan(java.lang.Object);
+    method public abstract void setSpan(java.lang.Object, int, int, int);
+  }
+
+  public static class Spannable.Factory {
+    ctor public Spannable.Factory();
+    method public static android.text.Spannable.Factory getInstance();
+    method public android.text.Spannable newSpannable(java.lang.CharSequence);
+  }
+
+  public class SpannableString extends android.text.SpannableStringInternal implements java.lang.CharSequence android.text.GetChars android.text.Spannable {
+    ctor public SpannableString(java.lang.CharSequence);
+    method public void removeSpan(java.lang.Object);
+    method public void setSpan(java.lang.Object, int, int, int);
+    method public final java.lang.CharSequence subSequence(int, int);
+    method public static android.text.SpannableString valueOf(java.lang.CharSequence);
+  }
+
+  public class SpannableStringBuilder implements java.lang.Appendable java.lang.CharSequence android.text.Editable android.text.GetChars android.text.Spannable {
+    ctor public SpannableStringBuilder();
+    ctor public SpannableStringBuilder(java.lang.CharSequence);
+    ctor public SpannableStringBuilder(java.lang.CharSequence, int, int);
+    method public android.text.SpannableStringBuilder append(java.lang.CharSequence);
+    method public android.text.SpannableStringBuilder append(java.lang.CharSequence, int, int);
+    method public android.text.SpannableStringBuilder append(char);
+    method public char charAt(int);
+    method public void clear();
+    method public void clearSpans();
+    method public android.text.SpannableStringBuilder delete(int, int);
+    method public void getChars(int, int, char[], int);
+    method public android.text.InputFilter[] getFilters();
+    method public int getSpanEnd(java.lang.Object);
+    method public int getSpanFlags(java.lang.Object);
+    method public int getSpanStart(java.lang.Object);
+    method public T[] getSpans(int, int, java.lang.Class<T>);
+    method public deprecated int getTextRunCursor(int, int, int, int, int, android.graphics.Paint);
+    method public android.text.SpannableStringBuilder insert(int, java.lang.CharSequence, int, int);
+    method public android.text.SpannableStringBuilder insert(int, java.lang.CharSequence);
+    method public int length();
+    method public int nextSpanTransition(int, int, java.lang.Class);
+    method public void removeSpan(java.lang.Object);
+    method public android.text.SpannableStringBuilder replace(int, int, java.lang.CharSequence);
+    method public android.text.SpannableStringBuilder replace(int, int, java.lang.CharSequence, int, int);
+    method public void setFilters(android.text.InputFilter[]);
+    method public void setSpan(java.lang.Object, int, int, int);
+    method public java.lang.CharSequence subSequence(int, int);
+    method public static android.text.SpannableStringBuilder valueOf(java.lang.CharSequence);
+  }
+
+   abstract class SpannableStringInternal {
+    method public final char charAt(int);
+    method public final void getChars(int, int, char[], int);
+    method public int getSpanEnd(java.lang.Object);
+    method public int getSpanFlags(java.lang.Object);
+    method public int getSpanStart(java.lang.Object);
+    method public T[] getSpans(int, int, java.lang.Class<T>);
+    method public final int length();
+    method public int nextSpanTransition(int, int, java.lang.Class);
+    method public final java.lang.String toString();
+  }
+
+  public abstract interface Spanned implements java.lang.CharSequence {
+    method public abstract int getSpanEnd(java.lang.Object);
+    method public abstract int getSpanFlags(java.lang.Object);
+    method public abstract int getSpanStart(java.lang.Object);
+    method public abstract T[] getSpans(int, int, java.lang.Class<T>);
+    method public abstract int nextSpanTransition(int, int, java.lang.Class);
+    field public static final int SPAN_COMPOSING = 256; // 0x100
+    field public static final int SPAN_EXCLUSIVE_EXCLUSIVE = 33; // 0x21
+    field public static final int SPAN_EXCLUSIVE_INCLUSIVE = 34; // 0x22
+    field public static final int SPAN_INCLUSIVE_EXCLUSIVE = 17; // 0x11
+    field public static final int SPAN_INCLUSIVE_INCLUSIVE = 18; // 0x12
+    field public static final int SPAN_INTERMEDIATE = 512; // 0x200
+    field public static final int SPAN_MARK_MARK = 17; // 0x11
+    field public static final int SPAN_MARK_POINT = 18; // 0x12
+    field public static final int SPAN_PARAGRAPH = 51; // 0x33
+    field public static final int SPAN_POINT_MARK = 33; // 0x21
+    field public static final int SPAN_POINT_MARK_MASK = 51; // 0x33
+    field public static final int SPAN_POINT_POINT = 34; // 0x22
+    field public static final int SPAN_PRIORITY = 16711680; // 0xff0000
+    field public static final int SPAN_PRIORITY_SHIFT = 16; // 0x10
+    field public static final int SPAN_USER = -16777216; // 0xff000000
+    field public static final int SPAN_USER_SHIFT = 24; // 0x18
+  }
+
+  public final class SpannedString extends android.text.SpannableStringInternal implements java.lang.CharSequence android.text.GetChars android.text.Spanned {
+    ctor public SpannedString(java.lang.CharSequence);
+    method public java.lang.CharSequence subSequence(int, int);
+    method public static android.text.SpannedString valueOf(java.lang.CharSequence);
+  }
+
+  public class StaticLayout extends android.text.Layout {
+    ctor public StaticLayout(java.lang.CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, boolean);
+    ctor public StaticLayout(java.lang.CharSequence, int, int, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, boolean);
+    ctor public StaticLayout(java.lang.CharSequence, int, int, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, boolean, android.text.TextUtils.TruncateAt, int);
+    method public int getBottomPadding();
+    method public int getEllipsisCount(int);
+    method public int getEllipsisStart(int);
+    method public boolean getLineContainsTab(int);
+    method public int getLineCount();
+    method public int getLineDescent(int);
+    method public final android.text.Layout.Directions getLineDirections(int);
+    method public int getLineStart(int);
+    method public int getLineTop(int);
+    method public int getParagraphDirection(int);
+    method public int getTopPadding();
+  }
+
+  public class TextPaint extends android.graphics.Paint {
+    ctor public TextPaint();
+    ctor public TextPaint(int);
+    ctor public TextPaint(android.graphics.Paint);
+    method public void set(android.text.TextPaint);
+    field public int baselineShift;
+    field public int bgColor;
+    field public float density;
+    field public int[] drawableState;
+    field public int linkColor;
+  }
+
+  public class TextUtils {
+    method public static java.lang.CharSequence commaEllipsize(java.lang.CharSequence, android.text.TextPaint, float, java.lang.String, java.lang.String);
+    method public static java.lang.CharSequence concat(java.lang.CharSequence...);
+    method public static void copySpansFrom(android.text.Spanned, int, int, java.lang.Class, android.text.Spannable, int);
+    method public static void dumpSpans(java.lang.CharSequence, android.util.Printer, java.lang.String);
+    method public static java.lang.CharSequence ellipsize(java.lang.CharSequence, android.text.TextPaint, float, android.text.TextUtils.TruncateAt);
+    method public static java.lang.CharSequence ellipsize(java.lang.CharSequence, android.text.TextPaint, float, android.text.TextUtils.TruncateAt, boolean, android.text.TextUtils.EllipsizeCallback);
+    method public static boolean equals(java.lang.CharSequence, java.lang.CharSequence);
+    method public static java.lang.CharSequence expandTemplate(java.lang.CharSequence, java.lang.CharSequence...);
+    method public static int getCapsMode(java.lang.CharSequence, int, int);
+    method public static void getChars(java.lang.CharSequence, int, int, char[], int);
+    method public static int getLayoutDirectionFromLocale(java.util.Locale);
+    method public static int getOffsetAfter(java.lang.CharSequence, int);
+    method public static int getOffsetBefore(java.lang.CharSequence, int);
+    method public static java.lang.CharSequence getReverse(java.lang.CharSequence, int, int);
+    method public static int getTrimmedLength(java.lang.CharSequence);
+    method public static java.lang.String htmlEncode(java.lang.String);
+    method public static int indexOf(java.lang.CharSequence, char);
+    method public static int indexOf(java.lang.CharSequence, char, int);
+    method public static int indexOf(java.lang.CharSequence, char, int, int);
+    method public static int indexOf(java.lang.CharSequence, java.lang.CharSequence);
+    method public static int indexOf(java.lang.CharSequence, java.lang.CharSequence, int);
+    method public static int indexOf(java.lang.CharSequence, java.lang.CharSequence, int, int);
+    method public static boolean isDigitsOnly(java.lang.CharSequence);
+    method public static boolean isEmpty(java.lang.CharSequence);
+    method public static boolean isGraphic(java.lang.CharSequence);
+    method public static boolean isGraphic(char);
+    method public static java.lang.String join(java.lang.CharSequence, java.lang.Object[]);
+    method public static java.lang.String join(java.lang.CharSequence, java.lang.Iterable);
+    method public static int lastIndexOf(java.lang.CharSequence, char);
+    method public static int lastIndexOf(java.lang.CharSequence, char, int);
+    method public static int lastIndexOf(java.lang.CharSequence, char, int, int);
+    method public static boolean regionMatches(java.lang.CharSequence, int, java.lang.CharSequence, int, int);
+    method public static java.lang.CharSequence replace(java.lang.CharSequence, java.lang.String[], java.lang.CharSequence[]);
+    method public static java.lang.String[] split(java.lang.String, java.lang.String);
+    method public static java.lang.String[] split(java.lang.String, java.util.regex.Pattern);
+    method public static java.lang.CharSequence stringOrSpannedString(java.lang.CharSequence);
+    method public static java.lang.String substring(java.lang.CharSequence, int, int);
+    method public static void writeToParcel(java.lang.CharSequence, android.os.Parcel, int);
+    field public static final int CAP_MODE_CHARACTERS = 4096; // 0x1000
+    field public static final int CAP_MODE_SENTENCES = 16384; // 0x4000
+    field public static final int CAP_MODE_WORDS = 8192; // 0x2000
+    field public static final android.os.Parcelable.Creator CHAR_SEQUENCE_CREATOR;
+  }
+
+  public static abstract interface TextUtils.EllipsizeCallback {
+    method public abstract void ellipsized(int, int);
+  }
+
+  public static class TextUtils.SimpleStringSplitter implements java.util.Iterator android.text.TextUtils.StringSplitter {
+    ctor public TextUtils.SimpleStringSplitter(char);
+    method public boolean hasNext();
+    method public java.util.Iterator<java.lang.String> iterator();
+    method public java.lang.String next();
+    method public void remove();
+    method public void setString(java.lang.String);
+  }
+
+  public static abstract interface TextUtils.StringSplitter implements java.lang.Iterable {
+    method public abstract void setString(java.lang.String);
+  }
+
+  public static final class TextUtils.TruncateAt extends java.lang.Enum {
+    method public static android.text.TextUtils.TruncateAt valueOf(java.lang.String);
+    method public static final android.text.TextUtils.TruncateAt[] values();
+    enum_constant public static final android.text.TextUtils.TruncateAt END;
+    enum_constant public static final android.text.TextUtils.TruncateAt MARQUEE;
+    enum_constant public static final android.text.TextUtils.TruncateAt MIDDLE;
+    enum_constant public static final android.text.TextUtils.TruncateAt START;
+  }
+
+  public abstract interface TextWatcher implements android.text.NoCopySpan {
+    method public abstract void afterTextChanged(android.text.Editable);
+    method public abstract void beforeTextChanged(java.lang.CharSequence, int, int, int);
+    method public abstract void onTextChanged(java.lang.CharSequence, int, int, int);
+  }
+
+}
+
+package android.text.format {
+
+  public class DateFormat {
+    ctor public DateFormat();
+    method public static java.lang.CharSequence format(java.lang.CharSequence, long);
+    method public static java.lang.CharSequence format(java.lang.CharSequence, java.util.Date);
+    method public static java.lang.CharSequence format(java.lang.CharSequence, java.util.Calendar);
+    method public static java.text.DateFormat getDateFormat(android.content.Context);
+    method public static char[] getDateFormatOrder(android.content.Context);
+    method public static java.text.DateFormat getLongDateFormat(android.content.Context);
+    method public static java.text.DateFormat getMediumDateFormat(android.content.Context);
+    method public static java.text.DateFormat getTimeFormat(android.content.Context);
+    method public static boolean is24HourFormat(android.content.Context);
+    field public static final char AM_PM = 97; // 0x0061 'a'
+    field public static final char CAPITAL_AM_PM = 65; // 0x0041 'A'
+    field public static final char DATE = 100; // 0x0064 'd'
+    field public static final char DAY = 69; // 0x0045 'E'
+    field public static final char HOUR = 104; // 0x0068 'h'
+    field public static final char HOUR_OF_DAY = 107; // 0x006b 'k'
+    field public static final char MINUTE = 109; // 0x006d 'm'
+    field public static final char MONTH = 77; // 0x004d 'M'
+    field public static final char QUOTE = 39; // 0x0027 '\''
+    field public static final char SECONDS = 115; // 0x0073 's'
+    field public static final char STANDALONE_MONTH = 76; // 0x004c 'L'
+    field public static final char TIME_ZONE = 122; // 0x007a 'z'
+    field public static final char YEAR = 121; // 0x0079 'y'
+  }
+
+  public class DateUtils {
+    ctor public DateUtils();
+    method public static java.lang.String formatDateRange(android.content.Context, long, long, int);
+    method public static java.util.Formatter formatDateRange(android.content.Context, java.util.Formatter, long, long, int);
+    method public static java.util.Formatter formatDateRange(android.content.Context, java.util.Formatter, long, long, int, java.lang.String);
+    method public static java.lang.String formatDateTime(android.content.Context, long, int);
+    method public static java.lang.String formatElapsedTime(long);
+    method public static java.lang.String formatElapsedTime(java.lang.StringBuilder, long);
+    method public static final java.lang.CharSequence formatSameDayTime(long, long, int, int);
+    method public static deprecated java.lang.String getAMPMString(int);
+    method public static deprecated java.lang.String getDayOfWeekString(int, int);
+    method public static deprecated java.lang.String getMonthString(int, int);
+    method public static java.lang.CharSequence getRelativeDateTimeString(android.content.Context, long, long, long, int);
+    method public static java.lang.CharSequence getRelativeTimeSpanString(long);
+    method public static java.lang.CharSequence getRelativeTimeSpanString(long, long, long);
+    method public static java.lang.CharSequence getRelativeTimeSpanString(long, long, long, int);
+    method public static java.lang.CharSequence getRelativeTimeSpanString(android.content.Context, long, boolean);
+    method public static java.lang.CharSequence getRelativeTimeSpanString(android.content.Context, long);
+    method public static boolean isToday(long);
+    field public static final deprecated java.lang.String ABBREV_MONTH_FORMAT = "%b";
+    field public static final java.lang.String ABBREV_WEEKDAY_FORMAT = "%a";
+    field public static final long DAY_IN_MILLIS = 86400000L; // 0x5265c00L
+    field public static final deprecated int FORMAT_12HOUR = 64; // 0x40
+    field public static final deprecated int FORMAT_24HOUR = 128; // 0x80
+    field public static final int FORMAT_ABBREV_ALL = 524288; // 0x80000
+    field public static final int FORMAT_ABBREV_MONTH = 65536; // 0x10000
+    field public static final int FORMAT_ABBREV_RELATIVE = 262144; // 0x40000
+    field public static final int FORMAT_ABBREV_TIME = 16384; // 0x4000
+    field public static final int FORMAT_ABBREV_WEEKDAY = 32768; // 0x8000
+    field public static final deprecated int FORMAT_CAP_AMPM = 256; // 0x100
+    field public static final deprecated int FORMAT_CAP_MIDNIGHT = 4096; // 0x1000
+    field public static final deprecated int FORMAT_CAP_NOON = 1024; // 0x400
+    field public static final deprecated int FORMAT_CAP_NOON_MIDNIGHT = 5120; // 0x1400
+    field public static final int FORMAT_NO_MIDNIGHT = 2048; // 0x800
+    field public static final int FORMAT_NO_MONTH_DAY = 32; // 0x20
+    field public static final int FORMAT_NO_NOON = 512; // 0x200
+    field public static final deprecated int FORMAT_NO_NOON_MIDNIGHT = 2560; // 0xa00
+    field public static final int FORMAT_NO_YEAR = 8; // 0x8
+    field public static final int FORMAT_NUMERIC_DATE = 131072; // 0x20000
+    field public static final int FORMAT_SHOW_DATE = 16; // 0x10
+    field public static final int FORMAT_SHOW_TIME = 1; // 0x1
+    field public static final int FORMAT_SHOW_WEEKDAY = 2; // 0x2
+    field public static final int FORMAT_SHOW_YEAR = 4; // 0x4
+    field public static final deprecated int FORMAT_UTC = 8192; // 0x2000
+    field public static final long HOUR_IN_MILLIS = 3600000L; // 0x36ee80L
+    field public static final deprecated java.lang.String HOUR_MINUTE_24 = "%H:%M";
+    field public static final deprecated int LENGTH_LONG = 10; // 0xa
+    field public static final deprecated int LENGTH_MEDIUM = 20; // 0x14
+    field public static final deprecated int LENGTH_SHORT = 30; // 0x1e
+    field public static final deprecated int LENGTH_SHORTER = 40; // 0x28
+    field public static final deprecated int LENGTH_SHORTEST = 50; // 0x32
+    field public static final long MINUTE_IN_MILLIS = 60000L; // 0xea60L
+    field public static final java.lang.String MONTH_DAY_FORMAT = "%-d";
+    field public static final java.lang.String MONTH_FORMAT = "%B";
+    field public static final java.lang.String NUMERIC_MONTH_FORMAT = "%m";
+    field public static final long SECOND_IN_MILLIS = 1000L; // 0x3e8L
+    field public static final java.lang.String WEEKDAY_FORMAT = "%A";
+    field public static final long WEEK_IN_MILLIS = 604800000L; // 0x240c8400L
+    field public static final java.lang.String YEAR_FORMAT = "%Y";
+    field public static final java.lang.String YEAR_FORMAT_TWO_DIGITS = "%g";
+    field public static final long YEAR_IN_MILLIS = 31449600000L; // 0x7528ad000L
+    field public static final deprecated int[] sameMonthTable;
+    field public static final deprecated int[] sameYearTable;
+  }
+
+  public final class Formatter {
+    ctor public Formatter();
+    method public static java.lang.String formatFileSize(android.content.Context, long);
+    method public static deprecated java.lang.String formatIpAddress(int);
+    method public static java.lang.String formatShortFileSize(android.content.Context, long);
+  }
+
+  public class Time {
+    ctor public Time(java.lang.String);
+    ctor public Time();
+    ctor public Time(android.text.format.Time);
+    method public boolean after(android.text.format.Time);
+    method public boolean before(android.text.format.Time);
+    method public void clear(java.lang.String);
+    method public static int compare(android.text.format.Time, android.text.format.Time);
+    method public java.lang.String format(java.lang.String);
+    method public java.lang.String format2445();
+    method public java.lang.String format3339(boolean);
+    method public int getActualMaximum(int);
+    method public static java.lang.String getCurrentTimezone();
+    method public static int getJulianDay(long, long);
+    method public static int getJulianMondayFromWeeksSinceEpoch(int);
+    method public int getWeekNumber();
+    method public static int getWeeksSinceEpochFromJulianDay(int, int);
+    method public static boolean isEpoch(android.text.format.Time);
+    method public long normalize(boolean);
+    method public boolean parse(java.lang.String);
+    method public boolean parse3339(java.lang.String);
+    method public void set(long);
+    method public void set(android.text.format.Time);
+    method public void set(int, int, int, int, int, int);
+    method public void set(int, int, int);
+    method public long setJulianDay(int);
+    method public void setToNow();
+    method public void switchTimezone(java.lang.String);
+    method public long toMillis(boolean);
+    field public static final int EPOCH_JULIAN_DAY = 2440588; // 0x253d8c
+    field public static final int FRIDAY = 5; // 0x5
+    field public static final int HOUR = 3; // 0x3
+    field public static final int MINUTE = 2; // 0x2
+    field public static final int MONDAY = 1; // 0x1
+    field public static final int MONDAY_BEFORE_JULIAN_EPOCH = 2440585; // 0x253d89
+    field public static final int MONTH = 5; // 0x5
+    field public static final int MONTH_DAY = 4; // 0x4
+    field public static final int SATURDAY = 6; // 0x6
+    field public static final int SECOND = 1; // 0x1
+    field public static final int SUNDAY = 0; // 0x0
+    field public static final int THURSDAY = 4; // 0x4
+    field public static final java.lang.String TIMEZONE_UTC = "UTC";
+    field public static final int TUESDAY = 2; // 0x2
+    field public static final int WEDNESDAY = 3; // 0x3
+    field public static final int WEEK_DAY = 7; // 0x7
+    field public static final int WEEK_NUM = 9; // 0x9
+    field public static final int YEAR = 6; // 0x6
+    field public static final int YEAR_DAY = 8; // 0x8
+    field public boolean allDay;
+    field public long gmtoff;
+    field public int hour;
+    field public int isDst;
+    field public int minute;
+    field public int month;
+    field public int monthDay;
+    field public int second;
+    field public java.lang.String timezone;
+    field public int weekDay;
+    field public int year;
+    field public int yearDay;
+  }
+
+}
+
+package android.text.method {
+
+  public class ArrowKeyMovementMethod extends android.text.method.BaseMovementMethod implements android.text.method.MovementMethod {
+    ctor public ArrowKeyMovementMethod();
+    method public static android.text.method.MovementMethod getInstance();
+  }
+
+  public abstract class BaseKeyListener extends android.text.method.MetaKeyKeyListener implements android.text.method.KeyListener {
+    ctor public BaseKeyListener();
+    method public boolean backspace(android.view.View, android.text.Editable, int, android.view.KeyEvent);
+    method public boolean forwardDelete(android.view.View, android.text.Editable, int, android.view.KeyEvent);
+    method public boolean onKeyOther(android.view.View, android.text.Editable, android.view.KeyEvent);
+  }
+
+  public class BaseMovementMethod implements android.text.method.MovementMethod {
+    ctor public BaseMovementMethod();
+    method protected boolean bottom(android.widget.TextView, android.text.Spannable);
+    method public boolean canSelectArbitrarily();
+    method protected boolean down(android.widget.TextView, android.text.Spannable);
+    method protected boolean end(android.widget.TextView, android.text.Spannable);
+    method protected int getMovementMetaState(android.text.Spannable, android.view.KeyEvent);
+    method protected boolean handleMovementKey(android.widget.TextView, android.text.Spannable, int, int, android.view.KeyEvent);
+    method protected boolean home(android.widget.TextView, android.text.Spannable);
+    method public void initialize(android.widget.TextView, android.text.Spannable);
+    method protected boolean left(android.widget.TextView, android.text.Spannable);
+    method protected boolean lineEnd(android.widget.TextView, android.text.Spannable);
+    method protected boolean lineStart(android.widget.TextView, android.text.Spannable);
+    method public boolean onGenericMotionEvent(android.widget.TextView, android.text.Spannable, android.view.MotionEvent);
+    method public boolean onKeyDown(android.widget.TextView, android.text.Spannable, int, android.view.KeyEvent);
+    method public boolean onKeyOther(android.widget.TextView, android.text.Spannable, android.view.KeyEvent);
+    method public boolean onKeyUp(android.widget.TextView, android.text.Spannable, int, android.view.KeyEvent);
+    method public void onTakeFocus(android.widget.TextView, android.text.Spannable, int);
+    method public boolean onTouchEvent(android.widget.TextView, android.text.Spannable, android.view.MotionEvent);
+    method public boolean onTrackballEvent(android.widget.TextView, android.text.Spannable, android.view.MotionEvent);
+    method protected boolean pageDown(android.widget.TextView, android.text.Spannable);
+    method protected boolean pageUp(android.widget.TextView, android.text.Spannable);
+    method protected boolean right(android.widget.TextView, android.text.Spannable);
+    method protected boolean top(android.widget.TextView, android.text.Spannable);
+    method protected boolean up(android.widget.TextView, android.text.Spannable);
+  }
+
+  public class CharacterPickerDialog extends android.app.Dialog implements android.widget.AdapterView.OnItemClickListener android.view.View.OnClickListener {
+    ctor public CharacterPickerDialog(android.content.Context, android.view.View, android.text.Editable, java.lang.String, boolean);
+    method public void onClick(android.view.View);
+    method public void onItemClick(android.widget.AdapterView, android.view.View, int, long);
+  }
+
+  public class DateKeyListener extends android.text.method.NumberKeyListener {
+    ctor public DateKeyListener();
+    method protected char[] getAcceptedChars();
+    method public int getInputType();
+    method public static android.text.method.DateKeyListener getInstance();
+    field public static final char[] CHARACTERS;
+  }
+
+  public class DateTimeKeyListener extends android.text.method.NumberKeyListener {
+    ctor public DateTimeKeyListener();
+    method protected char[] getAcceptedChars();
+    method public int getInputType();
+    method public static android.text.method.DateTimeKeyListener getInstance();
+    field public static final char[] CHARACTERS;
+  }
+
+  public class DialerKeyListener extends android.text.method.NumberKeyListener {
+    ctor public DialerKeyListener();
+    method protected char[] getAcceptedChars();
+    method public int getInputType();
+    method public static android.text.method.DialerKeyListener getInstance();
+    field public static final char[] CHARACTERS;
+  }
+
+  public class DigitsKeyListener extends android.text.method.NumberKeyListener {
+    ctor public DigitsKeyListener();
+    ctor public DigitsKeyListener(boolean, boolean);
+    method protected char[] getAcceptedChars();
+    method public int getInputType();
+    method public static android.text.method.DigitsKeyListener getInstance();
+    method public static android.text.method.DigitsKeyListener getInstance(boolean, boolean);
+    method public static android.text.method.DigitsKeyListener getInstance(java.lang.String);
+  }
+
+  public class HideReturnsTransformationMethod extends android.text.method.ReplacementTransformationMethod {
+    ctor public HideReturnsTransformationMethod();
+    method public static android.text.method.HideReturnsTransformationMethod getInstance();
+    method protected char[] getOriginal();
+    method protected char[] getReplacement();
+  }
+
+  public abstract interface KeyListener {
+    method public abstract void clearMetaKeyState(android.view.View, android.text.Editable, int);
+    method public abstract int getInputType();
+    method public abstract boolean onKeyDown(android.view.View, android.text.Editable, int, android.view.KeyEvent);
+    method public abstract boolean onKeyOther(android.view.View, android.text.Editable, android.view.KeyEvent);
+    method public abstract boolean onKeyUp(android.view.View, android.text.Editable, int, android.view.KeyEvent);
+  }
+
+  public class LinkMovementMethod extends android.text.method.ScrollingMovementMethod {
+    ctor public LinkMovementMethod();
+    method public static android.text.method.MovementMethod getInstance();
+  }
+
+  public abstract class MetaKeyKeyListener {
+    ctor public MetaKeyKeyListener();
+    method public static void adjustMetaAfterKeypress(android.text.Spannable);
+    method public static long adjustMetaAfterKeypress(long);
+    method public void clearMetaKeyState(android.view.View, android.text.Editable, int);
+    method public static void clearMetaKeyState(android.text.Editable, int);
+    method public long clearMetaKeyState(long, int);
+    method public static final int getMetaState(java.lang.CharSequence);
+    method public static final int getMetaState(java.lang.CharSequence, int);
+    method public static final int getMetaState(long);
+    method public static final int getMetaState(long, int);
+    method public static long handleKeyDown(long, int, android.view.KeyEvent);
+    method public static long handleKeyUp(long, int, android.view.KeyEvent);
+    method public static boolean isMetaTracker(java.lang.CharSequence, java.lang.Object);
+    method public static boolean isSelectingMetaTracker(java.lang.CharSequence, java.lang.Object);
+    method public boolean onKeyDown(android.view.View, android.text.Editable, int, android.view.KeyEvent);
+    method public boolean onKeyUp(android.view.View, android.text.Editable, int, android.view.KeyEvent);
+    method protected static void resetLockedMeta(android.text.Spannable);
+    method public static long resetLockedMeta(long);
+    method public static void resetMetaState(android.text.Spannable);
+    field public static final int META_ALT_LOCKED = 512; // 0x200
+    field public static final int META_ALT_ON = 2; // 0x2
+    field public static final int META_CAP_LOCKED = 256; // 0x100
+    field public static final int META_SHIFT_ON = 1; // 0x1
+    field public static final int META_SYM_LOCKED = 1024; // 0x400
+    field public static final int META_SYM_ON = 4; // 0x4
+  }
+
+  public abstract interface MovementMethod {
+    method public abstract boolean canSelectArbitrarily();
+    method public abstract void initialize(android.widget.TextView, android.text.Spannable);
+    method public abstract boolean onGenericMotionEvent(android.widget.TextView, android.text.Spannable, android.view.MotionEvent);
+    method public abstract boolean onKeyDown(android.widget.TextView, android.text.Spannable, int, android.view.KeyEvent);
+    method public abstract boolean onKeyOther(android.widget.TextView, android.text.Spannable, android.view.KeyEvent);
+    method public abstract boolean onKeyUp(android.widget.TextView, android.text.Spannable, int, android.view.KeyEvent);
+    method public abstract void onTakeFocus(android.widget.TextView, android.text.Spannable, int);
+    method public abstract boolean onTouchEvent(android.widget.TextView, android.text.Spannable, android.view.MotionEvent);
+    method public abstract boolean onTrackballEvent(android.widget.TextView, android.text.Spannable, android.view.MotionEvent);
+  }
+
+  public class MultiTapKeyListener extends android.text.method.BaseKeyListener implements android.text.SpanWatcher {
+    ctor public MultiTapKeyListener(android.text.method.TextKeyListener.Capitalize, boolean);
+    method public int getInputType();
+    method public static android.text.method.MultiTapKeyListener getInstance(boolean, android.text.method.TextKeyListener.Capitalize);
+    method public void onSpanAdded(android.text.Spannable, java.lang.Object, int, int);
+    method public void onSpanChanged(android.text.Spannable, java.lang.Object, int, int, int, int);
+    method public void onSpanRemoved(android.text.Spannable, java.lang.Object, int, int);
+  }
+
+  public abstract class NumberKeyListener extends android.text.method.BaseKeyListener implements android.text.InputFilter {
+    ctor public NumberKeyListener();
+    method public java.lang.CharSequence filter(java.lang.CharSequence, int, int, android.text.Spanned, int, int);
+    method protected abstract char[] getAcceptedChars();
+    method protected int lookup(android.view.KeyEvent, android.text.Spannable);
+    method protected static boolean ok(char[], char);
+  }
+
+  public class PasswordTransformationMethod implements android.text.TextWatcher android.text.method.TransformationMethod {
+    ctor public PasswordTransformationMethod();
+    method public void afterTextChanged(android.text.Editable);
+    method public void beforeTextChanged(java.lang.CharSequence, int, int, int);
+    method public static android.text.method.PasswordTransformationMethod getInstance();
+    method public java.lang.CharSequence getTransformation(java.lang.CharSequence, android.view.View);
+    method public void onFocusChanged(android.view.View, java.lang.CharSequence, boolean, int, android.graphics.Rect);
+    method public void onTextChanged(java.lang.CharSequence, int, int, int);
+  }
+
+  public class QwertyKeyListener extends android.text.method.BaseKeyListener {
+    ctor public QwertyKeyListener(android.text.method.TextKeyListener.Capitalize, boolean);
+    method public int getInputType();
+    method public static android.text.method.QwertyKeyListener getInstance(boolean, android.text.method.TextKeyListener.Capitalize);
+    method public static android.text.method.QwertyKeyListener getInstanceForFullKeyboard();
+    method public static void markAsReplaced(android.text.Spannable, int, int, java.lang.String);
+  }
+
+  public abstract class ReplacementTransformationMethod implements android.text.method.TransformationMethod {
+    ctor public ReplacementTransformationMethod();
+    method protected abstract char[] getOriginal();
+    method protected abstract char[] getReplacement();
+    method public java.lang.CharSequence getTransformation(java.lang.CharSequence, android.view.View);
+    method public void onFocusChanged(android.view.View, java.lang.CharSequence, boolean, int, android.graphics.Rect);
+  }
+
+  public class ScrollingMovementMethod extends android.text.method.BaseMovementMethod implements android.text.method.MovementMethod {
+    ctor public ScrollingMovementMethod();
+    method public static android.text.method.MovementMethod getInstance();
+  }
+
+  public class SingleLineTransformationMethod extends android.text.method.ReplacementTransformationMethod {
+    ctor public SingleLineTransformationMethod();
+    method public static android.text.method.SingleLineTransformationMethod getInstance();
+    method protected char[] getOriginal();
+    method protected char[] getReplacement();
+  }
+
+  public class TextKeyListener extends android.text.method.BaseKeyListener implements android.text.SpanWatcher {
+    ctor public TextKeyListener(android.text.method.TextKeyListener.Capitalize, boolean);
+    method public static void clear(android.text.Editable);
+    method public int getInputType();
+    method public static android.text.method.TextKeyListener getInstance(boolean, android.text.method.TextKeyListener.Capitalize);
+    method public static android.text.method.TextKeyListener getInstance();
+    method public void onSpanAdded(android.text.Spannable, java.lang.Object, int, int);
+    method public void onSpanChanged(android.text.Spannable, java.lang.Object, int, int, int, int);
+    method public void onSpanRemoved(android.text.Spannable, java.lang.Object, int, int);
+    method public void release();
+    method public static boolean shouldCap(android.text.method.TextKeyListener.Capitalize, java.lang.CharSequence, int);
+  }
+
+  public static final class TextKeyListener.Capitalize extends java.lang.Enum {
+    method public static android.text.method.TextKeyListener.Capitalize valueOf(java.lang.String);
+    method public static final android.text.method.TextKeyListener.Capitalize[] values();
+    enum_constant public static final android.text.method.TextKeyListener.Capitalize CHARACTERS;
+    enum_constant public static final android.text.method.TextKeyListener.Capitalize NONE;
+    enum_constant public static final android.text.method.TextKeyListener.Capitalize SENTENCES;
+    enum_constant public static final android.text.method.TextKeyListener.Capitalize WORDS;
+  }
+
+  public class TimeKeyListener extends android.text.method.NumberKeyListener {
+    ctor public TimeKeyListener();
+    method protected char[] getAcceptedChars();
+    method public int getInputType();
+    method public static android.text.method.TimeKeyListener getInstance();
+    field public static final char[] CHARACTERS;
+  }
+
+  public class Touch {
+    method public static int getInitialScrollX(android.widget.TextView, android.text.Spannable);
+    method public static int getInitialScrollY(android.widget.TextView, android.text.Spannable);
+    method public static boolean onTouchEvent(android.widget.TextView, android.text.Spannable, android.view.MotionEvent);
+    method public static void scrollTo(android.widget.TextView, android.text.Layout, int, int);
+  }
+
+  public abstract interface TransformationMethod {
+    method public abstract java.lang.CharSequence getTransformation(java.lang.CharSequence, android.view.View);
+    method public abstract void onFocusChanged(android.view.View, java.lang.CharSequence, boolean, int, android.graphics.Rect);
+  }
+
+}
+
+package android.text.style {
+
+  public class AbsoluteSizeSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
+    ctor public AbsoluteSizeSpan(int);
+    ctor public AbsoluteSizeSpan(int, boolean);
+    ctor public AbsoluteSizeSpan(android.os.Parcel);
+    method public int describeContents();
+    method public boolean getDip();
+    method public int getSize();
+    method public int getSpanTypeId();
+    method public void updateDrawState(android.text.TextPaint);
+    method public void updateMeasureState(android.text.TextPaint);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public abstract interface AlignmentSpan implements android.text.style.ParagraphStyle {
+    method public abstract android.text.Layout.Alignment getAlignment();
+  }
+
+  public static class AlignmentSpan.Standard implements android.text.style.AlignmentSpan android.text.ParcelableSpan {
+    ctor public AlignmentSpan.Standard(android.text.Layout.Alignment);
+    ctor public AlignmentSpan.Standard(android.os.Parcel);
+    method public int describeContents();
+    method public android.text.Layout.Alignment getAlignment();
+    method public int getSpanTypeId();
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class BackgroundColorSpan extends android.text.style.CharacterStyle implements android.text.ParcelableSpan android.text.style.UpdateAppearance {
+    ctor public BackgroundColorSpan(int);
+    ctor public BackgroundColorSpan(android.os.Parcel);
+    method public int describeContents();
+    method public int getBackgroundColor();
+    method public int getSpanTypeId();
+    method public void updateDrawState(android.text.TextPaint);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class BulletSpan implements android.text.style.LeadingMarginSpan android.text.ParcelableSpan {
+    ctor public BulletSpan();
+    ctor public BulletSpan(int);
+    ctor public BulletSpan(int, int);
+    ctor public BulletSpan(android.os.Parcel);
+    method public int describeContents();
+    method public void drawLeadingMargin(android.graphics.Canvas, android.graphics.Paint, int, int, int, int, int, java.lang.CharSequence, int, int, boolean, android.text.Layout);
+    method public int getLeadingMargin(boolean);
+    method public int getSpanTypeId();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int STANDARD_GAP_WIDTH = 2; // 0x2
+  }
+
+  public abstract class CharacterStyle {
+    ctor public CharacterStyle();
+    method public android.text.style.CharacterStyle getUnderlying();
+    method public abstract void updateDrawState(android.text.TextPaint);
+    method public static android.text.style.CharacterStyle wrap(android.text.style.CharacterStyle);
+  }
+
+  public abstract class ClickableSpan extends android.text.style.CharacterStyle implements android.text.style.UpdateAppearance {
+    ctor public ClickableSpan();
+    method public abstract void onClick(android.view.View);
+    method public void updateDrawState(android.text.TextPaint);
+  }
+
+  public class DrawableMarginSpan implements android.text.style.LeadingMarginSpan android.text.style.LineHeightSpan {
+    ctor public DrawableMarginSpan(android.graphics.drawable.Drawable);
+    ctor public DrawableMarginSpan(android.graphics.drawable.Drawable, int);
+    method public void chooseHeight(java.lang.CharSequence, int, int, int, int, android.graphics.Paint.FontMetricsInt);
+    method public void drawLeadingMargin(android.graphics.Canvas, android.graphics.Paint, int, int, int, int, int, java.lang.CharSequence, int, int, boolean, android.text.Layout);
+    method public int getLeadingMargin(boolean);
+  }
+
+  public abstract class DynamicDrawableSpan extends android.text.style.ReplacementSpan {
+    ctor public DynamicDrawableSpan();
+    ctor protected DynamicDrawableSpan(int);
+    method public void draw(android.graphics.Canvas, java.lang.CharSequence, int, int, float, int, int, int, android.graphics.Paint);
+    method public abstract android.graphics.drawable.Drawable getDrawable();
+    method public int getSize(android.graphics.Paint, java.lang.CharSequence, int, int, android.graphics.Paint.FontMetricsInt);
+    method public int getVerticalAlignment();
+    field public static final int ALIGN_BASELINE = 1; // 0x1
+    field public static final int ALIGN_BOTTOM = 0; // 0x0
+    field protected final int mVerticalAlignment;
+  }
+
+  public class EasyEditSpan implements android.text.ParcelableSpan {
+    ctor public EasyEditSpan();
+    method public int describeContents();
+    method public int getSpanTypeId();
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class ForegroundColorSpan extends android.text.style.CharacterStyle implements android.text.ParcelableSpan android.text.style.UpdateAppearance {
+    ctor public ForegroundColorSpan(int);
+    ctor public ForegroundColorSpan(android.os.Parcel);
+    method public int describeContents();
+    method public int getForegroundColor();
+    method public int getSpanTypeId();
+    method public void updateDrawState(android.text.TextPaint);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class IconMarginSpan implements android.text.style.LeadingMarginSpan android.text.style.LineHeightSpan {
+    ctor public IconMarginSpan(android.graphics.Bitmap);
+    ctor public IconMarginSpan(android.graphics.Bitmap, int);
+    method public void chooseHeight(java.lang.CharSequence, int, int, int, int, android.graphics.Paint.FontMetricsInt);
+    method public void drawLeadingMargin(android.graphics.Canvas, android.graphics.Paint, int, int, int, int, int, java.lang.CharSequence, int, int, boolean, android.text.Layout);
+    method public int getLeadingMargin(boolean);
+  }
+
+  public class ImageSpan extends android.text.style.DynamicDrawableSpan {
+    ctor public deprecated ImageSpan(android.graphics.Bitmap);
+    ctor public deprecated ImageSpan(android.graphics.Bitmap, int);
+    ctor public ImageSpan(android.content.Context, android.graphics.Bitmap);
+    ctor public ImageSpan(android.content.Context, android.graphics.Bitmap, int);
+    ctor public ImageSpan(android.graphics.drawable.Drawable);
+    ctor public ImageSpan(android.graphics.drawable.Drawable, int);
+    ctor public ImageSpan(android.graphics.drawable.Drawable, java.lang.String);
+    ctor public ImageSpan(android.graphics.drawable.Drawable, java.lang.String, int);
+    ctor public ImageSpan(android.content.Context, android.net.Uri);
+    ctor public ImageSpan(android.content.Context, android.net.Uri, int);
+    ctor public ImageSpan(android.content.Context, int);
+    ctor public ImageSpan(android.content.Context, int, int);
+    method public android.graphics.drawable.Drawable getDrawable();
+    method public java.lang.String getSource();
+  }
+
+  public abstract interface LeadingMarginSpan implements android.text.style.ParagraphStyle {
+    method public abstract void drawLeadingMargin(android.graphics.Canvas, android.graphics.Paint, int, int, int, int, int, java.lang.CharSequence, int, int, boolean, android.text.Layout);
+    method public abstract int getLeadingMargin(boolean);
+  }
+
+  public static abstract interface LeadingMarginSpan.LeadingMarginSpan2 implements android.text.style.LeadingMarginSpan android.text.style.WrapTogetherSpan {
+    method public abstract int getLeadingMarginLineCount();
+  }
+
+  public static class LeadingMarginSpan.Standard implements android.text.style.LeadingMarginSpan android.text.ParcelableSpan {
+    ctor public LeadingMarginSpan.Standard(int, int);
+    ctor public LeadingMarginSpan.Standard(int);
+    ctor public LeadingMarginSpan.Standard(android.os.Parcel);
+    method public int describeContents();
+    method public void drawLeadingMargin(android.graphics.Canvas, android.graphics.Paint, int, int, int, int, int, java.lang.CharSequence, int, int, boolean, android.text.Layout);
+    method public int getLeadingMargin(boolean);
+    method public int getSpanTypeId();
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public abstract interface LineBackgroundSpan implements android.text.style.ParagraphStyle {
+    method public abstract void drawBackground(android.graphics.Canvas, android.graphics.Paint, int, int, int, int, int, java.lang.CharSequence, int, int, int);
+  }
+
+  public abstract interface LineHeightSpan implements android.text.style.ParagraphStyle android.text.style.WrapTogetherSpan {
+    method public abstract void chooseHeight(java.lang.CharSequence, int, int, int, int, android.graphics.Paint.FontMetricsInt);
+  }
+
+  public static abstract interface LineHeightSpan.WithDensity implements android.text.style.LineHeightSpan {
+    method public abstract void chooseHeight(java.lang.CharSequence, int, int, int, int, android.graphics.Paint.FontMetricsInt, android.text.TextPaint);
+  }
+
+  public class LocaleSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
+    ctor public LocaleSpan(java.util.Locale);
+    ctor public LocaleSpan(android.os.Parcel);
+    method public int describeContents();
+    method public java.util.Locale getLocale();
+    method public int getSpanTypeId();
+    method public void updateDrawState(android.text.TextPaint);
+    method public void updateMeasureState(android.text.TextPaint);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class MaskFilterSpan extends android.text.style.CharacterStyle implements android.text.style.UpdateAppearance {
+    ctor public MaskFilterSpan(android.graphics.MaskFilter);
+    method public android.graphics.MaskFilter getMaskFilter();
+    method public void updateDrawState(android.text.TextPaint);
+  }
+
+  public abstract class MetricAffectingSpan extends android.text.style.CharacterStyle implements android.text.style.UpdateLayout {
+    ctor public MetricAffectingSpan();
+    method public abstract void updateMeasureState(android.text.TextPaint);
+  }
+
+  public abstract interface ParagraphStyle {
+  }
+
+  public class QuoteSpan implements android.text.style.LeadingMarginSpan android.text.ParcelableSpan {
+    ctor public QuoteSpan();
+    ctor public QuoteSpan(int);
+    ctor public QuoteSpan(android.os.Parcel);
+    method public int describeContents();
+    method public void drawLeadingMargin(android.graphics.Canvas, android.graphics.Paint, int, int, int, int, int, java.lang.CharSequence, int, int, boolean, android.text.Layout);
+    method public int getColor();
+    method public int getLeadingMargin(boolean);
+    method public int getSpanTypeId();
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class RasterizerSpan extends android.text.style.CharacterStyle implements android.text.style.UpdateAppearance {
+    ctor public RasterizerSpan(android.graphics.Rasterizer);
+    method public android.graphics.Rasterizer getRasterizer();
+    method public void updateDrawState(android.text.TextPaint);
+  }
+
+  public class RelativeSizeSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
+    ctor public RelativeSizeSpan(float);
+    ctor public RelativeSizeSpan(android.os.Parcel);
+    method public int describeContents();
+    method public float getSizeChange();
+    method public int getSpanTypeId();
+    method public void updateDrawState(android.text.TextPaint);
+    method public void updateMeasureState(android.text.TextPaint);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public abstract class ReplacementSpan extends android.text.style.MetricAffectingSpan {
+    ctor public ReplacementSpan();
+    method public abstract void draw(android.graphics.Canvas, java.lang.CharSequence, int, int, float, int, int, int, android.graphics.Paint);
+    method public abstract int getSize(android.graphics.Paint, java.lang.CharSequence, int, int, android.graphics.Paint.FontMetricsInt);
+    method public void updateDrawState(android.text.TextPaint);
+    method public void updateMeasureState(android.text.TextPaint);
+  }
+
+  public class ScaleXSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
+    ctor public ScaleXSpan(float);
+    ctor public ScaleXSpan(android.os.Parcel);
+    method public int describeContents();
+    method public float getScaleX();
+    method public int getSpanTypeId();
+    method public void updateDrawState(android.text.TextPaint);
+    method public void updateMeasureState(android.text.TextPaint);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class StrikethroughSpan extends android.text.style.CharacterStyle implements android.text.ParcelableSpan android.text.style.UpdateAppearance {
+    ctor public StrikethroughSpan();
+    ctor public StrikethroughSpan(android.os.Parcel);
+    method public int describeContents();
+    method public int getSpanTypeId();
+    method public void updateDrawState(android.text.TextPaint);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class StyleSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
+    ctor public StyleSpan(int);
+    ctor public StyleSpan(android.os.Parcel);
+    method public int describeContents();
+    method public int getSpanTypeId();
+    method public int getStyle();
+    method public void updateDrawState(android.text.TextPaint);
+    method public void updateMeasureState(android.text.TextPaint);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class SubscriptSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
+    ctor public SubscriptSpan();
+    ctor public SubscriptSpan(android.os.Parcel);
+    method public int describeContents();
+    method public int getSpanTypeId();
+    method public void updateDrawState(android.text.TextPaint);
+    method public void updateMeasureState(android.text.TextPaint);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class SuggestionSpan extends android.text.style.CharacterStyle implements android.text.ParcelableSpan {
+    ctor public SuggestionSpan(android.content.Context, java.lang.String[], int);
+    ctor public SuggestionSpan(java.util.Locale, java.lang.String[], int);
+    ctor public SuggestionSpan(android.content.Context, java.util.Locale, java.lang.String[], int, java.lang.Class<?>);
+    ctor public SuggestionSpan(android.os.Parcel);
+    method public int describeContents();
+    method public int getFlags();
+    method public java.lang.String getLocale();
+    method public int getSpanTypeId();
+    method public java.lang.String[] getSuggestions();
+    method public void setFlags(int);
+    method public void updateDrawState(android.text.TextPaint);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final java.lang.String ACTION_SUGGESTION_PICKED = "android.text.style.SUGGESTION_PICKED";
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_AUTO_CORRECTION = 4; // 0x4
+    field public static final int FLAG_EASY_CORRECT = 1; // 0x1
+    field public static final int FLAG_MISSPELLED = 2; // 0x2
+    field public static final int SUGGESTIONS_MAX_SIZE = 5; // 0x5
+    field public static final java.lang.String SUGGESTION_SPAN_PICKED_AFTER = "after";
+    field public static final java.lang.String SUGGESTION_SPAN_PICKED_BEFORE = "before";
+    field public static final java.lang.String SUGGESTION_SPAN_PICKED_HASHCODE = "hashcode";
+  }
+
+  public class SuperscriptSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
+    ctor public SuperscriptSpan();
+    ctor public SuperscriptSpan(android.os.Parcel);
+    method public int describeContents();
+    method public int getSpanTypeId();
+    method public void updateDrawState(android.text.TextPaint);
+    method public void updateMeasureState(android.text.TextPaint);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public abstract interface TabStopSpan implements android.text.style.ParagraphStyle {
+    method public abstract int getTabStop();
+  }
+
+  public static class TabStopSpan.Standard implements android.text.style.TabStopSpan {
+    ctor public TabStopSpan.Standard(int);
+    method public int getTabStop();
+  }
+
+  public class TextAppearanceSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
+    ctor public TextAppearanceSpan(android.content.Context, int);
+    ctor public TextAppearanceSpan(android.content.Context, int, int);
+    ctor public TextAppearanceSpan(java.lang.String, int, int, android.content.res.ColorStateList, android.content.res.ColorStateList);
+    ctor public TextAppearanceSpan(android.os.Parcel);
+    method public int describeContents();
+    method public java.lang.String getFamily();
+    method public android.content.res.ColorStateList getLinkTextColor();
+    method public int getSpanTypeId();
+    method public android.content.res.ColorStateList getTextColor();
+    method public int getTextSize();
+    method public int getTextStyle();
+    method public void updateDrawState(android.text.TextPaint);
+    method public void updateMeasureState(android.text.TextPaint);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class TypefaceSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
+    ctor public TypefaceSpan(java.lang.String);
+    ctor public TypefaceSpan(android.os.Parcel);
+    method public int describeContents();
+    method public java.lang.String getFamily();
+    method public int getSpanTypeId();
+    method public void updateDrawState(android.text.TextPaint);
+    method public void updateMeasureState(android.text.TextPaint);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class URLSpan extends android.text.style.ClickableSpan implements android.text.ParcelableSpan {
+    ctor public URLSpan(java.lang.String);
+    ctor public URLSpan(android.os.Parcel);
+    method public int describeContents();
+    method public int getSpanTypeId();
+    method public java.lang.String getURL();
+    method public void onClick(android.view.View);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class UnderlineSpan extends android.text.style.CharacterStyle implements android.text.ParcelableSpan android.text.style.UpdateAppearance {
+    ctor public UnderlineSpan();
+    ctor public UnderlineSpan(android.os.Parcel);
+    method public int describeContents();
+    method public int getSpanTypeId();
+    method public void updateDrawState(android.text.TextPaint);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public abstract interface UpdateAppearance {
+  }
+
+  public abstract interface UpdateLayout implements android.text.style.UpdateAppearance {
+  }
+
+  public abstract interface WrapTogetherSpan implements android.text.style.ParagraphStyle {
+  }
+
+}
+
+package android.text.util {
+
+  public class Linkify {
+    ctor public Linkify();
+    method public static final boolean addLinks(android.text.Spannable, int);
+    method public static final boolean addLinks(android.widget.TextView, int);
+    method public static final void addLinks(android.widget.TextView, java.util.regex.Pattern, java.lang.String);
+    method public static final void addLinks(android.widget.TextView, java.util.regex.Pattern, java.lang.String, android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter);
+    method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String);
+    method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter);
+    field public static final int ALL = 15; // 0xf
+    field public static final int EMAIL_ADDRESSES = 2; // 0x2
+    field public static final int MAP_ADDRESSES = 8; // 0x8
+    field public static final int PHONE_NUMBERS = 4; // 0x4
+    field public static final int WEB_URLS = 1; // 0x1
+    field public static final android.text.util.Linkify.MatchFilter sPhoneNumberMatchFilter;
+    field public static final android.text.util.Linkify.TransformFilter sPhoneNumberTransformFilter;
+    field public static final android.text.util.Linkify.MatchFilter sUrlMatchFilter;
+  }
+
+  public static abstract interface Linkify.MatchFilter {
+    method public abstract boolean acceptMatch(java.lang.CharSequence, int, int);
+  }
+
+  public static abstract interface Linkify.TransformFilter {
+    method public abstract java.lang.String transformUrl(java.util.regex.Matcher, java.lang.String);
+  }
+
+  public class Rfc822Token {
+    ctor public Rfc822Token(java.lang.String, java.lang.String, java.lang.String);
+    method public java.lang.String getAddress();
+    method public java.lang.String getComment();
+    method public java.lang.String getName();
+    method public static java.lang.String quoteComment(java.lang.String);
+    method public static java.lang.String quoteName(java.lang.String);
+    method public static java.lang.String quoteNameIfNecessary(java.lang.String);
+    method public void setAddress(java.lang.String);
+    method public void setComment(java.lang.String);
+    method public void setName(java.lang.String);
+  }
+
+  public class Rfc822Tokenizer implements android.widget.MultiAutoCompleteTextView.Tokenizer {
+    ctor public Rfc822Tokenizer();
+    method public int findTokenEnd(java.lang.CharSequence, int);
+    method public int findTokenStart(java.lang.CharSequence, int);
+    method public java.lang.CharSequence terminateToken(java.lang.CharSequence);
+    method public static void tokenize(java.lang.CharSequence, java.util.Collection<android.text.util.Rfc822Token>);
+    method public static android.text.util.Rfc822Token[] tokenize(java.lang.CharSequence);
+  }
+
+}
+
+package android.util {
+
+  public class AndroidException extends java.lang.Exception {
+    ctor public AndroidException();
+    ctor public AndroidException(java.lang.String);
+    ctor public AndroidException(java.lang.String, java.lang.Throwable);
+    ctor public AndroidException(java.lang.Exception);
+  }
+
+  public class AndroidRuntimeException extends java.lang.RuntimeException {
+    ctor public AndroidRuntimeException();
+    ctor public AndroidRuntimeException(java.lang.String);
+    ctor public AndroidRuntimeException(java.lang.String, java.lang.Throwable);
+    ctor public AndroidRuntimeException(java.lang.Exception);
+  }
+
+  public class AtomicFile {
+    ctor public AtomicFile(java.io.File);
+    method public void delete();
+    method public void failWrite(java.io.FileOutputStream);
+    method public void finishWrite(java.io.FileOutputStream);
+    method public java.io.File getBaseFile();
+    method public java.io.FileInputStream openRead() throws java.io.FileNotFoundException;
+    method public byte[] readFully() throws java.io.IOException;
+    method public java.io.FileOutputStream startWrite() throws java.io.IOException;
+  }
+
+  public abstract interface AttributeSet {
+    method public abstract boolean getAttributeBooleanValue(java.lang.String, java.lang.String, boolean);
+    method public abstract boolean getAttributeBooleanValue(int, boolean);
+    method public abstract int getAttributeCount();
+    method public abstract float getAttributeFloatValue(java.lang.String, java.lang.String, float);
+    method public abstract float getAttributeFloatValue(int, float);
+    method public abstract int getAttributeIntValue(java.lang.String, java.lang.String, int);
+    method public abstract int getAttributeIntValue(int, int);
+    method public abstract int getAttributeListValue(java.lang.String, java.lang.String, java.lang.String[], int);
+    method public abstract int getAttributeListValue(int, java.lang.String[], int);
+    method public abstract java.lang.String getAttributeName(int);
+    method public abstract int getAttributeNameResource(int);
+    method public abstract int getAttributeResourceValue(java.lang.String, java.lang.String, int);
+    method public abstract int getAttributeResourceValue(int, int);
+    method public abstract int getAttributeUnsignedIntValue(java.lang.String, java.lang.String, int);
+    method public abstract int getAttributeUnsignedIntValue(int, int);
+    method public abstract java.lang.String getAttributeValue(int);
+    method public abstract java.lang.String getAttributeValue(java.lang.String, java.lang.String);
+    method public abstract java.lang.String getClassAttribute();
+    method public abstract java.lang.String getIdAttribute();
+    method public abstract int getIdAttributeResourceValue(int);
+    method public abstract java.lang.String getPositionDescription();
+    method public abstract int getStyleAttribute();
+  }
+
+  public class Base64 {
+    method public static byte[] decode(java.lang.String, int);
+    method public static byte[] decode(byte[], int);
+    method public static byte[] decode(byte[], int, int, int);
+    method public static byte[] encode(byte[], int);
+    method public static byte[] encode(byte[], int, int, int);
+    method public static java.lang.String encodeToString(byte[], int);
+    method public static java.lang.String encodeToString(byte[], int, int, int);
+    field public static final int CRLF = 4; // 0x4
+    field public static final int DEFAULT = 0; // 0x0
+    field public static final int NO_CLOSE = 16; // 0x10
+    field public static final int NO_PADDING = 1; // 0x1
+    field public static final int NO_WRAP = 2; // 0x2
+    field public static final int URL_SAFE = 8; // 0x8
+  }
+
+  public class Base64DataException extends java.io.IOException {
+    ctor public Base64DataException(java.lang.String);
+  }
+
+  public class Base64InputStream extends java.io.FilterInputStream {
+    ctor public Base64InputStream(java.io.InputStream, int);
+  }
+
+  public class Base64OutputStream extends java.io.FilterOutputStream {
+    ctor public Base64OutputStream(java.io.OutputStream, int);
+  }
+
+  public final deprecated class Config {
+    field public static final deprecated boolean DEBUG = false;
+    field public static final deprecated boolean LOGD = true;
+    field public static final deprecated boolean LOGV = false;
+    field public static final deprecated boolean PROFILE = false;
+    field public static final deprecated boolean RELEASE = true;
+  }
+
+  public class DebugUtils {
+    method public static boolean isObjectSelected(java.lang.Object);
+  }
+
+  public class DisplayMetrics {
+    ctor public DisplayMetrics();
+    method public boolean equals(android.util.DisplayMetrics);
+    method public void setTo(android.util.DisplayMetrics);
+    method public void setToDefaults();
+    field public static final int DENSITY_DEFAULT = 160; // 0xa0
+    field public static final int DENSITY_HIGH = 240; // 0xf0
+    field public static final int DENSITY_LOW = 120; // 0x78
+    field public static final int DENSITY_MEDIUM = 160; // 0xa0
+    field public static final int DENSITY_TV = 213; // 0xd5
+    field public static final int DENSITY_XHIGH = 320; // 0x140
+    field public static final int DENSITY_XXHIGH = 480; // 0x1e0
+    field public float density;
+    field public int densityDpi;
+    field public int heightPixels;
+    field public float scaledDensity;
+    field public int widthPixels;
+    field public float xdpi;
+    field public float ydpi;
+  }
+
+  public class EventLog {
+    method public static int getTagCode(java.lang.String);
+    method public static java.lang.String getTagName(int);
+    method public static void readEvents(int[], java.util.Collection<android.util.EventLog.Event>) throws java.io.IOException;
+    method public static int writeEvent(int, int);
+    method public static int writeEvent(int, long);
+    method public static int writeEvent(int, java.lang.String);
+    method public static int writeEvent(int, java.lang.Object...);
+  }
+
+  public static final class EventLog.Event {
+    method public synchronized java.lang.Object getData();
+    method public int getProcessId();
+    method public int getTag();
+    method public int getThreadId();
+    method public long getTimeNanos();
+  }
+
+  public deprecated class EventLogTags {
+    ctor public EventLogTags() throws java.io.IOException;
+    ctor public EventLogTags(java.io.BufferedReader) throws java.io.IOException;
+    method public android.util.EventLogTags.Description get(java.lang.String);
+    method public android.util.EventLogTags.Description get(int);
+  }
+
+  public static class EventLogTags.Description {
+    field public final java.lang.String mName;
+    field public final int mTag;
+  }
+
+  public class FloatMath {
+    method public static float ceil(float);
+    method public static float cos(float);
+    method public static float exp(float);
+    method public static float floor(float);
+    method public static float hypot(float, float);
+    method public static float pow(float, float);
+    method public static float sin(float);
+    method public static float sqrt(float);
+  }
+
+  public final class JsonReader implements java.io.Closeable {
+    ctor public JsonReader(java.io.Reader);
+    method public void beginArray() throws java.io.IOException;
+    method public void beginObject() throws java.io.IOException;
+    method public void close() throws java.io.IOException;
+    method public void endArray() throws java.io.IOException;
+    method public void endObject() throws java.io.IOException;
+    method public boolean hasNext() throws java.io.IOException;
+    method public boolean isLenient();
+    method public boolean nextBoolean() throws java.io.IOException;
+    method public double nextDouble() throws java.io.IOException;
+    method public int nextInt() throws java.io.IOException;
+    method public long nextLong() throws java.io.IOException;
+    method public java.lang.String nextName() throws java.io.IOException;
+    method public void nextNull() throws java.io.IOException;
+    method public java.lang.String nextString() throws java.io.IOException;
+    method public android.util.JsonToken peek() throws java.io.IOException;
+    method public void setLenient(boolean);
+    method public void skipValue() throws java.io.IOException;
+  }
+
+  public final class JsonToken extends java.lang.Enum {
+    method public static android.util.JsonToken valueOf(java.lang.String);
+    method public static final android.util.JsonToken[] values();
+    enum_constant public static final android.util.JsonToken BEGIN_ARRAY;
+    enum_constant public static final android.util.JsonToken BEGIN_OBJECT;
+    enum_constant public static final android.util.JsonToken BOOLEAN;
+    enum_constant public static final android.util.JsonToken END_ARRAY;
+    enum_constant public static final android.util.JsonToken END_DOCUMENT;
+    enum_constant public static final android.util.JsonToken END_OBJECT;
+    enum_constant public static final android.util.JsonToken NAME;
+    enum_constant public static final android.util.JsonToken NULL;
+    enum_constant public static final android.util.JsonToken NUMBER;
+    enum_constant public static final android.util.JsonToken STRING;
+  }
+
+  public final class JsonWriter implements java.io.Closeable {
+    ctor public JsonWriter(java.io.Writer);
+    method public android.util.JsonWriter beginArray() throws java.io.IOException;
+    method public android.util.JsonWriter beginObject() throws java.io.IOException;
+    method public void close() throws java.io.IOException;
+    method public android.util.JsonWriter endArray() throws java.io.IOException;
+    method public android.util.JsonWriter endObject() throws java.io.IOException;
+    method public void flush() throws java.io.IOException;
+    method public boolean isLenient();
+    method public android.util.JsonWriter name(java.lang.String) throws java.io.IOException;
+    method public android.util.JsonWriter nullValue() throws java.io.IOException;
+    method public void setIndent(java.lang.String);
+    method public void setLenient(boolean);
+    method public android.util.JsonWriter value(java.lang.String) throws java.io.IOException;
+    method public android.util.JsonWriter value(boolean) throws java.io.IOException;
+    method public android.util.JsonWriter value(double) throws java.io.IOException;
+    method public android.util.JsonWriter value(long) throws java.io.IOException;
+    method public android.util.JsonWriter value(java.lang.Number) throws java.io.IOException;
+  }
+
+  public final class Log {
+    method public static int d(java.lang.String, java.lang.String);
+    method public static int d(java.lang.String, java.lang.String, java.lang.Throwable);
+    method public static int e(java.lang.String, java.lang.String);
+    method public static int e(java.lang.String, java.lang.String, java.lang.Throwable);
+    method public static java.lang.String getStackTraceString(java.lang.Throwable);
+    method public static int i(java.lang.String, java.lang.String);
+    method public static int i(java.lang.String, java.lang.String, java.lang.Throwable);
+    method public static boolean isLoggable(java.lang.String, int);
+    method public static int println(int, java.lang.String, java.lang.String);
+    method public static int v(java.lang.String, java.lang.String);
+    method public static int v(java.lang.String, java.lang.String, java.lang.Throwable);
+    method public static int w(java.lang.String, java.lang.String);
+    method public static int w(java.lang.String, java.lang.String, java.lang.Throwable);
+    method public static int w(java.lang.String, java.lang.Throwable);
+    method public static int wtf(java.lang.String, java.lang.String);
+    method public static int wtf(java.lang.String, java.lang.Throwable);
+    method public static int wtf(java.lang.String, java.lang.String, java.lang.Throwable);
+    field public static final int ASSERT = 7; // 0x7
+    field public static final int DEBUG = 3; // 0x3
+    field public static final int ERROR = 6; // 0x6
+    field public static final int INFO = 4; // 0x4
+    field public static final int VERBOSE = 2; // 0x2
+    field public static final int WARN = 5; // 0x5
+  }
+
+  public class LogPrinter implements android.util.Printer {
+    ctor public LogPrinter(int, java.lang.String);
+    method public void println(java.lang.String);
+  }
+
+  public class LongSparseArray implements java.lang.Cloneable {
+    ctor public LongSparseArray();
+    ctor public LongSparseArray(int);
+    method public void append(long, E);
+    method public void clear();
+    method public android.util.LongSparseArray<E> clone();
+    method public void delete(long);
+    method public E get(long);
+    method public E get(long, E);
+    method public int indexOfKey(long);
+    method public int indexOfValue(E);
+    method public long keyAt(int);
+    method public void put(long, E);
+    method public void remove(long);
+    method public void removeAt(int);
+    method public void setValueAt(int, E);
+    method public int size();
+    method public E valueAt(int);
+  }
+
+  public class LruCache {
+    ctor public LruCache(int);
+    method protected V create(K);
+    method public final synchronized int createCount();
+    method protected void entryRemoved(boolean, K, V, V);
+    method public final void evictAll();
+    method public final synchronized int evictionCount();
+    method public final V get(K);
+    method public final synchronized int hitCount();
+    method public final synchronized int maxSize();
+    method public final synchronized int missCount();
+    method public final V put(K, V);
+    method public final synchronized int putCount();
+    method public final V remove(K);
+    method public final synchronized int size();
+    method protected int sizeOf(K, V);
+    method public final synchronized java.util.Map<K, V> snapshot();
+    method public final synchronized java.lang.String toString();
+    method public void trimToSize(int);
+  }
+
+  public final class MalformedJsonException extends java.io.IOException {
+    ctor public MalformedJsonException(java.lang.String);
+  }
+
+  public class MonthDisplayHelper {
+    ctor public MonthDisplayHelper(int, int, int);
+    ctor public MonthDisplayHelper(int, int);
+    method public int getColumnOf(int);
+    method public int getDayAt(int, int);
+    method public int[] getDigitsForRow(int);
+    method public int getFirstDayOfMonth();
+    method public int getMonth();
+    method public int getNumberOfDaysInMonth();
+    method public int getOffset();
+    method public int getRowOf(int);
+    method public int getWeekStartDay();
+    method public int getYear();
+    method public boolean isWithinCurrentMonth(int, int);
+    method public void nextMonth();
+    method public void previousMonth();
+  }
+
+  public class NoSuchPropertyException extends java.lang.RuntimeException {
+    ctor public NoSuchPropertyException(java.lang.String);
+  }
+
+  public class Pair {
+    ctor public Pair(F, S);
+    method public static android.util.Pair<A, B> create(A, B);
+    field public final F first;
+    field public final S second;
+  }
+
+  public class Patterns {
+    method public static final java.lang.String concatGroups(java.util.regex.Matcher);
+    method public static final java.lang.String digitsAndPlusOnly(java.util.regex.Matcher);
+    field public static final java.util.regex.Pattern DOMAIN_NAME;
+    field public static final java.util.regex.Pattern EMAIL_ADDRESS;
+    field public static final java.lang.String GOOD_IRI_CHAR = "a-zA-Z0-9\u00a0-\ud7ff\uf900-\ufdcf\ufdf0-\uffef";
+    field public static final java.util.regex.Pattern IP_ADDRESS;
+    field public static final java.util.regex.Pattern PHONE;
+    field public static final java.util.regex.Pattern TOP_LEVEL_DOMAIN;
+    field public static final java.lang.String TOP_LEVEL_DOMAIN_STR = "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(biz|b[abdefghijmnorstvwyz])|(cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(edu|e[cegrstu])|f[ijkmor]|(gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(info|int|i[delmnoqrst])|(jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(name|net|n[acefgilopruz])|(org|om)|(pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw])";
+    field public static final java.lang.String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL = "(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(?:\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw]))";
+    field public static final java.util.regex.Pattern WEB_URL;
+  }
+
+  public class PrintStreamPrinter implements android.util.Printer {
+    ctor public PrintStreamPrinter(java.io.PrintStream);
+    method public void println(java.lang.String);
+  }
+
+  public class PrintWriterPrinter implements android.util.Printer {
+    ctor public PrintWriterPrinter(java.io.PrintWriter);
+    method public void println(java.lang.String);
+  }
+
+  public abstract interface Printer {
+    method public abstract void println(java.lang.String);
+  }
+
+  public abstract class Property {
+    ctor public Property(java.lang.Class<V>, java.lang.String);
+    method public abstract V get(T);
+    method public java.lang.String getName();
+    method public java.lang.Class<V> getType();
+    method public boolean isReadOnly();
+    method public static android.util.Property<T, V> of(java.lang.Class<T>, java.lang.Class<V>, java.lang.String);
+    method public void set(T, V);
+  }
+
+  public class SparseArray implements java.lang.Cloneable {
+    ctor public SparseArray();
+    ctor public SparseArray(int);
+    method public void append(int, E);
+    method public void clear();
+    method public android.util.SparseArray<E> clone();
+    method public void delete(int);
+    method public E get(int);
+    method public E get(int, E);
+    method public int indexOfKey(int);
+    method public int indexOfValue(E);
+    method public int keyAt(int);
+    method public void put(int, E);
+    method public void remove(int);
+    method public void removeAt(int);
+    method public void setValueAt(int, E);
+    method public int size();
+    method public E valueAt(int);
+  }
+
+  public class SparseBooleanArray implements java.lang.Cloneable {
+    ctor public SparseBooleanArray();
+    ctor public SparseBooleanArray(int);
+    method public void append(int, boolean);
+    method public void clear();
+    method public android.util.SparseBooleanArray clone();
+    method public void delete(int);
+    method public boolean get(int);
+    method public boolean get(int, boolean);
+    method public int indexOfKey(int);
+    method public int indexOfValue(boolean);
+    method public int keyAt(int);
+    method public void put(int, boolean);
+    method public int size();
+    method public boolean valueAt(int);
+  }
+
+  public class SparseIntArray implements java.lang.Cloneable {
+    ctor public SparseIntArray();
+    ctor public SparseIntArray(int);
+    method public void append(int, int);
+    method public void clear();
+    method public android.util.SparseIntArray clone();
+    method public void delete(int);
+    method public int get(int);
+    method public int get(int, int);
+    method public int indexOfKey(int);
+    method public int indexOfValue(int);
+    method public int keyAt(int);
+    method public void put(int, int);
+    method public void removeAt(int);
+    method public int size();
+    method public int valueAt(int);
+  }
+
+  public class StateSet {
+    method public static java.lang.String dump(int[]);
+    method public static boolean isWildCard(int[]);
+    method public static boolean stateSetMatches(int[], int[]);
+    method public static boolean stateSetMatches(int[], int);
+    method public static int[] trimStateSet(int[], int);
+    field public static final int[] NOTHING;
+    field public static final int[] WILD_CARD;
+  }
+
+  public class StringBuilderPrinter implements android.util.Printer {
+    ctor public StringBuilderPrinter(java.lang.StringBuilder);
+    method public void println(java.lang.String);
+  }
+
+  public class TimeFormatException extends java.lang.RuntimeException {
+  }
+
+  public class TimeUtils {
+    method public static java.util.TimeZone getTimeZone(int, boolean, long, java.lang.String);
+    method public static java.lang.String getTimeZoneDatabaseVersion();
+  }
+
+  public class TimingLogger {
+    ctor public TimingLogger(java.lang.String, java.lang.String);
+    method public void addSplit(java.lang.String);
+    method public void dumpToLog();
+    method public void reset(java.lang.String, java.lang.String);
+    method public void reset();
+  }
+
+  public class TypedValue {
+    ctor public TypedValue();
+    method public static float applyDimension(int, float, android.util.DisplayMetrics);
+    method public final java.lang.CharSequence coerceToString();
+    method public static final java.lang.String coerceToString(int, int);
+    method public static float complexToDimension(int, android.util.DisplayMetrics);
+    method public static float complexToDimensionNoisy(int, android.util.DisplayMetrics);
+    method public static int complexToDimensionPixelOffset(int, android.util.DisplayMetrics);
+    method public static int complexToDimensionPixelSize(int, android.util.DisplayMetrics);
+    method public static float complexToFloat(int);
+    method public static float complexToFraction(int, float, float);
+    method public float getDimension(android.util.DisplayMetrics);
+    method public final float getFloat();
+    method public float getFraction(float, float);
+    method public void setTo(android.util.TypedValue);
+    field public static final int COMPLEX_MANTISSA_MASK = 16777215; // 0xffffff
+    field public static final int COMPLEX_MANTISSA_SHIFT = 8; // 0x8
+    field public static final int COMPLEX_RADIX_0p23 = 3; // 0x3
+    field public static final int COMPLEX_RADIX_16p7 = 1; // 0x1
+    field public static final int COMPLEX_RADIX_23p0 = 0; // 0x0
+    field public static final int COMPLEX_RADIX_8p15 = 2; // 0x2
+    field public static final int COMPLEX_RADIX_MASK = 3; // 0x3
+    field public static final int COMPLEX_RADIX_SHIFT = 4; // 0x4
+    field public static final int COMPLEX_UNIT_DIP = 1; // 0x1
+    field public static final int COMPLEX_UNIT_FRACTION = 0; // 0x0
+    field public static final int COMPLEX_UNIT_FRACTION_PARENT = 1; // 0x1
+    field public static final int COMPLEX_UNIT_IN = 4; // 0x4
+    field public static final int COMPLEX_UNIT_MASK = 15; // 0xf
+    field public static final int COMPLEX_UNIT_MM = 5; // 0x5
+    field public static final int COMPLEX_UNIT_PT = 3; // 0x3
+    field public static final int COMPLEX_UNIT_PX = 0; // 0x0
+    field public static final int COMPLEX_UNIT_SHIFT = 0; // 0x0
+    field public static final int COMPLEX_UNIT_SP = 2; // 0x2
+    field public static final int DENSITY_DEFAULT = 0; // 0x0
+    field public static final int DENSITY_NONE = 65535; // 0xffff
+    field public static final int TYPE_ATTRIBUTE = 2; // 0x2
+    field public static final int TYPE_DIMENSION = 5; // 0x5
+    field public static final int TYPE_FIRST_COLOR_INT = 28; // 0x1c
+    field public static final int TYPE_FIRST_INT = 16; // 0x10
+    field public static final int TYPE_FLOAT = 4; // 0x4
+    field public static final int TYPE_FRACTION = 6; // 0x6
+    field public static final int TYPE_INT_BOOLEAN = 18; // 0x12
+    field public static final int TYPE_INT_COLOR_ARGB4 = 30; // 0x1e
+    field public static final int TYPE_INT_COLOR_ARGB8 = 28; // 0x1c
+    field public static final int TYPE_INT_COLOR_RGB4 = 31; // 0x1f
+    field public static final int TYPE_INT_COLOR_RGB8 = 29; // 0x1d
+    field public static final int TYPE_INT_DEC = 16; // 0x10
+    field public static final int TYPE_INT_HEX = 17; // 0x11
+    field public static final int TYPE_LAST_COLOR_INT = 31; // 0x1f
+    field public static final int TYPE_LAST_INT = 31; // 0x1f
+    field public static final int TYPE_NULL = 0; // 0x0
+    field public static final int TYPE_REFERENCE = 1; // 0x1
+    field public static final int TYPE_STRING = 3; // 0x3
+    field public int assetCookie;
+    field public int changingConfigurations;
+    field public int data;
+    field public int density;
+    field public int resourceId;
+    field public java.lang.CharSequence string;
+    field public int type;
+  }
+
+  public class Xml {
+    method public static android.util.AttributeSet asAttributeSet(org.xmlpull.v1.XmlPullParser);
+    method public static android.util.Xml.Encoding findEncodingByName(java.lang.String) throws java.io.UnsupportedEncodingException;
+    method public static org.xmlpull.v1.XmlPullParser newPullParser();
+    method public static org.xmlpull.v1.XmlSerializer newSerializer();
+    method public static void parse(java.lang.String, org.xml.sax.ContentHandler) throws org.xml.sax.SAXException;
+    method public static void parse(java.io.Reader, org.xml.sax.ContentHandler) throws java.io.IOException, org.xml.sax.SAXException;
+    method public static void parse(java.io.InputStream, android.util.Xml.Encoding, org.xml.sax.ContentHandler) throws java.io.IOException, org.xml.sax.SAXException;
+    field public static java.lang.String FEATURE_RELAXED;
+  }
+
+  public static final class Xml.Encoding extends java.lang.Enum {
+    method public static android.util.Xml.Encoding valueOf(java.lang.String);
+    method public static final android.util.Xml.Encoding[] values();
+    enum_constant public static final android.util.Xml.Encoding ISO_8859_1;
+    enum_constant public static final android.util.Xml.Encoding US_ASCII;
+    enum_constant public static final android.util.Xml.Encoding UTF_16;
+    enum_constant public static final android.util.Xml.Encoding UTF_8;
+  }
+
+}
+
+package android.view {
+
+  public abstract class AbsSavedState implements android.os.Parcelable {
+    ctor protected AbsSavedState(android.os.Parcelable);
+    ctor protected AbsSavedState(android.os.Parcel);
+    method public int describeContents();
+    method public final android.os.Parcelable getSuperState();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final android.view.AbsSavedState EMPTY_STATE;
+  }
+
+  public abstract class ActionMode {
+    ctor public ActionMode();
+    method public abstract void finish();
+    method public abstract android.view.View getCustomView();
+    method public abstract android.view.Menu getMenu();
+    method public abstract android.view.MenuInflater getMenuInflater();
+    method public abstract java.lang.CharSequence getSubtitle();
+    method public java.lang.Object getTag();
+    method public abstract java.lang.CharSequence getTitle();
+    method public boolean getTitleOptionalHint();
+    method public abstract void invalidate();
+    method public boolean isTitleOptional();
+    method public abstract void setCustomView(android.view.View);
+    method public abstract void setSubtitle(java.lang.CharSequence);
+    method public abstract void setSubtitle(int);
+    method public void setTag(java.lang.Object);
+    method public abstract void setTitle(java.lang.CharSequence);
+    method public abstract void setTitle(int);
+    method public void setTitleOptionalHint(boolean);
+  }
+
+  public static abstract interface ActionMode.Callback {
+    method public abstract boolean onActionItemClicked(android.view.ActionMode, android.view.MenuItem);
+    method public abstract boolean onCreateActionMode(android.view.ActionMode, android.view.Menu);
+    method public abstract void onDestroyActionMode(android.view.ActionMode);
+    method public abstract boolean onPrepareActionMode(android.view.ActionMode, android.view.Menu);
+  }
+
+  public abstract class ActionProvider {
+    ctor public ActionProvider(android.content.Context);
+    method public boolean hasSubMenu();
+    method public boolean isVisible();
+    method public abstract deprecated android.view.View onCreateActionView();
+    method public android.view.View onCreateActionView(android.view.MenuItem);
+    method public boolean onPerformDefaultAction();
+    method public void onPrepareSubMenu(android.view.SubMenu);
+    method public boolean overridesItemVisibility();
+    method public void refreshVisibility();
+    method public void setVisibilityListener(android.view.ActionProvider.VisibilityListener);
+  }
+
+  public static abstract interface ActionProvider.VisibilityListener {
+    method public abstract void onActionProviderVisibilityChanged(boolean);
+  }
+
+  public final class Choreographer {
+    method public static android.view.Choreographer getInstance();
+    method public void postFrameCallback(android.view.Choreographer.FrameCallback);
+    method public void postFrameCallbackDelayed(android.view.Choreographer.FrameCallback, long);
+    method public void removeFrameCallback(android.view.Choreographer.FrameCallback);
+  }
+
+  public static abstract interface Choreographer.FrameCallback {
+    method public abstract void doFrame(long);
+  }
+
+  public abstract interface CollapsibleActionView {
+    method public abstract void onActionViewCollapsed();
+    method public abstract void onActionViewExpanded();
+  }
+
+  public abstract interface ContextMenu implements android.view.Menu {
+    method public abstract void clearHeader();
+    method public abstract android.view.ContextMenu setHeaderIcon(int);
+    method public abstract android.view.ContextMenu setHeaderIcon(android.graphics.drawable.Drawable);
+    method public abstract android.view.ContextMenu setHeaderTitle(int);
+    method public abstract android.view.ContextMenu setHeaderTitle(java.lang.CharSequence);
+    method public abstract android.view.ContextMenu setHeaderView(android.view.View);
+  }
+
+  public static abstract interface ContextMenu.ContextMenuInfo {
+  }
+
+  public class ContextThemeWrapper extends android.content.ContextWrapper {
+    ctor public ContextThemeWrapper();
+    ctor public ContextThemeWrapper(android.content.Context, int);
+    method public void applyOverrideConfiguration(android.content.res.Configuration);
+    method protected void onApplyThemeResource(android.content.res.Resources.Theme, int, boolean);
+  }
+
+  public final class Display {
+    method public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point);
+    method public int getDisplayId();
+    method public int getFlags();
+    method public deprecated int getHeight();
+    method public void getMetrics(android.util.DisplayMetrics);
+    method public java.lang.String getName();
+    method public deprecated int getOrientation();
+    method public deprecated int getPixelFormat();
+    method public void getRealMetrics(android.util.DisplayMetrics);
+    method public void getRealSize(android.graphics.Point);
+    method public void getRectSize(android.graphics.Rect);
+    method public float getRefreshRate();
+    method public int getRotation();
+    method public void getSize(android.graphics.Point);
+    method public deprecated int getWidth();
+    method public boolean isValid();
+    field public static final int DEFAULT_DISPLAY = 0; // 0x0
+    field public static final int FLAG_SECURE = 2; // 0x2
+    field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1
+  }
+
+  public class DragEvent implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getAction();
+    method public android.content.ClipData getClipData();
+    method public android.content.ClipDescription getClipDescription();
+    method public java.lang.Object getLocalState();
+    method public boolean getResult();
+    method public float getX();
+    method public float getY();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ACTION_DRAG_ENDED = 4; // 0x4
+    field public static final int ACTION_DRAG_ENTERED = 5; // 0x5
+    field public static final int ACTION_DRAG_EXITED = 6; // 0x6
+    field public static final int ACTION_DRAG_LOCATION = 2; // 0x2
+    field public static final int ACTION_DRAG_STARTED = 1; // 0x1
+    field public static final int ACTION_DROP = 3; // 0x3
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class FocusFinder {
+    method public android.view.View findNearestTouchable(android.view.ViewGroup, int, int, int, int[]);
+    method public final android.view.View findNextFocus(android.view.ViewGroup, android.view.View, int);
+    method public android.view.View findNextFocusFromRect(android.view.ViewGroup, android.graphics.Rect, int);
+    method public static android.view.FocusFinder getInstance();
+  }
+
+  public class GestureDetector {
+    ctor public deprecated GestureDetector(android.view.GestureDetector.OnGestureListener, android.os.Handler);
+    ctor public deprecated GestureDetector(android.view.GestureDetector.OnGestureListener);
+    ctor public GestureDetector(android.content.Context, android.view.GestureDetector.OnGestureListener);
+    ctor public GestureDetector(android.content.Context, android.view.GestureDetector.OnGestureListener, android.os.Handler);
+    ctor public GestureDetector(android.content.Context, android.view.GestureDetector.OnGestureListener, android.os.Handler, boolean);
+    method public boolean isLongpressEnabled();
+    method public boolean onTouchEvent(android.view.MotionEvent);
+    method public void setIsLongpressEnabled(boolean);
+    method public void setOnDoubleTapListener(android.view.GestureDetector.OnDoubleTapListener);
+  }
+
+  public static abstract interface GestureDetector.OnDoubleTapListener {
+    method public abstract boolean onDoubleTap(android.view.MotionEvent);
+    method public abstract boolean onDoubleTapEvent(android.view.MotionEvent);
+    method public abstract boolean onSingleTapConfirmed(android.view.MotionEvent);
+  }
+
+  public static abstract interface GestureDetector.OnGestureListener {
+    method public abstract boolean onDown(android.view.MotionEvent);
+    method public abstract boolean onFling(android.view.MotionEvent, android.view.MotionEvent, float, float);
+    method public abstract void onLongPress(android.view.MotionEvent);
+    method public abstract boolean onScroll(android.view.MotionEvent, android.view.MotionEvent, float, float);
+    method public abstract void onShowPress(android.view.MotionEvent);
+    method public abstract boolean onSingleTapUp(android.view.MotionEvent);
+  }
+
+  public static class GestureDetector.SimpleOnGestureListener implements android.view.GestureDetector.OnDoubleTapListener android.view.GestureDetector.OnGestureListener {
+    ctor public GestureDetector.SimpleOnGestureListener();
+    method public boolean onDoubleTap(android.view.MotionEvent);
+    method public boolean onDoubleTapEvent(android.view.MotionEvent);
+    method public boolean onDown(android.view.MotionEvent);
+    method public boolean onFling(android.view.MotionEvent, android.view.MotionEvent, float, float);
+    method public void onLongPress(android.view.MotionEvent);
+    method public boolean onScroll(android.view.MotionEvent, android.view.MotionEvent, float, float);
+    method public void onShowPress(android.view.MotionEvent);
+    method public boolean onSingleTapConfirmed(android.view.MotionEvent);
+    method public boolean onSingleTapUp(android.view.MotionEvent);
+  }
+
+  public class Gravity {
+    ctor public Gravity();
+    method public static void apply(int, int, int, android.graphics.Rect, android.graphics.Rect);
+    method public static void apply(int, int, int, android.graphics.Rect, android.graphics.Rect, int);
+    method public static void apply(int, int, int, android.graphics.Rect, int, int, android.graphics.Rect);
+    method public static void apply(int, int, int, android.graphics.Rect, int, int, android.graphics.Rect, int);
+    method public static void applyDisplay(int, android.graphics.Rect, android.graphics.Rect);
+    method public static void applyDisplay(int, android.graphics.Rect, android.graphics.Rect, int);
+    method public static int getAbsoluteGravity(int, int);
+    method public static boolean isHorizontal(int);
+    method public static boolean isVertical(int);
+    field public static final int AXIS_CLIP = 8; // 0x8
+    field public static final int AXIS_PULL_AFTER = 4; // 0x4
+    field public static final int AXIS_PULL_BEFORE = 2; // 0x2
+    field public static final int AXIS_SPECIFIED = 1; // 0x1
+    field public static final int AXIS_X_SHIFT = 0; // 0x0
+    field public static final int AXIS_Y_SHIFT = 4; // 0x4
+    field public static final int BOTTOM = 80; // 0x50
+    field public static final int CENTER = 17; // 0x11
+    field public static final int CENTER_HORIZONTAL = 1; // 0x1
+    field public static final int CENTER_VERTICAL = 16; // 0x10
+    field public static final int CLIP_HORIZONTAL = 8; // 0x8
+    field public static final int CLIP_VERTICAL = 128; // 0x80
+    field public static final int DISPLAY_CLIP_HORIZONTAL = 16777216; // 0x1000000
+    field public static final int DISPLAY_CLIP_VERTICAL = 268435456; // 0x10000000
+    field public static final int END = 8388613; // 0x800005
+    field public static final int FILL = 119; // 0x77
+    field public static final int FILL_HORIZONTAL = 7; // 0x7
+    field public static final int FILL_VERTICAL = 112; // 0x70
+    field public static final int HORIZONTAL_GRAVITY_MASK = 7; // 0x7
+    field public static final int LEFT = 3; // 0x3
+    field public static final int NO_GRAVITY = 0; // 0x0
+    field public static final int RELATIVE_HORIZONTAL_GRAVITY_MASK = 8388615; // 0x800007
+    field public static final int RELATIVE_LAYOUT_DIRECTION = 8388608; // 0x800000
+    field public static final int RIGHT = 5; // 0x5
+    field public static final int START = 8388611; // 0x800003
+    field public static final int TOP = 48; // 0x30
+    field public static final int VERTICAL_GRAVITY_MASK = 112; // 0x70
+  }
+
+  public class HapticFeedbackConstants {
+    field public static final int FLAG_IGNORE_GLOBAL_SETTING = 2; // 0x2
+    field public static final int FLAG_IGNORE_VIEW_SETTING = 1; // 0x1
+    field public static final int KEYBOARD_TAP = 3; // 0x3
+    field public static final int LONG_PRESS = 0; // 0x0
+    field public static final int VIRTUAL_KEY = 1; // 0x1
+  }
+
+  public class InflateException extends java.lang.RuntimeException {
+    ctor public InflateException();
+    ctor public InflateException(java.lang.String, java.lang.Throwable);
+    ctor public InflateException(java.lang.String);
+    ctor public InflateException(java.lang.Throwable);
+  }
+
+  public final class InputDevice implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.String getDescriptor();
+    method public static android.view.InputDevice getDevice(int);
+    method public static int[] getDeviceIds();
+    method public int getId();
+    method public android.view.KeyCharacterMap getKeyCharacterMap();
+    method public int getKeyboardType();
+    method public android.view.InputDevice.MotionRange getMotionRange(int);
+    method public android.view.InputDevice.MotionRange getMotionRange(int, int);
+    method public java.util.List<android.view.InputDevice.MotionRange> getMotionRanges();
+    method public java.lang.String getName();
+    method public int getSources();
+    method public android.os.Vibrator getVibrator();
+    method public boolean isVirtual();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int KEYBOARD_TYPE_ALPHABETIC = 2; // 0x2
+    field public static final int KEYBOARD_TYPE_NONE = 0; // 0x0
+    field public static final int KEYBOARD_TYPE_NON_ALPHABETIC = 1; // 0x1
+    field public static final deprecated int MOTION_RANGE_ORIENTATION = 8; // 0x8
+    field public static final deprecated int MOTION_RANGE_PRESSURE = 2; // 0x2
+    field public static final deprecated int MOTION_RANGE_SIZE = 3; // 0x3
+    field public static final deprecated int MOTION_RANGE_TOOL_MAJOR = 6; // 0x6
+    field public static final deprecated int MOTION_RANGE_TOOL_MINOR = 7; // 0x7
+    field public static final deprecated int MOTION_RANGE_TOUCH_MAJOR = 4; // 0x4
+    field public static final deprecated int MOTION_RANGE_TOUCH_MINOR = 5; // 0x5
+    field public static final deprecated int MOTION_RANGE_X = 0; // 0x0
+    field public static final deprecated int MOTION_RANGE_Y = 1; // 0x1
+    field public static final int SOURCE_ANY = -256; // 0xffffff00
+    field public static final int SOURCE_CLASS_BUTTON = 1; // 0x1
+    field public static final int SOURCE_CLASS_JOYSTICK = 16; // 0x10
+    field public static final int SOURCE_CLASS_MASK = 255; // 0xff
+    field public static final int SOURCE_CLASS_POINTER = 2; // 0x2
+    field public static final int SOURCE_CLASS_POSITION = 8; // 0x8
+    field public static final int SOURCE_CLASS_TRACKBALL = 4; // 0x4
+    field public static final int SOURCE_DPAD = 513; // 0x201
+    field public static final int SOURCE_GAMEPAD = 1025; // 0x401
+    field public static final int SOURCE_JOYSTICK = 16777232; // 0x1000010
+    field public static final int SOURCE_KEYBOARD = 257; // 0x101
+    field public static final int SOURCE_MOUSE = 8194; // 0x2002
+    field public static final int SOURCE_STYLUS = 16386; // 0x4002
+    field public static final int SOURCE_TOUCHPAD = 1048584; // 0x100008
+    field public static final int SOURCE_TOUCHSCREEN = 4098; // 0x1002
+    field public static final int SOURCE_TRACKBALL = 65540; // 0x10004
+    field public static final int SOURCE_UNKNOWN = 0; // 0x0
+  }
+
+  public static final class InputDevice.MotionRange {
+    method public int getAxis();
+    method public float getFlat();
+    method public float getFuzz();
+    method public float getMax();
+    method public float getMin();
+    method public float getRange();
+    method public int getSource();
+  }
+
+  public abstract class InputEvent implements android.os.Parcelable {
+    method public int describeContents();
+    method public final android.view.InputDevice getDevice();
+    method public abstract int getDeviceId();
+    method public abstract long getEventTime();
+    method public abstract int getSource();
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class InputQueue {
+  }
+
+  public static abstract interface InputQueue.Callback {
+    method public abstract void onInputQueueCreated(android.view.InputQueue);
+    method public abstract void onInputQueueDestroyed(android.view.InputQueue);
+  }
+
+  public class KeyCharacterMap implements android.os.Parcelable {
+    method public int describeContents();
+    method public static boolean deviceHasKey(int);
+    method public static boolean[] deviceHasKeys(int[]);
+    method public int get(int, int);
+    method public static int getDeadChar(int, int);
+    method public char getDisplayLabel(int);
+    method public android.view.KeyEvent[] getEvents(char[]);
+    method public deprecated boolean getKeyData(int, android.view.KeyCharacterMap.KeyData);
+    method public int getKeyboardType();
+    method public char getMatch(int, char[]);
+    method public char getMatch(int, char[], int);
+    method public int getModifierBehavior();
+    method public char getNumber(int);
+    method public boolean isPrintingKey(int);
+    method public static android.view.KeyCharacterMap load(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ALPHA = 3; // 0x3
+    field public static final deprecated int BUILT_IN_KEYBOARD = 0; // 0x0
+    field public static final int COMBINING_ACCENT = -2147483648; // 0x80000000
+    field public static final int COMBINING_ACCENT_MASK = 2147483647; // 0x7fffffff
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FULL = 4; // 0x4
+    field public static final char HEX_INPUT = 61184; // 0xef00 '\uef00'
+    field public static final int MODIFIER_BEHAVIOR_CHORDED = 0; // 0x0
+    field public static final int MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED = 1; // 0x1
+    field public static final int NUMERIC = 1; // 0x1
+    field public static final char PICKER_DIALOG_INPUT = 61185; // 0xef01 '\uef01'
+    field public static final int PREDICTIVE = 2; // 0x2
+    field public static final int SPECIAL_FUNCTION = 5; // 0x5
+    field public static final int VIRTUAL_KEYBOARD = -1; // 0xffffffff
+  }
+
+  public static deprecated class KeyCharacterMap.KeyData {
+    ctor public KeyCharacterMap.KeyData();
+    field public static final int META_LENGTH = 4; // 0x4
+    field public char displayLabel;
+    field public char[] meta;
+    field public char number;
+  }
+
+  public static class KeyCharacterMap.UnavailableException extends android.util.AndroidRuntimeException {
+    ctor public KeyCharacterMap.UnavailableException(java.lang.String);
+  }
+
+  public class KeyEvent extends android.view.InputEvent implements android.os.Parcelable {
+    ctor public KeyEvent(int, int);
+    ctor public KeyEvent(long, long, int, int, int);
+    ctor public KeyEvent(long, long, int, int, int, int);
+    ctor public KeyEvent(long, long, int, int, int, int, int, int);
+    ctor public KeyEvent(long, long, int, int, int, int, int, int, int);
+    ctor public KeyEvent(long, long, int, int, int, int, int, int, int, int);
+    ctor public KeyEvent(long, java.lang.String, int, int);
+    ctor public KeyEvent(android.view.KeyEvent);
+    ctor public deprecated KeyEvent(android.view.KeyEvent, long, int);
+    method public static android.view.KeyEvent changeAction(android.view.KeyEvent, int);
+    method public static android.view.KeyEvent changeFlags(android.view.KeyEvent, int);
+    method public static android.view.KeyEvent changeTimeRepeat(android.view.KeyEvent, long, int);
+    method public static android.view.KeyEvent changeTimeRepeat(android.view.KeyEvent, long, int, int);
+    method public final deprecated boolean dispatch(android.view.KeyEvent.Callback);
+    method public final boolean dispatch(android.view.KeyEvent.Callback, android.view.KeyEvent.DispatcherState, java.lang.Object);
+    method public final int getAction();
+    method public final java.lang.String getCharacters();
+    method public static int getDeadChar(int, int);
+    method public final int getDeviceId();
+    method public char getDisplayLabel();
+    method public final long getDownTime();
+    method public final long getEventTime();
+    method public final int getFlags();
+    method public final android.view.KeyCharacterMap getKeyCharacterMap();
+    method public final int getKeyCode();
+    method public deprecated boolean getKeyData(android.view.KeyCharacterMap.KeyData);
+    method public char getMatch(char[]);
+    method public char getMatch(char[], int);
+    method public static int getMaxKeyCode();
+    method public final int getMetaState();
+    method public static int getModifierMetaStateMask();
+    method public final int getModifiers();
+    method public char getNumber();
+    method public final int getRepeatCount();
+    method public final int getScanCode();
+    method public final int getSource();
+    method public int getUnicodeChar();
+    method public int getUnicodeChar(int);
+    method public final boolean hasModifiers(int);
+    method public final boolean hasNoModifiers();
+    method public final boolean isAltPressed();
+    method public final boolean isCanceled();
+    method public final boolean isCapsLockOn();
+    method public final boolean isCtrlPressed();
+    method public final boolean isFunctionPressed();
+    method public static final boolean isGamepadButton(int);
+    method public final boolean isLongPress();
+    method public final boolean isMetaPressed();
+    method public static boolean isModifierKey(int);
+    method public final boolean isNumLockOn();
+    method public boolean isPrintingKey();
+    method public final boolean isScrollLockOn();
+    method public final boolean isShiftPressed();
+    method public final boolean isSymPressed();
+    method public final boolean isSystem();
+    method public final boolean isTracking();
+    method public static int keyCodeFromString(java.lang.String);
+    method public static java.lang.String keyCodeToString(int);
+    method public static boolean metaStateHasModifiers(int, int);
+    method public static boolean metaStateHasNoModifiers(int);
+    method public static int normalizeMetaState(int);
+    method public final void setSource(int);
+    method public final void startTracking();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ACTION_DOWN = 0; // 0x0
+    field public static final int ACTION_MULTIPLE = 2; // 0x2
+    field public static final int ACTION_UP = 1; // 0x1
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_CANCELED = 32; // 0x20
+    field public static final int FLAG_CANCELED_LONG_PRESS = 256; // 0x100
+    field public static final int FLAG_EDITOR_ACTION = 16; // 0x10
+    field public static final int FLAG_FALLBACK = 1024; // 0x400
+    field public static final int FLAG_FROM_SYSTEM = 8; // 0x8
+    field public static final int FLAG_KEEP_TOUCH_MODE = 4; // 0x4
+    field public static final int FLAG_LONG_PRESS = 128; // 0x80
+    field public static final int FLAG_SOFT_KEYBOARD = 2; // 0x2
+    field public static final int FLAG_TRACKING = 512; // 0x200
+    field public static final int FLAG_VIRTUAL_HARD_KEY = 64; // 0x40
+    field public static final int FLAG_WOKE_HERE = 1; // 0x1
+    field public static final int KEYCODE_0 = 7; // 0x7
+    field public static final int KEYCODE_1 = 8; // 0x8
+    field public static final int KEYCODE_2 = 9; // 0x9
+    field public static final int KEYCODE_3 = 10; // 0xa
+    field public static final int KEYCODE_3D_MODE = 206; // 0xce
+    field public static final int KEYCODE_4 = 11; // 0xb
+    field public static final int KEYCODE_5 = 12; // 0xc
+    field public static final int KEYCODE_6 = 13; // 0xd
+    field public static final int KEYCODE_7 = 14; // 0xe
+    field public static final int KEYCODE_8 = 15; // 0xf
+    field public static final int KEYCODE_9 = 16; // 0x10
+    field public static final int KEYCODE_A = 29; // 0x1d
+    field public static final int KEYCODE_ALT_LEFT = 57; // 0x39
+    field public static final int KEYCODE_ALT_RIGHT = 58; // 0x3a
+    field public static final int KEYCODE_APOSTROPHE = 75; // 0x4b
+    field public static final int KEYCODE_APP_SWITCH = 187; // 0xbb
+    field public static final int KEYCODE_ASSIST = 219; // 0xdb
+    field public static final int KEYCODE_AT = 77; // 0x4d
+    field public static final int KEYCODE_AVR_INPUT = 182; // 0xb6
+    field public static final int KEYCODE_AVR_POWER = 181; // 0xb5
+    field public static final int KEYCODE_B = 30; // 0x1e
+    field public static final int KEYCODE_BACK = 4; // 0x4
+    field public static final int KEYCODE_BACKSLASH = 73; // 0x49
+    field public static final int KEYCODE_BOOKMARK = 174; // 0xae
+    field public static final int KEYCODE_BREAK = 121; // 0x79
+    field public static final int KEYCODE_BUTTON_1 = 188; // 0xbc
+    field public static final int KEYCODE_BUTTON_10 = 197; // 0xc5
+    field public static final int KEYCODE_BUTTON_11 = 198; // 0xc6
+    field public static final int KEYCODE_BUTTON_12 = 199; // 0xc7
+    field public static final int KEYCODE_BUTTON_13 = 200; // 0xc8
+    field public static final int KEYCODE_BUTTON_14 = 201; // 0xc9
+    field public static final int KEYCODE_BUTTON_15 = 202; // 0xca
+    field public static final int KEYCODE_BUTTON_16 = 203; // 0xcb
+    field public static final int KEYCODE_BUTTON_2 = 189; // 0xbd
+    field public static final int KEYCODE_BUTTON_3 = 190; // 0xbe
+    field public static final int KEYCODE_BUTTON_4 = 191; // 0xbf
+    field public static final int KEYCODE_BUTTON_5 = 192; // 0xc0
+    field public static final int KEYCODE_BUTTON_6 = 193; // 0xc1
+    field public static final int KEYCODE_BUTTON_7 = 194; // 0xc2
+    field public static final int KEYCODE_BUTTON_8 = 195; // 0xc3
+    field public static final int KEYCODE_BUTTON_9 = 196; // 0xc4
+    field public static final int KEYCODE_BUTTON_A = 96; // 0x60
+    field public static final int KEYCODE_BUTTON_B = 97; // 0x61
+    field public static final int KEYCODE_BUTTON_C = 98; // 0x62
+    field public static final int KEYCODE_BUTTON_L1 = 102; // 0x66
+    field public static final int KEYCODE_BUTTON_L2 = 104; // 0x68
+    field public static final int KEYCODE_BUTTON_MODE = 110; // 0x6e
+    field public static final int KEYCODE_BUTTON_R1 = 103; // 0x67
+    field public static final int KEYCODE_BUTTON_R2 = 105; // 0x69
+    field public static final int KEYCODE_BUTTON_SELECT = 109; // 0x6d
+    field public static final int KEYCODE_BUTTON_START = 108; // 0x6c
+    field public static final int KEYCODE_BUTTON_THUMBL = 106; // 0x6a
+    field public static final int KEYCODE_BUTTON_THUMBR = 107; // 0x6b
+    field public static final int KEYCODE_BUTTON_X = 99; // 0x63
+    field public static final int KEYCODE_BUTTON_Y = 100; // 0x64
+    field public static final int KEYCODE_BUTTON_Z = 101; // 0x65
+    field public static final int KEYCODE_C = 31; // 0x1f
+    field public static final int KEYCODE_CALCULATOR = 210; // 0xd2
+    field public static final int KEYCODE_CALENDAR = 208; // 0xd0
+    field public static final int KEYCODE_CALL = 5; // 0x5
+    field public static final int KEYCODE_CAMERA = 27; // 0x1b
+    field public static final int KEYCODE_CAPS_LOCK = 115; // 0x73
+    field public static final int KEYCODE_CAPTIONS = 175; // 0xaf
+    field public static final int KEYCODE_CHANNEL_DOWN = 167; // 0xa7
+    field public static final int KEYCODE_CHANNEL_UP = 166; // 0xa6
+    field public static final int KEYCODE_CLEAR = 28; // 0x1c
+    field public static final int KEYCODE_COMMA = 55; // 0x37
+    field public static final int KEYCODE_CONTACTS = 207; // 0xcf
+    field public static final int KEYCODE_CTRL_LEFT = 113; // 0x71
+    field public static final int KEYCODE_CTRL_RIGHT = 114; // 0x72
+    field public static final int KEYCODE_D = 32; // 0x20
+    field public static final int KEYCODE_DEL = 67; // 0x43
+    field public static final int KEYCODE_DPAD_CENTER = 23; // 0x17
+    field public static final int KEYCODE_DPAD_DOWN = 20; // 0x14
+    field public static final int KEYCODE_DPAD_LEFT = 21; // 0x15
+    field public static final int KEYCODE_DPAD_RIGHT = 22; // 0x16
+    field public static final int KEYCODE_DPAD_UP = 19; // 0x13
+    field public static final int KEYCODE_DVR = 173; // 0xad
+    field public static final int KEYCODE_E = 33; // 0x21
+    field public static final int KEYCODE_EISU = 212; // 0xd4
+    field public static final int KEYCODE_ENDCALL = 6; // 0x6
+    field public static final int KEYCODE_ENTER = 66; // 0x42
+    field public static final int KEYCODE_ENVELOPE = 65; // 0x41
+    field public static final int KEYCODE_EQUALS = 70; // 0x46
+    field public static final int KEYCODE_ESCAPE = 111; // 0x6f
+    field public static final int KEYCODE_EXPLORER = 64; // 0x40
+    field public static final int KEYCODE_F = 34; // 0x22
+    field public static final int KEYCODE_F1 = 131; // 0x83
+    field public static final int KEYCODE_F10 = 140; // 0x8c
+    field public static final int KEYCODE_F11 = 141; // 0x8d
+    field public static final int KEYCODE_F12 = 142; // 0x8e
+    field public static final int KEYCODE_F2 = 132; // 0x84
+    field public static final int KEYCODE_F3 = 133; // 0x85
+    field public static final int KEYCODE_F4 = 134; // 0x86
+    field public static final int KEYCODE_F5 = 135; // 0x87
+    field public static final int KEYCODE_F6 = 136; // 0x88
+    field public static final int KEYCODE_F7 = 137; // 0x89
+    field public static final int KEYCODE_F8 = 138; // 0x8a
+    field public static final int KEYCODE_F9 = 139; // 0x8b
+    field public static final int KEYCODE_FOCUS = 80; // 0x50
+    field public static final int KEYCODE_FORWARD = 125; // 0x7d
+    field public static final int KEYCODE_FORWARD_DEL = 112; // 0x70
+    field public static final int KEYCODE_FUNCTION = 119; // 0x77
+    field public static final int KEYCODE_G = 35; // 0x23
+    field public static final int KEYCODE_GRAVE = 68; // 0x44
+    field public static final int KEYCODE_GUIDE = 172; // 0xac
+    field public static final int KEYCODE_H = 36; // 0x24
+    field public static final int KEYCODE_HEADSETHOOK = 79; // 0x4f
+    field public static final int KEYCODE_HENKAN = 214; // 0xd6
+    field public static final int KEYCODE_HOME = 3; // 0x3
+    field public static final int KEYCODE_I = 37; // 0x25
+    field public static final int KEYCODE_INFO = 165; // 0xa5
+    field public static final int KEYCODE_INSERT = 124; // 0x7c
+    field public static final int KEYCODE_J = 38; // 0x26
+    field public static final int KEYCODE_K = 39; // 0x27
+    field public static final int KEYCODE_KANA = 218; // 0xda
+    field public static final int KEYCODE_KATAKANA_HIRAGANA = 215; // 0xd7
+    field public static final int KEYCODE_L = 40; // 0x28
+    field public static final int KEYCODE_LANGUAGE_SWITCH = 204; // 0xcc
+    field public static final int KEYCODE_LEFT_BRACKET = 71; // 0x47
+    field public static final int KEYCODE_M = 41; // 0x29
+    field public static final int KEYCODE_MANNER_MODE = 205; // 0xcd
+    field public static final int KEYCODE_MEDIA_CLOSE = 128; // 0x80
+    field public static final int KEYCODE_MEDIA_EJECT = 129; // 0x81
+    field public static final int KEYCODE_MEDIA_FAST_FORWARD = 90; // 0x5a
+    field public static final int KEYCODE_MEDIA_NEXT = 87; // 0x57
+    field public static final int KEYCODE_MEDIA_PAUSE = 127; // 0x7f
+    field public static final int KEYCODE_MEDIA_PLAY = 126; // 0x7e
+    field public static final int KEYCODE_MEDIA_PLAY_PAUSE = 85; // 0x55
+    field public static final int KEYCODE_MEDIA_PREVIOUS = 88; // 0x58
+    field public static final int KEYCODE_MEDIA_RECORD = 130; // 0x82
+    field public static final int KEYCODE_MEDIA_REWIND = 89; // 0x59
+    field public static final int KEYCODE_MEDIA_STOP = 86; // 0x56
+    field public static final int KEYCODE_MENU = 82; // 0x52
+    field public static final int KEYCODE_META_LEFT = 117; // 0x75
+    field public static final int KEYCODE_META_RIGHT = 118; // 0x76
+    field public static final int KEYCODE_MINUS = 69; // 0x45
+    field public static final int KEYCODE_MOVE_END = 123; // 0x7b
+    field public static final int KEYCODE_MOVE_HOME = 122; // 0x7a
+    field public static final int KEYCODE_MUHENKAN = 213; // 0xd5
+    field public static final int KEYCODE_MUSIC = 209; // 0xd1
+    field public static final int KEYCODE_MUTE = 91; // 0x5b
+    field public static final int KEYCODE_N = 42; // 0x2a
+    field public static final int KEYCODE_NOTIFICATION = 83; // 0x53
+    field public static final int KEYCODE_NUM = 78; // 0x4e
+    field public static final int KEYCODE_NUMPAD_0 = 144; // 0x90
+    field public static final int KEYCODE_NUMPAD_1 = 145; // 0x91
+    field public static final int KEYCODE_NUMPAD_2 = 146; // 0x92
+    field public static final int KEYCODE_NUMPAD_3 = 147; // 0x93
+    field public static final int KEYCODE_NUMPAD_4 = 148; // 0x94
+    field public static final int KEYCODE_NUMPAD_5 = 149; // 0x95
+    field public static final int KEYCODE_NUMPAD_6 = 150; // 0x96
+    field public static final int KEYCODE_NUMPAD_7 = 151; // 0x97
+    field public static final int KEYCODE_NUMPAD_8 = 152; // 0x98
+    field public static final int KEYCODE_NUMPAD_9 = 153; // 0x99
+    field public static final int KEYCODE_NUMPAD_ADD = 157; // 0x9d
+    field public static final int KEYCODE_NUMPAD_COMMA = 159; // 0x9f
+    field public static final int KEYCODE_NUMPAD_DIVIDE = 154; // 0x9a
+    field public static final int KEYCODE_NUMPAD_DOT = 158; // 0x9e
+    field public static final int KEYCODE_NUMPAD_ENTER = 160; // 0xa0
+    field public static final int KEYCODE_NUMPAD_EQUALS = 161; // 0xa1
+    field public static final int KEYCODE_NUMPAD_LEFT_PAREN = 162; // 0xa2
+    field public static final int KEYCODE_NUMPAD_MULTIPLY = 155; // 0x9b
+    field public static final int KEYCODE_NUMPAD_RIGHT_PAREN = 163; // 0xa3
+    field public static final int KEYCODE_NUMPAD_SUBTRACT = 156; // 0x9c
+    field public static final int KEYCODE_NUM_LOCK = 143; // 0x8f
+    field public static final int KEYCODE_O = 43; // 0x2b
+    field public static final int KEYCODE_P = 44; // 0x2c
+    field public static final int KEYCODE_PAGE_DOWN = 93; // 0x5d
+    field public static final int KEYCODE_PAGE_UP = 92; // 0x5c
+    field public static final int KEYCODE_PERIOD = 56; // 0x38
+    field public static final int KEYCODE_PICTSYMBOLS = 94; // 0x5e
+    field public static final int KEYCODE_PLUS = 81; // 0x51
+    field public static final int KEYCODE_POUND = 18; // 0x12
+    field public static final int KEYCODE_POWER = 26; // 0x1a
+    field public static final int KEYCODE_PROG_BLUE = 186; // 0xba
+    field public static final int KEYCODE_PROG_GREEN = 184; // 0xb8
+    field public static final int KEYCODE_PROG_RED = 183; // 0xb7
+    field public static final int KEYCODE_PROG_YELLOW = 185; // 0xb9
+    field public static final int KEYCODE_Q = 45; // 0x2d
+    field public static final int KEYCODE_R = 46; // 0x2e
+    field public static final int KEYCODE_RIGHT_BRACKET = 72; // 0x48
+    field public static final int KEYCODE_RO = 217; // 0xd9
+    field public static final int KEYCODE_S = 47; // 0x2f
+    field public static final int KEYCODE_SCROLL_LOCK = 116; // 0x74
+    field public static final int KEYCODE_SEARCH = 84; // 0x54
+    field public static final int KEYCODE_SEMICOLON = 74; // 0x4a
+    field public static final int KEYCODE_SETTINGS = 176; // 0xb0
+    field public static final int KEYCODE_SHIFT_LEFT = 59; // 0x3b
+    field public static final int KEYCODE_SHIFT_RIGHT = 60; // 0x3c
+    field public static final int KEYCODE_SLASH = 76; // 0x4c
+    field public static final int KEYCODE_SOFT_LEFT = 1; // 0x1
+    field public static final int KEYCODE_SOFT_RIGHT = 2; // 0x2
+    field public static final int KEYCODE_SPACE = 62; // 0x3e
+    field public static final int KEYCODE_STAR = 17; // 0x11
+    field public static final int KEYCODE_STB_INPUT = 180; // 0xb4
+    field public static final int KEYCODE_STB_POWER = 179; // 0xb3
+    field public static final int KEYCODE_SWITCH_CHARSET = 95; // 0x5f
+    field public static final int KEYCODE_SYM = 63; // 0x3f
+    field public static final int KEYCODE_SYSRQ = 120; // 0x78
+    field public static final int KEYCODE_T = 48; // 0x30
+    field public static final int KEYCODE_TAB = 61; // 0x3d
+    field public static final int KEYCODE_TV = 170; // 0xaa
+    field public static final int KEYCODE_TV_INPUT = 178; // 0xb2
+    field public static final int KEYCODE_TV_POWER = 177; // 0xb1
+    field public static final int KEYCODE_U = 49; // 0x31
+    field public static final int KEYCODE_UNKNOWN = 0; // 0x0
+    field public static final int KEYCODE_V = 50; // 0x32
+    field public static final int KEYCODE_VOLUME_DOWN = 25; // 0x19
+    field public static final int KEYCODE_VOLUME_MUTE = 164; // 0xa4
+    field public static final int KEYCODE_VOLUME_UP = 24; // 0x18
+    field public static final int KEYCODE_W = 51; // 0x33
+    field public static final int KEYCODE_WINDOW = 171; // 0xab
+    field public static final int KEYCODE_X = 52; // 0x34
+    field public static final int KEYCODE_Y = 53; // 0x35
+    field public static final int KEYCODE_YEN = 216; // 0xd8
+    field public static final int KEYCODE_Z = 54; // 0x36
+    field public static final int KEYCODE_ZENKAKU_HANKAKU = 211; // 0xd3
+    field public static final int KEYCODE_ZOOM_IN = 168; // 0xa8
+    field public static final int KEYCODE_ZOOM_OUT = 169; // 0xa9
+    field public static final deprecated int MAX_KEYCODE = 84; // 0x54
+    field public static final int META_ALT_LEFT_ON = 16; // 0x10
+    field public static final int META_ALT_MASK = 50; // 0x32
+    field public static final int META_ALT_ON = 2; // 0x2
+    field public static final int META_ALT_RIGHT_ON = 32; // 0x20
+    field public static final int META_CAPS_LOCK_ON = 1048576; // 0x100000
+    field public static final int META_CTRL_LEFT_ON = 8192; // 0x2000
+    field public static final int META_CTRL_MASK = 28672; // 0x7000
+    field public static final int META_CTRL_ON = 4096; // 0x1000
+    field public static final int META_CTRL_RIGHT_ON = 16384; // 0x4000
+    field public static final int META_FUNCTION_ON = 8; // 0x8
+    field public static final int META_META_LEFT_ON = 131072; // 0x20000
+    field public static final int META_META_MASK = 458752; // 0x70000
+    field public static final int META_META_ON = 65536; // 0x10000
+    field public static final int META_META_RIGHT_ON = 262144; // 0x40000
+    field public static final int META_NUM_LOCK_ON = 2097152; // 0x200000
+    field public static final int META_SCROLL_LOCK_ON = 4194304; // 0x400000
+    field public static final int META_SHIFT_LEFT_ON = 64; // 0x40
+    field public static final int META_SHIFT_MASK = 193; // 0xc1
+    field public static final int META_SHIFT_ON = 1; // 0x1
+    field public static final int META_SHIFT_RIGHT_ON = 128; // 0x80
+    field public static final int META_SYM_ON = 4; // 0x4
+  }
+
+  public static abstract interface KeyEvent.Callback {
+    method public abstract boolean onKeyDown(int, android.view.KeyEvent);
+    method public abstract boolean onKeyLongPress(int, android.view.KeyEvent);
+    method public abstract boolean onKeyMultiple(int, int, android.view.KeyEvent);
+    method public abstract boolean onKeyUp(int, android.view.KeyEvent);
+  }
+
+  public static class KeyEvent.DispatcherState {
+    ctor public KeyEvent.DispatcherState();
+    method public void handleUpEvent(android.view.KeyEvent);
+    method public boolean isTracking(android.view.KeyEvent);
+    method public void performedLongPress(android.view.KeyEvent);
+    method public void reset();
+    method public void reset(java.lang.Object);
+    method public void startTracking(android.view.KeyEvent, java.lang.Object);
+  }
+
+  public abstract class LayoutInflater {
+    ctor protected LayoutInflater(android.content.Context);
+    ctor protected LayoutInflater(android.view.LayoutInflater, android.content.Context);
+    method public abstract android.view.LayoutInflater cloneInContext(android.content.Context);
+    method public final android.view.View createView(java.lang.String, java.lang.String, android.util.AttributeSet) throws java.lang.ClassNotFoundException, android.view.InflateException;
+    method public static android.view.LayoutInflater from(android.content.Context);
+    method public android.content.Context getContext();
+    method public final android.view.LayoutInflater.Factory getFactory();
+    method public final android.view.LayoutInflater.Factory2 getFactory2();
+    method public android.view.LayoutInflater.Filter getFilter();
+    method public android.view.View inflate(int, android.view.ViewGroup);
+    method public android.view.View inflate(org.xmlpull.v1.XmlPullParser, android.view.ViewGroup);
+    method public android.view.View inflate(int, android.view.ViewGroup, boolean);
+    method public android.view.View inflate(org.xmlpull.v1.XmlPullParser, android.view.ViewGroup, boolean);
+    method protected android.view.View onCreateView(java.lang.String, android.util.AttributeSet) throws java.lang.ClassNotFoundException;
+    method protected android.view.View onCreateView(android.view.View, java.lang.String, android.util.AttributeSet) throws java.lang.ClassNotFoundException;
+    method public void setFactory(android.view.LayoutInflater.Factory);
+    method public void setFactory2(android.view.LayoutInflater.Factory2);
+    method public void setFilter(android.view.LayoutInflater.Filter);
+  }
+
+  public static abstract interface LayoutInflater.Factory {
+    method public abstract android.view.View onCreateView(java.lang.String, android.content.Context, android.util.AttributeSet);
+  }
+
+  public static abstract interface LayoutInflater.Factory2 implements android.view.LayoutInflater.Factory {
+    method public abstract android.view.View onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet);
+  }
+
+  public static abstract interface LayoutInflater.Filter {
+    method public abstract boolean onLoadClass(java.lang.Class);
+  }
+
+  public abstract interface Menu {
+    method public abstract android.view.MenuItem add(java.lang.CharSequence);
+    method public abstract android.view.MenuItem add(int);
+    method public abstract android.view.MenuItem add(int, int, int, java.lang.CharSequence);
+    method public abstract android.view.MenuItem add(int, int, int, int);
+    method public abstract int addIntentOptions(int, int, int, android.content.ComponentName, android.content.Intent[], android.content.Intent, int, android.view.MenuItem[]);
+    method public abstract android.view.SubMenu addSubMenu(java.lang.CharSequence);
+    method public abstract android.view.SubMenu addSubMenu(int);
+    method public abstract android.view.SubMenu addSubMenu(int, int, int, java.lang.CharSequence);
+    method public abstract android.view.SubMenu addSubMenu(int, int, int, int);
+    method public abstract void clear();
+    method public abstract void close();
+    method public abstract android.view.MenuItem findItem(int);
+    method public abstract android.view.MenuItem getItem(int);
+    method public abstract boolean hasVisibleItems();
+    method public abstract boolean isShortcutKey(int, android.view.KeyEvent);
+    method public abstract boolean performIdentifierAction(int, int);
+    method public abstract boolean performShortcut(int, android.view.KeyEvent, int);
+    method public abstract void removeGroup(int);
+    method public abstract void removeItem(int);
+    method public abstract void setGroupCheckable(int, boolean, boolean);
+    method public abstract void setGroupEnabled(int, boolean);
+    method public abstract void setGroupVisible(int, boolean);
+    method public abstract void setQwertyMode(boolean);
+    method public abstract int size();
+    field public static final int CATEGORY_ALTERNATIVE = 262144; // 0x40000
+    field public static final int CATEGORY_CONTAINER = 65536; // 0x10000
+    field public static final int CATEGORY_SECONDARY = 196608; // 0x30000
+    field public static final int CATEGORY_SYSTEM = 131072; // 0x20000
+    field public static final int FIRST = 1; // 0x1
+    field public static final int FLAG_ALWAYS_PERFORM_CLOSE = 2; // 0x2
+    field public static final int FLAG_APPEND_TO_GROUP = 1; // 0x1
+    field public static final int FLAG_PERFORM_NO_CLOSE = 1; // 0x1
+    field public static final int NONE = 0; // 0x0
+  }
+
+  public class MenuInflater {
+    ctor public MenuInflater(android.content.Context);
+    method public void inflate(int, android.view.Menu);
+  }
+
+  public abstract interface MenuItem {
+    method public abstract boolean collapseActionView();
+    method public abstract boolean expandActionView();
+    method public abstract android.view.ActionProvider getActionProvider();
+    method public abstract android.view.View getActionView();
+    method public abstract char getAlphabeticShortcut();
+    method public abstract int getGroupId();
+    method public abstract android.graphics.drawable.Drawable getIcon();
+    method public abstract android.content.Intent getIntent();
+    method public abstract int getItemId();
+    method public abstract android.view.ContextMenu.ContextMenuInfo getMenuInfo();
+    method public abstract char getNumericShortcut();
+    method public abstract int getOrder();
+    method public abstract android.view.SubMenu getSubMenu();
+    method public abstract java.lang.CharSequence getTitle();
+    method public abstract java.lang.CharSequence getTitleCondensed();
+    method public abstract boolean hasSubMenu();
+    method public abstract boolean isActionViewExpanded();
+    method public abstract boolean isCheckable();
+    method public abstract boolean isChecked();
+    method public abstract boolean isEnabled();
+    method public abstract boolean isVisible();
+    method public abstract android.view.MenuItem setActionProvider(android.view.ActionProvider);
+    method public abstract android.view.MenuItem setActionView(android.view.View);
+    method public abstract android.view.MenuItem setActionView(int);
+    method public abstract android.view.MenuItem setAlphabeticShortcut(char);
+    method public abstract android.view.MenuItem setCheckable(boolean);
+    method public abstract android.view.MenuItem setChecked(boolean);
+    method public abstract android.view.MenuItem setEnabled(boolean);
+    method public abstract android.view.MenuItem setIcon(android.graphics.drawable.Drawable);
+    method public abstract android.view.MenuItem setIcon(int);
+    method public abstract android.view.MenuItem setIntent(android.content.Intent);
+    method public abstract android.view.MenuItem setNumericShortcut(char);
+    method public abstract android.view.MenuItem setOnActionExpandListener(android.view.MenuItem.OnActionExpandListener);
+    method public abstract android.view.MenuItem setOnMenuItemClickListener(android.view.MenuItem.OnMenuItemClickListener);
+    method public abstract android.view.MenuItem setShortcut(char, char);
+    method public abstract void setShowAsAction(int);
+    method public abstract android.view.MenuItem setShowAsActionFlags(int);
+    method public abstract android.view.MenuItem setTitle(java.lang.CharSequence);
+    method public abstract android.view.MenuItem setTitle(int);
+    method public abstract android.view.MenuItem setTitleCondensed(java.lang.CharSequence);
+    method public abstract android.view.MenuItem setVisible(boolean);
+    field public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2
+    field public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8
+    field public static final int SHOW_AS_ACTION_IF_ROOM = 1; // 0x1
+    field public static final int SHOW_AS_ACTION_NEVER = 0; // 0x0
+    field public static final int SHOW_AS_ACTION_WITH_TEXT = 4; // 0x4
+  }
+
+  public static abstract interface MenuItem.OnActionExpandListener {
+    method public abstract boolean onMenuItemActionCollapse(android.view.MenuItem);
+    method public abstract boolean onMenuItemActionExpand(android.view.MenuItem);
+  }
+
+  public static abstract interface MenuItem.OnMenuItemClickListener {
+    method public abstract boolean onMenuItemClick(android.view.MenuItem);
+  }
+
+  public final class MotionEvent extends android.view.InputEvent implements android.os.Parcelable {
+    method public final void addBatch(long, float, float, float, float, int);
+    method public final void addBatch(long, android.view.MotionEvent.PointerCoords[], int);
+    method public static int axisFromString(java.lang.String);
+    method public static java.lang.String axisToString(int);
+    method public final int findPointerIndex(int);
+    method public final int getAction();
+    method public final int getActionIndex();
+    method public final int getActionMasked();
+    method public final float getAxisValue(int);
+    method public final float getAxisValue(int, int);
+    method public final int getButtonState();
+    method public final int getDeviceId();
+    method public final long getDownTime();
+    method public final int getEdgeFlags();
+    method public final long getEventTime();
+    method public final int getFlags();
+    method public final float getHistoricalAxisValue(int, int);
+    method public final float getHistoricalAxisValue(int, int, int);
+    method public final long getHistoricalEventTime(int);
+    method public final float getHistoricalOrientation(int);
+    method public final float getHistoricalOrientation(int, int);
+    method public final void getHistoricalPointerCoords(int, int, android.view.MotionEvent.PointerCoords);
+    method public final float getHistoricalPressure(int);
+    method public final float getHistoricalPressure(int, int);
+    method public final float getHistoricalSize(int);
+    method public final float getHistoricalSize(int, int);
+    method public final float getHistoricalToolMajor(int);
+    method public final float getHistoricalToolMajor(int, int);
+    method public final float getHistoricalToolMinor(int);
+    method public final float getHistoricalToolMinor(int, int);
+    method public final float getHistoricalTouchMajor(int);
+    method public final float getHistoricalTouchMajor(int, int);
+    method public final float getHistoricalTouchMinor(int);
+    method public final float getHistoricalTouchMinor(int, int);
+    method public final float getHistoricalX(int);
+    method public final float getHistoricalX(int, int);
+    method public final float getHistoricalY(int);
+    method public final float getHistoricalY(int, int);
+    method public final int getHistorySize();
+    method public final int getMetaState();
+    method public final float getOrientation();
+    method public final float getOrientation(int);
+    method public final void getPointerCoords(int, android.view.MotionEvent.PointerCoords);
+    method public final int getPointerCount();
+    method public final int getPointerId(int);
+    method public final void getPointerProperties(int, android.view.MotionEvent.PointerProperties);
+    method public final float getPressure();
+    method public final float getPressure(int);
+    method public final float getRawX();
+    method public final float getRawY();
+    method public final float getSize();
+    method public final float getSize(int);
+    method public final int getSource();
+    method public final float getToolMajor();
+    method public final float getToolMajor(int);
+    method public final float getToolMinor();
+    method public final float getToolMinor(int);
+    method public final int getToolType(int);
+    method public final float getTouchMajor();
+    method public final float getTouchMajor(int);
+    method public final float getTouchMinor();
+    method public final float getTouchMinor(int);
+    method public final float getX();
+    method public final float getX(int);
+    method public final float getXPrecision();
+    method public final float getY();
+    method public final float getY(int);
+    method public final float getYPrecision();
+    method public static android.view.MotionEvent obtain(long, long, int, int, android.view.MotionEvent.PointerProperties[], android.view.MotionEvent.PointerCoords[], int, int, float, float, int, int, int, int);
+    method public static deprecated android.view.MotionEvent obtain(long, long, int, int, int[], android.view.MotionEvent.PointerCoords[], int, float, float, int, int, int, int);
+    method public static android.view.MotionEvent obtain(long, long, int, float, float, float, float, int, float, float, int, int);
+    method public static deprecated android.view.MotionEvent obtain(long, long, int, int, float, float, float, float, int, float, float, int, int);
+    method public static android.view.MotionEvent obtain(long, long, int, float, float, int);
+    method public static android.view.MotionEvent obtain(android.view.MotionEvent);
+    method public static android.view.MotionEvent obtainNoHistory(android.view.MotionEvent);
+    method public final void offsetLocation(float, float);
+    method public final void recycle();
+    method public final void setAction(int);
+    method public final void setEdgeFlags(int);
+    method public final void setLocation(float, float);
+    method public final void setSource(int);
+    method public final void transform(android.graphics.Matrix);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ACTION_CANCEL = 3; // 0x3
+    field public static final int ACTION_DOWN = 0; // 0x0
+    field public static final int ACTION_HOVER_ENTER = 9; // 0x9
+    field public static final int ACTION_HOVER_EXIT = 10; // 0xa
+    field public static final int ACTION_HOVER_MOVE = 7; // 0x7
+    field public static final int ACTION_MASK = 255; // 0xff
+    field public static final int ACTION_MOVE = 2; // 0x2
+    field public static final int ACTION_OUTSIDE = 4; // 0x4
+    field public static final deprecated int ACTION_POINTER_1_DOWN = 5; // 0x5
+    field public static final deprecated int ACTION_POINTER_1_UP = 6; // 0x6
+    field public static final deprecated int ACTION_POINTER_2_DOWN = 261; // 0x105
+    field public static final deprecated int ACTION_POINTER_2_UP = 262; // 0x106
+    field public static final deprecated int ACTION_POINTER_3_DOWN = 517; // 0x205
+    field public static final deprecated int ACTION_POINTER_3_UP = 518; // 0x206
+    field public static final int ACTION_POINTER_DOWN = 5; // 0x5
+    field public static final deprecated int ACTION_POINTER_ID_MASK = 65280; // 0xff00
+    field public static final deprecated int ACTION_POINTER_ID_SHIFT = 8; // 0x8
+    field public static final int ACTION_POINTER_INDEX_MASK = 65280; // 0xff00
+    field public static final int ACTION_POINTER_INDEX_SHIFT = 8; // 0x8
+    field public static final int ACTION_POINTER_UP = 6; // 0x6
+    field public static final int ACTION_SCROLL = 8; // 0x8
+    field public static final int ACTION_UP = 1; // 0x1
+    field public static final int AXIS_BRAKE = 23; // 0x17
+    field public static final int AXIS_DISTANCE = 24; // 0x18
+    field public static final int AXIS_GAS = 22; // 0x16
+    field public static final int AXIS_GENERIC_1 = 32; // 0x20
+    field public static final int AXIS_GENERIC_10 = 41; // 0x29
+    field public static final int AXIS_GENERIC_11 = 42; // 0x2a
+    field public static final int AXIS_GENERIC_12 = 43; // 0x2b
+    field public static final int AXIS_GENERIC_13 = 44; // 0x2c
+    field public static final int AXIS_GENERIC_14 = 45; // 0x2d
+    field public static final int AXIS_GENERIC_15 = 46; // 0x2e
+    field public static final int AXIS_GENERIC_16 = 47; // 0x2f
+    field public static final int AXIS_GENERIC_2 = 33; // 0x21
+    field public static final int AXIS_GENERIC_3 = 34; // 0x22
+    field public static final int AXIS_GENERIC_4 = 35; // 0x23
+    field public static final int AXIS_GENERIC_5 = 36; // 0x24
+    field public static final int AXIS_GENERIC_6 = 37; // 0x25
+    field public static final int AXIS_GENERIC_7 = 38; // 0x26
+    field public static final int AXIS_GENERIC_8 = 39; // 0x27
+    field public static final int AXIS_GENERIC_9 = 40; // 0x28
+    field public static final int AXIS_HAT_X = 15; // 0xf
+    field public static final int AXIS_HAT_Y = 16; // 0x10
+    field public static final int AXIS_HSCROLL = 10; // 0xa
+    field public static final int AXIS_LTRIGGER = 17; // 0x11
+    field public static final int AXIS_ORIENTATION = 8; // 0x8
+    field public static final int AXIS_PRESSURE = 2; // 0x2
+    field public static final int AXIS_RTRIGGER = 18; // 0x12
+    field public static final int AXIS_RUDDER = 20; // 0x14
+    field public static final int AXIS_RX = 12; // 0xc
+    field public static final int AXIS_RY = 13; // 0xd
+    field public static final int AXIS_RZ = 14; // 0xe
+    field public static final int AXIS_SIZE = 3; // 0x3
+    field public static final int AXIS_THROTTLE = 19; // 0x13
+    field public static final int AXIS_TILT = 25; // 0x19
+    field public static final int AXIS_TOOL_MAJOR = 6; // 0x6
+    field public static final int AXIS_TOOL_MINOR = 7; // 0x7
+    field public static final int AXIS_TOUCH_MAJOR = 4; // 0x4
+    field public static final int AXIS_TOUCH_MINOR = 5; // 0x5
+    field public static final int AXIS_VSCROLL = 9; // 0x9
+    field public static final int AXIS_WHEEL = 21; // 0x15
+    field public static final int AXIS_X = 0; // 0x0
+    field public static final int AXIS_Y = 1; // 0x1
+    field public static final int AXIS_Z = 11; // 0xb
+    field public static final int BUTTON_BACK = 8; // 0x8
+    field public static final int BUTTON_FORWARD = 16; // 0x10
+    field public static final int BUTTON_PRIMARY = 1; // 0x1
+    field public static final int BUTTON_SECONDARY = 2; // 0x2
+    field public static final int BUTTON_TERTIARY = 4; // 0x4
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int EDGE_BOTTOM = 2; // 0x2
+    field public static final int EDGE_LEFT = 4; // 0x4
+    field public static final int EDGE_RIGHT = 8; // 0x8
+    field public static final int EDGE_TOP = 1; // 0x1
+    field public static final int FLAG_WINDOW_IS_OBSCURED = 1; // 0x1
+    field public static final int INVALID_POINTER_ID = -1; // 0xffffffff
+    field public static final int TOOL_TYPE_ERASER = 4; // 0x4
+    field public static final int TOOL_TYPE_FINGER = 1; // 0x1
+    field public static final int TOOL_TYPE_MOUSE = 3; // 0x3
+    field public static final int TOOL_TYPE_STYLUS = 2; // 0x2
+    field public static final int TOOL_TYPE_UNKNOWN = 0; // 0x0
+  }
+
+  public static final class MotionEvent.PointerCoords {
+    ctor public MotionEvent.PointerCoords();
+    ctor public MotionEvent.PointerCoords(android.view.MotionEvent.PointerCoords);
+    method public void clear();
+    method public void copyFrom(android.view.MotionEvent.PointerCoords);
+    method public float getAxisValue(int);
+    method public void setAxisValue(int, float);
+    field public float orientation;
+    field public float pressure;
+    field public float size;
+    field public float toolMajor;
+    field public float toolMinor;
+    field public float touchMajor;
+    field public float touchMinor;
+    field public float x;
+    field public float y;
+  }
+
+  public static final class MotionEvent.PointerProperties {
+    ctor public MotionEvent.PointerProperties();
+    ctor public MotionEvent.PointerProperties(android.view.MotionEvent.PointerProperties);
+    method public void clear();
+    method public void copyFrom(android.view.MotionEvent.PointerProperties);
+    field public int id;
+    field public int toolType;
+  }
+
+  public abstract class OrientationEventListener {
+    ctor public OrientationEventListener(android.content.Context);
+    ctor public OrientationEventListener(android.content.Context, int);
+    method public boolean canDetectOrientation();
+    method public void disable();
+    method public void enable();
+    method public abstract void onOrientationChanged(int);
+    field public static final int ORIENTATION_UNKNOWN = -1; // 0xffffffff
+  }
+
+  public abstract deprecated class OrientationListener implements android.hardware.SensorListener {
+    ctor public OrientationListener(android.content.Context);
+    ctor public OrientationListener(android.content.Context, int);
+    method public void disable();
+    method public void enable();
+    method public void onAccuracyChanged(int, int);
+    method public abstract void onOrientationChanged(int);
+    method public void onSensorChanged(int, float[]);
+    field public static final int ORIENTATION_UNKNOWN = -1; // 0xffffffff
+  }
+
+  public class ScaleGestureDetector {
+    ctor public ScaleGestureDetector(android.content.Context, android.view.ScaleGestureDetector.OnScaleGestureListener);
+    method public float getCurrentSpan();
+    method public float getCurrentSpanX();
+    method public float getCurrentSpanY();
+    method public long getEventTime();
+    method public float getFocusX();
+    method public float getFocusY();
+    method public float getPreviousSpan();
+    method public float getPreviousSpanX();
+    method public float getPreviousSpanY();
+    method public float getScaleFactor();
+    method public long getTimeDelta();
+    method public boolean isInProgress();
+    method public boolean onTouchEvent(android.view.MotionEvent);
+  }
+
+  public static abstract interface ScaleGestureDetector.OnScaleGestureListener {
+    method public abstract boolean onScale(android.view.ScaleGestureDetector);
+    method public abstract boolean onScaleBegin(android.view.ScaleGestureDetector);
+    method public abstract void onScaleEnd(android.view.ScaleGestureDetector);
+  }
+
+  public static class ScaleGestureDetector.SimpleOnScaleGestureListener implements android.view.ScaleGestureDetector.OnScaleGestureListener {
+    ctor public ScaleGestureDetector.SimpleOnScaleGestureListener();
+    method public boolean onScale(android.view.ScaleGestureDetector);
+    method public boolean onScaleBegin(android.view.ScaleGestureDetector);
+    method public void onScaleEnd(android.view.ScaleGestureDetector);
+  }
+
+  public class SoundEffectConstants {
+    method public static int getContantForFocusDirection(int);
+    field public static final int CLICK = 0; // 0x0
+    field public static final int NAVIGATION_DOWN = 4; // 0x4
+    field public static final int NAVIGATION_LEFT = 1; // 0x1
+    field public static final int NAVIGATION_RIGHT = 3; // 0x3
+    field public static final int NAVIGATION_UP = 2; // 0x2
+  }
+
+  public abstract interface SubMenu implements android.view.Menu {
+    method public abstract void clearHeader();
+    method public abstract android.view.MenuItem getItem();
+    method public abstract android.view.SubMenu setHeaderIcon(int);
+    method public abstract android.view.SubMenu setHeaderIcon(android.graphics.drawable.Drawable);
+    method public abstract android.view.SubMenu setHeaderTitle(int);
+    method public abstract android.view.SubMenu setHeaderTitle(java.lang.CharSequence);
+    method public abstract android.view.SubMenu setHeaderView(android.view.View);
+    method public abstract android.view.SubMenu setIcon(int);
+    method public abstract android.view.SubMenu setIcon(android.graphics.drawable.Drawable);
+  }
+
+  public class Surface implements android.os.Parcelable {
+    ctor public Surface(android.graphics.SurfaceTexture);
+    method public int describeContents();
+    method public boolean isValid();
+    method public android.graphics.Canvas lockCanvas(android.graphics.Rect) throws java.lang.IllegalArgumentException, android.view.Surface.OutOfResourcesException;
+    method public void readFromParcel(android.os.Parcel);
+    method public void release();
+    method public deprecated void unlockCanvas(android.graphics.Canvas);
+    method public void unlockCanvasAndPost(android.graphics.Canvas);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int ROTATION_0 = 0; // 0x0
+    field public static final int ROTATION_180 = 2; // 0x2
+    field public static final int ROTATION_270 = 3; // 0x3
+    field public static final int ROTATION_90 = 1; // 0x1
+  }
+
+  public static class Surface.OutOfResourcesException extends java.lang.Exception {
+    ctor public Surface.OutOfResourcesException();
+    ctor public Surface.OutOfResourcesException(java.lang.String);
+  }
+
+  public abstract interface SurfaceHolder {
+    method public abstract void addCallback(android.view.SurfaceHolder.Callback);
+    method public abstract android.view.Surface getSurface();
+    method public abstract android.graphics.Rect getSurfaceFrame();
+    method public abstract boolean isCreating();
+    method public abstract android.graphics.Canvas lockCanvas();
+    method public abstract android.graphics.Canvas lockCanvas(android.graphics.Rect);
+    method public abstract void removeCallback(android.view.SurfaceHolder.Callback);
+    method public abstract void setFixedSize(int, int);
+    method public abstract void setFormat(int);
+    method public abstract void setKeepScreenOn(boolean);
+    method public abstract void setSizeFromLayout();
+    method public abstract deprecated void setType(int);
+    method public abstract void unlockCanvasAndPost(android.graphics.Canvas);
+    field public static final deprecated int SURFACE_TYPE_GPU = 2; // 0x2
+    field public static final deprecated int SURFACE_TYPE_HARDWARE = 1; // 0x1
+    field public static final deprecated int SURFACE_TYPE_NORMAL = 0; // 0x0
+    field public static final deprecated int SURFACE_TYPE_PUSH_BUFFERS = 3; // 0x3
+  }
+
+  public static class SurfaceHolder.BadSurfaceTypeException extends java.lang.RuntimeException {
+    ctor public SurfaceHolder.BadSurfaceTypeException();
+    ctor public SurfaceHolder.BadSurfaceTypeException(java.lang.String);
+  }
+
+  public static abstract interface SurfaceHolder.Callback {
+    method public abstract void surfaceChanged(android.view.SurfaceHolder, int, int, int);
+    method public abstract void surfaceCreated(android.view.SurfaceHolder);
+    method public abstract void surfaceDestroyed(android.view.SurfaceHolder);
+  }
+
+  public static abstract interface SurfaceHolder.Callback2 implements android.view.SurfaceHolder.Callback {
+    method public abstract void surfaceRedrawNeeded(android.view.SurfaceHolder);
+  }
+
+  public class SurfaceView extends android.view.View {
+    ctor public SurfaceView(android.content.Context);
+    ctor public SurfaceView(android.content.Context, android.util.AttributeSet);
+    ctor public SurfaceView(android.content.Context, android.util.AttributeSet, int);
+    method public boolean gatherTransparentRegion(android.graphics.Region);
+    method public android.view.SurfaceHolder getHolder();
+    method public void setSecure(boolean);
+    method public void setZOrderMediaOverlay(boolean);
+    method public void setZOrderOnTop(boolean);
+  }
+
+  public class TextureView extends android.view.View {
+    ctor public TextureView(android.content.Context);
+    ctor public TextureView(android.content.Context, android.util.AttributeSet);
+    ctor public TextureView(android.content.Context, android.util.AttributeSet, int);
+    method public final void draw(android.graphics.Canvas);
+    method public android.graphics.Bitmap getBitmap();
+    method public android.graphics.Bitmap getBitmap(int, int);
+    method public android.graphics.Bitmap getBitmap(android.graphics.Bitmap);
+    method public android.graphics.SurfaceTexture getSurfaceTexture();
+    method public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener();
+    method public android.graphics.Matrix getTransform(android.graphics.Matrix);
+    method public boolean isAvailable();
+    method public android.graphics.Canvas lockCanvas();
+    method public android.graphics.Canvas lockCanvas(android.graphics.Rect);
+    method protected final void onDraw(android.graphics.Canvas);
+    method public void setOpaque(boolean);
+    method public void setSurfaceTexture(android.graphics.SurfaceTexture);
+    method public void setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener);
+    method public void setTransform(android.graphics.Matrix);
+    method public void unlockCanvasAndPost(android.graphics.Canvas);
+  }
+
+  public static abstract interface TextureView.SurfaceTextureListener {
+    method public abstract void onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int);
+    method public abstract boolean onSurfaceTextureDestroyed(android.graphics.SurfaceTexture);
+    method public abstract void onSurfaceTextureSizeChanged(android.graphics.SurfaceTexture, int, int);
+    method public abstract void onSurfaceTextureUpdated(android.graphics.SurfaceTexture);
+  }
+
+  public class TouchDelegate {
+    ctor public TouchDelegate(android.graphics.Rect, android.view.View);
+    method public boolean onTouchEvent(android.view.MotionEvent);
+    field public static final int ABOVE = 1; // 0x1
+    field public static final int BELOW = 2; // 0x2
+    field public static final int TO_LEFT = 4; // 0x4
+    field public static final int TO_RIGHT = 8; // 0x8
+  }
+
+  public final class VelocityTracker {
+    method public void addMovement(android.view.MotionEvent);
+    method public void clear();
+    method public void computeCurrentVelocity(int);
+    method public void computeCurrentVelocity(int, float);
+    method public float getXVelocity();
+    method public float getXVelocity(int);
+    method public float getYVelocity();
+    method public float getYVelocity(int);
+    method public static android.view.VelocityTracker obtain();
+    method public void recycle();
+  }
+
+  public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
+    ctor public View(android.content.Context);
+    ctor public View(android.content.Context, android.util.AttributeSet);
+    ctor public View(android.content.Context, android.util.AttributeSet, int);
+    method public void addChildrenForAccessibility(java.util.ArrayList<android.view.View>);
+    method public void addFocusables(java.util.ArrayList<android.view.View>, int);
+    method public void addFocusables(java.util.ArrayList<android.view.View>, int, int);
+    method public void addOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
+    method public void addOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
+    method public void addTouchables(java.util.ArrayList<android.view.View>);
+    method public android.view.ViewPropertyAnimator animate();
+    method public void announceForAccessibility(java.lang.CharSequence);
+    method protected boolean awakenScrollBars();
+    method protected boolean awakenScrollBars(int);
+    method protected boolean awakenScrollBars(int, boolean);
+    method public void bringToFront();
+    method public void buildDrawingCache();
+    method public void buildDrawingCache(boolean);
+    method public void buildLayer();
+    method public boolean callOnClick();
+    method public boolean canScrollHorizontally(int);
+    method public boolean canScrollVertically(int);
+    method public void cancelLongPress();
+    method public boolean checkInputConnectionProxy(android.view.View);
+    method public void clearAnimation();
+    method public void clearFocus();
+    method public static int combineMeasuredStates(int, int);
+    method protected int computeHorizontalScrollExtent();
+    method protected int computeHorizontalScrollOffset();
+    method protected int computeHorizontalScrollRange();
+    method public void computeScroll();
+    method protected int computeVerticalScrollExtent();
+    method protected int computeVerticalScrollOffset();
+    method protected int computeVerticalScrollRange();
+    method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo();
+    method public void createContextMenu(android.view.ContextMenu);
+    method public void destroyDrawingCache();
+    method public void dispatchConfigurationChanged(android.content.res.Configuration);
+    method public void dispatchDisplayHint(int);
+    method public boolean dispatchDragEvent(android.view.DragEvent);
+    method protected void dispatchDraw(android.graphics.Canvas);
+    method protected boolean dispatchGenericFocusedEvent(android.view.MotionEvent);
+    method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
+    method protected boolean dispatchGenericPointerEvent(android.view.MotionEvent);
+    method protected boolean dispatchHoverEvent(android.view.MotionEvent);
+    method public boolean dispatchKeyEvent(android.view.KeyEvent);
+    method public boolean dispatchKeyEventPreIme(android.view.KeyEvent);
+    method public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
+    method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+    method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
+    method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
+    method protected void dispatchSetActivated(boolean);
+    method protected void dispatchSetPressed(boolean);
+    method protected void dispatchSetSelected(boolean);
+    method public void dispatchSystemUiVisibilityChanged(int);
+    method public boolean dispatchTouchEvent(android.view.MotionEvent);
+    method public boolean dispatchTrackballEvent(android.view.MotionEvent);
+    method public boolean dispatchUnhandledMove(android.view.View, int);
+    method protected void dispatchVisibilityChanged(android.view.View, int);
+    method public void dispatchWindowFocusChanged(boolean);
+    method public void dispatchWindowSystemUiVisiblityChanged(int);
+    method public void dispatchWindowVisibilityChanged(int);
+    method public void draw(android.graphics.Canvas);
+    method protected void drawableStateChanged();
+    method public android.view.View findFocus();
+    method public final android.view.View findViewById(int);
+    method public final android.view.View findViewWithTag(java.lang.Object);
+    method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
+    method protected boolean fitSystemWindows(android.graphics.Rect);
+    method public android.view.View focusSearch(int);
+    method public void forceLayout();
+    method public static int generateViewId();
+    method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider();
+    method public float getAlpha();
+    method public android.view.animation.Animation getAnimation();
+    method public android.os.IBinder getApplicationWindowToken();
+    method public android.graphics.drawable.Drawable getBackground();
+    method public int getBaseline();
+    method public final int getBottom();
+    method protected float getBottomFadingEdgeStrength();
+    method protected int getBottomPaddingOffset();
+    method public float getCameraDistance();
+    method public java.lang.CharSequence getContentDescription();
+    method public final android.content.Context getContext();
+    method protected android.view.ContextMenu.ContextMenuInfo getContextMenuInfo();
+    method public static int getDefaultSize(int, int);
+    method public android.view.Display getDisplay();
+    method public final int[] getDrawableState();
+    method public android.graphics.Bitmap getDrawingCache();
+    method public android.graphics.Bitmap getDrawingCache(boolean);
+    method public int getDrawingCacheBackgroundColor();
+    method public int getDrawingCacheQuality();
+    method public void getDrawingRect(android.graphics.Rect);
+    method public long getDrawingTime();
+    method public boolean getFilterTouchesWhenObscured();
+    method public boolean getFitsSystemWindows();
+    method public java.util.ArrayList<android.view.View> getFocusables(int);
+    method public void getFocusedRect(android.graphics.Rect);
+    method public boolean getGlobalVisibleRect(android.graphics.Rect, android.graphics.Point);
+    method public final boolean getGlobalVisibleRect(android.graphics.Rect);
+    method public android.os.Handler getHandler();
+    method public final int getHeight();
+    method public void getHitRect(android.graphics.Rect);
+    method public int getHorizontalFadingEdgeLength();
+    method protected int getHorizontalScrollbarHeight();
+    method public int getId();
+    method public int getImportantForAccessibility();
+    method public boolean getKeepScreenOn();
+    method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
+    method public int getLabelFor();
+    method public int getLayerType();
+    method public int getLayoutDirection();
+    method public android.view.ViewGroup.LayoutParams getLayoutParams();
+    method public final int getLeft();
+    method protected float getLeftFadingEdgeStrength();
+    method protected int getLeftPaddingOffset();
+    method public final boolean getLocalVisibleRect(android.graphics.Rect);
+    method public void getLocationInWindow(int[]);
+    method public void getLocationOnScreen(int[]);
+    method public android.graphics.Matrix getMatrix();
+    method public final int getMeasuredHeight();
+    method public final int getMeasuredHeightAndState();
+    method public final int getMeasuredState();
+    method public final int getMeasuredWidth();
+    method public final int getMeasuredWidthAndState();
+    method public int getMinimumHeight();
+    method public int getMinimumWidth();
+    method public int getNextFocusDownId();
+    method public int getNextFocusForwardId();
+    method public int getNextFocusLeftId();
+    method public int getNextFocusRightId();
+    method public int getNextFocusUpId();
+    method public android.view.View.OnFocusChangeListener getOnFocusChangeListener();
+    method public int getOverScrollMode();
+    method public int getPaddingBottom();
+    method public int getPaddingEnd();
+    method public int getPaddingLeft();
+    method public int getPaddingRight();
+    method public int getPaddingStart();
+    method public int getPaddingTop();
+    method public final android.view.ViewParent getParent();
+    method public android.view.ViewParent getParentForAccessibility();
+    method public float getPivotX();
+    method public float getPivotY();
+    method public android.content.res.Resources getResources();
+    method public final int getRight();
+    method protected float getRightFadingEdgeStrength();
+    method protected int getRightPaddingOffset();
+    method public android.view.View getRootView();
+    method public float getRotation();
+    method public float getRotationX();
+    method public float getRotationY();
+    method public float getScaleX();
+    method public float getScaleY();
+    method public int getScrollBarDefaultDelayBeforeFade();
+    method public int getScrollBarFadeDuration();
+    method public int getScrollBarSize();
+    method public int getScrollBarStyle();
+    method public final int getScrollX();
+    method public final int getScrollY();
+    method public int getSolidColor();
+    method protected int getSuggestedMinimumHeight();
+    method protected int getSuggestedMinimumWidth();
+    method public int getSystemUiVisibility();
+    method public java.lang.Object getTag();
+    method public java.lang.Object getTag(int);
+    method public int getTextAlignment();
+    method public int getTextDirection();
+    method public final int getTop();
+    method protected float getTopFadingEdgeStrength();
+    method protected int getTopPaddingOffset();
+    method public android.view.TouchDelegate getTouchDelegate();
+    method public java.util.ArrayList<android.view.View> getTouchables();
+    method public float getTranslationX();
+    method public float getTranslationY();
+    method public int getVerticalFadingEdgeLength();
+    method public int getVerticalScrollbarPosition();
+    method public int getVerticalScrollbarWidth();
+    method public android.view.ViewTreeObserver getViewTreeObserver();
+    method public int getVisibility();
+    method public final int getWidth();
+    method protected int getWindowAttachCount();
+    method public int getWindowSystemUiVisibility();
+    method public android.os.IBinder getWindowToken();
+    method public int getWindowVisibility();
+    method public void getWindowVisibleDisplayFrame(android.graphics.Rect);
+    method public float getX();
+    method public float getY();
+    method public boolean hasFocus();
+    method public boolean hasFocusable();
+    method public boolean hasOnClickListeners();
+    method public boolean hasOverlappingRendering();
+    method public boolean hasTransientState();
+    method public boolean hasWindowFocus();
+    method public static android.view.View inflate(android.content.Context, int, android.view.ViewGroup);
+    method protected void initializeFadingEdge(android.content.res.TypedArray);
+    method protected void initializeScrollbars(android.content.res.TypedArray);
+    method public void invalidate(android.graphics.Rect);
+    method public void invalidate(int, int, int, int);
+    method public void invalidate();
+    method public void invalidateDrawable(android.graphics.drawable.Drawable);
+    method public boolean isActivated();
+    method public boolean isClickable();
+    method public boolean isDirty();
+    method public boolean isDrawingCacheEnabled();
+    method public boolean isDuplicateParentStateEnabled();
+    method public boolean isEnabled();
+    method public final boolean isFocusable();
+    method public final boolean isFocusableInTouchMode();
+    method public boolean isFocused();
+    method public boolean isHapticFeedbackEnabled();
+    method public boolean isHardwareAccelerated();
+    method public boolean isHorizontalFadingEdgeEnabled();
+    method public boolean isHorizontalScrollBarEnabled();
+    method public boolean isHovered();
+    method public boolean isInEditMode();
+    method public boolean isInTouchMode();
+    method public boolean isLayoutRequested();
+    method public boolean isLongClickable();
+    method public boolean isOpaque();
+    method protected boolean isPaddingOffsetRequired();
+    method public boolean isPaddingRelative();
+    method public boolean isPressed();
+    method public boolean isSaveEnabled();
+    method public boolean isSaveFromParentEnabled();
+    method public boolean isScrollContainer();
+    method public boolean isScrollbarFadingEnabled();
+    method public boolean isSelected();
+    method public boolean isShown();
+    method public boolean isSoundEffectsEnabled();
+    method public boolean isVerticalFadingEdgeEnabled();
+    method public boolean isVerticalScrollBarEnabled();
+    method public void jumpDrawablesToCurrentState();
+    method public void layout(int, int, int, int);
+    method public final void measure(int, int);
+    method protected static int[] mergeDrawableStates(int[], int[]);
+    method public void offsetLeftAndRight(int);
+    method public void offsetTopAndBottom(int);
+    method protected void onAnimationEnd();
+    method protected void onAnimationStart();
+    method protected void onAttachedToWindow();
+    method public boolean onCheckIsTextEditor();
+    method protected void onConfigurationChanged(android.content.res.Configuration);
+    method protected void onCreateContextMenu(android.view.ContextMenu);
+    method protected int[] onCreateDrawableState(int);
+    method public android.view.inputmethod.InputConnection onCreateInputConnection(android.view.inputmethod.EditorInfo);
+    method protected void onDetachedFromWindow();
+    method protected void onDisplayHint(int);
+    method public boolean onDragEvent(android.view.DragEvent);
+    method protected void onDraw(android.graphics.Canvas);
+    method protected final void onDrawScrollBars(android.graphics.Canvas);
+    method public boolean onFilterTouchEventForSecurity(android.view.MotionEvent);
+    method protected void onFinishInflate();
+    method public void onFinishTemporaryDetach();
+    method protected void onFocusChanged(boolean, int, android.graphics.Rect);
+    method public boolean onGenericMotionEvent(android.view.MotionEvent);
+    method public void onHoverChanged(boolean);
+    method public boolean onHoverEvent(android.view.MotionEvent);
+    method public void onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+    method public void onInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo);
+    method public boolean onKeyDown(int, android.view.KeyEvent);
+    method public boolean onKeyLongPress(int, android.view.KeyEvent);
+    method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
+    method public boolean onKeyPreIme(int, android.view.KeyEvent);
+    method public boolean onKeyShortcut(int, android.view.KeyEvent);
+    method public boolean onKeyUp(int, android.view.KeyEvent);
+    method protected void onLayout(boolean, int, int, int, int);
+    method protected void onMeasure(int, int);
+    method protected void onOverScrolled(int, int, boolean, boolean);
+    method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+    method protected void onRestoreInstanceState(android.os.Parcelable);
+    method public void onRtlPropertiesChanged(int);
+    method protected android.os.Parcelable onSaveInstanceState();
+    method public void onScreenStateChanged(int);
+    method protected void onScrollChanged(int, int, int, int);
+    method protected boolean onSetAlpha(int);
+    method protected void onSizeChanged(int, int, int, int);
+    method public void onStartTemporaryDetach();
+    method public boolean onTouchEvent(android.view.MotionEvent);
+    method public boolean onTrackballEvent(android.view.MotionEvent);
+    method protected void onVisibilityChanged(android.view.View, int);
+    method public void onWindowFocusChanged(boolean);
+    method public void onWindowSystemUiVisibilityChanged(int);
+    method protected void onWindowVisibilityChanged(int);
+    method protected boolean overScrollBy(int, int, int, int, int, int, int, int, boolean);
+    method public boolean performAccessibilityAction(int, android.os.Bundle);
+    method public boolean performClick();
+    method public boolean performHapticFeedback(int);
+    method public boolean performHapticFeedback(int, int);
+    method public boolean performLongClick();
+    method public void playSoundEffect(int);
+    method public boolean post(java.lang.Runnable);
+    method public boolean postDelayed(java.lang.Runnable, long);
+    method public void postInvalidate();
+    method public void postInvalidate(int, int, int, int);
+    method public void postInvalidateDelayed(long);
+    method public void postInvalidateDelayed(long, int, int, int, int);
+    method public void postInvalidateOnAnimation();
+    method public void postInvalidateOnAnimation(int, int, int, int);
+    method public void postOnAnimation(java.lang.Runnable);
+    method public void postOnAnimationDelayed(java.lang.Runnable, long);
+    method public void refreshDrawableState();
+    method public boolean removeCallbacks(java.lang.Runnable);
+    method public void removeOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
+    method public void removeOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
+    method public void requestFitSystemWindows();
+    method public final boolean requestFocus();
+    method public final boolean requestFocus(int);
+    method public boolean requestFocus(int, android.graphics.Rect);
+    method public final boolean requestFocusFromTouch();
+    method public void requestLayout();
+    method public boolean requestRectangleOnScreen(android.graphics.Rect);
+    method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
+    method public static int resolveSize(int, int);
+    method public static int resolveSizeAndState(int, int, int);
+    method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
+    method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>);
+    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+    method public void scrollBy(int, int);
+    method public void scrollTo(int, int);
+    method public void sendAccessibilityEvent(int);
+    method public void sendAccessibilityEventUnchecked(android.view.accessibility.AccessibilityEvent);
+    method public void setAccessibilityDelegate(android.view.View.AccessibilityDelegate);
+    method public void setActivated(boolean);
+    method public void setAlpha(float);
+    method public void setAnimation(android.view.animation.Animation);
+    method public void setBackground(android.graphics.drawable.Drawable);
+    method public void setBackgroundColor(int);
+    method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public void setBackgroundResource(int);
+    method public final void setBottom(int);
+    method public void setCameraDistance(float);
+    method public void setClickable(boolean);
+    method public void setContentDescription(java.lang.CharSequence);
+    method public void setDrawingCacheBackgroundColor(int);
+    method public void setDrawingCacheEnabled(boolean);
+    method public void setDrawingCacheQuality(int);
+    method public void setDuplicateParentStateEnabled(boolean);
+    method public void setEnabled(boolean);
+    method public void setFadingEdgeLength(int);
+    method public void setFilterTouchesWhenObscured(boolean);
+    method public void setFitsSystemWindows(boolean);
+    method public void setFocusable(boolean);
+    method public void setFocusableInTouchMode(boolean);
+    method public void setHapticFeedbackEnabled(boolean);
+    method public void setHasTransientState(boolean);
+    method public void setHorizontalFadingEdgeEnabled(boolean);
+    method public void setHorizontalScrollBarEnabled(boolean);
+    method public void setHovered(boolean);
+    method public void setId(int);
+    method public void setImportantForAccessibility(int);
+    method public void setKeepScreenOn(boolean);
+    method public void setLabelFor(int);
+    method public void setLayerPaint(android.graphics.Paint);
+    method public void setLayerType(int, android.graphics.Paint);
+    method public void setLayoutDirection(int);
+    method public void setLayoutParams(android.view.ViewGroup.LayoutParams);
+    method public final void setLeft(int);
+    method public void setLongClickable(boolean);
+    method protected final void setMeasuredDimension(int, int);
+    method public void setMinimumHeight(int);
+    method public void setMinimumWidth(int);
+    method public void setNextFocusDownId(int);
+    method public void setNextFocusForwardId(int);
+    method public void setNextFocusLeftId(int);
+    method public void setNextFocusRightId(int);
+    method public void setNextFocusUpId(int);
+    method public void setOnClickListener(android.view.View.OnClickListener);
+    method public void setOnCreateContextMenuListener(android.view.View.OnCreateContextMenuListener);
+    method public void setOnDragListener(android.view.View.OnDragListener);
+    method public void setOnFocusChangeListener(android.view.View.OnFocusChangeListener);
+    method public void setOnGenericMotionListener(android.view.View.OnGenericMotionListener);
+    method public void setOnHoverListener(android.view.View.OnHoverListener);
+    method public void setOnKeyListener(android.view.View.OnKeyListener);
+    method public void setOnLongClickListener(android.view.View.OnLongClickListener);
+    method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener);
+    method public void setOnTouchListener(android.view.View.OnTouchListener);
+    method public void setOverScrollMode(int);
+    method public void setPadding(int, int, int, int);
+    method public void setPaddingRelative(int, int, int, int);
+    method public void setPivotX(float);
+    method public void setPivotY(float);
+    method public void setPressed(boolean);
+    method public final void setRight(int);
+    method public void setRotation(float);
+    method public void setRotationX(float);
+    method public void setRotationY(float);
+    method public void setSaveEnabled(boolean);
+    method public void setSaveFromParentEnabled(boolean);
+    method public void setScaleX(float);
+    method public void setScaleY(float);
+    method public void setScrollBarDefaultDelayBeforeFade(int);
+    method public void setScrollBarFadeDuration(int);
+    method public void setScrollBarSize(int);
+    method public void setScrollBarStyle(int);
+    method public void setScrollContainer(boolean);
+    method public void setScrollX(int);
+    method public void setScrollY(int);
+    method public void setScrollbarFadingEnabled(boolean);
+    method public void setSelected(boolean);
+    method public void setSoundEffectsEnabled(boolean);
+    method public void setSystemUiVisibility(int);
+    method public void setTag(java.lang.Object);
+    method public void setTag(int, java.lang.Object);
+    method public void setTextAlignment(int);
+    method public void setTextDirection(int);
+    method public final void setTop(int);
+    method public void setTouchDelegate(android.view.TouchDelegate);
+    method public void setTranslationX(float);
+    method public void setTranslationY(float);
+    method public void setVerticalFadingEdgeEnabled(boolean);
+    method public void setVerticalScrollBarEnabled(boolean);
+    method public void setVerticalScrollbarPosition(int);
+    method public void setVisibility(int);
+    method public void setWillNotCacheDrawing(boolean);
+    method public void setWillNotDraw(boolean);
+    method public void setX(float);
+    method public void setY(float);
+    method public boolean showContextMenu();
+    method public android.view.ActionMode startActionMode(android.view.ActionMode.Callback);
+    method public void startAnimation(android.view.animation.Animation);
+    method public final boolean startDrag(android.content.ClipData, android.view.View.DragShadowBuilder, java.lang.Object, int);
+    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+    method public void unscheduleDrawable(android.graphics.drawable.Drawable);
+    method protected boolean verifyDrawable(android.graphics.drawable.Drawable);
+    method public boolean willNotCacheDrawing();
+    method public boolean willNotDraw();
+    field public static final android.util.Property ALPHA;
+    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
+    field protected static final int[] EMPTY_STATE_SET;
+    field protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
+    field protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+    field protected static final int[] ENABLED_FOCUSED_STATE_SET;
+    field protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
+    field protected static final int[] ENABLED_SELECTED_STATE_SET;
+    field protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+    field protected static final int[] ENABLED_STATE_SET;
+    field protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
+    field public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 2; // 0x2
+    field public static final int FIND_VIEWS_WITH_TEXT = 1; // 0x1
+    field public static final int FOCUSABLES_ALL = 0; // 0x0
+    field public static final int FOCUSABLES_TOUCH_MODE = 1; // 0x1
+    field protected static final int[] FOCUSED_SELECTED_STATE_SET;
+    field protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+    field protected static final int[] FOCUSED_STATE_SET;
+    field protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
+    field public static final int FOCUS_BACKWARD = 1; // 0x1
+    field public static final int FOCUS_DOWN = 130; // 0x82
+    field public static final int FOCUS_FORWARD = 2; // 0x2
+    field public static final int FOCUS_LEFT = 17; // 0x11
+    field public static final int FOCUS_RIGHT = 66; // 0x42
+    field public static final int FOCUS_UP = 33; // 0x21
+    field public static final int GONE = 8; // 0x8
+    field public static final int HAPTIC_FEEDBACK_ENABLED = 268435456; // 0x10000000
+    field public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0; // 0x0
+    field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 2; // 0x2
+    field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
+    field public static final int INVISIBLE = 4; // 0x4
+    field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
+    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 = 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
+    field public static final int MEASURED_STATE_TOO_SMALL = 16777216; // 0x1000000
+    field public static final int NO_ID = -1; // 0xffffffff
+    field public static final int OVER_SCROLL_ALWAYS = 0; // 0x0
+    field public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1; // 0x1
+    field public static final int OVER_SCROLL_NEVER = 2; // 0x2
+    field protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
+    field protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+    field protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
+    field protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
+    field protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
+    field protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+    field protected static final int[] PRESSED_ENABLED_STATE_SET;
+    field protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
+    field protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
+    field protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+    field protected static final int[] PRESSED_FOCUSED_STATE_SET;
+    field protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
+    field protected static final int[] PRESSED_SELECTED_STATE_SET;
+    field protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+    field protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
+    field public static final android.util.Property ROTATION;
+    field public static final android.util.Property ROTATION_X;
+    field public static final android.util.Property ROTATION_Y;
+    field public static final android.util.Property SCALE_X;
+    field public static final android.util.Property SCALE_Y;
+    field public static final int SCREEN_STATE_OFF = 0; // 0x0
+    field public static final int SCREEN_STATE_ON = 1; // 0x1
+    field public static final int SCROLLBARS_INSIDE_INSET = 16777216; // 0x1000000
+    field public static final int SCROLLBARS_INSIDE_OVERLAY = 0; // 0x0
+    field public static final int SCROLLBARS_OUTSIDE_INSET = 50331648; // 0x3000000
+    field public static final int SCROLLBARS_OUTSIDE_OVERLAY = 33554432; // 0x2000000
+    field public static final int SCROLLBAR_POSITION_DEFAULT = 0; // 0x0
+    field public static final int SCROLLBAR_POSITION_LEFT = 1; // 0x1
+    field public static final int SCROLLBAR_POSITION_RIGHT = 2; // 0x2
+    field protected static final int[] SELECTED_STATE_SET;
+    field protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
+    field public static final int SOUND_EFFECTS_ENABLED = 134217728; // 0x8000000
+    field public static final deprecated int STATUS_BAR_HIDDEN = 1; // 0x1
+    field public static final deprecated int STATUS_BAR_VISIBLE = 0; // 0x0
+    field public static final int SYSTEM_UI_FLAG_FULLSCREEN = 4; // 0x4
+    field public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 2; // 0x2
+    field public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024; // 0x400
+    field public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512; // 0x200
+    field public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 256; // 0x100
+    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 SYSTEM_UI_LAYOUT_FLAGS = 1536; // 0x600
+    field public static final int TEXT_ALIGNMENT_CENTER = 4; // 0x4
+    field public static final int TEXT_ALIGNMENT_GRAVITY = 1; // 0x1
+    field public static final int TEXT_ALIGNMENT_INHERIT = 0; // 0x0
+    field public static final int TEXT_ALIGNMENT_TEXT_END = 3; // 0x3
+    field public static final int TEXT_ALIGNMENT_TEXT_START = 2; // 0x2
+    field public static final int TEXT_ALIGNMENT_VIEW_END = 6; // 0x6
+    field public static final int TEXT_ALIGNMENT_VIEW_START = 5; // 0x5
+    field public static final int TEXT_DIRECTION_ANY_RTL = 2; // 0x2
+    field 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
+    field public static final int TEXT_DIRECTION_LTR = 3; // 0x3
+    field public static final int TEXT_DIRECTION_RTL = 4; // 0x4
+    field public static final android.util.Property TRANSLATION_X;
+    field public static final android.util.Property TRANSLATION_Y;
+    field protected static final java.lang.String VIEW_LOG_TAG = "View";
+    field public static final int VISIBLE = 0; // 0x0
+    field protected static final int[] WINDOW_FOCUSED_STATE_SET;
+    field public static final android.util.Property X;
+    field public static final android.util.Property Y;
+  }
+
+  public static class View.AccessibilityDelegate {
+    ctor public View.AccessibilityDelegate();
+    method public boolean dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider(android.view.View);
+    method public void onInitializeAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public void onInitializeAccessibilityNodeInfo(android.view.View, android.view.accessibility.AccessibilityNodeInfo);
+    method public void onPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public boolean onRequestSendAccessibilityEvent(android.view.ViewGroup, android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public boolean performAccessibilityAction(android.view.View, int, android.os.Bundle);
+    method public void sendAccessibilityEvent(android.view.View, int);
+    method public void sendAccessibilityEventUnchecked(android.view.View, android.view.accessibility.AccessibilityEvent);
+  }
+
+  public static class View.BaseSavedState extends android.view.AbsSavedState {
+    ctor public View.BaseSavedState(android.os.Parcel);
+    ctor public View.BaseSavedState(android.os.Parcelable);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static class View.DragShadowBuilder {
+    ctor public View.DragShadowBuilder(android.view.View);
+    ctor public View.DragShadowBuilder();
+    method public final android.view.View getView();
+    method public void onDrawShadow(android.graphics.Canvas);
+    method public void onProvideShadowMetrics(android.graphics.Point, android.graphics.Point);
+  }
+
+  public static class View.MeasureSpec {
+    ctor public View.MeasureSpec();
+    method public static int getMode(int);
+    method public static int getSize(int);
+    method public static int makeMeasureSpec(int, int);
+    method public static java.lang.String toString(int);
+    field public static final int AT_MOST = -2147483648; // 0x80000000
+    field public static final int EXACTLY = 1073741824; // 0x40000000
+    field public static final int UNSPECIFIED = 0; // 0x0
+  }
+
+  public static abstract interface View.OnAttachStateChangeListener {
+    method public abstract void onViewAttachedToWindow(android.view.View);
+    method public abstract void onViewDetachedFromWindow(android.view.View);
+  }
+
+  public static abstract interface View.OnClickListener {
+    method public abstract void onClick(android.view.View);
+  }
+
+  public static abstract interface View.OnCreateContextMenuListener {
+    method public abstract void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo);
+  }
+
+  public static abstract interface View.OnDragListener {
+    method public abstract boolean onDrag(android.view.View, android.view.DragEvent);
+  }
+
+  public static abstract interface View.OnFocusChangeListener {
+    method public abstract void onFocusChange(android.view.View, boolean);
+  }
+
+  public static abstract interface View.OnGenericMotionListener {
+    method public abstract boolean onGenericMotion(android.view.View, android.view.MotionEvent);
+  }
+
+  public static abstract interface View.OnHoverListener {
+    method public abstract boolean onHover(android.view.View, android.view.MotionEvent);
+  }
+
+  public static abstract interface View.OnKeyListener {
+    method public abstract boolean onKey(android.view.View, int, android.view.KeyEvent);
+  }
+
+  public static abstract interface View.OnLayoutChangeListener {
+    method public abstract void onLayoutChange(android.view.View, int, int, int, int, int, int, int, int);
+  }
+
+  public static abstract interface View.OnLongClickListener {
+    method public abstract boolean onLongClick(android.view.View);
+  }
+
+  public static abstract interface View.OnSystemUiVisibilityChangeListener {
+    method public abstract void onSystemUiVisibilityChange(int);
+  }
+
+  public static abstract interface View.OnTouchListener {
+    method public abstract boolean onTouch(android.view.View, android.view.MotionEvent);
+  }
+
+  public class ViewConfiguration {
+    ctor public deprecated ViewConfiguration();
+    method public static android.view.ViewConfiguration get(android.content.Context);
+    method public static int getDoubleTapTimeout();
+    method public static deprecated int getEdgeSlop();
+    method public static deprecated int getFadingEdgeLength();
+    method public static long getGlobalActionKeyTimeout();
+    method public static int getJumpTapTimeout();
+    method public static int getKeyRepeatDelay();
+    method public static int getKeyRepeatTimeout();
+    method public static int getLongPressTimeout();
+    method public static deprecated int getMaximumDrawingCacheSize();
+    method public static deprecated int getMaximumFlingVelocity();
+    method public static deprecated int getMinimumFlingVelocity();
+    method public static int getPressedStateDuration();
+    method public int getScaledDoubleTapSlop();
+    method public int getScaledEdgeSlop();
+    method public int getScaledFadingEdgeLength();
+    method public int getScaledMaximumDrawingCacheSize();
+    method public int getScaledMaximumFlingVelocity();
+    method public int getScaledMinimumFlingVelocity();
+    method public int getScaledOverflingDistance();
+    method public int getScaledOverscrollDistance();
+    method public int getScaledPagingTouchSlop();
+    method public int getScaledScrollBarSize();
+    method public int getScaledTouchSlop();
+    method public int getScaledWindowTouchSlop();
+    method public static int getScrollBarFadeDuration();
+    method public static deprecated int getScrollBarSize();
+    method public static int getScrollDefaultDelay();
+    method public static float getScrollFriction();
+    method public static int getTapTimeout();
+    method public static deprecated int getTouchSlop();
+    method public static deprecated int getWindowTouchSlop();
+    method public static long getZoomControlsTimeout();
+    method public boolean hasPermanentMenuKey();
+  }
+
+  public class ViewDebug {
+    ctor public ViewDebug();
+    method public static void dumpCapturedView(java.lang.String, java.lang.Object);
+    method public static deprecated void startHierarchyTracing(java.lang.String, android.view.View);
+    method public static deprecated void startRecyclerTracing(java.lang.String, android.view.View);
+    method public static deprecated void stopHierarchyTracing();
+    method public static deprecated void stopRecyclerTracing();
+    method public static deprecated void trace(android.view.View, android.view.ViewDebug.RecyclerTraceType, int...);
+    method public static deprecated void trace(android.view.View, android.view.ViewDebug.HierarchyTraceType);
+    field public static final deprecated boolean TRACE_HIERARCHY = false;
+    field public static final deprecated boolean TRACE_RECYCLER = false;
+  }
+
+  public static abstract class ViewDebug.CapturedViewProperty implements java.lang.annotation.Annotation {
+  }
+
+  public static abstract class ViewDebug.ExportedProperty implements java.lang.annotation.Annotation {
+  }
+
+  public static abstract class ViewDebug.FlagToString implements java.lang.annotation.Annotation {
+  }
+
+  public static final deprecated class ViewDebug.HierarchyTraceType extends java.lang.Enum {
+    method public static android.view.ViewDebug.HierarchyTraceType valueOf(java.lang.String);
+    method public static final android.view.ViewDebug.HierarchyTraceType[] values();
+    enum_constant public static final android.view.ViewDebug.HierarchyTraceType BUILD_CACHE;
+    enum_constant public static final android.view.ViewDebug.HierarchyTraceType DRAW;
+    enum_constant public static final android.view.ViewDebug.HierarchyTraceType INVALIDATE;
+    enum_constant public static final android.view.ViewDebug.HierarchyTraceType INVALIDATE_CHILD;
+    enum_constant public static final android.view.ViewDebug.HierarchyTraceType INVALIDATE_CHILD_IN_PARENT;
+    enum_constant public static final android.view.ViewDebug.HierarchyTraceType ON_LAYOUT;
+    enum_constant public static final android.view.ViewDebug.HierarchyTraceType ON_MEASURE;
+    enum_constant public static final android.view.ViewDebug.HierarchyTraceType REQUEST_LAYOUT;
+  }
+
+  public static abstract class ViewDebug.IntToString implements java.lang.annotation.Annotation {
+  }
+
+  public static final deprecated class ViewDebug.RecyclerTraceType extends java.lang.Enum {
+    method public static android.view.ViewDebug.RecyclerTraceType valueOf(java.lang.String);
+    method public static final android.view.ViewDebug.RecyclerTraceType[] values();
+    enum_constant public static final android.view.ViewDebug.RecyclerTraceType BIND_VIEW;
+    enum_constant public static final android.view.ViewDebug.RecyclerTraceType MOVE_FROM_ACTIVE_TO_SCRAP_HEAP;
+    enum_constant public static final android.view.ViewDebug.RecyclerTraceType MOVE_TO_SCRAP_HEAP;
+    enum_constant public static final android.view.ViewDebug.RecyclerTraceType NEW_VIEW;
+    enum_constant public static final android.view.ViewDebug.RecyclerTraceType RECYCLE_FROM_ACTIVE_HEAP;
+    enum_constant public static final android.view.ViewDebug.RecyclerTraceType RECYCLE_FROM_SCRAP_HEAP;
+  }
+
+  public abstract class ViewGroup extends android.view.View implements android.view.ViewManager android.view.ViewParent {
+    ctor public ViewGroup(android.content.Context);
+    ctor public ViewGroup(android.content.Context, android.util.AttributeSet);
+    ctor public ViewGroup(android.content.Context, android.util.AttributeSet, int);
+    method public boolean addStatesFromChildren();
+    method public void addView(android.view.View);
+    method public void addView(android.view.View, int);
+    method public void addView(android.view.View, int, int);
+    method public void addView(android.view.View, android.view.ViewGroup.LayoutParams);
+    method public void addView(android.view.View, int, android.view.ViewGroup.LayoutParams);
+    method protected boolean addViewInLayout(android.view.View, int, android.view.ViewGroup.LayoutParams);
+    method protected boolean addViewInLayout(android.view.View, int, android.view.ViewGroup.LayoutParams, boolean);
+    method protected void attachLayoutAnimationParameters(android.view.View, android.view.ViewGroup.LayoutParams, int, int);
+    method protected void attachViewToParent(android.view.View, int, android.view.ViewGroup.LayoutParams);
+    method public void bringChildToFront(android.view.View);
+    method protected boolean canAnimate();
+    method protected boolean checkLayoutParams(android.view.ViewGroup.LayoutParams);
+    method public void childDrawableStateChanged(android.view.View);
+    method protected void cleanupLayoutState(android.view.View);
+    method public void clearChildFocus(android.view.View);
+    method public void clearDisappearingChildren();
+    method protected void debug(int);
+    method protected void detachAllViewsFromParent();
+    method protected void detachViewFromParent(android.view.View);
+    method protected void detachViewFromParent(int);
+    method protected void detachViewsFromParent(int, int);
+    method protected void dispatchFreezeSelfOnly(android.util.SparseArray<android.os.Parcelable>);
+    method public void dispatchSetActivated(boolean);
+    method public void dispatchSetSelected(boolean);
+    method protected void dispatchThawSelfOnly(android.util.SparseArray<android.os.Parcelable>);
+    method protected boolean drawChild(android.graphics.Canvas, android.view.View, long);
+    method public void endViewTransition(android.view.View);
+    method public android.view.View focusSearch(android.view.View, int);
+    method public void focusableViewAvailable(android.view.View);
+    method public boolean gatherTransparentRegion(android.graphics.Region);
+    method protected android.view.ViewGroup.LayoutParams generateDefaultLayoutParams();
+    method public android.view.ViewGroup.LayoutParams generateLayoutParams(android.util.AttributeSet);
+    method protected android.view.ViewGroup.LayoutParams generateLayoutParams(android.view.ViewGroup.LayoutParams);
+    method public android.view.View getChildAt(int);
+    method public int getChildCount();
+    method protected int getChildDrawingOrder(int, int);
+    method public static int getChildMeasureSpec(int, int, int);
+    method protected boolean getChildStaticTransformation(android.view.View, android.view.animation.Transformation);
+    method public boolean getChildVisibleRect(android.view.View, android.graphics.Rect, android.graphics.Point);
+    method public int getDescendantFocusability();
+    method public android.view.View getFocusedChild();
+    method public android.view.animation.LayoutAnimationController getLayoutAnimation();
+    method public android.view.animation.Animation.AnimationListener getLayoutAnimationListener();
+    method public android.animation.LayoutTransition getLayoutTransition();
+    method public int getPersistentDrawingCache();
+    method public int indexOfChild(android.view.View);
+    method public final void invalidateChild(android.view.View, android.graphics.Rect);
+    method public android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
+    method public boolean isAlwaysDrawnWithCacheEnabled();
+    method public boolean isAnimationCacheEnabled();
+    method protected boolean isChildrenDrawingOrderEnabled();
+    method protected boolean isChildrenDrawnWithCacheEnabled();
+    method public boolean isMotionEventSplittingEnabled();
+    method public final void layout(int, int, int, int);
+    method protected void measureChild(android.view.View, int, int);
+    method protected void measureChildWithMargins(android.view.View, int, int, int, int);
+    method protected void measureChildren(int, int);
+    method public final void offsetDescendantRectToMyCoords(android.view.View, android.graphics.Rect);
+    method public final void offsetRectIntoDescendantCoords(android.view.View, android.graphics.Rect);
+    method public boolean onInterceptHoverEvent(android.view.MotionEvent);
+    method public boolean onInterceptTouchEvent(android.view.MotionEvent);
+    method protected abstract void onLayout(boolean, int, int, int, int);
+    method protected boolean onRequestFocusInDescendants(int, android.graphics.Rect);
+    method public boolean onRequestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public void recomputeViewAttributes(android.view.View);
+    method public void removeAllViews();
+    method public void removeAllViewsInLayout();
+    method protected void removeDetachedView(android.view.View, boolean);
+    method public void removeView(android.view.View);
+    method public void removeViewAt(int);
+    method public void removeViewInLayout(android.view.View);
+    method public void removeViews(int, int);
+    method public void removeViewsInLayout(int, int);
+    method public void requestChildFocus(android.view.View, android.view.View);
+    method public boolean requestChildRectangleOnScreen(android.view.View, android.graphics.Rect, boolean);
+    method public void requestDisallowInterceptTouchEvent(boolean);
+    method public boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public void requestTransparentRegion(android.view.View);
+    method public void scheduleLayoutAnimation();
+    method public void setAddStatesFromChildren(boolean);
+    method public void setAlwaysDrawnWithCacheEnabled(boolean);
+    method public void setAnimationCacheEnabled(boolean);
+    method protected void setChildrenDrawingCacheEnabled(boolean);
+    method protected void setChildrenDrawingOrderEnabled(boolean);
+    method protected void setChildrenDrawnWithCacheEnabled(boolean);
+    method public void setClipChildren(boolean);
+    method public void setClipToPadding(boolean);
+    method public void setDescendantFocusability(int);
+    method public void setLayoutAnimation(android.view.animation.LayoutAnimationController);
+    method public void setLayoutAnimationListener(android.view.animation.Animation.AnimationListener);
+    method public void setLayoutTransition(android.animation.LayoutTransition);
+    method public void setMotionEventSplittingEnabled(boolean);
+    method public void setOnHierarchyChangeListener(android.view.ViewGroup.OnHierarchyChangeListener);
+    method public void setPersistentDrawingCache(int);
+    method protected void setStaticTransformationsEnabled(boolean);
+    method public boolean shouldDelayChildPressedState();
+    method public boolean showContextMenuForChild(android.view.View);
+    method public android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback);
+    method public void startLayoutAnimation();
+    method public void startViewTransition(android.view.View);
+    method public void updateViewLayout(android.view.View, android.view.ViewGroup.LayoutParams);
+    field protected static final int CLIP_TO_PADDING_MASK = 34; // 0x22
+    field public static final int FOCUS_AFTER_DESCENDANTS = 262144; // 0x40000
+    field public static final int FOCUS_BEFORE_DESCENDANTS = 131072; // 0x20000
+    field public static final int FOCUS_BLOCK_DESCENDANTS = 393216; // 0x60000
+    field public static final int PERSISTENT_ALL_CACHES = 3; // 0x3
+    field public static final int PERSISTENT_ANIMATION_CACHE = 1; // 0x1
+    field public static final int PERSISTENT_NO_CACHE = 0; // 0x0
+    field public static final int PERSISTENT_SCROLLING_CACHE = 2; // 0x2
+  }
+
+  public static class ViewGroup.LayoutParams {
+    ctor public ViewGroup.LayoutParams(android.content.Context, android.util.AttributeSet);
+    ctor public ViewGroup.LayoutParams(int, int);
+    ctor public ViewGroup.LayoutParams(android.view.ViewGroup.LayoutParams);
+    method public void resolveLayoutDirection(int);
+    method protected void setBaseAttributes(android.content.res.TypedArray, int, int);
+    field public static final deprecated int FILL_PARENT = -1; // 0xffffffff
+    field public static final int MATCH_PARENT = -1; // 0xffffffff
+    field public static final int WRAP_CONTENT = -2; // 0xfffffffe
+    field public int height;
+    field public android.view.animation.LayoutAnimationController.AnimationParameters layoutAnimationParameters;
+    field public int width;
+  }
+
+  public static class ViewGroup.MarginLayoutParams extends android.view.ViewGroup.LayoutParams {
+    ctor public ViewGroup.MarginLayoutParams(android.content.Context, android.util.AttributeSet);
+    ctor public ViewGroup.MarginLayoutParams(int, int);
+    ctor public ViewGroup.MarginLayoutParams(android.view.ViewGroup.MarginLayoutParams);
+    ctor public ViewGroup.MarginLayoutParams(android.view.ViewGroup.LayoutParams);
+    method public int getLayoutDirection();
+    method public int getMarginEnd();
+    method public int getMarginStart();
+    method public boolean isMarginRelative();
+    method public void setLayoutDirection(int);
+    method public void setMarginEnd(int);
+    method public void setMarginStart(int);
+    method public void setMargins(int, int, int, int);
+    field public int bottomMargin;
+    field public int leftMargin;
+    field public int rightMargin;
+    field public int topMargin;
+  }
+
+  public static abstract interface ViewGroup.OnHierarchyChangeListener {
+    method public abstract void onChildViewAdded(android.view.View, android.view.View);
+    method public abstract void onChildViewRemoved(android.view.View, android.view.View);
+  }
+
+  public abstract interface ViewManager {
+    method public abstract void addView(android.view.View, android.view.ViewGroup.LayoutParams);
+    method public abstract void removeView(android.view.View);
+    method public abstract void updateViewLayout(android.view.View, android.view.ViewGroup.LayoutParams);
+  }
+
+  public abstract interface ViewParent {
+    method public abstract void bringChildToFront(android.view.View);
+    method public abstract void childDrawableStateChanged(android.view.View);
+    method public abstract void clearChildFocus(android.view.View);
+    method public abstract void createContextMenu(android.view.ContextMenu);
+    method public abstract android.view.View focusSearch(android.view.View, int);
+    method public abstract void focusableViewAvailable(android.view.View);
+    method public abstract boolean getChildVisibleRect(android.view.View, android.graphics.Rect, android.graphics.Point);
+    method public abstract android.view.ViewParent getParent();
+    method public abstract android.view.ViewParent getParentForAccessibility();
+    method public abstract void invalidateChild(android.view.View, android.graphics.Rect);
+    method public abstract android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
+    method public abstract boolean isLayoutRequested();
+    method public abstract void recomputeViewAttributes(android.view.View);
+    method public abstract void requestChildFocus(android.view.View, android.view.View);
+    method public abstract boolean requestChildRectangleOnScreen(android.view.View, android.graphics.Rect, boolean);
+    method public abstract void requestDisallowInterceptTouchEvent(boolean);
+    method public abstract void requestFitSystemWindows();
+    method public abstract void requestLayout();
+    method public abstract boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public abstract void requestTransparentRegion(android.view.View);
+    method public abstract boolean showContextMenuForChild(android.view.View);
+    method public abstract android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback);
+  }
+
+  public class ViewPropertyAnimator {
+    method public android.view.ViewPropertyAnimator alpha(float);
+    method public android.view.ViewPropertyAnimator alphaBy(float);
+    method public void cancel();
+    method public long getDuration();
+    method public long getStartDelay();
+    method public android.view.ViewPropertyAnimator rotation(float);
+    method public android.view.ViewPropertyAnimator rotationBy(float);
+    method public android.view.ViewPropertyAnimator rotationX(float);
+    method public android.view.ViewPropertyAnimator rotationXBy(float);
+    method public android.view.ViewPropertyAnimator rotationY(float);
+    method public android.view.ViewPropertyAnimator rotationYBy(float);
+    method public android.view.ViewPropertyAnimator scaleX(float);
+    method public android.view.ViewPropertyAnimator scaleXBy(float);
+    method public android.view.ViewPropertyAnimator scaleY(float);
+    method public android.view.ViewPropertyAnimator scaleYBy(float);
+    method public android.view.ViewPropertyAnimator setDuration(long);
+    method public android.view.ViewPropertyAnimator setInterpolator(android.animation.TimeInterpolator);
+    method public android.view.ViewPropertyAnimator setListener(android.animation.Animator.AnimatorListener);
+    method public android.view.ViewPropertyAnimator setStartDelay(long);
+    method public void start();
+    method public android.view.ViewPropertyAnimator translationX(float);
+    method public android.view.ViewPropertyAnimator translationXBy(float);
+    method public android.view.ViewPropertyAnimator translationY(float);
+    method public android.view.ViewPropertyAnimator translationYBy(float);
+    method public android.view.ViewPropertyAnimator withEndAction(java.lang.Runnable);
+    method public android.view.ViewPropertyAnimator withLayer();
+    method public android.view.ViewPropertyAnimator withStartAction(java.lang.Runnable);
+    method public android.view.ViewPropertyAnimator x(float);
+    method public android.view.ViewPropertyAnimator xBy(float);
+    method public android.view.ViewPropertyAnimator y(float);
+    method public android.view.ViewPropertyAnimator yBy(float);
+  }
+
+  public final class ViewStub extends android.view.View {
+    ctor public ViewStub(android.content.Context);
+    ctor public ViewStub(android.content.Context, int);
+    ctor public ViewStub(android.content.Context, android.util.AttributeSet);
+    ctor public ViewStub(android.content.Context, android.util.AttributeSet, int);
+    method public int getInflatedId();
+    method public android.view.LayoutInflater getLayoutInflater();
+    method public int getLayoutResource();
+    method public android.view.View inflate();
+    method public void setInflatedId(int);
+    method public void setLayoutInflater(android.view.LayoutInflater);
+    method public void setLayoutResource(int);
+    method public void setOnInflateListener(android.view.ViewStub.OnInflateListener);
+  }
+
+  public static abstract interface ViewStub.OnInflateListener {
+    method public abstract void onInflate(android.view.ViewStub, android.view.View);
+  }
+
+  public final class ViewTreeObserver {
+    method public void addOnDrawListener(android.view.ViewTreeObserver.OnDrawListener);
+    method public void addOnGlobalFocusChangeListener(android.view.ViewTreeObserver.OnGlobalFocusChangeListener);
+    method public void addOnGlobalLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener);
+    method public void addOnPreDrawListener(android.view.ViewTreeObserver.OnPreDrawListener);
+    method public void addOnScrollChangedListener(android.view.ViewTreeObserver.OnScrollChangedListener);
+    method public void addOnTouchModeChangeListener(android.view.ViewTreeObserver.OnTouchModeChangeListener);
+    method public final void dispatchOnDraw();
+    method public final void dispatchOnGlobalLayout();
+    method public final boolean dispatchOnPreDraw();
+    method public boolean isAlive();
+    method public deprecated void removeGlobalOnLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener);
+    method public void removeOnDrawListener(android.view.ViewTreeObserver.OnDrawListener);
+    method public void removeOnGlobalFocusChangeListener(android.view.ViewTreeObserver.OnGlobalFocusChangeListener);
+    method public void removeOnGlobalLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener);
+    method public void removeOnPreDrawListener(android.view.ViewTreeObserver.OnPreDrawListener);
+    method public void removeOnScrollChangedListener(android.view.ViewTreeObserver.OnScrollChangedListener);
+    method public void removeOnTouchModeChangeListener(android.view.ViewTreeObserver.OnTouchModeChangeListener);
+  }
+
+  public static abstract interface ViewTreeObserver.OnDrawListener {
+    method public abstract void onDraw();
+  }
+
+  public static abstract interface ViewTreeObserver.OnGlobalFocusChangeListener {
+    method public abstract void onGlobalFocusChanged(android.view.View, android.view.View);
+  }
+
+  public static abstract interface ViewTreeObserver.OnGlobalLayoutListener {
+    method public abstract void onGlobalLayout();
+  }
+
+  public static abstract interface ViewTreeObserver.OnPreDrawListener {
+    method public abstract boolean onPreDraw();
+  }
+
+  public static abstract interface ViewTreeObserver.OnScrollChangedListener {
+    method public abstract void onScrollChanged();
+  }
+
+  public static abstract interface ViewTreeObserver.OnTouchModeChangeListener {
+    method public abstract void onTouchModeChanged(boolean);
+  }
+
+  public abstract class Window {
+    ctor public Window(android.content.Context);
+    method public abstract void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
+    method public void addFlags(int);
+    method public void clearFlags(int);
+    method public abstract void closeAllPanels();
+    method public abstract void closePanel(int);
+    method public android.view.View findViewById(int);
+    method public final android.view.WindowManager.LayoutParams getAttributes();
+    method public final android.view.Window.Callback getCallback();
+    method public final android.view.Window getContainer();
+    method public final android.content.Context getContext();
+    method public abstract android.view.View getCurrentFocus();
+    method public abstract android.view.View getDecorView();
+    method protected final int getFeatures();
+    method protected final int getForcedWindowFlags();
+    method public abstract android.view.LayoutInflater getLayoutInflater();
+    method protected final int getLocalFeatures();
+    method public abstract int getVolumeControlStream();
+    method public android.view.WindowManager getWindowManager();
+    method public final android.content.res.TypedArray getWindowStyle();
+    method public final boolean hasChildren();
+    method public boolean hasFeature(int);
+    method protected final boolean hasSoftInputMode();
+    method public abstract void invalidatePanelMenu(int);
+    method public final boolean isActive();
+    method public abstract boolean isFloating();
+    method public abstract boolean isShortcutKey(int, android.view.KeyEvent);
+    method public final void makeActive();
+    method protected abstract void onActive();
+    method public abstract void onConfigurationChanged(android.content.res.Configuration);
+    method public abstract void openPanel(int, android.view.KeyEvent);
+    method public abstract android.view.View peekDecorView();
+    method public abstract boolean performContextMenuIdentifierAction(int, int);
+    method public abstract boolean performPanelIdentifierAction(int, int, int);
+    method public abstract boolean performPanelShortcut(int, int, android.view.KeyEvent, int);
+    method public boolean requestFeature(int);
+    method public abstract void restoreHierarchyState(android.os.Bundle);
+    method public abstract android.os.Bundle saveHierarchyState();
+    method public void setAttributes(android.view.WindowManager.LayoutParams);
+    method public abstract void setBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public void setBackgroundDrawableResource(int);
+    method public void setCallback(android.view.Window.Callback);
+    method public abstract void setChildDrawable(int, android.graphics.drawable.Drawable);
+    method public abstract void setChildInt(int, int);
+    method public void setContainer(android.view.Window);
+    method public abstract void setContentView(int);
+    method public abstract void setContentView(android.view.View);
+    method public abstract void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
+    method protected void setDefaultWindowFormat(int);
+    method public void setDimAmount(float);
+    method public abstract void setFeatureDrawable(int, android.graphics.drawable.Drawable);
+    method public abstract void setFeatureDrawableAlpha(int, int);
+    method public abstract void setFeatureDrawableResource(int, int);
+    method public abstract void setFeatureDrawableUri(int, android.net.Uri);
+    method public abstract void setFeatureInt(int, int);
+    method public void setFlags(int, int);
+    method public void setFormat(int);
+    method public void setGravity(int);
+    method public void setLayout(int, int);
+    method public void setSoftInputMode(int);
+    method public abstract void setTitle(java.lang.CharSequence);
+    method public abstract void setTitleColor(int);
+    method public void setType(int);
+    method public void setUiOptions(int);
+    method public void setUiOptions(int, int);
+    method public abstract void setVolumeControlStream(int);
+    method public void setWindowAnimations(int);
+    method public void setWindowManager(android.view.WindowManager, android.os.IBinder, java.lang.String);
+    method public void setWindowManager(android.view.WindowManager, android.os.IBinder, java.lang.String, boolean);
+    method public abstract boolean superDispatchGenericMotionEvent(android.view.MotionEvent);
+    method public abstract boolean superDispatchKeyEvent(android.view.KeyEvent);
+    method public abstract boolean superDispatchKeyShortcutEvent(android.view.KeyEvent);
+    method public abstract boolean superDispatchTouchEvent(android.view.MotionEvent);
+    method public abstract boolean superDispatchTrackballEvent(android.view.MotionEvent);
+    method public abstract void takeInputQueue(android.view.InputQueue.Callback);
+    method public abstract void takeKeyEvents(boolean);
+    method public abstract void takeSurface(android.view.SurfaceHolder.Callback2);
+    method public abstract void togglePanel(int, android.view.KeyEvent);
+    field protected static final int DEFAULT_FEATURES = 65; // 0x41
+    field public static final int FEATURE_ACTION_BAR = 8; // 0x8
+    field public static final int FEATURE_ACTION_BAR_OVERLAY = 9; // 0x9
+    field public static final int FEATURE_ACTION_MODE_OVERLAY = 10; // 0xa
+    field public static final int FEATURE_CONTEXT_MENU = 6; // 0x6
+    field public static final int FEATURE_CUSTOM_TITLE = 7; // 0x7
+    field public static final int FEATURE_INDETERMINATE_PROGRESS = 5; // 0x5
+    field public static final int FEATURE_LEFT_ICON = 3; // 0x3
+    field public static final int FEATURE_NO_TITLE = 1; // 0x1
+    field public static final int FEATURE_OPTIONS_PANEL = 0; // 0x0
+    field public static final int FEATURE_PROGRESS = 2; // 0x2
+    field public static final int FEATURE_RIGHT_ICON = 4; // 0x4
+    field public static final int ID_ANDROID_CONTENT = 16908290; // 0x1020002
+    field public static final int PROGRESS_END = 10000; // 0x2710
+    field public static final int PROGRESS_INDETERMINATE_OFF = -4; // 0xfffffffc
+    field public static final int PROGRESS_INDETERMINATE_ON = -3; // 0xfffffffd
+    field public static final int PROGRESS_SECONDARY_END = 30000; // 0x7530
+    field public static final int PROGRESS_SECONDARY_START = 20000; // 0x4e20
+    field public static final int PROGRESS_START = 0; // 0x0
+    field public static final int PROGRESS_VISIBILITY_OFF = -2; // 0xfffffffe
+    field public static final int PROGRESS_VISIBILITY_ON = -1; // 0xffffffff
+  }
+
+  public static abstract interface Window.Callback {
+    method public abstract boolean dispatchGenericMotionEvent(android.view.MotionEvent);
+    method public abstract boolean dispatchKeyEvent(android.view.KeyEvent);
+    method public abstract boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
+    method public abstract boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+    method public abstract boolean dispatchTouchEvent(android.view.MotionEvent);
+    method public abstract boolean dispatchTrackballEvent(android.view.MotionEvent);
+    method public abstract void onActionModeFinished(android.view.ActionMode);
+    method public abstract void onActionModeStarted(android.view.ActionMode);
+    method public abstract void onAttachedToWindow();
+    method public abstract void onContentChanged();
+    method public abstract boolean onCreatePanelMenu(int, android.view.Menu);
+    method public abstract android.view.View onCreatePanelView(int);
+    method public abstract void onDetachedFromWindow();
+    method public abstract boolean onMenuItemSelected(int, android.view.MenuItem);
+    method public abstract boolean onMenuOpened(int, android.view.Menu);
+    method public abstract void onPanelClosed(int, android.view.Menu);
+    method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
+    method public abstract boolean onSearchRequested();
+    method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
+    method public abstract void onWindowFocusChanged(boolean);
+    method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
+  }
+
+  public abstract interface WindowManager implements android.view.ViewManager {
+    method public abstract android.view.Display getDefaultDisplay();
+    method public abstract void removeViewImmediate(android.view.View);
+  }
+
+  public static class WindowManager.BadTokenException extends java.lang.RuntimeException {
+    ctor public WindowManager.BadTokenException();
+    ctor public WindowManager.BadTokenException(java.lang.String);
+  }
+
+  public static class WindowManager.InvalidDisplayException extends java.lang.RuntimeException {
+    ctor public WindowManager.InvalidDisplayException();
+    ctor public WindowManager.InvalidDisplayException(java.lang.String);
+  }
+
+  public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
+    ctor public WindowManager.LayoutParams();
+    ctor public WindowManager.LayoutParams(int);
+    ctor public WindowManager.LayoutParams(int, int);
+    ctor public WindowManager.LayoutParams(int, int, int);
+    ctor public WindowManager.LayoutParams(int, int, int, int, int);
+    ctor public WindowManager.LayoutParams(int, int, int, int, int, int, int);
+    ctor public WindowManager.LayoutParams(android.os.Parcel);
+    method public final int copyFrom(android.view.WindowManager.LayoutParams);
+    method public java.lang.String debug(java.lang.String);
+    method public int describeContents();
+    method public final java.lang.CharSequence getTitle();
+    method public static boolean mayUseInputMethod(int);
+    method public final void setTitle(java.lang.CharSequence);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ALPHA_CHANGED = 128; // 0x80
+    field public static final int ANIMATION_CHANGED = 16; // 0x10
+    field public static final float BRIGHTNESS_OVERRIDE_FULL = 1.0f;
+    field public static final float BRIGHTNESS_OVERRIDE_NONE = -1.0f;
+    field public static final float BRIGHTNESS_OVERRIDE_OFF = 0.0f;
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int DIM_AMOUNT_CHANGED = 32; // 0x20
+    field public static final int FIRST_APPLICATION_WINDOW = 1; // 0x1
+    field public static final int FIRST_SUB_WINDOW = 1000; // 0x3e8
+    field public static final int FIRST_SYSTEM_WINDOW = 2000; // 0x7d0
+    field public static final int FLAGS_CHANGED = 4; // 0x4
+    field public static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 1; // 0x1
+    field public static final int FLAG_ALT_FOCUSABLE_IM = 131072; // 0x20000
+    field public static final deprecated int FLAG_BLUR_BEHIND = 4; // 0x4
+    field public static final int FLAG_DIM_BEHIND = 2; // 0x2
+    field public static final int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000
+    field public static final deprecated int FLAG_DITHER = 4096; // 0x1000
+    field public static final int FLAG_FORCE_NOT_FULLSCREEN = 2048; // 0x800
+    field public static final int FLAG_FULLSCREEN = 1024; // 0x400
+    field public static final int FLAG_HARDWARE_ACCELERATED = 16777216; // 0x1000000
+    field public static final int FLAG_IGNORE_CHEEK_PRESSES = 32768; // 0x8000
+    field public static final int FLAG_KEEP_SCREEN_ON = 128; // 0x80
+    field public static final int FLAG_LAYOUT_INSET_DECOR = 65536; // 0x10000
+    field public static final int FLAG_LAYOUT_IN_SCREEN = 256; // 0x100
+    field public static final int FLAG_LAYOUT_NO_LIMITS = 512; // 0x200
+    field public static final int FLAG_NOT_FOCUSABLE = 8; // 0x8
+    field public static final int FLAG_NOT_TOUCHABLE = 16; // 0x10
+    field public static final int FLAG_NOT_TOUCH_MODAL = 32; // 0x20
+    field public static final int FLAG_SCALED = 16384; // 0x4000
+    field public static final int FLAG_SECURE = 8192; // 0x2000
+    field public static final int FLAG_SHOW_WALLPAPER = 1048576; // 0x100000
+    field public static final int FLAG_SHOW_WHEN_LOCKED = 524288; // 0x80000
+    field public static final int FLAG_SPLIT_TOUCH = 8388608; // 0x800000
+    field public static final int FLAG_TOUCHABLE_WHEN_WAKING = 64; // 0x40
+    field public static final int FLAG_TURN_SCREEN_ON = 2097152; // 0x200000
+    field public static final int FLAG_WATCH_OUTSIDE_TOUCH = 262144; // 0x40000
+    field public static final int FORMAT_CHANGED = 8; // 0x8
+    field public static final int LAST_APPLICATION_WINDOW = 99; // 0x63
+    field public static final int LAST_SUB_WINDOW = 1999; // 0x7cf
+    field public static final int LAST_SYSTEM_WINDOW = 2999; // 0xbb7
+    field public static final int LAYOUT_CHANGED = 1; // 0x1
+    field public static final int MEMORY_TYPE_CHANGED = 256; // 0x100
+    field public static final deprecated int MEMORY_TYPE_GPU = 2; // 0x2
+    field public static final deprecated int MEMORY_TYPE_HARDWARE = 1; // 0x1
+    field public static final deprecated int MEMORY_TYPE_NORMAL = 0; // 0x0
+    field public static final deprecated int MEMORY_TYPE_PUSH_BUFFERS = 3; // 0x3
+    field public static final int SCREEN_BRIGHTNESS_CHANGED = 2048; // 0x800
+    field public static final int SCREEN_ORIENTATION_CHANGED = 1024; // 0x400
+    field public static final int SOFT_INPUT_ADJUST_NOTHING = 48; // 0x30
+    field public static final int SOFT_INPUT_ADJUST_PAN = 32; // 0x20
+    field public static final int SOFT_INPUT_ADJUST_RESIZE = 16; // 0x10
+    field public static final int SOFT_INPUT_ADJUST_UNSPECIFIED = 0; // 0x0
+    field public static final int SOFT_INPUT_IS_FORWARD_NAVIGATION = 256; // 0x100
+    field public static final int SOFT_INPUT_MASK_ADJUST = 240; // 0xf0
+    field public static final int SOFT_INPUT_MASK_STATE = 15; // 0xf
+    field public static final int SOFT_INPUT_MODE_CHANGED = 512; // 0x200
+    field public static final int SOFT_INPUT_STATE_ALWAYS_HIDDEN = 3; // 0x3
+    field public static final int SOFT_INPUT_STATE_ALWAYS_VISIBLE = 5; // 0x5
+    field public static final int SOFT_INPUT_STATE_HIDDEN = 2; // 0x2
+    field public static final int SOFT_INPUT_STATE_UNCHANGED = 1; // 0x1
+    field public static final int SOFT_INPUT_STATE_UNSPECIFIED = 0; // 0x0
+    field public static final int SOFT_INPUT_STATE_VISIBLE = 4; // 0x4
+    field public static final int TITLE_CHANGED = 64; // 0x40
+    field public static final int TYPE_APPLICATION = 2; // 0x2
+    field public static final int TYPE_APPLICATION_ATTACHED_DIALOG = 1003; // 0x3eb
+    field public static final int TYPE_APPLICATION_MEDIA = 1001; // 0x3e9
+    field public static final int TYPE_APPLICATION_PANEL = 1000; // 0x3e8
+    field public static final int TYPE_APPLICATION_STARTING = 3; // 0x3
+    field public static final int TYPE_APPLICATION_SUB_PANEL = 1002; // 0x3ea
+    field public static final int TYPE_BASE_APPLICATION = 1; // 0x1
+    field public static final int TYPE_CHANGED = 2; // 0x2
+    field public static final int TYPE_INPUT_METHOD = 2011; // 0x7db
+    field public static final int TYPE_INPUT_METHOD_DIALOG = 2012; // 0x7dc
+    field public static final int TYPE_KEYGUARD = 2004; // 0x7d4
+    field public static final int TYPE_KEYGUARD_DIALOG = 2009; // 0x7d9
+    field public static final int TYPE_PHONE = 2002; // 0x7d2
+    field public static final int TYPE_PRIORITY_PHONE = 2007; // 0x7d7
+    field public static final int TYPE_SEARCH_BAR = 2001; // 0x7d1
+    field public static final int TYPE_STATUS_BAR = 2000; // 0x7d0
+    field public static final int TYPE_STATUS_BAR_PANEL = 2014; // 0x7de
+    field public static final int TYPE_SYSTEM_ALERT = 2003; // 0x7d3
+    field public static final int TYPE_SYSTEM_DIALOG = 2008; // 0x7d8
+    field public static final int TYPE_SYSTEM_ERROR = 2010; // 0x7da
+    field public static final int TYPE_SYSTEM_OVERLAY = 2006; // 0x7d6
+    field public static final int TYPE_TOAST = 2005; // 0x7d5
+    field public static final int TYPE_WALLPAPER = 2013; // 0x7dd
+    field public float alpha;
+    field public float buttonBrightness;
+    field public float dimAmount;
+    field public int flags;
+    field public int format;
+    field public int gravity;
+    field public float horizontalMargin;
+    field public float horizontalWeight;
+    field public deprecated int memoryType;
+    field public java.lang.String packageName;
+    field public float screenBrightness;
+    field public int screenOrientation;
+    field public int softInputMode;
+    field public int systemUiVisibility;
+    field public android.os.IBinder token;
+    field public int type;
+    field public float verticalMargin;
+    field public float verticalWeight;
+    field public int windowAnimations;
+    field public int x;
+    field public int y;
+  }
+
+}
+
+package android.view.accessibility {
+
+  public final class AccessibilityEvent extends android.view.accessibility.AccessibilityRecord implements android.os.Parcelable {
+    method public void appendRecord(android.view.accessibility.AccessibilityRecord);
+    method public int describeContents();
+    method public static java.lang.String eventTypeToString(int);
+    method public int getAction();
+    method public long getEventTime();
+    method public int getEventType();
+    method public int getMovementGranularity();
+    method public java.lang.CharSequence getPackageName();
+    method public android.view.accessibility.AccessibilityRecord getRecord(int);
+    method public int getRecordCount();
+    method public void initFromParcel(android.os.Parcel);
+    method public static android.view.accessibility.AccessibilityEvent obtain(int);
+    method public static android.view.accessibility.AccessibilityEvent obtain(android.view.accessibility.AccessibilityEvent);
+    method public static android.view.accessibility.AccessibilityEvent obtain();
+    method public void setAction(int);
+    method public void setEventTime(long);
+    method public void setEventType(int);
+    method public void setMovementGranularity(int);
+    method public void setPackageName(java.lang.CharSequence);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int INVALID_POSITION = -1; // 0xffffffff
+    field public static final deprecated int MAX_TEXT_LENGTH = 500; // 0x1f4
+    field public static final int TYPES_ALL_MASK = -1; // 0xffffffff
+    field public static final int TYPE_ANNOUNCEMENT = 16384; // 0x4000
+    field public static final int TYPE_GESTURE_DETECTION_END = 524288; // 0x80000
+    field public static final int TYPE_GESTURE_DETECTION_START = 262144; // 0x40000
+    field public static final int TYPE_NOTIFICATION_STATE_CHANGED = 64; // 0x40
+    field public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 1024; // 0x400
+    field public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 512; // 0x200
+    field public static final int TYPE_TOUCH_INTERACTION_END = 2097152; // 0x200000
+    field public static final int TYPE_TOUCH_INTERACTION_START = 1048576; // 0x100000
+    field public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 32768; // 0x8000
+    field public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 65536; // 0x10000
+    field public static final int TYPE_VIEW_CLICKED = 1; // 0x1
+    field public static final int TYPE_VIEW_FOCUSED = 8; // 0x8
+    field public static final int TYPE_VIEW_HOVER_ENTER = 128; // 0x80
+    field public static final int TYPE_VIEW_HOVER_EXIT = 256; // 0x100
+    field public static final int TYPE_VIEW_LONG_CLICKED = 2; // 0x2
+    field public static final int TYPE_VIEW_SCROLLED = 4096; // 0x1000
+    field public static final int TYPE_VIEW_SELECTED = 4; // 0x4
+    field public static final int TYPE_VIEW_TEXT_CHANGED = 16; // 0x10
+    field public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192; // 0x2000
+    field public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 131072; // 0x20000
+    field public static final int TYPE_WINDOW_CONTENT_CHANGED = 2048; // 0x800
+    field public static final int TYPE_WINDOW_STATE_CHANGED = 32; // 0x20
+  }
+
+  public abstract interface AccessibilityEventSource {
+    method public abstract void sendAccessibilityEvent(int);
+    method public abstract void sendAccessibilityEventUnchecked(android.view.accessibility.AccessibilityEvent);
+  }
+
+  public final class AccessibilityManager {
+    method public boolean addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener);
+    method public deprecated java.util.List<android.content.pm.ServiceInfo> getAccessibilityServiceList();
+    method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int);
+    method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
+    method public void interrupt();
+    method public boolean isEnabled();
+    method public boolean isTouchExplorationEnabled();
+    method public boolean removeAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener);
+    method public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+  }
+
+  public static abstract interface AccessibilityManager.AccessibilityStateChangeListener {
+    method public abstract void onAccessibilityStateChanged(boolean);
+  }
+
+  public class AccessibilityNodeInfo implements android.os.Parcelable {
+    method public void addAction(int);
+    method public void addChild(android.view.View);
+    method public void addChild(android.view.View, int);
+    method public int describeContents();
+    method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByText(java.lang.String);
+    method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
+    method public android.view.accessibility.AccessibilityNodeInfo focusSearch(int);
+    method public int getActions();
+    method public void getBoundsInParent(android.graphics.Rect);
+    method public void getBoundsInScreen(android.graphics.Rect);
+    method public android.view.accessibility.AccessibilityNodeInfo getChild(int);
+    method public int getChildCount();
+    method public java.lang.CharSequence getClassName();
+    method public java.lang.CharSequence getContentDescription();
+    method public android.view.accessibility.AccessibilityNodeInfo getLabelFor();
+    method public android.view.accessibility.AccessibilityNodeInfo getLabeledBy();
+    method public int getMovementGranularities();
+    method public java.lang.CharSequence getPackageName();
+    method public android.view.accessibility.AccessibilityNodeInfo getParent();
+    method public java.lang.CharSequence getText();
+    method public int getWindowId();
+    method public boolean isAccessibilityFocused();
+    method public boolean isCheckable();
+    method public boolean isChecked();
+    method public boolean isClickable();
+    method public boolean isEnabled();
+    method public boolean isFocusable();
+    method public boolean isFocused();
+    method public boolean isLongClickable();
+    method public boolean isPassword();
+    method public boolean isScrollable();
+    method public boolean isSelected();
+    method public boolean isVisibleToUser();
+    method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View);
+    method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View, int);
+    method public static android.view.accessibility.AccessibilityNodeInfo obtain();
+    method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.accessibility.AccessibilityNodeInfo);
+    method public boolean performAction(int);
+    method public boolean performAction(int, android.os.Bundle);
+    method public void recycle();
+    method public void setAccessibilityFocused(boolean);
+    method public void setBoundsInParent(android.graphics.Rect);
+    method public void setBoundsInScreen(android.graphics.Rect);
+    method public void setCheckable(boolean);
+    method public void setChecked(boolean);
+    method public void setClassName(java.lang.CharSequence);
+    method public void setClickable(boolean);
+    method public void setContentDescription(java.lang.CharSequence);
+    method public void setEnabled(boolean);
+    method public void setFocusable(boolean);
+    method public void setFocused(boolean);
+    method public void setLabelFor(android.view.View);
+    method public void setLabelFor(android.view.View, int);
+    method public void setLabeledBy(android.view.View);
+    method public void setLabeledBy(android.view.View, int);
+    method public void setLongClickable(boolean);
+    method public void setMovementGranularities(int);
+    method public void setPackageName(java.lang.CharSequence);
+    method public void setParent(android.view.View);
+    method public void setParent(android.view.View, int);
+    method public void setPassword(boolean);
+    method public void setScrollable(boolean);
+    method public void setSelected(boolean);
+    method public void setSource(android.view.View);
+    method public void setSource(android.view.View, int);
+    method public void setText(java.lang.CharSequence);
+    method public void setVisibleToUser(boolean);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
+    field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
+    field public static final java.lang.String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT = "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
+    field public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 128; // 0x80
+    field public static final int ACTION_CLEAR_FOCUS = 2; // 0x2
+    field public static final int ACTION_CLEAR_SELECTION = 8; // 0x8
+    field public static final int ACTION_CLICK = 16; // 0x10
+    field public static final int ACTION_FOCUS = 1; // 0x1
+    field public static final int ACTION_LONG_CLICK = 32; // 0x20
+    field public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 256; // 0x100
+    field public static final int ACTION_NEXT_HTML_ELEMENT = 1024; // 0x400
+    field public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 512; // 0x200
+    field public static final int ACTION_PREVIOUS_HTML_ELEMENT = 2048; // 0x800
+    field public static final int ACTION_SCROLL_BACKWARD = 8192; // 0x2000
+    field public static final int ACTION_SCROLL_FORWARD = 4096; // 0x1000
+    field public static final int ACTION_SELECT = 4; // 0x4
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2
+    field public static final int FOCUS_INPUT = 1; // 0x1
+    field public static final int MOVEMENT_GRANULARITY_CHARACTER = 1; // 0x1
+    field public static final int MOVEMENT_GRANULARITY_LINE = 4; // 0x4
+    field public static final int MOVEMENT_GRANULARITY_PAGE = 16; // 0x10
+    field public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 8; // 0x8
+    field public static final int MOVEMENT_GRANULARITY_WORD = 2; // 0x2
+  }
+
+  public abstract class AccessibilityNodeProvider {
+    ctor public AccessibilityNodeProvider();
+    method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo(int);
+    method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByText(java.lang.String, int);
+    method public boolean performAction(int, int, android.os.Bundle);
+  }
+
+  public class AccessibilityRecord {
+    method public int getAddedCount();
+    method public java.lang.CharSequence getBeforeText();
+    method public java.lang.CharSequence getClassName();
+    method public java.lang.CharSequence getContentDescription();
+    method public int getCurrentItemIndex();
+    method public int getFromIndex();
+    method public int getItemCount();
+    method public int getMaxScrollX();
+    method public int getMaxScrollY();
+    method public android.os.Parcelable getParcelableData();
+    method public int getRemovedCount();
+    method public int getScrollX();
+    method public int getScrollY();
+    method public android.view.accessibility.AccessibilityNodeInfo getSource();
+    method public java.util.List<java.lang.CharSequence> getText();
+    method public int getToIndex();
+    method public int getWindowId();
+    method public boolean isChecked();
+    method public boolean isEnabled();
+    method public boolean isFullScreen();
+    method public boolean isPassword();
+    method public boolean isScrollable();
+    method public static android.view.accessibility.AccessibilityRecord obtain(android.view.accessibility.AccessibilityRecord);
+    method public static android.view.accessibility.AccessibilityRecord obtain();
+    method public void recycle();
+    method public void setAddedCount(int);
+    method public void setBeforeText(java.lang.CharSequence);
+    method public void setChecked(boolean);
+    method public void setClassName(java.lang.CharSequence);
+    method public void setContentDescription(java.lang.CharSequence);
+    method public void setCurrentItemIndex(int);
+    method public void setEnabled(boolean);
+    method public void setFromIndex(int);
+    method public void setFullScreen(boolean);
+    method public void setItemCount(int);
+    method public void setMaxScrollX(int);
+    method public void setMaxScrollY(int);
+    method public void setParcelableData(android.os.Parcelable);
+    method public void setPassword(boolean);
+    method public void setRemovedCount(int);
+    method public void setScrollX(int);
+    method public void setScrollY(int);
+    method public void setScrollable(boolean);
+    method public void setSource(android.view.View);
+    method public void setSource(android.view.View, int);
+    method public void setToIndex(int);
+  }
+
+}
+
+package android.view.animation {
+
+  public class AccelerateDecelerateInterpolator implements android.view.animation.Interpolator {
+    ctor public AccelerateDecelerateInterpolator();
+    ctor public AccelerateDecelerateInterpolator(android.content.Context, android.util.AttributeSet);
+    method public float getInterpolation(float);
+  }
+
+  public class AccelerateInterpolator implements android.view.animation.Interpolator {
+    ctor public AccelerateInterpolator();
+    ctor public AccelerateInterpolator(float);
+    ctor public AccelerateInterpolator(android.content.Context, android.util.AttributeSet);
+    method public float getInterpolation(float);
+  }
+
+  public class AlphaAnimation extends android.view.animation.Animation {
+    ctor public AlphaAnimation(android.content.Context, android.util.AttributeSet);
+    ctor public AlphaAnimation(float, float);
+  }
+
+  public abstract class Animation implements java.lang.Cloneable {
+    ctor public Animation();
+    ctor public Animation(android.content.Context, android.util.AttributeSet);
+    method protected void applyTransformation(float, android.view.animation.Transformation);
+    method public void cancel();
+    method public long computeDurationHint();
+    method protected void ensureInterpolator();
+    method public int getBackgroundColor();
+    method public boolean getDetachWallpaper();
+    method public long getDuration();
+    method public boolean getFillAfter();
+    method public boolean getFillBefore();
+    method public android.view.animation.Interpolator getInterpolator();
+    method public int getRepeatCount();
+    method public int getRepeatMode();
+    method protected float getScaleFactor();
+    method public long getStartOffset();
+    method public long getStartTime();
+    method public boolean getTransformation(long, android.view.animation.Transformation);
+    method public boolean getTransformation(long, android.view.animation.Transformation, float);
+    method public int getZAdjustment();
+    method public boolean hasEnded();
+    method public boolean hasStarted();
+    method public void initialize(int, int, int, int);
+    method public boolean isFillEnabled();
+    method public boolean isInitialized();
+    method public void reset();
+    method protected float resolveSize(int, float, int, int);
+    method public void restrictDuration(long);
+    method public void scaleCurrentDuration(float);
+    method public void setAnimationListener(android.view.animation.Animation.AnimationListener);
+    method public void setBackgroundColor(int);
+    method public void setDetachWallpaper(boolean);
+    method public void setDuration(long);
+    method public void setFillAfter(boolean);
+    method public void setFillBefore(boolean);
+    method public void setFillEnabled(boolean);
+    method public void setInterpolator(android.content.Context, int);
+    method public void setInterpolator(android.view.animation.Interpolator);
+    method public void setRepeatCount(int);
+    method public void setRepeatMode(int);
+    method public void setStartOffset(long);
+    method public void setStartTime(long);
+    method public void setZAdjustment(int);
+    method public void start();
+    method public void startNow();
+    method public boolean willChangeBounds();
+    method public boolean willChangeTransformationMatrix();
+    field public static final int ABSOLUTE = 0; // 0x0
+    field public static final int INFINITE = -1; // 0xffffffff
+    field public static final int RELATIVE_TO_PARENT = 2; // 0x2
+    field public static final int RELATIVE_TO_SELF = 1; // 0x1
+    field public static final int RESTART = 1; // 0x1
+    field public static final int REVERSE = 2; // 0x2
+    field public static final int START_ON_FIRST_FRAME = -1; // 0xffffffff
+    field public static final int ZORDER_BOTTOM = -1; // 0xffffffff
+    field public static final int ZORDER_NORMAL = 0; // 0x0
+    field public static final int ZORDER_TOP = 1; // 0x1
+  }
+
+  public static abstract interface Animation.AnimationListener {
+    method public abstract void onAnimationEnd(android.view.animation.Animation);
+    method public abstract void onAnimationRepeat(android.view.animation.Animation);
+    method public abstract void onAnimationStart(android.view.animation.Animation);
+  }
+
+  protected static class Animation.Description {
+    ctor protected Animation.Description();
+    field public int type;
+    field public float value;
+  }
+
+  public class AnimationSet extends android.view.animation.Animation {
+    ctor public AnimationSet(android.content.Context, android.util.AttributeSet);
+    ctor public AnimationSet(boolean);
+    method public void addAnimation(android.view.animation.Animation);
+    method public java.util.List<android.view.animation.Animation> getAnimations();
+  }
+
+  public class AnimationUtils {
+    ctor public AnimationUtils();
+    method public static long currentAnimationTimeMillis();
+    method public static android.view.animation.Animation loadAnimation(android.content.Context, int) throws android.content.res.Resources.NotFoundException;
+    method public static android.view.animation.Interpolator loadInterpolator(android.content.Context, int) throws android.content.res.Resources.NotFoundException;
+    method public static android.view.animation.LayoutAnimationController loadLayoutAnimation(android.content.Context, int) throws android.content.res.Resources.NotFoundException;
+    method public static android.view.animation.Animation makeInAnimation(android.content.Context, boolean);
+    method public static android.view.animation.Animation makeInChildBottomAnimation(android.content.Context);
+    method public static android.view.animation.Animation makeOutAnimation(android.content.Context, boolean);
+  }
+
+  public class AnticipateInterpolator implements android.view.animation.Interpolator {
+    ctor public AnticipateInterpolator();
+    ctor public AnticipateInterpolator(float);
+    ctor public AnticipateInterpolator(android.content.Context, android.util.AttributeSet);
+    method public float getInterpolation(float);
+  }
+
+  public class AnticipateOvershootInterpolator implements android.view.animation.Interpolator {
+    ctor public AnticipateOvershootInterpolator();
+    ctor public AnticipateOvershootInterpolator(float);
+    ctor public AnticipateOvershootInterpolator(float, float);
+    ctor public AnticipateOvershootInterpolator(android.content.Context, android.util.AttributeSet);
+    method public float getInterpolation(float);
+  }
+
+  public class BounceInterpolator implements android.view.animation.Interpolator {
+    ctor public BounceInterpolator();
+    ctor public BounceInterpolator(android.content.Context, android.util.AttributeSet);
+    method public float getInterpolation(float);
+  }
+
+  public class CycleInterpolator implements android.view.animation.Interpolator {
+    ctor public CycleInterpolator(float);
+    ctor public CycleInterpolator(android.content.Context, android.util.AttributeSet);
+    method public float getInterpolation(float);
+  }
+
+  public class DecelerateInterpolator implements android.view.animation.Interpolator {
+    ctor public DecelerateInterpolator();
+    ctor public DecelerateInterpolator(float);
+    ctor public DecelerateInterpolator(android.content.Context, android.util.AttributeSet);
+    method public float getInterpolation(float);
+  }
+
+  public class GridLayoutAnimationController extends android.view.animation.LayoutAnimationController {
+    ctor public GridLayoutAnimationController(android.content.Context, android.util.AttributeSet);
+    ctor public GridLayoutAnimationController(android.view.animation.Animation);
+    ctor public GridLayoutAnimationController(android.view.animation.Animation, float, float);
+    method public float getColumnDelay();
+    method public int getDirection();
+    method public int getDirectionPriority();
+    method public float getRowDelay();
+    method public void setColumnDelay(float);
+    method public void setDirection(int);
+    method public void setDirectionPriority(int);
+    method public void setRowDelay(float);
+    field public static final int DIRECTION_BOTTOM_TO_TOP = 2; // 0x2
+    field public static final int DIRECTION_HORIZONTAL_MASK = 1; // 0x1
+    field public static final int DIRECTION_LEFT_TO_RIGHT = 0; // 0x0
+    field public static final int DIRECTION_RIGHT_TO_LEFT = 1; // 0x1
+    field public static final int DIRECTION_TOP_TO_BOTTOM = 0; // 0x0
+    field public static final int DIRECTION_VERTICAL_MASK = 2; // 0x2
+    field public static final int PRIORITY_COLUMN = 1; // 0x1
+    field public static final int PRIORITY_NONE = 0; // 0x0
+    field public static final int PRIORITY_ROW = 2; // 0x2
+  }
+
+  public static class GridLayoutAnimationController.AnimationParameters extends android.view.animation.LayoutAnimationController.AnimationParameters {
+    ctor public GridLayoutAnimationController.AnimationParameters();
+    field public int column;
+    field public int columnsCount;
+    field public int row;
+    field public int rowsCount;
+  }
+
+  public abstract interface Interpolator implements android.animation.TimeInterpolator {
+  }
+
+  public class LayoutAnimationController {
+    ctor public LayoutAnimationController(android.content.Context, android.util.AttributeSet);
+    ctor public LayoutAnimationController(android.view.animation.Animation);
+    ctor public LayoutAnimationController(android.view.animation.Animation, float);
+    method public android.view.animation.Animation getAnimation();
+    method public final android.view.animation.Animation getAnimationForView(android.view.View);
+    method public float getDelay();
+    method protected long getDelayForView(android.view.View);
+    method public android.view.animation.Interpolator getInterpolator();
+    method public int getOrder();
+    method protected int getTransformedIndex(android.view.animation.LayoutAnimationController.AnimationParameters);
+    method public boolean isDone();
+    method public void setAnimation(android.content.Context, int);
+    method public void setAnimation(android.view.animation.Animation);
+    method public void setDelay(float);
+    method public void setInterpolator(android.content.Context, int);
+    method public void setInterpolator(android.view.animation.Interpolator);
+    method public void setOrder(int);
+    method public void start();
+    method public boolean willOverlap();
+    field public static final int ORDER_NORMAL = 0; // 0x0
+    field public static final int ORDER_RANDOM = 2; // 0x2
+    field public static final int ORDER_REVERSE = 1; // 0x1
+    field protected android.view.animation.Animation mAnimation;
+    field protected android.view.animation.Interpolator mInterpolator;
+    field protected java.util.Random mRandomizer;
+  }
+
+  public static class LayoutAnimationController.AnimationParameters {
+    ctor public LayoutAnimationController.AnimationParameters();
+    field public int count;
+    field public int index;
+  }
+
+  public class LinearInterpolator implements android.view.animation.Interpolator {
+    ctor public LinearInterpolator();
+    ctor public LinearInterpolator(android.content.Context, android.util.AttributeSet);
+    method public float getInterpolation(float);
+  }
+
+  public class OvershootInterpolator implements android.view.animation.Interpolator {
+    ctor public OvershootInterpolator();
+    ctor public OvershootInterpolator(float);
+    ctor public OvershootInterpolator(android.content.Context, android.util.AttributeSet);
+    method public float getInterpolation(float);
+  }
+
+  public class RotateAnimation extends android.view.animation.Animation {
+    ctor public RotateAnimation(android.content.Context, android.util.AttributeSet);
+    ctor public RotateAnimation(float, float);
+    ctor public RotateAnimation(float, float, float, float);
+    ctor public RotateAnimation(float, float, int, float, int, float);
+  }
+
+  public class ScaleAnimation extends android.view.animation.Animation {
+    ctor public ScaleAnimation(android.content.Context, android.util.AttributeSet);
+    ctor public ScaleAnimation(float, float, float, float);
+    ctor public ScaleAnimation(float, float, float, float, float, float);
+    ctor public ScaleAnimation(float, float, float, float, int, float, int, float);
+  }
+
+  public class Transformation {
+    ctor public Transformation();
+    method public void clear();
+    method public void compose(android.view.animation.Transformation);
+    method public float getAlpha();
+    method public android.graphics.Matrix getMatrix();
+    method public int getTransformationType();
+    method public void set(android.view.animation.Transformation);
+    method public void setAlpha(float);
+    method public void setTransformationType(int);
+    method public java.lang.String toShortString();
+    field public static int TYPE_ALPHA;
+    field public static int TYPE_BOTH;
+    field public static int TYPE_IDENTITY;
+    field public static int TYPE_MATRIX;
+    field protected float mAlpha;
+    field protected android.graphics.Matrix mMatrix;
+    field protected int mTransformationType;
+  }
+
+  public class TranslateAnimation extends android.view.animation.Animation {
+    ctor public TranslateAnimation(android.content.Context, android.util.AttributeSet);
+    ctor public TranslateAnimation(float, float, float, float);
+    ctor public TranslateAnimation(int, float, int, float, int, float, int, float);
+  }
+
+}
+
+package android.view.inputmethod {
+
+  public class BaseInputConnection implements android.view.inputmethod.InputConnection {
+    ctor public BaseInputConnection(android.view.View, boolean);
+    method public boolean beginBatchEdit();
+    method public boolean clearMetaKeyStates(int);
+    method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+    method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
+    method public boolean commitText(java.lang.CharSequence, int);
+    method public boolean deleteSurroundingText(int, int);
+    method public boolean endBatchEdit();
+    method public boolean finishComposingText();
+    method public static int getComposingSpanEnd(android.text.Spannable);
+    method public static int getComposingSpanStart(android.text.Spannable);
+    method public int getCursorCapsMode(int);
+    method public android.text.Editable getEditable();
+    method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
+    method public java.lang.CharSequence getSelectedText(int);
+    method public java.lang.CharSequence getTextAfterCursor(int, int);
+    method public java.lang.CharSequence getTextBeforeCursor(int, int);
+    method public boolean performContextMenuAction(int);
+    method public boolean performEditorAction(int);
+    method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
+    method public static final void removeComposingSpans(android.text.Spannable);
+    method public boolean reportFullscreenMode(boolean);
+    method public boolean sendKeyEvent(android.view.KeyEvent);
+    method public boolean setComposingRegion(int, int);
+    method public static void setComposingSpans(android.text.Spannable);
+    method public boolean setComposingText(java.lang.CharSequence, int);
+    method public boolean setSelection(int, int);
+  }
+
+  public final class CompletionInfo implements android.os.Parcelable {
+    ctor public CompletionInfo(long, int, java.lang.CharSequence);
+    ctor public CompletionInfo(long, int, java.lang.CharSequence, java.lang.CharSequence);
+    method public int describeContents();
+    method public long getId();
+    method public java.lang.CharSequence getLabel();
+    method public int getPosition();
+    method public java.lang.CharSequence getText();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CorrectionInfo implements android.os.Parcelable {
+    ctor public CorrectionInfo(int, java.lang.CharSequence, java.lang.CharSequence);
+    method public int describeContents();
+    method public java.lang.CharSequence getNewText();
+    method public int getOffset();
+    method public java.lang.CharSequence getOldText();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class EditorInfo implements android.text.InputType android.os.Parcelable {
+    ctor public EditorInfo();
+    method public int describeContents();
+    method public void dump(android.util.Printer, java.lang.String);
+    method public final void makeCompatible(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int IME_ACTION_DONE = 6; // 0x6
+    field public static final int IME_ACTION_GO = 2; // 0x2
+    field public static final int IME_ACTION_NEXT = 5; // 0x5
+    field public static final int IME_ACTION_NONE = 1; // 0x1
+    field public static final int IME_ACTION_PREVIOUS = 7; // 0x7
+    field public static final int IME_ACTION_SEARCH = 3; // 0x3
+    field public static final int IME_ACTION_SEND = 4; // 0x4
+    field public static final int IME_ACTION_UNSPECIFIED = 0; // 0x0
+    field public static final int IME_FLAG_FORCE_ASCII = -2147483648; // 0x80000000
+    field public static final int IME_FLAG_NAVIGATE_NEXT = 134217728; // 0x8000000
+    field public static final int IME_FLAG_NAVIGATE_PREVIOUS = 67108864; // 0x4000000
+    field public static final int IME_FLAG_NO_ACCESSORY_ACTION = 536870912; // 0x20000000
+    field public static final int IME_FLAG_NO_ENTER_ACTION = 1073741824; // 0x40000000
+    field public static final int IME_FLAG_NO_EXTRACT_UI = 268435456; // 0x10000000
+    field public static final int IME_FLAG_NO_FULLSCREEN = 33554432; // 0x2000000
+    field public static final int IME_MASK_ACTION = 255; // 0xff
+    field public static final int IME_NULL = 0; // 0x0
+    field public int actionId;
+    field public java.lang.CharSequence actionLabel;
+    field public android.os.Bundle extras;
+    field public int fieldId;
+    field public java.lang.String fieldName;
+    field public java.lang.CharSequence hintText;
+    field public int imeOptions;
+    field public int initialCapsMode;
+    field public int initialSelEnd;
+    field public int initialSelStart;
+    field public int inputType;
+    field public java.lang.CharSequence label;
+    field public java.lang.String packageName;
+    field public java.lang.String privateImeOptions;
+  }
+
+  public class ExtractedText implements android.os.Parcelable {
+    ctor public ExtractedText();
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_SELECTING = 2; // 0x2
+    field public static final int FLAG_SINGLE_LINE = 1; // 0x1
+    field public int flags;
+    field public int partialEndOffset;
+    field public int partialStartOffset;
+    field public int selectionEnd;
+    field public int selectionStart;
+    field public int startOffset;
+    field public java.lang.CharSequence text;
+  }
+
+  public class ExtractedTextRequest implements android.os.Parcelable {
+    ctor public ExtractedTextRequest();
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public int flags;
+    field public int hintMaxChars;
+    field public int hintMaxLines;
+    field public int token;
+  }
+
+  public final class InputBinding implements android.os.Parcelable {
+    ctor public InputBinding(android.view.inputmethod.InputConnection, android.os.IBinder, int, int);
+    ctor public InputBinding(android.view.inputmethod.InputConnection, android.view.inputmethod.InputBinding);
+    method public int describeContents();
+    method public android.view.inputmethod.InputConnection getConnection();
+    method public android.os.IBinder getConnectionToken();
+    method public int getPid();
+    method public int getUid();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public abstract interface InputConnection {
+    method public abstract boolean beginBatchEdit();
+    method public abstract boolean clearMetaKeyStates(int);
+    method public abstract boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+    method public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
+    method public abstract boolean commitText(java.lang.CharSequence, int);
+    method public abstract boolean deleteSurroundingText(int, int);
+    method public abstract boolean endBatchEdit();
+    method public abstract boolean finishComposingText();
+    method public abstract int getCursorCapsMode(int);
+    method public abstract android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
+    method public abstract java.lang.CharSequence getSelectedText(int);
+    method public abstract java.lang.CharSequence getTextAfterCursor(int, int);
+    method public abstract java.lang.CharSequence getTextBeforeCursor(int, int);
+    method public abstract boolean performContextMenuAction(int);
+    method public abstract boolean performEditorAction(int);
+    method public abstract boolean performPrivateCommand(java.lang.String, android.os.Bundle);
+    method public abstract boolean reportFullscreenMode(boolean);
+    method public abstract boolean sendKeyEvent(android.view.KeyEvent);
+    method public abstract boolean setComposingRegion(int, int);
+    method public abstract boolean setComposingText(java.lang.CharSequence, int);
+    method public abstract boolean setSelection(int, int);
+    field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1
+    field public static final int GET_TEXT_WITH_STYLES = 1; // 0x1
+  }
+
+  public class InputConnectionWrapper implements android.view.inputmethod.InputConnection {
+    ctor public InputConnectionWrapper(android.view.inputmethod.InputConnection, boolean);
+    method public boolean beginBatchEdit();
+    method public boolean clearMetaKeyStates(int);
+    method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+    method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
+    method public boolean commitText(java.lang.CharSequence, int);
+    method public boolean deleteSurroundingText(int, int);
+    method public boolean endBatchEdit();
+    method public boolean finishComposingText();
+    method public int getCursorCapsMode(int);
+    method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
+    method public java.lang.CharSequence getSelectedText(int);
+    method public java.lang.CharSequence getTextAfterCursor(int, int);
+    method public java.lang.CharSequence getTextBeforeCursor(int, int);
+    method public boolean performContextMenuAction(int);
+    method public boolean performEditorAction(int);
+    method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
+    method public boolean reportFullscreenMode(boolean);
+    method public boolean sendKeyEvent(android.view.KeyEvent);
+    method public boolean setComposingRegion(int, int);
+    method public boolean setComposingText(java.lang.CharSequence, int);
+    method public boolean setSelection(int, int);
+    method public void setTarget(android.view.inputmethod.InputConnection);
+  }
+
+  public abstract interface InputMethod {
+    method public abstract void attachToken(android.os.IBinder);
+    method public abstract void bindInput(android.view.inputmethod.InputBinding);
+    method public abstract void changeInputMethodSubtype(android.view.inputmethod.InputMethodSubtype);
+    method public abstract void createSession(android.view.inputmethod.InputMethod.SessionCallback);
+    method public abstract void hideSoftInput(int, android.os.ResultReceiver);
+    method public abstract void restartInput(android.view.inputmethod.InputConnection, android.view.inputmethod.EditorInfo);
+    method public abstract void revokeSession(android.view.inputmethod.InputMethodSession);
+    method public abstract void setSessionEnabled(android.view.inputmethod.InputMethodSession, boolean);
+    method public abstract void showSoftInput(int, android.os.ResultReceiver);
+    method public abstract void startInput(android.view.inputmethod.InputConnection, android.view.inputmethod.EditorInfo);
+    method public abstract void unbindInput();
+    field public static final java.lang.String SERVICE_INTERFACE = "android.view.InputMethod";
+    field public static final java.lang.String SERVICE_META_DATA = "android.view.im";
+    field public static final int SHOW_EXPLICIT = 1; // 0x1
+    field public static final int SHOW_FORCED = 2; // 0x2
+  }
+
+  public static abstract interface InputMethod.SessionCallback {
+    method public abstract void sessionCreated(android.view.inputmethod.InputMethodSession);
+  }
+
+  public final class InputMethodInfo implements android.os.Parcelable {
+    ctor public InputMethodInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    ctor public InputMethodInfo(java.lang.String, java.lang.String, java.lang.CharSequence, java.lang.String);
+    method public int describeContents();
+    method public void dump(android.util.Printer, java.lang.String);
+    method public android.content.ComponentName getComponent();
+    method public java.lang.String getId();
+    method public int getIsDefaultResourceId();
+    method public java.lang.String getPackageName();
+    method public android.content.pm.ServiceInfo getServiceInfo();
+    method public java.lang.String getServiceName();
+    method public java.lang.String getSettingsActivity();
+    method public android.view.inputmethod.InputMethodSubtype getSubtypeAt(int);
+    method public int getSubtypeCount();
+    method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
+    method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class InputMethodManager {
+    method public void displayCompletions(android.view.View, android.view.inputmethod.CompletionInfo[]);
+    method public android.view.inputmethod.InputMethodSubtype getCurrentInputMethodSubtype();
+    method public java.util.List<android.view.inputmethod.InputMethodInfo> getEnabledInputMethodList();
+    method public java.util.List<android.view.inputmethod.InputMethodSubtype> getEnabledInputMethodSubtypeList(android.view.inputmethod.InputMethodInfo, boolean);
+    method public java.util.List<android.view.inputmethod.InputMethodInfo> getInputMethodList();
+    method public android.view.inputmethod.InputMethodSubtype getLastInputMethodSubtype();
+    method public java.util.Map<android.view.inputmethod.InputMethodInfo, java.util.List<android.view.inputmethod.InputMethodSubtype>> getShortcutInputMethodsAndSubtypes();
+    method public void hideSoftInputFromInputMethod(android.os.IBinder, int);
+    method public boolean hideSoftInputFromWindow(android.os.IBinder, int);
+    method public boolean hideSoftInputFromWindow(android.os.IBinder, int, android.os.ResultReceiver);
+    method public void hideStatusIcon(android.os.IBinder);
+    method public boolean isAcceptingText();
+    method public boolean isActive(android.view.View);
+    method public boolean isActive();
+    method public boolean isFullscreenMode();
+    method public boolean isWatchingCursor(android.view.View);
+    method public void restartInput(android.view.View);
+    method public void sendAppPrivateCommand(android.view.View, java.lang.String, android.os.Bundle);
+    method public void setAdditionalInputMethodSubtypes(java.lang.String, android.view.inputmethod.InputMethodSubtype[]);
+    method public boolean setCurrentInputMethodSubtype(android.view.inputmethod.InputMethodSubtype);
+    method public void setInputMethod(android.os.IBinder, java.lang.String);
+    method public void setInputMethodAndSubtype(android.os.IBinder, java.lang.String, android.view.inputmethod.InputMethodSubtype);
+    method public void showInputMethodAndSubtypeEnabler(java.lang.String);
+    method public void showInputMethodPicker();
+    method public boolean showSoftInput(android.view.View, int);
+    method public boolean showSoftInput(android.view.View, int, android.os.ResultReceiver);
+    method public void showSoftInputFromInputMethod(android.os.IBinder, int);
+    method public void showStatusIcon(android.os.IBinder, java.lang.String, int);
+    method public boolean switchToLastInputMethod(android.os.IBinder);
+    method public boolean switchToNextInputMethod(android.os.IBinder, boolean);
+    method public void toggleSoftInput(int, int);
+    method public void toggleSoftInputFromWindow(android.os.IBinder, int, int);
+    method public void updateCursor(android.view.View, int, int, int, int);
+    method public void updateExtractedText(android.view.View, int, android.view.inputmethod.ExtractedText);
+    method public void updateSelection(android.view.View, int, int, int, int);
+    method public void viewClicked(android.view.View);
+    field public static final int HIDE_IMPLICIT_ONLY = 1; // 0x1
+    field public static final int HIDE_NOT_ALWAYS = 2; // 0x2
+    field public static final int RESULT_HIDDEN = 3; // 0x3
+    field public static final int RESULT_SHOWN = 2; // 0x2
+    field public static final int RESULT_UNCHANGED_HIDDEN = 1; // 0x1
+    field public static final int RESULT_UNCHANGED_SHOWN = 0; // 0x0
+    field public static final int SHOW_FORCED = 2; // 0x2
+    field public static final int SHOW_IMPLICIT = 1; // 0x1
+  }
+
+  public abstract interface InputMethodSession {
+    method public abstract void appPrivateCommand(java.lang.String, android.os.Bundle);
+    method public abstract void dispatchGenericMotionEvent(int, android.view.MotionEvent, android.view.inputmethod.InputMethodSession.EventCallback);
+    method public abstract void dispatchKeyEvent(int, android.view.KeyEvent, android.view.inputmethod.InputMethodSession.EventCallback);
+    method public abstract void dispatchTrackballEvent(int, android.view.MotionEvent, android.view.inputmethod.InputMethodSession.EventCallback);
+    method public abstract void displayCompletions(android.view.inputmethod.CompletionInfo[]);
+    method public abstract void finishInput();
+    method public abstract void toggleSoftInput(int, int);
+    method public abstract void updateCursor(android.graphics.Rect);
+    method public abstract void updateExtractedText(int, android.view.inputmethod.ExtractedText);
+    method public abstract void updateSelection(int, int, int, int, int, int);
+    method public abstract void viewClicked(boolean);
+  }
+
+  public static abstract interface InputMethodSession.EventCallback {
+    method public abstract void finishedEvent(int, boolean);
+  }
+
+  public final class InputMethodSubtype implements android.os.Parcelable {
+    ctor public InputMethodSubtype(int, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean);
+    ctor public InputMethodSubtype(int, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean, int);
+    method public boolean containsExtraValueKey(java.lang.String);
+    method public int describeContents();
+    method public java.lang.CharSequence getDisplayName(android.content.Context, java.lang.String, android.content.pm.ApplicationInfo);
+    method public java.lang.String getExtraValue();
+    method public java.lang.String getExtraValueOf(java.lang.String);
+    method public int getIconResId();
+    method public java.lang.String getLocale();
+    method public java.lang.String getMode();
+    method public int getNameResId();
+    method public boolean isAuxiliary();
+    method public boolean overridesImplicitlyEnabledSubtype();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+}
+
+package android.view.textservice {
+
+  public final class SentenceSuggestionsInfo implements android.os.Parcelable {
+    ctor public SentenceSuggestionsInfo(android.view.textservice.SuggestionsInfo[], int[], int[]);
+    ctor public SentenceSuggestionsInfo(android.os.Parcel);
+    method public int describeContents();
+    method public int getLengthAt(int);
+    method public int getOffsetAt(int);
+    method public int getSuggestionsCount();
+    method public android.view.textservice.SuggestionsInfo getSuggestionsInfoAt(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class SpellCheckerInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.content.ComponentName getComponent();
+    method public java.lang.String getId();
+    method public java.lang.String getPackageName();
+    method public android.content.pm.ServiceInfo getServiceInfo();
+    method public java.lang.String getSettingsActivity();
+    method public android.view.textservice.SpellCheckerSubtype getSubtypeAt(int);
+    method public int getSubtypeCount();
+    method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
+    method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class SpellCheckerSession {
+    method public void cancel();
+    method public void close();
+    method public void getSentenceSuggestions(android.view.textservice.TextInfo[], int);
+    method public android.view.textservice.SpellCheckerInfo getSpellChecker();
+    method public deprecated void getSuggestions(android.view.textservice.TextInfo, int);
+    method public deprecated void getSuggestions(android.view.textservice.TextInfo[], int, boolean);
+    method public boolean isSessionDisconnected();
+    field public static final java.lang.String SERVICE_META_DATA = "android.view.textservice.scs";
+  }
+
+  public static abstract interface SpellCheckerSession.SpellCheckerSessionListener {
+    method public abstract void onGetSentenceSuggestions(android.view.textservice.SentenceSuggestionsInfo[]);
+    method public abstract void onGetSuggestions(android.view.textservice.SuggestionsInfo[]);
+  }
+
+  public final class SpellCheckerSubtype implements android.os.Parcelable {
+    ctor public SpellCheckerSubtype(int, java.lang.String, java.lang.String);
+    method public boolean containsExtraValueKey(java.lang.String);
+    method public int describeContents();
+    method public java.lang.CharSequence getDisplayName(android.content.Context, java.lang.String, android.content.pm.ApplicationInfo);
+    method public java.lang.String getExtraValue();
+    method public java.lang.String getExtraValueOf(java.lang.String);
+    method public java.lang.String getLocale();
+    method public int getNameResId();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class SuggestionsInfo implements android.os.Parcelable {
+    ctor public SuggestionsInfo(int, java.lang.String[]);
+    ctor public SuggestionsInfo(int, java.lang.String[], int, int);
+    ctor public SuggestionsInfo(android.os.Parcel);
+    method public int describeContents();
+    method public int getCookie();
+    method public int getSequence();
+    method public java.lang.String getSuggestionAt(int);
+    method public int getSuggestionsAttributes();
+    method public int getSuggestionsCount();
+    method public void setCookieAndSequence(int, int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = 4; // 0x4
+    field public static final int RESULT_ATTR_IN_THE_DICTIONARY = 1; // 0x1
+    field public static final int RESULT_ATTR_LOOKS_LIKE_TYPO = 2; // 0x2
+  }
+
+  public final class TextInfo implements android.os.Parcelable {
+    ctor public TextInfo(java.lang.String);
+    ctor public TextInfo(java.lang.String, int, int);
+    ctor public TextInfo(android.os.Parcel);
+    method public int describeContents();
+    method public int getCookie();
+    method public int getSequence();
+    method public java.lang.String getText();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class TextServicesManager {
+    method public android.view.textservice.SpellCheckerSession newSpellCheckerSession(android.os.Bundle, java.util.Locale, android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener, boolean);
+  }
+
+}
+
+package android.webkit {
+
+  public class ConsoleMessage {
+    ctor public ConsoleMessage(java.lang.String, java.lang.String, int, android.webkit.ConsoleMessage.MessageLevel);
+    method public int lineNumber();
+    method public java.lang.String message();
+    method public android.webkit.ConsoleMessage.MessageLevel messageLevel();
+    method public java.lang.String sourceId();
+  }
+
+  public static final class ConsoleMessage.MessageLevel extends java.lang.Enum {
+    method public static android.webkit.ConsoleMessage.MessageLevel valueOf(java.lang.String);
+    method public static final android.webkit.ConsoleMessage.MessageLevel[] values();
+    enum_constant public static final android.webkit.ConsoleMessage.MessageLevel DEBUG;
+    enum_constant public static final android.webkit.ConsoleMessage.MessageLevel ERROR;
+    enum_constant public static final android.webkit.ConsoleMessage.MessageLevel LOG;
+    enum_constant public static final android.webkit.ConsoleMessage.MessageLevel TIP;
+    enum_constant public static final android.webkit.ConsoleMessage.MessageLevel WARNING;
+  }
+
+  public class CookieManager {
+    method public synchronized boolean acceptCookie();
+    method public static boolean allowFileSchemeCookies();
+    method public java.lang.String getCookie(java.lang.String);
+    method public static synchronized android.webkit.CookieManager getInstance();
+    method public synchronized boolean hasCookies();
+    method public void removeAllCookie();
+    method public void removeExpiredCookie();
+    method public void removeSessionCookie();
+    method public synchronized void setAcceptCookie(boolean);
+    method public static void setAcceptFileSchemeCookies(boolean);
+    method public void setCookie(java.lang.String, java.lang.String);
+  }
+
+  public final class CookieSyncManager extends android.webkit.WebSyncManager {
+    method public static synchronized android.webkit.CookieSyncManager createInstance(android.content.Context);
+    method public static synchronized android.webkit.CookieSyncManager getInstance();
+    method protected void syncFromRamToFlash();
+  }
+
+  public class DateSorter {
+    ctor public DateSorter(android.content.Context);
+    method public long getBoundary(int);
+    method public int getIndex(long);
+    method public java.lang.String getLabel(int);
+    field public static final int DAY_COUNT = 5; // 0x5
+  }
+
+  public abstract interface DownloadListener {
+    method public abstract void onDownloadStart(java.lang.String, java.lang.String, java.lang.String, java.lang.String, long);
+  }
+
+  public class GeolocationPermissions {
+    method public void allow(java.lang.String);
+    method public void clear(java.lang.String);
+    method public void clearAll();
+    method public void getAllowed(java.lang.String, android.webkit.ValueCallback<java.lang.Boolean>);
+    method public static android.webkit.GeolocationPermissions getInstance();
+    method public void getOrigins(android.webkit.ValueCallback<java.util.Set<java.lang.String>>);
+  }
+
+  public static abstract interface GeolocationPermissions.Callback {
+    method public abstract void invoke(java.lang.String, boolean, boolean);
+  }
+
+  public class HttpAuthHandler extends android.os.Handler {
+    method public void cancel();
+    method public void proceed(java.lang.String, java.lang.String);
+    method public boolean useHttpAuthUsernamePassword();
+  }
+
+  public abstract class JavascriptInterface implements java.lang.annotation.Annotation {
+  }
+
+  public class JsPromptResult extends android.webkit.JsResult {
+    method public void confirm(java.lang.String);
+  }
+
+  public class JsResult {
+    method public final void cancel();
+    method public final void confirm();
+  }
+
+  public class MimeTypeMap {
+    method public java.lang.String getExtensionFromMimeType(java.lang.String);
+    method public static java.lang.String getFileExtensionFromUrl(java.lang.String);
+    method public java.lang.String getMimeTypeFromExtension(java.lang.String);
+    method public static android.webkit.MimeTypeMap getSingleton();
+    method public boolean hasExtension(java.lang.String);
+    method public boolean hasMimeType(java.lang.String);
+  }
+
+  public abstract interface PluginStub {
+    method public abstract android.view.View getEmbeddedView(int, android.content.Context);
+    method public abstract android.view.View getFullScreenView(int, android.content.Context);
+  }
+
+  public class SslErrorHandler extends android.os.Handler {
+    method public void cancel();
+    method public void proceed();
+  }
+
+  public final class URLUtil {
+    ctor public URLUtil();
+    method public static java.lang.String composeSearchUrl(java.lang.String, java.lang.String, java.lang.String);
+    method public static byte[] decode(byte[]) throws java.lang.IllegalArgumentException;
+    method public static final java.lang.String guessFileName(java.lang.String, java.lang.String, java.lang.String);
+    method public static java.lang.String guessUrl(java.lang.String);
+    method public static boolean isAboutUrl(java.lang.String);
+    method public static boolean isAssetUrl(java.lang.String);
+    method public static boolean isContentUrl(java.lang.String);
+    method public static deprecated boolean isCookielessProxyUrl(java.lang.String);
+    method public static boolean isDataUrl(java.lang.String);
+    method public static boolean isFileUrl(java.lang.String);
+    method public static boolean isHttpUrl(java.lang.String);
+    method public static boolean isHttpsUrl(java.lang.String);
+    method public static boolean isJavaScriptUrl(java.lang.String);
+    method public static boolean isNetworkUrl(java.lang.String);
+    method public static boolean isValidUrl(java.lang.String);
+    method public static java.lang.String stripAnchor(java.lang.String);
+  }
+
+  public abstract interface ValueCallback {
+    method public abstract void onReceiveValue(T);
+  }
+
+  public class WebBackForwardList implements java.lang.Cloneable java.io.Serializable {
+    method public synchronized int getCurrentIndex();
+    method public synchronized android.webkit.WebHistoryItem getCurrentItem();
+    method public synchronized android.webkit.WebHistoryItem getItemAtIndex(int);
+    method public synchronized int getSize();
+  }
+
+  public class WebChromeClient {
+    ctor public WebChromeClient();
+    method public android.graphics.Bitmap getDefaultVideoPoster();
+    method public android.view.View getVideoLoadingProgressView();
+    method public void getVisitedHistory(android.webkit.ValueCallback<java.lang.String[]>);
+    method public void onCloseWindow(android.webkit.WebView);
+    method public deprecated void onConsoleMessage(java.lang.String, int, java.lang.String);
+    method public boolean onConsoleMessage(android.webkit.ConsoleMessage);
+    method public boolean onCreateWindow(android.webkit.WebView, boolean, boolean, android.os.Message);
+    method public void onExceededDatabaseQuota(java.lang.String, java.lang.String, long, long, long, android.webkit.WebStorage.QuotaUpdater);
+    method public void onGeolocationPermissionsHidePrompt();
+    method public void onGeolocationPermissionsShowPrompt(java.lang.String, android.webkit.GeolocationPermissions.Callback);
+    method public void onHideCustomView();
+    method public boolean onJsAlert(android.webkit.WebView, java.lang.String, java.lang.String, android.webkit.JsResult);
+    method public boolean onJsBeforeUnload(android.webkit.WebView, java.lang.String, java.lang.String, android.webkit.JsResult);
+    method public boolean onJsConfirm(android.webkit.WebView, java.lang.String, java.lang.String, android.webkit.JsResult);
+    method public boolean onJsPrompt(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String, android.webkit.JsPromptResult);
+    method public deprecated boolean onJsTimeout();
+    method public void onProgressChanged(android.webkit.WebView, int);
+    method public void onReachedMaxAppCacheSize(long, long, android.webkit.WebStorage.QuotaUpdater);
+    method public void onReceivedIcon(android.webkit.WebView, android.graphics.Bitmap);
+    method public void onReceivedTitle(android.webkit.WebView, java.lang.String);
+    method public void onReceivedTouchIconUrl(android.webkit.WebView, java.lang.String, boolean);
+    method public void onRequestFocus(android.webkit.WebView);
+    method public void onShowCustomView(android.view.View, android.webkit.WebChromeClient.CustomViewCallback);
+    method public void onShowCustomView(android.view.View, int, android.webkit.WebChromeClient.CustomViewCallback);
+  }
+
+  public static abstract interface WebChromeClient.CustomViewCallback {
+    method public abstract void onCustomViewHidden();
+  }
+
+  public class WebHistoryItem implements java.lang.Cloneable {
+    method public android.graphics.Bitmap getFavicon();
+    method public java.lang.String getOriginalUrl();
+    method public java.lang.String getTitle();
+    method public java.lang.String getUrl();
+  }
+
+  public class WebIconDatabase {
+    method public void close();
+    method public static android.webkit.WebIconDatabase getInstance();
+    method public void open(java.lang.String);
+    method public void releaseIconForPageUrl(java.lang.String);
+    method public void removeAllIcons();
+    method public void requestIconForPageUrl(java.lang.String, android.webkit.WebIconDatabase.IconListener);
+    method public void retainIconForPageUrl(java.lang.String);
+  }
+
+  public static abstract interface WebIconDatabase.IconListener {
+    method public abstract void onReceivedIcon(java.lang.String, android.graphics.Bitmap);
+  }
+
+  public class WebResourceResponse {
+    ctor public WebResourceResponse(java.lang.String, java.lang.String, java.io.InputStream);
+    method public java.io.InputStream getData();
+    method public java.lang.String getEncoding();
+    method public java.lang.String getMimeType();
+    method public void setData(java.io.InputStream);
+    method public void setEncoding(java.lang.String);
+    method public void setMimeType(java.lang.String);
+  }
+
+  public abstract class WebSettings {
+    method public deprecated boolean enableSmoothTransition();
+    method public boolean getAllowContentAccess();
+    method public boolean getAllowFileAccess();
+    method public abstract boolean getAllowFileAccessFromFileURLs();
+    method public abstract boolean getAllowUniversalAccessFromFileURLs();
+    method public synchronized boolean getBlockNetworkImage();
+    method public synchronized boolean getBlockNetworkLoads();
+    method public boolean getBuiltInZoomControls();
+    method public int getCacheMode();
+    method public synchronized java.lang.String getCursiveFontFamily();
+    method public synchronized boolean getDatabaseEnabled();
+    method public synchronized java.lang.String getDatabasePath();
+    method public synchronized int getDefaultFixedFontSize();
+    method public synchronized int getDefaultFontSize();
+    method public synchronized java.lang.String getDefaultTextEncodingName();
+    method public static java.lang.String getDefaultUserAgent(android.content.Context);
+    method public android.webkit.WebSettings.ZoomDensity getDefaultZoom();
+    method public boolean getDisplayZoomControls();
+    method public synchronized boolean getDomStorageEnabled();
+    method public synchronized java.lang.String getFantasyFontFamily();
+    method public synchronized java.lang.String getFixedFontFamily();
+    method public synchronized boolean getJavaScriptCanOpenWindowsAutomatically();
+    method public synchronized boolean getJavaScriptEnabled();
+    method public synchronized android.webkit.WebSettings.LayoutAlgorithm getLayoutAlgorithm();
+    method public boolean getLightTouchEnabled();
+    method public boolean getLoadWithOverviewMode();
+    method public synchronized boolean getLoadsImagesAutomatically();
+    method public boolean getMediaPlaybackRequiresUserGesture();
+    method public synchronized int getMinimumFontSize();
+    method public synchronized int getMinimumLogicalFontSize();
+    method public synchronized android.webkit.WebSettings.PluginState getPluginState();
+    method public deprecated synchronized boolean getPluginsEnabled();
+    method public deprecated synchronized java.lang.String getPluginsPath();
+    method public synchronized java.lang.String getSansSerifFontFamily();
+    method public boolean getSaveFormData();
+    method public boolean getSavePassword();
+    method public synchronized java.lang.String getSerifFontFamily();
+    method public synchronized java.lang.String getStandardFontFamily();
+    method public deprecated synchronized android.webkit.WebSettings.TextSize getTextSize();
+    method public synchronized int getTextZoom();
+    method public synchronized boolean getUseWideViewPort();
+    method public synchronized java.lang.String getUserAgentString();
+    method public void setAllowContentAccess(boolean);
+    method public void setAllowFileAccess(boolean);
+    method public abstract void setAllowFileAccessFromFileURLs(boolean);
+    method public abstract void setAllowUniversalAccessFromFileURLs(boolean);
+    method public synchronized void setAppCacheEnabled(boolean);
+    method public synchronized void setAppCacheMaxSize(long);
+    method public synchronized void setAppCachePath(java.lang.String);
+    method public synchronized void setBlockNetworkImage(boolean);
+    method public synchronized void setBlockNetworkLoads(boolean);
+    method public void setBuiltInZoomControls(boolean);
+    method public void setCacheMode(int);
+    method public synchronized void setCursiveFontFamily(java.lang.String);
+    method public synchronized void setDatabaseEnabled(boolean);
+    method public synchronized void setDatabasePath(java.lang.String);
+    method public synchronized void setDefaultFixedFontSize(int);
+    method public synchronized void setDefaultFontSize(int);
+    method public synchronized void setDefaultTextEncodingName(java.lang.String);
+    method public void setDefaultZoom(android.webkit.WebSettings.ZoomDensity);
+    method public void setDisplayZoomControls(boolean);
+    method public synchronized void setDomStorageEnabled(boolean);
+    method public deprecated void setEnableSmoothTransition(boolean);
+    method public synchronized void setFantasyFontFamily(java.lang.String);
+    method public synchronized void setFixedFontFamily(java.lang.String);
+    method public synchronized void setGeolocationDatabasePath(java.lang.String);
+    method public synchronized void setGeolocationEnabled(boolean);
+    method public synchronized void setJavaScriptCanOpenWindowsAutomatically(boolean);
+    method public synchronized void setJavaScriptEnabled(boolean);
+    method public synchronized void setLayoutAlgorithm(android.webkit.WebSettings.LayoutAlgorithm);
+    method public void setLightTouchEnabled(boolean);
+    method public void setLoadWithOverviewMode(boolean);
+    method public synchronized void setLoadsImagesAutomatically(boolean);
+    method public void setMediaPlaybackRequiresUserGesture(boolean);
+    method public synchronized void setMinimumFontSize(int);
+    method public synchronized void setMinimumLogicalFontSize(int);
+    method public void setNeedInitialFocus(boolean);
+    method public synchronized void setPluginState(android.webkit.WebSettings.PluginState);
+    method public deprecated synchronized void setPluginsEnabled(boolean);
+    method public deprecated synchronized void setPluginsPath(java.lang.String);
+    method public synchronized void setRenderPriority(android.webkit.WebSettings.RenderPriority);
+    method public synchronized void setSansSerifFontFamily(java.lang.String);
+    method public void setSaveFormData(boolean);
+    method public void setSavePassword(boolean);
+    method public synchronized void setSerifFontFamily(java.lang.String);
+    method public synchronized void setStandardFontFamily(java.lang.String);
+    method public synchronized void setSupportMultipleWindows(boolean);
+    method public void setSupportZoom(boolean);
+    method public deprecated synchronized void setTextSize(android.webkit.WebSettings.TextSize);
+    method public synchronized void setTextZoom(int);
+    method public synchronized void setUseWideViewPort(boolean);
+    method public synchronized void setUserAgentString(java.lang.String);
+    method public synchronized boolean supportMultipleWindows();
+    method public boolean supportZoom();
+    field public static final int LOAD_CACHE_ELSE_NETWORK = 1; // 0x1
+    field public static final int LOAD_CACHE_ONLY = 3; // 0x3
+    field public static final int LOAD_DEFAULT = -1; // 0xffffffff
+    field public static final deprecated int LOAD_NORMAL = 0; // 0x0
+    field public static final int LOAD_NO_CACHE = 2; // 0x2
+  }
+
+  public static final class WebSettings.LayoutAlgorithm extends java.lang.Enum {
+    method public static android.webkit.WebSettings.LayoutAlgorithm valueOf(java.lang.String);
+    method public static final android.webkit.WebSettings.LayoutAlgorithm[] values();
+    enum_constant public static final android.webkit.WebSettings.LayoutAlgorithm NARROW_COLUMNS;
+    enum_constant public static final android.webkit.WebSettings.LayoutAlgorithm NORMAL;
+    enum_constant public static final deprecated android.webkit.WebSettings.LayoutAlgorithm SINGLE_COLUMN;
+  }
+
+  public static final class WebSettings.PluginState extends java.lang.Enum {
+    method public static android.webkit.WebSettings.PluginState valueOf(java.lang.String);
+    method public static final android.webkit.WebSettings.PluginState[] values();
+    enum_constant public static final android.webkit.WebSettings.PluginState OFF;
+    enum_constant public static final android.webkit.WebSettings.PluginState ON;
+    enum_constant public static final android.webkit.WebSettings.PluginState ON_DEMAND;
+  }
+
+  public static final class WebSettings.RenderPriority extends java.lang.Enum {
+    method public static android.webkit.WebSettings.RenderPriority valueOf(java.lang.String);
+    method public static final android.webkit.WebSettings.RenderPriority[] values();
+    enum_constant public static final android.webkit.WebSettings.RenderPriority HIGH;
+    enum_constant public static final android.webkit.WebSettings.RenderPriority LOW;
+    enum_constant public static final android.webkit.WebSettings.RenderPriority NORMAL;
+  }
+
+  public static final deprecated class WebSettings.TextSize extends java.lang.Enum {
+    method public static android.webkit.WebSettings.TextSize valueOf(java.lang.String);
+    method public static final android.webkit.WebSettings.TextSize[] values();
+    enum_constant public static final android.webkit.WebSettings.TextSize LARGER;
+    enum_constant public static final android.webkit.WebSettings.TextSize LARGEST;
+    enum_constant public static final android.webkit.WebSettings.TextSize NORMAL;
+    enum_constant public static final android.webkit.WebSettings.TextSize SMALLER;
+    enum_constant public static final android.webkit.WebSettings.TextSize SMALLEST;
+  }
+
+  public static final class WebSettings.ZoomDensity extends java.lang.Enum {
+    method public static android.webkit.WebSettings.ZoomDensity valueOf(java.lang.String);
+    method public static final android.webkit.WebSettings.ZoomDensity[] values();
+    enum_constant public static final android.webkit.WebSettings.ZoomDensity CLOSE;
+    enum_constant public static final android.webkit.WebSettings.ZoomDensity FAR;
+    enum_constant public static final android.webkit.WebSettings.ZoomDensity MEDIUM;
+  }
+
+  public class WebStorage {
+    method public void deleteAllData();
+    method public void deleteOrigin(java.lang.String);
+    method public static android.webkit.WebStorage getInstance();
+    method public void getOrigins(android.webkit.ValueCallback<java.util.Map>);
+    method public void getQuotaForOrigin(java.lang.String, android.webkit.ValueCallback<java.lang.Long>);
+    method public void getUsageForOrigin(java.lang.String, android.webkit.ValueCallback<java.lang.Long>);
+    method public void setQuotaForOrigin(java.lang.String, long);
+  }
+
+  public static class WebStorage.Origin {
+    method public java.lang.String getOrigin();
+    method public long getQuota();
+    method public long getUsage();
+  }
+
+  public static abstract interface WebStorage.QuotaUpdater {
+    method public abstract void updateQuota(long);
+  }
+
+   abstract class WebSyncManager implements java.lang.Runnable {
+    ctor protected WebSyncManager(android.content.Context, java.lang.String);
+    method protected void onSyncInit();
+    method public void resetSync();
+    method public void run();
+    method public void startSync();
+    method public void stopSync();
+    method public void sync();
+    field protected static final java.lang.String LOGTAG = "websync";
+    field protected android.webkit.WebViewDatabase mDataBase;
+    field protected android.os.Handler mHandler;
+  }
+
+  public class WebView extends android.widget.AbsoluteLayout implements android.view.ViewGroup.OnHierarchyChangeListener android.view.ViewTreeObserver.OnGlobalFocusChangeListener {
+    ctor public WebView(android.content.Context);
+    ctor public WebView(android.content.Context, android.util.AttributeSet);
+    ctor public WebView(android.content.Context, android.util.AttributeSet, int);
+    ctor public deprecated WebView(android.content.Context, android.util.AttributeSet, int, boolean);
+    method public void addJavascriptInterface(java.lang.Object, java.lang.String);
+    method public boolean canGoBack();
+    method public boolean canGoBackOrForward(int);
+    method public boolean canGoForward();
+    method public deprecated boolean canZoomIn();
+    method public deprecated boolean canZoomOut();
+    method public android.graphics.Picture capturePicture();
+    method public void clearCache(boolean);
+    method public void clearFormData();
+    method public void clearHistory();
+    method public void clearMatches();
+    method public void clearSslPreferences();
+    method public void clearView();
+    method public android.webkit.WebBackForwardList copyBackForwardList();
+    method public void destroy();
+    method public void documentHasImages(android.os.Message);
+    method public static java.lang.String findAddress(java.lang.String);
+    method public deprecated int findAll(java.lang.String);
+    method public void findAllAsync(java.lang.String);
+    method public void findNext(boolean);
+    method public void flingScroll(int, int);
+    method public void freeMemory();
+    method public android.net.http.SslCertificate getCertificate();
+    method public int getContentHeight();
+    method public android.graphics.Bitmap getFavicon();
+    method public android.webkit.WebView.HitTestResult getHitTestResult();
+    method public java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
+    method public java.lang.String getOriginalUrl();
+    method public int getProgress();
+    method public deprecated float getScale();
+    method public android.webkit.WebSettings getSettings();
+    method public java.lang.String getTitle();
+    method public java.lang.String getUrl();
+    method public void goBack();
+    method public void goBackOrForward(int);
+    method public void goForward();
+    method public void invokeZoomPicker();
+    method public boolean isPrivateBrowsingEnabled();
+    method public void loadData(java.lang.String, java.lang.String, java.lang.String);
+    method public void loadDataWithBaseURL(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public void loadUrl(java.lang.String, java.util.Map<java.lang.String, java.lang.String>);
+    method public void loadUrl(java.lang.String);
+    method public deprecated void onChildViewAdded(android.view.View, android.view.View);
+    method public deprecated void onChildViewRemoved(android.view.View, android.view.View);
+    method public deprecated void onGlobalFocusChanged(android.view.View, android.view.View);
+    method public void onPause();
+    method public void onResume();
+    method public boolean overlayHorizontalScrollbar();
+    method public boolean overlayVerticalScrollbar();
+    method public boolean pageDown(boolean);
+    method public boolean pageUp(boolean);
+    method public void pauseTimers();
+    method public void postUrl(java.lang.String, byte[]);
+    method public void reload();
+    method public void removeJavascriptInterface(java.lang.String);
+    method public void requestFocusNodeHref(android.os.Message);
+    method public void requestImageRef(android.os.Message);
+    method public android.webkit.WebBackForwardList restoreState(android.os.Bundle);
+    method public void resumeTimers();
+    method public void savePassword(java.lang.String, java.lang.String, java.lang.String);
+    method public android.webkit.WebBackForwardList saveState(android.os.Bundle);
+    method public void saveWebArchive(java.lang.String);
+    method public void saveWebArchive(java.lang.String, boolean, android.webkit.ValueCallback<java.lang.String>);
+    method public deprecated void setCertificate(android.net.http.SslCertificate);
+    method public void setDownloadListener(android.webkit.DownloadListener);
+    method public void setFindListener(android.webkit.WebView.FindListener);
+    method public void setHorizontalScrollbarOverlay(boolean);
+    method public void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public void setInitialScale(int);
+    method public deprecated void setMapTrackballToArrowKeys(boolean);
+    method public void setNetworkAvailable(boolean);
+    method public deprecated void setPictureListener(android.webkit.WebView.PictureListener);
+    method public void setVerticalScrollbarOverlay(boolean);
+    method public void setWebChromeClient(android.webkit.WebChromeClient);
+    method public void setWebViewClient(android.webkit.WebViewClient);
+    method public boolean showFindDialog(java.lang.String, boolean);
+    method public void stopLoading();
+    method public boolean zoomIn();
+    method public boolean zoomOut();
+    field public static final java.lang.String SCHEME_GEO = "geo:0,0?q=";
+    field public static final java.lang.String SCHEME_MAILTO = "mailto:";
+    field public static final java.lang.String SCHEME_TEL = "tel:";
+  }
+
+  public static abstract interface WebView.FindListener {
+    method public abstract void onFindResultReceived(int, int, boolean);
+  }
+
+  public static class WebView.HitTestResult {
+    method public java.lang.String getExtra();
+    method public int getType();
+    field public static final deprecated int ANCHOR_TYPE = 1; // 0x1
+    field public static final int EDIT_TEXT_TYPE = 9; // 0x9
+    field public static final int EMAIL_TYPE = 4; // 0x4
+    field public static final int GEO_TYPE = 3; // 0x3
+    field public static final deprecated int IMAGE_ANCHOR_TYPE = 6; // 0x6
+    field public static final int IMAGE_TYPE = 5; // 0x5
+    field public static final int PHONE_TYPE = 2; // 0x2
+    field public static final int SRC_ANCHOR_TYPE = 7; // 0x7
+    field public static final int SRC_IMAGE_ANCHOR_TYPE = 8; // 0x8
+    field public static final int UNKNOWN_TYPE = 0; // 0x0
+  }
+
+  public static abstract deprecated interface WebView.PictureListener {
+    method public abstract deprecated void onNewPicture(android.webkit.WebView, android.graphics.Picture);
+  }
+
+  public class WebView.WebViewTransport {
+    ctor public WebView.WebViewTransport();
+    method public synchronized android.webkit.WebView getWebView();
+    method public synchronized void setWebView(android.webkit.WebView);
+  }
+
+  public class WebViewClient {
+    ctor public WebViewClient();
+    method public void doUpdateVisitedHistory(android.webkit.WebView, java.lang.String, boolean);
+    method public void onFormResubmission(android.webkit.WebView, android.os.Message, android.os.Message);
+    method public void onLoadResource(android.webkit.WebView, java.lang.String);
+    method public void onPageFinished(android.webkit.WebView, java.lang.String);
+    method public void onPageStarted(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
+    method public void onReceivedError(android.webkit.WebView, int, java.lang.String, java.lang.String);
+    method public void onReceivedHttpAuthRequest(android.webkit.WebView, android.webkit.HttpAuthHandler, java.lang.String, java.lang.String);
+    method public void onReceivedLoginRequest(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String);
+    method public void onReceivedSslError(android.webkit.WebView, android.webkit.SslErrorHandler, android.net.http.SslError);
+    method public void onScaleChanged(android.webkit.WebView, float, float);
+    method public deprecated void onTooManyRedirects(android.webkit.WebView, android.os.Message, android.os.Message);
+    method public void onUnhandledKeyEvent(android.webkit.WebView, android.view.KeyEvent);
+    method public android.webkit.WebResourceResponse shouldInterceptRequest(android.webkit.WebView, java.lang.String);
+    method public boolean shouldOverrideKeyEvent(android.webkit.WebView, android.view.KeyEvent);
+    method public boolean shouldOverrideUrlLoading(android.webkit.WebView, java.lang.String);
+    field public static final int ERROR_AUTHENTICATION = -4; // 0xfffffffc
+    field public static final int ERROR_BAD_URL = -12; // 0xfffffff4
+    field public static final int ERROR_CONNECT = -6; // 0xfffffffa
+    field public static final int ERROR_FAILED_SSL_HANDSHAKE = -11; // 0xfffffff5
+    field public static final int ERROR_FILE = -13; // 0xfffffff3
+    field public static final int ERROR_FILE_NOT_FOUND = -14; // 0xfffffff2
+    field public static final int ERROR_HOST_LOOKUP = -2; // 0xfffffffe
+    field public static final int ERROR_IO = -7; // 0xfffffff9
+    field public static final int ERROR_PROXY_AUTHENTICATION = -5; // 0xfffffffb
+    field public static final int ERROR_REDIRECT_LOOP = -9; // 0xfffffff7
+    field public static final int ERROR_TIMEOUT = -8; // 0xfffffff8
+    field public static final int ERROR_TOO_MANY_REQUESTS = -15; // 0xfffffff1
+    field public static final int ERROR_UNKNOWN = -1; // 0xffffffff
+    field public static final int ERROR_UNSUPPORTED_AUTH_SCHEME = -3; // 0xfffffffd
+    field public static final int ERROR_UNSUPPORTED_SCHEME = -10; // 0xfffffff6
+  }
+
+  public class WebViewDatabase {
+    method public void clearFormData();
+    method public void clearHttpAuthUsernamePassword();
+    method public void clearUsernamePassword();
+    method public static android.webkit.WebViewDatabase getInstance(android.content.Context);
+    method public boolean hasFormData();
+    method public boolean hasHttpAuthUsernamePassword();
+    method public boolean hasUsernamePassword();
+  }
+
+  public class WebViewFragment extends android.app.Fragment {
+    ctor public WebViewFragment();
+    method public android.webkit.WebView getWebView();
+  }
+
+}
+
+package android.widget {
+
+  public abstract class AbsListView extends android.widget.AdapterView implements android.widget.Filter.FilterListener android.text.TextWatcher android.view.ViewTreeObserver.OnGlobalLayoutListener android.view.ViewTreeObserver.OnTouchModeChangeListener {
+    ctor public AbsListView(android.content.Context);
+    ctor public AbsListView(android.content.Context, android.util.AttributeSet);
+    ctor public AbsListView(android.content.Context, android.util.AttributeSet, int);
+    method public void afterTextChanged(android.text.Editable);
+    method public void beforeTextChanged(java.lang.CharSequence, int, int, int);
+    method public void clearChoices();
+    method public void clearTextFilter();
+    method public void deferNotifyDataSetChanged();
+    method public int getCacheColorHint();
+    method public int getCheckedItemCount();
+    method public long[] getCheckedItemIds();
+    method public int getCheckedItemPosition();
+    method public android.util.SparseBooleanArray getCheckedItemPositions();
+    method public int getChoiceMode();
+    method public int getListPaddingBottom();
+    method public int getListPaddingLeft();
+    method public int getListPaddingRight();
+    method public int getListPaddingTop();
+    method public android.view.View getSelectedView();
+    method public android.graphics.drawable.Drawable getSelector();
+    method public java.lang.CharSequence getTextFilter();
+    method public int getTranscriptMode();
+    method protected void handleDataChanged();
+    method public boolean hasTextFilter();
+    method public void invalidateViews();
+    method public boolean isFastScrollAlwaysVisible();
+    method public boolean isFastScrollEnabled();
+    method protected boolean isInFilterMode();
+    method public boolean isItemChecked(int);
+    method public boolean isScrollingCacheEnabled();
+    method public boolean isSmoothScrollbarEnabled();
+    method public boolean isStackFromBottom();
+    method public boolean isTextFilterEnabled();
+    method protected void layoutChildren();
+    method public void onFilterComplete(int);
+    method public void onGlobalLayout();
+    method public boolean onRemoteAdapterConnected();
+    method public void onRemoteAdapterDisconnected();
+    method public void onRestoreInstanceState(android.os.Parcelable);
+    method public android.os.Parcelable onSaveInstanceState();
+    method public void onTextChanged(java.lang.CharSequence, int, int, int);
+    method public void onTouchModeChanged(boolean);
+    method public int pointToPosition(int, int);
+    method public long pointToRowId(int, int);
+    method public void reclaimViews(java.util.List<android.view.View>);
+    method public void setAdapter(android.widget.ListAdapter);
+    method public void setCacheColorHint(int);
+    method public void setChoiceMode(int);
+    method public void setDrawSelectorOnTop(boolean);
+    method public void setFastScrollAlwaysVisible(boolean);
+    method public void setFastScrollEnabled(boolean);
+    method public void setFilterText(java.lang.String);
+    method public void setFriction(float);
+    method public void setItemChecked(int, boolean);
+    method public void setMultiChoiceModeListener(android.widget.AbsListView.MultiChoiceModeListener);
+    method public void setOnScrollListener(android.widget.AbsListView.OnScrollListener);
+    method public void setRecyclerListener(android.widget.AbsListView.RecyclerListener);
+    method public void setRemoteViewsAdapter(android.content.Intent);
+    method public void setScrollIndicators(android.view.View, android.view.View);
+    method public void setScrollingCacheEnabled(boolean);
+    method public void setSelector(int);
+    method public void setSelector(android.graphics.drawable.Drawable);
+    method public void setSmoothScrollbarEnabled(boolean);
+    method public void setStackFromBottom(boolean);
+    method public void setTextFilterEnabled(boolean);
+    method public void setTranscriptMode(int);
+    method public void setVelocityScale(float);
+    method public void smoothScrollBy(int, int);
+    method public void smoothScrollToPosition(int);
+    method public void smoothScrollToPosition(int, int);
+    method public void smoothScrollToPositionFromTop(int, int, int);
+    method public void smoothScrollToPositionFromTop(int, int);
+    method public boolean verifyDrawable(android.graphics.drawable.Drawable);
+    field public static final int CHOICE_MODE_MULTIPLE = 2; // 0x2
+    field public static final int CHOICE_MODE_MULTIPLE_MODAL = 3; // 0x3
+    field public static final int CHOICE_MODE_NONE = 0; // 0x0
+    field public static final int CHOICE_MODE_SINGLE = 1; // 0x1
+    field public static final int TRANSCRIPT_MODE_ALWAYS_SCROLL = 2; // 0x2
+    field public static final int TRANSCRIPT_MODE_DISABLED = 0; // 0x0
+    field public static final int TRANSCRIPT_MODE_NORMAL = 1; // 0x1
+  }
+
+  public static class AbsListView.LayoutParams extends android.view.ViewGroup.LayoutParams {
+    ctor public AbsListView.LayoutParams(android.content.Context, android.util.AttributeSet);
+    ctor public AbsListView.LayoutParams(int, int);
+    ctor public AbsListView.LayoutParams(int, int, int);
+    ctor public AbsListView.LayoutParams(android.view.ViewGroup.LayoutParams);
+  }
+
+  public static abstract interface AbsListView.MultiChoiceModeListener implements android.view.ActionMode.Callback {
+    method public abstract void onItemCheckedStateChanged(android.view.ActionMode, int, long, boolean);
+  }
+
+  public static abstract interface AbsListView.OnScrollListener {
+    method public abstract void onScroll(android.widget.AbsListView, int, int, int);
+    method public abstract void onScrollStateChanged(android.widget.AbsListView, int);
+    field public static final int SCROLL_STATE_FLING = 2; // 0x2
+    field public static final int SCROLL_STATE_IDLE = 0; // 0x0
+    field public static final int SCROLL_STATE_TOUCH_SCROLL = 1; // 0x1
+  }
+
+  public static abstract interface AbsListView.RecyclerListener {
+    method public abstract void onMovedToScrapHeap(android.view.View);
+  }
+
+  public static abstract interface AbsListView.SelectionBoundsAdjuster {
+    method public abstract void adjustListItemSelectionBounds(android.graphics.Rect);
+  }
+
+  public abstract class AbsSeekBar extends android.widget.ProgressBar {
+    ctor public AbsSeekBar(android.content.Context);
+    ctor public AbsSeekBar(android.content.Context, android.util.AttributeSet);
+    ctor public AbsSeekBar(android.content.Context, android.util.AttributeSet, int);
+    method public int getKeyProgressIncrement();
+    method public android.graphics.drawable.Drawable getThumb();
+    method public int getThumbOffset();
+    method public void setKeyProgressIncrement(int);
+    method public void setThumb(android.graphics.drawable.Drawable);
+    method public void setThumbOffset(int);
+  }
+
+  public abstract class AbsSpinner extends android.widget.AdapterView {
+    ctor public AbsSpinner(android.content.Context);
+    ctor public AbsSpinner(android.content.Context, android.util.AttributeSet);
+    ctor public AbsSpinner(android.content.Context, android.util.AttributeSet, int);
+    method public android.widget.SpinnerAdapter getAdapter();
+    method public android.view.View getSelectedView();
+    method public void onRestoreInstanceState(android.os.Parcelable);
+    method public android.os.Parcelable onSaveInstanceState();
+    method public int pointToPosition(int, int);
+    method public void setAdapter(android.widget.SpinnerAdapter);
+    method public void setSelection(int, boolean);
+    method public void setSelection(int);
+  }
+
+  public deprecated class AbsoluteLayout extends android.view.ViewGroup {
+    ctor public AbsoluteLayout(android.content.Context);
+    ctor public AbsoluteLayout(android.content.Context, android.util.AttributeSet);
+    ctor public AbsoluteLayout(android.content.Context, android.util.AttributeSet, int);
+    method protected void onLayout(boolean, int, int, int, int);
+  }
+
+  public static class AbsoluteLayout.LayoutParams extends android.view.ViewGroup.LayoutParams {
+    ctor public AbsoluteLayout.LayoutParams(int, int, int, int);
+    ctor public AbsoluteLayout.LayoutParams(android.content.Context, android.util.AttributeSet);
+    ctor public AbsoluteLayout.LayoutParams(android.view.ViewGroup.LayoutParams);
+    method public java.lang.String debug(java.lang.String);
+    field public int x;
+    field public int y;
+  }
+
+  public abstract interface Adapter {
+    method public abstract int getCount();
+    method public abstract java.lang.Object getItem(int);
+    method public abstract long getItemId(int);
+    method public abstract int getItemViewType(int);
+    method public abstract android.view.View getView(int, android.view.View, android.view.ViewGroup);
+    method public abstract int getViewTypeCount();
+    method public abstract boolean hasStableIds();
+    method public abstract boolean isEmpty();
+    method public abstract void registerDataSetObserver(android.database.DataSetObserver);
+    method public abstract void unregisterDataSetObserver(android.database.DataSetObserver);
+    field public static final int IGNORE_ITEM_VIEW_TYPE = -1; // 0xffffffff
+    field public static final int NO_SELECTION = -2147483648; // 0x80000000
+  }
+
+  public abstract class AdapterView extends android.view.ViewGroup {
+    ctor public AdapterView(android.content.Context);
+    ctor public AdapterView(android.content.Context, android.util.AttributeSet);
+    ctor public AdapterView(android.content.Context, android.util.AttributeSet, int);
+    method public abstract T getAdapter();
+    method public int getCount();
+    method public android.view.View getEmptyView();
+    method public int getFirstVisiblePosition();
+    method public java.lang.Object getItemAtPosition(int);
+    method public long getItemIdAtPosition(int);
+    method public int getLastVisiblePosition();
+    method public final android.widget.AdapterView.OnItemClickListener getOnItemClickListener();
+    method public final android.widget.AdapterView.OnItemLongClickListener getOnItemLongClickListener();
+    method public final android.widget.AdapterView.OnItemSelectedListener getOnItemSelectedListener();
+    method public int getPositionForView(android.view.View);
+    method public java.lang.Object getSelectedItem();
+    method public long getSelectedItemId();
+    method public int getSelectedItemPosition();
+    method public abstract android.view.View getSelectedView();
+    method protected void onLayout(boolean, int, int, int, int);
+    method public boolean performItemClick(android.view.View, int, long);
+    method public abstract void setAdapter(T);
+    method public void setEmptyView(android.view.View);
+    method public void setOnItemClickListener(android.widget.AdapterView.OnItemClickListener);
+    method public void setOnItemLongClickListener(android.widget.AdapterView.OnItemLongClickListener);
+    method public void setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener);
+    method public abstract void setSelection(int);
+    field public static final int INVALID_POSITION = -1; // 0xffffffff
+    field public static final long INVALID_ROW_ID = -9223372036854775808L; // 0x8000000000000000L
+    field public static final int ITEM_VIEW_TYPE_HEADER_OR_FOOTER = -2; // 0xfffffffe
+    field public static final int ITEM_VIEW_TYPE_IGNORE = -1; // 0xffffffff
+  }
+
+  public static class AdapterView.AdapterContextMenuInfo implements android.view.ContextMenu.ContextMenuInfo {
+    ctor public AdapterView.AdapterContextMenuInfo(android.view.View, int, long);
+    field public long id;
+    field public int position;
+    field public android.view.View targetView;
+  }
+
+  public static abstract interface AdapterView.OnItemClickListener {
+    method public abstract void onItemClick(android.widget.AdapterView<?>, android.view.View, int, long);
+  }
+
+  public static abstract interface AdapterView.OnItemLongClickListener {
+    method public abstract boolean onItemLongClick(android.widget.AdapterView<?>, android.view.View, int, long);
+  }
+
+  public static abstract interface AdapterView.OnItemSelectedListener {
+    method public abstract void onItemSelected(android.widget.AdapterView<?>, android.view.View, int, long);
+    method public abstract void onNothingSelected(android.widget.AdapterView<?>);
+  }
+
+  public abstract class AdapterViewAnimator extends android.widget.AdapterView implements android.widget.Advanceable {
+    ctor public AdapterViewAnimator(android.content.Context);
+    ctor public AdapterViewAnimator(android.content.Context, android.util.AttributeSet);
+    ctor public AdapterViewAnimator(android.content.Context, android.util.AttributeSet, int);
+    method public void advance();
+    method public void deferNotifyDataSetChanged();
+    method public void fyiWillBeAdvancedByHostKThx();
+    method public android.widget.Adapter getAdapter();
+    method public android.view.View getCurrentView();
+    method public int getDisplayedChild();
+    method public android.animation.ObjectAnimator getInAnimation();
+    method public android.animation.ObjectAnimator getOutAnimation();
+    method public android.view.View getSelectedView();
+    method public boolean onRemoteAdapterConnected();
+    method public void onRemoteAdapterDisconnected();
+    method public void onRestoreInstanceState(android.os.Parcelable);
+    method public android.os.Parcelable onSaveInstanceState();
+    method public void setAdapter(android.widget.Adapter);
+    method public void setAnimateFirstView(boolean);
+    method public void setDisplayedChild(int);
+    method public void setInAnimation(android.animation.ObjectAnimator);
+    method public void setInAnimation(android.content.Context, int);
+    method public void setOutAnimation(android.animation.ObjectAnimator);
+    method public void setOutAnimation(android.content.Context, int);
+    method public void setRemoteViewsAdapter(android.content.Intent);
+    method public void setSelection(int);
+    method public void showNext();
+    method public void showPrevious();
+  }
+
+  public class AdapterViewFlipper extends android.widget.AdapterViewAnimator {
+    ctor public AdapterViewFlipper(android.content.Context);
+    ctor public AdapterViewFlipper(android.content.Context, android.util.AttributeSet);
+    method public int getFlipInterval();
+    method public boolean isAutoStart();
+    method public boolean isFlipping();
+    method public void setAutoStart(boolean);
+    method public void setFlipInterval(int);
+    method public void startFlipping();
+    method public void stopFlipping();
+  }
+
+  public abstract interface Advanceable {
+    method public abstract void advance();
+    method public abstract void fyiWillBeAdvancedByHostKThx();
+  }
+
+  public class AlphabetIndexer extends android.database.DataSetObserver implements android.widget.SectionIndexer {
+    ctor public AlphabetIndexer(android.database.Cursor, int, java.lang.CharSequence);
+    method protected int compare(java.lang.String, java.lang.String);
+    method public int getPositionForSection(int);
+    method public int getSectionForPosition(int);
+    method public java.lang.Object[] getSections();
+    method public void setCursor(android.database.Cursor);
+    field protected java.lang.CharSequence mAlphabet;
+    field protected int mColumnIndex;
+    field protected android.database.Cursor mDataCursor;
+  }
+
+  public class AnalogClock extends android.view.View {
+    ctor public AnalogClock(android.content.Context);
+    ctor public AnalogClock(android.content.Context, android.util.AttributeSet);
+    ctor public AnalogClock(android.content.Context, android.util.AttributeSet, int);
+  }
+
+  public class ArrayAdapter extends android.widget.BaseAdapter implements android.widget.Filterable {
+    ctor public ArrayAdapter(android.content.Context, int);
+    ctor public ArrayAdapter(android.content.Context, int, int);
+    ctor public ArrayAdapter(android.content.Context, int, T[]);
+    ctor public ArrayAdapter(android.content.Context, int, int, T[]);
+    ctor public ArrayAdapter(android.content.Context, int, java.util.List<T>);
+    ctor public ArrayAdapter(android.content.Context, int, int, java.util.List<T>);
+    method public void add(T);
+    method public void addAll(java.util.Collection<? extends T>);
+    method public void addAll(T...);
+    method public void clear();
+    method public static android.widget.ArrayAdapter<java.lang.CharSequence> createFromResource(android.content.Context, int, int);
+    method public android.content.Context getContext();
+    method public int getCount();
+    method public android.widget.Filter getFilter();
+    method public T getItem(int);
+    method public long getItemId(int);
+    method public int getPosition(T);
+    method public android.view.View getView(int, android.view.View, android.view.ViewGroup);
+    method public void insert(T, int);
+    method public void remove(T);
+    method public void setDropDownViewResource(int);
+    method public void setNotifyOnChange(boolean);
+    method public void sort(java.util.Comparator<? super T>);
+  }
+
+  public class AutoCompleteTextView extends android.widget.EditText implements android.widget.Filter.FilterListener {
+    ctor public AutoCompleteTextView(android.content.Context);
+    ctor public AutoCompleteTextView(android.content.Context, android.util.AttributeSet);
+    ctor public AutoCompleteTextView(android.content.Context, android.util.AttributeSet, int);
+    method public void clearListSelection();
+    method protected java.lang.CharSequence convertSelectionToString(java.lang.Object);
+    method public void dismissDropDown();
+    method public boolean enoughToFilter();
+    method public android.widget.ListAdapter getAdapter();
+    method public java.lang.CharSequence getCompletionHint();
+    method public int getDropDownAnchor();
+    method public android.graphics.drawable.Drawable getDropDownBackground();
+    method public int getDropDownHeight();
+    method public int getDropDownHorizontalOffset();
+    method public int getDropDownVerticalOffset();
+    method public int getDropDownWidth();
+    method protected android.widget.Filter getFilter();
+    method public deprecated android.widget.AdapterView.OnItemClickListener getItemClickListener();
+    method public deprecated android.widget.AdapterView.OnItemSelectedListener getItemSelectedListener();
+    method public int getListSelection();
+    method public android.widget.AdapterView.OnItemClickListener getOnItemClickListener();
+    method public android.widget.AdapterView.OnItemSelectedListener getOnItemSelectedListener();
+    method public int getThreshold();
+    method public android.widget.AutoCompleteTextView.Validator getValidator();
+    method public boolean isPerformingCompletion();
+    method public boolean isPopupShowing();
+    method public void onFilterComplete(int);
+    method public void performCompletion();
+    method protected void performFiltering(java.lang.CharSequence, int);
+    method public void performValidation();
+    method protected void replaceText(java.lang.CharSequence);
+    method public void setAdapter(T);
+    method public void setCompletionHint(java.lang.CharSequence);
+    method public void setDropDownAnchor(int);
+    method public void setDropDownBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public void setDropDownBackgroundResource(int);
+    method public void setDropDownHeight(int);
+    method public void setDropDownHorizontalOffset(int);
+    method public void setDropDownVerticalOffset(int);
+    method public void setDropDownWidth(int);
+    method public void setListSelection(int);
+    method public void setOnDismissListener(android.widget.AutoCompleteTextView.OnDismissListener);
+    method public void setOnItemClickListener(android.widget.AdapterView.OnItemClickListener);
+    method public void setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener);
+    method public void setText(java.lang.CharSequence, boolean);
+    method public void setThreshold(int);
+    method public void setValidator(android.widget.AutoCompleteTextView.Validator);
+    method public void showDropDown();
+  }
+
+  public static abstract interface AutoCompleteTextView.OnDismissListener {
+    method public abstract void onDismiss();
+  }
+
+  public static abstract interface AutoCompleteTextView.Validator {
+    method public abstract java.lang.CharSequence fixText(java.lang.CharSequence);
+    method public abstract boolean isValid(java.lang.CharSequence);
+  }
+
+  public abstract class BaseAdapter implements android.widget.ListAdapter android.widget.SpinnerAdapter {
+    ctor public BaseAdapter();
+    method public boolean areAllItemsEnabled();
+    method public android.view.View getDropDownView(int, android.view.View, android.view.ViewGroup);
+    method public int getItemViewType(int);
+    method public int getViewTypeCount();
+    method public boolean hasStableIds();
+    method public boolean isEmpty();
+    method public boolean isEnabled(int);
+    method public void notifyDataSetChanged();
+    method public void notifyDataSetInvalidated();
+    method public void registerDataSetObserver(android.database.DataSetObserver);
+    method public void unregisterDataSetObserver(android.database.DataSetObserver);
+  }
+
+  public abstract class BaseExpandableListAdapter implements android.widget.ExpandableListAdapter android.widget.HeterogeneousExpandableList {
+    ctor public BaseExpandableListAdapter();
+    method public boolean areAllItemsEnabled();
+    method public int getChildType(int, int);
+    method public int getChildTypeCount();
+    method public long getCombinedChildId(long, long);
+    method public long getCombinedGroupId(long);
+    method public int getGroupType(int);
+    method public int getGroupTypeCount();
+    method public boolean isEmpty();
+    method public void notifyDataSetChanged();
+    method public void notifyDataSetInvalidated();
+    method public void onGroupCollapsed(int);
+    method public void onGroupExpanded(int);
+    method public void registerDataSetObserver(android.database.DataSetObserver);
+    method public void unregisterDataSetObserver(android.database.DataSetObserver);
+  }
+
+  public class Button extends android.widget.TextView {
+    ctor public Button(android.content.Context);
+    ctor public Button(android.content.Context, android.util.AttributeSet);
+    ctor public Button(android.content.Context, android.util.AttributeSet, int);
+  }
+
+  public class CalendarView extends android.widget.FrameLayout {
+    ctor public CalendarView(android.content.Context);
+    ctor public CalendarView(android.content.Context, android.util.AttributeSet);
+    ctor public CalendarView(android.content.Context, android.util.AttributeSet, int);
+    method public long getDate();
+    method public int getDateTextAppearance();
+    method public int getFirstDayOfWeek();
+    method public int getFocusedMonthDateColor();
+    method public long getMaxDate();
+    method public long getMinDate();
+    method public android.graphics.drawable.Drawable getSelectedDateVerticalBar();
+    method public int getSelectedWeekBackgroundColor();
+    method public boolean getShowWeekNumber();
+    method public int getShownWeekCount();
+    method public int getUnfocusedMonthDateColor();
+    method public int getWeekDayTextAppearance();
+    method public int getWeekNumberColor();
+    method public int getWeekSeparatorLineColor();
+    method public void setDate(long);
+    method public void setDate(long, boolean, boolean);
+    method public void setDateTextAppearance(int);
+    method public void setFirstDayOfWeek(int);
+    method public void setFocusedMonthDateColor(int);
+    method public void setMaxDate(long);
+    method public void setMinDate(long);
+    method public void setOnDateChangeListener(android.widget.CalendarView.OnDateChangeListener);
+    method public void setSelectedDateVerticalBar(int);
+    method public void setSelectedDateVerticalBar(android.graphics.drawable.Drawable);
+    method public void setSelectedWeekBackgroundColor(int);
+    method public void setShowWeekNumber(boolean);
+    method public void setShownWeekCount(int);
+    method public void setUnfocusedMonthDateColor(int);
+    method public void setWeekDayTextAppearance(int);
+    method public void setWeekNumberColor(int);
+    method public void setWeekSeparatorLineColor(int);
+  }
+
+  public static abstract interface CalendarView.OnDateChangeListener {
+    method public abstract void onSelectedDayChange(android.widget.CalendarView, int, int, int);
+  }
+
+  public class CheckBox extends android.widget.CompoundButton {
+    ctor public CheckBox(android.content.Context);
+    ctor public CheckBox(android.content.Context, android.util.AttributeSet);
+    ctor public CheckBox(android.content.Context, android.util.AttributeSet, int);
+  }
+
+  public abstract interface Checkable {
+    method public abstract boolean isChecked();
+    method public abstract void setChecked(boolean);
+    method public abstract void toggle();
+  }
+
+  public class CheckedTextView extends android.widget.TextView implements android.widget.Checkable {
+    ctor public CheckedTextView(android.content.Context);
+    ctor public CheckedTextView(android.content.Context, android.util.AttributeSet);
+    ctor public CheckedTextView(android.content.Context, android.util.AttributeSet, int);
+    method public android.graphics.drawable.Drawable getCheckMarkDrawable();
+    method public boolean isChecked();
+    method public void setCheckMarkDrawable(int);
+    method public void setCheckMarkDrawable(android.graphics.drawable.Drawable);
+    method public void setChecked(boolean);
+    method public void toggle();
+  }
+
+  public class Chronometer extends android.widget.TextView {
+    ctor public Chronometer(android.content.Context);
+    ctor public Chronometer(android.content.Context, android.util.AttributeSet);
+    ctor public Chronometer(android.content.Context, android.util.AttributeSet, int);
+    method public long getBase();
+    method public java.lang.String getFormat();
+    method public android.widget.Chronometer.OnChronometerTickListener getOnChronometerTickListener();
+    method public void setBase(long);
+    method public void setFormat(java.lang.String);
+    method public void setOnChronometerTickListener(android.widget.Chronometer.OnChronometerTickListener);
+    method public void start();
+    method public void stop();
+  }
+
+  public static abstract interface Chronometer.OnChronometerTickListener {
+    method public abstract void onChronometerTick(android.widget.Chronometer);
+  }
+
+  public abstract class CompoundButton extends android.widget.Button implements android.widget.Checkable {
+    ctor public CompoundButton(android.content.Context);
+    ctor public CompoundButton(android.content.Context, android.util.AttributeSet);
+    ctor public CompoundButton(android.content.Context, android.util.AttributeSet, int);
+    method public boolean isChecked();
+    method public void setButtonDrawable(int);
+    method public void setButtonDrawable(android.graphics.drawable.Drawable);
+    method public void setChecked(boolean);
+    method public void setOnCheckedChangeListener(android.widget.CompoundButton.OnCheckedChangeListener);
+    method public void toggle();
+  }
+
+  public static abstract interface CompoundButton.OnCheckedChangeListener {
+    method public abstract void onCheckedChanged(android.widget.CompoundButton, boolean);
+  }
+
+  public abstract class CursorAdapter extends android.widget.BaseAdapter implements android.widget.Filterable {
+    ctor public deprecated CursorAdapter(android.content.Context, android.database.Cursor);
+    ctor public CursorAdapter(android.content.Context, android.database.Cursor, boolean);
+    ctor public CursorAdapter(android.content.Context, android.database.Cursor, int);
+    method public abstract void bindView(android.view.View, android.content.Context, android.database.Cursor);
+    method public void changeCursor(android.database.Cursor);
+    method public java.lang.CharSequence convertToString(android.database.Cursor);
+    method public int getCount();
+    method public android.database.Cursor getCursor();
+    method public android.widget.Filter getFilter();
+    method public android.widget.FilterQueryProvider getFilterQueryProvider();
+    method public java.lang.Object getItem(int);
+    method public long getItemId(int);
+    method public android.view.View getView(int, android.view.View, android.view.ViewGroup);
+    method protected deprecated void init(android.content.Context, android.database.Cursor, boolean);
+    method public android.view.View newDropDownView(android.content.Context, android.database.Cursor, android.view.ViewGroup);
+    method public abstract android.view.View newView(android.content.Context, android.database.Cursor, android.view.ViewGroup);
+    method protected void onContentChanged();
+    method public android.database.Cursor runQueryOnBackgroundThread(java.lang.CharSequence);
+    method public void setFilterQueryProvider(android.widget.FilterQueryProvider);
+    method public android.database.Cursor swapCursor(android.database.Cursor);
+    field public static final deprecated int FLAG_AUTO_REQUERY = 1; // 0x1
+    field public static final int FLAG_REGISTER_CONTENT_OBSERVER = 2; // 0x2
+  }
+
+  public abstract class CursorTreeAdapter extends android.widget.BaseExpandableListAdapter implements android.widget.Filterable {
+    ctor public CursorTreeAdapter(android.database.Cursor, android.content.Context);
+    ctor public CursorTreeAdapter(android.database.Cursor, android.content.Context, boolean);
+    method protected abstract void bindChildView(android.view.View, android.content.Context, android.database.Cursor, boolean);
+    method protected abstract void bindGroupView(android.view.View, android.content.Context, android.database.Cursor, boolean);
+    method public void changeCursor(android.database.Cursor);
+    method public java.lang.String convertToString(android.database.Cursor);
+    method public android.database.Cursor getChild(int, int);
+    method public long getChildId(int, int);
+    method public android.view.View getChildView(int, int, boolean, android.view.View, android.view.ViewGroup);
+    method public int getChildrenCount(int);
+    method protected abstract android.database.Cursor getChildrenCursor(android.database.Cursor);
+    method public android.database.Cursor getCursor();
+    method public android.widget.Filter getFilter();
+    method public android.widget.FilterQueryProvider getFilterQueryProvider();
+    method public android.database.Cursor getGroup(int);
+    method public int getGroupCount();
+    method public long getGroupId(int);
+    method public android.view.View getGroupView(int, boolean, android.view.View, android.view.ViewGroup);
+    method public boolean hasStableIds();
+    method public boolean isChildSelectable(int, int);
+    method protected abstract android.view.View newChildView(android.content.Context, android.database.Cursor, boolean, android.view.ViewGroup);
+    method protected abstract android.view.View newGroupView(android.content.Context, android.database.Cursor, boolean, android.view.ViewGroup);
+    method public void notifyDataSetChanged(boolean);
+    method public android.database.Cursor runQueryOnBackgroundThread(java.lang.CharSequence);
+    method public void setChildrenCursor(int, android.database.Cursor);
+    method public void setFilterQueryProvider(android.widget.FilterQueryProvider);
+    method public void setGroupCursor(android.database.Cursor);
+  }
+
+  public class DatePicker extends android.widget.FrameLayout {
+    ctor public DatePicker(android.content.Context);
+    ctor public DatePicker(android.content.Context, android.util.AttributeSet);
+    ctor public DatePicker(android.content.Context, android.util.AttributeSet, int);
+    method public android.widget.CalendarView getCalendarView();
+    method public boolean getCalendarViewShown();
+    method public int getDayOfMonth();
+    method public long getMaxDate();
+    method public long getMinDate();
+    method public int getMonth();
+    method public boolean getSpinnersShown();
+    method public int getYear();
+    method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener);
+    method public void setCalendarViewShown(boolean);
+    method public void setMaxDate(long);
+    method public void setMinDate(long);
+    method public void setSpinnersShown(boolean);
+    method public void updateDate(int, int, int);
+  }
+
+  public static abstract interface DatePicker.OnDateChangedListener {
+    method public abstract void onDateChanged(android.widget.DatePicker, int, int, int);
+  }
+
+  public class DialerFilter extends android.widget.RelativeLayout {
+    ctor public DialerFilter(android.content.Context);
+    ctor public DialerFilter(android.content.Context, android.util.AttributeSet);
+    method public void append(java.lang.String);
+    method public void clearText();
+    method public java.lang.CharSequence getDigits();
+    method public java.lang.CharSequence getFilterText();
+    method public java.lang.CharSequence getLetters();
+    method public int getMode();
+    method public boolean isQwertyKeyboard();
+    method protected void onModeChange(int, int);
+    method public void removeFilterWatcher(android.text.TextWatcher);
+    method public void setDigitsWatcher(android.text.TextWatcher);
+    method public void setFilterWatcher(android.text.TextWatcher);
+    method public void setLettersWatcher(android.text.TextWatcher);
+    method public void setMode(int);
+    field public static final int DIGITS_AND_LETTERS = 1; // 0x1
+    field public static final int DIGITS_AND_LETTERS_NO_DIGITS = 2; // 0x2
+    field public static final int DIGITS_AND_LETTERS_NO_LETTERS = 3; // 0x3
+    field public static final int DIGITS_ONLY = 4; // 0x4
+    field public static final int LETTERS_ONLY = 5; // 0x5
+  }
+
+  public deprecated class DigitalClock extends android.widget.TextView {
+    ctor public DigitalClock(android.content.Context);
+    ctor public DigitalClock(android.content.Context, android.util.AttributeSet);
+  }
+
+  public class EdgeEffect {
+    ctor public EdgeEffect(android.content.Context);
+    method public boolean draw(android.graphics.Canvas);
+    method public void finish();
+    method public boolean isFinished();
+    method public void onAbsorb(int);
+    method public void onPull(float);
+    method public void onRelease();
+    method public void setSize(int, int);
+  }
+
+  public class EditText extends android.widget.TextView {
+    ctor public EditText(android.content.Context);
+    ctor public EditText(android.content.Context, android.util.AttributeSet);
+    ctor public EditText(android.content.Context, android.util.AttributeSet, int);
+    method public void extendSelection(int);
+    method public void selectAll();
+    method public void setSelection(int, int);
+    method public void setSelection(int);
+  }
+
+  public abstract interface ExpandableListAdapter {
+    method public abstract boolean areAllItemsEnabled();
+    method public abstract java.lang.Object getChild(int, int);
+    method public abstract long getChildId(int, int);
+    method public abstract android.view.View getChildView(int, int, boolean, android.view.View, android.view.ViewGroup);
+    method public abstract int getChildrenCount(int);
+    method public abstract long getCombinedChildId(long, long);
+    method public abstract long getCombinedGroupId(long);
+    method public abstract java.lang.Object getGroup(int);
+    method public abstract int getGroupCount();
+    method public abstract long getGroupId(int);
+    method public abstract android.view.View getGroupView(int, boolean, android.view.View, android.view.ViewGroup);
+    method public abstract boolean hasStableIds();
+    method public abstract boolean isChildSelectable(int, int);
+    method public abstract boolean isEmpty();
+    method public abstract void onGroupCollapsed(int);
+    method public abstract void onGroupExpanded(int);
+    method public abstract void registerDataSetObserver(android.database.DataSetObserver);
+    method public abstract void unregisterDataSetObserver(android.database.DataSetObserver);
+  }
+
+  public class ExpandableListView extends android.widget.ListView {
+    ctor public ExpandableListView(android.content.Context);
+    ctor public ExpandableListView(android.content.Context, android.util.AttributeSet);
+    ctor public ExpandableListView(android.content.Context, android.util.AttributeSet, int);
+    method public boolean collapseGroup(int);
+    method public boolean expandGroup(int);
+    method public boolean expandGroup(int, boolean);
+    method public android.widget.ExpandableListAdapter getExpandableListAdapter();
+    method public long getExpandableListPosition(int);
+    method public int getFlatListPosition(long);
+    method public static int getPackedPositionChild(long);
+    method public static long getPackedPositionForChild(int, int);
+    method public static long getPackedPositionForGroup(int);
+    method public static int getPackedPositionGroup(long);
+    method public static int getPackedPositionType(long);
+    method public long getSelectedId();
+    method public long getSelectedPosition();
+    method public boolean isGroupExpanded(int);
+    method public void setAdapter(android.widget.ExpandableListAdapter);
+    method public void setChildDivider(android.graphics.drawable.Drawable);
+    method public void setChildIndicator(android.graphics.drawable.Drawable);
+    method public void setChildIndicatorBounds(int, int);
+    method public void setGroupIndicator(android.graphics.drawable.Drawable);
+    method public void setIndicatorBounds(int, int);
+    method public void setOnChildClickListener(android.widget.ExpandableListView.OnChildClickListener);
+    method public void setOnGroupClickListener(android.widget.ExpandableListView.OnGroupClickListener);
+    method public void setOnGroupCollapseListener(android.widget.ExpandableListView.OnGroupCollapseListener);
+    method public void setOnGroupExpandListener(android.widget.ExpandableListView.OnGroupExpandListener);
+    method public boolean setSelectedChild(int, int, boolean);
+    method public void setSelectedGroup(int);
+    field public static final int CHILD_INDICATOR_INHERIT = -1; // 0xffffffff
+    field public static final int PACKED_POSITION_TYPE_CHILD = 1; // 0x1
+    field public static final int PACKED_POSITION_TYPE_GROUP = 0; // 0x0
+    field public static final int PACKED_POSITION_TYPE_NULL = 2; // 0x2
+    field public static final long PACKED_POSITION_VALUE_NULL = 4294967295L; // 0xffffffffL
+  }
+
+  public static class ExpandableListView.ExpandableListContextMenuInfo implements android.view.ContextMenu.ContextMenuInfo {
+    ctor public ExpandableListView.ExpandableListContextMenuInfo(android.view.View, long, long);
+    field public long id;
+    field public long packedPosition;
+    field public android.view.View targetView;
+  }
+
+  public static abstract interface ExpandableListView.OnChildClickListener {
+    method public abstract boolean onChildClick(android.widget.ExpandableListView, android.view.View, int, int, long);
+  }
+
+  public static abstract interface ExpandableListView.OnGroupClickListener {
+    method public abstract boolean onGroupClick(android.widget.ExpandableListView, android.view.View, int, long);
+  }
+
+  public static abstract interface ExpandableListView.OnGroupCollapseListener {
+    method public abstract void onGroupCollapse(int);
+  }
+
+  public static abstract interface ExpandableListView.OnGroupExpandListener {
+    method public abstract void onGroupExpand(int);
+  }
+
+  public abstract class Filter {
+    ctor public Filter();
+    method public java.lang.CharSequence convertResultToString(java.lang.Object);
+    method public final void filter(java.lang.CharSequence);
+    method public final void filter(java.lang.CharSequence, android.widget.Filter.FilterListener);
+    method protected abstract android.widget.Filter.FilterResults performFiltering(java.lang.CharSequence);
+    method protected abstract void publishResults(java.lang.CharSequence, android.widget.Filter.FilterResults);
+  }
+
+  public static abstract interface Filter.FilterListener {
+    method public abstract void onFilterComplete(int);
+  }
+
+  protected static class Filter.FilterResults {
+    ctor public Filter.FilterResults();
+    field public int count;
+    field public java.lang.Object values;
+  }
+
+  public abstract interface FilterQueryProvider {
+    method public abstract android.database.Cursor runQuery(java.lang.CharSequence);
+  }
+
+  public abstract interface Filterable {
+    method public abstract android.widget.Filter getFilter();
+  }
+
+  public class FrameLayout extends android.view.ViewGroup {
+    ctor public FrameLayout(android.content.Context);
+    ctor public FrameLayout(android.content.Context, android.util.AttributeSet);
+    ctor public FrameLayout(android.content.Context, android.util.AttributeSet, int);
+    method public deprecated boolean getConsiderGoneChildrenWhenMeasuring();
+    method public android.graphics.drawable.Drawable getForeground();
+    method public int getForegroundGravity();
+    method public boolean getMeasureAllChildren();
+    method protected void onLayout(boolean, int, int, int, int);
+    method public void setForeground(android.graphics.drawable.Drawable);
+    method public void setForegroundGravity(int);
+    method public void setMeasureAllChildren(boolean);
+  }
+
+  public static class FrameLayout.LayoutParams extends android.view.ViewGroup.MarginLayoutParams {
+    ctor public FrameLayout.LayoutParams(android.content.Context, android.util.AttributeSet);
+    ctor public FrameLayout.LayoutParams(int, int);
+    ctor public FrameLayout.LayoutParams(int, int, int);
+    ctor public FrameLayout.LayoutParams(android.view.ViewGroup.LayoutParams);
+    ctor public FrameLayout.LayoutParams(android.view.ViewGroup.MarginLayoutParams);
+    field public int gravity;
+  }
+
+  public deprecated class Gallery extends android.widget.AbsSpinner implements android.view.GestureDetector.OnGestureListener {
+    ctor public Gallery(android.content.Context);
+    ctor public Gallery(android.content.Context, android.util.AttributeSet);
+    ctor public Gallery(android.content.Context, android.util.AttributeSet, int);
+    method public boolean onDown(android.view.MotionEvent);
+    method public boolean onFling(android.view.MotionEvent, android.view.MotionEvent, float, float);
+    method public void onLongPress(android.view.MotionEvent);
+    method public boolean onScroll(android.view.MotionEvent, android.view.MotionEvent, float, float);
+    method public void onShowPress(android.view.MotionEvent);
+    method public boolean onSingleTapUp(android.view.MotionEvent);
+    method public void setAnimationDuration(int);
+    method public void setCallbackDuringFling(boolean);
+    method public void setGravity(int);
+    method public void setSpacing(int);
+    method public void setUnselectedAlpha(float);
+  }
+
+  public static class Gallery.LayoutParams extends android.view.ViewGroup.LayoutParams {
+    ctor public Gallery.LayoutParams(android.content.Context, android.util.AttributeSet);
+    ctor public Gallery.LayoutParams(int, int);
+    ctor public Gallery.LayoutParams(android.view.ViewGroup.LayoutParams);
+  }
+
+  public class GridLayout extends android.view.ViewGroup {
+    ctor public GridLayout(android.content.Context, android.util.AttributeSet, int);
+    ctor public GridLayout(android.content.Context, android.util.AttributeSet);
+    ctor public GridLayout(android.content.Context);
+    method public int getAlignmentMode();
+    method public int getColumnCount();
+    method public int getOrientation();
+    method public int getRowCount();
+    method public boolean getUseDefaultMargins();
+    method public boolean isColumnOrderPreserved();
+    method public boolean isRowOrderPreserved();
+    method protected void onLayout(boolean, int, int, int, int);
+    method public void setAlignmentMode(int);
+    method public void setColumnCount(int);
+    method public void setColumnOrderPreserved(boolean);
+    method public void setOrientation(int);
+    method public void setRowCount(int);
+    method public void setRowOrderPreserved(boolean);
+    method public void setUseDefaultMargins(boolean);
+    method public static android.widget.GridLayout.Spec spec(int, int, android.widget.GridLayout.Alignment);
+    method public static android.widget.GridLayout.Spec spec(int, android.widget.GridLayout.Alignment);
+    method public static android.widget.GridLayout.Spec spec(int, int);
+    method public static android.widget.GridLayout.Spec spec(int);
+    field public static final int ALIGN_BOUNDS = 0; // 0x0
+    field public static final int ALIGN_MARGINS = 1; // 0x1
+    field public static final android.widget.GridLayout.Alignment BASELINE;
+    field public static final android.widget.GridLayout.Alignment BOTTOM;
+    field public static final android.widget.GridLayout.Alignment CENTER;
+    field public static final android.widget.GridLayout.Alignment END;
+    field public static final android.widget.GridLayout.Alignment FILL;
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final android.widget.GridLayout.Alignment LEFT;
+    field public static final android.widget.GridLayout.Alignment RIGHT;
+    field public static final android.widget.GridLayout.Alignment START;
+    field public static final android.widget.GridLayout.Alignment TOP;
+    field public static final int UNDEFINED = -2147483648; // 0x80000000
+    field public static final int VERTICAL = 1; // 0x1
+  }
+
+  public static abstract class GridLayout.Alignment {
+  }
+
+  public static class GridLayout.LayoutParams extends android.view.ViewGroup.MarginLayoutParams {
+    ctor public GridLayout.LayoutParams(android.widget.GridLayout.Spec, android.widget.GridLayout.Spec);
+    ctor public GridLayout.LayoutParams();
+    ctor public GridLayout.LayoutParams(android.view.ViewGroup.LayoutParams);
+    ctor public GridLayout.LayoutParams(android.view.ViewGroup.MarginLayoutParams);
+    ctor public GridLayout.LayoutParams(android.widget.GridLayout.LayoutParams);
+    ctor public GridLayout.LayoutParams(android.content.Context, android.util.AttributeSet);
+    method public void setGravity(int);
+    field public android.widget.GridLayout.Spec columnSpec;
+    field public android.widget.GridLayout.Spec rowSpec;
+  }
+
+  public static class GridLayout.Spec {
+  }
+
+  public class GridView extends android.widget.AbsListView {
+    ctor public GridView(android.content.Context);
+    ctor public GridView(android.content.Context, android.util.AttributeSet);
+    ctor public GridView(android.content.Context, android.util.AttributeSet, int);
+    method public android.widget.ListAdapter getAdapter();
+    method public int getColumnWidth();
+    method public int getGravity();
+    method public int getHorizontalSpacing();
+    method public int getNumColumns();
+    method public int getRequestedColumnWidth();
+    method public int getRequestedHorizontalSpacing();
+    method public int getStretchMode();
+    method public int getVerticalSpacing();
+    method public void setColumnWidth(int);
+    method public void setGravity(int);
+    method public void setHorizontalSpacing(int);
+    method public void setNumColumns(int);
+    method public void setSelection(int);
+    method public void setStretchMode(int);
+    method public void setVerticalSpacing(int);
+    method public void smoothScrollByOffset(int);
+    field public static final int AUTO_FIT = -1; // 0xffffffff
+    field public static final int NO_STRETCH = 0; // 0x0
+    field public static final int STRETCH_COLUMN_WIDTH = 2; // 0x2
+    field public static final int STRETCH_SPACING = 1; // 0x1
+    field public static final int STRETCH_SPACING_UNIFORM = 3; // 0x3
+  }
+
+  public class HeaderViewListAdapter implements android.widget.Filterable android.widget.WrapperListAdapter {
+    ctor public HeaderViewListAdapter(java.util.ArrayList<android.widget.ListView.FixedViewInfo>, java.util.ArrayList<android.widget.ListView.FixedViewInfo>, android.widget.ListAdapter);
+    method public boolean areAllItemsEnabled();
+    method public int getCount();
+    method public android.widget.Filter getFilter();
+    method public int getFootersCount();
+    method public int getHeadersCount();
+    method public java.lang.Object getItem(int);
+    method public long getItemId(int);
+    method public int getItemViewType(int);
+    method public android.view.View getView(int, android.view.View, android.view.ViewGroup);
+    method public int getViewTypeCount();
+    method public android.widget.ListAdapter getWrappedAdapter();
+    method public boolean hasStableIds();
+    method public boolean isEmpty();
+    method public boolean isEnabled(int);
+    method public void registerDataSetObserver(android.database.DataSetObserver);
+    method public boolean removeFooter(android.view.View);
+    method public boolean removeHeader(android.view.View);
+    method public void unregisterDataSetObserver(android.database.DataSetObserver);
+  }
+
+  public abstract interface HeterogeneousExpandableList {
+    method public abstract int getChildType(int, int);
+    method public abstract int getChildTypeCount();
+    method public abstract int getGroupType(int);
+    method public abstract int getGroupTypeCount();
+  }
+
+  public class HorizontalScrollView extends android.widget.FrameLayout {
+    ctor public HorizontalScrollView(android.content.Context);
+    ctor public HorizontalScrollView(android.content.Context, android.util.AttributeSet);
+    ctor public HorizontalScrollView(android.content.Context, android.util.AttributeSet, int);
+    method public boolean arrowScroll(int);
+    method protected int computeScrollDeltaToGetChildRectOnScreen(android.graphics.Rect);
+    method public boolean executeKeyEvent(android.view.KeyEvent);
+    method public void fling(int);
+    method public boolean fullScroll(int);
+    method public int getMaxScrollAmount();
+    method public boolean isFillViewport();
+    method public boolean isSmoothScrollingEnabled();
+    method public boolean pageScroll(int);
+    method public void setFillViewport(boolean);
+    method public void setSmoothScrollingEnabled(boolean);
+    method public final void smoothScrollBy(int, int);
+    method public final void smoothScrollTo(int, int);
+  }
+
+  public class ImageButton extends android.widget.ImageView {
+    ctor public ImageButton(android.content.Context);
+    ctor public ImageButton(android.content.Context, android.util.AttributeSet);
+    ctor public ImageButton(android.content.Context, android.util.AttributeSet, int);
+  }
+
+  public class ImageSwitcher extends android.widget.ViewSwitcher {
+    ctor public ImageSwitcher(android.content.Context);
+    ctor public ImageSwitcher(android.content.Context, android.util.AttributeSet);
+    method public void setImageDrawable(android.graphics.drawable.Drawable);
+    method public void setImageResource(int);
+    method public void setImageURI(android.net.Uri);
+  }
+
+  public class ImageView extends android.view.View {
+    ctor public ImageView(android.content.Context);
+    ctor public ImageView(android.content.Context, android.util.AttributeSet);
+    ctor public ImageView(android.content.Context, android.util.AttributeSet, int);
+    method public final void clearColorFilter();
+    method public boolean getAdjustViewBounds();
+    method public boolean getBaselineAlignBottom();
+    method public android.graphics.ColorFilter getColorFilter();
+    method public boolean getCropToPadding();
+    method public android.graphics.drawable.Drawable getDrawable();
+    method public int getImageAlpha();
+    method public android.graphics.Matrix getImageMatrix();
+    method public int getMaxHeight();
+    method public int getMaxWidth();
+    method public android.widget.ImageView.ScaleType getScaleType();
+    method public int[] onCreateDrawableState(int);
+    method public void setAdjustViewBounds(boolean);
+    method public deprecated void setAlpha(int);
+    method public void setBaseline(int);
+    method public void setBaselineAlignBottom(boolean);
+    method public final void setColorFilter(int, android.graphics.PorterDuff.Mode);
+    method public final void setColorFilter(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void setCropToPadding(boolean);
+    method protected boolean setFrame(int, int, int, int);
+    method public void setImageAlpha(int);
+    method public void setImageBitmap(android.graphics.Bitmap);
+    method public void setImageDrawable(android.graphics.drawable.Drawable);
+    method public void setImageLevel(int);
+    method public void setImageMatrix(android.graphics.Matrix);
+    method public void setImageResource(int);
+    method public void setImageState(int[], boolean);
+    method public void setImageURI(android.net.Uri);
+    method public void setMaxHeight(int);
+    method public void setMaxWidth(int);
+    method public void setScaleType(android.widget.ImageView.ScaleType);
+  }
+
+  public static final class ImageView.ScaleType extends java.lang.Enum {
+    method public static android.widget.ImageView.ScaleType valueOf(java.lang.String);
+    method public static final android.widget.ImageView.ScaleType[] values();
+    enum_constant public static final android.widget.ImageView.ScaleType CENTER;
+    enum_constant public static final android.widget.ImageView.ScaleType CENTER_CROP;
+    enum_constant public static final android.widget.ImageView.ScaleType CENTER_INSIDE;
+    enum_constant public static final android.widget.ImageView.ScaleType FIT_CENTER;
+    enum_constant public static final android.widget.ImageView.ScaleType FIT_END;
+    enum_constant public static final android.widget.ImageView.ScaleType FIT_START;
+    enum_constant public static final android.widget.ImageView.ScaleType FIT_XY;
+    enum_constant public static final android.widget.ImageView.ScaleType MATRIX;
+  }
+
+  public class LinearLayout extends android.view.ViewGroup {
+    ctor public LinearLayout(android.content.Context);
+    ctor public LinearLayout(android.content.Context, android.util.AttributeSet);
+    ctor public LinearLayout(android.content.Context, android.util.AttributeSet, int);
+    method public int getBaselineAlignedChildIndex();
+    method public android.graphics.drawable.Drawable getDividerDrawable();
+    method public int getDividerPadding();
+    method public int getOrientation();
+    method public int getShowDividers();
+    method public float getWeightSum();
+    method public boolean isBaselineAligned();
+    method public boolean isMeasureWithLargestChildEnabled();
+    method protected void onLayout(boolean, int, int, int, int);
+    method public void setBaselineAligned(boolean);
+    method public void setBaselineAlignedChildIndex(int);
+    method public void setDividerDrawable(android.graphics.drawable.Drawable);
+    method public void setDividerPadding(int);
+    method public void setGravity(int);
+    method public void setHorizontalGravity(int);
+    method public void setMeasureWithLargestChildEnabled(boolean);
+    method public void setOrientation(int);
+    method public void setShowDividers(int);
+    method public void setVerticalGravity(int);
+    method public void setWeightSum(float);
+    field public static final int HORIZONTAL = 0; // 0x0
+    field public static final int SHOW_DIVIDER_BEGINNING = 1; // 0x1
+    field public static final int SHOW_DIVIDER_END = 4; // 0x4
+    field public static final int SHOW_DIVIDER_MIDDLE = 2; // 0x2
+    field public static final int SHOW_DIVIDER_NONE = 0; // 0x0
+    field public static final int VERTICAL = 1; // 0x1
+  }
+
+  public static class LinearLayout.LayoutParams extends android.view.ViewGroup.MarginLayoutParams {
+    ctor public LinearLayout.LayoutParams(android.content.Context, android.util.AttributeSet);
+    ctor public LinearLayout.LayoutParams(int, int);
+    ctor public LinearLayout.LayoutParams(int, int, float);
+    ctor public LinearLayout.LayoutParams(android.view.ViewGroup.LayoutParams);
+    ctor public LinearLayout.LayoutParams(android.view.ViewGroup.MarginLayoutParams);
+    method public java.lang.String debug(java.lang.String);
+    field public int gravity;
+    field public float weight;
+  }
+
+  public abstract interface ListAdapter implements android.widget.Adapter {
+    method public abstract boolean areAllItemsEnabled();
+    method public abstract boolean isEnabled(int);
+  }
+
+  public class ListPopupWindow {
+    ctor public ListPopupWindow(android.content.Context);
+    ctor public ListPopupWindow(android.content.Context, android.util.AttributeSet);
+    ctor public ListPopupWindow(android.content.Context, android.util.AttributeSet, int);
+    ctor public ListPopupWindow(android.content.Context, android.util.AttributeSet, int, int);
+    method public void clearListSelection();
+    method public void dismiss();
+    method public android.view.View getAnchorView();
+    method public int getAnimationStyle();
+    method public android.graphics.drawable.Drawable getBackground();
+    method public int getHeight();
+    method public int getHorizontalOffset();
+    method public int getInputMethodMode();
+    method public android.widget.ListView getListView();
+    method public int getPromptPosition();
+    method public java.lang.Object getSelectedItem();
+    method public long getSelectedItemId();
+    method public int getSelectedItemPosition();
+    method public android.view.View getSelectedView();
+    method public int getSoftInputMode();
+    method public int getVerticalOffset();
+    method public int getWidth();
+    method public boolean isInputMethodNotNeeded();
+    method public boolean isModal();
+    method public boolean isShowing();
+    method public boolean onKeyDown(int, android.view.KeyEvent);
+    method public boolean onKeyPreIme(int, android.view.KeyEvent);
+    method public boolean onKeyUp(int, android.view.KeyEvent);
+    method public boolean performItemClick(int);
+    method public void postShow();
+    method public void setAdapter(android.widget.ListAdapter);
+    method public void setAnchorView(android.view.View);
+    method public void setAnimationStyle(int);
+    method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public void setContentWidth(int);
+    method public void setHeight(int);
+    method public void setHorizontalOffset(int);
+    method public void setInputMethodMode(int);
+    method public void setListSelector(android.graphics.drawable.Drawable);
+    method public void setModal(boolean);
+    method public void setOnDismissListener(android.widget.PopupWindow.OnDismissListener);
+    method public void setOnItemClickListener(android.widget.AdapterView.OnItemClickListener);
+    method public void setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener);
+    method public void setPromptPosition(int);
+    method public void setPromptView(android.view.View);
+    method public void setSelection(int);
+    method public void setSoftInputMode(int);
+    method public void setVerticalOffset(int);
+    method public void setWidth(int);
+    method public void show();
+    field public static final int INPUT_METHOD_FROM_FOCUSABLE = 0; // 0x0
+    field public static final int INPUT_METHOD_NEEDED = 1; // 0x1
+    field public static final int INPUT_METHOD_NOT_NEEDED = 2; // 0x2
+    field public static final int MATCH_PARENT = -1; // 0xffffffff
+    field public static final int POSITION_PROMPT_ABOVE = 0; // 0x0
+    field public static final int POSITION_PROMPT_BELOW = 1; // 0x1
+    field public static final int WRAP_CONTENT = -2; // 0xfffffffe
+  }
+
+  public class ListView extends android.widget.AbsListView {
+    ctor public ListView(android.content.Context);
+    ctor public ListView(android.content.Context, android.util.AttributeSet);
+    ctor public ListView(android.content.Context, android.util.AttributeSet, int);
+    method public void addFooterView(android.view.View, java.lang.Object, boolean);
+    method public void addFooterView(android.view.View);
+    method public void addHeaderView(android.view.View, java.lang.Object, boolean);
+    method public void addHeaderView(android.view.View);
+    method protected android.view.View findViewTraversal(int);
+    method protected android.view.View findViewWithTagTraversal(java.lang.Object);
+    method public android.widget.ListAdapter getAdapter();
+    method public deprecated long[] getCheckItemIds();
+    method public android.graphics.drawable.Drawable getDivider();
+    method public int getDividerHeight();
+    method public int getFooterViewsCount();
+    method public int getHeaderViewsCount();
+    method public boolean getItemsCanFocus();
+    method public int getMaxScrollAmount();
+    method public android.graphics.drawable.Drawable getOverscrollFooter();
+    method public android.graphics.drawable.Drawable getOverscrollHeader();
+    method public boolean removeFooterView(android.view.View);
+    method public boolean removeHeaderView(android.view.View);
+    method public void setDivider(android.graphics.drawable.Drawable);
+    method public void setDividerHeight(int);
+    method public void setFooterDividersEnabled(boolean);
+    method public void setHeaderDividersEnabled(boolean);
+    method public void setItemsCanFocus(boolean);
+    method public void setOverscrollFooter(android.graphics.drawable.Drawable);
+    method public void setOverscrollHeader(android.graphics.drawable.Drawable);
+    method public void setSelection(int);
+    method public void setSelectionAfterHeaderView();
+    method public void setSelectionFromTop(int, int);
+    method public void smoothScrollByOffset(int);
+  }
+
+  public class ListView.FixedViewInfo {
+    ctor public ListView.FixedViewInfo();
+    field public java.lang.Object data;
+    field public boolean isSelectable;
+    field public android.view.View view;
+  }
+
+  public class MediaController extends android.widget.FrameLayout {
+    ctor public MediaController(android.content.Context, android.util.AttributeSet);
+    ctor public MediaController(android.content.Context, boolean);
+    ctor public MediaController(android.content.Context);
+    method public void hide();
+    method public boolean isShowing();
+    method public void onFinishInflate();
+    method public void setAnchorView(android.view.View);
+    method public void setMediaPlayer(android.widget.MediaController.MediaPlayerControl);
+    method public void setPrevNextListeners(android.view.View.OnClickListener, android.view.View.OnClickListener);
+    method public void show();
+    method public void show(int);
+  }
+
+  public static abstract interface MediaController.MediaPlayerControl {
+    method public abstract boolean canPause();
+    method public abstract boolean canSeekBackward();
+    method public abstract boolean canSeekForward();
+    method public abstract int getBufferPercentage();
+    method public abstract int getCurrentPosition();
+    method public abstract int getDuration();
+    method public abstract boolean isPlaying();
+    method public abstract void pause();
+    method public abstract void seekTo(int);
+    method public abstract void start();
+  }
+
+  public class MultiAutoCompleteTextView extends android.widget.AutoCompleteTextView {
+    ctor public MultiAutoCompleteTextView(android.content.Context);
+    ctor public MultiAutoCompleteTextView(android.content.Context, android.util.AttributeSet);
+    ctor public MultiAutoCompleteTextView(android.content.Context, android.util.AttributeSet, int);
+    method protected void performFiltering(java.lang.CharSequence, int, int, int);
+    method public void setTokenizer(android.widget.MultiAutoCompleteTextView.Tokenizer);
+  }
+
+  public static class MultiAutoCompleteTextView.CommaTokenizer implements android.widget.MultiAutoCompleteTextView.Tokenizer {
+    ctor public MultiAutoCompleteTextView.CommaTokenizer();
+    method public int findTokenEnd(java.lang.CharSequence, int);
+    method public int findTokenStart(java.lang.CharSequence, int);
+    method public java.lang.CharSequence terminateToken(java.lang.CharSequence);
+  }
+
+  public static abstract interface MultiAutoCompleteTextView.Tokenizer {
+    method public abstract int findTokenEnd(java.lang.CharSequence, int);
+    method public abstract int findTokenStart(java.lang.CharSequence, int);
+    method public abstract java.lang.CharSequence terminateToken(java.lang.CharSequence);
+  }
+
+  public class NumberPicker extends android.widget.LinearLayout {
+    ctor public NumberPicker(android.content.Context);
+    ctor public NumberPicker(android.content.Context, android.util.AttributeSet);
+    ctor public NumberPicker(android.content.Context, android.util.AttributeSet, int);
+    method public java.lang.String[] getDisplayedValues();
+    method public int getMaxValue();
+    method public int getMinValue();
+    method public int getValue();
+    method public boolean getWrapSelectorWheel();
+    method public void setDisplayedValues(java.lang.String[]);
+    method public void setFormatter(android.widget.NumberPicker.Formatter);
+    method public void setMaxValue(int);
+    method public void setMinValue(int);
+    method public void setOnLongPressUpdateInterval(long);
+    method public void setOnScrollListener(android.widget.NumberPicker.OnScrollListener);
+    method public void setOnValueChangedListener(android.widget.NumberPicker.OnValueChangeListener);
+    method public void setValue(int);
+    method public void setWrapSelectorWheel(boolean);
+  }
+
+  public static abstract interface NumberPicker.Formatter {
+    method public abstract java.lang.String format(int);
+  }
+
+  public static abstract interface NumberPicker.OnScrollListener {
+    method public abstract void onScrollStateChange(android.widget.NumberPicker, int);
+    field public static final int SCROLL_STATE_FLING = 2; // 0x2
+    field public static final int SCROLL_STATE_IDLE = 0; // 0x0
+    field public static final int SCROLL_STATE_TOUCH_SCROLL = 1; // 0x1
+  }
+
+  public static abstract interface NumberPicker.OnValueChangeListener {
+    method public abstract void onValueChange(android.widget.NumberPicker, int, int);
+  }
+
+  public class OverScroller {
+    ctor public OverScroller(android.content.Context);
+    ctor public OverScroller(android.content.Context, android.view.animation.Interpolator);
+    ctor public OverScroller(android.content.Context, android.view.animation.Interpolator, float, float);
+    ctor public OverScroller(android.content.Context, android.view.animation.Interpolator, float, float, boolean);
+    method public void abortAnimation();
+    method public boolean computeScrollOffset();
+    method public void fling(int, int, int, int, int, int, int, int);
+    method public void fling(int, int, int, int, int, int, int, int, int, int);
+    method public final void forceFinished(boolean);
+    method public float getCurrVelocity();
+    method public final int getCurrX();
+    method public final int getCurrY();
+    method public final int getFinalX();
+    method public final int getFinalY();
+    method public final int getStartX();
+    method public final int getStartY();
+    method public final boolean isFinished();
+    method public boolean isOverScrolled();
+    method public void notifyHorizontalEdgeReached(int, int, int);
+    method public void notifyVerticalEdgeReached(int, int, int);
+    method public final void setFriction(float);
+    method public boolean springBack(int, int, int, int, int, int);
+    method public void startScroll(int, int, int, int);
+    method public void startScroll(int, int, int, int, int);
+  }
+
+  public class PopupMenu {
+    ctor public PopupMenu(android.content.Context, android.view.View);
+    method public void dismiss();
+    method public android.view.Menu getMenu();
+    method public android.view.MenuInflater getMenuInflater();
+    method public void inflate(int);
+    method public void setOnDismissListener(android.widget.PopupMenu.OnDismissListener);
+    method public void setOnMenuItemClickListener(android.widget.PopupMenu.OnMenuItemClickListener);
+    method public void show();
+  }
+
+  public static abstract interface PopupMenu.OnDismissListener {
+    method public abstract void onDismiss(android.widget.PopupMenu);
+  }
+
+  public static abstract interface PopupMenu.OnMenuItemClickListener {
+    method public abstract boolean onMenuItemClick(android.view.MenuItem);
+  }
+
+  public class PopupWindow {
+    ctor public PopupWindow(android.content.Context);
+    ctor public PopupWindow(android.content.Context, android.util.AttributeSet);
+    ctor public PopupWindow(android.content.Context, android.util.AttributeSet, int);
+    ctor public PopupWindow(android.content.Context, android.util.AttributeSet, int, int);
+    ctor public PopupWindow();
+    ctor public PopupWindow(android.view.View);
+    ctor public PopupWindow(int, int);
+    ctor public PopupWindow(android.view.View, int, int);
+    ctor public PopupWindow(android.view.View, int, int, boolean);
+    method public void dismiss();
+    method public int getAnimationStyle();
+    method public android.graphics.drawable.Drawable getBackground();
+    method public android.view.View getContentView();
+    method public int getHeight();
+    method public int getInputMethodMode();
+    method public int getMaxAvailableHeight(android.view.View);
+    method public int getMaxAvailableHeight(android.view.View, int);
+    method public int getSoftInputMode();
+    method public int getWidth();
+    method public boolean isAboveAnchor();
+    method public boolean isClippingEnabled();
+    method public boolean isFocusable();
+    method public boolean isOutsideTouchable();
+    method public boolean isShowing();
+    method public boolean isSplitTouchEnabled();
+    method public boolean isTouchable();
+    method public void setAnimationStyle(int);
+    method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public void setClippingEnabled(boolean);
+    method public void setContentView(android.view.View);
+    method public void setFocusable(boolean);
+    method public void setHeight(int);
+    method public void setIgnoreCheekPress();
+    method public void setInputMethodMode(int);
+    method public void setOnDismissListener(android.widget.PopupWindow.OnDismissListener);
+    method public void setOutsideTouchable(boolean);
+    method public void setSoftInputMode(int);
+    method public void setSplitTouchEnabled(boolean);
+    method public void setTouchInterceptor(android.view.View.OnTouchListener);
+    method public void setTouchable(boolean);
+    method public void setWidth(int);
+    method public void setWindowLayoutMode(int, int);
+    method public void showAsDropDown(android.view.View);
+    method public void showAsDropDown(android.view.View, int, int);
+    method public void showAtLocation(android.view.View, int, int, int);
+    method public void update();
+    method public void update(int, int);
+    method public void update(int, int, int, int);
+    method public void update(int, int, int, int, boolean);
+    method public void update(android.view.View, int, int);
+    method public void update(android.view.View, int, int, int, int);
+    field public static final int INPUT_METHOD_FROM_FOCUSABLE = 0; // 0x0
+    field public static final int INPUT_METHOD_NEEDED = 1; // 0x1
+    field public static final int INPUT_METHOD_NOT_NEEDED = 2; // 0x2
+  }
+
+  public static abstract interface PopupWindow.OnDismissListener {
+    method public abstract void onDismiss();
+  }
+
+  public class ProgressBar extends android.view.View {
+    ctor public ProgressBar(android.content.Context);
+    ctor public ProgressBar(android.content.Context, android.util.AttributeSet);
+    ctor public ProgressBar(android.content.Context, android.util.AttributeSet, int);
+    method public android.graphics.drawable.Drawable getIndeterminateDrawable();
+    method public android.view.animation.Interpolator getInterpolator();
+    method public synchronized int getMax();
+    method public synchronized int getProgress();
+    method public android.graphics.drawable.Drawable getProgressDrawable();
+    method public synchronized int getSecondaryProgress();
+    method public final synchronized void incrementProgressBy(int);
+    method public final synchronized void incrementSecondaryProgressBy(int);
+    method public synchronized boolean isIndeterminate();
+    method public void onRestoreInstanceState(android.os.Parcelable);
+    method public android.os.Parcelable onSaveInstanceState();
+    method public synchronized void setIndeterminate(boolean);
+    method public void setIndeterminateDrawable(android.graphics.drawable.Drawable);
+    method public void setInterpolator(android.content.Context, int);
+    method public void setInterpolator(android.view.animation.Interpolator);
+    method public synchronized void setMax(int);
+    method public synchronized void setProgress(int);
+    method public void setProgressDrawable(android.graphics.drawable.Drawable);
+    method public synchronized void setSecondaryProgress(int);
+  }
+
+  public class QuickContactBadge extends android.widget.ImageView implements android.view.View.OnClickListener {
+    ctor public QuickContactBadge(android.content.Context);
+    ctor public QuickContactBadge(android.content.Context, android.util.AttributeSet);
+    ctor public QuickContactBadge(android.content.Context, android.util.AttributeSet, int);
+    method public void assignContactFromEmail(java.lang.String, boolean);
+    method public void assignContactFromPhone(java.lang.String, boolean);
+    method public void assignContactUri(android.net.Uri);
+    method public void onClick(android.view.View);
+    method public void setExcludeMimes(java.lang.String[]);
+    method public void setImageToDefault();
+    method public void setMode(int);
+    field protected java.lang.String[] mExcludeMimes;
+  }
+
+  public class RadioButton extends android.widget.CompoundButton {
+    ctor public RadioButton(android.content.Context);
+    ctor public RadioButton(android.content.Context, android.util.AttributeSet);
+    ctor public RadioButton(android.content.Context, android.util.AttributeSet, int);
+  }
+
+  public class RadioGroup extends android.widget.LinearLayout {
+    ctor public RadioGroup(android.content.Context);
+    ctor public RadioGroup(android.content.Context, android.util.AttributeSet);
+    method public void check(int);
+    method public void clearCheck();
+    method public int getCheckedRadioButtonId();
+    method public void setOnCheckedChangeListener(android.widget.RadioGroup.OnCheckedChangeListener);
+  }
+
+  public static class RadioGroup.LayoutParams extends android.widget.LinearLayout.LayoutParams {
+    ctor public RadioGroup.LayoutParams(android.content.Context, android.util.AttributeSet);
+    ctor public RadioGroup.LayoutParams(int, int);
+    ctor public RadioGroup.LayoutParams(int, int, float);
+    ctor public RadioGroup.LayoutParams(android.view.ViewGroup.LayoutParams);
+    ctor public RadioGroup.LayoutParams(android.view.ViewGroup.MarginLayoutParams);
+  }
+
+  public static abstract interface RadioGroup.OnCheckedChangeListener {
+    method public abstract void onCheckedChanged(android.widget.RadioGroup, int);
+  }
+
+  public class RatingBar extends android.widget.AbsSeekBar {
+    ctor public RatingBar(android.content.Context, android.util.AttributeSet, int);
+    ctor public RatingBar(android.content.Context, android.util.AttributeSet);
+    ctor public RatingBar(android.content.Context);
+    method public int getNumStars();
+    method public android.widget.RatingBar.OnRatingBarChangeListener getOnRatingBarChangeListener();
+    method public float getRating();
+    method public float getStepSize();
+    method public boolean isIndicator();
+    method public void setIsIndicator(boolean);
+    method public void setNumStars(int);
+    method public void setOnRatingBarChangeListener(android.widget.RatingBar.OnRatingBarChangeListener);
+    method public void setRating(float);
+    method public void setStepSize(float);
+  }
+
+  public static abstract interface RatingBar.OnRatingBarChangeListener {
+    method public abstract void onRatingChanged(android.widget.RatingBar, float, boolean);
+  }
+
+  public class RelativeLayout extends android.view.ViewGroup {
+    ctor public RelativeLayout(android.content.Context);
+    ctor public RelativeLayout(android.content.Context, android.util.AttributeSet);
+    ctor public RelativeLayout(android.content.Context, android.util.AttributeSet, int);
+    method public int getGravity();
+    method protected void onLayout(boolean, int, int, int, int);
+    method public void setGravity(int);
+    method public void setHorizontalGravity(int);
+    method public void setIgnoreGravity(int);
+    method public void setVerticalGravity(int);
+    field public static final int ABOVE = 2; // 0x2
+    field public static final int ALIGN_BASELINE = 4; // 0x4
+    field public static final int ALIGN_BOTTOM = 8; // 0x8
+    field public static final int ALIGN_END = 19; // 0x13
+    field public static final int ALIGN_LEFT = 5; // 0x5
+    field public static final int ALIGN_PARENT_BOTTOM = 12; // 0xc
+    field public static final int ALIGN_PARENT_END = 21; // 0x15
+    field public static final int ALIGN_PARENT_LEFT = 9; // 0x9
+    field public static final int ALIGN_PARENT_RIGHT = 11; // 0xb
+    field public static final int ALIGN_PARENT_START = 20; // 0x14
+    field public static final int ALIGN_PARENT_TOP = 10; // 0xa
+    field public static final int ALIGN_RIGHT = 7; // 0x7
+    field public static final int ALIGN_START = 18; // 0x12
+    field public static final int ALIGN_TOP = 6; // 0x6
+    field public static final int BELOW = 3; // 0x3
+    field public static final int CENTER_HORIZONTAL = 14; // 0xe
+    field public static final int CENTER_IN_PARENT = 13; // 0xd
+    field public static final int CENTER_VERTICAL = 15; // 0xf
+    field public static final int END_OF = 17; // 0x11
+    field public static final int LEFT_OF = 0; // 0x0
+    field public static final int RIGHT_OF = 1; // 0x1
+    field public static final int START_OF = 16; // 0x10
+    field public static final int TRUE = -1; // 0xffffffff
+  }
+
+  public static class RelativeLayout.LayoutParams extends android.view.ViewGroup.MarginLayoutParams {
+    ctor public RelativeLayout.LayoutParams(android.content.Context, android.util.AttributeSet);
+    ctor public RelativeLayout.LayoutParams(int, int);
+    ctor public RelativeLayout.LayoutParams(android.view.ViewGroup.LayoutParams);
+    ctor public RelativeLayout.LayoutParams(android.view.ViewGroup.MarginLayoutParams);
+    method public void addRule(int);
+    method public void addRule(int, int);
+    method public java.lang.String debug(java.lang.String);
+    method public int[] getRules();
+    method public void removeRule(int);
+    field public boolean alignWithParent;
+  }
+
+  public class RemoteViews implements android.view.LayoutInflater.Filter android.os.Parcelable {
+    ctor public RemoteViews(java.lang.String, int);
+    ctor public RemoteViews(android.widget.RemoteViews, android.widget.RemoteViews);
+    ctor public RemoteViews(android.os.Parcel);
+    method public void addView(int, android.widget.RemoteViews);
+    method public android.view.View apply(android.content.Context, android.view.ViewGroup);
+    method public android.widget.RemoteViews clone();
+    method public int describeContents();
+    method public int getLayoutId();
+    method public java.lang.String getPackage();
+    method public boolean onLoadClass(java.lang.Class);
+    method public void reapply(android.content.Context, android.view.View);
+    method public void removeAllViews(int);
+    method public void setBitmap(int, java.lang.String, android.graphics.Bitmap);
+    method public void setBoolean(int, java.lang.String, boolean);
+    method public void setBundle(int, java.lang.String, android.os.Bundle);
+    method public void setByte(int, java.lang.String, byte);
+    method public void setChar(int, java.lang.String, char);
+    method public void setCharSequence(int, java.lang.String, java.lang.CharSequence);
+    method public void setChronometer(int, long, java.lang.String, boolean);
+    method public void setContentDescription(int, java.lang.CharSequence);
+    method public void setDisplayedChild(int, int);
+    method public void setDouble(int, java.lang.String, double);
+    method public void setEmptyView(int, int);
+    method public void setFloat(int, java.lang.String, float);
+    method public void setImageViewBitmap(int, android.graphics.Bitmap);
+    method public void setImageViewResource(int, int);
+    method public void setImageViewUri(int, android.net.Uri);
+    method public void setInt(int, java.lang.String, int);
+    method public void setIntent(int, java.lang.String, android.content.Intent);
+    method public void setLabelFor(int, int);
+    method public void setLong(int, java.lang.String, long);
+    method public void setOnClickFillInIntent(int, android.content.Intent);
+    method public void setOnClickPendingIntent(int, android.app.PendingIntent);
+    method public void setPendingIntentTemplate(int, android.app.PendingIntent);
+    method public void setProgressBar(int, int, int, boolean);
+    method public void setRelativeScrollPosition(int, int);
+    method public deprecated void setRemoteAdapter(int, int, android.content.Intent);
+    method public void setRemoteAdapter(int, android.content.Intent);
+    method public void setScrollPosition(int, int);
+    method public void setShort(int, java.lang.String, short);
+    method public void setString(int, java.lang.String, java.lang.String);
+    method public void setTextColor(int, int);
+    method public void setTextViewCompoundDrawables(int, int, int, int, int);
+    method public void setTextViewCompoundDrawablesRelative(int, int, int, int, int);
+    method public void setTextViewText(int, java.lang.CharSequence);
+    method public void setTextViewTextSize(int, int, float);
+    method public void setUri(int, java.lang.String, android.net.Uri);
+    method public void setViewPadding(int, int, int, int, int);
+    method public void setViewVisibility(int, int);
+    method public void showNext(int);
+    method public void showPrevious(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static class RemoteViews.ActionException extends java.lang.RuntimeException {
+    ctor public RemoteViews.ActionException(java.lang.Exception);
+    ctor public RemoteViews.ActionException(java.lang.String);
+  }
+
+  public static abstract class RemoteViews.RemoteView implements java.lang.annotation.Annotation {
+  }
+
+  public abstract class RemoteViewsService extends android.app.Service {
+    ctor public RemoteViewsService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract android.widget.RemoteViewsService.RemoteViewsFactory onGetViewFactory(android.content.Intent);
+  }
+
+  public static abstract interface RemoteViewsService.RemoteViewsFactory {
+    method public abstract int getCount();
+    method public abstract long getItemId(int);
+    method public abstract android.widget.RemoteViews getLoadingView();
+    method public abstract android.widget.RemoteViews getViewAt(int);
+    method public abstract int getViewTypeCount();
+    method public abstract boolean hasStableIds();
+    method public abstract void onCreate();
+    method public abstract void onDataSetChanged();
+    method public abstract void onDestroy();
+  }
+
+  public abstract class ResourceCursorAdapter extends android.widget.CursorAdapter {
+    ctor public deprecated ResourceCursorAdapter(android.content.Context, int, android.database.Cursor);
+    ctor public ResourceCursorAdapter(android.content.Context, int, android.database.Cursor, boolean);
+    ctor public ResourceCursorAdapter(android.content.Context, int, android.database.Cursor, int);
+    method public android.view.View newView(android.content.Context, android.database.Cursor, android.view.ViewGroup);
+    method public void setDropDownViewResource(int);
+    method public void setViewResource(int);
+  }
+
+  public abstract class ResourceCursorTreeAdapter extends android.widget.CursorTreeAdapter {
+    ctor public ResourceCursorTreeAdapter(android.content.Context, android.database.Cursor, int, int, int, int);
+    ctor public ResourceCursorTreeAdapter(android.content.Context, android.database.Cursor, int, int, int);
+    ctor public ResourceCursorTreeAdapter(android.content.Context, android.database.Cursor, int, int);
+    method public android.view.View newChildView(android.content.Context, android.database.Cursor, boolean, android.view.ViewGroup);
+    method public android.view.View newGroupView(android.content.Context, android.database.Cursor, boolean, android.view.ViewGroup);
+  }
+
+  public class ScrollView extends android.widget.FrameLayout {
+    ctor public ScrollView(android.content.Context);
+    ctor public ScrollView(android.content.Context, android.util.AttributeSet);
+    ctor public ScrollView(android.content.Context, android.util.AttributeSet, int);
+    method public boolean arrowScroll(int);
+    method protected int computeScrollDeltaToGetChildRectOnScreen(android.graphics.Rect);
+    method public boolean executeKeyEvent(android.view.KeyEvent);
+    method public void fling(int);
+    method public boolean fullScroll(int);
+    method public int getMaxScrollAmount();
+    method public boolean isFillViewport();
+    method public boolean isSmoothScrollingEnabled();
+    method public boolean pageScroll(int);
+    method public void setFillViewport(boolean);
+    method public void setSmoothScrollingEnabled(boolean);
+    method public final void smoothScrollBy(int, int);
+    method public final void smoothScrollTo(int, int);
+  }
+
+  public class Scroller {
+    ctor public Scroller(android.content.Context);
+    ctor public Scroller(android.content.Context, android.view.animation.Interpolator);
+    ctor public Scroller(android.content.Context, android.view.animation.Interpolator, boolean);
+    method public void abortAnimation();
+    method public boolean computeScrollOffset();
+    method public void extendDuration(int);
+    method public void fling(int, int, int, int, int, int, int, int);
+    method public final void forceFinished(boolean);
+    method public float getCurrVelocity();
+    method public final int getCurrX();
+    method public final int getCurrY();
+    method public final int getDuration();
+    method public final int getFinalX();
+    method public final int getFinalY();
+    method public final int getStartX();
+    method public final int getStartY();
+    method public final boolean isFinished();
+    method public void setFinalX(int);
+    method public void setFinalY(int);
+    method public final void setFriction(float);
+    method public void startScroll(int, int, int, int);
+    method public void startScroll(int, int, int, int, int);
+    method public int timePassed();
+  }
+
+  public class SearchView extends android.widget.LinearLayout implements android.view.CollapsibleActionView {
+    ctor public SearchView(android.content.Context);
+    ctor public SearchView(android.content.Context, android.util.AttributeSet);
+    method public int getImeOptions();
+    method public int getInputType();
+    method public int getMaxWidth();
+    method public java.lang.CharSequence getQuery();
+    method public java.lang.CharSequence getQueryHint();
+    method public android.widget.CursorAdapter getSuggestionsAdapter();
+    method public boolean isIconfiedByDefault();
+    method public boolean isIconified();
+    method public boolean isQueryRefinementEnabled();
+    method public boolean isSubmitButtonEnabled();
+    method public void onActionViewCollapsed();
+    method public void onActionViewExpanded();
+    method public void setIconified(boolean);
+    method public void setIconifiedByDefault(boolean);
+    method public void setImeOptions(int);
+    method public void setInputType(int);
+    method public void setMaxWidth(int);
+    method public void setOnCloseListener(android.widget.SearchView.OnCloseListener);
+    method public void setOnQueryTextFocusChangeListener(android.view.View.OnFocusChangeListener);
+    method public void setOnQueryTextListener(android.widget.SearchView.OnQueryTextListener);
+    method public void setOnSearchClickListener(android.view.View.OnClickListener);
+    method public void setOnSuggestionListener(android.widget.SearchView.OnSuggestionListener);
+    method public void setQuery(java.lang.CharSequence, boolean);
+    method public void setQueryHint(java.lang.CharSequence);
+    method public void setQueryRefinementEnabled(boolean);
+    method public void setSearchableInfo(android.app.SearchableInfo);
+    method public void setSubmitButtonEnabled(boolean);
+    method public void setSuggestionsAdapter(android.widget.CursorAdapter);
+  }
+
+  public static abstract interface SearchView.OnCloseListener {
+    method public abstract boolean onClose();
+  }
+
+  public static abstract interface SearchView.OnQueryTextListener {
+    method public abstract boolean onQueryTextChange(java.lang.String);
+    method public abstract boolean onQueryTextSubmit(java.lang.String);
+  }
+
+  public static abstract interface SearchView.OnSuggestionListener {
+    method public abstract boolean onSuggestionClick(int);
+    method public abstract boolean onSuggestionSelect(int);
+  }
+
+  public abstract interface SectionIndexer {
+    method public abstract int getPositionForSection(int);
+    method public abstract int getSectionForPosition(int);
+    method public abstract java.lang.Object[] getSections();
+  }
+
+  public class SeekBar extends android.widget.AbsSeekBar {
+    ctor public SeekBar(android.content.Context);
+    ctor public SeekBar(android.content.Context, android.util.AttributeSet);
+    ctor public SeekBar(android.content.Context, android.util.AttributeSet, int);
+    method public void setOnSeekBarChangeListener(android.widget.SeekBar.OnSeekBarChangeListener);
+  }
+
+  public static abstract interface SeekBar.OnSeekBarChangeListener {
+    method public abstract void onProgressChanged(android.widget.SeekBar, int, boolean);
+    method public abstract void onStartTrackingTouch(android.widget.SeekBar);
+    method public abstract void onStopTrackingTouch(android.widget.SeekBar);
+  }
+
+  public class ShareActionProvider extends android.view.ActionProvider {
+    ctor public ShareActionProvider(android.content.Context);
+    method public android.view.View onCreateActionView();
+    method public void setOnShareTargetSelectedListener(android.widget.ShareActionProvider.OnShareTargetSelectedListener);
+    method public void setShareHistoryFileName(java.lang.String);
+    method public void setShareIntent(android.content.Intent);
+    field public static final java.lang.String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";
+  }
+
+  public static abstract interface ShareActionProvider.OnShareTargetSelectedListener {
+    method public abstract boolean onShareTargetSelected(android.widget.ShareActionProvider, android.content.Intent);
+  }
+
+  public class SimpleAdapter extends android.widget.BaseAdapter implements android.widget.Filterable {
+    ctor public SimpleAdapter(android.content.Context, java.util.List<? extends java.util.Map<java.lang.String, ?>>, int, java.lang.String[], int[]);
+    method public int getCount();
+    method public android.widget.Filter getFilter();
+    method public java.lang.Object getItem(int);
+    method public long getItemId(int);
+    method public android.view.View getView(int, android.view.View, android.view.ViewGroup);
+    method public android.widget.SimpleAdapter.ViewBinder getViewBinder();
+    method public void setDropDownViewResource(int);
+    method public void setViewBinder(android.widget.SimpleAdapter.ViewBinder);
+    method public void setViewImage(android.widget.ImageView, int);
+    method public void setViewImage(android.widget.ImageView, java.lang.String);
+    method public void setViewText(android.widget.TextView, java.lang.String);
+  }
+
+  public static abstract interface SimpleAdapter.ViewBinder {
+    method public abstract boolean setViewValue(android.view.View, java.lang.Object, java.lang.String);
+  }
+
+  public class SimpleCursorAdapter extends android.widget.ResourceCursorAdapter {
+    ctor public deprecated SimpleCursorAdapter(android.content.Context, int, android.database.Cursor, java.lang.String[], int[]);
+    ctor public SimpleCursorAdapter(android.content.Context, int, android.database.Cursor, java.lang.String[], int[], int);
+    method public void bindView(android.view.View, android.content.Context, android.database.Cursor);
+    method public void changeCursorAndColumns(android.database.Cursor, java.lang.String[], int[]);
+    method public android.widget.SimpleCursorAdapter.CursorToStringConverter getCursorToStringConverter();
+    method public int getStringConversionColumn();
+    method public android.widget.SimpleCursorAdapter.ViewBinder getViewBinder();
+    method public void setCursorToStringConverter(android.widget.SimpleCursorAdapter.CursorToStringConverter);
+    method public void setStringConversionColumn(int);
+    method public void setViewBinder(android.widget.SimpleCursorAdapter.ViewBinder);
+    method public void setViewImage(android.widget.ImageView, java.lang.String);
+    method public void setViewText(android.widget.TextView, java.lang.String);
+  }
+
+  public static abstract interface SimpleCursorAdapter.CursorToStringConverter {
+    method public abstract java.lang.CharSequence convertToString(android.database.Cursor);
+  }
+
+  public static abstract interface SimpleCursorAdapter.ViewBinder {
+    method public abstract boolean setViewValue(android.view.View, android.database.Cursor, int);
+  }
+
+  public abstract class SimpleCursorTreeAdapter extends android.widget.ResourceCursorTreeAdapter {
+    ctor public SimpleCursorTreeAdapter(android.content.Context, android.database.Cursor, int, int, java.lang.String[], int[], int, int, java.lang.String[], int[]);
+    ctor public SimpleCursorTreeAdapter(android.content.Context, android.database.Cursor, int, int, java.lang.String[], int[], int, java.lang.String[], int[]);
+    ctor public SimpleCursorTreeAdapter(android.content.Context, android.database.Cursor, int, java.lang.String[], int[], int, java.lang.String[], int[]);
+    method protected void bindChildView(android.view.View, android.content.Context, android.database.Cursor, boolean);
+    method protected void bindGroupView(android.view.View, android.content.Context, android.database.Cursor, boolean);
+    method public android.widget.SimpleCursorTreeAdapter.ViewBinder getViewBinder();
+    method public void setViewBinder(android.widget.SimpleCursorTreeAdapter.ViewBinder);
+    method protected void setViewImage(android.widget.ImageView, java.lang.String);
+    method public void setViewText(android.widget.TextView, java.lang.String);
+  }
+
+  public static abstract interface SimpleCursorTreeAdapter.ViewBinder {
+    method public abstract boolean setViewValue(android.view.View, android.database.Cursor, int);
+  }
+
+  public class SimpleExpandableListAdapter extends android.widget.BaseExpandableListAdapter {
+    ctor public SimpleExpandableListAdapter(android.content.Context, java.util.List<? extends java.util.Map<java.lang.String, ?>>, int, java.lang.String[], int[], java.util.List<? extends java.util.List<? extends java.util.Map<java.lang.String, ?>>>, int, java.lang.String[], int[]);
+    ctor public SimpleExpandableListAdapter(android.content.Context, java.util.List<? extends java.util.Map<java.lang.String, ?>>, int, int, java.lang.String[], int[], java.util.List<? extends java.util.List<? extends java.util.Map<java.lang.String, ?>>>, int, java.lang.String[], int[]);
+    ctor public SimpleExpandableListAdapter(android.content.Context, java.util.List<? extends java.util.Map<java.lang.String, ?>>, int, int, java.lang.String[], int[], java.util.List<? extends java.util.List<? extends java.util.Map<java.lang.String, ?>>>, int, int, java.lang.String[], int[]);
+    method public java.lang.Object getChild(int, int);
+    method public long getChildId(int, int);
+    method public android.view.View getChildView(int, int, boolean, android.view.View, android.view.ViewGroup);
+    method public int getChildrenCount(int);
+    method public java.lang.Object getGroup(int);
+    method public int getGroupCount();
+    method public long getGroupId(int);
+    method public android.view.View getGroupView(int, boolean, android.view.View, android.view.ViewGroup);
+    method public boolean hasStableIds();
+    method public boolean isChildSelectable(int, int);
+    method public android.view.View newChildView(boolean, android.view.ViewGroup);
+    method public android.view.View newGroupView(boolean, android.view.ViewGroup);
+  }
+
+  public deprecated class SlidingDrawer extends android.view.ViewGroup {
+    ctor public SlidingDrawer(android.content.Context, android.util.AttributeSet);
+    ctor public SlidingDrawer(android.content.Context, android.util.AttributeSet, int);
+    method public void animateClose();
+    method public void animateOpen();
+    method public void animateToggle();
+    method public void close();
+    method public android.view.View getContent();
+    method public android.view.View getHandle();
+    method public boolean isMoving();
+    method public boolean isOpened();
+    method public void lock();
+    method protected void onLayout(boolean, int, int, int, int);
+    method public void open();
+    method public void setOnDrawerCloseListener(android.widget.SlidingDrawer.OnDrawerCloseListener);
+    method public void setOnDrawerOpenListener(android.widget.SlidingDrawer.OnDrawerOpenListener);
+    method public void setOnDrawerScrollListener(android.widget.SlidingDrawer.OnDrawerScrollListener);
+    method public void toggle();
+    method public void unlock();
+    field public static final int ORIENTATION_HORIZONTAL = 0; // 0x0
+    field public static final int ORIENTATION_VERTICAL = 1; // 0x1
+  }
+
+  public static abstract interface SlidingDrawer.OnDrawerCloseListener {
+    method public abstract void onDrawerClosed();
+  }
+
+  public static abstract interface SlidingDrawer.OnDrawerOpenListener {
+    method public abstract void onDrawerOpened();
+  }
+
+  public static abstract interface SlidingDrawer.OnDrawerScrollListener {
+    method public abstract void onScrollEnded();
+    method public abstract void onScrollStarted();
+  }
+
+  public final class Space extends android.view.View {
+    ctor public Space(android.content.Context, android.util.AttributeSet, int);
+    ctor public Space(android.content.Context, android.util.AttributeSet);
+    ctor public Space(android.content.Context);
+  }
+
+  public class Spinner extends android.widget.AbsSpinner implements android.content.DialogInterface.OnClickListener {
+    ctor public Spinner(android.content.Context);
+    ctor public Spinner(android.content.Context, int);
+    ctor public Spinner(android.content.Context, android.util.AttributeSet);
+    ctor public Spinner(android.content.Context, android.util.AttributeSet, int);
+    ctor public Spinner(android.content.Context, android.util.AttributeSet, int, int);
+    method public int getDropDownHorizontalOffset();
+    method public int getDropDownVerticalOffset();
+    method public int getDropDownWidth();
+    method public int getGravity();
+    method public android.graphics.drawable.Drawable getPopupBackground();
+    method public java.lang.CharSequence getPrompt();
+    method public void onClick(android.content.DialogInterface, int);
+    method public void setDropDownHorizontalOffset(int);
+    method public void setDropDownVerticalOffset(int);
+    method public void setDropDownWidth(int);
+    method public void setGravity(int);
+    method public void setPopupBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public void setPopupBackgroundResource(int);
+    method public void setPrompt(java.lang.CharSequence);
+    method public void setPromptId(int);
+    field public static final int MODE_DIALOG = 0; // 0x0
+    field public static final int MODE_DROPDOWN = 1; // 0x1
+  }
+
+  public abstract interface SpinnerAdapter implements android.widget.Adapter {
+    method public abstract android.view.View getDropDownView(int, android.view.View, android.view.ViewGroup);
+  }
+
+  public class StackView extends android.widget.AdapterViewAnimator {
+    ctor public StackView(android.content.Context);
+    ctor public StackView(android.content.Context, android.util.AttributeSet);
+    ctor public StackView(android.content.Context, android.util.AttributeSet, int);
+  }
+
+  public class Switch extends android.widget.CompoundButton {
+    ctor public Switch(android.content.Context);
+    ctor public Switch(android.content.Context, android.util.AttributeSet);
+    ctor public Switch(android.content.Context, android.util.AttributeSet, int);
+    method public int getSwitchMinWidth();
+    method public int getSwitchPadding();
+    method public java.lang.CharSequence getTextOff();
+    method public java.lang.CharSequence getTextOn();
+    method public android.graphics.drawable.Drawable getThumbDrawable();
+    method public int getThumbTextPadding();
+    method public android.graphics.drawable.Drawable getTrackDrawable();
+    method public void onMeasure(int, int);
+    method public void setSwitchMinWidth(int);
+    method public void setSwitchPadding(int);
+    method public void setSwitchTextAppearance(android.content.Context, int);
+    method public void setSwitchTypeface(android.graphics.Typeface, int);
+    method public void setSwitchTypeface(android.graphics.Typeface);
+    method public void setTextOff(java.lang.CharSequence);
+    method public void setTextOn(java.lang.CharSequence);
+    method public void setThumbDrawable(android.graphics.drawable.Drawable);
+    method public void setThumbResource(int);
+    method public void setThumbTextPadding(int);
+    method public void setTrackDrawable(android.graphics.drawable.Drawable);
+    method public void setTrackResource(int);
+  }
+
+  public class TabHost extends android.widget.FrameLayout implements android.view.ViewTreeObserver.OnTouchModeChangeListener {
+    ctor public TabHost(android.content.Context);
+    ctor public TabHost(android.content.Context, android.util.AttributeSet);
+    method public void addTab(android.widget.TabHost.TabSpec);
+    method public void clearAllTabs();
+    method public int getCurrentTab();
+    method public java.lang.String getCurrentTabTag();
+    method public android.view.View getCurrentTabView();
+    method public android.view.View getCurrentView();
+    method public android.widget.FrameLayout getTabContentView();
+    method public android.widget.TabWidget getTabWidget();
+    method public android.widget.TabHost.TabSpec newTabSpec(java.lang.String);
+    method public void onTouchModeChanged(boolean);
+    method public void setCurrentTab(int);
+    method public void setCurrentTabByTag(java.lang.String);
+    method public void setOnTabChangedListener(android.widget.TabHost.OnTabChangeListener);
+    method public void setup();
+    method public void setup(android.app.LocalActivityManager);
+  }
+
+  public static abstract interface TabHost.OnTabChangeListener {
+    method public abstract void onTabChanged(java.lang.String);
+  }
+
+  public static abstract interface TabHost.TabContentFactory {
+    method public abstract android.view.View createTabContent(java.lang.String);
+  }
+
+  public class TabHost.TabSpec {
+    method public java.lang.String getTag();
+    method public android.widget.TabHost.TabSpec setContent(int);
+    method public android.widget.TabHost.TabSpec setContent(android.widget.TabHost.TabContentFactory);
+    method public android.widget.TabHost.TabSpec setContent(android.content.Intent);
+    method public android.widget.TabHost.TabSpec setIndicator(java.lang.CharSequence);
+    method public android.widget.TabHost.TabSpec setIndicator(java.lang.CharSequence, android.graphics.drawable.Drawable);
+    method public android.widget.TabHost.TabSpec setIndicator(android.view.View);
+  }
+
+  public class TabWidget extends android.widget.LinearLayout implements android.view.View.OnFocusChangeListener {
+    ctor public TabWidget(android.content.Context);
+    ctor public TabWidget(android.content.Context, android.util.AttributeSet);
+    ctor public TabWidget(android.content.Context, android.util.AttributeSet, int);
+    method public void dispatchDraw(android.graphics.Canvas);
+    method public void focusCurrentTab(int);
+    method public android.view.View getChildTabViewAt(int);
+    method public int getTabCount();
+    method public boolean isStripEnabled();
+    method public void onFocusChange(android.view.View, boolean);
+    method public void setCurrentTab(int);
+    method public void setDividerDrawable(int);
+    method public void setLeftStripDrawable(android.graphics.drawable.Drawable);
+    method public void setLeftStripDrawable(int);
+    method public void setRightStripDrawable(android.graphics.drawable.Drawable);
+    method public void setRightStripDrawable(int);
+    method public void setStripEnabled(boolean);
+  }
+
+  public class TableLayout extends android.widget.LinearLayout {
+    ctor public TableLayout(android.content.Context);
+    ctor public TableLayout(android.content.Context, android.util.AttributeSet);
+    method public boolean isColumnCollapsed(int);
+    method public boolean isColumnShrinkable(int);
+    method public boolean isColumnStretchable(int);
+    method public boolean isShrinkAllColumns();
+    method public boolean isStretchAllColumns();
+    method public void setColumnCollapsed(int, boolean);
+    method public void setColumnShrinkable(int, boolean);
+    method public void setColumnStretchable(int, boolean);
+    method public void setShrinkAllColumns(boolean);
+    method public void setStretchAllColumns(boolean);
+  }
+
+  public static class TableLayout.LayoutParams extends android.widget.LinearLayout.LayoutParams {
+    ctor public TableLayout.LayoutParams(android.content.Context, android.util.AttributeSet);
+    ctor public TableLayout.LayoutParams(int, int);
+    ctor public TableLayout.LayoutParams(int, int, float);
+    ctor public TableLayout.LayoutParams();
+    ctor public TableLayout.LayoutParams(android.view.ViewGroup.LayoutParams);
+    ctor public TableLayout.LayoutParams(android.view.ViewGroup.MarginLayoutParams);
+  }
+
+  public class TableRow extends android.widget.LinearLayout {
+    ctor public TableRow(android.content.Context);
+    ctor public TableRow(android.content.Context, android.util.AttributeSet);
+    method public android.view.View getVirtualChildAt(int);
+    method public int getVirtualChildCount();
+  }
+
+  public static class TableRow.LayoutParams extends android.widget.LinearLayout.LayoutParams {
+    ctor public TableRow.LayoutParams(android.content.Context, android.util.AttributeSet);
+    ctor public TableRow.LayoutParams(int, int);
+    ctor public TableRow.LayoutParams(int, int, float);
+    ctor public TableRow.LayoutParams();
+    ctor public TableRow.LayoutParams(int);
+    ctor public TableRow.LayoutParams(android.view.ViewGroup.LayoutParams);
+    ctor public TableRow.LayoutParams(android.view.ViewGroup.MarginLayoutParams);
+    field public int column;
+    field public int span;
+  }
+
+  public class TextClock extends android.widget.TextView {
+    ctor public TextClock(android.content.Context);
+    ctor public TextClock(android.content.Context, android.util.AttributeSet);
+    ctor public TextClock(android.content.Context, android.util.AttributeSet, int);
+    method public java.lang.CharSequence getFormat12Hour();
+    method public java.lang.CharSequence getFormat24Hour();
+    method public java.lang.String getTimeZone();
+    method public boolean is24HourModeEnabled();
+    method public void setFormat12Hour(java.lang.CharSequence);
+    method public void setFormat24Hour(java.lang.CharSequence);
+    method public void setTimeZone(java.lang.String);
+    field public static final java.lang.CharSequence DEFAULT_FORMAT_12_HOUR;
+    field public static final java.lang.CharSequence DEFAULT_FORMAT_24_HOUR;
+  }
+
+  public class TextSwitcher extends android.widget.ViewSwitcher {
+    ctor public TextSwitcher(android.content.Context);
+    ctor public TextSwitcher(android.content.Context, android.util.AttributeSet);
+    method public void setCurrentText(java.lang.CharSequence);
+    method public void setText(java.lang.CharSequence);
+  }
+
+  public class TextView extends android.view.View implements android.view.ViewTreeObserver.OnPreDrawListener {
+    ctor public TextView(android.content.Context);
+    ctor public TextView(android.content.Context, android.util.AttributeSet);
+    ctor public TextView(android.content.Context, android.util.AttributeSet, int);
+    method public void addTextChangedListener(android.text.TextWatcher);
+    method public final void append(java.lang.CharSequence);
+    method public void append(java.lang.CharSequence, int, int);
+    method public void beginBatchEdit();
+    method public boolean bringPointIntoView(int);
+    method public void clearComposingText();
+    method public void debug(int);
+    method public boolean didTouchFocusSelect();
+    method public void endBatchEdit();
+    method public boolean extractText(android.view.inputmethod.ExtractedTextRequest, android.view.inputmethod.ExtractedText);
+    method public final int getAutoLinkMask();
+    method public int getCompoundDrawablePadding();
+    method public android.graphics.drawable.Drawable[] getCompoundDrawables();
+    method public android.graphics.drawable.Drawable[] getCompoundDrawablesRelative();
+    method public int getCompoundPaddingBottom();
+    method public int getCompoundPaddingEnd();
+    method public int getCompoundPaddingLeft();
+    method public int getCompoundPaddingRight();
+    method public int getCompoundPaddingStart();
+    method public int getCompoundPaddingTop();
+    method public final int getCurrentHintTextColor();
+    method public final int getCurrentTextColor();
+    method public android.view.ActionMode.Callback getCustomSelectionActionModeCallback();
+    method protected boolean getDefaultEditable();
+    method protected android.text.method.MovementMethod getDefaultMovementMethod();
+    method public android.text.Editable getEditableText();
+    method public android.text.TextUtils.TruncateAt getEllipsize();
+    method public java.lang.CharSequence getError();
+    method public int getExtendedPaddingBottom();
+    method public int getExtendedPaddingTop();
+    method public android.text.InputFilter[] getFilters();
+    method public boolean getFreezesText();
+    method public int getGravity();
+    method public int getHighlightColor();
+    method public java.lang.CharSequence getHint();
+    method public final android.content.res.ColorStateList getHintTextColors();
+    method public int getImeActionId();
+    method public java.lang.CharSequence getImeActionLabel();
+    method public int getImeOptions();
+    method public boolean getIncludeFontPadding();
+    method public android.os.Bundle getInputExtras(boolean);
+    method public int getInputType();
+    method public final android.text.method.KeyListener getKeyListener();
+    method public final android.text.Layout getLayout();
+    method public int getLineBounds(int, android.graphics.Rect);
+    method public int getLineCount();
+    method public int getLineHeight();
+    method public float getLineSpacingExtra();
+    method public float getLineSpacingMultiplier();
+    method public final android.content.res.ColorStateList getLinkTextColors();
+    method public final boolean getLinksClickable();
+    method public int getMarqueeRepeatLimit();
+    method public int getMaxEms();
+    method public int getMaxHeight();
+    method public int getMaxLines();
+    method public int getMaxWidth();
+    method public int getMinEms();
+    method public int getMinHeight();
+    method public int getMinLines();
+    method public int getMinWidth();
+    method public final android.text.method.MovementMethod getMovementMethod();
+    method public int getOffsetForPosition(float, float);
+    method public android.text.TextPaint getPaint();
+    method public int getPaintFlags();
+    method public java.lang.String getPrivateImeOptions();
+    method public int getSelectionEnd();
+    method public int getSelectionStart();
+    method public int getShadowColor();
+    method public float getShadowDx();
+    method public float getShadowDy();
+    method public float getShadowRadius();
+    method public java.lang.CharSequence getText();
+    method public static int getTextColor(android.content.Context, android.content.res.TypedArray, int);
+    method public final android.content.res.ColorStateList getTextColors();
+    method public static android.content.res.ColorStateList getTextColors(android.content.Context, android.content.res.TypedArray);
+    method public java.util.Locale getTextLocale();
+    method public float getTextScaleX();
+    method public float getTextSize();
+    method public int getTotalPaddingBottom();
+    method public int getTotalPaddingEnd();
+    method public int getTotalPaddingLeft();
+    method public int getTotalPaddingRight();
+    method public int getTotalPaddingStart();
+    method public int getTotalPaddingTop();
+    method public final android.text.method.TransformationMethod getTransformationMethod();
+    method public android.graphics.Typeface getTypeface();
+    method public android.text.style.URLSpan[] getUrls();
+    method public boolean hasSelection();
+    method public boolean isCursorVisible();
+    method public boolean isInputMethodTarget();
+    method public boolean isSuggestionsEnabled();
+    method public boolean isTextSelectable();
+    method public int length();
+    method public boolean moveCursorToVisibleOffset();
+    method public void onBeginBatchEdit();
+    method public void onCommitCompletion(android.view.inputmethod.CompletionInfo);
+    method public void onCommitCorrection(android.view.inputmethod.CorrectionInfo);
+    method public void onEditorAction(int);
+    method public void onEndBatchEdit();
+    method public boolean onPreDraw();
+    method public boolean onPrivateIMECommand(java.lang.String, android.os.Bundle);
+    method public void onRestoreInstanceState(android.os.Parcelable);
+    method public android.os.Parcelable onSaveInstanceState();
+    method protected void onSelectionChanged(int, int);
+    method protected void onTextChanged(java.lang.CharSequence, int, int, int);
+    method public boolean onTextContextMenuItem(int);
+    method public void removeTextChangedListener(android.text.TextWatcher);
+    method public void setAllCaps(boolean);
+    method public final void setAutoLinkMask(int);
+    method public void setCompoundDrawablePadding(int);
+    method public void setCompoundDrawables(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
+    method public void setCompoundDrawablesRelative(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
+    method public void setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int);
+    method public void setCompoundDrawablesRelativeWithIntrinsicBounds(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
+    method public void setCompoundDrawablesWithIntrinsicBounds(int, int, int, int);
+    method public void setCompoundDrawablesWithIntrinsicBounds(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
+    method public void setCursorVisible(boolean);
+    method public void setCustomSelectionActionModeCallback(android.view.ActionMode.Callback);
+    method public final void setEditableFactory(android.text.Editable.Factory);
+    method public void setEllipsize(android.text.TextUtils.TruncateAt);
+    method public void setEms(int);
+    method public void setError(java.lang.CharSequence);
+    method public void setError(java.lang.CharSequence, android.graphics.drawable.Drawable);
+    method public void setExtractedText(android.view.inputmethod.ExtractedText);
+    method public void setFilters(android.text.InputFilter[]);
+    method protected boolean setFrame(int, int, int, int);
+    method public void setFreezesText(boolean);
+    method public void setGravity(int);
+    method public void setHeight(int);
+    method public void setHighlightColor(int);
+    method public final void setHint(java.lang.CharSequence);
+    method public final void setHint(int);
+    method public final void setHintTextColor(int);
+    method public final void setHintTextColor(android.content.res.ColorStateList);
+    method public void setHorizontallyScrolling(boolean);
+    method public void setImeActionLabel(java.lang.CharSequence, int);
+    method public void setImeOptions(int);
+    method public void setIncludeFontPadding(boolean);
+    method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public void setInputType(int);
+    method public void setKeyListener(android.text.method.KeyListener);
+    method public void setLineSpacing(float, float);
+    method public void setLines(int);
+    method public final void setLinkTextColor(int);
+    method public final void setLinkTextColor(android.content.res.ColorStateList);
+    method public final void setLinksClickable(boolean);
+    method public void setMarqueeRepeatLimit(int);
+    method public void setMaxEms(int);
+    method public void setMaxHeight(int);
+    method public void setMaxLines(int);
+    method public void setMaxWidth(int);
+    method public void setMinEms(int);
+    method public void setMinHeight(int);
+    method public void setMinLines(int);
+    method public void setMinWidth(int);
+    method public final void setMovementMethod(android.text.method.MovementMethod);
+    method public void setOnEditorActionListener(android.widget.TextView.OnEditorActionListener);
+    method public void setPaintFlags(int);
+    method public void setPrivateImeOptions(java.lang.String);
+    method public void setRawInputType(int);
+    method public void setScroller(android.widget.Scroller);
+    method public void setSelectAllOnFocus(boolean);
+    method public void setShadowLayer(float, float, float, int);
+    method public void setSingleLine();
+    method public void setSingleLine(boolean);
+    method public final void setSpannableFactory(android.text.Spannable.Factory);
+    method public final void setText(java.lang.CharSequence);
+    method public void setText(java.lang.CharSequence, android.widget.TextView.BufferType);
+    method public final void setText(char[], int, int);
+    method public final void setText(int);
+    method public final void setText(int, android.widget.TextView.BufferType);
+    method public void setTextAppearance(android.content.Context, int);
+    method public void setTextColor(int);
+    method public void setTextColor(android.content.res.ColorStateList);
+    method public void setTextIsSelectable(boolean);
+    method public final void setTextKeepState(java.lang.CharSequence);
+    method public final void setTextKeepState(java.lang.CharSequence, android.widget.TextView.BufferType);
+    method public void setTextLocale(java.util.Locale);
+    method public void setTextScaleX(float);
+    method public void setTextSize(float);
+    method public void setTextSize(int, float);
+    method public final void setTransformationMethod(android.text.method.TransformationMethod);
+    method public void setTypeface(android.graphics.Typeface, int);
+    method public void setTypeface(android.graphics.Typeface);
+    method public void setWidth(int);
+  }
+
+  public static final class TextView.BufferType extends java.lang.Enum {
+    method public static android.widget.TextView.BufferType valueOf(java.lang.String);
+    method public static final android.widget.TextView.BufferType[] values();
+    enum_constant public static final android.widget.TextView.BufferType EDITABLE;
+    enum_constant public static final android.widget.TextView.BufferType NORMAL;
+    enum_constant public static final android.widget.TextView.BufferType SPANNABLE;
+  }
+
+  public static abstract interface TextView.OnEditorActionListener {
+    method public abstract boolean onEditorAction(android.widget.TextView, int, android.view.KeyEvent);
+  }
+
+  public static class TextView.SavedState extends android.view.View.BaseSavedState {
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class TimePicker extends android.widget.FrameLayout {
+    ctor public TimePicker(android.content.Context);
+    ctor public TimePicker(android.content.Context, android.util.AttributeSet);
+    ctor public TimePicker(android.content.Context, android.util.AttributeSet, int);
+    method public java.lang.Integer getCurrentHour();
+    method public java.lang.Integer getCurrentMinute();
+    method public boolean is24HourView();
+    method public void setCurrentHour(java.lang.Integer);
+    method public void setCurrentMinute(java.lang.Integer);
+    method public void setIs24HourView(java.lang.Boolean);
+    method public void setOnTimeChangedListener(android.widget.TimePicker.OnTimeChangedListener);
+  }
+
+  public static abstract interface TimePicker.OnTimeChangedListener {
+    method public abstract void onTimeChanged(android.widget.TimePicker, int, int);
+  }
+
+  public class Toast {
+    ctor public Toast(android.content.Context);
+    method public void cancel();
+    method public int getDuration();
+    method public int getGravity();
+    method public float getHorizontalMargin();
+    method public float getVerticalMargin();
+    method public android.view.View getView();
+    method public int getXOffset();
+    method public int getYOffset();
+    method public static android.widget.Toast makeText(android.content.Context, java.lang.CharSequence, int);
+    method public static android.widget.Toast makeText(android.content.Context, int, int) throws android.content.res.Resources.NotFoundException;
+    method public void setDuration(int);
+    method public void setGravity(int, int, int);
+    method public void setMargin(float, float);
+    method public void setText(int);
+    method public void setText(java.lang.CharSequence);
+    method public void setView(android.view.View);
+    method public void show();
+    field public static final int LENGTH_LONG = 1; // 0x1
+    field public static final int LENGTH_SHORT = 0; // 0x0
+  }
+
+  public class ToggleButton extends android.widget.CompoundButton {
+    ctor public ToggleButton(android.content.Context, android.util.AttributeSet, int);
+    ctor public ToggleButton(android.content.Context, android.util.AttributeSet);
+    ctor public ToggleButton(android.content.Context);
+    method public java.lang.CharSequence getTextOff();
+    method public java.lang.CharSequence getTextOn();
+    method public void setTextOff(java.lang.CharSequence);
+    method public void setTextOn(java.lang.CharSequence);
+  }
+
+  public deprecated class TwoLineListItem extends android.widget.RelativeLayout {
+    ctor public TwoLineListItem(android.content.Context);
+    ctor public TwoLineListItem(android.content.Context, android.util.AttributeSet);
+    ctor public TwoLineListItem(android.content.Context, android.util.AttributeSet, int);
+    method public android.widget.TextView getText1();
+    method public android.widget.TextView getText2();
+  }
+
+  public class VideoView extends android.view.SurfaceView implements android.widget.MediaController.MediaPlayerControl {
+    ctor public VideoView(android.content.Context);
+    ctor public VideoView(android.content.Context, android.util.AttributeSet);
+    ctor public VideoView(android.content.Context, android.util.AttributeSet, int);
+    method public boolean canPause();
+    method public boolean canSeekBackward();
+    method public boolean canSeekForward();
+    method public int getBufferPercentage();
+    method public int getCurrentPosition();
+    method public int getDuration();
+    method public boolean isPlaying();
+    method public void pause();
+    method public int resolveAdjustedSize(int, int);
+    method public void resume();
+    method public void seekTo(int);
+    method public void setMediaController(android.widget.MediaController);
+    method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
+    method public void setOnErrorListener(android.media.MediaPlayer.OnErrorListener);
+    method public void setOnInfoListener(android.media.MediaPlayer.OnInfoListener);
+    method public void setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener);
+    method public void setVideoPath(java.lang.String);
+    method public void setVideoURI(android.net.Uri);
+    method public void start();
+    method public void stopPlayback();
+    method public void suspend();
+  }
+
+  public class ViewAnimator extends android.widget.FrameLayout {
+    ctor public ViewAnimator(android.content.Context);
+    ctor public ViewAnimator(android.content.Context, android.util.AttributeSet);
+    method public boolean getAnimateFirstView();
+    method public android.view.View getCurrentView();
+    method public int getDisplayedChild();
+    method public android.view.animation.Animation getInAnimation();
+    method public android.view.animation.Animation getOutAnimation();
+    method public void setAnimateFirstView(boolean);
+    method public void setDisplayedChild(int);
+    method public void setInAnimation(android.view.animation.Animation);
+    method public void setInAnimation(android.content.Context, int);
+    method public void setOutAnimation(android.view.animation.Animation);
+    method public void setOutAnimation(android.content.Context, int);
+    method public void showNext();
+    method public void showPrevious();
+  }
+
+  public class ViewFlipper extends android.widget.ViewAnimator {
+    ctor public ViewFlipper(android.content.Context);
+    ctor public ViewFlipper(android.content.Context, android.util.AttributeSet);
+    method public boolean isAutoStart();
+    method public boolean isFlipping();
+    method public void setAutoStart(boolean);
+    method public void setFlipInterval(int);
+    method public void startFlipping();
+    method public void stopFlipping();
+  }
+
+  public class ViewSwitcher extends android.widget.ViewAnimator {
+    ctor public ViewSwitcher(android.content.Context);
+    ctor public ViewSwitcher(android.content.Context, android.util.AttributeSet);
+    method public android.view.View getNextView();
+    method public void reset();
+    method public void setFactory(android.widget.ViewSwitcher.ViewFactory);
+  }
+
+  public static abstract interface ViewSwitcher.ViewFactory {
+    method public abstract android.view.View makeView();
+  }
+
+  public abstract interface WrapperListAdapter implements android.widget.ListAdapter {
+    method public abstract android.widget.ListAdapter getWrappedAdapter();
+  }
+
+  public class ZoomButton extends android.widget.ImageButton implements android.view.View.OnLongClickListener {
+    ctor public ZoomButton(android.content.Context);
+    ctor public ZoomButton(android.content.Context, android.util.AttributeSet);
+    ctor public ZoomButton(android.content.Context, android.util.AttributeSet, int);
+    method public boolean onLongClick(android.view.View);
+    method public void setZoomSpeed(long);
+  }
+
+  public class ZoomButtonsController implements android.view.View.OnTouchListener {
+    ctor public ZoomButtonsController(android.view.View);
+    method public android.view.ViewGroup getContainer();
+    method public android.view.View getZoomControls();
+    method public boolean isAutoDismissed();
+    method public boolean isVisible();
+    method public boolean onTouch(android.view.View, android.view.MotionEvent);
+    method public void setAutoDismissed(boolean);
+    method public void setFocusable(boolean);
+    method public void setOnZoomListener(android.widget.ZoomButtonsController.OnZoomListener);
+    method public void setVisible(boolean);
+    method public void setZoomInEnabled(boolean);
+    method public void setZoomOutEnabled(boolean);
+    method public void setZoomSpeed(long);
+  }
+
+  public static abstract interface ZoomButtonsController.OnZoomListener {
+    method public abstract void onVisibilityChanged(boolean);
+    method public abstract void onZoom(boolean);
+  }
+
+  public class ZoomControls extends android.widget.LinearLayout {
+    ctor public ZoomControls(android.content.Context);
+    ctor public ZoomControls(android.content.Context, android.util.AttributeSet);
+    method public void hide();
+    method public void setIsZoomInEnabled(boolean);
+    method public void setIsZoomOutEnabled(boolean);
+    method public void setOnZoomInClickListener(android.view.View.OnClickListener);
+    method public void setOnZoomOutClickListener(android.view.View.OnClickListener);
+    method public void setZoomSpeed(long);
+    method public void show();
+  }
+
+}
+
+package com.android.internal.util {
+
+  public abstract interface Predicate {
+    method public abstract boolean apply(T);
+  }
+
+}
+
+package dalvik.annotation {
+
+  public abstract deprecated class TestTarget implements java.lang.annotation.Annotation {
+  }
+
+  public abstract deprecated class TestTargetClass implements java.lang.annotation.Annotation {
+  }
+
+}
+
+package dalvik.bytecode {
+
+  public final class OpcodeInfo {
+    field public static final int MAXIMUM_PACKED_VALUE;
+    field public static final int MAXIMUM_VALUE;
+  }
+
+  public abstract interface Opcodes {
+    field public static final int OP_ADD_DOUBLE = 171; // 0xab
+    field public static final int OP_ADD_DOUBLE_2ADDR = 203; // 0xcb
+    field public static final int OP_ADD_FLOAT = 166; // 0xa6
+    field public static final int OP_ADD_FLOAT_2ADDR = 198; // 0xc6
+    field public static final int OP_ADD_INT = 144; // 0x90
+    field public static final int OP_ADD_INT_2ADDR = 176; // 0xb0
+    field public static final int OP_ADD_INT_LIT16 = 208; // 0xd0
+    field public static final int OP_ADD_INT_LIT8 = 216; // 0xd8
+    field public static final int OP_ADD_LONG = 155; // 0x9b
+    field public static final int OP_ADD_LONG_2ADDR = 187; // 0xbb
+    field public static final int OP_AGET = 68; // 0x44
+    field public static final int OP_AGET_BOOLEAN = 71; // 0x47
+    field public static final int OP_AGET_BYTE = 72; // 0x48
+    field public static final int OP_AGET_CHAR = 73; // 0x49
+    field public static final int OP_AGET_OBJECT = 70; // 0x46
+    field public static final int OP_AGET_SHORT = 74; // 0x4a
+    field public static final int OP_AGET_WIDE = 69; // 0x45
+    field public static final int OP_AND_INT = 149; // 0x95
+    field public static final int OP_AND_INT_2ADDR = 181; // 0xb5
+    field public static final int OP_AND_INT_LIT16 = 213; // 0xd5
+    field public static final int OP_AND_INT_LIT8 = 221; // 0xdd
+    field public static final int OP_AND_LONG = 160; // 0xa0
+    field public static final int OP_AND_LONG_2ADDR = 192; // 0xc0
+    field public static final int OP_APUT = 75; // 0x4b
+    field public static final int OP_APUT_BOOLEAN = 78; // 0x4e
+    field public static final int OP_APUT_BYTE = 79; // 0x4f
+    field public static final int OP_APUT_CHAR = 80; // 0x50
+    field public static final int OP_APUT_OBJECT = 77; // 0x4d
+    field public static final int OP_APUT_SHORT = 81; // 0x51
+    field public static final int OP_APUT_WIDE = 76; // 0x4c
+    field public static final int OP_ARRAY_LENGTH = 33; // 0x21
+    field public static final deprecated int OP_BREAKPOINT = 236; // 0xec
+    field public static final int OP_CHECK_CAST = 31; // 0x1f
+    field public static final int OP_CHECK_CAST_JUMBO = 511; // 0x1ff
+    field public static final int OP_CMPG_DOUBLE = 48; // 0x30
+    field public static final int OP_CMPG_FLOAT = 46; // 0x2e
+    field public static final int OP_CMPL_DOUBLE = 47; // 0x2f
+    field public static final int OP_CMPL_FLOAT = 45; // 0x2d
+    field public static final int OP_CMP_LONG = 49; // 0x31
+    field public static final int OP_CONST = 20; // 0x14
+    field public static final int OP_CONST_16 = 19; // 0x13
+    field public static final int OP_CONST_4 = 18; // 0x12
+    field public static final int OP_CONST_CLASS = 28; // 0x1c
+    field public static final int OP_CONST_CLASS_JUMBO = 255; // 0xff
+    field public static final int OP_CONST_HIGH16 = 21; // 0x15
+    field public static final int OP_CONST_STRING = 26; // 0x1a
+    field public static final int OP_CONST_STRING_JUMBO = 27; // 0x1b
+    field public static final int OP_CONST_WIDE = 24; // 0x18
+    field public static final int OP_CONST_WIDE_16 = 22; // 0x16
+    field public static final int OP_CONST_WIDE_32 = 23; // 0x17
+    field public static final int OP_CONST_WIDE_HIGH16 = 25; // 0x19
+    field public static final int OP_DIV_DOUBLE = 174; // 0xae
+    field public static final int OP_DIV_DOUBLE_2ADDR = 206; // 0xce
+    field public static final int OP_DIV_FLOAT = 169; // 0xa9
+    field public static final int OP_DIV_FLOAT_2ADDR = 201; // 0xc9
+    field public static final int OP_DIV_INT = 147; // 0x93
+    field public static final int OP_DIV_INT_2ADDR = 179; // 0xb3
+    field public static final int OP_DIV_INT_LIT16 = 211; // 0xd3
+    field public static final int OP_DIV_INT_LIT8 = 219; // 0xdb
+    field public static final int OP_DIV_LONG = 158; // 0x9e
+    field public static final int OP_DIV_LONG_2ADDR = 190; // 0xbe
+    field public static final int OP_DOUBLE_TO_FLOAT = 140; // 0x8c
+    field public static final int OP_DOUBLE_TO_INT = 138; // 0x8a
+    field public static final int OP_DOUBLE_TO_LONG = 139; // 0x8b
+    field public static final deprecated int OP_EXECUTE_INLINE = 238; // 0xee
+    field public static final deprecated int OP_EXECUTE_INLINE_RANGE = 239; // 0xef
+    field public static final int OP_FILLED_NEW_ARRAY = 36; // 0x24
+    field public static final int OP_FILLED_NEW_ARRAY_JUMBO = 1535; // 0x5ff
+    field public static final int OP_FILLED_NEW_ARRAY_RANGE = 37; // 0x25
+    field public static final int OP_FILL_ARRAY_DATA = 38; // 0x26
+    field public static final int OP_FLOAT_TO_DOUBLE = 137; // 0x89
+    field public static final int OP_FLOAT_TO_INT = 135; // 0x87
+    field public static final int OP_FLOAT_TO_LONG = 136; // 0x88
+    field public static final int OP_GOTO = 40; // 0x28
+    field public static final int OP_GOTO_16 = 41; // 0x29
+    field public static final int OP_GOTO_32 = 42; // 0x2a
+    field public static final int OP_IF_EQ = 50; // 0x32
+    field public static final int OP_IF_EQZ = 56; // 0x38
+    field public static final int OP_IF_GE = 53; // 0x35
+    field public static final int OP_IF_GEZ = 59; // 0x3b
+    field public static final int OP_IF_GT = 54; // 0x36
+    field public static final int OP_IF_GTZ = 60; // 0x3c
+    field public static final int OP_IF_LE = 55; // 0x37
+    field public static final int OP_IF_LEZ = 61; // 0x3d
+    field public static final int OP_IF_LT = 52; // 0x34
+    field public static final int OP_IF_LTZ = 58; // 0x3a
+    field public static final int OP_IF_NE = 51; // 0x33
+    field public static final int OP_IF_NEZ = 57; // 0x39
+    field public static final int OP_IGET = 82; // 0x52
+    field public static final int OP_IGET_BOOLEAN = 85; // 0x55
+    field public static final int OP_IGET_BOOLEAN_JUMBO = 2559; // 0x9ff
+    field public static final int OP_IGET_BYTE = 86; // 0x56
+    field public static final int OP_IGET_BYTE_JUMBO = 2815; // 0xaff
+    field public static final int OP_IGET_CHAR = 87; // 0x57
+    field public static final int OP_IGET_CHAR_JUMBO = 3071; // 0xbff
+    field public static final int OP_IGET_JUMBO = 1791; // 0x6ff
+    field public static final int OP_IGET_OBJECT = 84; // 0x54
+    field public static final int OP_IGET_OBJECT_JUMBO = 2303; // 0x8ff
+    field public static final deprecated int OP_IGET_OBJECT_QUICK = 244; // 0xf4
+    field public static final deprecated int OP_IGET_QUICK = 242; // 0xf2
+    field public static final int OP_IGET_SHORT = 88; // 0x58
+    field public static final int OP_IGET_SHORT_JUMBO = 3327; // 0xcff
+    field public static final int OP_IGET_WIDE = 83; // 0x53
+    field public static final int OP_IGET_WIDE_JUMBO = 2047; // 0x7ff
+    field public static final deprecated int OP_IGET_WIDE_QUICK = 243; // 0xf3
+    field public static final deprecated int OP_IGET_WIDE_VOLATILE = 232; // 0xe8
+    field public static final int OP_INSTANCE_OF = 32; // 0x20
+    field public static final int OP_INSTANCE_OF_JUMBO = 767; // 0x2ff
+    field public static final int OP_INT_TO_BYTE = 141; // 0x8d
+    field public static final int OP_INT_TO_CHAR = 142; // 0x8e
+    field public static final int OP_INT_TO_DOUBLE = 131; // 0x83
+    field public static final int OP_INT_TO_FLOAT = 130; // 0x82
+    field public static final int OP_INT_TO_LONG = 129; // 0x81
+    field public static final int OP_INT_TO_SHORT = 143; // 0x8f
+    field public static final int OP_INVOKE_DIRECT = 112; // 0x70
+    field public static final deprecated int OP_INVOKE_DIRECT_EMPTY = 240; // 0xf0
+    field public static final int OP_INVOKE_DIRECT_JUMBO = 9471; // 0x24ff
+    field public static final int OP_INVOKE_DIRECT_RANGE = 118; // 0x76
+    field public static final int OP_INVOKE_INTERFACE = 114; // 0x72
+    field public static final int OP_INVOKE_INTERFACE_JUMBO = 9983; // 0x26ff
+    field public static final int OP_INVOKE_INTERFACE_RANGE = 120; // 0x78
+    field public static final int OP_INVOKE_STATIC = 113; // 0x71
+    field public static final int OP_INVOKE_STATIC_JUMBO = 9727; // 0x25ff
+    field public static final int OP_INVOKE_STATIC_RANGE = 119; // 0x77
+    field public static final int OP_INVOKE_SUPER = 111; // 0x6f
+    field public static final int OP_INVOKE_SUPER_JUMBO = 9215; // 0x23ff
+    field public static final deprecated int OP_INVOKE_SUPER_QUICK = 250; // 0xfa
+    field public static final deprecated int OP_INVOKE_SUPER_QUICK_RANGE = 251; // 0xfb
+    field public static final int OP_INVOKE_SUPER_RANGE = 117; // 0x75
+    field public static final int OP_INVOKE_VIRTUAL = 110; // 0x6e
+    field public static final int OP_INVOKE_VIRTUAL_JUMBO = 8959; // 0x22ff
+    field public static final deprecated int OP_INVOKE_VIRTUAL_QUICK = 248; // 0xf8
+    field public static final deprecated int OP_INVOKE_VIRTUAL_QUICK_RANGE = 249; // 0xf9
+    field public static final int OP_INVOKE_VIRTUAL_RANGE = 116; // 0x74
+    field public static final int OP_IPUT = 89; // 0x59
+    field public static final int OP_IPUT_BOOLEAN = 92; // 0x5c
+    field public static final int OP_IPUT_BOOLEAN_JUMBO = 4351; // 0x10ff
+    field public static final int OP_IPUT_BYTE = 93; // 0x5d
+    field public static final int OP_IPUT_BYTE_JUMBO = 4607; // 0x11ff
+    field public static final int OP_IPUT_CHAR = 94; // 0x5e
+    field public static final int OP_IPUT_CHAR_JUMBO = 4863; // 0x12ff
+    field public static final int OP_IPUT_JUMBO = 3583; // 0xdff
+    field public static final int OP_IPUT_OBJECT = 91; // 0x5b
+    field public static final int OP_IPUT_OBJECT_JUMBO = 4095; // 0xfff
+    field public static final deprecated int OP_IPUT_OBJECT_QUICK = 247; // 0xf7
+    field public static final deprecated int OP_IPUT_QUICK = 245; // 0xf5
+    field public static final int OP_IPUT_SHORT = 95; // 0x5f
+    field public static final int OP_IPUT_SHORT_JUMBO = 5119; // 0x13ff
+    field public static final int OP_IPUT_WIDE = 90; // 0x5a
+    field public static final int OP_IPUT_WIDE_JUMBO = 3839; // 0xeff
+    field public static final deprecated int OP_IPUT_WIDE_QUICK = 246; // 0xf6
+    field public static final deprecated int OP_IPUT_WIDE_VOLATILE = 233; // 0xe9
+    field public static final int OP_LONG_TO_DOUBLE = 134; // 0x86
+    field public static final int OP_LONG_TO_FLOAT = 133; // 0x85
+    field public static final int OP_LONG_TO_INT = 132; // 0x84
+    field public static final int OP_MONITOR_ENTER = 29; // 0x1d
+    field public static final int OP_MONITOR_EXIT = 30; // 0x1e
+    field public static final int OP_MOVE = 1; // 0x1
+    field public static final int OP_MOVE_16 = 3; // 0x3
+    field public static final int OP_MOVE_EXCEPTION = 13; // 0xd
+    field public static final int OP_MOVE_FROM16 = 2; // 0x2
+    field public static final int OP_MOVE_OBJECT = 7; // 0x7
+    field public static final int OP_MOVE_OBJECT_16 = 9; // 0x9
+    field public static final int OP_MOVE_OBJECT_FROM16 = 8; // 0x8
+    field public static final int OP_MOVE_RESULT = 10; // 0xa
+    field public static final int OP_MOVE_RESULT_OBJECT = 12; // 0xc
+    field public static final int OP_MOVE_RESULT_WIDE = 11; // 0xb
+    field public static final int OP_MOVE_WIDE = 4; // 0x4
+    field public static final int OP_MOVE_WIDE_16 = 6; // 0x6
+    field public static final int OP_MOVE_WIDE_FROM16 = 5; // 0x5
+    field public static final int OP_MUL_DOUBLE = 173; // 0xad
+    field public static final int OP_MUL_DOUBLE_2ADDR = 205; // 0xcd
+    field public static final int OP_MUL_FLOAT = 168; // 0xa8
+    field public static final int OP_MUL_FLOAT_2ADDR = 200; // 0xc8
+    field public static final int OP_MUL_INT = 146; // 0x92
+    field public static final int OP_MUL_INT_2ADDR = 178; // 0xb2
+    field public static final int OP_MUL_INT_LIT16 = 210; // 0xd2
+    field public static final int OP_MUL_INT_LIT8 = 218; // 0xda
+    field public static final int OP_MUL_LONG = 157; // 0x9d
+    field public static final int OP_MUL_LONG_2ADDR = 189; // 0xbd
+    field public static final int OP_NEG_DOUBLE = 128; // 0x80
+    field public static final int OP_NEG_FLOAT = 127; // 0x7f
+    field public static final int OP_NEG_INT = 123; // 0x7b
+    field public static final int OP_NEG_LONG = 125; // 0x7d
+    field public static final int OP_NEW_ARRAY = 35; // 0x23
+    field public static final int OP_NEW_ARRAY_JUMBO = 1279; // 0x4ff
+    field public static final int OP_NEW_INSTANCE = 34; // 0x22
+    field public static final int OP_NEW_INSTANCE_JUMBO = 1023; // 0x3ff
+    field public static final int OP_NOP = 0; // 0x0
+    field public static final int OP_NOT_INT = 124; // 0x7c
+    field public static final int OP_NOT_LONG = 126; // 0x7e
+    field public static final int OP_OR_INT = 150; // 0x96
+    field public static final int OP_OR_INT_2ADDR = 182; // 0xb6
+    field public static final int OP_OR_INT_LIT16 = 214; // 0xd6
+    field public static final int OP_OR_INT_LIT8 = 222; // 0xde
+    field public static final int OP_OR_LONG = 161; // 0xa1
+    field public static final int OP_OR_LONG_2ADDR = 193; // 0xc1
+    field public static final int OP_PACKED_SWITCH = 43; // 0x2b
+    field public static final int OP_REM_DOUBLE = 175; // 0xaf
+    field public static final int OP_REM_DOUBLE_2ADDR = 207; // 0xcf
+    field public static final int OP_REM_FLOAT = 170; // 0xaa
+    field public static final int OP_REM_FLOAT_2ADDR = 202; // 0xca
+    field public static final int OP_REM_INT = 148; // 0x94
+    field public static final int OP_REM_INT_2ADDR = 180; // 0xb4
+    field public static final int OP_REM_INT_LIT16 = 212; // 0xd4
+    field public static final int OP_REM_INT_LIT8 = 220; // 0xdc
+    field public static final int OP_REM_LONG = 159; // 0x9f
+    field public static final int OP_REM_LONG_2ADDR = 191; // 0xbf
+    field public static final int OP_RETURN = 15; // 0xf
+    field public static final int OP_RETURN_OBJECT = 17; // 0x11
+    field public static final int OP_RETURN_VOID = 14; // 0xe
+    field public static final int OP_RETURN_WIDE = 16; // 0x10
+    field public static final int OP_RSUB_INT = 209; // 0xd1
+    field public static final int OP_RSUB_INT_LIT8 = 217; // 0xd9
+    field public static final int OP_SGET = 96; // 0x60
+    field public static final int OP_SGET_BOOLEAN = 99; // 0x63
+    field public static final int OP_SGET_BOOLEAN_JUMBO = 6143; // 0x17ff
+    field public static final int OP_SGET_BYTE = 100; // 0x64
+    field public static final int OP_SGET_BYTE_JUMBO = 6399; // 0x18ff
+    field public static final int OP_SGET_CHAR = 101; // 0x65
+    field public static final int OP_SGET_CHAR_JUMBO = 6655; // 0x19ff
+    field public static final int OP_SGET_JUMBO = 5375; // 0x14ff
+    field public static final int OP_SGET_OBJECT = 98; // 0x62
+    field public static final int OP_SGET_OBJECT_JUMBO = 5887; // 0x16ff
+    field public static final int OP_SGET_SHORT = 102; // 0x66
+    field public static final int OP_SGET_SHORT_JUMBO = 6911; // 0x1aff
+    field public static final int OP_SGET_WIDE = 97; // 0x61
+    field public static final int OP_SGET_WIDE_JUMBO = 5631; // 0x15ff
+    field public static final deprecated int OP_SGET_WIDE_VOLATILE = 234; // 0xea
+    field public static final int OP_SHL_INT = 152; // 0x98
+    field public static final int OP_SHL_INT_2ADDR = 184; // 0xb8
+    field public static final int OP_SHL_INT_LIT8 = 224; // 0xe0
+    field public static final int OP_SHL_LONG = 163; // 0xa3
+    field public static final int OP_SHL_LONG_2ADDR = 195; // 0xc3
+    field public static final int OP_SHR_INT = 153; // 0x99
+    field public static final int OP_SHR_INT_2ADDR = 185; // 0xb9
+    field public static final int OP_SHR_INT_LIT8 = 225; // 0xe1
+    field public static final int OP_SHR_LONG = 164; // 0xa4
+    field public static final int OP_SHR_LONG_2ADDR = 196; // 0xc4
+    field public static final int OP_SPARSE_SWITCH = 44; // 0x2c
+    field public static final int OP_SPUT = 103; // 0x67
+    field public static final int OP_SPUT_BOOLEAN = 106; // 0x6a
+    field public static final int OP_SPUT_BOOLEAN_JUMBO = 7935; // 0x1eff
+    field public static final int OP_SPUT_BYTE = 107; // 0x6b
+    field public static final int OP_SPUT_BYTE_JUMBO = 8191; // 0x1fff
+    field public static final int OP_SPUT_CHAR = 108; // 0x6c
+    field public static final int OP_SPUT_CHAR_JUMBO = 8447; // 0x20ff
+    field public static final int OP_SPUT_JUMBO = 7167; // 0x1bff
+    field public static final int OP_SPUT_OBJECT = 105; // 0x69
+    field public static final int OP_SPUT_OBJECT_JUMBO = 7679; // 0x1dff
+    field public static final int OP_SPUT_SHORT = 109; // 0x6d
+    field public static final int OP_SPUT_SHORT_JUMBO = 8703; // 0x21ff
+    field public static final int OP_SPUT_WIDE = 104; // 0x68
+    field public static final int OP_SPUT_WIDE_JUMBO = 7423; // 0x1cff
+    field public static final deprecated int OP_SPUT_WIDE_VOLATILE = 235; // 0xeb
+    field public static final int OP_SUB_DOUBLE = 172; // 0xac
+    field public static final int OP_SUB_DOUBLE_2ADDR = 204; // 0xcc
+    field public static final int OP_SUB_FLOAT = 167; // 0xa7
+    field public static final int OP_SUB_FLOAT_2ADDR = 199; // 0xc7
+    field public static final int OP_SUB_INT = 145; // 0x91
+    field public static final int OP_SUB_INT_2ADDR = 177; // 0xb1
+    field public static final int OP_SUB_LONG = 156; // 0x9c
+    field public static final int OP_SUB_LONG_2ADDR = 188; // 0xbc
+    field public static final int OP_THROW = 39; // 0x27
+    field public static final deprecated int OP_THROW_VERIFICATION_ERROR = 237; // 0xed
+    field public static final int OP_USHR_INT = 154; // 0x9a
+    field public static final int OP_USHR_INT_2ADDR = 186; // 0xba
+    field public static final int OP_USHR_INT_LIT8 = 226; // 0xe2
+    field public static final int OP_USHR_LONG = 165; // 0xa5
+    field public static final int OP_USHR_LONG_2ADDR = 197; // 0xc5
+    field public static final int OP_XOR_INT = 151; // 0x97
+    field public static final int OP_XOR_INT_2ADDR = 183; // 0xb7
+    field public static final int OP_XOR_INT_LIT16 = 215; // 0xd7
+    field public static final int OP_XOR_INT_LIT8 = 223; // 0xdf
+    field public static final int OP_XOR_LONG = 162; // 0xa2
+    field public static final int OP_XOR_LONG_2ADDR = 194; // 0xc2
+  }
+
+}
+
+package dalvik.system {
+
+  public class BaseDexClassLoader extends java.lang.ClassLoader {
+    ctor public BaseDexClassLoader(java.lang.String, java.io.File, java.lang.String, java.lang.ClassLoader);
+    method public java.lang.String findLibrary(java.lang.String);
+  }
+
+  public class DexClassLoader extends dalvik.system.BaseDexClassLoader {
+    ctor public DexClassLoader(java.lang.String, java.lang.String, java.lang.String, java.lang.ClassLoader);
+  }
+
+  public final class DexFile {
+    ctor public DexFile(java.io.File) throws java.io.IOException;
+    ctor public DexFile(java.lang.String) throws java.io.IOException;
+    method public void close() throws java.io.IOException;
+    method public java.util.Enumeration<java.lang.String> entries();
+    method public java.lang.String getName();
+    method public static boolean isDexOptNeeded(java.lang.String) throws java.io.FileNotFoundException, java.io.IOException;
+    method public java.lang.Class loadClass(java.lang.String, java.lang.ClassLoader);
+    method public static dalvik.system.DexFile loadDex(java.lang.String, java.lang.String, int) throws java.io.IOException;
+  }
+
+  public class PathClassLoader extends dalvik.system.BaseDexClassLoader {
+    ctor public PathClassLoader(java.lang.String, java.lang.ClassLoader);
+    ctor public PathClassLoader(java.lang.String, java.lang.String, java.lang.ClassLoader);
+  }
+
+}
+
+package java.awt.font {
+
+  public final class NumericShaper implements java.io.Serializable {
+    method public static java.awt.font.NumericShaper getContextualShaper(int, int);
+    method public static java.awt.font.NumericShaper getContextualShaper(int);
+    method public int getRanges();
+    method public static java.awt.font.NumericShaper getShaper(int);
+    method public boolean isContextual();
+    method public void shape(char[], int, int, int);
+    method public void shape(char[], int, int);
+    field public static final int ALL_RANGES = 524287; // 0x7ffff
+    field public static final int ARABIC = 2; // 0x2
+    field public static final int BENGALI = 16; // 0x10
+    field public static final int DEVANAGARI = 8; // 0x8
+    field public static final int EASTERN_ARABIC = 4; // 0x4
+    field public static final int ETHIOPIC = 65536; // 0x10000
+    field public static final int EUROPEAN = 1; // 0x1
+    field public static final int GUJARATI = 64; // 0x40
+    field public static final int GURMUKHI = 32; // 0x20
+    field public static final int KANNADA = 1024; // 0x400
+    field public static final int KHMER = 131072; // 0x20000
+    field public static final int LAO = 8192; // 0x2000
+    field public static final int MALAYALAM = 2048; // 0x800
+    field public static final int MONGOLIAN = 262144; // 0x40000
+    field public static final int MYANMAR = 32768; // 0x8000
+    field public static final int ORIYA = 128; // 0x80
+    field public static final int TAMIL = 256; // 0x100
+    field public static final int TELUGU = 512; // 0x200
+    field public static final int THAI = 4096; // 0x1000
+    field public static final int TIBETAN = 16384; // 0x4000
+  }
+
+  public final class TextAttribute extends java.text.AttributedCharacterIterator.Attribute {
+    ctor protected TextAttribute(java.lang.String);
+    field public static final java.awt.font.TextAttribute BACKGROUND;
+    field public static final java.awt.font.TextAttribute BIDI_EMBEDDING;
+    field public static final java.awt.font.TextAttribute CHAR_REPLACEMENT;
+    field public static final java.awt.font.TextAttribute FAMILY;
+    field public static final java.awt.font.TextAttribute FONT;
+    field public static final java.awt.font.TextAttribute FOREGROUND;
+    field public static final java.awt.font.TextAttribute INPUT_METHOD_HIGHLIGHT;
+    field public static final java.awt.font.TextAttribute INPUT_METHOD_UNDERLINE;
+    field public static final java.awt.font.TextAttribute JUSTIFICATION;
+    field public static final java.lang.Float JUSTIFICATION_FULL;
+    field public static final java.lang.Float JUSTIFICATION_NONE;
+    field public static final java.awt.font.TextAttribute KERNING;
+    field public static final java.lang.Integer KERNING_ON;
+    field public static final java.awt.font.TextAttribute LIGATURES;
+    field public static final java.lang.Integer LIGATURES_ON;
+    field public static final java.awt.font.TextAttribute NUMERIC_SHAPING;
+    field public static final java.awt.font.TextAttribute POSTURE;
+    field public static final java.lang.Float POSTURE_OBLIQUE;
+    field public static final java.lang.Float POSTURE_REGULAR;
+    field public static final java.awt.font.TextAttribute RUN_DIRECTION;
+    field public static final java.lang.Boolean RUN_DIRECTION_LTR;
+    field public static final java.lang.Boolean RUN_DIRECTION_RTL;
+    field public static final java.awt.font.TextAttribute SIZE;
+    field public static final java.awt.font.TextAttribute STRIKETHROUGH;
+    field public static final java.lang.Boolean STRIKETHROUGH_ON;
+    field public static final java.awt.font.TextAttribute SUPERSCRIPT;
+    field public static final java.lang.Integer SUPERSCRIPT_SUB;
+    field public static final java.lang.Integer SUPERSCRIPT_SUPER;
+    field public static final java.awt.font.TextAttribute SWAP_COLORS;
+    field public static final java.lang.Boolean SWAP_COLORS_ON;
+    field public static final java.awt.font.TextAttribute TRACKING;
+    field public static final java.lang.Float TRACKING_LOOSE;
+    field public static final java.lang.Float TRACKING_TIGHT;
+    field public static final java.awt.font.TextAttribute TRANSFORM;
+    field public static final java.awt.font.TextAttribute UNDERLINE;
+    field public static final java.lang.Integer UNDERLINE_LOW_DASHED;
+    field public static final java.lang.Integer UNDERLINE_LOW_DOTTED;
+    field public static final java.lang.Integer UNDERLINE_LOW_GRAY;
+    field public static final java.lang.Integer UNDERLINE_LOW_ONE_PIXEL;
+    field public static final java.lang.Integer UNDERLINE_LOW_TWO_PIXEL;
+    field public static final java.lang.Integer UNDERLINE_ON;
+    field public static final java.awt.font.TextAttribute WEIGHT;
+    field public static final java.lang.Float WEIGHT_BOLD;
+    field public static final java.lang.Float WEIGHT_DEMIBOLD;
+    field public static final java.lang.Float WEIGHT_DEMILIGHT;
+    field public static final java.lang.Float WEIGHT_EXTRABOLD;
+    field public static final java.lang.Float WEIGHT_EXTRA_LIGHT;
+    field public static final java.lang.Float WEIGHT_HEAVY;
+    field public static final java.lang.Float WEIGHT_LIGHT;
+    field public static final java.lang.Float WEIGHT_MEDIUM;
+    field public static final java.lang.Float WEIGHT_REGULAR;
+    field public static final java.lang.Float WEIGHT_SEMIBOLD;
+    field public static final java.lang.Float WEIGHT_ULTRABOLD;
+    field public static final java.awt.font.TextAttribute WIDTH;
+    field public static final java.lang.Float WIDTH_CONDENSED;
+    field public static final java.lang.Float WIDTH_EXTENDED;
+    field public static final java.lang.Float WIDTH_REGULAR;
+    field public static final java.lang.Float WIDTH_SEMI_CONDENSED;
+    field public static final java.lang.Float WIDTH_SEMI_EXTENDED;
+  }
+
+}
+
+package java.beans {
+
+  public class IndexedPropertyChangeEvent extends java.beans.PropertyChangeEvent {
+    ctor public IndexedPropertyChangeEvent(java.lang.Object, java.lang.String, java.lang.Object, java.lang.Object, int);
+    method public int getIndex();
+  }
+
+  public class PropertyChangeEvent extends java.util.EventObject {
+    ctor public PropertyChangeEvent(java.lang.Object, java.lang.String, java.lang.Object, java.lang.Object);
+    method public java.lang.Object getNewValue();
+    method public java.lang.Object getOldValue();
+    method public java.lang.Object getPropagationId();
+    method public java.lang.String getPropertyName();
+    method public void setPropagationId(java.lang.Object);
+  }
+
+  public abstract interface PropertyChangeListener implements java.util.EventListener {
+    method public abstract void propertyChange(java.beans.PropertyChangeEvent);
+  }
+
+  public class PropertyChangeListenerProxy extends java.util.EventListenerProxy implements java.beans.PropertyChangeListener {
+    ctor public PropertyChangeListenerProxy(java.lang.String, java.beans.PropertyChangeListener);
+    method public java.lang.String getPropertyName();
+    method public void propertyChange(java.beans.PropertyChangeEvent);
+  }
+
+  public class PropertyChangeSupport implements java.io.Serializable {
+    ctor public PropertyChangeSupport(java.lang.Object);
+    method public void addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener);
+    method public void addPropertyChangeListener(java.beans.PropertyChangeListener);
+    method public void fireIndexedPropertyChange(java.lang.String, int, java.lang.Object, java.lang.Object);
+    method public void fireIndexedPropertyChange(java.lang.String, int, boolean, boolean);
+    method public void fireIndexedPropertyChange(java.lang.String, int, int, int);
+    method public void firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object);
+    method public void firePropertyChange(java.lang.String, boolean, boolean);
+    method public void firePropertyChange(java.lang.String, int, int);
+    method public void firePropertyChange(java.beans.PropertyChangeEvent);
+    method public java.beans.PropertyChangeListener[] getPropertyChangeListeners(java.lang.String);
+    method public java.beans.PropertyChangeListener[] getPropertyChangeListeners();
+    method public boolean hasListeners(java.lang.String);
+    method public void removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener);
+    method public void removePropertyChangeListener(java.beans.PropertyChangeListener);
+  }
+
+}
+
+package java.io {
+
+  public class BufferedInputStream extends java.io.FilterInputStream {
+    ctor public BufferedInputStream(java.io.InputStream);
+    ctor public BufferedInputStream(java.io.InputStream, int);
+    field protected volatile byte[] buf;
+    field protected int count;
+    field protected int marklimit;
+    field protected int markpos;
+    field protected int pos;
+  }
+
+  public class BufferedOutputStream extends java.io.FilterOutputStream {
+    ctor public BufferedOutputStream(java.io.OutputStream);
+    ctor public BufferedOutputStream(java.io.OutputStream, int);
+    field protected byte[] buf;
+    field protected int count;
+  }
+
+  public class BufferedReader extends java.io.Reader {
+    ctor public BufferedReader(java.io.Reader);
+    ctor public BufferedReader(java.io.Reader, int);
+    method public void close() throws java.io.IOException;
+    method public int read(char[], int, int) throws java.io.IOException;
+    method public java.lang.String readLine() throws java.io.IOException;
+  }
+
+  public class BufferedWriter extends java.io.Writer {
+    ctor public BufferedWriter(java.io.Writer);
+    ctor public BufferedWriter(java.io.Writer, int);
+    method public void close() throws java.io.IOException;
+    method public void flush() throws java.io.IOException;
+    method public void newLine() throws java.io.IOException;
+    method public void write(char[], int, int) throws java.io.IOException;
+  }
+
+  public class ByteArrayInputStream extends java.io.InputStream {
+    ctor public ByteArrayInputStream(byte[]);
+    ctor public ByteArrayInputStream(byte[], int, int);
+    method public synchronized int read();
+    field protected byte[] buf;
+    field protected int count;
+    field protected int mark;
+    field protected int pos;
+  }
+
+  public class ByteArrayOutputStream extends java.io.OutputStream {
+    ctor public ByteArrayOutputStream();
+    ctor public ByteArrayOutputStream(int);
+    method public synchronized void reset();
+    method public int size();
+    method public synchronized byte[] toByteArray();
+    method public deprecated java.lang.String toString(int);
+    method public java.lang.String toString(java.lang.String) throws java.io.UnsupportedEncodingException;
+    method public synchronized void write(int);
+    method public synchronized void writeTo(java.io.OutputStream) throws java.io.IOException;
+    field protected byte[] buf;
+    field protected int count;
+  }
+
+  public class CharArrayReader extends java.io.Reader {
+    ctor public CharArrayReader(char[]);
+    ctor public CharArrayReader(char[], int, int);
+    method public void close();
+    method public int read(char[], int, int) throws java.io.IOException;
+    field protected char[] buf;
+    field protected int count;
+    field protected int markedPos;
+    field protected int pos;
+  }
+
+  public class CharArrayWriter extends java.io.Writer {
+    ctor public CharArrayWriter();
+    ctor public CharArrayWriter(int);
+    method public void close();
+    method public void flush();
+    method public void reset();
+    method public int size();
+    method public char[] toCharArray();
+    method public void write(char[], int, int);
+    method public void writeTo(java.io.Writer) throws java.io.IOException;
+    field protected char[] buf;
+    field protected int count;
+  }
+
+  public class CharConversionException extends java.io.IOException {
+    ctor public CharConversionException();
+    ctor public CharConversionException(java.lang.String);
+  }
+
+  public abstract interface Closeable {
+    method public abstract void close() throws java.io.IOException;
+  }
+
+  public final class Console implements java.io.Flushable {
+    method public void flush();
+    method public java.io.Console format(java.lang.String, java.lang.Object...);
+    method public java.io.Console printf(java.lang.String, java.lang.Object...);
+    method public java.lang.String readLine();
+    method public java.lang.String readLine(java.lang.String, java.lang.Object...);
+    method public char[] readPassword();
+    method public char[] readPassword(java.lang.String, java.lang.Object...);
+    method public java.io.Reader reader();
+    method public java.io.PrintWriter writer();
+  }
+
+  public abstract interface DataInput {
+    method public abstract boolean readBoolean() throws java.io.IOException;
+    method public abstract byte readByte() throws java.io.IOException;
+    method public abstract char readChar() throws java.io.IOException;
+    method public abstract double readDouble() throws java.io.IOException;
+    method public abstract float readFloat() throws java.io.IOException;
+    method public abstract void readFully(byte[]) throws java.io.IOException;
+    method public abstract void readFully(byte[], int, int) throws java.io.IOException;
+    method public abstract int readInt() throws java.io.IOException;
+    method public abstract java.lang.String readLine() throws java.io.IOException;
+    method public abstract long readLong() throws java.io.IOException;
+    method public abstract short readShort() throws java.io.IOException;
+    method public abstract java.lang.String readUTF() throws java.io.IOException;
+    method public abstract int readUnsignedByte() throws java.io.IOException;
+    method public abstract int readUnsignedShort() throws java.io.IOException;
+    method public abstract int skipBytes(int) throws java.io.IOException;
+  }
+
+  public class DataInputStream extends java.io.FilterInputStream implements java.io.DataInput {
+    ctor public DataInputStream(java.io.InputStream);
+    method public final int read(byte[]) throws java.io.IOException;
+    method public final int read(byte[], int, int) throws java.io.IOException;
+    method public final boolean readBoolean() throws java.io.IOException;
+    method public final byte readByte() throws java.io.IOException;
+    method public final char readChar() throws java.io.IOException;
+    method public final double readDouble() throws java.io.IOException;
+    method public final float readFloat() throws java.io.IOException;
+    method public final void readFully(byte[]) throws java.io.IOException;
+    method public final void readFully(byte[], int, int) throws java.io.IOException;
+    method public final int readInt() throws java.io.IOException;
+    method public final deprecated java.lang.String readLine() throws java.io.IOException;
+    method public final long readLong() throws java.io.IOException;
+    method public final short readShort() throws java.io.IOException;
+    method public final java.lang.String readUTF() throws java.io.IOException;
+    method public static final java.lang.String readUTF(java.io.DataInput) throws java.io.IOException;
+    method public final int readUnsignedByte() throws java.io.IOException;
+    method public final int readUnsignedShort() throws java.io.IOException;
+    method public final int skipBytes(int) throws java.io.IOException;
+  }
+
+  public abstract interface DataOutput {
+    method public abstract void write(byte[]) throws java.io.IOException;
+    method public abstract void write(byte[], int, int) throws java.io.IOException;
+    method public abstract void write(int) throws java.io.IOException;
+    method public abstract void writeBoolean(boolean) throws java.io.IOException;
+    method public abstract void writeByte(int) throws java.io.IOException;
+    method public abstract void writeBytes(java.lang.String) throws java.io.IOException;
+    method public abstract void writeChar(int) throws java.io.IOException;
+    method public abstract void writeChars(java.lang.String) throws java.io.IOException;
+    method public abstract void writeDouble(double) throws java.io.IOException;
+    method public abstract void writeFloat(float) throws java.io.IOException;
+    method public abstract void writeInt(int) throws java.io.IOException;
+    method public abstract void writeLong(long) throws java.io.IOException;
+    method public abstract void writeShort(int) throws java.io.IOException;
+    method public abstract void writeUTF(java.lang.String) throws java.io.IOException;
+  }
+
+  public class DataOutputStream extends java.io.FilterOutputStream implements java.io.DataOutput {
+    ctor public DataOutputStream(java.io.OutputStream);
+    method public final int size();
+    method public final void writeBoolean(boolean) throws java.io.IOException;
+    method public final void writeByte(int) throws java.io.IOException;
+    method public final void writeBytes(java.lang.String) throws java.io.IOException;
+    method public final void writeChar(int) throws java.io.IOException;
+    method public final void writeChars(java.lang.String) throws java.io.IOException;
+    method public final void writeDouble(double) throws java.io.IOException;
+    method public final void writeFloat(float) throws java.io.IOException;
+    method public final void writeInt(int) throws java.io.IOException;
+    method public final void writeLong(long) throws java.io.IOException;
+    method public final void writeShort(int) throws java.io.IOException;
+    method public final void writeUTF(java.lang.String) throws java.io.IOException;
+    field protected int written;
+  }
+
+  public class EOFException extends java.io.IOException {
+    ctor public EOFException();
+    ctor public EOFException(java.lang.String);
+  }
+
+  public abstract interface Externalizable implements java.io.Serializable {
+    method public abstract void readExternal(java.io.ObjectInput) throws java.lang.ClassNotFoundException, java.io.IOException;
+    method public abstract void writeExternal(java.io.ObjectOutput) throws java.io.IOException;
+  }
+
+  public class File implements java.lang.Comparable java.io.Serializable {
+    ctor public File(java.io.File, java.lang.String);
+    ctor public File(java.lang.String);
+    ctor public File(java.lang.String, java.lang.String);
+    ctor public File(java.net.URI);
+    method public boolean canExecute();
+    method public boolean canRead();
+    method public boolean canWrite();
+    method public int compareTo(java.io.File);
+    method public boolean createNewFile() throws java.io.IOException;
+    method public static java.io.File createTempFile(java.lang.String, java.lang.String) throws java.io.IOException;
+    method public static java.io.File createTempFile(java.lang.String, java.lang.String, java.io.File) throws java.io.IOException;
+    method public boolean delete();
+    method public void deleteOnExit();
+    method public boolean exists();
+    method public java.io.File getAbsoluteFile();
+    method public java.lang.String getAbsolutePath();
+    method public java.io.File getCanonicalFile() throws java.io.IOException;
+    method public java.lang.String getCanonicalPath() throws java.io.IOException;
+    method public long getFreeSpace();
+    method public java.lang.String getName();
+    method public java.lang.String getParent();
+    method public java.io.File getParentFile();
+    method public java.lang.String getPath();
+    method public long getTotalSpace();
+    method public long getUsableSpace();
+    method public boolean isAbsolute();
+    method public boolean isDirectory();
+    method public boolean isFile();
+    method public boolean isHidden();
+    method public long lastModified();
+    method public long length();
+    method public java.lang.String[] list();
+    method public java.lang.String[] list(java.io.FilenameFilter);
+    method public java.io.File[] listFiles();
+    method public java.io.File[] listFiles(java.io.FilenameFilter);
+    method public java.io.File[] listFiles(java.io.FileFilter);
+    method public static java.io.File[] listRoots();
+    method public boolean mkdir();
+    method public boolean mkdirs();
+    method public boolean renameTo(java.io.File);
+    method public boolean setExecutable(boolean, boolean);
+    method public boolean setExecutable(boolean);
+    method public boolean setLastModified(long);
+    method public boolean setReadOnly();
+    method public boolean setReadable(boolean, boolean);
+    method public boolean setReadable(boolean);
+    method public boolean setWritable(boolean, boolean);
+    method public boolean setWritable(boolean);
+    method public java.net.URI toURI();
+    method public deprecated java.net.URL toURL() throws java.net.MalformedURLException;
+    field public static final java.lang.String pathSeparator;
+    field public static final char pathSeparatorChar;
+    field public static final java.lang.String separator;
+    field public static final char separatorChar;
+  }
+
+  public final class FileDescriptor {
+    ctor public FileDescriptor();
+    method public void sync() throws java.io.SyncFailedException;
+    method public boolean valid();
+    field public static final java.io.FileDescriptor err;
+    field public static final java.io.FileDescriptor in;
+    field public static final java.io.FileDescriptor out;
+  }
+
+  public abstract interface FileFilter {
+    method public abstract boolean accept(java.io.File);
+  }
+
+  public class FileInputStream extends java.io.InputStream implements java.io.Closeable {
+    ctor public FileInputStream(java.io.File) throws java.io.FileNotFoundException;
+    ctor public FileInputStream(java.io.FileDescriptor);
+    ctor public FileInputStream(java.lang.String) throws java.io.FileNotFoundException;
+    method public java.nio.channels.FileChannel getChannel();
+    method public final java.io.FileDescriptor getFD() throws java.io.IOException;
+    method public int read() throws java.io.IOException;
+  }
+
+  public class FileNotFoundException extends java.io.IOException {
+    ctor public FileNotFoundException();
+    ctor public FileNotFoundException(java.lang.String);
+  }
+
+  public class FileOutputStream extends java.io.OutputStream implements java.io.Closeable {
+    ctor public FileOutputStream(java.io.File) throws java.io.FileNotFoundException;
+    ctor public FileOutputStream(java.io.File, boolean) throws java.io.FileNotFoundException;
+    ctor public FileOutputStream(java.io.FileDescriptor);
+    ctor public FileOutputStream(java.lang.String) throws java.io.FileNotFoundException;
+    ctor public FileOutputStream(java.lang.String, boolean) throws java.io.FileNotFoundException;
+    method public java.nio.channels.FileChannel getChannel();
+    method public final java.io.FileDescriptor getFD() throws java.io.IOException;
+    method public void write(int) throws java.io.IOException;
+  }
+
+  public final class FilePermission extends java.security.Permission implements java.io.Serializable {
+    ctor public FilePermission(java.lang.String, java.lang.String);
+    method public java.lang.String getActions();
+    method public boolean implies(java.security.Permission);
+  }
+
+  public class FileReader extends java.io.InputStreamReader {
+    ctor public FileReader(java.io.File) throws java.io.FileNotFoundException;
+    ctor public FileReader(java.io.FileDescriptor);
+    ctor public FileReader(java.lang.String) throws java.io.FileNotFoundException;
+  }
+
+  public class FileWriter extends java.io.OutputStreamWriter {
+    ctor public FileWriter(java.io.File) throws java.io.IOException;
+    ctor public FileWriter(java.io.File, boolean) throws java.io.IOException;
+    ctor public FileWriter(java.io.FileDescriptor);
+    ctor public FileWriter(java.lang.String) throws java.io.IOException;
+    ctor public FileWriter(java.lang.String, boolean) throws java.io.IOException;
+  }
+
+  public abstract interface FilenameFilter {
+    method public abstract boolean accept(java.io.File, java.lang.String);
+  }
+
+  public class FilterInputStream extends java.io.InputStream {
+    ctor protected FilterInputStream(java.io.InputStream);
+    method public int read() throws java.io.IOException;
+    field protected volatile java.io.InputStream in;
+  }
+
+  public class FilterOutputStream extends java.io.OutputStream {
+    ctor public FilterOutputStream(java.io.OutputStream);
+    method public void write(int) throws java.io.IOException;
+    field protected java.io.OutputStream out;
+  }
+
+  public abstract class FilterReader extends java.io.Reader {
+    ctor protected FilterReader(java.io.Reader);
+    method public void close() throws java.io.IOException;
+    method public int read(char[], int, int) throws java.io.IOException;
+    field protected java.io.Reader in;
+  }
+
+  public abstract class FilterWriter extends java.io.Writer {
+    ctor protected FilterWriter(java.io.Writer);
+    method public void close() throws java.io.IOException;
+    method public void flush() throws java.io.IOException;
+    method public void write(char[], int, int) throws java.io.IOException;
+    field protected java.io.Writer out;
+  }
+
+  public abstract interface Flushable {
+    method public abstract void flush() throws java.io.IOException;
+  }
+
+  public class IOError extends java.lang.Error {
+    ctor public IOError(java.lang.Throwable);
+  }
+
+  public class IOException extends java.lang.Exception {
+    ctor public IOException();
+    ctor public IOException(java.lang.String);
+    ctor public IOException(java.lang.String, java.lang.Throwable);
+    ctor public IOException(java.lang.Throwable);
+  }
+
+  public abstract class InputStream implements java.io.Closeable {
+    ctor public InputStream();
+    method public int available() throws java.io.IOException;
+    method public void close() throws java.io.IOException;
+    method public void mark(int);
+    method public boolean markSupported();
+    method public abstract int read() throws java.io.IOException;
+    method public int read(byte[]) throws java.io.IOException;
+    method public int read(byte[], int, int) throws java.io.IOException;
+    method public synchronized void reset() throws java.io.IOException;
+    method public long skip(long) throws java.io.IOException;
+  }
+
+  public class InputStreamReader extends java.io.Reader {
+    ctor public InputStreamReader(java.io.InputStream);
+    ctor public InputStreamReader(java.io.InputStream, java.lang.String) throws java.io.UnsupportedEncodingException;
+    ctor public InputStreamReader(java.io.InputStream, java.nio.charset.CharsetDecoder);
+    ctor public InputStreamReader(java.io.InputStream, java.nio.charset.Charset);
+    method public void close() throws java.io.IOException;
+    method public java.lang.String getEncoding();
+    method public int read(char[], int, int) throws java.io.IOException;
+  }
+
+  public class InterruptedIOException extends java.io.IOException {
+    ctor public InterruptedIOException();
+    ctor public InterruptedIOException(java.lang.String);
+    field public int bytesTransferred;
+  }
+
+  public class InvalidClassException extends java.io.ObjectStreamException {
+    ctor public InvalidClassException(java.lang.String);
+    ctor public InvalidClassException(java.lang.String, java.lang.String);
+    field public java.lang.String classname;
+  }
+
+  public class InvalidObjectException extends java.io.ObjectStreamException {
+    ctor public InvalidObjectException(java.lang.String);
+  }
+
+  public deprecated class LineNumberInputStream extends java.io.FilterInputStream {
+    ctor public LineNumberInputStream(java.io.InputStream);
+    method public int getLineNumber();
+    method public void setLineNumber(int);
+  }
+
+  public class LineNumberReader extends java.io.BufferedReader {
+    ctor public LineNumberReader(java.io.Reader);
+    ctor public LineNumberReader(java.io.Reader, int);
+    method public int getLineNumber();
+    method public void setLineNumber(int);
+  }
+
+  public class NotActiveException extends java.io.ObjectStreamException {
+    ctor public NotActiveException();
+    ctor public NotActiveException(java.lang.String);
+  }
+
+  public class NotSerializableException extends java.io.ObjectStreamException {
+    ctor public NotSerializableException();
+    ctor public NotSerializableException(java.lang.String);
+  }
+
+  public abstract interface ObjectInput implements java.io.DataInput {
+    method public abstract int available() throws java.io.IOException;
+    method public abstract void close() throws java.io.IOException;
+    method public abstract int read() throws java.io.IOException;
+    method public abstract int read(byte[]) throws java.io.IOException;
+    method public abstract int read(byte[], int, int) throws java.io.IOException;
+    method public abstract java.lang.Object readObject() throws java.lang.ClassNotFoundException, java.io.IOException;
+    method public abstract long skip(long) throws java.io.IOException;
+  }
+
+  public class ObjectInputStream extends java.io.InputStream implements java.io.ObjectInput java.io.ObjectStreamConstants {
+    ctor protected ObjectInputStream() throws java.io.IOException;
+    ctor public ObjectInputStream(java.io.InputStream) throws java.io.IOException, java.io.StreamCorruptedException;
+    method public void defaultReadObject() throws java.lang.ClassNotFoundException, java.io.IOException, java.io.NotActiveException;
+    method protected boolean enableResolveObject(boolean);
+    method public int read() throws java.io.IOException;
+    method public boolean readBoolean() throws java.io.IOException;
+    method public byte readByte() throws java.io.IOException;
+    method public char readChar() throws java.io.IOException;
+    method protected java.io.ObjectStreamClass readClassDescriptor() throws java.lang.ClassNotFoundException, java.io.IOException;
+    method public double readDouble() throws java.io.IOException;
+    method public java.io.ObjectInputStream.GetField readFields() throws java.lang.ClassNotFoundException, java.io.IOException, java.io.NotActiveException;
+    method public float readFloat() throws java.io.IOException;
+    method public void readFully(byte[]) throws java.io.IOException;
+    method public void readFully(byte[], int, int) throws java.io.IOException;
+    method public int readInt() throws java.io.IOException;
+    method public deprecated java.lang.String readLine() throws java.io.IOException;
+    method public long readLong() throws java.io.IOException;
+    method public final java.lang.Object readObject() throws java.lang.ClassNotFoundException, java.io.IOException, java.io.OptionalDataException;
+    method protected java.lang.Object readObjectOverride() throws java.lang.ClassNotFoundException, java.io.IOException, java.io.OptionalDataException;
+    method public short readShort() throws java.io.IOException;
+    method protected void readStreamHeader() throws java.io.IOException, java.io.StreamCorruptedException;
+    method public java.lang.String readUTF() throws java.io.IOException;
+    method public java.lang.Object readUnshared() throws java.lang.ClassNotFoundException, java.io.IOException;
+    method public int readUnsignedByte() throws java.io.IOException;
+    method public int readUnsignedShort() throws java.io.IOException;
+    method public synchronized void registerValidation(java.io.ObjectInputValidation, int) throws java.io.InvalidObjectException, java.io.NotActiveException;
+    method protected java.lang.Class<?> resolveClass(java.io.ObjectStreamClass) throws java.lang.ClassNotFoundException, java.io.IOException;
+    method protected java.lang.Object resolveObject(java.lang.Object) throws java.io.IOException;
+    method protected java.lang.Class<?> resolveProxyClass(java.lang.String[]) throws java.lang.ClassNotFoundException, java.io.IOException;
+    method public int skipBytes(int) throws java.io.IOException;
+  }
+
+  public static abstract class ObjectInputStream.GetField {
+    ctor public ObjectInputStream.GetField();
+    method public abstract boolean defaulted(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException;
+    method public abstract boolean get(java.lang.String, boolean) throws java.io.IOException, java.lang.IllegalArgumentException;
+    method public abstract char get(java.lang.String, char) throws java.io.IOException, java.lang.IllegalArgumentException;
+    method public abstract byte get(java.lang.String, byte) throws java.io.IOException, java.lang.IllegalArgumentException;
+    method public abstract short get(java.lang.String, short) throws java.io.IOException, java.lang.IllegalArgumentException;
+    method public abstract int get(java.lang.String, int) throws java.io.IOException, java.lang.IllegalArgumentException;
+    method public abstract long get(java.lang.String, long) throws java.io.IOException, java.lang.IllegalArgumentException;
+    method public abstract float get(java.lang.String, float) throws java.io.IOException, java.lang.IllegalArgumentException;
+    method public abstract double get(java.lang.String, double) throws java.io.IOException, java.lang.IllegalArgumentException;
+    method public abstract java.lang.Object get(java.lang.String, java.lang.Object) throws java.io.IOException, java.lang.IllegalArgumentException;
+    method public abstract java.io.ObjectStreamClass getObjectStreamClass();
+  }
+
+  public abstract interface ObjectInputValidation {
+    method public abstract void validateObject() throws java.io.InvalidObjectException;
+  }
+
+  public abstract interface ObjectOutput implements java.io.DataOutput {
+    method public abstract void close() throws java.io.IOException;
+    method public abstract void flush() throws java.io.IOException;
+    method public abstract void write(byte[]) throws java.io.IOException;
+    method public abstract void write(byte[], int, int) throws java.io.IOException;
+    method public abstract void write(int) throws java.io.IOException;
+    method public abstract void writeObject(java.lang.Object) throws java.io.IOException;
+  }
+
+  public class ObjectOutputStream extends java.io.OutputStream implements java.io.ObjectOutput java.io.ObjectStreamConstants {
+    ctor protected ObjectOutputStream() throws java.io.IOException;
+    ctor public ObjectOutputStream(java.io.OutputStream) throws java.io.IOException;
+    method protected void annotateClass(java.lang.Class<?>) throws java.io.IOException;
+    method protected void annotateProxyClass(java.lang.Class<?>) throws java.io.IOException;
+    method public void defaultWriteObject() throws java.io.IOException;
+    method protected void drain() throws java.io.IOException;
+    method protected boolean enableReplaceObject(boolean);
+    method public java.io.ObjectOutputStream.PutField putFields() throws java.io.IOException;
+    method protected java.lang.Object replaceObject(java.lang.Object) throws java.io.IOException;
+    method public void reset() throws java.io.IOException;
+    method public void useProtocolVersion(int) throws java.io.IOException;
+    method public void write(int) throws java.io.IOException;
+    method public void writeBoolean(boolean) throws java.io.IOException;
+    method public void writeByte(int) throws java.io.IOException;
+    method public void writeBytes(java.lang.String) throws java.io.IOException;
+    method public void writeChar(int) throws java.io.IOException;
+    method public void writeChars(java.lang.String) throws java.io.IOException;
+    method protected void writeClassDescriptor(java.io.ObjectStreamClass) throws java.io.IOException;
+    method public void writeDouble(double) throws java.io.IOException;
+    method public void writeFields() throws java.io.IOException;
+    method public void writeFloat(float) throws java.io.IOException;
+    method public void writeInt(int) throws java.io.IOException;
+    method public void writeLong(long) throws java.io.IOException;
+    method public final void writeObject(java.lang.Object) throws java.io.IOException;
+    method protected void writeObjectOverride(java.lang.Object) throws java.io.IOException;
+    method public void writeShort(int) throws java.io.IOException;
+    method protected void writeStreamHeader() throws java.io.IOException;
+    method public void writeUTF(java.lang.String) throws java.io.IOException;
+    method public void writeUnshared(java.lang.Object) throws java.io.IOException;
+  }
+
+  public static abstract class ObjectOutputStream.PutField {
+    ctor public ObjectOutputStream.PutField();
+    method public abstract void put(java.lang.String, boolean);
+    method public abstract void put(java.lang.String, char);
+    method public abstract void put(java.lang.String, byte);
+    method public abstract void put(java.lang.String, short);
+    method public abstract void put(java.lang.String, int);
+    method public abstract void put(java.lang.String, long);
+    method public abstract void put(java.lang.String, float);
+    method public abstract void put(java.lang.String, double);
+    method public abstract void put(java.lang.String, java.lang.Object);
+    method public abstract deprecated void write(java.io.ObjectOutput) throws java.io.IOException;
+  }
+
+  public class ObjectStreamClass implements java.io.Serializable {
+    method public java.lang.Class<?> forClass();
+    method public java.io.ObjectStreamField getField(java.lang.String);
+    method public java.io.ObjectStreamField[] getFields();
+    method public java.lang.String getName();
+    method public long getSerialVersionUID();
+    method public static java.io.ObjectStreamClass lookup(java.lang.Class<?>);
+    method public static java.io.ObjectStreamClass lookupAny(java.lang.Class<?>);
+    field public static final java.io.ObjectStreamField[] NO_FIELDS;
+  }
+
+  public abstract interface ObjectStreamConstants {
+    field public static final int PROTOCOL_VERSION_1 = 1; // 0x1
+    field public static final int PROTOCOL_VERSION_2 = 2; // 0x2
+    field public static final byte SC_BLOCK_DATA = 8; // 0x8
+    field public static final byte SC_ENUM = 16; // 0x10
+    field public static final byte SC_EXTERNALIZABLE = 4; // 0x4
+    field public static final byte SC_SERIALIZABLE = 2; // 0x2
+    field public static final byte SC_WRITE_METHOD = 1; // 0x1
+    field public static final short STREAM_MAGIC = -21267; // 0xffffaced
+    field public static final short STREAM_VERSION = 5; // 0x5
+    field public static final java.io.SerializablePermission SUBCLASS_IMPLEMENTATION_PERMISSION;
+    field public static final java.io.SerializablePermission SUBSTITUTION_PERMISSION;
+    field public static final byte TC_ARRAY = 117; // 0x75
+    field public static final byte TC_BASE = 112; // 0x70
+    field public static final byte TC_BLOCKDATA = 119; // 0x77
+    field public static final byte TC_BLOCKDATALONG = 122; // 0x7a
+    field public static final byte TC_CLASS = 118; // 0x76
+    field public static final byte TC_CLASSDESC = 114; // 0x72
+    field public static final byte TC_ENDBLOCKDATA = 120; // 0x78
+    field public static final byte TC_ENUM = 126; // 0x7e
+    field public static final byte TC_EXCEPTION = 123; // 0x7b
+    field public static final byte TC_LONGSTRING = 124; // 0x7c
+    field public static final byte TC_MAX = 126; // 0x7e
+    field public static final byte TC_NULL = 112; // 0x70
+    field public static final byte TC_OBJECT = 115; // 0x73
+    field public static final byte TC_PROXYCLASSDESC = 125; // 0x7d
+    field public static final byte TC_REFERENCE = 113; // 0x71
+    field public static final byte TC_RESET = 121; // 0x79
+    field public static final byte TC_STRING = 116; // 0x74
+    field public static final int baseWireHandle = 8257536; // 0x7e0000
+  }
+
+  public abstract class ObjectStreamException extends java.io.IOException {
+    ctor protected ObjectStreamException();
+    ctor protected ObjectStreamException(java.lang.String);
+  }
+
+  public class ObjectStreamField implements java.lang.Comparable {
+    ctor public ObjectStreamField(java.lang.String, java.lang.Class<?>);
+    ctor public ObjectStreamField(java.lang.String, java.lang.Class<?>, boolean);
+    method public int compareTo(java.lang.Object);
+    method public java.lang.String getName();
+    method public int getOffset();
+    method public java.lang.Class<?> getType();
+    method public char getTypeCode();
+    method public java.lang.String getTypeString();
+    method public boolean isPrimitive();
+    method public boolean isUnshared();
+    method protected void setOffset(int);
+  }
+
+  public class OptionalDataException extends java.io.ObjectStreamException {
+    field public boolean eof;
+    field public int length;
+  }
+
+  public abstract class OutputStream implements java.io.Closeable java.io.Flushable {
+    ctor public OutputStream();
+    method public void close() throws java.io.IOException;
+    method public void flush() throws java.io.IOException;
+    method public void write(byte[]) throws java.io.IOException;
+    method public void write(byte[], int, int) throws java.io.IOException;
+    method public abstract void write(int) throws java.io.IOException;
+  }
+
+  public class OutputStreamWriter extends java.io.Writer {
+    ctor public OutputStreamWriter(java.io.OutputStream);
+    ctor public OutputStreamWriter(java.io.OutputStream, java.lang.String) throws java.io.UnsupportedEncodingException;
+    ctor public OutputStreamWriter(java.io.OutputStream, java.nio.charset.Charset);
+    ctor public OutputStreamWriter(java.io.OutputStream, java.nio.charset.CharsetEncoder);
+    method public void close() throws java.io.IOException;
+    method public void flush() throws java.io.IOException;
+    method public java.lang.String getEncoding();
+    method public void write(char[], int, int) throws java.io.IOException;
+  }
+
+  public class PipedInputStream extends java.io.InputStream {
+    ctor public PipedInputStream();
+    ctor public PipedInputStream(java.io.PipedOutputStream) throws java.io.IOException;
+    ctor public PipedInputStream(int);
+    ctor public PipedInputStream(java.io.PipedOutputStream, int) throws java.io.IOException;
+    method public void connect(java.io.PipedOutputStream) throws java.io.IOException;
+    method public synchronized int read() throws java.io.IOException;
+    method protected synchronized void receive(int) throws java.io.IOException;
+    field protected static final int PIPE_SIZE = 1024; // 0x400
+    field protected byte[] buffer;
+    field protected int in;
+    field protected int out;
+  }
+
+  public class PipedOutputStream extends java.io.OutputStream {
+    ctor public PipedOutputStream();
+    ctor public PipedOutputStream(java.io.PipedInputStream) throws java.io.IOException;
+    method public void connect(java.io.PipedInputStream) throws java.io.IOException;
+    method public void write(int) throws java.io.IOException;
+  }
+
+  public class PipedReader extends java.io.Reader {
+    ctor public PipedReader();
+    ctor public PipedReader(java.io.PipedWriter) throws java.io.IOException;
+    ctor public PipedReader(int);
+    ctor public PipedReader(java.io.PipedWriter, int) throws java.io.IOException;
+    method public synchronized void close() throws java.io.IOException;
+    method public void connect(java.io.PipedWriter) throws java.io.IOException;
+    method public synchronized int read(char[], int, int) throws java.io.IOException;
+  }
+
+  public class PipedWriter extends java.io.Writer {
+    ctor public PipedWriter();
+    ctor public PipedWriter(java.io.PipedReader) throws java.io.IOException;
+    method public void close() throws java.io.IOException;
+    method public void connect(java.io.PipedReader) throws java.io.IOException;
+    method public void flush() throws java.io.IOException;
+    method public void write(char[], int, int) throws java.io.IOException;
+  }
+
+  public class PrintStream extends java.io.FilterOutputStream implements java.lang.Appendable java.io.Closeable {
+    ctor public PrintStream(java.io.OutputStream);
+    ctor public PrintStream(java.io.OutputStream, boolean);
+    ctor public PrintStream(java.io.OutputStream, boolean, java.lang.String) throws java.io.UnsupportedEncodingException;
+    ctor public PrintStream(java.io.File) throws java.io.FileNotFoundException;
+    ctor public PrintStream(java.io.File, java.lang.String) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException;
+    ctor public PrintStream(java.lang.String) throws java.io.FileNotFoundException;
+    ctor public PrintStream(java.lang.String, java.lang.String) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException;
+    method public java.io.PrintStream append(char);
+    method public java.io.PrintStream append(java.lang.CharSequence);
+    method public java.io.PrintStream append(java.lang.CharSequence, int, int);
+    method public boolean checkError();
+    method protected void clearError();
+    method public java.io.PrintStream format(java.lang.String, java.lang.Object...);
+    method public java.io.PrintStream format(java.util.Locale, java.lang.String, java.lang.Object...);
+    method public void print(char[]);
+    method public void print(char);
+    method public void print(double);
+    method public void print(float);
+    method public void print(int);
+    method public void print(long);
+    method public void print(java.lang.Object);
+    method public synchronized void print(java.lang.String);
+    method public void print(boolean);
+    method public java.io.PrintStream printf(java.lang.String, java.lang.Object...);
+    method public java.io.PrintStream printf(java.util.Locale, java.lang.String, java.lang.Object...);
+    method public void println();
+    method public void println(char[]);
+    method public void println(char);
+    method public void println(double);
+    method public void println(float);
+    method public void println(int);
+    method public void println(long);
+    method public void println(java.lang.Object);
+    method public synchronized void println(java.lang.String);
+    method public void println(boolean);
+    method protected void setError();
+  }
+
+  public class PrintWriter extends java.io.Writer {
+    ctor public PrintWriter(java.io.OutputStream);
+    ctor public PrintWriter(java.io.OutputStream, boolean);
+    ctor public PrintWriter(java.io.Writer);
+    ctor public PrintWriter(java.io.Writer, boolean);
+    ctor public PrintWriter(java.io.File) throws java.io.FileNotFoundException;
+    ctor public PrintWriter(java.io.File, java.lang.String) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException;
+    ctor public PrintWriter(java.lang.String) throws java.io.FileNotFoundException;
+    ctor public PrintWriter(java.lang.String, java.lang.String) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException;
+    method public boolean checkError();
+    method protected void clearError();
+    method public void close();
+    method public void flush();
+    method public java.io.PrintWriter format(java.lang.String, java.lang.Object...);
+    method public java.io.PrintWriter format(java.util.Locale, java.lang.String, java.lang.Object...);
+    method public void print(char[]);
+    method public void print(char);
+    method public void print(double);
+    method public void print(float);
+    method public void print(int);
+    method public void print(long);
+    method public void print(java.lang.Object);
+    method public void print(java.lang.String);
+    method public void print(boolean);
+    method public java.io.PrintWriter printf(java.lang.String, java.lang.Object...);
+    method public java.io.PrintWriter printf(java.util.Locale, java.lang.String, java.lang.Object...);
+    method public void println();
+    method public void println(char[]);
+    method public void println(char);
+    method public void println(double);
+    method public void println(float);
+    method public void println(int);
+    method public void println(long);
+    method public void println(java.lang.Object);
+    method public void println(java.lang.String);
+    method public void println(boolean);
+    method protected void setError();
+    method public void write(char[], int, int);
+    field protected java.io.Writer out;
+  }
+
+  public class PushbackInputStream extends java.io.FilterInputStream {
+    ctor public PushbackInputStream(java.io.InputStream);
+    ctor public PushbackInputStream(java.io.InputStream, int);
+    method public void unread(byte[]) throws java.io.IOException;
+    method public void unread(byte[], int, int) throws java.io.IOException;
+    method public void unread(int) throws java.io.IOException;
+    field protected byte[] buf;
+    field protected int pos;
+  }
+
+  public class PushbackReader extends java.io.FilterReader {
+    ctor public PushbackReader(java.io.Reader);
+    ctor public PushbackReader(java.io.Reader, int);
+    method public void unread(char[]) throws java.io.IOException;
+    method public void unread(char[], int, int) throws java.io.IOException;
+    method public void unread(int) throws java.io.IOException;
+  }
+
+  public class RandomAccessFile implements java.io.Closeable java.io.DataInput java.io.DataOutput {
+    ctor public RandomAccessFile(java.io.File, java.lang.String) throws java.io.FileNotFoundException;
+    ctor public RandomAccessFile(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
+    method public void close() throws java.io.IOException;
+    method public final synchronized java.nio.channels.FileChannel getChannel();
+    method public final java.io.FileDescriptor getFD() throws java.io.IOException;
+    method public long getFilePointer() throws java.io.IOException;
+    method public long length() throws java.io.IOException;
+    method public int read() throws java.io.IOException;
+    method public int read(byte[]) throws java.io.IOException;
+    method public int read(byte[], int, int) throws java.io.IOException;
+    method public final boolean readBoolean() throws java.io.IOException;
+    method public final byte readByte() throws java.io.IOException;
+    method public final char readChar() throws java.io.IOException;
+    method public final double readDouble() throws java.io.IOException;
+    method public final float readFloat() throws java.io.IOException;
+    method public final void readFully(byte[]) throws java.io.IOException;
+    method public final void readFully(byte[], int, int) throws java.io.IOException;
+    method public final int readInt() throws java.io.IOException;
+    method public final java.lang.String readLine() throws java.io.IOException;
+    method public final long readLong() throws java.io.IOException;
+    method public final short readShort() throws java.io.IOException;
+    method public final java.lang.String readUTF() throws java.io.IOException;
+    method public final int readUnsignedByte() throws java.io.IOException;
+    method public final int readUnsignedShort() throws java.io.IOException;
+    method public void seek(long) throws java.io.IOException;
+    method public void setLength(long) throws java.io.IOException;
+    method public int skipBytes(int) throws java.io.IOException;
+    method public void write(byte[]) throws java.io.IOException;
+    method public void write(byte[], int, int) throws java.io.IOException;
+    method public void write(int) throws java.io.IOException;
+    method public final void writeBoolean(boolean) throws java.io.IOException;
+    method public final void writeByte(int) throws java.io.IOException;
+    method public final void writeBytes(java.lang.String) throws java.io.IOException;
+    method public final void writeChar(int) throws java.io.IOException;
+    method public final void writeChars(java.lang.String) throws java.io.IOException;
+    method public final void writeDouble(double) throws java.io.IOException;
+    method public final void writeFloat(float) throws java.io.IOException;
+    method public final void writeInt(int) throws java.io.IOException;
+    method public final void writeLong(long) throws java.io.IOException;
+    method public final void writeShort(int) throws java.io.IOException;
+    method public final void writeUTF(java.lang.String) throws java.io.IOException;
+  }
+
+  public abstract class Reader implements java.io.Closeable java.lang.Readable {
+    ctor protected Reader();
+    ctor protected Reader(java.lang.Object);
+    method public abstract void close() throws java.io.IOException;
+    method public void mark(int) throws java.io.IOException;
+    method public boolean markSupported();
+    method public int read() throws java.io.IOException;
+    method public int read(char[]) throws java.io.IOException;
+    method public abstract int read(char[], int, int) throws java.io.IOException;
+    method public int read(java.nio.CharBuffer) throws java.io.IOException;
+    method public boolean ready() throws java.io.IOException;
+    method public void reset() throws java.io.IOException;
+    method public long skip(long) throws java.io.IOException;
+    field protected java.lang.Object lock;
+  }
+
+  public class SequenceInputStream extends java.io.InputStream {
+    ctor public SequenceInputStream(java.io.InputStream, java.io.InputStream);
+    ctor public SequenceInputStream(java.util.Enumeration<? extends java.io.InputStream>);
+    method public int read() throws java.io.IOException;
+  }
+
+  public abstract interface Serializable {
+  }
+
+  public final class SerializablePermission extends java.security.BasicPermission {
+    ctor public SerializablePermission(java.lang.String);
+    ctor public SerializablePermission(java.lang.String, java.lang.String);
+  }
+
+  public class StreamCorruptedException extends java.io.ObjectStreamException {
+    ctor public StreamCorruptedException();
+    ctor public StreamCorruptedException(java.lang.String);
+  }
+
+  public class StreamTokenizer {
+    ctor public deprecated StreamTokenizer(java.io.InputStream);
+    ctor public StreamTokenizer(java.io.Reader);
+    method public void commentChar(int);
+    method public void eolIsSignificant(boolean);
+    method public int lineno();
+    method public void lowerCaseMode(boolean);
+    method public int nextToken() throws java.io.IOException;
+    method public void ordinaryChar(int);
+    method public void ordinaryChars(int, int);
+    method public void parseNumbers();
+    method public void pushBack();
+    method public void quoteChar(int);
+    method public void resetSyntax();
+    method public void slashSlashComments(boolean);
+    method public void slashStarComments(boolean);
+    method public void whitespaceChars(int, int);
+    method public void wordChars(int, int);
+    field public static final int TT_EOF = -1; // 0xffffffff
+    field public static final int TT_EOL = 10; // 0xa
+    field public static final int TT_NUMBER = -2; // 0xfffffffe
+    field public static final int TT_WORD = -3; // 0xfffffffd
+    field public double nval;
+    field public java.lang.String sval;
+    field public int ttype;
+  }
+
+  public deprecated class StringBufferInputStream extends java.io.InputStream {
+    ctor public StringBufferInputStream(java.lang.String);
+    method public synchronized int read();
+    field protected java.lang.String buffer;
+    field protected int count;
+    field protected int pos;
+  }
+
+  public class StringReader extends java.io.Reader {
+    ctor public StringReader(java.lang.String);
+    method public void close();
+    method public int read(char[], int, int) throws java.io.IOException;
+  }
+
+  public class StringWriter extends java.io.Writer {
+    ctor public StringWriter();
+    ctor public StringWriter(int);
+    method public void close() throws java.io.IOException;
+    method public void flush();
+    method public java.lang.StringBuffer getBuffer();
+    method public void write(char[], int, int);
+  }
+
+  public class SyncFailedException extends java.io.IOException {
+    ctor public SyncFailedException(java.lang.String);
+  }
+
+  public class UTFDataFormatException extends java.io.IOException {
+    ctor public UTFDataFormatException();
+    ctor public UTFDataFormatException(java.lang.String);
+  }
+
+  public class UnsupportedEncodingException extends java.io.IOException {
+    ctor public UnsupportedEncodingException();
+    ctor public UnsupportedEncodingException(java.lang.String);
+  }
+
+  public class WriteAbortedException extends java.io.ObjectStreamException {
+    ctor public WriteAbortedException(java.lang.String, java.lang.Exception);
+    field public java.lang.Exception detail;
+  }
+
+  public abstract class Writer implements java.lang.Appendable java.io.Closeable java.io.Flushable {
+    ctor protected Writer();
+    ctor protected Writer(java.lang.Object);
+    method public java.io.Writer append(char) throws java.io.IOException;
+    method public java.io.Writer append(java.lang.CharSequence) throws java.io.IOException;
+    method public java.io.Writer append(java.lang.CharSequence, int, int) throws java.io.IOException;
+    method public abstract void close() throws java.io.IOException;
+    method public abstract void flush() throws java.io.IOException;
+    method public void write(char[]) throws java.io.IOException;
+    method public abstract void write(char[], int, int) throws java.io.IOException;
+    method public void write(int) throws java.io.IOException;
+    method public void write(java.lang.String) throws java.io.IOException;
+    method public void write(java.lang.String, int, int) throws java.io.IOException;
+    field protected java.lang.Object lock;
+  }
+
+}
+
+package java.lang {
+
+  public class AbstractMethodError extends java.lang.IncompatibleClassChangeError {
+    ctor public AbstractMethodError();
+    ctor public AbstractMethodError(java.lang.String);
+  }
+
+   abstract class AbstractStringBuilder {
+    method public int capacity();
+    method public char charAt(int);
+    method public int codePointAt(int);
+    method public int codePointBefore(int);
+    method public int codePointCount(int, int);
+    method public void ensureCapacity(int);
+    method public void getChars(int, int, char[], int);
+    method public int indexOf(java.lang.String);
+    method public int indexOf(java.lang.String, int);
+    method public int lastIndexOf(java.lang.String);
+    method public int lastIndexOf(java.lang.String, int);
+    method public int length();
+    method public int offsetByCodePoints(int, int);
+    method public void setCharAt(int, char);
+    method public void setLength(int);
+    method public java.lang.CharSequence subSequence(int, int);
+    method public java.lang.String substring(int);
+    method public java.lang.String substring(int, int);
+    method public void trimToSize();
+  }
+
+  public abstract interface Appendable {
+    method public abstract java.lang.Appendable append(char) throws java.io.IOException;
+    method public abstract java.lang.Appendable append(java.lang.CharSequence) throws java.io.IOException;
+    method public abstract java.lang.Appendable append(java.lang.CharSequence, int, int) throws java.io.IOException;
+  }
+
+  public class ArithmeticException extends java.lang.RuntimeException {
+    ctor public ArithmeticException();
+    ctor public ArithmeticException(java.lang.String);
+  }
+
+  public class ArrayIndexOutOfBoundsException extends java.lang.IndexOutOfBoundsException {
+    ctor public ArrayIndexOutOfBoundsException();
+    ctor public ArrayIndexOutOfBoundsException(int);
+    ctor public ArrayIndexOutOfBoundsException(java.lang.String);
+  }
+
+  public class ArrayStoreException extends java.lang.RuntimeException {
+    ctor public ArrayStoreException();
+    ctor public ArrayStoreException(java.lang.String);
+  }
+
+  public class AssertionError extends java.lang.Error {
+    ctor public AssertionError();
+    ctor public AssertionError(java.lang.Object);
+    ctor public AssertionError(boolean);
+    ctor public AssertionError(char);
+    ctor public AssertionError(int);
+    ctor public AssertionError(long);
+    ctor public AssertionError(float);
+    ctor public AssertionError(double);
+  }
+
+  public final class Boolean implements java.lang.Comparable java.io.Serializable {
+    ctor public Boolean(java.lang.String);
+    ctor public Boolean(boolean);
+    method public boolean booleanValue();
+    method public int compareTo(java.lang.Boolean);
+    method public static boolean getBoolean(java.lang.String);
+    method public static boolean parseBoolean(java.lang.String);
+    method public static java.lang.String toString(boolean);
+    method public static java.lang.Boolean valueOf(java.lang.String);
+    method public static java.lang.Boolean valueOf(boolean);
+    field public static final java.lang.Boolean FALSE;
+    field public static final java.lang.Boolean TRUE;
+    field public static final java.lang.Class TYPE;
+  }
+
+  public final class Byte extends java.lang.Number implements java.lang.Comparable {
+    ctor public Byte(byte);
+    ctor public Byte(java.lang.String) throws java.lang.NumberFormatException;
+    method public int compareTo(java.lang.Byte);
+    method public static java.lang.Byte decode(java.lang.String) throws java.lang.NumberFormatException;
+    method public double doubleValue();
+    method public float floatValue();
+    method public int intValue();
+    method public long longValue();
+    method public static byte parseByte(java.lang.String) throws java.lang.NumberFormatException;
+    method public static byte parseByte(java.lang.String, int) throws java.lang.NumberFormatException;
+    method public static java.lang.String toString(byte);
+    method public static java.lang.Byte valueOf(java.lang.String) throws java.lang.NumberFormatException;
+    method public static java.lang.Byte valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
+    method public static java.lang.Byte valueOf(byte);
+    field public static final byte MAX_VALUE = 127; // 0x7f
+    field public static final byte MIN_VALUE = -128; // 0xffffff80
+    field public static final int SIZE = 8; // 0x8
+    field public static final java.lang.Class TYPE;
+  }
+
+  public abstract interface CharSequence {
+    method public abstract char charAt(int);
+    method public abstract int length();
+    method public abstract java.lang.CharSequence subSequence(int, int);
+    method public abstract java.lang.String toString();
+  }
+
+  public final class Character implements java.lang.Comparable java.io.Serializable {
+    ctor public Character(char);
+    method public static int charCount(int);
+    method public char charValue();
+    method public static int codePointAt(java.lang.CharSequence, int);
+    method public static int codePointAt(char[], int);
+    method public static int codePointAt(char[], int, int);
+    method public static int codePointBefore(java.lang.CharSequence, int);
+    method public static int codePointBefore(char[], int);
+    method public static int codePointBefore(char[], int, int);
+    method public static int codePointCount(java.lang.CharSequence, int, int);
+    method public static int codePointCount(char[], int, int);
+    method public int compareTo(java.lang.Character);
+    method public static int digit(char, int);
+    method public static int digit(int, int);
+    method public static char forDigit(int, int);
+    method public static byte getDirectionality(char);
+    method public static byte getDirectionality(int);
+    method public static int getNumericValue(char);
+    method public static int getNumericValue(int);
+    method public static int getType(char);
+    method public static int getType(int);
+    method public static boolean isDefined(char);
+    method public static boolean isDefined(int);
+    method public static boolean isDigit(char);
+    method public static boolean isDigit(int);
+    method public static boolean isHighSurrogate(char);
+    method public static boolean isISOControl(char);
+    method public static boolean isISOControl(int);
+    method public static boolean isIdentifierIgnorable(char);
+    method public static boolean isIdentifierIgnorable(int);
+    method public static boolean isJavaIdentifierPart(char);
+    method public static boolean isJavaIdentifierPart(int);
+    method public static boolean isJavaIdentifierStart(char);
+    method public static boolean isJavaIdentifierStart(int);
+    method public static deprecated boolean isJavaLetter(char);
+    method public static deprecated boolean isJavaLetterOrDigit(char);
+    method public static boolean isLetter(char);
+    method public static boolean isLetter(int);
+    method public static boolean isLetterOrDigit(char);
+    method public static boolean isLetterOrDigit(int);
+    method public static boolean isLowSurrogate(char);
+    method public static boolean isLowerCase(char);
+    method public static boolean isLowerCase(int);
+    method public static boolean isMirrored(char);
+    method public static boolean isMirrored(int);
+    method public static deprecated boolean isSpace(char);
+    method public static boolean isSpaceChar(char);
+    method public static boolean isSpaceChar(int);
+    method public static boolean isSupplementaryCodePoint(int);
+    method public static boolean isSurrogatePair(char, char);
+    method public static boolean isTitleCase(char);
+    method public static boolean isTitleCase(int);
+    method public static boolean isUnicodeIdentifierPart(char);
+    method public static boolean isUnicodeIdentifierPart(int);
+    method public static boolean isUnicodeIdentifierStart(char);
+    method public static boolean isUnicodeIdentifierStart(int);
+    method public static boolean isUpperCase(char);
+    method public static boolean isUpperCase(int);
+    method public static boolean isValidCodePoint(int);
+    method public static boolean isWhitespace(char);
+    method public static boolean isWhitespace(int);
+    method public static int offsetByCodePoints(java.lang.CharSequence, int, int);
+    method public static int offsetByCodePoints(char[], int, int, int, int);
+    method public static char reverseBytes(char);
+    method public static int toChars(int, char[], int);
+    method public static char[] toChars(int);
+    method public static int toCodePoint(char, char);
+    method public static char toLowerCase(char);
+    method public static int toLowerCase(int);
+    method public static java.lang.String toString(char);
+    method public static char toTitleCase(char);
+    method public static int toTitleCase(int);
+    method public static char toUpperCase(char);
+    method public static int toUpperCase(int);
+    method public static java.lang.Character valueOf(char);
+    field public static final byte COMBINING_SPACING_MARK = 8; // 0x8
+    field public static final byte CONNECTOR_PUNCTUATION = 23; // 0x17
+    field public static final byte CONTROL = 15; // 0xf
+    field public static final byte CURRENCY_SYMBOL = 26; // 0x1a
+    field public static final byte DASH_PUNCTUATION = 20; // 0x14
+    field public static final byte DECIMAL_DIGIT_NUMBER = 9; // 0x9
+    field public static final byte DIRECTIONALITY_ARABIC_NUMBER = 6; // 0x6
+    field public static final byte DIRECTIONALITY_BOUNDARY_NEUTRAL = 9; // 0x9
+    field public static final byte DIRECTIONALITY_COMMON_NUMBER_SEPARATOR = 7; // 0x7
+    field public static final byte DIRECTIONALITY_EUROPEAN_NUMBER = 3; // 0x3
+    field public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR = 4; // 0x4
+    field public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR = 5; // 0x5
+    field public static final byte DIRECTIONALITY_LEFT_TO_RIGHT = 0; // 0x0
+    field public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING = 14; // 0xe
+    field public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE = 15; // 0xf
+    field public static final byte DIRECTIONALITY_NONSPACING_MARK = 8; // 0x8
+    field public static final byte DIRECTIONALITY_OTHER_NEUTRALS = 13; // 0xd
+    field public static final byte DIRECTIONALITY_PARAGRAPH_SEPARATOR = 10; // 0xa
+    field public static final byte DIRECTIONALITY_POP_DIRECTIONAL_FORMAT = 18; // 0x12
+    field public static final byte DIRECTIONALITY_RIGHT_TO_LEFT = 1; // 0x1
+    field public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC = 2; // 0x2
+    field public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING = 16; // 0x10
+    field public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE = 17; // 0x11
+    field public static final byte DIRECTIONALITY_SEGMENT_SEPARATOR = 11; // 0xb
+    field public static final byte DIRECTIONALITY_UNDEFINED = -1; // 0xffffffff
+    field public static final byte DIRECTIONALITY_WHITESPACE = 12; // 0xc
+    field public static final byte ENCLOSING_MARK = 7; // 0x7
+    field public static final byte END_PUNCTUATION = 22; // 0x16
+    field public static final byte FINAL_QUOTE_PUNCTUATION = 30; // 0x1e
+    field public static final byte FORMAT = 16; // 0x10
+    field public static final byte INITIAL_QUOTE_PUNCTUATION = 29; // 0x1d
+    field public static final byte LETTER_NUMBER = 10; // 0xa
+    field public static final byte LINE_SEPARATOR = 13; // 0xd
+    field public static final byte LOWERCASE_LETTER = 2; // 0x2
+    field public static final byte MATH_SYMBOL = 25; // 0x19
+    field public static final int MAX_CODE_POINT = 1114111; // 0x10ffff
+    field public static final char MAX_HIGH_SURROGATE = 56319; // 0xdbff '\udbff'
+    field public static final char MAX_LOW_SURROGATE = 57343; // 0xdfff '\udfff'
+    field public static final int MAX_RADIX = 36; // 0x24
+    field public static final char MAX_SURROGATE = 57343; // 0xdfff '\udfff'
+    field public static final char MAX_VALUE = 65535; // 0xffff '\uffff'
+    field public static final int MIN_CODE_POINT = 0; // 0x0
+    field public static final char MIN_HIGH_SURROGATE = 55296; // 0xd800 '\ud800'
+    field public static final char MIN_LOW_SURROGATE = 56320; // 0xdc00 '\udc00'
+    field public static final int MIN_RADIX = 2; // 0x2
+    field public static final int MIN_SUPPLEMENTARY_CODE_POINT = 65536; // 0x10000
+    field public static final char MIN_SURROGATE = 55296; // 0xd800 '\ud800'
+    field public static final char MIN_VALUE = 0; // 0x0000 '\u0000'
+    field public static final byte MODIFIER_LETTER = 4; // 0x4
+    field public static final byte MODIFIER_SYMBOL = 27; // 0x1b
+    field public static final byte NON_SPACING_MARK = 6; // 0x6
+    field public static final byte OTHER_LETTER = 5; // 0x5
+    field public static final byte OTHER_NUMBER = 11; // 0xb
+    field public static final byte OTHER_PUNCTUATION = 24; // 0x18
+    field public static final byte OTHER_SYMBOL = 28; // 0x1c
+    field public static final byte PARAGRAPH_SEPARATOR = 14; // 0xe
+    field public static final byte PRIVATE_USE = 18; // 0x12
+    field public static final int SIZE = 16; // 0x10
+    field public static final byte SPACE_SEPARATOR = 12; // 0xc
+    field public static final byte START_PUNCTUATION = 21; // 0x15
+    field public static final byte SURROGATE = 19; // 0x13
+    field public static final byte TITLECASE_LETTER = 3; // 0x3
+    field public static final java.lang.Class TYPE;
+    field public static final byte UNASSIGNED = 0; // 0x0
+    field public static final byte UPPERCASE_LETTER = 1; // 0x1
+  }
+
+  public static class Character.Subset {
+    ctor protected Character.Subset(java.lang.String);
+    method public final boolean equals(java.lang.Object);
+    method public final int hashCode();
+    method public final java.lang.String toString();
+  }
+
+  public static final class Character.UnicodeBlock extends java.lang.Character.Subset {
+    method public static java.lang.Character.UnicodeBlock forName(java.lang.String);
+    method public static java.lang.Character.UnicodeBlock of(char);
+    method public static java.lang.Character.UnicodeBlock of(int);
+    field public static final java.lang.Character.UnicodeBlock AEGEAN_NUMBERS;
+    field public static final java.lang.Character.UnicodeBlock ALPHABETIC_PRESENTATION_FORMS;
+    field public static final java.lang.Character.UnicodeBlock ARABIC;
+    field public static final java.lang.Character.UnicodeBlock ARABIC_PRESENTATION_FORMS_A;
+    field public static final java.lang.Character.UnicodeBlock ARABIC_PRESENTATION_FORMS_B;
+    field public static final java.lang.Character.UnicodeBlock ARMENIAN;
+    field public static final java.lang.Character.UnicodeBlock ARROWS;
+    field public static final java.lang.Character.UnicodeBlock BASIC_LATIN;
+    field public static final java.lang.Character.UnicodeBlock BENGALI;
+    field public static final java.lang.Character.UnicodeBlock BLOCK_ELEMENTS;
+    field public static final java.lang.Character.UnicodeBlock BOPOMOFO;
+    field public static final java.lang.Character.UnicodeBlock BOPOMOFO_EXTENDED;
+    field public static final java.lang.Character.UnicodeBlock BOX_DRAWING;
+    field public static final java.lang.Character.UnicodeBlock BRAILLE_PATTERNS;
+    field public static final java.lang.Character.UnicodeBlock BUHID;
+    field public static final java.lang.Character.UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS;
+    field public static final java.lang.Character.UnicodeBlock CHEROKEE;
+    field public static final java.lang.Character.UnicodeBlock CJK_COMPATIBILITY;
+    field public static final java.lang.Character.UnicodeBlock CJK_COMPATIBILITY_FORMS;
+    field public static final java.lang.Character.UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS;
+    field public static final java.lang.Character.UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT;
+    field public static final java.lang.Character.UnicodeBlock CJK_RADICALS_SUPPLEMENT;
+    field public static final java.lang.Character.UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION;
+    field public static final java.lang.Character.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS;
+    field public static final java.lang.Character.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A;
+    field public static final java.lang.Character.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B;
+    field public static final java.lang.Character.UnicodeBlock COMBINING_DIACRITICAL_MARKS;
+    field public static final java.lang.Character.UnicodeBlock COMBINING_HALF_MARKS;
+    field public static final java.lang.Character.UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS;
+    field public static final java.lang.Character.UnicodeBlock CONTROL_PICTURES;
+    field public static final java.lang.Character.UnicodeBlock CURRENCY_SYMBOLS;
+    field public static final java.lang.Character.UnicodeBlock CYPRIOT_SYLLABARY;
+    field public static final java.lang.Character.UnicodeBlock CYRILLIC;
+    field public static final java.lang.Character.UnicodeBlock CYRILLIC_SUPPLEMENTARY;
+    field public static final java.lang.Character.UnicodeBlock DESERET;
+    field public static final java.lang.Character.UnicodeBlock DEVANAGARI;
+    field public static final java.lang.Character.UnicodeBlock DINGBATS;
+    field public static final java.lang.Character.UnicodeBlock ENCLOSED_ALPHANUMERICS;
+    field public static final java.lang.Character.UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS;
+    field public static final java.lang.Character.UnicodeBlock ETHIOPIC;
+    field public static final java.lang.Character.UnicodeBlock GENERAL_PUNCTUATION;
+    field public static final java.lang.Character.UnicodeBlock GEOMETRIC_SHAPES;
+    field public static final java.lang.Character.UnicodeBlock GEORGIAN;
+    field public static final java.lang.Character.UnicodeBlock GOTHIC;
+    field public static final java.lang.Character.UnicodeBlock GREEK;
+    field public static final java.lang.Character.UnicodeBlock GREEK_EXTENDED;
+    field public static final java.lang.Character.UnicodeBlock GUJARATI;
+    field public static final java.lang.Character.UnicodeBlock GURMUKHI;
+    field public static final java.lang.Character.UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS;
+    field public static final java.lang.Character.UnicodeBlock HANGUL_COMPATIBILITY_JAMO;
+    field public static final java.lang.Character.UnicodeBlock HANGUL_JAMO;
+    field public static final java.lang.Character.UnicodeBlock HANGUL_SYLLABLES;
+    field public static final java.lang.Character.UnicodeBlock HANUNOO;
+    field public static final java.lang.Character.UnicodeBlock HEBREW;
+    field public static final java.lang.Character.UnicodeBlock HIGH_PRIVATE_USE_SURROGATES;
+    field public static final java.lang.Character.UnicodeBlock HIGH_SURROGATES;
+    field public static final java.lang.Character.UnicodeBlock HIRAGANA;
+    field public static final java.lang.Character.UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS;
+    field public static final java.lang.Character.UnicodeBlock IPA_EXTENSIONS;
+    field public static final java.lang.Character.UnicodeBlock KANBUN;
+    field public static final java.lang.Character.UnicodeBlock KANGXI_RADICALS;
+    field public static final java.lang.Character.UnicodeBlock KANNADA;
+    field public static final java.lang.Character.UnicodeBlock KATAKANA;
+    field public static final java.lang.Character.UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS;
+    field public static final java.lang.Character.UnicodeBlock KHMER;
+    field public static final java.lang.Character.UnicodeBlock KHMER_SYMBOLS;
+    field public static final java.lang.Character.UnicodeBlock LAO;
+    field public static final java.lang.Character.UnicodeBlock LATIN_1_SUPPLEMENT;
+    field public static final java.lang.Character.UnicodeBlock LATIN_EXTENDED_A;
+    field public static final java.lang.Character.UnicodeBlock LATIN_EXTENDED_ADDITIONAL;
+    field public static final java.lang.Character.UnicodeBlock LATIN_EXTENDED_B;
+    field public static final java.lang.Character.UnicodeBlock LETTERLIKE_SYMBOLS;
+    field public static final java.lang.Character.UnicodeBlock LIMBU;
+    field public static final java.lang.Character.UnicodeBlock LINEAR_B_IDEOGRAMS;
+    field public static final java.lang.Character.UnicodeBlock LINEAR_B_SYLLABARY;
+    field public static final java.lang.Character.UnicodeBlock LOW_SURROGATES;
+    field public static final java.lang.Character.UnicodeBlock MALAYALAM;
+    field public static final java.lang.Character.UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS;
+    field public static final java.lang.Character.UnicodeBlock MATHEMATICAL_OPERATORS;
+    field public static final java.lang.Character.UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A;
+    field public static final java.lang.Character.UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B;
+    field public static final java.lang.Character.UnicodeBlock MISCELLANEOUS_SYMBOLS;
+    field public static final java.lang.Character.UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS;
+    field public static final java.lang.Character.UnicodeBlock MISCELLANEOUS_TECHNICAL;
+    field public static final java.lang.Character.UnicodeBlock MONGOLIAN;
+    field public static final java.lang.Character.UnicodeBlock MUSICAL_SYMBOLS;
+    field public static final java.lang.Character.UnicodeBlock MYANMAR;
+    field public static final java.lang.Character.UnicodeBlock NUMBER_FORMS;
+    field public static final java.lang.Character.UnicodeBlock OGHAM;
+    field public static final java.lang.Character.UnicodeBlock OLD_ITALIC;
+    field public static final java.lang.Character.UnicodeBlock OPTICAL_CHARACTER_RECOGNITION;
+    field public static final java.lang.Character.UnicodeBlock ORIYA;
+    field public static final java.lang.Character.UnicodeBlock OSMANYA;
+    field public static final java.lang.Character.UnicodeBlock PHONETIC_EXTENSIONS;
+    field public static final java.lang.Character.UnicodeBlock PRIVATE_USE_AREA;
+    field public static final java.lang.Character.UnicodeBlock RUNIC;
+    field public static final java.lang.Character.UnicodeBlock SHAVIAN;
+    field public static final java.lang.Character.UnicodeBlock SINHALA;
+    field public static final java.lang.Character.UnicodeBlock SMALL_FORM_VARIANTS;
+    field public static final java.lang.Character.UnicodeBlock SPACING_MODIFIER_LETTERS;
+    field public static final java.lang.Character.UnicodeBlock SPECIALS;
+    field public static final java.lang.Character.UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS;
+    field public static final java.lang.Character.UnicodeBlock SUPPLEMENTAL_ARROWS_A;
+    field public static final java.lang.Character.UnicodeBlock SUPPLEMENTAL_ARROWS_B;
+    field public static final java.lang.Character.UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS;
+    field public static final java.lang.Character.UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A;
+    field public static final java.lang.Character.UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B;
+    field public static final deprecated java.lang.Character.UnicodeBlock SURROGATES_AREA;
+    field public static final java.lang.Character.UnicodeBlock SYRIAC;
+    field public static final java.lang.Character.UnicodeBlock TAGALOG;
+    field public static final java.lang.Character.UnicodeBlock TAGBANWA;
+    field public static final java.lang.Character.UnicodeBlock TAGS;
+    field public static final java.lang.Character.UnicodeBlock TAI_LE;
+    field public static final java.lang.Character.UnicodeBlock TAI_XUAN_JING_SYMBOLS;
+    field public static final java.lang.Character.UnicodeBlock TAMIL;
+    field public static final java.lang.Character.UnicodeBlock TELUGU;
+    field public static final java.lang.Character.UnicodeBlock THAANA;
+    field public static final java.lang.Character.UnicodeBlock THAI;
+    field public static final java.lang.Character.UnicodeBlock TIBETAN;
+    field public static final java.lang.Character.UnicodeBlock UGARITIC;
+    field public static final java.lang.Character.UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS;
+    field public static final java.lang.Character.UnicodeBlock VARIATION_SELECTORS;
+    field public static final java.lang.Character.UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT;
+    field public static final java.lang.Character.UnicodeBlock YIJING_HEXAGRAM_SYMBOLS;
+    field public static final java.lang.Character.UnicodeBlock YI_RADICALS;
+    field public static final java.lang.Character.UnicodeBlock YI_SYLLABLES;
+  }
+
+  public final class Class implements java.lang.reflect.AnnotatedElement java.lang.reflect.GenericDeclaration java.io.Serializable java.lang.reflect.Type {
+    method public java.lang.Class<? extends U> asSubclass(java.lang.Class<U>);
+    method public T cast(java.lang.Object);
+    method public boolean desiredAssertionStatus();
+    method public static java.lang.Class<?> forName(java.lang.String) throws java.lang.ClassNotFoundException;
+    method public static java.lang.Class<?> forName(java.lang.String, boolean, java.lang.ClassLoader) throws java.lang.ClassNotFoundException;
+    method public A getAnnotation(java.lang.Class<A>);
+    method public java.lang.annotation.Annotation[] getAnnotations();
+    method public java.lang.String getCanonicalName();
+    method public java.lang.ClassLoader getClassLoader();
+    method public java.lang.Class<?>[] getClasses();
+    method public java.lang.Class<?> getComponentType();
+    method public java.lang.reflect.Constructor<T> getConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException;
+    method public java.lang.reflect.Constructor<?>[] getConstructors();
+    method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public java.lang.Class<?>[] getDeclaredClasses();
+    method public java.lang.reflect.Constructor<T> getDeclaredConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException;
+    method public java.lang.reflect.Constructor<?>[] getDeclaredConstructors();
+    method public java.lang.reflect.Field getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException;
+    method public java.lang.reflect.Field[] getDeclaredFields();
+    method public java.lang.reflect.Method getDeclaredMethod(java.lang.String, java.lang.Class<?>...) throws java.lang.NoSuchMethodException;
+    method public java.lang.reflect.Method[] getDeclaredMethods();
+    method public java.lang.Class<?> getDeclaringClass();
+    method public java.lang.Class<?> getEnclosingClass();
+    method public java.lang.reflect.Constructor<?> getEnclosingConstructor();
+    method public java.lang.reflect.Method getEnclosingMethod();
+    method public T[] getEnumConstants();
+    method public java.lang.reflect.Field getField(java.lang.String) throws java.lang.NoSuchFieldException;
+    method public java.lang.reflect.Field[] getFields();
+    method public java.lang.reflect.Type[] getGenericInterfaces();
+    method public java.lang.reflect.Type getGenericSuperclass();
+    method public java.lang.Class<?>[] getInterfaces();
+    method public java.lang.reflect.Method getMethod(java.lang.String, java.lang.Class<?>...) throws java.lang.NoSuchMethodException;
+    method public java.lang.reflect.Method[] getMethods();
+    method public int getModifiers();
+    method public java.lang.String getName();
+    method public java.lang.Package getPackage();
+    method public java.security.ProtectionDomain getProtectionDomain();
+    method public java.net.URL getResource(java.lang.String);
+    method public java.io.InputStream getResourceAsStream(java.lang.String);
+    method public java.lang.Object[] getSigners();
+    method public java.lang.String getSimpleName();
+    method public java.lang.Class<? super T> getSuperclass();
+    method public synchronized java.lang.reflect.TypeVariable<java.lang.Class<T>>[] getTypeParameters();
+    method public boolean isAnnotation();
+    method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
+    method public boolean isAnonymousClass();
+    method public boolean isArray();
+    method public boolean isAssignableFrom(java.lang.Class<?>);
+    method public boolean isEnum();
+    method public boolean isInstance(java.lang.Object);
+    method public boolean isInterface();
+    method public boolean isLocalClass();
+    method public boolean isMemberClass();
+    method public boolean isPrimitive();
+    method public boolean isSynthetic();
+    method public T newInstance() throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+  }
+
+  public class ClassCastException extends java.lang.RuntimeException {
+    ctor public ClassCastException();
+    ctor public ClassCastException(java.lang.String);
+  }
+
+  public class ClassCircularityError extends java.lang.LinkageError {
+    ctor public ClassCircularityError();
+    ctor public ClassCircularityError(java.lang.String);
+  }
+
+  public class ClassFormatError extends java.lang.LinkageError {
+    ctor public ClassFormatError();
+    ctor public ClassFormatError(java.lang.String);
+  }
+
+  public abstract class ClassLoader {
+    ctor protected ClassLoader();
+    ctor protected ClassLoader(java.lang.ClassLoader);
+    method public void clearAssertionStatus();
+    method protected final deprecated java.lang.Class<?> defineClass(byte[], int, int) throws java.lang.ClassFormatError;
+    method protected final java.lang.Class<?> defineClass(java.lang.String, byte[], int, int) throws java.lang.ClassFormatError;
+    method protected final java.lang.Class<?> defineClass(java.lang.String, byte[], int, int, java.security.ProtectionDomain) throws java.lang.ClassFormatError;
+    method protected final java.lang.Class<?> defineClass(java.lang.String, java.nio.ByteBuffer, java.security.ProtectionDomain) throws java.lang.ClassFormatError;
+    method protected java.lang.Package definePackage(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.net.URL) throws java.lang.IllegalArgumentException;
+    method protected java.lang.Class<?> findClass(java.lang.String) throws java.lang.ClassNotFoundException;
+    method protected java.lang.String findLibrary(java.lang.String);
+    method protected final java.lang.Class<?> findLoadedClass(java.lang.String);
+    method protected java.net.URL findResource(java.lang.String);
+    method protected java.util.Enumeration<java.net.URL> findResources(java.lang.String) throws java.io.IOException;
+    method protected final java.lang.Class<?> findSystemClass(java.lang.String) throws java.lang.ClassNotFoundException;
+    method protected java.lang.Package getPackage(java.lang.String);
+    method protected java.lang.Package[] getPackages();
+    method public final java.lang.ClassLoader getParent();
+    method public java.net.URL getResource(java.lang.String);
+    method public java.io.InputStream getResourceAsStream(java.lang.String);
+    method public java.util.Enumeration<java.net.URL> getResources(java.lang.String) throws java.io.IOException;
+    method public static java.lang.ClassLoader getSystemClassLoader();
+    method public static java.net.URL getSystemResource(java.lang.String);
+    method public static java.io.InputStream getSystemResourceAsStream(java.lang.String);
+    method public static java.util.Enumeration<java.net.URL> getSystemResources(java.lang.String) throws java.io.IOException;
+    method public java.lang.Class<?> loadClass(java.lang.String) throws java.lang.ClassNotFoundException;
+    method protected java.lang.Class<?> loadClass(java.lang.String, boolean) throws java.lang.ClassNotFoundException;
+    method protected final void resolveClass(java.lang.Class<?>);
+    method public void setClassAssertionStatus(java.lang.String, boolean);
+    method public void setDefaultAssertionStatus(boolean);
+    method public void setPackageAssertionStatus(java.lang.String, boolean);
+    method protected final void setSigners(java.lang.Class<?>, java.lang.Object[]);
+  }
+
+  public class ClassNotFoundException extends java.lang.Exception {
+    ctor public ClassNotFoundException();
+    ctor public ClassNotFoundException(java.lang.String);
+    ctor public ClassNotFoundException(java.lang.String, java.lang.Throwable);
+    method public java.lang.Throwable getException();
+  }
+
+  public class CloneNotSupportedException extends java.lang.Exception {
+    ctor public CloneNotSupportedException();
+    ctor public CloneNotSupportedException(java.lang.String);
+  }
+
+  public abstract interface Cloneable {
+  }
+
+  public abstract interface Comparable {
+    method public abstract int compareTo(T);
+  }
+
+  public final class Compiler {
+    method public static java.lang.Object command(java.lang.Object);
+    method public static boolean compileClass(java.lang.Class<?>);
+    method public static boolean compileClasses(java.lang.String);
+    method public static void disable();
+    method public static void enable();
+  }
+
+  public abstract class Deprecated implements java.lang.annotation.Annotation {
+  }
+
+  public final class Double extends java.lang.Number implements java.lang.Comparable {
+    ctor public Double(double);
+    ctor public Double(java.lang.String) throws java.lang.NumberFormatException;
+    method public static int compare(double, double);
+    method public int compareTo(java.lang.Double);
+    method public static long doubleToLongBits(double);
+    method public static long doubleToRawLongBits(double);
+    method public double doubleValue();
+    method public float floatValue();
+    method public int intValue();
+    method public boolean isInfinite();
+    method public static boolean isInfinite(double);
+    method public boolean isNaN();
+    method public static boolean isNaN(double);
+    method public static double longBitsToDouble(long);
+    method public long longValue();
+    method public static double parseDouble(java.lang.String) throws java.lang.NumberFormatException;
+    method public static java.lang.String toHexString(double);
+    method public static java.lang.String toString(double);
+    method public static java.lang.Double valueOf(java.lang.String) throws java.lang.NumberFormatException;
+    method public static java.lang.Double valueOf(double);
+    field public static final int MAX_EXPONENT = 1023; // 0x3ff
+    field public static final double MAX_VALUE = 1.7976931348623157E308;
+    field public static final int MIN_EXPONENT = -1022; // 0xfffffc02
+    field public static final double MIN_NORMAL = 2.2250738585072014E-308;
+    field public static final double MIN_VALUE = 4.9E-324;
+    field public static final double NEGATIVE_INFINITY = (-1.0/0.0);
+    field public static final double NaN = (0.0/0.0);
+    field public static final double POSITIVE_INFINITY = (1.0/0.0);
+    field public static final int SIZE = 64; // 0x40
+    field public static final java.lang.Class TYPE;
+  }
+
+  public abstract class Enum implements java.lang.Comparable java.io.Serializable {
+    ctor protected Enum(java.lang.String, int);
+    method protected final java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public final int compareTo(E);
+    method public final boolean equals(java.lang.Object);
+    method protected final void finalize();
+    method public final java.lang.Class<E> getDeclaringClass();
+    method public final int hashCode();
+    method public final java.lang.String name();
+    method public final int ordinal();
+    method public static T valueOf(java.lang.Class<T>, java.lang.String);
+  }
+
+  public class EnumConstantNotPresentException extends java.lang.RuntimeException {
+    ctor public EnumConstantNotPresentException(java.lang.Class<? extends java.lang.Enum>, java.lang.String);
+    method public java.lang.String constantName();
+    method public java.lang.Class<? extends java.lang.Enum> enumType();
+  }
+
+  public class Error extends java.lang.Throwable {
+    ctor public Error();
+    ctor public Error(java.lang.String);
+    ctor public Error(java.lang.String, java.lang.Throwable);
+    ctor public Error(java.lang.Throwable);
+  }
+
+  public class Exception extends java.lang.Throwable {
+    ctor public Exception();
+    ctor public Exception(java.lang.String);
+    ctor public Exception(java.lang.String, java.lang.Throwable);
+    ctor public Exception(java.lang.Throwable);
+  }
+
+  public class ExceptionInInitializerError extends java.lang.LinkageError {
+    ctor public ExceptionInInitializerError();
+    ctor public ExceptionInInitializerError(java.lang.String);
+    ctor public ExceptionInInitializerError(java.lang.Throwable);
+    method public java.lang.Throwable getException();
+  }
+
+  public final class Float extends java.lang.Number implements java.lang.Comparable {
+    ctor public Float(float);
+    ctor public Float(double);
+    ctor public Float(java.lang.String) throws java.lang.NumberFormatException;
+    method public static int compare(float, float);
+    method public int compareTo(java.lang.Float);
+    method public double doubleValue();
+    method public static int floatToIntBits(float);
+    method public static int floatToRawIntBits(float);
+    method public float floatValue();
+    method public static float intBitsToFloat(int);
+    method public int intValue();
+    method public boolean isInfinite();
+    method public static boolean isInfinite(float);
+    method public boolean isNaN();
+    method public static boolean isNaN(float);
+    method public long longValue();
+    method public static float parseFloat(java.lang.String) throws java.lang.NumberFormatException;
+    method public static java.lang.String toHexString(float);
+    method public static java.lang.String toString(float);
+    method public static java.lang.Float valueOf(java.lang.String) throws java.lang.NumberFormatException;
+    method public static java.lang.Float valueOf(float);
+    field public static final int MAX_EXPONENT = 127; // 0x7f
+    field public static final float MAX_VALUE = 3.4028235E38f;
+    field public static final int MIN_EXPONENT = -126; // 0xffffff82
+    field public static final float MIN_NORMAL = 1.17549435E-38f;
+    field public static final float MIN_VALUE = 1.4E-45f;
+    field public static final float NEGATIVE_INFINITY = (-1.0f/0.0f);
+    field public static final float NaN = (0.0f/0.0f);
+    field public static final float POSITIVE_INFINITY = (1.0f/0.0f);
+    field public static final int SIZE = 32; // 0x20
+    field public static final java.lang.Class TYPE;
+  }
+
+  public class IllegalAccessError extends java.lang.IncompatibleClassChangeError {
+    ctor public IllegalAccessError();
+    ctor public IllegalAccessError(java.lang.String);
+  }
+
+  public class IllegalAccessException extends java.lang.Exception {
+    ctor public IllegalAccessException();
+    ctor public IllegalAccessException(java.lang.String);
+  }
+
+  public class IllegalArgumentException extends java.lang.RuntimeException {
+    ctor public IllegalArgumentException();
+    ctor public IllegalArgumentException(java.lang.String);
+    ctor public IllegalArgumentException(java.lang.String, java.lang.Throwable);
+    ctor public IllegalArgumentException(java.lang.Throwable);
+  }
+
+  public class IllegalMonitorStateException extends java.lang.RuntimeException {
+    ctor public IllegalMonitorStateException();
+    ctor public IllegalMonitorStateException(java.lang.String);
+  }
+
+  public class IllegalStateException extends java.lang.RuntimeException {
+    ctor public IllegalStateException();
+    ctor public IllegalStateException(java.lang.String);
+    ctor public IllegalStateException(java.lang.String, java.lang.Throwable);
+    ctor public IllegalStateException(java.lang.Throwable);
+  }
+
+  public class IllegalThreadStateException extends java.lang.IllegalArgumentException {
+    ctor public IllegalThreadStateException();
+    ctor public IllegalThreadStateException(java.lang.String);
+  }
+
+  public class IncompatibleClassChangeError extends java.lang.LinkageError {
+    ctor public IncompatibleClassChangeError();
+    ctor public IncompatibleClassChangeError(java.lang.String);
+  }
+
+  public class IndexOutOfBoundsException extends java.lang.RuntimeException {
+    ctor public IndexOutOfBoundsException();
+    ctor public IndexOutOfBoundsException(java.lang.String);
+  }
+
+  public class InheritableThreadLocal extends java.lang.ThreadLocal {
+    ctor public InheritableThreadLocal();
+    method protected T childValue(T);
+  }
+
+  public class InstantiationError extends java.lang.IncompatibleClassChangeError {
+    ctor public InstantiationError();
+    ctor public InstantiationError(java.lang.String);
+  }
+
+  public class InstantiationException extends java.lang.Exception {
+    ctor public InstantiationException();
+    ctor public InstantiationException(java.lang.String);
+  }
+
+  public final class Integer extends java.lang.Number implements java.lang.Comparable {
+    ctor public Integer(int);
+    ctor public Integer(java.lang.String) throws java.lang.NumberFormatException;
+    method public static int bitCount(int);
+    method public int compareTo(java.lang.Integer);
+    method public static java.lang.Integer decode(java.lang.String) throws java.lang.NumberFormatException;
+    method public double doubleValue();
+    method public float floatValue();
+    method public static java.lang.Integer getInteger(java.lang.String);
+    method public static java.lang.Integer getInteger(java.lang.String, int);
+    method public static java.lang.Integer getInteger(java.lang.String, java.lang.Integer);
+    method public static int highestOneBit(int);
+    method public int intValue();
+    method public long longValue();
+    method public static int lowestOneBit(int);
+    method public static int numberOfLeadingZeros(int);
+    method public static int numberOfTrailingZeros(int);
+    method public static int parseInt(java.lang.String) throws java.lang.NumberFormatException;
+    method public static int parseInt(java.lang.String, int) throws java.lang.NumberFormatException;
+    method public static int reverse(int);
+    method public static int reverseBytes(int);
+    method public static int rotateLeft(int, int);
+    method public static int rotateRight(int, int);
+    method public static int signum(int);
+    method public static java.lang.String toBinaryString(int);
+    method public static java.lang.String toHexString(int);
+    method public static java.lang.String toOctalString(int);
+    method public static java.lang.String toString(int);
+    method public static java.lang.String toString(int, int);
+    method public static java.lang.Integer valueOf(java.lang.String) throws java.lang.NumberFormatException;
+    method public static java.lang.Integer valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
+    method public static java.lang.Integer valueOf(int);
+    field public static final int MAX_VALUE = 2147483647; // 0x7fffffff
+    field public static final int MIN_VALUE = -2147483648; // 0x80000000
+    field public static final int SIZE = 32; // 0x20
+    field public static final java.lang.Class TYPE;
+  }
+
+  public class InternalError extends java.lang.VirtualMachineError {
+    ctor public InternalError();
+    ctor public InternalError(java.lang.String);
+  }
+
+  public class InterruptedException extends java.lang.Exception {
+    ctor public InterruptedException();
+    ctor public InterruptedException(java.lang.String);
+  }
+
+  public abstract interface Iterable {
+    method public abstract java.util.Iterator<T> iterator();
+  }
+
+  public class LinkageError extends java.lang.Error {
+    ctor public LinkageError();
+    ctor public LinkageError(java.lang.String);
+  }
+
+  public final class Long extends java.lang.Number implements java.lang.Comparable {
+    ctor public Long(long);
+    ctor public Long(java.lang.String) throws java.lang.NumberFormatException;
+    method public static int bitCount(long);
+    method public int compareTo(java.lang.Long);
+    method public static java.lang.Long decode(java.lang.String) throws java.lang.NumberFormatException;
+    method public double doubleValue();
+    method public float floatValue();
+    method public static java.lang.Long getLong(java.lang.String);
+    method public static java.lang.Long getLong(java.lang.String, long);
+    method public static java.lang.Long getLong(java.lang.String, java.lang.Long);
+    method public static long highestOneBit(long);
+    method public int intValue();
+    method public long longValue();
+    method public static long lowestOneBit(long);
+    method public static int numberOfLeadingZeros(long);
+    method public static int numberOfTrailingZeros(long);
+    method public static long parseLong(java.lang.String) throws java.lang.NumberFormatException;
+    method public static long parseLong(java.lang.String, int) throws java.lang.NumberFormatException;
+    method public static long reverse(long);
+    method public static long reverseBytes(long);
+    method public static long rotateLeft(long, int);
+    method public static long rotateRight(long, int);
+    method public static int signum(long);
+    method public static java.lang.String toBinaryString(long);
+    method public static java.lang.String toHexString(long);
+    method public static java.lang.String toOctalString(long);
+    method public static java.lang.String toString(long);
+    method public static java.lang.String toString(long, int);
+    method public static java.lang.Long valueOf(java.lang.String) throws java.lang.NumberFormatException;
+    method public static java.lang.Long valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
+    method public static java.lang.Long valueOf(long);
+    field public static final long MAX_VALUE = 9223372036854775807L; // 0x7fffffffffffffffL
+    field public static final long MIN_VALUE = -9223372036854775808L; // 0x8000000000000000L
+    field public static final int SIZE = 64; // 0x40
+    field public static final java.lang.Class TYPE;
+  }
+
+  public final class Math {
+    method public static double IEEEremainder(double, double);
+    method public static double abs(double);
+    method public static float abs(float);
+    method public static int abs(int);
+    method public static long abs(long);
+    method public static double acos(double);
+    method public static double asin(double);
+    method public static double atan(double);
+    method public static double atan2(double, double);
+    method public static double cbrt(double);
+    method public static double ceil(double);
+    method public static double copySign(double, double);
+    method public static float copySign(float, float);
+    method public static double cos(double);
+    method public static double cosh(double);
+    method public static double exp(double);
+    method public static double expm1(double);
+    method public static double floor(double);
+    method public static int getExponent(float);
+    method public static int getExponent(double);
+    method public static double hypot(double, double);
+    method public static double log(double);
+    method public static double log10(double);
+    method public static double log1p(double);
+    method public static double max(double, double);
+    method public static float max(float, float);
+    method public static int max(int, int);
+    method public static long max(long, long);
+    method public static double min(double, double);
+    method public static float min(float, float);
+    method public static int min(int, int);
+    method public static long min(long, long);
+    method public static double nextAfter(double, double);
+    method public static float nextAfter(float, double);
+    method public static double nextUp(double);
+    method public static float nextUp(float);
+    method public static double pow(double, double);
+    method public static synchronized double random();
+    method public static double rint(double);
+    method public static long round(double);
+    method public static int round(float);
+    method public static double scalb(double, int);
+    method public static float scalb(float, int);
+    method public static double signum(double);
+    method public static float signum(float);
+    method public static double sin(double);
+    method public static double sinh(double);
+    method public static double sqrt(double);
+    method public static double tan(double);
+    method public static double tanh(double);
+    method public static double toDegrees(double);
+    method public static double toRadians(double);
+    method public static double ulp(double);
+    method public static float ulp(float);
+    field public static final double E = 2.718281828459045;
+    field public static final double PI = 3.141592653589793;
+  }
+
+  public class NegativeArraySizeException extends java.lang.RuntimeException {
+    ctor public NegativeArraySizeException();
+    ctor public NegativeArraySizeException(java.lang.String);
+  }
+
+  public class NoClassDefFoundError extends java.lang.LinkageError {
+    ctor public NoClassDefFoundError();
+    ctor public NoClassDefFoundError(java.lang.String);
+  }
+
+  public class NoSuchFieldError extends java.lang.IncompatibleClassChangeError {
+    ctor public NoSuchFieldError();
+    ctor public NoSuchFieldError(java.lang.String);
+  }
+
+  public class NoSuchFieldException extends java.lang.Exception {
+    ctor public NoSuchFieldException();
+    ctor public NoSuchFieldException(java.lang.String);
+  }
+
+  public class NoSuchMethodError extends java.lang.IncompatibleClassChangeError {
+    ctor public NoSuchMethodError();
+    ctor public NoSuchMethodError(java.lang.String);
+  }
+
+  public class NoSuchMethodException extends java.lang.Exception {
+    ctor public NoSuchMethodException();
+    ctor public NoSuchMethodException(java.lang.String);
+  }
+
+  public class NullPointerException extends java.lang.RuntimeException {
+    ctor public NullPointerException();
+    ctor public NullPointerException(java.lang.String);
+  }
+
+  public abstract class Number implements java.io.Serializable {
+    ctor public Number();
+    method public byte byteValue();
+    method public abstract double doubleValue();
+    method public abstract float floatValue();
+    method public abstract int intValue();
+    method public abstract long longValue();
+    method public short shortValue();
+  }
+
+  public class NumberFormatException extends java.lang.IllegalArgumentException {
+    ctor public NumberFormatException();
+    ctor public NumberFormatException(java.lang.String);
+  }
+
+  public class Object {
+    ctor public Object();
+    method protected java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public boolean equals(java.lang.Object);
+    method protected void finalize() throws java.lang.Throwable;
+    method public final java.lang.Class<?> getClass();
+    method public int hashCode();
+    method public final void notify();
+    method public final void notifyAll();
+    method public java.lang.String toString();
+    method public final void wait() throws java.lang.InterruptedException;
+    method public final void wait(long) throws java.lang.InterruptedException;
+    method public final void wait(long, int) throws java.lang.InterruptedException;
+  }
+
+  public class OutOfMemoryError extends java.lang.VirtualMachineError {
+    ctor public OutOfMemoryError();
+    ctor public OutOfMemoryError(java.lang.String);
+  }
+
+  public abstract class Override implements java.lang.annotation.Annotation {
+  }
+
+  public class Package implements java.lang.reflect.AnnotatedElement {
+    method public A getAnnotation(java.lang.Class<A>);
+    method public java.lang.annotation.Annotation[] getAnnotations();
+    method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public java.lang.String getImplementationTitle();
+    method public java.lang.String getImplementationVendor();
+    method public java.lang.String getImplementationVersion();
+    method public java.lang.String getName();
+    method public static java.lang.Package getPackage(java.lang.String);
+    method public static java.lang.Package[] getPackages();
+    method public java.lang.String getSpecificationTitle();
+    method public java.lang.String getSpecificationVendor();
+    method public java.lang.String getSpecificationVersion();
+    method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
+    method public boolean isCompatibleWith(java.lang.String) throws java.lang.NumberFormatException;
+    method public boolean isSealed();
+    method public boolean isSealed(java.net.URL);
+  }
+
+  public abstract class Process {
+    ctor public Process();
+    method public abstract void destroy();
+    method public abstract int exitValue();
+    method public abstract java.io.InputStream getErrorStream();
+    method public abstract java.io.InputStream getInputStream();
+    method public abstract java.io.OutputStream getOutputStream();
+    method public abstract int waitFor() throws java.lang.InterruptedException;
+  }
+
+  public final class ProcessBuilder {
+    ctor public ProcessBuilder(java.lang.String...);
+    ctor public ProcessBuilder(java.util.List<java.lang.String>);
+    method public java.util.List<java.lang.String> command();
+    method public java.lang.ProcessBuilder command(java.lang.String...);
+    method public java.lang.ProcessBuilder command(java.util.List<java.lang.String>);
+    method public java.io.File directory();
+    method public java.lang.ProcessBuilder directory(java.io.File);
+    method public java.util.Map<java.lang.String, java.lang.String> environment();
+    method public boolean redirectErrorStream();
+    method public java.lang.ProcessBuilder redirectErrorStream(boolean);
+    method public java.lang.Process start() throws java.io.IOException;
+  }
+
+  public abstract interface Readable {
+    method public abstract int read(java.nio.CharBuffer) throws java.io.IOException;
+  }
+
+  public abstract interface Runnable {
+    method public abstract void run();
+  }
+
+  public class Runtime {
+    method public void addShutdownHook(java.lang.Thread);
+    method public int availableProcessors();
+    method public java.lang.Process exec(java.lang.String[]) throws java.io.IOException;
+    method public java.lang.Process exec(java.lang.String[], java.lang.String[]) throws java.io.IOException;
+    method public java.lang.Process exec(java.lang.String[], java.lang.String[], java.io.File) throws java.io.IOException;
+    method public java.lang.Process exec(java.lang.String) throws java.io.IOException;
+    method public java.lang.Process exec(java.lang.String, java.lang.String[]) throws java.io.IOException;
+    method public java.lang.Process exec(java.lang.String, java.lang.String[], java.io.File) throws java.io.IOException;
+    method public void exit(int);
+    method public long freeMemory();
+    method public void gc();
+    method public deprecated java.io.InputStream getLocalizedInputStream(java.io.InputStream);
+    method public deprecated java.io.OutputStream getLocalizedOutputStream(java.io.OutputStream);
+    method public static java.lang.Runtime getRuntime();
+    method public void halt(int);
+    method public void load(java.lang.String);
+    method public void loadLibrary(java.lang.String);
+    method public long maxMemory();
+    method public boolean removeShutdownHook(java.lang.Thread);
+    method public void runFinalization();
+    method public static deprecated void runFinalizersOnExit(boolean);
+    method public long totalMemory();
+    method public void traceInstructions(boolean);
+    method public void traceMethodCalls(boolean);
+  }
+
+  public class RuntimeException extends java.lang.Exception {
+    ctor public RuntimeException();
+    ctor public RuntimeException(java.lang.String);
+    ctor public RuntimeException(java.lang.String, java.lang.Throwable);
+    ctor public RuntimeException(java.lang.Throwable);
+  }
+
+  public final class RuntimePermission extends java.security.BasicPermission {
+    ctor public RuntimePermission(java.lang.String);
+    ctor public RuntimePermission(java.lang.String, java.lang.String);
+  }
+
+  public class SecurityException extends java.lang.RuntimeException {
+    ctor public SecurityException();
+    ctor public SecurityException(java.lang.String);
+    ctor public SecurityException(java.lang.String, java.lang.Throwable);
+    ctor public SecurityException(java.lang.Throwable);
+  }
+
+  public class SecurityManager {
+    ctor public SecurityManager();
+    method public void checkAccept(java.lang.String, int);
+    method public void checkAccess(java.lang.Thread);
+    method public void checkAccess(java.lang.ThreadGroup);
+    method public void checkAwtEventQueueAccess();
+    method public void checkConnect(java.lang.String, int);
+    method public void checkConnect(java.lang.String, int, java.lang.Object);
+    method public void checkCreateClassLoader();
+    method public void checkDelete(java.lang.String);
+    method public void checkExec(java.lang.String);
+    method public void checkExit(int);
+    method public void checkLink(java.lang.String);
+    method public void checkListen(int);
+    method public void checkMemberAccess(java.lang.Class<?>, int);
+    method public void checkMulticast(java.net.InetAddress);
+    method public deprecated void checkMulticast(java.net.InetAddress, byte);
+    method public void checkPackageAccess(java.lang.String);
+    method public void checkPackageDefinition(java.lang.String);
+    method public void checkPermission(java.security.Permission);
+    method public void checkPermission(java.security.Permission, java.lang.Object);
+    method public void checkPrintJobAccess();
+    method public void checkPropertiesAccess();
+    method public void checkPropertyAccess(java.lang.String);
+    method public void checkRead(java.io.FileDescriptor);
+    method public void checkRead(java.lang.String);
+    method public void checkRead(java.lang.String, java.lang.Object);
+    method public void checkSecurityAccess(java.lang.String);
+    method public void checkSetFactory();
+    method public void checkSystemClipboardAccess();
+    method public boolean checkTopLevelWindow(java.lang.Object);
+    method public void checkWrite(java.io.FileDescriptor);
+    method public void checkWrite(java.lang.String);
+    method protected deprecated int classDepth(java.lang.String);
+    method protected deprecated int classLoaderDepth();
+    method protected deprecated java.lang.ClassLoader currentClassLoader();
+    method protected deprecated java.lang.Class<?> currentLoadedClass();
+    method protected java.lang.Class[] getClassContext();
+    method public deprecated boolean getInCheck();
+    method public java.lang.Object getSecurityContext();
+    method public java.lang.ThreadGroup getThreadGroup();
+    method protected deprecated boolean inClass(java.lang.String);
+    method protected deprecated boolean inClassLoader();
+    field protected deprecated boolean inCheck;
+  }
+
+  public final class Short extends java.lang.Number implements java.lang.Comparable {
+    ctor public Short(java.lang.String) throws java.lang.NumberFormatException;
+    ctor public Short(short);
+    method public int compareTo(java.lang.Short);
+    method public static java.lang.Short decode(java.lang.String) throws java.lang.NumberFormatException;
+    method public double doubleValue();
+    method public float floatValue();
+    method public int intValue();
+    method public long longValue();
+    method public static short parseShort(java.lang.String) throws java.lang.NumberFormatException;
+    method public static short parseShort(java.lang.String, int) throws java.lang.NumberFormatException;
+    method public static short reverseBytes(short);
+    method public static java.lang.String toString(short);
+    method public static java.lang.Short valueOf(java.lang.String) throws java.lang.NumberFormatException;
+    method public static java.lang.Short valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
+    method public static java.lang.Short valueOf(short);
+    field public static final short MAX_VALUE = 32767; // 0x7fff
+    field public static final short MIN_VALUE = -32768; // 0xffff8000
+    field public static final int SIZE = 16; // 0x10
+    field public static final java.lang.Class TYPE;
+  }
+
+  public class StackOverflowError extends java.lang.VirtualMachineError {
+    ctor public StackOverflowError();
+    ctor public StackOverflowError(java.lang.String);
+  }
+
+  public final class StackTraceElement implements java.io.Serializable {
+    ctor public StackTraceElement(java.lang.String, java.lang.String, java.lang.String, int);
+    method public java.lang.String getClassName();
+    method public java.lang.String getFileName();
+    method public int getLineNumber();
+    method public java.lang.String getMethodName();
+    method public boolean isNativeMethod();
+  }
+
+  public final class StrictMath {
+    method public static double IEEEremainder(double, double);
+    method public static double abs(double);
+    method public static float abs(float);
+    method public static int abs(int);
+    method public static long abs(long);
+    method public static double acos(double);
+    method public static double asin(double);
+    method public static double atan(double);
+    method public static double atan2(double, double);
+    method public static double cbrt(double);
+    method public static double ceil(double);
+    method public static double copySign(double, double);
+    method public static float copySign(float, float);
+    method public static double cos(double);
+    method public static double cosh(double);
+    method public static double exp(double);
+    method public static double expm1(double);
+    method public static double floor(double);
+    method public static int getExponent(float);
+    method public static int getExponent(double);
+    method public static double hypot(double, double);
+    method public static double log(double);
+    method public static double log10(double);
+    method public static double log1p(double);
+    method public static double max(double, double);
+    method public static float max(float, float);
+    method public static int max(int, int);
+    method public static long max(long, long);
+    method public static double min(double, double);
+    method public static float min(float, float);
+    method public static int min(int, int);
+    method public static long min(long, long);
+    method public static double nextAfter(double, double);
+    method public static float nextAfter(float, double);
+    method public static double nextUp(double);
+    method public static float nextUp(float);
+    method public static double pow(double, double);
+    method public static double random();
+    method public static double rint(double);
+    method public static long round(double);
+    method public static int round(float);
+    method public static double scalb(double, int);
+    method public static float scalb(float, int);
+    method public static double signum(double);
+    method public static float signum(float);
+    method public static double sin(double);
+    method public static double sinh(double);
+    method public static double sqrt(double);
+    method public static double tan(double);
+    method public static double tanh(double);
+    method public static double toDegrees(double);
+    method public static double toRadians(double);
+    method public static double ulp(double);
+    method public static float ulp(float);
+    field public static final double E = 2.718281828459045;
+    field public static final double PI = 3.141592653589793;
+  }
+
+  public final class String implements java.lang.CharSequence java.lang.Comparable java.io.Serializable {
+    ctor public String();
+    ctor public String(byte[]);
+    ctor public deprecated String(byte[], int);
+    ctor public String(byte[], int, int);
+    ctor public deprecated String(byte[], int, int, int);
+    ctor public String(byte[], int, int, java.lang.String) throws java.io.UnsupportedEncodingException;
+    ctor public String(byte[], java.lang.String) throws java.io.UnsupportedEncodingException;
+    ctor public String(byte[], int, int, java.nio.charset.Charset);
+    ctor public String(byte[], java.nio.charset.Charset);
+    ctor public String(char[]);
+    ctor public String(char[], int, int);
+    ctor public String(java.lang.String);
+    ctor public String(java.lang.StringBuffer);
+    ctor public String(int[], int, int);
+    ctor public String(java.lang.StringBuilder);
+    method public char charAt(int);
+    method public int codePointAt(int);
+    method public int codePointBefore(int);
+    method public int codePointCount(int, int);
+    method public int compareTo(java.lang.String);
+    method public int compareToIgnoreCase(java.lang.String);
+    method public java.lang.String concat(java.lang.String);
+    method public boolean contains(java.lang.CharSequence);
+    method public boolean contentEquals(java.lang.StringBuffer);
+    method public boolean contentEquals(java.lang.CharSequence);
+    method public static java.lang.String copyValueOf(char[]);
+    method public static java.lang.String copyValueOf(char[], int, int);
+    method public boolean endsWith(java.lang.String);
+    method public boolean equalsIgnoreCase(java.lang.String);
+    method public static java.lang.String format(java.lang.String, java.lang.Object...);
+    method public static java.lang.String format(java.util.Locale, java.lang.String, java.lang.Object...);
+    method public deprecated void getBytes(int, int, byte[], int);
+    method public byte[] getBytes();
+    method public byte[] getBytes(java.lang.String) throws java.io.UnsupportedEncodingException;
+    method public byte[] getBytes(java.nio.charset.Charset);
+    method public void getChars(int, int, char[], int);
+    method public int indexOf(int);
+    method public int indexOf(int, int);
+    method public int indexOf(java.lang.String);
+    method public int indexOf(java.lang.String, int);
+    method public java.lang.String intern();
+    method public boolean isEmpty();
+    method public int lastIndexOf(int);
+    method public int lastIndexOf(int, int);
+    method public int lastIndexOf(java.lang.String);
+    method public int lastIndexOf(java.lang.String, int);
+    method public int length();
+    method public boolean matches(java.lang.String);
+    method public int offsetByCodePoints(int, int);
+    method public boolean regionMatches(int, java.lang.String, int, int);
+    method public boolean regionMatches(boolean, int, java.lang.String, int, int);
+    method public java.lang.String replace(char, char);
+    method public java.lang.String replace(java.lang.CharSequence, java.lang.CharSequence);
+    method public java.lang.String replaceAll(java.lang.String, java.lang.String);
+    method public java.lang.String replaceFirst(java.lang.String, java.lang.String);
+    method public java.lang.String[] split(java.lang.String);
+    method public java.lang.String[] split(java.lang.String, int);
+    method public boolean startsWith(java.lang.String);
+    method public boolean startsWith(java.lang.String, int);
+    method public java.lang.CharSequence subSequence(int, int);
+    method public java.lang.String substring(int);
+    method public java.lang.String substring(int, int);
+    method public char[] toCharArray();
+    method public java.lang.String toLowerCase();
+    method public java.lang.String toLowerCase(java.util.Locale);
+    method public java.lang.String toUpperCase();
+    method public java.lang.String toUpperCase(java.util.Locale);
+    method public java.lang.String trim();
+    method public static java.lang.String valueOf(char[]);
+    method public static java.lang.String valueOf(char[], int, int);
+    method public static java.lang.String valueOf(char);
+    method public static java.lang.String valueOf(double);
+    method public static java.lang.String valueOf(float);
+    method public static java.lang.String valueOf(int);
+    method public static java.lang.String valueOf(long);
+    method public static java.lang.String valueOf(java.lang.Object);
+    method public static java.lang.String valueOf(boolean);
+    field public static final java.util.Comparator CASE_INSENSITIVE_ORDER;
+  }
+
+  public final class StringBuffer extends java.lang.AbstractStringBuilder implements java.lang.Appendable java.lang.CharSequence java.io.Serializable {
+    ctor public StringBuffer();
+    ctor public StringBuffer(int);
+    ctor public StringBuffer(java.lang.String);
+    ctor public StringBuffer(java.lang.CharSequence);
+    method public java.lang.StringBuffer append(boolean);
+    method public synchronized java.lang.StringBuffer append(char);
+    method public java.lang.StringBuffer append(double);
+    method public java.lang.StringBuffer append(float);
+    method public java.lang.StringBuffer append(int);
+    method public java.lang.StringBuffer append(long);
+    method public synchronized java.lang.StringBuffer append(java.lang.Object);
+    method public synchronized java.lang.StringBuffer append(java.lang.String);
+    method public synchronized java.lang.StringBuffer append(java.lang.StringBuffer);
+    method public synchronized java.lang.StringBuffer append(char[]);
+    method public synchronized java.lang.StringBuffer append(char[], int, int);
+    method public synchronized java.lang.StringBuffer append(java.lang.CharSequence);
+    method public synchronized java.lang.StringBuffer append(java.lang.CharSequence, int, int);
+    method public java.lang.StringBuffer appendCodePoint(int);
+    method public synchronized java.lang.StringBuffer delete(int, int);
+    method public synchronized java.lang.StringBuffer deleteCharAt(int);
+    method public synchronized java.lang.StringBuffer insert(int, char);
+    method public java.lang.StringBuffer insert(int, boolean);
+    method public java.lang.StringBuffer insert(int, int);
+    method public java.lang.StringBuffer insert(int, long);
+    method public java.lang.StringBuffer insert(int, double);
+    method public java.lang.StringBuffer insert(int, float);
+    method public java.lang.StringBuffer insert(int, java.lang.Object);
+    method public synchronized java.lang.StringBuffer insert(int, java.lang.String);
+    method public synchronized java.lang.StringBuffer insert(int, char[]);
+    method public synchronized java.lang.StringBuffer insert(int, char[], int, int);
+    method public synchronized java.lang.StringBuffer insert(int, java.lang.CharSequence);
+    method public synchronized java.lang.StringBuffer insert(int, java.lang.CharSequence, int, int);
+    method public synchronized java.lang.StringBuffer replace(int, int, java.lang.String);
+    method public synchronized java.lang.StringBuffer reverse();
+  }
+
+  public final class StringBuilder extends java.lang.AbstractStringBuilder implements java.lang.Appendable java.lang.CharSequence java.io.Serializable {
+    ctor public StringBuilder();
+    ctor public StringBuilder(int);
+    ctor public StringBuilder(java.lang.CharSequence);
+    ctor public StringBuilder(java.lang.String);
+    method public java.lang.StringBuilder append(boolean);
+    method public java.lang.StringBuilder append(char);
+    method public java.lang.StringBuilder append(int);
+    method public java.lang.StringBuilder append(long);
+    method public java.lang.StringBuilder append(float);
+    method public java.lang.StringBuilder append(double);
+    method public java.lang.StringBuilder append(java.lang.Object);
+    method public java.lang.StringBuilder append(java.lang.String);
+    method public java.lang.StringBuilder append(java.lang.StringBuffer);
+    method public java.lang.StringBuilder append(char[]);
+    method public java.lang.StringBuilder append(char[], int, int);
+    method public java.lang.StringBuilder append(java.lang.CharSequence);
+    method public java.lang.StringBuilder append(java.lang.CharSequence, int, int);
+    method public java.lang.StringBuilder appendCodePoint(int);
+    method public java.lang.StringBuilder delete(int, int);
+    method public java.lang.StringBuilder deleteCharAt(int);
+    method public java.lang.StringBuilder insert(int, boolean);
+    method public java.lang.StringBuilder insert(int, char);
+    method public java.lang.StringBuilder insert(int, int);
+    method public java.lang.StringBuilder insert(int, long);
+    method public java.lang.StringBuilder insert(int, float);
+    method public java.lang.StringBuilder insert(int, double);
+    method public java.lang.StringBuilder insert(int, java.lang.Object);
+    method public java.lang.StringBuilder insert(int, java.lang.String);
+    method public java.lang.StringBuilder insert(int, char[]);
+    method public java.lang.StringBuilder insert(int, char[], int, int);
+    method public java.lang.StringBuilder insert(int, java.lang.CharSequence);
+    method public java.lang.StringBuilder insert(int, java.lang.CharSequence, int, int);
+    method public java.lang.StringBuilder replace(int, int, java.lang.String);
+    method public java.lang.StringBuilder reverse();
+  }
+
+  public class StringIndexOutOfBoundsException extends java.lang.IndexOutOfBoundsException {
+    ctor public StringIndexOutOfBoundsException();
+    ctor public StringIndexOutOfBoundsException(int);
+    ctor public StringIndexOutOfBoundsException(java.lang.String);
+  }
+
+  public abstract class SuppressWarnings implements java.lang.annotation.Annotation {
+  }
+
+  public final class System {
+    method public static void arraycopy(java.lang.Object, int, java.lang.Object, int, int);
+    method public static java.lang.String clearProperty(java.lang.String);
+    method public static java.io.Console console();
+    method public static long currentTimeMillis();
+    method public static void exit(int);
+    method public static void gc();
+    method public static java.util.Properties getProperties();
+    method public static java.lang.String getProperty(java.lang.String);
+    method public static java.lang.String getProperty(java.lang.String, java.lang.String);
+    method public static java.lang.SecurityManager getSecurityManager();
+    method public static java.lang.String getenv(java.lang.String);
+    method public static java.util.Map<java.lang.String, java.lang.String> getenv();
+    method public static int identityHashCode(java.lang.Object);
+    method public static java.nio.channels.Channel inheritedChannel() throws java.io.IOException;
+    method public static void load(java.lang.String);
+    method public static void loadLibrary(java.lang.String);
+    method public static java.lang.String mapLibraryName(java.lang.String);
+    method public static long nanoTime();
+    method public static void runFinalization();
+    method public static deprecated void runFinalizersOnExit(boolean);
+    method public static void setErr(java.io.PrintStream);
+    method public static void setIn(java.io.InputStream);
+    method public static void setOut(java.io.PrintStream);
+    method public static void setProperties(java.util.Properties);
+    method public static java.lang.String setProperty(java.lang.String, java.lang.String);
+    method public static void setSecurityManager(java.lang.SecurityManager);
+    field public static final java.io.PrintStream err;
+    field public static final java.io.InputStream in;
+    field public static final java.io.PrintStream out;
+  }
+
+  public class Thread implements java.lang.Runnable {
+    ctor public Thread();
+    ctor public Thread(java.lang.Runnable);
+    ctor public Thread(java.lang.Runnable, java.lang.String);
+    ctor public Thread(java.lang.String);
+    ctor public Thread(java.lang.ThreadGroup, java.lang.Runnable);
+    ctor public Thread(java.lang.ThreadGroup, java.lang.Runnable, java.lang.String);
+    ctor public Thread(java.lang.ThreadGroup, java.lang.String);
+    ctor public Thread(java.lang.ThreadGroup, java.lang.Runnable, java.lang.String, long);
+    method public static int activeCount();
+    method public final void checkAccess();
+    method public deprecated int countStackFrames();
+    method public static java.lang.Thread currentThread();
+    method public deprecated void destroy();
+    method public static void dumpStack();
+    method public static int enumerate(java.lang.Thread[]);
+    method public static java.util.Map<java.lang.Thread, java.lang.StackTraceElement[]> getAllStackTraces();
+    method public java.lang.ClassLoader getContextClassLoader();
+    method public static java.lang.Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler();
+    method public long getId();
+    method public final java.lang.String getName();
+    method public final int getPriority();
+    method public java.lang.StackTraceElement[] getStackTrace();
+    method public java.lang.Thread.State getState();
+    method public final java.lang.ThreadGroup getThreadGroup();
+    method public java.lang.Thread.UncaughtExceptionHandler getUncaughtExceptionHandler();
+    method public static boolean holdsLock(java.lang.Object);
+    method public void interrupt();
+    method public static boolean interrupted();
+    method public final boolean isAlive();
+    method public final boolean isDaemon();
+    method public boolean isInterrupted();
+    method public final void join() throws java.lang.InterruptedException;
+    method public final void join(long) throws java.lang.InterruptedException;
+    method public final void join(long, int) throws java.lang.InterruptedException;
+    method public final deprecated void resume();
+    method public void run();
+    method public void setContextClassLoader(java.lang.ClassLoader);
+    method public final void setDaemon(boolean);
+    method public static void setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler);
+    method public final void setName(java.lang.String);
+    method public final void setPriority(int);
+    method public void setUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler);
+    method public static void sleep(long) throws java.lang.InterruptedException;
+    method public static void sleep(long, int) throws java.lang.InterruptedException;
+    method public synchronized void start();
+    method public final deprecated void stop();
+    method public final deprecated synchronized void stop(java.lang.Throwable);
+    method public final deprecated void suspend();
+    method public static void yield();
+    field public static final int MAX_PRIORITY = 10; // 0xa
+    field public static final int MIN_PRIORITY = 1; // 0x1
+    field public static final int NORM_PRIORITY = 5; // 0x5
+  }
+
+  public static final class Thread.State extends java.lang.Enum {
+    method public static java.lang.Thread.State valueOf(java.lang.String);
+    method public static final java.lang.Thread.State[] values();
+    enum_constant public static final java.lang.Thread.State BLOCKED;
+    enum_constant public static final java.lang.Thread.State NEW;
+    enum_constant public static final java.lang.Thread.State RUNNABLE;
+    enum_constant public static final java.lang.Thread.State TERMINATED;
+    enum_constant public static final java.lang.Thread.State TIMED_WAITING;
+    enum_constant public static final java.lang.Thread.State WAITING;
+  }
+
+  public static abstract interface Thread.UncaughtExceptionHandler {
+    method public abstract void uncaughtException(java.lang.Thread, java.lang.Throwable);
+  }
+
+  public class ThreadDeath extends java.lang.Error {
+    ctor public ThreadDeath();
+  }
+
+  public class ThreadGroup implements java.lang.Thread.UncaughtExceptionHandler {
+    ctor public ThreadGroup(java.lang.String);
+    ctor public ThreadGroup(java.lang.ThreadGroup, java.lang.String);
+    method public int activeCount();
+    method public int activeGroupCount();
+    method public deprecated boolean allowThreadSuspension(boolean);
+    method public final void checkAccess();
+    method public final void destroy();
+    method public int enumerate(java.lang.Thread[]);
+    method public int enumerate(java.lang.Thread[], boolean);
+    method public int enumerate(java.lang.ThreadGroup[]);
+    method public int enumerate(java.lang.ThreadGroup[], boolean);
+    method public final int getMaxPriority();
+    method public final java.lang.String getName();
+    method public final java.lang.ThreadGroup getParent();
+    method public final void interrupt();
+    method public final boolean isDaemon();
+    method public synchronized boolean isDestroyed();
+    method public void list();
+    method public final boolean parentOf(java.lang.ThreadGroup);
+    method public final deprecated void resume();
+    method public final void setDaemon(boolean);
+    method public final void setMaxPriority(int);
+    method public final deprecated void stop();
+    method public final deprecated void suspend();
+    method public void uncaughtException(java.lang.Thread, java.lang.Throwable);
+  }
+
+  public class ThreadLocal {
+    ctor public ThreadLocal();
+    method public T get();
+    method protected T initialValue();
+    method public void remove();
+    method public void set(T);
+  }
+
+  public class Throwable implements java.io.Serializable {
+    ctor public Throwable();
+    ctor public Throwable(java.lang.String);
+    ctor public Throwable(java.lang.String, java.lang.Throwable);
+    ctor public Throwable(java.lang.Throwable);
+    method public java.lang.Throwable fillInStackTrace();
+    method public java.lang.Throwable getCause();
+    method public java.lang.String getLocalizedMessage();
+    method public java.lang.String getMessage();
+    method public java.lang.StackTraceElement[] getStackTrace();
+    method public java.lang.Throwable initCause(java.lang.Throwable);
+    method public void printStackTrace();
+    method public void printStackTrace(java.io.PrintStream);
+    method public void printStackTrace(java.io.PrintWriter);
+    method public void setStackTrace(java.lang.StackTraceElement[]);
+  }
+
+  public class TypeNotPresentException extends java.lang.RuntimeException {
+    ctor public TypeNotPresentException(java.lang.String, java.lang.Throwable);
+    method public java.lang.String typeName();
+  }
+
+  public class UnknownError extends java.lang.VirtualMachineError {
+    ctor public UnknownError();
+    ctor public UnknownError(java.lang.String);
+  }
+
+  public class UnsatisfiedLinkError extends java.lang.LinkageError {
+    ctor public UnsatisfiedLinkError();
+    ctor public UnsatisfiedLinkError(java.lang.String);
+  }
+
+  public class UnsupportedClassVersionError extends java.lang.ClassFormatError {
+    ctor public UnsupportedClassVersionError();
+    ctor public UnsupportedClassVersionError(java.lang.String);
+  }
+
+  public class UnsupportedOperationException extends java.lang.RuntimeException {
+    ctor public UnsupportedOperationException();
+    ctor public UnsupportedOperationException(java.lang.String);
+    ctor public UnsupportedOperationException(java.lang.String, java.lang.Throwable);
+    ctor public UnsupportedOperationException(java.lang.Throwable);
+  }
+
+  public class VerifyError extends java.lang.LinkageError {
+    ctor public VerifyError();
+    ctor public VerifyError(java.lang.String);
+  }
+
+  public abstract class VirtualMachineError extends java.lang.Error {
+    ctor public VirtualMachineError();
+    ctor public VirtualMachineError(java.lang.String);
+  }
+
+  public final class Void {
+    field public static final java.lang.Class TYPE;
+  }
+
+}
+
+package java.lang.annotation {
+
+  public abstract interface Annotation {
+    method public abstract java.lang.Class<? extends java.lang.annotation.Annotation> annotationType();
+    method public abstract boolean equals(java.lang.Object);
+    method public abstract int hashCode();
+    method public abstract java.lang.String toString();
+  }
+
+  public class AnnotationFormatError extends java.lang.Error {
+    ctor public AnnotationFormatError(java.lang.String);
+    ctor public AnnotationFormatError(java.lang.String, java.lang.Throwable);
+    ctor public AnnotationFormatError(java.lang.Throwable);
+  }
+
+  public class AnnotationTypeMismatchException extends java.lang.RuntimeException {
+    ctor public AnnotationTypeMismatchException(java.lang.reflect.Method, java.lang.String);
+    method public java.lang.reflect.Method element();
+    method public java.lang.String foundType();
+  }
+
+  public abstract class Documented implements java.lang.annotation.Annotation {
+  }
+
+  public final class ElementType extends java.lang.Enum {
+    method public static java.lang.annotation.ElementType valueOf(java.lang.String);
+    method public static final java.lang.annotation.ElementType[] values();
+    enum_constant public static final java.lang.annotation.ElementType ANNOTATION_TYPE;
+    enum_constant public static final java.lang.annotation.ElementType CONSTRUCTOR;
+    enum_constant public static final java.lang.annotation.ElementType FIELD;
+    enum_constant public static final java.lang.annotation.ElementType LOCAL_VARIABLE;
+    enum_constant public static final java.lang.annotation.ElementType METHOD;
+    enum_constant public static final java.lang.annotation.ElementType PACKAGE;
+    enum_constant public static final java.lang.annotation.ElementType PARAMETER;
+    enum_constant public static final java.lang.annotation.ElementType TYPE;
+  }
+
+  public class IncompleteAnnotationException extends java.lang.RuntimeException {
+    ctor public IncompleteAnnotationException(java.lang.Class<? extends java.lang.annotation.Annotation>, java.lang.String);
+    method public java.lang.Class<? extends java.lang.annotation.Annotation> annotationType();
+    method public java.lang.String elementName();
+  }
+
+  public abstract class Inherited implements java.lang.annotation.Annotation {
+  }
+
+  public abstract class Retention implements java.lang.annotation.Annotation {
+  }
+
+  public final class RetentionPolicy extends java.lang.Enum {
+    method public static java.lang.annotation.RetentionPolicy valueOf(java.lang.String);
+    method public static final java.lang.annotation.RetentionPolicy[] values();
+    enum_constant public static final java.lang.annotation.RetentionPolicy CLASS;
+    enum_constant public static final java.lang.annotation.RetentionPolicy RUNTIME;
+    enum_constant public static final java.lang.annotation.RetentionPolicy SOURCE;
+  }
+
+  public abstract class Target implements java.lang.annotation.Annotation {
+  }
+
+}
+
+package java.lang.ref {
+
+  public class PhantomReference extends java.lang.ref.Reference {
+    ctor public PhantomReference(T, java.lang.ref.ReferenceQueue<? super T>);
+  }
+
+  public abstract class Reference {
+    method public void clear();
+    method public boolean enqueue();
+    method public T get();
+    method public boolean isEnqueued();
+  }
+
+  public class ReferenceQueue {
+    ctor public ReferenceQueue();
+    method public synchronized java.lang.ref.Reference<? extends T> poll();
+    method public java.lang.ref.Reference<? extends T> remove() throws java.lang.InterruptedException;
+    method public synchronized java.lang.ref.Reference<? extends T> remove(long) throws java.lang.InterruptedException;
+  }
+
+  public class SoftReference extends java.lang.ref.Reference {
+    ctor public SoftReference(T);
+    ctor public SoftReference(T, java.lang.ref.ReferenceQueue<? super T>);
+  }
+
+  public class WeakReference extends java.lang.ref.Reference {
+    ctor public WeakReference(T);
+    ctor public WeakReference(T, java.lang.ref.ReferenceQueue<? super T>);
+  }
+
+}
+
+package java.lang.reflect {
+
+  public class AccessibleObject implements java.lang.reflect.AnnotatedElement {
+    ctor protected AccessibleObject();
+    method public T getAnnotation(java.lang.Class<T>);
+    method public java.lang.annotation.Annotation[] getAnnotations();
+    method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public boolean isAccessible();
+    method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
+    method public static void setAccessible(java.lang.reflect.AccessibleObject[], boolean);
+    method public void setAccessible(boolean);
+  }
+
+  public abstract interface AnnotatedElement {
+    method public abstract T getAnnotation(java.lang.Class<T>);
+    method public abstract java.lang.annotation.Annotation[] getAnnotations();
+    method public abstract java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public abstract boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
+  }
+
+  public final class Array {
+    method public static java.lang.Object get(java.lang.Object, int) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+    method public static boolean getBoolean(java.lang.Object, int) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+    method public static byte getByte(java.lang.Object, int) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+    method public static char getChar(java.lang.Object, int) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+    method public static double getDouble(java.lang.Object, int) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+    method public static float getFloat(java.lang.Object, int) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+    method public static int getInt(java.lang.Object, int) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+    method public static int getLength(java.lang.Object);
+    method public static long getLong(java.lang.Object, int) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+    method public static short getShort(java.lang.Object, int) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+    method public static java.lang.Object newInstance(java.lang.Class<?>, int...) throws java.lang.IllegalArgumentException, java.lang.NegativeArraySizeException;
+    method public static java.lang.Object newInstance(java.lang.Class<?>, int) throws java.lang.NegativeArraySizeException;
+    method public static void set(java.lang.Object, int, java.lang.Object) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+    method public static void setBoolean(java.lang.Object, int, boolean);
+    method public static void setByte(java.lang.Object, int, byte) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+    method public static void setChar(java.lang.Object, int, char) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+    method public static void setDouble(java.lang.Object, int, double) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+    method public static void setFloat(java.lang.Object, int, float) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+    method public static void setInt(java.lang.Object, int, int) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+    method public static void setLong(java.lang.Object, int, long) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+    method public static void setShort(java.lang.Object, int, short) throws java.lang.ArrayIndexOutOfBoundsException, java.lang.IllegalArgumentException;
+  }
+
+  public final class Constructor extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
+    method public A getAnnotation(java.lang.Class<A>);
+    method public java.lang.Class<T> getDeclaringClass();
+    method public java.lang.Class<?>[] getExceptionTypes();
+    method public java.lang.reflect.Type[] getGenericExceptionTypes();
+    method public java.lang.reflect.Type[] getGenericParameterTypes();
+    method public int getModifiers();
+    method public java.lang.String getName();
+    method public java.lang.annotation.Annotation[][] getParameterAnnotations();
+    method public java.lang.Class<?>[] getParameterTypes();
+    method public java.lang.reflect.TypeVariable<java.lang.reflect.Constructor<T>>[] getTypeParameters();
+    method public boolean isSynthetic();
+    method public boolean isVarArgs();
+    method public T newInstance(java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException;
+    method public java.lang.String toGenericString();
+  }
+
+  public final class Field extends java.lang.reflect.AccessibleObject implements java.lang.reflect.Member {
+    method public java.lang.Object get(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public A getAnnotation(java.lang.Class<A>);
+    method public boolean getBoolean(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public byte getByte(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public char getChar(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public java.lang.Class<?> getDeclaringClass();
+    method public double getDouble(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public float getFloat(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public java.lang.reflect.Type getGenericType();
+    method public int getInt(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public long getLong(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public int getModifiers();
+    method public java.lang.String getName();
+    method public short getShort(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public java.lang.Class<?> getType();
+    method public boolean isEnumConstant();
+    method public boolean isSynthetic();
+    method public void set(java.lang.Object, java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public void setBoolean(java.lang.Object, boolean) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public void setByte(java.lang.Object, byte) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public void setChar(java.lang.Object, char) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public void setDouble(java.lang.Object, double) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public void setFloat(java.lang.Object, float) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public void setInt(java.lang.Object, int) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public void setLong(java.lang.Object, long) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public void setShort(java.lang.Object, short) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
+    method public java.lang.String toGenericString();
+  }
+
+  public abstract interface GenericArrayType implements java.lang.reflect.Type {
+    method public abstract java.lang.reflect.Type getGenericComponentType();
+  }
+
+  public abstract interface GenericDeclaration {
+    method public abstract java.lang.reflect.TypeVariable<?>[] getTypeParameters();
+  }
+
+  public class GenericSignatureFormatError extends java.lang.ClassFormatError {
+    ctor public GenericSignatureFormatError();
+  }
+
+  public abstract interface InvocationHandler {
+    method public abstract java.lang.Object invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) throws java.lang.Throwable;
+  }
+
+  public class InvocationTargetException extends java.lang.Exception {
+    ctor protected InvocationTargetException();
+    ctor public InvocationTargetException(java.lang.Throwable);
+    ctor public InvocationTargetException(java.lang.Throwable, java.lang.String);
+    method public java.lang.Throwable getTargetException();
+  }
+
+  public class MalformedParameterizedTypeException extends java.lang.RuntimeException {
+    ctor public MalformedParameterizedTypeException();
+  }
+
+  public abstract interface Member {
+    method public abstract java.lang.Class<?> getDeclaringClass();
+    method public abstract int getModifiers();
+    method public abstract java.lang.String getName();
+    method public abstract boolean isSynthetic();
+    field public static final int DECLARED = 1; // 0x1
+    field public static final int PUBLIC = 0; // 0x0
+  }
+
+  public final class Method extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
+    method public A getAnnotation(java.lang.Class<A>);
+    method public java.lang.Class<?> getDeclaringClass();
+    method public java.lang.Object getDefaultValue();
+    method public java.lang.Class<?>[] getExceptionTypes();
+    method public java.lang.reflect.Type[] getGenericExceptionTypes();
+    method public java.lang.reflect.Type[] getGenericParameterTypes();
+    method public java.lang.reflect.Type getGenericReturnType();
+    method public int getModifiers();
+    method public java.lang.String getName();
+    method public java.lang.annotation.Annotation[][] getParameterAnnotations();
+    method public java.lang.Class<?>[] getParameterTypes();
+    method public java.lang.Class<?> getReturnType();
+    method public java.lang.reflect.TypeVariable<java.lang.reflect.Method>[] getTypeParameters();
+    method public java.lang.Object invoke(java.lang.Object, java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException;
+    method public boolean isBridge();
+    method public boolean isSynthetic();
+    method public boolean isVarArgs();
+    method public java.lang.String toGenericString();
+  }
+
+  public class Modifier {
+    ctor public Modifier();
+    method public static boolean isAbstract(int);
+    method public static boolean isFinal(int);
+    method public static boolean isInterface(int);
+    method public static boolean isNative(int);
+    method public static boolean isPrivate(int);
+    method public static boolean isProtected(int);
+    method public static boolean isPublic(int);
+    method public static boolean isStatic(int);
+    method public static boolean isStrict(int);
+    method public static boolean isSynchronized(int);
+    method public static boolean isTransient(int);
+    method public static boolean isVolatile(int);
+    method public static java.lang.String toString(int);
+    field public static final int ABSTRACT = 1024; // 0x400
+    field public static final int FINAL = 16; // 0x10
+    field public static final int INTERFACE = 512; // 0x200
+    field public static final int NATIVE = 256; // 0x100
+    field public static final int PRIVATE = 2; // 0x2
+    field public static final int PROTECTED = 4; // 0x4
+    field public static final int PUBLIC = 1; // 0x1
+    field public static final int STATIC = 8; // 0x8
+    field public static final int STRICT = 2048; // 0x800
+    field public static final int SYNCHRONIZED = 32; // 0x20
+    field public static final int TRANSIENT = 128; // 0x80
+    field public static final int VOLATILE = 64; // 0x40
+  }
+
+  public abstract interface ParameterizedType implements java.lang.reflect.Type {
+    method public abstract java.lang.reflect.Type[] getActualTypeArguments();
+    method public abstract java.lang.reflect.Type getOwnerType();
+    method public abstract java.lang.reflect.Type getRawType();
+  }
+
+  public class Proxy implements java.io.Serializable {
+    ctor protected Proxy(java.lang.reflect.InvocationHandler);
+    method public static java.lang.reflect.InvocationHandler getInvocationHandler(java.lang.Object) throws java.lang.IllegalArgumentException;
+    method public static java.lang.Class<?> getProxyClass(java.lang.ClassLoader, java.lang.Class<?>...) throws java.lang.IllegalArgumentException;
+    method public static boolean isProxyClass(java.lang.Class<?>);
+    method public static java.lang.Object newProxyInstance(java.lang.ClassLoader, java.lang.Class<?>[], java.lang.reflect.InvocationHandler) throws java.lang.IllegalArgumentException;
+    field protected java.lang.reflect.InvocationHandler h;
+  }
+
+  public final class ReflectPermission extends java.security.BasicPermission {
+    ctor public ReflectPermission(java.lang.String);
+    ctor public ReflectPermission(java.lang.String, java.lang.String);
+  }
+
+  public abstract interface Type {
+  }
+
+  public abstract interface TypeVariable implements java.lang.reflect.Type {
+    method public abstract java.lang.reflect.Type[] getBounds();
+    method public abstract D getGenericDeclaration();
+    method public abstract java.lang.String getName();
+  }
+
+  public class UndeclaredThrowableException extends java.lang.RuntimeException {
+    ctor public UndeclaredThrowableException(java.lang.Throwable);
+    ctor public UndeclaredThrowableException(java.lang.Throwable, java.lang.String);
+    method public java.lang.Throwable getUndeclaredThrowable();
+  }
+
+  public abstract interface WildcardType implements java.lang.reflect.Type {
+    method public abstract java.lang.reflect.Type[] getLowerBounds();
+    method public abstract java.lang.reflect.Type[] getUpperBounds();
+  }
+
+}
+
+package java.math {
+
+  public class BigDecimal extends java.lang.Number implements java.lang.Comparable java.io.Serializable {
+    ctor public BigDecimal(char[], int, int);
+    ctor public BigDecimal(char[], int, int, java.math.MathContext);
+    ctor public BigDecimal(char[]);
+    ctor public BigDecimal(char[], java.math.MathContext);
+    ctor public BigDecimal(java.lang.String);
+    ctor public BigDecimal(java.lang.String, java.math.MathContext);
+    ctor public BigDecimal(double);
+    ctor public BigDecimal(double, java.math.MathContext);
+    ctor public BigDecimal(java.math.BigInteger);
+    ctor public BigDecimal(java.math.BigInteger, java.math.MathContext);
+    ctor public BigDecimal(java.math.BigInteger, int);
+    ctor public BigDecimal(java.math.BigInteger, int, java.math.MathContext);
+    ctor public BigDecimal(int);
+    ctor public BigDecimal(int, java.math.MathContext);
+    ctor public BigDecimal(long);
+    ctor public BigDecimal(long, java.math.MathContext);
+    method public java.math.BigDecimal abs();
+    method public java.math.BigDecimal abs(java.math.MathContext);
+    method public java.math.BigDecimal add(java.math.BigDecimal);
+    method public java.math.BigDecimal add(java.math.BigDecimal, java.math.MathContext);
+    method public byte byteValueExact();
+    method public int compareTo(java.math.BigDecimal);
+    method public java.math.BigDecimal divide(java.math.BigDecimal, int, int);
+    method public java.math.BigDecimal divide(java.math.BigDecimal, int, java.math.RoundingMode);
+    method public java.math.BigDecimal divide(java.math.BigDecimal, int);
+    method public java.math.BigDecimal divide(java.math.BigDecimal, java.math.RoundingMode);
+    method public java.math.BigDecimal divide(java.math.BigDecimal);
+    method public java.math.BigDecimal divide(java.math.BigDecimal, java.math.MathContext);
+    method public java.math.BigDecimal[] divideAndRemainder(java.math.BigDecimal);
+    method public java.math.BigDecimal[] divideAndRemainder(java.math.BigDecimal, java.math.MathContext);
+    method public java.math.BigDecimal divideToIntegralValue(java.math.BigDecimal);
+    method public java.math.BigDecimal divideToIntegralValue(java.math.BigDecimal, java.math.MathContext);
+    method public double doubleValue();
+    method public float floatValue();
+    method public int intValue();
+    method public int intValueExact();
+    method public long longValue();
+    method public long longValueExact();
+    method public java.math.BigDecimal max(java.math.BigDecimal);
+    method public java.math.BigDecimal min(java.math.BigDecimal);
+    method public java.math.BigDecimal movePointLeft(int);
+    method public java.math.BigDecimal movePointRight(int);
+    method public java.math.BigDecimal multiply(java.math.BigDecimal);
+    method public java.math.BigDecimal multiply(java.math.BigDecimal, java.math.MathContext);
+    method public java.math.BigDecimal negate();
+    method public java.math.BigDecimal negate(java.math.MathContext);
+    method public java.math.BigDecimal plus();
+    method public java.math.BigDecimal plus(java.math.MathContext);
+    method public java.math.BigDecimal pow(int);
+    method public java.math.BigDecimal pow(int, java.math.MathContext);
+    method public int precision();
+    method public java.math.BigDecimal remainder(java.math.BigDecimal);
+    method public java.math.BigDecimal remainder(java.math.BigDecimal, java.math.MathContext);
+    method public java.math.BigDecimal round(java.math.MathContext);
+    method public int scale();
+    method public java.math.BigDecimal scaleByPowerOfTen(int);
+    method public java.math.BigDecimal setScale(int, java.math.RoundingMode);
+    method public java.math.BigDecimal setScale(int, int);
+    method public java.math.BigDecimal setScale(int);
+    method public short shortValueExact();
+    method public int signum();
+    method public java.math.BigDecimal stripTrailingZeros();
+    method public java.math.BigDecimal subtract(java.math.BigDecimal);
+    method public java.math.BigDecimal subtract(java.math.BigDecimal, java.math.MathContext);
+    method public java.math.BigInteger toBigInteger();
+    method public java.math.BigInteger toBigIntegerExact();
+    method public java.lang.String toEngineeringString();
+    method public java.lang.String toPlainString();
+    method public java.math.BigDecimal ulp();
+    method public java.math.BigInteger unscaledValue();
+    method public static java.math.BigDecimal valueOf(long, int);
+    method public static java.math.BigDecimal valueOf(long);
+    method public static java.math.BigDecimal valueOf(double);
+    field public static final java.math.BigDecimal ONE;
+    field public static final int ROUND_CEILING = 2; // 0x2
+    field public static final int ROUND_DOWN = 1; // 0x1
+    field public static final int ROUND_FLOOR = 3; // 0x3
+    field public static final int ROUND_HALF_DOWN = 5; // 0x5
+    field public static final int ROUND_HALF_EVEN = 6; // 0x6
+    field public static final int ROUND_HALF_UP = 4; // 0x4
+    field public static final int ROUND_UNNECESSARY = 7; // 0x7
+    field public static final int ROUND_UP = 0; // 0x0
+    field public static final java.math.BigDecimal TEN;
+    field public static final java.math.BigDecimal ZERO;
+  }
+
+  public class BigInteger extends java.lang.Number implements java.lang.Comparable java.io.Serializable {
+    ctor public BigInteger(int, java.util.Random);
+    ctor public BigInteger(int, int, java.util.Random);
+    ctor public BigInteger(java.lang.String);
+    ctor public BigInteger(java.lang.String, int);
+    ctor public BigInteger(int, byte[]);
+    ctor public BigInteger(byte[]);
+    method public java.math.BigInteger abs();
+    method public java.math.BigInteger add(java.math.BigInteger);
+    method public java.math.BigInteger and(java.math.BigInteger);
+    method public java.math.BigInteger andNot(java.math.BigInteger);
+    method public int bitCount();
+    method public int bitLength();
+    method public java.math.BigInteger clearBit(int);
+    method public int compareTo(java.math.BigInteger);
+    method public java.math.BigInteger divide(java.math.BigInteger);
+    method public java.math.BigInteger[] divideAndRemainder(java.math.BigInteger);
+    method public double doubleValue();
+    method public java.math.BigInteger flipBit(int);
+    method public float floatValue();
+    method public java.math.BigInteger gcd(java.math.BigInteger);
+    method public int getLowestSetBit();
+    method public int intValue();
+    method public boolean isProbablePrime(int);
+    method public long longValue();
+    method public java.math.BigInteger max(java.math.BigInteger);
+    method public java.math.BigInteger min(java.math.BigInteger);
+    method public java.math.BigInteger mod(java.math.BigInteger);
+    method public java.math.BigInteger modInverse(java.math.BigInteger);
+    method public java.math.BigInteger modPow(java.math.BigInteger, java.math.BigInteger);
+    method public java.math.BigInteger multiply(java.math.BigInteger);
+    method public java.math.BigInteger negate();
+    method public java.math.BigInteger nextProbablePrime();
+    method public java.math.BigInteger not();
+    method public java.math.BigInteger or(java.math.BigInteger);
+    method public java.math.BigInteger pow(int);
+    method public static java.math.BigInteger probablePrime(int, java.util.Random);
+    method public java.math.BigInteger remainder(java.math.BigInteger);
+    method public java.math.BigInteger setBit(int);
+    method public java.math.BigInteger shiftLeft(int);
+    method public java.math.BigInteger shiftRight(int);
+    method public int signum();
+    method public java.math.BigInteger subtract(java.math.BigInteger);
+    method public boolean testBit(int);
+    method public byte[] toByteArray();
+    method public java.lang.String toString(int);
+    method public static java.math.BigInteger valueOf(long);
+    method public java.math.BigInteger xor(java.math.BigInteger);
+    field public static final java.math.BigInteger ONE;
+    field public static final java.math.BigInteger TEN;
+    field public static final java.math.BigInteger ZERO;
+  }
+
+  public final class MathContext implements java.io.Serializable {
+    ctor public MathContext(int);
+    ctor public MathContext(int, java.math.RoundingMode);
+    ctor public MathContext(java.lang.String);
+    method public int getPrecision();
+    method public java.math.RoundingMode getRoundingMode();
+    field public static final java.math.MathContext DECIMAL128;
+    field public static final java.math.MathContext DECIMAL32;
+    field public static final java.math.MathContext DECIMAL64;
+    field public static final java.math.MathContext UNLIMITED;
+  }
+
+  public final class RoundingMode extends java.lang.Enum {
+    method public static java.math.RoundingMode valueOf(java.lang.String);
+    method public static java.math.RoundingMode valueOf(int);
+    method public static final java.math.RoundingMode[] values();
+    enum_constant public static final java.math.RoundingMode CEILING;
+    enum_constant public static final java.math.RoundingMode DOWN;
+    enum_constant public static final java.math.RoundingMode FLOOR;
+    enum_constant public static final java.math.RoundingMode HALF_DOWN;
+    enum_constant public static final java.math.RoundingMode HALF_EVEN;
+    enum_constant public static final java.math.RoundingMode HALF_UP;
+    enum_constant public static final java.math.RoundingMode UNNECESSARY;
+    enum_constant public static final java.math.RoundingMode UP;
+  }
+
+}
+
+package java.net {
+
+  public abstract class Authenticator {
+    ctor public Authenticator();
+    method protected java.net.PasswordAuthentication getPasswordAuthentication();
+    method protected final java.lang.String getRequestingHost();
+    method protected final int getRequestingPort();
+    method protected final java.lang.String getRequestingPrompt();
+    method protected final java.lang.String getRequestingProtocol();
+    method protected final java.lang.String getRequestingScheme();
+    method protected final java.net.InetAddress getRequestingSite();
+    method protected java.net.URL getRequestingURL();
+    method protected java.net.Authenticator.RequestorType getRequestorType();
+    method public static synchronized java.net.PasswordAuthentication requestPasswordAuthentication(java.net.InetAddress, int, java.lang.String, java.lang.String, java.lang.String);
+    method public static synchronized java.net.PasswordAuthentication requestPasswordAuthentication(java.lang.String, java.net.InetAddress, int, java.lang.String, java.lang.String, java.lang.String);
+    method public static java.net.PasswordAuthentication requestPasswordAuthentication(java.lang.String, java.net.InetAddress, int, java.lang.String, java.lang.String, java.lang.String, java.net.URL, java.net.Authenticator.RequestorType);
+    method public static void setDefault(java.net.Authenticator);
+  }
+
+  public static final class Authenticator.RequestorType extends java.lang.Enum {
+    method public static java.net.Authenticator.RequestorType valueOf(java.lang.String);
+    method public static final java.net.Authenticator.RequestorType[] values();
+    enum_constant public static final java.net.Authenticator.RequestorType PROXY;
+    enum_constant public static final java.net.Authenticator.RequestorType SERVER;
+  }
+
+  public class BindException extends java.net.SocketException {
+    ctor public BindException();
+    ctor public BindException(java.lang.String);
+  }
+
+  public abstract class CacheRequest {
+    ctor public CacheRequest();
+    method public abstract void abort();
+    method public abstract java.io.OutputStream getBody() throws java.io.IOException;
+  }
+
+  public abstract class CacheResponse {
+    ctor public CacheResponse();
+    method public abstract java.io.InputStream getBody() throws java.io.IOException;
+    method public abstract java.util.Map<java.lang.String, java.util.List<java.lang.String>> getHeaders() throws java.io.IOException;
+  }
+
+  public class ConnectException extends java.net.SocketException {
+    ctor public ConnectException();
+    ctor public ConnectException(java.lang.String);
+  }
+
+  public abstract class ContentHandler {
+    ctor public ContentHandler();
+    method public abstract java.lang.Object getContent(java.net.URLConnection) throws java.io.IOException;
+    method public java.lang.Object getContent(java.net.URLConnection, java.lang.Class[]) throws java.io.IOException;
+  }
+
+  public abstract interface ContentHandlerFactory {
+    method public abstract java.net.ContentHandler createContentHandler(java.lang.String);
+  }
+
+  public abstract class CookieHandler {
+    ctor public CookieHandler();
+    method public abstract java.util.Map<java.lang.String, java.util.List<java.lang.String>> get(java.net.URI, java.util.Map<java.lang.String, java.util.List<java.lang.String>>) throws java.io.IOException;
+    method public static java.net.CookieHandler getDefault();
+    method public abstract void put(java.net.URI, java.util.Map<java.lang.String, java.util.List<java.lang.String>>) throws java.io.IOException;
+    method public static void setDefault(java.net.CookieHandler);
+  }
+
+  public class CookieManager extends java.net.CookieHandler {
+    ctor public CookieManager();
+    ctor public CookieManager(java.net.CookieStore, java.net.CookiePolicy);
+    method public java.util.Map<java.lang.String, java.util.List<java.lang.String>> get(java.net.URI, java.util.Map<java.lang.String, java.util.List<java.lang.String>>) throws java.io.IOException;
+    method public java.net.CookieStore getCookieStore();
+    method public void put(java.net.URI, java.util.Map<java.lang.String, java.util.List<java.lang.String>>) throws java.io.IOException;
+    method public void setCookiePolicy(java.net.CookiePolicy);
+  }
+
+  public abstract interface CookiePolicy {
+    method public abstract boolean shouldAccept(java.net.URI, java.net.HttpCookie);
+    field public static final java.net.CookiePolicy ACCEPT_ALL;
+    field public static final java.net.CookiePolicy ACCEPT_NONE;
+    field public static final java.net.CookiePolicy ACCEPT_ORIGINAL_SERVER;
+  }
+
+  public abstract interface CookieStore {
+    method public abstract void add(java.net.URI, java.net.HttpCookie);
+    method public abstract java.util.List<java.net.HttpCookie> get(java.net.URI);
+    method public abstract java.util.List<java.net.HttpCookie> getCookies();
+    method public abstract java.util.List<java.net.URI> getURIs();
+    method public abstract boolean remove(java.net.URI, java.net.HttpCookie);
+    method public abstract boolean removeAll();
+  }
+
+  public final class DatagramPacket {
+    ctor public DatagramPacket(byte[], int);
+    ctor public DatagramPacket(byte[], int, int);
+    ctor public DatagramPacket(byte[], int, int, java.net.InetAddress, int);
+    ctor public DatagramPacket(byte[], int, java.net.InetAddress, int);
+    ctor public DatagramPacket(byte[], int, java.net.SocketAddress) throws java.net.SocketException;
+    ctor public DatagramPacket(byte[], int, int, java.net.SocketAddress) throws java.net.SocketException;
+    method public synchronized java.net.InetAddress getAddress();
+    method public synchronized byte[] getData();
+    method public synchronized int getLength();
+    method public synchronized int getOffset();
+    method public synchronized int getPort();
+    method public synchronized java.net.SocketAddress getSocketAddress();
+    method public synchronized void setAddress(java.net.InetAddress);
+    method public synchronized void setData(byte[], int, int);
+    method public synchronized void setData(byte[]);
+    method public synchronized void setLength(int);
+    method public synchronized void setPort(int);
+    method public synchronized void setSocketAddress(java.net.SocketAddress);
+  }
+
+  public class DatagramSocket {
+    ctor public DatagramSocket() throws java.net.SocketException;
+    ctor public DatagramSocket(int) throws java.net.SocketException;
+    ctor public DatagramSocket(int, java.net.InetAddress) throws java.net.SocketException;
+    ctor protected DatagramSocket(java.net.DatagramSocketImpl);
+    ctor public DatagramSocket(java.net.SocketAddress) throws java.net.SocketException;
+    method public void bind(java.net.SocketAddress) throws java.net.SocketException;
+    method public void close();
+    method public void connect(java.net.SocketAddress) throws java.net.SocketException;
+    method public void connect(java.net.InetAddress, int);
+    method public void disconnect();
+    method public boolean getBroadcast() throws java.net.SocketException;
+    method public java.nio.channels.DatagramChannel getChannel();
+    method public java.net.InetAddress getInetAddress();
+    method public java.net.InetAddress getLocalAddress();
+    method public int getLocalPort();
+    method public java.net.SocketAddress getLocalSocketAddress();
+    method public int getPort();
+    method public synchronized int getReceiveBufferSize() throws java.net.SocketException;
+    method public java.net.SocketAddress getRemoteSocketAddress();
+    method public boolean getReuseAddress() throws java.net.SocketException;
+    method public synchronized int getSendBufferSize() throws java.net.SocketException;
+    method public synchronized int getSoTimeout() throws java.net.SocketException;
+    method public int getTrafficClass() throws java.net.SocketException;
+    method public boolean isBound();
+    method public boolean isClosed();
+    method public boolean isConnected();
+    method public synchronized void receive(java.net.DatagramPacket) throws java.io.IOException;
+    method public void send(java.net.DatagramPacket) throws java.io.IOException;
+    method public void setBroadcast(boolean) throws java.net.SocketException;
+    method public static synchronized void setDatagramSocketImplFactory(java.net.DatagramSocketImplFactory) throws java.io.IOException;
+    method public synchronized void setReceiveBufferSize(int) throws java.net.SocketException;
+    method public void setReuseAddress(boolean) throws java.net.SocketException;
+    method public synchronized void setSendBufferSize(int) throws java.net.SocketException;
+    method public synchronized void setSoTimeout(int) throws java.net.SocketException;
+    method public void setTrafficClass(int) throws java.net.SocketException;
+  }
+
+  public abstract class DatagramSocketImpl implements java.net.SocketOptions {
+    ctor public DatagramSocketImpl();
+    method protected abstract void bind(int, java.net.InetAddress) throws java.net.SocketException;
+    method protected abstract void close();
+    method protected void connect(java.net.InetAddress, int) throws java.net.SocketException;
+    method protected abstract void create() throws java.net.SocketException;
+    method protected void disconnect();
+    method protected java.io.FileDescriptor getFileDescriptor();
+    method protected int getLocalPort();
+    method protected abstract deprecated byte getTTL() throws java.io.IOException;
+    method protected abstract int getTimeToLive() throws java.io.IOException;
+    method protected abstract void join(java.net.InetAddress) throws java.io.IOException;
+    method protected abstract void joinGroup(java.net.SocketAddress, java.net.NetworkInterface) throws java.io.IOException;
+    method protected abstract void leave(java.net.InetAddress) throws java.io.IOException;
+    method protected abstract void leaveGroup(java.net.SocketAddress, java.net.NetworkInterface) throws java.io.IOException;
+    method protected abstract int peek(java.net.InetAddress) throws java.io.IOException;
+    method protected abstract int peekData(java.net.DatagramPacket) throws java.io.IOException;
+    method protected abstract void receive(java.net.DatagramPacket) throws java.io.IOException;
+    method protected abstract void send(java.net.DatagramPacket) throws java.io.IOException;
+    method protected abstract deprecated void setTTL(byte) throws java.io.IOException;
+    method protected abstract void setTimeToLive(int) throws java.io.IOException;
+    field protected java.io.FileDescriptor fd;
+    field protected int localPort;
+  }
+
+  public abstract interface DatagramSocketImplFactory {
+    method public abstract java.net.DatagramSocketImpl createDatagramSocketImpl();
+  }
+
+  public abstract interface FileNameMap {
+    method public abstract java.lang.String getContentTypeFor(java.lang.String);
+  }
+
+  public final class HttpCookie implements java.lang.Cloneable {
+    ctor public HttpCookie(java.lang.String, java.lang.String);
+    method public java.lang.Object clone();
+    method public static boolean domainMatches(java.lang.String, java.lang.String);
+    method public java.lang.String getComment();
+    method public java.lang.String getCommentURL();
+    method public boolean getDiscard();
+    method public java.lang.String getDomain();
+    method public long getMaxAge();
+    method public java.lang.String getName();
+    method public java.lang.String getPath();
+    method public java.lang.String getPortlist();
+    method public boolean getSecure();
+    method public java.lang.String getValue();
+    method public int getVersion();
+    method public boolean hasExpired();
+    method public static java.util.List<java.net.HttpCookie> parse(java.lang.String);
+    method public void setComment(java.lang.String);
+    method public void setCommentURL(java.lang.String);
+    method public void setDiscard(boolean);
+    method public void setDomain(java.lang.String);
+    method public void setMaxAge(long);
+    method public void setPath(java.lang.String);
+    method public void setPortlist(java.lang.String);
+    method public void setSecure(boolean);
+    method public void setValue(java.lang.String);
+    method public void setVersion(int);
+  }
+
+  public class HttpRetryException extends java.io.IOException {
+    ctor public HttpRetryException(java.lang.String, int);
+    ctor public HttpRetryException(java.lang.String, int, java.lang.String);
+    method public java.lang.String getLocation();
+    method public java.lang.String getReason();
+    method public int responseCode();
+  }
+
+  public abstract class HttpURLConnection extends java.net.URLConnection {
+    ctor protected HttpURLConnection(java.net.URL);
+    method public abstract void disconnect();
+    method public java.io.InputStream getErrorStream();
+    method public static boolean getFollowRedirects();
+    method public boolean getInstanceFollowRedirects();
+    method public java.lang.String getRequestMethod();
+    method public int getResponseCode() throws java.io.IOException;
+    method public java.lang.String getResponseMessage() throws java.io.IOException;
+    method public void setChunkedStreamingMode(int);
+    method public void setFixedLengthStreamingMode(int);
+    method public static void setFollowRedirects(boolean);
+    method public void setInstanceFollowRedirects(boolean);
+    method public void setRequestMethod(java.lang.String) throws java.net.ProtocolException;
+    method public abstract boolean usingProxy();
+    field public static final int HTTP_ACCEPTED = 202; // 0xca
+    field public static final int HTTP_BAD_GATEWAY = 502; // 0x1f6
+    field public static final int HTTP_BAD_METHOD = 405; // 0x195
+    field public static final int HTTP_BAD_REQUEST = 400; // 0x190
+    field public static final int HTTP_CLIENT_TIMEOUT = 408; // 0x198
+    field public static final int HTTP_CONFLICT = 409; // 0x199
+    field public static final int HTTP_CREATED = 201; // 0xc9
+    field public static final int HTTP_ENTITY_TOO_LARGE = 413; // 0x19d
+    field public static final int HTTP_FORBIDDEN = 403; // 0x193
+    field public static final int HTTP_GATEWAY_TIMEOUT = 504; // 0x1f8
+    field public static final int HTTP_GONE = 410; // 0x19a
+    field public static final int HTTP_INTERNAL_ERROR = 500; // 0x1f4
+    field public static final int HTTP_LENGTH_REQUIRED = 411; // 0x19b
+    field public static final int HTTP_MOVED_PERM = 301; // 0x12d
+    field public static final int HTTP_MOVED_TEMP = 302; // 0x12e
+    field public static final int HTTP_MULT_CHOICE = 300; // 0x12c
+    field public static final int HTTP_NOT_ACCEPTABLE = 406; // 0x196
+    field public static final int HTTP_NOT_AUTHORITATIVE = 203; // 0xcb
+    field public static final int HTTP_NOT_FOUND = 404; // 0x194
+    field public static final int HTTP_NOT_IMPLEMENTED = 501; // 0x1f5
+    field public static final int HTTP_NOT_MODIFIED = 304; // 0x130
+    field public static final int HTTP_NO_CONTENT = 204; // 0xcc
+    field public static final int HTTP_OK = 200; // 0xc8
+    field public static final int HTTP_PARTIAL = 206; // 0xce
+    field public static final int HTTP_PAYMENT_REQUIRED = 402; // 0x192
+    field public static final int HTTP_PRECON_FAILED = 412; // 0x19c
+    field public static final int HTTP_PROXY_AUTH = 407; // 0x197
+    field public static final int HTTP_REQ_TOO_LONG = 414; // 0x19e
+    field public static final int HTTP_RESET = 205; // 0xcd
+    field public static final int HTTP_SEE_OTHER = 303; // 0x12f
+    field public static final deprecated int HTTP_SERVER_ERROR = 500; // 0x1f4
+    field public static final int HTTP_UNAUTHORIZED = 401; // 0x191
+    field public static final int HTTP_UNAVAILABLE = 503; // 0x1f7
+    field public static final int HTTP_UNSUPPORTED_TYPE = 415; // 0x19f
+    field public static final int HTTP_USE_PROXY = 305; // 0x131
+    field public static final int HTTP_VERSION = 505; // 0x1f9
+    field protected int chunkLength;
+    field protected int fixedContentLength;
+    field protected boolean instanceFollowRedirects;
+    field protected java.lang.String method;
+    field protected int responseCode;
+    field protected java.lang.String responseMessage;
+  }
+
+  public final class IDN {
+    method public static java.lang.String toASCII(java.lang.String, int);
+    method public static java.lang.String toASCII(java.lang.String);
+    method public static java.lang.String toUnicode(java.lang.String, int);
+    method public static java.lang.String toUnicode(java.lang.String);
+    field public static final int ALLOW_UNASSIGNED = 1; // 0x1
+    field public static final int USE_STD3_ASCII_RULES = 2; // 0x2
+  }
+
+  public final class Inet4Address extends java.net.InetAddress {
+  }
+
+  public final class Inet6Address extends java.net.InetAddress {
+    method public static java.net.Inet6Address getByAddress(java.lang.String, byte[], int) throws java.net.UnknownHostException;
+    method public static java.net.Inet6Address getByAddress(java.lang.String, byte[], java.net.NetworkInterface) throws java.net.UnknownHostException;
+    method public int getScopeId();
+    method public java.net.NetworkInterface getScopedInterface();
+    method public boolean isIPv4CompatibleAddress();
+  }
+
+  public class InetAddress implements java.io.Serializable {
+    method public byte[] getAddress();
+    method public static java.net.InetAddress[] getAllByName(java.lang.String) throws java.net.UnknownHostException;
+    method public static java.net.InetAddress getByAddress(byte[]) throws java.net.UnknownHostException;
+    method public static java.net.InetAddress getByAddress(java.lang.String, byte[]) throws java.net.UnknownHostException;
+    method public static java.net.InetAddress getByName(java.lang.String) throws java.net.UnknownHostException;
+    method public java.lang.String getCanonicalHostName();
+    method public java.lang.String getHostAddress();
+    method public java.lang.String getHostName();
+    method public static java.net.InetAddress getLocalHost() throws java.net.UnknownHostException;
+    method public boolean isAnyLocalAddress();
+    method public boolean isLinkLocalAddress();
+    method public boolean isLoopbackAddress();
+    method public boolean isMCGlobal();
+    method public boolean isMCLinkLocal();
+    method public boolean isMCNodeLocal();
+    method public boolean isMCOrgLocal();
+    method public boolean isMCSiteLocal();
+    method public boolean isMulticastAddress();
+    method public boolean isReachable(int) throws java.io.IOException;
+    method public boolean isReachable(java.net.NetworkInterface, int, int) throws java.io.IOException;
+    method public boolean isSiteLocalAddress();
+  }
+
+  public class InetSocketAddress extends java.net.SocketAddress {
+    ctor public InetSocketAddress(int);
+    ctor public InetSocketAddress(java.net.InetAddress, int);
+    ctor public InetSocketAddress(java.lang.String, int);
+    method public static java.net.InetSocketAddress createUnresolved(java.lang.String, int);
+    method public final boolean equals(java.lang.Object);
+    method public final java.net.InetAddress getAddress();
+    method public final java.lang.String getHostName();
+    method public final int getPort();
+    method public final int hashCode();
+    method public final boolean isUnresolved();
+  }
+
+  public class InterfaceAddress {
+    method public java.net.InetAddress getAddress();
+    method public java.net.InetAddress getBroadcast();
+    method public short getNetworkPrefixLength();
+  }
+
+  public abstract class JarURLConnection extends java.net.URLConnection {
+    ctor protected JarURLConnection(java.net.URL) throws java.net.MalformedURLException;
+    method public java.util.jar.Attributes getAttributes() throws java.io.IOException;
+    method public java.security.cert.Certificate[] getCertificates() throws java.io.IOException;
+    method public java.lang.String getEntryName();
+    method public java.util.jar.JarEntry getJarEntry() throws java.io.IOException;
+    method public abstract java.util.jar.JarFile getJarFile() throws java.io.IOException;
+    method public java.net.URL getJarFileURL();
+    method public java.util.jar.Attributes getMainAttributes() throws java.io.IOException;
+    method public java.util.jar.Manifest getManifest() throws java.io.IOException;
+    field protected java.net.URLConnection jarFileURLConnection;
+  }
+
+  public class MalformedURLException extends java.io.IOException {
+    ctor public MalformedURLException();
+    ctor public MalformedURLException(java.lang.String);
+  }
+
+  public class MulticastSocket extends java.net.DatagramSocket {
+    ctor public MulticastSocket() throws java.io.IOException;
+    ctor public MulticastSocket(int) throws java.io.IOException;
+    ctor public MulticastSocket(java.net.SocketAddress) throws java.io.IOException;
+    method public java.net.InetAddress getInterface() throws java.net.SocketException;
+    method public boolean getLoopbackMode() throws java.net.SocketException;
+    method public java.net.NetworkInterface getNetworkInterface() throws java.net.SocketException;
+    method public deprecated byte getTTL() throws java.io.IOException;
+    method public int getTimeToLive() throws java.io.IOException;
+    method public void joinGroup(java.net.InetAddress) throws java.io.IOException;
+    method public void joinGroup(java.net.SocketAddress, java.net.NetworkInterface) throws java.io.IOException;
+    method public void leaveGroup(java.net.InetAddress) throws java.io.IOException;
+    method public void leaveGroup(java.net.SocketAddress, java.net.NetworkInterface) throws java.io.IOException;
+    method public deprecated void send(java.net.DatagramPacket, byte) throws java.io.IOException;
+    method public void setInterface(java.net.InetAddress) throws java.net.SocketException;
+    method public void setLoopbackMode(boolean) throws java.net.SocketException;
+    method public void setNetworkInterface(java.net.NetworkInterface) throws java.net.SocketException;
+    method public deprecated void setTTL(byte) throws java.io.IOException;
+    method public void setTimeToLive(int) throws java.io.IOException;
+  }
+
+  public final class NetPermission extends java.security.BasicPermission {
+    ctor public NetPermission(java.lang.String);
+    ctor public NetPermission(java.lang.String, java.lang.String);
+  }
+
+  public final class NetworkInterface {
+    method public static java.net.NetworkInterface getByInetAddress(java.net.InetAddress) throws java.net.SocketException;
+    method public static java.net.NetworkInterface getByName(java.lang.String) throws java.net.SocketException;
+    method public java.lang.String getDisplayName();
+    method public byte[] getHardwareAddress() throws java.net.SocketException;
+    method public java.util.Enumeration<java.net.InetAddress> getInetAddresses();
+    method public java.util.List<java.net.InterfaceAddress> getInterfaceAddresses();
+    method public int getMTU() throws java.net.SocketException;
+    method public java.lang.String getName();
+    method public static java.util.Enumeration<java.net.NetworkInterface> getNetworkInterfaces() throws java.net.SocketException;
+    method public java.net.NetworkInterface getParent();
+    method public java.util.Enumeration<java.net.NetworkInterface> getSubInterfaces();
+    method public boolean isLoopback() throws java.net.SocketException;
+    method public boolean isPointToPoint() throws java.net.SocketException;
+    method public boolean isUp() throws java.net.SocketException;
+    method public boolean isVirtual();
+    method public boolean supportsMulticast() throws java.net.SocketException;
+  }
+
+  public class NoRouteToHostException extends java.net.SocketException {
+    ctor public NoRouteToHostException();
+    ctor public NoRouteToHostException(java.lang.String);
+  }
+
+  public final class PasswordAuthentication {
+    ctor public PasswordAuthentication(java.lang.String, char[]);
+    method public char[] getPassword();
+    method public java.lang.String getUserName();
+  }
+
+  public class PortUnreachableException extends java.net.SocketException {
+    ctor public PortUnreachableException();
+    ctor public PortUnreachableException(java.lang.String);
+  }
+
+  public class ProtocolException extends java.io.IOException {
+    ctor public ProtocolException();
+    ctor public ProtocolException(java.lang.String);
+  }
+
+  public class Proxy {
+    ctor public Proxy(java.net.Proxy.Type, java.net.SocketAddress);
+    method public java.net.SocketAddress address();
+    method public final boolean equals(java.lang.Object);
+    method public final int hashCode();
+    method public java.net.Proxy.Type type();
+    field public static final java.net.Proxy NO_PROXY;
+  }
+
+  public static final class Proxy.Type extends java.lang.Enum {
+    method public static java.net.Proxy.Type valueOf(java.lang.String);
+    method public static final java.net.Proxy.Type[] values();
+    enum_constant public static final java.net.Proxy.Type DIRECT;
+    enum_constant public static final java.net.Proxy.Type HTTP;
+    enum_constant public static final java.net.Proxy.Type SOCKS;
+  }
+
+  public abstract class ProxySelector {
+    ctor public ProxySelector();
+    method public abstract void connectFailed(java.net.URI, java.net.SocketAddress, java.io.IOException);
+    method public static java.net.ProxySelector getDefault();
+    method public abstract java.util.List<java.net.Proxy> select(java.net.URI);
+    method public static void setDefault(java.net.ProxySelector);
+  }
+
+  public abstract class ResponseCache {
+    ctor public ResponseCache();
+    method public abstract java.net.CacheResponse get(java.net.URI, java.lang.String, java.util.Map<java.lang.String, java.util.List<java.lang.String>>) throws java.io.IOException;
+    method public static java.net.ResponseCache getDefault();
+    method public abstract java.net.CacheRequest put(java.net.URI, java.net.URLConnection) throws java.io.IOException;
+    method public static void setDefault(java.net.ResponseCache);
+  }
+
+  public abstract class SecureCacheResponse extends java.net.CacheResponse {
+    ctor public SecureCacheResponse();
+    method public abstract java.lang.String getCipherSuite();
+    method public abstract java.util.List<java.security.cert.Certificate> getLocalCertificateChain();
+    method public abstract java.security.Principal getLocalPrincipal();
+    method public abstract java.security.Principal getPeerPrincipal() throws javax.net.ssl.SSLPeerUnverifiedException;
+    method public abstract java.util.List<java.security.cert.Certificate> getServerCertificateChain() throws javax.net.ssl.SSLPeerUnverifiedException;
+  }
+
+  public class ServerSocket {
+    ctor public ServerSocket() throws java.io.IOException;
+    ctor public ServerSocket(int) throws java.io.IOException;
+    ctor public ServerSocket(int, int) throws java.io.IOException;
+    ctor public ServerSocket(int, int, java.net.InetAddress) throws java.io.IOException;
+    method public java.net.Socket accept() throws java.io.IOException;
+    method public void bind(java.net.SocketAddress) throws java.io.IOException;
+    method public void bind(java.net.SocketAddress, int) throws java.io.IOException;
+    method public void close() throws java.io.IOException;
+    method public java.nio.channels.ServerSocketChannel getChannel();
+    method public java.net.InetAddress getInetAddress();
+    method public int getLocalPort();
+    method public java.net.SocketAddress getLocalSocketAddress();
+    method public int getReceiveBufferSize() throws java.net.SocketException;
+    method public boolean getReuseAddress() throws java.net.SocketException;
+    method public synchronized int getSoTimeout() throws java.io.IOException;
+    method protected final void implAccept(java.net.Socket) throws java.io.IOException;
+    method public boolean isBound();
+    method public boolean isClosed();
+    method public void setPerformancePreferences(int, int, int);
+    method public void setReceiveBufferSize(int) throws java.net.SocketException;
+    method public void setReuseAddress(boolean) throws java.net.SocketException;
+    method public synchronized void setSoTimeout(int) throws java.net.SocketException;
+    method public static synchronized void setSocketFactory(java.net.SocketImplFactory) throws java.io.IOException;
+  }
+
+  public class Socket {
+    ctor public Socket();
+    ctor public Socket(java.net.Proxy);
+    ctor public Socket(java.lang.String, int) throws java.io.IOException, java.net.UnknownHostException;
+    ctor public Socket(java.lang.String, int, java.net.InetAddress, int) throws java.io.IOException;
+    ctor public deprecated Socket(java.lang.String, int, boolean) throws java.io.IOException;
+    ctor public Socket(java.net.InetAddress, int) throws java.io.IOException;
+    ctor public Socket(java.net.InetAddress, int, java.net.InetAddress, int) throws java.io.IOException;
+    ctor public deprecated Socket(java.net.InetAddress, int, boolean) throws java.io.IOException;
+    ctor protected Socket(java.net.SocketImpl) throws java.net.SocketException;
+    method public void bind(java.net.SocketAddress) throws java.io.IOException;
+    method public synchronized void close() throws java.io.IOException;
+    method public void connect(java.net.SocketAddress) throws java.io.IOException;
+    method public void connect(java.net.SocketAddress, int) throws java.io.IOException;
+    method public java.nio.channels.SocketChannel getChannel();
+    method public java.net.InetAddress getInetAddress();
+    method public java.io.InputStream getInputStream() throws java.io.IOException;
+    method public boolean getKeepAlive() throws java.net.SocketException;
+    method public java.net.InetAddress getLocalAddress();
+    method public int getLocalPort();
+    method public java.net.SocketAddress getLocalSocketAddress();
+    method public boolean getOOBInline() throws java.net.SocketException;
+    method public java.io.OutputStream getOutputStream() throws java.io.IOException;
+    method public int getPort();
+    method public synchronized int getReceiveBufferSize() throws java.net.SocketException;
+    method public java.net.SocketAddress getRemoteSocketAddress();
+    method public boolean getReuseAddress() throws java.net.SocketException;
+    method public synchronized int getSendBufferSize() throws java.net.SocketException;
+    method public int getSoLinger() throws java.net.SocketException;
+    method public synchronized int getSoTimeout() throws java.net.SocketException;
+    method public boolean getTcpNoDelay() throws java.net.SocketException;
+    method public int getTrafficClass() throws java.net.SocketException;
+    method public boolean isBound();
+    method public boolean isClosed();
+    method public boolean isConnected();
+    method public boolean isInputShutdown();
+    method public boolean isOutputShutdown();
+    method public void sendUrgentData(int) throws java.io.IOException;
+    method public void setKeepAlive(boolean) throws java.net.SocketException;
+    method public void setOOBInline(boolean) throws java.net.SocketException;
+    method public void setPerformancePreferences(int, int, int);
+    method public synchronized void setReceiveBufferSize(int) throws java.net.SocketException;
+    method public void setReuseAddress(boolean) throws java.net.SocketException;
+    method public synchronized void setSendBufferSize(int) throws java.net.SocketException;
+    method public void setSoLinger(boolean, int) throws java.net.SocketException;
+    method public synchronized void setSoTimeout(int) throws java.net.SocketException;
+    method public static synchronized void setSocketImplFactory(java.net.SocketImplFactory) throws java.io.IOException;
+    method public void setTcpNoDelay(boolean) throws java.net.SocketException;
+    method public void setTrafficClass(int) throws java.net.SocketException;
+    method public void shutdownInput() throws java.io.IOException;
+    method public void shutdownOutput() throws java.io.IOException;
+  }
+
+  public abstract class SocketAddress implements java.io.Serializable {
+    ctor public SocketAddress();
+  }
+
+  public class SocketException extends java.io.IOException {
+    ctor public SocketException();
+    ctor public SocketException(java.lang.String);
+  }
+
+  public abstract class SocketImpl implements java.net.SocketOptions {
+    ctor public SocketImpl();
+    method protected abstract void accept(java.net.SocketImpl) throws java.io.IOException;
+    method protected abstract int available() throws java.io.IOException;
+    method protected abstract void bind(java.net.InetAddress, int) throws java.io.IOException;
+    method protected abstract void close() throws java.io.IOException;
+    method protected abstract void connect(java.lang.String, int) throws java.io.IOException;
+    method protected abstract void connect(java.net.InetAddress, int) throws java.io.IOException;
+    method protected abstract void connect(java.net.SocketAddress, int) throws java.io.IOException;
+    method protected abstract void create(boolean) throws java.io.IOException;
+    method protected java.io.FileDescriptor getFileDescriptor();
+    method protected java.net.InetAddress getInetAddress();
+    method protected abstract java.io.InputStream getInputStream() throws java.io.IOException;
+    method protected int getLocalPort();
+    method protected abstract java.io.OutputStream getOutputStream() throws java.io.IOException;
+    method protected int getPort();
+    method protected abstract void listen(int) throws java.io.IOException;
+    method protected abstract void sendUrgentData(int) throws java.io.IOException;
+    method protected void setPerformancePreferences(int, int, int);
+    method protected void shutdownInput() throws java.io.IOException;
+    method protected void shutdownOutput() throws java.io.IOException;
+    method protected boolean supportsUrgentData();
+    field protected java.net.InetAddress address;
+    field protected java.io.FileDescriptor fd;
+    field protected int localport;
+    field protected int port;
+  }
+
+  public abstract interface SocketImplFactory {
+    method public abstract java.net.SocketImpl createSocketImpl();
+  }
+
+  public abstract interface SocketOptions {
+    method public abstract java.lang.Object getOption(int) throws java.net.SocketException;
+    method public abstract void setOption(int, java.lang.Object) throws java.net.SocketException;
+    field public static final int IP_MULTICAST_IF = 16; // 0x10
+    field public static final int IP_MULTICAST_IF2 = 31; // 0x1f
+    field public static final int IP_MULTICAST_LOOP = 18; // 0x12
+    field public static final int IP_TOS = 3; // 0x3
+    field public static final int SO_BINDADDR = 15; // 0xf
+    field public static final int SO_BROADCAST = 32; // 0x20
+    field public static final int SO_KEEPALIVE = 8; // 0x8
+    field public static final int SO_LINGER = 128; // 0x80
+    field public static final int SO_OOBINLINE = 4099; // 0x1003
+    field public static final int SO_RCVBUF = 4098; // 0x1002
+    field public static final int SO_REUSEADDR = 4; // 0x4
+    field public static final int SO_SNDBUF = 4097; // 0x1001
+    field public static final int SO_TIMEOUT = 4102; // 0x1006
+    field public static final int TCP_NODELAY = 1; // 0x1
+  }
+
+  public final class SocketPermission extends java.security.Permission implements java.io.Serializable {
+    ctor public SocketPermission(java.lang.String, java.lang.String);
+    method public java.lang.String getActions();
+    method public boolean implies(java.security.Permission);
+  }
+
+  public class SocketTimeoutException extends java.io.InterruptedIOException {
+    ctor public SocketTimeoutException();
+    ctor public SocketTimeoutException(java.lang.String);
+  }
+
+  public final class URI implements java.lang.Comparable java.io.Serializable {
+    ctor public URI(java.lang.String) throws java.net.URISyntaxException;
+    ctor public URI(java.lang.String, java.lang.String, java.lang.String) throws java.net.URISyntaxException;
+    ctor public URI(java.lang.String, java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String) throws java.net.URISyntaxException;
+    ctor public URI(java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws java.net.URISyntaxException;
+    ctor public URI(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws java.net.URISyntaxException;
+    method public int compareTo(java.net.URI);
+    method public static java.net.URI create(java.lang.String);
+    method public java.lang.String getAuthority();
+    method public java.lang.String getFragment();
+    method public java.lang.String getHost();
+    method public java.lang.String getPath();
+    method public int getPort();
+    method public java.lang.String getQuery();
+    method public java.lang.String getRawAuthority();
+    method public java.lang.String getRawFragment();
+    method public java.lang.String getRawPath();
+    method public java.lang.String getRawQuery();
+    method public java.lang.String getRawSchemeSpecificPart();
+    method public java.lang.String getRawUserInfo();
+    method public java.lang.String getScheme();
+    method public java.lang.String getSchemeSpecificPart();
+    method public java.lang.String getUserInfo();
+    method public boolean isAbsolute();
+    method public boolean isOpaque();
+    method public java.net.URI normalize();
+    method public java.net.URI parseServerAuthority() throws java.net.URISyntaxException;
+    method public java.net.URI relativize(java.net.URI);
+    method public java.net.URI resolve(java.net.URI);
+    method public java.net.URI resolve(java.lang.String);
+    method public java.lang.String toASCIIString();
+    method public java.net.URL toURL() throws java.net.MalformedURLException;
+  }
+
+  public class URISyntaxException extends java.lang.Exception {
+    ctor public URISyntaxException(java.lang.String, java.lang.String, int);
+    ctor public URISyntaxException(java.lang.String, java.lang.String);
+    method public int getIndex();
+    method public java.lang.String getInput();
+    method public java.lang.String getReason();
+  }
+
+  public final class URL implements java.io.Serializable {
+    ctor public URL(java.lang.String) throws java.net.MalformedURLException;
+    ctor public URL(java.net.URL, java.lang.String) throws java.net.MalformedURLException;
+    ctor public URL(java.net.URL, java.lang.String, java.net.URLStreamHandler) throws java.net.MalformedURLException;
+    ctor public URL(java.lang.String, java.lang.String, java.lang.String) throws java.net.MalformedURLException;
+    ctor public URL(java.lang.String, java.lang.String, int, java.lang.String) throws java.net.MalformedURLException;
+    ctor public URL(java.lang.String, java.lang.String, int, java.lang.String, java.net.URLStreamHandler) throws java.net.MalformedURLException;
+    method public java.lang.String getAuthority();
+    method public final java.lang.Object getContent() throws java.io.IOException;
+    method public final java.lang.Object getContent(java.lang.Class[]) throws java.io.IOException;
+    method public int getDefaultPort();
+    method public java.lang.String getFile();
+    method public java.lang.String getHost();
+    method public java.lang.String getPath();
+    method public int getPort();
+    method public java.lang.String getProtocol();
+    method public java.lang.String getQuery();
+    method public java.lang.String getRef();
+    method public java.lang.String getUserInfo();
+    method public java.net.URLConnection openConnection() throws java.io.IOException;
+    method public java.net.URLConnection openConnection(java.net.Proxy) throws java.io.IOException;
+    method public final java.io.InputStream openStream() throws java.io.IOException;
+    method public boolean sameFile(java.net.URL);
+    method protected void set(java.lang.String, java.lang.String, int, java.lang.String, java.lang.String);
+    method protected void set(java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public static synchronized void setURLStreamHandlerFactory(java.net.URLStreamHandlerFactory);
+    method public java.lang.String toExternalForm();
+    method public java.net.URI toURI() throws java.net.URISyntaxException;
+  }
+
+  public class URLClassLoader extends java.security.SecureClassLoader {
+    ctor public URLClassLoader(java.net.URL[]);
+    ctor public URLClassLoader(java.net.URL[], java.lang.ClassLoader);
+    ctor public URLClassLoader(java.net.URL[], java.lang.ClassLoader, java.net.URLStreamHandlerFactory);
+    method protected void addURL(java.net.URL);
+    method protected java.lang.Package definePackage(java.lang.String, java.util.jar.Manifest, java.net.URL) throws java.lang.IllegalArgumentException;
+    method public java.net.URL findResource(java.lang.String);
+    method public java.util.Enumeration<java.net.URL> findResources(java.lang.String) throws java.io.IOException;
+    method public java.net.URL[] getURLs();
+    method public static java.net.URLClassLoader newInstance(java.net.URL[]);
+    method public static java.net.URLClassLoader newInstance(java.net.URL[], java.lang.ClassLoader);
+  }
+
+  public abstract class URLConnection {
+    ctor protected URLConnection(java.net.URL);
+    method public void addRequestProperty(java.lang.String, java.lang.String);
+    method public abstract void connect() throws java.io.IOException;
+    method public boolean getAllowUserInteraction();
+    method public int getConnectTimeout();
+    method public java.lang.Object getContent() throws java.io.IOException;
+    method public java.lang.Object getContent(java.lang.Class[]) throws java.io.IOException;
+    method public java.lang.String getContentEncoding();
+    method public int getContentLength();
+    method public java.lang.String getContentType();
+    method public long getDate();
+    method public static boolean getDefaultAllowUserInteraction();
+    method public static deprecated java.lang.String getDefaultRequestProperty(java.lang.String);
+    method public boolean getDefaultUseCaches();
+    method public boolean getDoInput();
+    method public boolean getDoOutput();
+    method public long getExpiration();
+    method public static java.net.FileNameMap getFileNameMap();
+    method public java.lang.String getHeaderField(int);
+    method public java.lang.String getHeaderField(java.lang.String);
+    method public long getHeaderFieldDate(java.lang.String, long);
+    method public int getHeaderFieldInt(java.lang.String, int);
+    method public java.lang.String getHeaderFieldKey(int);
+    method public java.util.Map<java.lang.String, java.util.List<java.lang.String>> getHeaderFields();
+    method public long getIfModifiedSince();
+    method public java.io.InputStream getInputStream() throws java.io.IOException;
+    method public long getLastModified();
+    method public java.io.OutputStream getOutputStream() throws java.io.IOException;
+    method public java.security.Permission getPermission() throws java.io.IOException;
+    method public int getReadTimeout();
+    method public java.util.Map<java.lang.String, java.util.List<java.lang.String>> getRequestProperties();
+    method public java.lang.String getRequestProperty(java.lang.String);
+    method public java.net.URL getURL();
+    method public boolean getUseCaches();
+    method public static java.lang.String guessContentTypeFromName(java.lang.String);
+    method public static java.lang.String guessContentTypeFromStream(java.io.InputStream) throws java.io.IOException;
+    method public void setAllowUserInteraction(boolean);
+    method public void setConnectTimeout(int);
+    method public static synchronized void setContentHandlerFactory(java.net.ContentHandlerFactory);
+    method public static void setDefaultAllowUserInteraction(boolean);
+    method public static deprecated void setDefaultRequestProperty(java.lang.String, java.lang.String);
+    method public void setDefaultUseCaches(boolean);
+    method public void setDoInput(boolean);
+    method public void setDoOutput(boolean);
+    method public static void setFileNameMap(java.net.FileNameMap);
+    method public void setIfModifiedSince(long);
+    method public void setReadTimeout(int);
+    method public void setRequestProperty(java.lang.String, java.lang.String);
+    method public void setUseCaches(boolean);
+    field protected boolean allowUserInteraction;
+    field protected boolean connected;
+    field protected boolean doInput;
+    field protected boolean doOutput;
+    field protected long ifModifiedSince;
+    field protected java.net.URL url;
+    field protected boolean useCaches;
+  }
+
+  public class URLDecoder {
+    ctor public URLDecoder();
+    method public static deprecated java.lang.String decode(java.lang.String);
+    method public static java.lang.String decode(java.lang.String, java.lang.String) throws java.io.UnsupportedEncodingException;
+  }
+
+  public class URLEncoder {
+    method public static deprecated java.lang.String encode(java.lang.String);
+    method public static java.lang.String encode(java.lang.String, java.lang.String) throws java.io.UnsupportedEncodingException;
+  }
+
+  public abstract class URLStreamHandler {
+    ctor public URLStreamHandler();
+    method protected boolean equals(java.net.URL, java.net.URL);
+    method protected int getDefaultPort();
+    method protected java.net.InetAddress getHostAddress(java.net.URL);
+    method protected int hashCode(java.net.URL);
+    method protected boolean hostsEqual(java.net.URL, java.net.URL);
+    method protected abstract java.net.URLConnection openConnection(java.net.URL) throws java.io.IOException;
+    method protected java.net.URLConnection openConnection(java.net.URL, java.net.Proxy) throws java.io.IOException;
+    method protected void parseURL(java.net.URL, java.lang.String, int, int);
+    method protected boolean sameFile(java.net.URL, java.net.URL);
+    method protected deprecated void setURL(java.net.URL, java.lang.String, java.lang.String, int, java.lang.String, java.lang.String);
+    method protected void setURL(java.net.URL, java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method protected java.lang.String toExternalForm(java.net.URL);
+  }
+
+  public abstract interface URLStreamHandlerFactory {
+    method public abstract java.net.URLStreamHandler createURLStreamHandler(java.lang.String);
+  }
+
+  public class UnknownHostException extends java.io.IOException {
+    ctor public UnknownHostException();
+    ctor public UnknownHostException(java.lang.String);
+  }
+
+  public class UnknownServiceException extends java.io.IOException {
+    ctor public UnknownServiceException();
+    ctor public UnknownServiceException(java.lang.String);
+  }
+
+}
+
+package java.nio {
+
+  public abstract class Buffer {
+    method public abstract java.lang.Object array();
+    method public abstract int arrayOffset();
+    method public final int capacity();
+    method public final java.nio.Buffer clear();
+    method public final java.nio.Buffer flip();
+    method public abstract boolean hasArray();
+    method public final boolean hasRemaining();
+    method public abstract boolean isDirect();
+    method public abstract boolean isReadOnly();
+    method public final int limit();
+    method public final java.nio.Buffer limit(int);
+    method public final java.nio.Buffer mark();
+    method public final int position();
+    method public final java.nio.Buffer position(int);
+    method public final int remaining();
+    method public final java.nio.Buffer reset();
+    method public final java.nio.Buffer rewind();
+  }
+
+  public class BufferOverflowException extends java.lang.RuntimeException {
+    ctor public BufferOverflowException();
+  }
+
+  public class BufferUnderflowException extends java.lang.RuntimeException {
+    ctor public BufferUnderflowException();
+  }
+
+  public abstract class ByteBuffer extends java.nio.Buffer implements java.lang.Comparable {
+    method public static java.nio.ByteBuffer allocate(int);
+    method public static java.nio.ByteBuffer allocateDirect(int);
+    method public final byte[] array();
+    method public final int arrayOffset();
+    method public abstract java.nio.CharBuffer asCharBuffer();
+    method public abstract java.nio.DoubleBuffer asDoubleBuffer();
+    method public abstract java.nio.FloatBuffer asFloatBuffer();
+    method public abstract java.nio.IntBuffer asIntBuffer();
+    method public abstract java.nio.LongBuffer asLongBuffer();
+    method public abstract java.nio.ByteBuffer asReadOnlyBuffer();
+    method public abstract java.nio.ShortBuffer asShortBuffer();
+    method public abstract java.nio.ByteBuffer compact();
+    method public int compareTo(java.nio.ByteBuffer);
+    method public abstract java.nio.ByteBuffer duplicate();
+    method public abstract byte get();
+    method public java.nio.ByteBuffer get(byte[]);
+    method public java.nio.ByteBuffer get(byte[], int, int);
+    method public abstract byte get(int);
+    method public abstract char getChar();
+    method public abstract char getChar(int);
+    method public abstract double getDouble();
+    method public abstract double getDouble(int);
+    method public abstract float getFloat();
+    method public abstract float getFloat(int);
+    method public abstract int getInt();
+    method public abstract int getInt(int);
+    method public abstract long getLong();
+    method public abstract long getLong(int);
+    method public abstract short getShort();
+    method public abstract short getShort(int);
+    method public final boolean hasArray();
+    method public abstract boolean isDirect();
+    method public final java.nio.ByteOrder order();
+    method public final java.nio.ByteBuffer order(java.nio.ByteOrder);
+    method public abstract java.nio.ByteBuffer put(byte);
+    method public final java.nio.ByteBuffer put(byte[]);
+    method public java.nio.ByteBuffer put(byte[], int, int);
+    method public java.nio.ByteBuffer put(java.nio.ByteBuffer);
+    method public abstract java.nio.ByteBuffer put(int, byte);
+    method public abstract java.nio.ByteBuffer putChar(char);
+    method public abstract java.nio.ByteBuffer putChar(int, char);
+    method public abstract java.nio.ByteBuffer putDouble(double);
+    method public abstract java.nio.ByteBuffer putDouble(int, double);
+    method public abstract java.nio.ByteBuffer putFloat(float);
+    method public abstract java.nio.ByteBuffer putFloat(int, float);
+    method public abstract java.nio.ByteBuffer putInt(int);
+    method public abstract java.nio.ByteBuffer putInt(int, int);
+    method public abstract java.nio.ByteBuffer putLong(long);
+    method public abstract java.nio.ByteBuffer putLong(int, long);
+    method public abstract java.nio.ByteBuffer putShort(short);
+    method public abstract java.nio.ByteBuffer putShort(int, short);
+    method public abstract java.nio.ByteBuffer slice();
+    method public static java.nio.ByteBuffer wrap(byte[]);
+    method public static java.nio.ByteBuffer wrap(byte[], int, int);
+  }
+
+  public final class ByteOrder {
+    method public static java.nio.ByteOrder nativeOrder();
+    field public static final java.nio.ByteOrder BIG_ENDIAN;
+    field public static final java.nio.ByteOrder LITTLE_ENDIAN;
+  }
+
+  public abstract class CharBuffer extends java.nio.Buffer implements java.lang.Appendable java.lang.CharSequence java.lang.Comparable java.lang.Readable {
+    method public static java.nio.CharBuffer allocate(int);
+    method public java.nio.CharBuffer append(char);
+    method public java.nio.CharBuffer append(java.lang.CharSequence);
+    method public java.nio.CharBuffer append(java.lang.CharSequence, int, int);
+    method public final char[] array();
+    method public final int arrayOffset();
+    method public abstract java.nio.CharBuffer asReadOnlyBuffer();
+    method public final char charAt(int);
+    method public abstract java.nio.CharBuffer compact();
+    method public int compareTo(java.nio.CharBuffer);
+    method public abstract java.nio.CharBuffer duplicate();
+    method public abstract char get();
+    method public java.nio.CharBuffer get(char[]);
+    method public java.nio.CharBuffer get(char[], int, int);
+    method public abstract char get(int);
+    method public final boolean hasArray();
+    method public abstract boolean isDirect();
+    method public final int length();
+    method public abstract java.nio.ByteOrder order();
+    method public abstract java.nio.CharBuffer put(char);
+    method public final java.nio.CharBuffer put(char[]);
+    method public java.nio.CharBuffer put(char[], int, int);
+    method public java.nio.CharBuffer put(java.nio.CharBuffer);
+    method public abstract java.nio.CharBuffer put(int, char);
+    method public final java.nio.CharBuffer put(java.lang.String);
+    method public java.nio.CharBuffer put(java.lang.String, int, int);
+    method public int read(java.nio.CharBuffer) throws java.io.IOException;
+    method public abstract java.nio.CharBuffer slice();
+    method public abstract java.lang.CharSequence subSequence(int, int);
+    method public static java.nio.CharBuffer wrap(char[]);
+    method public static java.nio.CharBuffer wrap(char[], int, int);
+    method public static java.nio.CharBuffer wrap(java.lang.CharSequence);
+    method public static java.nio.CharBuffer wrap(java.lang.CharSequence, int, int);
+  }
+
+  public abstract class DoubleBuffer extends java.nio.Buffer implements java.lang.Comparable {
+    method public static java.nio.DoubleBuffer allocate(int);
+    method public final double[] array();
+    method public final int arrayOffset();
+    method public abstract java.nio.DoubleBuffer asReadOnlyBuffer();
+    method public abstract java.nio.DoubleBuffer compact();
+    method public int compareTo(java.nio.DoubleBuffer);
+    method public abstract java.nio.DoubleBuffer duplicate();
+    method public abstract double get();
+    method public java.nio.DoubleBuffer get(double[]);
+    method public java.nio.DoubleBuffer get(double[], int, int);
+    method public abstract double get(int);
+    method public final boolean hasArray();
+    method public abstract boolean isDirect();
+    method public abstract java.nio.ByteOrder order();
+    method public abstract java.nio.DoubleBuffer put(double);
+    method public final java.nio.DoubleBuffer put(double[]);
+    method public java.nio.DoubleBuffer put(double[], int, int);
+    method public java.nio.DoubleBuffer put(java.nio.DoubleBuffer);
+    method public abstract java.nio.DoubleBuffer put(int, double);
+    method public abstract java.nio.DoubleBuffer slice();
+    method public static java.nio.DoubleBuffer wrap(double[]);
+    method public static java.nio.DoubleBuffer wrap(double[], int, int);
+  }
+
+  public abstract class FloatBuffer extends java.nio.Buffer implements java.lang.Comparable {
+    method public static java.nio.FloatBuffer allocate(int);
+    method public final float[] array();
+    method public final int arrayOffset();
+    method public abstract java.nio.FloatBuffer asReadOnlyBuffer();
+    method public abstract java.nio.FloatBuffer compact();
+    method public int compareTo(java.nio.FloatBuffer);
+    method public abstract java.nio.FloatBuffer duplicate();
+    method public abstract float get();
+    method public java.nio.FloatBuffer get(float[]);
+    method public java.nio.FloatBuffer get(float[], int, int);
+    method public abstract float get(int);
+    method public final boolean hasArray();
+    method public abstract boolean isDirect();
+    method public abstract java.nio.ByteOrder order();
+    method public abstract java.nio.FloatBuffer put(float);
+    method public final java.nio.FloatBuffer put(float[]);
+    method public java.nio.FloatBuffer put(float[], int, int);
+    method public java.nio.FloatBuffer put(java.nio.FloatBuffer);
+    method public abstract java.nio.FloatBuffer put(int, float);
+    method public abstract java.nio.FloatBuffer slice();
+    method public static java.nio.FloatBuffer wrap(float[]);
+    method public static java.nio.FloatBuffer wrap(float[], int, int);
+  }
+
+  public abstract class IntBuffer extends java.nio.Buffer implements java.lang.Comparable {
+    method public static java.nio.IntBuffer allocate(int);
+    method public final int[] array();
+    method public final int arrayOffset();
+    method public abstract java.nio.IntBuffer asReadOnlyBuffer();
+    method public abstract java.nio.IntBuffer compact();
+    method public int compareTo(java.nio.IntBuffer);
+    method public abstract java.nio.IntBuffer duplicate();
+    method public abstract int get();
+    method public java.nio.IntBuffer get(int[]);
+    method public java.nio.IntBuffer get(int[], int, int);
+    method public abstract int get(int);
+    method public final boolean hasArray();
+    method public abstract boolean isDirect();
+    method public abstract java.nio.ByteOrder order();
+    method public abstract java.nio.IntBuffer put(int);
+    method public final java.nio.IntBuffer put(int[]);
+    method public java.nio.IntBuffer put(int[], int, int);
+    method public java.nio.IntBuffer put(java.nio.IntBuffer);
+    method public abstract java.nio.IntBuffer put(int, int);
+    method public abstract java.nio.IntBuffer slice();
+    method public static java.nio.IntBuffer wrap(int[]);
+    method public static java.nio.IntBuffer wrap(int[], int, int);
+  }
+
+  public class InvalidMarkException extends java.lang.IllegalStateException {
+    ctor public InvalidMarkException();
+  }
+
+  public abstract class LongBuffer extends java.nio.Buffer implements java.lang.Comparable {
+    method public static java.nio.LongBuffer allocate(int);
+    method public final long[] array();
+    method public final int arrayOffset();
+    method public abstract java.nio.LongBuffer asReadOnlyBuffer();
+    method public abstract java.nio.LongBuffer compact();
+    method public int compareTo(java.nio.LongBuffer);
+    method public abstract java.nio.LongBuffer duplicate();
+    method public abstract long get();
+    method public java.nio.LongBuffer get(long[]);
+    method public java.nio.LongBuffer get(long[], int, int);
+    method public abstract long get(int);
+    method public final boolean hasArray();
+    method public abstract boolean isDirect();
+    method public abstract java.nio.ByteOrder order();
+    method public abstract java.nio.LongBuffer put(long);
+    method public final java.nio.LongBuffer put(long[]);
+    method public java.nio.LongBuffer put(long[], int, int);
+    method public java.nio.LongBuffer put(java.nio.LongBuffer);
+    method public abstract java.nio.LongBuffer put(int, long);
+    method public abstract java.nio.LongBuffer slice();
+    method public static java.nio.LongBuffer wrap(long[]);
+    method public static java.nio.LongBuffer wrap(long[], int, int);
+  }
+
+  public abstract class MappedByteBuffer extends java.nio.ByteBuffer {
+    method public final java.nio.MappedByteBuffer force();
+    method public final boolean isLoaded();
+    method public final java.nio.MappedByteBuffer load();
+  }
+
+  public class ReadOnlyBufferException extends java.lang.UnsupportedOperationException {
+    ctor public ReadOnlyBufferException();
+  }
+
+  public abstract class ShortBuffer extends java.nio.Buffer implements java.lang.Comparable {
+    method public static java.nio.ShortBuffer allocate(int);
+    method public final short[] array();
+    method public final int arrayOffset();
+    method public abstract java.nio.ShortBuffer asReadOnlyBuffer();
+    method public abstract java.nio.ShortBuffer compact();
+    method public int compareTo(java.nio.ShortBuffer);
+    method public abstract java.nio.ShortBuffer duplicate();
+    method public abstract short get();
+    method public java.nio.ShortBuffer get(short[]);
+    method public java.nio.ShortBuffer get(short[], int, int);
+    method public abstract short get(int);
+    method public final boolean hasArray();
+    method public abstract boolean isDirect();
+    method public abstract java.nio.ByteOrder order();
+    method public abstract java.nio.ShortBuffer put(short);
+    method public final java.nio.ShortBuffer put(short[]);
+    method public java.nio.ShortBuffer put(short[], int, int);
+    method public java.nio.ShortBuffer put(java.nio.ShortBuffer);
+    method public abstract java.nio.ShortBuffer put(int, short);
+    method public abstract java.nio.ShortBuffer slice();
+    method public static java.nio.ShortBuffer wrap(short[]);
+    method public static java.nio.ShortBuffer wrap(short[], int, int);
+  }
+
+}
+
+package java.nio.channels {
+
+  public class AlreadyConnectedException extends java.lang.IllegalStateException {
+    ctor public AlreadyConnectedException();
+  }
+
+  public class AsynchronousCloseException extends java.nio.channels.ClosedChannelException {
+    ctor public AsynchronousCloseException();
+  }
+
+  public abstract interface ByteChannel implements java.nio.channels.ReadableByteChannel java.nio.channels.WritableByteChannel {
+  }
+
+  public class CancelledKeyException extends java.lang.IllegalStateException {
+    ctor public CancelledKeyException();
+  }
+
+  public abstract interface Channel implements java.io.Closeable {
+    method public abstract void close() throws java.io.IOException;
+    method public abstract boolean isOpen();
+  }
+
+  public final class Channels {
+    method public static java.nio.channels.ReadableByteChannel newChannel(java.io.InputStream);
+    method public static java.nio.channels.WritableByteChannel newChannel(java.io.OutputStream);
+    method public static java.io.InputStream newInputStream(java.nio.channels.ReadableByteChannel);
+    method public static java.io.OutputStream newOutputStream(java.nio.channels.WritableByteChannel);
+    method public static java.io.Reader newReader(java.nio.channels.ReadableByteChannel, java.nio.charset.CharsetDecoder, int);
+    method public static java.io.Reader newReader(java.nio.channels.ReadableByteChannel, java.lang.String);
+    method public static java.io.Writer newWriter(java.nio.channels.WritableByteChannel, java.nio.charset.CharsetEncoder, int);
+    method public static java.io.Writer newWriter(java.nio.channels.WritableByteChannel, java.lang.String);
+  }
+
+  public class ClosedByInterruptException extends java.nio.channels.AsynchronousCloseException {
+    ctor public ClosedByInterruptException();
+  }
+
+  public class ClosedChannelException extends java.io.IOException {
+    ctor public ClosedChannelException();
+  }
+
+  public class ClosedSelectorException extends java.lang.IllegalStateException {
+    ctor public ClosedSelectorException();
+  }
+
+  public class ConnectionPendingException extends java.lang.IllegalStateException {
+    ctor public ConnectionPendingException();
+  }
+
+  public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.ScatteringByteChannel {
+    ctor protected DatagramChannel(java.nio.channels.spi.SelectorProvider);
+    method public abstract java.nio.channels.DatagramChannel connect(java.net.SocketAddress) throws java.io.IOException;
+    method public abstract java.nio.channels.DatagramChannel disconnect() throws java.io.IOException;
+    method public abstract boolean isConnected();
+    method public static java.nio.channels.DatagramChannel open() throws java.io.IOException;
+    method public abstract int read(java.nio.ByteBuffer) throws java.io.IOException;
+    method public abstract long read(java.nio.ByteBuffer[], int, int) throws java.io.IOException;
+    method public final synchronized long read(java.nio.ByteBuffer[]) throws java.io.IOException;
+    method public abstract java.net.SocketAddress receive(java.nio.ByteBuffer) throws java.io.IOException;
+    method public abstract int send(java.nio.ByteBuffer, java.net.SocketAddress) throws java.io.IOException;
+    method public abstract java.net.DatagramSocket socket();
+    method public final int validOps();
+    method public abstract int write(java.nio.ByteBuffer) throws java.io.IOException;
+    method public abstract long write(java.nio.ByteBuffer[], int, int) throws java.io.IOException;
+    method public final synchronized long write(java.nio.ByteBuffer[]) throws java.io.IOException;
+  }
+
+  public abstract class FileChannel extends java.nio.channels.spi.AbstractInterruptibleChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.ScatteringByteChannel {
+    ctor protected FileChannel();
+    method public abstract void force(boolean) throws java.io.IOException;
+    method public final java.nio.channels.FileLock lock() throws java.io.IOException;
+    method public abstract java.nio.channels.FileLock lock(long, long, boolean) throws java.io.IOException;
+    method public abstract java.nio.MappedByteBuffer map(java.nio.channels.FileChannel.MapMode, long, long) throws java.io.IOException;
+    method public abstract long position() throws java.io.IOException;
+    method public abstract java.nio.channels.FileChannel position(long) throws java.io.IOException;
+    method public abstract int read(java.nio.ByteBuffer) throws java.io.IOException;
+    method public abstract int read(java.nio.ByteBuffer, long) throws java.io.IOException;
+    method public final long read(java.nio.ByteBuffer[]) throws java.io.IOException;
+    method public abstract long read(java.nio.ByteBuffer[], int, int) throws java.io.IOException;
+    method public abstract long size() throws java.io.IOException;
+    method public abstract long transferFrom(java.nio.channels.ReadableByteChannel, long, long) throws java.io.IOException;
+    method public abstract long transferTo(long, long, java.nio.channels.WritableByteChannel) throws java.io.IOException;
+    method public abstract java.nio.channels.FileChannel truncate(long) throws java.io.IOException;
+    method public final java.nio.channels.FileLock tryLock() throws java.io.IOException;
+    method public abstract java.nio.channels.FileLock tryLock(long, long, boolean) throws java.io.IOException;
+    method public abstract int write(java.nio.ByteBuffer) throws java.io.IOException;
+    method public abstract int write(java.nio.ByteBuffer, long) throws java.io.IOException;
+    method public final long write(java.nio.ByteBuffer[]) throws java.io.IOException;
+    method public abstract long write(java.nio.ByteBuffer[], int, int) throws java.io.IOException;
+  }
+
+  public static class FileChannel.MapMode {
+    field public static final java.nio.channels.FileChannel.MapMode PRIVATE;
+    field public static final java.nio.channels.FileChannel.MapMode READ_ONLY;
+    field public static final java.nio.channels.FileChannel.MapMode READ_WRITE;
+  }
+
+  public abstract class FileLock {
+    ctor protected FileLock(java.nio.channels.FileChannel, long, long, boolean);
+    method public final java.nio.channels.FileChannel channel();
+    method public final boolean isShared();
+    method public abstract boolean isValid();
+    method public final boolean overlaps(long, long);
+    method public final long position();
+    method public abstract void release() throws java.io.IOException;
+    method public final long size();
+    method public final java.lang.String toString();
+  }
+
+  public class FileLockInterruptionException extends java.io.IOException {
+    ctor public FileLockInterruptionException();
+  }
+
+  public abstract interface GatheringByteChannel implements java.nio.channels.WritableByteChannel {
+    method public abstract long write(java.nio.ByteBuffer[]) throws java.io.IOException;
+    method public abstract long write(java.nio.ByteBuffer[], int, int) throws java.io.IOException;
+  }
+
+  public class IllegalBlockingModeException extends java.lang.IllegalStateException {
+    ctor public IllegalBlockingModeException();
+  }
+
+  public class IllegalSelectorException extends java.lang.IllegalArgumentException {
+    ctor public IllegalSelectorException();
+  }
+
+  public abstract interface InterruptibleChannel implements java.nio.channels.Channel {
+    method public abstract void close() throws java.io.IOException;
+  }
+
+  public class NoConnectionPendingException extends java.lang.IllegalStateException {
+    ctor public NoConnectionPendingException();
+  }
+
+  public class NonReadableChannelException extends java.lang.IllegalStateException {
+    ctor public NonReadableChannelException();
+  }
+
+  public class NonWritableChannelException extends java.lang.IllegalStateException {
+    ctor public NonWritableChannelException();
+  }
+
+  public class NotYetBoundException extends java.lang.IllegalStateException {
+    ctor public NotYetBoundException();
+  }
+
+  public class NotYetConnectedException extends java.lang.IllegalStateException {
+    ctor public NotYetConnectedException();
+  }
+
+  public class OverlappingFileLockException extends java.lang.IllegalStateException {
+    ctor public OverlappingFileLockException();
+  }
+
+  public abstract class Pipe {
+    ctor protected Pipe();
+    method public static java.nio.channels.Pipe open() throws java.io.IOException;
+    method public abstract java.nio.channels.Pipe.SinkChannel sink();
+    method public abstract java.nio.channels.Pipe.SourceChannel source();
+  }
+
+  public static abstract class Pipe.SinkChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.GatheringByteChannel java.nio.channels.WritableByteChannel {
+    ctor protected Pipe.SinkChannel(java.nio.channels.spi.SelectorProvider);
+    method public final int validOps();
+  }
+
+  public static abstract class Pipe.SourceChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ReadableByteChannel java.nio.channels.ScatteringByteChannel {
+    ctor protected Pipe.SourceChannel(java.nio.channels.spi.SelectorProvider);
+    method public final int validOps();
+  }
+
+  public abstract interface ReadableByteChannel implements java.nio.channels.Channel {
+    method public abstract int read(java.nio.ByteBuffer) throws java.io.IOException;
+  }
+
+  public abstract interface ScatteringByteChannel implements java.nio.channels.ReadableByteChannel {
+    method public abstract long read(java.nio.ByteBuffer[]) throws java.io.IOException;
+    method public abstract long read(java.nio.ByteBuffer[], int, int) throws java.io.IOException;
+  }
+
+  public abstract class SelectableChannel extends java.nio.channels.spi.AbstractInterruptibleChannel implements java.nio.channels.Channel {
+    ctor protected SelectableChannel();
+    method public abstract java.lang.Object blockingLock();
+    method public abstract java.nio.channels.SelectableChannel configureBlocking(boolean) throws java.io.IOException;
+    method public abstract boolean isBlocking();
+    method public abstract boolean isRegistered();
+    method public abstract java.nio.channels.SelectionKey keyFor(java.nio.channels.Selector);
+    method public abstract java.nio.channels.spi.SelectorProvider provider();
+    method public final java.nio.channels.SelectionKey register(java.nio.channels.Selector, int) throws java.nio.channels.ClosedChannelException;
+    method public abstract java.nio.channels.SelectionKey register(java.nio.channels.Selector, int, java.lang.Object) throws java.nio.channels.ClosedChannelException;
+    method public abstract int validOps();
+  }
+
+  public abstract class SelectionKey {
+    ctor protected SelectionKey();
+    method public final java.lang.Object attach(java.lang.Object);
+    method public final java.lang.Object attachment();
+    method public abstract void cancel();
+    method public abstract java.nio.channels.SelectableChannel channel();
+    method public abstract int interestOps();
+    method public abstract java.nio.channels.SelectionKey interestOps(int);
+    method public final boolean isAcceptable();
+    method public final boolean isConnectable();
+    method public final boolean isReadable();
+    method public abstract boolean isValid();
+    method public final boolean isWritable();
+    method public abstract int readyOps();
+    method public abstract java.nio.channels.Selector selector();
+    field public static final int OP_ACCEPT = 16; // 0x10
+    field public static final int OP_CONNECT = 8; // 0x8
+    field public static final int OP_READ = 1; // 0x1
+    field public static final int OP_WRITE = 4; // 0x4
+  }
+
+  public abstract class Selector {
+    ctor protected Selector();
+    method public abstract void close() throws java.io.IOException;
+    method public abstract boolean isOpen();
+    method public abstract java.util.Set<java.nio.channels.SelectionKey> keys();
+    method public static java.nio.channels.Selector open() throws java.io.IOException;
+    method public abstract java.nio.channels.spi.SelectorProvider provider();
+    method public abstract int select() throws java.io.IOException;
+    method public abstract int select(long) throws java.io.IOException;
+    method public abstract int selectNow() throws java.io.IOException;
+    method public abstract java.util.Set<java.nio.channels.SelectionKey> selectedKeys();
+    method public abstract java.nio.channels.Selector wakeup();
+  }
+
+  public abstract class ServerSocketChannel extends java.nio.channels.spi.AbstractSelectableChannel {
+    ctor protected ServerSocketChannel(java.nio.channels.spi.SelectorProvider);
+    method public abstract java.nio.channels.SocketChannel accept() throws java.io.IOException;
+    method public static java.nio.channels.ServerSocketChannel open() throws java.io.IOException;
+    method public abstract java.net.ServerSocket socket();
+    method public final int validOps();
+  }
+
+  public abstract class SocketChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.ScatteringByteChannel {
+    ctor protected SocketChannel(java.nio.channels.spi.SelectorProvider);
+    method public abstract boolean connect(java.net.SocketAddress) throws java.io.IOException;
+    method public abstract boolean finishConnect() throws java.io.IOException;
+    method public abstract boolean isConnected();
+    method public abstract boolean isConnectionPending();
+    method public static java.nio.channels.SocketChannel open() throws java.io.IOException;
+    method public static java.nio.channels.SocketChannel open(java.net.SocketAddress) throws java.io.IOException;
+    method public abstract int read(java.nio.ByteBuffer) throws java.io.IOException;
+    method public abstract long read(java.nio.ByteBuffer[], int, int) throws java.io.IOException;
+    method public final synchronized long read(java.nio.ByteBuffer[]) throws java.io.IOException;
+    method public abstract java.net.Socket socket();
+    method public final int validOps();
+    method public abstract int write(java.nio.ByteBuffer) throws java.io.IOException;
+    method public abstract long write(java.nio.ByteBuffer[], int, int) throws java.io.IOException;
+    method public final synchronized long write(java.nio.ByteBuffer[]) throws java.io.IOException;
+  }
+
+  public class UnresolvedAddressException extends java.lang.IllegalArgumentException {
+    ctor public UnresolvedAddressException();
+  }
+
+  public class UnsupportedAddressTypeException extends java.lang.IllegalArgumentException {
+    ctor public UnsupportedAddressTypeException();
+  }
+
+  public abstract interface WritableByteChannel implements java.nio.channels.Channel {
+    method public abstract int write(java.nio.ByteBuffer) throws java.io.IOException;
+  }
+
+}
+
+package java.nio.channels.spi {
+
+  public abstract class AbstractInterruptibleChannel implements java.nio.channels.Channel java.nio.channels.InterruptibleChannel {
+    ctor protected AbstractInterruptibleChannel();
+    method protected final void begin();
+    method public final void close() throws java.io.IOException;
+    method protected final void end(boolean) throws java.nio.channels.AsynchronousCloseException;
+    method protected abstract void implCloseChannel() throws java.io.IOException;
+    method public final synchronized boolean isOpen();
+  }
+
+  public abstract class AbstractSelectableChannel extends java.nio.channels.SelectableChannel {
+    ctor protected AbstractSelectableChannel(java.nio.channels.spi.SelectorProvider);
+    method public final java.lang.Object blockingLock();
+    method public final java.nio.channels.SelectableChannel configureBlocking(boolean) throws java.io.IOException;
+    method protected final synchronized void implCloseChannel() throws java.io.IOException;
+    method protected abstract void implCloseSelectableChannel() throws java.io.IOException;
+    method protected abstract void implConfigureBlocking(boolean) throws java.io.IOException;
+    method public final boolean isBlocking();
+    method public final synchronized boolean isRegistered();
+    method public final synchronized java.nio.channels.SelectionKey keyFor(java.nio.channels.Selector);
+    method public final java.nio.channels.spi.SelectorProvider provider();
+    method public final java.nio.channels.SelectionKey register(java.nio.channels.Selector, int, java.lang.Object) throws java.nio.channels.ClosedChannelException;
+  }
+
+  public abstract class AbstractSelectionKey extends java.nio.channels.SelectionKey {
+    ctor protected AbstractSelectionKey();
+    method public final void cancel();
+    method public final boolean isValid();
+  }
+
+  public abstract class AbstractSelector extends java.nio.channels.Selector {
+    ctor protected AbstractSelector(java.nio.channels.spi.SelectorProvider);
+    method protected final void begin();
+    method protected final java.util.Set<java.nio.channels.SelectionKey> cancelledKeys();
+    method public final void close() throws java.io.IOException;
+    method protected final void deregister(java.nio.channels.spi.AbstractSelectionKey);
+    method protected final void end();
+    method protected abstract void implCloseSelector() throws java.io.IOException;
+    method public final boolean isOpen();
+    method public final java.nio.channels.spi.SelectorProvider provider();
+    method protected abstract java.nio.channels.SelectionKey register(java.nio.channels.spi.AbstractSelectableChannel, int, java.lang.Object);
+  }
+
+  public abstract class SelectorProvider {
+    ctor protected SelectorProvider();
+    method public java.nio.channels.Channel inheritedChannel() throws java.io.IOException;
+    method public abstract java.nio.channels.DatagramChannel openDatagramChannel() throws java.io.IOException;
+    method public abstract java.nio.channels.Pipe openPipe() throws java.io.IOException;
+    method public abstract java.nio.channels.spi.AbstractSelector openSelector() throws java.io.IOException;
+    method public abstract java.nio.channels.ServerSocketChannel openServerSocketChannel() throws java.io.IOException;
+    method public abstract java.nio.channels.SocketChannel openSocketChannel() throws java.io.IOException;
+    method public static synchronized java.nio.channels.spi.SelectorProvider provider();
+  }
+
+}
+
+package java.nio.charset {
+
+  public class CharacterCodingException extends java.io.IOException {
+    ctor public CharacterCodingException();
+  }
+
+  public abstract class Charset implements java.lang.Comparable {
+    ctor protected Charset(java.lang.String, java.lang.String[]);
+    method public final java.util.Set<java.lang.String> aliases();
+    method public static java.util.SortedMap<java.lang.String, java.nio.charset.Charset> availableCharsets();
+    method public boolean canEncode();
+    method public final int compareTo(java.nio.charset.Charset);
+    method public abstract boolean contains(java.nio.charset.Charset);
+    method public final java.nio.CharBuffer decode(java.nio.ByteBuffer);
+    method public static java.nio.charset.Charset defaultCharset();
+    method public java.lang.String displayName();
+    method public java.lang.String displayName(java.util.Locale);
+    method public final java.nio.ByteBuffer encode(java.nio.CharBuffer);
+    method public final java.nio.ByteBuffer encode(java.lang.String);
+    method public final boolean equals(java.lang.Object);
+    method public static java.nio.charset.Charset forName(java.lang.String);
+    method public final int hashCode();
+    method public final boolean isRegistered();
+    method public static boolean isSupported(java.lang.String);
+    method public final java.lang.String name();
+    method public abstract java.nio.charset.CharsetDecoder newDecoder();
+    method public abstract java.nio.charset.CharsetEncoder newEncoder();
+    method public final java.lang.String toString();
+  }
+
+  public abstract class CharsetDecoder {
+    ctor protected CharsetDecoder(java.nio.charset.Charset, float, float);
+    method public final float averageCharsPerByte();
+    method public final java.nio.charset.Charset charset();
+    method public final java.nio.CharBuffer decode(java.nio.ByteBuffer) throws java.nio.charset.CharacterCodingException;
+    method public final java.nio.charset.CoderResult decode(java.nio.ByteBuffer, java.nio.CharBuffer, boolean);
+    method protected abstract java.nio.charset.CoderResult decodeLoop(java.nio.ByteBuffer, java.nio.CharBuffer);
+    method public java.nio.charset.Charset detectedCharset();
+    method public final java.nio.charset.CoderResult flush(java.nio.CharBuffer);
+    method protected java.nio.charset.CoderResult implFlush(java.nio.CharBuffer);
+    method protected void implOnMalformedInput(java.nio.charset.CodingErrorAction);
+    method protected void implOnUnmappableCharacter(java.nio.charset.CodingErrorAction);
+    method protected void implReplaceWith(java.lang.String);
+    method protected void implReset();
+    method public boolean isAutoDetecting();
+    method public boolean isCharsetDetected();
+    method public java.nio.charset.CodingErrorAction malformedInputAction();
+    method public final float maxCharsPerByte();
+    method public final java.nio.charset.CharsetDecoder onMalformedInput(java.nio.charset.CodingErrorAction);
+    method public final java.nio.charset.CharsetDecoder onUnmappableCharacter(java.nio.charset.CodingErrorAction);
+    method public final java.nio.charset.CharsetDecoder replaceWith(java.lang.String);
+    method public final java.lang.String replacement();
+    method public final java.nio.charset.CharsetDecoder reset();
+    method public java.nio.charset.CodingErrorAction unmappableCharacterAction();
+  }
+
+  public abstract class CharsetEncoder {
+    ctor protected CharsetEncoder(java.nio.charset.Charset, float, float);
+    ctor protected CharsetEncoder(java.nio.charset.Charset, float, float, byte[]);
+    method public final float averageBytesPerChar();
+    method public boolean canEncode(char);
+    method public boolean canEncode(java.lang.CharSequence);
+    method public final java.nio.charset.Charset charset();
+    method public final java.nio.ByteBuffer encode(java.nio.CharBuffer) throws java.nio.charset.CharacterCodingException;
+    method public final java.nio.charset.CoderResult encode(java.nio.CharBuffer, java.nio.ByteBuffer, boolean);
+    method protected abstract java.nio.charset.CoderResult encodeLoop(java.nio.CharBuffer, java.nio.ByteBuffer);
+    method public final java.nio.charset.CoderResult flush(java.nio.ByteBuffer);
+    method protected java.nio.charset.CoderResult implFlush(java.nio.ByteBuffer);
+    method protected void implOnMalformedInput(java.nio.charset.CodingErrorAction);
+    method protected void implOnUnmappableCharacter(java.nio.charset.CodingErrorAction);
+    method protected void implReplaceWith(byte[]);
+    method protected void implReset();
+    method public boolean isLegalReplacement(byte[]);
+    method public java.nio.charset.CodingErrorAction malformedInputAction();
+    method public final float maxBytesPerChar();
+    method public final java.nio.charset.CharsetEncoder onMalformedInput(java.nio.charset.CodingErrorAction);
+    method public final java.nio.charset.CharsetEncoder onUnmappableCharacter(java.nio.charset.CodingErrorAction);
+    method public final java.nio.charset.CharsetEncoder replaceWith(byte[]);
+    method public final byte[] replacement();
+    method public final java.nio.charset.CharsetEncoder reset();
+    method public java.nio.charset.CodingErrorAction unmappableCharacterAction();
+  }
+
+  public class CoderMalfunctionError extends java.lang.Error {
+    ctor public CoderMalfunctionError(java.lang.Exception);
+  }
+
+  public class CoderResult {
+    method public boolean isError();
+    method public boolean isMalformed();
+    method public boolean isOverflow();
+    method public boolean isUnderflow();
+    method public boolean isUnmappable();
+    method public int length() throws java.lang.UnsupportedOperationException;
+    method public static synchronized java.nio.charset.CoderResult malformedForLength(int) throws java.lang.IllegalArgumentException;
+    method public void throwException() throws java.nio.BufferOverflowException, java.nio.BufferUnderflowException, java.nio.charset.CharacterCodingException, java.nio.charset.MalformedInputException, java.nio.charset.UnmappableCharacterException;
+    method public static synchronized java.nio.charset.CoderResult unmappableForLength(int) throws java.lang.IllegalArgumentException;
+    field public static final java.nio.charset.CoderResult OVERFLOW;
+    field public static final java.nio.charset.CoderResult UNDERFLOW;
+  }
+
+  public class CodingErrorAction {
+    field public static final java.nio.charset.CodingErrorAction IGNORE;
+    field public static final java.nio.charset.CodingErrorAction REPLACE;
+    field public static final java.nio.charset.CodingErrorAction REPORT;
+  }
+
+  public class IllegalCharsetNameException extends java.lang.IllegalArgumentException {
+    ctor public IllegalCharsetNameException(java.lang.String);
+    method public java.lang.String getCharsetName();
+  }
+
+  public class MalformedInputException extends java.nio.charset.CharacterCodingException {
+    ctor public MalformedInputException(int);
+    method public int getInputLength();
+  }
+
+  public class UnmappableCharacterException extends java.nio.charset.CharacterCodingException {
+    ctor public UnmappableCharacterException(int);
+    method public int getInputLength();
+  }
+
+  public class UnsupportedCharsetException extends java.lang.IllegalArgumentException {
+    ctor public UnsupportedCharsetException(java.lang.String);
+    method public java.lang.String getCharsetName();
+  }
+
+}
+
+package java.nio.charset.spi {
+
+  public abstract class CharsetProvider {
+    ctor protected CharsetProvider();
+    method public abstract java.nio.charset.Charset charsetForName(java.lang.String);
+    method public abstract java.util.Iterator<java.nio.charset.Charset> charsets();
+  }
+
+}
+
+package java.security {
+
+  public final class AccessControlContext {
+    ctor public AccessControlContext(java.security.AccessControlContext, java.security.DomainCombiner);
+    ctor public AccessControlContext(java.security.ProtectionDomain[]);
+    method public void checkPermission(java.security.Permission) throws java.security.AccessControlException;
+    method public java.security.DomainCombiner getDomainCombiner();
+  }
+
+  public class AccessControlException extends java.lang.SecurityException {
+    ctor public AccessControlException(java.lang.String);
+    ctor public AccessControlException(java.lang.String, java.security.Permission);
+    method public java.security.Permission getPermission();
+  }
+
+  public final class AccessController {
+    method public static void checkPermission(java.security.Permission) throws java.security.AccessControlException;
+    method public static T doPrivileged(java.security.PrivilegedAction<T>);
+    method public static T doPrivileged(java.security.PrivilegedAction<T>, java.security.AccessControlContext);
+    method public static T doPrivileged(java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
+    method public static T doPrivileged(java.security.PrivilegedExceptionAction<T>, java.security.AccessControlContext) throws java.security.PrivilegedActionException;
+    method public static T doPrivilegedWithCombiner(java.security.PrivilegedAction<T>);
+    method public static T doPrivilegedWithCombiner(java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
+    method public static java.security.AccessControlContext getContext();
+  }
+
+  public class AlgorithmParameterGenerator {
+    ctor protected AlgorithmParameterGenerator(java.security.AlgorithmParameterGeneratorSpi, java.security.Provider, java.lang.String);
+    method public final java.security.AlgorithmParameters generateParameters();
+    method public final java.lang.String getAlgorithm();
+    method public static java.security.AlgorithmParameterGenerator getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static java.security.AlgorithmParameterGenerator getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static java.security.AlgorithmParameterGenerator getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final java.security.Provider getProvider();
+    method public final void init(int);
+    method public final void init(int, java.security.SecureRandom);
+    method public final void init(java.security.spec.AlgorithmParameterSpec) throws java.security.InvalidAlgorithmParameterException;
+    method public final void init(java.security.spec.AlgorithmParameterSpec, java.security.SecureRandom) throws java.security.InvalidAlgorithmParameterException;
+  }
+
+  public abstract class AlgorithmParameterGeneratorSpi {
+    ctor public AlgorithmParameterGeneratorSpi();
+    method protected abstract java.security.AlgorithmParameters engineGenerateParameters();
+    method protected abstract void engineInit(int, java.security.SecureRandom);
+    method protected abstract void engineInit(java.security.spec.AlgorithmParameterSpec, java.security.SecureRandom) throws java.security.InvalidAlgorithmParameterException;
+  }
+
+  public class AlgorithmParameters {
+    ctor protected AlgorithmParameters(java.security.AlgorithmParametersSpi, java.security.Provider, java.lang.String);
+    method public final java.lang.String getAlgorithm();
+    method public final byte[] getEncoded() throws java.io.IOException;
+    method public final byte[] getEncoded(java.lang.String) throws java.io.IOException;
+    method public static java.security.AlgorithmParameters getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static java.security.AlgorithmParameters getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static java.security.AlgorithmParameters getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final T getParameterSpec(java.lang.Class<T>) throws java.security.spec.InvalidParameterSpecException;
+    method public final java.security.Provider getProvider();
+    method public final void init(java.security.spec.AlgorithmParameterSpec) throws java.security.spec.InvalidParameterSpecException;
+    method public final void init(byte[]) throws java.io.IOException;
+    method public final void init(byte[], java.lang.String) throws java.io.IOException;
+    method public final java.lang.String toString();
+  }
+
+  public abstract class AlgorithmParametersSpi {
+    ctor public AlgorithmParametersSpi();
+    method protected abstract byte[] engineGetEncoded() throws java.io.IOException;
+    method protected abstract byte[] engineGetEncoded(java.lang.String) throws java.io.IOException;
+    method protected abstract T engineGetParameterSpec(java.lang.Class<T>) throws java.security.spec.InvalidParameterSpecException;
+    method protected abstract void engineInit(java.security.spec.AlgorithmParameterSpec) throws java.security.spec.InvalidParameterSpecException;
+    method protected abstract void engineInit(byte[]) throws java.io.IOException;
+    method protected abstract void engineInit(byte[], java.lang.String) throws java.io.IOException;
+    method protected abstract java.lang.String engineToString();
+  }
+
+  public final class AllPermission extends java.security.Permission {
+    ctor public AllPermission(java.lang.String, java.lang.String);
+    ctor public AllPermission();
+    method public java.lang.String getActions();
+    method public boolean implies(java.security.Permission);
+  }
+
+  public abstract class AuthProvider extends java.security.Provider {
+    ctor protected AuthProvider(java.lang.String, double, java.lang.String);
+    method public abstract void login(javax.security.auth.Subject, javax.security.auth.callback.CallbackHandler) throws javax.security.auth.login.LoginException;
+    method public abstract void logout() throws javax.security.auth.login.LoginException;
+    method public abstract void setCallbackHandler(javax.security.auth.callback.CallbackHandler);
+  }
+
+  public abstract class BasicPermission extends java.security.Permission implements java.io.Serializable {
+    ctor public BasicPermission(java.lang.String);
+    ctor public BasicPermission(java.lang.String, java.lang.String);
+    method public java.lang.String getActions();
+    method public boolean implies(java.security.Permission);
+  }
+
+  public abstract deprecated interface Certificate {
+    method public abstract void decode(java.io.InputStream) throws java.io.IOException, java.security.KeyException;
+    method public abstract void encode(java.io.OutputStream) throws java.io.IOException, java.security.KeyException;
+    method public abstract java.lang.String getFormat();
+    method public abstract java.security.Principal getGuarantor();
+    method public abstract java.security.Principal getPrincipal();
+    method public abstract java.security.PublicKey getPublicKey();
+    method public abstract java.lang.String toString(boolean);
+  }
+
+  public final class CodeSigner implements java.io.Serializable {
+    ctor public CodeSigner(java.security.cert.CertPath, java.security.Timestamp);
+    method public java.security.cert.CertPath getSignerCertPath();
+    method public java.security.Timestamp getTimestamp();
+  }
+
+  public class CodeSource implements java.io.Serializable {
+    ctor public CodeSource(java.net.URL, java.security.cert.Certificate[]);
+    ctor public CodeSource(java.net.URL, java.security.CodeSigner[]);
+    method public final java.security.cert.Certificate[] getCertificates();
+    method public final java.security.CodeSigner[] getCodeSigners();
+    method public final java.net.URL getLocation();
+    method public boolean implies(java.security.CodeSource);
+  }
+
+  public class DigestException extends java.security.GeneralSecurityException {
+    ctor public DigestException(java.lang.String);
+    ctor public DigestException();
+    ctor public DigestException(java.lang.String, java.lang.Throwable);
+    ctor public DigestException(java.lang.Throwable);
+  }
+
+  public class DigestInputStream extends java.io.FilterInputStream {
+    ctor public DigestInputStream(java.io.InputStream, java.security.MessageDigest);
+    method public java.security.MessageDigest getMessageDigest();
+    method public void on(boolean);
+    method public void setMessageDigest(java.security.MessageDigest);
+    field protected java.security.MessageDigest digest;
+  }
+
+  public class DigestOutputStream extends java.io.FilterOutputStream {
+    ctor public DigestOutputStream(java.io.OutputStream, java.security.MessageDigest);
+    method public java.security.MessageDigest getMessageDigest();
+    method public void on(boolean);
+    method public void setMessageDigest(java.security.MessageDigest);
+    field protected java.security.MessageDigest digest;
+  }
+
+  public abstract interface DomainCombiner {
+    method public abstract java.security.ProtectionDomain[] combine(java.security.ProtectionDomain[], java.security.ProtectionDomain[]);
+  }
+
+  public class GeneralSecurityException extends java.lang.Exception {
+    ctor public GeneralSecurityException(java.lang.String);
+    ctor public GeneralSecurityException();
+    ctor public GeneralSecurityException(java.lang.String, java.lang.Throwable);
+    ctor public GeneralSecurityException(java.lang.Throwable);
+  }
+
+  public abstract interface Guard {
+    method public abstract void checkGuard(java.lang.Object) throws java.lang.SecurityException;
+  }
+
+  public class GuardedObject implements java.io.Serializable {
+    ctor public GuardedObject(java.lang.Object, java.security.Guard);
+    method public java.lang.Object getObject() throws java.lang.SecurityException;
+  }
+
+  public abstract deprecated class Identity implements java.security.Principal java.io.Serializable {
+    ctor protected Identity();
+    ctor public Identity(java.lang.String);
+    ctor public Identity(java.lang.String, java.security.IdentityScope) throws java.security.KeyManagementException;
+    method public void addCertificate(java.security.Certificate) throws java.security.KeyManagementException;
+    method public java.security.Certificate[] certificates();
+    method public final boolean equals(java.lang.Object);
+    method public java.lang.String getInfo();
+    method public final java.lang.String getName();
+    method public java.security.PublicKey getPublicKey();
+    method public final java.security.IdentityScope getScope();
+    method protected boolean identityEquals(java.security.Identity);
+    method public void removeCertificate(java.security.Certificate) throws java.security.KeyManagementException;
+    method public void setInfo(java.lang.String);
+    method public void setPublicKey(java.security.PublicKey) throws java.security.KeyManagementException;
+    method public java.lang.String toString(boolean);
+  }
+
+  public abstract deprecated class IdentityScope extends java.security.Identity {
+    ctor protected IdentityScope();
+    ctor public IdentityScope(java.lang.String);
+    ctor public IdentityScope(java.lang.String, java.security.IdentityScope) throws java.security.KeyManagementException;
+    method public abstract void addIdentity(java.security.Identity) throws java.security.KeyManagementException;
+    method public abstract java.security.Identity getIdentity(java.lang.String);
+    method public java.security.Identity getIdentity(java.security.Principal);
+    method public abstract java.security.Identity getIdentity(java.security.PublicKey);
+    method public static java.security.IdentityScope getSystemScope();
+    method public abstract java.util.Enumeration<java.security.Identity> identities();
+    method public abstract void removeIdentity(java.security.Identity) throws java.security.KeyManagementException;
+    method protected static void setSystemScope(java.security.IdentityScope);
+    method public abstract int size();
+  }
+
+  public class InvalidAlgorithmParameterException extends java.security.GeneralSecurityException {
+    ctor public InvalidAlgorithmParameterException(java.lang.String);
+    ctor public InvalidAlgorithmParameterException();
+    ctor public InvalidAlgorithmParameterException(java.lang.String, java.lang.Throwable);
+    ctor public InvalidAlgorithmParameterException(java.lang.Throwable);
+  }
+
+  public class InvalidKeyException extends java.security.KeyException {
+    ctor public InvalidKeyException(java.lang.String);
+    ctor public InvalidKeyException();
+    ctor public InvalidKeyException(java.lang.String, java.lang.Throwable);
+    ctor public InvalidKeyException(java.lang.Throwable);
+  }
+
+  public class InvalidParameterException extends java.lang.IllegalArgumentException {
+    ctor public InvalidParameterException(java.lang.String);
+    ctor public InvalidParameterException();
+  }
+
+  public abstract interface Key implements java.io.Serializable {
+    method public abstract java.lang.String getAlgorithm();
+    method public abstract byte[] getEncoded();
+    method public abstract java.lang.String getFormat();
+    field public static final long serialVersionUID = 6603384152749567654L; // 0x5ba3eee69414eea6L
+  }
+
+  public class KeyException extends java.security.GeneralSecurityException {
+    ctor public KeyException(java.lang.String);
+    ctor public KeyException();
+    ctor public KeyException(java.lang.String, java.lang.Throwable);
+    ctor public KeyException(java.lang.Throwable);
+  }
+
+  public class KeyFactory {
+    ctor protected KeyFactory(java.security.KeyFactorySpi, java.security.Provider, java.lang.String);
+    method public final java.security.PrivateKey generatePrivate(java.security.spec.KeySpec) throws java.security.spec.InvalidKeySpecException;
+    method public final java.security.PublicKey generatePublic(java.security.spec.KeySpec) throws java.security.spec.InvalidKeySpecException;
+    method public final java.lang.String getAlgorithm();
+    method public static java.security.KeyFactory getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static java.security.KeyFactory getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static java.security.KeyFactory getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final T getKeySpec(java.security.Key, java.lang.Class<T>) throws java.security.spec.InvalidKeySpecException;
+    method public final java.security.Provider getProvider();
+    method public final java.security.Key translateKey(java.security.Key) throws java.security.InvalidKeyException;
+  }
+
+  public abstract class KeyFactorySpi {
+    ctor public KeyFactorySpi();
+    method protected abstract java.security.PrivateKey engineGeneratePrivate(java.security.spec.KeySpec) throws java.security.spec.InvalidKeySpecException;
+    method protected abstract java.security.PublicKey engineGeneratePublic(java.security.spec.KeySpec) throws java.security.spec.InvalidKeySpecException;
+    method protected abstract T engineGetKeySpec(java.security.Key, java.lang.Class<T>) throws java.security.spec.InvalidKeySpecException;
+    method protected abstract java.security.Key engineTranslateKey(java.security.Key) throws java.security.InvalidKeyException;
+  }
+
+  public class KeyManagementException extends java.security.KeyException {
+    ctor public KeyManagementException(java.lang.String);
+    ctor public KeyManagementException();
+    ctor public KeyManagementException(java.lang.String, java.lang.Throwable);
+    ctor public KeyManagementException(java.lang.Throwable);
+  }
+
+  public final class KeyPair implements java.io.Serializable {
+    ctor public KeyPair(java.security.PublicKey, java.security.PrivateKey);
+    method public java.security.PrivateKey getPrivate();
+    method public java.security.PublicKey getPublic();
+  }
+
+  public abstract class KeyPairGenerator extends java.security.KeyPairGeneratorSpi {
+    ctor protected KeyPairGenerator(java.lang.String);
+    method public final java.security.KeyPair genKeyPair();
+    method public java.security.KeyPair generateKeyPair();
+    method public java.lang.String getAlgorithm();
+    method public static java.security.KeyPairGenerator getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static java.security.KeyPairGenerator getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static java.security.KeyPairGenerator getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final java.security.Provider getProvider();
+    method public void initialize(int);
+    method public void initialize(java.security.spec.AlgorithmParameterSpec) throws java.security.InvalidAlgorithmParameterException;
+    method public void initialize(int, java.security.SecureRandom);
+  }
+
+  public abstract class KeyPairGeneratorSpi {
+    ctor public KeyPairGeneratorSpi();
+    method public abstract java.security.KeyPair generateKeyPair();
+    method public abstract void initialize(int, java.security.SecureRandom);
+    method public void initialize(java.security.spec.AlgorithmParameterSpec, java.security.SecureRandom) throws java.security.InvalidAlgorithmParameterException;
+  }
+
+  public class KeyRep implements java.io.Serializable {
+    ctor public KeyRep(java.security.KeyRep.Type, java.lang.String, java.lang.String, byte[]);
+    method protected java.lang.Object readResolve() throws java.io.ObjectStreamException;
+  }
+
+  public static final class KeyRep.Type extends java.lang.Enum {
+    method public static java.security.KeyRep.Type valueOf(java.lang.String);
+    method public static final java.security.KeyRep.Type[] values();
+    enum_constant public static final java.security.KeyRep.Type PRIVATE;
+    enum_constant public static final java.security.KeyRep.Type PUBLIC;
+    enum_constant public static final java.security.KeyRep.Type SECRET;
+  }
+
+  public class KeyStore {
+    ctor protected KeyStore(java.security.KeyStoreSpi, java.security.Provider, java.lang.String);
+    method public final java.util.Enumeration<java.lang.String> aliases() throws java.security.KeyStoreException;
+    method public final boolean containsAlias(java.lang.String) throws java.security.KeyStoreException;
+    method public final void deleteEntry(java.lang.String) throws java.security.KeyStoreException;
+    method public final boolean entryInstanceOf(java.lang.String, java.lang.Class<? extends java.security.KeyStore.Entry>) throws java.security.KeyStoreException;
+    method public final java.security.cert.Certificate getCertificate(java.lang.String) throws java.security.KeyStoreException;
+    method public final java.lang.String getCertificateAlias(java.security.cert.Certificate) throws java.security.KeyStoreException;
+    method public final java.security.cert.Certificate[] getCertificateChain(java.lang.String) throws java.security.KeyStoreException;
+    method public final java.util.Date getCreationDate(java.lang.String) throws java.security.KeyStoreException;
+    method public static final java.lang.String getDefaultType();
+    method public final java.security.KeyStore.Entry getEntry(java.lang.String, java.security.KeyStore.ProtectionParameter) throws java.security.KeyStoreException, java.security.NoSuchAlgorithmException, java.security.UnrecoverableEntryException;
+    method public static java.security.KeyStore getInstance(java.lang.String) throws java.security.KeyStoreException;
+    method public static java.security.KeyStore getInstance(java.lang.String, java.lang.String) throws java.security.KeyStoreException, java.security.NoSuchProviderException;
+    method public static java.security.KeyStore getInstance(java.lang.String, java.security.Provider) throws java.security.KeyStoreException;
+    method public final java.security.Key getKey(java.lang.String, char[]) throws java.security.KeyStoreException, java.security.NoSuchAlgorithmException, java.security.UnrecoverableKeyException;
+    method public final java.security.Provider getProvider();
+    method public final java.lang.String getType();
+    method public final boolean isCertificateEntry(java.lang.String) throws java.security.KeyStoreException;
+    method public final boolean isKeyEntry(java.lang.String) throws java.security.KeyStoreException;
+    method public final void load(java.io.InputStream, char[]) throws java.security.cert.CertificateException, java.io.IOException, java.security.NoSuchAlgorithmException;
+    method public final void load(java.security.KeyStore.LoadStoreParameter) throws java.security.cert.CertificateException, java.io.IOException, java.security.NoSuchAlgorithmException;
+    method public final void setCertificateEntry(java.lang.String, java.security.cert.Certificate) throws java.security.KeyStoreException;
+    method public final void setEntry(java.lang.String, java.security.KeyStore.Entry, java.security.KeyStore.ProtectionParameter) throws java.security.KeyStoreException;
+    method public final void setKeyEntry(java.lang.String, java.security.Key, char[], java.security.cert.Certificate[]) throws java.security.KeyStoreException;
+    method public final void setKeyEntry(java.lang.String, byte[], java.security.cert.Certificate[]) throws java.security.KeyStoreException;
+    method public final int size() throws java.security.KeyStoreException;
+    method public final void store(java.io.OutputStream, char[]) throws java.security.cert.CertificateException, java.io.IOException, java.security.KeyStoreException, java.security.NoSuchAlgorithmException;
+    method public final void store(java.security.KeyStore.LoadStoreParameter) throws java.security.cert.CertificateException, java.io.IOException, java.security.KeyStoreException, java.security.NoSuchAlgorithmException;
+  }
+
+  public static abstract class KeyStore.Builder {
+    ctor protected KeyStore.Builder();
+    method public abstract java.security.KeyStore getKeyStore() throws java.security.KeyStoreException;
+    method public abstract java.security.KeyStore.ProtectionParameter getProtectionParameter(java.lang.String) throws java.security.KeyStoreException;
+    method public static java.security.KeyStore.Builder newInstance(java.security.KeyStore, java.security.KeyStore.ProtectionParameter);
+    method public static java.security.KeyStore.Builder newInstance(java.lang.String, java.security.Provider, java.io.File, java.security.KeyStore.ProtectionParameter);
+    method public static java.security.KeyStore.Builder newInstance(java.lang.String, java.security.Provider, java.security.KeyStore.ProtectionParameter);
+  }
+
+  public static class KeyStore.CallbackHandlerProtection implements java.security.KeyStore.ProtectionParameter {
+    ctor public KeyStore.CallbackHandlerProtection(javax.security.auth.callback.CallbackHandler);
+    method public javax.security.auth.callback.CallbackHandler getCallbackHandler();
+  }
+
+  public static abstract interface KeyStore.Entry {
+  }
+
+  public static abstract interface KeyStore.LoadStoreParameter {
+    method public abstract java.security.KeyStore.ProtectionParameter getProtectionParameter();
+  }
+
+  public static class KeyStore.PasswordProtection implements javax.security.auth.Destroyable java.security.KeyStore.ProtectionParameter {
+    ctor public KeyStore.PasswordProtection(char[]);
+    method public synchronized void destroy() throws javax.security.auth.DestroyFailedException;
+    method public synchronized char[] getPassword();
+    method public synchronized boolean isDestroyed();
+  }
+
+  public static final class KeyStore.PrivateKeyEntry implements java.security.KeyStore.Entry {
+    ctor public KeyStore.PrivateKeyEntry(java.security.PrivateKey, java.security.cert.Certificate[]);
+    method public java.security.cert.Certificate getCertificate();
+    method public java.security.cert.Certificate[] getCertificateChain();
+    method public java.security.PrivateKey getPrivateKey();
+  }
+
+  public static abstract interface KeyStore.ProtectionParameter {
+  }
+
+  public static final class KeyStore.SecretKeyEntry implements java.security.KeyStore.Entry {
+    ctor public KeyStore.SecretKeyEntry(javax.crypto.SecretKey);
+    method public javax.crypto.SecretKey getSecretKey();
+  }
+
+  public static final class KeyStore.TrustedCertificateEntry implements java.security.KeyStore.Entry {
+    ctor public KeyStore.TrustedCertificateEntry(java.security.cert.Certificate);
+    method public java.security.cert.Certificate getTrustedCertificate();
+  }
+
+  public class KeyStoreException extends java.security.GeneralSecurityException {
+    ctor public KeyStoreException(java.lang.String);
+    ctor public KeyStoreException();
+    ctor public KeyStoreException(java.lang.String, java.lang.Throwable);
+    ctor public KeyStoreException(java.lang.Throwable);
+  }
+
+  public abstract class KeyStoreSpi {
+    ctor public KeyStoreSpi();
+    method public abstract java.util.Enumeration<java.lang.String> engineAliases();
+    method public abstract boolean engineContainsAlias(java.lang.String);
+    method public abstract void engineDeleteEntry(java.lang.String) throws java.security.KeyStoreException;
+    method public boolean engineEntryInstanceOf(java.lang.String, java.lang.Class<? extends java.security.KeyStore.Entry>);
+    method public abstract java.security.cert.Certificate engineGetCertificate(java.lang.String);
+    method public abstract java.lang.String engineGetCertificateAlias(java.security.cert.Certificate);
+    method public abstract java.security.cert.Certificate[] engineGetCertificateChain(java.lang.String);
+    method public abstract java.util.Date engineGetCreationDate(java.lang.String);
+    method public java.security.KeyStore.Entry engineGetEntry(java.lang.String, java.security.KeyStore.ProtectionParameter) throws java.security.KeyStoreException, java.security.NoSuchAlgorithmException, java.security.UnrecoverableEntryException;
+    method public abstract java.security.Key engineGetKey(java.lang.String, char[]) throws java.security.NoSuchAlgorithmException, java.security.UnrecoverableKeyException;
+    method public abstract boolean engineIsCertificateEntry(java.lang.String);
+    method public abstract boolean engineIsKeyEntry(java.lang.String);
+    method public abstract void engineLoad(java.io.InputStream, char[]) throws java.security.cert.CertificateException, java.io.IOException, java.security.NoSuchAlgorithmException;
+    method public void engineLoad(java.security.KeyStore.LoadStoreParameter) throws java.security.cert.CertificateException, java.io.IOException, java.security.NoSuchAlgorithmException;
+    method public abstract void engineSetCertificateEntry(java.lang.String, java.security.cert.Certificate) throws java.security.KeyStoreException;
+    method public void engineSetEntry(java.lang.String, java.security.KeyStore.Entry, java.security.KeyStore.ProtectionParameter) throws java.security.KeyStoreException;
+    method public abstract void engineSetKeyEntry(java.lang.String, java.security.Key, char[], java.security.cert.Certificate[]) throws java.security.KeyStoreException;
+    method public abstract void engineSetKeyEntry(java.lang.String, byte[], java.security.cert.Certificate[]) throws java.security.KeyStoreException;
+    method public abstract int engineSize();
+    method public abstract void engineStore(java.io.OutputStream, char[]) throws java.security.cert.CertificateException, java.io.IOException, java.security.NoSuchAlgorithmException;
+    method public void engineStore(java.security.KeyStore.LoadStoreParameter) throws java.security.cert.CertificateException, java.io.IOException, java.security.NoSuchAlgorithmException;
+  }
+
+  public abstract class MessageDigest extends java.security.MessageDigestSpi {
+    ctor protected MessageDigest(java.lang.String);
+    method public byte[] digest();
+    method public int digest(byte[], int, int) throws java.security.DigestException;
+    method public byte[] digest(byte[]);
+    method public final java.lang.String getAlgorithm();
+    method public final int getDigestLength();
+    method public static java.security.MessageDigest getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static java.security.MessageDigest getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static java.security.MessageDigest getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final java.security.Provider getProvider();
+    method public static boolean isEqual(byte[], byte[]);
+    method public void reset();
+    method public void update(byte);
+    method public void update(byte[], int, int);
+    method public void update(byte[]);
+    method public final void update(java.nio.ByteBuffer);
+  }
+
+  public abstract class MessageDigestSpi {
+    ctor public MessageDigestSpi();
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method protected abstract byte[] engineDigest();
+    method protected int engineDigest(byte[], int, int) throws java.security.DigestException;
+    method protected int engineGetDigestLength();
+    method protected abstract void engineReset();
+    method protected abstract void engineUpdate(byte);
+    method protected abstract void engineUpdate(byte[], int, int);
+    method protected void engineUpdate(java.nio.ByteBuffer);
+  }
+
+  public class NoSuchAlgorithmException extends java.security.GeneralSecurityException {
+    ctor public NoSuchAlgorithmException(java.lang.String);
+    ctor public NoSuchAlgorithmException();
+    ctor public NoSuchAlgorithmException(java.lang.String, java.lang.Throwable);
+    ctor public NoSuchAlgorithmException(java.lang.Throwable);
+  }
+
+  public class NoSuchProviderException extends java.security.GeneralSecurityException {
+    ctor public NoSuchProviderException(java.lang.String);
+    ctor public NoSuchProviderException();
+  }
+
+  public abstract class Permission implements java.security.Guard java.io.Serializable {
+    ctor public Permission(java.lang.String);
+    method public void checkGuard(java.lang.Object) throws java.lang.SecurityException;
+    method public abstract java.lang.String getActions();
+    method public final java.lang.String getName();
+    method public abstract boolean implies(java.security.Permission);
+    method public java.security.PermissionCollection newPermissionCollection();
+  }
+
+  public abstract class PermissionCollection implements java.io.Serializable {
+    ctor public PermissionCollection();
+    method public abstract void add(java.security.Permission);
+    method public abstract java.util.Enumeration<java.security.Permission> elements();
+    method public abstract boolean implies(java.security.Permission);
+    method public boolean isReadOnly();
+    method public void setReadOnly();
+  }
+
+  public final class Permissions extends java.security.PermissionCollection implements java.io.Serializable {
+    ctor public Permissions();
+    method public void add(java.security.Permission);
+    method public java.util.Enumeration<java.security.Permission> elements();
+    method public boolean implies(java.security.Permission);
+  }
+
+  public abstract class Policy {
+    ctor public Policy();
+    method public static java.security.Policy getInstance(java.lang.String, java.security.Policy.Parameters) throws java.security.NoSuchAlgorithmException;
+    method public static java.security.Policy getInstance(java.lang.String, java.security.Policy.Parameters, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static java.security.Policy getInstance(java.lang.String, java.security.Policy.Parameters, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public java.security.Policy.Parameters getParameters();
+    method public java.security.PermissionCollection getPermissions(java.security.CodeSource);
+    method public java.security.PermissionCollection getPermissions(java.security.ProtectionDomain);
+    method public static java.security.Policy getPolicy();
+    method public java.security.Provider getProvider();
+    method public java.lang.String getType();
+    method public boolean implies(java.security.ProtectionDomain, java.security.Permission);
+    method public void refresh();
+    method public static void setPolicy(java.security.Policy);
+    field public static final java.security.PermissionCollection UNSUPPORTED_EMPTY_COLLECTION;
+  }
+
+  public static abstract interface Policy.Parameters {
+  }
+
+  public abstract class PolicySpi {
+    ctor public PolicySpi();
+    method protected java.security.PermissionCollection engineGetPermissions(java.security.CodeSource);
+    method protected java.security.PermissionCollection engineGetPermissions(java.security.ProtectionDomain);
+    method protected abstract boolean engineImplies(java.security.ProtectionDomain, java.security.Permission);
+    method protected void engineRefresh();
+  }
+
+  public abstract interface Principal {
+    method public abstract boolean equals(java.lang.Object);
+    method public abstract java.lang.String getName();
+    method public abstract int hashCode();
+    method public abstract java.lang.String toString();
+  }
+
+  public abstract interface PrivateKey implements java.security.Key {
+    field public static final long serialVersionUID = 6034044314589513430L; // 0x53bd3b559a12c6d6L
+  }
+
+  public abstract interface PrivilegedAction {
+    method public abstract T run();
+  }
+
+  public class PrivilegedActionException extends java.lang.Exception {
+    ctor public PrivilegedActionException(java.lang.Exception);
+    method public java.lang.Exception getException();
+  }
+
+  public abstract interface PrivilegedExceptionAction {
+    method public abstract T run() throws java.lang.Exception;
+  }
+
+  public class ProtectionDomain {
+    ctor public ProtectionDomain(java.security.CodeSource, java.security.PermissionCollection);
+    ctor public ProtectionDomain(java.security.CodeSource, java.security.PermissionCollection, java.lang.ClassLoader, java.security.Principal[]);
+    method public final java.lang.ClassLoader getClassLoader();
+    method public final java.security.CodeSource getCodeSource();
+    method public final java.security.PermissionCollection getPermissions();
+    method public final java.security.Principal[] getPrincipals();
+    method public boolean implies(java.security.Permission);
+  }
+
+  public abstract class Provider extends java.util.Properties {
+    ctor protected Provider(java.lang.String, double, java.lang.String);
+    method public java.lang.String getInfo();
+    method public java.lang.String getName();
+    method public synchronized java.security.Provider.Service getService(java.lang.String, java.lang.String);
+    method public synchronized java.util.Set<java.security.Provider.Service> getServices();
+    method public double getVersion();
+    method public synchronized java.lang.Object put(java.lang.Object, java.lang.Object);
+    method public synchronized void putAll(java.util.Map<?, ?>);
+    method protected synchronized void putService(java.security.Provider.Service);
+    method protected synchronized void removeService(java.security.Provider.Service);
+  }
+
+  public static class Provider.Service {
+    ctor public Provider.Service(java.security.Provider, java.lang.String, java.lang.String, java.lang.String, java.util.List<java.lang.String>, java.util.Map<java.lang.String, java.lang.String>);
+    method public final java.lang.String getAlgorithm();
+    method public final java.lang.String getAttribute(java.lang.String);
+    method public final java.lang.String getClassName();
+    method public final java.security.Provider getProvider();
+    method public final java.lang.String getType();
+    method public java.lang.Object newInstance(java.lang.Object) throws java.security.NoSuchAlgorithmException;
+    method public boolean supportsParameter(java.lang.Object);
+  }
+
+  public class ProviderException extends java.lang.RuntimeException {
+    ctor public ProviderException(java.lang.String);
+    ctor public ProviderException();
+    ctor public ProviderException(java.lang.String, java.lang.Throwable);
+    ctor public ProviderException(java.lang.Throwable);
+  }
+
+  public abstract interface PublicKey implements java.security.Key {
+    field public static final long serialVersionUID = 7187392471159151072L; // 0x63bebf5f40c219e0L
+  }
+
+  public class SecureClassLoader extends java.lang.ClassLoader {
+    ctor protected SecureClassLoader();
+    ctor protected SecureClassLoader(java.lang.ClassLoader);
+    method protected final java.lang.Class<?> defineClass(java.lang.String, byte[], int, int, java.security.CodeSource);
+    method protected final java.lang.Class<?> defineClass(java.lang.String, java.nio.ByteBuffer, java.security.CodeSource);
+    method protected java.security.PermissionCollection getPermissions(java.security.CodeSource);
+  }
+
+  public class SecureRandom extends java.util.Random {
+    ctor public SecureRandom();
+    ctor public SecureRandom(byte[]);
+    ctor protected SecureRandom(java.security.SecureRandomSpi, java.security.Provider);
+    method public byte[] generateSeed(int);
+    method public java.lang.String getAlgorithm();
+    method public static java.security.SecureRandom getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static java.security.SecureRandom getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static java.security.SecureRandom getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final java.security.Provider getProvider();
+    method public static byte[] getSeed(int);
+    method protected final int next(int);
+    method public synchronized void setSeed(byte[]);
+  }
+
+  public abstract class SecureRandomSpi implements java.io.Serializable {
+    ctor public SecureRandomSpi();
+    method protected abstract byte[] engineGenerateSeed(int);
+    method protected abstract void engineNextBytes(byte[]);
+    method protected abstract void engineSetSeed(byte[]);
+  }
+
+  public final class Security {
+    method public static int addProvider(java.security.Provider);
+    method public static deprecated java.lang.String getAlgorithmProperty(java.lang.String, java.lang.String);
+    method public static java.util.Set<java.lang.String> getAlgorithms(java.lang.String);
+    method public static java.lang.String getProperty(java.lang.String);
+    method public static synchronized java.security.Provider getProvider(java.lang.String);
+    method public static synchronized java.security.Provider[] getProviders();
+    method public static java.security.Provider[] getProviders(java.lang.String);
+    method public static synchronized java.security.Provider[] getProviders(java.util.Map<java.lang.String, java.lang.String>);
+    method public static synchronized int insertProviderAt(java.security.Provider, int);
+    method public static synchronized void removeProvider(java.lang.String);
+    method public static void setProperty(java.lang.String, java.lang.String);
+  }
+
+  public final class SecurityPermission extends java.security.BasicPermission {
+    ctor public SecurityPermission(java.lang.String);
+    ctor public SecurityPermission(java.lang.String, java.lang.String);
+  }
+
+  public abstract class Signature extends java.security.SignatureSpi {
+    ctor protected Signature(java.lang.String);
+    method public final java.lang.String getAlgorithm();
+    method public static java.security.Signature getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static java.security.Signature getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static java.security.Signature getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final deprecated java.lang.Object getParameter(java.lang.String) throws java.security.InvalidParameterException;
+    method public final java.security.AlgorithmParameters getParameters();
+    method public final java.security.Provider getProvider();
+    method public final void initSign(java.security.PrivateKey) throws java.security.InvalidKeyException;
+    method public final void initSign(java.security.PrivateKey, java.security.SecureRandom) throws java.security.InvalidKeyException;
+    method public final void initVerify(java.security.PublicKey) throws java.security.InvalidKeyException;
+    method public final void initVerify(java.security.cert.Certificate) throws java.security.InvalidKeyException;
+    method public final deprecated void setParameter(java.lang.String, java.lang.Object) throws java.security.InvalidParameterException;
+    method public final void setParameter(java.security.spec.AlgorithmParameterSpec) throws java.security.InvalidAlgorithmParameterException;
+    method public final byte[] sign() throws java.security.SignatureException;
+    method public final int sign(byte[], int, int) throws java.security.SignatureException;
+    method public final void update(byte) throws java.security.SignatureException;
+    method public final void update(byte[]) throws java.security.SignatureException;
+    method public final void update(byte[], int, int) throws java.security.SignatureException;
+    method public final void update(java.nio.ByteBuffer) throws java.security.SignatureException;
+    method public final boolean verify(byte[]) throws java.security.SignatureException;
+    method public final boolean verify(byte[], int, int) throws java.security.SignatureException;
+    field protected static final int SIGN = 2; // 0x2
+    field protected static final int UNINITIALIZED = 0; // 0x0
+    field protected static final int VERIFY = 3; // 0x3
+    field protected int state;
+  }
+
+  public class SignatureException extends java.security.GeneralSecurityException {
+    ctor public SignatureException(java.lang.String);
+    ctor public SignatureException();
+    ctor public SignatureException(java.lang.String, java.lang.Throwable);
+    ctor public SignatureException(java.lang.Throwable);
+  }
+
+  public abstract class SignatureSpi {
+    ctor public SignatureSpi();
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method protected abstract deprecated java.lang.Object engineGetParameter(java.lang.String) throws java.security.InvalidParameterException;
+    method protected java.security.AlgorithmParameters engineGetParameters();
+    method protected abstract void engineInitSign(java.security.PrivateKey) throws java.security.InvalidKeyException;
+    method protected void engineInitSign(java.security.PrivateKey, java.security.SecureRandom) throws java.security.InvalidKeyException;
+    method protected abstract void engineInitVerify(java.security.PublicKey) throws java.security.InvalidKeyException;
+    method protected abstract deprecated void engineSetParameter(java.lang.String, java.lang.Object) throws java.security.InvalidParameterException;
+    method protected void engineSetParameter(java.security.spec.AlgorithmParameterSpec) throws java.security.InvalidAlgorithmParameterException;
+    method protected abstract byte[] engineSign() throws java.security.SignatureException;
+    method protected int engineSign(byte[], int, int) throws java.security.SignatureException;
+    method protected abstract void engineUpdate(byte) throws java.security.SignatureException;
+    method protected abstract void engineUpdate(byte[], int, int) throws java.security.SignatureException;
+    method protected void engineUpdate(java.nio.ByteBuffer);
+    method protected abstract boolean engineVerify(byte[]) throws java.security.SignatureException;
+    method protected boolean engineVerify(byte[], int, int) throws java.security.SignatureException;
+    field protected java.security.SecureRandom appRandom;
+  }
+
+  public final class SignedObject implements java.io.Serializable {
+    ctor public SignedObject(java.io.Serializable, java.security.PrivateKey, java.security.Signature) throws java.io.IOException, java.security.InvalidKeyException, java.security.SignatureException;
+    method public java.lang.String getAlgorithm();
+    method public java.lang.Object getObject() throws java.lang.ClassNotFoundException, java.io.IOException;
+    method public byte[] getSignature();
+    method public boolean verify(java.security.PublicKey, java.security.Signature) throws java.security.InvalidKeyException, java.security.SignatureException;
+  }
+
+  public abstract deprecated class Signer extends java.security.Identity {
+    ctor protected Signer();
+    ctor public Signer(java.lang.String);
+    ctor public Signer(java.lang.String, java.security.IdentityScope) throws java.security.KeyManagementException;
+    method public java.security.PrivateKey getPrivateKey();
+    method public final void setKeyPair(java.security.KeyPair) throws java.security.InvalidParameterException, java.security.KeyException;
+  }
+
+  public final class Timestamp implements java.io.Serializable {
+    ctor public Timestamp(java.util.Date, java.security.cert.CertPath);
+    method public java.security.cert.CertPath getSignerCertPath();
+    method public java.util.Date getTimestamp();
+  }
+
+  public class UnrecoverableEntryException extends java.security.GeneralSecurityException {
+    ctor public UnrecoverableEntryException();
+    ctor public UnrecoverableEntryException(java.lang.String);
+  }
+
+  public class UnrecoverableKeyException extends java.security.UnrecoverableEntryException {
+    ctor public UnrecoverableKeyException(java.lang.String);
+    ctor public UnrecoverableKeyException();
+  }
+
+  public final class UnresolvedPermission extends java.security.Permission implements java.io.Serializable {
+    ctor public UnresolvedPermission(java.lang.String, java.lang.String, java.lang.String, java.security.cert.Certificate[]);
+    method public java.lang.String getActions();
+    method public java.lang.String getUnresolvedActions();
+    method public java.security.cert.Certificate[] getUnresolvedCerts();
+    method public java.lang.String getUnresolvedName();
+    method public java.lang.String getUnresolvedType();
+    method public boolean implies(java.security.Permission);
+  }
+
+}
+
+package java.security.acl {
+
+  public abstract interface Acl implements java.security.acl.Owner {
+    method public abstract boolean addEntry(java.security.Principal, java.security.acl.AclEntry) throws java.security.acl.NotOwnerException;
+    method public abstract boolean checkPermission(java.security.Principal, java.security.acl.Permission);
+    method public abstract java.util.Enumeration<java.security.acl.AclEntry> entries();
+    method public abstract java.lang.String getName();
+    method public abstract java.util.Enumeration<java.security.acl.Permission> getPermissions(java.security.Principal);
+    method public abstract boolean removeEntry(java.security.Principal, java.security.acl.AclEntry) throws java.security.acl.NotOwnerException;
+    method public abstract void setName(java.security.Principal, java.lang.String) throws java.security.acl.NotOwnerException;
+    method public abstract java.lang.String toString();
+  }
+
+  public abstract interface AclEntry implements java.lang.Cloneable {
+    method public abstract boolean addPermission(java.security.acl.Permission);
+    method public abstract boolean checkPermission(java.security.acl.Permission);
+    method public abstract java.lang.Object clone();
+    method public abstract java.security.Principal getPrincipal();
+    method public abstract boolean isNegative();
+    method public abstract java.util.Enumeration<java.security.acl.Permission> permissions();
+    method public abstract boolean removePermission(java.security.acl.Permission);
+    method public abstract void setNegativePermissions();
+    method public abstract boolean setPrincipal(java.security.Principal);
+    method public abstract java.lang.String toString();
+  }
+
+  public class AclNotFoundException extends java.lang.Exception {
+    ctor public AclNotFoundException();
+  }
+
+  public abstract interface Group implements java.security.Principal {
+    method public abstract boolean addMember(java.security.Principal);
+    method public abstract boolean isMember(java.security.Principal);
+    method public abstract java.util.Enumeration<? extends java.security.Principal> members();
+    method public abstract boolean removeMember(java.security.Principal);
+  }
+
+  public class LastOwnerException extends java.lang.Exception {
+    ctor public LastOwnerException();
+  }
+
+  public class NotOwnerException extends java.lang.Exception {
+    ctor public NotOwnerException();
+  }
+
+  public abstract interface Owner {
+    method public abstract boolean addOwner(java.security.Principal, java.security.Principal) throws java.security.acl.NotOwnerException;
+    method public abstract boolean deleteOwner(java.security.Principal, java.security.Principal) throws java.security.acl.LastOwnerException, java.security.acl.NotOwnerException;
+    method public abstract boolean isOwner(java.security.Principal);
+  }
+
+  public abstract interface Permission {
+    method public abstract boolean equals(java.lang.Object);
+    method public abstract java.lang.String toString();
+  }
+
+}
+
+package java.security.cert {
+
+  public abstract class CRL {
+    ctor protected CRL(java.lang.String);
+    method public final java.lang.String getType();
+    method public abstract boolean isRevoked(java.security.cert.Certificate);
+    method public abstract java.lang.String toString();
+  }
+
+  public class CRLException extends java.security.GeneralSecurityException {
+    ctor public CRLException(java.lang.String);
+    ctor public CRLException();
+    ctor public CRLException(java.lang.String, java.lang.Throwable);
+    ctor public CRLException(java.lang.Throwable);
+  }
+
+  public abstract interface CRLSelector implements java.lang.Cloneable {
+    method public abstract java.lang.Object clone();
+    method public abstract boolean match(java.security.cert.CRL);
+  }
+
+  public abstract class CertPath implements java.io.Serializable {
+    ctor protected CertPath(java.lang.String);
+    method public abstract java.util.List<? extends java.security.cert.Certificate> getCertificates();
+    method public abstract byte[] getEncoded() throws java.security.cert.CertificateEncodingException;
+    method public abstract byte[] getEncoded(java.lang.String) throws java.security.cert.CertificateEncodingException;
+    method public abstract java.util.Iterator<java.lang.String> getEncodings();
+    method public java.lang.String getType();
+    method protected java.lang.Object writeReplace() throws java.io.ObjectStreamException;
+  }
+
+  protected static class CertPath.CertPathRep implements java.io.Serializable {
+    ctor protected CertPath.CertPathRep(java.lang.String, byte[]);
+    method protected java.lang.Object readResolve() throws java.io.ObjectStreamException;
+  }
+
+  public class CertPathBuilder {
+    ctor protected CertPathBuilder(java.security.cert.CertPathBuilderSpi, java.security.Provider, java.lang.String);
+    method public final java.security.cert.CertPathBuilderResult build(java.security.cert.CertPathParameters) throws java.security.cert.CertPathBuilderException, java.security.InvalidAlgorithmParameterException;
+    method public final java.lang.String getAlgorithm();
+    method public static final java.lang.String getDefaultType();
+    method public static java.security.cert.CertPathBuilder getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static java.security.cert.CertPathBuilder getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static java.security.cert.CertPathBuilder getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final java.security.Provider getProvider();
+  }
+
+  public class CertPathBuilderException extends java.security.GeneralSecurityException {
+    ctor public CertPathBuilderException(java.lang.String, java.lang.Throwable);
+    ctor public CertPathBuilderException(java.lang.Throwable);
+    ctor public CertPathBuilderException(java.lang.String);
+    ctor public CertPathBuilderException();
+  }
+
+  public abstract interface CertPathBuilderResult implements java.lang.Cloneable {
+    method public abstract java.lang.Object clone();
+    method public abstract java.security.cert.CertPath getCertPath();
+  }
+
+  public abstract class CertPathBuilderSpi {
+    ctor public CertPathBuilderSpi();
+    method public abstract java.security.cert.CertPathBuilderResult engineBuild(java.security.cert.CertPathParameters) throws java.security.cert.CertPathBuilderException, java.security.InvalidAlgorithmParameterException;
+  }
+
+  public abstract interface CertPathParameters implements java.lang.Cloneable {
+    method public abstract java.lang.Object clone();
+  }
+
+  public class CertPathValidator {
+    ctor protected CertPathValidator(java.security.cert.CertPathValidatorSpi, java.security.Provider, java.lang.String);
+    method public final java.lang.String getAlgorithm();
+    method public static final java.lang.String getDefaultType();
+    method public static java.security.cert.CertPathValidator getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static java.security.cert.CertPathValidator getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static java.security.cert.CertPathValidator getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final java.security.Provider getProvider();
+    method public final java.security.cert.CertPathValidatorResult validate(java.security.cert.CertPath, java.security.cert.CertPathParameters) throws java.security.cert.CertPathValidatorException, java.security.InvalidAlgorithmParameterException;
+  }
+
+  public class CertPathValidatorException extends java.security.GeneralSecurityException {
+    ctor public CertPathValidatorException(java.lang.String, java.lang.Throwable, java.security.cert.CertPath, int);
+    ctor public CertPathValidatorException(java.lang.String, java.lang.Throwable);
+    ctor public CertPathValidatorException(java.lang.Throwable);
+    ctor public CertPathValidatorException(java.lang.String);
+    ctor public CertPathValidatorException();
+    method public java.security.cert.CertPath getCertPath();
+    method public int getIndex();
+  }
+
+  public abstract interface CertPathValidatorResult implements java.lang.Cloneable {
+    method public abstract java.lang.Object clone();
+  }
+
+  public abstract class CertPathValidatorSpi {
+    ctor public CertPathValidatorSpi();
+    method public abstract java.security.cert.CertPathValidatorResult engineValidate(java.security.cert.CertPath, java.security.cert.CertPathParameters) throws java.security.cert.CertPathValidatorException, java.security.InvalidAlgorithmParameterException;
+  }
+
+  public abstract interface CertSelector implements java.lang.Cloneable {
+    method public abstract java.lang.Object clone();
+    method public abstract boolean match(java.security.cert.Certificate);
+  }
+
+  public class CertStore {
+    ctor protected CertStore(java.security.cert.CertStoreSpi, java.security.Provider, java.lang.String, java.security.cert.CertStoreParameters);
+    method public final java.util.Collection<? extends java.security.cert.CRL> getCRLs(java.security.cert.CRLSelector) throws java.security.cert.CertStoreException;
+    method public final java.security.cert.CertStoreParameters getCertStoreParameters();
+    method public final java.util.Collection<? extends java.security.cert.Certificate> getCertificates(java.security.cert.CertSelector) throws java.security.cert.CertStoreException;
+    method public static final java.lang.String getDefaultType();
+    method public static java.security.cert.CertStore getInstance(java.lang.String, java.security.cert.CertStoreParameters) throws java.security.InvalidAlgorithmParameterException, java.security.NoSuchAlgorithmException;
+    method public static java.security.cert.CertStore getInstance(java.lang.String, java.security.cert.CertStoreParameters, java.lang.String) throws java.security.InvalidAlgorithmParameterException, java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static java.security.cert.CertStore getInstance(java.lang.String, java.security.cert.CertStoreParameters, java.security.Provider) throws java.security.InvalidAlgorithmParameterException, java.security.NoSuchAlgorithmException;
+    method public final java.security.Provider getProvider();
+    method public final java.lang.String getType();
+  }
+
+  public class CertStoreException extends java.security.GeneralSecurityException {
+    ctor public CertStoreException(java.lang.String, java.lang.Throwable);
+    ctor public CertStoreException(java.lang.Throwable);
+    ctor public CertStoreException(java.lang.String);
+    ctor public CertStoreException();
+  }
+
+  public abstract interface CertStoreParameters implements java.lang.Cloneable {
+    method public abstract java.lang.Object clone();
+  }
+
+  public abstract class CertStoreSpi {
+    ctor public CertStoreSpi(java.security.cert.CertStoreParameters) throws java.security.InvalidAlgorithmParameterException;
+    method public abstract java.util.Collection<? extends java.security.cert.CRL> engineGetCRLs(java.security.cert.CRLSelector) throws java.security.cert.CertStoreException;
+    method public abstract java.util.Collection<? extends java.security.cert.Certificate> engineGetCertificates(java.security.cert.CertSelector) throws java.security.cert.CertStoreException;
+  }
+
+  public abstract class Certificate implements java.io.Serializable {
+    ctor protected Certificate(java.lang.String);
+    method public abstract byte[] getEncoded() throws java.security.cert.CertificateEncodingException;
+    method public abstract java.security.PublicKey getPublicKey();
+    method public final java.lang.String getType();
+    method public abstract java.lang.String toString();
+    method public abstract void verify(java.security.PublicKey) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException, java.security.SignatureException;
+    method public abstract void verify(java.security.PublicKey, java.lang.String) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException, java.security.SignatureException;
+    method protected java.lang.Object writeReplace() throws java.io.ObjectStreamException;
+  }
+
+  protected static class Certificate.CertificateRep implements java.io.Serializable {
+    ctor protected Certificate.CertificateRep(java.lang.String, byte[]);
+    method protected java.lang.Object readResolve() throws java.io.ObjectStreamException;
+  }
+
+  public class CertificateEncodingException extends java.security.cert.CertificateException {
+    ctor public CertificateEncodingException(java.lang.String);
+    ctor public CertificateEncodingException();
+    ctor public CertificateEncodingException(java.lang.String, java.lang.Throwable);
+    ctor public CertificateEncodingException(java.lang.Throwable);
+  }
+
+  public class CertificateException extends java.security.GeneralSecurityException {
+    ctor public CertificateException(java.lang.String);
+    ctor public CertificateException();
+    ctor public CertificateException(java.lang.String, java.lang.Throwable);
+    ctor public CertificateException(java.lang.Throwable);
+  }
+
+  public class CertificateExpiredException extends java.security.cert.CertificateException {
+    ctor public CertificateExpiredException(java.lang.String);
+    ctor public CertificateExpiredException();
+  }
+
+  public class CertificateFactory {
+    ctor protected CertificateFactory(java.security.cert.CertificateFactorySpi, java.security.Provider, java.lang.String);
+    method public final java.security.cert.CRL generateCRL(java.io.InputStream) throws java.security.cert.CRLException;
+    method public final java.util.Collection<? extends java.security.cert.CRL> generateCRLs(java.io.InputStream) throws java.security.cert.CRLException;
+    method public final java.security.cert.CertPath generateCertPath(java.io.InputStream) throws java.security.cert.CertificateException;
+    method public final java.security.cert.CertPath generateCertPath(java.io.InputStream, java.lang.String) throws java.security.cert.CertificateException;
+    method public final java.security.cert.CertPath generateCertPath(java.util.List<? extends java.security.cert.Certificate>) throws java.security.cert.CertificateException;
+    method public final java.security.cert.Certificate generateCertificate(java.io.InputStream) throws java.security.cert.CertificateException;
+    method public final java.util.Collection<? extends java.security.cert.Certificate> generateCertificates(java.io.InputStream) throws java.security.cert.CertificateException;
+    method public final java.util.Iterator<java.lang.String> getCertPathEncodings();
+    method public static final java.security.cert.CertificateFactory getInstance(java.lang.String) throws java.security.cert.CertificateException;
+    method public static final java.security.cert.CertificateFactory getInstance(java.lang.String, java.lang.String) throws java.security.cert.CertificateException, java.security.NoSuchProviderException;
+    method public static final java.security.cert.CertificateFactory getInstance(java.lang.String, java.security.Provider) throws java.security.cert.CertificateException;
+    method public final java.security.Provider getProvider();
+    method public final java.lang.String getType();
+  }
+
+  public abstract class CertificateFactorySpi {
+    ctor public CertificateFactorySpi();
+    method public abstract java.security.cert.CRL engineGenerateCRL(java.io.InputStream) throws java.security.cert.CRLException;
+    method public abstract java.util.Collection<? extends java.security.cert.CRL> engineGenerateCRLs(java.io.InputStream) throws java.security.cert.CRLException;
+    method public java.security.cert.CertPath engineGenerateCertPath(java.io.InputStream) throws java.security.cert.CertificateException;
+    method public java.security.cert.CertPath engineGenerateCertPath(java.io.InputStream, java.lang.String) throws java.security.cert.CertificateException;
+    method public java.security.cert.CertPath engineGenerateCertPath(java.util.List<? extends java.security.cert.Certificate>) throws java.security.cert.CertificateException;
+    method public abstract java.security.cert.Certificate engineGenerateCertificate(java.io.InputStream) throws java.security.cert.CertificateException;
+    method public abstract java.util.Collection<? extends java.security.cert.Certificate> engineGenerateCertificates(java.io.InputStream) throws java.security.cert.CertificateException;
+    method public java.util.Iterator<java.lang.String> engineGetCertPathEncodings();
+  }
+
+  public class CertificateNotYetValidException extends java.security.cert.CertificateException {
+    ctor public CertificateNotYetValidException(java.lang.String);
+    ctor public CertificateNotYetValidException();
+  }
+
+  public class CertificateParsingException extends java.security.cert.CertificateException {
+    ctor public CertificateParsingException(java.lang.String);
+    ctor public CertificateParsingException();
+    ctor public CertificateParsingException(java.lang.String, java.lang.Throwable);
+    ctor public CertificateParsingException(java.lang.Throwable);
+  }
+
+  public class CollectionCertStoreParameters implements java.security.cert.CertStoreParameters {
+    ctor public CollectionCertStoreParameters();
+    ctor public CollectionCertStoreParameters(java.util.Collection<?>);
+    method public java.lang.Object clone();
+    method public java.util.Collection<?> getCollection();
+  }
+
+  public class LDAPCertStoreParameters implements java.security.cert.CertStoreParameters {
+    ctor public LDAPCertStoreParameters(java.lang.String, int);
+    ctor public LDAPCertStoreParameters();
+    ctor public LDAPCertStoreParameters(java.lang.String);
+    method public java.lang.Object clone();
+    method public int getPort();
+    method public java.lang.String getServerName();
+  }
+
+  public class PKIXBuilderParameters extends java.security.cert.PKIXParameters {
+    ctor public PKIXBuilderParameters(java.util.Set<java.security.cert.TrustAnchor>, java.security.cert.CertSelector) throws java.security.InvalidAlgorithmParameterException;
+    ctor public PKIXBuilderParameters(java.security.KeyStore, java.security.cert.CertSelector) throws java.security.InvalidAlgorithmParameterException, java.security.KeyStoreException;
+    method public int getMaxPathLength();
+    method public void setMaxPathLength(int);
+  }
+
+  public class PKIXCertPathBuilderResult extends java.security.cert.PKIXCertPathValidatorResult implements java.security.cert.CertPathBuilderResult {
+    ctor public PKIXCertPathBuilderResult(java.security.cert.CertPath, java.security.cert.TrustAnchor, java.security.cert.PolicyNode, java.security.PublicKey);
+    method public java.security.cert.CertPath getCertPath();
+  }
+
+  public abstract class PKIXCertPathChecker implements java.lang.Cloneable {
+    ctor protected PKIXCertPathChecker();
+    method public abstract void check(java.security.cert.Certificate, java.util.Collection<java.lang.String>) throws java.security.cert.CertPathValidatorException;
+    method public java.lang.Object clone();
+    method public abstract java.util.Set<java.lang.String> getSupportedExtensions();
+    method public abstract void init(boolean) throws java.security.cert.CertPathValidatorException;
+    method public abstract boolean isForwardCheckingSupported();
+  }
+
+  public class PKIXCertPathValidatorResult implements java.security.cert.CertPathValidatorResult {
+    ctor public PKIXCertPathValidatorResult(java.security.cert.TrustAnchor, java.security.cert.PolicyNode, java.security.PublicKey);
+    method public java.lang.Object clone();
+    method public java.security.cert.PolicyNode getPolicyTree();
+    method public java.security.PublicKey getPublicKey();
+    method public java.security.cert.TrustAnchor getTrustAnchor();
+  }
+
+  public class PKIXParameters implements java.security.cert.CertPathParameters {
+    ctor public PKIXParameters(java.util.Set<java.security.cert.TrustAnchor>) throws java.security.InvalidAlgorithmParameterException;
+    ctor public PKIXParameters(java.security.KeyStore) throws java.security.InvalidAlgorithmParameterException, java.security.KeyStoreException;
+    method public void addCertPathChecker(java.security.cert.PKIXCertPathChecker);
+    method public void addCertStore(java.security.cert.CertStore);
+    method public java.lang.Object clone();
+    method public java.util.List<java.security.cert.PKIXCertPathChecker> getCertPathCheckers();
+    method public java.util.List<java.security.cert.CertStore> getCertStores();
+    method public java.util.Date getDate();
+    method public java.util.Set<java.lang.String> getInitialPolicies();
+    method public boolean getPolicyQualifiersRejected();
+    method public java.lang.String getSigProvider();
+    method public java.security.cert.CertSelector getTargetCertConstraints();
+    method public java.util.Set<java.security.cert.TrustAnchor> getTrustAnchors();
+    method public boolean isAnyPolicyInhibited();
+    method public boolean isExplicitPolicyRequired();
+    method public boolean isPolicyMappingInhibited();
+    method public boolean isRevocationEnabled();
+    method public void setAnyPolicyInhibited(boolean);
+    method public void setCertPathCheckers(java.util.List<java.security.cert.PKIXCertPathChecker>);
+    method public void setCertStores(java.util.List<java.security.cert.CertStore>);
+    method public void setDate(java.util.Date);
+    method public void setExplicitPolicyRequired(boolean);
+    method public void setInitialPolicies(java.util.Set<java.lang.String>);
+    method public void setPolicyMappingInhibited(boolean);
+    method public void setPolicyQualifiersRejected(boolean);
+    method public void setRevocationEnabled(boolean);
+    method public void setSigProvider(java.lang.String);
+    method public void setTargetCertConstraints(java.security.cert.CertSelector);
+    method public void setTrustAnchors(java.util.Set<java.security.cert.TrustAnchor>) throws java.security.InvalidAlgorithmParameterException;
+  }
+
+  public abstract interface PolicyNode {
+    method public abstract java.util.Iterator<? extends java.security.cert.PolicyNode> getChildren();
+    method public abstract int getDepth();
+    method public abstract java.util.Set<java.lang.String> getExpectedPolicies();
+    method public abstract java.security.cert.PolicyNode getParent();
+    method public abstract java.util.Set<? extends java.security.cert.PolicyQualifierInfo> getPolicyQualifiers();
+    method public abstract java.lang.String getValidPolicy();
+    method public abstract boolean isCritical();
+  }
+
+  public class PolicyQualifierInfo {
+    ctor public PolicyQualifierInfo(byte[]) throws java.io.IOException;
+    method public final byte[] getEncoded();
+    method public final byte[] getPolicyQualifier();
+    method public final java.lang.String getPolicyQualifierId();
+  }
+
+  public class TrustAnchor {
+    ctor public TrustAnchor(java.security.cert.X509Certificate, byte[]);
+    ctor public TrustAnchor(java.lang.String, java.security.PublicKey, byte[]);
+    ctor public TrustAnchor(javax.security.auth.x500.X500Principal, java.security.PublicKey, byte[]);
+    method public final javax.security.auth.x500.X500Principal getCA();
+    method public final java.lang.String getCAName();
+    method public final java.security.PublicKey getCAPublicKey();
+    method public final byte[] getNameConstraints();
+    method public final java.security.cert.X509Certificate getTrustedCert();
+  }
+
+  public abstract class X509CRL extends java.security.cert.CRL implements java.security.cert.X509Extension {
+    ctor protected X509CRL();
+    method public abstract byte[] getEncoded() throws java.security.cert.CRLException;
+    method public abstract java.security.Principal getIssuerDN();
+    method public javax.security.auth.x500.X500Principal getIssuerX500Principal();
+    method public abstract java.util.Date getNextUpdate();
+    method public abstract java.security.cert.X509CRLEntry getRevokedCertificate(java.math.BigInteger);
+    method public java.security.cert.X509CRLEntry getRevokedCertificate(java.security.cert.X509Certificate);
+    method public abstract java.util.Set<? extends java.security.cert.X509CRLEntry> getRevokedCertificates();
+    method public abstract java.lang.String getSigAlgName();
+    method public abstract java.lang.String getSigAlgOID();
+    method public abstract byte[] getSigAlgParams();
+    method public abstract byte[] getSignature();
+    method public abstract byte[] getTBSCertList() throws java.security.cert.CRLException;
+    method public abstract java.util.Date getThisUpdate();
+    method public abstract int getVersion();
+    method public abstract void verify(java.security.PublicKey) throws java.security.cert.CRLException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException, java.security.SignatureException;
+    method public abstract void verify(java.security.PublicKey, java.lang.String) throws java.security.cert.CRLException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException, java.security.SignatureException;
+  }
+
+  public abstract class X509CRLEntry implements java.security.cert.X509Extension {
+    ctor public X509CRLEntry();
+    method public javax.security.auth.x500.X500Principal getCertificateIssuer();
+    method public abstract byte[] getEncoded() throws java.security.cert.CRLException;
+    method public abstract java.util.Date getRevocationDate();
+    method public abstract java.math.BigInteger getSerialNumber();
+    method public abstract boolean hasExtensions();
+    method public abstract java.lang.String toString();
+  }
+
+  public class X509CRLSelector implements java.security.cert.CRLSelector {
+    ctor public X509CRLSelector();
+    method public void addIssuer(javax.security.auth.x500.X500Principal);
+    method public void addIssuerName(java.lang.String) throws java.io.IOException;
+    method public void addIssuerName(byte[]) throws java.io.IOException;
+    method public java.lang.Object clone();
+    method public java.security.cert.X509Certificate getCertificateChecking();
+    method public java.util.Date getDateAndTime();
+    method public java.util.Collection<java.lang.Object> getIssuerNames();
+    method public java.util.Collection<javax.security.auth.x500.X500Principal> getIssuers();
+    method public java.math.BigInteger getMaxCRL();
+    method public java.math.BigInteger getMinCRL();
+    method public boolean match(java.security.cert.CRL);
+    method public void setCertificateChecking(java.security.cert.X509Certificate);
+    method public void setDateAndTime(java.util.Date);
+    method public void setIssuerNames(java.util.Collection<?>) throws java.io.IOException;
+    method public void setIssuers(java.util.Collection<javax.security.auth.x500.X500Principal>);
+    method public void setMaxCRLNumber(java.math.BigInteger);
+    method public void setMinCRLNumber(java.math.BigInteger);
+  }
+
+  public class X509CertSelector implements java.security.cert.CertSelector {
+    ctor public X509CertSelector();
+    method public void addPathToName(int, java.lang.String) throws java.io.IOException;
+    method public void addPathToName(int, byte[]) throws java.io.IOException;
+    method public void addSubjectAlternativeName(int, java.lang.String) throws java.io.IOException;
+    method public void addSubjectAlternativeName(int, byte[]) throws java.io.IOException;
+    method public java.lang.Object clone();
+    method public byte[] getAuthorityKeyIdentifier();
+    method public int getBasicConstraints();
+    method public java.security.cert.X509Certificate getCertificate();
+    method public java.util.Date getCertificateValid();
+    method public java.util.Set<java.lang.String> getExtendedKeyUsage();
+    method public javax.security.auth.x500.X500Principal getIssuer();
+    method public byte[] getIssuerAsBytes() throws java.io.IOException;
+    method public java.lang.String getIssuerAsString();
+    method public boolean[] getKeyUsage();
+    method public boolean getMatchAllSubjectAltNames();
+    method public byte[] getNameConstraints();
+    method public java.util.Collection<java.util.List<?>> getPathToNames();
+    method public java.util.Set<java.lang.String> getPolicy();
+    method public java.util.Date getPrivateKeyValid();
+    method public java.math.BigInteger getSerialNumber();
+    method public javax.security.auth.x500.X500Principal getSubject();
+    method public java.util.Collection<java.util.List<?>> getSubjectAlternativeNames();
+    method public byte[] getSubjectAsBytes() throws java.io.IOException;
+    method public java.lang.String getSubjectAsString();
+    method public byte[] getSubjectKeyIdentifier();
+    method public java.security.PublicKey getSubjectPublicKey();
+    method public java.lang.String getSubjectPublicKeyAlgID();
+    method public boolean match(java.security.cert.Certificate);
+    method public void setAuthorityKeyIdentifier(byte[]);
+    method public void setBasicConstraints(int);
+    method public void setCertificate(java.security.cert.X509Certificate);
+    method public void setCertificateValid(java.util.Date);
+    method public void setExtendedKeyUsage(java.util.Set<java.lang.String>) throws java.io.IOException;
+    method public void setIssuer(javax.security.auth.x500.X500Principal);
+    method public void setIssuer(java.lang.String) throws java.io.IOException;
+    method public void setIssuer(byte[]) throws java.io.IOException;
+    method public void setKeyUsage(boolean[]);
+    method public void setMatchAllSubjectAltNames(boolean);
+    method public void setNameConstraints(byte[]) throws java.io.IOException;
+    method public void setPathToNames(java.util.Collection<java.util.List<?>>) throws java.io.IOException;
+    method public void setPolicy(java.util.Set<java.lang.String>) throws java.io.IOException;
+    method public void setPrivateKeyValid(java.util.Date);
+    method public void setSerialNumber(java.math.BigInteger);
+    method public void setSubject(javax.security.auth.x500.X500Principal);
+    method public void setSubject(java.lang.String) throws java.io.IOException;
+    method public void setSubject(byte[]) throws java.io.IOException;
+    method public void setSubjectAlternativeNames(java.util.Collection<java.util.List<?>>) throws java.io.IOException;
+    method public void setSubjectKeyIdentifier(byte[]);
+    method public void setSubjectPublicKey(java.security.PublicKey);
+    method public void setSubjectPublicKey(byte[]) throws java.io.IOException;
+    method public void setSubjectPublicKeyAlgID(java.lang.String) throws java.io.IOException;
+  }
+
+  public abstract class X509Certificate extends java.security.cert.Certificate implements java.security.cert.X509Extension {
+    ctor protected X509Certificate();
+    method public abstract void checkValidity() throws java.security.cert.CertificateExpiredException, java.security.cert.CertificateNotYetValidException;
+    method public abstract void checkValidity(java.util.Date) throws java.security.cert.CertificateExpiredException, java.security.cert.CertificateNotYetValidException;
+    method public abstract int getBasicConstraints();
+    method public java.util.List<java.lang.String> getExtendedKeyUsage() throws java.security.cert.CertificateParsingException;
+    method public java.util.Collection<java.util.List<?>> getIssuerAlternativeNames() throws java.security.cert.CertificateParsingException;
+    method public abstract java.security.Principal getIssuerDN();
+    method public abstract boolean[] getIssuerUniqueID();
+    method public javax.security.auth.x500.X500Principal getIssuerX500Principal();
+    method public abstract boolean[] getKeyUsage();
+    method public abstract java.util.Date getNotAfter();
+    method public abstract java.util.Date getNotBefore();
+    method public abstract java.math.BigInteger getSerialNumber();
+    method public abstract java.lang.String getSigAlgName();
+    method public abstract java.lang.String getSigAlgOID();
+    method public abstract byte[] getSigAlgParams();
+    method public abstract byte[] getSignature();
+    method public java.util.Collection<java.util.List<?>> getSubjectAlternativeNames() throws java.security.cert.CertificateParsingException;
+    method public abstract java.security.Principal getSubjectDN();
+    method public abstract boolean[] getSubjectUniqueID();
+    method public javax.security.auth.x500.X500Principal getSubjectX500Principal();
+    method public abstract byte[] getTBSCertificate() throws java.security.cert.CertificateEncodingException;
+    method public abstract int getVersion();
+  }
+
+  public abstract interface X509Extension {
+    method public abstract java.util.Set<java.lang.String> getCriticalExtensionOIDs();
+    method public abstract byte[] getExtensionValue(java.lang.String);
+    method public abstract java.util.Set<java.lang.String> getNonCriticalExtensionOIDs();
+    method public abstract boolean hasUnsupportedCriticalExtension();
+  }
+
+}
+
+package java.security.interfaces {
+
+  public abstract interface DSAKey {
+    method public abstract java.security.interfaces.DSAParams getParams();
+  }
+
+  public abstract interface DSAKeyPairGenerator {
+    method public abstract void initialize(java.security.interfaces.DSAParams, java.security.SecureRandom) throws java.security.InvalidParameterException;
+    method public abstract void initialize(int, boolean, java.security.SecureRandom) throws java.security.InvalidParameterException;
+  }
+
+  public abstract interface DSAParams {
+    method public abstract java.math.BigInteger getG();
+    method public abstract java.math.BigInteger getP();
+    method public abstract java.math.BigInteger getQ();
+  }
+
+  public abstract interface DSAPrivateKey implements java.security.interfaces.DSAKey java.security.PrivateKey {
+    method public abstract java.math.BigInteger getX();
+    field public static final long serialVersionUID = 7776497482533790279L; // 0x6bebab423b256247L
+  }
+
+  public abstract interface DSAPublicKey implements java.security.interfaces.DSAKey java.security.PublicKey {
+    method public abstract java.math.BigInteger getY();
+    field public static final long serialVersionUID = 1234526332779022332L; // 0x1121eb28ab28c7fcL
+  }
+
+  public abstract interface ECKey {
+    method public abstract java.security.spec.ECParameterSpec getParams();
+  }
+
+  public abstract interface ECPrivateKey implements java.security.interfaces.ECKey java.security.PrivateKey {
+    method public abstract java.math.BigInteger getS();
+    field public static final long serialVersionUID = -7896394956925609184L; // 0x926a5e9fa2435b20L
+  }
+
+  public abstract interface ECPublicKey implements java.security.interfaces.ECKey java.security.PublicKey {
+    method public abstract java.security.spec.ECPoint getW();
+    field public static final long serialVersionUID = -3314988629879632826L; // 0xd1fecb679990cc46L
+  }
+
+  public abstract interface RSAKey {
+    method public abstract java.math.BigInteger getModulus();
+  }
+
+  public abstract interface RSAMultiPrimePrivateCrtKey implements java.security.interfaces.RSAPrivateKey {
+    method public abstract java.math.BigInteger getCrtCoefficient();
+    method public abstract java.security.spec.RSAOtherPrimeInfo[] getOtherPrimeInfo();
+    method public abstract java.math.BigInteger getPrimeExponentP();
+    method public abstract java.math.BigInteger getPrimeExponentQ();
+    method public abstract java.math.BigInteger getPrimeP();
+    method public abstract java.math.BigInteger getPrimeQ();
+    method public abstract java.math.BigInteger getPublicExponent();
+    field public static final long serialVersionUID = 618058533534628008L; // 0x893c8f62dbaf8a8L
+  }
+
+  public abstract interface RSAPrivateCrtKey implements java.security.interfaces.RSAPrivateKey {
+    method public abstract java.math.BigInteger getCrtCoefficient();
+    method public abstract java.math.BigInteger getPrimeExponentP();
+    method public abstract java.math.BigInteger getPrimeExponentQ();
+    method public abstract java.math.BigInteger getPrimeP();
+    method public abstract java.math.BigInteger getPrimeQ();
+    method public abstract java.math.BigInteger getPublicExponent();
+    field public static final long serialVersionUID = -5682214253527700368L; // 0xb124b83df8d1ec70L
+  }
+
+  public abstract interface RSAPrivateKey implements java.security.PrivateKey java.security.interfaces.RSAKey {
+    method public abstract java.math.BigInteger getPrivateExponent();
+    field public static final long serialVersionUID = 5187144804936595022L; // 0x47fc70b7a8c2364eL
+  }
+
+  public abstract interface RSAPublicKey implements java.security.PublicKey java.security.interfaces.RSAKey {
+    method public abstract java.math.BigInteger getPublicExponent();
+    field public static final long serialVersionUID = -8727434096241101194L; // 0x86e1ecedeceab676L
+  }
+
+}
+
+package java.security.spec {
+
+  public abstract interface AlgorithmParameterSpec {
+  }
+
+  public class DSAParameterSpec implements java.security.spec.AlgorithmParameterSpec java.security.interfaces.DSAParams {
+    ctor public DSAParameterSpec(java.math.BigInteger, java.math.BigInteger, java.math.BigInteger);
+    method public java.math.BigInteger getG();
+    method public java.math.BigInteger getP();
+    method public java.math.BigInteger getQ();
+  }
+
+  public class DSAPrivateKeySpec implements java.security.spec.KeySpec {
+    ctor public DSAPrivateKeySpec(java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger);
+    method public java.math.BigInteger getG();
+    method public java.math.BigInteger getP();
+    method public java.math.BigInteger getQ();
+    method public java.math.BigInteger getX();
+  }
+
+  public class DSAPublicKeySpec implements java.security.spec.KeySpec {
+    ctor public DSAPublicKeySpec(java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger);
+    method public java.math.BigInteger getG();
+    method public java.math.BigInteger getP();
+    method public java.math.BigInteger getQ();
+    method public java.math.BigInteger getY();
+  }
+
+  public abstract interface ECField {
+    method public abstract int getFieldSize();
+  }
+
+  public class ECFieldF2m implements java.security.spec.ECField {
+    ctor public ECFieldF2m(int);
+    ctor public ECFieldF2m(int, java.math.BigInteger);
+    ctor public ECFieldF2m(int, int[]);
+    method public int getFieldSize();
+    method public int getM();
+    method public int[] getMidTermsOfReductionPolynomial();
+    method public java.math.BigInteger getReductionPolynomial();
+  }
+
+  public class ECFieldFp implements java.security.spec.ECField {
+    ctor public ECFieldFp(java.math.BigInteger);
+    method public int getFieldSize();
+    method public java.math.BigInteger getP();
+  }
+
+  public class ECGenParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+    ctor public ECGenParameterSpec(java.lang.String);
+    method public java.lang.String getName();
+  }
+
+  public class ECParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+    ctor public ECParameterSpec(java.security.spec.EllipticCurve, java.security.spec.ECPoint, java.math.BigInteger, int);
+    method public int getCofactor();
+    method public java.security.spec.EllipticCurve getCurve();
+    method public java.security.spec.ECPoint getGenerator();
+    method public java.math.BigInteger getOrder();
+  }
+
+  public class ECPoint {
+    ctor public ECPoint(java.math.BigInteger, java.math.BigInteger);
+    method public java.math.BigInteger getAffineX();
+    method public java.math.BigInteger getAffineY();
+    field public static final java.security.spec.ECPoint POINT_INFINITY;
+  }
+
+  public class ECPrivateKeySpec implements java.security.spec.KeySpec {
+    ctor public ECPrivateKeySpec(java.math.BigInteger, java.security.spec.ECParameterSpec);
+    method public java.security.spec.ECParameterSpec getParams();
+    method public java.math.BigInteger getS();
+  }
+
+  public class ECPublicKeySpec implements java.security.spec.KeySpec {
+    ctor public ECPublicKeySpec(java.security.spec.ECPoint, java.security.spec.ECParameterSpec);
+    method public java.security.spec.ECParameterSpec getParams();
+    method public java.security.spec.ECPoint getW();
+  }
+
+  public class EllipticCurve {
+    ctor public EllipticCurve(java.security.spec.ECField, java.math.BigInteger, java.math.BigInteger, byte[]);
+    ctor public EllipticCurve(java.security.spec.ECField, java.math.BigInteger, java.math.BigInteger);
+    method public java.math.BigInteger getA();
+    method public java.math.BigInteger getB();
+    method public java.security.spec.ECField getField();
+    method public byte[] getSeed();
+  }
+
+  public abstract class EncodedKeySpec implements java.security.spec.KeySpec {
+    ctor public EncodedKeySpec(byte[]);
+    method public byte[] getEncoded();
+    method public abstract java.lang.String getFormat();
+  }
+
+  public class InvalidKeySpecException extends java.security.GeneralSecurityException {
+    ctor public InvalidKeySpecException(java.lang.String);
+    ctor public InvalidKeySpecException();
+    ctor public InvalidKeySpecException(java.lang.String, java.lang.Throwable);
+    ctor public InvalidKeySpecException(java.lang.Throwable);
+  }
+
+  public class InvalidParameterSpecException extends java.security.GeneralSecurityException {
+    ctor public InvalidParameterSpecException(java.lang.String);
+    ctor public InvalidParameterSpecException();
+  }
+
+  public abstract interface KeySpec {
+  }
+
+  public class MGF1ParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+    ctor public MGF1ParameterSpec(java.lang.String);
+    method public java.lang.String getDigestAlgorithm();
+    field public static final java.security.spec.MGF1ParameterSpec SHA1;
+    field public static final java.security.spec.MGF1ParameterSpec SHA256;
+    field public static final java.security.spec.MGF1ParameterSpec SHA384;
+    field public static final java.security.spec.MGF1ParameterSpec SHA512;
+  }
+
+  public class PKCS8EncodedKeySpec extends java.security.spec.EncodedKeySpec {
+    ctor public PKCS8EncodedKeySpec(byte[]);
+    method public final java.lang.String getFormat();
+  }
+
+  public class PSSParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+    ctor public PSSParameterSpec(int);
+    ctor public PSSParameterSpec(java.lang.String, java.lang.String, java.security.spec.AlgorithmParameterSpec, int, int);
+    method public java.lang.String getDigestAlgorithm();
+    method public java.lang.String getMGFAlgorithm();
+    method public java.security.spec.AlgorithmParameterSpec getMGFParameters();
+    method public int getSaltLength();
+    method public int getTrailerField();
+    field public static final java.security.spec.PSSParameterSpec DEFAULT;
+  }
+
+  public class RSAKeyGenParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+    ctor public RSAKeyGenParameterSpec(int, java.math.BigInteger);
+    method public int getKeysize();
+    method public java.math.BigInteger getPublicExponent();
+    field public static final java.math.BigInteger F0;
+    field public static final java.math.BigInteger F4;
+  }
+
+  public class RSAMultiPrimePrivateCrtKeySpec extends java.security.spec.RSAPrivateKeySpec {
+    ctor public RSAMultiPrimePrivateCrtKeySpec(java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.security.spec.RSAOtherPrimeInfo[]);
+    method public java.math.BigInteger getCrtCoefficient();
+    method public java.security.spec.RSAOtherPrimeInfo[] getOtherPrimeInfo();
+    method public java.math.BigInteger getPrimeExponentP();
+    method public java.math.BigInteger getPrimeExponentQ();
+    method public java.math.BigInteger getPrimeP();
+    method public java.math.BigInteger getPrimeQ();
+    method public java.math.BigInteger getPublicExponent();
+  }
+
+  public class RSAOtherPrimeInfo {
+    ctor public RSAOtherPrimeInfo(java.math.BigInteger, java.math.BigInteger, java.math.BigInteger);
+    method public final java.math.BigInteger getCrtCoefficient();
+    method public final java.math.BigInteger getExponent();
+    method public final java.math.BigInteger getPrime();
+  }
+
+  public class RSAPrivateCrtKeySpec extends java.security.spec.RSAPrivateKeySpec {
+    ctor public RSAPrivateCrtKeySpec(java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger);
+    method public java.math.BigInteger getCrtCoefficient();
+    method public java.math.BigInteger getPrimeExponentP();
+    method public java.math.BigInteger getPrimeExponentQ();
+    method public java.math.BigInteger getPrimeP();
+    method public java.math.BigInteger getPrimeQ();
+    method public java.math.BigInteger getPublicExponent();
+  }
+
+  public class RSAPrivateKeySpec implements java.security.spec.KeySpec {
+    ctor public RSAPrivateKeySpec(java.math.BigInteger, java.math.BigInteger);
+    method public java.math.BigInteger getModulus();
+    method public java.math.BigInteger getPrivateExponent();
+  }
+
+  public class RSAPublicKeySpec implements java.security.spec.KeySpec {
+    ctor public RSAPublicKeySpec(java.math.BigInteger, java.math.BigInteger);
+    method public java.math.BigInteger getModulus();
+    method public java.math.BigInteger getPublicExponent();
+  }
+
+  public class X509EncodedKeySpec extends java.security.spec.EncodedKeySpec {
+    ctor public X509EncodedKeySpec(byte[]);
+    method public final java.lang.String getFormat();
+  }
+
+}
+
+package java.sql {
+
+  public abstract interface Array {
+    method public abstract void free() throws java.sql.SQLException;
+    method public abstract java.lang.Object getArray() throws java.sql.SQLException;
+    method public abstract java.lang.Object getArray(long, int) throws java.sql.SQLException;
+    method public abstract java.lang.Object getArray(long, int, java.util.Map<java.lang.String, java.lang.Class<?>>) throws java.sql.SQLException;
+    method public abstract java.lang.Object getArray(java.util.Map<java.lang.String, java.lang.Class<?>>) throws java.sql.SQLException;
+    method public abstract int getBaseType() throws java.sql.SQLException;
+    method public abstract java.lang.String getBaseTypeName() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getResultSet() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getResultSet(long, int) throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getResultSet(long, int, java.util.Map<java.lang.String, java.lang.Class<?>>) throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getResultSet(java.util.Map<java.lang.String, java.lang.Class<?>>) throws java.sql.SQLException;
+  }
+
+  public class BatchUpdateException extends java.sql.SQLException implements java.io.Serializable {
+    ctor public BatchUpdateException();
+    ctor public BatchUpdateException(java.lang.Throwable);
+    ctor public BatchUpdateException(int[], java.lang.Throwable);
+    ctor public BatchUpdateException(java.lang.String, int[], java.lang.Throwable);
+    ctor public BatchUpdateException(java.lang.String, java.lang.String, int[], java.lang.Throwable);
+    ctor public BatchUpdateException(java.lang.String, java.lang.String, int, int[], java.lang.Throwable);
+    ctor public BatchUpdateException(int[]);
+    ctor public BatchUpdateException(java.lang.String, int[]);
+    ctor public BatchUpdateException(java.lang.String, java.lang.String, int[]);
+    ctor public BatchUpdateException(java.lang.String, java.lang.String, int, int[]);
+    method public int[] getUpdateCounts();
+  }
+
+  public abstract interface Blob {
+    method public abstract void free() throws java.sql.SQLException;
+    method public abstract java.io.InputStream getBinaryStream() throws java.sql.SQLException;
+    method public abstract java.io.InputStream getBinaryStream(long, long) throws java.sql.SQLException;
+    method public abstract byte[] getBytes(long, int) throws java.sql.SQLException;
+    method public abstract long length() throws java.sql.SQLException;
+    method public abstract long position(java.sql.Blob, long) throws java.sql.SQLException;
+    method public abstract long position(byte[], long) throws java.sql.SQLException;
+    method public abstract java.io.OutputStream setBinaryStream(long) throws java.sql.SQLException;
+    method public abstract int setBytes(long, byte[]) throws java.sql.SQLException;
+    method public abstract int setBytes(long, byte[], int, int) throws java.sql.SQLException;
+    method public abstract void truncate(long) throws java.sql.SQLException;
+  }
+
+  public abstract interface CallableStatement implements java.sql.PreparedStatement {
+    method public abstract java.sql.Array getArray(int) throws java.sql.SQLException;
+    method public abstract java.sql.Array getArray(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.math.BigDecimal getBigDecimal(int) throws java.sql.SQLException;
+    method public abstract deprecated java.math.BigDecimal getBigDecimal(int, int) throws java.sql.SQLException;
+    method public abstract java.math.BigDecimal getBigDecimal(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.Blob getBlob(int) throws java.sql.SQLException;
+    method public abstract java.sql.Blob getBlob(java.lang.String) throws java.sql.SQLException;
+    method public abstract boolean getBoolean(int) throws java.sql.SQLException;
+    method public abstract boolean getBoolean(java.lang.String) throws java.sql.SQLException;
+    method public abstract byte getByte(int) throws java.sql.SQLException;
+    method public abstract byte getByte(java.lang.String) throws java.sql.SQLException;
+    method public abstract byte[] getBytes(int) throws java.sql.SQLException;
+    method public abstract byte[] getBytes(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.io.Reader getCharacterStream(int) throws java.sql.SQLException;
+    method public abstract java.io.Reader getCharacterStream(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.Clob getClob(int) throws java.sql.SQLException;
+    method public abstract java.sql.Clob getClob(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.Date getDate(int) throws java.sql.SQLException;
+    method public abstract java.sql.Date getDate(int, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract java.sql.Date getDate(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.Date getDate(java.lang.String, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract double getDouble(int) throws java.sql.SQLException;
+    method public abstract double getDouble(java.lang.String) throws java.sql.SQLException;
+    method public abstract float getFloat(int) throws java.sql.SQLException;
+    method public abstract float getFloat(java.lang.String) throws java.sql.SQLException;
+    method public abstract int getInt(int) throws java.sql.SQLException;
+    method public abstract int getInt(java.lang.String) throws java.sql.SQLException;
+    method public abstract long getLong(int) throws java.sql.SQLException;
+    method public abstract long getLong(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.io.Reader getNCharacterStream(int) throws java.sql.SQLException;
+    method public abstract java.io.Reader getNCharacterStream(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.NClob getNClob(int) throws java.sql.SQLException;
+    method public abstract java.sql.NClob getNClob(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.lang.String getNString(int) throws java.sql.SQLException;
+    method public abstract java.lang.String getNString(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.lang.Object getObject(int) throws java.sql.SQLException;
+    method public abstract java.lang.Object getObject(int, java.util.Map<java.lang.String, java.lang.Class<?>>) throws java.sql.SQLException;
+    method public abstract java.lang.Object getObject(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.lang.Object getObject(java.lang.String, java.util.Map<java.lang.String, java.lang.Class<?>>) throws java.sql.SQLException;
+    method public abstract java.sql.Ref getRef(int) throws java.sql.SQLException;
+    method public abstract java.sql.Ref getRef(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.RowId getRowId(int) throws java.sql.SQLException;
+    method public abstract java.sql.RowId getRowId(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.SQLXML getSQLXML(int) throws java.sql.SQLException;
+    method public abstract java.sql.SQLXML getSQLXML(java.lang.String) throws java.sql.SQLException;
+    method public abstract short getShort(int) throws java.sql.SQLException;
+    method public abstract short getShort(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.lang.String getString(int) throws java.sql.SQLException;
+    method public abstract java.lang.String getString(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.Time getTime(int) throws java.sql.SQLException;
+    method public abstract java.sql.Time getTime(int, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract java.sql.Time getTime(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.Time getTime(java.lang.String, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract java.sql.Timestamp getTimestamp(int) throws java.sql.SQLException;
+    method public abstract java.sql.Timestamp getTimestamp(int, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract java.sql.Timestamp getTimestamp(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.Timestamp getTimestamp(java.lang.String, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract java.net.URL getURL(int) throws java.sql.SQLException;
+    method public abstract java.net.URL getURL(java.lang.String) throws java.sql.SQLException;
+    method public abstract void registerOutParameter(int, int) throws java.sql.SQLException;
+    method public abstract void registerOutParameter(int, int, int) throws java.sql.SQLException;
+    method public abstract void registerOutParameter(int, int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void registerOutParameter(java.lang.String, int) throws java.sql.SQLException;
+    method public abstract void registerOutParameter(java.lang.String, int, int) throws java.sql.SQLException;
+    method public abstract void registerOutParameter(java.lang.String, int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setAsciiStream(java.lang.String, java.io.InputStream, int) throws java.sql.SQLException;
+    method public abstract void setAsciiStream(java.lang.String, java.io.InputStream, long) throws java.sql.SQLException;
+    method public abstract void setAsciiStream(java.lang.String, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void setBigDecimal(java.lang.String, java.math.BigDecimal) throws java.sql.SQLException;
+    method public abstract void setBinaryStream(java.lang.String, java.io.InputStream, int) throws java.sql.SQLException;
+    method public abstract void setBinaryStream(java.lang.String, java.io.InputStream, long) throws java.sql.SQLException;
+    method public abstract void setBinaryStream(java.lang.String, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void setBlob(java.lang.String, java.io.InputStream, long) throws java.sql.SQLException;
+    method public abstract void setBlob(java.lang.String, java.sql.Blob) throws java.sql.SQLException;
+    method public abstract void setBlob(java.lang.String, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void setBoolean(java.lang.String, boolean) throws java.sql.SQLException;
+    method public abstract void setByte(java.lang.String, byte) throws java.sql.SQLException;
+    method public abstract void setBytes(java.lang.String, byte[]) throws java.sql.SQLException;
+    method public abstract void setCharacterStream(java.lang.String, java.io.Reader, int) throws java.sql.SQLException;
+    method public abstract void setCharacterStream(java.lang.String, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void setCharacterStream(java.lang.String, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void setClob(java.lang.String, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void setClob(java.lang.String, java.sql.Clob) throws java.sql.SQLException;
+    method public abstract void setClob(java.lang.String, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void setDate(java.lang.String, java.sql.Date) throws java.sql.SQLException;
+    method public abstract void setDate(java.lang.String, java.sql.Date, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract void setDouble(java.lang.String, double) throws java.sql.SQLException;
+    method public abstract void setFloat(java.lang.String, float) throws java.sql.SQLException;
+    method public abstract void setInt(java.lang.String, int) throws java.sql.SQLException;
+    method public abstract void setLong(java.lang.String, long) throws java.sql.SQLException;
+    method public abstract void setNCharacterStream(java.lang.String, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void setNCharacterStream(java.lang.String, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void setNClob(java.lang.String, java.sql.NClob) throws java.sql.SQLException;
+    method public abstract void setNClob(java.lang.String, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void setNClob(java.lang.String, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void setNString(java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setNull(java.lang.String, int) throws java.sql.SQLException;
+    method public abstract void setNull(java.lang.String, int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setObject(java.lang.String, java.lang.Object) throws java.sql.SQLException;
+    method public abstract void setObject(java.lang.String, java.lang.Object, int) throws java.sql.SQLException;
+    method public abstract void setObject(java.lang.String, java.lang.Object, int, int) throws java.sql.SQLException;
+    method public abstract void setRowId(java.lang.String, java.sql.RowId) throws java.sql.SQLException;
+    method public abstract void setSQLXML(java.lang.String, java.sql.SQLXML) throws java.sql.SQLException;
+    method public abstract void setShort(java.lang.String, short) throws java.sql.SQLException;
+    method public abstract void setString(java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setTime(java.lang.String, java.sql.Time) throws java.sql.SQLException;
+    method public abstract void setTime(java.lang.String, java.sql.Time, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract void setTimestamp(java.lang.String, java.sql.Timestamp) throws java.sql.SQLException;
+    method public abstract void setTimestamp(java.lang.String, java.sql.Timestamp, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract void setURL(java.lang.String, java.net.URL) throws java.sql.SQLException;
+    method public abstract boolean wasNull() throws java.sql.SQLException;
+  }
+
+  public final class ClientInfoStatus extends java.lang.Enum {
+    method public static java.sql.ClientInfoStatus valueOf(java.lang.String);
+    method public static final java.sql.ClientInfoStatus[] values();
+    enum_constant public static final java.sql.ClientInfoStatus REASON_UNKNOWN;
+    enum_constant public static final java.sql.ClientInfoStatus REASON_UNKNOWN_PROPERTY;
+    enum_constant public static final java.sql.ClientInfoStatus REASON_VALUE_INVALID;
+    enum_constant public static final java.sql.ClientInfoStatus REASON_VALUE_TRUNCATED;
+  }
+
+  public abstract interface Clob {
+    method public abstract void free() throws java.sql.SQLException;
+    method public abstract java.io.InputStream getAsciiStream() throws java.sql.SQLException;
+    method public abstract java.io.Reader getCharacterStream() throws java.sql.SQLException;
+    method public abstract java.io.Reader getCharacterStream(long, long) throws java.sql.SQLException;
+    method public abstract java.lang.String getSubString(long, int) throws java.sql.SQLException;
+    method public abstract long length() throws java.sql.SQLException;
+    method public abstract long position(java.sql.Clob, long) throws java.sql.SQLException;
+    method public abstract long position(java.lang.String, long) throws java.sql.SQLException;
+    method public abstract java.io.OutputStream setAsciiStream(long) throws java.sql.SQLException;
+    method public abstract java.io.Writer setCharacterStream(long) throws java.sql.SQLException;
+    method public abstract int setString(long, java.lang.String) throws java.sql.SQLException;
+    method public abstract int setString(long, java.lang.String, int, int) throws java.sql.SQLException;
+    method public abstract void truncate(long) throws java.sql.SQLException;
+  }
+
+  public abstract interface Connection implements java.sql.Wrapper {
+    method public abstract void clearWarnings() throws java.sql.SQLException;
+    method public abstract void close() throws java.sql.SQLException;
+    method public abstract void commit() throws java.sql.SQLException;
+    method public abstract java.sql.Array createArrayOf(java.lang.String, java.lang.Object[]) throws java.sql.SQLException;
+    method public abstract java.sql.Blob createBlob() throws java.sql.SQLException;
+    method public abstract java.sql.Clob createClob() throws java.sql.SQLException;
+    method public abstract java.sql.NClob createNClob() throws java.sql.SQLException;
+    method public abstract java.sql.SQLXML createSQLXML() throws java.sql.SQLException;
+    method public abstract java.sql.Statement createStatement() throws java.sql.SQLException;
+    method public abstract java.sql.Statement createStatement(int, int) throws java.sql.SQLException;
+    method public abstract java.sql.Statement createStatement(int, int, int) throws java.sql.SQLException;
+    method public abstract java.sql.Struct createStruct(java.lang.String, java.lang.Object[]) throws java.sql.SQLException;
+    method public abstract boolean getAutoCommit() throws java.sql.SQLException;
+    method public abstract java.lang.String getCatalog() throws java.sql.SQLException;
+    method public abstract java.lang.String getClientInfo(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.util.Properties getClientInfo() throws java.sql.SQLException;
+    method public abstract int getHoldability() throws java.sql.SQLException;
+    method public abstract java.sql.DatabaseMetaData getMetaData() throws java.sql.SQLException;
+    method public abstract int getTransactionIsolation() throws java.sql.SQLException;
+    method public abstract java.util.Map<java.lang.String, java.lang.Class<?>> getTypeMap() throws java.sql.SQLException;
+    method public abstract java.sql.SQLWarning getWarnings() throws java.sql.SQLException;
+    method public abstract boolean isClosed() throws java.sql.SQLException;
+    method public abstract boolean isReadOnly() throws java.sql.SQLException;
+    method public abstract boolean isValid(int) throws java.sql.SQLException;
+    method public abstract java.lang.String nativeSQL(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.CallableStatement prepareCall(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.CallableStatement prepareCall(java.lang.String, int, int) throws java.sql.SQLException;
+    method public abstract java.sql.CallableStatement prepareCall(java.lang.String, int, int, int) throws java.sql.SQLException;
+    method public abstract java.sql.PreparedStatement prepareStatement(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.PreparedStatement prepareStatement(java.lang.String, int) throws java.sql.SQLException;
+    method public abstract java.sql.PreparedStatement prepareStatement(java.lang.String, int[]) throws java.sql.SQLException;
+    method public abstract java.sql.PreparedStatement prepareStatement(java.lang.String, int, int) throws java.sql.SQLException;
+    method public abstract java.sql.PreparedStatement prepareStatement(java.lang.String, int, int, int) throws java.sql.SQLException;
+    method public abstract java.sql.PreparedStatement prepareStatement(java.lang.String, java.lang.String[]) throws java.sql.SQLException;
+    method public abstract void releaseSavepoint(java.sql.Savepoint) throws java.sql.SQLException;
+    method public abstract void rollback() throws java.sql.SQLException;
+    method public abstract void rollback(java.sql.Savepoint) throws java.sql.SQLException;
+    method public abstract void setAutoCommit(boolean) throws java.sql.SQLException;
+    method public abstract void setCatalog(java.lang.String) throws java.sql.SQLException;
+    method public abstract void setClientInfo(java.lang.String, java.lang.String) throws java.sql.SQLClientInfoException;
+    method public abstract void setClientInfo(java.util.Properties) throws java.sql.SQLClientInfoException;
+    method public abstract void setHoldability(int) throws java.sql.SQLException;
+    method public abstract void setReadOnly(boolean) throws java.sql.SQLException;
+    method public abstract java.sql.Savepoint setSavepoint() throws java.sql.SQLException;
+    method public abstract java.sql.Savepoint setSavepoint(java.lang.String) throws java.sql.SQLException;
+    method public abstract void setTransactionIsolation(int) throws java.sql.SQLException;
+    method public abstract void setTypeMap(java.util.Map<java.lang.String, java.lang.Class<?>>) throws java.sql.SQLException;
+    field public static final int TRANSACTION_NONE = 0; // 0x0
+    field public static final int TRANSACTION_READ_COMMITTED = 2; // 0x2
+    field public static final int TRANSACTION_READ_UNCOMMITTED = 1; // 0x1
+    field public static final int TRANSACTION_REPEATABLE_READ = 4; // 0x4
+    field public static final int TRANSACTION_SERIALIZABLE = 8; // 0x8
+  }
+
+  public class DataTruncation extends java.sql.SQLWarning implements java.io.Serializable {
+    ctor public DataTruncation(int, boolean, boolean, int, int);
+    ctor public DataTruncation(int, boolean, boolean, int, int, java.lang.Throwable);
+    method public int getDataSize();
+    method public int getIndex();
+    method public boolean getParameter();
+    method public boolean getRead();
+    method public int getTransferSize();
+  }
+
+  public abstract interface DatabaseMetaData implements java.sql.Wrapper {
+    method public abstract boolean allProceduresAreCallable() throws java.sql.SQLException;
+    method public abstract boolean allTablesAreSelectable() throws java.sql.SQLException;
+    method public abstract boolean autoCommitFailureClosesAllResultSets() throws java.sql.SQLException;
+    method public abstract boolean dataDefinitionCausesTransactionCommit() throws java.sql.SQLException;
+    method public abstract boolean dataDefinitionIgnoredInTransactions() throws java.sql.SQLException;
+    method public abstract boolean deletesAreDetected(int) throws java.sql.SQLException;
+    method public abstract boolean doesMaxRowSizeIncludeBlobs() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getAttributes(java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getBestRowIdentifier(java.lang.String, java.lang.String, java.lang.String, int, boolean) throws java.sql.SQLException;
+    method public abstract java.lang.String getCatalogSeparator() throws java.sql.SQLException;
+    method public abstract java.lang.String getCatalogTerm() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getCatalogs() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getClientInfoProperties() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getColumnPrivileges(java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getColumns(java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.Connection getConnection() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getCrossReference(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract int getDatabaseMajorVersion() throws java.sql.SQLException;
+    method public abstract int getDatabaseMinorVersion() throws java.sql.SQLException;
+    method public abstract java.lang.String getDatabaseProductName() throws java.sql.SQLException;
+    method public abstract java.lang.String getDatabaseProductVersion() throws java.sql.SQLException;
+    method public abstract int getDefaultTransactionIsolation() throws java.sql.SQLException;
+    method public abstract int getDriverMajorVersion();
+    method public abstract int getDriverMinorVersion();
+    method public abstract java.lang.String getDriverName() throws java.sql.SQLException;
+    method public abstract java.lang.String getDriverVersion() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getExportedKeys(java.lang.String, java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract java.lang.String getExtraNameCharacters() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getFunctionColumns(java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getFunctions(java.lang.String, java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract java.lang.String getIdentifierQuoteString() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getImportedKeys(java.lang.String, java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getIndexInfo(java.lang.String, java.lang.String, java.lang.String, boolean, boolean) throws java.sql.SQLException;
+    method public abstract int getJDBCMajorVersion() throws java.sql.SQLException;
+    method public abstract int getJDBCMinorVersion() throws java.sql.SQLException;
+    method public abstract int getMaxBinaryLiteralLength() throws java.sql.SQLException;
+    method public abstract int getMaxCatalogNameLength() throws java.sql.SQLException;
+    method public abstract int getMaxCharLiteralLength() throws java.sql.SQLException;
+    method public abstract int getMaxColumnNameLength() throws java.sql.SQLException;
+    method public abstract int getMaxColumnsInGroupBy() throws java.sql.SQLException;
+    method public abstract int getMaxColumnsInIndex() throws java.sql.SQLException;
+    method public abstract int getMaxColumnsInOrderBy() throws java.sql.SQLException;
+    method public abstract int getMaxColumnsInSelect() throws java.sql.SQLException;
+    method public abstract int getMaxColumnsInTable() throws java.sql.SQLException;
+    method public abstract int getMaxConnections() throws java.sql.SQLException;
+    method public abstract int getMaxCursorNameLength() throws java.sql.SQLException;
+    method public abstract int getMaxIndexLength() throws java.sql.SQLException;
+    method public abstract int getMaxProcedureNameLength() throws java.sql.SQLException;
+    method public abstract int getMaxRowSize() throws java.sql.SQLException;
+    method public abstract int getMaxSchemaNameLength() throws java.sql.SQLException;
+    method public abstract int getMaxStatementLength() throws java.sql.SQLException;
+    method public abstract int getMaxStatements() throws java.sql.SQLException;
+    method public abstract int getMaxTableNameLength() throws java.sql.SQLException;
+    method public abstract int getMaxTablesInSelect() throws java.sql.SQLException;
+    method public abstract int getMaxUserNameLength() throws java.sql.SQLException;
+    method public abstract java.lang.String getNumericFunctions() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getPrimaryKeys(java.lang.String, java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getProcedureColumns(java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract java.lang.String getProcedureTerm() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getProcedures(java.lang.String, java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract int getResultSetHoldability() throws java.sql.SQLException;
+    method public abstract java.sql.RowIdLifetime getRowIdLifetime() throws java.sql.SQLException;
+    method public abstract java.lang.String getSQLKeywords() throws java.sql.SQLException;
+    method public abstract int getSQLStateType() throws java.sql.SQLException;
+    method public abstract java.lang.String getSchemaTerm() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getSchemas() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getSchemas(java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract java.lang.String getSearchStringEscape() throws java.sql.SQLException;
+    method public abstract java.lang.String getStringFunctions() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getSuperTables(java.lang.String, java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getSuperTypes(java.lang.String, java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract java.lang.String getSystemFunctions() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getTablePrivileges(java.lang.String, java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getTableTypes() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getTables(java.lang.String, java.lang.String, java.lang.String, java.lang.String[]) throws java.sql.SQLException;
+    method public abstract java.lang.String getTimeDateFunctions() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getTypeInfo() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getUDTs(java.lang.String, java.lang.String, java.lang.String, int[]) throws java.sql.SQLException;
+    method public abstract java.lang.String getURL() throws java.sql.SQLException;
+    method public abstract java.lang.String getUserName() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getVersionColumns(java.lang.String, java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract boolean insertsAreDetected(int) throws java.sql.SQLException;
+    method public abstract boolean isCatalogAtStart() throws java.sql.SQLException;
+    method public abstract boolean isReadOnly() throws java.sql.SQLException;
+    method public abstract boolean locatorsUpdateCopy() throws java.sql.SQLException;
+    method public abstract boolean nullPlusNonNullIsNull() throws java.sql.SQLException;
+    method public abstract boolean nullsAreSortedAtEnd() throws java.sql.SQLException;
+    method public abstract boolean nullsAreSortedAtStart() throws java.sql.SQLException;
+    method public abstract boolean nullsAreSortedHigh() throws java.sql.SQLException;
+    method public abstract boolean nullsAreSortedLow() throws java.sql.SQLException;
+    method public abstract boolean othersDeletesAreVisible(int) throws java.sql.SQLException;
+    method public abstract boolean othersInsertsAreVisible(int) throws java.sql.SQLException;
+    method public abstract boolean othersUpdatesAreVisible(int) throws java.sql.SQLException;
+    method public abstract boolean ownDeletesAreVisible(int) throws java.sql.SQLException;
+    method public abstract boolean ownInsertsAreVisible(int) throws java.sql.SQLException;
+    method public abstract boolean ownUpdatesAreVisible(int) throws java.sql.SQLException;
+    method public abstract boolean storesLowerCaseIdentifiers() throws java.sql.SQLException;
+    method public abstract boolean storesLowerCaseQuotedIdentifiers() throws java.sql.SQLException;
+    method public abstract boolean storesMixedCaseIdentifiers() throws java.sql.SQLException;
+    method public abstract boolean storesMixedCaseQuotedIdentifiers() throws java.sql.SQLException;
+    method public abstract boolean storesUpperCaseIdentifiers() throws java.sql.SQLException;
+    method public abstract boolean storesUpperCaseQuotedIdentifiers() throws java.sql.SQLException;
+    method public abstract boolean supportsANSI92EntryLevelSQL() throws java.sql.SQLException;
+    method public abstract boolean supportsANSI92FullSQL() throws java.sql.SQLException;
+    method public abstract boolean supportsANSI92IntermediateSQL() throws java.sql.SQLException;
+    method public abstract boolean supportsAlterTableWithAddColumn() throws java.sql.SQLException;
+    method public abstract boolean supportsAlterTableWithDropColumn() throws java.sql.SQLException;
+    method public abstract boolean supportsBatchUpdates() throws java.sql.SQLException;
+    method public abstract boolean supportsCatalogsInDataManipulation() throws java.sql.SQLException;
+    method public abstract boolean supportsCatalogsInIndexDefinitions() throws java.sql.SQLException;
+    method public abstract boolean supportsCatalogsInPrivilegeDefinitions() throws java.sql.SQLException;
+    method public abstract boolean supportsCatalogsInProcedureCalls() throws java.sql.SQLException;
+    method public abstract boolean supportsCatalogsInTableDefinitions() throws java.sql.SQLException;
+    method public abstract boolean supportsColumnAliasing() throws java.sql.SQLException;
+    method public abstract boolean supportsConvert() throws java.sql.SQLException;
+    method public abstract boolean supportsConvert(int, int) throws java.sql.SQLException;
+    method public abstract boolean supportsCoreSQLGrammar() throws java.sql.SQLException;
+    method public abstract boolean supportsCorrelatedSubqueries() throws java.sql.SQLException;
+    method public abstract boolean supportsDataDefinitionAndDataManipulationTransactions() throws java.sql.SQLException;
+    method public abstract boolean supportsDataManipulationTransactionsOnly() throws java.sql.SQLException;
+    method public abstract boolean supportsDifferentTableCorrelationNames() throws java.sql.SQLException;
+    method public abstract boolean supportsExpressionsInOrderBy() throws java.sql.SQLException;
+    method public abstract boolean supportsExtendedSQLGrammar() throws java.sql.SQLException;
+    method public abstract boolean supportsFullOuterJoins() throws java.sql.SQLException;
+    method public abstract boolean supportsGetGeneratedKeys() throws java.sql.SQLException;
+    method public abstract boolean supportsGroupBy() throws java.sql.SQLException;
+    method public abstract boolean supportsGroupByBeyondSelect() throws java.sql.SQLException;
+    method public abstract boolean supportsGroupByUnrelated() throws java.sql.SQLException;
+    method public abstract boolean supportsIntegrityEnhancementFacility() throws java.sql.SQLException;
+    method public abstract boolean supportsLikeEscapeClause() throws java.sql.SQLException;
+    method public abstract boolean supportsLimitedOuterJoins() throws java.sql.SQLException;
+    method public abstract boolean supportsMinimumSQLGrammar() throws java.sql.SQLException;
+    method public abstract boolean supportsMixedCaseIdentifiers() throws java.sql.SQLException;
+    method public abstract boolean supportsMixedCaseQuotedIdentifiers() throws java.sql.SQLException;
+    method public abstract boolean supportsMultipleOpenResults() throws java.sql.SQLException;
+    method public abstract boolean supportsMultipleResultSets() throws java.sql.SQLException;
+    method public abstract boolean supportsMultipleTransactions() throws java.sql.SQLException;
+    method public abstract boolean supportsNamedParameters() throws java.sql.SQLException;
+    method public abstract boolean supportsNonNullableColumns() throws java.sql.SQLException;
+    method public abstract boolean supportsOpenCursorsAcrossCommit() throws java.sql.SQLException;
+    method public abstract boolean supportsOpenCursorsAcrossRollback() throws java.sql.SQLException;
+    method public abstract boolean supportsOpenStatementsAcrossCommit() throws java.sql.SQLException;
+    method public abstract boolean supportsOpenStatementsAcrossRollback() throws java.sql.SQLException;
+    method public abstract boolean supportsOrderByUnrelated() throws java.sql.SQLException;
+    method public abstract boolean supportsOuterJoins() throws java.sql.SQLException;
+    method public abstract boolean supportsPositionedDelete() throws java.sql.SQLException;
+    method public abstract boolean supportsPositionedUpdate() throws java.sql.SQLException;
+    method public abstract boolean supportsResultSetConcurrency(int, int) throws java.sql.SQLException;
+    method public abstract boolean supportsResultSetHoldability(int) throws java.sql.SQLException;
+    method public abstract boolean supportsResultSetType(int) throws java.sql.SQLException;
+    method public abstract boolean supportsSavepoints() throws java.sql.SQLException;
+    method public abstract boolean supportsSchemasInDataManipulation() throws java.sql.SQLException;
+    method public abstract boolean supportsSchemasInIndexDefinitions() throws java.sql.SQLException;
+    method public abstract boolean supportsSchemasInPrivilegeDefinitions() throws java.sql.SQLException;
+    method public abstract boolean supportsSchemasInProcedureCalls() throws java.sql.SQLException;
+    method public abstract boolean supportsSchemasInTableDefinitions() throws java.sql.SQLException;
+    method public abstract boolean supportsSelectForUpdate() throws java.sql.SQLException;
+    method public abstract boolean supportsStatementPooling() throws java.sql.SQLException;
+    method public abstract boolean supportsStoredFunctionsUsingCallSyntax() throws java.sql.SQLException;
+    method public abstract boolean supportsStoredProcedures() throws java.sql.SQLException;
+    method public abstract boolean supportsSubqueriesInComparisons() throws java.sql.SQLException;
+    method public abstract boolean supportsSubqueriesInExists() throws java.sql.SQLException;
+    method public abstract boolean supportsSubqueriesInIns() throws java.sql.SQLException;
+    method public abstract boolean supportsSubqueriesInQuantifieds() throws java.sql.SQLException;
+    method public abstract boolean supportsTableCorrelationNames() throws java.sql.SQLException;
+    method public abstract boolean supportsTransactionIsolationLevel(int) throws java.sql.SQLException;
+    method public abstract boolean supportsTransactions() throws java.sql.SQLException;
+    method public abstract boolean supportsUnion() throws java.sql.SQLException;
+    method public abstract boolean supportsUnionAll() throws java.sql.SQLException;
+    method public abstract boolean updatesAreDetected(int) throws java.sql.SQLException;
+    method public abstract boolean usesLocalFilePerTable() throws java.sql.SQLException;
+    method public abstract boolean usesLocalFiles() throws java.sql.SQLException;
+    field public static final short attributeNoNulls = 0; // 0x0
+    field public static final short attributeNullable = 1; // 0x1
+    field public static final short attributeNullableUnknown = 2; // 0x2
+    field public static final int bestRowNotPseudo = 1; // 0x1
+    field public static final int bestRowPseudo = 2; // 0x2
+    field public static final int bestRowSession = 2; // 0x2
+    field public static final int bestRowTemporary = 0; // 0x0
+    field public static final int bestRowTransaction = 1; // 0x1
+    field public static final int bestRowUnknown = 0; // 0x0
+    field public static final int columnNoNulls = 0; // 0x0
+    field public static final int columnNullable = 1; // 0x1
+    field public static final int columnNullableUnknown = 2; // 0x2
+    field public static final int functionColumnIn = 1; // 0x1
+    field public static final int functionColumnInOut = 2; // 0x2
+    field public static final int functionColumnOut = 3; // 0x3
+    field public static final int functionColumnResult = 5; // 0x5
+    field public static final int functionColumnUnknown = 0; // 0x0
+    field public static final int functionNoNulls = 0; // 0x0
+    field public static final int functionNoTable = 1; // 0x1
+    field public static final int functionNullable = 1; // 0x1
+    field public static final int functionNullableUnknown = 2; // 0x2
+    field public static final int functionResultUnknown = 0; // 0x0
+    field public static final int functionReturn = 4; // 0x4
+    field public static final int functionReturnsTable = 2; // 0x2
+    field public static final int importedKeyCascade = 0; // 0x0
+    field public static final int importedKeyInitiallyDeferred = 5; // 0x5
+    field public static final int importedKeyInitiallyImmediate = 6; // 0x6
+    field public static final int importedKeyNoAction = 3; // 0x3
+    field public static final int importedKeyNotDeferrable = 7; // 0x7
+    field public static final int importedKeyRestrict = 1; // 0x1
+    field public static final int importedKeySetDefault = 4; // 0x4
+    field public static final int importedKeySetNull = 2; // 0x2
+    field public static final int procedureColumnIn = 1; // 0x1
+    field public static final int procedureColumnInOut = 2; // 0x2
+    field public static final int procedureColumnOut = 4; // 0x4
+    field public static final int procedureColumnResult = 3; // 0x3
+    field public static final int procedureColumnReturn = 5; // 0x5
+    field public static final int procedureColumnUnknown = 0; // 0x0
+    field public static final int procedureNoNulls = 0; // 0x0
+    field public static final int procedureNoResult = 1; // 0x1
+    field public static final int procedureNullable = 1; // 0x1
+    field public static final int procedureNullableUnknown = 2; // 0x2
+    field public static final int procedureResultUnknown = 0; // 0x0
+    field public static final int procedureReturnsResult = 2; // 0x2
+    field public static final int sqlStateSQL = 2; // 0x2
+    field public static final int sqlStateSQL99 = 2; // 0x2
+    field public static final int sqlStateXOpen = 1; // 0x1
+    field public static final short tableIndexClustered = 1; // 0x1
+    field public static final short tableIndexHashed = 2; // 0x2
+    field public static final short tableIndexOther = 3; // 0x3
+    field public static final short tableIndexStatistic = 0; // 0x0
+    field public static final int typeNoNulls = 0; // 0x0
+    field public static final int typeNullable = 1; // 0x1
+    field public static final int typeNullableUnknown = 2; // 0x2
+    field public static final int typePredBasic = 2; // 0x2
+    field public static final int typePredChar = 1; // 0x1
+    field public static final int typePredNone = 0; // 0x0
+    field public static final int typeSearchable = 3; // 0x3
+    field public static final int versionColumnNotPseudo = 1; // 0x1
+    field public static final int versionColumnPseudo = 2; // 0x2
+    field public static final int versionColumnUnknown = 0; // 0x0
+  }
+
+  public class Date extends java.util.Date {
+    ctor public deprecated Date(int, int, int);
+    ctor public Date(long);
+    method public static java.sql.Date valueOf(java.lang.String);
+  }
+
+  public abstract interface Driver {
+    method public abstract boolean acceptsURL(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.Connection connect(java.lang.String, java.util.Properties) throws java.sql.SQLException;
+    method public abstract int getMajorVersion();
+    method public abstract int getMinorVersion();
+    method public abstract java.sql.DriverPropertyInfo[] getPropertyInfo(java.lang.String, java.util.Properties) throws java.sql.SQLException;
+    method public abstract boolean jdbcCompliant();
+  }
+
+  public class DriverManager {
+    method public static void deregisterDriver(java.sql.Driver) throws java.sql.SQLException;
+    method public static java.sql.Connection getConnection(java.lang.String) throws java.sql.SQLException;
+    method public static java.sql.Connection getConnection(java.lang.String, java.util.Properties) throws java.sql.SQLException;
+    method public static java.sql.Connection getConnection(java.lang.String, java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public static java.sql.Driver getDriver(java.lang.String) throws java.sql.SQLException;
+    method public static java.util.Enumeration<java.sql.Driver> getDrivers();
+    method public static deprecated java.io.PrintStream getLogStream();
+    method public static java.io.PrintWriter getLogWriter();
+    method public static int getLoginTimeout();
+    method public static void println(java.lang.String);
+    method public static void registerDriver(java.sql.Driver) throws java.sql.SQLException;
+    method public static deprecated void setLogStream(java.io.PrintStream);
+    method public static void setLogWriter(java.io.PrintWriter);
+    method public static void setLoginTimeout(int);
+  }
+
+  public class DriverPropertyInfo {
+    ctor public DriverPropertyInfo(java.lang.String, java.lang.String);
+    field public java.lang.String[] choices;
+    field public java.lang.String description;
+    field public java.lang.String name;
+    field public boolean required;
+    field public java.lang.String value;
+  }
+
+  public abstract interface NClob implements java.sql.Clob {
+  }
+
+  public abstract interface ParameterMetaData implements java.sql.Wrapper {
+    method public abstract java.lang.String getParameterClassName(int) throws java.sql.SQLException;
+    method public abstract int getParameterCount() throws java.sql.SQLException;
+    method public abstract int getParameterMode(int) throws java.sql.SQLException;
+    method public abstract int getParameterType(int) throws java.sql.SQLException;
+    method public abstract java.lang.String getParameterTypeName(int) throws java.sql.SQLException;
+    method public abstract int getPrecision(int) throws java.sql.SQLException;
+    method public abstract int getScale(int) throws java.sql.SQLException;
+    method public abstract int isNullable(int) throws java.sql.SQLException;
+    method public abstract boolean isSigned(int) throws java.sql.SQLException;
+    field public static final int parameterModeIn = 1; // 0x1
+    field public static final int parameterModeInOut = 2; // 0x2
+    field public static final int parameterModeOut = 4; // 0x4
+    field public static final int parameterModeUnknown = 0; // 0x0
+    field public static final int parameterNoNulls = 0; // 0x0
+    field public static final int parameterNullable = 1; // 0x1
+    field public static final int parameterNullableUnknown = 2; // 0x2
+  }
+
+  public abstract interface PreparedStatement implements java.sql.Statement {
+    method public abstract void addBatch() throws java.sql.SQLException;
+    method public abstract void clearParameters() throws java.sql.SQLException;
+    method public abstract boolean execute() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet executeQuery() throws java.sql.SQLException;
+    method public abstract int executeUpdate() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSetMetaData getMetaData() throws java.sql.SQLException;
+    method public abstract java.sql.ParameterMetaData getParameterMetaData() throws java.sql.SQLException;
+    method public abstract void setArray(int, java.sql.Array) throws java.sql.SQLException;
+    method public abstract void setAsciiStream(int, java.io.InputStream, int) throws java.sql.SQLException;
+    method public abstract void setAsciiStream(int, java.io.InputStream, long) throws java.sql.SQLException;
+    method public abstract void setAsciiStream(int, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void setBigDecimal(int, java.math.BigDecimal) throws java.sql.SQLException;
+    method public abstract void setBinaryStream(int, java.io.InputStream, int) throws java.sql.SQLException;
+    method public abstract void setBinaryStream(int, java.io.InputStream, long) throws java.sql.SQLException;
+    method public abstract void setBinaryStream(int, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void setBlob(int, java.sql.Blob) throws java.sql.SQLException;
+    method public abstract void setBlob(int, java.io.InputStream, long) throws java.sql.SQLException;
+    method public abstract void setBlob(int, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void setBoolean(int, boolean) throws java.sql.SQLException;
+    method public abstract void setByte(int, byte) throws java.sql.SQLException;
+    method public abstract void setBytes(int, byte[]) throws java.sql.SQLException;
+    method public abstract void setCharacterStream(int, java.io.Reader, int) throws java.sql.SQLException;
+    method public abstract void setCharacterStream(int, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void setCharacterStream(int, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void setClob(int, java.sql.Clob) throws java.sql.SQLException;
+    method public abstract void setClob(int, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void setClob(int, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void setDate(int, java.sql.Date) throws java.sql.SQLException;
+    method public abstract void setDate(int, java.sql.Date, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract void setDouble(int, double) throws java.sql.SQLException;
+    method public abstract void setFloat(int, float) throws java.sql.SQLException;
+    method public abstract void setInt(int, int) throws java.sql.SQLException;
+    method public abstract void setLong(int, long) throws java.sql.SQLException;
+    method public abstract void setNCharacterStream(int, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void setNCharacterStream(int, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void setNClob(int, java.sql.NClob) throws java.sql.SQLException;
+    method public abstract void setNClob(int, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void setNClob(int, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void setNString(int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setNull(int, int) throws java.sql.SQLException;
+    method public abstract void setNull(int, int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setObject(int, java.lang.Object) throws java.sql.SQLException;
+    method public abstract void setObject(int, java.lang.Object, int) throws java.sql.SQLException;
+    method public abstract void setObject(int, java.lang.Object, int, int) throws java.sql.SQLException;
+    method public abstract void setRef(int, java.sql.Ref) throws java.sql.SQLException;
+    method public abstract void setRowId(int, java.sql.RowId) throws java.sql.SQLException;
+    method public abstract void setSQLXML(int, java.sql.SQLXML) throws java.sql.SQLException;
+    method public abstract void setShort(int, short) throws java.sql.SQLException;
+    method public abstract void setString(int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setTime(int, java.sql.Time) throws java.sql.SQLException;
+    method public abstract void setTime(int, java.sql.Time, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract void setTimestamp(int, java.sql.Timestamp) throws java.sql.SQLException;
+    method public abstract void setTimestamp(int, java.sql.Timestamp, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract void setURL(int, java.net.URL) throws java.sql.SQLException;
+    method public abstract deprecated void setUnicodeStream(int, java.io.InputStream, int) throws java.sql.SQLException;
+  }
+
+  public abstract interface Ref {
+    method public abstract java.lang.String getBaseTypeName() throws java.sql.SQLException;
+    method public abstract java.lang.Object getObject() throws java.sql.SQLException;
+    method public abstract java.lang.Object getObject(java.util.Map<java.lang.String, java.lang.Class<?>>) throws java.sql.SQLException;
+    method public abstract void setObject(java.lang.Object) throws java.sql.SQLException;
+  }
+
+  public abstract interface ResultSet implements java.sql.Wrapper {
+    method public abstract boolean absolute(int) throws java.sql.SQLException;
+    method public abstract void afterLast() throws java.sql.SQLException;
+    method public abstract void beforeFirst() throws java.sql.SQLException;
+    method public abstract void cancelRowUpdates() throws java.sql.SQLException;
+    method public abstract void clearWarnings() throws java.sql.SQLException;
+    method public abstract void close() throws java.sql.SQLException;
+    method public abstract void deleteRow() throws java.sql.SQLException;
+    method public abstract int findColumn(java.lang.String) throws java.sql.SQLException;
+    method public abstract boolean first() throws java.sql.SQLException;
+    method public abstract java.sql.Array getArray(int) throws java.sql.SQLException;
+    method public abstract java.sql.Array getArray(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.io.InputStream getAsciiStream(int) throws java.sql.SQLException;
+    method public abstract java.io.InputStream getAsciiStream(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.math.BigDecimal getBigDecimal(int) throws java.sql.SQLException;
+    method public abstract deprecated java.math.BigDecimal getBigDecimal(int, int) throws java.sql.SQLException;
+    method public abstract java.math.BigDecimal getBigDecimal(java.lang.String) throws java.sql.SQLException;
+    method public abstract deprecated java.math.BigDecimal getBigDecimal(java.lang.String, int) throws java.sql.SQLException;
+    method public abstract java.io.InputStream getBinaryStream(int) throws java.sql.SQLException;
+    method public abstract java.io.InputStream getBinaryStream(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.Blob getBlob(int) throws java.sql.SQLException;
+    method public abstract java.sql.Blob getBlob(java.lang.String) throws java.sql.SQLException;
+    method public abstract boolean getBoolean(int) throws java.sql.SQLException;
+    method public abstract boolean getBoolean(java.lang.String) throws java.sql.SQLException;
+    method public abstract byte getByte(int) throws java.sql.SQLException;
+    method public abstract byte getByte(java.lang.String) throws java.sql.SQLException;
+    method public abstract byte[] getBytes(int) throws java.sql.SQLException;
+    method public abstract byte[] getBytes(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.io.Reader getCharacterStream(int) throws java.sql.SQLException;
+    method public abstract java.io.Reader getCharacterStream(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.Clob getClob(int) throws java.sql.SQLException;
+    method public abstract java.sql.Clob getClob(java.lang.String) throws java.sql.SQLException;
+    method public abstract int getConcurrency() throws java.sql.SQLException;
+    method public abstract java.lang.String getCursorName() throws java.sql.SQLException;
+    method public abstract java.sql.Date getDate(int) throws java.sql.SQLException;
+    method public abstract java.sql.Date getDate(int, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract java.sql.Date getDate(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.Date getDate(java.lang.String, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract double getDouble(int) throws java.sql.SQLException;
+    method public abstract double getDouble(java.lang.String) throws java.sql.SQLException;
+    method public abstract int getFetchDirection() throws java.sql.SQLException;
+    method public abstract int getFetchSize() throws java.sql.SQLException;
+    method public abstract float getFloat(int) throws java.sql.SQLException;
+    method public abstract float getFloat(java.lang.String) throws java.sql.SQLException;
+    method public abstract int getHoldability() throws java.sql.SQLException;
+    method public abstract int getInt(int) throws java.sql.SQLException;
+    method public abstract int getInt(java.lang.String) throws java.sql.SQLException;
+    method public abstract long getLong(int) throws java.sql.SQLException;
+    method public abstract long getLong(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.ResultSetMetaData getMetaData() throws java.sql.SQLException;
+    method public abstract java.io.Reader getNCharacterStream(int) throws java.sql.SQLException;
+    method public abstract java.io.Reader getNCharacterStream(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.NClob getNClob(int) throws java.sql.SQLException;
+    method public abstract java.sql.NClob getNClob(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.lang.String getNString(int) throws java.sql.SQLException;
+    method public abstract java.lang.String getNString(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.lang.Object getObject(int) throws java.sql.SQLException;
+    method public abstract java.lang.Object getObject(int, java.util.Map<java.lang.String, java.lang.Class<?>>) throws java.sql.SQLException;
+    method public abstract java.lang.Object getObject(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.lang.Object getObject(java.lang.String, java.util.Map<java.lang.String, java.lang.Class<?>>) throws java.sql.SQLException;
+    method public abstract java.sql.Ref getRef(int) throws java.sql.SQLException;
+    method public abstract java.sql.Ref getRef(java.lang.String) throws java.sql.SQLException;
+    method public abstract int getRow() throws java.sql.SQLException;
+    method public abstract java.sql.RowId getRowId(int) throws java.sql.SQLException;
+    method public abstract java.sql.RowId getRowId(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.SQLXML getSQLXML(int) throws java.sql.SQLException;
+    method public abstract java.sql.SQLXML getSQLXML(java.lang.String) throws java.sql.SQLException;
+    method public abstract short getShort(int) throws java.sql.SQLException;
+    method public abstract short getShort(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.Statement getStatement() throws java.sql.SQLException;
+    method public abstract java.lang.String getString(int) throws java.sql.SQLException;
+    method public abstract java.lang.String getString(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.Time getTime(int) throws java.sql.SQLException;
+    method public abstract java.sql.Time getTime(int, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract java.sql.Time getTime(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.Time getTime(java.lang.String, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract java.sql.Timestamp getTimestamp(int) throws java.sql.SQLException;
+    method public abstract java.sql.Timestamp getTimestamp(int, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract java.sql.Timestamp getTimestamp(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.Timestamp getTimestamp(java.lang.String, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract int getType() throws java.sql.SQLException;
+    method public abstract java.net.URL getURL(int) throws java.sql.SQLException;
+    method public abstract java.net.URL getURL(java.lang.String) throws java.sql.SQLException;
+    method public abstract deprecated java.io.InputStream getUnicodeStream(int) throws java.sql.SQLException;
+    method public abstract deprecated java.io.InputStream getUnicodeStream(java.lang.String) throws java.sql.SQLException;
+    method public abstract java.sql.SQLWarning getWarnings() throws java.sql.SQLException;
+    method public abstract void insertRow() throws java.sql.SQLException;
+    method public abstract boolean isAfterLast() throws java.sql.SQLException;
+    method public abstract boolean isBeforeFirst() throws java.sql.SQLException;
+    method public abstract boolean isClosed() throws java.sql.SQLException;
+    method public abstract boolean isFirst() throws java.sql.SQLException;
+    method public abstract boolean isLast() throws java.sql.SQLException;
+    method public abstract boolean last() throws java.sql.SQLException;
+    method public abstract void moveToCurrentRow() throws java.sql.SQLException;
+    method public abstract void moveToInsertRow() throws java.sql.SQLException;
+    method public abstract boolean next() throws java.sql.SQLException;
+    method public abstract boolean previous() throws java.sql.SQLException;
+    method public abstract void refreshRow() throws java.sql.SQLException;
+    method public abstract boolean relative(int) throws java.sql.SQLException;
+    method public abstract boolean rowDeleted() throws java.sql.SQLException;
+    method public abstract boolean rowInserted() throws java.sql.SQLException;
+    method public abstract boolean rowUpdated() throws java.sql.SQLException;
+    method public abstract void setFetchDirection(int) throws java.sql.SQLException;
+    method public abstract void setFetchSize(int) throws java.sql.SQLException;
+    method public abstract void updateArray(int, java.sql.Array) throws java.sql.SQLException;
+    method public abstract void updateArray(java.lang.String, java.sql.Array) throws java.sql.SQLException;
+    method public abstract void updateAsciiStream(int, java.io.InputStream, int) throws java.sql.SQLException;
+    method public abstract void updateAsciiStream(java.lang.String, java.io.InputStream, int) throws java.sql.SQLException;
+    method public abstract void updateAsciiStream(int, java.io.InputStream, long) throws java.sql.SQLException;
+    method public abstract void updateAsciiStream(java.lang.String, java.io.InputStream, long) throws java.sql.SQLException;
+    method public abstract void updateAsciiStream(int, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void updateAsciiStream(java.lang.String, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void updateBigDecimal(int, java.math.BigDecimal) throws java.sql.SQLException;
+    method public abstract void updateBigDecimal(java.lang.String, java.math.BigDecimal) throws java.sql.SQLException;
+    method public abstract void updateBinaryStream(int, java.io.InputStream, int) throws java.sql.SQLException;
+    method public abstract void updateBinaryStream(java.lang.String, java.io.InputStream, int) throws java.sql.SQLException;
+    method public abstract void updateBinaryStream(int, java.io.InputStream, long) throws java.sql.SQLException;
+    method public abstract void updateBinaryStream(java.lang.String, java.io.InputStream, long) throws java.sql.SQLException;
+    method public abstract void updateBinaryStream(int, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void updateBinaryStream(java.lang.String, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void updateBlob(int, java.sql.Blob) throws java.sql.SQLException;
+    method public abstract void updateBlob(java.lang.String, java.sql.Blob) throws java.sql.SQLException;
+    method public abstract void updateBlob(int, java.io.InputStream, long) throws java.sql.SQLException;
+    method public abstract void updateBlob(java.lang.String, java.io.InputStream, long) throws java.sql.SQLException;
+    method public abstract void updateBlob(int, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void updateBlob(java.lang.String, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void updateBoolean(int, boolean) throws java.sql.SQLException;
+    method public abstract void updateBoolean(java.lang.String, boolean) throws java.sql.SQLException;
+    method public abstract void updateByte(int, byte) throws java.sql.SQLException;
+    method public abstract void updateByte(java.lang.String, byte) throws java.sql.SQLException;
+    method public abstract void updateBytes(int, byte[]) throws java.sql.SQLException;
+    method public abstract void updateBytes(java.lang.String, byte[]) throws java.sql.SQLException;
+    method public abstract void updateCharacterStream(int, java.io.Reader, int) throws java.sql.SQLException;
+    method public abstract void updateCharacterStream(java.lang.String, java.io.Reader, int) throws java.sql.SQLException;
+    method public abstract void updateCharacterStream(int, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void updateCharacterStream(java.lang.String, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void updateCharacterStream(int, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void updateCharacterStream(java.lang.String, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void updateClob(int, java.sql.Clob) throws java.sql.SQLException;
+    method public abstract void updateClob(java.lang.String, java.sql.Clob) throws java.sql.SQLException;
+    method public abstract void updateClob(int, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void updateClob(java.lang.String, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void updateClob(int, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void updateClob(java.lang.String, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void updateDate(int, java.sql.Date) throws java.sql.SQLException;
+    method public abstract void updateDate(java.lang.String, java.sql.Date) throws java.sql.SQLException;
+    method public abstract void updateDouble(int, double) throws java.sql.SQLException;
+    method public abstract void updateDouble(java.lang.String, double) throws java.sql.SQLException;
+    method public abstract void updateFloat(int, float) throws java.sql.SQLException;
+    method public abstract void updateFloat(java.lang.String, float) throws java.sql.SQLException;
+    method public abstract void updateInt(int, int) throws java.sql.SQLException;
+    method public abstract void updateInt(java.lang.String, int) throws java.sql.SQLException;
+    method public abstract void updateLong(int, long) throws java.sql.SQLException;
+    method public abstract void updateLong(java.lang.String, long) throws java.sql.SQLException;
+    method public abstract void updateNCharacterStream(int, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void updateNCharacterStream(java.lang.String, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void updateNCharacterStream(int, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void updateNCharacterStream(java.lang.String, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void updateNClob(int, java.sql.NClob) throws java.sql.SQLException;
+    method public abstract void updateNClob(java.lang.String, java.sql.NClob) throws java.sql.SQLException;
+    method public abstract void updateNClob(int, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void updateNClob(java.lang.String, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void updateNClob(int, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void updateNClob(java.lang.String, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void updateNString(int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void updateNString(java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract void updateNull(int) throws java.sql.SQLException;
+    method public abstract void updateNull(java.lang.String) throws java.sql.SQLException;
+    method public abstract void updateObject(int, java.lang.Object) throws java.sql.SQLException;
+    method public abstract void updateObject(int, java.lang.Object, int) throws java.sql.SQLException;
+    method public abstract void updateObject(java.lang.String, java.lang.Object) throws java.sql.SQLException;
+    method public abstract void updateObject(java.lang.String, java.lang.Object, int) throws java.sql.SQLException;
+    method public abstract void updateRef(int, java.sql.Ref) throws java.sql.SQLException;
+    method public abstract void updateRef(java.lang.String, java.sql.Ref) throws java.sql.SQLException;
+    method public abstract void updateRow() throws java.sql.SQLException;
+    method public abstract void updateRowId(int, java.sql.RowId) throws java.sql.SQLException;
+    method public abstract void updateRowId(java.lang.String, java.sql.RowId) throws java.sql.SQLException;
+    method public abstract void updateSQLXML(int, java.sql.SQLXML) throws java.sql.SQLException;
+    method public abstract void updateSQLXML(java.lang.String, java.sql.SQLXML) throws java.sql.SQLException;
+    method public abstract void updateShort(int, short) throws java.sql.SQLException;
+    method public abstract void updateShort(java.lang.String, short) throws java.sql.SQLException;
+    method public abstract void updateString(int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void updateString(java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract void updateTime(int, java.sql.Time) throws java.sql.SQLException;
+    method public abstract void updateTime(java.lang.String, java.sql.Time) throws java.sql.SQLException;
+    method public abstract void updateTimestamp(int, java.sql.Timestamp) throws java.sql.SQLException;
+    method public abstract void updateTimestamp(java.lang.String, java.sql.Timestamp) throws java.sql.SQLException;
+    method public abstract boolean wasNull() throws java.sql.SQLException;
+    field public static final int CLOSE_CURSORS_AT_COMMIT = 2; // 0x2
+    field public static final int CONCUR_READ_ONLY = 1007; // 0x3ef
+    field public static final int CONCUR_UPDATABLE = 1008; // 0x3f0
+    field public static final int FETCH_FORWARD = 1000; // 0x3e8
+    field public static final int FETCH_REVERSE = 1001; // 0x3e9
+    field public static final int FETCH_UNKNOWN = 1002; // 0x3ea
+    field public static final int HOLD_CURSORS_OVER_COMMIT = 1; // 0x1
+    field public static final int TYPE_FORWARD_ONLY = 1003; // 0x3eb
+    field public static final int TYPE_SCROLL_INSENSITIVE = 1004; // 0x3ec
+    field public static final int TYPE_SCROLL_SENSITIVE = 1005; // 0x3ed
+  }
+
+  public abstract interface ResultSetMetaData implements java.sql.Wrapper {
+    method public abstract java.lang.String getCatalogName(int) throws java.sql.SQLException;
+    method public abstract java.lang.String getColumnClassName(int) throws java.sql.SQLException;
+    method public abstract int getColumnCount() throws java.sql.SQLException;
+    method public abstract int getColumnDisplaySize(int) throws java.sql.SQLException;
+    method public abstract java.lang.String getColumnLabel(int) throws java.sql.SQLException;
+    method public abstract java.lang.String getColumnName(int) throws java.sql.SQLException;
+    method public abstract int getColumnType(int) throws java.sql.SQLException;
+    method public abstract java.lang.String getColumnTypeName(int) throws java.sql.SQLException;
+    method public abstract int getPrecision(int) throws java.sql.SQLException;
+    method public abstract int getScale(int) throws java.sql.SQLException;
+    method public abstract java.lang.String getSchemaName(int) throws java.sql.SQLException;
+    method public abstract java.lang.String getTableName(int) throws java.sql.SQLException;
+    method public abstract boolean isAutoIncrement(int) throws java.sql.SQLException;
+    method public abstract boolean isCaseSensitive(int) throws java.sql.SQLException;
+    method public abstract boolean isCurrency(int) throws java.sql.SQLException;
+    method public abstract boolean isDefinitelyWritable(int) throws java.sql.SQLException;
+    method public abstract int isNullable(int) throws java.sql.SQLException;
+    method public abstract boolean isReadOnly(int) throws java.sql.SQLException;
+    method public abstract boolean isSearchable(int) throws java.sql.SQLException;
+    method public abstract boolean isSigned(int) throws java.sql.SQLException;
+    method public abstract boolean isWritable(int) throws java.sql.SQLException;
+    field public static final int columnNoNulls = 0; // 0x0
+    field public static final int columnNullable = 1; // 0x1
+    field public static final int columnNullableUnknown = 2; // 0x2
+  }
+
+  public abstract interface RowId {
+    method public abstract boolean equals(java.lang.Object);
+    method public abstract byte[] getBytes();
+    method public abstract int hashCode();
+    method public abstract java.lang.String toString();
+  }
+
+  public final class RowIdLifetime extends java.lang.Enum {
+    method public static java.sql.RowIdLifetime valueOf(java.lang.String);
+    method public static final java.sql.RowIdLifetime[] values();
+    enum_constant public static final java.sql.RowIdLifetime ROWID_UNSUPPORTED;
+    enum_constant public static final java.sql.RowIdLifetime ROWID_VALID_FOREVER;
+    enum_constant public static final java.sql.RowIdLifetime ROWID_VALID_OTHER;
+    enum_constant public static final java.sql.RowIdLifetime ROWID_VALID_SESSION;
+    enum_constant public static final java.sql.RowIdLifetime ROWID_VALID_TRANSACTION;
+  }
+
+  public class SQLClientInfoException extends java.sql.SQLException {
+    ctor public SQLClientInfoException();
+    ctor public SQLClientInfoException(java.util.Map<java.lang.String, java.sql.ClientInfoStatus>);
+    ctor public SQLClientInfoException(java.util.Map<java.lang.String, java.sql.ClientInfoStatus>, java.lang.Throwable);
+    ctor public SQLClientInfoException(java.lang.String, java.util.Map<java.lang.String, java.sql.ClientInfoStatus>);
+    ctor public SQLClientInfoException(java.lang.String, java.util.Map<java.lang.String, java.sql.ClientInfoStatus>, java.lang.Throwable);
+    ctor public SQLClientInfoException(java.lang.String, java.lang.String, int, java.util.Map<java.lang.String, java.sql.ClientInfoStatus>);
+    ctor public SQLClientInfoException(java.lang.String, java.lang.String, int, java.util.Map<java.lang.String, java.sql.ClientInfoStatus>, java.lang.Throwable);
+    ctor public SQLClientInfoException(java.lang.String, java.lang.String, java.util.Map<java.lang.String, java.sql.ClientInfoStatus>);
+    ctor public SQLClientInfoException(java.lang.String, java.lang.String, java.util.Map<java.lang.String, java.sql.ClientInfoStatus>, java.lang.Throwable);
+    method public java.util.Map<java.lang.String, java.sql.ClientInfoStatus> getFailedProperties();
+  }
+
+  public abstract interface SQLData {
+    method public abstract java.lang.String getSQLTypeName() throws java.sql.SQLException;
+    method public abstract void readSQL(java.sql.SQLInput, java.lang.String) throws java.sql.SQLException;
+    method public abstract void writeSQL(java.sql.SQLOutput) throws java.sql.SQLException;
+  }
+
+  public class SQLDataException extends java.sql.SQLNonTransientException {
+    ctor public SQLDataException();
+    ctor public SQLDataException(java.lang.String);
+    ctor public SQLDataException(java.lang.String, java.lang.String);
+    ctor public SQLDataException(java.lang.String, java.lang.String, int);
+    ctor public SQLDataException(java.lang.Throwable);
+    ctor public SQLDataException(java.lang.String, java.lang.Throwable);
+    ctor public SQLDataException(java.lang.String, java.lang.String, java.lang.Throwable);
+    ctor public SQLDataException(java.lang.String, java.lang.String, int, java.lang.Throwable);
+  }
+
+  public class SQLException extends java.lang.Exception implements java.lang.Iterable java.io.Serializable {
+    ctor public SQLException();
+    ctor public SQLException(java.lang.String);
+    ctor public SQLException(java.lang.String, java.lang.String);
+    ctor public SQLException(java.lang.String, java.lang.String, int);
+    ctor public SQLException(java.lang.Throwable);
+    ctor public SQLException(java.lang.String, java.lang.Throwable);
+    ctor public SQLException(java.lang.String, java.lang.String, java.lang.Throwable);
+    ctor public SQLException(java.lang.String, java.lang.String, int, java.lang.Throwable);
+    method public int getErrorCode();
+    method public java.sql.SQLException getNextException();
+    method public java.lang.String getSQLState();
+    method public java.util.Iterator<java.lang.Throwable> iterator();
+    method public void setNextException(java.sql.SQLException);
+  }
+
+  public class SQLFeatureNotSupportedException extends java.sql.SQLNonTransientException {
+    ctor public SQLFeatureNotSupportedException();
+    ctor public SQLFeatureNotSupportedException(java.lang.String);
+    ctor public SQLFeatureNotSupportedException(java.lang.String, java.lang.String);
+    ctor public SQLFeatureNotSupportedException(java.lang.String, java.lang.String, int);
+    ctor public SQLFeatureNotSupportedException(java.lang.Throwable);
+    ctor public SQLFeatureNotSupportedException(java.lang.String, java.lang.Throwable);
+    ctor public SQLFeatureNotSupportedException(java.lang.String, java.lang.String, java.lang.Throwable);
+    ctor public SQLFeatureNotSupportedException(java.lang.String, java.lang.String, int, java.lang.Throwable);
+  }
+
+  public abstract interface SQLInput {
+    method public abstract java.sql.Array readArray() throws java.sql.SQLException;
+    method public abstract java.io.InputStream readAsciiStream() throws java.sql.SQLException;
+    method public abstract java.math.BigDecimal readBigDecimal() throws java.sql.SQLException;
+    method public abstract java.io.InputStream readBinaryStream() throws java.sql.SQLException;
+    method public abstract java.sql.Blob readBlob() throws java.sql.SQLException;
+    method public abstract boolean readBoolean() throws java.sql.SQLException;
+    method public abstract byte readByte() throws java.sql.SQLException;
+    method public abstract byte[] readBytes() throws java.sql.SQLException;
+    method public abstract java.io.Reader readCharacterStream() throws java.sql.SQLException;
+    method public abstract java.sql.Clob readClob() throws java.sql.SQLException;
+    method public abstract java.sql.Date readDate() throws java.sql.SQLException;
+    method public abstract double readDouble() throws java.sql.SQLException;
+    method public abstract float readFloat() throws java.sql.SQLException;
+    method public abstract int readInt() throws java.sql.SQLException;
+    method public abstract long readLong() throws java.sql.SQLException;
+    method public abstract java.sql.NClob readNClob() throws java.sql.SQLException;
+    method public abstract java.lang.String readNString() throws java.sql.SQLException;
+    method public abstract java.lang.Object readObject() throws java.sql.SQLException;
+    method public abstract java.sql.Ref readRef() throws java.sql.SQLException;
+    method public abstract java.sql.RowId readRowId() throws java.sql.SQLException;
+    method public abstract java.sql.SQLXML readSQLXML() throws java.sql.SQLException;
+    method public abstract short readShort() throws java.sql.SQLException;
+    method public abstract java.lang.String readString() throws java.sql.SQLException;
+    method public abstract java.sql.Time readTime() throws java.sql.SQLException;
+    method public abstract java.sql.Timestamp readTimestamp() throws java.sql.SQLException;
+    method public abstract java.net.URL readURL() throws java.sql.SQLException;
+    method public abstract boolean wasNull() throws java.sql.SQLException;
+  }
+
+  public class SQLIntegrityConstraintViolationException extends java.sql.SQLNonTransientException {
+    ctor public SQLIntegrityConstraintViolationException();
+    ctor public SQLIntegrityConstraintViolationException(java.lang.String);
+    ctor public SQLIntegrityConstraintViolationException(java.lang.String, java.lang.String);
+    ctor public SQLIntegrityConstraintViolationException(java.lang.String, java.lang.String, int);
+    ctor public SQLIntegrityConstraintViolationException(java.lang.Throwable);
+    ctor public SQLIntegrityConstraintViolationException(java.lang.String, java.lang.Throwable);
+    ctor public SQLIntegrityConstraintViolationException(java.lang.String, java.lang.String, java.lang.Throwable);
+    ctor public SQLIntegrityConstraintViolationException(java.lang.String, java.lang.String, int, java.lang.Throwable);
+  }
+
+  public class SQLInvalidAuthorizationSpecException extends java.sql.SQLNonTransientException {
+    ctor public SQLInvalidAuthorizationSpecException();
+    ctor public SQLInvalidAuthorizationSpecException(java.lang.String);
+    ctor public SQLInvalidAuthorizationSpecException(java.lang.String, java.lang.String);
+    ctor public SQLInvalidAuthorizationSpecException(java.lang.String, java.lang.String, int);
+    ctor public SQLInvalidAuthorizationSpecException(java.lang.Throwable);
+    ctor public SQLInvalidAuthorizationSpecException(java.lang.String, java.lang.Throwable);
+    ctor public SQLInvalidAuthorizationSpecException(java.lang.String, java.lang.String, java.lang.Throwable);
+    ctor public SQLInvalidAuthorizationSpecException(java.lang.String, java.lang.String, int, java.lang.Throwable);
+  }
+
+  public class SQLNonTransientConnectionException extends java.sql.SQLNonTransientException {
+    ctor public SQLNonTransientConnectionException();
+    ctor public SQLNonTransientConnectionException(java.lang.String);
+    ctor public SQLNonTransientConnectionException(java.lang.String, java.lang.String);
+    ctor public SQLNonTransientConnectionException(java.lang.String, java.lang.String, int);
+    ctor public SQLNonTransientConnectionException(java.lang.Throwable);
+    ctor public SQLNonTransientConnectionException(java.lang.String, java.lang.Throwable);
+    ctor public SQLNonTransientConnectionException(java.lang.String, java.lang.String, java.lang.Throwable);
+    ctor public SQLNonTransientConnectionException(java.lang.String, java.lang.String, int, java.lang.Throwable);
+  }
+
+  public class SQLNonTransientException extends java.sql.SQLException {
+    ctor public SQLNonTransientException();
+    ctor public SQLNonTransientException(java.lang.String);
+    ctor public SQLNonTransientException(java.lang.String, java.lang.String);
+    ctor public SQLNonTransientException(java.lang.String, java.lang.String, int);
+    ctor public SQLNonTransientException(java.lang.Throwable);
+    ctor public SQLNonTransientException(java.lang.String, java.lang.Throwable);
+    ctor public SQLNonTransientException(java.lang.String, java.lang.String, java.lang.Throwable);
+    ctor public SQLNonTransientException(java.lang.String, java.lang.String, int, java.lang.Throwable);
+  }
+
+  public abstract interface SQLOutput {
+    method public abstract void writeArray(java.sql.Array) throws java.sql.SQLException;
+    method public abstract void writeAsciiStream(java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void writeBigDecimal(java.math.BigDecimal) throws java.sql.SQLException;
+    method public abstract void writeBinaryStream(java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void writeBlob(java.sql.Blob) throws java.sql.SQLException;
+    method public abstract void writeBoolean(boolean) throws java.sql.SQLException;
+    method public abstract void writeByte(byte) throws java.sql.SQLException;
+    method public abstract void writeBytes(byte[]) throws java.sql.SQLException;
+    method public abstract void writeCharacterStream(java.io.Reader) throws java.sql.SQLException;
+    method public abstract void writeClob(java.sql.Clob) throws java.sql.SQLException;
+    method public abstract void writeDate(java.sql.Date) throws java.sql.SQLException;
+    method public abstract void writeDouble(double) throws java.sql.SQLException;
+    method public abstract void writeFloat(float) throws java.sql.SQLException;
+    method public abstract void writeInt(int) throws java.sql.SQLException;
+    method public abstract void writeLong(long) throws java.sql.SQLException;
+    method public abstract void writeNClob(java.sql.NClob) throws java.sql.SQLException;
+    method public abstract void writeNString(java.lang.String) throws java.sql.SQLException;
+    method public abstract void writeObject(java.sql.SQLData) throws java.sql.SQLException;
+    method public abstract void writeRef(java.sql.Ref) throws java.sql.SQLException;
+    method public abstract void writeRowId(java.sql.RowId) throws java.sql.SQLException;
+    method public abstract void writeSQLXML(java.sql.SQLXML) throws java.sql.SQLException;
+    method public abstract void writeShort(short) throws java.sql.SQLException;
+    method public abstract void writeString(java.lang.String) throws java.sql.SQLException;
+    method public abstract void writeStruct(java.sql.Struct) throws java.sql.SQLException;
+    method public abstract void writeTime(java.sql.Time) throws java.sql.SQLException;
+    method public abstract void writeTimestamp(java.sql.Timestamp) throws java.sql.SQLException;
+    method public abstract void writeURL(java.net.URL) throws java.sql.SQLException;
+  }
+
+  public final class SQLPermission extends java.security.BasicPermission implements java.security.Guard java.io.Serializable {
+    ctor public SQLPermission(java.lang.String);
+    ctor public SQLPermission(java.lang.String, java.lang.String);
+  }
+
+  public class SQLRecoverableException extends java.sql.SQLException {
+    ctor public SQLRecoverableException();
+    ctor public SQLRecoverableException(java.lang.String);
+    ctor public SQLRecoverableException(java.lang.String, java.lang.String);
+    ctor public SQLRecoverableException(java.lang.String, java.lang.String, int);
+    ctor public SQLRecoverableException(java.lang.Throwable);
+    ctor public SQLRecoverableException(java.lang.String, java.lang.Throwable);
+    ctor public SQLRecoverableException(java.lang.String, java.lang.String, java.lang.Throwable);
+    ctor public SQLRecoverableException(java.lang.String, java.lang.String, int, java.lang.Throwable);
+  }
+
+  public class SQLSyntaxErrorException extends java.sql.SQLNonTransientException {
+    ctor public SQLSyntaxErrorException();
+    ctor public SQLSyntaxErrorException(java.lang.String);
+    ctor public SQLSyntaxErrorException(java.lang.String, java.lang.String);
+    ctor public SQLSyntaxErrorException(java.lang.String, java.lang.String, int);
+    ctor public SQLSyntaxErrorException(java.lang.Throwable);
+    ctor public SQLSyntaxErrorException(java.lang.String, java.lang.Throwable);
+    ctor public SQLSyntaxErrorException(java.lang.String, java.lang.String, java.lang.Throwable);
+    ctor public SQLSyntaxErrorException(java.lang.String, java.lang.String, int, java.lang.Throwable);
+  }
+
+  public class SQLTimeoutException extends java.sql.SQLTransientException {
+    ctor public SQLTimeoutException();
+    ctor public SQLTimeoutException(java.lang.String);
+    ctor public SQLTimeoutException(java.lang.String, java.lang.String);
+    ctor public SQLTimeoutException(java.lang.String, java.lang.String, int);
+    ctor public SQLTimeoutException(java.lang.Throwable);
+    ctor public SQLTimeoutException(java.lang.String, java.lang.Throwable);
+    ctor public SQLTimeoutException(java.lang.String, java.lang.String, java.lang.Throwable);
+    ctor public SQLTimeoutException(java.lang.String, java.lang.String, int, java.lang.Throwable);
+  }
+
+  public class SQLTransactionRollbackException extends java.sql.SQLTransientException {
+    ctor public SQLTransactionRollbackException();
+    ctor public SQLTransactionRollbackException(java.lang.String);
+    ctor public SQLTransactionRollbackException(java.lang.String, java.lang.String);
+    ctor public SQLTransactionRollbackException(java.lang.String, java.lang.String, int);
+    ctor public SQLTransactionRollbackException(java.lang.Throwable);
+    ctor public SQLTransactionRollbackException(java.lang.String, java.lang.Throwable);
+    ctor public SQLTransactionRollbackException(java.lang.String, java.lang.String, java.lang.Throwable);
+    ctor public SQLTransactionRollbackException(java.lang.String, java.lang.String, int, java.lang.Throwable);
+  }
+
+  public class SQLTransientConnectionException extends java.sql.SQLTransientException {
+    ctor public SQLTransientConnectionException();
+    ctor public SQLTransientConnectionException(java.lang.String);
+    ctor public SQLTransientConnectionException(java.lang.String, java.lang.String);
+    ctor public SQLTransientConnectionException(java.lang.String, java.lang.String, int);
+    ctor public SQLTransientConnectionException(java.lang.Throwable);
+    ctor public SQLTransientConnectionException(java.lang.String, java.lang.Throwable);
+    ctor public SQLTransientConnectionException(java.lang.String, java.lang.String, java.lang.Throwable);
+    ctor public SQLTransientConnectionException(java.lang.String, java.lang.String, int, java.lang.Throwable);
+  }
+
+  public class SQLTransientException extends java.sql.SQLException {
+    ctor public SQLTransientException();
+    ctor public SQLTransientException(java.lang.String);
+    ctor public SQLTransientException(java.lang.String, java.lang.String);
+    ctor public SQLTransientException(java.lang.String, java.lang.String, int);
+    ctor public SQLTransientException(java.lang.Throwable);
+    ctor public SQLTransientException(java.lang.String, java.lang.Throwable);
+    ctor public SQLTransientException(java.lang.String, java.lang.String, java.lang.Throwable);
+    ctor public SQLTransientException(java.lang.String, java.lang.String, int, java.lang.Throwable);
+  }
+
+  public class SQLWarning extends java.sql.SQLException implements java.io.Serializable {
+    ctor public SQLWarning();
+    ctor public SQLWarning(java.lang.String);
+    ctor public SQLWarning(java.lang.String, java.lang.String);
+    ctor public SQLWarning(java.lang.String, java.lang.String, int);
+    ctor public SQLWarning(java.lang.Throwable);
+    ctor public SQLWarning(java.lang.String, java.lang.Throwable);
+    ctor public SQLWarning(java.lang.String, java.lang.String, java.lang.Throwable);
+    ctor public SQLWarning(java.lang.String, java.lang.String, int, java.lang.Throwable);
+    method public java.sql.SQLWarning getNextWarning();
+    method public void setNextWarning(java.sql.SQLWarning);
+  }
+
+  public abstract interface SQLXML {
+    method public abstract void free() throws java.sql.SQLException;
+    method public abstract java.io.InputStream getBinaryStream() throws java.sql.SQLException;
+    method public abstract java.io.Reader getCharacterStream() throws java.sql.SQLException;
+    method public abstract T getSource(java.lang.Class<T>) throws java.sql.SQLException;
+    method public abstract java.lang.String getString() throws java.sql.SQLException;
+    method public abstract java.io.OutputStream setBinaryStream() throws java.sql.SQLException;
+    method public abstract java.io.Writer setCharacterStream() throws java.sql.SQLException;
+    method public abstract T setResult(java.lang.Class<T>) throws java.sql.SQLException;
+    method public abstract void setString(java.lang.String) throws java.sql.SQLException;
+  }
+
+  public abstract interface Savepoint {
+    method public abstract int getSavepointId() throws java.sql.SQLException;
+    method public abstract java.lang.String getSavepointName() throws java.sql.SQLException;
+  }
+
+  public abstract interface Statement implements java.sql.Wrapper {
+    method public abstract void addBatch(java.lang.String) throws java.sql.SQLException;
+    method public abstract void cancel() throws java.sql.SQLException;
+    method public abstract void clearBatch() throws java.sql.SQLException;
+    method public abstract void clearWarnings() throws java.sql.SQLException;
+    method public abstract void close() throws java.sql.SQLException;
+    method public abstract boolean execute(java.lang.String) throws java.sql.SQLException;
+    method public abstract boolean execute(java.lang.String, int) throws java.sql.SQLException;
+    method public abstract boolean execute(java.lang.String, int[]) throws java.sql.SQLException;
+    method public abstract boolean execute(java.lang.String, java.lang.String[]) throws java.sql.SQLException;
+    method public abstract int[] executeBatch() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet executeQuery(java.lang.String) throws java.sql.SQLException;
+    method public abstract int executeUpdate(java.lang.String) throws java.sql.SQLException;
+    method public abstract int executeUpdate(java.lang.String, int) throws java.sql.SQLException;
+    method public abstract int executeUpdate(java.lang.String, int[]) throws java.sql.SQLException;
+    method public abstract int executeUpdate(java.lang.String, java.lang.String[]) throws java.sql.SQLException;
+    method public abstract java.sql.Connection getConnection() throws java.sql.SQLException;
+    method public abstract int getFetchDirection() throws java.sql.SQLException;
+    method public abstract int getFetchSize() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getGeneratedKeys() throws java.sql.SQLException;
+    method public abstract int getMaxFieldSize() throws java.sql.SQLException;
+    method public abstract int getMaxRows() throws java.sql.SQLException;
+    method public abstract boolean getMoreResults() throws java.sql.SQLException;
+    method public abstract boolean getMoreResults(int) throws java.sql.SQLException;
+    method public abstract int getQueryTimeout() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getResultSet() throws java.sql.SQLException;
+    method public abstract int getResultSetConcurrency() throws java.sql.SQLException;
+    method public abstract int getResultSetHoldability() throws java.sql.SQLException;
+    method public abstract int getResultSetType() throws java.sql.SQLException;
+    method public abstract int getUpdateCount() throws java.sql.SQLException;
+    method public abstract java.sql.SQLWarning getWarnings() throws java.sql.SQLException;
+    method public abstract boolean isClosed() throws java.sql.SQLException;
+    method public abstract boolean isPoolable() throws java.sql.SQLException;
+    method public abstract void setCursorName(java.lang.String) throws java.sql.SQLException;
+    method public abstract void setEscapeProcessing(boolean) throws java.sql.SQLException;
+    method public abstract void setFetchDirection(int) throws java.sql.SQLException;
+    method public abstract void setFetchSize(int) throws java.sql.SQLException;
+    method public abstract void setMaxFieldSize(int) throws java.sql.SQLException;
+    method public abstract void setMaxRows(int) throws java.sql.SQLException;
+    method public abstract void setPoolable(boolean) throws java.sql.SQLException;
+    method public abstract void setQueryTimeout(int) throws java.sql.SQLException;
+    field public static final int CLOSE_ALL_RESULTS = 3; // 0x3
+    field public static final int CLOSE_CURRENT_RESULT = 1; // 0x1
+    field public static final int EXECUTE_FAILED = -3; // 0xfffffffd
+    field public static final int KEEP_CURRENT_RESULT = 2; // 0x2
+    field public static final int NO_GENERATED_KEYS = 2; // 0x2
+    field public static final int RETURN_GENERATED_KEYS = 1; // 0x1
+    field public static final int SUCCESS_NO_INFO = -2; // 0xfffffffe
+  }
+
+  public abstract interface Struct {
+    method public abstract java.lang.Object[] getAttributes() throws java.sql.SQLException;
+    method public abstract java.lang.Object[] getAttributes(java.util.Map<java.lang.String, java.lang.Class<?>>) throws java.sql.SQLException;
+    method public abstract java.lang.String getSQLTypeName() throws java.sql.SQLException;
+  }
+
+  public class Time extends java.util.Date {
+    ctor public deprecated Time(int, int, int);
+    ctor public Time(long);
+    method public static java.sql.Time valueOf(java.lang.String);
+  }
+
+  public class Timestamp extends java.util.Date {
+    ctor public deprecated Timestamp(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+    ctor public Timestamp(long);
+    method public boolean after(java.sql.Timestamp);
+    method public boolean before(java.sql.Timestamp);
+    method public int compareTo(java.sql.Timestamp);
+    method public boolean equals(java.sql.Timestamp);
+    method public int getNanos();
+    method public void setNanos(int) throws java.lang.IllegalArgumentException;
+    method public static java.sql.Timestamp valueOf(java.lang.String) throws java.lang.IllegalArgumentException;
+  }
+
+  public class Types {
+    field public static final int ARRAY = 2003; // 0x7d3
+    field public static final int BIGINT = -5; // 0xfffffffb
+    field public static final int BINARY = -2; // 0xfffffffe
+    field public static final int BIT = -7; // 0xfffffff9
+    field public static final int BLOB = 2004; // 0x7d4
+    field public static final int BOOLEAN = 16; // 0x10
+    field public static final int CHAR = 1; // 0x1
+    field public static final int CLOB = 2005; // 0x7d5
+    field public static final int DATALINK = 70; // 0x46
+    field public static final int DATE = 91; // 0x5b
+    field public static final int DECIMAL = 3; // 0x3
+    field public static final int DISTINCT = 2001; // 0x7d1
+    field public static final int DOUBLE = 8; // 0x8
+    field public static final int FLOAT = 6; // 0x6
+    field public static final int INTEGER = 4; // 0x4
+    field public static final int JAVA_OBJECT = 2000; // 0x7d0
+    field public static final int LONGNVARCHAR = -16; // 0xfffffff0
+    field public static final int LONGVARBINARY = -4; // 0xfffffffc
+    field public static final int LONGVARCHAR = -1; // 0xffffffff
+    field public static final int NCHAR = -15; // 0xfffffff1
+    field public static final int NCLOB = 2011; // 0x7db
+    field public static final int NULL = 0; // 0x0
+    field public static final int NUMERIC = 2; // 0x2
+    field public static final int NVARCHAR = -9; // 0xfffffff7
+    field public static final int OTHER = 1111; // 0x457
+    field public static final int REAL = 7; // 0x7
+    field public static final int REF = 2006; // 0x7d6
+    field public static final int ROWID = -8; // 0xfffffff8
+    field public static final int SMALLINT = 5; // 0x5
+    field public static final int SQLXML = 2009; // 0x7d9
+    field public static final int STRUCT = 2002; // 0x7d2
+    field public static final int TIME = 92; // 0x5c
+    field public static final int TIMESTAMP = 93; // 0x5d
+    field public static final int TINYINT = -6; // 0xfffffffa
+    field public static final int VARBINARY = -3; // 0xfffffffd
+    field public static final int VARCHAR = 12; // 0xc
+  }
+
+  public abstract interface Wrapper {
+    method public abstract boolean isWrapperFor(java.lang.Class<?>) throws java.sql.SQLException;
+    method public abstract T unwrap(java.lang.Class<T>) throws java.sql.SQLException;
+  }
+
+}
+
+package java.text {
+
+  public class Annotation {
+    ctor public Annotation(java.lang.Object);
+    method public java.lang.Object getValue();
+  }
+
+  public abstract interface AttributedCharacterIterator implements java.text.CharacterIterator {
+    method public abstract java.util.Set<java.text.AttributedCharacterIterator.Attribute> getAllAttributeKeys();
+    method public abstract java.lang.Object getAttribute(java.text.AttributedCharacterIterator.Attribute);
+    method public abstract java.util.Map<java.text.AttributedCharacterIterator.Attribute, java.lang.Object> getAttributes();
+    method public abstract int getRunLimit();
+    method public abstract int getRunLimit(java.text.AttributedCharacterIterator.Attribute);
+    method public abstract int getRunLimit(java.util.Set<? extends java.text.AttributedCharacterIterator.Attribute>);
+    method public abstract int getRunStart();
+    method public abstract int getRunStart(java.text.AttributedCharacterIterator.Attribute);
+    method public abstract int getRunStart(java.util.Set<? extends java.text.AttributedCharacterIterator.Attribute>);
+  }
+
+  public static class AttributedCharacterIterator.Attribute implements java.io.Serializable {
+    ctor protected AttributedCharacterIterator.Attribute(java.lang.String);
+    method public final boolean equals(java.lang.Object);
+    method protected java.lang.String getName();
+    method public final int hashCode();
+    method protected java.lang.Object readResolve() throws java.io.InvalidObjectException;
+    field public static final java.text.AttributedCharacterIterator.Attribute INPUT_METHOD_SEGMENT;
+    field public static final java.text.AttributedCharacterIterator.Attribute LANGUAGE;
+    field public static final java.text.AttributedCharacterIterator.Attribute READING;
+  }
+
+  public class AttributedString {
+    ctor public AttributedString(java.text.AttributedCharacterIterator);
+    ctor public AttributedString(java.text.AttributedCharacterIterator, int, int);
+    ctor public AttributedString(java.text.AttributedCharacterIterator, int, int, java.text.AttributedCharacterIterator.Attribute[]);
+    ctor public AttributedString(java.lang.String);
+    ctor public AttributedString(java.lang.String, java.util.Map<? extends java.text.AttributedCharacterIterator.Attribute, ?>);
+    method public void addAttribute(java.text.AttributedCharacterIterator.Attribute, java.lang.Object);
+    method public void addAttribute(java.text.AttributedCharacterIterator.Attribute, java.lang.Object, int, int);
+    method public void addAttributes(java.util.Map<? extends java.text.AttributedCharacterIterator.Attribute, ?>, int, int);
+    method public java.text.AttributedCharacterIterator getIterator();
+    method public java.text.AttributedCharacterIterator getIterator(java.text.AttributedCharacterIterator.Attribute[]);
+    method public java.text.AttributedCharacterIterator getIterator(java.text.AttributedCharacterIterator.Attribute[], int, int);
+  }
+
+  public final class Bidi {
+    ctor public Bidi(java.text.AttributedCharacterIterator);
+    ctor public Bidi(char[], int, byte[], int, int, int);
+    ctor public Bidi(java.lang.String, int);
+    method public boolean baseIsLeftToRight();
+    method public java.text.Bidi createLineBidi(int, int);
+    method public int getBaseLevel();
+    method public int getLength();
+    method public int getLevelAt(int);
+    method public int getRunCount();
+    method public int getRunLevel(int);
+    method public int getRunLimit(int);
+    method public int getRunStart(int);
+    method public boolean isLeftToRight();
+    method public boolean isMixed();
+    method public boolean isRightToLeft();
+    method public static void reorderVisually(byte[], int, java.lang.Object[], int, int);
+    method public static boolean requiresBidi(char[], int, int);
+    field public static final int DIRECTION_DEFAULT_LEFT_TO_RIGHT = -2; // 0xfffffffe
+    field public static final int DIRECTION_DEFAULT_RIGHT_TO_LEFT = -1; // 0xffffffff
+    field public static final int DIRECTION_LEFT_TO_RIGHT = 0; // 0x0
+    field public static final int DIRECTION_RIGHT_TO_LEFT = 1; // 0x1
+  }
+
+  public abstract class BreakIterator implements java.lang.Cloneable {
+    ctor protected BreakIterator();
+    method public java.lang.Object clone();
+    method public abstract int current();
+    method public abstract int first();
+    method public abstract int following(int);
+    method public static java.util.Locale[] getAvailableLocales();
+    method public static java.text.BreakIterator getCharacterInstance();
+    method public static java.text.BreakIterator getCharacterInstance(java.util.Locale);
+    method public static java.text.BreakIterator getLineInstance();
+    method public static java.text.BreakIterator getLineInstance(java.util.Locale);
+    method public static java.text.BreakIterator getSentenceInstance();
+    method public static java.text.BreakIterator getSentenceInstance(java.util.Locale);
+    method public abstract java.text.CharacterIterator getText();
+    method public static java.text.BreakIterator getWordInstance();
+    method public static java.text.BreakIterator getWordInstance(java.util.Locale);
+    method public boolean isBoundary(int);
+    method public abstract int last();
+    method public abstract int next();
+    method public abstract int next(int);
+    method public int preceding(int);
+    method public abstract int previous();
+    method public void setText(java.lang.String);
+    method public abstract void setText(java.text.CharacterIterator);
+    field public static final int DONE = -1; // 0xffffffff
+  }
+
+  public abstract interface CharacterIterator implements java.lang.Cloneable {
+    method public abstract java.lang.Object clone();
+    method public abstract char current();
+    method public abstract char first();
+    method public abstract int getBeginIndex();
+    method public abstract int getEndIndex();
+    method public abstract int getIndex();
+    method public abstract char last();
+    method public abstract char next();
+    method public abstract char previous();
+    method public abstract char setIndex(int);
+    field public static final char DONE = 65535; // 0xffff '\uffff'
+  }
+
+  public class ChoiceFormat extends java.text.NumberFormat {
+    ctor public ChoiceFormat(double[], java.lang.String[]);
+    ctor public ChoiceFormat(java.lang.String);
+    method public void applyPattern(java.lang.String);
+    method public java.lang.StringBuffer format(double, java.lang.StringBuffer, java.text.FieldPosition);
+    method public java.lang.StringBuffer format(long, java.lang.StringBuffer, java.text.FieldPosition);
+    method public java.lang.Object[] getFormats();
+    method public double[] getLimits();
+    method public static final double nextDouble(double);
+    method public static double nextDouble(double, boolean);
+    method public java.lang.Number parse(java.lang.String, java.text.ParsePosition);
+    method public static final double previousDouble(double);
+    method public void setChoices(double[], java.lang.String[]);
+    method public java.lang.String toPattern();
+  }
+
+  public final class CollationElementIterator {
+    method public int getMaxExpansion(int);
+    method public int getOffset();
+    method public int next();
+    method public int previous();
+    method public static final int primaryOrder(int);
+    method public void reset();
+    method public static final short secondaryOrder(int);
+    method public void setOffset(int);
+    method public void setText(java.text.CharacterIterator);
+    method public void setText(java.lang.String);
+    method public static final short tertiaryOrder(int);
+    field public static final int NULLORDER = -1; // 0xffffffff
+  }
+
+  public abstract class CollationKey implements java.lang.Comparable {
+    ctor protected CollationKey(java.lang.String);
+    method public abstract int compareTo(java.text.CollationKey);
+    method public java.lang.String getSourceString();
+    method public abstract byte[] toByteArray();
+  }
+
+  public abstract class Collator implements java.lang.Cloneable java.util.Comparator {
+    ctor protected Collator();
+    method public java.lang.Object clone();
+    method public int compare(java.lang.Object, java.lang.Object);
+    method public abstract int compare(java.lang.String, java.lang.String);
+    method public boolean equals(java.lang.String, java.lang.String);
+    method public static java.util.Locale[] getAvailableLocales();
+    method public abstract java.text.CollationKey getCollationKey(java.lang.String);
+    method public int getDecomposition();
+    method public static java.text.Collator getInstance();
+    method public static java.text.Collator getInstance(java.util.Locale);
+    method public int getStrength();
+    method public abstract int hashCode();
+    method public void setDecomposition(int);
+    method public void setStrength(int);
+    field public static final int CANONICAL_DECOMPOSITION = 1; // 0x1
+    field public static final int FULL_DECOMPOSITION = 2; // 0x2
+    field public static final int IDENTICAL = 3; // 0x3
+    field public static final int NO_DECOMPOSITION = 0; // 0x0
+    field public static final int PRIMARY = 0; // 0x0
+    field public static final int SECONDARY = 1; // 0x1
+    field public static final int TERTIARY = 2; // 0x2
+  }
+
+  public abstract class DateFormat extends java.text.Format {
+    ctor protected DateFormat();
+    method public final java.lang.StringBuffer format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition);
+    method public final java.lang.String format(java.util.Date);
+    method public abstract java.lang.StringBuffer format(java.util.Date, java.lang.StringBuffer, java.text.FieldPosition);
+    method public static java.util.Locale[] getAvailableLocales();
+    method public java.util.Calendar getCalendar();
+    method public static final java.text.DateFormat getDateInstance();
+    method public static final java.text.DateFormat getDateInstance(int);
+    method public static final java.text.DateFormat getDateInstance(int, java.util.Locale);
+    method public static final java.text.DateFormat getDateTimeInstance();
+    method public static final java.text.DateFormat getDateTimeInstance(int, int);
+    method public static final java.text.DateFormat getDateTimeInstance(int, int, java.util.Locale);
+    method public static final java.text.DateFormat getInstance();
+    method public java.text.NumberFormat getNumberFormat();
+    method public static final java.text.DateFormat getTimeInstance();
+    method public static final java.text.DateFormat getTimeInstance(int);
+    method public static final java.text.DateFormat getTimeInstance(int, java.util.Locale);
+    method public java.util.TimeZone getTimeZone();
+    method public boolean isLenient();
+    method public java.util.Date parse(java.lang.String) throws java.text.ParseException;
+    method public abstract java.util.Date parse(java.lang.String, java.text.ParsePosition);
+    method public java.lang.Object parseObject(java.lang.String, java.text.ParsePosition);
+    method public void setCalendar(java.util.Calendar);
+    method public void setLenient(boolean);
+    method public void setNumberFormat(java.text.NumberFormat);
+    method public void setTimeZone(java.util.TimeZone);
+    field public static final int AM_PM_FIELD = 14; // 0xe
+    field public static final int DATE_FIELD = 3; // 0x3
+    field public static final int DAY_OF_WEEK_FIELD = 9; // 0x9
+    field public static final int DAY_OF_WEEK_IN_MONTH_FIELD = 11; // 0xb
+    field public static final int DAY_OF_YEAR_FIELD = 10; // 0xa
+    field public static final int DEFAULT = 2; // 0x2
+    field public static final int ERA_FIELD = 0; // 0x0
+    field public static final int FULL = 0; // 0x0
+    field public static final int HOUR0_FIELD = 16; // 0x10
+    field public static final int HOUR1_FIELD = 15; // 0xf
+    field public static final int HOUR_OF_DAY0_FIELD = 5; // 0x5
+    field public static final int HOUR_OF_DAY1_FIELD = 4; // 0x4
+    field public static final int LONG = 1; // 0x1
+    field public static final int MEDIUM = 2; // 0x2
+    field public static final int MILLISECOND_FIELD = 8; // 0x8
+    field public static final int MINUTE_FIELD = 6; // 0x6
+    field public static final int MONTH_FIELD = 2; // 0x2
+    field public static final int SECOND_FIELD = 7; // 0x7
+    field public static final int SHORT = 3; // 0x3
+    field public static final int TIMEZONE_FIELD = 17; // 0x11
+    field public static final int WEEK_OF_MONTH_FIELD = 13; // 0xd
+    field public static final int WEEK_OF_YEAR_FIELD = 12; // 0xc
+    field public static final int YEAR_FIELD = 1; // 0x1
+    field protected java.util.Calendar calendar;
+    field protected java.text.NumberFormat numberFormat;
+  }
+
+  public static class DateFormat.Field extends java.text.Format.Field {
+    ctor protected DateFormat.Field(java.lang.String, int);
+    method public int getCalendarField();
+    method public static java.text.DateFormat.Field ofCalendarField(int);
+    field public static final java.text.DateFormat.Field AM_PM;
+    field public static final java.text.DateFormat.Field DAY_OF_MONTH;
+    field public static final java.text.DateFormat.Field DAY_OF_WEEK;
+    field public static final java.text.DateFormat.Field DAY_OF_WEEK_IN_MONTH;
+    field public static final java.text.DateFormat.Field DAY_OF_YEAR;
+    field public static final java.text.DateFormat.Field ERA;
+    field public static final java.text.DateFormat.Field HOUR0;
+    field public static final java.text.DateFormat.Field HOUR1;
+    field public static final java.text.DateFormat.Field HOUR_OF_DAY0;
+    field public static final java.text.DateFormat.Field HOUR_OF_DAY1;
+    field public static final java.text.DateFormat.Field MILLISECOND;
+    field public static final java.text.DateFormat.Field MINUTE;
+    field public static final java.text.DateFormat.Field MONTH;
+    field public static final java.text.DateFormat.Field SECOND;
+    field public static final java.text.DateFormat.Field TIME_ZONE;
+    field public static final java.text.DateFormat.Field WEEK_OF_MONTH;
+    field public static final java.text.DateFormat.Field WEEK_OF_YEAR;
+    field public static final java.text.DateFormat.Field YEAR;
+  }
+
+  public class DateFormatSymbols implements java.lang.Cloneable java.io.Serializable {
+    ctor public DateFormatSymbols();
+    ctor public DateFormatSymbols(java.util.Locale);
+    method public java.lang.Object clone();
+    method public java.lang.String[] getAmPmStrings();
+    method public static java.util.Locale[] getAvailableLocales();
+    method public java.lang.String[] getEras();
+    method public static final java.text.DateFormatSymbols getInstance();
+    method public static final java.text.DateFormatSymbols getInstance(java.util.Locale);
+    method public java.lang.String getLocalPatternChars();
+    method public java.lang.String[] getMonths();
+    method public java.lang.String[] getShortMonths();
+    method public java.lang.String[] getShortWeekdays();
+    method public java.lang.String[] getWeekdays();
+    method public java.lang.String[][] getZoneStrings();
+    method public void setAmPmStrings(java.lang.String[]);
+    method public void setEras(java.lang.String[]);
+    method public void setLocalPatternChars(java.lang.String);
+    method public void setMonths(java.lang.String[]);
+    method public void setShortMonths(java.lang.String[]);
+    method public void setShortWeekdays(java.lang.String[]);
+    method public void setWeekdays(java.lang.String[]);
+    method public void setZoneStrings(java.lang.String[][]);
+  }
+
+  public class DecimalFormat extends java.text.NumberFormat {
+    ctor public DecimalFormat();
+    ctor public DecimalFormat(java.lang.String);
+    ctor public DecimalFormat(java.lang.String, java.text.DecimalFormatSymbols);
+    method public void applyLocalizedPattern(java.lang.String);
+    method public void applyPattern(java.lang.String);
+    method public java.lang.StringBuffer format(double, java.lang.StringBuffer, java.text.FieldPosition);
+    method public java.lang.StringBuffer format(long, java.lang.StringBuffer, java.text.FieldPosition);
+    method public final java.lang.StringBuffer format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition);
+    method public java.text.DecimalFormatSymbols getDecimalFormatSymbols();
+    method public int getGroupingSize();
+    method public int getMultiplier();
+    method public java.lang.String getNegativePrefix();
+    method public java.lang.String getNegativeSuffix();
+    method public java.lang.String getPositivePrefix();
+    method public java.lang.String getPositiveSuffix();
+    method public boolean isDecimalSeparatorAlwaysShown();
+    method public boolean isParseBigDecimal();
+    method public java.lang.Number parse(java.lang.String, java.text.ParsePosition);
+    method public void setDecimalFormatSymbols(java.text.DecimalFormatSymbols);
+    method public void setDecimalSeparatorAlwaysShown(boolean);
+    method public void setGroupingSize(int);
+    method public void setMultiplier(int);
+    method public void setNegativePrefix(java.lang.String);
+    method public void setNegativeSuffix(java.lang.String);
+    method public void setParseBigDecimal(boolean);
+    method public void setPositivePrefix(java.lang.String);
+    method public void setPositiveSuffix(java.lang.String);
+    method public java.lang.String toLocalizedPattern();
+    method public java.lang.String toPattern();
+  }
+
+  public class DecimalFormatSymbols implements java.lang.Cloneable java.io.Serializable {
+    ctor public DecimalFormatSymbols();
+    ctor public DecimalFormatSymbols(java.util.Locale);
+    method public java.lang.Object clone();
+    method public static java.util.Locale[] getAvailableLocales();
+    method public java.util.Currency getCurrency();
+    method public java.lang.String getCurrencySymbol();
+    method public char getDecimalSeparator();
+    method public char getDigit();
+    method public java.lang.String getExponentSeparator();
+    method public char getGroupingSeparator();
+    method public java.lang.String getInfinity();
+    method public static java.text.DecimalFormatSymbols getInstance();
+    method public static java.text.DecimalFormatSymbols getInstance(java.util.Locale);
+    method public java.lang.String getInternationalCurrencySymbol();
+    method public char getMinusSign();
+    method public char getMonetaryDecimalSeparator();
+    method public java.lang.String getNaN();
+    method public char getPatternSeparator();
+    method public char getPerMill();
+    method public char getPercent();
+    method public char getZeroDigit();
+    method public void setCurrency(java.util.Currency);
+    method public void setCurrencySymbol(java.lang.String);
+    method public void setDecimalSeparator(char);
+    method public void setDigit(char);
+    method public void setExponentSeparator(java.lang.String);
+    method public void setGroupingSeparator(char);
+    method public void setInfinity(java.lang.String);
+    method public void setInternationalCurrencySymbol(java.lang.String);
+    method public void setMinusSign(char);
+    method public void setMonetaryDecimalSeparator(char);
+    method public void setNaN(java.lang.String);
+    method public void setPatternSeparator(char);
+    method public void setPerMill(char);
+    method public void setPercent(char);
+    method public void setZeroDigit(char);
+  }
+
+  public class FieldPosition {
+    ctor public FieldPosition(int);
+    ctor public FieldPosition(java.text.Format.Field);
+    ctor public FieldPosition(java.text.Format.Field, int);
+    method public int getBeginIndex();
+    method public int getEndIndex();
+    method public int getField();
+    method public java.text.Format.Field getFieldAttribute();
+    method public void setBeginIndex(int);
+    method public void setEndIndex(int);
+  }
+
+  public abstract class Format implements java.lang.Cloneable java.io.Serializable {
+    ctor protected Format();
+    method public java.lang.Object clone();
+    method public final java.lang.String format(java.lang.Object);
+    method public abstract java.lang.StringBuffer format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition);
+    method public java.text.AttributedCharacterIterator formatToCharacterIterator(java.lang.Object);
+    method public java.lang.Object parseObject(java.lang.String) throws java.text.ParseException;
+    method public abstract java.lang.Object parseObject(java.lang.String, java.text.ParsePosition);
+  }
+
+  public static class Format.Field extends java.text.AttributedCharacterIterator.Attribute {
+    ctor protected Format.Field(java.lang.String);
+  }
+
+  public class MessageFormat extends java.text.Format {
+    ctor public MessageFormat(java.lang.String, java.util.Locale);
+    ctor public MessageFormat(java.lang.String);
+    method public void applyPattern(java.lang.String);
+    method public final java.lang.StringBuffer format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition);
+    method public final java.lang.StringBuffer format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition);
+    method public static java.lang.String format(java.lang.String, java.lang.Object...);
+    method public java.text.Format[] getFormats();
+    method public java.text.Format[] getFormatsByArgumentIndex();
+    method public java.util.Locale getLocale();
+    method public java.lang.Object[] parse(java.lang.String) throws java.text.ParseException;
+    method public java.lang.Object[] parse(java.lang.String, java.text.ParsePosition);
+    method public java.lang.Object parseObject(java.lang.String, java.text.ParsePosition);
+    method public void setFormat(int, java.text.Format);
+    method public void setFormatByArgumentIndex(int, java.text.Format);
+    method public void setFormats(java.text.Format[]);
+    method public void setFormatsByArgumentIndex(java.text.Format[]);
+    method public void setLocale(java.util.Locale);
+    method public java.lang.String toPattern();
+  }
+
+  public static class MessageFormat.Field extends java.text.Format.Field {
+    ctor protected MessageFormat.Field(java.lang.String);
+    field public static final java.text.MessageFormat.Field ARGUMENT;
+  }
+
+  public final class Normalizer {
+    method public static boolean isNormalized(java.lang.CharSequence, java.text.Normalizer.Form);
+    method public static java.lang.String normalize(java.lang.CharSequence, java.text.Normalizer.Form);
+  }
+
+  public static final class Normalizer.Form extends java.lang.Enum {
+    method public static java.text.Normalizer.Form valueOf(java.lang.String);
+    method public static final java.text.Normalizer.Form[] values();
+    enum_constant public static final java.text.Normalizer.Form NFC;
+    enum_constant public static final java.text.Normalizer.Form NFD;
+    enum_constant public static final java.text.Normalizer.Form NFKC;
+    enum_constant public static final java.text.Normalizer.Form NFKD;
+  }
+
+  public abstract class NumberFormat extends java.text.Format {
+    ctor protected NumberFormat();
+    method public final java.lang.String format(double);
+    method public abstract java.lang.StringBuffer format(double, java.lang.StringBuffer, java.text.FieldPosition);
+    method public final java.lang.String format(long);
+    method public abstract java.lang.StringBuffer format(long, java.lang.StringBuffer, java.text.FieldPosition);
+    method public java.lang.StringBuffer format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition);
+    method public static java.util.Locale[] getAvailableLocales();
+    method public java.util.Currency getCurrency();
+    method public static final java.text.NumberFormat getCurrencyInstance();
+    method public static java.text.NumberFormat getCurrencyInstance(java.util.Locale);
+    method public static final java.text.NumberFormat getInstance();
+    method public static java.text.NumberFormat getInstance(java.util.Locale);
+    method public static final java.text.NumberFormat getIntegerInstance();
+    method public static java.text.NumberFormat getIntegerInstance(java.util.Locale);
+    method public int getMaximumFractionDigits();
+    method public int getMaximumIntegerDigits();
+    method public int getMinimumFractionDigits();
+    method public int getMinimumIntegerDigits();
+    method public static final java.text.NumberFormat getNumberInstance();
+    method public static java.text.NumberFormat getNumberInstance(java.util.Locale);
+    method public static final java.text.NumberFormat getPercentInstance();
+    method public static java.text.NumberFormat getPercentInstance(java.util.Locale);
+    method public java.math.RoundingMode getRoundingMode();
+    method public boolean isGroupingUsed();
+    method public boolean isParseIntegerOnly();
+    method public java.lang.Number parse(java.lang.String) throws java.text.ParseException;
+    method public abstract java.lang.Number parse(java.lang.String, java.text.ParsePosition);
+    method public final java.lang.Object parseObject(java.lang.String, java.text.ParsePosition);
+    method public void setCurrency(java.util.Currency);
+    method public void setGroupingUsed(boolean);
+    method public void setMaximumFractionDigits(int);
+    method public void setMaximumIntegerDigits(int);
+    method public void setMinimumFractionDigits(int);
+    method public void setMinimumIntegerDigits(int);
+    method public void setParseIntegerOnly(boolean);
+    method public void setRoundingMode(java.math.RoundingMode);
+    field public static final int FRACTION_FIELD = 1; // 0x1
+    field public static final int INTEGER_FIELD = 0; // 0x0
+  }
+
+  public static class NumberFormat.Field extends java.text.Format.Field {
+    ctor protected NumberFormat.Field(java.lang.String);
+    field public static final java.text.NumberFormat.Field CURRENCY;
+    field public static final java.text.NumberFormat.Field DECIMAL_SEPARATOR;
+    field public static final java.text.NumberFormat.Field EXPONENT;
+    field public static final java.text.NumberFormat.Field EXPONENT_SIGN;
+    field public static final java.text.NumberFormat.Field EXPONENT_SYMBOL;
+    field public static final java.text.NumberFormat.Field FRACTION;
+    field public static final java.text.NumberFormat.Field GROUPING_SEPARATOR;
+    field public static final java.text.NumberFormat.Field INTEGER;
+    field public static final java.text.NumberFormat.Field PERCENT;
+    field public static final java.text.NumberFormat.Field PERMILLE;
+    field public static final java.text.NumberFormat.Field SIGN;
+  }
+
+  public class ParseException extends java.lang.Exception {
+    ctor public ParseException(java.lang.String, int);
+    method public int getErrorOffset();
+  }
+
+  public class ParsePosition {
+    ctor public ParsePosition(int);
+    method public int getErrorIndex();
+    method public int getIndex();
+    method public void setErrorIndex(int);
+    method public void setIndex(int);
+  }
+
+  public class RuleBasedCollator extends java.text.Collator {
+    ctor public RuleBasedCollator(java.lang.String) throws java.text.ParseException;
+    method public int compare(java.lang.String, java.lang.String);
+    method public java.text.CollationElementIterator getCollationElementIterator(java.text.CharacterIterator);
+    method public java.text.CollationElementIterator getCollationElementIterator(java.lang.String);
+    method public java.text.CollationKey getCollationKey(java.lang.String);
+    method public java.lang.String getRules();
+    method public int hashCode();
+  }
+
+  public class SimpleDateFormat extends java.text.DateFormat {
+    ctor public SimpleDateFormat();
+    ctor public SimpleDateFormat(java.lang.String);
+    ctor public SimpleDateFormat(java.lang.String, java.text.DateFormatSymbols);
+    ctor public SimpleDateFormat(java.lang.String, java.util.Locale);
+    method public void applyLocalizedPattern(java.lang.String);
+    method public void applyPattern(java.lang.String);
+    method public java.lang.StringBuffer format(java.util.Date, java.lang.StringBuffer, java.text.FieldPosition);
+    method public java.util.Date get2DigitYearStart();
+    method public java.text.DateFormatSymbols getDateFormatSymbols();
+    method public java.util.Date parse(java.lang.String, java.text.ParsePosition);
+    method public void set2DigitYearStart(java.util.Date);
+    method public void setDateFormatSymbols(java.text.DateFormatSymbols);
+    method public java.lang.String toLocalizedPattern();
+    method public java.lang.String toPattern();
+  }
+
+  public final class StringCharacterIterator implements java.text.CharacterIterator {
+    ctor public StringCharacterIterator(java.lang.String);
+    ctor public StringCharacterIterator(java.lang.String, int);
+    ctor public StringCharacterIterator(java.lang.String, int, int, int);
+    method public java.lang.Object clone();
+    method public char current();
+    method public char first();
+    method public int getBeginIndex();
+    method public int getEndIndex();
+    method public int getIndex();
+    method public char last();
+    method public char next();
+    method public char previous();
+    method public char setIndex(int);
+    method public void setText(java.lang.String);
+  }
+
+}
+
+package java.util {
+
+  public abstract class AbstractCollection implements java.util.Collection {
+    ctor protected AbstractCollection();
+    method public boolean add(E);
+    method public boolean addAll(java.util.Collection<? extends E>);
+    method public void clear();
+    method public boolean contains(java.lang.Object);
+    method public boolean containsAll(java.util.Collection<?>);
+    method public boolean isEmpty();
+    method public abstract java.util.Iterator<E> iterator();
+    method public boolean remove(java.lang.Object);
+    method public boolean removeAll(java.util.Collection<?>);
+    method public boolean retainAll(java.util.Collection<?>);
+    method public abstract int size();
+    method public java.lang.Object[] toArray();
+    method public T[] toArray(T[]);
+  }
+
+  public abstract class AbstractList extends java.util.AbstractCollection implements java.util.List {
+    ctor protected AbstractList();
+    method public void add(int, E);
+    method public boolean addAll(int, java.util.Collection<? extends E>);
+    method public abstract E get(int);
+    method public int indexOf(java.lang.Object);
+    method public java.util.Iterator<E> iterator();
+    method public int lastIndexOf(java.lang.Object);
+    method public java.util.ListIterator<E> listIterator();
+    method public java.util.ListIterator<E> listIterator(int);
+    method public E remove(int);
+    method protected void removeRange(int, int);
+    method public E set(int, E);
+    method public java.util.List<E> subList(int, int);
+    field protected transient int modCount;
+  }
+
+  public abstract class AbstractMap implements java.util.Map {
+    ctor protected AbstractMap();
+    method public void clear();
+    method public boolean containsKey(java.lang.Object);
+    method public boolean containsValue(java.lang.Object);
+    method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public V get(java.lang.Object);
+    method public boolean isEmpty();
+    method public java.util.Set<K> keySet();
+    method public V put(K, V);
+    method public void putAll(java.util.Map<? extends K, ? extends V>);
+    method public V remove(java.lang.Object);
+    method public int size();
+    method public java.util.Collection<V> values();
+  }
+
+  public static class AbstractMap.SimpleEntry implements java.util.Map.Entry java.io.Serializable {
+    ctor public AbstractMap.SimpleEntry(K, V);
+    ctor public AbstractMap.SimpleEntry(java.util.Map.Entry<? extends K, ? extends V>);
+    method public K getKey();
+    method public V getValue();
+    method public V setValue(V);
+  }
+
+  public static class AbstractMap.SimpleImmutableEntry implements java.util.Map.Entry java.io.Serializable {
+    ctor public AbstractMap.SimpleImmutableEntry(K, V);
+    ctor public AbstractMap.SimpleImmutableEntry(java.util.Map.Entry<? extends K, ? extends V>);
+    method public K getKey();
+    method public V getValue();
+    method public V setValue(V);
+  }
+
+  public abstract class AbstractQueue extends java.util.AbstractCollection implements java.util.Queue {
+    ctor protected AbstractQueue();
+    method public E element();
+    method public E remove();
+  }
+
+  public abstract class AbstractSequentialList extends java.util.AbstractList {
+    ctor protected AbstractSequentialList();
+    method public E get(int);
+    method public abstract java.util.ListIterator<E> listIterator(int);
+  }
+
+  public abstract class AbstractSet extends java.util.AbstractCollection implements java.util.Set {
+    ctor protected AbstractSet();
+  }
+
+  public class ArrayDeque extends java.util.AbstractCollection implements java.lang.Cloneable java.util.Deque java.io.Serializable {
+    ctor public ArrayDeque();
+    ctor public ArrayDeque(int);
+    ctor public ArrayDeque(java.util.Collection<? extends E>);
+    method public void addFirst(E);
+    method public void addLast(E);
+    method public java.util.ArrayDeque<E> clone();
+    method public java.util.Iterator<E> descendingIterator();
+    method public E element();
+    method public E getFirst();
+    method public E getLast();
+    method public java.util.Iterator<E> iterator();
+    method public boolean offer(E);
+    method public boolean offerFirst(E);
+    method public boolean offerLast(E);
+    method public E peek();
+    method public E peekFirst();
+    method public E peekLast();
+    method public E poll();
+    method public E pollFirst();
+    method public E pollLast();
+    method public E pop();
+    method public void push(E);
+    method public E remove();
+    method public E removeFirst();
+    method public boolean removeFirstOccurrence(java.lang.Object);
+    method public E removeLast();
+    method public boolean removeLastOccurrence(java.lang.Object);
+    method public int size();
+  }
+
+  public class ArrayList extends java.util.AbstractList implements java.lang.Cloneable java.util.RandomAccess java.io.Serializable {
+    ctor public ArrayList(int);
+    ctor public ArrayList();
+    ctor public ArrayList(java.util.Collection<? extends E>);
+    method public java.lang.Object clone();
+    method public void ensureCapacity(int);
+    method public E get(int);
+    method public int size();
+    method public void trimToSize();
+  }
+
+  public class Arrays {
+    method public static java.util.List<T> asList(T...);
+    method public static int binarySearch(byte[], byte);
+    method public static int binarySearch(byte[], int, int, byte);
+    method public static int binarySearch(char[], char);
+    method public static int binarySearch(char[], int, int, char);
+    method public static int binarySearch(double[], double);
+    method public static int binarySearch(double[], int, int, double);
+    method public static int binarySearch(float[], float);
+    method public static int binarySearch(float[], int, int, float);
+    method public static int binarySearch(int[], int);
+    method public static int binarySearch(int[], int, int, int);
+    method public static int binarySearch(long[], long);
+    method public static int binarySearch(long[], int, int, long);
+    method public static int binarySearch(java.lang.Object[], java.lang.Object);
+    method public static int binarySearch(java.lang.Object[], int, int, java.lang.Object);
+    method public static int binarySearch(T[], T, java.util.Comparator<? super T>);
+    method public static int binarySearch(T[], int, int, T, java.util.Comparator<? super T>);
+    method public static int binarySearch(short[], short);
+    method public static int binarySearch(short[], int, int, short);
+    method public static boolean[] copyOf(boolean[], int);
+    method public static byte[] copyOf(byte[], int);
+    method public static char[] copyOf(char[], int);
+    method public static double[] copyOf(double[], int);
+    method public static float[] copyOf(float[], int);
+    method public static int[] copyOf(int[], int);
+    method public static long[] copyOf(long[], int);
+    method public static short[] copyOf(short[], int);
+    method public static T[] copyOf(T[], int);
+    method public static T[] copyOf(U[], int, java.lang.Class<? extends T[]>);
+    method public static boolean[] copyOfRange(boolean[], int, int);
+    method public static byte[] copyOfRange(byte[], int, int);
+    method public static char[] copyOfRange(char[], int, int);
+    method public static double[] copyOfRange(double[], int, int);
+    method public static float[] copyOfRange(float[], int, int);
+    method public static int[] copyOfRange(int[], int, int);
+    method public static long[] copyOfRange(long[], int, int);
+    method public static short[] copyOfRange(short[], int, int);
+    method public static T[] copyOfRange(T[], int, int);
+    method public static T[] copyOfRange(U[], int, int, java.lang.Class<? extends T[]>);
+    method public static boolean deepEquals(java.lang.Object[], java.lang.Object[]);
+    method public static int deepHashCode(java.lang.Object[]);
+    method public static java.lang.String deepToString(java.lang.Object[]);
+    method public static boolean equals(byte[], byte[]);
+    method public static boolean equals(short[], short[]);
+    method public static boolean equals(char[], char[]);
+    method public static boolean equals(int[], int[]);
+    method public static boolean equals(long[], long[]);
+    method public static boolean equals(float[], float[]);
+    method public static boolean equals(double[], double[]);
+    method public static boolean equals(boolean[], boolean[]);
+    method public static boolean equals(java.lang.Object[], java.lang.Object[]);
+    method public static void fill(byte[], byte);
+    method public static void fill(byte[], int, int, byte);
+    method public static void fill(short[], short);
+    method public static void fill(short[], int, int, short);
+    method public static void fill(char[], char);
+    method public static void fill(char[], int, int, char);
+    method public static void fill(int[], int);
+    method public static void fill(int[], int, int, int);
+    method public static void fill(long[], long);
+    method public static void fill(long[], int, int, long);
+    method public static void fill(float[], float);
+    method public static void fill(float[], int, int, float);
+    method public static void fill(double[], double);
+    method public static void fill(double[], int, int, double);
+    method public static void fill(boolean[], boolean);
+    method public static void fill(boolean[], int, int, boolean);
+    method public static void fill(java.lang.Object[], java.lang.Object);
+    method public static void fill(java.lang.Object[], int, int, java.lang.Object);
+    method public static int hashCode(boolean[]);
+    method public static int hashCode(int[]);
+    method public static int hashCode(short[]);
+    method public static int hashCode(char[]);
+    method public static int hashCode(byte[]);
+    method public static int hashCode(long[]);
+    method public static int hashCode(float[]);
+    method public static int hashCode(double[]);
+    method public static int hashCode(java.lang.Object[]);
+    method public static void sort(byte[]);
+    method public static void sort(byte[], int, int);
+    method public static void sort(char[]);
+    method public static void sort(char[], int, int);
+    method public static void sort(double[]);
+    method public static void sort(double[], int, int);
+    method public static void sort(float[]);
+    method public static void sort(float[], int, int);
+    method public static void sort(int[]);
+    method public static void sort(int[], int, int);
+    method public static void sort(long[]);
+    method public static void sort(long[], int, int);
+    method public static void sort(short[]);
+    method public static void sort(short[], int, int);
+    method public static void sort(java.lang.Object[]);
+    method public static void sort(java.lang.Object[], int, int);
+    method public static void sort(T[], int, int, java.util.Comparator<? super T>);
+    method public static void sort(T[], java.util.Comparator<? super T>);
+    method public static java.lang.String toString(boolean[]);
+    method public static java.lang.String toString(byte[]);
+    method public static java.lang.String toString(char[]);
+    method public static java.lang.String toString(double[]);
+    method public static java.lang.String toString(float[]);
+    method public static java.lang.String toString(int[]);
+    method public static java.lang.String toString(long[]);
+    method public static java.lang.String toString(short[]);
+    method public static java.lang.String toString(java.lang.Object[]);
+  }
+
+  public class BitSet implements java.lang.Cloneable java.io.Serializable {
+    ctor public BitSet();
+    ctor public BitSet(int);
+    method public void and(java.util.BitSet);
+    method public void andNot(java.util.BitSet);
+    method public int cardinality();
+    method public void clear(int);
+    method public void clear();
+    method public void clear(int, int);
+    method public java.lang.Object clone();
+    method public void flip(int);
+    method public void flip(int, int);
+    method public boolean get(int);
+    method public java.util.BitSet get(int, int);
+    method public boolean intersects(java.util.BitSet);
+    method public boolean isEmpty();
+    method public int length();
+    method public int nextClearBit(int);
+    method public int nextSetBit(int);
+    method public void or(java.util.BitSet);
+    method public void set(int);
+    method public void set(int, boolean);
+    method public void set(int, int, boolean);
+    method public void set(int, int);
+    method public int size();
+    method public void xor(java.util.BitSet);
+  }
+
+  public abstract class Calendar implements java.lang.Cloneable java.lang.Comparable java.io.Serializable {
+    ctor protected Calendar();
+    ctor protected Calendar(java.util.TimeZone, java.util.Locale);
+    method public abstract void add(int, int);
+    method public boolean after(java.lang.Object);
+    method public boolean before(java.lang.Object);
+    method public final void clear();
+    method public final void clear(int);
+    method public java.lang.Object clone();
+    method public int compareTo(java.util.Calendar);
+    method protected void complete();
+    method protected abstract void computeFields();
+    method protected abstract void computeTime();
+    method public int get(int);
+    method public int getActualMaximum(int);
+    method public int getActualMinimum(int);
+    method public static synchronized java.util.Locale[] getAvailableLocales();
+    method public java.lang.String getDisplayName(int, int, java.util.Locale);
+    method public java.util.Map<java.lang.String, java.lang.Integer> getDisplayNames(int, int, java.util.Locale);
+    method public int getFirstDayOfWeek();
+    method public abstract int getGreatestMinimum(int);
+    method public static synchronized java.util.Calendar getInstance();
+    method public static synchronized java.util.Calendar getInstance(java.util.Locale);
+    method public static synchronized java.util.Calendar getInstance(java.util.TimeZone);
+    method public static synchronized java.util.Calendar getInstance(java.util.TimeZone, java.util.Locale);
+    method public abstract int getLeastMaximum(int);
+    method public abstract int getMaximum(int);
+    method public int getMinimalDaysInFirstWeek();
+    method public abstract int getMinimum(int);
+    method public final java.util.Date getTime();
+    method public long getTimeInMillis();
+    method public java.util.TimeZone getTimeZone();
+    method protected final int internalGet(int);
+    method public boolean isLenient();
+    method public final boolean isSet(int);
+    method public void roll(int, int);
+    method public abstract void roll(int, boolean);
+    method public void set(int, int);
+    method public final void set(int, int, int);
+    method public final void set(int, int, int, int, int);
+    method public final void set(int, int, int, int, int, int);
+    method public void setFirstDayOfWeek(int);
+    method public void setLenient(boolean);
+    method public void setMinimalDaysInFirstWeek(int);
+    method public final void setTime(java.util.Date);
+    method public void setTimeInMillis(long);
+    method public void setTimeZone(java.util.TimeZone);
+    field public static final int ALL_STYLES = 0; // 0x0
+    field public static final int AM = 0; // 0x0
+    field public static final int AM_PM = 9; // 0x9
+    field public static final int APRIL = 3; // 0x3
+    field public static final int AUGUST = 7; // 0x7
+    field public static final int DATE = 5; // 0x5
+    field public static final int DAY_OF_MONTH = 5; // 0x5
+    field public static final int DAY_OF_WEEK = 7; // 0x7
+    field public static final int DAY_OF_WEEK_IN_MONTH = 8; // 0x8
+    field public static final int DAY_OF_YEAR = 6; // 0x6
+    field public static final int DECEMBER = 11; // 0xb
+    field public static final int DST_OFFSET = 16; // 0x10
+    field public static final int ERA = 0; // 0x0
+    field public static final int FEBRUARY = 1; // 0x1
+    field public static final int FIELD_COUNT = 17; // 0x11
+    field public static final int FRIDAY = 6; // 0x6
+    field public static final int HOUR = 10; // 0xa
+    field public static final int HOUR_OF_DAY = 11; // 0xb
+    field public static final int JANUARY = 0; // 0x0
+    field public static final int JULY = 6; // 0x6
+    field public static final int JUNE = 5; // 0x5
+    field public static final int LONG = 2; // 0x2
+    field public static final int MARCH = 2; // 0x2
+    field public static final int MAY = 4; // 0x4
+    field public static final int MILLISECOND = 14; // 0xe
+    field public static final int MINUTE = 12; // 0xc
+    field public static final int MONDAY = 2; // 0x2
+    field public static final int MONTH = 2; // 0x2
+    field public static final int NOVEMBER = 10; // 0xa
+    field public static final int OCTOBER = 9; // 0x9
+    field public static final int PM = 1; // 0x1
+    field public static final int SATURDAY = 7; // 0x7
+    field public static final int SECOND = 13; // 0xd
+    field public static final int SEPTEMBER = 8; // 0x8
+    field public static final int SHORT = 1; // 0x1
+    field public static final int SUNDAY = 1; // 0x1
+    field public static final int THURSDAY = 5; // 0x5
+    field public static final int TUESDAY = 3; // 0x3
+    field public static final int UNDECIMBER = 12; // 0xc
+    field public static final int WEDNESDAY = 4; // 0x4
+    field public static final int WEEK_OF_MONTH = 4; // 0x4
+    field public static final int WEEK_OF_YEAR = 3; // 0x3
+    field public static final int YEAR = 1; // 0x1
+    field public static final int ZONE_OFFSET = 15; // 0xf
+    field protected boolean areFieldsSet;
+    field protected int[] fields;
+    field protected boolean[] isSet;
+    field protected boolean isTimeSet;
+    field protected long time;
+  }
+
+  public abstract interface Collection implements java.lang.Iterable {
+    method public abstract boolean add(E);
+    method public abstract boolean addAll(java.util.Collection<? extends E>);
+    method public abstract void clear();
+    method public abstract boolean contains(java.lang.Object);
+    method public abstract boolean containsAll(java.util.Collection<?>);
+    method public abstract boolean equals(java.lang.Object);
+    method public abstract int hashCode();
+    method public abstract boolean isEmpty();
+    method public abstract java.util.Iterator<E> iterator();
+    method public abstract boolean remove(java.lang.Object);
+    method public abstract boolean removeAll(java.util.Collection<?>);
+    method public abstract boolean retainAll(java.util.Collection<?>);
+    method public abstract int size();
+    method public abstract java.lang.Object[] toArray();
+    method public abstract T[] toArray(T[]);
+  }
+
+  public class Collections {
+    method public static boolean addAll(java.util.Collection<? super T>, T...);
+    method public static java.util.Queue<T> asLifoQueue(java.util.Deque<T>);
+    method public static int binarySearch(java.util.List<? extends java.lang.Comparable<? super T>>, T);
+    method public static int binarySearch(java.util.List<? extends T>, T, java.util.Comparator<? super T>);
+    method public static java.util.Collection<E> checkedCollection(java.util.Collection<E>, java.lang.Class<E>);
+    method public static java.util.List<E> checkedList(java.util.List<E>, java.lang.Class<E>);
+    method public static java.util.Map<K, V> checkedMap(java.util.Map<K, V>, java.lang.Class<K>, java.lang.Class<V>);
+    method public static java.util.Set<E> checkedSet(java.util.Set<E>, java.lang.Class<E>);
+    method public static java.util.SortedMap<K, V> checkedSortedMap(java.util.SortedMap<K, V>, java.lang.Class<K>, java.lang.Class<V>);
+    method public static java.util.SortedSet<E> checkedSortedSet(java.util.SortedSet<E>, java.lang.Class<E>);
+    method public static void copy(java.util.List<? super T>, java.util.List<? extends T>);
+    method public static boolean disjoint(java.util.Collection<?>, java.util.Collection<?>);
+    method public static final java.util.List<T> emptyList();
+    method public static final java.util.Map<K, V> emptyMap();
+    method public static final java.util.Set<T> emptySet();
+    method public static java.util.Enumeration<T> enumeration(java.util.Collection<T>);
+    method public static void fill(java.util.List<? super T>, T);
+    method public static int frequency(java.util.Collection<?>, java.lang.Object);
+    method public static int indexOfSubList(java.util.List<?>, java.util.List<?>);
+    method public static int lastIndexOfSubList(java.util.List<?>, java.util.List<?>);
+    method public static java.util.ArrayList<T> list(java.util.Enumeration<T>);
+    method public static T max(java.util.Collection<? extends T>);
+    method public static T max(java.util.Collection<? extends T>, java.util.Comparator<? super T>);
+    method public static T min(java.util.Collection<? extends T>);
+    method public static T min(java.util.Collection<? extends T>, java.util.Comparator<? super T>);
+    method public static java.util.List<T> nCopies(int, T);
+    method public static java.util.Set<E> newSetFromMap(java.util.Map<E, java.lang.Boolean>);
+    method public static boolean replaceAll(java.util.List<T>, T, T);
+    method public static void reverse(java.util.List<?>);
+    method public static java.util.Comparator<T> reverseOrder();
+    method public static java.util.Comparator<T> reverseOrder(java.util.Comparator<T>);
+    method public static void rotate(java.util.List<?>, int);
+    method public static void shuffle(java.util.List<?>);
+    method public static void shuffle(java.util.List<?>, java.util.Random);
+    method public static java.util.Set<E> singleton(E);
+    method public static java.util.List<E> singletonList(E);
+    method public static java.util.Map<K, V> singletonMap(K, V);
+    method public static void sort(java.util.List<T>);
+    method public static void sort(java.util.List<T>, java.util.Comparator<? super T>);
+    method public static void swap(java.util.List<?>, int, int);
+    method public static java.util.Collection<T> synchronizedCollection(java.util.Collection<T>);
+    method public static java.util.List<T> synchronizedList(java.util.List<T>);
+    method public static java.util.Map<K, V> synchronizedMap(java.util.Map<K, V>);
+    method public static java.util.Set<E> synchronizedSet(java.util.Set<E>);
+    method public static java.util.SortedMap<K, V> synchronizedSortedMap(java.util.SortedMap<K, V>);
+    method public static java.util.SortedSet<E> synchronizedSortedSet(java.util.SortedSet<E>);
+    method public static java.util.Collection<E> unmodifiableCollection(java.util.Collection<? extends E>);
+    method public static java.util.List<E> unmodifiableList(java.util.List<? extends E>);
+    method public static java.util.Map<K, V> unmodifiableMap(java.util.Map<? extends K, ? extends V>);
+    method public static java.util.Set<E> unmodifiableSet(java.util.Set<? extends E>);
+    method public static java.util.SortedMap<K, V> unmodifiableSortedMap(java.util.SortedMap<K, ? extends V>);
+    method public static java.util.SortedSet<E> unmodifiableSortedSet(java.util.SortedSet<E>);
+    field public static final java.util.List EMPTY_LIST;
+    field public static final java.util.Map EMPTY_MAP;
+    field public static final java.util.Set EMPTY_SET;
+  }
+
+  public abstract interface Comparator {
+    method public abstract int compare(T, T);
+    method public abstract boolean equals(java.lang.Object);
+  }
+
+  public class ConcurrentModificationException extends java.lang.RuntimeException {
+    ctor public ConcurrentModificationException();
+    ctor public ConcurrentModificationException(java.lang.String);
+  }
+
+  public final class Currency implements java.io.Serializable {
+    method public java.lang.String getCurrencyCode();
+    method public int getDefaultFractionDigits();
+    method public static java.util.Currency getInstance(java.lang.String);
+    method public static java.util.Currency getInstance(java.util.Locale);
+    method public java.lang.String getSymbol();
+    method public java.lang.String getSymbol(java.util.Locale);
+  }
+
+  public class Date implements java.lang.Cloneable java.lang.Comparable java.io.Serializable {
+    ctor public Date();
+    ctor public deprecated Date(int, int, int);
+    ctor public deprecated Date(int, int, int, int, int);
+    ctor public deprecated Date(int, int, int, int, int, int);
+    ctor public Date(long);
+    ctor public deprecated Date(java.lang.String);
+    method public static deprecated long UTC(int, int, int, int, int, int);
+    method public boolean after(java.util.Date);
+    method public boolean before(java.util.Date);
+    method public java.lang.Object clone();
+    method public int compareTo(java.util.Date);
+    method public deprecated int getDate();
+    method public deprecated int getDay();
+    method public deprecated int getHours();
+    method public deprecated int getMinutes();
+    method public deprecated int getMonth();
+    method public deprecated int getSeconds();
+    method public long getTime();
+    method public deprecated int getTimezoneOffset();
+    method public deprecated int getYear();
+    method public static deprecated long parse(java.lang.String);
+    method public deprecated void setDate(int);
+    method public deprecated void setHours(int);
+    method public deprecated void setMinutes(int);
+    method public deprecated void setMonth(int);
+    method public deprecated void setSeconds(int);
+    method public void setTime(long);
+    method public deprecated void setYear(int);
+    method public deprecated java.lang.String toGMTString();
+    method public deprecated java.lang.String toLocaleString();
+  }
+
+  public abstract interface Deque implements java.util.Queue {
+    method public abstract boolean add(E);
+    method public abstract void addFirst(E);
+    method public abstract void addLast(E);
+    method public abstract boolean contains(java.lang.Object);
+    method public abstract java.util.Iterator<E> descendingIterator();
+    method public abstract E element();
+    method public abstract E getFirst();
+    method public abstract E getLast();
+    method public abstract java.util.Iterator<E> iterator();
+    method public abstract boolean offer(E);
+    method public abstract boolean offerFirst(E);
+    method public abstract boolean offerLast(E);
+    method public abstract E peek();
+    method public abstract E peekFirst();
+    method public abstract E peekLast();
+    method public abstract E poll();
+    method public abstract E pollFirst();
+    method public abstract E pollLast();
+    method public abstract E pop();
+    method public abstract void push(E);
+    method public abstract E remove();
+    method public abstract boolean remove(java.lang.Object);
+    method public abstract E removeFirst();
+    method public abstract boolean removeFirstOccurrence(java.lang.Object);
+    method public abstract E removeLast();
+    method public abstract boolean removeLastOccurrence(java.lang.Object);
+    method public abstract int size();
+  }
+
+  public abstract class Dictionary {
+    ctor public Dictionary();
+    method public abstract java.util.Enumeration<V> elements();
+    method public abstract V get(java.lang.Object);
+    method public abstract boolean isEmpty();
+    method public abstract java.util.Enumeration<K> keys();
+    method public abstract V put(K, V);
+    method public abstract V remove(java.lang.Object);
+    method public abstract int size();
+  }
+
+  public class DuplicateFormatFlagsException extends java.util.IllegalFormatException {
+    ctor public DuplicateFormatFlagsException(java.lang.String);
+    method public java.lang.String getFlags();
+  }
+
+  public class EmptyStackException extends java.lang.RuntimeException {
+    ctor public EmptyStackException();
+  }
+
+  public class EnumMap extends java.util.AbstractMap implements java.lang.Cloneable java.util.Map java.io.Serializable {
+    ctor public EnumMap(java.lang.Class<K>);
+    ctor public EnumMap(java.util.EnumMap<K, ? extends V>);
+    ctor public EnumMap(java.util.Map<K, ? extends V>);
+    method public java.util.EnumMap<K, V> clone();
+    method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+  }
+
+  public abstract class EnumSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable {
+    method public static java.util.EnumSet<E> allOf(java.lang.Class<E>);
+    method public java.util.EnumSet<E> clone();
+    method public static java.util.EnumSet<E> complementOf(java.util.EnumSet<E>);
+    method public static java.util.EnumSet<E> copyOf(java.util.EnumSet<E>);
+    method public static java.util.EnumSet<E> copyOf(java.util.Collection<E>);
+    method public static java.util.EnumSet<E> noneOf(java.lang.Class<E>);
+    method public static java.util.EnumSet<E> of(E);
+    method public static java.util.EnumSet<E> of(E, E);
+    method public static java.util.EnumSet<E> of(E, E, E);
+    method public static java.util.EnumSet<E> of(E, E, E, E);
+    method public static java.util.EnumSet<E> of(E, E, E, E, E);
+    method public static java.util.EnumSet<E> of(E, E...);
+    method public static java.util.EnumSet<E> range(E, E);
+  }
+
+  public abstract interface Enumeration {
+    method public abstract boolean hasMoreElements();
+    method public abstract E nextElement();
+  }
+
+  public abstract interface EventListener {
+  }
+
+  public abstract class EventListenerProxy implements java.util.EventListener {
+    ctor public EventListenerProxy(java.util.EventListener);
+    method public java.util.EventListener getListener();
+  }
+
+  public class EventObject implements java.io.Serializable {
+    ctor public EventObject(java.lang.Object);
+    method public java.lang.Object getSource();
+    field protected transient java.lang.Object source;
+  }
+
+  public class FormatFlagsConversionMismatchException extends java.util.IllegalFormatException implements java.io.Serializable {
+    ctor public FormatFlagsConversionMismatchException(java.lang.String, char);
+    method public char getConversion();
+    method public java.lang.String getFlags();
+  }
+
+  public abstract interface Formattable {
+    method public abstract void formatTo(java.util.Formatter, int, int, int) throws java.util.IllegalFormatException;
+  }
+
+  public class FormattableFlags {
+    field public static final int ALTERNATE = 4; // 0x4
+    field public static final int LEFT_JUSTIFY = 1; // 0x1
+    field public static final int UPPERCASE = 2; // 0x2
+  }
+
+  public final class Formatter implements java.io.Closeable java.io.Flushable {
+    ctor public Formatter();
+    ctor public Formatter(java.lang.Appendable);
+    ctor public Formatter(java.util.Locale);
+    ctor public Formatter(java.lang.Appendable, java.util.Locale);
+    ctor public Formatter(java.lang.String) throws java.io.FileNotFoundException;
+    ctor public Formatter(java.lang.String, java.lang.String) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException;
+    ctor public Formatter(java.lang.String, java.lang.String, java.util.Locale) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException;
+    ctor public Formatter(java.io.File) throws java.io.FileNotFoundException;
+    ctor public Formatter(java.io.File, java.lang.String) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException;
+    ctor public Formatter(java.io.File, java.lang.String, java.util.Locale) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException;
+    ctor public Formatter(java.io.OutputStream);
+    ctor public Formatter(java.io.OutputStream, java.lang.String) throws java.io.UnsupportedEncodingException;
+    ctor public Formatter(java.io.OutputStream, java.lang.String, java.util.Locale) throws java.io.UnsupportedEncodingException;
+    ctor public Formatter(java.io.PrintStream);
+    method public void close();
+    method public void flush();
+    method public java.util.Formatter format(java.lang.String, java.lang.Object...);
+    method public java.util.Formatter format(java.util.Locale, java.lang.String, java.lang.Object...);
+    method public java.io.IOException ioException();
+    method public java.util.Locale locale();
+    method public java.lang.Appendable out();
+  }
+
+  public static final class Formatter.BigDecimalLayoutForm extends java.lang.Enum {
+    method public static java.util.Formatter.BigDecimalLayoutForm valueOf(java.lang.String);
+    method public static final java.util.Formatter.BigDecimalLayoutForm[] values();
+    enum_constant public static final java.util.Formatter.BigDecimalLayoutForm DECIMAL_FLOAT;
+    enum_constant public static final java.util.Formatter.BigDecimalLayoutForm SCIENTIFIC;
+  }
+
+  public class FormatterClosedException extends java.lang.IllegalStateException implements java.io.Serializable {
+    ctor public FormatterClosedException();
+  }
+
+  public class GregorianCalendar extends java.util.Calendar {
+    ctor public GregorianCalendar();
+    ctor public GregorianCalendar(int, int, int);
+    ctor public GregorianCalendar(int, int, int, int, int);
+    ctor public GregorianCalendar(int, int, int, int, int, int);
+    ctor public GregorianCalendar(java.util.Locale);
+    ctor public GregorianCalendar(java.util.TimeZone);
+    ctor public GregorianCalendar(java.util.TimeZone, java.util.Locale);
+    method public void add(int, int);
+    method protected void computeFields();
+    method protected void computeTime();
+    method public int getGreatestMinimum(int);
+    method public final java.util.Date getGregorianChange();
+    method public int getLeastMaximum(int);
+    method public int getMaximum(int);
+    method public int getMinimum(int);
+    method public boolean isLeapYear(int);
+    method public void roll(int, boolean);
+    method public void setGregorianChange(java.util.Date);
+    field public static final int AD = 1; // 0x1
+    field public static final int BC = 0; // 0x0
+  }
+
+  public class HashMap extends java.util.AbstractMap implements java.lang.Cloneable java.io.Serializable {
+    ctor public HashMap();
+    ctor public HashMap(int);
+    ctor public HashMap(int, float);
+    ctor public HashMap(java.util.Map<? extends K, ? extends V>);
+    method public java.lang.Object clone();
+    method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+  }
+
+  public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
+    ctor public HashSet();
+    ctor public HashSet(int);
+    ctor public HashSet(int, float);
+    ctor public HashSet(java.util.Collection<? extends E>);
+    method public java.lang.Object clone();
+    method public java.util.Iterator<E> iterator();
+    method public int size();
+  }
+
+  public class Hashtable extends java.util.Dictionary implements java.lang.Cloneable java.util.Map java.io.Serializable {
+    ctor public Hashtable();
+    ctor public Hashtable(int);
+    ctor public Hashtable(int, float);
+    ctor public Hashtable(java.util.Map<? extends K, ? extends V>);
+    method public synchronized void clear();
+    method public synchronized java.lang.Object clone();
+    method public boolean contains(java.lang.Object);
+    method public synchronized boolean containsKey(java.lang.Object);
+    method public synchronized boolean containsValue(java.lang.Object);
+    method public synchronized java.util.Enumeration<V> elements();
+    method public synchronized java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public synchronized V get(java.lang.Object);
+    method public synchronized boolean isEmpty();
+    method public synchronized java.util.Set<K> keySet();
+    method public synchronized java.util.Enumeration<K> keys();
+    method public synchronized V put(K, V);
+    method public synchronized void putAll(java.util.Map<? extends K, ? extends V>);
+    method protected void rehash();
+    method public synchronized V remove(java.lang.Object);
+    method public synchronized int size();
+    method public synchronized java.util.Collection<V> values();
+  }
+
+  public class IdentityHashMap extends java.util.AbstractMap implements java.lang.Cloneable java.util.Map java.io.Serializable {
+    ctor public IdentityHashMap();
+    ctor public IdentityHashMap(int);
+    ctor public IdentityHashMap(java.util.Map<? extends K, ? extends V>);
+    method public java.lang.Object clone();
+    method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+  }
+
+  public class IllegalFormatCodePointException extends java.util.IllegalFormatException implements java.io.Serializable {
+    ctor public IllegalFormatCodePointException(int);
+    method public int getCodePoint();
+  }
+
+  public class IllegalFormatConversionException extends java.util.IllegalFormatException implements java.io.Serializable {
+    ctor public IllegalFormatConversionException(char, java.lang.Class<?>);
+    method public java.lang.Class<?> getArgumentClass();
+    method public char getConversion();
+  }
+
+  public class IllegalFormatException extends java.lang.IllegalArgumentException implements java.io.Serializable {
+  }
+
+  public class IllegalFormatFlagsException extends java.util.IllegalFormatException implements java.io.Serializable {
+    ctor public IllegalFormatFlagsException(java.lang.String);
+    method public java.lang.String getFlags();
+  }
+
+  public class IllegalFormatPrecisionException extends java.util.IllegalFormatException {
+    ctor public IllegalFormatPrecisionException(int);
+    method public int getPrecision();
+  }
+
+  public class IllegalFormatWidthException extends java.util.IllegalFormatException {
+    ctor public IllegalFormatWidthException(int);
+    method public int getWidth();
+  }
+
+  public class InputMismatchException extends java.util.NoSuchElementException implements java.io.Serializable {
+    ctor public InputMismatchException();
+    ctor public InputMismatchException(java.lang.String);
+  }
+
+  public class InvalidPropertiesFormatException extends java.io.IOException {
+    ctor public InvalidPropertiesFormatException(java.lang.String);
+    ctor public InvalidPropertiesFormatException(java.lang.Throwable);
+  }
+
+  public abstract interface Iterator {
+    method public abstract boolean hasNext();
+    method public abstract E next();
+    method public abstract void remove();
+  }
+
+  public class LinkedHashMap extends java.util.HashMap {
+    ctor public LinkedHashMap();
+    ctor public LinkedHashMap(int);
+    ctor public LinkedHashMap(int, float);
+    ctor public LinkedHashMap(int, float, boolean);
+    ctor public LinkedHashMap(java.util.Map<? extends K, ? extends V>);
+    method protected boolean removeEldestEntry(java.util.Map.Entry<K, V>);
+  }
+
+  public class LinkedHashSet extends java.util.HashSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
+    ctor public LinkedHashSet();
+    ctor public LinkedHashSet(int);
+    ctor public LinkedHashSet(int, float);
+    ctor public LinkedHashSet(java.util.Collection<? extends E>);
+  }
+
+  public class LinkedList extends java.util.AbstractSequentialList implements java.lang.Cloneable java.util.Deque java.util.List java.util.Queue java.io.Serializable {
+    ctor public LinkedList();
+    ctor public LinkedList(java.util.Collection<? extends E>);
+    method public void addFirst(E);
+    method public void addLast(E);
+    method public java.lang.Object clone();
+    method public java.util.Iterator<E> descendingIterator();
+    method public E element();
+    method public E getFirst();
+    method public E getLast();
+    method public java.util.ListIterator<E> listIterator(int);
+    method public boolean offer(E);
+    method public boolean offerFirst(E);
+    method public boolean offerLast(E);
+    method public E peek();
+    method public E peekFirst();
+    method public E peekLast();
+    method public E poll();
+    method public E pollFirst();
+    method public E pollLast();
+    method public E pop();
+    method public void push(E);
+    method public E remove();
+    method public E removeFirst();
+    method public boolean removeFirstOccurrence(java.lang.Object);
+    method public E removeLast();
+    method public boolean removeLastOccurrence(java.lang.Object);
+    method public int size();
+  }
+
+  public abstract interface List implements java.util.Collection {
+    method public abstract void add(int, E);
+    method public abstract boolean add(E);
+    method public abstract boolean addAll(int, java.util.Collection<? extends E>);
+    method public abstract boolean addAll(java.util.Collection<? extends E>);
+    method public abstract void clear();
+    method public abstract boolean contains(java.lang.Object);
+    method public abstract boolean containsAll(java.util.Collection<?>);
+    method public abstract boolean equals(java.lang.Object);
+    method public abstract E get(int);
+    method public abstract int hashCode();
+    method public abstract int indexOf(java.lang.Object);
+    method public abstract boolean isEmpty();
+    method public abstract java.util.Iterator<E> iterator();
+    method public abstract int lastIndexOf(java.lang.Object);
+    method public abstract java.util.ListIterator<E> listIterator();
+    method public abstract java.util.ListIterator<E> listIterator(int);
+    method public abstract E remove(int);
+    method public abstract boolean remove(java.lang.Object);
+    method public abstract boolean removeAll(java.util.Collection<?>);
+    method public abstract boolean retainAll(java.util.Collection<?>);
+    method public abstract E set(int, E);
+    method public abstract int size();
+    method public abstract java.util.List<E> subList(int, int);
+    method public abstract java.lang.Object[] toArray();
+    method public abstract T[] toArray(T[]);
+  }
+
+  public abstract interface ListIterator implements java.util.Iterator {
+    method public abstract void add(E);
+    method public abstract boolean hasNext();
+    method public abstract boolean hasPrevious();
+    method public abstract E next();
+    method public abstract int nextIndex();
+    method public abstract E previous();
+    method public abstract int previousIndex();
+    method public abstract void remove();
+    method public abstract void set(E);
+  }
+
+  public abstract class ListResourceBundle extends java.util.ResourceBundle {
+    ctor public ListResourceBundle();
+    method protected abstract java.lang.Object[][] getContents();
+    method public java.util.Enumeration<java.lang.String> getKeys();
+    method public final java.lang.Object handleGetObject(java.lang.String);
+  }
+
+  public final class Locale implements java.lang.Cloneable java.io.Serializable {
+    ctor public Locale(java.lang.String);
+    ctor public Locale(java.lang.String, java.lang.String);
+    ctor public Locale(java.lang.String, java.lang.String, java.lang.String);
+    method public java.lang.Object clone();
+    method public static java.util.Locale[] getAvailableLocales();
+    method public java.lang.String getCountry();
+    method public static java.util.Locale getDefault();
+    method public final java.lang.String getDisplayCountry();
+    method public java.lang.String getDisplayCountry(java.util.Locale);
+    method public final java.lang.String getDisplayLanguage();
+    method public java.lang.String getDisplayLanguage(java.util.Locale);
+    method public final java.lang.String getDisplayName();
+    method public java.lang.String getDisplayName(java.util.Locale);
+    method public final java.lang.String getDisplayVariant();
+    method public java.lang.String getDisplayVariant(java.util.Locale);
+    method public java.lang.String getISO3Country();
+    method public java.lang.String getISO3Language();
+    method public static java.lang.String[] getISOCountries();
+    method public static java.lang.String[] getISOLanguages();
+    method public java.lang.String getLanguage();
+    method public java.lang.String getVariant();
+    method public static synchronized void setDefault(java.util.Locale);
+    method public final java.lang.String toString();
+    field public static final java.util.Locale CANADA;
+    field public static final java.util.Locale CANADA_FRENCH;
+    field public static final java.util.Locale CHINA;
+    field public static final java.util.Locale CHINESE;
+    field public static final java.util.Locale ENGLISH;
+    field public static final java.util.Locale FRANCE;
+    field public static final java.util.Locale FRENCH;
+    field public static final java.util.Locale GERMAN;
+    field public static final java.util.Locale GERMANY;
+    field public static final java.util.Locale ITALIAN;
+    field public static final java.util.Locale ITALY;
+    field public static final java.util.Locale JAPAN;
+    field public static final java.util.Locale JAPANESE;
+    field public static final java.util.Locale KOREA;
+    field public static final java.util.Locale KOREAN;
+    field public static final java.util.Locale PRC;
+    field public static final java.util.Locale ROOT;
+    field public static final java.util.Locale SIMPLIFIED_CHINESE;
+    field public static final java.util.Locale TAIWAN;
+    field public static final java.util.Locale TRADITIONAL_CHINESE;
+    field public static final java.util.Locale UK;
+    field public static final java.util.Locale US;
+  }
+
+  public abstract interface Map {
+    method public abstract void clear();
+    method public abstract boolean containsKey(java.lang.Object);
+    method public abstract boolean containsValue(java.lang.Object);
+    method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public abstract boolean equals(java.lang.Object);
+    method public abstract V get(java.lang.Object);
+    method public abstract int hashCode();
+    method public abstract boolean isEmpty();
+    method public abstract java.util.Set<K> keySet();
+    method public abstract V put(K, V);
+    method public abstract void putAll(java.util.Map<? extends K, ? extends V>);
+    method public abstract V remove(java.lang.Object);
+    method public abstract int size();
+    method public abstract java.util.Collection<V> values();
+  }
+
+  public static abstract interface Map.Entry {
+    method public abstract boolean equals(java.lang.Object);
+    method public abstract K getKey();
+    method public abstract V getValue();
+    method public abstract int hashCode();
+    method public abstract V setValue(V);
+  }
+
+  public class MissingFormatArgumentException extends java.util.IllegalFormatException {
+    ctor public MissingFormatArgumentException(java.lang.String);
+    method public java.lang.String getFormatSpecifier();
+  }
+
+  public class MissingFormatWidthException extends java.util.IllegalFormatException {
+    ctor public MissingFormatWidthException(java.lang.String);
+    method public java.lang.String getFormatSpecifier();
+  }
+
+  public class MissingResourceException extends java.lang.RuntimeException {
+    ctor public MissingResourceException(java.lang.String, java.lang.String, java.lang.String);
+    method public java.lang.String getClassName();
+    method public java.lang.String getKey();
+  }
+
+  public abstract interface NavigableMap implements java.util.SortedMap {
+    method public abstract java.util.Map.Entry<K, V> ceilingEntry(K);
+    method public abstract K ceilingKey(K);
+    method public abstract java.util.NavigableSet<K> descendingKeySet();
+    method public abstract java.util.NavigableMap<K, V> descendingMap();
+    method public abstract java.util.Map.Entry<K, V> firstEntry();
+    method public abstract java.util.Map.Entry<K, V> floorEntry(K);
+    method public abstract K floorKey(K);
+    method public abstract java.util.NavigableMap<K, V> headMap(K, boolean);
+    method public abstract java.util.SortedMap<K, V> headMap(K);
+    method public abstract java.util.Map.Entry<K, V> higherEntry(K);
+    method public abstract K higherKey(K);
+    method public abstract java.util.Map.Entry<K, V> lastEntry();
+    method public abstract java.util.Map.Entry<K, V> lowerEntry(K);
+    method public abstract K lowerKey(K);
+    method public abstract java.util.NavigableSet<K> navigableKeySet();
+    method public abstract java.util.Map.Entry<K, V> pollFirstEntry();
+    method public abstract java.util.Map.Entry<K, V> pollLastEntry();
+    method public abstract java.util.NavigableMap<K, V> subMap(K, boolean, K, boolean);
+    method public abstract java.util.SortedMap<K, V> subMap(K, K);
+    method public abstract java.util.NavigableMap<K, V> tailMap(K, boolean);
+    method public abstract java.util.SortedMap<K, V> tailMap(K);
+  }
+
+  public abstract interface NavigableSet implements java.util.SortedSet {
+    method public abstract E ceiling(E);
+    method public abstract java.util.Iterator<E> descendingIterator();
+    method public abstract java.util.NavigableSet<E> descendingSet();
+    method public abstract E floor(E);
+    method public abstract java.util.NavigableSet<E> headSet(E, boolean);
+    method public abstract java.util.SortedSet<E> headSet(E);
+    method public abstract E higher(E);
+    method public abstract java.util.Iterator<E> iterator();
+    method public abstract E lower(E);
+    method public abstract E pollFirst();
+    method public abstract E pollLast();
+    method public abstract java.util.NavigableSet<E> subSet(E, boolean, E, boolean);
+    method public abstract java.util.SortedSet<E> subSet(E, E);
+    method public abstract java.util.NavigableSet<E> tailSet(E, boolean);
+    method public abstract java.util.SortedSet<E> tailSet(E);
+  }
+
+  public class NoSuchElementException extends java.lang.RuntimeException {
+    ctor public NoSuchElementException();
+    ctor public NoSuchElementException(java.lang.String);
+  }
+
+  public class Observable {
+    ctor public Observable();
+    method public void addObserver(java.util.Observer);
+    method protected void clearChanged();
+    method public int countObservers();
+    method public synchronized void deleteObserver(java.util.Observer);
+    method public synchronized void deleteObservers();
+    method public boolean hasChanged();
+    method public void notifyObservers();
+    method public void notifyObservers(java.lang.Object);
+    method protected void setChanged();
+  }
+
+  public abstract interface Observer {
+    method public abstract void update(java.util.Observable, java.lang.Object);
+  }
+
+  public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
+    ctor public PriorityQueue();
+    ctor public PriorityQueue(int);
+    ctor public PriorityQueue(int, java.util.Comparator<? super E>);
+    ctor public PriorityQueue(java.util.Collection<? extends E>);
+    ctor public PriorityQueue(java.util.PriorityQueue<? extends E>);
+    ctor public PriorityQueue(java.util.SortedSet<? extends E>);
+    method public java.util.Comparator<? super E> comparator();
+    method public java.util.Iterator<E> iterator();
+    method public boolean offer(E);
+    method public E peek();
+    method public E poll();
+    method public int size();
+  }
+
+  public class Properties extends java.util.Hashtable {
+    ctor public Properties();
+    ctor public Properties(java.util.Properties);
+    method public java.lang.String getProperty(java.lang.String);
+    method public java.lang.String getProperty(java.lang.String, java.lang.String);
+    method public void list(java.io.PrintStream);
+    method public void list(java.io.PrintWriter);
+    method public synchronized void load(java.io.InputStream) throws java.io.IOException;
+    method public synchronized void load(java.io.Reader) throws java.io.IOException;
+    method public synchronized void loadFromXML(java.io.InputStream) throws java.io.IOException, java.util.InvalidPropertiesFormatException;
+    method public java.util.Enumeration<?> propertyNames();
+    method public deprecated void save(java.io.OutputStream, java.lang.String);
+    method public java.lang.Object setProperty(java.lang.String, java.lang.String);
+    method public synchronized void store(java.io.OutputStream, java.lang.String) throws java.io.IOException;
+    method public synchronized void store(java.io.Writer, java.lang.String) throws java.io.IOException;
+    method public void storeToXML(java.io.OutputStream, java.lang.String) throws java.io.IOException;
+    method public synchronized void storeToXML(java.io.OutputStream, java.lang.String, java.lang.String) throws java.io.IOException;
+    method public java.util.Set<java.lang.String> stringPropertyNames();
+    field protected java.util.Properties defaults;
+  }
+
+  public final class PropertyPermission extends java.security.BasicPermission {
+    ctor public PropertyPermission(java.lang.String, java.lang.String);
+  }
+
+  public class PropertyResourceBundle extends java.util.ResourceBundle {
+    ctor public PropertyResourceBundle(java.io.InputStream) throws java.io.IOException;
+    ctor public PropertyResourceBundle(java.io.Reader) throws java.io.IOException;
+    method public java.util.Enumeration<java.lang.String> getKeys();
+    method public java.lang.Object handleGetObject(java.lang.String);
+  }
+
+  public abstract interface Queue implements java.util.Collection {
+    method public abstract boolean add(E);
+    method public abstract E element();
+    method public abstract boolean offer(E);
+    method public abstract E peek();
+    method public abstract E poll();
+    method public abstract E remove();
+  }
+
+  public class Random implements java.io.Serializable {
+    ctor public Random();
+    ctor public Random(long);
+    method protected synchronized int next(int);
+    method public boolean nextBoolean();
+    method public void nextBytes(byte[]);
+    method public double nextDouble();
+    method public float nextFloat();
+    method public synchronized double nextGaussian();
+    method public int nextInt();
+    method public int nextInt(int);
+    method public long nextLong();
+    method public synchronized void setSeed(long);
+  }
+
+  public abstract interface RandomAccess {
+  }
+
+  public abstract class ResourceBundle {
+    ctor public ResourceBundle();
+    method public static void clearCache();
+    method public static void clearCache(java.lang.ClassLoader);
+    method public boolean containsKey(java.lang.String);
+    method public static java.util.ResourceBundle getBundle(java.lang.String) throws java.util.MissingResourceException;
+    method public static java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale);
+    method public static java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader) throws java.util.MissingResourceException;
+    method public static java.util.ResourceBundle getBundle(java.lang.String, java.util.ResourceBundle.Control);
+    method public static java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale, java.util.ResourceBundle.Control);
+    method public static java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader, java.util.ResourceBundle.Control);
+    method public abstract java.util.Enumeration<java.lang.String> getKeys();
+    method public java.util.Locale getLocale();
+    method public final java.lang.Object getObject(java.lang.String);
+    method public final java.lang.String getString(java.lang.String);
+    method public final java.lang.String[] getStringArray(java.lang.String);
+    method protected abstract java.lang.Object handleGetObject(java.lang.String);
+    method protected java.util.Set<java.lang.String> handleKeySet();
+    method public java.util.Set<java.lang.String> keySet();
+    method protected void setParent(java.util.ResourceBundle);
+    field protected java.util.ResourceBundle parent;
+  }
+
+  public static class ResourceBundle.Control {
+    ctor protected ResourceBundle.Control();
+    method public java.util.List<java.util.Locale> getCandidateLocales(java.lang.String, java.util.Locale);
+    method public static java.util.ResourceBundle.Control getControl(java.util.List<java.lang.String>);
+    method public java.util.Locale getFallbackLocale(java.lang.String, java.util.Locale);
+    method public java.util.List<java.lang.String> getFormats(java.lang.String);
+    method public static java.util.ResourceBundle.Control getNoFallbackControl(java.util.List<java.lang.String>);
+    method public long getTimeToLive(java.lang.String, java.util.Locale);
+    method public boolean needsReload(java.lang.String, java.util.Locale, java.lang.String, java.lang.ClassLoader, java.util.ResourceBundle, long);
+    method public java.util.ResourceBundle newBundle(java.lang.String, java.util.Locale, java.lang.String, java.lang.ClassLoader, boolean) throws java.io.IOException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public java.lang.String toBundleName(java.lang.String, java.util.Locale);
+    method public final java.lang.String toResourceName(java.lang.String, java.lang.String);
+    field public static final java.util.List FORMAT_CLASS;
+    field public static final java.util.List FORMAT_DEFAULT;
+    field public static final java.util.List FORMAT_PROPERTIES;
+    field public static final long TTL_DONT_CACHE = -1L; // 0xffffffffffffffffL
+    field public static final long TTL_NO_EXPIRATION_CONTROL = -2L; // 0xfffffffffffffffeL
+  }
+
+  public final class Scanner implements java.util.Iterator {
+    ctor public Scanner(java.io.File) throws java.io.FileNotFoundException;
+    ctor public Scanner(java.io.File, java.lang.String) throws java.io.FileNotFoundException;
+    ctor public Scanner(java.lang.String);
+    ctor public Scanner(java.io.InputStream);
+    ctor public Scanner(java.io.InputStream, java.lang.String);
+    ctor public Scanner(java.lang.Readable);
+    ctor public Scanner(java.nio.channels.ReadableByteChannel);
+    ctor public Scanner(java.nio.channels.ReadableByteChannel, java.lang.String);
+    method public void close();
+    method public java.util.regex.Pattern delimiter();
+    method public java.lang.String findInLine(java.util.regex.Pattern);
+    method public java.lang.String findInLine(java.lang.String);
+    method public java.lang.String findWithinHorizon(java.util.regex.Pattern, int);
+    method public java.lang.String findWithinHorizon(java.lang.String, int);
+    method public boolean hasNext();
+    method public boolean hasNext(java.util.regex.Pattern);
+    method public boolean hasNext(java.lang.String);
+    method public boolean hasNextBigDecimal();
+    method public boolean hasNextBigInteger();
+    method public boolean hasNextBigInteger(int);
+    method public boolean hasNextBoolean();
+    method public boolean hasNextByte();
+    method public boolean hasNextByte(int);
+    method public boolean hasNextDouble();
+    method public boolean hasNextFloat();
+    method public boolean hasNextInt();
+    method public boolean hasNextInt(int);
+    method public boolean hasNextLine();
+    method public boolean hasNextLong();
+    method public boolean hasNextLong(int);
+    method public boolean hasNextShort();
+    method public boolean hasNextShort(int);
+    method public java.io.IOException ioException();
+    method public java.util.Locale locale();
+    method public java.util.regex.MatchResult match();
+    method public java.lang.String next();
+    method public java.lang.String next(java.util.regex.Pattern);
+    method public java.lang.String next(java.lang.String);
+    method public java.math.BigDecimal nextBigDecimal();
+    method public java.math.BigInteger nextBigInteger();
+    method public java.math.BigInteger nextBigInteger(int);
+    method public boolean nextBoolean();
+    method public byte nextByte();
+    method public byte nextByte(int);
+    method public double nextDouble();
+    method public float nextFloat();
+    method public int nextInt();
+    method public int nextInt(int);
+    method public java.lang.String nextLine();
+    method public long nextLong();
+    method public long nextLong(int);
+    method public short nextShort();
+    method public short nextShort(int);
+    method public int radix();
+    method public void remove();
+    method public java.util.Scanner reset();
+    method public java.util.Scanner skip(java.util.regex.Pattern);
+    method public java.util.Scanner skip(java.lang.String);
+    method public java.util.Scanner useDelimiter(java.util.regex.Pattern);
+    method public java.util.Scanner useDelimiter(java.lang.String);
+    method public java.util.Scanner useLocale(java.util.Locale);
+    method public java.util.Scanner useRadix(int);
+  }
+
+  public class ServiceConfigurationError extends java.lang.Error {
+    ctor public ServiceConfigurationError(java.lang.String);
+    ctor public ServiceConfigurationError(java.lang.String, java.lang.Throwable);
+  }
+
+  public final class ServiceLoader implements java.lang.Iterable {
+    method public java.util.Iterator<S> iterator();
+    method public static java.util.ServiceLoader<S> load(java.lang.Class<S>, java.lang.ClassLoader);
+    method public static java.util.ServiceLoader<S> load(java.lang.Class<S>);
+    method public static java.util.ServiceLoader<S> loadInstalled(java.lang.Class<S>);
+    method public void reload();
+  }
+
+  public abstract interface Set implements java.util.Collection {
+    method public abstract boolean add(E);
+    method public abstract boolean addAll(java.util.Collection<? extends E>);
+    method public abstract void clear();
+    method public abstract boolean contains(java.lang.Object);
+    method public abstract boolean containsAll(java.util.Collection<?>);
+    method public abstract boolean equals(java.lang.Object);
+    method public abstract int hashCode();
+    method public abstract boolean isEmpty();
+    method public abstract java.util.Iterator<E> iterator();
+    method public abstract boolean remove(java.lang.Object);
+    method public abstract boolean removeAll(java.util.Collection<?>);
+    method public abstract boolean retainAll(java.util.Collection<?>);
+    method public abstract int size();
+    method public abstract java.lang.Object[] toArray();
+    method public abstract T[] toArray(T[]);
+  }
+
+  public class SimpleTimeZone extends java.util.TimeZone {
+    ctor public SimpleTimeZone(int, java.lang.String);
+    ctor public SimpleTimeZone(int, java.lang.String, int, int, int, int, int, int, int, int);
+    ctor public SimpleTimeZone(int, java.lang.String, int, int, int, int, int, int, int, int, int);
+    ctor public SimpleTimeZone(int, java.lang.String, int, int, int, int, int, int, int, int, int, int, int);
+    method public int getOffset(int, int, int, int, int, int);
+    method public int getRawOffset();
+    method public boolean inDaylightTime(java.util.Date);
+    method public void setDSTSavings(int);
+    method public void setEndRule(int, int, int);
+    method public void setEndRule(int, int, int, int);
+    method public void setEndRule(int, int, int, int, boolean);
+    method public void setRawOffset(int);
+    method public void setStartRule(int, int, int);
+    method public void setStartRule(int, int, int, int);
+    method public void setStartRule(int, int, int, int, boolean);
+    method public void setStartYear(int);
+    method public boolean useDaylightTime();
+    field public static final int STANDARD_TIME = 1; // 0x1
+    field public static final int UTC_TIME = 2; // 0x2
+    field public static final int WALL_TIME = 0; // 0x0
+  }
+
+  public abstract interface SortedMap implements java.util.Map {
+    method public abstract java.util.Comparator<? super K> comparator();
+    method public abstract K firstKey();
+    method public abstract java.util.SortedMap<K, V> headMap(K);
+    method public abstract K lastKey();
+    method public abstract java.util.SortedMap<K, V> subMap(K, K);
+    method public abstract java.util.SortedMap<K, V> tailMap(K);
+  }
+
+  public abstract interface SortedSet implements java.util.Set {
+    method public abstract java.util.Comparator<? super E> comparator();
+    method public abstract E first();
+    method public abstract java.util.SortedSet<E> headSet(E);
+    method public abstract E last();
+    method public abstract java.util.SortedSet<E> subSet(E, E);
+    method public abstract java.util.SortedSet<E> tailSet(E);
+  }
+
+  public class Stack extends java.util.Vector {
+    ctor public Stack();
+    method public boolean empty();
+    method public synchronized E peek();
+    method public synchronized E pop();
+    method public E push(E);
+    method public synchronized int search(java.lang.Object);
+  }
+
+  public class StringTokenizer implements java.util.Enumeration {
+    ctor public StringTokenizer(java.lang.String);
+    ctor public StringTokenizer(java.lang.String, java.lang.String);
+    ctor public StringTokenizer(java.lang.String, java.lang.String, boolean);
+    method public int countTokens();
+    method public boolean hasMoreElements();
+    method public boolean hasMoreTokens();
+    method public java.lang.Object nextElement();
+    method public java.lang.String nextToken();
+    method public java.lang.String nextToken(java.lang.String);
+  }
+
+  public abstract class TimeZone implements java.lang.Cloneable java.io.Serializable {
+    ctor public TimeZone();
+    method public java.lang.Object clone();
+    method public static synchronized java.lang.String[] getAvailableIDs();
+    method public static synchronized java.lang.String[] getAvailableIDs(int);
+    method public int getDSTSavings();
+    method public static synchronized java.util.TimeZone getDefault();
+    method public final java.lang.String getDisplayName();
+    method public final java.lang.String getDisplayName(java.util.Locale);
+    method public final java.lang.String getDisplayName(boolean, int);
+    method public java.lang.String getDisplayName(boolean, int, java.util.Locale);
+    method public java.lang.String getID();
+    method public int getOffset(long);
+    method public abstract int getOffset(int, int, int, int, int, int);
+    method public abstract int getRawOffset();
+    method public static synchronized java.util.TimeZone getTimeZone(java.lang.String);
+    method public boolean hasSameRules(java.util.TimeZone);
+    method public abstract boolean inDaylightTime(java.util.Date);
+    method public static synchronized void setDefault(java.util.TimeZone);
+    method public void setID(java.lang.String);
+    method public abstract void setRawOffset(int);
+    method public abstract boolean useDaylightTime();
+    field public static final int LONG = 1; // 0x1
+    field public static final int SHORT = 0; // 0x0
+  }
+
+  public class Timer {
+    ctor public Timer(java.lang.String, boolean);
+    ctor public Timer(java.lang.String);
+    ctor public Timer(boolean);
+    ctor public Timer();
+    method public void cancel();
+    method public int purge();
+    method public void schedule(java.util.TimerTask, java.util.Date);
+    method public void schedule(java.util.TimerTask, long);
+    method public void schedule(java.util.TimerTask, long, long);
+    method public void schedule(java.util.TimerTask, java.util.Date, long);
+    method public void scheduleAtFixedRate(java.util.TimerTask, long, long);
+    method public void scheduleAtFixedRate(java.util.TimerTask, java.util.Date, long);
+  }
+
+  public abstract class TimerTask implements java.lang.Runnable {
+    ctor protected TimerTask();
+    method public boolean cancel();
+    method public abstract void run();
+    method public long scheduledExecutionTime();
+  }
+
+  public class TooManyListenersException extends java.lang.Exception {
+    ctor public TooManyListenersException();
+    ctor public TooManyListenersException(java.lang.String);
+  }
+
+  public class TreeMap extends java.util.AbstractMap implements java.lang.Cloneable java.util.NavigableMap java.io.Serializable java.util.SortedMap {
+    ctor public TreeMap();
+    ctor public TreeMap(java.util.Map<? extends K, ? extends V>);
+    ctor public TreeMap(java.util.Comparator<? super K>);
+    ctor public TreeMap(java.util.SortedMap<K, ? extends V>);
+    method public java.util.Map.Entry<K, V> ceilingEntry(K);
+    method public K ceilingKey(K);
+    method public java.lang.Object clone();
+    method public java.util.Comparator<? super K> comparator();
+    method public java.util.NavigableSet<K> descendingKeySet();
+    method public java.util.NavigableMap<K, V> descendingMap();
+    method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public java.util.Map.Entry<K, V> firstEntry();
+    method public K firstKey();
+    method public java.util.Map.Entry<K, V> floorEntry(K);
+    method public K floorKey(K);
+    method public java.util.NavigableMap<K, V> headMap(K, boolean);
+    method public java.util.SortedMap<K, V> headMap(K);
+    method public java.util.Map.Entry<K, V> higherEntry(K);
+    method public K higherKey(K);
+    method public java.util.Map.Entry<K, V> lastEntry();
+    method public K lastKey();
+    method public java.util.Map.Entry<K, V> lowerEntry(K);
+    method public K lowerKey(K);
+    method public java.util.NavigableSet<K> navigableKeySet();
+    method public java.util.Map.Entry<K, V> pollFirstEntry();
+    method public java.util.Map.Entry<K, V> pollLastEntry();
+    method public java.util.NavigableMap<K, V> subMap(K, boolean, K, boolean);
+    method public java.util.SortedMap<K, V> subMap(K, K);
+    method public java.util.NavigableMap<K, V> tailMap(K, boolean);
+    method public java.util.SortedMap<K, V> tailMap(K);
+  }
+
+  public class TreeSet extends java.util.AbstractSet implements java.lang.Cloneable java.util.NavigableSet java.io.Serializable {
+    ctor public TreeSet();
+    ctor public TreeSet(java.util.Collection<? extends E>);
+    ctor public TreeSet(java.util.Comparator<? super E>);
+    ctor public TreeSet(java.util.SortedSet<E>);
+    method public E ceiling(E);
+    method public java.lang.Object clone();
+    method public java.util.Comparator<? super E> comparator();
+    method public java.util.Iterator<E> descendingIterator();
+    method public java.util.NavigableSet<E> descendingSet();
+    method public E first();
+    method public E floor(E);
+    method public java.util.NavigableSet<E> headSet(E, boolean);
+    method public java.util.SortedSet<E> headSet(E);
+    method public E higher(E);
+    method public java.util.Iterator<E> iterator();
+    method public E last();
+    method public E lower(E);
+    method public E pollFirst();
+    method public E pollLast();
+    method public int size();
+    method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean);
+    method public java.util.SortedSet<E> subSet(E, E);
+    method public java.util.NavigableSet<E> tailSet(E, boolean);
+    method public java.util.SortedSet<E> tailSet(E);
+  }
+
+  public final class UUID implements java.lang.Comparable java.io.Serializable {
+    ctor public UUID(long, long);
+    method public int clockSequence();
+    method public int compareTo(java.util.UUID);
+    method public static java.util.UUID fromString(java.lang.String);
+    method public long getLeastSignificantBits();
+    method public long getMostSignificantBits();
+    method public static java.util.UUID nameUUIDFromBytes(byte[]);
+    method public long node();
+    method public static java.util.UUID randomUUID();
+    method public long timestamp();
+    method public int variant();
+    method public int version();
+  }
+
+  public class UnknownFormatConversionException extends java.util.IllegalFormatException {
+    ctor public UnknownFormatConversionException(java.lang.String);
+    method public java.lang.String getConversion();
+  }
+
+  public class UnknownFormatFlagsException extends java.util.IllegalFormatException {
+    ctor public UnknownFormatFlagsException(java.lang.String);
+    method public java.lang.String getFlags();
+  }
+
+  public class Vector extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
+    ctor public Vector();
+    ctor public Vector(int);
+    ctor public Vector(int, int);
+    ctor public Vector(java.util.Collection<? extends E>);
+    method public synchronized void addElement(E);
+    method public synchronized int capacity();
+    method public synchronized java.lang.Object clone();
+    method public synchronized void copyInto(java.lang.Object[]);
+    method public synchronized E elementAt(int);
+    method public java.util.Enumeration<E> elements();
+    method public synchronized void ensureCapacity(int);
+    method public synchronized E firstElement();
+    method public E get(int);
+    method public synchronized int indexOf(java.lang.Object, int);
+    method public synchronized void insertElementAt(E, int);
+    method public synchronized E lastElement();
+    method public synchronized int lastIndexOf(java.lang.Object, int);
+    method public synchronized void removeAllElements();
+    method public synchronized boolean removeElement(java.lang.Object);
+    method public synchronized void removeElementAt(int);
+    method public synchronized void setElementAt(E, int);
+    method public synchronized void setSize(int);
+    method public synchronized int size();
+    method public synchronized void trimToSize();
+    field protected int capacityIncrement;
+    field protected int elementCount;
+    field protected java.lang.Object[] elementData;
+  }
+
+  public class WeakHashMap extends java.util.AbstractMap implements java.util.Map {
+    ctor public WeakHashMap();
+    ctor public WeakHashMap(int);
+    ctor public WeakHashMap(int, float);
+    ctor public WeakHashMap(java.util.Map<? extends K, ? extends V>);
+    method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+  }
+
+}
+
+package java.util.concurrent {
+
+  public abstract class AbstractExecutorService implements java.util.concurrent.ExecutorService {
+    ctor public AbstractExecutorService();
+    method public java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.lang.InterruptedException;
+    method public java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method protected java.util.concurrent.RunnableFuture<T> newTaskFor(java.lang.Runnable, T);
+    method protected java.util.concurrent.RunnableFuture<T> newTaskFor(java.util.concurrent.Callable<T>);
+    method public java.util.concurrent.Future<?> submit(java.lang.Runnable);
+    method public java.util.concurrent.Future<T> submit(java.lang.Runnable, T);
+    method public java.util.concurrent.Future<T> submit(java.util.concurrent.Callable<T>);
+  }
+
+  public class ArrayBlockingQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
+    ctor public ArrayBlockingQueue(int);
+    ctor public ArrayBlockingQueue(int, boolean);
+    ctor public ArrayBlockingQueue(int, boolean, java.util.Collection<? extends E>);
+    method public int drainTo(java.util.Collection<? super E>);
+    method public int drainTo(java.util.Collection<? super E>, int);
+    method public java.util.Iterator<E> iterator();
+    method public boolean offer(E);
+    method public boolean offer(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public E peek();
+    method public E poll();
+    method public E poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public void put(E) throws java.lang.InterruptedException;
+    method public int remainingCapacity();
+    method public int size();
+    method public E take() throws java.lang.InterruptedException;
+  }
+
+  public abstract interface BlockingDeque implements java.util.concurrent.BlockingQueue java.util.Deque {
+    method public abstract boolean add(E);
+    method public abstract void addFirst(E);
+    method public abstract void addLast(E);
+    method public abstract boolean contains(java.lang.Object);
+    method public abstract E element();
+    method public abstract java.util.Iterator<E> iterator();
+    method public abstract boolean offer(E);
+    method public abstract boolean offer(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public abstract boolean offerFirst(E);
+    method public abstract boolean offerFirst(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public abstract boolean offerLast(E);
+    method public abstract boolean offerLast(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public abstract E peek();
+    method public abstract E poll();
+    method public abstract E poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public abstract E pollFirst(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public abstract E pollLast(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public abstract void push(E);
+    method public abstract void put(E) throws java.lang.InterruptedException;
+    method public abstract void putFirst(E) throws java.lang.InterruptedException;
+    method public abstract void putLast(E) throws java.lang.InterruptedException;
+    method public abstract E remove();
+    method public abstract boolean remove(java.lang.Object);
+    method public abstract boolean removeFirstOccurrence(java.lang.Object);
+    method public abstract boolean removeLastOccurrence(java.lang.Object);
+    method public abstract int size();
+    method public abstract E take() throws java.lang.InterruptedException;
+    method public abstract E takeFirst() throws java.lang.InterruptedException;
+    method public abstract E takeLast() throws java.lang.InterruptedException;
+  }
+
+  public abstract interface BlockingQueue implements java.util.Queue {
+    method public abstract boolean add(E);
+    method public abstract boolean contains(java.lang.Object);
+    method public abstract int drainTo(java.util.Collection<? super E>);
+    method public abstract int drainTo(java.util.Collection<? super E>, int);
+    method public abstract boolean offer(E);
+    method public abstract boolean offer(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public abstract E poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public abstract void put(E) throws java.lang.InterruptedException;
+    method public abstract int remainingCapacity();
+    method public abstract boolean remove(java.lang.Object);
+    method public abstract E take() throws java.lang.InterruptedException;
+  }
+
+  public class BrokenBarrierException extends java.lang.Exception {
+    ctor public BrokenBarrierException();
+    ctor public BrokenBarrierException(java.lang.String);
+  }
+
+  public abstract interface Callable {
+    method public abstract V call() throws java.lang.Exception;
+  }
+
+  public class CancellationException extends java.lang.IllegalStateException {
+    ctor public CancellationException();
+    ctor public CancellationException(java.lang.String);
+  }
+
+  public abstract interface CompletionService {
+    method public abstract java.util.concurrent.Future<V> poll();
+    method public abstract java.util.concurrent.Future<V> poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public abstract java.util.concurrent.Future<V> submit(java.util.concurrent.Callable<V>);
+    method public abstract java.util.concurrent.Future<V> submit(java.lang.Runnable, V);
+    method public abstract java.util.concurrent.Future<V> take() throws java.lang.InterruptedException;
+  }
+
+  public class ConcurrentHashMap extends java.util.AbstractMap implements java.util.concurrent.ConcurrentMap java.io.Serializable {
+    ctor public ConcurrentHashMap(int, float, int);
+    ctor public ConcurrentHashMap(int, float);
+    ctor public ConcurrentHashMap(int);
+    ctor public ConcurrentHashMap();
+    ctor public ConcurrentHashMap(java.util.Map<? extends K, ? extends V>);
+    method public boolean contains(java.lang.Object);
+    method public java.util.Enumeration<V> elements();
+    method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public java.util.Enumeration<K> keys();
+    method public V putIfAbsent(K, V);
+    method public boolean remove(java.lang.Object, java.lang.Object);
+    method public boolean replace(K, V, V);
+    method public V replace(K, V);
+  }
+
+  public class ConcurrentLinkedQueue extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable {
+    ctor public ConcurrentLinkedQueue();
+    ctor public ConcurrentLinkedQueue(java.util.Collection<? extends E>);
+    method public java.util.Iterator<E> iterator();
+    method public boolean offer(E);
+    method public E peek();
+    method public E poll();
+    method public int size();
+  }
+
+  public abstract interface ConcurrentMap implements java.util.Map {
+    method public abstract V putIfAbsent(K, V);
+    method public abstract boolean remove(java.lang.Object, java.lang.Object);
+    method public abstract boolean replace(K, V, V);
+    method public abstract V replace(K, V);
+  }
+
+  public abstract interface ConcurrentNavigableMap implements java.util.concurrent.ConcurrentMap java.util.NavigableMap {
+    method public abstract java.util.NavigableSet<K> descendingKeySet();
+    method public abstract java.util.concurrent.ConcurrentNavigableMap<K, V> descendingMap();
+    method public abstract java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K, boolean);
+    method public abstract java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K);
+    method public abstract java.util.NavigableSet<K> keySet();
+    method public abstract java.util.NavigableSet<K> navigableKeySet();
+    method public abstract java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, boolean, K, boolean);
+    method public abstract java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, K);
+    method public abstract java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K, boolean);
+    method public abstract java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K);
+  }
+
+  public class ConcurrentSkipListMap extends java.util.AbstractMap implements java.lang.Cloneable java.util.concurrent.ConcurrentNavigableMap java.io.Serializable {
+    ctor public ConcurrentSkipListMap();
+    ctor public ConcurrentSkipListMap(java.util.Comparator<? super K>);
+    ctor public ConcurrentSkipListMap(java.util.Map<? extends K, ? extends V>);
+    ctor public ConcurrentSkipListMap(java.util.SortedMap<K, ? extends V>);
+    method public java.util.Map.Entry<K, V> ceilingEntry(K);
+    method public K ceilingKey(K);
+    method public java.util.concurrent.ConcurrentSkipListMap<K, V> clone();
+    method public java.util.Comparator<? super K> comparator();
+    method public java.util.NavigableSet<K> descendingKeySet();
+    method public java.util.concurrent.ConcurrentNavigableMap<K, V> descendingMap();
+    method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public java.util.Map.Entry<K, V> firstEntry();
+    method public K firstKey();
+    method public java.util.Map.Entry<K, V> floorEntry(K);
+    method public K floorKey(K);
+    method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K, boolean);
+    method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K);
+    method public java.util.Map.Entry<K, V> higherEntry(K);
+    method public K higherKey(K);
+    method public java.util.Map.Entry<K, V> lastEntry();
+    method public K lastKey();
+    method public java.util.Map.Entry<K, V> lowerEntry(K);
+    method public K lowerKey(K);
+    method public java.util.NavigableSet<K> navigableKeySet();
+    method public java.util.Map.Entry<K, V> pollFirstEntry();
+    method public java.util.Map.Entry<K, V> pollLastEntry();
+    method public V putIfAbsent(K, V);
+    method public boolean remove(java.lang.Object, java.lang.Object);
+    method public boolean replace(K, V, V);
+    method public V replace(K, V);
+    method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, boolean, K, boolean);
+    method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, K);
+    method public java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K, boolean);
+    method public java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K);
+  }
+
+  public class ConcurrentSkipListSet extends java.util.AbstractSet implements java.lang.Cloneable java.util.NavigableSet java.io.Serializable {
+    ctor public ConcurrentSkipListSet();
+    ctor public ConcurrentSkipListSet(java.util.Comparator<? super E>);
+    ctor public ConcurrentSkipListSet(java.util.Collection<? extends E>);
+    ctor public ConcurrentSkipListSet(java.util.SortedSet<E>);
+    method public E ceiling(E);
+    method public java.util.concurrent.ConcurrentSkipListSet<E> clone();
+    method public java.util.Comparator<? super E> comparator();
+    method public java.util.Iterator<E> descendingIterator();
+    method public java.util.NavigableSet<E> descendingSet();
+    method public E first();
+    method public E floor(E);
+    method public java.util.NavigableSet<E> headSet(E, boolean);
+    method public java.util.NavigableSet<E> headSet(E);
+    method public E higher(E);
+    method public java.util.Iterator<E> iterator();
+    method public E last();
+    method public E lower(E);
+    method public E pollFirst();
+    method public E pollLast();
+    method public int size();
+    method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean);
+    method public java.util.NavigableSet<E> subSet(E, E);
+    method public java.util.NavigableSet<E> tailSet(E, boolean);
+    method public java.util.NavigableSet<E> tailSet(E);
+  }
+
+  public class CopyOnWriteArrayList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
+    ctor public CopyOnWriteArrayList();
+    ctor public CopyOnWriteArrayList(java.util.Collection<? extends E>);
+    ctor public CopyOnWriteArrayList(E[]);
+    method public synchronized boolean add(E);
+    method public synchronized void add(int, E);
+    method public synchronized boolean addAll(java.util.Collection<? extends E>);
+    method public synchronized boolean addAll(int, java.util.Collection<? extends E>);
+    method public synchronized int addAllAbsent(java.util.Collection<? extends E>);
+    method public synchronized boolean addIfAbsent(E);
+    method public synchronized void clear();
+    method public java.lang.Object clone();
+    method public boolean contains(java.lang.Object);
+    method public boolean containsAll(java.util.Collection<?>);
+    method public E get(int);
+    method public int indexOf(E, int);
+    method public int indexOf(java.lang.Object);
+    method public boolean isEmpty();
+    method public java.util.Iterator<E> iterator();
+    method public int lastIndexOf(E, int);
+    method public int lastIndexOf(java.lang.Object);
+    method public java.util.ListIterator<E> listIterator(int);
+    method public java.util.ListIterator<E> listIterator();
+    method public synchronized E remove(int);
+    method public synchronized boolean remove(java.lang.Object);
+    method public synchronized boolean removeAll(java.util.Collection<?>);
+    method public synchronized boolean retainAll(java.util.Collection<?>);
+    method public synchronized E set(int, E);
+    method public int size();
+    method public java.util.List<E> subList(int, int);
+    method public java.lang.Object[] toArray();
+    method public T[] toArray(T[]);
+  }
+
+  public class CopyOnWriteArraySet extends java.util.AbstractSet implements java.io.Serializable {
+    ctor public CopyOnWriteArraySet();
+    ctor public CopyOnWriteArraySet(java.util.Collection<? extends E>);
+    method public java.util.Iterator<E> iterator();
+    method public int size();
+  }
+
+  public class CountDownLatch {
+    ctor public CountDownLatch(int);
+    method public void await() throws java.lang.InterruptedException;
+    method public boolean await(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public void countDown();
+    method public long getCount();
+  }
+
+  public class CyclicBarrier {
+    ctor public CyclicBarrier(int, java.lang.Runnable);
+    ctor public CyclicBarrier(int);
+    method public int await() throws java.util.concurrent.BrokenBarrierException, java.lang.InterruptedException;
+    method public int await(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.BrokenBarrierException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method public int getNumberWaiting();
+    method public int getParties();
+    method public boolean isBroken();
+    method public void reset();
+  }
+
+  public class DelayQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue {
+    ctor public DelayQueue();
+    ctor public DelayQueue(java.util.Collection<? extends E>);
+    method public int drainTo(java.util.Collection<? super E>);
+    method public int drainTo(java.util.Collection<? super E>, int);
+    method public java.util.Iterator<E> iterator();
+    method public boolean offer(E);
+    method public boolean offer(E, long, java.util.concurrent.TimeUnit);
+    method public E peek();
+    method public E poll();
+    method public E poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public void put(E);
+    method public int remainingCapacity();
+    method public int size();
+    method public E take() throws java.lang.InterruptedException;
+  }
+
+  public abstract interface Delayed implements java.lang.Comparable {
+    method public abstract long getDelay(java.util.concurrent.TimeUnit);
+  }
+
+  public class Exchanger {
+    ctor public Exchanger();
+    method public V exchange(V) throws java.lang.InterruptedException;
+    method public V exchange(V, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+  }
+
+  public class ExecutionException extends java.lang.Exception {
+    ctor protected ExecutionException();
+    ctor protected ExecutionException(java.lang.String);
+    ctor public ExecutionException(java.lang.String, java.lang.Throwable);
+    ctor public ExecutionException(java.lang.Throwable);
+  }
+
+  public abstract interface Executor {
+    method public abstract void execute(java.lang.Runnable);
+  }
+
+  public class ExecutorCompletionService implements java.util.concurrent.CompletionService {
+    ctor public ExecutorCompletionService(java.util.concurrent.Executor);
+    ctor public ExecutorCompletionService(java.util.concurrent.Executor, java.util.concurrent.BlockingQueue<java.util.concurrent.Future<V>>);
+    method public java.util.concurrent.Future<V> poll();
+    method public java.util.concurrent.Future<V> poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public java.util.concurrent.Future<V> submit(java.util.concurrent.Callable<V>);
+    method public java.util.concurrent.Future<V> submit(java.lang.Runnable, V);
+    method public java.util.concurrent.Future<V> take() throws java.lang.InterruptedException;
+  }
+
+  public abstract interface ExecutorService implements java.util.concurrent.Executor {
+    method public abstract boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public abstract java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.lang.InterruptedException;
+    method public abstract java.util.List<java.util.concurrent.Future<T>> invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public abstract T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public abstract T invokeAny(java.util.Collection<? extends java.util.concurrent.Callable<T>>, long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method public abstract boolean isShutdown();
+    method public abstract boolean isTerminated();
+    method public abstract void shutdown();
+    method public abstract java.util.List<java.lang.Runnable> shutdownNow();
+    method public abstract java.util.concurrent.Future<T> submit(java.util.concurrent.Callable<T>);
+    method public abstract java.util.concurrent.Future<T> submit(java.lang.Runnable, T);
+    method public abstract java.util.concurrent.Future<?> submit(java.lang.Runnable);
+  }
+
+  public class Executors {
+    method public static java.util.concurrent.Callable<T> callable(java.lang.Runnable, T);
+    method public static java.util.concurrent.Callable<java.lang.Object> callable(java.lang.Runnable);
+    method public static java.util.concurrent.Callable<java.lang.Object> callable(java.security.PrivilegedAction<?>);
+    method public static java.util.concurrent.Callable<java.lang.Object> callable(java.security.PrivilegedExceptionAction<?>);
+    method public static java.util.concurrent.ThreadFactory defaultThreadFactory();
+    method public static java.util.concurrent.ExecutorService newCachedThreadPool();
+    method public static java.util.concurrent.ExecutorService newCachedThreadPool(java.util.concurrent.ThreadFactory);
+    method public static java.util.concurrent.ExecutorService newFixedThreadPool(int);
+    method public static java.util.concurrent.ExecutorService newFixedThreadPool(int, java.util.concurrent.ThreadFactory);
+    method public static java.util.concurrent.ScheduledExecutorService newScheduledThreadPool(int);
+    method public static java.util.concurrent.ScheduledExecutorService newScheduledThreadPool(int, java.util.concurrent.ThreadFactory);
+    method public static java.util.concurrent.ExecutorService newSingleThreadExecutor();
+    method public static java.util.concurrent.ExecutorService newSingleThreadExecutor(java.util.concurrent.ThreadFactory);
+    method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor();
+    method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory);
+    method public static java.util.concurrent.Callable<T> privilegedCallable(java.util.concurrent.Callable<T>);
+    method public static java.util.concurrent.Callable<T> privilegedCallableUsingCurrentClassLoader(java.util.concurrent.Callable<T>);
+    method public static java.util.concurrent.ThreadFactory privilegedThreadFactory();
+    method public static java.util.concurrent.ExecutorService unconfigurableExecutorService(java.util.concurrent.ExecutorService);
+    method public static java.util.concurrent.ScheduledExecutorService unconfigurableScheduledExecutorService(java.util.concurrent.ScheduledExecutorService);
+  }
+
+  public abstract interface Future {
+    method public abstract boolean cancel(boolean);
+    method public abstract V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public abstract V get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method public abstract boolean isCancelled();
+    method public abstract boolean isDone();
+  }
+
+  public class FutureTask implements java.util.concurrent.RunnableFuture {
+    ctor public FutureTask(java.util.concurrent.Callable<V>);
+    ctor public FutureTask(java.lang.Runnable, V);
+    method public boolean cancel(boolean);
+    method protected void done();
+    method public V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public V get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method public boolean isCancelled();
+    method public boolean isDone();
+    method public void run();
+    method protected boolean runAndReset();
+    method protected void set(V);
+    method protected void setException(java.lang.Throwable);
+  }
+
+  public class LinkedBlockingDeque extends java.util.AbstractQueue implements java.util.concurrent.BlockingDeque java.io.Serializable {
+    ctor public LinkedBlockingDeque();
+    ctor public LinkedBlockingDeque(int);
+    ctor public LinkedBlockingDeque(java.util.Collection<? extends E>);
+    method public void addFirst(E);
+    method public void addLast(E);
+    method public java.util.Iterator<E> descendingIterator();
+    method public int drainTo(java.util.Collection<? super E>);
+    method public int drainTo(java.util.Collection<? super E>, int);
+    method public E getFirst();
+    method public E getLast();
+    method public java.util.Iterator<E> iterator();
+    method public boolean offer(E);
+    method public boolean offer(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public boolean offerFirst(E);
+    method public boolean offerFirst(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public boolean offerLast(E);
+    method public boolean offerLast(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public E peek();
+    method public E peekFirst();
+    method public E peekLast();
+    method public E poll();
+    method public E poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public E pollFirst();
+    method public E pollFirst(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public E pollLast();
+    method public E pollLast(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public E pop();
+    method public void push(E);
+    method public void put(E) throws java.lang.InterruptedException;
+    method public void putFirst(E) throws java.lang.InterruptedException;
+    method public void putLast(E) throws java.lang.InterruptedException;
+    method public int remainingCapacity();
+    method public E removeFirst();
+    method public boolean removeFirstOccurrence(java.lang.Object);
+    method public E removeLast();
+    method public boolean removeLastOccurrence(java.lang.Object);
+    method public int size();
+    method public E take() throws java.lang.InterruptedException;
+    method public E takeFirst() throws java.lang.InterruptedException;
+    method public E takeLast() throws java.lang.InterruptedException;
+  }
+
+  public class LinkedBlockingQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
+    ctor public LinkedBlockingQueue();
+    ctor public LinkedBlockingQueue(int);
+    ctor public LinkedBlockingQueue(java.util.Collection<? extends E>);
+    method public int drainTo(java.util.Collection<? super E>);
+    method public int drainTo(java.util.Collection<? super E>, int);
+    method public java.util.Iterator<E> iterator();
+    method public boolean offer(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public boolean offer(E);
+    method public E peek();
+    method public E poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public E poll();
+    method public void put(E) throws java.lang.InterruptedException;
+    method public int remainingCapacity();
+    method public int size();
+    method public E take() throws java.lang.InterruptedException;
+  }
+
+  public class PriorityBlockingQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
+    ctor public PriorityBlockingQueue();
+    ctor public PriorityBlockingQueue(int);
+    ctor public PriorityBlockingQueue(int, java.util.Comparator<? super E>);
+    ctor public PriorityBlockingQueue(java.util.Collection<? extends E>);
+    method public java.util.Comparator<? super E> comparator();
+    method public int drainTo(java.util.Collection<? super E>);
+    method public int drainTo(java.util.Collection<? super E>, int);
+    method public java.util.Iterator<E> iterator();
+    method public boolean offer(E);
+    method public boolean offer(E, long, java.util.concurrent.TimeUnit);
+    method public E peek();
+    method public E poll();
+    method public E poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public void put(E);
+    method public int remainingCapacity();
+    method public int size();
+    method public E take() throws java.lang.InterruptedException;
+  }
+
+  public class RejectedExecutionException extends java.lang.RuntimeException {
+    ctor public RejectedExecutionException();
+    ctor public RejectedExecutionException(java.lang.String);
+    ctor public RejectedExecutionException(java.lang.String, java.lang.Throwable);
+    ctor public RejectedExecutionException(java.lang.Throwable);
+  }
+
+  public abstract interface RejectedExecutionHandler {
+    method public abstract void rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor);
+  }
+
+  public abstract interface RunnableFuture implements java.util.concurrent.Future java.lang.Runnable {
+    method public abstract void run();
+  }
+
+  public abstract interface RunnableScheduledFuture implements java.util.concurrent.RunnableFuture java.util.concurrent.ScheduledFuture {
+    method public abstract boolean isPeriodic();
+  }
+
+  public abstract interface ScheduledExecutorService implements java.util.concurrent.ExecutorService {
+    method public abstract java.util.concurrent.ScheduledFuture<?> schedule(java.lang.Runnable, long, java.util.concurrent.TimeUnit);
+    method public abstract java.util.concurrent.ScheduledFuture<V> schedule(java.util.concurrent.Callable<V>, long, java.util.concurrent.TimeUnit);
+    method public abstract java.util.concurrent.ScheduledFuture<?> scheduleAtFixedRate(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
+    method public abstract java.util.concurrent.ScheduledFuture<?> scheduleWithFixedDelay(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
+  }
+
+  public abstract interface ScheduledFuture implements java.util.concurrent.Delayed java.util.concurrent.Future {
+  }
+
+  public class ScheduledThreadPoolExecutor extends java.util.concurrent.ThreadPoolExecutor implements java.util.concurrent.ScheduledExecutorService {
+    ctor public ScheduledThreadPoolExecutor(int);
+    ctor public ScheduledThreadPoolExecutor(int, java.util.concurrent.ThreadFactory);
+    ctor public ScheduledThreadPoolExecutor(int, java.util.concurrent.RejectedExecutionHandler);
+    ctor public ScheduledThreadPoolExecutor(int, java.util.concurrent.ThreadFactory, java.util.concurrent.RejectedExecutionHandler);
+    method protected java.util.concurrent.RunnableScheduledFuture<V> decorateTask(java.lang.Runnable, java.util.concurrent.RunnableScheduledFuture<V>);
+    method protected java.util.concurrent.RunnableScheduledFuture<V> decorateTask(java.util.concurrent.Callable<V>, java.util.concurrent.RunnableScheduledFuture<V>);
+    method public boolean getContinueExistingPeriodicTasksAfterShutdownPolicy();
+    method public boolean getExecuteExistingDelayedTasksAfterShutdownPolicy();
+    method public java.util.concurrent.ScheduledFuture<?> schedule(java.lang.Runnable, long, java.util.concurrent.TimeUnit);
+    method public java.util.concurrent.ScheduledFuture<V> schedule(java.util.concurrent.Callable<V>, long, java.util.concurrent.TimeUnit);
+    method public java.util.concurrent.ScheduledFuture<?> scheduleAtFixedRate(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
+    method public java.util.concurrent.ScheduledFuture<?> scheduleWithFixedDelay(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
+    method public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean);
+    method public void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean);
+  }
+
+  public class Semaphore implements java.io.Serializable {
+    ctor public Semaphore(int);
+    ctor public Semaphore(int, boolean);
+    method public void acquire() throws java.lang.InterruptedException;
+    method public void acquire(int) throws java.lang.InterruptedException;
+    method public void acquireUninterruptibly();
+    method public void acquireUninterruptibly(int);
+    method public int availablePermits();
+    method public int drainPermits();
+    method public final int getQueueLength();
+    method protected java.util.Collection<java.lang.Thread> getQueuedThreads();
+    method public final boolean hasQueuedThreads();
+    method public boolean isFair();
+    method protected void reducePermits(int);
+    method public void release();
+    method public void release(int);
+    method public boolean tryAcquire();
+    method public boolean tryAcquire(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public boolean tryAcquire(int);
+    method public boolean tryAcquire(int, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+  }
+
+  public class SynchronousQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
+    ctor public SynchronousQueue();
+    ctor public SynchronousQueue(boolean);
+    method public int drainTo(java.util.Collection<? super E>);
+    method public int drainTo(java.util.Collection<? super E>, int);
+    method public java.util.Iterator<E> iterator();
+    method public boolean offer(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public boolean offer(E);
+    method public E peek();
+    method public E poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public E poll();
+    method public void put(E) throws java.lang.InterruptedException;
+    method public int remainingCapacity();
+    method public int size();
+    method public E take() throws java.lang.InterruptedException;
+  }
+
+  public abstract interface ThreadFactory {
+    method public abstract java.lang.Thread newThread(java.lang.Runnable);
+  }
+
+  public class ThreadPoolExecutor extends java.util.concurrent.AbstractExecutorService {
+    ctor public ThreadPoolExecutor(int, int, long, java.util.concurrent.TimeUnit, java.util.concurrent.BlockingQueue<java.lang.Runnable>);
+    ctor public ThreadPoolExecutor(int, int, long, java.util.concurrent.TimeUnit, java.util.concurrent.BlockingQueue<java.lang.Runnable>, java.util.concurrent.ThreadFactory);
+    ctor public ThreadPoolExecutor(int, int, long, java.util.concurrent.TimeUnit, java.util.concurrent.BlockingQueue<java.lang.Runnable>, java.util.concurrent.RejectedExecutionHandler);
+    ctor public ThreadPoolExecutor(int, int, long, java.util.concurrent.TimeUnit, java.util.concurrent.BlockingQueue<java.lang.Runnable>, java.util.concurrent.ThreadFactory, java.util.concurrent.RejectedExecutionHandler);
+    method protected void afterExecute(java.lang.Runnable, java.lang.Throwable);
+    method public void allowCoreThreadTimeOut(boolean);
+    method public boolean allowsCoreThreadTimeOut();
+    method public boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method protected void beforeExecute(java.lang.Thread, java.lang.Runnable);
+    method public void execute(java.lang.Runnable);
+    method public int getActiveCount();
+    method public long getCompletedTaskCount();
+    method public int getCorePoolSize();
+    method public long getKeepAliveTime(java.util.concurrent.TimeUnit);
+    method public int getLargestPoolSize();
+    method public int getMaximumPoolSize();
+    method public int getPoolSize();
+    method public java.util.concurrent.BlockingQueue<java.lang.Runnable> getQueue();
+    method public java.util.concurrent.RejectedExecutionHandler getRejectedExecutionHandler();
+    method public long getTaskCount();
+    method public java.util.concurrent.ThreadFactory getThreadFactory();
+    method public boolean isShutdown();
+    method public boolean isTerminated();
+    method public boolean isTerminating();
+    method public int prestartAllCoreThreads();
+    method public boolean prestartCoreThread();
+    method public void purge();
+    method public boolean remove(java.lang.Runnable);
+    method public void setCorePoolSize(int);
+    method public void setKeepAliveTime(long, java.util.concurrent.TimeUnit);
+    method public void setMaximumPoolSize(int);
+    method public void setRejectedExecutionHandler(java.util.concurrent.RejectedExecutionHandler);
+    method public void setThreadFactory(java.util.concurrent.ThreadFactory);
+    method public void shutdown();
+    method public java.util.List<java.lang.Runnable> shutdownNow();
+    method protected void terminated();
+  }
+
+  public static class ThreadPoolExecutor.AbortPolicy implements java.util.concurrent.RejectedExecutionHandler {
+    ctor public ThreadPoolExecutor.AbortPolicy();
+    method public void rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor);
+  }
+
+  public static class ThreadPoolExecutor.CallerRunsPolicy implements java.util.concurrent.RejectedExecutionHandler {
+    ctor public ThreadPoolExecutor.CallerRunsPolicy();
+    method public void rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor);
+  }
+
+  public static class ThreadPoolExecutor.DiscardOldestPolicy implements java.util.concurrent.RejectedExecutionHandler {
+    ctor public ThreadPoolExecutor.DiscardOldestPolicy();
+    method public void rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor);
+  }
+
+  public static class ThreadPoolExecutor.DiscardPolicy implements java.util.concurrent.RejectedExecutionHandler {
+    ctor public ThreadPoolExecutor.DiscardPolicy();
+    method public void rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor);
+  }
+
+  public class TimeUnit extends java.lang.Enum {
+    method public long convert(long, java.util.concurrent.TimeUnit);
+    method public void sleep(long) throws java.lang.InterruptedException;
+    method public void timedJoin(java.lang.Thread, long) throws java.lang.InterruptedException;
+    method public void timedWait(java.lang.Object, long) throws java.lang.InterruptedException;
+    method public long toDays(long);
+    method public long toHours(long);
+    method public long toMicros(long);
+    method public long toMillis(long);
+    method public long toMinutes(long);
+    method public long toNanos(long);
+    method public long toSeconds(long);
+    method public static java.util.concurrent.TimeUnit valueOf(java.lang.String);
+    method public static final java.util.concurrent.TimeUnit[] values();
+    enum_constant public static final java.util.concurrent.TimeUnit DAYS;
+    enum_constant public static final java.util.concurrent.TimeUnit HOURS;
+    enum_constant public static final java.util.concurrent.TimeUnit MICROSECONDS;
+    enum_constant public static final java.util.concurrent.TimeUnit MILLISECONDS;
+    enum_constant public static final java.util.concurrent.TimeUnit MINUTES;
+    enum_constant public static final java.util.concurrent.TimeUnit NANOSECONDS;
+    enum_constant public static final java.util.concurrent.TimeUnit SECONDS;
+  }
+
+  public class TimeoutException extends java.lang.Exception {
+    ctor public TimeoutException();
+    ctor public TimeoutException(java.lang.String);
+  }
+
+}
+
+package java.util.concurrent.atomic {
+
+  public class AtomicBoolean implements java.io.Serializable {
+    ctor public AtomicBoolean(boolean);
+    ctor public AtomicBoolean();
+    method public final boolean compareAndSet(boolean, boolean);
+    method public final boolean get();
+    method public final boolean getAndSet(boolean);
+    method public final void lazySet(boolean);
+    method public final void set(boolean);
+    method public boolean weakCompareAndSet(boolean, boolean);
+  }
+
+  public class AtomicInteger extends java.lang.Number implements java.io.Serializable {
+    ctor public AtomicInteger(int);
+    ctor public AtomicInteger();
+    method public final int addAndGet(int);
+    method public final boolean compareAndSet(int, int);
+    method public final int decrementAndGet();
+    method public double doubleValue();
+    method public float floatValue();
+    method public final int get();
+    method public final int getAndAdd(int);
+    method public final int getAndDecrement();
+    method public final int getAndIncrement();
+    method public final int getAndSet(int);
+    method public final int incrementAndGet();
+    method public int intValue();
+    method public final void lazySet(int);
+    method public long longValue();
+    method public final void set(int);
+    method public final boolean weakCompareAndSet(int, int);
+  }
+
+  public class AtomicIntegerArray implements java.io.Serializable {
+    ctor public AtomicIntegerArray(int);
+    ctor public AtomicIntegerArray(int[]);
+    method public final int addAndGet(int, int);
+    method public final boolean compareAndSet(int, int, int);
+    method public final int decrementAndGet(int);
+    method public final int get(int);
+    method public final int getAndAdd(int, int);
+    method public final int getAndDecrement(int);
+    method public final int getAndIncrement(int);
+    method public final int getAndSet(int, int);
+    method public final int incrementAndGet(int);
+    method public final void lazySet(int, int);
+    method public final int length();
+    method public final void set(int, int);
+    method public final boolean weakCompareAndSet(int, int, int);
+  }
+
+  public abstract class AtomicIntegerFieldUpdater {
+    ctor protected AtomicIntegerFieldUpdater();
+    method public int addAndGet(T, int);
+    method public abstract boolean compareAndSet(T, int, int);
+    method public int decrementAndGet(T);
+    method public abstract int get(T);
+    method public int getAndAdd(T, int);
+    method public int getAndDecrement(T);
+    method public int getAndIncrement(T);
+    method public int getAndSet(T, int);
+    method public int incrementAndGet(T);
+    method public abstract void lazySet(T, int);
+    method public static java.util.concurrent.atomic.AtomicIntegerFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
+    method public abstract void set(T, int);
+    method public abstract boolean weakCompareAndSet(T, int, int);
+  }
+
+  public class AtomicLong extends java.lang.Number implements java.io.Serializable {
+    ctor public AtomicLong(long);
+    ctor public AtomicLong();
+    method public final long addAndGet(long);
+    method public final boolean compareAndSet(long, long);
+    method public final long decrementAndGet();
+    method public double doubleValue();
+    method public float floatValue();
+    method public final long get();
+    method public final long getAndAdd(long);
+    method public final long getAndDecrement();
+    method public final long getAndIncrement();
+    method public final long getAndSet(long);
+    method public final long incrementAndGet();
+    method public int intValue();
+    method public final void lazySet(long);
+    method public long longValue();
+    method public final void set(long);
+    method public final boolean weakCompareAndSet(long, long);
+  }
+
+  public class AtomicLongArray implements java.io.Serializable {
+    ctor public AtomicLongArray(int);
+    ctor public AtomicLongArray(long[]);
+    method public long addAndGet(int, long);
+    method public final boolean compareAndSet(int, long, long);
+    method public final long decrementAndGet(int);
+    method public final long get(int);
+    method public final long getAndAdd(int, long);
+    method public final long getAndDecrement(int);
+    method public final long getAndIncrement(int);
+    method public final long getAndSet(int, long);
+    method public final long incrementAndGet(int);
+    method public final void lazySet(int, long);
+    method public final int length();
+    method public final void set(int, long);
+    method public final boolean weakCompareAndSet(int, long, long);
+  }
+
+  public abstract class AtomicLongFieldUpdater {
+    ctor protected AtomicLongFieldUpdater();
+    method public long addAndGet(T, long);
+    method public abstract boolean compareAndSet(T, long, long);
+    method public long decrementAndGet(T);
+    method public abstract long get(T);
+    method public long getAndAdd(T, long);
+    method public long getAndDecrement(T);
+    method public long getAndIncrement(T);
+    method public long getAndSet(T, long);
+    method public long incrementAndGet(T);
+    method public abstract void lazySet(T, long);
+    method public static java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
+    method public abstract void set(T, long);
+    method public abstract boolean weakCompareAndSet(T, long, long);
+  }
+
+  public class AtomicMarkableReference {
+    ctor public AtomicMarkableReference(V, boolean);
+    method public boolean attemptMark(V, boolean);
+    method public boolean compareAndSet(V, V, boolean, boolean);
+    method public V get(boolean[]);
+    method public V getReference();
+    method public boolean isMarked();
+    method public void set(V, boolean);
+    method public boolean weakCompareAndSet(V, V, boolean, boolean);
+  }
+
+  public class AtomicReference implements java.io.Serializable {
+    ctor public AtomicReference(V);
+    ctor public AtomicReference();
+    method public final boolean compareAndSet(V, V);
+    method public final V get();
+    method public final V getAndSet(V);
+    method public final void lazySet(V);
+    method public final void set(V);
+    method public final boolean weakCompareAndSet(V, V);
+  }
+
+  public class AtomicReferenceArray implements java.io.Serializable {
+    ctor public AtomicReferenceArray(int);
+    ctor public AtomicReferenceArray(E[]);
+    method public final boolean compareAndSet(int, E, E);
+    method public final E get(int);
+    method public final E getAndSet(int, E);
+    method public final void lazySet(int, E);
+    method public final int length();
+    method public final void set(int, E);
+    method public final boolean weakCompareAndSet(int, E, E);
+  }
+
+  public abstract class AtomicReferenceFieldUpdater {
+    ctor protected AtomicReferenceFieldUpdater();
+    method public abstract boolean compareAndSet(T, V, V);
+    method public abstract V get(T);
+    method public V getAndSet(T, V);
+    method public abstract void lazySet(T, V);
+    method public static java.util.concurrent.atomic.AtomicReferenceFieldUpdater<U, W> newUpdater(java.lang.Class<U>, java.lang.Class<W>, java.lang.String);
+    method public abstract void set(T, V);
+    method public abstract boolean weakCompareAndSet(T, V, V);
+  }
+
+  public class AtomicStampedReference {
+    ctor public AtomicStampedReference(V, int);
+    method public boolean attemptStamp(V, int);
+    method public boolean compareAndSet(V, V, int, int);
+    method public V get(int[]);
+    method public V getReference();
+    method public int getStamp();
+    method public void set(V, int);
+    method public boolean weakCompareAndSet(V, V, int, int);
+  }
+
+}
+
+package java.util.concurrent.locks {
+
+  public abstract class AbstractOwnableSynchronizer implements java.io.Serializable {
+    ctor protected AbstractOwnableSynchronizer();
+    method protected final java.lang.Thread getExclusiveOwnerThread();
+    method protected final void setExclusiveOwnerThread(java.lang.Thread);
+  }
+
+  public abstract class AbstractQueuedLongSynchronizer extends java.util.concurrent.locks.AbstractOwnableSynchronizer implements java.io.Serializable {
+    ctor protected AbstractQueuedLongSynchronizer();
+    method public final void acquire(long);
+    method public final void acquireInterruptibly(long) throws java.lang.InterruptedException;
+    method public final void acquireShared(long);
+    method public final void acquireSharedInterruptibly(long) throws java.lang.InterruptedException;
+    method protected final boolean compareAndSetState(long, long);
+    method public final java.util.Collection<java.lang.Thread> getExclusiveQueuedThreads();
+    method public final java.lang.Thread getFirstQueuedThread();
+    method public final int getQueueLength();
+    method public final java.util.Collection<java.lang.Thread> getQueuedThreads();
+    method public final java.util.Collection<java.lang.Thread> getSharedQueuedThreads();
+    method protected final long getState();
+    method public final int getWaitQueueLength(java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject);
+    method public final java.util.Collection<java.lang.Thread> getWaitingThreads(java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject);
+    method public final boolean hasContended();
+    method public final boolean hasQueuedThreads();
+    method public final boolean hasWaiters(java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject);
+    method protected boolean isHeldExclusively();
+    method public final boolean isQueued(java.lang.Thread);
+    method public final boolean owns(java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject);
+    method public final boolean release(long);
+    method public final boolean releaseShared(long);
+    method protected final void setState(long);
+    method protected boolean tryAcquire(long);
+    method public final boolean tryAcquireNanos(long, long) throws java.lang.InterruptedException;
+    method protected long tryAcquireShared(long);
+    method public final boolean tryAcquireSharedNanos(long, long) throws java.lang.InterruptedException;
+    method protected boolean tryRelease(long);
+    method protected boolean tryReleaseShared(long);
+  }
+
+  public class AbstractQueuedLongSynchronizer.ConditionObject implements java.util.concurrent.locks.Condition java.io.Serializable {
+    ctor public AbstractQueuedLongSynchronizer.ConditionObject();
+    method public final void await() throws java.lang.InterruptedException;
+    method public final boolean await(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public final long awaitNanos(long) throws java.lang.InterruptedException;
+    method public final void awaitUninterruptibly();
+    method public final boolean awaitUntil(java.util.Date) throws java.lang.InterruptedException;
+    method protected final int getWaitQueueLength();
+    method protected final java.util.Collection<java.lang.Thread> getWaitingThreads();
+    method protected final boolean hasWaiters();
+    method public final void signal();
+    method public final void signalAll();
+  }
+
+  public abstract class AbstractQueuedSynchronizer extends java.util.concurrent.locks.AbstractOwnableSynchronizer implements java.io.Serializable {
+    ctor protected AbstractQueuedSynchronizer();
+    method public final void acquire(int);
+    method public final void acquireInterruptibly(int) throws java.lang.InterruptedException;
+    method public final void acquireShared(int);
+    method public final void acquireSharedInterruptibly(int) throws java.lang.InterruptedException;
+    method protected final boolean compareAndSetState(int, int);
+    method public final java.util.Collection<java.lang.Thread> getExclusiveQueuedThreads();
+    method public final java.lang.Thread getFirstQueuedThread();
+    method public final int getQueueLength();
+    method public final java.util.Collection<java.lang.Thread> getQueuedThreads();
+    method public final java.util.Collection<java.lang.Thread> getSharedQueuedThreads();
+    method protected final int getState();
+    method public final int getWaitQueueLength(java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject);
+    method public final java.util.Collection<java.lang.Thread> getWaitingThreads(java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject);
+    method public final boolean hasContended();
+    method public final boolean hasQueuedThreads();
+    method public final boolean hasWaiters(java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject);
+    method protected boolean isHeldExclusively();
+    method public final boolean isQueued(java.lang.Thread);
+    method public final boolean owns(java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject);
+    method public final boolean release(int);
+    method public final boolean releaseShared(int);
+    method protected final void setState(int);
+    method protected boolean tryAcquire(int);
+    method public final boolean tryAcquireNanos(int, long) throws java.lang.InterruptedException;
+    method protected int tryAcquireShared(int);
+    method public final boolean tryAcquireSharedNanos(int, long) throws java.lang.InterruptedException;
+    method protected boolean tryRelease(int);
+    method protected boolean tryReleaseShared(int);
+  }
+
+  public class AbstractQueuedSynchronizer.ConditionObject implements java.util.concurrent.locks.Condition java.io.Serializable {
+    ctor public AbstractQueuedSynchronizer.ConditionObject();
+    method public final void await() throws java.lang.InterruptedException;
+    method public final boolean await(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public final long awaitNanos(long) throws java.lang.InterruptedException;
+    method public final void awaitUninterruptibly();
+    method public final boolean awaitUntil(java.util.Date) throws java.lang.InterruptedException;
+    method protected final int getWaitQueueLength();
+    method protected final java.util.Collection<java.lang.Thread> getWaitingThreads();
+    method protected final boolean hasWaiters();
+    method public final void signal();
+    method public final void signalAll();
+  }
+
+  public abstract interface Condition {
+    method public abstract void await() throws java.lang.InterruptedException;
+    method public abstract boolean await(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public abstract long awaitNanos(long) throws java.lang.InterruptedException;
+    method public abstract void awaitUninterruptibly();
+    method public abstract boolean awaitUntil(java.util.Date) throws java.lang.InterruptedException;
+    method public abstract void signal();
+    method public abstract void signalAll();
+  }
+
+  public abstract interface Lock {
+    method public abstract void lock();
+    method public abstract void lockInterruptibly() throws java.lang.InterruptedException;
+    method public abstract java.util.concurrent.locks.Condition newCondition();
+    method public abstract boolean tryLock();
+    method public abstract boolean tryLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public abstract void unlock();
+  }
+
+  public class LockSupport {
+    method public static java.lang.Object getBlocker(java.lang.Thread);
+    method public static void park(java.lang.Object);
+    method public static void park();
+    method public static void parkNanos(java.lang.Object, long);
+    method public static void parkNanos(long);
+    method public static void parkUntil(java.lang.Object, long);
+    method public static void parkUntil(long);
+    method public static void unpark(java.lang.Thread);
+  }
+
+  public abstract interface ReadWriteLock {
+    method public abstract java.util.concurrent.locks.Lock readLock();
+    method public abstract java.util.concurrent.locks.Lock writeLock();
+  }
+
+  public class ReentrantLock implements java.util.concurrent.locks.Lock java.io.Serializable {
+    ctor public ReentrantLock();
+    ctor public ReentrantLock(boolean);
+    method public int getHoldCount();
+    method protected java.lang.Thread getOwner();
+    method public final int getQueueLength();
+    method protected java.util.Collection<java.lang.Thread> getQueuedThreads();
+    method public int getWaitQueueLength(java.util.concurrent.locks.Condition);
+    method protected java.util.Collection<java.lang.Thread> getWaitingThreads(java.util.concurrent.locks.Condition);
+    method public final boolean hasQueuedThread(java.lang.Thread);
+    method public final boolean hasQueuedThreads();
+    method public boolean hasWaiters(java.util.concurrent.locks.Condition);
+    method public final boolean isFair();
+    method public boolean isHeldByCurrentThread();
+    method public boolean isLocked();
+    method public void lock();
+    method public void lockInterruptibly() throws java.lang.InterruptedException;
+    method public java.util.concurrent.locks.Condition newCondition();
+    method public boolean tryLock();
+    method public boolean tryLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public void unlock();
+  }
+
+  public class ReentrantReadWriteLock implements java.util.concurrent.locks.ReadWriteLock java.io.Serializable {
+    ctor public ReentrantReadWriteLock();
+    ctor public ReentrantReadWriteLock(boolean);
+    method protected java.lang.Thread getOwner();
+    method public final int getQueueLength();
+    method protected java.util.Collection<java.lang.Thread> getQueuedReaderThreads();
+    method protected java.util.Collection<java.lang.Thread> getQueuedThreads();
+    method protected java.util.Collection<java.lang.Thread> getQueuedWriterThreads();
+    method public int getReadHoldCount();
+    method public int getReadLockCount();
+    method public int getWaitQueueLength(java.util.concurrent.locks.Condition);
+    method protected java.util.Collection<java.lang.Thread> getWaitingThreads(java.util.concurrent.locks.Condition);
+    method public int getWriteHoldCount();
+    method public final boolean hasQueuedThread(java.lang.Thread);
+    method public final boolean hasQueuedThreads();
+    method public boolean hasWaiters(java.util.concurrent.locks.Condition);
+    method public final boolean isFair();
+    method public boolean isWriteLocked();
+    method public boolean isWriteLockedByCurrentThread();
+    method public java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock readLock();
+    method public java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock writeLock();
+  }
+
+  public static class ReentrantReadWriteLock.ReadLock implements java.util.concurrent.locks.Lock java.io.Serializable {
+    ctor protected ReentrantReadWriteLock.ReadLock(java.util.concurrent.locks.ReentrantReadWriteLock);
+    method public void lock();
+    method public void lockInterruptibly() throws java.lang.InterruptedException;
+    method public java.util.concurrent.locks.Condition newCondition();
+    method public boolean tryLock();
+    method public boolean tryLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public void unlock();
+  }
+
+  public static class ReentrantReadWriteLock.WriteLock implements java.util.concurrent.locks.Lock java.io.Serializable {
+    ctor protected ReentrantReadWriteLock.WriteLock(java.util.concurrent.locks.ReentrantReadWriteLock);
+    method public int getHoldCount();
+    method public boolean isHeldByCurrentThread();
+    method public void lock();
+    method public void lockInterruptibly() throws java.lang.InterruptedException;
+    method public java.util.concurrent.locks.Condition newCondition();
+    method public boolean tryLock();
+    method public boolean tryLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public void unlock();
+  }
+
+}
+
+package java.util.jar {
+
+  public class Attributes implements java.lang.Cloneable java.util.Map {
+    ctor public Attributes();
+    ctor public Attributes(java.util.jar.Attributes);
+    ctor public Attributes(int);
+    method public void clear();
+    method public java.lang.Object clone();
+    method public boolean containsKey(java.lang.Object);
+    method public boolean containsValue(java.lang.Object);
+    method public java.util.Set<java.util.Map.Entry<java.lang.Object, java.lang.Object>> entrySet();
+    method public java.lang.Object get(java.lang.Object);
+    method public java.lang.String getValue(java.util.jar.Attributes.Name);
+    method public java.lang.String getValue(java.lang.String);
+    method public boolean isEmpty();
+    method public java.util.Set<java.lang.Object> keySet();
+    method public java.lang.Object put(java.lang.Object, java.lang.Object);
+    method public void putAll(java.util.Map<?, ?>);
+    method public java.lang.String putValue(java.lang.String, java.lang.String);
+    method public java.lang.Object remove(java.lang.Object);
+    method public int size();
+    method public java.util.Collection<java.lang.Object> values();
+    field protected java.util.Map map;
+  }
+
+  public static class Attributes.Name {
+    ctor public Attributes.Name(java.lang.String);
+    field public static final java.util.jar.Attributes.Name CLASS_PATH;
+    field public static final java.util.jar.Attributes.Name CONTENT_TYPE;
+    field public static final java.util.jar.Attributes.Name EXTENSION_INSTALLATION;
+    field public static final java.util.jar.Attributes.Name EXTENSION_LIST;
+    field public static final java.util.jar.Attributes.Name EXTENSION_NAME;
+    field public static final java.util.jar.Attributes.Name IMPLEMENTATION_TITLE;
+    field public static final java.util.jar.Attributes.Name IMPLEMENTATION_URL;
+    field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR;
+    field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR_ID;
+    field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VERSION;
+    field public static final java.util.jar.Attributes.Name MAIN_CLASS;
+    field public static final java.util.jar.Attributes.Name MANIFEST_VERSION;
+    field public static final java.util.jar.Attributes.Name SEALED;
+    field public static final java.util.jar.Attributes.Name SIGNATURE_VERSION;
+    field public static final java.util.jar.Attributes.Name SPECIFICATION_TITLE;
+    field public static final java.util.jar.Attributes.Name SPECIFICATION_VENDOR;
+    field public static final java.util.jar.Attributes.Name SPECIFICATION_VERSION;
+  }
+
+  public class JarEntry extends java.util.zip.ZipEntry {
+    ctor public JarEntry(java.lang.String);
+    ctor public JarEntry(java.util.zip.ZipEntry);
+    ctor public JarEntry(java.util.jar.JarEntry);
+    method public java.util.jar.Attributes getAttributes() throws java.io.IOException;
+    method public java.security.cert.Certificate[] getCertificates();
+    method public java.security.CodeSigner[] getCodeSigners();
+  }
+
+  public class JarException extends java.util.zip.ZipException {
+    ctor public JarException();
+    ctor public JarException(java.lang.String);
+  }
+
+  public class JarFile extends java.util.zip.ZipFile {
+    ctor public JarFile(java.io.File) throws java.io.IOException;
+    ctor public JarFile(java.io.File, boolean) throws java.io.IOException;
+    ctor public JarFile(java.io.File, boolean, int) throws java.io.IOException;
+    ctor public JarFile(java.lang.String) throws java.io.IOException;
+    ctor public JarFile(java.lang.String, boolean) throws java.io.IOException;
+    method public java.util.jar.JarEntry getJarEntry(java.lang.String);
+    method public java.util.jar.Manifest getManifest() throws java.io.IOException;
+    field public static final java.lang.String MANIFEST_NAME = "META-INF/MANIFEST.MF";
+  }
+
+  public class JarInputStream extends java.util.zip.ZipInputStream {
+    ctor public JarInputStream(java.io.InputStream, boolean) throws java.io.IOException;
+    ctor public JarInputStream(java.io.InputStream) throws java.io.IOException;
+    method public java.util.jar.Manifest getManifest();
+    method public java.util.jar.JarEntry getNextJarEntry() throws java.io.IOException;
+  }
+
+  public class JarOutputStream extends java.util.zip.ZipOutputStream {
+    ctor public JarOutputStream(java.io.OutputStream, java.util.jar.Manifest) throws java.io.IOException;
+    ctor public JarOutputStream(java.io.OutputStream) throws java.io.IOException;
+  }
+
+  public class Manifest implements java.lang.Cloneable {
+    ctor public Manifest();
+    ctor public Manifest(java.io.InputStream) throws java.io.IOException;
+    ctor public Manifest(java.util.jar.Manifest);
+    method public void clear();
+    method public java.lang.Object clone();
+    method public java.util.jar.Attributes getAttributes(java.lang.String);
+    method public java.util.Map<java.lang.String, java.util.jar.Attributes> getEntries();
+    method public java.util.jar.Attributes getMainAttributes();
+    method public void read(java.io.InputStream) throws java.io.IOException;
+    method public void write(java.io.OutputStream) throws java.io.IOException;
+  }
+
+  public abstract class Pack200 {
+    method public static java.util.jar.Pack200.Packer newPacker();
+    method public static java.util.jar.Pack200.Unpacker newUnpacker();
+  }
+
+  public static abstract interface Pack200.Packer {
+    method public abstract void addPropertyChangeListener(java.beans.PropertyChangeListener);
+    method public abstract void pack(java.util.jar.JarFile, java.io.OutputStream) throws java.io.IOException;
+    method public abstract void pack(java.util.jar.JarInputStream, java.io.OutputStream) throws java.io.IOException;
+    method public abstract java.util.SortedMap<java.lang.String, java.lang.String> properties();
+    method public abstract void removePropertyChangeListener(java.beans.PropertyChangeListener);
+    field public static final java.lang.String CLASS_ATTRIBUTE_PFX = "pack.class.attribute.";
+    field public static final java.lang.String CODE_ATTRIBUTE_PFX = "pack.code.attribute.";
+    field public static final java.lang.String DEFLATE_HINT = "pack.deflate.hint";
+    field public static final java.lang.String EFFORT = "pack.effort";
+    field public static final java.lang.String ERROR = "error";
+    field public static final java.lang.String FALSE = "false";
+    field public static final java.lang.String FIELD_ATTRIBUTE_PFX = "pack.field.attribute.";
+    field public static final java.lang.String KEEP = "keep";
+    field public static final java.lang.String KEEP_FILE_ORDER = "pack.keep.file.order";
+    field public static final java.lang.String LATEST = "latest";
+    field public static final java.lang.String METHOD_ATTRIBUTE_PFX = "pack.method.attribute.";
+    field public static final java.lang.String MODIFICATION_TIME = "pack.modification.time";
+    field public static final java.lang.String PASS = "pass";
+    field public static final java.lang.String PASS_FILE_PFX = "pack.pass.file.";
+    field public static final java.lang.String PROGRESS = "pack.progress";
+    field public static final java.lang.String SEGMENT_LIMIT = "pack.segment.limit";
+    field public static final java.lang.String STRIP = "strip";
+    field public static final java.lang.String TRUE = "true";
+    field public static final java.lang.String UNKNOWN_ATTRIBUTE = "pack.unknown.attribute";
+  }
+
+  public static abstract interface Pack200.Unpacker {
+    method public abstract void addPropertyChangeListener(java.beans.PropertyChangeListener);
+    method public abstract java.util.SortedMap<java.lang.String, java.lang.String> properties();
+    method public abstract void removePropertyChangeListener(java.beans.PropertyChangeListener);
+    method public abstract void unpack(java.io.InputStream, java.util.jar.JarOutputStream) throws java.io.IOException;
+    method public abstract void unpack(java.io.File, java.util.jar.JarOutputStream) throws java.io.IOException;
+    field public static final java.lang.String DEFLATE_HINT = "unpack.deflate.hint";
+    field public static final java.lang.String FALSE = "false";
+    field public static final java.lang.String KEEP = "keep";
+    field public static final java.lang.String PROGRESS = "unpack.progress";
+    field public static final java.lang.String TRUE = "true";
+  }
+
+}
+
+package java.util.logging {
+
+  public class ConsoleHandler extends java.util.logging.StreamHandler {
+    ctor public ConsoleHandler();
+  }
+
+  public class ErrorManager {
+    ctor public ErrorManager();
+    method public void error(java.lang.String, java.lang.Exception, int);
+    field public static final int CLOSE_FAILURE = 3; // 0x3
+    field public static final int FLUSH_FAILURE = 2; // 0x2
+    field public static final int FORMAT_FAILURE = 5; // 0x5
+    field public static final int GENERIC_FAILURE = 0; // 0x0
+    field public static final int OPEN_FAILURE = 4; // 0x4
+    field public static final int WRITE_FAILURE = 1; // 0x1
+  }
+
+  public class FileHandler extends java.util.logging.StreamHandler {
+    ctor public FileHandler() throws java.io.IOException;
+    ctor public FileHandler(java.lang.String) throws java.io.IOException;
+    ctor public FileHandler(java.lang.String, boolean) throws java.io.IOException;
+    ctor public FileHandler(java.lang.String, int, int) throws java.io.IOException;
+    ctor public FileHandler(java.lang.String, int, int, boolean) throws java.io.IOException;
+  }
+
+  public abstract interface Filter {
+    method public abstract boolean isLoggable(java.util.logging.LogRecord);
+  }
+
+  public abstract class Formatter {
+    ctor protected Formatter();
+    method public abstract java.lang.String format(java.util.logging.LogRecord);
+    method public java.lang.String formatMessage(java.util.logging.LogRecord);
+    method public java.lang.String getHead(java.util.logging.Handler);
+    method public java.lang.String getTail(java.util.logging.Handler);
+  }
+
+  public abstract class Handler {
+    ctor protected Handler();
+    method public abstract void close();
+    method public abstract void flush();
+    method public java.lang.String getEncoding();
+    method public java.util.logging.ErrorManager getErrorManager();
+    method public java.util.logging.Filter getFilter();
+    method public java.util.logging.Formatter getFormatter();
+    method public java.util.logging.Level getLevel();
+    method public boolean isLoggable(java.util.logging.LogRecord);
+    method public abstract void publish(java.util.logging.LogRecord);
+    method protected void reportError(java.lang.String, java.lang.Exception, int);
+    method public void setEncoding(java.lang.String) throws java.io.UnsupportedEncodingException;
+    method public void setErrorManager(java.util.logging.ErrorManager);
+    method public void setFilter(java.util.logging.Filter);
+    method public void setFormatter(java.util.logging.Formatter);
+    method public void setLevel(java.util.logging.Level);
+  }
+
+  public class Level implements java.io.Serializable {
+    ctor protected Level(java.lang.String, int);
+    ctor protected Level(java.lang.String, int, java.lang.String);
+    method public java.lang.String getLocalizedName();
+    method public java.lang.String getName();
+    method public java.lang.String getResourceBundleName();
+    method public final int intValue();
+    method public static java.util.logging.Level parse(java.lang.String) throws java.lang.IllegalArgumentException;
+    method public final java.lang.String toString();
+    field public static final java.util.logging.Level ALL;
+    field public static final java.util.logging.Level CONFIG;
+    field public static final java.util.logging.Level FINE;
+    field public static final java.util.logging.Level FINER;
+    field public static final java.util.logging.Level FINEST;
+    field public static final java.util.logging.Level INFO;
+    field public static final java.util.logging.Level OFF;
+    field public static final java.util.logging.Level SEVERE;
+    field public static final java.util.logging.Level WARNING;
+  }
+
+  public class LogManager {
+    ctor protected LogManager();
+    method public synchronized boolean addLogger(java.util.logging.Logger);
+    method public void addPropertyChangeListener(java.beans.PropertyChangeListener);
+    method public void checkAccess();
+    method public static java.util.logging.LogManager getLogManager();
+    method public synchronized java.util.logging.Logger getLogger(java.lang.String);
+    method public synchronized java.util.Enumeration<java.lang.String> getLoggerNames();
+    method public static java.util.logging.LoggingMXBean getLoggingMXBean();
+    method public java.lang.String getProperty(java.lang.String);
+    method public void readConfiguration() throws java.io.IOException;
+    method public void readConfiguration(java.io.InputStream) throws java.io.IOException;
+    method public void removePropertyChangeListener(java.beans.PropertyChangeListener);
+    method public synchronized void reset();
+    field public static final java.lang.String LOGGING_MXBEAN_NAME = "java.util.logging:type=Logging";
+  }
+
+  public class LogRecord implements java.io.Serializable {
+    ctor public LogRecord(java.util.logging.Level, java.lang.String);
+    method public java.util.logging.Level getLevel();
+    method public java.lang.String getLoggerName();
+    method public java.lang.String getMessage();
+    method public long getMillis();
+    method public java.lang.Object[] getParameters();
+    method public java.util.ResourceBundle getResourceBundle();
+    method public java.lang.String getResourceBundleName();
+    method public long getSequenceNumber();
+    method public java.lang.String getSourceClassName();
+    method public java.lang.String getSourceMethodName();
+    method public int getThreadID();
+    method public java.lang.Throwable getThrown();
+    method public void setLevel(java.util.logging.Level);
+    method public void setLoggerName(java.lang.String);
+    method public void setMessage(java.lang.String);
+    method public void setMillis(long);
+    method public void setParameters(java.lang.Object[]);
+    method public void setResourceBundle(java.util.ResourceBundle);
+    method public void setResourceBundleName(java.lang.String);
+    method public void setSequenceNumber(long);
+    method public void setSourceClassName(java.lang.String);
+    method public void setSourceMethodName(java.lang.String);
+    method public void setThreadID(int);
+    method public void setThrown(java.lang.Throwable);
+  }
+
+  public class Logger {
+    ctor protected Logger(java.lang.String, java.lang.String);
+    method public void addHandler(java.util.logging.Handler);
+    method public void config(java.lang.String);
+    method public void entering(java.lang.String, java.lang.String);
+    method public void entering(java.lang.String, java.lang.String, java.lang.Object);
+    method public void entering(java.lang.String, java.lang.String, java.lang.Object[]);
+    method public void exiting(java.lang.String, java.lang.String);
+    method public void exiting(java.lang.String, java.lang.String, java.lang.Object);
+    method public void fine(java.lang.String);
+    method public void finer(java.lang.String);
+    method public void finest(java.lang.String);
+    method public static java.util.logging.Logger getAnonymousLogger();
+    method public static java.util.logging.Logger getAnonymousLogger(java.lang.String);
+    method public java.util.logging.Filter getFilter();
+    method public java.util.logging.Handler[] getHandlers();
+    method public java.util.logging.Level getLevel();
+    method public static java.util.logging.Logger getLogger(java.lang.String);
+    method public static java.util.logging.Logger getLogger(java.lang.String, java.lang.String);
+    method public java.lang.String getName();
+    method public java.util.logging.Logger getParent();
+    method public java.util.ResourceBundle getResourceBundle();
+    method public java.lang.String getResourceBundleName();
+    method public boolean getUseParentHandlers();
+    method public void info(java.lang.String);
+    method public boolean isLoggable(java.util.logging.Level);
+    method public void log(java.util.logging.Level, java.lang.String);
+    method public void log(java.util.logging.Level, java.lang.String, java.lang.Object);
+    method public void log(java.util.logging.Level, java.lang.String, java.lang.Object[]);
+    method public void log(java.util.logging.Level, java.lang.String, java.lang.Throwable);
+    method public void log(java.util.logging.LogRecord);
+    method public void logp(java.util.logging.Level, java.lang.String, java.lang.String, java.lang.String);
+    method public void logp(java.util.logging.Level, java.lang.String, java.lang.String, java.lang.String, java.lang.Object);
+    method public void logp(java.util.logging.Level, java.lang.String, java.lang.String, java.lang.String, java.lang.Object[]);
+    method public void logp(java.util.logging.Level, java.lang.String, java.lang.String, java.lang.String, java.lang.Throwable);
+    method public void logrb(java.util.logging.Level, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public void logrb(java.util.logging.Level, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.Object);
+    method public void logrb(java.util.logging.Level, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.Object[]);
+    method public void logrb(java.util.logging.Level, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.Throwable);
+    method public void removeHandler(java.util.logging.Handler);
+    method public void setFilter(java.util.logging.Filter);
+    method public void setLevel(java.util.logging.Level);
+    method public void setParent(java.util.logging.Logger);
+    method public void setUseParentHandlers(boolean);
+    method public void severe(java.lang.String);
+    method public void throwing(java.lang.String, java.lang.String, java.lang.Throwable);
+    method public void warning(java.lang.String);
+    field public static final java.lang.String GLOBAL_LOGGER_NAME = "global";
+    field public static final deprecated java.util.logging.Logger global;
+  }
+
+  public abstract interface LoggingMXBean {
+    method public abstract java.lang.String getLoggerLevel(java.lang.String);
+    method public abstract java.util.List<java.lang.String> getLoggerNames();
+    method public abstract java.lang.String getParentLoggerName(java.lang.String);
+    method public abstract void setLoggerLevel(java.lang.String, java.lang.String);
+  }
+
+  public final class LoggingPermission extends java.security.BasicPermission implements java.security.Guard java.io.Serializable {
+    ctor public LoggingPermission(java.lang.String, java.lang.String);
+  }
+
+  public class MemoryHandler extends java.util.logging.Handler {
+    ctor public MemoryHandler();
+    ctor public MemoryHandler(java.util.logging.Handler, int, java.util.logging.Level);
+    method public void close();
+    method public void flush();
+    method public java.util.logging.Level getPushLevel();
+    method public synchronized void publish(java.util.logging.LogRecord);
+    method public void push();
+    method public void setPushLevel(java.util.logging.Level);
+  }
+
+  public class SimpleFormatter extends java.util.logging.Formatter {
+    ctor public SimpleFormatter();
+    method public java.lang.String format(java.util.logging.LogRecord);
+  }
+
+  public class SocketHandler extends java.util.logging.StreamHandler {
+    ctor public SocketHandler() throws java.io.IOException;
+    ctor public SocketHandler(java.lang.String, int) throws java.io.IOException;
+  }
+
+  public class StreamHandler extends java.util.logging.Handler {
+    ctor public StreamHandler();
+    ctor public StreamHandler(java.io.OutputStream, java.util.logging.Formatter);
+    method public void close();
+    method public void flush();
+    method public synchronized void publish(java.util.logging.LogRecord);
+    method protected void setOutputStream(java.io.OutputStream);
+  }
+
+  public class XMLFormatter extends java.util.logging.Formatter {
+    ctor public XMLFormatter();
+    method public java.lang.String format(java.util.logging.LogRecord);
+  }
+
+}
+
+package java.util.prefs {
+
+  public abstract class AbstractPreferences extends java.util.prefs.Preferences {
+    ctor protected AbstractPreferences(java.util.prefs.AbstractPreferences, java.lang.String);
+    method public java.lang.String absolutePath();
+    method public void addNodeChangeListener(java.util.prefs.NodeChangeListener);
+    method public void addPreferenceChangeListener(java.util.prefs.PreferenceChangeListener);
+    method protected final java.util.prefs.AbstractPreferences[] cachedChildren();
+    method protected abstract java.util.prefs.AbstractPreferences childSpi(java.lang.String);
+    method public java.lang.String[] childrenNames() throws java.util.prefs.BackingStoreException;
+    method protected abstract java.lang.String[] childrenNamesSpi() throws java.util.prefs.BackingStoreException;
+    method public void clear() throws java.util.prefs.BackingStoreException;
+    method public void exportNode(java.io.OutputStream) throws java.util.prefs.BackingStoreException, java.io.IOException;
+    method public void exportSubtree(java.io.OutputStream) throws java.util.prefs.BackingStoreException, java.io.IOException;
+    method public void flush() throws java.util.prefs.BackingStoreException;
+    method protected abstract void flushSpi() throws java.util.prefs.BackingStoreException;
+    method public java.lang.String get(java.lang.String, java.lang.String);
+    method public boolean getBoolean(java.lang.String, boolean);
+    method public byte[] getByteArray(java.lang.String, byte[]);
+    method protected java.util.prefs.AbstractPreferences getChild(java.lang.String) throws java.util.prefs.BackingStoreException;
+    method public double getDouble(java.lang.String, double);
+    method public float getFloat(java.lang.String, float);
+    method public int getInt(java.lang.String, int);
+    method public long getLong(java.lang.String, long);
+    method protected abstract java.lang.String getSpi(java.lang.String);
+    method protected boolean isRemoved();
+    method public boolean isUserNode();
+    method public java.lang.String[] keys() throws java.util.prefs.BackingStoreException;
+    method protected abstract java.lang.String[] keysSpi() throws java.util.prefs.BackingStoreException;
+    method public java.lang.String name();
+    method public java.util.prefs.Preferences node(java.lang.String);
+    method public boolean nodeExists(java.lang.String) throws java.util.prefs.BackingStoreException;
+    method public java.util.prefs.Preferences parent();
+    method public void put(java.lang.String, java.lang.String);
+    method public void putBoolean(java.lang.String, boolean);
+    method public void putByteArray(java.lang.String, byte[]);
+    method public void putDouble(java.lang.String, double);
+    method public void putFloat(java.lang.String, float);
+    method public void putInt(java.lang.String, int);
+    method public void putLong(java.lang.String, long);
+    method protected abstract void putSpi(java.lang.String, java.lang.String);
+    method public void remove(java.lang.String);
+    method public void removeNode() throws java.util.prefs.BackingStoreException;
+    method public void removeNodeChangeListener(java.util.prefs.NodeChangeListener);
+    method protected abstract void removeNodeSpi() throws java.util.prefs.BackingStoreException;
+    method public void removePreferenceChangeListener(java.util.prefs.PreferenceChangeListener);
+    method protected abstract void removeSpi(java.lang.String);
+    method public void sync() throws java.util.prefs.BackingStoreException;
+    method protected abstract void syncSpi() throws java.util.prefs.BackingStoreException;
+    method public java.lang.String toString();
+    field protected final java.lang.Object lock;
+    field protected boolean newNode;
+  }
+
+  public class BackingStoreException extends java.lang.Exception {
+    ctor public BackingStoreException(java.lang.String);
+    ctor public BackingStoreException(java.lang.Throwable);
+  }
+
+  public class InvalidPreferencesFormatException extends java.lang.Exception {
+    ctor public InvalidPreferencesFormatException(java.lang.String);
+    ctor public InvalidPreferencesFormatException(java.lang.String, java.lang.Throwable);
+    ctor public InvalidPreferencesFormatException(java.lang.Throwable);
+  }
+
+  public class NodeChangeEvent extends java.util.EventObject implements java.io.Serializable {
+    ctor public NodeChangeEvent(java.util.prefs.Preferences, java.util.prefs.Preferences);
+    method public java.util.prefs.Preferences getChild();
+    method public java.util.prefs.Preferences getParent();
+  }
+
+  public abstract interface NodeChangeListener implements java.util.EventListener {
+    method public abstract void childAdded(java.util.prefs.NodeChangeEvent);
+    method public abstract void childRemoved(java.util.prefs.NodeChangeEvent);
+  }
+
+  public class PreferenceChangeEvent extends java.util.EventObject implements java.io.Serializable {
+    ctor public PreferenceChangeEvent(java.util.prefs.Preferences, java.lang.String, java.lang.String);
+    method public java.lang.String getKey();
+    method public java.lang.String getNewValue();
+    method public java.util.prefs.Preferences getNode();
+  }
+
+  public abstract interface PreferenceChangeListener implements java.util.EventListener {
+    method public abstract void preferenceChange(java.util.prefs.PreferenceChangeEvent);
+  }
+
+  public abstract class Preferences {
+    ctor protected Preferences();
+    method public abstract java.lang.String absolutePath();
+    method public abstract void addNodeChangeListener(java.util.prefs.NodeChangeListener);
+    method public abstract void addPreferenceChangeListener(java.util.prefs.PreferenceChangeListener);
+    method public abstract java.lang.String[] childrenNames() throws java.util.prefs.BackingStoreException;
+    method public abstract void clear() throws java.util.prefs.BackingStoreException;
+    method public abstract void exportNode(java.io.OutputStream) throws java.util.prefs.BackingStoreException, java.io.IOException;
+    method public abstract void exportSubtree(java.io.OutputStream) throws java.util.prefs.BackingStoreException, java.io.IOException;
+    method public abstract void flush() throws java.util.prefs.BackingStoreException;
+    method public abstract java.lang.String get(java.lang.String, java.lang.String);
+    method public abstract boolean getBoolean(java.lang.String, boolean);
+    method public abstract byte[] getByteArray(java.lang.String, byte[]);
+    method public abstract double getDouble(java.lang.String, double);
+    method public abstract float getFloat(java.lang.String, float);
+    method public abstract int getInt(java.lang.String, int);
+    method public abstract long getLong(java.lang.String, long);
+    method public static void importPreferences(java.io.InputStream) throws java.io.IOException, java.util.prefs.InvalidPreferencesFormatException;
+    method public abstract boolean isUserNode();
+    method public abstract java.lang.String[] keys() throws java.util.prefs.BackingStoreException;
+    method public abstract java.lang.String name();
+    method public abstract java.util.prefs.Preferences node(java.lang.String);
+    method public abstract boolean nodeExists(java.lang.String) throws java.util.prefs.BackingStoreException;
+    method public abstract java.util.prefs.Preferences parent();
+    method public abstract void put(java.lang.String, java.lang.String);
+    method public abstract void putBoolean(java.lang.String, boolean);
+    method public abstract void putByteArray(java.lang.String, byte[]);
+    method public abstract void putDouble(java.lang.String, double);
+    method public abstract void putFloat(java.lang.String, float);
+    method public abstract void putInt(java.lang.String, int);
+    method public abstract void putLong(java.lang.String, long);
+    method public abstract void remove(java.lang.String);
+    method public abstract void removeNode() throws java.util.prefs.BackingStoreException;
+    method public abstract void removeNodeChangeListener(java.util.prefs.NodeChangeListener);
+    method public abstract void removePreferenceChangeListener(java.util.prefs.PreferenceChangeListener);
+    method public abstract void sync() throws java.util.prefs.BackingStoreException;
+    method public static java.util.prefs.Preferences systemNodeForPackage(java.lang.Class<?>);
+    method public static java.util.prefs.Preferences systemRoot();
+    method public abstract java.lang.String toString();
+    method public static java.util.prefs.Preferences userNodeForPackage(java.lang.Class<?>);
+    method public static java.util.prefs.Preferences userRoot();
+    field public static final int MAX_KEY_LENGTH = 80; // 0x50
+    field public static final int MAX_NAME_LENGTH = 80; // 0x50
+    field public static final int MAX_VALUE_LENGTH = 8192; // 0x2000
+  }
+
+  public abstract interface PreferencesFactory {
+    method public abstract java.util.prefs.Preferences systemRoot();
+    method public abstract java.util.prefs.Preferences userRoot();
+  }
+
+}
+
+package java.util.regex {
+
+  public abstract interface MatchResult {
+    method public abstract int end();
+    method public abstract int end(int);
+    method public abstract java.lang.String group();
+    method public abstract java.lang.String group(int);
+    method public abstract int groupCount();
+    method public abstract int start();
+    method public abstract int start(int);
+  }
+
+  public final class Matcher implements java.util.regex.MatchResult {
+    method public java.util.regex.Matcher appendReplacement(java.lang.StringBuffer, java.lang.String);
+    method public java.lang.StringBuffer appendTail(java.lang.StringBuffer);
+    method public int end(int);
+    method public int end();
+    method public boolean find(int);
+    method public boolean find();
+    method public java.lang.String group(int);
+    method public java.lang.String group();
+    method public int groupCount();
+    method public boolean hasAnchoringBounds();
+    method public boolean hasTransparentBounds();
+    method public boolean hitEnd();
+    method public boolean lookingAt();
+    method public boolean matches();
+    method public java.util.regex.Pattern pattern();
+    method public static java.lang.String quoteReplacement(java.lang.String);
+    method public java.util.regex.Matcher region(int, int);
+    method public int regionEnd();
+    method public int regionStart();
+    method public java.lang.String replaceAll(java.lang.String);
+    method public java.lang.String replaceFirst(java.lang.String);
+    method public boolean requireEnd();
+    method public java.util.regex.Matcher reset();
+    method public java.util.regex.Matcher reset(java.lang.CharSequence);
+    method public int start(int) throws java.lang.IllegalStateException;
+    method public int start();
+    method public java.util.regex.MatchResult toMatchResult();
+    method public java.util.regex.Matcher useAnchoringBounds(boolean);
+    method public java.util.regex.Matcher usePattern(java.util.regex.Pattern);
+    method public java.util.regex.Matcher useTransparentBounds(boolean);
+  }
+
+  public final class Pattern implements java.io.Serializable {
+    method public static java.util.regex.Pattern compile(java.lang.String, int) throws java.util.regex.PatternSyntaxException;
+    method public static java.util.regex.Pattern compile(java.lang.String);
+    method public int flags();
+    method public java.util.regex.Matcher matcher(java.lang.CharSequence);
+    method public static boolean matches(java.lang.String, java.lang.CharSequence);
+    method public java.lang.String pattern();
+    method public static java.lang.String quote(java.lang.String);
+    method public java.lang.String[] split(java.lang.CharSequence, int);
+    method public java.lang.String[] split(java.lang.CharSequence);
+    field public static final int CANON_EQ = 128; // 0x80
+    field public static final int CASE_INSENSITIVE = 2; // 0x2
+    field public static final int COMMENTS = 4; // 0x4
+    field public static final int DOTALL = 32; // 0x20
+    field public static final int LITERAL = 16; // 0x10
+    field public static final int MULTILINE = 8; // 0x8
+    field public static final int UNICODE_CASE = 64; // 0x40
+    field public static final int UNIX_LINES = 1; // 0x1
+  }
+
+  public class PatternSyntaxException extends java.lang.IllegalArgumentException {
+    ctor public PatternSyntaxException(java.lang.String, java.lang.String, int);
+    method public java.lang.String getDescription();
+    method public int getIndex();
+    method public java.lang.String getPattern();
+  }
+
+}
+
+package java.util.zip {
+
+  public class Adler32 implements java.util.zip.Checksum {
+    ctor public Adler32();
+    method public long getValue();
+    method public void reset();
+    method public void update(int);
+    method public void update(byte[]);
+    method public void update(byte[], int, int);
+  }
+
+  public class CRC32 implements java.util.zip.Checksum {
+    ctor public CRC32();
+    method public long getValue();
+    method public void reset();
+    method public void update(int);
+    method public void update(byte[]);
+    method public void update(byte[], int, int);
+  }
+
+  public class CheckedInputStream extends java.io.FilterInputStream {
+    ctor public CheckedInputStream(java.io.InputStream, java.util.zip.Checksum);
+    method public java.util.zip.Checksum getChecksum();
+  }
+
+  public class CheckedOutputStream extends java.io.FilterOutputStream {
+    ctor public CheckedOutputStream(java.io.OutputStream, java.util.zip.Checksum);
+    method public java.util.zip.Checksum getChecksum();
+  }
+
+  public abstract interface Checksum {
+    method public abstract long getValue();
+    method public abstract void reset();
+    method public abstract void update(byte[], int, int);
+    method public abstract void update(int);
+  }
+
+  public class DataFormatException extends java.lang.Exception {
+    ctor public DataFormatException();
+    ctor public DataFormatException(java.lang.String);
+  }
+
+  public class Deflater {
+    ctor public Deflater();
+    ctor public Deflater(int);
+    ctor public Deflater(int, boolean);
+    method public int deflate(byte[]);
+    method public synchronized int deflate(byte[], int, int);
+    method public synchronized void end();
+    method public synchronized void finish();
+    method public synchronized boolean finished();
+    method public synchronized int getAdler();
+    method public synchronized long getBytesRead();
+    method public synchronized long getBytesWritten();
+    method public synchronized int getTotalIn();
+    method public synchronized int getTotalOut();
+    method public synchronized boolean needsInput();
+    method public synchronized void reset();
+    method public void setDictionary(byte[]);
+    method public synchronized void setDictionary(byte[], int, int);
+    method public void setInput(byte[]);
+    method public synchronized void setInput(byte[], int, int);
+    method public synchronized void setLevel(int);
+    method public synchronized void setStrategy(int);
+    field public static final int BEST_COMPRESSION = 9; // 0x9
+    field public static final int BEST_SPEED = 1; // 0x1
+    field public static final int DEFAULT_COMPRESSION = -1; // 0xffffffff
+    field public static final int DEFAULT_STRATEGY = 0; // 0x0
+    field public static final int DEFLATED = 8; // 0x8
+    field public static final int FILTERED = 1; // 0x1
+    field public static final int HUFFMAN_ONLY = 2; // 0x2
+    field public static final int NO_COMPRESSION = 0; // 0x0
+  }
+
+  public class DeflaterInputStream extends java.io.FilterInputStream {
+    ctor public DeflaterInputStream(java.io.InputStream);
+    ctor public DeflaterInputStream(java.io.InputStream, java.util.zip.Deflater);
+    ctor public DeflaterInputStream(java.io.InputStream, java.util.zip.Deflater, int);
+    field protected final byte[] buf;
+    field protected final java.util.zip.Deflater def;
+  }
+
+  public class DeflaterOutputStream extends java.io.FilterOutputStream {
+    ctor public DeflaterOutputStream(java.io.OutputStream, java.util.zip.Deflater);
+    ctor public DeflaterOutputStream(java.io.OutputStream);
+    ctor public DeflaterOutputStream(java.io.OutputStream, java.util.zip.Deflater, int);
+    method protected void deflate() throws java.io.IOException;
+    method public void finish() throws java.io.IOException;
+    field protected byte[] buf;
+    field protected java.util.zip.Deflater def;
+  }
+
+  public class GZIPInputStream extends java.util.zip.InflaterInputStream {
+    ctor public GZIPInputStream(java.io.InputStream) throws java.io.IOException;
+    ctor public GZIPInputStream(java.io.InputStream, int) throws java.io.IOException;
+    field public static final int GZIP_MAGIC = 35615; // 0x8b1f
+    field protected java.util.zip.CRC32 crc;
+    field protected boolean eos;
+  }
+
+  public class GZIPOutputStream extends java.util.zip.DeflaterOutputStream {
+    ctor public GZIPOutputStream(java.io.OutputStream) throws java.io.IOException;
+    ctor public GZIPOutputStream(java.io.OutputStream, int) throws java.io.IOException;
+    field protected java.util.zip.CRC32 crc;
+  }
+
+  public class Inflater {
+    ctor public Inflater();
+    ctor public Inflater(boolean);
+    method public synchronized void end();
+    method public synchronized boolean finished();
+    method public synchronized int getAdler();
+    method public synchronized long getBytesRead();
+    method public synchronized long getBytesWritten();
+    method public synchronized int getRemaining();
+    method public synchronized int getTotalIn();
+    method public synchronized int getTotalOut();
+    method public int inflate(byte[]) throws java.util.zip.DataFormatException;
+    method public synchronized int inflate(byte[], int, int) throws java.util.zip.DataFormatException;
+    method public synchronized boolean needsDictionary();
+    method public synchronized boolean needsInput();
+    method public synchronized void reset();
+    method public synchronized void setDictionary(byte[]);
+    method public synchronized void setDictionary(byte[], int, int);
+    method public synchronized void setInput(byte[]);
+    method public synchronized void setInput(byte[], int, int);
+  }
+
+  public class InflaterInputStream extends java.io.FilterInputStream {
+    ctor public InflaterInputStream(java.io.InputStream);
+    ctor public InflaterInputStream(java.io.InputStream, java.util.zip.Inflater);
+    ctor public InflaterInputStream(java.io.InputStream, java.util.zip.Inflater, int);
+    method protected void fill() throws java.io.IOException;
+    field protected byte[] buf;
+    field protected java.util.zip.Inflater inf;
+    field protected int len;
+  }
+
+  public class InflaterOutputStream extends java.io.FilterOutputStream {
+    ctor public InflaterOutputStream(java.io.OutputStream);
+    ctor public InflaterOutputStream(java.io.OutputStream, java.util.zip.Inflater);
+    ctor public InflaterOutputStream(java.io.OutputStream, java.util.zip.Inflater, int);
+    method public void finish() throws java.io.IOException;
+    field protected final byte[] buf;
+    field protected final java.util.zip.Inflater inf;
+  }
+
+  public class ZipEntry implements java.lang.Cloneable {
+    ctor public ZipEntry(java.lang.String);
+    ctor public ZipEntry(java.util.zip.ZipEntry);
+    method public java.lang.Object clone();
+    method public java.lang.String getComment();
+    method public long getCompressedSize();
+    method public long getCrc();
+    method public byte[] getExtra();
+    method public int getMethod();
+    method public java.lang.String getName();
+    method public long getSize();
+    method public long getTime();
+    method public boolean isDirectory();
+    method public void setComment(java.lang.String);
+    method public void setCompressedSize(long);
+    method public void setCrc(long);
+    method public void setExtra(byte[]);
+    method public void setMethod(int);
+    method public void setSize(long);
+    method public void setTime(long);
+    field public static final int DEFLATED = 8; // 0x8
+    field public static final int STORED = 0; // 0x0
+  }
+
+  public class ZipError extends java.lang.InternalError {
+    ctor public ZipError(java.lang.String);
+  }
+
+  public class ZipException extends java.io.IOException {
+    ctor public ZipException();
+    ctor public ZipException(java.lang.String);
+  }
+
+  public class ZipFile {
+    ctor public ZipFile(java.io.File) throws java.io.IOException, java.util.zip.ZipException;
+    ctor public ZipFile(java.io.File, int) throws java.io.IOException;
+    ctor public ZipFile(java.lang.String) throws java.io.IOException;
+    method public void close() throws java.io.IOException;
+    method public java.util.Enumeration<? extends java.util.zip.ZipEntry> entries();
+    method public java.util.zip.ZipEntry getEntry(java.lang.String);
+    method public java.io.InputStream getInputStream(java.util.zip.ZipEntry) throws java.io.IOException;
+    method public java.lang.String getName();
+    method public int size();
+    field public static final int OPEN_DELETE = 4; // 0x4
+    field public static final int OPEN_READ = 1; // 0x1
+  }
+
+  public class ZipInputStream extends java.util.zip.InflaterInputStream {
+    ctor public ZipInputStream(java.io.InputStream);
+    method public void closeEntry() throws java.io.IOException;
+    method protected java.util.zip.ZipEntry createZipEntry(java.lang.String);
+    method public java.util.zip.ZipEntry getNextEntry() throws java.io.IOException;
+  }
+
+  public class ZipOutputStream extends java.util.zip.DeflaterOutputStream {
+    ctor public ZipOutputStream(java.io.OutputStream);
+    method public void closeEntry() throws java.io.IOException;
+    method public void putNextEntry(java.util.zip.ZipEntry) throws java.io.IOException;
+    method public void setComment(java.lang.String);
+    method public void setLevel(int);
+    method public void setMethod(int);
+    field public static final int DEFLATED = 8; // 0x8
+    field public static final int STORED = 0; // 0x0
+  }
+
+}
+
+package javax.crypto {
+
+  public class BadPaddingException extends java.security.GeneralSecurityException {
+    ctor public BadPaddingException(java.lang.String);
+    ctor public BadPaddingException();
+  }
+
+  public class Cipher {
+    ctor protected Cipher(javax.crypto.CipherSpi, java.security.Provider, java.lang.String);
+    method public final byte[] doFinal() throws javax.crypto.BadPaddingException, javax.crypto.IllegalBlockSizeException;
+    method public final int doFinal(byte[], int) throws javax.crypto.BadPaddingException, javax.crypto.IllegalBlockSizeException, javax.crypto.ShortBufferException;
+    method public final byte[] doFinal(byte[]) throws javax.crypto.BadPaddingException, javax.crypto.IllegalBlockSizeException;
+    method public final byte[] doFinal(byte[], int, int) throws javax.crypto.BadPaddingException, javax.crypto.IllegalBlockSizeException;
+    method public final int doFinal(byte[], int, int, byte[]) throws javax.crypto.BadPaddingException, javax.crypto.IllegalBlockSizeException, javax.crypto.ShortBufferException;
+    method public final int doFinal(byte[], int, int, byte[], int) throws javax.crypto.BadPaddingException, javax.crypto.IllegalBlockSizeException, javax.crypto.ShortBufferException;
+    method public final int doFinal(java.nio.ByteBuffer, java.nio.ByteBuffer) throws javax.crypto.BadPaddingException, javax.crypto.IllegalBlockSizeException, javax.crypto.ShortBufferException;
+    method public final java.lang.String getAlgorithm();
+    method public final int getBlockSize();
+    method public final javax.crypto.ExemptionMechanism getExemptionMechanism();
+    method public final byte[] getIV();
+    method public static final javax.crypto.Cipher getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException, javax.crypto.NoSuchPaddingException;
+    method public static final javax.crypto.Cipher getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, javax.crypto.NoSuchPaddingException, java.security.NoSuchProviderException;
+    method public static final javax.crypto.Cipher getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException, javax.crypto.NoSuchPaddingException;
+    method public static final int getMaxAllowedKeyLength(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static final java.security.spec.AlgorithmParameterSpec getMaxAllowedParameterSpec(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public final int getOutputSize(int);
+    method public final java.security.AlgorithmParameters getParameters();
+    method public final java.security.Provider getProvider();
+    method public final void init(int, java.security.Key) throws java.security.InvalidKeyException;
+    method public final void init(int, java.security.Key, java.security.SecureRandom) throws java.security.InvalidKeyException;
+    method public final void init(int, java.security.Key, java.security.spec.AlgorithmParameterSpec) throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException;
+    method public final void init(int, java.security.Key, java.security.spec.AlgorithmParameterSpec, java.security.SecureRandom) throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException;
+    method public final void init(int, java.security.Key, java.security.AlgorithmParameters) throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException;
+    method public final void init(int, java.security.Key, java.security.AlgorithmParameters, java.security.SecureRandom) throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException;
+    method public final void init(int, java.security.cert.Certificate) throws java.security.InvalidKeyException;
+    method public final void init(int, java.security.cert.Certificate, java.security.SecureRandom) throws java.security.InvalidKeyException;
+    method public final java.security.Key unwrap(byte[], java.lang.String, int) throws java.security.InvalidKeyException, java.security.NoSuchAlgorithmException;
+    method public final byte[] update(byte[]);
+    method public final byte[] update(byte[], int, int);
+    method public final int update(byte[], int, int, byte[]) throws javax.crypto.ShortBufferException;
+    method public final int update(byte[], int, int, byte[], int) throws javax.crypto.ShortBufferException;
+    method public final int update(java.nio.ByteBuffer, java.nio.ByteBuffer) throws javax.crypto.ShortBufferException;
+    method public final byte[] wrap(java.security.Key) throws javax.crypto.IllegalBlockSizeException, java.security.InvalidKeyException;
+    field public static final int DECRYPT_MODE = 2; // 0x2
+    field public static final int ENCRYPT_MODE = 1; // 0x1
+    field public static final int PRIVATE_KEY = 2; // 0x2
+    field public static final int PUBLIC_KEY = 1; // 0x1
+    field public static final int SECRET_KEY = 3; // 0x3
+    field public static final int UNWRAP_MODE = 4; // 0x4
+    field public static final int WRAP_MODE = 3; // 0x3
+  }
+
+  public class CipherInputStream extends java.io.FilterInputStream {
+    ctor public CipherInputStream(java.io.InputStream, javax.crypto.Cipher);
+    ctor protected CipherInputStream(java.io.InputStream);
+  }
+
+  public class CipherOutputStream extends java.io.FilterOutputStream {
+    ctor public CipherOutputStream(java.io.OutputStream, javax.crypto.Cipher);
+    ctor protected CipherOutputStream(java.io.OutputStream);
+  }
+
+  public abstract class CipherSpi {
+    ctor public CipherSpi();
+    method protected abstract byte[] engineDoFinal(byte[], int, int) throws javax.crypto.BadPaddingException, javax.crypto.IllegalBlockSizeException;
+    method protected abstract int engineDoFinal(byte[], int, int, byte[], int) throws javax.crypto.BadPaddingException, javax.crypto.IllegalBlockSizeException, javax.crypto.ShortBufferException;
+    method protected int engineDoFinal(java.nio.ByteBuffer, java.nio.ByteBuffer) throws javax.crypto.BadPaddingException, javax.crypto.IllegalBlockSizeException, javax.crypto.ShortBufferException;
+    method protected abstract int engineGetBlockSize();
+    method protected abstract byte[] engineGetIV();
+    method protected int engineGetKeySize(java.security.Key) throws java.security.InvalidKeyException;
+    method protected abstract int engineGetOutputSize(int);
+    method protected abstract java.security.AlgorithmParameters engineGetParameters();
+    method protected abstract void engineInit(int, java.security.Key, java.security.SecureRandom) throws java.security.InvalidKeyException;
+    method protected abstract void engineInit(int, java.security.Key, java.security.spec.AlgorithmParameterSpec, java.security.SecureRandom) throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException;
+    method protected abstract void engineInit(int, java.security.Key, java.security.AlgorithmParameters, java.security.SecureRandom) throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException;
+    method protected abstract void engineSetMode(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method protected abstract void engineSetPadding(java.lang.String) throws javax.crypto.NoSuchPaddingException;
+    method protected java.security.Key engineUnwrap(byte[], java.lang.String, int) throws java.security.InvalidKeyException, java.security.NoSuchAlgorithmException;
+    method protected abstract byte[] engineUpdate(byte[], int, int);
+    method protected abstract int engineUpdate(byte[], int, int, byte[], int) throws javax.crypto.ShortBufferException;
+    method protected int engineUpdate(java.nio.ByteBuffer, java.nio.ByteBuffer) throws javax.crypto.ShortBufferException;
+    method protected byte[] engineWrap(java.security.Key) throws javax.crypto.IllegalBlockSizeException, java.security.InvalidKeyException;
+  }
+
+  public class EncryptedPrivateKeyInfo {
+    ctor public EncryptedPrivateKeyInfo(byte[]) throws java.io.IOException;
+    ctor public EncryptedPrivateKeyInfo(java.lang.String, byte[]) throws java.security.NoSuchAlgorithmException;
+    ctor public EncryptedPrivateKeyInfo(java.security.AlgorithmParameters, byte[]) throws java.security.NoSuchAlgorithmException;
+    method public java.lang.String getAlgName();
+    method public java.security.AlgorithmParameters getAlgParameters();
+    method public byte[] getEncoded() throws java.io.IOException;
+    method public byte[] getEncryptedData();
+    method public java.security.spec.PKCS8EncodedKeySpec getKeySpec(javax.crypto.Cipher) throws java.security.spec.InvalidKeySpecException;
+    method public java.security.spec.PKCS8EncodedKeySpec getKeySpec(java.security.Key) throws java.security.InvalidKeyException, java.security.NoSuchAlgorithmException;
+    method public java.security.spec.PKCS8EncodedKeySpec getKeySpec(java.security.Key, java.lang.String) throws java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public java.security.spec.PKCS8EncodedKeySpec getKeySpec(java.security.Key, java.security.Provider) throws java.security.InvalidKeyException, java.security.NoSuchAlgorithmException;
+  }
+
+  public class ExemptionMechanism {
+    ctor protected ExemptionMechanism(javax.crypto.ExemptionMechanismSpi, java.security.Provider, java.lang.String);
+    method public final byte[] genExemptionBlob() throws javax.crypto.ExemptionMechanismException, java.lang.IllegalStateException;
+    method public final int genExemptionBlob(byte[]) throws javax.crypto.ExemptionMechanismException, java.lang.IllegalStateException, javax.crypto.ShortBufferException;
+    method public final int genExemptionBlob(byte[], int) throws javax.crypto.ExemptionMechanismException, java.lang.IllegalStateException, javax.crypto.ShortBufferException;
+    method public static final javax.crypto.ExemptionMechanism getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static final javax.crypto.ExemptionMechanism getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static final javax.crypto.ExemptionMechanism getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final java.lang.String getName();
+    method public final int getOutputSize(int) throws java.lang.IllegalStateException;
+    method public final java.security.Provider getProvider();
+    method public final void init(java.security.Key) throws javax.crypto.ExemptionMechanismException, java.security.InvalidKeyException;
+    method public final void init(java.security.Key, java.security.AlgorithmParameters) throws javax.crypto.ExemptionMechanismException, java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException;
+    method public final void init(java.security.Key, java.security.spec.AlgorithmParameterSpec) throws javax.crypto.ExemptionMechanismException, java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException;
+    method public final boolean isCryptoAllowed(java.security.Key) throws javax.crypto.ExemptionMechanismException;
+  }
+
+  public class ExemptionMechanismException extends java.security.GeneralSecurityException {
+    ctor public ExemptionMechanismException(java.lang.String);
+    ctor public ExemptionMechanismException();
+  }
+
+  public abstract class ExemptionMechanismSpi {
+    ctor public ExemptionMechanismSpi();
+    method protected abstract byte[] engineGenExemptionBlob() throws javax.crypto.ExemptionMechanismException;
+    method protected abstract int engineGenExemptionBlob(byte[], int) throws javax.crypto.ExemptionMechanismException, javax.crypto.ShortBufferException;
+    method protected abstract int engineGetOutputSize(int);
+    method protected abstract void engineInit(java.security.Key) throws javax.crypto.ExemptionMechanismException, java.security.InvalidKeyException;
+    method protected abstract void engineInit(java.security.Key, java.security.AlgorithmParameters) throws javax.crypto.ExemptionMechanismException, java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException;
+    method protected abstract void engineInit(java.security.Key, java.security.spec.AlgorithmParameterSpec) throws javax.crypto.ExemptionMechanismException, java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException;
+  }
+
+  public class IllegalBlockSizeException extends java.security.GeneralSecurityException {
+    ctor public IllegalBlockSizeException(java.lang.String);
+    ctor public IllegalBlockSizeException();
+  }
+
+  public class KeyAgreement {
+    ctor protected KeyAgreement(javax.crypto.KeyAgreementSpi, java.security.Provider, java.lang.String);
+    method public final java.security.Key doPhase(java.security.Key, boolean) throws java.lang.IllegalStateException, java.security.InvalidKeyException;
+    method public final byte[] generateSecret() throws java.lang.IllegalStateException;
+    method public final int generateSecret(byte[], int) throws java.lang.IllegalStateException, javax.crypto.ShortBufferException;
+    method public final javax.crypto.SecretKey generateSecret(java.lang.String) throws java.lang.IllegalStateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException;
+    method public final java.lang.String getAlgorithm();
+    method public static final javax.crypto.KeyAgreement getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static final javax.crypto.KeyAgreement getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static final javax.crypto.KeyAgreement getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final java.security.Provider getProvider();
+    method public final void init(java.security.Key) throws java.security.InvalidKeyException;
+    method public final void init(java.security.Key, java.security.SecureRandom) throws java.security.InvalidKeyException;
+    method public final void init(java.security.Key, java.security.spec.AlgorithmParameterSpec) throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException;
+    method public final void init(java.security.Key, java.security.spec.AlgorithmParameterSpec, java.security.SecureRandom) throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException;
+  }
+
+  public abstract class KeyAgreementSpi {
+    ctor public KeyAgreementSpi();
+    method protected abstract java.security.Key engineDoPhase(java.security.Key, boolean) throws java.lang.IllegalStateException, java.security.InvalidKeyException;
+    method protected abstract byte[] engineGenerateSecret() throws java.lang.IllegalStateException;
+    method protected abstract int engineGenerateSecret(byte[], int) throws java.lang.IllegalStateException, javax.crypto.ShortBufferException;
+    method protected abstract javax.crypto.SecretKey engineGenerateSecret(java.lang.String) throws java.lang.IllegalStateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException;
+    method protected abstract void engineInit(java.security.Key, java.security.SecureRandom) throws java.security.InvalidKeyException;
+    method protected abstract void engineInit(java.security.Key, java.security.spec.AlgorithmParameterSpec, java.security.SecureRandom) throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException;
+  }
+
+  public class KeyGenerator {
+    ctor protected KeyGenerator(javax.crypto.KeyGeneratorSpi, java.security.Provider, java.lang.String);
+    method public final javax.crypto.SecretKey generateKey();
+    method public final java.lang.String getAlgorithm();
+    method public static final javax.crypto.KeyGenerator getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static final javax.crypto.KeyGenerator getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static final javax.crypto.KeyGenerator getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final java.security.Provider getProvider();
+    method public final void init(java.security.spec.AlgorithmParameterSpec) throws java.security.InvalidAlgorithmParameterException;
+    method public final void init(java.security.spec.AlgorithmParameterSpec, java.security.SecureRandom) throws java.security.InvalidAlgorithmParameterException;
+    method public final void init(int);
+    method public final void init(int, java.security.SecureRandom);
+    method public final void init(java.security.SecureRandom);
+  }
+
+  public abstract class KeyGeneratorSpi {
+    ctor public KeyGeneratorSpi();
+    method protected abstract javax.crypto.SecretKey engineGenerateKey();
+    method protected abstract void engineInit(java.security.spec.AlgorithmParameterSpec, java.security.SecureRandom) throws java.security.InvalidAlgorithmParameterException;
+    method protected abstract void engineInit(int, java.security.SecureRandom);
+    method protected abstract void engineInit(java.security.SecureRandom);
+  }
+
+  public class Mac implements java.lang.Cloneable {
+    ctor protected Mac(javax.crypto.MacSpi, java.security.Provider, java.lang.String);
+    method public final java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public final byte[] doFinal() throws java.lang.IllegalStateException;
+    method public final void doFinal(byte[], int) throws java.lang.IllegalStateException, javax.crypto.ShortBufferException;
+    method public final byte[] doFinal(byte[]) throws java.lang.IllegalStateException;
+    method public final java.lang.String getAlgorithm();
+    method public static final javax.crypto.Mac getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static final javax.crypto.Mac getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static final javax.crypto.Mac getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final int getMacLength();
+    method public final java.security.Provider getProvider();
+    method public final void init(java.security.Key, java.security.spec.AlgorithmParameterSpec) throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException;
+    method public final void init(java.security.Key) throws java.security.InvalidKeyException;
+    method public final void reset();
+    method public final void update(byte) throws java.lang.IllegalStateException;
+    method public final void update(byte[], int, int) throws java.lang.IllegalStateException;
+    method public final void update(byte[]) throws java.lang.IllegalStateException;
+    method public final void update(java.nio.ByteBuffer);
+  }
+
+  public abstract class MacSpi {
+    ctor public MacSpi();
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method protected abstract byte[] engineDoFinal();
+    method protected abstract int engineGetMacLength();
+    method protected abstract void engineInit(java.security.Key, java.security.spec.AlgorithmParameterSpec) throws java.security.InvalidAlgorithmParameterException, java.security.InvalidKeyException;
+    method protected abstract void engineReset();
+    method protected abstract void engineUpdate(byte);
+    method protected abstract void engineUpdate(byte[], int, int);
+    method protected void engineUpdate(java.nio.ByteBuffer);
+  }
+
+  public class NoSuchPaddingException extends java.security.GeneralSecurityException {
+    ctor public NoSuchPaddingException(java.lang.String);
+    ctor public NoSuchPaddingException();
+  }
+
+  public class NullCipher extends javax.crypto.Cipher {
+    ctor public NullCipher();
+  }
+
+  public class SealedObject implements java.io.Serializable {
+    ctor public SealedObject(java.io.Serializable, javax.crypto.Cipher) throws java.io.IOException, javax.crypto.IllegalBlockSizeException;
+    ctor protected SealedObject(javax.crypto.SealedObject);
+    method public final java.lang.String getAlgorithm();
+    method public final java.lang.Object getObject(java.security.Key) throws java.lang.ClassNotFoundException, java.io.IOException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException;
+    method public final java.lang.Object getObject(javax.crypto.Cipher) throws javax.crypto.BadPaddingException, java.lang.ClassNotFoundException, java.io.IOException, javax.crypto.IllegalBlockSizeException;
+    method public final java.lang.Object getObject(java.security.Key, java.lang.String) throws java.lang.ClassNotFoundException, java.io.IOException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    field protected byte[] encodedParams;
+  }
+
+  public abstract interface SecretKey implements java.security.Key {
+    field public static final long serialVersionUID = -4795878709595146952L; // 0xbd719db928b8f538L
+  }
+
+  public class SecretKeyFactory {
+    ctor protected SecretKeyFactory(javax.crypto.SecretKeyFactorySpi, java.security.Provider, java.lang.String);
+    method public final javax.crypto.SecretKey generateSecret(java.security.spec.KeySpec) throws java.security.spec.InvalidKeySpecException;
+    method public final java.lang.String getAlgorithm();
+    method public static final javax.crypto.SecretKeyFactory getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static final javax.crypto.SecretKeyFactory getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static final javax.crypto.SecretKeyFactory getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final java.security.spec.KeySpec getKeySpec(javax.crypto.SecretKey, java.lang.Class) throws java.security.spec.InvalidKeySpecException;
+    method public final java.security.Provider getProvider();
+    method public final javax.crypto.SecretKey translateKey(javax.crypto.SecretKey) throws java.security.InvalidKeyException;
+  }
+
+  public abstract class SecretKeyFactorySpi {
+    ctor public SecretKeyFactorySpi();
+    method protected abstract javax.crypto.SecretKey engineGenerateSecret(java.security.spec.KeySpec) throws java.security.spec.InvalidKeySpecException;
+    method protected abstract java.security.spec.KeySpec engineGetKeySpec(javax.crypto.SecretKey, java.lang.Class) throws java.security.spec.InvalidKeySpecException;
+    method protected abstract javax.crypto.SecretKey engineTranslateKey(javax.crypto.SecretKey) throws java.security.InvalidKeyException;
+  }
+
+  public class ShortBufferException extends java.security.GeneralSecurityException {
+    ctor public ShortBufferException(java.lang.String);
+    ctor public ShortBufferException();
+  }
+
+}
+
+package javax.crypto.interfaces {
+
+  public abstract interface DHKey {
+    method public abstract javax.crypto.spec.DHParameterSpec getParams();
+  }
+
+  public abstract interface DHPrivateKey implements javax.crypto.interfaces.DHKey java.security.PrivateKey {
+    method public abstract java.math.BigInteger getX();
+    field public static final long serialVersionUID = 2211791113380396553L; // 0x1eb1dc4c8e677e09L
+  }
+
+  public abstract interface DHPublicKey implements javax.crypto.interfaces.DHKey java.security.PublicKey {
+    method public abstract java.math.BigInteger getY();
+    field public static final long serialVersionUID = -6628103563352519193L; // 0xa4043eed23df4de7L
+  }
+
+  public abstract interface PBEKey implements javax.crypto.SecretKey {
+    method public abstract int getIterationCount();
+    method public abstract char[] getPassword();
+    method public abstract byte[] getSalt();
+    field public static final long serialVersionUID = -1430015993304333921L; // 0xec279007d7f7c19fL
+  }
+
+}
+
+package javax.crypto.spec {
+
+  public class DESKeySpec implements java.security.spec.KeySpec {
+    ctor public DESKeySpec(byte[]) throws java.security.InvalidKeyException;
+    ctor public DESKeySpec(byte[], int) throws java.security.InvalidKeyException;
+    method public byte[] getKey();
+    method public static boolean isParityAdjusted(byte[], int) throws java.security.InvalidKeyException;
+    method public static boolean isWeak(byte[], int) throws java.security.InvalidKeyException;
+    field public static final int DES_KEY_LEN = 8; // 0x8
+  }
+
+  public class DESedeKeySpec implements java.security.spec.KeySpec {
+    ctor public DESedeKeySpec(byte[]) throws java.security.InvalidKeyException;
+    ctor public DESedeKeySpec(byte[], int) throws java.security.InvalidKeyException;
+    method public byte[] getKey();
+    method public static boolean isParityAdjusted(byte[], int) throws java.security.InvalidKeyException;
+    field public static final int DES_EDE_KEY_LEN = 24; // 0x18
+  }
+
+  public class DHGenParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+    ctor public DHGenParameterSpec(int, int);
+    method public int getExponentSize();
+    method public int getPrimeSize();
+  }
+
+  public class DHParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+    ctor public DHParameterSpec(java.math.BigInteger, java.math.BigInteger);
+    ctor public DHParameterSpec(java.math.BigInteger, java.math.BigInteger, int);
+    method public java.math.BigInteger getG();
+    method public int getL();
+    method public java.math.BigInteger getP();
+  }
+
+  public class DHPrivateKeySpec implements java.security.spec.KeySpec {
+    ctor public DHPrivateKeySpec(java.math.BigInteger, java.math.BigInteger, java.math.BigInteger);
+    method public java.math.BigInteger getG();
+    method public java.math.BigInteger getP();
+    method public java.math.BigInteger getX();
+  }
+
+  public class DHPublicKeySpec implements java.security.spec.KeySpec {
+    ctor public DHPublicKeySpec(java.math.BigInteger, java.math.BigInteger, java.math.BigInteger);
+    method public java.math.BigInteger getG();
+    method public java.math.BigInteger getP();
+    method public java.math.BigInteger getY();
+  }
+
+  public class IvParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+    ctor public IvParameterSpec(byte[]);
+    ctor public IvParameterSpec(byte[], int, int);
+    method public byte[] getIV();
+  }
+
+  public class OAEPParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+    ctor public OAEPParameterSpec(java.lang.String, java.lang.String, java.security.spec.AlgorithmParameterSpec, javax.crypto.spec.PSource);
+    method public java.lang.String getDigestAlgorithm();
+    method public java.lang.String getMGFAlgorithm();
+    method public java.security.spec.AlgorithmParameterSpec getMGFParameters();
+    method public javax.crypto.spec.PSource getPSource();
+    field public static final javax.crypto.spec.OAEPParameterSpec DEFAULT;
+  }
+
+  public class PBEKeySpec implements java.security.spec.KeySpec {
+    ctor public PBEKeySpec(char[]);
+    ctor public PBEKeySpec(char[], byte[], int, int);
+    ctor public PBEKeySpec(char[], byte[], int);
+    method public final void clearPassword();
+    method public final int getIterationCount();
+    method public final int getKeyLength();
+    method public final char[] getPassword();
+    method public final byte[] getSalt();
+  }
+
+  public class PBEParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+    ctor public PBEParameterSpec(byte[], int);
+    method public int getIterationCount();
+    method public byte[] getSalt();
+  }
+
+  public class PSource {
+    ctor protected PSource(java.lang.String);
+    method public java.lang.String getAlgorithm();
+  }
+
+  public static final class PSource.PSpecified extends javax.crypto.spec.PSource {
+    ctor public PSource.PSpecified(byte[]);
+    method public byte[] getValue();
+    field public static final javax.crypto.spec.PSource.PSpecified DEFAULT;
+  }
+
+  public class RC2ParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+    ctor public RC2ParameterSpec(int);
+    ctor public RC2ParameterSpec(int, byte[]);
+    ctor public RC2ParameterSpec(int, byte[], int);
+    method public int getEffectiveKeyBits();
+    method public byte[] getIV();
+  }
+
+  public class RC5ParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+    ctor public RC5ParameterSpec(int, int, int);
+    ctor public RC5ParameterSpec(int, int, int, byte[]);
+    ctor public RC5ParameterSpec(int, int, int, byte[], int);
+    method public byte[] getIV();
+    method public int getRounds();
+    method public int getVersion();
+    method public int getWordSize();
+  }
+
+  public class SecretKeySpec implements java.security.spec.KeySpec javax.crypto.SecretKey java.io.Serializable {
+    ctor public SecretKeySpec(byte[], java.lang.String);
+    ctor public SecretKeySpec(byte[], int, int, java.lang.String);
+    method public java.lang.String getAlgorithm();
+    method public byte[] getEncoded();
+    method public java.lang.String getFormat();
+  }
+
+}
+
+package javax.microedition.khronos.egl {
+
+  public abstract interface EGL {
+  }
+
+  public abstract interface EGL10 implements javax.microedition.khronos.egl.EGL {
+    method public abstract boolean eglChooseConfig(javax.microedition.khronos.egl.EGLDisplay, int[], javax.microedition.khronos.egl.EGLConfig[], int, int[]);
+    method public abstract boolean eglCopyBuffers(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLSurface, java.lang.Object);
+    method public abstract javax.microedition.khronos.egl.EGLContext eglCreateContext(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig, javax.microedition.khronos.egl.EGLContext, int[]);
+    method public abstract javax.microedition.khronos.egl.EGLSurface eglCreatePbufferSurface(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig, int[]);
+    method public abstract javax.microedition.khronos.egl.EGLSurface eglCreatePixmapSurface(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig, java.lang.Object, int[]);
+    method public abstract javax.microedition.khronos.egl.EGLSurface eglCreateWindowSurface(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig, java.lang.Object, int[]);
+    method public abstract boolean eglDestroyContext(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLContext);
+    method public abstract boolean eglDestroySurface(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLSurface);
+    method public abstract boolean eglGetConfigAttrib(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig, int, int[]);
+    method public abstract boolean eglGetConfigs(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig[], int, int[]);
+    method public abstract javax.microedition.khronos.egl.EGLContext eglGetCurrentContext();
+    method public abstract javax.microedition.khronos.egl.EGLDisplay eglGetCurrentDisplay();
+    method public abstract javax.microedition.khronos.egl.EGLSurface eglGetCurrentSurface(int);
+    method public abstract javax.microedition.khronos.egl.EGLDisplay eglGetDisplay(java.lang.Object);
+    method public abstract int eglGetError();
+    method public abstract boolean eglInitialize(javax.microedition.khronos.egl.EGLDisplay, int[]);
+    method public abstract boolean eglMakeCurrent(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLSurface, javax.microedition.khronos.egl.EGLSurface, javax.microedition.khronos.egl.EGLContext);
+    method public abstract boolean eglQueryContext(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLContext, int, int[]);
+    method public abstract java.lang.String eglQueryString(javax.microedition.khronos.egl.EGLDisplay, int);
+    method public abstract boolean eglQuerySurface(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLSurface, int, int[]);
+    method public abstract boolean eglSwapBuffers(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLSurface);
+    method public abstract boolean eglTerminate(javax.microedition.khronos.egl.EGLDisplay);
+    method public abstract boolean eglWaitGL();
+    method public abstract boolean eglWaitNative(int, java.lang.Object);
+    field public static final int EGL_ALPHA_FORMAT = 12424; // 0x3088
+    field public static final int EGL_ALPHA_MASK_SIZE = 12350; // 0x303e
+    field public static final int EGL_ALPHA_SIZE = 12321; // 0x3021
+    field public static final int EGL_BAD_ACCESS = 12290; // 0x3002
+    field public static final int EGL_BAD_ALLOC = 12291; // 0x3003
+    field public static final int EGL_BAD_ATTRIBUTE = 12292; // 0x3004
+    field public static final int EGL_BAD_CONFIG = 12293; // 0x3005
+    field public static final int EGL_BAD_CONTEXT = 12294; // 0x3006
+    field public static final int EGL_BAD_CURRENT_SURFACE = 12295; // 0x3007
+    field public static final int EGL_BAD_DISPLAY = 12296; // 0x3008
+    field public static final int EGL_BAD_MATCH = 12297; // 0x3009
+    field public static final int EGL_BAD_NATIVE_PIXMAP = 12298; // 0x300a
+    field public static final int EGL_BAD_NATIVE_WINDOW = 12299; // 0x300b
+    field public static final int EGL_BAD_PARAMETER = 12300; // 0x300c
+    field public static final int EGL_BAD_SURFACE = 12301; // 0x300d
+    field public static final int EGL_BLUE_SIZE = 12322; // 0x3022
+    field public static final int EGL_BUFFER_SIZE = 12320; // 0x3020
+    field public static final int EGL_COLORSPACE = 12423; // 0x3087
+    field public static final int EGL_COLOR_BUFFER_TYPE = 12351; // 0x303f
+    field public static final int EGL_CONFIG_CAVEAT = 12327; // 0x3027
+    field public static final int EGL_CONFIG_ID = 12328; // 0x3028
+    field public static final int EGL_CORE_NATIVE_ENGINE = 12379; // 0x305b
+    field public static final java.lang.Object EGL_DEFAULT_DISPLAY;
+    field public static final int EGL_DEPTH_SIZE = 12325; // 0x3025
+    field public static final int EGL_DONT_CARE = -1; // 0xffffffff
+    field public static final int EGL_DRAW = 12377; // 0x3059
+    field public static final int EGL_EXTENSIONS = 12373; // 0x3055
+    field public static final int EGL_GREEN_SIZE = 12323; // 0x3023
+    field public static final int EGL_HEIGHT = 12374; // 0x3056
+    field public static final int EGL_HORIZONTAL_RESOLUTION = 12432; // 0x3090
+    field public static final int EGL_LARGEST_PBUFFER = 12376; // 0x3058
+    field public static final int EGL_LEVEL = 12329; // 0x3029
+    field public static final int EGL_LUMINANCE_BUFFER = 12431; // 0x308f
+    field public static final int EGL_LUMINANCE_SIZE = 12349; // 0x303d
+    field public static final int EGL_MAX_PBUFFER_HEIGHT = 12330; // 0x302a
+    field public static final int EGL_MAX_PBUFFER_PIXELS = 12331; // 0x302b
+    field public static final int EGL_MAX_PBUFFER_WIDTH = 12332; // 0x302c
+    field public static final int EGL_NATIVE_RENDERABLE = 12333; // 0x302d
+    field public static final int EGL_NATIVE_VISUAL_ID = 12334; // 0x302e
+    field public static final int EGL_NATIVE_VISUAL_TYPE = 12335; // 0x302f
+    field public static final int EGL_NONE = 12344; // 0x3038
+    field public static final int EGL_NON_CONFORMANT_CONFIG = 12369; // 0x3051
+    field public static final int EGL_NOT_INITIALIZED = 12289; // 0x3001
+    field public static final javax.microedition.khronos.egl.EGLContext EGL_NO_CONTEXT;
+    field public static final javax.microedition.khronos.egl.EGLDisplay EGL_NO_DISPLAY;
+    field public static final javax.microedition.khronos.egl.EGLSurface EGL_NO_SURFACE;
+    field public static final int EGL_PBUFFER_BIT = 1; // 0x1
+    field public static final int EGL_PIXEL_ASPECT_RATIO = 12434; // 0x3092
+    field public static final int EGL_PIXMAP_BIT = 2; // 0x2
+    field public static final int EGL_READ = 12378; // 0x305a
+    field public static final int EGL_RED_SIZE = 12324; // 0x3024
+    field public static final int EGL_RENDERABLE_TYPE = 12352; // 0x3040
+    field public static final int EGL_RENDER_BUFFER = 12422; // 0x3086
+    field public static final int EGL_RGB_BUFFER = 12430; // 0x308e
+    field public static final int EGL_SAMPLES = 12337; // 0x3031
+    field public static final int EGL_SAMPLE_BUFFERS = 12338; // 0x3032
+    field public static final int EGL_SINGLE_BUFFER = 12421; // 0x3085
+    field public static final int EGL_SLOW_CONFIG = 12368; // 0x3050
+    field public static final int EGL_STENCIL_SIZE = 12326; // 0x3026
+    field public static final int EGL_SUCCESS = 12288; // 0x3000
+    field public static final int EGL_SURFACE_TYPE = 12339; // 0x3033
+    field public static final int EGL_TRANSPARENT_BLUE_VALUE = 12341; // 0x3035
+    field public static final int EGL_TRANSPARENT_GREEN_VALUE = 12342; // 0x3036
+    field public static final int EGL_TRANSPARENT_RED_VALUE = 12343; // 0x3037
+    field public static final int EGL_TRANSPARENT_RGB = 12370; // 0x3052
+    field public static final int EGL_TRANSPARENT_TYPE = 12340; // 0x3034
+    field public static final int EGL_VENDOR = 12371; // 0x3053
+    field public static final int EGL_VERSION = 12372; // 0x3054
+    field public static final int EGL_VERTICAL_RESOLUTION = 12433; // 0x3091
+    field public static final int EGL_WIDTH = 12375; // 0x3057
+    field public static final int EGL_WINDOW_BIT = 4; // 0x4
+  }
+
+  public abstract interface EGL11 implements javax.microedition.khronos.egl.EGL10 {
+    field public static final int EGL_CONTEXT_LOST = 12302; // 0x300e
+  }
+
+  public abstract class EGLConfig {
+    ctor public EGLConfig();
+  }
+
+  public abstract class EGLContext {
+    ctor public EGLContext();
+    method public static javax.microedition.khronos.egl.EGL getEGL();
+    method public abstract javax.microedition.khronos.opengles.GL getGL();
+  }
+
+  public abstract class EGLDisplay {
+    ctor public EGLDisplay();
+  }
+
+  public abstract class EGLSurface {
+    ctor public EGLSurface();
+  }
+
+}
+
+package javax.microedition.khronos.opengles {
+
+  public abstract interface GL {
+  }
+
+  public abstract interface GL10 implements javax.microedition.khronos.opengles.GL {
+    method public abstract void glActiveTexture(int);
+    method public abstract void glAlphaFunc(int, float);
+    method public abstract void glAlphaFuncx(int, int);
+    method public abstract void glBindTexture(int, int);
+    method public abstract void glBlendFunc(int, int);
+    method public abstract void glClear(int);
+    method public abstract void glClearColor(float, float, float, float);
+    method public abstract void glClearColorx(int, int, int, int);
+    method public abstract void glClearDepthf(float);
+    method public abstract void glClearDepthx(int);
+    method public abstract void glClearStencil(int);
+    method public abstract void glClientActiveTexture(int);
+    method public abstract void glColor4f(float, float, float, float);
+    method public abstract void glColor4x(int, int, int, int);
+    method public abstract void glColorMask(boolean, boolean, boolean, boolean);
+    method public abstract void glColorPointer(int, int, int, java.nio.Buffer);
+    method public abstract void glCompressedTexImage2D(int, int, int, int, int, int, int, java.nio.Buffer);
+    method public abstract void glCompressedTexSubImage2D(int, int, int, int, int, int, int, int, java.nio.Buffer);
+    method public abstract void glCopyTexImage2D(int, int, int, int, int, int, int, int);
+    method public abstract void glCopyTexSubImage2D(int, int, int, int, int, int, int, int);
+    method public abstract void glCullFace(int);
+    method public abstract void glDeleteTextures(int, int[], int);
+    method public abstract void glDeleteTextures(int, java.nio.IntBuffer);
+    method public abstract void glDepthFunc(int);
+    method public abstract void glDepthMask(boolean);
+    method public abstract void glDepthRangef(float, float);
+    method public abstract void glDepthRangex(int, int);
+    method public abstract void glDisable(int);
+    method public abstract void glDisableClientState(int);
+    method public abstract void glDrawArrays(int, int, int);
+    method public abstract void glDrawElements(int, int, int, java.nio.Buffer);
+    method public abstract void glEnable(int);
+    method public abstract void glEnableClientState(int);
+    method public abstract void glFinish();
+    method public abstract void glFlush();
+    method public abstract void glFogf(int, float);
+    method public abstract void glFogfv(int, float[], int);
+    method public abstract void glFogfv(int, java.nio.FloatBuffer);
+    method public abstract void glFogx(int, int);
+    method public abstract void glFogxv(int, int[], int);
+    method public abstract void glFogxv(int, java.nio.IntBuffer);
+    method public abstract void glFrontFace(int);
+    method public abstract void glFrustumf(float, float, float, float, float, float);
+    method public abstract void glFrustumx(int, int, int, int, int, int);
+    method public abstract void glGenTextures(int, int[], int);
+    method public abstract void glGenTextures(int, java.nio.IntBuffer);
+    method public abstract int glGetError();
+    method public abstract void glGetIntegerv(int, int[], int);
+    method public abstract void glGetIntegerv(int, java.nio.IntBuffer);
+    method public abstract java.lang.String glGetString(int);
+    method public abstract void glHint(int, int);
+    method public abstract void glLightModelf(int, float);
+    method public abstract void glLightModelfv(int, float[], int);
+    method public abstract void glLightModelfv(int, java.nio.FloatBuffer);
+    method public abstract void glLightModelx(int, int);
+    method public abstract void glLightModelxv(int, int[], int);
+    method public abstract void glLightModelxv(int, java.nio.IntBuffer);
+    method public abstract void glLightf(int, int, float);
+    method public abstract void glLightfv(int, int, float[], int);
+    method public abstract void glLightfv(int, int, java.nio.FloatBuffer);
+    method public abstract void glLightx(int, int, int);
+    method public abstract void glLightxv(int, int, int[], int);
+    method public abstract void glLightxv(int, int, java.nio.IntBuffer);
+    method public abstract void glLineWidth(float);
+    method public abstract void glLineWidthx(int);
+    method public abstract void glLoadIdentity();
+    method public abstract void glLoadMatrixf(float[], int);
+    method public abstract void glLoadMatrixf(java.nio.FloatBuffer);
+    method public abstract void glLoadMatrixx(int[], int);
+    method public abstract void glLoadMatrixx(java.nio.IntBuffer);
+    method public abstract void glLogicOp(int);
+    method public abstract void glMaterialf(int, int, float);
+    method public abstract void glMaterialfv(int, int, float[], int);
+    method public abstract void glMaterialfv(int, int, java.nio.FloatBuffer);
+    method public abstract void glMaterialx(int, int, int);
+    method public abstract void glMaterialxv(int, int, int[], int);
+    method public abstract void glMaterialxv(int, int, java.nio.IntBuffer);
+    method public abstract void glMatrixMode(int);
+    method public abstract void glMultMatrixf(float[], int);
+    method public abstract void glMultMatrixf(java.nio.FloatBuffer);
+    method public abstract void glMultMatrixx(int[], int);
+    method public abstract void glMultMatrixx(java.nio.IntBuffer);
+    method public abstract void glMultiTexCoord4f(int, float, float, float, float);
+    method public abstract void glMultiTexCoord4x(int, int, int, int, int);
+    method public abstract void glNormal3f(float, float, float);
+    method public abstract void glNormal3x(int, int, int);
+    method public abstract void glNormalPointer(int, int, java.nio.Buffer);
+    method public abstract void glOrthof(float, float, float, float, float, float);
+    method public abstract void glOrthox(int, int, int, int, int, int);
+    method public abstract void glPixelStorei(int, int);
+    method public abstract void glPointSize(float);
+    method public abstract void glPointSizex(int);
+    method public abstract void glPolygonOffset(float, float);
+    method public abstract void glPolygonOffsetx(int, int);
+    method public abstract void glPopMatrix();
+    method public abstract void glPushMatrix();
+    method public abstract void glReadPixels(int, int, int, int, int, int, java.nio.Buffer);
+    method public abstract void glRotatef(float, float, float, float);
+    method public abstract void glRotatex(int, int, int, int);
+    method public abstract void glSampleCoverage(float, boolean);
+    method public abstract void glSampleCoveragex(int, boolean);
+    method public abstract void glScalef(float, float, float);
+    method public abstract void glScalex(int, int, int);
+    method public abstract void glScissor(int, int, int, int);
+    method public abstract void glShadeModel(int);
+    method public abstract void glStencilFunc(int, int, int);
+    method public abstract void glStencilMask(int);
+    method public abstract void glStencilOp(int, int, int);
+    method public abstract void glTexCoordPointer(int, int, int, java.nio.Buffer);
+    method public abstract void glTexEnvf(int, int, float);
+    method public abstract void glTexEnvfv(int, int, float[], int);
+    method public abstract void glTexEnvfv(int, int, java.nio.FloatBuffer);
+    method public abstract void glTexEnvx(int, int, int);
+    method public abstract void glTexEnvxv(int, int, int[], int);
+    method public abstract void glTexEnvxv(int, int, java.nio.IntBuffer);
+    method public abstract void glTexImage2D(int, int, int, int, int, int, int, int, java.nio.Buffer);
+    method public abstract void glTexParameterf(int, int, float);
+    method public abstract void glTexParameterx(int, int, int);
+    method public abstract void glTexSubImage2D(int, int, int, int, int, int, int, int, java.nio.Buffer);
+    method public abstract void glTranslatef(float, float, float);
+    method public abstract void glTranslatex(int, int, int);
+    method public abstract void glVertexPointer(int, int, int, java.nio.Buffer);
+    method public abstract void glViewport(int, int, int, int);
+    field public static final int GL_ADD = 260; // 0x104
+    field public static final int GL_ALIASED_LINE_WIDTH_RANGE = 33902; // 0x846e
+    field public static final int GL_ALIASED_POINT_SIZE_RANGE = 33901; // 0x846d
+    field public static final int GL_ALPHA = 6406; // 0x1906
+    field public static final int GL_ALPHA_BITS = 3413; // 0xd55
+    field public static final int GL_ALPHA_TEST = 3008; // 0xbc0
+    field public static final int GL_ALWAYS = 519; // 0x207
+    field public static final int GL_AMBIENT = 4608; // 0x1200
+    field public static final int GL_AMBIENT_AND_DIFFUSE = 5634; // 0x1602
+    field public static final int GL_AND = 5377; // 0x1501
+    field public static final int GL_AND_INVERTED = 5380; // 0x1504
+    field public static final int GL_AND_REVERSE = 5378; // 0x1502
+    field public static final int GL_BACK = 1029; // 0x405
+    field public static final int GL_BLEND = 3042; // 0xbe2
+    field public static final int GL_BLUE_BITS = 3412; // 0xd54
+    field public static final int GL_BYTE = 5120; // 0x1400
+    field public static final int GL_CCW = 2305; // 0x901
+    field public static final int GL_CLAMP_TO_EDGE = 33071; // 0x812f
+    field public static final int GL_CLEAR = 5376; // 0x1500
+    field public static final int GL_COLOR_ARRAY = 32886; // 0x8076
+    field public static final int GL_COLOR_BUFFER_BIT = 16384; // 0x4000
+    field public static final int GL_COLOR_LOGIC_OP = 3058; // 0xbf2
+    field public static final int GL_COLOR_MATERIAL = 2903; // 0xb57
+    field public static final int GL_COMPRESSED_TEXTURE_FORMATS = 34467; // 0x86a3
+    field public static final int GL_CONSTANT_ATTENUATION = 4615; // 0x1207
+    field public static final int GL_COPY = 5379; // 0x1503
+    field public static final int GL_COPY_INVERTED = 5388; // 0x150c
+    field public static final int GL_CULL_FACE = 2884; // 0xb44
+    field public static final int GL_CW = 2304; // 0x900
+    field public static final int GL_DECAL = 8449; // 0x2101
+    field public static final int GL_DECR = 7683; // 0x1e03
+    field public static final int GL_DEPTH_BITS = 3414; // 0xd56
+    field public static final int GL_DEPTH_BUFFER_BIT = 256; // 0x100
+    field public static final int GL_DEPTH_TEST = 2929; // 0xb71
+    field public static final int GL_DIFFUSE = 4609; // 0x1201
+    field public static final int GL_DITHER = 3024; // 0xbd0
+    field public static final int GL_DONT_CARE = 4352; // 0x1100
+    field public static final int GL_DST_ALPHA = 772; // 0x304
+    field public static final int GL_DST_COLOR = 774; // 0x306
+    field public static final int GL_EMISSION = 5632; // 0x1600
+    field public static final int GL_EQUAL = 514; // 0x202
+    field public static final int GL_EQUIV = 5385; // 0x1509
+    field public static final int GL_EXP = 2048; // 0x800
+    field public static final int GL_EXP2 = 2049; // 0x801
+    field public static final int GL_EXTENSIONS = 7939; // 0x1f03
+    field public static final int GL_FALSE = 0; // 0x0
+    field public static final int GL_FASTEST = 4353; // 0x1101
+    field public static final int GL_FIXED = 5132; // 0x140c
+    field public static final int GL_FLAT = 7424; // 0x1d00
+    field public static final int GL_FLOAT = 5126; // 0x1406
+    field public static final int GL_FOG = 2912; // 0xb60
+    field public static final int GL_FOG_COLOR = 2918; // 0xb66
+    field public static final int GL_FOG_DENSITY = 2914; // 0xb62
+    field public static final int GL_FOG_END = 2916; // 0xb64
+    field public static final int GL_FOG_HINT = 3156; // 0xc54
+    field public static final int GL_FOG_MODE = 2917; // 0xb65
+    field public static final int GL_FOG_START = 2915; // 0xb63
+    field public static final int GL_FRONT = 1028; // 0x404
+    field public static final int GL_FRONT_AND_BACK = 1032; // 0x408
+    field public static final int GL_GEQUAL = 518; // 0x206
+    field public static final int GL_GREATER = 516; // 0x204
+    field public static final int GL_GREEN_BITS = 3411; // 0xd53
+    field public static final int GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES = 35739; // 0x8b9b
+    field public static final int GL_IMPLEMENTATION_COLOR_READ_TYPE_OES = 35738; // 0x8b9a
+    field public static final int GL_INCR = 7682; // 0x1e02
+    field public static final int GL_INVALID_ENUM = 1280; // 0x500
+    field public static final int GL_INVALID_OPERATION = 1282; // 0x502
+    field public static final int GL_INVALID_VALUE = 1281; // 0x501
+    field public static final int GL_INVERT = 5386; // 0x150a
+    field public static final int GL_KEEP = 7680; // 0x1e00
+    field public static final int GL_LEQUAL = 515; // 0x203
+    field public static final int GL_LESS = 513; // 0x201
+    field public static final int GL_LIGHT0 = 16384; // 0x4000
+    field public static final int GL_LIGHT1 = 16385; // 0x4001
+    field public static final int GL_LIGHT2 = 16386; // 0x4002
+    field public static final int GL_LIGHT3 = 16387; // 0x4003
+    field public static final int GL_LIGHT4 = 16388; // 0x4004
+    field public static final int GL_LIGHT5 = 16389; // 0x4005
+    field public static final int GL_LIGHT6 = 16390; // 0x4006
+    field public static final int GL_LIGHT7 = 16391; // 0x4007
+    field public static final int GL_LIGHTING = 2896; // 0xb50
+    field public static final int GL_LIGHT_MODEL_AMBIENT = 2899; // 0xb53
+    field public static final int GL_LIGHT_MODEL_TWO_SIDE = 2898; // 0xb52
+    field public static final int GL_LINEAR = 9729; // 0x2601
+    field public static final int GL_LINEAR_ATTENUATION = 4616; // 0x1208
+    field public static final int GL_LINEAR_MIPMAP_LINEAR = 9987; // 0x2703
+    field public static final int GL_LINEAR_MIPMAP_NEAREST = 9985; // 0x2701
+    field public static final int GL_LINES = 1; // 0x1
+    field public static final int GL_LINE_LOOP = 2; // 0x2
+    field public static final int GL_LINE_SMOOTH = 2848; // 0xb20
+    field public static final int GL_LINE_SMOOTH_HINT = 3154; // 0xc52
+    field public static final int GL_LINE_STRIP = 3; // 0x3
+    field public static final int GL_LUMINANCE = 6409; // 0x1909
+    field public static final int GL_LUMINANCE_ALPHA = 6410; // 0x190a
+    field public static final int GL_MAX_ELEMENTS_INDICES = 33001; // 0x80e9
+    field public static final int GL_MAX_ELEMENTS_VERTICES = 33000; // 0x80e8
+    field public static final int GL_MAX_LIGHTS = 3377; // 0xd31
+    field public static final int GL_MAX_MODELVIEW_STACK_DEPTH = 3382; // 0xd36
+    field public static final int GL_MAX_PROJECTION_STACK_DEPTH = 3384; // 0xd38
+    field public static final int GL_MAX_TEXTURE_SIZE = 3379; // 0xd33
+    field public static final int GL_MAX_TEXTURE_STACK_DEPTH = 3385; // 0xd39
+    field public static final int GL_MAX_TEXTURE_UNITS = 34018; // 0x84e2
+    field public static final int GL_MAX_VIEWPORT_DIMS = 3386; // 0xd3a
+    field public static final int GL_MODELVIEW = 5888; // 0x1700
+    field public static final int GL_MODULATE = 8448; // 0x2100
+    field public static final int GL_MULTISAMPLE = 32925; // 0x809d
+    field public static final int GL_NAND = 5390; // 0x150e
+    field public static final int GL_NEAREST = 9728; // 0x2600
+    field public static final int GL_NEAREST_MIPMAP_LINEAR = 9986; // 0x2702
+    field public static final int GL_NEAREST_MIPMAP_NEAREST = 9984; // 0x2700
+    field public static final int GL_NEVER = 512; // 0x200
+    field public static final int GL_NICEST = 4354; // 0x1102
+    field public static final int GL_NOOP = 5381; // 0x1505
+    field public static final int GL_NOR = 5384; // 0x1508
+    field public static final int GL_NORMALIZE = 2977; // 0xba1
+    field public static final int GL_NORMAL_ARRAY = 32885; // 0x8075
+    field public static final int GL_NOTEQUAL = 517; // 0x205
+    field public static final int GL_NO_ERROR = 0; // 0x0
+    field public static final int GL_NUM_COMPRESSED_TEXTURE_FORMATS = 34466; // 0x86a2
+    field public static final int GL_ONE = 1; // 0x1
+    field public static final int GL_ONE_MINUS_DST_ALPHA = 773; // 0x305
+    field public static final int GL_ONE_MINUS_DST_COLOR = 775; // 0x307
+    field public static final int GL_ONE_MINUS_SRC_ALPHA = 771; // 0x303
+    field public static final int GL_ONE_MINUS_SRC_COLOR = 769; // 0x301
+    field public static final int GL_OR = 5383; // 0x1507
+    field public static final int GL_OR_INVERTED = 5389; // 0x150d
+    field public static final int GL_OR_REVERSE = 5387; // 0x150b
+    field public static final int GL_OUT_OF_MEMORY = 1285; // 0x505
+    field public static final int GL_PACK_ALIGNMENT = 3333; // 0xd05
+    field public static final int GL_PALETTE4_R5_G6_B5_OES = 35730; // 0x8b92
+    field public static final int GL_PALETTE4_RGB5_A1_OES = 35732; // 0x8b94
+    field public static final int GL_PALETTE4_RGB8_OES = 35728; // 0x8b90
+    field public static final int GL_PALETTE4_RGBA4_OES = 35731; // 0x8b93
+    field public static final int GL_PALETTE4_RGBA8_OES = 35729; // 0x8b91
+    field public static final int GL_PALETTE8_R5_G6_B5_OES = 35735; // 0x8b97
+    field public static final int GL_PALETTE8_RGB5_A1_OES = 35737; // 0x8b99
+    field public static final int GL_PALETTE8_RGB8_OES = 35733; // 0x8b95
+    field public static final int GL_PALETTE8_RGBA4_OES = 35736; // 0x8b98
+    field public static final int GL_PALETTE8_RGBA8_OES = 35734; // 0x8b96
+    field public static final int GL_PERSPECTIVE_CORRECTION_HINT = 3152; // 0xc50
+    field public static final int GL_POINTS = 0; // 0x0
+    field public static final int GL_POINT_FADE_THRESHOLD_SIZE = 33064; // 0x8128
+    field public static final int GL_POINT_SIZE = 2833; // 0xb11
+    field public static final int GL_POINT_SMOOTH = 2832; // 0xb10
+    field public static final int GL_POINT_SMOOTH_HINT = 3153; // 0xc51
+    field public static final int GL_POLYGON_OFFSET_FILL = 32823; // 0x8037
+    field public static final int GL_POLYGON_SMOOTH_HINT = 3155; // 0xc53
+    field public static final int GL_POSITION = 4611; // 0x1203
+    field public static final int GL_PROJECTION = 5889; // 0x1701
+    field public static final int GL_QUADRATIC_ATTENUATION = 4617; // 0x1209
+    field public static final int GL_RED_BITS = 3410; // 0xd52
+    field public static final int GL_RENDERER = 7937; // 0x1f01
+    field public static final int GL_REPEAT = 10497; // 0x2901
+    field public static final int GL_REPLACE = 7681; // 0x1e01
+    field public static final int GL_RESCALE_NORMAL = 32826; // 0x803a
+    field public static final int GL_RGB = 6407; // 0x1907
+    field public static final int GL_RGBA = 6408; // 0x1908
+    field public static final int GL_SAMPLE_ALPHA_TO_COVERAGE = 32926; // 0x809e
+    field public static final int GL_SAMPLE_ALPHA_TO_ONE = 32927; // 0x809f
+    field public static final int GL_SAMPLE_COVERAGE = 32928; // 0x80a0
+    field public static final int GL_SCISSOR_TEST = 3089; // 0xc11
+    field public static final int GL_SET = 5391; // 0x150f
+    field public static final int GL_SHININESS = 5633; // 0x1601
+    field public static final int GL_SHORT = 5122; // 0x1402
+    field public static final int GL_SMOOTH = 7425; // 0x1d01
+    field public static final int GL_SMOOTH_LINE_WIDTH_RANGE = 2850; // 0xb22
+    field public static final int GL_SMOOTH_POINT_SIZE_RANGE = 2834; // 0xb12
+    field public static final int GL_SPECULAR = 4610; // 0x1202
+    field public static final int GL_SPOT_CUTOFF = 4614; // 0x1206
+    field public static final int GL_SPOT_DIRECTION = 4612; // 0x1204
+    field public static final int GL_SPOT_EXPONENT = 4613; // 0x1205
+    field public static final int GL_SRC_ALPHA = 770; // 0x302
+    field public static final int GL_SRC_ALPHA_SATURATE = 776; // 0x308
+    field public static final int GL_SRC_COLOR = 768; // 0x300
+    field public static final int GL_STACK_OVERFLOW = 1283; // 0x503
+    field public static final int GL_STACK_UNDERFLOW = 1284; // 0x504
+    field public static final int GL_STENCIL_BITS = 3415; // 0xd57
+    field public static final int GL_STENCIL_BUFFER_BIT = 1024; // 0x400
+    field public static final int GL_STENCIL_TEST = 2960; // 0xb90
+    field public static final int GL_SUBPIXEL_BITS = 3408; // 0xd50
+    field public static final int GL_TEXTURE = 5890; // 0x1702
+    field public static final int GL_TEXTURE0 = 33984; // 0x84c0
+    field public static final int GL_TEXTURE1 = 33985; // 0x84c1
+    field public static final int GL_TEXTURE10 = 33994; // 0x84ca
+    field public static final int GL_TEXTURE11 = 33995; // 0x84cb
+    field public static final int GL_TEXTURE12 = 33996; // 0x84cc
+    field public static final int GL_TEXTURE13 = 33997; // 0x84cd
+    field public static final int GL_TEXTURE14 = 33998; // 0x84ce
+    field public static final int GL_TEXTURE15 = 33999; // 0x84cf
+    field public static final int GL_TEXTURE16 = 34000; // 0x84d0
+    field public static final int GL_TEXTURE17 = 34001; // 0x84d1
+    field public static final int GL_TEXTURE18 = 34002; // 0x84d2
+    field public static final int GL_TEXTURE19 = 34003; // 0x84d3
+    field public static final int GL_TEXTURE2 = 33986; // 0x84c2
+    field public static final int GL_TEXTURE20 = 34004; // 0x84d4
+    field public static final int GL_TEXTURE21 = 34005; // 0x84d5
+    field public static final int GL_TEXTURE22 = 34006; // 0x84d6
+    field public static final int GL_TEXTURE23 = 34007; // 0x84d7
+    field public static final int GL_TEXTURE24 = 34008; // 0x84d8
+    field public static final int GL_TEXTURE25 = 34009; // 0x84d9
+    field public static final int GL_TEXTURE26 = 34010; // 0x84da
+    field public static final int GL_TEXTURE27 = 34011; // 0x84db
+    field public static final int GL_TEXTURE28 = 34012; // 0x84dc
+    field public static final int GL_TEXTURE29 = 34013; // 0x84dd
+    field public static final int GL_TEXTURE3 = 33987; // 0x84c3
+    field public static final int GL_TEXTURE30 = 34014; // 0x84de
+    field public static final int GL_TEXTURE31 = 34015; // 0x84df
+    field public static final int GL_TEXTURE4 = 33988; // 0x84c4
+    field public static final int GL_TEXTURE5 = 33989; // 0x84c5
+    field public static final int GL_TEXTURE6 = 33990; // 0x84c6
+    field public static final int GL_TEXTURE7 = 33991; // 0x84c7
+    field public static final int GL_TEXTURE8 = 33992; // 0x84c8
+    field public static final int GL_TEXTURE9 = 33993; // 0x84c9
+    field public static final int GL_TEXTURE_2D = 3553; // 0xde1
+    field public static final int GL_TEXTURE_COORD_ARRAY = 32888; // 0x8078
+    field public static final int GL_TEXTURE_ENV = 8960; // 0x2300
+    field public static final int GL_TEXTURE_ENV_COLOR = 8705; // 0x2201
+    field public static final int GL_TEXTURE_ENV_MODE = 8704; // 0x2200
+    field public static final int GL_TEXTURE_MAG_FILTER = 10240; // 0x2800
+    field public static final int GL_TEXTURE_MIN_FILTER = 10241; // 0x2801
+    field public static final int GL_TEXTURE_WRAP_S = 10242; // 0x2802
+    field public static final int GL_TEXTURE_WRAP_T = 10243; // 0x2803
+    field public static final int GL_TRIANGLES = 4; // 0x4
+    field public static final int GL_TRIANGLE_FAN = 6; // 0x6
+    field public static final int GL_TRIANGLE_STRIP = 5; // 0x5
+    field public static final int GL_TRUE = 1; // 0x1
+    field public static final int GL_UNPACK_ALIGNMENT = 3317; // 0xcf5
+    field public static final int GL_UNSIGNED_BYTE = 5121; // 0x1401
+    field public static final int GL_UNSIGNED_SHORT = 5123; // 0x1403
+    field public static final int GL_UNSIGNED_SHORT_4_4_4_4 = 32819; // 0x8033
+    field public static final int GL_UNSIGNED_SHORT_5_5_5_1 = 32820; // 0x8034
+    field public static final int GL_UNSIGNED_SHORT_5_6_5 = 33635; // 0x8363
+    field public static final int GL_VENDOR = 7936; // 0x1f00
+    field public static final int GL_VERSION = 7938; // 0x1f02
+    field public static final int GL_VERTEX_ARRAY = 32884; // 0x8074
+    field public static final int GL_XOR = 5382; // 0x1506
+    field public static final int GL_ZERO = 0; // 0x0
+  }
+
+  public abstract interface GL10Ext implements javax.microedition.khronos.opengles.GL {
+    method public abstract int glQueryMatrixxOES(int[], int, int[], int);
+    method public abstract int glQueryMatrixxOES(java.nio.IntBuffer, java.nio.IntBuffer);
+  }
+
+  public abstract interface GL11 implements javax.microedition.khronos.opengles.GL10 {
+    method public abstract void glBindBuffer(int, int);
+    method public abstract void glBufferData(int, int, java.nio.Buffer, int);
+    method public abstract void glBufferSubData(int, int, int, java.nio.Buffer);
+    method public abstract void glClipPlanef(int, float[], int);
+    method public abstract void glClipPlanef(int, java.nio.FloatBuffer);
+    method public abstract void glClipPlanex(int, int[], int);
+    method public abstract void glClipPlanex(int, java.nio.IntBuffer);
+    method public abstract void glColor4ub(byte, byte, byte, byte);
+    method public abstract void glColorPointer(int, int, int, int);
+    method public abstract void glDeleteBuffers(int, int[], int);
+    method public abstract void glDeleteBuffers(int, java.nio.IntBuffer);
+    method public abstract void glDrawElements(int, int, int, int);
+    method public abstract void glGenBuffers(int, int[], int);
+    method public abstract void glGenBuffers(int, java.nio.IntBuffer);
+    method public abstract void glGetBooleanv(int, boolean[], int);
+    method public abstract void glGetBooleanv(int, java.nio.IntBuffer);
+    method public abstract void glGetBufferParameteriv(int, int, int[], int);
+    method public abstract void glGetBufferParameteriv(int, int, java.nio.IntBuffer);
+    method public abstract void glGetClipPlanef(int, float[], int);
+    method public abstract void glGetClipPlanef(int, java.nio.FloatBuffer);
+    method public abstract void glGetClipPlanex(int, int[], int);
+    method public abstract void glGetClipPlanex(int, java.nio.IntBuffer);
+    method public abstract void glGetFixedv(int, int[], int);
+    method public abstract void glGetFixedv(int, java.nio.IntBuffer);
+    method public abstract void glGetFloatv(int, float[], int);
+    method public abstract void glGetFloatv(int, java.nio.FloatBuffer);
+    method public abstract void glGetLightfv(int, int, float[], int);
+    method public abstract void glGetLightfv(int, int, java.nio.FloatBuffer);
+    method public abstract void glGetLightxv(int, int, int[], int);
+    method public abstract void glGetLightxv(int, int, java.nio.IntBuffer);
+    method public abstract void glGetMaterialfv(int, int, float[], int);
+    method public abstract void glGetMaterialfv(int, int, java.nio.FloatBuffer);
+    method public abstract void glGetMaterialxv(int, int, int[], int);
+    method public abstract void glGetMaterialxv(int, int, java.nio.IntBuffer);
+    method public abstract void glGetPointerv(int, java.nio.Buffer[]);
+    method public abstract void glGetTexEnviv(int, int, int[], int);
+    method public abstract void glGetTexEnviv(int, int, java.nio.IntBuffer);
+    method public abstract void glGetTexEnvxv(int, int, int[], int);
+    method public abstract void glGetTexEnvxv(int, int, java.nio.IntBuffer);
+    method public abstract void glGetTexParameterfv(int, int, float[], int);
+    method public abstract void glGetTexParameterfv(int, int, java.nio.FloatBuffer);
+    method public abstract void glGetTexParameteriv(int, int, int[], int);
+    method public abstract void glGetTexParameteriv(int, int, java.nio.IntBuffer);
+    method public abstract void glGetTexParameterxv(int, int, int[], int);
+    method public abstract void glGetTexParameterxv(int, int, java.nio.IntBuffer);
+    method public abstract boolean glIsBuffer(int);
+    method public abstract boolean glIsEnabled(int);
+    method public abstract boolean glIsTexture(int);
+    method public abstract void glNormalPointer(int, int, int);
+    method public abstract void glPointParameterf(int, float);
+    method public abstract void glPointParameterfv(int, float[], int);
+    method public abstract void glPointParameterfv(int, java.nio.FloatBuffer);
+    method public abstract void glPointParameterx(int, int);
+    method public abstract void glPointParameterxv(int, int[], int);
+    method public abstract void glPointParameterxv(int, java.nio.IntBuffer);
+    method public abstract void glPointSizePointerOES(int, int, java.nio.Buffer);
+    method public abstract void glTexCoordPointer(int, int, int, int);
+    method public abstract void glTexEnvi(int, int, int);
+    method public abstract void glTexEnviv(int, int, int[], int);
+    method public abstract void glTexEnviv(int, int, java.nio.IntBuffer);
+    method public abstract void glTexParameterfv(int, int, float[], int);
+    method public abstract void glTexParameterfv(int, int, java.nio.FloatBuffer);
+    method public abstract void glTexParameteri(int, int, int);
+    method public abstract void glTexParameteriv(int, int, int[], int);
+    method public abstract void glTexParameteriv(int, int, java.nio.IntBuffer);
+    method public abstract void glTexParameterxv(int, int, int[], int);
+    method public abstract void glTexParameterxv(int, int, java.nio.IntBuffer);
+    method public abstract void glVertexPointer(int, int, int, int);
+    field public static final int GL_ACTIVE_TEXTURE = 34016; // 0x84e0
+    field public static final int GL_ADD_SIGNED = 34164; // 0x8574
+    field public static final int GL_ALPHA_SCALE = 3356; // 0xd1c
+    field public static final int GL_ALPHA_TEST_FUNC = 3009; // 0xbc1
+    field public static final int GL_ALPHA_TEST_REF = 3010; // 0xbc2
+    field public static final int GL_ARRAY_BUFFER = 34962; // 0x8892
+    field public static final int GL_ARRAY_BUFFER_BINDING = 34964; // 0x8894
+    field public static final int GL_BLEND_DST = 3040; // 0xbe0
+    field public static final int GL_BLEND_SRC = 3041; // 0xbe1
+    field public static final int GL_BUFFER_ACCESS = 35003; // 0x88bb
+    field public static final int GL_BUFFER_SIZE = 34660; // 0x8764
+    field public static final int GL_BUFFER_USAGE = 34661; // 0x8765
+    field public static final int GL_CLIENT_ACTIVE_TEXTURE = 34017; // 0x84e1
+    field public static final int GL_CLIP_PLANE0 = 12288; // 0x3000
+    field public static final int GL_CLIP_PLANE1 = 12289; // 0x3001
+    field public static final int GL_CLIP_PLANE2 = 12290; // 0x3002
+    field public static final int GL_CLIP_PLANE3 = 12291; // 0x3003
+    field public static final int GL_CLIP_PLANE4 = 12292; // 0x3004
+    field public static final int GL_CLIP_PLANE5 = 12293; // 0x3005
+    field public static final int GL_COLOR_ARRAY_BUFFER_BINDING = 34968; // 0x8898
+    field public static final int GL_COLOR_ARRAY_POINTER = 32912; // 0x8090
+    field public static final int GL_COLOR_ARRAY_SIZE = 32897; // 0x8081
+    field public static final int GL_COLOR_ARRAY_STRIDE = 32899; // 0x8083
+    field public static final int GL_COLOR_ARRAY_TYPE = 32898; // 0x8082
+    field public static final int GL_COLOR_CLEAR_VALUE = 3106; // 0xc22
+    field public static final int GL_COLOR_WRITEMASK = 3107; // 0xc23
+    field public static final int GL_COMBINE = 34160; // 0x8570
+    field public static final int GL_COMBINE_ALPHA = 34162; // 0x8572
+    field public static final int GL_COMBINE_RGB = 34161; // 0x8571
+    field public static final int GL_CONSTANT = 34166; // 0x8576
+    field public static final int GL_COORD_REPLACE_OES = 34914; // 0x8862
+    field public static final int GL_CULL_FACE_MODE = 2885; // 0xb45
+    field public static final int GL_CURRENT_COLOR = 2816; // 0xb00
+    field public static final int GL_CURRENT_NORMAL = 2818; // 0xb02
+    field public static final int GL_CURRENT_TEXTURE_COORDS = 2819; // 0xb03
+    field public static final int GL_DEPTH_CLEAR_VALUE = 2931; // 0xb73
+    field public static final int GL_DEPTH_FUNC = 2932; // 0xb74
+    field public static final int GL_DEPTH_RANGE = 2928; // 0xb70
+    field public static final int GL_DEPTH_WRITEMASK = 2930; // 0xb72
+    field public static final int GL_DOT3_RGB = 34478; // 0x86ae
+    field public static final int GL_DOT3_RGBA = 34479; // 0x86af
+    field public static final int GL_DYNAMIC_DRAW = 35048; // 0x88e8
+    field public static final int GL_ELEMENT_ARRAY_BUFFER = 34963; // 0x8893
+    field public static final int GL_ELEMENT_ARRAY_BUFFER_BINDING = 34965; // 0x8895
+    field public static final int GL_FRONT_FACE = 2886; // 0xb46
+    field public static final int GL_GENERATE_MIPMAP = 33169; // 0x8191
+    field public static final int GL_GENERATE_MIPMAP_HINT = 33170; // 0x8192
+    field public static final int GL_INTERPOLATE = 34165; // 0x8575
+    field public static final int GL_LINE_WIDTH = 2849; // 0xb21
+    field public static final int GL_LOGIC_OP_MODE = 3056; // 0xbf0
+    field public static final int GL_MATRIX_MODE = 2976; // 0xba0
+    field public static final int GL_MAX_CLIP_PLANES = 3378; // 0xd32
+    field public static final int GL_MODELVIEW_MATRIX = 2982; // 0xba6
+    field public static final int GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES = 35213; // 0x898d
+    field public static final int GL_MODELVIEW_STACK_DEPTH = 2979; // 0xba3
+    field public static final int GL_NORMAL_ARRAY_BUFFER_BINDING = 34967; // 0x8897
+    field public static final int GL_NORMAL_ARRAY_POINTER = 32911; // 0x808f
+    field public static final int GL_NORMAL_ARRAY_STRIDE = 32895; // 0x807f
+    field public static final int GL_NORMAL_ARRAY_TYPE = 32894; // 0x807e
+    field public static final int GL_OPERAND0_ALPHA = 34200; // 0x8598
+    field public static final int GL_OPERAND0_RGB = 34192; // 0x8590
+    field public static final int GL_OPERAND1_ALPHA = 34201; // 0x8599
+    field public static final int GL_OPERAND1_RGB = 34193; // 0x8591
+    field public static final int GL_OPERAND2_ALPHA = 34202; // 0x859a
+    field public static final int GL_OPERAND2_RGB = 34194; // 0x8592
+    field public static final int GL_POINT_DISTANCE_ATTENUATION = 33065; // 0x8129
+    field public static final int GL_POINT_FADE_THRESHOLD_SIZE = 33064; // 0x8128
+    field public static final int GL_POINT_SIZE = 2833; // 0xb11
+    field public static final int GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES = 35743; // 0x8b9f
+    field public static final int GL_POINT_SIZE_ARRAY_OES = 35740; // 0x8b9c
+    field public static final int GL_POINT_SIZE_ARRAY_POINTER_OES = 35212; // 0x898c
+    field public static final int GL_POINT_SIZE_ARRAY_STRIDE_OES = 35211; // 0x898b
+    field public static final int GL_POINT_SIZE_ARRAY_TYPE_OES = 35210; // 0x898a
+    field public static final int GL_POINT_SIZE_MAX = 33063; // 0x8127
+    field public static final int GL_POINT_SIZE_MIN = 33062; // 0x8126
+    field public static final int GL_POINT_SPRITE_OES = 34913; // 0x8861
+    field public static final int GL_POLYGON_OFFSET_FACTOR = 32824; // 0x8038
+    field public static final int GL_POLYGON_OFFSET_UNITS = 10752; // 0x2a00
+    field public static final int GL_PREVIOUS = 34168; // 0x8578
+    field public static final int GL_PRIMARY_COLOR = 34167; // 0x8577
+    field public static final int GL_PROJECTION_MATRIX = 2983; // 0xba7
+    field public static final int GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES = 35214; // 0x898e
+    field public static final int GL_PROJECTION_STACK_DEPTH = 2980; // 0xba4
+    field public static final int GL_RGB_SCALE = 34163; // 0x8573
+    field public static final int GL_SAMPLES = 32937; // 0x80a9
+    field public static final int GL_SAMPLE_BUFFERS = 32936; // 0x80a8
+    field public static final int GL_SAMPLE_COVERAGE_INVERT = 32939; // 0x80ab
+    field public static final int GL_SAMPLE_COVERAGE_VALUE = 32938; // 0x80aa
+    field public static final int GL_SCISSOR_BOX = 3088; // 0xc10
+    field public static final int GL_SHADE_MODEL = 2900; // 0xb54
+    field public static final int GL_SRC0_ALPHA = 34184; // 0x8588
+    field public static final int GL_SRC0_RGB = 34176; // 0x8580
+    field public static final int GL_SRC1_ALPHA = 34185; // 0x8589
+    field public static final int GL_SRC1_RGB = 34177; // 0x8581
+    field public static final int GL_SRC2_ALPHA = 34186; // 0x858a
+    field public static final int GL_SRC2_RGB = 34178; // 0x8582
+    field public static final int GL_STATIC_DRAW = 35044; // 0x88e4
+    field public static final int GL_STENCIL_CLEAR_VALUE = 2961; // 0xb91
+    field public static final int GL_STENCIL_FAIL = 2964; // 0xb94
+    field public static final int GL_STENCIL_FUNC = 2962; // 0xb92
+    field public static final int GL_STENCIL_PASS_DEPTH_FAIL = 2965; // 0xb95
+    field public static final int GL_STENCIL_PASS_DEPTH_PASS = 2966; // 0xb96
+    field public static final int GL_STENCIL_REF = 2967; // 0xb97
+    field public static final int GL_STENCIL_VALUE_MASK = 2963; // 0xb93
+    field public static final int GL_STENCIL_WRITEMASK = 2968; // 0xb98
+    field public static final int GL_SUBTRACT = 34023; // 0x84e7
+    field public static final int GL_TEXTURE_BINDING_2D = 32873; // 0x8069
+    field public static final int GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING = 34970; // 0x889a
+    field public static final int GL_TEXTURE_COORD_ARRAY_POINTER = 32914; // 0x8092
+    field public static final int GL_TEXTURE_COORD_ARRAY_SIZE = 32904; // 0x8088
+    field public static final int GL_TEXTURE_COORD_ARRAY_STRIDE = 32906; // 0x808a
+    field public static final int GL_TEXTURE_COORD_ARRAY_TYPE = 32905; // 0x8089
+    field public static final int GL_TEXTURE_MATRIX = 2984; // 0xba8
+    field public static final int GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES = 35215; // 0x898f
+    field public static final int GL_TEXTURE_STACK_DEPTH = 2981; // 0xba5
+    field public static final int GL_VERTEX_ARRAY_BUFFER_BINDING = 34966; // 0x8896
+    field public static final int GL_VERTEX_ARRAY_POINTER = 32910; // 0x808e
+    field public static final int GL_VERTEX_ARRAY_SIZE = 32890; // 0x807a
+    field public static final int GL_VERTEX_ARRAY_STRIDE = 32892; // 0x807c
+    field public static final int GL_VERTEX_ARRAY_TYPE = 32891; // 0x807b
+    field public static final int GL_VIEWPORT = 2978; // 0xba2
+    field public static final int GL_WRITE_ONLY = 35001; // 0x88b9
+  }
+
+  public abstract interface GL11Ext implements javax.microedition.khronos.opengles.GL {
+    method public abstract void glCurrentPaletteMatrixOES(int);
+    method public abstract void glDrawTexfOES(float, float, float, float, float);
+    method public abstract void glDrawTexfvOES(float[], int);
+    method public abstract void glDrawTexfvOES(java.nio.FloatBuffer);
+    method public abstract void glDrawTexiOES(int, int, int, int, int);
+    method public abstract void glDrawTexivOES(int[], int);
+    method public abstract void glDrawTexivOES(java.nio.IntBuffer);
+    method public abstract void glDrawTexsOES(short, short, short, short, short);
+    method public abstract void glDrawTexsvOES(short[], int);
+    method public abstract void glDrawTexsvOES(java.nio.ShortBuffer);
+    method public abstract void glDrawTexxOES(int, int, int, int, int);
+    method public abstract void glDrawTexxvOES(int[], int);
+    method public abstract void glDrawTexxvOES(java.nio.IntBuffer);
+    method public abstract void glEnable(int);
+    method public abstract void glEnableClientState(int);
+    method public abstract void glLoadPaletteFromModelViewMatrixOES();
+    method public abstract void glMatrixIndexPointerOES(int, int, int, java.nio.Buffer);
+    method public abstract void glMatrixIndexPointerOES(int, int, int, int);
+    method public abstract void glTexParameterfv(int, int, float[], int);
+    method public abstract void glWeightPointerOES(int, int, int, java.nio.Buffer);
+    method public abstract void glWeightPointerOES(int, int, int, int);
+    field public static final int GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES = 35742; // 0x8b9e
+    field public static final int GL_MATRIX_INDEX_ARRAY_OES = 34884; // 0x8844
+    field public static final int GL_MATRIX_INDEX_ARRAY_POINTER_OES = 34889; // 0x8849
+    field public static final int GL_MATRIX_INDEX_ARRAY_SIZE_OES = 34886; // 0x8846
+    field public static final int GL_MATRIX_INDEX_ARRAY_STRIDE_OES = 34888; // 0x8848
+    field public static final int GL_MATRIX_INDEX_ARRAY_TYPE_OES = 34887; // 0x8847
+    field public static final int GL_MATRIX_PALETTE_OES = 34880; // 0x8840
+    field public static final int GL_MAX_PALETTE_MATRICES_OES = 34882; // 0x8842
+    field public static final int GL_MAX_VERTEX_UNITS_OES = 34468; // 0x86a4
+    field public static final int GL_TEXTURE_CROP_RECT_OES = 35741; // 0x8b9d
+    field public static final int GL_WEIGHT_ARRAY_BUFFER_BINDING_OES = 34974; // 0x889e
+    field public static final int GL_WEIGHT_ARRAY_OES = 34477; // 0x86ad
+    field public static final int GL_WEIGHT_ARRAY_POINTER_OES = 34476; // 0x86ac
+    field public static final int GL_WEIGHT_ARRAY_SIZE_OES = 34475; // 0x86ab
+    field public static final int GL_WEIGHT_ARRAY_STRIDE_OES = 34474; // 0x86aa
+    field public static final int GL_WEIGHT_ARRAY_TYPE_OES = 34473; // 0x86a9
+  }
+
+  public abstract interface GL11ExtensionPack implements javax.microedition.khronos.opengles.GL {
+    method public abstract void glBindFramebufferOES(int, int);
+    method public abstract void glBindRenderbufferOES(int, int);
+    method public abstract void glBindTexture(int, int);
+    method public abstract void glBlendEquation(int);
+    method public abstract void glBlendEquationSeparate(int, int);
+    method public abstract void glBlendFuncSeparate(int, int, int, int);
+    method public abstract int glCheckFramebufferStatusOES(int);
+    method public abstract void glCompressedTexImage2D(int, int, int, int, int, int, int, java.nio.Buffer);
+    method public abstract void glCopyTexImage2D(int, int, int, int, int, int, int, int);
+    method public abstract void glDeleteFramebuffersOES(int, int[], int);
+    method public abstract void glDeleteFramebuffersOES(int, java.nio.IntBuffer);
+    method public abstract void glDeleteRenderbuffersOES(int, int[], int);
+    method public abstract void glDeleteRenderbuffersOES(int, java.nio.IntBuffer);
+    method public abstract void glEnable(int);
+    method public abstract void glFramebufferRenderbufferOES(int, int, int, int);
+    method public abstract void glFramebufferTexture2DOES(int, int, int, int, int);
+    method public abstract void glGenFramebuffersOES(int, int[], int);
+    method public abstract void glGenFramebuffersOES(int, java.nio.IntBuffer);
+    method public abstract void glGenRenderbuffersOES(int, int[], int);
+    method public abstract void glGenRenderbuffersOES(int, java.nio.IntBuffer);
+    method public abstract void glGenerateMipmapOES(int);
+    method public abstract void glGetFramebufferAttachmentParameterivOES(int, int, int, int[], int);
+    method public abstract void glGetFramebufferAttachmentParameterivOES(int, int, int, java.nio.IntBuffer);
+    method public abstract void glGetIntegerv(int, int[], int);
+    method public abstract void glGetIntegerv(int, java.nio.IntBuffer);
+    method public abstract void glGetRenderbufferParameterivOES(int, int, int[], int);
+    method public abstract void glGetRenderbufferParameterivOES(int, int, java.nio.IntBuffer);
+    method public abstract void glGetTexGenfv(int, int, float[], int);
+    method public abstract void glGetTexGenfv(int, int, java.nio.FloatBuffer);
+    method public abstract void glGetTexGeniv(int, int, int[], int);
+    method public abstract void glGetTexGeniv(int, int, java.nio.IntBuffer);
+    method public abstract void glGetTexGenxv(int, int, int[], int);
+    method public abstract void glGetTexGenxv(int, int, java.nio.IntBuffer);
+    method public abstract boolean glIsFramebufferOES(int);
+    method public abstract boolean glIsRenderbufferOES(int);
+    method public abstract void glRenderbufferStorageOES(int, int, int, int);
+    method public abstract void glStencilOp(int, int, int);
+    method public abstract void glTexEnvf(int, int, float);
+    method public abstract void glTexEnvfv(int, int, float[], int);
+    method public abstract void glTexEnvfv(int, int, java.nio.FloatBuffer);
+    method public abstract void glTexEnvx(int, int, int);
+    method public abstract void glTexEnvxv(int, int, int[], int);
+    method public abstract void glTexEnvxv(int, int, java.nio.IntBuffer);
+    method public abstract void glTexGenf(int, int, float);
+    method public abstract void glTexGenfv(int, int, float[], int);
+    method public abstract void glTexGenfv(int, int, java.nio.FloatBuffer);
+    method public abstract void glTexGeni(int, int, int);
+    method public abstract void glTexGeniv(int, int, int[], int);
+    method public abstract void glTexGeniv(int, int, java.nio.IntBuffer);
+    method public abstract void glTexGenx(int, int, int);
+    method public abstract void glTexGenxv(int, int, int[], int);
+    method public abstract void glTexGenxv(int, int, java.nio.IntBuffer);
+    method public abstract void glTexParameterf(int, int, float);
+    field public static final int GL_BLEND_DST_ALPHA = 32970; // 0x80ca
+    field public static final int GL_BLEND_DST_RGB = 32968; // 0x80c8
+    field public static final int GL_BLEND_EQUATION = 32777; // 0x8009
+    field public static final int GL_BLEND_EQUATION_ALPHA = 34877; // 0x883d
+    field public static final int GL_BLEND_EQUATION_RGB = 32777; // 0x8009
+    field public static final int GL_BLEND_SRC_ALPHA = 32971; // 0x80cb
+    field public static final int GL_BLEND_SRC_RGB = 32969; // 0x80c9
+    field public static final int GL_COLOR_ATTACHMENT0_OES = 36064; // 0x8ce0
+    field public static final int GL_COLOR_ATTACHMENT10_OES = 36074; // 0x8cea
+    field public static final int GL_COLOR_ATTACHMENT11_OES = 36075; // 0x8ceb
+    field public static final int GL_COLOR_ATTACHMENT12_OES = 36076; // 0x8cec
+    field public static final int GL_COLOR_ATTACHMENT13_OES = 36077; // 0x8ced
+    field public static final int GL_COLOR_ATTACHMENT14_OES = 36078; // 0x8cee
+    field public static final int GL_COLOR_ATTACHMENT15_OES = 36079; // 0x8cef
+    field public static final int GL_COLOR_ATTACHMENT1_OES = 36065; // 0x8ce1
+    field public static final int GL_COLOR_ATTACHMENT2_OES = 36066; // 0x8ce2
+    field public static final int GL_COLOR_ATTACHMENT3_OES = 36067; // 0x8ce3
+    field public static final int GL_COLOR_ATTACHMENT4_OES = 36068; // 0x8ce4
+    field public static final int GL_COLOR_ATTACHMENT5_OES = 36069; // 0x8ce5
+    field public static final int GL_COLOR_ATTACHMENT6_OES = 36070; // 0x8ce6
+    field public static final int GL_COLOR_ATTACHMENT7_OES = 36071; // 0x8ce7
+    field public static final int GL_COLOR_ATTACHMENT8_OES = 36072; // 0x8ce8
+    field public static final int GL_COLOR_ATTACHMENT9_OES = 36073; // 0x8ce9
+    field public static final int GL_DECR_WRAP = 34056; // 0x8508
+    field public static final int GL_DEPTH_ATTACHMENT_OES = 36096; // 0x8d00
+    field public static final int GL_DEPTH_COMPONENT = 6402; // 0x1902
+    field public static final int GL_DEPTH_COMPONENT16 = 33189; // 0x81a5
+    field public static final int GL_DEPTH_COMPONENT24 = 33190; // 0x81a6
+    field public static final int GL_DEPTH_COMPONENT32 = 33191; // 0x81a7
+    field public static final int GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES = 36049; // 0x8cd1
+    field public static final int GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES = 36048; // 0x8cd0
+    field public static final int GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES = 36051; // 0x8cd3
+    field public static final int GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES = 36050; // 0x8cd2
+    field public static final int GL_FRAMEBUFFER_BINDING_OES = 36006; // 0x8ca6
+    field public static final int GL_FRAMEBUFFER_COMPLETE_OES = 36053; // 0x8cd5
+    field public static final int GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES = 36054; // 0x8cd6
+    field public static final int GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES = 36057; // 0x8cd9
+    field public static final int GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_OES = 36059; // 0x8cdb
+    field public static final int GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES = 36058; // 0x8cda
+    field public static final int GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES = 36055; // 0x8cd7
+    field public static final int GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_OES = 36060; // 0x8cdc
+    field public static final int GL_FRAMEBUFFER_OES = 36160; // 0x8d40
+    field public static final int GL_FRAMEBUFFER_UNSUPPORTED_OES = 36061; // 0x8cdd
+    field public static final int GL_FUNC_ADD = 32774; // 0x8006
+    field public static final int GL_FUNC_REVERSE_SUBTRACT = 32779; // 0x800b
+    field public static final int GL_FUNC_SUBTRACT = 32778; // 0x800a
+    field public static final int GL_INCR_WRAP = 34055; // 0x8507
+    field public static final int GL_INVALID_FRAMEBUFFER_OPERATION_OES = 1286; // 0x506
+    field public static final int GL_MAX_COLOR_ATTACHMENTS_OES = 36063; // 0x8cdf
+    field public static final int GL_MAX_CUBE_MAP_TEXTURE_SIZE = 34076; // 0x851c
+    field public static final int GL_MAX_RENDERBUFFER_SIZE_OES = 34024; // 0x84e8
+    field public static final int GL_MIRRORED_REPEAT = 33648; // 0x8370
+    field public static final int GL_NORMAL_MAP = 34065; // 0x8511
+    field public static final int GL_REFLECTION_MAP = 34066; // 0x8512
+    field public static final int GL_RENDERBUFFER_ALPHA_SIZE_OES = 36179; // 0x8d53
+    field public static final int GL_RENDERBUFFER_BINDING_OES = 36007; // 0x8ca7
+    field public static final int GL_RENDERBUFFER_BLUE_SIZE_OES = 36178; // 0x8d52
+    field public static final int GL_RENDERBUFFER_DEPTH_SIZE_OES = 36180; // 0x8d54
+    field public static final int GL_RENDERBUFFER_GREEN_SIZE_OES = 36177; // 0x8d51
+    field public static final int GL_RENDERBUFFER_HEIGHT_OES = 36163; // 0x8d43
+    field public static final int GL_RENDERBUFFER_INTERNAL_FORMAT_OES = 36164; // 0x8d44
+    field public static final int GL_RENDERBUFFER_OES = 36161; // 0x8d41
+    field public static final int GL_RENDERBUFFER_RED_SIZE_OES = 36176; // 0x8d50
+    field public static final int GL_RENDERBUFFER_STENCIL_SIZE_OES = 36181; // 0x8d55
+    field public static final int GL_RENDERBUFFER_WIDTH_OES = 36162; // 0x8d42
+    field public static final int GL_RGB565_OES = 36194; // 0x8d62
+    field public static final int GL_RGB5_A1 = 32855; // 0x8057
+    field public static final int GL_RGB8 = 32849; // 0x8051
+    field public static final int GL_RGBA4 = 32854; // 0x8056
+    field public static final int GL_RGBA8 = 32856; // 0x8058
+    field public static final int GL_STENCIL_ATTACHMENT_OES = 36128; // 0x8d20
+    field public static final int GL_STENCIL_INDEX = 6401; // 0x1901
+    field public static final int GL_STENCIL_INDEX1_OES = 36166; // 0x8d46
+    field public static final int GL_STENCIL_INDEX4_OES = 36167; // 0x8d47
+    field public static final int GL_STENCIL_INDEX8_OES = 36168; // 0x8d48
+    field public static final int GL_STR = -1; // 0xffffffff
+    field public static final int GL_TEXTURE_BINDING_CUBE_MAP = 34068; // 0x8514
+    field public static final int GL_TEXTURE_CUBE_MAP = 34067; // 0x8513
+    field public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 34070; // 0x8516
+    field public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 34072; // 0x8518
+    field public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 34074; // 0x851a
+    field public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_X = 34069; // 0x8515
+    field public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 34071; // 0x8517
+    field public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 34073; // 0x8519
+    field public static final int GL_TEXTURE_GEN_MODE = 9472; // 0x2500
+    field public static final int GL_TEXTURE_GEN_STR = 36192; // 0x8d60
+  }
+
+}
+
+package javax.net {
+
+  public abstract class ServerSocketFactory {
+    ctor protected ServerSocketFactory();
+    method public java.net.ServerSocket createServerSocket() throws java.io.IOException;
+    method public abstract java.net.ServerSocket createServerSocket(int) throws java.io.IOException;
+    method public abstract java.net.ServerSocket createServerSocket(int, int) throws java.io.IOException;
+    method public abstract java.net.ServerSocket createServerSocket(int, int, java.net.InetAddress) throws java.io.IOException;
+    method public static synchronized javax.net.ServerSocketFactory getDefault();
+  }
+
+  public abstract class SocketFactory {
+    ctor protected SocketFactory();
+    method public java.net.Socket createSocket() throws java.io.IOException;
+    method public abstract java.net.Socket createSocket(java.lang.String, int) throws java.io.IOException, java.net.UnknownHostException;
+    method public abstract java.net.Socket createSocket(java.lang.String, int, java.net.InetAddress, int) throws java.io.IOException, java.net.UnknownHostException;
+    method public abstract java.net.Socket createSocket(java.net.InetAddress, int) throws java.io.IOException;
+    method public abstract java.net.Socket createSocket(java.net.InetAddress, int, java.net.InetAddress, int) throws java.io.IOException;
+    method public static synchronized javax.net.SocketFactory getDefault();
+  }
+
+}
+
+package javax.net.ssl {
+
+  public class CertPathTrustManagerParameters implements javax.net.ssl.ManagerFactoryParameters {
+    ctor public CertPathTrustManagerParameters(java.security.cert.CertPathParameters);
+    method public java.security.cert.CertPathParameters getParameters();
+  }
+
+  public class HandshakeCompletedEvent extends java.util.EventObject {
+    ctor public HandshakeCompletedEvent(javax.net.ssl.SSLSocket, javax.net.ssl.SSLSession);
+    method public java.lang.String getCipherSuite();
+    method public java.security.cert.Certificate[] getLocalCertificates();
+    method public java.security.Principal getLocalPrincipal();
+    method public javax.security.cert.X509Certificate[] getPeerCertificateChain() throws javax.net.ssl.SSLPeerUnverifiedException;
+    method public java.security.cert.Certificate[] getPeerCertificates() throws javax.net.ssl.SSLPeerUnverifiedException;
+    method public java.security.Principal getPeerPrincipal() throws javax.net.ssl.SSLPeerUnverifiedException;
+    method public javax.net.ssl.SSLSession getSession();
+    method public javax.net.ssl.SSLSocket getSocket();
+  }
+
+  public abstract interface HandshakeCompletedListener implements java.util.EventListener {
+    method public abstract void handshakeCompleted(javax.net.ssl.HandshakeCompletedEvent);
+  }
+
+  public abstract interface HostnameVerifier {
+    method public abstract boolean verify(java.lang.String, javax.net.ssl.SSLSession);
+  }
+
+  public abstract class HttpsURLConnection extends java.net.HttpURLConnection {
+    ctor protected HttpsURLConnection(java.net.URL);
+    method public abstract java.lang.String getCipherSuite();
+    method public static javax.net.ssl.HostnameVerifier getDefaultHostnameVerifier();
+    method public static javax.net.ssl.SSLSocketFactory getDefaultSSLSocketFactory();
+    method public javax.net.ssl.HostnameVerifier getHostnameVerifier();
+    method public abstract java.security.cert.Certificate[] getLocalCertificates();
+    method public java.security.Principal getLocalPrincipal();
+    method public java.security.Principal getPeerPrincipal() throws javax.net.ssl.SSLPeerUnverifiedException;
+    method public javax.net.ssl.SSLSocketFactory getSSLSocketFactory();
+    method public abstract java.security.cert.Certificate[] getServerCertificates() throws javax.net.ssl.SSLPeerUnverifiedException;
+    method public static void setDefaultHostnameVerifier(javax.net.ssl.HostnameVerifier);
+    method public static void setDefaultSSLSocketFactory(javax.net.ssl.SSLSocketFactory);
+    method public void setHostnameVerifier(javax.net.ssl.HostnameVerifier);
+    method public void setSSLSocketFactory(javax.net.ssl.SSLSocketFactory);
+    field protected javax.net.ssl.HostnameVerifier hostnameVerifier;
+  }
+
+  public abstract interface KeyManager {
+  }
+
+  public class KeyManagerFactory {
+    ctor protected KeyManagerFactory(javax.net.ssl.KeyManagerFactorySpi, java.security.Provider, java.lang.String);
+    method public final java.lang.String getAlgorithm();
+    method public static final java.lang.String getDefaultAlgorithm();
+    method public static final javax.net.ssl.KeyManagerFactory getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static final javax.net.ssl.KeyManagerFactory getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static final javax.net.ssl.KeyManagerFactory getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final javax.net.ssl.KeyManager[] getKeyManagers();
+    method public final java.security.Provider getProvider();
+    method public final void init(java.security.KeyStore, char[]) throws java.security.KeyStoreException, java.security.NoSuchAlgorithmException, java.security.UnrecoverableKeyException;
+    method public final void init(javax.net.ssl.ManagerFactoryParameters) throws java.security.InvalidAlgorithmParameterException;
+  }
+
+  public abstract class KeyManagerFactorySpi {
+    ctor public KeyManagerFactorySpi();
+    method protected abstract javax.net.ssl.KeyManager[] engineGetKeyManagers();
+    method protected abstract void engineInit(java.security.KeyStore, char[]) throws java.security.KeyStoreException, java.security.NoSuchAlgorithmException, java.security.UnrecoverableKeyException;
+    method protected abstract void engineInit(javax.net.ssl.ManagerFactoryParameters) throws java.security.InvalidAlgorithmParameterException;
+  }
+
+  public class KeyStoreBuilderParameters implements javax.net.ssl.ManagerFactoryParameters {
+    ctor public KeyStoreBuilderParameters(java.security.KeyStore.Builder);
+    ctor public KeyStoreBuilderParameters(java.util.List<java.security.KeyStore.Builder>);
+    method public java.util.List<java.security.KeyStore.Builder> getParameters();
+  }
+
+  public abstract interface ManagerFactoryParameters {
+  }
+
+  public class SSLContext {
+    ctor protected SSLContext(javax.net.ssl.SSLContextSpi, java.security.Provider, java.lang.String);
+    method public final javax.net.ssl.SSLEngine createSSLEngine();
+    method public final javax.net.ssl.SSLEngine createSSLEngine(java.lang.String, int);
+    method public final javax.net.ssl.SSLSessionContext getClientSessionContext();
+    method public static javax.net.ssl.SSLContext getDefault() throws java.security.NoSuchAlgorithmException;
+    method public final javax.net.ssl.SSLParameters getDefaultSSLParameters();
+    method public static javax.net.ssl.SSLContext getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static javax.net.ssl.SSLContext getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static javax.net.ssl.SSLContext getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final java.lang.String getProtocol();
+    method public final java.security.Provider getProvider();
+    method public final javax.net.ssl.SSLSessionContext getServerSessionContext();
+    method public final javax.net.ssl.SSLServerSocketFactory getServerSocketFactory();
+    method public final javax.net.ssl.SSLSocketFactory getSocketFactory();
+    method public final javax.net.ssl.SSLParameters getSupportedSSLParameters();
+    method public final void init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom) throws java.security.KeyManagementException;
+    method public static void setDefault(javax.net.ssl.SSLContext);
+  }
+
+  public abstract class SSLContextSpi {
+    ctor public SSLContextSpi();
+    method protected abstract javax.net.ssl.SSLEngine engineCreateSSLEngine(java.lang.String, int);
+    method protected abstract javax.net.ssl.SSLEngine engineCreateSSLEngine();
+    method protected abstract javax.net.ssl.SSLSessionContext engineGetClientSessionContext();
+    method protected javax.net.ssl.SSLParameters engineGetDefaultSSLParameters();
+    method protected abstract javax.net.ssl.SSLSessionContext engineGetServerSessionContext();
+    method protected abstract javax.net.ssl.SSLServerSocketFactory engineGetServerSocketFactory();
+    method protected abstract javax.net.ssl.SSLSocketFactory engineGetSocketFactory();
+    method protected javax.net.ssl.SSLParameters engineGetSupportedSSLParameters();
+    method protected abstract void engineInit(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom) throws java.security.KeyManagementException;
+  }
+
+  public abstract class SSLEngine {
+    ctor protected SSLEngine();
+    ctor protected SSLEngine(java.lang.String, int);
+    method public abstract void beginHandshake() throws javax.net.ssl.SSLException;
+    method public abstract void closeInbound() throws javax.net.ssl.SSLException;
+    method public abstract void closeOutbound();
+    method public abstract java.lang.Runnable getDelegatedTask();
+    method public abstract boolean getEnableSessionCreation();
+    method public abstract java.lang.String[] getEnabledCipherSuites();
+    method public abstract java.lang.String[] getEnabledProtocols();
+    method public abstract javax.net.ssl.SSLEngineResult.HandshakeStatus getHandshakeStatus();
+    method public abstract boolean getNeedClientAuth();
+    method public java.lang.String getPeerHost();
+    method public int getPeerPort();
+    method public javax.net.ssl.SSLParameters getSSLParameters();
+    method public abstract javax.net.ssl.SSLSession getSession();
+    method public abstract java.lang.String[] getSupportedCipherSuites();
+    method public abstract java.lang.String[] getSupportedProtocols();
+    method public abstract boolean getUseClientMode();
+    method public abstract boolean getWantClientAuth();
+    method public abstract boolean isInboundDone();
+    method public abstract boolean isOutboundDone();
+    method public abstract void setEnableSessionCreation(boolean);
+    method public abstract void setEnabledCipherSuites(java.lang.String[]);
+    method public abstract void setEnabledProtocols(java.lang.String[]);
+    method public abstract void setNeedClientAuth(boolean);
+    method public void setSSLParameters(javax.net.ssl.SSLParameters);
+    method public abstract void setUseClientMode(boolean);
+    method public abstract void setWantClientAuth(boolean);
+    method public abstract javax.net.ssl.SSLEngineResult unwrap(java.nio.ByteBuffer, java.nio.ByteBuffer[], int, int) throws javax.net.ssl.SSLException;
+    method public javax.net.ssl.SSLEngineResult unwrap(java.nio.ByteBuffer, java.nio.ByteBuffer) throws javax.net.ssl.SSLException;
+    method public javax.net.ssl.SSLEngineResult unwrap(java.nio.ByteBuffer, java.nio.ByteBuffer[]) throws javax.net.ssl.SSLException;
+    method public abstract javax.net.ssl.SSLEngineResult wrap(java.nio.ByteBuffer[], int, int, java.nio.ByteBuffer) throws javax.net.ssl.SSLException;
+    method public javax.net.ssl.SSLEngineResult wrap(java.nio.ByteBuffer[], java.nio.ByteBuffer) throws javax.net.ssl.SSLException;
+    method public javax.net.ssl.SSLEngineResult wrap(java.nio.ByteBuffer, java.nio.ByteBuffer) throws javax.net.ssl.SSLException;
+  }
+
+  public class SSLEngineResult {
+    ctor public SSLEngineResult(javax.net.ssl.SSLEngineResult.Status, javax.net.ssl.SSLEngineResult.HandshakeStatus, int, int);
+    method public final int bytesConsumed();
+    method public final int bytesProduced();
+    method public final javax.net.ssl.SSLEngineResult.HandshakeStatus getHandshakeStatus();
+    method public final javax.net.ssl.SSLEngineResult.Status getStatus();
+  }
+
+  public static final class SSLEngineResult.HandshakeStatus extends java.lang.Enum {
+    method public static javax.net.ssl.SSLEngineResult.HandshakeStatus valueOf(java.lang.String);
+    method public static final javax.net.ssl.SSLEngineResult.HandshakeStatus[] values();
+    enum_constant public static final javax.net.ssl.SSLEngineResult.HandshakeStatus FINISHED;
+    enum_constant public static final javax.net.ssl.SSLEngineResult.HandshakeStatus NEED_TASK;
+    enum_constant public static final javax.net.ssl.SSLEngineResult.HandshakeStatus NEED_UNWRAP;
+    enum_constant public static final javax.net.ssl.SSLEngineResult.HandshakeStatus NEED_WRAP;
+    enum_constant public static final javax.net.ssl.SSLEngineResult.HandshakeStatus NOT_HANDSHAKING;
+  }
+
+  public static final class SSLEngineResult.Status extends java.lang.Enum {
+    method public static javax.net.ssl.SSLEngineResult.Status valueOf(java.lang.String);
+    method public static final javax.net.ssl.SSLEngineResult.Status[] values();
+    enum_constant public static final javax.net.ssl.SSLEngineResult.Status BUFFER_OVERFLOW;
+    enum_constant public static final javax.net.ssl.SSLEngineResult.Status BUFFER_UNDERFLOW;
+    enum_constant public static final javax.net.ssl.SSLEngineResult.Status CLOSED;
+    enum_constant public static final javax.net.ssl.SSLEngineResult.Status OK;
+  }
+
+  public class SSLException extends java.io.IOException {
+    ctor public SSLException(java.lang.String);
+    ctor public SSLException(java.lang.String, java.lang.Throwable);
+    ctor public SSLException(java.lang.Throwable);
+  }
+
+  public class SSLHandshakeException extends javax.net.ssl.SSLException {
+    ctor public SSLHandshakeException(java.lang.String);
+  }
+
+  public class SSLKeyException extends javax.net.ssl.SSLException {
+    ctor public SSLKeyException(java.lang.String);
+  }
+
+  public class SSLParameters {
+    ctor public SSLParameters();
+    ctor public SSLParameters(java.lang.String[]);
+    ctor public SSLParameters(java.lang.String[], java.lang.String[]);
+    method public java.lang.String[] getCipherSuites();
+    method public boolean getNeedClientAuth();
+    method public java.lang.String[] getProtocols();
+    method public boolean getWantClientAuth();
+    method public void setCipherSuites(java.lang.String[]);
+    method public void setNeedClientAuth(boolean);
+    method public void setProtocols(java.lang.String[]);
+    method public void setWantClientAuth(boolean);
+  }
+
+  public class SSLPeerUnverifiedException extends javax.net.ssl.SSLException {
+    ctor public SSLPeerUnverifiedException(java.lang.String);
+  }
+
+  public final class SSLPermission extends java.security.BasicPermission {
+    ctor public SSLPermission(java.lang.String);
+    ctor public SSLPermission(java.lang.String, java.lang.String);
+  }
+
+  public class SSLProtocolException extends javax.net.ssl.SSLException {
+    ctor public SSLProtocolException(java.lang.String);
+  }
+
+  public abstract class SSLServerSocket extends java.net.ServerSocket {
+    ctor protected SSLServerSocket() throws java.io.IOException;
+    ctor protected SSLServerSocket(int) throws java.io.IOException;
+    ctor protected SSLServerSocket(int, int) throws java.io.IOException;
+    ctor protected SSLServerSocket(int, int, java.net.InetAddress) throws java.io.IOException;
+    method public abstract boolean getEnableSessionCreation();
+    method public abstract java.lang.String[] getEnabledCipherSuites();
+    method public abstract java.lang.String[] getEnabledProtocols();
+    method public abstract boolean getNeedClientAuth();
+    method public abstract java.lang.String[] getSupportedCipherSuites();
+    method public abstract java.lang.String[] getSupportedProtocols();
+    method public abstract boolean getUseClientMode();
+    method public abstract boolean getWantClientAuth();
+    method public abstract void setEnableSessionCreation(boolean);
+    method public abstract void setEnabledCipherSuites(java.lang.String[]);
+    method public abstract void setEnabledProtocols(java.lang.String[]);
+    method public abstract void setNeedClientAuth(boolean);
+    method public abstract void setUseClientMode(boolean);
+    method public abstract void setWantClientAuth(boolean);
+  }
+
+  public abstract class SSLServerSocketFactory extends javax.net.ServerSocketFactory {
+    ctor protected SSLServerSocketFactory();
+    method public static synchronized javax.net.ServerSocketFactory getDefault();
+    method public abstract java.lang.String[] getDefaultCipherSuites();
+    method public abstract java.lang.String[] getSupportedCipherSuites();
+  }
+
+  public abstract interface SSLSession {
+    method public abstract int getApplicationBufferSize();
+    method public abstract java.lang.String getCipherSuite();
+    method public abstract long getCreationTime();
+    method public abstract byte[] getId();
+    method public abstract long getLastAccessedTime();
+    method public abstract java.security.cert.Certificate[] getLocalCertificates();
+    method public abstract java.security.Principal getLocalPrincipal();
+    method public abstract int getPacketBufferSize();
+    method public abstract javax.security.cert.X509Certificate[] getPeerCertificateChain() throws javax.net.ssl.SSLPeerUnverifiedException;
+    method public abstract java.security.cert.Certificate[] getPeerCertificates() throws javax.net.ssl.SSLPeerUnverifiedException;
+    method public abstract java.lang.String getPeerHost();
+    method public abstract int getPeerPort();
+    method public abstract java.security.Principal getPeerPrincipal() throws javax.net.ssl.SSLPeerUnverifiedException;
+    method public abstract java.lang.String getProtocol();
+    method public abstract javax.net.ssl.SSLSessionContext getSessionContext();
+    method public abstract java.lang.Object getValue(java.lang.String);
+    method public abstract java.lang.String[] getValueNames();
+    method public abstract void invalidate();
+    method public abstract boolean isValid();
+    method public abstract void putValue(java.lang.String, java.lang.Object);
+    method public abstract void removeValue(java.lang.String);
+  }
+
+  public class SSLSessionBindingEvent extends java.util.EventObject {
+    ctor public SSLSessionBindingEvent(javax.net.ssl.SSLSession, java.lang.String);
+    method public java.lang.String getName();
+    method public javax.net.ssl.SSLSession getSession();
+  }
+
+  public abstract interface SSLSessionBindingListener implements java.util.EventListener {
+    method public abstract void valueBound(javax.net.ssl.SSLSessionBindingEvent);
+    method public abstract void valueUnbound(javax.net.ssl.SSLSessionBindingEvent);
+  }
+
+  public abstract interface SSLSessionContext {
+    method public abstract java.util.Enumeration<byte[]> getIds();
+    method public abstract javax.net.ssl.SSLSession getSession(byte[]);
+    method public abstract int getSessionCacheSize();
+    method public abstract int getSessionTimeout();
+    method public abstract void setSessionCacheSize(int) throws java.lang.IllegalArgumentException;
+    method public abstract void setSessionTimeout(int) throws java.lang.IllegalArgumentException;
+  }
+
+  public abstract class SSLSocket extends java.net.Socket {
+    ctor protected SSLSocket();
+    ctor protected SSLSocket(java.lang.String, int) throws java.io.IOException, java.net.UnknownHostException;
+    ctor protected SSLSocket(java.net.InetAddress, int) throws java.io.IOException;
+    ctor protected SSLSocket(java.lang.String, int, java.net.InetAddress, int) throws java.io.IOException, java.net.UnknownHostException;
+    ctor protected SSLSocket(java.net.InetAddress, int, java.net.InetAddress, int) throws java.io.IOException;
+    method public abstract void addHandshakeCompletedListener(javax.net.ssl.HandshakeCompletedListener);
+    method public abstract boolean getEnableSessionCreation();
+    method public abstract java.lang.String[] getEnabledCipherSuites();
+    method public abstract java.lang.String[] getEnabledProtocols();
+    method public abstract boolean getNeedClientAuth();
+    method public javax.net.ssl.SSLParameters getSSLParameters();
+    method public abstract javax.net.ssl.SSLSession getSession();
+    method public abstract java.lang.String[] getSupportedCipherSuites();
+    method public abstract java.lang.String[] getSupportedProtocols();
+    method public abstract boolean getUseClientMode();
+    method public abstract boolean getWantClientAuth();
+    method public abstract void removeHandshakeCompletedListener(javax.net.ssl.HandshakeCompletedListener);
+    method public abstract void setEnableSessionCreation(boolean);
+    method public abstract void setEnabledCipherSuites(java.lang.String[]);
+    method public abstract void setEnabledProtocols(java.lang.String[]);
+    method public abstract void setNeedClientAuth(boolean);
+    method public void setSSLParameters(javax.net.ssl.SSLParameters);
+    method public abstract void setUseClientMode(boolean);
+    method public abstract void setWantClientAuth(boolean);
+    method public abstract void startHandshake() throws java.io.IOException;
+  }
+
+  public abstract class SSLSocketFactory extends javax.net.SocketFactory {
+    ctor public SSLSocketFactory();
+    method public abstract java.net.Socket createSocket(java.net.Socket, java.lang.String, int, boolean) throws java.io.IOException;
+    method public static synchronized javax.net.SocketFactory getDefault();
+    method public abstract java.lang.String[] getDefaultCipherSuites();
+    method public abstract java.lang.String[] getSupportedCipherSuites();
+  }
+
+  public abstract interface TrustManager {
+  }
+
+  public class TrustManagerFactory {
+    ctor protected TrustManagerFactory(javax.net.ssl.TrustManagerFactorySpi, java.security.Provider, java.lang.String);
+    method public final java.lang.String getAlgorithm();
+    method public static final java.lang.String getDefaultAlgorithm();
+    method public static final javax.net.ssl.TrustManagerFactory getInstance(java.lang.String) throws java.security.NoSuchAlgorithmException;
+    method public static final javax.net.ssl.TrustManagerFactory getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
+    method public static final javax.net.ssl.TrustManagerFactory getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
+    method public final java.security.Provider getProvider();
+    method public final javax.net.ssl.TrustManager[] getTrustManagers();
+    method public final void init(java.security.KeyStore) throws java.security.KeyStoreException;
+    method public final void init(javax.net.ssl.ManagerFactoryParameters) throws java.security.InvalidAlgorithmParameterException;
+  }
+
+  public abstract class TrustManagerFactorySpi {
+    ctor public TrustManagerFactorySpi();
+    method protected abstract javax.net.ssl.TrustManager[] engineGetTrustManagers();
+    method protected abstract void engineInit(java.security.KeyStore) throws java.security.KeyStoreException;
+    method protected abstract void engineInit(javax.net.ssl.ManagerFactoryParameters) throws java.security.InvalidAlgorithmParameterException;
+  }
+
+  public abstract class X509ExtendedKeyManager implements javax.net.ssl.X509KeyManager {
+    ctor protected X509ExtendedKeyManager();
+    method public java.lang.String chooseEngineClientAlias(java.lang.String[], java.security.Principal[], javax.net.ssl.SSLEngine);
+    method public java.lang.String chooseEngineServerAlias(java.lang.String, java.security.Principal[], javax.net.ssl.SSLEngine);
+  }
+
+  public abstract interface X509KeyManager implements javax.net.ssl.KeyManager {
+    method public abstract java.lang.String chooseClientAlias(java.lang.String[], java.security.Principal[], java.net.Socket);
+    method public abstract java.lang.String chooseServerAlias(java.lang.String, java.security.Principal[], java.net.Socket);
+    method public abstract java.security.cert.X509Certificate[] getCertificateChain(java.lang.String);
+    method public abstract java.lang.String[] getClientAliases(java.lang.String, java.security.Principal[]);
+    method public abstract java.security.PrivateKey getPrivateKey(java.lang.String);
+    method public abstract java.lang.String[] getServerAliases(java.lang.String, java.security.Principal[]);
+  }
+
+  public abstract interface X509TrustManager implements javax.net.ssl.TrustManager {
+    method public abstract void checkClientTrusted(java.security.cert.X509Certificate[], java.lang.String) throws java.security.cert.CertificateException;
+    method public abstract void checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String) throws java.security.cert.CertificateException;
+    method public abstract java.security.cert.X509Certificate[] getAcceptedIssuers();
+  }
+
+}
+
+package javax.security.auth {
+
+  public final class AuthPermission extends java.security.BasicPermission {
+    ctor public AuthPermission(java.lang.String);
+    ctor public AuthPermission(java.lang.String, java.lang.String);
+  }
+
+  public class DestroyFailedException extends java.lang.Exception {
+    ctor public DestroyFailedException();
+    ctor public DestroyFailedException(java.lang.String);
+  }
+
+  public abstract interface Destroyable {
+    method public abstract void destroy() throws javax.security.auth.DestroyFailedException;
+    method public abstract boolean isDestroyed();
+  }
+
+  public final class PrivateCredentialPermission extends java.security.Permission {
+    ctor public PrivateCredentialPermission(java.lang.String, java.lang.String);
+    method public java.lang.String getActions();
+    method public java.lang.String getCredentialClass();
+    method public java.lang.String[][] getPrincipals();
+    method public boolean implies(java.security.Permission);
+  }
+
+  public final class Subject implements java.io.Serializable {
+    ctor public Subject();
+    ctor public Subject(boolean, java.util.Set<? extends java.security.Principal>, java.util.Set<?>, java.util.Set<?>);
+    method public static T doAs(javax.security.auth.Subject, java.security.PrivilegedAction<T>);
+    method public static T doAs(javax.security.auth.Subject, java.security.PrivilegedExceptionAction<T>) throws java.security.PrivilegedActionException;
+    method public static T doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedAction<T>, java.security.AccessControlContext);
+    method public static T doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedExceptionAction<T>, java.security.AccessControlContext) throws java.security.PrivilegedActionException;
+    method public java.util.Set<java.security.Principal> getPrincipals();
+    method public java.util.Set<T> getPrincipals(java.lang.Class<T>);
+    method public java.util.Set<java.lang.Object> getPrivateCredentials();
+    method public java.util.Set<T> getPrivateCredentials(java.lang.Class<T>);
+    method public java.util.Set<java.lang.Object> getPublicCredentials();
+    method public java.util.Set<T> getPublicCredentials(java.lang.Class<T>);
+    method public static javax.security.auth.Subject getSubject(java.security.AccessControlContext);
+    method public boolean isReadOnly();
+    method public void setReadOnly();
+  }
+
+  public class SubjectDomainCombiner implements java.security.DomainCombiner {
+    ctor public SubjectDomainCombiner(javax.security.auth.Subject);
+    method public java.security.ProtectionDomain[] combine(java.security.ProtectionDomain[], java.security.ProtectionDomain[]);
+    method public javax.security.auth.Subject getSubject();
+  }
+
+}
+
+package javax.security.auth.callback {
+
+  public abstract interface Callback {
+  }
+
+  public abstract interface CallbackHandler {
+    method public abstract void handle(javax.security.auth.callback.Callback[]) throws java.io.IOException, javax.security.auth.callback.UnsupportedCallbackException;
+  }
+
+  public class PasswordCallback implements javax.security.auth.callback.Callback java.io.Serializable {
+    ctor public PasswordCallback(java.lang.String, boolean);
+    method public void clearPassword();
+    method public char[] getPassword();
+    method public java.lang.String getPrompt();
+    method public boolean isEchoOn();
+    method public void setPassword(char[]);
+  }
+
+  public class UnsupportedCallbackException extends java.lang.Exception {
+    ctor public UnsupportedCallbackException(javax.security.auth.callback.Callback);
+    ctor public UnsupportedCallbackException(javax.security.auth.callback.Callback, java.lang.String);
+    method public javax.security.auth.callback.Callback getCallback();
+  }
+
+}
+
+package javax.security.auth.login {
+
+  public class LoginException extends java.security.GeneralSecurityException {
+    ctor public LoginException();
+    ctor public LoginException(java.lang.String);
+  }
+
+}
+
+package javax.security.auth.x500 {
+
+  public final class X500Principal implements java.security.Principal java.io.Serializable {
+    ctor public X500Principal(byte[]);
+    ctor public X500Principal(java.io.InputStream);
+    ctor public X500Principal(java.lang.String);
+    ctor public X500Principal(java.lang.String, java.util.Map<java.lang.String, java.lang.String>);
+    method public byte[] getEncoded();
+    method public java.lang.String getName();
+    method public java.lang.String getName(java.lang.String);
+    method public java.lang.String getName(java.lang.String, java.util.Map<java.lang.String, java.lang.String>);
+    field public static final java.lang.String CANONICAL = "CANONICAL";
+    field public static final java.lang.String RFC1779 = "RFC1779";
+    field public static final java.lang.String RFC2253 = "RFC2253";
+  }
+
+}
+
+package javax.security.cert {
+
+  public abstract class Certificate {
+    ctor public Certificate();
+    method public abstract byte[] getEncoded() throws javax.security.cert.CertificateEncodingException;
+    method public abstract java.security.PublicKey getPublicKey();
+    method public abstract java.lang.String toString();
+    method public abstract void verify(java.security.PublicKey) throws javax.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException, java.security.SignatureException;
+    method public abstract void verify(java.security.PublicKey, java.lang.String) throws javax.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException, java.security.SignatureException;
+  }
+
+  public class CertificateEncodingException extends javax.security.cert.CertificateException {
+    ctor public CertificateEncodingException(java.lang.String);
+    ctor public CertificateEncodingException();
+  }
+
+  public class CertificateException extends java.lang.Exception {
+    ctor public CertificateException(java.lang.String);
+    ctor public CertificateException();
+  }
+
+  public class CertificateExpiredException extends javax.security.cert.CertificateException {
+    ctor public CertificateExpiredException(java.lang.String);
+    ctor public CertificateExpiredException();
+  }
+
+  public class CertificateNotYetValidException extends javax.security.cert.CertificateException {
+    ctor public CertificateNotYetValidException(java.lang.String);
+    ctor public CertificateNotYetValidException();
+  }
+
+  public class CertificateParsingException extends javax.security.cert.CertificateException {
+    ctor public CertificateParsingException(java.lang.String);
+    ctor public CertificateParsingException();
+  }
+
+  public abstract class X509Certificate extends javax.security.cert.Certificate {
+    ctor public X509Certificate();
+    method public abstract void checkValidity() throws javax.security.cert.CertificateExpiredException, javax.security.cert.CertificateNotYetValidException;
+    method public abstract void checkValidity(java.util.Date) throws javax.security.cert.CertificateExpiredException, javax.security.cert.CertificateNotYetValidException;
+    method public static final javax.security.cert.X509Certificate getInstance(java.io.InputStream) throws javax.security.cert.CertificateException;
+    method public static final javax.security.cert.X509Certificate getInstance(byte[]) throws javax.security.cert.CertificateException;
+    method public abstract java.security.Principal getIssuerDN();
+    method public abstract java.util.Date getNotAfter();
+    method public abstract java.util.Date getNotBefore();
+    method public abstract java.math.BigInteger getSerialNumber();
+    method public abstract java.lang.String getSigAlgName();
+    method public abstract java.lang.String getSigAlgOID();
+    method public abstract byte[] getSigAlgParams();
+    method public abstract java.security.Principal getSubjectDN();
+    method public abstract int getVersion();
+  }
+
+}
+
+package javax.sql {
+
+  public abstract interface CommonDataSource {
+    method public abstract java.io.PrintWriter getLogWriter() throws java.sql.SQLException;
+    method public abstract int getLoginTimeout() throws java.sql.SQLException;
+    method public abstract void setLogWriter(java.io.PrintWriter) throws java.sql.SQLException;
+    method public abstract void setLoginTimeout(int) throws java.sql.SQLException;
+  }
+
+  public class ConnectionEvent extends java.util.EventObject implements java.io.Serializable {
+    ctor public ConnectionEvent(javax.sql.PooledConnection);
+    ctor public ConnectionEvent(javax.sql.PooledConnection, java.sql.SQLException);
+    method public java.sql.SQLException getSQLException();
+  }
+
+  public abstract interface ConnectionEventListener implements java.util.EventListener {
+    method public abstract void connectionClosed(javax.sql.ConnectionEvent);
+    method public abstract void connectionErrorOccurred(javax.sql.ConnectionEvent);
+  }
+
+  public abstract interface ConnectionPoolDataSource implements javax.sql.CommonDataSource {
+    method public abstract javax.sql.PooledConnection getPooledConnection() throws java.sql.SQLException;
+    method public abstract javax.sql.PooledConnection getPooledConnection(java.lang.String, java.lang.String) throws java.sql.SQLException;
+  }
+
+  public abstract interface DataSource implements javax.sql.CommonDataSource java.sql.Wrapper {
+    method public abstract java.sql.Connection getConnection() throws java.sql.SQLException;
+    method public abstract java.sql.Connection getConnection(java.lang.String, java.lang.String) throws java.sql.SQLException;
+  }
+
+  public abstract interface PooledConnection {
+    method public abstract void addConnectionEventListener(javax.sql.ConnectionEventListener);
+    method public abstract void addStatementEventListener(javax.sql.StatementEventListener);
+    method public abstract void close() throws java.sql.SQLException;
+    method public abstract java.sql.Connection getConnection() throws java.sql.SQLException;
+    method public abstract void removeConnectionEventListener(javax.sql.ConnectionEventListener);
+    method public abstract void removeStatementEventListener(javax.sql.StatementEventListener);
+  }
+
+  public abstract interface RowSet implements java.sql.ResultSet {
+    method public abstract void addRowSetListener(javax.sql.RowSetListener);
+    method public abstract void clearParameters() throws java.sql.SQLException;
+    method public abstract void execute() throws java.sql.SQLException;
+    method public abstract java.lang.String getCommand();
+    method public abstract java.lang.String getDataSourceName();
+    method public abstract boolean getEscapeProcessing() throws java.sql.SQLException;
+    method public abstract int getMaxFieldSize() throws java.sql.SQLException;
+    method public abstract int getMaxRows() throws java.sql.SQLException;
+    method public abstract java.lang.String getPassword();
+    method public abstract int getQueryTimeout() throws java.sql.SQLException;
+    method public abstract int getTransactionIsolation();
+    method public abstract java.util.Map<java.lang.String, java.lang.Class<?>> getTypeMap() throws java.sql.SQLException;
+    method public abstract java.lang.String getUrl() throws java.sql.SQLException;
+    method public abstract java.lang.String getUsername();
+    method public abstract boolean isReadOnly();
+    method public abstract void removeRowSetListener(javax.sql.RowSetListener);
+    method public abstract void setArray(int, java.sql.Array) throws java.sql.SQLException;
+    method public abstract void setAsciiStream(int, java.io.InputStream, int) throws java.sql.SQLException;
+    method public abstract void setAsciiStream(int, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void setAsciiStream(java.lang.String, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void setAsciiStream(java.lang.String, java.io.InputStream, int) throws java.sql.SQLException;
+    method public abstract void setBigDecimal(int, java.math.BigDecimal) throws java.sql.SQLException;
+    method public abstract void setBigDecimal(java.lang.String, java.math.BigDecimal) throws java.sql.SQLException;
+    method public abstract void setBinaryStream(int, java.io.InputStream, int) throws java.sql.SQLException;
+    method public abstract void setBinaryStream(int, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void setBinaryStream(java.lang.String, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void setBinaryStream(java.lang.String, java.io.InputStream, int) throws java.sql.SQLException;
+    method public abstract void setBlob(int, java.sql.Blob) throws java.sql.SQLException;
+    method public abstract void setBlob(int, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void setBlob(int, java.io.InputStream, long) throws java.sql.SQLException;
+    method public abstract void setBlob(java.lang.String, java.io.InputStream) throws java.sql.SQLException;
+    method public abstract void setBlob(java.lang.String, java.io.InputStream, long) throws java.sql.SQLException;
+    method public abstract void setBlob(java.lang.String, java.sql.Blob) throws java.sql.SQLException;
+    method public abstract void setBoolean(int, boolean) throws java.sql.SQLException;
+    method public abstract void setBoolean(java.lang.String, boolean) throws java.sql.SQLException;
+    method public abstract void setByte(int, byte) throws java.sql.SQLException;
+    method public abstract void setByte(java.lang.String, byte) throws java.sql.SQLException;
+    method public abstract void setBytes(int, byte[]) throws java.sql.SQLException;
+    method public abstract void setBytes(java.lang.String, byte[]) throws java.sql.SQLException;
+    method public abstract void setCharacterStream(int, java.io.Reader, int) throws java.sql.SQLException;
+    method public abstract void setCharacterStream(int, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void setCharacterStream(java.lang.String, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void setCharacterStream(java.lang.String, java.io.Reader, int) throws java.sql.SQLException;
+    method public abstract void setClob(int, java.sql.Clob) throws java.sql.SQLException;
+    method public abstract void setClob(int, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void setClob(int, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void setClob(java.lang.String, java.sql.Clob) throws java.sql.SQLException;
+    method public abstract void setClob(java.lang.String, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void setClob(java.lang.String, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void setCommand(java.lang.String) throws java.sql.SQLException;
+    method public abstract void setConcurrency(int) throws java.sql.SQLException;
+    method public abstract void setDataSourceName(java.lang.String) throws java.sql.SQLException;
+    method public abstract void setDate(int, java.sql.Date) throws java.sql.SQLException;
+    method public abstract void setDate(int, java.sql.Date, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract void setDate(java.lang.String, java.sql.Date) throws java.sql.SQLException;
+    method public abstract void setDate(java.lang.String, java.sql.Date, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract void setDouble(int, double) throws java.sql.SQLException;
+    method public abstract void setDouble(java.lang.String, double) throws java.sql.SQLException;
+    method public abstract void setEscapeProcessing(boolean) throws java.sql.SQLException;
+    method public abstract void setFloat(int, float) throws java.sql.SQLException;
+    method public abstract void setFloat(java.lang.String, float) throws java.sql.SQLException;
+    method public abstract void setInt(int, int) throws java.sql.SQLException;
+    method public abstract void setInt(java.lang.String, int) throws java.sql.SQLException;
+    method public abstract void setLong(int, long) throws java.sql.SQLException;
+    method public abstract void setLong(java.lang.String, long) throws java.sql.SQLException;
+    method public abstract void setMaxFieldSize(int) throws java.sql.SQLException;
+    method public abstract void setMaxRows(int) throws java.sql.SQLException;
+    method public abstract void setNCharacterStream(int, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void setNCharacterStream(int, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void setNCharacterStream(java.lang.String, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void setNCharacterStream(java.lang.String, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void setNClob(int, java.sql.NClob) throws java.sql.SQLException;
+    method public abstract void setNClob(int, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void setNClob(int, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void setNClob(java.lang.String, java.sql.NClob) throws java.sql.SQLException;
+    method public abstract void setNClob(java.lang.String, java.io.Reader) throws java.sql.SQLException;
+    method public abstract void setNClob(java.lang.String, java.io.Reader, long) throws java.sql.SQLException;
+    method public abstract void setNString(int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setNString(java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setNull(int, int) throws java.sql.SQLException;
+    method public abstract void setNull(int, int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setNull(java.lang.String, int) throws java.sql.SQLException;
+    method public abstract void setNull(java.lang.String, int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setObject(int, java.lang.Object) throws java.sql.SQLException;
+    method public abstract void setObject(int, java.lang.Object, int) throws java.sql.SQLException;
+    method public abstract void setObject(int, java.lang.Object, int, int) throws java.sql.SQLException;
+    method public abstract void setObject(java.lang.String, java.lang.Object) throws java.sql.SQLException;
+    method public abstract void setObject(java.lang.String, java.lang.Object, int) throws java.sql.SQLException;
+    method public abstract void setObject(java.lang.String, java.lang.Object, int, int) throws java.sql.SQLException;
+    method public abstract void setPassword(java.lang.String) throws java.sql.SQLException;
+    method public abstract void setQueryTimeout(int) throws java.sql.SQLException;
+    method public abstract void setReadOnly(boolean) throws java.sql.SQLException;
+    method public abstract void setRef(int, java.sql.Ref) throws java.sql.SQLException;
+    method public abstract void setRowId(int, java.sql.RowId) throws java.sql.SQLException;
+    method public abstract void setRowId(java.lang.String, java.sql.RowId) throws java.sql.SQLException;
+    method public abstract void setSQLXML(int, java.sql.SQLXML) throws java.sql.SQLException;
+    method public abstract void setSQLXML(java.lang.String, java.sql.SQLXML) throws java.sql.SQLException;
+    method public abstract void setShort(int, short) throws java.sql.SQLException;
+    method public abstract void setShort(java.lang.String, short) throws java.sql.SQLException;
+    method public abstract void setString(int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setString(java.lang.String, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setTime(int, java.sql.Time) throws java.sql.SQLException;
+    method public abstract void setTime(int, java.sql.Time, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract void setTime(java.lang.String, java.sql.Time) throws java.sql.SQLException;
+    method public abstract void setTime(java.lang.String, java.sql.Time, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract void setTimestamp(int, java.sql.Timestamp) throws java.sql.SQLException;
+    method public abstract void setTimestamp(int, java.sql.Timestamp, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract void setTimestamp(java.lang.String, java.sql.Timestamp) throws java.sql.SQLException;
+    method public abstract void setTimestamp(java.lang.String, java.sql.Timestamp, java.util.Calendar) throws java.sql.SQLException;
+    method public abstract void setTransactionIsolation(int) throws java.sql.SQLException;
+    method public abstract void setType(int) throws java.sql.SQLException;
+    method public abstract void setTypeMap(java.util.Map<java.lang.String, java.lang.Class<?>>) throws java.sql.SQLException;
+    method public abstract void setURL(int, java.net.URL) throws java.sql.SQLException;
+    method public abstract void setUrl(java.lang.String) throws java.sql.SQLException;
+    method public abstract void setUsername(java.lang.String) throws java.sql.SQLException;
+  }
+
+  public class RowSetEvent extends java.util.EventObject implements java.io.Serializable {
+    ctor public RowSetEvent(javax.sql.RowSet);
+  }
+
+  public abstract interface RowSetInternal {
+    method public abstract java.sql.Connection getConnection() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getOriginal() throws java.sql.SQLException;
+    method public abstract java.sql.ResultSet getOriginalRow() throws java.sql.SQLException;
+    method public abstract java.lang.Object[] getParams() throws java.sql.SQLException;
+    method public abstract void setMetaData(javax.sql.RowSetMetaData) throws java.sql.SQLException;
+  }
+
+  public abstract interface RowSetListener implements java.util.EventListener {
+    method public abstract void cursorMoved(javax.sql.RowSetEvent);
+    method public abstract void rowChanged(javax.sql.RowSetEvent);
+    method public abstract void rowSetChanged(javax.sql.RowSetEvent);
+  }
+
+  public abstract interface RowSetMetaData implements java.sql.ResultSetMetaData {
+    method public abstract void setAutoIncrement(int, boolean) throws java.sql.SQLException;
+    method public abstract void setCaseSensitive(int, boolean) throws java.sql.SQLException;
+    method public abstract void setCatalogName(int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setColumnCount(int) throws java.sql.SQLException;
+    method public abstract void setColumnDisplaySize(int, int) throws java.sql.SQLException;
+    method public abstract void setColumnLabel(int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setColumnName(int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setColumnType(int, int) throws java.sql.SQLException;
+    method public abstract void setColumnTypeName(int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setCurrency(int, boolean) throws java.sql.SQLException;
+    method public abstract void setNullable(int, int) throws java.sql.SQLException;
+    method public abstract void setPrecision(int, int) throws java.sql.SQLException;
+    method public abstract void setScale(int, int) throws java.sql.SQLException;
+    method public abstract void setSchemaName(int, java.lang.String) throws java.sql.SQLException;
+    method public abstract void setSearchable(int, boolean) throws java.sql.SQLException;
+    method public abstract void setSigned(int, boolean) throws java.sql.SQLException;
+    method public abstract void setTableName(int, java.lang.String) throws java.sql.SQLException;
+  }
+
+  public abstract interface RowSetReader {
+    method public abstract void readData(javax.sql.RowSetInternal) throws java.sql.SQLException;
+  }
+
+  public abstract interface RowSetWriter {
+    method public abstract boolean writeData(javax.sql.RowSetInternal) throws java.sql.SQLException;
+  }
+
+  public class StatementEvent extends java.util.EventObject {
+    ctor public StatementEvent(javax.sql.PooledConnection, java.sql.PreparedStatement, java.sql.SQLException);
+    ctor public StatementEvent(javax.sql.PooledConnection, java.sql.PreparedStatement);
+    method public java.sql.SQLException getSQLException();
+    method public java.sql.PreparedStatement getStatement();
+  }
+
+  public abstract interface StatementEventListener implements java.util.EventListener {
+    method public abstract void statementClosed(javax.sql.StatementEvent);
+    method public abstract void statementErrorOccurred(javax.sql.StatementEvent);
+  }
+
+}
+
+package javax.xml {
+
+  public final class XMLConstants {
+    field public static final java.lang.String DEFAULT_NS_PREFIX = "";
+    field public static final java.lang.String FEATURE_SECURE_PROCESSING = "http://javax.xml.XMLConstants/feature/secure-processing";
+    field public static final java.lang.String NULL_NS_URI = "";
+    field public static final java.lang.String RELAXNG_NS_URI = "http://relaxng.org/ns/structure/1.0";
+    field public static final java.lang.String W3C_XML_SCHEMA_INSTANCE_NS_URI = "http://www.w3.org/2001/XMLSchema-instance";
+    field public static final java.lang.String W3C_XML_SCHEMA_NS_URI = "http://www.w3.org/2001/XMLSchema";
+    field public static final java.lang.String W3C_XPATH_DATATYPE_NS_URI = "http://www.w3.org/2003/11/xpath-datatypes";
+    field public static final java.lang.String XMLNS_ATTRIBUTE = "xmlns";
+    field public static final java.lang.String XMLNS_ATTRIBUTE_NS_URI = "http://www.w3.org/2000/xmlns/";
+    field public static final java.lang.String XML_DTD_NS_URI = "http://www.w3.org/TR/REC-xml";
+    field public static final java.lang.String XML_NS_PREFIX = "xml";
+    field public static final java.lang.String XML_NS_URI = "http://www.w3.org/XML/1998/namespace";
+  }
+
+}
+
+package javax.xml.datatype {
+
+  public class DatatypeConfigurationException extends java.lang.Exception {
+    ctor public DatatypeConfigurationException();
+    ctor public DatatypeConfigurationException(java.lang.String);
+    ctor public DatatypeConfigurationException(java.lang.String, java.lang.Throwable);
+    ctor public DatatypeConfigurationException(java.lang.Throwable);
+  }
+
+  public final class DatatypeConstants {
+    field public static final int APRIL = 4; // 0x4
+    field public static final int AUGUST = 8; // 0x8
+    field public static final javax.xml.namespace.QName DATE;
+    field public static final javax.xml.namespace.QName DATETIME;
+    field public static final javax.xml.datatype.DatatypeConstants.Field DAYS;
+    field public static final int DECEMBER = 12; // 0xc
+    field public static final javax.xml.namespace.QName DURATION;
+    field public static final javax.xml.namespace.QName DURATION_DAYTIME;
+    field public static final javax.xml.namespace.QName DURATION_YEARMONTH;
+    field public static final int EQUAL = 0; // 0x0
+    field public static final int FEBRUARY = 2; // 0x2
+    field public static final int FIELD_UNDEFINED = -2147483648; // 0x80000000
+    field public static final javax.xml.namespace.QName GDAY;
+    field public static final javax.xml.namespace.QName GMONTH;
+    field public static final javax.xml.namespace.QName GMONTHDAY;
+    field public static final int GREATER = 1; // 0x1
+    field public static final javax.xml.namespace.QName GYEAR;
+    field public static final javax.xml.namespace.QName GYEARMONTH;
+    field public static final javax.xml.datatype.DatatypeConstants.Field HOURS;
+    field public static final int INDETERMINATE = 2; // 0x2
+    field public static final int JANUARY = 1; // 0x1
+    field public static final int JULY = 7; // 0x7
+    field public static final int JUNE = 6; // 0x6
+    field public static final int LESSER = -1; // 0xffffffff
+    field public static final int MARCH = 3; // 0x3
+    field public static final int MAX_TIMEZONE_OFFSET = -840; // 0xfffffcb8
+    field public static final int MAY = 5; // 0x5
+    field public static final javax.xml.datatype.DatatypeConstants.Field MINUTES;
+    field public static final int MIN_TIMEZONE_OFFSET = 840; // 0x348
+    field public static final javax.xml.datatype.DatatypeConstants.Field MONTHS;
+    field public static final int NOVEMBER = 11; // 0xb
+    field public static final int OCTOBER = 10; // 0xa
+    field public static final javax.xml.datatype.DatatypeConstants.Field SECONDS;
+    field public static final int SEPTEMBER = 9; // 0x9
+    field public static final javax.xml.namespace.QName TIME;
+    field public static final javax.xml.datatype.DatatypeConstants.Field YEARS;
+  }
+
+  public static final class DatatypeConstants.Field {
+    method public int getId();
+  }
+
+  public abstract class DatatypeFactory {
+    ctor protected DatatypeFactory();
+    method public abstract javax.xml.datatype.Duration newDuration(java.lang.String);
+    method public abstract javax.xml.datatype.Duration newDuration(long);
+    method public abstract javax.xml.datatype.Duration newDuration(boolean, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.math.BigDecimal);
+    method public javax.xml.datatype.Duration newDuration(boolean, int, int, int, int, int, int);
+    method public javax.xml.datatype.Duration newDurationDayTime(java.lang.String);
+    method public javax.xml.datatype.Duration newDurationDayTime(long);
+    method public javax.xml.datatype.Duration newDurationDayTime(boolean, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger, java.math.BigInteger);
+    method public javax.xml.datatype.Duration newDurationDayTime(boolean, int, int, int, int);
+    method public javax.xml.datatype.Duration newDurationYearMonth(java.lang.String);
+    method public javax.xml.datatype.Duration newDurationYearMonth(long);
+    method public javax.xml.datatype.Duration newDurationYearMonth(boolean, java.math.BigInteger, java.math.BigInteger);
+    method public javax.xml.datatype.Duration newDurationYearMonth(boolean, int, int);
+    method public static javax.xml.datatype.DatatypeFactory newInstance() throws javax.xml.datatype.DatatypeConfigurationException;
+    method public static javax.xml.datatype.DatatypeFactory newInstance(java.lang.String, java.lang.ClassLoader) throws javax.xml.datatype.DatatypeConfigurationException;
+    method public abstract javax.xml.datatype.XMLGregorianCalendar newXMLGregorianCalendar();
+    method public abstract javax.xml.datatype.XMLGregorianCalendar newXMLGregorianCalendar(java.lang.String);
+    method public abstract javax.xml.datatype.XMLGregorianCalendar newXMLGregorianCalendar(java.util.GregorianCalendar);
+    method public abstract javax.xml.datatype.XMLGregorianCalendar newXMLGregorianCalendar(java.math.BigInteger, int, int, int, int, int, java.math.BigDecimal, int);
+    method public javax.xml.datatype.XMLGregorianCalendar newXMLGregorianCalendar(int, int, int, int, int, int, int, int);
+    method public javax.xml.datatype.XMLGregorianCalendar newXMLGregorianCalendarDate(int, int, int, int);
+    method public javax.xml.datatype.XMLGregorianCalendar newXMLGregorianCalendarTime(int, int, int, int);
+    method public javax.xml.datatype.XMLGregorianCalendar newXMLGregorianCalendarTime(int, int, int, java.math.BigDecimal, int);
+    method public javax.xml.datatype.XMLGregorianCalendar newXMLGregorianCalendarTime(int, int, int, int, int);
+    field public static final java.lang.String DATATYPEFACTORY_IMPLEMENTATION_CLASS;
+    field public static final java.lang.String DATATYPEFACTORY_PROPERTY = "javax.xml.datatype.DatatypeFactory";
+  }
+
+  public abstract class Duration {
+    ctor public Duration();
+    method public abstract javax.xml.datatype.Duration add(javax.xml.datatype.Duration);
+    method public abstract void addTo(java.util.Calendar);
+    method public void addTo(java.util.Date);
+    method public abstract int compare(javax.xml.datatype.Duration);
+    method public int getDays();
+    method public abstract java.lang.Number getField(javax.xml.datatype.DatatypeConstants.Field);
+    method public int getHours();
+    method public int getMinutes();
+    method public int getMonths();
+    method public int getSeconds();
+    method public abstract int getSign();
+    method public long getTimeInMillis(java.util.Calendar);
+    method public long getTimeInMillis(java.util.Date);
+    method public javax.xml.namespace.QName getXMLSchemaType();
+    method public int getYears();
+    method public abstract int hashCode();
+    method public boolean isLongerThan(javax.xml.datatype.Duration);
+    method public abstract boolean isSet(javax.xml.datatype.DatatypeConstants.Field);
+    method public boolean isShorterThan(javax.xml.datatype.Duration);
+    method public javax.xml.datatype.Duration multiply(int);
+    method public abstract javax.xml.datatype.Duration multiply(java.math.BigDecimal);
+    method public abstract javax.xml.datatype.Duration negate();
+    method public abstract javax.xml.datatype.Duration normalizeWith(java.util.Calendar);
+    method public javax.xml.datatype.Duration subtract(javax.xml.datatype.Duration);
+  }
+
+  public abstract class XMLGregorianCalendar implements java.lang.Cloneable {
+    ctor public XMLGregorianCalendar();
+    method public abstract void add(javax.xml.datatype.Duration);
+    method public abstract void clear();
+    method public abstract java.lang.Object clone();
+    method public abstract int compare(javax.xml.datatype.XMLGregorianCalendar);
+    method public abstract int getDay();
+    method public abstract java.math.BigInteger getEon();
+    method public abstract java.math.BigInteger getEonAndYear();
+    method public abstract java.math.BigDecimal getFractionalSecond();
+    method public abstract int getHour();
+    method public int getMillisecond();
+    method public abstract int getMinute();
+    method public abstract int getMonth();
+    method public abstract int getSecond();
+    method public abstract java.util.TimeZone getTimeZone(int);
+    method public abstract int getTimezone();
+    method public abstract javax.xml.namespace.QName getXMLSchemaType();
+    method public abstract int getYear();
+    method public abstract boolean isValid();
+    method public abstract javax.xml.datatype.XMLGregorianCalendar normalize();
+    method public abstract void reset();
+    method public abstract void setDay(int);
+    method public abstract void setFractionalSecond(java.math.BigDecimal);
+    method public abstract void setHour(int);
+    method public abstract void setMillisecond(int);
+    method public abstract void setMinute(int);
+    method public abstract void setMonth(int);
+    method public abstract void setSecond(int);
+    method public void setTime(int, int, int);
+    method public void setTime(int, int, int, java.math.BigDecimal);
+    method public void setTime(int, int, int, int);
+    method public abstract void setTimezone(int);
+    method public abstract void setYear(java.math.BigInteger);
+    method public abstract void setYear(int);
+    method public abstract java.util.GregorianCalendar toGregorianCalendar();
+    method public abstract java.util.GregorianCalendar toGregorianCalendar(java.util.TimeZone, java.util.Locale, javax.xml.datatype.XMLGregorianCalendar);
+    method public abstract java.lang.String toXMLFormat();
+  }
+
+}
+
+package javax.xml.namespace {
+
+  public abstract interface NamespaceContext {
+    method public abstract java.lang.String getNamespaceURI(java.lang.String);
+    method public abstract java.lang.String getPrefix(java.lang.String);
+    method public abstract java.util.Iterator getPrefixes(java.lang.String);
+  }
+
+  public class QName implements java.io.Serializable {
+    ctor public QName(java.lang.String, java.lang.String);
+    ctor public QName(java.lang.String, java.lang.String, java.lang.String);
+    ctor public QName(java.lang.String);
+    method public final boolean equals(java.lang.Object);
+    method public java.lang.String getLocalPart();
+    method public java.lang.String getNamespaceURI();
+    method public java.lang.String getPrefix();
+    method public final int hashCode();
+    method public static javax.xml.namespace.QName valueOf(java.lang.String);
+  }
+
+}
+
+package javax.xml.parsers {
+
+  public abstract class DocumentBuilder {
+    ctor protected DocumentBuilder();
+    method public abstract org.w3c.dom.DOMImplementation getDOMImplementation();
+    method public javax.xml.validation.Schema getSchema();
+    method public abstract boolean isNamespaceAware();
+    method public abstract boolean isValidating();
+    method public boolean isXIncludeAware();
+    method public abstract org.w3c.dom.Document newDocument();
+    method public org.w3c.dom.Document parse(java.io.InputStream) throws java.io.IOException, org.xml.sax.SAXException;
+    method public org.w3c.dom.Document parse(java.io.InputStream, java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+    method public org.w3c.dom.Document parse(java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+    method public org.w3c.dom.Document parse(java.io.File) throws java.io.IOException, org.xml.sax.SAXException;
+    method public abstract org.w3c.dom.Document parse(org.xml.sax.InputSource) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void reset();
+    method public abstract void setEntityResolver(org.xml.sax.EntityResolver);
+    method public abstract void setErrorHandler(org.xml.sax.ErrorHandler);
+  }
+
+  public abstract class DocumentBuilderFactory {
+    ctor protected DocumentBuilderFactory();
+    method public abstract java.lang.Object getAttribute(java.lang.String) throws java.lang.IllegalArgumentException;
+    method public abstract boolean getFeature(java.lang.String) throws javax.xml.parsers.ParserConfigurationException;
+    method public javax.xml.validation.Schema getSchema();
+    method public boolean isCoalescing();
+    method public boolean isExpandEntityReferences();
+    method public boolean isIgnoringComments();
+    method public boolean isIgnoringElementContentWhitespace();
+    method public boolean isNamespaceAware();
+    method public boolean isValidating();
+    method public boolean isXIncludeAware();
+    method public abstract javax.xml.parsers.DocumentBuilder newDocumentBuilder() throws javax.xml.parsers.ParserConfigurationException;
+    method public static javax.xml.parsers.DocumentBuilderFactory newInstance();
+    method public static javax.xml.parsers.DocumentBuilderFactory newInstance(java.lang.String, java.lang.ClassLoader);
+    method public abstract void setAttribute(java.lang.String, java.lang.Object) throws java.lang.IllegalArgumentException;
+    method public void setCoalescing(boolean);
+    method public void setExpandEntityReferences(boolean);
+    method public abstract void setFeature(java.lang.String, boolean) throws javax.xml.parsers.ParserConfigurationException;
+    method public void setIgnoringComments(boolean);
+    method public void setIgnoringElementContentWhitespace(boolean);
+    method public void setNamespaceAware(boolean);
+    method public void setSchema(javax.xml.validation.Schema);
+    method public void setValidating(boolean);
+    method public void setXIncludeAware(boolean);
+  }
+
+  public class FactoryConfigurationError extends java.lang.Error {
+    ctor public FactoryConfigurationError();
+    ctor public FactoryConfigurationError(java.lang.String);
+    ctor public FactoryConfigurationError(java.lang.Exception);
+    ctor public FactoryConfigurationError(java.lang.Exception, java.lang.String);
+    method public java.lang.Exception getException();
+  }
+
+  public class ParserConfigurationException extends java.lang.Exception {
+    ctor public ParserConfigurationException();
+    ctor public ParserConfigurationException(java.lang.String);
+  }
+
+  public abstract class SAXParser {
+    ctor protected SAXParser();
+    method public abstract org.xml.sax.Parser getParser() throws org.xml.sax.SAXException;
+    method public abstract java.lang.Object getProperty(java.lang.String) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public javax.xml.validation.Schema getSchema();
+    method public abstract org.xml.sax.XMLReader getXMLReader() throws org.xml.sax.SAXException;
+    method public abstract boolean isNamespaceAware();
+    method public abstract boolean isValidating();
+    method public boolean isXIncludeAware();
+    method public void parse(java.io.InputStream, org.xml.sax.HandlerBase) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void parse(java.io.InputStream, org.xml.sax.HandlerBase, java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void parse(java.io.InputStream, org.xml.sax.helpers.DefaultHandler) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void parse(java.io.InputStream, org.xml.sax.helpers.DefaultHandler, java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void parse(java.lang.String, org.xml.sax.HandlerBase) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void parse(java.lang.String, org.xml.sax.helpers.DefaultHandler) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void parse(java.io.File, org.xml.sax.HandlerBase) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void parse(java.io.File, org.xml.sax.helpers.DefaultHandler) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void parse(org.xml.sax.InputSource, org.xml.sax.HandlerBase) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void parse(org.xml.sax.InputSource, org.xml.sax.helpers.DefaultHandler) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void reset();
+    method public abstract void setProperty(java.lang.String, java.lang.Object) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+  }
+
+  public abstract class SAXParserFactory {
+    ctor protected SAXParserFactory();
+    method public abstract boolean getFeature(java.lang.String) throws javax.xml.parsers.ParserConfigurationException, org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public javax.xml.validation.Schema getSchema();
+    method public boolean isNamespaceAware();
+    method public boolean isValidating();
+    method public boolean isXIncludeAware();
+    method public static javax.xml.parsers.SAXParserFactory newInstance();
+    method public static javax.xml.parsers.SAXParserFactory newInstance(java.lang.String, java.lang.ClassLoader);
+    method public abstract javax.xml.parsers.SAXParser newSAXParser() throws javax.xml.parsers.ParserConfigurationException, org.xml.sax.SAXException;
+    method public abstract void setFeature(java.lang.String, boolean) throws javax.xml.parsers.ParserConfigurationException, org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public void setNamespaceAware(boolean);
+    method public void setSchema(javax.xml.validation.Schema);
+    method public void setValidating(boolean);
+    method public void setXIncludeAware(boolean);
+  }
+
+}
+
+package javax.xml.transform {
+
+  public abstract interface ErrorListener {
+    method public abstract void error(javax.xml.transform.TransformerException) throws javax.xml.transform.TransformerException;
+    method public abstract void fatalError(javax.xml.transform.TransformerException) throws javax.xml.transform.TransformerException;
+    method public abstract void warning(javax.xml.transform.TransformerException) throws javax.xml.transform.TransformerException;
+  }
+
+  public class OutputKeys {
+    field public static final java.lang.String CDATA_SECTION_ELEMENTS = "cdata-section-elements";
+    field public static final java.lang.String DOCTYPE_PUBLIC = "doctype-public";
+    field public static final java.lang.String DOCTYPE_SYSTEM = "doctype-system";
+    field public static final java.lang.String ENCODING = "encoding";
+    field public static final java.lang.String INDENT = "indent";
+    field public static final java.lang.String MEDIA_TYPE = "media-type";
+    field public static final java.lang.String METHOD = "method";
+    field public static final java.lang.String OMIT_XML_DECLARATION = "omit-xml-declaration";
+    field public static final java.lang.String STANDALONE = "standalone";
+    field public static final java.lang.String VERSION = "version";
+  }
+
+  public abstract interface Result {
+    method public abstract java.lang.String getSystemId();
+    method public abstract void setSystemId(java.lang.String);
+    field public static final java.lang.String PI_DISABLE_OUTPUT_ESCAPING = "javax.xml.transform.disable-output-escaping";
+    field public static final java.lang.String PI_ENABLE_OUTPUT_ESCAPING = "javax.xml.transform.enable-output-escaping";
+  }
+
+  public abstract interface Source {
+    method public abstract java.lang.String getSystemId();
+    method public abstract void setSystemId(java.lang.String);
+  }
+
+  public abstract interface SourceLocator {
+    method public abstract int getColumnNumber();
+    method public abstract int getLineNumber();
+    method public abstract java.lang.String getPublicId();
+    method public abstract java.lang.String getSystemId();
+  }
+
+  public abstract interface Templates {
+    method public abstract java.util.Properties getOutputProperties();
+    method public abstract javax.xml.transform.Transformer newTransformer() throws javax.xml.transform.TransformerConfigurationException;
+  }
+
+  public abstract class Transformer {
+    ctor protected Transformer();
+    method public abstract void clearParameters();
+    method public abstract javax.xml.transform.ErrorListener getErrorListener();
+    method public abstract java.util.Properties getOutputProperties();
+    method public abstract java.lang.String getOutputProperty(java.lang.String) throws java.lang.IllegalArgumentException;
+    method public abstract java.lang.Object getParameter(java.lang.String);
+    method public abstract javax.xml.transform.URIResolver getURIResolver();
+    method public void reset();
+    method public abstract void setErrorListener(javax.xml.transform.ErrorListener) throws java.lang.IllegalArgumentException;
+    method public abstract void setOutputProperties(java.util.Properties);
+    method public abstract void setOutputProperty(java.lang.String, java.lang.String) throws java.lang.IllegalArgumentException;
+    method public abstract void setParameter(java.lang.String, java.lang.Object);
+    method public abstract void setURIResolver(javax.xml.transform.URIResolver);
+    method public abstract void transform(javax.xml.transform.Source, javax.xml.transform.Result) throws javax.xml.transform.TransformerException;
+  }
+
+  public class TransformerConfigurationException extends javax.xml.transform.TransformerException {
+    ctor public TransformerConfigurationException();
+    ctor public TransformerConfigurationException(java.lang.String);
+    ctor public TransformerConfigurationException(java.lang.Throwable);
+    ctor public TransformerConfigurationException(java.lang.String, java.lang.Throwable);
+    ctor public TransformerConfigurationException(java.lang.String, javax.xml.transform.SourceLocator);
+    ctor public TransformerConfigurationException(java.lang.String, javax.xml.transform.SourceLocator, java.lang.Throwable);
+  }
+
+  public class TransformerException extends java.lang.Exception {
+    ctor public TransformerException(java.lang.String);
+    ctor public TransformerException(java.lang.Throwable);
+    ctor public TransformerException(java.lang.String, java.lang.Throwable);
+    ctor public TransformerException(java.lang.String, javax.xml.transform.SourceLocator);
+    ctor public TransformerException(java.lang.String, javax.xml.transform.SourceLocator, java.lang.Throwable);
+    method public java.lang.Throwable getException();
+    method public java.lang.String getLocationAsString();
+    method public javax.xml.transform.SourceLocator getLocator();
+    method public java.lang.String getMessageAndLocation();
+    method public void setLocator(javax.xml.transform.SourceLocator);
+  }
+
+  public abstract class TransformerFactory {
+    ctor protected TransformerFactory();
+    method public abstract javax.xml.transform.Source getAssociatedStylesheet(javax.xml.transform.Source, java.lang.String, java.lang.String, java.lang.String) throws javax.xml.transform.TransformerConfigurationException;
+    method public abstract java.lang.Object getAttribute(java.lang.String);
+    method public abstract javax.xml.transform.ErrorListener getErrorListener();
+    method public abstract boolean getFeature(java.lang.String);
+    method public abstract javax.xml.transform.URIResolver getURIResolver();
+    method public static javax.xml.transform.TransformerFactory newInstance() throws javax.xml.transform.TransformerFactoryConfigurationError;
+    method public static javax.xml.transform.TransformerFactory newInstance(java.lang.String, java.lang.ClassLoader) throws javax.xml.transform.TransformerFactoryConfigurationError;
+    method public abstract javax.xml.transform.Templates newTemplates(javax.xml.transform.Source) throws javax.xml.transform.TransformerConfigurationException;
+    method public abstract javax.xml.transform.Transformer newTransformer(javax.xml.transform.Source) throws javax.xml.transform.TransformerConfigurationException;
+    method public abstract javax.xml.transform.Transformer newTransformer() throws javax.xml.transform.TransformerConfigurationException;
+    method public abstract void setAttribute(java.lang.String, java.lang.Object);
+    method public abstract void setErrorListener(javax.xml.transform.ErrorListener);
+    method public abstract void setFeature(java.lang.String, boolean) throws javax.xml.transform.TransformerConfigurationException;
+    method public abstract void setURIResolver(javax.xml.transform.URIResolver);
+  }
+
+  public class TransformerFactoryConfigurationError extends java.lang.Error {
+    ctor public TransformerFactoryConfigurationError();
+    ctor public TransformerFactoryConfigurationError(java.lang.String);
+    ctor public TransformerFactoryConfigurationError(java.lang.Exception);
+    ctor public TransformerFactoryConfigurationError(java.lang.Exception, java.lang.String);
+    method public java.lang.Exception getException();
+  }
+
+  public abstract interface URIResolver {
+    method public abstract javax.xml.transform.Source resolve(java.lang.String, java.lang.String) throws javax.xml.transform.TransformerException;
+  }
+
+}
+
+package javax.xml.transform.dom {
+
+  public abstract interface DOMLocator implements javax.xml.transform.SourceLocator {
+    method public abstract org.w3c.dom.Node getOriginatingNode();
+  }
+
+  public class DOMResult implements javax.xml.transform.Result {
+    ctor public DOMResult();
+    ctor public DOMResult(org.w3c.dom.Node);
+    ctor public DOMResult(org.w3c.dom.Node, java.lang.String);
+    ctor public DOMResult(org.w3c.dom.Node, org.w3c.dom.Node);
+    ctor public DOMResult(org.w3c.dom.Node, org.w3c.dom.Node, java.lang.String);
+    method public org.w3c.dom.Node getNextSibling();
+    method public org.w3c.dom.Node getNode();
+    method public java.lang.String getSystemId();
+    method public void setNextSibling(org.w3c.dom.Node);
+    method public void setNode(org.w3c.dom.Node);
+    method public void setSystemId(java.lang.String);
+    field public static final java.lang.String FEATURE = "http://javax.xml.transform.dom.DOMResult/feature";
+  }
+
+  public class DOMSource implements javax.xml.transform.Source {
+    ctor public DOMSource();
+    ctor public DOMSource(org.w3c.dom.Node);
+    ctor public DOMSource(org.w3c.dom.Node, java.lang.String);
+    method public org.w3c.dom.Node getNode();
+    method public java.lang.String getSystemId();
+    method public void setNode(org.w3c.dom.Node);
+    method public void setSystemId(java.lang.String);
+    field public static final java.lang.String FEATURE = "http://javax.xml.transform.dom.DOMSource/feature";
+  }
+
+}
+
+package javax.xml.transform.sax {
+
+  public class SAXResult implements javax.xml.transform.Result {
+    ctor public SAXResult();
+    ctor public SAXResult(org.xml.sax.ContentHandler);
+    method public org.xml.sax.ContentHandler getHandler();
+    method public org.xml.sax.ext.LexicalHandler getLexicalHandler();
+    method public java.lang.String getSystemId();
+    method public void setHandler(org.xml.sax.ContentHandler);
+    method public void setLexicalHandler(org.xml.sax.ext.LexicalHandler);
+    method public void setSystemId(java.lang.String);
+    field public static final java.lang.String FEATURE = "http://javax.xml.transform.sax.SAXResult/feature";
+  }
+
+  public class SAXSource implements javax.xml.transform.Source {
+    ctor public SAXSource();
+    ctor public SAXSource(org.xml.sax.XMLReader, org.xml.sax.InputSource);
+    ctor public SAXSource(org.xml.sax.InputSource);
+    method public org.xml.sax.InputSource getInputSource();
+    method public java.lang.String getSystemId();
+    method public org.xml.sax.XMLReader getXMLReader();
+    method public void setInputSource(org.xml.sax.InputSource);
+    method public void setSystemId(java.lang.String);
+    method public void setXMLReader(org.xml.sax.XMLReader);
+    method public static org.xml.sax.InputSource sourceToInputSource(javax.xml.transform.Source);
+    field public static final java.lang.String FEATURE = "http://javax.xml.transform.sax.SAXSource/feature";
+  }
+
+  public abstract class SAXTransformerFactory extends javax.xml.transform.TransformerFactory {
+    ctor protected SAXTransformerFactory();
+    method public abstract javax.xml.transform.sax.TemplatesHandler newTemplatesHandler() throws javax.xml.transform.TransformerConfigurationException;
+    method public abstract javax.xml.transform.sax.TransformerHandler newTransformerHandler(javax.xml.transform.Source) throws javax.xml.transform.TransformerConfigurationException;
+    method public abstract javax.xml.transform.sax.TransformerHandler newTransformerHandler(javax.xml.transform.Templates) throws javax.xml.transform.TransformerConfigurationException;
+    method public abstract javax.xml.transform.sax.TransformerHandler newTransformerHandler() throws javax.xml.transform.TransformerConfigurationException;
+    method public abstract org.xml.sax.XMLFilter newXMLFilter(javax.xml.transform.Source) throws javax.xml.transform.TransformerConfigurationException;
+    method public abstract org.xml.sax.XMLFilter newXMLFilter(javax.xml.transform.Templates) throws javax.xml.transform.TransformerConfigurationException;
+    field public static final java.lang.String FEATURE = "http://javax.xml.transform.sax.SAXTransformerFactory/feature";
+    field public static final java.lang.String FEATURE_XMLFILTER = "http://javax.xml.transform.sax.SAXTransformerFactory/feature/xmlfilter";
+  }
+
+  public abstract interface TemplatesHandler implements org.xml.sax.ContentHandler {
+    method public abstract java.lang.String getSystemId();
+    method public abstract javax.xml.transform.Templates getTemplates();
+    method public abstract void setSystemId(java.lang.String);
+  }
+
+  public abstract interface TransformerHandler implements org.xml.sax.ContentHandler org.xml.sax.DTDHandler org.xml.sax.ext.LexicalHandler {
+    method public abstract java.lang.String getSystemId();
+    method public abstract javax.xml.transform.Transformer getTransformer();
+    method public abstract void setResult(javax.xml.transform.Result) throws java.lang.IllegalArgumentException;
+    method public abstract void setSystemId(java.lang.String);
+  }
+
+}
+
+package javax.xml.transform.stream {
+
+  public class StreamResult implements javax.xml.transform.Result {
+    ctor public StreamResult();
+    ctor public StreamResult(java.io.OutputStream);
+    ctor public StreamResult(java.io.Writer);
+    ctor public StreamResult(java.lang.String);
+    ctor public StreamResult(java.io.File);
+    method public java.io.OutputStream getOutputStream();
+    method public java.lang.String getSystemId();
+    method public java.io.Writer getWriter();
+    method public void setOutputStream(java.io.OutputStream);
+    method public void setSystemId(java.lang.String);
+    method public void setSystemId(java.io.File);
+    method public void setWriter(java.io.Writer);
+    field public static final java.lang.String FEATURE = "http://javax.xml.transform.stream.StreamResult/feature";
+  }
+
+  public class StreamSource implements javax.xml.transform.Source {
+    ctor public StreamSource();
+    ctor public StreamSource(java.io.InputStream);
+    ctor public StreamSource(java.io.InputStream, java.lang.String);
+    ctor public StreamSource(java.io.Reader);
+    ctor public StreamSource(java.io.Reader, java.lang.String);
+    ctor public StreamSource(java.lang.String);
+    ctor public StreamSource(java.io.File);
+    method public java.io.InputStream getInputStream();
+    method public java.lang.String getPublicId();
+    method public java.io.Reader getReader();
+    method public java.lang.String getSystemId();
+    method public void setInputStream(java.io.InputStream);
+    method public void setPublicId(java.lang.String);
+    method public void setReader(java.io.Reader);
+    method public void setSystemId(java.lang.String);
+    method public void setSystemId(java.io.File);
+    field public static final java.lang.String FEATURE = "http://javax.xml.transform.stream.StreamSource/feature";
+  }
+
+}
+
+package javax.xml.validation {
+
+  public abstract class Schema {
+    ctor protected Schema();
+    method public abstract javax.xml.validation.Validator newValidator();
+    method public abstract javax.xml.validation.ValidatorHandler newValidatorHandler();
+  }
+
+  public abstract class SchemaFactory {
+    ctor protected SchemaFactory();
+    method public abstract org.xml.sax.ErrorHandler getErrorHandler();
+    method public boolean getFeature(java.lang.String) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public java.lang.Object getProperty(java.lang.String) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public abstract org.w3c.dom.ls.LSResourceResolver getResourceResolver();
+    method public abstract boolean isSchemaLanguageSupported(java.lang.String);
+    method public static javax.xml.validation.SchemaFactory newInstance(java.lang.String);
+    method public static javax.xml.validation.SchemaFactory newInstance(java.lang.String, java.lang.String, java.lang.ClassLoader);
+    method public javax.xml.validation.Schema newSchema(javax.xml.transform.Source) throws org.xml.sax.SAXException;
+    method public javax.xml.validation.Schema newSchema(java.io.File) throws org.xml.sax.SAXException;
+    method public javax.xml.validation.Schema newSchema(java.net.URL) throws org.xml.sax.SAXException;
+    method public abstract javax.xml.validation.Schema newSchema(javax.xml.transform.Source[]) throws org.xml.sax.SAXException;
+    method public abstract javax.xml.validation.Schema newSchema() throws org.xml.sax.SAXException;
+    method public abstract void setErrorHandler(org.xml.sax.ErrorHandler);
+    method public void setFeature(java.lang.String, boolean) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public void setProperty(java.lang.String, java.lang.Object) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public abstract void setResourceResolver(org.w3c.dom.ls.LSResourceResolver);
+  }
+
+  public abstract class SchemaFactoryLoader {
+    ctor protected SchemaFactoryLoader();
+    method public abstract javax.xml.validation.SchemaFactory newFactory(java.lang.String);
+  }
+
+  public abstract class TypeInfoProvider {
+    ctor protected TypeInfoProvider();
+    method public abstract org.w3c.dom.TypeInfo getAttributeTypeInfo(int);
+    method public abstract org.w3c.dom.TypeInfo getElementTypeInfo();
+    method public abstract boolean isIdAttribute(int);
+    method public abstract boolean isSpecified(int);
+  }
+
+  public abstract class Validator {
+    ctor protected Validator();
+    method public abstract org.xml.sax.ErrorHandler getErrorHandler();
+    method public boolean getFeature(java.lang.String) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public java.lang.Object getProperty(java.lang.String) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public abstract org.w3c.dom.ls.LSResourceResolver getResourceResolver();
+    method public abstract void reset();
+    method public abstract void setErrorHandler(org.xml.sax.ErrorHandler);
+    method public void setFeature(java.lang.String, boolean) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public void setProperty(java.lang.String, java.lang.Object) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public abstract void setResourceResolver(org.w3c.dom.ls.LSResourceResolver);
+    method public void validate(javax.xml.transform.Source) throws java.io.IOException, org.xml.sax.SAXException;
+    method public abstract void validate(javax.xml.transform.Source, javax.xml.transform.Result) throws java.io.IOException, org.xml.sax.SAXException;
+  }
+
+  public abstract class ValidatorHandler implements org.xml.sax.ContentHandler {
+    ctor protected ValidatorHandler();
+    method public abstract org.xml.sax.ContentHandler getContentHandler();
+    method public abstract org.xml.sax.ErrorHandler getErrorHandler();
+    method public boolean getFeature(java.lang.String) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public java.lang.Object getProperty(java.lang.String) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public abstract org.w3c.dom.ls.LSResourceResolver getResourceResolver();
+    method public abstract javax.xml.validation.TypeInfoProvider getTypeInfoProvider();
+    method public abstract void setContentHandler(org.xml.sax.ContentHandler);
+    method public abstract void setErrorHandler(org.xml.sax.ErrorHandler);
+    method public void setFeature(java.lang.String, boolean) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public void setProperty(java.lang.String, java.lang.Object) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public abstract void setResourceResolver(org.w3c.dom.ls.LSResourceResolver);
+  }
+
+}
+
+package javax.xml.xpath {
+
+  public abstract interface XPath {
+    method public abstract javax.xml.xpath.XPathExpression compile(java.lang.String) throws javax.xml.xpath.XPathExpressionException;
+    method public abstract java.lang.Object evaluate(java.lang.String, java.lang.Object, javax.xml.namespace.QName) throws javax.xml.xpath.XPathExpressionException;
+    method public abstract java.lang.String evaluate(java.lang.String, java.lang.Object) throws javax.xml.xpath.XPathExpressionException;
+    method public abstract java.lang.Object evaluate(java.lang.String, org.xml.sax.InputSource, javax.xml.namespace.QName) throws javax.xml.xpath.XPathExpressionException;
+    method public abstract java.lang.String evaluate(java.lang.String, org.xml.sax.InputSource) throws javax.xml.xpath.XPathExpressionException;
+    method public abstract javax.xml.namespace.NamespaceContext getNamespaceContext();
+    method public abstract javax.xml.xpath.XPathFunctionResolver getXPathFunctionResolver();
+    method public abstract javax.xml.xpath.XPathVariableResolver getXPathVariableResolver();
+    method public abstract void reset();
+    method public abstract void setNamespaceContext(javax.xml.namespace.NamespaceContext);
+    method public abstract void setXPathFunctionResolver(javax.xml.xpath.XPathFunctionResolver);
+    method public abstract void setXPathVariableResolver(javax.xml.xpath.XPathVariableResolver);
+  }
+
+  public class XPathConstants {
+    field public static final javax.xml.namespace.QName BOOLEAN;
+    field public static final java.lang.String DOM_OBJECT_MODEL = "http://java.sun.com/jaxp/xpath/dom";
+    field public static final javax.xml.namespace.QName NODE;
+    field public static final javax.xml.namespace.QName NODESET;
+    field public static final javax.xml.namespace.QName NUMBER;
+    field public static final javax.xml.namespace.QName STRING;
+  }
+
+  public class XPathException extends java.lang.Exception {
+    ctor public XPathException(java.lang.String);
+    ctor public XPathException(java.lang.Throwable);
+  }
+
+  public abstract interface XPathExpression {
+    method public abstract java.lang.Object evaluate(java.lang.Object, javax.xml.namespace.QName) throws javax.xml.xpath.XPathExpressionException;
+    method public abstract java.lang.String evaluate(java.lang.Object) throws javax.xml.xpath.XPathExpressionException;
+    method public abstract java.lang.Object evaluate(org.xml.sax.InputSource, javax.xml.namespace.QName) throws javax.xml.xpath.XPathExpressionException;
+    method public abstract java.lang.String evaluate(org.xml.sax.InputSource) throws javax.xml.xpath.XPathExpressionException;
+  }
+
+  public class XPathExpressionException extends javax.xml.xpath.XPathException {
+    ctor public XPathExpressionException(java.lang.String);
+    ctor public XPathExpressionException(java.lang.Throwable);
+  }
+
+  public abstract class XPathFactory {
+    ctor protected XPathFactory();
+    method public abstract boolean getFeature(java.lang.String) throws javax.xml.xpath.XPathFactoryConfigurationException;
+    method public abstract boolean isObjectModelSupported(java.lang.String);
+    method public static final javax.xml.xpath.XPathFactory newInstance();
+    method public static final javax.xml.xpath.XPathFactory newInstance(java.lang.String) throws javax.xml.xpath.XPathFactoryConfigurationException;
+    method public static javax.xml.xpath.XPathFactory newInstance(java.lang.String, java.lang.String, java.lang.ClassLoader) throws javax.xml.xpath.XPathFactoryConfigurationException;
+    method public abstract javax.xml.xpath.XPath newXPath();
+    method public abstract void setFeature(java.lang.String, boolean) throws javax.xml.xpath.XPathFactoryConfigurationException;
+    method public abstract void setXPathFunctionResolver(javax.xml.xpath.XPathFunctionResolver);
+    method public abstract void setXPathVariableResolver(javax.xml.xpath.XPathVariableResolver);
+    field public static final java.lang.String DEFAULT_OBJECT_MODEL_URI = "http://java.sun.com/jaxp/xpath/dom";
+    field public static final java.lang.String DEFAULT_PROPERTY_NAME = "javax.xml.xpath.XPathFactory";
+  }
+
+  public class XPathFactoryConfigurationException extends javax.xml.xpath.XPathException {
+    ctor public XPathFactoryConfigurationException(java.lang.String);
+    ctor public XPathFactoryConfigurationException(java.lang.Throwable);
+  }
+
+  public abstract interface XPathFunction {
+    method public abstract java.lang.Object evaluate(java.util.List) throws javax.xml.xpath.XPathFunctionException;
+  }
+
+  public class XPathFunctionException extends javax.xml.xpath.XPathExpressionException {
+    ctor public XPathFunctionException(java.lang.String);
+    ctor public XPathFunctionException(java.lang.Throwable);
+  }
+
+  public abstract interface XPathFunctionResolver {
+    method public abstract javax.xml.xpath.XPathFunction resolveFunction(javax.xml.namespace.QName, int);
+  }
+
+  public abstract interface XPathVariableResolver {
+    method public abstract java.lang.Object resolveVariable(javax.xml.namespace.QName);
+  }
+
+}
+
+package junit.framework {
+
+  public class Assert {
+    ctor protected Assert();
+    method public static void assertEquals(java.lang.String, java.lang.Object, java.lang.Object);
+    method public static void assertEquals(java.lang.Object, java.lang.Object);
+    method public static void assertEquals(java.lang.String, java.lang.String, java.lang.String);
+    method public static void assertEquals(java.lang.String, java.lang.String);
+    method public static void assertEquals(java.lang.String, double, double, double);
+    method public static void assertEquals(double, double, double);
+    method public static void assertEquals(java.lang.String, float, float, float);
+    method public static void assertEquals(float, float, float);
+    method public static void assertEquals(java.lang.String, long, long);
+    method public static void assertEquals(long, long);
+    method public static void assertEquals(java.lang.String, boolean, boolean);
+    method public static void assertEquals(boolean, boolean);
+    method public static void assertEquals(java.lang.String, byte, byte);
+    method public static void assertEquals(byte, byte);
+    method public static void assertEquals(java.lang.String, char, char);
+    method public static void assertEquals(char, char);
+    method public static void assertEquals(java.lang.String, short, short);
+    method public static void assertEquals(short, short);
+    method public static void assertEquals(java.lang.String, int, int);
+    method public static void assertEquals(int, int);
+    method public static void assertFalse(java.lang.String, boolean);
+    method public static void assertFalse(boolean);
+    method public static void assertNotNull(java.lang.Object);
+    method public static void assertNotNull(java.lang.String, java.lang.Object);
+    method public static void assertNotSame(java.lang.String, java.lang.Object, java.lang.Object);
+    method public static void assertNotSame(java.lang.Object, java.lang.Object);
+    method public static void assertNull(java.lang.Object);
+    method public static void assertNull(java.lang.String, java.lang.Object);
+    method public static void assertSame(java.lang.String, java.lang.Object, java.lang.Object);
+    method public static void assertSame(java.lang.Object, java.lang.Object);
+    method public static void assertTrue(java.lang.String, boolean);
+    method public static void assertTrue(boolean);
+    method public static void fail(java.lang.String);
+    method public static void fail();
+    method public static void failNotEquals(java.lang.String, java.lang.Object, java.lang.Object);
+    method public static void failNotSame(java.lang.String, java.lang.Object, java.lang.Object);
+    method public static void failSame(java.lang.String);
+    method public static java.lang.String format(java.lang.String, java.lang.Object, java.lang.Object);
+  }
+
+  public class AssertionFailedError extends java.lang.AssertionError {
+    ctor public AssertionFailedError();
+    ctor public AssertionFailedError(java.lang.String);
+  }
+
+  public class ComparisonFailure extends junit.framework.AssertionFailedError {
+    ctor public ComparisonFailure(java.lang.String, java.lang.String, java.lang.String);
+    method public java.lang.String getActual();
+    method public java.lang.String getExpected();
+  }
+
+  public abstract interface Protectable {
+    method public abstract void protect() throws java.lang.Throwable;
+  }
+
+  public abstract interface Test {
+    method public abstract int countTestCases();
+    method public abstract void run(junit.framework.TestResult);
+  }
+
+  public abstract class TestCase extends junit.framework.Assert implements junit.framework.Test {
+    ctor public TestCase();
+    ctor public TestCase(java.lang.String);
+    method public int countTestCases();
+    method protected junit.framework.TestResult createResult();
+    method public java.lang.String getName();
+    method public junit.framework.TestResult run();
+    method public void run(junit.framework.TestResult);
+    method public void runBare() throws java.lang.Throwable;
+    method protected void runTest() throws java.lang.Throwable;
+    method public void setName(java.lang.String);
+    method protected void setUp() throws java.lang.Exception;
+    method protected void tearDown() throws java.lang.Exception;
+  }
+
+  public class TestFailure {
+    ctor public TestFailure(junit.framework.Test, java.lang.Throwable);
+    method public java.lang.String exceptionMessage();
+    method public junit.framework.Test failedTest();
+    method public boolean isFailure();
+    method public java.lang.Throwable thrownException();
+    method public java.lang.String trace();
+    field protected junit.framework.Test fFailedTest;
+    field protected java.lang.Throwable fThrownException;
+  }
+
+  public abstract interface TestListener {
+    method public abstract void addError(junit.framework.Test, java.lang.Throwable);
+    method public abstract void addFailure(junit.framework.Test, junit.framework.AssertionFailedError);
+    method public abstract void endTest(junit.framework.Test);
+    method public abstract void startTest(junit.framework.Test);
+  }
+
+  public class TestResult {
+    ctor public TestResult();
+    method public synchronized void addError(junit.framework.Test, java.lang.Throwable);
+    method public synchronized void addFailure(junit.framework.Test, junit.framework.AssertionFailedError);
+    method public synchronized void addListener(junit.framework.TestListener);
+    method public void endTest(junit.framework.Test);
+    method public synchronized int errorCount();
+    method public synchronized java.util.Enumeration<junit.framework.TestFailure> errors();
+    method public synchronized int failureCount();
+    method public synchronized java.util.Enumeration<junit.framework.TestFailure> failures();
+    method public synchronized void removeListener(junit.framework.TestListener);
+    method protected void run(junit.framework.TestCase);
+    method public synchronized int runCount();
+    method public void runProtected(junit.framework.Test, junit.framework.Protectable);
+    method public synchronized boolean shouldStop();
+    method public void startTest(junit.framework.Test);
+    method public synchronized void stop();
+    method public synchronized boolean wasSuccessful();
+    field protected java.util.Vector fErrors;
+    field protected java.util.Vector fFailures;
+    field protected java.util.Vector fListeners;
+    field protected int fRunTests;
+  }
+
+  public class TestSuite implements junit.framework.Test {
+    ctor public TestSuite();
+    ctor public TestSuite(java.lang.Class<?>);
+    ctor public TestSuite(java.lang.Class<? extends junit.framework.TestCase>, java.lang.String);
+    ctor public TestSuite(java.lang.String);
+    ctor public TestSuite(java.lang.Class<?>...);
+    ctor public TestSuite(java.lang.Class<? extends junit.framework.TestCase>[], java.lang.String);
+    method public void addTest(junit.framework.Test);
+    method public void addTestSuite(java.lang.Class<? extends junit.framework.TestCase>);
+    method public int countTestCases();
+    method public static junit.framework.Test createTest(java.lang.Class<?>, java.lang.String);
+    method public java.lang.String getName();
+    method public static java.lang.reflect.Constructor<?> getTestConstructor(java.lang.Class<?>) throws java.lang.NoSuchMethodException;
+    method public void run(junit.framework.TestResult);
+    method public void runTest(junit.framework.Test, junit.framework.TestResult);
+    method public void setName(java.lang.String);
+    method public junit.framework.Test testAt(int);
+    method public int testCount();
+    method public java.util.Enumeration<junit.framework.Test> tests();
+    method public static junit.framework.Test warning(java.lang.String);
+  }
+
+}
+
+package junit.runner {
+
+  public abstract class BaseTestRunner implements junit.framework.TestListener {
+    ctor public BaseTestRunner();
+    method public synchronized void addError(junit.framework.Test, java.lang.Throwable);
+    method public synchronized void addFailure(junit.framework.Test, junit.framework.AssertionFailedError);
+    method protected void clearStatus();
+    method public java.lang.String elapsedTimeAsString(long);
+    method public synchronized void endTest(junit.framework.Test);
+    method public java.lang.String extractClassName(java.lang.String);
+    method public static java.lang.String getFilteredTrace(java.lang.Throwable);
+    method public static java.lang.String getFilteredTrace(java.lang.String);
+    method public deprecated junit.runner.TestSuiteLoader getLoader();
+    method public static java.lang.String getPreference(java.lang.String);
+    method public static int getPreference(java.lang.String, int);
+    method protected static java.util.Properties getPreferences();
+    method public junit.framework.Test getTest(java.lang.String);
+    method public static deprecated boolean inVAJava();
+    method protected java.lang.Class<?> loadSuiteClass(java.lang.String) throws java.lang.ClassNotFoundException;
+    method protected java.lang.String processArguments(java.lang.String[]);
+    method protected abstract void runFailed(java.lang.String);
+    method public static void savePreferences() throws java.io.IOException;
+    method public void setLoading(boolean);
+    method public void setPreference(java.lang.String, java.lang.String);
+    method protected static void setPreferences(java.util.Properties);
+    method protected static boolean showStackRaw();
+    method public synchronized void startTest(junit.framework.Test);
+    method public abstract void testEnded(java.lang.String);
+    method public abstract void testFailed(int, junit.framework.Test, java.lang.Throwable);
+    method public abstract void testStarted(java.lang.String);
+    method public static java.lang.String truncate(java.lang.String);
+    method protected boolean useReloadingTestSuiteLoader();
+    field public static final java.lang.String SUITE_METHODNAME = "suite";
+  }
+
+  public abstract interface TestSuiteLoader {
+    method public abstract java.lang.Class load(java.lang.String) throws java.lang.ClassNotFoundException;
+    method public abstract java.lang.Class reload(java.lang.Class) throws java.lang.ClassNotFoundException;
+  }
+
+  public class Version {
+    method public static java.lang.String id();
+  }
+
+}
+
+package org.apache.commons.logging {
+
+  public abstract interface Log {
+    method public abstract void debug(java.lang.Object);
+    method public abstract void debug(java.lang.Object, java.lang.Throwable);
+    method public abstract void error(java.lang.Object);
+    method public abstract void error(java.lang.Object, java.lang.Throwable);
+    method public abstract void fatal(java.lang.Object);
+    method public abstract void fatal(java.lang.Object, java.lang.Throwable);
+    method public abstract void info(java.lang.Object);
+    method public abstract void info(java.lang.Object, java.lang.Throwable);
+    method public abstract boolean isDebugEnabled();
+    method public abstract boolean isErrorEnabled();
+    method public abstract boolean isFatalEnabled();
+    method public abstract boolean isInfoEnabled();
+    method public abstract boolean isTraceEnabled();
+    method public abstract boolean isWarnEnabled();
+    method public abstract void trace(java.lang.Object);
+    method public abstract void trace(java.lang.Object, java.lang.Throwable);
+    method public abstract void warn(java.lang.Object);
+    method public abstract void warn(java.lang.Object, java.lang.Throwable);
+  }
+
+}
+
+package org.apache.http {
+
+  public class ConnectionClosedException extends java.io.IOException {
+    ctor public ConnectionClosedException(java.lang.String);
+  }
+
+  public abstract interface ConnectionReuseStrategy {
+    method public abstract boolean keepAlive(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
+  }
+
+  public abstract interface FormattedHeader implements org.apache.http.Header {
+    method public abstract org.apache.http.util.CharArrayBuffer getBuffer();
+    method public abstract int getValuePos();
+  }
+
+  public abstract interface Header {
+    method public abstract org.apache.http.HeaderElement[] getElements() throws org.apache.http.ParseException;
+    method public abstract java.lang.String getName();
+    method public abstract java.lang.String getValue();
+  }
+
+  public abstract interface HeaderElement {
+    method public abstract java.lang.String getName();
+    method public abstract org.apache.http.NameValuePair getParameter(int);
+    method public abstract org.apache.http.NameValuePair getParameterByName(java.lang.String);
+    method public abstract int getParameterCount();
+    method public abstract org.apache.http.NameValuePair[] getParameters();
+    method public abstract java.lang.String getValue();
+  }
+
+  public abstract interface HeaderElementIterator implements java.util.Iterator {
+    method public abstract boolean hasNext();
+    method public abstract org.apache.http.HeaderElement nextElement();
+  }
+
+  public abstract interface HeaderIterator implements java.util.Iterator {
+    method public abstract boolean hasNext();
+    method public abstract org.apache.http.Header nextHeader();
+  }
+
+  public abstract interface HttpClientConnection implements org.apache.http.HttpConnection {
+    method public abstract void flush() throws java.io.IOException;
+    method public abstract boolean isResponseAvailable(int) throws java.io.IOException;
+    method public abstract void receiveResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
+    method public abstract org.apache.http.HttpResponse receiveResponseHeader() throws org.apache.http.HttpException, java.io.IOException;
+    method public abstract void sendRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException;
+    method public abstract void sendRequestHeader(org.apache.http.HttpRequest) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public abstract interface HttpConnection {
+    method public abstract void close() throws java.io.IOException;
+    method public abstract org.apache.http.HttpConnectionMetrics getMetrics();
+    method public abstract int getSocketTimeout();
+    method public abstract boolean isOpen();
+    method public abstract boolean isStale();
+    method public abstract void setSocketTimeout(int);
+    method public abstract void shutdown() throws java.io.IOException;
+  }
+
+  public abstract interface HttpConnectionMetrics {
+    method public abstract java.lang.Object getMetric(java.lang.String);
+    method public abstract long getReceivedBytesCount();
+    method public abstract long getRequestCount();
+    method public abstract long getResponseCount();
+    method public abstract long getSentBytesCount();
+    method public abstract void reset();
+  }
+
+  public abstract interface HttpEntity {
+    method public abstract void consumeContent() throws java.io.IOException;
+    method public abstract java.io.InputStream getContent() throws java.io.IOException, java.lang.IllegalStateException;
+    method public abstract org.apache.http.Header getContentEncoding();
+    method public abstract long getContentLength();
+    method public abstract org.apache.http.Header getContentType();
+    method public abstract boolean isChunked();
+    method public abstract boolean isRepeatable();
+    method public abstract boolean isStreaming();
+    method public abstract void writeTo(java.io.OutputStream) throws java.io.IOException;
+  }
+
+  public abstract interface HttpEntityEnclosingRequest implements org.apache.http.HttpRequest {
+    method public abstract boolean expectContinue();
+    method public abstract org.apache.http.HttpEntity getEntity();
+    method public abstract void setEntity(org.apache.http.HttpEntity);
+  }
+
+  public class HttpException extends java.lang.Exception {
+    ctor public HttpException();
+    ctor public HttpException(java.lang.String);
+    ctor public HttpException(java.lang.String, java.lang.Throwable);
+  }
+
+  public final class HttpHost implements java.lang.Cloneable {
+    ctor public HttpHost(java.lang.String, int, java.lang.String);
+    ctor public HttpHost(java.lang.String, int);
+    ctor public HttpHost(java.lang.String);
+    ctor public HttpHost(org.apache.http.HttpHost);
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public java.lang.String getHostName();
+    method public int getPort();
+    method public java.lang.String getSchemeName();
+    method public java.lang.String toHostString();
+    method public java.lang.String toURI();
+    field public static final java.lang.String DEFAULT_SCHEME_NAME = "http";
+    field protected final java.lang.String hostname;
+    field protected final java.lang.String lcHostname;
+    field protected final int port;
+    field protected final java.lang.String schemeName;
+  }
+
+  public abstract interface HttpInetConnection implements org.apache.http.HttpConnection {
+    method public abstract java.net.InetAddress getLocalAddress();
+    method public abstract int getLocalPort();
+    method public abstract java.net.InetAddress getRemoteAddress();
+    method public abstract int getRemotePort();
+  }
+
+  public abstract interface HttpMessage {
+    method public abstract void addHeader(org.apache.http.Header);
+    method public abstract void addHeader(java.lang.String, java.lang.String);
+    method public abstract boolean containsHeader(java.lang.String);
+    method public abstract org.apache.http.Header[] getAllHeaders();
+    method public abstract org.apache.http.Header getFirstHeader(java.lang.String);
+    method public abstract org.apache.http.Header[] getHeaders(java.lang.String);
+    method public abstract org.apache.http.Header getLastHeader(java.lang.String);
+    method public abstract org.apache.http.params.HttpParams getParams();
+    method public abstract org.apache.http.ProtocolVersion getProtocolVersion();
+    method public abstract org.apache.http.HeaderIterator headerIterator();
+    method public abstract org.apache.http.HeaderIterator headerIterator(java.lang.String);
+    method public abstract void removeHeader(org.apache.http.Header);
+    method public abstract void removeHeaders(java.lang.String);
+    method public abstract void setHeader(org.apache.http.Header);
+    method public abstract void setHeader(java.lang.String, java.lang.String);
+    method public abstract void setHeaders(org.apache.http.Header[]);
+    method public abstract void setParams(org.apache.http.params.HttpParams);
+  }
+
+  public abstract interface HttpRequest implements org.apache.http.HttpMessage {
+    method public abstract org.apache.http.RequestLine getRequestLine();
+  }
+
+  public abstract interface HttpRequestFactory {
+    method public abstract org.apache.http.HttpRequest newHttpRequest(org.apache.http.RequestLine) throws org.apache.http.MethodNotSupportedException;
+    method public abstract org.apache.http.HttpRequest newHttpRequest(java.lang.String, java.lang.String) throws org.apache.http.MethodNotSupportedException;
+  }
+
+  public abstract interface HttpRequestInterceptor {
+    method public abstract void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public abstract interface HttpResponse implements org.apache.http.HttpMessage {
+    method public abstract org.apache.http.HttpEntity getEntity();
+    method public abstract java.util.Locale getLocale();
+    method public abstract org.apache.http.StatusLine getStatusLine();
+    method public abstract void setEntity(org.apache.http.HttpEntity);
+    method public abstract void setLocale(java.util.Locale);
+    method public abstract void setReasonPhrase(java.lang.String) throws java.lang.IllegalStateException;
+    method public abstract void setStatusCode(int) throws java.lang.IllegalStateException;
+    method public abstract void setStatusLine(org.apache.http.StatusLine);
+    method public abstract void setStatusLine(org.apache.http.ProtocolVersion, int);
+    method public abstract void setStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String);
+  }
+
+  public abstract interface HttpResponseFactory {
+    method public abstract org.apache.http.HttpResponse newHttpResponse(org.apache.http.ProtocolVersion, int, org.apache.http.protocol.HttpContext);
+    method public abstract org.apache.http.HttpResponse newHttpResponse(org.apache.http.StatusLine, org.apache.http.protocol.HttpContext);
+  }
+
+  public abstract interface HttpResponseInterceptor {
+    method public abstract void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public abstract interface HttpServerConnection implements org.apache.http.HttpConnection {
+    method public abstract void flush() throws java.io.IOException;
+    method public abstract void receiveRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException;
+    method public abstract org.apache.http.HttpRequest receiveRequestHeader() throws org.apache.http.HttpException, java.io.IOException;
+    method public abstract void sendResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
+    method public abstract void sendResponseHeader(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public abstract interface HttpStatus {
+    field public static final int SC_ACCEPTED = 202; // 0xca
+    field public static final int SC_BAD_GATEWAY = 502; // 0x1f6
+    field public static final int SC_BAD_REQUEST = 400; // 0x190
+    field public static final int SC_CONFLICT = 409; // 0x199
+    field public static final int SC_CONTINUE = 100; // 0x64
+    field public static final int SC_CREATED = 201; // 0xc9
+    field public static final int SC_EXPECTATION_FAILED = 417; // 0x1a1
+    field public static final int SC_FAILED_DEPENDENCY = 424; // 0x1a8
+    field public static final int SC_FORBIDDEN = 403; // 0x193
+    field public static final int SC_GATEWAY_TIMEOUT = 504; // 0x1f8
+    field public static final int SC_GONE = 410; // 0x19a
+    field public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505; // 0x1f9
+    field public static final int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 419; // 0x1a3
+    field public static final int SC_INSUFFICIENT_STORAGE = 507; // 0x1fb
+    field public static final int SC_INTERNAL_SERVER_ERROR = 500; // 0x1f4
+    field public static final int SC_LENGTH_REQUIRED = 411; // 0x19b
+    field public static final int SC_LOCKED = 423; // 0x1a7
+    field public static final int SC_METHOD_FAILURE = 420; // 0x1a4
+    field public static final int SC_METHOD_NOT_ALLOWED = 405; // 0x195
+    field public static final int SC_MOVED_PERMANENTLY = 301; // 0x12d
+    field public static final int SC_MOVED_TEMPORARILY = 302; // 0x12e
+    field public static final int SC_MULTIPLE_CHOICES = 300; // 0x12c
+    field public static final int SC_MULTI_STATUS = 207; // 0xcf
+    field public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203; // 0xcb
+    field public static final int SC_NOT_ACCEPTABLE = 406; // 0x196
+    field public static final int SC_NOT_FOUND = 404; // 0x194
+    field public static final int SC_NOT_IMPLEMENTED = 501; // 0x1f5
+    field public static final int SC_NOT_MODIFIED = 304; // 0x130
+    field public static final int SC_NO_CONTENT = 204; // 0xcc
+    field public static final int SC_OK = 200; // 0xc8
+    field public static final int SC_PARTIAL_CONTENT = 206; // 0xce
+    field public static final int SC_PAYMENT_REQUIRED = 402; // 0x192
+    field public static final int SC_PRECONDITION_FAILED = 412; // 0x19c
+    field public static final int SC_PROCESSING = 102; // 0x66
+    field public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407; // 0x197
+    field public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416; // 0x1a0
+    field public static final int SC_REQUEST_TIMEOUT = 408; // 0x198
+    field public static final int SC_REQUEST_TOO_LONG = 413; // 0x19d
+    field public static final int SC_REQUEST_URI_TOO_LONG = 414; // 0x19e
+    field public static final int SC_RESET_CONTENT = 205; // 0xcd
+    field public static final int SC_SEE_OTHER = 303; // 0x12f
+    field public static final int SC_SERVICE_UNAVAILABLE = 503; // 0x1f7
+    field public static final int SC_SWITCHING_PROTOCOLS = 101; // 0x65
+    field public static final int SC_TEMPORARY_REDIRECT = 307; // 0x133
+    field public static final int SC_UNAUTHORIZED = 401; // 0x191
+    field public static final int SC_UNPROCESSABLE_ENTITY = 422; // 0x1a6
+    field public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415; // 0x19f
+    field public static final int SC_USE_PROXY = 305; // 0x131
+  }
+
+  public final class HttpVersion extends org.apache.http.ProtocolVersion implements java.io.Serializable {
+    ctor public HttpVersion(int, int);
+    field public static final java.lang.String HTTP = "HTTP";
+    field public static final org.apache.http.HttpVersion HTTP_0_9;
+    field public static final org.apache.http.HttpVersion HTTP_1_0;
+    field public static final org.apache.http.HttpVersion HTTP_1_1;
+  }
+
+  public class MalformedChunkCodingException extends java.io.IOException {
+    ctor public MalformedChunkCodingException();
+    ctor public MalformedChunkCodingException(java.lang.String);
+  }
+
+  public class MethodNotSupportedException extends org.apache.http.HttpException {
+    ctor public MethodNotSupportedException(java.lang.String);
+    ctor public MethodNotSupportedException(java.lang.String, java.lang.Throwable);
+  }
+
+  public abstract interface NameValuePair {
+    method public abstract java.lang.String getName();
+    method public abstract java.lang.String getValue();
+  }
+
+  public class NoHttpResponseException extends java.io.IOException {
+    ctor public NoHttpResponseException(java.lang.String);
+  }
+
+  public class ParseException extends java.lang.RuntimeException {
+    ctor public ParseException();
+    ctor public ParseException(java.lang.String);
+  }
+
+  public class ProtocolException extends org.apache.http.HttpException {
+    ctor public ProtocolException();
+    ctor public ProtocolException(java.lang.String);
+    ctor public ProtocolException(java.lang.String, java.lang.Throwable);
+  }
+
+  public class ProtocolVersion implements java.lang.Cloneable java.io.Serializable {
+    ctor public ProtocolVersion(java.lang.String, int, int);
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public int compareToVersion(org.apache.http.ProtocolVersion);
+    method public final boolean equals(java.lang.Object);
+    method public org.apache.http.ProtocolVersion forVersion(int, int);
+    method public final int getMajor();
+    method public final int getMinor();
+    method public final java.lang.String getProtocol();
+    method public final boolean greaterEquals(org.apache.http.ProtocolVersion);
+    method public final int hashCode();
+    method public boolean isComparable(org.apache.http.ProtocolVersion);
+    method public final boolean lessEquals(org.apache.http.ProtocolVersion);
+    field protected final int major;
+    field protected final int minor;
+    field protected final java.lang.String protocol;
+  }
+
+  public abstract interface ReasonPhraseCatalog {
+    method public abstract java.lang.String getReason(int, java.util.Locale);
+  }
+
+  public abstract interface RequestLine {
+    method public abstract java.lang.String getMethod();
+    method public abstract org.apache.http.ProtocolVersion getProtocolVersion();
+    method public abstract java.lang.String getUri();
+  }
+
+  public abstract interface StatusLine {
+    method public abstract org.apache.http.ProtocolVersion getProtocolVersion();
+    method public abstract java.lang.String getReasonPhrase();
+    method public abstract int getStatusCode();
+  }
+
+  public abstract interface TokenIterator implements java.util.Iterator {
+    method public abstract boolean hasNext();
+    method public abstract java.lang.String nextToken();
+  }
+
+  public class UnsupportedHttpVersionException extends org.apache.http.ProtocolException {
+    ctor public UnsupportedHttpVersionException();
+    ctor public UnsupportedHttpVersionException(java.lang.String);
+  }
+
+}
+
+package org.apache.http.auth {
+
+  public final class AUTH {
+    field public static final java.lang.String PROXY_AUTH = "Proxy-Authenticate";
+    field public static final java.lang.String PROXY_AUTH_RESP = "Proxy-Authorization";
+    field public static final java.lang.String WWW_AUTH = "WWW-Authenticate";
+    field public static final java.lang.String WWW_AUTH_RESP = "Authorization";
+  }
+
+  public abstract interface AuthScheme {
+    method public abstract org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException;
+    method public abstract java.lang.String getParameter(java.lang.String);
+    method public abstract java.lang.String getRealm();
+    method public abstract java.lang.String getSchemeName();
+    method public abstract boolean isComplete();
+    method public abstract boolean isConnectionBased();
+    method public abstract void processChallenge(org.apache.http.Header) throws org.apache.http.auth.MalformedChallengeException;
+  }
+
+  public abstract interface AuthSchemeFactory {
+    method public abstract org.apache.http.auth.AuthScheme newInstance(org.apache.http.params.HttpParams);
+  }
+
+  public final class AuthSchemeRegistry {
+    ctor public AuthSchemeRegistry();
+    method public synchronized org.apache.http.auth.AuthScheme getAuthScheme(java.lang.String, org.apache.http.params.HttpParams) throws java.lang.IllegalStateException;
+    method public synchronized java.util.List<java.lang.String> getSchemeNames();
+    method public synchronized void register(java.lang.String, org.apache.http.auth.AuthSchemeFactory);
+    method public synchronized void setItems(java.util.Map<java.lang.String, org.apache.http.auth.AuthSchemeFactory>);
+    method public synchronized void unregister(java.lang.String);
+  }
+
+  public class AuthScope {
+    ctor public AuthScope(java.lang.String, int, java.lang.String, java.lang.String);
+    ctor public AuthScope(java.lang.String, int, java.lang.String);
+    ctor public AuthScope(java.lang.String, int);
+    ctor public AuthScope(org.apache.http.auth.AuthScope);
+    method public java.lang.String getHost();
+    method public int getPort();
+    method public java.lang.String getRealm();
+    method public java.lang.String getScheme();
+    method public int match(org.apache.http.auth.AuthScope);
+    field public static final org.apache.http.auth.AuthScope ANY;
+    field public static final java.lang.String ANY_HOST;
+    field public static final int ANY_PORT = -1; // 0xffffffff
+    field public static final java.lang.String ANY_REALM;
+    field public static final java.lang.String ANY_SCHEME;
+  }
+
+  public class AuthState {
+    ctor public AuthState();
+    method public org.apache.http.auth.AuthScheme getAuthScheme();
+    method public org.apache.http.auth.AuthScope getAuthScope();
+    method public org.apache.http.auth.Credentials getCredentials();
+    method public void invalidate();
+    method public boolean isValid();
+    method public void setAuthScheme(org.apache.http.auth.AuthScheme);
+    method public void setAuthScope(org.apache.http.auth.AuthScope);
+    method public void setCredentials(org.apache.http.auth.Credentials);
+  }
+
+  public class AuthenticationException extends org.apache.http.ProtocolException {
+    ctor public AuthenticationException();
+    ctor public AuthenticationException(java.lang.String);
+    ctor public AuthenticationException(java.lang.String, java.lang.Throwable);
+  }
+
+  public final class BasicUserPrincipal implements java.security.Principal {
+    ctor public BasicUserPrincipal(java.lang.String);
+    method public java.lang.String getName();
+  }
+
+  public abstract interface Credentials {
+    method public abstract java.lang.String getPassword();
+    method public abstract java.security.Principal getUserPrincipal();
+  }
+
+  public class InvalidCredentialsException extends org.apache.http.auth.AuthenticationException {
+    ctor public InvalidCredentialsException();
+    ctor public InvalidCredentialsException(java.lang.String);
+    ctor public InvalidCredentialsException(java.lang.String, java.lang.Throwable);
+  }
+
+  public class MalformedChallengeException extends org.apache.http.ProtocolException {
+    ctor public MalformedChallengeException();
+    ctor public MalformedChallengeException(java.lang.String);
+    ctor public MalformedChallengeException(java.lang.String, java.lang.Throwable);
+  }
+
+  public class NTCredentials implements org.apache.http.auth.Credentials {
+    ctor public NTCredentials(java.lang.String);
+    ctor public NTCredentials(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public java.lang.String getDomain();
+    method public java.lang.String getPassword();
+    method public java.lang.String getUserName();
+    method public java.security.Principal getUserPrincipal();
+    method public java.lang.String getWorkstation();
+  }
+
+  public class NTUserPrincipal implements java.security.Principal {
+    ctor public NTUserPrincipal(java.lang.String, java.lang.String);
+    method public java.lang.String getDomain();
+    method public java.lang.String getName();
+    method public java.lang.String getUsername();
+  }
+
+  public class UsernamePasswordCredentials implements org.apache.http.auth.Credentials {
+    ctor public UsernamePasswordCredentials(java.lang.String);
+    ctor public UsernamePasswordCredentials(java.lang.String, java.lang.String);
+    method public java.lang.String getPassword();
+    method public java.lang.String getUserName();
+    method public java.security.Principal getUserPrincipal();
+  }
+
+}
+
+package org.apache.http.auth.params {
+
+  public abstract interface AuthPNames {
+    field public static final java.lang.String CREDENTIAL_CHARSET = "http.auth.credential-charset";
+  }
+
+  public class AuthParamBean extends org.apache.http.params.HttpAbstractParamBean {
+    ctor public AuthParamBean(org.apache.http.params.HttpParams);
+    method public void setCredentialCharset(java.lang.String);
+  }
+
+  public final class AuthParams {
+    method public static java.lang.String getCredentialCharset(org.apache.http.params.HttpParams);
+    method public static void setCredentialCharset(org.apache.http.params.HttpParams, java.lang.String);
+  }
+
+}
+
+package org.apache.http.client {
+
+  public abstract interface AuthenticationHandler {
+    method public abstract java.util.Map<java.lang.String, org.apache.http.Header> getChallenges(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.MalformedChallengeException;
+    method public abstract boolean isAuthenticationRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
+    method public abstract org.apache.http.auth.AuthScheme selectScheme(java.util.Map<java.lang.String, org.apache.http.Header>, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.AuthenticationException;
+  }
+
+  public class CircularRedirectException extends org.apache.http.client.RedirectException {
+    ctor public CircularRedirectException();
+    ctor public CircularRedirectException(java.lang.String);
+    ctor public CircularRedirectException(java.lang.String, java.lang.Throwable);
+  }
+
+  public class ClientProtocolException extends java.io.IOException {
+    ctor public ClientProtocolException();
+    ctor public ClientProtocolException(java.lang.String);
+    ctor public ClientProtocolException(java.lang.Throwable);
+    ctor public ClientProtocolException(java.lang.String, java.lang.Throwable);
+  }
+
+  public abstract interface CookieStore {
+    method public abstract void addCookie(org.apache.http.cookie.Cookie);
+    method public abstract void clear();
+    method public abstract boolean clearExpired(java.util.Date);
+    method public abstract java.util.List<org.apache.http.cookie.Cookie> getCookies();
+  }
+
+  public abstract interface CredentialsProvider {
+    method public abstract void clear();
+    method public abstract org.apache.http.auth.Credentials getCredentials(org.apache.http.auth.AuthScope);
+    method public abstract void setCredentials(org.apache.http.auth.AuthScope, org.apache.http.auth.Credentials);
+  }
+
+  public abstract interface HttpClient {
+    method public abstract org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public abstract org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public abstract org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public abstract org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public abstract T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public abstract T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public abstract T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public abstract T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public abstract org.apache.http.conn.ClientConnectionManager getConnectionManager();
+    method public abstract org.apache.http.params.HttpParams getParams();
+  }
+
+  public abstract interface HttpRequestRetryHandler {
+    method public abstract boolean retryRequest(java.io.IOException, int, org.apache.http.protocol.HttpContext);
+  }
+
+  public class HttpResponseException extends org.apache.http.client.ClientProtocolException {
+    ctor public HttpResponseException(int, java.lang.String);
+    method public int getStatusCode();
+  }
+
+  public class NonRepeatableRequestException extends org.apache.http.ProtocolException {
+    ctor public NonRepeatableRequestException();
+    ctor public NonRepeatableRequestException(java.lang.String);
+  }
+
+  public class RedirectException extends org.apache.http.ProtocolException {
+    ctor public RedirectException();
+    ctor public RedirectException(java.lang.String);
+    ctor public RedirectException(java.lang.String, java.lang.Throwable);
+  }
+
+  public abstract interface RedirectHandler {
+    method public abstract java.net.URI getLocationURI(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.ProtocolException;
+    method public abstract boolean isRedirectRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
+  }
+
+  public abstract interface RequestDirector {
+    method public abstract org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public abstract interface ResponseHandler {
+    method public abstract T handleResponse(org.apache.http.HttpResponse) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+  }
+
+  public abstract interface UserTokenHandler {
+    method public abstract java.lang.Object getUserToken(org.apache.http.protocol.HttpContext);
+  }
+
+}
+
+package org.apache.http.client.entity {
+
+  public class UrlEncodedFormEntity extends org.apache.http.entity.StringEntity {
+    ctor public UrlEncodedFormEntity(java.util.List<? extends org.apache.http.NameValuePair>, java.lang.String) throws java.io.UnsupportedEncodingException;
+    ctor public UrlEncodedFormEntity(java.util.List<? extends org.apache.http.NameValuePair>) throws java.io.UnsupportedEncodingException;
+  }
+
+}
+
+package org.apache.http.client.methods {
+
+  public abstract interface AbortableHttpRequest {
+    method public abstract void abort();
+    method public abstract void setConnectionRequest(org.apache.http.conn.ClientConnectionRequest) throws java.io.IOException;
+    method public abstract void setReleaseTrigger(org.apache.http.conn.ConnectionReleaseTrigger) throws java.io.IOException;
+  }
+
+  public class HttpDelete extends org.apache.http.client.methods.HttpRequestBase {
+    ctor public HttpDelete();
+    ctor public HttpDelete(java.net.URI);
+    ctor public HttpDelete(java.lang.String);
+    method public java.lang.String getMethod();
+    field public static final java.lang.String METHOD_NAME = "DELETE";
+  }
+
+  public abstract class HttpEntityEnclosingRequestBase extends org.apache.http.client.methods.HttpRequestBase implements org.apache.http.HttpEntityEnclosingRequest {
+    ctor public HttpEntityEnclosingRequestBase();
+    method public boolean expectContinue();
+    method public org.apache.http.HttpEntity getEntity();
+    method public void setEntity(org.apache.http.HttpEntity);
+  }
+
+  public class HttpGet extends org.apache.http.client.methods.HttpRequestBase {
+    ctor public HttpGet();
+    ctor public HttpGet(java.net.URI);
+    ctor public HttpGet(java.lang.String);
+    method public java.lang.String getMethod();
+    field public static final java.lang.String METHOD_NAME = "GET";
+  }
+
+  public class HttpHead extends org.apache.http.client.methods.HttpRequestBase {
+    ctor public HttpHead();
+    ctor public HttpHead(java.net.URI);
+    ctor public HttpHead(java.lang.String);
+    method public java.lang.String getMethod();
+    field public static final java.lang.String METHOD_NAME = "HEAD";
+  }
+
+  public class HttpOptions extends org.apache.http.client.methods.HttpRequestBase {
+    ctor public HttpOptions();
+    ctor public HttpOptions(java.net.URI);
+    ctor public HttpOptions(java.lang.String);
+    method public java.util.Set<java.lang.String> getAllowedMethods(org.apache.http.HttpResponse);
+    method public java.lang.String getMethod();
+    field public static final java.lang.String METHOD_NAME = "OPTIONS";
+  }
+
+  public class HttpPost extends org.apache.http.client.methods.HttpEntityEnclosingRequestBase {
+    ctor public HttpPost();
+    ctor public HttpPost(java.net.URI);
+    ctor public HttpPost(java.lang.String);
+    method public java.lang.String getMethod();
+    field public static final java.lang.String METHOD_NAME = "POST";
+  }
+
+  public class HttpPut extends org.apache.http.client.methods.HttpEntityEnclosingRequestBase {
+    ctor public HttpPut();
+    ctor public HttpPut(java.net.URI);
+    ctor public HttpPut(java.lang.String);
+    method public java.lang.String getMethod();
+    field public static final java.lang.String METHOD_NAME = "PUT";
+  }
+
+  public abstract class HttpRequestBase extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.client.methods.AbortableHttpRequest java.lang.Cloneable org.apache.http.client.methods.HttpUriRequest {
+    ctor public HttpRequestBase();
+    method public void abort();
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public abstract java.lang.String getMethod();
+    method public org.apache.http.ProtocolVersion getProtocolVersion();
+    method public org.apache.http.RequestLine getRequestLine();
+    method public java.net.URI getURI();
+    method public boolean isAborted();
+    method public void setConnectionRequest(org.apache.http.conn.ClientConnectionRequest) throws java.io.IOException;
+    method public void setReleaseTrigger(org.apache.http.conn.ConnectionReleaseTrigger) throws java.io.IOException;
+    method public void setURI(java.net.URI);
+  }
+
+  public class HttpTrace extends org.apache.http.client.methods.HttpRequestBase {
+    ctor public HttpTrace();
+    ctor public HttpTrace(java.net.URI);
+    ctor public HttpTrace(java.lang.String);
+    method public java.lang.String getMethod();
+    field public static final java.lang.String METHOD_NAME = "TRACE";
+  }
+
+  public abstract interface HttpUriRequest implements org.apache.http.HttpRequest {
+    method public abstract void abort() throws java.lang.UnsupportedOperationException;
+    method public abstract java.lang.String getMethod();
+    method public abstract java.net.URI getURI();
+    method public abstract boolean isAborted();
+  }
+
+}
+
+package org.apache.http.client.params {
+
+  public abstract interface AllClientPNames implements org.apache.http.auth.params.AuthPNames org.apache.http.client.params.ClientPNames org.apache.http.conn.params.ConnConnectionPNames org.apache.http.conn.params.ConnManagerPNames org.apache.http.conn.params.ConnRoutePNames org.apache.http.cookie.params.CookieSpecPNames org.apache.http.params.CoreConnectionPNames org.apache.http.params.CoreProtocolPNames {
+  }
+
+  public final class AuthPolicy {
+    field public static final java.lang.String BASIC = "Basic";
+    field public static final java.lang.String DIGEST = "Digest";
+    field public static final java.lang.String NTLM = "NTLM";
+  }
+
+  public abstract interface ClientPNames {
+    field public static final java.lang.String ALLOW_CIRCULAR_REDIRECTS = "http.protocol.allow-circular-redirects";
+    field public static final java.lang.String CONNECTION_MANAGER_FACTORY = "http.connection-manager.factory-object";
+    field public static final java.lang.String CONNECTION_MANAGER_FACTORY_CLASS_NAME = "http.connection-manager.factory-class-name";
+    field public static final java.lang.String COOKIE_POLICY = "http.protocol.cookie-policy";
+    field public static final java.lang.String DEFAULT_HEADERS = "http.default-headers";
+    field public static final java.lang.String DEFAULT_HOST = "http.default-host";
+    field public static final java.lang.String HANDLE_AUTHENTICATION = "http.protocol.handle-authentication";
+    field public static final java.lang.String HANDLE_REDIRECTS = "http.protocol.handle-redirects";
+    field public static final java.lang.String MAX_REDIRECTS = "http.protocol.max-redirects";
+    field public static final java.lang.String REJECT_RELATIVE_REDIRECT = "http.protocol.reject-relative-redirect";
+    field public static final java.lang.String VIRTUAL_HOST = "http.virtual-host";
+  }
+
+  public class ClientParamBean extends org.apache.http.params.HttpAbstractParamBean {
+    ctor public ClientParamBean(org.apache.http.params.HttpParams);
+    method public void setAllowCircularRedirects(boolean);
+    method public void setConnectionManagerFactory(org.apache.http.conn.ClientConnectionManagerFactory);
+    method public void setConnectionManagerFactoryClassName(java.lang.String);
+    method public void setCookiePolicy(java.lang.String);
+    method public void setDefaultHeaders(java.util.Collection<org.apache.http.Header>);
+    method public void setDefaultHost(org.apache.http.HttpHost);
+    method public void setHandleAuthentication(boolean);
+    method public void setHandleRedirects(boolean);
+    method public void setMaxRedirects(int);
+    method public void setRejectRelativeRedirect(boolean);
+    method public void setVirtualHost(org.apache.http.HttpHost);
+  }
+
+  public final class CookiePolicy {
+    field public static final java.lang.String BEST_MATCH = "best-match";
+    field public static final java.lang.String BROWSER_COMPATIBILITY = "compatibility";
+    field public static final java.lang.String NETSCAPE = "netscape";
+    field public static final java.lang.String RFC_2109 = "rfc2109";
+    field public static final java.lang.String RFC_2965 = "rfc2965";
+  }
+
+  public class HttpClientParams {
+    method public static java.lang.String getCookiePolicy(org.apache.http.params.HttpParams);
+    method public static boolean isAuthenticating(org.apache.http.params.HttpParams);
+    method public static boolean isRedirecting(org.apache.http.params.HttpParams);
+    method public static void setAuthenticating(org.apache.http.params.HttpParams, boolean);
+    method public static void setCookiePolicy(org.apache.http.params.HttpParams, java.lang.String);
+    method public static void setRedirecting(org.apache.http.params.HttpParams, boolean);
+  }
+
+}
+
+package org.apache.http.client.protocol {
+
+  public abstract interface ClientContext {
+    field public static final java.lang.String AUTHSCHEME_REGISTRY = "http.authscheme-registry";
+    field public static final java.lang.String AUTH_SCHEME_PREF = "http.auth.scheme-pref";
+    field public static final java.lang.String COOKIESPEC_REGISTRY = "http.cookiespec-registry";
+    field public static final java.lang.String COOKIE_ORIGIN = "http.cookie-origin";
+    field public static final java.lang.String COOKIE_SPEC = "http.cookie-spec";
+    field public static final java.lang.String COOKIE_STORE = "http.cookie-store";
+    field public static final java.lang.String CREDS_PROVIDER = "http.auth.credentials-provider";
+    field public static final java.lang.String PROXY_AUTH_STATE = "http.auth.proxy-scope";
+    field public static final java.lang.String TARGET_AUTH_STATE = "http.auth.target-scope";
+    field public static final java.lang.String USER_TOKEN = "http.user-token";
+  }
+
+  public class ClientContextConfigurer implements org.apache.http.client.protocol.ClientContext {
+    ctor public ClientContextConfigurer(org.apache.http.protocol.HttpContext);
+    method public void setAuthSchemePref(java.util.List<java.lang.String>);
+    method public void setAuthSchemeRegistry(org.apache.http.auth.AuthSchemeRegistry);
+    method public void setCookieSpecRegistry(org.apache.http.cookie.CookieSpecRegistry);
+    method public void setCookieStore(org.apache.http.client.CookieStore);
+    method public void setCredentialsProvider(org.apache.http.client.CredentialsProvider);
+  }
+
+  public class RequestAddCookies implements org.apache.http.HttpRequestInterceptor {
+    ctor public RequestAddCookies();
+    method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class RequestDefaultHeaders implements org.apache.http.HttpRequestInterceptor {
+    ctor public RequestDefaultHeaders();
+    method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class RequestProxyAuthentication implements org.apache.http.HttpRequestInterceptor {
+    ctor public RequestProxyAuthentication();
+    method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class RequestTargetAuthentication implements org.apache.http.HttpRequestInterceptor {
+    ctor public RequestTargetAuthentication();
+    method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class ResponseProcessCookies implements org.apache.http.HttpResponseInterceptor {
+    ctor public ResponseProcessCookies();
+    method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+}
+
+package org.apache.http.client.utils {
+
+  public class CloneUtils {
+    method public static java.lang.Object clone(java.lang.Object) throws java.lang.CloneNotSupportedException;
+  }
+
+  public class URIUtils {
+    method public static java.net.URI createURI(java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String) throws java.net.URISyntaxException;
+    method public static java.net.URI resolve(java.net.URI, java.lang.String);
+    method public static java.net.URI resolve(java.net.URI, java.net.URI);
+    method public static java.net.URI rewriteURI(java.net.URI, org.apache.http.HttpHost, boolean) throws java.net.URISyntaxException;
+    method public static java.net.URI rewriteURI(java.net.URI, org.apache.http.HttpHost) throws java.net.URISyntaxException;
+  }
+
+  public class URLEncodedUtils {
+    ctor public URLEncodedUtils();
+    method public static java.lang.String format(java.util.List<? extends org.apache.http.NameValuePair>, java.lang.String);
+    method public static boolean isEncoded(org.apache.http.HttpEntity);
+    method public static java.util.List<org.apache.http.NameValuePair> parse(java.net.URI, java.lang.String);
+    method public static java.util.List<org.apache.http.NameValuePair> parse(org.apache.http.HttpEntity) throws java.io.IOException;
+    method public static void parse(java.util.List<org.apache.http.NameValuePair>, java.util.Scanner, java.lang.String);
+    field public static final java.lang.String CONTENT_TYPE = "application/x-www-form-urlencoded";
+  }
+
+}
+
+package org.apache.http.conn {
+
+  public class BasicEofSensorWatcher implements org.apache.http.conn.EofSensorWatcher {
+    ctor public BasicEofSensorWatcher(org.apache.http.conn.ManagedClientConnection, boolean);
+    method public boolean eofDetected(java.io.InputStream) throws java.io.IOException;
+    method public boolean streamAbort(java.io.InputStream) throws java.io.IOException;
+    method public boolean streamClosed(java.io.InputStream) throws java.io.IOException;
+    field protected boolean attemptReuse;
+    field protected org.apache.http.conn.ManagedClientConnection managedConn;
+  }
+
+  public class BasicManagedEntity extends org.apache.http.entity.HttpEntityWrapper implements org.apache.http.conn.ConnectionReleaseTrigger org.apache.http.conn.EofSensorWatcher {
+    ctor public BasicManagedEntity(org.apache.http.HttpEntity, org.apache.http.conn.ManagedClientConnection, boolean);
+    method public void abortConnection() throws java.io.IOException;
+    method public boolean eofDetected(java.io.InputStream) throws java.io.IOException;
+    method public void releaseConnection() throws java.io.IOException;
+    method protected void releaseManagedConnection() throws java.io.IOException;
+    method public boolean streamAbort(java.io.InputStream) throws java.io.IOException;
+    method public boolean streamClosed(java.io.InputStream) throws java.io.IOException;
+    field protected final boolean attemptReuse;
+    field protected org.apache.http.conn.ManagedClientConnection managedConn;
+  }
+
+  public abstract interface ClientConnectionManager {
+    method public abstract void closeExpiredConnections();
+    method public abstract void closeIdleConnections(long, java.util.concurrent.TimeUnit);
+    method public abstract org.apache.http.conn.scheme.SchemeRegistry getSchemeRegistry();
+    method public abstract void releaseConnection(org.apache.http.conn.ManagedClientConnection, long, java.util.concurrent.TimeUnit);
+    method public abstract org.apache.http.conn.ClientConnectionRequest requestConnection(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
+    method public abstract void shutdown();
+  }
+
+  public abstract interface ClientConnectionManagerFactory {
+    method public abstract org.apache.http.conn.ClientConnectionManager newInstance(org.apache.http.params.HttpParams, org.apache.http.conn.scheme.SchemeRegistry);
+  }
+
+  public abstract interface ClientConnectionOperator {
+    method public abstract org.apache.http.conn.OperatedClientConnection createConnection();
+    method public abstract void openConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public abstract void updateSecureConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
+  }
+
+  public abstract interface ClientConnectionRequest {
+    method public abstract void abortRequest();
+    method public abstract org.apache.http.conn.ManagedClientConnection getConnection(long, java.util.concurrent.TimeUnit) throws org.apache.http.conn.ConnectionPoolTimeoutException, java.lang.InterruptedException;
+  }
+
+  public class ConnectTimeoutException extends java.io.InterruptedIOException {
+    ctor public ConnectTimeoutException();
+    ctor public ConnectTimeoutException(java.lang.String);
+  }
+
+  public abstract interface ConnectionKeepAliveStrategy {
+    method public abstract long getKeepAliveDuration(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
+  }
+
+  public class ConnectionPoolTimeoutException extends org.apache.http.conn.ConnectTimeoutException {
+    ctor public ConnectionPoolTimeoutException();
+    ctor public ConnectionPoolTimeoutException(java.lang.String);
+  }
+
+  public abstract interface ConnectionReleaseTrigger {
+    method public abstract void abortConnection() throws java.io.IOException;
+    method public abstract void releaseConnection() throws java.io.IOException;
+  }
+
+  public class EofSensorInputStream extends java.io.InputStream implements org.apache.http.conn.ConnectionReleaseTrigger {
+    ctor public EofSensorInputStream(java.io.InputStream, org.apache.http.conn.EofSensorWatcher);
+    method public void abortConnection() throws java.io.IOException;
+    method protected void checkAbort() throws java.io.IOException;
+    method protected void checkClose() throws java.io.IOException;
+    method protected void checkEOF(int) throws java.io.IOException;
+    method protected boolean isReadAllowed() throws java.io.IOException;
+    method public int read() throws java.io.IOException;
+    method public void releaseConnection() throws java.io.IOException;
+    field protected java.io.InputStream wrappedStream;
+  }
+
+  public abstract interface EofSensorWatcher {
+    method public abstract boolean eofDetected(java.io.InputStream) throws java.io.IOException;
+    method public abstract boolean streamAbort(java.io.InputStream) throws java.io.IOException;
+    method public abstract boolean streamClosed(java.io.InputStream) throws java.io.IOException;
+  }
+
+  public class HttpHostConnectException extends java.net.ConnectException {
+    ctor public HttpHostConnectException(org.apache.http.HttpHost, java.net.ConnectException);
+    method public org.apache.http.HttpHost getHost();
+  }
+
+  public abstract interface ManagedClientConnection implements org.apache.http.conn.ConnectionReleaseTrigger org.apache.http.HttpClientConnection org.apache.http.HttpInetConnection {
+    method public abstract org.apache.http.conn.routing.HttpRoute getRoute();
+    method public abstract javax.net.ssl.SSLSession getSSLSession();
+    method public abstract java.lang.Object getState();
+    method public abstract boolean isMarkedReusable();
+    method public abstract boolean isSecure();
+    method public abstract void layerProtocol(org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public abstract void markReusable();
+    method public abstract void open(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public abstract void setIdleDuration(long, java.util.concurrent.TimeUnit);
+    method public abstract void setState(java.lang.Object);
+    method public abstract void tunnelProxy(org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public abstract void tunnelTarget(boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public abstract void unmarkReusable();
+  }
+
+  public final class MultihomePlainSocketFactory implements org.apache.http.conn.scheme.SocketFactory {
+    method public java.net.Socket connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public java.net.Socket createSocket();
+    method public static org.apache.http.conn.MultihomePlainSocketFactory getSocketFactory();
+    method public final boolean isSecure(java.net.Socket) throws java.lang.IllegalArgumentException;
+  }
+
+  public abstract interface OperatedClientConnection implements org.apache.http.HttpClientConnection org.apache.http.HttpInetConnection {
+    method public abstract java.net.Socket getSocket();
+    method public abstract org.apache.http.HttpHost getTargetHost();
+    method public abstract boolean isSecure();
+    method public abstract void openCompleted(boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public abstract void opening(java.net.Socket, org.apache.http.HttpHost) throws java.io.IOException;
+    method public abstract void update(java.net.Socket, org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
+  }
+
+}
+
+package org.apache.http.conn.params {
+
+  public abstract interface ConnConnectionPNames {
+    field public static final java.lang.String MAX_STATUS_LINE_GARBAGE = "http.connection.max-status-line-garbage";
+  }
+
+  public class ConnConnectionParamBean extends org.apache.http.params.HttpAbstractParamBean {
+    ctor public ConnConnectionParamBean(org.apache.http.params.HttpParams);
+    method public void setMaxStatusLineGarbage(int);
+  }
+
+  public abstract interface ConnManagerPNames {
+    field public static final java.lang.String MAX_CONNECTIONS_PER_ROUTE = "http.conn-manager.max-per-route";
+    field public static final java.lang.String MAX_TOTAL_CONNECTIONS = "http.conn-manager.max-total";
+    field public static final java.lang.String TIMEOUT = "http.conn-manager.timeout";
+  }
+
+  public class ConnManagerParamBean extends org.apache.http.params.HttpAbstractParamBean {
+    ctor public ConnManagerParamBean(org.apache.http.params.HttpParams);
+    method public void setConnectionsPerRoute(org.apache.http.conn.params.ConnPerRouteBean);
+    method public void setMaxTotalConnections(int);
+    method public void setTimeout(long);
+  }
+
+  public final class ConnManagerParams implements org.apache.http.conn.params.ConnManagerPNames {
+    ctor public ConnManagerParams();
+    method public static org.apache.http.conn.params.ConnPerRoute getMaxConnectionsPerRoute(org.apache.http.params.HttpParams);
+    method public static int getMaxTotalConnections(org.apache.http.params.HttpParams);
+    method public static long getTimeout(org.apache.http.params.HttpParams);
+    method public static void setMaxConnectionsPerRoute(org.apache.http.params.HttpParams, org.apache.http.conn.params.ConnPerRoute);
+    method public static void setMaxTotalConnections(org.apache.http.params.HttpParams, int);
+    method public static void setTimeout(org.apache.http.params.HttpParams, long);
+    field public static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 20; // 0x14
+  }
+
+  public abstract interface ConnPerRoute {
+    method public abstract int getMaxForRoute(org.apache.http.conn.routing.HttpRoute);
+  }
+
+  public final class ConnPerRouteBean implements org.apache.http.conn.params.ConnPerRoute {
+    ctor public ConnPerRouteBean(int);
+    ctor public ConnPerRouteBean();
+    method public int getDefaultMax();
+    method public int getMaxForRoute(org.apache.http.conn.routing.HttpRoute);
+    method public void setDefaultMaxPerRoute(int);
+    method public void setMaxForRoute(org.apache.http.conn.routing.HttpRoute, int);
+    method public void setMaxForRoutes(java.util.Map<org.apache.http.conn.routing.HttpRoute, java.lang.Integer>);
+    field public static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 2; // 0x2
+  }
+
+  public abstract interface ConnRoutePNames {
+    field public static final java.lang.String DEFAULT_PROXY = "http.route.default-proxy";
+    field public static final java.lang.String FORCED_ROUTE = "http.route.forced-route";
+    field public static final java.lang.String LOCAL_ADDRESS = "http.route.local-address";
+  }
+
+  public class ConnRouteParamBean extends org.apache.http.params.HttpAbstractParamBean {
+    ctor public ConnRouteParamBean(org.apache.http.params.HttpParams);
+    method public void setDefaultProxy(org.apache.http.HttpHost);
+    method public void setForcedRoute(org.apache.http.conn.routing.HttpRoute);
+    method public void setLocalAddress(java.net.InetAddress);
+  }
+
+  public class ConnRouteParams implements org.apache.http.conn.params.ConnRoutePNames {
+    method public static org.apache.http.HttpHost getDefaultProxy(org.apache.http.params.HttpParams);
+    method public static org.apache.http.conn.routing.HttpRoute getForcedRoute(org.apache.http.params.HttpParams);
+    method public static java.net.InetAddress getLocalAddress(org.apache.http.params.HttpParams);
+    method public static void setDefaultProxy(org.apache.http.params.HttpParams, org.apache.http.HttpHost);
+    method public static void setForcedRoute(org.apache.http.params.HttpParams, org.apache.http.conn.routing.HttpRoute);
+    method public static void setLocalAddress(org.apache.http.params.HttpParams, java.net.InetAddress);
+    field public static final org.apache.http.HttpHost NO_HOST;
+    field public static final org.apache.http.conn.routing.HttpRoute NO_ROUTE;
+  }
+
+}
+
+package org.apache.http.conn.routing {
+
+  public class BasicRouteDirector implements org.apache.http.conn.routing.HttpRouteDirector {
+    ctor public BasicRouteDirector();
+    method protected int directStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo);
+    method protected int firstStep(org.apache.http.conn.routing.RouteInfo);
+    method public int nextStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo);
+    method protected int proxiedStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo);
+  }
+
+  public final class HttpRoute implements java.lang.Cloneable org.apache.http.conn.routing.RouteInfo {
+    ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.HttpHost[], boolean, org.apache.http.conn.routing.RouteInfo.TunnelType, org.apache.http.conn.routing.RouteInfo.LayerType);
+    ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.HttpHost, boolean, org.apache.http.conn.routing.RouteInfo.TunnelType, org.apache.http.conn.routing.RouteInfo.LayerType);
+    ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, boolean);
+    ctor public HttpRoute(org.apache.http.HttpHost);
+    ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.HttpHost, boolean);
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public final boolean equals(java.lang.Object);
+    method public final int getHopCount();
+    method public final org.apache.http.HttpHost getHopTarget(int);
+    method public final org.apache.http.conn.routing.RouteInfo.LayerType getLayerType();
+    method public final java.net.InetAddress getLocalAddress();
+    method public final org.apache.http.HttpHost getProxyHost();
+    method public final org.apache.http.HttpHost getTargetHost();
+    method public final org.apache.http.conn.routing.RouteInfo.TunnelType getTunnelType();
+    method public final int hashCode();
+    method public final boolean isLayered();
+    method public final boolean isSecure();
+    method public final boolean isTunnelled();
+    method public final java.lang.String toString();
+  }
+
+  public abstract interface HttpRouteDirector {
+    method public abstract int nextStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo);
+    field public static final int COMPLETE = 0; // 0x0
+    field public static final int CONNECT_PROXY = 2; // 0x2
+    field public static final int CONNECT_TARGET = 1; // 0x1
+    field public static final int LAYER_PROTOCOL = 5; // 0x5
+    field public static final int TUNNEL_PROXY = 4; // 0x4
+    field public static final int TUNNEL_TARGET = 3; // 0x3
+    field public static final int UNREACHABLE = -1; // 0xffffffff
+  }
+
+  public abstract interface HttpRoutePlanner {
+    method public abstract org.apache.http.conn.routing.HttpRoute determineRoute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
+  }
+
+  public abstract interface RouteInfo {
+    method public abstract int getHopCount();
+    method public abstract org.apache.http.HttpHost getHopTarget(int);
+    method public abstract org.apache.http.conn.routing.RouteInfo.LayerType getLayerType();
+    method public abstract java.net.InetAddress getLocalAddress();
+    method public abstract org.apache.http.HttpHost getProxyHost();
+    method public abstract org.apache.http.HttpHost getTargetHost();
+    method public abstract org.apache.http.conn.routing.RouteInfo.TunnelType getTunnelType();
+    method public abstract boolean isLayered();
+    method public abstract boolean isSecure();
+    method public abstract boolean isTunnelled();
+  }
+
+  public static final class RouteInfo.LayerType extends java.lang.Enum {
+    method public static org.apache.http.conn.routing.RouteInfo.LayerType valueOf(java.lang.String);
+    method public static final org.apache.http.conn.routing.RouteInfo.LayerType[] values();
+    enum_constant public static final org.apache.http.conn.routing.RouteInfo.LayerType LAYERED;
+    enum_constant public static final org.apache.http.conn.routing.RouteInfo.LayerType PLAIN;
+  }
+
+  public static final class RouteInfo.TunnelType extends java.lang.Enum {
+    method public static org.apache.http.conn.routing.RouteInfo.TunnelType valueOf(java.lang.String);
+    method public static final org.apache.http.conn.routing.RouteInfo.TunnelType[] values();
+    enum_constant public static final org.apache.http.conn.routing.RouteInfo.TunnelType PLAIN;
+    enum_constant public static final org.apache.http.conn.routing.RouteInfo.TunnelType TUNNELLED;
+  }
+
+  public final class RouteTracker implements java.lang.Cloneable org.apache.http.conn.routing.RouteInfo {
+    ctor public RouteTracker(org.apache.http.HttpHost, java.net.InetAddress);
+    ctor public RouteTracker(org.apache.http.conn.routing.HttpRoute);
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public final void connectProxy(org.apache.http.HttpHost, boolean);
+    method public final void connectTarget(boolean);
+    method public final boolean equals(java.lang.Object);
+    method public final int getHopCount();
+    method public final org.apache.http.HttpHost getHopTarget(int);
+    method public final org.apache.http.conn.routing.RouteInfo.LayerType getLayerType();
+    method public final java.net.InetAddress getLocalAddress();
+    method public final org.apache.http.HttpHost getProxyHost();
+    method public final org.apache.http.HttpHost getTargetHost();
+    method public final org.apache.http.conn.routing.RouteInfo.TunnelType getTunnelType();
+    method public final int hashCode();
+    method public final boolean isConnected();
+    method public final boolean isLayered();
+    method public final boolean isSecure();
+    method public final boolean isTunnelled();
+    method public final void layerProtocol(boolean);
+    method public final org.apache.http.conn.routing.HttpRoute toRoute();
+    method public final java.lang.String toString();
+    method public final void tunnelProxy(org.apache.http.HttpHost, boolean);
+    method public final void tunnelTarget(boolean);
+  }
+
+}
+
+package org.apache.http.conn.scheme {
+
+  public abstract interface HostNameResolver {
+    method public abstract java.net.InetAddress resolve(java.lang.String) throws java.io.IOException;
+  }
+
+  public abstract interface LayeredSocketFactory implements org.apache.http.conn.scheme.SocketFactory {
+    method public abstract java.net.Socket createSocket(java.net.Socket, java.lang.String, int, boolean) throws java.io.IOException, java.net.UnknownHostException;
+  }
+
+  public final class PlainSocketFactory implements org.apache.http.conn.scheme.SocketFactory {
+    ctor public PlainSocketFactory(org.apache.http.conn.scheme.HostNameResolver);
+    ctor public PlainSocketFactory();
+    method public java.net.Socket connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public java.net.Socket createSocket();
+    method public static org.apache.http.conn.scheme.PlainSocketFactory getSocketFactory();
+    method public final boolean isSecure(java.net.Socket) throws java.lang.IllegalArgumentException;
+  }
+
+  public final class Scheme {
+    ctor public Scheme(java.lang.String, org.apache.http.conn.scheme.SocketFactory, int);
+    method public final boolean equals(java.lang.Object);
+    method public final int getDefaultPort();
+    method public final java.lang.String getName();
+    method public final org.apache.http.conn.scheme.SocketFactory getSocketFactory();
+    method public final boolean isLayered();
+    method public final int resolvePort(int);
+    method public final java.lang.String toString();
+  }
+
+  public final class SchemeRegistry {
+    ctor public SchemeRegistry();
+    method public final synchronized org.apache.http.conn.scheme.Scheme get(java.lang.String);
+    method public final synchronized org.apache.http.conn.scheme.Scheme getScheme(java.lang.String);
+    method public final synchronized org.apache.http.conn.scheme.Scheme getScheme(org.apache.http.HttpHost);
+    method public final synchronized java.util.List<java.lang.String> getSchemeNames();
+    method public final synchronized org.apache.http.conn.scheme.Scheme register(org.apache.http.conn.scheme.Scheme);
+    method public synchronized void setItems(java.util.Map<java.lang.String, org.apache.http.conn.scheme.Scheme>);
+    method public final synchronized org.apache.http.conn.scheme.Scheme unregister(java.lang.String);
+  }
+
+  public abstract interface SocketFactory {
+    method public abstract java.net.Socket connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams) throws org.apache.http.conn.ConnectTimeoutException, java.io.IOException, java.net.UnknownHostException;
+    method public abstract java.net.Socket createSocket() throws java.io.IOException;
+    method public abstract boolean isSecure(java.net.Socket) throws java.lang.IllegalArgumentException;
+  }
+
+}
+
+package org.apache.http.conn.ssl {
+
+  public abstract class AbstractVerifier implements org.apache.http.conn.ssl.X509HostnameVerifier {
+    ctor public AbstractVerifier();
+    method public static boolean acceptableCountryWildcard(java.lang.String);
+    method public static int countDots(java.lang.String);
+    method public static java.lang.String[] getCNs(java.security.cert.X509Certificate);
+    method public static java.lang.String[] getDNSSubjectAlts(java.security.cert.X509Certificate);
+    method public final void verify(java.lang.String, javax.net.ssl.SSLSocket) throws java.io.IOException;
+    method public final boolean verify(java.lang.String, javax.net.ssl.SSLSession);
+    method public final void verify(java.lang.String, java.security.cert.X509Certificate) throws javax.net.ssl.SSLException;
+    method public final void verify(java.lang.String, java.lang.String[], java.lang.String[], boolean) throws javax.net.ssl.SSLException;
+  }
+
+  public class AllowAllHostnameVerifier extends org.apache.http.conn.ssl.AbstractVerifier {
+    ctor public AllowAllHostnameVerifier();
+    method public final java.lang.String toString();
+    method public final void verify(java.lang.String, java.lang.String[], java.lang.String[]);
+  }
+
+  public class BrowserCompatHostnameVerifier extends org.apache.http.conn.ssl.AbstractVerifier {
+    ctor public BrowserCompatHostnameVerifier();
+    method public final java.lang.String toString();
+    method public final void verify(java.lang.String, java.lang.String[], java.lang.String[]) throws javax.net.ssl.SSLException;
+  }
+
+  public class SSLSocketFactory implements org.apache.http.conn.scheme.LayeredSocketFactory {
+    ctor public SSLSocketFactory(java.lang.String, java.security.KeyStore, java.lang.String, java.security.KeyStore, java.security.SecureRandom, org.apache.http.conn.scheme.HostNameResolver) throws java.security.KeyManagementException, java.security.KeyStoreException, java.security.NoSuchAlgorithmException, java.security.UnrecoverableKeyException;
+    ctor public SSLSocketFactory(java.security.KeyStore, java.lang.String, java.security.KeyStore) throws java.security.KeyManagementException, java.security.KeyStoreException, java.security.NoSuchAlgorithmException, java.security.UnrecoverableKeyException;
+    ctor public SSLSocketFactory(java.security.KeyStore, java.lang.String) throws java.security.KeyManagementException, java.security.KeyStoreException, java.security.NoSuchAlgorithmException, java.security.UnrecoverableKeyException;
+    ctor public SSLSocketFactory(java.security.KeyStore) throws java.security.KeyManagementException, java.security.KeyStoreException, java.security.NoSuchAlgorithmException, java.security.UnrecoverableKeyException;
+    method public java.net.Socket connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public java.net.Socket createSocket() throws java.io.IOException;
+    method public java.net.Socket createSocket(java.net.Socket, java.lang.String, int, boolean) throws java.io.IOException, java.net.UnknownHostException;
+    method public org.apache.http.conn.ssl.X509HostnameVerifier getHostnameVerifier();
+    method public static org.apache.http.conn.ssl.SSLSocketFactory getSocketFactory();
+    method public boolean isSecure(java.net.Socket) throws java.lang.IllegalArgumentException;
+    method public void setHostnameVerifier(org.apache.http.conn.ssl.X509HostnameVerifier);
+    field public static final org.apache.http.conn.ssl.X509HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER;
+    field public static final org.apache.http.conn.ssl.X509HostnameVerifier BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
+    field public static final java.lang.String SSL = "SSL";
+    field public static final java.lang.String SSLV2 = "SSLv2";
+    field public static final org.apache.http.conn.ssl.X509HostnameVerifier STRICT_HOSTNAME_VERIFIER;
+    field public static final java.lang.String TLS = "TLS";
+  }
+
+  public class StrictHostnameVerifier extends org.apache.http.conn.ssl.AbstractVerifier {
+    ctor public StrictHostnameVerifier();
+    method public final java.lang.String toString();
+    method public final void verify(java.lang.String, java.lang.String[], java.lang.String[]) throws javax.net.ssl.SSLException;
+  }
+
+  public abstract interface X509HostnameVerifier implements javax.net.ssl.HostnameVerifier {
+    method public abstract boolean verify(java.lang.String, javax.net.ssl.SSLSession);
+    method public abstract void verify(java.lang.String, javax.net.ssl.SSLSocket) throws java.io.IOException;
+    method public abstract void verify(java.lang.String, java.security.cert.X509Certificate) throws javax.net.ssl.SSLException;
+    method public abstract void verify(java.lang.String, java.lang.String[], java.lang.String[]) throws javax.net.ssl.SSLException;
+  }
+
+}
+
+package org.apache.http.conn.util {
+
+  public class InetAddressUtils {
+    method public static boolean isIPv4Address(java.lang.String);
+    method public static boolean isIPv6Address(java.lang.String);
+    method public static boolean isIPv6HexCompressedAddress(java.lang.String);
+    method public static boolean isIPv6StdAddress(java.lang.String);
+  }
+
+}
+
+package org.apache.http.cookie {
+
+  public abstract interface ClientCookie implements org.apache.http.cookie.Cookie {
+    method public abstract boolean containsAttribute(java.lang.String);
+    method public abstract java.lang.String getAttribute(java.lang.String);
+    field public static final java.lang.String COMMENTURL_ATTR = "commenturl";
+    field public static final java.lang.String COMMENT_ATTR = "comment";
+    field public static final java.lang.String DISCARD_ATTR = "discard";
+    field public static final java.lang.String DOMAIN_ATTR = "domain";
+    field public static final java.lang.String EXPIRES_ATTR = "expires";
+    field public static final java.lang.String MAX_AGE_ATTR = "max-age";
+    field public static final java.lang.String PATH_ATTR = "path";
+    field public static final java.lang.String PORT_ATTR = "port";
+    field public static final java.lang.String SECURE_ATTR = "secure";
+    field public static final java.lang.String VERSION_ATTR = "version";
+  }
+
+  public abstract interface Cookie {
+    method public abstract java.lang.String getComment();
+    method public abstract java.lang.String getCommentURL();
+    method public abstract java.lang.String getDomain();
+    method public abstract java.util.Date getExpiryDate();
+    method public abstract java.lang.String getName();
+    method public abstract java.lang.String getPath();
+    method public abstract int[] getPorts();
+    method public abstract java.lang.String getValue();
+    method public abstract int getVersion();
+    method public abstract boolean isExpired(java.util.Date);
+    method public abstract boolean isPersistent();
+    method public abstract boolean isSecure();
+  }
+
+  public abstract interface CookieAttributeHandler {
+    method public abstract boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
+    method public abstract void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
+    method public abstract void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public class CookieIdentityComparator implements java.util.Comparator java.io.Serializable {
+    ctor public CookieIdentityComparator();
+    method public int compare(org.apache.http.cookie.Cookie, org.apache.http.cookie.Cookie);
+  }
+
+  public final class CookieOrigin {
+    ctor public CookieOrigin(java.lang.String, int, java.lang.String, boolean);
+    method public java.lang.String getHost();
+    method public java.lang.String getPath();
+    method public int getPort();
+    method public boolean isSecure();
+  }
+
+  public class CookiePathComparator implements java.util.Comparator java.io.Serializable {
+    ctor public CookiePathComparator();
+    method public int compare(org.apache.http.cookie.Cookie, org.apache.http.cookie.Cookie);
+  }
+
+  public abstract interface CookieSpec {
+    method public abstract java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
+    method public abstract int getVersion();
+    method public abstract org.apache.http.Header getVersionHeader();
+    method public abstract boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
+    method public abstract java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+    method public abstract void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public abstract interface CookieSpecFactory {
+    method public abstract org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
+  }
+
+  public final class CookieSpecRegistry {
+    ctor public CookieSpecRegistry();
+    method public synchronized org.apache.http.cookie.CookieSpec getCookieSpec(java.lang.String, org.apache.http.params.HttpParams) throws java.lang.IllegalStateException;
+    method public synchronized org.apache.http.cookie.CookieSpec getCookieSpec(java.lang.String) throws java.lang.IllegalStateException;
+    method public synchronized java.util.List<java.lang.String> getSpecNames();
+    method public synchronized void register(java.lang.String, org.apache.http.cookie.CookieSpecFactory);
+    method public synchronized void setItems(java.util.Map<java.lang.String, org.apache.http.cookie.CookieSpecFactory>);
+    method public synchronized void unregister(java.lang.String);
+  }
+
+  public class MalformedCookieException extends org.apache.http.ProtocolException {
+    ctor public MalformedCookieException();
+    ctor public MalformedCookieException(java.lang.String);
+    ctor public MalformedCookieException(java.lang.String, java.lang.Throwable);
+  }
+
+  public abstract interface SM {
+    field public static final java.lang.String COOKIE = "Cookie";
+    field public static final java.lang.String COOKIE2 = "Cookie2";
+    field public static final java.lang.String SET_COOKIE = "Set-Cookie";
+    field public static final java.lang.String SET_COOKIE2 = "Set-Cookie2";
+  }
+
+  public abstract interface SetCookie implements org.apache.http.cookie.Cookie {
+    method public abstract void setComment(java.lang.String);
+    method public abstract void setDomain(java.lang.String);
+    method public abstract void setExpiryDate(java.util.Date);
+    method public abstract void setPath(java.lang.String);
+    method public abstract void setSecure(boolean);
+    method public abstract void setValue(java.lang.String);
+    method public abstract void setVersion(int);
+  }
+
+  public abstract interface SetCookie2 implements org.apache.http.cookie.SetCookie {
+    method public abstract void setCommentURL(java.lang.String);
+    method public abstract void setDiscard(boolean);
+    method public abstract void setPorts(int[]);
+  }
+
+}
+
+package org.apache.http.cookie.params {
+
+  public abstract interface CookieSpecPNames {
+    field public static final java.lang.String DATE_PATTERNS = "http.protocol.cookie-datepatterns";
+    field public static final java.lang.String SINGLE_COOKIE_HEADER = "http.protocol.single-cookie-header";
+  }
+
+  public class CookieSpecParamBean extends org.apache.http.params.HttpAbstractParamBean {
+    ctor public CookieSpecParamBean(org.apache.http.params.HttpParams);
+    method public void setDatePatterns(java.util.Collection<java.lang.String>);
+    method public void setSingleHeader(boolean);
+  }
+
+}
+
+package org.apache.http.entity {
+
+  public abstract class AbstractHttpEntity implements org.apache.http.HttpEntity {
+    ctor protected AbstractHttpEntity();
+    method public void consumeContent() throws java.io.IOException, java.lang.UnsupportedOperationException;
+    method public org.apache.http.Header getContentEncoding();
+    method public org.apache.http.Header getContentType();
+    method public boolean isChunked();
+    method public void setChunked(boolean);
+    method public void setContentEncoding(org.apache.http.Header);
+    method public void setContentEncoding(java.lang.String);
+    method public void setContentType(org.apache.http.Header);
+    method public void setContentType(java.lang.String);
+    field protected boolean chunked;
+    field protected org.apache.http.Header contentEncoding;
+    field protected org.apache.http.Header contentType;
+  }
+
+  public class BasicHttpEntity extends org.apache.http.entity.AbstractHttpEntity {
+    ctor public BasicHttpEntity();
+    method public java.io.InputStream getContent() throws java.lang.IllegalStateException;
+    method public long getContentLength();
+    method public boolean isRepeatable();
+    method public boolean isStreaming();
+    method public void setContent(java.io.InputStream);
+    method public void setContentLength(long);
+    method public void writeTo(java.io.OutputStream) throws java.io.IOException;
+  }
+
+  public class BufferedHttpEntity extends org.apache.http.entity.HttpEntityWrapper {
+    ctor public BufferedHttpEntity(org.apache.http.HttpEntity) throws java.io.IOException;
+  }
+
+  public class ByteArrayEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable {
+    ctor public ByteArrayEntity(byte[]);
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public java.io.InputStream getContent();
+    method public long getContentLength();
+    method public boolean isRepeatable();
+    method public boolean isStreaming();
+    method public void writeTo(java.io.OutputStream) throws java.io.IOException;
+    field protected final byte[] content;
+  }
+
+  public abstract interface ContentLengthStrategy {
+    method public abstract long determineLength(org.apache.http.HttpMessage) throws org.apache.http.HttpException;
+    field public static final int CHUNKED = -2; // 0xfffffffe
+    field public static final int IDENTITY = -1; // 0xffffffff
+  }
+
+  public abstract interface ContentProducer {
+    method public abstract void writeTo(java.io.OutputStream) throws java.io.IOException;
+  }
+
+  public class EntityTemplate extends org.apache.http.entity.AbstractHttpEntity {
+    ctor public EntityTemplate(org.apache.http.entity.ContentProducer);
+    method public java.io.InputStream getContent();
+    method public long getContentLength();
+    method public boolean isRepeatable();
+    method public boolean isStreaming();
+    method public void writeTo(java.io.OutputStream) throws java.io.IOException;
+  }
+
+  public class FileEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable {
+    ctor public FileEntity(java.io.File, java.lang.String);
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public java.io.InputStream getContent() throws java.io.IOException;
+    method public long getContentLength();
+    method public boolean isRepeatable();
+    method public boolean isStreaming();
+    method public void writeTo(java.io.OutputStream) throws java.io.IOException;
+    field protected final java.io.File file;
+  }
+
+  public class HttpEntityWrapper implements org.apache.http.HttpEntity {
+    ctor public HttpEntityWrapper(org.apache.http.HttpEntity);
+    method public void consumeContent() throws java.io.IOException;
+    method public java.io.InputStream getContent() throws java.io.IOException;
+    method public org.apache.http.Header getContentEncoding();
+    method public long getContentLength();
+    method public org.apache.http.Header getContentType();
+    method public boolean isChunked();
+    method public boolean isRepeatable();
+    method public boolean isStreaming();
+    method public void writeTo(java.io.OutputStream) throws java.io.IOException;
+    field protected org.apache.http.HttpEntity wrappedEntity;
+  }
+
+  public class InputStreamEntity extends org.apache.http.entity.AbstractHttpEntity {
+    ctor public InputStreamEntity(java.io.InputStream, long);
+    method public java.io.InputStream getContent() throws java.io.IOException;
+    method public long getContentLength();
+    method public boolean isRepeatable();
+    method public boolean isStreaming();
+    method public void writeTo(java.io.OutputStream) throws java.io.IOException;
+  }
+
+  public class SerializableEntity extends org.apache.http.entity.AbstractHttpEntity {
+    ctor public SerializableEntity(java.io.Serializable, boolean) throws java.io.IOException;
+    method public java.io.InputStream getContent() throws java.io.IOException, java.lang.IllegalStateException;
+    method public long getContentLength();
+    method public boolean isRepeatable();
+    method public boolean isStreaming();
+    method public void writeTo(java.io.OutputStream) throws java.io.IOException;
+  }
+
+  public class StringEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable {
+    ctor public StringEntity(java.lang.String, java.lang.String) throws java.io.UnsupportedEncodingException;
+    ctor public StringEntity(java.lang.String) throws java.io.UnsupportedEncodingException;
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public java.io.InputStream getContent() throws java.io.IOException;
+    method public long getContentLength();
+    method public boolean isRepeatable();
+    method public boolean isStreaming();
+    method public void writeTo(java.io.OutputStream) throws java.io.IOException;
+    field protected final byte[] content;
+  }
+
+}
+
+package org.apache.http.impl {
+
+  public abstract class AbstractHttpClientConnection implements org.apache.http.HttpClientConnection {
+    ctor public AbstractHttpClientConnection();
+    method protected abstract void assertOpen() throws java.lang.IllegalStateException;
+    method protected org.apache.http.impl.entity.EntityDeserializer createEntityDeserializer();
+    method protected org.apache.http.impl.entity.EntitySerializer createEntitySerializer();
+    method protected org.apache.http.HttpResponseFactory createHttpResponseFactory();
+    method protected org.apache.http.io.HttpMessageWriter createRequestWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.params.HttpParams);
+    method protected org.apache.http.io.HttpMessageParser createResponseParser(org.apache.http.io.SessionInputBuffer, org.apache.http.HttpResponseFactory, org.apache.http.params.HttpParams);
+    method protected void doFlush() throws java.io.IOException;
+    method public void flush() throws java.io.IOException;
+    method public org.apache.http.HttpConnectionMetrics getMetrics();
+    method protected void init(org.apache.http.io.SessionInputBuffer, org.apache.http.io.SessionOutputBuffer, org.apache.http.params.HttpParams);
+    method public boolean isResponseAvailable(int) throws java.io.IOException;
+    method public boolean isStale();
+    method public void receiveResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
+    method public org.apache.http.HttpResponse receiveResponseHeader() throws org.apache.http.HttpException, java.io.IOException;
+    method public void sendRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException;
+    method public void sendRequestHeader(org.apache.http.HttpRequest) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public abstract class AbstractHttpServerConnection implements org.apache.http.HttpServerConnection {
+    ctor public AbstractHttpServerConnection();
+    method protected abstract void assertOpen() throws java.lang.IllegalStateException;
+    method protected org.apache.http.impl.entity.EntityDeserializer createEntityDeserializer();
+    method protected org.apache.http.impl.entity.EntitySerializer createEntitySerializer();
+    method protected org.apache.http.HttpRequestFactory createHttpRequestFactory();
+    method protected org.apache.http.io.HttpMessageParser createRequestParser(org.apache.http.io.SessionInputBuffer, org.apache.http.HttpRequestFactory, org.apache.http.params.HttpParams);
+    method protected org.apache.http.io.HttpMessageWriter createResponseWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.params.HttpParams);
+    method protected void doFlush() throws java.io.IOException;
+    method public void flush() throws java.io.IOException;
+    method public org.apache.http.HttpConnectionMetrics getMetrics();
+    method protected void init(org.apache.http.io.SessionInputBuffer, org.apache.http.io.SessionOutputBuffer, org.apache.http.params.HttpParams);
+    method public boolean isStale();
+    method public void receiveRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException;
+    method public org.apache.http.HttpRequest receiveRequestHeader() throws org.apache.http.HttpException, java.io.IOException;
+    method public void sendResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
+    method public void sendResponseHeader(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class DefaultConnectionReuseStrategy implements org.apache.http.ConnectionReuseStrategy {
+    ctor public DefaultConnectionReuseStrategy();
+    method protected org.apache.http.TokenIterator createTokenIterator(org.apache.http.HeaderIterator);
+    method public boolean keepAlive(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
+  }
+
+  public class DefaultHttpClientConnection extends org.apache.http.impl.SocketHttpClientConnection {
+    ctor public DefaultHttpClientConnection();
+    method public void bind(java.net.Socket, org.apache.http.params.HttpParams) throws java.io.IOException;
+  }
+
+  public class DefaultHttpRequestFactory implements org.apache.http.HttpRequestFactory {
+    ctor public DefaultHttpRequestFactory();
+    method public org.apache.http.HttpRequest newHttpRequest(org.apache.http.RequestLine) throws org.apache.http.MethodNotSupportedException;
+    method public org.apache.http.HttpRequest newHttpRequest(java.lang.String, java.lang.String) throws org.apache.http.MethodNotSupportedException;
+  }
+
+  public class DefaultHttpResponseFactory implements org.apache.http.HttpResponseFactory {
+    ctor public DefaultHttpResponseFactory(org.apache.http.ReasonPhraseCatalog);
+    ctor public DefaultHttpResponseFactory();
+    method protected java.util.Locale determineLocale(org.apache.http.protocol.HttpContext);
+    method public org.apache.http.HttpResponse newHttpResponse(org.apache.http.ProtocolVersion, int, org.apache.http.protocol.HttpContext);
+    method public org.apache.http.HttpResponse newHttpResponse(org.apache.http.StatusLine, org.apache.http.protocol.HttpContext);
+    field protected final org.apache.http.ReasonPhraseCatalog reasonCatalog;
+  }
+
+  public class DefaultHttpServerConnection extends org.apache.http.impl.SocketHttpServerConnection {
+    ctor public DefaultHttpServerConnection();
+    method public void bind(java.net.Socket, org.apache.http.params.HttpParams) throws java.io.IOException;
+  }
+
+  public class EnglishReasonPhraseCatalog implements org.apache.http.ReasonPhraseCatalog {
+    ctor protected EnglishReasonPhraseCatalog();
+    method public java.lang.String getReason(int, java.util.Locale);
+    field public static final org.apache.http.impl.EnglishReasonPhraseCatalog INSTANCE;
+  }
+
+  public class HttpConnectionMetricsImpl implements org.apache.http.HttpConnectionMetrics {
+    ctor public HttpConnectionMetricsImpl(org.apache.http.io.HttpTransportMetrics, org.apache.http.io.HttpTransportMetrics);
+    method public java.lang.Object getMetric(java.lang.String);
+    method public long getReceivedBytesCount();
+    method public long getRequestCount();
+    method public long getResponseCount();
+    method public long getSentBytesCount();
+    method public void incrementRequestCount();
+    method public void incrementResponseCount();
+    method public void reset();
+    method public void setMetric(java.lang.String, java.lang.Object);
+    field public static final java.lang.String RECEIVED_BYTES_COUNT = "http.received-bytes-count";
+    field public static final java.lang.String REQUEST_COUNT = "http.request-count";
+    field public static final java.lang.String RESPONSE_COUNT = "http.response-count";
+    field public static final java.lang.String SENT_BYTES_COUNT = "http.sent-bytes-count";
+  }
+
+  public class NoConnectionReuseStrategy implements org.apache.http.ConnectionReuseStrategy {
+    ctor public NoConnectionReuseStrategy();
+    method public boolean keepAlive(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
+  }
+
+  public class SocketHttpClientConnection extends org.apache.http.impl.AbstractHttpClientConnection implements org.apache.http.HttpInetConnection {
+    ctor public SocketHttpClientConnection();
+    method protected void assertNotOpen();
+    method protected void assertOpen();
+    method protected void bind(java.net.Socket, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public void close() throws java.io.IOException;
+    method protected org.apache.http.io.SessionInputBuffer createSessionInputBuffer(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method protected org.apache.http.io.SessionOutputBuffer createSessionOutputBuffer(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public java.net.InetAddress getLocalAddress();
+    method public int getLocalPort();
+    method public java.net.InetAddress getRemoteAddress();
+    method public int getRemotePort();
+    method protected java.net.Socket getSocket();
+    method public int getSocketTimeout();
+    method public boolean isOpen();
+    method public void setSocketTimeout(int);
+    method public void shutdown() throws java.io.IOException;
+  }
+
+  public class SocketHttpServerConnection extends org.apache.http.impl.AbstractHttpServerConnection implements org.apache.http.HttpInetConnection {
+    ctor public SocketHttpServerConnection();
+    method protected void assertNotOpen();
+    method protected void assertOpen();
+    method protected void bind(java.net.Socket, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public void close() throws java.io.IOException;
+    method protected org.apache.http.io.SessionInputBuffer createHttpDataReceiver(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method protected org.apache.http.io.SessionOutputBuffer createHttpDataTransmitter(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public java.net.InetAddress getLocalAddress();
+    method public int getLocalPort();
+    method public java.net.InetAddress getRemoteAddress();
+    method public int getRemotePort();
+    method protected java.net.Socket getSocket();
+    method public int getSocketTimeout();
+    method public boolean isOpen();
+    method public void setSocketTimeout(int);
+    method public void shutdown() throws java.io.IOException;
+  }
+
+}
+
+package org.apache.http.impl.auth {
+
+  public abstract class AuthSchemeBase implements org.apache.http.auth.AuthScheme {
+    ctor public AuthSchemeBase();
+    method public boolean isProxy();
+    method protected abstract void parseChallenge(org.apache.http.util.CharArrayBuffer, int, int) throws org.apache.http.auth.MalformedChallengeException;
+    method public void processChallenge(org.apache.http.Header) throws org.apache.http.auth.MalformedChallengeException;
+  }
+
+  public class BasicScheme extends org.apache.http.impl.auth.RFC2617Scheme {
+    ctor public BasicScheme();
+    method public org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException;
+    method public static org.apache.http.Header authenticate(org.apache.http.auth.Credentials, java.lang.String, boolean);
+    method public java.lang.String getSchemeName();
+    method public boolean isComplete();
+    method public boolean isConnectionBased();
+  }
+
+  public class BasicSchemeFactory implements org.apache.http.auth.AuthSchemeFactory {
+    ctor public BasicSchemeFactory();
+    method public org.apache.http.auth.AuthScheme newInstance(org.apache.http.params.HttpParams);
+  }
+
+  public class DigestScheme extends org.apache.http.impl.auth.RFC2617Scheme {
+    ctor public DigestScheme();
+    method public org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException;
+    method public static java.lang.String createCnonce();
+    method public java.lang.String getSchemeName();
+    method public boolean isComplete();
+    method public boolean isConnectionBased();
+    method public void overrideParamter(java.lang.String, java.lang.String);
+  }
+
+  public class DigestSchemeFactory implements org.apache.http.auth.AuthSchemeFactory {
+    ctor public DigestSchemeFactory();
+    method public org.apache.http.auth.AuthScheme newInstance(org.apache.http.params.HttpParams);
+  }
+
+  public abstract interface NTLMEngine {
+    method public abstract java.lang.String generateType1Msg(java.lang.String, java.lang.String) throws org.apache.http.impl.auth.NTLMEngineException;
+    method public abstract java.lang.String generateType3Msg(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws org.apache.http.impl.auth.NTLMEngineException;
+  }
+
+  public class NTLMEngineException extends org.apache.http.auth.AuthenticationException {
+    ctor public NTLMEngineException();
+    ctor public NTLMEngineException(java.lang.String);
+    ctor public NTLMEngineException(java.lang.String, java.lang.Throwable);
+  }
+
+  public class NTLMScheme extends org.apache.http.impl.auth.AuthSchemeBase {
+    ctor public NTLMScheme(org.apache.http.impl.auth.NTLMEngine);
+    method public org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException;
+    method public java.lang.String getParameter(java.lang.String);
+    method public java.lang.String getRealm();
+    method public java.lang.String getSchemeName();
+    method public boolean isComplete();
+    method public boolean isConnectionBased();
+    method protected void parseChallenge(org.apache.http.util.CharArrayBuffer, int, int) throws org.apache.http.auth.MalformedChallengeException;
+  }
+
+  public abstract class RFC2617Scheme extends org.apache.http.impl.auth.AuthSchemeBase {
+    ctor public RFC2617Scheme();
+    method public java.lang.String getParameter(java.lang.String);
+    method protected java.util.Map<java.lang.String, java.lang.String> getParameters();
+    method public java.lang.String getRealm();
+    method protected void parseChallenge(org.apache.http.util.CharArrayBuffer, int, int) throws org.apache.http.auth.MalformedChallengeException;
+  }
+
+  public class UnsupportedDigestAlgorithmException extends java.lang.RuntimeException {
+    ctor public UnsupportedDigestAlgorithmException();
+    ctor public UnsupportedDigestAlgorithmException(java.lang.String);
+    ctor public UnsupportedDigestAlgorithmException(java.lang.String, java.lang.Throwable);
+  }
+
+}
+
+package org.apache.http.impl.client {
+
+  public abstract class AbstractAuthenticationHandler implements org.apache.http.client.AuthenticationHandler {
+    ctor public AbstractAuthenticationHandler();
+    method protected java.util.List<java.lang.String> getAuthPreferences();
+    method protected java.util.Map<java.lang.String, org.apache.http.Header> parseChallenges(org.apache.http.Header[]) throws org.apache.http.auth.MalformedChallengeException;
+    method public org.apache.http.auth.AuthScheme selectScheme(java.util.Map<java.lang.String, org.apache.http.Header>, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.AuthenticationException;
+  }
+
+  public abstract class AbstractHttpClient implements org.apache.http.client.HttpClient {
+    ctor protected AbstractHttpClient(org.apache.http.conn.ClientConnectionManager, org.apache.http.params.HttpParams);
+    method public synchronized void addRequestInterceptor(org.apache.http.HttpRequestInterceptor);
+    method public synchronized void addRequestInterceptor(org.apache.http.HttpRequestInterceptor, int);
+    method public synchronized void addResponseInterceptor(org.apache.http.HttpResponseInterceptor);
+    method public synchronized void addResponseInterceptor(org.apache.http.HttpResponseInterceptor, int);
+    method public synchronized void clearRequestInterceptors();
+    method public synchronized void clearResponseInterceptors();
+    method protected abstract org.apache.http.auth.AuthSchemeRegistry createAuthSchemeRegistry();
+    method protected abstract org.apache.http.conn.ClientConnectionManager createClientConnectionManager();
+    method protected org.apache.http.client.RequestDirector createClientRequestDirector(org.apache.http.protocol.HttpRequestExecutor, org.apache.http.conn.ClientConnectionManager, org.apache.http.ConnectionReuseStrategy, org.apache.http.conn.ConnectionKeepAliveStrategy, org.apache.http.conn.routing.HttpRoutePlanner, org.apache.http.protocol.HttpProcessor, org.apache.http.client.HttpRequestRetryHandler, org.apache.http.client.RedirectHandler, org.apache.http.client.AuthenticationHandler, org.apache.http.client.AuthenticationHandler, org.apache.http.client.UserTokenHandler, org.apache.http.params.HttpParams);
+    method protected abstract org.apache.http.conn.ConnectionKeepAliveStrategy createConnectionKeepAliveStrategy();
+    method protected abstract org.apache.http.ConnectionReuseStrategy createConnectionReuseStrategy();
+    method protected abstract org.apache.http.cookie.CookieSpecRegistry createCookieSpecRegistry();
+    method protected abstract org.apache.http.client.CookieStore createCookieStore();
+    method protected abstract org.apache.http.client.CredentialsProvider createCredentialsProvider();
+    method protected abstract org.apache.http.protocol.HttpContext createHttpContext();
+    method protected abstract org.apache.http.params.HttpParams createHttpParams();
+    method protected abstract org.apache.http.protocol.BasicHttpProcessor createHttpProcessor();
+    method protected abstract org.apache.http.client.HttpRequestRetryHandler createHttpRequestRetryHandler();
+    method protected abstract org.apache.http.conn.routing.HttpRoutePlanner createHttpRoutePlanner();
+    method protected abstract org.apache.http.client.AuthenticationHandler createProxyAuthenticationHandler();
+    method protected abstract org.apache.http.client.RedirectHandler createRedirectHandler();
+    method protected abstract org.apache.http.protocol.HttpRequestExecutor createRequestExecutor();
+    method protected abstract org.apache.http.client.AuthenticationHandler createTargetAuthenticationHandler();
+    method protected abstract org.apache.http.client.UserTokenHandler createUserTokenHandler();
+    method protected org.apache.http.params.HttpParams determineParams(org.apache.http.HttpRequest);
+    method public final org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public final org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public final org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public final org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
+    method public final synchronized org.apache.http.auth.AuthSchemeRegistry getAuthSchemes();
+    method public final synchronized org.apache.http.conn.ConnectionKeepAliveStrategy getConnectionKeepAliveStrategy();
+    method public final synchronized org.apache.http.conn.ClientConnectionManager getConnectionManager();
+    method public final synchronized org.apache.http.ConnectionReuseStrategy getConnectionReuseStrategy();
+    method public final synchronized org.apache.http.cookie.CookieSpecRegistry getCookieSpecs();
+    method public final synchronized org.apache.http.client.CookieStore getCookieStore();
+    method public final synchronized org.apache.http.client.CredentialsProvider getCredentialsProvider();
+    method protected final synchronized org.apache.http.protocol.BasicHttpProcessor getHttpProcessor();
+    method public final synchronized org.apache.http.client.HttpRequestRetryHandler getHttpRequestRetryHandler();
+    method public final synchronized org.apache.http.params.HttpParams getParams();
+    method public final synchronized org.apache.http.client.AuthenticationHandler getProxyAuthenticationHandler();
+    method public final synchronized org.apache.http.client.RedirectHandler getRedirectHandler();
+    method public final synchronized org.apache.http.protocol.HttpRequestExecutor getRequestExecutor();
+    method public synchronized org.apache.http.HttpRequestInterceptor getRequestInterceptor(int);
+    method public synchronized int getRequestInterceptorCount();
+    method public synchronized org.apache.http.HttpResponseInterceptor getResponseInterceptor(int);
+    method public synchronized int getResponseInterceptorCount();
+    method public final synchronized org.apache.http.conn.routing.HttpRoutePlanner getRoutePlanner();
+    method public final synchronized org.apache.http.client.AuthenticationHandler getTargetAuthenticationHandler();
+    method public final synchronized org.apache.http.client.UserTokenHandler getUserTokenHandler();
+    method public void removeRequestInterceptorByClass(java.lang.Class<? extends org.apache.http.HttpRequestInterceptor>);
+    method public void removeResponseInterceptorByClass(java.lang.Class<? extends org.apache.http.HttpResponseInterceptor>);
+    method public synchronized void setAuthSchemes(org.apache.http.auth.AuthSchemeRegistry);
+    method public synchronized void setCookieSpecs(org.apache.http.cookie.CookieSpecRegistry);
+    method public synchronized void setCookieStore(org.apache.http.client.CookieStore);
+    method public synchronized void setCredentialsProvider(org.apache.http.client.CredentialsProvider);
+    method public synchronized void setHttpRequestRetryHandler(org.apache.http.client.HttpRequestRetryHandler);
+    method public synchronized void setKeepAliveStrategy(org.apache.http.conn.ConnectionKeepAliveStrategy);
+    method public synchronized void setParams(org.apache.http.params.HttpParams);
+    method public synchronized void setProxyAuthenticationHandler(org.apache.http.client.AuthenticationHandler);
+    method public synchronized void setRedirectHandler(org.apache.http.client.RedirectHandler);
+    method public synchronized void setReuseStrategy(org.apache.http.ConnectionReuseStrategy);
+    method public synchronized void setRoutePlanner(org.apache.http.conn.routing.HttpRoutePlanner);
+    method public synchronized void setTargetAuthenticationHandler(org.apache.http.client.AuthenticationHandler);
+    method public synchronized void setUserTokenHandler(org.apache.http.client.UserTokenHandler);
+  }
+
+  public class BasicCookieStore implements org.apache.http.client.CookieStore {
+    ctor public BasicCookieStore();
+    method public synchronized void addCookie(org.apache.http.cookie.Cookie);
+    method public synchronized void addCookies(org.apache.http.cookie.Cookie[]);
+    method public synchronized void clear();
+    method public synchronized boolean clearExpired(java.util.Date);
+    method public synchronized java.util.List<org.apache.http.cookie.Cookie> getCookies();
+  }
+
+  public class BasicCredentialsProvider implements org.apache.http.client.CredentialsProvider {
+    ctor public BasicCredentialsProvider();
+    method public synchronized void clear();
+    method public synchronized org.apache.http.auth.Credentials getCredentials(org.apache.http.auth.AuthScope);
+    method public synchronized void setCredentials(org.apache.http.auth.AuthScope, org.apache.http.auth.Credentials);
+  }
+
+  public class BasicResponseHandler implements org.apache.http.client.ResponseHandler {
+    ctor public BasicResponseHandler();
+    method public java.lang.String handleResponse(org.apache.http.HttpResponse) throws org.apache.http.client.HttpResponseException, java.io.IOException;
+  }
+
+  public class ClientParamsStack extends org.apache.http.params.AbstractHttpParams {
+    ctor public ClientParamsStack(org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams);
+    ctor public ClientParamsStack(org.apache.http.impl.client.ClientParamsStack);
+    ctor public ClientParamsStack(org.apache.http.impl.client.ClientParamsStack, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams);
+    method public org.apache.http.params.HttpParams copy();
+    method public final org.apache.http.params.HttpParams getApplicationParams();
+    method public final org.apache.http.params.HttpParams getClientParams();
+    method public final org.apache.http.params.HttpParams getOverrideParams();
+    method public java.lang.Object getParameter(java.lang.String);
+    method public final org.apache.http.params.HttpParams getRequestParams();
+    method public boolean removeParameter(java.lang.String);
+    method public org.apache.http.params.HttpParams setParameter(java.lang.String, java.lang.Object) throws java.lang.UnsupportedOperationException;
+    field protected final org.apache.http.params.HttpParams applicationParams;
+    field protected final org.apache.http.params.HttpParams clientParams;
+    field protected final org.apache.http.params.HttpParams overrideParams;
+    field protected final org.apache.http.params.HttpParams requestParams;
+  }
+
+  public class DefaultConnectionKeepAliveStrategy implements org.apache.http.conn.ConnectionKeepAliveStrategy {
+    ctor public DefaultConnectionKeepAliveStrategy();
+    method public long getKeepAliveDuration(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
+  }
+
+  public class DefaultHttpClient extends org.apache.http.impl.client.AbstractHttpClient {
+    ctor public DefaultHttpClient(org.apache.http.conn.ClientConnectionManager, org.apache.http.params.HttpParams);
+    ctor public DefaultHttpClient(org.apache.http.params.HttpParams);
+    ctor public DefaultHttpClient();
+    method protected org.apache.http.auth.AuthSchemeRegistry createAuthSchemeRegistry();
+    method protected org.apache.http.conn.ClientConnectionManager createClientConnectionManager();
+    method protected org.apache.http.conn.ConnectionKeepAliveStrategy createConnectionKeepAliveStrategy();
+    method protected org.apache.http.ConnectionReuseStrategy createConnectionReuseStrategy();
+    method protected org.apache.http.cookie.CookieSpecRegistry createCookieSpecRegistry();
+    method protected org.apache.http.client.CookieStore createCookieStore();
+    method protected org.apache.http.client.CredentialsProvider createCredentialsProvider();
+    method protected org.apache.http.protocol.HttpContext createHttpContext();
+    method protected org.apache.http.params.HttpParams createHttpParams();
+    method protected org.apache.http.protocol.BasicHttpProcessor createHttpProcessor();
+    method protected org.apache.http.client.HttpRequestRetryHandler createHttpRequestRetryHandler();
+    method protected org.apache.http.conn.routing.HttpRoutePlanner createHttpRoutePlanner();
+    method protected org.apache.http.client.AuthenticationHandler createProxyAuthenticationHandler();
+    method protected org.apache.http.client.RedirectHandler createRedirectHandler();
+    method protected org.apache.http.protocol.HttpRequestExecutor createRequestExecutor();
+    method protected org.apache.http.client.AuthenticationHandler createTargetAuthenticationHandler();
+    method protected org.apache.http.client.UserTokenHandler createUserTokenHandler();
+  }
+
+  public class DefaultHttpRequestRetryHandler implements org.apache.http.client.HttpRequestRetryHandler {
+    ctor public DefaultHttpRequestRetryHandler(int, boolean);
+    ctor public DefaultHttpRequestRetryHandler();
+    method public int getRetryCount();
+    method public boolean isRequestSentRetryEnabled();
+    method public boolean retryRequest(java.io.IOException, int, org.apache.http.protocol.HttpContext);
+  }
+
+  public class DefaultProxyAuthenticationHandler extends org.apache.http.impl.client.AbstractAuthenticationHandler {
+    ctor public DefaultProxyAuthenticationHandler();
+    method public java.util.Map<java.lang.String, org.apache.http.Header> getChallenges(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.MalformedChallengeException;
+    method public boolean isAuthenticationRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
+  }
+
+  public class DefaultRedirectHandler implements org.apache.http.client.RedirectHandler {
+    ctor public DefaultRedirectHandler();
+    method public java.net.URI getLocationURI(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.ProtocolException;
+    method public boolean isRedirectRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
+  }
+
+  public class DefaultRequestDirector implements org.apache.http.client.RequestDirector {
+    ctor public DefaultRequestDirector(org.apache.http.protocol.HttpRequestExecutor, org.apache.http.conn.ClientConnectionManager, org.apache.http.ConnectionReuseStrategy, org.apache.http.conn.ConnectionKeepAliveStrategy, org.apache.http.conn.routing.HttpRoutePlanner, org.apache.http.protocol.HttpProcessor, org.apache.http.client.HttpRequestRetryHandler, org.apache.http.client.RedirectHandler, org.apache.http.client.AuthenticationHandler, org.apache.http.client.AuthenticationHandler, org.apache.http.client.UserTokenHandler, org.apache.http.params.HttpParams);
+    method protected org.apache.http.HttpRequest createConnectRequest(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext);
+    method protected boolean createTunnelToProxy(org.apache.http.conn.routing.HttpRoute, int, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+    method protected boolean createTunnelToTarget(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+    method protected org.apache.http.conn.routing.HttpRoute determineRoute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
+    method protected void establishRoute(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+    method public org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+    method protected org.apache.http.impl.client.RoutedRequest handleResponse(org.apache.http.impl.client.RoutedRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+    method protected void releaseConnection();
+    method protected void rewriteRequestURI(org.apache.http.impl.client.RequestWrapper, org.apache.http.conn.routing.HttpRoute) throws org.apache.http.ProtocolException;
+    field protected final org.apache.http.conn.ClientConnectionManager connManager;
+    field protected final org.apache.http.protocol.HttpProcessor httpProcessor;
+    field protected final org.apache.http.conn.ConnectionKeepAliveStrategy keepAliveStrategy;
+    field protected org.apache.http.conn.ManagedClientConnection managedConn;
+    field protected final org.apache.http.params.HttpParams params;
+    field protected final org.apache.http.client.RedirectHandler redirectHandler;
+    field protected final org.apache.http.protocol.HttpRequestExecutor requestExec;
+    field protected final org.apache.http.client.HttpRequestRetryHandler retryHandler;
+    field protected final org.apache.http.ConnectionReuseStrategy reuseStrategy;
+    field protected final org.apache.http.conn.routing.HttpRoutePlanner routePlanner;
+  }
+
+  public class DefaultTargetAuthenticationHandler extends org.apache.http.impl.client.AbstractAuthenticationHandler {
+    ctor public DefaultTargetAuthenticationHandler();
+    method public java.util.Map<java.lang.String, org.apache.http.Header> getChallenges(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.MalformedChallengeException;
+    method public boolean isAuthenticationRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
+  }
+
+  public class DefaultUserTokenHandler implements org.apache.http.client.UserTokenHandler {
+    ctor public DefaultUserTokenHandler();
+    method public java.lang.Object getUserToken(org.apache.http.protocol.HttpContext);
+  }
+
+  public class EntityEnclosingRequestWrapper extends org.apache.http.impl.client.RequestWrapper implements org.apache.http.HttpEntityEnclosingRequest {
+    ctor public EntityEnclosingRequestWrapper(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.ProtocolException;
+    method public boolean expectContinue();
+    method public org.apache.http.HttpEntity getEntity();
+    method public void setEntity(org.apache.http.HttpEntity);
+  }
+
+  public class RedirectLocations {
+    ctor public RedirectLocations();
+    method public void add(java.net.URI);
+    method public boolean contains(java.net.URI);
+    method public boolean remove(java.net.URI);
+  }
+
+  public class RequestWrapper extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.client.methods.HttpUriRequest {
+    ctor public RequestWrapper(org.apache.http.HttpRequest) throws org.apache.http.ProtocolException;
+    method public void abort() throws java.lang.UnsupportedOperationException;
+    method public int getExecCount();
+    method public java.lang.String getMethod();
+    method public org.apache.http.HttpRequest getOriginal();
+    method public org.apache.http.ProtocolVersion getProtocolVersion();
+    method public org.apache.http.RequestLine getRequestLine();
+    method public java.net.URI getURI();
+    method public void incrementExecCount();
+    method public boolean isAborted();
+    method public boolean isRepeatable();
+    method public void resetHeaders();
+    method public void setMethod(java.lang.String);
+    method public void setProtocolVersion(org.apache.http.ProtocolVersion);
+    method public void setURI(java.net.URI);
+  }
+
+  public class RoutedRequest {
+    ctor public RoutedRequest(org.apache.http.impl.client.RequestWrapper, org.apache.http.conn.routing.HttpRoute);
+    method public final org.apache.http.impl.client.RequestWrapper getRequest();
+    method public final org.apache.http.conn.routing.HttpRoute getRoute();
+    field protected final org.apache.http.impl.client.RequestWrapper request;
+    field protected final org.apache.http.conn.routing.HttpRoute route;
+  }
+
+  public class TunnelRefusedException extends org.apache.http.HttpException {
+    ctor public TunnelRefusedException(java.lang.String, org.apache.http.HttpResponse);
+    method public org.apache.http.HttpResponse getResponse();
+  }
+
+}
+
+package org.apache.http.impl.conn {
+
+  public abstract class AbstractClientConnAdapter implements org.apache.http.conn.ManagedClientConnection {
+    ctor protected AbstractClientConnAdapter(org.apache.http.conn.ClientConnectionManager, org.apache.http.conn.OperatedClientConnection);
+    method public void abortConnection();
+    method protected final void assertNotAborted() throws java.io.InterruptedIOException;
+    method protected final void assertValid(org.apache.http.conn.OperatedClientConnection);
+    method protected void detach();
+    method public void flush() throws java.io.IOException;
+    method public java.net.InetAddress getLocalAddress();
+    method public int getLocalPort();
+    method protected org.apache.http.conn.ClientConnectionManager getManager();
+    method public org.apache.http.HttpConnectionMetrics getMetrics();
+    method public java.net.InetAddress getRemoteAddress();
+    method public int getRemotePort();
+    method public javax.net.ssl.SSLSession getSSLSession();
+    method public int getSocketTimeout();
+    method protected org.apache.http.conn.OperatedClientConnection getWrappedConnection();
+    method public boolean isMarkedReusable();
+    method public boolean isOpen();
+    method public boolean isResponseAvailable(int) throws java.io.IOException;
+    method public boolean isSecure();
+    method public boolean isStale();
+    method public void markReusable();
+    method public void receiveResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
+    method public org.apache.http.HttpResponse receiveResponseHeader() throws org.apache.http.HttpException, java.io.IOException;
+    method public void releaseConnection();
+    method public void sendRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException;
+    method public void sendRequestHeader(org.apache.http.HttpRequest) throws org.apache.http.HttpException, java.io.IOException;
+    method public void setIdleDuration(long, java.util.concurrent.TimeUnit);
+    method public void setSocketTimeout(int);
+    method public void unmarkReusable();
+  }
+
+  public abstract class AbstractPoolEntry {
+    ctor protected AbstractPoolEntry(org.apache.http.conn.ClientConnectionOperator, org.apache.http.conn.routing.HttpRoute);
+    method public java.lang.Object getState();
+    method public void layerProtocol(org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public void open(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public void setState(java.lang.Object);
+    method protected void shutdownEntry();
+    method public void tunnelProxy(org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public void tunnelTarget(boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
+    field protected final org.apache.http.conn.ClientConnectionOperator connOperator;
+    field protected final org.apache.http.conn.OperatedClientConnection connection;
+    field protected volatile org.apache.http.conn.routing.HttpRoute route;
+    field protected volatile java.lang.Object state;
+    field protected volatile org.apache.http.conn.routing.RouteTracker tracker;
+  }
+
+  public abstract class AbstractPooledConnAdapter extends org.apache.http.impl.conn.AbstractClientConnAdapter {
+    ctor protected AbstractPooledConnAdapter(org.apache.http.conn.ClientConnectionManager, org.apache.http.impl.conn.AbstractPoolEntry);
+    method protected final void assertAttached();
+    method public void close() throws java.io.IOException;
+    method public org.apache.http.conn.routing.HttpRoute getRoute();
+    method public java.lang.Object getState();
+    method public void layerProtocol(org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public void open(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public void setState(java.lang.Object);
+    method public void shutdown() throws java.io.IOException;
+    method public void tunnelProxy(org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public void tunnelTarget(boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
+    field protected volatile org.apache.http.impl.conn.AbstractPoolEntry poolEntry;
+  }
+
+  public class DefaultClientConnection extends org.apache.http.impl.SocketHttpClientConnection implements org.apache.http.conn.OperatedClientConnection {
+    ctor public DefaultClientConnection();
+    method public final java.net.Socket getSocket();
+    method public final org.apache.http.HttpHost getTargetHost();
+    method public final boolean isSecure();
+    method public void openCompleted(boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public void opening(java.net.Socket, org.apache.http.HttpHost) throws java.io.IOException;
+    method public void update(java.net.Socket, org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
+  }
+
+  public class DefaultClientConnectionOperator implements org.apache.http.conn.ClientConnectionOperator {
+    ctor public DefaultClientConnectionOperator(org.apache.http.conn.scheme.SchemeRegistry);
+    method public org.apache.http.conn.OperatedClientConnection createConnection();
+    method public void openConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method protected void prepareSocket(java.net.Socket, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public void updateSecureConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
+    field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
+  }
+
+  public class DefaultHttpRoutePlanner implements org.apache.http.conn.routing.HttpRoutePlanner {
+    ctor public DefaultHttpRoutePlanner(org.apache.http.conn.scheme.SchemeRegistry);
+    method public org.apache.http.conn.routing.HttpRoute determineRoute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
+    field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
+  }
+
+  public class DefaultResponseParser extends org.apache.http.impl.io.AbstractMessageParser {
+    ctor public DefaultResponseParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.HttpResponseFactory, org.apache.http.params.HttpParams);
+    method protected org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class IdleConnectionHandler {
+    ctor public IdleConnectionHandler();
+    method public void add(org.apache.http.HttpConnection, long, java.util.concurrent.TimeUnit);
+    method public void closeExpiredConnections();
+    method public void closeIdleConnections(long);
+    method public boolean remove(org.apache.http.HttpConnection);
+    method public void removeAll();
+  }
+
+  public class LoggingSessionInputBuffer implements org.apache.http.io.SessionInputBuffer {
+    ctor public LoggingSessionInputBuffer(org.apache.http.io.SessionInputBuffer, org.apache.http.impl.conn.Wire);
+    method public org.apache.http.io.HttpTransportMetrics getMetrics();
+    method public boolean isDataAvailable(int) throws java.io.IOException;
+    method public int read(byte[], int, int) throws java.io.IOException;
+    method public int read() throws java.io.IOException;
+    method public int read(byte[]) throws java.io.IOException;
+    method public java.lang.String readLine() throws java.io.IOException;
+    method public int readLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
+  }
+
+  public class LoggingSessionOutputBuffer implements org.apache.http.io.SessionOutputBuffer {
+    ctor public LoggingSessionOutputBuffer(org.apache.http.io.SessionOutputBuffer, org.apache.http.impl.conn.Wire);
+    method public void flush() throws java.io.IOException;
+    method public org.apache.http.io.HttpTransportMetrics getMetrics();
+    method public void write(byte[], int, int) throws java.io.IOException;
+    method public void write(int) throws java.io.IOException;
+    method public void write(byte[]) throws java.io.IOException;
+    method public void writeLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
+    method public void writeLine(java.lang.String) throws java.io.IOException;
+  }
+
+  public class ProxySelectorRoutePlanner implements org.apache.http.conn.routing.HttpRoutePlanner {
+    ctor public ProxySelectorRoutePlanner(org.apache.http.conn.scheme.SchemeRegistry, java.net.ProxySelector);
+    method protected java.net.Proxy chooseProxy(java.util.List<java.net.Proxy>, org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext);
+    method protected org.apache.http.HttpHost determineProxy(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
+    method public org.apache.http.conn.routing.HttpRoute determineRoute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
+    method protected java.lang.String getHost(java.net.InetSocketAddress);
+    method public java.net.ProxySelector getProxySelector();
+    method public void setProxySelector(java.net.ProxySelector);
+    field protected java.net.ProxySelector proxySelector;
+    field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
+  }
+
+  public class SingleClientConnManager implements org.apache.http.conn.ClientConnectionManager {
+    ctor public SingleClientConnManager(org.apache.http.params.HttpParams, org.apache.http.conn.scheme.SchemeRegistry);
+    method protected final void assertStillUp() throws java.lang.IllegalStateException;
+    method public void closeExpiredConnections();
+    method public void closeIdleConnections(long, java.util.concurrent.TimeUnit);
+    method protected org.apache.http.conn.ClientConnectionOperator createConnectionOperator(org.apache.http.conn.scheme.SchemeRegistry);
+    method public org.apache.http.conn.ManagedClientConnection getConnection(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
+    method public org.apache.http.conn.scheme.SchemeRegistry getSchemeRegistry();
+    method public void releaseConnection(org.apache.http.conn.ManagedClientConnection, long, java.util.concurrent.TimeUnit);
+    method public final org.apache.http.conn.ClientConnectionRequest requestConnection(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
+    method protected void revokeConnection();
+    method public void shutdown();
+    field public static final java.lang.String MISUSE_MESSAGE = "Invalid use of SingleClientConnManager: connection still allocated.\nMake sure to release the connection before allocating another one.";
+    field protected boolean alwaysShutDown;
+    field protected org.apache.http.conn.ClientConnectionOperator connOperator;
+    field protected long connectionExpiresTime;
+    field protected volatile boolean isShutDown;
+    field protected long lastReleaseTime;
+    field protected org.apache.http.impl.conn.SingleClientConnManager.ConnAdapter managedConn;
+    field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
+    field protected org.apache.http.impl.conn.SingleClientConnManager.PoolEntry uniquePoolEntry;
+  }
+
+  protected class SingleClientConnManager.ConnAdapter extends org.apache.http.impl.conn.AbstractPooledConnAdapter {
+    ctor protected SingleClientConnManager.ConnAdapter(org.apache.http.impl.conn.SingleClientConnManager.PoolEntry, org.apache.http.conn.routing.HttpRoute);
+  }
+
+  protected class SingleClientConnManager.PoolEntry extends org.apache.http.impl.conn.AbstractPoolEntry {
+    ctor protected SingleClientConnManager.PoolEntry();
+    method protected void close() throws java.io.IOException;
+    method protected void shutdown() throws java.io.IOException;
+  }
+
+  public class Wire {
+    ctor public Wire(org.apache.commons.logging.Log);
+    method public boolean enabled();
+    method public void input(java.io.InputStream) throws java.io.IOException;
+    method public void input(byte[], int, int) throws java.io.IOException;
+    method public void input(byte[]) throws java.io.IOException;
+    method public void input(int) throws java.io.IOException;
+    method public void input(java.lang.String) throws java.io.IOException;
+    method public void output(java.io.InputStream) throws java.io.IOException;
+    method public void output(byte[], int, int) throws java.io.IOException;
+    method public void output(byte[]) throws java.io.IOException;
+    method public void output(int) throws java.io.IOException;
+    method public void output(java.lang.String) throws java.io.IOException;
+  }
+
+}
+
+package org.apache.http.impl.conn.tsccm {
+
+  public abstract class AbstractConnPool implements org.apache.http.impl.conn.tsccm.RefQueueHandler {
+    ctor protected AbstractConnPool();
+    method protected void closeConnection(org.apache.http.conn.OperatedClientConnection);
+    method public void closeExpiredConnections();
+    method public void closeIdleConnections(long, java.util.concurrent.TimeUnit);
+    method public abstract void deleteClosedConnections();
+    method public void enableConnectionGC() throws java.lang.IllegalStateException;
+    method public abstract void freeEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry, boolean, long, java.util.concurrent.TimeUnit);
+    method public final org.apache.http.impl.conn.tsccm.BasicPoolEntry getEntry(org.apache.http.conn.routing.HttpRoute, java.lang.Object, long, java.util.concurrent.TimeUnit) throws org.apache.http.conn.ConnectionPoolTimeoutException, java.lang.InterruptedException;
+    method protected abstract void handleLostEntry(org.apache.http.conn.routing.HttpRoute);
+    method public void handleReference(java.lang.ref.Reference);
+    method public abstract org.apache.http.impl.conn.tsccm.PoolEntryRequest requestPoolEntry(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
+    method public void shutdown();
+    field protected org.apache.http.impl.conn.IdleConnectionHandler idleConnHandler;
+    field protected volatile boolean isShutDown;
+    field protected java.util.Set issuedConnections;
+    field protected int numConnections;
+    field protected final java.util.concurrent.locks.Lock poolLock;
+    field protected java.lang.ref.ReferenceQueue refQueue;
+  }
+
+  public class BasicPoolEntry extends org.apache.http.impl.conn.AbstractPoolEntry {
+    ctor public BasicPoolEntry(org.apache.http.conn.ClientConnectionOperator, org.apache.http.conn.routing.HttpRoute, java.lang.ref.ReferenceQueue<java.lang.Object>);
+    method protected final org.apache.http.conn.OperatedClientConnection getConnection();
+    method protected final org.apache.http.conn.routing.HttpRoute getPlannedRoute();
+    method protected final org.apache.http.impl.conn.tsccm.BasicPoolEntryRef getWeakRef();
+  }
+
+  public class BasicPoolEntryRef extends java.lang.ref.WeakReference {
+    ctor public BasicPoolEntryRef(org.apache.http.impl.conn.tsccm.BasicPoolEntry, java.lang.ref.ReferenceQueue<java.lang.Object>);
+    method public final org.apache.http.conn.routing.HttpRoute getRoute();
+  }
+
+  public class BasicPooledConnAdapter extends org.apache.http.impl.conn.AbstractPooledConnAdapter {
+    ctor protected BasicPooledConnAdapter(org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager, org.apache.http.impl.conn.AbstractPoolEntry);
+    method protected org.apache.http.impl.conn.AbstractPoolEntry getPoolEntry();
+  }
+
+  public class ConnPoolByRoute extends org.apache.http.impl.conn.tsccm.AbstractConnPool {
+    ctor public ConnPoolByRoute(org.apache.http.conn.ClientConnectionOperator, org.apache.http.params.HttpParams);
+    method protected org.apache.http.impl.conn.tsccm.BasicPoolEntry createEntry(org.apache.http.impl.conn.tsccm.RouteSpecificPool, org.apache.http.conn.ClientConnectionOperator);
+    method protected java.util.Queue<org.apache.http.impl.conn.tsccm.BasicPoolEntry> createFreeConnQueue();
+    method protected java.util.Map<org.apache.http.conn.routing.HttpRoute, org.apache.http.impl.conn.tsccm.RouteSpecificPool> createRouteToPoolMap();
+    method protected java.util.Queue<org.apache.http.impl.conn.tsccm.WaitingThread> createWaitingThreadQueue();
+    method public void deleteClosedConnections();
+    method protected void deleteEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry);
+    method protected void deleteLeastUsedEntry();
+    method public void freeEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry, boolean, long, java.util.concurrent.TimeUnit);
+    method public int getConnectionsInPool(org.apache.http.conn.routing.HttpRoute);
+    method protected org.apache.http.impl.conn.tsccm.BasicPoolEntry getEntryBlocking(org.apache.http.conn.routing.HttpRoute, java.lang.Object, long, java.util.concurrent.TimeUnit, org.apache.http.impl.conn.tsccm.WaitingThreadAborter) throws org.apache.http.conn.ConnectionPoolTimeoutException, java.lang.InterruptedException;
+    method protected org.apache.http.impl.conn.tsccm.BasicPoolEntry getFreeEntry(org.apache.http.impl.conn.tsccm.RouteSpecificPool, java.lang.Object);
+    method protected org.apache.http.impl.conn.tsccm.RouteSpecificPool getRoutePool(org.apache.http.conn.routing.HttpRoute, boolean);
+    method protected void handleLostEntry(org.apache.http.conn.routing.HttpRoute);
+    method protected org.apache.http.impl.conn.tsccm.RouteSpecificPool newRouteSpecificPool(org.apache.http.conn.routing.HttpRoute);
+    method protected org.apache.http.impl.conn.tsccm.WaitingThread newWaitingThread(java.util.concurrent.locks.Condition, org.apache.http.impl.conn.tsccm.RouteSpecificPool);
+    method protected void notifyWaitingThread(org.apache.http.impl.conn.tsccm.RouteSpecificPool);
+    method public org.apache.http.impl.conn.tsccm.PoolEntryRequest requestPoolEntry(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
+    field protected java.util.Queue freeConnections;
+    field protected final int maxTotalConnections;
+    field protected final org.apache.http.conn.ClientConnectionOperator operator;
+    field protected final java.util.Map routeToPool;
+    field protected java.util.Queue waitingThreads;
+  }
+
+  public abstract interface PoolEntryRequest {
+    method public abstract void abortRequest();
+    method public abstract org.apache.http.impl.conn.tsccm.BasicPoolEntry getPoolEntry(long, java.util.concurrent.TimeUnit) throws org.apache.http.conn.ConnectionPoolTimeoutException, java.lang.InterruptedException;
+  }
+
+  public abstract interface RefQueueHandler {
+    method public abstract void handleReference(java.lang.ref.Reference<?>);
+  }
+
+  public class RefQueueWorker implements java.lang.Runnable {
+    ctor public RefQueueWorker(java.lang.ref.ReferenceQueue<?>, org.apache.http.impl.conn.tsccm.RefQueueHandler);
+    method public void run();
+    method public void shutdown();
+    field protected final org.apache.http.impl.conn.tsccm.RefQueueHandler refHandler;
+    field protected final java.lang.ref.ReferenceQueue refQueue;
+    field protected volatile java.lang.Thread workerThread;
+  }
+
+  public class RouteSpecificPool {
+    ctor public RouteSpecificPool(org.apache.http.conn.routing.HttpRoute, int);
+    method public org.apache.http.impl.conn.tsccm.BasicPoolEntry allocEntry(java.lang.Object);
+    method public void createdEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry);
+    method public boolean deleteEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry);
+    method public void dropEntry();
+    method public void freeEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry);
+    method public int getCapacity();
+    method public final int getEntryCount();
+    method public final int getMaxEntries();
+    method public final org.apache.http.conn.routing.HttpRoute getRoute();
+    method public boolean hasThread();
+    method public boolean isUnused();
+    method public org.apache.http.impl.conn.tsccm.WaitingThread nextThread();
+    method public void queueThread(org.apache.http.impl.conn.tsccm.WaitingThread);
+    method public void removeThread(org.apache.http.impl.conn.tsccm.WaitingThread);
+    field protected final java.util.LinkedList freeEntries;
+    field protected final int maxEntries;
+    field protected int numEntries;
+    field protected final org.apache.http.conn.routing.HttpRoute route;
+    field protected final java.util.Queue waitingThreads;
+  }
+
+  public class ThreadSafeClientConnManager implements org.apache.http.conn.ClientConnectionManager {
+    ctor public ThreadSafeClientConnManager(org.apache.http.params.HttpParams, org.apache.http.conn.scheme.SchemeRegistry);
+    method public void closeExpiredConnections();
+    method public void closeIdleConnections(long, java.util.concurrent.TimeUnit);
+    method protected org.apache.http.conn.ClientConnectionOperator createConnectionOperator(org.apache.http.conn.scheme.SchemeRegistry);
+    method protected org.apache.http.impl.conn.tsccm.AbstractConnPool createConnectionPool(org.apache.http.params.HttpParams);
+    method public int getConnectionsInPool(org.apache.http.conn.routing.HttpRoute);
+    method public int getConnectionsInPool();
+    method public org.apache.http.conn.scheme.SchemeRegistry getSchemeRegistry();
+    method public void releaseConnection(org.apache.http.conn.ManagedClientConnection, long, java.util.concurrent.TimeUnit);
+    method public org.apache.http.conn.ClientConnectionRequest requestConnection(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
+    method public void shutdown();
+    field protected org.apache.http.conn.ClientConnectionOperator connOperator;
+    field protected final org.apache.http.impl.conn.tsccm.AbstractConnPool connectionPool;
+    field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
+  }
+
+  public class WaitingThread {
+    ctor public WaitingThread(java.util.concurrent.locks.Condition, org.apache.http.impl.conn.tsccm.RouteSpecificPool);
+    method public boolean await(java.util.Date) throws java.lang.InterruptedException;
+    method public final java.util.concurrent.locks.Condition getCondition();
+    method public final org.apache.http.impl.conn.tsccm.RouteSpecificPool getPool();
+    method public final java.lang.Thread getThread();
+    method public void interrupt();
+    method public void wakeup();
+  }
+
+  public class WaitingThreadAborter {
+    ctor public WaitingThreadAborter();
+    method public void abort();
+    method public void setWaitingThread(org.apache.http.impl.conn.tsccm.WaitingThread);
+  }
+
+}
+
+package org.apache.http.impl.cookie {
+
+  public abstract class AbstractCookieAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
+    ctor public AbstractCookieAttributeHandler();
+    method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
+    method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public abstract class AbstractCookieSpec implements org.apache.http.cookie.CookieSpec {
+    ctor public AbstractCookieSpec();
+    method protected org.apache.http.cookie.CookieAttributeHandler findAttribHandler(java.lang.String);
+    method protected org.apache.http.cookie.CookieAttributeHandler getAttribHandler(java.lang.String);
+    method protected java.util.Collection<org.apache.http.cookie.CookieAttributeHandler> getAttribHandlers();
+    method public void registerAttribHandler(java.lang.String, org.apache.http.cookie.CookieAttributeHandler);
+  }
+
+  public class BasicClientCookie implements org.apache.http.cookie.ClientCookie java.lang.Cloneable org.apache.http.cookie.SetCookie {
+    ctor public BasicClientCookie(java.lang.String, java.lang.String);
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public boolean containsAttribute(java.lang.String);
+    method public java.lang.String getAttribute(java.lang.String);
+    method public java.lang.String getComment();
+    method public java.lang.String getCommentURL();
+    method public java.lang.String getDomain();
+    method public java.util.Date getExpiryDate();
+    method public java.lang.String getName();
+    method public java.lang.String getPath();
+    method public int[] getPorts();
+    method public java.lang.String getValue();
+    method public int getVersion();
+    method public boolean isExpired(java.util.Date);
+    method public boolean isPersistent();
+    method public boolean isSecure();
+    method public void setAttribute(java.lang.String, java.lang.String);
+    method public void setComment(java.lang.String);
+    method public void setDomain(java.lang.String);
+    method public void setExpiryDate(java.util.Date);
+    method public void setPath(java.lang.String);
+    method public void setSecure(boolean);
+    method public void setValue(java.lang.String);
+    method public void setVersion(int);
+  }
+
+  public class BasicClientCookie2 extends org.apache.http.impl.cookie.BasicClientCookie implements org.apache.http.cookie.SetCookie2 {
+    ctor public BasicClientCookie2(java.lang.String, java.lang.String);
+    method public void setCommentURL(java.lang.String);
+    method public void setDiscard(boolean);
+    method public void setPorts(int[]);
+  }
+
+  public class BasicCommentHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
+    ctor public BasicCommentHandler();
+    method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public class BasicDomainHandler implements org.apache.http.cookie.CookieAttributeHandler {
+    ctor public BasicDomainHandler();
+    method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
+    method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
+    method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public class BasicExpiresHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
+    ctor public BasicExpiresHandler(java.lang.String[]);
+    method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public class BasicMaxAgeHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
+    ctor public BasicMaxAgeHandler();
+    method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public class BasicPathHandler implements org.apache.http.cookie.CookieAttributeHandler {
+    ctor public BasicPathHandler();
+    method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
+    method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
+    method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public class BasicSecureHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
+    ctor public BasicSecureHandler();
+    method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public class BestMatchSpec implements org.apache.http.cookie.CookieSpec {
+    ctor public BestMatchSpec(java.lang.String[], boolean);
+    ctor public BestMatchSpec();
+    method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
+    method public int getVersion();
+    method public org.apache.http.Header getVersionHeader();
+    method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
+    method public java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+    method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public class BestMatchSpecFactory implements org.apache.http.cookie.CookieSpecFactory {
+    ctor public BestMatchSpecFactory();
+    method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
+  }
+
+  public class BrowserCompatSpec extends org.apache.http.impl.cookie.CookieSpecBase {
+    ctor public BrowserCompatSpec(java.lang.String[]);
+    ctor public BrowserCompatSpec();
+    method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
+    method public int getVersion();
+    method public org.apache.http.Header getVersionHeader();
+    method public java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+    field protected static final java.lang.String[] DATE_PATTERNS;
+  }
+
+  public class BrowserCompatSpecFactory implements org.apache.http.cookie.CookieSpecFactory {
+    ctor public BrowserCompatSpecFactory();
+    method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
+  }
+
+  public abstract class CookieSpecBase extends org.apache.http.impl.cookie.AbstractCookieSpec {
+    ctor public CookieSpecBase();
+    method protected static java.lang.String getDefaultDomain(org.apache.http.cookie.CookieOrigin);
+    method protected static java.lang.String getDefaultPath(org.apache.http.cookie.CookieOrigin);
+    method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
+    method protected java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.HeaderElement[], org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+    method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public class DateParseException extends java.lang.Exception {
+    ctor public DateParseException();
+    ctor public DateParseException(java.lang.String);
+  }
+
+  public final class DateUtils {
+    method public static java.lang.String formatDate(java.util.Date);
+    method public static java.lang.String formatDate(java.util.Date, java.lang.String);
+    method public static java.util.Date parseDate(java.lang.String) throws org.apache.http.impl.cookie.DateParseException;
+    method public static java.util.Date parseDate(java.lang.String, java.lang.String[]) throws org.apache.http.impl.cookie.DateParseException;
+    method public static java.util.Date parseDate(java.lang.String, java.lang.String[], java.util.Date) throws org.apache.http.impl.cookie.DateParseException;
+    field public static final java.util.TimeZone GMT;
+    field public static final java.lang.String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
+    field public static final java.lang.String PATTERN_RFC1036 = "EEEE, dd-MMM-yy HH:mm:ss zzz";
+    field public static final java.lang.String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
+  }
+
+  public class NetscapeDomainHandler extends org.apache.http.impl.cookie.BasicDomainHandler {
+    ctor public NetscapeDomainHandler();
+  }
+
+  public class NetscapeDraftHeaderParser {
+    ctor public NetscapeDraftHeaderParser();
+    method public org.apache.http.HeaderElement parseHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
+    field public static final org.apache.http.impl.cookie.NetscapeDraftHeaderParser DEFAULT;
+  }
+
+  public class NetscapeDraftSpec extends org.apache.http.impl.cookie.CookieSpecBase {
+    ctor public NetscapeDraftSpec(java.lang.String[]);
+    ctor public NetscapeDraftSpec();
+    method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
+    method public int getVersion();
+    method public org.apache.http.Header getVersionHeader();
+    method public java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+    field protected static final java.lang.String EXPIRES_PATTERN = "EEE, dd-MMM-yyyy HH:mm:ss z";
+  }
+
+  public class NetscapeDraftSpecFactory implements org.apache.http.cookie.CookieSpecFactory {
+    ctor public NetscapeDraftSpecFactory();
+    method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
+  }
+
+  public class RFC2109DomainHandler implements org.apache.http.cookie.CookieAttributeHandler {
+    ctor public RFC2109DomainHandler();
+    method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
+    method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
+    method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public class RFC2109Spec extends org.apache.http.impl.cookie.CookieSpecBase {
+    ctor public RFC2109Spec(java.lang.String[], boolean);
+    ctor public RFC2109Spec();
+    method protected void formatCookieAsVer(org.apache.http.util.CharArrayBuffer, org.apache.http.cookie.Cookie, int);
+    method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
+    method protected void formatParamAsVer(org.apache.http.util.CharArrayBuffer, java.lang.String, java.lang.String, int);
+    method public int getVersion();
+    method public org.apache.http.Header getVersionHeader();
+    method public java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public class RFC2109SpecFactory implements org.apache.http.cookie.CookieSpecFactory {
+    ctor public RFC2109SpecFactory();
+    method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
+  }
+
+  public class RFC2109VersionHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
+    ctor public RFC2109VersionHandler();
+    method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public class RFC2965CommentUrlAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
+    ctor public RFC2965CommentUrlAttributeHandler();
+    method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
+    method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
+    method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public class RFC2965DiscardAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
+    ctor public RFC2965DiscardAttributeHandler();
+    method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
+    method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
+    method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public class RFC2965DomainAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
+    ctor public RFC2965DomainAttributeHandler();
+    method public boolean domainMatch(java.lang.String, java.lang.String);
+    method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
+    method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
+    method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public class RFC2965PortAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
+    ctor public RFC2965PortAttributeHandler();
+    method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
+    method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
+    method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+  public class RFC2965Spec extends org.apache.http.impl.cookie.RFC2109Spec {
+    ctor public RFC2965Spec();
+    ctor public RFC2965Spec(java.lang.String[], boolean);
+  }
+
+  public class RFC2965SpecFactory implements org.apache.http.cookie.CookieSpecFactory {
+    ctor public RFC2965SpecFactory();
+    method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
+  }
+
+  public class RFC2965VersionAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
+    ctor public RFC2965VersionAttributeHandler();
+    method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
+    method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
+    method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
+  }
+
+}
+
+package org.apache.http.impl.entity {
+
+  public class EntityDeserializer {
+    ctor public EntityDeserializer(org.apache.http.entity.ContentLengthStrategy);
+    method public org.apache.http.HttpEntity deserialize(org.apache.http.io.SessionInputBuffer, org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
+    method protected org.apache.http.entity.BasicHttpEntity doDeserialize(org.apache.http.io.SessionInputBuffer, org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class EntitySerializer {
+    ctor public EntitySerializer(org.apache.http.entity.ContentLengthStrategy);
+    method protected java.io.OutputStream doSerialize(org.apache.http.io.SessionOutputBuffer, org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
+    method public void serialize(org.apache.http.io.SessionOutputBuffer, org.apache.http.HttpMessage, org.apache.http.HttpEntity) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class LaxContentLengthStrategy implements org.apache.http.entity.ContentLengthStrategy {
+    ctor public LaxContentLengthStrategy();
+    method public long determineLength(org.apache.http.HttpMessage) throws org.apache.http.HttpException;
+  }
+
+  public class StrictContentLengthStrategy implements org.apache.http.entity.ContentLengthStrategy {
+    ctor public StrictContentLengthStrategy();
+    method public long determineLength(org.apache.http.HttpMessage) throws org.apache.http.HttpException;
+  }
+
+}
+
+package org.apache.http.impl.io {
+
+  public abstract class AbstractMessageParser implements org.apache.http.io.HttpMessageParser {
+    ctor public AbstractMessageParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.params.HttpParams);
+    method public org.apache.http.HttpMessage parse() throws org.apache.http.HttpException, java.io.IOException;
+    method protected abstract org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException, org.apache.http.ParseException;
+    method public static org.apache.http.Header[] parseHeaders(org.apache.http.io.SessionInputBuffer, int, int, org.apache.http.message.LineParser) throws org.apache.http.HttpException, java.io.IOException;
+    field protected final org.apache.http.message.LineParser lineParser;
+  }
+
+  public abstract class AbstractMessageWriter implements org.apache.http.io.HttpMessageWriter {
+    ctor public AbstractMessageWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.message.LineFormatter, org.apache.http.params.HttpParams);
+    method public void write(org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
+    method protected abstract void writeHeadLine(org.apache.http.HttpMessage) throws java.io.IOException;
+    field protected final org.apache.http.util.CharArrayBuffer lineBuf;
+    field protected final org.apache.http.message.LineFormatter lineFormatter;
+    field protected final org.apache.http.io.SessionOutputBuffer sessionBuffer;
+  }
+
+  public abstract class AbstractSessionInputBuffer implements org.apache.http.io.SessionInputBuffer {
+    ctor public AbstractSessionInputBuffer();
+    method protected int fillBuffer() throws java.io.IOException;
+    method public org.apache.http.io.HttpTransportMetrics getMetrics();
+    method protected boolean hasBufferedData();
+    method protected void init(java.io.InputStream, int, org.apache.http.params.HttpParams);
+    method public int read() throws java.io.IOException;
+    method public int read(byte[], int, int) throws java.io.IOException;
+    method public int read(byte[]) throws java.io.IOException;
+    method public int readLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
+    method public java.lang.String readLine() throws java.io.IOException;
+  }
+
+  public abstract class AbstractSessionOutputBuffer implements org.apache.http.io.SessionOutputBuffer {
+    ctor public AbstractSessionOutputBuffer();
+    method public void flush() throws java.io.IOException;
+    method protected void flushBuffer() throws java.io.IOException;
+    method public org.apache.http.io.HttpTransportMetrics getMetrics();
+    method protected void init(java.io.OutputStream, int, org.apache.http.params.HttpParams);
+    method public void write(byte[], int, int) throws java.io.IOException;
+    method public void write(byte[]) throws java.io.IOException;
+    method public void write(int) throws java.io.IOException;
+    method public void writeLine(java.lang.String) throws java.io.IOException;
+    method public void writeLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
+  }
+
+  public class ChunkedInputStream extends java.io.InputStream {
+    ctor public ChunkedInputStream(org.apache.http.io.SessionInputBuffer);
+    method public org.apache.http.Header[] getFooters();
+    method public int read() throws java.io.IOException;
+  }
+
+  public class ChunkedOutputStream extends java.io.OutputStream {
+    ctor public ChunkedOutputStream(org.apache.http.io.SessionOutputBuffer, int) throws java.io.IOException;
+    ctor public ChunkedOutputStream(org.apache.http.io.SessionOutputBuffer) throws java.io.IOException;
+    method public void finish() throws java.io.IOException;
+    method protected void flushCache() throws java.io.IOException;
+    method protected void flushCacheWithAppend(byte[], int, int) throws java.io.IOException;
+    method public void write(int) throws java.io.IOException;
+    method protected void writeClosingChunk() throws java.io.IOException;
+  }
+
+  public class ContentLengthInputStream extends java.io.InputStream {
+    ctor public ContentLengthInputStream(org.apache.http.io.SessionInputBuffer, long);
+    method public int read() throws java.io.IOException;
+  }
+
+  public class ContentLengthOutputStream extends java.io.OutputStream {
+    ctor public ContentLengthOutputStream(org.apache.http.io.SessionOutputBuffer, long);
+    method public void write(int) throws java.io.IOException;
+  }
+
+  public class HttpRequestParser extends org.apache.http.impl.io.AbstractMessageParser {
+    ctor public HttpRequestParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.HttpRequestFactory, org.apache.http.params.HttpParams);
+    method protected org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException, org.apache.http.ParseException;
+  }
+
+  public class HttpRequestWriter extends org.apache.http.impl.io.AbstractMessageWriter {
+    ctor public HttpRequestWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.message.LineFormatter, org.apache.http.params.HttpParams);
+    method protected void writeHeadLine(org.apache.http.HttpMessage) throws java.io.IOException;
+  }
+
+  public class HttpResponseParser extends org.apache.http.impl.io.AbstractMessageParser {
+    ctor public HttpResponseParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.HttpResponseFactory, org.apache.http.params.HttpParams);
+    method protected org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException, org.apache.http.ParseException;
+  }
+
+  public class HttpResponseWriter extends org.apache.http.impl.io.AbstractMessageWriter {
+    ctor public HttpResponseWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.message.LineFormatter, org.apache.http.params.HttpParams);
+    method protected void writeHeadLine(org.apache.http.HttpMessage) throws java.io.IOException;
+  }
+
+  public class HttpTransportMetricsImpl implements org.apache.http.io.HttpTransportMetrics {
+    ctor public HttpTransportMetricsImpl();
+    method public long getBytesTransferred();
+    method public void incrementBytesTransferred(long);
+    method public void reset();
+    method public void setBytesTransferred(long);
+  }
+
+  public class IdentityInputStream extends java.io.InputStream {
+    ctor public IdentityInputStream(org.apache.http.io.SessionInputBuffer);
+    method public int read() throws java.io.IOException;
+  }
+
+  public class IdentityOutputStream extends java.io.OutputStream {
+    ctor public IdentityOutputStream(org.apache.http.io.SessionOutputBuffer);
+    method public void write(int) throws java.io.IOException;
+  }
+
+  public class SocketInputBuffer extends org.apache.http.impl.io.AbstractSessionInputBuffer {
+    ctor public SocketInputBuffer(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
+    method public boolean isDataAvailable(int) throws java.io.IOException;
+  }
+
+  public class SocketOutputBuffer extends org.apache.http.impl.io.AbstractSessionOutputBuffer {
+    ctor public SocketOutputBuffer(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
+  }
+
+}
+
+package org.apache.http.io {
+
+  public abstract interface HttpMessageParser {
+    method public abstract org.apache.http.HttpMessage parse() throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public abstract interface HttpMessageWriter {
+    method public abstract void write(org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public abstract interface HttpTransportMetrics {
+    method public abstract long getBytesTransferred();
+    method public abstract void reset();
+  }
+
+  public abstract interface SessionInputBuffer {
+    method public abstract org.apache.http.io.HttpTransportMetrics getMetrics();
+    method public abstract boolean isDataAvailable(int) throws java.io.IOException;
+    method public abstract int read(byte[], int, int) throws java.io.IOException;
+    method public abstract int read(byte[]) throws java.io.IOException;
+    method public abstract int read() throws java.io.IOException;
+    method public abstract int readLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
+    method public abstract java.lang.String readLine() throws java.io.IOException;
+  }
+
+  public abstract interface SessionOutputBuffer {
+    method public abstract void flush() throws java.io.IOException;
+    method public abstract org.apache.http.io.HttpTransportMetrics getMetrics();
+    method public abstract void write(byte[], int, int) throws java.io.IOException;
+    method public abstract void write(byte[]) throws java.io.IOException;
+    method public abstract void write(int) throws java.io.IOException;
+    method public abstract void writeLine(java.lang.String) throws java.io.IOException;
+    method public abstract void writeLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
+  }
+
+}
+
+package org.apache.http.message {
+
+  public abstract class AbstractHttpMessage implements org.apache.http.HttpMessage {
+    ctor protected AbstractHttpMessage(org.apache.http.params.HttpParams);
+    ctor protected AbstractHttpMessage();
+    method public void addHeader(org.apache.http.Header);
+    method public void addHeader(java.lang.String, java.lang.String);
+    method public boolean containsHeader(java.lang.String);
+    method public org.apache.http.Header[] getAllHeaders();
+    method public org.apache.http.Header getFirstHeader(java.lang.String);
+    method public org.apache.http.Header[] getHeaders(java.lang.String);
+    method public org.apache.http.Header getLastHeader(java.lang.String);
+    method public org.apache.http.params.HttpParams getParams();
+    method public org.apache.http.HeaderIterator headerIterator();
+    method public org.apache.http.HeaderIterator headerIterator(java.lang.String);
+    method public void removeHeader(org.apache.http.Header);
+    method public void removeHeaders(java.lang.String);
+    method public void setHeader(org.apache.http.Header);
+    method public void setHeader(java.lang.String, java.lang.String);
+    method public void setHeaders(org.apache.http.Header[]);
+    method public void setParams(org.apache.http.params.HttpParams);
+    field protected org.apache.http.message.HeaderGroup headergroup;
+    field protected org.apache.http.params.HttpParams params;
+  }
+
+  public class BasicHeader implements java.lang.Cloneable org.apache.http.Header {
+    ctor public BasicHeader(java.lang.String, java.lang.String);
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public org.apache.http.HeaderElement[] getElements() throws org.apache.http.ParseException;
+    method public java.lang.String getName();
+    method public java.lang.String getValue();
+  }
+
+  public class BasicHeaderElement implements java.lang.Cloneable org.apache.http.HeaderElement {
+    ctor public BasicHeaderElement(java.lang.String, java.lang.String, org.apache.http.NameValuePair[]);
+    ctor public BasicHeaderElement(java.lang.String, java.lang.String);
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public java.lang.String getName();
+    method public org.apache.http.NameValuePair getParameter(int);
+    method public org.apache.http.NameValuePair getParameterByName(java.lang.String);
+    method public int getParameterCount();
+    method public org.apache.http.NameValuePair[] getParameters();
+    method public java.lang.String getValue();
+  }
+
+  public class BasicHeaderElementIterator implements org.apache.http.HeaderElementIterator {
+    ctor public BasicHeaderElementIterator(org.apache.http.HeaderIterator, org.apache.http.message.HeaderValueParser);
+    ctor public BasicHeaderElementIterator(org.apache.http.HeaderIterator);
+    method public boolean hasNext();
+    method public final java.lang.Object next() throws java.util.NoSuchElementException;
+    method public org.apache.http.HeaderElement nextElement() throws java.util.NoSuchElementException;
+    method public void remove() throws java.lang.UnsupportedOperationException;
+  }
+
+  public class BasicHeaderIterator implements org.apache.http.HeaderIterator {
+    ctor public BasicHeaderIterator(org.apache.http.Header[], java.lang.String);
+    method protected boolean filterHeader(int);
+    method protected int findNext(int);
+    method public boolean hasNext();
+    method public final java.lang.Object next() throws java.util.NoSuchElementException;
+    method public org.apache.http.Header nextHeader() throws java.util.NoSuchElementException;
+    method public void remove() throws java.lang.UnsupportedOperationException;
+    field protected final org.apache.http.Header[] allHeaders;
+    field protected int currentIndex;
+    field protected java.lang.String headerName;
+  }
+
+  public class BasicHeaderValueFormatter implements org.apache.http.message.HeaderValueFormatter {
+    ctor public BasicHeaderValueFormatter();
+    method protected void doFormatValue(org.apache.http.util.CharArrayBuffer, java.lang.String, boolean);
+    method protected int estimateElementsLen(org.apache.http.HeaderElement[]);
+    method protected int estimateHeaderElementLen(org.apache.http.HeaderElement);
+    method protected int estimateNameValuePairLen(org.apache.http.NameValuePair);
+    method protected int estimateParametersLen(org.apache.http.NameValuePair[]);
+    method public static final java.lang.String formatElements(org.apache.http.HeaderElement[], boolean, org.apache.http.message.HeaderValueFormatter);
+    method public org.apache.http.util.CharArrayBuffer formatElements(org.apache.http.util.CharArrayBuffer, org.apache.http.HeaderElement[], boolean);
+    method public static final java.lang.String formatHeaderElement(org.apache.http.HeaderElement, boolean, org.apache.http.message.HeaderValueFormatter);
+    method public org.apache.http.util.CharArrayBuffer formatHeaderElement(org.apache.http.util.CharArrayBuffer, org.apache.http.HeaderElement, boolean);
+    method public static final java.lang.String formatNameValuePair(org.apache.http.NameValuePair, boolean, org.apache.http.message.HeaderValueFormatter);
+    method public org.apache.http.util.CharArrayBuffer formatNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.NameValuePair, boolean);
+    method public static final java.lang.String formatParameters(org.apache.http.NameValuePair[], boolean, org.apache.http.message.HeaderValueFormatter);
+    method public org.apache.http.util.CharArrayBuffer formatParameters(org.apache.http.util.CharArrayBuffer, org.apache.http.NameValuePair[], boolean);
+    method protected boolean isSeparator(char);
+    method protected boolean isUnsafe(char);
+    field public static final org.apache.http.message.BasicHeaderValueFormatter DEFAULT;
+    field public static final java.lang.String SEPARATORS = " ;,:@()<>\\\"/[]?={}\t";
+    field public static final java.lang.String UNSAFE_CHARS = "\"\\";
+  }
+
+  public class BasicHeaderValueParser implements org.apache.http.message.HeaderValueParser {
+    ctor public BasicHeaderValueParser();
+    method protected org.apache.http.HeaderElement createHeaderElement(java.lang.String, java.lang.String, org.apache.http.NameValuePair[]);
+    method protected org.apache.http.NameValuePair createNameValuePair(java.lang.String, java.lang.String);
+    method public static final org.apache.http.HeaderElement[] parseElements(java.lang.String, org.apache.http.message.HeaderValueParser) throws org.apache.http.ParseException;
+    method public org.apache.http.HeaderElement[] parseElements(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
+    method public static final org.apache.http.HeaderElement parseHeaderElement(java.lang.String, org.apache.http.message.HeaderValueParser) throws org.apache.http.ParseException;
+    method public org.apache.http.HeaderElement parseHeaderElement(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
+    method public static final org.apache.http.NameValuePair parseNameValuePair(java.lang.String, org.apache.http.message.HeaderValueParser) throws org.apache.http.ParseException;
+    method public org.apache.http.NameValuePair parseNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
+    method public org.apache.http.NameValuePair parseNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor, char[]);
+    method public static final org.apache.http.NameValuePair[] parseParameters(java.lang.String, org.apache.http.message.HeaderValueParser) throws org.apache.http.ParseException;
+    method public org.apache.http.NameValuePair[] parseParameters(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
+    field public static final org.apache.http.message.BasicHeaderValueParser DEFAULT;
+  }
+
+  public class BasicHttpEntityEnclosingRequest extends org.apache.http.message.BasicHttpRequest implements org.apache.http.HttpEntityEnclosingRequest {
+    ctor public BasicHttpEntityEnclosingRequest(java.lang.String, java.lang.String);
+    ctor public BasicHttpEntityEnclosingRequest(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion);
+    ctor public BasicHttpEntityEnclosingRequest(org.apache.http.RequestLine);
+    method public boolean expectContinue();
+    method public org.apache.http.HttpEntity getEntity();
+    method public void setEntity(org.apache.http.HttpEntity);
+  }
+
+  public class BasicHttpRequest extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.HttpRequest {
+    ctor public BasicHttpRequest(java.lang.String, java.lang.String);
+    ctor public BasicHttpRequest(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion);
+    ctor public BasicHttpRequest(org.apache.http.RequestLine);
+    method public org.apache.http.ProtocolVersion getProtocolVersion();
+    method public org.apache.http.RequestLine getRequestLine();
+  }
+
+  public class BasicHttpResponse extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.HttpResponse {
+    ctor public BasicHttpResponse(org.apache.http.StatusLine, org.apache.http.ReasonPhraseCatalog, java.util.Locale);
+    ctor public BasicHttpResponse(org.apache.http.StatusLine);
+    ctor public BasicHttpResponse(org.apache.http.ProtocolVersion, int, java.lang.String);
+    method public org.apache.http.HttpEntity getEntity();
+    method public java.util.Locale getLocale();
+    method public org.apache.http.ProtocolVersion getProtocolVersion();
+    method protected java.lang.String getReason(int);
+    method public org.apache.http.StatusLine getStatusLine();
+    method public void setEntity(org.apache.http.HttpEntity);
+    method public void setLocale(java.util.Locale);
+    method public void setReasonPhrase(java.lang.String);
+    method public void setStatusCode(int);
+    method public void setStatusLine(org.apache.http.StatusLine);
+    method public void setStatusLine(org.apache.http.ProtocolVersion, int);
+    method public void setStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String);
+  }
+
+  public class BasicLineFormatter implements org.apache.http.message.LineFormatter {
+    ctor public BasicLineFormatter();
+    method public org.apache.http.util.CharArrayBuffer appendProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.ProtocolVersion);
+    method protected void doFormatHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.Header);
+    method protected void doFormatRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.RequestLine);
+    method protected void doFormatStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.StatusLine);
+    method protected int estimateProtocolVersionLen(org.apache.http.ProtocolVersion);
+    method public static final java.lang.String formatHeader(org.apache.http.Header, org.apache.http.message.LineFormatter);
+    method public org.apache.http.util.CharArrayBuffer formatHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.Header);
+    method public static final java.lang.String formatProtocolVersion(org.apache.http.ProtocolVersion, org.apache.http.message.LineFormatter);
+    method public static final java.lang.String formatRequestLine(org.apache.http.RequestLine, org.apache.http.message.LineFormatter);
+    method public org.apache.http.util.CharArrayBuffer formatRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.RequestLine);
+    method public static final java.lang.String formatStatusLine(org.apache.http.StatusLine, org.apache.http.message.LineFormatter);
+    method public org.apache.http.util.CharArrayBuffer formatStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.StatusLine);
+    method protected org.apache.http.util.CharArrayBuffer initBuffer(org.apache.http.util.CharArrayBuffer);
+    field public static final org.apache.http.message.BasicLineFormatter DEFAULT;
+  }
+
+  public class BasicLineParser implements org.apache.http.message.LineParser {
+    ctor public BasicLineParser(org.apache.http.ProtocolVersion);
+    ctor public BasicLineParser();
+    method protected org.apache.http.ProtocolVersion createProtocolVersion(int, int);
+    method protected org.apache.http.RequestLine createRequestLine(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion);
+    method protected org.apache.http.StatusLine createStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String);
+    method public boolean hasProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
+    method public static final org.apache.http.Header parseHeader(java.lang.String, org.apache.http.message.LineParser) throws org.apache.http.ParseException;
+    method public org.apache.http.Header parseHeader(org.apache.http.util.CharArrayBuffer) throws org.apache.http.ParseException;
+    method public static final org.apache.http.ProtocolVersion parseProtocolVersion(java.lang.String, org.apache.http.message.LineParser) throws org.apache.http.ParseException;
+    method public org.apache.http.ProtocolVersion parseProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
+    method public static final org.apache.http.RequestLine parseRequestLine(java.lang.String, org.apache.http.message.LineParser) throws org.apache.http.ParseException;
+    method public org.apache.http.RequestLine parseRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
+    method public static final org.apache.http.StatusLine parseStatusLine(java.lang.String, org.apache.http.message.LineParser) throws org.apache.http.ParseException;
+    method public org.apache.http.StatusLine parseStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
+    method protected void skipWhitespace(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
+    field public static final org.apache.http.message.BasicLineParser DEFAULT;
+    field protected final org.apache.http.ProtocolVersion protocol;
+  }
+
+  public class BasicListHeaderIterator implements org.apache.http.HeaderIterator {
+    ctor public BasicListHeaderIterator(java.util.List, java.lang.String);
+    method protected boolean filterHeader(int);
+    method protected int findNext(int);
+    method public boolean hasNext();
+    method public final java.lang.Object next() throws java.util.NoSuchElementException;
+    method public org.apache.http.Header nextHeader() throws java.util.NoSuchElementException;
+    method public void remove() throws java.lang.UnsupportedOperationException;
+    field protected final java.util.List allHeaders;
+    field protected int currentIndex;
+    field protected java.lang.String headerName;
+    field protected int lastIndex;
+  }
+
+  public class BasicNameValuePair implements java.lang.Cloneable org.apache.http.NameValuePair {
+    ctor public BasicNameValuePair(java.lang.String, java.lang.String);
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public java.lang.String getName();
+    method public java.lang.String getValue();
+  }
+
+  public class BasicRequestLine implements java.lang.Cloneable org.apache.http.RequestLine {
+    ctor public BasicRequestLine(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion);
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public java.lang.String getMethod();
+    method public org.apache.http.ProtocolVersion getProtocolVersion();
+    method public java.lang.String getUri();
+  }
+
+  public class BasicStatusLine implements java.lang.Cloneable org.apache.http.StatusLine {
+    ctor public BasicStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String);
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public org.apache.http.ProtocolVersion getProtocolVersion();
+    method public java.lang.String getReasonPhrase();
+    method public int getStatusCode();
+  }
+
+  public class BasicTokenIterator implements org.apache.http.TokenIterator {
+    ctor public BasicTokenIterator(org.apache.http.HeaderIterator);
+    method protected java.lang.String createToken(java.lang.String, int, int);
+    method protected int findNext(int) throws org.apache.http.ParseException;
+    method protected int findTokenEnd(int);
+    method protected int findTokenSeparator(int);
+    method protected int findTokenStart(int);
+    method public boolean hasNext();
+    method protected boolean isHttpSeparator(char);
+    method protected boolean isTokenChar(char);
+    method protected boolean isTokenSeparator(char);
+    method protected boolean isWhitespace(char);
+    method public final java.lang.Object next() throws java.util.NoSuchElementException, org.apache.http.ParseException;
+    method public java.lang.String nextToken() throws java.util.NoSuchElementException, org.apache.http.ParseException;
+    method public final void remove() throws java.lang.UnsupportedOperationException;
+    field public static final java.lang.String HTTP_SEPARATORS = " ,;=()<>@:\\\"/[]?{}\t";
+    field protected java.lang.String currentHeader;
+    field protected java.lang.String currentToken;
+    field protected final org.apache.http.HeaderIterator headerIt;
+    field protected int searchPos;
+  }
+
+  public class BufferedHeader implements java.lang.Cloneable org.apache.http.FormattedHeader {
+    ctor public BufferedHeader(org.apache.http.util.CharArrayBuffer) throws org.apache.http.ParseException;
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public org.apache.http.util.CharArrayBuffer getBuffer();
+    method public org.apache.http.HeaderElement[] getElements() throws org.apache.http.ParseException;
+    method public java.lang.String getName();
+    method public java.lang.String getValue();
+    method public int getValuePos();
+  }
+
+  public class HeaderGroup implements java.lang.Cloneable {
+    ctor public HeaderGroup();
+    method public void addHeader(org.apache.http.Header);
+    method public void clear();
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public boolean containsHeader(java.lang.String);
+    method public org.apache.http.message.HeaderGroup copy();
+    method public org.apache.http.Header[] getAllHeaders();
+    method public org.apache.http.Header getCondensedHeader(java.lang.String);
+    method public org.apache.http.Header getFirstHeader(java.lang.String);
+    method public org.apache.http.Header[] getHeaders(java.lang.String);
+    method public org.apache.http.Header getLastHeader(java.lang.String);
+    method public org.apache.http.HeaderIterator iterator();
+    method public org.apache.http.HeaderIterator iterator(java.lang.String);
+    method public void removeHeader(org.apache.http.Header);
+    method public void setHeaders(org.apache.http.Header[]);
+    method public void updateHeader(org.apache.http.Header);
+  }
+
+  public abstract interface HeaderValueFormatter {
+    method public abstract org.apache.http.util.CharArrayBuffer formatElements(org.apache.http.util.CharArrayBuffer, org.apache.http.HeaderElement[], boolean);
+    method public abstract org.apache.http.util.CharArrayBuffer formatHeaderElement(org.apache.http.util.CharArrayBuffer, org.apache.http.HeaderElement, boolean);
+    method public abstract org.apache.http.util.CharArrayBuffer formatNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.NameValuePair, boolean);
+    method public abstract org.apache.http.util.CharArrayBuffer formatParameters(org.apache.http.util.CharArrayBuffer, org.apache.http.NameValuePair[], boolean);
+  }
+
+  public abstract interface HeaderValueParser {
+    method public abstract org.apache.http.HeaderElement[] parseElements(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
+    method public abstract org.apache.http.HeaderElement parseHeaderElement(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
+    method public abstract org.apache.http.NameValuePair parseNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
+    method public abstract org.apache.http.NameValuePair[] parseParameters(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
+  }
+
+  public abstract interface LineFormatter {
+    method public abstract org.apache.http.util.CharArrayBuffer appendProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.ProtocolVersion);
+    method public abstract org.apache.http.util.CharArrayBuffer formatHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.Header);
+    method public abstract org.apache.http.util.CharArrayBuffer formatRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.RequestLine);
+    method public abstract org.apache.http.util.CharArrayBuffer formatStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.StatusLine);
+  }
+
+  public abstract interface LineParser {
+    method public abstract boolean hasProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
+    method public abstract org.apache.http.Header parseHeader(org.apache.http.util.CharArrayBuffer) throws org.apache.http.ParseException;
+    method public abstract org.apache.http.ProtocolVersion parseProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
+    method public abstract org.apache.http.RequestLine parseRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
+    method public abstract org.apache.http.StatusLine parseStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
+  }
+
+  public class ParserCursor {
+    ctor public ParserCursor(int, int);
+    method public boolean atEnd();
+    method public int getLowerBound();
+    method public int getPos();
+    method public int getUpperBound();
+    method public void updatePos(int);
+  }
+
+}
+
+package org.apache.http.params {
+
+  public abstract class AbstractHttpParams implements org.apache.http.params.HttpParams {
+    ctor protected AbstractHttpParams();
+    method public boolean getBooleanParameter(java.lang.String, boolean);
+    method public double getDoubleParameter(java.lang.String, double);
+    method public int getIntParameter(java.lang.String, int);
+    method public long getLongParameter(java.lang.String, long);
+    method public boolean isParameterFalse(java.lang.String);
+    method public boolean isParameterTrue(java.lang.String);
+    method public org.apache.http.params.HttpParams setBooleanParameter(java.lang.String, boolean);
+    method public org.apache.http.params.HttpParams setDoubleParameter(java.lang.String, double);
+    method public org.apache.http.params.HttpParams setIntParameter(java.lang.String, int);
+    method public org.apache.http.params.HttpParams setLongParameter(java.lang.String, long);
+  }
+
+  public final class BasicHttpParams extends org.apache.http.params.AbstractHttpParams implements java.lang.Cloneable java.io.Serializable {
+    ctor public BasicHttpParams();
+    method public void clear();
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public org.apache.http.params.HttpParams copy();
+    method protected void copyParams(org.apache.http.params.HttpParams);
+    method public java.lang.Object getParameter(java.lang.String);
+    method public boolean isParameterSet(java.lang.String);
+    method public boolean isParameterSetLocally(java.lang.String);
+    method public boolean removeParameter(java.lang.String);
+    method public org.apache.http.params.HttpParams setParameter(java.lang.String, java.lang.Object);
+    method public void setParameters(java.lang.String[], java.lang.Object);
+  }
+
+  public abstract interface CoreConnectionPNames {
+    field public static final java.lang.String CONNECTION_TIMEOUT = "http.connection.timeout";
+    field public static final java.lang.String MAX_HEADER_COUNT = "http.connection.max-header-count";
+    field public static final java.lang.String MAX_LINE_LENGTH = "http.connection.max-line-length";
+    field public static final java.lang.String SOCKET_BUFFER_SIZE = "http.socket.buffer-size";
+    field public static final java.lang.String SO_LINGER = "http.socket.linger";
+    field public static final java.lang.String SO_TIMEOUT = "http.socket.timeout";
+    field public static final java.lang.String STALE_CONNECTION_CHECK = "http.connection.stalecheck";
+    field public static final java.lang.String TCP_NODELAY = "http.tcp.nodelay";
+  }
+
+  public abstract interface CoreProtocolPNames {
+    field public static final java.lang.String HTTP_CONTENT_CHARSET = "http.protocol.content-charset";
+    field public static final java.lang.String HTTP_ELEMENT_CHARSET = "http.protocol.element-charset";
+    field public static final java.lang.String ORIGIN_SERVER = "http.origin-server";
+    field public static final java.lang.String PROTOCOL_VERSION = "http.protocol.version";
+    field public static final java.lang.String STRICT_TRANSFER_ENCODING = "http.protocol.strict-transfer-encoding";
+    field public static final java.lang.String USER_AGENT = "http.useragent";
+    field public static final java.lang.String USE_EXPECT_CONTINUE = "http.protocol.expect-continue";
+    field public static final java.lang.String WAIT_FOR_CONTINUE = "http.protocol.wait-for-continue";
+  }
+
+  public final class DefaultedHttpParams extends org.apache.http.params.AbstractHttpParams {
+    ctor public DefaultedHttpParams(org.apache.http.params.HttpParams, org.apache.http.params.HttpParams);
+    method public org.apache.http.params.HttpParams copy();
+    method public org.apache.http.params.HttpParams getDefaults();
+    method public java.lang.Object getParameter(java.lang.String);
+    method public boolean removeParameter(java.lang.String);
+    method public org.apache.http.params.HttpParams setParameter(java.lang.String, java.lang.Object);
+  }
+
+  public abstract class HttpAbstractParamBean {
+    ctor public HttpAbstractParamBean(org.apache.http.params.HttpParams);
+    field protected final org.apache.http.params.HttpParams params;
+  }
+
+  public class HttpConnectionParamBean extends org.apache.http.params.HttpAbstractParamBean {
+    ctor public HttpConnectionParamBean(org.apache.http.params.HttpParams);
+    method public void setConnectionTimeout(int);
+    method public void setLinger(int);
+    method public void setSoTimeout(int);
+    method public void setSocketBufferSize(int);
+    method public void setStaleCheckingEnabled(boolean);
+    method public void setTcpNoDelay(boolean);
+  }
+
+  public final class HttpConnectionParams implements org.apache.http.params.CoreConnectionPNames {
+    method public static int getConnectionTimeout(org.apache.http.params.HttpParams);
+    method public static int getLinger(org.apache.http.params.HttpParams);
+    method public static int getSoTimeout(org.apache.http.params.HttpParams);
+    method public static int getSocketBufferSize(org.apache.http.params.HttpParams);
+    method public static boolean getTcpNoDelay(org.apache.http.params.HttpParams);
+    method public static boolean isStaleCheckingEnabled(org.apache.http.params.HttpParams);
+    method public static void setConnectionTimeout(org.apache.http.params.HttpParams, int);
+    method public static void setLinger(org.apache.http.params.HttpParams, int);
+    method public static void setSoTimeout(org.apache.http.params.HttpParams, int);
+    method public static void setSocketBufferSize(org.apache.http.params.HttpParams, int);
+    method public static void setStaleCheckingEnabled(org.apache.http.params.HttpParams, boolean);
+    method public static void setTcpNoDelay(org.apache.http.params.HttpParams, boolean);
+  }
+
+  public abstract interface HttpParams {
+    method public abstract org.apache.http.params.HttpParams copy();
+    method public abstract boolean getBooleanParameter(java.lang.String, boolean);
+    method public abstract double getDoubleParameter(java.lang.String, double);
+    method public abstract int getIntParameter(java.lang.String, int);
+    method public abstract long getLongParameter(java.lang.String, long);
+    method public abstract java.lang.Object getParameter(java.lang.String);
+    method public abstract boolean isParameterFalse(java.lang.String);
+    method public abstract boolean isParameterTrue(java.lang.String);
+    method public abstract boolean removeParameter(java.lang.String);
+    method public abstract org.apache.http.params.HttpParams setBooleanParameter(java.lang.String, boolean);
+    method public abstract org.apache.http.params.HttpParams setDoubleParameter(java.lang.String, double);
+    method public abstract org.apache.http.params.HttpParams setIntParameter(java.lang.String, int);
+    method public abstract org.apache.http.params.HttpParams setLongParameter(java.lang.String, long);
+    method public abstract org.apache.http.params.HttpParams setParameter(java.lang.String, java.lang.Object);
+  }
+
+  public class HttpProtocolParamBean extends org.apache.http.params.HttpAbstractParamBean {
+    ctor public HttpProtocolParamBean(org.apache.http.params.HttpParams);
+    method public void setContentCharset(java.lang.String);
+    method public void setHttpElementCharset(java.lang.String);
+    method public void setUseExpectContinue(boolean);
+    method public void setUserAgent(java.lang.String);
+    method public void setVersion(org.apache.http.HttpVersion);
+  }
+
+  public final class HttpProtocolParams implements org.apache.http.params.CoreProtocolPNames {
+    method public static java.lang.String getContentCharset(org.apache.http.params.HttpParams);
+    method public static java.lang.String getHttpElementCharset(org.apache.http.params.HttpParams);
+    method public static java.lang.String getUserAgent(org.apache.http.params.HttpParams);
+    method public static org.apache.http.ProtocolVersion getVersion(org.apache.http.params.HttpParams);
+    method public static void setContentCharset(org.apache.http.params.HttpParams, java.lang.String);
+    method public static void setHttpElementCharset(org.apache.http.params.HttpParams, java.lang.String);
+    method public static void setUseExpectContinue(org.apache.http.params.HttpParams, boolean);
+    method public static void setUserAgent(org.apache.http.params.HttpParams, java.lang.String);
+    method public static void setVersion(org.apache.http.params.HttpParams, org.apache.http.ProtocolVersion);
+    method public static boolean useExpectContinue(org.apache.http.params.HttpParams);
+  }
+
+}
+
+package org.apache.http.protocol {
+
+  public class BasicHttpContext implements org.apache.http.protocol.HttpContext {
+    ctor public BasicHttpContext();
+    ctor public BasicHttpContext(org.apache.http.protocol.HttpContext);
+    method public java.lang.Object getAttribute(java.lang.String);
+    method public java.lang.Object removeAttribute(java.lang.String);
+    method public void setAttribute(java.lang.String, java.lang.Object);
+  }
+
+  public final class BasicHttpProcessor implements java.lang.Cloneable org.apache.http.protocol.HttpProcessor org.apache.http.protocol.HttpRequestInterceptorList org.apache.http.protocol.HttpResponseInterceptorList {
+    ctor public BasicHttpProcessor();
+    method public final void addInterceptor(org.apache.http.HttpRequestInterceptor);
+    method public final void addInterceptor(org.apache.http.HttpRequestInterceptor, int);
+    method public final void addInterceptor(org.apache.http.HttpResponseInterceptor);
+    method public final void addInterceptor(org.apache.http.HttpResponseInterceptor, int);
+    method public void addRequestInterceptor(org.apache.http.HttpRequestInterceptor);
+    method public void addRequestInterceptor(org.apache.http.HttpRequestInterceptor, int);
+    method public void addResponseInterceptor(org.apache.http.HttpResponseInterceptor, int);
+    method public void addResponseInterceptor(org.apache.http.HttpResponseInterceptor);
+    method public void clearInterceptors();
+    method public void clearRequestInterceptors();
+    method public void clearResponseInterceptors();
+    method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
+    method public org.apache.http.protocol.BasicHttpProcessor copy();
+    method protected void copyInterceptors(org.apache.http.protocol.BasicHttpProcessor);
+    method public org.apache.http.HttpRequestInterceptor getRequestInterceptor(int);
+    method public int getRequestInterceptorCount();
+    method public org.apache.http.HttpResponseInterceptor getResponseInterceptor(int);
+    method public int getResponseInterceptorCount();
+    method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+    method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+    method public void removeRequestInterceptorByClass(java.lang.Class);
+    method public void removeResponseInterceptorByClass(java.lang.Class);
+    method public void setInterceptors(java.util.List);
+    field protected java.util.List requestInterceptors;
+    field protected java.util.List responseInterceptors;
+  }
+
+  public final class DefaultedHttpContext implements org.apache.http.protocol.HttpContext {
+    ctor public DefaultedHttpContext(org.apache.http.protocol.HttpContext, org.apache.http.protocol.HttpContext);
+    method public java.lang.Object getAttribute(java.lang.String);
+    method public org.apache.http.protocol.HttpContext getDefaults();
+    method public java.lang.Object removeAttribute(java.lang.String);
+    method public void setAttribute(java.lang.String, java.lang.Object);
+  }
+
+  public abstract interface ExecutionContext {
+    field public static final java.lang.String HTTP_CONNECTION = "http.connection";
+    field public static final java.lang.String HTTP_PROXY_HOST = "http.proxy_host";
+    field public static final java.lang.String HTTP_REQUEST = "http.request";
+    field public static final java.lang.String HTTP_REQ_SENT = "http.request_sent";
+    field public static final java.lang.String HTTP_RESPONSE = "http.response";
+    field public static final java.lang.String HTTP_TARGET_HOST = "http.target_host";
+  }
+
+  public final class HTTP {
+    method public static boolean isWhitespace(char);
+    field public static final java.lang.String ASCII = "ASCII";
+    field public static final java.lang.String CHARSET_PARAM = "; charset=";
+    field public static final java.lang.String CHUNK_CODING = "chunked";
+    field public static final java.lang.String CONN_CLOSE = "Close";
+    field public static final java.lang.String CONN_DIRECTIVE = "Connection";
+    field public static final java.lang.String CONN_KEEP_ALIVE = "Keep-Alive";
+    field public static final java.lang.String CONTENT_ENCODING = "Content-Encoding";
+    field public static final java.lang.String CONTENT_LEN = "Content-Length";
+    field public static final java.lang.String CONTENT_TYPE = "Content-Type";
+    field public static final int CR = 13; // 0xd
+    field public static final java.lang.String DATE_HEADER = "Date";
+    field public static final java.lang.String DEFAULT_CONTENT_CHARSET = "ISO-8859-1";
+    field public static final java.lang.String DEFAULT_CONTENT_TYPE = "application/octet-stream";
+    field public static final java.lang.String DEFAULT_PROTOCOL_CHARSET = "US-ASCII";
+    field public static final java.lang.String EXPECT_CONTINUE = "100-continue";
+    field public static final java.lang.String EXPECT_DIRECTIVE = "Expect";
+    field public static final int HT = 9; // 0x9
+    field public static final java.lang.String IDENTITY_CODING = "identity";
+    field public static final java.lang.String ISO_8859_1 = "ISO-8859-1";
+    field public static final int LF = 10; // 0xa
+    field public static final java.lang.String OCTET_STREAM_TYPE = "application/octet-stream";
+    field public static final java.lang.String PLAIN_TEXT_TYPE = "text/plain";
+    field public static final java.lang.String SERVER_HEADER = "Server";
+    field public static final int SP = 32; // 0x20
+    field public static final java.lang.String TARGET_HOST = "Host";
+    field public static final java.lang.String TRANSFER_ENCODING = "Transfer-Encoding";
+    field public static final java.lang.String USER_AGENT = "User-Agent";
+    field public static final java.lang.String US_ASCII = "US-ASCII";
+    field public static final java.lang.String UTF_16 = "UTF-16";
+    field public static final java.lang.String UTF_8 = "UTF-8";
+  }
+
+  public abstract interface HttpContext {
+    method public abstract java.lang.Object getAttribute(java.lang.String);
+    method public abstract java.lang.Object removeAttribute(java.lang.String);
+    method public abstract void setAttribute(java.lang.String, java.lang.Object);
+    field public static final java.lang.String RESERVED_PREFIX = "http.";
+  }
+
+  public class HttpDateGenerator {
+    ctor public HttpDateGenerator();
+    method public synchronized java.lang.String getCurrentDate();
+    field public static final java.util.TimeZone GMT;
+    field public static final java.lang.String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
+  }
+
+  public abstract interface HttpExpectationVerifier {
+    method public abstract void verify(org.apache.http.HttpRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
+  }
+
+  public abstract interface HttpProcessor implements org.apache.http.HttpRequestInterceptor org.apache.http.HttpResponseInterceptor {
+  }
+
+  public class HttpRequestExecutor {
+    ctor public HttpRequestExecutor();
+    method protected boolean canResponseHaveBody(org.apache.http.HttpRequest, org.apache.http.HttpResponse);
+    method protected org.apache.http.HttpResponse doReceiveResponse(org.apache.http.HttpRequest, org.apache.http.HttpClientConnection, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+    method protected org.apache.http.HttpResponse doSendRequest(org.apache.http.HttpRequest, org.apache.http.HttpClientConnection, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+    method public org.apache.http.HttpResponse execute(org.apache.http.HttpRequest, org.apache.http.HttpClientConnection, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+    method public void postProcess(org.apache.http.HttpResponse, org.apache.http.protocol.HttpProcessor, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+    method public void preProcess(org.apache.http.HttpRequest, org.apache.http.protocol.HttpProcessor, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public abstract interface HttpRequestHandler {
+    method public abstract void handle(org.apache.http.HttpRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class HttpRequestHandlerRegistry implements org.apache.http.protocol.HttpRequestHandlerResolver {
+    ctor public HttpRequestHandlerRegistry();
+    method public org.apache.http.protocol.HttpRequestHandler lookup(java.lang.String);
+    method protected deprecated boolean matchUriRequestPattern(java.lang.String, java.lang.String);
+    method public void register(java.lang.String, org.apache.http.protocol.HttpRequestHandler);
+    method public void setHandlers(java.util.Map);
+    method public void unregister(java.lang.String);
+  }
+
+  public abstract interface HttpRequestHandlerResolver {
+    method public abstract org.apache.http.protocol.HttpRequestHandler lookup(java.lang.String);
+  }
+
+  public abstract interface HttpRequestInterceptorList {
+    method public abstract void addRequestInterceptor(org.apache.http.HttpRequestInterceptor);
+    method public abstract void addRequestInterceptor(org.apache.http.HttpRequestInterceptor, int);
+    method public abstract void clearRequestInterceptors();
+    method public abstract org.apache.http.HttpRequestInterceptor getRequestInterceptor(int);
+    method public abstract int getRequestInterceptorCount();
+    method public abstract void removeRequestInterceptorByClass(java.lang.Class);
+    method public abstract void setInterceptors(java.util.List);
+  }
+
+  public abstract interface HttpResponseInterceptorList {
+    method public abstract void addResponseInterceptor(org.apache.http.HttpResponseInterceptor);
+    method public abstract void addResponseInterceptor(org.apache.http.HttpResponseInterceptor, int);
+    method public abstract void clearResponseInterceptors();
+    method public abstract org.apache.http.HttpResponseInterceptor getResponseInterceptor(int);
+    method public abstract int getResponseInterceptorCount();
+    method public abstract void removeResponseInterceptorByClass(java.lang.Class);
+    method public abstract void setInterceptors(java.util.List);
+  }
+
+  public class HttpService {
+    ctor public HttpService(org.apache.http.protocol.HttpProcessor, org.apache.http.ConnectionReuseStrategy, org.apache.http.HttpResponseFactory);
+    method protected void doService(org.apache.http.HttpRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+    method public org.apache.http.params.HttpParams getParams();
+    method protected void handleException(org.apache.http.HttpException, org.apache.http.HttpResponse);
+    method public void handleRequest(org.apache.http.HttpServerConnection, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+    method public void setConnReuseStrategy(org.apache.http.ConnectionReuseStrategy);
+    method public void setExpectationVerifier(org.apache.http.protocol.HttpExpectationVerifier);
+    method public void setHandlerResolver(org.apache.http.protocol.HttpRequestHandlerResolver);
+    method public void setHttpProcessor(org.apache.http.protocol.HttpProcessor);
+    method public void setParams(org.apache.http.params.HttpParams);
+    method public void setResponseFactory(org.apache.http.HttpResponseFactory);
+  }
+
+  public class RequestConnControl implements org.apache.http.HttpRequestInterceptor {
+    ctor public RequestConnControl();
+    method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class RequestContent implements org.apache.http.HttpRequestInterceptor {
+    ctor public RequestContent();
+    method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class RequestDate implements org.apache.http.HttpRequestInterceptor {
+    ctor public RequestDate();
+    method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class RequestExpectContinue implements org.apache.http.HttpRequestInterceptor {
+    ctor public RequestExpectContinue();
+    method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class RequestTargetHost implements org.apache.http.HttpRequestInterceptor {
+    ctor public RequestTargetHost();
+    method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class RequestUserAgent implements org.apache.http.HttpRequestInterceptor {
+    ctor public RequestUserAgent();
+    method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class ResponseConnControl implements org.apache.http.HttpResponseInterceptor {
+    ctor public ResponseConnControl();
+    method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class ResponseContent implements org.apache.http.HttpResponseInterceptor {
+    ctor public ResponseContent();
+    method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class ResponseDate implements org.apache.http.HttpResponseInterceptor {
+    ctor public ResponseDate();
+    method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class ResponseServer implements org.apache.http.HttpResponseInterceptor {
+    ctor public ResponseServer();
+    method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
+  }
+
+  public class SyncBasicHttpContext extends org.apache.http.protocol.BasicHttpContext {
+    ctor public SyncBasicHttpContext(org.apache.http.protocol.HttpContext);
+  }
+
+  public class UriPatternMatcher {
+    ctor public UriPatternMatcher();
+    method public java.lang.Object lookup(java.lang.String);
+    method protected boolean matchUriRequestPattern(java.lang.String, java.lang.String);
+    method public void register(java.lang.String, java.lang.Object);
+    method public void setHandlers(java.util.Map);
+    method public void unregister(java.lang.String);
+  }
+
+}
+
+package org.apache.http.util {
+
+  public final class ByteArrayBuffer {
+    ctor public ByteArrayBuffer(int);
+    method public void append(byte[], int, int);
+    method public void append(int);
+    method public void append(char[], int, int);
+    method public void append(org.apache.http.util.CharArrayBuffer, int, int);
+    method public byte[] buffer();
+    method public int byteAt(int);
+    method public int capacity();
+    method public void clear();
+    method public boolean isEmpty();
+    method public boolean isFull();
+    method public int length();
+    method public void setLength(int);
+    method public byte[] toByteArray();
+  }
+
+  public final class CharArrayBuffer {
+    ctor public CharArrayBuffer(int);
+    method public void append(char[], int, int);
+    method public void append(java.lang.String);
+    method public void append(org.apache.http.util.CharArrayBuffer, int, int);
+    method public void append(org.apache.http.util.CharArrayBuffer);
+    method public void append(char);
+    method public void append(byte[], int, int);
+    method public void append(org.apache.http.util.ByteArrayBuffer, int, int);
+    method public void append(java.lang.Object);
+    method public char[] buffer();
+    method public int capacity();
+    method public char charAt(int);
+    method public void clear();
+    method public void ensureCapacity(int);
+    method public int indexOf(int, int, int);
+    method public int indexOf(int);
+    method public boolean isEmpty();
+    method public boolean isFull();
+    method public int length();
+    method public void setLength(int);
+    method public java.lang.String substring(int, int);
+    method public java.lang.String substringTrimmed(int, int);
+    method public char[] toCharArray();
+  }
+
+  public final class EncodingUtils {
+    method public static byte[] getAsciiBytes(java.lang.String);
+    method public static java.lang.String getAsciiString(byte[], int, int);
+    method public static java.lang.String getAsciiString(byte[]);
+    method public static byte[] getBytes(java.lang.String, java.lang.String);
+    method public static java.lang.String getString(byte[], int, int, java.lang.String);
+    method public static java.lang.String getString(byte[], java.lang.String);
+  }
+
+  public final class EntityUtils {
+    method public static java.lang.String getContentCharSet(org.apache.http.HttpEntity) throws org.apache.http.ParseException;
+    method public static byte[] toByteArray(org.apache.http.HttpEntity) throws java.io.IOException;
+    method public static java.lang.String toString(org.apache.http.HttpEntity, java.lang.String) throws java.io.IOException, org.apache.http.ParseException;
+    method public static java.lang.String toString(org.apache.http.HttpEntity) throws java.io.IOException, org.apache.http.ParseException;
+  }
+
+  public final class ExceptionUtils {
+    method public static void initCause(java.lang.Throwable, java.lang.Throwable);
+  }
+
+  public final class LangUtils {
+    method public static boolean equals(java.lang.Object, java.lang.Object);
+    method public static boolean equals(java.lang.Object[], java.lang.Object[]);
+    method public static int hashCode(int, int);
+    method public static int hashCode(int, boolean);
+    method public static int hashCode(int, java.lang.Object);
+    field public static final int HASH_OFFSET = 37; // 0x25
+    field public static final int HASH_SEED = 17; // 0x11
+  }
+
+  public class VersionInfo {
+    ctor protected VersionInfo(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method protected static final org.apache.http.util.VersionInfo fromMap(java.lang.String, java.util.Map, java.lang.ClassLoader);
+    method public final java.lang.String getClassloader();
+    method public final java.lang.String getModule();
+    method public final java.lang.String getPackage();
+    method public final java.lang.String getRelease();
+    method public final java.lang.String getTimestamp();
+    method public static final org.apache.http.util.VersionInfo[] loadVersionInfo(java.lang.String[], java.lang.ClassLoader);
+    method public static final org.apache.http.util.VersionInfo loadVersionInfo(java.lang.String, java.lang.ClassLoader);
+    field public static final java.lang.String PROPERTY_MODULE = "info.module";
+    field public static final java.lang.String PROPERTY_RELEASE = "info.release";
+    field public static final java.lang.String PROPERTY_TIMESTAMP = "info.timestamp";
+    field public static final java.lang.String UNAVAILABLE = "UNAVAILABLE";
+    field public static final java.lang.String VERSION_PROPERTY_FILE = "version.properties";
+  }
+
+}
+
+package org.json {
+
+  public class JSONArray {
+    ctor public JSONArray();
+    ctor public JSONArray(java.util.Collection);
+    ctor public JSONArray(org.json.JSONTokener) throws org.json.JSONException;
+    ctor public JSONArray(java.lang.String) throws org.json.JSONException;
+    method public java.lang.Object get(int) throws org.json.JSONException;
+    method public boolean getBoolean(int) throws org.json.JSONException;
+    method public double getDouble(int) throws org.json.JSONException;
+    method public int getInt(int) throws org.json.JSONException;
+    method public org.json.JSONArray getJSONArray(int) throws org.json.JSONException;
+    method public org.json.JSONObject getJSONObject(int) throws org.json.JSONException;
+    method public long getLong(int) throws org.json.JSONException;
+    method public java.lang.String getString(int) throws org.json.JSONException;
+    method public boolean isNull(int);
+    method public java.lang.String join(java.lang.String) throws org.json.JSONException;
+    method public int length();
+    method public java.lang.Object opt(int);
+    method public boolean optBoolean(int);
+    method public boolean optBoolean(int, boolean);
+    method public double optDouble(int);
+    method public double optDouble(int, double);
+    method public int optInt(int);
+    method public int optInt(int, int);
+    method public org.json.JSONArray optJSONArray(int);
+    method public org.json.JSONObject optJSONObject(int);
+    method public long optLong(int);
+    method public long optLong(int, long);
+    method public java.lang.String optString(int);
+    method public java.lang.String optString(int, java.lang.String);
+    method public org.json.JSONArray put(boolean);
+    method public org.json.JSONArray put(double) throws org.json.JSONException;
+    method public org.json.JSONArray put(int);
+    method public org.json.JSONArray put(long);
+    method public org.json.JSONArray put(java.lang.Object);
+    method public org.json.JSONArray put(int, boolean) throws org.json.JSONException;
+    method public org.json.JSONArray put(int, double) throws org.json.JSONException;
+    method public org.json.JSONArray put(int, int) throws org.json.JSONException;
+    method public org.json.JSONArray put(int, long) throws org.json.JSONException;
+    method public org.json.JSONArray put(int, java.lang.Object) throws org.json.JSONException;
+    method public org.json.JSONObject toJSONObject(org.json.JSONArray) throws org.json.JSONException;
+    method public java.lang.String toString(int) throws org.json.JSONException;
+  }
+
+  public class JSONException extends java.lang.Exception {
+    ctor public JSONException(java.lang.String);
+  }
+
+  public class JSONObject {
+    ctor public JSONObject();
+    ctor public JSONObject(java.util.Map);
+    ctor public JSONObject(org.json.JSONTokener) throws org.json.JSONException;
+    ctor public JSONObject(java.lang.String) throws org.json.JSONException;
+    ctor public JSONObject(org.json.JSONObject, java.lang.String[]) throws org.json.JSONException;
+    method public org.json.JSONObject accumulate(java.lang.String, java.lang.Object) throws org.json.JSONException;
+    method public java.lang.Object get(java.lang.String) throws org.json.JSONException;
+    method public boolean getBoolean(java.lang.String) throws org.json.JSONException;
+    method public double getDouble(java.lang.String) throws org.json.JSONException;
+    method public int getInt(java.lang.String) throws org.json.JSONException;
+    method public org.json.JSONArray getJSONArray(java.lang.String) throws org.json.JSONException;
+    method public org.json.JSONObject getJSONObject(java.lang.String) throws org.json.JSONException;
+    method public long getLong(java.lang.String) throws org.json.JSONException;
+    method public java.lang.String getString(java.lang.String) throws org.json.JSONException;
+    method public boolean has(java.lang.String);
+    method public boolean isNull(java.lang.String);
+    method public java.util.Iterator keys();
+    method public int length();
+    method public org.json.JSONArray names();
+    method public static java.lang.String numberToString(java.lang.Number) throws org.json.JSONException;
+    method public java.lang.Object opt(java.lang.String);
+    method public boolean optBoolean(java.lang.String);
+    method public boolean optBoolean(java.lang.String, boolean);
+    method public double optDouble(java.lang.String);
+    method public double optDouble(java.lang.String, double);
+    method public int optInt(java.lang.String);
+    method public int optInt(java.lang.String, int);
+    method public org.json.JSONArray optJSONArray(java.lang.String);
+    method public org.json.JSONObject optJSONObject(java.lang.String);
+    method public long optLong(java.lang.String);
+    method public long optLong(java.lang.String, long);
+    method public java.lang.String optString(java.lang.String);
+    method public java.lang.String optString(java.lang.String, java.lang.String);
+    method public org.json.JSONObject put(java.lang.String, boolean) throws org.json.JSONException;
+    method public org.json.JSONObject put(java.lang.String, double) throws org.json.JSONException;
+    method public org.json.JSONObject put(java.lang.String, int) throws org.json.JSONException;
+    method public org.json.JSONObject put(java.lang.String, long) throws org.json.JSONException;
+    method public org.json.JSONObject put(java.lang.String, java.lang.Object) throws org.json.JSONException;
+    method public org.json.JSONObject putOpt(java.lang.String, java.lang.Object) throws org.json.JSONException;
+    method public static java.lang.String quote(java.lang.String);
+    method public java.lang.Object remove(java.lang.String);
+    method public org.json.JSONArray toJSONArray(org.json.JSONArray) throws org.json.JSONException;
+    method public java.lang.String toString(int) throws org.json.JSONException;
+    field public static final java.lang.Object NULL;
+  }
+
+  public class JSONStringer {
+    ctor public JSONStringer();
+    method public org.json.JSONStringer array() throws org.json.JSONException;
+    method public org.json.JSONStringer endArray() throws org.json.JSONException;
+    method public org.json.JSONStringer endObject() throws org.json.JSONException;
+    method public org.json.JSONStringer key(java.lang.String) throws org.json.JSONException;
+    method public org.json.JSONStringer object() throws org.json.JSONException;
+    method public org.json.JSONStringer value(java.lang.Object) throws org.json.JSONException;
+    method public org.json.JSONStringer value(boolean) throws org.json.JSONException;
+    method public org.json.JSONStringer value(double) throws org.json.JSONException;
+    method public org.json.JSONStringer value(long) throws org.json.JSONException;
+  }
+
+  public class JSONTokener {
+    ctor public JSONTokener(java.lang.String);
+    method public void back();
+    method public static int dehexchar(char);
+    method public boolean more();
+    method public char next();
+    method public char next(char) throws org.json.JSONException;
+    method public java.lang.String next(int) throws org.json.JSONException;
+    method public char nextClean() throws org.json.JSONException;
+    method public java.lang.String nextString(char) throws org.json.JSONException;
+    method public java.lang.String nextTo(java.lang.String);
+    method public java.lang.String nextTo(char);
+    method public java.lang.Object nextValue() throws org.json.JSONException;
+    method public void skipPast(java.lang.String);
+    method public char skipTo(char);
+    method public org.json.JSONException syntaxError(java.lang.String);
+  }
+
+}
+
+package org.w3c.dom {
+
+  public abstract interface Attr implements org.w3c.dom.Node {
+    method public abstract java.lang.String getName();
+    method public abstract org.w3c.dom.Element getOwnerElement();
+    method public abstract org.w3c.dom.TypeInfo getSchemaTypeInfo();
+    method public abstract boolean getSpecified();
+    method public abstract java.lang.String getValue();
+    method public abstract boolean isId();
+    method public abstract void setValue(java.lang.String) throws org.w3c.dom.DOMException;
+  }
+
+  public abstract interface CDATASection implements org.w3c.dom.Text {
+  }
+
+  public abstract interface CharacterData implements org.w3c.dom.Node {
+    method public abstract void appendData(java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract void deleteData(int, int) throws org.w3c.dom.DOMException;
+    method public abstract java.lang.String getData() throws org.w3c.dom.DOMException;
+    method public abstract int getLength();
+    method public abstract void insertData(int, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract void replaceData(int, int, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract void setData(java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract java.lang.String substringData(int, int) throws org.w3c.dom.DOMException;
+  }
+
+  public abstract interface Comment implements org.w3c.dom.CharacterData {
+  }
+
+  public abstract interface DOMConfiguration {
+    method public abstract boolean canSetParameter(java.lang.String, java.lang.Object);
+    method public abstract java.lang.Object getParameter(java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.DOMStringList getParameterNames();
+    method public abstract void setParameter(java.lang.String, java.lang.Object) throws org.w3c.dom.DOMException;
+  }
+
+  public abstract interface DOMError {
+    method public abstract org.w3c.dom.DOMLocator getLocation();
+    method public abstract java.lang.String getMessage();
+    method public abstract java.lang.Object getRelatedData();
+    method public abstract java.lang.Object getRelatedException();
+    method public abstract short getSeverity();
+    method public abstract java.lang.String getType();
+    field public static final short SEVERITY_ERROR = 2; // 0x2
+    field public static final short SEVERITY_FATAL_ERROR = 3; // 0x3
+    field public static final short SEVERITY_WARNING = 1; // 0x1
+  }
+
+  public abstract interface DOMErrorHandler {
+    method public abstract boolean handleError(org.w3c.dom.DOMError);
+  }
+
+  public class DOMException extends java.lang.RuntimeException {
+    ctor public DOMException(short, java.lang.String);
+    field public static final short DOMSTRING_SIZE_ERR = 2; // 0x2
+    field public static final short HIERARCHY_REQUEST_ERR = 3; // 0x3
+    field public static final short INDEX_SIZE_ERR = 1; // 0x1
+    field public static final short INUSE_ATTRIBUTE_ERR = 10; // 0xa
+    field public static final short INVALID_ACCESS_ERR = 15; // 0xf
+    field public static final short INVALID_CHARACTER_ERR = 5; // 0x5
+    field public static final short INVALID_MODIFICATION_ERR = 13; // 0xd
+    field public static final short INVALID_STATE_ERR = 11; // 0xb
+    field public static final short NAMESPACE_ERR = 14; // 0xe
+    field public static final short NOT_FOUND_ERR = 8; // 0x8
+    field public static final short NOT_SUPPORTED_ERR = 9; // 0x9
+    field public static final short NO_DATA_ALLOWED_ERR = 6; // 0x6
+    field public static final short NO_MODIFICATION_ALLOWED_ERR = 7; // 0x7
+    field public static final short SYNTAX_ERR = 12; // 0xc
+    field public static final short TYPE_MISMATCH_ERR = 17; // 0x11
+    field public static final short VALIDATION_ERR = 16; // 0x10
+    field public static final short WRONG_DOCUMENT_ERR = 4; // 0x4
+    field public short code;
+  }
+
+  public abstract interface DOMImplementation {
+    method public abstract org.w3c.dom.Document createDocument(java.lang.String, java.lang.String, org.w3c.dom.DocumentType) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.DocumentType createDocumentType(java.lang.String, java.lang.String, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract java.lang.Object getFeature(java.lang.String, java.lang.String);
+    method public abstract boolean hasFeature(java.lang.String, java.lang.String);
+  }
+
+  public abstract interface DOMImplementationList {
+    method public abstract int getLength();
+    method public abstract org.w3c.dom.DOMImplementation item(int);
+  }
+
+  public abstract interface DOMImplementationSource {
+    method public abstract org.w3c.dom.DOMImplementation getDOMImplementation(java.lang.String);
+    method public abstract org.w3c.dom.DOMImplementationList getDOMImplementationList(java.lang.String);
+  }
+
+  public abstract interface DOMLocator {
+    method public abstract int getByteOffset();
+    method public abstract int getColumnNumber();
+    method public abstract int getLineNumber();
+    method public abstract org.w3c.dom.Node getRelatedNode();
+    method public abstract java.lang.String getUri();
+    method public abstract int getUtf16Offset();
+  }
+
+  public abstract interface DOMStringList {
+    method public abstract boolean contains(java.lang.String);
+    method public abstract int getLength();
+    method public abstract java.lang.String item(int);
+  }
+
+  public abstract interface Document implements org.w3c.dom.Node {
+    method public abstract org.w3c.dom.Node adoptNode(org.w3c.dom.Node) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Attr createAttribute(java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Attr createAttributeNS(java.lang.String, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.CDATASection createCDATASection(java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Comment createComment(java.lang.String);
+    method public abstract org.w3c.dom.DocumentFragment createDocumentFragment();
+    method public abstract org.w3c.dom.Element createElement(java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Element createElementNS(java.lang.String, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.EntityReference createEntityReference(java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.ProcessingInstruction createProcessingInstruction(java.lang.String, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Text createTextNode(java.lang.String);
+    method public abstract org.w3c.dom.DocumentType getDoctype();
+    method public abstract org.w3c.dom.Element getDocumentElement();
+    method public abstract java.lang.String getDocumentURI();
+    method public abstract org.w3c.dom.DOMConfiguration getDomConfig();
+    method public abstract org.w3c.dom.Element getElementById(java.lang.String);
+    method public abstract org.w3c.dom.NodeList getElementsByTagName(java.lang.String);
+    method public abstract org.w3c.dom.NodeList getElementsByTagNameNS(java.lang.String, java.lang.String);
+    method public abstract org.w3c.dom.DOMImplementation getImplementation();
+    method public abstract java.lang.String getInputEncoding();
+    method public abstract boolean getStrictErrorChecking();
+    method public abstract java.lang.String getXmlEncoding();
+    method public abstract boolean getXmlStandalone();
+    method public abstract java.lang.String getXmlVersion();
+    method public abstract org.w3c.dom.Node importNode(org.w3c.dom.Node, boolean) throws org.w3c.dom.DOMException;
+    method public abstract void normalizeDocument();
+    method public abstract org.w3c.dom.Node renameNode(org.w3c.dom.Node, java.lang.String, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract void setDocumentURI(java.lang.String);
+    method public abstract void setStrictErrorChecking(boolean);
+    method public abstract void setXmlStandalone(boolean) throws org.w3c.dom.DOMException;
+    method public abstract void setXmlVersion(java.lang.String) throws org.w3c.dom.DOMException;
+  }
+
+  public abstract interface DocumentFragment implements org.w3c.dom.Node {
+  }
+
+  public abstract interface DocumentType implements org.w3c.dom.Node {
+    method public abstract org.w3c.dom.NamedNodeMap getEntities();
+    method public abstract java.lang.String getInternalSubset();
+    method public abstract java.lang.String getName();
+    method public abstract org.w3c.dom.NamedNodeMap getNotations();
+    method public abstract java.lang.String getPublicId();
+    method public abstract java.lang.String getSystemId();
+  }
+
+  public abstract interface Element implements org.w3c.dom.Node {
+    method public abstract java.lang.String getAttribute(java.lang.String);
+    method public abstract java.lang.String getAttributeNS(java.lang.String, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Attr getAttributeNode(java.lang.String);
+    method public abstract org.w3c.dom.Attr getAttributeNodeNS(java.lang.String, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.NodeList getElementsByTagName(java.lang.String);
+    method public abstract org.w3c.dom.NodeList getElementsByTagNameNS(java.lang.String, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.TypeInfo getSchemaTypeInfo();
+    method public abstract java.lang.String getTagName();
+    method public abstract boolean hasAttribute(java.lang.String);
+    method public abstract boolean hasAttributeNS(java.lang.String, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract void removeAttribute(java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract void removeAttributeNS(java.lang.String, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Attr removeAttributeNode(org.w3c.dom.Attr) throws org.w3c.dom.DOMException;
+    method public abstract void setAttribute(java.lang.String, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract void setAttributeNS(java.lang.String, java.lang.String, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Attr setAttributeNode(org.w3c.dom.Attr) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Attr setAttributeNodeNS(org.w3c.dom.Attr) throws org.w3c.dom.DOMException;
+    method public abstract void setIdAttribute(java.lang.String, boolean) throws org.w3c.dom.DOMException;
+    method public abstract void setIdAttributeNS(java.lang.String, java.lang.String, boolean) throws org.w3c.dom.DOMException;
+    method public abstract void setIdAttributeNode(org.w3c.dom.Attr, boolean) throws org.w3c.dom.DOMException;
+  }
+
+  public abstract interface Entity implements org.w3c.dom.Node {
+    method public abstract java.lang.String getInputEncoding();
+    method public abstract java.lang.String getNotationName();
+    method public abstract java.lang.String getPublicId();
+    method public abstract java.lang.String getSystemId();
+    method public abstract java.lang.String getXmlEncoding();
+    method public abstract java.lang.String getXmlVersion();
+  }
+
+  public abstract interface EntityReference implements org.w3c.dom.Node {
+  }
+
+  public abstract interface NameList {
+    method public abstract boolean contains(java.lang.String);
+    method public abstract boolean containsNS(java.lang.String, java.lang.String);
+    method public abstract int getLength();
+    method public abstract java.lang.String getName(int);
+    method public abstract java.lang.String getNamespaceURI(int);
+  }
+
+  public abstract interface NamedNodeMap {
+    method public abstract int getLength();
+    method public abstract org.w3c.dom.Node getNamedItem(java.lang.String);
+    method public abstract org.w3c.dom.Node getNamedItemNS(java.lang.String, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Node item(int);
+    method public abstract org.w3c.dom.Node removeNamedItem(java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Node removeNamedItemNS(java.lang.String, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Node setNamedItem(org.w3c.dom.Node) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Node setNamedItemNS(org.w3c.dom.Node) throws org.w3c.dom.DOMException;
+  }
+
+  public abstract interface Node {
+    method public abstract org.w3c.dom.Node appendChild(org.w3c.dom.Node) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Node cloneNode(boolean);
+    method public abstract short compareDocumentPosition(org.w3c.dom.Node) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.NamedNodeMap getAttributes();
+    method public abstract java.lang.String getBaseURI();
+    method public abstract org.w3c.dom.NodeList getChildNodes();
+    method public abstract java.lang.Object getFeature(java.lang.String, java.lang.String);
+    method public abstract org.w3c.dom.Node getFirstChild();
+    method public abstract org.w3c.dom.Node getLastChild();
+    method public abstract java.lang.String getLocalName();
+    method public abstract java.lang.String getNamespaceURI();
+    method public abstract org.w3c.dom.Node getNextSibling();
+    method public abstract java.lang.String getNodeName();
+    method public abstract short getNodeType();
+    method public abstract java.lang.String getNodeValue() throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Document getOwnerDocument();
+    method public abstract org.w3c.dom.Node getParentNode();
+    method public abstract java.lang.String getPrefix();
+    method public abstract org.w3c.dom.Node getPreviousSibling();
+    method public abstract java.lang.String getTextContent() throws org.w3c.dom.DOMException;
+    method public abstract java.lang.Object getUserData(java.lang.String);
+    method public abstract boolean hasAttributes();
+    method public abstract boolean hasChildNodes();
+    method public abstract org.w3c.dom.Node insertBefore(org.w3c.dom.Node, org.w3c.dom.Node) throws org.w3c.dom.DOMException;
+    method public abstract boolean isDefaultNamespace(java.lang.String);
+    method public abstract boolean isEqualNode(org.w3c.dom.Node);
+    method public abstract boolean isSameNode(org.w3c.dom.Node);
+    method public abstract boolean isSupported(java.lang.String, java.lang.String);
+    method public abstract java.lang.String lookupNamespaceURI(java.lang.String);
+    method public abstract java.lang.String lookupPrefix(java.lang.String);
+    method public abstract void normalize();
+    method public abstract org.w3c.dom.Node removeChild(org.w3c.dom.Node) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Node replaceChild(org.w3c.dom.Node, org.w3c.dom.Node) throws org.w3c.dom.DOMException;
+    method public abstract void setNodeValue(java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract void setPrefix(java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract void setTextContent(java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract java.lang.Object setUserData(java.lang.String, java.lang.Object, org.w3c.dom.UserDataHandler);
+    field public static final short ATTRIBUTE_NODE = 2; // 0x2
+    field public static final short CDATA_SECTION_NODE = 4; // 0x4
+    field public static final short COMMENT_NODE = 8; // 0x8
+    field public static final short DOCUMENT_FRAGMENT_NODE = 11; // 0xb
+    field public static final short DOCUMENT_NODE = 9; // 0x9
+    field public static final short DOCUMENT_POSITION_CONTAINED_BY = 16; // 0x10
+    field public static final short DOCUMENT_POSITION_CONTAINS = 8; // 0x8
+    field public static final short DOCUMENT_POSITION_DISCONNECTED = 1; // 0x1
+    field public static final short DOCUMENT_POSITION_FOLLOWING = 4; // 0x4
+    field public static final short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 32; // 0x20
+    field public static final short DOCUMENT_POSITION_PRECEDING = 2; // 0x2
+    field public static final short DOCUMENT_TYPE_NODE = 10; // 0xa
+    field public static final short ELEMENT_NODE = 1; // 0x1
+    field public static final short ENTITY_NODE = 6; // 0x6
+    field public static final short ENTITY_REFERENCE_NODE = 5; // 0x5
+    field public static final short NOTATION_NODE = 12; // 0xc
+    field public static final short PROCESSING_INSTRUCTION_NODE = 7; // 0x7
+    field public static final short TEXT_NODE = 3; // 0x3
+  }
+
+  public abstract interface NodeList {
+    method public abstract int getLength();
+    method public abstract org.w3c.dom.Node item(int);
+  }
+
+  public abstract interface Notation implements org.w3c.dom.Node {
+    method public abstract java.lang.String getPublicId();
+    method public abstract java.lang.String getSystemId();
+  }
+
+  public abstract interface ProcessingInstruction implements org.w3c.dom.Node {
+    method public abstract java.lang.String getData();
+    method public abstract java.lang.String getTarget();
+    method public abstract void setData(java.lang.String) throws org.w3c.dom.DOMException;
+  }
+
+  public abstract interface Text implements org.w3c.dom.CharacterData {
+    method public abstract java.lang.String getWholeText();
+    method public abstract boolean isElementContentWhitespace();
+    method public abstract org.w3c.dom.Text replaceWholeText(java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.Text splitText(int) throws org.w3c.dom.DOMException;
+  }
+
+  public abstract interface TypeInfo {
+    method public abstract java.lang.String getTypeName();
+    method public abstract java.lang.String getTypeNamespace();
+    method public abstract boolean isDerivedFrom(java.lang.String, java.lang.String, int);
+    field public static final int DERIVATION_EXTENSION = 2; // 0x2
+    field public static final int DERIVATION_LIST = 8; // 0x8
+    field public static final int DERIVATION_RESTRICTION = 1; // 0x1
+    field public static final int DERIVATION_UNION = 4; // 0x4
+  }
+
+  public abstract interface UserDataHandler {
+    method public abstract void handle(short, java.lang.String, java.lang.Object, org.w3c.dom.Node, org.w3c.dom.Node);
+    field public static final short NODE_ADOPTED = 5; // 0x5
+    field public static final short NODE_CLONED = 1; // 0x1
+    field public static final short NODE_DELETED = 3; // 0x3
+    field public static final short NODE_IMPORTED = 2; // 0x2
+    field public static final short NODE_RENAMED = 4; // 0x4
+  }
+
+}
+
+package org.w3c.dom.ls {
+
+  public abstract interface DOMImplementationLS {
+    method public abstract org.w3c.dom.ls.LSInput createLSInput();
+    method public abstract org.w3c.dom.ls.LSOutput createLSOutput();
+    method public abstract org.w3c.dom.ls.LSParser createLSParser(short, java.lang.String) throws org.w3c.dom.DOMException;
+    method public abstract org.w3c.dom.ls.LSSerializer createLSSerializer();
+    field public static final short MODE_ASYNCHRONOUS = 2; // 0x2
+    field public static final short MODE_SYNCHRONOUS = 1; // 0x1
+  }
+
+  public class LSException extends java.lang.RuntimeException {
+    ctor public LSException(short, java.lang.String);
+    field public static final short PARSE_ERR = 81; // 0x51
+    field public static final short SERIALIZE_ERR = 82; // 0x52
+    field public short code;
+  }
+
+  public abstract interface LSInput {
+    method public abstract java.lang.String getBaseURI();
+    method public abstract java.io.InputStream getByteStream();
+    method public abstract boolean getCertifiedText();
+    method public abstract java.io.Reader getCharacterStream();
+    method public abstract java.lang.String getEncoding();
+    method public abstract java.lang.String getPublicId();
+    method public abstract java.lang.String getStringData();
+    method public abstract java.lang.String getSystemId();
+    method public abstract void setBaseURI(java.lang.String);
+    method public abstract void setByteStream(java.io.InputStream);
+    method public abstract void setCertifiedText(boolean);
+    method public abstract void setCharacterStream(java.io.Reader);
+    method public abstract void setEncoding(java.lang.String);
+    method public abstract void setPublicId(java.lang.String);
+    method public abstract void setStringData(java.lang.String);
+    method public abstract void setSystemId(java.lang.String);
+  }
+
+  public abstract interface LSOutput {
+    method public abstract java.io.OutputStream getByteStream();
+    method public abstract java.io.Writer getCharacterStream();
+    method public abstract java.lang.String getEncoding();
+    method public abstract java.lang.String getSystemId();
+    method public abstract void setByteStream(java.io.OutputStream);
+    method public abstract void setCharacterStream(java.io.Writer);
+    method public abstract void setEncoding(java.lang.String);
+    method public abstract void setSystemId(java.lang.String);
+  }
+
+  public abstract interface LSParser {
+    method public abstract void abort();
+    method public abstract boolean getAsync();
+    method public abstract boolean getBusy();
+    method public abstract org.w3c.dom.DOMConfiguration getDomConfig();
+    method public abstract org.w3c.dom.ls.LSParserFilter getFilter();
+    method public abstract org.w3c.dom.Document parse(org.w3c.dom.ls.LSInput) throws org.w3c.dom.DOMException, org.w3c.dom.ls.LSException;
+    method public abstract org.w3c.dom.Document parseURI(java.lang.String) throws org.w3c.dom.DOMException, org.w3c.dom.ls.LSException;
+    method public abstract org.w3c.dom.Node parseWithContext(org.w3c.dom.ls.LSInput, org.w3c.dom.Node, short) throws org.w3c.dom.DOMException, org.w3c.dom.ls.LSException;
+    method public abstract void setFilter(org.w3c.dom.ls.LSParserFilter);
+    field public static final short ACTION_APPEND_AS_CHILDREN = 1; // 0x1
+    field public static final short ACTION_INSERT_AFTER = 4; // 0x4
+    field public static final short ACTION_INSERT_BEFORE = 3; // 0x3
+    field public static final short ACTION_REPLACE = 5; // 0x5
+    field public static final short ACTION_REPLACE_CHILDREN = 2; // 0x2
+  }
+
+  public abstract interface LSParserFilter {
+    method public abstract short acceptNode(org.w3c.dom.Node);
+    method public abstract int getWhatToShow();
+    method public abstract short startElement(org.w3c.dom.Element);
+    field public static final short FILTER_ACCEPT = 1; // 0x1
+    field public static final short FILTER_INTERRUPT = 4; // 0x4
+    field public static final short FILTER_REJECT = 2; // 0x2
+    field public static final short FILTER_SKIP = 3; // 0x3
+  }
+
+  public abstract interface LSResourceResolver {
+    method public abstract org.w3c.dom.ls.LSInput resolveResource(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+  }
+
+  public abstract interface LSSerializer {
+    method public abstract org.w3c.dom.DOMConfiguration getDomConfig();
+    method public abstract java.lang.String getNewLine();
+    method public abstract void setNewLine(java.lang.String);
+    method public abstract boolean write(org.w3c.dom.Node, org.w3c.dom.ls.LSOutput) throws org.w3c.dom.ls.LSException;
+    method public abstract java.lang.String writeToString(org.w3c.dom.Node) throws org.w3c.dom.DOMException, org.w3c.dom.ls.LSException;
+    method public abstract boolean writeToURI(org.w3c.dom.Node, java.lang.String) throws org.w3c.dom.ls.LSException;
+  }
+
+}
+
+package org.xml.sax {
+
+  public abstract deprecated interface AttributeList {
+    method public abstract int getLength();
+    method public abstract java.lang.String getName(int);
+    method public abstract java.lang.String getType(int);
+    method public abstract java.lang.String getType(java.lang.String);
+    method public abstract java.lang.String getValue(int);
+    method public abstract java.lang.String getValue(java.lang.String);
+  }
+
+  public abstract interface Attributes {
+    method public abstract int getIndex(java.lang.String, java.lang.String);
+    method public abstract int getIndex(java.lang.String);
+    method public abstract int getLength();
+    method public abstract java.lang.String getLocalName(int);
+    method public abstract java.lang.String getQName(int);
+    method public abstract java.lang.String getType(int);
+    method public abstract java.lang.String getType(java.lang.String, java.lang.String);
+    method public abstract java.lang.String getType(java.lang.String);
+    method public abstract java.lang.String getURI(int);
+    method public abstract java.lang.String getValue(int);
+    method public abstract java.lang.String getValue(java.lang.String, java.lang.String);
+    method public abstract java.lang.String getValue(java.lang.String);
+  }
+
+  public abstract interface ContentHandler {
+    method public abstract void characters(char[], int, int) throws org.xml.sax.SAXException;
+    method public abstract void endDocument() throws org.xml.sax.SAXException;
+    method public abstract void endElement(java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public abstract void endPrefixMapping(java.lang.String) throws org.xml.sax.SAXException;
+    method public abstract void ignorableWhitespace(char[], int, int) throws org.xml.sax.SAXException;
+    method public abstract void processingInstruction(java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public abstract void setDocumentLocator(org.xml.sax.Locator);
+    method public abstract void skippedEntity(java.lang.String) throws org.xml.sax.SAXException;
+    method public abstract void startDocument() throws org.xml.sax.SAXException;
+    method public abstract void startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) throws org.xml.sax.SAXException;
+    method public abstract void startPrefixMapping(java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+  }
+
+  public abstract interface DTDHandler {
+    method public abstract void notationDecl(java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public abstract void unparsedEntityDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+  }
+
+  public abstract deprecated interface DocumentHandler {
+    method public abstract void characters(char[], int, int) throws org.xml.sax.SAXException;
+    method public abstract void endDocument() throws org.xml.sax.SAXException;
+    method public abstract void endElement(java.lang.String) throws org.xml.sax.SAXException;
+    method public abstract void ignorableWhitespace(char[], int, int) throws org.xml.sax.SAXException;
+    method public abstract void processingInstruction(java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public abstract void setDocumentLocator(org.xml.sax.Locator);
+    method public abstract void startDocument() throws org.xml.sax.SAXException;
+    method public abstract void startElement(java.lang.String, org.xml.sax.AttributeList) throws org.xml.sax.SAXException;
+  }
+
+  public abstract interface EntityResolver {
+    method public abstract org.xml.sax.InputSource resolveEntity(java.lang.String, java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+  }
+
+  public abstract interface ErrorHandler {
+    method public abstract void error(org.xml.sax.SAXParseException) throws org.xml.sax.SAXException;
+    method public abstract void fatalError(org.xml.sax.SAXParseException) throws org.xml.sax.SAXException;
+    method public abstract void warning(org.xml.sax.SAXParseException) throws org.xml.sax.SAXException;
+  }
+
+  public deprecated class HandlerBase implements org.xml.sax.DTDHandler org.xml.sax.DocumentHandler org.xml.sax.EntityResolver org.xml.sax.ErrorHandler {
+    ctor public HandlerBase();
+    method public void characters(char[], int, int) throws org.xml.sax.SAXException;
+    method public void endDocument() throws org.xml.sax.SAXException;
+    method public void endElement(java.lang.String) throws org.xml.sax.SAXException;
+    method public void error(org.xml.sax.SAXParseException) throws org.xml.sax.SAXException;
+    method public void fatalError(org.xml.sax.SAXParseException) throws org.xml.sax.SAXException;
+    method public void ignorableWhitespace(char[], int, int) throws org.xml.sax.SAXException;
+    method public void notationDecl(java.lang.String, java.lang.String, java.lang.String);
+    method public void processingInstruction(java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public org.xml.sax.InputSource resolveEntity(java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public void setDocumentLocator(org.xml.sax.Locator);
+    method public void startDocument() throws org.xml.sax.SAXException;
+    method public void startElement(java.lang.String, org.xml.sax.AttributeList) throws org.xml.sax.SAXException;
+    method public void unparsedEntityDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public void warning(org.xml.sax.SAXParseException) throws org.xml.sax.SAXException;
+  }
+
+  public class InputSource {
+    ctor public InputSource();
+    ctor public InputSource(java.lang.String);
+    ctor public InputSource(java.io.InputStream);
+    ctor public InputSource(java.io.Reader);
+    method public java.io.InputStream getByteStream();
+    method public java.io.Reader getCharacterStream();
+    method public java.lang.String getEncoding();
+    method public java.lang.String getPublicId();
+    method public java.lang.String getSystemId();
+    method public void setByteStream(java.io.InputStream);
+    method public void setCharacterStream(java.io.Reader);
+    method public void setEncoding(java.lang.String);
+    method public void setPublicId(java.lang.String);
+    method public void setSystemId(java.lang.String);
+  }
+
+  public abstract interface Locator {
+    method public abstract int getColumnNumber();
+    method public abstract int getLineNumber();
+    method public abstract java.lang.String getPublicId();
+    method public abstract java.lang.String getSystemId();
+  }
+
+  public abstract deprecated interface Parser {
+    method public abstract void parse(org.xml.sax.InputSource) throws java.io.IOException, org.xml.sax.SAXException;
+    method public abstract void parse(java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+    method public abstract void setDTDHandler(org.xml.sax.DTDHandler);
+    method public abstract void setDocumentHandler(org.xml.sax.DocumentHandler);
+    method public abstract void setEntityResolver(org.xml.sax.EntityResolver);
+    method public abstract void setErrorHandler(org.xml.sax.ErrorHandler);
+    method public abstract void setLocale(java.util.Locale) throws org.xml.sax.SAXException;
+  }
+
+  public class SAXException extends java.lang.Exception {
+    ctor public SAXException();
+    ctor public SAXException(java.lang.String);
+    ctor public SAXException(java.lang.Exception);
+    ctor public SAXException(java.lang.String, java.lang.Exception);
+    method public java.lang.Exception getException();
+  }
+
+  public class SAXNotRecognizedException extends org.xml.sax.SAXException {
+    ctor public SAXNotRecognizedException();
+    ctor public SAXNotRecognizedException(java.lang.String);
+  }
+
+  public class SAXNotSupportedException extends org.xml.sax.SAXException {
+    ctor public SAXNotSupportedException();
+    ctor public SAXNotSupportedException(java.lang.String);
+  }
+
+  public class SAXParseException extends org.xml.sax.SAXException {
+    ctor public SAXParseException(java.lang.String, org.xml.sax.Locator);
+    ctor public SAXParseException(java.lang.String, org.xml.sax.Locator, java.lang.Exception);
+    ctor public SAXParseException(java.lang.String, java.lang.String, java.lang.String, int, int);
+    ctor public SAXParseException(java.lang.String, java.lang.String, java.lang.String, int, int, java.lang.Exception);
+    method public int getColumnNumber();
+    method public int getLineNumber();
+    method public java.lang.String getPublicId();
+    method public java.lang.String getSystemId();
+  }
+
+  public abstract interface XMLFilter implements org.xml.sax.XMLReader {
+    method public abstract org.xml.sax.XMLReader getParent();
+    method public abstract void setParent(org.xml.sax.XMLReader);
+  }
+
+  public abstract interface XMLReader {
+    method public abstract org.xml.sax.ContentHandler getContentHandler();
+    method public abstract org.xml.sax.DTDHandler getDTDHandler();
+    method public abstract org.xml.sax.EntityResolver getEntityResolver();
+    method public abstract org.xml.sax.ErrorHandler getErrorHandler();
+    method public abstract boolean getFeature(java.lang.String) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public abstract java.lang.Object getProperty(java.lang.String) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public abstract void parse(org.xml.sax.InputSource) throws java.io.IOException, org.xml.sax.SAXException;
+    method public abstract void parse(java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+    method public abstract void setContentHandler(org.xml.sax.ContentHandler);
+    method public abstract void setDTDHandler(org.xml.sax.DTDHandler);
+    method public abstract void setEntityResolver(org.xml.sax.EntityResolver);
+    method public abstract void setErrorHandler(org.xml.sax.ErrorHandler);
+    method public abstract void setFeature(java.lang.String, boolean) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public abstract void setProperty(java.lang.String, java.lang.Object) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+  }
+
+}
+
+package org.xml.sax.ext {
+
+  public abstract interface Attributes2 implements org.xml.sax.Attributes {
+    method public abstract boolean isDeclared(int);
+    method public abstract boolean isDeclared(java.lang.String);
+    method public abstract boolean isDeclared(java.lang.String, java.lang.String);
+    method public abstract boolean isSpecified(int);
+    method public abstract boolean isSpecified(java.lang.String, java.lang.String);
+    method public abstract boolean isSpecified(java.lang.String);
+  }
+
+  public class Attributes2Impl extends org.xml.sax.helpers.AttributesImpl implements org.xml.sax.ext.Attributes2 {
+    ctor public Attributes2Impl();
+    ctor public Attributes2Impl(org.xml.sax.Attributes);
+    method public boolean isDeclared(int);
+    method public boolean isDeclared(java.lang.String, java.lang.String);
+    method public boolean isDeclared(java.lang.String);
+    method public boolean isSpecified(int);
+    method public boolean isSpecified(java.lang.String, java.lang.String);
+    method public boolean isSpecified(java.lang.String);
+    method public void setDeclared(int, boolean);
+    method public void setSpecified(int, boolean);
+  }
+
+  public abstract interface DeclHandler {
+    method public abstract void attributeDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public abstract void elementDecl(java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public abstract void externalEntityDecl(java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public abstract void internalEntityDecl(java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+  }
+
+  public class DefaultHandler2 extends org.xml.sax.helpers.DefaultHandler implements org.xml.sax.ext.DeclHandler org.xml.sax.ext.EntityResolver2 org.xml.sax.ext.LexicalHandler {
+    ctor public DefaultHandler2();
+    method public void attributeDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public void comment(char[], int, int) throws org.xml.sax.SAXException;
+    method public void elementDecl(java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public void endCDATA() throws org.xml.sax.SAXException;
+    method public void endDTD() throws org.xml.sax.SAXException;
+    method public void endEntity(java.lang.String) throws org.xml.sax.SAXException;
+    method public void externalEntityDecl(java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public org.xml.sax.InputSource getExternalSubset(java.lang.String, java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void internalEntityDecl(java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public org.xml.sax.InputSource resolveEntity(java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void startCDATA() throws org.xml.sax.SAXException;
+    method public void startDTD(java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public void startEntity(java.lang.String) throws org.xml.sax.SAXException;
+  }
+
+  public abstract interface EntityResolver2 implements org.xml.sax.EntityResolver {
+    method public abstract org.xml.sax.InputSource getExternalSubset(java.lang.String, java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+    method public abstract org.xml.sax.InputSource resolveEntity(java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+  }
+
+  public abstract interface LexicalHandler {
+    method public abstract void comment(char[], int, int) throws org.xml.sax.SAXException;
+    method public abstract void endCDATA() throws org.xml.sax.SAXException;
+    method public abstract void endDTD() throws org.xml.sax.SAXException;
+    method public abstract void endEntity(java.lang.String) throws org.xml.sax.SAXException;
+    method public abstract void startCDATA() throws org.xml.sax.SAXException;
+    method public abstract void startDTD(java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public abstract void startEntity(java.lang.String) throws org.xml.sax.SAXException;
+  }
+
+  public abstract interface Locator2 implements org.xml.sax.Locator {
+    method public abstract java.lang.String getEncoding();
+    method public abstract java.lang.String getXMLVersion();
+  }
+
+  public class Locator2Impl extends org.xml.sax.helpers.LocatorImpl implements org.xml.sax.ext.Locator2 {
+    ctor public Locator2Impl();
+    ctor public Locator2Impl(org.xml.sax.Locator);
+    method public java.lang.String getEncoding();
+    method public java.lang.String getXMLVersion();
+    method public void setEncoding(java.lang.String);
+    method public void setXMLVersion(java.lang.String);
+  }
+
+}
+
+package org.xml.sax.helpers {
+
+  public deprecated class AttributeListImpl implements org.xml.sax.AttributeList {
+    ctor public AttributeListImpl();
+    ctor public AttributeListImpl(org.xml.sax.AttributeList);
+    method public void addAttribute(java.lang.String, java.lang.String, java.lang.String);
+    method public void clear();
+    method public int getLength();
+    method public java.lang.String getName(int);
+    method public java.lang.String getType(int);
+    method public java.lang.String getType(java.lang.String);
+    method public java.lang.String getValue(int);
+    method public java.lang.String getValue(java.lang.String);
+    method public void removeAttribute(java.lang.String);
+    method public void setAttributeList(org.xml.sax.AttributeList);
+  }
+
+  public class AttributesImpl implements org.xml.sax.Attributes {
+    ctor public AttributesImpl();
+    ctor public AttributesImpl(org.xml.sax.Attributes);
+    method public void addAttribute(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public void clear();
+    method public int getIndex(java.lang.String, java.lang.String);
+    method public int getIndex(java.lang.String);
+    method public int getLength();
+    method public java.lang.String getLocalName(int);
+    method public java.lang.String getQName(int);
+    method public java.lang.String getType(int);
+    method public java.lang.String getType(java.lang.String, java.lang.String);
+    method public java.lang.String getType(java.lang.String);
+    method public java.lang.String getURI(int);
+    method public java.lang.String getValue(int);
+    method public java.lang.String getValue(java.lang.String, java.lang.String);
+    method public java.lang.String getValue(java.lang.String);
+    method public void removeAttribute(int);
+    method public void setAttribute(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    method public void setAttributes(org.xml.sax.Attributes);
+    method public void setLocalName(int, java.lang.String);
+    method public void setQName(int, java.lang.String);
+    method public void setType(int, java.lang.String);
+    method public void setURI(int, java.lang.String);
+    method public void setValue(int, java.lang.String);
+  }
+
+  public class DefaultHandler implements org.xml.sax.ContentHandler org.xml.sax.DTDHandler org.xml.sax.EntityResolver org.xml.sax.ErrorHandler {
+    ctor public DefaultHandler();
+    method public void characters(char[], int, int) throws org.xml.sax.SAXException;
+    method public void endDocument() throws org.xml.sax.SAXException;
+    method public void endElement(java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public void endPrefixMapping(java.lang.String) throws org.xml.sax.SAXException;
+    method public void error(org.xml.sax.SAXParseException) throws org.xml.sax.SAXException;
+    method public void fatalError(org.xml.sax.SAXParseException) throws org.xml.sax.SAXException;
+    method public void ignorableWhitespace(char[], int, int) throws org.xml.sax.SAXException;
+    method public void notationDecl(java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public void processingInstruction(java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public org.xml.sax.InputSource resolveEntity(java.lang.String, java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void setDocumentLocator(org.xml.sax.Locator);
+    method public void skippedEntity(java.lang.String) throws org.xml.sax.SAXException;
+    method public void startDocument() throws org.xml.sax.SAXException;
+    method public void startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) throws org.xml.sax.SAXException;
+    method public void startPrefixMapping(java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public void unparsedEntityDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public void warning(org.xml.sax.SAXParseException) throws org.xml.sax.SAXException;
+  }
+
+  public class LocatorImpl implements org.xml.sax.Locator {
+    ctor public LocatorImpl();
+    ctor public LocatorImpl(org.xml.sax.Locator);
+    method public int getColumnNumber();
+    method public int getLineNumber();
+    method public java.lang.String getPublicId();
+    method public java.lang.String getSystemId();
+    method public void setColumnNumber(int);
+    method public void setLineNumber(int);
+    method public void setPublicId(java.lang.String);
+    method public void setSystemId(java.lang.String);
+  }
+
+  public class NamespaceSupport {
+    ctor public NamespaceSupport();
+    method public boolean declarePrefix(java.lang.String, java.lang.String);
+    method public java.util.Enumeration getDeclaredPrefixes();
+    method public java.lang.String getPrefix(java.lang.String);
+    method public java.util.Enumeration getPrefixes();
+    method public java.util.Enumeration getPrefixes(java.lang.String);
+    method public java.lang.String getURI(java.lang.String);
+    method public boolean isNamespaceDeclUris();
+    method public void popContext();
+    method public java.lang.String[] processName(java.lang.String, java.lang.String[], boolean);
+    method public void pushContext();
+    method public void reset();
+    method public void setNamespaceDeclUris(boolean);
+    field public static final java.lang.String NSDECL = "http://www.w3.org/xmlns/2000/";
+    field public static final java.lang.String XMLNS = "http://www.w3.org/XML/1998/namespace";
+  }
+
+  public class ParserAdapter implements org.xml.sax.DocumentHandler org.xml.sax.XMLReader {
+    ctor public ParserAdapter() throws org.xml.sax.SAXException;
+    ctor public ParserAdapter(org.xml.sax.Parser);
+    method public void characters(char[], int, int) throws org.xml.sax.SAXException;
+    method public void endDocument() throws org.xml.sax.SAXException;
+    method public void endElement(java.lang.String) throws org.xml.sax.SAXException;
+    method public org.xml.sax.ContentHandler getContentHandler();
+    method public org.xml.sax.DTDHandler getDTDHandler();
+    method public org.xml.sax.EntityResolver getEntityResolver();
+    method public org.xml.sax.ErrorHandler getErrorHandler();
+    method public boolean getFeature(java.lang.String) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public java.lang.Object getProperty(java.lang.String) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public void ignorableWhitespace(char[], int, int) throws org.xml.sax.SAXException;
+    method public void parse(java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void parse(org.xml.sax.InputSource) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void processingInstruction(java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public void setContentHandler(org.xml.sax.ContentHandler);
+    method public void setDTDHandler(org.xml.sax.DTDHandler);
+    method public void setDocumentLocator(org.xml.sax.Locator);
+    method public void setEntityResolver(org.xml.sax.EntityResolver);
+    method public void setErrorHandler(org.xml.sax.ErrorHandler);
+    method public void setFeature(java.lang.String, boolean) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public void setProperty(java.lang.String, java.lang.Object) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public void startDocument() throws org.xml.sax.SAXException;
+    method public void startElement(java.lang.String, org.xml.sax.AttributeList) throws org.xml.sax.SAXException;
+  }
+
+  public deprecated class ParserFactory {
+    method public static org.xml.sax.Parser makeParser() throws java.lang.ClassCastException, java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException, java.lang.NullPointerException;
+    method public static org.xml.sax.Parser makeParser(java.lang.String) throws java.lang.ClassCastException, java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException;
+  }
+
+  public class XMLFilterImpl implements org.xml.sax.ContentHandler org.xml.sax.DTDHandler org.xml.sax.EntityResolver org.xml.sax.ErrorHandler org.xml.sax.XMLFilter {
+    ctor public XMLFilterImpl();
+    ctor public XMLFilterImpl(org.xml.sax.XMLReader);
+    method public void characters(char[], int, int) throws org.xml.sax.SAXException;
+    method public void endDocument() throws org.xml.sax.SAXException;
+    method public void endElement(java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public void endPrefixMapping(java.lang.String) throws org.xml.sax.SAXException;
+    method public void error(org.xml.sax.SAXParseException) throws org.xml.sax.SAXException;
+    method public void fatalError(org.xml.sax.SAXParseException) throws org.xml.sax.SAXException;
+    method public org.xml.sax.ContentHandler getContentHandler();
+    method public org.xml.sax.DTDHandler getDTDHandler();
+    method public org.xml.sax.EntityResolver getEntityResolver();
+    method public org.xml.sax.ErrorHandler getErrorHandler();
+    method public boolean getFeature(java.lang.String) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public org.xml.sax.XMLReader getParent();
+    method public java.lang.Object getProperty(java.lang.String) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public void ignorableWhitespace(char[], int, int) throws org.xml.sax.SAXException;
+    method public void notationDecl(java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public void parse(org.xml.sax.InputSource) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void parse(java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void processingInstruction(java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public org.xml.sax.InputSource resolveEntity(java.lang.String, java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void setContentHandler(org.xml.sax.ContentHandler);
+    method public void setDTDHandler(org.xml.sax.DTDHandler);
+    method public void setDocumentLocator(org.xml.sax.Locator);
+    method public void setEntityResolver(org.xml.sax.EntityResolver);
+    method public void setErrorHandler(org.xml.sax.ErrorHandler);
+    method public void setFeature(java.lang.String, boolean) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public void setParent(org.xml.sax.XMLReader);
+    method public void setProperty(java.lang.String, java.lang.Object) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public void skippedEntity(java.lang.String) throws org.xml.sax.SAXException;
+    method public void startDocument() throws org.xml.sax.SAXException;
+    method public void startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) throws org.xml.sax.SAXException;
+    method public void startPrefixMapping(java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public void unparsedEntityDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public void warning(org.xml.sax.SAXParseException) throws org.xml.sax.SAXException;
+  }
+
+  public class XMLReaderAdapter implements org.xml.sax.ContentHandler org.xml.sax.Parser {
+    ctor public XMLReaderAdapter() throws org.xml.sax.SAXException;
+    ctor public XMLReaderAdapter(org.xml.sax.XMLReader);
+    method public void characters(char[], int, int) throws org.xml.sax.SAXException;
+    method public void endDocument() throws org.xml.sax.SAXException;
+    method public void endElement(java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public void endPrefixMapping(java.lang.String);
+    method public void ignorableWhitespace(char[], int, int) throws org.xml.sax.SAXException;
+    method public void parse(java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void parse(org.xml.sax.InputSource) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void processingInstruction(java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    method public void setDTDHandler(org.xml.sax.DTDHandler);
+    method public void setDocumentHandler(org.xml.sax.DocumentHandler);
+    method public void setDocumentLocator(org.xml.sax.Locator);
+    method public void setEntityResolver(org.xml.sax.EntityResolver);
+    method public void setErrorHandler(org.xml.sax.ErrorHandler);
+    method public void setLocale(java.util.Locale) throws org.xml.sax.SAXException;
+    method public void skippedEntity(java.lang.String) throws org.xml.sax.SAXException;
+    method public void startDocument() throws org.xml.sax.SAXException;
+    method public void startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) throws org.xml.sax.SAXException;
+    method public void startPrefixMapping(java.lang.String, java.lang.String);
+  }
+
+  public final class XMLReaderFactory {
+    method public static org.xml.sax.XMLReader createXMLReader() throws org.xml.sax.SAXException;
+    method public static org.xml.sax.XMLReader createXMLReader(java.lang.String) throws org.xml.sax.SAXException;
+  }
+
+}
+
+package org.xmlpull.v1 {
+
+  public abstract interface XmlPullParser {
+    method public abstract void defineEntityReplacementText(java.lang.String, java.lang.String) throws org.xmlpull.v1.XmlPullParserException;
+    method public abstract int getAttributeCount();
+    method public abstract java.lang.String getAttributeName(int);
+    method public abstract java.lang.String getAttributeNamespace(int);
+    method public abstract java.lang.String getAttributePrefix(int);
+    method public abstract java.lang.String getAttributeType(int);
+    method public abstract java.lang.String getAttributeValue(int);
+    method public abstract java.lang.String getAttributeValue(java.lang.String, java.lang.String);
+    method public abstract int getColumnNumber();
+    method public abstract int getDepth();
+    method public abstract int getEventType() throws org.xmlpull.v1.XmlPullParserException;
+    method public abstract boolean getFeature(java.lang.String);
+    method public abstract java.lang.String getInputEncoding();
+    method public abstract int getLineNumber();
+    method public abstract java.lang.String getName();
+    method public abstract java.lang.String getNamespace(java.lang.String);
+    method public abstract java.lang.String getNamespace();
+    method public abstract int getNamespaceCount(int) throws org.xmlpull.v1.XmlPullParserException;
+    method public abstract java.lang.String getNamespacePrefix(int) throws org.xmlpull.v1.XmlPullParserException;
+    method public abstract java.lang.String getNamespaceUri(int) throws org.xmlpull.v1.XmlPullParserException;
+    method public abstract java.lang.String getPositionDescription();
+    method public abstract java.lang.String getPrefix();
+    method public abstract java.lang.Object getProperty(java.lang.String);
+    method public abstract java.lang.String getText();
+    method public abstract char[] getTextCharacters(int[]);
+    method public abstract boolean isAttributeDefault(int);
+    method public abstract boolean isEmptyElementTag() throws org.xmlpull.v1.XmlPullParserException;
+    method public abstract boolean isWhitespace() throws org.xmlpull.v1.XmlPullParserException;
+    method public abstract int next() throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public abstract int nextTag() throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public abstract java.lang.String nextText() throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public abstract int nextToken() throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public abstract void require(int, java.lang.String, java.lang.String) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public abstract void setFeature(java.lang.String, boolean) throws org.xmlpull.v1.XmlPullParserException;
+    method public abstract void setInput(java.io.Reader) throws org.xmlpull.v1.XmlPullParserException;
+    method public abstract void setInput(java.io.InputStream, java.lang.String) throws org.xmlpull.v1.XmlPullParserException;
+    method public abstract void setProperty(java.lang.String, java.lang.Object) throws org.xmlpull.v1.XmlPullParserException;
+    field public static final int CDSECT = 5; // 0x5
+    field public static final int COMMENT = 9; // 0x9
+    field public static final int DOCDECL = 10; // 0xa
+    field public static final int END_DOCUMENT = 1; // 0x1
+    field public static final int END_TAG = 3; // 0x3
+    field public static final int ENTITY_REF = 6; // 0x6
+    field public static final java.lang.String FEATURE_PROCESS_DOCDECL = "http://xmlpull.org/v1/doc/features.html#process-docdecl";
+    field public static final java.lang.String FEATURE_PROCESS_NAMESPACES = "http://xmlpull.org/v1/doc/features.html#process-namespaces";
+    field public static final java.lang.String FEATURE_REPORT_NAMESPACE_ATTRIBUTES = "http://xmlpull.org/v1/doc/features.html#report-namespace-prefixes";
+    field public static final java.lang.String FEATURE_VALIDATION = "http://xmlpull.org/v1/doc/features.html#validation";
+    field public static final int IGNORABLE_WHITESPACE = 7; // 0x7
+    field public static final java.lang.String NO_NAMESPACE = "";
+    field public static final int PROCESSING_INSTRUCTION = 8; // 0x8
+    field public static final int START_DOCUMENT = 0; // 0x0
+    field public static final int START_TAG = 2; // 0x2
+    field public static final int TEXT = 4; // 0x4
+    field public static final java.lang.String[] TYPES;
+  }
+
+  public class XmlPullParserException extends java.lang.Exception {
+    ctor public XmlPullParserException(java.lang.String);
+    ctor public XmlPullParserException(java.lang.String, org.xmlpull.v1.XmlPullParser, java.lang.Throwable);
+    method public int getColumnNumber();
+    method public java.lang.Throwable getDetail();
+    method public int getLineNumber();
+    field protected int column;
+    field protected java.lang.Throwable detail;
+    field protected int row;
+  }
+
+  public class XmlPullParserFactory {
+    ctor protected XmlPullParserFactory();
+    method public boolean getFeature(java.lang.String);
+    method public boolean isNamespaceAware();
+    method public boolean isValidating();
+    method public static org.xmlpull.v1.XmlPullParserFactory newInstance() throws org.xmlpull.v1.XmlPullParserException;
+    method public static org.xmlpull.v1.XmlPullParserFactory newInstance(java.lang.String, java.lang.Class) throws org.xmlpull.v1.XmlPullParserException;
+    method public org.xmlpull.v1.XmlPullParser newPullParser() throws org.xmlpull.v1.XmlPullParserException;
+    method public org.xmlpull.v1.XmlSerializer newSerializer() throws org.xmlpull.v1.XmlPullParserException;
+    method public void setFeature(java.lang.String, boolean) throws org.xmlpull.v1.XmlPullParserException;
+    method public void setNamespaceAware(boolean);
+    method public void setValidating(boolean);
+    field public static final java.lang.String PROPERTY_NAME = "org.xmlpull.v1.XmlPullParserFactory";
+    field protected java.lang.String classNamesLocation;
+    field protected java.util.HashMap features;
+    field protected java.util.ArrayList parserClasses;
+    field protected java.util.ArrayList serializerClasses;
+  }
+
+  public abstract interface XmlSerializer {
+    method public abstract org.xmlpull.v1.XmlSerializer attribute(java.lang.String, java.lang.String, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract void cdsect(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract void comment(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract void docdecl(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract void endDocument() throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract org.xmlpull.v1.XmlSerializer endTag(java.lang.String, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract void entityRef(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract void flush() throws java.io.IOException;
+    method public abstract int getDepth();
+    method public abstract boolean getFeature(java.lang.String);
+    method public abstract java.lang.String getName();
+    method public abstract java.lang.String getNamespace();
+    method public abstract java.lang.String getPrefix(java.lang.String, boolean) throws java.lang.IllegalArgumentException;
+    method public abstract java.lang.Object getProperty(java.lang.String);
+    method public abstract void ignorableWhitespace(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract void processingInstruction(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract void setFeature(java.lang.String, boolean) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract void setOutput(java.io.OutputStream, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract void setOutput(java.io.Writer) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract void setPrefix(java.lang.String, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract void setProperty(java.lang.String, java.lang.Object) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract void startDocument(java.lang.String, java.lang.Boolean) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract org.xmlpull.v1.XmlSerializer startTag(java.lang.String, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract org.xmlpull.v1.XmlSerializer text(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public abstract org.xmlpull.v1.XmlSerializer text(char[], int, int) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+  }
+
+}
+
+package org.xmlpull.v1.sax2 {
+
+  public class Driver implements org.xml.sax.Attributes org.xml.sax.Locator org.xml.sax.XMLReader {
+    ctor public Driver() throws org.xmlpull.v1.XmlPullParserException;
+    ctor public Driver(org.xmlpull.v1.XmlPullParser) throws org.xmlpull.v1.XmlPullParserException;
+    method public int getColumnNumber();
+    method public org.xml.sax.ContentHandler getContentHandler();
+    method public org.xml.sax.DTDHandler getDTDHandler();
+    method public org.xml.sax.EntityResolver getEntityResolver();
+    method public org.xml.sax.ErrorHandler getErrorHandler();
+    method public boolean getFeature(java.lang.String) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public int getIndex(java.lang.String, java.lang.String);
+    method public int getIndex(java.lang.String);
+    method public int getLength();
+    method public int getLineNumber();
+    method public java.lang.String getLocalName(int);
+    method public java.lang.Object getProperty(java.lang.String) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public java.lang.String getPublicId();
+    method public java.lang.String getQName(int);
+    method public java.lang.String getSystemId();
+    method public java.lang.String getType(int);
+    method public java.lang.String getType(java.lang.String, java.lang.String);
+    method public java.lang.String getType(java.lang.String);
+    method public java.lang.String getURI(int);
+    method public java.lang.String getValue(int);
+    method public java.lang.String getValue(java.lang.String, java.lang.String);
+    method public java.lang.String getValue(java.lang.String);
+    method public void parse(org.xml.sax.InputSource) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void parse(java.lang.String) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void parseSubTree(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xml.sax.SAXException;
+    method public void setContentHandler(org.xml.sax.ContentHandler);
+    method public void setDTDHandler(org.xml.sax.DTDHandler);
+    method public void setEntityResolver(org.xml.sax.EntityResolver);
+    method public void setErrorHandler(org.xml.sax.ErrorHandler);
+    method public void setFeature(java.lang.String, boolean) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method public void setProperty(java.lang.String, java.lang.Object) throws org.xml.sax.SAXNotRecognizedException, org.xml.sax.SAXNotSupportedException;
+    method protected void startElement(java.lang.String, java.lang.String, java.lang.String) throws org.xml.sax.SAXException;
+    field protected static final java.lang.String APACHE_DYNAMIC_VALIDATION_FEATURE = "http://apache.org/xml/features/validation/dynamic";
+    field protected static final java.lang.String APACHE_SCHEMA_VALIDATION_FEATURE = "http://apache.org/xml/features/validation/schema";
+    field protected static final java.lang.String DECLARATION_HANDLER_PROPERTY = "http://xml.org/sax/properties/declaration-handler";
+    field protected static final java.lang.String LEXICAL_HANDLER_PROPERTY = "http://xml.org/sax/properties/lexical-handler";
+    field protected static final java.lang.String NAMESPACES_FEATURE = "http://xml.org/sax/features/namespaces";
+    field protected static final java.lang.String NAMESPACE_PREFIXES_FEATURE = "http://xml.org/sax/features/namespace-prefixes";
+    field protected static final java.lang.String VALIDATION_FEATURE = "http://xml.org/sax/features/validation";
+    field protected org.xml.sax.ContentHandler contentHandler;
+    field protected org.xml.sax.ErrorHandler errorHandler;
+    field protected org.xmlpull.v1.XmlPullParser pp;
+    field protected java.lang.String systemId;
+  }
+
+}
+
diff --git a/api/current.txt b/api/current.txt
index b5fd82b..6b893d5 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -141,16 +141,35 @@
   public static final class Manifest.permission_group {
     ctor public Manifest.permission_group();
     field public static final java.lang.String ACCOUNTS = "android.permission-group.ACCOUNTS";
+    field public static final java.lang.String AFFECTS_BATTERY = "android.permission-group.AFFECTS_BATTERY";
+    field public static final java.lang.String APP_INFO = "android.permission-group.APP_INFO";
+    field public static final java.lang.String AUDIO_SETTINGS = "android.permission-group.AUDIO_SETTINGS";
+    field public static final java.lang.String BLUETOOTH_NETWORK = "android.permission-group.BLUETOOTH_NETWORK";
+    field public static final java.lang.String BOOKMARKS = "android.permission-group.BOOKMARKS";
+    field public static final java.lang.String CALENDAR = "android.permission-group.CALENDAR";
+    field public static final java.lang.String CAMERA = "android.permission-group.CAMERA";
     field public static final java.lang.String COST_MONEY = "android.permission-group.COST_MONEY";
     field public static final java.lang.String DEVELOPMENT_TOOLS = "android.permission-group.DEVELOPMENT_TOOLS";
+    field public static final java.lang.String DEVICE_ALARMS = "android.permission-group.DEVICE_ALARMS";
+    field public static final java.lang.String DISPLAY = "android.permission-group.DISPLAY";
     field public static final java.lang.String HARDWARE_CONTROLS = "android.permission-group.HARDWARE_CONTROLS";
     field public static final java.lang.String LOCATION = "android.permission-group.LOCATION";
     field public static final java.lang.String MESSAGES = "android.permission-group.MESSAGES";
+    field public static final java.lang.String MICROPHONE = "android.permission-group.MICROPHONE";
     field public static final java.lang.String NETWORK = "android.permission-group.NETWORK";
     field public static final java.lang.String PERSONAL_INFO = "android.permission-group.PERSONAL_INFO";
     field public static final java.lang.String PHONE_CALLS = "android.permission-group.PHONE_CALLS";
+    field public static final java.lang.String SCREENLOCK = "android.permission-group.SCREENLOCK";
+    field public static final java.lang.String SOCIAL_INFO = "android.permission-group.SOCIAL_INFO";
+    field public static final java.lang.String STATUS_BAR = "android.permission-group.STATUS_BAR";
     field public static final java.lang.String STORAGE = "android.permission-group.STORAGE";
+    field public static final java.lang.String SYNC_SETTINGS = "android.permission-group.SYNC_SETTINGS";
+    field public static final java.lang.String SYSTEM_CLOCK = "android.permission-group.SYSTEM_CLOCK";
     field public static final java.lang.String SYSTEM_TOOLS = "android.permission-group.SYSTEM_TOOLS";
+    field public static final java.lang.String USER_DICTIONARY = "android.permission-group.USER_DICTIONARY";
+    field public static final java.lang.String VOICEMAIL = "android.permission-group.VOICEMAIL";
+    field public static final java.lang.String WALLPAPER = "android.permission-group.WALLPAPER";
+    field public static final java.lang.String WRITE_USER_DICTIONARY = "android.permission-group.WRITE_USER_DICTIONARY";
   }
 
   public final class R {
@@ -312,6 +331,7 @@
     field public static final int checkboxStyle = 16842860; // 0x101006c
     field public static final int checked = 16843014; // 0x1010106
     field public static final int checkedButton = 16843080; // 0x1010148
+    field public static final int checkedTextViewStyle = 16843720; // 0x10103c8
     field public static final int childDivider = 16843025; // 0x1010111
     field public static final int childIndicator = 16843020; // 0x101010c
     field public static final int childIndicatorLeft = 16843023; // 0x101010f
@@ -471,6 +491,8 @@
     field public static final int foreground = 16843017; // 0x1010109
     field public static final int foregroundGravity = 16843264; // 0x1010200
     field public static final int format = 16843013; // 0x1010105
+    field public static final int format12Hour = 16843722; // 0x10103ca
+    field public static final int format24Hour = 16843723; // 0x10103cb
     field public static final int fragment = 16843491; // 0x10102e3
     field public static final int fragmentCloseEnterAnimation = 16843495; // 0x10102e7
     field public static final int fragmentCloseExitAnimation = 16843496; // 0x10102e8
@@ -551,6 +573,7 @@
     field public static final int indicatorRight = 16843022; // 0x101010e
     field public static final int inflatedId = 16842995; // 0x10100f3
     field public static final int initOrder = 16842778; // 0x101001a
+    field public static final int initialKeyguardLayout = 16843714; // 0x10103c2
     field public static final int initialLayout = 16843345; // 0x1010251
     field public static final int innerRadius = 16843359; // 0x101025f
     field public static final int innerRadiusRatio = 16843163; // 0x101019b
@@ -594,6 +617,7 @@
     field public static final int keycode = 16842949; // 0x10100c5
     field public static final int killAfterRestore = 16843420; // 0x101029c
     field public static final int label = 16842753; // 0x1010001
+    field public static final int labelFor = 16843718; // 0x10103c6
     field public static final int labelTextSize = 16843317; // 0x1010235
     field public static final int largeHeap = 16843610; // 0x101035a
     field public static final int largeScreens = 16843398; // 0x1010286
@@ -602,15 +626,20 @@
     field public static final int layerType = 16843604; // 0x1010354
     field public static final int layout = 16842994; // 0x10100f2
     field public static final int layoutAnimation = 16842988; // 0x10100ec
+    field public static final int layoutDirection = 16843698; // 0x10103b2
     field public static final int layout_above = 16843140; // 0x1010184
     field public static final int layout_alignBaseline = 16843142; // 0x1010186
     field public static final int layout_alignBottom = 16843146; // 0x101018a
+    field public static final int layout_alignEnd = 16843706; // 0x10103ba
     field public static final int layout_alignLeft = 16843143; // 0x1010187
     field public static final int layout_alignParentBottom = 16843150; // 0x101018e
+    field public static final int layout_alignParentEnd = 16843708; // 0x10103bc
     field public static final int layout_alignParentLeft = 16843147; // 0x101018b
     field public static final int layout_alignParentRight = 16843149; // 0x101018d
+    field public static final int layout_alignParentStart = 16843707; // 0x10103bb
     field public static final int layout_alignParentTop = 16843148; // 0x101018c
     field public static final int layout_alignRight = 16843145; // 0x1010189
+    field public static final int layout_alignStart = 16843705; // 0x10103b9
     field public static final int layout_alignTop = 16843144; // 0x1010188
     field public static final int layout_alignWithParentIfMissing = 16843154; // 0x1010192
     field public static final int layout_below = 16843141; // 0x1010185
@@ -623,15 +652,19 @@
     field public static final int layout_height = 16842997; // 0x10100f5
     field public static final int layout_margin = 16842998; // 0x10100f6
     field public static final int layout_marginBottom = 16843002; // 0x10100fa
+    field public static final int layout_marginEnd = 16843702; // 0x10103b6
     field public static final int layout_marginLeft = 16842999; // 0x10100f7
     field public static final int layout_marginRight = 16843001; // 0x10100f9
+    field public static final int layout_marginStart = 16843701; // 0x10103b5
     field public static final int layout_marginTop = 16843000; // 0x10100f8
     field public static final int layout_row = 16843643; // 0x101037b
     field public static final int layout_rowSpan = 16843644; // 0x101037c
     field public static final int layout_scale = 16843155; // 0x1010193
     field public static final int layout_span = 16843085; // 0x101014d
+    field public static final int layout_toEndOf = 16843704; // 0x10103b8
     field public static final int layout_toLeftOf = 16843138; // 0x1010182
     field public static final int layout_toRightOf = 16843139; // 0x1010183
+    field public static final int layout_toStartOf = 16843703; // 0x10103b7
     field public static final int layout_weight = 16843137; // 0x1010181
     field public static final int layout_width = 16842996; // 0x10100f4
     field public static final int layout_x = 16843135; // 0x101017f
@@ -650,8 +683,10 @@
     field public static final int listPreferredItemHeight = 16842829; // 0x101004d
     field public static final int listPreferredItemHeightLarge = 16843654; // 0x1010386
     field public static final int listPreferredItemHeightSmall = 16843655; // 0x1010387
+    field public static final int listPreferredItemPaddingEnd = 16843710; // 0x10103be
     field public static final int listPreferredItemPaddingLeft = 16843683; // 0x10103a3
     field public static final int listPreferredItemPaddingRight = 16843684; // 0x10103a4
+    field public static final int listPreferredItemPaddingStart = 16843709; // 0x10103bd
     field public static final int listSelector = 16843003; // 0x10100fb
     field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208
     field public static final int listViewStyle = 16842868; // 0x1010074
@@ -722,8 +757,10 @@
     field public static final int packageNames = 16843649; // 0x1010381
     field public static final int padding = 16842965; // 0x10100d5
     field public static final int paddingBottom = 16842969; // 0x10100d9
+    field public static final int paddingEnd = 16843700; // 0x10103b4
     field public static final int paddingLeft = 16842966; // 0x10100d6
     field public static final int paddingRight = 16842968; // 0x10100d8
+    field public static final int paddingStart = 16843699; // 0x10103b3
     field public static final int paddingTop = 16842967; // 0x10100d7
     field public static final int panelBackground = 16842846; // 0x101005e
     field public static final int panelColorBackground = 16842849; // 0x1010061
@@ -736,7 +773,9 @@
     field public static final int pathPattern = 16842796; // 0x101002c
     field public static final int pathPrefix = 16842795; // 0x101002b
     field public static final int permission = 16842758; // 0x1010006
+    field public static final int permissionFlags = 16843719; // 0x10103c7
     field public static final int permissionGroup = 16842762; // 0x101000a
+    field public static final int permissionGroupFlags = 16843717; // 0x10103c5
     field public static final int persistent = 16842765; // 0x101000d
     field public static final int persistentDrawingCache = 16842990; // 0x10100ee
     field public static final deprecated int phoneNumber = 16843111; // 0x1010167
@@ -756,6 +795,7 @@
     field public static final int preferenceLayoutChild = 16842900; // 0x1010094
     field public static final int preferenceScreenStyle = 16842891; // 0x101008b
     field public static final int preferenceStyle = 16842894; // 0x101008e
+    field public static final int presentationTheme = 16843712; // 0x10103c0
     field public static final int previewImage = 16843482; // 0x10102da
     field public static final int priority = 16842780; // 0x101001c
     field public static final int privateImeOptions = 16843299; // 0x1010223
@@ -874,11 +914,13 @@
     field public static final int showAsAction = 16843481; // 0x10102d9
     field public static final int showDefault = 16843258; // 0x10101fa
     field public static final int showDividers = 16843561; // 0x1010329
+    field public static final int showOnLockScreen = 16843721; // 0x10103c9
     field public static final int showSilent = 16843259; // 0x10101fb
     field public static final int showWeekNumber = 16843582; // 0x101033e
     field public static final int shownWeekCount = 16843585; // 0x1010341
     field public static final int shrinkColumns = 16843082; // 0x101014a
     field public static final deprecated int singleLine = 16843101; // 0x101015d
+    field public static final int singleUser = 16843711; // 0x10103bf
     field public static final int smallIcon = 16843422; // 0x101029e
     field public static final int smallScreens = 16843396; // 0x1010284
     field public static final int smoothScrollbar = 16843313; // 0x1010231
@@ -928,6 +970,7 @@
     field public static final int subtitle = 16843473; // 0x10102d1
     field public static final int subtitleTextStyle = 16843513; // 0x10102f9
     field public static final int subtypeExtraValue = 16843674; // 0x101039a
+    field public static final int subtypeId = 16843713; // 0x10103c1
     field public static final int subtypeLocale = 16843673; // 0x1010399
     field public static final int suggestActionMsg = 16843228; // 0x10101dc
     field public static final int suggestActionMsgColumn = 16843229; // 0x10101dd
@@ -935,6 +978,7 @@
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
+    field public static final int supportsRtl = 16843695; // 0x10103af
     field public static final int supportsUploading = 16843419; // 0x101029b
     field public static final int switchMinWidth = 16843632; // 0x1010370
     field public static final int switchPadding = 16843633; // 0x1010371
@@ -965,6 +1009,7 @@
     field public static final int tension = 16843370; // 0x101026a
     field public static final int testOnly = 16843378; // 0x1010272
     field public static final int text = 16843087; // 0x101014f
+    field public static final int textAlignment = 16843697; // 0x10103b1
     field public static final int textAllCaps = 16843660; // 0x101038c
     field public static final int textAppearance = 16842804; // 0x1010034
     field public static final int textAppearanceButton = 16843271; // 0x1010207
@@ -1004,6 +1049,7 @@
     field public static final int textColorTertiary = 16843282; // 0x1010212
     field public static final int textColorTertiaryInverse = 16843283; // 0x1010213
     field public static final int textCursorDrawable = 16843618; // 0x1010362
+    field public static final int textDirection = 16843696; // 0x10103b0
     field public static final int textEditNoPasteWindowLayout = 16843541; // 0x1010315
     field public static final int textEditPasteWindowLayout = 16843540; // 0x1010314
     field public static final int textEditSideNoPasteWindowLayout = 16843615; // 0x101035f
@@ -1030,6 +1076,7 @@
     field public static final int thumbTextPadding = 16843634; // 0x1010372
     field public static final int thumbnail = 16843429; // 0x10102a5
     field public static final int tileMode = 16843265; // 0x1010201
+    field public static final int timeZone = 16843724; // 0x10103cc
     field public static final int tint = 16843041; // 0x1010121
     field public static final int title = 16843233; // 0x10101e1
     field public static final int titleCondensed = 16843234; // 0x10101e2
@@ -1097,6 +1144,7 @@
     field public static final int weekNumberColor = 16843589; // 0x1010345
     field public static final int weekSeparatorLineColor = 16843590; // 0x1010346
     field public static final int weightSum = 16843048; // 0x1010128
+    field public static final int widgetCategory = 16843716; // 0x10103c4
     field public static final int widgetLayout = 16843243; // 0x10101eb
     field public static final int width = 16843097; // 0x1010159
     field public static final int windowActionBar = 16843469; // 0x10102cd
@@ -1745,6 +1793,7 @@
     field public static final int Widget_DeviceDefault_Button_Small = 16974146; // 0x1030142
     field public static final int Widget_DeviceDefault_Button_Toggle = 16974148; // 0x1030144
     field public static final int Widget_DeviceDefault_CalendarView = 16974190; // 0x103016e
+    field public static final int Widget_DeviceDefault_CheckedTextView = 16974299; // 0x10301db
     field public static final int Widget_DeviceDefault_CompoundButton_CheckBox = 16974152; // 0x1030148
     field public static final int Widget_DeviceDefault_CompoundButton_RadioButton = 16974169; // 0x1030159
     field public static final int Widget_DeviceDefault_CompoundButton_Star = 16974173; // 0x103015d
@@ -1778,6 +1827,7 @@
     field public static final int Widget_DeviceDefault_Light_Button_Small = 16974198; // 0x1030176
     field public static final int Widget_DeviceDefault_Light_Button_Toggle = 16974200; // 0x1030178
     field public static final int Widget_DeviceDefault_Light_CalendarView = 16974238; // 0x103019e
+    field public static final int Widget_DeviceDefault_Light_CheckedTextView = 16974300; // 0x10301dc
     field public static final int Widget_DeviceDefault_Light_CompoundButton_CheckBox = 16974204; // 0x103017c
     field public static final int Widget_DeviceDefault_Light_CompoundButton_RadioButton = 16974224; // 0x1030190
     field public static final int Widget_DeviceDefault_Light_CompoundButton_Star = 16974228; // 0x1030194
@@ -1863,6 +1913,7 @@
     field public static final int Widget_Holo_Button_Small = 16973964; // 0x103008c
     field public static final int Widget_Holo_Button_Toggle = 16973966; // 0x103008e
     field public static final int Widget_Holo_CalendarView = 16974060; // 0x10300ec
+    field public static final int Widget_Holo_CheckedTextView = 16974297; // 0x10301d9
     field public static final int Widget_Holo_CompoundButton_CheckBox = 16973969; // 0x1030091
     field public static final int Widget_Holo_CompoundButton_RadioButton = 16973986; // 0x10300a2
     field public static final int Widget_Holo_CompoundButton_Star = 16973990; // 0x10300a6
@@ -1896,6 +1947,7 @@
     field public static final int Widget_Holo_Light_Button_Small = 16974007; // 0x10300b7
     field public static final int Widget_Holo_Light_Button_Toggle = 16974009; // 0x10300b9
     field public static final int Widget_Holo_Light_CalendarView = 16974061; // 0x10300ed
+    field public static final int Widget_Holo_Light_CheckedTextView = 16974298; // 0x10301da
     field public static final int Widget_Holo_Light_CompoundButton_CheckBox = 16974012; // 0x10300bc
     field public static final int Widget_Holo_Light_CompoundButton_RadioButton = 16974032; // 0x10300d0
     field public static final int Widget_Holo_Light_CompoundButton_Star = 16974036; // 0x10300d4
@@ -2022,6 +2074,7 @@
     field public static final int GLOBAL_ACTION_BACK = 1; // 0x1
     field public static final int GLOBAL_ACTION_HOME = 2; // 0x2
     field public static final int GLOBAL_ACTION_NOTIFICATIONS = 4; // 0x4
+    field public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5; // 0x5
     field public static final int GLOBAL_ACTION_RECENTS = 3; // 0x3
     field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
     field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
@@ -2043,6 +2096,7 @@
     field public static final int DEFAULT = 1; // 0x1
     field public static final int FEEDBACK_ALL_MASK = -1; // 0xffffffff
     field public static final int FEEDBACK_AUDIBLE = 4; // 0x4
+    field public static final int FEEDBACK_BRAILLE = 32; // 0x20
     field public static final int FEEDBACK_GENERIC = 16; // 0x10
     field public static final int FEEDBACK_HAPTIC = 2; // 0x2
     field public static final int FEEDBACK_SPOKEN = 1; // 0x1
@@ -2627,6 +2681,7 @@
     method public void invalidateOptionsMenu();
     method public boolean isChangingConfigurations();
     method public final boolean isChild();
+    method public boolean isDestroyed();
     method public boolean isFinishing();
     method public boolean isTaskRoot();
     method public final deprecated android.database.Cursor managedQuery(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
@@ -2992,6 +3047,7 @@
     method public android.app.AlertDialog.Builder setNeutralButton(int, android.content.DialogInterface.OnClickListener);
     method public android.app.AlertDialog.Builder setNeutralButton(java.lang.CharSequence, android.content.DialogInterface.OnClickListener);
     method public android.app.AlertDialog.Builder setOnCancelListener(android.content.DialogInterface.OnCancelListener);
+    method public android.app.AlertDialog.Builder setOnDismissListener(android.content.DialogInterface.OnDismissListener);
     method public android.app.AlertDialog.Builder setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener);
     method public android.app.AlertDialog.Builder setOnKeyListener(android.content.DialogInterface.OnKeyListener);
     method public android.app.AlertDialog.Builder setPositiveButton(int, android.content.DialogInterface.OnClickListener);
@@ -3324,9 +3380,11 @@
     method public final boolean equals(java.lang.Object);
     method public final android.app.Activity getActivity();
     method public final android.os.Bundle getArguments();
+    method public final android.app.FragmentManager getChildFragmentManager();
     method public final android.app.FragmentManager getFragmentManager();
     method public final int getId();
     method public android.app.LoaderManager getLoaderManager();
+    method public final android.app.Fragment getParentFragment();
     method public final android.content.res.Resources getResources();
     method public final boolean getRetainInstance();
     method public final java.lang.String getString(int);
@@ -3375,6 +3433,7 @@
     method public void onStop();
     method public void onTrimMemory(int);
     method public void onViewCreated(android.view.View, android.os.Bundle);
+    method public void onViewStateRestored(android.os.Bundle);
     method public void registerForContextMenu(android.view.View);
     method public void setArguments(android.os.Bundle);
     method public void setHasOptionsMenu(boolean);
@@ -3430,6 +3489,7 @@
     method public abstract int getBackStackEntryCount();
     method public abstract android.app.Fragment getFragment(android.os.Bundle, java.lang.String);
     method public void invalidateOptionsMenu();
+    method public abstract boolean isDestroyed();
     method public abstract void popBackStack();
     method public abstract void popBackStack(java.lang.String, int);
     method public abstract void popBackStack(int, int);
@@ -3799,6 +3859,7 @@
     method public android.app.Notification.Builder setOnlyAlertOnce(boolean);
     method public android.app.Notification.Builder setPriority(int);
     method public android.app.Notification.Builder setProgress(int, int, boolean);
+    method public android.app.Notification.Builder setShowWhen(boolean);
     method public android.app.Notification.Builder setSmallIcon(int);
     method public android.app.Notification.Builder setSmallIcon(int, int);
     method public android.app.Notification.Builder setSound(android.net.Uri);
@@ -3848,9 +3909,12 @@
     method public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int);
     method public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int, android.os.Bundle);
     method public static android.app.PendingIntent getBroadcast(android.content.Context, int, android.content.Intent, int);
+    method public java.lang.String getCreatorPackage();
+    method public int getCreatorUid();
+    method public android.os.UserHandle getCreatorUserHandle();
     method public android.content.IntentSender getIntentSender();
     method public static android.app.PendingIntent getService(android.content.Context, int, android.content.Intent, int);
-    method public java.lang.String getTargetPackage();
+    method public deprecated java.lang.String getTargetPackage();
     method public static android.app.PendingIntent readPendingIntentOrNullFromParcel(android.os.Parcel);
     method public void send() throws android.app.PendingIntent.CanceledException;
     method public void send(int) throws android.app.PendingIntent.CanceledException;
@@ -3877,6 +3941,15 @@
     method public abstract void onSendFinished(android.app.PendingIntent, android.content.Intent, int, java.lang.String, android.os.Bundle);
   }
 
+  public class Presentation extends android.app.Dialog {
+    ctor public Presentation(android.content.Context, android.view.Display);
+    ctor public Presentation(android.content.Context, android.view.Display, int);
+    method public android.view.Display getDisplay();
+    method public android.content.res.Resources getResources();
+    method public void onDisplayChanged();
+    method public void onDisplayRemoved();
+  }
+
   public class ProgressDialog extends android.app.AlertDialog {
     ctor public ProgressDialog(android.content.Context);
     ctor public ProgressDialog(android.content.Context, int);
@@ -4105,6 +4178,7 @@
     method public android.graphics.drawable.Drawable getFastDrawable();
     method public static android.app.WallpaperManager getInstance(android.content.Context);
     method public android.app.WallpaperInfo getWallpaperInfo();
+    method public boolean hasResourceWallpaper(int);
     method public android.graphics.drawable.Drawable peekDrawable();
     method public android.graphics.drawable.Drawable peekFastDrawable();
     method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle);
@@ -4145,6 +4219,7 @@
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final int USES_ENCRYPTED_STORAGE = 7; // 0x7
     field public static final int USES_POLICY_DISABLE_CAMERA = 8; // 0x8
+    field public static final int USES_POLICY_DISABLE_KEYGUARD_FEATURES = 9; // 0x9
     field public static final int USES_POLICY_EXPIRE_PASSWORD = 6; // 0x6
     field public static final int USES_POLICY_FORCE_LOCK = 3; // 0x3
     field public static final int USES_POLICY_LIMIT_PASSWORD = 0; // 0x0
@@ -4180,6 +4255,7 @@
     method public java.util.List<android.content.ComponentName> getActiveAdmins();
     method public boolean getCameraDisabled(android.content.ComponentName);
     method public int getCurrentFailedPasswordAttempts();
+    method public int getKeyguardDisabledFeatures(android.content.ComponentName);
     method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
     method public long getMaximumTimeToLock(android.content.ComponentName);
     method public long getPasswordExpiration(android.content.ComponentName);
@@ -4203,6 +4279,7 @@
     method public void removeActiveAdmin(android.content.ComponentName);
     method public boolean resetPassword(java.lang.String, int);
     method public void setCameraDisabled(android.content.ComponentName, boolean);
+    method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
     method public void setMaximumTimeToLock(android.content.ComponentName, long);
     method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
@@ -4226,6 +4303,10 @@
     field public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0; // 0x0
     field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
     field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
+    field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff
+    field public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0; // 0x0
+    field public static final int KEYGUARD_DISABLE_SECURE_CAMERA = 2; // 0x2
+    field public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1; // 0x1
     field public static final int PASSWORD_QUALITY_ALPHABETIC = 262144; // 0x40000
     field public static final int PASSWORD_QUALITY_ALPHANUMERIC = 327680; // 0x50000
     field public static final int PASSWORD_QUALITY_BIOMETRIC_WEAK = 32768; // 0x8000
@@ -4333,6 +4414,7 @@
     method public void deleteHost();
     method protected android.appwidget.AppWidgetHostView onCreateView(android.content.Context, int, android.appwidget.AppWidgetProviderInfo);
     method protected void onProviderChanged(int, android.appwidget.AppWidgetProviderInfo);
+    method protected void onProvidersChanged();
     method public void startListening();
     method public void stopListening();
   }
@@ -4354,6 +4436,7 @@
 
   public class AppWidgetManager {
     method public boolean bindAppWidgetIdIfAllowed(int, android.content.ComponentName);
+    method public boolean bindAppWidgetIdIfAllowed(int, android.content.ComponentName, android.os.Bundle);
     method public int[] getAppWidgetIds(android.content.ComponentName);
     method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
     method public android.os.Bundle getAppWidgetOptions(int);
@@ -4383,6 +4466,7 @@
     field public static final java.lang.String EXTRA_CUSTOM_INFO = "customInfo";
     field public static final int INVALID_APPWIDGET_ID = 0; // 0x0
     field public static final java.lang.String META_DATA_APPWIDGET_PROVIDER = "android.appwidget.provider";
+    field public static final java.lang.String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory";
     field public static final java.lang.String OPTION_APPWIDGET_MAX_HEIGHT = "appWidgetMaxHeight";
     field public static final java.lang.String OPTION_APPWIDGET_MAX_WIDTH = "appWidgetMaxWidth";
     field public static final java.lang.String OPTION_APPWIDGET_MIN_HEIGHT = "appWidgetMinHeight";
@@ -4402,6 +4486,7 @@
   public class AppWidgetProviderInfo implements android.os.Parcelable {
     ctor public AppWidgetProviderInfo();
     ctor public AppWidgetProviderInfo(android.os.Parcel);
+    method public android.appwidget.AppWidgetProviderInfo clone();
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
@@ -4409,9 +4494,12 @@
     field public static final int RESIZE_HORIZONTAL = 1; // 0x1
     field public static final int RESIZE_NONE = 0; // 0x0
     field public static final int RESIZE_VERTICAL = 2; // 0x2
+    field public static final int WIDGET_CATEGORY_HOME_SCREEN = 1; // 0x1
+    field public static final int WIDGET_CATEGORY_KEYGUARD = 2; // 0x2
     field public int autoAdvanceViewId;
     field public android.content.ComponentName configure;
     field public int icon;
+    field public int initialKeyguardLayout;
     field public int initialLayout;
     field public java.lang.String label;
     field public int minHeight;
@@ -4422,6 +4510,7 @@
     field public android.content.ComponentName provider;
     field public int resizeMode;
     field public int updatePeriodMillis;
+    field public int widgetCategory;
   }
 
 }
@@ -4429,6 +4518,7 @@
 package android.bluetooth {
 
   public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
+    method public void finalize();
     method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
     method public int getConnectionState(android.bluetooth.BluetoothDevice);
     method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
@@ -5054,6 +5144,7 @@
   public class ContentProviderClient {
     method public android.content.ContentProviderResult[] applyBatch(java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException;
     method public int bulkInsert(android.net.Uri, android.content.ContentValues[]) throws android.os.RemoteException;
+    method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle) throws android.os.RemoteException;
     method public int delete(android.net.Uri, java.lang.String, java.lang.String[]) throws android.os.RemoteException;
     method public android.content.ContentProvider getLocalContentProvider();
     method public java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String) throws android.os.RemoteException;
@@ -5240,6 +5331,8 @@
     method public abstract int checkUriPermission(android.net.Uri, int, int, int);
     method public abstract int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public abstract deprecated void clearWallpaper() throws java.io.IOException;
+    method public abstract android.content.Context createConfigurationContext(android.content.res.Configuration);
+    method public abstract android.content.Context createDisplayContext(android.view.Display);
     method public abstract android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract java.lang.String[] databaseList();
     method public abstract boolean deleteDatabase(java.lang.String);
@@ -5295,13 +5388,19 @@
     method public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter);
     method public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler);
     method public abstract void removeStickyBroadcast(android.content.Intent);
+    method public abstract void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
     method public abstract void revokeUriPermission(android.net.Uri, int);
     method public abstract void sendBroadcast(android.content.Intent);
     method public abstract void sendBroadcast(android.content.Intent, java.lang.String);
+    method public abstract void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+    method public abstract void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String);
     method public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String);
     method public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public abstract void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
     method public abstract void sendStickyBroadcast(android.content.Intent);
+    method public abstract void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
     method public abstract void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public abstract void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
     method public abstract void setTheme(int);
     method public abstract deprecated void setWallpaper(android.graphics.Bitmap) throws java.io.IOException;
     method public abstract deprecated void setWallpaper(java.io.InputStream) throws java.io.IOException;
@@ -5336,6 +5435,7 @@
     field public static final int CONTEXT_INCLUDE_CODE = 1; // 0x1
     field public static final int CONTEXT_RESTRICTED = 4; // 0x4
     field public static final java.lang.String DEVICE_POLICY_SERVICE = "device_policy";
+    field public static final java.lang.String DISPLAY_SERVICE = "display";
     field public static final java.lang.String DOWNLOAD_SERVICE = "download";
     field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
@@ -5348,8 +5448,8 @@
     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
-    field public static final int MODE_WORLD_WRITEABLE = 2; // 0x2
+    field public static final deprecated int MODE_WORLD_READABLE = 1; // 0x1
+    field public static final deprecated int MODE_WORLD_WRITEABLE = 2; // 0x2
     field public static final java.lang.String NFC_SERVICE = "nfc";
     field public static final java.lang.String NOTIFICATION_SERVICE = "notification";
     field public static final java.lang.String NSD_SERVICE = "servicediscovery";
@@ -5361,6 +5461,7 @@
     field public static final java.lang.String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
     field public static final java.lang.String UI_MODE_SERVICE = "uimode";
     field public static final java.lang.String USB_SERVICE = "usb";
+    field public static final java.lang.String USER_SERVICE = "user";
     field public static final java.lang.String VIBRATOR_SERVICE = "vibrator";
     field public static final java.lang.String WALLPAPER_SERVICE = "wallpaper";
     field public static final java.lang.String WIFI_P2P_SERVICE = "wifip2p";
@@ -5380,6 +5481,8 @@
     method public int checkUriPermission(android.net.Uri, int, int, int);
     method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public void clearWallpaper() throws java.io.IOException;
+    method public android.content.Context createConfigurationContext(android.content.res.Configuration);
+    method public android.content.Context createDisplayContext(android.view.Display);
     method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] databaseList();
     method public boolean deleteDatabase(java.lang.String);
@@ -5427,13 +5530,19 @@
     method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter);
     method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler);
     method public void removeStickyBroadcast(android.content.Intent);
+    method public void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
     method public void revokeUriPermission(android.net.Uri, int);
     method public void sendBroadcast(android.content.Intent);
     method public void sendBroadcast(android.content.Intent, java.lang.String);
+    method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+    method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String);
     method public void sendOrderedBroadcast(android.content.Intent, java.lang.String);
     method public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
     method public void sendStickyBroadcast(android.content.Intent);
+    method public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
     method public void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
     method public void setTheme(int);
     method public void setWallpaper(android.graphics.Bitmap) throws java.io.IOException;
     method public void setWallpaper(java.io.InputStream) throws java.io.IOException;
@@ -5674,6 +5783,8 @@
     field public static final java.lang.String ACTION_DEVICE_STORAGE_OK = "android.intent.action.DEVICE_STORAGE_OK";
     field public static final java.lang.String ACTION_DIAL = "android.intent.action.DIAL";
     field public static final java.lang.String ACTION_DOCK_EVENT = "android.intent.action.DOCK_EVENT";
+    field public static final java.lang.String ACTION_DREAMING_STARTED = "android.intent.action.DREAMING_STARTED";
+    field public static final java.lang.String ACTION_DREAMING_STOPPED = "android.intent.action.DREAMING_STOPPED";
     field public static final java.lang.String ACTION_EDIT = "android.intent.action.EDIT";
     field public static final java.lang.String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE";
     field public static final java.lang.String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE";
@@ -5715,6 +5826,7 @@
     field public static final java.lang.String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED";
     field public static final java.lang.String ACTION_PACKAGE_REPLACED = "android.intent.action.PACKAGE_REPLACED";
     field public static final java.lang.String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED";
+    field public static final java.lang.String ACTION_PACKAGE_VERIFIED = "android.intent.action.PACKAGE_VERIFIED";
     field public static final java.lang.String ACTION_PASTE = "android.intent.action.PASTE";
     field public static final java.lang.String ACTION_PICK = "android.intent.action.PICK";
     field public static final java.lang.String ACTION_PICK_ACTIVITY = "android.intent.action.PICK_ACTIVITY";
@@ -5722,6 +5834,7 @@
     field public static final java.lang.String ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED";
     field public static final java.lang.String ACTION_POWER_USAGE_SUMMARY = "android.intent.action.POWER_USAGE_SUMMARY";
     field public static final java.lang.String ACTION_PROVIDER_CHANGED = "android.intent.action.PROVIDER_CHANGED";
+    field public static final java.lang.String ACTION_QUICK_CLOCK = "android.intent.action.QUICK_CLOCK";
     field public static final java.lang.String ACTION_REBOOT = "android.intent.action.REBOOT";
     field public static final java.lang.String ACTION_RUN = "android.intent.action.RUN";
     field public static final java.lang.String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF";
@@ -5742,6 +5855,9 @@
     field public static final deprecated java.lang.String ACTION_UMS_CONNECTED = "android.intent.action.UMS_CONNECTED";
     field public static final deprecated java.lang.String ACTION_UMS_DISCONNECTED = "android.intent.action.UMS_DISCONNECTED";
     field public static final java.lang.String ACTION_UNINSTALL_PACKAGE = "android.intent.action.UNINSTALL_PACKAGE";
+    field public static final java.lang.String ACTION_USER_BACKGROUND = "android.intent.action.USER_BACKGROUND";
+    field public static final java.lang.String ACTION_USER_FOREGROUND = "android.intent.action.USER_FOREGROUND";
+    field public static final java.lang.String ACTION_USER_INITIALIZE = "android.intent.action.USER_INITIALIZE";
     field public static final java.lang.String ACTION_USER_PRESENT = "android.intent.action.USER_PRESENT";
     field public static final java.lang.String ACTION_VIEW = "android.intent.action.VIEW";
     field public static final java.lang.String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND";
@@ -5805,7 +5921,9 @@
     field public static final java.lang.String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT";
     field public static final java.lang.String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY";
     field public static final java.lang.String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
+    field public static final java.lang.String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI";
     field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
+    field public static final java.lang.String EXTRA_REFERRER = "android.intent.extra.REFERRER";
     field public static final java.lang.String EXTRA_REMOTE_INTENT_TOKEN = "android.intent.extra.remote_intent_token";
     field public static final java.lang.String EXTRA_REPLACING = "android.intent.extra.REPLACING";
     field public static final java.lang.String EXTRA_RETURN_RESULT = "android.intent.extra.RETURN_RESULT";
@@ -5953,7 +6071,10 @@
 
   public class IntentSender implements android.os.Parcelable {
     method public int describeContents();
-    method public java.lang.String getTargetPackage();
+    method public java.lang.String getCreatorPackage();
+    method public int getCreatorUid();
+    method public android.os.UserHandle getCreatorUserHandle();
+    method public deprecated java.lang.String getTargetPackage();
     method public static android.content.IntentSender readIntentSenderOrNullFromParcel(android.os.Parcel);
     method public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender.OnFinished, android.os.Handler) throws android.content.IntentSender.SendIntentException;
     method public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender.OnFinished, android.os.Handler, java.lang.String) throws android.content.IntentSender.SendIntentException;
@@ -6186,9 +6307,11 @@
     method public int describeContents();
     method public void dump(android.util.Printer, java.lang.String);
     method public final int getThemeResource();
+    field public static final int CONFIG_DENSITY = 4096; // 0x1000
     field public static final int CONFIG_FONT_SCALE = 1073741824; // 0x40000000
     field public static final int CONFIG_KEYBOARD = 16; // 0x10
     field public static final int CONFIG_KEYBOARD_HIDDEN = 32; // 0x20
+    field public static final int CONFIG_LAYOUT_DIRECTION = 8192; // 0x2000
     field public static final int CONFIG_LOCALE = 4; // 0x4
     field public static final int CONFIG_MCC = 1; // 0x1
     field public static final int CONFIG_MNC = 2; // 0x2
@@ -6209,6 +6332,7 @@
     field public static final int FLAG_HARDWARE_ACCELERATED = 512; // 0x200
     field public static final int FLAG_MULTIPROCESS = 1; // 0x1
     field public static final int FLAG_NO_HISTORY = 128; // 0x80
+    field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000
     field public static final int FLAG_STATE_NOT_NEEDED = 16; // 0x10
     field public static final int LAUNCH_MULTIPLE = 0; // 0x0
     field public static final int LAUNCH_SINGLE_INSTANCE = 3; // 0x3
@@ -6254,6 +6378,8 @@
     field public static final int FLAG_EXTERNAL_STORAGE = 262144; // 0x40000
     field public static final int FLAG_FACTORY_TEST = 16; // 0x10
     field public static final int FLAG_HAS_CODE = 4; // 0x4
+    field public static final int FLAG_INSTALLED = 8388608; // 0x800000
+    field public static final int FLAG_IS_DATA_ONLY = 16777216; // 0x1000000
     field public static final int FLAG_KILL_AFTER_RESTORE = 65536; // 0x10000
     field public static final int FLAG_LARGE_HEAP = 1048576; // 0x100000
     field public static final int FLAG_PERSISTENT = 8; // 0x8
@@ -6262,6 +6388,7 @@
     field public static final int FLAG_STOPPED = 2097152; // 0x200000
     field public static final int FLAG_SUPPORTS_LARGE_SCREENS = 2048; // 0x800
     field public static final int FLAG_SUPPORTS_NORMAL_SCREENS = 1024; // 0x400
+    field public static final int FLAG_SUPPORTS_RTL = 4194304; // 0x400000
     field public static final int FLAG_SUPPORTS_SCREEN_DENSITIES = 8192; // 0x2000
     field public static final int FLAG_SUPPORTS_SMALL_SCREENS = 512; // 0x200
     field public static final int FLAG_SUPPORTS_XLARGE_SCREENS = 524288; // 0x80000
@@ -6434,6 +6561,7 @@
     method public abstract int checkSignatures(int, int);
     method public abstract void clearPackagePreferredActivities(java.lang.String);
     method public abstract java.lang.String[] currentToCanonicalPackageNames(java.lang.String[]);
+    method public abstract void extendVerificationTimeout(int, int, long);
     method public abstract android.graphics.drawable.Drawable getActivityIcon(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.graphics.drawable.Drawable getActivityIcon(android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.pm.ActivityInfo getActivityInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -6498,9 +6626,11 @@
     field public static final int COMPONENT_ENABLED_STATE_ENABLED = 1; // 0x1
     field public static final int DONT_KILL_APP = 1; // 0x1
     field public static final java.lang.String EXTRA_VERIFICATION_ID = "android.content.pm.extra.VERIFICATION_ID";
+    field public static final java.lang.String EXTRA_VERIFICATION_RESULT = "android.content.pm.extra.VERIFICATION_RESULT";
     field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency";
     field public static final java.lang.String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
     field public static final java.lang.String FEATURE_CAMERA = "android.hardware.camera";
+    field public static final java.lang.String FEATURE_CAMERA_ANY = "android.hardware.camera.any";
     field public static final java.lang.String FEATURE_CAMERA_AUTOFOCUS = "android.hardware.camera.autofocus";
     field public static final java.lang.String FEATURE_CAMERA_FLASH = "android.hardware.camera.flash";
     field public static final java.lang.String FEATURE_CAMERA_FRONT = "android.hardware.camera.front";
@@ -6552,6 +6682,7 @@
     field public static final int GET_UNINSTALLED_PACKAGES = 8192; // 0x2000
     field public static final int GET_URI_PERMISSION_PATTERNS = 2048; // 0x800
     field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
+    field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L
     field public static final int PERMISSION_DENIED = -1; // 0xffffffff
     field public static final int PERMISSION_GRANTED = 0; // 0x0
     field public static final int SIGNATURE_FIRST_NOT_SIGNED = -1; // 0xffffffff
@@ -6601,8 +6732,11 @@
     method public int describeContents();
     method public java.lang.CharSequence loadDescription(android.content.pm.PackageManager);
     field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_PERSONAL_INFO = 1; // 0x1
     field public int descriptionRes;
+    field public int flags;
     field public java.lang.CharSequence nonLocalizedDescription;
+    field public int priority;
   }
 
   public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
@@ -6611,6 +6745,7 @@
     method public int describeContents();
     method public java.lang.CharSequence loadDescription(android.content.pm.PackageManager);
     field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_COSTS_MONEY = 1; // 0x1
     field public static final int PROTECTION_DANGEROUS = 1; // 0x1
     field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20
     field public static final int PROTECTION_FLAG_SYSTEM = 16; // 0x10
@@ -6620,6 +6755,7 @@
     field public static final int PROTECTION_SIGNATURE = 2; // 0x2
     field public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3; // 0x3
     field public int descriptionRes;
+    field public int flags;
     field public java.lang.String group;
     field public java.lang.CharSequence nonLocalizedDescription;
     field public int protectionLevel;
@@ -6630,7 +6766,9 @@
     ctor public ProviderInfo(android.content.pm.ProviderInfo);
     method public int describeContents();
     field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000
     field public java.lang.String authority;
+    field public int flags;
     field public boolean grantUriPermissions;
     field public int initOrder;
     field public deprecated boolean isSyncable;
@@ -6643,6 +6781,7 @@
 
   public class ResolveInfo implements android.os.Parcelable {
     ctor public ResolveInfo();
+    ctor public ResolveInfo(android.content.pm.ResolveInfo);
     method public int describeContents();
     method public void dump(android.util.Printer, java.lang.String);
     method public final int getIconResource();
@@ -6676,6 +6815,7 @@
     method public void dump(android.util.Printer, java.lang.String);
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final int FLAG_ISOLATED_PROCESS = 2; // 0x2
+    field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000
     field public static final int FLAG_STOP_WITH_TASK = 1; // 0x1
     field public int flags;
     field public java.lang.String permission;
@@ -6771,14 +6911,18 @@
     method public int describeContents();
     method public int diff(android.content.res.Configuration);
     method public boolean equals(android.content.res.Configuration);
+    method public int getLayoutDirection();
     method public boolean isLayoutSizeAtLeast(int);
     method public static boolean needNewResources(int, int);
     method public void readFromParcel(android.os.Parcel);
+    method public void setLayoutDirection(java.util.Locale);
+    method public void setLocale(java.util.Locale);
     method public void setTo(android.content.res.Configuration);
     method public void setToDefaults();
     method public int updateFrom(android.content.res.Configuration);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int DENSITY_DPI_UNDEFINED = 0; // 0x0
     field public static final int HARDKEYBOARDHIDDEN_NO = 1; // 0x1
     field public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0; // 0x0
     field public static final int HARDKEYBOARDHIDDEN_YES = 2; // 0x2
@@ -6801,6 +6945,11 @@
     field public static final int ORIENTATION_PORTRAIT = 1; // 0x1
     field public static final deprecated int ORIENTATION_SQUARE = 3; // 0x3
     field public static final int ORIENTATION_UNDEFINED = 0; // 0x0
+    field public static final int SCREENLAYOUT_LAYOUTDIR_LTR = 64; // 0x40
+    field public static final int SCREENLAYOUT_LAYOUTDIR_MASK = 192; // 0xc0
+    field public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 128; // 0x80
+    field public static final int SCREENLAYOUT_LAYOUTDIR_SHIFT = 6; // 0x6
+    field public static final int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0; // 0x0
     field public static final int SCREENLAYOUT_LONG_MASK = 48; // 0x30
     field public static final int SCREENLAYOUT_LONG_NO = 16; // 0x10
     field public static final int SCREENLAYOUT_LONG_UNDEFINED = 0; // 0x0
@@ -6811,6 +6960,7 @@
     field public static final int SCREENLAYOUT_SIZE_SMALL = 1; // 0x1
     field public static final int SCREENLAYOUT_SIZE_UNDEFINED = 0; // 0x0
     field public static final int SCREENLAYOUT_SIZE_XLARGE = 4; // 0x4
+    field public static final int SCREENLAYOUT_UNDEFINED = 0; // 0x0
     field public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0; // 0x0
     field public static final int SCREEN_WIDTH_DP_UNDEFINED = 0; // 0x0
     field public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0; // 0x0
@@ -6829,6 +6979,7 @@
     field public static final int UI_MODE_TYPE_NORMAL = 1; // 0x1
     field public static final int UI_MODE_TYPE_TELEVISION = 4; // 0x4
     field public static final int UI_MODE_TYPE_UNDEFINED = 0; // 0x0
+    field public int densityDpi;
     field public float fontScale;
     field public int hardKeyboardHidden;
     field public int keyboard;
@@ -7307,7 +7458,7 @@
     field public static final int STATEMENT_UPDATE = 2; // 0x2
   }
 
-  public static class DatabaseUtils.InsertHelper {
+  public static deprecated class DatabaseUtils.InsertHelper {
     ctor public DatabaseUtils.InsertHelper(android.database.sqlite.SQLiteDatabase, java.lang.String);
     method public void bind(int, double);
     method public void bind(int, float);
@@ -7324,7 +7475,6 @@
     method public void prepareForInsert();
     method public void prepareForReplace();
     method public long replace(android.content.ContentValues);
-    field public static final int TABLE_INFO_PRAGMA_DEFAULT_INDEX = 4; // 0x4
   }
 
   public final class DefaultDatabaseErrorHandler implements android.database.DatabaseErrorHandler {
@@ -8085,8 +8235,11 @@
     method public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap, int, int, int, int);
     method public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap, int, int, int, int, android.graphics.Matrix, boolean);
     method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config);
+    method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config);
     method public static android.graphics.Bitmap createBitmap(int[], int, int, int, int, android.graphics.Bitmap.Config);
+    method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int[], int, int, int, int, android.graphics.Bitmap.Config);
     method public static android.graphics.Bitmap createBitmap(int[], int, int, android.graphics.Bitmap.Config);
+    method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int[], int, int, android.graphics.Bitmap.Config);
     method public static android.graphics.Bitmap createScaledBitmap(android.graphics.Bitmap, int, int, boolean);
     method public int describeContents();
     method public void eraseColor(int);
@@ -8109,13 +8262,16 @@
     method public int getScaledWidth(int);
     method public final int getWidth();
     method public final boolean hasAlpha();
+    method public final boolean hasMipMap();
     method public final boolean isMutable();
+    method public final boolean isPremultiplied();
     method public final boolean isRecycled();
     method public void prepareToDraw();
     method public void recycle();
     method public boolean sameAs(android.graphics.Bitmap);
     method public void setDensity(int);
     method public void setHasAlpha(boolean);
+    method public final void setHasMipMap(boolean);
     method public void setPixel(int, int, int);
     method public void setPixels(int[], int, int, int, int, int, int);
     method public void writeToParcel(android.os.Parcel, int);
@@ -8599,6 +8755,7 @@
     method public android.graphics.Paint.Align getTextAlign();
     method public void getTextBounds(java.lang.String, int, int, android.graphics.Rect);
     method public void getTextBounds(char[], int, int, android.graphics.Rect);
+    method public java.util.Locale getTextLocale();
     method public void getTextPath(char[], int, int, float, float, android.graphics.Path);
     method public void getTextPath(java.lang.String, int, int, float, float, android.graphics.Path);
     method public float getTextScaleX();
@@ -8648,6 +8805,7 @@
     method public void setStyle(android.graphics.Paint.Style);
     method public void setSubpixelText(boolean);
     method public void setTextAlign(android.graphics.Paint.Align);
+    method public void setTextLocale(java.util.Locale);
     method public void setTextScaleX(float);
     method public void setTextSize(float);
     method public void setTextSkewX(float);
@@ -9547,6 +9705,7 @@
     method public final void addCallbackBuffer(byte[]);
     method public final void autoFocus(android.hardware.Camera.AutoFocusCallback);
     method public final void cancelAutoFocus();
+    method public final boolean enableShutterSound(boolean);
     method public static void getCameraInfo(int, android.hardware.Camera.CameraInfo);
     method public static int getNumberOfCameras();
     method public android.hardware.Camera.Parameters getParameters();
@@ -9599,6 +9758,7 @@
     ctor public Camera.CameraInfo();
     field public static final int CAMERA_FACING_BACK = 0; // 0x0
     field public static final int CAMERA_FACING_FRONT = 1; // 0x1
+    field public boolean canDisableShutterSound;
     field public int facing;
     field public int orientation;
   }
@@ -9754,6 +9914,7 @@
     field public static final java.lang.String SCENE_MODE_BEACH = "beach";
     field public static final java.lang.String SCENE_MODE_CANDLELIGHT = "candlelight";
     field public static final java.lang.String SCENE_MODE_FIREWORKS = "fireworks";
+    field public static final java.lang.String SCENE_MODE_HDR = "hdr";
     field public static final java.lang.String SCENE_MODE_LANDSCAPE = "landscape";
     field public static final java.lang.String SCENE_MODE_NIGHT = "night";
     field public static final java.lang.String SCENE_MODE_NIGHT_PORTRAIT = "night-portrait";
@@ -9803,7 +9964,7 @@
     method public float getZ();
   }
 
-  public class Sensor {
+  public final class Sensor {
     method public float getMaximumRange();
     method public int getMinDelay();
     method public java.lang.String getName();
@@ -9926,6 +10087,25 @@
 
 }
 
+package android.hardware.display {
+
+  public final class DisplayManager {
+    method public android.view.Display getDisplay(int);
+    method public android.view.Display[] getDisplays();
+    method public android.view.Display[] getDisplays(java.lang.String);
+    method public void registerDisplayListener(android.hardware.display.DisplayManager.DisplayListener, android.os.Handler);
+    method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
+    field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
+  }
+
+  public static abstract interface DisplayManager.DisplayListener {
+    method public abstract void onDisplayAdded(int);
+    method public abstract void onDisplayChanged(int);
+    method public abstract void onDisplayRemoved(int);
+  }
+
+}
+
 package android.hardware.input {
 
   public final class InputManager {
@@ -10089,6 +10269,7 @@
     method public final android.os.IBinder onBind(android.content.Intent);
     method public abstract android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodImpl onCreateInputMethodInterface();
     method public abstract android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface();
+    method public boolean onGenericMotionEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
   }
 
@@ -10101,6 +10282,7 @@
 
   public abstract class AbstractInputMethodService.AbstractInputMethodSessionImpl implements android.view.inputmethod.InputMethodSession {
     ctor public AbstractInputMethodService.AbstractInputMethodSessionImpl();
+    method public void dispatchGenericMotionEvent(int, android.view.MotionEvent, android.view.inputmethod.InputMethodSession.EventCallback);
     method public void dispatchKeyEvent(int, android.view.KeyEvent, android.view.inputmethod.InputMethodSession.EventCallback);
     method public void dispatchTrackballEvent(int, android.view.MotionEvent, android.view.inputmethod.InputMethodSession.EventCallback);
     method public boolean isEnabled();
@@ -10120,6 +10302,7 @@
 
   public class InputMethodService extends android.inputmethodservice.AbstractInputMethodService {
     ctor public InputMethodService();
+    method public boolean enableHardwareAcceleration();
     method public int getBackDisposition();
     method public int getCandidatesHiddenVisibility();
     method public android.view.inputmethod.InputBinding getCurrentInputBinding();
@@ -10486,6 +10669,7 @@
     method public float getAccuracy();
     method public double getAltitude();
     method public float getBearing();
+    method public long getElapsedRealtimeNanos();
     method public android.os.Bundle getExtras();
     method public double getLatitude();
     method public double getLongitude();
@@ -10505,6 +10689,7 @@
     method public void setAccuracy(float);
     method public void setAltitude(double);
     method public void setBearing(float);
+    method public void setElapsedRealtimeNanos(long);
     method public void setExtras(android.os.Bundle);
     method public void setLatitude(double);
     method public void setLongitude(double);
@@ -10570,18 +10755,18 @@
     field public static final java.lang.String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";
   }
 
-  public abstract class LocationProvider {
-    method public abstract int getAccuracy();
+  public class LocationProvider {
+    method public int getAccuracy();
     method public java.lang.String getName();
-    method public abstract int getPowerRequirement();
-    method public abstract boolean hasMonetaryCost();
+    method public int getPowerRequirement();
+    method public boolean hasMonetaryCost();
     method public boolean meetsCriteria(android.location.Criteria);
-    method public abstract boolean requiresCell();
-    method public abstract boolean requiresNetwork();
-    method public abstract boolean requiresSatellite();
-    method public abstract boolean supportsAltitude();
-    method public abstract boolean supportsBearing();
-    method public abstract boolean supportsSpeed();
+    method public boolean requiresCell();
+    method public boolean requiresNetwork();
+    method public boolean requiresSatellite();
+    method public boolean supportsAltitude();
+    method public boolean supportsBearing();
+    method public boolean supportsSpeed();
     field public static final int AVAILABLE = 2; // 0x2
     field public static final int OUT_OF_SERVICE = 0; // 0x0
     field public static final int TEMPORARILY_UNAVAILABLE = 1; // 0x1
@@ -10650,6 +10835,7 @@
     method public void adjustVolume(int, int);
     method public int getMode();
     method public java.lang.String getParameters(java.lang.String);
+    method public java.lang.String getProperty(java.lang.String);
     method public int getRingerMode();
     method public deprecated int getRouting(int);
     method public int getStreamMaxVolume(int);
@@ -10727,6 +10913,8 @@
     field public static final int MODE_NORMAL = 0; // 0x0
     field public static final int MODE_RINGTONE = 1; // 0x1
     field public static final deprecated int NUM_STREAMS = 5; // 0x5
+    field public static final java.lang.String PROPERTY_OUTPUT_FRAMES_PER_BUFFER = "android.media.property.OUTPUT_FRAMES_PER_BUFFER";
+    field public static final java.lang.String PROPERTY_OUTPUT_SAMPLE_RATE = "android.media.property.OUTPUT_SAMPLE_RATE";
     field public static final java.lang.String RINGER_MODE_CHANGED_ACTION = "android.media.RINGER_MODE_CHANGED";
     field public static final int RINGER_MODE_NORMAL = 2; // 0x2
     field public static final int RINGER_MODE_SILENT = 0; // 0x0
@@ -11305,6 +11493,7 @@
     field public static final int METADATA_KEY_NUM_TRACKS = 10; // 0xa
     field public static final int METADATA_KEY_TITLE = 7; // 0x7
     field public static final int METADATA_KEY_VIDEO_HEIGHT = 19; // 0x13
+    field public static final int METADATA_KEY_VIDEO_ROTATION = 24; // 0x18
     field public static final int METADATA_KEY_VIDEO_WIDTH = 18; // 0x12
     field public static final int METADATA_KEY_WRITER = 11; // 0xb
     field public static final int METADATA_KEY_YEAR = 8; // 0x8
@@ -11366,15 +11555,20 @@
     method public void setWakeMode(android.content.Context, int);
     method public void start() throws java.lang.IllegalStateException;
     method public void stop() throws java.lang.IllegalStateException;
+    field public static final int MEDIA_ERROR_IO = -1004; // 0xfffffc14
+    field public static final int MEDIA_ERROR_MALFORMED = -1007; // 0xfffffc11
     field public static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200; // 0xc8
     field public static final int MEDIA_ERROR_SERVER_DIED = 100; // 0x64
+    field public static final int MEDIA_ERROR_TIMED_OUT = -110; // 0xffffff92
     field public static final int MEDIA_ERROR_UNKNOWN = 1; // 0x1
+    field public static final int MEDIA_ERROR_UNSUPPORTED = -1010; // 0xfffffc0e
     field public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; // 0x320
     field public static final int MEDIA_INFO_BUFFERING_END = 702; // 0x2be
     field public static final int MEDIA_INFO_BUFFERING_START = 701; // 0x2bd
     field public static final int MEDIA_INFO_METADATA_UPDATE = 802; // 0x322
     field public static final int MEDIA_INFO_NOT_SEEKABLE = 801; // 0x321
     field public static final int MEDIA_INFO_UNKNOWN = 1; // 0x1
+    field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
     field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
     field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
     field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT = 1; // 0x1
@@ -11456,6 +11650,7 @@
     method public void setVideoSource(int) throws java.lang.IllegalStateException;
     method public void start() throws java.lang.IllegalStateException;
     method public void stop() throws java.lang.IllegalStateException;
+    field public static final int MEDIA_ERROR_SERVER_DIED = 100; // 0x64
     field public static final int MEDIA_RECORDER_ERROR_UNKNOWN = 1; // 0x1
     field public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800; // 0x320
     field public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801; // 0x321
@@ -11528,6 +11723,7 @@
     method public void removeUserRoute(android.media.MediaRouter.UserRouteInfo);
     method public void selectRoute(int, android.media.MediaRouter.RouteInfo);
     field public static final int ROUTE_TYPE_LIVE_AUDIO = 1; // 0x1
+    field public static final int ROUTE_TYPE_LIVE_VIDEO = 2; // 0x2
     field public static final int ROUTE_TYPE_USER = 8388608; // 0x800000
   }
 
@@ -11536,6 +11732,7 @@
     method public abstract void onRouteAdded(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
     method public abstract void onRouteChanged(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
     method public abstract void onRouteGrouped(android.media.MediaRouter, android.media.MediaRouter.RouteInfo, android.media.MediaRouter.RouteGroup, int);
+    method public void onRoutePresentationDisplayChanged(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
     method public abstract void onRouteRemoved(android.media.MediaRouter, android.media.MediaRouter.RouteInfo);
     method public abstract void onRouteSelected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo);
     method public abstract void onRouteUngrouped(android.media.MediaRouter, android.media.MediaRouter.RouteInfo, android.media.MediaRouter.RouteGroup);
@@ -11570,12 +11767,14 @@
     method public java.lang.CharSequence getName(android.content.Context);
     method public int getPlaybackStream();
     method public int getPlaybackType();
+    method public android.view.Display getPresentationDisplay();
     method public java.lang.CharSequence getStatus();
     method public int getSupportedTypes();
     method public java.lang.Object getTag();
     method public int getVolume();
     method public int getVolumeHandling();
     method public int getVolumeMax();
+    method public boolean isEnabled();
     method public void requestSetVolume(int);
     method public void requestUpdateVolume(int);
     method public void setTag(java.lang.Object);
@@ -12353,6 +12552,7 @@
     field public static final java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
     field public static final java.lang.String EXTRA_IS_FAILOVER = "isFailover";
     field public static final deprecated java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
+    field public static final java.lang.String EXTRA_NETWORK_TYPE = "networkType";
     field public static final java.lang.String EXTRA_NO_CONNECTIVITY = "noConnectivity";
     field public static final java.lang.String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
     field public static final java.lang.String EXTRA_REASON = "reason";
@@ -12397,7 +12597,7 @@
     method public android.net.LocalSocketAddress getLocalSocketAddress();
   }
 
-  public class LocalSocket {
+  public class LocalSocket implements java.io.Closeable {
     ctor public LocalSocket();
     method public void bind(android.net.LocalSocketAddress) throws java.io.IOException;
     method public void close() throws java.io.IOException;
@@ -12475,6 +12675,7 @@
     method public static final android.net.NetworkInfo.DetailedState[] values();
     enum_constant public static final android.net.NetworkInfo.DetailedState AUTHENTICATING;
     enum_constant public static final android.net.NetworkInfo.DetailedState BLOCKED;
+    enum_constant public static final android.net.NetworkInfo.DetailedState CAPTIVE_PORTAL_CHECK;
     enum_constant public static final android.net.NetworkInfo.DetailedState CONNECTED;
     enum_constant public static final android.net.NetworkInfo.DetailedState CONNECTING;
     enum_constant public static final android.net.NetworkInfo.DetailedState DISCONNECTED;
@@ -12525,9 +12726,11 @@
     method public static javax.net.ssl.SSLSocketFactory getInsecure(int, android.net.SSLSessionCache);
     method public byte[] getNpnSelectedProtocol(java.net.Socket);
     method public java.lang.String[] getSupportedCipherSuites();
+    method public void setHostname(java.net.Socket, java.lang.String);
     method public void setKeyManagers(javax.net.ssl.KeyManager[]);
     method public void setNpnProtocols(byte[][]);
     method public void setTrustManagers(javax.net.ssl.TrustManager[]);
+    method public void setUseSessionTickets(java.net.Socket, boolean);
   }
 
   public final class SSLSessionCache {
@@ -12812,6 +13015,11 @@
     field public static final int SSL_UNTRUSTED = 3; // 0x3
   }
 
+  public class X509TrustManagerExtensions {
+    ctor public X509TrustManagerExtensions(javax.net.ssl.X509TrustManager) throws java.lang.IllegalArgumentException;
+    method public java.util.List<java.security.cert.X509Certificate> checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String, java.lang.String) throws java.security.cert.CertificateException;
+  }
+
 }
 
 package android.net.nsd {
@@ -13114,6 +13322,7 @@
     field public java.lang.String capabilities;
     field public int frequency;
     field public int level;
+    field public long timestamp;
   }
 
   public final class SupplicantState extends java.lang.Enum implements android.os.Parcelable {
@@ -13718,6 +13927,14 @@
     method public byte[] transceive(byte[]) throws java.io.IOException;
   }
 
+  public final class NfcBarcode extends android.nfc.tech.BasicTagTechnology {
+    method public static android.nfc.tech.NfcBarcode get(android.nfc.Tag);
+    method public byte[] getBarcode();
+    method public int getType();
+    field public static final int TYPE_KOVIO = 1; // 0x1
+    field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
+  }
+
   public final class NfcF extends android.nfc.tech.BasicTagTechnology {
     method public static android.nfc.tech.NfcF get(android.nfc.Tag);
     method public byte[] getManufacturer();
@@ -13747,6 +13964,174 @@
 
 package android.opengl {
 
+  public class EGL14 {
+    ctor public EGL14();
+    method public static boolean eglBindAPI(int);
+    method public static boolean eglBindTexImage(android.opengl.EGLDisplay, android.opengl.EGLSurface, int);
+    method public static boolean eglChooseConfig(android.opengl.EGLDisplay, int[], int, android.opengl.EGLConfig[], int, int, int[], int);
+    method public static boolean eglCopyBuffers(android.opengl.EGLDisplay, android.opengl.EGLSurface, int);
+    method public static android.opengl.EGLContext eglCreateContext(android.opengl.EGLDisplay, android.opengl.EGLConfig, android.opengl.EGLContext, int[], int);
+    method public static android.opengl.EGLSurface eglCreatePbufferFromClientBuffer(android.opengl.EGLDisplay, int, int, android.opengl.EGLConfig, int[], int);
+    method public static android.opengl.EGLSurface eglCreatePbufferSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, int[], int);
+    method public static android.opengl.EGLSurface eglCreatePixmapSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, int, int[], int);
+    method public static android.opengl.EGLSurface eglCreateWindowSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, java.lang.Object, int[], int);
+    method public static boolean eglDestroyContext(android.opengl.EGLDisplay, android.opengl.EGLContext);
+    method public static boolean eglDestroySurface(android.opengl.EGLDisplay, android.opengl.EGLSurface);
+    method public static boolean eglGetConfigAttrib(android.opengl.EGLDisplay, android.opengl.EGLConfig, int, int[], int);
+    method public static boolean eglGetConfigs(android.opengl.EGLDisplay, android.opengl.EGLConfig[], int, int, int[], int);
+    method public static android.opengl.EGLContext eglGetCurrentContext();
+    method public static android.opengl.EGLDisplay eglGetCurrentDisplay();
+    method public static android.opengl.EGLSurface eglGetCurrentSurface(int);
+    method public static android.opengl.EGLDisplay eglGetDisplay(int);
+    method public static int eglGetError();
+    method public static boolean eglInitialize(android.opengl.EGLDisplay, int[], int, int[], int);
+    method public static boolean eglMakeCurrent(android.opengl.EGLDisplay, android.opengl.EGLSurface, android.opengl.EGLSurface, android.opengl.EGLContext);
+    method public static int eglQueryAPI();
+    method public static boolean eglQueryContext(android.opengl.EGLDisplay, android.opengl.EGLContext, int, int[], int);
+    method public static java.lang.String eglQueryString(android.opengl.EGLDisplay, int);
+    method public static boolean eglQuerySurface(android.opengl.EGLDisplay, android.opengl.EGLSurface, int, int[], int);
+    method public static boolean eglReleaseTexImage(android.opengl.EGLDisplay, android.opengl.EGLSurface, int);
+    method public static boolean eglReleaseThread();
+    method public static boolean eglSurfaceAttrib(android.opengl.EGLDisplay, android.opengl.EGLSurface, int, int);
+    method public static boolean eglSwapBuffers(android.opengl.EGLDisplay, android.opengl.EGLSurface);
+    method public static boolean eglSwapInterval(android.opengl.EGLDisplay, int);
+    method public static boolean eglTerminate(android.opengl.EGLDisplay);
+    method public static boolean eglWaitClient();
+    method public static boolean eglWaitGL();
+    method public static boolean eglWaitNative(int);
+    field public static final int EGL_ALPHA_MASK_SIZE = 12350; // 0x303e
+    field public static final int EGL_ALPHA_SIZE = 12321; // 0x3021
+    field public static final int EGL_BACK_BUFFER = 12420; // 0x3084
+    field public static final int EGL_BAD_ACCESS = 12290; // 0x3002
+    field public static final int EGL_BAD_ALLOC = 12291; // 0x3003
+    field public static final int EGL_BAD_ATTRIBUTE = 12292; // 0x3004
+    field public static final int EGL_BAD_CONFIG = 12293; // 0x3005
+    field public static final int EGL_BAD_CONTEXT = 12294; // 0x3006
+    field public static final int EGL_BAD_CURRENT_SURFACE = 12295; // 0x3007
+    field public static final int EGL_BAD_DISPLAY = 12296; // 0x3008
+    field public static final int EGL_BAD_MATCH = 12297; // 0x3009
+    field public static final int EGL_BAD_NATIVE_PIXMAP = 12298; // 0x300a
+    field public static final int EGL_BAD_NATIVE_WINDOW = 12299; // 0x300b
+    field public static final int EGL_BAD_PARAMETER = 12300; // 0x300c
+    field public static final int EGL_BAD_SURFACE = 12301; // 0x300d
+    field public static final int EGL_BIND_TO_TEXTURE_RGB = 12345; // 0x3039
+    field public static final int EGL_BIND_TO_TEXTURE_RGBA = 12346; // 0x303a
+    field public static final int EGL_BLUE_SIZE = 12322; // 0x3022
+    field public static final int EGL_BUFFER_DESTROYED = 12437; // 0x3095
+    field public static final int EGL_BUFFER_PRESERVED = 12436; // 0x3094
+    field public static final int EGL_BUFFER_SIZE = 12320; // 0x3020
+    field public static final int EGL_CLIENT_APIS = 12429; // 0x308d
+    field public static final int EGL_COLOR_BUFFER_TYPE = 12351; // 0x303f
+    field public static final int EGL_CONFIG_CAVEAT = 12327; // 0x3027
+    field public static final int EGL_CONFIG_ID = 12328; // 0x3028
+    field public static final int EGL_CONFORMANT = 12354; // 0x3042
+    field public static final int EGL_CONTEXT_CLIENT_TYPE = 12439; // 0x3097
+    field public static final int EGL_CONTEXT_CLIENT_VERSION = 12440; // 0x3098
+    field public static final int EGL_CONTEXT_LOST = 12302; // 0x300e
+    field public static final int EGL_CORE_NATIVE_ENGINE = 12379; // 0x305b
+    field public static final int EGL_DEFAULT_DISPLAY = 0; // 0x0
+    field public static final int EGL_DEPTH_SIZE = 12325; // 0x3025
+    field public static final int EGL_DISPLAY_SCALING = 10000; // 0x2710
+    field public static final int EGL_DRAW = 12377; // 0x3059
+    field public static final int EGL_EXTENSIONS = 12373; // 0x3055
+    field public static final int EGL_FALSE = 0; // 0x0
+    field public static final int EGL_GREEN_SIZE = 12323; // 0x3023
+    field public static final int EGL_HEIGHT = 12374; // 0x3056
+    field public static final int EGL_HORIZONTAL_RESOLUTION = 12432; // 0x3090
+    field public static final int EGL_LARGEST_PBUFFER = 12376; // 0x3058
+    field public static final int EGL_LEVEL = 12329; // 0x3029
+    field public static final int EGL_LUMINANCE_BUFFER = 12431; // 0x308f
+    field public static final int EGL_LUMINANCE_SIZE = 12349; // 0x303d
+    field public static final int EGL_MATCH_NATIVE_PIXMAP = 12353; // 0x3041
+    field public static final int EGL_MAX_PBUFFER_HEIGHT = 12330; // 0x302a
+    field public static final int EGL_MAX_PBUFFER_PIXELS = 12331; // 0x302b
+    field public static final int EGL_MAX_PBUFFER_WIDTH = 12332; // 0x302c
+    field public static final int EGL_MAX_SWAP_INTERVAL = 12348; // 0x303c
+    field public static final int EGL_MIN_SWAP_INTERVAL = 12347; // 0x303b
+    field public static final int EGL_MIPMAP_LEVEL = 12419; // 0x3083
+    field public static final int EGL_MIPMAP_TEXTURE = 12418; // 0x3082
+    field public static final int EGL_MULTISAMPLE_RESOLVE = 12441; // 0x3099
+    field public static final int EGL_MULTISAMPLE_RESOLVE_BOX = 12443; // 0x309b
+    field public static final int EGL_MULTISAMPLE_RESOLVE_BOX_BIT = 512; // 0x200
+    field public static final int EGL_MULTISAMPLE_RESOLVE_DEFAULT = 12442; // 0x309a
+    field public static final int EGL_NATIVE_RENDERABLE = 12333; // 0x302d
+    field public static final int EGL_NATIVE_VISUAL_ID = 12334; // 0x302e
+    field public static final int EGL_NATIVE_VISUAL_TYPE = 12335; // 0x302f
+    field public static final int EGL_NONE = 12344; // 0x3038
+    field public static final int EGL_NON_CONFORMANT_CONFIG = 12369; // 0x3051
+    field public static final int EGL_NOT_INITIALIZED = 12289; // 0x3001
+    field public static android.opengl.EGLContext EGL_NO_CONTEXT;
+    field public static android.opengl.EGLDisplay EGL_NO_DISPLAY;
+    field public static android.opengl.EGLSurface EGL_NO_SURFACE;
+    field public static final int EGL_NO_TEXTURE = 12380; // 0x305c
+    field public static final int EGL_OPENGL_API = 12450; // 0x30a2
+    field public static final int EGL_OPENGL_BIT = 8; // 0x8
+    field public static final int EGL_OPENGL_ES2_BIT = 4; // 0x4
+    field public static final int EGL_OPENGL_ES_API = 12448; // 0x30a0
+    field public static final int EGL_OPENGL_ES_BIT = 1; // 0x1
+    field public static final int EGL_OPENVG_API = 12449; // 0x30a1
+    field public static final int EGL_OPENVG_BIT = 2; // 0x2
+    field public static final int EGL_OPENVG_IMAGE = 12438; // 0x3096
+    field public static final int EGL_PBUFFER_BIT = 1; // 0x1
+    field public static final int EGL_PIXEL_ASPECT_RATIO = 12434; // 0x3092
+    field public static final int EGL_PIXMAP_BIT = 2; // 0x2
+    field public static final int EGL_READ = 12378; // 0x305a
+    field public static final int EGL_RED_SIZE = 12324; // 0x3024
+    field public static final int EGL_RENDERABLE_TYPE = 12352; // 0x3040
+    field public static final int EGL_RENDER_BUFFER = 12422; // 0x3086
+    field public static final int EGL_RGB_BUFFER = 12430; // 0x308e
+    field public static final int EGL_SAMPLES = 12337; // 0x3031
+    field public static final int EGL_SAMPLE_BUFFERS = 12338; // 0x3032
+    field public static final int EGL_SINGLE_BUFFER = 12421; // 0x3085
+    field public static final int EGL_SLOW_CONFIG = 12368; // 0x3050
+    field public static final int EGL_STENCIL_SIZE = 12326; // 0x3026
+    field public static final int EGL_SUCCESS = 12288; // 0x3000
+    field public static final int EGL_SURFACE_TYPE = 12339; // 0x3033
+    field public static final int EGL_SWAP_BEHAVIOR = 12435; // 0x3093
+    field public static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 1024; // 0x400
+    field public static final int EGL_TEXTURE_2D = 12383; // 0x305f
+    field public static final int EGL_TEXTURE_FORMAT = 12416; // 0x3080
+    field public static final int EGL_TEXTURE_RGB = 12381; // 0x305d
+    field public static final int EGL_TEXTURE_RGBA = 12382; // 0x305e
+    field public static final int EGL_TEXTURE_TARGET = 12417; // 0x3081
+    field public static final int EGL_TRANSPARENT_BLUE_VALUE = 12341; // 0x3035
+    field public static final int EGL_TRANSPARENT_GREEN_VALUE = 12342; // 0x3036
+    field public static final int EGL_TRANSPARENT_RED_VALUE = 12343; // 0x3037
+    field public static final int EGL_TRANSPARENT_RGB = 12370; // 0x3052
+    field public static final int EGL_TRANSPARENT_TYPE = 12340; // 0x3034
+    field public static final int EGL_TRUE = 1; // 0x1
+    field public static final int EGL_VENDOR = 12371; // 0x3053
+    field public static final int EGL_VERSION = 12372; // 0x3054
+    field public static final int EGL_VERTICAL_RESOLUTION = 12433; // 0x3091
+    field public static final int EGL_VG_ALPHA_FORMAT = 12424; // 0x3088
+    field public static final int EGL_VG_ALPHA_FORMAT_NONPRE = 12427; // 0x308b
+    field public static final int EGL_VG_ALPHA_FORMAT_PRE = 12428; // 0x308c
+    field public static final int EGL_VG_ALPHA_FORMAT_PRE_BIT = 64; // 0x40
+    field public static final int EGL_VG_COLORSPACE = 12423; // 0x3087
+    field public static final int EGL_VG_COLORSPACE_LINEAR = 12426; // 0x308a
+    field public static final int EGL_VG_COLORSPACE_LINEAR_BIT = 32; // 0x20
+    field public static final int EGL_VG_COLORSPACE_sRGB = 12425; // 0x3089
+    field public static final int EGL_WIDTH = 12375; // 0x3057
+    field public static final int EGL_WINDOW_BIT = 4; // 0x4
+  }
+
+  public class EGLConfig extends android.opengl.EGLObjectHandle {
+  }
+
+  public class EGLContext extends android.opengl.EGLObjectHandle {
+  }
+
+  public class EGLDisplay extends android.opengl.EGLObjectHandle {
+  }
+
+  public abstract class EGLObjectHandle {
+    ctor protected EGLObjectHandle(int);
+    method public int getHandle();
+  }
+
+  public class EGLSurface extends android.opengl.EGLObjectHandle {
+  }
+
   public class ETC1 {
     ctor public ETC1();
     method public static void decodeBlock(java.nio.Buffer, java.nio.Buffer);
@@ -14654,8 +15039,12 @@
     method public static void glGenerateMipmap(int);
     method public static void glGetActiveAttrib(int, int, int, int[], int, int[], int, int[], int, byte[], int);
     method public static void glGetActiveAttrib(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static java.lang.String glGetActiveAttrib(int, int, int[], int, int[], int);
+    method public static java.lang.String glGetActiveAttrib(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static void glGetActiveUniform(int, int, int, int[], int, int[], int, int[], int, byte[], int);
     method public static void glGetActiveUniform(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static java.lang.String glGetActiveUniform(int, int, int[], int, int[], int);
+    method public static java.lang.String glGetActiveUniform(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static void glGetAttachedShaders(int, int, int[], int, int[], int);
     method public static void glGetAttachedShaders(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static int glGetAttribLocation(int, java.lang.String);
@@ -14680,6 +15069,7 @@
     method public static void glGetShaderPrecisionFormat(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static void glGetShaderSource(int, int, int[], int, byte[], int);
     method public static void glGetShaderSource(int, int, java.nio.IntBuffer, byte);
+    method public static java.lang.String glGetShaderSource(int);
     method public static void glGetShaderiv(int, int, int[], int);
     method public static void glGetShaderiv(int, int, java.nio.IntBuffer);
     method public static java.lang.String glGetString(int);
@@ -15239,6 +15629,7 @@
     field public static final int BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6; // 0x6
     field public static final int BATTERY_PLUGGED_AC = 1; // 0x1
     field public static final int BATTERY_PLUGGED_USB = 2; // 0x2
+    field public static final int BATTERY_PLUGGED_WIRELESS = 4; // 0x4
     field public static final int BATTERY_STATUS_CHARGING = 2; // 0x2
     field public static final int BATTERY_STATUS_DISCHARGING = 3; // 0x3
     field public static final int BATTERY_STATUS_FULL = 5; // 0x5
@@ -15266,6 +15657,7 @@
     method public static final void flushPendingCommands();
     method public static final int getCallingPid();
     method public static final int getCallingUid();
+    method public static final android.os.UserHandle getCallingUserHandle();
     method public java.lang.String getInterfaceDescriptor();
     method public boolean isBinderAlive();
     method public static final void joinThreadPool();
@@ -15332,6 +15724,7 @@
     field public static final int ICE_CREAM_SANDWICH = 14; // 0xe
     field public static final int ICE_CREAM_SANDWICH_MR1 = 15; // 0xf
     field public static final int JELLY_BEAN = 16; // 0x10
+    field public static final int JELLY_BEAN_MR1 = 17; // 0x11
   }
 
   public final class Bundle implements java.lang.Cloneable android.os.Parcelable {
@@ -15991,21 +16384,22 @@
     field public static final int PATTERN_SIMPLE_GLOB = 2; // 0x2
   }
 
-  public class PowerManager {
+  public final class PowerManager {
     method public void goToSleep(long);
     method public boolean isScreenOn();
     method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
     method public void reboot(java.lang.String);
     method public void userActivity(long, boolean);
+    method public void wakeUp(long);
     field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
-    field public static final int FULL_WAKE_LOCK = 26; // 0x1a
+    field public static final deprecated int FULL_WAKE_LOCK = 26; // 0x1a
     field public static final int ON_AFTER_RELEASE = 536870912; // 0x20000000
     field public static final int PARTIAL_WAKE_LOCK = 1; // 0x1
     field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
-    field public static final int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
+    field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
   }
 
-  public class PowerManager.WakeLock {
+  public final class PowerManager.WakeLock {
     method public void acquire();
     method public void acquire(long);
     method public boolean isHeld();
@@ -16024,6 +16418,7 @@
     method public static final int myPid();
     method public static final int myTid();
     method public static final int myUid();
+    method public static final android.os.UserHandle myUserHandle();
     method public static final void sendSignal(int, int);
     method public static final void setThreadPriority(int, int) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
     method public static final void setThreadPriority(int) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
@@ -16066,6 +16461,7 @@
     method public void finishBroadcast();
     method public java.lang.Object getBroadcastCookie(int);
     method public E getBroadcastItem(int);
+    method public int getRegisteredCallbackCount();
     method public void kill();
     method public void onCallbackDied(E);
     method public void onCallbackDied(E, java.lang.Object);
@@ -16156,6 +16552,7 @@
   public final class SystemClock {
     method public static long currentThreadTimeMillis();
     method public static long elapsedRealtime();
+    method public static long elapsedRealtimeNanos();
     method public static boolean setCurrentTimeMillis(long);
     method public static void sleep(long);
     method public static long uptimeMillis();
@@ -16177,6 +16574,25 @@
     ctor public TransactionTooLargeException();
   }
 
+  public final class UserHandle implements android.os.Parcelable {
+    ctor public UserHandle(android.os.Parcel);
+    method public int describeContents();
+    method public static android.os.UserHandle readFromParcel(android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    method public static void writeToParcel(android.os.UserHandle, android.os.Parcel);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class UserManager {
+    method public long getSerialNumberForUser(android.os.UserHandle);
+    method public int getUserCount();
+    method public android.os.UserHandle getUserForSerialNumber(long);
+    method public java.lang.String getUserName();
+    method public boolean isUserAGoat();
+    method public boolean isUserRunning(android.os.UserHandle);
+    method public boolean isUserRunningOrStopping(android.os.UserHandle);
+  }
+
   public abstract class Vibrator {
     method public abstract void cancel();
     method public abstract boolean hasVibrator();
@@ -16755,6 +17171,7 @@
     field public static final int CAL_ACCESS_ROOT = 800; // 0x320
     field public static final java.lang.String CAN_MODIFY_TIME_ZONE = "canModifyTimeZone";
     field public static final java.lang.String CAN_ORGANIZER_RESPOND = "canOrganizerRespond";
+    field public static final java.lang.String IS_PRIMARY = "isPrimary";
     field public static final java.lang.String MAX_REMINDERS = "maxReminders";
     field public static final java.lang.String OWNER_ACCOUNT = "ownerAccount";
     field public static final java.lang.String SYNC_EVENTS = "sync_events";
@@ -16846,6 +17263,7 @@
     field public static final java.lang.String HAS_ALARM = "hasAlarm";
     field public static final java.lang.String HAS_ATTENDEE_DATA = "hasAttendeeData";
     field public static final java.lang.String HAS_EXTENDED_PROPERTIES = "hasExtendedProperties";
+    field public static final java.lang.String IS_ORGANIZER = "isOrganizer";
     field public static final java.lang.String LAST_DATE = "lastDate";
     field public static final java.lang.String LAST_SYNCED = "lastSynced";
     field public static final java.lang.String ORGANIZER = "organizer";
@@ -16871,6 +17289,7 @@
     field public static final java.lang.String SYNC_DATA8 = "sync_data8";
     field public static final java.lang.String SYNC_DATA9 = "sync_data9";
     field public static final java.lang.String TITLE = "title";
+    field public static final java.lang.String UID_2445 = "uid2445";
   }
 
   public static final class CalendarContract.EventsEntity implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.SyncColumns {
@@ -16956,9 +17375,11 @@
     field public static final java.lang.String DURATION = "duration";
     field public static final int INCOMING_TYPE = 1; // 0x1
     field public static final java.lang.String IS_READ = "is_read";
+    field public static final java.lang.String LIMIT_PARAM_KEY = "limit";
     field public static final int MISSED_TYPE = 3; // 0x3
     field public static final java.lang.String NEW = "new";
     field public static final java.lang.String NUMBER = "number";
+    field public static final java.lang.String OFFSET_PARAM_KEY = "offset";
     field public static final int OUTGOING_TYPE = 2; // 0x2
     field public static final java.lang.String TYPE = "type";
   }
@@ -17992,6 +18413,7 @@
     method public static android.net.Uri getMediaScannerUri();
     method public static java.lang.String getVersion(android.content.Context);
     field public static final java.lang.String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
+    field public static final java.lang.String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE";
     field public static final java.lang.String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE";
     field public static final java.lang.String AUTHORITY = "media";
     field public static final java.lang.String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit";
@@ -18010,7 +18432,10 @@
     field public static final java.lang.String INTENT_ACTION_MEDIA_SEARCH = "android.intent.action.MEDIA_SEARCH";
     field public static final deprecated java.lang.String INTENT_ACTION_MUSIC_PLAYER = "android.intent.action.MUSIC_PLAYER";
     field public static final java.lang.String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA";
+    field public static final java.lang.String INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE = "android.media.action.STILL_IMAGE_CAMERA_SECURE";
+    field public static final java.lang.String INTENT_ACTION_TEXT_OPEN_FROM_SEARCH = "android.media.action.TEXT_OPEN_FROM_SEARCH";
     field public static final java.lang.String INTENT_ACTION_VIDEO_CAMERA = "android.media.action.VIDEO_CAMERA";
+    field public static final java.lang.String INTENT_ACTION_VIDEO_PLAY_FROM_SEARCH = "android.media.action.VIDEO_PLAY_FROM_SEARCH";
     field public static final java.lang.String MEDIA_IGNORE_FILENAME = ".nomedia";
     field public static final java.lang.String MEDIA_SCANNER_VOLUME = "volume";
     field public static final java.lang.String UNKNOWN_STRING = "<unknown>";
@@ -18349,6 +18774,62 @@
     field public static final java.lang.String EXTRA_INPUT_METHOD_ID = "input_method_id";
   }
 
+  public static final class Settings.Global extends android.provider.Settings.NameValueTable {
+    ctor public Settings.Global();
+    method public static float getFloat(android.content.ContentResolver, java.lang.String, float);
+    method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
+    method public static int getInt(android.content.ContentResolver, java.lang.String, int);
+    method public static int getInt(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
+    method public static long getLong(android.content.ContentResolver, java.lang.String, long);
+    method public static long getLong(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
+    method public static java.lang.String getString(android.content.ContentResolver, java.lang.String);
+    method public static android.net.Uri getUriFor(java.lang.String);
+    method public static boolean putFloat(android.content.ContentResolver, java.lang.String, float);
+    method public static boolean putInt(android.content.ContentResolver, java.lang.String, int);
+    method public static boolean putLong(android.content.ContentResolver, java.lang.String, long);
+    method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String);
+    field public static final java.lang.String ADB_ENABLED = "adb_enabled";
+    field public static final java.lang.String AIRPLANE_MODE_ON = "airplane_mode_on";
+    field public static final java.lang.String AIRPLANE_MODE_RADIOS = "airplane_mode_radios";
+    field public static final java.lang.String ALWAYS_FINISH_ACTIVITIES = "always_finish_activities";
+    field public static final java.lang.String ANIMATOR_DURATION_SCALE = "animator_duration_scale";
+    field public static final java.lang.String AUTO_TIME = "auto_time";
+    field public static final java.lang.String AUTO_TIME_ZONE = "auto_time_zone";
+    field public static final java.lang.String BLUETOOTH_ON = "bluetooth_on";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DATA_ROAMING = "data_roaming";
+    field public static final java.lang.String DEBUG_APP = "debug_app";
+    field public static final java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
+    field public static final java.lang.String DEVICE_PROVISIONED = "device_provisioned";
+    field public static final java.lang.String HTTP_PROXY = "http_proxy";
+    field public static final java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+    field public static final java.lang.String MODE_RINGER = "mode_ringer";
+    field public static final java.lang.String NETWORK_PREFERENCE = "network_preference";
+    field public static final java.lang.String RADIO_BLUETOOTH = "bluetooth";
+    field public static final java.lang.String RADIO_CELL = "cell";
+    field public static final java.lang.String RADIO_NFC = "nfc";
+    field public static final java.lang.String RADIO_WIFI = "wifi";
+    field public static final java.lang.String SHOW_PROCESSES = "show_processes";
+    field public static final java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
+    field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_global_version";
+    field public static final java.lang.String TRANSITION_ANIMATION_SCALE = "transition_animation_scale";
+    field public static final java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
+    field public static final java.lang.String USE_GOOGLE_MAIL = "use_google_mail";
+    field public static final java.lang.String WAIT_FOR_DEBUGGER = "wait_for_debugger";
+    field public static final java.lang.String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
+    field public static final java.lang.String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS = "wifi_mobile_data_transition_wakelock_timeout_ms";
+    field public static final java.lang.String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = "wifi_networks_available_notification_on";
+    field public static final java.lang.String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY = "wifi_networks_available_repeat_delay";
+    field public static final java.lang.String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
+    field public static final java.lang.String WIFI_ON = "wifi_on";
+    field public static final java.lang.String WIFI_SLEEP_POLICY = "wifi_sleep_policy";
+    field public static final int WIFI_SLEEP_POLICY_DEFAULT = 0; // 0x0
+    field public static final int WIFI_SLEEP_POLICY_NEVER = 2; // 0x2
+    field public static final int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED = 1; // 0x1
+    field public static final java.lang.String WIFI_WATCHDOG_ON = "wifi_watchdog_on";
+    field public static final java.lang.String WINDOW_ANIMATION_SCALE = "window_animation_scale";
+  }
+
   public static class Settings.NameValueTable implements android.provider.BaseColumns {
     ctor public Settings.NameValueTable();
     method public static android.net.Uri getUriFor(android.net.Uri, java.lang.String);
@@ -18365,7 +18846,7 @@
     method public static int getInt(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
     method public static long getLong(android.content.ContentResolver, java.lang.String, long);
     method public static long getLong(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
-    method public static synchronized java.lang.String getString(android.content.ContentResolver, java.lang.String);
+    method public static java.lang.String getString(android.content.ContentResolver, java.lang.String);
     method public static android.net.Uri getUriFor(java.lang.String);
     method public static final boolean isLocationProviderEnabled(android.content.ContentResolver, java.lang.String);
     method public static boolean putFloat(android.content.ContentResolver, java.lang.String, float);
@@ -18375,28 +18856,28 @@
     method public static final void setLocationProviderEnabled(android.content.ContentResolver, java.lang.String, boolean);
     field public static final java.lang.String ACCESSIBILITY_ENABLED = "accessibility_enabled";
     field public static final java.lang.String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
-    field public static final java.lang.String ADB_ENABLED = "adb_enabled";
+    field public static final deprecated java.lang.String ADB_ENABLED = "adb_enabled";
     field public static final java.lang.String ALLOWED_GEOLOCATION_ORIGINS = "allowed_geolocation_origins";
     field public static final java.lang.String ALLOW_MOCK_LOCATION = "mock_location";
     field public static final java.lang.String ANDROID_ID = "android_id";
     field public static final deprecated java.lang.String BACKGROUND_DATA = "background_data";
-    field public static final java.lang.String BLUETOOTH_ON = "bluetooth_on";
+    field public static final deprecated java.lang.String BLUETOOTH_ON = "bluetooth_on";
     field public static final android.net.Uri CONTENT_URI;
-    field public static final java.lang.String DATA_ROAMING = "data_roaming";
+    field public static final deprecated java.lang.String DATA_ROAMING = "data_roaming";
     field public static final java.lang.String DEFAULT_INPUT_METHOD = "default_input_method";
-    field public static final java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
-    field public static final java.lang.String DEVICE_PROVISIONED = "device_provisioned";
+    field public static final deprecated java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
+    field public static final deprecated java.lang.String DEVICE_PROVISIONED = "device_provisioned";
     field public static final java.lang.String ENABLED_ACCESSIBILITY_SERVICES = "enabled_accessibility_services";
     field public static final java.lang.String ENABLED_INPUT_METHODS = "enabled_input_methods";
-    field public static final java.lang.String HTTP_PROXY = "http_proxy";
+    field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
     field public static final java.lang.String INPUT_METHOD_SELECTOR_VISIBILITY = "input_method_selector_visibility";
-    field public static final java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+    field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
     field public static final java.lang.String LOCATION_PROVIDERS_ALLOWED = "location_providers_allowed";
     field public static final java.lang.String LOCK_PATTERN_ENABLED = "lock_pattern_autolock";
-    field public static final java.lang.String LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED = "lock_pattern_tactile_feedback_enabled";
+    field public static final deprecated java.lang.String LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED = "lock_pattern_tactile_feedback_enabled";
     field public static final java.lang.String LOCK_PATTERN_VISIBLE = "lock_pattern_visible_pattern";
     field public static final deprecated java.lang.String LOGGING_ID = "logging_id";
-    field public static final java.lang.String NETWORK_PREFERENCE = "network_preference";
+    field public static final deprecated java.lang.String NETWORK_PREFERENCE = "network_preference";
     field public static final java.lang.String PARENTAL_CONTROL_ENABLED = "parental_control_enabled";
     field public static final java.lang.String PARENTAL_CONTROL_LAST_UPDATE = "parental_control_last_update";
     field public static final java.lang.String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url";
@@ -18412,14 +18893,14 @@
     field public static final deprecated java.lang.String TTS_DEFAULT_VARIANT = "tts_default_variant";
     field public static final java.lang.String TTS_ENABLED_PLUGINS = "tts_enabled_plugins";
     field public static final deprecated java.lang.String TTS_USE_DEFAULTS = "tts_use_defaults";
-    field public static final java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
-    field public static final java.lang.String USE_GOOGLE_MAIL = "use_google_mail";
-    field public static final java.lang.String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
-    field public static final java.lang.String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS = "wifi_mobile_data_transition_wakelock_timeout_ms";
-    field public static final java.lang.String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = "wifi_networks_available_notification_on";
-    field public static final java.lang.String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY = "wifi_networks_available_repeat_delay";
-    field public static final java.lang.String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
-    field public static final java.lang.String WIFI_ON = "wifi_on";
+    field public static final deprecated java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
+    field public static final deprecated java.lang.String USE_GOOGLE_MAIL = "use_google_mail";
+    field public static final deprecated java.lang.String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
+    field public static final deprecated java.lang.String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS = "wifi_mobile_data_transition_wakelock_timeout_ms";
+    field public static final deprecated java.lang.String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = "wifi_networks_available_notification_on";
+    field public static final deprecated java.lang.String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY = "wifi_networks_available_repeat_delay";
+    field public static final deprecated java.lang.String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
+    field public static final deprecated java.lang.String WIFI_ON = "wifi_on";
     field public static final deprecated java.lang.String WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE = "wifi_watchdog_acceptable_packet_loss_percentage";
     field public static final deprecated java.lang.String WIFI_WATCHDOG_AP_COUNT = "wifi_watchdog_ap_count";
     field public static final deprecated java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS = "wifi_watchdog_background_check_delay_ms";
@@ -18427,7 +18908,7 @@
     field public static final deprecated java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS = "wifi_watchdog_background_check_timeout_ms";
     field public static final deprecated java.lang.String WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT = "wifi_watchdog_initial_ignored_ping_count";
     field public static final deprecated java.lang.String WIFI_WATCHDOG_MAX_AP_CHECKS = "wifi_watchdog_max_ap_checks";
-    field public static final java.lang.String WIFI_WATCHDOG_ON = "wifi_watchdog_on";
+    field public static final deprecated java.lang.String WIFI_WATCHDOG_ON = "wifi_watchdog_on";
     field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_COUNT = "wifi_watchdog_ping_count";
     field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_DELAY_MS = "wifi_watchdog_ping_delay_ms";
     field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_TIMEOUT_MS = "wifi_watchdog_ping_timeout_ms";
@@ -18447,38 +18928,38 @@
     method public static int getInt(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
     method public static long getLong(android.content.ContentResolver, java.lang.String, long);
     method public static long getLong(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
-    method public static boolean getShowGTalkServiceStatus(android.content.ContentResolver);
-    method public static synchronized java.lang.String getString(android.content.ContentResolver, java.lang.String);
+    method public static deprecated boolean getShowGTalkServiceStatus(android.content.ContentResolver);
+    method public static java.lang.String getString(android.content.ContentResolver, java.lang.String);
     method public static android.net.Uri getUriFor(java.lang.String);
     method public static boolean putConfiguration(android.content.ContentResolver, android.content.res.Configuration);
     method public static boolean putFloat(android.content.ContentResolver, java.lang.String, float);
     method public static boolean putInt(android.content.ContentResolver, java.lang.String, int);
     method public static boolean putLong(android.content.ContentResolver, java.lang.String, long);
     method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String);
-    method public static void setShowGTalkServiceStatus(android.content.ContentResolver, boolean);
+    method public static deprecated void setShowGTalkServiceStatus(android.content.ContentResolver, boolean);
     field public static final java.lang.String ACCELEROMETER_ROTATION = "accelerometer_rotation";
     field public static final deprecated java.lang.String ADB_ENABLED = "adb_enabled";
-    field public static final java.lang.String AIRPLANE_MODE_ON = "airplane_mode_on";
-    field public static final java.lang.String AIRPLANE_MODE_RADIOS = "airplane_mode_radios";
+    field public static final deprecated java.lang.String AIRPLANE_MODE_ON = "airplane_mode_on";
+    field public static final deprecated java.lang.String AIRPLANE_MODE_RADIOS = "airplane_mode_radios";
     field public static final java.lang.String ALARM_ALERT = "alarm_alert";
-    field public static final java.lang.String ALWAYS_FINISH_ACTIVITIES = "always_finish_activities";
+    field public static final deprecated java.lang.String ALWAYS_FINISH_ACTIVITIES = "always_finish_activities";
     field public static final deprecated java.lang.String ANDROID_ID = "android_id";
-    field public static final java.lang.String ANIMATOR_DURATION_SCALE = "animator_duration_scale";
+    field public static final deprecated java.lang.String ANIMATOR_DURATION_SCALE = "animator_duration_scale";
     field public static final java.lang.String APPEND_FOR_LAST_AUDIBLE = "_last_audible";
-    field public static final java.lang.String AUTO_TIME = "auto_time";
-    field public static final java.lang.String AUTO_TIME_ZONE = "auto_time_zone";
+    field public static final deprecated java.lang.String AUTO_TIME = "auto_time";
+    field public static final deprecated java.lang.String AUTO_TIME_ZONE = "auto_time_zone";
     field public static final java.lang.String BLUETOOTH_DISCOVERABILITY = "bluetooth_discoverability";
     field public static final java.lang.String BLUETOOTH_DISCOVERABILITY_TIMEOUT = "bluetooth_discoverability_timeout";
     field public static final deprecated java.lang.String BLUETOOTH_ON = "bluetooth_on";
     field public static final android.net.Uri CONTENT_URI;
     field public static final deprecated java.lang.String DATA_ROAMING = "data_roaming";
     field public static final java.lang.String DATE_FORMAT = "date_format";
-    field public static final java.lang.String DEBUG_APP = "debug_app";
+    field public static final deprecated java.lang.String DEBUG_APP = "debug_app";
     field public static final android.net.Uri DEFAULT_ALARM_ALERT_URI;
     field public static final android.net.Uri DEFAULT_NOTIFICATION_URI;
     field public static final android.net.Uri DEFAULT_RINGTONE_URI;
     field public static final deprecated java.lang.String DEVICE_PROVISIONED = "device_provisioned";
-    field public static final java.lang.String DIM_SCREEN = "dim_screen";
+    field public static final deprecated java.lang.String DIM_SCREEN = "dim_screen";
     field public static final java.lang.String DTMF_TONE_WHEN_DIALING = "dtmf_tone";
     field public static final java.lang.String END_BUTTON_BEHAVIOR = "end_button_behavior";
     field public static final java.lang.String FONT_SCALE = "font_scale";
@@ -18490,7 +18971,7 @@
     field public static final deprecated java.lang.String LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED = "lock_pattern_tactile_feedback_enabled";
     field public static final deprecated java.lang.String LOCK_PATTERN_VISIBLE = "lock_pattern_visible_pattern";
     field public static final deprecated java.lang.String LOGGING_ID = "logging_id";
-    field public static final java.lang.String MODE_RINGER = "mode_ringer";
+    field public static final deprecated java.lang.String MODE_RINGER = "mode_ringer";
     field public static final java.lang.String MODE_RINGER_STREAMS_AFFECTED = "mode_ringer_streams_affected";
     field public static final java.lang.String MUTE_STREAMS_AFFECTED = "mute_streams_affected";
     field public static final deprecated java.lang.String NETWORK_PREFERENCE = "network_preference";
@@ -18499,10 +18980,10 @@
     field public static final deprecated java.lang.String PARENTAL_CONTROL_ENABLED = "parental_control_enabled";
     field public static final deprecated java.lang.String PARENTAL_CONTROL_LAST_UPDATE = "parental_control_last_update";
     field public static final deprecated java.lang.String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url";
-    field public static final java.lang.String RADIO_BLUETOOTH = "bluetooth";
-    field public static final java.lang.String RADIO_CELL = "cell";
-    field public static final java.lang.String RADIO_NFC = "nfc";
-    field public static final java.lang.String RADIO_WIFI = "wifi";
+    field public static final deprecated java.lang.String RADIO_BLUETOOTH = "bluetooth";
+    field public static final deprecated java.lang.String RADIO_CELL = "cell";
+    field public static final deprecated java.lang.String RADIO_NFC = "nfc";
+    field public static final deprecated java.lang.String RADIO_WIFI = "wifi";
     field public static final java.lang.String RINGTONE = "ringtone";
     field public static final java.lang.String SCREEN_BRIGHTNESS = "screen_brightness";
     field public static final java.lang.String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
@@ -18512,17 +18993,17 @@
     field public static final deprecated java.lang.String SETTINGS_CLASSNAME = "settings_classname";
     field public static final java.lang.String SETUP_WIZARD_HAS_RUN = "setup_wizard_has_run";
     field public static final java.lang.String SHOW_GTALK_SERVICE_STATUS = "SHOW_GTALK_SERVICE_STATUS";
-    field public static final java.lang.String SHOW_PROCESSES = "show_processes";
+    field public static final deprecated java.lang.String SHOW_PROCESSES = "show_processes";
     field public static final deprecated java.lang.String SHOW_WEB_SUGGESTIONS = "show_web_suggestions";
     field public static final java.lang.String SOUND_EFFECTS_ENABLED = "sound_effects_enabled";
-    field public static final java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
+    field public static final deprecated java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
     field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_system_version";
     field public static final java.lang.String TEXT_AUTO_CAPS = "auto_caps";
     field public static final java.lang.String TEXT_AUTO_PUNCTUATE = "auto_punctuate";
     field public static final java.lang.String TEXT_AUTO_REPLACE = "auto_replace";
     field public static final java.lang.String TEXT_SHOW_PASSWORD = "show_password";
     field public static final java.lang.String TIME_12_24 = "time_12_24";
-    field public static final java.lang.String TRANSITION_ANIMATION_SCALE = "transition_animation_scale";
+    field public static final deprecated java.lang.String TRANSITION_ANIMATION_SCALE = "transition_animation_scale";
     field public static final deprecated java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
     field public static final java.lang.String USER_ROTATION = "user_rotation";
     field public static final deprecated java.lang.String USE_GOOGLE_MAIL = "use_google_mail";
@@ -18535,24 +19016,24 @@
     field public static final java.lang.String[] VOLUME_SETTINGS;
     field public static final java.lang.String VOLUME_SYSTEM = "volume_system";
     field public static final java.lang.String VOLUME_VOICE = "volume_voice";
-    field public static final java.lang.String WAIT_FOR_DEBUGGER = "wait_for_debugger";
-    field public static final java.lang.String WALLPAPER_ACTIVITY = "wallpaper_activity";
+    field public static final deprecated java.lang.String WAIT_FOR_DEBUGGER = "wait_for_debugger";
+    field public static final deprecated java.lang.String WALLPAPER_ACTIVITY = "wallpaper_activity";
     field public static final deprecated java.lang.String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
     field public static final deprecated java.lang.String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS = "wifi_mobile_data_transition_wakelock_timeout_ms";
     field public static final deprecated java.lang.String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = "wifi_networks_available_notification_on";
     field public static final deprecated java.lang.String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY = "wifi_networks_available_repeat_delay";
     field public static final deprecated java.lang.String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
     field public static final deprecated java.lang.String WIFI_ON = "wifi_on";
-    field public static final java.lang.String WIFI_SLEEP_POLICY = "wifi_sleep_policy";
-    field public static final int WIFI_SLEEP_POLICY_DEFAULT = 0; // 0x0
-    field public static final int WIFI_SLEEP_POLICY_NEVER = 2; // 0x2
-    field public static final int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED = 1; // 0x1
-    field public static final java.lang.String WIFI_STATIC_DNS1 = "wifi_static_dns1";
-    field public static final java.lang.String WIFI_STATIC_DNS2 = "wifi_static_dns2";
-    field public static final java.lang.String WIFI_STATIC_GATEWAY = "wifi_static_gateway";
-    field public static final java.lang.String WIFI_STATIC_IP = "wifi_static_ip";
-    field public static final java.lang.String WIFI_STATIC_NETMASK = "wifi_static_netmask";
-    field public static final java.lang.String WIFI_USE_STATIC_IP = "wifi_use_static_ip";
+    field public static final deprecated java.lang.String WIFI_SLEEP_POLICY = "wifi_sleep_policy";
+    field public static final deprecated int WIFI_SLEEP_POLICY_DEFAULT = 0; // 0x0
+    field public static final deprecated int WIFI_SLEEP_POLICY_NEVER = 2; // 0x2
+    field public static final deprecated int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED = 1; // 0x1
+    field public static final deprecated java.lang.String WIFI_STATIC_DNS1 = "wifi_static_dns1";
+    field public static final deprecated java.lang.String WIFI_STATIC_DNS2 = "wifi_static_dns2";
+    field public static final deprecated java.lang.String WIFI_STATIC_GATEWAY = "wifi_static_gateway";
+    field public static final deprecated java.lang.String WIFI_STATIC_IP = "wifi_static_ip";
+    field public static final deprecated java.lang.String WIFI_STATIC_NETMASK = "wifi_static_netmask";
+    field public static final deprecated java.lang.String WIFI_USE_STATIC_IP = "wifi_use_static_ip";
     field public static final deprecated java.lang.String WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE = "wifi_watchdog_acceptable_packet_loss_percentage";
     field public static final deprecated java.lang.String WIFI_WATCHDOG_AP_COUNT = "wifi_watchdog_ap_count";
     field public static final deprecated java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS = "wifi_watchdog_background_check_delay_ms";
@@ -18564,7 +19045,7 @@
     field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_COUNT = "wifi_watchdog_ping_count";
     field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_DELAY_MS = "wifi_watchdog_ping_delay_ms";
     field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_TIMEOUT_MS = "wifi_watchdog_ping_timeout_ms";
-    field public static final java.lang.String WINDOW_ANIMATION_SCALE = "window_animation_scale";
+    field public static final deprecated java.lang.String WINDOW_ANIMATION_SCALE = "window_animation_scale";
   }
 
   public class SyncStateContract {
@@ -19546,6 +20027,8 @@
 
   public class Script extends android.renderscript.BaseObj {
     method public void bindAllocation(android.renderscript.Allocation, int);
+    method protected android.renderscript.Script.FieldID createFieldID(int, android.renderscript.Element);
+    method protected android.renderscript.Script.KernelID createKernelID(int, int, android.renderscript.Element, android.renderscript.Element);
     method protected void forEach(int, android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.FieldPacker);
     method protected void invoke(int);
     method protected void invoke(int, android.renderscript.FieldPacker);
@@ -19575,11 +20058,124 @@
     field protected android.renderscript.Element mElement;
   }
 
+  public static final class Script.FieldID extends android.renderscript.BaseObj {
+  }
+
+  public static final class Script.KernelID extends android.renderscript.BaseObj {
+  }
+
   public class ScriptC extends android.renderscript.Script {
     ctor protected ScriptC(int, android.renderscript.RenderScript);
     ctor protected ScriptC(android.renderscript.RenderScript, android.content.res.Resources, int);
   }
 
+  public final class ScriptGroup extends android.renderscript.BaseObj {
+    method public void execute();
+    method public void setInput(android.renderscript.Script.KernelID, android.renderscript.Allocation);
+    method public void setOutput(android.renderscript.Script.KernelID, android.renderscript.Allocation);
+  }
+
+  public static final class ScriptGroup.Builder {
+    ctor public ScriptGroup.Builder(android.renderscript.RenderScript);
+    method public android.renderscript.ScriptGroup.Builder addConnection(android.renderscript.Type, android.renderscript.Script.KernelID, android.renderscript.Script.FieldID);
+    method public android.renderscript.ScriptGroup.Builder addConnection(android.renderscript.Type, android.renderscript.Script.KernelID, android.renderscript.Script.KernelID);
+    method public android.renderscript.ScriptGroup.Builder addKernel(android.renderscript.Script.KernelID);
+    method public android.renderscript.ScriptGroup create();
+  }
+
+  public abstract class ScriptIntrinsic extends android.renderscript.Script {
+  }
+
+  public class ScriptIntrinsicBlend extends android.renderscript.ScriptIntrinsic {
+    method public static android.renderscript.ScriptIntrinsicBlend create(android.renderscript.RenderScript, android.renderscript.Element);
+    method public void forEachAdd(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachClear(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachDst(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachDstAtop(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachDstIn(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachDstOut(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachDstOver(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachMultiply(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachSrc(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachSrcAtop(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachSrcIn(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachSrcOut(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachSrcOver(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachSubtract(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public void forEachXor(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public android.renderscript.Script.KernelID getKernelIDAdd();
+    method public android.renderscript.Script.KernelID getKernelIDClear();
+    method public android.renderscript.Script.KernelID getKernelIDDst();
+    method public android.renderscript.Script.KernelID getKernelIDDstAtop();
+    method public android.renderscript.Script.KernelID getKernelIDDstIn();
+    method public android.renderscript.Script.KernelID getKernelIDDstOut();
+    method public android.renderscript.Script.KernelID getKernelIDDstOver();
+    method public android.renderscript.Script.KernelID getKernelIDMultiply();
+    method public android.renderscript.Script.KernelID getKernelIDSrc();
+    method public android.renderscript.Script.KernelID getKernelIDSrcAtop();
+    method public android.renderscript.Script.KernelID getKernelIDSrcIn();
+    method public android.renderscript.Script.KernelID getKernelIDSrcOut();
+    method public android.renderscript.Script.KernelID getKernelIDSrcOver();
+    method public android.renderscript.Script.KernelID getKernelIDSubtract();
+    method public android.renderscript.Script.KernelID getKernelIDXor();
+  }
+
+  public final class ScriptIntrinsicBlur extends android.renderscript.ScriptIntrinsic {
+    method public static android.renderscript.ScriptIntrinsicBlur create(android.renderscript.RenderScript, android.renderscript.Element);
+    method public void forEach(android.renderscript.Allocation);
+    method public android.renderscript.Script.FieldID getFieldID_Input();
+    method public android.renderscript.Script.KernelID getKernelID();
+    method public void setInput(android.renderscript.Allocation);
+    method public void setRadius(float);
+  }
+
+  public final class ScriptIntrinsicColorMatrix extends android.renderscript.ScriptIntrinsic {
+    method public static android.renderscript.ScriptIntrinsicColorMatrix create(android.renderscript.RenderScript, android.renderscript.Element);
+    method public void forEach(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public android.renderscript.Script.KernelID getKernelID();
+    method public void setColorMatrix(android.renderscript.Matrix4f);
+    method public void setColorMatrix(android.renderscript.Matrix3f);
+    method public void setGreyscale();
+    method public void setRGBtoYUV();
+    method public void setYUVtoRGB();
+  }
+
+  public final class ScriptIntrinsicConvolve3x3 extends android.renderscript.ScriptIntrinsic {
+    method public static android.renderscript.ScriptIntrinsicConvolve3x3 create(android.renderscript.RenderScript, android.renderscript.Element);
+    method public void forEach(android.renderscript.Allocation);
+    method public android.renderscript.Script.FieldID getFieldID_Input();
+    method public android.renderscript.Script.KernelID getKernelID();
+    method public void setCoefficients(float[]);
+    method public void setInput(android.renderscript.Allocation);
+  }
+
+  public final class ScriptIntrinsicConvolve5x5 extends android.renderscript.ScriptIntrinsic {
+    method public static android.renderscript.ScriptIntrinsicConvolve5x5 create(android.renderscript.RenderScript, android.renderscript.Element);
+    method public void forEach(android.renderscript.Allocation);
+    method public android.renderscript.Script.FieldID getFieldID_Input();
+    method public android.renderscript.Script.KernelID getKernelID();
+    method public void setCoefficients(float[]);
+    method public void setInput(android.renderscript.Allocation);
+  }
+
+  public final class ScriptIntrinsicLUT extends android.renderscript.ScriptIntrinsic {
+    method public static android.renderscript.ScriptIntrinsicLUT create(android.renderscript.RenderScript, android.renderscript.Element);
+    method public void forEach(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public android.renderscript.Script.KernelID getKernelID();
+    method public void setAlpha(int, int);
+    method public void setBlue(int, int);
+    method public void setGreen(int, int);
+    method public void setRed(int, int);
+  }
+
+  public final class ScriptIntrinsicYuvToRGB extends android.renderscript.ScriptIntrinsic {
+    method public static android.renderscript.ScriptIntrinsicYuvToRGB create(android.renderscript.RenderScript, android.renderscript.Element);
+    method public void forEach(android.renderscript.Allocation);
+    method public android.renderscript.Script.FieldID getFieldID_Input();
+    method public android.renderscript.Script.KernelID getKernelID();
+    method public void setInput(android.renderscript.Allocation);
+  }
+
   public class Short2 {
     ctor public Short2();
     ctor public Short2(short, short);
@@ -19706,6 +20302,54 @@
 
 }
 
+package android.service.dreams {
+
+  public class DreamService extends android.app.Service implements android.view.Window.Callback {
+    ctor public DreamService();
+    method public void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
+    method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
+    method public boolean dispatchKeyEvent(android.view.KeyEvent);
+    method public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
+    method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+    method public boolean dispatchTouchEvent(android.view.MotionEvent);
+    method public boolean dispatchTrackballEvent(android.view.MotionEvent);
+    method public android.view.View findViewById(int);
+    method public final void finish();
+    method public android.view.Window getWindow();
+    method public android.view.WindowManager getWindowManager();
+    method public boolean isFullscreen();
+    method public boolean isInteractive();
+    method public boolean isScreenBright();
+    method public void onActionModeFinished(android.view.ActionMode);
+    method public void onActionModeStarted(android.view.ActionMode);
+    method public void onAttachedToWindow();
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public void onContentChanged();
+    method public boolean onCreatePanelMenu(int, android.view.Menu);
+    method public android.view.View onCreatePanelView(int);
+    method public void onDetachedFromWindow();
+    method public void onDreamingStarted();
+    method public void onDreamingStopped();
+    method public boolean onMenuItemSelected(int, android.view.MenuItem);
+    method public boolean onMenuOpened(int, android.view.Menu);
+    method public void onPanelClosed(int, android.view.Menu);
+    method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+    method public boolean onSearchRequested();
+    method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
+    method public void onWindowFocusChanged(boolean);
+    method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
+    method public void setContentView(int);
+    method public void setContentView(android.view.View);
+    method public void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
+    method public void setFullscreen(boolean);
+    method public void setInteractive(boolean);
+    method public void setScreenBright(boolean);
+    field public static final java.lang.String DREAM_META_DATA = "android.service.dream";
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.dreams.DreamService";
+  }
+
+}
+
 package android.service.textservice {
 
   public abstract class SpellCheckerService extends android.app.Service {
@@ -19992,12 +20636,123 @@
 
 package android.telephony {
 
+  public final class CellIdentityCdma implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getBasestationId();
+    method public int getLatitude();
+    method public int getLongitude();
+    method public int getNetworkId();
+    method public int getSystemId();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellIdentityGsm implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getCid();
+    method public int getLac();
+    method public int getMcc();
+    method public int getMnc();
+    method public int getPsc();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellIdentityLte implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getCi();
+    method public int getMcc();
+    method public int getMnc();
+    method public int getPci();
+    method public int getTac();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public abstract class CellInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public long getTimeStamp();
+    method public boolean isRegistered();
+    method public abstract void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellInfoCdma extends android.telephony.CellInfo implements android.os.Parcelable {
+    method public android.telephony.CellIdentityCdma getCellIdentity();
+    method public android.telephony.CellSignalStrengthCdma getCellSignalStrength();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellInfoGsm extends android.telephony.CellInfo implements android.os.Parcelable {
+    method public android.telephony.CellIdentityGsm getCellIdentity();
+    method public android.telephony.CellSignalStrengthGsm getCellSignalStrength();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellInfoLte extends android.telephony.CellInfo implements android.os.Parcelable {
+    method public android.telephony.CellIdentityLte getCellIdentity();
+    method public android.telephony.CellSignalStrengthLte getCellSignalStrength();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
   public abstract class CellLocation {
     ctor public CellLocation();
     method public static android.telephony.CellLocation getEmpty();
     method public static void requestLocationUpdate();
   }
 
+  public abstract class CellSignalStrength {
+    method public abstract boolean equals(java.lang.Object);
+    method public abstract int getAsuLevel();
+    method public abstract int getDbm();
+    method public abstract int getLevel();
+    method public abstract int hashCode();
+  }
+
+  public final class CellSignalStrengthCdma extends android.telephony.CellSignalStrength implements android.os.Parcelable {
+    method public int describeContents();
+    method public boolean equals(java.lang.Object);
+    method public int getAsuLevel();
+    method public int getCdmaDbm();
+    method public int getCdmaEcio();
+    method public int getCdmaLevel();
+    method public int getDbm();
+    method public int getEvdoDbm();
+    method public int getEvdoEcio();
+    method public int getEvdoLevel();
+    method public int getEvdoSnr();
+    method public int getLevel();
+    method public int hashCode();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellSignalStrengthGsm extends android.telephony.CellSignalStrength implements android.os.Parcelable {
+    method public int describeContents();
+    method public boolean equals(java.lang.Object);
+    method public int getAsuLevel();
+    method public int getDbm();
+    method public int getLevel();
+    method public int hashCode();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellSignalStrengthLte extends android.telephony.CellSignalStrength implements android.os.Parcelable {
+    method public int describeContents();
+    method public boolean equals(java.lang.Object);
+    method public int getAsuLevel();
+    method public int getDbm();
+    method public int getLevel();
+    method public int getTimingAdvance();
+    method public int hashCode();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
   public class NeighboringCellInfo implements android.os.Parcelable {
     ctor public deprecated NeighboringCellInfo();
     ctor public deprecated NeighboringCellInfo(int, int);
@@ -20070,6 +20825,7 @@
     ctor public PhoneStateListener();
     method public void onCallForwardingIndicatorChanged(boolean);
     method public void onCallStateChanged(int, java.lang.String);
+    method public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>);
     method public void onCellLocationChanged(android.telephony.CellLocation);
     method public void onDataActivity(int);
     method public void onDataConnectionStateChanged(int);
@@ -20080,6 +20836,7 @@
     method public void onSignalStrengthsChanged(android.telephony.SignalStrength);
     field public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8
     field public static final int LISTEN_CALL_STATE = 32; // 0x20
+    field public static final int LISTEN_CELL_INFO = 1024; // 0x400
     field public static final int LISTEN_CELL_LOCATION = 16; // 0x10
     field public static final int LISTEN_DATA_ACTIVITY = 128; // 0x80
     field public static final int LISTEN_DATA_CONNECTION_STATE = 64; // 0x40
@@ -20205,6 +20962,7 @@
   }
 
   public class TelephonyManager {
+    method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
     method public int getCallState();
     method public android.telephony.CellLocation getCellLocation();
     method public int getDataActivity();
@@ -20725,6 +21483,8 @@
     method public int checkUriPermission(android.net.Uri, int, int, int);
     method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public void clearWallpaper();
+    method public android.content.Context createConfigurationContext(android.content.res.Configuration);
+    method public android.content.Context createDisplayContext(android.view.Display);
     method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] databaseList();
     method public boolean deleteDatabase(java.lang.String);
@@ -20771,13 +21531,19 @@
     method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter);
     method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler);
     method public void removeStickyBroadcast(android.content.Intent);
+    method public void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
     method public void revokeUriPermission(android.net.Uri, int);
     method public void sendBroadcast(android.content.Intent);
     method public void sendBroadcast(android.content.Intent, java.lang.String);
+    method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+    method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String);
     method public void sendOrderedBroadcast(android.content.Intent, java.lang.String);
     method public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
     method public void sendStickyBroadcast(android.content.Intent);
+    method public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
     method public void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
     method public void setTheme(int);
     method public void setWallpaper(android.graphics.Bitmap) throws java.io.IOException;
     method public void setWallpaper(java.io.InputStream) throws java.io.IOException;
@@ -20855,6 +21621,7 @@
     method public int checkSignatures(int, int);
     method public void clearPackagePreferredActivities(java.lang.String);
     method public java.lang.String[] currentToCanonicalPackageNames(java.lang.String[]);
+    method public void extendVerificationTimeout(int, int, long);
     method public android.graphics.drawable.Drawable getActivityIcon(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.graphics.drawable.Drawable getActivityIcon(android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.pm.ActivityInfo getActivityInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -21423,6 +22190,7 @@
     method public static java.lang.CharSequence expandTemplate(java.lang.CharSequence, java.lang.CharSequence...);
     method public static int getCapsMode(java.lang.CharSequence, int, int);
     method public static void getChars(java.lang.CharSequence, int, int, char[], int);
+    method public static int getLayoutDirectionFromLocale(java.util.Locale);
     method public static int getOffsetAfter(java.lang.CharSequence, int);
     method public static int getOffsetBefore(java.lang.CharSequence, int);
     method public static java.lang.CharSequence getReverse(java.lang.CharSequence, int, int);
@@ -21494,14 +22262,14 @@
 
   public class DateFormat {
     ctor public DateFormat();
-    method public static final java.lang.CharSequence format(java.lang.CharSequence, long);
-    method public static final java.lang.CharSequence format(java.lang.CharSequence, java.util.Date);
-    method public static final java.lang.CharSequence format(java.lang.CharSequence, java.util.Calendar);
-    method public static final java.text.DateFormat getDateFormat(android.content.Context);
-    method public static final char[] getDateFormatOrder(android.content.Context);
-    method public static final java.text.DateFormat getLongDateFormat(android.content.Context);
-    method public static final java.text.DateFormat getMediumDateFormat(android.content.Context);
-    method public static final java.text.DateFormat getTimeFormat(android.content.Context);
+    method public static java.lang.CharSequence format(java.lang.CharSequence, long);
+    method public static java.lang.CharSequence format(java.lang.CharSequence, java.util.Date);
+    method public static java.lang.CharSequence format(java.lang.CharSequence, java.util.Calendar);
+    method public static java.text.DateFormat getDateFormat(android.content.Context);
+    method public static char[] getDateFormatOrder(android.content.Context);
+    method public static java.text.DateFormat getLongDateFormat(android.content.Context);
+    method public static java.text.DateFormat getMediumDateFormat(android.content.Context);
+    method public static java.text.DateFormat getTimeFormat(android.content.Context);
     method public static boolean is24HourFormat(android.content.Context);
     field public static final char AM_PM = 97; // 0x0061 'a'
     field public static final char CAPITAL_AM_PM = 65; // 0x0041 'A'
@@ -21513,6 +22281,7 @@
     field public static final char MONTH = 77; // 0x004d 'M'
     field public static final char QUOTE = 39; // 0x0027 '\''
     field public static final char SECONDS = 115; // 0x0073 's'
+    field public static final char STANDALONE_MONTH = 76; // 0x004c 'L'
     field public static final char TIME_ZONE = 122; // 0x007a 'z'
     field public static final char YEAR = 121; // 0x0079 'y'
   }
@@ -22051,6 +22820,17 @@
     method public abstract void chooseHeight(java.lang.CharSequence, int, int, int, int, android.graphics.Paint.FontMetricsInt, android.text.TextPaint);
   }
 
+  public class LocaleSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
+    ctor public LocaleSpan(java.util.Locale);
+    ctor public LocaleSpan(android.os.Parcel);
+    method public int describeContents();
+    method public java.util.Locale getLocale();
+    method public int getSpanTypeId();
+    method public void updateDrawState(android.text.TextPaint);
+    method public void updateMeasureState(android.text.TextPaint);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
   public class MaskFilterSpan extends android.text.style.CharacterStyle implements android.text.style.UpdateAppearance {
     ctor public MaskFilterSpan(android.graphics.MaskFilter);
     method public android.graphics.MaskFilter getMaskFilter();
@@ -22312,6 +23092,17 @@
     ctor public AndroidRuntimeException(java.lang.Exception);
   }
 
+  public class AtomicFile {
+    ctor public AtomicFile(java.io.File);
+    method public void delete();
+    method public void failWrite(java.io.FileOutputStream);
+    method public void finishWrite(java.io.FileOutputStream);
+    method public java.io.File getBaseFile();
+    method public java.io.FileInputStream openRead() throws java.io.FileNotFoundException;
+    method public byte[] readFully() throws java.io.IOException;
+    method public java.io.FileOutputStream startWrite() throws java.io.IOException;
+  }
+
   public abstract interface AttributeSet {
     method public abstract boolean getAttributeBooleanValue(java.lang.String, java.lang.String, boolean);
     method public abstract boolean getAttributeBooleanValue(int, boolean);
@@ -22379,6 +23170,7 @@
 
   public class DisplayMetrics {
     ctor public DisplayMetrics();
+    method public boolean equals(android.util.DisplayMetrics);
     method public void setTo(android.util.DisplayMetrics);
     method public void setToDefaults();
     field public static final int DENSITY_DEFAULT = 160; // 0xa0
@@ -22430,7 +23222,10 @@
   public class FloatMath {
     method public static float ceil(float);
     method public static float cos(float);
+    method public static float exp(float);
     method public static float floor(float);
+    method public static float hypot(float, float);
+    method public static float pow(float, float);
     method public static float sin(float);
     method public static float sqrt(float);
   }
@@ -22560,6 +23355,7 @@
     method protected int sizeOf(K, V);
     method public final synchronized java.util.Map<K, V> snapshot();
     method public final synchronized java.lang.String toString();
+    method public void trimToSize(int);
   }
 
   public final class MalformedJsonException extends java.io.IOException {
@@ -22891,22 +23687,30 @@
   public class ContextThemeWrapper extends android.content.ContextWrapper {
     ctor public ContextThemeWrapper();
     ctor public ContextThemeWrapper(android.content.Context, int);
+    method public void applyOverrideConfiguration(android.content.res.Configuration);
     method protected void onApplyThemeResource(android.content.res.Resources.Theme, int, boolean);
   }
 
-  public class Display {
+  public final class Display {
     method public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point);
     method public int getDisplayId();
+    method public int getFlags();
     method public deprecated int getHeight();
     method public void getMetrics(android.util.DisplayMetrics);
+    method public java.lang.String getName();
     method public deprecated int getOrientation();
-    method public int getPixelFormat();
+    method public deprecated int getPixelFormat();
+    method public void getRealMetrics(android.util.DisplayMetrics);
+    method public void getRealSize(android.graphics.Point);
     method public void getRectSize(android.graphics.Rect);
     method public float getRefreshRate();
     method public int getRotation();
     method public void getSize(android.graphics.Point);
     method public deprecated int getWidth();
+    method public boolean isValid();
     field public static final int DEFAULT_DISPLAY = 0; // 0x0
+    field public static final int FLAG_SECURE = 2; // 0x2
+    field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1
   }
 
   public class DragEvent implements android.os.Parcelable {
@@ -22978,8 +23782,12 @@
   public class Gravity {
     ctor public Gravity();
     method public static void apply(int, int, int, android.graphics.Rect, android.graphics.Rect);
+    method public static void apply(int, int, int, android.graphics.Rect, android.graphics.Rect, int);
     method public static void apply(int, int, int, android.graphics.Rect, int, int, android.graphics.Rect);
+    method public static void apply(int, int, int, android.graphics.Rect, int, int, android.graphics.Rect, int);
     method public static void applyDisplay(int, android.graphics.Rect, android.graphics.Rect);
+    method public static void applyDisplay(int, android.graphics.Rect, android.graphics.Rect, int);
+    method public static int getAbsoluteGravity(int, int);
     method public static boolean isHorizontal(int);
     method public static boolean isVertical(int);
     field public static final int AXIS_CLIP = 8; // 0x8
@@ -23892,7 +24700,7 @@
     method public android.graphics.Canvas lockCanvas(android.graphics.Rect) throws java.lang.IllegalArgumentException, android.view.Surface.OutOfResourcesException;
     method public void readFromParcel(android.os.Parcel);
     method public void release();
-    method public void unlockCanvas(android.graphics.Canvas);
+    method public deprecated void unlockCanvas(android.graphics.Canvas);
     method public void unlockCanvasAndPost(android.graphics.Canvas);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
@@ -23948,6 +24756,7 @@
     ctor public SurfaceView(android.content.Context, android.util.AttributeSet, int);
     method public boolean gatherTransparentRegion(android.graphics.Region);
     method public android.view.SurfaceHolder getHolder();
+    method public void setSecure(boolean);
     method public void setZOrderMediaOverlay(boolean);
     method public void setZOrderOnTop(boolean);
   }
@@ -24074,6 +24883,7 @@
     method protected boolean fitSystemWindows(android.graphics.Rect);
     method public android.view.View focusSearch(int);
     method public void forceLayout();
+    method public static int generateViewId();
     method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider();
     method public float getAlpha();
     method public android.view.animation.Animation getAnimation();
@@ -24088,6 +24898,7 @@
     method public final android.content.Context getContext();
     method protected android.view.ContextMenu.ContextMenuInfo getContextMenuInfo();
     method public static int getDefaultSize(int, int);
+    method public android.view.Display getDisplay();
     method public final int[] getDrawableState();
     method public android.graphics.Bitmap getDrawingCache();
     method public android.graphics.Bitmap getDrawingCache(boolean);
@@ -24097,7 +24908,6 @@
     method public long getDrawingTime();
     method public boolean getFilterTouchesWhenObscured();
     method public boolean getFitsSystemWindows();
-    method public void getFocusRect(android.graphics.Rect);
     method public java.util.ArrayList<android.view.View> getFocusables(int);
     method public void getFocusedRect(android.graphics.Rect);
     method public boolean getGlobalVisibleRect(android.graphics.Rect, android.graphics.Point);
@@ -24111,7 +24921,9 @@
     method public int getImportantForAccessibility();
     method public boolean getKeepScreenOn();
     method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
+    method public int getLabelFor();
     method public int getLayerType();
+    method public int getLayoutDirection();
     method public android.view.ViewGroup.LayoutParams getLayoutParams();
     method public final int getLeft();
     method protected float getLeftFadingEdgeStrength();
@@ -24135,8 +24947,10 @@
     method public android.view.View.OnFocusChangeListener getOnFocusChangeListener();
     method public int getOverScrollMode();
     method public int getPaddingBottom();
+    method public int getPaddingEnd();
     method public int getPaddingLeft();
     method public int getPaddingRight();
+    method public int getPaddingStart();
     method public int getPaddingTop();
     method public final android.view.ViewParent getParent();
     method public android.view.ViewParent getParentForAccessibility();
@@ -24164,6 +24978,8 @@
     method public int getSystemUiVisibility();
     method public java.lang.Object getTag();
     method public java.lang.Object getTag(int);
+    method public int getTextAlignment();
+    method public int getTextDirection();
     method public final int getTop();
     method protected float getTopFadingEdgeStrength();
     method protected int getTopPaddingOffset();
@@ -24217,6 +25033,7 @@
     method public boolean isLongClickable();
     method public boolean isOpaque();
     method protected boolean isPaddingOffsetRequired();
+    method public boolean isPaddingRelative();
     method public boolean isPressed();
     method public boolean isSaveEnabled();
     method public boolean isSaveFromParentEnabled();
@@ -24266,6 +25083,7 @@
     method protected void onOverScrolled(int, int, boolean, boolean);
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method protected void onRestoreInstanceState(android.os.Parcelable);
+    method public void onRtlPropertiesChanged(int);
     method protected android.os.Parcelable onSaveInstanceState();
     method public void onScreenStateChanged(int);
     method protected void onScrollChanged(int, int, int, int);
@@ -24346,7 +25164,10 @@
     method public void setId(int);
     method public void setImportantForAccessibility(int);
     method public void setKeepScreenOn(boolean);
+    method public void setLabelFor(int);
+    method public void setLayerPaint(android.graphics.Paint);
     method public void setLayerType(int, android.graphics.Paint);
+    method public void setLayoutDirection(int);
     method public void setLayoutParams(android.view.ViewGroup.LayoutParams);
     method public final void setLeft(int);
     method public void setLongClickable(boolean);
@@ -24370,6 +25191,7 @@
     method public void setOnTouchListener(android.view.View.OnTouchListener);
     method public void setOverScrollMode(int);
     method public void setPadding(int, int, int, int);
+    method public void setPaddingRelative(int, int, int, int);
     method public void setPivotX(float);
     method public void setPivotY(float);
     method public void setPressed(boolean);
@@ -24394,6 +25216,8 @@
     method public void setSystemUiVisibility(int);
     method public void setTag(java.lang.Object);
     method public void setTag(int, java.lang.Object);
+    method public void setTextAlignment(int);
+    method public void setTextDirection(int);
     method public final void setTop(int);
     method public void setTouchDelegate(android.view.TouchDelegate);
     method public void setTranslationX(float);
@@ -24452,6 +25276,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 = 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
@@ -24502,8 +25330,19 @@
     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 SYSTEM_UI_LAYOUT_FLAGS = 1536; // 0x600
+    field public static final int TEXT_ALIGNMENT_CENTER = 4; // 0x4
+    field public static final int TEXT_ALIGNMENT_GRAVITY = 1; // 0x1
     field public static final int TEXT_ALIGNMENT_INHERIT = 0; // 0x0
-    field public static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = 131072; // 0x20000
+    field public static final int TEXT_ALIGNMENT_TEXT_END = 3; // 0x3
+    field public static final int TEXT_ALIGNMENT_TEXT_START = 2; // 0x2
+    field public static final int TEXT_ALIGNMENT_VIEW_END = 6; // 0x6
+    field public static final int TEXT_ALIGNMENT_VIEW_START = 5; // 0x5
+    field public static final int TEXT_DIRECTION_ANY_RTL = 2; // 0x2
+    field 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
+    field public static final int TEXT_DIRECTION_LTR = 3; // 0x3
+    field public static final int TEXT_DIRECTION_RTL = 4; // 0x4
     field public static final android.util.Property TRANSLATION_X;
     field public static final android.util.Property TRANSLATION_Y;
     field protected static final java.lang.String VIEW_LOG_TAG = "View";
@@ -24807,6 +25646,7 @@
     ctor public ViewGroup.LayoutParams(android.content.Context, android.util.AttributeSet);
     ctor public ViewGroup.LayoutParams(int, int);
     ctor public ViewGroup.LayoutParams(android.view.ViewGroup.LayoutParams);
+    method public void resolveLayoutDirection(int);
     method protected void setBaseAttributes(android.content.res.TypedArray, int, int);
     field public static final deprecated int FILL_PARENT = -1; // 0xffffffff
     field public static final int MATCH_PARENT = -1; // 0xffffffff
@@ -24821,6 +25661,13 @@
     ctor public ViewGroup.MarginLayoutParams(int, int);
     ctor public ViewGroup.MarginLayoutParams(android.view.ViewGroup.MarginLayoutParams);
     ctor public ViewGroup.MarginLayoutParams(android.view.ViewGroup.LayoutParams);
+    method public int getLayoutDirection();
+    method public int getMarginEnd();
+    method public int getMarginStart();
+    method public boolean isMarginRelative();
+    method public void setLayoutDirection(int);
+    method public void setMarginEnd(int);
+    method public void setMarginStart(int);
     method public void setMargins(int, int, int, int);
     field public int bottomMargin;
     field public int leftMargin;
@@ -25097,6 +25944,11 @@
     ctor public WindowManager.BadTokenException(java.lang.String);
   }
 
+  public static class WindowManager.InvalidDisplayException extends java.lang.RuntimeException {
+    ctor public WindowManager.InvalidDisplayException();
+    ctor public WindowManager.InvalidDisplayException(java.lang.String);
+  }
+
   public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
     ctor public WindowManager.LayoutParams();
     ctor public WindowManager.LayoutParams(int);
@@ -25128,7 +25980,7 @@
     field public static final deprecated int FLAG_BLUR_BEHIND = 4; // 0x4
     field public static final int FLAG_DIM_BEHIND = 2; // 0x2
     field public static final int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000
-    field public static final int FLAG_DITHER = 4096; // 0x1000
+    field public static final deprecated int FLAG_DITHER = 4096; // 0x1000
     field public static final int FLAG_FORCE_NOT_FULLSCREEN = 2048; // 0x800
     field public static final int FLAG_FULLSCREEN = 1024; // 0x400
     field public static final int FLAG_HARDWARE_ACCELERATED = 16777216; // 0x1000000
@@ -25251,9 +26103,13 @@
     field public static final deprecated int MAX_TEXT_LENGTH = 500; // 0x1f4
     field public static final int TYPES_ALL_MASK = -1; // 0xffffffff
     field public static final int TYPE_ANNOUNCEMENT = 16384; // 0x4000
+    field public static final int TYPE_GESTURE_DETECTION_END = 524288; // 0x80000
+    field public static final int TYPE_GESTURE_DETECTION_START = 262144; // 0x40000
     field public static final int TYPE_NOTIFICATION_STATE_CHANGED = 64; // 0x40
     field public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 1024; // 0x400
     field public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 512; // 0x200
+    field public static final int TYPE_TOUCH_INTERACTION_END = 2097152; // 0x200000
+    field public static final int TYPE_TOUCH_INTERACTION_START = 1048576; // 0x100000
     field public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 32768; // 0x8000
     field public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 65536; // 0x10000
     field public static final int TYPE_VIEW_CLICKED = 1; // 0x1
@@ -25306,6 +26162,8 @@
     method public int getChildCount();
     method public java.lang.CharSequence getClassName();
     method public java.lang.CharSequence getContentDescription();
+    method public android.view.accessibility.AccessibilityNodeInfo getLabelFor();
+    method public android.view.accessibility.AccessibilityNodeInfo getLabeledBy();
     method public int getMovementGranularities();
     method public java.lang.CharSequence getPackageName();
     method public android.view.accessibility.AccessibilityNodeInfo getParent();
@@ -25341,6 +26199,10 @@
     method public void setEnabled(boolean);
     method public void setFocusable(boolean);
     method public void setFocused(boolean);
+    method public void setLabelFor(android.view.View);
+    method public void setLabelFor(android.view.View, int);
+    method public void setLabeledBy(android.view.View);
+    method public void setLabeledBy(android.view.View, int);
     method public void setLongClickable(boolean);
     method public void setMovementGranularities(int);
     method public void setPackageName(java.lang.CharSequence);
@@ -25981,6 +26843,7 @@
 
   public abstract interface InputMethodSession {
     method public abstract void appPrivateCommand(java.lang.String, android.os.Bundle);
+    method public abstract void dispatchGenericMotionEvent(int, android.view.MotionEvent, android.view.inputmethod.InputMethodSession.EventCallback);
     method public abstract void dispatchKeyEvent(int, android.view.KeyEvent, android.view.inputmethod.InputMethodSession.EventCallback);
     method public abstract void dispatchTrackballEvent(int, android.view.MotionEvent, android.view.inputmethod.InputMethodSession.EventCallback);
     method public abstract void displayCompletions(android.view.inputmethod.CompletionInfo[]);
@@ -25998,6 +26861,7 @@
 
   public final class InputMethodSubtype implements android.os.Parcelable {
     ctor public InputMethodSubtype(int, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean);
+    ctor public InputMethodSubtype(int, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean, int);
     method public boolean containsExtraValueKey(java.lang.String);
     method public int describeContents();
     method public java.lang.CharSequence getDisplayName(android.content.Context, java.lang.String, android.content.pm.ApplicationInfo);
@@ -26111,35 +26975,6 @@
 
 package android.webkit {
 
-  public final deprecated class CacheManager {
-    ctor public CacheManager();
-    method public static deprecated boolean cacheDisabled();
-    method public static deprecated boolean endCacheTransaction();
-    method public static deprecated android.webkit.CacheManager.CacheResult getCacheFile(java.lang.String, java.util.Map<java.lang.String, java.lang.String>);
-    method public static deprecated java.io.File getCacheFileBaseDir();
-    method public static deprecated void saveCacheFile(java.lang.String, android.webkit.CacheManager.CacheResult);
-    method public static deprecated boolean startCacheTransaction();
-  }
-
-  public static deprecated class CacheManager.CacheResult {
-    ctor public CacheManager.CacheResult();
-    method public java.lang.String getContentDisposition();
-    method public long getContentLength();
-    method public java.lang.String getETag();
-    method public java.lang.String getEncoding();
-    method public long getExpires();
-    method public java.lang.String getExpiresString();
-    method public int getHttpStatusCode();
-    method public java.io.InputStream getInputStream();
-    method public java.lang.String getLastModified();
-    method public java.lang.String getLocalPath();
-    method public java.lang.String getLocation();
-    method public java.lang.String getMimeType();
-    method public java.io.OutputStream getOutputStream();
-    method public void setEncoding(java.lang.String);
-    method public void setInputStream(java.io.InputStream);
-  }
-
   public class ConsoleMessage {
     ctor public ConsoleMessage(java.lang.String, java.lang.String, int, android.webkit.ConsoleMessage.MessageLevel);
     method public int lineNumber();
@@ -26209,6 +27044,9 @@
     method public boolean useHttpAuthUsernamePassword();
   }
 
+  public abstract class JavascriptInterface implements java.lang.annotation.Annotation {
+  }
+
   public class JsPromptResult extends android.webkit.JsResult {
     method public void confirm(java.lang.String);
   }
@@ -26285,7 +27123,7 @@
     method public boolean onJsBeforeUnload(android.webkit.WebView, java.lang.String, java.lang.String, android.webkit.JsResult);
     method public boolean onJsConfirm(android.webkit.WebView, java.lang.String, java.lang.String, android.webkit.JsResult);
     method public boolean onJsPrompt(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String, android.webkit.JsPromptResult);
-    method public boolean onJsTimeout();
+    method public deprecated boolean onJsTimeout();
     method public void onProgressChanged(android.webkit.WebView, int);
     method public void onReachedMaxAppCacheSize(long, long, android.webkit.WebStorage.QuotaUpdater);
     method public void onReceivedIcon(android.webkit.WebView, android.graphics.Bitmap);
@@ -26302,7 +27140,6 @@
 
   public class WebHistoryItem implements java.lang.Cloneable {
     method public android.graphics.Bitmap getFavicon();
-    method public deprecated int getId();
     method public java.lang.String getOriginalUrl();
     method public java.lang.String getTitle();
     method public java.lang.String getUrl();
@@ -26333,7 +27170,7 @@
   }
 
   public abstract class WebSettings {
-    method public boolean enableSmoothTransition();
+    method public deprecated boolean enableSmoothTransition();
     method public boolean getAllowContentAccess();
     method public boolean getAllowFileAccess();
     method public abstract boolean getAllowFileAccessFromFileURLs();
@@ -26348,6 +27185,7 @@
     method public synchronized int getDefaultFixedFontSize();
     method public synchronized int getDefaultFontSize();
     method public synchronized java.lang.String getDefaultTextEncodingName();
+    method public static java.lang.String getDefaultUserAgent(android.content.Context);
     method public android.webkit.WebSettings.ZoomDensity getDefaultZoom();
     method public boolean getDisplayZoomControls();
     method public synchronized boolean getDomStorageEnabled();
@@ -26359,9 +27197,9 @@
     method public boolean getLightTouchEnabled();
     method public boolean getLoadWithOverviewMode();
     method public synchronized boolean getLoadsImagesAutomatically();
+    method public boolean getMediaPlaybackRequiresUserGesture();
     method public synchronized int getMinimumFontSize();
     method public synchronized int getMinimumLogicalFontSize();
-    method public deprecated boolean getNavDump();
     method public synchronized android.webkit.WebSettings.PluginState getPluginState();
     method public deprecated synchronized boolean getPluginsEnabled();
     method public deprecated synchronized java.lang.String getPluginsPath();
@@ -26372,10 +27210,7 @@
     method public synchronized java.lang.String getStandardFontFamily();
     method public deprecated synchronized android.webkit.WebSettings.TextSize getTextSize();
     method public synchronized int getTextZoom();
-    method public deprecated synchronized boolean getUseDoubleTree();
-    method public deprecated boolean getUseWebViewBackgroundForOverscrollBackground();
     method public synchronized boolean getUseWideViewPort();
-    method public deprecated synchronized int getUserAgent();
     method public synchronized java.lang.String getUserAgentString();
     method public void setAllowContentAccess(boolean);
     method public void setAllowFileAccess(boolean);
@@ -26397,7 +27232,7 @@
     method public void setDefaultZoom(android.webkit.WebSettings.ZoomDensity);
     method public void setDisplayZoomControls(boolean);
     method public synchronized void setDomStorageEnabled(boolean);
-    method public void setEnableSmoothTransition(boolean);
+    method public deprecated void setEnableSmoothTransition(boolean);
     method public synchronized void setFantasyFontFamily(java.lang.String);
     method public synchronized void setFixedFontFamily(java.lang.String);
     method public synchronized void setGeolocationDatabasePath(java.lang.String);
@@ -26408,9 +27243,9 @@
     method public void setLightTouchEnabled(boolean);
     method public void setLoadWithOverviewMode(boolean);
     method public synchronized void setLoadsImagesAutomatically(boolean);
+    method public void setMediaPlaybackRequiresUserGesture(boolean);
     method public synchronized void setMinimumFontSize(int);
     method public synchronized void setMinimumLogicalFontSize(int);
-    method public deprecated void setNavDump(boolean);
     method public void setNeedInitialFocus(boolean);
     method public synchronized void setPluginState(android.webkit.WebSettings.PluginState);
     method public deprecated synchronized void setPluginsEnabled(boolean);
@@ -26425,17 +27260,14 @@
     method public void setSupportZoom(boolean);
     method public deprecated synchronized void setTextSize(android.webkit.WebSettings.TextSize);
     method public synchronized void setTextZoom(int);
-    method public deprecated synchronized void setUseDoubleTree(boolean);
-    method public deprecated void setUseWebViewBackgroundForOverscrollBackground(boolean);
     method public synchronized void setUseWideViewPort(boolean);
-    method public deprecated synchronized void setUserAgent(int);
     method public synchronized void setUserAgentString(java.lang.String);
     method public synchronized boolean supportMultipleWindows();
     method public boolean supportZoom();
     field public static final int LOAD_CACHE_ELSE_NETWORK = 1; // 0x1
     field public static final int LOAD_CACHE_ONLY = 3; // 0x3
     field public static final int LOAD_DEFAULT = -1; // 0xffffffff
-    field public static final int LOAD_NORMAL = 0; // 0x0
+    field public static final deprecated int LOAD_NORMAL = 0; // 0x0
     field public static final int LOAD_NO_CACHE = 2; // 0x2
   }
 
@@ -26518,13 +27350,13 @@
     ctor public WebView(android.content.Context);
     ctor public WebView(android.content.Context, android.util.AttributeSet);
     ctor public WebView(android.content.Context, android.util.AttributeSet, int);
-    ctor public WebView(android.content.Context, android.util.AttributeSet, int, boolean);
+    ctor public deprecated WebView(android.content.Context, android.util.AttributeSet, int, boolean);
     method public void addJavascriptInterface(java.lang.Object, java.lang.String);
     method public boolean canGoBack();
     method public boolean canGoBackOrForward(int);
     method public boolean canGoForward();
-    method public boolean canZoomIn();
-    method public boolean canZoomOut();
+    method public deprecated boolean canZoomIn();
+    method public deprecated boolean canZoomOut();
     method public android.graphics.Picture capturePicture();
     method public void clearCache(boolean);
     method public void clearFormData();
@@ -26533,12 +27365,8 @@
     method public void clearSslPreferences();
     method public void clearView();
     method public android.webkit.WebBackForwardList copyBackForwardList();
-    method public deprecated void debugDump();
     method public void destroy();
-    method public static deprecated void disablePlatformNotifications();
     method public void documentHasImages(android.os.Message);
-    method public deprecated void emulateShiftHeld();
-    method public static deprecated void enablePlatformNotifications();
     method public static java.lang.String findAddress(java.lang.String);
     method public deprecated int findAll(java.lang.String);
     method public void findAllAsync(java.lang.String);
@@ -26552,11 +27380,10 @@
     method public java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
     method public java.lang.String getOriginalUrl();
     method public int getProgress();
-    method public float getScale();
+    method public deprecated float getScale();
     method public android.webkit.WebSettings getSettings();
     method public java.lang.String getTitle();
     method public java.lang.String getUrl();
-    method public deprecated int getVisibleTitleHeight();
     method public void goBack();
     method public void goBackOrForward(int);
     method public void goForward();
@@ -26581,21 +27408,19 @@
     method public void removeJavascriptInterface(java.lang.String);
     method public void requestFocusNodeHref(android.os.Message);
     method public void requestImageRef(android.os.Message);
-    method public deprecated boolean restorePicture(android.os.Bundle, java.io.File);
     method public android.webkit.WebBackForwardList restoreState(android.os.Bundle);
     method public void resumeTimers();
     method public void savePassword(java.lang.String, java.lang.String, java.lang.String);
-    method public deprecated boolean savePicture(android.os.Bundle, java.io.File);
     method public android.webkit.WebBackForwardList saveState(android.os.Bundle);
     method public void saveWebArchive(java.lang.String);
     method public void saveWebArchive(java.lang.String, boolean, android.webkit.ValueCallback<java.lang.String>);
-    method public void setCertificate(android.net.http.SslCertificate);
+    method public deprecated void setCertificate(android.net.http.SslCertificate);
     method public void setDownloadListener(android.webkit.DownloadListener);
     method public void setFindListener(android.webkit.WebView.FindListener);
     method public void setHorizontalScrollbarOverlay(boolean);
     method public void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
     method public void setInitialScale(int);
-    method public void setMapTrackballToArrowKeys(boolean);
+    method public deprecated void setMapTrackballToArrowKeys(boolean);
     method public void setNetworkAvailable(boolean);
     method public deprecated void setPictureListener(android.webkit.WebView.PictureListener);
     method public void setVerticalScrollbarOverlay(boolean);
@@ -26677,11 +27502,10 @@
     method public void clearFormData();
     method public void clearHttpAuthUsernamePassword();
     method public void clearUsernamePassword();
-    method public static synchronized android.webkit.WebViewDatabase getInstance(android.content.Context);
+    method public static android.webkit.WebViewDatabase getInstance(android.content.Context);
     method public boolean hasFormData();
     method public boolean hasHttpAuthUsernamePassword();
     method public boolean hasUsernamePassword();
-    field protected static final java.lang.String LOGTAG = "webviewdatabase";
   }
 
   public class WebViewFragment extends android.app.Fragment {
@@ -27045,13 +27869,19 @@
     method public void setDropDownVerticalOffset(int);
     method public void setDropDownWidth(int);
     method public void setListSelection(int);
+    method public void setOnDismissListener(android.widget.AutoCompleteTextView.OnDismissListener);
     method public void setOnItemClickListener(android.widget.AdapterView.OnItemClickListener);
     method public void setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener);
+    method public void setText(java.lang.CharSequence, boolean);
     method public void setThreshold(int);
     method public void setValidator(android.widget.AutoCompleteTextView.Validator);
     method public void showDropDown();
   }
 
+  public static abstract interface AutoCompleteTextView.OnDismissListener {
+    method public abstract void onDismiss();
+  }
+
   public static abstract interface AutoCompleteTextView.Validator {
     method public abstract java.lang.CharSequence fixText(java.lang.CharSequence);
     method public abstract boolean isValid(java.lang.CharSequence);
@@ -27155,7 +27985,6 @@
     ctor public CheckedTextView(android.content.Context, android.util.AttributeSet, int);
     method public android.graphics.drawable.Drawable getCheckMarkDrawable();
     method public boolean isChecked();
-    method public void onPaddingChanged(int);
     method public void setCheckMarkDrawable(int);
     method public void setCheckMarkDrawable(android.graphics.drawable.Drawable);
     method public void setChecked(boolean);
@@ -27298,7 +28127,7 @@
     field public static final int LETTERS_ONLY = 5; // 0x5
   }
 
-  public class DigitalClock extends android.widget.TextView {
+  public deprecated class DigitalClock extends android.widget.TextView {
     ctor public DigitalClock(android.content.Context);
     ctor public DigitalClock(android.content.Context, android.util.AttributeSet);
   }
@@ -28114,19 +28943,25 @@
     field public static final int ABOVE = 2; // 0x2
     field public static final int ALIGN_BASELINE = 4; // 0x4
     field public static final int ALIGN_BOTTOM = 8; // 0x8
+    field public static final int ALIGN_END = 19; // 0x13
     field public static final int ALIGN_LEFT = 5; // 0x5
     field public static final int ALIGN_PARENT_BOTTOM = 12; // 0xc
+    field public static final int ALIGN_PARENT_END = 21; // 0x15
     field public static final int ALIGN_PARENT_LEFT = 9; // 0x9
     field public static final int ALIGN_PARENT_RIGHT = 11; // 0xb
+    field public static final int ALIGN_PARENT_START = 20; // 0x14
     field public static final int ALIGN_PARENT_TOP = 10; // 0xa
     field public static final int ALIGN_RIGHT = 7; // 0x7
+    field public static final int ALIGN_START = 18; // 0x12
     field public static final int ALIGN_TOP = 6; // 0x6
     field public static final int BELOW = 3; // 0x3
     field public static final int CENTER_HORIZONTAL = 14; // 0xe
     field public static final int CENTER_IN_PARENT = 13; // 0xd
     field public static final int CENTER_VERTICAL = 15; // 0xf
+    field public static final int END_OF = 17; // 0x11
     field public static final int LEFT_OF = 0; // 0x0
     field public static final int RIGHT_OF = 1; // 0x1
+    field public static final int START_OF = 16; // 0x10
     field public static final int TRUE = -1; // 0xffffffff
   }
 
@@ -28139,6 +28974,7 @@
     method public void addRule(int, int);
     method public java.lang.String debug(java.lang.String);
     method public int[] getRules();
+    method public void removeRule(int);
     field public boolean alignWithParent;
   }
 
@@ -28172,6 +29008,7 @@
     method public void setImageViewUri(int, android.net.Uri);
     method public void setInt(int, java.lang.String, int);
     method public void setIntent(int, java.lang.String, android.content.Intent);
+    method public void setLabelFor(int, int);
     method public void setLong(int, java.lang.String, long);
     method public void setOnClickFillInIntent(int, android.content.Intent);
     method public void setOnClickPendingIntent(int, android.app.PendingIntent);
@@ -28440,7 +29277,7 @@
     method public android.view.View newGroupView(boolean, android.view.ViewGroup);
   }
 
-  public class SlidingDrawer extends android.view.ViewGroup {
+  public deprecated class SlidingDrawer extends android.view.ViewGroup {
     ctor public SlidingDrawer(android.content.Context, android.util.AttributeSet);
     ctor public SlidingDrawer(android.content.Context, android.util.AttributeSet, int);
     method public void animateClose();
@@ -28643,6 +29480,21 @@
     field public int span;
   }
 
+  public class TextClock extends android.widget.TextView {
+    ctor public TextClock(android.content.Context);
+    ctor public TextClock(android.content.Context, android.util.AttributeSet);
+    ctor public TextClock(android.content.Context, android.util.AttributeSet, int);
+    method public java.lang.CharSequence getFormat12Hour();
+    method public java.lang.CharSequence getFormat24Hour();
+    method public java.lang.String getTimeZone();
+    method public boolean is24HourModeEnabled();
+    method public void setFormat12Hour(java.lang.CharSequence);
+    method public void setFormat24Hour(java.lang.CharSequence);
+    method public void setTimeZone(java.lang.String);
+    field public static final java.lang.CharSequence DEFAULT_FORMAT_12_HOUR;
+    field public static final java.lang.CharSequence DEFAULT_FORMAT_24_HOUR;
+  }
+
   public class TextSwitcher extends android.widget.ViewSwitcher {
     ctor public TextSwitcher(android.content.Context);
     ctor public TextSwitcher(android.content.Context, android.util.AttributeSet);
@@ -28667,9 +29519,12 @@
     method public final int getAutoLinkMask();
     method public int getCompoundDrawablePadding();
     method public android.graphics.drawable.Drawable[] getCompoundDrawables();
+    method public android.graphics.drawable.Drawable[] getCompoundDrawablesRelative();
     method public int getCompoundPaddingBottom();
+    method public int getCompoundPaddingEnd();
     method public int getCompoundPaddingLeft();
     method public int getCompoundPaddingRight();
+    method public int getCompoundPaddingStart();
     method public int getCompoundPaddingTop();
     method public final int getCurrentHintTextColor();
     method public final int getCurrentTextColor();
@@ -28726,11 +29581,14 @@
     method public static int getTextColor(android.content.Context, android.content.res.TypedArray, int);
     method public final android.content.res.ColorStateList getTextColors();
     method public static android.content.res.ColorStateList getTextColors(android.content.Context, android.content.res.TypedArray);
+    method public java.util.Locale getTextLocale();
     method public float getTextScaleX();
     method public float getTextSize();
     method public int getTotalPaddingBottom();
+    method public int getTotalPaddingEnd();
     method public int getTotalPaddingLeft();
     method public int getTotalPaddingRight();
+    method public int getTotalPaddingStart();
     method public int getTotalPaddingTop();
     method public final android.text.method.TransformationMethod getTransformationMethod();
     method public android.graphics.Typeface getTypeface();
@@ -28755,12 +29613,13 @@
     method protected void onTextChanged(java.lang.CharSequence, int, int, int);
     method public boolean onTextContextMenuItem(int);
     method public void removeTextChangedListener(android.text.TextWatcher);
-    method protected void resetResolvedDrawables();
-    method protected void resolveDrawables();
     method public void setAllCaps(boolean);
     method public final void setAutoLinkMask(int);
     method public void setCompoundDrawablePadding(int);
     method public void setCompoundDrawables(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
+    method public void setCompoundDrawablesRelative(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
+    method public void setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int);
+    method public void setCompoundDrawablesRelativeWithIntrinsicBounds(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
     method public void setCompoundDrawablesWithIntrinsicBounds(int, int, int, int);
     method public void setCompoundDrawablesWithIntrinsicBounds(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
     method public void setCursorVisible(boolean);
@@ -28804,7 +29663,6 @@
     method public void setMinWidth(int);
     method public final void setMovementMethod(android.text.method.MovementMethod);
     method public void setOnEditorActionListener(android.widget.TextView.OnEditorActionListener);
-    method public void setPaddingRelative(int, int, int, int);
     method public void setPaintFlags(int);
     method public void setPrivateImeOptions(java.lang.String);
     method public void setRawInputType(int);
@@ -28825,6 +29683,7 @@
     method public void setTextIsSelectable(boolean);
     method public final void setTextKeepState(java.lang.CharSequence);
     method public final void setTextKeepState(java.lang.CharSequence, android.widget.TextView.BufferType);
+    method public void setTextLocale(java.util.Locale);
     method public void setTextScaleX(float);
     method public void setTextSize(float);
     method public void setTextSize(int, float);
@@ -28900,7 +29759,7 @@
     method public void setTextOn(java.lang.CharSequence);
   }
 
-  public class TwoLineListItem extends android.widget.RelativeLayout {
+  public deprecated class TwoLineListItem extends android.widget.RelativeLayout {
     ctor public TwoLineListItem(android.content.Context);
     ctor public TwoLineListItem(android.content.Context, android.util.AttributeSet);
     ctor public TwoLineListItem(android.content.Context, android.util.AttributeSet, int);
@@ -28926,6 +29785,7 @@
     method public void setMediaController(android.widget.MediaController);
     method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
     method public void setOnErrorListener(android.media.MediaPlayer.OnErrorListener);
+    method public void setOnInfoListener(android.media.MediaPlayer.OnInfoListener);
     method public void setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener);
     method public void setVideoPath(java.lang.String);
     method public void setVideoURI(android.net.Uri);
@@ -28937,6 +29797,7 @@
   public class ViewAnimator extends android.widget.FrameLayout {
     ctor public ViewAnimator(android.content.Context);
     ctor public ViewAnimator(android.content.Context, android.util.AttributeSet);
+    method public boolean getAnimateFirstView();
     method public android.view.View getCurrentView();
     method public int getDisplayedChild();
     method public android.view.animation.Animation getInAnimation();
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 54b5836..add7a23 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -31,13 +31,14 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.ResolveInfo;
 import android.net.Uri;
-import android.os.Binder;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.util.AndroidException;
+import android.view.Display;
 import android.view.IWindowManager;
 
 import java.io.BufferedReader;
@@ -62,7 +63,7 @@
     private boolean mStopOption = false;
 
     private int mRepeat = 0;
-    private int mUserId = 0;
+    private int mUserId;
 
     private String mProfileFile;
 
@@ -126,24 +127,42 @@
             runSetDebugApp();
         } else if (op.equals("clear-debug-app")) {
             runClearDebugApp();
+        } else if (op.equals("bug-report")) {
+            runBugReport();
         } else if (op.equals("monitor")) {
             runMonitor();
         } else if (op.equals("screen-compat")) {
             runScreenCompat();
         } else if (op.equals("display-size")) {
             runDisplaySize();
+        } else if (op.equals("display-density")) {
+            runDisplayDensity();
         } else if (op.equals("to-uri")) {
             runToUri(false);
         } else if (op.equals("to-intent-uri")) {
             runToUri(true);
         } else if (op.equals("switch-user")) {
             runSwitchUser();
+        } else if (op.equals("stop-user")) {
+            runStopUser();
         } else {
             throw new IllegalArgumentException("Unknown command: " + op);
         }
     }
 
-    private Intent makeIntent() throws URISyntaxException {
+    int parseUserArg(String arg) {
+        int userId;
+        if ("all".equals(arg)) {
+            userId = UserHandle.USER_ALL;
+        } else if ("current".equals(arg) || "cur".equals(arg)) {
+            userId = UserHandle.USER_CURRENT;
+        } else {
+            userId = Integer.parseInt(arg);
+        }
+        return userId;
+    }
+
+    private Intent makeIntent(int defUser) throws URISyntaxException {
         Intent intent = new Intent();
         Intent baseIntent = intent;
         boolean hasIntentInfo = false;
@@ -153,7 +172,7 @@
         mStopOption = false;
         mRepeat = 0;
         mProfileFile = null;
-        mUserId = 0;
+        mUserId = defUser;
         Uri data = null;
         String type = null;
 
@@ -317,10 +336,9 @@
             } else if (opt.equals("--opengl-trace")) {
                 mStartFlags |= ActivityManager.START_FLAG_OPENGL_TRACES;
             } else if (opt.equals("--user")) {
-                mUserId = Integer.parseInt(nextArgRequired());
+                mUserId = parseUserArg(nextArgRequired());
             } else {
                 System.err.println("Error: Unknown option: " + opt);
-                showUsage();
                 return null;
             }
         }
@@ -388,21 +406,34 @@
     }
 
     private void runStartService() throws Exception {
-        Intent intent = makeIntent();
+        Intent intent = makeIntent(UserHandle.USER_CURRENT);
+        if (mUserId == UserHandle.USER_ALL) {
+            System.err.println("Error: Can't start activity with user 'all'");
+            return;
+        }
         System.out.println("Starting service: " + intent);
-        ComponentName cn = mAm.startService(null, intent, intent.getType());
+        ComponentName cn = mAm.startService(null, intent, intent.getType(), mUserId);
         if (cn == null) {
             System.err.println("Error: Not found; no service started.");
+        } else if (cn.getPackageName().equals("!")) {
+            System.err.println("Error: Requires permission " + cn.getClassName());
+        } else if (cn.getPackageName().equals("!!")) {
+            System.err.println("Error: " + cn.getClassName());
         }
     }
 
     private void runStart() throws Exception {
-        Intent intent = makeIntent();
+        Intent intent = makeIntent(UserHandle.USER_CURRENT);
+
+        if (mUserId == UserHandle.USER_ALL) {
+            System.err.println("Error: Can't start service with user 'all'");
+            return;
+        }
 
         String mimeType = intent.getType();
         if (mimeType == null && intent.getData() != null
                 && "content".equals(intent.getData().getScheme())) {
-            mimeType = mAm.getProviderMimeType(intent.getData());
+            mimeType = mAm.getProviderMimeType(intent.getData(), mUserId);
         }
 
         do {
@@ -431,7 +462,7 @@
                     packageName = activities.get(0).activityInfo.packageName;
                 }
                 System.out.println("Stopping: " + packageName);
-                mAm.forceStopPackage(packageName);
+                mAm.forceStopPackage(packageName, mUserId);
                 Thread.sleep(250);
             }
     
@@ -457,11 +488,11 @@
             int res;
             if (mWaitOption) {
                 result = mAm.startActivityAndWait(null, intent, mimeType,
-                            null, null, 0, mStartFlags, mProfileFile, fd, null);
+                            null, null, 0, mStartFlags, mProfileFile, fd, null, mUserId);
                 res = result.result;
             } else {
-                res = mAm.startActivity(null, intent, mimeType,
-                        null, null, 0, mStartFlags, mProfileFile, fd, null);
+                res = mAm.startActivityAsUser(null, intent, mimeType,
+                        null, null, 0, mStartFlags, mProfileFile, fd, null, mUserId);
             }
             PrintStream out = mWaitOption ? System.out : System.err;
             boolean launched = false;
@@ -545,11 +576,33 @@
     }
 
     private void runForceStop() throws Exception {
-        mAm.forceStopPackage(nextArgRequired());
+        int userId = UserHandle.USER_ALL;
+
+        String opt;
+        while ((opt=nextOption()) != null) {
+            if (opt.equals("--user")) {
+                userId = parseUserArg(nextArgRequired());
+            } else {
+                System.err.println("Error: Unknown option: " + opt);
+                return;
+            }
+        }
+        mAm.forceStopPackage(nextArgRequired(), userId);
     }
 
     private void runKill() throws Exception {
-        mAm.killBackgroundProcesses(nextArgRequired());
+        int userId = UserHandle.USER_ALL;
+
+        String opt;
+        while ((opt=nextOption()) != null) {
+            if (opt.equals("--user")) {
+                userId = parseUserArg(nextArgRequired());
+            } else {
+                System.err.println("Error: Unknown option: " + opt);
+                return;
+            }
+        }
+        mAm.killBackgroundProcesses(nextArgRequired(), userId);
     }
 
     private void runKillAll() throws Exception {
@@ -557,7 +610,7 @@
     }
 
     private void sendBroadcast() throws Exception {
-        Intent intent = makeIntent();
+        Intent intent = makeIntent(UserHandle.USER_ALL);
         IntentReceiver receiver = new IntentReceiver();
         System.out.println("Broadcasting: " + intent);
         mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, null, true, false,
@@ -570,6 +623,7 @@
         boolean wait = false;
         boolean rawMode = false;
         boolean no_window_animation = false;
+        int userId = UserHandle.USER_CURRENT;
         Bundle args = new Bundle();
         String argKey = null, argValue = null;
         IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
@@ -589,13 +643,19 @@
             } else if (opt.equals("--no_window_animation")
                     || opt.equals("--no-window-animation")) {
                 no_window_animation = true;
+            } else if (opt.equals("--user")) {
+                userId = parseUserArg(nextArgRequired());
             } else {
                 System.err.println("Error: Unknown option: " + opt);
-                showUsage();
                 return;
             }
         }
 
+        if (userId == UserHandle.USER_ALL) {
+            System.err.println("Error: Can't start instrumentation with user 'all'");
+            return;
+        }
+
         String cnArg = nextArgRequired();
         ComponentName cn = ComponentName.unflattenFromString(cnArg);
         if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
@@ -612,7 +672,7 @@
             wm.setAnimationScale(1, 0.0f);
         }
 
-        if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher)) {
+        if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, userId)) {
             throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
         }
 
@@ -640,17 +700,37 @@
         String profileFile = null;
         boolean start = false;
         boolean wall = false;
+        int userId = UserHandle.USER_CURRENT;
         int profileType = 0;
-        
+
         String process = null;
-        
+
         String cmd = nextArgRequired();
 
         if ("start".equals(cmd)) {
             start = true;
-            wall = "--wall".equals(nextOption());
+            String opt;
+            while ((opt=nextOption()) != null) {
+                if (opt.equals("--user")) {
+                    userId = parseUserArg(nextArgRequired());
+                } else if (opt.equals("--wall")) {
+                    wall = true;
+                } else {
+                    System.err.println("Error: Unknown option: " + opt);
+                    return;
+                }
+            }
             process = nextArgRequired();
         } else if ("stop".equals(cmd)) {
+            String opt;
+            while ((opt=nextOption()) != null) {
+                if (opt.equals("--user")) {
+                    userId = parseUserArg(nextArgRequired());
+                } else {
+                    System.err.println("Error: Unknown option: " + opt);
+                    return;
+                }
+            }
             process = nextArg();
         } else {
             // Compatibility with old syntax: process is specified first.
@@ -662,7 +742,12 @@
                 throw new IllegalArgumentException("Profile command " + process + " not valid");
             }
         }
-        
+
+        if (userId == UserHandle.USER_ALL) {
+            System.err.println("Error: Can't profile with user 'all'");
+            return;
+        }
+
         ParcelFileDescriptor fd = null;
 
         if (start) {
@@ -690,7 +775,7 @@
             } else if (start) {
                 //removeWallOption();
             }
-            if (!mAm.profileControl(process, start, profileFile, fd, profileType)) {
+            if (!mAm.profileControl(process, userId, start, profileFile, fd, profileType)) {
                 wall = false;
                 throw new AndroidException("PROFILE FAILED on process " + process);
             }
@@ -702,14 +787,32 @@
     }
 
     private void runDumpHeap() throws Exception {
-        boolean managed = !"-n".equals(nextOption());
+        boolean managed = true;
+        int userId = UserHandle.USER_CURRENT;
+
+        String opt;
+        while ((opt=nextOption()) != null) {
+            if (opt.equals("--user")) {
+                userId = parseUserArg(nextArgRequired());
+                if (userId == UserHandle.USER_ALL) {
+                    System.err.println("Error: Can't dump heap with user 'all'");
+                    return;
+                }
+            } else if (opt.equals("-n")) {
+                managed = false;
+            } else {
+                System.err.println("Error: Unknown option: " + opt);
+                return;
+            }
+        }
         String process = nextArgRequired();
         String heapFile = nextArgRequired();
         ParcelFileDescriptor fd = null;
 
         try {
-            fd = ParcelFileDescriptor.open(
-                    new File(heapFile),
+            File file = new File(heapFile);
+            file.delete();
+            fd = ParcelFileDescriptor.open(file,
                     ParcelFileDescriptor.MODE_CREATE |
                     ParcelFileDescriptor.MODE_TRUNCATE |
                     ParcelFileDescriptor.MODE_READ_WRITE);
@@ -718,7 +821,7 @@
             return;
         }
 
-        if (!mAm.dumpHeap(process, managed, heapFile, fd)) {
+        if (!mAm.dumpHeap(process, userId, managed, heapFile, fd)) {
             throw new AndroidException("HEAP DUMP FAILED on process " + process);
         }
     }
@@ -735,7 +838,6 @@
                 persistent = true;
             } else {
                 System.err.println("Error: Unknown option: " + opt);
-                showUsage();
                 return;
             }
         }
@@ -748,14 +850,33 @@
         mAm.setDebugApp(null, false, true);
     }
 
+    private void runBugReport() throws Exception {
+        mAm.requestBugReport();
+        System.out.println("Your lovely bug report is being created; please be patient.");
+    }
+
     private void runSwitchUser() throws Exception {
-        if (android.os.Process.myUid() != 0) {
-            throw new RuntimeException("switchuser can only be run as root");
-        }
         String user = nextArgRequired();
         mAm.switchUser(Integer.parseInt(user));
     }
 
+    private void runStopUser() throws Exception {
+        String user = nextArgRequired();
+        int res = mAm.stopUser(Integer.parseInt(user), null);
+        if (res != ActivityManager.USER_OP_SUCCESS) {
+            String txt = "";
+            switch (res) {
+                case ActivityManager.USER_OP_IS_CURRENT:
+                    txt = " (Can't stop current user)";
+                    break;
+                case ActivityManager.USER_OP_UNKNOWN_USER:
+                    txt = " (Unknown user " + user + ")";
+                    break;
+            }
+            System.err.println("Switch failed: " + res + txt);
+        }
+    }
+
     class MyActivityController extends IActivityController.Stub {
         final String mGdbPort;
 
@@ -1044,7 +1165,6 @@
                 gdbPort = nextArgRequired();
             } else {
                 System.err.println("Error: Unknown option: " + opt);
-                showUsage();
                 return;
             }
         }
@@ -1062,7 +1182,6 @@
             enabled = false;
         } else {
             System.err.println("Error: enabled mode must be 'on' or 'off' at " + mode);
-            showUsage();
             return;
         }
 
@@ -1080,34 +1199,26 @@
 
     private void runDisplaySize() throws Exception {
         String size = nextArgRequired();
-        int m, n;
+        int w, h;
         if ("reset".equals(size)) {
-            m = n = -1;
+            w = h = -1;
         } else {
             int div = size.indexOf('x');
             if (div <= 0 || div >= (size.length()-1)) {
                 System.err.println("Error: bad size " + size);
-                showUsage();
                 return;
             }
-            String mstr = size.substring(0, div);
-            String nstr = size.substring(div+1);
+            String wstr = size.substring(0, div);
+            String hstr = size.substring(div+1);
             try {
-                m = Integer.parseInt(mstr);
-                n = Integer.parseInt(nstr);
+                w = Integer.parseInt(wstr);
+                h = Integer.parseInt(hstr);
             } catch (NumberFormatException e) {
                 System.err.println("Error: bad number " + e);
-                showUsage();
                 return;
             }
         }
 
-        if (m < n) {
-            int tmp = m;
-            m = n;
-            n = tmp;
-        }
-
         IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.checkService(
                 Context.WINDOW_SERVICE));
         if (wm == null) {
@@ -1116,32 +1227,71 @@
         }
 
         try {
-            if (m >= 0 && n >= 0) {
-                wm.setForcedDisplaySize(m, n);
+            if (w >= 0 && h >= 0) {
+                // TODO(multidisplay): For now Configuration only applies to main screen.
+                wm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, w, h);
             } else {
-                wm.clearForcedDisplaySize();
+                wm.clearForcedDisplaySize(Display.DEFAULT_DISPLAY);
+            }
+        } catch (RemoteException e) {
+        }
+    }
+
+    private void runDisplayDensity() throws Exception {
+        String densityStr = nextArgRequired();
+        int density;
+        if ("reset".equals(densityStr)) {
+            density = -1;
+        } else {
+            try {
+                density = Integer.parseInt(densityStr);
+            } catch (NumberFormatException e) {
+                System.err.println("Error: bad number " + e);
+                return;
+            }
+            if (density < 72) {
+                System.err.println("Error: density must be >= 72");
+                return;
+            }
+        }
+
+        IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.checkService(
+                Context.WINDOW_SERVICE));
+        if (wm == null) {
+            System.err.println(NO_SYSTEM_ERROR_CODE);
+            throw new AndroidException("Can't connect to window manager; is the system running?");
+        }
+
+        try {
+            if (density > 0) {
+                // TODO(multidisplay): For now Configuration only applies to main screen.
+                wm.setForcedDisplayDensity(Display.DEFAULT_DISPLAY, density);
+            } else {
+                wm.clearForcedDisplayDensity(Display.DEFAULT_DISPLAY);
             }
         } catch (RemoteException e) {
         }
     }
 
     private void runToUri(boolean intentScheme) throws Exception {
-        Intent intent = makeIntent();
+        Intent intent = makeIntent(UserHandle.USER_CURRENT);
         System.out.println(intent.toUri(intentScheme ? Intent.URI_INTENT_SCHEME : 0));
     }
 
     private class IntentReceiver extends IIntentReceiver.Stub {
         private boolean mFinished = false;
 
-        public synchronized void performReceive(
-                Intent intent, int rc, String data, Bundle ext, boolean ord,
-                boolean sticky) {
-            String line = "Broadcast completed: result=" + rc;
+        @Override
+        public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
+                boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
+            String line = "Broadcast completed: result=" + resultCode;
             if (data != null) line = line + ", data=\"" + data + "\"";
-            if (ext != null) line = line + ", extras: " + ext;
+            if (extras != null) line = line + ", extras: " + extras;
             System.out.println(line);
-            mFinished = true;
-            notifyAll();
+            synchronized (this) {
+              mFinished = true;
+              notifyAll();
+            }
         }
 
         public synchronized void waitForFinish() {
@@ -1283,24 +1433,29 @@
         System.err.println(
                 "usage: am [subcommand] [options]\n" +
                 "usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" +
-                "               [--R COUNT] [-S] [--opengl-trace] <INTENT>\n" +
-                "       am startservice <INTENT>\n" +
-                "       am force-stop <PACKAGE>\n" +
-                "       am kill <PACKAGE>\n" +
+                "               [--R COUNT] [-S] [--opengl-trace]\n" +
+                "               [--user <USER_ID> | current] <INTENT>\n" +
+                "       am startservice [--user <USER_ID> | current] <INTENT>\n" +
+                "       am force-stop [--user <USER_ID> | all | current] <PACKAGE>\n" +
+                "       am kill [--user <USER_ID> | all | current] <PACKAGE>\n" +
                 "       am kill-all\n" +
-                "       am broadcast <INTENT>\n" +
+                "       am broadcast [--user <USER_ID> | all | current] <INTENT>\n" +
                 "       am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" +
+                "               [--user <USER_ID> | current]\n" +
                 "               [--no-window-animation] <COMPONENT>\n" +
-                "       am profile start <PROCESS> <FILE>\n" +
-                "       am profile stop [<PROCESS>]\n" +
-                "       am dumpheap [flags] <PROCESS> <FILE>\n" +
+                "       am profile start [--user <USER_ID> current] <PROCESS> <FILE>\n" +
+                "       am profile stop [--user <USER_ID> current] [<PROCESS>]\n" +
+                "       am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>\n" +
                 "       am set-debug-app [-w] [--persistent] <PACKAGE>\n" +
                 "       am clear-debug-app\n" +
                 "       am monitor [--gdb <port>]\n" +
                 "       am screen-compat [on|off] <PACKAGE>\n" +
-                "       am display-size [reset|MxN]\n" +
+                "       am display-size [reset|WxH]\n" +
+                "       am display-density [reset|DENSITY]\n" +
                 "       am to-uri [INTENT]\n" +
                 "       am to-intent-uri [INTENT]\n" +
+                "       am switch-user <USER_ID>\n" +
+                "       am stop-user <USER_ID>\n" +
                 "\n" +
                 "am start: start an Activity.  Options are:\n" +
                 "    -D: enable debugging\n" +
@@ -1311,18 +1466,28 @@
                 "        the top activity will be finished.\n" +
                 "    -S: force stop the target app before starting the activity\n" +
                 "    --opengl-trace: enable tracing of OpenGL functions\n" +
+                "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
+                "        specified then run as the current user.\n" +
                 "\n" +
-                "am startservice: start a Service.\n" +
+                "am startservice: start a Service.  Options are:\n" +
+                "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
+                "        specified then run as the current user.\n" +
                 "\n" +
                 "am force-stop: force stop everything associated with <PACKAGE>.\n" +
+                "    --user <USER_ID> | all | current: Specify user to force stop;\n" +
+                "        all users if not specified.\n" +
                 "\n" +
                 "am kill: Kill all processes associated with <PACKAGE>.  Only kills.\n" +
                 "  processes that are safe to kill -- that is, will not impact the user\n" +
                 "  experience.\n" +
+                "    --user <USER_ID> | all | current: Specify user whose processes to kill;\n" +
+                "        all users if not specified.\n" +
                 "\n" +
                 "am kill-all: Kill all background processes.\n" +
                 "\n" +
-                "am broadcast: send a broadcast Intent.\n" +
+                "am broadcast: send a broadcast Intent.  Options are:\n" +
+                "    --user <USER_ID> | all | current: Specify which user to send to; if not\n" +
+                "        specified then send to all users.\n" +
                 "\n" +
                 "am instrument: start an Instrumentation.  Typically this target <COMPONENT>\n" +
                 "  is the form <TEST_PACKAGE>/<RUNNER_CLASS>.  Options are:\n" +
@@ -1333,12 +1498,20 @@
                 "    -p <FILE>: write profiling data to <FILE>\n" +
                 "    -w: wait for instrumentation to finish before returning.  Required for\n" +
                 "        test runners.\n" +
+                "    --user <USER_ID> | current: Specify user instrumentation runs in;\n" +
+                "        current user if not specified.\n" +
                 "    --no-window-animation: turn off window animations will running.\n" +
                 "\n" +
-                "am profile: start and stop profiler on a process.\n" +
+                "am profile: start and stop profiler on a process.  The given <PROCESS> argument\n" +
+                "  may be either a process name or pid.  Options are:\n" +
+                "    --user <USER_ID> | current: When supplying a process name,\n" +
+                "        specify user of process to profile; uses current user if not specified.\n" +
                 "\n" +
-                "am dumpheap: dump the heap of a process.  Options are:\n" +
+                "am dumpheap: dump the heap of a process.  The given <PROCESS> argument may\n" +
+                "  be either a process name or pid.  Options are:\n" +
                 "    -n: dump native heap instead of managed heap\n" +
+                "    --user <USER_ID> | current: When supplying a process name,\n" +
+                "        specify user of process to dump; uses current user if not specified.\n" +
                 "\n" +
                 "am set-debug-app: set application <PACKAGE> to debug.  Options are:\n" +
                 "    -w: wait for debugger when application starts\n" +
@@ -1346,6 +1519,9 @@
                 "\n" +
                 "am clear-debug-app: clear the previously set-debug-app.\n" +
                 "\n" +
+                "am bug-report: request bug report generation; will launch UI\n" +
+                "    when done to select where it should be delivered." +
+                "\n" +
                 "am monitor: start monitoring for crashes or ANRs.\n" +
                 "    --gdb: start gdbserv on the given port at crash/ANR\n" +
                 "\n" +
@@ -1353,10 +1529,18 @@
                 "\n" +
                 "am display-size: override display size.\n" +
                 "\n" +
+                "am display-density: override display density.\n" +
+                "\n" +
                 "am to-uri: print the given Intent specification as a URI.\n" +
                 "\n" +
                 "am to-intent-uri: print the given Intent specification as an intent: URI.\n" +
                 "\n" +
+                "am switch-user: switch to put USER_ID in the foreground, starting\n" +
+                "  execution of that user if it is currently stopped.\n" +
+                "\n" +
+                "am stop-user: stop execution of USER_ID, not allowing it to run any\n" +
+                "  code until a later explicit switch to it.\n" +
+                "\n" +
                 "<INTENT> specifications include these flags and arguments:\n" +
                 "    [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
                 "    [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 6b5048607..8511735 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -38,6 +38,7 @@
 #include <ui/DisplayInfo.h>
 #include <ui/FramebufferNativeWindow.h>
 
+#include <gui/ISurfaceComposer.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 
@@ -216,14 +217,16 @@
 status_t BootAnimation::readyToRun() {
     mAssets.addDefaultAssets();
 
+    sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
+            ISurfaceComposer::eDisplayIdMain));
     DisplayInfo dinfo;
-    status_t status = session()->getDisplayInfo(0, &dinfo);
+    status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
     if (status)
         return -1;
 
     // create the native surface
-    sp<SurfaceControl> control = session()->createSurface(
-            0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
+    sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
+            dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
 
     SurfaceComposerClient::openGlobalTransaction();
     control->setLayer(0x40000000);
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index bd9eb9a..787fbdb 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -25,6 +25,7 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.IBinder;
+import android.os.UserHandle;
 import android.text.TextUtils;
 
 /**
@@ -63,7 +64,8 @@
     private static final String USAGE =
         "usage: adb shell content [subcommand] [options]\n"
         + "\n"
-        + "usage: adb shell content insert --uri <URI> --bind <BINDING> [--bind <BINDING>...]\n"
+        + "usage: adb shell content insert --uri <URI> [--user <USER_ID>]"
+                + " --bind <BINDING> [--bind <BINDING>...]\n"
         + "  <URI> a content provider URI.\n"
         + "  <BINDING> binds a typed value to a column and is formatted:\n"
         + "  <COLUMN_NAME>:<TYPE>:<COLUMN_VALUE> where:\n"
@@ -75,7 +77,7 @@
         + "  adb shell content insert --uri content://settings/secure --bind name:s:new_setting"
                 + " --bind value:s:new_value\n"
         + "\n"
-        + "usage: adb shell content update --uri <URI> [--where <WHERE>]\n"
+        + "usage: adb shell content update --uri <URI> [--user <USER_ID>] [--where <WHERE>]\n"
         + "  <WHERE> is a SQL style where clause in quotes (You have to escape single quotes"
                 + " - see example below).\n"
         + "  Example:\n"
@@ -83,15 +85,15 @@
         + "  adb shell content update --uri content://settings/secure --bind"
                 + " value:s:newer_value --where \"name=\'new_setting\'\"\n"
         + "\n"
-        + "usage: adb shell content delete --uri <URI> --bind <BINDING>"
+        + "usage: adb shell content delete --uri <URI> [--user <USER_ID>] --bind <BINDING>"
                 + " [--bind <BINDING>...] [--where <WHERE>]\n"
         + "  Example:\n"
         + "  # Remove \"new_setting\" secure setting.\n"
         + "  adb shell content delete --uri content://settings/secure "
                 + "--where \"name=\'new_setting\'\"\n"
         + "\n"
-        + "usage: adb shell content query --uri <URI> [--projection <PROJECTION>]"
-                + " [--where <WHERE>] [--sort <SORT_ORDER>]\n"
+        + "usage: adb shell content query --uri <URI> [--user <USER_ID>]"
+                + " [--projection <PROJECTION>] [--where <WHERE>] [--sort <SORT_ORDER>]\n"
         + "  <PROJECTION> is a list of colon separated column names and is formatted:\n"
         + "  <COLUMN_NAME>[:<COLUMN_NAME>...]\n"
         + "  <SORT_OREDER> is the order in which rows in the result should be sorted.\n"
@@ -110,6 +112,7 @@
         private static final String ARGUMENT_WHERE = "--where";
         private static final String ARGUMENT_BIND = "--bind";
         private static final String ARGUMENT_URI = "--uri";
+        private static final String ARGUMENT_USER = "--user";
         private static final String ARGUMENT_PROJECTION = "--projection";
         private static final String ARGUMENT_SORT = "--sort";
         private static final String TYPE_BOOLEAN = "b";
@@ -150,10 +153,13 @@
 
         private InsertCommand parseInsertCommand() {
             Uri uri = null;
+            int userId = UserHandle.USER_OWNER;
             ContentValues values = new ContentValues();
             for (String argument; (argument = mTokenizer.nextArg()) != null;) {
                 if (ARGUMENT_URI.equals(argument)) {
                     uri = Uri.parse(argumentValueRequired(argument));
+                } else if (ARGUMENT_USER.equals(argument)) {
+                    userId = Integer.parseInt(argumentValueRequired(argument));
                 } else if (ARGUMENT_BIND.equals(argument)) {
                     parseBindValue(values);
                 } else {
@@ -168,15 +174,18 @@
                 throw new IllegalArgumentException("Bindings not specified."
                         + " Did you specify --bind argument(s)?");
             }
-            return new InsertCommand(uri, values);
+            return new InsertCommand(uri, userId, values);
         }
 
         private DeleteCommand parseDeleteCommand() {
             Uri uri = null;
+            int userId = UserHandle.USER_OWNER;
             String where = null;
             for (String argument; (argument = mTokenizer.nextArg())!= null;) {
                 if (ARGUMENT_URI.equals(argument)) {
                     uri = Uri.parse(argumentValueRequired(argument));
+                } else if (ARGUMENT_USER.equals(argument)) {
+                    userId = Integer.parseInt(argumentValueRequired(argument));
                 } else if (ARGUMENT_WHERE.equals(argument)) {
                     where = argumentValueRequired(argument);
                 } else {
@@ -187,16 +196,19 @@
                 throw new IllegalArgumentException("Content provider URI not specified."
                         + " Did you specify --uri argument?");
             }
-            return new DeleteCommand(uri, where);
+            return new DeleteCommand(uri, userId, where);
         }
 
         private UpdateCommand parseUpdateCommand() {
             Uri uri = null;
+            int userId = UserHandle.USER_OWNER;
             String where = null;
             ContentValues values = new ContentValues();
             for (String argument; (argument = mTokenizer.nextArg())!= null;) {
                 if (ARGUMENT_URI.equals(argument)) {
                     uri = Uri.parse(argumentValueRequired(argument));
+                } else if (ARGUMENT_USER.equals(argument)) {
+                    userId = Integer.parseInt(argumentValueRequired(argument));
                 } else if (ARGUMENT_WHERE.equals(argument)) {
                     where = argumentValueRequired(argument);
                 } else if (ARGUMENT_BIND.equals(argument)) {
@@ -213,17 +225,20 @@
                 throw new IllegalArgumentException("Bindings not specified."
                         + " Did you specify --bind argument(s)?");
             }
-            return new UpdateCommand(uri, values, where);
+            return new UpdateCommand(uri, userId, values, where);
         }
 
         public QueryCommand parseQueryCommand() {
             Uri uri = null;
+            int userId = UserHandle.USER_OWNER;
             String[] projection = null;
             String sort = null;
             String where = null;
             for (String argument; (argument = mTokenizer.nextArg())!= null;) {
                 if (ARGUMENT_URI.equals(argument)) {
                     uri = Uri.parse(argumentValueRequired(argument));
+                } else if (ARGUMENT_USER.equals(argument)) {
+                    userId = Integer.parseInt(argumentValueRequired(argument));
                 } else if (ARGUMENT_WHERE.equals(argument)) {
                     where = argumentValueRequired(argument);
                 } else if (ARGUMENT_SORT.equals(argument)) {
@@ -238,7 +253,7 @@
                 throw new IllegalArgumentException("Content provider URI not specified."
                         + " Did you specify --uri argument?");
             }
-            return new QueryCommand(uri, projection, where, sort);
+            return new QueryCommand(uri, userId, projection, where, sort);
         }
 
         private void parseBindValue(ContentValues values) {
@@ -298,9 +313,11 @@
 
     private static abstract class Command {
         final Uri mUri;
+        final int mUserId;
 
-        public Command(Uri uri) {
+        public Command(Uri uri, int userId) {
             mUri = uri;
+            mUserId = userId;
         }
 
         public final void execute() {
@@ -311,7 +328,7 @@
                 IBinder token = new Binder();
                 try {
                     ContentProviderHolder holder = activityManager.getContentProviderExternal(
-                            providerName, token);
+                            providerName, mUserId, token);
                     if (holder == null) {
                         throw new IllegalStateException("Could not find provider: " + providerName);
                     }
@@ -334,8 +351,8 @@
     private static class InsertCommand extends Command {
         final ContentValues mContentValues;
 
-        public InsertCommand(Uri uri, ContentValues contentValues) {
-            super(uri);
+        public InsertCommand(Uri uri, int userId, ContentValues contentValues) {
+            super(uri, userId);
             mContentValues = contentValues;
         }
 
@@ -348,8 +365,8 @@
     private static class DeleteCommand extends Command {
         final String mWhere;
 
-        public DeleteCommand(Uri uri, String where) {
-            super(uri);
+        public DeleteCommand(Uri uri, int userId, String where) {
+            super(uri, userId);
             mWhere = where;
         }
 
@@ -363,8 +380,9 @@
         final String[] mProjection;
         final String mSortOrder;
 
-        public QueryCommand(Uri uri, String[] projection, String where, String sortOrder) {
-            super(uri, where);
+        public QueryCommand(
+                Uri uri, int userId, String[] projection, String where, String sortOrder) {
+            super(uri, userId, where);
             mProjection = projection;
             mSortOrder = sortOrder;
         }
@@ -426,8 +444,8 @@
     private static class UpdateCommand extends InsertCommand {
         final String mWhere;
 
-        public UpdateCommand(Uri uri, ContentValues contentValues, String where) {
-            super(uri, contentValues);
+        public UpdateCommand(Uri uri, int userId, ContentValues contentValues, String where) {
+            super(uri, userId, contentValues);
             mWhere = where;
         }
 
diff --git a/cmds/input/src/com/android/commands/input/Input.java b/cmds/input/src/com/android/commands/input/Input.java
index 341f30f..a21df0d 100755
--- a/cmds/input/src/com/android/commands/input/Input.java
+++ b/cmds/input/src/com/android/commands/input/Input.java
@@ -66,15 +66,54 @@
                 }
             } else if (command.equals("tap")) {
                 if (args.length == 3) {
-                    sendTap(Float.parseFloat(args[1]), Float.parseFloat(args[2]));
+                    sendTap(InputDevice.SOURCE_TOUCHSCREEN, Float.parseFloat(args[1]), Float.parseFloat(args[2]));
                     return;
                 }
             } else if (command.equals("swipe")) {
                 if (args.length == 5) {
-                    sendSwipe(Float.parseFloat(args[1]), Float.parseFloat(args[2]),
+                    sendSwipe(InputDevice.SOURCE_TOUCHSCREEN, Float.parseFloat(args[1]), Float.parseFloat(args[2]),
                             Float.parseFloat(args[3]), Float.parseFloat(args[4]));
                     return;
                 }
+            } else if (command.equals("touchscreen") || command.equals("touchpad")) {
+                // determine input source
+                int inputSource = InputDevice.SOURCE_TOUCHSCREEN;
+                if (command.equals("touchpad")) {
+                    inputSource = InputDevice.SOURCE_TOUCHPAD;
+                }
+                // determine subcommand
+                if (args.length > 1) {
+                    String subcommand = args[1];
+                    if (subcommand.equals("tap")) {
+                        if (args.length == 4) {
+                            sendTap(inputSource, Float.parseFloat(args[2]),
+                                    Float.parseFloat(args[3]));
+                            return;
+                        }
+                    } else if (subcommand.equals("swipe")) {
+                        if (args.length == 6) {
+                            sendSwipe(inputSource, Float.parseFloat(args[2]),
+                                    Float.parseFloat(args[3]), Float.parseFloat(args[4]),
+                                    Float.parseFloat(args[5]));
+                            return;
+                        }
+                    }
+                }
+            } else if (command.equals("trackball")) {
+                // determine subcommand
+                if (args.length > 1) {
+                    String subcommand = args[1];
+                    if (subcommand.equals("press")) {
+                        sendTap(InputDevice.SOURCE_TRACKBALL, 0.0f, 0.0f);
+                        return;
+                    } else if (subcommand.equals("roll")) {
+                        if (args.length == 4) {
+                            sendMove(InputDevice.SOURCE_TRACKBALL, Float.parseFloat(args[2]),
+                                    Float.parseFloat(args[3]));
+                            return;
+                        }
+                    }
+                }
             } else {
                 System.err.println("Error: Unknown command: " + command);
                 showUsage();
@@ -127,33 +166,64 @@
                 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD));
     }
 
-    private void sendTap(float x, float y) {
+    private void sendTap(int inputSource, float x, float y) {
         long now = SystemClock.uptimeMillis();
-        injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, x, y, 0));
-        injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, x, y, 0));
+        injectMotionEvent(inputSource, MotionEvent.ACTION_DOWN, now, x, y, 1.0f);
+        injectMotionEvent(inputSource, MotionEvent.ACTION_UP, now, x, y, 0.0f);
     }
 
-    private void sendSwipe(float x1, float y1, float x2, float y2) {
+    private void sendSwipe(int inputSource, float x1, float y1, float x2, float y2) {
         final int NUM_STEPS = 11;
         long now = SystemClock.uptimeMillis();
-        injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, x1, y1, 0));
+        injectMotionEvent(inputSource, MotionEvent.ACTION_DOWN, now, x1, y1, 1.0f);
         for (int i = 1; i < NUM_STEPS; i++) {
-            float alpha = (float)i / NUM_STEPS;
-            injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE,
-                    lerp(x1, x2, alpha), lerp(y1, y2, alpha), 0));
+            float alpha = (float) i / NUM_STEPS;
+            injectMotionEvent(inputSource, MotionEvent.ACTION_MOVE, now, lerp(x1, x2, alpha),
+                    lerp(y1, y2, alpha), 1.0f);
         }
-        injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, x2, y2, 0));
+        injectMotionEvent(inputSource, MotionEvent.ACTION_UP, now, x1, y1, 0.0f);
+    }
+
+    /**
+     * Sends a simple zero-pressure move event.
+     *
+     * @param inputSource the InputDevice.SOURCE_* sending the input event
+     * @param dx change in x coordinate due to move
+     * @param dy change in y coordinate due to move
+     */
+    private void sendMove(int inputSource, float dx, float dy) {
+        long now = SystemClock.uptimeMillis();
+        injectMotionEvent(inputSource, MotionEvent.ACTION_MOVE, now, dx, dy, 0.0f);
     }
 
     private void injectKeyEvent(KeyEvent event) {
-        Log.i(TAG, "InjectKeyEvent: " + event);
+        Log.i(TAG, "injectKeyEvent: " + event);
         InputManager.getInstance().injectInputEvent(event,
                 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
     }
 
-    private void injectPointerEvent(MotionEvent event) {
-        event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
-        Log.i("Input", "InjectPointerEvent: " + event);
+    /**
+     * Builds a MotionEvent and injects it into the event stream.
+     *
+     * @param inputSource the InputDevice.SOURCE_* sending the input event
+     * @param action the MotionEvent.ACTION_* for the event
+     * @param when the value of SystemClock.uptimeMillis() at which the event happened
+     * @param x x coordinate of event
+     * @param y y coordinate of event
+     * @param pressure pressure of event
+     */
+    private void injectMotionEvent(int inputSource, int action, long when, float x, float y, float pressure) {
+        final float DEFAULT_SIZE = 1.0f;
+        final int DEFAULT_META_STATE = 0;
+        final float DEFAULT_PRECISION_X = 1.0f;
+        final float DEFAULT_PRECISION_Y = 1.0f;
+        final int DEFAULT_DEVICE_ID = 0;
+        final int DEFAULT_EDGE_FLAGS = 0;
+        MotionEvent event = MotionEvent.obtain(when, when, action, x, y, pressure, DEFAULT_SIZE,
+                DEFAULT_META_STATE, DEFAULT_PRECISION_X, DEFAULT_PRECISION_Y, DEFAULT_DEVICE_ID,
+                DEFAULT_EDGE_FLAGS);
+        event.setSource(inputSource);
+        Log.i("Input", "injectMotionEvent: " + event);
         InputManager.getInstance().injectInputEvent(event,
                 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
     }
@@ -166,7 +236,9 @@
         System.err.println("usage: input ...");
         System.err.println("       input text <string>");
         System.err.println("       input keyevent <key code number or name>");
-        System.err.println("       input tap <x> <y>");
-        System.err.println("       input swipe <x1> <y1> <x2> <y2>");
+        System.err.println("       input [touchscreen|touchpad] tap <x> <y>");
+        System.err.println("       input [touchscreen|touchpad] swipe <x1> <y1> <x2> <y2>");
+        System.err.println("       input trackball press");
+        System.err.println("       input trackball roll <dx> <dy>");
     }
 }
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 41e7b8d..387f33d 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -14,6 +14,7 @@
 ** limitations under the License.
 */
 
+#include <linux/capability.h>
 #include "installd.h"
 #include <diskusage/dirsize.h>
 
@@ -26,12 +27,16 @@
 dir_rec_t android_asec_dir;
 dir_rec_t android_app_dir;
 dir_rec_t android_app_private_dir;
+dir_rec_t android_app_lib_dir;
+dir_rec_t android_media_dir;
 dir_rec_array_t android_system_dirs;
 
 int install(const char *pkgname, uid_t uid, gid_t gid)
 {
     char pkgdir[PKG_PATH_MAX];
-    char libdir[PKG_PATH_MAX];
+    char libsymlink[PKG_PATH_MAX];
+    char applibdir[PKG_PATH_MAX];
+    struct stat libStat;
 
     if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
         ALOGE("invalid uid/gid: %d %d\n", uid, gid);
@@ -43,64 +48,68 @@
         return -1;
     }
 
-    if (create_pkg_path(libdir, pkgname, PKG_LIB_POSTFIX, 0)) {
-        ALOGE("cannot create package lib path\n");
+    if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, 0)) {
+        ALOGE("cannot create package lib symlink origin path\n");
+        return -1;
+    }
+
+    if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
+        ALOGE("cannot create package lib symlink dest path\n");
         return -1;
     }
 
     if (mkdir(pkgdir, 0751) < 0) {
         ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
-        return -errno;
+        return -1;
     }
     if (chmod(pkgdir, 0751) < 0) {
         ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
         unlink(pkgdir);
-        return -errno;
+        return -1;
     }
 
-    if (mkdir(libdir, 0755) < 0) {
-        ALOGE("cannot create dir '%s': %s\n", libdir, strerror(errno));
-        unlink(pkgdir);
-        return -errno;
-    }
-    if (chmod(libdir, 0755) < 0) {
-        ALOGE("cannot chmod dir '%s': %s\n", libdir, strerror(errno));
-        unlink(libdir);
-        unlink(pkgdir);
-        return -errno;
-    }
-    if (chown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
-        ALOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
-        unlink(libdir);
-        unlink(pkgdir);
-        return -errno;
+    if (lstat(libsymlink, &libStat) < 0) {
+        if (errno != ENOENT) {
+            ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
+            return -1;
+        }
+    } else {
+        if (S_ISDIR(libStat.st_mode)) {
+            if (delete_dir_contents(libsymlink, 1, 0) < 0) {
+                ALOGE("couldn't delete lib directory during install for: %s", libsymlink);
+                return -1;
+            }
+        } else if (S_ISLNK(libStat.st_mode)) {
+            if (unlink(libsymlink) < 0) {
+                ALOGE("couldn't unlink lib directory during install for: %s", libsymlink);
+                return -1;
+            }
+        }
     }
 
-#ifdef HAVE_SELINUX
-    if (selinux_android_setfilecon(libdir, pkgname, AID_SYSTEM) < 0) {
-        ALOGE("cannot setfilecon dir '%s': %s\n", libdir, strerror(errno));
-        unlink(libdir);
+    if (symlink(applibdir, libsymlink) < 0) {
+        ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, applibdir,
+                strerror(errno));
         unlink(pkgdir);
-        return -errno;
-    }
-#endif
-
-    if (chown(pkgdir, uid, gid) < 0) {
-        ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(libdir);
-        unlink(pkgdir);
-        return -errno;
+        return -1;
     }
 
 #ifdef HAVE_SELINUX
     if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) {
         ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(libdir);
+        unlink(libsymlink);
         unlink(pkgdir);
-        return -errno;
+        return -1;
     }
 #endif
 
+    if (chown(pkgdir, uid, gid) < 0) {
+        ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
+        unlink(libsymlink);
+        unlink(pkgdir);
+        return -1;
+    }
+
     return 0;
 }
 
@@ -151,7 +160,7 @@
     if (stat(pkgdir, &s) < 0) return -1;
 
     if (s.st_uid != 0 || s.st_gid != 0) {
-        ALOGE("fixing uid of non-root pkg: %s %d %d\n", pkgdir, s.st_uid, s.st_gid);
+        ALOGE("fixing uid of non-root pkg: %s %lu %lu\n", pkgdir, s.st_uid, s.st_gid);
         return -1;
     }
 
@@ -183,18 +192,67 @@
 int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
 {
     char pkgdir[PKG_PATH_MAX];
-    char real_libdir[PKG_PATH_MAX];
+    char applibdir[PKG_PATH_MAX];
+    char libsymlink[PKG_PATH_MAX];
+    struct stat libStat;
 
     // Create the data dir for the package
     if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) {
         return -1;
     }
+    if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, persona)) {
+        ALOGE("cannot create package lib symlink origin path\n");
+        return -1;
+    }
+    if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
+        ALOGE("cannot create package lib symlink dest path\n");
+        return -1;
+    }
+
     if (mkdir(pkgdir, 0751) < 0) {
         ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
         return -errno;
     }
+    if (chmod(pkgdir, 0751) < 0) {
+        ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
+        unlink(pkgdir);
+        return -errno;
+    }
+
+    if (lstat(libsymlink, &libStat) < 0) {
+        if (errno != ENOENT) {
+            ALOGE("couldn't stat lib dir for non-primary: %s\n", strerror(errno));
+            unlink(pkgdir);
+            return -1;
+        }
+    } else {
+        if (S_ISDIR(libStat.st_mode)) {
+            if (delete_dir_contents(libsymlink, 1, 0) < 0) {
+                ALOGE("couldn't delete lib directory during install for non-primary: %s",
+                        libsymlink);
+                unlink(pkgdir);
+                return -1;
+            }
+        } else if (S_ISLNK(libStat.st_mode)) {
+            if (unlink(libsymlink) < 0) {
+                ALOGE("couldn't unlink lib directory during install for non-primary: %s",
+                        libsymlink);
+                unlink(pkgdir);
+                return -1;
+            }
+        }
+    }
+
+    if (symlink(applibdir, libsymlink) < 0) {
+        ALOGE("couldn't symlink directory for non-primary '%s' -> '%s': %s\n", libsymlink,
+                applibdir, strerror(errno));
+        unlink(pkgdir);
+        return -1;
+    }
+
     if (chown(pkgdir, uid, uid) < 0) {
         ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
+        unlink(libsymlink);
         unlink(pkgdir);
         return -errno;
     }
@@ -202,6 +260,7 @@
 #ifdef HAVE_SELINUX
     if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) {
         ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
+        unlink(libsymlink);
         unlink(pkgdir);
         return -errno;
     }
@@ -212,12 +271,23 @@
 
 int delete_persona(uid_t persona)
 {
-    char pkgdir[PKG_PATH_MAX];
-
-    if (create_persona_path(pkgdir, persona))
+    char data_path[PKG_PATH_MAX];
+    if (create_persona_path(data_path, persona)) {
         return -1;
+    }
+    if (delete_dir_contents(data_path, 1, NULL)) {
+        return -1;
+    }
 
-    return delete_dir_contents(pkgdir, 1, NULL);
+    char media_path[PATH_MAX];
+    if (create_persona_media_path(media_path, (userid_t) persona) == -1) {
+        return -1;
+    }
+    if (delete_dir_contents(media_path, 1, NULL) == -1) {
+        return -1;
+    }
+
+    return 0;
 }
 
 int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
@@ -250,7 +320,7 @@
                 /* Get the file stat */
                 if (stat(pkg_path, &s) < 0) continue;
                 /* Get the uid of the package */
-                ALOGI("Adding datadir for uid = %d\n", s.st_uid);
+                ALOGI("Adding datadir for uid = %lu\n", s.st_uid);
                 uid = (uid_t) s.st_uid % PER_USER_RANGE;
                 /* Create the directory for the target */
                 make_user_data(name, uid + target_persona * PER_USER_RANGE,
@@ -259,31 +329,25 @@
         }
         closedir(d);
     }
+
+    if (ensure_media_user_dirs((userid_t) target_persona) == -1) {
+        return -1;
+    }
+
     return 0;
 }
 
-int delete_cache(const char *pkgname)
+int delete_cache(const char *pkgname, uid_t persona)
 {
     char cachedir[PKG_PATH_MAX];
 
-    if (create_pkg_path(cachedir, pkgname, CACHE_DIR_POSTFIX, 0))
+    if (create_pkg_path(cachedir, pkgname, CACHE_DIR_POSTFIX, persona))
         return -1;
 
         /* delete contents, not the directory, no exceptions */
     return delete_dir_contents(cachedir, 0, 0);
 }
 
-static int64_t disk_free()
-{
-    struct statfs sfs;
-    if (statfs(android_data_dir.path, &sfs) == 0) {
-        return sfs.f_bavail * sfs.f_bsize;
-    } else {
-        ALOGE("Couldn't statfs %s: %s\n", android_data_dir.path, strerror(errno));
-        return -1;
-    }
-}
-
 /* Try to ensure free_size bytes of storage are available.
  * Returns 0 on success.
  * This is rather simple-minded because doing a full LRU would
@@ -293,57 +357,85 @@
  */
 int free_cache(int64_t free_size)
 {
-    const char *name;
-    int dfd, subfd;
+    cache_t* cache;
+    int64_t avail;
     DIR *d;
     struct dirent *de;
-    int64_t avail;
-    char datadir[PKG_PATH_MAX];
+    char tmpdir[PATH_MAX];
+    char *dirpos;
 
-    avail = disk_free();
+    avail = data_disk_free();
     if (avail < 0) return -1;
 
     ALOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail);
     if (avail >= free_size) return 0;
 
-    if (create_persona_path(datadir, 0)) {
-        ALOGE("couldn't get directory for persona 0");
-        return -1;
+    cache = start_cache_collection();
+
+    // Collect cache files for primary user.
+    if (create_persona_path(tmpdir, 0) == 0) {
+        //ALOGI("adding cache files from %s\n", tmpdir);
+        add_cache_files(cache, tmpdir, "cache");
     }
 
-    d = opendir(datadir);
-    if (d == NULL) {
-        ALOGE("cannot open %s: %s\n", datadir, strerror(errno));
-        return -1;
-    }
-    dfd = dirfd(d);
-
-    while ((de = readdir(d))) {
-        if (de->d_type != DT_DIR) continue;
-        name = de->d_name;
-
-        /* always skip "." and ".." */
-        if (name[0] == '.') {
-            if (name[1] == 0) continue;
-            if ((name[1] == '.') && (name[2] == 0)) continue;
+    // Search for other users and add any cache files from them.
+    snprintf(tmpdir, sizeof(tmpdir), "%s%s", android_data_dir.path,
+            SECONDARY_USER_PREFIX);
+    dirpos = tmpdir + strlen(tmpdir);
+    d = opendir(tmpdir);
+    if (d != NULL) {
+        while ((de = readdir(d))) {
+            if (de->d_type == DT_DIR) {
+                const char *name = de->d_name;
+                    /* always skip "." and ".." */
+                if (name[0] == '.') {
+                    if (name[1] == 0) continue;
+                    if ((name[1] == '.') && (name[2] == 0)) continue;
+                }
+                if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) {
+                    strcpy(dirpos, name);
+                    //ALOGI("adding cache files from %s\n", tmpdir);
+                    add_cache_files(cache, tmpdir, "cache");
+                } else {
+                    ALOGW("Path exceeds limit: %s%s", tmpdir, name);
+                }
+            }
         }
-
-        subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
-        if (subfd < 0) continue;
-
-        delete_dir_contents_fd(subfd, "cache");
-        close(subfd);
-
-        avail = disk_free();
-        if (avail >= free_size) {
-            closedir(d);
-            return 0;
-        }
+        closedir(d);
     }
-    closedir(d);
 
-    /* Fail case - not possible to free space */
-    return -1;
+    // Collect cache files on external storage for all users (if it is mounted as part
+    // of the internal storage).
+    strcpy(tmpdir, android_media_dir.path);
+    dirpos = tmpdir + strlen(tmpdir);
+    d = opendir(tmpdir);
+    if (d != NULL) {
+        while ((de = readdir(d))) {
+            if (de->d_type == DT_DIR) {
+                const char *name = de->d_name;
+                    /* skip any dir that doesn't start with a number, so not a user */
+                if (name[0] < '0' || name[0] > '9') {
+                    continue;
+                }
+                if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) {
+                    strcpy(dirpos, name);
+                    if (lookup_media_dir(tmpdir, "Android") == 0
+                            && lookup_media_dir(tmpdir, "data") == 0) {
+                        //ALOGI("adding cache files from %s\n", tmpdir);
+                        add_cache_files(cache, tmpdir, "cache");
+                    }
+                } else {
+                    ALOGW("Path exceeds limit: %s%s", tmpdir, name);
+                }
+            }
+        }
+        closedir(d);
+    }
+
+    clear_cache_files(cache, free_size);
+    finish_cache_collection(cache);
+
+    return data_disk_free() >= free_size ? 0 : -1;
 }
 
 int move_dex(const char *src, const char *dst)
@@ -382,38 +474,7 @@
     }
 }
 
-int protect(char *pkgname, gid_t gid)
-{
-    struct stat s;
-    char pkgpath[PKG_PATH_MAX];
-
-    if (gid < AID_SYSTEM) return -1;
-
-    if (create_pkg_path_in_dir(pkgpath, &android_app_private_dir, pkgname, ".apk"))
-        return -1;
-
-    if (stat(pkgpath, &s) < 0) return -1;
-
-    if (chown(pkgpath, s.st_uid, gid) < 0) {
-        ALOGE("failed to chgrp '%s': %s\n", pkgpath, strerror(errno));
-        return -1;
-    }
-    if (chmod(pkgpath, S_IRUSR|S_IWUSR|S_IRGRP) < 0) {
-        ALOGE("failed to chmod '%s': %s\n", pkgpath, strerror(errno));
-        return -1;
-    }
-
-#ifdef HAVE_SELINUX
-    if (selinux_android_setfilecon(pkgpath, pkgname, s.st_uid) < 0) {
-        ALOGE("cannot setfilecon dir '%s': %s\n", pkgpath, strerror(errno));
-        return -1;
-    }
-#endif
-
-    return 0;
-}
-
-int get_size(const char *pkgname, const char *apkpath,
+int get_size(const char *pkgname, int persona, const char *apkpath,
              const char *fwdlock_apkpath, const char *asecpath,
              int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize,
              int64_t* _asecsize)
@@ -452,6 +513,16 @@
         }
     }
 
+        /* add in size of any libraries */
+    if (!create_pkg_path_in_dir(path, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
+        d = opendir(path);
+        if (d != NULL) {
+            dfd = dirfd(d);
+            codesize += calculate_dir_size(dfd);
+            closedir(d);
+        }
+    }
+
         /* compute asec size if it is given
          */
     if (asecpath != NULL && asecpath[0] != '!') {
@@ -460,7 +531,7 @@
         }
     }
 
-    if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, 0)) {
+    if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, persona)) {
         goto done;
     }
 
@@ -479,21 +550,33 @@
 
         if (de->d_type == DT_DIR) {
             int subfd;
+            int64_t statsize = 0;
+            int64_t dirsize = 0;
                 /* always skip "." and ".." */
             if (name[0] == '.') {
                 if (name[1] == 0) continue;
                 if ((name[1] == '.') && (name[2] == 0)) continue;
             }
+            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+                statsize = stat_size(&s);
+            }
             subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
             if (subfd >= 0) {
-                int64_t size = calculate_dir_size(subfd);
-                if (!strcmp(name,"lib")) {
-                    codesize += size;
-                } else if(!strcmp(name,"cache")) {
-                    cachesize += size;
-                } else {
-                    datasize += size;
-                }
+                dirsize = calculate_dir_size(subfd);
+            }
+            if(!strcmp(name,"lib")) {
+                codesize += dirsize + statsize;
+            } else if(!strcmp(name,"cache")) {
+                cachesize += dirsize + statsize;
+            } else {
+                datasize += dirsize + statsize;
+            }
+        } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) {
+            // This is the symbolic link to the application's library
+            // code.  We'll count this as code instead of data, since
+            // it is not something that the app creates.
+            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+                codesize += stat_size(&s);
             }
         } else {
             if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
@@ -645,16 +728,16 @@
         ALOGE("dexopt cannot open '%s' for output\n", dex_path);
         goto fail;
     }
-    if (fchown(odex_fd, AID_SYSTEM, uid) < 0) {
-        ALOGE("dexopt cannot chown '%s'\n", dex_path);
-        goto fail;
-    }
     if (fchmod(odex_fd,
                S_IRUSR|S_IWUSR|S_IRGRP |
                (is_public ? S_IROTH : 0)) < 0) {
         ALOGE("dexopt cannot chmod '%s'\n", dex_path);
         goto fail;
     }
+    if (fchown(odex_fd, AID_SYSTEM, uid) < 0) {
+        ALOGE("dexopt cannot chown '%s'\n", dex_path);
+        goto fail;
+    }
 
     ALOGV("DexInv: --- BEGIN '%s' ---\n", apk_path);
 
@@ -670,13 +753,23 @@
             ALOGE("setuid(%d) during dexopt\n", uid);
             exit(65);
         }
+        // drop capabilities
+        struct __user_cap_header_struct capheader;
+        struct __user_cap_data_struct capdata[2];
+        memset(&capheader, 0, sizeof(capheader));
+        memset(&capdata, 0, sizeof(capdata));
+        capheader.version = _LINUX_CAPABILITY_VERSION_3;
+        if (capset(&capheader, &capdata[0]) < 0) {
+            ALOGE("capset failed: %s\n", strerror(errno));
+            exit(66);
+        }
         if (flock(odex_fd, LOCK_EX | LOCK_NB) != 0) {
             ALOGE("flock(%s) failed: %s\n", dex_path, strerror(errno));
-            exit(66);
+            exit(67);
         }
 
         run_dexopt(zip_fd, odex_fd, apk_path, dexopt_flags);
-        exit(67);   /* only get here on exec failure */
+        exit(68);   /* only get here on exec failure */
     } else {
         res = wait_dexopt(pid, apk_path);
         if (res != 0) {
@@ -964,159 +1057,73 @@
     return 0;
 }
 
-int linklib(const char* dataDir, const char* asecLibDir)
+int linklib(const char* pkgname, const char* asecLibDir, int userId)
 {
-    char libdir[PKG_PATH_MAX];
+    char pkgdir[PKG_PATH_MAX];
+    char libsymlink[PKG_PATH_MAX];
     struct stat s, libStat;
     int rc = 0;
 
-    const size_t libdirLen = strlen(dataDir) + strlen(PKG_LIB_POSTFIX);
-    if (libdirLen >= PKG_PATH_MAX) {
-        ALOGE("library dir len too large");
+    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userId)) {
+        ALOGE("cannot create package path\n");
+        return -1;
+    }
+    if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userId)) {
+        ALOGE("cannot create package lib symlink origin path\n");
         return -1;
     }
 
-    if (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) {
-        ALOGE("library dir not written successfully: %s\n", strerror(errno));
+    if (stat(pkgdir, &s) < 0) return -1;
+
+    if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) {
+        ALOGE("failed to chown '%s': %s\n", pkgdir, strerror(errno));
         return -1;
     }
 
-    if (stat(dataDir, &s) < 0) return -1;
-
-    if (chown(dataDir, 0, 0) < 0) {
-        ALOGE("failed to chown '%s': %s\n", dataDir, strerror(errno));
-        return -1;
-    }
-
-    if (chmod(dataDir, 0700) < 0) {
-        ALOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno));
+    if (chmod(pkgdir, 0700) < 0) {
+        ALOGE("linklib() 1: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
         rc = -1;
         goto out;
     }
 
-    if (lstat(libdir, &libStat) < 0) {
-        ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
-        rc = -1;
-        goto out;
-    }
-
-    if (S_ISDIR(libStat.st_mode)) {
-        if (delete_dir_contents(libdir, 1, 0) < 0) {
+    if (lstat(libsymlink, &libStat) < 0) {
+        if (errno != ENOENT) {
+            ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
             rc = -1;
             goto out;
         }
-    } else if (S_ISLNK(libStat.st_mode)) {
-        if (unlink(libdir) < 0) {
-            rc = -1;
-            goto out;
+    } else {
+        if (S_ISDIR(libStat.st_mode)) {
+            if (delete_dir_contents(libsymlink, 1, 0) < 0) {
+                rc = -1;
+                goto out;
+            }
+        } else if (S_ISLNK(libStat.st_mode)) {
+            if (unlink(libsymlink) < 0) {
+                ALOGE("couldn't unlink lib dir: %s\n", strerror(errno));
+                rc = -1;
+                goto out;
+            }
         }
     }
 
-    if (symlink(asecLibDir, libdir) < 0) {
-        ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libdir, asecLibDir, strerror(errno));
-        rc = -errno;
-        goto out;
-    }
-
-    if (lchown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
-        ALOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
-        unlink(libdir);
+    if (symlink(asecLibDir, libsymlink) < 0) {
+        ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, asecLibDir,
+                strerror(errno));
         rc = -errno;
         goto out;
     }
 
 out:
-    if (chmod(dataDir, s.st_mode) < 0) {
-        ALOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno));
+    if (chmod(pkgdir, s.st_mode) < 0) {
+        ALOGE("linklib() 2: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
         rc = -errno;
     }
 
-    if (chown(dataDir, s.st_uid, s.st_gid) < 0) {
-        ALOGE("failed to chown '%s' : %s\n", dataDir, strerror(errno));
+    if (chown(pkgdir, s.st_uid, s.st_gid) < 0) {
+        ALOGE("failed to chown '%s' : %s\n", pkgdir, strerror(errno));
         return -errno;
     }
 
     return rc;
 }
-
-int unlinklib(const char* dataDir)
-{
-    char libdir[PKG_PATH_MAX];
-    struct stat s, libStat;
-    int rc = 0;
-
-    const size_t libdirLen = strlen(dataDir) + strlen(PKG_LIB_POSTFIX);
-    if (libdirLen >= PKG_PATH_MAX) {
-        return -1;
-    }
-
-    if (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) {
-        ALOGE("library dir not written successfully: %s\n", strerror(errno));
-        return -1;
-    }
-
-    if (stat(dataDir, &s) < 0) {
-        ALOGE("couldn't state data dir");
-        return -1;
-    }
-
-    if (chown(dataDir, 0, 0) < 0) {
-        ALOGE("failed to chown '%s': %s\n", dataDir, strerror(errno));
-        return -1;
-    }
-
-    if (chmod(dataDir, 0700) < 0) {
-        ALOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno));
-        rc = -1;
-        goto out;
-    }
-
-    if (lstat(libdir, &libStat) < 0) {
-        ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
-        rc = -1;
-        goto out;
-    }
-
-    if (S_ISDIR(libStat.st_mode)) {
-        if (delete_dir_contents(libdir, 1, 0) < 0) {
-            rc = -1;
-            goto out;
-        }
-    } else if (S_ISLNK(libStat.st_mode)) {
-        if (unlink(libdir) < 0) {
-            rc = -1;
-            goto out;
-        }
-    }
-
-    if (mkdir(libdir, 0755) < 0) {
-        ALOGE("cannot create dir '%s': %s\n", libdir, strerror(errno));
-        rc = -errno;
-        goto out;
-    }
-    if (chmod(libdir, 0755) < 0) {
-        ALOGE("cannot chmod dir '%s': %s\n", libdir, strerror(errno));
-        unlink(libdir);
-        rc = -errno;
-        goto out;
-    }
-    if (chown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
-        ALOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
-        unlink(libdir);
-        rc = -errno;
-        goto out;
-    }
-
-out:
-    if (chmod(dataDir, s.st_mode) < 0) {
-        ALOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno));
-        rc = -1;
-    }
-
-    if (chown(dataDir, s.st_uid, s.st_gid) < 0) {
-        ALOGE("failed to chown '%s' : %s\n", dataDir, strerror(errno));
-        return -1;
-    }
-
-    return rc;
-}
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index fa4b8a6..21d674a 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -14,6 +14,9 @@
 ** limitations under the License.
 */
 
+#include <linux/capability.h>
+#include <linux/prctl.h>
+
 #include "installd.h"
 
 
@@ -69,12 +72,7 @@
 
 static int do_rm_cache(char **arg, char reply[REPLY_MAX])
 {
-    return delete_cache(arg[0]); /* pkgname */
-}
-
-static int do_protect(char **arg, char reply[REPLY_MAX])
-{
-    return protect(arg[0], atoi(arg[1])); /* pkgname, gid */
+    return delete_cache(arg[0], atoi(arg[1])); /* pkgname, userid */
 }
 
 static int do_get_size(char **arg, char reply[REPLY_MAX])
@@ -85,8 +83,9 @@
     int64_t asecsize = 0;
     int res = 0;
 
-        /* pkgdir, apkpath */
-    res = get_size(arg[0], arg[1], arg[2], arg[3], &codesize, &datasize, &cachesize, &asecsize);
+        /* pkgdir, persona, apkpath */
+    res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4],
+            &codesize, &datasize, &cachesize, &asecsize);
 
     /*
      * Each int64_t can take up 22 characters printed out. Make sure it
@@ -124,12 +123,7 @@
 
 static int do_linklib(char **arg, char reply[REPLY_MAX])
 {
-    return linklib(arg[0], arg[1]);
-}
-
-static int do_unlinklib(char **arg, char reply[REPLY_MAX])
-{
-    return unlinklib(arg[0]);
+    return linklib(arg[0], arg[1], atoi(arg[2]));
 }
 
 struct cmdinfo {
@@ -148,13 +142,11 @@
     { "rename",               2, do_rename },
     { "fixuid",               3, do_fixuid },
     { "freecache",            1, do_free_cache },
-    { "rmcache",              1, do_rm_cache },
-    { "protect",              2, do_protect },
-    { "getsize",              4, do_get_size },
+    { "rmcache",              2, do_rm_cache },
+    { "getsize",              5, do_get_size },
     { "rmuserdata",           2, do_rm_user_data },
     { "movefiles",            0, do_movefiles },
-    { "linklib",              2, do_linklib },
-    { "unlinklib",            1, do_unlinklib },
+    { "linklib",              3, do_linklib },
     { "mkuserdata",           3, do_mk_user_data },
     { "rmuser",               1, do_rm_user },
     { "cloneuserdata",        3, do_clone_user_data },
@@ -292,11 +284,21 @@
         return -1;
     }
 
+    // Get the android app native library directory.
+    if (copy_and_append(&android_app_lib_dir, &android_data_dir, APP_LIB_SUBDIR) < 0) {
+        return -1;
+    }
+
     // Get the sd-card ASEC mount point.
     if (get_path_from_env(&android_asec_dir, "ASEC_MOUNTPOINT") < 0) {
         return -1;
     }
 
+    // Get the android media directory.
+    if (copy_and_append(&android_media_dir, &android_data_dir, MEDIA_SUBDIR) < 0) {
+        return -1;
+    }
+
     // Take note of the system and vendor directories.
     android_system_dirs.count = 2;
 
@@ -326,37 +328,202 @@
 }
 
 int initialize_directories() {
+    int res = -1;
+
+    // Read current filesystem layout version to handle upgrade paths
+    char version_path[PATH_MAX];
+    snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path);
+
+    int oldVersion;
+    if (fs_read_atomic_int(version_path, &oldVersion) == -1) {
+        oldVersion = 0;
+    }
+    int version = oldVersion;
+
     // /data/user
     char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX);
     // /data/data
     char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX);
     // /data/user/0
-    char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX,
-            "0");
-    int ret = -1;
-    if (user_data_dir != NULL && primary_data_dir != NULL && legacy_data_dir != NULL) {
-        ret = 0;
-        // Make the /data/user directory if necessary
-        if (access(user_data_dir, R_OK) < 0) {
-            if (mkdir(user_data_dir, 0711) < 0) {
-                return -1;
-            }
-            if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) {
-                return -1;
-            }
-            if (chmod(user_data_dir, 0711) < 0) {
-                return -1;
-            }
-        }
-        // Make the /data/user/0 symlink to /data/data if necessary
-        if (access(primary_data_dir, R_OK) < 0) {
-              ret = symlink(legacy_data_dir, primary_data_dir);
-        }
-        free(user_data_dir);
-        free(legacy_data_dir);
-        free(primary_data_dir);
+    char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, "0");
+    if (!user_data_dir || !legacy_data_dir || !primary_data_dir) {
+        goto fail;
     }
-    return ret;
+
+    // Make the /data/user directory if necessary
+    if (access(user_data_dir, R_OK) < 0) {
+        if (mkdir(user_data_dir, 0711) < 0) {
+            goto fail;
+        }
+        if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) {
+            goto fail;
+        }
+        if (chmod(user_data_dir, 0711) < 0) {
+            goto fail;
+        }
+    }
+    // Make the /data/user/0 symlink to /data/data if necessary
+    if (access(primary_data_dir, R_OK) < 0) {
+        if (symlink(legacy_data_dir, primary_data_dir)) {
+            goto fail;
+        }
+    }
+
+    if (version == 0) {
+        // Introducing multi-user, so migrate /data/media contents into /data/media/0
+        ALOGD("Upgrading /data/media for multi-user");
+
+        // Ensure /data/media
+        if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+            goto fail;
+        }
+
+        // /data/media.tmp
+        char media_tmp_dir[PATH_MAX];
+        snprintf(media_tmp_dir, PATH_MAX, "%smedia.tmp", android_data_dir.path);
+
+        // Only copy when upgrade not already in progress
+        if (access(media_tmp_dir, F_OK) == -1) {
+            if (rename(android_media_dir.path, media_tmp_dir) == -1) {
+                ALOGE("Failed to move legacy media path: %s", strerror(errno));
+                goto fail;
+            }
+        }
+
+        // Create /data/media again
+        if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+            goto fail;
+        }
+
+        // /data/media/0
+        char owner_media_dir[PATH_MAX];
+        snprintf(owner_media_dir, PATH_MAX, "%s0", android_media_dir.path);
+
+        // Move any owner data into place
+        if (access(media_tmp_dir, F_OK) == 0) {
+            if (rename(media_tmp_dir, owner_media_dir) == -1) {
+                ALOGE("Failed to move owner media path: %s", strerror(errno));
+                goto fail;
+            }
+        }
+
+        // Ensure media directories for any existing users
+        DIR *dir;
+        struct dirent *dirent;
+        char user_media_dir[PATH_MAX];
+
+        dir = opendir(user_data_dir);
+        if (dir != NULL) {
+            while ((dirent = readdir(dir))) {
+                if (dirent->d_type == DT_DIR) {
+                    const char *name = dirent->d_name;
+
+                    // skip "." and ".."
+                    if (name[0] == '.') {
+                        if (name[1] == 0) continue;
+                        if ((name[1] == '.') && (name[2] == 0)) continue;
+                    }
+
+                    // /data/media/<user_id>
+                    snprintf(user_media_dir, PATH_MAX, "%s%s", android_media_dir.path, name);
+                    if (fs_prepare_dir(user_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+                        goto fail;
+                    }
+                }
+            }
+            closedir(dir);
+        }
+
+        version = 1;
+    }
+
+    // /data/media/obb
+    char media_obb_dir[PATH_MAX];
+    snprintf(media_obb_dir, PATH_MAX, "%sobb", android_media_dir.path);
+
+    if (version == 1) {
+        // Introducing /data/media/obb for sharing OBB across users; migrate
+        // any existing OBB files from owner.
+        ALOGD("Upgrading to shared /data/media/obb");
+
+        // /data/media/0/Android/obb
+        char owner_obb_path[PATH_MAX];
+        snprintf(owner_obb_path, PATH_MAX, "%s0/Android/obb", android_media_dir.path);
+
+        // Only move if target doesn't already exist
+        if (access(media_obb_dir, F_OK) != 0 && access(owner_obb_path, F_OK) == 0) {
+            if (rename(owner_obb_path, media_obb_dir) == -1) {
+                ALOGE("Failed to move OBB from owner: %s", strerror(errno));
+                goto fail;
+            }
+        }
+
+        version = 2;
+    }
+
+    if (ensure_media_user_dirs(0) == -1) {
+        ALOGE("Failed to setup media for user 0");
+        goto fail;
+    }
+    if (fs_prepare_dir(media_obb_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+        goto fail;
+    }
+
+    // Persist layout version if changed
+    if (version != oldVersion) {
+        if (fs_write_atomic_int(version_path, version) == -1) {
+            ALOGE("Failed to save version to %s: %s", version_path, strerror(errno));
+            goto fail;
+        }
+    }
+
+    // Success!
+    res = 0;
+
+fail:
+    free(user_data_dir);
+    free(legacy_data_dir);
+    free(primary_data_dir);
+    return res;
+}
+
+static void drop_privileges() {
+    if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
+        ALOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno));
+        exit(1);
+    }
+
+    if (setgid(AID_INSTALL) < 0) {
+        ALOGE("setgid() can't drop privileges; exiting.\n");
+        exit(1);
+    }
+
+    if (setuid(AID_INSTALL) < 0) {
+        ALOGE("setuid() can't drop privileges; exiting.\n");
+        exit(1);
+    }
+
+    struct __user_cap_header_struct capheader;
+    struct __user_cap_data_struct capdata[2];
+    memset(&capheader, 0, sizeof(capheader));
+    memset(&capdata, 0, sizeof(capdata));
+    capheader.version = _LINUX_CAPABILITY_VERSION_3;
+    capheader.pid = 0;
+
+    capdata[CAP_TO_INDEX(CAP_DAC_OVERRIDE)].permitted |= CAP_TO_MASK(CAP_DAC_OVERRIDE);
+    capdata[CAP_TO_INDEX(CAP_CHOWN)].permitted        |= CAP_TO_MASK(CAP_CHOWN);
+    capdata[CAP_TO_INDEX(CAP_SETUID)].permitted       |= CAP_TO_MASK(CAP_SETUID);
+    capdata[CAP_TO_INDEX(CAP_SETGID)].permitted       |= CAP_TO_MASK(CAP_SETGID);
+
+    capdata[0].effective = capdata[0].permitted;
+    capdata[1].effective = capdata[1].permitted;
+    capdata[0].inheritable = 0;
+    capdata[1].inheritable = 0;
+
+    if (capset(&capheader, &capdata[0]) < 0) {
+        ALOGE("capset failed: %s\n", strerror(errno));
+        exit(1);
+    }
 }
 
 int main(const int argc, const char *argv[]) {
@@ -365,6 +532,8 @@
     socklen_t alen;
     int lsocket, s, count;
 
+    ALOGI("installd firing up\n");
+
     if (initialize_globals() < 0) {
         ALOGE("Could not initialize globals; exiting.\n");
         exit(1);
@@ -375,6 +544,8 @@
         exit(1);
     }
 
+    drop_privileges();
+
     lsocket = android_get_control_socket(SOCKET_PATH);
     if (lsocket < 0) {
         ALOGE("Failed to get socket from environment: %s\n", strerror(errno));
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 1b843fd..0500c23 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -32,9 +32,11 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 
+#include <cutils/fs.h>
 #include <cutils/sockets.h>
 #include <cutils/log.h>
 #include <cutils/properties.h>
+#include <cutils/multiuser.h>
 
 #include <private/android_filesystem_config.h>
 
@@ -60,6 +62,10 @@
 
 #define APP_SUBDIR             "app/" // sub-directory under ANDROID_DATA
 
+#define APP_LIB_SUBDIR         "app-lib/" // sub-directory under ANDROID_DATA
+
+#define MEDIA_SUBDIR           "media/" // sub-directory under ANDROID_DATA
+
 /* other handy constants */
 
 #define PRIVATE_APP_SUBDIR     "app-private/" // sub-directory under ANDROID_DATA
@@ -89,10 +95,39 @@
 
 extern dir_rec_t android_app_dir;
 extern dir_rec_t android_app_private_dir;
+extern dir_rec_t android_app_lib_dir;
 extern dir_rec_t android_data_dir;
 extern dir_rec_t android_asec_dir;
+extern dir_rec_t android_media_dir;
 extern dir_rec_array_t android_system_dirs;
 
+typedef struct cache_dir_struct {
+    struct cache_dir_struct* parent;
+    int32_t childCount;
+    int32_t hiddenCount;
+    int32_t deleted;
+    char name[];
+} cache_dir_t;
+
+typedef struct {
+    cache_dir_t* dir;
+    time_t modTime;
+    char name[];
+} cache_file_t;
+
+typedef struct {
+    size_t numDirs;
+    size_t availDirs;
+    cache_dir_t** dirs;
+    size_t numFiles;
+    size_t availFiles;
+    cache_file_t** files;
+    size_t numCollected;
+    void* memBlocks;
+    int8_t* curMemBlockAvail;
+    int8_t* curMemBlockEnd;
+} cache_t;
+
 /* util.c */
 
 int create_pkg_path_in_dir(char path[PKG_PATH_MAX],
@@ -108,6 +143,8 @@
 int create_persona_path(char path[PKG_PATH_MAX],
                     uid_t persona);
 
+int create_persona_media_path(char path[PKG_PATH_MAX], userid_t userid);
+
 int create_move_path(char path[PKG_PATH_MAX],
                      const char* pkgname,
                      const char* leaf,
@@ -123,6 +160,18 @@
 
 int delete_dir_contents_fd(int dfd, const char *name);
 
+int lookup_media_dir(char basepath[PATH_MAX], const char *dir);
+
+int64_t data_disk_free();
+
+cache_t* start_cache_collection();
+
+void add_cache_files(cache_t* cache, const char *basepath, const char *cachedir);
+
+void clear_cache_files(cache_t* cache, int64_t free_size);
+
+void finish_cache_collection(cache_t* cache);
+
 int validate_system_app_path(const char* path);
 
 int get_path_from_env(dir_rec_t* rec, const char* var);
@@ -138,6 +187,9 @@
 char *build_string2(char *s1, char *s2);
 char *build_string3(char *s1, char *s2, char *s3);
 
+int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
+int ensure_media_user_dirs(userid_t userid);
+
 /* commands.c */
 
 int install(const char *pkgname, uid_t uid, gid_t gid);
@@ -148,15 +200,14 @@
 int make_user_data(const char *pkgname, uid_t uid, uid_t persona);
 int delete_persona(uid_t persona);
 int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy);
-int delete_cache(const char *pkgname);
+int delete_cache(const char *pkgname, uid_t persona);
 int move_dex(const char *src, const char *dst);
 int rm_dex(const char *path);
 int protect(char *pkgname, gid_t gid);
-int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpath,
+int get_size(const char *pkgname, int persona, const char *apkpath, const char *fwdlock_apkpath,
              const char *asecpath, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
              int64_t *asecsize);
 int free_cache(int64_t free_size);
 int dexopt(const char *apk_path, uid_t uid, int is_public);
 int movefiles();
-int linklib(const char* target, const char* source);
-int unlinklib(const char* libPath);
+int linklib(const char* target, const char* source, int userId);
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c
index 52ec9e8..625a35e 100644
--- a/cmds/installd/utils.c
+++ b/cmds/installd/utils.c
@@ -16,6 +16,8 @@
 
 #include "installd.h"
 
+#define CACHE_NOISY(x) //x
+
 int create_pkg_path_in_dir(char path[PKG_PATH_MAX],
                                 const dir_rec_t* dir,
                                 const char* pkgname,
@@ -135,6 +137,17 @@
     return 0;
 }
 
+/**
+ * Create the path name for media for a certain persona.
+ * Returns 0 on success, and -1 on failure.
+ */
+int create_persona_media_path(char path[PATH_MAX], userid_t userid) {
+    if (snprintf(path, PATH_MAX, "%s%d", android_media_dir.path, userid) > PATH_MAX) {
+        return -1;
+    }
+    return 0;
+}
+
 int create_move_path(char path[PKG_PATH_MAX],
     const char* pkgname,
     const char* leaf,
@@ -296,6 +309,489 @@
     return res;
 }
 
+int lookup_media_dir(char basepath[PATH_MAX], const char *dir)
+{
+    DIR *d;
+    struct dirent *de;
+    struct stat s;
+    char* dirpos = basepath + strlen(basepath);
+
+    if ((*(dirpos-1)) != '/') {
+        *dirpos = '/';
+        dirpos++;
+    }
+
+    CACHE_NOISY(ALOGI("Looking up %s in %s\n", dir, basepath));
+    // Verify the path won't extend beyond our buffer, to avoid
+    // repeated checking later.
+    if ((dirpos-basepath+strlen(dir)) >= (PATH_MAX-1)) {
+        ALOGW("Path exceeds limit: %s%s", basepath, dir);
+        return -1;
+    }
+
+    // First, can we find this directory with the case that is given?
+    strcpy(dirpos, dir);
+    if (stat(basepath, &s) >= 0) {
+        CACHE_NOISY(ALOGI("Found direct: %s\n", basepath));
+        return 0;
+    }
+
+    // Not found with that case...  search through all entries to find
+    // one that matches regardless of case.
+    *dirpos = 0;
+
+    d = opendir(basepath);
+    if (d == NULL) {
+        return -1;
+    }
+
+    while ((de = readdir(d))) {
+        if (strcasecmp(de->d_name, dir) == 0) {
+            strcpy(dirpos, de->d_name);
+            closedir(d);
+            CACHE_NOISY(ALOGI("Found search: %s\n", basepath));
+            return 0;
+        }
+    }
+
+    ALOGW("Couldn't find %s in %s", dir, basepath);
+    closedir(d);
+    return -1;
+}
+
+int64_t data_disk_free()
+{
+    struct statfs sfs;
+    if (statfs(android_data_dir.path, &sfs) == 0) {
+        return sfs.f_bavail * sfs.f_bsize;
+    } else {
+        ALOGE("Couldn't statfs %s: %s\n", android_data_dir.path, strerror(errno));
+        return -1;
+    }
+}
+
+cache_t* start_cache_collection()
+{
+    cache_t* cache = (cache_t*)calloc(1, sizeof(cache_t));
+    return cache;
+}
+
+#define CACHE_BLOCK_SIZE (512*1024)
+
+static void* _cache_malloc(cache_t* cache, size_t len)
+{
+    len = (len+3)&~3;
+    if (len > (CACHE_BLOCK_SIZE/2)) {
+        // It doesn't make sense to try to put this allocation into one
+        // of our blocks, because it is so big.  Instead, make a new dedicated
+        // block for it.
+        int8_t* res = (int8_t*)malloc(len+sizeof(void*));
+        if (res == NULL) {
+            return NULL;
+        }
+        CACHE_NOISY(ALOGI("Allocated large cache mem block: %p size %d", res, len));
+        // Link it into our list of blocks, not disrupting the current one.
+        if (cache->memBlocks == NULL) {
+            *(void**)res = NULL;
+            cache->memBlocks = res;
+        } else {
+            *(void**)res = *(void**)cache->memBlocks;
+            *(void**)cache->memBlocks = res;
+        }
+        return res + sizeof(void*);
+    }
+    int8_t* res = cache->curMemBlockAvail;
+    int8_t* nextPos = res + len;
+    if (cache->memBlocks == NULL || nextPos > cache->curMemBlockEnd) {
+        int8_t* newBlock = malloc(CACHE_BLOCK_SIZE);
+        if (newBlock == NULL) {
+            return NULL;
+        }
+        CACHE_NOISY(ALOGI("Allocated new cache mem block: %p", newBlock));
+        *(void**)newBlock = cache->memBlocks;
+        cache->memBlocks = newBlock;
+        res = cache->curMemBlockAvail = newBlock + sizeof(void*);
+        cache->curMemBlockEnd = newBlock + CACHE_BLOCK_SIZE;
+        nextPos = res + len;
+    }
+    CACHE_NOISY(ALOGI("cache_malloc: ret %p size %d, block=%p, nextPos=%p",
+            res, len, cache->memBlocks, nextPos));
+    cache->curMemBlockAvail = nextPos;
+    return res;
+}
+
+static void* _cache_realloc(cache_t* cache, void* cur, size_t origLen, size_t len)
+{
+    // This isn't really a realloc, but it is good enough for our purposes here.
+    void* alloc = _cache_malloc(cache, len);
+    if (alloc != NULL && cur != NULL) {
+        memcpy(alloc, cur, origLen < len ? origLen : len);
+    }
+    return alloc;
+}
+
+static void _inc_num_cache_collected(cache_t* cache)
+{
+    cache->numCollected++;
+    if ((cache->numCollected%20000) == 0) {
+        ALOGI("Collected cache so far: %d directories, %d files",
+            cache->numDirs, cache->numFiles);
+    }
+}
+
+static cache_dir_t* _add_cache_dir_t(cache_t* cache, cache_dir_t* parent, const char *name)
+{
+    size_t nameLen = strlen(name);
+    cache_dir_t* dir = (cache_dir_t*)_cache_malloc(cache, sizeof(cache_dir_t)+nameLen+1);
+    if (dir != NULL) {
+        dir->parent = parent;
+        dir->childCount = 0;
+        dir->hiddenCount = 0;
+        dir->deleted = 0;
+        strcpy(dir->name, name);
+        if (cache->numDirs >= cache->availDirs) {
+            size_t newAvail = cache->availDirs < 1000 ? 1000 : cache->availDirs*2;
+            cache_dir_t** newDirs = (cache_dir_t**)_cache_realloc(cache, cache->dirs,
+                    cache->availDirs*sizeof(cache_dir_t*), newAvail*sizeof(cache_dir_t*));
+            if (newDirs == NULL) {
+                ALOGE("Failure growing cache dirs array for %s\n", name);
+                return NULL;
+            }
+            cache->availDirs = newAvail;
+            cache->dirs = newDirs;
+        }
+        cache->dirs[cache->numDirs] = dir;
+        cache->numDirs++;
+        if (parent != NULL) {
+            parent->childCount++;
+        }
+        _inc_num_cache_collected(cache);
+    } else {
+        ALOGE("Failure allocating cache_dir_t for %s\n", name);
+    }
+    return dir;
+}
+
+static cache_file_t* _add_cache_file_t(cache_t* cache, cache_dir_t* dir, time_t modTime,
+        const char *name)
+{
+    size_t nameLen = strlen(name);
+    cache_file_t* file = (cache_file_t*)_cache_malloc(cache, sizeof(cache_file_t)+nameLen+1);
+    if (file != NULL) {
+        file->dir = dir;
+        file->modTime = modTime;
+        strcpy(file->name, name);
+        if (cache->numFiles >= cache->availFiles) {
+            size_t newAvail = cache->availFiles < 1000 ? 1000 : cache->availFiles*2;
+            cache_file_t** newFiles = (cache_file_t**)_cache_realloc(cache, cache->files,
+                    cache->availFiles*sizeof(cache_file_t*), newAvail*sizeof(cache_file_t*));
+            if (newFiles == NULL) {
+                ALOGE("Failure growing cache file array for %s\n", name);
+                return NULL;
+            }
+            cache->availFiles = newAvail;
+            cache->files = newFiles;
+        }
+        CACHE_NOISY(ALOGI("Setting file %p at position %d in array %p", file,
+                cache->numFiles, cache->files));
+        cache->files[cache->numFiles] = file;
+        cache->numFiles++;
+        dir->childCount++;
+        _inc_num_cache_collected(cache);
+    } else {
+        ALOGE("Failure allocating cache_file_t for %s\n", name);
+    }
+    return file;
+}
+
+static int _add_cache_files(cache_t *cache, cache_dir_t *parentDir, const char *dirName,
+        DIR* dir, char *pathBase, char *pathPos, size_t pathAvailLen)
+{
+    struct dirent *de;
+    cache_dir_t* cacheDir = NULL;
+    int dfd;
+
+    CACHE_NOISY(ALOGI("_add_cache_files: parent=%p dirName=%s dir=%p pathBase=%s",
+            parentDir, dirName, dir, pathBase));
+
+    dfd = dirfd(dir);
+
+    if (dfd < 0) return 0;
+
+    // Sub-directories always get added to the data structure, so if they
+    // are empty we will know about them to delete them later.
+    cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
+
+    while ((de = readdir(dir))) {
+        const char *name = de->d_name;
+
+        if (de->d_type == DT_DIR) {
+            int subfd;
+            DIR *subdir;
+
+                /* always skip "." and ".." */
+            if (name[0] == '.') {
+                if (name[1] == 0) continue;
+                if ((name[1] == '.') && (name[2] == 0)) continue;
+            }
+
+            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+            if (subfd < 0) {
+                ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
+                continue;
+            }
+            subdir = fdopendir(subfd);
+            if (subdir == NULL) {
+                ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
+                close(subfd);
+                continue;
+            }
+            if (cacheDir == NULL) {
+                cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
+            }
+            if (cacheDir != NULL) {
+                // Update pathBase for the new path...  this may change dirName
+                // if that is also pointing to the path, but we are done with it
+                // now.
+                size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name);
+                CACHE_NOISY(ALOGI("Collecting dir %s\n", pathBase));
+                if (finallen < pathAvailLen) {
+                    _add_cache_files(cache, cacheDir, name, subdir, pathBase,
+                            pathPos+finallen, pathAvailLen-finallen);
+                } else {
+                    // Whoops, the final path is too long!  We'll just delete
+                    // this directory.
+                    ALOGW("Cache dir %s truncated in path %s; deleting dir\n",
+                            name, pathBase);
+                    _delete_dir_contents(subdir, NULL);
+                    if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
+                        ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
+                    }
+                }
+            }
+            closedir(subdir);
+        } else if (de->d_type == DT_REG) {
+            // Skip files that start with '.'; they will be deleted if
+            // their entire directory is deleted.  This allows for metadata
+            // like ".nomedia" to remain in the directory until the entire
+            // directory is deleted.
+            if (cacheDir == NULL) {
+                cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
+            }
+            if (name[0] == '.') {
+                cacheDir->hiddenCount++;
+                continue;
+            }
+            if (cacheDir != NULL) {
+                // Build final full path for file...  this may change dirName
+                // if that is also pointing to the path, but we are done with it
+                // now.
+                size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name);
+                CACHE_NOISY(ALOGI("Collecting file %s\n", pathBase));
+                if (finallen < pathAvailLen) {
+                    struct stat s;
+                    if (stat(pathBase, &s) >= 0) {
+                        _add_cache_file_t(cache, cacheDir, s.st_mtime, name);
+                    } else {
+                        ALOGW("Unable to stat cache file %s; deleting\n", pathBase);
+                        if (unlink(pathBase) < 0) {
+                            ALOGE("Couldn't unlink %s: %s\n", pathBase, strerror(errno));
+                        }
+                    }
+                } else {
+                    // Whoops, the final path is too long!  We'll just delete
+                    // this file.
+                    ALOGW("Cache file %s truncated in path %s; deleting\n",
+                            name, pathBase);
+                    if (unlinkat(dfd, name, 0) < 0) {
+                        *pathPos = 0;
+                        ALOGE("Couldn't unlinkat %s in %s: %s\n", name, pathBase,
+                                strerror(errno));
+                    }
+                }
+            }
+        } else {
+            cacheDir->hiddenCount++;
+        }
+    }
+    return 0;
+}
+
+void add_cache_files(cache_t* cache, const char *basepath, const char *cachedir)
+{
+    DIR *d;
+    struct dirent *de;
+    char dirname[PATH_MAX];
+
+    CACHE_NOISY(ALOGI("add_cache_files: base=%s cachedir=%s\n", basepath, cachedir));
+
+    d = opendir(basepath);
+    if (d == NULL) {
+        return;
+    }
+
+    while ((de = readdir(d))) {
+        if (de->d_type == DT_DIR) {
+            DIR* subdir;
+            const char *name = de->d_name;
+            char* pathpos;
+
+                /* always skip "." and ".." */
+            if (name[0] == '.') {
+                if (name[1] == 0) continue;
+                if ((name[1] == '.') && (name[2] == 0)) continue;
+            }
+
+            strcpy(dirname, basepath);
+            pathpos = dirname + strlen(dirname);
+            if ((*(pathpos-1)) != '/') {
+                *pathpos = '/';
+                pathpos++;
+                *pathpos = 0;
+            }
+            if (cachedir != NULL) {
+                snprintf(pathpos, sizeof(dirname)-(pathpos-dirname), "%s/%s", name, cachedir);
+            } else {
+                snprintf(pathpos, sizeof(dirname)-(pathpos-dirname), "%s", name);
+            }
+            CACHE_NOISY(ALOGI("Adding cache files from dir: %s\n", dirname));
+            subdir = opendir(dirname);
+            if (subdir != NULL) {
+                size_t dirnameLen = strlen(dirname);
+                _add_cache_files(cache, NULL, dirname, subdir, dirname, dirname+dirnameLen,
+                        PATH_MAX - dirnameLen);
+                closedir(subdir);
+            }
+        }
+    }
+
+    closedir(d);
+}
+
+static char *create_dir_path(char path[PATH_MAX], cache_dir_t* dir)
+{
+    char *pos = path;
+    if (dir->parent != NULL) {
+        pos = create_dir_path(path, dir->parent);
+    }
+    // Note that we don't need to worry about going beyond the buffer,
+    // since when we were constructing the cache entries our maximum
+    // buffer size for full paths was PATH_MAX.
+    strcpy(pos, dir->name);
+    pos += strlen(pos);
+    *pos = '/';
+    pos++;
+    *pos = 0;
+    return pos;
+}
+
+static void delete_cache_dir(char path[PATH_MAX], cache_dir_t* dir)
+{
+    if (dir->parent != NULL) {
+        create_dir_path(path, dir);
+        ALOGI("DEL DIR %s\n", path);
+        if (dir->hiddenCount <= 0) {
+            if (rmdir(path)) {
+                ALOGE("Couldn't rmdir %s: %s\n", path, strerror(errno));
+                return;
+            }
+        } else {
+            // The directory contains hidden files so we need to delete
+            // them along with the directory itself.
+            if (delete_dir_contents(path, 1, NULL)) {
+                return;
+            }
+        }
+        dir->parent->childCount--;
+        dir->deleted = 1;
+        if (dir->parent->childCount <= 0) {
+            delete_cache_dir(path, dir->parent);
+        }
+    } else if (dir->hiddenCount > 0) {
+        // This is a root directory, but it has hidden files.  Get rid of
+        // all of those files, but not the directory itself.
+        create_dir_path(path, dir);
+        ALOGI("DEL CONTENTS %s\n", path);
+        delete_dir_contents(path, 0, NULL);
+    }
+}
+
+static int cache_modtime_sort(const void *lhsP, const void *rhsP)
+{
+    const cache_file_t *lhs = *(const cache_file_t**)lhsP;
+    const cache_file_t *rhs = *(const cache_file_t**)rhsP;
+    return lhs->modTime < rhs->modTime ? -1 : (lhs->modTime > rhs->modTime ? 1 : 0);
+}
+
+void clear_cache_files(cache_t* cache, int64_t free_size)
+{
+    size_t i;
+    int skip = 0;
+    char path[PATH_MAX];
+
+    ALOGI("Collected cache files: %d directories, %d files",
+        cache->numDirs, cache->numFiles);
+
+    CACHE_NOISY(ALOGI("Sorting files..."));
+    qsort(cache->files, cache->numFiles, sizeof(cache_file_t*),
+            cache_modtime_sort);
+
+    CACHE_NOISY(ALOGI("Cleaning empty directories..."));
+    for (i=cache->numDirs; i>0; i--) {
+        cache_dir_t* dir = cache->dirs[i-1];
+        if (dir->childCount <= 0 && !dir->deleted) {
+            delete_cache_dir(path, dir);
+        }
+    }
+
+    CACHE_NOISY(ALOGI("Trimming files..."));
+    for (i=0; i<cache->numFiles; i++) {
+        skip++;
+        if (skip > 10) {
+            if (data_disk_free() > free_size) {
+                return;
+            }
+            skip = 0;
+        }
+        cache_file_t* file = cache->files[i];
+        strcpy(create_dir_path(path, file->dir), file->name);
+        ALOGI("DEL (mod %d) %s\n", (int)file->modTime, path);
+        if (unlink(path) < 0) {
+            ALOGE("Couldn't unlink %s: %s\n", path, strerror(errno));
+        }
+        file->dir->childCount--;
+        if (file->dir->childCount <= 0) {
+            delete_cache_dir(path, file->dir);
+        }
+    }
+}
+
+void finish_cache_collection(cache_t* cache)
+{
+    size_t i;
+
+    CACHE_NOISY(ALOGI("clear_cache_files: %d dirs, %d files\n", cache->numDirs, cache->numFiles));
+    CACHE_NOISY(
+        for (i=0; i<cache->numDirs; i++) {
+            cache_dir_t* dir = cache->dirs[i];
+            ALOGI("dir #%d: %p %s parent=%p\n", i, dir, dir->name, dir->parent);
+        })
+    CACHE_NOISY(
+        for (i=0; i<cache->numFiles; i++) {
+            cache_file_t* file = cache->files[i];
+            ALOGI("file #%d: %p %s time=%d dir=%p\n", i, file, file->name,
+                    (int)file->modTime, file->dir);
+        })
+    void* block = cache->memBlocks;
+    while (block != NULL) {
+        void* nextBlock = *(void**)block;
+        CACHE_NOISY(ALOGI("Freeing cache mem block: %p", block));
+        free(block);
+        block = nextBlock;
+    }
+    free(cache);
+}
+
 /**
  * Checks whether a path points to a system app (.apk file). Returns 0
  * if it is a system app or -1 if it is not.
@@ -494,3 +990,17 @@
 
     return result;
 }
+
+/* Ensure that /data/media directories are prepared for given user. */
+int ensure_media_user_dirs(userid_t userid) {
+    char media_user_path[PATH_MAX];
+    char path[PATH_MAX];
+
+    // Ensure /data/media/<userid> exists
+    create_persona_media_path(media_user_path, userid);
+    if (fs_prepare_dir(media_user_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 88a025e..42c9d34 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -35,13 +35,15 @@
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
 import android.content.pm.UserInfo;
+import android.content.pm.VerificationParams;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.net.Uri;
-import android.os.Binder;
-import android.os.Process;
+import android.os.IUserManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.os.UserManager;
 
 import java.io.File;
 import java.lang.reflect.Field;
@@ -59,6 +61,7 @@
 
 public final class Pm {
     IPackageManager mPm;
+    IUserManager mUm;
 
     private WeakHashMap<String, Resources> mResourceCache
             = new WeakHashMap<String, Resources>();
@@ -69,7 +72,6 @@
 
     private static final String PM_NOT_RUNNING_ERR =
         "Error: Could not access the Package Manager.  Is the system running?";
-    private static final int ROOT_UID = 0;
 
     public static void main(String[] args) {
         new Pm().run(args);
@@ -82,6 +84,7 @@
             return;
         }
 
+        mUm = IUserManager.Stub.asInterface(ServiceManager.getService("user"));
         mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
         if (mPm == null) {
             System.err.println(PM_NOT_RUNNING_ERR);
@@ -157,6 +160,11 @@
             return;
         }
 
+        if ("trim-caches".equals(op)) {
+            runTrimCaches();
+            return;
+        }
+
         if ("create-user".equals(op)) {
             runCreateUser();
             return;
@@ -167,8 +175,8 @@
             return;
         }
 
-        if ("list-users".equals(op)) {
-            runListUsers();
+        if ("get-max-users".equals(op)) {
+            runGetMaxUsers();
             return;
         }
 
@@ -211,7 +219,6 @@
         String type = nextArg();
         if (type == null) {
             System.err.println("Error: didn't specify type of data to list");
-            showUsage();
             return;
         }
         if ("package".equals(type) || "packages".equals(type)) {
@@ -230,7 +237,6 @@
             runListUsers();
         } else {
             System.err.println("Error: unknown list type '" + type + "'");
-            showUsage();
         }
     }
 
@@ -242,6 +248,7 @@
         boolean listDisabled = false, listEnabled = false;
         boolean listSystem = false, listThirdParty = false;
         boolean listInstaller = false;
+        int userId = UserHandle.USER_OWNER;
         try {
             String opt;
             while ((opt=nextOption()) != null) {
@@ -261,24 +268,24 @@
                     listThirdParty = true;
                 } else if (opt.equals("-i")) {
                     listInstaller = true;
+                } else if (opt.equals("--user")) {
+                    userId = Integer.parseInt(nextArg());
                 } else if (opt.equals("-u")) {
                     getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES;
                 } else {
                     System.err.println("Error: Unknown option: " + opt);
-                    showUsage();
                     return;
                 }
             }
         } catch (RuntimeException ex) {
             System.err.println("Error: " + ex.toString());
-            showUsage();
             return;
         }
 
         String filter = nextArg();
 
         try {
-            final List<PackageInfo> packages = getInstalledPackages(mPm, getFlags);
+            final List<PackageInfo> packages = getInstalledPackages(mPm, getFlags, userId);
 
             int count = packages.size();
             for (int p = 0 ; p < count ; p++) {
@@ -312,7 +319,7 @@
     }
 
     @SuppressWarnings("unchecked")
-    private List<PackageInfo> getInstalledPackages(IPackageManager pm, int flags)
+    private List<PackageInfo> getInstalledPackages(IPackageManager pm, int flags, int userId)
             throws RemoteException {
         final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>();
         PackageInfo lastItem = null;
@@ -320,7 +327,7 @@
 
         do {
             final String lastKey = lastItem != null ? lastItem.packageName : null;
-            slice = pm.getInstalledPackages(flags, lastKey);
+            slice = pm.getInstalledPackages(flags, lastKey, userId);
             lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR);
         } while (!slice.isLastSlice());
 
@@ -420,13 +427,11 @@
                     targetPackage = opt;
                 } else {
                     System.err.println("Error: Unknown option: " + opt);
-                    showUsage();
                     return;
                 }
             }
         } catch (RuntimeException ex) {
             System.err.println("Error: " + ex.toString());
-            showUsage();
             return;
         }
 
@@ -518,7 +523,6 @@
                     dangerousOnly = true;
                 } else {
                     System.err.println("Error: Unknown option: " + opt);
-                    showUsage();
                     return;
                 }
             }
@@ -667,7 +671,6 @@
         String pkg = nextArg();
         if (pkg == null) {
             System.err.println("Error: no package specified");
-            showUsage();
             return;
         }
         displayPackageFilePath(pkg);
@@ -725,20 +728,17 @@
         String arg = nextArg();
         if (arg == null) {
             System.err.println("Error: no install location specified.");
-            showUsage();
             return;
         }
         try {
             loc = Integer.parseInt(arg);
         } catch (NumberFormatException e) {
             System.err.println("Error: install location has to be a number.");
-            showUsage();
             return;
         }
         try {
             if (!mPm.setInstallLocation(loc)) {
                 System.err.println("Error: install location has to be a number.");
-                showUsage();
             }
         } catch (RemoteException e) {
             System.err.println(e.toString());
@@ -765,7 +765,7 @@
     }
 
     private void runInstall() {
-        int installFlags = 0;
+        int installFlags = PackageManager.INSTALL_ALL_USERS;
         String installerPackageName = null;
 
         String opt;
@@ -777,6 +777,8 @@
         String macAlgo = null;
         byte[] macKey = null;
         byte[] tag = null;
+        String originatingUriString = null;
+        String referrer = null;
 
         while ((opt=nextOption()) != null) {
             if (opt.equals("-l")) {
@@ -787,7 +789,6 @@
                 installerPackageName = nextOptionData();
                 if (installerPackageName == null) {
                     System.err.println("Error: no value specified for -i");
-                    showUsage();
                     return;
                 }
             } else if (opt.equals("-t")) {
@@ -798,51 +799,58 @@
             } else if (opt.equals("-f")) {
                 // Override if -s option is specified.
                 installFlags |= PackageManager.INSTALL_INTERNAL;
+            } else if (opt.equals("-d")) {
+                installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
             } else if (opt.equals("--algo")) {
                 algo = nextOptionData();
                 if (algo == null) {
                     System.err.println("Error: must supply argument for --algo");
-                    showUsage();
                     return;
                 }
             } else if (opt.equals("--iv")) {
                 iv = hexToBytes(nextOptionData());
                 if (iv == null) {
                     System.err.println("Error: must supply argument for --iv");
-                    showUsage();
                     return;
                 }
             } else if (opt.equals("--key")) {
                 key = hexToBytes(nextOptionData());
                 if (key == null) {
                     System.err.println("Error: must supply argument for --key");
-                    showUsage();
                     return;
                 }
             } else if (opt.equals("--macalgo")) {
                 macAlgo = nextOptionData();
                 if (macAlgo == null) {
                     System.err.println("Error: must supply argument for --macalgo");
-                    showUsage();
                     return;
                 }
             } else if (opt.equals("--mackey")) {
                 macKey = hexToBytes(nextOptionData());
                 if (macKey == null) {
                     System.err.println("Error: must supply argument for --mackey");
-                    showUsage();
                     return;
                 }
             } else if (opt.equals("--tag")) {
                 tag = hexToBytes(nextOptionData());
                 if (tag == null) {
                     System.err.println("Error: must supply argument for --tag");
-                    showUsage();
+                    return;
+                }
+            } else if (opt.equals("--originating-uri")) {
+                originatingUriString = nextOptionData();
+                if (originatingUriString == null) {
+                    System.err.println("Error: must supply argument for --originating-uri");
+                    return;
+                }
+            } else if (opt.equals("--referrer")) {
+                referrer = nextOptionData();
+                if (referrer == null) {
+                    System.err.println("Error: must supply argument for --referrer");
                     return;
                 }
             } else {
                 System.err.println("Error: Unknown option: " + opt);
-                showUsage();
                 return;
             }
         }
@@ -852,7 +860,6 @@
                 || tag != null) {
             if (algo == null || iv == null || key == null) {
                 System.err.println("Error: all of --algo, --iv, and --key must be specified");
-                showUsage();
                 return;
             }
 
@@ -860,7 +867,6 @@
                 if (macAlgo == null || macKey == null || tag == null) {
                     System.err.println("Error: all of --macalgo, --mackey, and --tag must "
                             + "be specified");
-                    showUsage();
                     return;
                 }
             }
@@ -887,6 +893,20 @@
 
         final Uri apkURI;
         final Uri verificationURI;
+        final Uri originatingURI;
+        final Uri referrerURI;
+
+        if (originatingUriString != null) {
+            originatingURI = Uri.parse(originatingUriString);
+        } else {
+            originatingURI = null;
+        }
+
+        if (referrer != null) {
+            referrerURI = Uri.parse(referrer);
+        } else {
+            referrerURI = null;
+        }
 
         // Populate apkURI, must be present
         final String apkFilePath = nextArg();
@@ -895,7 +915,6 @@
             apkURI = Uri.fromFile(new File(apkFilePath));
         } else {
             System.err.println("Error: no package specified");
-            showUsage();
             return;
         }
 
@@ -910,8 +929,11 @@
 
         PackageInstallObserver obs = new PackageInstallObserver();
         try {
-            mPm.installPackageWithVerification(apkURI, obs, installFlags, installerPackageName,
-                    verificationURI, null, encryptionParams);
+            VerificationParams verificationParams = new VerificationParams(verificationURI,
+                    originatingURI, referrerURI, VerificationParams.NO_UID, null);
+
+            mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags,
+                    installerPackageName, verificationParams, encryptionParams);
 
             synchronized (obs) {
                 while (!obs.finished) {
@@ -966,23 +988,19 @@
     }
 
     public void runCreateUser() {
-        // Need to be run as root
-        if (Process.myUid() != ROOT_UID) {
-            System.err.println("Error: create-user must be run as root");
-            return;
-        }
         String name;
         String arg = nextArg();
         if (arg == null) {
             System.err.println("Error: no user name specified.");
-            showUsage();
             return;
         }
         name = arg;
         try {
-            if (mPm.createUser(name, 0) == null) {
+            final UserInfo info = mUm.createUser(name, 0);
+            if (info != null) {
+                System.out.println("Success: created user id " + info.id);
+            } else {
                 System.err.println("Error: couldn't create User.");
-                showUsage();
             }
         } catch (RemoteException e) {
             System.err.println(e.toString());
@@ -992,29 +1010,23 @@
     }
 
     public void runRemoveUser() {
-        // Need to be run as root
-        if (Process.myUid() != ROOT_UID) {
-            System.err.println("Error: remove-user must be run as root");
-            return;
-        }
         int userId;
         String arg = nextArg();
         if (arg == null) {
             System.err.println("Error: no user id specified.");
-            showUsage();
             return;
         }
         try {
             userId = Integer.parseInt(arg);
         } catch (NumberFormatException e) {
-            System.err.println("Error: user id has to be a number.");
-            showUsage();
+            System.err.println("Error: user id '" + arg + "' is not a number.");
             return;
         }
         try {
-            if (!mPm.removeUser(userId)) {
-                System.err.println("Error: couldn't remove user.");
-                showUsage();
+            if (mUm.removeUser(userId)) {
+                System.out.println("Success: removed user");
+            } else {
+                System.err.println("Error: couldn't remove user id " + userId);
             }
         } catch (RemoteException e) {
             System.err.println(e.toString());
@@ -1023,13 +1035,8 @@
     }
 
     public void runListUsers() {
-        // Need to be run as root
-        if (Process.myUid() != ROOT_UID) {
-            System.err.println("Error: list-users must be run as root");
-            return;
-        }
         try {
-            List<UserInfo> users = mPm.getUsers();
+            List<UserInfo> users = mUm.getUsers(false);
             if (users == null) {
                 System.err.println("Error: couldn't get users");
             } else {
@@ -1043,6 +1050,11 @@
             System.err.println(PM_NOT_RUNNING_ERR);
         }
     }
+
+    public void runGetMaxUsers() {
+        System.out.println("Maximum supported users: " + UserManager.getMaxSupportedUsers());
+    }
+
     class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
         boolean finished;
         boolean result;
@@ -1057,11 +1069,16 @@
     }
 
     private void runUninstall() {
-        int unInstallFlags = 0;
+        int unInstallFlags = PackageManager.DELETE_ALL_USERS;
 
-        String opt = nextOption();
-        if (opt != null && opt.equals("-k")) {
-            unInstallFlags = PackageManager.DONT_DELETE_DATA;
+        String opt;
+        while ((opt=nextOption()) != null) {
+            if (opt.equals("-k")) {
+                unInstallFlags |= PackageManager.DELETE_KEEP_DATA;
+            } else {
+                System.err.println("Error: Unknown option: " + opt);
+                return;
+            }
         }
 
         String pkg = nextArg();
@@ -1098,7 +1115,7 @@
         return obs.result;
     }
 
-    class ClearDataObserver extends IPackageDataObserver.Stub {
+    static class ClearDataObserver extends IPackageDataObserver.Stub {
         boolean finished;
         boolean result;
 
@@ -1114,6 +1131,19 @@
     }
 
     private void runClear() {
+        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 specified");
@@ -1123,8 +1153,7 @@
 
         ClearDataObserver obs = new ClearDataObserver();
         try {
-            if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs,
-                    Binder.getOrigCallingUser())) {
+            if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs, userId)) {
                 System.err.println("Failed");
             }
 
@@ -1162,7 +1191,7 @@
         return "unknown";
     }
 
-    private boolean isNumber(String s) {
+    private static boolean isNumber(String s) {
         try {
             Integer.parseInt(s);
         } catch (NumberFormatException nfe) {
@@ -1272,6 +1301,75 @@
         }
     }
 
+    static class ClearCacheObserver extends IPackageDataObserver.Stub {
+        boolean finished;
+        boolean result;
+
+        @Override
+        public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
+            synchronized (this) {
+                finished = true;
+                result = succeeded;
+                notifyAll();
+            }
+        }
+
+    }
+
+    private void runTrimCaches() {
+        String size = nextArg();
+        if (size == null) {
+            System.err.println("Error: no size specified");
+            showUsage();
+            return;
+        }
+        int len = size.length();
+        long multiplier = 1;
+        if (len > 1) {
+            char c = size.charAt(len-1);
+            if (c == 'K' || c == 'k') {
+                multiplier = 1024L;
+            } else if (c == 'M' || c == 'm') {
+                multiplier = 1024L*1024L;
+            } else if (c == 'G' || c == 'g') {
+                multiplier = 1024L*1024L*1024L;
+            } else {
+                System.err.println("Invalid suffix: " + c);
+                showUsage();
+                return;
+            }
+            size = size.substring(0, len-1);
+        }
+        long sizeVal;
+        try {
+            sizeVal = Long.parseLong(size) * multiplier;
+        } catch (NumberFormatException e) {
+            System.err.println("Error: expected number at: " + size);
+            showUsage();
+            return;
+        }
+        ClearDataObserver obs = new ClearDataObserver();
+        try {
+            mPm.freeStorageAndNotify(sizeVal, obs);
+            synchronized (obs) {
+                while (!obs.finished) {
+                    try {
+                        obs.wait();
+                    } catch (InterruptedException e) {
+                    }
+                }
+            }
+        } catch (RemoteException e) {
+            System.err.println(e.toString());
+            System.err.println(PM_NOT_RUNNING_ERR);
+        } catch (IllegalArgumentException e) {
+            System.err.println("Bad argument: " + e.toString());
+            showUsage();
+        } catch (SecurityException e) {
+            System.err.println("Operation not allowed: " + e.toString());
+        }
+    }
+
     /**
      * Displays the package file for a package.
      * @param pckg
@@ -1354,25 +1452,31 @@
     }
 
     private static void showUsage() {
-        System.err.println("usage: pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [FILTER]");
+        System.err.println("usage: pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]");
         System.err.println("       pm list permission-groups");
         System.err.println("       pm list permissions [-g] [-f] [-d] [-u] [GROUP]");
         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]");
-        System.err.println("                  [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>] PATH");
+        System.err.println("                  [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>]");
+        System.err.println("                  [--originating-uri <URI>] [--referrer <URI>] PATH");
         System.err.println("       pm uninstall [-k] PACKAGE");
-        System.err.println("       pm clear PACKAGE");
-        System.err.println("       pm enable PACKAGE_OR_COMPONENT");
-        System.err.println("       pm disable PACKAGE_OR_COMPONENT");
-        System.err.println("       pm disable-user PACKAGE_OR_COMPONENT");
+        System.err.println("       pm clear [--user USER_ID] PACKAGE");
+        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 set-permission-enforced PERMISSION [true|false]");
+        System.err.println("       pm trim-caches DESIRED_FREE_SPACE");
+        System.err.println("       pm create-user USER_NAME");
+        System.err.println("       pm remove-user USER_ID");
+        System.err.println("       pm get-max-users");
         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:");
@@ -1401,6 +1505,8 @@
         System.err.println("");
         System.err.println("pm list features: prints all features of the system.");
         System.err.println("");
+        System.err.println("pm list users: prints all users on the system.");
+        System.err.println("");
         System.err.println("pm path: print the path to the .apk of the given PACKAGE.");
         System.err.println("");
         System.err.println("pm install: installs a package to the system.  Options:");
@@ -1410,6 +1516,7 @@
         System.err.println("    -i: specify the installer package name.");
         System.err.println("    -s: install package on sdcard.");
         System.err.println("    -f: install package on internal flash.");
+        System.err.println("    -d: allow version code downgrade.");
         System.err.println("");
         System.err.println("pm uninstall: removes a package from the system. Options:");
         System.err.println("    -k: keep the data and cache directories around after package removal.");
@@ -1434,5 +1541,13 @@
         System.err.println("    0 [auto]: Let system decide the best location");
         System.err.println("    1 [internal]: Install on internal device storage");
         System.err.println("    2 [external]: Install on external media");
+        System.err.println("");
+        System.err.println("pm trim-caches: trim cache files to reach the given free space.");
+        System.err.println("");
+        System.err.println("pm create-user: create a new user with the given USER_NAME,");
+        System.err.println("  printing the new user identifier of the user.");
+        System.err.println("");
+        System.err.println("pm remove-user: remove the user with the given USER_IDENTIFIER,");
+        System.err.println("  deleting all data associated with that user");
     }
 }
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 46e41e3..a1ea81a 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -25,6 +25,7 @@
 
 #include <binder/IMemory.h>
 #include <gui/SurfaceComposerClient.h>
+#include <gui/ISurfaceComposer.h>
 
 #include <SkImageEncoder.h>
 #include <SkBitmap.h>
@@ -33,15 +34,18 @@
 
 using namespace android;
 
+static uint32_t DEFAULT_DISPLAY_ID = ISurfaceComposer::eDisplayIdMain;
+
 static void usage(const char* pname)
 {
     fprintf(stderr,
-            "usage: %s [-hp] [FILENAME]\n"
+            "usage: %s [-hp] [-d display-id] [FILENAME]\n"
             "   -h: this message\n"
             "   -p: save the file as a png.\n"
+            "   -d: specify the display id to capture, default %d.\n"
             "If FILENAME ends with .png it will be saved as a png.\n"
             "If FILENAME is not given, the results will be printed to stdout.\n",
-            pname
+            pname, DEFAULT_DISPLAY_ID
     );
 }
 
@@ -87,12 +91,16 @@
 {
     const char* pname = argv[0];
     bool png = false;
+    int32_t displayId = DEFAULT_DISPLAY_ID;
     int c;
-    while ((c = getopt(argc, argv, "ph")) != -1) {
+    while ((c = getopt(argc, argv, "phd:")) != -1) {
         switch (c) {
             case 'p':
                 png = true;
                 break;
+            case 'd':
+                displayId = atoi(optarg);
+                break;
             case '?':
             case 'h':
                 usage(pname);
@@ -131,7 +139,8 @@
     size_t size = 0;
 
     ScreenshotClient screenshot;
-    if (screenshot.update() == NO_ERROR) {
+    sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(displayId);
+    if (display != NULL && screenshot.update(display) == NO_ERROR) {
         base = screenshot.getPixels();
         w = screenshot.getWidth();
         h = screenshot.getHeight();
diff --git a/cmds/sensorservice/Android.mk b/cmds/sensorservice/Android.mk
deleted file mode 100644
index 0811be5..0000000
--- a/cmds/sensorservice/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	main_sensorservice.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libsensorservice \
-	libbinder \
-	libutils
-
-LOCAL_C_INCLUDES := \
-	$(LOCAL_PATH)/../../services/sensorservice
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE:= sensorservice
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/sensorservice/main_sensorservice.cpp b/cmds/sensorservice/main_sensorservice.cpp
deleted file mode 100644
index 8610627..0000000
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ /dev/null
@@ -1,25 +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.
- */
-
-#include <binder/BinderService.h>
-#include <SensorService.h>
-
-using namespace android;
-
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 71c5622..3314dc3 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -33,6 +33,7 @@
     { AID_MEDIA, "media.audio_policy" },
     { AID_DRM,   "drm.drmManager" },
     { AID_NFC,   "nfc" },
+    { AID_BLUETOOTH, "bluetooth" },
     { AID_RADIO, "radio.phone" },
     { AID_RADIO, "radio.sms" },
     { AID_RADIO, "radio.phonesubinfo" },
diff --git a/cmds/settings/Android.mk b/cmds/settings/Android.mk
new file mode 100644
index 0000000..05deb99
--- /dev/null
+++ b/cmds/settings/Android.mk
@@ -0,0 +1,18 @@
+# Copyright 2011 The Android Open Source Project
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_MODULE := settings
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := settings
+LOCAL_SRC_FILES := settings
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_PREBUILT)
+
+
diff --git a/cmds/settings/settings b/cmds/settings/settings
new file mode 100755
index 0000000..ef459ca
--- /dev/null
+++ b/cmds/settings/settings
@@ -0,0 +1,5 @@
+# Script to start "settings" on the device
+#
+base=/system
+export CLASSPATH=$base/framework/settings.jar
+exec app_process $base/bin com.android.commands.settings.SettingsCmd "$@"
diff --git a/cmds/settings/src/com/android/commands/settings/SettingsCmd.java b/cmds/settings/src/com/android/commands/settings/SettingsCmd.java
new file mode 100644
index 0000000..0c69f01
--- /dev/null
+++ b/cmds/settings/src/com/android/commands/settings/SettingsCmd.java
@@ -0,0 +1,220 @@
+/*
+ * 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.commands.settings;
+
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
+import android.app.IActivityManager.ContentProviderHolder;
+import android.content.IContentProvider;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+public final class SettingsCmd {
+    static final String TAG = "settings";
+
+    enum CommandVerb {
+        UNSPECIFIED,
+        GET,
+        PUT
+    }
+
+    static String[] mArgs;
+    int mNextArg;
+    int mUser = -1;     // unspecified
+    CommandVerb mVerb = CommandVerb.UNSPECIFIED;
+    String mTable = null;
+    String mKey = null;
+    String mValue = null;
+
+    public static void main(String[] args) {
+        if (args == null || args.length < 3) {
+            printUsage();
+            return;
+        }
+
+        mArgs = args;
+        try {
+            new SettingsCmd().run();
+        } catch (Exception e) {
+            System.err.println("Unable to run settings command");
+        }
+    }
+
+    public void run() {
+        boolean valid = false;
+        String arg;
+        try {
+            while ((arg = nextArg()) != null) {
+                if ("--user".equals(arg)) {
+                    if (mUser != -1) {
+                        // --user specified more than once; invalid
+                        break;
+                    }
+                    mUser = Integer.parseInt(nextArg());
+                } else if (mVerb == CommandVerb.UNSPECIFIED) {
+                    if ("get".equalsIgnoreCase(arg)) {
+                        mVerb = CommandVerb.GET;
+                    } else if ("put".equalsIgnoreCase(arg)) {
+                        mVerb = CommandVerb.PUT;
+                    } else {
+                        // invalid
+                        System.err.println("Invalid command: " + arg);
+                        break;
+                    }
+                } else if (mTable == null) {
+                    if (!"system".equalsIgnoreCase(arg)
+                            && !"secure".equalsIgnoreCase(arg)
+                            && !"global".equalsIgnoreCase(arg)) {
+                        System.err.println("Invalid namespace '" + arg + "'");
+                        break;  // invalid
+                    }
+                    mTable = arg.toLowerCase();
+                } else if (mVerb == CommandVerb.GET) {
+                    mKey = arg;
+                    if (mNextArg >= mArgs.length) {
+                        valid = true;
+                    } else {
+                        System.err.println("Too many arguments");
+                    }
+                    break;
+                } else if (mKey == null) {
+                    mKey = arg;
+                    // keep going; there's another PUT arg
+                } else {    // PUT, final arg
+                    mValue = arg;
+                    if (mNextArg >= mArgs.length) {
+                        valid = true;
+                    } else {
+                        System.err.println("Too many arguments");
+                    }
+                    break;
+                }
+            }
+        } catch (Exception e) {
+            valid = false;
+        }
+
+        if (valid) {
+            if (mUser < 0) {
+                mUser = UserHandle.USER_OWNER;
+            }
+
+            try {
+                IActivityManager activityManager = ActivityManagerNative.getDefault();
+                IContentProvider provider = null;
+                IBinder token = new Binder();
+                try {
+                    ContentProviderHolder holder = activityManager.getContentProviderExternal(
+                            "settings", UserHandle.USER_OWNER, token);
+                    if (holder == null) {
+                        throw new IllegalStateException("Could not find settings provider");
+                    }
+                    provider = holder.provider;
+
+                    switch (mVerb) {
+                        case GET:
+                            System.out.println(getForUser(provider, mUser, mTable, mKey));
+                            break;
+                        case PUT:
+                            putForUser(provider, mUser, mTable, mKey, mValue);
+                            break;
+                        default:
+                            System.err.println("Unspecified command");
+                            break;
+                    }
+
+                } finally {
+                    if (provider != null) {
+                        activityManager.removeContentProviderExternal("settings", token);
+                    }
+                }
+            } catch (Exception e) {
+                System.err.println("Error while accessing settings provider");
+                e.printStackTrace();
+            }
+
+        } else {
+            printUsage();
+        }
+    }
+
+    private String nextArg() {
+        if (mNextArg >= mArgs.length) {
+            return null;
+        }
+        String arg = mArgs[mNextArg];
+        mNextArg++;
+        return arg;
+    }
+
+    String getForUser(IContentProvider provider, int userHandle,
+            final String table, final String key) {
+        final String callGetCommand;
+        if ("system".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_SYSTEM;
+        else if ("secure".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_SECURE;
+        else if ("global".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_GLOBAL;
+        else {
+            System.err.println("Invalid table; no put performed");
+            throw new IllegalArgumentException("Invalid table " + table);
+        }
+
+        String result = null;
+        try {
+            Bundle arg = new Bundle();
+            arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
+            Bundle b = provider.call(callGetCommand, key, arg);
+            if (b != null) {
+                result = b.getPairValue();
+            }
+        } catch (RemoteException e) {
+            System.err.println("Can't read key " + key + " in " + table + " for user " + userHandle);
+        }
+        return result;
+    }
+
+    void putForUser(IContentProvider provider, int userHandle,
+            final String table, final String key, final String value) {
+        final String callPutCommand;
+        if ("system".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SYSTEM;
+        else if ("secure".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SECURE;
+        else if ("global".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_GLOBAL;
+        else {
+            System.err.println("Invalid table; no put performed");
+            return;
+        }
+
+        try {
+            Bundle arg = new Bundle();
+            arg.putString(Settings.NameValueTable.VALUE, value);
+            arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
+            provider.call(callPutCommand, key, arg);
+        } catch (RemoteException e) {
+            System.err.println("Can't set key " + key + " in " + table + " for user " + userHandle);
+        }
+    }
+
+    private static void printUsage() {
+        System.err.println("usage:  settings [--user NUM] get namespace key");
+        System.err.println("        settings [--user NUM] put namespace key value");
+        System.err.println("\n'namespace' is one of {system, secure, global}, case-insensitive");
+        System.err.println("If '--user NUM' is not given, the operations are performed on the owner user.");
+    }
+}
diff --git a/cmds/svc/src/com/android/commands/svc/PowerCommand.java b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
index e1d6619..58105fa 100644
--- a/cmds/svc/src/com/android/commands/svc/PowerCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
@@ -16,14 +16,12 @@
 
 package com.android.commands.svc;
 
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.IPowerManager;
-import android.os.PowerManager;
-import android.os.ServiceManager;
-import android.os.RemoteException;
-import android.os.BatteryManager;
 import android.content.Context;
+import android.os.BatteryManager;
+import android.os.IPowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
 
 public class PowerCommand extends Svc.Command {
     public PowerCommand() {
@@ -37,7 +35,7 @@
     public String longHelp() {
         return shortHelp() + "\n"
                 + "\n"
-                + "usage: svc power stayon [true|false|usb|ac]\n"
+                + "usage: svc power stayon [true|false|usb|ac|wireless]\n"
                 + "         Set the 'keep awake while plugged in' setting.\n";
     }
 
@@ -48,7 +46,8 @@
                     int val;
                     if ("true".equals(args[2])) {
                         val = BatteryManager.BATTERY_PLUGGED_AC |
-                                BatteryManager.BATTERY_PLUGGED_USB;
+                                BatteryManager.BATTERY_PLUGGED_USB |
+                                BatteryManager.BATTERY_PLUGGED_WIRELESS;
                     }
                     else if ("false".equals(args[2])) {
                         val = 0;
@@ -56,17 +55,20 @@
                         val = BatteryManager.BATTERY_PLUGGED_USB;
                     } else if ("ac".equals(args[2])) {
                         val = BatteryManager.BATTERY_PLUGGED_AC;
-                    }
-                    else {
+                    } else if ("wireless".equals(args[2])) {
+                        val = BatteryManager.BATTERY_PLUGGED_WIRELESS;
+                    } else {
                         break fail;
                     }
                     IPowerManager pm
                             = IPowerManager.Stub.asInterface(ServiceManager.getService(Context.POWER_SERVICE));
                     try {
-                        IBinder lock = new Binder();
-                        pm.acquireWakeLock(PowerManager.FULL_WAKE_LOCK, lock, "svc power", null);
+                        if (val != 0) {
+                            // if the request is not to set it to false, wake up the screen so that
+                            // it can stay on as requested
+                            pm.wakeUp(SystemClock.uptimeMillis());
+                        }
                         pm.setStayOnSetting(val);
-                        pm.releaseWakeLock(lock, 0);
                     }
                     catch (RemoteException e) {
                         System.err.println("Faild to set setting: " + e);
diff --git a/cmds/system_server/library/Android.mk b/cmds/system_server/library/Android.mk
index 9f92330..c42424c 100644
--- a/cmds/system_server/library/Android.mk
+++ b/cmds/system_server/library/Android.mk
@@ -8,7 +8,7 @@
 native = $(LOCAL_PATH)/../../../../native
 
 LOCAL_C_INCLUDES := \
-	$(base)/services/sensorservice \
+	$(native)/services/sensorservice \
 	$(native)/services/surfaceflinger \
 	$(JNI_H_INCLUDE)
 
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 81ee192..b0bad07 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -323,7 +323,7 @@
     public static final int GLOBAL_ACTION_HOME = 2;
 
     /**
-     * Action to open the recents.
+     * Action to open the recent apps.
      */
     public static final int GLOBAL_ACTION_RECENTS = 3;
 
@@ -332,6 +332,11 @@
      */
     public static final int GLOBAL_ACTION_NOTIFICATIONS = 4;
 
+    /**
+     * Action to open the quick settings.
+     */
+    public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5;
+
     private static final String LOG_TAG = "AccessibilityService";
 
     interface Callbacks {
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 10ea0fe..75a4f83 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -85,6 +85,11 @@
     public static final int FEEDBACK_GENERIC = 0x0000010;
 
     /**
+     * Denotes braille feedback.
+     */
+    public static final int FEEDBACK_BRAILLE = 0x0000020;
+
+    /**
      * Mask for all feedback types.
      *
      * @see #FEEDBACK_SPOKEN
@@ -92,6 +97,7 @@
      * @see #FEEDBACK_AUDIBLE
      * @see #FEEDBACK_VISUAL
      * @see #FEEDBACK_GENERIC
+     * @see #FEEDBACK_BRAILLE
      */
     public static final int FEEDBACK_ALL_MASK = 0xFFFFFFFF;
 
@@ -186,6 +192,7 @@
      * @see #FEEDBACK_HAPTIC
      * @see #FEEDBACK_SPOKEN
      * @see #FEEDBACK_VISUAL
+     * @see #FEEDBACK_BRAILLE
      */
     public int feedbackType;
 
@@ -591,6 +598,12 @@
                     }
                     builder.append("FEEDBACK_VISUAL");
                     break;
+                case FEEDBACK_BRAILLE:
+                    if (builder.length() > 1) {
+                        builder.append(", ");
+                    }
+                    builder.append("FEEDBACK_BRAILLE");
+                    break;
             }
         }
         builder.append("]");
diff --git a/core/java/android/accounts/AccountAuthenticatorCache.java b/core/java/android/accounts/AccountAuthenticatorCache.java
index 7214c50..f937cde 100644
--- a/core/java/android/accounts/AccountAuthenticatorCache.java
+++ b/core/java/android/accounts/AccountAuthenticatorCache.java
@@ -16,17 +16,18 @@
 
 package android.accounts;
 
+import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.RegisteredServicesCache;
 import android.content.pm.XmlSerializerAndParser;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
-import android.content.Context;
-import android.util.AttributeSet;
 import android.text.TextUtils;
+import android.util.AttributeSet;
+
 import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlSerializer;
 import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
 
 import java.io.IOException;
 
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index f3c6566..bcb35d5 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -28,6 +28,8 @@
 import android.os.RemoteException;
 import android.os.Parcelable;
 import android.os.Build;
+import android.os.Process;
+import android.os.UserHandle;
 import android.util.Log;
 import android.text.TextUtils;
 
@@ -42,7 +44,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
 /**
@@ -396,8 +397,13 @@
      *     (never null) if no accounts of the specified type have been added.
      */
     public Account[] getAccountsByType(String type) {
+        return getAccountsByTypeAsUser(type, Process.myUserHandle());
+    }
+
+    /** @hide Same as {@link #getAccountsByType(String)} but for a specific user. */
+    public Account[] getAccountsByTypeAsUser(String type, UserHandle userHandle) {
         try {
-            return mService.getAccounts(type);
+            return mService.getAccountsAsUser(type, userHandle.getIdentifier());
         } catch (RemoteException e) {
             // won't ever happen
             throw new RuntimeException(e);
@@ -1175,10 +1181,26 @@
             final Activity activity,
             final AccountManagerCallback<Bundle> callback,
             final Handler handler) {
+        return confirmCredentialsAsUser(account, options, activity, callback, handler,
+                Process.myUserHandle());
+    }
+
+    /**
+     * @hide
+     * Same as {@link #confirmCredentials(Account, Bundle, Activity, AccountManagerCallback, Handler)}
+     * but for the specified user.
+     */
+    public AccountManagerFuture<Bundle> confirmCredentialsAsUser(final Account account,
+            final Bundle options,
+            final Activity activity,
+            final AccountManagerCallback<Bundle> callback,
+            final Handler handler, UserHandle userHandle) {
         if (account == null) throw new IllegalArgumentException("account is null");
+        final int userId = userHandle.getIdentifier();
         return new AmsTask(activity, handler, callback) {
             public void doWork() throws RemoteException {
-                mService.confirmCredentials(mResponse, account, options, activity != null);
+                mService.confirmCredentialsAsUser(mResponse, account, options, activity != null,
+                        userId);
             }
         }.start();
     }
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 22e454f..2b1a2b2 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -18,7 +18,7 @@
 
 import android.Manifest;
 import android.app.ActivityManager;
-import android.app.AppGlobals;
+import android.app.ActivityManagerNative;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -32,10 +32,10 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.RegisteredServicesCache;
 import android.content.pm.RegisteredServicesCacheListener;
 import android.content.pm.UserInfo;
-import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.DatabaseUtils;
 import android.database.sqlite.SQLiteDatabase;
@@ -50,14 +50,18 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.UserId;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
+import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.R;
 import com.android.internal.util.IndentingPrintWriter;
+import com.google.android.collect.Lists;
+import com.google.android.collect.Sets;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -66,6 +70,7 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -92,6 +97,7 @@
     private final Context mContext;
 
     private final PackageManager mPackageManager;
+    private UserManager mUserManager;
 
     private HandlerThread mMessageThread;
     private final MessageHandler mMessageHandler;
@@ -241,8 +247,13 @@
     }
 
     public void systemReady() {
-        mAuthenticatorCache.generateServicesMap();
-        initUser(0);
+    }
+
+    private UserManager getUserManager() {
+        if (mUserManager == null) {
+            mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        }
+        return mUserManager;
     }
 
     private UserAccounts initUser(int userId) {
@@ -252,7 +263,7 @@
                 accounts = new UserAccounts(mContext, userId);
                 mUsers.append(userId, accounts);
                 purgeOldGrants(accounts);
-                validateAccountsAndPopulateCache(accounts);
+                validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */);
             }
             return accounts;
         }
@@ -290,7 +301,34 @@
         }
     }
 
-    private void validateAccountsAndPopulateCache(UserAccounts accounts) {
+    /**
+     * Validate internal set of accounts against installed authenticators for
+     * given user. Clears cached authenticators before validating.
+     */
+    public void validateAccounts(int userId) {
+        final UserAccounts accounts = getUserAccounts(userId);
+
+        // Invalidate user-specific cache to make sure we catch any
+        // removed authenticators.
+        validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */);
+    }
+
+    /**
+     * Validate internal set of accounts against installed authenticators for
+     * given user. Clear cached authenticators before validating when requested.
+     */
+    private void validateAccountsInternal(
+            UserAccounts accounts, boolean invalidateAuthenticatorCache) {
+        if (invalidateAuthenticatorCache) {
+            mAuthenticatorCache.invalidateCache(accounts.userId);
+        }
+
+        final HashSet<AuthenticatorDescription> knownAuth = Sets.newHashSet();
+        for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service :
+                mAuthenticatorCache.getAllServices(accounts.userId)) {
+            knownAuth.add(service.type);
+        }
+
         synchronized (accounts.cacheLock) {
             final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
             boolean accountDeleted = false;
@@ -305,9 +343,9 @@
                     final long accountId = cursor.getLong(0);
                     final String accountType = cursor.getString(1);
                     final String accountName = cursor.getString(2);
-                    if (mAuthenticatorCache.getServiceInfo(
-                            AuthenticatorDescription.newKey(accountType)) == null) {
-                        Log.d(TAG, "deleting account " + accountName + " because type "
+
+                    if (!knownAuth.contains(AuthenticatorDescription.newKey(accountType))) {
+                        Slog.w(TAG, "deleting account " + accountName + " because type "
                                 + accountType + " no longer has a registered authenticator");
                         db.delete(TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null);
                         accountDeleted = true;
@@ -345,7 +383,7 @@
     }
 
     private UserAccounts getUserAccountsForCaller() {
-        return getUserAccounts(UserId.getCallingUserId());
+        return getUserAccounts(UserHandle.getCallingUserId());
     }
 
     protected UserAccounts getUserAccounts(int userId) {
@@ -360,7 +398,7 @@
     }
 
     private void onUserRemoved(Intent intent) {
-        int userId = intent.getIntExtra(Intent.EXTRA_USERID, -1);
+        int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
         if (userId < 1) return;
 
         UserAccounts accounts;
@@ -381,25 +419,10 @@
         }
     }
 
-    private List<UserInfo> getAllUsers() {
-        try {
-            return AppGlobals.getPackageManager().getUsers();
-        } catch (RemoteException re) {
-            // Local to system process, shouldn't happen
-        }
-        return null;
-    }
-
-    public void onServiceChanged(AuthenticatorDescription desc, boolean removed) {
-        // Validate accounts for all users
-        List<UserInfo> users = getAllUsers();
-        if (users == null) {
-            validateAccountsAndPopulateCache(getUserAccountsForCaller());
-        } else {
-            for (UserInfo user : users) {
-                validateAccountsAndPopulateCache(getUserAccounts(user.id));
-            }
-        }
+    @Override
+    public void onServiceChanged(AuthenticatorDescription desc, int userId, boolean removed) {
+        Slog.d(TAG, "onServiceChanged() for userId " + userId);
+        validateAccountsInternal(getUserAccounts(userId), false /* invalidateAuthenticatorCache */);
     }
 
     public String getPassword(Account account) {
@@ -466,10 +489,11 @@
                     + "caller's uid " + Binder.getCallingUid()
                     + ", pid " + Binder.getCallingPid());
         }
-        long identityToken = clearCallingIdentity();
+        final int userId = UserHandle.getCallingUserId();
+        final long identityToken = clearCallingIdentity();
         try {
             Collection<AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription>>
-                    authenticatorCollection = mAuthenticatorCache.getAllServices();
+                    authenticatorCollection = mAuthenticatorCache.getAllServices(userId);
             AuthenticatorDescription[] types =
                     new AuthenticatorDescription[authenticatorCollection.size()];
             int i = 0;
@@ -643,16 +667,17 @@
         if (response == null) throw new IllegalArgumentException("response is null");
         if (account == null) throw new IllegalArgumentException("account is null");
         checkManageAccountsPermission();
+        UserHandle user = Binder.getCallingUserHandle();
         UserAccounts accounts = getUserAccountsForCaller();
         long identityToken = clearCallingIdentity();
 
-        cancelNotification(getSigninRequiredNotificationId(accounts, account));
+        cancelNotification(getSigninRequiredNotificationId(accounts, account), user);
         synchronized(accounts.credentialsPermissionNotificationIds) {
             for (Pair<Pair<Account, String>, Integer> pair:
                 accounts.credentialsPermissionNotificationIds.keySet()) {
                 if (account.equals(pair.first.first)) {
                     int id = accounts.credentialsPermissionNotificationIds.get(pair);
-                    cancelNotification(id);
+                    cancelNotification(id, user);
                 }
             }
         }
@@ -785,7 +810,8 @@
         if (account == null || type == null) {
             return false;
         }
-        cancelNotification(getSigninRequiredNotificationId(accounts, account));
+        cancelNotification(getSigninRequiredNotificationId(accounts, account),
+                new UserHandle(accounts.userId));
         synchronized (accounts.cacheLock) {
             final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
             db.beginTransaction();
@@ -896,7 +922,7 @@
     private void sendAccountsChangedBroadcast(int userId) {
         Log.i(TAG, "the accounts changed, sending broadcast of "
                 + ACCOUNTS_CHANGED_INTENT.getAction());
-        mContext.sendBroadcast(ACCOUNTS_CHANGED_INTENT, userId);
+        mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId));
     }
 
     public void clearPassword(Account account) {
@@ -1000,7 +1026,7 @@
         if (callingUid != android.os.Process.SYSTEM_UID) {
             throw new SecurityException("can only call from system");
         }
-        UserAccounts accounts = getUserAccounts(UserId.getUserId(callingUid));
+        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid));
         long identityToken = clearCallingIdentity();
         try {
             new Session(accounts, response, accountType, false,
@@ -1048,10 +1074,10 @@
         if (account == null) throw new IllegalArgumentException("account is null");
         if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
         checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
-        UserAccounts accounts = getUserAccountsForCaller();
-        AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo =
-            mAuthenticatorCache.getServiceInfo(
-                    AuthenticatorDescription.newKey(account.type));
+        final UserAccounts accounts = getUserAccountsForCaller();
+        final RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
+        authenticatorInfo = mAuthenticatorCache.getServiceInfo(
+                AuthenticatorDescription.newKey(account.type), accounts.userId);
         final boolean customTokens =
             authenticatorInfo != null && authenticatorInfo.type.customTokens;
 
@@ -1068,7 +1094,7 @@
         if (notifyOnAuthFailure) {
             loginOptions.putBoolean(AccountManager.KEY_NOTIFY_ON_FAILURE, true);
         }
-        
+
         long identityToken = clearCallingIdentity();
         try {
             // if the caller has permission, do the peek. otherwise go the more expensive
@@ -1137,7 +1163,7 @@
                         if (intent != null && notifyOnAuthFailure && !customTokens) {
                             doNotification(mAccounts,
                                     account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE),
-                                    intent);
+                                    intent, accounts.userId);
                         }
                     }
                     super.onResult(result);
@@ -1148,7 +1174,8 @@
         }
     }
 
-    private void createNoCredentialsPermissionNotification(Account account, Intent intent) {
+    private void createNoCredentialsPermissionNotification(Account account, Intent intent,
+            int userId) {
         int uid = intent.getIntExtra(
                 GrantCredentialsPermissionActivity.EXTRAS_REQUESTING_UID, -1);
         String authTokenType = intent.getStringExtra(
@@ -1168,32 +1195,12 @@
             title = titleAndSubtitle.substring(0, index);
             subtitle = titleAndSubtitle.substring(index + 1);            
         }
-        n.setLatestEventInfo(mContext,
-                title, subtitle,
-                PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT));
-        installNotification(getCredentialPermissionNotificationId(account, authTokenType, uid), n);
-    }
-
-    String getAccountLabel(String accountType) {
-        RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo =
-            mAuthenticatorCache.getServiceInfo(
-                    AuthenticatorDescription.newKey(accountType));
-        if (serviceInfo == null) {
-            throw new IllegalArgumentException("unknown account type: " + accountType);
-        }
-
-        final Context authContext;
-        try {
-            authContext = mContext.createPackageContext(
-                    serviceInfo.type.packageName, 0);
-        } catch (PackageManager.NameNotFoundException e) {
-            throw new IllegalArgumentException("unknown account type: " + accountType);
-        }
-        try {
-            return authContext.getString(serviceInfo.type.labelId);
-        } catch (Resources.NotFoundException e) {
-            throw new IllegalArgumentException("unknown account type: " + accountType);
-        }
+        UserHandle user = new UserHandle(userId);
+        n.setLatestEventInfo(mContext, title, subtitle,
+                PendingIntent.getActivityAsUser(mContext, 0, intent,
+                        PendingIntent.FLAG_CANCEL_CURRENT, null, user));
+        installNotification(getCredentialPermissionNotificationId(
+                account, authTokenType, uid), n, user);
     }
 
     private Intent newGrantCredentialsPermissionIntent(Account account, int uid,
@@ -1218,7 +1225,7 @@
     private Integer getCredentialPermissionNotificationId(Account account, String authTokenType,
             int uid) {
         Integer id;
-        UserAccounts accounts = getUserAccounts(UserId.getUserId(uid));
+        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
         synchronized (accounts.credentialsPermissionNotificationIds) {
             final Pair<Pair<Account, String>, Integer> key =
                     new Pair<Pair<Account, String>, Integer>(
@@ -1290,8 +1297,17 @@
         }
     }
 
-    public void confirmCredentials(IAccountManagerResponse response,
-            final Account account, final Bundle options, final boolean expectActivityLaunch) {
+    @Override
+    public void confirmCredentialsAsUser(IAccountManagerResponse response,
+            final Account account, final Bundle options, final boolean expectActivityLaunch,
+            int userId) {
+        // Only allow the system process to read accounts of other users
+        if (userId != UserHandle.getCallingUserId()
+                && Binder.getCallingUid() != android.os.Process.myUid()) {
+            throw new SecurityException("User " + UserHandle.getCallingUserId()
+                    + " trying to confirm account credentials for " + userId);
+        }
+
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "confirmCredentials: " + account
                     + ", response " + response
@@ -1302,7 +1318,7 @@
         if (response == null) throw new IllegalArgumentException("response is null");
         if (account == null) throw new IllegalArgumentException("account is null");
         checkManageAccountsPermission();
-        UserAccounts accounts = getUserAccountsForCaller();
+        UserAccounts accounts = getUserAccounts(userId);
         long identityToken = clearCallingIdentity();
         try {
             new Session(accounts, response, account.type, expectActivityLaunch,
@@ -1497,38 +1513,66 @@
     }
 
     /**
-     * Returns all the accounts qualified by user.
+     * Returns accounts for all running users.
+     *
      * @hide
      */
-    public AccountAndUser[] getAllAccounts() {
-        ArrayList<AccountAndUser> allAccounts = new ArrayList<AccountAndUser>();
-        List<UserInfo> users = getAllUsers();
-        if (users == null)  return new AccountAndUser[0];
+    public AccountAndUser[] getRunningAccounts() {
+        final int[] runningUserIds;
+        try {
+            runningUserIds = ActivityManagerNative.getDefault().getRunningUserIds();
+        } catch (RemoteException e) {
+            // Running in system_server; should never happen
+            throw new RuntimeException(e);
+        }
+        return getAccounts(runningUserIds);
+    }
 
-        synchronized(mUsers) {
-            for (UserInfo user : users) {
-                UserAccounts userAccounts = getUserAccounts(user.id);
+    /** {@hide} */
+    public AccountAndUser[] getAllAccounts() {
+        final List<UserInfo> users = getUserManager().getUsers();
+        final int[] userIds = new int[users.size()];
+        for (int i = 0; i < userIds.length; i++) {
+            userIds[i] = users.get(i).id;
+        }
+        return getAccounts(userIds);
+    }
+
+    private AccountAndUser[] getAccounts(int[] userIds) {
+        final ArrayList<AccountAndUser> runningAccounts = Lists.newArrayList();
+        synchronized (mUsers) {
+            for (int userId : userIds) {
+                UserAccounts userAccounts = getUserAccounts(userId);
                 if (userAccounts == null) continue;
                 synchronized (userAccounts.cacheLock) {
                     Account[] accounts = getAccountsFromCacheLocked(userAccounts, null);
                     for (int a = 0; a < accounts.length; a++) {
-                        allAccounts.add(new AccountAndUser(accounts[a], user.id));
+                        runningAccounts.add(new AccountAndUser(accounts[a], userId));
                     }
                 }
             }
         }
-        AccountAndUser[] accountsArray = new AccountAndUser[allAccounts.size()];
-        return allAccounts.toArray(accountsArray);
+
+        AccountAndUser[] accountsArray = new AccountAndUser[runningAccounts.size()];
+        return runningAccounts.toArray(accountsArray);
     }
 
-    public Account[] getAccounts(String type) {
+    @Override
+    public Account[] getAccountsAsUser(String type, int userId) {
+        // Only allow the system process to read accounts of other users
+        if (userId != UserHandle.getCallingUserId()
+                && Binder.getCallingUid() != android.os.Process.myUid()) {
+            throw new SecurityException("User " + UserHandle.getCallingUserId()
+                    + " trying to get account for " + userId);
+        }
+
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "getAccounts: accountType " + type
                     + ", caller's uid " + Binder.getCallingUid()
                     + ", pid " + Binder.getCallingPid());
         }
         checkReadAccountsPermission();
-        UserAccounts accounts = getUserAccountsForCaller();
+        UserAccounts accounts = getUserAccounts(userId);
         long identityToken = clearCallingIdentity();
         try {
             synchronized (accounts.cacheLock) {
@@ -1539,6 +1583,11 @@
         }
     }
 
+    @Override
+    public Account[] getAccounts(String type) {
+        return getAccountsAsUser(type, UserHandle.getCallingUserId());
+    }
+
     public void getAccountsByFeatures(IAccountManagerResponse response,
             String type, String[] features) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -1757,7 +1806,8 @@
                 String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
                 if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) {
                     Account account = new Account(accountName, accountType);
-                    cancelNotification(getSigninRequiredNotificationId(mAccounts, account));
+                    cancelNotification(getSigninRequiredNotificationId(mAccounts, account),
+                            new UserHandle(mAccounts.userId));
                 }
             }
             IAccountManagerResponse response;
@@ -1826,9 +1876,9 @@
          * if no authenticator or the bind fails then return false, otherwise return true
          */
         private boolean bindToAuthenticator(String authenticatorType) {
-            AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo =
-                    mAuthenticatorCache.getServiceInfo(
-                            AuthenticatorDescription.newKey(authenticatorType));
+            final AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
+            authenticatorInfo = mAuthenticatorCache.getServiceInfo(
+                    AuthenticatorDescription.newKey(authenticatorType), mAccounts.userId);
             if (authenticatorInfo == null) {
                 if (Log.isLoggable(TAG, Log.VERBOSE)) {
                     Log.v(TAG, "there is no authenticator for " + authenticatorType
@@ -1875,7 +1925,7 @@
 
     private static String getDatabaseName(int userId) {
         File systemDir = Environment.getSystemSecureDirectory();
-        File databaseFile = new File(systemDir, "users/" + userId + "/" + DATABASE_NAME);
+        File databaseFile = new File(Environment.getUserSystemDirectory(userId), DATABASE_NAME);
         if (userId == 0) {
             // Migrate old file, if it exists, to the new location.
             // Make sure the new file doesn't already exist. A dummy file could have been
@@ -1884,7 +1934,7 @@
             File oldFile = new File(systemDir, DATABASE_NAME);
             if (oldFile.exists() && !databaseFile.exists()) {
                 // Check for use directory; create if it doesn't exist, else renameTo will fail
-                File userDir = new File(systemDir, "users/" + userId);
+                File userDir = Environment.getUserSystemDirectory(userId);
                 if (!userDir.exists()) {
                     if (!userDir.mkdirs()) {
                         throw new IllegalStateException("User dir cannot be created: " + userDir);
@@ -2014,6 +2064,7 @@
         return false;
     }
 
+    @Override
     protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                 != PackageManager.PERMISSION_GRANTED) {
@@ -2023,17 +2074,15 @@
             return;
         }
         final boolean isCheckinRequest = scanArgs(args, "--checkin") || scanArgs(args, "-c");
+        final IndentingPrintWriter ipw = new IndentingPrintWriter(fout, "  ");
 
-        fout = new IndentingPrintWriter(fout, "  ");
-        int size = mUsers.size();
-        for (int i = 0; i < size; i++) {
-            fout.println("User " + mUsers.keyAt(i) + ":");
-            ((IndentingPrintWriter) fout).increaseIndent();
-            dumpUser(mUsers.valueAt(i), fd, fout, args, isCheckinRequest);
-            ((IndentingPrintWriter) fout).decreaseIndent();
-            if (i < size - 1) {
-                fout.println();
-            }
+        final List<UserInfo> users = getUserManager().getUsers();
+        for (UserInfo user : users) {
+            ipw.println("User " + user + ":");
+            ipw.increaseIndent();
+            dumpUser(getUserAccounts(user.id), fd, ipw, args, isCheckinRequest);
+            ipw.println();
+            ipw.decreaseIndent();
         }
     }
 
@@ -2073,13 +2122,13 @@
                 }
 
                 fout.println();
-                mAuthenticatorCache.dump(fd, fout, args);
+                mAuthenticatorCache.dump(fd, fout, args, userAccounts.userId);
             }
         }
     }
 
     private void doNotification(UserAccounts accounts, Account account, CharSequence message,
-            Intent intent) {
+            Intent intent, int userId) {
         long identityToken = clearCallingIdentity();
         try {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -2089,35 +2138,38 @@
             if (intent.getComponent() != null &&
                     GrantCredentialsPermissionActivity.class.getName().equals(
                             intent.getComponent().getClassName())) {
-                createNoCredentialsPermissionNotification(account, intent);
+                createNoCredentialsPermissionNotification(account, intent, userId);
             } else {
                 final Integer notificationId = getSigninRequiredNotificationId(accounts, account);
                 intent.addCategory(String.valueOf(notificationId));
                 Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
                         0 /* when */);
+                UserHandle user = new UserHandle(userId);
                 final String notificationTitleFormat =
                         mContext.getText(R.string.notification_title).toString();
                 n.setLatestEventInfo(mContext,
                         String.format(notificationTitleFormat, account.name),
-                        message, PendingIntent.getActivity(
-                        mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT));
-                installNotification(notificationId, n);
+                        message, PendingIntent.getActivityAsUser(
+                        mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT,
+                        null, user));
+                installNotification(notificationId, n, user);
             }
         } finally {
             restoreCallingIdentity(identityToken);
         }
     }
 
-    protected void installNotification(final int notificationId, final Notification n) {
+    protected void installNotification(final int notificationId, final Notification n,
+            UserHandle user) {
         ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
-                .notify(notificationId, n);
+                .notifyAsUser(null, notificationId, n, user);
     }
 
-    protected void cancelNotification(int id) {
+    protected void cancelNotification(int id, UserHandle user) {
         long identityToken = clearCallingIdentity();
         try {
             ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
-                .cancel(id);
+                .cancelAsUser(null, id, user);
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -2141,11 +2193,21 @@
         throw new SecurityException(msg);
     }
 
-    private boolean inSystemImage(int callerUid) {
-        String[] packages = mPackageManager.getPackagesForUid(callerUid);
+    private boolean inSystemImage(int callingUid) {
+        final int callingUserId = UserHandle.getUserId(callingUid);
+
+        final PackageManager userPackageManager;
+        try {
+            userPackageManager = mContext.createPackageContextAsUser(
+                    "android", 0, new UserHandle(callingUserId)).getPackageManager();
+        } catch (NameNotFoundException e) {
+            return false;
+        }
+
+        String[] packages = userPackageManager.getPackagesForUid(callingUid);
         for (String name : packages) {
             try {
-                PackageInfo packageInfo = mPackageManager.getPackageInfo(name, 0 /* flags */);
+                PackageInfo packageInfo = userPackageManager.getPackageInfo(name, 0 /* flags */);
                 if (packageInfo != null
                         && (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                     return true;
@@ -2173,8 +2235,9 @@
     }
 
     private boolean hasAuthenticatorUid(String accountType, int callingUid) {
+        final int callingUserId = UserHandle.getUserId(callingUid);
         for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
-                mAuthenticatorCache.getAllServices()) {
+                mAuthenticatorCache.getAllServices(callingUserId)) {
             if (serviceInfo.type.type.equals(accountType)) {
                 return (serviceInfo.uid == callingUid) ||
                         (mPackageManager.checkSignatures(serviceInfo.uid, callingUid)
@@ -2265,7 +2328,7 @@
             Log.e(TAG, "grantAppPermission: called with invalid arguments", new Exception());
             return;
         }
-        UserAccounts accounts = getUserAccounts(UserId.getUserId(uid));
+        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
         synchronized (accounts.cacheLock) {
             final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
             db.beginTransaction();
@@ -2282,7 +2345,8 @@
             } finally {
                 db.endTransaction();
             }
-            cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid));
+            cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid),
+                    new UserHandle(accounts.userId));
         }
     }
 
@@ -2299,7 +2363,7 @@
             Log.e(TAG, "revokeAppPermission: called with invalid arguments", new Exception());
             return;
         }
-        UserAccounts accounts = getUserAccounts(UserId.getUserId(uid));
+        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
         synchronized (accounts.cacheLock) {
             final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
             db.beginTransaction();
@@ -2316,7 +2380,8 @@
             } finally {
                 db.endTransaction();
             }
-            cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid));
+            cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid),
+                    new UserHandle(accounts.userId));
         }
     }
 
diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
index 6b3b7fd..5358bc7 100644
--- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java
+++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
@@ -15,6 +15,8 @@
  */
 package android.accounts;
 
+import com.google.android.collect.Sets;
+
 import android.app.Activity;
 import android.content.Intent;
 import android.os.Bundle;
@@ -105,6 +107,13 @@
 
     private static final int SELECTED_ITEM_NONE = -1;
 
+    private Set<Account> mSetOfAllowableAccounts;
+    private Set<String> mSetOfRelevantAccountTypes;
+    private String mSelectedAccountName = null;
+    private boolean mSelectedAddNewAccount = false;
+    private boolean mAlwaysPromptForAccount = false;
+    private String mDescriptionOverride;
+
     private ArrayList<Account> mAccounts;
     private int mPendingRequest = REQUEST_NULL;
     private Parcelable[] mExistingAccounts = null;
@@ -120,22 +129,18 @@
         }
 
         // save some items we use frequently
-        final AccountManager accountManager = AccountManager.get(this);
         final Intent intent = getIntent();
 
-        String selectedAccountName = null;
-        boolean selectedAddNewAccount = false;
-
         if (savedInstanceState != null) {
             mPendingRequest = savedInstanceState.getInt(KEY_INSTANCE_STATE_PENDING_REQUEST);
             mExistingAccounts =
                     savedInstanceState.getParcelableArray(KEY_INSTANCE_STATE_EXISTING_ACCOUNTS);
 
             // Makes sure that any user selection is preserved across orientation changes.
-            selectedAccountName = savedInstanceState.getString(
+            mSelectedAccountName = savedInstanceState.getString(
                     KEY_INSTANCE_STATE_SELECTED_ACCOUNT_NAME);
 
-            selectedAddNewAccount = savedInstanceState.getBoolean(
+            mSelectedAddNewAccount = savedInstanceState.getBoolean(
                     KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT, false);
         } else {
             mPendingRequest = REQUEST_NULL;
@@ -144,85 +149,38 @@
             // show is as pre-selected.
             Account selectedAccount = (Account) intent.getParcelableExtra(EXTRA_SELECTED_ACCOUNT);
             if (selectedAccount != null) {
-                selectedAccountName = selectedAccount.name;
+                mSelectedAccountName = selectedAccount.name;
             }
         }
 
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "selected account name is " + selectedAccountName);
+            Log.v(TAG, "selected account name is " + mSelectedAccountName);
         }
 
-        // build an efficiently queryable map of account types to authenticator descriptions
-        final HashMap<String, AuthenticatorDescription> typeToAuthDescription =
-                new HashMap<String, AuthenticatorDescription>();
-        for(AuthenticatorDescription desc : accountManager.getAuthenticatorTypes()) {
-            typeToAuthDescription.put(desc.type, desc);
-        }
 
-        // Read the validAccounts, if present, and add them to the setOfAllowableAccounts
-        Set<Account> setOfAllowableAccounts = null;
-        final ArrayList<Parcelable> validAccounts =
-                intent.getParcelableArrayListExtra(EXTRA_ALLOWABLE_ACCOUNTS_ARRAYLIST);
-        if (validAccounts != null) {
-            setOfAllowableAccounts = new HashSet<Account>(validAccounts.size());
-            for (Parcelable parcelable : validAccounts) {
-                setOfAllowableAccounts.add((Account)parcelable);
-            }
-        }
+        mSetOfAllowableAccounts = getAllowableAccountSet(intent);
+        mSetOfRelevantAccountTypes = getReleventAccountTypes(intent);
+        mAlwaysPromptForAccount = intent.getBooleanExtra(EXTRA_ALWAYS_PROMPT_FOR_ACCOUNT, false);
+        mDescriptionOverride = intent.getStringExtra(EXTRA_DESCRIPTION_TEXT_OVERRIDE);
+    }
 
-        // An account type is relevant iff it is allowed by the caller and supported by the account
-        // manager.
-        Set<String> setOfRelevantAccountTypes = null;
-        final String[] allowedAccountTypes =
-                intent.getStringArrayExtra(EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY);
-        if (allowedAccountTypes != null) {
+    @Override
+    protected void onResume() {
+        super.onResume();
+        final AccountManager accountManager = AccountManager.get(this);
 
-            setOfRelevantAccountTypes = new HashSet<String>(allowedAccountTypes.length);
-            Set<String> setOfAllowedAccountTypes = new HashSet<String>(allowedAccountTypes.length);
-            for (String type : allowedAccountTypes) {
-                setOfAllowedAccountTypes.add(type);
-            }
+        mAccounts = getAcceptableAccountChoices(accountManager);
 
-            AuthenticatorDescription[] descs = AccountManager.get(this).getAuthenticatorTypes();
-            Set<String> supportedAccountTypes = new HashSet<String>(descs.length);
-            for (AuthenticatorDescription desc : descs) {
-                supportedAccountTypes.add(desc.type);
-            }
-
-            for (String acctType : setOfAllowedAccountTypes) {
-                if (supportedAccountTypes.contains(acctType)) {
-                    setOfRelevantAccountTypes.add(acctType);
-                }
-            }
-        }
-
-        // Create a list of AccountInfo objects for each account that is allowable. Filter out
-        // accounts that don't match the allowable types, if provided, or that don't match the
-        // allowable accounts, if provided.
-        final Account[] accounts = accountManager.getAccounts();
-        mAccounts = new ArrayList<Account>(accounts.length);
-        mSelectedItemIndex = SELECTED_ITEM_NONE;
-        for (Account account : accounts) {
-            if (setOfAllowableAccounts != null
-                    && !setOfAllowableAccounts.contains(account)) {
-                continue;
-            }
-            if (setOfRelevantAccountTypes != null
-                    && !setOfRelevantAccountTypes.contains(account.type)) {
-                continue;
-            }
-            if (account.name.equals(selectedAccountName)) {
-                mSelectedItemIndex = mAccounts.size();
-            }
-            mAccounts.add(account);
-        }
-
+        // In cases where the activity does not need to show an account picker, cut the chase
+        // and return the result directly. Eg:
+        // Single account -> select it directly
+        // No account -> launch add account activity directly
         if (mPendingRequest == REQUEST_NULL) {
             // If there are no relevant accounts and only one relevant account type go directly to
             // add account. Otherwise let the user choose.
             if (mAccounts.isEmpty()) {
-                if (setOfRelevantAccountTypes.size() == 1) {
-                    runAddAccountForAuthenticator(setOfRelevantAccountTypes.iterator().next());
+                if (mSetOfRelevantAccountTypes.size() == 1) {
+                    runAddAccountForAuthenticator(mSetOfRelevantAccountTypes.iterator().next());
                 } else {
                     startChooseAccountTypeActivity();
                 }
@@ -230,61 +188,22 @@
             }
 
             // if there is only one allowable account return it
-            if (!intent.getBooleanExtra(EXTRA_ALWAYS_PROMPT_FOR_ACCOUNT, false)
-                    && mAccounts.size() == 1) {
+            if (!mAlwaysPromptForAccount && mAccounts.size() == 1) {
                 Account account = mAccounts.get(0);
                 setResultAndFinish(account.name, account.type);
                 return;
             }
         }
 
+        String[] listItems = getListOfDisplayableOptions(mAccounts);
+        mSelectedItemIndex = getItemIndexToSelect(
+            mAccounts, mSelectedAccountName, mSelectedAddNewAccount);
+
         // Cannot set content view until we know that mPendingRequest is not null, otherwise
         // would cause screen flicker.
         setContentView(R.layout.choose_type_and_account);
-
-        // Override the description text if supplied
-        final String descriptionOverride =
-                intent.getStringExtra(EXTRA_DESCRIPTION_TEXT_OVERRIDE);
-        TextView descriptionView = (TextView) findViewById(R.id.description);
-        if (!TextUtils.isEmpty(descriptionOverride)) {
-            descriptionView.setText(descriptionOverride);
-        } else {
-            descriptionView.setVisibility(View.GONE);
-        }
-
-        // List of options includes all accounts found together with "Add new account" as the
-        // last item in the list.
-        String[] listItems = new String[mAccounts.size() + 1];
-        for (int i = 0; i < mAccounts.size(); i++) {
-            listItems[i] = mAccounts.get(i).name;
-        }
-        listItems[mAccounts.size()] = getResources().getString(
-                R.string.add_account_button_label);
-
-        ListView list = (ListView) findViewById(android.R.id.list);
-        list.setAdapter(new ArrayAdapter<String>(this,
-                android.R.layout.simple_list_item_single_choice, listItems));
-        list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
-        list.setItemsCanFocus(false);
-        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
-            @Override
-            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
-                mSelectedItemIndex = position;
-                mOkButton.setEnabled(true);
-            }
-        });
-
-        // If "Add account" option was previously selected by user, preserve it across
-        // orientation changes.
-        if (selectedAddNewAccount) {
-            mSelectedItemIndex = mAccounts.size();
-        }
-        if (mSelectedItemIndex != SELECTED_ITEM_NONE) {
-            list.setItemChecked(mSelectedItemIndex, true);
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "List item " + mSelectedItemIndex + " should be selected");
-            }
-        }
+        overrideDescriptionIfSupplied(mDescriptionOverride);
+        populateUIAccountList(listItems);
 
         // Only enable "OK" button if something has been selected.
         mOkButton = (Button) findViewById(android.R.id.button2);
@@ -480,4 +399,137 @@
         startActivityForResult(intent, REQUEST_CHOOSE_TYPE);
         mPendingRequest = REQUEST_CHOOSE_TYPE;
     }
+
+    /**
+     * @return a value between 0 (inclusive) and accounts.size() (inclusive) or SELECTED_ITEM_NONE.
+     *      An index value of accounts.size() indicates 'Add account' option.
+     */
+    private int getItemIndexToSelect(ArrayList<Account> accounts, String selectedAccountName,
+        boolean selectedAddNewAccount) {
+      // If "Add account" option was previously selected by user, preserve it across
+      // orientation changes.
+      if (selectedAddNewAccount) {
+          return accounts.size();
+      }
+      // search for the selected account name if present
+      for (int i = 0; i < accounts.size(); i++) {
+        if (accounts.get(i).name.equals(selectedAccountName)) {
+          return i;
+        }
+      }
+      // no account selected.
+      return SELECTED_ITEM_NONE;
+    }
+
+    private String[] getListOfDisplayableOptions(ArrayList<Account> accounts) {
+      // List of options includes all accounts found together with "Add new account" as the
+      // last item in the list.
+      String[] listItems = new String[accounts.size() + 1];
+      for (int i = 0; i < accounts.size(); i++) {
+          listItems[i] = accounts.get(i).name;
+      }
+      listItems[accounts.size()] = getResources().getString(
+              R.string.add_account_button_label);
+      return listItems;
+    }
+
+    /**
+     * Create a list of Account objects for each account that is acceptable. Filter out
+     * accounts that don't match the allowable types, if provided, or that don't match the
+     * allowable accounts, if provided.
+     */
+    private ArrayList<Account> getAcceptableAccountChoices(AccountManager accountManager) {
+      final Account[] accounts = accountManager.getAccounts();
+      ArrayList<Account> accountsToPopulate = new ArrayList<Account>(accounts.length);
+      for (Account account : accounts) {
+          if (mSetOfAllowableAccounts != null
+                  && !mSetOfAllowableAccounts.contains(account)) {
+              continue;
+          }
+          if (mSetOfRelevantAccountTypes != null
+                  && !mSetOfRelevantAccountTypes.contains(account.type)) {
+              continue;
+          }
+          accountsToPopulate.add(account);
+      }
+      return accountsToPopulate;
+    }
+
+    /**
+     * Return a set of account types speficied by the intent as well as supported by the
+     * AccountManager.
+     */
+    private Set<String> getReleventAccountTypes(final Intent intent) {
+      // An account type is relevant iff it is allowed by the caller and supported by the account
+      // manager.
+      Set<String> setOfRelevantAccountTypes = null;
+      final String[] allowedAccountTypes =
+              intent.getStringArrayExtra(EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY);
+      if (allowedAccountTypes != null) {
+          setOfRelevantAccountTypes = Sets.newHashSet(allowedAccountTypes);
+          AuthenticatorDescription[] descs = AccountManager.get(this).getAuthenticatorTypes();
+          Set<String> supportedAccountTypes = new HashSet<String>(descs.length);
+          for (AuthenticatorDescription desc : descs) {
+              supportedAccountTypes.add(desc.type);
+          }
+          setOfRelevantAccountTypes.retainAll(supportedAccountTypes);
+      }
+      return setOfRelevantAccountTypes;
+    }
+
+    /**
+     * Returns a set of whitelisted accounts given by the intent or null if none specified by the
+     * intent.
+     */
+    private Set<Account> getAllowableAccountSet(final Intent intent) {
+      Set<Account> setOfAllowableAccounts = null;
+      final ArrayList<Parcelable> validAccounts =
+              intent.getParcelableArrayListExtra(EXTRA_ALLOWABLE_ACCOUNTS_ARRAYLIST);
+      if (validAccounts != null) {
+          setOfAllowableAccounts = new HashSet<Account>(validAccounts.size());
+          for (Parcelable parcelable : validAccounts) {
+              setOfAllowableAccounts.add((Account)parcelable);
+          }
+      }
+      return setOfAllowableAccounts;
+    }
+
+    /**
+     * Overrides the description text view for the picker activity if specified by the intent.
+     * If not specified then makes the description invisible.
+     */
+    private void overrideDescriptionIfSupplied(String descriptionOverride) {
+      TextView descriptionView = (TextView) findViewById(R.id.description);
+      if (!TextUtils.isEmpty(descriptionOverride)) {
+          descriptionView.setText(descriptionOverride);
+      } else {
+          descriptionView.setVisibility(View.GONE);
+      }
+    }
+
+    /**
+     * Populates the UI ListView with the given list of items and selects an item
+     * based on {@code mSelectedItemIndex} member variable.
+     */
+    private final void populateUIAccountList(String[] listItems) {
+      ListView list = (ListView) findViewById(android.R.id.list);
+      list.setAdapter(new ArrayAdapter<String>(this,
+              android.R.layout.simple_list_item_single_choice, listItems));
+      list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+      list.setItemsCanFocus(false);
+      list.setOnItemClickListener(
+              new AdapterView.OnItemClickListener() {
+                  @Override
+                  public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
+                      mSelectedItemIndex = position;
+                      mOkButton.setEnabled(true);
+                  }
+              });
+      if (mSelectedItemIndex != SELECTED_ITEM_NONE) {
+          list.setItemChecked(mSelectedItemIndex, true);
+          if (Log.isLoggable(TAG, Log.VERBOSE)) {
+              Log.v(TAG, "List item " + mSelectedItemIndex + " should be selected");
+          }
+      }
+    }
 }
diff --git a/core/java/android/accounts/IAccountAuthenticatorCache.java b/core/java/android/accounts/IAccountAuthenticatorCache.java
index 20dd585..06c2106 100644
--- a/core/java/android/accounts/IAccountAuthenticatorCache.java
+++ b/core/java/android/accounts/IAccountAuthenticatorCache.java
@@ -39,18 +39,19 @@
      * matches the account type or null if none is present
      */
     RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> getServiceInfo(
-            AuthenticatorDescription type);
+            AuthenticatorDescription type, int userId);
 
     /**
      * @return A copy of a Collection of all the current Authenticators.
      */
-    Collection<RegisteredServicesCache.ServiceInfo<AuthenticatorDescription>> getAllServices();
+    Collection<RegisteredServicesCache.ServiceInfo<AuthenticatorDescription>> getAllServices(
+            int userId);
 
     /**
      * Dumps the state of the cache. See
      * {@link android.os.Binder#dump(java.io.FileDescriptor, java.io.PrintWriter, String[])}
      */
-    void dump(FileDescriptor fd, PrintWriter fout, String[] args);
+    void dump(FileDescriptor fd, PrintWriter fout, String[] args, int userId);
 
     /**
      * Sets a listener that will be notified whenever the authenticator set changes
@@ -61,8 +62,5 @@
     void setListener(RegisteredServicesCacheListener<AuthenticatorDescription> listener,
             Handler handler);
 
-    /**
-     * Refreshes the authenticator cache.
-     */
-    void generateServicesMap();
-}
\ No newline at end of file
+    void invalidateCache(int userId);
+}
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index 6007321..dbb4924 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -31,6 +31,7 @@
     String getUserData(in Account account, String key);
     AuthenticatorDescription[] getAuthenticatorTypes();
     Account[] getAccounts(String accountType);
+    Account[] getAccountsAsUser(String accountType, int userId);
     void hasFeatures(in IAccountManagerResponse response, in Account account, in String[] features);
     void getAccountsByFeatures(in IAccountManagerResponse response, String accountType, in String[] features);
     boolean addAccount(in Account account, String password, in Bundle extras);
@@ -53,8 +54,8 @@
         String authTokenType, boolean expectActivityLaunch, in Bundle options);
     void editProperties(in IAccountManagerResponse response, String accountType,
         boolean expectActivityLaunch);
-    void confirmCredentials(in IAccountManagerResponse response, in Account account,
-        in Bundle options, boolean expectActivityLaunch);
+    void confirmCredentialsAsUser(in IAccountManagerResponse response, in Account account,
+        in Bundle options, boolean expectActivityLaunch, int userId);
     void getAuthTokenLabel(in IAccountManagerResponse response, String accountType,
         String authTokenType);
 }
diff --git a/core/java/android/animation/ArgbEvaluator.java b/core/java/android/animation/ArgbEvaluator.java
index c3875be..717a3d9 100644
--- a/core/java/android/animation/ArgbEvaluator.java
+++ b/core/java/android/animation/ArgbEvaluator.java
@@ -40,13 +40,13 @@
      */
     public Object evaluate(float fraction, Object startValue, Object endValue) {
         int startInt = (Integer) startValue;
-        int startA = (startInt >> 24);
+        int startA = (startInt >> 24) & 0xff;
         int startR = (startInt >> 16) & 0xff;
         int startG = (startInt >> 8) & 0xff;
         int startB = startInt & 0xff;
 
         int endInt = (Integer) endValue;
-        int endA = (endInt >> 24);
+        int endA = (endInt >> 24) & 0xff;
         int endR = (endInt >> 16) & 0xff;
         int endG = (endInt >> 8) & 0xff;
         int endB = endInt & 0xff;
diff --git a/core/java/android/animation/Keyframe.java b/core/java/android/animation/Keyframe.java
index e98719a..dc8538f 100644
--- a/core/java/android/animation/Keyframe.java
+++ b/core/java/android/animation/Keyframe.java
@@ -261,7 +261,7 @@
 
         @Override
         public ObjectKeyframe clone() {
-            ObjectKeyframe kfClone = new ObjectKeyframe(getFraction(), mValue);
+            ObjectKeyframe kfClone = new ObjectKeyframe(getFraction(), mHasValue ? mValue : null);
             kfClone.setInterpolator(getInterpolator());
             return kfClone;
         }
@@ -306,7 +306,9 @@
 
         @Override
         public IntKeyframe clone() {
-            IntKeyframe kfClone = new IntKeyframe(getFraction(), mValue);
+            IntKeyframe kfClone = mHasValue ?
+                    new IntKeyframe(getFraction(), mValue) :
+                    new IntKeyframe(getFraction());
             kfClone.setInterpolator(getInterpolator());
             return kfClone;
         }
@@ -350,7 +352,9 @@
 
         @Override
         public FloatKeyframe clone() {
-            FloatKeyframe kfClone = new FloatKeyframe(getFraction(), mValue);
+            FloatKeyframe kfClone = mHasValue ?
+                    new FloatKeyframe(getFraction(), mValue) :
+                    new FloatKeyframe(getFraction());
             kfClone.setInterpolator(getInterpolator());
             return kfClone;
         }
diff --git a/core/java/android/animation/TimeAnimator.java b/core/java/android/animation/TimeAnimator.java
index 088d20d..f9aa00e 100644
--- a/core/java/android/animation/TimeAnimator.java
+++ b/core/java/android/animation/TimeAnimator.java
@@ -13,6 +13,12 @@
     private long mPreviousTime = -1;
 
     @Override
+    public void start() {
+        mPreviousTime = -1;
+        super.start();
+    }
+
+    @Override
     boolean animationFrame(long currentTime) {
         if (mListener != null) {
             long totalTime = currentTime - mStartTime;
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index f3a442a..f7460c4 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -232,6 +232,13 @@
     }
 
     /**
+     * @hide
+     */
+    public static float getDurationScale() {
+        return sDurationScale;
+    }
+
+    /**
      * Creates a new ValueAnimator object. This default constructor is primarily for
      * use internally; the factory methods which take parameters are more generally
      * useful.
@@ -529,6 +536,9 @@
         // The per-thread list of all active animations
         private final ArrayList<ValueAnimator> mAnimations = new ArrayList<ValueAnimator>();
 
+        // Used in doAnimationFrame() to avoid concurrent modifications of mAnimations
+        private final ArrayList<ValueAnimator> mTmpAnimations = new ArrayList<ValueAnimator>();
+
         // The per-thread set of animations to be started on the next animation frame
         private final ArrayList<ValueAnimator> mPendingAnimations = new ArrayList<ValueAnimator>();
 
@@ -598,28 +608,18 @@
             // Now process all active animations. The return value from animationFrame()
             // tells the handler whether it should now be ended
             int numAnims = mAnimations.size();
-            int i = 0;
-            while (i < numAnims) {
-                ValueAnimator anim = mAnimations.get(i);
-                if (anim.doAnimationFrame(frameTime)) {
+            for (int i = 0; i < numAnims; ++i) {
+                mTmpAnimations.add(mAnimations.get(i));
+            }
+            for (int i = 0; i < numAnims; ++i) {
+                ValueAnimator anim = mTmpAnimations.get(i);
+                if (mAnimations.contains(anim) && anim.doAnimationFrame(frameTime)) {
                     mEndingAnims.add(anim);
                 }
-                if (mAnimations.size() == numAnims) {
-                    ++i;
-                } else {
-                    // An animation might be canceled or ended by client code
-                    // during the animation frame. Check to see if this happened by
-                    // seeing whether the current index is the same as it was before
-                    // calling animationFrame(). Another approach would be to copy
-                    // animations to a temporary list and process that list instead,
-                    // but that entails garbage and processing overhead that would
-                    // be nice to avoid.
-                    --numAnims;
-                    mEndingAnims.remove(anim);
-                }
             }
+            mTmpAnimations.clear();
             if (mEndingAnims.size() > 0) {
-                for (i = 0; i < mEndingAnims.size(); ++i) {
+                for (int i = 0; i < mEndingAnims.size(); ++i) {
                     mEndingAnims.get(i).endAnimation(this);
                 }
                 mEndingAnims.clear();
@@ -958,13 +958,7 @@
         } else if (!mInitialized) {
             initAnimation();
         }
-        // The final value set on the target varies, depending on whether the animation
-        // was supposed to repeat an odd number of times
-        if (mRepeatCount > 0 && (mRepeatCount & 0x01) == 1) {
-            animateValue(0f);
-        } else {
-            animateValue(1f);
-        }
+        animateValue(mPlayingBackwards ? 0f : 1f);
         endAnimation(handler);
     }
 
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index cff16ff..23377908 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -918,6 +918,8 @@
             @ViewDebug.IntToString(from = Gravity.BOTTOM,            to = "BOTTOM"),
             @ViewDebug.IntToString(from = Gravity.LEFT,              to = "LEFT"),
             @ViewDebug.IntToString(from = Gravity.RIGHT,             to = "RIGHT"),
+            @ViewDebug.IntToString(from = Gravity.START,             to = "START"),
+            @ViewDebug.IntToString(from = Gravity.END,               to = "END"),
             @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL,   to = "CENTER_VERTICAL"),
             @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL,     to = "FILL_VERTICAL"),
             @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"),
@@ -925,7 +927,7 @@
             @ViewDebug.IntToString(from = Gravity.CENTER,            to = "CENTER"),
             @ViewDebug.IntToString(from = Gravity.FILL,              to = "FILL")
         })
-        public int gravity = -1;
+        public int gravity = Gravity.NO_GRAVITY;
 
         public LayoutParams(Context c, AttributeSet attrs) {
             super(c, attrs);
@@ -933,13 +935,14 @@
             TypedArray a = c.obtainStyledAttributes(attrs,
                     com.android.internal.R.styleable.ActionBar_LayoutParams);
             gravity = a.getInt(
-                    com.android.internal.R.styleable.ActionBar_LayoutParams_layout_gravity, -1);
+                    com.android.internal.R.styleable.ActionBar_LayoutParams_layout_gravity,
+                    Gravity.NO_GRAVITY);
             a.recycle();
         }
 
         public LayoutParams(int width, int height) {
             super(width, height);
-            this.gravity = Gravity.CENTER_VERTICAL | Gravity.LEFT;
+            this.gravity = Gravity.CENTER_VERTICAL | Gravity.START;
         }
 
         public LayoutParams(int width, int height, int gravity) {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f20fd33..5dc9da2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -48,6 +48,7 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.StrictMode;
+import android.os.UserHandle;
 import android.text.Selection;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
@@ -74,7 +75,7 @@
 import android.view.ViewManager;
 import android.view.Window;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.AdapterView;
 
@@ -652,8 +653,9 @@
     /** Start of user-defined activity results. */
     public static final int RESULT_FIRST_USER   = 1;
 
+    static final String FRAGMENTS_TAG = "android:fragments";
+
     private static final String WINDOW_HIERARCHY_TAG = "android:viewHierarchyState";
-    private static final String FRAGMENTS_TAG = "android:fragments";
     private static final String SAVED_DIALOG_IDS_KEY = "android:savedDialogIds";
     private static final String SAVED_DIALOGS_TAG = "android:savedDialogs";
     private static final String SAVED_DIALOG_KEY_PREFIX = "android:dialog_";
@@ -683,6 +685,7 @@
     private boolean mStopped;
     boolean mFinished;
     boolean mStartedActivity;
+    private boolean mDestroyed;
     /** true if the activity is going through a transient pause */
     /*package*/ boolean mTemporaryPause = false;
     /** true if the activity is being destroyed in order to recreate it with a new configuration */
@@ -696,7 +699,7 @@
         Object activity;
         HashMap<String, Object> children;
         ArrayList<Fragment> fragments;
-        SparseArray<LoaderManagerImpl> loaders;
+        HashMap<String, LoaderManagerImpl> loaders;
     }
     /* package */ NonConfigurationInstances mLastNonConfigurationInstances;
     
@@ -714,8 +717,14 @@
     private int mTitleColor = 0;
 
     final FragmentManagerImpl mFragments = new FragmentManagerImpl();
+    final FragmentContainer mContainer = new FragmentContainer() {
+        @Override
+        public View findViewById(int id) {
+            return Activity.this.findViewById(id);
+        }
+    };
     
-    SparseArray<LoaderManagerImpl> mAllLoaderManagers;
+    HashMap<String, LoaderManagerImpl> mAllLoaderManagers;
     LoaderManagerImpl mLoaderManager;
     
     private static final class ManagedCursor {
@@ -743,6 +752,7 @@
     
     protected static final int[] FOCUSED_STATE_SET = {com.android.internal.R.attr.state_focused};
 
+    @SuppressWarnings("unused")
     private final Object mInstanceTracker = StrictMode.trackActivity(this);
 
     private Thread mUiThread;
@@ -807,19 +817,19 @@
             return mLoaderManager;
         }
         mCheckedForLoaderManager = true;
-        mLoaderManager = getLoaderManager(-1, mLoadersStarted, true);
+        mLoaderManager = getLoaderManager(null, mLoadersStarted, true);
         return mLoaderManager;
     }
     
-    LoaderManagerImpl getLoaderManager(int index, boolean started, boolean create) {
+    LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {
         if (mAllLoaderManagers == null) {
-            mAllLoaderManagers = new SparseArray<LoaderManagerImpl>();
+            mAllLoaderManagers = new HashMap<String, LoaderManagerImpl>();
         }
-        LoaderManagerImpl lm = mAllLoaderManagers.get(index);
+        LoaderManagerImpl lm = mAllLoaderManagers.get(who);
         if (lm == null) {
             if (create) {
-                lm = new LoaderManagerImpl(this, started);
-                mAllLoaderManagers.put(index, lm);
+                lm = new LoaderManagerImpl(who, this, started);
+                mAllLoaderManagers.put(who, lm);
             }
         } else {
             lm.updateActivity(this);
@@ -1024,7 +1034,7 @@
             if (mLoaderManager != null) {
                 mLoaderManager.doStart();
             } else if (!mCheckedForLoaderManager) {
-                mLoaderManager = getLoaderManager(-1, mLoadersStarted, false);
+                mLoaderManager = getLoaderManager(null, mLoadersStarted, false);
             }
             mCheckedForLoaderManager = true;
         }
@@ -1600,13 +1610,17 @@
         if (mAllLoaderManagers != null) {
             // prune out any loader managers that were already stopped and so
             // have nothing useful to retain.
-            for (int i=mAllLoaderManagers.size()-1; i>=0; i--) {
-                LoaderManagerImpl lm = mAllLoaderManagers.valueAt(i);
-                if (lm.mRetaining) {
-                    retainLoaders = true;
-                } else {
-                    lm.doDestroy();
-                    mAllLoaderManagers.removeAt(i);
+            LoaderManagerImpl loaders[] = new LoaderManagerImpl[mAllLoaderManagers.size()];
+            mAllLoaderManagers.values().toArray(loaders);
+            if (loaders != null) {
+                for (int i=0; i<loaders.length; i++) {
+                    LoaderManagerImpl lm = loaders[i];
+                    if (lm.mRetaining) {
+                        retainLoaders = true;
+                    } else {
+                        lm.doDestroy();
+                        mAllLoaderManagers.remove(lm.mWho);
+                    }
                 }
             }
         }
@@ -1642,13 +1656,13 @@
         return mFragments;
     }
 
-    void invalidateFragmentIndex(int index) {
+    void invalidateFragment(String who) {
         //Log.v(TAG, "invalidateFragmentIndex: index=" + index);
         if (mAllLoaderManagers != null) {
-            LoaderManagerImpl lm = mAllLoaderManagers.get(index);
+            LoaderManagerImpl lm = mAllLoaderManagers.get(who);
             if (lm != null && !lm.mRetaining) {
                 lm.doDestroy();
-                mAllLoaderManagers.remove(index);
+                mAllLoaderManagers.remove(who);
             }
         }
     }
@@ -2708,7 +2722,12 @@
         // metadata is available.
         Intent upIntent = getParentActivityIntent();
         if (upIntent != null) {
-            if (shouldUpRecreateTask(upIntent)) {
+            if (mActivityInfo.taskAffinity == null) {
+                // Activities with a null affinity are special; they really shouldn't
+                // specify a parent activity intent in the first place. Just finish
+                // the current activity and call it a day.
+                finish();
+            } else if (shouldUpRecreateTask(upIntent)) {
                 TaskStackBuilder b = TaskStackBuilder.create(this);
                 onCreateNavigateUpTaskStack(b);
                 onPrepareNavigateUpTaskStack(b);
@@ -3379,6 +3398,31 @@
     }
 
     /**
+     * @hide Implement to provide correct calling token.
+     */
+    public void startActivityAsUser(Intent intent, UserHandle user) {
+        startActivityAsUser(intent, null, user);
+    }
+
+    /**
+     * @hide Implement to provide correct calling token.
+     */
+    public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) {
+        if (mParent != null) {
+            throw new RuntimeException("Called be called from a child");
+        }
+        Instrumentation.ActivityResult ar =
+                mInstrumentation.execStartActivity(
+                        this, mMainThread.getApplicationThread(), mToken, this,
+                        intent, -1, options, user);
+        if (ar != null) {
+            mMainThread.sendActivityResult(
+                mToken, mEmbeddedID, -1, ar.getResultCode(),
+                ar.getResultData());
+        }
+    }
+
+    /**
      * Same as calling {@link #startIntentSenderForResult(IntentSender, int,
      * Intent, int, int, int, Bundle)} with no options.
      *
@@ -4046,6 +4090,14 @@
     }
 
     /**
+     * Returns true if the final {@link #onDestroy()} call has been made
+     * on the Activity, so this instance is now dead.
+     */
+    public boolean isDestroyed() {
+        return mDestroyed;
+    }
+
+    /**
      * Check to see whether this activity is in the process of being destroyed in order to be
      * recreated with a new configuration. This is often used in
      * {@link #onStop} to determine whether the state needs to be cleaned up or will be passed
@@ -4247,7 +4299,8 @@
                 ActivityManagerNative.getDefault().getIntentSender(
                         ActivityManager.INTENT_SENDER_ACTIVITY_RESULT, packageName,
                         mParent == null ? mToken : mParent.mToken,
-                        mEmbeddedID, requestCode, new Intent[] { data }, null, flags, null);
+                        mEmbeddedID, requestCode, new Intent[] { data }, null, flags, null,
+                        UserHandle.myUserId());
             return target != null ? new PendingIntent(target) : null;
         } catch (RemoteException e) {
             // Empty
@@ -4707,6 +4760,10 @@
      * @param args additional arguments to the dump request.
      */
     public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        dumpInner(prefix, fd, writer, args);
+    }
+
+    void dumpInner(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
         writer.print(prefix); writer.print("Local Activity ");
                 writer.print(Integer.toHexString(System.identityHashCode(this)));
                 writer.println(" State:");
@@ -4728,6 +4785,29 @@
             mLoaderManager.dump(prefix + "  ", fd, writer, args);
         }
         mFragments.dump(prefix, fd, writer, args);
+        writer.print(prefix); writer.println("View Hierarchy:");
+        dumpViewHierarchy(prefix + "  ", writer, getWindow().getDecorView());
+    }
+
+    private void dumpViewHierarchy(String prefix, PrintWriter writer, View view) {
+        writer.print(prefix);
+        if (view == null) {
+            writer.println("null");
+            return;
+        }
+        writer.println(view.toString());
+        if (!(view instanceof ViewGroup)) {
+            return;
+        }
+        ViewGroup grp = (ViewGroup)view;
+        final int N = grp.getChildCount();
+        if (N <= 0) {
+            return;
+        }
+        prefix = prefix + "  ";
+        for (int i=0; i<N; i++) {
+            dumpViewHierarchy(prefix, writer, grp.getChildAt(i));
+        }
     }
 
     /**
@@ -4939,7 +5019,21 @@
         if (TextUtils.isEmpty(parentName)) {
             return null;
         }
-        return new Intent().setClassName(this, parentName);
+
+        // If the parent itself has no parent, generate a main activity intent.
+        final ComponentName target = new ComponentName(this, parentName);
+        try {
+            final ActivityInfo parentInfo = getPackageManager().getActivityInfo(target, 0);
+            final String parentActivity = parentInfo.parentActivityName;
+            final Intent parentIntent = parentActivity == null
+                    ? Intent.makeMainActivity(target)
+                    : new Intent().setComponent(target);
+            return parentIntent;
+        } catch (NameNotFoundException e) {
+            Log.e(TAG, "getParentActivityIntent: bad parentActivityName '" + parentName +
+                    "' in manifest");
+            return null;
+        }
     }
 
     // ------------------ Internal API ------------------
@@ -4964,7 +5058,7 @@
             Configuration config) {
         attachBaseContext(context);
 
-        mFragments.attachActivity(this);
+        mFragments.attachActivity(this, mContainer, null);
         
         mWindow = PolicyManager.makeNewWindow(this);
         mWindow.setCallback(this);
@@ -4990,7 +5084,9 @@
         mEmbeddedID = id;
         mLastNonConfigurationInstances = lastNonConfigurationInstances;
 
-        mWindow.setWindowManager(null, mToken, mComponent.flattenToString(),
+        mWindow.setWindowManager(
+                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
+                mToken, mComponent.flattenToString(),
                 (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
         if (mParent != null) {
             mWindow.setContainer(mParent.getWindow());
@@ -5023,10 +5119,14 @@
         }
         mFragments.dispatchStart();
         if (mAllLoaderManagers != null) {
-            for (int i=mAllLoaderManagers.size()-1; i>=0; i--) {
-                LoaderManagerImpl lm = mAllLoaderManagers.valueAt(i);
-                lm.finishRetain();
-                lm.doReportStart();
+            LoaderManagerImpl loaders[] = new LoaderManagerImpl[mAllLoaderManagers.size()];
+            mAllLoaderManagers.values().toArray(loaders);
+            if (loaders != null) {
+                for (int i=0; i<loaders.length; i++) {
+                    LoaderManagerImpl lm = loaders[i];
+                    lm.finishRetain();
+                    lm.doReportStart();
+                }
             }
         }
     }
@@ -5037,7 +5137,7 @@
         if (mStopped) {
             mStopped = false;
             if (mToken != null && mParent == null) {
-                WindowManagerImpl.getDefault().setStoppedState(mToken, false);
+                WindowManagerGlobal.getInstance().setStoppedState(mToken, false);
             }
 
             synchronized (mManagedCursors) {
@@ -5137,7 +5237,7 @@
             }
 
             if (mToken != null && mParent == null) {
-                WindowManagerImpl.getDefault().setStoppedState(mToken, true);
+                WindowManagerGlobal.getInstance().setStoppedState(mToken, true);
             }
             
             mFragments.dispatchStop();
@@ -5167,6 +5267,7 @@
     }
 
     final void performDestroy() {
+        mDestroyed = true;
         mWindow.destroy();
         mFragments.dispatchDestroy();
         onDestroy();
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 92b6f72..594be68 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -27,9 +27,12 @@
 import android.content.pm.ConfigurationInfo;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Point;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerGlobal;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Debug;
@@ -40,7 +43,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -209,6 +212,15 @@
      */
     public static final int INTENT_SENDER_SERVICE = 4;
 
+    /** @hide User operation call: success! */
+    public static final int USER_OP_SUCCESS = 0;
+
+    /** @hide User operation call: given user id is not known. */
+    public static final int USER_OP_UNKNOWN_USER = -1;
+
+    /** @hide User operation call: given user id is the current user, can't be stopped. */
+    public static final int USER_OP_IS_CURRENT = -2;
+
     /*package*/ ActivityManager(Context context, Handler handler) {
         mContext = context;
         mHandler = handler;
@@ -366,7 +378,7 @@
      * (which tends to consume a lot more RAM).
      * @hide
      */
-    static public boolean isHighEndGfx(Display display) {
+    static public boolean isHighEndGfx() {
         MemInfoReader reader = new MemInfoReader();
         reader.readMemInfo();
         if (reader.getTotalSize() >= (512*1024*1024)) {
@@ -374,6 +386,9 @@
             // we can afford the overhead of graphics acceleration.
             return true;
         }
+
+        Display display = DisplayManagerGlobal.getInstance().getRealDisplay(
+                Display.DEFAULT_DISPLAY);
         Point p = new Point();
         display.getRealSize(p);
         int pixels = p.x * p.y;
@@ -529,7 +544,36 @@
             throws SecurityException {
         try {
             return ActivityManagerNative.getDefault().getRecentTasks(maxNum,
-                    flags);
+                    flags, UserHandle.myUserId());
+        } catch (RemoteException e) {
+            // System dead, we will be dead too soon!
+            return null;
+        }
+    }
+
+    /**
+     * Same as {@link #getRecentTasks(int, int)} but returns the recent tasks for a
+     * specific user. It requires holding
+     * the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission.
+     * @param maxNum The maximum number of entries to return in the list.  The
+     * actual number returned may be smaller, depending on how many tasks the
+     * user has started and the maximum number the system can remember.
+     * @param flags Information about what to return.  May be any combination
+     * of {@link #RECENT_WITH_EXCLUDED} and {@link #RECENT_IGNORE_UNAVAILABLE}.
+     *
+     * @return Returns a list of RecentTaskInfo records describing each of
+     * the recent tasks.
+     *
+     * @throws SecurityException Throws SecurityException if the caller does
+     * not hold the {@link android.Manifest.permission#GET_TASKS} or the
+     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permissions.
+     * @hide
+     */
+    public List<RecentTaskInfo> getRecentTasksForUser(int maxNum, int flags, int userId)
+            throws SecurityException {
+        try {
+            return ActivityManagerNative.getDefault().getRecentTasks(maxNum,
+                    flags, userId);
         } catch (RemoteException e) {
             // System dead, we will be dead too soon!
             return null;
@@ -820,7 +864,17 @@
             return null;
         }
     }
-    
+
+    /** @hide */
+    public Bitmap getTaskTopThumbnail(int id) throws SecurityException {
+        try {
+            return ActivityManagerNative.getDefault().getTaskTopThumbnail(id);
+        } catch (RemoteException e) {
+            // System dead, we will be dead too soon!
+            return null;
+        }
+    }
+
     /**
      * Flag for {@link #moveTaskToFront(int, int)}: also move the "home"
      * activity along with the task, so it is positioned immediately behind
@@ -1182,7 +1236,7 @@
     public boolean clearApplicationUserData(String packageName, IPackageDataObserver observer) {
         try {
             return ActivityManagerNative.getDefault().clearApplicationUserData(packageName, 
-                    observer, Binder.getOrigCallingUser());
+                    observer, UserHandle.myUserId());
         } catch (RemoteException e) {
             return false;
         }
@@ -1346,6 +1400,13 @@
         public static final int FLAG_PERSISTENT = 1<<1;
 
         /**
+         * Constant for {@link #flags}: this process is associated with a
+         * persistent system app.
+         * @hide
+         */
+        public static final int FLAG_HAS_ACTIVITIES = 1<<2;
+
+        /**
          * Flags of information.  May be any of
          * {@link #FLAG_CANT_SAVE_STATE}.
          * @hide
@@ -1642,7 +1703,8 @@
      */
     public void killBackgroundProcesses(String packageName) {
         try {
-            ActivityManagerNative.getDefault().killBackgroundProcesses(packageName);
+            ActivityManagerNative.getDefault().killBackgroundProcesses(packageName,
+                    UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
@@ -1667,7 +1729,8 @@
      */
     public void forceStopPackage(String packageName) {
         try {
-            ActivityManagerNative.getDefault().forceStopPackage(packageName);
+            ActivityManagerNative.getDefault().forceStopPackage(packageName,
+                    UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
@@ -1814,12 +1877,12 @@
             return PackageManager.PERMISSION_GRANTED;
         }
         // Isolated processes don't get any permissions.
-        if (UserId.isIsolated(uid)) {
+        if (UserHandle.isIsolated(uid)) {
             return PackageManager.PERMISSION_DENIED;
         }
         // If there is a uid that owns whatever is being accessed, it has
         // blanket access to it regardless of the permissions it requires.
-        if (owningUid >= 0 && UserId.isSameApp(uid, owningUid)) {
+        if (owningUid >= 0 && UserHandle.isSameApp(uid, owningUid)) {
             return PackageManager.PERMISSION_GRANTED;
         }
         // If the target is not exported, then nobody else can get to it.
@@ -1840,6 +1903,43 @@
         return PackageManager.PERMISSION_DENIED;
     }
 
+    /** @hide */
+    public static int checkUidPermission(String permission, int uid) {
+        try {
+            return AppGlobals.getPackageManager()
+                    .checkUidPermission(permission, uid);
+        } catch (RemoteException e) {
+            // Should never happen, but if it does... deny!
+            Slog.e(TAG, "PackageManager is dead?!?", e);
+        }
+        return PackageManager.PERMISSION_DENIED;
+    }
+
+    /** @hide */
+    public static int handleIncomingUser(int callingPid, int callingUid, int userId,
+            boolean allowAll, boolean requireFull, String name, String callerPackage) {
+        if (UserHandle.getUserId(callingUid) == userId) {
+            return userId;
+        }
+        try {
+            return ActivityManagerNative.getDefault().handleIncomingUser(callingPid,
+                    callingUid, userId, allowAll, requireFull, name, callerPackage);
+        } catch (RemoteException e) {
+            throw new SecurityException("Failed calling activity manager", e);
+        }
+    }
+
+    /** @hide */
+    public static int getCurrentUser() {
+        UserInfo ui;
+        try {
+            ui = ActivityManagerNative.getDefault().getCurrentUser();
+            return ui != null ? ui.id : 0;
+        } catch (RemoteException e) {
+            return 0;
+        }
+    }
+
     /**
      * Returns the usage statistics of each installed package.
      *
@@ -1869,4 +1969,21 @@
             return false;
         }
     }
+
+    /**
+     * Return whether the given user is actively running.  This means that
+     * the user is in the "started" state, not "stopped" -- it is currently
+     * allowed to run code through scheduled alarms, receiving broadcasts,
+     * etc.  A started user may be either the current foreground user or a
+     * background user; the result here does not distinguish between the two.
+     * @param userid the user's id. Zero indicates the default user.
+     * @hide
+     */
+    public boolean isUserRunning(int userid) {
+        try {
+            return ActivityManagerNative.getDefault().isUserRunning(userid, false);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
 }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index e12fa19..67d3930 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -39,6 +39,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StrictMode;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Singleton;
@@ -88,11 +89,11 @@
      * Convenience for sending a sticky broadcast.  For internal use only.
      * If you don't care about permission, use null.
      */
-    static public void broadcastStickyIntent(Intent intent, String permission) {
+    static public void broadcastStickyIntent(Intent intent, String permission, int userId) {
         try {
             getDefault().broadcastIntent(
                 null, intent, null, null, Activity.RESULT_OK, null, null,
-                null /*permission*/, false, true, Binder.getOrigCallingUser());
+                null /*permission*/, false, true, userId);
         } catch (RemoteException ex) {
         }
     }
@@ -135,6 +136,31 @@
             return true;
         }
 
+        case START_ACTIVITY_AS_USER_TRANSACTION:
+        {
+            data.enforceInterface(IActivityManager.descriptor);
+            IBinder b = data.readStrongBinder();
+            IApplicationThread app = ApplicationThreadNative.asInterface(b);
+            Intent intent = Intent.CREATOR.createFromParcel(data);
+            String resolvedType = data.readString();
+            IBinder resultTo = data.readStrongBinder();
+            String resultWho = data.readString();
+            int requestCode = data.readInt();
+            int startFlags = data.readInt();
+            String profileFile = data.readString();
+            ParcelFileDescriptor profileFd = data.readInt() != 0
+                    ? data.readFileDescriptor() : null;
+            Bundle options = data.readInt() != 0
+                    ? Bundle.CREATOR.createFromParcel(data) : null;
+            int userId = data.readInt();
+            int result = startActivityAsUser(app, intent, resolvedType,
+                    resultTo, resultWho, requestCode, startFlags,
+                    profileFile, profileFd, options, userId);
+            reply.writeNoException();
+            reply.writeInt(result);
+            return true;
+        }
+
         case START_ACTIVITY_AND_WAIT_TRANSACTION:
         {
             data.enforceInterface(IActivityManager.descriptor);
@@ -151,9 +177,10 @@
                     ? data.readFileDescriptor() : null;
             Bundle options = data.readInt() != 0
                     ? Bundle.CREATOR.createFromParcel(data) : null;
+            int userId = data.readInt();
             WaitResult result = startActivityAndWait(app, intent, resolvedType,
                     resultTo, resultWho, requestCode, startFlags,
-                    profileFile, profileFd, options);
+                    profileFile, profileFd, options, userId);
             reply.writeNoException();
             result.writeToParcel(reply, 0);
             return true;
@@ -173,8 +200,9 @@
             Configuration config = Configuration.CREATOR.createFromParcel(data);
             Bundle options = data.readInt() != 0
                     ? Bundle.CREATOR.createFromParcel(data) : null;
+            int userId = data.readInt();
             int result = startActivityWithConfig(app, intent, resolvedType,
-                    resultTo, resultWho, requestCode, startFlags, config, options);
+                    resultTo, resultWho, requestCode, startFlags, config, options, userId);
             reply.writeNoException();
             reply.writeInt(result);
             return true;
@@ -273,7 +301,8 @@
                 = b != null ? IIntentReceiver.Stub.asInterface(b) : null;
             IntentFilter filter = IntentFilter.CREATOR.createFromParcel(data);
             String perm = data.readString();
-            Intent intent = registerReceiver(app, packageName, rec, filter, perm);
+            int userId = data.readInt();
+            Intent intent = registerReceiver(app, packageName, rec, filter, perm, userId);
             reply.writeNoException();
             if (intent != null) {
                 reply.writeInt(1);
@@ -375,6 +404,14 @@
             return true;
         }
 
+        case ACTIVITY_RESUMED_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IBinder token = data.readStrongBinder();
+            activityResumed(token);
+            reply.writeNoException();
+            return true;
+        }
+
         case ACTIVITY_PAUSED_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
@@ -454,13 +491,14 @@
             data.enforceInterface(IActivityManager.descriptor);
             int maxNum = data.readInt();
             int fl = data.readInt();
+            int userId = data.readInt();
             List<ActivityManager.RecentTaskInfo> list = getRecentTasks(maxNum,
-                    fl);
+                    fl, userId);
             reply.writeNoException();
             reply.writeTypedList(list);
             return true;
         }
-        
+
         case GET_TASK_THUMBNAILS_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             int id = data.readInt();
@@ -474,7 +512,21 @@
             }
             return true;
         }
-        
+
+        case GET_TASK_TOP_THUMBNAIL_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int id = data.readInt();
+            Bitmap bm = getTaskTopThumbnail(id);
+            reply.writeNoException();
+            if (bm != null) {
+                reply.writeInt(1);
+                bm.writeToParcel(reply, 0);
+            } else {
+                reply.writeInt(0);
+            }
+            return true;
+        }
+
         case GET_SERVICES_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             int maxNum = data.readInt();
@@ -580,8 +632,9 @@
             IBinder b = data.readStrongBinder();
             IApplicationThread app = ApplicationThreadNative.asInterface(b);
             String name = data.readString();
+            int userId = data.readInt();
             boolean stable = data.readInt() != 0;
-            ContentProviderHolder cph = getContentProvider(app, name, stable);
+            ContentProviderHolder cph = getContentProvider(app, name, userId, stable);
             reply.writeNoException();
             if (cph != null) {
                 reply.writeInt(1);
@@ -595,8 +648,9 @@
         case GET_CONTENT_PROVIDER_EXTERNAL_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             String name = data.readString();
+            int userId = data.readInt();
             IBinder token = data.readStrongBinder();
-            ContentProviderHolder cph = getContentProviderExternal(name, token);
+            ContentProviderHolder cph = getContentProviderExternal(name, userId, token);
             reply.writeNoException();
             if (cph != null) {
                 reply.writeInt(1);
@@ -670,7 +724,8 @@
             IApplicationThread app = ApplicationThreadNative.asInterface(b);
             Intent service = Intent.CREATOR.createFromParcel(data);
             String resolvedType = data.readString();
-            ComponentName cn = startService(app, service, resolvedType);
+            int userId = data.readInt();
+            ComponentName cn = startService(app, service, resolvedType, userId);
             reply.writeNoException();
             ComponentName.writeToParcel(cn, reply);
             return true;
@@ -682,7 +737,8 @@
             IApplicationThread app = ApplicationThreadNative.asInterface(b);
             Intent service = Intent.CREATOR.createFromParcel(data);
             String resolvedType = data.readString();
-            int res = stopService(app, service, resolvedType);
+            int userId = data.readInt();
+            int res = stopService(app, service, resolvedType, userId);
             reply.writeNoException();
             reply.writeInt(res);
             return true;
@@ -780,7 +836,8 @@
             Bundle arguments = data.readBundle();
             IBinder b = data.readStrongBinder();
             IInstrumentationWatcher w = IInstrumentationWatcher.Stub.asInterface(b);
-            boolean res = startInstrumentation(className, profileFile, fl, arguments, w);
+            int userId = data.readInt();
+            boolean res = startInstrumentation(className, profileFile, fl, arguments, w, userId);
             reply.writeNoException();
             reply.writeInt(res ? 1 : 0);
             return true;
@@ -868,9 +925,10 @@
             int fl = data.readInt();
             Bundle options = data.readInt() != 0
                     ? Bundle.CREATOR.createFromParcel(data) : null;
+            int userId = data.readInt();
             IIntentSender res = getIntentSender(type, packageName, token,
                     resultWho, requestCode, requestIntents,
-                    requestResolvedTypes, fl, options);
+                    requestResolvedTypes, fl, options, userId);
             reply.writeNoException();
             reply.writeStrongBinder(res != null ? res.asBinder() : null);
             return true;
@@ -905,6 +963,22 @@
             return true;
         }
 
+        case HANDLE_INCOMING_USER_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int callingPid = data.readInt();
+            int callingUid = data.readInt();
+            int userId = data.readInt();
+            boolean allowAll = data.readInt() != 0 ;
+            boolean requireFull = data.readInt() != 0;
+            String name = data.readString();
+            String callerPackage = data.readString();
+            int res = handleIncomingUser(callingPid, callingUid, userId, allowAll,
+                    requireFull, name, callerPackage);
+            reply.writeNoException();
+            reply.writeInt(res);
+            return true;
+        }
+
         case SET_PROCESS_LIMIT_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             int max = data.readInt();
@@ -1164,7 +1238,8 @@
         case KILL_BACKGROUND_PROCESSES_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             String packageName = data.readString();
-            killBackgroundProcesses(packageName);
+            int userId = data.readInt();
+            killBackgroundProcesses(packageName, userId);
             reply.writeNoException();
             return true;
         }
@@ -1179,7 +1254,8 @@
         case FORCE_STOP_PACKAGE_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             String packageName = data.readString();
-            forceStopPackage(packageName);
+            int userId = data.readInt();
+            forceStopPackage(packageName, userId);
             reply.writeNoException();
             return true;
         }
@@ -1205,12 +1281,13 @@
         case PROFILE_CONTROL_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             String process = data.readString();
+            int userId = data.readInt();
             boolean start = data.readInt() != 0;
             int profileType = data.readInt();
             String path = data.readString();
             ParcelFileDescriptor fd = data.readInt() != 0
                     ? data.readFileDescriptor() : null;
-            boolean res = profileControl(process, start, path, fd, profileType);
+            boolean res = profileControl(process, userId, start, path, fd, profileType);
             reply.writeNoException();
             reply.writeInt(res ? 1 : 0);
             return true;
@@ -1275,30 +1352,11 @@
             return true;
         }
         
-        case START_ACTIVITY_IN_PACKAGE_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            int uid = data.readInt();
-            Intent intent = Intent.CREATOR.createFromParcel(data);
-            String resolvedType = data.readString();
-            IBinder resultTo = data.readStrongBinder();
-            String resultWho = data.readString();    
-            int requestCode = data.readInt();
-            int startFlags = data.readInt();
-            Bundle options = data.readInt() != 0
-                    ? Bundle.CREATOR.createFromParcel(data) : null;
-            int result = startActivityInPackage(uid, intent, resolvedType,
-                    resultTo, resultWho, requestCode, startFlags, options);
-            reply.writeNoException();
-            reply.writeInt(result);
-            return true;
-        }
-        
-        case KILL_APPLICATION_WITH_UID_TRANSACTION: {
+        case KILL_APPLICATION_WITH_APPID_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             String pkg = data.readString();
-            int uid = data.readInt();
-            killApplicationWithUid(pkg, uid);
+            int appid = data.readInt();
+            killApplicationWithAppId(pkg, appid);
             reply.writeNoException();
             return true;
         }
@@ -1395,7 +1453,8 @@
         case GET_PROVIDER_MIME_TYPE_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             Uri uri = Uri.CREATOR.createFromParcel(data);
-            String type = getProviderMimeType(uri);
+            int userId = data.readInt();
+            String type = getProviderMimeType(uri, userId);
             reply.writeNoException();
             reply.writeString(type);
             return true;
@@ -1450,32 +1509,17 @@
         case DUMP_HEAP_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             String process = data.readString();
+            int userId = data.readInt();
             boolean managed = data.readInt() != 0;
             String path = data.readString();
             ParcelFileDescriptor fd = data.readInt() != 0
                     ? data.readFileDescriptor() : null;
-            boolean res = dumpHeap(process, managed, path, fd);
+            boolean res = dumpHeap(process, userId, managed, path, fd);
             reply.writeNoException();
             reply.writeInt(res ? 1 : 0);
             return true;
         }
 
-        case START_ACTIVITIES_IN_PACKAGE_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            int uid = data.readInt();
-            Intent[] intents = data.createTypedArray(Intent.CREATOR);
-            String[] resolvedTypes = data.createStringArray();
-            IBinder resultTo = data.readStrongBinder();
-            Bundle options = data.readInt() != 0
-                    ? Bundle.CREATOR.createFromParcel(data) : null;
-            int result = startActivitiesInPackage(uid, intents, resolvedTypes,
-                    resultTo, options);
-            reply.writeNoException();
-            reply.writeInt(result);
-            return true;
-        }
-
         case START_ACTIVITIES_TRANSACTION:
         {
             data.enforceInterface(IActivityManager.descriptor);
@@ -1486,8 +1530,9 @@
             IBinder resultTo = data.readStrongBinder();
             Bundle options = data.readInt() != 0
                     ? Bundle.CREATOR.createFromParcel(data) : null;
+            int userId = data.readInt();
             int result = startActivities(app, intents, resolvedTypes, resultTo,
-                    options);
+                    options, userId);
             reply.writeNoException();
             reply.writeInt(result);
             return true;
@@ -1541,6 +1586,17 @@
             return true;
         }
 
+        case STOP_USER_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int userid = data.readInt();
+            IStopUserCallback callback = IStopUserCallback.Stub.asInterface(
+                    data.readStrongBinder());
+            int result = stopUser(userid, callback);
+            reply.writeNoException();
+            reply.writeInt(result);
+            return true;
+        }
+
         case GET_CURRENT_USER_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             UserInfo userInfo = getCurrentUser();
@@ -1549,6 +1605,24 @@
             return true;
         }
 
+        case IS_USER_RUNNING_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int userid = data.readInt();
+            boolean orStopping = data.readInt() != 0;
+            boolean result = isUserRunning(userid, orStopping);
+            reply.writeNoException();
+            reply.writeInt(result ? 1 : 0);
+            return true;
+        }
+
+        case GET_RUNNING_USER_IDS_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int[] result = getRunningUserIds();
+            reply.writeNoException();
+            reply.writeIntArray(result);
+            return true;
+        }
+
         case REMOVE_SUB_TASK_TRANSACTION:
         {
             data.enforceInterface(IActivityManager.descriptor);
@@ -1694,6 +1768,41 @@
             return true;
         }
 
+        case REGISTER_USER_SWITCH_OBSERVER_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IUserSwitchObserver observer = IUserSwitchObserver.Stub.asInterface(
+                    data.readStrongBinder());
+            registerUserSwitchObserver(observer);
+            reply.writeNoException();
+            return true;
+        }
+
+        case UNREGISTER_USER_SWITCH_OBSERVER_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IUserSwitchObserver observer = IUserSwitchObserver.Stub.asInterface(
+                    data.readStrongBinder());
+            unregisterUserSwitchObserver(observer);
+            reply.writeNoException();
+            return true;
+        }
+
+        case REQUEST_BUG_REPORT_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            requestBugReport();
+            reply.writeNoException();
+            return true;
+        }
+
+        case INPUT_DISPATCHING_TIMED_OUT_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int pid = data.readInt();
+            boolean aboveSystem = data.readInt() != 0;
+            long res = inputDispatchingTimedOut(pid, aboveSystem);
+            reply.writeNoException();
+            reply.writeLong(res);
+            return true;
+        }
+
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -1764,10 +1873,11 @@
         data.recycle();
         return result;
     }
-    public WaitResult startActivityAndWait(IApplicationThread caller, Intent intent,
-            String resolvedType, IBinder resultTo, String resultWho,
-            int requestCode, int startFlags, String profileFile,
-            ParcelFileDescriptor profileFd, Bundle options) throws RemoteException {
+
+    public int startActivityAsUser(IApplicationThread caller, Intent intent,
+            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
+            int startFlags, String profileFile,
+            ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
@@ -1791,6 +1901,42 @@
         } else {
             data.writeInt(0);
         }
+        data.writeInt(userId);
+        mRemote.transact(START_ACTIVITY_AS_USER_TRANSACTION, data, reply, 0);
+        reply.readException();
+        int result = reply.readInt();
+        reply.recycle();
+        data.recycle();
+        return result;
+    }
+    public WaitResult startActivityAndWait(IApplicationThread caller, Intent intent,
+            String resolvedType, IBinder resultTo, String resultWho,
+            int requestCode, int startFlags, String profileFile,
+            ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
+        intent.writeToParcel(data, 0);
+        data.writeString(resolvedType);
+        data.writeStrongBinder(resultTo);
+        data.writeString(resultWho);
+        data.writeInt(requestCode);
+        data.writeInt(startFlags);
+        data.writeString(profileFile);
+        if (profileFd != null) {
+            data.writeInt(1);
+            profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+        } else {
+            data.writeInt(0);
+        }
+        if (options != null) {
+            data.writeInt(1);
+            options.writeToParcel(data, 0);
+        } else {
+            data.writeInt(0);
+        }
+        data.writeInt(userId);
         mRemote.transact(START_ACTIVITY_AND_WAIT_TRANSACTION, data, reply, 0);
         reply.readException();
         WaitResult result = WaitResult.CREATOR.createFromParcel(reply);
@@ -1801,7 +1947,7 @@
     public int startActivityWithConfig(IApplicationThread caller, Intent intent,
             String resolvedType, IBinder resultTo, String resultWho,
             int requestCode, int startFlags, Configuration config,
-            Bundle options) throws RemoteException {
+            Bundle options, int userId) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
@@ -1819,6 +1965,7 @@
         } else {
             data.writeInt(0);
         }
+        data.writeInt(userId);
         mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
         reply.readException();
         int result = reply.readInt();
@@ -1939,7 +2086,7 @@
     }
     public Intent registerReceiver(IApplicationThread caller, String packageName,
             IIntentReceiver receiver,
-            IntentFilter filter, String perm) throws RemoteException
+            IntentFilter filter, String perm, int userId) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -1949,6 +2096,7 @@
         data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
         filter.writeToParcel(data, 0);
         data.writeString(perm);
+        data.writeInt(userId);
         mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);
         reply.readException();
         Intent intent = null;
@@ -2057,6 +2205,17 @@
         data.recycle();
         reply.recycle();
     }
+    public void activityResumed(IBinder token) throws RemoteException
+    {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(token);
+        mRemote.transact(ACTIVITY_RESUMED_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
     public void activityPaused(IBinder token) throws RemoteException
     {
         Parcel data = Parcel.obtain();
@@ -2163,12 +2322,13 @@
         return list;
     }
     public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
-            int flags) throws RemoteException {
+            int flags, int userId) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeInt(maxNum);
         data.writeInt(flags);
+        data.writeInt(userId);
         mRemote.transact(GET_RECENT_TASKS_TRANSACTION, data, reply, 0);
         reply.readException();
         ArrayList<ActivityManager.RecentTaskInfo> list
@@ -2192,6 +2352,21 @@
         reply.recycle();
         return bm;
     }
+    public Bitmap getTaskTopThumbnail(int id) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(id);
+        mRemote.transact(GET_TASK_TOP_THUMBNAIL_TRANSACTION, data, reply, 0);
+        reply.readException();
+        Bitmap bm = null;
+        if (reply.readInt() != 0) {
+            bm = Bitmap.CREATOR.createFromParcel(reply);
+        }
+        data.recycle();
+        reply.recycle();
+        return bm;
+    }
     public List getServices(int maxNum, int flags) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -2343,12 +2518,13 @@
         reply.recycle();
     }
     public ContentProviderHolder getContentProvider(IApplicationThread caller,
-            String name, boolean stable) throws RemoteException {
+            String name, int userId, boolean stable) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(caller != null ? caller.asBinder() : null);
         data.writeString(name);
+        data.writeInt(userId);
         data.writeInt(stable ? 1 : 0);
         mRemote.transact(GET_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
         reply.readException();
@@ -2361,13 +2537,13 @@
         reply.recycle();
         return cph;
     }
-    public ContentProviderHolder getContentProviderExternal(String name, IBinder token)
-            throws RemoteException
-    {
+    public ContentProviderHolder getContentProviderExternal(String name, int userId, IBinder token)
+            throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeString(name);
+        data.writeInt(userId);
         data.writeStrongBinder(token);
         mRemote.transact(GET_CONTENT_PROVIDER_EXTERNAL_TRANSACTION, data, reply, 0);
         reply.readException();
@@ -2459,7 +2635,7 @@
     }
     
     public ComponentName startService(IApplicationThread caller, Intent service,
-            String resolvedType) throws RemoteException
+            String resolvedType, int userId) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -2467,6 +2643,7 @@
         data.writeStrongBinder(caller != null ? caller.asBinder() : null);
         service.writeToParcel(data, 0);
         data.writeString(resolvedType);
+        data.writeInt(userId);
         mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
         reply.readException();
         ComponentName res = ComponentName.readFromParcel(reply);
@@ -2475,7 +2652,7 @@
         return res;
     }
     public int stopService(IApplicationThread caller, Intent service,
-            String resolvedType) throws RemoteException
+            String resolvedType, int userId) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -2483,6 +2660,7 @@
         data.writeStrongBinder(caller != null ? caller.asBinder() : null);
         service.writeToParcel(data, 0);
         data.writeString(resolvedType);
+        data.writeInt(userId);
         mRemote.transact(STOP_SERVICE_TRANSACTION, data, reply, 0);
         reply.readException();
         int res = reply.readInt();
@@ -2631,6 +2809,15 @@
         return success;
     }
 
+    public void clearPendingBackup() throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        mRemote.transact(CLEAR_PENDING_BACKUP_TRANSACTION, data, reply, 0);
+        reply.recycle();
+        data.recycle();
+    }
+
     public void backupAgentCreated(String packageName, IBinder agent) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -2654,7 +2841,7 @@
     }
 
     public boolean startInstrumentation(ComponentName className, String profileFile,
-            int flags, Bundle arguments, IInstrumentationWatcher watcher)
+            int flags, Bundle arguments, IInstrumentationWatcher watcher, int userId)
             throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -2664,6 +2851,7 @@
         data.writeInt(flags);
         data.writeBundle(arguments);
         data.writeStrongBinder(watcher != null ? watcher.asBinder() : null);
+        data.writeInt(userId);
         mRemote.transact(START_INSTRUMENTATION_TRANSACTION, data, reply, 0);
         reply.readException();
         boolean res = reply.readInt() != 0;
@@ -2761,7 +2949,7 @@
     public IIntentSender getIntentSender(int type,
             String packageName, IBinder token, String resultWho,
             int requestCode, Intent[] intents, String[] resolvedTypes, int flags,
-            Bundle options) throws RemoteException {
+            Bundle options, int userId) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
@@ -2784,6 +2972,7 @@
         } else {
             data.writeInt(0);
         }
+        data.writeInt(userId);
         mRemote.transact(GET_INTENT_SENDER_TRANSACTION, data, reply, 0);
         reply.readException();
         IIntentSender res = IIntentSender.Stub.asInterface(
@@ -2826,6 +3015,25 @@
         reply.recycle();
         return res;
     }
+    public int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
+            boolean requireFull, String name, String callerPackage) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(callingPid);
+        data.writeInt(callingUid);
+        data.writeInt(userId);
+        data.writeInt(allowAll ? 1 : 0);
+        data.writeInt(requireFull ? 1 : 0);
+        data.writeString(name);
+        data.writeString(callerPackage);
+        mRemote.transact(HANDLE_INCOMING_USER_TRANSACTION, data, reply, 0);
+        reply.readException();
+        int res = reply.readInt();
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
     public void setProcessLimit(int max) throws RemoteException
     {
         Parcel data = Parcel.obtain();
@@ -3165,11 +3373,12 @@
         reply.recycle();
     }
 
-    public void killBackgroundProcesses(String packageName) throws RemoteException {
+    public void killBackgroundProcesses(String packageName, int userId) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeString(packageName);
+        data.writeInt(userId);
         mRemote.transact(KILL_BACKGROUND_PROCESSES_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
@@ -3186,11 +3395,12 @@
         reply.recycle();
     }
 
-    public void forceStopPackage(String packageName) throws RemoteException {
+    public void forceStopPackage(String packageName, int userId) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeString(packageName);
+        data.writeInt(userId);
         mRemote.transact(FORCE_STOP_PACKAGE_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
@@ -3223,13 +3433,14 @@
         return res;
     }
     
-    public boolean profileControl(String process, boolean start,
+    public boolean profileControl(String process, int userId, boolean start,
             String path, ParcelFileDescriptor fd, int profileType) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeString(process);
+        data.writeInt(userId);
         data.writeInt(start ? 1 : 0);
         data.writeInt(profileType);
         data.writeString(path);
@@ -3281,41 +3492,13 @@
         data.recycle();
     }
     
-    public int startActivityInPackage(int uid,
-            Intent intent, String resolvedType, IBinder resultTo,
-            String resultWho, int requestCode, int startFlags, Bundle options)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(uid);
-        intent.writeToParcel(data, 0);
-        data.writeString(resolvedType);
-        data.writeStrongBinder(resultTo);
-        data.writeString(resultWho);
-        data.writeInt(requestCode);
-        data.writeInt(startFlags);
-        if (options != null) {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        mRemote.transact(START_ACTIVITY_IN_PACKAGE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int result = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-    
-    public void killApplicationWithUid(String pkg, int uid) throws RemoteException {
+    public void killApplicationWithAppId(String pkg, int appid) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeString(pkg);
-        data.writeInt(uid);
-        mRemote.transact(KILL_APPLICATION_WITH_UID_TRANSACTION, data, reply, 0);
+        data.writeInt(appid);
+        mRemote.transact(KILL_APPLICATION_WITH_APPID_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
@@ -3450,12 +3633,12 @@
         reply.recycle();
     }
 
-    public String getProviderMimeType(Uri uri)
-            throws RemoteException {
+    public String getProviderMimeType(Uri uri, int userId) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         uri.writeToParcel(data, 0);
+        data.writeInt(userId);
         mRemote.transact(GET_PROVIDER_MIME_TYPE_TRANSACTION, data, reply, 0);
         reply.readException();
         String res = reply.readString();
@@ -3530,12 +3713,13 @@
         return res;
     }
 
-    public boolean dumpHeap(String process, boolean managed,
+    public boolean dumpHeap(String process, int userId, boolean managed,
             String path, ParcelFileDescriptor fd) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeString(process);
+        data.writeInt(userId);
         data.writeInt(managed ? 1 : 0);
         data.writeString(path);
         if (fd != null) {
@@ -3554,7 +3738,7 @@
     
     public int startActivities(IApplicationThread caller,
             Intent[] intents, String[] resolvedTypes, IBinder resultTo,
-            Bundle options) throws RemoteException {
+            Bundle options, int userId) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
@@ -3568,6 +3752,7 @@
         } else {
             data.writeInt(0);
         }
+        data.writeInt(userId);
         mRemote.transact(START_ACTIVITIES_TRANSACTION, data, reply, 0);
         reply.readException();
         int result = reply.readInt();
@@ -3576,30 +3761,6 @@
         return result;
     }
 
-    public int startActivitiesInPackage(int uid,
-            Intent[] intents, String[] resolvedTypes, IBinder resultTo,
-            Bundle options) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(uid);
-        data.writeTypedArray(intents, 0);
-        data.writeStringArray(resolvedTypes);
-        data.writeStrongBinder(resultTo);
-        if (options != null) {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        mRemote.transact(START_ACTIVITIES_IN_PACKAGE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int result = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-
     public int getFrontActivityScreenCompatMode() throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -3688,11 +3849,25 @@
         return result;
     }
 
+    public int stopUser(int userid, IStopUserCallback callback) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(userid);
+        data.writeStrongInterface(callback);
+        mRemote.transact(STOP_USER_TRANSACTION, data, reply, 0);
+        reply.readException();
+        int result = reply.readInt();
+        reply.recycle();
+        data.recycle();
+        return result;
+    }
+
     public UserInfo getCurrentUser() throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(SWITCH_USER_TRANSACTION, data, reply, 0);
+        mRemote.transact(GET_CURRENT_USER_TRANSACTION, data, reply, 0);
         reply.readException();
         UserInfo userInfo = UserInfo.CREATOR.createFromParcel(reply);
         reply.recycle();
@@ -3700,6 +3875,32 @@
         return userInfo;
     }
 
+    public boolean isUserRunning(int userid, boolean orStopping) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(userid);
+        data.writeInt(orStopping ? 1 : 0);
+        mRemote.transact(IS_USER_RUNNING_TRANSACTION, data, reply, 0);
+        reply.readException();
+        boolean result = reply.readInt() != 0;
+        reply.recycle();
+        data.recycle();
+        return result;
+    }
+
+    public int[] getRunningUserIds() throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        mRemote.transact(GET_RUNNING_USER_IDS_TRANSACTION, data, reply, 0);
+        reply.readException();
+        int[] result = reply.createIntArray();
+        reply.recycle();
+        data.recycle();
+        return result;
+    }
+
     public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -3873,5 +4074,51 @@
         return result;
     }
 
+    public void registerUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(observer != null ? observer.asBinder() : null);
+        mRemote.transact(REGISTER_USER_SWITCH_OBSERVER_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
+    public void unregisterUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(observer != null ? observer.asBinder() : null);
+        mRemote.transact(UNREGISTER_USER_SWITCH_OBSERVER_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
+    public void requestBugReport() throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        mRemote.transact(REQUEST_BUG_REPORT_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
+    public long inputDispatchingTimedOut(int pid, boolean aboveSystem) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(pid);
+        data.writeInt(aboveSystem ? 1 : 0);
+        mRemote.transact(INPUT_DISPATCHING_TIMED_OUT_TRANSACTION, data, reply, 0);
+        reply.readException();
+        long res = reply.readInt();
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
+
     private IBinder mRemote;
 }
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 4edfdfb..87b1e24 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -97,9 +97,9 @@
     /** @hide */
     public static final int ANIM_SCALE_UP = 2;
     /** @hide */
-    public static final int ANIM_THUMBNAIL = 3;
+    public static final int ANIM_THUMBNAIL_SCALE_UP = 3;
     /** @hide */
-    public static final int ANIM_THUMBNAIL_DELAYED = 4;
+    public static final int ANIM_THUMBNAIL_SCALE_DOWN = 4;
 
     private String mPackageName;
     private int mAnimationType = ANIM_NONE;
@@ -262,20 +262,19 @@
      */
     public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
-        return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, listener, false);
+        return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, true);
     }
 
     /**
-     * Create an ActivityOptions specifying an animation where a thumbnail
-     * is scaled from a given position to the new activity window that is
-     * being started. Before the animation, there is a short delay.
+     * Create an ActivityOptions specifying an animation where an activity window
+     * is scaled from a given position to a thumbnail at a specified location.
      *
-     * @param source The View that this thumbnail is animating from.  This
+     * @param source The View that this thumbnail is animating to.  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
+     * @param thumbnail The bitmap that will be shown as the final thumbnail
      * of the animation.
-     * @param startX The x starting location of the bitmap, relative to <var>source</var>.
-     * @param startY The y starting location of the bitmap, relative to <var>source</var>.
+     * @param startX The x end location of the bitmap, relative to <var>source</var>.
+     * @param startY The y end location of the bitmap, relative to <var>source</var>.
      * @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.
@@ -283,17 +282,17 @@
      * supply these options as the options Bundle when starting an activity.
      * @hide
      */
-    public static ActivityOptions makeDelayedThumbnailScaleUpAnimation(View source,
+    public static ActivityOptions makeThumbnailScaleDownAnimation(View source,
             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
-        return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, listener, true);
+        return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, false);
     }
 
-    private static ActivityOptions makeThumbnailScaleUpAnimation(View source,
+    private static ActivityOptions makeThumbnailAnimation(View source,
             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener,
-            boolean delayed) {
+            boolean scaleUp) {
         ActivityOptions opts = new ActivityOptions();
         opts.mPackageName = source.getContext().getPackageName();
-        opts.mAnimationType = delayed ? ANIM_THUMBNAIL_DELAYED : ANIM_THUMBNAIL;
+        opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_SCALE_UP : ANIM_THUMBNAIL_SCALE_DOWN;
         opts.mThumbnail = thumbnail;
         int[] pts = new int[2];
         source.getLocationOnScreen(pts);
@@ -320,8 +319,8 @@
             mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
             mStartWidth = opts.getInt(KEY_ANIM_START_WIDTH, 0);
             mStartHeight = opts.getInt(KEY_ANIM_START_HEIGHT, 0);
-        } else if (mAnimationType == ANIM_THUMBNAIL ||
-                mAnimationType == ANIM_THUMBNAIL_DELAYED) {
+        } else if (mAnimationType == ANIM_THUMBNAIL_SCALE_UP ||
+                mAnimationType == ANIM_THUMBNAIL_SCALE_DOWN) {
             mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL);
             mStartX = opts.getInt(KEY_ANIM_START_X, 0);
             mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
@@ -434,8 +433,8 @@
                 }
                 mAnimationStartedListener = null;
                 break;
-            case ANIM_THUMBNAIL:
-            case ANIM_THUMBNAIL_DELAYED:
+            case ANIM_THUMBNAIL_SCALE_UP:
+            case ANIM_THUMBNAIL_SCALE_DOWN:
                 mAnimationType = otherOptions.mAnimationType;
                 mThumbnail = otherOptions.mThumbnail;
                 mStartX = otherOptions.mStartX;
@@ -479,8 +478,8 @@
                 b.putInt(KEY_ANIM_START_WIDTH, mStartWidth);
                 b.putInt(KEY_ANIM_START_HEIGHT, mStartHeight);
                 break;
-            case ANIM_THUMBNAIL:
-            case ANIM_THUMBNAIL_DELAYED:
+            case ANIM_THUMBNAIL_SCALE_UP:
+            case ANIM_THUMBNAIL_SCALE_DOWN:
                 b.putInt(KEY_ANIM_TYPE, mAnimationType);
                 b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
                 b.putInt(KEY_ANIM_START_X, mStartX);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b7e0683a..456d757 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -29,6 +29,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.InstrumentationInfo;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ProviderInfo;
@@ -42,6 +43,8 @@
 import android.database.sqlite.SQLiteDebug.DbStats;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerGlobal;
 import android.net.IConnectivityManager;
 import android.net.Proxy;
 import android.net.ProxyProperties;
@@ -50,6 +53,8 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Debug;
+import android.os.DropBoxManager;
+import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -61,8 +66,9 @@
 import android.os.ServiceManager;
 import android.os.StrictMode;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.Trace;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.AndroidRuntimeException;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
@@ -70,6 +76,7 @@
 import android.util.LogPrinter;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
+import android.view.CompatibilityInfoHolder;
 import android.view.Display;
 import android.view.HardwareRenderer;
 import android.view.View;
@@ -78,12 +85,13 @@
 import android.view.ViewRootImpl;
 import android.view.Window;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+import android.view.WindowManagerGlobal;
 import android.renderscript.RenderScript;
 
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.RuntimeInit;
 import com.android.internal.os.SamplingProfilerIntegration;
+import com.android.internal.util.Objects;
 
 import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
 
@@ -94,6 +102,7 @@
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.net.InetAddress;
+import java.security.Security;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -103,6 +112,8 @@
 import java.util.TimeZone;
 import java.util.regex.Pattern;
 
+import libcore.io.DropBox;
+import libcore.io.EventLogger;
 import libcore.io.IoUtils;
 
 import dalvik.system.CloseGuard;
@@ -165,6 +176,8 @@
             = new HashMap<IBinder, Service>();
     AppBindData mBoundApplication;
     Profiler mProfiler;
+    int mCurDefaultDisplayDpi;
+    boolean mDensityCompatMode;
     Configuration mConfiguration;
     Configuration mCompatConfiguration;
     Configuration mResConfiguration;
@@ -196,7 +209,7 @@
             = new HashMap<String, WeakReference<LoadedApk>>();
     final HashMap<String, WeakReference<LoadedApk>> mResourcePackages
             = new HashMap<String, WeakReference<LoadedApk>>();
-    final HashMap<CompatibilityInfo, DisplayMetrics> mDisplayMetrics
+    final HashMap<CompatibilityInfo, DisplayMetrics> mDefaultDisplayMetrics
             = new HashMap<CompatibilityInfo, DisplayMetrics>();
     final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
             = new HashMap<ResourcesKey, WeakReference<Resources> >();
@@ -204,9 +217,33 @@
             = new ArrayList<ActivityClientRecord>();
     Configuration mPendingConfiguration = null;
 
+    private static final class ProviderKey {
+        final String authority;
+        final int userId;
+
+        public ProviderKey(String authority, int userId) {
+            this.authority = authority;
+            this.userId = userId;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o instanceof ProviderKey) {
+                final ProviderKey other = (ProviderKey) o;
+                return Objects.equal(authority, other.authority) && userId == other.userId;
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return ((authority != null) ? authority.hashCode() : 0) ^ userId;
+        }
+    }
+
     // The lock of mProviderMap protects the following variables.
-    final HashMap<String, ProviderClientRecord> mProviderMap
-        = new HashMap<String, ProviderClientRecord>();
+    final HashMap<ProviderKey, ProviderClientRecord> mProviderMap
+        = new HashMap<ProviderKey, ProviderClientRecord>();
     final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap
         = new HashMap<IBinder, ProviderRefCount>();
     final HashMap<IBinder, ProviderClientRecord> mLocalProviders
@@ -313,8 +350,9 @@
 
     static final class ReceiverData extends BroadcastReceiver.PendingResult {
         public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras,
-                boolean ordered, boolean sticky, IBinder token) {
-            super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, token);
+                boolean ordered, boolean sticky, IBinder token, int sendingUser) {
+            super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky,
+                    token, sendingUser);
             this.intent = intent;
         }
 
@@ -606,9 +644,9 @@
 
         public final void scheduleReceiver(Intent intent, ActivityInfo info,
                 CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
-                boolean sync) {
+                boolean sync, int sendingUser) {
             ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
-                    sync, false, mAppThread.asBinder());
+                    sync, false, mAppThread.asBinder(), sendingUser);
             r.info = info;
             r.compatInfo = compatInfo;
             queueOrSendMessage(H.RECEIVER, r);
@@ -767,8 +805,9 @@
         // applies transaction ordering per object for such calls.
         public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
                 int resultCode, String dataStr, Bundle extras, boolean ordered,
-                boolean sticky) throws RemoteException {
-            receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
+                boolean sticky, int sendingUser) throws RemoteException {
+            receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
+                    sticky, sendingUser);
         }
 
         public void scheduleLowMemory() {
@@ -1052,7 +1091,7 @@
         @Override
         public void dumpGfxInfo(FileDescriptor fd, String[] args) {
             dumpGraphicsInfo(fd);
-            WindowManagerImpl.getDefault().dumpGfxInfo(fd);
+            WindowManagerGlobal.getInstance().dumpGfxInfo(fd);
         }
 
         @Override
@@ -1235,7 +1274,7 @@
                 case RESUME_ACTIVITY:
                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
                     handleResumeActivity((IBinder)msg.obj, true,
-                            msg.arg1 != 0);
+                            msg.arg1 != 0, true);
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     break;
                 case SEND_RESULT:
@@ -1305,6 +1344,7 @@
                     break;
                 case CONFIGURATION_CHANGED:
                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
+                    mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;
                     handleConfigurationChanged((Configuration)msg.obj, null);
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     break;
@@ -1467,13 +1507,28 @@
 
     private static class ResourcesKey {
         final private String mResDir;
+        final private int mDisplayId;
+        final private Configuration mOverrideConfiguration;
         final private float mScale;
         final private int mHash;
 
-        ResourcesKey(String resDir, float scale) {
+        ResourcesKey(String resDir, int displayId, Configuration overrideConfiguration, float scale) {
             mResDir = resDir;
+            mDisplayId = displayId;
+            if (overrideConfiguration != null) {
+                if (Configuration.EMPTY.equals(overrideConfiguration)) {
+                    overrideConfiguration = null;
+                }
+            }
+            mOverrideConfiguration = overrideConfiguration;
             mScale = scale;
-            mHash = mResDir.hashCode() << 2 + (int) (mScale * 2);
+            int hash = 17;
+            hash = 31 * hash + mResDir.hashCode();
+            hash = 31 * hash + mDisplayId;
+            hash = 31 * hash + (mOverrideConfiguration != null
+                    ? mOverrideConfiguration.hashCode() : 0);
+            hash = 31 * hash + Float.floatToIntBits(mScale);
+            mHash = hash;
         }
 
         @Override
@@ -1487,7 +1542,24 @@
                 return false;
             }
             ResourcesKey peer = (ResourcesKey) obj;
-            return mResDir.equals(peer.mResDir) && mScale == peer.mScale;
+            if (!mResDir.equals(peer.mResDir)) {
+                return false;
+            }
+            if (mDisplayId != peer.mDisplayId) {
+                return false;
+            }
+            if (mOverrideConfiguration != peer.mOverrideConfiguration) {
+                if (mOverrideConfiguration == null || peer.mOverrideConfiguration == null) {
+                    return false;
+                }
+                if (!mOverrideConfiguration.equals(peer.mOverrideConfiguration)) {
+                    return false;
+                }
+            }
+            if (mScale != peer.mScale) {
+                return false;
+            }
+            return true;
         }
     }
 
@@ -1518,17 +1590,41 @@
         return sPackageManager;
     }
 
-    DisplayMetrics getDisplayMetricsLocked(CompatibilityInfo ci, boolean forceUpdate) {
-        DisplayMetrics dm = mDisplayMetrics.get(ci);
-        if (dm != null && !forceUpdate) {
+    private void flushDisplayMetricsLocked() {
+        mDefaultDisplayMetrics.clear();
+    }
+
+    DisplayMetrics getDisplayMetricsLocked(int displayId, CompatibilityInfo ci) {
+        boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+        DisplayMetrics dm = isDefaultDisplay ? mDefaultDisplayMetrics.get(ci) : null;
+        if (dm != null) {
             return dm;
         }
-        if (dm == null) {
-            dm = new DisplayMetrics();
-            mDisplayMetrics.put(ci, dm);
+        dm = new DisplayMetrics();
+
+        DisplayManagerGlobal displayManager = DisplayManagerGlobal.getInstance();
+        if (displayManager == null) {
+            // may be null early in system startup
+            dm.setToDefaults();
+            return dm;
         }
-        Display d = WindowManagerImpl.getDefault(ci).getDefaultDisplay();
-        d.getMetrics(dm);
+
+        if (isDefaultDisplay) {
+            mDefaultDisplayMetrics.put(ci, dm);
+        }
+
+        CompatibilityInfoHolder cih = new CompatibilityInfoHolder();
+        cih.set(ci);
+        Display d = displayManager.getCompatibleDisplay(displayId, cih);
+        if (d != null) {
+            d.getMetrics(dm);
+        } else {
+            // Display no longer exists
+            // FIXME: This would not be a problem if we kept the Display object around
+            // instead of using the raw display id everywhere.  The Display object caches
+            // its information even after the display has been removed.
+            dm.setToDefaults();
+        }
         //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
         //        + metrics.heightPixels + " den=" + metrics.density
         //        + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
@@ -1536,14 +1632,15 @@
     }
 
     private Configuration mMainThreadConfig = new Configuration();
-    Configuration applyConfigCompatMainThread(Configuration config, CompatibilityInfo compat) {
+    Configuration applyConfigCompatMainThread(int displayDensity, Configuration config,
+            CompatibilityInfo compat) {
         if (config == null) {
             return null;
         }
         if (compat != null && !compat.supportsScreen()) {
             mMainThreadConfig.setTo(config);
             config = mMainThreadConfig;
-            compat.applyToConfiguration(config);
+            compat.applyToConfiguration(displayDensity, config);
         }
         return config;
     }
@@ -1555,8 +1652,12 @@
      * @param compInfo the compability info. It will use the default compatibility info when it's
      * null.
      */
-    Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) {
-        ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale);
+    Resources getTopLevelResources(String resDir,
+            int displayId, Configuration overrideConfiguration,
+            CompatibilityInfo compInfo) {
+        ResourcesKey key = new ResourcesKey(resDir,
+                displayId, overrideConfiguration,
+                compInfo.applicationScale);
         Resources r;
         synchronized (mPackages) {
             // Resources is app scale dependent.
@@ -1587,14 +1688,27 @@
         }
 
         //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
-        DisplayMetrics metrics = getDisplayMetricsLocked(null, false);
-        r = new Resources(assets, metrics, getConfiguration(), compInfo);
+        DisplayMetrics dm = getDisplayMetricsLocked(displayId, null);
+        Configuration config;
+        boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+        if (!isDefaultDisplay || key.mOverrideConfiguration != null) {
+            config = new Configuration(getConfiguration());
+            if (!isDefaultDisplay) {
+                applyNonDefaultDisplayMetricsToConfigurationLocked(dm, config);
+            }
+            if (key.mOverrideConfiguration != null) {
+                config.updateFrom(key.mOverrideConfiguration);
+            }
+        } else {
+            config = getConfiguration();
+        }
+        r = new Resources(assets, dm, config, compInfo);
         if (false) {
             Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
                     + r.getConfiguration() + " appScale="
                     + r.getCompatibilityInfo().applicationScale);
         }
-        
+
         synchronized (mPackages) {
             WeakReference<Resources> wr = mActiveResources.get(key);
             Resources existing = wr != null ? wr.get() : null;
@@ -1614,8 +1728,11 @@
     /**
      * Creates the top level resources for the given package.
      */
-    Resources getTopLevelResources(String resDir, LoadedApk pkgInfo) {
-        return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo.get());
+    Resources getTopLevelResources(String resDir,
+            int displayId, Configuration overrideConfiguration,
+            LoadedApk pkgInfo) {
+        return getTopLevelResources(resDir, displayId, overrideConfiguration,
+                pkgInfo.mCompatibilityInfo.get());
     }
 
     final Handler getHandler() {
@@ -1624,6 +1741,11 @@
 
     public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
             int flags) {
+        return getPackageInfo(packageName, compatInfo, flags, UserHandle.myUserId());
+    }
+
+    public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
+            int flags, int userId) {
         synchronized (mPackages) {
             WeakReference<LoadedApk> ref;
             if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) {
@@ -1652,7 +1774,7 @@
         ApplicationInfo ai = null;
         try {
             ai = getPackageManager().getApplicationInfo(packageName,
-                    PackageManager.GET_SHARED_LIBRARY_FILES, UserId.myUserId());
+                    PackageManager.GET_SHARED_LIBRARY_FILES, userId);
         } catch (RemoteException e) {
             // Ignore
         }
@@ -1669,7 +1791,7 @@
         boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
         boolean securityViolation = includeCode && ai.uid != 0
                 && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
-                        ? !UserId.isSameApp(ai.uid, mBoundApplication.appInfo.uid)
+                        ? !UserHandle.isSameApp(ai.uid, mBoundApplication.appInfo.uid)
                         : true);
         if ((flags&(Context.CONTEXT_INCLUDE_CODE
                 |Context.CONTEXT_IGNORE_SECURITY))
@@ -1786,7 +1908,8 @@
                 context.init(info, null, this);
                 context.getResources().updateConfiguration(
                         getConfiguration(), getDisplayMetricsLocked(
-                                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, false));
+                                Display.DEFAULT_DISPLAY,
+                                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO));
                 mSystemContext = context;
                 //Slog.i(TAG, "Created system resources " + context.getResources()
                 //        + ": " + context.getResources().getConfiguration());
@@ -1998,9 +2121,7 @@
                     + ", dir=" + r.packageInfo.getAppDir());
 
             if (activity != null) {
-                ContextImpl appContext = new ContextImpl();
-                appContext.init(r.packageInfo, r.token, this);
-                appContext.setOuterContext(activity);
+                Context appContext = createBaseContextForActivity(r, activity);
                 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                 Configuration config = new Configuration(mCompatConfiguration);
                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
@@ -2065,6 +2186,31 @@
         return activity;
     }
 
+    private Context createBaseContextForActivity(ActivityClientRecord r,
+            final Activity activity) {
+        ContextImpl appContext = new ContextImpl();
+        appContext.init(r.packageInfo, r.token, this);
+        appContext.setOuterContext(activity);
+
+        // For debugging purposes, if the activity's package name contains the value of
+        // the "debug.use-second-display" system property as a substring, then show
+        // its content on a secondary display if there is one.
+        Context baseContext = appContext;
+        String pkgName = SystemProperties.get("debug.second-display.pkg");
+        if (pkgName != null && !pkgName.isEmpty()
+                && r.packageInfo.mPackageName.contains(pkgName)) {
+            DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
+            for (int displayId : dm.getDisplayIds()) {
+                if (displayId != Display.DEFAULT_DISPLAY) {
+                    Display display = dm.getRealDisplay(displayId);
+                    baseContext = appContext.createDisplayContext(display);
+                    break;
+                }
+            }
+        }
+        return baseContext;
+    }
+
     private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
         // If we are getting ready to gc after going to the background, well
         // we are back active so skip it.
@@ -2086,7 +2232,8 @@
         if (a != null) {
             r.createdConfig = new Configuration(mConfiguration);
             Bundle oldState = r.state;
-            handleResumeActivity(r.token, false, r.isForward);
+            handleResumeActivity(r.token, false, r.isForward,
+                    !r.activity.mFinished && !r.startsNotResumed);
 
             if (!r.activity.mFinished && r.startsNotResumed) {
                 // The activity manager actually wants this one to start out
@@ -2250,12 +2397,31 @@
     private void handleCreateBackupAgent(CreateBackupAgentData data) {
         if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data);
 
+        // Sanity check the requested target package's uid against ours
+        try {
+            PackageInfo requestedPackage = getPackageManager().getPackageInfo(
+                    data.appInfo.packageName, 0, UserHandle.myUserId());
+            if (requestedPackage.applicationInfo.uid != Process.myUid()) {
+                Slog.w(TAG, "Asked to instantiate non-matching package "
+                        + data.appInfo.packageName);
+                return;
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Can't reach package manager", e);
+            return;
+        }
+
         // no longer idle; we have backup work to do
         unscheduleGcIdler();
 
         // instantiate the BackupAgent class named in the manifest
         LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
         String packageName = packageInfo.mPackageName;
+        if (packageName == null) {
+            Slog.d(TAG, "Asked to create backup agent for nonexistent package");
+            return;
+        }
+
         if (mBackupAgents.get(packageName) != null) {
             Slog.d(TAG, "BackupAgent " + "  for " + packageName
                     + " already exists");
@@ -2554,6 +2720,7 @@
                 r.activity.mStartedActivity = false;
             }
             try {
+                r.activity.mFragments.noteStateNotSaved();
                 if (r.pendingIntents != null) {
                     deliverNewIntents(r, r.pendingIntents);
                     r.pendingIntents = null;
@@ -2565,7 +2732,7 @@
                 r.activity.performResume();
 
                 EventLog.writeEvent(LOG_ON_RESUME_CALLED,
-                        r.activity.getComponentName().getClassName());
+                        UserHandle.myUserId(), r.activity.getComponentName().getClassName());
 
                 r.paused = false;
                 r.stopped = false;
@@ -2587,7 +2754,7 @@
             r.mPendingRemoveWindowManager.removeViewImmediate(r.mPendingRemoveWindow);
             IBinder wtoken = r.mPendingRemoveWindow.getWindowToken();
             if (wtoken != null) {
-                WindowManagerImpl.getDefault().closeAll(wtoken,
+                WindowManagerGlobal.getInstance().closeAll(wtoken,
                         r.activity.getClass().getName(), "Activity");
             }
         }
@@ -2595,7 +2762,8 @@
         r.mPendingRemoveWindowManager = null;
     }
 
-    final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
+    final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
+            boolean reallyResume) {
         // If we are getting ready to gc after going to the background, well
         // we are back active so skip it.
         unscheduleGcIdler();
@@ -2692,6 +2860,14 @@
             }
             r.onlyLocalRequest = false;
 
+            // Tell the activity manager we have resumed.
+            if (reallyResume) {
+                try {
+                    ActivityManagerNative.getDefault().activityResumed(token);
+                } catch (RemoteException ex) {
+                }
+            }
+
         } else {
             // If an exception was thrown when trying to resume, then
             // just end this activity.
@@ -2727,7 +2903,8 @@
 
                 // On platforms where we don't want thumbnails, set dims to (0,0)
                 if ((w > 0) && (h > 0)) {
-                    thumbnail = Bitmap.createBitmap(w, h, THUMBNAIL_FORMAT);
+                    thumbnail = Bitmap.createBitmap(r.activity.getResources().getDisplayMetrics(),
+                            w, h, THUMBNAIL_FORMAT);
                     thumbnail.eraseColor(0);
                 }
             }
@@ -2775,7 +2952,7 @@
             if (r.isPreHoneycomb()) {
                 QueuedWork.waitToFinish();
             }
-            
+
             // Tell the activity manager we have paused.
             try {
                 ActivityManagerNative.getDefault().activityPaused(token);
@@ -2823,7 +3000,8 @@
             // Now we are idle.
             r.activity.mCalled = false;
             mInstrumentation.callActivityOnPause(r.activity);
-            EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName());
+            EventLog.writeEvent(LOG_ON_PAUSE_CALLED, UserHandle.myUserId(),
+                    r.activity.getComponentName().getClassName());
             if (!r.activity.mCalled) {
                 throw new SuperNotCalledException(
                     "Activity " + r.intent.getComponent().toShortString() +
@@ -3121,7 +3299,7 @@
             apk.mCompatibilityInfo.set(data.info);
         }
         handleConfigurationChanged(mConfiguration, data.info);
-        WindowManagerImpl.getDefault().reportNewConfiguration(mConfiguration);
+        WindowManagerGlobal.getInstance().reportNewConfiguration(mConfiguration);
     }
 
     private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
@@ -3208,7 +3386,7 @@
                 try {
                     r.activity.mCalled = false;
                     mInstrumentation.callActivityOnPause(r.activity);
-                    EventLog.writeEvent(LOG_ON_PAUSE_CALLED,
+                    EventLog.writeEvent(LOG_ON_PAUSE_CALLED, UserHandle.myUserId(),
                             r.activity.getComponentName().getClassName());
                     if (!r.activity.mCalled) {
                         throw new SuperNotCalledException(
@@ -3310,7 +3488,7 @@
                     }
                 }
                 if (wtoken != null && r.mPendingRemoveWindow == null) {
-                    WindowManagerImpl.getDefault().closeAll(wtoken,
+                    WindowManagerGlobal.getInstance().closeAll(wtoken,
                             r.activity.getClass().getName(), "Activity");
                 }
                 r.activity.mDecor = null;
@@ -3322,7 +3500,7 @@
                 // by the app will leak.  Well we try to warning them a lot
                 // about leaking windows, because that is a bug, so if they are
                 // using this recreate facility then they get to live with leaks.
-                WindowManagerImpl.getDefault().closeAll(token,
+                WindowManagerGlobal.getInstance().closeAll(token,
                         r.activity.getClass().getName(), "Activity");
             }
 
@@ -3461,6 +3639,8 @@
         
         // If there was a pending configuration change, execute it first.
         if (changedConfig != null) {
+            mCurDefaultDisplayDpi = changedConfig.densityDpi;
+            updateDefaultDensity();
             handleConfigurationChanged(changedConfig, null);
         }
 
@@ -3534,39 +3714,45 @@
         }
     }
 
-    ArrayList<ComponentCallbacks2> collectComponentCallbacksLocked(
+    ArrayList<ComponentCallbacks2> collectComponentCallbacks(
             boolean allActivities, Configuration newConfig) {
         ArrayList<ComponentCallbacks2> callbacks
                 = new ArrayList<ComponentCallbacks2>();
 
-        if (mActivities.size() > 0) {
-            for (ActivityClientRecord ar : mActivities.values()) {
-                Activity a = ar.activity;
-                if (a != null) {
-                    Configuration thisConfig = applyConfigCompatMainThread(newConfig,
-                            ar.packageInfo.mCompatibilityInfo.getIfNeeded());
-                    if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
-                        // If the activity is currently resumed, its configuration
-                        // needs to change right now.
-                        callbacks.add(a);
-                    } else if (thisConfig != null) {
-                        // Otherwise, we will tell it about the change
-                        // the next time it is resumed or shown.  Note that
-                        // the activity manager may, before then, decide the
-                        // activity needs to be destroyed to handle its new
-                        // configuration.
-                        if (DEBUG_CONFIGURATION) {
-                            Slog.v(TAG, "Setting activity "
-                                    + ar.activityInfo.name + " newConfig=" + thisConfig);
+        synchronized (mPackages) {
+            final int N = mAllApplications.size();
+            for (int i=0; i<N; i++) {
+                callbacks.add(mAllApplications.get(i));
+            }
+            if (mActivities.size() > 0) {
+                for (ActivityClientRecord ar : mActivities.values()) {
+                    Activity a = ar.activity;
+                    if (a != null) {
+                        Configuration thisConfig = applyConfigCompatMainThread(mCurDefaultDisplayDpi,
+                                newConfig, ar.packageInfo.mCompatibilityInfo.getIfNeeded());
+                        if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
+                            // If the activity is currently resumed, its configuration
+                            // needs to change right now.
+                            callbacks.add(a);
+                        } else if (thisConfig != null) {
+                            // Otherwise, we will tell it about the change
+                            // the next time it is resumed or shown.  Note that
+                            // the activity manager may, before then, decide the
+                            // activity needs to be destroyed to handle its new
+                            // configuration.
+                            if (DEBUG_CONFIGURATION) {
+                                Slog.v(TAG, "Setting activity "
+                                        + ar.activityInfo.name + " newConfig=" + thisConfig);
+                            }
+                            ar.newConfig = thisConfig;
                         }
-                        ar.newConfig = thisConfig;
                     }
                 }
             }
-        }
-        if (mServices.size() > 0) {
-            for (Service service : mServices.values()) {
-                callbacks.add(service);
+            if (mServices.size() > 0) {
+                for (Service service : mServices.values()) {
+                    callbacks.add(service);
+                }
             }
         }
         synchronized (mProviderMap) {
@@ -3576,10 +3762,6 @@
                 }
             }
         }
-        final int N = mAllApplications.size();
-        for (int i=0; i<N; i++) {
-            callbacks.add(mAllApplications.get(i));
-        }
 
         return callbacks;
     }
@@ -3646,7 +3828,9 @@
             return false;
         }
         int changes = mResConfiguration.updateFrom(config);
-        DisplayMetrics dm = getDisplayMetricsLocked(null, true);
+        flushDisplayMetricsLocked();
+        DisplayMetrics defaultDisplayMetrics = getDisplayMetricsLocked(
+                Display.DEFAULT_DISPLAY, null);
 
         if (compat != null && (mResCompatibilityInfo == null ||
                 !mResCompatibilityInfo.equals(compat))) {
@@ -3661,22 +3845,41 @@
             Locale.setDefault(config.locale);
         }
 
-        Resources.updateSystemConfiguration(config, dm, compat);
+        Resources.updateSystemConfiguration(config, defaultDisplayMetrics, compat);
 
         ApplicationPackageManager.configurationChanged();
         //Slog.i(TAG, "Configuration changed in " + currentPackageName());
-        
-        Iterator<WeakReference<Resources>> it =
-            mActiveResources.values().iterator();
-        //Iterator<Map.Entry<String, WeakReference<Resources>>> it =
-        //    mActiveResources.entrySet().iterator();
+
+        Configuration tmpConfig = null;
+
+        Iterator<Map.Entry<ResourcesKey, WeakReference<Resources>>> it =
+                mActiveResources.entrySet().iterator();
         while (it.hasNext()) {
-            WeakReference<Resources> v = it.next();
-            Resources r = v.get();
+            Map.Entry<ResourcesKey, WeakReference<Resources>> entry = it.next();
+            Resources r = entry.getValue().get();
             if (r != null) {
                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
                         + r + " config to: " + config);
-                r.updateConfiguration(config, dm, compat);
+                int displayId = entry.getKey().mDisplayId;
+                boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+                DisplayMetrics dm = defaultDisplayMetrics;
+                Configuration overrideConfig = entry.getKey().mOverrideConfiguration;
+                if (!isDefaultDisplay || overrideConfig != null) {
+                    if (tmpConfig == null) {
+                        tmpConfig = new Configuration();
+                    }
+                    tmpConfig.setTo(config);
+                    if (!isDefaultDisplay) {
+                        dm = getDisplayMetricsLocked(displayId, null);
+                        applyNonDefaultDisplayMetricsToConfigurationLocked(dm, tmpConfig);
+                    }
+                    if (overrideConfig != null) {
+                        tmpConfig.updateFrom(overrideConfig);
+                    }
+                    r.updateConfiguration(tmpConfig, dm, compat);
+                } else {
+                    r.updateConfiguration(config, dm, compat);
+                }
                 //Slog.i(TAG, "Updated app resources " + v.getKey()
                 //        + " " + r + ": " + r.getConfiguration());
             } else {
@@ -3688,14 +3891,36 @@
         return changes != 0;
     }
 
-    final Configuration applyCompatConfiguration() {
+    final void applyNonDefaultDisplayMetricsToConfigurationLocked(
+            DisplayMetrics dm, Configuration config) {
+        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
+        config.densityDpi = dm.densityDpi;
+        config.screenWidthDp = (int)(dm.widthPixels / dm.density);
+        config.screenHeightDp = (int)(dm.heightPixels / dm.density);
+        int sl = Configuration.resetScreenLayout(config.screenLayout);
+        if (dm.widthPixels > dm.heightPixels) {
+            config.orientation = Configuration.ORIENTATION_LANDSCAPE;
+            config.screenLayout = Configuration.reduceScreenLayout(sl,
+                    config.screenWidthDp, config.screenHeightDp);
+        } else {
+            config.orientation = Configuration.ORIENTATION_PORTRAIT;
+            config.screenLayout = Configuration.reduceScreenLayout(sl,
+                    config.screenHeightDp, config.screenWidthDp);
+        }
+        config.smallestScreenWidthDp = config.screenWidthDp; // assume screen does not rotate
+        config.compatScreenWidthDp = config.screenWidthDp;
+        config.compatScreenHeightDp = config.screenHeightDp;
+        config.compatSmallestScreenWidthDp = config.smallestScreenWidthDp;
+    }
+
+    final Configuration applyCompatConfiguration(int displayDensity) {
         Configuration config = mConfiguration;
         if (mCompatConfiguration == null) {
             mCompatConfiguration = new Configuration();
         }
         mCompatConfiguration.setTo(mConfiguration);
         if (mResCompatibilityInfo != null && !mResCompatibilityInfo.supportsScreen()) {
-            mResCompatibilityInfo.applyToConfiguration(mCompatConfiguration);
+            mResCompatibilityInfo.applyToConfiguration(displayDensity, mCompatConfiguration);
             config = mCompatConfiguration;
         }
         return config;
@@ -3703,13 +3928,14 @@
 
     final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {
 
-        ArrayList<ComponentCallbacks2> callbacks = null;
         int configDiff = 0;
 
         synchronized (mPackages) {
             if (mPendingConfiguration != null) {
                 if (!mPendingConfiguration.isOtherSeqNewer(config)) {
                     config = mPendingConfiguration;
+                    mCurDefaultDisplayDpi = config.densityDpi;
+                    updateDefaultDensity();
                 }
                 mPendingConfiguration = null;
             }
@@ -3731,12 +3957,13 @@
             }
             configDiff = mConfiguration.diff(config);
             mConfiguration.updateFrom(config);
-            config = applyCompatConfiguration();
-            callbacks = collectComponentCallbacksLocked(false, config);
+            config = applyCompatConfiguration(mCurDefaultDisplayDpi);
         }
-        
+
+        ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
+
         // Cleanup hardware accelerated stuff
-        WindowManagerImpl.getDefault().trimLocalMemory();
+        WindowManagerGlobal.getInstance().trimLocalMemory();
 
         freeTextLayoutCachesIfNeeded(configDiff);
 
@@ -3847,11 +4074,7 @@
     }
         
     final void handleLowMemory() {
-        ArrayList<ComponentCallbacks2> callbacks;
-
-        synchronized (mPackages) {
-            callbacks = collectComponentCallbacksLocked(true, null);
-        }
+        ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
 
         final int N = callbacks.size();
         for (int i=0; i<N; i++) {
@@ -3876,20 +4099,17 @@
     final void handleTrimMemory(int level) {
         if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level);
 
-        final WindowManagerImpl windowManager = WindowManagerImpl.getDefault();
+        final WindowManagerGlobal windowManager = WindowManagerGlobal.getInstance();
         windowManager.startTrimMemory(level);
 
-        ArrayList<ComponentCallbacks2> callbacks;
-        synchronized (mPackages) {
-            callbacks = collectComponentCallbacksLocked(true, null);
-        }
+        ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
 
         final int N = callbacks.size();
         for (int i = 0; i < N; i++) {
             callbacks.get(i).onTrimMemory(level);
         }
 
-        windowManager.endTrimMemory();        
+        windowManager.endTrimMemory();
     }
 
     private void setupGraphicsSupport(LoadedApk info, File cacheDir) {
@@ -3910,8 +4130,20 @@
         } catch (RemoteException e) {
             // Ignore
         }
-    }    
-    
+    }
+
+    private void updateDefaultDensity() {
+        if (mCurDefaultDisplayDpi != Configuration.DENSITY_DPI_UNDEFINED
+                && mCurDefaultDisplayDpi != DisplayMetrics.DENSITY_DEVICE
+                && !mDensityCompatMode) {
+            Slog.i(TAG, "Switching default density from "
+                    + DisplayMetrics.DENSITY_DEVICE + " to "
+                    + mCurDefaultDisplayDpi);
+            DisplayMetrics.DENSITY_DEVICE = mCurDefaultDisplayDpi;
+            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
+        }
+    }
+
     private void handleBindApplication(AppBindData data) {
         mBoundApplication = data;
         mConfiguration = new Configuration(data.config);
@@ -3924,14 +4156,14 @@
 
         // send up app name; do this *before* waiting for debugger
         Process.setArgV0(data.processName);
-        android.ddm.DdmHandleAppName.setAppName(data.processName);
+        android.ddm.DdmHandleAppName.setAppName(data.processName,
+                                                UserHandle.myUserId());
 
         if (data.persistent) {
             // Persistent processes on low-memory devices do not get to
             // use hardware accelerated drawing, since this can add too much
             // overhead to the process.
-            Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
-            if (!ActivityManager.isHighEndGfx(display)) {
+            if (!ActivityManager.isHighEndGfx()) {
                 HardwareRenderer.disable(false);
             }
         }
@@ -3967,19 +4199,35 @@
          * in AppBindData can be safely assumed to be up to date
          */
         applyConfigurationToResourcesLocked(data.config, data.compatInfo);
-        applyCompatConfiguration();
+        mCurDefaultDisplayDpi = data.config.densityDpi;
+        applyCompatConfiguration(mCurDefaultDisplayDpi);
 
         data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
 
+        /**
+         * Switch this process to density compatibility mode if needed.
+         */
+        if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
+                == 0) {
+            mDensityCompatMode = true;
+            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
+        }
+        updateDefaultDensity();
+
         final ContextImpl appContext = new ContextImpl();
         appContext.init(data.info, null, this);
-        final File cacheDir = appContext.getCacheDir();
+        if (!Process.isIsolated()) {
+            final File cacheDir = appContext.getCacheDir();
 
-        // Provide a usable directory for temporary files
-        System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
-
-        setupGraphicsSupport(data.info, cacheDir);
-
+            if (cacheDir != null) {
+                // Provide a usable directory for temporary files
+                System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
+    
+                setupGraphicsSupport(data.info, cacheDir);
+            } else {
+                Log.e(TAG, "Unable to setupGraphicsSupport due to missing cache directory");
+            }
+        }
         /**
          * For system applications on userdebug/eng builds, log stack
          * traces of disk and network access to dropbox for analysis.
@@ -4001,14 +4249,6 @@
             StrictMode.enableDeathOnNetwork();
         }
 
-        /**
-         * Switch this process to density compatibility mode if needed.
-         */
-        if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
-                == 0) {
-            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
-        }
-
         if (data.debugMode != IApplicationThread.DEBUG_OFF) {
             // XXX should have option to change the port.
             Debug.changeDebugPort(8100);
@@ -4202,8 +4442,9 @@
         }
     }
 
-    public final IContentProvider acquireProvider(Context c, String name, boolean stable) {
-        IContentProvider provider = acquireExistingProvider(c, name, stable);
+    public final IContentProvider acquireProvider(
+            Context c, String auth, int userId, boolean stable) {
+        final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
         if (provider != null) {
             return provider;
         }
@@ -4217,11 +4458,11 @@
         IActivityManager.ContentProviderHolder holder = null;
         try {
             holder = ActivityManagerNative.getDefault().getContentProvider(
-                    getApplicationThread(), name, stable);
+                    getApplicationThread(), auth, userId, stable);
         } catch (RemoteException ex) {
         }
         if (holder == null) {
-            Slog.e(TAG, "Failed to find provider info for " + name);
+            Slog.e(TAG, "Failed to find provider info for " + auth);
             return null;
         }
 
@@ -4298,16 +4539,25 @@
         }
     }
 
-    public final IContentProvider acquireExistingProvider(Context c, String name,
-            boolean stable) {
+    public final IContentProvider acquireExistingProvider(
+            Context c, String auth, int userId, boolean stable) {
         synchronized (mProviderMap) {
-            ProviderClientRecord pr = mProviderMap.get(name);
+            final ProviderKey key = new ProviderKey(auth, userId);
+            final ProviderClientRecord pr = mProviderMap.get(key);
             if (pr == null) {
                 return null;
             }
 
             IContentProvider provider = pr.mProvider;
             IBinder jBinder = provider.asBinder();
+            if (!jBinder.isBinderAlive()) {
+                // The hosting process of the provider has died; we can't
+                // use this one.
+                Log.i(TAG, "Acquiring provider " + auth + " for user " + userId
+                        + ": existing object's process dead");
+                handleUnstableProviderDiedLocked(jBinder, true);
+                return null;
+            }
 
             // Only increment the ref count if we have one.  If we don't then the
             // provider is not reference counted and never needs to be released.
@@ -4448,50 +4698,57 @@
     }
 
     final void handleUnstableProviderDied(IBinder provider, boolean fromClient) {
-        synchronized(mProviderMap) {
-            ProviderRefCount prc = mProviderRefCountMap.get(provider);
-            if (prc != null) {
-                if (DEBUG_PROVIDER) Slog.v(TAG, "Cleaning up dead provider "
-                        + provider + " " + prc.holder.info.name);
-                mProviderRefCountMap.remove(provider);
-                if (prc.client != null && prc.client.mNames != null) {
-                    for (String name : prc.client.mNames) {
-                        ProviderClientRecord pr = mProviderMap.get(name);
-                        if (pr != null && pr.mProvider.asBinder() == provider) {
-                            Slog.i(TAG, "Removing dead content provider: " + name);
-                            mProviderMap.remove(name);
-                        }
+        synchronized (mProviderMap) {
+            handleUnstableProviderDiedLocked(provider, fromClient);
+        }
+    }
+
+    final void handleUnstableProviderDiedLocked(IBinder provider, boolean fromClient) {
+        ProviderRefCount prc = mProviderRefCountMap.get(provider);
+        if (prc != null) {
+            if (DEBUG_PROVIDER) Slog.v(TAG, "Cleaning up dead provider "
+                    + provider + " " + prc.holder.info.name);
+            mProviderRefCountMap.remove(provider);
+            if (prc.client != null && prc.client.mNames != null) {
+                for (String name : prc.client.mNames) {
+                    ProviderClientRecord pr = mProviderMap.get(name);
+                    if (pr != null && pr.mProvider.asBinder() == provider) {
+                        Slog.i(TAG, "Removing dead content provider: " + name);
+                        mProviderMap.remove(name);
                     }
                 }
-                if (fromClient) {
-                    // We found out about this due to execution in our client
-                    // code.  Tell the activity manager about it now, to ensure
-                    // that the next time we go to do anything with the provider
-                    // it knows it is dead (so we don't race with its death
-                    // notification).
-                    try {
-                        ActivityManagerNative.getDefault().unstableProviderDied(
-                                prc.holder.connection);
-                    } catch (RemoteException e) {
-                        //do nothing content provider object is dead any way
-                    }
+            }
+            if (fromClient) {
+                // We found out about this due to execution in our client
+                // code.  Tell the activity manager about it now, to ensure
+                // that the next time we go to do anything with the provider
+                // it knows it is dead (so we don't race with its death
+                // notification).
+                try {
+                    ActivityManagerNative.getDefault().unstableProviderDied(
+                            prc.holder.connection);
+                } catch (RemoteException e) {
+                    //do nothing content provider object is dead any way
                 }
             }
         }
     }
 
     private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,
-            ContentProvider localProvider,IActivityManager.ContentProviderHolder holder) {
-        String names[] = PATTERN_SEMICOLON.split(holder.info.authority);
-        ProviderClientRecord pcr = new ProviderClientRecord(names, provider,
-                localProvider, holder);
-        for (int i = 0; i < names.length; i++) {
-            ProviderClientRecord existing = mProviderMap.get(names[i]);
+            ContentProvider localProvider, IActivityManager.ContentProviderHolder holder) {
+        final String auths[] = PATTERN_SEMICOLON.split(holder.info.authority);
+        final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid);
+
+        final ProviderClientRecord pcr = new ProviderClientRecord(
+                auths, provider, localProvider, holder);
+        for (String auth : auths) {
+            final ProviderKey key = new ProviderKey(auth, userId);
+            final ProviderClientRecord existing = mProviderMap.get(key);
             if (existing != null) {
                 Slog.w(TAG, "Content provider " + pcr.mHolder.info.name
-                        + " already published as " + names[i]);
+                        + " already published as " + auth);
             } else {
-                mProviderMap.put(names[i], pcr);
+                mProviderMap.put(key, pcr);
             }
         }
         return pcr;
@@ -4643,7 +4900,8 @@
                     ensureJitEnabled();
                 }
             });
-            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
+            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
+                                                    UserHandle.myUserId());
             RuntimeInit.setApplicationObject(mAppThread.asBinder());
             IActivityManager mgr = ActivityManagerNative.getDefault();
             try {
@@ -4654,7 +4912,8 @@
         } else {
             // Don't set application object here -- if the system crashes,
             // we can't display an alert, we just want to die die die.
-            android.ddm.DdmHandleAppName.setAppName("system_process");
+            android.ddm.DdmHandleAppName.setAppName("system_process",
+                                                    UserHandle.myUserId());
             try {
                 mInstrumentation = new Instrumentation();
                 ContextImpl context = new ContextImpl();
@@ -4668,7 +4927,10 @@
                         "Unable to instantiate Application():" + e.toString(), e);
             }
         }
-        
+
+        // add dropbox logging to libcore
+        DropBox.setReporter(new DropBoxReporter());
+
         ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
             public void onConfigurationChanged(Configuration newConfig) {
                 synchronized (mPackages) {
@@ -4717,6 +4979,32 @@
         }
     }
 
+    private static class EventLoggingReporter implements EventLogger.Reporter {
+        @Override
+        public void report (int code, Object... list) {
+            EventLog.writeEvent(code, list);
+        }
+    }
+
+    private class DropBoxReporter implements DropBox.Reporter {
+
+        private DropBoxManager dropBox;
+
+        public DropBoxReporter() {
+            dropBox = (DropBoxManager) getSystemContext().getSystemService(Context.DROPBOX_SERVICE);
+        }
+
+        @Override
+        public void addData(String tag, byte[] data, int flags) {
+            dropBox.addData(tag, data, flags);
+        }
+
+        @Override
+        public void addText(String tag, String data) {
+            dropBox.addText(tag, data);
+        }
+    }
+
     public static void main(String[] args) {
         SamplingProfilerIntegration.start();
 
@@ -4725,6 +5013,11 @@
         // StrictMode) on debug builds, but using DropBox, not logs.
         CloseGuard.setEnabled(false);
 
+        Environment.initForCurrentUser();
+
+        // Set the reporter for event logging in libcore
+        EventLogger.setReporter(new EventLoggingReporter());
+
         Process.setArgV0("<pre-initialized>");
 
         Looper.prepareMainLooper();
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index e37b3fa..6ab2bd1 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -110,8 +110,9 @@
         this(context, theme, true);
     }
 
-    AlertDialog(Context context, int theme, boolean createContextWrapper) {
-        super(context, resolveDialogTheme(context, theme), createContextWrapper);
+    AlertDialog(Context context, int theme, boolean createThemeContextWrapper) {
+        super(context, resolveDialogTheme(context, theme), createThemeContextWrapper);
+
         mWindow.alwaysReadCloseOnTouchAttr();
         mAlert = new AlertController(getContext(), this, getWindow());
     }
@@ -566,7 +567,14 @@
         
         /**
          * Sets the callback that will be called if the dialog is canceled.
+         *
+         * <p>Even in a cancelable dialog, the dialog may be dismissed for reasons other than
+         * being canceled or one of the supplied choices being selected.
+         * If you are interested in listening for all cases where the dialog is dismissed
+         * and not just when it is canceled, see
+         * {@link #setOnDismissListener(android.content.DialogInterface.OnDismissListener) setOnDismissListener}.</p>
          * @see #setCancelable(boolean)
+         * @see #setOnDismissListener(android.content.DialogInterface.OnDismissListener)
          *
          * @return This Builder object to allow for chaining of calls to set methods
          */
@@ -576,6 +584,16 @@
         }
         
         /**
+         * Sets the callback that will be called when the dialog is dismissed for any reason.
+         *
+         * @return This Builder object to allow for chaining of calls to set methods
+         */
+        public Builder setOnDismissListener(OnDismissListener onDismissListener) {
+            P.mOnDismissListener = onDismissListener;
+            return this;
+        }
+
+        /**
          * Sets the callback that will be called if a key is dispatched to the dialog.
          *
          * @return This Builder object to allow for chaining of calls to set methods
@@ -917,6 +935,7 @@
                 dialog.setCanceledOnTouchOutside(true);
             }
             dialog.setOnCancelListener(P.mOnCancelListener);
+            dialog.setOnDismissListener(P.mOnDismissListener);
             if (P.mOnKeyListener != null) {
                 dialog.setOnKeyListener(P.mOnKeyListener);
             }
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index ebf42619..954476d 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -158,8 +158,8 @@
     public static ComponentName getErrorReportReceiver(Context context,
             String packageName, int appFlags) {
         // check if error reporting is enabled in secure settings
-        int enabled = Settings.Secure.getInt(context.getContentResolver(),
-                Settings.Secure.SEND_ACTION_APP_ERROR, 0);
+        int enabled = Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.SEND_ACTION_APP_ERROR, 0);
         if (enabled == 0) {
             return null;
         }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 191a696..7431765 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -41,8 +41,8 @@
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.UserInfo;
 import android.content.pm.ManifestDigest;
+import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
@@ -50,8 +50,8 @@
 import android.net.Uri;
 import android.os.Process;
 import android.os.RemoteException;
-import android.os.UserId;
 import android.util.Log;
+import android.view.Display;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -69,7 +69,7 @@
     public PackageInfo getPackageInfo(String packageName, int flags)
             throws NameNotFoundException {
         try {
-            PackageInfo pi = mPM.getPackageInfo(packageName, flags, UserId.myUserId());
+            PackageInfo pi = mPM.getPackageInfo(packageName, flags, mContext.getUserId());
             if (pi != null) {
                 return pi;
             }
@@ -199,7 +199,7 @@
     public ApplicationInfo getApplicationInfo(String packageName, int flags)
             throws NameNotFoundException {
         try {
-            ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags, UserId.myUserId());
+            ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags, mContext.getUserId());
             if (ai != null) {
                 return ai;
             }
@@ -214,7 +214,7 @@
     public ActivityInfo getActivityInfo(ComponentName className, int flags)
             throws NameNotFoundException {
         try {
-            ActivityInfo ai = mPM.getActivityInfo(className, flags, UserId.myUserId());
+            ActivityInfo ai = mPM.getActivityInfo(className, flags, mContext.getUserId());
             if (ai != null) {
                 return ai;
             }
@@ -229,7 +229,7 @@
     public ActivityInfo getReceiverInfo(ComponentName className, int flags)
             throws NameNotFoundException {
         try {
-            ActivityInfo ai = mPM.getReceiverInfo(className, flags, UserId.myUserId());
+            ActivityInfo ai = mPM.getReceiverInfo(className, flags, mContext.getUserId());
             if (ai != null) {
                 return ai;
             }
@@ -244,7 +244,7 @@
     public ServiceInfo getServiceInfo(ComponentName className, int flags)
             throws NameNotFoundException {
         try {
-            ServiceInfo si = mPM.getServiceInfo(className, flags, UserId.myUserId());
+            ServiceInfo si = mPM.getServiceInfo(className, flags, mContext.getUserId());
             if (si != null) {
                 return si;
             }
@@ -259,7 +259,7 @@
     public ProviderInfo getProviderInfo(ComponentName className, int flags)
             throws NameNotFoundException {
         try {
-            ProviderInfo pi = mPM.getProviderInfo(className, flags, UserId.myUserId());
+            ProviderInfo pi = mPM.getProviderInfo(className, flags, mContext.getUserId());
             if (pi != null) {
                 return pi;
             }
@@ -404,6 +404,12 @@
     @SuppressWarnings("unchecked")
     @Override
     public List<PackageInfo> getInstalledPackages(int flags) {
+        return getInstalledPackages(flags, mContext.getUserId());
+    }
+
+    /** @hide */
+    @Override
+    public List<PackageInfo> getInstalledPackages(int flags, int userId) {
         try {
             final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>();
             PackageInfo lastItem = null;
@@ -411,7 +417,7 @@
 
             do {
                 final String lastKey = lastItem != null ? lastItem.packageName : null;
-                slice = mPM.getInstalledPackages(flags, lastKey);
+                slice = mPM.getInstalledPackages(flags, lastKey, userId);
                 lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR);
             } while (!slice.isLastSlice());
 
@@ -424,7 +430,7 @@
     @SuppressWarnings("unchecked")
     @Override
     public List<ApplicationInfo> getInstalledApplications(int flags) {
-        int userId = UserId.getUserId(Process.myUid());
+        final int userId = mContext.getUserId();
         try {
             final List<ApplicationInfo> applicationInfos = new ArrayList<ApplicationInfo>();
             ApplicationInfo lastItem = null;
@@ -444,11 +450,17 @@
 
     @Override
     public ResolveInfo resolveActivity(Intent intent, int flags) {
+        return resolveActivityAsUser(intent, flags, mContext.getUserId());
+    }
+
+    @Override
+    public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) {
         try {
             return mPM.resolveIntent(
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                    flags, UserId.myUserId());
+                flags,
+                userId);
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -457,12 +469,19 @@
     @Override
     public List<ResolveInfo> queryIntentActivities(Intent intent,
                                                    int flags) {
+        return queryIntentActivitiesAsUser(intent, flags, mContext.getUserId());
+    }
+
+    /** @hide Same as above but for a specific user */
+    @Override
+    public List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent,
+                                                   int flags, int userId) {
         try {
             return mPM.queryIntentActivities(
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                 flags,
-                UserId.myUserId());
+                userId);
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -494,7 +513,23 @@
         try {
             return mPM.queryIntentActivityOptions(caller, specifics,
                                                   specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
-                                                  flags, UserId.myUserId());
+                                                  flags, mContext.getUserId());
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags, int userId) {
+        try {
+            return mPM.queryIntentReceivers(
+                intent,
+                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                flags,
+                userId);
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -502,15 +537,7 @@
 
     @Override
     public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
-        try {
-            return mPM.queryIntentReceivers(
-                intent,
-                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                flags,
-                UserId.myUserId());
-        } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
-        }
+        return queryBroadcastReceivers(intent, flags, mContext.getUserId());
     }
 
     @Override
@@ -520,7 +547,20 @@
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                 flags,
-                UserId.myUserId());
+                mContext.getUserId());
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) {
+        try {
+            return mPM.queryIntentServices(
+                intent,
+                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                flags,
+                userId);
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -528,22 +568,14 @@
 
     @Override
     public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
-        try {
-            return mPM.queryIntentServices(
-                intent,
-                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                flags,
-                UserId.myUserId());
-        } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
-        }
+        return queryIntentServicesAsUser(intent, flags, mContext.getUserId());
     }
 
     @Override
     public ProviderInfo resolveContentProvider(String name,
                                                int flags) {
         try {
-            return mPM.resolveContentProvider(name, flags, UserId.myUserId());
+            return mPM.resolveContentProvider(name, flags, mContext.getUserId());
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -712,8 +744,8 @@
             return mContext.mMainThread.getSystemContext().getResources();
         }
         Resources r = mContext.mMainThread.getTopLevelResources(
-            app.uid == Process.myUid() ? app.sourceDir
-            : app.publicSourceDir, mContext.mPackageInfo);
+                app.uid == Process.myUid() ? app.sourceDir : app.publicSourceDir,
+                        Display.DEFAULT_DISPLAY, null, mContext.mPackageInfo);
         if (r != null) {
             return r;
         }
@@ -726,6 +758,28 @@
             getApplicationInfo(appPackageName, 0));
     }
 
+    /** @hide */
+    @Override
+    public Resources getResourcesForApplicationAsUser(String appPackageName, int userId)
+            throws NameNotFoundException {
+        if (userId < 0) {
+            throw new IllegalArgumentException(
+                    "Call does not support special user #" + userId);
+        }
+        if ("system".equals(appPackageName)) {
+            return mContext.mMainThread.getSystemContext().getResources();
+        }
+        try {
+            ApplicationInfo ai = mPM.getApplicationInfo(appPackageName, 0, userId);
+            if (ai != null) {
+                return getResourcesForApplication(ai);
+            }
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+        throw new NameNotFoundException("Package " + appPackageName + " doesn't exist");
+    }
+
     int mCachedSafeMode = -1;
     @Override public boolean isSafeMode() {
         try {
@@ -984,6 +1038,33 @@
     }
 
     @Override
+	  public void installPackageWithVerificationAndEncryption(Uri packageURI,
+            IPackageInstallObserver observer, int flags, String installerPackageName,
+            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+        try {
+            mPM.installPackageWithVerificationAndEncryption(packageURI, observer, flags,
+                    installerPackageName, verificationParams, encryptionParams);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
+    public int installExistingPackage(String packageName)
+            throws NameNotFoundException {
+        try {
+            int res = mPM.installExistingPackage(packageName);
+            if (res == INSTALL_FAILED_INVALID_URI) {
+                throw new NameNotFoundException("Package " + packageName + " doesn't exist");
+            }
+            return res;
+        } catch (RemoteException e) {
+            // Should never happen!
+            throw new NameNotFoundException("Package " + packageName + " doesn't exist");
+        }
+    }
+
+    @Override
     public void verifyPendingInstall(int id, int response) {
         try {
             mPM.verifyPendingInstall(id, response);
@@ -993,6 +1074,16 @@
     }
 
     @Override
+    public void extendVerificationTimeout(int id, int verificationCodeAtTimeout,
+            long millisecondsToDelay) {
+        try {
+            mPM.extendVerificationTimeout(id, verificationCodeAtTimeout, millisecondsToDelay);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
     public void setInstallerPackageName(String targetPackage,
             String installerPackageName) {
         try {
@@ -1033,7 +1124,7 @@
     public void clearApplicationUserData(String packageName,
                                          IPackageDataObserver observer) {
         try {
-            mPM.clearApplicationUserData(packageName, observer, UserId.myUserId());
+            mPM.clearApplicationUserData(packageName, observer, mContext.getUserId());
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -1066,10 +1157,10 @@
     }
 
     @Override
-    public void getPackageSizeInfo(String packageName,
-                                   IPackageStatsObserver observer) {
+    public void getPackageSizeInfo(String packageName, int userHandle,
+            IPackageStatsObserver observer) {
         try {
-            mPM.getPackageSizeInfo(packageName, observer);
+            mPM.getPackageSizeInfo(packageName, userHandle, observer);
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -1106,7 +1197,17 @@
     public void addPreferredActivity(IntentFilter filter,
                                      int match, ComponentName[] set, ComponentName activity) {
         try {
-            mPM.addPreferredActivity(filter, match, set, activity);
+            mPM.addPreferredActivity(filter, match, set, activity, mContext.getUserId());
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
+    public void addPreferredActivity(IntentFilter filter, int match,
+            ComponentName[] set, ComponentName activity, int userId) {
+        try {
+            mPM.addPreferredActivity(filter, match, set, activity, userId);
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -1146,7 +1247,7 @@
     public void setComponentEnabledSetting(ComponentName componentName,
                                            int newState, int flags) {
         try {
-            mPM.setComponentEnabledSetting(componentName, newState, flags, UserId.myUserId());
+            mPM.setComponentEnabledSetting(componentName, newState, flags, mContext.getUserId());
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -1155,7 +1256,7 @@
     @Override
     public int getComponentEnabledSetting(ComponentName componentName) {
         try {
-            return mPM.getComponentEnabledSetting(componentName, UserId.myUserId());
+            return mPM.getComponentEnabledSetting(componentName, mContext.getUserId());
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -1166,7 +1267,7 @@
     public void setApplicationEnabledSetting(String packageName,
                                              int newState, int flags) {
         try {
-            mPM.setApplicationEnabledSetting(packageName, newState, flags, UserId.myUserId());
+            mPM.setApplicationEnabledSetting(packageName, newState, flags, mContext.getUserId());
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -1175,86 +1276,13 @@
     @Override
     public int getApplicationEnabledSetting(String packageName) {
         try {
-            return mPM.getApplicationEnabledSetting(packageName, UserId.myUserId());
+            return mPM.getApplicationEnabledSetting(packageName, mContext.getUserId());
         } catch (RemoteException e) {
             // Should never happen!
         }
         return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
     }
 
-    // Multi-user support
-
-    /**
-     * @hide
-     */
-    @Override
-    public UserInfo createUser(String name, int flags) {
-        try {
-            return mPM.createUser(name, flags);
-        } catch (RemoteException e) {
-            // Should never happen!
-        }
-        return null;
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public List<UserInfo> getUsers() {
-        try {
-            return mPM.getUsers();
-        } catch (RemoteException re) {
-            ArrayList<UserInfo> users = new ArrayList<UserInfo>();
-            UserInfo primary = new UserInfo(0, "Root!", UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY);
-            users.add(primary);
-            return users;
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public UserInfo getUser(int userId) {
-        try {
-            return mPM.getUser(userId);
-        } catch (RemoteException re) {
-            return null;
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public boolean removeUser(int id) {
-        try {
-            return mPM.removeUser(id);
-        } catch (RemoteException e) {
-            return false;
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public void updateUserName(int id, String name) {
-        try {
-            mPM.updateUserName(id, name);
-        } catch (RemoteException re) {
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public void updateUserFlags(int id, int flags) {
-        // TODO:
-    }
-
     /**
      * @hide
      */
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 8e6278d..63aa5f9 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -193,8 +193,9 @@
             String resultData = data.readString();
             Bundle resultExtras = data.readBundle();
             boolean sync = data.readInt() != 0;
+            int sendingUser = data.readInt();
             scheduleReceiver(intent, info, compatInfo, resultCode, resultData,
-                    resultExtras, sync);
+                    resultExtras, sync, sendingUser);
             return true;
         }
 
@@ -378,8 +379,9 @@
             Bundle extras = data.readBundle();
             boolean ordered = data.readInt() != 0;
             boolean sticky = data.readInt() != 0;
+            int sendingUser = data.readInt();
             scheduleRegisteredReceiver(receiver, intent,
-                    resultCode, dataStr, extras, ordered, sticky);
+                    resultCode, dataStr, extras, ordered, sticky, sendingUser);
             return true;
         }
 
@@ -755,7 +757,7 @@
     
     public final void scheduleReceiver(Intent intent, ActivityInfo info,
             CompatibilityInfo compatInfo, int resultCode, String resultData,
-            Bundle map, boolean sync) throws RemoteException {
+            Bundle map, boolean sync, int sendingUser) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         intent.writeToParcel(data, 0);
@@ -765,6 +767,7 @@
         data.writeString(resultData);
         data.writeBundle(map);
         data.writeInt(sync ? 1 : 0);
+        data.writeInt(sendingUser);
         mRemote.transact(SCHEDULE_RECEIVER_TRANSACTION, data, null,
                 IBinder.FLAG_ONEWAY);
         data.recycle();
@@ -991,8 +994,8 @@
     }
 
     public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
-            int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky)
-            throws RemoteException {
+            int resultCode, String dataStr, Bundle extras, boolean ordered,
+            boolean sticky, int sendingUser) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeStrongBinder(receiver.asBinder());
@@ -1002,6 +1005,7 @@
         data.writeBundle(extras);
         data.writeInt(ordered ? 1 : 0);
         data.writeInt(sticky ? 1 : 0);
+        data.writeInt(sendingUser);
         mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,
                 IBinder.FLAG_ONEWAY);
         data.recycle();
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 96814b7..1b1d341 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -20,6 +20,7 @@
 import android.os.Parcelable;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.LogWriter;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -94,11 +95,12 @@
     public BackStackRecord instantiate(FragmentManagerImpl fm) {
         BackStackRecord bse = new BackStackRecord(fm);
         int pos = 0;
+        int num = 0;
         while (pos < mOps.length) {
             BackStackRecord.Op op = new BackStackRecord.Op();
             op.cmd = mOps[pos++];
             if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
-                    "BSE " + bse + " set base fragment #" + mOps[pos]);
+                    "Instantiate " + bse + " op #" + num + " base fragment #" + mOps[pos]);
             int findex = mOps[pos++];
             if (findex >= 0) {
                 Fragment f = fm.mActive.get(findex);
@@ -115,12 +117,13 @@
                 op.removed = new ArrayList<Fragment>(N);
                 for (int i=0; i<N; i++) {
                     if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
-                            "BSE " + bse + " set remove fragment #" + mOps[pos]);
+                            "Instantiate " + bse + " set remove fragment #" + mOps[pos]);
                     Fragment r = fm.mActive.get(mOps[pos++]);
                     op.removed.add(r);
                 }
             }
             bse.addOp(op);
+            num++;
         }
         bse.mTransition = mTransition;
         bse.mTransitionStyle = mTransitionStyle;
@@ -168,7 +171,7 @@
  */
 final class BackStackRecord extends FragmentTransaction implements
         FragmentManager.BackStackEntry, Runnable {
-    static final String TAG = "BackStackEntry";
+    static final String TAG = FragmentManagerImpl.TAG;
 
     final FragmentManagerImpl mManager;
 
@@ -206,46 +209,69 @@
     boolean mAllowAddToBackStack = true;
     String mName;
     boolean mCommitted;
-    int mIndex;
+    int mIndex = -1;
 
     int mBreadCrumbTitleRes;
     CharSequence mBreadCrumbTitleText;
     int mBreadCrumbShortTitleRes;
     CharSequence mBreadCrumbShortTitleText;
 
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("BackStackEntry{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        if (mIndex >= 0) {
+            sb.append(" #");
+            sb.append(mIndex);
+        }
+        if (mName != null) {
+            sb.append(" ");
+            sb.append(mName);
+        }
+        sb.append("}");
+        return sb.toString();
+    }
+
     public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
-        writer.print(prefix); writer.print("mName="); writer.print(mName);
-                writer.print(" mIndex="); writer.print(mIndex);
-                writer.print(" mCommitted="); writer.println(mCommitted);
-        if (mTransition != FragmentTransaction.TRANSIT_NONE) {
-            writer.print(prefix); writer.print("mTransition=#");
-                    writer.print(Integer.toHexString(mTransition));
-                    writer.print(" mTransitionStyle=#");
-                    writer.println(Integer.toHexString(mTransitionStyle));
-        }
-        if (mEnterAnim != 0 || mExitAnim !=0) {
-            writer.print(prefix); writer.print("mEnterAnim=#");
-                    writer.print(Integer.toHexString(mEnterAnim));
-                    writer.print(" mExitAnim=#");
-                    writer.println(Integer.toHexString(mExitAnim));
-        }
-        if (mPopEnterAnim != 0 || mPopExitAnim !=0) {
-            writer.print(prefix); writer.print("mPopEnterAnim=#");
-                    writer.print(Integer.toHexString(mPopEnterAnim));
-                    writer.print(" mPopExitAnim=#");
-                    writer.println(Integer.toHexString(mPopExitAnim));
-        }
-        if (mBreadCrumbTitleRes != 0 || mBreadCrumbTitleText != null) {
-            writer.print(prefix); writer.print("mBreadCrumbTitleRes=#");
-                    writer.print(Integer.toHexString(mBreadCrumbTitleRes));
-                    writer.print(" mBreadCrumbTitleText=");
-                    writer.println(mBreadCrumbTitleText);
-        }
-        if (mBreadCrumbShortTitleRes != 0 || mBreadCrumbShortTitleText != null) {
-            writer.print(prefix); writer.print("mBreadCrumbShortTitleRes=#");
-                    writer.print(Integer.toHexString(mBreadCrumbShortTitleRes));
-                    writer.print(" mBreadCrumbShortTitleText=");
-                    writer.println(mBreadCrumbShortTitleText);
+        dump(prefix, writer, true);
+    }
+
+    void dump(String prefix, PrintWriter writer, boolean full) {
+        if (full) {
+            writer.print(prefix); writer.print("mName="); writer.print(mName);
+                    writer.print(" mIndex="); writer.print(mIndex);
+                    writer.print(" mCommitted="); writer.println(mCommitted);
+            if (mTransition != FragmentTransaction.TRANSIT_NONE) {
+                writer.print(prefix); writer.print("mTransition=#");
+                        writer.print(Integer.toHexString(mTransition));
+                        writer.print(" mTransitionStyle=#");
+                        writer.println(Integer.toHexString(mTransitionStyle));
+            }
+            if (mEnterAnim != 0 || mExitAnim !=0) {
+                writer.print(prefix); writer.print("mEnterAnim=#");
+                        writer.print(Integer.toHexString(mEnterAnim));
+                        writer.print(" mExitAnim=#");
+                        writer.println(Integer.toHexString(mExitAnim));
+            }
+            if (mPopEnterAnim != 0 || mPopExitAnim !=0) {
+                writer.print(prefix); writer.print("mPopEnterAnim=#");
+                        writer.print(Integer.toHexString(mPopEnterAnim));
+                        writer.print(" mPopExitAnim=#");
+                        writer.println(Integer.toHexString(mPopExitAnim));
+            }
+            if (mBreadCrumbTitleRes != 0 || mBreadCrumbTitleText != null) {
+                writer.print(prefix); writer.print("mBreadCrumbTitleRes=#");
+                        writer.print(Integer.toHexString(mBreadCrumbTitleRes));
+                        writer.print(" mBreadCrumbTitleText=");
+                        writer.println(mBreadCrumbTitleText);
+            }
+            if (mBreadCrumbShortTitleRes != 0 || mBreadCrumbShortTitleText != null) {
+                writer.print(prefix); writer.print("mBreadCrumbShortTitleRes=#");
+                        writer.print(Integer.toHexString(mBreadCrumbShortTitleRes));
+                        writer.print(" mBreadCrumbShortTitleText=");
+                        writer.println(mBreadCrumbShortTitleText);
+            }
         }
 
         if (mHead != null) {
@@ -254,21 +280,34 @@
             Op op = mHead;
             int num = 0;
             while (op != null) {
-                writer.print(prefix); writer.print("  Op #"); writer.print(num);
-                        writer.println(":");
-                writer.print(innerPrefix); writer.print("cmd="); writer.print(op.cmd);
-                        writer.print(" fragment="); writer.println(op.fragment);
-                if (op.enterAnim != 0 || op.exitAnim != 0) {
-                    writer.print(prefix); writer.print("enterAnim=#");
-                            writer.print(Integer.toHexString(op.enterAnim));
-                            writer.print(" exitAnim=#");
-                            writer.println(Integer.toHexString(op.exitAnim));
+                String cmdStr;
+                switch (op.cmd) {
+                    case OP_NULL: cmdStr="NULL"; break;
+                    case OP_ADD: cmdStr="ADD"; break;
+                    case OP_REPLACE: cmdStr="REPLACE"; break;
+                    case OP_REMOVE: cmdStr="REMOVE"; break;
+                    case OP_HIDE: cmdStr="HIDE"; break;
+                    case OP_SHOW: cmdStr="SHOW"; break;
+                    case OP_DETACH: cmdStr="DETACH"; break;
+                    case OP_ATTACH: cmdStr="ATTACH"; break;
+                    default: cmdStr="cmd=" + op.cmd; break;
                 }
-                if (op.popEnterAnim != 0 || op.popExitAnim != 0) {
-                    writer.print(prefix); writer.print("popEnterAnim=#");
-                            writer.print(Integer.toHexString(op.popEnterAnim));
-                            writer.print(" popExitAnim=#");
-                            writer.println(Integer.toHexString(op.popExitAnim));
+                writer.print(prefix); writer.print("  Op #"); writer.print(num);
+                        writer.print(": "); writer.print(cmdStr);
+                        writer.print(" "); writer.println(op.fragment);
+                if (full) {
+                    if (op.enterAnim != 0 || op.exitAnim != 0) {
+                        writer.print(innerPrefix); writer.print("enterAnim=#");
+                                writer.print(Integer.toHexString(op.enterAnim));
+                                writer.print(" exitAnim=#");
+                                writer.println(Integer.toHexString(op.exitAnim));
+                    }
+                    if (op.popEnterAnim != 0 || op.popExitAnim != 0) {
+                        writer.print(innerPrefix); writer.print("popEnterAnim=#");
+                                writer.print(Integer.toHexString(op.popEnterAnim));
+                                writer.print(" popExitAnim=#");
+                                writer.println(Integer.toHexString(op.popExitAnim));
+                    }
                 }
                 if (op.removed != null && op.removed.size() > 0) {
                     for (int i=0; i<op.removed.size(); i++) {
@@ -276,14 +315,17 @@
                         if (op.removed.size() == 1) {
                             writer.print("Removed: ");
                         } else {
-                            writer.println("Removed:");
-                            writer.print(innerPrefix); writer.print("  #"); writer.print(num);
+                            if (i == 0) {
+                                writer.println("Removed:");
+                            }
+                            writer.print(innerPrefix); writer.print("  #"); writer.print(i);
                                     writer.print(": "); 
                         }
                         writer.println(op.removed.get(i));
                     }
                 }
                 op = op.next;
+                num++;
             }
         }
     }
@@ -538,7 +580,12 @@
     
     int commitInternal(boolean allowStateLoss) {
         if (mCommitted) throw new IllegalStateException("commit already called");
-        if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Commit: " + this);
+        if (FragmentManagerImpl.DEBUG) {
+            Log.v(TAG, "Commit: " + this);
+            LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
+            PrintWriter pw = new PrintWriter(logw);
+            dump("  ", null, pw, null);
+        }
         mCommitted = true;
         if (mAddToBackStack) {
             mIndex = mManager.allocBackStackIndex(this);
@@ -641,7 +688,12 @@
     }
 
     public void popFromBackStack(boolean doStateMove) {
-        if (FragmentManagerImpl.DEBUG) Log.v(TAG, "popFromBackStack: " + this);
+        if (FragmentManagerImpl.DEBUG) {
+            Log.v(TAG, "popFromBackStack: " + this);
+            LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
+            PrintWriter pw = new PrintWriter(logw);
+            dump("  ", null, pw, null);
+        }
 
         bumpBackStackNesting(-1);
 
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 411f6d0..95b6bed 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -17,7 +17,9 @@
 package android.app;
 
 import com.android.internal.policy.PolicyManager;
+import com.android.internal.util.Preconditions;
 
+import android.bluetooth.BluetoothAdapter;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -34,8 +36,10 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.AssetManager;
 import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.DatabaseErrorHandler;
 import android.database.sqlite.SQLiteDatabase;
@@ -46,6 +50,7 @@
 import android.hardware.SensorManager;
 import android.hardware.SerialManager;
 import android.hardware.SystemSensorManager;
+import android.hardware.display.DisplayManager;
 import android.hardware.input.IInputManager;
 import android.hardware.input.InputManager;
 import android.hardware.usb.IUsbManager;
@@ -72,25 +77,31 @@
 import android.nfc.NfcManager;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Debug;
 import android.os.DropBoxManager;
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IPowerManager;
+import android.os.IUserManager;
 import android.os.Looper;
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.os.SystemVibrator;
+import android.os.UserManager;
 import android.os.storage.StorageManager;
 import android.telephony.TelephonyManager;
 import android.content.ClipboardManager;
 import android.util.AndroidRuntimeException;
 import android.util.Log;
+import android.util.Slog;
+import android.view.CompatibilityInfoHolder;
 import android.view.ContextThemeWrapper;
+import android.view.Display;
 import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityManager;
 import android.view.inputmethod.InputMethodManager;
@@ -122,21 +133,33 @@
     @Override
     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
             String broadcastPermission, Handler scheduler) {
-        throw new ReceiverCallNotAllowedException(
-                "IntentReceiver components are not allowed to register to receive intents");
-        //ex.fillInStackTrace();
-        //Log.e("IntentReceiver", ex.getMessage(), ex);
-        //return mContext.registerReceiver(receiver, filter, broadcastPermission,
-        //        scheduler);
+        if (receiver == null) {
+            // Allow retrieving current sticky broadcast; this is safe since we
+            // aren't actually registering a receiver.
+            return super.registerReceiver(null, filter, broadcastPermission, scheduler);
+        } else {
+            throw new ReceiverCallNotAllowedException(
+                    "BroadcastReceiver components are not allowed to register to receive intents");
+        }
+    }
+
+    @Override
+    public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+            IntentFilter filter, String broadcastPermission, Handler scheduler) {
+        if (receiver == null) {
+            // Allow retrieving current sticky broadcast; this is safe since we
+            // aren't actually registering a receiver.
+            return super.registerReceiverAsUser(null, user, filter, broadcastPermission, scheduler);
+        } else {
+            throw new ReceiverCallNotAllowedException(
+                    "BroadcastReceiver components are not allowed to register to receive intents");
+        }
     }
 
     @Override
     public boolean bindService(Intent service, ServiceConnection conn, int flags) {
         throw new ReceiverCallNotAllowedException(
-                "IntentReceiver components are not allowed to bind to services");
-        //ex.fillInStackTrace();
-        //Log.e("IntentReceiver", ex.getMessage(), ex);
-        //return mContext.bindService(service, interfaceName, conn, flags);
+                "BroadcastReceiver components are not allowed to bind to services");
     }
 }
 
@@ -161,8 +184,10 @@
     private int mThemeResource = 0;
     private Resources.Theme mTheme = null;
     private PackageManager mPackageManager;
+    private Display mDisplay; // may be null if default display
     private Context mReceiverRestrictedContext = null;
     private boolean mRestricted;
+    private UserHandle mUser;
 
     private final Object mSync = new Object();
 
@@ -294,6 +319,11 @@
                     return new MediaRouter(ctx);
                 }});
 
+        registerService(BLUETOOTH_SERVICE, new ServiceFetcher() {
+                public Object createService(ContextImpl ctx) {
+                    return BluetoothAdapter.getDefaultAdapter();
+                }});
+
         registerService(CLIPBOARD_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
                     return new ClipboardManager(ctx.getOuterContext(),
@@ -337,6 +367,12 @@
                     return InputManager.getInstance();
                 }});
 
+        registerService(DISPLAY_SERVICE, new ServiceFetcher() {
+                @Override
+                public Object createService(ContextImpl ctx) {
+                    return new DisplayManager(ctx.getOuterContext());
+                }});
+
         registerService(INPUT_METHOD_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
                     return InputMethodManager.getInstance(ctx);
@@ -403,7 +439,8 @@
                 public Object createService(ContextImpl ctx) {
                     IBinder b = ServiceManager.getService(POWER_SERVICE);
                     IPowerManager service = IPowerManager.Stub.asInterface(b);
-                    return new PowerManager(service, ctx.mMainThread.getHandler());
+                    return new PowerManager(ctx.getOuterContext(),
+                            service, ctx.mMainThread.getHandler());
                 }});
 
         registerService(SEARCH_SERVICE, new ServiceFetcher() {
@@ -471,7 +508,7 @@
                 public Object createService(ContextImpl ctx) {
                     IBinder b = ServiceManager.getService(WIFI_SERVICE);
                     IWifiManager service = IWifiManager.Stub.asInterface(b);
-                    return new WifiManager(service, ctx.mMainThread.getHandler());
+                    return new WifiManager(ctx.getOuterContext(), service);
                 }});
 
         registerService(WIFI_P2P_SERVICE, new ServiceFetcher() {
@@ -483,8 +520,21 @@
 
         registerService(WINDOW_SERVICE, new ServiceFetcher() {
                 public Object getService(ContextImpl ctx) {
-                    return WindowManagerImpl.getDefault(ctx.mPackageInfo.mCompatibilityInfo);
+                    Display display = ctx.mDisplay;
+                    if (display == null) {
+                        DisplayManager dm = (DisplayManager)ctx.getOuterContext().getSystemService(
+                                Context.DISPLAY_SERVICE);
+                        display = dm.getDisplay(Display.DEFAULT_DISPLAY);
+                    }
+                    return new WindowManagerImpl(display);
                 }});
+
+        registerService(USER_SERVICE, new ServiceFetcher() {
+            public Object getService(ContextImpl ctx) {
+                IBinder b = ServiceManager.getService(USER_SERVICE);
+                IUserManager service = IUserManager.Stub.asInterface(b);
+                return new UserManager(ctx, service);
+            }});
     }
 
     static ContextImpl getImpl(Context context) {
@@ -503,7 +553,7 @@
 
     @Override
     public AssetManager getAssets() {
-        return mResources.getAssets();
+        return getResources().getAssets();
     }
 
     @Override
@@ -743,7 +793,7 @@
             }
             if (!mCacheDir.exists()) {
                 if(!mCacheDir.mkdirs()) {
-                    Log.w(TAG, "Unable to create cache directory");
+                    Log.w(TAG, "Unable to create cache directory " + mCacheDir.getAbsolutePath());
                     return null;
                 }
                 FileUtils.setPermissions(
@@ -877,11 +927,19 @@
 
     @Override
     public void startActivity(Intent intent) {
+        warnIfCallingFromSystemProcess();
         startActivity(intent, null);
     }
 
+    /** @hide */
+    @Override
+    public void startActivityAsUser(Intent intent, UserHandle user) {
+        startActivityAsUser(intent, null, user);
+    }
+
     @Override
     public void startActivity(Intent intent, Bundle options) {
+        warnIfCallingFromSystemProcess();
         if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
             throw new AndroidRuntimeException(
                     "Calling startActivity() from outside of an Activity "
@@ -893,13 +951,42 @@
             (Activity)null, intent, -1, options);
     }
 
+    /** @hide */
+    @Override
+    public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) {
+        try {
+            ActivityManagerNative.getDefault().startActivityAsUser(
+                mMainThread.getApplicationThread(), intent,
+                intent.resolveTypeIfNeeded(getContentResolver()),
+                null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null, options,
+                user.getIdentifier());
+        } catch (RemoteException re) {
+        }
+    }
+
     @Override
     public void startActivities(Intent[] intents) {
+        warnIfCallingFromSystemProcess();
         startActivities(intents, null);
     }
 
+    /** @hide */
+    @Override
+    public void startActivitiesAsUser(Intent[] intents, Bundle options, UserHandle userHandle) {
+        if ((intents[0].getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
+            throw new AndroidRuntimeException(
+                    "Calling startActivities() from outside of an Activity "
+                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag on first Intent."
+                    + " Is this really what you want?");
+        }
+        mMainThread.getInstrumentation().execStartActivitiesAsUser(
+            getOuterContext(), mMainThread.getApplicationThread(), null,
+            (Activity)null, intents, options, userHandle.getIdentifier());
+    }
+
     @Override
     public void startActivities(Intent[] intents, Bundle options) {
+        warnIfCallingFromSystemProcess();
         if ((intents[0].getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
             throw new AndroidRuntimeException(
                     "Calling startActivities() from outside of an Activity "
@@ -942,39 +1029,28 @@
 
     @Override
     public void sendBroadcast(Intent intent) {
+        warnIfCallingFromSystemProcess();
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         try {
             intent.setAllowFds(false);
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, null,
                 Activity.RESULT_OK, null, null, null, false, false,
-                Binder.getOrigCallingUser());
-        } catch (RemoteException e) {
-        }
-    }
-
-    /** @hide */
-    @Override
-    public void sendBroadcast(Intent intent, int userId) {
-        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
-        try {
-            intent.setAllowFds(false);
-            ActivityManagerNative.getDefault().broadcastIntent(mMainThread.getApplicationThread(),
-                    intent, resolvedType, null, Activity.RESULT_OK, null, null, null, false, false,
-                    userId);
+                getUserId());
         } catch (RemoteException e) {
         }
     }
 
     @Override
     public void sendBroadcast(Intent intent, String receiverPermission) {
+        warnIfCallingFromSystemProcess();
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         try {
             intent.setAllowFds(false);
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, null,
                 Activity.RESULT_OK, null, null, receiverPermission, false, false,
-                Binder.getOrigCallingUser());
+                getUserId());
         } catch (RemoteException e) {
         }
     }
@@ -982,13 +1058,14 @@
     @Override
     public void sendOrderedBroadcast(Intent intent,
             String receiverPermission) {
+        warnIfCallingFromSystemProcess();
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         try {
             intent.setAllowFds(false);
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, null,
                 Activity.RESULT_OK, null, null, receiverPermission, true, false,
-                Binder.getOrigCallingUser());
+                getUserId());
         } catch (RemoteException e) {
         }
     }
@@ -998,6 +1075,7 @@
             String receiverPermission, BroadcastReceiver resultReceiver,
             Handler scheduler, int initialCode, String initialData,
             Bundle initialExtras) {
+        warnIfCallingFromSystemProcess();
         IIntentReceiver rd = null;
         if (resultReceiver != null) {
             if (mPackageInfo != null) {
@@ -1021,20 +1099,79 @@
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, rd,
                 initialCode, initialData, initialExtras, receiverPermission,
-                true, false, Binder.getOrigCallingUser());
+                true, false, getUserId());
+        } catch (RemoteException e) {
+        }
+    }
+
+    @Override
+    public void sendBroadcastAsUser(Intent intent, UserHandle user) {
+        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
+        try {
+            intent.setAllowFds(false);
+            ActivityManagerNative.getDefault().broadcastIntent(mMainThread.getApplicationThread(),
+                    intent, resolvedType, null, Activity.RESULT_OK, null, null, null, false, false,
+                    user.getIdentifier());
+        } catch (RemoteException e) {
+        }
+    }
+
+    @Override
+    public void sendBroadcastAsUser(Intent intent, UserHandle user,
+            String receiverPermission) {
+        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
+        try {
+            intent.setAllowFds(false);
+            ActivityManagerNative.getDefault().broadcastIntent(
+                mMainThread.getApplicationThread(), intent, resolvedType, null,
+                Activity.RESULT_OK, null, null, receiverPermission, false, false,
+                user.getIdentifier());
+        } catch (RemoteException e) {
+        }
+    }
+
+    @Override
+    public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
+            String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
+            int initialCode, String initialData, Bundle initialExtras) {
+        IIntentReceiver rd = null;
+        if (resultReceiver != null) {
+            if (mPackageInfo != null) {
+                if (scheduler == null) {
+                    scheduler = mMainThread.getHandler();
+                }
+                rd = mPackageInfo.getReceiverDispatcher(
+                    resultReceiver, getOuterContext(), scheduler,
+                    mMainThread.getInstrumentation(), false);
+            } else {
+                if (scheduler == null) {
+                    scheduler = mMainThread.getHandler();
+                }
+                rd = new LoadedApk.ReceiverDispatcher(
+                        resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
+            }
+        }
+        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
+        try {
+            intent.setAllowFds(false);
+            ActivityManagerNative.getDefault().broadcastIntent(
+                mMainThread.getApplicationThread(), intent, resolvedType, rd,
+                initialCode, initialData, initialExtras, receiverPermission,
+                true, false, user.getIdentifier());
         } catch (RemoteException e) {
         }
     }
 
     @Override
     public void sendStickyBroadcast(Intent intent) {
+        warnIfCallingFromSystemProcess();
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         try {
             intent.setAllowFds(false);
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, null,
                 Activity.RESULT_OK, null, null, null, false, true,
-                Binder.getOrigCallingUser());
+                getUserId());
         } catch (RemoteException e) {
         }
     }
@@ -1044,6 +1181,67 @@
             BroadcastReceiver resultReceiver,
             Handler scheduler, int initialCode, String initialData,
             Bundle initialExtras) {
+        warnIfCallingFromSystemProcess();
+        IIntentReceiver rd = null;
+        if (resultReceiver != null) {
+            if (mPackageInfo != null) {
+                if (scheduler == null) {
+                    scheduler = mMainThread.getHandler();
+                }
+                rd = mPackageInfo.getReceiverDispatcher(
+                    resultReceiver, getOuterContext(), scheduler,
+                    mMainThread.getInstrumentation(), false);
+            } else {
+                if (scheduler == null) {
+                    scheduler = mMainThread.getHandler();
+                }
+                rd = new LoadedApk.ReceiverDispatcher(
+                        resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
+            }
+        }
+        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
+        try {
+            intent.setAllowFds(false);
+            ActivityManagerNative.getDefault().broadcastIntent(
+                mMainThread.getApplicationThread(), intent, resolvedType, rd,
+                initialCode, initialData, initialExtras, null,
+                true, true, getUserId());
+        } catch (RemoteException e) {
+        }
+    }
+
+    @Override
+    public void removeStickyBroadcast(Intent intent) {
+        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
+        if (resolvedType != null) {
+            intent = new Intent(intent);
+            intent.setDataAndType(intent.getData(), resolvedType);
+        }
+        try {
+            intent.setAllowFds(false);
+            ActivityManagerNative.getDefault().unbroadcastIntent(
+                    mMainThread.getApplicationThread(), intent, getUserId());
+        } catch (RemoteException e) {
+        }
+    }
+
+    @Override
+    public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
+        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
+        try {
+            intent.setAllowFds(false);
+            ActivityManagerNative.getDefault().broadcastIntent(
+                mMainThread.getApplicationThread(), intent, resolvedType, null,
+                Activity.RESULT_OK, null, null, null, false, true, user.getIdentifier());
+        } catch (RemoteException e) {
+        }
+    }
+
+    @Override
+    public void sendStickyOrderedBroadcastAsUser(Intent intent,
+            UserHandle user, BroadcastReceiver resultReceiver,
+            Handler scheduler, int initialCode, String initialData,
+            Bundle initialExtras) {
         IIntentReceiver rd = null;
         if (resultReceiver != null) {
             if (mPackageInfo != null) {
@@ -1067,13 +1265,13 @@
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, rd,
                 initialCode, initialData, initialExtras, null,
-                true, true, Binder.getOrigCallingUser());
+                true, true, user.getIdentifier());
         } catch (RemoteException e) {
         }
     }
 
     @Override
-    public void removeStickyBroadcast(Intent intent) {
+    public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         if (resolvedType != null) {
             intent = new Intent(intent);
@@ -1082,7 +1280,7 @@
         try {
             intent.setAllowFds(false);
             ActivityManagerNative.getDefault().unbroadcastIntent(
-                    mMainThread.getApplicationThread(), intent, Binder.getOrigCallingUser());
+                    mMainThread.getApplicationThread(), intent, user.getIdentifier());
         } catch (RemoteException e) {
         }
     }
@@ -1095,11 +1293,18 @@
     @Override
     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
             String broadcastPermission, Handler scheduler) {
-        return registerReceiverInternal(receiver, filter, broadcastPermission,
-                scheduler, getOuterContext());
+        return registerReceiverInternal(receiver, getUserId(),
+                filter, broadcastPermission, scheduler, getOuterContext());
     }
 
-    private Intent registerReceiverInternal(BroadcastReceiver receiver,
+    @Override
+    public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+            IntentFilter filter, String broadcastPermission, Handler scheduler) {
+        return registerReceiverInternal(receiver, user.getIdentifier(),
+                filter, broadcastPermission, scheduler, getOuterContext());
+    }
+
+    private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
             IntentFilter filter, String broadcastPermission,
             Handler scheduler, Context context) {
         IIntentReceiver rd = null;
@@ -1122,7 +1327,7 @@
         try {
             return ActivityManagerNative.getDefault().registerReceiver(
                     mMainThread.getApplicationThread(), mBasePackageName,
-                    rd, filter, broadcastPermission);
+                    rd, filter, broadcastPermission, userId);
         } catch (RemoteException e) {
             return null;
         }
@@ -1144,15 +1349,33 @@
 
     @Override
     public ComponentName startService(Intent service) {
+        warnIfCallingFromSystemProcess();
+        return startServiceAsUser(service, mUser);
+    }
+
+    @Override
+    public boolean stopService(Intent service) {
+        warnIfCallingFromSystemProcess();
+        return stopServiceAsUser(service, mUser);
+    }
+
+    @Override
+    public ComponentName startServiceAsUser(Intent service, UserHandle user) {
         try {
             service.setAllowFds(false);
             ComponentName cn = ActivityManagerNative.getDefault().startService(
                 mMainThread.getApplicationThread(), service,
-                service.resolveTypeIfNeeded(getContentResolver()));
-            if (cn != null && cn.getPackageName().equals("!")) {
-                throw new SecurityException(
-                        "Not allowed to start service " + service
-                        + " without permission " + cn.getClassName());
+                service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
+            if (cn != null) {
+                if (cn.getPackageName().equals("!")) {
+                    throw new SecurityException(
+                            "Not allowed to start service " + service
+                            + " without permission " + cn.getClassName());
+                } else if (cn.getPackageName().equals("!!")) {
+                    throw new SecurityException(
+                            "Unable to start service " + service
+                            + ": " + cn.getClassName());
+                }
             }
             return cn;
         } catch (RemoteException e) {
@@ -1161,12 +1384,12 @@
     }
 
     @Override
-    public boolean stopService(Intent service) {
+    public boolean stopServiceAsUser(Intent service, UserHandle user) {
         try {
             service.setAllowFds(false);
             int res = ActivityManagerNative.getDefault().stopService(
                 mMainThread.getApplicationThread(), service,
-                service.resolveTypeIfNeeded(getContentResolver()));
+                service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
             if (res < 0) {
                 throw new SecurityException(
                         "Not allowed to stop service " + service);
@@ -1180,13 +1403,17 @@
     @Override
     public boolean bindService(Intent service, ServiceConnection conn,
             int flags) {
-        return bindService(service, conn, flags, UserId.getUserId(Process.myUid()));
+        warnIfCallingFromSystemProcess();
+        return bindService(service, conn, flags, UserHandle.getUserId(Process.myUid()));
     }
 
     /** @hide */
     @Override
-    public boolean bindService(Intent service, ServiceConnection conn, int flags, int userId) {
+    public boolean bindService(Intent service, ServiceConnection conn, int flags, int userHandle) {
         IServiceConnection sd;
+        if (conn == null) {
+            throw new IllegalArgumentException("connection is null");
+        }
         if (mPackageInfo != null) {
             sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
                     mMainThread.getHandler(), flags);
@@ -1204,7 +1431,7 @@
             int res = ActivityManagerNative.getDefault().bindService(
                 mMainThread.getApplicationThread(), getActivityToken(),
                 service, service.resolveTypeIfNeeded(getContentResolver()),
-                sd, flags, userId);
+                sd, flags, userHandle);
             if (res < 0) {
                 throw new SecurityException(
                         "Not allowed to bind to service " + service);
@@ -1217,6 +1444,9 @@
 
     @Override
     public void unbindService(ServiceConnection conn) {
+        if (conn == null) {
+            throw new IllegalArgumentException("connection is null");
+        }
         if (mPackageInfo != null) {
             IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
                     getOuterContext(), conn);
@@ -1237,7 +1467,7 @@
                 arguments.setAllowFds(false);
             }
             return ActivityManagerNative.getDefault().startInstrumentation(
-                    className, profileFile, 0, arguments, null);
+                    className, profileFile, 0, arguments, null, getUserId());
         } catch (RemoteException e) {
             // System has crashed, nothing we can do.
         }
@@ -1312,7 +1542,7 @@
                     (message != null ? (message + ": ") : "") +
                     (selfToo
                      ? "Neither user " + uid + " nor current process has "
-                     : "User " + uid + " does not have ") +
+                     : "uid " + uid + " does not have ") +
                     permission +
                     ".");
         }
@@ -1482,21 +1712,37 @@
                       message);
     }
 
+    private void warnIfCallingFromSystemProcess() {
+        if (Process.myUid() == Process.SYSTEM_UID) {
+            Slog.w(TAG, "Calling a method in the system process without a qualified user: "
+                    + Debug.getCallers(3));
+        }
+    }
+
     @Override
     public Context createPackageContext(String packageName, int flags)
-        throws PackageManager.NameNotFoundException {
+            throws NameNotFoundException {
+        return createPackageContextAsUser(packageName, flags,
+                mUser != null ? mUser : Process.myUserHandle());
+    }
+
+    @Override
+    public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
+            throws NameNotFoundException {
         if (packageName.equals("system") || packageName.equals("android")) {
             final ContextImpl context = new ContextImpl(mMainThread.getSystemContext());
-            context.mBasePackageName = mBasePackageName;
+            context.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
+            context.init(mPackageInfo, null, mMainThread, mResources, mBasePackageName, user);
             return context;
         }
 
         LoadedApk pi =
-            mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(), flags);
+            mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(), flags,
+                    user.getIdentifier());
         if (pi != null) {
             ContextImpl c = new ContextImpl();
             c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
-            c.init(pi, null, mMainThread, mResources, mBasePackageName);
+            c.init(pi, null, mMainThread, mResources, mBasePackageName, user);
             if (c.mResources != null) {
                 return c;
             }
@@ -1508,10 +1754,55 @@
     }
 
     @Override
+    public Context createConfigurationContext(Configuration overrideConfiguration) {
+        if (overrideConfiguration == null) {
+            throw new IllegalArgumentException("overrideConfiguration must not be null");
+        }
+
+        ContextImpl c = new ContextImpl();
+        c.init(mPackageInfo, null, mMainThread);
+        c.mResources = mMainThread.getTopLevelResources(
+                mPackageInfo.getResDir(),
+                getDisplayId(), overrideConfiguration,
+                mResources.getCompatibilityInfo());
+        return c;
+    }
+
+    @Override
+    public Context createDisplayContext(Display display) {
+        if (display == null) {
+            throw new IllegalArgumentException("display must not be null");
+        }
+
+        int displayId = display.getDisplayId();
+        CompatibilityInfo ci = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+        CompatibilityInfoHolder cih = getCompatibilityInfo(displayId);
+        if (cih != null) {
+            ci = cih.get();
+        }
+
+        ContextImpl context = new ContextImpl();
+        context.init(mPackageInfo, null, mMainThread);
+        context.mDisplay = display;
+        context.mResources = mMainThread.getTopLevelResources(
+                mPackageInfo.getResDir(), displayId, null, ci);
+        return context;
+    }
+
+    private int getDisplayId() {
+        return mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
+    }
+
+    @Override
     public boolean isRestricted() {
         return mRestricted;
     }
 
+    @Override
+    public CompatibilityInfoHolder getCompatibilityInfo(int displayId) {
+        return displayId == Display.DEFAULT_DISPLAY ? mPackageInfo.mCompatibilityInfo : null;
+    }
+
     private File getDataDirFile() {
         if (mPackageInfo != null) {
             return mPackageInfo.getDataDirFile();
@@ -1531,9 +1822,14 @@
         return file;
     }
 
+    /** {@hide} */
+    public int getUserId() {
+        return mUser.getIdentifier();
+    }
+
     static ContextImpl createSystemContext(ActivityThread mainThread) {
-        ContextImpl context = new ContextImpl();
-        context.init(Resources.getSystem(), mainThread);
+        final ContextImpl context = new ContextImpl();
+        context.init(Resources.getSystem(), mainThread, Process.myUserHandle());
         return context;
     }
 
@@ -1553,17 +1849,17 @@
         mResources = context.mResources;
         mMainThread = context.mMainThread;
         mContentResolver = context.mContentResolver;
+        mUser = context.mUser;
+        mDisplay = context.mDisplay;
         mOuterContext = this;
     }
 
-    final void init(LoadedApk packageInfo,
-            IBinder activityToken, ActivityThread mainThread) {
-        init(packageInfo, activityToken, mainThread, null, null);
+    final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread) {
+        init(packageInfo, activityToken, mainThread, null, null, Process.myUserHandle());
     }
 
-    final void init(LoadedApk packageInfo,
-                IBinder activityToken, ActivityThread mainThread,
-                Resources container, String basePackageName) {
+    final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread,
+            Resources container, String basePackageName, UserHandle user) {
         mPackageInfo = packageInfo;
         mBasePackageName = basePackageName != null ? basePackageName : packageInfo.mPackageName;
         mResources = mPackageInfo.getResources(mainThread);
@@ -1576,20 +1872,22 @@
                         " compatiblity info:" + container.getDisplayMetrics());
             }
             mResources = mainThread.getTopLevelResources(
-                    mPackageInfo.getResDir(), container.getCompatibilityInfo());
+                    mPackageInfo.getResDir(), Display.DEFAULT_DISPLAY,
+                    null, container.getCompatibilityInfo());
         }
         mMainThread = mainThread;
-        mContentResolver = new ApplicationContentResolver(this, mainThread);
-
-        setActivityToken(activityToken);
+        mActivityToken = activityToken;
+        mContentResolver = new ApplicationContentResolver(this, mainThread, user);
+        mUser = user;
     }
 
-    final void init(Resources resources, ActivityThread mainThread) {
+    final void init(Resources resources, ActivityThread mainThread, UserHandle user) {
         mPackageInfo = null;
         mBasePackageName = null;
         mResources = resources;
         mMainThread = mainThread;
-        mContentResolver = new ApplicationContentResolver(this, mainThread);
+        mContentResolver = new ApplicationContentResolver(this, mainThread, user);
+        mUser = user;
     }
 
     final void scheduleFinalCleanup(String who, String what) {
@@ -1608,10 +1906,6 @@
         return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
     }
 
-    final void setActivityToken(IBinder token) {
-        mActivityToken = token;
-    }
-
     final void setOuterContext(Context context) {
         mOuterContext = context;
     }
@@ -1678,19 +1972,24 @@
     // ----------------------------------------------------------------------
 
     private static final class ApplicationContentResolver extends ContentResolver {
-        public ApplicationContentResolver(Context context, ActivityThread mainThread) {
+        private final ActivityThread mMainThread;
+        private final UserHandle mUser;
+
+        public ApplicationContentResolver(
+                Context context, ActivityThread mainThread, UserHandle user) {
             super(context);
-            mMainThread = mainThread;
+            mMainThread = Preconditions.checkNotNull(mainThread);
+            mUser = Preconditions.checkNotNull(user);
         }
 
         @Override
-        protected IContentProvider acquireProvider(Context context, String name) {
-            return mMainThread.acquireProvider(context, name, true);
+        protected IContentProvider acquireProvider(Context context, String auth) {
+            return mMainThread.acquireProvider(context, auth, mUser.getIdentifier(), true);
         }
 
         @Override
-        protected IContentProvider acquireExistingProvider(Context context, String name) {
-            return mMainThread.acquireExistingProvider(context, name, true);
+        protected IContentProvider acquireExistingProvider(Context context, String auth) {
+            return mMainThread.acquireExistingProvider(context, auth, mUser.getIdentifier(), true);
         }
 
         @Override
@@ -1699,8 +1998,8 @@
         }
 
         @Override
-        protected IContentProvider acquireUnstableProvider(Context c, String name) {
-            return mMainThread.acquireProvider(c, name, false);
+        protected IContentProvider acquireUnstableProvider(Context c, String auth) {
+            return mMainThread.acquireProvider(c, auth, mUser.getIdentifier(), false);
         }
 
         @Override
@@ -1712,7 +2011,5 @@
         public void unstableProviderDied(IContentProvider icp) {
             mMainThread.handleUnstableProviderDied(icp.asBinder(), true);
         }
-
-        private final ActivityThread mMainThread;
     }
 }
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 2cc3b02..b3d99c5 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -147,15 +147,19 @@
         this(context, theme, true);
     }
 
-    Dialog(Context context, int theme, boolean createContextWrapper) {
-        if (theme == 0) {
-            TypedValue outValue = new TypedValue();
-            context.getTheme().resolveAttribute(com.android.internal.R.attr.dialogTheme,
-                    outValue, true);
-            theme = outValue.resourceId;
+    Dialog(Context context, int theme, boolean createContextThemeWrapper) {
+        if (createContextThemeWrapper) {
+            if (theme == 0) {
+                TypedValue outValue = new TypedValue();
+                context.getTheme().resolveAttribute(com.android.internal.R.attr.dialogTheme,
+                        outValue, true);
+                theme = outValue.resourceId;
+            }
+            mContext = new ContextThemeWrapper(context, theme);
+        } else {
+            mContext = context;
         }
 
-        mContext = createContextWrapper ? new ContextThemeWrapper(context, theme) : context;
         mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
         Window w = PolicyManager.makeNewWindow(mContext);
         mWindow = w;
@@ -164,7 +168,7 @@
         w.setGravity(Gravity.CENTER);
         mListenersHandler = new ListenersHandler(this);
     }
-    
+
     /**
      * @deprecated
      * @hide
@@ -1106,10 +1110,12 @@
 
     /**
      * Set a listener to be invoked when the dialog is canceled.
-     * <p>
-     * This will only be invoked when the dialog is canceled, if the creator
-     * needs to know when it is dismissed in general, use
-     * {@link #setOnDismissListener}.
+     *
+     * <p>This will only be invoked when the dialog is canceled.
+     * Cancel events alone will not capture all ways that
+     * the dialog might be dismissed. If the creator needs
+     * to know when a dialog is dismissed in general, use
+     * {@link #setOnDismissListener}.</p>
      * 
      * @param listener The {@link DialogInterface.OnCancelListener} to use.
      */
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 0b1c524..6cf4dd0 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -1098,8 +1098,8 @@
      */
     public static Long getMaxBytesOverMobile(Context context) {
         try {
-            return Settings.Secure.getLong(context.getContentResolver(),
-                    Settings.Secure.DOWNLOAD_MAX_BYTES_OVER_MOBILE);
+            return Settings.Global.getLong(context.getContentResolver(),
+                    Settings.Global.DOWNLOAD_MAX_BYTES_OVER_MOBILE);
         } catch (SettingNotFoundException exc) {
             return null;
         }
@@ -1116,8 +1116,8 @@
      */
     public static Long getRecommendedMaxBytesOverMobile(Context context) {
         try {
-            return Settings.Secure.getLong(context.getContentResolver(),
-                    Settings.Secure.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE);
+            return Settings.Global.getLong(context.getContentResolver(),
+                    Settings.Global.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE);
         } catch (SettingNotFoundException exc) {
             return null;
         }
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 28876d3..c5a382d 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -85,7 +85,7 @@
         mSavedFragmentState = in.readBundle();
     }
     
-    public Fragment instantiate(Activity activity) {
+    public Fragment instantiate(Activity activity, Fragment parent) {
         if (mInstance != null) {
             return mInstance;
         }
@@ -100,7 +100,7 @@
             mSavedFragmentState.setClassLoader(activity.getClassLoader());
             mInstance.mSavedFragmentState = mSavedFragmentState;
         }
-        mInstance.setIndex(mIndex);
+        mInstance.setIndex(mIndex, parent);
         mInstance.mFromLayout = mFromLayout;
         mInstance.mRestored = true;
         mInstance.mFragmentId = mFragmentId;
@@ -207,6 +207,8 @@
  * with the fragment.
  * <li> {@link #onActivityCreated} tells the fragment that its activity has
  * completed its own {@link Activity#onCreate Activity.onCreate()}.
+ * <li> {@link #onViewStateRestored} tells the fragment that all of the saved
+ * state of its view hierarchy has been restored.
  * <li> {@link #onStart} makes the fragment visible to the user (based on its
  * containing activity being started).
  * <li> {@link #onResume} makes the fragment interacting with the user (based on its
@@ -412,7 +414,13 @@
 
     // Activity this fragment is attached to.
     Activity mActivity;
-    
+
+    // Private fragment manager for child fragments inside of this one.
+    FragmentManagerImpl mChildFragmentManager;
+
+    // If this Fragment is contained in another Fragment, this is that container.
+    Fragment mParentFragment;
+
     // The optional identifier for this fragment -- either the container ID if it
     // was dynamically added to the view hierarchy, or the ID supplied in
     // layout.
@@ -595,18 +603,28 @@
         }
     }
     
-    final void restoreViewState() {
+    final void restoreViewState(Bundle savedInstanceState) {
         if (mSavedViewState != null) {
             mView.restoreHierarchyState(mSavedViewState);
             mSavedViewState = null;
         }
+        mCalled = false;
+        onViewStateRestored(savedInstanceState);
+        if (!mCalled) {
+            throw new SuperNotCalledException("Fragment " + this
+                    + " did not call through to super.onViewStateRestored()");
+        }
     }
-    
-    final void setIndex(int index) {
+
+    final void setIndex(int index, Fragment parent) {
         mIndex = index;
-        mWho = "android:fragment:" + mIndex;
-   }
-    
+        if (parent != null) {
+            mWho = parent.mWho + ":" + mIndex;
+        } else {
+            mWho = "android:fragment:" + mIndex;
+        }
+    }
+
     final boolean isInBackStack() {
         return mBackStackNesting > 0;
     }
@@ -785,12 +803,43 @@
      * before {@link #getActivity()}, during the time from when the fragment is
      * placed in a {@link FragmentTransaction} until it is committed and
      * attached to its activity.
+     *
+     * <p>If this Fragment is a child of another Fragment, the FragmentManager
+     * returned here will be the parent's {@link #getChildFragmentManager()}.
      */
     final public FragmentManager getFragmentManager() {
         return mFragmentManager;
     }
 
     /**
+     * Return a private FragmentManager for placing and managing Fragments
+     * inside of this Fragment.
+     */
+    final public FragmentManager getChildFragmentManager() {
+        if (mChildFragmentManager == null) {
+            instantiateChildFragmentManager();
+            if (mState >= RESUMED) {
+                mChildFragmentManager.dispatchResume();
+            } else if (mState >= STARTED) {
+                mChildFragmentManager.dispatchStart();
+            } else if (mState >= ACTIVITY_CREATED) {
+                mChildFragmentManager.dispatchActivityCreated();
+            } else if (mState >= CREATED) {
+                mChildFragmentManager.dispatchCreate();
+            }
+        }
+        return mChildFragmentManager;
+    }
+
+    /**
+     * Returns the parent Fragment containing this Fragment.  If this Fragment
+     * is attached directly to an Activity, returns null.
+     */
+    final public Fragment getParentFragment() {
+        return mParentFragment;
+    }
+
+    /**
      * Return true if the fragment is currently added to its activity.
      */
     final public boolean isAdded() {
@@ -880,6 +929,10 @@
      * </ul>
      */
     public void setRetainInstance(boolean retain) {
+        if (retain && mParentFragment != null) {
+            throw new IllegalStateException(
+                    "Can't retain fragements that are nested in other fragments");
+        }
         mRetainInstance = retain;
     }
     
@@ -961,7 +1014,7 @@
             throw new IllegalStateException("Fragment " + this + " not attached to Activity");
         }
         mCheckedForLoaderManager = true;
-        mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, true);
+        mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, true);
         return mLoaderManager;
     }
 
@@ -1135,20 +1188,7 @@
     public void onCreate(Bundle savedInstanceState) {
         mCalled = true;
     }
-    
-    /**
-     * Called immediately after {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}
-     * has returned, but before any saved state has been restored in to the view.
-     * This gives subclasses a chance to initialize themselves once
-     * they know their view hierarchy has been completely created.  The fragment's
-     * view hierarchy is not however attached to its parent at this point.
-     * @param view The View returned by {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}.
-     * @param savedInstanceState If non-null, this fragment is being re-constructed
-     * from a previous saved state as given here.
-     */
-    public void onViewCreated(View view, Bundle savedInstanceState) {
-    }
-    
+
     /**
      * Called to have the fragment instantiate its user interface view.
      * This is optional, and non-graphical fragments can return null (which
@@ -1172,6 +1212,19 @@
             Bundle savedInstanceState) {
         return null;
     }
+
+    /**
+     * Called immediately after {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}
+     * has returned, but before any saved state has been restored in to the view.
+     * This gives subclasses a chance to initialize themselves once
+     * they know their view hierarchy has been completely created.  The fragment's
+     * view hierarchy is not however attached to its parent at this point.
+     * @param view The View returned by {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}.
+     * @param savedInstanceState If non-null, this fragment is being re-constructed
+     * from a previous saved state as given here.
+     */
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+    }
     
     /**
      * Get the root view for the fragment's layout (the one returned by {@link #onCreateView}),
@@ -1191,15 +1244,30 @@
      * {@link #setRetainInstance(boolean)} to retain their instance,
      * as this callback tells the fragment when it is fully associated with
      * the new activity instance.  This is called after {@link #onCreateView}
-     * and before {@link #onStart()}.
-     * 
+     * and before {@link #onViewStateRestored(Bundle)}.
+     *
      * @param savedInstanceState If the fragment is being re-created from
      * a previous saved state, this is the state.
      */
     public void onActivityCreated(Bundle savedInstanceState) {
         mCalled = true;
     }
-    
+
+    /**
+     * Called when all saved state has been restored into the view hierarchy
+     * of the fragment.  This can be used to do initialization based on saved
+     * state that you are letting the view hierarchy track itself, such as
+     * whether check box widgets are currently checked.  This is called
+     * after {@link #onActivityCreated(Bundle)} and before
+     * {@link #onStart()}.
+     *
+     * @param savedInstanceState If the fragment is being re-created from
+     * a previous saved state, this is the state.
+     */
+    public void onViewStateRestored(Bundle savedInstanceState) {
+        mCalled = true;
+    }
+
     /**
      * Called when the Fragment is visible to the user.  This is generally
      * tied to {@link Activity#onStart() Activity.onStart} of the containing
@@ -1212,7 +1280,7 @@
             mLoadersStarted = true;
             if (!mCheckedForLoaderManager) {
                 mCheckedForLoaderManager = true;
-                mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, false);
+                mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
             }
             if (mLoaderManager != null) {
                 mLoaderManager.doStart();
@@ -1305,7 +1373,7 @@
         //        + " mLoaderManager=" + mLoaderManager);
         if (!mCheckedForLoaderManager) {
             mCheckedForLoaderManager = true;
-            mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, false);
+            mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
         }
         if (mLoaderManager != null) {
             mLoaderManager.doDestroy();
@@ -1530,6 +1598,10 @@
             writer.print(prefix); writer.print("mActivity=");
                     writer.println(mActivity);
         }
+        if (mParentFragment != null) {
+            writer.print(prefix); writer.print("mParentFragment=");
+                    writer.println(mParentFragment);
+        }
         if (mArguments != null) {
             writer.print(prefix); writer.print("mArguments="); writer.println(mArguments);
         }
@@ -1564,23 +1636,244 @@
             writer.print(prefix); writer.println("Loader Manager:");
             mLoaderManager.dump(prefix + "  ", fd, writer, args);
         }
+        if (mChildFragmentManager != null) {
+            writer.print(prefix); writer.println("Child " + mChildFragmentManager + ":");
+            mChildFragmentManager.dump(prefix + "  ", fd, writer, args);
+        }
+    }
+
+    Fragment findFragmentByWho(String who) {
+        if (who.equals(mWho)) {
+            return this;
+        }
+        if (mChildFragmentManager != null) {
+            return mChildFragmentManager.findFragmentByWho(who);
+        }
+        return null;
+    }
+
+    void instantiateChildFragmentManager() {
+        mChildFragmentManager = new FragmentManagerImpl();
+        mChildFragmentManager.attachActivity(mActivity, new FragmentContainer() {
+            @Override
+            public View findViewById(int id) {
+                if (mView == null) {
+                    throw new IllegalStateException("Fragment does not have a view");
+                }
+                return mView.findViewById(id);
+            }
+        }, this);
+    }
+
+    void performCreate(Bundle savedInstanceState) {
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.noteStateNotSaved();
+        }
+        mCalled = false;
+        onCreate(savedInstanceState);
+        if (!mCalled) {
+            throw new SuperNotCalledException("Fragment " + this
+                    + " did not call through to super.onCreate()");
+        }
+        if (savedInstanceState != null) {
+            Parcelable p = savedInstanceState.getParcelable(Activity.FRAGMENTS_TAG);
+            if (p != null) {
+                if (mChildFragmentManager == null) {
+                    instantiateChildFragmentManager();
+                }
+                mChildFragmentManager.restoreAllState(p, null);
+                mChildFragmentManager.dispatchCreate();
+            }
+        }
+    }
+
+    View performCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.noteStateNotSaved();
+        }
+        return onCreateView(inflater, container, savedInstanceState);
+    }
+
+    void performActivityCreated(Bundle savedInstanceState) {
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.noteStateNotSaved();
+        }
+        mCalled = false;
+        onActivityCreated(savedInstanceState);
+        if (!mCalled) {
+            throw new SuperNotCalledException("Fragment " + this
+                    + " did not call through to super.onActivityCreated()");
+        }
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.dispatchActivityCreated();
+        }
     }
 
     void performStart() {
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.noteStateNotSaved();
+            mChildFragmentManager.execPendingActions();
+        }
+        mCalled = false;
         onStart();
+        if (!mCalled) {
+            throw new SuperNotCalledException("Fragment " + this
+                    + " did not call through to super.onStart()");
+        }
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.dispatchStart();
+        }
         if (mLoaderManager != null) {
             mLoaderManager.doReportStart();
         }
     }
 
+    void performResume() {
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.noteStateNotSaved();
+            mChildFragmentManager.execPendingActions();
+        }
+        mCalled = false;
+        onResume();
+        if (!mCalled) {
+            throw new SuperNotCalledException("Fragment " + this
+                    + " did not call through to super.onResume()");
+        }
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.dispatchResume();
+            mChildFragmentManager.execPendingActions();
+        }
+    }
+
+    void performConfigurationChanged(Configuration newConfig) {
+        onConfigurationChanged(newConfig);
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.dispatchConfigurationChanged(newConfig);
+        }
+    }
+
+    void performLowMemory() {
+        onLowMemory();
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.dispatchLowMemory();
+        }
+    }
+
+    void performTrimMemory(int level) {
+        onTrimMemory(level);
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.dispatchTrimMemory(level);
+        }
+    }
+
+    boolean performCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        boolean show = false;
+        if (!mHidden) {
+            if (mHasMenu && mMenuVisible) {
+                show = true;
+                onCreateOptionsMenu(menu, inflater);
+            }
+            if (mChildFragmentManager != null) {
+                show |= mChildFragmentManager.dispatchCreateOptionsMenu(menu, inflater);
+            }
+        }
+        return show;
+    }
+
+    boolean performPrepareOptionsMenu(Menu menu) {
+        boolean show = false;
+        if (!mHidden) {
+            if (mHasMenu && mMenuVisible) {
+                show = true;
+                onPrepareOptionsMenu(menu);
+            }
+            if (mChildFragmentManager != null) {
+                show |= mChildFragmentManager.dispatchPrepareOptionsMenu(menu);
+            }
+        }
+        return show;
+    }
+
+    boolean performOptionsItemSelected(MenuItem item) {
+        if (!mHidden) {
+            if (mHasMenu && mMenuVisible) {
+                if (onOptionsItemSelected(item)) {
+                    return true;
+                }
+            }
+            if (mChildFragmentManager != null) {
+                if (mChildFragmentManager.dispatchOptionsItemSelected(item)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    boolean performContextItemSelected(MenuItem item) {
+        if (!mHidden) {
+            if (onContextItemSelected(item)) {
+                return true;
+            }
+            if (mChildFragmentManager != null) {
+                if (mChildFragmentManager.dispatchContextItemSelected(item)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    void performOptionsMenuClosed(Menu menu) {
+        if (!mHidden) {
+            if (mHasMenu && mMenuVisible) {
+                onOptionsMenuClosed(menu);
+            }
+            if (mChildFragmentManager != null) {
+                mChildFragmentManager.dispatchOptionsMenuClosed(menu);
+            }
+        }
+    }
+
+    void performSaveInstanceState(Bundle outState) {
+        onSaveInstanceState(outState);
+        if (mChildFragmentManager != null) {
+            Parcelable p = mChildFragmentManager.saveAllState();
+            if (p != null) {
+                outState.putParcelable(Activity.FRAGMENTS_TAG, p);
+            }
+        }
+    }
+
+    void performPause() {
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.dispatchPause();
+        }
+        mCalled = false;
+        onPause();
+        if (!mCalled) {
+            throw new SuperNotCalledException("Fragment " + this
+                    + " did not call through to super.onPause()");
+        }
+    }
+
     void performStop() {
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.dispatchStop();
+        }
+        mCalled = false;
         onStop();
+        if (!mCalled) {
+            throw new SuperNotCalledException("Fragment " + this
+                    + " did not call through to super.onStop()");
+        }
         
         if (mLoadersStarted) {
             mLoadersStarted = false;
             if (!mCheckedForLoaderManager) {
                 mCheckedForLoaderManager = true;
-                mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, false);
+                mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
             }
             if (mLoaderManager != null) {
                 if (mActivity == null || !mActivity.mChangingConfigurations) {
@@ -1593,9 +1886,29 @@
     }
 
     void performDestroyView() {
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.dispatchDestroyView();
+        }
+        mCalled = false;
         onDestroyView();
+        if (!mCalled) {
+            throw new SuperNotCalledException("Fragment " + this
+                    + " did not call through to super.onDestroyView()");
+        }
         if (mLoaderManager != null) {
             mLoaderManager.doReportNextStart();
         }
     }
+
+    void performDestroy() {
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.dispatchDestroy();
+        }
+        mCalled = false;
+        onDestroy();
+        if (!mCalled) {
+            throw new SuperNotCalledException("Fragment " + this
+                    + " did not call through to super.onDestroy()");
+        }
+    }
 }
diff --git a/core/java/android/app/FragmentBreadCrumbs.java b/core/java/android/app/FragmentBreadCrumbs.java
index df64035..b810b89 100644
--- a/core/java/android/app/FragmentBreadCrumbs.java
+++ b/core/java/android/app/FragmentBreadCrumbs.java
@@ -19,7 +19,9 @@
 import android.animation.LayoutTransition;
 import android.app.FragmentManager.BackStackEntry;
 import android.content.Context;
+import android.content.res.TypedArray;
 import android.util.AttributeSet;
+import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -51,7 +53,11 @@
     private OnClickListener mParentClickListener;
 
     private OnBreadCrumbClickListener mOnBreadCrumbClickListener;
-    
+
+    private int mGravity;
+
+    private static final int DEFAULT_GRAVITY = Gravity.START | Gravity.CENTER_VERTICAL;
+
     /**
      * Interface to intercept clicks on the bread crumbs.
      */
@@ -80,6 +86,14 @@
 
     public FragmentBreadCrumbs(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
+
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.FragmentBreadCrumbs, defStyle, 0);
+
+        mGravity = a.getInt(com.android.internal.R.styleable.FragmentBreadCrumbs_gravity,
+                DEFAULT_GRAVITY);
+
+        a.recycle();
     }
 
     /**
@@ -159,16 +173,50 @@
 
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        // Eventually we should implement our own layout of the views,
-        // rather than relying on a linear layout.
+        // Eventually we should implement our own layout of the views, rather than relying on
+        // a single linear layout.
         final int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            final View child = getChildAt(i);
-
-            int childRight = mPaddingLeft + child.getMeasuredWidth() - mPaddingRight;
-            int childBottom = mPaddingTop + child.getMeasuredHeight() - mPaddingBottom;
-            child.layout(mPaddingLeft, mPaddingTop, childRight, childBottom);
+        if (childCount == 0) {
+            return;
         }
+
+        final View child = getChildAt(0);
+
+        final int childTop = mPaddingTop;
+        final int childBottom = mPaddingTop + child.getMeasuredHeight() - mPaddingBottom;
+
+        int childLeft;
+        int childRight;
+
+        final int layoutDirection = getLayoutDirection();
+        final int horizontalGravity = mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
+        switch (Gravity.getAbsoluteGravity(horizontalGravity, layoutDirection)) {
+            case Gravity.RIGHT:
+                childRight = mRight - mLeft - mPaddingRight;
+                childLeft = childRight - child.getMeasuredWidth();
+                break;
+
+            case Gravity.CENTER_HORIZONTAL:
+                childLeft = mPaddingLeft + (mRight - mLeft - child.getMeasuredWidth()) / 2;
+                childRight = childLeft + child.getMeasuredWidth();
+                break;
+
+            case Gravity.LEFT:
+            default:
+                childLeft = mPaddingLeft;
+                childRight = childLeft + child.getMeasuredWidth();
+                break;
+        }
+
+        if (childLeft < mPaddingLeft) {
+            childLeft = mPaddingLeft;
+        }
+
+        if (childRight > mRight - mLeft - mPaddingRight) {
+            childRight = mRight - mLeft - mPaddingRight;
+        }
+
+        child.layout(childLeft, childTop, childRight, childBottom);
     }
 
     @Override
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 39e2423..10ea109 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -22,6 +22,7 @@
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.os.Bundle;
+import android.os.Debug;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Parcel;
@@ -29,7 +30,6 @@
 import android.util.DebugUtils;
 import android.util.Log;
 import android.util.LogWriter;
-import android.util.Slog;
 import android.util.SparseArray;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -318,6 +318,12 @@
     public abstract Fragment.SavedState saveFragmentInstanceState(Fragment f);
 
     /**
+     * Returns true if the final {@link Activity#onDestroy() Activity.onDestroy()}
+     * call has been made on the FragmentManager's Activity, so this instance is now dead.
+     */
+    public abstract boolean isDestroyed();
+
+    /**
      * Print the FragmentManager's state into the given stream.
      *
      * @param prefix Text to print at the front of each line.
@@ -380,6 +386,13 @@
 }
 
 /**
+ * Callbacks from FragmentManagerImpl to its container.
+ */
+interface FragmentContainer {
+    public View findViewById(int id);
+}
+
+/**
  * Container for fragments associated with an activity.
  */
 final class FragmentManagerImpl extends FragmentManager {
@@ -409,6 +422,8 @@
 
     int mCurState = Fragment.INITIALIZING;
     Activity mActivity;
+    FragmentContainer mContainer;
+    Fragment mParent;
     
     boolean mNeedMenuInvalidate;
     boolean mStateSaved;
@@ -427,6 +442,28 @@
         }
     };
 
+    private void throwException(RuntimeException ex) {
+        Log.e(TAG, ex.getMessage());
+        LogWriter logw = new LogWriter(Log.ERROR, TAG);
+        PrintWriter pw = new PrintWriter(logw);
+        if (mActivity != null) {
+            Log.e(TAG, "Activity state:");
+            try {
+                mActivity.dump("  ", null, pw, new String[] { });
+            } catch (Exception e) {
+                Log.e(TAG, "Failed dumping state", e);
+            }
+        } else {
+            Log.e(TAG, "Fragment manager state:");
+            try {
+                dump("  ", null, pw, new String[] { });
+            } catch (Exception e) {
+                Log.e(TAG, "Failed dumping state", e);
+            }
+        }
+        throw ex;
+    }
+
     @Override
     public FragmentTransaction beginTransaction() {
         return new BackStackRecord(this);
@@ -519,8 +556,8 @@
     @Override
     public void putFragment(Bundle bundle, String key, Fragment fragment) {
         if (fragment.mIndex < 0) {
-            throw new IllegalStateException("Fragment " + fragment
-                    + " is not currently in the FragmentManager");
+            throwException(new IllegalStateException("Fragment " + fragment
+                    + " is not currently in the FragmentManager"));
         }
         bundle.putInt(key, fragment.mIndex);
     }
@@ -532,13 +569,13 @@
             return null;
         }
         if (index >= mActive.size()) {
-            throw new IllegalStateException("Fragement no longer exists for key "
-                    + key + ": index " + index);
+            throwException(new IllegalStateException("Fragement no longer exists for key "
+                    + key + ": index " + index));
         }
         Fragment f = mActive.get(index);
         if (f == null) {
-            throw new IllegalStateException("Fragement no longer exists for key "
-                    + key + ": index " + index);
+            throwException(new IllegalStateException("Fragement no longer exists for key "
+                    + key + ": index " + index));
         }
         return f;
     }
@@ -546,8 +583,8 @@
     @Override
     public Fragment.SavedState saveFragmentInstanceState(Fragment fragment) {
         if (fragment.mIndex < 0) {
-            throw new IllegalStateException("Fragment " + fragment
-                    + " is not currently in the FragmentManager");
+            throwException(new IllegalStateException("Fragment " + fragment
+                    + " is not currently in the FragmentManager"));
         }
         if (fragment.mState > Fragment.INITIALIZING) {
             Bundle result = saveFragmentBasicState(fragment);
@@ -557,12 +594,21 @@
     }
 
     @Override
+    public boolean isDestroyed() {
+        return mDestroyed;
+    }
+
+    @Override
     public String toString() {
         StringBuilder sb = new StringBuilder(128);
         sb.append("FragmentManager{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
         sb.append(" in ");
-        DebugUtils.buildShortClassTag(mActivity, sb);
+        if (mParent != null) {
+            DebugUtils.buildShortClassTag(mParent, sb);
+        } else {
+            DebugUtils.buildShortClassTag(mActivity, sb);
+        }
         sb.append("}}");
         return sb.toString();
     }
@@ -658,6 +704,11 @@
         }
 
         writer.print(prefix); writer.println("FragmentManager misc state:");
+        writer.print(prefix); writer.print("  mActivity="); writer.println(mActivity);
+        writer.print(prefix); writer.print("  mContainer="); writer.println(mContainer);
+        if (mParent != null) {
+            writer.print(prefix); writer.print("  mParent="); writer.println(mParent);
+        }
         writer.print(prefix); writer.print("  mCurState="); writer.print(mCurState);
                 writer.print(" mStateSaved="); writer.print(mStateSaved);
                 writer.print(" mDestroyed="); writer.println(mDestroyed);
@@ -732,8 +783,12 @@
 
     void moveToState(Fragment f, int newState, int transit, int transitionStyle,
             boolean keepActive) {
+        if (DEBUG && false) Log.v(TAG, "moveToState: " + f
+            + " oldState=" + f.mState + " newState=" + newState
+            + " mRemoving=" + f.mRemoving + " Callers=" + Debug.getCallers(5));
+
         // Fragments that are not currently added will sit in the onCreate() state.
-        if (!f.mAdded && newState > Fragment.CREATED) {
+        if ((!f.mAdded || f.mDetached) && newState > Fragment.CREATED) {
             newState = Fragment.CREATED;
         }
         if (f.mRemoving && newState > f.mState) {
@@ -782,30 +837,29 @@
                         }
                     }
                     f.mActivity = mActivity;
-                    f.mFragmentManager = mActivity.mFragments;
+                    f.mParentFragment = mParent;
+                    f.mFragmentManager = mParent != null
+                            ? mParent.mChildFragmentManager : mActivity.mFragments;
                     f.mCalled = false;
                     f.onAttach(mActivity);
                     if (!f.mCalled) {
                         throw new SuperNotCalledException("Fragment " + f
                                 + " did not call through to super.onAttach()");
                     }
-                    mActivity.onAttachFragment(f);
-                    
+                    if (f.mParentFragment == null) {
+                        mActivity.onAttachFragment(f);
+                    }
+
                     if (!f.mRetaining) {
-                        f.mCalled = false;
-                        f.onCreate(f.mSavedFragmentState);
-                        if (!f.mCalled) {
-                            throw new SuperNotCalledException("Fragment " + f
-                                    + " did not call through to super.onCreate()");
-                        }
+                        f.performCreate(f.mSavedFragmentState);
                     }
                     f.mRetaining = false;
                     if (f.mFromLayout) {
                         // For fragments that are part of the content view
                         // layout, we need to instantiate the view immediately
                         // and the inflater will take care of adding it.
-                        f.mView = f.onCreateView(f.getLayoutInflater(f.mSavedFragmentState),
-                                null, f.mSavedFragmentState);
+                        f.mView = f.performCreateView(f.getLayoutInflater(
+                                f.mSavedFragmentState), null, f.mSavedFragmentState);
                         if (f.mView != null) {
                             f.mView.setSaveFromParentEnabled(false);
                             if (f.mHidden) f.mView.setVisibility(View.GONE);
@@ -818,16 +872,18 @@
                         if (!f.mFromLayout) {
                             ViewGroup container = null;
                             if (f.mContainerId != 0) {
-                                container = (ViewGroup)mActivity.findViewById(f.mContainerId);
+                                container = (ViewGroup)mContainer.findViewById(f.mContainerId);
                                 if (container == null && !f.mRestored) {
-                                    throw new IllegalArgumentException("No view found for id 0x"
-                                            + Integer.toHexString(f.mContainerId)
-                                            + " for fragment " + f);
+                                    throwException(new IllegalArgumentException(
+                                            "No view found for id 0x"
+                                            + Integer.toHexString(f.mContainerId) + " ("
+                                            + f.getResources().getResourceName(f.mContainerId)
+                                            + ") for fragment " + f));
                                 }
                             }
                             f.mContainer = container;
-                            f.mView = f.onCreateView(f.getLayoutInflater(f.mSavedFragmentState),
-                                    container, f.mSavedFragmentState);
+                            f.mView = f.performCreateView(f.getLayoutInflater(
+                                    f.mSavedFragmentState), container, f.mSavedFragmentState);
                             if (f.mView != null) {
                                 f.mView.setSaveFromParentEnabled(false);
                                 if (container != null) {
@@ -843,15 +899,10 @@
                                 f.onViewCreated(f.mView, f.mSavedFragmentState);
                             }
                         }
-                        
-                        f.mCalled = false;
-                        f.onActivityCreated(f.mSavedFragmentState);
-                        if (!f.mCalled) {
-                            throw new SuperNotCalledException("Fragment " + f
-                                    + " did not call through to super.onActivityCreated()");
-                        }
+
+                        f.performActivityCreated(f.mSavedFragmentState);
                         if (f.mView != null) {
-                            f.restoreViewState();
+                            f.restoreViewState(f.mSavedFragmentState);
                         }
                         f.mSavedFragmentState = null;
                     }
@@ -859,23 +910,13 @@
                 case Fragment.STOPPED:
                     if (newState > Fragment.STOPPED) {
                         if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
-                        f.mCalled = false;
                         f.performStart();
-                        if (!f.mCalled) {
-                            throw new SuperNotCalledException("Fragment " + f
-                                    + " did not call through to super.onStart()");
-                        }
                     }
                 case Fragment.STARTED:
                     if (newState > Fragment.STARTED) {
                         if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
-                        f.mCalled = false;
                         f.mResumed = true;
-                        f.onResume();
-                        if (!f.mCalled) {
-                            throw new SuperNotCalledException("Fragment " + f
-                                    + " did not call through to super.onResume()");
-                        }
+                        f.performResume();
                         // Get rid of this in case we saved it and never needed it.
                         f.mSavedFragmentState = null;
                         f.mSavedViewState = null;
@@ -886,23 +927,13 @@
                 case Fragment.RESUMED:
                     if (newState < Fragment.RESUMED) {
                         if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
-                        f.mCalled = false;
-                        f.onPause();
-                        if (!f.mCalled) {
-                            throw new SuperNotCalledException("Fragment " + f
-                                    + " did not call through to super.onPause()");
-                        }
+                        f.performPause();
                         f.mResumed = false;
                     }
                 case Fragment.STARTED:
                     if (newState < Fragment.STARTED) {
                         if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
-                        f.mCalled = false;
                         f.performStop();
-                        if (!f.mCalled) {
-                            throw new SuperNotCalledException("Fragment " + f
-                                    + " did not call through to super.onStop()");
-                        }
                     }
                 case Fragment.STOPPED:
                 case Fragment.ACTIVITY_CREATED:
@@ -915,12 +946,7 @@
                                 saveFragmentViewState(f);
                             }
                         }
-                        f.mCalled = false;
                         f.performDestroyView();
-                        if (!f.mCalled) {
-                            throw new SuperNotCalledException("Fragment " + f
-                                    + " did not call through to super.onDestroyView()");
-                        }
                         if (f.mView != null && f.mContainer != null) {
                             Animator anim = null;
                             if (mCurState > Fragment.INITIALIZING && !mDestroyed) {
@@ -979,12 +1005,7 @@
                         } else {
                             if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
                             if (!f.mRetaining) {
-                                f.mCalled = false;
-                                f.onDestroy();
-                                if (!f.mCalled) {
-                                    throw new SuperNotCalledException("Fragment " + f
-                                            + " did not call through to super.onDestroy()");
-                                }
+                                f.performDestroy();
                             }
 
                             f.mCalled = false;
@@ -998,6 +1019,7 @@
                                     makeInactive(f);
                                 } else {
                                     f.mActivity = null;
+                                    f.mParentFragment = null;
                                     f.mFragmentManager = null;
                                 }
                             }
@@ -1021,11 +1043,11 @@
         if (mActivity == null && newState != Fragment.INITIALIZING) {
             throw new IllegalStateException("No activity");
         }
-        
+
         if (!always && mCurState == newState) {
             return;
         }
-        
+
         mCurState = newState;
         if (mActive != null) {
             boolean loadersRunning = false;
@@ -1070,11 +1092,11 @@
             if (mActive == null) {
                 mActive = new ArrayList<Fragment>();
             }
-            f.setIndex(mActive.size());
+            f.setIndex(mActive.size(), mParent);
             mActive.add(f);
             
         } else {
-            f.setIndex(mAvailIndices.remove(mAvailIndices.size()-1));
+            f.setIndex(mAvailIndices.remove(mAvailIndices.size()-1), mParent);
             mActive.set(f.mIndex, f);
         }
         if (DEBUG) Log.v(TAG, "Allocated fragment index " + f);
@@ -1091,7 +1113,7 @@
             mAvailIndices = new ArrayList<Integer>();
         }
         mAvailIndices.add(f.mIndex);
-        mActivity.invalidateFragmentIndex(f.mIndex);
+        mActivity.invalidateFragment(f.mWho);
         f.initState();
     }
     
@@ -1102,6 +1124,9 @@
         if (DEBUG) Log.v(TAG, "add: " + fragment);
         makeActive(fragment);
         if (!fragment.mDetached) {
+            if (mAdded.contains(fragment)) {
+                throw new IllegalStateException("Fragment already added: " + fragment);
+            }
             mAdded.add(fragment);
             fragment.mAdded = true;
             fragment.mRemoving = false;
@@ -1118,6 +1143,14 @@
         if (DEBUG) Log.v(TAG, "remove: " + fragment + " nesting=" + fragment.mBackStackNesting);
         final boolean inactive = !fragment.isInBackStack();
         if (!fragment.mDetached || inactive) {
+            if (false) {
+                // Would be nice to catch a bad remove here, but we need
+                // time to test this to make sure we aren't crashes cases
+                // where it is not a problem.
+                if (!mAdded.contains(fragment)) {
+                    throw new IllegalStateException("Fragment not added: " + fragment);
+                }
+            }
             if (mAdded != null) {
                 mAdded.remove(fragment);
             }
@@ -1190,6 +1223,7 @@
             if (fragment.mAdded) {
                 // We are not already in back stack, so need to remove the fragment.
                 if (mAdded != null) {
+                    if (DEBUG) Log.v(TAG, "remove from detach: " + fragment);
                     mAdded.remove(fragment);
                 }
                 if (fragment.mHasMenu && fragment.mMenuVisible) {
@@ -1209,6 +1243,10 @@
                 if (mAdded == null) {
                     mAdded = new ArrayList<Fragment>();
                 }
+                if (mAdded.contains(fragment)) {
+                    throw new IllegalStateException("Fragment already added: " + fragment);
+                }
+                if (DEBUG) Log.v(TAG, "add from attach: " + fragment);
                 mAdded.add(fragment);
                 fragment.mAdded = true;
                 if (fragment.mHasMenu && fragment.mMenuVisible) {
@@ -1267,7 +1305,7 @@
         if (mActive != null && who != null) {
             for (int i=mActive.size()-1; i>=0; i--) {
                 Fragment f = mActive.get(i);
-                if (f != null && who.equals(f.mWho)) {
+                if (f != null && (f=f.findFragmentByWho(who)) != null) {
                     return f;
                 }
             }
@@ -1537,7 +1575,7 @@
         if (mStateBundle == null) {
             mStateBundle = new Bundle();
         }
-        f.onSaveInstanceState(mStateBundle);
+        f.performSaveInstanceState(mStateBundle);
         if (!mStateBundle.isEmpty()) {
             result = mStateBundle;
             mStateBundle = null;
@@ -1583,12 +1621,9 @@
             Fragment f = mActive.get(i);
             if (f != null) {
                 if (f.mIndex < 0) {
-                    String msg = "Failure saving state: active " + f
-                            + " has cleared index: " + f.mIndex;
-                    Slog.e(TAG, msg);
-                    dump("  ", null, new PrintWriter(new LogWriter(
-                            Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { });
-                    throw new IllegalStateException(msg);
+                    throwException(new IllegalStateException(
+                            "Failure saving state: active " + f
+                            + " has cleared index: " + f.mIndex));
                 }
 
                 haveFragments = true;
@@ -1601,12 +1636,9 @@
 
                     if (f.mTarget != null) {
                         if (f.mTarget.mIndex < 0) {
-                            String msg = "Failure saving state: " + f
-                                + " has target not in fragment manager: " + f.mTarget;
-                            Slog.e(TAG, msg);
-                            dump("  ", null, new PrintWriter(new LogWriter(
-                                    Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { });
-                            throw new IllegalStateException(msg);
+                            throwException(new IllegalStateException(
+                                    "Failure saving state: " + f
+                                    + " has target not in fragment manager: " + f.mTarget));
                         }
                         if (fs.mSavedFragmentState == null) {
                             fs.mSavedFragmentState = new Bundle();
@@ -1645,12 +1677,9 @@
                 for (int i=0; i<N; i++) {
                     added[i] = mAdded.get(i).mIndex;
                     if (added[i] < 0) {
-                        String msg = "Failure saving state: active " + mAdded.get(i)
-                                + " has cleared index: " + added[i];
-                        Slog.e(TAG, msg);
-                        dump("  ", null, new PrintWriter(new LogWriter(
-                                Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { });
-                        throw new IllegalStateException(msg);
+                        throwException(new IllegalStateException(
+                                "Failure saving state: active " + mAdded.get(i)
+                                + " has cleared index: " + added[i]));
                     }
                     if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i
                             + ": " + mAdded.get(i));
@@ -1715,20 +1744,19 @@
         for (int i=0; i<fms.mActive.length; i++) {
             FragmentState fs = fms.mActive[i];
             if (fs != null) {
-                Fragment f = fs.instantiate(mActivity);
-                if (DEBUG) Log.v(TAG, "restoreAllState: adding #" + i + ": " + f);
+                Fragment f = fs.instantiate(mActivity, mParent);
+                if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
                 mActive.add(f);
                 // Now that the fragment is instantiated (or came from being
                 // retained above), clear mInstance in case we end up re-restoring
                 // from this FragmentState again.
                 fs.mInstance = null;
             } else {
-                if (DEBUG) Log.v(TAG, "restoreAllState: adding #" + i + ": (null)");
                 mActive.add(null);
                 if (mAvailIndices == null) {
                     mAvailIndices = new ArrayList<Integer>();
                 }
-                if (DEBUG) Log.v(TAG, "restoreAllState: adding avail #" + i);
+                if (DEBUG) Log.v(TAG, "restoreAllState: avail #" + i);
                 mAvailIndices.add(i);
             }
         }
@@ -1755,11 +1783,14 @@
             for (int i=0; i<fms.mAdded.length; i++) {
                 Fragment f = mActive.get(fms.mAdded[i]);
                 if (f == null) {
-                    throw new IllegalStateException(
-                            "No instantiated fragment for index #" + fms.mAdded[i]);
+                    throwException(new IllegalStateException(
+                            "No instantiated fragment for index #" + fms.mAdded[i]));
                 }
                 f.mAdded = true;
-                if (DEBUG) Log.v(TAG, "restoreAllState: making added #" + i + ": " + f);
+                if (DEBUG) Log.v(TAG, "restoreAllState: added #" + i + ": " + f);
+                if (mAdded.contains(f)) {
+                    throw new IllegalStateException("Already added!");
+                }
                 mAdded.add(f);
             }
         } else {
@@ -1771,8 +1802,13 @@
             mBackStack = new ArrayList<BackStackRecord>(fms.mBackStack.length);
             for (int i=0; i<fms.mBackStack.length; i++) {
                 BackStackRecord bse = fms.mBackStack[i].instantiate(this);
-                if (DEBUG) Log.v(TAG, "restoreAllState: adding bse #" + i
+                if (DEBUG) {
+                    Log.v(TAG, "restoreAllState: back stack #" + i
                         + " (index " + bse.mIndex + "): " + bse);
+                    LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
+                    PrintWriter pw = new PrintWriter(logw);
+                    bse.dump("  ", pw, false);
+                }
                 mBackStack.add(bse);
                 if (bse.mIndex >= 0) {
                     setBackStackIndex(bse.mIndex, bse);
@@ -1783,9 +1819,11 @@
         }
     }
     
-    public void attachActivity(Activity activity) {
-        if (mActivity != null) throw new IllegalStateException();
+    public void attachActivity(Activity activity, FragmentContainer container, Fragment parent) {
+        if (mActivity != null) throw new IllegalStateException("Already attached");
         mActivity = activity;
+        mContainer = container;
+        mParent = parent;
     }
     
     public void noteStateNotSaved() {
@@ -1820,11 +1858,17 @@
         moveToState(Fragment.STOPPED, false);
     }
     
+    public void dispatchDestroyView() {
+        moveToState(Fragment.CREATED, false);
+    }
+
     public void dispatchDestroy() {
         mDestroyed = true;
         execPendingActions();
         moveToState(Fragment.INITIALIZING, false);
         mActivity = null;
+        mContainer = null;
+        mParent = null;
     }
     
     public void dispatchConfigurationChanged(Configuration newConfig) {
@@ -1832,7 +1876,7 @@
             for (int i=0; i<mAdded.size(); i++) {
                 Fragment f = mAdded.get(i);
                 if (f != null) {
-                    f.onConfigurationChanged(newConfig);
+                    f.performConfigurationChanged(newConfig);
                 }
             }
         }
@@ -1843,7 +1887,7 @@
             for (int i=0; i<mAdded.size(); i++) {
                 Fragment f = mAdded.get(i);
                 if (f != null) {
-                    f.onLowMemory();
+                    f.performLowMemory();
                 }
             }
         }
@@ -1854,7 +1898,7 @@
             for (int i=0; i<mAdded.size(); i++) {
                 Fragment f = mAdded.get(i);
                 if (f != null) {
-                    f.onTrimMemory(level);
+                    f.performTrimMemory(level);
                 }
             }
         }
@@ -1866,13 +1910,14 @@
         if (mAdded != null) {
             for (int i=0; i<mAdded.size(); i++) {
                 Fragment f = mAdded.get(i);
-                if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible) {
-                    show = true;
-                    f.onCreateOptionsMenu(menu, inflater);
-                    if (newMenus == null) {
-                        newMenus = new ArrayList<Fragment>();
+                if (f != null) {
+                    if (f.performCreateOptionsMenu(menu, inflater)) {
+                        show = true;
+                        if (newMenus == null) {
+                            newMenus = new ArrayList<Fragment>();
+                        }
+                        newMenus.add(f);
                     }
-                    newMenus.add(f);
                 }
             }
         }
@@ -1896,9 +1941,10 @@
         if (mAdded != null) {
             for (int i=0; i<mAdded.size(); i++) {
                 Fragment f = mAdded.get(i);
-                if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible) {
-                    show = true;
-                    f.onPrepareOptionsMenu(menu);
+                if (f != null) {
+                    if (f.performPrepareOptionsMenu(menu)) {
+                        show = true;
+                    }
                 }
             }
         }
@@ -1909,8 +1955,8 @@
         if (mAdded != null) {
             for (int i=0; i<mAdded.size(); i++) {
                 Fragment f = mAdded.get(i);
-                if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible) {
-                    if (f.onOptionsItemSelected(item)) {
+                if (f != null) {
+                    if (f.performOptionsItemSelected(item)) {
                         return true;
                     }
                 }
@@ -1923,8 +1969,8 @@
         if (mAdded != null) {
             for (int i=0; i<mAdded.size(); i++) {
                 Fragment f = mAdded.get(i);
-                if (f != null && !f.mHidden && f.mUserVisibleHint) {
-                    if (f.onContextItemSelected(item)) {
+                if (f != null) {
+                    if (f.performContextItemSelected(item)) {
                         return true;
                     }
                 }
@@ -1937,8 +1983,8 @@
         if (mAdded != null) {
             for (int i=0; i<mAdded.size(); i++) {
                 Fragment f = mAdded.get(i);
-                if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible) {
-                    f.onOptionsMenuClosed(menu);
+                if (f != null) {
+                    f.performOptionsMenuClosed(menu);
                 }
             }
         }
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 031e39b..8fc1c86 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -55,14 +55,18 @@
             Intent intent, String resolvedType, IBinder resultTo, String resultWho,
             int requestCode, int flags, String profileFile,
             ParcelFileDescriptor profileFd, Bundle options) throws RemoteException;
+    public int startActivityAsUser(IApplicationThread caller,
+            Intent intent, String resolvedType, IBinder resultTo, String resultWho,
+            int requestCode, int flags, String profileFile,
+            ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException;
     public WaitResult startActivityAndWait(IApplicationThread caller,
             Intent intent, String resolvedType, IBinder resultTo, String resultWho,
             int requestCode, int flags, String profileFile,
-            ParcelFileDescriptor profileFd, Bundle options) throws RemoteException;
+            ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException;
     public int startActivityWithConfig(IApplicationThread caller,
             Intent intent, String resolvedType, IBinder resultTo, String resultWho,
             int requestCode, int startFlags, Configuration newConfig,
-            Bundle options) throws RemoteException;
+            Bundle options, int userId) throws RemoteException;
     public int startActivityIntentSender(IApplicationThread caller,
             IntentSender intent, Intent fillInIntent, String resolvedType,
             IBinder resultTo, String resultWho, int requestCode,
@@ -76,34 +80,31 @@
     public boolean willActivityBeVisible(IBinder token) throws RemoteException;
     public Intent registerReceiver(IApplicationThread caller, String callerPackage,
             IIntentReceiver receiver, IntentFilter filter,
-            String requiredPermission) throws RemoteException;
+            String requiredPermission, int userId) throws RemoteException;
     public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException;
     public int broadcastIntent(IApplicationThread caller, Intent intent,
             String resolvedType, IIntentReceiver resultTo, int resultCode,
             String resultData, Bundle map, String requiredPermission,
             boolean serialized, boolean sticky, int userId) throws RemoteException;
     public void unbroadcastIntent(IApplicationThread caller, Intent intent, int userId) throws RemoteException;
-    /* oneway */
     public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle map, boolean abortBroadcast) throws RemoteException;
     public void attachApplication(IApplicationThread app) throws RemoteException;
-    /* oneway */
+    public void activityResumed(IBinder token) throws RemoteException;
     public void activityIdle(IBinder token, Configuration config,
             boolean stopProfiling) throws RemoteException;
     public void activityPaused(IBinder token) throws RemoteException;
-    /* oneway */
     public void activityStopped(IBinder token, Bundle state,
             Bitmap thumbnail, CharSequence description) throws RemoteException;
-    /* oneway */
     public void activitySlept(IBinder token) throws RemoteException;
-    /* oneway */
     public void activityDestroyed(IBinder token) throws RemoteException;
     public String getCallingPackage(IBinder token) throws RemoteException;
     public ComponentName getCallingActivity(IBinder token) throws RemoteException;
     public List getTasks(int maxNum, int flags,
                          IThumbnailReceiver receiver) throws RemoteException;
     public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
-            int flags) throws RemoteException;
+            int flags, int userId) throws RemoteException;
     public ActivityManager.TaskThumbnails getTaskThumbnails(int taskId) throws RemoteException;
+    public Bitmap getTaskTopThumbnail(int taskId) throws RemoteException;
     public List getServices(int maxNum, int flags) throws RemoteException;
     public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState()
             throws RemoteException;
@@ -116,8 +117,8 @@
     public void reportThumbnail(IBinder token,
             Bitmap thumbnail, CharSequence description) throws RemoteException;
     public ContentProviderHolder getContentProvider(IApplicationThread caller,
-            String name, boolean stable) throws RemoteException;
-    public ContentProviderHolder getContentProviderExternal(String name, IBinder token)
+            String name, int userId, boolean stable) throws RemoteException;
+    public ContentProviderHolder getContentProviderExternal(String name, int userId, IBinder token)
             throws RemoteException;
     public void removeContentProvider(IBinder connection, boolean stable) throws RemoteException;
     public void removeContentProviderExternal(String name, IBinder token) throws RemoteException;
@@ -129,9 +130,9 @@
     public PendingIntent getRunningServiceControlPanel(ComponentName service)
             throws RemoteException;
     public ComponentName startService(IApplicationThread caller, Intent service,
-            String resolvedType) throws RemoteException;
+            String resolvedType, int userId) throws RemoteException;
     public int stopService(IApplicationThread caller, Intent service,
-            String resolvedType) throws RemoteException;
+            String resolvedType, int userId) throws RemoteException;
     public boolean stopServiceToken(ComponentName className, IBinder token,
             int startId) throws RemoteException;
     public void setServiceForeground(ComponentName className, IBinder token,
@@ -151,12 +152,13 @@
     
     public boolean bindBackupAgent(ApplicationInfo appInfo, int backupRestoreMode)
             throws RemoteException;
+    public void clearPendingBackup() throws RemoteException;
     public void backupAgentCreated(String packageName, IBinder agent) throws RemoteException;
     public void unbindBackupAgent(ApplicationInfo appInfo) throws RemoteException;
     public void killApplicationProcess(String processName, int uid) throws RemoteException;
     
     public boolean startInstrumentation(ComponentName className, String profileFile,
-            int flags, Bundle arguments, IInstrumentationWatcher watcher)
+            int flags, Bundle arguments, IInstrumentationWatcher watcher, int userId)
             throws RemoteException;
     public void finishInstrumentation(IApplicationThread target,
             int resultCode, Bundle results) throws RemoteException;
@@ -173,13 +175,16 @@
     public IIntentSender getIntentSender(int type,
             String packageName, IBinder token, String resultWho,
             int requestCode, Intent[] intents, String[] resolvedTypes,
-            int flags, Bundle options) throws RemoteException;
+            int flags, Bundle options, int userId) throws RemoteException;
     public void cancelIntentSender(IIntentSender sender) throws RemoteException;
     public boolean clearApplicationUserData(final String packageName,
             final IPackageDataObserver observer, int userId) throws RemoteException;
     public String getPackageForIntentSender(IIntentSender sender) throws RemoteException;
     public int getUidForIntentSender(IIntentSender sender) throws RemoteException;
     
+    public int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
+            boolean requireFull, String name, String callerPackage) throws RemoteException;
+
     public void setProcessLimit(int max) throws RemoteException;
     public int getProcessLimit() throws RemoteException;
     
@@ -201,9 +206,10 @@
     
     public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) throws RemoteException;
     
-    public void killBackgroundProcesses(final String packageName) throws RemoteException;
+    public void killBackgroundProcesses(final String packageName, int userId)
+            throws RemoteException;
     public void killAllBackgroundProcesses() throws RemoteException;
-    public void forceStopPackage(final String packageName) throws RemoteException;
+    public void forceStopPackage(final String packageName, int userId) throws RemoteException;
     
     // Note: probably don't want to allow applications access to these.
     public void goingToSleep() throws RemoteException;
@@ -260,7 +266,7 @@
     public ConfigurationInfo getDeviceConfigurationInfo() throws RemoteException;
     
     // Turn on/off profiling in a particular process.
-    public boolean profileControl(String process, boolean start,
+    public boolean profileControl(String process, int userId, boolean start,
             String path, ParcelFileDescriptor fd, int profileType) throws RemoteException;
     
     public boolean shutdown(int timeout) throws RemoteException;
@@ -268,12 +274,7 @@
     public void stopAppSwitches() throws RemoteException;
     public void resumeAppSwitches() throws RemoteException;
     
-    public int startActivityInPackage(int uid,
-            Intent intent, String resolvedType, IBinder resultTo,
-            String resultWho, int requestCode, int startFlags, Bundle options)
-            throws RemoteException;
-
-    public void killApplicationWithUid(String pkg, int uid) throws RemoteException;
+    public void killApplicationWithAppId(String pkg, int appid) throws RemoteException;
     
     public void closeSystemDialogs(String reason) throws RemoteException;
     
@@ -294,7 +295,7 @@
     public void crashApplication(int uid, int initialPid, String packageName,
             String message) throws RemoteException;
 
-    public String getProviderMimeType(Uri uri) throws RemoteException;
+    public String getProviderMimeType(Uri uri, int userId) throws RemoteException;
     
     public IBinder newUriPermissionOwner(String name) throws RemoteException;
     public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg,
@@ -306,15 +307,12 @@
             Uri uri, int modeFlags) throws RemoteException;
 
     // Cause the specified process to dump the specified heap.
-    public boolean dumpHeap(String process, boolean managed, String path,
+    public boolean dumpHeap(String process, int userId, boolean managed, String path,
         ParcelFileDescriptor fd) throws RemoteException;
 
     public int startActivities(IApplicationThread caller,
             Intent[] intents, String[] resolvedTypes, IBinder resultTo,
-            Bundle options) throws RemoteException;
-    public int startActivitiesInPackage(int uid,
-            Intent[] intents, String[] resolvedTypes, IBinder resultTo,
-            Bundle options) throws RemoteException;
+            Bundle options, int userId) throws RemoteException;
 
     public int getFrontActivityScreenCompatMode() throws RemoteException;
     public void setFrontActivityScreenCompatMode(int mode) throws RemoteException;
@@ -327,7 +325,10 @@
 
     // Multi-user APIs
     public boolean switchUser(int userid) throws RemoteException;
+    public int stopUser(int userid, IStopUserCallback callback) throws RemoteException;
     public UserInfo getCurrentUser() throws RemoteException;
+    public boolean isUserRunning(int userid, boolean orStopping) throws RemoteException;
+    public int[] getRunningUserIds() throws RemoteException;
 
     public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException;
 
@@ -358,6 +359,13 @@
     // manage your activity to make sure it is always the uid you expect.
     public int getLaunchedFromUid(IBinder activityToken) throws RemoteException;
 
+    public void registerUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException;
+    public void unregisterUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException;
+
+    public void requestBugReport() throws RemoteException;
+
+    public long inputDispatchingTimedOut(int pid, boolean aboveSystem) throws RemoteException;
+
     /*
      * Private non-Binder interfaces
      */
@@ -491,7 +499,7 @@
     int BIND_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+35;
     int UNBIND_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+36;
     int PUBLISH_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+37;
-
+    int ACTIVITY_RESUMED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+38;
     int GOING_TO_SLEEP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+39;
     int WAKING_UP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+40;
     int SET_DEBUG_APP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+41;
@@ -546,10 +554,9 @@
     int BACKUP_AGENT_CREATED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+90;
     int UNBIND_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+91;
     int GET_UID_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92;
-
-
-    int START_ACTIVITY_IN_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94;
-    int KILL_APPLICATION_WITH_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
+    int HANDLE_INCOMING_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93;
+    int GET_TASK_TOP_THUMBNAIL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94;
+    int KILL_APPLICATION_WITH_APPID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
     int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96;
     int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97;
     int KILL_APPLICATION_PROCESS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+98;
@@ -575,7 +582,7 @@
     int CHECK_GRANT_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+118;
     int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+119;
     int START_ACTIVITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+120;
-    int START_ACTIVITIES_IN_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+121;
+    int IS_USER_RUNNING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+121;
     int ACTIVITY_SLEPT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+122;
     int GET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+123;
     int SET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+124;
@@ -606,4 +613,12 @@
     int GET_LAUNCHED_FROM_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+149;
     int UNSTABLE_PROVIDER_DIED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+150;
     int IS_INTENT_SENDER_AN_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+151;
+    int START_ACTIVITY_AS_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+152;
+    int STOP_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+153;
+    int REGISTER_USER_SWITCH_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+154;
+    int UNREGISTER_USER_SWITCH_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+155;
+    int GET_RUNNING_USER_IDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+156;
+    int REQUEST_BUG_REPORT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+157;
+    int INPUT_DISPATCHING_TIMED_OUT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+158;
+    int CLEAR_PENDING_BACKUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+159;
 }
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index f60cfd6..03a26d4 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -65,7 +65,8 @@
     void scheduleDestroyActivity(IBinder token, boolean finished,
             int configChanges) throws RemoteException;
     void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo,
-            int resultCode, String data, Bundle extras, boolean sync) throws RemoteException;
+            int resultCode, String data, Bundle extras, boolean sync,
+            int sendingUser) throws RemoteException;
     static final int BACKUP_MODE_INCREMENTAL = 0;
     static final int BACKUP_MODE_FULL = 1;
     static final int BACKUP_MODE_RESTORE = 2;
@@ -105,8 +106,8 @@
     void dumpProvider(FileDescriptor fd, IBinder servicetoken, String[] args)
             throws RemoteException;
     void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
-            int resultCode, String data, Bundle extras, boolean ordered, boolean sticky)
-            throws RemoteException;
+            int resultCode, String data, Bundle extras, boolean ordered,
+            boolean sticky, int sendingUser) throws RemoteException;
     void scheduleLowMemory() throws RemoteException;
     void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException;
     void profilerControl(boolean start, String path, ParcelFileDescriptor fd, int profileType)
diff --git a/core/java/android/app/IInstrumentationWatcher.aidl b/core/java/android/app/IInstrumentationWatcher.aidl
index 405a3d8..6c8c4d6 100644
--- a/core/java/android/app/IInstrumentationWatcher.aidl
+++ b/core/java/android/app/IInstrumentationWatcher.aidl
@@ -21,7 +21,7 @@
 import android.os.Bundle;
 
 /** @hide */
-oneway interface IInstrumentationWatcher
+interface IInstrumentationWatcher
 {
     void instrumentationStatus(in ComponentName name, int resultCode,
             in Bundle results);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 6f95e26..62d4962 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -24,16 +24,13 @@
 /** {@hide} */
 interface INotificationManager
 {
-    /** @deprecated use {@link #enqueueNotificationWithTag} instead */
-    void enqueueNotification(String pkg, int id, in Notification notification, inout int[] idReceived);
-    /** @deprecated use {@link #cancelNotificationWithTag} instead */
-    void cancelNotification(String pkg, int id);
-    void cancelAllNotifications(String pkg);
+    void cancelAllNotifications(String pkg, int userId);
 
     void enqueueToast(String pkg, ITransientNotification callback, int duration);
     void cancelToast(String pkg, ITransientNotification callback);
-    void enqueueNotificationWithTag(String pkg, String tag, int id, in Notification notification, inout int[] idReceived);
-    void cancelNotificationWithTag(String pkg, String tag, int id);
+    void enqueueNotificationWithTag(String pkg, String tag, int id,
+            in Notification notification, inout int[] idReceived, int userId);
+    void cancelNotificationWithTag(String pkg, String tag, int id, int userId);
 
     void setNotificationsEnabledForPackage(String pkg, boolean enabled);
     boolean areNotificationsEnabledForPackage(String pkg);
diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl
index 688cdfd..074d343 100644
--- a/core/java/android/app/ISearchManager.aidl
+++ b/core/java/android/app/ISearchManager.aidl
@@ -30,4 +30,5 @@
    List<ResolveInfo> getGlobalSearchActivities();
    ComponentName getGlobalSearchActivity();
    ComponentName getWebSearchActivity();
+   ComponentName getAssistIntent(int userHandle);
 }
diff --git a/core/java/android/app/IStopUserCallback.aidl b/core/java/android/app/IStopUserCallback.aidl
new file mode 100644
index 0000000..19ac1d5
--- /dev/null
+++ b/core/java/android/app/IStopUserCallback.aidl
@@ -0,0 +1,27 @@
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.app;
+
+/**
+ * Callback to find out when we have finished stopping a user.
+ * {@hide}
+ */
+interface IStopUserCallback
+{
+    void userStopped(int userId);
+    void userStopAborted(int userId);
+}
diff --git a/core/java/android/app/IUserSwitchObserver.aidl b/core/java/android/app/IUserSwitchObserver.aidl
new file mode 100644
index 0000000..845897b
--- /dev/null
+++ b/core/java/android/app/IUserSwitchObserver.aidl
@@ -0,0 +1,25 @@
+/*
+ * 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.app;
+
+import android.os.IRemoteCallback;
+
+/** {@hide} */
+oneway interface IUserSwitchObserver {
+    void onUserSwitching(int newUserId, IRemoteCallback reply);
+    void onUserSwitchComplete(int newUserId);
+}
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index 69f64a1..3efd3c0 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -52,6 +52,11 @@
     void clearWallpaper();
 
     /**
+     * Return whether there is a wallpaper set with the given name.
+     */
+    boolean hasNamedWallpaper(String name);
+
+    /**
      * Sets the dimension hint for the wallpaper. These hints indicate the desired
      * minimum width and height for the wallpaper.
      */
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index cad4b01..e0856ae 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -33,6 +33,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.util.AndroidRuntimeException;
 import android.util.Log;
 import android.view.IWindowManager;
@@ -1429,6 +1430,21 @@
      */
     public void execStartActivities(Context who, IBinder contextThread,
             IBinder token, Activity target, Intent[] intents, Bundle options) {
+        execStartActivitiesAsUser(who, contextThread, token, target, intents, options,
+                UserHandle.myUserId());
+    }
+
+    /**
+     * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int)},
+     * but accepts an array of activities to be started.  Note that active
+     * {@link ActivityMonitor} objects only match against the first activity in
+     * the array.
+     *
+     * {@hide}
+     */
+    public void execStartActivitiesAsUser(Context who, IBinder contextThread,
+            IBinder token, Activity target, Intent[] intents, Bundle options,
+            int userId) {
         IApplicationThread whoThread = (IApplicationThread) contextThread;
         if (mActivityMonitors != null) {
             synchronized (mSync) {
@@ -1452,7 +1468,8 @@
                 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
             }
             int result = ActivityManagerNative.getDefault()
-                .startActivities(whoThread, intents, resolvedTypes, token, options);
+                .startActivities(whoThread, intents, resolvedTypes, token, options,
+                        userId);
             checkStartActivityResult(result, intents[0]);
         } catch (RemoteException e) {
         }
@@ -1518,6 +1535,66 @@
         return null;
     }
 
+    /**
+     * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int)},
+     * but for starting as a particular user.
+     *
+     * @param who The Context from which the activity is being started.
+     * @param contextThread The main thread of the Context from which the activity
+     *                      is being started.
+     * @param token Internal token identifying to the system who is starting
+     *              the activity; may be null.
+     * @param target Which fragment is performing the start (and thus receiving
+     *               any result).
+     * @param intent The actual Intent to start.
+     * @param requestCode Identifier for this request's result; less than zero
+     *                    if the caller is not expecting a result.
+     *
+     * @return To force the return of a particular result, return an
+     *         ActivityResult object containing the desired data; otherwise
+     *         return null.  The default implementation always returns null.
+     *
+     * @throws android.content.ActivityNotFoundException
+     *
+     * @see Activity#startActivity(Intent)
+     * @see Activity#startActivityForResult(Intent, int)
+     * @see Activity#startActivityFromChild
+     *
+     * {@hide}
+     */
+    public ActivityResult execStartActivity(
+            Context who, IBinder contextThread, IBinder token, Activity target,
+            Intent intent, int requestCode, Bundle options, UserHandle user) {
+        IApplicationThread whoThread = (IApplicationThread) contextThread;
+        if (mActivityMonitors != null) {
+            synchronized (mSync) {
+                final int N = mActivityMonitors.size();
+                for (int i=0; i<N; i++) {
+                    final ActivityMonitor am = mActivityMonitors.get(i);
+                    if (am.match(who, null, intent)) {
+                        am.mHits++;
+                        if (am.isBlocking()) {
+                            return requestCode >= 0 ? am.getResult() : null;
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+        try {
+            intent.setAllowFds(false);
+            intent.migrateExtraStreamToClipData();
+            int result = ActivityManagerNative.getDefault()
+                .startActivityAsUser(whoThread, intent,
+                        intent.resolveTypeIfNeeded(who.getContentResolver()),
+                        token, target != null ? target.mEmbeddedID : null,
+                        requestCode, 0, null, null, options, user.getIdentifier());
+            checkStartActivityResult(result, intent);
+        } catch (RemoteException e) {
+        }
+        return null;
+    }
+
     /*package*/ final void init(ActivityThread thread,
             Context instrContext, Context appContext, ComponentName component, 
             IInstrumentationWatcher watcher) {
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index ef61af7..22a21cd 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -16,13 +16,12 @@
 
 package android.app;
 
-import android.content.Context;
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.IBinder;
-import android.os.ServiceManager;
 import android.view.IWindowManager;
 import android.view.IOnKeyguardExitResult;
+import android.view.WindowManagerGlobal;
 
 /**
  * Class that can be used to lock and unlock the keyboard. Get an instance of this 
@@ -111,7 +110,7 @@
 
 
     KeyguardManager() {
-        mWM = IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
+        mWM = WindowManagerGlobal.getWindowManagerService();
     }
 
     /**
diff --git a/core/java/android/app/LauncherActivity.java b/core/java/android/app/LauncherActivity.java
index 8eb9ba4..96c7246 100644
--- a/core/java/android/app/LauncherActivity.java
+++ b/core/java/android/app/LauncherActivity.java
@@ -439,14 +439,21 @@
     protected List<ResolveInfo> onQueryPackageManager(Intent queryIntent) {
         return mPackageManager.queryIntentActivities(queryIntent, /* no flags */ 0);
     }
-    
+
+    /**
+     * @hide
+     */
+    protected void onSortResultList(List<ResolveInfo> results) {
+        Collections.sort(results, new ResolveInfo.DisplayNameComparator(mPackageManager));
+    }
+
     /**
      * Perform the query to determine which results to show and return a list of them.
      */
     public List<ListItem> makeListItems() {
         // Load all matching activities and sort correctly
         List<ResolveInfo> list = onQueryPackageManager(mIntent);
-        Collections.sort(list, new ResolveInfo.DisplayNameComparator(mPackageManager));
+        onSortResultList(list);
 
         ArrayList<ListItem> result = new ArrayList<ListItem>(list.size());
         int listSize = list.size();
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index be4b284..0a9ed58 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -37,10 +37,11 @@
 import android.os.RemoteException;
 import android.os.StrictMode;
 import android.os.Trace;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.AndroidRuntimeException;
 import android.util.Slog;
 import android.view.CompatibilityInfoHolder;
+import android.view.Display;
 
 import java.io.File;
 import java.io.IOException;
@@ -120,8 +121,8 @@
         final int myUid = Process.myUid();
         mResDir = aInfo.uid == myUid ? aInfo.sourceDir
                 : aInfo.publicSourceDir;
-        if (!UserId.isSameUser(aInfo.uid, myUid) && !Process.isIsolated()) {
-            aInfo.dataDir = PackageManager.getDataDirForUser(UserId.getUserId(myUid),
+        if (!UserHandle.isSameUser(aInfo.uid, myUid) && !Process.isIsolated()) {
+            aInfo.dataDir = PackageManager.getDataDirForUser(UserHandle.getUserId(myUid),
                     mPackageName);
         }
         mSharedLibraries = aInfo.sharedLibraryFiles;
@@ -139,7 +140,8 @@
                     ContextImpl.createSystemContext(mainThread);
                 ActivityThread.mSystemContext.getResources().updateConfiguration(
                          mainThread.getConfiguration(),
-                         mainThread.getDisplayMetricsLocked(compatInfo, false),
+                         mainThread.getDisplayMetricsLocked(
+                                 Display.DEFAULT_DISPLAY, compatInfo),
                          compatInfo);
                 //Slog.i(TAG, "Created system resources "
                 //        + mSystemContext.getResources() + ": "
@@ -195,7 +197,7 @@
         ApplicationInfo ai = null;
         try {
             ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
-                    PackageManager.GET_SHARED_LIBRARY_FILES, UserId.myUserId());
+                    PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId());
         } catch (RemoteException e) {
             throw new AssertionError(e);
         }
@@ -358,7 +360,7 @@
         IPackageManager pm = ActivityThread.getPackageManager();
         android.content.pm.PackageInfo pi;
         try {
-            pi = pm.getPackageInfo(mPackageName, 0, UserId.myUserId());
+            pi = pm.getPackageInfo(mPackageName, 0, UserHandle.myUserId());
         } catch (RemoteException e) {
             throw new AssertionError(e);
         }
@@ -471,7 +473,8 @@
 
     public Resources getResources(ActivityThread mainThread) {
         if (mResources == null) {
-            mResources = mainThread.getTopLevelResources(mResDir, this);
+            mResources = mainThread.getTopLevelResources(mResDir,
+                    Display.DEFAULT_DISPLAY, null, this);
         }
         return mResources;
     }
@@ -667,8 +670,8 @@
                 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
                 mStrongRef = strong ? rd : null;
             }
-            public void performReceive(Intent intent, int resultCode,
-                    String data, Bundle extras, boolean ordered, boolean sticky) {
+            public void performReceive(Intent intent, int resultCode, String data,
+                    Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                 LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
                 if (ActivityThread.DEBUG_BROADCAST) {
                     int seq = intent.getIntExtra("seq", -1);
@@ -677,7 +680,7 @@
                 }
                 if (rd != null) {
                     rd.performReceive(intent, resultCode, data, extras,
-                            ordered, sticky);
+                            ordered, sticky, sendingUser);
                 } else {
                     // The activity manager dispatched a broadcast to a registered
                     // receiver in this process, but before it could be delivered the
@@ -713,10 +716,10 @@
             private final boolean mOrdered;
 
             public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
-                    boolean ordered, boolean sticky) {
+                    boolean ordered, boolean sticky, int sendingUser) {
                 super(resultCode, resultData, resultExtras,
                         mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED,
-                        ordered, sticky, mIIntentReceiver.asBinder());
+                        ordered, sticky, mIIntentReceiver.asBinder(), sendingUser);
                 mCurIntent = intent;
                 mOrdered = ordered;
             }
@@ -827,14 +830,15 @@
             return mUnregisterLocation;
         }
 
-        public void performReceive(Intent intent, int resultCode,
-                String data, Bundle extras, boolean ordered, boolean sticky) {
+        public void performReceive(Intent intent, int resultCode, String data,
+                Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
             if (ActivityThread.DEBUG_BROADCAST) {
                 int seq = intent.getIntExtra("seq", -1);
                 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
                         + " to " + mReceiver);
             }
-            Args args = new Args(intent, resultCode, data, extras, ordered, sticky);
+            Args args = new Args(intent, resultCode, data, extras, ordered,
+                    sticky, sendingUser);
             if (!mActivityThread.post(args)) {
                 if (mRegistered && ordered) {
                     IActivityManager mgr = ActivityManagerNative.getDefault();
diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java
index ff71ee7..fd0f0bf 100644
--- a/core/java/android/app/LoaderManager.java
+++ b/core/java/android/app/LoaderManager.java
@@ -17,7 +17,6 @@
 package android.app;
 
 import android.content.Loader;
-import android.content.Loader.OnLoadCanceledListener;
 import android.os.Bundle;
 import android.util.DebugUtils;
 import android.util.Log;
@@ -213,6 +212,8 @@
     // previously run loader until the new loader's data is available.
     final SparseArray<LoaderInfo> mInactiveLoaders = new SparseArray<LoaderInfo>();
 
+    final String mWho;
+
     Activity mActivity;
     boolean mStarted;
     boolean mRetaining;
@@ -529,7 +530,8 @@
         }
     }
     
-    LoaderManagerImpl(Activity activity, boolean started) {
+    LoaderManagerImpl(String who, Activity activity, boolean started) {
+        mWho = who;
         mActivity = activity;
         mStarted = started;
     }
diff --git a/core/java/android/app/MediaRouteActionProvider.java b/core/java/android/app/MediaRouteActionProvider.java
index c2f5ac1..63b641c 100644
--- a/core/java/android/app/MediaRouteActionProvider.java
+++ b/core/java/android/app/MediaRouteActionProvider.java
@@ -26,6 +26,7 @@
 import android.view.ActionProvider;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.ViewGroup;
 
 import java.lang.ref.WeakReference;
 
@@ -80,8 +81,11 @@
         }
         mMenuItem = item;
         mView = new MediaRouteButton(mContext);
+        mView.setCheatSheetEnabled(true);
         mView.setRouteTypes(mRouteTypes);
         mView.setExtendedSettingsClickListener(mExtendedSettingsListener);
+        mView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.MATCH_PARENT));
         return mView;
     }
 
diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java
index b0bfe74..3ecafc3 100644
--- a/core/java/android/app/MediaRouteButton.java
+++ b/core/java/android/app/MediaRouteButton.java
@@ -23,14 +23,19 @@
 import android.content.ContextWrapper;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.media.MediaRouter;
 import android.media.MediaRouter.RouteGroup;
 import android.media.MediaRouter.RouteInfo;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.view.Gravity;
+import android.view.HapticFeedbackConstants;
 import android.view.SoundEffectConstants;
 import android.view.View;
+import android.widget.Toast;
 
 public class MediaRouteButton extends View {
     private static final String TAG = "MediaRouteButton";
@@ -44,6 +49,8 @@
     private Drawable mRemoteIndicator;
     private boolean mRemoteActive;
     private boolean mToggleMode;
+    private boolean mCheatSheetEnabled;
+    private boolean mIsConnecting;
 
     private int mMinWidth;
     private int mMinHeight;
@@ -51,6 +58,10 @@
     private OnClickListener mExtendedSettingsClickListener;
     private MediaRouteChooserDialogFragment mDialogFragment;
 
+    private static final int[] CHECKED_STATE_SET = {
+        R.attr.state_checked
+    };
+
     private static final int[] ACTIVATED_STATE_SET = {
         R.attr.state_activated
     };
@@ -82,6 +93,7 @@
         a.recycle();
 
         setClickable(true);
+        setLongClickable(true);
 
         setRouteTypes(routeTypes);
     }
@@ -129,6 +141,52 @@
         return handled;
     }
 
+    void setCheatSheetEnabled(boolean enable) {
+        mCheatSheetEnabled = enable;
+    }
+
+    @Override
+    public boolean performLongClick() {
+        if (super.performLongClick()) {
+            return true;
+        }
+
+        if (!mCheatSheetEnabled) {
+            return false;
+        }
+
+        final CharSequence contentDesc = getContentDescription();
+        if (TextUtils.isEmpty(contentDesc)) {
+            // Don't show the cheat sheet if we have no description
+            return false;
+        }
+
+        final int[] screenPos = new int[2];
+        final Rect displayFrame = new Rect();
+        getLocationOnScreen(screenPos);
+        getWindowVisibleDisplayFrame(displayFrame);
+
+        final Context context = getContext();
+        final int width = getWidth();
+        final int height = getHeight();
+        final int midy = screenPos[1] + height / 2;
+        final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
+
+        Toast cheatSheet = Toast.makeText(context, contentDesc, Toast.LENGTH_SHORT);
+        if (midy < displayFrame.height()) {
+            // Show along the top; follow action buttons
+            cheatSheet.setGravity(Gravity.TOP | Gravity.END,
+                    screenWidth - screenPos[0] - width / 2, height);
+        } else {
+            // Show along the bottom center
+            cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height);
+        }
+        cheatSheet.show();
+        performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+
+        return true;
+    }
+
     public void setRouteTypes(int types) {
         if (types == mRouteTypes) {
             // Already registered; nothing to do.
@@ -157,10 +215,21 @@
     }
 
     void updateRemoteIndicator() {
-        final boolean isRemote =
-                mRouter.getSelectedRoute(mRouteTypes) != mRouter.getSystemAudioRoute();
+        final RouteInfo selected = mRouter.getSelectedRoute(mRouteTypes);
+        final boolean isRemote = selected != mRouter.getSystemAudioRoute();
+        final boolean isConnecting = selected.getStatusCode() == RouteInfo.STATUS_CONNECTING;
+
+        boolean needsRefresh = false;
         if (mRemoteActive != isRemote) {
             mRemoteActive = isRemote;
+            needsRefresh = true;
+        }
+        if (mIsConnecting != isConnecting) {
+            mIsConnecting = isConnecting;
+            needsRefresh = true;
+        }
+
+        if (needsRefresh) {
             refreshDrawableState();
         }
     }
@@ -168,27 +237,41 @@
     void updateRouteCount() {
         final int N = mRouter.getRouteCount();
         int count = 0;
+        boolean hasVideoRoutes = false;
         for (int i = 0; i < N; i++) {
             final RouteInfo route = mRouter.getRouteAt(i);
-            if ((route.getSupportedTypes() & mRouteTypes) != 0) {
+            final int routeTypes = route.getSupportedTypes();
+            if ((routeTypes & mRouteTypes) != 0) {
                 if (route instanceof RouteGroup) {
                     count += ((RouteGroup) route).getRouteCount();
                 } else {
                     count++;
                 }
+                if ((routeTypes & MediaRouter.ROUTE_TYPE_LIVE_VIDEO) != 0) {
+                    hasVideoRoutes = true;
+                }
             }
         }
 
         setEnabled(count != 0);
 
-        // Only allow toggling if we have more than just user routes
-        mToggleMode = count == 2 && (mRouteTypes & MediaRouter.ROUTE_TYPE_LIVE_AUDIO) != 0;
+        // Only allow toggling if we have more than just user routes.
+        // Don't toggle if we support video routes, we may have to let the dialog scan.
+        mToggleMode = count == 2 && (mRouteTypes & MediaRouter.ROUTE_TYPE_LIVE_AUDIO) != 0 &&
+                !hasVideoRoutes;
     }
 
     @Override
     protected int[] onCreateDrawableState(int extraSpace) {
         final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
-        if (mRemoteActive) {
+
+        // Technically we should be handling this more completely, but these
+        // are implementation details here. Checked is used to express the connecting
+        // drawable state and it's mutually exclusive with activated for the purposes
+        // of state selection here.
+        if (mIsConnecting) {
+            mergeDrawableStates(drawableState, CHECKED_STATE_SET);
+        } else if (mRemoteActive) {
             mergeDrawableStates(drawableState, ACTIVATED_STATE_SET);
         }
         return drawableState;
@@ -366,6 +449,11 @@
         }
 
         @Override
+        public void onRouteChanged(MediaRouter router, RouteInfo info) {
+            updateRemoteIndicator();
+        }
+
+        @Override
         public void onRouteAdded(MediaRouter router, RouteInfo info) {
             updateRouteCount();
         }
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index 35cc324..396f910 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -1,6 +1,5 @@
 package android.app;
 
-import com.android.internal.view.IInputMethodCallback;
 import com.android.internal.view.IInputMethodSession;
 
 import android.content.Context;
@@ -119,7 +118,7 @@
         }
     }
     
-    static class InputMethodCallback extends IInputMethodCallback.Stub {
+    static final class InputMethodCallback implements InputMethodManager.FinishedEventCallback {
         WeakReference<NativeActivity> mNa;
 
         InputMethodCallback(NativeActivity na) {
@@ -133,11 +132,6 @@
                 na.finishPreDispatchKeyEventNative(na.mNativeHandle, seq, handled);
             }
         }
-
-        @Override
-        public void sessionCreated(IInputMethodSession session) {
-            // Stub -- not for use in the client.
-        }
     }
 
     @Override
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index cb83dc2..e79b214 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -29,6 +29,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.IntProperty;
 import android.util.Log;
@@ -893,6 +894,22 @@
         return sb.toString();
     }
 
+    /** {@hide} */
+    public void setUser(UserHandle user) {
+        if (user.getIdentifier() == UserHandle.USER_ALL) {
+            user = UserHandle.OWNER;
+        }
+        if (tickerView != null) {
+            tickerView.setUser(user);
+        }
+        if (contentView != null) {
+            contentView.setUser(user);
+        }
+        if (bigContentView != null) {
+            bigContentView.setUser(user);
+        }
+    }
+
     /**
      * Builder class for {@link Notification} objects.
      * 
@@ -951,6 +968,7 @@
         private ArrayList<Action> mActions = new ArrayList<Action>(MAX_ACTION_BUTTONS);
         private boolean mUseChronometer;
         private Style mStyle;
+        private boolean mShowWhen = true;
 
         /**
          * Constructs a new Builder with the defaults:
@@ -982,8 +1000,9 @@
 
         /**
          * Add a timestamp pertaining to the notification (usually the time the event occurred).
+         * It will be shown in the notification content view by default; use
+         * {@link Builder#setShowWhen(boolean) setShowWhen} to control this.
          *
-
          * @see Notification#when
          */
         public Builder setWhen(long when) {
@@ -992,6 +1011,15 @@
         }
 
         /**
+         * Control whether the timestamp set with {@link Builder#setWhen(long) setWhen} is shown
+         * in the content view.
+         */
+        public Builder setShowWhen(boolean show) {
+            mShowWhen = show;
+            return this;
+        }
+
+        /**
          * Show the {@link Notification#when} field as a stopwatch.
          * 
          * Instead of presenting <code>when</code> as a timestamp, the notification will show an 
@@ -1467,7 +1495,7 @@
                 contentView.setViewPadding(R.id.line1, 0, 0, 0, 0);
             }
 
-            if (mWhen != 0) {
+            if (mWhen != 0 && mShowWhen) {
                 if (mUseChronometer) {
                     contentView.setViewVisibility(R.id.chronometer, View.VISIBLE);
                     contentView.setLong(R.id.chronometer, "setBase",
@@ -1477,7 +1505,10 @@
                     contentView.setViewVisibility(R.id.time, View.VISIBLE);
                     contentView.setLong(R.id.time, "setTime", mWhen);
                 }
+            } else {
+                contentView.setViewVisibility(R.id.time, View.GONE);
             }
+
             contentView.setViewVisibility(R.id.line3, showLine3 ? View.VISIBLE : View.GONE);
             contentView.setViewVisibility(R.id.overflow_divider, showLine3 ? View.VISIBLE : View.GONE);
             return contentView;
@@ -1777,7 +1808,7 @@
      * 
      * This class is a "rebuilder": It consumes a Builder object and modifies its behavior, like so:
      * <pre class="prettyprint">
-     * Notification noti = new Notification.BigPictureStyle(
+     * Notification noti = new Notification.BigTextStyle(
      *      new Notification.Builder()
      *         .setContentTitle(&quot;New mail from &quot; + sender.toString())
      *         .setContentText(subject)
@@ -1923,6 +1954,7 @@
                 contentView.setViewVisibility(rowId, View.GONE);
             }
 
+
             int i=0;
             while (i < mTexts.size() && i < rowIds.length) {
                 CharSequence str = mTexts.get(i);
@@ -1933,11 +1965,11 @@
                 i++;
             }
 
-            if  (mTexts.size() > rowIds.length) {
-                contentView.setViewVisibility(R.id.inbox_more, View.VISIBLE);
-            } else {
-                contentView.setViewVisibility(R.id.inbox_more, View.GONE);
-            }
+            contentView.setViewVisibility(R.id.inbox_end_pad,
+                    mTexts.size() > 0 ? View.VISIBLE : View.GONE);
+
+            contentView.setViewVisibility(R.id.inbox_more,
+                    mTexts.size() > rowIds.length ? View.VISIBLE : View.GONE);
 
             return contentView;
         }
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index bf83f5e..0acad75 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -17,11 +17,11 @@
 package android.app;
 
 import android.content.Context;
-import android.os.Binder;
-import android.os.RemoteException;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.Log;
 
 /**
@@ -88,6 +88,11 @@
         mContext = context;
     }
 
+    /** {@hide} */
+    public static NotificationManager from(Context context) {
+        return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+    }
+
     /**
      * Post a notification to be shown in the status bar. If a notification with
      * the same id has already been posted by your application and has not yet been canceled, it
@@ -119,9 +124,35 @@
         int[] idOut = new int[1];
         INotificationManager service = getService();
         String pkg = mContext.getPackageName();
+        if (notification.sound != null) {
+            notification.sound = notification.sound.getCanonicalUri();
+        }
         if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
         try {
-            service.enqueueNotificationWithTag(pkg, tag, id, notification, idOut);
+            service.enqueueNotificationWithTag(pkg, tag, id, notification, idOut,
+                    UserHandle.myUserId());
+            if (id != idOut[0]) {
+                Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
+            }
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void notifyAsUser(String tag, int id, Notification notification, UserHandle user)
+    {
+        int[] idOut = new int[1];
+        INotificationManager service = getService();
+        String pkg = mContext.getPackageName();
+        if (notification.sound != null) {
+            notification.sound = notification.sound.getCanonicalUri();
+        }
+        if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
+        try {
+            service.enqueueNotificationWithTag(pkg, tag, id, notification, idOut,
+                    user.getIdentifier());
             if (id != idOut[0]) {
                 Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
             }
@@ -150,7 +181,21 @@
         String pkg = mContext.getPackageName();
         if (localLOGV) Log.v(TAG, pkg + ": cancel(" + id + ")");
         try {
-            service.cancelNotificationWithTag(pkg, tag, id);
+            service.cancelNotificationWithTag(pkg, tag, id, UserHandle.myUserId());
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void cancelAsUser(String tag, int id, UserHandle user)
+    {
+        INotificationManager service = getService();
+        String pkg = mContext.getPackageName();
+        if (localLOGV) Log.v(TAG, pkg + ": cancel(" + id + ")");
+        try {
+            service.cancelNotificationWithTag(pkg, tag, id, user.getIdentifier());
         } catch (RemoteException e) {
         }
     }
@@ -165,7 +210,7 @@
         String pkg = mContext.getPackageName();
         if (localLOGV) Log.v(TAG, pkg + ": cancelAll()");
         try {
-            service.cancelAllNotifications(pkg);
+            service.cancelAllNotifications(pkg, UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 8adc8a2..d36d99d 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -27,12 +27,13 @@
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
 import android.util.AndroidException;
 
 /**
  * A description of an Intent and target action to perform with it.  Instances
- * of this class are created with {@link #getActivity},
- * {@link #getBroadcast}, {@link #getService}; the returned object can be
+ * of this class are created with {@link #getActivity}, {@link #getActivities},
+ * {@link #getBroadcast}, and {@link #getService}; the returned object can be
  * handed to other applications so that they can perform the action you
  * described on your behalf at a later time.
  *
@@ -53,6 +54,34 @@
  * categories, and components, and same flags), it will receive a PendingIntent
  * representing the same token if that is still valid, and can thus call
  * {@link #cancel} to remove it.
+ *
+ * <p>Because of this behavior, it is important to know when two Intents
+ * are considered to be the same for purposes of retrieving a PendingIntent.
+ * A common mistake people make is to create multiple PendingIntent objects
+ * with Intents that only vary in their "extra" contents, expecting to get
+ * a different PendingIntent each time.  This does <em>not</em> happen.  The
+ * parts of the Intent that are used for matching are the same ones defined
+ * by {@link Intent#filterEquals(Intent) Intent.filterEquals}.  If you use two
+ * Intent objects that are equivalent as per
+ * {@link Intent#filterEquals(Intent) Intent.filterEquals}, then you will get
+ * the same PendingIntent for both of them.
+ *
+ * <p>There are two typical ways to deal with this.
+ *
+ * <p>If you truly need multiple distinct PendingIntent objects active at
+ * the same time (such as to use as two notifications that are both shown
+ * at the same time), then you will need to ensure there is something that
+ * is different about them to associate them with different PendingIntents.
+ * This may be any of the Intent attributes considered by
+ * {@link Intent#filterEquals(Intent) Intent.filterEquals}, or different
+ * request code integers supplied to {@link #getActivity}, {@link #getActivities},
+ * {@link #getBroadcast}, or {@link #getService}.
+ *
+ * <p>If you only need one PendingIntent active at a time for any of the
+ * Intents you will use, then you can alternatively use the flags
+ * {@link #FLAG_CANCEL_CURRENT} or {@link #FLAG_UPDATE_CURRENT} to either
+ * cancel or modify whatever current PendingIntent is associated with the
+ * Intent you are supplying.
  */
 public final class PendingIntent implements Parcelable {
     private final IIntentSender mTarget;
@@ -146,8 +175,8 @@
             mWho = who;
             mHandler = handler;
         }
-        public void performReceive(Intent intent, int resultCode,
-                String data, Bundle extras, boolean serialized, boolean sticky) {
+        public void performReceive(Intent intent, int resultCode, String data,
+                Bundle extras, boolean serialized, boolean sticky, int sendingUser) {
             mIntent = intent;
             mResultCode = resultCode;
             mResultData = data;
@@ -227,7 +256,31 @@
                     ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
                     null, null, requestCode, new Intent[] { intent },
                     resolvedType != null ? new String[] { resolvedType } : null,
-                    flags, options);
+                    flags, options, UserHandle.myUserId());
+            return target != null ? new PendingIntent(target) : null;
+        } catch (RemoteException e) {
+        }
+        return null;
+    }
+
+    /**
+     * @hide
+     * Note that UserHandle.CURRENT will be interpreted at the time the
+     * activity is started, not when the pending intent is created.
+     */
+    public static PendingIntent getActivityAsUser(Context context, int requestCode,
+            Intent intent, int flags, Bundle options, UserHandle user) {
+        String packageName = context.getPackageName();
+        String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
+                context.getContentResolver()) : null;
+        try {
+            intent.setAllowFds(false);
+            IIntentSender target =
+                ActivityManagerNative.getDefault().getIntentSender(
+                    ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
+                    null, null, requestCode, new Intent[] { intent },
+                    resolvedType != null ? new String[] { resolvedType } : null,
+                    flags, options, user.getIdentifier());
             return target != null ? new PendingIntent(target) : null;
         } catch (RemoteException e) {
         }
@@ -333,7 +386,33 @@
             IIntentSender target =
                 ActivityManagerNative.getDefault().getIntentSender(
                     ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
-                    null, null, requestCode, intents, resolvedTypes, flags, options);
+                    null, null, requestCode, intents, resolvedTypes, flags, options,
+                    UserHandle.myUserId());
+            return target != null ? new PendingIntent(target) : null;
+        } catch (RemoteException e) {
+        }
+        return null;
+    }
+
+    /**
+     * @hide
+     * Note that UserHandle.CURRENT will be interpreted at the time the
+     * activity is started, not when the pending intent is created.
+     */
+    public static PendingIntent getActivitiesAsUser(Context context, int requestCode,
+            Intent[] intents, int flags, Bundle options, UserHandle user) {
+        String packageName = context.getPackageName();
+        String[] resolvedTypes = new String[intents.length];
+        for (int i=0; i<intents.length; i++) {
+            intents[i].setAllowFds(false);
+            resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver());
+        }
+        try {
+            IIntentSender target =
+                ActivityManagerNative.getDefault().getIntentSender(
+                    ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
+                    null, null, requestCode, intents, resolvedTypes,
+                    flags, options, user.getIdentifier());
             return target != null ? new PendingIntent(target) : null;
         } catch (RemoteException e) {
         }
@@ -361,6 +440,17 @@
      */
     public static PendingIntent getBroadcast(Context context, int requestCode,
             Intent intent, int flags) {
+        return getBroadcastAsUser(context, requestCode, intent, flags,
+                new UserHandle(UserHandle.myUserId()));
+    }
+
+    /**
+     * @hide
+     * Note that UserHandle.CURRENT will be interpreted at the time the
+     * broadcast is sent, not when the pending intent is created.
+     */
+    public static PendingIntent getBroadcastAsUser(Context context, int requestCode,
+            Intent intent, int flags, UserHandle userHandle) {
         String packageName = context.getPackageName();
         String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
                 context.getContentResolver()) : null;
@@ -371,7 +461,7 @@
                     ActivityManager.INTENT_SENDER_BROADCAST, packageName,
                     null, null, requestCode, new Intent[] { intent },
                     resolvedType != null ? new String[] { resolvedType } : null,
-                    flags, null);
+                    flags, null, userHandle.getIdentifier());
             return target != null ? new PendingIntent(target) : null;
         } catch (RemoteException e) {
         }
@@ -410,7 +500,7 @@
                     ActivityManager.INTENT_SENDER_SERVICE, packageName,
                     null, null, requestCode, new Intent[] { intent },
                     resolvedType != null ? new String[] { resolvedType } : null,
-                    flags, null);
+                    flags, null, UserHandle.myUserId());
             return target != null ? new PendingIntent(target) : null;
         } catch (RemoteException e) {
         }
@@ -598,6 +688,20 @@
     }
 
     /**
+     * @deprecated Renamed to {@link #getCreatorPackage()}.
+     */
+    @Deprecated
+    public String getTargetPackage() {
+        try {
+            return ActivityManagerNative.getDefault()
+                .getPackageForIntentSender(mTarget);
+        } catch (RemoteException e) {
+            // Should never happen.
+            return null;
+        }
+    }
+
+    /**
      * Return the package name of the application that created this
      * PendingIntent, that is the identity under which you will actually be
      * sending the Intent.  The returned string is supplied by the system, so
@@ -606,7 +710,7 @@
      * @return The package name of the PendingIntent, or null if there is
      * none associated with it.
      */
-    public String getTargetPackage() {
+    public String getCreatorPackage() {
         try {
             return ActivityManagerNative.getDefault()
                 .getPackageForIntentSender(mTarget);
@@ -617,6 +721,47 @@
     }
 
     /**
+     * Return the uid of the application that created this
+     * PendingIntent, that is the identity under which you will actually be
+     * sending the Intent.  The returned integer is supplied by the system, so
+     * that an application can not spoof its uid.
+     *
+     * @return The uid of the PendingIntent, or -1 if there is
+     * none associated with it.
+     */
+    public int getCreatorUid() {
+        try {
+            return ActivityManagerNative.getDefault()
+                .getUidForIntentSender(mTarget);
+        } catch (RemoteException e) {
+            // Should never happen.
+            return -1;
+        }
+    }
+
+    /**
+     * Return the user handle of the application that created this
+     * PendingIntent, that is the user under which you will actually be
+     * sending the Intent.  The returned UserHandle is supplied by the system, so
+     * that an application can not spoof its user.  See
+     * {@link android.os.Process#myUserHandle() Process.myUserHandle()} for
+     * more explanation of user handles.
+     *
+     * @return The user handle of the PendingIntent, or null if there is
+     * none associated with it.
+     */
+    public UserHandle getCreatorUserHandle() {
+        try {
+            int uid = ActivityManagerNative.getDefault()
+                .getUidForIntentSender(mTarget);
+            return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
+        } catch (RemoteException e) {
+            // Should never happen.
+            return null;
+        }
+    }
+
+    /**
      * @hide
      * Check to verify that this PendingIntent targets a specific package.
      */
diff --git a/core/java/android/app/Presentation.java b/core/java/android/app/Presentation.java
new file mode 100644
index 0000000..16a0c57
--- /dev/null
+++ b/core/java/android/app/Presentation.java
@@ -0,0 +1,353 @@
+/*
+ * 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.app;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
+import android.view.ContextThemeWrapper;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.WindowManagerImpl;
+import android.os.Handler;
+import android.os.Message;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.TypedValue;
+
+/**
+ * Base class for presentations.
+ * <p>
+ * A presentation is a special kind of dialog whose purpose is to present
+ * content on a secondary display.  A {@link Presentation} is associated with
+ * the target {@link Display} at creation time and configures its context and
+ * resource configuration according to the display's metrics.
+ * </p><p>
+ * Notably, the {@link Context} of a presentation is different from the context
+ * of its containing {@link Activity}.  It is important to inflate the layout
+ * of a presentation and load other resources using the presentation's own context
+ * to ensure that assets of the correct size and density for the target display
+ * are loaded.
+ * </p><p>
+ * A presentation is automatically canceled (see {@link Dialog#cancel()}) when
+ * the display to which it is attached is removed.  An activity should take
+ * care of pausing and resuming whatever content is playing within the presentation
+ * whenever the activity itself is paused or resumed.
+ * </p>
+ *
+ * <h3>Choosing a presentation display</h3>
+ * <p>
+ * Before showing a {@link Presentation} it's important to choose the {@link Display}
+ * on which it will appear.  Choosing a presentation display is sometimes difficult
+ * because there may be multiple displays attached.  Rather than trying to guess
+ * which display is best, an application should let the system choose a suitable
+ * presentation display.
+ * </p><p>
+ * There are two main ways to choose a {@link Display}.
+ * </p>
+ *
+ * <h4>Using the media router to choose a presentation display</h4>
+ * <p>
+ * The easiest way to choose a presentation display is to use the
+ * {@link android.media.MediaRouter MediaRouter} API.  The media router service keeps
+ * track of which audio and video routes are available on the system.
+ * The media router sends notifications whenever routes are selected or unselected
+ * or when the preferred presentation display of a route changes.
+ * So an application can simply watch for these notifications and show or dismiss
+ * a presentation on the preferred presentation display automatically.
+ * </p><p>
+ * The preferred presentation display is the display that the media router recommends
+ * that the application should use if it wants to show content on the secondary display.
+ * Sometimes there may not be a preferred presentation display in which
+ * case the application should show its content locally without using a presentation.
+ * </p><p>
+ * Here's how to use the media router to create and show a presentation on the preferred
+ * presentation display using {@link android.media.MediaRouter.RouteInfo#getPresentationDisplay()}.
+ * </p>
+ * <pre>
+ * MediaRouter mediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
+ * MediaRouter.RouteInfo route = mediaRouter.getSelectedRoute();
+ * if (route != null) {
+ *     Display presentationDisplay = route.getPresentationDisplay();
+ *     if (presentationDisplay != null) {
+ *         Presentation presentation = new MyPresentation(context, presentationDisplay);
+ *         presentation.show();
+ *     }
+ * }</pre>
+ * <p>
+ * The following sample code from <code>ApiDemos</code> demonstrates how to use the media
+ * router to automatically switch between showing content in the main activity and showing
+ * the content in a presentation when a presentation display is available.
+ * </p>
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/PresentationWithMediaRouterActivity.java
+ *      activity}
+ *
+ * <h4>Using the display manager to choose a presentation display</h4>
+ * <p>
+ * Another way to choose a presentation display is to use the {@link DisplayManager} API
+ * directly.  The display manager service provides functions to enumerate and describe all
+ * displays that are attached to the system including displays that may be used
+ * for presentations.
+ * </p><p>
+ * The display manager keeps track of all displays in the system.  However, not all
+ * displays are appropriate for showing presentations.  For example, if an activity
+ * attempted to show a presentation on the main display it might obscure its own content
+ * (it's like opening a dialog on top of your activity).
+ * </p><p>
+ * Here's how to identify suitable displays for showing presentations using
+ * {@link DisplayManager#getDisplays(String)} and the
+ * {@link DisplayManager#DISPLAY_CATEGORY_PRESENTATION} category.
+ * </p>
+ * <pre>
+ * DisplayManager displayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
+ * Display[] presentationDisplays = displayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
+ * if (presentationDisplays.length > 0) {
+ *     // If there is more than one suitable presentation display, then we could consider
+ *     // giving the user a choice.  For this example, we simply choose the first display
+ *     // which is the one the system recommends as the preferred presentation display.
+ *     Display display = presentationDisplays[0];
+ *     Presentation presentation = new MyPresentation(context, presentationDisplay);
+ *     presentation.show();
+ * }</pre>
+ * <p>
+ * The following sample code from <code>ApiDemos</code> demonstrates how to use the display
+ * manager to enumerate displays and show content on multiple presentation displays
+ * simultaneously.
+ * </p>
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java
+ *      activity}
+ *
+ * @see android.media.MediaRouter#ROUTE_TYPE_LIVE_VIDEO for information on about live
+ * video routes and how to obtain the preferred presentation display for the
+ * current media route.
+ * @see DisplayManager for information on how to enumerate displays and receive
+ * notifications when displays are added or removed.
+ */
+public class Presentation extends Dialog {
+    private static final String TAG = "Presentation";
+
+    private static final int MSG_CANCEL = 1;
+
+    private final Display mDisplay;
+    private final DisplayManager mDisplayManager;
+
+    /**
+     * Creates a new presentation that is attached to the specified display
+     * using the default theme.
+     *
+     * @param outerContext The context of the application that is showing the presentation.
+     * The presentation will create its own context (see {@link #getContext()}) based
+     * on this context and information about the associated display.
+     * @param display The display to which the presentation should be attached.
+     */
+    public Presentation(Context outerContext, Display display) {
+        this(outerContext, display, 0);
+    }
+
+    /**
+     * Creates a new presentation that is attached to the specified display
+     * using the optionally specified theme.
+     *
+     * @param outerContext The context of the application that is showing the presentation.
+     * The presentation will create its own context (see {@link #getContext()}) based
+     * on this context and information about the associated display.
+     * @param display The display to which the presentation should be attached.
+     * @param theme A style resource describing the theme to use for the window.
+     * See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes">
+     * Style and Theme Resources</a> for more information about defining and using
+     * styles.  This theme is applied on top of the current theme in
+     * <var>outerContext</var>.  If 0, the default presentation theme will be used.
+     */
+    public Presentation(Context outerContext, Display display, int theme) {
+        super(createPresentationContext(outerContext, display, theme), theme, false);
+
+        mDisplay = display;
+        mDisplayManager = (DisplayManager)getContext().getSystemService(Context.DISPLAY_SERVICE);
+
+        getWindow().setGravity(Gravity.FILL);
+        setCanceledOnTouchOutside(false);
+    }
+
+    /**
+     * Gets the {@link Display} that this presentation appears on.
+     *
+     * @return The display.
+     */
+    public Display getDisplay() {
+        return mDisplay;
+    }
+
+    /**
+     * Gets the {@link Resources} that should be used to inflate the layout of this presentation.
+     * This resources object has been configured according to the metrics of the
+     * display that the presentation appears on.
+     *
+     * @return The presentation resources object.
+     */
+    public Resources getResources() {
+        return getContext().getResources();
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
+
+        // Since we were not watching for display changes until just now, there is a
+        // chance that the display metrics have changed.  If so, we will need to
+        // dismiss the presentation immediately.  This case is expected
+        // to be rare but surprising, so we'll write a log message about it.
+        if (!isConfigurationStillValid()) {
+            Log.i(TAG, "Presentation is being immediately dismissed because the "
+                    + "display metrics have changed since it was created.");
+            mHandler.sendEmptyMessage(MSG_CANCEL);
+        }
+    }
+
+    @Override
+    protected void onStop() {
+        mDisplayManager.unregisterDisplayListener(mDisplayListener);
+        super.onStop();
+    }
+
+    /**
+     * Inherited from {@link Dialog#show}. Will throw
+     * {@link android.view.WindowManager.InvalidDisplayException} if the specified secondary
+     * {@link Display} can't be found.
+     */
+    @Override
+    public void show() {
+        super.show();
+    }
+
+    /**
+     * Called by the system when the {@link Display} to which the presentation
+     * is attached has been removed.
+     *
+     * The system automatically calls {@link #cancel} to dismiss the presentation
+     * after sending this event.
+     *
+     * @see #getDisplay
+     */
+    public void onDisplayRemoved() {
+    }
+
+    /**
+     * Called by the system when the properties of the {@link Display} to which
+     * the presentation is attached have changed.
+     *
+     * If the display metrics have changed (for example, if the display has been
+     * resized or rotated), then the system automatically calls
+     * {@link #cancel} to dismiss the presentation.
+     *
+     * @see #getDisplay
+     */
+    public void onDisplayChanged() {
+    }
+
+    private void handleDisplayRemoved() {
+        onDisplayRemoved();
+        cancel();
+    }
+
+    private void handleDisplayChanged() {
+        onDisplayChanged();
+
+        // We currently do not support configuration changes for presentations
+        // (although we could add that feature with a bit more work).
+        // If the display metrics have changed in any way then the current configuration
+        // is invalid and the application must recreate the presentation to get
+        // a new context.
+        if (!isConfigurationStillValid()) {
+            cancel();
+        }
+    }
+
+    private boolean isConfigurationStillValid() {
+        DisplayMetrics dm = new DisplayMetrics();
+        mDisplay.getMetrics(dm);
+        return dm.equals(getResources().getDisplayMetrics());
+    }
+
+    private static Context createPresentationContext(
+            Context outerContext, Display display, int theme) {
+        if (outerContext == null) {
+            throw new IllegalArgumentException("outerContext must not be null");
+        }
+        if (display == null) {
+            throw new IllegalArgumentException("display must not be null");
+        }
+
+        Context displayContext = outerContext.createDisplayContext(display);
+        if (theme == 0) {
+            TypedValue outValue = new TypedValue();
+            displayContext.getTheme().resolveAttribute(
+                    com.android.internal.R.attr.presentationTheme, outValue, true);
+            theme = outValue.resourceId;
+        }
+
+        // Derive the display's window manager from the outer window manager.
+        // We do this because the outer window manager have some extra information
+        // such as the parent window, which is important if the presentation uses
+        // an application window type.
+        final WindowManagerImpl outerWindowManager =
+                (WindowManagerImpl)outerContext.getSystemService(Context.WINDOW_SERVICE);
+        final WindowManagerImpl displayWindowManager =
+                outerWindowManager.createPresentationWindowManager(display);
+        return new ContextThemeWrapper(displayContext, theme) {
+            @Override
+            public Object getSystemService(String name) {
+                if (Context.WINDOW_SERVICE.equals(name)) {
+                    return displayWindowManager;
+                }
+                return super.getSystemService(name);
+            }
+        };
+    }
+
+    private final DisplayListener mDisplayListener = new DisplayListener() {
+        @Override
+        public void onDisplayAdded(int displayId) {
+        }
+
+        @Override
+        public void onDisplayRemoved(int displayId) {
+            if (displayId == mDisplay.getDisplayId()) {
+                handleDisplayRemoved();
+            }
+        }
+
+        @Override
+        public void onDisplayChanged(int displayId) {
+            if (displayId == mDisplay.getDisplayId()) {
+                handleDisplayChanged();
+            }
+        }
+    };
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_CANCEL:
+                    cancel();
+                    break;
+            }
+        }
+    };
+}
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index d1d5131..43a163d 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -31,6 +31,7 @@
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Slog;
@@ -845,14 +846,28 @@
      *
      * @hide
      */
-    public static final Intent getAssistIntent(Context context) {
-        PackageManager pm = context.getPackageManager();
-        Intent intent = new Intent(Intent.ACTION_ASSIST);
-        ComponentName component = intent.resolveActivity(pm);
-        if (component != null) {
-            intent.setComponent(component);
+    public Intent getAssistIntent(Context context) {
+        return getAssistIntent(context, UserHandle.myUserId());
+    }
+
+    /**
+     * Gets an intent for launching installed assistant activity, or null if not available.
+     * @return The assist intent.
+     *
+     * @hide
+     */
+    public Intent getAssistIntent(Context context, int userHandle) {
+        try {
+            ComponentName comp = mService.getAssistIntent(userHandle);
+            if (comp == null) {
+                return null;
+            }
+            Intent intent = new Intent(Intent.ACTION_ASSIST);
+            intent.setComponent(comp);
             return intent;
+        } catch (RemoteException re) {
+            Log.e(TAG, "getAssistIntent() failed: " + re);
+            return null;
         }
-        return null;
     }
 }
diff --git a/core/java/android/app/SearchableInfo.java b/core/java/android/app/SearchableInfo.java
index 5482f60..922ebdd 100644
--- a/core/java/android/app/SearchableInfo.java
+++ b/core/java/android/app/SearchableInfo.java
@@ -24,10 +24,12 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
 import android.text.InputType;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -510,16 +512,25 @@
      *
      * @hide For use by SearchManagerService.
      */
-    public static SearchableInfo getActivityMetaData(Context context, ActivityInfo activityInfo) {
+    public static SearchableInfo getActivityMetaData(Context context, ActivityInfo activityInfo,
+            int userId) {
+        Context userContext = null;
+        try {
+            userContext = context.createPackageContextAsUser("system", 0,
+                new UserHandle(userId));
+        } catch (NameNotFoundException nnfe) {
+            Log.e(LOG_TAG, "Couldn't create package context for user " + userId);
+            return null;
+        }
         // for each component, try to find metadata
         XmlResourceParser xml = 
-                activityInfo.loadXmlMetaData(context.getPackageManager(), MD_LABEL_SEARCHABLE);
+                activityInfo.loadXmlMetaData(userContext.getPackageManager(), MD_LABEL_SEARCHABLE);
         if (xml == null) {
             return null;
         }
         ComponentName cName = new ComponentName(activityInfo.packageName, activityInfo.name);
         
-        SearchableInfo searchable = getActivityMetaData(context, xml, cName);
+        SearchableInfo searchable = getActivityMetaData(userContext, xml, cName);
         xml.close();
         
         if (DBG) {
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 201d7b2..86fd7b9 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -312,7 +312,8 @@
         }
         public Editor putStringSet(String key, Set<String> values) {
             synchronized (this) {
-                mModified.put(key, values);
+                mModified.put(key,
+                        (values == null) ? null : new HashSet<String>(values));
                 return this;
             }
         }
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index dd9f337..829b80c 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -45,6 +45,7 @@
     public static final int DISABLE_RECENT = View.STATUS_BAR_DISABLE_RECENT;
     public static final int DISABLE_BACK = View.STATUS_BAR_DISABLE_BACK;
     public static final int DISABLE_CLOCK = View.STATUS_BAR_DISABLE_CLOCK;
+    public static final int DISABLE_SEARCH = View.STATUS_BAR_DISABLE_SEARCH;
 
     @Deprecated
     public static final int DISABLE_NAVIGATION = 
@@ -54,7 +55,8 @@
 
     public static final int DISABLE_MASK = DISABLE_EXPAND | DISABLE_NOTIFICATION_ICONS
             | DISABLE_NOTIFICATION_ALERTS | DISABLE_NOTIFICATION_TICKER
-            | DISABLE_SYSTEM_INFO | DISABLE_RECENT | DISABLE_HOME | DISABLE_BACK | DISABLE_CLOCK;
+            | DISABLE_SYSTEM_INFO | DISABLE_RECENT | DISABLE_HOME | DISABLE_BACK | DISABLE_CLOCK
+            | DISABLE_SEARCH;
 
     public static final int NAVIGATION_HINT_BACK_NOP      = 1 << 0;
     public static final int NAVIGATION_HINT_HOME_NOP      = 1 << 1;
@@ -97,13 +99,13 @@
     }
     
     /**
-     * Expand the status bar.
+     * Expand the notifications panel.
      */
-    public void expand() {
+    public void expandNotificationsPanel() {
         try {
             final IStatusBarService svc = getService();
             if (svc != null) {
-                svc.expand();
+                svc.expandNotificationsPanel();
             }
         } catch (RemoteException ex) {
             // system process is dead anyway.
@@ -112,13 +114,28 @@
     }
     
     /**
-     * Collapse the status bar.
+     * Collapse the notifications and settings panels.
      */
-    public void collapse() {
+    public void collapsePanels() {
         try {
             final IStatusBarService svc = getService();
             if (svc != null) {
-                svc.collapse();
+                svc.collapsePanels();
+            }
+        } catch (RemoteException ex) {
+            // system process is dead anyway.
+            throw new RuntimeException(ex);
+        }
+    }
+
+    /**
+     * Expand the settings panel.
+     */
+    public void expandSettingsPanel() {
+        try {
+            final IStatusBarService svc = getService();
+            if (svc != null) {
+                svc.expandSettingsPanel();
             }
         } catch (RemoteException ex) {
             // system process is dead anyway.
diff --git a/core/java/android/app/TaskStackBuilder.java b/core/java/android/app/TaskStackBuilder.java
index f21b3fd..3e0ac7e 100644
--- a/core/java/android/app/TaskStackBuilder.java
+++ b/core/java/android/app/TaskStackBuilder.java
@@ -23,6 +23,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -124,24 +125,16 @@
      * @return This TaskStackBuilder for method chaining
      */
     public TaskStackBuilder addParentStack(Activity sourceActivity) {
-        final int insertAt = mIntents.size();
-        Intent parent = sourceActivity.getParentActivityIntent();
-        PackageManager pm = sourceActivity.getPackageManager();
-        while (parent != null) {
-            mIntents.add(insertAt, parent);
-            try {
-                ActivityInfo info = pm.getActivityInfo(parent.getComponent(), 0);
-                String parentActivity = info.parentActivityName;
-                if (parentActivity != null) {
-                    parent = new Intent().setComponent(
-                            new ComponentName(mSourceContext, parentActivity));
-                } else {
-                    parent = null;
-                }
-            } catch (NameNotFoundException e) {
-                Log.e(TAG, "Bad ComponentName while traversing activity parent metadata");
-                throw new IllegalArgumentException(e);
+        final Intent parent = sourceActivity.getParentActivityIntent();
+        if (parent != null) {
+            // We have the actual parent intent, build the rest from static metadata
+            // then add the direct parent intent to the end.
+            ComponentName target = parent.getComponent();
+            if (target == null) {
+                target = parent.resolveActivity(mSourceContext.getPackageManager());
             }
+            addParentStack(target);
+            addNextIntent(parent);
         }
         return this;
     }
@@ -155,24 +148,7 @@
      * @return This TaskStackBuilder for method chaining
      */
     public TaskStackBuilder addParentStack(Class<?> sourceActivityClass) {
-        final int insertAt = mIntents.size();
-        PackageManager pm = mSourceContext.getPackageManager();
-        try {
-            ActivityInfo info = pm.getActivityInfo(
-                    new ComponentName(mSourceContext, sourceActivityClass), 0);
-            String parentActivity = info.parentActivityName;
-            while (parentActivity != null) {
-                Intent parent = new Intent().setComponent(
-                        new ComponentName(mSourceContext, parentActivity));
-                mIntents.add(insertAt, parent);
-                info = pm.getActivityInfo(parent.getComponent(), 0);
-                parentActivity = info.parentActivityName;
-            }
-        } catch (NameNotFoundException e) {
-            Log.e(TAG, "Bad ComponentName while traversing activity parent metadata");
-            throw new IllegalArgumentException(e);
-        }
-        return this;
+        return addParentStack(new ComponentName(mSourceContext, sourceActivityClass));
     }
 
     /**
@@ -191,11 +167,13 @@
             ActivityInfo info = pm.getActivityInfo(sourceActivityName, 0);
             String parentActivity = info.parentActivityName;
             while (parentActivity != null) {
-                Intent parent = new Intent().setComponent(
-                        new ComponentName(info.packageName, parentActivity));
-                mIntents.add(insertAt, parent);
-                info = pm.getActivityInfo(parent.getComponent(), 0);
+                final ComponentName target = new ComponentName(info.packageName, parentActivity);
+                info = pm.getActivityInfo(target, 0);
                 parentActivity = info.parentActivityName;
+                final Intent parent = parentActivity == null && insertAt == 0
+                        ? Intent.makeMainActivity(target)
+                        : new Intent().setComponent(target);
+                mIntents.add(insertAt, parent);
             }
         } catch (NameNotFoundException e) {
             Log.e(TAG, "Bad ComponentName while traversing activity parent metadata");
@@ -232,22 +210,26 @@
 
     /**
      * Start the task stack constructed by this builder.
+     * @hide
+     */
+    public void startActivities(Bundle options, UserHandle userHandle) {
+        if (mIntents.isEmpty()) {
+            throw new IllegalStateException(
+                    "No intents added to TaskStackBuilder; cannot startActivities");
+        }
+
+        mSourceContext.startActivitiesAsUser(getIntents(), options, userHandle);
+    }
+
+    /**
+     * Start the task stack constructed by this builder.
      *
      * @param options Additional options for how the Activity should be started.
      * See {@link android.content.Context#startActivity(Intent, Bundle)
      * Context.startActivity(Intent, Bundle)} for more details.
      */
     public void startActivities(Bundle options) {
-        if (mIntents.isEmpty()) {
-            throw new IllegalStateException(
-                    "No intents added to TaskStackBuilder; cannot startActivities");
-        }
-
-        Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]);
-        intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                Intent.FLAG_ACTIVITY_CLEAR_TASK |
-                Intent.FLAG_ACTIVITY_TASK_ON_HOME);
-        mSourceContext.startActivities(intents, options);
+        startActivities(options, new UserHandle(UserHandle.myUserId()));
     }
 
     /**
@@ -287,11 +269,22 @@
                     "No intents added to TaskStackBuilder; cannot getPendingIntent");
         }
 
-        Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]);
-        intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                Intent.FLAG_ACTIVITY_CLEAR_TASK |
-                Intent.FLAG_ACTIVITY_TASK_ON_HOME);
-        return PendingIntent.getActivities(mSourceContext, requestCode, intents, flags, options);
+        return PendingIntent.getActivities(mSourceContext, requestCode, getIntents(),
+                flags, options);
+    }
+
+    /**
+     * @hide
+     */
+    public PendingIntent getPendingIntent(int requestCode, int flags, Bundle options,
+            UserHandle user) {
+        if (mIntents.isEmpty()) {
+            throw new IllegalStateException(
+                    "No intents added to TaskStackBuilder; cannot getPendingIntent");
+        }
+
+        return PendingIntent.getActivitiesAsUser(mSourceContext, requestCode, getIntents(), flags,
+                options, user);
     }
 
     /**
@@ -302,6 +295,15 @@
      * @return An array containing the intents added to this builder.
      */
     public Intent[] getIntents() {
-        return mIntents.toArray(new Intent[mIntents.size()]);
+        Intent[] intents = new Intent[mIntents.size()];
+        if (intents.length == 0) return intents;
+
+        intents[0] = new Intent(mIntents.get(0)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                Intent.FLAG_ACTIVITY_CLEAR_TASK |
+                Intent.FLAG_ACTIVITY_TASK_ON_HOME);
+        for (int i = 1; i < intents.length; i++) {
+            intents[i] = new Intent(mIntents.get(i));
+        }
+        return intents;
     }
 }
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index c131549..9c0064e 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -42,6 +42,8 @@
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.ViewRootImpl;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -241,7 +243,7 @@
                 }
                 mWallpaper = null;
                 try {
-                    mWallpaper = getCurrentWallpaperLocked();
+                    mWallpaper = getCurrentWallpaperLocked(context);
                 } catch (OutOfMemoryError e) {
                     Log.w(TAG, "No memory load current wallpaper", e);
                 }
@@ -264,7 +266,7 @@
             }
         }
 
-        private Bitmap getCurrentWallpaperLocked() {
+        private Bitmap getCurrentWallpaperLocked(Context context) {
             try {
                 Bundle params = new Bundle();
                 ParcelFileDescriptor fd = mService.getWallpaper(this, params);
@@ -276,7 +278,7 @@
                         BitmapFactory.Options options = new BitmapFactory.Options();
                         Bitmap bm = BitmapFactory.decodeFileDescriptor(
                                 fd.getFileDescriptor(), null, options);
-                        return generateBitmap(bm, width, height);
+                        return generateBitmap(context, bm, width, height);
                     } catch (OutOfMemoryError e) {
                         Log.w(TAG, "Can't decode file", e);
                     } finally {
@@ -304,7 +306,7 @@
                     try {
                         BitmapFactory.Options options = new BitmapFactory.Options();
                         Bitmap bm = BitmapFactory.decodeStream(is, null, options);
-                        return generateBitmap(bm, width, height);
+                        return generateBitmap(context, bm, width, height);
                     } catch (OutOfMemoryError e) {
                         Log.w(TAG, "Can't decode stream", e);
                     } finally {
@@ -588,6 +590,25 @@
     }
 
     /**
+     * Return whether any users are currently set to use the wallpaper
+     * with the given resource ID.  That is, their wallpaper has been
+     * set through {@link #setResource(int)} with the same resource id.
+     */
+    public boolean hasResourceWallpaper(int resid) {
+        if (sGlobals.mService == null) {
+            Log.w(TAG, "WallpaperService not running");
+            return false;
+        }
+        try {
+            Resources resources = mContext.getResources();
+            String name = "res:" + resources.getResourceName(resid);
+            return sGlobals.mService.hasNamedWallpaper(name);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
      * Returns the desired minimum width for the wallpaper. Callers of
      * {@link #setBitmap(android.graphics.Bitmap)} or
      * {@link #setStream(java.io.InputStream)} should check this value
@@ -688,7 +709,7 @@
     public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) {
         try {
             //Log.v(TAG, "Sending new wallpaper offsets from app...");
-            ViewRootImpl.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
+            WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
                     windowToken, xOffset, yOffset, mWallpaperXStep, mWallpaperYStep);
             //Log.v(TAG, "...app returning after sending offsets!");
         } catch (RemoteException e) {
@@ -726,7 +747,7 @@
             int x, int y, int z, Bundle extras) {
         try {
             //Log.v(TAG, "Sending new wallpaper offsets from app...");
-            ViewRootImpl.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand(
+            WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand(
                     windowToken, action, x, y, z, extras, false);
             //Log.v(TAG, "...app returning after sending offsets!");
         } catch (RemoteException e) {
@@ -746,7 +767,7 @@
      */
     public void clearWallpaperOffsets(IBinder windowToken) {
         try {
-            ViewRootImpl.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
+            WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
                     windowToken, -1, -1, -1, -1);
         } catch (RemoteException e) {
             // Ignore.
@@ -768,12 +789,15 @@
         setResource(com.android.internal.R.drawable.default_wallpaper);
     }
     
-    static Bitmap generateBitmap(Bitmap bm, int width, int height) {
+    static Bitmap generateBitmap(Context context, Bitmap bm, int width, int height) {
         if (bm == null) {
             return null;
         }
 
-        bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
+        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+        DisplayMetrics metrics = new DisplayMetrics();
+        wm.getDefaultDisplay().getMetrics(metrics);
+        bm.setDensity(metrics.noncompatDensityDpi);
 
         if (width <= 0 || height <= 0
                 || (bm.getWidth() == width && bm.getHeight() == height)) {
@@ -783,7 +807,7 @@
         // This is the final bitmap we want to return.
         try {
             Bitmap newbm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-            newbm.setDensity(DisplayMetrics.DENSITY_DEVICE);
+            newbm.setDensity(metrics.noncompatDensityDpi);
 
             Canvas c = new Canvas(newbm);
             Rect targetRect = new Rect();
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 1c37414..b351811 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -50,23 +50,23 @@
  */
 public final class DeviceAdminInfo implements Parcelable {
     static final String TAG = "DeviceAdminInfo";
-    
+
     /**
      * A type of policy that this device admin can use: limit the passwords
      * that the user can select, via {@link DevicePolicyManager#setPasswordQuality}
      * and {@link DevicePolicyManager#setPasswordMinimumLength}.
-     * 
+     *
      * <p>To control this policy, the device admin must have a "limit-password"
      * tag in the "uses-policies" section of its meta-data.
      */
     public static final int USES_POLICY_LIMIT_PASSWORD = 0;
-    
+
     /**
      * A type of policy that this device admin can use: able to watch login
      * attempts from the user, via {@link DeviceAdminReceiver#ACTION_PASSWORD_FAILED},
      * {@link DeviceAdminReceiver#ACTION_PASSWORD_SUCCEEDED}, and
      * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts}.
-     * 
+     *
      * <p>To control this policy, the device admin must have a "watch-login"
      * tag in the "uses-policies" section of its meta-data.
      */
@@ -76,7 +76,7 @@
      * A type of policy that this device admin can use: able to reset the
      * user's password via
      * {@link DevicePolicyManager#resetPassword}.
-     * 
+     *
      * <p>To control this policy, the device admin must have a "reset-password"
      * tag in the "uses-policies" section of its meta-data.
      */
@@ -87,7 +87,7 @@
      * to lock via{@link DevicePolicyManager#lockNow} or limit the
      * maximum lock timeout for the device via
      * {@link DevicePolicyManager#setMaximumTimeToLock}.
-     * 
+     *
      * <p>To control this policy, the device admin must have a "force-lock"
      * tag in the "uses-policies" section of its meta-data.
      */
@@ -97,7 +97,7 @@
      * A type of policy that this device admin can use: able to factory
      * reset the device, erasing all of the user's data, via
      * {@link DevicePolicyManager#wipeData}.
-     * 
+     *
      * <p>To control this policy, the device admin must have a "wipe-data"
      * tag in the "uses-policies" section of its meta-data.
      */
@@ -138,13 +138,21 @@
      */
     public static final int USES_POLICY_DISABLE_CAMERA = 8;
 
+    /**
+     * A type of policy that this device admin can use: disables use of keyguard widgets.
+     *
+     * <p>To control this policy, the device admin must have a "disable-keyguard-widgets"
+     * tag in the "uses-policies" section of its meta-data.
+     */
+    public static final int USES_POLICY_DISABLE_KEYGUARD_FEATURES = 9;
+
     /** @hide */
     public static class PolicyInfo {
         public final int ident;
         final public String tag;
         final public int label;
         final public int description;
-        
+
         public PolicyInfo(int identIn, String tagIn, int labelIn, int descriptionIn) {
             ident = identIn;
             tag = tagIn;
@@ -152,11 +160,11 @@
             description = descriptionIn;
         }
     }
-    
+
     static ArrayList<PolicyInfo> sPoliciesDisplayOrder = new ArrayList<PolicyInfo>();
     static HashMap<String, Integer> sKnownPolicies = new HashMap<String, Integer>();
     static SparseArray<PolicyInfo> sRevKnownPolicies = new SparseArray<PolicyInfo>();
-    
+
     static {
         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_WIPE_DATA, "wipe-data",
                 com.android.internal.R.string.policylab_wipeData,
@@ -185,6 +193,10 @@
         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_DISABLE_CAMERA, "disable-camera",
                 com.android.internal.R.string.policylab_disableCamera,
                 com.android.internal.R.string.policydesc_disableCamera));
+        sPoliciesDisplayOrder.add(new PolicyInfo(
+                USES_POLICY_DISABLE_KEYGUARD_FEATURES, "disable-keyguard-features",
+                com.android.internal.R.string.policylab_disableKeyguardFeatures,
+                com.android.internal.R.string.policydesc_disableKeyguardFeatures));
 
         for (int i=0; i<sPoliciesDisplayOrder.size(); i++) {
             PolicyInfo pi = sPoliciesDisplayOrder.get(i);
@@ -192,25 +204,25 @@
             sKnownPolicies.put(pi.tag, pi.ident);
         }
     }
-    
+
     /**
      * The BroadcastReceiver that implements this device admin component.
      */
     final ResolveInfo mReceiver;
-    
+
     /**
      * Whether this should be visible to the user.
      */
     boolean mVisible;
-    
+
     /**
      * The policies this administrator needs access to.
      */
     int mUsesPolicies;
-    
+
     /**
      * Constructor.
-     * 
+     *
      * @param context The Context in which we are parsing the device admin.
      * @param receiver The ResolveInfo returned from the package manager about
      * this device admin's component.
@@ -219,9 +231,9 @@
             throws XmlPullParserException, IOException {
         mReceiver = receiver;
         ActivityInfo ai = receiver.activityInfo;
-        
+
         PackageManager pm = context.getPackageManager();
-        
+
         XmlResourceParser parser = null;
         try {
             parser = ai.loadXmlMetaData(pm, DeviceAdminReceiver.DEVICE_ADMIN_META_DATA);
@@ -229,30 +241,30 @@
                 throw new XmlPullParserException("No "
                         + DeviceAdminReceiver.DEVICE_ADMIN_META_DATA + " meta-data");
             }
-        
+
             Resources res = pm.getResourcesForApplication(ai.applicationInfo);
-            
+
             AttributeSet attrs = Xml.asAttributeSet(parser);
-            
+
             int type;
             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
                     && type != XmlPullParser.START_TAG) {
             }
-            
+
             String nodeName = parser.getName();
             if (!"device-admin".equals(nodeName)) {
                 throw new XmlPullParserException(
                         "Meta-data does not start with device-admin tag");
             }
-            
+
             TypedArray sa = res.obtainAttributes(attrs,
                     com.android.internal.R.styleable.DeviceAdmin);
 
             mVisible = sa.getBoolean(
                     com.android.internal.R.styleable.DeviceAdmin_visible, true);
-            
+
             sa.recycle();
-            
+
             int outerDepth = parser.getDepth();
             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
@@ -290,14 +302,14 @@
         mReceiver = ResolveInfo.CREATOR.createFromParcel(source);
         mUsesPolicies = source.readInt();
     }
-    
+
     /**
      * Return the .apk package that implements this device admin.
      */
     public String getPackageName() {
         return mReceiver.activityInfo.packageName;
     }
-    
+
     /**
      * Return the class name of the receiver component that implements
      * this device admin.
@@ -321,20 +333,20 @@
         return new ComponentName(mReceiver.activityInfo.packageName,
                 mReceiver.activityInfo.name);
     }
-    
+
     /**
      * Load the user-displayed label for this device admin.
-     * 
+     *
      * @param pm Supply a PackageManager used to load the device admin's
      * resources.
      */
     public CharSequence loadLabel(PackageManager pm) {
         return mReceiver.loadLabel(pm);
     }
-    
+
     /**
      * Load user-visible description associated with this device admin.
-     * 
+     *
      * @param pm Supply a PackageManager used to load the device admin's
      * resources.
      */
@@ -351,17 +363,17 @@
         }
         throw new NotFoundException();
     }
-    
+
     /**
      * Load the user-displayed icon for this device admin.
-     * 
+     *
      * @param pm Supply a PackageManager used to load the device admin's
      * resources.
      */
     public Drawable loadIcon(PackageManager pm) {
         return mReceiver.loadIcon(pm);
     }
-    
+
     /**
      * Returns whether this device admin would like to be visible to the
      * user, even when it is not enabled.
@@ -369,7 +381,7 @@
     public boolean isVisible() {
         return mVisible;
     }
-    
+
     /**
      * Return true if the device admin has requested that it be able to use
      * the given policy control.  The possible policy identifier inputs are:
@@ -382,7 +394,7 @@
     public boolean usesPolicy(int policyIdent) {
         return (mUsesPolicies & (1<<policyIdent)) != 0;
     }
-    
+
     /**
      * Return the XML tag name for the given policy identifier.  Valid identifiers
      * are as per {@link #usesPolicy(int)}.  If the given identifier is not
@@ -391,7 +403,7 @@
     public String getTagForPolicy(int policyIdent) {
         return sRevKnownPolicies.get(policyIdent).tag;
     }
-    
+
     /** @hide */
     public ArrayList<PolicyInfo> getUsedPolicies() {
         ArrayList<PolicyInfo> res = new ArrayList<PolicyInfo>();
@@ -403,25 +415,25 @@
         }
         return res;
     }
-    
+
     /** @hide */
     public void writePoliciesToXml(XmlSerializer out)
             throws IllegalArgumentException, IllegalStateException, IOException {
         out.attribute(null, "flags", Integer.toString(mUsesPolicies));
     }
-    
+
     /** @hide */
     public void readPoliciesFromXml(XmlPullParser parser)
             throws XmlPullParserException, IOException {
         mUsesPolicies = Integer.parseInt(
                 parser.getAttributeValue(null, "flags"));
     }
-    
+
     public void dump(Printer pw, String prefix) {
         pw.println(prefix + "Receiver:");
         mReceiver.dump(pw, prefix + "  ");
     }
-    
+
     @Override
     public String toString() {
         return "DeviceAdminInfo{" + mReceiver.activityInfo.name + "}";
@@ -429,7 +441,7 @@
 
     /**
      * Used to package this object into a {@link Parcel}.
-     * 
+     *
      * @param dest The {@link Parcel} to be written.
      * @param flags The flags used for parceling.
      */
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 0b58396..4c0eba0 100755
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -29,6 +29,7 @@
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.Log;
 
 import java.io.IOException;
@@ -131,7 +132,7 @@
     public boolean isAdminActive(ComponentName who) {
         if (mService != null) {
             try {
-                return mService.isAdminActive(who);
+                return mService.isAdminActive(who, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -147,7 +148,7 @@
     public List<ComponentName> getActiveAdmins() {
         if (mService != null) {
             try {
-                return mService.getActiveAdmins();
+                return mService.getActiveAdmins(UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -156,12 +157,14 @@
     }
 
     /**
+     * Used by package administration code to determine if a package can be stopped
+     * or uninstalled.
      * @hide
      */
     public boolean packageHasActiveAdmins(String packageName) {
         if (mService != null) {
             try {
-                return mService.packageHasActiveAdmins(packageName);
+                return mService.packageHasActiveAdmins(packageName, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -178,7 +181,7 @@
     public void removeActiveAdmin(ComponentName who) {
         if (mService != null) {
             try {
-                mService.removeActiveAdmin(who);
+                mService.removeActiveAdmin(who, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -197,7 +200,7 @@
     public boolean hasGrantedPolicy(ComponentName admin, int usesPolicy) {
         if (mService != null) {
             try {
-                return mService.hasGrantedPolicy(admin, usesPolicy);
+                return mService.hasGrantedPolicy(admin, usesPolicy, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -289,7 +292,7 @@
     public void setPasswordQuality(ComponentName admin, int quality) {
         if (mService != null) {
             try {
-                mService.setPasswordQuality(admin, quality);
+                mService.setPasswordQuality(admin, quality, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -303,9 +306,14 @@
      * all admins.
      */
     public int getPasswordQuality(ComponentName admin) {
+        return getPasswordQuality(admin, UserHandle.myUserId());
+    }
+
+    /** @hide per-user version */
+    public int getPasswordQuality(ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
-                return mService.getPasswordQuality(admin);
+                return mService.getPasswordQuality(admin, userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -337,7 +345,7 @@
     public void setPasswordMinimumLength(ComponentName admin, int length) {
         if (mService != null) {
             try {
-                mService.setPasswordMinimumLength(admin, length);
+                mService.setPasswordMinimumLength(admin, length, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -351,9 +359,14 @@
      * all admins.
      */
     public int getPasswordMinimumLength(ComponentName admin) {
+        return getPasswordMinimumLength(admin, UserHandle.myUserId());
+    }
+
+    /** @hide per-user version */
+    public int getPasswordMinimumLength(ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
-                return mService.getPasswordMinimumLength(admin);
+                return mService.getPasswordMinimumLength(admin, userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -386,7 +399,7 @@
     public void setPasswordMinimumUpperCase(ComponentName admin, int length) {
         if (mService != null) {
             try {
-                mService.setPasswordMinimumUpperCase(admin, length);
+                mService.setPasswordMinimumUpperCase(admin, length, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -406,9 +419,14 @@
      *         password.
      */
     public int getPasswordMinimumUpperCase(ComponentName admin) {
+        return getPasswordMinimumUpperCase(admin, UserHandle.myUserId());
+    }
+
+    /** @hide per-user version */
+    public int getPasswordMinimumUpperCase(ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
-                return mService.getPasswordMinimumUpperCase(admin);
+                return mService.getPasswordMinimumUpperCase(admin, userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -441,7 +459,7 @@
     public void setPasswordMinimumLowerCase(ComponentName admin, int length) {
         if (mService != null) {
             try {
-                mService.setPasswordMinimumLowerCase(admin, length);
+                mService.setPasswordMinimumLowerCase(admin, length, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -461,9 +479,14 @@
      *         password.
      */
     public int getPasswordMinimumLowerCase(ComponentName admin) {
+        return getPasswordMinimumLowerCase(admin, UserHandle.myUserId());
+    }
+
+    /** @hide per-user version */
+    public int getPasswordMinimumLowerCase(ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
-                return mService.getPasswordMinimumLowerCase(admin);
+                return mService.getPasswordMinimumLowerCase(admin, userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -495,7 +518,7 @@
     public void setPasswordMinimumLetters(ComponentName admin, int length) {
         if (mService != null) {
             try {
-                mService.setPasswordMinimumLetters(admin, length);
+                mService.setPasswordMinimumLetters(admin, length, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -514,9 +537,14 @@
      * @return The minimum number of letters required in the password.
      */
     public int getPasswordMinimumLetters(ComponentName admin) {
+        return getPasswordMinimumLetters(admin, UserHandle.myUserId());
+    }
+
+    /** @hide per-user version */
+    public int getPasswordMinimumLetters(ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
-                return mService.getPasswordMinimumLetters(admin);
+                return mService.getPasswordMinimumLetters(admin, userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -548,7 +576,7 @@
     public void setPasswordMinimumNumeric(ComponentName admin, int length) {
         if (mService != null) {
             try {
-                mService.setPasswordMinimumNumeric(admin, length);
+                mService.setPasswordMinimumNumeric(admin, length, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -567,9 +595,14 @@
      * @return The minimum number of numerical digits required in the password.
      */
     public int getPasswordMinimumNumeric(ComponentName admin) {
+        return getPasswordMinimumNumeric(admin, UserHandle.myUserId());
+    }
+
+    /** @hide per-user version */
+    public int getPasswordMinimumNumeric(ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
-                return mService.getPasswordMinimumNumeric(admin);
+                return mService.getPasswordMinimumNumeric(admin, userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -601,7 +634,7 @@
     public void setPasswordMinimumSymbols(ComponentName admin, int length) {
         if (mService != null) {
             try {
-                mService.setPasswordMinimumSymbols(admin, length);
+                mService.setPasswordMinimumSymbols(admin, length, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -620,9 +653,14 @@
      * @return The minimum number of symbols required in the password.
      */
     public int getPasswordMinimumSymbols(ComponentName admin) {
+        return getPasswordMinimumSymbols(admin, UserHandle.myUserId());
+    }
+
+    /** @hide per-user version */
+    public int getPasswordMinimumSymbols(ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
-                return mService.getPasswordMinimumSymbols(admin);
+                return mService.getPasswordMinimumSymbols(admin, userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -654,7 +692,7 @@
     public void setPasswordMinimumNonLetter(ComponentName admin, int length) {
         if (mService != null) {
             try {
-                mService.setPasswordMinimumNonLetter(admin, length);
+                mService.setPasswordMinimumNonLetter(admin, length, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -673,9 +711,14 @@
      * @return The minimum number of letters required in the password.
      */
     public int getPasswordMinimumNonLetter(ComponentName admin) {
+        return getPasswordMinimumNonLetter(admin, UserHandle.myUserId());
+    }
+
+    /** @hide per-user version */
+    public int getPasswordMinimumNonLetter(ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
-                return mService.getPasswordMinimumNonLetter(admin);
+                return mService.getPasswordMinimumNonLetter(admin, userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -708,7 +751,7 @@
     public void setPasswordHistoryLength(ComponentName admin, int length) {
         if (mService != null) {
             try {
-                mService.setPasswordHistoryLength(admin, length);
+                mService.setPasswordHistoryLength(admin, length, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -737,7 +780,7 @@
     public void setPasswordExpirationTimeout(ComponentName admin, long timeout) {
         if (mService != null) {
             try {
-                mService.setPasswordExpirationTimeout(admin, timeout);
+                mService.setPasswordExpirationTimeout(admin, timeout, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -756,7 +799,7 @@
     public long getPasswordExpirationTimeout(ComponentName admin) {
         if (mService != null) {
             try {
-                return mService.getPasswordExpirationTimeout(admin);
+                return mService.getPasswordExpirationTimeout(admin, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -776,7 +819,7 @@
     public long getPasswordExpiration(ComponentName admin) {
         if (mService != null) {
             try {
-                return mService.getPasswordExpiration(admin);
+                return mService.getPasswordExpiration(admin, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -792,9 +835,14 @@
      * @return The length of the password history
      */
     public int getPasswordHistoryLength(ComponentName admin) {
+        return getPasswordHistoryLength(admin, UserHandle.myUserId());
+    }
+
+    /** @hide per-user version */
+    public int getPasswordHistoryLength(ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
-                return mService.getPasswordHistoryLength(admin);
+                return mService.getPasswordHistoryLength(admin, userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -828,7 +876,7 @@
     public boolean isActivePasswordSufficient() {
         if (mService != null) {
             try {
-                return mService.isActivePasswordSufficient();
+                return mService.isActivePasswordSufficient(UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -847,7 +895,7 @@
     public int getCurrentFailedPasswordAttempts() {
         if (mService != null) {
             try {
-                return mService.getCurrentFailedPasswordAttempts();
+                return mService.getCurrentFailedPasswordAttempts(UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -877,7 +925,7 @@
     public void setMaximumFailedPasswordsForWipe(ComponentName admin, int num) {
         if (mService != null) {
             try {
-                mService.setMaximumFailedPasswordsForWipe(admin, num);
+                mService.setMaximumFailedPasswordsForWipe(admin, num, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -892,9 +940,14 @@
      * all admins.
      */
     public int getMaximumFailedPasswordsForWipe(ComponentName admin) {
+        return getMaximumFailedPasswordsForWipe(admin, UserHandle.myUserId());
+    }
+
+    /** @hide per-user version */
+    public int getMaximumFailedPasswordsForWipe(ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
-                return mService.getMaximumFailedPasswordsForWipe(admin);
+                return mService.getMaximumFailedPasswordsForWipe(admin, userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -933,7 +986,7 @@
     public boolean resetPassword(String password, int flags) {
         if (mService != null) {
             try {
-                return mService.resetPassword(password, flags);
+                return mService.resetPassword(password, flags, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -957,7 +1010,7 @@
     public void setMaximumTimeToLock(ComponentName admin, long timeMs) {
         if (mService != null) {
             try {
-                mService.setMaximumTimeToLock(admin, timeMs);
+                mService.setMaximumTimeToLock(admin, timeMs, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -971,9 +1024,14 @@
      * all admins.
      */
     public long getMaximumTimeToLock(ComponentName admin) {
+        return getMaximumTimeToLock(admin, UserHandle.myUserId());
+    }
+
+    /** @hide per-user version */
+    public long getMaximumTimeToLock(ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
-                return mService.getMaximumTimeToLock(admin);
+                return mService.getMaximumTimeToLock(admin, userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1021,7 +1079,7 @@
     public void wipeData(int flags) {
         if (mService != null) {
             try {
-                mService.wipeData(flags);
+                mService.wipeData(flags, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1090,7 +1148,7 @@
                     }
                     android.net.Proxy.validate(hostName, Integer.toString(port), exclSpec);
                 }
-                return mService.setGlobalProxy(admin, hostSpec, exclSpec);
+                return mService.setGlobalProxy(admin, hostSpec, exclSpec, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1107,7 +1165,7 @@
     public ComponentName getGlobalProxyAdmin() {
         if (mService != null) {
             try {
-                return mService.getGlobalProxyAdmin();
+                return mService.getGlobalProxyAdmin(UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1155,6 +1213,26 @@
             = "android.app.action.START_ENCRYPTION";
 
     /**
+     * Widgets are enabled in keyguard
+     */
+    public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0;
+
+    /**
+     * Disable all keyguard widgets
+     */
+    public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1 << 0;
+
+    /**
+     * Disable the camera on secure keyguard screens (e.g. PIN/Pattern/Password)
+     */
+    public static final int KEYGUARD_DISABLE_SECURE_CAMERA = 1 << 1;
+
+    /**
+     * Disable all current and future keyguard customizations.
+     */
+    public static final int KEYGUARD_DISABLE_FEATURES_ALL = 0x7fffffff;
+
+    /**
      * Called by an application that is administering the device to
      * request that the storage system be encrypted.
      *
@@ -1189,7 +1267,7 @@
     public int setStorageEncryption(ComponentName admin, boolean encrypt) {
         if (mService != null) {
             try {
-                return mService.setStorageEncryption(admin, encrypt);
+                return mService.setStorageEncryption(admin, encrypt, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1209,7 +1287,7 @@
     public boolean getStorageEncryption(ComponentName admin) {
         if (mService != null) {
             try {
-                return mService.getStorageEncryption(admin);
+                return mService.getStorageEncryption(admin, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1234,9 +1312,14 @@
      * {@link #ENCRYPTION_STATUS_ACTIVATING}, or{@link #ENCRYPTION_STATUS_ACTIVE}.
      */
     public int getStorageEncryptionStatus() {
+        return getStorageEncryptionStatus(UserHandle.myUserId());
+    }
+
+    /** @hide per-user version */
+    public int getStorageEncryptionStatus(int userHandle) {
         if (mService != null) {
             try {
-                return mService.getStorageEncryptionStatus();
+                return mService.getStorageEncryptionStatus(userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1259,7 +1342,7 @@
     public void setCameraDisabled(ComponentName admin, boolean disabled) {
         if (mService != null) {
             try {
-                mService.setCameraDisabled(admin, disabled);
+                mService.setCameraDisabled(admin, disabled, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1273,9 +1356,14 @@
      * have disabled the camera
      */
     public boolean getCameraDisabled(ComponentName admin) {
+        return getCameraDisabled(admin, UserHandle.myUserId());
+    }
+
+    /** @hide per-user version */
+    public boolean getCameraDisabled(ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
-                return mService.getCameraDisabled(admin);
+                return mService.getCameraDisabled(admin, userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1284,12 +1372,60 @@
     }
 
     /**
+     * Called by an application that is administering the device to disable keyguard customizations,
+     * such as widgets. After setting this, keyguard features will be disabled according to the
+     * provided feature list.
+     *
+     * <p>The calling device admin must have requested
+     * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call
+     * this method; if it has not, a security exception will be thrown.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param which {@link #KEYGUARD_DISABLE_FEATURES_NONE} (default),
+     * {@link #KEYGUARD_DISABLE_WIDGETS_ALL}, {@link #KEYGUARD_DISABLE_SECURE_CAMERA},
+     * {@link #KEYGUARD_DISABLE_FEATURES_ALL}
+     */
+    public void setKeyguardDisabledFeatures(ComponentName admin, int which) {
+        if (mService != null) {
+            try {
+                mService.setKeyguardDisabledFeatures(admin, which, UserHandle.myUserId());
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
+     * Determine whether or not features have been disabled in keyguard either by the current
+     * admin, if specified, or all admins.
+     * @param admin The name of the admin component to check, or null to check if any admins
+     * have disabled features in keyguard.
+     * @return bitfield of flags. See {@link #setKeyguardDisabledFeatures(ComponentName, int)}
+     * for a list.
+     */
+    public int getKeyguardDisabledFeatures(ComponentName admin) {
+        return getKeyguardDisabledFeatures(admin, UserHandle.myUserId());
+    }
+
+    /** @hide per-user version */
+    public int getKeyguardDisabledFeatures(ComponentName admin, int userHandle) {
+        if (mService != null) {
+            try {
+                return mService.getKeyguardDisabledFeatures(admin, userHandle);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return KEYGUARD_DISABLE_FEATURES_NONE;
+    }
+
+    /**
      * @hide
      */
     public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) {
         if (mService != null) {
             try {
-                mService.setActiveAdmin(policyReceiver, refreshing);
+                mService.setActiveAdmin(policyReceiver, refreshing, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1330,7 +1466,7 @@
     public void getRemoveWarning(ComponentName admin, RemoteCallback result) {
         if (mService != null) {
             try {
-                mService.getRemoveWarning(admin, result);
+                mService.getRemoveWarning(admin, result, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1341,11 +1477,11 @@
      * @hide
      */
     public void setActivePasswordState(int quality, int length, int letters, int uppercase,
-            int lowercase, int numbers, int symbols, int nonletter) {
+            int lowercase, int numbers, int symbols, int nonletter, int userHandle) {
         if (mService != null) {
             try {
                 mService.setActivePasswordState(quality, length, letters, uppercase, lowercase,
-                        numbers, symbols, nonletter);
+                        numbers, symbols, nonletter, userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1355,10 +1491,10 @@
     /**
      * @hide
      */
-    public void reportFailedPasswordAttempt() {
+    public void reportFailedPasswordAttempt(int userHandle) {
         if (mService != null) {
             try {
-                mService.reportFailedPasswordAttempt();
+                mService.reportFailedPasswordAttempt(userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1368,14 +1504,13 @@
     /**
      * @hide
      */
-    public void reportSuccessfulPasswordAttempt() {
+    public void reportSuccessfulPasswordAttempt(int userHandle) {
         if (mService != null) {
             try {
-                mService.reportSuccessfulPasswordAttempt();
+                mService.reportSuccessfulPasswordAttempt(userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
         }
     }
-
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 9419a62..e061ab3 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -25,73 +25,76 @@
  * {@hide}
  */
 interface IDevicePolicyManager {
-    void setPasswordQuality(in ComponentName who, int quality);
-    int getPasswordQuality(in ComponentName who);
+    void setPasswordQuality(in ComponentName who, int quality, int userHandle);
+    int getPasswordQuality(in ComponentName who, int userHandle);
 
-    void setPasswordMinimumLength(in ComponentName who, int length);
-    int getPasswordMinimumLength(in ComponentName who);
+    void setPasswordMinimumLength(in ComponentName who, int length, int userHandle);
+    int getPasswordMinimumLength(in ComponentName who, int userHandle);
 
-    void setPasswordMinimumUpperCase(in ComponentName who, int length);
-    int getPasswordMinimumUpperCase(in ComponentName who);
+    void setPasswordMinimumUpperCase(in ComponentName who, int length, int userHandle);
+    int getPasswordMinimumUpperCase(in ComponentName who, int userHandle);
 
-    void setPasswordMinimumLowerCase(in ComponentName who, int length);
-    int getPasswordMinimumLowerCase(in ComponentName who);
+    void setPasswordMinimumLowerCase(in ComponentName who, int length, int userHandle);
+    int getPasswordMinimumLowerCase(in ComponentName who, int userHandle);
 
-    void setPasswordMinimumLetters(in ComponentName who, int length);
-    int getPasswordMinimumLetters(in ComponentName who);
+    void setPasswordMinimumLetters(in ComponentName who, int length, int userHandle);
+    int getPasswordMinimumLetters(in ComponentName who, int userHandle);
 
-    void setPasswordMinimumNumeric(in ComponentName who, int length);
-    int getPasswordMinimumNumeric(in ComponentName who);
+    void setPasswordMinimumNumeric(in ComponentName who, int length, int userHandle);
+    int getPasswordMinimumNumeric(in ComponentName who, int userHandle);
 
-    void setPasswordMinimumSymbols(in ComponentName who, int length);
-    int getPasswordMinimumSymbols(in ComponentName who);
+    void setPasswordMinimumSymbols(in ComponentName who, int length, int userHandle);
+    int getPasswordMinimumSymbols(in ComponentName who, int userHandle);
 
-    void setPasswordMinimumNonLetter(in ComponentName who, int length);
-    int getPasswordMinimumNonLetter(in ComponentName who);
-    
-    void setPasswordHistoryLength(in ComponentName who, int length);
-    int getPasswordHistoryLength(in ComponentName who);
+    void setPasswordMinimumNonLetter(in ComponentName who, int length, int userHandle);
+    int getPasswordMinimumNonLetter(in ComponentName who, int userHandle);
 
-    void setPasswordExpirationTimeout(in ComponentName who, long expiration);
-    long getPasswordExpirationTimeout(in ComponentName who);
+    void setPasswordHistoryLength(in ComponentName who, int length, int userHandle);
+    int getPasswordHistoryLength(in ComponentName who, int userHandle);
 
-    long getPasswordExpiration(in ComponentName who);
+    void setPasswordExpirationTimeout(in ComponentName who, long expiration, int userHandle);
+    long getPasswordExpirationTimeout(in ComponentName who, int userHandle);
 
-    boolean isActivePasswordSufficient();
-    int getCurrentFailedPasswordAttempts();
-    
-    void setMaximumFailedPasswordsForWipe(in ComponentName admin, int num);
-    int getMaximumFailedPasswordsForWipe(in ComponentName admin);
-    
-    boolean resetPassword(String password, int flags);
-    
-    void setMaximumTimeToLock(in ComponentName who, long timeMs);
-    long getMaximumTimeToLock(in ComponentName who);
-    
+    long getPasswordExpiration(in ComponentName who, int userHandle);
+
+    boolean isActivePasswordSufficient(int userHandle);
+    int getCurrentFailedPasswordAttempts(int userHandle);
+
+    void setMaximumFailedPasswordsForWipe(in ComponentName admin, int num, int userHandle);
+    int getMaximumFailedPasswordsForWipe(in ComponentName admin, int userHandle);
+
+    boolean resetPassword(String password, int flags, int userHandle);
+
+    void setMaximumTimeToLock(in ComponentName who, long timeMs, int userHandle);
+    long getMaximumTimeToLock(in ComponentName who, int userHandle);
+
     void lockNow();
-    
-    void wipeData(int flags);
 
-    ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList);
-    ComponentName getGlobalProxyAdmin();
+    void wipeData(int flags, int userHandle);
 
-    int setStorageEncryption(in ComponentName who, boolean encrypt);
-    boolean getStorageEncryption(in ComponentName who);
-    int getStorageEncryptionStatus();
+    ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList, int userHandle);
+    ComponentName getGlobalProxyAdmin(int userHandle);
 
-    void setCameraDisabled(in ComponentName who, boolean disabled);
-    boolean getCameraDisabled(in ComponentName who);
+    int setStorageEncryption(in ComponentName who, boolean encrypt, int userHandle);
+    boolean getStorageEncryption(in ComponentName who, int userHandle);
+    int getStorageEncryptionStatus(int userHandle);
 
-    void setActiveAdmin(in ComponentName policyReceiver, boolean refreshing);
-    boolean isAdminActive(in ComponentName policyReceiver);
-    List<ComponentName> getActiveAdmins();
-    boolean packageHasActiveAdmins(String packageName);
-    void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result);
-    void removeActiveAdmin(in ComponentName policyReceiver);
-    boolean hasGrantedPolicy(in ComponentName policyReceiver, int usesPolicy);
-    
+    void setCameraDisabled(in ComponentName who, boolean disabled, int userHandle);
+    boolean getCameraDisabled(in ComponentName who, int userHandle);
+
+    void setKeyguardDisabledFeatures(in ComponentName who, int which, int userHandle);
+    int getKeyguardDisabledFeatures(in ComponentName who, int userHandle);
+
+    void setActiveAdmin(in ComponentName policyReceiver, boolean refreshing, int userHandle);
+    boolean isAdminActive(in ComponentName policyReceiver, int userHandle);
+    List<ComponentName> getActiveAdmins(int userHandle);
+    boolean packageHasActiveAdmins(String packageName, int userHandle);
+    void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result, int userHandle);
+    void removeActiveAdmin(in ComponentName policyReceiver, int userHandle);
+    boolean hasGrantedPolicy(in ComponentName policyReceiver, int usesPolicy, int userHandle);
+
     void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase,
-        int numbers, int symbols, int nonletter);
-    void reportFailedPasswordAttempt();
-    void reportSuccessfulPasswordAttempt();
+        int numbers, int symbols, int nonletter, int userHandle);
+    void reportFailedPasswordAttempt(int userHandle);
+    void reportSuccessfulPasswordAttempt(int userHandle);
 }
diff --git a/core/java/android/app/backup/WallpaperBackupHelper.java b/core/java/android/app/backup/WallpaperBackupHelper.java
index a74a268..9e8ab2c 100644
--- a/core/java/android/app/backup/WallpaperBackupHelper.java
+++ b/core/java/android/app/backup/WallpaperBackupHelper.java
@@ -20,7 +20,9 @@
 import android.content.Context;
 import android.graphics.BitmapFactory;
 import android.graphics.Point;
+import android.os.Environment;
 import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
 import android.util.Slog;
 import android.view.Display;
 import android.view.WindowManager;
@@ -39,8 +41,12 @@
 
     // This path must match what the WallpaperManagerService uses
     // TODO: Will need to change if backing up non-primary user's wallpaper
-    public static final String WALLPAPER_IMAGE = "/data/system/users/0/wallpaper";
-    public static final String WALLPAPER_INFO = "/data/system/users/0/wallpaper_info.xml";
+    public static final String WALLPAPER_IMAGE =
+            new File(Environment.getUserSystemDirectory(UserHandle.USER_OWNER),
+                    "wallpaper").getAbsolutePath();
+    public static final String WALLPAPER_INFO =
+            new File(Environment.getUserSystemDirectory(UserHandle.USER_OWNER),
+                    "wallpaper_info.xml").getAbsolutePath();
     // Use old keys to keep legacy data compatibility and avoid writing two wallpapers
     public static final String WALLPAPER_IMAGE_KEY =
             "/data/data/com.android.settings/files/wallpaper";
@@ -50,7 +56,9 @@
     // will be saved to this file from the restore stream, then renamed to the proper
     // location if it's deemed suitable.
     // TODO: Will need to change if backing up non-primary user's wallpaper
-    private static final String STAGE_FILE = "/data/system/users/0/wallpaper-tmp";
+    private static final String STAGE_FILE =
+            new File(Environment.getUserSystemDirectory(UserHandle.USER_OWNER),
+                    "wallpaper-tmp").getAbsolutePath();
 
     Context mContext;
     String[] mFiles;
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 08bc0ac..cb61a71 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -19,16 +19,21 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 
+import android.app.ActivityThread;
 import android.content.Context;
+import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
 import android.widget.RemoteViews;
+import android.widget.RemoteViews.OnClickHandler;
 
 import com.android.internal.appwidget.IAppWidgetHost;
 import com.android.internal.appwidget.IAppWidgetService;
@@ -41,7 +46,8 @@
 
     static final int HANDLE_UPDATE = 1;
     static final int HANDLE_PROVIDER_CHANGED = 2;
-    static final int HANDLE_VIEW_DATA_CHANGED = 3;
+    static final int HANDLE_PROVIDERS_CHANGED = 3;
+    static final int HANDLE_VIEW_DATA_CHANGED = 4;
 
     final static Object sServiceLock = new Object();
     static IAppWidgetService sService;
@@ -52,6 +58,9 @@
 
     class Callbacks extends IAppWidgetHost.Stub {
         public void updateAppWidget(int appWidgetId, RemoteViews views) {
+            if (isLocalBinder() && views != null) {
+                views = views.clone();
+            }
             Message msg = mHandler.obtainMessage(HANDLE_UPDATE);
             msg.arg1 = appWidgetId;
             msg.obj = views;
@@ -59,12 +68,20 @@
         }
 
         public void providerChanged(int appWidgetId, AppWidgetProviderInfo info) {
+            if (isLocalBinder() && info != null) {
+                info = info.clone();
+            }
             Message msg = mHandler.obtainMessage(HANDLE_PROVIDER_CHANGED);
             msg.arg1 = appWidgetId;
             msg.obj = info;
             msg.sendToTarget();
         }
 
+        public void providersChanged() {
+            Message msg = mHandler.obtainMessage(HANDLE_PROVIDERS_CHANGED);
+            msg.sendToTarget();
+        }
+
         public void viewDataChanged(int appWidgetId, int viewId) {
             Message msg = mHandler.obtainMessage(HANDLE_VIEW_DATA_CHANGED);
             msg.arg1 = appWidgetId;
@@ -77,7 +94,7 @@
         public UpdateHandler(Looper looper) {
             super(looper);
         }
-        
+
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case HANDLE_UPDATE: {
@@ -88,6 +105,10 @@
                     onProviderChanged(msg.arg1, (AppWidgetProviderInfo)msg.obj);
                     break;
                 }
+                case HANDLE_PROVIDERS_CHANGED: {
+                    onProvidersChanged();
+                    break;
+                }
                 case HANDLE_VIEW_DATA_CHANGED: {
                     viewDataChanged(msg.arg1, msg.arg2);
                     break;
@@ -95,18 +116,31 @@
             }
         }
     }
-    
+
     Handler mHandler;
 
     int mHostId;
     Callbacks mCallbacks = new Callbacks();
     final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<Integer, AppWidgetHostView>();
+    private OnClickHandler mOnClickHandler;
 
     public AppWidgetHost(Context context, int hostId) {
+        this(context, hostId, null, context.getMainLooper());
+    }
+
+    /**
+     * @hide
+     */
+    public AppWidgetHost(Context context, int hostId, OnClickHandler handler, Looper looper) {
         mContext = context;
         mHostId = hostId;
-        mHandler = new UpdateHandler(context.getMainLooper());
+        mOnClickHandler = handler;
+        mHandler = new UpdateHandler(looper);
         mDisplayMetrics = context.getResources().getDisplayMetrics();
+        bindService();
+    }
+
+    private static void bindService() {
         synchronized (sServiceLock) {
             if (sService == null) {
                 IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE);
@@ -122,7 +156,7 @@
     public void startListening() {
         int[] updatedIds;
         ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>();
-        
+
         try {
             if (mPackageName == null) {
                 mPackageName = mContext.getPackageName();
@@ -170,7 +204,40 @@
     }
 
     /**
-     * Stop listening to changes for this AppWidget.  
+     * Get a appWidgetId for a host in the calling process.
+     *
+     * @return a appWidgetId
+     * @hide
+     */
+    public static int allocateAppWidgetIdForSystem(int hostId) {
+        checkCallerIsSystem();
+        try {
+            if (sService == null) {
+                bindService();
+            }
+            Context systemContext =
+                    (Context) ActivityThread.currentActivityThread().getSystemContext();
+            String packageName = systemContext.getPackageName();
+            return sService.allocateAppWidgetId(packageName, hostId);
+        } catch (RemoteException e) {
+            throw new RuntimeException("system server dead?", e);
+        }
+    }
+
+    private static void checkCallerIsSystem() {
+        int uid = Process.myUid();
+        if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) {
+            return;
+        }
+        throw new SecurityException("Disallowed call for uid " + uid);
+    }
+
+    private boolean isLocalBinder() {
+        return Process.myPid() == Binder.getCallingPid();
+    }
+
+    /**
+     * Stop listening to changes for this AppWidget.
      */
     public void deleteAppWidgetId(int appWidgetId) {
         synchronized (mViews) {
@@ -185,6 +252,22 @@
     }
 
     /**
+     * Stop listening to changes for this AppWidget.
+     * @hide
+     */
+    public static void deleteAppWidgetIdForSystem(int appWidgetId) {
+        checkCallerIsSystem();
+        try {
+            if (sService == null) {
+                bindService();
+            }
+            sService.deleteAppWidgetId(appWidgetId);
+        } catch (RemoteException e) {
+            throw new RuntimeException("system server dead?", e);
+        }
+    }
+
+    /**
      * Remove all records about this host from the AppWidget manager.
      * <ul>
      *   <li>Call this when initializing your database, as it might be because of a data wipe.</li>
@@ -225,6 +308,7 @@
     public final AppWidgetHostView createView(Context context, int appWidgetId,
             AppWidgetProviderInfo appWidget) {
         AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget);
+        view.setOnClickHandler(mOnClickHandler);
         view.setAppWidget(appWidgetId, appWidget);
         synchronized (mViews) {
             mViews.put(appWidgetId, view);
@@ -236,6 +320,7 @@
             throw new RuntimeException("system server dead?", e);
         }
         view.updateAppWidget(views);
+
         return view;
     }
 
@@ -245,7 +330,7 @@
      */
     protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
             AppWidgetProviderInfo appWidget) {
-        return new AppWidgetHostView(context);
+        return new AppWidgetHostView(context, mOnClickHandler);
     }
 
     /**
@@ -255,7 +340,7 @@
         AppWidgetHostView v;
 
         // Convert complex to dp -- we are getting the AppWidgetProviderInfo from the
-        // AppWidgetService, which doesn't have our context, hence we need to do the 
+        // AppWidgetService, which doesn't have our context, hence we need to do the
         // conversion here.
         appWidget.minWidth =
             TypedValue.complexToDimensionPixelSize(appWidget.minWidth, mDisplayMetrics);
@@ -274,6 +359,14 @@
         }
     }
 
+    /**
+     * Called when the set of available widgets changes (ie. widget containing packages
+     * are added, updated or removed, or widget components are enabled or disabled.)
+     */
+    protected void onProvidersChanged() {
+        // Do nothing
+    }
+
     void updateAppWidgetView(int appWidgetId, RemoteViews views) {
         AppWidgetHostView v;
         synchronized (mViews) {
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index ed95ae5..52771ee 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -44,6 +44,7 @@
 import android.widget.BaseAdapter;
 import android.widget.FrameLayout;
 import android.widget.RemoteViews;
+import android.widget.RemoteViews.OnClickHandler;
 import android.widget.RemoteViewsAdapter.RemoteAdapterConnectionCallback;
 import android.widget.TextView;
 
@@ -83,7 +84,8 @@
     long mFadeStartTime = -1;
     Bitmap mOld;
     Paint mOldPaint = new Paint();
-    
+    private OnClickHandler mOnClickHandler;
+
     /**
      * Create a host view.  Uses default fade animations.
      */
@@ -92,9 +94,17 @@
     }
 
     /**
+     * @hide
+     */
+    public AppWidgetHostView(Context context, OnClickHandler handler) {
+        this(context, android.R.anim.fade_in, android.R.anim.fade_out);
+        mOnClickHandler = handler;
+    }
+
+    /**
      * Create a host view. Uses specified animations when pushing
      * {@link #updateAppWidget(RemoteViews)}.
-     * 
+     *
      * @param animationIn Resource ID of in animation to use
      * @param animationOut Resource ID of out animation to use
      */
@@ -109,6 +119,17 @@
     }
 
     /**
+     * Pass the given handler to RemoteViews when updating this widget. Unless this
+     * is done immediatly after construction, a call to {@link #updateAppWidget(RemoteViews)}
+     * should be made.
+     * @param handler
+     * @hide
+     */
+    public void setOnClickHandler(OnClickHandler handler) {
+        mOnClickHandler = handler;
+    }
+
+    /**
      * Set the AppWidget that will be displayed by this view. This method also adds default padding
      * to widgets, as described in {@link #getDefaultPaddingForWidget(Context, ComponentName, Rect)}
      * and can be overridden in order to add custom padding.
@@ -123,6 +144,7 @@
             // We add padding to the AppWidgetHostView if necessary
             Rect padding = getDefaultPaddingForWidget(mContext, info.provider, null);
             setPadding(padding.left, padding.top, padding.right, padding.bottom);
+            setContentDescription(info.label);
         }
     }
 
@@ -140,7 +162,7 @@
      * @param component the component name of the widget
      * @param padding Rect in which to place the output, if null, a new Rect will be allocated and
      *                returned
-     * @return default padding for this widget
+     * @return default padding for this widget, in pixels
      */
     public static Rect getDefaultPaddingForWidget(Context context, ComponentName component,
             Rect padding) {
@@ -177,7 +199,7 @@
     public int getAppWidgetId() {
         return mAppWidgetId;
     }
-    
+
     public AppWidgetProviderInfo getAppWidgetInfo() {
         return mInfo;
     }
@@ -205,7 +227,12 @@
 
         if (jail == null) jail = new ParcelableSparseArray();
 
-        super.dispatchRestoreInstanceState(jail);
+        try  {
+            super.dispatchRestoreInstanceState(jail);
+        } catch (Exception e) {
+            Log.e(TAG, "failed to restoreInstanceState for widget id: " + mAppWidgetId + ", "
+                    + (mInfo == null ? "null" : mInfo.provider), e);
+        }
     }
 
     /**
@@ -215,18 +242,26 @@
      * AppWidget options and causes a callback to the AppWidgetProvider.
      * @see AppWidgetProvider#onAppWidgetOptionsChanged(Context, AppWidgetManager, int, Bundle)
      *
-     * @param options The bundle of options, in addition to the size information,
+     * @param newOptions The bundle of options, in addition to the size information,
      *          can be null.
-     * @param minWidth The minimum width that the widget will be displayed at.
-     * @param minHeight The maximum height that the widget will be displayed at.
-     * @param maxWidth The maximum width that the widget will be displayed at.
-     * @param maxHeight The maximum height that the widget will be displayed at.
+     * @param minWidth The minimum width in dips that the widget will be displayed at.
+     * @param minHeight The maximum height in dips that the widget will be displayed at.
+     * @param maxWidth The maximum width in dips that the widget will be displayed at.
+     * @param maxHeight The maximum height in dips that the widget will be displayed at.
      *
      */
-    public void updateAppWidgetSize(Bundle options, int minWidth, int minHeight, int maxWidth,
+    public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth,
             int maxHeight) {
-        if (options == null) {
-            options = new Bundle();
+        updateAppWidgetSize(newOptions, minWidth, minHeight, maxWidth, maxHeight, false);
+    }
+
+    /**
+     * @hide
+     */
+    public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth,
+            int maxHeight, boolean ignorePadding) {
+        if (newOptions == null) {
+            newOptions = new Bundle();
         }
 
         Rect padding = new Rect();
@@ -238,11 +273,30 @@
         int xPaddingDips = (int) ((padding.left + padding.right) / density);
         int yPaddingDips = (int) ((padding.top + padding.bottom) / density);
 
-        options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, minWidth - xPaddingDips);
-        options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, minHeight - yPaddingDips);
-        options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, maxWidth - xPaddingDips);
-        options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, maxHeight - yPaddingDips);
-        updateAppWidgetOptions(options);
+        int newMinWidth = minWidth - (ignorePadding ? 0 : xPaddingDips);
+        int newMinHeight = minHeight - (ignorePadding ? 0 : yPaddingDips);
+        int newMaxWidth = maxWidth - (ignorePadding ? 0 : xPaddingDips);
+        int newMaxHeight = maxHeight - (ignorePadding ? 0 : yPaddingDips);
+
+        AppWidgetManager widgetManager = AppWidgetManager.getInstance(mContext);
+
+        // We get the old options to see if the sizes have changed
+        Bundle oldOptions = widgetManager.getAppWidgetOptions(mAppWidgetId);
+        boolean needsUpdate = false;
+        if (newMinWidth != oldOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH) ||
+                newMinHeight != oldOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT) ||
+                newMaxWidth != oldOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH) ||
+                newMaxHeight != oldOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)) {
+            needsUpdate = true;
+        }
+
+        if (needsUpdate) {
+            newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, newMinWidth);
+            newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, newMinHeight);
+            newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, newMaxWidth);
+            newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, newMaxHeight);
+            updateAppWidgetOptions(newOptions);
+        }
     }
 
     /**
@@ -281,12 +335,13 @@
      * AppWidget provider. Will animate into these new views as needed
      */
     public void updateAppWidget(RemoteViews remoteViews) {
+
         if (LOGD) Log.d(TAG, "updateAppWidget called mOld=" + mOld);
 
         boolean recycled = false;
         View content = null;
         Exception exception = null;
-        
+
         // Capture the old view into a bitmap so we can do the crossfade.
         if (CROSSFADE) {
             if (mFadeStartTime < 0) {
@@ -305,7 +360,7 @@
                 }
             }
         }
-        
+
         if (remoteViews == null) {
             if (mViewMode == VIEW_MODE_DEFAULT) {
                 // We've already done this -- nothing to do.
@@ -324,7 +379,7 @@
             // layout matches, try recycling it
             if (content == null && layoutId == mLayoutId) {
                 try {
-                    remoteViews.reapply(mContext, mView);
+                    remoteViews.reapply(mContext, mView, mOnClickHandler);
                     content = mView;
                     recycled = true;
                     if (LOGD) Log.d(TAG, "was able to recycled existing layout");
@@ -332,11 +387,11 @@
                     exception = e;
                 }
             }
-            
+
             // Try normal RemoteView inflation
             if (content == null) {
                 try {
-                    content = remoteViews.apply(mContext, this);
+                    content = remoteViews.apply(mContext, this, mOnClickHandler);
                     if (LOGD) Log.d(TAG, "had to inflate new layout");
                 } catch (RuntimeException e) {
                     exception = e;
@@ -346,7 +401,7 @@
             mLayoutId = layoutId;
             mViewMode = VIEW_MODE_CONTENT;
         }
-        
+
         if (content == null) {
             if (mViewMode == VIEW_MODE_ERROR) {
                 // We've already done this -- nothing to do.
@@ -356,7 +411,7 @@
             content = getErrorView();
             mViewMode = VIEW_MODE_ERROR;
         }
-        
+
         if (!recycled) {
             prepareView(content);
             addView(content);
@@ -455,7 +510,7 @@
             return super.drawChild(canvas, child, drawingTime);
         }
     }
-    
+
     /**
      * Prepare the given view to be shown. This might include adjusting
      * {@link FrameLayout.LayoutParams} before inserting.
@@ -471,7 +526,7 @@
         requested.gravity = Gravity.CENTER;
         view.setLayoutParams(requested);
     }
-    
+
     /**
      * Inflate and return the default layout requested by AppWidget provider.
      */
@@ -481,7 +536,7 @@
         }
         View defaultView = null;
         Exception exception = null;
-        
+
         try {
             if (mInfo != null) {
                 Context theirContext = mContext.createPackageContext(
@@ -491,7 +546,20 @@
                         theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                 inflater = inflater.cloneInContext(theirContext);
                 inflater.setFilter(sInflaterFilter);
-                defaultView = inflater.inflate(mInfo.initialLayout, this, false);
+                AppWidgetManager manager = AppWidgetManager.getInstance(mContext);
+                Bundle options = manager.getAppWidgetOptions(mAppWidgetId);
+
+                int layoutId = mInfo.initialLayout;
+                if (options.containsKey(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)) {
+                    int category = options.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY);
+                    if (category == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD) {
+                        int kgLayoutId = mInfo.initialKeyguardLayout;
+                        // If a default keyguard layout is not specified, use the standard
+                        // default layout.
+                        layoutId = kgLayoutId == 0 ? layoutId : kgLayoutId;
+                    }
+                }
+                defaultView = inflater.inflate(layoutId, this, false);
             } else {
                 Log.w(TAG, "can't inflate defaultView because mInfo is missing");
             }
@@ -500,19 +568,19 @@
         } catch (RuntimeException e) {
             exception = e;
         }
-        
+
         if (exception != null) {
             Log.w(TAG, "Error inflating AppWidget " + mInfo + ": " + exception.toString());
         }
-        
+
         if (defaultView == null) {
             if (LOGD) Log.d(TAG, "getDefaultView couldn't find any view, so inflating error");
             defaultView = getErrorView();
         }
-        
+
         return defaultView;
     }
-    
+
     /**
      * Inflate and return a view that represents an error state.
      */
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 2df675e..3dd640c 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -80,6 +80,13 @@
     public static final String ACTION_APPWIDGET_PICK = "android.appwidget.action.APPWIDGET_PICK";
 
     /**
+     * Similar to ACTION_APPWIDGET_PICK, but used from keyguard
+     * @hide
+     */
+    public static final String
+            ACTION_KEYGUARD_APPWIDGET_PICK = "android.appwidget.action.KEYGUARD_APPWIDGET_PICK";
+
+    /**
      * Send this from your {@link AppWidgetHost} activity when you want to bind an AppWidget to
      * display and bindAppWidgetIdIfAllowed returns false.
      * <p>
@@ -150,26 +157,34 @@
     public static final String EXTRA_APPWIDGET_ID = "appWidgetId";
 
     /**
-     * An bundle extra that contains the lower bound on the current width, in dips, of a widget instance.
+     * A bundle extra that contains the lower bound on the current width, in dips, of a widget instance.
      */
     public static final String OPTION_APPWIDGET_MIN_WIDTH = "appWidgetMinWidth";
 
     /**
-     * An bundle extra that contains the lower bound on the current height, in dips, of a widget instance.
+     * A bundle extra that contains the lower bound on the current height, in dips, of a widget instance.
      */
     public static final String OPTION_APPWIDGET_MIN_HEIGHT = "appWidgetMinHeight";
 
     /**
-     * An bundle extra that contains the upper bound on the current width, in dips, of a widget instance.
+     * A bundle extra that contains the upper bound on the current width, in dips, of a widget instance.
      */
     public static final String OPTION_APPWIDGET_MAX_WIDTH = "appWidgetMaxWidth";
 
     /**
-     * An bundle extra that contains the upper bound on the current width, in dips, of a widget instance.
+     * A bundle extra that contains the upper bound on the current width, in dips, of a widget instance.
      */
     public static final String OPTION_APPWIDGET_MAX_HEIGHT = "appWidgetMaxHeight";
 
     /**
+     * A bundle extra that hints to the AppWidgetProvider the category of host that owns this
+     * this widget. Can have the value {@link
+     * AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN} or {@link
+     * AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD}.
+     */
+    public static final String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory";
+
+    /**
      * An intent extra which points to a bundle of extra information for a particular widget id.
      * In particular this bundle can contain EXTRA_APPWIDGET_WIDTH and EXTRA_APPWIDGET_HEIGHT.
      */
@@ -208,6 +223,21 @@
     public static final String EXTRA_CUSTOM_EXTRAS = "customExtras";
 
     /**
+     * An intent extra to pass to the AppWidget picker which allows the picker to filter
+     * the list based on the {@link AppWidgetProviderInfo#widgetCategory}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_CATEGORY_FILTER = "categoryFilter";
+
+    /**
+     * An intent extra to pass to the AppWidget picker to specify whether or not to sort
+     * the list of caller-specified extra AppWidgets along with the rest of the AppWidgets
+     * @hide
+     */
+    public static final String EXTRA_CUSTOM_SORT = "customSort";
+
+    /**
      * A sentiel value that the AppWidget manager will never return as a appWidgetId.
      */
     public static final int INVALID_APPWIDGET_ID = 0;
@@ -406,10 +436,9 @@
      *
      * This update  differs from {@link #updateAppWidget(int[], RemoteViews)} in that the
      * RemoteViews object which is passed is understood to be an incomplete representation of the 
-     * widget, and hence is not cached by the AppWidgetService. Note that because these updates are 
-     * not cached, any state that they modify that is not restored by restoreInstanceState will not
-     * persist in the case that the widgets are restored using the cached version in
-     * AppWidgetService.
+     * widget, and hence does not replace the cached representation of the widget. As of API
+     * level 17, the new properties set within the views objects will be appended to the cached
+     * representation of the widget, and hence will persist.
      *
      * Use with {@link RemoteViews#showNext(int)}, {@link RemoteViews#showPrevious(int)},
      * {@link RemoteViews#setScrollPosition(int, int)} and similar commands.
@@ -419,6 +448,10 @@
      * and outside of the handler.
      * This method will only work when called from the uid that owns the AppWidget provider.
      *
+     * <p>
+     * This method will be ignored if a widget has not received a full update via
+     * {@link #updateAppWidget(int[], RemoteViews)}.
+     *
      * @param appWidgetIds     The AppWidget instances for which to set the RemoteViews.
      * @param views            The RemoteViews object containing the incremental update / command.
      */
@@ -447,6 +480,10 @@
      * and outside of the handler.
      * This method will only work when called from the uid that owns the AppWidget provider.
      *
+     * <p>
+     * This method will be ignored if a widget has not received a full update via
+     * {@link #updateAppWidget(int[], RemoteViews)}.
+     *
      * @param appWidgetId      The AppWidget instance for which to set the RemoteViews.
      * @param views            The RemoteViews object containing the incremental update / command.
      */
@@ -568,7 +605,31 @@
      */
     public void bindAppWidgetId(int appWidgetId, ComponentName provider) {
         try {
-            sService.bindAppWidgetId(appWidgetId, provider);
+            sService.bindAppWidgetId(appWidgetId, provider, null);
+        }
+        catch (RemoteException e) {
+            throw new RuntimeException("system server dead?", e);
+        }
+    }
+
+    /**
+     * Set the component for a given appWidgetId.
+     *
+     * <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
+     *         widgets always for your component. This method is used by the AppWidget picker and
+     *         should not be used by other apps.
+     *
+     * @param appWidgetId     The AppWidget instance for which to set the RemoteViews.
+     * @param provider      The {@link android.content.BroadcastReceiver} that will be the AppWidget
+     *                      provider for this AppWidget.
+     * @param options       Bundle containing options for the AppWidget. See also
+     *                      {@link #updateAppWidgetOptions(int, Bundle)}
+     *
+     * @hide
+     */
+    public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options) {
+        try {
+            sService.bindAppWidgetId(appWidgetId, provider, options);
         }
         catch (RemoteException e) {
             throw new RuntimeException("system server dead?", e);
@@ -594,7 +655,37 @@
         }
         try {
             return sService.bindAppWidgetIdIfAllowed(
-                    mContext.getPackageName(), appWidgetId, provider);
+                    mContext.getPackageName(), appWidgetId, provider, null);
+        }
+        catch (RemoteException e) {
+            throw new RuntimeException("system server dead?", e);
+        }
+    }
+
+    /**
+     * Set the component for a given appWidgetId.
+     *
+     * <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
+     *         widgets always for your component. Should be used by apps that host widgets; if this
+     *         method returns false, call {@link #ACTION_APPWIDGET_BIND} to request permission to
+     *         bind
+     *
+     * @param appWidgetId     The AppWidget instance for which to set the RemoteViews.
+     * @param provider      The {@link android.content.BroadcastReceiver} that will be the AppWidget
+     *                      provider for this AppWidget.
+     * @param options       Bundle containing options for the AppWidget. See also
+     *                      {@link #updateAppWidgetOptions(int, Bundle)}
+     *
+     * @return true if this component has permission to bind the AppWidget
+     */
+    public boolean bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider,
+            Bundle options) {
+        if (mContext == null) {
+            return false;
+        }
+        try {
+            return sService.bindAppWidgetIdIfAllowed(
+                    mContext.getPackageName(), appWidgetId, provider, options);
         }
         catch (RemoteException e) {
             throw new RuntimeException("system server dead?", e);
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index c33681d..7b8b286 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -44,6 +44,16 @@
     public static final int RESIZE_BOTH = RESIZE_HORIZONTAL | RESIZE_VERTICAL;
 
     /**
+     * Indicates that the widget can be displayed on the home screen. This is the default value.
+     */
+    public static final int WIDGET_CATEGORY_HOME_SCREEN = 1;
+
+    /**
+     * Indicates that the widget can be displayed on the keyguard.
+     */
+    public static final int WIDGET_CATEGORY_KEYGUARD = 2;
+
+    /**
      * Identity of this AppWidget component.  This component should be a {@link
      * android.content.BroadcastReceiver}, and it will be sent the AppWidget intents
      * {@link android.appwidget as described in the AppWidget package documentation}.
@@ -111,6 +121,16 @@
     public int initialLayout;
 
     /**
+     * The resource id of the initial layout for this AppWidget when it is displayed on keyguard.
+     * This parameter only needs to be provided if the widget can be displayed on the keyguard,
+     * see {@link #widgetCategory}.
+     *
+     * <p>This field corresponds to the <code>android:initialKeyguardLayout</code> attribute in
+     * the AppWidget meta-data file.
+     */
+    public int initialKeyguardLayout;
+
+    /**
      * The activity to launch that will configure the AppWidget.
      *
      * <p>This class name of field corresponds to the <code>android:configure</code> attribute in
@@ -164,6 +184,17 @@
      */
     public int resizeMode;
 
+    /**
+     * Determines whether this widget can be displayed on the home screen, the keyguard, or both.
+     * A widget which is displayed on both needs to ensure that it follows the design guidelines
+     * for both widget classes. This can be achieved by querying the AppWidget options in its
+     * widget provider's update method.
+     *
+     * <p>This field corresponds to the <code>widgetCategory</code> attribute in
+     * the AppWidget meta-data file.
+     */
+    public int widgetCategory;
+
     public AppWidgetProviderInfo() {
     }
 
@@ -180,6 +211,7 @@
         this.minResizeHeight = in.readInt();
         this.updatePeriodMillis = in.readInt();
         this.initialLayout = in.readInt();
+        this.initialKeyguardLayout = in.readInt();
         if (0 != in.readInt()) {
             this.configure = new ComponentName(in);
         }
@@ -188,6 +220,7 @@
         this.previewImage = in.readInt();
         this.autoAdvanceViewId = in.readInt();
         this.resizeMode = in.readInt();
+        this.widgetCategory = in.readInt();
     }
 
     public void writeToParcel(android.os.Parcel out, int flags) {
@@ -203,6 +236,7 @@
         out.writeInt(this.minResizeHeight);
         out.writeInt(this.updatePeriodMillis);
         out.writeInt(this.initialLayout);
+        out.writeInt(this.initialKeyguardLayout);
         if (this.configure != null) {
             out.writeInt(1);
             this.configure.writeToParcel(out, flags);
@@ -214,6 +248,28 @@
         out.writeInt(this.previewImage);
         out.writeInt(this.autoAdvanceViewId);
         out.writeInt(this.resizeMode);
+        out.writeInt(this.widgetCategory);
+    }
+
+    @Override
+    public AppWidgetProviderInfo clone() {
+        AppWidgetProviderInfo that = new AppWidgetProviderInfo();
+        that.provider = this.provider == null ? null : this.provider.clone();
+        that.minWidth = this.minWidth;
+        that.minHeight = this.minHeight;
+        that.minResizeWidth = this.minResizeHeight;
+        that.minResizeHeight = this.minResizeHeight;
+        that.updatePeriodMillis = this.updatePeriodMillis;
+        that.initialLayout = this.initialLayout;
+        that.initialKeyguardLayout = this.initialKeyguardLayout;
+        that.configure = this.configure == null ? null : this.configure.clone();
+        that.label = this.label == null ? null : this.label.substring(0);
+        that.icon = this.icon;
+        that.previewImage = this.previewImage;
+        that.autoAdvanceViewId = this.autoAdvanceViewId;
+        that.resizeMode = this.resizeMode;
+        that.widgetCategory  = this.widgetCategory;
+        return that;
     }
 
     public int describeContents() {
diff --git a/core/java/android/bluetooth/AtCommandHandler.java b/core/java/android/bluetooth/AtCommandHandler.java
deleted file mode 100644
index 6deab34..0000000
--- a/core/java/android/bluetooth/AtCommandHandler.java
+++ /dev/null
@@ -1,94 +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.
- */
-
-package android.bluetooth;
-
-import android.bluetooth.AtCommandResult;
-
-/**
- * Handler Interface for {@link AtParser}.<p>
- * @hide
- */
-public abstract class AtCommandHandler {
-
-    /**
-     * Handle Basic commands "ATA".<p>
-     * These are single letter commands such as ATA and ATD. Anything following
-     * the single letter command ('A' and 'D' respectively) will be passed as
-     * 'arg'.<p>
-     * For example, "ATDT1234" would result in the call
-     * handleBasicCommand("T1234").<p>
-     * @param arg Everything following the basic command character.
-     * @return    The result of this command.
-     */
-    public AtCommandResult handleBasicCommand(String arg) {
-        return new AtCommandResult(AtCommandResult.ERROR);
-    }
-
-    /**
-     * Handle Actions command "AT+FOO".<p>
-     * Action commands are part of the Extended command syntax, and are
-     * typically used to signal an action on "FOO".<p>
-     * @return The result of this command.
-     */
-    public AtCommandResult handleActionCommand() {
-        return new AtCommandResult(AtCommandResult.ERROR);
-    }
-
-    /**
-     * Handle Read command "AT+FOO?".<p>
-     * Read commands are part of the Extended command syntax, and are
-     * typically used to read the value of "FOO".<p>
-     * @return The result of this command.
-     */
-    public AtCommandResult handleReadCommand() {
-        return new AtCommandResult(AtCommandResult.ERROR);
-    }
-
-    /**
-     * Handle Set command "AT+FOO=...".<p>
-     * Set commands are part of the Extended command syntax, and are
-     * typically used to set the value of "FOO". Multiple arguments can be
-     * sent.<p>
-     * AT+FOO=[<arg1>[,<arg2>[,...]]]<p>
-     * Each argument will be either numeric (Integer) or String.
-     * handleSetCommand is passed a generic Object[] array in which each
-     * element will be an Integer (if it can be parsed with parseInt()) or
-     * String.<p>
-     * Missing arguments ",," are set to empty Strings.<p>
-     * @param args Array of String and/or Integer's. There will always be at
-     *             least one element in this array.
-     * @return     The result of this command.
-     */
-    // Typically used to set this parameter
-    public AtCommandResult handleSetCommand(Object[] args) {
-        return new AtCommandResult(AtCommandResult.ERROR);
-    }
-
-    /**
-     * Handle Test command "AT+FOO=?".<p>
-     * Test commands are part of the Extended command syntax, and are typically
-     * used to request an indication of the range of legal values that "FOO"
-     * can take.<p>
-     * By default we return an OK result, to indicate that this command is at
-     * least recognized.<p>
-     * @return The result of this command.
-     */
-    public AtCommandResult handleTestCommand() {
-        return new AtCommandResult(AtCommandResult.OK);
-    }
-
-}
diff --git a/core/java/android/bluetooth/AtCommandResult.java b/core/java/android/bluetooth/AtCommandResult.java
deleted file mode 100644
index 9675234..0000000
--- a/core/java/android/bluetooth/AtCommandResult.java
+++ /dev/null
@@ -1,115 +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.
- */
-
-package android.bluetooth;
-
-/**
- * The result of execution of a single AT command.<p>
- *
- *
- * This class can represent the final response to an AT command line, and also
- * intermediate responses to a single command within a chained AT command
- * line.<p>
- *
- * The actual responses that are intended to be send in reply to the AT command
- * line are stored in a string array. The final response is stored as an
- * int enum, converted to a string when toString() is called. Only a single
- * final response is sent from multiple commands chained into a single command
- * line.<p>
- * @hide
- */
-public class AtCommandResult {
-    // Result code enumerations
-    public static final int OK = 0;
-    public static final int ERROR = 1;
-    public static final int UNSOLICITED = 2;
-
-    private static final String OK_STRING = "OK";
-    private static final String ERROR_STRING = "ERROR";
-
-    private int mResultCode;  // Result code
-    private StringBuilder mResponse; // Response with CRLF line breaks
-
-    /**
-     * Construct a new AtCommandResult with given result code, and an empty
-     * response array.
-     * @param resultCode One of OK, ERROR or UNSOLICITED.
-     */
-    public AtCommandResult(int resultCode) {
-        mResultCode = resultCode;
-        mResponse = new StringBuilder();
-    }
-
-    /**
-     * Construct a new AtCommandResult with result code OK, and the specified
-     * single line response.
-     * @param response The single line response.
-     */
-    public AtCommandResult(String response) {
-        this(OK);
-        addResponse(response);
-    }
-
-    public int getResultCode() {
-        return mResultCode;
-    }
-
-    /**
-     * Add another line to the response.
-     */
-    public void addResponse(String response) {
-        appendWithCrlf(mResponse, response);
-    }
-
-    /**
-     * Add the given result into this AtCommandResult object.<p>
-     * Used to combine results from multiple commands in a single command line
-     * (command chaining).
-     * @param result The AtCommandResult to add to this result.
-     */
-    public void addResult(AtCommandResult result) {
-        if (result != null) {
-            appendWithCrlf(mResponse, result.mResponse.toString());
-            mResultCode = result.mResultCode;
-        }
-    }
-
-    /**
-     * Generate the string response ready to send
-     */
-    public String toString() {
-        StringBuilder result = new StringBuilder(mResponse.toString());
-        switch (mResultCode) {
-        case OK:
-            appendWithCrlf(result, OK_STRING);
-            break;
-        case ERROR:
-            appendWithCrlf(result, ERROR_STRING);
-            break;
-        }
-        return result.toString();
-    }
-
-    /** Append a string to a string builder, joining with a double
-     * CRLF. Used to create multi-line AT command replies
-     */
-    public static void appendWithCrlf(StringBuilder str1, String str2) {
-        if (str1.length() > 0 && str2.length() > 0) {
-            str1.append("\r\n\r\n");
-        }
-        str1.append(str2);
-    }
-};
diff --git a/core/java/android/bluetooth/AtParser.java b/core/java/android/bluetooth/AtParser.java
deleted file mode 100644
index 328fb2b..0000000
--- a/core/java/android/bluetooth/AtParser.java
+++ /dev/null
@@ -1,367 +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.
- */
-
-package android.bluetooth;
-
-import java.util.*;
-
-/**
- * An AT (Hayes command) Parser based on (a subset of) the ITU-T V.250 standard.
- * <p>
- *
- * Conformant with the subset of V.250 required for implementation of the
- * Bluetooth Headset and Handsfree Profiles, as per Bluetooth SIP
- * specifications. Also implements some V.250 features not required by
- * Bluetooth - such as chained commands.<p>
- *
- * Command handlers are registered with an AtParser object. These handlers are
- * invoked when command lines are processed by AtParser's process() method.<p>
- *
- * The AtParser object accepts a new command line to parse via its process()
- * method. It breaks each command line into one or more commands. Each command
- * is parsed for name, type, and (optional) arguments, and an appropriate
- * external handler method is called through the AtCommandHandler interface.
- *
- * The command types are<ul>
- * <li>Basic Command. For example "ATDT1234567890". Basic command names are a
- * single character (e.g. "D"), and everything following this character is
- * passed to the handler as a string argument (e.g. "T1234567890").
- * <li>Action Command. For example "AT+CIMI". The command name is "CIMI", and
- * there are no arguments for action commands.
- * <li>Read Command. For example "AT+VGM?". The command name is "VGM", and there
- * are no arguments for get commands.
- * <li>Set Command. For example "AT+VGM=14". The command name is "VGM", and
- * there is a single integer argument in this case. In the general case then
- * can be zero or more arguments (comma delimited) each of integer or string
- * form.
- * <li>Test Command. For example "AT+VGM=?. No arguments.
- * </ul>
- *
- * In V.250 the last four command types are known as Extended Commands, and
- * they are used heavily in Bluetooth.<p>
- *
- * Basic commands cannot be chained in this implementation. For Bluetooth
- * headset/handsfree use this is acceptable, because they only use the basic
- * commands ATA and ATD, which are not allowed to be chained. For general V.250
- * use we would need to improve this class to allow Basic command chaining -
- * however it's tricky to get right because there is no delimiter for Basic
- * command chaining.<p>
- *
- * Extended commands can be chained. For example:<p>
- * AT+VGM?;+VGM=14;+CIMI<p>
- * This is equivalent to:<p>
- * AT+VGM?
- * AT+VGM=14
- * AT+CIMI
- * Except that only one final result code is return (although several
- * intermediate responses may be returned), and as soon as one command in the
- * chain fails the rest are abandoned.<p>
- *
- * Handlers are registered by there command name via register(Char c, ...) or
- * register(String s, ...). Handlers for Basic command should be registered by
- * the basic command character, and handlers for Extended commands should be
- * registered by String.<p>
- *
- * Refer to:<ul>
- * <li>ITU-T Recommendation V.250
- * <li>ETSI TS 127.007  (AT Command set for User Equipment, 3GPP TS 27.007)
- * <li>Bluetooth Headset Profile Spec (K6)
- * <li>Bluetooth Handsfree Profile Spec (HFP 1.5)
- * </ul>
- * @hide
- */
-public class AtParser {
-
-    // Extended command type enumeration, only used internally
-    private static final int TYPE_ACTION = 0;   // AT+FOO
-    private static final int TYPE_READ = 1;     // AT+FOO?
-    private static final int TYPE_SET = 2;      // AT+FOO=
-    private static final int TYPE_TEST = 3;     // AT+FOO=?
-
-    private HashMap<String, AtCommandHandler> mExtHandlers;
-    private HashMap<Character, AtCommandHandler> mBasicHandlers;
-
-    private String mLastInput;  // for "A/" (repeat last command) support
-
-    /**
-     * Create a new AtParser.<p>
-     * No handlers are registered.
-     */
-    public AtParser() {
-        mBasicHandlers = new HashMap<Character, AtCommandHandler>();
-        mExtHandlers = new HashMap<String, AtCommandHandler>();
-        mLastInput = "";
-    }
-
-    /**
-     * Register a Basic command handler.<p>
-     * Basic command handlers are later called via their
-     * <code>handleBasicCommand(String args)</code> method.
-     * @param  command Command name - a single character
-     * @param  handler Handler to register
-     */
-    public void register(Character command, AtCommandHandler handler) {
-        mBasicHandlers.put(command, handler);
-    }
-
-    /**
-     * Register an Extended command handler.<p>
-     * Extended command handlers are later called via:<ul>
-     * <li><code>handleActionCommand()</code>
-     * <li><code>handleGetCommand()</code>
-     * <li><code>handleSetCommand()</code>
-     * <li><code>handleTestCommand()</code>
-     * </ul>
-     * Only one method will be called for each command processed.
-     * @param  command Command name - can be multiple characters
-     * @param  handler Handler to register
-     */
-    public void register(String command, AtCommandHandler handler) {
-        mExtHandlers.put(command, handler);
-    }
-
-
-    /**
-     * Strip input of whitespace and force Uppercase - except sections inside
-     * quotes. Also fixes unmatched quotes (by appending a quote). Double
-     * quotes " are the only quotes allowed by V.250
-     */
-    static private String clean(String input) {
-        StringBuilder out = new StringBuilder(input.length());
-
-        for (int i = 0; i < input.length(); i++) {
-            char c = input.charAt(i);
-            if (c == '"') {
-                int j = input.indexOf('"', i + 1 );  // search for closing "
-                if (j == -1) {  // unmatched ", insert one.
-                    out.append(input.substring(i, input.length()));
-                    out.append('"');
-                    break;
-                }
-                out.append(input.substring(i, j + 1));
-                i = j;
-            } else if (c != ' ') {
-                out.append(Character.toUpperCase(c));
-            }
-        }
-
-        return out.toString();
-    }
-
-    static private boolean isAtoZ(char c) {
-        return (c >= 'A' && c <= 'Z');
-    }
-
-    /**
-     * Find a character ch, ignoring quoted sections.
-     * Return input.length() if not found.
-     */
-    static private int findChar(char ch, String input, int fromIndex) {
-        for (int i = fromIndex; i < input.length(); i++) {
-            char c = input.charAt(i);
-            if (c == '"') {
-                i = input.indexOf('"', i + 1);
-                if (i == -1) {
-                    return input.length();
-                }
-            } else if (c == ch) {
-                return i;
-            }
-        }
-        return input.length();
-    }
-
-    /**
-     * Break an argument string into individual arguments (comma delimited).
-     * Integer arguments are turned into Integer objects. Otherwise a String
-     * object is used.
-     */
-    static private Object[] generateArgs(String input) {
-        int i = 0;
-        int j;
-        ArrayList<Object> out = new ArrayList<Object>();
-        while (i <= input.length()) {
-            j = findChar(',', input, i);
-
-            String arg = input.substring(i, j);
-            try {
-                out.add(new Integer(arg));
-            } catch (NumberFormatException e) {
-                out.add(arg);
-            }
-
-            i = j + 1; // move past comma
-        }
-        return out.toArray();
-    }
-
-    /**
-     * Return the index of the end of character after the last character in
-     * the extended command name. Uses the V.250 spec for allowed command
-     * names.
-     */
-    static private int findEndExtendedName(String input, int index) {
-        for (int i = index; i < input.length(); i++) {
-            char c = input.charAt(i);
-
-            // V.250 defines the following chars as legal extended command
-            // names
-            if (isAtoZ(c)) continue;
-            if (c >= '0' && c <= '9') continue;
-            switch (c) {
-            case '!':
-            case '%':
-            case '-':
-            case '.':
-            case '/':
-            case ':':
-            case '_':
-                continue;
-            default:
-                return i;
-            }
-        }
-        return input.length();
-    }
-
-    /**
-     * Processes an incoming AT command line.<p>
-     * This method will invoke zero or one command handler methods for each
-     * command in the command line.<p>
-     * @param raw_input The AT input, without EOL delimiter (e.g. <CR>).
-     * @return          Result object for this command line. This can be
-     *                  converted to a String[] response with toStrings().
-     */
-    public AtCommandResult process(String raw_input) {
-        String input = clean(raw_input);
-
-        // Handle "A/" (repeat previous line)
-        if (input.regionMatches(0, "A/", 0, 2)) {
-            input = new String(mLastInput);
-        } else {
-            mLastInput = new String(input);
-        }
-
-        // Handle empty line - no response necessary
-        if (input.equals("")) {
-            // Return []
-            return new AtCommandResult(AtCommandResult.UNSOLICITED);
-        }
-
-        // Anything else deserves an error
-        if (!input.regionMatches(0, "AT", 0, 2)) {
-            // Return ["ERROR"]
-            return new AtCommandResult(AtCommandResult.ERROR);
-        }
-
-        // Ok we have a command that starts with AT. Process it
-        int index = 2;
-        AtCommandResult result =
-                new AtCommandResult(AtCommandResult.UNSOLICITED);
-        while (index < input.length()) {
-            char c = input.charAt(index);
-
-            if (isAtoZ(c)) {
-                // Option 1: Basic Command
-                // Pass the rest of the line as is to the handler. Do not
-                // look for any more commands on this line.
-                String args = input.substring(index + 1);
-                if (mBasicHandlers.containsKey((Character)c)) {
-                    result.addResult(mBasicHandlers.get(
-                            (Character)c).handleBasicCommand(args));
-                    return result;
-                } else {
-                    // no handler
-                    result.addResult(
-                            new AtCommandResult(AtCommandResult.ERROR));
-                    return result;
-                }
-                // control never reaches here
-            }
-
-            if (c == '+') {
-                // Option 2: Extended Command
-                // Search for first non-name character. Short-circuit if
-                // we don't handle this command name.
-                int i = findEndExtendedName(input, index + 1);
-                String commandName = input.substring(index, i);
-                if (!mExtHandlers.containsKey(commandName)) {
-                    // no handler
-                    result.addResult(
-                            new AtCommandResult(AtCommandResult.ERROR));
-                    return result;
-                }
-                AtCommandHandler handler = mExtHandlers.get(commandName);
-
-                // Search for end of this command - this is usually the end of
-                // line
-                int endIndex = findChar(';', input, index);
-
-                // Determine what type of command this is.
-                // Default to TYPE_ACTION if we can't find anything else
-                // obvious.
-                int type;
-
-                if (i >= endIndex) {
-                    type = TYPE_ACTION;
-                } else if (input.charAt(i) == '?') {
-                    type = TYPE_READ;
-                } else if (input.charAt(i) == '=') {
-                    if (i + 1 < endIndex) {
-                        if (input.charAt(i + 1) == '?') {
-                            type = TYPE_TEST;
-                        } else {
-                            type = TYPE_SET;
-                        }
-                    } else {
-                        type = TYPE_SET;
-                    }
-                } else {
-                    type = TYPE_ACTION;
-                }
-
-                // Call this command. Short-circuit as soon as a command fails
-                switch (type) {
-                case TYPE_ACTION:
-                    result.addResult(handler.handleActionCommand());
-                    break;
-                case TYPE_READ:
-                    result.addResult(handler.handleReadCommand());
-                    break;
-                case TYPE_TEST:
-                    result.addResult(handler.handleTestCommand());
-                    break;
-                case TYPE_SET:
-                    Object[] args =
-                            generateArgs(input.substring(i + 1, endIndex));
-                    result.addResult(handler.handleSetCommand(args));
-                    break;
-                }
-                if (result.getResultCode() != AtCommandResult.OK) {
-                    return result;   // short-circuit
-                }
-
-                index = endIndex;
-            } else {
-                // Can't tell if this is a basic or extended command.
-                // Push forwards and hope we hit something.
-                index++;
-            }
-        }
-        // Finished processing (and all results were ok)
-        return result;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
old mode 100644
new mode 100755
index 7300107..6fdf3b4
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -18,12 +18,13 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
 import android.os.IBinder;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.server.BluetoothA2dpService;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -43,7 +44,8 @@
  */
 public final class BluetoothA2dp implements BluetoothProfile {
     private static final String TAG = "BluetoothA2dp";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
+    private static final boolean VDBG = false;
 
     /**
      * Intent used to broadcast the change in connection state of the A2DP
@@ -102,37 +104,90 @@
      */
     public static final int STATE_NOT_PLAYING   =  11;
 
+    private Context mContext;
     private ServiceListener mServiceListener;
     private IBluetoothA2dp mService;
     private BluetoothAdapter mAdapter;
 
+    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+            new IBluetoothStateChangeCallback.Stub() {
+                public void onBluetoothStateChange(boolean up) {
+                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
+                    if (!up) {
+                        if (VDBG) Log.d(TAG,"Unbinding service...");
+                        synchronized (mConnection) {
+                            try {
+                                mService = null;
+                                mContext.unbindService(mConnection);
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    } else {
+                        synchronized (mConnection) {
+                            try {
+                                if (mService == null) {
+                                    if (VDBG) Log.d(TAG,"Binding service...");
+                                    if (!mContext.bindService(new Intent(IBluetoothA2dp.class.getName()), mConnection, 0)) {
+                                        Log.e(TAG, "Could not bind to Bluetooth A2DP Service");
+                                    }
+                                }
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    }
+                }
+        };
     /**
      * Create a BluetoothA2dp proxy object for interacting with the local
      * Bluetooth A2DP service.
      *
      */
-    /*package*/ BluetoothA2dp(Context mContext, ServiceListener l) {
-        IBinder b = ServiceManager.getService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE);
+    /*package*/ BluetoothA2dp(Context context, ServiceListener l) {
+        mContext = context;
         mServiceListener = l;
         mAdapter = BluetoothAdapter.getDefaultAdapter();
-        if (b != null) {
-            mService = IBluetoothA2dp.Stub.asInterface(b);
-            if (mServiceListener != null) {
-                mServiceListener.onServiceConnected(BluetoothProfile.A2DP, this);
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG,"",e);
             }
-        } else {
-            Log.w(TAG, "Bluetooth A2DP service not available!");
+        }
 
-            // Instead of throwing an exception which prevents people from going
-            // into Wireless settings in the emulator. Let it crash later when it is actually used.
-            mService = null;
+        if (!context.bindService(new Intent(IBluetoothA2dp.class.getName()), mConnection, 0)) {
+            Log.e(TAG, "Could not bind to Bluetooth A2DP Service");
         }
     }
 
     /*package*/ void close() {
         mServiceListener = null;
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (Exception e) {
+                Log.e(TAG,"",e);
+            }
+        }
+
+        synchronized (mConnection) {
+            if (mService != null) {
+                try {
+                    mService = null;
+                    mContext.unbindService(mConnection);
+                } catch (Exception re) {
+                    Log.e(TAG,"",re);
+                }
+            }
+        }
     }
 
+    public void finalize() {
+        close();
+    }
     /**
      * Initiate connection to a profile of the remote bluetooth device.
      *
@@ -215,7 +270,7 @@
      * {@inheritDoc}
      */
     public List<BluetoothDevice> getConnectedDevices() {
-        if (DBG) log("getConnectedDevices()");
+        if (VDBG) log("getConnectedDevices()");
         if (mService != null && isEnabled()) {
             try {
                 return mService.getConnectedDevices();
@@ -232,7 +287,7 @@
      * {@inheritDoc}
      */
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (DBG) log("getDevicesMatchingStates()");
+        if (VDBG) log("getDevicesMatchingStates()");
         if (mService != null && isEnabled()) {
             try {
                 return mService.getDevicesMatchingConnectionStates(states);
@@ -249,7 +304,7 @@
      * {@inheritDoc}
      */
     public int getConnectionState(BluetoothDevice device) {
-        if (DBG) log("getState(" + device + ")");
+        if (VDBG) log("getState(" + device + ")");
         if (mService != null && isEnabled()
             && isValidDevice(device)) {
             try {
@@ -267,7 +322,7 @@
      * Set priority of the profile
      *
      * <p> The device should already be paired.
-     *  Priority can be one of {@link #PRIORITY_ON} or
+     *  Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
      * {@link #PRIORITY_OFF},
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
@@ -283,7 +338,7 @@
         if (mService != null && isEnabled()
             && isValidDevice(device)) {
             if (priority != BluetoothProfile.PRIORITY_OFF &&
-                priority != BluetoothProfile.PRIORITY_ON) {
+                priority != BluetoothProfile.PRIORITY_ON){
               return false;
             }
             try {
@@ -311,7 +366,7 @@
      * @hide
      */
     public int getPriority(BluetoothDevice device) {
-        if (DBG) log("getPriority(" + device + ")");
+        if (VDBG) log("getPriority(" + device + ")");
         if (mService != null && isEnabled()
             && isValidDevice(device)) {
             try {
@@ -347,67 +402,6 @@
     }
 
     /**
-     * Initiate suspend from an A2DP sink.
-     *
-     * <p> This API will return false in scenarios like the A2DP
-     * device is not in connected state etc. When this API returns,
-     * true, it is guaranteed that {@link #ACTION_CONNECTION_STATE_CHANGED}
-     * intent will be broadcasted with the state. Users can get the
-     * state of the A2DP device from this intent.
-     *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-     * permission.
-     *
-     * @param device Remote A2DP sink
-     * @return false on immediate error,
-     *               true otherwise
-     * @hide
-     */
-    public boolean suspendSink(BluetoothDevice device) {
-        if (mService != null && isEnabled()
-            && isValidDevice(device)) {
-            try {
-                return mService.suspendSink(device);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
-                return false;
-            }
-        }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
-        return false;
-    }
-
-    /**
-     * Initiate resume from a suspended A2DP sink.
-     *
-     * <p> This API will return false in scenarios like the A2DP
-     * device is not in suspended state etc. When this API returns,
-     * true, it is guaranteed that {@link #ACTION_SINK_STATE_CHANGED}
-     * intent will be broadcasted with the state. Users can get the
-     * state of the A2DP device from this intent.
-     *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-     *
-     * @param device Remote A2DP sink
-     * @return false on immediate error,
-     *               true otherwise
-     * @hide
-     */
-    public boolean resumeSink(BluetoothDevice device) {
-        if (mService != null && isEnabled()
-            && isValidDevice(device)) {
-            try {
-                return mService.resumeSink(device);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
-                return false;
-            }
-        }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
-        return false;
-    }
-
-    /**
      * This function checks if the remote device is an AVCRP
      * target and thus whether we should send volume keys
      * changes or not.
@@ -428,23 +422,6 @@
     }
 
     /**
-     * Allow or disallow incoming connection
-     * @param device Sink
-     * @param value True / False
-     * @return Success or Failure of the binder call.
-     * @hide
-     */
-    public boolean allowIncomingConnect(BluetoothDevice device, boolean value) {
-        if (DBG) log("allowIncomingConnect(" + device + ":" + value + ")");
-        try {
-            return mService.allowIncomingConnect(device, value);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-    }
-
-    /**
      * Helper for converting a state to a string.
      *
      * For debug use only - strings are not internationalized.
@@ -469,6 +446,24 @@
         }
     }
 
+    private ServiceConnection mConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            if (DBG) Log.d(TAG, "Proxy object connected");
+            mService = IBluetoothA2dp.Stub.asInterface(service);
+
+            if (mServiceListener != null) {
+                mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this);
+            }
+        }
+        public void onServiceDisconnected(ComponentName className) {
+            if (DBG) Log.d(TAG, "Proxy object disconnected");
+            mService = null;
+            if (mServiceListener != null) {
+                mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
+            }
+        }
+    };
+
     private boolean isEnabled() {
        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
        return false;
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
old mode 100644
new mode 100755
index 8e3df47..f817fb4
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -31,6 +31,7 @@
 import android.util.Pair;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
@@ -73,7 +74,8 @@
  */
 public final class BluetoothAdapter {
     private static final String TAG = "BluetoothAdapter";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
+    private static final boolean VDBG = false;
 
     /**
      * Sentinel error value for this class. Guaranteed to not equal any other
@@ -343,7 +345,7 @@
     public static final int STATE_DISCONNECTING = 3;
 
     /** @hide */
-    public static final String BLUETOOTH_SERVICE = "bluetooth";
+    public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
 
     private static final int ADDRESS_LENGTH = 17;
 
@@ -353,7 +355,8 @@
      */
     private static BluetoothAdapter sAdapter;
 
-    private final IBluetooth mService;
+    private final IBluetoothManager mManagerService;
+    private IBluetooth mService;
 
     private Handler mServiceRecordHandler;
 
@@ -367,10 +370,12 @@
      */
     public static synchronized BluetoothAdapter getDefaultAdapter() {
         if (sAdapter == null) {
-            IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
+            IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
             if (b != null) {
-                IBluetooth service = IBluetooth.Stub.asInterface(b);
-                sAdapter = new BluetoothAdapter(service);
+                IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
+                sAdapter = new BluetoothAdapter(managerService);
+            } else {
+                Log.e(TAG, "Bluetooth binder is null");
             }
         }
         return sAdapter;
@@ -378,13 +383,16 @@
 
     /**
      * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
-     * @hide
      */
-    public BluetoothAdapter(IBluetooth service) {
-        if (service == null) {
-            throw new IllegalArgumentException("service is null");
+    BluetoothAdapter(IBluetoothManager managerService) {
+
+        if (managerService == null) {
+            throw new IllegalArgumentException("bluetooth manager service is null");
         }
-        mService = service;
+        try {
+            mService = managerService.registerAdapter(mManagerCallback);
+        } catch (RemoteException e) {Log.e(TAG, "", e);}
+        mManagerService = managerService;
         mServiceRecordHandler = null;
     }
 
@@ -432,8 +440,11 @@
      * @return true if the local adapter is turned on
      */
     public boolean isEnabled() {
+
         try {
-            return mService.isEnabled();
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.isEnabled();
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -451,8 +462,18 @@
      */
     public int getState() {
         try {
-            return mService.getBluetoothState();
+            synchronized(mManagerCallback) {
+                if (mService != null)
+                {
+                    int state=  mService.getState();
+                    if (VDBG) Log.d(TAG, "" + hashCode() + ": getState(). Returning " + state);
+                    return state;
+                }
+                // TODO(BT) there might be a small gap during STATE_TURNING_ON that
+                //          mService is null, handle that case
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
+        if (DBG) Log.d(TAG, "" + hashCode() + ": getState() :  mService = null. Returning STATE_OFF");
         return STATE_OFF;
     }
 
@@ -484,8 +505,12 @@
      *         immediate error
      */
     public boolean enable() {
+        if (isEnabled() == true){
+            if (DBG) Log.d(TAG, "enable(): BT is already enabled..!");
+            return true;
+        }
         try {
-            return mService.enable();
+            return mManagerService.enable();
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -516,7 +541,25 @@
      */
     public boolean disable() {
         try {
-            return mService.disable(true);
+            return mManagerService.disable(true);
+        } catch (RemoteException e) {Log.e(TAG, "", e);}
+        return false;
+    }
+
+    /**
+     * Turn off the local Bluetooth adapter and don't persist the setting.
+     *
+     * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+     * permission
+     *
+     * @return true to indicate adapter shutdown has begun, or false on
+     *         immediate error
+     * @hide
+     */
+    public boolean disable(boolean persist) {
+
+        try {
+            return mManagerService.disable(persist);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -530,7 +573,7 @@
      */
     public String getAddress() {
         try {
-            return mService.getAddress();
+            return mManagerService.getAddress();
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return null;
     }
@@ -544,7 +587,7 @@
      */
     public String getName() {
         try {
-            return mService.getName();
+            return mManagerService.getName();
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return null;
     }
@@ -560,7 +603,9 @@
     public ParcelUuid[] getUuids() {
         if (getState() != STATE_ON) return null;
         try {
-            return mService.getUuids();
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.getUuids();
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return null;
     }
@@ -583,7 +628,9 @@
     public boolean setName(String name) {
         if (getState() != STATE_ON) return false;
         try {
-            return mService.setName(name);
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.setName(name);
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -607,7 +654,9 @@
     public int getScanMode() {
         if (getState() != STATE_ON) return SCAN_MODE_NONE;
         try {
-            return mService.getScanMode();
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.getScanMode();
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return SCAN_MODE_NONE;
     }
@@ -643,7 +692,9 @@
     public boolean setScanMode(int mode, int duration) {
         if (getState() != STATE_ON) return false;
         try {
-            return mService.setScanMode(mode, duration);
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.setScanMode(mode, duration);
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -651,14 +702,17 @@
     /** @hide */
     public boolean setScanMode(int mode) {
         if (getState() != STATE_ON) return false;
-        return setScanMode(mode, 120);
+        /* getDiscoverableTimeout() to use the latest from NV than use 0 */
+        return setScanMode(mode, getDiscoverableTimeout());
     }
 
     /** @hide */
     public int getDiscoverableTimeout() {
         if (getState() != STATE_ON) return -1;
         try {
-            return mService.getDiscoverableTimeout();
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.getDiscoverableTimeout();
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return -1;
     }
@@ -667,7 +721,9 @@
     public void setDiscoverableTimeout(int timeout) {
         if (getState() != STATE_ON) return;
         try {
-            mService.setDiscoverableTimeout(timeout);
+            synchronized(mManagerCallback) {
+                if (mService != null) mService.setDiscoverableTimeout(timeout);
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
     }
 
@@ -704,7 +760,9 @@
     public boolean startDiscovery() {
         if (getState() != STATE_ON) return false;
         try {
-            return mService.startDiscovery();
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.startDiscovery();
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -729,7 +787,9 @@
     public boolean cancelDiscovery() {
         if (getState() != STATE_ON) return false;
         try {
-            return mService.cancelDiscovery();
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.cancelDiscovery();
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -756,7 +816,9 @@
     public boolean isDiscovering() {
         if (getState() != STATE_ON) return false;
         try {
-            return mService.isDiscovering();
+            synchronized(mManagerCallback) {
+                if (mService != null ) return mService.isDiscovering();
+            }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -774,10 +836,13 @@
      */
     public Set<BluetoothDevice> getBondedDevices() {
         if (getState() != STATE_ON) {
-            return toDeviceSet(new String[0]);
+            return toDeviceSet(new BluetoothDevice[0]);
         }
         try {
-            return toDeviceSet(mService.listBonds());
+            synchronized(mManagerCallback) {
+                if (mService != null) return toDeviceSet(mService.getBondedDevices());
+            }
+            return toDeviceSet(new BluetoothDevice[0]);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return null;
     }
@@ -798,7 +863,9 @@
     public int getConnectionState() {
         if (getState() != STATE_ON) return BluetoothAdapter.STATE_DISCONNECTED;
         try {
-            return mService.getAdapterConnectionState();
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.getAdapterConnectionState();
+            }
         } catch (RemoteException e) {Log.e(TAG, "getConnectionState:", e);}
         return BluetoothAdapter.STATE_DISCONNECTED;
     }
@@ -821,7 +888,9 @@
     public int getProfileConnectionState(int profile) {
         if (getState() != STATE_ON) return BluetoothProfile.STATE_DISCONNECTED;
         try {
-            return mService.getProfileConnectionState(profile);
+            synchronized(mManagerCallback) {
+                if (mService != null) return mService.getProfileConnectionState(profile);
+            }
         } catch (RemoteException e) {
             Log.e(TAG, "getProfileConnectionState:", e);
         }
@@ -829,51 +898,6 @@
     }
 
     /**
-    /**
-     * Picks RFCOMM channels until none are left.
-     * Avoids reserved channels.
-     */
-    private static class RfcommChannelPicker {
-        private static final int[] RESERVED_RFCOMM_CHANNELS =  new int[] {
-            10,  // HFAG
-            11,  // HSAG
-            12,  // OPUSH
-            19,  // PBAP
-        };
-        private static LinkedList<Integer> sChannels;  // master list of non-reserved channels
-        private static Random sRandom;
-
-        private final LinkedList<Integer> mChannels;  // local list of channels left to try
-
-        private final UUID mUuid;
-
-        public RfcommChannelPicker(UUID uuid) {
-            synchronized (RfcommChannelPicker.class) {
-                if (sChannels == null) {
-                    // lazy initialization of non-reserved rfcomm channels
-                    sChannels = new LinkedList<Integer>();
-                    for (int i = 1; i <= BluetoothSocket.MAX_RFCOMM_CHANNEL; i++) {
-                        sChannels.addLast(new Integer(i));
-                    }
-                    for (int reserved : RESERVED_RFCOMM_CHANNELS) {
-                        sChannels.remove(new Integer(reserved));
-                    }
-                    sRandom = new Random();
-                }
-                mChannels = (LinkedList<Integer>)sChannels.clone();
-            }
-            mUuid = uuid;
-        }
-        /* Returns next random channel, or -1 if we're out */
-        public int nextChannel() {
-            if (mChannels.size() == 0) {
-                return -1;
-            }
-            return mChannels.remove(sRandom.nextInt(mChannels.size()));
-        }
-    }
-
-    /**
      * Create a listening, secure RFCOMM Bluetooth socket.
      * <p>A remote device connecting to this socket will be authenticated and
      * communication on this socket will be encrypted.
@@ -892,10 +916,10 @@
                 BluetoothSocket.TYPE_RFCOMM, true, true, channel);
         int errno = socket.mSocket.bindListen();
         if (errno != 0) {
-            try {
-                socket.close();
-            } catch (IOException e) {}
-            socket.mSocket.throwErrnoNative(errno);
+            //TODO(BT): Throw the same exception error code
+            // that the previous code was using.
+            //socket.mSocket.throwErrnoNative(errno);
+            throw new IOException("Error: " + errno);
         }
         return socket;
     }
@@ -996,70 +1020,23 @@
         return createNewRfcommSocketAndRecord(name, uuid, false, true);
     }
 
+
     private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
             boolean auth, boolean encrypt) throws IOException {
-        RfcommChannelPicker picker = new RfcommChannelPicker(uuid);
-
         BluetoothServerSocket socket;
-        int channel;
-        int errno;
-        while (true) {
-            channel = picker.nextChannel();
-
-            if (channel == -1) {
-                throw new IOException("No available channels");
-            }
-
-            socket = new BluetoothServerSocket(
-                    BluetoothSocket.TYPE_RFCOMM, auth, encrypt, channel);
-            errno = socket.mSocket.bindListen();
-            if (errno == 0) {
-                if (DBG) Log.d(TAG, "listening on RFCOMM channel " + channel);
-                break;  // success
-            } else if (errno == BluetoothSocket.EADDRINUSE) {
-                if (DBG) Log.d(TAG, "RFCOMM channel " + channel + " in use");
-                try {
-                    socket.close();
-                } catch (IOException e) {}
-                continue;  // try another channel
-            } else {
-                try {
-                    socket.close();
-                } catch (IOException e) {}
-                socket.mSocket.throwErrnoNative(errno);  // Exception as a result of bindListen()
-            }
+        socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth,
+                        encrypt, new ParcelUuid(uuid));
+        socket.setServiceName(name);
+        int errno = socket.mSocket.bindListen();
+        if (errno != 0) {
+            //TODO(BT): Throw the same exception error code
+            // that the previous code was using.
+            //socket.mSocket.throwErrnoNative(errno);
+            throw new IOException("Error: " + errno);
         }
-
-        int handle = -1;
-        try {
-            handle = mService.addRfcommServiceRecord(name, new ParcelUuid(uuid), channel,
-                    new Binder());
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
-        if (handle == -1) {
-            try {
-                socket.close();
-            } catch (IOException e) {}
-            throw new IOException("Not able to register SDP record for " + name);
-        }
-
-        if (mServiceRecordHandler == null) {
-            mServiceRecordHandler = new Handler(Looper.getMainLooper()) {
-                    public void handleMessage(Message msg) {
-                        /* handle socket closing */
-                        int handle = msg.what;
-                        try {
-                            if (DBG) Log.d(TAG, "Removing service record " +
-                                           Integer.toHexString(handle));
-                            mService.removeServiceRecord(handle);
-                        } catch (RemoteException e) {Log.e(TAG, "", e);}
-                    }
-                };
-        }
-        socket.setCloseHandler(mServiceRecordHandler, handle);
         return socket;
     }
 
-
     /**
      * Construct an unencrypted, unauthenticated, RFCOMM server socket.
      * Call #accept to retrieve connections to this socket.
@@ -1073,10 +1050,10 @@
                 BluetoothSocket.TYPE_RFCOMM, false, false, port);
         int errno = socket.mSocket.bindListen();
         if (errno != 0) {
-            try {
-                socket.close();
-            } catch (IOException e) {}
-            socket.mSocket.throwErrnoNative(errno);
+            //TODO(BT): Throw the same exception error code
+            // that the previous code was using.
+            //socket.mSocket.throwErrnoNative(errno);
+            throw new IOException("Error: " + errno);
         }
         return socket;
     }
@@ -1094,11 +1071,11 @@
         BluetoothServerSocket socket = new BluetoothServerSocket(
                 BluetoothSocket.TYPE_RFCOMM, false, true, port);
         int errno = socket.mSocket.bindListen();
-        if (errno != 0) {
-            try {
-                socket.close();
-            } catch (IOException e) {}
-            socket.mSocket.throwErrnoNative(errno);
+        if (errno < 0) {
+            //TODO(BT): Throw the same exception error code
+            // that the previous code was using.
+            //socket.mSocket.throwErrnoNative(errno);
+            throw new IOException("Error: " + errno);
         }
         return socket;
     }
@@ -1115,11 +1092,10 @@
         BluetoothServerSocket socket = new BluetoothServerSocket(
                 BluetoothSocket.TYPE_SCO, false, false, -1);
         int errno = socket.mSocket.bindListen();
-        if (errno != 0) {
-            try {
-                socket.close();
-            } catch (IOException e) {}
-            socket.mSocket.throwErrnoNative(errno);
+        if (errno < 0) {
+            //TODO(BT): Throw the same exception error code
+            // that the previous code was using.
+            //socket.mSocket.throwErrnoNative(errno);
         }
         return socket;
     }
@@ -1134,6 +1110,8 @@
      */
     public Pair<byte[], byte[]> readOutOfBandData() {
         if (getState() != STATE_ON) return null;
+        //TODO(BT
+        /*
         try {
             byte[] hash;
             byte[] randomizer;
@@ -1151,7 +1129,7 @@
             }
             return new Pair<byte[], byte[]>(hash, randomizer);
 
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+        } catch (RemoteException e) {Log.e(TAG, "", e);}*/
         return null;
     }
 
@@ -1231,14 +1209,53 @@
         }
     }
 
+    final private IBluetoothManagerCallback mManagerCallback =
+        new IBluetoothManagerCallback.Stub() {
+            public void onBluetoothServiceUp(IBluetooth bluetoothService) {
+                if (DBG) Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
+                synchronized (mManagerCallback) {
+                    mService = bluetoothService;
+                    for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
+                        try {
+                            if (cb != null) {
+                                cb.onBluetoothServiceUp(bluetoothService);
+                            } else {
+                                Log.d(TAG, "onBluetoothServiceUp: cb is null!!!");
+                            }
+                        } catch (Exception e)  { Log.e(TAG,"",e);}
+                    }
+                }
+            }
+
+            public void onBluetoothServiceDown() {
+                if (DBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
+                synchronized (mManagerCallback) {
+                    mService = null;
+                    for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
+                        try {
+                            if (cb != null) {
+                                cb.onBluetoothServiceDown();
+                            } else {
+                                Log.d(TAG, "onBluetoothServiceDown: cb is null!!!");
+                            }
+                        } catch (Exception e)  { Log.e(TAG,"",e);}
+                    }
+                }
+            }
+    };
+
     /**
      * Enable the Bluetooth Adapter, but don't auto-connect devices
      * and don't persist state. Only for use by system applications.
      * @hide
      */
     public boolean enableNoAutoConnect() {
+        if (isEnabled() == true){
+            if (DBG) Log.d(TAG, "enableNoAutoConnect(): BT is already enabled..!");
+            return true;
+        }
         try {
-            return mService.enableNoAutoConnect();
+            return mManagerService.enableNoAutoConnect();
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -1276,12 +1293,14 @@
                                                    BluetoothStateChangeCallback callback) {
         if (callback == null) return false;
 
+        //TODO(BT)
+        /*
         try {
             return mService.changeApplicationBluetoothState(on, new
                     StateChangeCallbackWrapper(callback), new Binder());
         } catch (RemoteException e) {
             Log.e(TAG, "changeBluetoothState", e);
-        }
+        }*/
         return false;
     }
 
@@ -1309,14 +1328,22 @@
         }
     }
 
-    private Set<BluetoothDevice> toDeviceSet(String[] addresses) {
-        Set<BluetoothDevice> devices = new HashSet<BluetoothDevice>(addresses.length);
-        for (int i = 0; i < addresses.length; i++) {
-            devices.add(getRemoteDevice(addresses[i]));
-        }
-        return Collections.unmodifiableSet(devices);
+    private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) {
+        Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices));
+        return Collections.unmodifiableSet(deviceSet);
     }
 
+    protected void finalize() throws Throwable {
+        try {
+            mManagerService.unregisterAdapter(mManagerCallback);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        } finally {
+            super.finalize();
+        }
+    }
+
+
     /**
      * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"
      * <p>Alphabetic characters must be uppercase to be valid.
@@ -1347,4 +1374,27 @@
         }
         return true;
     }
+
+    /*package*/ IBluetoothManager getBluetoothManager() {
+            return mManagerService;
+    }
+
+    private ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks = new ArrayList<IBluetoothManagerCallback>();
+
+    /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
+        synchronized (mManagerCallback) {
+            if (cb == null) {
+                Log.w(TAG, "getBluetoothService() called with no BluetoothManagerCallback");
+            } else if (!mProxyServiceStateCallbacks.contains(cb)) {
+                mProxyServiceStateCallbacks.add(cb);
+            }
+        }
+        return mService;
+    }
+
+    /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) {
+        synchronized (mManagerCallback) {
+            mProxyServiceStateCallbacks.remove(cb);
+        }
+    }
 }
diff --git a/core/java/android/bluetooth/BluetoothAudioGateway.java b/core/java/android/bluetooth/BluetoothAudioGateway.java
deleted file mode 100644
index 9351393..0000000
--- a/core/java/android/bluetooth/BluetoothAudioGateway.java
+++ /dev/null
@@ -1,202 +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.
- */
-
-package android.bluetooth;
-
-import java.lang.Thread;
-
-import android.os.Message;
-import android.os.Handler;
-import android.util.Log;
-
-/**
- * Listens for incoming RFCOMM connection for the headset / handsfree service.
- *
- * TODO: Use the new generic BluetoothSocket class instead of this legacy code
- *
- * @hide
- */
-public final class BluetoothAudioGateway {
-    private static final String TAG = "BT Audio Gateway";
-    private static final boolean DBG = false;
-
-    private int mNativeData;
-    static { classInitNative(); }
-
-    /* in */
-    private int mHandsfreeAgRfcommChannel = -1;
-    private int mHeadsetAgRfcommChannel   = -1;
-
-    /* out - written by native code */
-    private String mConnectingHeadsetAddress;
-    private int mConnectingHeadsetRfcommChannel; /* -1 when not connected */
-    private int mConnectingHeadsetSocketFd;
-    private String mConnectingHandsfreeAddress;
-    private int mConnectingHandsfreeRfcommChannel; /* -1 when not connected */
-    private int mConnectingHandsfreeSocketFd;
-    private int mTimeoutRemainingMs; /* in/out */
-
-    private final BluetoothAdapter mAdapter;
-
-    public static final int DEFAULT_HF_AG_CHANNEL = 10;
-    public static final int DEFAULT_HS_AG_CHANNEL = 11;
-
-    public BluetoothAudioGateway(BluetoothAdapter adapter) {
-        this(adapter, DEFAULT_HF_AG_CHANNEL, DEFAULT_HS_AG_CHANNEL);
-    }
-
-    public BluetoothAudioGateway(BluetoothAdapter adapter, int handsfreeAgRfcommChannel,
-                int headsetAgRfcommChannel) {
-        mAdapter = adapter;
-        mHandsfreeAgRfcommChannel = handsfreeAgRfcommChannel;
-        mHeadsetAgRfcommChannel = headsetAgRfcommChannel;
-        initializeNativeDataNative();
-    }
-
-    private Thread mConnectThead;
-    private volatile boolean mInterrupted;
-    private static final int SELECT_WAIT_TIMEOUT = 1000;
-
-    private Handler mCallback;
-
-    public class IncomingConnectionInfo {
-        public BluetoothAdapter mAdapter;
-        public BluetoothDevice mRemoteDevice;
-        public int mSocketFd;
-        public int mRfcommChan;
-        IncomingConnectionInfo(BluetoothAdapter adapter, BluetoothDevice remoteDevice,
-                int socketFd, int rfcommChan) {
-            mAdapter = adapter;
-            mRemoteDevice = remoteDevice;
-            mSocketFd = socketFd;
-            mRfcommChan = rfcommChan;
-        }
-    }
-
-    public static final int MSG_INCOMING_HEADSET_CONNECTION   = 100;
-    public static final int MSG_INCOMING_HANDSFREE_CONNECTION = 101;
-
-    public synchronized boolean start(Handler callback) {
-
-        if (mConnectThead == null) {
-            mCallback = callback;
-            mConnectThead = new Thread(TAG) {
-                    public void run() {
-                        if (DBG) log("Connect Thread starting");
-                        while (!mInterrupted) {
-                            //Log.i(TAG, "waiting for connect");
-                            mConnectingHeadsetRfcommChannel = -1;
-                            mConnectingHandsfreeRfcommChannel = -1;
-                            if (waitForHandsfreeConnectNative(SELECT_WAIT_TIMEOUT) == false) {
-                                if (mTimeoutRemainingMs > 0) {
-                                    try {
-                                        Log.i(TAG, "select thread timed out, but " + 
-                                              mTimeoutRemainingMs + "ms of waiting remain.");
-                                        Thread.sleep(mTimeoutRemainingMs);
-                                    } catch (InterruptedException e) {
-                                        Log.i(TAG, "select thread was interrupted (2), exiting");
-                                        mInterrupted = true;
-                                    }
-                                }
-                            }
-                            else {
-                                Log.i(TAG, "connect notification!");
-                                /* A device connected (most likely just one, but 
-                                   it is possible for two separate devices, one 
-                                   a headset and one a handsfree, to connect
-                                   simultaneously. 
-                                */
-                                if (mConnectingHeadsetRfcommChannel >= 0) {
-                                    Log.i(TAG, "Incoming connection from headset " + 
-                                          mConnectingHeadsetAddress + " on channel " + 
-                                          mConnectingHeadsetRfcommChannel);
-                                    Message msg = Message.obtain(mCallback);
-                                    msg.what = MSG_INCOMING_HEADSET_CONNECTION;
-                                    msg.obj = new IncomingConnectionInfo(
-                                        mAdapter,
-                                        mAdapter.getRemoteDevice(mConnectingHeadsetAddress),
-                                        mConnectingHeadsetSocketFd,
-                                        mConnectingHeadsetRfcommChannel);
-                                    msg.sendToTarget();
-                                }
-                                if (mConnectingHandsfreeRfcommChannel >= 0) {
-                                    Log.i(TAG, "Incoming connection from handsfree " + 
-                                          mConnectingHandsfreeAddress + " on channel " + 
-                                          mConnectingHandsfreeRfcommChannel);
-                                    Message msg = Message.obtain();
-                                    msg.setTarget(mCallback);
-                                    msg.what = MSG_INCOMING_HANDSFREE_CONNECTION;
-                                    msg.obj = new IncomingConnectionInfo(
-                                        mAdapter,
-                                        mAdapter.getRemoteDevice(mConnectingHandsfreeAddress),
-                                        mConnectingHandsfreeSocketFd,
-                                        mConnectingHandsfreeRfcommChannel);
-                                    msg.sendToTarget();
-                                }
-                            }
-                        }
-                        if (DBG) log("Connect Thread finished");
-                    }
-                };
-
-            if (setUpListeningSocketsNative() == false) {
-                Log.e(TAG, "Could not set up listening socket, exiting");
-                return false;
-            }
-
-            mInterrupted = false;
-            mConnectThead.start();
-        }
-
-        return true;
-    }
-
-    public synchronized void stop() {
-        if (mConnectThead != null) {
-            if (DBG) log("stopping Connect Thread");
-            mInterrupted = true;
-            try {
-                mConnectThead.interrupt();
-                if (DBG) log("waiting for thread to terminate");
-                mConnectThead.join();
-                mConnectThead = null;
-                mCallback = null;
-                tearDownListeningSocketsNative();
-            } catch (InterruptedException e) {
-                Log.w(TAG, "Interrupted waiting for Connect Thread to join");
-            }
-        }
-    }
-
-    protected void finalize() throws Throwable {
-        try {
-            cleanupNativeDataNative();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    private static native void classInitNative();
-    private native void initializeNativeDataNative();
-    private native void cleanupNativeDataNative();
-    private native boolean waitForHandsfreeConnectNative(int timeoutMs);
-    private native boolean setUpListeningSocketsNative();
-    private native void tearDownListeningSocketsNative();
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
old mode 100644
new mode 100755
index 56e1735..4cc22b4
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -65,6 +65,7 @@
  */
 public final class BluetoothDevice implements Parcelable {
     private static final String TAG = "BluetoothDevice";
+    private static final boolean DBG = false;
 
     /**
      * Sentinel error value for this class. Guaranteed to not equal any other
@@ -483,16 +484,29 @@
     /*package*/ static IBluetooth getService() {
         synchronized (BluetoothDevice.class) {
             if (sService == null) {
-                IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
-                if (b == null) {
-                    throw new RuntimeException("Bluetooth service not available");
-                }
-                sService = IBluetooth.Stub.asInterface(b);
+                BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+                sService = adapter.getBluetoothService(mStateChangeCallback);
             }
         }
         return sService;
     }
 
+    static IBluetoothManagerCallback mStateChangeCallback = new IBluetoothManagerCallback.Stub() {
+
+        public void onBluetoothServiceUp(IBluetooth bluetoothService)
+                throws RemoteException {
+            synchronized (BluetoothDevice.class) {
+                sService = bluetoothService;
+            }
+        }
+
+        public void onBluetoothServiceDown()
+            throws RemoteException {
+            synchronized (BluetoothDevice.class) {
+                sService = null;
+            }
+        }
+    };
     /**
      * Create a new BluetoothDevice
      * Bluetooth MAC address must be upper case, such as "00:11:22:33:AA:BB",
@@ -561,6 +575,7 @@
      * @return Bluetooth hardware address as string
      */
     public String getAddress() {
+        if (DBG) Log.d(TAG, "mAddress: " + mAddress);
         return mAddress;
     }
 
@@ -575,8 +590,12 @@
      * @return the Bluetooth name, or null if there was a problem.
      */
     public String getName() {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot get Remote Device name");
+            return null;
+        }
         try {
-            return sService.getRemoteName(mAddress);
+            return sService.getRemoteName(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return null;
     }
@@ -589,8 +608,12 @@
      * @hide
      */
     public String getAlias() {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot get Remote Device Alias");
+            return null;
+        }
         try {
-            return sService.getRemoteAlias(mAddress);
+            return sService.getRemoteAlias(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return null;
     }
@@ -606,8 +629,12 @@
      * @hide
      */
     public boolean setAlias(String alias) {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot set Remote Device name");
+            return false;
+        }
         try {
-            return sService.setRemoteAlias(mAddress, alias);
+            return sService.setRemoteAlias(this, alias);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -642,8 +669,12 @@
      * @hide
      */
     public boolean createBond() {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
+            return false;
+        }
         try {
-            return sService.createBond(mAddress);
+            return sService.createBond(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -668,9 +699,11 @@
      * @hide
      */
     public boolean createBondOutOfBand(byte[] hash, byte[] randomizer) {
+        //TODO(BT)
+        /*
         try {
-            return sService.createBondOutOfBand(mAddress, hash, randomizer);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return sService.createBondOutOfBand(this, hash, randomizer);
+        } catch (RemoteException e) {Log.e(TAG, "", e);}*/
         return false;
     }
 
@@ -688,9 +721,11 @@
      * @hide
      */
     public boolean setDeviceOutOfBandData(byte[] hash, byte[] randomizer) {
+      //TODO(BT)
+      /*
       try {
-        return sService.setDeviceOutOfBandData(mAddress, hash, randomizer);
-      } catch (RemoteException e) {Log.e(TAG, "", e);}
+        return sService.setDeviceOutOfBandData(this, hash, randomizer);
+      } catch (RemoteException e) {Log.e(TAG, "", e);} */
       return false;
     }
 
@@ -702,8 +737,12 @@
      * @hide
      */
     public boolean cancelBondProcess() {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot cancel Remote Device bond");
+            return false;
+        }
         try {
-            return sService.cancelBondProcess(mAddress);
+            return sService.cancelBondProcess(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -719,8 +758,12 @@
      * @hide
      */
     public boolean removeBond() {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot remove Remote Device bond");
+            return false;
+        }
         try {
-            return sService.removeBond(mAddress);
+            return sService.removeBond(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -736,9 +779,19 @@
      * @return the bond state
      */
     public int getBondState() {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot get bond state");
+            return BOND_NONE;
+        }
         try {
-            return sService.getBondState(mAddress);
+            return sService.getBondState(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
+        catch (NullPointerException npe) {
+            // Handle case where bluetooth service proxy
+            // is already null.
+            Log.e(TAG, "NullPointerException for getBondState() of device ("+
+                getAddress()+")", npe);
+        }
         return BOND_NONE;
     }
 
@@ -749,8 +802,12 @@
      * @return Bluetooth class object, or null on error
      */
     public BluetoothClass getBluetoothClass() {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot get Bluetooth Class");
+            return null;
+        }
         try {
-            int classInt = sService.getRemoteClass(mAddress);
+            int classInt = sService.getRemoteClass(this);
             if (classInt == BluetoothClass.ERROR) return null;
             return new BluetoothClass(classInt);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
@@ -763,11 +820,13 @@
      * @hide
      */
     public boolean getTrustState() {
+        //TODO(BT)
+        /*
         try {
-            return sService.getTrustState(mAddress);
+            return sService.getTrustState(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
-        }
+        }*/
         return false;
     }
 
@@ -778,11 +837,13 @@
      * @hide
      */
     public boolean setTrust(boolean value) {
+        //TODO(BT)
+        /*
         try {
-            return sService.setTrust(mAddress, value);
+            return sService.setTrust(this, value);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
-        }
+        }*/
         return false;
     }
 
@@ -799,8 +860,12 @@
      *         or null on error
      */
      public ParcelUuid[] getUuids() {
+         if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot get remote device Uuids");
+             return null;
+         }
         try {
-            return sService.getRemoteUuids(mAddress);
+            return sService.getRemoteUuids(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return null;
     }
@@ -822,64 +887,84 @@
       */
      public boolean fetchUuidsWithSdp() {
         try {
-            return sService.fetchRemoteUuids(mAddress, null, null);
+            return sService.fetchRemoteUuids(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
-        return false;
+            return false;
     }
 
     /** @hide */
     public int getServiceChannel(ParcelUuid uuid) {
+        //TODO(BT)
+        /*
          try {
-             return sService.getRemoteServiceChannel(mAddress, uuid);
-         } catch (RemoteException e) {Log.e(TAG, "", e);}
+             return sService.getRemoteServiceChannel(this, uuid);
+         } catch (RemoteException e) {Log.e(TAG, "", e);}*/
          return BluetoothDevice.ERROR;
     }
 
     /** @hide */
     public boolean setPin(byte[] pin) {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot set Remote Device pin");
+            return false;
+        }
         try {
-            return sService.setPin(mAddress, pin);
+            return sService.setPin(this, true, pin.length, pin);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
 
     /** @hide */
     public boolean setPasskey(int passkey) {
+        //TODO(BT)
+        /*
         try {
-            return sService.setPasskey(mAddress, passkey);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return sService.setPasskey(this, true, 4, passkey);
+        } catch (RemoteException e) {Log.e(TAG, "", e);}*/
         return false;
     }
 
     /** @hide */
     public boolean setPairingConfirmation(boolean confirm) {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot set pairing confirmation");
+            return false;
+        }
         try {
-            return sService.setPairingConfirmation(mAddress, confirm);
+            return sService.setPairingConfirmation(this, confirm);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
 
     /** @hide */
     public boolean setRemoteOutOfBandData() {
+        // TODO(BT)
+        /*
         try {
-          return sService.setRemoteOutOfBandData(mAddress);
-      } catch (RemoteException e) {Log.e(TAG, "", e);}
+          return sService.setRemoteOutOfBandData(this);
+      } catch (RemoteException e) {Log.e(TAG, "", e);}*/
       return false;
     }
 
     /** @hide */
     public boolean cancelPairingUserInput() {
+        if (sService == null) {
+            Log.e(TAG, "BT not enabled. Cannot create pairing user input");
+            return false;
+        }
         try {
-            return sService.cancelPairingUserInput(mAddress);
+            return sService.cancelBondProcess(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
 
     /** @hide */
     public boolean isBluetoothDock() {
+        // TODO(BT)
+        /*
         try {
-            return sService.isBluetoothDock(mAddress);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return sService.isBluetoothDock(this);
+        } catch (RemoteException e) {Log.e(TAG, "", e);}*/
         return false;
     }
 
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
deleted file mode 100644
index 020f051..0000000
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ /dev/null
@@ -1,1357 +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.
- */
-
-package android.bluetooth;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Message;
-import android.bluetooth.BluetoothAdapter;
-import android.os.PowerManager;
-import android.server.BluetoothA2dpService;
-import android.server.BluetoothService;
-import android.util.Log;
-import android.util.Pair;
-
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-
-import java.util.Set;
-
-/**
- * This class is the Profile connection state machine associated with a remote
- * device. When the device bonds an instance of this class is created.
- * This tracks incoming and outgoing connections of all the profiles. Incoming
- * connections are preferred over outgoing connections and HFP preferred over
- * A2DP. When the device is unbonded, the instance is removed.
- *
- * States:
- * {@link BondedDevice}: This state represents a bonded device. When in this
- * state none of the profiles are in transition states.
- *
- * {@link OutgoingHandsfree}: Handsfree profile connection is in a transition
- * state because of a outgoing Connect or Disconnect.
- *
- * {@link IncomingHandsfree}: Handsfree profile connection is in a transition
- * state because of a incoming Connect or Disconnect.
- *
- * {@link IncomingA2dp}: A2dp profile connection is in a transition
- * state because of a incoming Connect or Disconnect.
- *
- * {@link OutgoingA2dp}: A2dp profile connection is in a transition
- * state because of a outgoing Connect or Disconnect.
- *
- * Todo(): Write tests for this class, when the Android Mock support is completed.
- * @hide
- */
-public final class BluetoothDeviceProfileState extends StateMachine {
-    private static final String TAG = "BluetoothDeviceProfileState";
-    private static final boolean DBG = false;
-
-    // TODO(): Restructure the state machine to make it scalable with regard to profiles.
-    public static final int CONNECT_HFP_OUTGOING = 1;
-    public static final int CONNECT_HFP_INCOMING = 2;
-    public static final int CONNECT_A2DP_OUTGOING = 3;
-    public static final int CONNECT_A2DP_INCOMING = 4;
-    public static final int CONNECT_HID_OUTGOING = 5;
-    public static final int CONNECT_HID_INCOMING = 6;
-
-    public static final int DISCONNECT_HFP_OUTGOING = 50;
-    private static final int DISCONNECT_HFP_INCOMING = 51;
-    public static final int DISCONNECT_A2DP_OUTGOING = 52;
-    public static final int DISCONNECT_A2DP_INCOMING = 53;
-    public static final int DISCONNECT_HID_OUTGOING = 54;
-    public static final int DISCONNECT_HID_INCOMING = 55;
-    public static final int DISCONNECT_PBAP_OUTGOING = 56;
-
-    public static final int UNPAIR = 100;
-    public static final int AUTO_CONNECT_PROFILES = 101;
-    public static final int TRANSITION_TO_STABLE = 102;
-    public static final int CONNECT_OTHER_PROFILES = 103;
-    private static final int CONNECTION_ACCESS_REQUEST_REPLY = 104;
-    private static final int CONNECTION_ACCESS_REQUEST_EXPIRY = 105;
-
-    public static final int CONNECT_OTHER_PROFILES_DELAY = 4000; // 4 secs
-    private static final int CONNECTION_ACCESS_REQUEST_EXPIRY_TIMEOUT = 7000; // 7 secs
-    private static final int CONNECTION_ACCESS_UNDEFINED = -1;
-    private static final long INIT_INCOMING_REJECT_TIMER = 1000; // 1 sec
-    private static final long MAX_INCOMING_REJECT_TIMER = 3600 * 1000 * 4; // 4 hours
-
-    private static final String ACCESS_AUTHORITY_PACKAGE = "com.android.settings";
-    private static final String ACCESS_AUTHORITY_CLASS =
-        "com.android.settings.bluetooth.BluetoothPermissionRequest";
-
-    private BondedDevice mBondedDevice = new BondedDevice();
-    private OutgoingHandsfree mOutgoingHandsfree = new OutgoingHandsfree();
-    private IncomingHandsfree mIncomingHandsfree = new IncomingHandsfree();
-    private IncomingA2dp mIncomingA2dp = new IncomingA2dp();
-    private OutgoingA2dp mOutgoingA2dp = new OutgoingA2dp();
-    private OutgoingHid mOutgoingHid = new OutgoingHid();
-    private IncomingHid mIncomingHid = new IncomingHid();
-
-    private Context mContext;
-    private BluetoothService mService;
-    private BluetoothA2dpService mA2dpService;
-    private BluetoothHeadset  mHeadsetService;
-    private BluetoothPbap     mPbapService;
-    private PbapServiceListener mPbap;
-    private BluetoothAdapter mAdapter;
-    private boolean mPbapServiceConnected;
-    private boolean mAutoConnectionPending;
-    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
-
-    private BluetoothDevice mDevice;
-    private int mHeadsetState = BluetoothProfile.STATE_DISCONNECTED;
-    private int mA2dpState = BluetoothProfile.STATE_DISCONNECTED;
-    private long mIncomingRejectTimer;
-    private boolean mConnectionAccessReplyReceived = false;
-    private Pair<Integer, String> mIncomingConnections;
-    private PowerManager.WakeLock mWakeLock;
-    private PowerManager mPowerManager;
-    private boolean mPairingRequestRcvd = false;
-
-    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-            if (device == null || !device.equals(mDevice)) return;
-
-            if (action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) {
-                int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
-                int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
-                // We trust this device now
-                if (newState == BluetoothHeadset.STATE_CONNECTED) {
-                    setTrust(BluetoothDevice.CONNECTION_ACCESS_YES);
-                }
-                mA2dpState = newState;
-                if (oldState == BluetoothA2dp.STATE_CONNECTED &&
-                    newState == BluetoothA2dp.STATE_DISCONNECTED) {
-                    sendMessage(DISCONNECT_A2DP_INCOMING);
-                }
-                if (newState == BluetoothProfile.STATE_CONNECTED ||
-                    newState == BluetoothProfile.STATE_DISCONNECTED) {
-                    sendMessage(TRANSITION_TO_STABLE);
-                }
-            } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
-                int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
-                int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
-                // We trust this device now
-                if (newState == BluetoothHeadset.STATE_CONNECTED) {
-                    setTrust(BluetoothDevice.CONNECTION_ACCESS_YES);
-                }
-                mHeadsetState = newState;
-                if (oldState == BluetoothHeadset.STATE_CONNECTED &&
-                    newState == BluetoothHeadset.STATE_DISCONNECTED) {
-                    sendMessage(DISCONNECT_HFP_INCOMING);
-                }
-                if (newState == BluetoothProfile.STATE_CONNECTED ||
-                    newState == BluetoothProfile.STATE_DISCONNECTED) {
-                    sendMessage(TRANSITION_TO_STABLE);
-                }
-            } else if (action.equals(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED)) {
-                int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
-                int oldState =
-                    intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
-                // We trust this device now
-                if (newState == BluetoothHeadset.STATE_CONNECTED) {
-                    setTrust(BluetoothDevice.CONNECTION_ACCESS_YES);
-                }
-                if (oldState == BluetoothProfile.STATE_CONNECTED &&
-                    newState == BluetoothProfile.STATE_DISCONNECTED) {
-                    sendMessage(DISCONNECT_HID_INCOMING);
-                }
-                if (newState == BluetoothProfile.STATE_CONNECTED ||
-                    newState == BluetoothProfile.STATE_DISCONNECTED) {
-                    sendMessage(TRANSITION_TO_STABLE);
-                }
-            } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
-                // This is technically not needed, but we can get stuck sometimes.
-                // For example, if incoming A2DP fails, we are not informed by Bluez
-                sendMessage(TRANSITION_TO_STABLE);
-            } else if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY)) {
-                mWakeLock.release();
-                int val = intent.getIntExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT,
-                                             BluetoothDevice.CONNECTION_ACCESS_NO);
-                Message msg = obtainMessage(CONNECTION_ACCESS_REQUEST_REPLY);
-                msg.arg1 = val;
-                sendMessage(msg);
-            } else if (action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) {
-                mPairingRequestRcvd = true;
-            } else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
-                int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
-                        BluetoothDevice.ERROR);
-                if (state == BluetoothDevice.BOND_BONDED && mPairingRequestRcvd) {
-                    setTrust(BluetoothDevice.CONNECTION_ACCESS_YES);
-                    mPairingRequestRcvd = false;
-                } else if (state == BluetoothDevice.BOND_NONE) {
-                    mPairingRequestRcvd = false;
-                }
-            }
-        }
-    };
-
-    private boolean isPhoneDocked(BluetoothDevice autoConnectDevice) {
-        // This works only because these broadcast intents are "sticky"
-        Intent i = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
-        if (i != null) {
-            int state = i.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED);
-            if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
-                BluetoothDevice device = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-                if (device != null && autoConnectDevice.equals(device)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    public BluetoothDeviceProfileState(Context context, String address,
-          BluetoothService service, BluetoothA2dpService a2dpService, boolean setTrust) {
-        super(address);
-        mContext = context;
-        mDevice = new BluetoothDevice(address);
-        mService = service;
-        mA2dpService = a2dpService;
-
-        addState(mBondedDevice);
-        addState(mOutgoingHandsfree);
-        addState(mIncomingHandsfree);
-        addState(mIncomingA2dp);
-        addState(mOutgoingA2dp);
-        addState(mOutgoingHid);
-        addState(mIncomingHid);
-        setInitialState(mBondedDevice);
-
-        IntentFilter filter = new IntentFilter();
-        // Fine-grained state broadcasts
-        filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
-        filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
-        filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
-        filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
-
-        mContext.registerReceiver(mBroadcastReceiver, filter);
-
-        mAdapter = BluetoothAdapter.getDefaultAdapter();
-        mAdapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
-                                BluetoothProfile.HEADSET);
-        // TODO(): Convert PBAP to the new Profile APIs.
-        mPbap = new PbapServiceListener();
-
-        mIncomingConnections = mService.getIncomingState(address);
-        mIncomingRejectTimer = readTimerValue();
-        mPowerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK |
-                                              PowerManager.ACQUIRE_CAUSES_WAKEUP |
-                                              PowerManager.ON_AFTER_RELEASE, TAG);
-        mWakeLock.setReferenceCounted(false);
-
-        if (setTrust) {
-            setTrust(BluetoothDevice.CONNECTION_ACCESS_YES);
-        }
-    }
-
-    private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
-        new BluetoothProfile.ServiceListener() {
-        public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            synchronized(BluetoothDeviceProfileState.this) {
-                mHeadsetService = (BluetoothHeadset) proxy;
-                if (mAutoConnectionPending) {
-                    sendMessage(AUTO_CONNECT_PROFILES);
-                    mAutoConnectionPending = false;
-                }
-            }
-        }
-        public void onServiceDisconnected(int profile) {
-            synchronized(BluetoothDeviceProfileState.this) {
-                mHeadsetService = null;
-            }
-        }
-    };
-
-    private class PbapServiceListener implements BluetoothPbap.ServiceListener {
-        public PbapServiceListener() {
-            mPbapService = new BluetoothPbap(mContext, this);
-        }
-        public void onServiceConnected() {
-            synchronized(BluetoothDeviceProfileState.this) {
-                mPbapServiceConnected = true;
-            }
-        }
-        public void onServiceDisconnected() {
-            synchronized(BluetoothDeviceProfileState.this) {
-                mPbapServiceConnected = false;
-            }
-        }
-    }
-
-    @Override
-    protected void onQuitting() {
-        mContext.unregisterReceiver(mBroadcastReceiver);
-        mBroadcastReceiver = null;
-        mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mHeadsetService);
-        mBluetoothProfileServiceListener = null;
-        mOutgoingHandsfree = null;
-        mPbap = null;
-        mPbapService.close();
-        mPbapService = null;
-        mIncomingHid = null;
-        mOutgoingHid = null;
-        mIncomingHandsfree = null;
-        mOutgoingHandsfree = null;
-        mIncomingA2dp = null;
-        mOutgoingA2dp = null;
-        mBondedDevice = null;
-    }
-
-    private class BondedDevice extends State {
-        @Override
-        public void enter() {
-            Log.i(TAG, "Entering ACL Connected state with: " + getCurrentMessage().what);
-            Message m = new Message();
-            m.copyFrom(getCurrentMessage());
-            sendMessageAtFrontOfQueue(m);
-        }
-        @Override
-        public boolean processMessage(Message message) {
-            log("ACL Connected State -> Processing Message: " + message.what);
-            switch(message.what) {
-                case CONNECT_HFP_OUTGOING:
-                case DISCONNECT_HFP_OUTGOING:
-                    transitionTo(mOutgoingHandsfree);
-                    break;
-                case CONNECT_HFP_INCOMING:
-                    transitionTo(mIncomingHandsfree);
-                    break;
-                case DISCONNECT_HFP_INCOMING:
-                    transitionTo(mIncomingHandsfree);
-                    break;
-                case CONNECT_A2DP_OUTGOING:
-                case DISCONNECT_A2DP_OUTGOING:
-                    transitionTo(mOutgoingA2dp);
-                    break;
-                case CONNECT_A2DP_INCOMING:
-                case DISCONNECT_A2DP_INCOMING:
-                    transitionTo(mIncomingA2dp);
-                    break;
-                case CONNECT_HID_OUTGOING:
-                case DISCONNECT_HID_OUTGOING:
-                    transitionTo(mOutgoingHid);
-                    break;
-                case CONNECT_HID_INCOMING:
-                case DISCONNECT_HID_INCOMING:
-                    transitionTo(mIncomingHid);
-                    break;
-                case DISCONNECT_PBAP_OUTGOING:
-                    processCommand(DISCONNECT_PBAP_OUTGOING);
-                    break;
-                case UNPAIR:
-                    if (mHeadsetState != BluetoothHeadset.STATE_DISCONNECTED) {
-                        sendMessage(DISCONNECT_HFP_OUTGOING);
-                        deferMessage(message);
-                        break;
-                    } else if (mA2dpState != BluetoothA2dp.STATE_DISCONNECTED) {
-                        sendMessage(DISCONNECT_A2DP_OUTGOING);
-                        deferMessage(message);
-                        break;
-                    } else if (mService.getInputDeviceConnectionState(mDevice) !=
-                            BluetoothInputDevice.STATE_DISCONNECTED) {
-                        sendMessage(DISCONNECT_HID_OUTGOING);
-                        deferMessage(message);
-                        break;
-                    }
-                    processCommand(UNPAIR);
-                    break;
-                case AUTO_CONNECT_PROFILES:
-                    if (isPhoneDocked(mDevice)) {
-                        // Don't auto connect to docks.
-                        break;
-                    } else {
-                        if (mHeadsetService == null) {
-                              mAutoConnectionPending = true;
-                        } else if (mHeadsetService.getPriority(mDevice) ==
-                              BluetoothHeadset.PRIORITY_AUTO_CONNECT &&
-                              mHeadsetService.getDevicesMatchingConnectionStates(
-                                  new int[] {BluetoothProfile.STATE_CONNECTED,
-                                             BluetoothProfile.STATE_CONNECTING,
-                                             BluetoothProfile.STATE_DISCONNECTING}).size() == 0) {
-                            mHeadsetService.connect(mDevice);
-                        }
-                        if (mA2dpService != null &&
-                              mA2dpService.getPriority(mDevice) ==
-                              BluetoothA2dp.PRIORITY_AUTO_CONNECT &&
-                              mA2dpService.getDevicesMatchingConnectionStates(
-                                  new int[] {BluetoothA2dp.STATE_CONNECTED,
-                                             BluetoothProfile.STATE_CONNECTING,
-                                             BluetoothProfile.STATE_DISCONNECTING}).size() == 0) {
-                            mA2dpService.connect(mDevice);
-                        }
-                        if (mService.getInputDevicePriority(mDevice) ==
-                              BluetoothInputDevice.PRIORITY_AUTO_CONNECT) {
-                            mService.connectInputDevice(mDevice);
-                        }
-                    }
-                    break;
-                case CONNECT_OTHER_PROFILES:
-                    if (isPhoneDocked(mDevice)) {
-                       break;
-                    }
-                    if (message.arg1 == CONNECT_A2DP_OUTGOING) {
-                        if (mA2dpService != null &&
-                            mA2dpService.getConnectedDevices().size() == 0) {
-                            Log.i(TAG, "A2dp:Connect Other Profiles");
-                            mA2dpService.connect(mDevice);
-                        }
-                    } else if (message.arg1 == CONNECT_HFP_OUTGOING) {
-                        if (mHeadsetService == null) {
-                            deferMessage(message);
-                        } else {
-                            if (mHeadsetService.getConnectedDevices().size() == 0) {
-                                Log.i(TAG, "Headset:Connect Other Profiles");
-                                mHeadsetService.connect(mDevice);
-                            }
-                        }
-                    }
-                    break;
-                case TRANSITION_TO_STABLE:
-                    // ignore.
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return HANDLED;
-        }
-    }
-
-    private class OutgoingHandsfree extends State {
-        private boolean mStatus = false;
-        private int mCommand;
-
-        @Override
-        public void enter() {
-            Log.i(TAG, "Entering OutgoingHandsfree state with: " + getCurrentMessage().what);
-            mCommand = getCurrentMessage().what;
-            if (mCommand != CONNECT_HFP_OUTGOING &&
-                mCommand != DISCONNECT_HFP_OUTGOING) {
-                Log.e(TAG, "Error: OutgoingHandsfree state with command:" + mCommand);
-            }
-            mStatus = processCommand(mCommand);
-            if (!mStatus) {
-                sendMessage(TRANSITION_TO_STABLE);
-                mService.sendProfileStateMessage(BluetoothProfileState.HFP,
-                                                 BluetoothProfileState.TRANSITION_TO_STABLE);
-            }
-        }
-
-        @Override
-        public boolean processMessage(Message message) {
-            log("OutgoingHandsfree State -> Processing Message: " + message.what);
-            Message deferMsg = new Message();
-            int command = message.what;
-            switch(command) {
-                case CONNECT_HFP_OUTGOING:
-                    if (command != mCommand) {
-                        // Disconnect followed by a connect - defer
-                        deferMessage(message);
-                    }
-                    break;
-                case CONNECT_HFP_INCOMING:
-                    if (mCommand == CONNECT_HFP_OUTGOING) {
-                        // Cancel outgoing connect, accept incoming
-                        cancelCommand(CONNECT_HFP_OUTGOING);
-                        transitionTo(mIncomingHandsfree);
-                    } else {
-                        // We have done the disconnect but we are not
-                        // sure which state we are in at this point.
-                        deferMessage(message);
-                    }
-                    break;
-                case CONNECT_A2DP_INCOMING:
-                    // accept incoming A2DP, retry HFP_OUTGOING
-                    transitionTo(mIncomingA2dp);
-
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break;
-                case CONNECT_A2DP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_HFP_OUTGOING:
-                    if (mCommand == CONNECT_HFP_OUTGOING) {
-                        // Cancel outgoing connect
-                        cancelCommand(CONNECT_HFP_OUTGOING);
-                        processCommand(DISCONNECT_HFP_OUTGOING);
-                    }
-                    // else ignore
-                    break;
-                case DISCONNECT_HFP_INCOMING:
-                    // When this happens the socket would be closed and the headset
-                    // state moved to DISCONNECTED, cancel the outgoing thread.
-                    // if it still is in CONNECTING state
-                    cancelCommand(CONNECT_HFP_OUTGOING);
-                    break;
-                case DISCONNECT_A2DP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_A2DP_INCOMING:
-                    // Bluez will handle the disconnect. If because of this the outgoing
-                    // handsfree connection has failed, then retry.
-                    if (mStatus) {
-                       deferMsg.what = mCommand;
-                       deferMessage(deferMsg);
-                    }
-                    break;
-                case CONNECT_HID_OUTGOING:
-                case DISCONNECT_HID_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case CONNECT_HID_INCOMING:
-                    transitionTo(mIncomingHid);
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break;
-                case DISCONNECT_HID_INCOMING:
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break; // ignore
-                case DISCONNECT_PBAP_OUTGOING:
-                case UNPAIR:
-                case AUTO_CONNECT_PROFILES:
-                case CONNECT_OTHER_PROFILES:
-                    deferMessage(message);
-                    break;
-                case TRANSITION_TO_STABLE:
-                    transitionTo(mBondedDevice);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return HANDLED;
-        }
-    }
-
-    private class IncomingHandsfree extends State {
-        private boolean mStatus = false;
-        private int mCommand;
-
-        @Override
-        public void enter() {
-            Log.i(TAG, "Entering IncomingHandsfree state with: " + getCurrentMessage().what);
-            mCommand = getCurrentMessage().what;
-            if (mCommand != CONNECT_HFP_INCOMING &&
-                mCommand != DISCONNECT_HFP_INCOMING) {
-                Log.e(TAG, "Error: IncomingHandsfree state with command:" + mCommand);
-            }
-            mStatus = processCommand(mCommand);
-            if (!mStatus) {
-                sendMessage(TRANSITION_TO_STABLE);
-                mService.sendProfileStateMessage(BluetoothProfileState.HFP,
-                                                 BluetoothProfileState.TRANSITION_TO_STABLE);
-            }
-        }
-
-        @Override
-        public boolean processMessage(Message message) {
-            log("IncomingHandsfree State -> Processing Message: " + message.what);
-            switch(message.what) {
-                case CONNECT_HFP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case CONNECT_HFP_INCOMING:
-                    // Ignore
-                    Log.e(TAG, "Error: Incoming connection with a pending incoming connection");
-                    break;
-                case CONNECTION_ACCESS_REQUEST_REPLY:
-                    int val = message.arg1;
-                    mConnectionAccessReplyReceived = true;
-                    boolean value = false;
-                    if (val == BluetoothDevice.CONNECTION_ACCESS_YES) {
-                        value = true;
-                    }
-                    setTrust(val);
-
-                    handleIncomingConnection(CONNECT_HFP_INCOMING, value);
-                    break;
-                case CONNECTION_ACCESS_REQUEST_EXPIRY:
-                    if (!mConnectionAccessReplyReceived) {
-                        handleIncomingConnection(CONNECT_HFP_INCOMING, false);
-                        sendConnectionAccessRemovalIntent();
-                        sendMessage(TRANSITION_TO_STABLE);
-                    }
-                    break;
-                case CONNECT_A2DP_INCOMING:
-                    // Serialize the commands.
-                    deferMessage(message);
-                    break;
-                case CONNECT_A2DP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_HFP_OUTGOING:
-                    // We don't know at what state we are in the incoming HFP connection state.
-                    // We can be changing from DISCONNECTED to CONNECTING, or
-                    // from CONNECTING to CONNECTED, so serializing this command is
-                    // the safest option.
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_HFP_INCOMING:
-                    // Nothing to do here, we will already be DISCONNECTED
-                    // by this point.
-                    break;
-                case DISCONNECT_A2DP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_A2DP_INCOMING:
-                    // Bluez handles incoming A2DP disconnect.
-                    // If this causes incoming HFP to fail, it is more of a headset problem
-                    // since both connections are incoming ones.
-                    break;
-                case CONNECT_HID_OUTGOING:
-                case DISCONNECT_HID_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case CONNECT_HID_INCOMING:
-                case DISCONNECT_HID_INCOMING:
-                     break; // ignore
-                case DISCONNECT_PBAP_OUTGOING:
-                case UNPAIR:
-                case AUTO_CONNECT_PROFILES:
-                case CONNECT_OTHER_PROFILES:
-                    deferMessage(message);
-                    break;
-                case TRANSITION_TO_STABLE:
-                    transitionTo(mBondedDevice);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return HANDLED;
-        }
-    }
-
-    private class OutgoingA2dp extends State {
-        private boolean mStatus = false;
-        private int mCommand;
-
-        @Override
-        public void enter() {
-            Log.i(TAG, "Entering OutgoingA2dp state with: " + getCurrentMessage().what);
-            mCommand = getCurrentMessage().what;
-            if (mCommand != CONNECT_A2DP_OUTGOING &&
-                mCommand != DISCONNECT_A2DP_OUTGOING) {
-                Log.e(TAG, "Error: OutgoingA2DP state with command:" + mCommand);
-            }
-            mStatus = processCommand(mCommand);
-            if (!mStatus) {
-                sendMessage(TRANSITION_TO_STABLE);
-                mService.sendProfileStateMessage(BluetoothProfileState.A2DP,
-                                                 BluetoothProfileState.TRANSITION_TO_STABLE);
-            }
-        }
-
-        @Override
-        public boolean processMessage(Message message) {
-            log("OutgoingA2dp State->Processing Message: " + message.what);
-            Message deferMsg = new Message();
-            switch(message.what) {
-                case CONNECT_HFP_OUTGOING:
-                    processCommand(CONNECT_HFP_OUTGOING);
-
-                    // Don't cancel A2DP outgoing as there is no guarantee it
-                    // will get canceled.
-                    // It might already be connected but we might not have got the
-                    // A2DP_SINK_STATE_CHANGE. Hence, no point disconnecting here.
-                    // The worst case, the connection will fail, retry.
-                    // The same applies to Disconnecting an A2DP connection.
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break;
-                case CONNECT_HFP_INCOMING:
-                    processCommand(CONNECT_HFP_INCOMING);
-
-                    // Don't cancel A2DP outgoing as there is no guarantee
-                    // it will get canceled.
-                    // The worst case, the connection will fail, retry.
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break;
-                case CONNECT_A2DP_INCOMING:
-                    // Bluez will take care of conflicts between incoming and outgoing
-                    // connections.
-                    transitionTo(mIncomingA2dp);
-                    break;
-                case CONNECT_A2DP_OUTGOING:
-                    // Ignore
-                    break;
-                case DISCONNECT_HFP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_HFP_INCOMING:
-                    // At this point, we are already disconnected
-                    // with HFP. Sometimes A2DP connection can
-                    // fail due to the disconnection of HFP. So add a retry
-                    // for the A2DP.
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break;
-                case DISCONNECT_A2DP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_A2DP_INCOMING:
-                    // Ignore, will be handled by Bluez
-                    break;
-                case CONNECT_HID_OUTGOING:
-                case DISCONNECT_HID_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case CONNECT_HID_INCOMING:
-                    transitionTo(mIncomingHid);
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break;
-                case DISCONNECT_HID_INCOMING:
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break; // ignore
-                case DISCONNECT_PBAP_OUTGOING:
-                case UNPAIR:
-                case AUTO_CONNECT_PROFILES:
-                case CONNECT_OTHER_PROFILES:
-                    deferMessage(message);
-                    break;
-                case TRANSITION_TO_STABLE:
-                    transitionTo(mBondedDevice);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return HANDLED;
-        }
-    }
-
-    private class IncomingA2dp extends State {
-        private boolean mStatus = false;
-        private int mCommand;
-
-        @Override
-        public void enter() {
-            Log.i(TAG, "Entering IncomingA2dp state with: " + getCurrentMessage().what);
-            mCommand = getCurrentMessage().what;
-            if (mCommand != CONNECT_A2DP_INCOMING &&
-                mCommand != DISCONNECT_A2DP_INCOMING) {
-                Log.e(TAG, "Error: IncomingA2DP state with command:" + mCommand);
-            }
-            mStatus = processCommand(mCommand);
-            if (!mStatus) {
-                sendMessage(TRANSITION_TO_STABLE);
-                mService.sendProfileStateMessage(BluetoothProfileState.A2DP,
-                                                 BluetoothProfileState.TRANSITION_TO_STABLE);
-            }
-        }
-
-        @Override
-        public boolean processMessage(Message message) {
-            log("IncomingA2dp State->Processing Message: " + message.what);
-            switch(message.what) {
-                case CONNECT_HFP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case CONNECT_HFP_INCOMING:
-                    // Shouldn't happen, but serialize the commands.
-                    deferMessage(message);
-                    break;
-                case CONNECT_A2DP_INCOMING:
-                    // ignore
-                    break;
-                case CONNECTION_ACCESS_REQUEST_REPLY:
-                    int val = message.arg1;
-                    mConnectionAccessReplyReceived = true;
-                    boolean value = false;
-                    if (val == BluetoothDevice.CONNECTION_ACCESS_YES) {
-                        value = true;
-                    }
-                    setTrust(val);
-                    handleIncomingConnection(CONNECT_A2DP_INCOMING, value);
-                    break;
-                case CONNECTION_ACCESS_REQUEST_EXPIRY:
-                    // The check protects the race condition between REQUEST_REPLY
-                    // and the timer expiry.
-                    if (!mConnectionAccessReplyReceived) {
-                        handleIncomingConnection(CONNECT_A2DP_INCOMING, false);
-                        sendConnectionAccessRemovalIntent();
-                        sendMessage(TRANSITION_TO_STABLE);
-                    }
-                    break;
-                case CONNECT_A2DP_OUTGOING:
-                    // Defer message and retry
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_HFP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_HFP_INCOMING:
-                    // Shouldn't happen but if does, we can handle it.
-                    // Depends if the headset can handle it.
-                    // Incoming A2DP will be handled by Bluez, Disconnect HFP
-                    // the socket would have already been closed.
-                    // ignore
-                    break;
-                case DISCONNECT_A2DP_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case DISCONNECT_A2DP_INCOMING:
-                    // Ignore, will be handled by Bluez
-                    break;
-                case CONNECT_HID_OUTGOING:
-                case DISCONNECT_HID_OUTGOING:
-                    deferMessage(message);
-                    break;
-                case CONNECT_HID_INCOMING:
-                case DISCONNECT_HID_INCOMING:
-                     break; // ignore
-                case DISCONNECT_PBAP_OUTGOING:
-                case UNPAIR:
-                case AUTO_CONNECT_PROFILES:
-                case CONNECT_OTHER_PROFILES:
-                    deferMessage(message);
-                    break;
-                case TRANSITION_TO_STABLE:
-                    transitionTo(mBondedDevice);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return HANDLED;
-        }
-    }
-
-
-    private class OutgoingHid extends State {
-        private boolean mStatus = false;
-        private int mCommand;
-
-        @Override
-        public void enter() {
-            log("Entering OutgoingHid state with: " + getCurrentMessage().what);
-            mCommand = getCurrentMessage().what;
-            if (mCommand != CONNECT_HID_OUTGOING &&
-                mCommand != DISCONNECT_HID_OUTGOING) {
-                Log.e(TAG, "Error: OutgoingHid state with command:" + mCommand);
-            }
-            mStatus = processCommand(mCommand);
-            if (!mStatus) sendMessage(TRANSITION_TO_STABLE);
-        }
-
-        @Override
-        public boolean processMessage(Message message) {
-            log("OutgoingHid State->Processing Message: " + message.what);
-            Message deferMsg = new Message();
-            switch(message.what) {
-                // defer all outgoing messages
-                case CONNECT_HFP_OUTGOING:
-                case CONNECT_A2DP_OUTGOING:
-                case CONNECT_HID_OUTGOING:
-                case DISCONNECT_HFP_OUTGOING:
-                case DISCONNECT_A2DP_OUTGOING:
-                case DISCONNECT_HID_OUTGOING:
-                    deferMessage(message);
-                    break;
-
-                case CONNECT_HFP_INCOMING:
-                    transitionTo(mIncomingHandsfree);
-                    break;
-                case CONNECT_A2DP_INCOMING:
-                    transitionTo(mIncomingA2dp);
-
-                    // Don't cancel HID outgoing as there is no guarantee it
-                    // will get canceled.
-                    // It might already be connected but we might not have got the
-                    // INPUT_DEVICE_STATE_CHANGE. Hence, no point disconnecting here.
-                    // The worst case, the connection will fail, retry.
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break;
-                case CONNECT_HID_INCOMING:
-                  // Bluez will take care of the conflicts
-                    transitionTo(mIncomingHid);
-                    break;
-
-                case DISCONNECT_HFP_INCOMING:
-                case DISCONNECT_A2DP_INCOMING:
-                    // At this point, we are already disconnected
-                    // with HFP. Sometimes HID connection can
-                    // fail due to the disconnection of HFP. So add a retry
-                    // for the HID.
-                    if (mStatus) {
-                        deferMsg.what = mCommand;
-                        deferMessage(deferMsg);
-                    }
-                    break;
-                case DISCONNECT_HID_INCOMING:
-                    // Ignore, will be handled by Bluez
-                    break;
-                case DISCONNECT_PBAP_OUTGOING:
-                case UNPAIR:
-                case AUTO_CONNECT_PROFILES:
-                    deferMessage(message);
-                    break;
-                case TRANSITION_TO_STABLE:
-                    transitionTo(mBondedDevice);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return HANDLED;
-        }
-    }
-
-  private class IncomingHid extends State {
-      private boolean mStatus = false;
-      private int mCommand;
-
-      @Override
-    public void enter() {
-          log("Entering IncomingHid state with: " + getCurrentMessage().what);
-          mCommand = getCurrentMessage().what;
-          if (mCommand != CONNECT_HID_INCOMING &&
-              mCommand != DISCONNECT_HID_INCOMING) {
-              Log.e(TAG, "Error: IncomingHid state with command:" + mCommand);
-          }
-          mStatus = processCommand(mCommand);
-          if (!mStatus) sendMessage(TRANSITION_TO_STABLE);
-      }
-
-      @Override
-    public boolean processMessage(Message message) {
-          log("IncomingHid State->Processing Message: " + message.what);
-          Message deferMsg = new Message();
-          switch(message.what) {
-              case CONNECT_HFP_OUTGOING:
-              case CONNECT_HFP_INCOMING:
-              case DISCONNECT_HFP_OUTGOING:
-              case CONNECT_A2DP_INCOMING:
-              case CONNECT_A2DP_OUTGOING:
-              case DISCONNECT_A2DP_OUTGOING:
-              case CONNECT_HID_OUTGOING:
-              case CONNECT_HID_INCOMING:
-              case DISCONNECT_HID_OUTGOING:
-                  deferMessage(message);
-                  break;
-              case CONNECTION_ACCESS_REQUEST_REPLY:
-                  mConnectionAccessReplyReceived = true;
-                  int val = message.arg1;
-                  setTrust(val);
-                  handleIncomingConnection(CONNECT_HID_INCOMING,
-                      val == BluetoothDevice.CONNECTION_ACCESS_YES);
-                  break;
-              case CONNECTION_ACCESS_REQUEST_EXPIRY:
-                  if (!mConnectionAccessReplyReceived) {
-                      handleIncomingConnection(CONNECT_HID_INCOMING, false);
-                      sendConnectionAccessRemovalIntent();
-                      sendMessage(TRANSITION_TO_STABLE);
-                  }
-                  break;
-              case DISCONNECT_HFP_INCOMING:
-                  // Shouldn't happen but if does, we can handle it.
-                  // Depends if the headset can handle it.
-                  // Incoming HID will be handled by Bluez, Disconnect HFP
-                  // the socket would have already been closed.
-                  // ignore
-                  break;
-              case DISCONNECT_HID_INCOMING:
-              case DISCONNECT_A2DP_INCOMING:
-                  // Ignore, will be handled by Bluez
-                  break;
-              case DISCONNECT_PBAP_OUTGOING:
-              case UNPAIR:
-              case AUTO_CONNECT_PROFILES:
-                  deferMessage(message);
-                  break;
-              case TRANSITION_TO_STABLE:
-                  transitionTo(mBondedDevice);
-                  break;
-              default:
-                  return NOT_HANDLED;
-          }
-          return HANDLED;
-      }
-  }
-
-
-    synchronized void cancelCommand(int command) {
-        if (command == CONNECT_HFP_OUTGOING ) {
-            // Cancel the outgoing thread.
-            if (mHeadsetService != null) {
-                mHeadsetService.cancelConnectThread();
-            }
-            // HeadsetService is down. Phone process most likely crashed.
-            // The thread would have got killed.
-        }
-    }
-
-    synchronized void deferProfileServiceMessage(int command) {
-        Message msg = new Message();
-        msg.what = command;
-        deferMessage(msg);
-    }
-
-    private void updateIncomingAllowedTimer() {
-        // Not doing a perfect exponential backoff because
-        // we want two different rates. For all practical
-        // purposes, this is good enough.
-        if (mIncomingRejectTimer == 0) mIncomingRejectTimer = INIT_INCOMING_REJECT_TIMER;
-
-        mIncomingRejectTimer *= 5;
-        if (mIncomingRejectTimer > MAX_INCOMING_REJECT_TIMER) {
-            mIncomingRejectTimer = MAX_INCOMING_REJECT_TIMER;
-        }
-        writeTimerValue(mIncomingRejectTimer);
-    }
-
-    private boolean handleIncomingConnection(int command, boolean accept) {
-        boolean ret = false;
-        Log.i(TAG, "handleIncomingConnection:" + command + ":" + accept);
-        switch (command) {
-            case CONNECT_HFP_INCOMING:
-                if (!accept) {
-                    ret = mHeadsetService.rejectIncomingConnect(mDevice);
-                    sendMessage(TRANSITION_TO_STABLE);
-                    updateIncomingAllowedTimer();
-                } else if (mHeadsetState == BluetoothHeadset.STATE_CONNECTING) {
-                    writeTimerValue(0);
-                    ret =  mHeadsetService.acceptIncomingConnect(mDevice);
-                } else if (mHeadsetState == BluetoothHeadset.STATE_DISCONNECTED) {
-                    writeTimerValue(0);
-                    handleConnectionOfOtherProfiles(command);
-                    ret = mHeadsetService.createIncomingConnect(mDevice);
-                }
-                break;
-            case CONNECT_A2DP_INCOMING:
-                if (!accept) {
-                    ret = mA2dpService.allowIncomingConnect(mDevice, false);
-                    sendMessage(TRANSITION_TO_STABLE);
-                    updateIncomingAllowedTimer();
-                } else {
-                    writeTimerValue(0);
-                    ret = mA2dpService.allowIncomingConnect(mDevice, true);
-                    handleConnectionOfOtherProfiles(command);
-                }
-                break;
-            case CONNECT_HID_INCOMING:
-                if (!accept) {
-                    ret = mService.allowIncomingProfileConnect(mDevice, false);
-                    sendMessage(TRANSITION_TO_STABLE);
-                    updateIncomingAllowedTimer();
-                } else {
-                    writeTimerValue(0);
-                    ret = mService.allowIncomingProfileConnect(mDevice, true);
-                }
-                break;
-            default:
-                Log.e(TAG, "Waiting for incoming connection but state changed to:" + command);
-                break;
-       }
-       return ret;
-    }
-
-    private void sendConnectionAccessIntent() {
-        mConnectionAccessReplyReceived = false;
-
-        if (!mPowerManager.isScreenOn()) mWakeLock.acquire();
-
-        Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REQUEST);
-        intent.setClassName(ACCESS_AUTHORITY_PACKAGE, ACCESS_AUTHORITY_CLASS);
-        intent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
-                        BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-    }
-
-    private void sendConnectionAccessRemovalIntent() {
-        mWakeLock.release();
-        Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-    }
-
-    private int getTrust() {
-        String address = mDevice.getAddress();
-        if (mIncomingConnections != null) return mIncomingConnections.first;
-        return CONNECTION_ACCESS_UNDEFINED;
-    }
-
-
-    private String getStringValue(long value) {
-        StringBuilder sbr = new StringBuilder();
-        sbr.append(Long.toString(System.currentTimeMillis()));
-        sbr.append("-");
-        sbr.append(Long.toString(value));
-        return sbr.toString();
-    }
-
-    private void setTrust(int value) {
-        String second;
-        if (mIncomingConnections == null) {
-            second = getStringValue(INIT_INCOMING_REJECT_TIMER);
-        } else {
-            second = mIncomingConnections.second;
-        }
-
-        mIncomingConnections = new Pair(value, second);
-        mService.writeIncomingConnectionState(mDevice.getAddress(), mIncomingConnections);
-    }
-
-    private void writeTimerValue(long value) {
-        Integer first;
-        if (mIncomingConnections == null) {
-            first = CONNECTION_ACCESS_UNDEFINED;
-        } else {
-            first = mIncomingConnections.first;
-        }
-        mIncomingConnections = new Pair(first, getStringValue(value));
-        mService.writeIncomingConnectionState(mDevice.getAddress(), mIncomingConnections);
-    }
-
-    private long readTimerValue() {
-        if (mIncomingConnections == null)
-            return 0;
-        String value = mIncomingConnections.second;
-        String[] splits = value.split("-");
-        if (splits != null && splits.length == 2) {
-            return Long.parseLong(splits[1]);
-        }
-        return 0;
-    }
-
-    private boolean readIncomingAllowedValue() {
-        if (readTimerValue() == 0) return true;
-        String value = mIncomingConnections.second;
-        String[] splits = value.split("-");
-        if (splits != null && splits.length == 2) {
-            long val1 = Long.parseLong(splits[0]);
-            long val2 = Long.parseLong(splits[1]);
-            if (val1 + val2 <= System.currentTimeMillis()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    synchronized boolean processCommand(int command) {
-        log("Processing command:" + command);
-        switch(command) {
-            case  CONNECT_HFP_OUTGOING:
-                if (mHeadsetService == null) {
-                    deferProfileServiceMessage(command);
-                } else {
-                    return mHeadsetService.connectHeadsetInternal(mDevice);
-                }
-                break;
-            case CONNECT_HFP_INCOMING:
-                if (mHeadsetService == null) {
-                    deferProfileServiceMessage(command);
-                } else {
-                    processIncomingConnectCommand(command);
-                    return true;
-                }
-                break;
-            case CONNECT_A2DP_OUTGOING:
-                if (mA2dpService != null) {
-                    return mA2dpService.connectSinkInternal(mDevice);
-                }
-                break;
-            case CONNECT_A2DP_INCOMING:
-                processIncomingConnectCommand(command);
-                return true;
-            case CONNECT_HID_OUTGOING:
-                return mService.connectInputDeviceInternal(mDevice);
-            case CONNECT_HID_INCOMING:
-                processIncomingConnectCommand(command);
-                return true;
-            case DISCONNECT_HFP_OUTGOING:
-                if (mHeadsetService == null) {
-                    deferProfileServiceMessage(command);
-                } else {
-                    // Disconnect PBAP
-                    // TODO(): Add PBAP to the state machine.
-                    Message m = new Message();
-                    m.what = DISCONNECT_PBAP_OUTGOING;
-                    deferMessage(m);
-                    if (mHeadsetService.getPriority(mDevice) ==
-                        BluetoothHeadset.PRIORITY_AUTO_CONNECT) {
-                        mHeadsetService.setPriority(mDevice, BluetoothHeadset.PRIORITY_ON);
-                    }
-                    return mHeadsetService.disconnectHeadsetInternal(mDevice);
-                }
-                break;
-            case DISCONNECT_HFP_INCOMING:
-                // ignore
-                return true;
-            case DISCONNECT_A2DP_INCOMING:
-                // ignore
-                return true;
-            case DISCONNECT_A2DP_OUTGOING:
-                if (mA2dpService != null) {
-                    if (mA2dpService.getPriority(mDevice) ==
-                        BluetoothA2dp.PRIORITY_AUTO_CONNECT) {
-                        mA2dpService.setPriority(mDevice, BluetoothHeadset.PRIORITY_ON);
-                    }
-                    return mA2dpService.disconnectSinkInternal(mDevice);
-                }
-                break;
-            case DISCONNECT_HID_INCOMING:
-                // ignore
-                return true;
-            case DISCONNECT_HID_OUTGOING:
-                if (mService.getInputDevicePriority(mDevice) ==
-                    BluetoothInputDevice.PRIORITY_AUTO_CONNECT) {
-                    mService.setInputDevicePriority(mDevice, BluetoothInputDevice.PRIORITY_ON);
-                }
-                return mService.disconnectInputDeviceInternal(mDevice);
-            case DISCONNECT_PBAP_OUTGOING:
-                if (!mPbapServiceConnected) {
-                    deferProfileServiceMessage(command);
-                } else {
-                    return mPbapService.disconnect();
-                }
-                break;
-            case UNPAIR:
-                writeTimerValue(INIT_INCOMING_REJECT_TIMER);
-                setTrust(CONNECTION_ACCESS_UNDEFINED);
-                return mService.removeBondInternal(mDevice.getAddress());
-            default:
-                Log.e(TAG, "Error: Unknown Command");
-        }
-        return false;
-    }
-
-    private void processIncomingConnectCommand(int command) {
-        // Check if device is already trusted
-        int access = getTrust();
-        if (access == BluetoothDevice.CONNECTION_ACCESS_YES) {
-            handleIncomingConnection(command, true);
-        } else if (access == BluetoothDevice.CONNECTION_ACCESS_NO &&
-                   !readIncomingAllowedValue()) {
-            handleIncomingConnection(command, false);
-        } else {
-            sendConnectionAccessIntent();
-            Message msg = obtainMessage(CONNECTION_ACCESS_REQUEST_EXPIRY);
-            sendMessageDelayed(msg,
-                               CONNECTION_ACCESS_REQUEST_EXPIRY_TIMEOUT);
-        }
-    }
-
-    private void handleConnectionOfOtherProfiles(int command) {
-        // The white paper recommendations mentions that when there is a
-        // link loss, it is the responsibility of the remote device to connect.
-        // Many connect only 1 profile - and they connect the second profile on
-        // some user action (like play being pressed) and so we need this code.
-        // Auto Connect code only connects to the last connected device - which
-        // is useful in cases like when the phone reboots. But consider the
-        // following case:
-        // User is connected to the car's phone and  A2DP profile.
-        // User comes to the desk  and places the phone in the dock
-        // (or any speaker or music system or even another headset) and thus
-        // gets connected to the A2DP profile.  User goes back to the car.
-        // Ideally the car's system is supposed to send incoming connections
-        // from both Handsfree and A2DP profile. But they don't. The Auto
-        // connect code, will not work here because we only auto connect to the
-        // last connected device for that profile which in this case is the dock.
-        // Now suppose a user is using 2 headsets simultaneously, one for the
-        // phone profile one for the A2DP profile. If this is the use case, we
-        // expect the user to use the preference to turn off the A2DP profile in
-        // the Settings screen for the first headset. Else, after link loss,
-        // there can be an incoming connection from the first headset which
-        // might result in the connection of the A2DP profile (if the second
-        // headset is slower) and thus the A2DP profile on the second headset
-        // will never get connected.
-        //
-        // TODO(): Handle other profiles here.
-        switch (command) {
-            case CONNECT_HFP_INCOMING:
-                // Connect A2DP if there is no incoming connection
-                // If the priority is OFF - don't auto connect.
-                if (mA2dpService.getPriority(mDevice) == BluetoothProfile.PRIORITY_ON ||
-                        mA2dpService.getPriority(mDevice) ==
-                            BluetoothProfile.PRIORITY_AUTO_CONNECT) {
-                    Message msg = new Message();
-                    msg.what = CONNECT_OTHER_PROFILES;
-                    msg.arg1 = CONNECT_A2DP_OUTGOING;
-                    sendMessageDelayed(msg, CONNECT_OTHER_PROFILES_DELAY);
-                }
-                break;
-            case CONNECT_A2DP_INCOMING:
-                // This is again against spec. HFP incoming connections should be made
-                // before A2DP, so we should not hit this case. But many devices
-                // don't follow this.
-                if (mHeadsetService != null &&
-                    (mHeadsetService.getPriority(mDevice) == BluetoothProfile.PRIORITY_ON ||
-                        mHeadsetService.getPriority(mDevice) ==
-                            BluetoothProfile.PRIORITY_AUTO_CONNECT)) {
-                    Message msg = new Message();
-                    msg.what = CONNECT_OTHER_PROFILES;
-                    msg.arg1 = CONNECT_HFP_OUTGOING;
-                    sendMessageDelayed(msg, CONNECT_OTHER_PROFILES_DELAY);
-                }
-                break;
-            default:
-                break;
-        }
-
-    }
-
-    /*package*/ BluetoothDevice getDevice() {
-        return mDevice;
-    }
-
-    /**
-     * Quit the state machine, only to be called by BluetoothService.
-     *
-     * @hide
-     */
-    public void doQuit() {
-        this.quit();
-    }
-
-    private void log(String message) {
-        if (DBG) {
-            Log.i(TAG, "Device:" + mDevice + " Message:" + message);
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
old mode 100644
new mode 100755
index 2bbf008..793d798
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -45,7 +45,8 @@
  */
 public final class BluetoothHeadset implements BluetoothProfile {
     private static final String TAG = "BluetoothHeadset";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
+    private static final boolean VDBG = false;
 
     /**
      * Intent used to broadcast the change in connection state of the Headset
@@ -219,7 +220,38 @@
     private Context mContext;
     private ServiceListener mServiceListener;
     private IBluetoothHeadset mService;
-    BluetoothAdapter mAdapter;
+    private BluetoothAdapter mAdapter;
+
+    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+            new IBluetoothStateChangeCallback.Stub() {
+                public void onBluetoothStateChange(boolean up) {
+                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
+                    if (!up) {
+                        if (VDBG) Log.d(TAG,"Unbinding service...");
+                        synchronized (mConnection) {
+                            try {
+                                mService = null;
+                                mContext.unbindService(mConnection);
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    } else {
+                        synchronized (mConnection) {
+                            try {
+                                if (mService == null) {
+                                    if (VDBG) Log.d(TAG,"Binding service...");
+                                    if (!mContext.bindService(new Intent(IBluetoothHeadset.class.getName()), mConnection, 0)) {
+                                        Log.e(TAG, "Could not bind to Bluetooth Headset Service");
+                                    }
+                                }
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    }
+                }
+        };
 
     /**
      * Create a BluetoothHeadset proxy object.
@@ -228,6 +260,16 @@
         mContext = context;
         mServiceListener = l;
         mAdapter = BluetoothAdapter.getDefaultAdapter();
+
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG,"",e);
+            }
+        }
+
         if (!context.bindService(new Intent(IBluetoothHeadset.class.getName()), mConnection, 0)) {
             Log.e(TAG, "Could not bind to Bluetooth Headset Service");
         }
@@ -239,11 +281,27 @@
      * results once close() has been called. Multiple invocations of close()
      * are ok.
      */
-    /*package*/ synchronized void close() {
-        if (DBG) log("close()");
-        if (mConnection != null) {
-            mContext.unbindService(mConnection);
-            mConnection = null;
+    /*package*/ void close() {
+        if (VDBG) log("close()");
+
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (Exception e) {
+                Log.e(TAG,"",e);
+            }
+        }
+
+        synchronized (mConnection) {
+            if (mService != null) {
+                try {
+                    mService = null;
+                    mContext.unbindService(mConnection);
+                } catch (Exception re) {
+                    Log.e(TAG,"",re);
+                }
+            }
         }
         mServiceListener = null;
     }
@@ -330,7 +388,7 @@
      * {@inheritDoc}
      */
     public List<BluetoothDevice> getConnectedDevices() {
-        if (DBG) log("getConnectedDevices()");
+        if (VDBG) log("getConnectedDevices()");
         if (mService != null && isEnabled()) {
             try {
                 return mService.getConnectedDevices();
@@ -347,7 +405,7 @@
      * {@inheritDoc}
      */
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (DBG) log("getDevicesMatchingStates()");
+        if (VDBG) log("getDevicesMatchingStates()");
         if (mService != null && isEnabled()) {
             try {
                 return mService.getDevicesMatchingConnectionStates(states);
@@ -364,7 +422,7 @@
      * {@inheritDoc}
      */
     public int getConnectionState(BluetoothDevice device) {
-        if (DBG) log("getConnectionState(" + device + ")");
+        if (VDBG) log("getConnectionState(" + device + ")");
         if (mService != null && isEnabled() &&
             isValidDevice(device)) {
             try {
@@ -426,7 +484,7 @@
      * @hide
      */
     public int getPriority(BluetoothDevice device) {
-        if (DBG) log("getPriority(" + device + ")");
+        if (VDBG) log("getPriority(" + device + ")");
         if (mService != null && isEnabled() &&
             isValidDevice(device)) {
             try {
@@ -509,7 +567,7 @@
      *         false otherwise or on error
      */
     public boolean isAudioConnected(BluetoothDevice device) {
-        if (DBG) log("isAudioConnected()");
+        if (VDBG) log("isAudioConnected()");
         if (mService != null && isEnabled() &&
             isValidDevice(device)) {
             try {
@@ -537,7 +595,7 @@
      * @hide
      */
     public int getBatteryUsageHint(BluetoothDevice device) {
-        if (DBG) log("getBatteryUsageHint()");
+        if (VDBG) log("getBatteryUsageHint()");
         if (mService != null && isEnabled() &&
             isValidDevice(device)) {
             try {
@@ -562,25 +620,6 @@
     }
 
     /**
-     * Cancel the outgoing connection.
-     * Note: This is an internal function and shouldn't be exposed
-     *
-     * @hide
-     */
-    public boolean cancelConnectThread() {
-        if (DBG) log("cancelConnectThread");
-        if (mService != null && isEnabled()) {
-            try {
-                return mService.cancelConnectThread();
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
-        } else {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        }
-        return false;
-    }
-
-    /**
      * Accept the incoming connection.
      * Note: This is an internal function and shouldn't be exposed
      *
@@ -600,25 +639,6 @@
     }
 
     /**
-     * Create the connect thread for the incoming connection.
-     * Note: This is an internal function and shouldn't be exposed
-     *
-     * @hide
-     */
-    public boolean createIncomingConnect(BluetoothDevice device) {
-        if (DBG) log("createIncomingConnect");
-        if (mService != null && isEnabled()) {
-            try {
-                return mService.createIncomingConnect(device);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
-        } else {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        }
-        return false;
-    }
-
-    /**
      * Reject the incoming connection.
      * @hide
      */
@@ -636,70 +656,13 @@
     }
 
     /**
-     * Connect to a Bluetooth Headset.
-     * Note: This is an internal function and shouldn't be exposed
-     *
-     * @hide
-     */
-    public boolean connectHeadsetInternal(BluetoothDevice device) {
-        if (DBG) log("connectHeadsetInternal");
-        if (mService != null && isEnabled()) {
-            try {
-                return mService.connectHeadsetInternal(device);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
-        } else {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        }
-        return false;
-    }
-
-    /**
-     * Disconnect a Bluetooth Headset.
-     * Note: This is an internal function and shouldn't be exposed
-     *
-     * @hide
-     */
-    public boolean disconnectHeadsetInternal(BluetoothDevice device) {
-        if (DBG) log("disconnectHeadsetInternal");
-        if (mService != null && !isDisabled()) {
-            try {
-                 return mService.disconnectHeadsetInternal(device);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
-        } else {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        }
-        return false;
-    }
-
-    /**
-     * Set the audio state of the Headset.
-     * Note: This is an internal function and shouldn't be exposed
-     *
-     * @hide
-     */
-    public boolean setAudioState(BluetoothDevice device, int state) {
-        if (DBG) log("setAudioState");
-        if (mService != null && !isDisabled()) {
-            try {
-                return mService.setAudioState(device, state);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
-        } else {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        }
-        return false;
-    }
-
-    /**
      * Get the current audio state of the Headset.
      * Note: This is an internal function and shouldn't be exposed
      *
      * @hide
      */
     public int getAudioState(BluetoothDevice device) {
-        if (DBG) log("getAudioState");
+        if (VDBG) log("getAudioState");
         if (mService != null && !isDisabled()) {
             try {
                 return mService.getAudioState(device);
@@ -712,6 +675,75 @@
     }
 
     /**
+     * Check if Bluetooth SCO audio is connected.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     *
+     * @return true if SCO is connected,
+     *         false otherwise or on error
+     * @hide
+     */
+    public boolean isAudioOn() {
+        if (VDBG) log("isAudioOn()");
+        if (mService != null && isEnabled()) {
+            try {
+              return mService.isAudioOn();
+            } catch (RemoteException e) {
+              Log.e(TAG,  Log.getStackTraceString(new Throwable()));
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
+
+    }
+
+    /**
+     * Initiates a connection of headset audio.
+     * It setup SCO channel with remote connected headset device.
+     *
+     * @return true if successful
+     *         false if there was some error such as
+     *               there is no connected headset
+     * @hide
+     */
+    public boolean connectAudio() {
+        if (mService != null && isEnabled()) {
+            try {
+                return mService.connectAudio();
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+        return false;
+    }
+
+    /**
+     * Initiates a disconnection of headset audio.
+     * It tears down the SCO channel from remote headset device.
+     *
+     * @return true if successful
+     *         false if there was some error such as
+     *               there is no connected SCO channel
+     * @hide
+     */
+    public boolean disconnectAudio() {
+        if (mService != null && isEnabled()) {
+            try {
+                return mService.disconnectAudio();
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+        return false;
+    }
+
+    /**
      * Initiates a SCO channel connection with the headset (if connected).
      * Also initiates a virtual voice call for Handsfree devices as many devices
      * do not accept SCO audio without a call.
@@ -760,6 +792,68 @@
         return false;
     }
 
+    /**
+     * Notify Headset of phone state change.
+     * This is a backdoor for phone app to call BluetoothHeadset since
+     * there is currently not a good way to get precise call state change outside
+     * of phone app.
+     *
+     * @hide
+     */
+    public void phoneStateChanged(int numActive, int numHeld, int callState, String number,
+                                  int type) {
+        if (mService != null && isEnabled()) {
+            try {
+                mService.phoneStateChanged(numActive, numHeld, callState, number, type);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+    }
+
+    /**
+     * Notify Headset of phone roam state change.
+     * This is a backdoor for phone app to call BluetoothHeadset since
+     * there is currently not a good way to get roaming state change outside
+     * of phone app.
+     *
+     * @hide
+     */
+    public void roamChanged(boolean roaming) {
+        if (mService != null && isEnabled()) {
+            try {
+                mService.roamChanged(roaming);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+    }
+
+    /**
+     * Send Headset of CLCC response
+     *
+     * @hide
+     */
+    public void clccResponse(int index, int direction, int status, int mode, boolean mpty,
+                             String number, int type) {
+        if (mService != null && isEnabled()) {
+            try {
+                mService.clccResponse(index, direction, status, mode, mpty, number, type);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+    }
+
     private ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java
index f850c02..cb23662 100644
--- a/core/java/android/bluetooth/BluetoothHealth.java
+++ b/core/java/android/bluetooth/BluetoothHealth.java
@@ -16,7 +16,10 @@
 
 package android.bluetooth;
 
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
@@ -54,7 +57,8 @@
  */
 public final class BluetoothHealth implements BluetoothProfile {
     private static final String TAG = "BluetoothHealth";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
+    private static final boolean VDBG = false;
 
     /**
      * Health Profile Source Role - the health device.
@@ -94,6 +98,37 @@
     /** @hide */
     public static final int HEALTH_OPERATION_NOT_ALLOWED = 6005;
 
+    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+            new IBluetoothStateChangeCallback.Stub() {
+                public void onBluetoothStateChange(boolean up) {
+                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
+                    if (!up) {
+                        if (VDBG) Log.d(TAG,"Unbinding service...");
+                        synchronized (mConnection) {
+                            try {
+                                mService = null;
+                                mContext.unbindService(mConnection);
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    } else {
+                        synchronized (mConnection) {
+                            try {
+                                if (mService == null) {
+                                    if (VDBG) Log.d(TAG,"Binding service...");
+                                    if (!mContext.bindService(new Intent(IBluetoothHealth.class.getName()), mConnection, 0)) {
+                                        Log.e(TAG, "Could not bind to Bluetooth Health Service");
+                                    }
+                                }
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    }
+                }
+        };
+
 
     /**
      * Register an application configuration that acts as a Health SINK.
@@ -114,7 +149,7 @@
             BluetoothHealthCallback callback) {
         if (!isEnabled() || name == null) return false;
 
-        if (DBG) log("registerSinkApplication(" + name + ":" + dataType + ")");
+        if (VDBG) log("registerSinkApplication(" + name + ":" + dataType + ")");
         return registerAppConfiguration(name, dataType, SINK_ROLE,
                 CHANNEL_TYPE_ANY, callback);
     }
@@ -140,7 +175,7 @@
         boolean result = false;
         if (!isEnabled() || !checkAppParam(name, role, channelType, callback)) return result;
 
-        if (DBG) log("registerApplication(" + name + ":" + dataType + ")");
+        if (VDBG) log("registerApplication(" + name + ":" + dataType + ")");
         BluetoothHealthCallbackWrapper wrapper = new BluetoothHealthCallbackWrapper(callback);
         BluetoothHealthAppConfiguration config =
                 new BluetoothHealthAppConfiguration(name, dataType, role, channelType);
@@ -427,35 +462,74 @@
     /** Health App Configuration un-registration failure */
     public static final int APP_CONFIG_UNREGISTRATION_FAILURE = 3;
 
+    private Context mContext;
     private ServiceListener mServiceListener;
-    private IBluetooth mService;
+    private IBluetoothHealth mService;
     BluetoothAdapter mAdapter;
 
     /**
      * Create a BluetoothHealth proxy object.
      */
-    /*package*/ BluetoothHealth(Context mContext, ServiceListener l) {
-        IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
+    /*package*/ BluetoothHealth(Context context, ServiceListener l) {
+        mContext = context;
         mServiceListener = l;
         mAdapter = BluetoothAdapter.getDefaultAdapter();
-        if (b != null) {
-            mService = IBluetooth.Stub.asInterface(b);
-            if (mServiceListener != null) {
-                mServiceListener.onServiceConnected(BluetoothProfile.HEALTH, this);
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG,"",e);
             }
-        } else {
-            Log.w(TAG, "Bluetooth Service not available!");
+        }
 
-            // Instead of throwing an exception which prevents people from going
-            // into Wireless settings in the emulator. Let it crash later when it is actually used.
-            mService = null;
+        if (!context.bindService(new Intent(IBluetoothHealth.class.getName()), mConnection, 0)) {
+            Log.e(TAG, "Could not bind to Bluetooth Health Service");
         }
     }
 
     /*package*/ void close() {
+        if (VDBG) log("close()");
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (Exception e) {
+                Log.e(TAG,"",e);
+            }
+        }
+
+        synchronized (mConnection) {
+            if (mService != null) {
+                try {
+                    mService = null;
+                    mContext.unbindService(mConnection);
+                } catch (Exception re) {
+                    Log.e(TAG,"",re);
+                }
+            }
+        }
         mServiceListener = null;
     }
 
+    private ServiceConnection mConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            if (DBG) Log.d(TAG, "Proxy object connected");
+            mService = IBluetoothHealth.Stub.asInterface(service);
+
+            if (mServiceListener != null) {
+                mServiceListener.onServiceConnected(BluetoothProfile.HEALTH, BluetoothHealth.this);
+            }
+        }
+        public void onServiceDisconnected(ComponentName className) {
+            if (DBG) Log.d(TAG, "Proxy object disconnected");
+            mService = null;
+            if (mServiceListener != null) {
+                mServiceListener.onServiceDisconnected(BluetoothProfile.HEALTH);
+            }
+        }
+    };
+
     private boolean isEnabled() {
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
 
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
old mode 100644
new mode 100755
index 1a9e011..db7e424
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -18,7 +18,10 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -41,7 +44,8 @@
  */
 public final class BluetoothInputDevice implements BluetoothProfile {
     private static final String TAG = "BluetoothInputDevice";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
+    private static final boolean VDBG = false;
 
     /**
      * Intent used to broadcast the change in connection state of the Input
@@ -66,6 +70,22 @@
         "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
 
     /**
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_PROTOCOL_MODE_CHANGED =
+        "android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED";
+
+
+    /**
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_VIRTUAL_UNPLUG_STATUS =
+        "android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS";
+
+
+    /**
      * Return codes for the connect and disconnect Bluez / Dbus calls.
      * @hide
      */
@@ -91,34 +111,159 @@
      */
     public static final int INPUT_OPERATION_SUCCESS = 5004;
 
+    /**
+     * @hide
+     */
+    public static final int PROTOCOL_REPORT_MODE = 0;
+
+    /**
+     * @hide
+     */
+    public static final int PROTOCOL_BOOT_MODE = 1;
+
+    /**
+     * @hide
+     */
+    public static final int PROTOCOL_UNSUPPORTED_MODE = 255;
+
+    /*  int reportType, int reportType, int bufferSize */
+    /**
+     * @hide
+     */
+    public static final byte REPORT_TYPE_INPUT = 0;
+
+    /**
+     * @hide
+     */
+    public static final byte REPORT_TYPE_OUTPUT = 1;
+
+    /**
+     * @hide
+     */
+    public static final byte REPORT_TYPE_FEATURE = 2;
+
+    /**
+     * @hide
+     */
+    public static final int VIRTUAL_UNPLUG_STATUS_SUCCESS = 0;
+
+    /**
+     * @hide
+     */
+    public static final int VIRTUAL_UNPLUG_STATUS_FAIL = 1;
+
+    /**
+     * @hide
+     */
+    public static final String EXTRA_PROTOCOL_MODE = "android.bluetooth.BluetoothInputDevice.extra.PROTOCOL_MODE";
+
+    /**
+     * @hide
+     */
+    public static final String EXTRA_REPORT_TYPE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_TYPE";
+
+    /**
+     * @hide
+     */
+    public static final String EXTRA_REPORT_ID = "android.bluetooth.BluetoothInputDevice.extra.REPORT_ID";
+
+    /**
+     * @hide
+     */
+    public static final String EXTRA_REPORT_BUFFER_SIZE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_BUFFER_SIZE";
+
+    /**
+     * @hide
+     */
+    public static final String EXTRA_REPORT = "android.bluetooth.BluetoothInputDevice.extra.REPORT";
+
+    /**
+     * @hide
+     */
+    public static final String EXTRA_VIRTUAL_UNPLUG_STATUS = "android.bluetooth.BluetoothInputDevice.extra.VIRTUAL_UNPLUG_STATUS";
+
+    private Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
-    private IBluetooth mService;
+    private IBluetoothInputDevice mService;
+
+    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+            new IBluetoothStateChangeCallback.Stub() {
+                public void onBluetoothStateChange(boolean up) {
+                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
+                    if (!up) {
+                        if (VDBG) Log.d(TAG,"Unbinding service...");
+                        synchronized (mConnection) {
+                            try {
+                                mService = null;
+                                mContext.unbindService(mConnection);
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    } else {
+                        synchronized (mConnection) {
+                            try {
+                                if (mService == null) {
+                                    if (VDBG) Log.d(TAG,"Binding service...");
+                                    if (!mContext.bindService(new Intent(IBluetoothInputDevice.class.getName()), mConnection, 0)) {
+                                        Log.e(TAG, "Could not bind to Bluetooth HID Service");
+                                    }
+                                }
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    }
+                }
+        };
 
     /**
      * Create a BluetoothInputDevice proxy object for interacting with the local
      * Bluetooth Service which handles the InputDevice profile
      *
      */
-    /*package*/ BluetoothInputDevice(Context mContext, ServiceListener l) {
-        IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
+    /*package*/ BluetoothInputDevice(Context context, ServiceListener l) {
+        mContext = context;
         mServiceListener = l;
         mAdapter = BluetoothAdapter.getDefaultAdapter();
-        if (b != null) {
-            mService = IBluetooth.Stub.asInterface(b);
-            if (mServiceListener != null) {
-                mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, this);
-            }
-        } else {
-            Log.w(TAG, "Bluetooth Service not available!");
 
-            // Instead of throwing an exception which prevents people from going
-            // into Wireless settings in the emulator. Let it crash later when it is actually used.
-            mService = null;
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG,"",e);
+            }
+        }
+
+        if (!context.bindService(new Intent(IBluetoothInputDevice.class.getName()),
+                                 mConnection, 0)) {
+            Log.e(TAG, "Could not bind to Bluetooth HID Service");
         }
     }
 
     /*package*/ void close() {
+        if (VDBG) log("close()");
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (Exception e) {
+                Log.e(TAG,"",e);
+            }
+        }
+
+        synchronized (mConnection) {
+            if (mService != null) {
+                try {
+                    mService = null;
+                    mContext.unbindService(mConnection);
+                } catch (Exception re) {
+                    Log.e(TAG,"",re);
+                }
+           }
+        }
         mServiceListener = null;
     }
 
@@ -144,10 +289,9 @@
      */
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        if (mService != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.connectInputDevice(device);
+                return mService.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
@@ -185,10 +329,9 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        if (mService != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.disconnectInputDevice(device);
+                return mService.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
@@ -202,10 +345,10 @@
      * {@inheritDoc}
      */
     public List<BluetoothDevice> getConnectedDevices() {
-        if (DBG) log("getConnectedDevices()");
+        if (VDBG) log("getConnectedDevices()");
         if (mService != null && isEnabled()) {
             try {
-                return mService.getConnectedInputDevices();
+                return mService.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
@@ -219,10 +362,10 @@
      * {@inheritDoc}
      */
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (DBG) log("getDevicesMatchingStates()");
+        if (VDBG) log("getDevicesMatchingStates()");
         if (mService != null && isEnabled()) {
             try {
-                return mService.getInputDevicesMatchingConnectionStates(states);
+                return mService.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
@@ -236,11 +379,10 @@
      * {@inheritDoc}
      */
     public int getConnectionState(BluetoothDevice device) {
-        if (DBG) log("getState(" + device + ")");
-        if (mService != null && isEnabled()
-            && isValidDevice(device)) {
+        if (VDBG) log("getState(" + device + ")");
+        if (mService != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getInputDeviceConnectionState(device);
+                return mService.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
@@ -267,14 +409,13 @@
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        if (mService != null && isEnabled()
-            && isValidDevice(device)) {
+        if (mService != null && isEnabled() && isValidDevice(device)) {
             if (priority != BluetoothProfile.PRIORITY_OFF &&
                 priority != BluetoothProfile.PRIORITY_ON) {
               return false;
             }
             try {
-                return mService.setInputDevicePriority(device, priority);
+                return mService.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
@@ -298,11 +439,10 @@
      * @hide
      */
     public int getPriority(BluetoothDevice device) {
-        if (DBG) log("getPriority(" + device + ")");
-        if (mService != null && isEnabled()
-            && isValidDevice(device)) {
+        if (VDBG) log("getPriority(" + device + ")");
+        if (mService != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getInputDevicePriority(device);
+                return mService.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.PRIORITY_OFF;
@@ -312,6 +452,24 @@
         return BluetoothProfile.PRIORITY_OFF;
     }
 
+    private ServiceConnection mConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            if (DBG) Log.d(TAG, "Proxy object connected");
+            mService = IBluetoothInputDevice.Stub.asInterface(service);
+
+            if (mServiceListener != null) {
+                mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, BluetoothInputDevice.this);
+            }
+        }
+        public void onServiceDisconnected(ComponentName className) {
+            if (DBG) Log.d(TAG, "Proxy object disconnected");
+            mService = null;
+            if (mServiceListener != null) {
+                mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_DEVICE);
+            }
+        }
+    };
+
     private boolean isEnabled() {
        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
        return false;
@@ -324,6 +482,158 @@
        return false;
     }
 
+
+    /**
+     * Initiate virtual unplug for a HID input device.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+     *
+     * @param device Remote Bluetooth Device
+     * @return false on immediate error,
+     *               true otherwise
+     * @hide
+     */
+    public boolean virtualUnplug(BluetoothDevice device) {
+        if (DBG) log("virtualUnplug(" + device + ")");
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return mService.virtualUnplug(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
+
+    }
+
+    /**
+    * Send Get_Protocol_Mode command to the connected HID input device.
+    *
+    * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+    *
+    * @param device Remote Bluetooth Device
+    * @return false on immediate error,
+    *true otherwise
+    * @hide
+    */
+    public boolean getProtocolMode(BluetoothDevice device) {
+        if (VDBG) log("getProtocolMode(" + device + ")");
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return mService.getProtocolMode(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+            return false;
+    }
+
+    /**
+     * Send Set_Protocol_Mode command to the connected HID input device.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+     *
+     * @param device Remote Bluetooth Device
+     * @return false on immediate error,
+     *               true otherwise
+     * @hide
+     */
+    public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
+        if (DBG) log("setProtocolMode(" + device + ")");
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return mService.setProtocolMode(device, protocolMode);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
+    }
+
+    /**
+     * Send Get_Report command to the connected HID input device.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+     *
+     * @param device Remote Bluetooth Device
+     * @param reportType Report type
+     * @param reportId Report ID
+     * @param bufferSize Report receiving buffer size
+     * @return false on immediate error,
+     *               true otherwise
+     * @hide
+     */
+    public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) {
+        if (VDBG) log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId + "bufferSize=" + bufferSize);
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return mService.getReport(device, reportType, reportId, bufferSize);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
+    }
+
+    /**
+     * Send Set_Report command to the connected HID input device.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+     *
+     * @param device Remote Bluetooth Device
+     * @param reportType Report type
+     * @param report Report receiving buffer size
+     * @return false on immediate error,
+     *               true otherwise
+     * @hide
+     */
+    public boolean setReport(BluetoothDevice device, byte reportType, String report) {
+        if (DBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return mService.setReport(device, reportType, report);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
+    }
+
+    /**
+     * Send Send_Data command to the connected HID input device.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+     *
+     * @param device Remote Bluetooth Device
+     * @param data Data to send
+     * @return false on immediate error,
+     *               true otherwise
+     * @hide
+     */
+    public boolean sendData(BluetoothDevice device, String report) {
+        if (DBG) log("sendData(" + device + "), report=" + report);
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return mService.sendData(device, report);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
+    }
     private static void log(String msg) {
       Log.d(TAG, msg);
     }
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 5d9d8be..e25ec86 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -18,7 +18,10 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -27,7 +30,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-
 /**
  * This class provides the APIs to control the Bluetooth Pan
  * Profile.
@@ -41,7 +43,8 @@
  */
 public final class BluetoothPan implements BluetoothProfile {
     private static final String TAG = "BluetoothPan";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
+    private static final boolean VDBG = false;
 
     /**
      * Intent used to broadcast the change in connection state of the Pan
@@ -76,15 +79,18 @@
      */
     public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE";
 
+    public static final int PAN_ROLE_NONE = 0;
     /**
      * The local device is acting as a Network Access Point.
      */
     public static final int LOCAL_NAP_ROLE = 1;
+    public static final int REMOTE_NAP_ROLE = 1;
 
     /**
      * The local device is acting as a PAN User.
      */
     public static final int LOCAL_PANU_ROLE = 2;
+    public static final int REMOTE_PANU_ROLE = 2;
 
     /**
      * Return codes for the connect and disconnect Bluez / Dbus calls.
@@ -112,37 +118,77 @@
      */
     public static final int PAN_OPERATION_SUCCESS = 1004;
 
+    private Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
-    private IBluetooth mService;
+    private IBluetoothPan mPanService;
 
     /**
      * Create a BluetoothPan proxy object for interacting with the local
      * Bluetooth Service which handles the Pan profile
      *
      */
-    /*package*/ BluetoothPan(Context mContext, ServiceListener l) {
-        IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
+    /*package*/ BluetoothPan(Context context, ServiceListener l) {
+        mContext = context;
         mServiceListener = l;
         mAdapter = BluetoothAdapter.getDefaultAdapter();
-        if (b != null) {
-            mService = IBluetooth.Stub.asInterface(b);
-            if (mServiceListener != null) {
-                mServiceListener.onServiceConnected(BluetoothProfile.PAN, this);
-            }
-        } else {
-            Log.w(TAG, "Bluetooth Service not available!");
-
-            // Instead of throwing an exception which prevents people from going
-            // into Wireless settings in the emulator. Let it crash later when it is actually used.
-            mService = null;
+        try {
+            mAdapter.getBluetoothManager().registerStateChangeCallback(mStateChangeCallback);
+        } catch (RemoteException re) {
+            Log.w(TAG,"Unable to register BluetoothStateChangeCallback",re);
         }
+        Log.d(TAG, "BluetoothPan() call bindService");
+        if (!context.bindService(new Intent(IBluetoothPan.class.getName()),
+                                 mConnection, 0)) {
+            Log.e(TAG, "Could not bind to Bluetooth HID Service");
+        }
+        Log.d(TAG, "BluetoothPan(), bindService called");
     }
 
     /*package*/ void close() {
+        if (VDBG) log("close()");
+        if (mConnection != null) {
+            mContext.unbindService(mConnection);
+            mConnection = null;
+        }
         mServiceListener = null;
+        try {
+            mAdapter.getBluetoothManager().unregisterStateChangeCallback(mStateChangeCallback);
+        } catch (RemoteException re) {
+            Log.w(TAG,"Unable to register BluetoothStateChangeCallback",re);
+        }
     }
 
+    protected void finalize() {
+        close();
+    }
+
+    private IBluetoothStateChangeCallback mStateChangeCallback = new IBluetoothStateChangeCallback.Stub() {
+
+        @Override
+        public void onBluetoothStateChange(boolean on) throws RemoteException {
+            //Handle enable request to bind again.
+            if (on) {
+                Log.d(TAG, "onBluetoothStateChange(on) call bindService");
+                if (!mContext.bindService(new Intent(IBluetoothPan.class.getName()),
+                                     mConnection, 0)) {
+                    Log.e(TAG, "Could not bind to Bluetooth HID Service");
+                }
+                Log.d(TAG, "BluetoothPan(), bindService called");
+            } else {
+                if (VDBG) Log.d(TAG,"Unbinding service...");
+                synchronized (mConnection) {
+                    try {
+                        mPanService = null;
+                        mContext.unbindService(mConnection);
+                    } catch (Exception re) {
+                        Log.e(TAG,"",re);
+                    }
+                }
+            }
+        }
+    };
+
     /**
      * Initiate connection to a profile of the remote bluetooth device.
      *
@@ -163,16 +209,16 @@
      */
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
-        if (mService != null && isEnabled() &&
+        if (mPanService != null && isEnabled() &&
             isValidDevice(device)) {
             try {
-                return mService.connectPanDevice(device);
+                return mPanService.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -204,16 +250,16 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mService != null && isEnabled() &&
+        if (mPanService != null && isEnabled() &&
             isValidDevice(device)) {
             try {
-                return mService.disconnectPanDevice(device);
+                return mPanService.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -221,16 +267,16 @@
      * {@inheritDoc}
      */
     public List<BluetoothDevice> getConnectedDevices() {
-        if (DBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        if (VDBG) log("getConnectedDevices()");
+        if (mPanService != null && isEnabled()) {
             try {
-                return mService.getConnectedPanDevices();
+                return mPanService.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -238,16 +284,16 @@
      * {@inheritDoc}
      */
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (DBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        if (VDBG) log("getDevicesMatchingStates()");
+        if (mPanService != null && isEnabled()) {
             try {
-                return mService.getPanDevicesMatchingConnectionStates(states);
+                return mPanService.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -255,39 +301,58 @@
      * {@inheritDoc}
      */
     public int getConnectionState(BluetoothDevice device) {
-        if (DBG) log("getState(" + device + ")");
-        if (mService != null && isEnabled()
+        if (VDBG) log("getState(" + device + ")");
+        if (mPanService != null && isEnabled()
             && isValidDevice(device)) {
             try {
-                return mService.getPanDeviceConnectionState(device);
+                return mPanService.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
     public void setBluetoothTethering(boolean value) {
         if (DBG) log("setBluetoothTethering(" + value + ")");
         try {
-            mService.setBluetoothTethering(value);
+            mPanService.setBluetoothTethering(value);
         } catch (RemoteException e) {
             Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
         }
     }
 
     public boolean isTetheringOn() {
-        if (DBG) log("isTetheringOn()");
+        if (VDBG) log("isTetheringOn()");
         try {
-            return mService.isTetheringOn();
+            return mPanService.isTetheringOn();
         } catch (RemoteException e) {
             Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
-            return false;
         }
+        return false;
     }
 
+    private ServiceConnection mConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            if (DBG) Log.d(TAG, "BluetoothPAN Proxy object connected");
+            mPanService = IBluetoothPan.Stub.asInterface(service);
+
+            if (mServiceListener != null) {
+                mServiceListener.onServiceConnected(BluetoothProfile.PAN,
+                                                    BluetoothPan.this);
+            }
+        }
+        public void onServiceDisconnected(ComponentName className) {
+            if (DBG) Log.d(TAG, "BluetoothPAN Proxy object disconnected");
+            mPanService = null;
+            if (mServiceListener != null) {
+                mServiceListener.onServiceDisconnected(BluetoothProfile.PAN);
+            }
+        }
+    };
+
     private boolean isEnabled() {
        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
        return false;
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
old mode 100644
new mode 100755
index 639ae1a..b5280e5
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -51,7 +51,8 @@
 public class BluetoothPbap {
 
     private static final String TAG = "BluetoothPbap";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
+    private static final boolean VDBG = false;
 
     /** int extra for PBAP_STATE_CHANGED_ACTION */
     public static final String PBAP_STATE =
@@ -70,6 +71,7 @@
     private IBluetoothPbap mService;
     private final Context mContext;
     private ServiceListener mServiceListener;
+    private BluetoothAdapter mAdapter;
 
     /** There was an error trying to obtain the state */
     public static final int STATE_ERROR        = -1;
@@ -96,7 +98,7 @@
          * this callback before making IPC calls on the BluetoothPbap
          * service.
          */
-        public void onServiceConnected();
+        public void onServiceConnected(BluetoothPbap proxy);
 
         /**
          * Called to notify the client that this proxy object has been
@@ -108,12 +110,54 @@
         public void onServiceDisconnected();
     }
 
+    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+            new IBluetoothStateChangeCallback.Stub() {
+                public void onBluetoothStateChange(boolean up) {
+                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
+                    if (!up) {
+                        if (VDBG) Log.d(TAG,"Unbinding service...");
+                        synchronized (mConnection) {
+                            try {
+                                mService = null;
+                                mContext.unbindService(mConnection);
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    } else {
+                        synchronized (mConnection) {
+                            try {
+                                if (mService == null) {
+                                    if (VDBG) Log.d(TAG,"Binding service...");
+                                    if (!mContext.bindService(
+                                                        new Intent(IBluetoothPbap.class.getName()),
+                                                        mConnection, 0)) {
+                                        Log.e(TAG, "Could not bind to Bluetooth PBAP Service");
+                                    }
+                                }
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    }
+                }
+        };
+
     /**
      * Create a BluetoothPbap proxy object.
      */
     public BluetoothPbap(Context context, ServiceListener l) {
         mContext = context;
         mServiceListener = l;
+        mAdapter = BluetoothAdapter.getDefaultAdapter();
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG,"",e);
+            }
+        }
         if (!context.bindService(new Intent(IBluetoothPbap.class.getName()), mConnection, 0)) {
             Log.e(TAG, "Could not bind to Bluetooth Pbap Service");
         }
@@ -134,9 +178,25 @@
      * are ok.
      */
     public synchronized void close() {
-        if (mConnection != null) {
-            mContext.unbindService(mConnection);
-            mConnection = null;
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (Exception e) {
+                Log.e(TAG,"",e);
+            }
+        }
+
+        synchronized (mConnection) {
+            if (mService != null) {
+                try {
+                    mService = null;
+                    mContext.unbindService(mConnection);
+                    mConnection = null;
+                } catch (Exception re) {
+                    Log.e(TAG,"",re);
+                }
+            }
         }
         mServiceListener = null;
     }
@@ -147,7 +207,7 @@
      *         object is currently not connected to the Pbap service.
      */
     public int getState() {
-        if (DBG) log("getState()");
+        if (VDBG) log("getState()");
         if (mService != null) {
             try {
                 return mService.getState();
@@ -166,7 +226,7 @@
      *         the Pbap service.
      */
     public BluetoothDevice getClient() {
-        if (DBG) log("getClient()");
+        if (VDBG) log("getClient()");
         if (mService != null) {
             try {
                 return mService.getClient();
@@ -184,7 +244,7 @@
      * object is not currently connected to the Pbap service.
      */
     public boolean isConnected(BluetoothDevice device) {
-        if (DBG) log("isConnected(" + device + ")");
+        if (VDBG) log("isConnected(" + device + ")");
         if (mService != null) {
             try {
                 return mService.isConnected(device);
@@ -240,7 +300,7 @@
             if (DBG) log("Proxy object connected");
             mService = IBluetoothPbap.Stub.asInterface(service);
             if (mServiceListener != null) {
-                mServiceListener.onServiceConnected();
+                mServiceListener.onServiceConnected(BluetoothPbap.this);
             }
         }
         public void onServiceDisconnected(ComponentName className) {
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
old mode 100644
new mode 100755
diff --git a/core/java/android/bluetooth/BluetoothProfileState.java b/core/java/android/bluetooth/BluetoothProfileState.java
deleted file mode 100644
index b0c0a0b..0000000
--- a/core/java/android/bluetooth/BluetoothProfileState.java
+++ /dev/null
@@ -1,160 +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.
- */
-package android.bluetooth;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Message;
-import android.util.Log;
-
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-
-/**
- * This state machine is used to serialize the connections
- * to a particular profile. Currently, we only allow one device
- * to be connected to a particular profile.
- * States:
- *      {@link StableState} : No pending commands. Send the
- *      command to the appropriate remote device specific state machine.
- *
- *      {@link PendingCommandState} : A profile connection / disconnection
- *      command is being executed. This will result in a profile state
- *      change. Defer all commands.
- * @hide
- */
-
-public class BluetoothProfileState extends StateMachine {
-    private static final boolean DBG = true;
-    private static final String TAG = "BluetoothProfileState";
-
-    public static final int HFP = 0;
-    public static final int A2DP = 1;
-    public static final int HID = 2;
-
-    static final int TRANSITION_TO_STABLE = 100;
-
-    private int mProfile;
-    private BluetoothDevice mPendingDevice;
-    private PendingCommandState mPendingCommandState = new PendingCommandState();
-    private StableState mStableState = new StableState();
-
-    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-            if (device == null) {
-                return;
-            }
-            if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
-                int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
-                if (mProfile == HFP && (newState == BluetoothProfile.STATE_CONNECTED ||
-                    newState == BluetoothProfile.STATE_DISCONNECTED)) {
-                    sendMessage(TRANSITION_TO_STABLE);
-                }
-            } else if (action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) {
-                int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
-                if (mProfile == A2DP && (newState == BluetoothProfile.STATE_CONNECTED ||
-                    newState == BluetoothProfile.STATE_DISCONNECTED)) {
-                    sendMessage(TRANSITION_TO_STABLE);
-                }
-            } else if (action.equals(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED)) {
-                int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
-                if (mProfile == HID && (newState == BluetoothProfile.STATE_CONNECTED ||
-                    newState == BluetoothProfile.STATE_DISCONNECTED)) {
-                    sendMessage(TRANSITION_TO_STABLE);
-                }
-            } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
-                if (device.equals(mPendingDevice)) {
-                    sendMessage(TRANSITION_TO_STABLE);
-                }
-            }
-        }
-    };
-
-    public BluetoothProfileState(Context context, int profile) {
-        super("BluetoothProfileState:" + profile);
-        mProfile = profile;
-        addState(mStableState);
-        addState(mPendingCommandState);
-        setInitialState(mStableState);
-
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
-        context.registerReceiver(mBroadcastReceiver, filter);
-    }
-
-    private class StableState extends State {
-        @Override
-        public void enter() {
-            log("Entering Stable State");
-            mPendingDevice = null;
-        }
-
-        @Override
-        public boolean processMessage(Message msg) {
-            if (msg.what != TRANSITION_TO_STABLE) {
-                transitionTo(mPendingCommandState);
-            }
-            return true;
-        }
-    }
-
-    private class PendingCommandState extends State {
-        @Override
-        public void enter() {
-            log("Entering PendingCommandState State");
-            dispatchMessage(getCurrentMessage());
-        }
-
-        @Override
-        public boolean processMessage(Message msg) {
-            if (msg.what == TRANSITION_TO_STABLE) {
-                transitionTo(mStableState);
-            } else {
-                dispatchMessage(msg);
-            }
-            return true;
-        }
-
-        private void dispatchMessage(Message msg) {
-            BluetoothDeviceProfileState deviceProfileMgr =
-              (BluetoothDeviceProfileState)msg.obj;
-            int cmd = msg.arg1;
-            if (mPendingDevice == null || mPendingDevice.equals(deviceProfileMgr.getDevice())) {
-                mPendingDevice = deviceProfileMgr.getDevice();
-                deviceProfileMgr.sendMessage(cmd);
-            } else {
-                Message deferMsg = new Message();
-                deferMsg.arg1 = cmd;
-                deferMsg.obj = deviceProfileMgr;
-                deferMessage(deferMsg);
-            }
-        }
-    }
-
-    private void log(String message) {
-        if (DBG) {
-            Log.i(TAG, "Message:" + message);
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index 4021f7b..96be8a2 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -17,6 +17,8 @@
 package android.bluetooth;
 
 import android.os.Handler;
+import android.os.Message;
+import android.os.ParcelUuid;
 
 import java.io.Closeable;
 import java.io.IOException;
@@ -86,6 +88,22 @@
     }
 
     /**
+     * Construct a socket for incoming connections.
+     * @param type    type of socket
+     * @param auth    require the remote device to be authenticated
+     * @param encrypt require the connection to be encrypted
+     * @param uuid    uuid
+     * @throws IOException On error, for example Bluetooth not available, or
+     *                     insufficient privileges
+     */
+    /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, ParcelUuid uuid)
+            throws IOException {
+        mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, -1, uuid);
+        mChannel = mSocket.getPort();
+    }
+
+
+    /**
      * Block until a connection is established.
      * <p>Returns a connected {@link BluetoothSocket} on successful connection.
      * <p>Once this call returns, it can be called again to accept subsequent
@@ -133,7 +151,9 @@
         mHandler = handler;
         mMessage = message;
     }
-
+    /*package*/ void setServiceName(String ServiceName) {
+        mSocket.setServiceName(ServiceName);
+    }
     /**
      * Returns the channel on which this socket is bound.
      * @hide
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 19d13ef..26bde19 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 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.
@@ -16,17 +16,25 @@
 
 package android.bluetooth;
 
-import android.bluetooth.IBluetoothCallback;
+import android.os.IBinder;
 import android.os.ParcelUuid;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.util.Log;
 
 import java.io.Closeable;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
+import java.util.List;
+import java.util.UUID;
+import android.net.LocalSocket;
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
 /**
  * A connected or connecting Bluetooth socket.
  *
@@ -77,6 +85,8 @@
  */
 public final class BluetoothSocket implements Closeable {
     private static final String TAG = "BluetoothSocket";
+    private static final boolean DBG = true;
+    private static final boolean VDBG = false;
 
     /** @hide */
     public static final int MAX_RFCOMM_CHANNEL = 30;
@@ -89,31 +99,40 @@
     /*package*/ static final int EBADFD = 77;
     /*package*/ static final int EADDRINUSE = 98;
 
+    /*package*/ static final int SEC_FLAG_ENCRYPT = 1;
+    /*package*/ static final int SEC_FLAG_AUTH = 1 << 1;
+
     private final int mType;  /* one of TYPE_RFCOMM etc */
-    private final BluetoothDevice mDevice;    /* remote device */
-    private final String mAddress;    /* remote address */
+    private BluetoothDevice mDevice;    /* remote device */
+    private String mAddress;    /* remote address */
     private final boolean mAuth;
     private final boolean mEncrypt;
     private final BluetoothInputStream mInputStream;
     private final BluetoothOutputStream mOutputStream;
-    private final SdpHelper mSdp;
-
+    private final ParcelUuid mUuid;
+    private ParcelFileDescriptor mPfd;
+    private LocalSocket mSocket;
+    private InputStream mSocketIS;
+    private OutputStream mSocketOS;
     private int mPort;  /* RFCOMM channel or L2CAP psm */
+    private int mFd;
+    private String mServiceName;
+    private static int PROXY_CONNECTION_TIMEOUT = 5000;
+
+    private static int SOCK_SIGNAL_SIZE = 16;
 
     private enum SocketState {
         INIT,
         CONNECTED,
-        CLOSED
+        LISTENING,
+        CLOSED,
     }
 
     /** prevents all native calls after destroyNative() */
-    private SocketState mSocketState;
+    private volatile SocketState mSocketState;
 
     /** protects mSocketState */
-    private final ReentrantReadWriteLock mLock;
-
-    /** used by native code only */
-    private int mSocketData;
+    //private final ReentrantReadWriteLock mLock;
 
     /**
      * Construct a BluetoothSocket.
@@ -134,33 +153,54 @@
                 throw new IOException("Invalid RFCOMM channel: " + port);
             }
         }
-        if (uuid == null) {
-            mPort = port;
-            mSdp = null;
-        } else {
-            mSdp = new SdpHelper(device, uuid);
-            mPort = -1;
-        }
+        if(uuid != null)
+            mUuid = uuid;
+        else mUuid = new ParcelUuid(new UUID(0, 0));
         mType = type;
         mAuth = auth;
         mEncrypt = encrypt;
         mDevice = device;
+        mPort = port;
+        mFd = fd;
+
+        mSocketState = SocketState.INIT;
+
         if (device == null) {
-            mAddress = null;
+            // Server socket
+            mAddress = BluetoothAdapter.getDefaultAdapter().getAddress();
         } else {
+            // Remote socket
             mAddress = device.getAddress();
         }
-        if (fd == -1) {
-            initSocketNative();
-        } else {
-            initSocketFromFdNative(fd);
-        }
         mInputStream = new BluetoothInputStream(this);
         mOutputStream = new BluetoothOutputStream(this);
-        mSocketState = SocketState.INIT;
-        mLock = new ReentrantReadWriteLock();
     }
-
+    private BluetoothSocket(BluetoothSocket s) {
+        mUuid = s.mUuid;
+        mType = s.mType;
+        mAuth = s.mAuth;
+        mEncrypt = s.mEncrypt;
+        mPort = s.mPort;
+        mInputStream = new BluetoothInputStream(this);
+        mOutputStream = new BluetoothOutputStream(this);
+        mServiceName = s.mServiceName;
+    }
+    private BluetoothSocket acceptSocket(String RemoteAddr) throws IOException {
+        BluetoothSocket as = new BluetoothSocket(this);
+        as.mSocketState = SocketState.CONNECTED;
+        FileDescriptor[] fds = mSocket.getAncillaryFileDescriptors();
+        if (VDBG) Log.d(TAG, "socket fd passed by stack  fds: " + fds);
+        if(fds == null || fds.length != 1) {
+            Log.e(TAG, "socket fd passed from stack failed, fds: " + fds);
+            throw new IOException("bt socket acept failed");
+        }
+        as.mSocket = new LocalSocket(fds[0]);
+        as.mSocketIS = as.mSocket.getInputStream();
+        as.mSocketOS = as.mSocket.getOutputStream();
+        as.mAddress = RemoteAddr;
+        as.mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(RemoteAddr);
+        return as;
+    }
     /**
      * Construct a BluetoothSocket from address. Used by native code.
      * @param type    type of socket
@@ -186,67 +226,13 @@
             super.finalize();
         }
     }
-
-    /**
-     * Attempt to connect to a remote device.
-     * <p>This method will block until a connection is made or the connection
-     * fails. If this method returns without an exception then this socket
-     * is now connected.
-     * <p>Creating new connections to
-     * remote Bluetooth devices should not be attempted while device discovery
-     * is in progress. Device discovery is a heavyweight procedure on the
-     * Bluetooth adapter and will significantly slow a device connection.
-     * Use {@link BluetoothAdapter#cancelDiscovery()} to cancel an ongoing
-     * discovery. Discovery is not managed by the Activity,
-     * but is run as a system service, so an application should always call
-     * {@link BluetoothAdapter#cancelDiscovery()} even if it
-     * did not directly request a discovery, just to be sure.
-     * <p>{@link #close} can be used to abort this call from another thread.
-     * @throws IOException on error, for example connection failure
-     */
-    public void connect() throws IOException {
-        mLock.readLock().lock();
-        try {
-            if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
-
-            if (mSdp != null) {
-                mPort = mSdp.doSdp();  // blocks
-            }
-
-            connectNative();  // blocks
-            mSocketState = SocketState.CONNECTED;
-        } finally {
-            mLock.readLock().unlock();
-        }
-    }
-
-    /**
-     * Immediately close this socket, and release all associated resources.
-     * <p>Causes blocked calls on this socket in other threads to immediately
-     * throw an IOException.
-     */
-    public void close() throws IOException {
-        // abort blocking operations on the socket
-        mLock.readLock().lock();
-        try {
-            if (mSocketState == SocketState.CLOSED) return;
-            if (mSdp != null) {
-                mSdp.cancel();
-            }
-            abortNative();
-        } finally {
-            mLock.readLock().unlock();
-        }
-
-        // all native calls are guaranteed to immediately return after
-        // abortNative(), so this lock should immediately acquire
-        mLock.writeLock().lock();
-        try {
-            mSocketState = SocketState.CLOSED;
-            destroyNative();
-        } finally {
-            mLock.writeLock().unlock();
-        }
+    private int getSecurityFlags() {
+        int flags = 0;
+        if(mAuth)
+            flags |= SEC_FLAG_AUTH;
+        if(mEncrypt)
+            flags |= SEC_FLAG_ENCRYPT;
+        return flags;
     }
 
     /**
@@ -286,7 +272,64 @@
      *         false if not connected
      */
     public boolean isConnected() {
-        return (mSocketState == SocketState.CONNECTED);
+        return mSocketState == SocketState.CONNECTED;
+    }
+
+    /*package*/ void setServiceName(String name) {
+        mServiceName = name;
+    }
+
+    /**
+     * Attempt to connect to a remote device.
+     * <p>This method will block until a connection is made or the connection
+     * fails. If this method returns without an exception then this socket
+     * is now connected.
+     * <p>Creating new connections to
+     * remote Bluetooth devices should not be attempted while device discovery
+     * is in progress. Device discovery is a heavyweight procedure on the
+     * Bluetooth adapter and will significantly slow a device connection.
+     * Use {@link BluetoothAdapter#cancelDiscovery()} to cancel an ongoing
+     * discovery. Discovery is not managed by the Activity,
+     * but is run as a system service, so an application should always call
+     * {@link BluetoothAdapter#cancelDiscovery()} even if it
+     * did not directly request a discovery, just to be sure.
+     * <p>{@link #close} can be used to abort this call from another thread.
+     * @throws IOException on error, for example connection failure
+     */
+    public void connect() throws IOException {
+        if (mDevice == null) throw new IOException("Connect is called on null device");
+
+        try {
+            // TODO(BT) derive flag from auth and encrypt
+            if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
+            IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null);
+            if (bluetoothProxy == null) throw new IOException("Bluetooth is off");
+            mPfd = bluetoothProxy.connectSocket(mDevice, mType,
+                    mUuid, mPort, getSecurityFlags());
+            synchronized(this)
+            {
+                if (DBG) Log.d(TAG, "connect(), SocketState: " + mSocketState + ", mPfd: " + mPfd);
+                if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
+                if (mPfd == null) throw new IOException("bt socket connect failed");
+                FileDescriptor fd = mPfd.getFileDescriptor();
+                mSocket = new LocalSocket(fd);
+                mSocketIS = mSocket.getInputStream();
+                mSocketOS = mSocket.getOutputStream();
+            }
+            int channel = readInt(mSocketIS);
+            if (channel <= 0)
+                throw new IOException("bt socket connect failed");
+            mPort = channel;
+            waitSocketSignal(mSocketIS);
+            synchronized(this)
+            {
+                if (mSocketState == SocketState.CLOSED)
+                    throw new IOException("bt socket closed");
+                mSocketState = SocketState.CONNECTED;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, Log.getStackTraceString(new Throwable()));
+        }
     }
 
     /**
@@ -294,129 +337,171 @@
      * so that BluetoothAdapter can check the error code for EADDRINUSE
      */
     /*package*/ int bindListen() {
-        mLock.readLock().lock();
-        try {
-            if (mSocketState == SocketState.CLOSED) return EBADFD;
-            return bindListenNative();
-        } finally {
-            mLock.readLock().unlock();
+        int ret;
+        if (mSocketState == SocketState.CLOSED) return EBADFD;
+        IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null);
+        if (bluetoothProxy == null) {
+            Log.e(TAG, "bindListen fail, reason: bluetooth is off");
+            return -1;
         }
+        try {
+            mPfd = bluetoothProxy.createSocketChannel(mType, mServiceName,
+                    mUuid, mPort, getSecurityFlags());
+        } catch (RemoteException e) {
+            Log.e(TAG, Log.getStackTraceString(new Throwable()));
+            // TODO(BT) right error code?
+            return -1;
+        }
+
+        // read out port number
+        try {
+            synchronized(this) {
+                if (VDBG) Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " +
+                                mPfd);
+                if(mSocketState != SocketState.INIT) return EBADFD;
+                if(mPfd == null) return -1;
+                FileDescriptor fd = mPfd.getFileDescriptor();
+                if (VDBG) Log.d(TAG, "bindListen(), new LocalSocket ");
+                mSocket = new LocalSocket(fd);
+                if (VDBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream() ");
+                mSocketIS = mSocket.getInputStream();
+                mSocketOS = mSocket.getOutputStream();
+            }
+            if (VDBG) Log.d(TAG, "bindListen(), readInt mSocketIS: " + mSocketIS);
+            int channel = readInt(mSocketIS);
+            synchronized(this) {
+                if(mSocketState == SocketState.INIT)
+                    mSocketState = SocketState.LISTENING;
+            }
+            if (VDBG) Log.d(TAG, "channel: " + channel);
+            if (mPort == -1) {
+                mPort = channel;
+            } // else ASSERT(mPort == channel)
+            ret = 0;
+        } catch (IOException e) {
+            Log.e(TAG, "bindListen, fail to get port number, exception: " + e);
+            return -1;
+        }
+        return ret;
     }
 
     /*package*/ BluetoothSocket accept(int timeout) throws IOException {
-        mLock.readLock().lock();
-        try {
-            if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
-
-            BluetoothSocket acceptedSocket = acceptNative(timeout);
-            mSocketState = SocketState.CONNECTED;
-            return acceptedSocket;
-        } finally {
-            mLock.readLock().unlock();
+        BluetoothSocket acceptedSocket;
+        if (mSocketState != SocketState.LISTENING) throw new IOException("bt socket is not in listen state");
+        // TODO(BT) wait on an incoming connection
+        String RemoteAddr = waitSocketSignal(mSocketIS);
+        synchronized(this)
+        {
+            if (mSocketState != SocketState.LISTENING)
+                throw new IOException("bt socket is not in listen state");
+            acceptedSocket = acceptSocket(RemoteAddr);
+            //quick drop the reference of the file handle
         }
+        // TODO(BT) rfcomm socket only supports one connection, return this?
+        // return this;
+        return acceptedSocket;
     }
 
     /*package*/ int available() throws IOException {
-        mLock.readLock().lock();
-        try {
-            if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
-            return availableNative();
-        } finally {
-            mLock.readLock().unlock();
-        }
+        if (VDBG) Log.d(TAG, "available: " + mSocketIS);
+        return mSocketIS.available();
     }
 
     /*package*/ int read(byte[] b, int offset, int length) throws IOException {
-        mLock.readLock().lock();
-        try {
-            if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
-            return readNative(b, offset, length);
-        } finally {
-            mLock.readLock().unlock();
-        }
+
+            if (VDBG) Log.d(TAG, "read in:  " + mSocketIS + " len: " + length);
+            int ret = mSocketIS.read(b, offset, length);
+            if(ret < 0)
+                throw new IOException("bt socket closed, read return: " + ret);
+            if (VDBG) Log.d(TAG, "read out:  " + mSocketIS + " ret: " + ret);
+            return ret;
     }
 
     /*package*/ int write(byte[] b, int offset, int length) throws IOException {
-        mLock.readLock().lock();
-        try {
-            if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
-            return writeNative(b, offset, length);
-        } finally {
-            mLock.readLock().unlock();
-        }
+
+            if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length);
+            mSocketOS.write(b, offset, length);
+            // There is no good way to confirm since the entire process is asynchronous anyway
+            if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length);
+            return length;
     }
 
-    private native void initSocketNative() throws IOException;
-    private native void initSocketFromFdNative(int fd) throws IOException;
-    private native void connectNative() throws IOException;
-    private native int bindListenNative();
-    private native BluetoothSocket acceptNative(int timeout) throws IOException;
-    private native int availableNative() throws IOException;
-    private native int readNative(byte[] b, int offset, int length) throws IOException;
-    private native int writeNative(byte[] b, int offset, int length) throws IOException;
-    private native void abortNative() throws IOException;
-    private native void destroyNative() throws IOException;
-    /**
-     * Throws an IOException for given posix errno. Done natively so we can
-     * use strerr to convert to string error.
-     */
-    /*package*/ native void throwErrnoNative(int errno) throws IOException;
-
-    /**
-     * Helper to perform blocking SDP lookup.
-     */
-    private static class SdpHelper extends IBluetoothCallback.Stub {
-        private final IBluetooth service;
-        private final ParcelUuid uuid;
-        private final BluetoothDevice device;
-        private int channel;
-        private boolean canceled;
-        public SdpHelper(BluetoothDevice device, ParcelUuid uuid) {
-            service = BluetoothDevice.getService();
-            this.device = device;
-            this.uuid = uuid;
-            canceled = false;
+    @Override
+    public void close() throws IOException {
+        Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: " + mSocketState);
+        if(mSocketState == SocketState.CLOSED)
+            return;
+        else
+        {
+            synchronized(this)
+            {
+                 if(mSocketState == SocketState.CLOSED)
+                    return;
+                 mSocketState = SocketState.CLOSED;
+                 if (VDBG) Log.d(TAG, "close() this: " + this + ", channel: " + mPort + ", mSocketIS: " + mSocketIS +
+                        ", mSocketOS: " + mSocketOS + "mSocket: " + mSocket);
+                 if(mSocket != null) {
+                    if (VDBG) Log.d(TAG, "Closing mSocket: " + mSocket);
+                    mSocket.shutdownInput();
+                    mSocket.shutdownOutput();
+                    mSocket.close();
+                    mSocket = null;
+                }
+                if(mPfd != null)
+                    mPfd.detachFd();
+           }
         }
-        /**
-         * Returns the RFCOMM channel for the UUID, or throws IOException
-         * on failure.
-         */
-        public synchronized int doSdp() throws IOException {
-            if (canceled) throw new IOException("Service discovery canceled");
-            channel = -1;
+        // TODO(BT) unbind proxy,
+    }
 
-            boolean inProgress = false;
-            try {
-                inProgress = service.fetchRemoteUuids(device.getAddress(), uuid, this);
-            } catch (RemoteException e) {Log.e(TAG, "", e);}
+    /*package */ void removeChannel() {
+    }
 
-            if (!inProgress) throw new IOException("Unable to start Service Discovery");
-
-            try {
-                /* 12 second timeout as a precaution - onRfcommChannelFound
-                 * should always occur before the timeout */
-                wait(12000);   // block
-
-            } catch (InterruptedException e) {}
-
-            if (canceled) throw new IOException("Service discovery canceled");
-            if (channel < 1) throw new IOException("Service discovery failed");
-
-            return channel;
+    /*package */ int getPort() {
+        return mPort;
+    }
+    private String convertAddr(final byte[] addr)  {
+        return String.format("%02X:%02X:%02X:%02X:%02X:%02X",
+                addr[0] , addr[1], addr[2], addr[3] , addr[4], addr[5]);
+    }
+    private String waitSocketSignal(InputStream is) throws IOException {
+        byte [] sig = new byte[SOCK_SIGNAL_SIZE];
+        int ret = readAll(is, sig);
+        if (VDBG) Log.d(TAG, "waitSocketSignal read 16 bytes signal ret: " + ret);
+        ByteBuffer bb = ByteBuffer.wrap(sig);
+        bb.order(ByteOrder.nativeOrder());
+        int size = bb.getShort();
+        byte [] addr = new byte[6];
+        bb.get(addr);
+        int channel = bb.getInt();
+        int status = bb.getInt();
+        String RemoteAddr = convertAddr(addr);
+        if (VDBG) Log.d(TAG, "waitSocketSignal: sig size: " + size + ", remote addr: "
+                + RemoteAddr + ", channel: " + channel + ", status: " + status);
+        if(status != 0)
+            throw new IOException("Connection failure, status: " + status);
+        return RemoteAddr;
+    }
+    private int readAll(InputStream is, byte[] b) throws IOException {
+        int left = b.length;
+        while(left > 0) {
+            int ret = is.read(b, b.length - left, left);
+            if(ret <= 0)
+                 throw new IOException("read failed, socket might closed, read ret: " + ret);
+            left -= ret;
+            if(left != 0)
+                Log.w(TAG, "readAll() looping, read partial size: " + (b.length - left) +
+                            ", expect size: " + b.length);
         }
-        /** Object cannot be re-used after calling cancel() */
-        public synchronized void cancel() {
-            if (!canceled) {
-                canceled = true;
-                channel = -1;
-                notifyAll();  // unblock
-            }
-        }
-        public synchronized void onRfcommChannelFound(int channel) {
-            if (!canceled) {
-                this.channel = channel;
-                notifyAll();  // unblock
-            }
-        }
+        return b.length;
+    }
+
+    private int readInt(InputStream is) throws IOException {
+        byte[] ibytes = new byte[4];
+        int ret = readAll(is, ibytes);
+        if (VDBG) Log.d(TAG, "inputStream.read ret: " + ret);
+        ByteBuffer bb = ByteBuffer.wrap(ibytes);
+        bb.order(ByteOrder.nativeOrder());
+        return bb.getInt();
     }
 }
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
index 83d1bda..063e5a8 100644
--- a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
+++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
@@ -16,6 +16,9 @@
 
 package android.bluetooth;
 
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.os.INetworkManagementService;
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.DhcpInfoInternal;
@@ -28,6 +31,11 @@
 import android.os.Handler;
 import android.os.Message;
 import android.util.Log;
+import java.net.InterfaceAddress;
+import android.net.LinkAddress;
+import android.net.RouteInfo;
+import java.net.Inet4Address;
+import android.os.SystemProperties;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -43,6 +51,8 @@
 public class BluetoothTetheringDataTracker implements NetworkStateTracker {
     private static final String NETWORKTYPE = "BLUETOOTH_TETHER";
     private static final String TAG = "BluetoothTethering";
+    private static final boolean DBG = true;
+    private static final boolean VDBG = false;
 
     private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
     private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
@@ -54,9 +64,8 @@
     private NetworkInfo mNetworkInfo;
 
     private BluetoothPan mBluetoothPan;
-    private BluetoothDevice mDevice;
     private static String mIface;
-
+    private Thread mDhcpThread;
     /* For sending events to connectivity service handler */
     private Handler mCsHandler;
     private Context mContext;
@@ -92,8 +101,10 @@
      * Begin monitoring connectivity
      */
     public void startMonitoring(Context context, Handler target) {
+        if (DBG) Log.d(TAG, "startMonitoring: target: " + target);
         mContext = context;
         mCsHandler = target;
+        if (VDBG) Log.d(TAG, "startMonitoring: mCsHandler: " + mCsHandler);
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
         if (adapter != null) {
             adapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.PAN);
@@ -124,6 +135,11 @@
         return true;
     }
 
+    @Override
+    public void captivePortalCheckComplete() {
+        // not implemented
+    }
+
     /**
      * Re-enable connectivity to a network after a {@link #teardown()}.
      */
@@ -259,38 +275,91 @@
         return "net.tcp.buffersize.wifi";
     }
 
+    private static short countPrefixLength(byte [] mask) {
+        short count = 0;
+        for (byte b : mask) {
+            for (int i = 0; i < 8; ++i) {
+                if ((b & (1 << i)) != 0) {
+                    ++count;
+                }
+            }
+        }
+        return count;
+    }
 
-    public synchronized void startReverseTether(String iface, BluetoothDevice device) {
+
+    private boolean readLinkProperty(String iface) {
+        String DhcpPrefix = "dhcp." + iface + ".";
+        String ip = SystemProperties.get(DhcpPrefix + "ipaddress");
+        String dns1 = SystemProperties.get(DhcpPrefix + "dns1");
+        String dns2 = SystemProperties.get(DhcpPrefix + "dns2");
+        String gateway = SystemProperties.get(DhcpPrefix + "gateway");
+        String mask = SystemProperties.get(DhcpPrefix + "mask");
+        if(ip.isEmpty() || gateway.isEmpty()) {
+            Log.e(TAG, "readLinkProperty, ip: " +  ip + ", gateway: " + gateway + ", can not be empty");
+            return false;
+        }
+        int PrefixLen = countPrefixLength(NetworkUtils.numericToInetAddress(mask).getAddress());
+        mLinkProperties.addLinkAddress(new LinkAddress(NetworkUtils.numericToInetAddress(ip), PrefixLen));
+        RouteInfo ri = new RouteInfo(NetworkUtils.numericToInetAddress(gateway));
+        mLinkProperties.addRoute(ri);
+        if(!dns1.isEmpty())
+            mLinkProperties.addDns(NetworkUtils.numericToInetAddress(dns1));
+        if(!dns2.isEmpty())
+            mLinkProperties.addDns(NetworkUtils.numericToInetAddress(dns2));
+        mLinkProperties.setInterfaceName(iface);
+        return true;
+    }
+    public synchronized void startReverseTether(String iface) {
         mIface = iface;
-        mDevice = device;
-        Thread dhcpThread = new Thread(new Runnable() {
+        if (DBG) Log.d(TAG, "startReverseTether mCsHandler: " + mCsHandler);
+         mDhcpThread = new Thread(new Runnable() {
             public void run() {
                 //TODO(): Add callbacks for failure and success case.
                 //Currently this thread runs independently.
-                DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
-                if (!NetworkUtils.runDhcp(mIface, dhcpInfoInternal)) {
-                    Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
-                    return;
+                if (DBG) Log.d(TAG, "startReverseTether mCsHandler: " + mCsHandler);
+                String DhcpResultName = "dhcp." + mIface + ".result";;
+                String result = "";
+                if (VDBG) Log.d(TAG, "waiting for change of sys prop dhcp result: " + DhcpResultName);
+                for(int i = 0; i < 30*5; i++) {
+                    try { Thread.sleep(200); } catch (InterruptedException ie) { return;}
+                    result = SystemProperties.get(DhcpResultName);
+                    if (VDBG) Log.d(TAG, "read " + DhcpResultName + ": " + result);
+                    if(result.equals("failed")) {
+                        Log.e(TAG, "startReverseTether, failed to start dhcp service");
+                        return;
+                    }
+                    if(result.equals("ok")) {
+                        if (VDBG) Log.d(TAG, "startReverseTether, dhcp resut: " + result);
+                        if(readLinkProperty(mIface)) {
+
+                            mNetworkInfo.setIsAvailable(true);
+                            mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
+
+                            if (VDBG) Log.d(TAG, "startReverseTether mCsHandler: " + mCsHandler);
+                            if(mCsHandler != null) {
+                                Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
+                                msg.sendToTarget();
+
+                                msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
+                                msg.sendToTarget();
+                            }
+                        }
+                        return;
+                    }
                 }
-                mLinkProperties = dhcpInfoInternal.makeLinkProperties();
-                mLinkProperties.setInterfaceName(mIface);
-
-                mNetworkInfo.setIsAvailable(true);
-                mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
-
-                Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
-                msg.sendToTarget();
-
-                msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
-                msg.sendToTarget();
+                Log.e(TAG, "startReverseTether, dhcp failed, resut: " + result);
             }
         });
-        dhcpThread.start();
+        mDhcpThread.start();
     }
 
-    public synchronized void stopReverseTether(String iface) {
-        NetworkUtils.stopDhcp(iface);
-
+    public synchronized void stopReverseTether() {
+        //NetworkUtils.stopDhcp(iface);
+        if(mDhcpThread != null && mDhcpThread.isAlive()) {
+            mDhcpThread.interrupt();
+            try { mDhcpThread.join(); } catch (InterruptedException ie) { return; }
+        }
         mLinkProperties.clear();
         mNetworkInfo.setIsAvailable(false);
         mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
diff --git a/core/java/android/bluetooth/HeadsetBase.java b/core/java/android/bluetooth/HeadsetBase.java
deleted file mode 100644
index 9ef2eb5..0000000
--- a/core/java/android/bluetooth/HeadsetBase.java
+++ /dev/null
@@ -1,298 +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.
- */
-
-package android.bluetooth;
-
-import android.os.Handler;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
-import android.util.Log;
-
-/**
- * The Android Bluetooth API is not finalized, and *will* change. Use at your
- * own risk.
- *
- * The base RFCOMM (service) connection for a headset or handsfree device.
- *
- * In the future this class will be removed.
- *
- * @hide
- */
-public final class HeadsetBase {
-    private static final String TAG = "Bluetooth HeadsetBase";
-    private static final boolean DBG = false;
-
-    public static final int RFCOMM_DISCONNECTED = 1;
-
-    public static final int DIRECTION_INCOMING = 1;
-    public static final int DIRECTION_OUTGOING = 2;
-
-    private static int sAtInputCount = 0;  /* TODO: Consider not using a static variable */
-
-    private final BluetoothAdapter mAdapter;
-    private final BluetoothDevice mRemoteDevice;
-    private final String mAddress;  // for native code
-    private final int mRfcommChannel;
-    private int mNativeData;
-    private Thread mEventThread;
-    private volatile boolean mEventThreadInterrupted;
-    private Handler mEventThreadHandler;
-    private int mTimeoutRemainingMs;
-    private final int mDirection;
-    private final long mConnectTimestamp;
-
-    protected AtParser mAtParser;
-
-    private WakeLock mWakeLock;  // held while processing an AT command
-
-    private native static void classInitNative();
-    static {
-        classInitNative();
-    }
-
-    protected void finalize() throws Throwable {
-        try {
-            cleanupNativeDataNative();
-            releaseWakeLock();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    private native void cleanupNativeDataNative();
-
-    public HeadsetBase(PowerManager pm, BluetoothAdapter adapter,
-                       BluetoothDevice device, int rfcommChannel) {
-        mDirection = DIRECTION_OUTGOING;
-        mConnectTimestamp = System.currentTimeMillis();
-        mAdapter = adapter;
-        mRemoteDevice = device;
-        mAddress = device.getAddress();
-        mRfcommChannel = rfcommChannel;
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "HeadsetBase");
-        mWakeLock.setReferenceCounted(false);
-        initializeAtParser();
-        // Must be called after this.mAddress is set.
-        initializeNativeDataNative(-1);
-    }
-
-    /* Create from an existing rfcomm connection */
-    public HeadsetBase(PowerManager pm, BluetoothAdapter adapter,
-                       BluetoothDevice device,
-                       int socketFd, int rfcommChannel, Handler handler) {
-        mDirection = DIRECTION_INCOMING;
-        mConnectTimestamp = System.currentTimeMillis();
-        mAdapter = adapter;
-        mRemoteDevice = device;
-        mAddress = device.getAddress();
-        mRfcommChannel = rfcommChannel;
-        mEventThreadHandler = handler;
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "HeadsetBase");
-        mWakeLock.setReferenceCounted(false);
-        initializeAtParser();
-        // Must be called after this.mAddress is set.
-        initializeNativeDataNative(socketFd);
-    }
-
-    private native void initializeNativeDataNative(int socketFd);
-
-    /* Process an incoming AT command line
-     */
-    protected void handleInput(String input) {
-        acquireWakeLock();
-        long timestamp;
-
-        synchronized(HeadsetBase.class) {
-            if (sAtInputCount == Integer.MAX_VALUE) {
-                sAtInputCount = 0;
-            } else {
-                sAtInputCount++;
-            }
-        }
-
-        if (DBG) timestamp = System.currentTimeMillis();
-        AtCommandResult result = mAtParser.process(input);
-        if (DBG) Log.d(TAG, "Processing " + input + " took " +
-                       (System.currentTimeMillis() - timestamp) + " ms");
-
-        if (result.getResultCode() == AtCommandResult.ERROR) {
-            Log.i(TAG, "Error processing <" + input + ">");
-        }
-
-        sendURC(result.toString());
-
-        releaseWakeLock();
-    }
-
-    /**
-     * Register AT commands that are common to all Headset / Handsets. This
-     * function is called by the HeadsetBase constructor.
-     */
-    protected void initializeAtParser() {
-        mAtParser = new AtParser();
-
-        //TODO(): Get rid of this as there are no parsers registered. But because of dependencies
-        // it needs to be done as part of refactoring HeadsetBase and BluetoothHandsfree
-    }
-
-    public AtParser getAtParser() {
-        return mAtParser;
-    }
-
-    public void startEventThread() {
-        mEventThread =
-            new Thread("HeadsetBase Event Thread") {
-                public void run() {
-                    int last_read_error;
-                    while (!mEventThreadInterrupted) {
-                        String input = readNative(500);
-                        if (input != null) {
-                            handleInput(input);
-                        } else {
-                            last_read_error = getLastReadStatusNative();
-                            if (last_read_error != 0) {
-                                Log.i(TAG, "headset read error " + last_read_error);
-                                if (mEventThreadHandler != null) {
-                                    mEventThreadHandler.obtainMessage(RFCOMM_DISCONNECTED)
-                                            .sendToTarget();
-                                }
-                                disconnectNative();
-                                break;
-                            }
-                        }
-                    }
-                }
-            };
-        mEventThreadInterrupted = false;
-        mEventThread.start();
-    }
-
-    private native String readNative(int timeout_ms);
-    private native int getLastReadStatusNative();
-
-    private void stopEventThread() {
-        mEventThreadInterrupted = true;
-        mEventThread.interrupt();
-        try {
-            mEventThread.join();
-        } catch (java.lang.InterruptedException e) {
-            // FIXME: handle this,
-        }
-        mEventThread = null;
-    }
-
-    public boolean connect(Handler handler) {
-        if (mEventThread == null) {
-            if (!connectNative()) return false;
-            mEventThreadHandler = handler;
-        }
-        return true;
-    }
-    private native boolean connectNative();
-
-    /*
-     * Returns true when either the asynchronous connect is in progress, or
-     * the connect is complete.  Call waitForAsyncConnect() to find out whether
-     * the connect is actually complete, or disconnect() to cancel.
-     */
-
-    public boolean connectAsync() {
-        int ret = connectAsyncNative();
-        return (ret == 0) ? true : false;
-    }
-    private native int connectAsyncNative();
-
-    public int getRemainingAsyncConnectWaitingTimeMs() {
-        return mTimeoutRemainingMs;
-    }
-
-    /*
-     * Returns 1 when an async connect is complete, 0 on timeout, and -1 on
-     * error.  On error, handler will be called, and you need to re-initiate
-     * the async connect.
-     */
-    public int waitForAsyncConnect(int timeout_ms, Handler handler) {
-        int res = waitForAsyncConnectNative(timeout_ms);
-        if (res > 0) {
-            mEventThreadHandler = handler;
-        }
-        return res;
-    }
-    private native int waitForAsyncConnectNative(int timeout_ms);
-
-    public void disconnect() {
-        if (mEventThread != null) {
-            stopEventThread();
-        }
-        disconnectNative();
-    }
-    private native void disconnectNative();
-
-
-    /*
-     * Note that if a remote side disconnects, this method will still return
-     * true until disconnect() is called.  You know when a remote side
-     * disconnects because you will receive the intent
-     * IBluetoothService.REMOTE_DEVICE_DISCONNECTED_ACTION.  If, when you get
-     * this intent, method isConnected() returns true, you know that the
-     * disconnect was initiated by the remote device.
-     */
-
-    public boolean isConnected() {
-        return mEventThread != null;
-    }
-
-    public BluetoothDevice getRemoteDevice() {
-        return mRemoteDevice;
-    }
-
-    public int getDirection() {
-        return mDirection;
-    }
-
-    public long getConnectTimestamp() {
-        return mConnectTimestamp;
-    }
-
-    public synchronized boolean sendURC(String urc) {
-        if (urc.length() > 0) {
-            boolean ret = sendURCNative(urc);
-            return ret;
-        }
-        return true;
-    }
-    private native boolean sendURCNative(String urc);
-
-    private synchronized void acquireWakeLock() {
-        if (!mWakeLock.isHeld()) {
-            mWakeLock.acquire();
-        }
-    }
-
-    private synchronized void releaseWakeLock() {
-        if (mWakeLock.isHeld()) {
-            mWakeLock.release();
-        }
-    }
-
-    public static int getAtInputCount() {
-        return sAtInputCount;
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-}
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 6075363..d016c26 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -18,9 +18,7 @@
 
 import android.bluetooth.IBluetoothCallback;
 import android.bluetooth.IBluetoothStateChangeCallback;
-import android.bluetooth.IBluetoothHealthCallback;
 import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHealthAppConfiguration;
 import android.os.ParcelUuid;
 import android.os.ParcelFileDescriptor;
 
@@ -32,15 +30,15 @@
 interface IBluetooth
 {
     boolean isEnabled();
-    int getBluetoothState();
+    int getState();
     boolean enable();
     boolean enableNoAutoConnect();
-    boolean disable(boolean persistSetting);
+    boolean disable();
 
     String getAddress();
-    String getName();
-    boolean setName(in String name);
     ParcelUuid[] getUuids();
+    boolean setName(in String name);
+    String getName();
 
     int getScanMode();
     boolean setScanMode(int mode, int duration);
@@ -51,77 +49,34 @@
     boolean startDiscovery();
     boolean cancelDiscovery();
     boolean isDiscovering();
-    byte[] readOutOfBandData();
 
     int getAdapterConnectionState();
     int getProfileConnectionState(int profile);
-    boolean changeApplicationBluetoothState(boolean on,
-                                in IBluetoothStateChangeCallback callback, in
-                                IBinder b);
 
-    boolean createBond(in String address);
-    boolean createBondOutOfBand(in String address, in byte[] hash, in byte[] randomizer);
-    boolean cancelBondProcess(in String address);
-    boolean removeBond(in String address);
-    String[] listBonds();
-    int getBondState(in String address);
-    boolean setDeviceOutOfBandData(in String address, in byte[] hash, in byte[] randomizer);
+    BluetoothDevice[] getBondedDevices();
+    boolean createBond(in BluetoothDevice device);
+    boolean cancelBondProcess(in BluetoothDevice device);
+    boolean removeBond(in BluetoothDevice device);
+    int getBondState(in BluetoothDevice device);
 
-    String getRemoteName(in String address);
-    String getRemoteAlias(in String address);
-    boolean setRemoteAlias(in String address, in String name);
-    int getRemoteClass(in String address);
-    ParcelUuid[] getRemoteUuids(in String address);
-    boolean fetchRemoteUuids(in String address, in ParcelUuid uuid, in IBluetoothCallback callback);
-    int getRemoteServiceChannel(in String address, in ParcelUuid uuid);
+    String getRemoteName(in BluetoothDevice device);
+    String getRemoteAlias(in BluetoothDevice device);
+    boolean setRemoteAlias(in BluetoothDevice device, in String name);
+    int getRemoteClass(in BluetoothDevice device);
+    ParcelUuid[] getRemoteUuids(in BluetoothDevice device);
+    boolean fetchRemoteUuids(in BluetoothDevice device);
 
-    boolean setPin(in String address, in byte[] pin);
-    boolean setPasskey(in String address, int passkey);
-    boolean setPairingConfirmation(in String address, boolean confirm);
-    boolean setRemoteOutOfBandData(in String addres);
-    boolean cancelPairingUserInput(in String address);
-
-    boolean setTrust(in String address, in boolean value);
-    boolean getTrustState(in String address);
-    boolean isBluetoothDock(in String address);
-
-    int addRfcommServiceRecord(in String serviceName, in ParcelUuid uuid, int channel, IBinder b);
-    void removeServiceRecord(int handle);
-    boolean allowIncomingProfileConnect(in BluetoothDevice device, boolean value);
-
-    boolean connectHeadset(String address);
-    boolean disconnectHeadset(String address);
-    boolean notifyIncomingConnection(String address, boolean rejected);
-
-    // HID profile APIs
-    boolean connectInputDevice(in BluetoothDevice device);
-    boolean disconnectInputDevice(in BluetoothDevice device);
-    List<BluetoothDevice> getConnectedInputDevices();
-    List<BluetoothDevice> getInputDevicesMatchingConnectionStates(in int[] states);
-    int getInputDeviceConnectionState(in BluetoothDevice device);
-    boolean setInputDevicePriority(in BluetoothDevice device, int priority);
-    int getInputDevicePriority(in BluetoothDevice device);
-
-    boolean isTetheringOn();
-    void setBluetoothTethering(boolean value);
-    int getPanDeviceConnectionState(in BluetoothDevice device);
-    List<BluetoothDevice> getConnectedPanDevices();
-    List<BluetoothDevice> getPanDevicesMatchingConnectionStates(in int[] states);
-    boolean connectPanDevice(in BluetoothDevice device);
-    boolean disconnectPanDevice(in BluetoothDevice device);
-
-    // HDP profile APIs
-    boolean registerAppConfiguration(in BluetoothHealthAppConfiguration config,
-        in IBluetoothHealthCallback callback);
-    boolean unregisterAppConfiguration(in BluetoothHealthAppConfiguration config);
-    boolean connectChannelToSource(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
-    boolean connectChannelToSink(in BluetoothDevice device, in BluetoothHealthAppConfiguration config,
-        int channelType);
-    boolean disconnectChannel(in BluetoothDevice device, in BluetoothHealthAppConfiguration config, int id);
-    ParcelFileDescriptor getMainChannelFd(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
-    List<BluetoothDevice> getConnectedHealthDevices();
-    List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(in int[] states);
-    int getHealthDeviceConnectionState(in BluetoothDevice device);
+    boolean setPin(in BluetoothDevice device, boolean accept, int len, in byte[] pinCode);
+    boolean setPasskey(in BluetoothDevice device, boolean accept, int len, in byte[]
+    passkey);
+    boolean setPairingConfirmation(in BluetoothDevice device, boolean accept);
 
     void sendConnectionStateChange(in BluetoothDevice device, int profile, int state, int prevState);
+
+    void registerCallback(in IBluetoothCallback callback);
+    void unregisterCallback(in IBluetoothCallback callback);
+
+    // For Socket
+    ParcelFileDescriptor connectSocket(in BluetoothDevice device, int type, in ParcelUuid uuid, int port, int flag);
+    ParcelFileDescriptor createSocketChannel(int type, in String serviceName, in ParcelUuid uuid, int port, int flag);
 }
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
index 444dd1e..1f10998 100644
--- a/core/java/android/bluetooth/IBluetoothA2dp.aidl
+++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl
@@ -33,12 +33,4 @@
     boolean setPriority(in BluetoothDevice device, int priority);
     int getPriority(in BluetoothDevice device);
     boolean isA2dpPlaying(in BluetoothDevice device);
-
-    // Internal APIs
-    boolean suspendSink(in BluetoothDevice device);
-    boolean resumeSink(in BluetoothDevice device);
-    boolean connectSinkInternal(in BluetoothDevice device);
-    boolean disconnectSinkInternal(in BluetoothDevice device);
-    boolean allowIncomingConnect(in BluetoothDevice device, boolean value);
-
 }
diff --git a/core/java/android/bluetooth/IBluetoothCallback.aidl b/core/java/android/bluetooth/IBluetoothCallback.aidl
index 8edb3f4..e280978 100644
--- a/core/java/android/bluetooth/IBluetoothCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothCallback.aidl
@@ -23,5 +23,6 @@
  */
 interface IBluetoothCallback
 {
-    void onRfcommChannelFound(int channel);
+    //void onRfcommChannelFound(int channel);
+    void onBluetoothStateChange(int prevState, int newState);
 }
diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl
index ec00527..fc7627a 100644
--- a/core/java/android/bluetooth/IBluetoothHeadset.aidl
+++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl
@@ -40,15 +40,17 @@
     int getBatteryUsageHint(in BluetoothDevice device);
 
     // Internal functions, not be made public
-    boolean createIncomingConnect(in BluetoothDevice device);
     boolean acceptIncomingConnect(in BluetoothDevice device);
     boolean rejectIncomingConnect(in BluetoothDevice device);
-    boolean cancelConnectThread();
-    boolean connectHeadsetInternal(in BluetoothDevice device);
-    boolean disconnectHeadsetInternal(in BluetoothDevice device);
-    boolean setAudioState(in BluetoothDevice device, int state);
     int getAudioState(in BluetoothDevice device);
 
+    boolean isAudioOn();
+    boolean connectAudio();
+    boolean disconnectAudio();
     boolean startScoUsingVirtualVoiceCall(in BluetoothDevice device);
     boolean stopScoUsingVirtualVoiceCall(in BluetoothDevice device);
+    void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type);
+    void roamChanged(boolean roam);
+    void clccResponse(int index, int direction, int status, int mode, boolean mpty,
+                      String number, int type);
 }
diff --git a/core/java/android/bluetooth/IBluetoothHeadsetPhone.aidl b/core/java/android/bluetooth/IBluetoothHeadsetPhone.aidl
new file mode 100644
index 0000000..d5e64f6
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothHeadsetPhone.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.bluetooth;
+
+/**
+ * API for Bluetooth Headset Phone Service in phone app
+ *
+ * {@hide}
+ */
+interface IBluetoothHeadsetPhone {
+  // Internal functions, not be made public
+  boolean answerCall();
+  boolean hangupCall();
+  boolean sendDtmf(int dtmf);
+  boolean processChld(int chld);
+  String getNetworkOperator();
+  String getSubscriberNumber();
+  boolean listCurrentCalls();
+  boolean queryPhoneState();
+
+  // Internal for phone app to call
+  void updateBtHandsfreeAfterRadioTechnologyChange();
+  void cdmaSwapSecondCallState();
+  void cdmaSetSecondCallState(boolean state);
+}
diff --git a/core/java/android/bluetooth/IBluetoothHealth.aidl b/core/java/android/bluetooth/IBluetoothHealth.aidl
new file mode 100644
index 0000000..a84a42c
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothHealth.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHealthAppConfiguration;
+import android.bluetooth.IBluetoothHealthCallback;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * API for Bluetooth Health service
+ *
+ * {@hide}
+ */
+interface IBluetoothHealth
+{
+    boolean registerAppConfiguration(in BluetoothHealthAppConfiguration config,
+        in IBluetoothHealthCallback callback);
+    boolean unregisterAppConfiguration(in BluetoothHealthAppConfiguration config);
+    boolean connectChannelToSource(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
+    boolean connectChannelToSink(in BluetoothDevice device, in BluetoothHealthAppConfiguration config,
+        int channelType);
+    boolean disconnectChannel(in BluetoothDevice device, in BluetoothHealthAppConfiguration config, int id);
+    ParcelFileDescriptor getMainChannelFd(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
+    List<BluetoothDevice> getConnectedHealthDevices();
+    List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(in int[] states);
+    int getHealthDeviceConnectionState(in BluetoothDevice device);
+}
diff --git a/core/java/android/bluetooth/IBluetoothInputDevice.aidl b/core/java/android/bluetooth/IBluetoothInputDevice.aidl
new file mode 100755
index 0000000..1ebb9ca
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothInputDevice.aidl
@@ -0,0 +1,59 @@
+/*
+ * 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.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * API for Bluetooth HID service
+ *
+ * {@hide}
+ */
+interface IBluetoothInputDevice {
+    // Public API
+    boolean connect(in BluetoothDevice device);
+    boolean disconnect(in BluetoothDevice device);
+    List<BluetoothDevice> getConnectedDevices();
+    List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+    int getConnectionState(in BluetoothDevice device);
+    boolean setPriority(in BluetoothDevice device, int priority);
+    int getPriority(in BluetoothDevice device);
+    /**
+    * @hide
+    */
+    boolean getProtocolMode(in BluetoothDevice device);
+    /**
+    * @hide
+    */
+    boolean virtualUnplug(in BluetoothDevice device);
+    /**
+    * @hide
+    */
+    boolean setProtocolMode(in BluetoothDevice device, int protocolMode);
+    /**
+    * @hide
+    */
+    boolean getReport(in BluetoothDevice device, byte reportType, byte reportId, int bufferSize);
+    /**
+    * @hide
+    */
+    boolean setReport(in BluetoothDevice device, byte reportType, String report);
+    /**
+    * @hide
+    */
+    boolean sendData(in BluetoothDevice device, String report);
+}
diff --git a/core/java/android/bluetooth/IBluetoothManager.aidl b/core/java/android/bluetooth/IBluetoothManager.aidl
new file mode 100755
index 0000000..ed8777c
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothManager.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.bluetooth;
+
+import android.bluetooth.IBluetooth;
+import android.bluetooth.IBluetoothManagerCallback;
+import android.bluetooth.IBluetoothStateChangeCallback;
+
+/**
+ * System private API for talking with the Bluetooth service.
+ *
+ * {@hide}
+ */
+interface IBluetoothManager
+{
+    IBluetooth registerAdapter(in IBluetoothManagerCallback callback);
+    void unregisterAdapter(in IBluetoothManagerCallback callback);
+    void registerStateChangeCallback(in IBluetoothStateChangeCallback callback);
+    void unregisterStateChangeCallback(in IBluetoothStateChangeCallback callback);
+    boolean isEnabled();
+    boolean enable();
+    boolean enableNoAutoConnect();
+    boolean disable(boolean persist);
+
+    String getAddress();
+    String getName();
+}
diff --git a/core/java/android/bluetooth/IBluetoothManagerCallback.aidl b/core/java/android/bluetooth/IBluetoothManagerCallback.aidl
new file mode 100644
index 0000000..9551086
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothManagerCallback.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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.bluetooth;
+
+import android.bluetooth.IBluetooth;
+
+/**
+ * API for Communication between BluetoothAdapter and BluetoothManager
+ *
+ * {@hide}
+ */
+interface IBluetoothManagerCallback {
+    void onBluetoothServiceUp(in IBluetooth bluetoothService);
+    void onBluetoothServiceDown();
+}
\ No newline at end of file
diff --git a/core/java/android/bluetooth/IBluetoothPan.aidl b/core/java/android/bluetooth/IBluetoothPan.aidl
new file mode 100644
index 0000000..5a32347
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothPan.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * API for Bluetooth Pan service
+ *
+ * {@hide}
+ */
+interface IBluetoothPan {
+    // Public API
+    boolean isTetheringOn();
+    void setBluetoothTethering(boolean value);
+    boolean connect(in BluetoothDevice device);
+    boolean disconnect(in BluetoothDevice device);
+    List<BluetoothDevice> getConnectedDevices();
+    List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+    int getConnectionState(in BluetoothDevice device);
+}
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index 446f1af..1500b00 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -237,16 +237,17 @@
         final boolean mOrderedHint;
         final boolean mInitialStickyHint;
         final IBinder mToken;
+        final int mSendingUser;
         
         int mResultCode;
         String mResultData;
         Bundle mResultExtras;
         boolean mAbortBroadcast;
         boolean mFinished;
-        
+
         /** @hide */
         public PendingResult(int resultCode, String resultData, Bundle resultExtras,
-                int type, boolean ordered, boolean sticky, IBinder token) {
+                int type, boolean ordered, boolean sticky, IBinder token, int userId) {
             mResultCode = resultCode;
             mResultData = resultData;
             mResultExtras = resultExtras;
@@ -254,6 +255,7 @@
             mOrderedHint = ordered;
             mInitialStickyHint = sticky;
             mToken = token;
+            mSendingUser = userId;
         }
         
         /**
@@ -425,7 +427,12 @@
                 }
             }
         }
-        
+
+        /** @hide */
+        public int getSendingUserId() {
+            return mSendingUser;
+        }
+
         void checkSynchronousHint() {
             // Note that we don't assert when receiving the initial sticky value,
             // since that may have come from an ordered broadcast.  We'll catch
@@ -733,6 +740,11 @@
         return mPendingResult;
     }
     
+    /** @hide */
+    public int getSendingUserId() {
+        return mPendingResult.mSendingUser;
+    }
+
     /**
      * Control inclusion of debugging help for mismatched
      * calls to {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index 1866830..88f1a3d 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -563,7 +563,7 @@
         private String uriToHtml(String uri) {
             StringBuilder builder = new StringBuilder(256);
             builder.append("<a href=\"");
-            builder.append(uri);
+            builder.append(Html.escapeHtml(uri));
             builder.append("\">");
             builder.append(Html.escapeHtml(uri));
             builder.append("</a>");
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index b22179e..23d8f46 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -35,7 +35,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.Log;
 
 import java.io.File;
@@ -279,7 +279,7 @@
             final int uid = Binder.getCallingUid();
             String missingPerm = null;
 
-            if (uid == mMyUid) {
+            if (UserHandle.isSameApp(uid, mMyUid)) {
                 return;
             }
 
@@ -340,7 +340,7 @@
             final int uid = Binder.getCallingUid();
             String missingPerm = null;
 
-            if (uid == mMyUid) {
+            if (UserHandle.isSameApp(uid, mMyUid)) {
                 return;
             }
 
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 5c315ce..204f963 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -231,6 +231,19 @@
         }
     }
 
+    /** See {@link ContentProvider#call(String, String, Bundle)} */
+    public Bundle call(String method, String arg, Bundle extras)
+            throws RemoteException {
+        try {
+            return mContentProvider.call(method, arg, extras);
+        } catch (DeadObjectException e) {
+            if (!mStable) {
+                mContentResolver.unstableProviderDied(mContentProvider);
+            }
+            throw e;
+        }
+    }
+
     /**
      * Call this to indicate to the system that the associated {@link ContentProvider} is no
      * longer needed by this {@link ContentProviderClient}.
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 0a5a26a..9e406d4 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -39,6 +39,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.Log;
@@ -230,7 +231,8 @@
         }
 
         try {
-            String type = ActivityManagerNative.getDefault().getProviderMimeType(url);
+            String type = ActivityManagerNative.getDefault().getProviderMimeType(
+                    url, UserHandle.myUserId());
             return type;
         } catch (RemoteException e) {
             // Arbitrary and not worth documenting, as Activity
@@ -1217,9 +1219,16 @@
     public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
             ContentObserver observer)
     {
+        registerContentObserver(uri, notifyForDescendents, observer, UserHandle.myUserId());
+    }
+
+    /** @hide - designated user version */
+    public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
+            ContentObserver observer, int userHandle)
+    {
         try {
             getContentService().registerContentObserver(uri, notifyForDescendents,
-                    observer.getContentObserver());
+                    observer.getContentObserver(), userHandle);
         } catch (RemoteException e) {
         }
     }
@@ -1274,10 +1283,21 @@
      * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
      */
     public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
+        notifyChange(uri, observer, syncToNetwork, UserHandle.getCallingUserId());
+    }
+
+    /**
+     * Notify registered observers within the designated user(s) that a row was updated.
+     *
+     * @hide
+     */
+    public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork,
+            int userHandle) {
         try {
             getContentService().notifyChange(
                     uri, observer == null ? null : observer.getContentObserver(),
-                    observer != null && observer.deliverSelfNotifications(), syncToNetwork);
+                    observer != null && observer.deliverSelfNotifications(), syncToNetwork,
+                    userHandle);
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/content/ContentService.java b/core/java/android/content/ContentService.java
index 1a07504..4512e82 100644
--- a/core/java/android/content/ContentService.java
+++ b/core/java/android/content/ContentService.java
@@ -17,6 +17,7 @@
 package android.content;
 
 import android.accounts.Account;
+import android.app.ActivityManager;
 import android.database.IContentObserver;
 import android.database.sqlite.SQLiteException;
 import android.net.Uri;
@@ -26,13 +27,14 @@
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.Log;
 import android.util.SparseIntArray;
 import android.Manifest;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.security.InvalidParameterException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -138,17 +140,47 @@
         getSyncManager();
     }
 
-    public void registerContentObserver(Uri uri, boolean notifyForDescendents,
-            IContentObserver observer) {
+    /**
+     * Register a content observer tied to a specific user's view of the provider.
+     * @param userHandle the user whose view of the provider is to be observed.  May be
+     *     the calling user without requiring any permission, otherwise the caller needs to
+     *     hold the INTERACT_ACROSS_USERS_FULL permission.  Pseudousers USER_ALL and
+     *     USER_CURRENT are properly handled; all other pseudousers are forbidden.
+     */
+    @Override
+    public void registerContentObserver(Uri uri, boolean notifyForDescendants,
+            IContentObserver observer, int userHandle) {
         if (observer == null || uri == null) {
             throw new IllegalArgumentException("You must pass a valid uri and observer");
         }
-        synchronized (mRootNode) {
-            mRootNode.addObserverLocked(uri, observer, notifyForDescendents, mRootNode,
-                    Binder.getCallingUid(), Binder.getCallingPid());
-            if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
-                    " with notifyForDescendents " + notifyForDescendents);
+
+        final int callingUser = UserHandle.getCallingUserId();
+        if (callingUser != userHandle) {
+            mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    "no permission to observe other users' provider view");
         }
+
+        if (userHandle < 0) {
+            if (userHandle == UserHandle.USER_CURRENT) {
+                userHandle = ActivityManager.getCurrentUser();
+            } else if (userHandle != UserHandle.USER_ALL) {
+                throw new InvalidParameterException("Bad user handle for registerContentObserver: "
+                        + userHandle);
+            }
+        }
+
+        synchronized (mRootNode) {
+            mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode,
+                    Binder.getCallingUid(), Binder.getCallingPid(), userHandle);
+            if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
+                    " with notifyForDescendants " + notifyForDescendants);
+        }
+    }
+
+    public void registerContentObserver(Uri uri, boolean notifyForDescendants,
+            IContentObserver observer) {
+        registerContentObserver(uri, notifyForDescendants, observer,
+                UserHandle.getCallingUserId());
     }
 
     public void unregisterContentObserver(IContentObserver observer) {
@@ -161,14 +193,39 @@
         }
     }
 
+    /**
+     * Notify observers of a particular user's view of the provider.
+     * @param userHandle the user whose view of the provider is to be notified.  May be
+     *     the calling user without requiring any permission, otherwise the caller needs to
+     *     hold the INTERACT_ACROSS_USERS_FULL permission.  Pseudousers USER_ALL and
+     *     USER_CURRENT are properly interpreted; no other pseudousers are allowed.
+     */
+    @Override
     public void notifyChange(Uri uri, IContentObserver observer,
-            boolean observerWantsSelfNotifications, boolean syncToNetwork) {
+            boolean observerWantsSelfNotifications, boolean syncToNetwork,
+            int userHandle) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "Notifying update of " + uri + " from observer " + observer
-                    + ", syncToNetwork " + syncToNetwork);
+            Log.v(TAG, "Notifying update of " + uri + " for user " + userHandle
+                    + " from observer " + observer + ", syncToNetwork " + syncToNetwork);
         }
 
-        int userId = UserId.getCallingUserId();
+        // Notify for any user other than the caller's own requires permission.
+        final int callingUserHandle = UserHandle.getCallingUserId();
+        if (userHandle != callingUserHandle) {
+            mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    "no permission to notify other users");
+        }
+
+        // We passed the permission check; resolve pseudouser targets as appropriate
+        if (userHandle < 0) {
+            if (userHandle == UserHandle.USER_CURRENT) {
+                userHandle = ActivityManager.getCurrentUser();
+            } else if (userHandle != UserHandle.USER_ALL) {
+                throw new InvalidParameterException("Bad user handle for notifyChange: "
+                        + userHandle);
+            }
+        }
+
         // This makes it so that future permission checks will be in the context of this
         // process rather than the caller's process. We will restore this before returning.
         long identityToken = clearCallingIdentity();
@@ -176,7 +233,7 @@
             ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
             synchronized (mRootNode) {
                 mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
-                        calls);
+                        userHandle, calls);
             }
             final int numCalls = calls.size();
             for (int i=0; i<numCalls; i++) {
@@ -207,7 +264,7 @@
             if (syncToNetwork) {
                 SyncManager syncManager = getSyncManager();
                 if (syncManager != null) {
-                    syncManager.scheduleLocalSync(null /* all accounts */, userId,
+                    syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle,
                             uri.getAuthority());
                 }
             }
@@ -216,6 +273,12 @@
         }
     }
 
+    public void notifyChange(Uri uri, IContentObserver observer,
+            boolean observerWantsSelfNotifications, boolean syncToNetwork) {
+        notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork,
+                UserHandle.getCallingUserId());
+    }
+
     /**
      * Hide this class since it is not part of api,
      * but current unittest framework requires it to be public
@@ -236,7 +299,7 @@
 
     public void requestSync(Account account, String authority, Bundle extras) {
         ContentResolver.validateSyncExtrasBundle(extras);
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
 
         // This makes it so that future permission checks will be in the context of this
         // process rather than the caller's process. We will restore this before returning.
@@ -259,7 +322,7 @@
      * @param authority filter the pending and active syncs to cancel using this authority
      */
     public void cancelSync(Account account, String authority) {
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
 
         // This makes it so that future permission checks will be in the context of this
         // process rather than the caller's process. We will restore this before returning.
@@ -282,10 +345,11 @@
     public SyncAdapterType[] getSyncAdapterTypes() {
         // This makes it so that future permission checks will be in the context of this
         // process rather than the caller's process. We will restore this before returning.
-        long identityToken = clearCallingIdentity();
+        final int userId = UserHandle.getCallingUserId();
+        final long identityToken = clearCallingIdentity();
         try {
             SyncManager syncManager = getSyncManager();
-            return syncManager.getSyncAdapterTypes();
+            return syncManager.getSyncAdapterTypes(userId);
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -294,7 +358,7 @@
     public boolean getSyncAutomatically(Account account, String providerName) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
                 "no permission to read the sync settings");
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
 
         long identityToken = clearCallingIdentity();
         try {
@@ -312,7 +376,7 @@
     public void setSyncAutomatically(Account account, String providerName, boolean sync) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
                 "no permission to write the sync settings");
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
 
         long identityToken = clearCallingIdentity();
         try {
@@ -330,7 +394,7 @@
             long pollFrequency) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
                 "no permission to write the sync settings");
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
 
         long identityToken = clearCallingIdentity();
         try {
@@ -344,7 +408,7 @@
     public void removePeriodicSync(Account account, String authority, Bundle extras) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
                 "no permission to write the sync settings");
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
 
         long identityToken = clearCallingIdentity();
         try {
@@ -358,7 +422,7 @@
     public List<PeriodicSync> getPeriodicSyncs(Account account, String providerName) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
                 "no permission to read the sync settings");
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
 
         long identityToken = clearCallingIdentity();
         try {
@@ -372,7 +436,7 @@
     public int getIsSyncable(Account account, String providerName) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
                 "no permission to read the sync settings");
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
 
         long identityToken = clearCallingIdentity();
         try {
@@ -390,7 +454,7 @@
     public void setIsSyncable(Account account, String providerName, int syncable) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
                 "no permission to write the sync settings");
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
 
         long identityToken = clearCallingIdentity();
         try {
@@ -407,7 +471,7 @@
     public boolean getMasterSyncAutomatically() {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
                 "no permission to read the sync settings");
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
 
         long identityToken = clearCallingIdentity();
         try {
@@ -424,7 +488,7 @@
     public void setMasterSyncAutomatically(boolean flag) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
                 "no permission to write the sync settings");
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
 
         long identityToken = clearCallingIdentity();
         try {
@@ -440,7 +504,7 @@
     public boolean isSyncActive(Account account, String authority) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
                 "no permission to read the sync stats");
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
 
         long identityToken = clearCallingIdentity();
         try {
@@ -458,7 +522,7 @@
     public List<SyncInfo> getCurrentSyncs() {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
                 "no permission to read the sync stats");
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
 
         long identityToken = clearCallingIdentity();
         try {
@@ -471,7 +535,7 @@
     public SyncStatusInfo getSyncStatus(Account account, String authority) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
                 "no permission to read the sync stats");
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
 
         long identityToken = clearCallingIdentity();
         try {
@@ -489,7 +553,7 @@
     public boolean isSyncPending(Account account, String authority) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
                 "no permission to read the sync stats");
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
 
         long identityToken = clearCallingIdentity();
         try {
@@ -543,16 +607,18 @@
             public final IContentObserver observer;
             public final int uid;
             public final int pid;
-            public final boolean notifyForDescendents;
+            public final boolean notifyForDescendants;
+            private final int userHandle;
             private final Object observersLock;
 
             public ObserverEntry(IContentObserver o, boolean n, Object observersLock,
-                    int _uid, int _pid) {
+                    int _uid, int _pid, int _userHandle) {
                 this.observersLock = observersLock;
                 observer = o;
                 uid = _uid;
                 pid = _pid;
-                notifyForDescendents = n;
+                userHandle = _userHandle;
+                notifyForDescendants = n;
                 try {
                     observer.asBinder().linkToDeath(this, 0);
                 } catch (RemoteException e) {
@@ -571,7 +637,8 @@
                 pidCounts.put(pid, pidCounts.get(pid)+1);
                 pw.print(prefix); pw.print(name); pw.print(": pid=");
                         pw.print(pid); pw.print(" uid=");
-                        pw.print(uid); pw.print(" target=");
+                        pw.print(uid); pw.print(" user=");
+                        pw.print(userHandle); pw.print(" target=");
                         pw.println(Integer.toHexString(System.identityHashCode(
                                 observer != null ? observer.asBinder() : null)));
             }
@@ -639,17 +706,21 @@
             return uri.getPathSegments().size() + 1;
         }
 
+        // Invariant:  userHandle is either a hard user number or is USER_ALL
         public void addObserverLocked(Uri uri, IContentObserver observer,
-                boolean notifyForDescendents, Object observersLock, int uid, int pid) {
-            addObserverLocked(uri, 0, observer, notifyForDescendents, observersLock, uid, pid);
+                boolean notifyForDescendants, Object observersLock,
+                int uid, int pid, int userHandle) {
+            addObserverLocked(uri, 0, observer, notifyForDescendants, observersLock,
+                    uid, pid, userHandle);
         }
 
         private void addObserverLocked(Uri uri, int index, IContentObserver observer,
-                boolean notifyForDescendents, Object observersLock, int uid, int pid) {
+                boolean notifyForDescendants, Object observersLock,
+                int uid, int pid, int userHandle) {
             // If this is the leaf node add the observer
             if (index == countUriSegments(uri)) {
-                mObservers.add(new ObserverEntry(observer, notifyForDescendents, observersLock,
-                        uid, pid));
+                mObservers.add(new ObserverEntry(observer, notifyForDescendants, observersLock,
+                        uid, pid, userHandle));
                 return;
             }
 
@@ -662,8 +733,8 @@
             for (int i = 0; i < N; i++) {
                 ObserverNode node = mChildren.get(i);
                 if (node.mName.equals(segment)) {
-                    node.addObserverLocked(uri, index + 1, observer, notifyForDescendents,
-                            observersLock, uid, pid);
+                    node.addObserverLocked(uri, index + 1, observer, notifyForDescendants,
+                            observersLock, uid, pid, userHandle);
                     return;
                 }
             }
@@ -671,8 +742,8 @@
             // No child found, create one
             ObserverNode node = new ObserverNode(segment);
             mChildren.add(node);
-            node.addObserverLocked(uri, index + 1, observer, notifyForDescendents,
-                    observersLock, uid, pid);
+            node.addObserverLocked(uri, index + 1, observer, notifyForDescendants,
+                    observersLock, uid, pid, userHandle);
         }
 
         public boolean removeObserverLocked(IContentObserver observer) {
@@ -705,37 +776,49 @@
         }
 
         private void collectMyObserversLocked(boolean leaf, IContentObserver observer,
-                boolean observerWantsSelfNotifications, ArrayList<ObserverCall> calls) {
+                boolean observerWantsSelfNotifications, int targetUserHandle,
+                ArrayList<ObserverCall> calls) {
             int N = mObservers.size();
             IBinder observerBinder = observer == null ? null : observer.asBinder();
             for (int i = 0; i < N; i++) {
                 ObserverEntry entry = mObservers.get(i);
 
-                // Don't notify the observer if it sent the notification and isn't interesed
+                // Don't notify the observer if it sent the notification and isn't interested
                 // in self notifications
                 boolean selfChange = (entry.observer.asBinder() == observerBinder);
                 if (selfChange && !observerWantsSelfNotifications) {
                     continue;
                 }
 
-                // Make sure the observer is interested in the notification
-                if (leaf || (!leaf && entry.notifyForDescendents)) {
-                    calls.add(new ObserverCall(this, entry.observer, selfChange));
+                // Does this observer match the target user?
+                if (targetUserHandle == UserHandle.USER_ALL
+                        || entry.userHandle == UserHandle.USER_ALL
+                        || targetUserHandle == entry.userHandle) {
+                    // Make sure the observer is interested in the notification
+                    if (leaf || (!leaf && entry.notifyForDescendants)) {
+                        calls.add(new ObserverCall(this, entry.observer, selfChange));
+                    }
                 }
             }
         }
 
+        /**
+         * targetUserHandle is either a hard user handle or is USER_ALL
+         */
         public void collectObserversLocked(Uri uri, int index, IContentObserver observer,
-                boolean observerWantsSelfNotifications, ArrayList<ObserverCall> calls) {
+                boolean observerWantsSelfNotifications, int targetUserHandle,
+                ArrayList<ObserverCall> calls) {
             String segment = null;
             int segmentCount = countUriSegments(uri);
             if (index >= segmentCount) {
                 // This is the leaf node, notify all observers
-                collectMyObserversLocked(true, observer, observerWantsSelfNotifications, calls);
+                collectMyObserversLocked(true, observer, observerWantsSelfNotifications,
+                        targetUserHandle, calls);
             } else if (index < segmentCount){
                 segment = getUriSegment(uri, index);
-                // Notify any observers at this level who are interested in descendents
-                collectMyObserversLocked(false, observer, observerWantsSelfNotifications, calls);
+                // Notify any observers at this level who are interested in descendants
+                collectMyObserversLocked(false, observer, observerWantsSelfNotifications,
+                        targetUserHandle, calls);
             }
 
             int N = mChildren.size();
@@ -744,7 +827,7 @@
                 if (segment == null || node.mName.equals(segment)) {
                     // We found the child,
                     node.collectObserversLocked(uri, index + 1,
-                            observer, observerWantsSelfNotifications, calls);
+                            observer, observerWantsSelfNotifications, targetUserHandle, calls);
                     if (segment != null) {
                         break;
                     }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ffff9be..7aa2507 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -19,6 +19,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.AssetManager;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.database.DatabaseErrorHandler;
@@ -31,7 +32,12 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.util.AttributeSet;
+import android.view.CompatibilityInfoHolder;
+import android.view.Display;
+import android.view.WindowManager;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -58,18 +64,34 @@
      */
     public static final int MODE_PRIVATE = 0x0000;
     /**
+     * @deprecated Creating world-readable files is very dangerous, and likely
+     * to cause security holes in applications.  It is strongly discouraged;
+     * instead, applications should use more formal mechanism for interactions
+     * such as {@link ContentProvider}, {@link BroadcastReceiver}, and
+     * {@link android.app.Service}.  There are no guarantees that this
+     * access mode will remain on a file, such as when it goes through a
+     * backup and restore.
      * File creation mode: allow all other applications to have read access
      * to the created file.
      * @see #MODE_PRIVATE
      * @see #MODE_WORLD_WRITEABLE
      */
+    @Deprecated
     public static final int MODE_WORLD_READABLE = 0x0001;
     /**
+     * @deprecated Creating world-writable files is very dangerous, and likely
+     * to cause security holes in applications.  It is strongly discouraged;
+     * instead, applications should use more formal mechanism for interactions
+     * such as {@link ContentProvider}, {@link BroadcastReceiver}, and
+     * {@link android.app.Service}.  There are no guarantees that this
+     * access mode will remain on a file, such as when it goes through a
+     * backup and restore.
      * File creation mode: allow all other applications to have write access
      * to the created file.
      * @see #MODE_PRIVATE
      * @see #MODE_WORLD_READABLE
      */
+    @Deprecated
     public static final int MODE_WORLD_WRITEABLE = 0x0002;
     /**
      * File creation mode: for use with {@link #openFileOutput}, if the file
@@ -157,7 +179,7 @@
      * Flag for {@link #bindService}: indicates that the client application
      * binding to this service considers the service to be more important than
      * the app itself.  When set, the platform will try to have the out of
-     * memory kill the app before it kills the service it is bound to, though
+     * memory killer kill the app before it kills the service it is bound to, though
      * this is not guaranteed to be the case.
      */
     public static final int BIND_ABOVE_CLIENT = 0x0008;
@@ -198,6 +220,19 @@
     public static final int BIND_ADJUST_WITH_ACTIVITY = 0x0080;
 
     /**
+     * @hide An idea that is not yet implemented.
+     * Flag for {@link #bindService}: If binding from an activity, consider
+     * this service to be visible like the binding activity is.  That is,
+     * it will be treated as something more important to keep around than
+     * invisible background activities.  This will impact the number of
+     * recent activities the user can switch between without having them
+     * restart.  There is no guarantee this will be respected, as the system
+     * tries to balance such requests from one app vs. the importantance of
+     * keeping other apps around.
+     */
+    public static final int BIND_VISIBLE = 0x0100;
+
+    /**
      * Flag for {@link #bindService}: Don't consider the bound service to be
      * visible, even if the caller is visible.
      * @hide
@@ -553,6 +588,10 @@
      * can read and write files placed here.
      * </ul>
      *
+     * <p>On devices with multiple users (as described by {@link UserManager}),
+     * each user has their own isolated external storage. Applications only
+     * have access to the external storage for the user they're running as.</p>
+     *
      * <p>Here is an example of typical code to manipulate a file in
      * an application's private storage:</p>
      *
@@ -582,6 +621,9 @@
      * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
      * private_picture}
      *
+     * <p>Writing to this path requires the
+     * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permission.</p>
+     *
      * @param type The type of files directory to return.  May be null for
      * the root of the files directory or one of
      * the following Environment constants for a subdirectory:
@@ -607,6 +649,11 @@
      * Return the directory where this application's OBB files (if there
      * are any) can be found.  Note if the application does not have any OBB
      * files, this directory may not exist.
+     *
+     * <p>On devices with multiple users (as described by {@link UserManager}),
+     * multiple users may share the same OBB storage location. Applications
+     * should ensure that multiple instances running under different users
+     * don't interfere with each other.</p>
      */
     public abstract File getObbDir();
 
@@ -640,8 +687,12 @@
      * are some important differences:
      *
      * <ul>
-     * <li>The platform does not monitor the space available in external storage,
-     * and thus will not automatically delete these files.  Note that you should
+     * <li>The platform does not always monitor the space available in external
+     * storage, and thus may not automatically delete these files.  Currently
+     * the only time files here will be deleted by the platform is when running
+     * on {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} or later and
+     * {@link android.os.Environment#isExternalStorageEmulated()
+     * Environment.isExternalStorageEmulated()} returns true.  Note that you should
      * be managing the maximum space you will use for these anyway, just like
      * with {@link #getCacheDir()}.
      * <li>External files are not always available: they will disappear if the
@@ -651,6 +702,13 @@
      * can read and write files placed here.
      * </ul>
      *
+     * <p>On devices with multiple users (as described by {@link UserManager}),
+     * each user has their own isolated external storage. Applications only
+     * have access to the external storage for the user they're running as.</p>
+     *
+     * <p>Writing to this path requires the
+     * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permission.</p>
+     *
      * @return Returns the path of the directory holding application cache files
      * on external storage.  Returns null if external storage is not currently
      * mounted so it could not ensure the path exists; you will need to call
@@ -851,6 +909,20 @@
     public abstract void startActivity(Intent intent);
 
     /**
+     * Version of {@link #startActivity(Intent)} that allows you to specify the
+     * user the activity will be started for.  This is not available to applications
+     * that are not pre-installed on the system image.  Using it requires holding
+     * the INTERACT_ACROSS_USERS_FULL permission.
+     * @param intent The description of the activity to start.
+     * @param user The UserHandle of the user to start this activity for.
+     * @throws ActivityNotFoundException
+     * @hide
+     */
+    public void startActivityAsUser(Intent intent, UserHandle user) {
+        throw new RuntimeException("Not implemented. Must override in a subclass.");
+    }
+
+    /**
      * Launch a new activity.  You will not receive any information about when
      * the activity exits.
      *
@@ -878,6 +950,24 @@
     public abstract void startActivity(Intent intent, Bundle options);
 
     /**
+     * Version of {@link #startActivity(Intent, Bundle)} that allows you to specify the
+     * user the activity will be started for.  This is not available to applications
+     * that are not pre-installed on the system image.  Using it requires holding
+     * the INTERACT_ACROSS_USERS_FULL permission.
+     * @param intent The description of the activity to start.
+     * @param options Additional options for how the Activity should be started.
+     * May be null if there are no options.  See {@link android.app.ActivityOptions}
+     * for how to build the Bundle supplied here; there are no supported definitions
+     * for building it manually.
+     * @param user The UserHandle of the user to start this activity for.
+     * @throws ActivityNotFoundException
+     * @hide
+     */
+    public void startActivityAsUser(Intent intent, Bundle options, UserHandle userId) {
+        throw new RuntimeException("Not implemented. Must override in a subclass.");
+    }
+
+    /**
      * Same as {@link #startActivities(Intent[], Bundle)} with no options
      * specified.
      *
@@ -917,6 +1007,36 @@
     public abstract void startActivities(Intent[] intents, Bundle options);
 
     /**
+     * @hide
+     * Launch multiple new activities.  This is generally the same as calling
+     * {@link #startActivity(Intent)} for the first Intent in the array,
+     * that activity during its creation calling {@link #startActivity(Intent)}
+     * for the second entry, etc.  Note that unlike that approach, generally
+     * none of the activities except the last in the array will be created
+     * at this point, but rather will be created when the user first visits
+     * them (due to pressing back from the activity on top).
+     *
+     * <p>This method throws {@link ActivityNotFoundException}
+     * if there was no Activity found for <em>any</em> given Intent.  In this
+     * case the state of the activity stack is undefined (some Intents in the
+     * list may be on it, some not), so you probably want to avoid such situations.
+     *
+     * @param intents An array of Intents to be started.
+     * @param options Additional options for how the Activity should be started.
+     * @param userHandle The user for whom to launch the activities
+     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * Context.startActivity(Intent, Bundle)} for more details.
+     *
+     * @throws ActivityNotFoundException
+     *
+     * @see {@link #startActivities(Intent[])}
+     * @see PackageManager#resolveActivity
+     */
+    public void startActivitiesAsUser(Intent[] intents, Bundle options, UserHandle userHandle) {
+        throw new RuntimeException("Not implemented. Must override in a subclass.");
+    }
+
+    /**
      * Same as {@link #startIntentSender(IntentSender, Intent, int, int, int, Bundle)}
      * with no options specified.
      *
@@ -988,16 +1108,6 @@
     public abstract void sendBroadcast(Intent intent);
 
     /**
-     * Same as #sendBroadcast(Intent intent), but for a specific user. Used by the system only.
-     * @param intent the intent to broadcast
-     * @param userId user to send the intent to
-     * @hide
-     */
-    public void sendBroadcast(Intent intent, int userId) {
-        throw new RuntimeException("Not implemented. Must override in a subclass.");
-    }
-
-    /**
      * Broadcast the given intent to all interested BroadcastReceivers, allowing
      * an optional required permission to be enforced.  This
      * call is asynchronous; it returns immediately, and you will continue
@@ -1095,6 +1205,69 @@
             Bundle initialExtras);
 
     /**
+     * Version of {@link #sendBroadcast(Intent)} that allows you to specify the
+     * user the broadcast will be sent to.  This is not available to applications
+     * that are not pre-installed on the system image.  Using it requires holding
+     * the INTERACT_ACROSS_USERS permission.
+     * @param intent The intent to broadcast
+     * @param user UserHandle to send the intent to.
+     * @see #sendBroadcast(Intent)
+     */
+    public abstract void sendBroadcastAsUser(Intent intent, UserHandle user);
+
+    /**
+     * Version of {@link #sendBroadcast(Intent, String)} that allows you to specify the
+     * user the broadcast will be sent to.  This is not available to applications
+     * that are not pre-installed on the system image.  Using it requires holding
+     * the INTERACT_ACROSS_USERS permission.
+     *
+     * @param intent The Intent to broadcast; all receivers matching this
+     *               Intent will receive the broadcast.
+     * @param user UserHandle to send the intent to.
+     * @param receiverPermission (optional) String naming a permission that
+     *               a receiver must hold in order to receive your broadcast.
+     *               If null, no permission is required.
+     *
+     * @see #sendBroadcast(Intent, String)
+     */
+    public abstract void sendBroadcastAsUser(Intent intent, UserHandle user,
+            String receiverPermission);
+
+    /**
+     * Version of
+     * {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)}
+     * that allows you to specify the
+     * user the broadcast will be sent to.  This is not available to applications
+     * that are not pre-installed on the system image.  Using it requires holding
+     * the INTERACT_ACROSS_USERS permission.
+     *
+     * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
+     *
+     * @param intent The Intent to broadcast; all receivers matching this
+     *               Intent will receive the broadcast.
+     * @param user UserHandle to send the intent to.
+     * @param receiverPermission String naming a permissions that
+     *               a receiver must hold in order to receive your broadcast.
+     *               If null, no permission is required.
+     * @param resultReceiver Your own BroadcastReceiver to treat as the final
+     *                       receiver of the broadcast.
+     * @param scheduler A custom Handler with which to schedule the
+     *                  resultReceiver callback; if null it will be
+     *                  scheduled in the Context's main thread.
+     * @param initialCode An initial value for the result code.  Often
+     *                    Activity.RESULT_OK.
+     * @param initialData An initial value for the result data.  Often
+     *                    null.
+     * @param initialExtras An initial value for the result extras.  Often
+     *                      null.
+     *
+     * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
+     */
+    public abstract void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
+            String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
+            int initialCode, String initialData, Bundle initialExtras);
+
+    /**
      * Perform a {@link #sendBroadcast(Intent)} that is "sticky," meaning the
      * Intent you are sending stays around after the broadcast is complete,
      * so that others can quickly retrieve that data through the return
@@ -1160,7 +1333,6 @@
             Handler scheduler, int initialCode, String initialData,
             Bundle initialExtras);
 
-
     /**
      * Remove the data previously sent with {@link #sendStickyBroadcast},
      * so that it is as if the sticky broadcast had never happened.
@@ -1176,6 +1348,70 @@
     public abstract void removeStickyBroadcast(Intent intent);
 
     /**
+     * Version of {@link #sendStickyBroadcast(Intent)} that allows you to specify the
+     * user the broadcast will be sent to.  This is not available to applications
+     * that are not pre-installed on the system image.  Using it requires holding
+     * the INTERACT_ACROSS_USERS permission.
+     *
+     * @param intent The Intent to broadcast; all receivers matching this
+     * Intent will receive the broadcast, and the Intent will be held to
+     * be re-broadcast to future receivers.
+     * @param user UserHandle to send the intent to.
+     *
+     * @see #sendBroadcast(Intent)
+     */
+    public abstract void sendStickyBroadcastAsUser(Intent intent, UserHandle user);
+
+    /**
+     * Version of
+     * {@link #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle)}
+     * that allows you to specify the
+     * user the broadcast will be sent to.  This is not available to applications
+     * that are not pre-installed on the system image.  Using it requires holding
+     * the INTERACT_ACROSS_USERS permission.
+     *
+     * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
+     *
+     * @param intent The Intent to broadcast; all receivers matching this
+     *               Intent will receive the broadcast.
+     * @param user UserHandle to send the intent to.
+     * @param resultReceiver Your own BroadcastReceiver to treat as the final
+     *                       receiver of the broadcast.
+     * @param scheduler A custom Handler with which to schedule the
+     *                  resultReceiver callback; if null it will be
+     *                  scheduled in the Context's main thread.
+     * @param initialCode An initial value for the result code.  Often
+     *                    Activity.RESULT_OK.
+     * @param initialData An initial value for the result data.  Often
+     *                    null.
+     * @param initialExtras An initial value for the result extras.  Often
+     *                      null.
+     *
+     * @see #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle)
+     */
+    public abstract void sendStickyOrderedBroadcastAsUser(Intent intent,
+            UserHandle user, BroadcastReceiver resultReceiver,
+            Handler scheduler, int initialCode, String initialData,
+            Bundle initialExtras);
+
+    /**
+     * Version of {@link #removeStickyBroadcast(Intent)} that allows you to specify the
+     * user the broadcast will be sent to.  This is not available to applications
+     * that are not pre-installed on the system image.  Using it requires holding
+     * the INTERACT_ACROSS_USERS permission.
+     *
+     * <p>You must hold the {@link android.Manifest.permission#BROADCAST_STICKY}
+     * permission in order to use this API.  If you do not hold that
+     * permission, {@link SecurityException} will be thrown.
+     *
+     * @param intent The Intent that was previously broadcast.
+     * @param user UserHandle to remove the sticky broadcast from.
+     *
+     * @see #sendStickyBroadcastAsUser
+     */
+    public abstract void removeStickyBroadcastAsUser(Intent intent, UserHandle user);
+
+    /**
      * Register a BroadcastReceiver to be run in the main activity thread.  The
      * <var>receiver</var> will be called with any broadcast Intent that
      * matches <var>filter</var>, in the main application thread.
@@ -1258,9 +1494,35 @@
      * @see #unregisterReceiver
      */
     public abstract Intent registerReceiver(BroadcastReceiver receiver,
-                                            IntentFilter filter,
-                                            String broadcastPermission,
-                                            Handler scheduler);
+            IntentFilter filter, String broadcastPermission, Handler scheduler);
+
+    /**
+     * @hide
+     * Same as {@link #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)
+     * but for a specific user.  This receiver will receiver broadcasts that
+     * are sent to the requested user.  It
+     * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}
+     * permission.
+     *
+     * @param receiver The BroadcastReceiver to handle the broadcast.
+     * @param user UserHandle to send the intent to.
+     * @param filter Selects the Intent broadcasts to be received.
+     * @param broadcastPermission String naming a permissions that a
+     *      broadcaster must hold in order to send an Intent to you.  If null,
+     *      no permission is required.
+     * @param scheduler Handler identifying the thread that will receive
+     *      the Intent.  If null, the main thread of the process will be used.
+     *
+     * @return The first sticky intent found that matches <var>filter</var>,
+     *         or null if there are none.
+     *
+     * @see #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler
+     * @see #sendBroadcast
+     * @see #unregisterReceiver
+     */
+    public abstract Intent registerReceiverAsUser(BroadcastReceiver receiver,
+            UserHandle user, IntentFilter filter, String broadcastPermission,
+            Handler scheduler);
 
     /**
      * Unregister a previously registered BroadcastReceiver.  <em>All</em>
@@ -1351,6 +1613,16 @@
     public abstract boolean stopService(Intent service);
 
     /**
+     * @hide like {@link #startService(Intent)} but for a specific user.
+     */
+    public abstract ComponentName startServiceAsUser(Intent service, UserHandle user);
+
+    /**
+     * @hide like {@link #stopService(Intent)} but for a specific user.
+     */
+    public abstract boolean stopServiceAsUser(Intent service, UserHandle user);
+    
+    /**
      * Connect to an application service, creating it if needed.  This defines
      * a dependency between your application and the service.  The given
      * <var>conn</var> will receive the service object when it is created and be
@@ -1379,6 +1651,7 @@
      *      description (action, category, etc) to match an
      *      {@link IntentFilter} published by a service.
      * @param conn Receives information as the service is started and stopped.
+     *      This must be a valid ServiceConnection object; it must not be null.
      * @param flags Operation options for the binding.  May be 0,
      *          {@link #BIND_AUTO_CREATE}, {@link #BIND_DEBUG_UNBIND},
      *          {@link #BIND_NOT_FOREGROUND}, {@link #BIND_ABOVE_CLIENT},
@@ -1400,11 +1673,11 @@
             int flags);
 
     /**
-     * Same as {@link #bindService(Intent, ServiceConnection, int)}, but with an explicit userId
+     * Same as {@link #bindService(Intent, ServiceConnection, int)}, but with an explicit userHandle
      * argument for use by system server and other multi-user aware code.
      * @hide
      */
-    public boolean bindService(Intent service, ServiceConnection conn, int flags, int userId) {
+    public boolean bindService(Intent service, ServiceConnection conn, int flags, int userHandle) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
     }
 
@@ -1414,7 +1687,7 @@
      * stop at any time.
      *
      * @param conn The connection interface previously supplied to
-     *             bindService().
+     *             bindService().  This parameter must not be null.
      *
      * @see #bindService
      */
@@ -1906,6 +2179,15 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
+     * {@link android.bluetooth.BluetoothAdapter} for using Bluetooth.
+     *
+     * @see #getSystemService
+     * @hide
+     */
+    public static final String BLUETOOTH_SERVICE = "bluetooth";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a
      * {@link android.net.sip.SipManager} for accessing the SIP related service.
      *
      * @see #getSystemService
@@ -1945,6 +2227,15 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
+     * {@link android.hardware.display.DisplayManager} for interacting with display devices.
+     *
+     * @see #getSystemService
+     * @see android.hardware.display.DisplayManager
+     */
+    public static final String DISPLAY_SERVICE = "display";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a
      * {@link android.os.SchedulingPolicyService} for managing scheduling policy.
      *
      * @see #getSystemService
@@ -1955,6 +2246,15 @@
     public static final String SCHEDULING_POLICY_SERVICE = "scheduling_policy";
 
     /**
+     * Use with {@link #getSystemService} to retrieve a
+     * {@link android.os.UserManager} for managing users on devices that support multiple users.
+     *
+     * @see #getSystemService
+     * @see android.os.UserManager
+     */
+    public static final String USER_SERVICE = "user";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
@@ -2357,6 +2657,65 @@
             int flags) throws PackageManager.NameNotFoundException;
 
     /**
+     * Similar to {@link #createPackageContext(String, int)}, but with a
+     * different {@link UserHandle}. For example, {@link #getContentResolver()}
+     * will open any {@link Uri} as the given user.
+     *
+     * @hide
+     */
+    public abstract Context createPackageContextAsUser(
+            String packageName, int flags, UserHandle user)
+            throws PackageManager.NameNotFoundException;
+
+    /**
+     * Return a new Context object for the current Context but whose resources
+     * are adjusted to match the given Configuration.  Each call to this method
+     * returns a new instance of a Context object; Context objects are not
+     * shared, however common state (ClassLoader, other Resources for the
+     * same configuration) may be so the Context itself can be fairly lightweight.
+     *
+     * @param overrideConfiguration A {@link Configuration} specifying what
+     * values to modify in the base Configuration of the original Context's
+     * resources.  If the base configuration changes (such as due to an
+     * orientation change), the resources of this context will also change except
+     * for those that have been explicitly overridden with a value here.
+     *
+     * @return A Context with the given configuration override.
+     */
+    public abstract Context createConfigurationContext(Configuration overrideConfiguration);
+
+    /**
+     * Return a new Context object for the current Context but whose resources
+     * are adjusted to match the metrics of the given Display.  Each call to this method
+     * returns a new instance of a Context object; Context objects are not
+     * shared, however common state (ClassLoader, other Resources for the
+     * same configuration) may be so the Context itself can be fairly lightweight.
+     *
+     * The returned display Context provides a {@link WindowManager}
+     * (see {@link #getSystemService(String)}) that is configured to show windows
+     * on the given display.  The WindowManager's {@link WindowManager#getDefaultDisplay}
+     * method can be used to retrieve the Display from the returned Context.
+     *
+     * @param display A {@link Display} object specifying the display
+     * for whose metrics the Context's resources should be tailored and upon which
+     * new windows should be shown.
+     *
+     * @return A Context for the display.
+     */
+    public abstract Context createDisplayContext(Display display);
+
+    /**
+     * Gets the compatibility info holder for this context.  This information
+     * is provided on a per-application basis and is used to simulate lower density
+     * display metrics for legacy applications.
+     *
+     * @param displayId The display id for which to get compatibility info.
+     * @return The compatibility info holder, or null if not required by the application.
+     * @hide
+     */
+    public abstract CompatibilityInfoHolder getCompatibilityInfo(int displayId);
+
+    /**
      * Indicates whether this Context is restricted.
      *
      * @return True if this Context is restricted, false otherwise.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 6b950e0..84ad667 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -16,9 +16,13 @@
 
 package android.content;
 
+import android.app.Activity;
+import android.app.ActivityManagerNative;
+import android.app.LoadedApk;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.AssetManager;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.DatabaseErrorHandler;
 import android.database.sqlite.SQLiteDatabase;
@@ -29,6 +33,10 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.view.CompatibilityInfoHolder;
+import android.view.Display;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -276,11 +284,23 @@
         mBase.startActivity(intent);
     }
 
+    /** @hide */
+    @Override
+    public void startActivityAsUser(Intent intent, UserHandle user) {
+        mBase.startActivityAsUser(intent, user);
+    }
+
     @Override
     public void startActivity(Intent intent, Bundle options) {
         mBase.startActivity(intent, options);
     }
 
+    /** @hide */
+    @Override
+    public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) {
+        mBase.startActivityAsUser(intent, options, user);
+    }
+
     @Override
     public void startActivities(Intent[] intents) {
         mBase.startActivities(intents);
@@ -291,6 +311,12 @@
         mBase.startActivities(intents, options);
     }
 
+    /** @hide */
+    @Override
+    public void startActivitiesAsUser(Intent[] intents, Bundle options, UserHandle userHandle) {
+        mBase.startActivitiesAsUser(intents, options, userHandle);
+    }
+
     @Override
     public void startIntentSender(IntentSender intent,
             Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
@@ -312,12 +338,6 @@
         mBase.sendBroadcast(intent);
     }
 
-    /** @hide */
-    @Override
-    public void sendBroadcast(Intent intent, int userId) {
-        mBase.sendBroadcast(intent, userId);
-    }
-
     @Override
     public void sendBroadcast(Intent intent, String receiverPermission) {
         mBase.sendBroadcast(intent, receiverPermission);
@@ -340,6 +360,25 @@
     }
 
     @Override
+    public void sendBroadcastAsUser(Intent intent, UserHandle user) {
+        mBase.sendBroadcastAsUser(intent, user);
+    }
+
+    @Override
+    public void sendBroadcastAsUser(Intent intent, UserHandle user,
+            String receiverPermission) {
+        mBase.sendBroadcastAsUser(intent, user, receiverPermission);
+    }
+
+    @Override
+    public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
+            String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
+            int initialCode, String initialData, Bundle initialExtras) {
+        mBase.sendOrderedBroadcastAsUser(intent, user, receiverPermission, resultReceiver,
+                scheduler, initialCode, initialData, initialExtras);
+    }
+
+    @Override
     public void sendStickyBroadcast(Intent intent) {
         mBase.sendStickyBroadcast(intent);
     }
@@ -360,6 +399,25 @@
     }
 
     @Override
+    public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
+        mBase.sendStickyBroadcastAsUser(intent, user);
+    }
+
+    @Override
+    public void sendStickyOrderedBroadcastAsUser(Intent intent,
+            UserHandle user, BroadcastReceiver resultReceiver,
+            Handler scheduler, int initialCode, String initialData,
+            Bundle initialExtras) {
+        mBase.sendStickyOrderedBroadcastAsUser(intent, user, resultReceiver,
+                scheduler, initialCode, initialData, initialExtras);
+    }
+
+    @Override
+    public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
+        mBase.removeStickyBroadcastAsUser(intent, user);
+    }
+
+    @Override
     public Intent registerReceiver(
         BroadcastReceiver receiver, IntentFilter filter) {
         return mBase.registerReceiver(receiver, filter);
@@ -373,6 +431,15 @@
                 scheduler);
     }
 
+    /** @hide */
+    @Override
+    public Intent registerReceiverAsUser(
+        BroadcastReceiver receiver, UserHandle user, IntentFilter filter,
+        String broadcastPermission, Handler scheduler) {
+        return mBase.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
+                scheduler);
+    }
+
     @Override
     public void unregisterReceiver(BroadcastReceiver receiver) {
         mBase.unregisterReceiver(receiver);
@@ -388,6 +455,18 @@
         return mBase.stopService(name);
     }
 
+    /** @hide */
+    @Override
+    public ComponentName startServiceAsUser(Intent service, UserHandle user) {
+        return mBase.startServiceAsUser(service, user);
+    }
+
+    /** @hide */
+    @Override
+    public boolean stopServiceAsUser(Intent name, UserHandle user) {
+        return mBase.stopServiceAsUser(name, user);
+    }
+
     @Override
     public boolean bindService(Intent service, ServiceConnection conn,
             int flags) {
@@ -396,8 +475,8 @@
 
     /** @hide */
     @Override
-    public boolean bindService(Intent service, ServiceConnection conn, int flags, int userId) {
-        return mBase.bindService(service, conn, flags, userId);
+    public boolean bindService(Intent service, ServiceConnection conn, int flags, int userHandle) {
+        return mBase.bindService(service, conn, flags, userHandle);
     }
 
     @Override
@@ -513,8 +592,31 @@
         return mBase.createPackageContext(packageName, flags);
     }
 
+    /** @hide */
+    @Override
+    public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
+            throws PackageManager.NameNotFoundException {
+        return mBase.createPackageContextAsUser(packageName, flags, user);
+    }
+
+    @Override
+    public Context createConfigurationContext(Configuration overrideConfiguration) {
+        return mBase.createConfigurationContext(overrideConfiguration);
+    }
+
+    @Override
+    public Context createDisplayContext(Display display) {
+        return mBase.createDisplayContext(display);
+    }
+
     @Override
     public boolean isRestricted() {
         return mBase.isRestricted();
     }
+
+    /** @hide */
+    @Override
+    public CompatibilityInfoHolder getCompatibilityInfo(int displayId) {
+        return mBase.getCompatibilityInfo(displayId);
+    }
 }
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 86a9392..f956bcf 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -30,12 +30,28 @@
  * @hide
  */
 interface IContentService {
-    void registerContentObserver(in Uri uri, boolean notifyForDescendentsn,
-            IContentObserver observer);
     void unregisterContentObserver(IContentObserver observer);
 
+    /**
+     * Register a content observer tied to a specific user's view of the provider.
+     * @param userHandle the user whose view of the provider is to be observed.  May be
+     *     the calling user without requiring any permission, otherwise the caller needs to
+     *     hold the INTERACT_ACROSS_USERS_FULL permission.  Pseudousers USER_ALL and
+     *     USER_CURRENT are properly handled.
+     */
+    void registerContentObserver(in Uri uri, boolean notifyForDescendants,
+            IContentObserver observer, int userHandle);
+
+    /**
+     * Notify observers of a particular user's view of the provider.
+     * @param userHandle the user whose view of the provider is to be notified.  May be
+     *     the calling user without requiring any permission, otherwise the caller needs to
+     *     hold the INTERACT_ACROSS_USERS_FULL permission.  Pseudousers USER_ALL
+     *     USER_CURRENT are properly interpreted.
+     */
     void notifyChange(in Uri uri, IContentObserver observer,
-            boolean observerWantsSelfNotifications, boolean syncToNetwork);
+            boolean observerWantsSelfNotifications, boolean syncToNetwork,
+            int userHandle);
 
     void requestSync(in Account account, String authority, in Bundle extras);
     void cancelSync(in Account account, String authority);
diff --git a/core/java/android/content/IIntentReceiver.aidl b/core/java/android/content/IIntentReceiver.aidl
index 6f2f7c4..3d92723 100755
--- a/core/java/android/content/IIntentReceiver.aidl
+++ b/core/java/android/content/IIntentReceiver.aidl
@@ -27,7 +27,7 @@
  * {@hide}
  */
 oneway interface IIntentReceiver {
-    void performReceive(in Intent intent, int resultCode,
-            String data, in Bundle extras, boolean ordered, boolean sticky);
+    void performReceive(in Intent intent, int resultCode, String data,
+            in Bundle extras, boolean ordered, boolean sticky, int sendingUser);
 }
 
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 3fdf451..cf0603e 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -27,7 +27,6 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
-import android.media.RemoteControlClient;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -571,7 +570,9 @@
  *     <li> {@link #EXTRA_INITIAL_INTENTS}
  *     <li> {@link #EXTRA_INTENT}
  *     <li> {@link #EXTRA_KEY_EVENT}
+ *     <li> {@link #EXTRA_ORIGINATING_URI}
  *     <li> {@link #EXTRA_PHONE_NUMBER}
+ *     <li> {@link #EXTRA_REFERRER}
  *     <li> {@link #EXTRA_REMOTE_INTENT_TOKEN}
  *     <li> {@link #EXTRA_REPLACING}
  *     <li> {@link #EXTRA_SHORTCUT_ICON}
@@ -1253,7 +1254,9 @@
      * Activity Action: Launch application installer.
      * <p>
      * Input: The data must be a content: or file: URI at which the application
-     * can be retrieved.  You can optionally supply
+     * can be retrieved.  As of {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1},
+     * you can also use "package:<package-name>" to install an application for the
+     * current user that is already installed for another user. You can optionally supply
      * {@link #EXTRA_INSTALLER_PACKAGE_NAME}, {@link #EXTRA_NOT_UNKNOWN_SOURCE},
      * {@link #EXTRA_ALLOW_REPLACE}, and {@link #EXTRA_RETURN_RESULT}.
      * <p>
@@ -1286,6 +1289,30 @@
             = "android.intent.extra.NOT_UNKNOWN_SOURCE";
 
     /**
+     * Used as a URI extra field with {@link #ACTION_INSTALL_PACKAGE} and
+     * {@link #ACTION_VIEW} to indicate the URI from which the local APK in the Intent
+     * data field originated from.
+     */
+    public static final String EXTRA_ORIGINATING_URI
+            = "android.intent.extra.ORIGINATING_URI";
+
+    /**
+     * Used as a URI extra field with {@link #ACTION_INSTALL_PACKAGE} and
+     * {@link #ACTION_VIEW} to indicate the HTTP referrer URI associated with the Intent
+     * data field or {@link #EXTRA_ORIGINATING_URI}.
+     */
+    public static final String EXTRA_REFERRER
+            = "android.intent.extra.REFERRER";
+
+    /**
+     * Used as an int extra field with {@link #ACTION_INSTALL_PACKAGE} and
+     * {@link} #ACTION_VIEW} to indicate the uid of the package that initiated the install
+     * @hide
+     */
+    public static final String EXTRA_ORIGINATING_UID
+            = "android.intent.extra.ORIGINATING_UID";
+
+    /**
      * Used as a boolean extra field with {@link #ACTION_INSTALL_PACKAGE} to install a
      * package.  Tells the installer UI to skip the confirmation with the user
      * if the .apk is replacing an existing one.
@@ -1328,6 +1355,13 @@
     public static final String ACTION_UNINSTALL_PACKAGE = "android.intent.action.UNINSTALL_PACKAGE";
 
     /**
+     * Specify whether the package should be uninstalled for all users.
+     * @hide because these should not be part of normal application flow.
+     */
+    public static final String EXTRA_UNINSTALL_ALL_USERS
+            = "android.intent.extra.UNINSTALL_ALL_USERS";
+
+    /**
      * A string associated with a {@link #ACTION_UPGRADE_SETUP} activity
      * describing the last run version of the platform that was setup.
      * @hide
@@ -1356,6 +1390,24 @@
     public static final String ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON";
 
     /**
+     * Broadcast Action: Sent after the system stops dreaming.
+     *
+     * <p class="note">This is a protected intent that can only be sent by the system.
+     * It is only sent to registered receivers.</p>
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_DREAMING_STOPPED = "android.intent.action.DREAMING_STOPPED";
+
+    /**
+     * Broadcast Action: Sent after the system starts dreaming.
+     *
+     * <p class="note">This is a protected intent that can only be sent by the system.
+     * It is only sent to registered receivers.</p>
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_DREAMING_STARTED = "android.intent.action.DREAMING_STARTED";
+
+    /**
      * Broadcast Action: Sent when the user is present after device wakes up (e.g when the
      * keyguard is gone).
      *
@@ -1456,7 +1508,7 @@
      * Broadcast Action: A new application package has been installed on the
      * device. The data contains the name of the package.  Note that the
      * newly installed package does <em>not</em> receive this broadcast.
-     * <p>My include the following extras:
+     * <p>May include the following extras:
      * <ul>
      * <li> {@link #EXTRA_UID} containing the integer uid assigned to the new package.
      * <li> {@link #EXTRA_REPLACING} is set to true if this is following
@@ -1472,7 +1524,7 @@
      * Broadcast Action: A new version of an application package has been
      * installed, replacing an existing version that was previously installed.
      * The data contains the name of the package.
-     * <p>My include the following extras:
+     * <p>May include the following extras:
      * <ul>
      * <li> {@link #EXTRA_UID} containing the integer uid assigned to the new package.
      * </ul>
@@ -1624,6 +1676,15 @@
     public static final String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION";
 
     /**
+     * Broadcast Action: Sent to the system package verifier when a package is
+     * verified. The data contains the package URI.
+     * <p class="note">
+     * This is a protected intent that can only be sent by the system.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_PACKAGE_VERIFIED = "android.intent.action.PACKAGE_VERIFIED";
+
+    /**
      * Broadcast Action: Resources for a set of packages (which were
      * previously unavailable) are currently
      * available since the media on which they exist is available.
@@ -2261,29 +2322,149 @@
             "android.intent.action.PRE_BOOT_COMPLETED";
 
     /**
-     * Broadcast sent to the system when a user is added. Carries an extra EXTRA_USERID that has the
-     * userid of the new user.
+     * Sent the first time a user is starting, to allow system apps to
+     * perform one time initialization.  (This will not be seen by third
+     * party applications because a newly initialized user does not have any
+     * third party applications installed for it.)  This is sent early in
+     * starting the user, around the time the home app is started, before
+     * {@link #ACTION_BOOT_COMPLETED} is sent.  This is sent as a foreground
+     * broadcast, since it is part of a visible user interaction; be as quick
+     * as possible when handling it.
+     */
+    public static final String ACTION_USER_INITIALIZE =
+            "android.intent.action.USER_INITIALIZE";
+
+    /**
+     * Sent when a user switch is happening, causing the process's user to be
+     * brought to the foreground.  This is only sent to receivers registered
+     * through {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
+     * Context.registerReceiver}.  It is sent to the user that is going to the
+     * foreground.  This is sent as a foreground
+     * broadcast, since it is part of a visible user interaction; be as quick
+     * as possible when handling it.
+     */
+    public static final String ACTION_USER_FOREGROUND =
+            "android.intent.action.USER_FOREGROUND";
+
+    /**
+     * Sent when a user switch is happening, causing the process's user to be
+     * sent to the background.  This is only sent to receivers registered
+     * through {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
+     * Context.registerReceiver}.  It is sent to the user that is going to the
+     * background.  This is sent as a foreground
+     * broadcast, since it is part of a visible user interaction; be as quick
+     * as possible when handling it.
+     */
+    public static final String ACTION_USER_BACKGROUND =
+            "android.intent.action.USER_BACKGROUND";
+
+    /**
+     * Broadcast sent to the system when a user is added. Carries an extra
+     * EXTRA_USER_HANDLE that has the userHandle of the new user.  It is sent to
+     * all running users.  You must hold
+     * {@link android.Manifest.permission#MANAGE_USERS} to receive this broadcast.
      * @hide
      */
     public static final String ACTION_USER_ADDED =
             "android.intent.action.USER_ADDED";
 
     /**
-     * Broadcast sent to the system when a user is removed. Carries an extra EXTRA_USERID that has
-     * the userid of the user.
+     * Broadcast sent by the system when a user is started. Carries an extra
+     * EXTRA_USER_HANDLE that has the userHandle of the user.  This is only sent to
+     * registered receivers, not manifest receivers.  It is sent to the user
+     * that has been started.  This is sent as a foreground
+     * broadcast, since it is part of a visible user interaction; be as quick
+     * as possible when handling it.
+     * @hide
+     */
+    public static final String ACTION_USER_STARTED =
+            "android.intent.action.USER_STARTED";
+
+    /**
+     * Broadcast sent when a user is in the process of starting.  Carries an extra
+     * EXTRA_USER_HANDLE that has the userHandle of the user.  This is only
+     * sent to registered receivers, not manifest receivers.  It is sent to all
+     * users (including the one that is being started).  You must hold
+     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS} to receive
+     * this broadcast.  This is sent as a background broadcast, since
+     * its result is not part of the primary UX flow; to safely keep track of
+     * started/stopped state of a user you can use this in conjunction with
+     * {@link #ACTION_USER_STOPPING}.  It is <b>not</b> generally safe to use with
+     * other user state broadcasts since those are foreground broadcasts so can
+     * execute in a different order.
+     * @hide
+     */
+    public static final String ACTION_USER_STARTING =
+            "android.intent.action.USER_STARTING";
+
+    /**
+     * Broadcast sent when a user is going to be stopped.  Carries an extra
+     * EXTRA_USER_HANDLE that has the userHandle of the user.  This is only
+     * sent to registered receivers, not manifest receivers.  It is sent to all
+     * users (including the one that is being stopped).  You must hold
+     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS} to receive
+     * this broadcast.  The user will not stop until all receivers have
+     * handled the broadcast.  This is sent as a background broadcast, since
+     * its result is not part of the primary UX flow; to safely keep track of
+     * started/stopped state of a user you can use this in conjunction with
+     * {@link #ACTION_USER_STARTING}.  It is <b>not</b> generally safe to use with
+     * other user state broadcasts since those are foreground broadcasts so can
+     * execute in a different order.
+     * @hide
+     */
+    public static final String ACTION_USER_STOPPING =
+            "android.intent.action.USER_STOPPING";
+
+    /**
+     * Broadcast sent to the system when a user is stopped. Carries an extra
+     * EXTRA_USER_HANDLE that has the userHandle of the user.  This is similar to
+     * {@link #ACTION_PACKAGE_RESTARTED}, but for an entire user instead of a
+     * specific package.  This is only sent to registered receivers, not manifest
+     * receivers.  It is sent to all running users <em>except</em> the one that
+     * has just been stopped (which is no longer running).
+     * @hide
+     */
+    public static final String ACTION_USER_STOPPED =
+            "android.intent.action.USER_STOPPED";
+
+    /**
+     * Broadcast sent to the system when a user is removed. Carries an extra EXTRA_USER_HANDLE that has
+     * the userHandle of the user.  It is sent to all running users except the
+     * one that has been removed. The user will not be completely removed until all receivers have
+     * handled the broadcast. You must hold
+     * {@link android.Manifest.permission#MANAGE_USERS} to receive this broadcast.
      * @hide
      */
     public static final String ACTION_USER_REMOVED =
             "android.intent.action.USER_REMOVED";
 
     /**
-     * Broadcast sent to the system when the user switches. Carries an extra EXTRA_USERID that has
-     * the userid of the user to become the current one.
+     * Broadcast sent to the system when the user switches. Carries an extra EXTRA_USER_HANDLE that has
+     * the userHandle of the user to become the current one. This is only sent to
+     * registered receivers, not manifest receivers.  It is sent to all running users.
+     * You must hold
+     * {@link android.Manifest.permission#MANAGE_USERS} to receive this broadcast.
      * @hide
      */
     public static final String ACTION_USER_SWITCHED =
             "android.intent.action.USER_SWITCHED";
 
+    /**
+     * Broadcast sent to the system when a user's information changes. Carries an extra
+     * {@link #EXTRA_USER_HANDLE} to indicate which user's information changed.
+     * This is only sent to registered receivers, not manifest receivers. It is sent to the user
+     * whose information has changed.
+     * @hide
+     */
+    public static final String ACTION_USER_INFO_CHANGED =
+            "android.intent.action.USER_INFO_CHANGED";
+
+    /**
+     * Sent when the user taps on the clock widget in the system's "quick settings" area.
+     */
+    public static final String ACTION_QUICK_CLOCK =
+            "android.intent.action.QUICK_CLOCK";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Standard intent categories (see addCategory()).
@@ -2693,6 +2874,15 @@
     public static final String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED";
 
     /**
+     * @hide
+     * Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED}
+     * intents to indicate that at this point the package has been removed for
+     * all users on the device.
+     */
+    public static final String EXTRA_REMOVED_FOR_ALL_USERS
+            = "android.intent.extra.REMOVED_FOR_ALL_USERS";
+
+    /**
      * Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED}
      * intents to indicate that this is a replacement of the package, so this
      * broadcast will immediately be followed by an add broadcast for a
@@ -2834,12 +3024,12 @@
         "android.intent.extra.LOCAL_ONLY";
 
     /**
-     * The userid carried with broadcast intents related to addition, removal and switching of users
+     * The userHandle carried with broadcast intents related to addition, removal and switching of users
      * - {@link #ACTION_USER_ADDED}, {@link #ACTION_USER_REMOVED} and {@link #ACTION_USER_SWITCHED}.
      * @hide
      */
-    public static final String EXTRA_USERID =
-            "android.intent.extra.user_id";
+    public static final String EXTRA_USER_HANDLE =
+            "android.intent.extra.user_handle";
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 4db4bdc..166495b 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -27,6 +27,7 @@
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
 import android.util.AndroidException;
 
 
@@ -113,8 +114,8 @@
             mWho = who;
             mHandler = handler;
         }
-        public void performReceive(Intent intent, int resultCode,
-                String data, Bundle extras, boolean serialized, boolean sticky) {
+        public void performReceive(Intent intent, int resultCode, String data,
+                Bundle extras, boolean serialized, boolean sticky, int sendingUser) {
             mIntent = intent;
             mResultCode = resultCode;
             mResultData = data;
@@ -204,6 +205,20 @@
     }
 
     /**
+     * @deprecated Renamed to {@link #getCreatorPackage()}.
+     */
+    @Deprecated
+    public String getTargetPackage() {
+        try {
+            return ActivityManagerNative.getDefault()
+                .getPackageForIntentSender(mTarget);
+        } catch (RemoteException e) {
+            // Should never happen.
+            return null;
+        }
+    }
+
+    /**
      * Return the package name of the application that created this
      * IntentSender, that is the identity under which you will actually be
      * sending the Intent.  The returned string is supplied by the system, so
@@ -212,7 +227,7 @@
      * @return The package name of the PendingIntent, or null if there is
      * none associated with it.
      */
-    public String getTargetPackage() {
+    public String getCreatorPackage() {
         try {
             return ActivityManagerNative.getDefault()
                 .getPackageForIntentSender(mTarget);
@@ -223,6 +238,47 @@
     }
 
     /**
+     * Return the uid of the application that created this
+     * PendingIntent, that is the identity under which you will actually be
+     * sending the Intent.  The returned integer is supplied by the system, so
+     * that an application can not spoof its uid.
+     *
+     * @return The uid of the PendingIntent, or -1 if there is
+     * none associated with it.
+     */
+    public int getCreatorUid() {
+        try {
+            return ActivityManagerNative.getDefault()
+                .getUidForIntentSender(mTarget);
+        } catch (RemoteException e) {
+            // Should never happen.
+            return -1;
+        }
+    }
+
+    /**
+     * Return the user handle of the application that created this
+     * PendingIntent, that is the user under which you will actually be
+     * sending the Intent.  The returned UserHandle is supplied by the system, so
+     * that an application can not spoof its user.  See
+     * {@link android.os.Process#myUserHandle() Process.myUserHandle()} for
+     * more explanation of user handles.
+     *
+     * @return The user handle of the PendingIntent, or null if there is
+     * none associated with it.
+     */
+    public UserHandle getCreatorUserHandle() {
+        try {
+            int uid = ActivityManagerNative.getDefault()
+                .getUidForIntentSender(mTarget);
+            return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
+        } catch (RemoteException e) {
+            // Should never happen.
+            return null;
+        }
+    }
+
+    /**
      * Comparison operator on two IntentSender objects, such that true
      * is returned then they both represent the same operation from the
      * same package.
diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
index bdc38d6..da5480e 100644
--- a/core/java/android/content/SharedPreferences.java
+++ b/core/java/android/content/SharedPreferences.java
@@ -25,7 +25,8 @@
  * there is a single instance of this class that all clients share.
  * Modifications to the preferences must go through an {@link Editor} object
  * to ensure the preference values remain in a consistent state and control
- * when they are committed to storage.
+ * when they are committed to storage.  Objects that are returned from the
+ * various <code>get</code> methods must be treated as immutable by the application.
  *
  * <p><em>Note: currently this class does not support use across multiple
  * processes.  This will be added later.</em>
@@ -226,6 +227,10 @@
     /**
      * Retrieve all values from the preferences.
      *
+     * <p>Note that you <em>must not</em> modify the collection returned
+     * by this method, or alter any of its contents.  The consistency of your
+     * stored data is not guaranteed if you do.
+     *
      * @return Returns a map containing a list of pairs key/value representing
      * the preferences.
      *
@@ -250,6 +255,10 @@
     /**
      * Retrieve a set of String values from the preferences.
      * 
+     * <p>Note that you <em>must not</em> modify the set instance returned
+     * by this call.  The consistency of the stored data is not guaranteed
+     * if you do, nor is your ability to modify the instance at all.
+     *
      * @param key The name of the preference to retrieve.
      * @param defValues Values to return if this preference does not exist.
      * 
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index badcb03..977b461 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -16,18 +16,12 @@
 
 package android.content;
 
-import com.android.internal.R;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-
 import android.accounts.Account;
 import android.accounts.AccountAndUser;
 import android.accounts.AccountManager;
 import android.accounts.AccountManagerService;
-import android.accounts.OnAccountsUpdateListener;
 import android.app.ActivityManager;
 import android.app.AlarmManager;
-import android.app.AppGlobals;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -52,7 +46,8 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.os.UserId;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.text.format.DateUtils;
@@ -60,6 +55,13 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Pair;
+import android.util.Slog;
+
+import com.android.internal.R;
+import com.android.internal.util.IndentingPrintWriter;
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
+import com.google.android.collect.Sets;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -74,12 +76,13 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
+import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 
 /**
  * @hide
  */
-public class SyncManager implements OnAccountsUpdateListener {
+public class SyncManager {
     private static final String TAG = "SyncManager";
 
     /** Delay a sync due to local changes this long. In milliseconds */
@@ -139,7 +142,8 @@
 
     private static final AccountAndUser[] INITIAL_ACCOUNTS_ARRAY = new AccountAndUser[0];
 
-    private volatile AccountAndUser[] mAccounts = INITIAL_ACCOUNTS_ARRAY;
+    // TODO: add better locking around mRunningAccounts
+    private volatile AccountAndUser[] mRunningAccounts = INITIAL_ACCOUNTS_ARRAY;
 
     volatile private PowerManager.WakeLock mHandleAlarmWakeLock;
     volatile private PowerManager.WakeLock mSyncManagerWakeLock;
@@ -150,7 +154,9 @@
     private AlarmManager mAlarmService = null;
 
     private SyncStorageEngine mSyncStorageEngine;
-    public SyncQueue mSyncQueue;
+
+    // @GuardedBy("mSyncQueue")
+    private final SyncQueue mSyncQueue;
 
     protected final ArrayList<ActiveSyncContext> mActiveSyncContexts = Lists.newArrayList();
 
@@ -173,7 +179,7 @@
                             Log.v(TAG, "Internal storage is low.");
                         }
                         mStorageIsLow = true;
-                        cancelActiveSync(null /* any account */, UserId.USER_ALL,
+                        cancelActiveSync(null /* any account */, UserHandle.USER_ALL,
                                 null /* any authority */);
                     } else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) {
                         if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -194,28 +200,34 @@
     private BroadcastReceiver mBackgroundDataSettingChanged = new BroadcastReceiver() {
         public void onReceive(Context context, Intent intent) {
             if (getConnectivityManager().getBackgroundDataSetting()) {
-                scheduleSync(null /* account */, UserId.USER_ALL, null /* authority */,
+                scheduleSync(null /* account */, UserHandle.USER_ALL, null /* authority */,
                         new Bundle(), 0 /* delay */,
                         false /* onlyThoseWithUnknownSyncableState */);
             }
         }
     };
 
+    private BroadcastReceiver mAccountsUpdatedReceiver = new BroadcastReceiver() {
+        public void onReceive(Context context, Intent intent) {
+            updateRunningAccounts();
+
+            // Kick off sync for everyone, since this was a radical account change
+            scheduleSync(null, UserHandle.USER_ALL, null, null, 0 /* no delay */, false);
+        }
+    };
+
     private final PowerManager mPowerManager;
 
     // Use this as a random offset to seed all periodic syncs
     private int mSyncRandomOffsetMillis;
 
+    private final UserManager mUserManager;
+
     private static final long SYNC_ALARM_TIMEOUT_MIN = 30 * 1000; // 30 seconds
     private static final long SYNC_ALARM_TIMEOUT_MAX = 2 * 60 * 60 * 1000; // two hours
 
     private List<UserInfo> getAllUsers() {
-        try {
-            return AppGlobals.getPackageManager().getUsers();
-        } catch (RemoteException re) {
-            // Local to system process, shouldn't happen
-        }
-        return null;
+        return mUserManager.getUsers();
     }
 
     private boolean containsAccountAndUser(AccountAndUser[] accounts, Account account, int userId) {
@@ -230,33 +242,18 @@
         return found;
     }
 
-    public void onAccountsUpdated(Account[] accounts) {
-        // remember if this was the first time this was called after an update
-        final boolean justBootedUp = mAccounts == INITIAL_ACCOUNTS_ARRAY;
+    public void updateRunningAccounts() {
+        mRunningAccounts = AccountManagerService.getSingleton().getRunningAccounts();
 
-        List<UserInfo> users = getAllUsers();
-        if (users == null)  return;
-
-        int count = 0;
-
-        // Get accounts from AccountManager for all the users on the system
-        // TODO: Limit this to active users, when such a concept exists.
-        AccountAndUser[] allAccounts = AccountManagerService.getSingleton().getAllAccounts();
-        for (UserInfo user : users) {
-            if (mBootCompleted) {
-                Account[] accountsForUser =
-                        AccountManagerService.getSingleton().getAccounts(user.id);
-                mSyncStorageEngine.doDatabaseCleanup(accountsForUser, user.id);
-            }
+        if (mBootCompleted) {
+            doDatabaseCleanup();
         }
 
-        mAccounts = allAccounts;
-
         for (ActiveSyncContext currentSyncContext : mActiveSyncContexts) {
-            if (!containsAccountAndUser(allAccounts,
+            if (!containsAccountAndUser(mRunningAccounts,
                     currentSyncContext.mSyncOperation.account,
                     currentSyncContext.mSyncOperation.userId)) {
-                Log.d(TAG, "canceling sync since the account has been removed");
+                Log.d(TAG, "canceling sync since the account is no longer running");
                 sendSyncFinishedOrCanceledMessage(currentSyncContext,
                         null /* no result since this is a cancel */);
             }
@@ -265,25 +262,14 @@
         // we must do this since we don't bother scheduling alarms when
         // the accounts are not set yet
         sendCheckAlarmsMessage();
+    }
 
-        if (allAccounts.length > 0) {
-            // If this is the first time this was called after a bootup then
-            // the accounts haven't really changed, instead they were just loaded
-            // from the AccountManager. Otherwise at least one of the accounts
-            // has a change.
-            //
-            // If there was a real account change then force a sync of all accounts.
-            // This is a bit of overkill, but at least it will end up retrying syncs
-            // that failed due to an authentication failure and thus will recover if the
-            // account change was a password update.
-            //
-            // If this was the bootup case then don't sync everything, instead only
-            // sync those that have an unknown syncable state, which will give them
-            // a chance to set their syncable state.
-
-            boolean onlyThoseWithUnkownSyncableState = justBootedUp;
-            scheduleSync(null, UserId.USER_ALL, null, null, 0 /* no delay */,
-                    onlyThoseWithUnkownSyncableState);
+    private void doDatabaseCleanup() {
+        for (UserInfo user : mUserManager.getUsers(true)) {
+            // Skip any partially created/removed users
+            if (user.partial) continue;
+            Account[] accountsForUser = AccountManagerService.getSingleton().getAccounts(user.id);
+            mSyncStorageEngine.doDatabaseCleanup(accountsForUser, user.id);
         }
     }
 
@@ -323,7 +309,17 @@
     private BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            onUserRemoved(intent);
+            String action = intent.getAction();
+            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+            if (userId == UserHandle.USER_NULL) return;
+
+            if (Intent.ACTION_USER_REMOVED.equals(action)) {
+                onUserRemoved(userId);
+            } else if (Intent.ACTION_USER_STARTING.equals(action)) {
+                onUserStarting(userId);
+            } else if (Intent.ACTION_USER_STOPPING.equals(action)) {
+                onUserStopping(userId);
+            }
         }
     };
 
@@ -342,10 +338,15 @@
         }
     }
 
+    /**
+     * Should only be created after {@link ContentService#systemReady()} so that
+     * {@link PackageManager} is ready to query.
+     */
     public SyncManager(Context context, boolean factoryTest) {
         // Initialize the SyncStorageEngine first, before registering observers
         // and creating threads and so on; it may fail if the disk is full.
         mContext = context;
+
         SyncStorageEngine.init(context);
         mSyncStorageEngine = SyncStorageEngine.getSingleton();
         mSyncStorageEngine.setOnSyncRequestListener(new OnSyncRequestListener() {
@@ -364,9 +365,10 @@
         mSyncHandler = new SyncHandler(syncThread.getLooper());
 
         mSyncAdapters.setListener(new RegisteredServicesCacheListener<SyncAdapterType>() {
-            public void onServiceChanged(SyncAdapterType type, boolean removed) {
+            @Override
+            public void onServiceChanged(SyncAdapterType type, int userId, boolean removed) {
                 if (!removed) {
-                    scheduleSync(null, UserId.USER_ALL, type.authority, null, 0 /* no delay */,
+                    scheduleSync(null, UserHandle.USER_ALL, type.authority, null, 0 /* no delay */,
                             false /* onlyThoseWithUnkownSyncableState */);
                 }
             }
@@ -396,7 +398,10 @@
 
         intentFilter = new IntentFilter();
         intentFilter.addAction(Intent.ACTION_USER_REMOVED);
-        mContext.registerReceiver(mUserIntentReceiver, intentFilter);
+        intentFilter.addAction(Intent.ACTION_USER_STARTING);
+        intentFilter.addAction(Intent.ACTION_USER_STOPPING);
+        mContext.registerReceiverAsUser(
+                mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
 
         if (!factoryTest) {
             mNotificationMgr = (NotificationManager)
@@ -407,6 +412,7 @@
             mNotificationMgr = null;
         }
         mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
 
         // This WakeLock is used to ensure that we stay awake between the time that we receive
         // a sync alarm notification and when we finish processing it. We need to do this
@@ -434,10 +440,11 @@
         });
 
         if (!factoryTest) {
-            AccountManager.get(mContext).addOnAccountsUpdatedListener(SyncManager.this,
-                mSyncHandler, false /* updateImmediately */);
-            // do this synchronously to ensure we have the accounts before this call returns
-            onAccountsUpdated(null);
+            // Register for account list updates for all users
+            mContext.registerReceiverAsUser(mAccountsUpdatedReceiver,
+                    UserHandle.ALL,
+                    new IntentFilter(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION),
+                    null, null);
         }
 
         // Pick a random second in a day to seed all periodic syncs
@@ -512,12 +519,12 @@
         }
 
         AccountAndUser[] accounts;
-        if (requestedAccount != null && userId != UserId.USER_ALL) {
+        if (requestedAccount != null && userId != UserHandle.USER_ALL) {
             accounts = new AccountAndUser[] { new AccountAndUser(requestedAccount, userId) };
         } else {
             // if the accounts aren't configured yet then we can't support an account-less
             // sync request
-            accounts = mAccounts;
+            accounts = mRunningAccounts;
             if (accounts.length == 0) {
                 if (isLoggable) {
                     Log.v(TAG, "scheduleSync: no accounts configured, dropping");
@@ -548,32 +555,33 @@
             source = SyncStorageEngine.SOURCE_SERVER;
         }
 
-        // Compile a list of authorities that have sync adapters.
-        // For each authority sync each account that matches a sync adapter.
-        final HashSet<String> syncableAuthorities = new HashSet<String>();
-        for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter :
-                mSyncAdapters.getAllServices()) {
-            syncableAuthorities.add(syncAdapter.type.authority);
-        }
+        for (AccountAndUser account : accounts) {
+            // Compile a list of authorities that have sync adapters.
+            // For each authority sync each account that matches a sync adapter.
+            final HashSet<String> syncableAuthorities = new HashSet<String>();
+            for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter :
+                    mSyncAdapters.getAllServices(account.userId)) {
+                syncableAuthorities.add(syncAdapter.type.authority);
+            }
 
-        // if the url was specified then replace the list of authorities with just this authority
-        // or clear it if this authority isn't syncable
-        if (requestedAuthority != null) {
-            final boolean hasSyncAdapter = syncableAuthorities.contains(requestedAuthority);
-            syncableAuthorities.clear();
-            if (hasSyncAdapter) syncableAuthorities.add(requestedAuthority);
-        }
+            // if the url was specified then replace the list of authorities
+            // with just this authority or clear it if this authority isn't
+            // syncable
+            if (requestedAuthority != null) {
+                final boolean hasSyncAdapter = syncableAuthorities.contains(requestedAuthority);
+                syncableAuthorities.clear();
+                if (hasSyncAdapter) syncableAuthorities.add(requestedAuthority);
+            }
 
-        for (String authority : syncableAuthorities) {
-            for (AccountAndUser account : accounts) {
+            for (String authority : syncableAuthorities) {
                 int isSyncable = mSyncStorageEngine.getIsSyncable(account.account, account.userId,
                         authority);
                 if (isSyncable == 0) {
                     continue;
                 }
-                final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
-                        mSyncAdapters.getServiceInfo(
-                                SyncAdapterType.newKey(authority, account.account.type));
+                final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
+                syncAdapterInfo = mSyncAdapters.getServiceInfo(
+                        SyncAdapterType.newKey(authority, account.account.type), account.userId);
                 if (syncAdapterInfo == null) {
                     continue;
                 }
@@ -650,10 +658,9 @@
                 false /* onlyThoseWithUnkownSyncableState */);
     }
 
-    public SyncAdapterType[] getSyncAdapterTypes() {
-        final Collection<RegisteredServicesCache.ServiceInfo<SyncAdapterType>>
-                serviceInfos =
-                mSyncAdapters.getAllServices();
+    public SyncAdapterType[] getSyncAdapterTypes(int userId) {
+        final Collection<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> serviceInfos;
+        serviceInfos = mSyncAdapters.getAllServices(userId);
         SyncAdapterType[] types = new SyncAdapterType[serviceInfos.size()];
         int i = 0;
         for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> serviceInfo : serviceInfos) {
@@ -746,8 +753,8 @@
         }
 
         // Cap the delay
-        long maxSyncRetryTimeInSeconds = Settings.Secure.getLong(mContext.getContentResolver(),
-                Settings.Secure.SYNC_MAX_RETRY_DELAY_IN_SECONDS,
+        long maxSyncRetryTimeInSeconds = Settings.Global.getLong(mContext.getContentResolver(),
+                Settings.Global.SYNC_MAX_RETRY_DELAY_IN_SECONDS,
                 DEFAULT_MAX_SYNC_RETRY_TIME_IN_SECONDS);
         if (newDelayInMs > maxSyncRetryTimeInSeconds * 1000) {
             newDelayInMs = maxSyncRetryTimeInSeconds * 1000;
@@ -889,13 +896,42 @@
         }
     }
 
-    private void onUserRemoved(Intent intent) {
-        int userId = intent.getIntExtra(Intent.EXTRA_USERID, -1);
-        if (userId == -1) return;
+    private void onUserStarting(int userId) {
+        // Make sure that accounts we're about to use are valid
+        AccountManagerService.getSingleton().validateAccounts(userId);
+
+        mSyncAdapters.invalidateCache(userId);
+
+        updateRunningAccounts();
+
+        synchronized (mSyncQueue) {
+            mSyncQueue.addPendingOperations(userId);
+        }
+
+        // Schedule sync for any accounts under started user
+        final Account[] accounts = AccountManagerService.getSingleton().getAccounts(userId);
+        for (Account account : accounts) {
+            scheduleSync(account, userId, null, null, 0 /* no delay */,
+                    true /* onlyThoseWithUnknownSyncableState */);
+        }
+
+        sendCheckAlarmsMessage();
+    }
+
+    private void onUserStopping(int userId) {
+        updateRunningAccounts();
+
+        cancelActiveSync(
+                null /* any account */,
+                userId,
+                null /* any authority */);
+    }
+
+    private void onUserRemoved(int userId) {
+        updateRunningAccounts();
 
         // Clean up the storage engine database
         mSyncStorageEngine.doDatabaseCleanup(new Account[0], userId);
-        onAccountsUpdated(null);
         synchronized (mSyncQueue) {
             mSyncQueue.removeUser(userId);
         }
@@ -975,7 +1011,7 @@
             mSyncHandler.sendMessage(msg);
         }
 
-        boolean bindToSyncAdapter(RegisteredServicesCache.ServiceInfo info) {
+        boolean bindToSyncAdapter(RegisteredServicesCache.ServiceInfo info, int userId) {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 Log.d(TAG, "bindToSyncAdapter: " + info.componentName + ", connection " + this);
             }
@@ -984,8 +1020,9 @@
             intent.setComponent(info.componentName);
             intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
                     com.android.internal.R.string.sync_binding_label);
-            intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
-                    mContext, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0));
+            intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
+                    mContext, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0,
+                    null, new UserHandle(userId)));
             mBound = true;
             final boolean bindResult = mContext.bindService(intent, this,
                     Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
@@ -1027,14 +1064,10 @@
     }
 
     protected void dump(FileDescriptor fd, PrintWriter pw) {
-        dumpSyncState(pw);
-        dumpSyncHistory(pw);
-
-        pw.println();
-        pw.println("SyncAdapters:");
-        for (RegisteredServicesCache.ServiceInfo info : mSyncAdapters.getAllServices()) {
-            pw.println("  " + info);
-        }
+        final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
+        dumpSyncState(ipw);
+        dumpSyncHistory(ipw);
+        dumpSyncAdapters(ipw);
     }
 
     static String formatTime(long time) {
@@ -1050,13 +1083,13 @@
         if (users != null) {
             for (UserInfo user : users) {
                 pw.print("u" + user.id + "="
-                        + mSyncStorageEngine.getMasterSyncAutomatically(user.id));
+                        + mSyncStorageEngine.getMasterSyncAutomatically(user.id) + " ");
             }
             pw.println();
         }
         pw.print("memory low: "); pw.println(mStorageIsLow);
 
-        final AccountAndUser[] accounts = mAccounts;
+        final AccountAndUser[] accounts = AccountManagerService.getSingleton().getAllAccounts();
 
         pw.print("accounts: ");
         if (accounts != INITIAL_ACCOUNTS_ARRAY) {
@@ -1118,7 +1151,7 @@
                     pw.print(" "); pw.print(account.account.type);
                     pw.println(":");
             for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterType :
-                    mSyncAdapters.getAllServices()) {
+                    mSyncAdapters.getAllServices(account.userId)) {
                 if (!syncAdapterType.type.accountType.equals(account.account.type)) {
                     continue;
                 }
@@ -1261,7 +1294,8 @@
                 final String accountKey;
                 if (authority != null) {
                     authorityName = authority.authority;
-                    accountKey = authority.account.name + "/" + authority.account.type;
+                    accountKey = authority.account.name + "/" + authority.account.type
+                            + " u" + authority.userId;
                 } else {
                     authorityName = "Unknown";
                     accountKey = "Unknown";
@@ -1388,7 +1422,8 @@
                 final String accountKey;
                 if (authority != null) {
                     authorityName = authority.authority;
-                    accountKey = authority.account.name + "/" + authority.account.type;
+                    accountKey = authority.account.name + "/" + authority.account.type
+                            + " u" + authority.userId;
                 } else {
                     authorityName = "Unknown";
                     accountKey = "Unknown";
@@ -1493,6 +1528,23 @@
         }
     }
 
+    private void dumpSyncAdapters(IndentingPrintWriter pw) {
+        pw.println();
+        final List<UserInfo> users = getAllUsers();
+        if (users != null) {
+            for (UserInfo user : users) {
+                pw.println("Sync adapters for " + user + ":");
+                pw.increaseIndent();
+                for (RegisteredServicesCache.ServiceInfo<?> info :
+                        mSyncAdapters.getAllServices(user.id)) {
+                    pw.println(info);
+                }
+                pw.decreaseIndent();
+                pw.println();
+            }
+        }
+    }
+
     private static class AuthoritySyncStats {
         String name;
         long elapsedTime;
@@ -1576,18 +1628,12 @@
                 Maps.newHashMap();
 
         private volatile CountDownLatch mReadyToRunLatch = new CountDownLatch(1);
+
         public void onBootCompleted() {
             mBootCompleted = true;
-            // TODO: Handle bootcompleted event for specific user. Now let's just iterate through
-            // all the users.
-            List<UserInfo> users = getAllUsers();
-            if (users != null) {
-                for (UserInfo user : users) {
-                    mSyncStorageEngine.doDatabaseCleanup(
-                            AccountManagerService.getSingleton().getAccounts(user.id),
-                            user.id);
-                }
-            }
+
+            doDatabaseCleanup();
+
             if (mReadyToRunLatch != null) {
                 mReadyToRunLatch.countDown();
             }
@@ -1777,7 +1823,7 @@
                 return earliestFuturePollTime;
             }
 
-            AccountAndUser[] accounts = mAccounts;
+            AccountAndUser[] accounts = mRunningAccounts;
 
             final long nowAbsolute = System.currentTimeMillis();
             final long shiftedNowAbsolute = (0 < nowAbsolute - mSyncRandomOffsetMillis)
@@ -1832,9 +1878,10 @@
                         // Sync now
                         final Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(
                                 info.account, info.userId, info.authority);
-                        final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
-                                mSyncAdapters.getServiceInfo(
-                                        SyncAdapterType.newKey(info.authority, info.account.type));
+                        final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
+                        syncAdapterInfo = mSyncAdapters.getServiceInfo(
+                                SyncAdapterType.newKey(info.authority, info.account.type),
+                                info.userId);
                         if (syncAdapterInfo == null) {
                             continue;
                         }
@@ -1890,7 +1937,7 @@
 
             // If the accounts aren't known yet then we aren't ready to run. We will be kicked
             // when the account lookup request does complete.
-            AccountAndUser[] accounts = mAccounts;
+            AccountAndUser[] accounts = mRunningAccounts;
             if (accounts == INITIAL_ACCOUNTS_ARRAY) {
                 if (isLoggable) {
                     Log.v(TAG, "maybeStartNextSync: accounts not known, skipping");
@@ -1914,10 +1961,14 @@
             synchronized (mSyncQueue) {
                 if (isLoggable) {
                     Log.v(TAG, "build the operation array, syncQueue size is "
-                        + mSyncQueue.mOperationsMap.size());
+                        + mSyncQueue.getOperations().size());
                 }
-                Iterator<SyncOperation> operationIterator =
-                        mSyncQueue.mOperationsMap.values().iterator();
+                final Iterator<SyncOperation> operationIterator = mSyncQueue.getOperations()
+                        .iterator();
+
+                final ActivityManager activityManager
+                        = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+                final Set<Integer> removedUsers = Sets.newHashSet();
                 while (operationIterator.hasNext()) {
                     final SyncOperation op = operationIterator.next();
 
@@ -1937,6 +1988,15 @@
                         continue;
                     }
 
+                    // if the user in not running, drop the request
+                    if (!activityManager.isUserRunning(op.userId)) {
+                        final UserInfo userInfo = mUserManager.getUserInfo(op.userId);
+                        if (userInfo == null) {
+                            removedUsers.add(op.userId);
+                        }
+                        continue;
+                    }
+
                     // if the next run time is in the future, meaning there are no syncs ready
                     // to run, return the time
                     if (op.effectiveRunTime > now) {
@@ -1948,7 +2008,7 @@
 
                     final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
                     syncAdapterInfo = mSyncAdapters.getServiceInfo(
-                            SyncAdapterType.newKey(op.authority, op.account.type));
+                            SyncAdapterType.newKey(op.authority, op.account.type), op.userId);
 
                     // only proceed if network is connected for requesting UID
                     final boolean uidNetworkConnected;
@@ -1977,6 +2037,12 @@
 
                     operations.add(op);
                 }
+                for (Integer user : removedUsers) {
+                    // if it's still removed
+                    if (mUserManager.getUserInfo(user) == null) {
+                        onUserRemoved(user);
+                    }
+                }
             }
 
             // find the next operation to dispatch, if one is ready
@@ -2091,7 +2157,7 @@
                     runSyncFinishedOrCanceledLocked(null, toReschedule);
                     scheduleSyncOperation(toReschedule.mSyncOperation);
                 }
-                synchronized (mSyncQueue){
+                synchronized (mSyncQueue) {
                     mSyncQueue.remove(candidate);
                 }
                 dispatchSyncOperation(candidate);
@@ -2111,8 +2177,8 @@
 
             // connect to the sync adapter
             SyncAdapterType syncAdapterType = SyncAdapterType.newKey(op.authority, op.account.type);
-            RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
-                    mSyncAdapters.getServiceInfo(syncAdapterType);
+            final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
+            syncAdapterInfo = mSyncAdapters.getServiceInfo(syncAdapterType, op.userId);
             if (syncAdapterInfo == null) {
                 Log.d(TAG, "can't find a sync adapter for " + syncAdapterType
                         + ", removing settings for it");
@@ -2127,7 +2193,7 @@
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 Log.v(TAG, "dispatchSyncOperation: starting " + activeSyncContext);
             }
-            if (!activeSyncContext.bindToSyncAdapter(syncAdapterInfo)) {
+            if (!activeSyncContext.bindToSyncAdapter(syncAdapterInfo, op.userId)) {
                 Log.e(TAG, "Bind attempt failed to " + syncAdapterInfo);
                 closeActiveSyncContext(activeSyncContext);
                 return false;
@@ -2162,20 +2228,20 @@
                     new ArrayList<ActiveSyncContext>(mActiveSyncContexts);
             for (ActiveSyncContext activeSyncContext : activeSyncs) {
                 if (activeSyncContext != null) {
-                    // if an authority was specified then only cancel the sync if it matches
+                    // if an account was specified then only cancel the sync if it matches
                     if (account != null) {
                         if (!account.equals(activeSyncContext.mSyncOperation.account)) {
                             continue;
                         }
                     }
-                    // if an account was specified then only cancel the sync if it matches
+                    // if an authority was specified then only cancel the sync if it matches
                     if (authority != null) {
                         if (!authority.equals(activeSyncContext.mSyncOperation.authority)) {
                             continue;
                         }
                     }
                     // check if the userid matches
-                    if (userId != UserId.USER_ALL
+                    if (userId != UserHandle.USER_ALL
                             && userId != activeSyncContext.mSyncOperation.userId) {
                         continue;
                     }
@@ -2250,10 +2316,12 @@
 
             if (syncResult != null && syncResult.tooManyDeletions) {
                 installHandleTooManyDeletesNotification(syncOperation.account,
-                        syncOperation.authority, syncResult.stats.numDeletes);
+                        syncOperation.authority, syncResult.stats.numDeletes,
+                        syncOperation.userId);
             } else {
-                mNotificationMgr.cancel(
-                        syncOperation.account.hashCode() ^ syncOperation.authority.hashCode());
+                mNotificationMgr.cancelAsUser(null,
+                        syncOperation.account.hashCode() ^ syncOperation.authority.hashCode(),
+                        new UserHandle(syncOperation.userId));
             }
 
             if (syncResult != null && syncResult.fullSyncRequested) {
@@ -2462,11 +2530,11 @@
             syncStateIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
             syncStateIntent.putExtra("active", mNeedSyncActiveNotification);
             syncStateIntent.putExtra("failing", false);
-            mContext.sendBroadcast(syncStateIntent);
+            mContext.sendBroadcastAsUser(syncStateIntent, UserHandle.OWNER);
         }
 
         private void installHandleTooManyDeletesNotification(Account account, String authority,
-                long numDeletes) {
+                long numDeletes, int userId) {
             if (mNotificationMgr == null) return;
 
             final ProviderInfo providerInfo = mContext.getPackageManager().resolveContentProvider(
@@ -2488,7 +2556,8 @@
             }
 
             final PendingIntent pendingIntent = PendingIntent
-                    .getActivity(mContext, 0, clickIntent, PendingIntent.FLAG_CANCEL_CURRENT);
+                    .getActivityAsUser(mContext, 0, clickIntent,
+                            PendingIntent.FLAG_CANCEL_CURRENT, null, new UserHandle(userId));
 
             CharSequence tooManyDeletesDescFormat = mContext.getResources().getText(
                     R.string.contentServiceTooManyDeletesNotificationDesc);
@@ -2502,7 +2571,8 @@
                     String.format(tooManyDeletesDescFormat.toString(), authorityName),
                     pendingIntent);
             notification.flags |= Notification.FLAG_ONGOING_EVENT;
-            mNotificationMgr.notify(account.hashCode() ^ authority.hashCode(), notification);
+            mNotificationMgr.notifyAsUser(null, account.hashCode() ^ authority.hashCode(),
+                    notification, new UserHandle(userId));
         }
 
         /**
diff --git a/core/java/android/content/SyncOperation.java b/core/java/android/content/SyncOperation.java
index 9fcc22d..6611fcd 100644
--- a/core/java/android/content/SyncOperation.java
+++ b/core/java/android/content/SyncOperation.java
@@ -95,13 +95,18 @@
     }
 
     public String dump(boolean useOneLine) {
-        StringBuilder sb = new StringBuilder();
-        sb.append(account.name);
-        sb.append(" (" + account.type + ")");
-        sb.append(", " + authority);
-        sb.append(", ");
-        sb.append(SyncStorageEngine.SOURCES[syncSource]);
-        sb.append(", earliestRunTime " + earliestRunTime);
+        StringBuilder sb = new StringBuilder()
+                .append(account.name)
+                .append(" u")
+                .append(userId).append(" (")
+                .append(account.type)
+                .append(")")
+                .append(", ")
+                .append(authority)
+                .append(", ")
+                .append(SyncStorageEngine.SOURCES[syncSource])
+                .append(", earliestRunTime ")
+                .append(earliestRunTime);
         if (expedited) {
             sb.append(", EXPEDITED");
         }
diff --git a/core/java/android/content/SyncQueue.java b/core/java/android/content/SyncQueue.java
index c18c86bf..c9a325e 100644
--- a/core/java/android/content/SyncQueue.java
+++ b/core/java/android/content/SyncQueue.java
@@ -16,51 +16,60 @@
 
 package android.content;
 
+import android.accounts.Account;
+import android.content.pm.RegisteredServicesCache.ServiceInfo;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.text.format.DateUtils;
+import android.util.Log;
+import android.util.Pair;
+
 import com.google.android.collect.Maps;
 
-import android.content.pm.RegisteredServicesCache;
-import android.os.SystemClock;
-import android.text.format.DateUtils;
-import android.util.Pair;
-import android.util.Log;
-import android.accounts.Account;
-
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 
 /**
+ * Queue of pending sync operations. Not inherently thread safe, external
+ * callers are responsible for locking.
  *
  * @hide
  */
 public class SyncQueue {
     private static final String TAG = "SyncManager";
-    private SyncStorageEngine mSyncStorageEngine;
+
+    private final SyncStorageEngine mSyncStorageEngine;
+    private final SyncAdaptersCache mSyncAdapters;
 
     // A Map of SyncOperations operationKey -> SyncOperation that is designed for
     // quick lookup of an enqueued SyncOperation.
-    public final HashMap<String, SyncOperation> mOperationsMap = Maps.newHashMap();
+    private final HashMap<String, SyncOperation> mOperationsMap = Maps.newHashMap();
 
     public SyncQueue(SyncStorageEngine syncStorageEngine, final SyncAdaptersCache syncAdapters) {
         mSyncStorageEngine = syncStorageEngine;
-        ArrayList<SyncStorageEngine.PendingOperation> ops
-                = mSyncStorageEngine.getPendingOperations();
-        final int N = ops.size();
-        for (int i=0; i<N; i++) {
-            SyncStorageEngine.PendingOperation op = ops.get(i);
-            final Pair<Long, Long> backoff =
-                    syncStorageEngine.getBackoff(op.account, op.userId, op.authority);
-            final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
-                    syncAdapters.getServiceInfo(
-                            SyncAdapterType.newKey(op.authority, op.account.type));
+        mSyncAdapters = syncAdapters;
+    }
+
+    public void addPendingOperations(int userId) {
+        for (SyncStorageEngine.PendingOperation op : mSyncStorageEngine.getPendingOperations()) {
+            if (op.userId != userId) continue;
+
+            final Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(
+                    op.account, op.userId, op.authority);
+            final ServiceInfo<SyncAdapterType> syncAdapterInfo = mSyncAdapters.getServiceInfo(
+                    SyncAdapterType.newKey(op.authority, op.account.type), op.userId);
             if (syncAdapterInfo == null) {
+                Log.w(TAG, "Missing sync adapter info for authority " + op.authority + ", userId "
+                        + op.userId);
                 continue;
             }
             SyncOperation syncOperation = new SyncOperation(
                     op.account, op.userId, op.syncSource, op.authority, op.extras, 0 /* delay */,
                     backoff != null ? backoff.first : 0,
-                    syncStorageEngine.getDelayUntilTime(op.account, op.userId, op.authority),
+                    mSyncStorageEngine.getDelayUntilTime(op.account, op.userId, op.authority),
                     syncAdapterInfo.type.allowParallelSyncs());
             syncOperation.expedited = op.expedited;
             syncOperation.pendingOperation = op;
@@ -190,6 +199,10 @@
         }
     }
 
+    public Collection<SyncOperation> getOperations() {
+        return mOperationsMap.values();
+    }
+
     public void dump(StringBuilder sb) {
         final long now = SystemClock.elapsedRealtime();
         sb.append("SyncQueue: ").append(mOperationsMap.size()).append(" operation(s)\n");
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index 7a9fc65..10e7bff 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -16,7 +16,6 @@
 
 package android.content;
 
-import com.android.internal.os.AtomicFile;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastXmlSerializer;
 
@@ -38,7 +37,7 @@
 import android.os.Parcel;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
-import android.os.SystemClock;
+import android.util.AtomicFile;
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.Xml;
@@ -610,23 +609,25 @@
     public void clearAllBackoffs(SyncQueue syncQueue) {
         boolean changed = false;
         synchronized (mAuthorities) {
-            for (AccountInfo accountInfo : mAccounts.values()) {
-                for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
-                    if (authorityInfo.backoffTime != NOT_IN_BACKOFF_MODE
-                            || authorityInfo.backoffDelay != NOT_IN_BACKOFF_MODE) {
-                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                            Log.v(TAG, "clearAllBackoffs:"
-                                    + " authority:" + authorityInfo.authority
-                                    + " account:" + accountInfo.accountAndUser.account.name
-                                    + " user:" + accountInfo.accountAndUser.userId
-                                    + " backoffTime was: " + authorityInfo.backoffTime
-                                    + " backoffDelay was: " + authorityInfo.backoffDelay);
+            synchronized (syncQueue) {
+                for (AccountInfo accountInfo : mAccounts.values()) {
+                    for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
+                        if (authorityInfo.backoffTime != NOT_IN_BACKOFF_MODE
+                                || authorityInfo.backoffDelay != NOT_IN_BACKOFF_MODE) {
+                            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                                Log.v(TAG, "clearAllBackoffs:"
+                                        + " authority:" + authorityInfo.authority
+                                        + " account:" + accountInfo.accountAndUser.account.name
+                                        + " user:" + accountInfo.accountAndUser.userId
+                                        + " backoffTime was: " + authorityInfo.backoffTime
+                                        + " backoffDelay was: " + authorityInfo.backoffDelay);
+                            }
+                            authorityInfo.backoffTime = NOT_IN_BACKOFF_MODE;
+                            authorityInfo.backoffDelay = NOT_IN_BACKOFF_MODE;
+                            syncQueue.onBackoffChanged(accountInfo.accountAndUser.account,
+                                    accountInfo.accountAndUser.userId, authorityInfo.authority, 0);
+                            changed = true;
                         }
-                        authorityInfo.backoffTime = NOT_IN_BACKOFF_MODE;
-                        authorityInfo.backoffDelay = NOT_IN_BACKOFF_MODE;
-                        syncQueue.onBackoffChanged(accountInfo.accountAndUser.account,
-                                accountInfo.accountAndUser.userId, authorityInfo.authority, 0);
-                        changed = true;
                     }
                 }
             }
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 6b16e74..e2ca1dd 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -155,6 +155,12 @@
      */
     public static final int FLAG_HARDWARE_ACCELERATED = 0x0200;
     /**
+     * Value for {@link #flags}: true when the application can be displayed over the lockscreen
+     * and consequently over all users' windows.
+     * @hide
+     */
+    public static final int FLAG_SHOW_ON_LOCK_SCREEN = 0x0400;
+    /**
      * @hide
      * Bit in {@link #flags} corresponding to an immersive activity
      * that wishes not to be interrupted by notifications.
@@ -170,7 +176,21 @@
      * "toast" window).
      * {@see android.app.Notification#FLAG_HIGH_PRIORITY}
      */
-    public static final int FLAG_IMMERSIVE = 0x0400;
+    public static final int FLAG_IMMERSIVE = 0x0800;
+    /**
+     * @hide Bit in {@link #flags}: If set, this component will only be seen
+     * by the primary user.  Only works with broadcast receivers.  Set from the
+     * {@link android.R.attr#primaryUserOnly} attribute.
+     */
+    public static final int FLAG_PRIMARY_USER_ONLY = 0x20000000;
+    /**
+     * Bit in {@link #flags}: If set, a single instance of the receiver will
+     * run for all users on the device.  Set from the
+     * {@link android.R.attr#singleUser} attribute.  Note that this flag is
+     * only relevant for ActivityInfo structures that are describing receiver
+     * components; it is not applied to activities.
+     */
+    public static final int FLAG_SINGLE_USER = 0x40000000;
     /**
      * Options that have been set in the activity declaration in the
      * manifest.
@@ -181,7 +201,7 @@
      * {@link #FLAG_STATE_NOT_NEEDED}, {@link #FLAG_EXCLUDE_FROM_RECENTS},
      * {@link #FLAG_ALLOW_TASK_REPARENTING}, {@link #FLAG_NO_HISTORY},
      * {@link #FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS},
-     * {@link #FLAG_HARDWARE_ACCELERATED}
+     * {@link #FLAG_HARDWARE_ACCELERATED}, {@link #FLAG_SINGLE_USER}.
      */
     public int flags;
 
@@ -358,6 +378,18 @@
     public static final int CONFIG_SMALLEST_SCREEN_SIZE = 0x0800;
     /**
      * Bit in {@link #configChanges} that indicates that the activity
+     * can itself handle density changes. Set from the
+     * {@link android.R.attr#configChanges} attribute.
+     */
+    public static final int CONFIG_DENSITY = 0x1000;
+    /**
+     * Bit in {@link #configChanges} that indicates that the activity
+     * can itself handle the change to layout direction. Set from the
+     * {@link android.R.attr#configChanges} attribute.
+     */
+    public static final int CONFIG_LAYOUT_DIRECTION = 0x2000;
+    /**
+     * Bit in {@link #configChanges} that indicates that the activity
      * can itself handle changes to the font scaling factor.  Set from the
      * {@link android.R.attr#configChanges} attribute.  This is
      * not a core resource configutation, but a higher-level value, so its
@@ -383,6 +415,8 @@
         0x1000, // UI MODE
         0x0200, // SCREEN SIZE
         0x2000, // SMALLEST SCREEN SIZE
+        0x0100, // DENSITY
+        0x4000, // LAYOUT DIRECTION
     };
     /** @hide
      * Convert Java change bits to native.
@@ -419,8 +453,9 @@
      * {@link #CONFIG_MCC}, {@link #CONFIG_MNC},
      * {@link #CONFIG_LOCALE}, {@link #CONFIG_TOUCHSCREEN},
      * {@link #CONFIG_KEYBOARD}, {@link #CONFIG_NAVIGATION},
-     * {@link #CONFIG_ORIENTATION}, and {@link #CONFIG_SCREEN_LAYOUT}.  Set from the
-     * {@link android.R.attr#configChanges} attribute.
+     * {@link #CONFIG_ORIENTATION}, {@link #CONFIG_SCREEN_LAYOUT} and
+     * {@link #CONFIG_LAYOUT_DIRECTION}.  Set from the {@link android.R.attr#configChanges}
+     * attribute.
      */
     public int configChanges;
     
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index e1434b3..32cc7fd 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -298,11 +298,23 @@
      * activity's manifest.
      *
      * Default value is false (no support for RTL).
-     * @hide
      */
     public static final int FLAG_SUPPORTS_RTL = 1<<22;
 
     /**
+     * Value for {@link #flags}: true if the application is currently
+     * installed for the calling user.
+     */
+    public static final int FLAG_INSTALLED = 1<<23;
+
+    /**
+     * Value for {@link #flags}: true if the application only has its
+     * data installed; the application package itself does not currently
+     * exist on the device.
+     */
+    public static final int FLAG_IS_DATA_ONLY = 1<<24;
+
+    /**
      * Value for {@link #flags}: Set to true if the application has been
      * installed using the forward lock option.
      *
@@ -335,7 +347,8 @@
      * {@link #FLAG_SUPPORTS_NORMAL_SCREENS},
      * {@link #FLAG_SUPPORTS_LARGE_SCREENS}, {@link #FLAG_SUPPORTS_XLARGE_SCREENS},
      * {@link #FLAG_RESIZEABLE_FOR_SCREENS},
-     * {@link #FLAG_SUPPORTS_SCREEN_DENSITIES}, {@link #FLAG_VM_SAFE_MODE}
+     * {@link #FLAG_SUPPORTS_SCREEN_DENSITIES}, {@link #FLAG_VM_SAFE_MODE},
+     * {@link #FLAG_INSTALLED}.
      */
     public int flags = 0;
     
@@ -541,6 +554,7 @@
         manageSpaceActivityName = orig.manageSpaceActivityName;
         descriptionRes = orig.descriptionRes;
         uiOptions = orig.uiOptions;
+        backupAgentName = orig.backupAgentName;
     }
 
 
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 90b4247..b0ae5da 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -32,6 +32,7 @@
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.ManifestDigest;
+import android.content.pm.PackageCleanItem;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ProviderInfo;
 import android.content.pm.PermissionGroupInfo;
@@ -39,8 +40,10 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
+import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
 import android.content.IntentSender;
 
 /**
@@ -124,7 +127,7 @@
      * limit that kicks in when flags are included that bloat up the data
      * returned.
      */
-    ParceledListSlice getInstalledPackages(int flags, in String lastRead);
+    ParceledListSlice getInstalledPackages(int flags, in String lastRead, in int userId);
 
     /**
      * This implements getInstalledApplications via a "last returned row"
@@ -199,7 +202,7 @@
     List<PackageInfo> getPreferredPackages(int flags);
 
     void addPreferredActivity(in IntentFilter filter, int match,
-            in ComponentName[] set, in ComponentName activity);
+            in ComponentName[] set, in ComponentName activity, int userId);
 
     void replacePreferredActivity(in IntentFilter filter, int match,
             in ComponentName[] set, in ComponentName activity);
@@ -303,10 +306,11 @@
      * Get package statistics including the code, data and cache size for
      * an already installed package
      * @param packageName The package name of the application
+     * @param userHandle Which user the size should be retrieved for
      * @param observer a callback to use to notify when the asynchronous
      * retrieval of information is complete.
      */
-    void getPackageSizeInfo(in String packageName, IPackageStatsObserver observer);
+    void getPackageSizeInfo(in String packageName, int userHandle, IPackageStatsObserver observer);
     
     /**
      * Get a list of shared libraries that are available on the
@@ -348,7 +352,7 @@
      */
     void updateExternalMediaStatus(boolean mounted, boolean reportStatus);
 
-    String nextPackageToClean(String lastPackage);
+    PackageCleanItem nextPackageToClean(in PackageCleanItem lastPackage);
 
     void movePackage(String packageName, IPackageMoveObserver observer, int flags);
     
@@ -357,23 +361,24 @@
     boolean setInstallLocation(int loc);
     int getInstallLocation();
 
-    UserInfo createUser(in String name, int flags);
-    boolean removeUser(int userId);
-    void updateUserName(int userId, String name);
-
     void installPackageWithVerification(in Uri packageURI, in IPackageInstallObserver observer,
             int flags, in String installerPackageName, in Uri verificationURI,
             in ManifestDigest manifestDigest, in ContainerEncryptionParams encryptionParams);
 
+    void installPackageWithVerificationAndEncryption(in Uri packageURI,
+            in IPackageInstallObserver observer, int flags, in String installerPackageName,
+            in VerificationParams verificationParams,
+            in ContainerEncryptionParams encryptionParams);
+
+    int installExistingPackage(String packageName);
+
     void verifyPendingInstall(int id, int verificationCode);
+    void extendVerificationTimeout(int id, int verificationCodeAtTimeout, long millisecondsToDelay);
 
     VerifierDeviceIdentity getVerifierDeviceIdentity();
 
     boolean isFirstBoot();
 
-    List<UserInfo> getUsers();
-    UserInfo getUser(int userId);
-
     void setPermissionEnforced(String permission, boolean enforced);
     boolean isPermissionEnforced(String permission);
 
diff --git a/core/java/android/content/pm/InstrumentationInfo.java b/core/java/android/content/pm/InstrumentationInfo.java
index ea47e8e..a977e41 100644
--- a/core/java/android/content/pm/InstrumentationInfo.java
+++ b/core/java/android/content/pm/InstrumentationInfo.java
@@ -18,10 +18,6 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.text.TextUtils;
-
-import java.text.Collator;
-import java.util.Comparator;
 
 /**
  * Information you can retrieve about a particular piece of test
diff --git a/core/java/android/content/pm/ManifestDigest.java b/core/java/android/content/pm/ManifestDigest.java
index f5e72e0..75505bc 100644
--- a/core/java/android/content/pm/ManifestDigest.java
+++ b/core/java/android/content/pm/ManifestDigest.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package android.content.pm;
 
 import android.os.Parcel;
diff --git a/core/java/android/content/pm/PackageCleanItem.aidl b/core/java/android/content/pm/PackageCleanItem.aidl
new file mode 100644
index 0000000..9bb203e
--- /dev/null
+++ b/core/java/android/content/pm/PackageCleanItem.aidl
@@ -0,0 +1,18 @@
+/* Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.content.pm;
+
+parcelable PackageCleanItem;
diff --git a/core/java/android/content/pm/PackageCleanItem.java b/core/java/android/content/pm/PackageCleanItem.java
new file mode 100644
index 0000000..b1896aa
--- /dev/null
+++ b/core/java/android/content/pm/PackageCleanItem.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/** @hide */
+public class PackageCleanItem {
+    public final int userId;
+    public final String packageName;
+    public final boolean andCode;
+
+    public PackageCleanItem(int userId, String packageName, boolean andCode) {
+        this.userId = userId;
+        this.packageName = packageName;
+        this.andCode = andCode;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        try {
+            if (obj != null) {
+                PackageCleanItem other = (PackageCleanItem)obj;
+                return userId == other.userId && packageName.equals(other.packageName)
+                        && andCode == other.andCode;
+            }
+        } catch (ClassCastException e) {
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = 17;
+        result = 31 * result + userId;
+        result = 31 * result + packageName.hashCode();
+        result = 31 * result + (andCode ? 1 : 0);
+        return result;
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel dest, int parcelableFlags) {
+        dest.writeInt(userId);
+        dest.writeString(packageName);
+        dest.writeInt(andCode ? 1 : 0);
+    }
+
+    public static final Parcelable.Creator<PackageCleanItem> CREATOR
+            = new Parcelable.Creator<PackageCleanItem>() {
+        public PackageCleanItem createFromParcel(Parcel source) {
+            return new PackageCleanItem(source);
+        }
+
+        public PackageCleanItem[] newArray(int size) {
+            return new PackageCleanItem[size];
+        }
+    };
+
+    private PackageCleanItem(Parcel source) {
+        userId = source.readInt();
+        packageName = source.readString();
+        andCode = source.readInt() != 0;
+    }
+}
diff --git a/core/java/android/content/pm/PackageInfoLite.java b/core/java/android/content/pm/PackageInfoLite.java
index 9625944..a1566da 100644
--- a/core/java/android/content/pm/PackageInfoLite.java
+++ b/core/java/android/content/pm/PackageInfoLite.java
@@ -32,6 +32,11 @@
     public String packageName;
 
     /**
+     * The android:versionCode of the package.
+     */
+    public int versionCode;
+
+    /**
      * Specifies the recommended install location. Can be one of
      * {@link #PackageHelper.RECOMMEND_INSTALL_INTERNAL} to install on internal storage
      * {@link #PackageHelper.RECOMMEND_INSTALL_EXTERNAL} to install on external media
@@ -58,6 +63,7 @@
 
     public void writeToParcel(Parcel dest, int parcelableFlags) {
         dest.writeString(packageName);
+        dest.writeInt(versionCode);
         dest.writeInt(recommendedInstallLocation);
         dest.writeInt(installLocation);
 
@@ -82,6 +88,7 @@
 
     private PackageInfoLite(Parcel source) {
         packageName = source.readString();
+        versionCode = source.readInt();
         recommendedInstallLocation = source.readInt();
         installLocation = source.readInt();
 
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index d73aaf6..a67326e 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -218,7 +218,7 @@
         }
         return null;
     }
-    
+
     protected void dumpFront(Printer pw, String prefix) {
         if (name != null) {
             pw.println(prefix + "name=" + name);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 7e96ae6..8ba1988 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -28,6 +28,7 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Environment;
+import android.os.UserHandle;
 import android.util.AndroidException;
 import android.util.DisplayMetrics;
 
@@ -309,6 +310,23 @@
     public static final int INSTALL_FROM_ADB = 0x00000020;
 
     /**
+     * Flag parameter for {@link #installPackage} to indicate that this install
+     * should immediately be visible to all users.
+     *
+     * @hide
+     */
+    public static final int INSTALL_ALL_USERS = 0x00000040;
+
+    /**
+     * Flag parameter for {@link #installPackage} to indicate that it is okay
+     * to install an update to an app where the newly installed app has a lower
+     * version code than the currently installed app.
+     *
+     * @hide
+     */
+    public static final int INSTALL_ALLOW_DOWNGRADE = 0x00000080;
+
+    /**
      * Flag parameter for
      * {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate
      * that you don't want to kill the app containing the component.  Be careful when you set this
@@ -528,6 +546,14 @@
     public static final int INSTALL_FAILED_UID_CHANGED = -24;
 
     /**
+     * Installation return code: this is passed to the {@link IPackageInstallObserver} by
+     * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
+     * the new package has an older version code than the currently installed package.
+     * @hide
+     */
+    public static final int INSTALL_FAILED_VERSION_DOWNGRADE = -25;
+
+    /**
      * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
      * if the parser was given a path that is not a file, or does not end with the expected
@@ -624,7 +650,15 @@
      *
      * @hide
      */
-    public static final int DONT_DELETE_DATA = 0x00000001;
+    public static final int DELETE_KEEP_DATA = 0x00000001;
+
+    /**
+     * Flag parameter for {@link #deletePackage} to indicate that you want the
+     * package deleted for all users.
+     *
+     * @hide
+     */
+    public static final int DELETE_ALL_USERS = 0x00000002;
 
     /**
      * Return code for when package deletion succeeds. This is passed to the
@@ -761,6 +795,14 @@
     public static final int VERIFICATION_REJECT = -1;
 
     /**
+     * Can be used as the {@code millisecondsToDelay} argument for
+     * {@link PackageManager#extendVerificationTimeout}. This is the
+     * maximum time {@code PackageManager} waits for the verification
+     * agent to return (in milliseconds).
+     */
+    public static final long MAXIMUM_VERIFICATION_TIMEOUT = 60*60*1000;
+
+    /**
      * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device's
      * audio pipeline is low-latency, more suitable for audio applications sensitive to delays or
      * lag in sound input or output.
@@ -793,6 +835,14 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature}: The device has at least one camera pointing in
+     * some direction.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_CAMERA_ANY = "android.hardware.camera.any";
+
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device's camera supports flash.
      */
     @SdkConstant(SdkConstantType.FEATURE)
@@ -1109,6 +1159,38 @@
             = "android.content.pm.extra.VERIFICATION_INSTALL_FLAGS";
 
     /**
+     * Extra field name for the uid of who is requesting to install
+     * the package.
+     *
+     * @hide
+     */
+    public static final String EXTRA_VERIFICATION_INSTALLER_UID
+            = "android.content.pm.extra.VERIFICATION_INSTALLER_UID";
+
+    /**
+     * Extra field name for the package name of a package pending verification.
+     *
+     * @hide
+     */
+    public static final String EXTRA_VERIFICATION_PACKAGE_NAME
+            = "android.content.pm.extra.VERIFICATION_PACKAGE_NAME";
+    /**
+     * Extra field name for the result of a verification, either
+     * {@link #VERIFICATION_ALLOW}, or {@link #VERIFICATION_REJECT}.
+     * Passed to package verifiers after a package is verified.
+     */
+    public static final String EXTRA_VERIFICATION_RESULT
+            = "android.content.pm.extra.VERIFICATION_RESULT";
+
+    /**
+     * Extra field name for the version code of a package pending verification.
+     *
+     * @hide
+     */
+    public static final String EXTRA_VERIFICATION_VERSION_CODE
+            = "android.content.pm.extra.VERIFICATION_VERSION_CODE";
+
+    /**
      * Retrieve overall information about an application package that is
      * installed on the system.
      * <p>
@@ -1419,6 +1501,45 @@
     public abstract List<PackageInfo> getInstalledPackages(int flags);
 
     /**
+     * Return a List of all packages that are installed on the device, for a specific user.
+     * Requesting a list of installed packages for another user
+     * will require the permission INTERACT_ACROSS_USERS_FULL.
+     * @param flags Additional option flags. Use any combination of
+     * {@link #GET_ACTIVITIES},
+     * {@link #GET_GIDS},
+     * {@link #GET_CONFIGURATIONS},
+     * {@link #GET_INSTRUMENTATION},
+     * {@link #GET_PERMISSIONS},
+     * {@link #GET_PROVIDERS},
+     * {@link #GET_RECEIVERS},
+     * {@link #GET_SERVICES},
+     * {@link #GET_SIGNATURES},
+     * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned.
+     * @param userId The user for whom the installed packages are to be listed
+     *
+     * @return A List of PackageInfo objects, one for each package that is
+     *         installed on the device.  In the unlikely case of there being no
+     *         installed packages, an empty list is returned.
+     *         If flag GET_UNINSTALLED_PACKAGES is set, a list of all
+     *         applications including those deleted with DONT_DELETE_DATA
+     *         (partially installed apps with data directory) will be returned.
+     *
+     * @see #GET_ACTIVITIES
+     * @see #GET_GIDS
+     * @see #GET_CONFIGURATIONS
+     * @see #GET_INSTRUMENTATION
+     * @see #GET_PERMISSIONS
+     * @see #GET_PROVIDERS
+     * @see #GET_RECEIVERS
+     * @see #GET_SERVICES
+     * @see #GET_SIGNATURES
+     * @see #GET_UNINSTALLED_PACKAGES
+     *
+     * @hide
+     */
+    public abstract List<PackageInfo> getInstalledPackages(int flags, int userId);
+
+    /**
      * Check whether a particular package has been granted a particular
      * permission.
      *
@@ -1684,6 +1805,39 @@
     public abstract ResolveInfo resolveActivity(Intent intent, int flags);
 
     /**
+     * Determine the best action to perform for a given Intent for a given user. This
+     * is how {@link Intent#resolveActivity} finds an activity if a class has not
+     * been explicitly specified.
+     *
+     * <p><em>Note:</em> if using an implicit Intent (without an explicit ComponentName
+     * specified), be sure to consider whether to set the {@link #MATCH_DEFAULT_ONLY}
+     * only flag.  You need to do so to resolve the activity in the same way
+     * that {@link android.content.Context#startActivity(Intent)} and
+     * {@link android.content.Intent#resolveActivity(PackageManager)
+     * Intent.resolveActivity(PackageManager)} do.</p>
+     *
+     * @param intent An intent containing all of the desired specification
+     *               (action, data, type, category, and/or component).
+     * @param flags Additional option flags.  The most important is
+     * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
+     * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
+     * @param userId The user id.
+     *
+     * @return Returns a ResolveInfo containing the final activity intent that
+     *         was determined to be the best action.  Returns null if no
+     *         matching activity was found. If multiple matching activities are
+     *         found and there is no default set, returns a ResolveInfo
+     *         containing something else, such as the activity resolver.
+     *
+     * @see #MATCH_DEFAULT_ONLY
+     * @see #GET_INTENT_FILTERS
+     * @see #GET_RESOLVED_FILTER
+     *
+     * @hide
+     */
+    public abstract ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId);
+
+    /**
      * Retrieve all activities that can be performed for the given intent.
      *
      * @param intent The desired intent as per resolveActivity().
@@ -1705,6 +1859,29 @@
             int flags);
 
     /**
+     * Retrieve all activities that can be performed for the given intent, for a specific user.
+     *
+     * @param intent The desired intent as per resolveActivity().
+     * @param flags Additional option flags.  The most important is
+     * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
+     * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
+     *
+     * @return A List&lt;ResolveInfo&gt; containing one entry for each matching
+     *         Activity. These are ordered from best to worst match -- that
+     *         is, the first item in the list is what is returned by
+     *         {@link #resolveActivity}.  If there are no matching activities, an empty
+     *         list is returned.
+     *
+     * @see #MATCH_DEFAULT_ONLY
+     * @see #GET_INTENT_FILTERS
+     * @see #GET_RESOLVED_FILTER
+     * @hide
+     */
+    public abstract List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent,
+            int flags, int userId);
+
+
+    /**
      * Retrieve a set of activities that should be presented to the user as
      * similar options.  This is like {@link #queryIntentActivities}, except it
      * also allows you to supply a list of more explicit Intents that you would
@@ -1754,6 +1931,26 @@
             int flags);
 
     /**
+     * Retrieve all receivers that can handle a broadcast of the given intent, for a specific
+     * user.
+     *
+     * @param intent The desired intent as per resolveActivity().
+     * @param flags Additional option flags.
+     * @param userId The userId of the user being queried.
+     *
+     * @return A List&lt;ResolveInfo&gt; containing one entry for each matching
+     *         Receiver. These are ordered from first to last in priority.  If
+     *         there are no matching receivers, an empty list is returned.
+     *
+     * @see #MATCH_DEFAULT_ONLY
+     * @see #GET_INTENT_FILTERS
+     * @see #GET_RESOLVED_FILTER
+     * @hide
+     */
+    public abstract List<ResolveInfo> queryBroadcastReceivers(Intent intent,
+            int flags, int userId);
+
+    /**
      * Determine the best service to handle for a given Intent.
      *
      * @param intent An intent containing all of the desired specification
@@ -1788,6 +1985,27 @@
             int flags);
 
     /**
+     * Retrieve all services that can match the given intent for a given user.
+     *
+     * @param intent The desired intent as per resolveService().
+     * @param flags Additional option flags.
+     * @param userId The user id.
+     *
+     * @return A List&lt;ResolveInfo&gt; containing one entry for each matching
+     *         ServiceInfo. These are ordered from best to worst match -- that
+     *         is, the first item in the list is what is returned by
+     *         resolveService().  If there are no matching services, an empty
+     *         list is returned.
+     *
+     * @see #GET_INTENT_FILTERS
+     * @see #GET_RESOLVED_FILTER
+     *
+     * @hide
+     */
+    public abstract List<ResolveInfo> queryIntentServicesAsUser(Intent intent,
+            int flags, int userId);
+
+    /**
      * Find a single content provider by its base path name.
      *
      * @param name The name of the provider to find.
@@ -2123,6 +2341,10 @@
     public abstract Resources getResourcesForApplication(String appPackageName)
             throws NameNotFoundException;
 
+    /** @hide */
+    public abstract Resources getResourcesForApplicationAsUser(String appPackageName, int userId)
+            throws NameNotFoundException;
+
     /**
      * Retrieve overall information about an application package defined
      * in a package archive file
@@ -2166,8 +2388,8 @@
         if ((flags & GET_SIGNATURES) != 0) {
             packageParser.collectCertificates(pkg, 0);
         }
-        return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0, null, false,
-                COMPONENT_ENABLED_STATE_DEFAULT);
+        PackageUserState state = new PackageUserState();
+        return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0, null, state);
     }
 
     /**
@@ -2227,6 +2449,45 @@
             ContainerEncryptionParams encryptionParams);
 
     /**
+     * Similar to
+     * {@link #installPackage(Uri, IPackageInstallObserver, int, String)} but
+     * with an extra verification information provided.
+     *
+     * @param packageURI The location of the package file to install. This can
+     *            be a 'file:' or a 'content:' URI.
+     * @param observer An observer callback to get notified when the package
+     *            installation is complete.
+     *            {@link IPackageInstallObserver#packageInstalled(String, int)}
+     *            will be called when that happens. observer may be null to
+     *            indicate that no callback is desired.
+     * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
+     *            {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}
+     *            .
+     * @param installerPackageName Optional package name of the application that
+     *            is performing the installation. This identifies which market
+     *            the package came from.
+     * @param verificationParams an object that holds signal information to
+     *            assist verification. May be {@code null}.
+     * @param encryptionParams if the package to be installed is encrypted,
+     *            these parameters describing the encryption and authentication
+     *            used. May be {@code null}.
+     *
+     * @hide
+     */
+    public abstract void installPackageWithVerificationAndEncryption(Uri packageURI,
+            IPackageInstallObserver observer, int flags, String installerPackageName,
+            VerificationParams verificationParams,
+            ContainerEncryptionParams encryptionParams);
+
+    /**
+     * If there is already an application with the given package name installed
+     * on the system for other users, also install it for the calling user.
+     * @hide
+     */
+    public abstract int installExistingPackage(String packageName)
+            throws NameNotFoundException;
+
+    /**
      * Allows a package listening to the
      * {@link Intent#ACTION_PACKAGE_NEEDS_VERIFICATION package verification
      * broadcast} to respond to the package manager. The response must include
@@ -2238,10 +2499,47 @@
      *            {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra
      * @param verificationCode either {@link PackageManager#VERIFICATION_ALLOW}
      *            or {@link PackageManager#VERIFICATION_REJECT}.
+     * @throws SecurityException if the caller does not have the
+     *            PACKAGE_VERIFICATION_AGENT permission.
      */
     public abstract void verifyPendingInstall(int id, int verificationCode);
 
     /**
+     * Allows a package listening to the
+     * {@link Intent#ACTION_PACKAGE_NEEDS_VERIFICATION package verification
+     * broadcast} to extend the default timeout for a response and declare what
+     * action to perform after the timeout occurs. The response must include
+     * the {@code verificationCodeAtTimeout} which is one of
+     * {@link PackageManager#VERIFICATION_ALLOW} or
+     * {@link PackageManager#VERIFICATION_REJECT}.
+     *
+     * This method may only be called once per package id. Additional calls
+     * will have no effect.
+     *
+     * @param id pending package identifier as passed via the
+     *            {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra
+     * @param verificationCodeAtTimeout either
+     *            {@link PackageManager#VERIFICATION_ALLOW} or
+     *            {@link PackageManager#VERIFICATION_REJECT}. If
+     *            {@code verificationCodeAtTimeout} is neither
+     *            {@link PackageManager#VERIFICATION_ALLOW} or
+     *            {@link PackageManager#VERIFICATION_REJECT}, then
+     *            {@code verificationCodeAtTimeout} will default to
+     *            {@link PackageManager#VERIFICATION_REJECT}.
+     * @param millisecondsToDelay the amount of time requested for the timeout.
+     *            Must be positive and less than
+     *            {@link PackageManager#MAXIMUM_VERIFICATION_TIMEOUT}. If
+     *            {@code millisecondsToDelay} is out of bounds,
+     *            {@code millisecondsToDelay} will be set to the closest in
+     *            bounds value; namely, 0 or
+     *            {@link PackageManager#MAXIMUM_VERIFICATION_TIMEOUT}.
+     * @throws SecurityException if the caller does not have the
+     *            PACKAGE_VERIFICATION_AGENT permission.
+     */
+    public abstract void extendVerificationTimeout(int id,
+            int verificationCodeAtTimeout, long millisecondsToDelay);
+
+    /**
      * Change the installer associated with a given package.  There are limitations
      * on how the installer package can be changed; in particular:
      * <ul>
@@ -2270,7 +2568,8 @@
      * @param observer An observer callback to get notified when the package deletion is
      * complete. {@link android.content.pm.IPackageDeleteObserver#packageDeleted(boolean)} will be
      * called when that happens.  observer may be null to indicate that no callback is desired.
-     * @param flags - possible values: {@link #DONT_DELETE_DATA}
+     * @param flags - possible values: {@link #DELETE_KEEP_DATA},
+     * {@link #DELETE_ALL_USERS}.
      *
      * @hide
      */
@@ -2376,6 +2675,7 @@
      * should have the {@link android.Manifest.permission#GET_PACKAGE_SIZE} permission.
      *
      * @param packageName The name of the package whose size information is to be retrieved
+     * @param userHandle The user whose size information should be retrieved.
      * @param observer An observer callback to get notified when the operation
      * is complete.
      * {@link android.content.pm.IPackageStatsObserver#onGetStatsCompleted(PackageStats, boolean)}
@@ -2386,10 +2686,20 @@
      *
      * @hide
      */
-    public abstract void getPackageSizeInfo(String packageName,
+    public abstract void getPackageSizeInfo(String packageName, int userHandle,
             IPackageStatsObserver observer);
 
     /**
+     * Like {@link #getPackageSizeInfo(String, int, IPackageStatsObserver)}, but
+     * returns the size for the calling user.
+     *
+     * @hide
+     */
+    public void getPackageSizeInfo(String packageName, IPackageStatsObserver observer) {
+        getPackageSizeInfo(packageName, UserHandle.myUserId(), observer);
+    }
+
+    /**
      * @deprecated This function no longer does anything; it was an old
      * approach to managing preferred activities, which has been superceeded
      * (and conflicts with) the modern activity-based preferences.
@@ -2460,6 +2770,17 @@
             ComponentName[] set, ComponentName activity);
 
     /**
+     * Same as {@link #addPreferredActivity(IntentFilter, int,
+            ComponentName[], ComponentName)}, but with a specific userId to apply the preference
+            to.
+     * @hide
+     */
+    public void addPreferredActivity(IntentFilter filter, int match,
+            ComponentName[] set, ComponentName activity, int userId) {
+        throw new RuntimeException("Not implemented. Must override in a subclass.");
+    }
+
+    /**
      * @deprecated This is a protected API that should not have been available
      * to third party applications.  It is the platform's responsibility for
      * assigning preferred activities and this can not be directly modified.
@@ -2616,56 +2937,6 @@
             String packageName, IPackageMoveObserver observer, int flags);
 
     /**
-     * Creates a user with the specified name and options.
-     *
-     * @param name the user's name
-     * @param flags flags that identify the type of user and other properties.
-     * @see UserInfo
-     *
-     * @return the UserInfo object for the created user, or null if the user could not be created.
-     * @hide
-     */
-    public abstract UserInfo createUser(String name, int flags);
-
-    /**
-     * @return the list of users that were created
-     * @hide
-     */
-    public abstract List<UserInfo> getUsers();
-
-    /**
-     * @param id the ID of the user, where 0 is the primary user.
-     * @hide
-     */
-    public abstract boolean removeUser(int id);
-
-    /**
-     * Updates the user's name.
-     *
-     * @param id the user's id
-     * @param name the new name for the user
-     * @hide
-     */
-    public abstract void updateUserName(int id, String name);
-
-    /**
-     * Changes the user's properties specified by the flags.
-     *
-     * @param id the user's id
-     * @param flags the new flags for the user
-     * @hide
-     */
-    public abstract void updateUserFlags(int id, int flags);
-
-    /**
-     * Returns the details for the user specified by userId.
-     * @param userId the user id of the user
-     * @return UserInfo for the specified user, or null if no such user exists.
-     * @hide
-     */
-    public abstract UserInfo getUser(int userId);
-
-    /**
      * Returns the device identity that verifiers can use to associate their scheme to a particular
      * device. This should not be used by anything other than a package verifier.
      * 
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index f8898c1..3e8c2a8 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -28,7 +28,7 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.PatternMatcher;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.util.Base64;
 import android.util.DisplayMetrics;
@@ -203,11 +203,14 @@
      */
     public static class PackageLite {
         public final String packageName;
+        public final int versionCode;
         public final int installLocation;
         public final VerifierInfo[] verifiers;
 
-        public PackageLite(String packageName, int installLocation, List<VerifierInfo> verifiers) {
+        public PackageLite(String packageName, int versionCode,
+                int installLocation, List<VerifierInfo> verifiers) {
             this.packageName = packageName;
+            this.versionCode = versionCode;
             this.installLocation = installLocation;
             this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
         }
@@ -243,14 +246,15 @@
         return name.endsWith(".apk");
     }
 
+    /*
     public static PackageInfo generatePackageInfo(PackageParser.Package p,
             int gids[], int flags, long firstInstallTime, long lastUpdateTime,
             HashSet<String> grantedPermissions) {
-
+        PackageUserState state = new PackageUserState();
         return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
-                grantedPermissions, false, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
-                UserId.getCallingUserId());
+                grantedPermissions, state, UserHandle.getCallingUserId());
     }
+    */
 
     /**
      * Generate and return the {@link PackageInfo} for a parsed package.
@@ -260,23 +264,30 @@
      */
     public static PackageInfo generatePackageInfo(PackageParser.Package p,
             int gids[], int flags, long firstInstallTime, long lastUpdateTime,
-            HashSet<String> grantedPermissions, boolean stopped, int enabledState) {
+            HashSet<String> grantedPermissions, PackageUserState state) {
 
         return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
-                grantedPermissions, stopped, enabledState, UserId.getCallingUserId());
+                grantedPermissions, state, UserHandle.getCallingUserId());
+    }
+
+    private static boolean checkUseInstalled(int flags, PackageUserState state) {
+        return state.installed || ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0);
     }
 
     public static PackageInfo generatePackageInfo(PackageParser.Package p,
             int gids[], int flags, long firstInstallTime, long lastUpdateTime,
-            HashSet<String> grantedPermissions, boolean stopped, int enabledState, int userId) {
+            HashSet<String> grantedPermissions, PackageUserState state, int userId) {
 
+        if (!checkUseInstalled(flags, state)) {
+            return null;
+        }
         PackageInfo pi = new PackageInfo();
         pi.packageName = p.packageName;
         pi.versionCode = p.mVersionCode;
         pi.versionName = p.mVersionName;
         pi.sharedUserId = p.mSharedUserId;
         pi.sharedUserLabel = p.mSharedUserLabel;
-        pi.applicationInfo = generateApplicationInfo(p, flags, stopped, enabledState, userId);
+        pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
         pi.installLocation = p.installLocation;
         pi.firstInstallTime = firstInstallTime;
         pi.lastUpdateTime = lastUpdateTime;
@@ -312,7 +323,7 @@
                     if (activity.info.enabled
                         || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
                         pi.activities[j++] = generateActivityInfo(p.activities.get(i), flags,
-                                stopped, enabledState, userId);
+                                state, userId);
                     }
                 }
             }
@@ -334,7 +345,7 @@
                     if (activity.info.enabled
                         || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
                         pi.receivers[j++] = generateActivityInfo(p.receivers.get(i), flags,
-                                stopped, enabledState, userId);
+                                state, userId);
                     }
                 }
             }
@@ -355,8 +366,8 @@
                     final Service service = p.services.get(i);
                     if (service.info.enabled
                         || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
-                        pi.services[j++] = generateServiceInfo(p.services.get(i), flags, stopped,
-                                enabledState, userId);
+                        pi.services[j++] = generateServiceInfo(p.services.get(i), flags,
+                                state, userId);
                     }
                 }
             }
@@ -377,8 +388,8 @@
                     final Provider provider = p.providers.get(i);
                     if (provider.info.enabled
                         || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
-                        pi.providers[j++] = generateProviderInfo(p.providers.get(i), flags, stopped,
-                                enabledState, userId);
+                        pi.providers[j++] = generateProviderInfo(p.providers.get(i), flags,
+                                state, userId);
                     }
                 }
             }
@@ -840,11 +851,19 @@
             return null;
         }
         int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
+        int versionCode = 0;
+        int numFound = 0;
         for (int i = 0; i < attrs.getAttributeCount(); i++) {
             String attr = attrs.getAttributeName(i);
             if (attr.equals("installLocation")) {
                 installLocation = attrs.getAttributeIntValue(i,
                         PARSE_DEFAULT_INSTALL_LOCATION);
+                numFound++;
+            } else if (attr.equals("versionCode")) {
+                versionCode = attrs.getAttributeIntValue(i, 0);
+                numFound++;
+            }
+            if (numFound >= 2) {
                 break;
             }
         }
@@ -867,7 +886,7 @@
             }
         }
 
-        return new PackageLite(pkgName.intern(), installLocation, verifiers);
+        return new PackageLite(pkgName.intern(), versionCode, installLocation, verifiers);
     }
 
     /**
@@ -1468,7 +1487,8 @@
         perm.info.descriptionRes = sa.getResourceId(
                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
                 0);
-        perm.info.flags = 0;
+        perm.info.flags = sa.getInt(
+                com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
         perm.info.priority = sa.getInt(
                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
         if (perm.info.priority > 0 && (flags&PARSE_IS_SYSTEM) == 0) {
@@ -1523,6 +1543,9 @@
                 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
                 PermissionInfo.PROTECTION_NORMAL);
 
+        perm.info.flags = sa.getInt(
+                com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
+
         sa.recycle();
 
         if (perm.info.protectionLevel == -1) {
@@ -2040,7 +2063,7 @@
             return null;
         }
 
-        final boolean setExported = sa.hasValue(
+        boolean setExported = sa.hasValue(
                 com.android.internal.R.styleable.AndroidManifestActivity_exported);
         if (setExported) {
             a.info.exported = sa.getBoolean(
@@ -2137,11 +2160,17 @@
         }
 
         if (sa.getBoolean(
+                com.android.internal.R.styleable.AndroidManifestActivity_showOnLockScreen,
+                false)) {
+            a.info.flags |= ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN;
+        }
+
+        if (sa.getBoolean(
                 com.android.internal.R.styleable.AndroidManifestActivity_immersive,
                 false)) {
             a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
         }
-        
+
         if (!receiver) {
             if (sa.getBoolean(
                     com.android.internal.R.styleable.AndroidManifestActivity_hardwareAccelerated,
@@ -2166,6 +2195,26 @@
             a.info.configChanges = 0;
         }
 
+        if (receiver) {
+            if (sa.getBoolean(
+                    com.android.internal.R.styleable.AndroidManifestActivity_singleUser,
+                    false)) {
+                a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
+                if (a.info.exported) {
+                    Slog.w(TAG, "Activity exported request ignored due to singleUser: "
+                            + a.className + " at " + mArchiveSourcePath + " "
+                            + parser.getPositionDescription());
+                    a.info.exported = false;
+                }
+                setExported = true;
+            }
+            if (sa.getBoolean(
+                    com.android.internal.R.styleable.AndroidManifestActivity_primaryUserOnly,
+                    false)) {
+                a.info.flags |= ActivityInfo.FLAG_PRIMARY_USER_ONLY;
+            }
+        }
+
         sa.recycle();
 
         if (receiver && (owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
@@ -2428,8 +2477,18 @@
             return null;
         }
 
+        boolean providerExportedDefault = false;
+
+        if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            // For compatibility, applications targeting API level 16 or lower
+            // should have their content providers exported by default, unless they
+            // specify otherwise.
+            providerExportedDefault = true;
+        }
+
         p.info.exported = sa.getBoolean(
-                com.android.internal.R.styleable.AndroidManifestProvider_exported, true);
+                com.android.internal.R.styleable.AndroidManifestProvider_exported,
+                providerExportedDefault);
 
         String cpname = sa.getNonConfigurationString(
                 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
@@ -2475,6 +2534,20 @@
                 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
                 0);
 
+        p.info.flags = 0;
+
+        if (sa.getBoolean(
+                com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
+                false)) {
+            p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
+            if (p.info.exported) {
+                Slog.w(TAG, "Provider exported request ignored due to singleUser: "
+                        + p.className + " at " + mArchiveSourcePath + " "
+                        + parser.getPositionDescription());
+                p.info.exported = false;
+            }
+        }
+
         sa.recycle();
 
         if ((owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
@@ -2487,7 +2560,7 @@
         }
         
         if (cpname == null) {
-            outError[0] = "<provider> does not incude authorities attribute";
+            outError[0] = "<provider> does not include authorities attribute";
             return null;
         }
         p.info.authority = cpname.intern();
@@ -2703,7 +2776,7 @@
             return null;
         }
 
-        final boolean setExported = sa.hasValue(
+        boolean setExported = sa.hasValue(
                 com.android.internal.R.styleable.AndroidManifestService_exported);
         if (setExported) {
             s.info.exported = sa.getBoolean(
@@ -2729,6 +2802,18 @@
                 false)) {
             s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
         }
+        if (sa.getBoolean(
+                com.android.internal.R.styleable.AndroidManifestService_singleUser,
+                false)) {
+            s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
+            if (s.info.exported) {
+                Slog.w(TAG, "Service exported request ignored due to singleUser: "
+                        + s.className + " at " + mArchiveSourcePath + " "
+                        + parser.getPositionDescription());
+                s.info.exported = false;
+            }
+            setExported = true;
+        }
 
         sa.recycle();
 
@@ -3407,13 +3492,25 @@
         }
     }
 
-    private static boolean copyNeeded(int flags, Package p, int enabledState, Bundle metaData) {
-        if (enabledState != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
-            boolean enabled = enabledState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+    private static boolean copyNeeded(int flags, Package p,
+            PackageUserState state, Bundle metaData, int userId) {
+        if (userId != 0) {
+            // We always need to copy for other users, since we need
+            // to fix up the uid.
+            return true;
+        }
+        if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
+            boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
             if (p.applicationInfo.enabled != enabled) {
                 return true;
             }
         }
+        if (!state.installed) {
+            return true;
+        }
+        if (state.stopped) {
+            return true;
+        }
         if ((flags & PackageManager.GET_META_DATA) != 0
                 && (metaData != null || p.mAppMetaData != null)) {
             return true;
@@ -3425,39 +3522,41 @@
         return false;
     }
 
-    public static ApplicationInfo generateApplicationInfo(Package p, int flags, boolean stopped,
-            int enabledState) {
-        return generateApplicationInfo(p, flags, stopped, enabledState, UserId.getCallingUserId());
+    public static ApplicationInfo generateApplicationInfo(Package p, int flags,
+            PackageUserState state) {
+        return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
     }
 
     public static ApplicationInfo generateApplicationInfo(Package p, int flags,
-            boolean stopped, int enabledState, int userId) {
+            PackageUserState state, int userId) {
         if (p == null) return null;
-        if (!copyNeeded(flags, p, enabledState, null) && userId == 0) {
+        if (!checkUseInstalled(flags, state)) {
+            return null;
+        }
+        if (!copyNeeded(flags, p, state, null, userId)) {
             // CompatibilityMode is global state. It's safe to modify the instance
             // of the package.
             if (!sCompatibilityModeEnabled) {
                 p.applicationInfo.disableCompatibilityMode();
             }
-            if (stopped) {
-                p.applicationInfo.flags |= ApplicationInfo.FLAG_STOPPED;
-            } else {
-                p.applicationInfo.flags &= ~ApplicationInfo.FLAG_STOPPED;
-            }
-            if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+            // Make sure we report as installed.  Also safe to do, since the
+            // default state should be installed (we will always copy if we
+            // need to report it is not installed).
+            p.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
+            if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
                 p.applicationInfo.enabled = true;
-            } else if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
-                    || enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
+            } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+                    || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
                 p.applicationInfo.enabled = false;
             }
-            p.applicationInfo.enabledSetting = enabledState;
+            p.applicationInfo.enabledSetting = state.enabled;
             return p.applicationInfo;
         }
 
         // Make shallow copy so we can store the metadata/libraries safely
         ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
         if (userId != 0) {
-            ai.uid = UserId.getUid(userId, ai.uid);
+            ai.uid = UserHandle.getUid(userId, ai.uid);
             ai.dataDir = PackageManager.getDataDirForUser(userId, ai.packageName);
         }
         if ((flags & PackageManager.GET_META_DATA) != 0) {
@@ -3469,18 +3568,23 @@
         if (!sCompatibilityModeEnabled) {
             ai.disableCompatibilityMode();
         }
-        if (stopped) {
+        if (state.stopped) {
             ai.flags |= ApplicationInfo.FLAG_STOPPED;
         } else {
             ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
         }
-        if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+        if (state.installed) {
+            ai.flags |= ApplicationInfo.FLAG_INSTALLED;
+        } else {
+            ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
+        }
+        if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
             ai.enabled = true;
-        } else if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
-                || enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
+        } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+                || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
             ai.enabled = false;
         }
-        ai.enabledSetting = enabledState;
+        ai.enabledSetting = state.enabled;
         return ai;
     }
 
@@ -3527,16 +3631,19 @@
         }
     }
 
-    public static final ActivityInfo generateActivityInfo(Activity a, int flags, boolean stopped,
-            int enabledState, int userId) {
+    public static final ActivityInfo generateActivityInfo(Activity a, int flags,
+            PackageUserState state, int userId) {
         if (a == null) return null;
-        if (!copyNeeded(flags, a.owner, enabledState, a.metaData) && userId == 0) {
+        if (!checkUseInstalled(flags, state)) {
+            return null;
+        }
+        if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
             return a.info;
         }
         // Make shallow copies so we can store the metadata safely
         ActivityInfo ai = new ActivityInfo(a.info);
         ai.metaData = a.metaData;
-        ai.applicationInfo = generateApplicationInfo(a.owner, flags, stopped, enabledState, userId);
+        ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
         return ai;
     }
 
@@ -3561,17 +3668,19 @@
         }
     }
 
-    public static final ServiceInfo generateServiceInfo(Service s, int flags, boolean stopped,
-            int enabledState, int userId) {
+    public static final ServiceInfo generateServiceInfo(Service s, int flags,
+            PackageUserState state, int userId) {
         if (s == null) return null;
-        if (!copyNeeded(flags, s.owner, enabledState, s.metaData)
-                && userId == UserId.getUserId(s.info.applicationInfo.uid)) {
+        if (!checkUseInstalled(flags, state)) {
+            return null;
+        }
+        if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
             return s.info;
         }
         // Make shallow copies so we can store the metadata safely
         ServiceInfo si = new ServiceInfo(s.info);
         si.metaData = s.metaData;
-        si.applicationInfo = generateApplicationInfo(s.owner, flags, stopped, enabledState, userId);
+        si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
         return si;
     }
 
@@ -3604,13 +3713,15 @@
         }
     }
 
-    public static final ProviderInfo generateProviderInfo(Provider p, int flags, boolean stopped,
-            int enabledState, int userId) {
+    public static final ProviderInfo generateProviderInfo(Provider p, int flags,
+            PackageUserState state, int userId) {
         if (p == null) return null;
-        if (!copyNeeded(flags, p.owner, enabledState, p.metaData)
+        if (!checkUseInstalled(flags, state)) {
+            return null;
+        }
+        if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
                 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
-                        || p.info.uriPermissionPatterns == null)
-                && userId == 0) {
+                        || p.info.uriPermissionPatterns == null)) {
             return p.info;
         }
         // Make shallow copies so we can store the metadata safely
@@ -3619,7 +3730,7 @@
         if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
             pi.uriPermissionPatterns = null;
         }
-        pi.applicationInfo = generateApplicationInfo(p.owner, flags, stopped, enabledState, userId);
+        pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
         return pi;
     }
 
diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java
index 1205da7..cb9039b 100644
--- a/core/java/android/content/pm/PackageStats.java
+++ b/core/java/android/content/pm/PackageStats.java
@@ -18,6 +18,7 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
 
 /**
  * implementation of PackageStats associated with a
@@ -27,6 +28,9 @@
     /** Name of the package to which this stats applies. */
     public String packageName;
 
+    /** @hide */
+    public int userHandle;
+
     /** Size of the code (e.g., APK) */
     public long codeSize;
 
@@ -78,33 +82,58 @@
     public String toString() {
         final StringBuilder sb = new StringBuilder("PackageStats{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
-        sb.append(" packageName=");
+        sb.append(" ");
         sb.append(packageName);
-        sb.append(",codeSize=");
-        sb.append(codeSize);
-        sb.append(",dataSize=");
-        sb.append(dataSize);
-        sb.append(",cacheSize=");
-        sb.append(cacheSize);
-        sb.append(",externalCodeSize=");
-        sb.append(externalCodeSize);
-        sb.append(",externalDataSize=");
-        sb.append(externalDataSize);
-        sb.append(",externalCacheSize=");
-        sb.append(externalCacheSize);
-        sb.append(",externalMediaSize=");
-        sb.append(externalMediaSize);
-        sb.append(",externalObbSize=");
-        sb.append(externalObbSize);
+        if (codeSize != 0) {
+            sb.append(" code=");
+            sb.append(codeSize);
+        }
+        if (dataSize != 0) {
+            sb.append(" data=");
+            sb.append(dataSize);
+        }
+        if (cacheSize != 0) {
+            sb.append(" cache=");
+            sb.append(cacheSize);
+        }
+        if (externalCodeSize != 0) {
+            sb.append(" extCode=");
+            sb.append(externalCodeSize);
+        }
+        if (externalDataSize != 0) {
+            sb.append(" extData=");
+            sb.append(externalDataSize);
+        }
+        if (externalCacheSize != 0) {
+            sb.append(" extCache=");
+            sb.append(externalCacheSize);
+        }
+        if (externalMediaSize != 0) {
+            sb.append(" media=");
+            sb.append(externalMediaSize);
+        }
+        if (externalObbSize != 0) {
+            sb.append(" obb=");
+            sb.append(externalObbSize);
+        }
+        sb.append("}");
         return sb.toString();
     }
 
     public PackageStats(String pkgName) {
         packageName = pkgName;
+        userHandle = UserHandle.myUserId();
+    }
+
+    /** @hide */
+    public PackageStats(String pkgName, int userHandle) {
+        this.packageName = pkgName;
+        this.userHandle = userHandle;
     }
 
     public PackageStats(Parcel source) {
         packageName = source.readString();
+        userHandle = source.readInt();
         codeSize = source.readLong();
         dataSize = source.readLong();
         cacheSize = source.readLong();
@@ -117,6 +146,7 @@
 
     public PackageStats(PackageStats pStats) {
         packageName = pStats.packageName;
+        userHandle = pStats.userHandle;
         codeSize = pStats.codeSize;
         dataSize = pStats.dataSize;
         cacheSize = pStats.cacheSize;
@@ -133,6 +163,7 @@
 
     public void writeToParcel(Parcel dest, int parcelableFlags){
         dest.writeString(packageName);
+        dest.writeInt(userHandle);
         dest.writeLong(codeSize);
         dest.writeLong(dataSize);
         dest.writeLong(cacheSize);
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
new file mode 100644
index 0000000..3579977
--- /dev/null
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+
+import java.util.HashSet;
+
+/**
+ * Per-user state information about a package.
+ * @hide
+ */
+public class PackageUserState {
+    public boolean stopped;
+    public boolean notLaunched;
+    public boolean installed;
+    public int enabled;
+
+    public HashSet<String> disabledComponents;
+    public HashSet<String> enabledComponents;
+
+    public PackageUserState() {
+        installed = true;
+        enabled = COMPONENT_ENABLED_STATE_DEFAULT;
+    }
+
+    public PackageUserState(PackageUserState o) {
+        installed = o.installed;
+        stopped = o.stopped;
+        notLaunched = o.notLaunched;
+        enabled = o.enabled;
+        disabledComponents = o.disabledComponents != null
+                ? new HashSet<String>(o.disabledComponents) : null;
+        enabledComponents = o.enabledComponents != null
+                ? new HashSet<String>(o.enabledComponents) : null;
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/content/pm/PermissionGroupInfo.java b/core/java/android/content/pm/PermissionGroupInfo.java
index 96d30d4..452bf0d 100644
--- a/core/java/android/content/pm/PermissionGroupInfo.java
+++ b/core/java/android/content/pm/PermissionGroupInfo.java
@@ -44,20 +44,17 @@
     /**
      * Flag for {@link #flags}, corresponding to <code>personalInfo</code>
      * value of {@link android.R.attr#permissionGroupFlags}.
-     * @hide
      */
     public static final int FLAG_PERSONAL_INFO = 1<<0;
 
     /**
      * Additional flags about this group as given by
      * {@link android.R.attr#permissionGroupFlags}.
-     * @hide
      */
     public int flags;
 
     /**
      * Prioritization of this group, for visually sorting with other groups.
-     * @hide
      */
     public int priority;
 
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 69b812c..5a63e5f 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -79,11 +79,34 @@
     public static final int PROTECTION_MASK_FLAGS = 0xf0;
 
     /**
+     * The level of access this permission is protecting, as per
+     * {@link android.R.attr#protectionLevel}.  Values may be
+     * {@link #PROTECTION_NORMAL}, {@link #PROTECTION_DANGEROUS}, or
+     * {@link #PROTECTION_SIGNATURE}.  May also include the additional
+     * flags {@link #PROTECTION_FLAG_SYSTEM} or {@link #PROTECTION_FLAG_DEVELOPMENT}
+     * (which only make sense in combination with the base
+     * {@link #PROTECTION_SIGNATURE}.
+     */
+    public int protectionLevel;
+
+    /**
      * The group this permission is a part of, as per
      * {@link android.R.attr#permissionGroup}.
      */
     public String group;
-    
+
+    /**
+     * Flag for {@link #flags}, corresponding to <code>costsMoney</code>
+     * value of {@link android.R.attr#permissionFlags}.
+     */
+    public static final int FLAG_COSTS_MONEY = 1<<0;
+
+    /**
+     * Additional flags about this permission as given by
+     * {@link android.R.attr#permissionFlags}.
+     */
+    public int flags;
+
     /**
      * A string resource identifier (in the package's resources) of this
      * permission's description.  From the "description" attribute or,
@@ -99,17 +122,6 @@
      */
     public CharSequence nonLocalizedDescription;
 
-    /**
-     * The level of access this permission is protecting, as per
-     * {@link android.R.attr#protectionLevel}.  Values may be
-     * {@link #PROTECTION_NORMAL}, {@link #PROTECTION_DANGEROUS}, or
-     * {@link #PROTECTION_SIGNATURE}.  May also include the additional
-     * flags {@link #PROTECTION_FLAG_SYSTEM} or {@link #PROTECTION_FLAG_DEVELOPMENT}
-     * (which only make sense in combination with the base
-     * {@link #PROTECTION_SIGNATURE}.
-     */
-    public int protectionLevel;
-
     /** @hide */
     public static int fixProtectionLevel(int level) {
         if (level == PROTECTION_SIGNATURE_OR_SYSTEM) {
@@ -149,9 +161,10 @@
 
     public PermissionInfo(PermissionInfo orig) {
         super(orig);
+        protectionLevel = orig.protectionLevel;
+        flags = orig.flags;
         group = orig.group;
         descriptionRes = orig.descriptionRes;
-        protectionLevel = orig.protectionLevel;
         nonLocalizedDescription = orig.nonLocalizedDescription;
     }
 
@@ -191,9 +204,10 @@
 
     public void writeToParcel(Parcel dest, int parcelableFlags) {
         super.writeToParcel(dest, parcelableFlags);
+        dest.writeInt(protectionLevel);
+        dest.writeInt(flags);
         dest.writeString(group);
         dest.writeInt(descriptionRes);
-        dest.writeInt(protectionLevel);
         TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags);
     }
 
@@ -209,9 +223,10 @@
 
     private PermissionInfo(Parcel source) {
         super(source);
+        protectionLevel = source.readInt();
+        flags = source.readInt();
         group = source.readString();
         descriptionRes = source.readInt();
-        protectionLevel = source.readInt();
         nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
     }
 }
diff --git a/core/java/android/content/pm/ProviderInfo.java b/core/java/android/content/pm/ProviderInfo.java
index ec01775..a534176 100644
--- a/core/java/android/content/pm/ProviderInfo.java
+++ b/core/java/android/content/pm/ProviderInfo.java
@@ -73,7 +73,21 @@
     /** Used to control initialization order of single-process providers
      *  running in the same process.  Higher goes first. */
     public int initOrder = 0;
-    
+
+    /**
+     * Bit in {@link #flags}: If set, a single instance of the provider will
+     * run for all users on the device.  Set from the
+     * {@link android.R.attr#singleUser} attribute.
+     */
+    public static final int FLAG_SINGLE_USER = 0x40000000;
+
+    /**
+     * Options that have been set in the provider declaration in the
+     * manifest.
+     * These include: {@link #FLAG_SINGLE_USER}.
+     */
+    public int flags = 0;
+
     /**
      * Whether or not this provider is syncable.
      * @deprecated This flag is now being ignored. The current way to make a provider
@@ -95,6 +109,7 @@
         pathPermissions = orig.pathPermissions;
         multiprocess = orig.multiprocess;
         initOrder = orig.initOrder;
+        flags = orig.flags;
         isSyncable = orig.isSyncable;
     }
     
@@ -112,6 +127,7 @@
         out.writeTypedArray(pathPermissions, parcelableFlags);
         out.writeInt(multiprocess ? 1 : 0);
         out.writeInt(initOrder);
+        out.writeInt(flags);
         out.writeInt(isSyncable ? 1 : 0);
     }
 
@@ -127,8 +143,7 @@
     };
 
     public String toString() {
-        return "ContentProviderInfo{name=" + authority + " className=" + name
-            + " isSyncable=" + (isSyncable ? "true" : "false") + "}";
+        return "ContentProviderInfo{name=" + authority + " className=" + name + "}";
     }
 
     private ProviderInfo(Parcel in) {
@@ -141,6 +156,7 @@
         pathPermissions = in.createTypedArray(PathPermission.CREATOR);
         multiprocess = in.readInt() != 0;
         initOrder = in.readInt();
+        flags = in.readInt();
         isSyncable = in.readInt() != 0;
     }
 }
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index d8f9204..6def4a1 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -16,49 +16,54 @@
 
 package android.content.pm;
 
-import android.content.Context;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.ComponentName;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.os.Environment;
 import android.os.Handler;
-import android.util.Log;
+import android.os.UserHandle;
+import android.util.AtomicFile;
 import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
 import android.util.Xml;
 
-import java.util.Map;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.concurrent.atomic.AtomicReference;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.io.IOException;
-import java.io.FileInputStream;
-
-import com.android.internal.os.AtomicFile;
 import com.android.internal.util.FastXmlSerializer;
-
-import com.google.android.collect.Maps;
 import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
 
-import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
 /**
- * A cache of registered services. This cache
- * is built by interrogating the {@link PackageManager} and is updated as packages are added,
- * removed and changed. The services are referred to by type V and
- * are made available via the {@link #getServiceInfo} method.
+ * Cache of registered services. This cache is lazily built by interrogating
+ * {@link PackageManager} on a per-user basis. It's updated as packages are
+ * added, removed and changed. Users are responsible for calling
+ * {@link #invalidateCache(int)} when a user is started, since
+ * {@link PackageManager} broadcasts aren't sent for stopped users.
+ * <p>
+ * The services are referred to by type V and are made available via the
+ * {@link #getServiceInfo} method.
+ * 
  * @hide
  */
 public abstract class RegisteredServicesCache<V> {
@@ -69,15 +74,29 @@
     private final String mMetaDataName;
     private final String mAttributesName;
     private final XmlSerializerAndParser<V> mSerializerAndParser;
-    private final AtomicReference<BroadcastReceiver> mReceiver;
 
     private final Object mServicesLock = new Object();
-    // synchronized on mServicesLock
-    private HashMap<V, Integer> mPersistentServices;
-    // synchronized on mServicesLock
-    private Map<V, ServiceInfo<V>> mServices;
-    // synchronized on mServicesLock
+
+    // @GuardedBy("mServicesLock")
     private boolean mPersistentServicesFileDidNotExist;
+    // @GuardedBy("mServicesLock")
+    private final SparseArray<UserServices<V>> mUserServices = new SparseArray<UserServices<V>>();
+
+    private static class UserServices<V> {
+        // @GuardedBy("mServicesLock")
+        public final Map<V, Integer> persistentServices = Maps.newHashMap();
+        // @GuardedBy("mServicesLock")
+        public Map<V, ServiceInfo<V>> services = null;
+    }
+
+    private UserServices<V> findOrCreateUserLocked(int userId) {
+        UserServices<V> services = mUserServices.get(userId);
+        if (services == null) {
+            services = new UserServices<V>();
+            mUserServices.put(userId, services);
+        }
+        return services;
+    }
 
     /**
      * This file contains the list of known services. We would like to maintain this forever
@@ -102,36 +121,59 @@
         File syncDir = new File(systemDir, "registered_services");
         mPersistentServicesFile = new AtomicFile(new File(syncDir, interfaceName + ".xml"));
 
-        generateServicesMap();
+        // Load persisted services from disk
+        readPersistentServicesLocked();
 
-        final BroadcastReceiver receiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context1, Intent intent) {
-                generateServicesMap();
-            }
-        };
-        mReceiver = new AtomicReference<BroadcastReceiver>(receiver);
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
         intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         intentFilter.addDataScheme("package");
-        mContext.registerReceiver(receiver, intentFilter);
+        mContext.registerReceiverAsUser(mPackageReceiver, UserHandle.ALL, intentFilter, null, null);
+
         // Register for events related to sdcard installation.
         IntentFilter sdFilter = new IntentFilter();
         sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
         sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
-        mContext.registerReceiver(receiver, sdFilter);
+        mContext.registerReceiver(mExternalReceiver, sdFilter);
     }
 
-    public void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
-        Map<V, ServiceInfo<V>> services;
-        synchronized (mServicesLock) {
-            services = mServices;
+    private final BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+            if (uid != -1) {
+                generateServicesMap(UserHandle.getUserId(uid));
+            }
         }
-        fout.println("RegisteredServicesCache: " + services.size() + " services");
-        for (ServiceInfo info : services.values()) {
-            fout.println("  " + info);
+    };
+
+    private final BroadcastReceiver mExternalReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // External apps can't coexist with multi-user, so scan owner
+            generateServicesMap(UserHandle.USER_OWNER);
+        }
+    };
+
+    public void invalidateCache(int userId) {
+        synchronized (mServicesLock) {
+            final UserServices<V> user = findOrCreateUserLocked(userId);
+            user.services = null;
+        }
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter fout, String[] args, int userId) {
+        synchronized (mServicesLock) {
+            final UserServices<V> user = findOrCreateUserLocked(userId);
+            if (user.services != null) {
+                fout.println("RegisteredServicesCache: " + user.services.size() + " services");
+                for (ServiceInfo<?> info : user.services.values()) {
+                    fout.println("  " + info);
+                }
+            } else {
+                fout.println("RegisteredServicesCache: services not loaded");
+            }
         }
     }
 
@@ -151,7 +193,7 @@
         }
     }
 
-    private void notifyListener(final V type, final boolean removed) {
+    private void notifyListener(final V type, final int userId, final boolean removed) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.d(TAG, "notifyListener: " + type + " is " + (removed ? "removed" : "added"));
         }
@@ -168,7 +210,7 @@
         final RegisteredServicesCacheListener<V> listener2 = listener;
         handler.post(new Runnable() {
             public void run() {
-                listener2.onServiceChanged(type, removed);
+                listener2.onServiceChanged(type, userId, removed);
             }
         });
     }
@@ -200,9 +242,14 @@
      * @param type the account type of the authenticator
      * @return the AuthenticatorInfo that matches the account type or null if none is present
      */
-    public ServiceInfo<V> getServiceInfo(V type) {
+    public ServiceInfo<V> getServiceInfo(V type, int userId) {
         synchronized (mServicesLock) {
-            return mServices.get(type);
+            // Find user and lazily populate cache
+            final UserServices<V> user = findOrCreateUserLocked(userId);
+            if (user.services == null) {
+                generateServicesMap(userId);
+            }
+            return user.services.get(type);
         }
     }
 
@@ -210,31 +257,18 @@
      * @return a collection of {@link RegisteredServicesCache.ServiceInfo} objects for all
      * registered authenticators.
      */
-    public Collection<ServiceInfo<V>> getAllServices() {
+    public Collection<ServiceInfo<V>> getAllServices(int userId) {
         synchronized (mServicesLock) {
-            return Collections.unmodifiableCollection(mServices.values());
+            // Find user and lazily populate cache
+            final UserServices<V> user = findOrCreateUserLocked(userId);
+            if (user.services == null) {
+                generateServicesMap(userId);
+            }
+            return Collections.unmodifiableCollection(
+                    new ArrayList<ServiceInfo<V>>(user.services.values()));
         }
     }
 
-    /**
-     * Stops the monitoring of package additions, removals and changes.
-     */
-    public void close() {
-        final BroadcastReceiver receiver = mReceiver.getAndSet(null);
-        if (receiver != null) {
-            mContext.unregisterReceiver(receiver);
-        }
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        if (mReceiver.get() != null) {
-            Log.e(TAG, "RegisteredServicesCache finalized without being closed");
-        }
-        close();
-        super.finalize();
-    }
-
     private boolean inSystemImage(int callerUid) {
         String[] packages = mContext.getPackageManager().getPackagesForUid(callerUid);
         for (String name : packages) {
@@ -251,11 +285,17 @@
         return false;
     }
 
-    public void generateServicesMap() {
-        PackageManager pm = mContext.getPackageManager();
-        ArrayList<ServiceInfo<V>> serviceInfos = new ArrayList<ServiceInfo<V>>();
-        List<ResolveInfo> resolveInfos = pm.queryIntentServices(new Intent(mInterfaceName),
-                PackageManager.GET_META_DATA);
+    /**
+     * Populate {@link UserServices#services} by scanning installed packages for
+     * given {@link UserHandle}.
+     */
+    private void generateServicesMap(int userId) {
+        Slog.d(TAG, "generateServicesMap() for " + userId);
+
+        final PackageManager pm = mContext.getPackageManager();
+        final ArrayList<ServiceInfo<V>> serviceInfos = new ArrayList<ServiceInfo<V>>();
+        final List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(
+                new Intent(mInterfaceName), PackageManager.GET_META_DATA, userId);
         for (ResolveInfo resolveInfo : resolveInfos) {
             try {
                 ServiceInfo<V> info = parseServiceInfo(resolveInfo);
@@ -272,10 +312,14 @@
         }
 
         synchronized (mServicesLock) {
-            if (mPersistentServices == null) {
-                readPersistentServicesLocked();
+            final UserServices<V> user = findOrCreateUserLocked(userId);
+            final boolean firstScan = user.services == null;
+            if (firstScan) {
+                user.services = Maps.newHashMap();
+            } else {
+                user.services.clear();
             }
-            mServices = Maps.newHashMap();
+
             StringBuilder changes = new StringBuilder();
             for (ServiceInfo<V> info : serviceInfos) {
                 // four cases:
@@ -287,19 +331,19 @@
                 //   - ignore
                 // - exists, the UID is different, and the new one is a system package
                 //   - add, notify user that it was added
-                Integer previousUid = mPersistentServices.get(info.type);
+                Integer previousUid = user.persistentServices.get(info.type);
                 if (previousUid == null) {
                     changes.append("  New service added: ").append(info).append("\n");
-                    mServices.put(info.type, info);
-                    mPersistentServices.put(info.type, info.uid);
-                    if (!mPersistentServicesFileDidNotExist) {
-                        notifyListener(info.type, false /* removed */);
+                    user.services.put(info.type, info);
+                    user.persistentServices.put(info.type, info.uid);
+                    if (!(mPersistentServicesFileDidNotExist && firstScan)) {
+                        notifyListener(info.type, userId, false /* removed */);
                     }
                 } else if (previousUid == info.uid) {
                     if (Log.isLoggable(TAG, Log.VERBOSE)) {
                         changes.append("  Existing service (nop): ").append(info).append("\n");
                     }
-                    mServices.put(info.type, info);
+                    user.services.put(info.type, info);
                 } else if (inSystemImage(info.uid)
                         || !containsTypeAndUid(serviceInfos, info.type, previousUid)) {
                     if (inSystemImage(info.uid)) {
@@ -309,9 +353,9 @@
                         changes.append("  Existing service replacing a removed service: ")
                                 .append(info).append("\n");
                     }
-                    mServices.put(info.type, info);
-                    mPersistentServices.put(info.type, info.uid);
-                    notifyListener(info.type, false /* removed */);
+                    user.services.put(info.type, info);
+                    user.persistentServices.put(info.type, info.uid);
+                    notifyListener(info.type, userId, false /* removed */);
                 } else {
                     // ignore
                     changes.append("  Existing service with new uid ignored: ").append(info)
@@ -320,25 +364,28 @@
             }
 
             ArrayList<V> toBeRemoved = Lists.newArrayList();
-            for (V v1 : mPersistentServices.keySet()) {
+            for (V v1 : user.persistentServices.keySet()) {
                 if (!containsType(serviceInfos, v1)) {
                     toBeRemoved.add(v1);
                 }
             }
             for (V v1 : toBeRemoved) {
-                mPersistentServices.remove(v1);
+                user.persistentServices.remove(v1);
                 changes.append("  Service removed: ").append(v1).append("\n");
-                notifyListener(v1, true /* removed */);
+                notifyListener(v1, userId, true /* removed */);
             }
             if (changes.length() > 0) {
-                Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " +
-                        serviceInfos.size() + " services:\n" + changes);
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " +
+                            serviceInfos.size() + " services:\n" + changes);
+                }
                 writePersistentServicesLocked();
             } else {
-                Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " +
-                        serviceInfos.size() + " services unchanged");
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " +
+                            serviceInfos.size() + " services unchanged");
+                }
             }
-            mPersistentServicesFileDidNotExist = false;
         }
     }
 
@@ -411,7 +458,7 @@
      * Read all sync status back in to the initial engine state.
      */
     private void readPersistentServicesLocked() {
-        mPersistentServices = Maps.newHashMap();
+        mUserServices.clear();
         if (mSerializerAndParser == null) {
             return;
         }
@@ -440,8 +487,10 @@
                                 break;
                             }
                             String uidString = parser.getAttributeValue(null, "uid");
-                            int uid = Integer.parseInt(uidString);
-                            mPersistentServices.put(service, uid);
+                            final int uid = Integer.parseInt(uidString);
+                            final int userId = UserHandle.getUserId(uid);
+                            final UserServices<V> user = findOrCreateUserLocked(userId);
+                            user.persistentServices.put(service, uid);
                         }
                     }
                     eventType = parser.next();
@@ -474,11 +523,14 @@
             out.startDocument(null, true);
             out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
             out.startTag(null, "services");
-            for (Map.Entry<V, Integer> service : mPersistentServices.entrySet()) {
-                out.startTag(null, "service");
-                out.attribute(null, "uid", Integer.toString(service.getValue()));
-                mSerializerAndParser.writeAsXml(service.getKey(), out);
-                out.endTag(null, "service");
+            for (int i = 0; i < mUserServices.size(); i++) {
+                final UserServices<V> user = mUserServices.valueAt(i);
+                for (Map.Entry<V, Integer> service : user.persistentServices.entrySet()) {
+                    out.startTag(null, "service");
+                    out.attribute(null, "uid", Integer.toString(service.getValue()));
+                    mSerializerAndParser.writeAsXml(service.getKey(), out);
+                    out.endTag(null, "service");
+                }
             }
             out.endTag(null, "services");
             out.endDocument();
diff --git a/core/java/android/content/pm/RegisteredServicesCacheListener.java b/core/java/android/content/pm/RegisteredServicesCacheListener.java
index 7095229..df79544 100644
--- a/core/java/android/content/pm/RegisteredServicesCacheListener.java
+++ b/core/java/android/content/pm/RegisteredServicesCacheListener.java
@@ -16,8 +16,6 @@
 
 package android.content.pm;
 
-import android.os.Parcelable;
-
 /**
  * Listener for changes to the set of registered services managed by a RegisteredServicesCache.
  * @hide
@@ -28,5 +26,5 @@
      * @param type the type of registered service
      * @param removed true if the service was removed
      */
-    void onServiceChanged(V type, boolean removed);
+    void onServiceChanged(V type, int userId, boolean removed);
 }
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index e3749b4..07117fe 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -230,6 +230,21 @@
     public ResolveInfo() {
     }
 
+    public ResolveInfo(ResolveInfo orig) {
+        activityInfo = orig.activityInfo;
+        serviceInfo = orig.serviceInfo;
+        filter = orig.filter;
+        priority = orig.priority;
+        preferredOrder = orig.preferredOrder;
+        match = orig.match;
+        specificIndex = orig.specificIndex;
+        labelRes = orig.labelRes;
+        nonLocalizedLabel = orig.nonLocalizedLabel;
+        icon = orig.icon;
+        resolvePackageName = orig.resolvePackageName;
+        system = orig.system;
+    }
+
     public String toString() {
         ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo;
         return "ResolveInfo{"
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index 7ee84ab..796c2a4 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -49,10 +49,18 @@
     public static final int FLAG_ISOLATED_PROCESS = 0x0002;
 
     /**
+     * Bit in {@link #flags}: If set, a single instance of the service will
+     * run for all users on the device.  Set from the
+     * {@link android.R.attr#singleUser} attribute.
+     */
+    public static final int FLAG_SINGLE_USER = 0x40000000;
+
+    /**
      * Options that have been set in the service declaration in the
      * manifest.
      * These include:
-     * {@link #FLAG_STOP_WITH_TASK}, {@link #FLAG_ISOLATED_PROCESS}.
+     * {@link #FLAG_STOP_WITH_TASK}, {@link #FLAG_ISOLATED_PROCESS},
+     * {@link #FLAG_SINGLE_USER}.
      */
     public int flags;
 
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index ba5331c..593f826 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -18,12 +18,23 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
 
 /**
  * Per-user information.
  * @hide
  */
 public class UserInfo implements Parcelable {
+
+    /** 6 bits for user type */
+    public static final int FLAG_MASK_USER_TYPE = 0x0000003F;
+
+    /**
+     * *************************** NOTE ***************************
+     * These flag values CAN NOT CHANGE because they are written
+     * directly to storage.
+     */
+
     /**
      * Primary user. Only one user can have this flag set. Meaning of this
      * flag TBD.
@@ -41,14 +52,37 @@
      */
     public static final int FLAG_GUEST   = 0x00000004;
 
+    /**
+     * Indicates the user has restrictions in privileges, in addition to those for normal users.
+     * Exact meaning TBD. For instance, maybe they can't install apps or administer WiFi access pts.
+     */
+    public static final int FLAG_RESTRICTED = 0x00000008;
+
+    /**
+     * Indicates that this user has gone through its first-time initialization.
+     */
+    public static final int FLAG_INITIALIZED = 0x00000010;
+
     public int id;
+    public int serialNumber;
     public String name;
+    public String iconPath;
     public int flags;
+    public long creationTime;
+    public long lastLoggedInTime;
+
+    /** User is only partially created. */
+    public boolean partial;
 
     public UserInfo(int id, String name, int flags) {
+        this(id, name, null, flags);
+    }
+
+    public UserInfo(int id, String name, String iconPath, int flags) {
         this.id = id;
         this.name = name;
         this.flags = flags;
+        this.iconPath = iconPath;
     }
 
     public boolean isPrimary() {
@@ -68,8 +102,17 @@
 
     public UserInfo(UserInfo orig) {
         name = orig.name;
+        iconPath = orig.iconPath;
         id = orig.id;
         flags = orig.flags;
+        serialNumber = orig.serialNumber;
+        creationTime = orig.creationTime;
+        lastLoggedInTime = orig.lastLoggedInTime;
+        partial = orig.partial;
+    }
+
+    public UserHandle getUserHandle() {
+        return new UserHandle(id);
     }
 
     @Override
@@ -84,7 +127,12 @@
     public void writeToParcel(Parcel dest, int parcelableFlags) {
         dest.writeInt(id);
         dest.writeString(name);
+        dest.writeString(iconPath);
         dest.writeInt(flags);
+        dest.writeInt(serialNumber);
+        dest.writeLong(creationTime);
+        dest.writeLong(lastLoggedInTime);
+        dest.writeInt(partial ? 1 : 0);
     }
 
     public static final Parcelable.Creator<UserInfo> CREATOR
@@ -100,6 +148,11 @@
     private UserInfo(Parcel source) {
         id = source.readInt();
         name = source.readString();
+        iconPath = source.readString();
         flags = source.readInt();
+        serialNumber = source.readInt();
+        creationTime = source.readLong();
+        lastLoggedInTime = source.readLong();
+        partial = source.readInt() != 0;
     }
 }
diff --git a/core/java/android/content/pm/VerificationParams.aidl b/core/java/android/content/pm/VerificationParams.aidl
new file mode 100644
index 0000000..5bb7f6962
--- /dev/null
+++ b/core/java/android/content/pm/VerificationParams.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+parcelable VerificationParams;
diff --git a/core/java/android/content/pm/VerificationParams.java b/core/java/android/content/pm/VerificationParams.java
new file mode 100644
index 0000000..22e1a85
--- /dev/null
+++ b/core/java/android/content/pm/VerificationParams.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.content.pm.ManifestDigest;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents verification parameters used to verify packages to be installed.
+ *
+ * @hide
+ */
+public class VerificationParams implements Parcelable {
+    /** A constant used to indicate that a uid value is not present. */
+    public static final int NO_UID = -1;
+
+    /** What we print out first when toString() is called. */
+    private static final String TO_STRING_PREFIX = "VerificationParams{";
+
+    /** The location of the supplementary verification file. */
+    private final Uri mVerificationURI;
+
+    /** URI referencing where the package was downloaded from. */
+    private final Uri mOriginatingURI;
+
+    /** HTTP referrer URI associated with the originatingURI. */
+    private final Uri mReferrer;
+
+    /** UID of the application that the install request originated from. */
+    private final int mOriginatingUid;
+
+    /** UID of application requesting the install */
+    private int mInstallerUid;
+
+    /**
+     * An object that holds the digest of the package which can be used to
+     * verify ownership.
+     */
+    private final ManifestDigest mManifestDigest;
+
+    /**
+     * Creates verification specifications for installing with application verification.
+     *
+     * @param verificationURI The location of the supplementary verification
+     *            file. This can be a 'file:' or a 'content:' URI. May be {@code null}.
+     * @param originatingURI URI referencing where the package was downloaded
+     *            from. May be {@code null}.
+     * @param referrer HTTP referrer URI associated with the originatingURI.
+     *            May be {@code null}.
+     * @param originatingUid UID of the application that the install request originated
+     *            from, or NO_UID if not present
+     * @param manifestDigest an object that holds the digest of the package
+     *            which can be used to verify ownership. May be {@code null}.
+     */
+    public VerificationParams(Uri verificationURI, Uri originatingURI, Uri referrer,
+            int originatingUid, ManifestDigest manifestDigest) {
+        mVerificationURI = verificationURI;
+        mOriginatingURI = originatingURI;
+        mReferrer = referrer;
+        mOriginatingUid = originatingUid;
+        mManifestDigest = manifestDigest;
+        mInstallerUid = NO_UID;
+    }
+
+    public Uri getVerificationURI() {
+        return mVerificationURI;
+    }
+
+    public Uri getOriginatingURI() {
+        return mOriginatingURI;
+    }
+
+    public Uri getReferrer() {
+        return mReferrer;
+    }
+
+    /** return NO_UID if not available */
+    public int getOriginatingUid() {
+        return mOriginatingUid;
+    }
+
+    public ManifestDigest getManifestDigest() {
+        return mManifestDigest;
+    }
+
+    /** @return NO_UID when not set */
+    public int getInstallerUid() {
+        return mInstallerUid;
+    }
+
+    public void setInstallerUid(int uid) {
+        mInstallerUid = uid;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (!(o instanceof VerificationParams)) {
+            return false;
+        }
+
+        final VerificationParams other = (VerificationParams) o;
+
+        if (mVerificationURI == null) {
+            if (other.mVerificationURI != null) {
+                return false;
+            }
+        } else if (!mVerificationURI.equals(other.mVerificationURI)) {
+            return false;
+        }
+
+        if (mOriginatingURI == null) {
+            if (other.mOriginatingURI != null) {
+                return false;
+            }
+        } else if (!mOriginatingURI.equals(other.mOriginatingURI)) {
+            return false;
+        }
+
+        if (mReferrer == null) {
+            if (other.mReferrer != null) {
+                return false;
+            }
+        } else if (!mReferrer.equals(other.mReferrer)) {
+            return false;
+        }
+
+        if (mOriginatingUid != other.mOriginatingUid) {
+            return false;
+        }
+
+        if (mManifestDigest == null) {
+            if (other.mManifestDigest != null) {
+                return false;
+            }
+        } else if (!mManifestDigest.equals(other.mManifestDigest)) {
+            return false;
+        }
+
+        if (mInstallerUid != other.mInstallerUid) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 3;
+
+        hash += 5 * (mVerificationURI == null ? 1 : mVerificationURI.hashCode());
+        hash += 7 * (mOriginatingURI == null ? 1 : mOriginatingURI.hashCode());
+        hash += 11 * (mReferrer == null ? 1 : mReferrer.hashCode());
+        hash += 13 * mOriginatingUid;
+        hash += 17 * (mManifestDigest == null ? 1 : mManifestDigest.hashCode());
+        hash += 19 * mInstallerUid;
+
+        return hash;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder(TO_STRING_PREFIX);
+
+        sb.append("mVerificationURI=");
+        sb.append(mVerificationURI.toString());
+        sb.append(",mOriginatingURI=");
+        sb.append(mOriginatingURI.toString());
+        sb.append(",mReferrer=");
+        sb.append(mReferrer.toString());
+        sb.append(",mOriginatingUid=");
+        sb.append(mOriginatingUid);
+        sb.append(",mManifestDigest=");
+        sb.append(mManifestDigest.toString());
+        sb.append(",mInstallerUid=");
+        sb.append(mInstallerUid);
+        sb.append('}');
+
+        return sb.toString();
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(mVerificationURI, 0);
+        dest.writeParcelable(mOriginatingURI, 0);
+        dest.writeParcelable(mReferrer, 0);
+        dest.writeInt(mOriginatingUid);
+        dest.writeParcelable(mManifestDigest, 0);
+        dest.writeInt(mInstallerUid);
+    }
+
+
+    private VerificationParams(Parcel source) {
+        mVerificationURI = source.readParcelable(Uri.class.getClassLoader());
+        mOriginatingURI = source.readParcelable(Uri.class.getClassLoader());
+        mReferrer = source.readParcelable(Uri.class.getClassLoader());
+        mOriginatingUid = source.readInt();
+        mManifestDigest = source.readParcelable(ManifestDigest.class.getClassLoader());
+        mInstallerUid = source.readInt();
+    }
+
+    public static final Parcelable.Creator<VerificationParams> CREATOR =
+            new Parcelable.Creator<VerificationParams>() {
+        public VerificationParams createFromParcel(Parcel source) {
+                return new VerificationParams(source);
+        }
+
+        public VerificationParams[] newArray(int size) {
+            return new VerificationParams[size];
+        }
+    };
+}
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 1c9285e..28c751c 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -439,7 +439,7 @@
         if (isScalingRequired()) {
             float invertedRatio = applicationInvertedScale;
             inoutDm.density = inoutDm.noncompatDensity * invertedRatio;
-            inoutDm.densityDpi = (int)((inoutDm.density*DisplayMetrics.DENSITY_DEFAULT)+.5f);
+            inoutDm.densityDpi = (int)((inoutDm.noncompatDensityDpi * invertedRatio) + .5f);
             inoutDm.scaledDensity = inoutDm.noncompatScaledDensity * invertedRatio;
             inoutDm.xdpi = inoutDm.noncompatXdpi * invertedRatio;
             inoutDm.ydpi = inoutDm.noncompatYdpi * invertedRatio;
@@ -448,7 +448,7 @@
         }
     }
 
-    public void applyToConfiguration(Configuration inoutConfig) {
+    public void applyToConfiguration(int displayDensity, Configuration inoutConfig) {
         if (!supportsScreen()) {
             // This is a larger screen device and the app is not
             // compatible with large screens, so we are forcing it to
@@ -460,6 +460,11 @@
             inoutConfig.screenHeightDp = inoutConfig.compatScreenHeightDp;
             inoutConfig.smallestScreenWidthDp = inoutConfig.compatSmallestScreenWidthDp;
         }
+        inoutConfig.densityDpi = displayDensity;
+        if (isScalingRequired()) {
+            float invertedRatio = applicationInvertedScale;
+            inoutConfig.densityDpi = (int)((inoutConfig.densityDpi * invertedRatio) + .5f);
+        }
     }
 
     /**
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 423b9af..86d6ee7 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -19,7 +19,7 @@
 import android.content.pm.ActivityInfo;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.util.LocaleUtil;
+import android.text.TextUtils;
 import android.view.View;
 
 import java.util.Locale;
@@ -35,6 +35,9 @@
  * <pre>Configuration config = getResources().getConfiguration();</pre>
  */
 public final class Configuration implements Parcelable, Comparable<Configuration> {
+    /** @hide */
+    public static final Configuration EMPTY = new Configuration();
+
     /**
      * Current user preference for the scaling factor for fonts, relative
      * to the base density scaling.
@@ -122,7 +125,25 @@
      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">long</a>
      * resource qualifier. */
     public static final int SCREENLAYOUT_LONG_YES = 0x20;
-    
+
+    /** Constant for {@link #screenLayout}: bits that encode the layout direction. */
+    public static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0;
+    /** Constant for {@link #screenLayout}: bits shift to get the layout direction. */
+    public static final int SCREENLAYOUT_LAYOUTDIR_SHIFT = 6;
+    /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
+     * value indicating that no layout dir has been set. */
+    public static final int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0x00;
+    /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
+     * value indicating that a layout dir has been set to LTR. */
+    public static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x01 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
+    /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
+     * value indicating that a layout dir has been set to RTL. */
+    public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x02 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
+
+    /** Constant for {@link #screenLayout}: a value indicating that screenLayout is undefined */
+    public static final int SCREENLAYOUT_UNDEFINED = SCREENLAYOUT_SIZE_UNDEFINED |
+            SCREENLAYOUT_LONG_UNDEFINED | SCREENLAYOUT_LAYOUTDIR_UNDEFINED;
+
     /**
      * Special flag we generate to indicate that the screen layout requires
      * us to use a compatibility mode for apps that are not modern layout
@@ -143,11 +164,85 @@
      * is wider/taller than normal.  They may be one of
      * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.
      * 
+     * <p>The {@link #SCREENLAYOUT_LAYOUTDIR_MASK} defines whether the screen layout
+     * is either LTR or RTL.  They may be one of
+     * {@link #SCREENLAYOUT_LAYOUTDIR_LTR} or {@link #SCREENLAYOUT_LAYOUTDIR_RTL}.
+     *
      * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
      * Multiple Screens</a> for more information.
      */
     public int screenLayout;
-    
+
+    /** @hide */
+    static public int resetScreenLayout(int curLayout) {
+        return (curLayout&~(SCREENLAYOUT_LONG_MASK | SCREENLAYOUT_SIZE_MASK
+                        | SCREENLAYOUT_COMPAT_NEEDED))
+                | (SCREENLAYOUT_LONG_YES | SCREENLAYOUT_SIZE_XLARGE);
+    }
+
+    /** @hide */
+    static public int reduceScreenLayout(int curLayout, int longSizeDp, int shortSizeDp) {
+        int screenLayoutSize;
+        boolean screenLayoutLong;
+        boolean screenLayoutCompatNeeded;
+
+        // These semi-magic numbers define our compatibility modes for
+        // applications with different screens.  These are guarantees to
+        // app developers about the space they can expect for a particular
+        // configuration.  DO NOT CHANGE!
+        if (longSizeDp < 470) {
+            // This is shorter than an HVGA normal density screen (which
+            // is 480 pixels on its long side).
+            screenLayoutSize = SCREENLAYOUT_SIZE_SMALL;
+            screenLayoutLong = false;
+            screenLayoutCompatNeeded = false;
+        } else {
+            // What size is this screen screen?
+            if (longSizeDp >= 960 && shortSizeDp >= 720) {
+                // 1.5xVGA or larger screens at medium density are the point
+                // at which we consider it to be an extra large screen.
+                screenLayoutSize = SCREENLAYOUT_SIZE_XLARGE;
+            } else if (longSizeDp >= 640 && shortSizeDp >= 480) {
+                // VGA or larger screens at medium density are the point
+                // at which we consider it to be a large screen.
+                screenLayoutSize = SCREENLAYOUT_SIZE_LARGE;
+            } else {
+                screenLayoutSize = SCREENLAYOUT_SIZE_NORMAL;
+            }
+
+            // If this screen is wider than normal HVGA, or taller
+            // than FWVGA, then for old apps we want to run in size
+            // compatibility mode.
+            if (shortSizeDp > 321 || longSizeDp > 570) {
+                screenLayoutCompatNeeded = true;
+            } else {
+                screenLayoutCompatNeeded = false;
+            }
+
+            // Is this a long screen?
+            if (((longSizeDp*3)/5) >= (shortSizeDp-1)) {
+                // Anything wider than WVGA (5:3) is considering to be long.
+                screenLayoutLong = true;
+            } else {
+                screenLayoutLong = false;
+            }
+        }
+
+        // Now reduce the last screenLayout to not be better than what we
+        // have found.
+        if (!screenLayoutLong) {
+            curLayout = (curLayout&~SCREENLAYOUT_LONG_MASK) | SCREENLAYOUT_LONG_NO;
+        }
+        if (screenLayoutCompatNeeded) {
+            curLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
+        }
+        int curSize = curLayout&SCREENLAYOUT_SIZE_MASK;
+        if (screenLayoutSize < curSize) {
+            curLayout = (curLayout&~SCREENLAYOUT_SIZE_MASK) | screenLayoutSize;
+        }
+        return curLayout;
+    }
+
     /**
      * Check if the Configuration's current {@link #screenLayout} is at
      * least the given size.
@@ -369,26 +464,40 @@
      */
     public int uiMode;
 
+    /**
+     * Default value for {@link #screenWidthDp} indicating that no width
+     * has been specified.
+     */
     public static final int SCREEN_WIDTH_DP_UNDEFINED = 0;
 
     /**
      * The current width of the available screen space, in dp units,
      * corresponding to
      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenWidthQualifier">screen
-     * width</a> resource qualifier.
+     * width</a> resource qualifier.  Set to
+     * {@link #SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
      */
     public int screenWidthDp;
 
+    /**
+     * Default value for {@link #screenHeightDp} indicating that no width
+     * has been specified.
+     */
     public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0;
 
     /**
      * The current height of the available screen space, in dp units,
      * corresponding to
      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenHeightQualifier">screen
-     * height</a> resource qualifier.
+     * height</a> resource qualifier.  Set to
+     * {@link #SCREEN_HEIGHT_DP_UNDEFINED} if no height is specified.
      */
     public int screenHeightDp;
 
+    /**
+     * Default value for {@link #smallestScreenWidthDp} indicating that no width
+     * has been specified.
+     */
     public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0;
 
     /**
@@ -397,10 +506,26 @@
      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">smallest
      * screen width</a> resource qualifier.
      * This is the smallest value of both screenWidthDp and screenHeightDp
-     * in both portrait and landscape.
+     * in both portrait and landscape.  Set to
+     * {@link #SMALLEST_SCREEN_WIDTH_DP_UNDEFINED} if no width is specified.
      */
     public int smallestScreenWidthDp;
 
+    /**
+     * Default value for {@link #densityDpi} indicating that no width
+     * has been specified.
+     */
+    public static final int DENSITY_DPI_UNDEFINED = 0;
+
+    /**
+     * The target screen density being rendered to,
+     * corresponding to
+     * <a href="{@docRoot}guide/topics/resources/providing-resources.html#DensityQualifier">density</a>
+     * resource qualifier.  Set to
+     * {@link #DENSITY_DPI_UNDEFINED} if no density is specified.
+     */
+    public int densityDpi;
+
     /** @hide Hack to get this information from WM to app running in compat mode. */
     public int compatScreenWidthDp;
     /** @hide Hack to get this information from WM to app running in compat mode. */
@@ -409,11 +534,6 @@
     public int compatSmallestScreenWidthDp;
 
     /**
-     * @hide The layout direction associated to the current Locale
-     */
-    public int layoutDirection;
-
-    /**
      * @hide Internal book-keeping.
      */
     public int seq;
@@ -439,7 +559,6 @@
         mnc = o.mnc;
         if (o.locale != null) {
             locale = (Locale) o.locale.clone();
-            layoutDirection = o.layoutDirection;
         }
         userSetLocale = o.userSetLocale;
         touchscreen = o.touchscreen;
@@ -454,6 +573,7 @@
         screenWidthDp = o.screenWidthDp;
         screenHeightDp = o.screenHeightDp;
         smallestScreenWidthDp = o.smallestScreenWidthDp;
+        densityDpi = o.densityDpi;
         compatScreenWidthDp = o.compatScreenWidthDp;
         compatScreenHeightDp = o.compatScreenHeightDp;
         compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
@@ -465,20 +585,31 @@
         sb.append("{");
         sb.append(fontScale);
         sb.append(" ");
-        sb.append(mcc);
-        sb.append("mcc");
-        sb.append(mnc);
-        sb.append("mnc");
+        if (mcc != 0) {
+            sb.append(mcc);
+            sb.append("mcc");
+        } else {
+            sb.append("?mcc");
+        }
+        if (mnc != 0) {
+            sb.append(mnc);
+            sb.append("mnc");
+        } else {
+            sb.append("?mnc");
+        }
         if (locale != null) {
             sb.append(" ");
             sb.append(locale);
         } else {
-            sb.append(" (no locale)");
+            sb.append(" ?locale");
         }
-        switch (layoutDirection) {
-            case View.LAYOUT_DIRECTION_LTR: /* ltr not interesting */ break;
-            case View.LAYOUT_DIRECTION_RTL: sb.append(" rtl"); break;
-            default: sb.append(" layoutDir="); sb.append(layoutDirection); break;
+        int layoutDir = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK);
+        switch (layoutDir) {
+            case SCREENLAYOUT_LAYOUTDIR_UNDEFINED: sb.append(" ?layoutDir"); break;
+            case SCREENLAYOUT_LAYOUTDIR_LTR: sb.append(" ldltr"); break;
+            case SCREENLAYOUT_LAYOUTDIR_RTL: sb.append(" ldrtl"); break;
+            default: sb.append(" layoutDir=");
+                sb.append(layoutDir >> SCREENLAYOUT_LAYOUTDIR_SHIFT); break;
         }
         if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
             sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp");
@@ -495,6 +626,11 @@
         } else {
             sb.append(" ?hdp");
         }
+        if (densityDpi != DENSITY_DPI_UNDEFINED) {
+            sb.append(" "); sb.append(densityDpi); sb.append("dpi");
+        } else {
+            sb.append(" ?density");
+        }
         switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) {
             case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break;
             case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break;
@@ -596,12 +732,12 @@
         navigation = NAVIGATION_UNDEFINED;
         navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
         orientation = ORIENTATION_UNDEFINED;
-        screenLayout = SCREENLAYOUT_SIZE_UNDEFINED;
+        screenLayout = SCREENLAYOUT_UNDEFINED;
         uiMode = UI_MODE_TYPE_UNDEFINED;
         screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
         screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
         smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
-        layoutDirection = View.LAYOUT_DIRECTION_LTR;
+        densityDpi = DENSITY_DPI_UNDEFINED;
         seq = 0;
     }
 
@@ -637,7 +773,11 @@
             changed |= ActivityInfo.CONFIG_LOCALE;
             locale = delta.locale != null
                     ? (Locale) delta.locale.clone() : null;
-            layoutDirection = LocaleUtil.getLayoutDirectionFromLocale(locale);
+            // If locale has changed, then layout direction is also changed ...
+            changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
+            // ... and we need to update the layout direction (represented by the first
+            // 2 most significant bits in screenLayout).
+            setLayoutDirection(locale);
         }
         if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0)))
         {
@@ -679,10 +819,17 @@
             changed |= ActivityInfo.CONFIG_ORIENTATION;
             orientation = delta.orientation;
         }
-        if (delta.screenLayout != SCREENLAYOUT_SIZE_UNDEFINED
-                && screenLayout != delta.screenLayout) {
+        if (getScreenLayoutNoDirection(delta.screenLayout) !=
+                    (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED)
+                && (getScreenLayoutNoDirection(screenLayout) !=
+                    getScreenLayoutNoDirection(delta.screenLayout))) {
             changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
-            screenLayout = delta.screenLayout;
+            // We need to preserve the previous layout dir bits if they were defined
+            if ((delta.screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == 0) {
+                screenLayout = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK)|delta.screenLayout;
+            } else {
+                screenLayout = delta.screenLayout;
+            }
         }
         if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
                 && uiMode != delta.uiMode) {
@@ -707,8 +854,13 @@
             screenHeightDp = delta.screenHeightDp;
         }
         if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
+            changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
             smallestScreenWidthDp = delta.smallestScreenWidthDp;
         }
+        if (delta.densityDpi != DENSITY_DPI_UNDEFINED) {
+            changed |= ActivityInfo.CONFIG_DENSITY;
+            densityDpi = delta.densityDpi;
+        }
         if (delta.compatScreenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
             compatScreenWidthDp = delta.compatScreenWidthDp;
         }
@@ -718,7 +870,6 @@
         if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
             compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp;
         }
-        
         if (delta.seq != 0) {
             seq = delta.seq;
         }
@@ -754,6 +905,8 @@
      * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or
      * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
      * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}.
+     * {@link android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION
+     * PackageManager.ActivityInfo.CONFIG_LAYOUT_DIRECTION}.
      */
     public int diff(Configuration delta) {
         int changed = 0;
@@ -769,6 +922,7 @@
         if (delta.locale != null
                 && (locale == null || !locale.equals(delta.locale))) {
             changed |= ActivityInfo.CONFIG_LOCALE;
+            changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
         }
         if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
                 && touchscreen != delta.touchscreen) {
@@ -798,8 +952,10 @@
                 && orientation != delta.orientation) {
             changed |= ActivityInfo.CONFIG_ORIENTATION;
         }
-        if (delta.screenLayout != SCREENLAYOUT_SIZE_UNDEFINED
-                && screenLayout != delta.screenLayout) {
+        if (getScreenLayoutNoDirection(delta.screenLayout) !=
+                    (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED)
+                && getScreenLayoutNoDirection(screenLayout) !=
+                    getScreenLayoutNoDirection(delta.screenLayout)) {
             changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
         }
         if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
@@ -818,7 +974,11 @@
                 && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
             changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
         }
-        
+        if (delta.densityDpi != DENSITY_DPI_UNDEFINED
+                && densityDpi != delta.densityDpi) {
+            changed |= ActivityInfo.CONFIG_DENSITY;
+        }
+
         return changed;
     }
 
@@ -902,10 +1062,10 @@
         dest.writeInt(screenWidthDp);
         dest.writeInt(screenHeightDp);
         dest.writeInt(smallestScreenWidthDp);
+        dest.writeInt(densityDpi);
         dest.writeInt(compatScreenWidthDp);
         dest.writeInt(compatScreenHeightDp);
         dest.writeInt(compatSmallestScreenWidthDp);
-        dest.writeInt(layoutDirection);
         dest.writeInt(seq);
     }
 
@@ -930,10 +1090,10 @@
         screenWidthDp = source.readInt();
         screenHeightDp = source.readInt();
         smallestScreenWidthDp = source.readInt();
+        densityDpi = source.readInt();
         compatScreenWidthDp = source.readInt();
         compatScreenHeightDp = source.readInt();
         compatSmallestScreenWidthDp = source.readInt();
-        layoutDirection = source.readInt();
         seq = source.readInt();
     }
     
@@ -1000,6 +1160,8 @@
         n = this.screenHeightDp - that.screenHeightDp;
         if (n != 0) return n;
         n = this.smallestScreenWidthDp - that.smallestScreenWidthDp;
+        if (n != 0) return n;
+        n = this.densityDpi - that.densityDpi;
         //if (n != 0) return n;
         return n;
     }
@@ -1036,6 +1198,53 @@
         result = 31 * result + screenWidthDp;
         result = 31 * result + screenHeightDp;
         result = 31 * result + smallestScreenWidthDp;
+        result = 31 * result + densityDpi;
         return result;
     }
+
+    /**
+     * Set the locale. This is the preferred way for setting up the locale (instead of using the
+     * direct accessor). This will also set the userLocale and layout direction according to
+     * the locale.
+     *
+     * @param loc The locale. Can be null.
+     */
+    public void setLocale(Locale loc) {
+        locale = loc;
+        userSetLocale = true;
+        setLayoutDirection(locale);
+    }
+
+    /**
+     * Return the layout direction. Will be either {@link View#LAYOUT_DIRECTION_LTR} or
+     * {@link View#LAYOUT_DIRECTION_RTL}.
+     *
+     * @return the layout direction
+     */
+    public int getLayoutDirection() {
+        // We need to substract one here as the configuration values are using "0" as undefined thus
+        // having LRT set to "1" and RTL set to "2"
+        return ((screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) >> SCREENLAYOUT_LAYOUTDIR_SHIFT) - 1;
+    }
+
+    /**
+     * Set the layout direction from the Locale.
+     *
+     * @param locale The Locale. If null will set the layout direction to
+     * {@link View#LAYOUT_DIRECTION_LTR}. If not null will set it to the layout direction
+     * corresponding to the Locale.
+     *
+     * @see {@link View#LAYOUT_DIRECTION_LTR} and {@link View#LAYOUT_DIRECTION_RTL}
+     */
+    public void setLayoutDirection(Locale locale) {
+        // There is a "1" difference between the configuration values for
+        // layout direction and View constants for layout direction, just add "1".
+        final int layoutDirection = 1 + TextUtils.getLayoutDirectionFromLocale(locale);
+        screenLayout = (screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK)|
+                (layoutDirection << SCREENLAYOUT_LAYOUTDIR_SHIFT);
+    }
+
+    private static int getScreenLayoutNoDirection(int screenLayout) {
+        return screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK;
+    }
 }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index ab2fe1c..b316f23 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -89,7 +89,8 @@
             = new LongSparseArray<ColorStateList>();
     private static final LongSparseArray<Drawable.ConstantState> sPreloadedColorDrawables
             = new LongSparseArray<Drawable.ConstantState>();
-    private static boolean mPreloaded;
+    private static boolean sPreloaded;
+    private static int sPreloadedDensity;
 
     /*package*/ final TypedValue mTmpValue = new TypedValue();
     /*package*/ final Configuration mTmpConfig = new Configuration();
@@ -693,9 +694,9 @@
              */
             if (value.density > 0 && value.density != TypedValue.DENSITY_NONE) {
                 if (value.density == density) {
-                    value.density = DisplayMetrics.DENSITY_DEVICE;
+                    value.density = mMetrics.densityDpi;
                 } else {
-                    value.density = (value.density * DisplayMetrics.DENSITY_DEVICE) / density;
+                    value.density = (value.density * mMetrics.densityDpi) / density;
                 }
             }
 
@@ -1434,17 +1435,27 @@
             int configChanges = 0xfffffff;
             if (config != null) {
                 mTmpConfig.setTo(config);
+                int density = config.densityDpi;
+                if (density == Configuration.DENSITY_DPI_UNDEFINED) {
+                    density = mMetrics.noncompatDensityDpi;
+                }
                 if (mCompatibilityInfo != null) {
-                    mCompatibilityInfo.applyToConfiguration(mTmpConfig);
+                    mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
                 }
                 if (mTmpConfig.locale == null) {
                     mTmpConfig.locale = Locale.getDefault();
+                    mTmpConfig.setLayoutDirection(mTmpConfig.locale);
                 }
                 configChanges = mConfiguration.updateFrom(mTmpConfig);
                 configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
             }
             if (mConfiguration.locale == null) {
                 mConfiguration.locale = Locale.getDefault();
+                mConfiguration.setLayoutDirection(mConfiguration.locale);
+            }
+            if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
+                mMetrics.densityDpi = mConfiguration.densityDpi;
+                mMetrics.density = mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
             }
             mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
 
@@ -1474,7 +1485,7 @@
             mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
                     locale, mConfiguration.orientation,
                     mConfiguration.touchscreen,
-                    (int)(mMetrics.density*160), mConfiguration.keyboard,
+                    mConfiguration.densityDpi, mConfiguration.keyboard,
                     keyboardHidden, mConfiguration.navigation, width, height,
                     mConfiguration.smallestScreenWidthDp,
                     mConfiguration.screenWidthDp, mConfiguration.screenHeightDp,
@@ -1836,11 +1847,14 @@
      */
     public final void startPreloading() {
         synchronized (mSync) {
-            if (mPreloaded) {
+            if (sPreloaded) {
                 throw new IllegalStateException("Resources already preloaded");
             }
-            mPreloaded = true;
+            sPreloaded = true;
             mPreloading = true;
+            sPreloadedDensity = DisplayMetrics.DENSITY_DEVICE;
+            mConfiguration.densityDpi = sPreloadedDensity;
+            updateConfiguration(null, null);
         }
     }
     
@@ -1854,7 +1868,24 @@
             flushLayoutCache();
         }
     }
-    
+
+    private boolean verifyPreloadConfig(TypedValue value, String name) {
+        if ((value.changingConfigurations&~(ActivityInfo.CONFIG_FONT_SCALE
+                | ActivityInfo.CONFIG_DENSITY)) != 0) {
+            String resName;
+            try {
+                resName = getResourceName(value.resourceId);
+            } catch (NotFoundException e) {
+                resName = "?";
+            }
+            Log.w(TAG, "Preloaded " + name + " resource #0x"
+                    + Integer.toHexString(value.resourceId)
+                    + " (" + resName + ") that varies with configuration!!");
+            return false;
+        }
+        return true;
+    }
+
     /*package*/ Drawable loadDrawable(TypedValue value, int id)
             throws NotFoundException {
 
@@ -1866,20 +1897,24 @@
             }
         }
 
-        final long key = (((long) value.assetCookie) << 32) | value.data;
         boolean isColorDrawable = false;
         if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
                 value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
             isColorDrawable = true;
         }
+        final long key = isColorDrawable ? value.data :
+                (((long) value.assetCookie) << 32) | value.data;
+
         Drawable dr = getCachedDrawable(isColorDrawable ? mColorDrawableCache : mDrawableCache, key);
 
         if (dr != null) {
             return dr;
         }
 
-        Drawable.ConstantState cs = isColorDrawable ?
-                sPreloadedColorDrawables.get(key) : sPreloadedDrawables.get(key);
+        Drawable.ConstantState cs = isColorDrawable
+                ? sPreloadedColorDrawables.get(key)
+                : (sPreloadedDensity == mConfiguration.densityDpi
+                        ? sPreloadedDrawables.get(key) : null);
         if (cs != null) {
             dr = cs.newDrawable(this);
         } else {
@@ -1947,10 +1982,12 @@
             cs = dr.getConstantState();
             if (cs != null) {
                 if (mPreloading) {
-                    if (isColorDrawable) {
-                        sPreloadedColorDrawables.put(key, cs);
-                    } else {
-                        sPreloadedDrawables.put(key, cs);
+                    if (verifyPreloadConfig(value, "drawable")) {
+                        if (isColorDrawable) {
+                            sPreloadedColorDrawables.put(key, cs);
+                        } else {
+                            sPreloadedDrawables.put(key, cs);
+                        }
                     }
                 } else {
                     synchronized (mTmpValue) {
@@ -2015,7 +2052,9 @@
 
             csl = ColorStateList.valueOf(value.data);
             if (mPreloading) {
-                sPreloadedColorStateLists.put(key, csl);
+                if (verifyPreloadConfig(value, "color")) {
+                    sPreloadedColorStateLists.put(key, csl);
+                }
             }
 
             return csl;
@@ -2059,7 +2098,9 @@
 
         if (csl != null) {
             if (mPreloading) {
-                sPreloadedColorStateLists.put(key, csl);
+                if (verifyPreloadConfig(value, "color")) {
+                    sPreloadedColorStateLists.put(key, csl);
+                }
             } else {
                 synchronized (mTmpValue) {
                     //Log.i(TAG, "Saving cached color state list @ #" +
diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java
index e7ff92d..300b4d1 100644
--- a/core/java/android/database/AbstractCursor.java
+++ b/core/java/android/database/AbstractCursor.java
@@ -19,6 +19,7 @@
 import android.content.ContentResolver;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.util.Log;
 
 import java.lang.ref.WeakReference;
@@ -350,6 +351,11 @@
      * specific row URI, or a base URI for a whole class of content.
      */
     public void setNotificationUri(ContentResolver cr, Uri notifyUri) {
+        setNotificationUri(cr, notifyUri, UserHandle.myUserId());
+    }
+
+    /** @hide - set the notification uri but with an observer for a particular user's view */
+    public void setNotificationUri(ContentResolver cr, Uri notifyUri, int userHandle) {
         synchronized (mSelfObserverLock) {
             mNotifyUri = notifyUri;
             mContentResolver = cr;
@@ -357,7 +363,7 @@
                 mContentResolver.unregisterContentObserver(mSelfObserver);
             }
             mSelfObserver = new SelfContentObserver(this);
-            mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);
+            mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver, userHandle);
             mSelfObserverRegistered = true;
         }
     }
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index a6af5c2..1fc1226 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -50,9 +50,6 @@
     private static final String TAG = "DatabaseUtils";
 
     private static final boolean DEBUG = false;
-    private static final boolean LOCAL_LOGV = false;
-
-    private static final String[] countProjection = new String[]{"count(*)"};
 
     /** One of the values returned by {@link #getSqlStatementType(String)}. */
     public static final int STATEMENT_SELECT = 1;
@@ -963,10 +960,15 @@
     }
 
     /**
-     * This class allows users to do multiple inserts into a table but
-     * compile the SQL insert statement only once, which may increase
-     * performance.
+     * This class allows users to do multiple inserts into a table using
+     * the same statement.
+     * <p>
+     * This class is not thread-safe.
+     * </p>
+     *
+     * @deprecated Use {@link SQLiteStatement} instead.
      */
+    @Deprecated
     public static class InsertHelper {
         private final SQLiteDatabase mDb;
         private final String mTableName;
@@ -983,6 +985,13 @@
          * table_info(...)" command that we depend on.
          */
         public static final int TABLE_INFO_PRAGMA_COLUMNNAME_INDEX = 1;
+
+        /**
+         * This field was accidentally exposed in earlier versions of the platform
+         * so we can hide it but we can't remove it.
+         *
+         * @hide
+         */
         public static final int TABLE_INFO_PRAGMA_DEFAULT_INDEX = 4;
 
         /**
@@ -1036,7 +1045,7 @@
             sb.append(sbv);
 
             mInsertSQL = sb.toString();
-            if (LOCAL_LOGV) Log.v(TAG, "insert statement is " + mInsertSQL);
+            if (DEBUG) Log.v(TAG, "insert statement is " + mInsertSQL);
         }
 
         private SQLiteStatement getStatement(boolean allowReplace) throws SQLException {
@@ -1069,24 +1078,35 @@
          * @return the row ID of the newly inserted row, or -1 if an
          * error occurred
          */
-        private synchronized long insertInternal(ContentValues values, boolean allowReplace) {
+        private long insertInternal(ContentValues values, boolean allowReplace) {
+            // Start a transaction even though we don't really need one.
+            // This is to help maintain compatibility with applications that
+            // access InsertHelper from multiple threads even though they never should have.
+            // The original code used to lock the InsertHelper itself which was prone
+            // to deadlocks.  Starting a transaction achieves the same mutual exclusion
+            // effect as grabbing a lock but without the potential for deadlocks.
+            mDb.beginTransactionNonExclusive();
             try {
                 SQLiteStatement stmt = getStatement(allowReplace);
                 stmt.clearBindings();
-                if (LOCAL_LOGV) Log.v(TAG, "--- inserting in table " + mTableName);
+                if (DEBUG) Log.v(TAG, "--- inserting in table " + mTableName);
                 for (Map.Entry<String, Object> e: values.valueSet()) {
                     final String key = e.getKey();
                     int i = getColumnIndex(key);
                     DatabaseUtils.bindObjectToProgram(stmt, i, e.getValue());
-                    if (LOCAL_LOGV) {
+                    if (DEBUG) {
                         Log.v(TAG, "binding " + e.getValue() + " to column " +
                               i + " (" + key + ")");
                     }
                 }
-                return stmt.executeInsert();
+                long result = stmt.executeInsert();
+                mDb.setTransactionSuccessful();
+                return result;
             } catch (SQLException e) {
                 Log.e(TAG, "Error inserting " + values + " into table  " + mTableName, e);
                 return -1;
+            } finally {
+                mDb.endTransaction();
             }
         }
 
@@ -1223,7 +1243,7 @@
                         + "execute");
             }
             try {
-                if (LOCAL_LOGV) Log.v(TAG, "--- doing insert or replace in table " + mTableName);
+                if (DEBUG) Log.v(TAG, "--- doing insert or replace in table " + mTableName);
                 return mPreparedStatement.executeInsert();
             } catch (SQLException e) {
                 Log.e(TAG, "Error executing InsertHelper with table " + mTableName, e);
diff --git a/core/java/android/ddm/DdmHandleAppName.java b/core/java/android/ddm/DdmHandleAppName.java
index 78dd23e..7e39e47 100644
--- a/core/java/android/ddm/DdmHandleAppName.java
+++ b/core/java/android/ddm/DdmHandleAppName.java
@@ -69,14 +69,14 @@
      * before or after DDMS connects.  For the latter we need to send up
      * an APNM message.
      */
-    public static void setAppName(String name) {
+    public static void setAppName(String name, int userId) {
         if (name == null || name.length() == 0)
             return;
 
         mAppName = name;
 
         // if DDMS is already connected, send the app name up
-        sendAPNM(name);
+        sendAPNM(name, userId);
     }
 
     public static String getAppName() {
@@ -86,14 +86,18 @@
     /*
      * Send an APNM (APplication NaMe) chunk.
      */
-    private static void sendAPNM(String appName) {
+    private static void sendAPNM(String appName, int userId) {
         if (false)
             Log.v("ddm", "Sending app name");
 
-        ByteBuffer out = ByteBuffer.allocate(4 + appName.length()*2);
+        ByteBuffer out = ByteBuffer.allocate(
+                            4 /* appName's length */
+                            + appName.length()*2 /* appName */
+                            + 4 /* userId */);
         out.order(ChunkHandler.CHUNK_ORDER);
         out.putInt(appName.length());
         putString(out, appName);
+        out.putInt(userId);
 
         Chunk chunk = new Chunk(CHUNK_APNM, out);
         DdmServer.sendChunk(chunk);
diff --git a/core/java/android/ddm/DdmHandleHello.java b/core/java/android/ddm/DdmHandleHello.java
index 5088d22..e99fa92 100644
--- a/core/java/android/ddm/DdmHandleHello.java
+++ b/core/java/android/ddm/DdmHandleHello.java
@@ -21,6 +21,7 @@
 import org.apache.harmony.dalvik.ddmc.DdmServer;
 import android.util.Log;
 import android.os.Debug;
+import android.os.UserHandle;
 
 import java.nio.ByteBuffer;
 
@@ -119,7 +120,7 @@
         //    appName = "unknown";
         String appName = DdmHandleAppName.getAppName();
 
-        ByteBuffer out = ByteBuffer.allocate(16
+        ByteBuffer out = ByteBuffer.allocate(20
                             + vmIdent.length()*2 + appName.length()*2);
         out.order(ChunkHandler.CHUNK_ORDER);
         out.putInt(DdmServer.CLIENT_PROTOCOL_VERSION);
@@ -128,6 +129,7 @@
         out.putInt(appName.length());
         putString(out, vmIdent);
         putString(out, appName);
+        out.putInt(UserHandle.myUserId());
 
         Chunk reply = new Chunk(CHUNK_HELO, out);
 
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 829620b..a300776 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -18,13 +18,18 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.content.Context;
 import android.graphics.ImageFormat;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
+import android.media.IAudioService;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.util.Log;
 import android.text.TextUtils;
 import android.view.Surface;
@@ -192,7 +197,21 @@
      * Returns the information about a particular camera.
      * If {@link #getNumberOfCameras()} returns N, the valid id is 0 to N-1.
      */
-    public native static void getCameraInfo(int cameraId, CameraInfo cameraInfo);
+    public static void getCameraInfo(int cameraId, CameraInfo cameraInfo) {
+        _getCameraInfo(cameraId, cameraInfo);
+        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
+        IAudioService audioService = IAudioService.Stub.asInterface(b);
+        try {
+            if (audioService.isCameraSoundForced()) {
+                // Only set this when sound is forced; otherwise let native code
+                // decide.
+                cameraInfo.canDisableShutterSound = false;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Audio service is unavailable for queries");
+        }
+    }
+    private native static void _getCameraInfo(int cameraId, CameraInfo cameraInfo);
 
     /**
      * Information about a camera
@@ -233,6 +252,21 @@
          * @see Parameters#setJpegThumbnailSize(int, int)
          */
         public int orientation;
+
+        /**
+         * <p>Whether the shutter sound can be disabled.</p>
+         *
+         * <p>On some devices, the camera shutter sound cannot be turned off
+         * through {@link #enableShutterSound enableShutterSound}. This field
+         * can be used to determine whether a call to disable the shutter sound
+         * will succeed.</p>
+         *
+         * <p>If this field is set to true, then a call of
+         * {@code enableShutterSound(false)} will be successful. If set to
+         * false, then that call will fail, and the shutter sound will be played
+         * when {@link Camera#takePicture takePicture} is called.</p>
+         */
+        public boolean canDisableShutterSound;
     };
 
     /**
@@ -1146,6 +1180,46 @@
     public native final void setDisplayOrientation(int degrees);
 
     /**
+     * <p>Enable or disable the default shutter sound when taking a picture.</p>
+     *
+     * <p>By default, the camera plays the system-defined camera shutter sound
+     * when {@link #takePicture} is called. Using this method, the shutter sound
+     * can be disabled. It is strongly recommended that an alternative shutter
+     * sound is played in the {@link ShutterCallback} when the system shutter
+     * sound is disabled.</p>
+     *
+     * <p>Note that devices may not always allow disabling the camera shutter
+     * sound. If the shutter sound state cannot be set to the desired value,
+     * this method will return false. {@link CameraInfo#canDisableShutterSound}
+     * can be used to determine whether the device will allow the shutter sound
+     * to be disabled.</p>
+     *
+     * @param enabled whether the camera should play the system shutter sound
+     *                when {@link #takePicture takePicture} is called.
+     * @return {@code true} if the shutter sound state was successfully
+     *         changed. {@code false} if the shutter sound state could not be
+     *         changed. {@code true} is also returned if shutter sound playback
+     *         is already set to the requested state.
+     * @see #takePicture
+     * @see CameraInfo#canDisableShutterSound
+     * @see ShutterCallback
+     */
+    public final boolean enableShutterSound(boolean enabled) {
+        if (!enabled) {
+            IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
+            IAudioService audioService = IAudioService.Stub.asInterface(b);
+            try {
+                if (audioService.isCameraSoundForced()) return false;
+            } catch (RemoteException e) {
+                Log.e(TAG, "Audio service is unavailable for queries");
+            }
+        }
+        return _enableShutterSound(enabled);
+    }
+
+    private native final boolean _enableShutterSound(boolean enabled);
+
+    /**
      * Callback interface for zoom changes during a smooth zoom operation.
      *
      * @see #setZoomChangeListener(OnZoomChangeListener)
@@ -1308,8 +1382,14 @@
         public Rect rect;
 
         /**
-         * The confidence level for the detection of the face. The range is 1 to 100. 100 is the
-         * highest confidence.
+         * <p>The confidence level for the detection of the face. The range is 1 to
+         * 100. 100 is the highest confidence.</p>
+         *
+         * <p>Depending on the device, even very low-confidence faces may be
+         * listed, so applications should filter out faces with low confidence,
+         * depending on the use case. For a typical point-and-shoot camera
+         * application that wishes to display rectangles around detected faces,
+         * filtering out faces with confidence less than 50 is recommended.</p>
          *
          * @see #startFaceDetection()
          */
@@ -1782,6 +1862,14 @@
         public static final String SCENE_MODE_BARCODE = "barcode";
 
         /**
+         * Capture a scene using high dynamic range imaging techniques. The
+         * camera will return an image that has an extended dynamic range
+         * compared to a regular capture. Capturing such an image may take
+         * longer than a regular capture.
+         */
+        public static final String SCENE_MODE_HDR = "hdr";
+
+        /**
          * Auto-focus mode. Applications should call {@link
          * #autoFocus(AutoFocusCallback)} to start the focus in this mode.
          */
@@ -2784,6 +2872,7 @@
          * @see #SCENE_MODE_SPORTS
          * @see #SCENE_MODE_PARTY
          * @see #SCENE_MODE_CANDLELIGHT
+         * @see #SCENE_MODE_BARCODE
          */
         public String getSceneMode() {
             return get(KEY_SCENE_MODE);
@@ -3406,25 +3495,29 @@
         }
 
         /**
-         * Returns true if video snapshot is supported. That is, applications
+         * <p>Returns true if video snapshot is supported. That is, applications
          * can call {@link #takePicture(Camera.ShutterCallback,
-         * Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback)}
-         * during recording. Applications do not need to call {@link
-         * #startPreview()} after taking a picture. The preview will be still
-         * active. Other than that, taking a picture during recording is
-         * identical to taking a picture normally. All settings and methods
-         * related to takePicture work identically. Ex: {@link
-         * #getPictureSize()}, {@link #getSupportedPictureSizes()}, {@link
-         * #setJpegQuality(int)}, {@link #setRotation(int)}, and etc. The
-         * picture will have an EXIF header. {@link #FLASH_MODE_AUTO} and {@link
-         * #FLASH_MODE_ON} also still work, but the video will record the flash.
+         * Camera.PictureCallback, Camera.PictureCallback,
+         * Camera.PictureCallback)} during recording. Applications do not need
+         * to call {@link #startPreview()} after taking a picture. The preview
+         * will be still active. Other than that, taking a picture during
+         * recording is identical to taking a picture normally. All settings and
+         * methods related to takePicture work identically. Ex:
+         * {@link #getPictureSize()}, {@link #getSupportedPictureSizes()},
+         * {@link #setJpegQuality(int)}, {@link #setRotation(int)}, and etc. The
+         * picture will have an EXIF header. {@link #FLASH_MODE_AUTO} and
+         * {@link #FLASH_MODE_ON} also still work, but the video will record the
+         * flash.</p>
          *
-         * Applications can set shutter callback as null to avoid the shutter
+         * <p>Applications can set shutter callback as null to avoid the shutter
          * sound. It is also recommended to set raw picture and post view
-         * callbacks to null to avoid the interrupt of preview display.
+         * callbacks to null to avoid the interrupt of preview display.</p>
          *
-         * Field-of-view of the recorded video may be different from that of the
-         * captured pictures.
+         * <p>Field-of-view of the recorded video may be different from that of the
+         * captured pictures. The maximum size of a video snapshot may be
+         * smaller than that for regular still captures. If the current picture
+         * size is set higher than can be supported by video snapshot, the
+         * picture will be captured at the maximum supported size instead.</p>
          *
          * @return true if video snapshot is supported.
          */
diff --git a/core/java/android/hardware/LegacySensorManager.java b/core/java/android/hardware/LegacySensorManager.java
index 62c194f..f959093 100644
--- a/core/java/android/hardware/LegacySensorManager.java
+++ b/core/java/android/hardware/LegacySensorManager.java
@@ -371,7 +371,7 @@
         private static final float PREDICTION_RATIO = 1.0f/3.0f;
         private static final float PREDICTION_TIME = (SENSORS_RATE_MS*COUNT/1000.0f)*PREDICTION_RATIO;
         private float mV[] = new float[COUNT*2];
-        private float mT[] = new float[COUNT*2];
+        private long mT[] = new long[COUNT*2];
         private int mIndex;
 
         public LmsFilter() {
@@ -381,7 +381,6 @@
         public float filter(long time, float in) {
             float v = in;
             final float ns = 1.0f / 1000000000.0f;
-            final float t = time*ns;
             float v1 = mV[mIndex];
             if ((v-v1) > 180) {
                 v -= 360;
@@ -396,9 +395,9 @@
             if (mIndex >= COUNT*2)
                 mIndex = COUNT;
             mV[mIndex] = v;
-            mT[mIndex] = t;
+            mT[mIndex] = time;
             mV[mIndex-COUNT] = v;
-            mT[mIndex-COUNT] = t;
+            mT[mIndex-COUNT] = time;
 
             float A, B, C, D, E;
             float a, b;
@@ -408,8 +407,8 @@
             for (i=0 ; i<COUNT-1 ; i++) {
                 final int j = mIndex - 1 - i;
                 final float Z = mV[j];
-                final float T = 0.5f*(mT[j] + mT[j+1]) - t;
-                float dT = mT[j] - mT[j+1];
+                final float T = (mT[j]/2 + mT[j+1]/2 - time)*ns;
+                float dT = (mT[j] - mT[j+1])*ns;
                 dT *= dT;
                 A += Z*dT;
                 B += T*(T*dT);
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 3c70dc6..e0c9d2c 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -26,7 +26,7 @@
  * @see SensorEvent
  *
  */
-public class Sensor {
+public final class Sensor {
 
     /**
      * A constant describing an accelerometer sensor type. See
@@ -202,4 +202,11 @@
         mMaxRange = max;
         mResolution = res;
     }
+
+    @Override
+    public String toString() {
+        return "{Sensor name=\"" + mName + "\", vendor=\"" + mVendor + "\", version=" + mVersion
+                + ", type=" + mType + ", maxRange=" + mMaxRange + ", resolution=" + mResolution
+                + ", power=" + mPower + ", minDelay=" + mMinDelay + "}";
+    }
 }
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
new file mode 100644
index 0000000..0a7a2e7
--- /dev/null
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -0,0 +1,304 @@
+/*
+ * 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.hardware.display;
+
+import android.content.Context;
+import android.os.Handler;
+import android.util.SparseArray;
+import android.view.Display;
+
+import java.util.ArrayList;
+
+/**
+ * Manages the properties of attached displays.
+ * <p>
+ * Get an instance of this class by calling
+ * {@link android.content.Context#getSystemService(java.lang.String)
+ * Context.getSystemService()} with the argument
+ * {@link android.content.Context#DISPLAY_SERVICE}.
+ * </p>
+ */
+public final class DisplayManager {
+    private static final String TAG = "DisplayManager";
+    private static final boolean DEBUG = false;
+
+    private final Context mContext;
+    private final DisplayManagerGlobal mGlobal;
+
+    private final Object mLock = new Object();
+    private final SparseArray<Display> mDisplays = new SparseArray<Display>();
+
+    private final ArrayList<Display> mTempDisplays = new ArrayList<Display>();
+
+    /**
+     * Broadcast receiver that indicates when the Wifi display status changes.
+     * <p>
+     * The status is provided as a {@link WifiDisplayStatus} object in the
+     * {@link #EXTRA_WIFI_DISPLAY_STATUS} extra.
+     * </p><p>
+     * This broadcast is only sent to registered receivers and can only be sent by the system.
+     * </p>
+     * @hide
+     */
+    public static final String ACTION_WIFI_DISPLAY_STATUS_CHANGED =
+            "android.hardware.display.action.WIFI_DISPLAY_STATUS_CHANGED";
+
+    /**
+     * Contains a {@link WifiDisplayStatus} object.
+     * @hide
+     */
+    public static final String EXTRA_WIFI_DISPLAY_STATUS =
+            "android.hardware.display.extra.WIFI_DISPLAY_STATUS";
+
+    /**
+     * Display category: Presentation displays.
+     * <p>
+     * This category can be used to identify secondary displays that are suitable for
+     * use as presentation displays.
+     * </p>
+     *
+     * @see android.app.Presentation for information about presenting content
+     * on secondary displays.
+     * @see #getDisplays(String)
+     */
+    public static final String DISPLAY_CATEGORY_PRESENTATION =
+            "android.hardware.display.category.PRESENTATION";
+
+    /** @hide */
+    public DisplayManager(Context context) {
+        mContext = context;
+        mGlobal = DisplayManagerGlobal.getInstance();
+    }
+
+    /**
+     * Gets information about a logical display.
+     *
+     * The display metrics may be adjusted to provide compatibility
+     * for legacy applications.
+     *
+     * @param displayId The logical display id.
+     * @return The display object, or null if there is no valid display with the given id.
+     */
+    public Display getDisplay(int displayId) {
+        synchronized (mLock) {
+            return getOrCreateDisplayLocked(displayId, false /*assumeValid*/);
+        }
+    }
+
+    /**
+     * Gets all currently valid logical displays.
+     *
+     * @return An array containing all displays.
+     */
+    public Display[] getDisplays() {
+        return getDisplays(null);
+    }
+
+    /**
+     * Gets all currently valid logical displays of the specified category.
+     * <p>
+     * When there are multiple displays in a category the returned displays are sorted
+     * of preference.  For example, if the requested category is
+     * {@link #DISPLAY_CATEGORY_PRESENTATION} and there are multiple presentation displays
+     * then the displays are sorted so that the first display in the returned array
+     * is the most preferred presentation display.  The application may simply
+     * use the first display or allow the user to choose.
+     * </p>
+     *
+     * @param category The requested display category or null to return all displays.
+     * @return An array containing all displays sorted by order of preference.
+     *
+     * @see #DISPLAY_CATEGORY_PRESENTATION
+     */
+    public Display[] getDisplays(String category) {
+        final int[] displayIds = mGlobal.getDisplayIds();
+        synchronized (mLock) {
+            try {
+                if (category == null) {
+                    addMatchingDisplaysLocked(mTempDisplays, displayIds, -1);
+                } else if (category.equals(DISPLAY_CATEGORY_PRESENTATION)) {
+                    addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI);
+                    addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_HDMI);
+                    addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_OVERLAY);
+                }
+                return mTempDisplays.toArray(new Display[mTempDisplays.size()]);
+            } finally {
+                mTempDisplays.clear();
+            }
+        }
+    }
+
+    private void addMatchingDisplaysLocked(
+            ArrayList<Display> displays, int[] displayIds, int matchType) {
+        for (int i = 0; i < displayIds.length; i++) {
+            Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/);
+            if (display != null
+                    && (matchType < 0 || display.getType() == matchType)) {
+                displays.add(display);
+            }
+        }
+    }
+
+    private Display getOrCreateDisplayLocked(int displayId, boolean assumeValid) {
+        Display display = mDisplays.get(displayId);
+        if (display == null) {
+            display = mGlobal.getCompatibleDisplay(displayId,
+                    mContext.getCompatibilityInfo(displayId));
+            if (display != null) {
+                mDisplays.put(displayId, display);
+            }
+        } else if (!assumeValid && !display.isValid()) {
+            display = null;
+        }
+        return display;
+    }
+
+    /**
+     * Registers an display listener to receive notifications about when
+     * displays are added, removed or changed.
+     *
+     * @param listener The listener to register.
+     * @param handler The handler on which the listener should be invoked, or null
+     * if the listener should be invoked on the calling thread's looper.
+     *
+     * @see #unregisterDisplayListener
+     */
+    public void registerDisplayListener(DisplayListener listener, Handler handler) {
+        mGlobal.registerDisplayListener(listener, handler);
+    }
+
+    /**
+     * Unregisters an input device listener.
+     *
+     * @param listener The listener to unregister.
+     *
+     * @see #registerDisplayListener
+     */
+    public void unregisterDisplayListener(DisplayListener listener) {
+        mGlobal.unregisterDisplayListener(listener);
+    }
+
+    /**
+     * Initiates a fresh scan of availble Wifi displays.
+     * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
+     * @hide
+     */
+    public void scanWifiDisplays() {
+        mGlobal.scanWifiDisplays();
+    }
+
+    /**
+     * Connects to a Wifi display.
+     * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
+     * <p>
+     * Automatically remembers the display after a successful connection, if not
+     * already remembered.
+     * </p><p>
+     * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY} to connect
+     * to unknown displays.  No permissions are required to connect to already known displays.
+     * </p>
+     *
+     * @param deviceAddress The MAC address of the device to which we should connect.
+     * @hide
+     */
+    public void connectWifiDisplay(String deviceAddress) {
+        mGlobal.connectWifiDisplay(deviceAddress);
+    }
+
+    /**
+     * Disconnects from the current Wifi display.
+     * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
+     * @hide
+     */
+    public void disconnectWifiDisplay() {
+        mGlobal.disconnectWifiDisplay();
+    }
+
+    /**
+     * Renames a Wifi display.
+     * <p>
+     * The display must already be remembered for this call to succeed.  In other words,
+     * we must already have successfully connected to the display at least once and then
+     * not forgotten it.
+     * </p><p>
+     * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}.
+     * </p>
+     *
+     * @param deviceAddress The MAC address of the device to rename.
+     * @param alias The alias name by which to remember the device, or null
+     * or empty if no alias should be used.
+     * @hide
+     */
+    public void renameWifiDisplay(String deviceAddress, String alias) {
+        mGlobal.renameWifiDisplay(deviceAddress, alias);
+    }
+
+    /**
+     * Forgets a previously remembered Wifi display.
+     * <p>
+     * Automatically disconnects from the display if currently connected to it.
+     * </p><p>
+     * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}.
+     * </p>
+     *
+     * @param deviceAddress The MAC address of the device to forget.
+     * @hide
+     */
+    public void forgetWifiDisplay(String deviceAddress) {
+        mGlobal.forgetWifiDisplay(deviceAddress);
+    }
+
+    /**
+     * Gets the current Wifi display status.
+     * Watch for changes in the status by registering a broadcast receiver for
+     * {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED}.
+     *
+     * @return The current Wifi display status.
+     * @hide
+     */
+    public WifiDisplayStatus getWifiDisplayStatus() {
+        return mGlobal.getWifiDisplayStatus();
+    }
+
+    /**
+     * Listens for changes in available display devices.
+     */
+    public interface DisplayListener {
+        /**
+         * Called whenever a logical display has been added to the system.
+         * Use {@link DisplayManager#getDisplay} to get more information about
+         * the display.
+         *
+         * @param displayId The id of the logical display that was added.
+         */
+        void onDisplayAdded(int displayId);
+
+        /**
+         * Called whenever a logical display has been removed from the system.
+         *
+         * @param displayId The id of the logical display that was removed.
+         */
+        void onDisplayRemoved(int displayId);
+
+        /**
+         * Called whenever the properties of a logical display have changed.
+         *
+         * @param displayId The id of the logical display that changed.
+         */
+        void onDisplayChanged(int displayId);
+    }
+}
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
new file mode 100644
index 0000000..a858681
--- /dev/null
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -0,0 +1,360 @@
+/*
+ * 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.hardware.display;
+
+import android.content.Context;
+import android.hardware.display.DisplayManager.DisplayListener;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.CompatibilityInfoHolder;
+import android.view.Display;
+import android.view.DisplayInfo;
+
+import java.util.ArrayList;
+
+/**
+ * Manager communication with the display manager service on behalf of
+ * an application process.  You're probably looking for {@link DisplayManager}.
+ *
+ * @hide
+ */
+public final class DisplayManagerGlobal {
+    private static final String TAG = "DisplayManager";
+    private static final boolean DEBUG = false;
+
+    // True if display info and display ids should be cached.
+    //
+    // FIXME: The cache is currently disabled because it's unclear whether we have the
+    // necessary guarantees that the caches will always be flushed before clients
+    // attempt to observe their new state.  For example, depending on the order
+    // in which the binder transactions take place, we might have a problem where
+    // an application could start processing a configuration change due to a display
+    // orientation change before the display info cache has actually been invalidated.
+    private static final boolean USE_CACHE = false;
+
+    public static final int EVENT_DISPLAY_ADDED = 1;
+    public static final int EVENT_DISPLAY_CHANGED = 2;
+    public static final int EVENT_DISPLAY_REMOVED = 3;
+
+    private static DisplayManagerGlobal sInstance;
+
+    private final Object mLock = new Object();
+
+    private final IDisplayManager mDm;
+
+    private DisplayManagerCallback mCallback;
+    private final ArrayList<DisplayListenerDelegate> mDisplayListeners =
+            new ArrayList<DisplayListenerDelegate>();
+
+    private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<DisplayInfo>();
+    private int[] mDisplayIdCache;
+
+    private DisplayManagerGlobal(IDisplayManager dm) {
+        mDm = dm;
+    }
+
+    /**
+     * Gets an instance of the display manager global singleton.
+     *
+     * @return The display manager instance, may be null early in system startup
+     * before the display manager has been fully initialized.
+     */
+    public static DisplayManagerGlobal getInstance() {
+        synchronized (DisplayManagerGlobal.class) {
+            if (sInstance == null) {
+                IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE);
+                if (b != null) {
+                    sInstance = new DisplayManagerGlobal(IDisplayManager.Stub.asInterface(b));
+                }
+            }
+            return sInstance;
+        }
+    }
+
+    /**
+     * Get information about a particular logical display.
+     *
+     * @param displayId The logical display id.
+     * @return Information about the specified display, or null if it does not exist.
+     * This object belongs to an internal cache and should be treated as if it were immutable.
+     */
+    public DisplayInfo getDisplayInfo(int displayId) {
+        try {
+            synchronized (mLock) {
+                DisplayInfo info;
+                if (USE_CACHE) {
+                    info = mDisplayInfoCache.get(displayId);
+                    if (info != null) {
+                        return info;
+                    }
+                }
+
+                info = mDm.getDisplayInfo(displayId);
+                if (info == null) {
+                    return null;
+                }
+
+                if (USE_CACHE) {
+                    mDisplayInfoCache.put(displayId, info);
+                }
+                registerCallbackIfNeededLocked();
+
+                if (DEBUG) {
+                    Log.d(TAG, "getDisplayInfo: displayId=" + displayId + ", info=" + info);
+                }
+                return info;
+            }
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Could not get display information from display manager.", ex);
+            return null;
+        }
+    }
+
+    /**
+     * Gets all currently valid logical display ids.
+     *
+     * @return An array containing all display ids.
+     */
+    public int[] getDisplayIds() {
+        try {
+            synchronized (mLock) {
+                if (USE_CACHE) {
+                    if (mDisplayIdCache != null) {
+                        return mDisplayIdCache;
+                    }
+                }
+
+                int[] displayIds = mDm.getDisplayIds();
+                if (USE_CACHE) {
+                    mDisplayIdCache = displayIds;
+                }
+                registerCallbackIfNeededLocked();
+                return displayIds;
+            }
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Could not get display ids from display manager.", ex);
+            return new int[] { Display.DEFAULT_DISPLAY };
+        }
+    }
+
+    /**
+     * Gets information about a logical display.
+     *
+     * The display metrics may be adjusted to provide compatibility
+     * for legacy applications.
+     *
+     * @param displayId The logical display id.
+     * @param cih The compatibility info, or null if none is required.
+     * @return The display object, or null if there is no display with the given id.
+     */
+    public Display getCompatibleDisplay(int displayId, CompatibilityInfoHolder cih) {
+        DisplayInfo displayInfo = getDisplayInfo(displayId);
+        if (displayInfo == null) {
+            return null;
+        }
+        return new Display(this, displayId, displayInfo, cih);
+    }
+
+    /**
+     * Gets information about a logical display without applying any compatibility metrics.
+     *
+     * @param displayId The logical display id.
+     * @return The display object, or null if there is no display with the given id.
+     */
+    public Display getRealDisplay(int displayId) {
+        return getCompatibleDisplay(displayId, null);
+    }
+
+    public void registerDisplayListener(DisplayListener listener, Handler handler) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+
+        synchronized (mLock) {
+            int index = findDisplayListenerLocked(listener);
+            if (index < 0) {
+                mDisplayListeners.add(new DisplayListenerDelegate(listener, handler));
+                registerCallbackIfNeededLocked();
+            }
+        }
+    }
+
+    public void unregisterDisplayListener(DisplayListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+
+        synchronized (mLock) {
+            int index = findDisplayListenerLocked(listener);
+            if (index >= 0) {
+                DisplayListenerDelegate d = mDisplayListeners.get(index);
+                d.clearEvents();
+                mDisplayListeners.remove(index);
+            }
+        }
+    }
+
+    private int findDisplayListenerLocked(DisplayListener listener) {
+        final int numListeners = mDisplayListeners.size();
+        for (int i = 0; i < numListeners; i++) {
+            if (mDisplayListeners.get(i).mListener == listener) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private void registerCallbackIfNeededLocked() {
+        if (mCallback == null) {
+            mCallback = new DisplayManagerCallback();
+            try {
+                mDm.registerCallback(mCallback);
+            } catch (RemoteException ex) {
+                Log.e(TAG, "Failed to register callback with display manager service.", ex);
+                mCallback = null;
+            }
+        }
+    }
+
+    private void handleDisplayEvent(int displayId, int event) {
+        synchronized (mLock) {
+            if (USE_CACHE) {
+                mDisplayInfoCache.remove(displayId);
+
+                if (event == EVENT_DISPLAY_ADDED || event == EVENT_DISPLAY_REMOVED) {
+                    mDisplayIdCache = null;
+                }
+            }
+
+            final int numListeners = mDisplayListeners.size();
+            for (int i = 0; i < numListeners; i++) {
+                mDisplayListeners.get(i).sendDisplayEvent(displayId, event);
+            }
+        }
+    }
+
+    public void scanWifiDisplays() {
+        try {
+            mDm.scanWifiDisplays();
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Failed to scan for Wifi displays.", ex);
+        }
+    }
+
+    public void connectWifiDisplay(String deviceAddress) {
+        if (deviceAddress == null) {
+            throw new IllegalArgumentException("deviceAddress must not be null");
+        }
+
+        try {
+            mDm.connectWifiDisplay(deviceAddress);
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Failed to connect to Wifi display " + deviceAddress + ".", ex);
+        }
+    }
+
+    public void disconnectWifiDisplay() {
+        try {
+            mDm.disconnectWifiDisplay();
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Failed to disconnect from Wifi display.", ex);
+        }
+    }
+
+    public void renameWifiDisplay(String deviceAddress, String alias) {
+        if (deviceAddress == null) {
+            throw new IllegalArgumentException("deviceAddress must not be null");
+        }
+
+        try {
+            mDm.renameWifiDisplay(deviceAddress, alias);
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Failed to rename Wifi display " + deviceAddress
+                    + " with alias " + alias + ".", ex);
+        }
+    }
+
+    public void forgetWifiDisplay(String deviceAddress) {
+        if (deviceAddress == null) {
+            throw new IllegalArgumentException("deviceAddress must not be null");
+        }
+
+        try {
+            mDm.forgetWifiDisplay(deviceAddress);
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Failed to forget Wifi display.", ex);
+        }
+    }
+
+    public WifiDisplayStatus getWifiDisplayStatus() {
+        try {
+            return mDm.getWifiDisplayStatus();
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Failed to get Wifi display status.", ex);
+            return new WifiDisplayStatus();
+        }
+    }
+
+    private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub {
+        @Override
+        public void onDisplayEvent(int displayId, int event) {
+            if (DEBUG) {
+                Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" + event);
+            }
+            handleDisplayEvent(displayId, event);
+        }
+    }
+
+    private static final class DisplayListenerDelegate extends Handler {
+        public final DisplayListener mListener;
+
+        public DisplayListenerDelegate(DisplayListener listener, Handler handler) {
+            super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/);
+            mListener = listener;
+        }
+
+        public void sendDisplayEvent(int displayId, int event) {
+            Message msg = obtainMessage(event, displayId, 0);
+            sendMessage(msg);
+        }
+
+        public void clearEvents() {
+            removeCallbacksAndMessages(null);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case EVENT_DISPLAY_ADDED:
+                    mListener.onDisplayAdded(msg.arg1);
+                    break;
+                case EVENT_DISPLAY_CHANGED:
+                    mListener.onDisplayChanged(msg.arg1);
+                    break;
+                case EVENT_DISPLAY_REMOVED:
+                    mListener.onDisplayRemoved(msg.arg1);
+                    break;
+            }
+        }
+    }
+}
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
new file mode 100644
index 0000000..79aad78
--- /dev/null
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -0,0 +1,49 @@
+/*
+ * 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.hardware.display;
+
+import android.hardware.display.IDisplayManagerCallback;
+import android.hardware.display.WifiDisplay;
+import android.hardware.display.WifiDisplayStatus;
+import android.view.DisplayInfo;
+
+/** @hide */
+interface IDisplayManager {
+    DisplayInfo getDisplayInfo(int displayId);
+    int[] getDisplayIds();
+
+    void registerCallback(in IDisplayManagerCallback callback);
+
+    // No permissions required.
+    void scanWifiDisplays();
+
+    // Requires CONFIGURE_WIFI_DISPLAY permission to connect to an unknown device.
+    // No permissions required to connect to a known device.
+    void connectWifiDisplay(String address);
+
+    // No permissions required.
+    void disconnectWifiDisplay();
+
+    // Requires CONFIGURE_WIFI_DISPLAY permission.
+    void renameWifiDisplay(String address, String alias);
+
+    // Requires CONFIGURE_WIFI_DISPLAY permission.
+    void forgetWifiDisplay(String address);
+
+    // No permissions required.
+    WifiDisplayStatus getWifiDisplayStatus();
+}
diff --git a/core/java/android/hardware/display/IDisplayManagerCallback.aidl b/core/java/android/hardware/display/IDisplayManagerCallback.aidl
new file mode 100644
index 0000000..c50e3fb
--- /dev/null
+++ b/core/java/android/hardware/display/IDisplayManagerCallback.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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.hardware.display;
+
+/** @hide */
+interface IDisplayManagerCallback {
+    oneway void onDisplayEvent(int displayId, int event);
+}
diff --git a/core/java/android/hardware/display/WifiDisplay.aidl b/core/java/android/hardware/display/WifiDisplay.aidl
new file mode 100644
index 0000000..7733075
--- /dev/null
+++ b/core/java/android/hardware/display/WifiDisplay.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.hardware.display;
+
+parcelable WifiDisplay;
diff --git a/core/java/android/hardware/display/WifiDisplay.java b/core/java/android/hardware/display/WifiDisplay.java
new file mode 100644
index 0000000..0138b1c
--- /dev/null
+++ b/core/java/android/hardware/display/WifiDisplay.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.display;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import libcore.util.Objects;
+
+/**
+ * Describes the properties of a Wifi display.
+ * <p>
+ * This object is immutable.
+ * </p>
+ *
+ * @hide
+ */
+public final class WifiDisplay implements Parcelable {
+    private final String mDeviceAddress;
+    private final String mDeviceName;
+    private final String mDeviceAlias;
+
+    public static final WifiDisplay[] EMPTY_ARRAY = new WifiDisplay[0];
+
+    public static final Creator<WifiDisplay> CREATOR = new Creator<WifiDisplay>() {
+        public WifiDisplay createFromParcel(Parcel in) {
+            String deviceAddress = in.readString();
+            String deviceName = in.readString();
+            String deviceAlias = in.readString();
+            return new WifiDisplay(deviceAddress, deviceName, deviceAlias);
+        }
+
+        public WifiDisplay[] newArray(int size) {
+            return size == 0 ? EMPTY_ARRAY : new WifiDisplay[size];
+        }
+    };
+
+    public WifiDisplay(String deviceAddress, String deviceName, String deviceAlias) {
+        if (deviceAddress == null) {
+            throw new IllegalArgumentException("deviceAddress must not be null");
+        }
+        if (deviceName == null) {
+            throw new IllegalArgumentException("deviceName must not be null");
+        }
+
+        mDeviceAddress = deviceAddress;
+        mDeviceName = deviceName;
+        mDeviceAlias = deviceAlias;
+    }
+
+    /**
+     * Gets the MAC address of the Wifi display device.
+     */
+    public String getDeviceAddress() {
+        return mDeviceAddress;
+    }
+
+    /**
+     * Gets the name of the Wifi display device.
+     */
+    public String getDeviceName() {
+        return mDeviceName;
+    }
+
+    /**
+     * Gets the user-specified alias of the Wifi display device, or null if none.
+     * <p>
+     * The alias should be used in the UI whenever available.  It is the value
+     * provided by the user when renaming the device.
+     * </p>
+     */
+    public String getDeviceAlias() {
+        return mDeviceAlias;
+    }
+
+    /**
+     * Gets the name to show in the UI.
+     * Uses the device alias if available, otherwise uses the device name.
+     */
+    public String getFriendlyDisplayName() {
+        return mDeviceAlias != null ? mDeviceAlias : mDeviceName;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o instanceof WifiDisplay && equals((WifiDisplay)o);
+    }
+
+    public boolean equals(WifiDisplay other) {
+        return other != null
+                && mDeviceAddress.equals(other.mDeviceAddress)
+                && mDeviceName.equals(other.mDeviceName)
+                && Objects.equal(mDeviceAlias, other.mDeviceAlias);
+    }
+
+    @Override
+    public int hashCode() {
+        // The address on its own should be sufficiently unique for hashing purposes.
+        return mDeviceAddress.hashCode();
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mDeviceAddress);
+        dest.writeString(mDeviceName);
+        dest.writeString(mDeviceAlias);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    // For debugging purposes only.
+    @Override
+    public String toString() {
+        String result = mDeviceName + " (" + mDeviceAddress + ")";
+        if (mDeviceAlias != null) {
+            result += ", alias " + mDeviceAlias;
+        }
+        return result;
+    }
+}
diff --git a/core/java/android/hardware/display/WifiDisplayStatus.aidl b/core/java/android/hardware/display/WifiDisplayStatus.aidl
new file mode 100644
index 0000000..35c633e
--- /dev/null
+++ b/core/java/android/hardware/display/WifiDisplayStatus.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.hardware.display;
+
+parcelable WifiDisplayStatus;
diff --git a/core/java/android/hardware/display/WifiDisplayStatus.java b/core/java/android/hardware/display/WifiDisplayStatus.java
new file mode 100644
index 0000000..f7e72c4
--- /dev/null
+++ b/core/java/android/hardware/display/WifiDisplayStatus.java
@@ -0,0 +1,215 @@
+/*
+ * 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.hardware.display;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+
+/**
+ * Describes the current global state of Wifi display connectivity, including the
+ * currently connected display and all available or remembered displays.
+ * <p>
+ * This object is immutable.
+ * </p>
+ *
+ * @hide
+ */
+public final class WifiDisplayStatus implements Parcelable {
+    private final int mFeatureState;
+    private final int mScanState;
+    private final int mActiveDisplayState;
+    private final WifiDisplay mActiveDisplay;
+    private final WifiDisplay[] mAvailableDisplays;
+    private final WifiDisplay[] mRememberedDisplays;
+
+    /** Feature state: Wifi display is not available on this device. */
+    public static final int FEATURE_STATE_UNAVAILABLE = 0;
+    /** Feature state: Wifi display is disabled, probably because Wifi is disabled. */
+    public static final int FEATURE_STATE_DISABLED = 1;
+    /** Feature state: Wifi display is turned off in settings. */
+    public static final int FEATURE_STATE_OFF = 2;
+    /** Feature state: Wifi display is turned on in settings. */
+    public static final int FEATURE_STATE_ON = 3;
+
+    /** Scan state: Not currently scanning. */
+    public static final int SCAN_STATE_NOT_SCANNING = 0;
+    /** Scan state: Currently scanning. */
+    public static final int SCAN_STATE_SCANNING = 1;
+
+    /** Display state: Not connected. */
+    public static final int DISPLAY_STATE_NOT_CONNECTED = 0;
+    /** Display state: Connecting to active display. */
+    public static final int DISPLAY_STATE_CONNECTING = 1;
+    /** Display state: Connected to active display. */
+    public static final int DISPLAY_STATE_CONNECTED = 2;
+
+    public static final Creator<WifiDisplayStatus> CREATOR = new Creator<WifiDisplayStatus>() {
+        public WifiDisplayStatus createFromParcel(Parcel in) {
+            int featureState = in.readInt();
+            int scanState = in.readInt();
+            int activeDisplayState= in.readInt();
+
+            WifiDisplay activeDisplay = null;
+            if (in.readInt() != 0) {
+                activeDisplay = WifiDisplay.CREATOR.createFromParcel(in);
+            }
+
+            WifiDisplay[] availableDisplays = WifiDisplay.CREATOR.newArray(in.readInt());
+            for (int i = 0; i < availableDisplays.length; i++) {
+                availableDisplays[i] = WifiDisplay.CREATOR.createFromParcel(in);
+            }
+
+            WifiDisplay[] rememberedDisplays = WifiDisplay.CREATOR.newArray(in.readInt());
+            for (int i = 0; i < rememberedDisplays.length; i++) {
+                rememberedDisplays[i] = WifiDisplay.CREATOR.createFromParcel(in);
+            }
+
+            return new WifiDisplayStatus(featureState, scanState, activeDisplayState,
+                    activeDisplay, availableDisplays, rememberedDisplays);
+        }
+
+        public WifiDisplayStatus[] newArray(int size) {
+            return new WifiDisplayStatus[size];
+        }
+    };
+
+    public WifiDisplayStatus() {
+        this(FEATURE_STATE_UNAVAILABLE, SCAN_STATE_NOT_SCANNING, DISPLAY_STATE_NOT_CONNECTED,
+                null, WifiDisplay.EMPTY_ARRAY, WifiDisplay.EMPTY_ARRAY);
+    }
+
+    public WifiDisplayStatus(int featureState, int scanState,
+            int activeDisplayState, WifiDisplay activeDisplay,
+            WifiDisplay[] availableDisplays, WifiDisplay[] rememberedDisplays) {
+        if (availableDisplays == null) {
+            throw new IllegalArgumentException("availableDisplays must not be null");
+        }
+        if (rememberedDisplays == null) {
+            throw new IllegalArgumentException("rememberedDisplays must not be null");
+        }
+
+        mFeatureState = featureState;
+        mScanState = scanState;
+        mActiveDisplayState = activeDisplayState;
+        mActiveDisplay = activeDisplay;
+        mAvailableDisplays = availableDisplays;
+        mRememberedDisplays = rememberedDisplays;
+    }
+
+    /**
+     * Returns the state of the Wifi display feature on this device.
+     * <p>
+     * The value of this property reflects whether the device supports the Wifi display,
+     * whether it has been enabled by the user and whether the prerequisites for
+     * connecting to displays have been met.
+     * </p>
+     */
+    public int getFeatureState() {
+        return mFeatureState;
+    }
+
+    /**
+     * Returns the current state of the Wifi display scan.
+     *
+     * @return One of: {@link #SCAN_STATE_NOT_SCANNING} or {@link #SCAN_STATE_SCANNING}.
+     */
+    public int getScanState() {
+        return mScanState;
+    }
+
+    /**
+     * Get the state of the currently active display.
+     *
+     * @return One of: {@link #DISPLAY_STATE_NOT_CONNECTED}, {@link #DISPLAY_STATE_CONNECTING},
+     * or {@link #DISPLAY_STATE_CONNECTED}.
+     */
+    public int getActiveDisplayState() {
+        return mActiveDisplayState;
+    }
+
+    /**
+     * Gets the Wifi display that is currently active.  It may be connecting or
+     * connected.
+     */
+    public WifiDisplay getActiveDisplay() {
+        return mActiveDisplay;
+    }
+
+    /**
+     * Gets the list of all available Wifi displays as reported by the most recent
+     * scan, never null.
+     * <p>
+     * Some of these displays may already be remembered, others may be unknown.
+     * </p>
+     */
+    public WifiDisplay[] getAvailableDisplays() {
+        return mAvailableDisplays;
+    }
+
+    /**
+     * Gets the list of all remembered Wifi displays, never null.
+     * <p>
+     * Not all remembered displays will necessarily be available.
+     * </p>
+     */
+    public WifiDisplay[] getRememberedDisplays() {
+        return mRememberedDisplays;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mFeatureState);
+        dest.writeInt(mScanState);
+        dest.writeInt(mActiveDisplayState);
+
+        if (mActiveDisplay != null) {
+            dest.writeInt(1);
+            mActiveDisplay.writeToParcel(dest, flags);
+        } else {
+            dest.writeInt(0);
+        }
+
+        dest.writeInt(mAvailableDisplays.length);
+        for (WifiDisplay display : mAvailableDisplays) {
+            display.writeToParcel(dest, flags);
+        }
+
+        dest.writeInt(mRememberedDisplays.length);
+        for (WifiDisplay display : mRememberedDisplays) {
+            display.writeToParcel(dest, flags);
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    // For debugging purposes only.
+    @Override
+    public String toString() {
+        return "WifiDisplayStatus{featureState=" + mFeatureState
+                + ", scanState=" + mScanState
+                + ", activeDisplayState=" + mActiveDisplayState
+                + ", activeDisplay=" + mActiveDisplay
+                + ", availableDisplays=" + Arrays.toString(mAvailableDisplays)
+                + ", rememberedDisplays=" + Arrays.toString(mRememberedDisplays)
+                + "}";
+    }
+}
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 9bab797..8286686 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -44,12 +44,12 @@
     /* Sets the default package for a USB device
      * (or clears it if the package name is null)
      */
-    void setDevicePackage(in UsbDevice device, String packageName);
+    void setDevicePackage(in UsbDevice device, String packageName, int userId);
 
     /* Sets the default package for a USB accessory
      * (or clears it if the package name is null)
      */
-    void setAccessoryPackage(in UsbAccessory accessory, String packageName);
+    void setAccessoryPackage(in UsbAccessory accessory, String packageName, int userId);
 
     /* Returns true if the caller has permission to access the device. */
     boolean hasDevicePermission(in UsbDevice device);
@@ -77,14 +77,22 @@
     void grantAccessoryPermission(in UsbAccessory accessory, int uid);
 
     /* Returns true if the USB manager has default preferences or permissions for the package */
-    boolean hasDefaults(String packageName);
+    boolean hasDefaults(String packageName, int userId);
 
     /* Clears default preferences and permissions for the package */
-    void clearDefaults(String packageName);
+    void clearDefaults(String packageName, int userId);
 
     /* Sets the current USB function. */
     void setCurrentFunction(String function, boolean makeDefault);
 
     /* Sets the file path for USB mass storage backing file. */
     void setMassStorageBackingFile(String path);
+
+    /* Allow USB debugging from the attached host. If alwaysAllow is true, add the
+     * the public key to list of host keys that the user has approved.
+     */
+    void allowUsbDebugging(boolean alwaysAllow, String publicKey);
+
+    /* Deny USB debugging from the attached host */
+    void denyUsbDebugging();
 }
diff --git a/core/java/android/hardware/usb/UsbRequest.java b/core/java/android/hardware/usb/UsbRequest.java
index 2252248..3646715 100644
--- a/core/java/android/hardware/usb/UsbRequest.java
+++ b/core/java/android/hardware/usb/UsbRequest.java
@@ -152,10 +152,14 @@
 
     /* package */ void dequeue() {
         boolean out = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT);
+        int bytesRead;
         if (mBuffer.isDirect()) {
-            native_dequeue_direct();
+            bytesRead = native_dequeue_direct();
         } else {
-            native_dequeue_array(mBuffer.array(), mLength, out);
+            bytesRead = native_dequeue_array(mBuffer.array(), mLength, out);
+        }
+        if (bytesRead >= 0) {
+            mBuffer.position(Math.min(bytesRead, mLength));
         }
         mBuffer = null;
         mLength = 0;
@@ -174,8 +178,8 @@
             int ep_attributes, int ep_max_packet_size, int ep_interval);
     private native void native_close();
     private native boolean native_queue_array(byte[] buffer, int length, boolean out);
-    private native void native_dequeue_array(byte[] buffer, int length, boolean out);
+    private native int native_dequeue_array(byte[] buffer, int length, boolean out);
     private native boolean native_queue_direct(ByteBuffer buffer, int length, boolean out);
-    private native void native_dequeue_direct();
+    private native int native_dequeue_direct();
     private native boolean native_cancel();
 }
diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java
index 27af013..3c3182a 100644
--- a/core/java/android/inputmethodservice/AbstractInputMethodService.java
+++ b/core/java/android/inputmethodservice/AbstractInputMethodService.java
@@ -149,6 +149,17 @@
                 callback.finishedEvent(seq, handled);
             }
         }
+
+        /**
+         * Take care of dispatching incoming generic motion events to the appropriate
+         * callbacks on the service, and tell the client when this is done.
+         */
+        public void dispatchGenericMotionEvent(int seq, MotionEvent event, EventCallback callback) {
+            boolean handled = onGenericMotionEvent(event);
+            if (callback != null) {
+                callback.finishedEvent(seq, handled);
+            }
+        }
     }
     
     /**
@@ -189,7 +200,25 @@
         return new IInputMethodWrapper(this, mInputMethod);
     }
     
+    /**
+     * Implement this to handle trackball events on your input method.
+     *
+     * @param event The motion event being received.
+     * @return True if the event was handled in this function, false otherwise.
+     * @see View#onTrackballEvent
+     */
     public boolean onTrackballEvent(MotionEvent event) {
         return false;
     }
+
+    /**
+     * Implement this to handle generic motion events on your input method.
+     *
+     * @param event The motion event being received.
+     * @return True if the event was handled in this function, false otherwise.
+     * @see View#onGenericMotionEvent
+     */
+    public boolean onGenericMotionEvent(MotionEvent event) {
+        return false;
+    }
 }
diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
index e10f218..5324f81 100644
--- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
@@ -17,6 +17,7 @@
 package android.inputmethodservice;
 
 import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.SomeArgs;
 import com.android.internal.view.IInputMethodCallback;
 import com.android.internal.view.IInputMethodSession;
 
@@ -42,6 +43,7 @@
     private static final int DO_UPDATE_EXTRACTED_TEXT = 67;
     private static final int DO_DISPATCH_KEY_EVENT = 70;
     private static final int DO_DISPATCH_TRACKBALL_EVENT = 80;
+    private static final int DO_DISPATCH_GENERIC_MOTION_EVENT = 85;
     private static final int DO_UPDATE_SELECTION = 90;
     private static final int DO_UPDATE_CURSOR = 95;
     private static final int DO_APP_PRIVATE_COMMAND = 100;
@@ -91,28 +93,37 @@
                         (ExtractedText)msg.obj);
                 return;
             case DO_DISPATCH_KEY_EVENT: {
-                HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
+                SomeArgs args = (SomeArgs)msg.obj;
                 mInputMethodSession.dispatchKeyEvent(msg.arg1,
                         (KeyEvent)args.arg1,
                         new InputMethodEventCallbackWrapper(
                                 (IInputMethodCallback)args.arg2));
-                mCaller.recycleArgs(args);
+                args.recycle();
                 return;
             }
             case DO_DISPATCH_TRACKBALL_EVENT: {
-                HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
+                SomeArgs args = (SomeArgs)msg.obj;
                 mInputMethodSession.dispatchTrackballEvent(msg.arg1,
                         (MotionEvent)args.arg1,
                         new InputMethodEventCallbackWrapper(
                                 (IInputMethodCallback)args.arg2));
-                mCaller.recycleArgs(args);
+                args.recycle();
+                return;
+            }
+            case DO_DISPATCH_GENERIC_MOTION_EVENT: {
+                SomeArgs args = (SomeArgs)msg.obj;
+                mInputMethodSession.dispatchGenericMotionEvent(msg.arg1,
+                        (MotionEvent)args.arg1,
+                        new InputMethodEventCallbackWrapper(
+                                (IInputMethodCallback)args.arg2));
+                args.recycle();
                 return;
             }
             case DO_UPDATE_SELECTION: {
-                HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
+                SomeArgs args = (SomeArgs)msg.obj;
                 mInputMethodSession.updateSelection(args.argi1, args.argi2,
                         args.argi3, args.argi4, args.argi5, args.argi6);
-                mCaller.recycleArgs(args);
+                args.recycle();
                 return;
             }
             case DO_UPDATE_CURSOR: {
@@ -120,10 +131,10 @@
                 return;
             }
             case DO_APP_PRIVATE_COMMAND: {
-                HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
+                SomeArgs args = (SomeArgs)msg.obj;
                 mInputMethodSession.appPrivateCommand((String)args.arg1,
                         (Bundle)args.arg2);
-                mCaller.recycleArgs(args);
+                args.recycle();
                 return;
             }
             case DO_TOGGLE_SOFT_INPUT: {
@@ -166,6 +177,12 @@
                 event, callback));
     }
 
+    public void dispatchGenericMotionEvent(int seq, MotionEvent event,
+            IInputMethodCallback callback) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_DISPATCH_GENERIC_MOTION_EVENT, seq,
+                event, callback));
+    }
+
     public void updateSelection(int oldSelStart, int oldSelEnd,
             int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) {
         mCaller.executeOrSendMessage(mCaller.obtainMessageIIIIII(DO_UPDATE_SELECTION,
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 17c9ee7..5275314 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -17,6 +17,7 @@
 package android.inputmethodservice;
 
 import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.SomeArgs;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethod;
 import com.android.internal.view.IInputMethodCallback;
@@ -124,7 +125,7 @@
                 if (target == null) {
                     return;
                 }
-                HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
+                SomeArgs args = (SomeArgs)msg.obj;
                 try {
                     target.dump((FileDescriptor)args.arg1,
                             (PrintWriter)args.arg2, (String[])args.arg3);
@@ -134,6 +135,7 @@
                 synchronized (args.arg4) {
                     ((CountDownLatch)args.arg4).countDown();
                 }
+                args.recycle();
                 return;
             }
             
@@ -149,23 +151,25 @@
                 inputMethod.unbindInput();
                 return;
             case DO_START_INPUT: {
-                HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
+                SomeArgs args = (SomeArgs)msg.obj;
                 IInputContext inputContext = (IInputContext)args.arg1;
                 InputConnection ic = inputContext != null
                         ? new InputConnectionWrapper(inputContext) : null;
                 EditorInfo info = (EditorInfo)args.arg2;
                 info.makeCompatible(mTargetSdkVersion);
                 inputMethod.startInput(ic, info);
+                args.recycle();
                 return;
             }
             case DO_RESTART_INPUT: {
-                HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
+                SomeArgs args = (SomeArgs)msg.obj;
                 IInputContext inputContext = (IInputContext)args.arg1;
                 InputConnection ic = inputContext != null
                         ? new InputConnectionWrapper(inputContext) : null;
                 EditorInfo info = (EditorInfo)args.arg2;
                 info.makeCompatible(mTargetSdkVersion);
                 inputMethod.restartInput(ic, info);
+                args.recycle();
                 return;
             }
             case DO_CREATE_SESSION: {
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 46153e7..f07002e 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -19,6 +19,7 @@
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 
+import android.app.ActivityManager;
 import android.app.Dialog;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -250,6 +251,7 @@
     InputMethodManager mImm;
     
     int mTheme = 0;
+    boolean mHardwareAccelerated = false;
     
     LayoutInflater mInflater;
     TypedArray mThemeAttrs;
@@ -614,6 +616,26 @@
         mTheme = theme;
     }
 
+    /**
+     * You can call this to try to enable hardware accelerated drawing for
+     * your IME. This must be set before {@link #onCreate}, so you
+     * will typically call it in your constructor.  It is not always possible
+     * to use hardware acclerated drawing in an IME (for example on low-end
+     * devices that do not have the resources to support this), so the call
+     * returns true if it succeeds otherwise false if you will need to draw
+     * in software.  You must be able to handle either case.
+     */
+    public boolean enableHardwareAcceleration() {
+        if (mWindow != null) {
+            throw new IllegalStateException("Must be called before onCreate()");
+        }
+        if (ActivityManager.isHighEndGfx()) {
+            mHardwareAccelerated = true;
+            return true;
+        }
+        return false;
+    }
+
     @Override public void onCreate() {
         mTheme = Resources.selectSystemTheme(mTheme,
                 getApplicationInfo().targetSdkVersion,
@@ -626,6 +648,9 @@
         mInflater = (LayoutInflater)getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
         mWindow = new SoftInputWindow(this, mTheme, mDispatcherState);
+        if (mHardwareAccelerated) {
+            mWindow.getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+        }
         initViews();
         mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT);
     }
@@ -658,8 +683,8 @@
                 com.android.internal.R.layout.input_method, null);
         mWindow.setContentView(mRootView);
         mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer);
-        if (Settings.System.getInt(getContentResolver(),
-                Settings.System.FANCY_IME_ANIMATIONS, 0) != 0) {
+        if (Settings.Global.getInt(getContentResolver(),
+                Settings.Global.FANCY_IME_ANIMATIONS, 0) != 0) {
             mWindow.getWindow().setWindowAnimations(
                     com.android.internal.R.style.Animation_InputMethodFancy);
         }
@@ -1674,9 +1699,6 @@
     /**
      * Show the input method. This is a call back to the
      * IMF to handle showing the input method.
-     * Close this input method's soft input area, removing it from the display.
-     * The input method will continue running, but the user can no longer use
-     * it to generate input by touching the screen.
      * @param flags Provides additional operating flags.  Currently may be
      * 0 or have the {@link InputMethodManager#SHOW_FORCED
      * InputMethodManager.} bit set.
@@ -1751,7 +1773,7 @@
      * Override this to intercept special key multiple events before they are
      * processed by the
      * application.  If you return true, the application will not itself
-     * process the event.  If you return true, the normal application processing
+     * process the event.  If you return false, the normal application processing
      * will occur as if the IME had not seen the event at all.
      * 
      * <p>The default implementation always returns false, except when
@@ -1766,7 +1788,7 @@
     /**
      * Override this to intercept key up events before they are processed by the
      * application.  If you return true, the application will not itself
-     * process the event.  If you return true, the normal application processing
+     * process the event.  If you return false, the normal application processing
      * will occur as if the IME had not seen the event at all.
      * 
      * <p>The default implementation intercepts {@link KeyEvent#KEYCODE_BACK
@@ -1784,8 +1806,29 @@
         return doMovementKey(keyCode, event, MOVEMENT_UP);
     }
 
+    /**
+     * Override this to intercept trackball motion events before they are
+     * processed by the application.
+     * If you return true, the application will not itself process the event.
+     * If you return false, the normal application processing will occur as if
+     * the IME had not seen the event at all.
+     */
     @Override
     public boolean onTrackballEvent(MotionEvent event) {
+        if (DEBUG) Log.v(TAG, "onTrackballEvent: " + event);
+        return false;
+    }
+
+    /**
+     * Override this to intercept generic motion events before they are
+     * processed by the application.
+     * If you return true, the application will not itself process the event.
+     * If you return false, the normal application processing will occur as if
+     * the IME had not seen the event at all.
+     */
+    @Override
+    public boolean onGenericMotionEvent(MotionEvent event) {
+        if (DEBUG) Log.v(TAG, "onGenericMotionEvent(): event " + event);
         return false;
     }
 
diff --git a/core/java/android/net/BaseNetworkStateTracker.java b/core/java/android/net/BaseNetworkStateTracker.java
new file mode 100644
index 0000000..4b60f07
--- /dev/null
+++ b/core/java/android/net/BaseNetworkStateTracker.java
@@ -0,0 +1,158 @@
+/*
+ * 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.net;
+
+import android.content.Context;
+import android.os.Handler;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Interface to control and observe state of a specific network, hiding
+ * network-specific details from {@link ConnectivityManager}. Surfaces events
+ * through the registered {@link Handler} to enable {@link ConnectivityManager}
+ * to respond to state changes over time.
+ *
+ * @hide
+ */
+public abstract class BaseNetworkStateTracker implements NetworkStateTracker {
+    // TODO: better document threading expectations
+    // TODO: migrate to make NetworkStateTracker abstract class
+
+    public static final String PROP_TCP_BUFFER_UNKNOWN = "net.tcp.buffersize.unknown";
+    public static final String PROP_TCP_BUFFER_WIFI = "net.tcp.buffersize.wifi";
+
+    protected Context mContext;
+    private Handler mTarget;
+
+    protected NetworkInfo mNetworkInfo;
+    protected LinkProperties mLinkProperties;
+    protected LinkCapabilities mLinkCapabilities;
+
+    private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
+    private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
+    private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
+
+    public BaseNetworkStateTracker(int networkType) {
+        mNetworkInfo = new NetworkInfo(
+                networkType, -1, ConnectivityManager.getNetworkTypeName(networkType), null);
+        mLinkProperties = new LinkProperties();
+        mLinkCapabilities = new LinkCapabilities();
+    }
+
+    @Deprecated
+    protected Handler getTargetHandler() {
+        return mTarget;
+    }
+
+    protected final void dispatchStateChanged() {
+        // TODO: include snapshot of other fields when sending
+        mTarget.obtainMessage(EVENT_STATE_CHANGED, getNetworkInfo()).sendToTarget();
+    }
+
+    protected final void dispatchConfigurationChanged() {
+        // TODO: include snapshot of other fields when sending
+        mTarget.obtainMessage(EVENT_CONFIGURATION_CHANGED, getNetworkInfo()).sendToTarget();
+    }
+
+    @Override
+    public final void startMonitoring(Context context, Handler target) {
+        mContext = Preconditions.checkNotNull(context);
+        mTarget = Preconditions.checkNotNull(target);
+        startMonitoringInternal();
+    }
+
+    protected abstract void startMonitoringInternal();
+
+    @Override
+    public final NetworkInfo getNetworkInfo() {
+        return new NetworkInfo(mNetworkInfo);
+    }
+
+    @Override
+    public final LinkProperties getLinkProperties() {
+        return new LinkProperties(mLinkProperties);
+    }
+
+    @Override
+    public final LinkCapabilities getLinkCapabilities() {
+        return new LinkCapabilities(mLinkCapabilities);
+    }
+
+    @Override
+    public void captivePortalCheckComplete() {
+        // not implemented
+    }
+
+    @Override
+    public boolean setRadio(boolean turnOn) {
+        // Base tracker doesn't handle radios
+        return true;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return mNetworkInfo.isAvailable();
+    }
+
+    @Override
+    public void setUserDataEnable(boolean enabled) {
+        // Base tracker doesn't handle enabled flags
+    }
+
+    @Override
+    public void setPolicyDataEnable(boolean enabled) {
+        // Base tracker doesn't handle enabled flags
+    }
+
+    @Override
+    public boolean isPrivateDnsRouteSet() {
+        return mPrivateDnsRouteSet.get();
+    }
+
+    @Override
+    public void privateDnsRouteSet(boolean enabled) {
+        mPrivateDnsRouteSet.set(enabled);
+    }
+
+    @Override
+    public boolean isDefaultRouteSet() {
+        return mDefaultRouteSet.get();
+    }
+
+    @Override
+    public void defaultRouteSet(boolean enabled) {
+        mDefaultRouteSet.set(enabled);
+    }
+
+    @Override
+    public boolean isTeardownRequested() {
+        return mTeardownRequested.get();
+    }
+
+    @Override
+    public void setTeardownRequested(boolean isRequested) {
+        mTeardownRequested.set(isRequested);
+    }
+
+    @Override
+    public void setDependencyMet(boolean met) {
+        // Base tracker doesn't handle dependencies
+    }
+}
diff --git a/core/java/android/net/CaptivePortalTracker.java b/core/java/android/net/CaptivePortalTracker.java
new file mode 100644
index 0000000..ce71e6b
--- /dev/null
+++ b/core/java/android/net/CaptivePortalTracker.java
@@ -0,0 +1,382 @@
+/*
+ * 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.net;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.net.ConnectivityManager;
+import android.net.IConnectivityManager;
+import android.os.UserHandle;
+import android.os.Message;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.URL;
+import java.net.UnknownHostException;
+
+import com.android.internal.R;
+
+/**
+ * This class allows captive portal detection on a network.
+ * @hide
+ */
+public class CaptivePortalTracker extends StateMachine {
+    private static final boolean DBG = false;
+    private static final String TAG = "CaptivePortalTracker";
+
+    private static final String DEFAULT_SERVER = "clients3.google.com";
+    private static final String NOTIFICATION_ID = "CaptivePortal.Notification";
+
+    private static final int SOCKET_TIMEOUT_MS = 10000;
+
+    private String mServer;
+    private String mUrl;
+    private boolean mNotificationShown = false;
+    private boolean mIsCaptivePortalCheckEnabled = false;
+    private IConnectivityManager mConnService;
+    private TelephonyManager mTelephonyManager;
+    private Context mContext;
+    private NetworkInfo mNetworkInfo;
+
+    private static final int CMD_DETECT_PORTAL          = 0;
+    private static final int CMD_CONNECTIVITY_CHANGE    = 1;
+    private static final int CMD_DELAYED_CAPTIVE_CHECK  = 2;
+
+    /* This delay happens every time before we do a captive check on a network */
+    private static final int DELAYED_CHECK_INTERVAL_MS = 10000;
+    private int mDelayedCheckToken = 0;
+
+    private State mDefaultState = new DefaultState();
+    private State mNoActiveNetworkState = new NoActiveNetworkState();
+    private State mActiveNetworkState = new ActiveNetworkState();
+    private State mDelayedCaptiveCheckState = new DelayedCaptiveCheckState();
+
+    private CaptivePortalTracker(Context context, IConnectivityManager cs) {
+        super(TAG);
+
+        mContext = context;
+        mConnService = cs;
+        mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+        mContext.registerReceiver(mReceiver, filter);
+
+        mServer = Settings.Global.getString(mContext.getContentResolver(),
+                Settings.Global.CAPTIVE_PORTAL_SERVER);
+        if (mServer == null) mServer = DEFAULT_SERVER;
+
+        mIsCaptivePortalCheckEnabled = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED, 1) == 1;
+
+        addState(mDefaultState);
+            addState(mNoActiveNetworkState, mDefaultState);
+            addState(mActiveNetworkState, mDefaultState);
+                addState(mDelayedCaptiveCheckState, mActiveNetworkState);
+        setInitialState(mNoActiveNetworkState);
+    }
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+                NetworkInfo info = intent.getParcelableExtra(
+                        ConnectivityManager.EXTRA_NETWORK_INFO);
+                sendMessage(obtainMessage(CMD_CONNECTIVITY_CHANGE, info));
+            }
+        }
+    };
+
+    public static CaptivePortalTracker makeCaptivePortalTracker(Context context,
+            IConnectivityManager cs) {
+        CaptivePortalTracker captivePortal = new CaptivePortalTracker(context, cs);
+        captivePortal.start();
+        return captivePortal;
+    }
+
+    public void detectCaptivePortal(NetworkInfo info) {
+        sendMessage(obtainMessage(CMD_DETECT_PORTAL, info));
+    }
+
+    private class DefaultState extends State {
+        @Override
+        public void enter() {
+            if (DBG) log(getName() + "\n");
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) log(getName() + message.toString() + "\n");
+            switch (message.what) {
+                case CMD_DETECT_PORTAL:
+                    NetworkInfo info = (NetworkInfo) message.obj;
+                    // Checking on a secondary connection is not supported
+                    // yet
+                    notifyPortalCheckComplete(info);
+                    break;
+                case CMD_CONNECTIVITY_CHANGE:
+                case CMD_DELAYED_CAPTIVE_CHECK:
+                    break;
+                default:
+                    loge("Ignoring " + message);
+                    break;
+            }
+            return HANDLED;
+        }
+    }
+
+    private class NoActiveNetworkState extends State {
+        @Override
+        public void enter() {
+            if (DBG) log(getName() + "\n");
+            mNetworkInfo = null;
+            /* Clear any previous notification */
+            setNotificationVisible(false);
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) log(getName() + message.toString() + "\n");
+            InetAddress server;
+            NetworkInfo info;
+            switch (message.what) {
+                case CMD_CONNECTIVITY_CHANGE:
+                    info = (NetworkInfo) message.obj;
+                    if (info.isConnected() && isActiveNetwork(info)) {
+                        mNetworkInfo = info;
+                        transitionTo(mDelayedCaptiveCheckState);
+                    }
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+    private class ActiveNetworkState extends State {
+        @Override
+        public void enter() {
+            if (DBG) log(getName() + "\n");
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            NetworkInfo info;
+            switch (message.what) {
+               case CMD_CONNECTIVITY_CHANGE:
+                    info = (NetworkInfo) message.obj;
+                    if (!info.isConnected()
+                            && info.getType() == mNetworkInfo.getType()) {
+                        if (DBG) log("Disconnected from active network " + info);
+                        transitionTo(mNoActiveNetworkState);
+                    } else if (info.getType() != mNetworkInfo.getType() &&
+                            info.isConnected() &&
+                            isActiveNetwork(info)) {
+                        if (DBG) log("Active network switched " + info);
+                        deferMessage(message);
+                        transitionTo(mNoActiveNetworkState);
+                    }
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+
+
+    private class DelayedCaptiveCheckState extends State {
+        @Override
+        public void enter() {
+            if (DBG) log(getName() + "\n");
+            sendMessageDelayed(obtainMessage(CMD_DELAYED_CAPTIVE_CHECK,
+                        ++mDelayedCheckToken, 0), DELAYED_CHECK_INTERVAL_MS);
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) log(getName() + message.toString() + "\n");
+            switch (message.what) {
+                case CMD_DELAYED_CAPTIVE_CHECK:
+                    if (message.arg1 == mDelayedCheckToken) {
+                        InetAddress server = lookupHost(mServer);
+                        if (server != null) {
+                            if (isCaptivePortal(server)) {
+                                if (DBG) log("Captive network " + mNetworkInfo);
+                                setNotificationVisible(true);
+                            }
+                        }
+                        if (DBG) log("Not captive network " + mNetworkInfo);
+                        transitionTo(mActiveNetworkState);
+                    }
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+    private void notifyPortalCheckComplete(NetworkInfo info) {
+        if (info == null) {
+            loge("notifyPortalCheckComplete on null");
+            return;
+        }
+        try {
+            mConnService.captivePortalCheckComplete(info);
+        } catch(RemoteException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private boolean isActiveNetwork(NetworkInfo info) {
+        try {
+            NetworkInfo active = mConnService.getActiveNetworkInfo();
+            if (active != null && active.getType() == info.getType()) {
+                return true;
+            }
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+        return false;
+    }
+
+    /**
+     * Do a URL fetch on a known server to see if we get the data we expect
+     */
+    private boolean isCaptivePortal(InetAddress server) {
+        HttpURLConnection urlConnection = null;
+        if (!mIsCaptivePortalCheckEnabled) return false;
+
+        mUrl = "http://" + server.getHostAddress() + "/generate_204";
+        if (DBG) log("Checking " + mUrl);
+        try {
+            URL url = new URL(mUrl);
+            urlConnection = (HttpURLConnection) url.openConnection();
+            urlConnection.setInstanceFollowRedirects(false);
+            urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
+            urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
+            urlConnection.setUseCaches(false);
+            urlConnection.getInputStream();
+            // we got a valid response, but not from the real google
+            return urlConnection.getResponseCode() != 204;
+        } catch (IOException e) {
+            if (DBG) log("Probably not a portal: exception " + e);
+            return false;
+        } finally {
+            if (urlConnection != null) {
+                urlConnection.disconnect();
+            }
+        }
+    }
+
+    private InetAddress lookupHost(String hostname) {
+        InetAddress inetAddress[];
+        try {
+            inetAddress = InetAddress.getAllByName(hostname);
+        } catch (UnknownHostException e) {
+            return null;
+        }
+
+        for (InetAddress a : inetAddress) {
+            if (a instanceof Inet4Address) return a;
+        }
+        return null;
+    }
+
+    private void setNotificationVisible(boolean visible) {
+        // if it should be hidden and it is already hidden, then noop
+        if (!visible && !mNotificationShown) {
+            return;
+        }
+
+        Resources r = Resources.getSystem();
+        NotificationManager notificationManager = (NotificationManager) mContext
+            .getSystemService(Context.NOTIFICATION_SERVICE);
+
+        if (visible) {
+            CharSequence title;
+            CharSequence details;
+            int icon;
+            switch (mNetworkInfo.getType()) {
+                case ConnectivityManager.TYPE_WIFI:
+                    title = r.getString(R.string.wifi_available_sign_in, 0);
+                    details = r.getString(R.string.network_available_sign_in_detailed,
+                            mNetworkInfo.getExtraInfo());
+                    icon = R.drawable.stat_notify_wifi_in_range;
+                    break;
+                case ConnectivityManager.TYPE_MOBILE:
+                    title = r.getString(R.string.network_available_sign_in, 0);
+                    // TODO: Change this to pull from NetworkInfo once a printable
+                    // name has been added to it
+                    details = mTelephonyManager.getNetworkOperatorName();
+                    icon = R.drawable.stat_notify_rssi_in_range;
+                    break;
+                default:
+                    title = r.getString(R.string.network_available_sign_in, 0);
+                    details = r.getString(R.string.network_available_sign_in_detailed,
+                            mNetworkInfo.getExtraInfo());
+                    icon = R.drawable.stat_notify_rssi_in_range;
+                    break;
+            }
+
+            Notification notification = new Notification();
+            notification.when = 0;
+            notification.icon = icon;
+            notification.flags = Notification.FLAG_AUTO_CANCEL;
+            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(mUrl));
+            intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
+                    Intent.FLAG_ACTIVITY_NEW_TASK);
+            notification.contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
+            notification.tickerText = title;
+            notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);
+
+            notificationManager.notify(NOTIFICATION_ID, 1, notification);
+        } else {
+            notificationManager.cancel(NOTIFICATION_ID, 1);
+        }
+        mNotificationShown = visible;
+    }
+
+    private static void log(String s) {
+        Log.d(TAG, s);
+    }
+
+    private static void loge(String s) {
+        Log.e(TAG, s);
+    }
+
+}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 5f8793c..6ff1a339 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -89,11 +89,21 @@
      *             should always obtain network information through
      *             {@link #getActiveNetworkInfo()} or
      *             {@link #getAllNetworkInfo()}.
+     * @see #EXTRA_NETWORK_TYPE
      */
     @Deprecated
     public static final String EXTRA_NETWORK_INFO = "networkInfo";
 
     /**
+     * Network type which triggered a {@link #CONNECTIVITY_ACTION} broadcast.
+     * Can be used with {@link #getNetworkInfo(int)} to get {@link NetworkInfo}
+     * state based on the calling application.
+     *
+     * @see android.content.Intent#getIntExtra(String, int)
+     */
+    public static final String EXTRA_NETWORK_TYPE = "networkType";
+
+    /**
      * The lookup key for a boolean that indicates whether a connect event
      * is for a network to which the connectivity manager was failing over
      * following a disconnect on another network.
@@ -137,6 +147,28 @@
     public static final String EXTRA_INET_CONDITION = "inetCondition";
 
     /**
+     * Broadcast action to indicate the change of data activity status
+     * (idle or active) on a network in a recent period.
+     * The network becomes active when data transimission is started, or
+     * idle if there is no data transimition for a period of time.
+     * {@hide}
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_DATA_ACTIVITY_CHANGE = "android.net.conn.DATA_ACTIVITY_CHANGE";
+    /**
+     * The lookup key for an enum that indicates the network device type on which this data activity
+     * change happens.
+     * {@hide}
+     */
+    public static final String EXTRA_DEVICE_TYPE = "deviceType";
+    /**
+     * The lookup key for a boolean that indicates the device is active or not. {@code true} means
+     * it is actively sending or receiving data and {@code false} means it is idle.
+     * {@hide}
+     */
+    public static final String EXTRA_IS_ACTIVE = "isActive";
+
+    /**
      * Broadcast Action: The setting for background data usage has changed
      * values. Use {@link #getBackgroundDataSetting()} to get the current value.
      * <p>
@@ -298,6 +330,14 @@
 
     public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;
 
+    /**
+     * Default value for {@link Settings.Global#CONNECTIVITY_CHANGE_DELAY} in
+     * milliseconds.
+     *
+     * @hide
+     */
+    public static final int CONNECTIVITY_CHANGE_DELAY_DEFAULT = 3000;
+
     private final IConnectivityManager mService;
 
     public static boolean isNetworkTypeValid(int networkType) {
@@ -880,4 +920,24 @@
             return false;
         }
     }
+
+    /** {@hide} */
+    public boolean updateLockdownVpn() {
+        try {
+            return mService.updateLockdownVpn();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * {@hide}
+     */
+    public void captivePortalCheckComplete(NetworkInfo info) {
+        try {
+            mService.captivePortalCheckComplete(info);
+        } catch (RemoteException e) {
+        }
+    }
+
 }
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java
index cc3e34f..874e80a 100644
--- a/core/java/android/net/DhcpStateMachine.java
+++ b/core/java/android/net/DhcpStateMachine.java
@@ -92,10 +92,12 @@
     /* Notification from DHCP state machine post DHCP discovery/renewal. Indicates
      * success/failure */
     public static final int CMD_POST_DHCP_ACTION            = BASE + 5;
+    /* Notification from DHCP state machine before quitting */
+    public static final int CMD_ON_QUIT                     = BASE + 6;
 
     /* Command from controller to indicate DHCP discovery/renewal can continue
      * after pre DHCP action is complete */
-    public static final int CMD_PRE_DHCP_ACTION_COMPLETE    = BASE + 6;
+    public static final int CMD_PRE_DHCP_ACTION_COMPLETE    = BASE + 7;
 
     /* Message.arg1 arguments to CMD_POST_DHCP notification */
     public static final int DHCP_SUCCESS = 1;
@@ -172,6 +174,10 @@
         quit();
     }
 
+    protected void onQuitting() {
+        mController.sendMessage(CMD_ON_QUIT);
+    }
+
     class DefaultState extends State {
         @Override
         public void exit() {
diff --git a/core/java/android/net/DnsPinger.java b/core/java/android/net/DnsPinger.java
index 11acabe..66f0fd0 100644
--- a/core/java/android/net/DnsPinger.java
+++ b/core/java/android/net/DnsPinger.java
@@ -295,8 +295,8 @@
     }
 
     private InetAddress getDefaultDns() {
-        String dns = Settings.Secure.getString(mContext.getContentResolver(),
-                Settings.Secure.DEFAULT_DNS_SERVER);
+        String dns = Settings.Global.getString(mContext.getContentResolver(),
+                Settings.Global.DEFAULT_DNS_SERVER);
         if (dns == null || dns.length() == 0) {
             dns = mContext.getResources().getString(
                     com.android.internal.R.string.config_default_dns_server);
diff --git a/core/java/android/net/DummyDataStateTracker.java b/core/java/android/net/DummyDataStateTracker.java
index ccd96ff..39440c2 100644
--- a/core/java/android/net/DummyDataStateTracker.java
+++ b/core/java/android/net/DummyDataStateTracker.java
@@ -119,6 +119,10 @@
         return true;
     }
 
+    public void captivePortalCheckComplete() {
+        // not implemented
+    }
+
     /**
      * Record the detailed state of a network, and if it is a
      * change from the previous state, send a notification to
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 0cc78c9..3a06dc0 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -99,6 +99,10 @@
         public void limitReached(String limitName, String iface) {
             // Ignored.
         }
+
+        public void interfaceClassDataActivityChanged(String label, boolean active) {
+            // Ignored.
+        }
     }
 
     private EthernetDataTracker() {
@@ -230,6 +234,10 @@
                             mNetworkInfo.setExtraInfo(mHwAddr);
                         }
                     }
+
+                    // if a DHCP client had previously been started for this interface, then stop it
+                    NetworkUtils.stopDhcp(mIface);
+
                     reconnect();
                     break;
                 }
@@ -266,6 +274,11 @@
         return mLinkUp;
     }
 
+    @Override
+    public void captivePortalCheckComplete() {
+        // not implemented
+    }
+
     /**
      * Turn the wireless radio off for a network.
      * @param turnOn {@code true} to turn the radio on, {@code false}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 92aeff2..056fa03 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -26,6 +26,7 @@
 
 import com.android.internal.net.LegacyVpnInfo;
 import com.android.internal.net.VpnConfig;
+import com.android.internal.net.VpnProfile;
 
 /**
  * Interface that answers queries about, and allows changing, the
@@ -118,7 +119,11 @@
 
     ParcelFileDescriptor establishVpn(in VpnConfig config);
 
-    void startLegacyVpn(in VpnConfig config, in String[] racoon, in String[] mtpd);
+    void startLegacyVpn(in VpnProfile profile);
 
     LegacyVpnInfo getLegacyVpnInfo();
+
+    boolean updateLockdownVpn();
+
+    void captivePortalCheckComplete(in NetworkInfo info);
 }
diff --git a/core/java/android/net/INetworkManagementEventObserver.aidl b/core/java/android/net/INetworkManagementEventObserver.aidl
index a97f203..6f4dd5f 100644
--- a/core/java/android/net/INetworkManagementEventObserver.aidl
+++ b/core/java/android/net/INetworkManagementEventObserver.aidl
@@ -62,4 +62,11 @@
      */
     void limitReached(String limitName, String iface);
 
+    /**
+     * Interface data activity status is changed.
+     *
+     * @param iface The interface.
+     * @param active  True if the interface is actively transmitting data, false if it is idle.
+     */
+    void interfaceClassDataActivityChanged(String label, boolean active);
 }
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 3250ae7..df6057e 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -30,9 +30,9 @@
 interface INetworkPolicyManager {
 
     /** Control UID policies. */
-    void setAppPolicy(int appId, int policy);
-    int getAppPolicy(int appId);
-    int[] getAppsWithPolicy(int policy);
+    void setUidPolicy(int uid, int policy);
+    int getUidPolicy(int uid);
+    int[] getUidsWithPolicy(int policy);
 
     boolean isUidForeground(int uid);
 
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
index 3ee8a80..14a8094 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import java.io.Closeable;
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InputStream;
@@ -26,7 +27,7 @@
  * Creates a (non-server) socket in the UNIX-domain namespace. The interface
  * here is not entirely unlike that of java.net.Socket
  */
-public class LocalSocket {
+public class LocalSocket implements Closeable {
 
     private LocalSocketImpl impl;
     private volatile boolean implCreated;
@@ -42,6 +43,15 @@
         isBound = false;
         isConnected = false;
     }
+    /**
+     * Creates a AF_LOCAL/UNIX domain stream socket with FileDescriptor.
+     * @hide
+     */
+    public LocalSocket(FileDescriptor fd) throws IOException {
+        this(new LocalSocketImpl(fd));
+        isBound = true;
+        isConnected = true;
+    }
 
     /**
      * for use with AndroidServerSocket
@@ -158,6 +168,7 @@
      *
      * @throws IOException
      */
+    @Override
     public void close() throws IOException {
         implCreateIfNeeded();
         impl.close();
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index d59fa6a..b35d61c 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -381,6 +381,11 @@
         return (setEnableApn(mApnType, false) != PhoneConstants.APN_REQUEST_FAILED);
     }
 
+    @Override
+    public void captivePortalCheckComplete() {
+        // not implemented
+    }
+
     /**
      * Record the detailed state of a network, and if it is a
      * change from the previous state, send a notification to
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 0bc6b58..0b23cb7 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -79,7 +79,9 @@
         /** Access to this network is blocked. */
         BLOCKED,
         /** Link has poor connectivity. */
-        VERIFYING_POOR_LINK
+        VERIFYING_POOR_LINK,
+        /** Checking if network is a captive portal */
+        CAPTIVE_PORTAL_CHECK,
     }
 
     /**
@@ -97,6 +99,7 @@
         stateMap.put(DetailedState.AUTHENTICATING, State.CONNECTING);
         stateMap.put(DetailedState.OBTAINING_IPADDR, State.CONNECTING);
         stateMap.put(DetailedState.VERIFYING_POOR_LINK, State.CONNECTING);
+        stateMap.put(DetailedState.CAPTIVE_PORTAL_CHECK, State.CONNECTING);
         stateMap.put(DetailedState.CONNECTED, State.CONNECTED);
         stateMap.put(DetailedState.SUSPENDED, State.SUSPENDED);
         stateMap.put(DetailedState.DISCONNECTING, State.DISCONNECTING);
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 07bfd4b..2cd1f9b 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -26,6 +26,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.Signature;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.text.format.Time;
 
 import com.google.android.collect.Sets;
@@ -72,29 +73,29 @@
     }
 
     /**
-     * Set policy flags for specific application.
+     * Set policy flags for specific UID.
      *
      * @param policy {@link #POLICY_NONE} or combination of flags like
      *            {@link #POLICY_REJECT_METERED_BACKGROUND}.
      */
-    public void setAppPolicy(int appId, int policy) {
+    public void setUidPolicy(int uid, int policy) {
         try {
-            mService.setAppPolicy(appId, policy);
+            mService.setUidPolicy(uid, policy);
         } catch (RemoteException e) {
         }
     }
 
-    public int getAppPolicy(int appId) {
+    public int getUidPolicy(int uid) {
         try {
-            return mService.getAppPolicy(appId);
+            return mService.getUidPolicy(uid);
         } catch (RemoteException e) {
             return POLICY_NONE;
         }
     }
 
-    public int[] getAppsWithPolicy(int policy) {
+    public int[] getUidsWithPolicy(int policy) {
         try {
-            return mService.getAppsWithPolicy(policy);
+            return mService.getUidsWithPolicy(policy);
         } catch (RemoteException e) {
             return new int[0];
         }
@@ -236,8 +237,7 @@
     @Deprecated
     public static boolean isUidValidForPolicy(Context context, int uid) {
         // first, quick-reject non-applications
-        if (uid < android.os.Process.FIRST_APPLICATION_UID
-                || uid > android.os.Process.LAST_APPLICATION_UID) {
+        if (!UserHandle.isApp(uid)) {
             return false;
         }
 
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
index 0d6dcd6..0a0c1e0 100644
--- a/core/java/android/net/NetworkStateTracker.java
+++ b/core/java/android/net/NetworkStateTracker.java
@@ -41,12 +41,6 @@
      * -------------------------------------------------------------
      */
 
-    // Share the event space with ConnectivityService (which we can't see, but
-    // must send events to).  If you change these, change ConnectivityService
-    // too.
-    static final int MIN_NETWORK_STATE_TRACKER_EVENT = 1;
-    static final int MAX_NETWORK_STATE_TRACKER_EVENT = 100;
-
     /**
      * The network state has changed and the NetworkInfo object
      * contains the new state.
@@ -129,6 +123,11 @@
     public boolean reconnect();
 
     /**
+     * Ready to switch on to the network after captive portal check
+     */
+    public void captivePortalCheckComplete();
+
+    /**
      * Turn the wireless radio off for a network.
      * @param turnOn {@code true} to turn the radio on, {@code false}
      */
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index fb7a4f8..446bbf0 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -21,6 +21,7 @@
 import android.os.SystemClock;
 import android.util.SparseBooleanArray;
 
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Objects;
 
 import java.io.CharArrayWriter;
@@ -608,13 +609,13 @@
      * Return all rows except those attributed to the requested UID; doesn't
      * mutate the original structure.
      */
-    public NetworkStats withoutUid(int uid) {
+    public NetworkStats withoutUids(int[] uids) {
         final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
 
         Entry entry = new Entry();
         for (int i = 0; i < size; i++) {
             entry = getValues(i, entry);
-            if (entry.uid != uid) {
+            if (!ArrayUtils.contains(uids, entry.uid)) {
                 stats.addValues(entry);
             }
         }
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index a37c26f9..382b25e 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -177,6 +177,12 @@
                 throw new ProtocolException("unexpected version: " + version);
             }
         }
+
+        if (bucketStart.length != bucketCount || rxBytes.length != bucketCount
+                || rxPackets.length != bucketCount || txBytes.length != bucketCount
+                || txPackets.length != bucketCount || operations.length != bucketCount) {
+            throw new ProtocolException("Mismatched history lengths");
+        }
     }
 
     public void writeToStream(DataOutputStream out) throws IOException {
diff --git a/core/java/android/net/ParseException.java b/core/java/android/net/ParseException.java
index 000fa68..68b209b 100644
--- a/core/java/android/net/ParseException.java
+++ b/core/java/android/net/ParseException.java
@@ -17,10 +17,9 @@
 package android.net;
 
 /**
- * 
- *
- * When WebAddress Parser Fails, this exception is thrown
+ * Thrown when parsing a URL fails.
  */
+// See non-public class {@link WebAddress}.
 public class ParseException extends RuntimeException {
     public String response;
 
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index 2703f1d..846443d 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -21,6 +21,7 @@
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.Socket;
+import java.net.SocketException;
 import java.security.KeyManagementException;
 import java.security.cert.X509Certificate;
 import javax.net.SocketFactory;
@@ -300,9 +301,10 @@
      * null if no protocol was negotiated.
      *
      * @param socket a socket created by this factory.
+     * @throws IllegalArgumentException if the socket was not created by this factory.
      */
     public byte[] getNpnSelectedProtocol(Socket socket) {
-        return ((OpenSSLSocketImpl) socket).getNpnSelectedProtocol();
+        return castToOpenSSLSocket(socket).getNpnSelectedProtocol();
     }
 
     /**
@@ -316,6 +318,54 @@
         mInsecureFactory = null;
     }
 
+    /**
+     * Enables <a href="http://tools.ietf.org/html/rfc5077#section-3.2">session ticket</a>
+     * support on the given socket.
+     *
+     * @param socket a socket created by this factory
+     * @param useSessionTickets {@code true} to enable session ticket support on this socket.
+     * @throws IllegalArgumentException if the socket was not created by this factory.
+     */
+    public void setUseSessionTickets(Socket socket, boolean useSessionTickets) {
+        castToOpenSSLSocket(socket).setUseSessionTickets(useSessionTickets);
+    }
+
+    /**
+     * Turns on <a href="http://tools.ietf.org/html/rfc6066#section-3">Server
+     * Name Indication (SNI)</a> on a given socket.
+     *
+     * @param socket a socket created by this factory.
+     * @param hostName the desired SNI hostname, null to disable.
+     * @throws IllegalArgumentException if the socket was not created by this factory.
+     */
+    public void setHostname(Socket socket, String hostName) {
+        castToOpenSSLSocket(socket).setHostname(hostName);
+    }
+
+    /**
+     * Sets this socket's SO_SNDTIMEO write timeout in milliseconds.
+     * Use 0 for no timeout.
+     * To take effect, this option must be set before the blocking method was called.
+     *
+     * @param socket a socket created by this factory.
+     * @param timeout the desired write timeout in milliseconds.
+     * @throws IllegalArgumentException if the socket was not created by this factory.
+     *
+     * @hide
+     */
+    public void setSoWriteTimeout(Socket socket, int writeTimeoutMilliseconds)
+            throws SocketException {
+        castToOpenSSLSocket(socket).setSoWriteTimeout(writeTimeoutMilliseconds);
+    }
+
+    private static OpenSSLSocketImpl castToOpenSSLSocket(Socket socket) {
+        if (!(socket instanceof OpenSSLSocketImpl)) {
+            throw new IllegalArgumentException("Socket not created by this factory: "
+                    + socket);
+        }
+
+        return (OpenSSLSocketImpl) socket;
+    }
 
     /**
      * {@inheritDoc}
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index 3b990e3..cc6903d 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -16,10 +16,13 @@
 
 package android.net;
 
+import android.os.Environment;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.Environment.UserEnvironment;
 import android.util.Log;
 import java.io.File;
+import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
 import java.nio.charset.Charsets;
@@ -2288,4 +2291,39 @@
         builder = builder.appendEncodedPath(pathSegment);
         return builder.build();
     }
+
+    /**
+     * If this {@link Uri} is {@code file://}, then resolve and return its
+     * canonical path. Also fixes legacy emulated storage paths so they are
+     * usable across user boundaries. Should always be called from the app
+     * process before sending elsewhere.
+     *
+     * @hide
+     */
+    public Uri getCanonicalUri() {
+        if ("file".equals(getScheme())) {
+            final String canonicalPath;
+            try {
+                canonicalPath = new File(getPath()).getCanonicalPath();
+            } catch (IOException e) {
+                return this;
+            }
+
+            if (Environment.isExternalStorageEmulated()) {
+                final String legacyPath = Environment.getLegacyExternalStorageDirectory()
+                        .toString();
+
+                // Splice in user-specific path when legacy path is found
+                if (canonicalPath.startsWith(legacyPath)) {
+                    return Uri.fromFile(new File(
+                            Environment.getExternalStorageDirectory().toString(),
+                            canonicalPath.substring(legacyPath.length() + 1)));
+                }
+            }
+
+            return Uri.fromFile(new File(canonicalPath));
+        } else {
+            return this;
+        }
+    }
 }
diff --git a/core/java/android/net/arp/ArpPeer.java b/core/java/android/net/arp/ArpPeer.java
index 6ba1e7c..2013b11 100644
--- a/core/java/android/net/arp/ArpPeer.java
+++ b/core/java/android/net/arp/ArpPeer.java
@@ -16,8 +16,12 @@
 
 package android.net.arp;
 
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.RouteInfo;
 import android.os.SystemClock;
 import android.util.Log;
+
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.Inet6Address;
@@ -35,6 +39,8 @@
  * @hide
  */
 public class ArpPeer {
+    private static final boolean DBG = false;
+    private static final String TAG = "ArpPeer";
     private String mInterfaceName;
     private final InetAddress mMyAddr;
     private final byte[] mMyMac = new byte[6];
@@ -46,7 +52,6 @@
     private static final int ARP_LENGTH = 28;
     private static final int MAC_ADDR_LENGTH = 6;
     private static final int IPV4_LENGTH = 4;
-    private static final String TAG = "ArpPeer";
 
     public ArpPeer(String interfaceName, InetAddress myAddr, String mac,
                    InetAddress peer) throws SocketException {
@@ -125,6 +130,41 @@
         return null;
     }
 
+    public static boolean doArp(String myMacAddress, LinkProperties linkProperties,
+            int timeoutMillis, int numArpPings, int minArpResponses) {
+        String interfaceName = linkProperties.getInterfaceName();
+        InetAddress inetAddress = null;
+        InetAddress gateway = null;
+        boolean success;
+
+        for (LinkAddress la : linkProperties.getLinkAddresses()) {
+            inetAddress = la.getAddress();
+            break;
+        }
+
+        for (RouteInfo route : linkProperties.getRoutes()) {
+            gateway = route.getGateway();
+            break;
+        }
+
+        try {
+            ArpPeer peer = new ArpPeer(interfaceName, inetAddress, myMacAddress, gateway);
+            int responses = 0;
+            for (int i=0; i < numArpPings; i++) {
+                if(peer.doArp(timeoutMillis) != null) responses++;
+            }
+            if (DBG) Log.d(TAG, "ARP test result: " + responses + "/" + numArpPings);
+            success = (responses >= minArpResponses);
+            peer.close();
+        } catch (SocketException se) {
+            //Consider an Arp socket creation issue as a successful Arp
+            //test to avoid any wifi connectivity issues
+            Log.e(TAG, "ARP test initiation failure: " + se);
+            success = true;
+        }
+        return success;
+    }
+
     public void close() {
         try {
             mSocket.close();
diff --git a/core/java/android/net/http/CertificateChainValidator.java b/core/java/android/net/http/CertificateChainValidator.java
index 6ad8fe3..f66075d6 100644
--- a/core/java/android/net/http/CertificateChainValidator.java
+++ b/core/java/android/net/http/CertificateChainValidator.java
@@ -168,7 +168,13 @@
         }
 
         try {
-            SSLParametersImpl.getDefaultTrustManager().checkServerTrusted(chain, authType);
+            X509TrustManager x509TrustManager = SSLParametersImpl.getDefaultTrustManager();
+            if (x509TrustManager instanceof TrustManagerImpl) {
+                TrustManagerImpl trustManager = (TrustManagerImpl) x509TrustManager;
+                trustManager.checkServerTrusted(chain, authType, domain);
+            } else {
+                x509TrustManager.checkServerTrusted(chain, authType);
+            }
             return null;  // No errors.
         } catch (GeneralSecurityException e) {
             if (HttpLog.LOGV) {
diff --git a/core/java/android/net/http/X509TrustManagerExtensions.java b/core/java/android/net/http/X509TrustManagerExtensions.java
new file mode 100644
index 0000000..64eacbc
--- /dev/null
+++ b/core/java/android/net/http/X509TrustManagerExtensions.java
@@ -0,0 +1,66 @@
+/*
+ * 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.net.http;
+
+import org.apache.harmony.xnet.provider.jsse.TrustManagerImpl;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * X509TrustManager wrapper exposing Android-added features.
+ *
+ * <p> The checkServerTrusted method allows callers to perform additional
+ * verification of certificate chains after they have been successfully
+ * verified by the platform.</p>
+ */
+public class X509TrustManagerExtensions {
+
+    TrustManagerImpl mDelegate;
+
+    /**
+     * Constructs a new X509TrustManagerExtensions wrapper.
+     *
+     * @param tm A {@link X509TrustManager} as returned by TrustManagerFactory.getInstance();
+     * @throws IllegalArgumentException If tm is an unsupported TrustManager type.
+     */
+    public X509TrustManagerExtensions(X509TrustManager tm) throws IllegalArgumentException {
+        if (tm instanceof TrustManagerImpl) {
+            mDelegate = (TrustManagerImpl) tm;
+        } else {
+            throw new IllegalArgumentException("tm is not a supported type of X509TrustManager");
+        }
+    }
+
+    /**
+     * Verifies the given certificate chain.
+     *
+     * <p>See {@link X509TrustManager#checkServerTrusted(X509Certificate[], String)} for a
+     * description of the chain and authType parameters. The final parameter, host, should be the
+     * hostname of the server.</p>
+     *
+     * @throws CertificateException if the chain does not verify correctly.
+     * @return the properly ordered chain used for verification as a list of X509Certificates.
+     */
+    public List<X509Certificate> checkServerTrusted(X509Certificate[] chain, String authType,
+                                                    String host) throws CertificateException {
+        return mDelegate.checkServerTrusted(chain, authType, host);
+    }
+}
diff --git a/core/java/android/nfc/INfcAdapterExtras.aidl b/core/java/android/nfc/INfcAdapterExtras.aidl
index 2b9d4f0..41ebf63 100644
--- a/core/java/android/nfc/INfcAdapterExtras.aidl
+++ b/core/java/android/nfc/INfcAdapterExtras.aidl
@@ -29,4 +29,5 @@
     int getCardEmulationRoute(in String pkg);
     void setCardEmulationRoute(in String pkg, int route);
     void authenticate(in String pkg, in byte[] token);
+    String getDriverName(in String pkg);
 }
diff --git a/core/java/android/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index ed1c5b3..2d9dae9 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -688,7 +688,8 @@
                         }
                     } catch (FormatException e) {  }
                 } else if (Arrays.equals(mType, RTD_URI)) {
-                    return parseWktUri().normalizeScheme();
+                    Uri wktUri = parseWktUri();
+                    return (wktUri != null ? wktUri.normalizeScheme() : null);
                 }
                 break;
 
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index f9b765cb..f2cd232 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -24,6 +24,7 @@
 import android.nfc.tech.NdefFormatable;
 import android.nfc.tech.NfcA;
 import android.nfc.tech.NfcB;
+import android.nfc.tech.NfcBarcode;
 import android.nfc.tech.NfcF;
 import android.nfc.tech.NfcV;
 import android.nfc.tech.TagTechnology;
@@ -184,6 +185,9 @@
                 case TagTechnology.NFC_V:
                     strings[i] = NfcV.class.getName();
                     break;
+                case TagTechnology.NFC_BARCODE:
+                    strings[i] = NfcBarcode.class.getName();
+                    break;
                 default:
                     throw new IllegalArgumentException("Unknown tech type " + techList[i]);
             }
diff --git a/core/java/android/nfc/tech/Ndef.java b/core/java/android/nfc/tech/Ndef.java
index a31cb9c..64aa2996 100644
--- a/core/java/android/nfc/tech/Ndef.java
+++ b/core/java/android/nfc/tech/Ndef.java
@@ -140,8 +140,8 @@
      *
      * <p>Does not cause any RF activity and does not block.
      *
-     * @param tag an MIFARE Classic compatible tag
-     * @return MIFARE Classic object
+     * @param tag an NDEF compatible tag
+     * @return Ndef object
      */
     public static Ndef get(Tag tag) {
         if (!tag.hasTech(TagTechnology.NDEF)) return null;
diff --git a/core/java/android/nfc/tech/NfcBarcode.java b/core/java/android/nfc/tech/NfcBarcode.java
new file mode 100644
index 0000000..3149857
--- /dev/null
+++ b/core/java/android/nfc/tech/NfcBarcode.java
@@ -0,0 +1,102 @@
+/*
+ * 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.nfc.tech;
+
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+/**
+ * Provides access to tags containing just a barcode.
+ *
+ * <p>Acquire an {@link NfcBarcode} object using {@link #get}.
+ *
+ */
+public final class NfcBarcode extends BasicTagTechnology {
+
+    /** Kovio Tags */
+    public static final int TYPE_KOVIO = 1;
+    public static final int TYPE_UNKNOWN = -1;
+
+    /** @hide */
+    public static final String EXTRA_BARCODE_TYPE = "barcodetype";
+
+    private int mType;
+
+    /**
+     * Get an instance of {@link NfcBarcode} for the given tag.
+     *
+     * <p>Returns null if {@link NfcBarcode} was not enumerated in {@link Tag#getTechList}.
+     *
+     * <p>Does not cause any RF activity and does not block.
+     *
+     * @param tag an NfcBarcode compatible tag
+     * @return NfcBarcode object
+     */
+    public static NfcBarcode get(Tag tag) {
+        if (!tag.hasTech(TagTechnology.NFC_BARCODE)) return null;
+        try {
+            return new NfcBarcode(tag);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Internal constructor, to be used by NfcAdapter
+     * @hide
+     */
+    public NfcBarcode(Tag tag) throws RemoteException {
+        super(tag, TagTechnology.NFC_BARCODE);
+        Bundle extras = tag.getTechExtras(TagTechnology.NFC_BARCODE);
+        if (extras != null) {
+            mType = extras.getInt(EXTRA_BARCODE_TYPE);
+        } else {
+            throw new NullPointerException("NfcBarcode tech extras are null.");
+        }
+    }
+
+    /**
+     * Returns the NFC Barcode tag type.
+     *
+     * <p>Currently only one of {@link #TYPE_KOVIO} or {@link #TYPE_UNKNOWN}.
+     *
+     * <p>Does not cause any RF activity and does not block.
+     *
+     * @return the NFC Barcode tag type
+     */
+    public int getType() {
+        return mType;
+    }
+
+    /**
+     * Returns the barcode of an NfcBarcode tag.
+     *
+     * <p>Does not cause any RF activity and does not block.
+     *
+     * @return a byte array containing the barcode
+     */
+    public byte[] getBarcode() {
+        switch (mType) {
+            case TYPE_KOVIO:
+                // For Kovio tags the barcode matches the ID
+                return mTag.getId();
+            default:
+                return null;
+        }
+    }
+}
diff --git a/core/java/android/nfc/tech/TagTechnology.java b/core/java/android/nfc/tech/TagTechnology.java
index be5cbd2..3493ea7 100644
--- a/core/java/android/nfc/tech/TagTechnology.java
+++ b/core/java/android/nfc/tech/TagTechnology.java
@@ -148,6 +148,15 @@
     public static final int MIFARE_ULTRALIGHT = 9;
 
     /**
+     * This technology is an instance of {@link NfcBarcode}.
+     * <p>Support for this technology type is optional. If a stack doesn't support this technology
+     * type tags using it must still be discovered and present the lower level radio interface
+     * technologies in use.
+     * @hide
+     */
+    public static final int NFC_BARCODE = 10;
+
+    /**
      * Get the {@link Tag} object backing this {@link TagTechnology} object.
      * @return the {@link Tag} backing this {@link TagTechnology} object.
      */
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index 69e1de9..ce5f163 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -110,7 +110,7 @@
  * <h2>The 4 steps</h2>
  * <p>When an asynchronous task is executed, the task goes through 4 steps:</p>
  * <ol>
- *     <li>{@link #onPreExecute()}, invoked on the UI thread immediately after the task
+ *     <li>{@link #onPreExecute()}, invoked on the UI thread before the task
  *     is executed. This step is normally used to setup the task, for instance by
  *     showing a progress bar in the user interface.</li>
  *     <li>{@link #doInBackground}, invoked on the background thread
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index c62715b..2e38960 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -115,4 +115,10 @@
     public static final int BATTERY_PLUGGED_AC = 1;
     /** Power source is a USB port. */
     public static final int BATTERY_PLUGGED_USB = 2;
+    /** Power source is wireless. */
+    public static final int BATTERY_PLUGGED_WIRELESS = 4;
+
+    /** @hide */
+    public static final int BATTERY_PLUGGED_ANY =
+            BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS;
 }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 438c536..54f2fe3 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -71,9 +71,9 @@
     public static final int FULL_WIFI_LOCK = 5;
     
     /**
-     * A constant indicating a scan wifi lock timer
+     * A constant indicating a wifi scan
      */
-    public static final int SCAN_WIFI_LOCK = 6;
+    public static final int WIFI_SCAN = 6;
 
      /**
       * A constant indicating a wifi multicast timer
@@ -136,7 +136,7 @@
     private static final String BATTERY_DATA = "bt";
     private static final String BATTERY_DISCHARGE_DATA = "dc";
     private static final String BATTERY_LEVEL_DATA = "lv";
-    private static final String WIFI_LOCK_DATA = "wfl";
+    private static final String WIFI_DATA = "wfl";
     private static final String MISC_DATA = "m";
     private static final String SCREEN_BRIGHTNESS_DATA = "br";
     private static final String SIGNAL_STRENGTH_TIME_DATA = "sgt";
@@ -260,8 +260,8 @@
         public abstract void noteWifiStoppedLocked();
         public abstract void noteFullWifiLockAcquiredLocked();
         public abstract void noteFullWifiLockReleasedLocked();
-        public abstract void noteScanWifiLockAcquiredLocked();
-        public abstract void noteScanWifiLockReleasedLocked();
+        public abstract void noteWifiScanStartedLocked();
+        public abstract void noteWifiScanStoppedLocked();
         public abstract void noteWifiMulticastEnabledLocked();
         public abstract void noteWifiMulticastDisabledLocked();
         public abstract void noteAudioTurnedOnLocked();
@@ -270,20 +270,22 @@
         public abstract void noteVideoTurnedOffLocked();
         public abstract long getWifiRunningTime(long batteryRealtime, int which);
         public abstract long getFullWifiLockTime(long batteryRealtime, int which);
-        public abstract long getScanWifiLockTime(long batteryRealtime, int which);
+        public abstract long getWifiScanTime(long batteryRealtime, int which);
         public abstract long getWifiMulticastTime(long batteryRealtime,
                                                   int which);
         public abstract long getAudioTurnedOnTime(long batteryRealtime, int which);
         public abstract long getVideoTurnedOnTime(long batteryRealtime, int which);
 
         /**
-         * Note that these must match the constants in android.os.LocalPowerManager.
+         * Note that these must match the constants in android.os.PowerManager.
+         * Also, if the user activity types change, the BatteryStatsImpl.VERSION must
+         * also be bumped.
          */
         static final String[] USER_ACTIVITY_TYPES = {
-            "other", "cheek", "touch", "long_touch", "touch_up", "button", "unknown"
+            "other", "button", "touch"
         };
         
-        public static final int NUM_USER_ACTIVITY_TYPES = 7;
+        public static final int NUM_USER_ACTIVITY_TYPES = 3;
         
         public abstract void noteUserActivityLocked(int type);
         public abstract boolean hasUserActivity();
@@ -453,7 +455,7 @@
         public static final int STATE_PHONE_SCANNING_FLAG = 1<<27;
         public static final int STATE_WIFI_RUNNING_FLAG = 1<<26;
         public static final int STATE_WIFI_FULL_LOCK_FLAG = 1<<25;
-        public static final int STATE_WIFI_SCAN_LOCK_FLAG = 1<<24;
+        public static final int STATE_WIFI_SCAN_FLAG = 1<<24;
         public static final int STATE_WIFI_MULTICAST_ON_FLAG = 1<<23;
         // These are on the lower bits used for the command; if they change
         // we need to write another int of data.
@@ -859,7 +861,7 @@
         new BitDescription(HistoryItem.STATE_WIFI_ON_FLAG, "wifi"),
         new BitDescription(HistoryItem.STATE_WIFI_RUNNING_FLAG, "wifi_running"),
         new BitDescription(HistoryItem.STATE_WIFI_FULL_LOCK_FLAG, "wifi_full_lock"),
-        new BitDescription(HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG, "wifi_scan_lock"),
+        new BitDescription(HistoryItem.STATE_WIFI_SCAN_FLAG, "wifi_scan"),
         new BitDescription(HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG, "wifi_multicast"),
         new BitDescription(HistoryItem.STATE_BLUETOOTH_ON_FLAG, "bluetooth"),
         new BitDescription(HistoryItem.STATE_AUDIO_ON_FLAG, "audio"),
@@ -1326,15 +1328,15 @@
             long rx = u.getTcpBytesReceived(which);
             long tx = u.getTcpBytesSent(which);
             long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
-            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
+            long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
             long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
             
             if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
             
-            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
+            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
                     || uidWifiRunningTime != 0) {
-                dumpLine(pw, uid, category, WIFI_LOCK_DATA, 
-                        fullWifiLockOnTime, scanWifiLockOnTime, uidWifiRunningTime);
+                dumpLine(pw, uid, category, WIFI_DATA,
+                        fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime);
             }
 
             if (u.hasUserActivity()) {
@@ -1692,7 +1694,7 @@
             long tcpReceived = u.getTcpBytesReceived(which);
             long tcpSent = u.getTcpBytesSent(which);
             long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
-            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
+            long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
             long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
             
             if (tcpReceived != 0 || tcpSent != 0) {
@@ -1703,7 +1705,7 @@
             
             if (u.hasUserActivity()) {
                 boolean hasData = false;
-                for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
+                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
                     int val = u.getUserActivityCount(i, which);
                     if (val != 0) {
                         if (!hasData) {
@@ -1723,7 +1725,7 @@
                 }
             }
             
-            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
+            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
                     || uidWifiRunningTime != 0) {
                 sb.setLength(0);
                 sb.append(prefix); sb.append("    Wifi Running: ");
@@ -1731,12 +1733,12 @@
                         sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
                                 whichBatteryRealtime)); sb.append(")\n");
                 sb.append(prefix); sb.append("    Full Wifi Lock: "); 
-                        formatTimeMs(sb, fullWifiLockOnTime / 1000); 
-                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime, 
+                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
+                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
                                 whichBatteryRealtime)); sb.append(")\n");
-                sb.append(prefix); sb.append("    Scan Wifi Lock: "); 
-                        formatTimeMs(sb, scanWifiLockOnTime / 1000);
-                        sb.append("("); sb.append(formatRatioLocked(scanWifiLockOnTime, 
+                sb.append(prefix); sb.append("    Wifi Scan: ");
+                        formatTimeMs(sb, wifiScanTime / 1000);
+                        sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
                                 whichBatteryRealtime)); sb.append(")");
                 pw.println(sb.toString());
             }
@@ -2069,6 +2071,9 @@
                         case BatteryManager.BATTERY_PLUGGED_USB:
                             pw.print("usb");
                             break;
+                        case BatteryManager.BATTERY_PLUGGED_WIRELESS:
+                            pw.print("wireless");
+                            break;
                         default:
                             pw.print(oldPlug);
                             break;
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 7b51119..16b4835 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -64,7 +64,7 @@
     public static final native int getCallingPid();
     
     /**
-     * Return the ID of the user assigned to the process that sent you the
+     * Return the Linux uid assigned to the process that sent you the
      * current transaction that is being processed.  This uid can be used with
      * higher-level system services to determine its identity and check
      * permissions.  If the current thread is not currently executing an
@@ -73,31 +73,15 @@
     public static final native int getCallingUid();
 
     /**
-     * Return the original ID of the user assigned to the process that sent you the current
-     * transaction that is being processed. This uid can be used with higher-level system services
-     * to determine its identity and check permissions. If the current thread is not currently
-     * executing an incoming transaction, then its own uid is returned.
-     * <p/>
-     * This value cannot be reset by calls to {@link #clearCallingIdentity()}.
-     * @hide
+     * Return the UserHandle assigned to the process that sent you the
+     * current transaction that is being processed.  This is the user
+     * of the caller.  It is distinct from {@link #getCallingUid()} in that a
+     * particular user will have multiple distinct apps running under it each
+     * with their own uid.  If the current thread is not currently executing an
+     * incoming transaction, then its own UserHandle is returned.
      */
-    public static final int getOrigCallingUid() {
-        if (UserId.MU_ENABLED) {
-            return getOrigCallingUidNative();
-        } else {
-            return getCallingUid();
-        }
-    }
-
-    private static final native int getOrigCallingUidNative();
-
-    /**
-     * Utility function to return the user id of the calling process.
-     * @return userId of the calling process, extracted from the callingUid
-     * @hide
-     */
-    public static final int getOrigCallingUser() {
-        return UserId.getUserId(getOrigCallingUid());
+    public static final UserHandle getCallingUserHandle() {
+        return new UserHandle(UserHandle.getUserId(getCallingUid()));
     }
 
     /**
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 8ec0c69..a7f39d5 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -370,7 +370,7 @@
         public static final int ICE_CREAM_SANDWICH_MR1 = 15;
 
         /**
-         * Android 4.1.
+         * June 2012: Android 4.1.
          *
          * <p>Applications targeting this or a later release will get these
          * new changes in behavior:</p>
@@ -411,6 +411,26 @@
          * </ul>
          */
         public static final int JELLY_BEAN = 16;
+
+        /**
+         * Android 4.2: Moar jelly beans!
+         *
+         * <p>Applications targeting this or a later release will get these
+         * new changes in behavior:</p>
+         * <ul>
+         * <li>Content Providers: The default value of {@code android:exported} is now
+         * {@code false}. See
+         * <a href="{@docRoot}guide/topics/manifest/provider-element.html#exported">
+         * the android:exported section</a> in the provider documentation for more details.</li>
+         * <li>{@link android.view.View#getLayoutDirection() View.getLayoutDirection()}
+         * can return different values than {@link android.view.View#LAYOUT_DIRECTION_LTR}
+         * based on the locale etc.
+         * <li> {@link android.webkit.WebView#addJavascriptInterface(Object, String)
+         * WebView.addJavascriptInterface} requires explicit annotations on methods
+         * for them to be accessible from Javascript.
+         * </ul>
+         */
+        public static final int JELLY_BEAN_MR1 = 17;
     }
     
     /** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 591cd0e..e50c948 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -95,7 +95,7 @@
      * Default trace file path and file
      */
     private static final String DEFAULT_TRACE_PATH_PREFIX =
-        Environment.getExternalStorageDirectory().getPath() + "/";
+        Environment.getLegacyExternalStorageDirectory().getPath() + "/";
     private static final String DEFAULT_TRACE_BODY = "dmtrace";
     private static final String DEFAULT_TRACE_EXTENSION = ".trace";
     private static final String DEFAULT_TRACE_FILE_PATH =
@@ -1363,6 +1363,23 @@
     }
 
     /**
+     * Like {@link #getCallers(int)}, but each location is append to the string
+     * as a new line with <var>linePrefix</var> in front of it.
+     * @param depth the number of levels to return, starting with the immediate caller.
+     * @param linePrefix prefix to put in front of each location.
+     * @return a string describing the call stack.
+     * {@hide}
+     */
+    public static String getCallers(final int depth, String linePrefix) {
+        final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < depth; i++) {
+            sb.append(linePrefix).append(getCaller(callStack, i)).append("\n");
+        }
+        return sb.toString();
+    }
+
+    /**
      * @return a String describing the immediate caller of the calling function.
      * {@hide}
      */
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 679cf1a..88529f8 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -16,9 +16,10 @@
 
 package android.os;
 
-import android.content.res.Resources;
 import android.os.storage.IMountService;
+import android.os.storage.StorageManager;
 import android.os.storage.StorageVolume;
+import android.text.TextUtils;
 import android.util.Log;
 
 import java.io.File;
@@ -29,31 +30,146 @@
 public class Environment {
     private static final String TAG = "Environment";
 
+    private static final String ENV_EXTERNAL_STORAGE = "EXTERNAL_STORAGE";
+    private static final String ENV_EMULATED_STORAGE_SOURCE = "EMULATED_STORAGE_SOURCE";
+    private static final String ENV_EMULATED_STORAGE_TARGET = "EMULATED_STORAGE_TARGET";
+    private static final String ENV_MEDIA_STORAGE = "MEDIA_STORAGE";
+
+    /** {@hide} */
+    public static String DIRECTORY_ANDROID = "Android";
+
     private static final File ROOT_DIRECTORY
             = getDirectory("ANDROID_ROOT", "/system");
 
     private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
 
-    private static final Object mLock = new Object();
+    private static UserEnvironment sCurrentUser;
 
-    private volatile static StorageVolume mPrimaryVolume = null;
+    private static final Object sLock = new Object();
+
+    // @GuardedBy("sLock")
+    private static volatile StorageVolume sPrimaryVolume;
 
     private static StorageVolume getPrimaryVolume() {
-        if (mPrimaryVolume == null) {
-            synchronized (mLock) {
-                if (mPrimaryVolume == null) {
+        if (sPrimaryVolume == null) {
+            synchronized (sLock) {
+                if (sPrimaryVolume == null) {
                     try {
                         IMountService mountService = IMountService.Stub.asInterface(ServiceManager
                                 .getService("mount"));
-                        Parcelable[] volumes = mountService.getVolumeList();
-                        mPrimaryVolume = (StorageVolume)volumes[0];
+                        final StorageVolume[] volumes = mountService.getVolumeList();
+                        sPrimaryVolume = StorageManager.getPrimaryVolume(volumes);
                     } catch (Exception e) {
                         Log.e(TAG, "couldn't talk to MountService", e);
                     }
                 }
             }
         }
-        return mPrimaryVolume;
+        return sPrimaryVolume;
+    }
+
+    static {
+        initForCurrentUser();
+    }
+
+    /** {@hide} */
+    public static void initForCurrentUser() {
+        final int userId = UserHandle.myUserId();
+        sCurrentUser = new UserEnvironment(userId);
+
+        synchronized (sLock) {
+            sPrimaryVolume = null;
+        }
+    }
+
+    /** {@hide} */
+    public static class UserEnvironment {
+        // TODO: generalize further to create package-specific environment
+
+        private final File mExternalStorage;
+        private final File mExternalStorageAndroidData;
+        private final File mExternalStorageAndroidMedia;
+        private final File mExternalStorageAndroidObb;
+        private final File mMediaStorage;
+
+        public UserEnvironment(int userId) {
+            // See storage config details at http://source.android.com/tech/storage/
+            String rawExternalStorage = System.getenv(ENV_EXTERNAL_STORAGE);
+            String rawEmulatedStorageTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET);
+            String rawMediaStorage = System.getenv(ENV_MEDIA_STORAGE);
+            if (TextUtils.isEmpty(rawMediaStorage)) {
+                rawMediaStorage = "/data/media";
+            }
+
+            if (!TextUtils.isEmpty(rawEmulatedStorageTarget)) {
+                // Device has emulated storage; external storage paths should have
+                // userId burned into them.
+                final String rawUserId = Integer.toString(userId);
+                final File emulatedBase = new File(rawEmulatedStorageTarget);
+                final File mediaBase = new File(rawMediaStorage);
+
+                // /storage/emulated/0
+                mExternalStorage = buildPath(emulatedBase, rawUserId);
+                // /data/media/0
+                mMediaStorage = buildPath(mediaBase, rawUserId);
+
+            } else {
+                // Device has physical external storage; use plain paths.
+                if (TextUtils.isEmpty(rawExternalStorage)) {
+                    Log.w(TAG, "EXTERNAL_STORAGE undefined; falling back to default");
+                    rawExternalStorage = "/storage/sdcard0";
+                }
+
+                // /storage/sdcard0
+                mExternalStorage = new File(rawExternalStorage);
+                // /data/media
+                mMediaStorage = new File(rawMediaStorage);
+            }
+
+            mExternalStorageAndroidObb = buildPath(mExternalStorage, DIRECTORY_ANDROID, "obb");
+            mExternalStorageAndroidData = buildPath(mExternalStorage, DIRECTORY_ANDROID, "data");
+            mExternalStorageAndroidMedia = buildPath(mExternalStorage, DIRECTORY_ANDROID, "media");
+        }
+
+        public File getExternalStorageDirectory() {
+            return mExternalStorage;
+        }
+
+        public File getExternalStorageObbDirectory() {
+            return mExternalStorageAndroidObb;
+        }
+
+        public File getExternalStoragePublicDirectory(String type) {
+            return new File(mExternalStorage, type);
+        }
+
+        public File getExternalStorageAndroidDataDir() {
+            return mExternalStorageAndroidData;
+        }
+
+        public File getExternalStorageAppDataDirectory(String packageName) {
+            return new File(mExternalStorageAndroidData, packageName);
+        }
+
+        public File getExternalStorageAppMediaDirectory(String packageName) {
+            return new File(mExternalStorageAndroidMedia, packageName);
+        }
+
+        public File getExternalStorageAppObbDirectory(String packageName) {
+            return new File(mExternalStorageAndroidObb, packageName);
+        }
+
+        public File getExternalStorageAppFilesDirectory(String packageName) {
+            return new File(new File(mExternalStorageAndroidData, packageName), "files");
+        }
+
+        public File getExternalStorageAppCacheDirectory(String packageName) {
+            return new File(new File(mExternalStorageAndroidData, packageName), "cache");
+        }
+
+        public File getMediaStorageDirectory() {
+            return mMediaStorage;
+        }
     }
 
     /**
@@ -100,7 +216,19 @@
      * @hide
      */
     public static File getMediaStorageDirectory() {
-        return MEDIA_STORAGE_DIRECTORY;
+        throwIfSystem();
+        return sCurrentUser.getMediaStorageDirectory();
+    }
+
+    /**
+     * Return the system directory for a user. This is for use by system services to store
+     * files relating to the user. This directory will be automatically deleted when the user
+     * is removed.
+     *
+     * @hide
+     */
+    public static File getUserSystemDirectory(int userId) {
+        return new File(new File(getSystemSecureDirectory(), "users"), Integer.toString(userId));
     }
 
     /**
@@ -122,24 +250,7 @@
     private static final File SECURE_DATA_DIRECTORY
             = getDirectory("ANDROID_SECURE_DATA", "/data/secure");
 
-    /** @hide */
-    private static final File MEDIA_STORAGE_DIRECTORY
-            = getDirectory("MEDIA_STORAGE", "/data/media");
-
-    private static final File EXTERNAL_STORAGE_DIRECTORY
-            = getDirectory("EXTERNAL_STORAGE", "/storage/sdcard0");
-
-    private static final File EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY = new File(new File(
-            getDirectory("EXTERNAL_STORAGE", "/storage/sdcard0"), "Android"), "data");
-
-    private static final File EXTERNAL_STORAGE_ANDROID_MEDIA_DIRECTORY = new File(new File(
-            getDirectory("EXTERNAL_STORAGE", "/storage/sdcard0"), "Android"), "media");
-
-    private static final File EXTERNAL_STORAGE_ANDROID_OBB_DIRECTORY = new File(new File(
-            getDirectory("EXTERNAL_STORAGE", "/storage/sdcard0"), "Android"), "obb");
-
-    private static final File DOWNLOAD_CACHE_DIRECTORY
-            = getDirectory("DOWNLOAD_CACHE", "/cache");
+    private static final File DOWNLOAD_CACHE_DIRECTORY = getDirectory("DOWNLOAD_CACHE", "/cache");
 
     /**
      * Gets the Android data directory.
@@ -163,6 +274,10 @@
      * built-in storage in a device that is distinct from the protected
      * internal storage and can be mounted as a filesystem on a computer.</em></p>
      *
+     * <p>On devices with multiple users (as described by {@link UserManager}),
+     * each user has their own isolated external storage. Applications only
+     * have access to the external storage for the user they're running as.</p>
+     *
      * <p>In devices with multiple "external" storage directories (such as
      * both secure app storage and mountable shared storage), this directory
      * represents the "primary" external storage that the user will interact
@@ -175,7 +290,16 @@
      * Context.getExternalFilesDir}, which the system will take care of deleting
      * if the application is uninstalled.  Other shared files should be placed
      * in one of the directories returned by
-     * {@link #getExternalStoragePublicDirectory}.
+     * {@link #getExternalStoragePublicDirectory}.</p>
+     *
+     * <p>Writing to this path requires the
+     * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permission. In
+     * a future platform release, access to this path will require the
+     * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission,
+     * which is automatically granted if you hold the write permission.</p>
+     *
+     * <p>This path may change between platform versions, so applications
+     * should only persist relative paths.</p>
      * 
      * <p>Here is an example of typical code to monitor the state of
      * external storage:</p>
@@ -187,7 +311,30 @@
      * @see #isExternalStorageRemovable()
      */
     public static File getExternalStorageDirectory() {
-        return EXTERNAL_STORAGE_DIRECTORY;
+        throwIfSystem();
+        return sCurrentUser.getExternalStorageDirectory();
+    }
+
+    /** {@hide} */
+    public static File getLegacyExternalStorageDirectory() {
+        return new File(System.getenv(ENV_EXTERNAL_STORAGE));
+    }
+
+    /** {@hide} */
+    public static File getLegacyExternalStorageObbDirectory() {
+        return buildPath(getLegacyExternalStorageDirectory(), DIRECTORY_ANDROID, "obb");
+    }
+
+    /** {@hide} */
+    public static File getEmulatedStorageSource(int userId) {
+        // /mnt/shell/emulated/0
+        return new File(System.getenv(ENV_EMULATED_STORAGE_SOURCE), String.valueOf(userId));
+    }
+
+    /** {@hide} */
+    public static File getEmulatedStorageObbSource() {
+        // /mnt/shell/emulated/obb
+        return new File(System.getenv(ENV_EMULATED_STORAGE_SOURCE), "obb");
     }
 
     /**
@@ -289,6 +436,10 @@
      * to ensure you don't erase their files or get in the way of their own
      * organization.
      * 
+     * <p>On devices with multiple users (as described by {@link UserManager}),
+     * each user has their own isolated external storage. Applications only
+     * have access to the external storage for the user they're running as.</p>
+     *
      * <p>Here is an example of typical code to manipulate a picture on
      * the public external storage:</p>
      * 
@@ -307,7 +458,8 @@
      * using it such as with {@link File#mkdirs File.mkdirs()}.
      */
     public static File getExternalStoragePublicDirectory(String type) {
-        return new File(getExternalStorageDirectory(), type);
+        throwIfSystem();
+        return sCurrentUser.getExternalStoragePublicDirectory(type);
     }
 
     /**
@@ -315,7 +467,8 @@
      * @hide
      */
     public static File getExternalStorageAndroidDataDir() {
-        return EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY;
+        throwIfSystem();
+        return sCurrentUser.getExternalStorageAndroidDataDir();
     }
     
     /**
@@ -323,7 +476,8 @@
      * @hide
      */
     public static File getExternalStorageAppDataDirectory(String packageName) {
-        return new File(EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY, packageName);
+        throwIfSystem();
+        return sCurrentUser.getExternalStorageAppDataDirectory(packageName);
     }
     
     /**
@@ -331,7 +485,8 @@
      * @hide
      */
     public static File getExternalStorageAppMediaDirectory(String packageName) {
-        return new File(EXTERNAL_STORAGE_ANDROID_MEDIA_DIRECTORY, packageName);
+        throwIfSystem();
+        return sCurrentUser.getExternalStorageAppMediaDirectory(packageName);
     }
     
     /**
@@ -339,7 +494,8 @@
      * @hide
      */
     public static File getExternalStorageAppObbDirectory(String packageName) {
-        return new File(EXTERNAL_STORAGE_ANDROID_OBB_DIRECTORY, packageName);
+        throwIfSystem();
+        return sCurrentUser.getExternalStorageAppObbDirectory(packageName);
     }
     
     /**
@@ -347,21 +503,21 @@
      * @hide
      */
     public static File getExternalStorageAppFilesDirectory(String packageName) {
-        return new File(new File(EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY,
-                packageName), "files");
+        throwIfSystem();
+        return sCurrentUser.getExternalStorageAppFilesDirectory(packageName);
     }
-    
+
     /**
      * Generates the path to an application's cache.
      * @hide
      */
     public static File getExternalStorageAppCacheDirectory(String packageName) {
-        return new File(new File(EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY,
-                packageName), "cache");
+        throwIfSystem();
+        return sCurrentUser.getExternalStorageAppCacheDirectory(packageName);
     }
     
     /**
-     * Gets the Android Download/Cache content directory.
+     * Gets the Android download/cache content directory.
      */
     public static File getDownloadCacheDirectory() {
         return DOWNLOAD_CACHE_DIRECTORY;
@@ -424,15 +580,16 @@
     /**
      * Gets the current state of the primary "external" storage device.
      * 
-     * <p>See {@link #getExternalStorageDirectory()} for more information.
+     * @see #getExternalStorageDirectory()
      */
     public static String getExternalStorageState() {
         try {
             IMountService mountService = IMountService.Stub.asInterface(ServiceManager
                     .getService("mount"));
-            return mountService.getVolumeState(getExternalStorageDirectory()
-                    .toString());
-        } catch (Exception rex) {
+            final StorageVolume primary = getPrimaryVolume();
+            return mountService.getVolumeState(primary.getPath());
+        } catch (RemoteException rex) {
+            Log.w(TAG, "Failed to read external storage state; assuming REMOVED: " + rex);
             return Environment.MEDIA_REMOVED;
         }
     }
@@ -446,8 +603,8 @@
      * <p>See {@link #getExternalStorageDirectory()} for more information.
      */
     public static boolean isExternalStorageRemovable() {
-        StorageVolume volume = getPrimaryVolume();
-        return (volume != null && volume.isRemovable());
+        final StorageVolume primary = getPrimaryVolume();
+        return (primary != null && primary.isRemovable());
     }
 
     /**
@@ -464,12 +621,30 @@
      * android.content.ComponentName, boolean)} for additional details.
      */
     public static boolean isExternalStorageEmulated() {
-        StorageVolume volume = getPrimaryVolume();
-        return (volume != null && volume.isEmulated());
+        final StorageVolume primary = getPrimaryVolume();
+        return (primary != null && primary.isEmulated());
     }
 
     static File getDirectory(String variableName, String defaultPath) {
         String path = System.getenv(variableName);
         return path == null ? new File(defaultPath) : new File(path);
     }
+
+    private static void throwIfSystem() {
+        if (Process.myUid() == Process.SYSTEM_UID) {
+            Log.wtf(TAG, "Static storage paths aren't available from AID_SYSTEM", new Throwable());
+        }
+    }
+
+    private static File buildPath(File base, String... segments) {
+        File cur = base;
+        for (String segment : segments) {
+            if (cur == null) {
+                cur = new File(segment);
+            } else {
+                cur = new File(cur, segment);
+            }
+        }
+        return cur;
+    }
 }
diff --git a/core/java/android/os/FactoryTest.java b/core/java/android/os/FactoryTest.java
new file mode 100644
index 0000000..ec99697
--- /dev/null
+++ b/core/java/android/os/FactoryTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/**
+ * Provides support for in-place factory test functions.
+ *
+ * This class provides a few properties that alter the normal operation of the system
+ * during factory testing.
+ *
+ * {@hide}
+ */
+public final class FactoryTest {
+    /**
+     * When true, long-press on power should immediately cause the device to
+     * shut down, without prompting the user.
+     */
+    public static boolean isLongPressOnPowerOffEnabled() {
+        return SystemProperties.getInt("factory.long_press_power_off", 0) != 0;
+    }
+}
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 0941d71..2bec1c1 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import java.io.BufferedInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -91,7 +92,7 @@
         }
         return result;
     }
-    
+
     /**
      * Copy data from a source stream to destFile.
      * Return true if succeed, return false if failed.
@@ -143,12 +144,16 @@
      */
     public static String readTextFile(File file, int max, String ellipsis) throws IOException {
         InputStream input = new FileInputStream(file);
+        // wrapping a BufferedInputStream around it because when reading /proc with unbuffered
+        // input stream, bytes read not equal to buffer size is not necessarily the correct
+        // indication for EOF; but it is true for BufferedInputStream due to its implementation.
+        BufferedInputStream bis = new BufferedInputStream(input);
         try {
             long size = file.length();
             if (max > 0 || (size > 0 && max == 0)) {  // "head" mode: read the first N bytes
                 if (size > 0 && (max == 0 || size < max)) max = (int) size;
                 byte[] data = new byte[max + 1];
-                int length = input.read(data);
+                int length = bis.read(data);
                 if (length <= 0) return "";
                 if (length <= max) return new String(data, 0, length);
                 if (ellipsis == null) return new String(data, 0, max);
@@ -161,7 +166,7 @@
                     if (last != null) rolled = true;
                     byte[] tmp = last; last = data; data = tmp;
                     if (data == null) data = new byte[-max];
-                    len = input.read(data);
+                    len = bis.read(data);
                 } while (len == data.length);
 
                 if (last == null && len <= 0) return "";
@@ -178,12 +183,13 @@
                 int len;
                 byte[] data = new byte[1024];
                 do {
-                    len = input.read(data);
+                    len = bis.read(data);
                     if (len > 0) contents.write(data, 0, len);
                 } while (len == data.length);
                 return contents.toString();
             }
         } finally {
+            bis.close();
             input.close();
         }
     }
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index b892c81..94de448 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -101,36 +101,88 @@
     }
 
     /**
-     * Default constructor associates this handler with the queue for the
+     * Default constructor associates this handler with the {@link Looper} for the
      * current thread.
      *
-     * If there isn't one, this handler won't be able to receive messages.
+     * If this thread does not have a looper, this handler won't be able to receive messages
+     * so an exception is thrown.
      */
     public Handler() {
-        if (FIND_POTENTIAL_LEAKS) {
-            final Class<? extends Handler> klass = getClass();
-            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
-                    (klass.getModifiers() & Modifier.STATIC) == 0) {
-                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
-                    klass.getCanonicalName());
-            }
-        }
-
-        mLooper = Looper.myLooper();
-        if (mLooper == null) {
-            throw new RuntimeException(
-                "Can't create handler inside thread that has not called Looper.prepare()");
-        }
-        mQueue = mLooper.mQueue;
-        mCallback = null;
+        this(null, false);
     }
 
     /**
-     * Constructor associates this handler with the queue for the
+     * Constructor associates this handler with the {@link Looper} for the
      * current thread and takes a callback interface in which you can handle
      * messages.
+     *
+     * If this thread does not have a looper, this handler won't be able to receive messages
+     * so an exception is thrown.
+     *
+     * @param callback The callback interface in which to handle messages, or null.
      */
     public Handler(Callback callback) {
+        this(callback, false);
+    }
+
+    /**
+     * Use the provided {@link Looper} instead of the default one.
+     *
+     * @param looper The looper, must not be null.
+     */
+    public Handler(Looper looper) {
+        this(looper, null, false);
+    }
+
+    /**
+     * Use the provided {@link Looper} instead of the default one and take a callback
+     * interface in which to handle messages.
+     *
+     * @param looper The looper, must not be null.
+     * @param callback The callback interface in which to handle messages, or null.
+     */
+    public Handler(Looper looper, Callback callback) {
+        this(looper, callback, false);
+    }
+
+    /**
+     * Use the {@link Looper} for the current thread
+     * and set whether the handler should be asynchronous.
+     *
+     * Handlers are synchronous by default unless this constructor is used to make
+     * one that is strictly asynchronous.
+     *
+     * Asynchronous messages represent interrupts or events that do not require global ordering
+     * with represent to synchronous messages.  Asynchronous messages are not subject to
+     * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
+     *
+     * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
+     * each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
+     *
+     * @hide
+     */
+    public Handler(boolean async) {
+        this(null, async);
+    }
+
+    /**
+     * Use the {@link Looper} for the current thread with the specified callback interface
+     * and set whether the handler should be asynchronous.
+     *
+     * Handlers are synchronous by default unless this constructor is used to make
+     * one that is strictly asynchronous.
+     *
+     * Asynchronous messages represent interrupts or events that do not require global ordering
+     * with represent to synchronous messages.  Asynchronous messages are not subject to
+     * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
+     *
+     * @param callback The callback interface in which to handle messages, or null.
+     * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
+     * each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
+     *
+     * @hide
+     */
+    public Handler(Callback callback, boolean async) {
         if (FIND_POTENTIAL_LEAKS) {
             final Class<? extends Handler> klass = getClass();
             if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
@@ -147,25 +199,33 @@
         }
         mQueue = mLooper.mQueue;
         mCallback = callback;
+        mAsynchronous = async;
     }
 
     /**
-     * Use the provided queue instead of the default one.
+     * Use the provided {@link Looper} instead of the default one and take a callback
+     * interface in which to handle messages.  Also set whether the handler
+     * should be asynchronous.
+     *
+     * Handlers are synchronous by default unless this constructor is used to make
+     * one that is strictly asynchronous.
+     *
+     * Asynchronous messages represent interrupts or events that do not require global ordering
+     * with represent to synchronous messages.  Asynchronous messages are not subject to
+     * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
+     *
+     * @param looper The looper, must not be null.
+     * @param callback The callback interface in which to handle messages, or null.
+     * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
+     * each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
+     *
+     * @hide
      */
-    public Handler(Looper looper) {
-        mLooper = looper;
-        mQueue = looper.mQueue;
-        mCallback = null;
-    }
-
-    /**
-     * Use the provided queue instead of the default one and take a callback
-     * interface in which to handle messages.
-     */
-    public Handler(Looper looper, Callback callback) {
+    public Handler(Looper looper, Callback callback, boolean async) {
         mLooper = looper;
         mQueue = looper.mQueue;
         mCallback = callback;
+        mAsynchronous = async;
     }
 
     /**
@@ -352,6 +412,58 @@
     }
 
     /**
+     * Runs the specified task synchronously.
+     *
+     * If the current thread is the same as the handler thread, then the runnable
+     * runs immediately without being enqueued.  Otherwise, posts the runnable
+     * to the handler and waits for it to complete before returning.
+     *
+     * This method is dangerous!  Improper use can result in deadlocks.
+     * Never call this method while any locks are held or use it in a
+     * possibly re-entrant manner.
+     *
+     * This method is occasionally useful in situations where a background thread
+     * must synchronously await completion of a task that must run on the
+     * handler's thread.  However, this problem is often a symptom of bad design.
+     * Consider improving the design (if possible) before resorting to this method.
+     *
+     * One example of where you might want to use this method is when you just
+     * set up a Handler thread and need to perform some initialization steps on
+     * it before continuing execution.
+     *
+     * If timeout occurs then this method returns <code>false</code> but the runnable
+     * will remain posted on the handler and may already be in progress or
+     * complete at a later time.
+     *
+     * @param r The Runnable that will be executed synchronously.
+     * @param timeout The timeout in milliseconds, or 0 to wait indefinitely.
+     *
+     * @return Returns true if the Runnable was successfully executed.
+     *         Returns false on failure, usually because the
+     *         looper processing the message queue is exiting.
+     *
+     * @hide This method is prone to abuse and should probably not be in the API.
+     * If we ever do make it part of the API, we might want to rename it to something
+     * less funny like runUnsafe().
+     */
+    public final boolean runWithScissors(final Runnable r, long timeout) {
+        if (r == null) {
+            throw new IllegalArgumentException("runnable must not be null");
+        }
+        if (timeout < 0) {
+            throw new IllegalArgumentException("timeout must be non-negative");
+        }
+
+        if (Looper.myLooper() == mLooper) {
+            r.run();
+            return true;
+        }
+
+        BlockingRunnable br = new BlockingRunnable(r);
+        return br.postAndWait(this, timeout);
+    }
+
+    /**
      * Remove any pending posts of Runnable r that are in the message queue.
      */
     public final void removeCallbacks(Runnable r)
@@ -464,20 +576,15 @@
      *         the looper is quit before the delivery time of the message
      *         occurs then the message will be dropped.
      */
-    public boolean sendMessageAtTime(Message msg, long uptimeMillis)
-    {
-        boolean sent = false;
+    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
         MessageQueue queue = mQueue;
-        if (queue != null) {
-            msg.target = this;
-            sent = queue.enqueueMessage(msg, uptimeMillis);
-        }
-        else {
+        if (queue == null) {
             RuntimeException e = new RuntimeException(
-                this + " sendMessageAtTime() called with no mQueue");
+                    this + " sendMessageAtTime() called with no mQueue");
             Log.w("Looper", e.getMessage(), e);
+            return false;
         }
-        return sent;
+        return enqueueMessage(queue, msg, uptimeMillis);
     }
 
     /**
@@ -492,20 +599,23 @@
      *         message queue.  Returns false on failure, usually because the
      *         looper processing the message queue is exiting.
      */
-    public final boolean sendMessageAtFrontOfQueue(Message msg)
-    {
-        boolean sent = false;
+    public final boolean sendMessageAtFrontOfQueue(Message msg) {
         MessageQueue queue = mQueue;
-        if (queue != null) {
-            msg.target = this;
-            sent = queue.enqueueMessage(msg, 0);
-        }
-        else {
+        if (queue == null) {
             RuntimeException e = new RuntimeException(
                 this + " sendMessageAtTime() called with no mQueue");
             Log.w("Looper", e.getMessage(), e);
+            return false;
         }
-        return sent;
+        return enqueueMessage(queue, msg, 0);
+    }
+
+    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
+        msg.target = this;
+        if (mAsynchronous) {
+            msg.setAsynchronous(true);
+        }
+        return queue.enqueueMessage(msg, uptimeMillis);
     }
 
     /**
@@ -618,5 +728,57 @@
     final MessageQueue mQueue;
     final Looper mLooper;
     final Callback mCallback;
+    final boolean mAsynchronous;
     IMessenger mMessenger;
+
+    private static final class BlockingRunnable implements Runnable {
+        private final Runnable mTask;
+        private boolean mDone;
+
+        public BlockingRunnable(Runnable task) {
+            mTask = task;
+        }
+
+        @Override
+        public void run() {
+            try {
+                mTask.run();
+            } finally {
+                synchronized (this) {
+                    mDone = true;
+                    notifyAll();
+                }
+            }
+        }
+
+        public boolean postAndWait(Handler handler, long timeout) {
+            if (!handler.post(this)) {
+                return false;
+            }
+
+            synchronized (this) {
+                if (timeout > 0) {
+                    final long expirationTime = SystemClock.uptimeMillis() + timeout;
+                    while (!mDone) {
+                        long delay = expirationTime - SystemClock.uptimeMillis();
+                        if (delay <= 0) {
+                            return false; // timeout
+                        }
+                        try {
+                            wait(delay);
+                        } catch (InterruptedException ex) {
+                        }
+                    }
+                } else {
+                    while (!mDone) {
+                        try {
+                            wait();
+                        } catch (InterruptedException ex) {
+                        }
+                    }
+                }
+            }
+            return true;
+        }
+    }
 }
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index e7ea355..2179fa1 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -152,6 +152,16 @@
     boolean isTetheringStarted();
 
     /**
+     * Start bluetooth reverse tethering services
+     */
+    void startReverseTethering(in String iface);
+
+    /**
+     * Stop currently running bluetooth reserse tethering services
+     */
+    void stopReverseTethering();
+
+    /**
      * Tethers the specified interface
      */
     void tetherInterface(String iface);
@@ -218,17 +228,17 @@
     /**
      * Start Wifi Access Point
      */
-    void startAccessPoint(in WifiConfiguration wifiConfig, String wlanIface, String softapIface);
+    void startAccessPoint(in WifiConfiguration wifiConfig, String iface);
 
     /**
      * Stop Wifi Access Point
      */
-    void stopAccessPoint(String wlanIface);
+    void stopAccessPoint(String iface);
 
     /**
      * Set Access Point config
      */
-    void setAccessPoint(in WifiConfiguration wifiConfig, String wlanIface, String softapIface);
+    void setAccessPoint(in WifiConfiguration wifiConfig, String iface);
 
     /**
      ** DATA USAGE RELATED
@@ -313,6 +323,27 @@
     int getInterfaceTxThrottle(String iface);
 
     /**
+     * Sets idletimer for an interface.
+     *
+     * This either initializes a new idletimer or increases its
+     * reference-counting if an idletimer already exists for given
+     * {@code iface}.
+     *
+     * {@code label} usually represents the network type of {@code iface}.
+     * Caller should ensure that {@code label} for an {@code iface} remains the
+     * same for all calls to addIdleTimer.
+     *
+     * Every {@code addIdleTimer} should be paired with a
+     * {@link removeIdleTimer} to cleanup when the network disconnects.
+     */
+    void addIdleTimer(String iface, int timeout, String label);
+
+    /**
+     * Removes idletimer for an interface.
+     */
+    void removeIdleTimer(String iface);
+
+    /**
      * Sets the name of the default interface in the DNS resolver.
      */
     void setDefaultInterfaceForDns(String iface);
@@ -331,4 +362,11 @@
      * Flush the DNS cache associated with the specified interface.
      */
     void flushInterfaceDnsCache(String iface);
+
+    void setFirewallEnabled(boolean enabled);
+    boolean isFirewallEnabled();
+    void setFirewallInterfaceRule(String iface, boolean allow);
+    void setFirewallEgressSourceRule(String addr, boolean allow);
+    void setFirewallEgressDestRule(String addr, int port, boolean allow);
+    void setFirewallUidRule(int uid, boolean allow);
 }
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 270e9be..6d6d147 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -23,27 +23,32 @@
 
 interface IPowerManager
 {
-    // WARNING: changes in acquireWakeLock() signature must be reflected in IPowerManager.cpp/h
-    void acquireWakeLock(int flags, IBinder lock, String tag, in WorkSource ws);
-    void updateWakeLockWorkSource(IBinder lock, in WorkSource ws);
-    void goToSleep(long time);
-    void goToSleepWithReason(long time, int reason);
-    // WARNING: changes in releaseWakeLock() signature must be reflected in IPowerManager.cpp/h
+    // WARNING: The first two methods must remain the first two methods because their
+    // transaction numbers must not change unless IPowerManager.cpp is also updated.
+    void acquireWakeLock(IBinder lock, int flags, String tag, in WorkSource ws);
     void releaseWakeLock(IBinder lock, int flags);
-    void userActivity(long when, boolean noChangeLights);
-    void userActivityWithForce(long when, boolean noChangeLights, boolean force);
-    void clearUserActivityTimeout(long now, long timeout);
-    void setPokeLock(int pokey, IBinder lock, String tag);
-    int getSupportedWakeLockFlags();
-    void setStayOnSetting(int val);
-    void setMaximumScreenOffTimeount(int timeMs);
-    void preventScreenOn(boolean prevent);
+
+    void updateWakeLockWorkSource(IBinder lock, in WorkSource ws);
+    boolean isWakeLockLevelSupported(int level);
+
+    void userActivity(long time, int event, int flags);
+    void wakeUp(long time);
+    void goToSleep(long time, int reason);
+    void nap(long time);
+
     boolean isScreenOn();
-    void reboot(String reason);
+    void reboot(boolean confirm, String reason, boolean wait);
+    void shutdown(boolean confirm, boolean wait);
     void crash(String message);
 
-    // sets the brightness of the backlights (screen, keyboard, button) 0-255
-    void setBacklightBrightness(int brightness);
+    void setStayOnSetting(int val);
+    void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs);
+
+    // temporarily overrides the screen brightness settings to allow the user to
+    // see the effect of a settings change without applying it immediately
+    void setTemporaryScreenBrightnessSettingOverride(int brightness);
+    void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj);
+
+    // sets the attention light (used by phone app only)
     void setAttentionLight(boolean on, int color);
-    void setAutoBrightnessAdjustment(float adj);
 }
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
new file mode 100644
index 0000000..ec02ae0
--- /dev/null
+++ b/core/java/android/os/IUserManager.aidl
@@ -0,0 +1,40 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.os;
+
+import android.os.ParcelFileDescriptor;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+
+/**
+ *  {@hide}
+ */
+interface IUserManager {
+    UserInfo createUser(in String name, int flags);
+    boolean removeUser(int userHandle);
+    void setUserName(int userHandle, String name);
+    void setUserIcon(int userHandle, in Bitmap icon);
+    Bitmap getUserIcon(int userHandle);
+    List<UserInfo> getUsers(boolean excludeDying);
+    UserInfo getUserInfo(int userHandle);
+    void setGuestEnabled(boolean enable);
+    boolean isGuestEnabled();
+    void wipeUser(int userHandle);
+    int getUserSerialNumber(int userHandle);
+    int getUserHandle(int userSerialNumber);
+}
diff --git a/core/java/android/os/LocalPowerManager.java b/core/java/android/os/LocalPowerManager.java
deleted file mode 100644
index 52df1f8..0000000
--- a/core/java/android/os/LocalPowerManager.java
+++ /dev/null
@@ -1,48 +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.
- */
-
-package android.os;
-
-/** @hide */
-public interface LocalPowerManager {
-    // Note: be sure to update BatteryStats if adding or modifying event constants.
-    
-    public static final int OTHER_EVENT = 0;
-    public static final int BUTTON_EVENT = 1;
-    public static final int TOUCH_EVENT = 2;
-
-    public static final int POKE_LOCK_IGNORE_TOUCH_EVENTS = 0x1;
-
-    public static final int POKE_LOCK_SHORT_TIMEOUT = 0x2;
-    public static final int POKE_LOCK_MEDIUM_TIMEOUT = 0x4;
-    public static final int POKE_LOCK_TIMEOUT_MASK = 0x6;
-
-    void goToSleep(long time);
-    
-    // notify power manager when keyboard is opened/closed
-    void setKeyboardVisibility(boolean visible);
-
-    // when the keyguard is up, it manages the power state, and userActivity doesn't do anything.
-    void enableUserActivity(boolean enabled);
-
-    // the same as the method on PowerManager
-    void userActivity(long time, boolean noChangeLights, int eventType);
-
-    boolean isScreenOn();
-
-    void setScreenBrightnessOverride(int brightness);
-    void setButtonBrightnessOverride(int brightness);
-}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 903c8b3..4a01113 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -16,22 +16,25 @@
 
 package android.os;
 
+import android.content.Context;
 import android.util.Log;
 
 /**
- * This class gives you control of the power state of the device.  
- * 
- * <p><b>Device battery life will be significantly affected by the use of this API.</b>  Do not
- * acquire WakeLocks unless you really need them, use the minimum levels possible, and be sure
- * to release it as soon as you can.
- * 
- * <p>You can obtain an instance of this class by calling 
+ * This class gives you control of the power state of the device.
+ *
+ * <p>
+ * <b>Device battery life will be significantly affected by the use of this API.</b>
+ * Do not acquire {@link WakeLock}s unless you really need them, use the minimum levels
+ * possible, and be sure to release them as soon as possible.
+ * </p><p>
+ * You can obtain an instance of this class by calling
  * {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
- * 
- * <p>The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}.  This will
- * create a {@link PowerManager.WakeLock} object.  You can then use methods on this object to 
- * control the power state of the device.  In practice it's quite simple:
- * 
+ * </p><p>
+ * The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}.
+ * This will create a {@link PowerManager.WakeLock} object.  You can then use methods
+ * on the wake lock object to control the power state of the device.
+ * </p><p>
+ * In practice it's quite simple:
  * {@samplecode
  * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
  * PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
@@ -39,49 +42,43 @@
  *   ..screen will stay on during this section..
  * wl.release();
  * }
- * 
- * <p>The following flags are defined, with varying effects on system power.  <i>These flags are
- * mutually exclusive - you may only specify one of them.</i>
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
+ * </p><p>
+ * The following wake lock levels are defined, with varying effects on system power.
+ * <i>These levels are mutually exclusive - you may only specify one of them.</i>
  *
- *     <thead>
+ * <table>
  *     <tr><th>Flag Value</th> 
  *     <th>CPU</th> <th>Screen</th> <th>Keyboard</th></tr>
- *     </thead>
  *
- *     <tbody>
- *     <tr><th>{@link #PARTIAL_WAKE_LOCK}</th>
+ *     <tr><td>{@link #PARTIAL_WAKE_LOCK}</td>
  *         <td>On*</td> <td>Off</td> <td>Off</td> 
  *     </tr>
  *     
- *     <tr><th>{@link #SCREEN_DIM_WAKE_LOCK}</th>
+ *     <tr><td>{@link #SCREEN_DIM_WAKE_LOCK}</td>
  *         <td>On</td> <td>Dim</td> <td>Off</td> 
  *     </tr>
  *
- *     <tr><th>{@link #SCREEN_BRIGHT_WAKE_LOCK}</th>
+ *     <tr><td>{@link #SCREEN_BRIGHT_WAKE_LOCK}</td>
  *         <td>On</td> <td>Bright</td> <td>Off</td> 
  *     </tr>
  *     
- *     <tr><th>{@link #FULL_WAKE_LOCK}</th>
+ *     <tr><td>{@link #FULL_WAKE_LOCK}</td>
  *         <td>On</td> <td>Bright</td> <td>Bright</td> 
  *     </tr>
- *     </tbody>
  * </table>
- * 
- * <p>*<i>If you hold a partial wakelock, the CPU will continue to run, irrespective of any timers 
- * and even after the user presses the power button.  In all other wakelocks, the CPU will run, but
- * the user can still put the device to sleep using the power button.</i>
- * 
- * <p>In addition, you can add two more flags, which affect behavior of the screen only.  <i>These
- * flags have no effect when combined with a {@link #PARTIAL_WAKE_LOCK}.</i>
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
+ * </p><p>
+ * *<i>If you hold a partial wake lock, the CPU will continue to run, regardless of any
+ * display timeouts or the state of the screen and even after the user presses the power button.
+ * In all other wake locks, the CPU will run, but the user can still put the device to sleep
+ * using the power button.</i>
+ * </p><p>
+ * In addition, you can add two more flags, which affect behavior of the screen only.
+ * <i>These flags have no effect when combined with a {@link #PARTIAL_WAKE_LOCK}.</i></p>
  *
- *     <thead>
+ * <table>
  *     <tr><th>Flag Value</th> <th>Description</th></tr>
- *     </thead>
  *
- *     <tbody>
- *     <tr><th>{@link #ACQUIRE_CAUSES_WAKEUP}</th>
+ *     <tr><td>{@link #ACQUIRE_CAUSES_WAKEUP}</td>
  *         <td>Normal wake locks don't actually turn on the illumination.  Instead, they cause
  *         the illumination to remain on once it turns on (e.g. from user activity).  This flag
  *         will force the screen and/or keyboard to turn on immediately, when the WakeLock is
@@ -89,88 +86,143 @@
  *         see immediately.</td> 
  *     </tr>
  *     
- *     <tr><th>{@link #ON_AFTER_RELEASE}</th>
+ *     <tr><td>{@link #ON_AFTER_RELEASE}</td>
  *         <td>If this flag is set, the user activity timer will be reset when the WakeLock is
  *         released, causing the illumination to remain on a bit longer.  This can be used to 
  *         reduce flicker if you are cycling between wake lock conditions.</td> 
  *     </tr>
- *     </tbody>
  * </table>
- * 
+ * <p>
  * Any application using a WakeLock must request the {@code android.permission.WAKE_LOCK}
  * permission in an {@code &lt;uses-permission&gt;} element of the application's manifest.
+ * </p>
  */
-public class PowerManager
-{
+public final class PowerManager {
     private static final String TAG = "PowerManager";
-    
-    /**
-     * These internal values define the underlying power elements that we might
-     * want to control individually.  Eventually we'd like to expose them.
+
+    /* NOTE: Wake lock levels were previously defined as a bit field, except that only a few
+     * combinations were actually supported so the bit field was removed.  This explains
+     * why the numbering scheme is so odd.  If adding a new wake lock level, any unused
+     * value can be used.
      */
-    private static final int WAKE_BIT_CPU_STRONG = 1;
-    private static final int WAKE_BIT_CPU_WEAK = 2;
-    private static final int WAKE_BIT_SCREEN_DIM = 4;
-    private static final int WAKE_BIT_SCREEN_BRIGHT = 8;
-    private static final int WAKE_BIT_KEYBOARD_BRIGHT = 16;
-    private static final int WAKE_BIT_PROXIMITY_SCREEN_OFF = 32;
-    
-    private static final int LOCK_MASK = WAKE_BIT_CPU_STRONG
-                                        | WAKE_BIT_CPU_WEAK
-                                        | WAKE_BIT_SCREEN_DIM
-                                        | WAKE_BIT_SCREEN_BRIGHT
-                                        | WAKE_BIT_KEYBOARD_BRIGHT
-                                        | WAKE_BIT_PROXIMITY_SCREEN_OFF;
 
     /**
-     * Wake lock that ensures that the CPU is running.  The screen might
-     * not be on.
+     * Wake lock level: Ensures that the CPU is running; the screen and keyboard
+     * backlight will be allowed to go off.
+     * <p>
+     * If the user presses the power button, then the screen will be turned off
+     * but the CPU will be kept on until all partial wake locks have been released.
+     * </p>
      */
-    public static final int PARTIAL_WAKE_LOCK = WAKE_BIT_CPU_STRONG;
+    public static final int PARTIAL_WAKE_LOCK = 0x00000001;
 
     /**
-     * Wake lock that ensures that the screen and keyboard are on at
-     * full brightness.
+     * Wake lock level: Ensures that the screen is on (but may be dimmed);
+     * the keyboard backlight will be allowed to go off.
+     * <p>
+     * If the user presses the power button, then the {@link #SCREEN_DIM_WAKE_LOCK} will be
+     * implicitly released by the system, causing both the screen and the CPU to be turned off.
+     * Contrast with {@link #PARTIAL_WAKE_LOCK}.
+     * </p>
      *
-     * <p class="note">Most applications should strongly consider using
-     * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
-     * This window flag will be correctly managed by the platform
-     * as the user moves between applications and doesn't require a special permission.</p>
-     */
-    public static final int FULL_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT 
-                                            | WAKE_BIT_KEYBOARD_BRIGHT;
-
-    /**
      * @deprecated Most applications should use
      * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead
      * of this type of wake lock, as it will be correctly managed by the platform
      * as the user moves between applications and doesn't require a special permission.
-     *
-     * Wake lock that ensures that the screen is on at full brightness;
-     * the keyboard backlight will be allowed to go off.
      */
     @Deprecated
-    public static final int SCREEN_BRIGHT_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT;
+    public static final int SCREEN_DIM_WAKE_LOCK = 0x00000006;
 
     /**
-     * Wake lock that ensures that the screen is on (but may be dimmed);
+     * Wake lock level: Ensures that the screen is on at full brightness;
      * the keyboard backlight will be allowed to go off.
+     * <p>
+     * If the user presses the power button, then the {@link #SCREEN_BRIGHT_WAKE_LOCK} will be
+     * implicitly released by the system, causing both the screen and the CPU to be turned off.
+     * Contrast with {@link #PARTIAL_WAKE_LOCK}.
+     * </p>
+     *
+     * @deprecated Most applications should use
+     * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead
+     * of this type of wake lock, as it will be correctly managed by the platform
+     * as the user moves between applications and doesn't require a special permission.
      */
-    public static final int SCREEN_DIM_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_DIM;
+    @Deprecated
+    public static final int SCREEN_BRIGHT_WAKE_LOCK = 0x0000000a;
 
     /**
-     * Wake lock that turns the screen off when the proximity sensor activates.
-     * Since not all devices have proximity sensors, use
-     * {@link #getSupportedWakeLockFlags() getSupportedWakeLockFlags()} to determine if
-     * this wake lock mode is supported.
+     * Wake lock level: Ensures that the screen and keyboard backlight are on at
+     * full brightness.
+     * <p>
+     * If the user presses the power button, then the {@link #FULL_WAKE_LOCK} will be
+     * implicitly released by the system, causing both the screen and the CPU to be turned off.
+     * Contrast with {@link #PARTIAL_WAKE_LOCK}.
+     * </p>
+     *
+     * @deprecated Most applications should use
+     * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead
+     * of this type of wake lock, as it will be correctly managed by the platform
+     * as the user moves between applications and doesn't require a special permission.
+     */
+    @Deprecated
+    public static final int FULL_WAKE_LOCK = 0x0000001a;
+
+    /**
+     * Wake lock level: Turns the screen off when the proximity sensor activates.
+     * <p>
+     * If the proximity sensor detects that an object is nearby, the screen turns off
+     * immediately.  Shortly after the object moves away, the screen turns on again.
+     * </p><p>
+     * A proximity wake lock does not prevent the device from falling asleep
+     * unlike {@link #FULL_WAKE_LOCK}, {@link #SCREEN_BRIGHT_WAKE_LOCK} and
+     * {@link #SCREEN_DIM_WAKE_LOCK}.  If there is no user activity and no other
+     * wake locks are held, then the device will fall asleep (and lock) as usual.
+     * However, the device will not fall asleep while the screen has been turned off
+     * by the proximity sensor because it effectively counts as ongoing user activity.
+     * </p><p>
+     * Since not all devices have proximity sensors, use {@link #isWakeLockLevelSupported}
+     * to determine whether this wake lock level is supported.
+     * </p>
      *
      * {@hide}
      */
-    public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = WAKE_BIT_PROXIMITY_SCREEN_OFF;
+    public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 0x00000020;
+
+    /**
+     * Mask for the wake lock level component of a combined wake lock level and flags integer.
+     *
+     * @hide
+     */
+    public static final int WAKE_LOCK_LEVEL_MASK = 0x0000ffff;
+
+    /**
+     * Wake lock flag: Turn the screen on when the wake lock is acquired.
+     * <p>
+     * Normally wake locks don't actually wake the device, they just cause
+     * the screen to remain on once it's already on.  Think of the video player
+     * application as the normal behavior.  Notifications that pop up and want
+     * the device to be on are the exception; use this flag to be like them.
+     * </p><p>
+     * Cannot be used with {@link #PARTIAL_WAKE_LOCK}.
+     * </p>
+     */
+    public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;
+
+    /**
+     * Wake lock flag: When this wake lock is released, poke the user activity timer
+     * so the screen stays on for a little longer.
+     * <p>
+     * Will not turn the screen on if it is not already on.
+     * See {@link #ACQUIRE_CAUSES_WAKEUP} if you want that.
+     * </p><p>
+     * Cannot be used with {@link #PARTIAL_WAKE_LOCK}.
+     * </p>
+     */
+    public static final int ON_AFTER_RELEASE = 0x20000000;
 
     /**
      * Flag for {@link WakeLock#release release(int)} to defer releasing a
-     * {@link #WAKE_BIT_PROXIMITY_SCREEN_OFF} wakelock until the proximity sensor returns
+     * {@link #WAKE_BIT_PROXIMITY_SCREEN_OFF} wake lock until the proximity sensor returns
      * a negative value.
      *
      * {@hide}
@@ -178,79 +230,187 @@
     public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1;
 
     /**
-     * Normally wake locks don't actually wake the device, they just cause
-     * it to remain on once it's already on.  Think of the video player
-     * app as the normal behavior.  Notifications that pop up and want
-     * the device to be on are the exception; use this flag to be like them.
-     * <p> 
-     * Does not work with PARTIAL_WAKE_LOCKs.
-     */
-    public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;
-
-    /**
-     * When this wake lock is released, poke the user activity timer
-     * so the screen stays on for a little longer.
-     * <p>
-     * Will not turn the screen on if it is not already on.  See {@link #ACQUIRE_CAUSES_WAKEUP}
-     * if you want that.
-     * <p>
-     * Does not work with PARTIAL_WAKE_LOCKs.
-     */
-    public static final int ON_AFTER_RELEASE = 0x20000000;
-
-    /**
-     * Brightness value to use when battery is low.
-     * @hide
-     */
-    public static final int BRIGHTNESS_LOW_BATTERY = 10;
-
-    /**
      * Brightness value for fully on.
      * @hide
      */
     public static final int BRIGHTNESS_ON = 255;
 
     /**
-     * Brightness value for dim backlight.
-     * @hide
-     */
-    public static final int BRIGHTNESS_DIM = 20;
-
-    /**
      * Brightness value for fully off.
      * @hide
      */
     public static final int BRIGHTNESS_OFF = 0;
 
+    // Note: Be sure to update android.os.BatteryStats and PowerManager.h
+    // if adding or modifying user activity event constants.
+
     /**
-     * Class lets you say that you need to have the device on.
-     * <p>
-     * Call release when you are done and don't need the lock anymore.
-     * <p>
-     * Any application using a WakeLock must request the {@code android.permission.WAKE_LOCK}
-     * permission in an {@code &lt;uses-permission&gt;} element of the application's manifest.
+     * User activity event type: Unspecified event type.
+     * @hide
      */
-    public class WakeLock
-    {
-        static final int RELEASE_WAKE_LOCK = 1;
+    public static final int USER_ACTIVITY_EVENT_OTHER = 0;
 
-        Runnable mReleaser = new Runnable() {
-            public void run() {
-                release();
-            }
-        };
-	
-        int mFlags;
-        String mTag;
-        IBinder mToken;
-        int mCount = 0;
-        boolean mRefCounted = true;
-        boolean mHeld = false;
-        WorkSource mWorkSource;
+    /**
+     * User activity event type: Button or key pressed or released.
+     * @hide
+     */
+    public static final int USER_ACTIVITY_EVENT_BUTTON = 1;
 
-        WakeLock(int flags, String tag)
-        {
-            switch (flags & LOCK_MASK) {
+    /**
+     * User activity event type: Touch down, move or up.
+     * @hide
+     */
+    public static final int USER_ACTIVITY_EVENT_TOUCH = 2;
+
+    /**
+     * User activity flag: Do not restart the user activity timeout or brighten
+     * the display in response to user activity if it is already dimmed.
+     * @hide
+     */
+    public static final int USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS = 1 << 0;
+
+    /**
+     * Go to sleep reason code: Going to sleep due by user request.
+     * @hide
+     */
+    public static final int GO_TO_SLEEP_REASON_USER = 0;
+
+    /**
+     * Go to sleep reason code: Going to sleep due by request of the
+     * device administration policy.
+     * @hide
+     */
+    public static final int GO_TO_SLEEP_REASON_DEVICE_ADMIN = 1;
+
+    /**
+     * Go to sleep reason code: Going to sleep due to a screen timeout.
+     * @hide
+     */
+    public static final int GO_TO_SLEEP_REASON_TIMEOUT = 2;
+
+    final Context mContext;
+    final IPowerManager mService;
+    final Handler mHandler;
+
+    /**
+     * {@hide}
+     */
+    public PowerManager(Context context, IPowerManager service, Handler handler) {
+        mContext = context;
+        mService = service;
+        mHandler = handler;
+    }
+
+    /**
+     * Gets the minimum supported screen brightness setting.
+     * The screen may be allowed to become dimmer than this value but
+     * this is the minimum value that can be set by the user.
+     * @hide
+     */
+    public int getMinimumScreenBrightnessSetting() {
+        return mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_screenBrightnessSettingMinimum);
+    }
+
+    /**
+     * Gets the maximum supported screen brightness setting.
+     * The screen may be allowed to become dimmer than this value but
+     * this is the maximum value that can be set by the user.
+     * @hide
+     */
+    public int getMaximumScreenBrightnessSetting() {
+        return mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_screenBrightnessSettingMaximum);
+    }
+
+    /**
+     * Gets the default screen brightness setting.
+     * @hide
+     */
+    public int getDefaultScreenBrightnessSetting() {
+        return mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_screenBrightnessSettingDefault);
+    }
+
+    /**
+     * Returns true if the screen auto-brightness adjustment setting should
+     * be available in the UI.  This setting is experimental and disabled by default.
+     * @hide
+     */
+    public static boolean useScreenAutoBrightnessAdjustmentFeature() {
+        return SystemProperties.getBoolean("persist.power.useautobrightadj", false);
+    }
+
+    /**
+     * Returns true if the twilight service should be used to adjust screen brightness
+     * policy.  This setting is experimental and disabled by default.
+     * @hide
+     */
+    public static boolean useTwilightAdjustmentFeature() {
+        return SystemProperties.getBoolean("persist.power.usetwilightadj", false);
+    }
+
+    /**
+     * Creates a new wake lock with the specified level and flags.
+     * <p>
+     * The {@code levelAndFlags} parameter specifies a wake lock level and optional flags
+     * combined using the logical OR operator.
+     * </p><p>
+     * The wake lock levels are: {@link #PARTIAL_WAKE_LOCK},
+     * {@link #FULL_WAKE_LOCK}, {@link #SCREEN_DIM_WAKE_LOCK}
+     * and {@link #SCREEN_BRIGHT_WAKE_LOCK}.  Exactly one wake lock level must be
+     * specified as part of the {@code levelAndFlags} parameter.
+     * </p><p>
+     * The wake lock flags are: {@link #ACQUIRE_CAUSES_WAKEUP}
+     * and {@link #ON_AFTER_RELEASE}.  Multiple flags can be combined as part of the
+     * {@code levelAndFlags} parameters.
+     * </p><p>
+     * Call {@link WakeLock#acquire() acquire()} on the object to acquire the
+     * wake lock, and {@link WakeLock#release release()} when you are done.
+     * </p><p>
+     * {@samplecode
+     * PowerManager pm = (PowerManager)mContext.getSystemService(
+     *                                          Context.POWER_SERVICE);
+     * PowerManager.WakeLock wl = pm.newWakeLock(
+     *                                      PowerManager.SCREEN_DIM_WAKE_LOCK
+     *                                      | PowerManager.ON_AFTER_RELEASE,
+     *                                      TAG);
+     * wl.acquire();
+     * // ... do work...
+     * wl.release();
+     * }
+     * </p><p>
+     * Although a wake lock can be created without special permissions,
+     * the {@link android.Manifest.permission#WAKE_LOCK} permission is
+     * required to actually acquire or release the wake lock that is returned.
+     * </p><p class="note">
+     * If using this to keep the screen on, you should strongly consider using
+     * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead.
+     * This window flag will be correctly managed by the platform
+     * as the user moves between applications and doesn't require a special permission.
+     * </p>
+     *
+     * @param levelAndFlags Combination of wake lock level and flag values defining
+     * the requested behavior of the WakeLock.
+     * @param tag Your class name (or other tag) for debugging purposes.
+     *
+     * @see WakeLock#acquire()
+     * @see WakeLock#release()
+     * @see #PARTIAL_WAKE_LOCK
+     * @see #FULL_WAKE_LOCK
+     * @see #SCREEN_DIM_WAKE_LOCK
+     * @see #SCREEN_BRIGHT_WAKE_LOCK
+     * @see #ACQUIRE_CAUSES_WAKEUP
+     * @see #ON_AFTER_RELEASE
+     */
+    public WakeLock newWakeLock(int levelAndFlags, String tag) {
+        validateWakeLockParameters(levelAndFlags, tag);
+        return new WakeLock(levelAndFlags, tag);
+    }
+
+    /** @hide */
+    public static void validateWakeLockParameters(int levelAndFlags, String tag) {
+        switch (levelAndFlags & WAKE_LOCK_LEVEL_MASK) {
             case PARTIAL_WAKE_LOCK:
             case SCREEN_DIM_WAKE_LOCK:
             case SCREEN_BRIGHT_WAKE_LOCK:
@@ -258,143 +418,230 @@
             case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
                 break;
             default:
-                throw new IllegalArgumentException();
-            }
+                throw new IllegalArgumentException("Must specify a valid wake lock level.");
+        }
+        if (tag == null) {
+            throw new IllegalArgumentException("The tag must not be null.");
+        }
+    }
 
+    /**
+     * Notifies the power manager that user activity happened.
+     * <p>
+     * Resets the auto-off timer and brightens the screen if the device
+     * is not asleep.  This is what happens normally when a key or the touch
+     * screen is pressed or when some other user activity occurs.
+     * This method does not wake up the device if it has been put to sleep.
+     * </p><p>
+     * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+     * </p>
+     *
+     * @param when The time of the user activity, in the {@link SystemClock#uptimeMillis()}
+     * time base.  This timestamp is used to correctly order the user activity request with
+     * other power management functions.  It should be set
+     * to the timestamp of the input event that caused the user activity.
+     * @param noChangeLights If true, does not cause the keyboard backlight to turn on
+     * because of this event.  This is set when the power key is pressed.
+     * We want the device to stay on while the button is down, but we're about
+     * to turn off the screen so we don't want the keyboard backlight to turn on again.
+     * Otherwise the lights flash on and then off and it looks weird.
+     *
+     * @see #wakeUp
+     * @see #goToSleep
+     */
+    public void userActivity(long when, boolean noChangeLights) {
+        try {
+            mService.userActivity(when, USER_ACTIVITY_EVENT_OTHER,
+                    noChangeLights ? USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS : 0);
+        } catch (RemoteException e) {
+        }
+    }
+
+   /**
+     * Forces the device to go to sleep.
+     * <p>
+     * Overrides all the wake locks that are held.
+     * This is what happens when the power key is pressed to turn off the screen.
+     * </p><p>
+     * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+     * </p>
+     *
+     * @param time The time when the request to go to sleep was issued, in the
+     * {@link SystemClock#uptimeMillis()} time base.  This timestamp is used to correctly
+     * order the go to sleep request with other power management functions.  It should be set
+     * to the timestamp of the input event that caused the request to go to sleep.
+     *
+     * @see #userActivity
+     * @see #wakeUp
+     */
+    public void goToSleep(long time) {
+        try {
+            mService.goToSleep(time, GO_TO_SLEEP_REASON_USER);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Forces the device to wake up from sleep.
+     * <p>
+     * If the device is currently asleep, wakes it up, otherwise does nothing.
+     * This is what happens when the power key is pressed to turn on the screen.
+     * </p><p>
+     * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+     * </p>
+     *
+     * @param time The time when the request to wake up was issued, in the
+     * {@link SystemClock#uptimeMillis()} time base.  This timestamp is used to correctly
+     * order the wake up request with other power management functions.  It should be set
+     * to the timestamp of the input event that caused the request to wake up.
+     *
+     * @see #userActivity
+     * @see #goToSleep
+     */
+    public void wakeUp(long time) {
+        try {
+            mService.wakeUp(time);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Forces the device to start napping.
+     * <p>
+     * If the device is currently awake, starts dreaming, otherwise does nothing.
+     * When the dream ends or if the dream cannot be started, the device will
+     * either wake up or go to sleep depending on whether there has been recent
+     * user activity.
+     * </p><p>
+     * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+     * </p>
+     *
+     * @param time The time when the request to nap was issued, in the
+     * {@link SystemClock#uptimeMillis()} time base.  This timestamp is used to correctly
+     * order the nap request with other power management functions.  It should be set
+     * to the timestamp of the input event that caused the request to nap.
+     *
+     * @see #wakeUp
+     * @see #goToSleep
+     *
+     * @hide
+     */
+    public void nap(long time) {
+        try {
+            mService.nap(time);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Sets the brightness of the backlights (screen, keyboard, button).
+     * <p>
+     * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+     * </p>
+     *
+     * @param brightness The brightness value from 0 to 255.
+     *
+     * {@hide}
+     */
+    public void setBacklightBrightness(int brightness) {
+        try {
+            mService.setTemporaryScreenBrightnessSettingOverride(brightness);
+        } catch (RemoteException e) {
+        }
+    }
+
+   /**
+     * Returns true if the specified wake lock level is supported.
+     *
+     * @param level The wake lock level to check.
+     * @return True if the specified wake lock level is supported.
+     *
+     * {@hide}
+     */
+    public boolean isWakeLockLevelSupported(int level) {
+        try {
+            return mService.isWakeLockLevelSupported(level);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+      * Returns whether the screen is currently on.
+      * <p>
+      * Only indicates whether the screen is on.  The screen could be either bright or dim.
+      * </p><p>
+      * {@samplecode
+      * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+      * boolean isScreenOn = pm.isScreenOn();
+      * }
+      * </p>
+      *
+      * @return whether the screen is on (bright or dim).
+      */
+    public boolean isScreenOn() {
+        try {
+            return mService.isScreenOn();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Reboot the device.  Will not return if the reboot is successful.
+     * <p>
+     * Requires the {@link android.Manifest.permission#REBOOT} permission.
+     * </p>
+     *
+     * @param reason code to pass to the kernel (e.g., "recovery") to
+     *               request special boot modes, or null.
+     */
+    public void reboot(String reason) {
+        try {
+            mService.reboot(false, reason, true);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * A wake lock is a mechanism to indicate that your application needs
+     * to have the device stay on.
+     * <p>
+     * Any application using a WakeLock must request the {@code android.permission.WAKE_LOCK}
+     * permission in an {@code &lt;uses-permission&gt;} element of the application's manifest.
+     * Obtain a wake lock by calling {@link PowerManager#newWakeLock(int, String)}.
+     * </p><p>
+     * Call {@link #acquire()} to acquire the wake lock and force the device to stay
+     * on at the level that was requested when the wake lock was created.
+     * </p><p>
+     * Call {@link #release()} when you are done and don't need the lock anymore.
+     * It is very important to do this as soon as possible to avoid running down the
+     * device's battery excessively.
+     * </p>
+     */
+    public final class WakeLock {
+        private final int mFlags;
+        private final String mTag;
+        private final IBinder mToken;
+        private int mCount;
+        private boolean mRefCounted = true;
+        private boolean mHeld;
+        private WorkSource mWorkSource;
+
+        private final Runnable mReleaser = new Runnable() {
+            public void run() {
+                release();
+            }
+        };
+
+        WakeLock(int flags, String tag) {
             mFlags = flags;
             mTag = tag;
             mToken = new Binder();
         }
 
-        /**
-         * Sets whether this WakeLock is ref counted.
-         *
-         * <p>Wake locks are reference counted by default.
-         *
-         * @param value true for ref counted, false for not ref counted.
-         */
-        public void setReferenceCounted(boolean value)
-        {
-            mRefCounted = value;
-        }
-
-        /**
-         * Makes sure the device is on at the level you asked when you created
-         * the wake lock.
-         */
-        public void acquire()
-        {
-            synchronized (mToken) {
-                acquireLocked();
-            }
-        }
-
-        /**
-         * Makes sure the device is on at the level you asked when you created
-         * the wake lock. The lock will be released after the given timeout.
-         * 
-         * @param timeout Release the lock after the give timeout in milliseconds.
-         */
-        public void acquire(long timeout) {
-            synchronized (mToken) {
-                acquireLocked();
-                mHandler.postDelayed(mReleaser, timeout);
-            }
-        }
-        
-        private void acquireLocked() {
-            if (!mRefCounted || mCount++ == 0) {
-                mHandler.removeCallbacks(mReleaser);
-                try {
-                    mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource);
-                } catch (RemoteException e) {
-                }
-                mHeld = true;
-            }
-        }
-
-        /**
-         * Release your claim to the CPU or screen being on.
-         *
-         * <p>
-         * It may turn off shortly after you release it, or it may not if there
-         * are other wake locks held.
-         */
-        public void release() {
-            release(0);
-        }
-
-        /**
-         * Release your claim to the CPU or screen being on.
-         * @param flags Combination of flag values to modify the release behavior.
-         *              Currently only {@link #WAIT_FOR_PROXIMITY_NEGATIVE} is supported.
-         *
-         * <p>
-         * It may turn off shortly after you release it, or it may not if there
-         * are other wake locks held.
-         *
-         * {@hide}
-         */
-        public void release(int flags) {
-            synchronized (mToken) {
-                if (!mRefCounted || --mCount == 0) {
-                    mHandler.removeCallbacks(mReleaser);
-                    try {
-                        mService.releaseWakeLock(mToken, flags);
-                    } catch (RemoteException e) {
-                    }
-                    mHeld = false;
-                }
-                if (mCount < 0) {
-                    throw new RuntimeException("WakeLock under-locked " + mTag);
-                }
-            }
-        }
-
-        public boolean isHeld()
-        {
-            synchronized (mToken) {
-                return mHeld;
-            }
-        }
-
-        public void setWorkSource(WorkSource ws) {
-            synchronized (mToken) {
-                if (ws != null && ws.size() == 0) {
-                    ws = null;
-                }
-                boolean changed = true;
-                if (ws == null) {
-                    mWorkSource = null;
-                } else if (mWorkSource == null) {
-                    changed = mWorkSource != null;
-                    mWorkSource = new WorkSource(ws);
-                } else {
-                    changed = mWorkSource.diff(ws);
-                    if (changed) {
-                        mWorkSource.set(ws);
-                    }
-                }
-                if (changed && mHeld) {
-                    try {
-                        mService.updateWakeLockWorkSource(mToken, mWorkSource);
-                    } catch (RemoteException e) {
-                    }
-                }
-            }
-        }
-
-        public String toString() {
-            synchronized (mToken) {
-                return "WakeLock{"
-                    + Integer.toHexString(System.identityHashCode(this))
-                    + " held=" + mHeld + ", refCount=" + mCount + "}";
-            }
-        }
-
         @Override
-        protected void finalize() throws Throwable
-        {
+        protected void finalize() throws Throwable {
             synchronized (mToken) {
                 if (mHeld) {
                     Log.wtf(TAG, "WakeLock finalized while still held: " + mTag);
@@ -405,180 +652,174 @@
                 }
             }
         }
-    }
 
-    /**
-     * Get a wake lock at the level of the flags parameter.  Call
-     * {@link WakeLock#acquire() acquire()} on the object to acquire the
-     * wake lock, and {@link WakeLock#release release()} when you are done.
-     *
-     * {@samplecode
-     *PowerManager pm = (PowerManager)mContext.getSystemService(
-     *                                          Context.POWER_SERVICE);
-     *PowerManager.WakeLock wl = pm.newWakeLock(
-     *                                      PowerManager.SCREEN_DIM_WAKE_LOCK
-     *                                      | PowerManager.ON_AFTER_RELEASE,
-     *                                      TAG);
-     *wl.acquire();
-     * // ...
-     *wl.release();
-     * }
-     *
-     * <p class="note">If using this to keep the screen on, you should strongly consider using
-     * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead.
-     * This window flag will be correctly managed by the platform
-     * as the user moves between applications and doesn't require a special permission.</p>
-     *
-     * @param flags Combination of flag values defining the requested behavior of the WakeLock.
-     * @param tag Your class name (or other tag) for debugging purposes.
-     *
-     * @see WakeLock#acquire()
-     * @see WakeLock#release()
-     */
-    public WakeLock newWakeLock(int flags, String tag)
-    {
-        if (tag == null) {
-            throw new NullPointerException("tag is null in PowerManager.newWakeLock");
+        /**
+         * Sets whether this WakeLock is reference counted.
+         * <p>
+         * Wake locks are reference counted by default.  If a wake lock is
+         * reference counted, then each call to {@link #acquire()} must be
+         * balanced by an equal number of calls to {@link #release()}.  If a wake
+         * lock is not reference counted, then one call to {@link #release()} is
+         * sufficient to undo the effect of all previous calls to {@link #acquire()}.
+         * </p>
+         *
+         * @param value True to make the wake lock reference counted, false to
+         * make the wake lock non-reference counted.
+         */
+        public void setReferenceCounted(boolean value) {
+            synchronized (mToken) {
+                mRefCounted = value;
+            }
         }
-        return new WakeLock(flags, tag);
-    }
 
-    /**
-     * User activity happened.
-     * <p>
-     * Turns the device from whatever state it's in to full on, and resets
-     * the auto-off timer.
-     *
-     * @param when is used to order this correctly with the wake lock calls.
-     *          This time should be in the {@link SystemClock#uptimeMillis
-     *          SystemClock.uptimeMillis()} time base.
-     * @param noChangeLights should be true if you don't want the lights to
-     *          turn on because of this event.  This is set when the power
-     *          key goes down.  We want the device to stay on while the button
-     *          is down, but we're about to turn off.  Otherwise the lights
-     *          flash on and then off and it looks weird.
-     */
-    public void userActivity(long when, boolean noChangeLights)
-    {
-        try {
-            mService.userActivity(when, noChangeLights);
-        } catch (RemoteException e) {
+        /**
+         * Acquires the wake lock.
+         * <p>
+         * Ensures that the device is on at the level requested when
+         * the wake lock was created.
+         * </p>
+         */
+        public void acquire() {
+            synchronized (mToken) {
+                acquireLocked();
+            }
+        }
+
+        /**
+         * Acquires the wake lock with a timeout.
+         * <p>
+         * Ensures that the device is on at the level requested when
+         * the wake lock was created.  The lock will be released after the given timeout
+         * expires.
+         * </p>
+         *
+         * @param timeout The timeout after which to release the wake lock, in milliseconds.
+         */
+        public void acquire(long timeout) {
+            synchronized (mToken) {
+                acquireLocked();
+                mHandler.postDelayed(mReleaser, timeout);
+            }
+        }
+
+        private void acquireLocked() {
+            if (!mRefCounted || mCount++ == 0) {
+                // Do this even if the wake lock is already thought to be held (mHeld == true)
+                // because non-reference counted wake locks are not always properly released.
+                // For example, the keyguard's wake lock might be forcibly released by the
+                // power manager without the keyguard knowing.  A subsequent call to acquire
+                // should immediately acquire the wake lock once again despite never having
+                // been explicitly released by the keyguard.
+                mHandler.removeCallbacks(mReleaser);
+                try {
+                    mService.acquireWakeLock(mToken, mFlags, mTag, mWorkSource);
+                } catch (RemoteException e) {
+                }
+                mHeld = true;
+            }
+        }
+
+        /**
+         * Releases the wake lock.
+         * <p>
+         * This method releases your claim to the CPU or screen being on.
+         * The screen may turn off shortly after you release the wake lock, or it may
+         * not if there are other wake locks still held.
+         * </p>
+         */
+        public void release() {
+            release(0);
+        }
+
+        /**
+         * Releases the wake lock with flags to modify the release behavior.
+         * <p>
+         * This method releases your claim to the CPU or screen being on.
+         * The screen may turn off shortly after you release the wake lock, or it may
+         * not if there are other wake locks still held.
+         * </p>
+         *
+         * @param flags Combination of flag values to modify the release behavior.
+         * Currently only {@link #WAIT_FOR_PROXIMITY_NEGATIVE} is supported.
+         *
+         * {@hide}
+         */
+        public void release(int flags) {
+            synchronized (mToken) {
+                if (!mRefCounted || --mCount == 0) {
+                    mHandler.removeCallbacks(mReleaser);
+                    if (mHeld) {
+                        try {
+                            mService.releaseWakeLock(mToken, flags);
+                        } catch (RemoteException e) {
+                        }
+                        mHeld = false;
+                    }
+                }
+                if (mCount < 0) {
+                    throw new RuntimeException("WakeLock under-locked " + mTag);
+                }
+            }
+        }
+
+        /**
+         * Returns true if the wake lock has been acquired but not yet released.
+         *
+         * @return True if the wake lock is held.
+         */
+        public boolean isHeld() {
+            synchronized (mToken) {
+                return mHeld;
+            }
+        }
+
+        /**
+         * Sets the work source associated with the wake lock.
+         * <p>
+         * The work source is used to determine on behalf of which application
+         * the wake lock is being held.  This is useful in the case where a
+         * service is performing work on behalf of an application so that the
+         * cost of that work can be accounted to the application.
+         * </p>
+         *
+         * @param ws The work source, or null if none.
+         */
+        public void setWorkSource(WorkSource ws) {
+            synchronized (mToken) {
+                if (ws != null && ws.size() == 0) {
+                    ws = null;
+                }
+
+                final boolean changed;
+                if (ws == null) {
+                    changed = mWorkSource != null;
+                    mWorkSource = null;
+                } else if (mWorkSource == null) {
+                    changed = true;
+                    mWorkSource = new WorkSource(ws);
+                } else {
+                    changed = mWorkSource.diff(ws);
+                    if (changed) {
+                        mWorkSource.set(ws);
+                    }
+                }
+
+                if (changed && mHeld) {
+                    try {
+                        mService.updateWakeLockWorkSource(mToken, mWorkSource);
+                    } catch (RemoteException e) {
+                    }
+                }
+            }
+        }
+
+        @Override
+        public String toString() {
+            synchronized (mToken) {
+                return "WakeLock{"
+                    + Integer.toHexString(System.identityHashCode(this))
+                    + " held=" + mHeld + ", refCount=" + mCount + "}";
+            }
         }
     }
-
-   /**
-     * Force the device to go to sleep. Overrides all the wake locks that are
-     * held.
-     * 
-     * @param time is used to order this correctly with the wake lock calls. 
-     *          The time  should be in the {@link SystemClock#uptimeMillis 
-     *          SystemClock.uptimeMillis()} time base.
-     */
-    public void goToSleep(long time) 
-    {
-        try {
-            mService.goToSleep(time);
-        } catch (RemoteException e) {
-        }
-    }
-
-    /**
-     * sets the brightness of the backlights (screen, keyboard, button).
-     *
-     * @param brightness value from 0 to 255
-     *
-     * {@hide}
-     */
-    public void setBacklightBrightness(int brightness)
-    {
-        try {
-            mService.setBacklightBrightness(brightness);
-        } catch (RemoteException e) {
-        }
-    }
-
-   /**
-     * Returns the set of flags for {@link #newWakeLock(int, String) newWakeLock()}
-     * that are supported on the device.
-     * For example, to test to see if the {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK}
-     * is supported:
-     *
-     * {@samplecode
-     * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
-     * int supportedFlags = pm.getSupportedWakeLockFlags();
-     *  boolean proximitySupported = ((supportedFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
-     *                                  == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK);
-     * }
-     *
-     * @return the set of supported WakeLock flags.
-     *
-     * {@hide}
-     */
-    public int getSupportedWakeLockFlags()
-    {
-        try {
-            return mService.getSupportedWakeLockFlags();
-        } catch (RemoteException e) {
-            return 0;
-        }
-    }
-
-    /**
-      * Returns whether the screen is currently on. The screen could be bright
-      * or dim.
-      *
-      * {@samplecode
-      * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
-      * boolean isScreenOn = pm.isScreenOn();
-      * }
-      *
-      * @return whether the screen is on (bright or dim).
-      */
-    public boolean isScreenOn()
-    {
-        try {
-            return mService.isScreenOn();
-        } catch (RemoteException e) {
-            return false;
-        }
-    }
-
-    /**
-     * Reboot the device.  Will not return if the reboot is
-     * successful.  Requires the {@link android.Manifest.permission#REBOOT}
-     * permission.
-     *
-     * @param reason code to pass to the kernel (e.g., "recovery") to
-     *               request special boot modes, or null.
-     */
-    public void reboot(String reason)
-    {
-        try {
-            mService.reboot(reason);
-        } catch (RemoteException e) {
-        }
-    }
-
-    private PowerManager()
-    {
-    }
-
-    /**
-     * {@hide}
-     */
-    public PowerManager(IPowerManager service, Handler handler)
-    {
-        mService = service;
-        mHandler = handler;
-    }
-
-    /**
-     *  TODO: It would be nice to be able to set the poke lock here,
-     *  but I'm not sure what would be acceptable as an interface -
-     *  either a PokeLock object (like WakeLock) or, possibly just a
-     *  method call to set the poke lock. 
-     */
-    
-    IPowerManager mService;
-    Handler mHandler;
 }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 6ab4dc1..05099fb 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -116,6 +116,12 @@
     public static final int NFC_UID = 1027;
 
     /**
+     * Defines the UID/GID for the Bluetooth service process.
+     * @hide
+     */
+    public static final int BLUETOOTH_UID = 1002;
+
+    /**
      * Defines the GID for the group that allows write access to the internal media storage.
      * @hide
      */
@@ -146,10 +152,24 @@
     public static final int LAST_ISOLATED_UID = 99999;
 
     /**
+     * First gid for applications to share resources. Used when forward-locking
+     * is enabled but all UserHandles need to be able to read the resources.
+     * @hide
+     */
+    public static final int FIRST_SHARED_APPLICATION_GID = 50000;
+
+    /**
+     * Last gid for applications to share resources. Used when forward-locking
+     * is enabled but all UserHandles need to be able to read the resources.
+     * @hide
+     */
+    public static final int LAST_SHARED_APPLICATION_GID = 59999;
+
+    /**
      * Defines a secondary group id for access to the bluetooth hardware.
      */
     public static final int BLUETOOTH_GID = 2000;
-    
+
     /**
      * Standard priority of application threads.
      * Use with {@link #setThreadPriority(int)} and
@@ -370,12 +390,13 @@
     public static final ProcessStartResult start(final String processClass,
                                   final String niceName,
                                   int uid, int gid, int[] gids,
-                                  int debugFlags, int targetSdkVersion,
+                                  int debugFlags, int mountExternal,
+                                  int targetSdkVersion,
                                   String seInfo,
                                   String[] zygoteArgs) {
         try {
             return startViaZygote(processClass, niceName, uid, gid, gids,
-                    debugFlags, targetSdkVersion, seInfo, zygoteArgs);
+                    debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);
         } catch (ZygoteStartFailedEx ex) {
             Log.e(LOG_TAG,
                     "Starting VM process through Zygote failed");
@@ -547,7 +568,8 @@
                                   final String niceName,
                                   final int uid, final int gid,
                                   final int[] gids,
-                                  int debugFlags, int targetSdkVersion,
+                                  int debugFlags, int mountExternal,
+                                  int targetSdkVersion,
                                   String seInfo,
                                   String[] extraArgs)
                                   throws ZygoteStartFailedEx {
@@ -574,6 +596,11 @@
             if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
                 argsForZygote.add("--enable-assert");
             }
+            if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER) {
+                argsForZygote.add("--mount-external-multiuser");
+            } else if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL) {
+                argsForZygote.add("--mount-external-multiuser-all");
+            }
             argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
 
             //TODO optionally enable debuger
@@ -634,16 +661,29 @@
     public static final native int myTid();
 
     /**
-     * Returns the identifier of this process's user.
+     * Returns the identifier of this process's uid.  This is the kernel uid
+     * that the process is running under, which is the identity of its
+     * app-specific sandbox.  It is different from {@link #myUserHandle} in that
+     * a uid identifies a specific app sandbox in a specific user.
      */
     public static final native int myUid();
 
     /**
+     * Returns this process's user handle.  This is the
+     * user the process is running under.  It is distinct from
+     * {@link #myUid()} in that a particular user will have multiple
+     * distinct apps running under it each with their own uid.
+     */
+    public static final UserHandle myUserHandle() {
+        return new UserHandle(UserHandle.getUserId(myUid()));
+    }
+
+    /**
      * Returns whether the current process is in an isolated sandbox.
      * @hide
      */
     public static final boolean isIsolated() {
-        int uid = UserId.getAppId(myUid());
+        int uid = UserHandle.getAppId(myUid());
         return uid >= FIRST_ISOLATED_UID && uid <= LAST_ISOLATED_UID;
     }
 
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 43cf74e..480fe7d 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -40,6 +40,7 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Locale;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
@@ -326,7 +327,8 @@
         throws IOException {
         String filename = packageFile.getCanonicalPath();
         Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
-        String arg = "--update_package=" + filename;
+        String arg = "--update_package=" + filename +
+            "\n--locale=" + Locale.getDefault().toString();
         bootCommand(context, arg);
     }
 
@@ -346,7 +348,8 @@
         final ConditionVariable condition = new ConditionVariable();
 
         Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION");
-        context.sendOrderedBroadcast(intent, android.Manifest.permission.MASTER_CLEAR,
+        context.sendOrderedBroadcastAsUser(intent, UserHandle.OWNER,
+                android.Manifest.permission.MASTER_CLEAR,
                 new BroadcastReceiver() {
                     @Override
                     public void onReceive(Context context, Intent intent) {
@@ -357,7 +360,7 @@
         // Block until the ordered broadcast has completed.
         condition.block();
 
-        bootCommand(context, "--wipe_data");
+        bootCommand(context, "--wipe_data\n--locale=" + Locale.getDefault().toString());
     }
 
     /**
@@ -365,7 +368,7 @@
      * @throws IOException if something goes wrong.
      */
     public static void rebootWipeCache(Context context) throws IOException {
-        bootCommand(context, "--wipe_cache");
+        bootCommand(context, "--wipe_cache\n--locale=" + Locale.getDefault().toString());
     }
 
     /**
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index b74af16..d02a320 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -304,4 +304,25 @@
         
         mBroadcastCount = -1;
     }
+
+    /**
+     * Returns the number of registered callbacks. Note that the number of registered
+     * callbacks may differ from the value returned by {@link #beginBroadcast()} since
+     * the former returns the number of callbacks registered at the time of the call
+     * and the second the number of callback to which the broadcast will be delivered.
+     * <p>
+     * This function is useful to decide whether to schedule a broadcast if this
+     * requires doing some work which otherwise would not be performed.
+     * </p>
+     *
+     * @return The size.
+     */
+    public int getRegisteredCallbackCount() {
+        synchronized (mCallbacks) {
+            if (mKilled) {
+                return 0;
+            }
+            return mCallbacks.size();
+        }
+    }
 }
diff --git a/core/java/android/os/SchedulingPolicyService.java b/core/java/android/os/SchedulingPolicyService.java
index 94f907b..a3fede6 100644
--- a/core/java/android/os/SchedulingPolicyService.java
+++ b/core/java/android/os/SchedulingPolicyService.java
@@ -33,7 +33,7 @@
 
     // Minimum and maximum values allowed for requestPriority parameter prio
     private static final int PRIORITY_MIN = 1;
-    private static final int PRIORITY_MAX = 2;
+    private static final int PRIORITY_MAX = 3;
 
     public SchedulingPolicyService() {
     }
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index 7291739..c9adf45 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -46,15 +46,16 @@
  *     such as {@link Thread#sleep(long) Thread.sleep(millls)},
  *     {@link Object#wait(long) Object.wait(millis)}, and
  *     {@link System#nanoTime System.nanoTime()}.  This clock is guaranteed
- *     to be monotonic, and is the recommended basis for the general purpose
- *     interval timing of user interface events, performance measurements,
- *     and anything else that does not need to measure elapsed time during
- *     device sleep.  Most methods that accept a timestamp value expect the
- *     {@link #uptimeMillis} clock.
+ *     to be monotonic, and is suitable for interval timing when the
+ *     interval does not span device sleep.  Most methods that accept a
+ *     timestamp value currently expect the {@link #uptimeMillis} clock.
  *
- *     <li> <p> {@link #elapsedRealtime} is counted in milliseconds since the
- *     system was booted, including deep sleep.  This clock should be used
- *     when measuring time intervals that may span periods of system sleep.
+ *     <li> <p> {@link #elapsedRealtime} and {@link #elapsedRealtimeNanos}
+ *     return the time since the system was booted, and include deep sleep.
+ *     This clock is guaranteed to be monotonic, and continues to tick even
+ *     when the CPU is in power saving modes, so is the recommend basis
+ *     for general purpose interval timing.
+ *
  * </ul>
  *
  * There are several mechanisms for controlling the timing of events:
@@ -150,7 +151,14 @@
      * @return elapsed milliseconds since boot.
      */
     native public static long elapsedRealtime();
-    
+
+    /**
+     * Returns nanoseconds since boot, including time spent in sleep.
+     *
+     * @return elapsed nanoseconds since boot.
+     */
+    public static native long elapsedRealtimeNanos();
+
     /**
      * Returns milliseconds running in the current thread.
      * 
diff --git a/core/java/android/os/SystemService.java b/core/java/android/os/SystemService.java
index da27db5..f345271 100644
--- a/core/java/android/os/SystemService.java
+++ b/core/java/android/os/SystemService.java
@@ -16,15 +16,55 @@
 
 package android.os;
 
-/** @hide */
-public class SystemService
-{
-        /** Request that the init daemon start a named service. */
+import android.util.Slog;
+
+import com.google.android.collect.Maps;
+
+import java.util.HashMap;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Controls and utilities for low-level {@code init} services.
+ *
+ * @hide
+ */
+public class SystemService {
+
+    private static HashMap<String, State> sStates = Maps.newHashMap();
+
+    /**
+     * State of a known {@code init} service.
+     */
+    public enum State {
+        RUNNING("running"),
+        STOPPING("stopping"),
+        STOPPED("stopped"),
+        RESTARTING("restarting");
+
+        State(String state) {
+            sStates.put(state, this);
+        }
+    }
+
+    private static Object sPropertyLock = new Object();
+
+    static {
+        SystemProperties.addChangeCallback(new Runnable() {
+            @Override
+            public void run() {
+                synchronized (sPropertyLock) {
+                    sPropertyLock.notifyAll();
+                }
+            }
+        });
+    }
+
+    /** Request that the init daemon start a named service. */
     public static void start(String name) {
         SystemProperties.set("ctl.start", name);
     }
-    
-        /** Request that the init daemon stop a named service. */
+
+    /** Request that the init daemon stop a named service. */
     public static void stop(String name) {
         SystemProperties.set("ctl.stop", name);
     }
@@ -33,4 +73,77 @@
     public static void restart(String name) {
         SystemProperties.set("ctl.restart", name);
     }
+
+    /**
+     * Return current state of given service.
+     */
+    public static State getState(String service) {
+        final String rawState = SystemProperties.get("init.svc." + service);
+        final State state = sStates.get(rawState);
+        if (state != null) {
+            return state;
+        } else {
+            return State.STOPPED;
+        }
+    }
+
+    /**
+     * Check if given service is {@link State#STOPPED}.
+     */
+    public static boolean isStopped(String service) {
+        return State.STOPPED.equals(getState(service));
+    }
+
+    /**
+     * Check if given service is {@link State#RUNNING}.
+     */
+    public static boolean isRunning(String service) {
+        return State.RUNNING.equals(getState(service));
+    }
+
+    /**
+     * Wait until given service has entered specific state.
+     */
+    public static void waitForState(String service, State state, long timeoutMillis)
+            throws TimeoutException {
+        final long endMillis = SystemClock.elapsedRealtime() + timeoutMillis;
+        while (true) {
+            synchronized (sPropertyLock) {
+                final State currentState = getState(service);
+                if (state.equals(currentState)) {
+                    return;
+                }
+
+                if (SystemClock.elapsedRealtime() >= endMillis) {
+                    throw new TimeoutException("Service " + service + " currently " + currentState
+                            + "; waited " + timeoutMillis + "ms for " + state);
+                }
+
+                try {
+                    sPropertyLock.wait(timeoutMillis);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+    }
+
+    /**
+     * Wait until any of given services enters {@link State#STOPPED}.
+     */
+    public static void waitForAnyStopped(String... services)  {
+        while (true) {
+            synchronized (sPropertyLock) {
+                for (String service : services) {
+                    if (State.STOPPED.equals(getState(service))) {
+                        return;
+                    }
+                }
+
+                try {
+                    sPropertyLock.wait();
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+    }
 }
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index d2050b7..ed51818 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import android.util.Log;
+
 /**
  * Writes trace events to the kernel trace buffer.  These trace events can be
  * collected using the "atrace" program for offline analysis.
@@ -27,6 +29,8 @@
  * @hide
  */
 public final class Trace {
+    private static final String TAG = "Trace";
+
     // These tags must be kept in sync with frameworks/native/include/utils/Trace.h.
     public static final long TRACE_TAG_NEVER = 0;
     public static final long TRACE_TAG_ALWAYS = 1L << 0;
@@ -39,16 +43,21 @@
     public static final long TRACE_TAG_SYNC_MANAGER = 1L << 7;
     public static final long TRACE_TAG_AUDIO = 1L << 8;
     public static final long TRACE_TAG_VIDEO = 1L << 9;
+    public static final long TRACE_TAG_CAMERA = 1L << 10;
 
     public static final int TRACE_FLAGS_START_BIT = 1;
     public static final String[] TRACE_TAGS = {
         "Graphics", "Input", "View", "WebView", "Window Manager",
-        "Activity Manager", "Sync Manager", "Audio", "Video",
+        "Activity Manager", "Sync Manager", "Audio", "Video", "Camera",
     };
 
     public static final String PROPERTY_TRACE_TAG_ENABLEFLAGS = "debug.atrace.tags.enableflags";
 
-    private static long sEnabledTags = nativeGetEnabledTags();
+    // This works as a "not ready" flag because TRACE_TAG_ALWAYS is always set.
+    private static final long TRACE_FLAGS_NOT_READY = 0;
+
+    // Must be volatile to avoid word tearing.
+    private static volatile long sEnabledTags = TRACE_FLAGS_NOT_READY;
 
     private static native long nativeGetEnabledTags();
     private static native void nativeTraceCounter(long tag, String name, int value);
@@ -56,9 +65,17 @@
     private static native void nativeTraceEnd(long tag);
 
     static {
+        // We configure two separate change callbacks, one in Trace.cpp and one here.  The
+        // native callback reads the tags from the system property, and this callback
+        // reads the value that the native code retrieved.  It's essential that the native
+        // callback executes first.
+        //
+        // The system provides ordering through a priority level.  Callbacks made through
+        // SystemProperties.addChangeCallback currently have a negative priority, while
+        // our native code is using a priority of zero.
         SystemProperties.addChangeCallback(new Runnable() {
             @Override public void run() {
-                sEnabledTags = nativeGetEnabledTags();
+                cacheEnabledTags();
             }
         });
     }
@@ -67,13 +84,41 @@
     }
 
     /**
+     * Caches a copy of the enabled-tag bits.  The "master" copy is held by the native code,
+     * and comes from the PROPERTY_TRACE_TAG_ENABLEFLAGS property.
+     * <p>
+     * If the native code hasn't yet read the property, we will cause it to do one-time
+     * initialization.  We don't want to do this during class init, because this class is
+     * preloaded, so all apps would be stuck with whatever the zygote saw.  (The zygote
+     * doesn't see the system-property update broadcasts.)
+     * <p>
+     * We want to defer initialization until the first use by an app, post-zygote.
+     * <p>
+     * We're okay if multiple threads call here simultaneously -- the native state is
+     * synchronized, and sEnabledTags is volatile (prevents word tearing).
+     */
+    private static long cacheEnabledTags() {
+        long tags = nativeGetEnabledTags();
+        if (tags == TRACE_FLAGS_NOT_READY) {
+            Log.w(TAG, "Unexpected value from nativeGetEnabledTags: " + tags);
+            // keep going
+        }
+        sEnabledTags = tags;
+        return tags;
+    }
+
+    /**
      * Returns true if a trace tag is enabled.
      *
      * @param traceTag The trace tag to check.
      * @return True if the trace tag is valid.
      */
     public static boolean isTagEnabled(long traceTag) {
-        return (sEnabledTags & traceTag) != 0;
+        long tags = sEnabledTags;
+        if (tags == TRACE_FLAGS_NOT_READY) {
+            tags = cacheEnabledTags();
+        }
+        return (tags & traceTag) != 0;
     }
 
     /**
@@ -84,7 +129,7 @@
      * @param counterValue The counter value.
      */
     public static void traceCounter(long traceTag, String counterName, int counterValue) {
-        if ((sEnabledTags & traceTag) != 0) {
+        if (isTagEnabled(traceTag)) {
             nativeTraceCounter(traceTag, counterName, counterValue);
         }
     }
@@ -97,7 +142,7 @@
      * @param methodName The method name to appear in the trace.
      */
     public static void traceBegin(long traceTag, String methodName) {
-        if ((sEnabledTags & traceTag) != 0) {
+        if (isTagEnabled(traceTag)) {
             nativeTraceBegin(traceTag, methodName);
         }
     }
@@ -109,7 +154,7 @@
      * @param traceTag The trace tag.
      */
     public static void traceEnd(long traceTag) {
-        if ((sEnabledTags & traceTag) != 0) {
+        if (isTagEnabled(traceTag)) {
             nativeTraceEnd(traceTag);
         }
     }
diff --git a/core/java/android/os/UEventObserver.java b/core/java/android/os/UEventObserver.java
index b924e84..9dbfd50 100644
--- a/core/java/android/os/UEventObserver.java
+++ b/core/java/android/os/UEventObserver.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import android.util.Log;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 
@@ -37,14 +39,93 @@
  * @hide
 */
 public abstract class UEventObserver {
-    private static final String TAG = UEventObserver.class.getSimpleName();
+    private static final String TAG = "UEventObserver";
+    private static final boolean DEBUG = false;
+
+    private static UEventThread sThread;
+
+    private static native void nativeSetup();
+    private static native String nativeWaitForNextEvent();
+    private static native void nativeAddMatch(String match);
+    private static native void nativeRemoveMatch(String match);
+
+    public UEventObserver() {
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            stopObserving();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    private static UEventThread getThread() {
+        synchronized (UEventObserver.class) {
+            if (sThread == null) {
+                sThread = new UEventThread();
+                sThread.start();
+            }
+            return sThread;
+        }
+    }
+
+    private static UEventThread peekThread() {
+        synchronized (UEventObserver.class) {
+            return sThread;
+        }
+    }
+
+    /**
+     * Begin observation of UEvent's.<p>
+     * This method will cause the UEvent thread to start if this is the first
+     * invocation of startObserving in this process.<p>
+     * Once called, the UEvent thread will call onUEvent() when an incoming
+     * UEvent matches the specified string.<p>
+     * This method can be called multiple times to register multiple matches.
+     * Only one call to stopObserving is required even with multiple registered
+     * matches.
+     *
+     * @param match A substring of the UEvent to match.  Try to be as specific
+     * as possible to avoid incurring unintended additional cost from processing
+     * irrelevant messages.  Netlink messages can be moderately high bandwidth and
+     * are expensive to parse.  For example, some devices may send one netlink message
+     * for each vsync period.
+     */
+    public final void startObserving(String match) {
+        if (match == null || match.isEmpty()) {
+            throw new IllegalArgumentException("match substring must be non-empty");
+        }
+
+        final UEventThread t = getThread();
+        t.addObserver(match, this);
+    }
+
+    /**
+     * End observation of UEvent's.<p>
+     * This process's UEvent thread will never call onUEvent() on this
+     * UEventObserver after this call. Repeated calls have no effect.
+     */
+    public final void stopObserving() {
+        final UEventThread t = getThread();
+        if (t != null) {
+            t.removeObserver(this);
+        }
+    }
+
+    /**
+     * Subclasses of UEventObserver should override this method to handle
+     * UEvents.
+     */
+    public abstract void onUEvent(UEvent event);
 
     /**
      * Representation of a UEvent.
      */
-    static public class UEvent {
+    public static final class UEvent {
         // collection of key=value pairs parsed from the uevent message
-        public HashMap<String,String> mMap = new HashMap<String,String>();
+        private final HashMap<String,String> mMap = new HashMap<String,String>();
 
         public UEvent(String message) {
             int offset = 0;
@@ -52,7 +133,7 @@
 
             while (offset < length) {
                 int equals = message.indexOf('=', offset);
-                int at = message.indexOf(0, offset);
+                int at = message.indexOf('\0', offset);
                 if (at < 0) break;
 
                 if (equals > offset && equals < at) {
@@ -79,113 +160,80 @@
         }
     }
 
-    private static UEventThread sThread;
-    private static boolean sThreadStarted = false;
-
-    private static class UEventThread extends Thread {
+    private static final class UEventThread extends Thread {
         /** Many to many mapping of string match to observer.
          *  Multimap would be better, but not available in android, so use
          *  an ArrayList where even elements are the String match and odd
          *  elements the corresponding UEventObserver observer */
-        private ArrayList<Object> mObservers = new ArrayList<Object>();
-        
-        UEventThread() {
+        private final ArrayList<Object> mKeysAndObservers = new ArrayList<Object>();
+
+        private final ArrayList<UEventObserver> mTempObserversToSignal =
+                new ArrayList<UEventObserver>();
+
+        public UEventThread() {
             super("UEventObserver");
         }
-        
-        public void run() {
-            native_setup();
 
-            byte[] buffer = new byte[1024];
-            int len;
+        @Override
+        public void run() {
+            nativeSetup();
+
             while (true) {
-                len = next_event(buffer);
-                if (len > 0) {
-                    String bufferStr = new String(buffer, 0, len);  // easier to search a String
-                    synchronized (mObservers) {
-                        for (int i = 0; i < mObservers.size(); i += 2) {
-                            if (bufferStr.indexOf((String)mObservers.get(i)) != -1) {
-                                ((UEventObserver)mObservers.get(i+1))
-                                        .onUEvent(new UEvent(bufferStr));
-                            }
-                        }
+                String message = nativeWaitForNextEvent();
+                if (message != null) {
+                    if (DEBUG) {
+                        Log.d(TAG, message);
                     }
+                    sendEvent(message);
                 }
             }
         }
-        public void addObserver(String match, UEventObserver observer) {
-            synchronized(mObservers) {
-                mObservers.add(match);
-                mObservers.add(observer);
+
+        private void sendEvent(String message) {
+            synchronized (mKeysAndObservers) {
+                final int N = mKeysAndObservers.size();
+                for (int i = 0; i < N; i += 2) {
+                    final String key = (String)mKeysAndObservers.get(i);
+                    if (message.contains(key)) {
+                        final UEventObserver observer =
+                                (UEventObserver)mKeysAndObservers.get(i + 1);
+                        mTempObserversToSignal.add(observer);
+                    }
+                }
+            }
+
+            if (!mTempObserversToSignal.isEmpty()) {
+                final UEvent event = new UEvent(message);
+                final int N = mTempObserversToSignal.size();
+                for (int i = 0; i < N; i++) {
+                    final UEventObserver observer = mTempObserversToSignal.get(i);
+                    observer.onUEvent(event);
+                }
+                mTempObserversToSignal.clear();
             }
         }
+
+        public void addObserver(String match, UEventObserver observer) {
+            synchronized (mKeysAndObservers) {
+                mKeysAndObservers.add(match);
+                mKeysAndObservers.add(observer);
+                nativeAddMatch(match);
+            }
+        }
+
         /** Removes every key/value pair where value=observer from mObservers */
         public void removeObserver(UEventObserver observer) {
-            synchronized(mObservers) {
-                boolean found = true;
-                while (found) {
-                    found = false;
-                    for (int i = 0; i < mObservers.size(); i += 2) {
-                        if (mObservers.get(i+1) == observer) {
-                            mObservers.remove(i+1);
-                            mObservers.remove(i);
-                            found = true;
-                            break;
-                        }
+            synchronized (mKeysAndObservers) {
+                for (int i = 0; i < mKeysAndObservers.size(); ) {
+                    if (mKeysAndObservers.get(i + 1) == observer) {
+                        mKeysAndObservers.remove(i + 1);
+                        final String match = (String)mKeysAndObservers.remove(i);
+                        nativeRemoveMatch(match);
+                    } else {
+                        i += 2;
                     }
                 }
             }
         }
     }
-
-    private static native void native_setup();
-    private static native int next_event(byte[] buffer);
-
-    private static final synchronized void ensureThreadStarted() {
-        if (sThreadStarted == false) {
-            sThread = new UEventThread();
-            sThread.start();
-            sThreadStarted = true;
-        }
-    }
-
-    /**
-     * Begin observation of UEvent's.<p>
-     * This method will cause the UEvent thread to start if this is the first
-     * invocation of startObserving in this process.<p>
-     * Once called, the UEvent thread will call onUEvent() when an incoming
-     * UEvent matches the specified string.<p>
-     * This method can be called multiple times to register multiple matches.
-     * Only one call to stopObserving is required even with multiple registered
-     * matches.
-     * @param match A substring of the UEvent to match. Use "" to match all
-     *              UEvent's
-     */
-    public final synchronized void startObserving(String match) {
-        ensureThreadStarted();
-        sThread.addObserver(match, this);
-    }
-
-    /**
-     * End observation of UEvent's.<p>
-     * This process's UEvent thread will never call onUEvent() on this
-     * UEventObserver after this call. Repeated calls have no effect.
-     */
-    public final synchronized void stopObserving() {
-        sThread.removeObserver(this);
-    }
-
-    /**
-     * Subclasses of UEventObserver should override this method to handle
-     * UEvents.
-     */
-    public abstract void onUEvent(UEvent event);
-
-    protected void finalize() throws Throwable {
-        try {
-            stopObserving();
-        } finally {
-            super.finalize();
-        }
-    }
 }
diff --git a/core/java/android/os/UserHandle.aidl b/core/java/android/os/UserHandle.aidl
new file mode 100644
index 0000000..4892d32
--- /dev/null
+++ b/core/java/android/os/UserHandle.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+parcelable UserHandle;
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
new file mode 100644
index 0000000..cc96152
--- /dev/null
+++ b/core/java/android/os/UserHandle.java
@@ -0,0 +1,260 @@
+/*
+ * 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.
+ */
+
+package android.os;
+
+/**
+ * Representation of a user on the device.
+ */
+public final class UserHandle implements Parcelable {
+    /**
+     * @hide Range of uids allocated for a user.
+     */
+    public static final int PER_USER_RANGE = 100000;
+
+    /** @hide A user id to indicate all users on the device */
+    public static final int USER_ALL = -1;
+
+    /** @hide A user handle to indicate all users on the device */
+    public static final UserHandle ALL = new UserHandle(USER_ALL);
+
+    /** @hide A user id to indicate the currently active user */
+    public static final int USER_CURRENT = -2;
+
+    /** @hide A user handle to indicate the current user of the device */
+    public static final UserHandle CURRENT = new UserHandle(USER_CURRENT);
+
+    /** @hide A user id to indicate that we would like to send to the current
+     *  user, but if this is calling from a user process then we will send it
+     *  to the caller's user instead of failing wiht a security exception */
+    public static final int USER_CURRENT_OR_SELF = -3;
+
+    /** @hide A user handle to indicate that we would like to send to the current
+     *  user, but if this is calling from a user process then we will send it
+     *  to the caller's user instead of failing wiht a security exception */
+    public static final UserHandle CURRENT_OR_SELF = new UserHandle(USER_CURRENT_OR_SELF);
+
+    /** @hide An undefined user id */
+    public static final int USER_NULL = -10000;
+
+    /** @hide A user id constant to indicate the "owner" user of the device */
+    public static final int USER_OWNER = 0;
+
+    /** @hide A user handle to indicate the primary/owner user of the device */
+    public static final UserHandle OWNER = new UserHandle(USER_OWNER);
+
+    /**
+     * @hide Enable multi-user related side effects. Set this to false if
+     * there are problems with single user use-cases.
+     */
+    public static final boolean MU_ENABLED = true;
+
+    final int mHandle;
+
+    /**
+     * Checks to see if the user id is the same for the two uids, i.e., they belong to the same
+     * user.
+     * @hide
+     */
+    public static final boolean isSameUser(int uid1, int uid2) {
+        return getUserId(uid1) == getUserId(uid2);
+    }
+
+    /**
+     * Checks to see if both uids are referring to the same app id, ignoring the user id part of the
+     * uids.
+     * @param uid1 uid to compare
+     * @param uid2 other uid to compare
+     * @return whether the appId is the same for both uids
+     * @hide
+     */
+    public static final boolean isSameApp(int uid1, int uid2) {
+        return getAppId(uid1) == getAppId(uid2);
+    }
+
+    /** @hide */
+    public static final boolean isIsolated(int uid) {
+        if (uid > 0) {
+            final int appId = getAppId(uid);
+            return appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID;
+        } else {
+            return false;
+        }
+    }
+
+    /** @hide */
+    public static boolean isApp(int uid) {
+        if (uid > 0) {
+            final int appId = getAppId(uid);
+            return appId >= Process.FIRST_APPLICATION_UID && appId <= Process.LAST_APPLICATION_UID;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Returns the user id for a given uid.
+     * @hide
+     */
+    public static final int getUserId(int uid) {
+        if (MU_ENABLED) {
+            return uid / PER_USER_RANGE;
+        } else {
+            return 0;
+        }
+    }
+
+    /** @hide */
+    public static final int getCallingUserId() {
+        return getUserId(Binder.getCallingUid());
+    }
+
+    /**
+     * Returns the uid that is composed from the userId and the appId.
+     * @hide
+     */
+    public static final int getUid(int userId, int appId) {
+        if (MU_ENABLED) {
+            return userId * PER_USER_RANGE + (appId % PER_USER_RANGE);
+        } else {
+            return appId;
+        }
+    }
+
+    /**
+     * Returns the app id (or base uid) for a given uid, stripping out the user id from it.
+     * @hide
+     */
+    public static final int getAppId(int uid) {
+        return uid % PER_USER_RANGE;
+    }
+
+    /**
+     * Returns the shared app gid for a given uid or appId.
+     * @hide
+     */
+    public static final int getSharedAppGid(int id) {
+        return Process.FIRST_SHARED_APPLICATION_GID + (id % PER_USER_RANGE)
+                - Process.FIRST_APPLICATION_UID;
+    }
+
+    /**
+     * Returns the user id of the current process
+     * @return user id of the current process
+     * @hide
+     */
+    public static final int myUserId() {
+        return getUserId(Process.myUid());
+    }
+
+    /** @hide */
+    public UserHandle(int h) {
+        mHandle = h;
+    }
+
+    /** @hide */
+    public int getIdentifier() {
+        return mHandle;
+    }
+
+    @Override
+    public String toString() {
+        return "UserHandle{" + mHandle + "}";
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        try {
+            if (obj != null) {
+                UserHandle other = (UserHandle)obj;
+                return mHandle == other.mHandle;
+            }
+        } catch (ClassCastException e) {
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return mHandle;
+    }
+    
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mHandle);
+    }
+
+    /**
+     * Write a UserHandle to a Parcel, handling null pointers.  Must be
+     * read with {@link #readFromParcel(Parcel)}.
+     * 
+     * @param h The UserHandle to be written.
+     * @param out The Parcel in which the UserHandle will be placed.
+     * 
+     * @see #readFromParcel(Parcel)
+     */
+    public static void writeToParcel(UserHandle h, Parcel out) {
+        if (h != null) {
+            h.writeToParcel(out, 0);
+        } else {
+            out.writeInt(USER_NULL);
+        }
+    }
+    
+    /**
+     * Read a UserHandle from a Parcel that was previously written
+     * with {@link #writeToParcel(UserHandle, Parcel)}, returning either
+     * a null or new object as appropriate.
+     * 
+     * @param in The Parcel from which to read the UserHandle
+     * @return Returns a new UserHandle matching the previously written
+     * object, or null if a null had been written.
+     * 
+     * @see #writeToParcel(UserHandle, Parcel)
+     */
+    public static UserHandle readFromParcel(Parcel in) {
+        int h = in.readInt();
+        return h != USER_NULL ? new UserHandle(h) : null;
+    }
+    
+    public static final Parcelable.Creator<UserHandle> CREATOR
+            = new Parcelable.Creator<UserHandle>() {
+        public UserHandle createFromParcel(Parcel in) {
+            return new UserHandle(in);
+        }
+
+        public UserHandle[] newArray(int size) {
+            return new UserHandle[size];
+        }
+    };
+
+    /**
+     * Instantiate a new UserHandle from the data in a Parcel that was
+     * previously written with {@link #writeToParcel(Parcel, int)}.  Note that you
+     * must not use this with data written by
+     * {@link #writeToParcel(UserHandle, Parcel)} since it is not possible
+     * to handle a null UserHandle here.
+     * 
+     * @param in The Parcel containing the previously written UserHandle,
+     * positioned at the location in the buffer where it was written.
+     */
+    public UserHandle(Parcel in) {
+        mHandle = in.readInt();
+    }
+}
diff --git a/core/java/android/os/UserId.java b/core/java/android/os/UserId.java
deleted file mode 100644
index 8bf6c6e..0000000
--- a/core/java/android/os/UserId.java
+++ /dev/null
@@ -1,116 +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.
- */
-
-package android.os;
-
-/**
- * @hide
- */
-public final class UserId {
-    /**
-     * Range of IDs allocated for a user.
-     *
-     * @hide
-     */
-    public static final int PER_USER_RANGE = 100000;
-
-    public static final int USER_ALL = -1;
-
-    /**
-     * Enable multi-user related side effects. Set this to false if there are problems with single
-     * user usecases.
-     * */
-    public static final boolean MU_ENABLED = true;
-
-    /**
-     * Checks to see if the user id is the same for the two uids, i.e., they belong to the same
-     * user.
-     * @hide
-     */
-    public static final boolean isSameUser(int uid1, int uid2) {
-        return getUserId(uid1) == getUserId(uid2);
-    }
-
-    /**
-     * Checks to see if both uids are referring to the same app id, ignoring the user id part of the
-     * uids.
-     * @param uid1 uid to compare
-     * @param uid2 other uid to compare
-     * @return whether the appId is the same for both uids
-     * @hide
-     */
-    public static final boolean isSameApp(int uid1, int uid2) {
-        return getAppId(uid1) == getAppId(uid2);
-    }
-
-    public static final boolean isIsolated(int uid) {
-        uid = getAppId(uid);
-        return uid >= Process.FIRST_ISOLATED_UID && uid <= Process.LAST_ISOLATED_UID;
-    }
-
-    public static boolean isApp(int uid) {
-        if (uid > 0) {
-            uid = UserId.getAppId(uid);
-            return uid >= Process.FIRST_APPLICATION_UID && uid <= Process.LAST_APPLICATION_UID;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Returns the user id for a given uid.
-     * @hide
-     */
-    public static final int getUserId(int uid) {
-        if (MU_ENABLED) {
-            return uid / PER_USER_RANGE;
-        } else {
-            return 0;
-        }
-    }
-
-    public static final int getCallingUserId() {
-        return getUserId(Binder.getCallingUid());
-    }
-
-    /**
-     * Returns the uid that is composed from the userId and the appId.
-     * @hide
-     */
-    public static final int getUid(int userId, int appId) {
-        if (MU_ENABLED) {
-            return userId * PER_USER_RANGE + (appId % PER_USER_RANGE);
-        } else {
-            return appId;
-        }
-    }
-
-    /**
-     * Returns the app id (or base uid) for a given uid, stripping out the user id from it.
-     * @hide
-     */
-    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/os/UserManager.java b/core/java/android/os/UserManager.java
new file mode 100644
index 0000000..d73f99a
--- /dev/null
+++ b/core/java/android/os/UserManager.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os;
+
+import com.android.internal.R;
+
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.content.res.Resources;
+import android.util.Log;
+
+import java.util.List;
+
+/**
+ * Manages users and user details on a multi-user system.
+ */
+public class UserManager {
+
+    private static String TAG = "UserManager";
+    private final IUserManager mService;
+    private final Context mContext;
+
+    /** @hide */
+    public UserManager(Context context, IUserManager service) {
+        mService = service;
+        mContext = context;
+    }
+
+    /**
+     * Returns whether the system supports multiple users.
+     * @return true if multiple users can be created, false if it is a single user device.
+     * @hide
+     */
+    public static boolean supportsMultipleUsers() {
+        return getMaxSupportedUsers() > 1;
+    }
+
+    /** 
+     * Returns the user handle for the user that this application is running for.
+     * @return the user handle of the user making this call.
+     * @hide
+     * */
+    public int getUserHandle() {
+        return UserHandle.myUserId();
+    }
+
+    /**
+     * Returns the user name of the user making this call.  This call is only
+     * available to applications on the system image; it requires the
+     * MANAGE_USERS permission.
+     * @return the user name
+     */
+    public String getUserName() {
+        try {
+            return mService.getUserInfo(getUserHandle()).name;
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not get user name", re);
+            return "";
+        }
+    }
+
+   /**
+     * Used to determine whether the user making this call is subject to
+     * teleportations.
+     * @return whether the user making this call is a goat 
+     */
+    public boolean isUserAGoat() {
+        return false;
+    }
+ 
+    /**
+     * Return whether the given user is actively running.  This means that
+     * the user is in the "started" state, not "stopped" -- it is currently
+     * allowed to run code through scheduled alarms, receiving broadcasts,
+     * etc.  A started user may be either the current foreground user or a
+     * background user; the result here does not distinguish between the two.
+     * @param user The user to retrieve the running state for.
+     */
+    public boolean isUserRunning(UserHandle user) {
+        try {
+            return ActivityManagerNative.getDefault().isUserRunning(
+                    user.getIdentifier(), false);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Return whether the given user is actively running <em>or</em> stopping.
+     * This is like {@link #isUserRunning(UserHandle)}, but will also return
+     * true if the user had been running but is in the process of being stopped
+     * (but is not yet fully stopped, and still running some code).
+     * @param user The user to retrieve the running state for.
+     */
+    public boolean isUserRunningOrStopping(UserHandle user) {
+        try {
+            return ActivityManagerNative.getDefault().isUserRunning(
+                    user.getIdentifier(), true);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Returns the UserInfo object describing a specific user.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * @param userHandle the user handle of the user whose information is being requested.
+     * @return the UserInfo object for a specific user.
+     * @hide
+     */
+    public UserInfo getUserInfo(int userHandle) {
+        try {
+            return mService.getUserInfo(userHandle);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not get user info", re);
+            return null;
+        }
+    }
+
+    /**
+     * Return the serial number for a user.  This is a device-unique
+     * number assigned to that user; if the user is deleted and then a new
+     * user created, the new users will not be given the same serial number.
+     * @param user The user whose serial number is to be retrieved.
+     * @return The serial number of the given user; returns -1 if the
+     * given UserHandle does not exist.
+     * @see #getUserForSerialNumber(long)
+     */
+    public long getSerialNumberForUser(UserHandle user) {
+        return getUserSerialNumber(user.getIdentifier());
+    }
+
+    /**
+     * Return the user associated with a serial number previously
+     * returned by {@link #getSerialNumberForUser(UserHandle)}.
+     * @param serialNumber The serial number of the user that is being
+     * retrieved.
+     * @return Return the user associated with the serial number, or null
+     * if there is not one.
+     * @see #getSerialNumberForUser(UserHandle)
+     */
+    public UserHandle getUserForSerialNumber(long serialNumber) {
+        int ident = getUserHandle((int)serialNumber);
+        return ident >= 0 ? new UserHandle(ident) : null;
+    }
+
+    /**
+     * Creates a user with the specified name and options.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     *
+     * @param name the user's name
+     * @param flags flags that identify the type of user and other properties.
+     * @see UserInfo
+     *
+     * @return the UserInfo object for the created user, or null if the user could not be created.
+     * @hide
+     */
+    public UserInfo createUser(String name, int flags) {
+        try {
+            return mService.createUser(name, flags);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not create a user", re);
+            return null;
+        }
+    }
+
+    /**
+     * Return the number of users currently created on the device.
+     */
+    public int getUserCount() {
+        List<UserInfo> users = getUsers();
+        return users != null ? users.size() : 1;
+    }
+
+    /**
+     * Returns information for all users on this device.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * @return the list of users that were created.
+     * @hide
+     */
+    public List<UserInfo> getUsers() {
+        try {
+            return mService.getUsers(false);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not get user list", re);
+            return null;
+        }
+    }
+
+    /**
+     * Returns information for all users on this device.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * @param excludeDying specify if the list should exclude users being removed.
+     * @return the list of users that were created.
+     * @hide
+     */
+    public List<UserInfo> getUsers(boolean excludeDying) {
+        try {
+            return mService.getUsers(excludeDying);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not get user list", re);
+            return null;
+        }
+    }
+
+    /**
+     * Removes a user and all associated data.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * @param userHandle the integer handle of the user, where 0 is the primary user.
+     * @hide
+     */
+    public boolean removeUser(int userHandle) {
+        try {
+            return mService.removeUser(userHandle);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not remove user ", re);
+            return false;
+        }
+    }
+
+    /**
+     * Updates the user's name.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     *
+     * @param userHandle the user's integer handle
+     * @param name the new name for the user
+     * @hide
+     */
+    public void setUserName(int userHandle, String name) {
+        try {
+            mService.setUserName(userHandle, name);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not set the user name ", re);
+        }
+    }
+
+    /**
+     * Sets the user's photo.
+     * @param userHandle the user for whom to change the photo.
+     * @param icon the bitmap to set as the photo.
+     * @hide
+     */
+    public void setUserIcon(int userHandle, Bitmap icon) {
+        try {
+            mService.setUserIcon(userHandle, icon);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not set the user icon ", re);
+        }
+    }
+
+    /**
+     * Returns a file descriptor for the user's photo. PNG data can be read from this file.
+     * @param userHandle the user whose photo we want to read.
+     * @return a {@link Bitmap} of the user's photo, or null if there's no photo.
+     * @hide
+     */
+    public Bitmap getUserIcon(int userHandle) {
+        try {
+            return mService.getUserIcon(userHandle);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not get the user icon ", re);
+            return null;
+        }
+    }
+
+    /**
+     * Enable or disable the use of a guest account. If disabled, the existing guest account
+     * will be wiped.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * @param enable whether to enable a guest account.
+     * @hide
+     */
+    public void setGuestEnabled(boolean enable) {
+        try {
+            mService.setGuestEnabled(enable);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not change guest account availability to " + enable);
+        }
+    }
+
+    /**
+     * Checks if a guest user is enabled for this device.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * @return whether a guest user is enabled
+     * @hide
+     */
+    public boolean isGuestEnabled() {
+        try {
+            return mService.isGuestEnabled();
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not retrieve guest enabled state");
+            return false;
+        }
+    }
+
+    /**
+     * Wipes all the data for a user, but doesn't remove the user.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * @param userHandle
+     * @hide
+     */
+    public void wipeUser(int userHandle) {
+        try {
+            mService.wipeUser(userHandle);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not wipe user " + userHandle);
+        }
+    }
+
+    /**
+     * Returns the maximum number of users that can be created on this device. A return value
+     * of 1 means that it is a single user device.
+     * @hide
+     * @return a value greater than or equal to 1 
+     */
+    public static int getMaxSupportedUsers() {
+        // Don't allow multiple users on certain builds
+        if (android.os.Build.ID.startsWith("JVP")) return 1;
+        return SystemProperties.getInt("fw.max_users",
+                Resources.getSystem().getInteger(R.integer.config_multiuserMaximumUsers));
+    }
+
+    /**
+     * Returns a serial number on this device for a given userHandle. User handles can be recycled
+     * when deleting and creating users, but serial numbers are not reused until the device is wiped.
+     * @param userHandle
+     * @return a serial number associated with that user, or -1 if the userHandle is not valid.
+     * @hide
+     */
+    public int getUserSerialNumber(int userHandle) {
+        try {
+            return mService.getUserSerialNumber(userHandle);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not get serial number for user " + userHandle);
+        }
+        return -1;
+    }
+
+    /**
+     * Returns a userHandle on this device for a given user serial number. User handles can be
+     * recycled when deleting and creating users, but serial numbers are not reused until the device
+     * is wiped.
+     * @param userSerialNumber
+     * @return the userHandle associated with that user serial number, or -1 if the serial number
+     * is not valid.
+     * @hide
+     */
+    public int getUserHandle(int userSerialNumber) {
+        try {
+            return mService.getUserHandle(userSerialNumber);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not get userHandle for user " + userSerialNumber);
+        }
+        return -1;
+    }
+}
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index 287c136..ba77df7 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -1,5 +1,9 @@
 package android.os;
 
+import com.android.internal.util.ArrayUtils;
+
+import java.util.Arrays;
+
 /**
  * Describes the source of some work that may be done by someone else.
  * Currently the public representation of what a work source is is not
@@ -76,6 +80,20 @@
         mNum = 0;
     }
 
+    @Override
+    public boolean equals(Object o) {
+        return o instanceof WorkSource && !diff((WorkSource)o);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = 0;
+        for (int i = 0; i < mNum; i++) {
+            result = ((result << 4) | (result >>> 28)) ^ mUids[i];
+        }
+        return result;
+    }
+
     /**
      * Compare this WorkSource with another.
      * @param other The WorkSource to compare against.
@@ -299,6 +317,20 @@
         dest.writeIntArray(mUids);
     }
 
+    @Override
+    public String toString() {
+        StringBuilder result = new StringBuilder();
+        result.append("{WorkSource: uids=[");
+        for (int i = 0; i < mNum; i++) {
+            if (i != 0) {
+                result.append(", ");
+            }
+            result.append(mUids[i]);
+        }
+        result.append("]}");
+        return result.toString();
+    }
+
     public static final Parcelable.Creator<WorkSource> CREATOR
             = new Parcelable.Creator<WorkSource>() {
         public WorkSource createFromParcel(Parcel in) {
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index ab64866..fc18617 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -489,13 +489,14 @@
              * IObbActionListener to inform it of the terminal state of the
              * call.
              */
-            public void mountObb(String filename, String key, IObbActionListener token, int nonce)
-                    throws RemoteException {
+            public void mountObb(String rawPath, String canonicalPath, String key,
+                    IObbActionListener token, int nonce) throws RemoteException {
                 Parcel _data = Parcel.obtain();
                 Parcel _reply = Parcel.obtain();
                 try {
                     _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(filename);
+                    _data.writeString(rawPath);
+                    _data.writeString(canonicalPath);
                     _data.writeString(key);
                     _data.writeStrongBinder((token != null ? token.asBinder() : null));
                     _data.writeInt(nonce);
@@ -514,13 +515,14 @@
              * IObbActionListener to inform it of the terminal state of the
              * call.
              */
-            public void unmountObb(String filename, boolean force, IObbActionListener token,
-                    int nonce) throws RemoteException {
+            public void unmountObb(
+                    String rawPath, boolean force, IObbActionListener token, int nonce)
+                    throws RemoteException {
                 Parcel _data = Parcel.obtain();
                 Parcel _reply = Parcel.obtain();
                 try {
                     _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(filename);
+                    _data.writeString(rawPath);
                     _data.writeInt((force ? 1 : 0));
                     _data.writeStrongBinder((token != null ? token.asBinder() : null));
                     _data.writeInt(nonce);
@@ -536,13 +538,13 @@
              * Checks whether the specified Opaque Binary Blob (OBB) is mounted
              * somewhere.
              */
-            public boolean isObbMounted(String filename) throws RemoteException {
+            public boolean isObbMounted(String rawPath) throws RemoteException {
                 Parcel _data = Parcel.obtain();
                 Parcel _reply = Parcel.obtain();
                 boolean _result;
                 try {
                     _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(filename);
+                    _data.writeString(rawPath);
                     mRemote.transact(Stub.TRANSACTION_isObbMounted, _data, _reply, 0);
                     _reply.readException();
                     _result = 0 != _reply.readInt();
@@ -556,13 +558,13 @@
             /**
              * Gets the path to the mounted Opaque Binary Blob (OBB).
              */
-            public String getMountedObbPath(String filename) throws RemoteException {
+            public String getMountedObbPath(String rawPath) throws RemoteException {
                 Parcel _data = Parcel.obtain();
                 Parcel _reply = Parcel.obtain();
                 String _result;
                 try {
                     _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(filename);
+                    _data.writeString(rawPath);
                     mRemote.transact(Stub.TRANSACTION_getMountedObbPath, _data, _reply, 0);
                     _reply.readException();
                     _result = _reply.readString();
@@ -677,15 +679,15 @@
                 return _result;
             }
 
-            public Parcelable[] getVolumeList() throws RemoteException {
+            public StorageVolume[] getVolumeList() throws RemoteException {
                 Parcel _data = Parcel.obtain();
                 Parcel _reply = Parcel.obtain();
-                Parcelable[] _result;
+                StorageVolume[] _result;
                 try {
                     _data.writeInterfaceToken(DESCRIPTOR);
                     mRemote.transact(Stub.TRANSACTION_getVolumeList, _data, _reply, 0);
                     _reply.readException();
-                    _result = _reply.readParcelableArray(StorageVolume.class.getClassLoader());
+                    _result = _reply.createTypedArray(StorageVolume.CREATOR);
                 } finally {
                     _reply.recycle();
                     _data.recycle();
@@ -1042,15 +1044,14 @@
                 }
                 case TRANSACTION_mountObb: {
                     data.enforceInterface(DESCRIPTOR);
-                    String filename;
-                    filename = data.readString();
-                    String key;
-                    key = data.readString();
+                    final String rawPath = data.readString();
+                    final String canonicalPath = data.readString();
+                    final String key = data.readString();
                     IObbActionListener observer;
                     observer = IObbActionListener.Stub.asInterface(data.readStrongBinder());
                     int nonce;
                     nonce = data.readInt();
-                    mountObb(filename, key, observer, nonce);
+                    mountObb(rawPath, canonicalPath, key, observer, nonce);
                     reply.writeNoException();
                     return true;
                 }
@@ -1119,9 +1120,9 @@
                 }
                 case TRANSACTION_getVolumeList: {
                     data.enforceInterface(DESCRIPTOR);
-                    Parcelable[] result = getVolumeList();
+                    StorageVolume[] result = getVolumeList();
                     reply.writeNoException();
-                    reply.writeParcelableArray(result, 0);
+                    reply.writeTypedArray(result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                     return true;
                 }
                 case TRANSACTION_getSecureContainerFilesystemPath: {
@@ -1194,7 +1195,7 @@
     /**
      * Gets the path to the mounted Opaque Binary Blob (OBB).
      */
-    public String getMountedObbPath(String filename) throws RemoteException;
+    public String getMountedObbPath(String rawPath) throws RemoteException;
 
     /**
      * Gets an Array of currently known secure container IDs
@@ -1220,7 +1221,7 @@
      * Checks whether the specified Opaque Binary Blob (OBB) is mounted
      * somewhere.
      */
-    public boolean isObbMounted(String filename) throws RemoteException;
+    public boolean isObbMounted(String rawPath) throws RemoteException;
 
     /*
      * Returns true if the specified container is mounted
@@ -1243,8 +1244,8 @@
      * MountService will call back to the supplied IObbActionListener to inform
      * it of the terminal state of the call.
      */
-    public void mountObb(String filename, String key, IObbActionListener token, int nonce)
-            throws RemoteException;
+    public void mountObb(String rawPath, String canonicalPath, String key,
+            IObbActionListener token, int nonce) throws RemoteException;
 
     /*
      * Mount a secure container with the specified key and owner UID. Returns an
@@ -1287,7 +1288,7 @@
      * MountService will call back to the supplied IObbActionListener to inform
      * it of the terminal state of the call.
      */
-    public void unmountObb(String filename, boolean force, IObbActionListener token, int nonce)
+    public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce)
             throws RemoteException;
 
     /*
@@ -1358,7 +1359,7 @@
     /**
      * Returns list of all mountable volumes.
      */
-    public Parcelable[] getVolumeList() throws RemoteException;
+    public StorageVolume[] getVolumeList() throws RemoteException;
 
     /**
      * Gets the path on the filesystem for the ASEC container itself.
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 8a20a6e..862a95c 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -16,6 +16,8 @@
 
 package android.os.storage;
 
+import android.app.NotificationManager;
+import android.content.Context;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.Looper;
@@ -26,6 +28,10 @@
 import android.util.Log;
 import android.util.SparseArray;
 
+import com.android.internal.util.Preconditions;
+
+import java.io.File;
+import java.io.IOException;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
@@ -285,6 +291,11 @@
         }
     }
 
+    /** {@hide} */
+    public static StorageManager from(Context context) {
+        return (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
+    }
+
     /**
      * Constructs a StorageManager object through which an application can
      * can communicate with the systems mount service.
@@ -436,25 +447,23 @@
      * That is, shared UID applications can attempt to mount any other
      * application's OBB that shares its UID.
      * 
-     * @param filename the path to the OBB file
+     * @param rawPath the path to the OBB file
      * @param key secret used to encrypt the OBB; may be <code>null</code> if no
      *            encryption was used on the OBB.
      * @param listener will receive the success or failure of the operation
      * @return whether the mount call was successfully queued or not
      */
-    public boolean mountObb(String filename, String key, OnObbStateChangeListener listener) {
-        if (filename == null) {
-            throw new IllegalArgumentException("filename cannot be null");
-        }
-
-        if (listener == null) {
-            throw new IllegalArgumentException("listener cannot be null");
-        }
+    public boolean mountObb(String rawPath, String key, OnObbStateChangeListener listener) {
+        Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
+        Preconditions.checkNotNull(listener, "listener cannot be null");
 
         try {
+            final String canonicalPath = new File(rawPath).getCanonicalPath();
             final int nonce = mObbActionListener.addListener(listener);
-            mMountService.mountObb(filename, key, mObbActionListener, nonce);
+            mMountService.mountObb(rawPath, canonicalPath, key, mObbActionListener, nonce);
             return true;
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Failed to resolve path: " + rawPath, e);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to mount OBB", e);
         }
@@ -476,24 +485,19 @@
      * application's OBB that shares its UID.
      * <p>
      * 
-     * @param filename path to the OBB file
+     * @param rawPath path to the OBB file
      * @param force whether to kill any programs using this in order to unmount
      *            it
      * @param listener will receive the success or failure of the operation
      * @return whether the unmount call was successfully queued or not
      */
-    public boolean unmountObb(String filename, boolean force, OnObbStateChangeListener listener) {
-        if (filename == null) {
-            throw new IllegalArgumentException("filename cannot be null");
-        }
-
-        if (listener == null) {
-            throw new IllegalArgumentException("listener cannot be null");
-        }
+    public boolean unmountObb(String rawPath, boolean force, OnObbStateChangeListener listener) {
+        Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
+        Preconditions.checkNotNull(listener, "listener cannot be null");
 
         try {
             final int nonce = mObbActionListener.addListener(listener);
-            mMountService.unmountObb(filename, force, mObbActionListener, nonce);
+            mMountService.unmountObb(rawPath, force, mObbActionListener, nonce);
             return true;
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to mount OBB", e);
@@ -505,16 +509,14 @@
     /**
      * Check whether an Opaque Binary Blob (OBB) is mounted or not.
      * 
-     * @param filename path to OBB image
+     * @param rawPath path to OBB image
      * @return true if OBB is mounted; false if not mounted or on error
      */
-    public boolean isObbMounted(String filename) {
-        if (filename == null) {
-            throw new IllegalArgumentException("filename cannot be null");
-        }
+    public boolean isObbMounted(String rawPath) {
+        Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
 
         try {
-            return mMountService.isObbMounted(filename);
+            return mMountService.isObbMounted(rawPath);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to check if OBB is mounted", e);
         }
@@ -527,17 +529,15 @@
      * give you the path to where you can obtain access to the internals of the
      * OBB.
      * 
-     * @param filename path to OBB image
+     * @param rawPath path to OBB image
      * @return absolute path to mounted OBB image data or <code>null</code> if
      *         not mounted or exception encountered trying to read status
      */
-    public String getMountedObbPath(String filename) {
-        if (filename == null) {
-            throw new IllegalArgumentException("filename cannot be null");
-        }
+    public String getMountedObbPath(String rawPath) {
+        Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
 
         try {
-            return mMountService.getMountedObbPath(filename);
+            return mMountService.getMountedObbPath(rawPath);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to find mounted path for OBB", e);
         }
@@ -594,4 +594,20 @@
         }
         return paths;
     }
+
+    /** {@hide} */
+    public StorageVolume getPrimaryVolume() {
+        return getPrimaryVolume(getVolumeList());
+    }
+
+    /** {@hide} */
+    public static StorageVolume getPrimaryVolume(StorageVolume[] volumes) {
+        for (StorageVolume volume : volumes) {
+            if (volume.isPrimary()) {
+                return volume;
+            }
+        }
+        Log.w(TAG, "No primary storage defined");
+        return null;
+    }
 }
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index 79c8f3b..177a955 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -19,53 +19,69 @@
 import android.content.Context;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
+
+import java.io.File;
 
 /**
- * A class representing a storage volume
+ * Description of a storage volume and its capabilities, including the
+ * filesystem path where it may be mounted.
+ *
  * @hide
  */
 public class StorageVolume implements Parcelable {
 
-    //private static final String TAG = "StorageVolume";
+    // TODO: switch to more durable token
+    private int mStorageId;
 
-    private final String mPath;
+    private final File mPath;
     private final int mDescriptionId;
+    private final boolean mPrimary;
     private final boolean mRemovable;
     private final boolean mEmulated;
     private final int mMtpReserveSpace;
     private final boolean mAllowMassStorage;
-    private int mStorageId;
-    // maximum file size for the storage, or zero for no limit
+    /** Maximum file size for the storage, or zero for no limit */
     private final long mMaxFileSize;
+    /** When set, indicates exclusive ownership of this volume */
+    private final UserHandle mOwner;
 
     // StorageVolume extra for ACTION_MEDIA_REMOVED, ACTION_MEDIA_UNMOUNTED, ACTION_MEDIA_CHECKING,
     // ACTION_MEDIA_NOFS, ACTION_MEDIA_MOUNTED, ACTION_MEDIA_SHARED, ACTION_MEDIA_UNSHARED,
     // ACTION_MEDIA_BAD_REMOVAL, ACTION_MEDIA_UNMOUNTABLE and ACTION_MEDIA_EJECT broadcasts.
     public static final String EXTRA_STORAGE_VOLUME = "storage_volume";
 
-    public StorageVolume(String path, int descriptionId, boolean removable,
-            boolean emulated, int mtpReserveSpace, boolean allowMassStorage, long maxFileSize) {
+    public StorageVolume(File path, int descriptionId, boolean primary, boolean removable,
+            boolean emulated, int mtpReserveSpace, boolean allowMassStorage, long maxFileSize,
+            UserHandle owner) {
         mPath = path;
         mDescriptionId = descriptionId;
+        mPrimary = primary;
         mRemovable = removable;
         mEmulated = emulated;
         mMtpReserveSpace = mtpReserveSpace;
         mAllowMassStorage = allowMassStorage;
         mMaxFileSize = maxFileSize;
+        mOwner = owner;
     }
 
-    // for parcelling only
-    private StorageVolume(String path, int descriptionId, boolean removable,
-            boolean emulated, int mtpReserveSpace, int storageId,
-            boolean allowMassStorage, long maxFileSize) {
-        mPath = path;
-        mDescriptionId = descriptionId;
-        mRemovable = removable;
-        mEmulated = emulated;
-        mMtpReserveSpace = mtpReserveSpace;
-        mAllowMassStorage = allowMassStorage;
-        mStorageId = storageId;
-        mMaxFileSize = maxFileSize;
+    private StorageVolume(Parcel in) {
+        mStorageId = in.readInt();
+        mPath = new File(in.readString());
+        mDescriptionId = in.readInt();
+        mPrimary = in.readInt() != 0;
+        mRemovable = in.readInt() != 0;
+        mEmulated = in.readInt() != 0;
+        mMtpReserveSpace = in.readInt();
+        mAllowMassStorage = in.readInt() != 0;
+        mMaxFileSize = in.readLong();
+        mOwner = in.readParcelable(null);
+    }
+
+    public static StorageVolume fromTemplate(StorageVolume template, File path, UserHandle owner) {
+        return new StorageVolume(path, template.mDescriptionId, template.mPrimary,
+                template.mRemovable, template.mEmulated, template.mMtpReserveSpace,
+                template.mAllowMassStorage, template.mMaxFileSize, owner);
     }
 
     /**
@@ -74,6 +90,10 @@
      * @return the mount path
      */
     public String getPath() {
+        return mPath.toString();
+    }
+
+    public File getPathFile() {
         return mPath;
     }
 
@@ -90,6 +110,10 @@
         return mDescriptionId;
     }
 
+    public boolean isPrimary() {
+        return mPrimary;
+    }
+
     /**
      * Returns true if the volume is removable.
      *
@@ -161,6 +185,10 @@
         return mMaxFileSize;
     }
 
+    public UserHandle getOwner() {
+        return mOwner;
+    }
+
     @Override
     public boolean equals(Object obj) {
         if (obj instanceof StorageVolume && mPath != null) {
@@ -177,45 +205,49 @@
 
     @Override
     public String toString() {
-        return "StorageVolume [mAllowMassStorage=" + mAllowMassStorage + ", mDescriptionId="
-                + mDescriptionId + ", mEmulated=" + mEmulated + ", mMaxFileSize=" + mMaxFileSize
-                + ", mMtpReserveSpace=" + mMtpReserveSpace + ", mPath=" + mPath + ", mRemovable="
-                + mRemovable + ", mStorageId=" + mStorageId + "]";
+        final StringBuilder builder = new StringBuilder("StorageVolume [");
+        builder.append("mStorageId=").append(mStorageId);
+        builder.append(" mPath=").append(mPath);
+        builder.append(" mDescriptionId=").append(mDescriptionId);
+        builder.append(" mPrimary=").append(mPrimary);
+        builder.append(" mRemovable=").append(mRemovable);
+        builder.append(" mEmulated=").append(mEmulated);
+        builder.append(" mMtpReserveSpace=").append(mMtpReserveSpace);
+        builder.append(" mAllowMassStorage=").append(mAllowMassStorage);
+        builder.append(" mMaxFileSize=").append(mMaxFileSize);
+        builder.append(" mOwner=").append(mOwner);
+        builder.append("]");
+        return builder.toString();
     }
 
-    public static final Parcelable.Creator<StorageVolume> CREATOR =
-        new Parcelable.Creator<StorageVolume>() {
+    public static final Creator<StorageVolume> CREATOR = new Creator<StorageVolume>() {
+        @Override
         public StorageVolume createFromParcel(Parcel in) {
-            String path = in.readString();
-            int descriptionId = in.readInt();
-            int removable = in.readInt();
-            int emulated = in.readInt();
-            int storageId = in.readInt();
-            int mtpReserveSpace = in.readInt();
-            int allowMassStorage = in.readInt();
-            long maxFileSize = in.readLong();
-            return new StorageVolume(path, descriptionId,
-                    removable == 1, emulated == 1, mtpReserveSpace,
-                    storageId, allowMassStorage == 1, maxFileSize);
+            return new StorageVolume(in);
         }
 
+        @Override
         public StorageVolume[] newArray(int size) {
             return new StorageVolume[size];
         }
     };
 
+    @Override
     public int describeContents() {
         return 0;
     }
 
+    @Override
     public void writeToParcel(Parcel parcel, int flags) {
-        parcel.writeString(mPath);
+        parcel.writeInt(mStorageId);
+        parcel.writeString(mPath.toString());
         parcel.writeInt(mDescriptionId);
+        parcel.writeInt(mPrimary ? 1 : 0);
         parcel.writeInt(mRemovable ? 1 : 0);
         parcel.writeInt(mEmulated ? 1 : 0);
-        parcel.writeInt(mStorageId);
         parcel.writeInt(mMtpReserveSpace);
         parcel.writeInt(mAllowMassStorage ? 1 : 0);
         parcel.writeLong(mMaxFileSize);
+        parcel.writeParcelable(mOwner, flags);
     }
 }
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 9bfa8c0..09ff7be 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -1083,6 +1083,12 @@
                 }
                 return;
             }
+            if (mSinglePane) {
+                mFragmentBreadCrumbs.setVisibility(View.GONE);
+                // Hide the breadcrumb section completely for single-pane
+                View bcSection = findViewById(com.android.internal.R.id.breadcrumb_section);
+                if (bcSection != null) bcSection.setVisibility(View.GONE);
+            }
             mFragmentBreadCrumbs.setMaxVisible(2);
             mFragmentBreadCrumbs.setActivity(this);
         }
diff --git a/core/java/android/preference/TwoStatePreference.java b/core/java/android/preference/TwoStatePreference.java
index d186b20..c649879 100644
--- a/core/java/android/preference/TwoStatePreference.java
+++ b/core/java/android/preference/TwoStatePreference.java
@@ -37,6 +37,7 @@
     private CharSequence mSummaryOn;
     private CharSequence mSummaryOff;
     boolean mChecked;
+    private boolean mCheckedSet;
     private boolean mSendClickAccessibilityEvent;
     private boolean mDisableDependentsState;
 
@@ -74,11 +75,16 @@
      * @param checked The checked state.
      */
     public void setChecked(boolean checked) {
-        if (mChecked != checked) {
+        // Always persist/notify the first time; don't assume the field's default of false.
+        final boolean changed = mChecked != checked;
+        if (changed || !mCheckedSet) {
             mChecked = checked;
+            mCheckedSet = true;
             persistBoolean(checked);
-            notifyDependencyChange(shouldDisableDependents());
-            notifyChanged();
+            if (changed) {
+                notifyDependencyChange(shouldDisableDependents());
+                notifyChanged();
+            }
         }
     }
 
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index a28585c..af6e88e9 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -467,6 +467,13 @@
          *
          */
         public static final String ALLOWED_ATTENDEE_TYPES = "allowedAttendeeTypes";
+
+        /**
+         * Is this the primary calendar for this account. If this column is not explicitly set, the
+         * provider will return 1 if {@link Calendars#ACCOUNT_NAME} is equal to
+         * {@link Calendars#OWNER_ACCOUNT}.
+         */
+        public static final String IS_PRIMARY = "isPrimary";
     }
 
     /**
@@ -1206,6 +1213,14 @@
         public static final String ORGANIZER = "organizer";
 
         /**
+         * Are we the organizer of this event. If this column is not explicitly set, the provider
+         * will return 1 if {@link #ORGANIZER} is equal to {@link Calendars#OWNER_ACCOUNT}.
+         * Column name.
+         * <P>Type: STRING</P>
+         */
+        public static final String IS_ORGANIZER = "isOrganizer";
+
+        /**
          * Whether the user can invite others to the event. The
          * GUESTS_CAN_INVITE_OTHERS is a setting that applies to an arbitrary
          * guest, while CAN_INVITE_OTHERS indicates if the user can invite
@@ -1230,6 +1245,12 @@
          */
         public static final String CUSTOM_APP_URI = "customAppUri";
 
+        /**
+         * The UID for events added from the RFC 2445 iCalendar format.
+         * Column name.
+         * <P>Type: TEXT</P>
+         */
+        public static final String UID_2445 = "uid2445";
     }
 
     /**
@@ -1367,7 +1388,9 @@
                 DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, GUESTS_CAN_SEE_GUESTS);
                 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, CUSTOM_APP_PACKAGE);
                 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, CUSTOM_APP_URI);
+                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, UID_2445);
                 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, ORGANIZER);
+                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, IS_ORGANIZER);
                 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, _SYNC_ID);
                 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, DIRTY);
                 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, LAST_SYNCED);
@@ -1571,6 +1594,7 @@
      * <li>{@link #GUESTS_CAN_SEE_GUESTS}</li>
      * <li>{@link #CUSTOM_APP_PACKAGE}</li>
      * <li>{@link #CUSTOM_APP_URI}</li>
+     * <li>{@link #UID_2445}</li>
      * </ul>
      * The following Events columns are writable only by a sync adapter
      * <ul>
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 22b68bc..5dca67f 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -17,9 +17,6 @@
 
 package android.provider;
 
-import com.android.internal.telephony.CallerInfo;
-import com.android.internal.telephony.PhoneConstants;
-
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
@@ -30,6 +27,9 @@
 import android.provider.ContactsContract.DataUsageFeedback;
 import android.text.TextUtils;
 
+import com.android.internal.telephony.CallerInfo;
+import com.android.internal.telephony.PhoneConstants;
+
 /**
  * The CallLog provider contains information about placed and received calls.
  */
@@ -59,6 +59,20 @@
                 Uri.parse("content://call_log/calls/filter");
 
         /**
+         * Query parameter used to limit the number of call logs returned.
+         * <p>
+         * TYPE: integer
+         */
+        public static final String LIMIT_PARAM_KEY = "limit";
+
+        /**
+         * Query parameter used to specify the starting record to return.
+         * <p>
+         * TYPE: integer
+         */
+        public static final String OFFSET_PARAM_KEY = "offset";
+
+        /**
          * An optional URI parameter which instructs the provider to allow the operation to be
          * applied to voicemail records as well.
          * <p>
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index e7b0579..5b49ba3 100755
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -37,6 +37,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.Pair;
@@ -345,10 +346,10 @@
      * directory provider URIs by themselves. This level of indirection allows
      * Contacts Provider to implement additional system-level features and
      * optimizations. Access to Contacts Provider is protected by the
-     * READ_CONTACTS permission, but access to the directory provider is not.
-     * Therefore directory providers must reject requests coming from clients
-     * other than the Contacts Provider itself. An easy way to prevent such
-     * unauthorized access is to check the name of the calling package:
+     * READ_CONTACTS permission, but access to the directory provider is protected by
+     * BIND_DIRECTORY_SEARCH. This permission was introduced at the API level 17, for previous
+     * platform versions the provider should perform the following check to make sure the call
+     * is coming from the ContactsProvider:
      * <pre>
      * private boolean isCallerAllowed() {
      *   PackageManager pm = getContext().getPackageManager();
@@ -7658,6 +7659,54 @@
         public static final int MODE_LARGE = 3;
 
         /**
+         * Constructs the QuickContacts intent with a view's rect.
+         * @hide
+         */
+        public static Intent composeQuickContactsIntent(Context context, View target, Uri lookupUri,
+                int mode, String[] excludeMimes) {
+            // Find location and bounds of target view, adjusting based on the
+            // assumed local density.
+            final float appScale = context.getResources().getCompatibilityInfo().applicationScale;
+            final int[] pos = new int[2];
+            target.getLocationOnScreen(pos);
+
+            final Rect rect = new Rect();
+            rect.left = (int) (pos[0] * appScale + 0.5f);
+            rect.top = (int) (pos[1] * appScale + 0.5f);
+            rect.right = (int) ((pos[0] + target.getWidth()) * appScale + 0.5f);
+            rect.bottom = (int) ((pos[1] + target.getHeight()) * appScale + 0.5f);
+
+            return composeQuickContactsIntent(context, rect, lookupUri, mode, excludeMimes);
+        }
+
+        /**
+         * Constructs the QuickContacts intent.
+         * @hide
+         */
+        public static Intent composeQuickContactsIntent(Context context, Rect target,
+                Uri lookupUri, int mode, String[] excludeMimes) {
+            // When launching from an Activiy, we don't want to start a new task, but otherwise
+            // we *must* start a new task.  (Otherwise startActivity() would crash.)
+            Context actualContext = context;
+            while ((actualContext instanceof ContextWrapper)
+                    && !(actualContext instanceof Activity)) {
+                actualContext = ((ContextWrapper) actualContext).getBaseContext();
+            }
+            final int intentFlags = (actualContext instanceof Activity)
+                    ? Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
+                    : Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK;
+
+            // Launch pivot dialog through intent for now
+            final Intent intent = new Intent(ACTION_QUICK_CONTACT).addFlags(intentFlags);
+
+            intent.setData(lookupUri);
+            intent.setSourceBounds(target);
+            intent.putExtra(EXTRA_MODE, mode);
+            intent.putExtra(EXTRA_EXCLUDE_MIMES, excludeMimes);
+            return intent;
+        }
+
+        /**
          * Trigger a dialog that lists the various methods of interacting with
          * the requested {@link Contacts} entry. This may be based on available
          * {@link ContactsContract.Data} rows under that contact, and may also
@@ -7682,20 +7731,10 @@
          */
         public static void showQuickContact(Context context, View target, Uri lookupUri, int mode,
                 String[] excludeMimes) {
-            // Find location and bounds of target view, adjusting based on the
-            // assumed local density.
-            final float appScale = context.getResources().getCompatibilityInfo().applicationScale;
-            final int[] pos = new int[2];
-            target.getLocationOnScreen(pos);
-
-            final Rect rect = new Rect();
-            rect.left = (int) (pos[0] * appScale + 0.5f);
-            rect.top = (int) (pos[1] * appScale + 0.5f);
-            rect.right = (int) ((pos[0] + target.getWidth()) * appScale + 0.5f);
-            rect.bottom = (int) ((pos[1] + target.getHeight()) * appScale + 0.5f);
-
             // Trigger with obtained rectangle
-            showQuickContact(context, rect, lookupUri, mode, excludeMimes);
+            Intent intent = composeQuickContactsIntent(context, target, lookupUri, mode,
+                    excludeMimes);
+            context.startActivity(intent);
         }
 
         /**
@@ -7726,24 +7765,8 @@
          */
         public static void showQuickContact(Context context, Rect target, Uri lookupUri, int mode,
                 String[] excludeMimes) {
-            // When launching from an Activiy, we don't want to start a new task, but otherwise
-            // we *must* start a new task.  (Otherwise startActivity() would crash.)
-            Context actualContext = context;
-            while ((actualContext instanceof ContextWrapper)
-                    && !(actualContext instanceof Activity)) {
-                actualContext = ((ContextWrapper) actualContext).getBaseContext();
-            }
-            final int intentFlags = (actualContext instanceof Activity)
-                    ? Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
-                    : Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK;
-
-            // Launch pivot dialog through intent for now
-            final Intent intent = new Intent(ACTION_QUICK_CONTACT).addFlags(intentFlags);
-
-            intent.setData(lookupUri);
-            intent.setSourceBounds(target);
-            intent.putExtra(EXTRA_MODE, mode);
-            intent.putExtra(EXTRA_EXCLUDE_MIMES, excludeMimes);
+            Intent intent = composeQuickContactsIntent(context, target, lookupUri, mode,
+                    excludeMimes);
             context.startActivity(intent);
         }
     }
@@ -7900,6 +7923,16 @@
                 "com.android.contacts.action.GET_MULTIPLE_PHONES";
 
         /**
+         * A broadcast action which is sent when any change has been made to the profile, such
+         * as the profile name or the picture.  A receiver must have
+         * the android.permission.READ_PROFILE permission.
+         *
+         * @hide
+         */
+        public static final String ACTION_PROFILE_CHANGED =
+                "android.provider.Contacts.PROFILE_CHANGED";
+
+        /**
          * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new
          * contact if no matching contact found. Otherwise, default behavior is
          * to prompt user with dialog before creating.
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 79d0144..0e7ab52 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -120,7 +120,39 @@
      */
     public static final String INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH =
             "android.media.action.MEDIA_PLAY_FROM_SEARCH";
-    
+
+    /**
+     * An intent to perform a search for readable media and automatically play content from the
+     * result when possible. This can be fired, for example, by the result of a voice recognition
+     * command to read a book or magazine.
+     * <p>
+     * Contains the {@link android.app.SearchManager#QUERY} extra, which is a string that can
+     * contain any type of unstructured text search, like the name of a book or magazine, an author
+     * a genre, a publisher, or any combination of these.
+     * <p>
+     * Because this intent includes an open-ended unstructured search string, it makes the most
+     * sense for apps that can support large-scale search of text media, such as services connected
+     * to an online database of books and/or magazines which can be read on the device.
+     */
+    public static final String INTENT_ACTION_TEXT_OPEN_FROM_SEARCH =
+            "android.media.action.TEXT_OPEN_FROM_SEARCH";
+
+    /**
+     * An intent to perform a search for video media and automatically play content from the
+     * result when possible. This can be fired, for example, by the result of a voice recognition
+     * command to play movies.
+     * <p>
+     * Contains the {@link android.app.SearchManager#QUERY} extra, which is a string that can
+     * contain any type of unstructured video search, like the name of a movie, one or more actors,
+     * a genre, or any combination of these.
+     * <p>
+     * Because this intent includes an open-ended unstructured search string, it makes the most
+     * sense for apps that can support large-scale search of video, such as services connected to an
+     * online database of videos which can be streamed and played on the device.
+     */
+    public static final String INTENT_ACTION_VIDEO_PLAY_FROM_SEARCH =
+            "android.media.action.VIDEO_PLAY_FROM_SEARCH";
+
     /**
      * The name of the Intent-extra used to define the artist
      */
@@ -173,6 +205,21 @@
     public static final String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA";
 
     /**
+     * The name of the Intent action used to launch a camera in still image mode
+     * for use when the device is secured (e.g. with a pin, password, pattern,
+     * or face unlock). Applications responding to this intent must not expose
+     * any personal content like existing photos or videos on the device. The
+     * applications should be careful not to share any photo or video with other
+     * applications or internet. The activity should use {@link
+     * android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} to display
+     * on top of the lock screen while secured. There is no activity stack when
+     * this flag is used, so launching more than one activity is strongly
+     * discouraged.
+     */
+    public static final String INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE =
+            "android.media.action.STILL_IMAGE_CAMERA_SECURE";
+
+    /**
      * The name of the Intent action used to launch a camera in video mode.
      */
     public static final String INTENT_ACTION_VIDEO_CAMERA = "android.media.action.VIDEO_CAMERA";
@@ -191,6 +238,28 @@
     public final static String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
 
     /**
+     * Intent action that can be sent to have the camera application capture an image and return
+     * it when the device is secured (e.g. with a pin, password, pattern, or face unlock).
+     * Applications responding to this intent must not expose any personal content like existing
+     * photos or videos on the device. The applications should be careful not to share any photo
+     * or video with other applications or internet. The activity should use {@link
+     * android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} to display on top of the
+     * lock screen while secured. There is no activity stack when this flag is used, so
+     * launching more than one activity is strongly discouraged.
+     * <p>
+     * The caller may pass an extra EXTRA_OUTPUT to control where this image will be written.
+     * If the EXTRA_OUTPUT is not present, then a small sized image is returned as a Bitmap
+     * object in the extra field. This is useful for applications that only need a small image.
+     * If the EXTRA_OUTPUT is present, then the full-sized image will be written to the Uri
+     * value of EXTRA_OUTPUT.
+     *
+     * @see #ACTION_IMAGE_CAPTURE
+     * @see #EXTRA_OUTPUT
+     */
+    public static final String ACTION_IMAGE_CAPTURE_SECURE =
+            "android.media.action.IMAGE_CAPTURE_SECURE";
+
+    /**
      * Standard Intent action that can be sent to have the camera application
      * capture a video and return it.
      * <p>
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 74c0a97..b94f0b9 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -19,6 +19,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.SearchManager;
+import android.app.WallpaperManager;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -32,16 +33,19 @@
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.SQLException;
+import android.net.ConnectivityManager;
 import android.net.Uri;
 import android.net.wifi.WifiManager;
 import android.os.BatteryManager;
 import android.os.Bundle;
+import android.os.DropBoxManager;
 import android.os.IBinder;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
-import android.os.UserId;
+import android.os.UserHandle;
+import android.os.Build.VERSION_CODES;
 import android.speech.tts.TextToSpeech;
 import android.text.TextUtils;
 import android.util.AndroidException;
@@ -214,6 +218,21 @@
             "android.settings.BLUETOOTH_SETTINGS";
 
     /**
+     * Activity Action: Show settings to allow configuration of Wifi Displays.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_WIFI_DISPLAY_SETTINGS =
+            "android.settings.WIFI_DISPLAY_SETTINGS";
+
+    /**
      * Activity Action: Show settings to allow configuration of date and time.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you
@@ -367,10 +386,9 @@
 
     /**
      * Activity Action: Show settings to allow configuration of application
-     * development-related settings.
-     * <p>
-     * In some cases, a matching Activity may not exist, so ensure you safeguard
-     * against this.
+     * development-related settings.  As of
+     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} this action is
+     * a required part of the platform.
      * <p>
      * Input: Nothing.
      * <p>
@@ -621,6 +639,25 @@
     public static final String CALL_METHOD_GET_SECURE = "GET_secure";
 
     /**
+     * @hide - Private call() method on SettingsProvider to read from 'global' table.
+     */
+    public static final String CALL_METHOD_GET_GLOBAL = "GET_global";
+
+    /**
+     * @hide - User handle argument extra to the fast-path call()-based requests
+     */
+    public static final String CALL_METHOD_USER_KEY = "_user";
+
+    /** @hide - Private call() method to write to 'system' table */
+    public static final String CALL_METHOD_PUT_SYSTEM = "PUT_system";
+
+    /** @hide - Private call() method to write to 'secure' table */
+    public static final String CALL_METHOD_PUT_SECURE = "PUT_secure";
+
+    /** @hide - Private call() method to write to 'global' table */
+    public static final String CALL_METHOD_PUT_GLOBAL= "PUT_global";
+
+    /**
      * Activity Extra: Limit available options in launched activity based on the given authority.
      * <p>
      * This can be passed as an extra field in an Activity Intent with one or more syncable content
@@ -640,7 +677,7 @@
     public static final String AUTHORITY = "settings";
 
     private static final String TAG = "Settings";
-    private static final boolean LOCAL_LOGV = false || false;
+    private static final boolean LOCAL_LOGV = false;
 
     public static class SettingNotFoundException extends AndroidException {
         public SettingNotFoundException(String msg) {
@@ -693,33 +730,18 @@
 
         // The method we'll call (or null, to not use) on the provider
         // for the fast path of retrieving settings.
-        private final String mCallCommand;
+        private final String mCallGetCommand;
+        private final String mCallSetCommand;
 
-        public NameValueCache(String versionSystemProperty, Uri uri, String callCommand) {
+        public NameValueCache(String versionSystemProperty, Uri uri,
+                String getCommand, String setCommand) {
             mVersionSystemProperty = versionSystemProperty;
             mUri = uri;
-            mCallCommand = callCommand;
+            mCallGetCommand = getCommand;
+            mCallSetCommand = setCommand;
         }
 
-        public String getString(ContentResolver cr, String name) {
-            long newValuesVersion = SystemProperties.getLong(mVersionSystemProperty, 0);
-
-            synchronized (this) {
-                if (mValuesVersion != newValuesVersion) {
-                    if (LOCAL_LOGV) {
-                        Log.v(TAG, "invalidate [" + mUri.getLastPathSegment() + "]: current " +
-                                newValuesVersion + " != cached " + mValuesVersion);
-                    }
-
-                    mValues.clear();
-                    mValuesVersion = newValuesVersion;
-                }
-
-                if (mValues.containsKey(name)) {
-                    return mValues.get(name);  // Could be null, that's OK -- negative caching
-                }
-            }
-
+        private IContentProvider lazyGetProvider(ContentResolver cr) {
             IContentProvider cp = null;
             synchronized (this) {
                 cp = mContentProvider;
@@ -727,18 +749,75 @@
                     cp = mContentProvider = cr.acquireProvider(mUri.getAuthority());
                 }
             }
+            return cp;
+        }
+
+        public boolean putStringForUser(ContentResolver cr, String name, String value,
+                final int userHandle) {
+            try {
+                Bundle arg = new Bundle();
+                arg.putString(Settings.NameValueTable.VALUE, value);
+                arg.putInt(CALL_METHOD_USER_KEY, userHandle);
+                IContentProvider cp = lazyGetProvider(cr);
+                cp.call(mCallSetCommand, name, arg);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Can't set key " + name + " in " + mUri, e);
+                return false;
+            }
+            return true;
+        }
+
+        public String getStringForUser(ContentResolver cr, String name, final int userHandle) {
+            final boolean isSelf = (userHandle == UserHandle.myUserId());
+            if (isSelf) {
+                long newValuesVersion = SystemProperties.getLong(mVersionSystemProperty, 0);
+
+                // Our own user's settings data uses a client-side cache
+                synchronized (this) {
+                    if (mValuesVersion != newValuesVersion) {
+                        if (LOCAL_LOGV || false) {
+                            Log.v(TAG, "invalidate [" + mUri.getLastPathSegment() + "]: current "
+                                    + newValuesVersion + " != cached " + mValuesVersion);
+                        }
+
+                        mValues.clear();
+                        mValuesVersion = newValuesVersion;
+                    }
+
+                    if (mValues.containsKey(name)) {
+                        return mValues.get(name);  // Could be null, that's OK -- negative caching
+                    }
+                }
+            } else {
+                if (LOCAL_LOGV) Log.v(TAG, "get setting for user " + userHandle
+                        + " by user " + UserHandle.myUserId() + " so skipping cache");
+            }
+
+            IContentProvider cp = lazyGetProvider(cr);
 
             // Try the fast path first, not using query().  If this
             // fails (alternate Settings provider that doesn't support
             // this interface?) then we fall back to the query/table
             // interface.
-            if (mCallCommand != null) {
+            if (mCallGetCommand != null) {
                 try {
-                    Bundle b = cp.call(mCallCommand, name, null);
+                    Bundle args = null;
+                    if (!isSelf) {
+                        args = new Bundle();
+                        args.putInt(CALL_METHOD_USER_KEY, userHandle);
+                    }
+                    Bundle b = cp.call(mCallGetCommand, name, args);
                     if (b != null) {
                         String value = b.getPairValue();
-                        synchronized (this) {
-                            mValues.put(name, value);
+                        // Don't update our cache for reads of other users' data
+                        if (isSelf) {
+                            synchronized (this) {
+                                mValues.put(name, value);
+                            }
+                        } else {
+                            if (LOCAL_LOGV) Log.i(TAG, "call-query of user " + userHandle
+                                    + " by " + UserHandle.myUserId()
+                                    + " so not updating cache");
                         }
                         return value;
                     }
@@ -785,19 +864,23 @@
     public static final class System extends NameValueTable {
         public static final String SYS_PROP_SETTING_VERSION = "sys.settings_system_version";
 
-        // Populated lazily, guarded by class object:
-        private static NameValueCache sNameValueCache = null;
+        /**
+         * The content:// style URL for this table
+         */
+        public static final Uri CONTENT_URI =
+            Uri.parse("content://" + AUTHORITY + "/system");
+
+        private static final NameValueCache sNameValueCache = new NameValueCache(
+                SYS_PROP_SETTING_VERSION,
+                CONTENT_URI,
+                CALL_METHOD_GET_SYSTEM,
+                CALL_METHOD_PUT_SYSTEM);
 
         private static final HashSet<String> MOVED_TO_SECURE;
         static {
             MOVED_TO_SECURE = new HashSet<String>(30);
-            MOVED_TO_SECURE.add(Secure.ADB_ENABLED);
             MOVED_TO_SECURE.add(Secure.ANDROID_ID);
-            MOVED_TO_SECURE.add(Secure.BLUETOOTH_ON);
-            MOVED_TO_SECURE.add(Secure.DATA_ROAMING);
-            MOVED_TO_SECURE.add(Secure.DEVICE_PROVISIONED);
             MOVED_TO_SECURE.add(Secure.HTTP_PROXY);
-            MOVED_TO_SECURE.add(Secure.INSTALL_NON_MARKET_APPS);
             MOVED_TO_SECURE.add(Secure.LOCATION_PROVIDERS_ALLOWED);
             MOVED_TO_SECURE.add(Secure.LOCK_BIOMETRIC_WEAK_FLAGS);
             MOVED_TO_SECURE.add(Secure.LOCK_PATTERN_ENABLED);
@@ -808,7 +891,6 @@
             MOVED_TO_SECURE.add(Secure.PARENTAL_CONTROL_LAST_UPDATE);
             MOVED_TO_SECURE.add(Secure.PARENTAL_CONTROL_REDIRECT_URL);
             MOVED_TO_SECURE.add(Secure.SETTINGS_CLASSNAME);
-            MOVED_TO_SECURE.add(Secure.USB_MASS_STORAGE_ENABLED);
             MOVED_TO_SECURE.add(Secure.USE_GOOGLE_MAIL);
             MOVED_TO_SECURE.add(Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON);
             MOVED_TO_SECURE.add(Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY);
@@ -827,23 +909,88 @@
             MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS);
         }
 
+        private static final HashSet<String> MOVED_TO_GLOBAL;
+        private static final HashSet<String> MOVED_TO_SECURE_THEN_GLOBAL;
+        static {
+            MOVED_TO_GLOBAL = new HashSet<String>();
+            MOVED_TO_SECURE_THEN_GLOBAL = new HashSet<String>();
+
+            // these were originally in system but migrated to secure in the past,
+            // so are duplicated in the Secure.* namespace
+            MOVED_TO_SECURE_THEN_GLOBAL.add(Global.ADB_ENABLED);
+            MOVED_TO_SECURE_THEN_GLOBAL.add(Global.BLUETOOTH_ON);
+            MOVED_TO_SECURE_THEN_GLOBAL.add(Global.DATA_ROAMING);
+            MOVED_TO_SECURE_THEN_GLOBAL.add(Global.DEVICE_PROVISIONED);
+            MOVED_TO_SECURE_THEN_GLOBAL.add(Global.INSTALL_NON_MARKET_APPS);
+            MOVED_TO_SECURE_THEN_GLOBAL.add(Global.USB_MASS_STORAGE_ENABLED);
+            MOVED_TO_SECURE_THEN_GLOBAL.add(Global.HTTP_PROXY);
+
+            // these are moving directly from system to global
+            MOVED_TO_GLOBAL.add(Settings.Global.AIRPLANE_MODE_ON);
+            MOVED_TO_GLOBAL.add(Settings.Global.AIRPLANE_MODE_RADIOS);
+            MOVED_TO_GLOBAL.add(Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
+            MOVED_TO_GLOBAL.add(Settings.Global.AUTO_TIME);
+            MOVED_TO_GLOBAL.add(Settings.Global.AUTO_TIME_ZONE);
+            MOVED_TO_GLOBAL.add(Settings.Global.CAR_DOCK_SOUND);
+            MOVED_TO_GLOBAL.add(Settings.Global.CAR_UNDOCK_SOUND);
+            MOVED_TO_GLOBAL.add(Settings.Global.DESK_DOCK_SOUND);
+            MOVED_TO_GLOBAL.add(Settings.Global.DESK_UNDOCK_SOUND);
+            MOVED_TO_GLOBAL.add(Settings.Global.DOCK_SOUNDS_ENABLED);
+            MOVED_TO_GLOBAL.add(Settings.Global.LOCK_SOUND);
+            MOVED_TO_GLOBAL.add(Settings.Global.UNLOCK_SOUND);
+            MOVED_TO_GLOBAL.add(Settings.Global.LOW_BATTERY_SOUND);
+            MOVED_TO_GLOBAL.add(Settings.Global.POWER_SOUNDS_ENABLED);
+            MOVED_TO_GLOBAL.add(Settings.Global.STAY_ON_WHILE_PLUGGED_IN);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_SLEEP_POLICY);
+            MOVED_TO_GLOBAL.add(Settings.Global.MODE_RINGER);
+            MOVED_TO_GLOBAL.add(Settings.Global.WINDOW_ANIMATION_SCALE);
+            MOVED_TO_GLOBAL.add(Settings.Global.TRANSITION_ANIMATION_SCALE);
+            MOVED_TO_GLOBAL.add(Settings.Global.ANIMATOR_DURATION_SCALE);
+            MOVED_TO_GLOBAL.add(Settings.Global.FANCY_IME_ANIMATIONS);
+            MOVED_TO_GLOBAL.add(Settings.Global.COMPATIBILITY_MODE);
+            MOVED_TO_GLOBAL.add(Settings.Global.EMERGENCY_TONE);
+            MOVED_TO_GLOBAL.add(Settings.Global.CALL_AUTO_RETRY);
+            MOVED_TO_GLOBAL.add(Settings.Global.DEBUG_APP);
+            MOVED_TO_GLOBAL.add(Settings.Global.WAIT_FOR_DEBUGGER);
+            MOVED_TO_GLOBAL.add(Settings.Global.SHOW_PROCESSES);
+            MOVED_TO_GLOBAL.add(Settings.Global.ALWAYS_FINISH_ACTIVITIES);
+        }
+
+        /** @hide */
+        public static void getMovedKeys(HashSet<String> outKeySet) {
+            outKeySet.addAll(MOVED_TO_GLOBAL);
+            outKeySet.addAll(MOVED_TO_SECURE_THEN_GLOBAL);
+        }
+
+        /** @hide */
+        public static void getNonLegacyMovedKeys(HashSet<String> outKeySet) {
+            outKeySet.addAll(MOVED_TO_GLOBAL);
+        }
+
         /**
          * Look up a name in the database.
          * @param resolver to access the database with
          * @param name to look up in the table
          * @return the corresponding value, or null if not present
          */
-        public synchronized static String getString(ContentResolver resolver, String name) {
+        public static String getString(ContentResolver resolver, String name) {
+            return getStringForUser(resolver, name, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static String getStringForUser(ContentResolver resolver, String name,
+                int userHandle) {
             if (MOVED_TO_SECURE.contains(name)) {
                 Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
                         + " to android.provider.Settings.Secure, returning read-only value.");
-                return Secure.getString(resolver, name);
+                return Secure.getStringForUser(resolver, name, userHandle);
             }
-            if (sNameValueCache == null) {
-                sNameValueCache = new NameValueCache(SYS_PROP_SETTING_VERSION, CONTENT_URI,
-                                                     CALL_METHOD_GET_SYSTEM);
+            if (MOVED_TO_GLOBAL.contains(name) || MOVED_TO_SECURE_THEN_GLOBAL.contains(name)) {
+                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
+                        + " to android.provider.Settings.Global, returning read-only value.");
+                return Global.getStringForUser(resolver, name, userHandle);
             }
-            return sNameValueCache.getString(resolver, name);
+            return sNameValueCache.getStringForUser(resolver, name, userHandle);
         }
 
         /**
@@ -854,12 +1001,23 @@
          * @return true if the value was set, false on database errors
          */
         public static boolean putString(ContentResolver resolver, String name, String value) {
+            return putStringForUser(resolver, name, value, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static boolean putStringForUser(ContentResolver resolver, String name, String value,
+                int userHandle) {
             if (MOVED_TO_SECURE.contains(name)) {
                 Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
                         + " to android.provider.Settings.Secure, value is unchanged.");
                 return false;
             }
-            return putString(resolver, CONTENT_URI, name, value);
+            if (MOVED_TO_GLOBAL.contains(name) || MOVED_TO_SECURE_THEN_GLOBAL.contains(name)) {
+                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
+                        + " to android.provider.Settings.Global, value is unchanged.");
+                return false;
+            }
+            return sNameValueCache.putStringForUser(resolver, name, value, userHandle);
         }
 
         /**
@@ -874,6 +1032,11 @@
                     + " to android.provider.Settings.Secure, returning Secure URI.");
                 return Secure.getUriFor(Secure.CONTENT_URI, name);
             }
+            if (MOVED_TO_GLOBAL.contains(name) || MOVED_TO_SECURE_THEN_GLOBAL.contains(name)) {
+                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
+                        + " to android.provider.Settings.Global, returning read-only global URI.");
+                return Global.getUriFor(Global.CONTENT_URI, name);
+            }
             return getUriFor(CONTENT_URI, name);
         }
 
@@ -892,7 +1055,12 @@
          * or not a valid integer.
          */
         public static int getInt(ContentResolver cr, String name, int def) {
-            String v = getString(cr, name);
+            return getIntForUser(cr, name, def, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static int getIntForUser(ContentResolver cr, String name, int def, int userHandle) {
+            String v = getStringForUser(cr, name, userHandle);
             try {
                 return v != null ? Integer.parseInt(v) : def;
             } catch (NumberFormatException e) {
@@ -920,7 +1088,13 @@
          */
         public static int getInt(ContentResolver cr, String name)
                 throws SettingNotFoundException {
-            String v = getString(cr, name);
+            return getIntForUser(cr, name, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static int getIntForUser(ContentResolver cr, String name, int userHandle)
+                throws SettingNotFoundException {
+            String v = getStringForUser(cr, name, userHandle);
             try {
                 return Integer.parseInt(v);
             } catch (NumberFormatException e) {
@@ -942,7 +1116,13 @@
          * @return true if the value was set, false on database errors
          */
         public static boolean putInt(ContentResolver cr, String name, int value) {
-            return putString(cr, name, Integer.toString(value));
+            return putIntForUser(cr, name, value, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static boolean putIntForUser(ContentResolver cr, String name, int value,
+                int userHandle) {
+            return putStringForUser(cr, name, Integer.toString(value), userHandle);
         }
 
         /**
@@ -960,7 +1140,13 @@
          * or not a valid {@code long}.
          */
         public static long getLong(ContentResolver cr, String name, long def) {
-            String valString = getString(cr, name);
+            return getLongForUser(cr, name, def, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static long getLongForUser(ContentResolver cr, String name, long def,
+                int userHandle) {
+            String valString = getStringForUser(cr, name, userHandle);
             long value;
             try {
                 value = valString != null ? Long.parseLong(valString) : def;
@@ -989,7 +1175,13 @@
          */
         public static long getLong(ContentResolver cr, String name)
                 throws SettingNotFoundException {
-            String valString = getString(cr, name);
+            return getLongForUser(cr, name, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static long getLongForUser(ContentResolver cr, String name, int userHandle)
+                throws SettingNotFoundException {
+            String valString = getStringForUser(cr, name, userHandle);
             try {
                 return Long.parseLong(valString);
             } catch (NumberFormatException e) {
@@ -1011,7 +1203,13 @@
          * @return true if the value was set, false on database errors
          */
         public static boolean putLong(ContentResolver cr, String name, long value) {
-            return putString(cr, name, Long.toString(value));
+            return putLongForUser(cr, name, value, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static boolean putLongForUser(ContentResolver cr, String name, long value,
+                int userHandle) {
+            return putStringForUser(cr, name, Long.toString(value), userHandle);
         }
 
         /**
@@ -1029,7 +1227,13 @@
          * or not a valid float.
          */
         public static float getFloat(ContentResolver cr, String name, float def) {
-            String v = getString(cr, name);
+            return getFloatForUser(cr, name, def, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static float getFloatForUser(ContentResolver cr, String name, float def,
+                int userHandle) {
+            String v = getStringForUser(cr, name, userHandle);
             try {
                 return v != null ? Float.parseFloat(v) : def;
             } catch (NumberFormatException e) {
@@ -1057,7 +1261,13 @@
          */
         public static float getFloat(ContentResolver cr, String name)
                 throws SettingNotFoundException {
-            String v = getString(cr, name);
+            return getFloatForUser(cr, name, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static float getFloatForUser(ContentResolver cr, String name, int userHandle)
+                throws SettingNotFoundException {
+            String v = getStringForUser(cr, name, userHandle);
             if (v == null) {
                 throw new SettingNotFoundException(name);
             }
@@ -1082,7 +1292,13 @@
          * @return true if the value was set, false on database errors
          */
         public static boolean putFloat(ContentResolver cr, String name, float value) {
-            return putString(cr, name, Float.toString(value));
+            return putFloatForUser(cr, name, value, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static boolean putFloatForUser(ContentResolver cr, String name, float value,
+                int userHandle) {
+            return putStringForUser(cr, name, Float.toString(value), userHandle);
         }
 
         /**
@@ -1094,8 +1310,14 @@
          * @param outConfig Where to place the configuration settings.
          */
         public static void getConfiguration(ContentResolver cr, Configuration outConfig) {
-            outConfig.fontScale = Settings.System.getFloat(
-                cr, FONT_SCALE, outConfig.fontScale);
+            getConfigurationForUser(cr, outConfig, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static void getConfigurationForUser(ContentResolver cr, Configuration outConfig,
+                int userHandle) {
+            outConfig.fontScale = Settings.System.getFloatForUser(
+                cr, FONT_SCALE, outConfig.fontScale, userHandle);
             if (outConfig.fontScale < 0) {
                 outConfig.fontScale = 1;
             }
@@ -1118,7 +1340,13 @@
          * @return true if the values were set, false on database errors
          */
         public static boolean putConfiguration(ContentResolver cr, Configuration config) {
-            return Settings.System.putFloat(cr, FONT_SCALE, config.fontScale);
+            return putConfigurationForUser(cr, config, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static boolean putConfigurationForUser(ContentResolver cr, Configuration config,
+                int userHandle) {
+            return Settings.System.putFloatForUser(cr, FONT_SCALE, config.fontScale, userHandle);
         }
 
         /** @hide */
@@ -1126,31 +1354,42 @@
             return (changes&ActivityInfo.CONFIG_FONT_SCALE) != 0;
         }
 
+        /** @deprecated - Do not use */
+        @Deprecated
         public static boolean getShowGTalkServiceStatus(ContentResolver cr) {
-            return getInt(cr, SHOW_GTALK_SERVICE_STATUS, 0) != 0;
+            return getShowGTalkServiceStatusForUser(cr, UserHandle.myUserId());
         }
 
+        /**
+         * @hide
+         * @deprecated - Do not use
+         */
+        public static boolean getShowGTalkServiceStatusForUser(ContentResolver cr,
+                int userHandle) {
+            return getIntForUser(cr, SHOW_GTALK_SERVICE_STATUS, 0, userHandle) != 0;
+        }
+
+        /** @deprecated - Do not use */
+        @Deprecated
         public static void setShowGTalkServiceStatus(ContentResolver cr, boolean flag) {
-            putInt(cr, SHOW_GTALK_SERVICE_STATUS, flag ? 1 : 0);
+            setShowGTalkServiceStatusForUser(cr, flag, UserHandle.myUserId());
         }
 
         /**
-         * The content:// style URL for this table
+         * @hide
+         * @deprecated - Do not use
          */
-        public static final Uri CONTENT_URI =
-            Uri.parse("content://" + AUTHORITY + "/system");
+        @Deprecated
+        public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean flag,
+                int userHandle) {
+            putIntForUser(cr, SHOW_GTALK_SERVICE_STATUS, flag ? 1 : 0, userHandle);
+        }
 
         /**
-         * Whether we keep the device on while the device is plugged in.
-         * Supported values are:
-         * <ul>
-         * <li>{@code 0} to never stay on while plugged in</li>
-         * <li>{@link BatteryManager#BATTERY_PLUGGED_AC} to stay on for AC charger</li>
-         * <li>{@link BatteryManager#BATTERY_PLUGGED_USB} to stay on for USB charger</li>
-         * </ul>
-         * These values can be OR-ed together.
+         * @deprecated Use {@link android.provider.Settings.Global#STAY_ON_WHILE_PLUGGED_IN} instead
          */
-        public static final String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
+        @Deprecated
+        public static final String STAY_ON_WHILE_PLUGGED_IN = Global.STAY_ON_WHILE_PLUGGED_IN;
 
         /**
          * What happens when the user presses the end call button if they're not
@@ -1195,122 +1434,146 @@
         public static final int ADVANCED_SETTINGS_DEFAULT = 0;
 
         /**
-         * Whether Airplane Mode is on.
+         * @deprecated Use {@link android.provider.Settings.Global#AIRPLANE_MODE_ON} instead
          */
-        public static final String AIRPLANE_MODE_ON = "airplane_mode_on";
+        @Deprecated
+        public static final String AIRPLANE_MODE_ON = Global.AIRPLANE_MODE_ON;
 
         /**
-         * Constant for use in AIRPLANE_MODE_RADIOS to specify Bluetooth radio.
+         * @deprecated Use {@link android.provider.Settings.Global#RADIO_BLUETOOTH} instead
          */
-        public static final String RADIO_BLUETOOTH = "bluetooth";
+        @Deprecated
+        public static final String RADIO_BLUETOOTH = Global.RADIO_BLUETOOTH;
 
         /**
-         * Constant for use in AIRPLANE_MODE_RADIOS to specify Wi-Fi radio.
+         * @deprecated Use {@link android.provider.Settings.Global#RADIO_WIFI} instead
          */
-        public static final String RADIO_WIFI = "wifi";
+        @Deprecated
+        public static final String RADIO_WIFI = Global.RADIO_WIFI;
 
         /**
+         * @deprecated Use {@link android.provider.Settings.Global#RADIO_WIMAX} instead
          * {@hide}
          */
-        public static final String RADIO_WIMAX = "wimax";
-        /**
-         * Constant for use in AIRPLANE_MODE_RADIOS to specify Cellular radio.
-         */
-        public static final String RADIO_CELL = "cell";
+        @Deprecated
+        public static final String RADIO_WIMAX = Global.RADIO_WIMAX;
 
         /**
-         * Constant for use in AIRPLANE_MODE_RADIOS to specify NFC radio.
+         * @deprecated Use {@link android.provider.Settings.Global#RADIO_CELL} instead
          */
-        public static final String RADIO_NFC = "nfc";
+        @Deprecated
+        public static final String RADIO_CELL = Global.RADIO_CELL;
 
         /**
-         * A comma separated list of radios that need to be disabled when airplane mode
-         * is on. This overrides WIFI_ON and BLUETOOTH_ON, if Wi-Fi and bluetooth are
-         * included in the comma separated list.
+         * @deprecated Use {@link android.provider.Settings.Global#RADIO_NFC} instead
          */
-        public static final String AIRPLANE_MODE_RADIOS = "airplane_mode_radios";
+        @Deprecated
+        public static final String RADIO_NFC = Global.RADIO_NFC;
 
         /**
-         * A comma separated list of radios that should to be disabled when airplane mode
-         * is on, but can be manually reenabled by the user.  For example, if RADIO_WIFI is
-         * added to both AIRPLANE_MODE_RADIOS and AIRPLANE_MODE_TOGGLEABLE_RADIOS, then Wifi
-         * will be turned off when entering airplane mode, but the user will be able to reenable
-         * Wifi in the Settings app.
+         * @deprecated Use {@link android.provider.Settings.Global#AIRPLANE_MODE_RADIOS} instead
+         */
+        @Deprecated
+        public static final String AIRPLANE_MODE_RADIOS = Global.AIRPLANE_MODE_RADIOS;
+
+        /**
+         * @deprecated Use {@link android.provider.Settings.Global#AIRPLANE_MODE_TOGGLEABLE_RADIOS} instead
          *
          * {@hide}
          */
-        public static final String AIRPLANE_MODE_TOGGLEABLE_RADIOS = "airplane_mode_toggleable_radios";
+        @Deprecated
+        public static final String AIRPLANE_MODE_TOGGLEABLE_RADIOS =
+                Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS;
 
         /**
-         * The policy for deciding when Wi-Fi should go to sleep (which will in
-         * turn switch to using the mobile data as an Internet connection).
-         * <p>
-         * Set to one of {@link #WIFI_SLEEP_POLICY_DEFAULT},
-         * {@link #WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED}, or
-         * {@link #WIFI_SLEEP_POLICY_NEVER}.
+         * @deprecated Use {@link android.provider.Settings.Global#WIFI_SLEEP_POLICY} instead
          */
-        public static final String WIFI_SLEEP_POLICY = "wifi_sleep_policy";
+        @Deprecated
+        public static final String WIFI_SLEEP_POLICY = Global.WIFI_SLEEP_POLICY;
 
         /**
-         * Value for {@link #WIFI_SLEEP_POLICY} to use the default Wi-Fi sleep
-         * policy, which is to sleep shortly after the turning off
-         * according to the {@link #STAY_ON_WHILE_PLUGGED_IN} setting.
+         * @deprecated Use {@link android.provider.Settings.Global#WIFI_SLEEP_POLICY_DEFAULT} instead
          */
-        public static final int WIFI_SLEEP_POLICY_DEFAULT = 0;
+        @Deprecated
+        public static final int WIFI_SLEEP_POLICY_DEFAULT = Global.WIFI_SLEEP_POLICY_DEFAULT;
 
         /**
-         * Value for {@link #WIFI_SLEEP_POLICY} to use the default policy when
-         * the device is on battery, and never go to sleep when the device is
-         * plugged in.
+         * @deprecated Use {@link android.provider.Settings.Global#WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED} instead
          */
-        public static final int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED = 1;
+        @Deprecated
+        public static final int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED =
+                Global.WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED;
 
         /**
-         * Value for {@link #WIFI_SLEEP_POLICY} to never go to sleep.
+         * @deprecated Use {@link android.provider.Settings.Global#WIFI_SLEEP_POLICY_NEVER} instead
          */
-        public static final int WIFI_SLEEP_POLICY_NEVER = 2;
+        @Deprecated
+        public static final int WIFI_SLEEP_POLICY_NEVER = Global.WIFI_SLEEP_POLICY_NEVER;
 
-        //TODO: deprecate static IP constants
+        /**
+         * @deprecated Use {@link android.provider.Settings.Global#MODE_RINGER} instead
+         */
+        @Deprecated
+        public static final String MODE_RINGER = Global.MODE_RINGER;
+
         /**
          * Whether to use static IP and other static network attributes.
          * <p>
          * Set to 1 for true and 0 for false.
+         *
+         * @deprecated Use {@link WifiManager} instead
          */
+        @Deprecated
         public static final String WIFI_USE_STATIC_IP = "wifi_use_static_ip";
 
         /**
          * The static IP address.
          * <p>
          * Example: "192.168.1.51"
+         *
+         * @deprecated Use {@link WifiManager} instead
          */
+        @Deprecated
         public static final String WIFI_STATIC_IP = "wifi_static_ip";
 
         /**
          * If using static IP, the gateway's IP address.
          * <p>
          * Example: "192.168.1.1"
+         *
+         * @deprecated Use {@link WifiManager} instead
          */
+        @Deprecated
         public static final String WIFI_STATIC_GATEWAY = "wifi_static_gateway";
 
         /**
          * If using static IP, the net mask.
          * <p>
          * Example: "255.255.255.0"
+         *
+         * @deprecated Use {@link WifiManager} instead
          */
+        @Deprecated
         public static final String WIFI_STATIC_NETMASK = "wifi_static_netmask";
 
         /**
          * If using static IP, the primary DNS's IP address.
          * <p>
          * Example: "192.168.1.1"
+         *
+         * @deprecated Use {@link WifiManager} instead
          */
+        @Deprecated
         public static final String WIFI_STATIC_DNS1 = "wifi_static_dns1";
 
         /**
          * If using static IP, the secondary DNS's IP address.
          * <p>
          * Example: "192.168.1.2"
+         *
+         * @deprecated Use {@link WifiManager} instead
          */
+        @Deprecated
         public static final String WIFI_STATIC_DNS2 = "wifi_static_dns2";
 
 
@@ -1370,18 +1633,26 @@
 
         /**
          * Name of an application package to be debugged.
+         *
+         * @deprecated Use {@link Global#DEBUG_APP} instead
          */
-        public static final String DEBUG_APP = "debug_app";
+        @Deprecated
+        public static final String DEBUG_APP = Global.DEBUG_APP;
 
         /**
          * If 1, when launching DEBUG_APP it will wait for the debugger before
          * starting user code.  If 0, it will run normally.
+         *
+         * @deprecated Use {@link Global#WAIT_FOR_DEBUGGER} instead
          */
-        public static final String WAIT_FOR_DEBUGGER = "wait_for_debugger";
+        @Deprecated
+        public static final String WAIT_FOR_DEBUGGER = Global.WAIT_FOR_DEBUGGER;
 
         /**
          * Whether or not to dim the screen. 0=no  1=yes
+         * @deprecated This setting is no longer used.
          */
+        @Deprecated
         public static final String DIM_SCREEN = "dim_screen";
 
         /**
@@ -1390,14 +1661,6 @@
         public static final String SCREEN_OFF_TIMEOUT = "screen_off_timeout";
 
         /**
-         * If 0, the compatibility mode is off for all applications.
-         * If 1, older applications run under compatibility mode.
-         * TODO: remove this settings before code freeze (bug/1907571)
-         * @hide
-         */
-        public static final String COMPATIBILITY_MODE = "compatibility_mode";
-
-        /**
          * The screen backlight brightness between 0 and 255.
          */
         public static final String SCREEN_BRIGHTNESS = "screen_brightness";
@@ -1426,23 +1689,21 @@
 
         /**
          * Control whether the process CPU usage meter should be shown.
+         *
+         * @deprecated Use {@link Global#SHOW_PROCESSES} instead
          */
-        public static final String SHOW_PROCESSES = "show_processes";
+        @Deprecated
+        public static final String SHOW_PROCESSES = Global.SHOW_PROCESSES;
 
         /**
          * If 1, the activity manager will aggressively finish activities and
          * processes as soon as they are no longer needed.  If 0, the normal
          * extended lifetime is used.
+         *
+         * @deprecated Use {@link Global#ALWAYS_FINISH_ACTIVITIES} instead
          */
-        public static final String ALWAYS_FINISH_ACTIVITIES =
-                "always_finish_activities";
-
-
-        /**
-         * Ringer mode. This is used internally, changing this value will not
-         * change the ringer mode. See AudioManager.
-         */
-        public static final String MODE_RINGER = "mode_ringer";
+        @Deprecated
+        public static final String ALWAYS_FINISH_ACTIVITIES = Global.ALWAYS_FINISH_ACTIVITIES;
 
         /**
          * Determines which streams are affected by ringer mode changes. The
@@ -1666,20 +1927,25 @@
 
         /**
          * Name of activity to use for wallpaper on the home screen.
+         *
+         * @deprecated Use {@link WallpaperManager} instead.
          */
+        @Deprecated
         public static final String WALLPAPER_ACTIVITY = "wallpaper_activity";
 
         /**
-         * Value to specify if the user prefers the date, time and time zone
-         * to be automatically fetched from the network (NITZ). 1=yes, 0=no
+         * @deprecated Use {@link android.provider.Settings.Global#AUTO_TIME}
+         * instead
          */
-        public static final String AUTO_TIME = "auto_time";
+        @Deprecated
+        public static final String AUTO_TIME = Global.AUTO_TIME;
 
         /**
-         * Value to specify if the user prefers the time zone
-         * to be automatically fetched from the network (NITZ). 1=yes, 0=no
+         * @deprecated Use {@link android.provider.Settings.Global#AUTO_TIME_ZONE}
+         * instead
          */
-        public static final String AUTO_TIME_ZONE = "auto_time_zone";
+        @Deprecated
+        public static final String AUTO_TIME_ZONE = Global.AUTO_TIME_ZONE;
 
         /**
          * Display times as 12 or 24 hours
@@ -1708,28 +1974,30 @@
         /**
          * Scaling factor for normal window animations. Setting to 0 will disable window
          * animations.
+         *
+         * @deprecated Use {@link Global#WINDOW_ANIMATION_SCALE} instead
          */
-        public static final String WINDOW_ANIMATION_SCALE = "window_animation_scale";
+        @Deprecated
+        public static final String WINDOW_ANIMATION_SCALE = Global.WINDOW_ANIMATION_SCALE;
 
         /**
          * Scaling factor for activity transition animations. Setting to 0 will disable window
          * animations.
+         *
+         * @deprecated Use {@link Global#TRANSITION_ANIMATION_SCALE} instead
          */
-        public static final String TRANSITION_ANIMATION_SCALE = "transition_animation_scale";
+        @Deprecated
+        public static final String TRANSITION_ANIMATION_SCALE = Global.TRANSITION_ANIMATION_SCALE;
 
         /**
          * Scaling factor for Animator-based animations. This affects both the start delay and
          * duration of all such animations. Setting to 0 will cause animations to end immediately.
          * The default value is 1.
+         *
+         * @deprecated Use {@link Global#ANIMATOR_DURATION_SCALE} instead
          */
-        public static final String ANIMATOR_DURATION_SCALE = "animator_duration_scale";
-
-        /**
-         * Scaling factor for normal window animations. Setting to 0 will disable window
-         * animations.
-         * @hide
-         */
-        public static final String FANCY_IME_ANIMATIONS = "fancy_ime_animations";
+        @Deprecated
+        public static final String ANIMATOR_DURATION_SCALE = Global.ANIMATOR_DURATION_SCALE;
 
         /**
          * Control whether the accelerometer will be used to change screen
@@ -1793,23 +2061,6 @@
         public static final String DTMF_TONE_TYPE_WHEN_DIALING = "dtmf_tone_type";
 
         /**
-         * CDMA only settings
-         * Emergency Tone  0 = Off
-         *                 1 = Alert
-         *                 2 = Vibrate
-         * @hide
-         */
-        public static final String EMERGENCY_TONE = "emergency_tone";
-
-        /**
-         * CDMA only settings
-         * Whether the auto retry is enabled. The value is
-         * boolean (1 or 0).
-         * @hide
-         */
-        public static final String CALL_AUTO_RETRY = "call_auto_retry";
-
-        /**
          * Whether the hearing aid is enabled. The value is
          * boolean (1 or 0).
          * @hide
@@ -1880,16 +2131,20 @@
                 "window_orientation_listener_log";
 
         /**
-         * Whether to play a sound for low-battery alerts.
+         * @deprecated Use {@link android.provider.Settings.Global#POWER_SOUNDS_ENABLED}
+         * instead
          * @hide
          */
-        public static final String POWER_SOUNDS_ENABLED = "power_sounds_enabled";
+        @Deprecated
+        public static final String POWER_SOUNDS_ENABLED = Global.POWER_SOUNDS_ENABLED;
 
         /**
-         * Whether to play a sound for dock events.
+         * @deprecated Use {@link android.provider.Settings.Global#DOCK_SOUNDS_ENABLED}
+         * instead
          * @hide
          */
-        public static final String DOCK_SOUNDS_ENABLED = "dock_sounds_enabled";
+        @Deprecated
+        public static final String DOCK_SOUNDS_ENABLED = Global.DOCK_SOUNDS_ENABLED;
 
         /**
          * Whether to play sounds when the keyguard is shown and dismissed.
@@ -1904,46 +2159,60 @@
         public static final String LOCKSCREEN_DISABLED = "lockscreen.disabled";
 
         /**
-         * URI for the low battery sound file.
+         * @deprecated Use {@link android.provider.Settings.Global#LOW_BATTERY_SOUND}
+         * instead
          * @hide
          */
-        public static final String LOW_BATTERY_SOUND = "low_battery_sound";
+        @Deprecated
+        public static final String LOW_BATTERY_SOUND = Global.LOW_BATTERY_SOUND;
 
         /**
-         * URI for the desk dock "in" event sound.
+         * @deprecated Use {@link android.provider.Settings.Global#DESK_DOCK_SOUND}
+         * instead
          * @hide
          */
-        public static final String DESK_DOCK_SOUND = "desk_dock_sound";
+        @Deprecated
+        public static final String DESK_DOCK_SOUND = Global.DESK_DOCK_SOUND;
 
         /**
-         * URI for the desk dock "out" event sound.
+         * @deprecated Use {@link android.provider.Settings.Global#DESK_UNDOCK_SOUND}
+         * instead
          * @hide
          */
-        public static final String DESK_UNDOCK_SOUND = "desk_undock_sound";
+        @Deprecated
+        public static final String DESK_UNDOCK_SOUND = Global.DESK_UNDOCK_SOUND;
 
         /**
-         * URI for the car dock "in" event sound.
+         * @deprecated Use {@link android.provider.Settings.Global#CAR_DOCK_SOUND}
+         * instead
          * @hide
          */
-        public static final String CAR_DOCK_SOUND = "car_dock_sound";
+        @Deprecated
+        public static final String CAR_DOCK_SOUND = Global.CAR_DOCK_SOUND;
 
         /**
-         * URI for the car dock "out" event sound.
+         * @deprecated Use {@link android.provider.Settings.Global#CAR_UNDOCK_SOUND}
+         * instead
          * @hide
          */
-        public static final String CAR_UNDOCK_SOUND = "car_undock_sound";
+        @Deprecated
+        public static final String CAR_UNDOCK_SOUND = Global.CAR_UNDOCK_SOUND;
 
         /**
-         * URI for the "device locked" (keyguard shown) sound.
+         * @deprecated Use {@link android.provider.Settings.Global#LOCK_SOUND}
+         * instead
          * @hide
          */
-        public static final String LOCK_SOUND = "lock_sound";
+        @Deprecated
+        public static final String LOCK_SOUND = Global.LOCK_SOUND;
 
         /**
-         * URI for the "device unlocked" (keyguard dismissed) sound.
+         * @deprecated Use {@link android.provider.Settings.Global#UNLOCK_SOUND}
+         * instead
          * @hide
          */
-        public static final String UNLOCK_SOUND = "unlock_sound";
+        @Deprecated
+        public static final String UNLOCK_SOUND = Global.UNLOCK_SOUND;
 
         /**
          * Receive incoming SIP calls?
@@ -2001,7 +2270,7 @@
          * @hide
          */
         public static final String[] SETTINGS_TO_BACKUP = {
-            STAY_ON_WHILE_PLUGGED_IN,
+            STAY_ON_WHILE_PLUGGED_IN,   // moved to global
             WIFI_USE_STATIC_IP,
             WIFI_STATIC_IP,
             WIFI_STATIC_GATEWAY,
@@ -2016,7 +2285,7 @@
             SCREEN_BRIGHTNESS_MODE,
             SCREEN_AUTO_BRIGHTNESS_ADJ,
             VIBRATE_INPUT_DEVICES,
-            MODE_RINGER,
+            MODE_RINGER,                // moved to global
             MODE_RINGER_STREAMS_AFFECTED,
             MUTE_STREAMS_AFFECTED,
             VOLUME_VOICE,
@@ -2037,20 +2306,18 @@
             TEXT_AUTO_CAPS,
             TEXT_AUTO_PUNCTUATE,
             TEXT_SHOW_PASSWORD,
-            AUTO_TIME,
-            AUTO_TIME_ZONE,
+            AUTO_TIME,                  // moved to global
+            AUTO_TIME_ZONE,             // moved to global
             TIME_12_24,
             DATE_FORMAT,
             DTMF_TONE_WHEN_DIALING,
             DTMF_TONE_TYPE_WHEN_DIALING,
-            EMERGENCY_TONE,
-            CALL_AUTO_RETRY,
             HEARING_AID,
             TTY_MODE,
             SOUND_EFFECTS_ENABLED,
             HAPTIC_FEEDBACK_ENABLED,
-            POWER_SOUNDS_ENABLED,
-            DOCK_SOUNDS_ENABLED,
+            POWER_SOUNDS_ENABLED,       // moved to global
+            DOCK_SOUNDS_ENABLED,        // moved to global
             LOCKSCREEN_SOUNDS_ENABLED,
             SHOW_WEB_SUGGESTIONS,
             NOTIFICATION_LIGHT_PULSE,
@@ -2063,11 +2330,11 @@
         // Settings moved to Settings.Secure
 
         /**
-         * @deprecated Use {@link android.provider.Settings.Secure#ADB_ENABLED}
+         * @deprecated Use {@link android.provider.Settings.Global#ADB_ENABLED}
          * instead
          */
         @Deprecated
-        public static final String ADB_ENABLED = Secure.ADB_ENABLED;
+        public static final String ADB_ENABLED = Global.ADB_ENABLED;
 
         /**
          * @deprecated Use {@link android.provider.Settings.Secure#ANDROID_ID} instead
@@ -2076,34 +2343,34 @@
         public static final String ANDROID_ID = Secure.ANDROID_ID;
 
         /**
-         * @deprecated Use {@link android.provider.Settings.Secure#BLUETOOTH_ON} instead
+         * @deprecated Use {@link android.provider.Settings.Global#BLUETOOTH_ON} instead
          */
         @Deprecated
-        public static final String BLUETOOTH_ON = Secure.BLUETOOTH_ON;
+        public static final String BLUETOOTH_ON = Global.BLUETOOTH_ON;
 
         /**
-         * @deprecated Use {@link android.provider.Settings.Secure#DATA_ROAMING} instead
+         * @deprecated Use {@link android.provider.Settings.Global#DATA_ROAMING} instead
          */
         @Deprecated
-        public static final String DATA_ROAMING = Secure.DATA_ROAMING;
+        public static final String DATA_ROAMING = Global.DATA_ROAMING;
 
         /**
-         * @deprecated Use {@link android.provider.Settings.Secure#DEVICE_PROVISIONED} instead
+         * @deprecated Use {@link android.provider.Settings.Global#DEVICE_PROVISIONED} instead
          */
         @Deprecated
-        public static final String DEVICE_PROVISIONED = Secure.DEVICE_PROVISIONED;
+        public static final String DEVICE_PROVISIONED = Global.DEVICE_PROVISIONED;
 
         /**
-         * @deprecated Use {@link android.provider.Settings.Secure#HTTP_PROXY} instead
+         * @deprecated Use {@link android.provider.Settings.Global#HTTP_PROXY} instead
          */
         @Deprecated
-        public static final String HTTP_PROXY = Secure.HTTP_PROXY;
+        public static final String HTTP_PROXY = Global.HTTP_PROXY;
 
         /**
-         * @deprecated Use {@link android.provider.Settings.Secure#INSTALL_NON_MARKET_APPS} instead
+         * @deprecated Use {@link android.provider.Settings.Global#INSTALL_NON_MARKET_APPS} instead
          */
         @Deprecated
-        public static final String INSTALL_NON_MARKET_APPS = Secure.INSTALL_NON_MARKET_APPS;
+        public static final String INSTALL_NON_MARKET_APPS = Global.INSTALL_NON_MARKET_APPS;
 
         /**
          * @deprecated Use {@link android.provider.Settings.Secure#LOCATION_PROVIDERS_ALLOWED}
@@ -2119,10 +2386,10 @@
         public static final String LOGGING_ID = Secure.LOGGING_ID;
 
         /**
-         * @deprecated Use {@link android.provider.Settings.Secure#NETWORK_PREFERENCE} instead
+         * @deprecated Use {@link android.provider.Settings.Global#NETWORK_PREFERENCE} instead
          */
         @Deprecated
-        public static final String NETWORK_PREFERENCE = Secure.NETWORK_PREFERENCE;
+        public static final String NETWORK_PREFERENCE = Global.NETWORK_PREFERENCE;
 
         /**
          * @deprecated Use {@link android.provider.Settings.Secure#PARENTAL_CONTROL_ENABLED}
@@ -2153,60 +2420,60 @@
         public static final String SETTINGS_CLASSNAME = Secure.SETTINGS_CLASSNAME;
 
         /**
-         * @deprecated Use {@link android.provider.Settings.Secure#USB_MASS_STORAGE_ENABLED} instead
+         * @deprecated Use {@link android.provider.Settings.Global#USB_MASS_STORAGE_ENABLED} instead
          */
         @Deprecated
-        public static final String USB_MASS_STORAGE_ENABLED = Secure.USB_MASS_STORAGE_ENABLED;
+        public static final String USB_MASS_STORAGE_ENABLED = Global.USB_MASS_STORAGE_ENABLED;
 
         /**
-         * @deprecated Use {@link android.provider.Settings.Secure#USE_GOOGLE_MAIL} instead
+         * @deprecated Use {@link android.provider.Settings.Global#USE_GOOGLE_MAIL} instead
          */
         @Deprecated
-        public static final String USE_GOOGLE_MAIL = Secure.USE_GOOGLE_MAIL;
+        public static final String USE_GOOGLE_MAIL = Global.USE_GOOGLE_MAIL;
 
        /**
          * @deprecated Use
-         * {@link android.provider.Settings.Secure#WIFI_MAX_DHCP_RETRY_COUNT} instead
+         * {@link android.provider.Settings.Global#WIFI_MAX_DHCP_RETRY_COUNT} instead
          */
         @Deprecated
-        public static final String WIFI_MAX_DHCP_RETRY_COUNT = Secure.WIFI_MAX_DHCP_RETRY_COUNT;
+        public static final String WIFI_MAX_DHCP_RETRY_COUNT = Global.WIFI_MAX_DHCP_RETRY_COUNT;
 
         /**
          * @deprecated Use
-         * {@link android.provider.Settings.Secure#WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS} instead
+         * {@link android.provider.Settings.Global#WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS} instead
          */
         @Deprecated
         public static final String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS =
-                Secure.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS;
+                Global.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS;
 
         /**
          * @deprecated Use
-         * {@link android.provider.Settings.Secure#WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON} instead
+         * {@link android.provider.Settings.Global#WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON} instead
          */
         @Deprecated
         public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON =
-            Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON;
+                Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON;
 
         /**
          * @deprecated Use
-         * {@link android.provider.Settings.Secure#WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY} instead
+         * {@link android.provider.Settings.Global#WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY} instead
          */
         @Deprecated
         public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY =
-            Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY;
+                Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY;
 
         /**
-         * @deprecated Use {@link android.provider.Settings.Secure#WIFI_NUM_OPEN_NETWORKS_KEPT}
+         * @deprecated Use {@link android.provider.Settings.Global#WIFI_NUM_OPEN_NETWORKS_KEPT}
          * instead
          */
         @Deprecated
-        public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = Secure.WIFI_NUM_OPEN_NETWORKS_KEPT;
+        public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = Global.WIFI_NUM_OPEN_NETWORKS_KEPT;
 
         /**
-         * @deprecated Use {@link android.provider.Settings.Secure#WIFI_ON} instead
+         * @deprecated Use {@link android.provider.Settings.Global#WIFI_ON} instead
          */
         @Deprecated
-        public static final String WIFI_ON = Secure.WIFI_ON;
+        public static final String WIFI_ON = Global.WIFI_ON;
 
         /**
          * @deprecated Use
@@ -2264,10 +2531,10 @@
         public static final String WIFI_WATCHDOG_MAX_AP_CHECKS = Secure.WIFI_WATCHDOG_MAX_AP_CHECKS;
 
         /**
-         * @deprecated Use {@link android.provider.Settings.Secure#WIFI_WATCHDOG_ON} instead
+         * @deprecated Use {@link android.provider.Settings.Global#WIFI_WATCHDOG_ON} instead
          */
         @Deprecated
-        public static final String WIFI_WATCHDOG_ON = Secure.WIFI_WATCHDOG_ON;
+        public static final String WIFI_WATCHDOG_ON = Global.WIFI_WATCHDOG_ON;
 
         /**
          * @deprecated Use {@link android.provider.Settings.Secure#WIFI_WATCHDOG_PING_COUNT} instead
@@ -2300,18 +2567,155 @@
     public static final class Secure extends NameValueTable {
         public static final String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version";
 
+        /**
+         * The content:// style URL for this table
+         */
+        public static final Uri CONTENT_URI =
+            Uri.parse("content://" + AUTHORITY + "/secure");
+
         // Populated lazily, guarded by class object:
-        private static NameValueCache sNameValueCache = null;
+        private static final NameValueCache sNameValueCache = new NameValueCache(
+                SYS_PROP_SETTING_VERSION,
+                CONTENT_URI,
+                CALL_METHOD_GET_SECURE,
+                CALL_METHOD_PUT_SECURE);
 
         private static ILockSettings sLockSettings = null;
 
         private static boolean sIsSystemProcess;
         private static final HashSet<String> MOVED_TO_LOCK_SETTINGS;
+        private static final HashSet<String> MOVED_TO_GLOBAL;
         static {
             MOVED_TO_LOCK_SETTINGS = new HashSet<String>(3);
             MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_ENABLED);
             MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_VISIBLE);
             MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED);
+
+            MOVED_TO_GLOBAL = new HashSet<String>();
+            MOVED_TO_GLOBAL.add(Settings.Global.ADB_ENABLED);
+            MOVED_TO_GLOBAL.add(Settings.Global.ASSISTED_GPS_ENABLED);
+            MOVED_TO_GLOBAL.add(Settings.Global.BLUETOOTH_ON);
+            MOVED_TO_GLOBAL.add(Settings.Global.CDMA_CELL_BROADCAST_SMS);
+            MOVED_TO_GLOBAL.add(Settings.Global.CDMA_ROAMING_MODE);
+            MOVED_TO_GLOBAL.add(Settings.Global.CDMA_SUBSCRIPTION_MODE);
+            MOVED_TO_GLOBAL.add(Settings.Global.DATA_ACTIVITY_TIMEOUT_MOBILE);
+            MOVED_TO_GLOBAL.add(Settings.Global.DATA_ACTIVITY_TIMEOUT_WIFI);
+            MOVED_TO_GLOBAL.add(Settings.Global.DATA_ROAMING);
+            MOVED_TO_GLOBAL.add(Settings.Global.DEVELOPMENT_SETTINGS_ENABLED);
+            MOVED_TO_GLOBAL.add(Settings.Global.DEVICE_PROVISIONED);
+            MOVED_TO_GLOBAL.add(Settings.Global.DISPLAY_DENSITY_FORCED);
+            MOVED_TO_GLOBAL.add(Settings.Global.DISPLAY_SIZE_FORCED);
+            MOVED_TO_GLOBAL.add(Settings.Global.DOWNLOAD_MAX_BYTES_OVER_MOBILE);
+            MOVED_TO_GLOBAL.add(Settings.Global.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE);
+            MOVED_TO_GLOBAL.add(Settings.Global.INSTALL_NON_MARKET_APPS);
+            MOVED_TO_GLOBAL.add(Settings.Global.MOBILE_DATA);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_DEV_BUCKET_DURATION);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_DEV_DELETE_AGE);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_DEV_PERSIST_BYTES);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_DEV_ROTATE_AGE);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_ENABLED);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_POLL_INTERVAL);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_REPORT_XT_OVER_DEV);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_SAMPLE_ENABLED);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_TIME_CACHE_MAX_AGE);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_UID_BUCKET_DURATION);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_UID_DELETE_AGE);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_UID_PERSIST_BYTES);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_UID_ROTATE_AGE);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_UID_TAG_DELETE_AGE);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE);
+            MOVED_TO_GLOBAL.add(Settings.Global.NETWORK_PREFERENCE);
+            MOVED_TO_GLOBAL.add(Settings.Global.NITZ_UPDATE_DIFF);
+            MOVED_TO_GLOBAL.add(Settings.Global.NITZ_UPDATE_SPACING);
+            MOVED_TO_GLOBAL.add(Settings.Global.NTP_SERVER);
+            MOVED_TO_GLOBAL.add(Settings.Global.NTP_TIMEOUT);
+            MOVED_TO_GLOBAL.add(Settings.Global.PDP_WATCHDOG_ERROR_POLL_COUNT);
+            MOVED_TO_GLOBAL.add(Settings.Global.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS);
+            MOVED_TO_GLOBAL.add(Settings.Global.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT);
+            MOVED_TO_GLOBAL.add(Settings.Global.PDP_WATCHDOG_POLL_INTERVAL_MS);
+            MOVED_TO_GLOBAL.add(Settings.Global.PDP_WATCHDOG_TRIGGER_PACKET_COUNT);
+            MOVED_TO_GLOBAL.add(Settings.Global.SAMPLING_PROFILER_MS);
+            MOVED_TO_GLOBAL.add(Settings.Global.SETUP_PREPAID_DATA_SERVICE_URL);
+            MOVED_TO_GLOBAL.add(Settings.Global.SETUP_PREPAID_DETECTION_REDIR_HOST);
+            MOVED_TO_GLOBAL.add(Settings.Global.SETUP_PREPAID_DETECTION_TARGET_URL);
+            MOVED_TO_GLOBAL.add(Settings.Global.TETHER_DUN_APN);
+            MOVED_TO_GLOBAL.add(Settings.Global.TETHER_DUN_REQUIRED);
+            MOVED_TO_GLOBAL.add(Settings.Global.TETHER_SUPPORTED);
+            MOVED_TO_GLOBAL.add(Settings.Global.THROTTLE_HELP_URI);
+            MOVED_TO_GLOBAL.add(Settings.Global.THROTTLE_MAX_NTP_CACHE_AGE_SEC);
+            MOVED_TO_GLOBAL.add(Settings.Global.THROTTLE_NOTIFICATION_TYPE);
+            MOVED_TO_GLOBAL.add(Settings.Global.THROTTLE_POLLING_SEC);
+            MOVED_TO_GLOBAL.add(Settings.Global.THROTTLE_RESET_DAY);
+            MOVED_TO_GLOBAL.add(Settings.Global.THROTTLE_THRESHOLD_BYTES);
+            MOVED_TO_GLOBAL.add(Settings.Global.THROTTLE_VALUE_KBITSPS);
+            MOVED_TO_GLOBAL.add(Settings.Global.USB_MASS_STORAGE_ENABLED);
+            MOVED_TO_GLOBAL.add(Settings.Global.USE_GOOGLE_MAIL);
+            MOVED_TO_GLOBAL.add(Settings.Global.WEB_AUTOFILL_QUERY_URL);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_COUNTRY_CODE);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_FRAMEWORK_SCAN_INTERVAL_MS);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_FREQUENCY_BAND);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_IDLE_MS);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_NUM_OPEN_NETWORKS_KEPT);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_ON);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_P2P_DEVICE_NAME);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_SAVED_STATE);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_WATCHDOG_ON);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON);
+            MOVED_TO_GLOBAL.add(Settings.Global.PACKAGE_VERIFIER_ENABLE);
+            MOVED_TO_GLOBAL.add(Settings.Global.PACKAGE_VERIFIER_TIMEOUT);
+            MOVED_TO_GLOBAL.add(Settings.Global.PACKAGE_VERIFIER_DEFAULT_RESPONSE);
+            MOVED_TO_GLOBAL.add(Settings.Global.DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS);
+            MOVED_TO_GLOBAL.add(Settings.Global.DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS);
+            MOVED_TO_GLOBAL.add(Settings.Global.GPRS_REGISTER_CHECK_PERIOD_MS);
+            MOVED_TO_GLOBAL.add(Settings.Global.WTF_IS_FATAL);
+            MOVED_TO_GLOBAL.add(Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD);
+            MOVED_TO_GLOBAL.add(Settings.Global.BATTERY_DISCHARGE_THRESHOLD);
+            MOVED_TO_GLOBAL.add(Settings.Global.SEND_ACTION_APP_ERROR);
+            MOVED_TO_GLOBAL.add(Settings.Global.DROPBOX_AGE_SECONDS);
+            MOVED_TO_GLOBAL.add(Settings.Global.DROPBOX_MAX_FILES);
+            MOVED_TO_GLOBAL.add(Settings.Global.DROPBOX_QUOTA_KB);
+            MOVED_TO_GLOBAL.add(Settings.Global.DROPBOX_QUOTA_PERCENT);
+            MOVED_TO_GLOBAL.add(Settings.Global.DROPBOX_RESERVE_PERCENT);
+            MOVED_TO_GLOBAL.add(Settings.Global.DROPBOX_TAG_PREFIX);
+            MOVED_TO_GLOBAL.add(Settings.Global.ERROR_LOGCAT_PREFIX);
+            MOVED_TO_GLOBAL.add(Settings.Global.SYS_FREE_STORAGE_LOG_INTERVAL);
+            MOVED_TO_GLOBAL.add(Settings.Global.DISK_FREE_CHANGE_REPORTING_THRESHOLD);
+            MOVED_TO_GLOBAL.add(Settings.Global.SYS_STORAGE_THRESHOLD_PERCENTAGE);
+            MOVED_TO_GLOBAL.add(Settings.Global.SYS_STORAGE_THRESHOLD_MAX_BYTES);
+            MOVED_TO_GLOBAL.add(Settings.Global.SYS_STORAGE_FULL_THRESHOLD_BYTES);
+            MOVED_TO_GLOBAL.add(Settings.Global.SYNC_MAX_RETRY_DELAY_IN_SECONDS);
+            MOVED_TO_GLOBAL.add(Settings.Global.CONNECTIVITY_CHANGE_DELAY);
+            MOVED_TO_GLOBAL.add(Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED);
+            MOVED_TO_GLOBAL.add(Settings.Global.CAPTIVE_PORTAL_SERVER);
+            MOVED_TO_GLOBAL.add(Settings.Global.NSD_ON);
+            MOVED_TO_GLOBAL.add(Settings.Global.SET_INSTALL_LOCATION);
+            MOVED_TO_GLOBAL.add(Settings.Global.DEFAULT_INSTALL_LOCATION);
+            MOVED_TO_GLOBAL.add(Settings.Global.INET_CONDITION_DEBOUNCE_UP_DELAY);
+            MOVED_TO_GLOBAL.add(Settings.Global.INET_CONDITION_DEBOUNCE_DOWN_DELAY);
+            MOVED_TO_GLOBAL.add(Settings.Global.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT);
+            MOVED_TO_GLOBAL.add(Settings.Global.HTTP_PROXY);
+            MOVED_TO_GLOBAL.add(Settings.Global.GLOBAL_HTTP_PROXY_HOST);
+            MOVED_TO_GLOBAL.add(Settings.Global.GLOBAL_HTTP_PROXY_PORT);
+            MOVED_TO_GLOBAL.add(Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
+            MOVED_TO_GLOBAL.add(Settings.Global.SET_GLOBAL_HTTP_PROXY);
+            MOVED_TO_GLOBAL.add(Settings.Global.DEFAULT_DNS_SERVER);
+            MOVED_TO_GLOBAL.add(Settings.Global.PREFERRED_NETWORK_MODE);
+            MOVED_TO_GLOBAL.add(Settings.Global.PREFERRED_CDMA_SUBSCRIPTION);
+        }
+
+        /** @hide */
+        public static void getMovedKeys(HashSet<String> outKeySet) {
+            outKeySet.addAll(MOVED_TO_GLOBAL);
         }
 
         /**
@@ -2320,27 +2724,37 @@
          * @param name to look up in the table
          * @return the corresponding value, or null if not present
          */
-        public synchronized static String getString(ContentResolver resolver, String name) {
-            if (sNameValueCache == null) {
-                sNameValueCache = new NameValueCache(SYS_PROP_SETTING_VERSION, CONTENT_URI,
-                                                     CALL_METHOD_GET_SECURE);
+        public static String getString(ContentResolver resolver, String name) {
+            return getStringForUser(resolver, name, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static String getStringForUser(ContentResolver resolver, String name,
+                int userHandle) {
+            if (MOVED_TO_GLOBAL.contains(name)) {
+                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.Secure"
+                        + " to android.provider.Settings.Global.");
+                return Global.getStringForUser(resolver, name, userHandle);
             }
 
-            if (sLockSettings == null) {
-                sLockSettings = ILockSettings.Stub.asInterface(
-                        (IBinder) ServiceManager.getService("lock_settings"));
-                sIsSystemProcess = Process.myUid() == Process.SYSTEM_UID;
-            }
-            if (sLockSettings != null && !sIsSystemProcess
-                    && MOVED_TO_LOCK_SETTINGS.contains(name)) {
-                try {
-                    return sLockSettings.getString(name, "0", UserId.getCallingUserId());
-                } catch (RemoteException re) {
-                    // Fall through
+            if (MOVED_TO_LOCK_SETTINGS.contains(name)) {
+                synchronized (Secure.class) {
+                    if (sLockSettings == null) {
+                        sLockSettings = ILockSettings.Stub.asInterface(
+                                (IBinder) ServiceManager.getService("lock_settings"));
+                        sIsSystemProcess = Process.myUid() == Process.SYSTEM_UID;
+                    }
+                }
+                if (sLockSettings != null && !sIsSystemProcess) {
+                    try {
+                        return sLockSettings.getString(name, "0", userHandle);
+                    } catch (RemoteException re) {
+                        // Fall through
+                    }
                 }
             }
 
-            return sNameValueCache.getString(resolver, name);
+            return sNameValueCache.getStringForUser(resolver, name, userHandle);
         }
 
         /**
@@ -2350,9 +2764,19 @@
          * @param value to associate with the name
          * @return true if the value was set, false on database errors
          */
-        public static boolean putString(ContentResolver resolver,
-                String name, String value) {
-            return putString(resolver, CONTENT_URI, name, value);
+        public static boolean putString(ContentResolver resolver, String name, String value) {
+            return putStringForUser(resolver, name, value, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static boolean putStringForUser(ContentResolver resolver, String name, String value,
+                int userHandle) {
+            if (MOVED_TO_GLOBAL.contains(name)) {
+                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
+                        + " to android.provider.Settings.Global");
+                return Global.putStringForUser(resolver, name, value, userHandle);
+            }
+            return sNameValueCache.putStringForUser(resolver, name, value, userHandle);
         }
 
         /**
@@ -2362,6 +2786,11 @@
          * @return the corresponding content URI, or null if not present
          */
         public static Uri getUriFor(String name) {
+            if (MOVED_TO_GLOBAL.contains(name)) {
+                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.Secure"
+                        + " to android.provider.Settings.Global, returning global URI.");
+                return Global.getUriFor(Global.CONTENT_URI, name);
+            }
             return getUriFor(CONTENT_URI, name);
         }
 
@@ -2380,7 +2809,12 @@
          * or not a valid integer.
          */
         public static int getInt(ContentResolver cr, String name, int def) {
-            String v = getString(cr, name);
+            return getIntForUser(cr, name, def, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static int getIntForUser(ContentResolver cr, String name, int def, int userHandle) {
+            String v = getStringForUser(cr, name, userHandle);
             try {
                 return v != null ? Integer.parseInt(v) : def;
             } catch (NumberFormatException e) {
@@ -2408,7 +2842,13 @@
          */
         public static int getInt(ContentResolver cr, String name)
                 throws SettingNotFoundException {
-            String v = getString(cr, name);
+            return getIntForUser(cr, name, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static int getIntForUser(ContentResolver cr, String name, int userHandle)
+                throws SettingNotFoundException {
+            String v = getStringForUser(cr, name, userHandle);
             try {
                 return Integer.parseInt(v);
             } catch (NumberFormatException e) {
@@ -2430,7 +2870,13 @@
          * @return true if the value was set, false on database errors
          */
         public static boolean putInt(ContentResolver cr, String name, int value) {
-            return putString(cr, name, Integer.toString(value));
+            return putIntForUser(cr, name, value, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static boolean putIntForUser(ContentResolver cr, String name, int value,
+                int userHandle) {
+            return putStringForUser(cr, name, Integer.toString(value), userHandle);
         }
 
         /**
@@ -2448,7 +2894,13 @@
          * or not a valid {@code long}.
          */
         public static long getLong(ContentResolver cr, String name, long def) {
-            String valString = getString(cr, name);
+            return getLongForUser(cr, name, def, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static long getLongForUser(ContentResolver cr, String name, long def,
+                int userHandle) {
+            String valString = getStringForUser(cr, name, userHandle);
             long value;
             try {
                 value = valString != null ? Long.parseLong(valString) : def;
@@ -2477,7 +2929,13 @@
          */
         public static long getLong(ContentResolver cr, String name)
                 throws SettingNotFoundException {
-            String valString = getString(cr, name);
+            return getLongForUser(cr, name, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static long getLongForUser(ContentResolver cr, String name, int userHandle)
+                throws SettingNotFoundException {
+            String valString = getStringForUser(cr, name, userHandle);
             try {
                 return Long.parseLong(valString);
             } catch (NumberFormatException e) {
@@ -2499,7 +2957,13 @@
          * @return true if the value was set, false on database errors
          */
         public static boolean putLong(ContentResolver cr, String name, long value) {
-            return putString(cr, name, Long.toString(value));
+            return putLongForUser(cr, name, value, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static boolean putLongForUser(ContentResolver cr, String name, long value,
+                int userHandle) {
+            return putStringForUser(cr, name, Long.toString(value), userHandle);
         }
 
         /**
@@ -2517,7 +2981,13 @@
          * or not a valid float.
          */
         public static float getFloat(ContentResolver cr, String name, float def) {
-            String v = getString(cr, name);
+            return getFloatForUser(cr, name, def, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static float getFloatForUser(ContentResolver cr, String name, float def,
+                int userHandle) {
+            String v = getStringForUser(cr, name, userHandle);
             try {
                 return v != null ? Float.parseFloat(v) : def;
             } catch (NumberFormatException e) {
@@ -2545,7 +3015,13 @@
          */
         public static float getFloat(ContentResolver cr, String name)
                 throws SettingNotFoundException {
-            String v = getString(cr, name);
+            return getFloatForUser(cr, name, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static float getFloatForUser(ContentResolver cr, String name, int userHandle)
+                throws SettingNotFoundException {
+            String v = getStringForUser(cr, name, userHandle);
             if (v == null) {
                 throw new SettingNotFoundException(name);
             }
@@ -2570,24 +3046,35 @@
          * @return true if the value was set, false on database errors
          */
         public static boolean putFloat(ContentResolver cr, String name, float value) {
-            return putString(cr, name, Float.toString(value));
+            return putFloatForUser(cr, name, value, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static boolean putFloatForUser(ContentResolver cr, String name, float value,
+                int userHandle) {
+            return putStringForUser(cr, name, Float.toString(value), userHandle);
         }
 
         /**
-         * The content:// style URL for this table
+         * @deprecated Use {@link android.provider.Settings.Global#DEVELOPMENT_SETTINGS_ENABLED}
+         * instead
          */
-        public static final Uri CONTENT_URI =
-            Uri.parse("content://" + AUTHORITY + "/secure");
+        @Deprecated
+        public static final String DEVELOPMENT_SETTINGS_ENABLED =
+                Global.DEVELOPMENT_SETTINGS_ENABLED;
 
         /**
-         * Whether user has enabled development settings.
+         * When the user has enable the option to have a "bug report" command
+         * in the power menu.
+         * @hide
          */
-        public static final String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
+        public static final String BUGREPORT_IN_POWER_MENU = "bugreport_in_power_menu";
 
         /**
-         * Whether ADB is enabled.
+         * @deprecated Use {@link android.provider.Settings.Global#ADB_ENABLED} instead
          */
-        public static final String ADB_ENABLED = "adb_enabled";
+        @Deprecated
+        public static final String ADB_ENABLED = Global.ADB_ENABLED;
 
         /**
          * Setting to allow mock locations and location provider status to be injected into the
@@ -2606,39 +3093,16 @@
         public static final String ANDROID_ID = "android_id";
 
         /**
-         * Whether bluetooth is enabled/disabled
-         * 0=disabled. 1=enabled.
+         * @deprecated Use {@link android.provider.Settings.Global#BLUETOOTH_ON} instead
          */
-        public static final String BLUETOOTH_ON = "bluetooth_on";
+        @Deprecated
+        public static final String BLUETOOTH_ON = Global.BLUETOOTH_ON;
 
         /**
-         * Get the key that retrieves a bluetooth headset's priority.
-         * @hide
+         * @deprecated Use {@link android.provider.Settings.Global#DATA_ROAMING} instead
          */
-        public static final String getBluetoothHeadsetPriorityKey(String address) {
-            return ("bluetooth_headset_priority_" + address.toUpperCase());
-        }
-
-        /**
-         * Get the key that retrieves a bluetooth a2dp sink's priority.
-         * @hide
-         */
-        public static final String getBluetoothA2dpSinkPriorityKey(String address) {
-            return ("bluetooth_a2dp_sink_priority_" + address.toUpperCase());
-        }
-
-        /**
-         * Get the key that retrieves a bluetooth Input Device's priority.
-         * @hide
-         */
-        public static final String getBluetoothInputDevicePriorityKey(String address) {
-            return ("bluetooth_input_device_priority_" + address.toUpperCase());
-        }
-
-        /**
-         * Whether or not data roaming is enabled. (0 = false, 1 = true)
-         */
-        public static final String DATA_ROAMING = "data_roaming";
+        @Deprecated
+        public static final String DATA_ROAMING = Global.DATA_ROAMING;
 
         /**
          * Setting to record the input method used by default, holding the ID
@@ -2668,9 +3132,16 @@
                 "input_method_selector_visibility";
 
         /**
-         * Whether the device has been provisioned (0 = false, 1 = true)
+         * @deprecated Use {@link android.provider.Settings.Global#DEVICE_PROVISIONED} instead
          */
-        public static final String DEVICE_PROVISIONED = "device_provisioned";
+        @Deprecated
+        public static final String DEVICE_PROVISIONED = Global.DEVICE_PROVISIONED;
+
+        /**
+         * Whether the current user has been set up via setup wizard (0 = false, 1 = true)
+         * @hide
+         */
+        public static final String USER_SETUP_COMPLETE = "user_setup_complete";
 
         /**
          * List of input methods that are currently enabled.  This is a string
@@ -2688,54 +3159,19 @@
         public static final String DISABLED_SYSTEM_INPUT_METHODS = "disabled_system_input_methods";
 
         /**
-         * Host name and port for global http proxy.  Uses ':' seperator for between host and port
-         * TODO - deprecate in favor of global_http_proxy_host, etc
-         */
-        public static final String HTTP_PROXY = "http_proxy";
-
-        /**
-         * Host name for global http proxy.  Set via ConnectivityManager.
-         * @hide
-         */
-        public static final String GLOBAL_HTTP_PROXY_HOST = "global_http_proxy_host";
-
-        /**
-         * Integer host port for global http proxy.  Set via ConnectivityManager.
-         * @hide
-         */
-        public static final String GLOBAL_HTTP_PROXY_PORT = "global_http_proxy_port";
-
-        /**
-         * Exclusion list for global proxy. This string contains a list of comma-separated
-         * domains where the global proxy does not apply. Domains should be listed in a comma-
-         * separated list. Example of acceptable formats: ".domain1.com,my.domain2.com"
-         * Use ConnectivityManager to set/get.
-         * @hide
-         */
-        public static final String GLOBAL_HTTP_PROXY_EXCLUSION_LIST =
-                "global_http_proxy_exclusion_list";
-
-        /**
-         * Enables the UI setting to allow the user to specify the global HTTP proxy
-         * and associated exclusion list.
-         * @hide
-         */
-        public static final String SET_GLOBAL_HTTP_PROXY = "set_global_http_proxy";
-
-        /**
-         * Setting for default DNS in case nobody suggests one
-         * @hide
-         */
-        public static final String DEFAULT_DNS_SERVER = "default_dns_server";
-
-        /**
-         * Whether the package installer should allow installation of apps downloaded from
-         * sources other than Google Play.
+         * Host name and port for global http proxy. Uses ':' seperator for
+         * between host and port.
          *
-         * 1 = allow installing from other sources
-         * 0 = only allow installing from Google Play
+         * @deprecated Use {@link Global#HTTP_PROXY}
          */
-        public static final String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+        @Deprecated
+        public static final String HTTP_PROXY = Global.HTTP_PROXY;
+
+        /**
+         * @deprecated Use {@link android.provider.Settings.Global#INSTALL_NON_MARKET_APPS} instead
+         */
+        @Deprecated
+        public static final String INSTALL_NON_MARKET_APPS = Global.INSTALL_NON_MARKET_APPS;
 
         /**
          * Comma-separated list of location providers that activities may access.
@@ -2760,10 +3196,16 @@
         public static final String LOCK_PATTERN_VISIBLE = "lock_pattern_visible_pattern";
 
         /**
-         * Whether lock pattern will vibrate as user enters (0 = false, 1 = true)
+         * Whether lock pattern will vibrate as user enters (0 = false, 1 =
+         * true)
+         *
+         * @deprecated Starting in {@link VERSION_CODES#JELLY_BEAN_MR1} the
+         *             lockscreen uses
+         *             {@link Settings.System#HAPTIC_FEEDBACK_ENABLED}.
          */
-        public static final String LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED =
-            "lock_pattern_tactile_feedback_enabled";
+        @Deprecated
+        public static final String
+                LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED = "lock_pattern_tactile_feedback_enabled";
 
         /**
          * This preference allows the device to be locked given time after screen goes off,
@@ -2774,32 +3216,40 @@
 
 
         /**
-         * This preference contains the string that shows for owner info on LockScren.
+         * This preference contains the string that shows for owner info on LockScreen.
          * @hide
          */
         public static final String LOCK_SCREEN_OWNER_INFO = "lock_screen_owner_info";
 
         /**
-         * This preference enables showing the owner info on LockScren.
+         * Ids of the user-selected appwidgets on the lockscreen (comma-delimited).
+         * @hide
+         */
+        public static final String LOCK_SCREEN_APPWIDGET_IDS =
+            "lock_screen_appwidget_ids";
+
+        /**
+         * Id of the appwidget shown on the lock screen when appwidgets are disabled.
+         * @hide
+         */
+        public static final String LOCK_SCREEN_FALLBACK_APPWIDGET_ID =
+            "lock_screen_fallback_appwidget_id";
+
+        /**
+         * Index of the lockscreen appwidget to restore, -1 if none.
+         * @hide
+         */
+        public static final String LOCK_SCREEN_STICKY_APPWIDGET =
+            "lock_screen_sticky_appwidget";
+
+        /**
+         * This preference enables showing the owner info on LockScreen.
          * @hide
          */
         public static final String LOCK_SCREEN_OWNER_INFO_ENABLED =
             "lock_screen_owner_info_enabled";
 
         /**
-         * The saved value for WindowManagerService.setForcedDisplaySize().
-         * Two integers separated by a comma.  If unset, then use the real display size.
-         * @hide
-         */
-        public static final String DISPLAY_SIZE_FORCED = "display_size_forced";
-
-        /**
-         * Whether assisted GPS should be enabled or not.
-         * @hide
-         */
-        public static final String ASSISTED_GPS_ENABLED = "assisted_gps_enabled";
-
-        /**
          * The Logging ID (a unique 64-bit value) as a hex string.
          * Used as a pseudonymous identifier for logging.
          * @deprecated This identifier is poorly initialized and has
@@ -2809,34 +3259,10 @@
         public static final String LOGGING_ID = "logging_id";
 
         /**
-         * User preference for which network(s) should be used. Only the
-         * connectivity service should touch this.
+         * @deprecated Use {@link android.provider.Settings.Global#NETWORK_PREFERENCE} instead
          */
-        public static final String NETWORK_PREFERENCE = "network_preference";
-
-        /**
-         * Used to disable Tethering on a device - defaults to true
-         * @hide
-         */
-        public static final String TETHER_SUPPORTED = "tether_supported";
-
-        /**
-         * Used to require DUN APN on the device or not - defaults to a build config value
-         * which defaults to false
-         * @hide
-         */
-        public static final String TETHER_DUN_REQUIRED = "tether_dun_required";
-
-        /**
-         * Used to hold a gservices-provisioned apn value for DUN.  If set, or the
-         * corresponding build config values are set it will override the APN DB
-         * values.
-         * Consists of a comma seperated list of strings:
-         * "name,apn,proxy,port,username,password,server,mmsc,mmsproxy,mmsport,mcc,mnc,auth,type"
-         * note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN"
-         * @hide
-         */
-        public static final String TETHER_DUN_APN = "tether_dun_apn";
+        @Deprecated
+        public static final String NETWORK_PREFERENCE = Global.NETWORK_PREFERENCE;
 
         /**
          * No longer supported.
@@ -2854,15 +3280,6 @@
         public static final String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url";
 
         /**
-         * A positive value indicates how often the SamplingProfiler
-         * should take snapshots. Zero value means SamplingProfiler
-         * is disabled.
-         *
-         * @hide
-         */
-        public static final String SAMPLING_PROFILER_MS = "sampling_profiler_ms";
-
-        /**
          * Settings classname to launch when Settings is clicked from All
          * Applications.  Needed because of user testing between the old
          * and new Settings apps.
@@ -2871,15 +3288,16 @@
         public static final String SETTINGS_CLASSNAME = "settings_classname";
 
         /**
-         * USB Mass Storage Enabled
+         * @deprecated Use {@link android.provider.Settings.Global#USB_MASS_STORAGE_ENABLED} instead
          */
-        public static final String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
+        @Deprecated
+        public static final String USB_MASS_STORAGE_ENABLED = Global.USB_MASS_STORAGE_ENABLED;
 
         /**
-         * If this setting is set (to anything), then all references
-         * to Gmail on the device must change to Google Mail.
+         * @deprecated Use {@link android.provider.Settings.Global#USE_GOOGLE_MAIL} instead
          */
-        public static final String USE_GOOGLE_MAIL = "use_google_mail";
+        @Deprecated
+        public static final String USE_GOOGLE_MAIL = Global.USE_GOOGLE_MAIL;
 
         /**
          * If accessibility is enabled.
@@ -2898,7 +3316,7 @@
             "enabled_accessibility_services";
 
         /**
-         * List of the accessibility services to which the user has graned
+         * List of the accessibility services to which the user has granted
          * permission to put the device into touch exploration mode.
          *
          * @hide
@@ -2917,7 +3335,7 @@
          * <p>
          *   Note: The JavaScript based screen-reader is served by the
          *   Google infrastructure and enable users with disabilities to
-         *   efficiantly navigate in and explore web content.
+         *   efficiently navigate in and explore web content.
          * </p>
          * <p>
          *   This property represents a boolean value.
@@ -2929,7 +3347,7 @@
 
         /**
          * The URL for the injected JavaScript based screen-reader used
-         * for providing accessiblity of content in WebView.
+         * for providing accessibility of content in WebView.
          * <p>
          *   Note: The JavaScript based screen-reader is served by the
          *   Google infrastructure and enable users with disabilities to
@@ -2982,6 +3400,46 @@
             "accessibility_web_content_key_bindings";
 
         /**
+         * Setting that specifies whether the display magnification is enabled.
+         * Display magnifications allows the user to zoom in the display content
+         * and is targeted to low vision users. The current magnification scale
+         * is controlled by {@link #ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE}.
+         *
+         * @hide
+         */
+        public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED =
+                "accessibility_display_magnification_enabled";
+
+        /**
+         * Setting that specifies what the display magnification scale is.
+         * Display magnifications allows the user to zoom in the display
+         * content and is targeted to low vision users. Whether a display
+         * magnification is performed is controlled by
+         * {@link #ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED}
+         *
+         * @hide
+         */
+        public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE =
+                "accessibility_display_magnification_scale";
+
+        /**
+         * Setting that specifies whether the display magnification should be
+         * automatically updated. If this fearture is enabled the system will
+         * exit magnification mode or pan the viewport when a context change
+         * occurs. For example, on staring a new activity or rotating the screen,
+         * the system may zoom out so the user can see the new context he is in.
+         * Another example is on showing a window that is not visible in the
+         * magnified viewport the system may pan the viewport to make the window
+         * the has popped up so the user knows that the context has changed.
+         * Whether a screen magnification is performed is controlled by
+         * {@link #ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED}
+         *
+         * @hide
+         */
+        public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE =
+                "accessibility_display_magnification_auto_update";
+
+        /**
          * The timout for considering a press to be a long press in milliseconds.
          * @hide
          */
@@ -3067,80 +3525,40 @@
         public static final String TTS_ENABLED_PLUGINS = "tts_enabled_plugins";
 
         /**
-         * Whether to notify the user of open networks.
-         * <p>
-         * If not connected and the scan results have an open network, we will
-         * put this notification up. If we attempt to connect to a network or
-         * the open network(s) disappear, we remove the notification. When we
-         * show the notification, we will not show it again for
-         * {@link android.provider.Settings.Secure#WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY} time.
+         * @deprecated Use {@link android.provider.Settings.Global#WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON}
+         * instead.
          */
+        @Deprecated
         public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON =
-                "wifi_networks_available_notification_on";
-        /**
-         * {@hide}
-         */
-        public static final String WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON =
-                "wimax_networks_available_notification_on";
+                Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON;
 
         /**
-         * Delay (in seconds) before repeating the Wi-Fi networks available notification.
-         * Connecting to a network will reset the timer.
+         * @deprecated Use {@link android.provider.Settings.Global#WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY}
+         * instead.
          */
+        @Deprecated
         public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY =
-                "wifi_networks_available_repeat_delay";
+                Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY;
 
         /**
-         * 802.11 country code in ISO 3166 format
-         * @hide
+         * @deprecated Use {@link android.provider.Settings.Global#WIFI_NUM_OPEN_NETWORKS_KEPT}
+         * instead.
          */
-        public static final String WIFI_COUNTRY_CODE = "wifi_country_code";
-
+        @Deprecated
+        public static final String WIFI_NUM_OPEN_NETWORKS_KEPT =
+                Global.WIFI_NUM_OPEN_NETWORKS_KEPT;
 
         /**
-         * When the number of open networks exceeds this number, the
-         * least-recently-used excess networks will be removed.
+         * @deprecated Use {@link android.provider.Settings.Global#WIFI_ON}
+         * instead.
          */
-        public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
-
-        /**
-         * Whether the Wi-Fi should be on.  Only the Wi-Fi service should touch this.
-         */
-        public static final String WIFI_ON = "wifi_on";
-
-        /**
-         * Used to save the Wifi_ON state prior to tethering.
-         * This state will be checked to restore Wifi after
-         * the user turns off tethering.
-         *
-         * @hide
-         */
-        public static final String WIFI_SAVED_STATE = "wifi_saved_state";
-
-        /**
-         * AP SSID
-         *
-         * @hide
-         */
-        public static final String WIFI_AP_SSID = "wifi_ap_ssid";
-
-        /**
-         * AP security
-         *
-         * @hide
-         */
-        public static final String WIFI_AP_SECURITY = "wifi_ap_security";
-
-        /**
-         * AP passphrase
-         *
-         * @hide
-         */
-        public static final String WIFI_AP_PASSWD = "wifi_ap_passwd";
+        @Deprecated
+        public static final String WIFI_ON = Global.WIFI_ON;
 
         /**
          * The acceptable packet loss percentage (range 0 - 100) before trying
          * another AP on the same network.
+         * @deprecated This setting is not used.
          */
         @Deprecated
         public static final String WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE =
@@ -3149,12 +3567,14 @@
         /**
          * The number of access points required for a network in order for the
          * watchdog to monitor it.
+         * @deprecated This setting is not used.
          */
         @Deprecated
         public static final String WIFI_WATCHDOG_AP_COUNT = "wifi_watchdog_ap_count";
 
         /**
          * The delay between background checks.
+         * @deprecated This setting is not used.
          */
         @Deprecated
         public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS =
@@ -3163,6 +3583,7 @@
         /**
          * Whether the Wi-Fi watchdog is enabled for background checking even
          * after it thinks the user has connected to a good access point.
+         * @deprecated This setting is not used.
          */
         @Deprecated
         public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED =
@@ -3170,6 +3591,7 @@
 
         /**
          * The timeout for a background ping
+         * @deprecated This setting is not used.
          */
         @Deprecated
         public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS =
@@ -3180,6 +3602,7 @@
          * fail. Again, if these fail, they will *not* be used in packet loss
          * calculation. For example, one network always seemed to time out for
          * the first couple pings, so this is set to 3 by default.
+         * @deprecated This setting is not used.
          */
         @Deprecated
         public static final String WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT =
@@ -3190,145 +3613,68 @@
          * If this number is reached, the watchdog will no longer monitor the
          * initial connection state for the network. This is a safeguard for
          * networks containing multiple APs whose DNS does not respond to pings.
+         * @deprecated This setting is not used.
          */
         @Deprecated
         public static final String WIFI_WATCHDOG_MAX_AP_CHECKS = "wifi_watchdog_max_ap_checks";
 
         /**
-         * Whether the Wi-Fi watchdog is enabled.
+         * @deprecated Use {@link android.provider.Settings.Global#WIFI_WATCHDOG_ON} instead
          */
+        @Deprecated
         public static final String WIFI_WATCHDOG_ON = "wifi_watchdog_on";
 
         /**
          * A comma-separated list of SSIDs for which the Wi-Fi watchdog should be enabled.
+         * @deprecated This setting is not used.
          */
         @Deprecated
         public static final String WIFI_WATCHDOG_WATCH_LIST = "wifi_watchdog_watch_list";
 
         /**
          * The number of pings to test if an access point is a good connection.
+         * @deprecated This setting is not used.
          */
         @Deprecated
         public static final String WIFI_WATCHDOG_PING_COUNT = "wifi_watchdog_ping_count";
 
         /**
          * The delay between pings.
+         * @deprecated This setting is not used.
          */
         @Deprecated
         public static final String WIFI_WATCHDOG_PING_DELAY_MS = "wifi_watchdog_ping_delay_ms";
 
         /**
          * The timeout per ping.
+         * @deprecated This setting is not used.
          */
         @Deprecated
         public static final String WIFI_WATCHDOG_PING_TIMEOUT_MS = "wifi_watchdog_ping_timeout_ms";
 
         /**
-         * ms delay before rechecking an 'online' wifi connection when it is thought to be unstable.
-         * @hide
+         * @deprecated Use
+         * {@link android.provider.Settings.Global#WIFI_MAX_DHCP_RETRY_COUNT} instead
          */
-        public static final String WIFI_WATCHDOG_ARP_CHECK_INTERVAL_MS =
-                "wifi_watchdog_arp_interval_ms";
+        @Deprecated
+        public static final String WIFI_MAX_DHCP_RETRY_COUNT = Global.WIFI_MAX_DHCP_RETRY_COUNT;
 
         /**
-         * ms delay interval between rssi polling when the signal is known to be weak
-         * @hide
+         * @deprecated Use
+         * {@link android.provider.Settings.Global#WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS} instead
          */
-        public static final String WIFI_WATCHDOG_RSSI_FETCH_INTERVAL_MS =
-                "wifi_watchdog_rssi_fetch_interval_ms";
-
-
-        /**
-         * ms delay before rechecking a connect SSID for walled garden with a http download.
-         * @hide
-         */
-        public static final String WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS =
-                "wifi_watchdog_walled_garden_interval_ms";
-
-        /**
-         * Number of ARP pings per check.
-         * @hide
-         */
-        public static final String WIFI_WATCHDOG_NUM_ARP_PINGS = "wifi_watchdog_num_arp_pings";
-
-        /**
-         * Minimum number of responses to the arp pings to consider the test 'successful'.
-         * @hide
-         */
-        public static final String WIFI_WATCHDOG_MIN_ARP_RESPONSES =
-                "wifi_watchdog_min_arp_responses";
-
-        /**
-         * Timeout on ARP pings
-         * @hide
-         */
-        public static final String WIFI_WATCHDOG_ARP_PING_TIMEOUT_MS =
-                "wifi_watchdog_arp_ping_timeout_ms";
-
-        /**
-         * Setting to turn off poor network avoidance on Wi-Fi. Feature is enabled by default and
-         * the setting needs to be set to 0 to disable it.
-         * @hide
-         */
-        public static final String WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED =
-                "wifi_watchdog_poor_network_test_enabled";
-
-        /**
-         * Setting to turn off walled garden test on Wi-Fi. Feature is enabled by default and
-         * the setting needs to be set to 0 to disable it.
-         * @hide
-         */
-        public static final String WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED =
-                "wifi_watchdog_walled_garden_test_enabled";
-
-        /**
-         * The URL used for walled garden check upon a new conection. WifiWatchdogService
-         * fetches the URL and checks to see if {@link #WIFI_WATCHDOG_WALLED_GARDEN_PATTERN}
-         * is not part of the title string to notify the user on the presence of a walled garden.
-         * @hide
-         */
-        public static final String WIFI_WATCHDOG_WALLED_GARDEN_URL =
-                "wifi_watchdog_walled_garden_url";
-
-        /**
-         * The maximum number of times we will retry a connection to an access
-         * point for which we have failed in acquiring an IP address from DHCP.
-         * A value of N means that we will make N+1 connection attempts in all.
-         */
-        public static final String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
-
-        /**
-         * The operational wifi frequency band
-         * Set to one of {@link WifiManager#WIFI_FREQUENCY_BAND_AUTO},
-         * {@link WifiManager#WIFI_FREQUENCY_BAND_5GHZ} or
-         * {@link WifiManager#WIFI_FREQUENCY_BAND_2GHZ}
-         *
-         * @hide
-         */
-        public static final String WIFI_FREQUENCY_BAND = "wifi_frequency_band";
-
-        /**
-         * The Wi-Fi peer-to-peer device name
-         * @hide
-         */
-        public static final String WIFI_P2P_DEVICE_NAME = "wifi_p2p_device_name";
-
-        /**
-         * Maximum amount of time in milliseconds to hold a wakelock while waiting for mobile
-         * data connectivity to be established after a disconnect from Wi-Fi.
-         */
+        @Deprecated
         public static final String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS =
-            "wifi_mobile_data_transition_wakelock_timeout_ms";
+                Global.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS;
 
         /**
-         * Whether network service discovery is enabled.
-         * @hide
-         */
-        public static final String NSD_ON = "nsd_on";
-
-        /**
-         * Whether background data usage is allowed by the user. See
-         * ConnectivityManager for more info.
+         * Whether background data usage is allowed.
+         *
+         * @deprecated As of {@link VERSION_CODES#ICE_CREAM_SANDWICH},
+         *             availability of background data depends on several
+         *             combined factors. When background data is unavailable,
+         *             {@link ConnectivityManager#getActiveNetworkInfo()} will
+         *             now appear disconnected.
          */
         @Deprecated
         public static final String BACKGROUND_DATA = "background_data";
@@ -3341,42 +3687,6 @@
                 = "allowed_geolocation_origins";
 
         /**
-         * Whether mobile data connections are allowed by the user.  See
-         * ConnectivityManager for more info.
-         * @hide
-         */
-        public static final String MOBILE_DATA = "mobile_data";
-
-        /**
-         * The CDMA roaming mode 0 = Home Networks, CDMA default
-         *                       1 = Roaming on Affiliated networks
-         *                       2 = Roaming on any networks
-         * @hide
-         */
-        public static final String CDMA_ROAMING_MODE = "roaming_settings";
-
-        /**
-         * The CDMA subscription mode 0 = RUIM/SIM (default)
-         *                                1 = NV
-         * @hide
-         */
-        public static final String CDMA_SUBSCRIPTION_MODE = "subscription_mode";
-
-        /**
-         * The preferred network mode   7 = Global
-         *                              6 = EvDo only
-         *                              5 = CDMA w/o EvDo
-         *                              4 = CDMA / EvDo auto
-         *                              3 = GSM / WCDMA auto
-         *                              2 = WCDMA only
-         *                              1 = GSM only
-         *                              0 = GSM / WCDMA preferred
-         * @hide
-         */
-        public static final String PREFERRED_NETWORK_MODE =
-                "preferred_network_mode";
-
-        /**
          * The preferred TTY mode     0 = TTy Off, CDMA default
          *                            1 = TTY Full
          *                            2 = TTY HCO
@@ -3386,24 +3696,6 @@
         public static final String PREFERRED_TTY_MODE =
                 "preferred_tty_mode";
 
-
-        /**
-         * CDMA Cell Broadcast SMS
-         *                            0 = CDMA Cell Broadcast SMS disabled
-         *                            1 = CDMA Cell Broadcast SMS enabled
-         * @hide
-         */
-        public static final String CDMA_CELL_BROADCAST_SMS =
-                "cdma_cell_broadcast_sms";
-
-        /**
-         * The cdma subscription 0 = Subscription from RUIM, when available
-         *                       1 = Subscription from NV
-         * @hide
-         */
-        public static final String PREFERRED_CDMA_SUBSCRIPTION =
-                "preferred_cdma_subscription";
-
         /**
          * Whether the enhanced voice privacy mode is enabled.
          * 0 = normal voice privacy
@@ -3421,18 +3713,6 @@
         public static final String TTY_MODE_ENABLED = "tty_mode_enabled";
 
         /**
-         * The number of milliseconds to delay before sending out Connectivyt Change broadcasts
-         * @hide
-         */
-        public static final String CONNECTIVITY_CHANGE_DELAY = "connectivity_change_delay";
-
-        /**
-         * Default value for CONNECTIVITY_CHANGE_DELAY in milliseconds.
-         * @hide
-         */
-        public static final int CONNECTIVITY_CHANGE_DELAY_DEFAULT = 3000;
-
-        /**
          * Controls whether settings backup is enabled.
          * Type: int ( 0 = disabled, 1 = enabled )
          * @hide
@@ -3468,402 +3748,15 @@
         public static final String LAST_SETUP_SHOWN = "last_setup_shown";
 
         /**
-         * How frequently (in seconds) to check the memory status of the
-         * device.
-         * @hide
-         */
-        public static final String MEMCHECK_INTERVAL = "memcheck_interval";
-
-        /**
-         * Max frequency (in seconds) to log memory check stats, in realtime
-         * seconds.  This allows for throttling of logs when the device is
-         * running for large amounts of time.
-         * @hide
-         */
-        public static final String MEMCHECK_LOG_REALTIME_INTERVAL =
-                "memcheck_log_realtime_interval";
-
-        /**
-         * Boolean indicating whether rebooting due to system memory checks
-         * is enabled.
-         * @hide
-         */
-        public static final String MEMCHECK_SYSTEM_ENABLED = "memcheck_system_enabled";
-
-        /**
-         * How many bytes the system process must be below to avoid scheduling
-         * a soft reboot.  This reboot will happen when it is next determined
-         * to be a good time.
-         * @hide
-         */
-        public static final String MEMCHECK_SYSTEM_SOFT_THRESHOLD = "memcheck_system_soft";
-
-        /**
-         * How many bytes the system process must be below to avoid scheduling
-         * a hard reboot.  This reboot will happen immediately.
-         * @hide
-         */
-        public static final String MEMCHECK_SYSTEM_HARD_THRESHOLD = "memcheck_system_hard";
-
-        /**
-         * How many bytes the phone process must be below to avoid scheduling
-         * a soft restart.  This restart will happen when it is next determined
-         * to be a good time.
-         * @hide
-         */
-        public static final String MEMCHECK_PHONE_SOFT_THRESHOLD = "memcheck_phone_soft";
-
-        /**
-         * How many bytes the phone process must be below to avoid scheduling
-         * a hard restart.  This restart will happen immediately.
-         * @hide
-         */
-        public static final String MEMCHECK_PHONE_HARD_THRESHOLD = "memcheck_phone_hard";
-
-        /**
-         * Boolean indicating whether restarting the phone process due to
-         * memory checks is enabled.
-         * @hide
-         */
-        public static final String MEMCHECK_PHONE_ENABLED = "memcheck_phone_enabled";
-
-        /**
-         * First time during the day it is okay to kill processes
-         * or reboot the device due to low memory situations.  This number is
-         * in seconds since midnight.
-         * @hide
-         */
-        public static final String MEMCHECK_EXEC_START_TIME = "memcheck_exec_start_time";
-
-        /**
-         * Last time during the day it is okay to kill processes
-         * or reboot the device due to low memory situations.  This number is
-         * in seconds since midnight.
-         * @hide
-         */
-        public static final String MEMCHECK_EXEC_END_TIME = "memcheck_exec_end_time";
-
-        /**
-         * How long the screen must have been off in order to kill processes
-         * or reboot.  This number is in seconds.  A value of -1 means to
-         * entirely disregard whether the screen is on.
-         * @hide
-         */
-        public static final String MEMCHECK_MIN_SCREEN_OFF = "memcheck_min_screen_off";
-
-        /**
-         * How much time there must be until the next alarm in order to kill processes
-         * or reboot.  This number is in seconds.  Note: this value must be
-         * smaller than {@link #MEMCHECK_RECHECK_INTERVAL} or else it will
-         * always see an alarm scheduled within its time.
-         * @hide
-         */
-        public static final String MEMCHECK_MIN_ALARM = "memcheck_min_alarm";
-
-        /**
-         * How frequently to check whether it is a good time to restart things,
-         * if the device is in a bad state.  This number is in seconds.  Note:
-         * this value must be larger than {@link #MEMCHECK_MIN_ALARM} or else
-         * the alarm to schedule the recheck will always appear within the
-         * minimum "do not execute now" time.
-         * @hide
-         */
-        public static final String MEMCHECK_RECHECK_INTERVAL = "memcheck_recheck_interval";
-
-        /**
-         * How frequently (in DAYS) to reboot the device.  If 0, no reboots
-         * will occur.
-         * @hide
-         */
-        public static final String REBOOT_INTERVAL = "reboot_interval";
-
-        /**
-         * First time during the day it is okay to force a reboot of the
-         * device (if REBOOT_INTERVAL is set).  This number is
-         * in seconds since midnight.
-         * @hide
-         */
-        public static final String REBOOT_START_TIME = "reboot_start_time";
-
-        /**
-         * The window of time (in seconds) after each REBOOT_INTERVAL in which
-         * a reboot can be executed.  If 0, a reboot will always be executed at
-         * exactly the given time.  Otherwise, it will only be executed if
-         * the device is idle within the window.
-         * @hide
-         */
-        public static final String REBOOT_WINDOW = "reboot_window";
-
-        /**
-         * Threshold values for the duration and level of a discharge cycle, under
-         * which we log discharge cycle info.
-         * @hide
-         */
-        public static final String BATTERY_DISCHARGE_DURATION_THRESHOLD =
-                "battery_discharge_duration_threshold";
-        /** @hide */
-        public static final String BATTERY_DISCHARGE_THRESHOLD = "battery_discharge_threshold";
-
-        /**
-         * Flag for allowing ActivityManagerService to send ACTION_APP_ERROR intents
-         * on application crashes and ANRs. If this is disabled, the crash/ANR dialog
-         * will never display the "Report" button.
-         * Type: int ( 0 = disallow, 1 = allow )
-         * @hide
-         */
-        public static final String SEND_ACTION_APP_ERROR = "send_action_app_error";
-
-        /**
-         * Nonzero causes Log.wtf() to crash.
-         * @hide
-         */
-        public static final String WTF_IS_FATAL = "wtf_is_fatal";
-
-        /**
-         * Maximum age of entries kept by {@link com.android.internal.os.IDropBoxManagerService}.
-         * @hide
-         */
-        public static final String DROPBOX_AGE_SECONDS =
-                "dropbox_age_seconds";
-        /**
-         * Maximum number of entry files which {@link com.android.internal.os.IDropBoxManagerService} will keep around.
-         * @hide
-         */
-        public static final String DROPBOX_MAX_FILES =
-                "dropbox_max_files";
-        /**
-         * Maximum amount of disk space used by {@link com.android.internal.os.IDropBoxManagerService} no matter what.
-         * @hide
-         */
-        public static final String DROPBOX_QUOTA_KB =
-                "dropbox_quota_kb";
-        /**
-         * Percent of free disk (excluding reserve) which {@link com.android.internal.os.IDropBoxManagerService} will use.
-         * @hide
-         */
-        public static final String DROPBOX_QUOTA_PERCENT =
-                "dropbox_quota_percent";
-        /**
-         * Percent of total disk which {@link com.android.internal.os.IDropBoxManagerService} will never dip into.
-         * @hide
-         */
-        public static final String DROPBOX_RESERVE_PERCENT =
-                "dropbox_reserve_percent";
-        /**
-         * Prefix for per-tag dropbox disable/enable settings.
-         * @hide
-         */
-        public static final String DROPBOX_TAG_PREFIX =
-                "dropbox:";
-        /**
-         * Lines of logcat to include with system crash/ANR/etc. reports,
-         * as a prefix of the dropbox tag of the report type.
-         * For example, "logcat_for_system_server_anr" controls the lines
-         * of logcat captured with system server ANR reports.  0 to disable.
-         * @hide
-         */
-        public static final String ERROR_LOGCAT_PREFIX =
-                "logcat_for_";
-
-
-        /**
-         * Screen timeout in milliseconds corresponding to the
-         * PowerManager's POKE_LOCK_SHORT_TIMEOUT flag (i.e. the fastest
-         * possible screen timeout behavior.)
-         * @hide
-         */
-        public static final String SHORT_KEYLIGHT_DELAY_MS =
-                "short_keylight_delay_ms";
-
-        /**
-         * The interval in minutes after which the amount of free storage left on the
-         * device is logged to the event log
-         * @hide
-         */
-        public static final String SYS_FREE_STORAGE_LOG_INTERVAL =
-                "sys_free_storage_log_interval";
-
-        /**
-         * Threshold for the amount of change in disk free space required to report the amount of
-         * free space. Used to prevent spamming the logs when the disk free space isn't changing
-         * frequently.
-         * @hide
-         */
-        public static final String DISK_FREE_CHANGE_REPORTING_THRESHOLD =
-                "disk_free_change_reporting_threshold";
-
-
-        /**
-         * Minimum percentage of free storage on the device that is used to determine if
-         * the device is running low on storage.  The default is 10.
-         * <p>Say this value is set to 10, the device is considered running low on storage
-         * if 90% or more of the device storage is filled up.
-         * @hide
-         */
-        public static final String SYS_STORAGE_THRESHOLD_PERCENTAGE =
-                "sys_storage_threshold_percentage";
-
-        /**
-         * Maximum byte size of the low storage threshold.  This is to ensure
-         * that {@link #SYS_STORAGE_THRESHOLD_PERCENTAGE} does not result in
-         * an overly large threshold for large storage devices.  Currently this
-         * must be less than 2GB.  This default is 500MB.
-         * @hide
-         */
-        public static final String SYS_STORAGE_THRESHOLD_MAX_BYTES =
-                "sys_storage_threshold_max_bytes";
-
-        /**
-         * Minimum bytes of free storage on the device before the data
-         * partition is considered full. By default, 1 MB is reserved
-         * to avoid system-wide SQLite disk full exceptions.
-         * @hide
-         */
-        public static final String SYS_STORAGE_FULL_THRESHOLD_BYTES =
-                "sys_storage_full_threshold_bytes";
-
-        /**
          * The interval in milliseconds after which Wi-Fi is considered idle.
          * When idle, it is possible for the device to be switched from Wi-Fi to
          * the mobile data network.
          * @hide
+         * @deprecated Use {@link android.provider.Settings.Global#WIFI_IDLE_MS}
+         * instead.
          */
-        public static final String WIFI_IDLE_MS = "wifi_idle_ms";
-
-        /**
-         * The interval in milliseconds to issue wake up scans when wifi needs
-         * to connect. This is necessary to connect to an access point when
-         * device is on the move and the screen is off.
-         * @hide
-         */
-        public static final String WIFI_FRAMEWORK_SCAN_INTERVAL_MS =
-                "wifi_framework_scan_interval_ms";
-
-        /**
-         * The interval in milliseconds to scan as used by the wifi supplicant
-         * @hide
-         */
-        public static final String WIFI_SUPPLICANT_SCAN_INTERVAL_MS =
-                "wifi_supplicant_scan_interval_ms";
-
-        /**
-         * The interval in milliseconds at which to check packet counts on the
-         * mobile data interface when screen is on, to detect possible data
-         * connection problems.
-         * @hide
-         */
-        public static final String PDP_WATCHDOG_POLL_INTERVAL_MS =
-                "pdp_watchdog_poll_interval_ms";
-
-        /**
-         * The interval in milliseconds at which to check packet counts on the
-         * mobile data interface when screen is off, to detect possible data
-         * connection problems.
-         * @hide
-         */
-        public static final String PDP_WATCHDOG_LONG_POLL_INTERVAL_MS =
-                "pdp_watchdog_long_poll_interval_ms";
-
-        /**
-         * The interval in milliseconds at which to check packet counts on the
-         * mobile data interface after {@link #PDP_WATCHDOG_TRIGGER_PACKET_COUNT}
-         * outgoing packets has been reached without incoming packets.
-         * @hide
-         */
-        public static final String PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS =
-                "pdp_watchdog_error_poll_interval_ms";
-
-        /**
-         * The number of outgoing packets sent without seeing an incoming packet
-         * that triggers a countdown (of {@link #PDP_WATCHDOG_ERROR_POLL_COUNT}
-         * device is logged to the event log
-         * @hide
-         */
-        public static final String PDP_WATCHDOG_TRIGGER_PACKET_COUNT =
-                "pdp_watchdog_trigger_packet_count";
-
-        /**
-         * The number of polls to perform (at {@link #PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS})
-         * after hitting {@link #PDP_WATCHDOG_TRIGGER_PACKET_COUNT} before
-         * attempting data connection recovery.
-         * @hide
-         */
-        public static final String PDP_WATCHDOG_ERROR_POLL_COUNT =
-                "pdp_watchdog_error_poll_count";
-
-        /**
-         * The number of failed PDP reset attempts before moving to something more
-         * drastic: re-registering to the network.
-         * @hide
-         */
-        public static final String PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT =
-                "pdp_watchdog_max_pdp_reset_fail_count";
-
-        /**
-         * The number of milliseconds to delay when checking for data stalls during
-         * non-aggressive detection. (screen is turned off.)
-         * @hide
-         */
-        public static final String DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS =
-                "data_stall_alarm_non_aggressive_delay_in_ms";
-
-        /**
-         * The number of milliseconds to delay when checking for data stalls during
-         * aggressive detection. (screen on or suspected data stall)
-         * @hide
-         */
-        public static final String DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS =
-                "data_stall_alarm_aggressive_delay_in_ms";
-
-        /**
-         * The interval in milliseconds at which to check gprs registration
-         * after the first registration mismatch of gprs and voice service,
-         * to detect possible data network registration problems.
-         *
-         * @hide
-         */
-        public static final String GPRS_REGISTER_CHECK_PERIOD_MS =
-                "gprs_register_check_period_ms";
-
-        /**
-         * The length of time in milli-seconds that automatic small adjustments to
-         * SystemClock are ignored if NITZ_UPDATE_DIFF is not exceeded.
-         * @hide
-         */
-        public static final String NITZ_UPDATE_SPACING = "nitz_update_spacing";
-
-        /**
-         * If the NITZ_UPDATE_DIFF time is exceeded then an automatic adjustment
-         * to SystemClock will be allowed even if NITZ_UPDATE_SPACING has not been
-         * exceeded.
-         * @hide
-         */
-        public static final String NITZ_UPDATE_DIFF = "nitz_update_diff";
-
-        /**
-         * The maximum reconnect delay for short network outages or when the network is suspended
-         * due to phone use.
-         * @hide
-         */
-        public static final String SYNC_MAX_RETRY_DELAY_IN_SECONDS =
-                "sync_max_retry_delay_in_seconds";
-
-        /**
-         * The interval in milliseconds at which to check the number of SMS sent
-         * out without asking for use permit, to limit the un-authorized SMS
-         * usage.
-         * @hide
-         */
-        public static final String SMS_OUTGOING_CHECK_INTERVAL_MS =
-                "sms_outgoing_check_interval_ms";
-
-        /**
-         * The number of outgoing SMS sent without asking for user permit
-         * (of {@link #SMS_OUTGOING_CHECK_INTERVAL_MS}
-         * @hide
-         */
-        public static final String SMS_OUTGOING_CHECK_MAX_COUNT =
-                "sms_outgoing_check_max_count";
+        @Deprecated
+        public static final String WIFI_IDLE_MS = Global.WIFI_IDLE_MS;
 
         /**
          * The global search provider chosen by the user (if multiple global
@@ -4085,215 +3978,39 @@
         public static final String UI_NIGHT_MODE = "ui_night_mode";
 
         /**
-         * Let user pick default install location.
-         * @hide
-         */
-        public static final String SET_INSTALL_LOCATION = "set_install_location";
-
-        /**
-         * Default install location value.
-         * 0 = auto, let system decide
-         * 1 = internal
-         * 2 = sdcard
-         * @hide
-         */
-        public static final String DEFAULT_INSTALL_LOCATION = "default_install_location";
-
-        /**
-         * The bandwidth throttle polling freqency in seconds
-         * @hide
-         */
-        public static final String THROTTLE_POLLING_SEC = "throttle_polling_sec";
-
-        /**
-         * The bandwidth throttle threshold (long)
-         * @hide
-         */
-        public static final String THROTTLE_THRESHOLD_BYTES = "throttle_threshold_bytes";
-
-        /**
-         * The bandwidth throttle value (kbps)
-         * @hide
-         */
-        public static final String THROTTLE_VALUE_KBITSPS = "throttle_value_kbitsps";
-
-        /**
-         * The bandwidth throttle reset calendar day (1-28)
-         * @hide
-         */
-        public static final String THROTTLE_RESET_DAY = "throttle_reset_day";
-
-        /**
-         * The throttling notifications we should send
-         * @hide
-         */
-        public static final String THROTTLE_NOTIFICATION_TYPE = "throttle_notification_type";
-
-        /**
-         * Help URI for data throttling policy
-         * @hide
-         */
-        public static final String THROTTLE_HELP_URI = "throttle_help_uri";
-
-        /**
-         * The length of time in Sec that we allow our notion of NTP time
-         * to be cached before we refresh it
-         * @hide
-         */
-        public static final String THROTTLE_MAX_NTP_CACHE_AGE_SEC =
-                "throttle_max_ntp_cache_age_sec";
-
-        /**
-         * The maximum size, in bytes, of a download that the download manager will transfer over
-         * a non-wifi connection.
-         * @hide
-         */
-        public static final String DOWNLOAD_MAX_BYTES_OVER_MOBILE =
-                "download_manager_max_bytes_over_mobile";
-
-        /**
-         * The recommended maximum size, in bytes, of a download that the download manager should
-         * transfer over a non-wifi connection. Over this size, the use will be warned, but will
-         * have the option to start the download over the mobile connection anyway.
-         * @hide
-         */
-        public static final String DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE =
-                "download_manager_recommended_max_bytes_over_mobile";
-
-        /**
-         * ms during which to consume extra events related to Inet connection condition
-         * after a transtion to fully-connected
-         * @hide
-         */
-        public static final String INET_CONDITION_DEBOUNCE_UP_DELAY =
-                "inet_condition_debounce_up_delay";
-
-        /**
-         * ms during which to consume extra events related to Inet connection condtion
-         * after a transtion to partly-connected
-         * @hide
-         */
-        public static final String INET_CONDITION_DEBOUNCE_DOWN_DELAY =
-                "inet_condition_debounce_down_delay";
-
-        /**
-         * URL to open browser on to allow user to manage a prepay account
-         * @hide
-         */
-        public static final String SETUP_PREPAID_DATA_SERVICE_URL =
-                "setup_prepaid_data_service_url";
-
-        /**
-         * URL to attempt a GET on to see if this is a prepay device
-         * @hide
-         */
-        public static final String SETUP_PREPAID_DETECTION_TARGET_URL =
-                "setup_prepaid_detection_target_url";
-
-        /**
-         * Host to check for a redirect to after an attempt to GET
-         * SETUP_PREPAID_DETECTION_TARGET_URL. (If we redirected there,
-         * this is a prepaid device with zero balance.)
-         * @hide
-         */
-        public static final String SETUP_PREPAID_DETECTION_REDIR_HOST =
-                "setup_prepaid_detection_redir_host";
-
-        /**
-         * Whether the screensaver is enabled.
+         * Whether screensavers are enabled.
          * @hide
          */
         public static final String SCREENSAVER_ENABLED = "screensaver_enabled";
 
         /**
-         * The user's chosen screensaver component.
+         * The user's chosen screensaver components.
          *
-         * This component will be launched by the PhoneWindowManager after a timeout when not on
+         * These will be launched by the PhoneWindowManager after a timeout when not on
          * battery, or upon dock insertion (if SCREENSAVER_ACTIVATE_ON_DOCK is set to 1).
          * @hide
          */
-        public static final String SCREENSAVER_COMPONENT = "screensaver_component";
+        public static final String SCREENSAVER_COMPONENTS = "screensaver_components";
 
         /**
-         * Whether the screensaver should be automatically launched when the device is inserted
-         * into a (desk) dock.
+         * If screensavers are enabled, whether the screensaver should be automatically launched
+         * when the device is inserted into a (desk) dock.
          * @hide
          */
         public static final String SCREENSAVER_ACTIVATE_ON_DOCK = "screensaver_activate_on_dock";
 
-        /** {@hide} */
-        public static final String NETSTATS_ENABLED = "netstats_enabled";
-        /** {@hide} */
-        public static final String NETSTATS_POLL_INTERVAL = "netstats_poll_interval";
-        /** {@hide} */
-        public static final String NETSTATS_TIME_CACHE_MAX_AGE = "netstats_time_cache_max_age";
-        /** {@hide} */
-        public static final String NETSTATS_GLOBAL_ALERT_BYTES = "netstats_global_alert_bytes";
-        /** {@hide} */
-        public static final String NETSTATS_SAMPLE_ENABLED = "netstats_sample_enabled";
-        /** {@hide} */
-        public static final String NETSTATS_REPORT_XT_OVER_DEV = "netstats_report_xt_over_dev";
-
-        /** {@hide} */
-        public static final String NETSTATS_DEV_BUCKET_DURATION = "netstats_dev_bucket_duration";
-        /** {@hide} */
-        public static final String NETSTATS_DEV_PERSIST_BYTES = "netstats_dev_persist_bytes";
-        /** {@hide} */
-        public static final String NETSTATS_DEV_ROTATE_AGE = "netstats_dev_rotate_age";
-        /** {@hide} */
-        public static final String NETSTATS_DEV_DELETE_AGE = "netstats_dev_delete_age";
-
-        /** {@hide} */
-        public static final String NETSTATS_UID_BUCKET_DURATION = "netstats_uid_bucket_duration";
-        /** {@hide} */
-        public static final String NETSTATS_UID_PERSIST_BYTES = "netstats_uid_persist_bytes";
-        /** {@hide} */
-        public static final String NETSTATS_UID_ROTATE_AGE = "netstats_uid_rotate_age";
-        /** {@hide} */
-        public static final String NETSTATS_UID_DELETE_AGE = "netstats_uid_delete_age";
-
-        /** {@hide} */
-        public static final String NETSTATS_UID_TAG_BUCKET_DURATION = "netstats_uid_tag_bucket_duration";
-        /** {@hide} */
-        public static final String NETSTATS_UID_TAG_PERSIST_BYTES = "netstats_uid_tag_persist_bytes";
-        /** {@hide} */
-        public static final String NETSTATS_UID_TAG_ROTATE_AGE = "netstats_uid_tag_rotate_age";
-        /** {@hide} */
-        public static final String NETSTATS_UID_TAG_DELETE_AGE = "netstats_uid_tag_delete_age";
-
-        /** Preferred NTP server. {@hide} */
-        public static final String NTP_SERVER = "ntp_server";
-        /** Timeout in milliseconds to wait for NTP server. {@hide} */
-        public static final String NTP_TIMEOUT = "ntp_timeout";
-
-        /** Autofill server address (Used in WebView/browser). {@hide} */
-        public static final String WEB_AUTOFILL_QUERY_URL =
-            "web_autofill_query_url";
-
-        /** Whether package verification is enabled. {@hide} */
-        public static final String PACKAGE_VERIFIER_ENABLE = "verifier_enable";
-
-        /** Timeout for package verification. {@hide} */
-        public static final String PACKAGE_VERIFIER_TIMEOUT = "verifier_timeout";
-
-        /** {@hide} */
-        public static final String
-                READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT = "read_external_storage_enforced_default";
-
         /**
-         * Duration in milliseconds before pre-authorized URIs for the contacts
-         * provider should expire.
+         * If screensavers are enabled, whether the screensaver should be automatically launched
+         * when the screen times out when not on battery.
          * @hide
          */
-        public static final String CONTACTS_PREAUTH_URI_EXPIRATION =
-                "contacts_preauth_uri_expiration";
+        public static final String SCREENSAVER_ACTIVATE_ON_SLEEP = "screensaver_activate_on_sleep";
 
         /**
-         * Prefix for SMS short code regex patterns (country code is appended).
-         * @see com.android.internal.telephony.SmsUsageMonitor
+         * If screensavers are enabled, the default screensaver component.
          * @hide
          */
-        public static final String SMS_SHORT_CODES_PREFIX = "sms_short_codes_";
+        public static final String SCREENSAVER_DEFAULT_COMPONENT = "screensaver_default_component";
 
         /**
          * This are the settings to be backed up.
@@ -4305,11 +4022,14 @@
          * @hide
          */
         public static final String[] SETTINGS_TO_BACKUP = {
-            ADB_ENABLED,
+            BUGREPORT_IN_POWER_MENU,
             ALLOW_MOCK_LOCATION,
             PARENTAL_CONTROL_ENABLED,
             PARENTAL_CONTROL_REDIRECT_URL,
-            USB_MASS_STORAGE_ENABLED,
+            USB_MASS_STORAGE_ENABLED,                           // moved to global
+            ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
+            ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+            ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE,
             ACCESSIBILITY_SCRIPT_INJECTION,
             BACKUP_AUTO_RESTORE,
             ENABLED_ACCESSIBILITY_SERVICES,
@@ -4325,9 +4045,9 @@
             TTS_DEFAULT_COUNTRY,
             TTS_ENABLED_PLUGINS,
             TTS_DEFAULT_LOCALE,
-            WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
-            WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
-            WIFI_NUM_OPEN_NETWORKS_KEPT,
+            WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,            // moved to global
+            WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,               // moved to global
+            WIFI_NUM_OPEN_NETWORKS_KEPT,                        // moved to global
             MOUNT_PLAY_NOTIFICATION_SND,
             MOUNT_UMS_AUTOSTART,
             MOUNT_UMS_PROMPT,
@@ -4344,7 +4064,20 @@
          * @return true if the provider is enabled
          */
         public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) {
-            String allowedProviders = Settings.Secure.getString(cr, LOCATION_PROVIDERS_ALLOWED);
+            return isLocationProviderEnabledForUser(cr, provider, UserHandle.myUserId());
+        }
+
+        /**
+         * Helper method for determining if a location provider is enabled.
+         * @param cr the content resolver to use
+         * @param provider the location provider to query
+         * @param userId the userId to query
+         * @return true if the provider is enabled
+         * @hide
+         */
+        public static final boolean isLocationProviderEnabledForUser(ContentResolver cr, String provider, int userId) {
+            String allowedProviders = Settings.Secure.getStringForUser(cr,
+                    LOCATION_PROVIDERS_ALLOWED, userId);
             return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
         }
 
@@ -4356,6 +4089,19 @@
          */
         public static final void setLocationProviderEnabled(ContentResolver cr,
                 String provider, boolean enabled) {
+            setLocationProviderEnabledForUser(cr, provider, enabled, UserHandle.myUserId());
+        }
+
+        /**
+         * Thread-safe method for enabling or disabling a single location provider.
+         * @param cr the content resolver to use
+         * @param provider the location provider to enable or disable
+         * @param enabled true if the provider should be enabled
+         * @param userId the userId for which to enable/disable providers
+         * @hide
+         */
+        public static final void setLocationProviderEnabledForUser(ContentResolver cr,
+                String provider, boolean enabled, int userId) {
             // to ensure thread safety, we write the provider name with a '+' or '-'
             // and let the SettingsProvider handle it rather than reading and modifying
             // the list of enabled providers.
@@ -4364,7 +4110,1505 @@
             } else {
                 provider = "-" + provider;
             }
-            putString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider);
+            putStringForUser(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider,
+                    userId);
+        }
+    }
+
+    /**
+     * Global system settings, containing preferences that always apply identically
+     * to all defined users.  Applications can read these but are not allowed to write;
+     * like the "Secure" settings, these are for preferences that the user must
+     * explicitly modify through the system UI or specialized APIs for those values.
+     */
+    public static final class Global extends NameValueTable {
+        public static final String SYS_PROP_SETTING_VERSION = "sys.settings_global_version";
+
+        /**
+         * The content:// style URL for global secure settings items.  Not public.
+         */
+        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/global");
+
+        /**
+         * Setting whether the global gesture for enabling accessibility is enabled.
+         * If this gesture is enabled the user will be able to perfrom it to enable
+         * the accessibility state without visiting the settings app.
+         * @hide
+         */
+        public static final String ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED =
+                "enable_accessibility_global_gesture_enabled";
+
+        /**
+         * Whether Airplane Mode is on.
+         */
+        public static final String AIRPLANE_MODE_ON = "airplane_mode_on";
+
+        /**
+         * Constant for use in AIRPLANE_MODE_RADIOS to specify Bluetooth radio.
+         */
+        public static final String RADIO_BLUETOOTH = "bluetooth";
+
+        /**
+         * Constant for use in AIRPLANE_MODE_RADIOS to specify Wi-Fi radio.
+         */
+        public static final String RADIO_WIFI = "wifi";
+
+        /**
+         * {@hide}
+         */
+        public static final String RADIO_WIMAX = "wimax";
+        /**
+         * Constant for use in AIRPLANE_MODE_RADIOS to specify Cellular radio.
+         */
+        public static final String RADIO_CELL = "cell";
+
+        /**
+         * Constant for use in AIRPLANE_MODE_RADIOS to specify NFC radio.
+         */
+        public static final String RADIO_NFC = "nfc";
+
+        /**
+         * A comma separated list of radios that need to be disabled when airplane mode
+         * is on. This overrides WIFI_ON and BLUETOOTH_ON, if Wi-Fi and bluetooth are
+         * included in the comma separated list.
+         */
+        public static final String AIRPLANE_MODE_RADIOS = "airplane_mode_radios";
+
+        /**
+         * A comma separated list of radios that should to be disabled when airplane mode
+         * is on, but can be manually reenabled by the user.  For example, if RADIO_WIFI is
+         * added to both AIRPLANE_MODE_RADIOS and AIRPLANE_MODE_TOGGLEABLE_RADIOS, then Wifi
+         * will be turned off when entering airplane mode, but the user will be able to reenable
+         * Wifi in the Settings app.
+         *
+         * {@hide}
+         */
+        public static final String AIRPLANE_MODE_TOGGLEABLE_RADIOS = "airplane_mode_toggleable_radios";
+
+        /**
+         * The policy for deciding when Wi-Fi should go to sleep (which will in
+         * turn switch to using the mobile data as an Internet connection).
+         * <p>
+         * Set to one of {@link #WIFI_SLEEP_POLICY_DEFAULT},
+         * {@link #WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED}, or
+         * {@link #WIFI_SLEEP_POLICY_NEVER}.
+         */
+        public static final String WIFI_SLEEP_POLICY = "wifi_sleep_policy";
+
+        /**
+         * Value for {@link #WIFI_SLEEP_POLICY} to use the default Wi-Fi sleep
+         * policy, which is to sleep shortly after the turning off
+         * according to the {@link #STAY_ON_WHILE_PLUGGED_IN} setting.
+         */
+        public static final int WIFI_SLEEP_POLICY_DEFAULT = 0;
+
+        /**
+         * Value for {@link #WIFI_SLEEP_POLICY} to use the default policy when
+         * the device is on battery, and never go to sleep when the device is
+         * plugged in.
+         */
+        public static final int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED = 1;
+
+        /**
+         * Value for {@link #WIFI_SLEEP_POLICY} to never go to sleep.
+         */
+        public static final int WIFI_SLEEP_POLICY_NEVER = 2;
+
+        /**
+         * Value to specify if the user prefers the date, time and time zone
+         * to be automatically fetched from the network (NITZ). 1=yes, 0=no
+         */
+        public static final String AUTO_TIME = "auto_time";
+
+        /**
+         * Value to specify if the user prefers the time zone
+         * to be automatically fetched from the network (NITZ). 1=yes, 0=no
+         */
+        public static final String AUTO_TIME_ZONE = "auto_time_zone";
+
+        /**
+         * URI for the car dock "in" event sound.
+         * @hide
+         */
+        public static final String CAR_DOCK_SOUND = "car_dock_sound";
+
+        /**
+         * URI for the car dock "out" event sound.
+         * @hide
+         */
+        public static final String CAR_UNDOCK_SOUND = "car_undock_sound";
+
+        /**
+         * URI for the desk dock "in" event sound.
+         * @hide
+         */
+        public static final String DESK_DOCK_SOUND = "desk_dock_sound";
+
+        /**
+         * URI for the desk dock "out" event sound.
+         * @hide
+         */
+        public static final String DESK_UNDOCK_SOUND = "desk_undock_sound";
+
+        /**
+         * Whether to play a sound for dock events.
+         * @hide
+         */
+        public static final String DOCK_SOUNDS_ENABLED = "dock_sounds_enabled";
+
+        /**
+         * URI for the "device locked" (keyguard shown) sound.
+         * @hide
+         */
+        public static final String LOCK_SOUND = "lock_sound";
+
+        /**
+         * URI for the "device unlocked" sound.
+         * @hide
+         */
+        public static final String UNLOCK_SOUND = "unlock_sound";
+
+        /**
+         * URI for the low battery sound file.
+         * @hide
+         */
+        public static final String LOW_BATTERY_SOUND = "low_battery_sound";
+
+        /**
+         * Whether to play a sound for low-battery alerts.
+         * @hide
+         */
+        public static final String POWER_SOUNDS_ENABLED = "power_sounds_enabled";
+
+        /**
+         * Whether we keep the device on while the device is plugged in.
+         * Supported values are:
+         * <ul>
+         * <li>{@code 0} to never stay on while plugged in</li>
+         * <li>{@link BatteryManager#BATTERY_PLUGGED_AC} to stay on for AC charger</li>
+         * <li>{@link BatteryManager#BATTERY_PLUGGED_USB} to stay on for USB charger</li>
+         * <li>{@link BatteryManager#BATTERY_PLUGGED_WIRELESS} to stay on for wireless charger</li>
+         * </ul>
+         * These values can be OR-ed together.
+         */
+        public static final String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
+
+        /**
+         * Whether ADB is enabled.
+         */
+        public static final String ADB_ENABLED = "adb_enabled";
+
+        /**
+         * Whether assisted GPS should be enabled or not.
+         * @hide
+         */
+        public static final String ASSISTED_GPS_ENABLED = "assisted_gps_enabled";
+
+        /**
+         * Whether bluetooth is enabled/disabled
+         * 0=disabled. 1=enabled.
+         */
+        public static final String BLUETOOTH_ON = "bluetooth_on";
+
+        /**
+         * CDMA Cell Broadcast SMS
+         *                            0 = CDMA Cell Broadcast SMS disabled
+         *                            1 = CDMA Cell Broadcast SMS enabled
+         * @hide
+         */
+        public static final String CDMA_CELL_BROADCAST_SMS =
+                "cdma_cell_broadcast_sms";
+
+        /**
+         * The CDMA roaming mode 0 = Home Networks, CDMA default
+         *                       1 = Roaming on Affiliated networks
+         *                       2 = Roaming on any networks
+         * @hide
+         */
+        public static final String CDMA_ROAMING_MODE = "roaming_settings";
+
+        /**
+         * The CDMA subscription mode 0 = RUIM/SIM (default)
+         *                                1 = NV
+         * @hide
+         */
+        public static final String CDMA_SUBSCRIPTION_MODE = "subscription_mode";
+
+        /** Inactivity timeout to track mobile data activity.
+        *
+        * If set to a positive integer, it indicates the inactivity timeout value in seconds to
+        * infer the data activity of mobile network. After a period of no activity on mobile
+        * networks with length specified by the timeout, an {@code ACTION_DATA_ACTIVITY_CHANGE}
+        * intent is fired to indicate a transition of network status from "active" to "idle". Any
+        * subsequent activity on mobile networks triggers the firing of {@code
+        * ACTION_DATA_ACTIVITY_CHANGE} intent indicating transition from "idle" to "active".
+        *
+        * Network activity refers to transmitting or receiving data on the network interfaces.
+        *
+        * Tracking is disabled if set to zero or negative value.
+        *
+        * @hide
+        */
+       public static final String DATA_ACTIVITY_TIMEOUT_MOBILE = "data_activity_timeout_mobile";
+
+       /** Timeout to tracking Wifi data activity. Same as {@code DATA_ACTIVITY_TIMEOUT_MOBILE}
+        * but for Wifi network.
+        * @hide
+        */
+       public static final String DATA_ACTIVITY_TIMEOUT_WIFI = "data_activity_timeout_wifi";
+
+       /**
+        * Whether or not data roaming is enabled. (0 = false, 1 = true)
+        */
+       public static final String DATA_ROAMING = "data_roaming";
+
+       /**
+        * Whether user has enabled development settings.
+        */
+       public static final String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
+
+       /**
+        * Whether the device has been provisioned (0 = false, 1 = true)
+        */
+       public static final String DEVICE_PROVISIONED = "device_provisioned";
+
+       /**
+        * The saved value for WindowManagerService.setForcedDisplayDensity().
+        * One integer in dpi.  If unset, then use the real display density.
+        * @hide
+        */
+       public static final String DISPLAY_DENSITY_FORCED = "display_density_forced";
+
+       /**
+        * The saved value for WindowManagerService.setForcedDisplaySize().
+        * Two integers separated by a comma.  If unset, then use the real display size.
+        * @hide
+        */
+       public static final String DISPLAY_SIZE_FORCED = "display_size_forced";
+
+       /**
+        * The maximum size, in bytes, of a download that the download manager will transfer over
+        * a non-wifi connection.
+        * @hide
+        */
+       public static final String DOWNLOAD_MAX_BYTES_OVER_MOBILE =
+               "download_manager_max_bytes_over_mobile";
+
+       /**
+        * The recommended maximum size, in bytes, of a download that the download manager should
+        * transfer over a non-wifi connection. Over this size, the use will be warned, but will
+        * have the option to start the download over the mobile connection anyway.
+        * @hide
+        */
+       public static final String DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE =
+               "download_manager_recommended_max_bytes_over_mobile";
+
+       /**
+        * Whether the package installer should allow installation of apps downloaded from
+        * sources other than Google Play.
+        *
+        * 1 = allow installing from other sources
+        * 0 = only allow installing from Google Play
+        */
+       public static final String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+
+       /**
+        * Whether mobile data connections are allowed by the user.  See
+        * ConnectivityManager for more info.
+        * @hide
+        */
+       public static final String MOBILE_DATA = "mobile_data";
+
+       /** {@hide} */
+       public static final String NETSTATS_ENABLED = "netstats_enabled";
+       /** {@hide} */
+       public static final String NETSTATS_POLL_INTERVAL = "netstats_poll_interval";
+       /** {@hide} */
+       public static final String NETSTATS_TIME_CACHE_MAX_AGE = "netstats_time_cache_max_age";
+       /** {@hide} */
+       public static final String NETSTATS_GLOBAL_ALERT_BYTES = "netstats_global_alert_bytes";
+       /** {@hide} */
+       public static final String NETSTATS_SAMPLE_ENABLED = "netstats_sample_enabled";
+       /** {@hide} */
+       public static final String NETSTATS_REPORT_XT_OVER_DEV = "netstats_report_xt_over_dev";
+
+       /** {@hide} */
+       public static final String NETSTATS_DEV_BUCKET_DURATION = "netstats_dev_bucket_duration";
+       /** {@hide} */
+       public static final String NETSTATS_DEV_PERSIST_BYTES = "netstats_dev_persist_bytes";
+       /** {@hide} */
+       public static final String NETSTATS_DEV_ROTATE_AGE = "netstats_dev_rotate_age";
+       /** {@hide} */
+       public static final String NETSTATS_DEV_DELETE_AGE = "netstats_dev_delete_age";
+
+       /** {@hide} */
+       public static final String NETSTATS_UID_BUCKET_DURATION = "netstats_uid_bucket_duration";
+       /** {@hide} */
+       public static final String NETSTATS_UID_PERSIST_BYTES = "netstats_uid_persist_bytes";
+       /** {@hide} */
+       public static final String NETSTATS_UID_ROTATE_AGE = "netstats_uid_rotate_age";
+       /** {@hide} */
+       public static final String NETSTATS_UID_DELETE_AGE = "netstats_uid_delete_age";
+
+       /** {@hide} */
+       public static final String NETSTATS_UID_TAG_BUCKET_DURATION = "netstats_uid_tag_bucket_duration";
+       /** {@hide} */
+       public static final String NETSTATS_UID_TAG_PERSIST_BYTES = "netstats_uid_tag_persist_bytes";
+       /** {@hide} */
+       public static final String NETSTATS_UID_TAG_ROTATE_AGE = "netstats_uid_tag_rotate_age";
+       /** {@hide} */
+       public static final String NETSTATS_UID_TAG_DELETE_AGE = "netstats_uid_tag_delete_age";
+
+       /**
+        * User preference for which network(s) should be used. Only the
+        * connectivity service should touch this.
+        */
+       public static final String NETWORK_PREFERENCE = "network_preference";
+
+       /**
+        * If the NITZ_UPDATE_DIFF time is exceeded then an automatic adjustment
+        * to SystemClock will be allowed even if NITZ_UPDATE_SPACING has not been
+        * exceeded.
+        * @hide
+        */
+       public static final String NITZ_UPDATE_DIFF = "nitz_update_diff";
+
+       /**
+        * The length of time in milli-seconds that automatic small adjustments to
+        * SystemClock are ignored if NITZ_UPDATE_DIFF is not exceeded.
+        * @hide
+        */
+       public static final String NITZ_UPDATE_SPACING = "nitz_update_spacing";
+
+       /** Preferred NTP server. {@hide} */
+       public static final String NTP_SERVER = "ntp_server";
+       /** Timeout in milliseconds to wait for NTP server. {@hide} */
+       public static final String NTP_TIMEOUT = "ntp_timeout";
+
+       /**
+        * Whether the package manager should send package verification broadcasts for verifiers to
+        * review apps prior to installation.
+        * 1 = request apps to be verified prior to installation, if a verifier exists.
+        * 0 = do not verify apps before installation
+        * @hide
+        */
+       public static final String PACKAGE_VERIFIER_ENABLE = "package_verifier_enable";
+
+       /** Timeout for package verification.
+        * @hide */
+       public static final String PACKAGE_VERIFIER_TIMEOUT = "verifier_timeout";
+
+       /** Default response code for package verification.
+        * @hide */
+       public static final String PACKAGE_VERIFIER_DEFAULT_RESPONSE = "verifier_default_response";
+
+       /**
+        * Show package verification setting in the Settings app.
+        * 1 = show (default)
+        * 0 = hide
+        * @hide
+        */
+       public static final String PACKAGE_VERIFIER_SETTING_VISIBLE = "verifier_setting_visible";
+
+       /**
+        * Run package verificaiton on apps installed through ADB/ADT/USB
+        * 1 = perform package verification on ADB installs (default)
+        * 0 = bypass package verification on ADB installs
+        * @hide
+        */
+       public static final String PACKAGE_VERIFIER_INCLUDE_ADB = "verifier_verify_adb_installs";
+
+       /**
+        * The interval in milliseconds at which to check packet counts on the
+        * mobile data interface when screen is on, to detect possible data
+        * connection problems.
+        * @hide
+        */
+       public static final String PDP_WATCHDOG_POLL_INTERVAL_MS =
+               "pdp_watchdog_poll_interval_ms";
+
+       /**
+        * The interval in milliseconds at which to check packet counts on the
+        * mobile data interface when screen is off, to detect possible data
+        * connection problems.
+        * @hide
+        */
+       public static final String PDP_WATCHDOG_LONG_POLL_INTERVAL_MS =
+               "pdp_watchdog_long_poll_interval_ms";
+
+       /**
+        * The interval in milliseconds at which to check packet counts on the
+        * mobile data interface after {@link #PDP_WATCHDOG_TRIGGER_PACKET_COUNT}
+        * outgoing packets has been reached without incoming packets.
+        * @hide
+        */
+       public static final String PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS =
+               "pdp_watchdog_error_poll_interval_ms";
+
+       /**
+        * The number of outgoing packets sent without seeing an incoming packet
+        * that triggers a countdown (of {@link #PDP_WATCHDOG_ERROR_POLL_COUNT}
+        * device is logged to the event log
+        * @hide
+        */
+       public static final String PDP_WATCHDOG_TRIGGER_PACKET_COUNT =
+               "pdp_watchdog_trigger_packet_count";
+
+       /**
+        * The number of polls to perform (at {@link #PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS})
+        * after hitting {@link #PDP_WATCHDOG_TRIGGER_PACKET_COUNT} before
+        * attempting data connection recovery.
+        * @hide
+        */
+       public static final String PDP_WATCHDOG_ERROR_POLL_COUNT =
+               "pdp_watchdog_error_poll_count";
+
+       /**
+        * The number of failed PDP reset attempts before moving to something more
+        * drastic: re-registering to the network.
+        * @hide
+        */
+       public static final String PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT =
+               "pdp_watchdog_max_pdp_reset_fail_count";
+
+       /**
+        * A positive value indicates how often the SamplingProfiler
+        * should take snapshots. Zero value means SamplingProfiler
+        * is disabled.
+        *
+        * @hide
+        */
+       public static final String SAMPLING_PROFILER_MS = "sampling_profiler_ms";
+
+       /**
+        * URL to open browser on to allow user to manage a prepay account
+        * @hide
+        */
+       public static final String SETUP_PREPAID_DATA_SERVICE_URL =
+               "setup_prepaid_data_service_url";
+
+       /**
+        * URL to attempt a GET on to see if this is a prepay device
+        * @hide
+        */
+       public static final String SETUP_PREPAID_DETECTION_TARGET_URL =
+               "setup_prepaid_detection_target_url";
+
+       /**
+        * Host to check for a redirect to after an attempt to GET
+        * SETUP_PREPAID_DETECTION_TARGET_URL. (If we redirected there,
+        * this is a prepaid device with zero balance.)
+        * @hide
+        */
+       public static final String SETUP_PREPAID_DETECTION_REDIR_HOST =
+               "setup_prepaid_detection_redir_host";
+
+       /**
+        * The interval in milliseconds at which to check the number of SMS sent out without asking
+        * for use permit, to limit the un-authorized SMS usage.
+        *
+        * @hide
+        */
+       public static final String SMS_OUTGOING_CHECK_INTERVAL_MS =
+               "sms_outgoing_check_interval_ms";
+
+       /**
+        * The number of outgoing SMS sent without asking for user permit (of {@link
+        * #SMS_OUTGOING_CHECK_INTERVAL_MS}
+        *
+        * @hide
+        */
+       public static final String SMS_OUTGOING_CHECK_MAX_COUNT =
+               "sms_outgoing_check_max_count";
+
+       /**
+        * Used to disable SMS short code confirmation - defaults to true.
+        * True indcates we will do the check, etc.  Set to false to disable.
+        * @see com.android.internal.telephony.SmsUsageMonitor
+        * @hide
+        */
+       public static final String SMS_SHORT_CODE_CONFIRMATION = "sms_short_code_confirmation";
+
+        /**
+         * Used to select which country we use to determine premium sms codes.
+         * One of com.android.internal.telephony.SMSDispatcher.PREMIUM_RULE_USE_SIM,
+         * com.android.internal.telephony.SMSDispatcher.PREMIUM_RULE_USE_NETWORK,
+         * or com.android.internal.telephony.SMSDispatcher.PREMIUM_RULE_USE_BOTH.
+         * @hide
+         */
+        public static final String SMS_SHORT_CODE_RULE = "sms_short_code_rule";
+
+       /**
+        * Used to disable Tethering on a device - defaults to true
+        * @hide
+        */
+       public static final String TETHER_SUPPORTED = "tether_supported";
+
+       /**
+        * Used to require DUN APN on the device or not - defaults to a build config value
+        * which defaults to false
+        * @hide
+        */
+       public static final String TETHER_DUN_REQUIRED = "tether_dun_required";
+
+       /**
+        * Used to hold a gservices-provisioned apn value for DUN.  If set, or the
+        * corresponding build config values are set it will override the APN DB
+        * values.
+        * Consists of a comma seperated list of strings:
+        * "name,apn,proxy,port,username,password,server,mmsc,mmsproxy,mmsport,mcc,mnc,auth,type"
+        * note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN"
+        * @hide
+        */
+       public static final String TETHER_DUN_APN = "tether_dun_apn";
+
+       /**
+        * The bandwidth throttle polling freqency in seconds
+        * @hide
+        */
+       public static final String THROTTLE_POLLING_SEC = "throttle_polling_sec";
+
+       /**
+        * The bandwidth throttle threshold (long)
+        * @hide
+        */
+       public static final String THROTTLE_THRESHOLD_BYTES = "throttle_threshold_bytes";
+
+       /**
+        * The bandwidth throttle value (kbps)
+        * @hide
+        */
+       public static final String THROTTLE_VALUE_KBITSPS = "throttle_value_kbitsps";
+
+       /**
+        * The bandwidth throttle reset calendar day (1-28)
+        * @hide
+        */
+       public static final String THROTTLE_RESET_DAY = "throttle_reset_day";
+
+       /**
+        * The throttling notifications we should send
+        * @hide
+        */
+       public static final String THROTTLE_NOTIFICATION_TYPE = "throttle_notification_type";
+
+       /**
+        * Help URI for data throttling policy
+        * @hide
+        */
+       public static final String THROTTLE_HELP_URI = "throttle_help_uri";
+
+       /**
+        * The length of time in Sec that we allow our notion of NTP time
+        * to be cached before we refresh it
+        * @hide
+        */
+       public static final String THROTTLE_MAX_NTP_CACHE_AGE_SEC =
+               "throttle_max_ntp_cache_age_sec";
+
+       /**
+        * USB Mass Storage Enabled
+        */
+       public static final String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
+
+       /**
+        * If this setting is set (to anything), then all references
+        * to Gmail on the device must change to Google Mail.
+        */
+       public static final String USE_GOOGLE_MAIL = "use_google_mail";
+
+       /** Autofill server address (Used in WebView/browser).
+        * {@hide} */
+       public static final String WEB_AUTOFILL_QUERY_URL =
+           "web_autofill_query_url";
+
+       /**
+        * Whether Wifi display is enabled/disabled
+        * 0=disabled. 1=enabled.
+        * @hide
+        */
+       public static final String WIFI_DISPLAY_ON = "wifi_display_on";
+
+       /**
+        * Whether to notify the user of open networks.
+        * <p>
+        * If not connected and the scan results have an open network, we will
+        * put this notification up. If we attempt to connect to a network or
+        * the open network(s) disappear, we remove the notification. When we
+        * show the notification, we will not show it again for
+        * {@link android.provider.Settings.Secure#WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY} time.
+        */
+       public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON =
+               "wifi_networks_available_notification_on";
+       /**
+        * {@hide}
+        */
+       public static final String WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON =
+               "wimax_networks_available_notification_on";
+
+       /**
+        * Delay (in seconds) before repeating the Wi-Fi networks available notification.
+        * Connecting to a network will reset the timer.
+        */
+       public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY =
+               "wifi_networks_available_repeat_delay";
+
+       /**
+        * 802.11 country code in ISO 3166 format
+        * @hide
+        */
+       public static final String WIFI_COUNTRY_CODE = "wifi_country_code";
+
+       /**
+        * The interval in milliseconds to issue wake up scans when wifi needs
+        * to connect. This is necessary to connect to an access point when
+        * device is on the move and the screen is off.
+        * @hide
+        */
+       public static final String WIFI_FRAMEWORK_SCAN_INTERVAL_MS =
+               "wifi_framework_scan_interval_ms";
+
+       /**
+        * The interval in milliseconds after which Wi-Fi is considered idle.
+        * When idle, it is possible for the device to be switched from Wi-Fi to
+        * the mobile data network.
+        * @hide
+        */
+       public static final String WIFI_IDLE_MS = "wifi_idle_ms";
+
+       /**
+        * When the number of open networks exceeds this number, the
+        * least-recently-used excess networks will be removed.
+        */
+       public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
+
+       /**
+        * Whether the Wi-Fi should be on.  Only the Wi-Fi service should touch this.
+        */
+       public static final String WIFI_ON = "wifi_on";
+
+       /**
+        * Used to save the Wifi_ON state prior to tethering.
+        * This state will be checked to restore Wifi after
+        * the user turns off tethering.
+        *
+        * @hide
+        */
+       public static final String WIFI_SAVED_STATE = "wifi_saved_state";
+
+       /**
+        * The interval in milliseconds to scan as used by the wifi supplicant
+        * @hide
+        */
+       public static final String WIFI_SUPPLICANT_SCAN_INTERVAL_MS =
+               "wifi_supplicant_scan_interval_ms";
+
+       /**
+        * The interval in milliseconds to scan at supplicant when p2p is connected
+        * @hide
+        */
+       public static final String WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS =
+               "wifi_scan_interval_p2p_connected_ms";
+
+       /**
+        * Whether the Wi-Fi watchdog is enabled.
+        */
+       public static final String WIFI_WATCHDOG_ON = "wifi_watchdog_on";
+
+       /**
+        * Setting to turn off poor network avoidance on Wi-Fi. Feature is enabled by default and
+        * the setting needs to be set to 0 to disable it.
+        * @hide
+        */
+       public static final String WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED =
+               "wifi_watchdog_poor_network_test_enabled";
+
+       /**
+        * Setting to turn on suspend optimizations at screen off on Wi-Fi. Enabled by default and
+        * needs to be set to 0 to disable it.
+        * @hide
+        */
+       public static final String WIFI_SUSPEND_OPTIMIZATIONS_ENABLED =
+               "wifi_suspend_optimizations_enabled";
+
+       /**
+        * The maximum number of times we will retry a connection to an access
+        * point for which we have failed in acquiring an IP address from DHCP.
+        * A value of N means that we will make N+1 connection attempts in all.
+        */
+       public static final String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
+
+       /**
+        * Maximum amount of time in milliseconds to hold a wakelock while waiting for mobile
+        * data connectivity to be established after a disconnect from Wi-Fi.
+        */
+       public static final String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS =
+           "wifi_mobile_data_transition_wakelock_timeout_ms";
+
+       /**
+        * The operational wifi frequency band
+        * Set to one of {@link WifiManager#WIFI_FREQUENCY_BAND_AUTO},
+        * {@link WifiManager#WIFI_FREQUENCY_BAND_5GHZ} or
+        * {@link WifiManager#WIFI_FREQUENCY_BAND_2GHZ}
+        *
+        * @hide
+        */
+       public static final String WIFI_FREQUENCY_BAND = "wifi_frequency_band";
+
+       /**
+        * The Wi-Fi peer-to-peer device name
+        * @hide
+        */
+       public static final String WIFI_P2P_DEVICE_NAME = "wifi_p2p_device_name";
+
+       /**
+        * The number of milliseconds to delay when checking for data stalls during
+        * non-aggressive detection. (screen is turned off.)
+        * @hide
+        */
+       public static final String DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS =
+               "data_stall_alarm_non_aggressive_delay_in_ms";
+
+       /**
+        * The number of milliseconds to delay when checking for data stalls during
+        * aggressive detection. (screen on or suspected data stall)
+        * @hide
+        */
+       public static final String DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS =
+               "data_stall_alarm_aggressive_delay_in_ms";
+
+       /**
+        * The interval in milliseconds at which to check gprs registration
+        * after the first registration mismatch of gprs and voice service,
+        * to detect possible data network registration problems.
+        *
+        * @hide
+        */
+       public static final String GPRS_REGISTER_CHECK_PERIOD_MS =
+               "gprs_register_check_period_ms";
+
+       /**
+        * Nonzero causes Log.wtf() to crash.
+        * @hide
+        */
+       public static final String WTF_IS_FATAL = "wtf_is_fatal";
+
+       /**
+        * Ringer mode. This is used internally, changing this value will not
+        * change the ringer mode. See AudioManager.
+        */
+       public static final String MODE_RINGER = "mode_ringer";
+
+       /**
+        * Overlay display devices setting.
+        * The associated value is a specially formatted string that describes the
+        * size and density of simulated secondary display devices.
+        * <p>
+        * Format: {width}x{height}/{dpi};...
+        * </p><p>
+        * Example:
+        * <ul>
+        * <li><code>1280x720/213</code>: make one overlay that is 1280x720 at 213dpi.</li>
+        * <li><code>1920x1080/320;1280x720/213</code>: make two overlays, the first
+        * at 1080p and the second at 720p.</li>
+        * <li>If the value is empty, then no overlay display devices are created.</li>
+        * </ul></p>
+        *
+        * @hide
+        */
+       public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices";
+
+        /**
+         * Threshold values for the duration and level of a discharge cycle,
+         * under which we log discharge cycle info.
+         *
+         * @hide
+         */
+        public static final String
+                BATTERY_DISCHARGE_DURATION_THRESHOLD = "battery_discharge_duration_threshold";
+
+        /** @hide */
+        public static final String BATTERY_DISCHARGE_THRESHOLD = "battery_discharge_threshold";
+
+        /**
+         * Flag for allowing ActivityManagerService to send ACTION_APP_ERROR
+         * intents on application crashes and ANRs. If this is disabled, the
+         * crash/ANR dialog will never display the "Report" button.
+         * <p>
+         * Type: int (0 = disallow, 1 = allow)
+         *
+         * @hide
+         */
+        public static final String SEND_ACTION_APP_ERROR = "send_action_app_error";
+
+        /**
+         * Maximum age of entries kept by {@link DropBoxManager}.
+         *
+         * @hide
+         */
+        public static final String DROPBOX_AGE_SECONDS = "dropbox_age_seconds";
+
+        /**
+         * Maximum number of entry files which {@link DropBoxManager} will keep
+         * around.
+         *
+         * @hide
+         */
+        public static final String DROPBOX_MAX_FILES = "dropbox_max_files";
+
+        /**
+         * Maximum amount of disk space used by {@link DropBoxManager} no matter
+         * what.
+         *
+         * @hide
+         */
+        public static final String DROPBOX_QUOTA_KB = "dropbox_quota_kb";
+
+        /**
+         * Percent of free disk (excluding reserve) which {@link DropBoxManager}
+         * will use.
+         *
+         * @hide
+         */
+        public static final String DROPBOX_QUOTA_PERCENT = "dropbox_quota_percent";
+
+        /**
+         * Percent of total disk which {@link DropBoxManager} will never dip
+         * into.
+         *
+         * @hide
+         */
+        public static final String DROPBOX_RESERVE_PERCENT = "dropbox_reserve_percent";
+
+        /**
+         * Prefix for per-tag dropbox disable/enable settings.
+         *
+         * @hide
+         */
+        public static final String DROPBOX_TAG_PREFIX = "dropbox:";
+
+        /**
+         * Lines of logcat to include with system crash/ANR/etc. reports, as a
+         * prefix of the dropbox tag of the report type. For example,
+         * "logcat_for_system_server_anr" controls the lines of logcat captured
+         * with system server ANR reports. 0 to disable.
+         *
+         * @hide
+         */
+        public static final String ERROR_LOGCAT_PREFIX = "logcat_for_";
+
+        /**
+         * The interval in minutes after which the amount of free storage left
+         * on the device is logged to the event log
+         *
+         * @hide
+         */
+        public static final String SYS_FREE_STORAGE_LOG_INTERVAL = "sys_free_storage_log_interval";
+
+        /**
+         * Threshold for the amount of change in disk free space required to
+         * report the amount of free space. Used to prevent spamming the logs
+         * when the disk free space isn't changing frequently.
+         *
+         * @hide
+         */
+        public static final String
+                DISK_FREE_CHANGE_REPORTING_THRESHOLD = "disk_free_change_reporting_threshold";
+
+        /**
+         * Minimum percentage of free storage on the device that is used to
+         * determine if the device is running low on storage. The default is 10.
+         * <p>
+         * Say this value is set to 10, the device is considered running low on
+         * storage if 90% or more of the device storage is filled up.
+         *
+         * @hide
+         */
+        public static final String
+                SYS_STORAGE_THRESHOLD_PERCENTAGE = "sys_storage_threshold_percentage";
+
+        /**
+         * Maximum byte size of the low storage threshold. This is to ensure
+         * that {@link #SYS_STORAGE_THRESHOLD_PERCENTAGE} does not result in an
+         * overly large threshold for large storage devices. Currently this must
+         * be less than 2GB. This default is 500MB.
+         *
+         * @hide
+         */
+        public static final String
+                SYS_STORAGE_THRESHOLD_MAX_BYTES = "sys_storage_threshold_max_bytes";
+
+        /**
+         * Minimum bytes of free storage on the device before the data partition
+         * is considered full. By default, 1 MB is reserved to avoid system-wide
+         * SQLite disk full exceptions.
+         *
+         * @hide
+         */
+        public static final String
+                SYS_STORAGE_FULL_THRESHOLD_BYTES = "sys_storage_full_threshold_bytes";
+
+        /**
+         * The maximum reconnect delay for short network outages or when the
+         * network is suspended due to phone use.
+         *
+         * @hide
+         */
+        public static final String
+                SYNC_MAX_RETRY_DELAY_IN_SECONDS = "sync_max_retry_delay_in_seconds";
+
+        /**
+         * The number of milliseconds to delay before sending out
+         * {@link ConnectivityManager#CONNECTIVITY_ACTION} broadcasts.
+         *
+         * @hide
+         */
+        public static final String CONNECTIVITY_CHANGE_DELAY = "connectivity_change_delay";
+
+        /**
+         * Setting to turn off captive portal detection. Feature is enabled by
+         * default and the setting needs to be set to 0 to disable it.
+         *
+         * @hide
+         */
+        public static final String
+                CAPTIVE_PORTAL_DETECTION_ENABLED = "captive_portal_detection_enabled";
+
+        /**
+         * The server used for captive portal detection upon a new conection. A
+         * 204 response code from the server is used for validation.
+         *
+         * @hide
+         */
+        public static final String CAPTIVE_PORTAL_SERVER = "captive_portal_server";
+
+        /**
+         * Whether network service discovery is enabled.
+         *
+         * @hide
+         */
+        public static final String NSD_ON = "nsd_on";
+
+        /**
+         * Let user pick default install location.
+         *
+         * @hide
+         */
+        public static final String SET_INSTALL_LOCATION = "set_install_location";
+
+        /**
+         * Default install location value.
+         * 0 = auto, let system decide
+         * 1 = internal
+         * 2 = sdcard
+         * @hide
+         */
+        public static final String DEFAULT_INSTALL_LOCATION = "default_install_location";
+
+        /**
+         * ms during which to consume extra events related to Inet connection
+         * condition after a transtion to fully-connected
+         *
+         * @hide
+         */
+        public static final String
+                INET_CONDITION_DEBOUNCE_UP_DELAY = "inet_condition_debounce_up_delay";
+
+        /**
+         * ms during which to consume extra events related to Inet connection
+         * condtion after a transtion to partly-connected
+         *
+         * @hide
+         */
+        public static final String
+                INET_CONDITION_DEBOUNCE_DOWN_DELAY = "inet_condition_debounce_down_delay";
+
+        /** {@hide} */
+        public static final String
+                READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT = "read_external_storage_enforced_default";
+
+        /**
+         * Host name and port for global http proxy. Uses ':' seperator for
+         * between host and port.
+         */
+        public static final String HTTP_PROXY = "http_proxy";
+
+        /**
+         * Host name for global http proxy. Set via ConnectivityManager.
+         *
+         * @hide
+         */
+        public static final String GLOBAL_HTTP_PROXY_HOST = "global_http_proxy_host";
+
+        /**
+         * Integer host port for global http proxy. Set via ConnectivityManager.
+         *
+         * @hide
+         */
+        public static final String GLOBAL_HTTP_PROXY_PORT = "global_http_proxy_port";
+
+        /**
+         * Exclusion list for global proxy. This string contains a list of
+         * comma-separated domains where the global proxy does not apply.
+         * Domains should be listed in a comma- separated list. Example of
+         * acceptable formats: ".domain1.com,my.domain2.com" Use
+         * ConnectivityManager to set/get.
+         *
+         * @hide
+         */
+        public static final String
+                GLOBAL_HTTP_PROXY_EXCLUSION_LIST = "global_http_proxy_exclusion_list";
+
+        /**
+         * Enables the UI setting to allow the user to specify the global HTTP
+         * proxy and associated exclusion list.
+         *
+         * @hide
+         */
+        public static final String SET_GLOBAL_HTTP_PROXY = "set_global_http_proxy";
+
+        /**
+         * Setting for default DNS in case nobody suggests one
+         *
+         * @hide
+         */
+        public static final String DEFAULT_DNS_SERVER = "default_dns_server";
+
+        /** {@hide} */
+        public static final String
+                BLUETOOTH_HEADSET_PRIORITY_PREFIX = "bluetooth_headset_priority_";
+        /** {@hide} */
+        public static final String
+                BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX = "bluetooth_a2dp_sink_priority_";
+        /** {@hide} */
+        public static final String
+                BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX = "bluetooth_input_device_priority_";
+
+        /**
+         * Get the key that retrieves a bluetooth headset's priority.
+         * @hide
+         */
+        public static final String getBluetoothHeadsetPriorityKey(String address) {
+            return BLUETOOTH_HEADSET_PRIORITY_PREFIX + address.toUpperCase();
+        }
+
+        /**
+         * Get the key that retrieves a bluetooth a2dp sink's priority.
+         * @hide
+         */
+        public static final String getBluetoothA2dpSinkPriorityKey(String address) {
+            return BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX + address.toUpperCase();
+        }
+
+        /**
+         * Get the key that retrieves a bluetooth Input Device's priority.
+         * @hide
+         */
+        public static final String getBluetoothInputDevicePriorityKey(String address) {
+            return BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX + address.toUpperCase();
+        }
+
+        /**
+         * Scaling factor for normal window animations. Setting to 0 will
+         * disable window animations.
+         */
+        public static final String WINDOW_ANIMATION_SCALE = "window_animation_scale";
+
+        /**
+         * Scaling factor for activity transition animations. Setting to 0 will
+         * disable window animations.
+         */
+        public static final String TRANSITION_ANIMATION_SCALE = "transition_animation_scale";
+
+        /**
+         * Scaling factor for Animator-based animations. This affects both the
+         * start delay and duration of all such animations. Setting to 0 will
+         * cause animations to end immediately. The default value is 1.
+         */
+        public static final String ANIMATOR_DURATION_SCALE = "animator_duration_scale";
+
+        /**
+         * Scaling factor for normal window animations. Setting to 0 will
+         * disable window animations.
+         *
+         * @hide
+         */
+        public static final String FANCY_IME_ANIMATIONS = "fancy_ime_animations";
+
+        /**
+         * If 0, the compatibility mode is off for all applications.
+         * If 1, older applications run under compatibility mode.
+         * TODO: remove this settings before code freeze (bug/1907571)
+         * @hide
+         */
+        public static final String COMPATIBILITY_MODE = "compatibility_mode";
+
+        /**
+         * CDMA only settings
+         * Emergency Tone  0 = Off
+         *                 1 = Alert
+         *                 2 = Vibrate
+         * @hide
+         */
+        public static final String EMERGENCY_TONE = "emergency_tone";
+
+        /**
+         * CDMA only settings
+         * Whether the auto retry is enabled. The value is
+         * boolean (1 or 0).
+         * @hide
+         */
+        public static final String CALL_AUTO_RETRY = "call_auto_retry";
+
+        /**
+         * The preferred network mode   7 = Global
+         *                              6 = EvDo only
+         *                              5 = CDMA w/o EvDo
+         *                              4 = CDMA / EvDo auto
+         *                              3 = GSM / WCDMA auto
+         *                              2 = WCDMA only
+         *                              1 = GSM only
+         *                              0 = GSM / WCDMA preferred
+         * @hide
+         */
+        public static final String PREFERRED_NETWORK_MODE =
+                "preferred_network_mode";
+
+        /**
+         * The cdma subscription 0 = Subscription from RUIM, when available
+         *                       1 = Subscription from NV
+         * @hide
+         */
+        public static final String PREFERRED_CDMA_SUBSCRIPTION =
+                "preferred_cdma_subscription";
+
+        /**
+         * Name of an application package to be debugged.
+         */
+        public static final String DEBUG_APP = "debug_app";
+
+        /**
+         * If 1, when launching DEBUG_APP it will wait for the debugger before
+         * starting user code.  If 0, it will run normally.
+         */
+        public static final String WAIT_FOR_DEBUGGER = "wait_for_debugger";
+
+        /**
+         * Control whether the process CPU usage meter should be shown.
+         */
+        public static final String SHOW_PROCESSES = "show_processes";
+
+        /**
+         * If 1, the activity manager will aggressively finish activities and
+         * processes as soon as they are no longer needed.  If 0, the normal
+         * extended lifetime is used.
+         */
+        public static final String ALWAYS_FINISH_ACTIVITIES =
+                "always_finish_activities";
+
+        /**
+         * Use Dock audio output for media:
+         *      0 = disabled
+         *      1 = enabled
+         * @hide
+         */
+        public static final String DOCK_AUDIO_MEDIA_ENABLED = "dock_audio_media_enabled";
+
+        /**
+         * Settings to backup. This is here so that it's in the same place as the settings
+         * keys and easy to update.
+         *
+         * These keys may be mentioned in the SETTINGS_TO_BACKUP arrays in System
+         * and Secure as well.  This is because those tables drive both backup and
+         * restore, and restore needs to properly whitelist keys that used to live
+         * in those namespaces.  The keys will only actually be backed up / restored
+         * if they are also mentioned in this table (Global.SETTINGS_TO_BACKUP).
+         *
+         * NOTE: Settings are backed up and restored in the order they appear
+         *       in this array. If you have one setting depending on another,
+         *       make sure that they are ordered appropriately.
+         *
+         * @hide
+         */
+        public static final String[] SETTINGS_TO_BACKUP = {
+            STAY_ON_WHILE_PLUGGED_IN,
+            MODE_RINGER,
+            AUTO_TIME,
+            AUTO_TIME_ZONE,
+            POWER_SOUNDS_ENABLED,
+            DOCK_SOUNDS_ENABLED,
+            USB_MASS_STORAGE_ENABLED,
+            ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED,
+            WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
+            WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
+            WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED,
+            WIFI_NUM_OPEN_NETWORKS_KEPT,
+            EMERGENCY_TONE,
+            CALL_AUTO_RETRY,
+            DOCK_AUDIO_MEDIA_ENABLED
+        };
+
+        // Populated lazily, guarded by class object:
+        private static NameValueCache sNameValueCache = new NameValueCache(
+                    SYS_PROP_SETTING_VERSION,
+                    CONTENT_URI,
+                    CALL_METHOD_GET_GLOBAL,
+                    CALL_METHOD_PUT_GLOBAL);
+
+        /**
+         * Look up a name in the database.
+         * @param resolver to access the database with
+         * @param name to look up in the table
+         * @return the corresponding value, or null if not present
+         */
+        public static String getString(ContentResolver resolver, String name) {
+            return getStringForUser(resolver, name, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static String getStringForUser(ContentResolver resolver, String name,
+                int userHandle) {
+            return sNameValueCache.getStringForUser(resolver, name, userHandle);
+        }
+
+        /**
+         * Store a name/value pair into the database.
+         * @param resolver to access the database with
+         * @param name to store
+         * @param value to associate with the name
+         * @return true if the value was set, false on database errors
+         */
+        public static boolean putString(ContentResolver resolver,
+                String name, String value) {
+            return putStringForUser(resolver, name, value, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public static boolean putStringForUser(ContentResolver resolver,
+                String name, String value, int userHandle) {
+            if (LOCAL_LOGV) {
+                Log.v(TAG, "Global.putString(name=" + name + ", value=" + value
+                        + " for " + userHandle);
+            }
+            return sNameValueCache.putStringForUser(resolver, name, value, userHandle);
+        }
+
+        /**
+         * Construct the content URI for a particular name/value pair,
+         * useful for monitoring changes with a ContentObserver.
+         * @param name to look up in the table
+         * @return the corresponding content URI, or null if not present
+         */
+        public static Uri getUriFor(String name) {
+            return getUriFor(CONTENT_URI, name);
+        }
+
+        /**
+         * Convenience function for retrieving a single secure settings value
+         * as an integer.  Note that internally setting values are always
+         * stored as strings; this function converts the string to an integer
+         * for you.  The default value will be returned if the setting is
+         * not defined or not an integer.
+         *
+         * @param cr The ContentResolver to access.
+         * @param name The name of the setting to retrieve.
+         * @param def Value to return if the setting is not defined.
+         *
+         * @return The setting's current value, or 'def' if it is not defined
+         * or not a valid integer.
+         */
+        public static int getInt(ContentResolver cr, String name, int def) {
+            String v = getString(cr, name);
+            try {
+                return v != null ? Integer.parseInt(v) : def;
+            } catch (NumberFormatException e) {
+                return def;
+            }
+        }
+
+        /**
+         * Convenience function for retrieving a single secure settings value
+         * as an integer.  Note that internally setting values are always
+         * stored as strings; this function converts the string to an integer
+         * for you.
+         * <p>
+         * This version does not take a default value.  If the setting has not
+         * been set, or the string value is not a number,
+         * it throws {@link SettingNotFoundException}.
+         *
+         * @param cr The ContentResolver to access.
+         * @param name The name of the setting to retrieve.
+         *
+         * @throws SettingNotFoundException Thrown if a setting by the given
+         * name can't be found or the setting value is not an integer.
+         *
+         * @return The setting's current value.
+         */
+        public static int getInt(ContentResolver cr, String name)
+                throws SettingNotFoundException {
+            String v = getString(cr, name);
+            try {
+                return Integer.parseInt(v);
+            } catch (NumberFormatException e) {
+                throw new SettingNotFoundException(name);
+            }
+        }
+
+        /**
+         * Convenience function for updating a single settings value as an
+         * integer. This will either create a new entry in the table if the
+         * given name does not exist, or modify the value of the existing row
+         * with that name.  Note that internally setting values are always
+         * stored as strings, so this function converts the given value to a
+         * string before storing it.
+         *
+         * @param cr The ContentResolver to access.
+         * @param name The name of the setting to modify.
+         * @param value The new value for the setting.
+         * @return true if the value was set, false on database errors
+         */
+        public static boolean putInt(ContentResolver cr, String name, int value) {
+            return putString(cr, name, Integer.toString(value));
+        }
+
+        /**
+         * Convenience function for retrieving a single secure settings value
+         * as a {@code long}.  Note that internally setting values are always
+         * stored as strings; this function converts the string to a {@code long}
+         * for you.  The default value will be returned if the setting is
+         * not defined or not a {@code long}.
+         *
+         * @param cr The ContentResolver to access.
+         * @param name The name of the setting to retrieve.
+         * @param def Value to return if the setting is not defined.
+         *
+         * @return The setting's current value, or 'def' if it is not defined
+         * or not a valid {@code long}.
+         */
+        public static long getLong(ContentResolver cr, String name, long def) {
+            String valString = getString(cr, name);
+            long value;
+            try {
+                value = valString != null ? Long.parseLong(valString) : def;
+            } catch (NumberFormatException e) {
+                value = def;
+            }
+            return value;
+        }
+
+        /**
+         * Convenience function for retrieving a single secure settings value
+         * as a {@code long}.  Note that internally setting values are always
+         * stored as strings; this function converts the string to a {@code long}
+         * for you.
+         * <p>
+         * This version does not take a default value.  If the setting has not
+         * been set, or the string value is not a number,
+         * it throws {@link SettingNotFoundException}.
+         *
+         * @param cr The ContentResolver to access.
+         * @param name The name of the setting to retrieve.
+         *
+         * @return The setting's current value.
+         * @throws SettingNotFoundException Thrown if a setting by the given
+         * name can't be found or the setting value is not an integer.
+         */
+        public static long getLong(ContentResolver cr, String name)
+                throws SettingNotFoundException {
+            String valString = getString(cr, name);
+            try {
+                return Long.parseLong(valString);
+            } catch (NumberFormatException e) {
+                throw new SettingNotFoundException(name);
+            }
+        }
+
+        /**
+         * Convenience function for updating a secure settings value as a long
+         * integer. This will either create a new entry in the table if the
+         * given name does not exist, or modify the value of the existing row
+         * with that name.  Note that internally setting values are always
+         * stored as strings, so this function converts the given value to a
+         * string before storing it.
+         *
+         * @param cr The ContentResolver to access.
+         * @param name The name of the setting to modify.
+         * @param value The new value for the setting.
+         * @return true if the value was set, false on database errors
+         */
+        public static boolean putLong(ContentResolver cr, String name, long value) {
+            return putString(cr, name, Long.toString(value));
+        }
+
+        /**
+         * Convenience function for retrieving a single secure settings value
+         * as a floating point number.  Note that internally setting values are
+         * always stored as strings; this function converts the string to an
+         * float for you. The default value will be returned if the setting
+         * is not defined or not a valid float.
+         *
+         * @param cr The ContentResolver to access.
+         * @param name The name of the setting to retrieve.
+         * @param def Value to return if the setting is not defined.
+         *
+         * @return The setting's current value, or 'def' if it is not defined
+         * or not a valid float.
+         */
+        public static float getFloat(ContentResolver cr, String name, float def) {
+            String v = getString(cr, name);
+            try {
+                return v != null ? Float.parseFloat(v) : def;
+            } catch (NumberFormatException e) {
+                return def;
+            }
+        }
+
+        /**
+         * Convenience function for retrieving a single secure settings value
+         * as a float.  Note that internally setting values are always
+         * stored as strings; this function converts the string to a float
+         * for you.
+         * <p>
+         * This version does not take a default value.  If the setting has not
+         * been set, or the string value is not a number,
+         * it throws {@link SettingNotFoundException}.
+         *
+         * @param cr The ContentResolver to access.
+         * @param name The name of the setting to retrieve.
+         *
+         * @throws SettingNotFoundException Thrown if a setting by the given
+         * name can't be found or the setting value is not a float.
+         *
+         * @return The setting's current value.
+         */
+        public static float getFloat(ContentResolver cr, String name)
+                throws SettingNotFoundException {
+            String v = getString(cr, name);
+            if (v == null) {
+                throw new SettingNotFoundException(name);
+            }
+            try {
+                return Float.parseFloat(v);
+            } catch (NumberFormatException e) {
+                throw new SettingNotFoundException(name);
+            }
+        }
+
+        /**
+         * Convenience function for updating a single settings value as a
+         * floating point number. This will either create a new entry in the
+         * table if the given name does not exist, or modify the value of the
+         * existing row with that name.  Note that internally setting values
+         * are always stored as strings, so this function converts the given
+         * value to a string before storing it.
+         *
+         * @param cr The ContentResolver to access.
+         * @param name The name of the setting to modify.
+         * @param value The new value for the setting.
+         * @return true if the value was set, false on database errors
+         */
+        public static boolean putFloat(ContentResolver cr, String name, float value) {
+            return putString(cr, name, Float.toString(value));
         }
     }
 
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
deleted file mode 100644
index 08a99d2..0000000
--- a/core/java/android/server/BluetoothA2dpService.java
+++ /dev/null
@@ -1,653 +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.
- */
-
-/**
- * TODO: Move this to services.jar
- * and make the constructor package private again.
- * @hide
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothUuid;
-import android.bluetooth.IBluetoothA2dp;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.media.AudioManager;
-import android.os.Handler;
-import android.os.Message;
-import android.os.ParcelUuid;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
-import android.provider.Settings;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-
-public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
-    private static final String TAG = "BluetoothA2dpService";
-    private static final boolean DBG = true;
-
-    public static final String BLUETOOTH_A2DP_SERVICE = "bluetooth_a2dp";
-
-    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
-    private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
-
-    private static final String BLUETOOTH_ENABLED = "bluetooth_enabled";
-
-    private static final String PROPERTY_STATE = "State";
-
-    private final Context mContext;
-    private final IntentFilter mIntentFilter;
-    private HashMap<BluetoothDevice, Integer> mAudioDevices;
-    private final AudioManager mAudioManager;
-    private final BluetoothService mBluetoothService;
-    private final BluetoothAdapter mAdapter;
-    private int   mTargetA2dpState;
-    private BluetoothDevice mPlayingA2dpDevice;
-    private IntentBroadcastHandler mIntentBroadcastHandler;
-    private final WakeLock mWakeLock;
-
-    private static final int MSG_CONNECTION_STATE_CHANGED = 0;
-
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            BluetoothDevice device =
-                    intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-            if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
-                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
-                                               BluetoothAdapter.ERROR);
-                switch (state) {
-                case BluetoothAdapter.STATE_ON:
-                    onBluetoothEnable();
-                    break;
-                case BluetoothAdapter.STATE_TURNING_OFF:
-                    onBluetoothDisable();
-                    break;
-                }
-            } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
-                synchronized (this) {
-                    if (mAudioDevices.containsKey(device)) {
-                        int state = mAudioDevices.get(device);
-                        handleSinkStateChange(device, state, BluetoothA2dp.STATE_DISCONNECTED);
-                    }
-                }
-            } else if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
-                int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
-                if (streamType == AudioManager.STREAM_MUSIC) {
-                    List<BluetoothDevice> sinks = getConnectedDevices();
-
-                    if (sinks.size() != 0 && isPhoneDocked(sinks.get(0))) {
-                        String address = sinks.get(0).getAddress();
-                        int newVolLevel =
-                          intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0);
-                        int oldVolLevel =
-                          intent.getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, 0);
-                        String path = mBluetoothService.getObjectPathFromAddress(address);
-                        if (newVolLevel > oldVolLevel) {
-                            avrcpVolumeUpNative(path);
-                        } else if (newVolLevel < oldVolLevel) {
-                            avrcpVolumeDownNative(path);
-                        }
-                    }
-                }
-            }
-        }
-    };
-
-    private boolean isPhoneDocked(BluetoothDevice device) {
-        // This works only because these broadcast intents are "sticky"
-        Intent i = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
-        if (i != null) {
-            int state = i.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED);
-            if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
-                BluetoothDevice dockDevice = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-                if (dockDevice != null && device.equals(dockDevice)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    public BluetoothA2dpService(Context context, BluetoothService bluetoothService) {
-        mContext = context;
-
-        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "BluetoothA2dpService");
-
-        mIntentBroadcastHandler = new IntentBroadcastHandler();
-
-        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-
-        mBluetoothService = bluetoothService;
-        if (mBluetoothService == null) {
-            throw new RuntimeException("Platform does not support Bluetooth");
-        }
-
-        if (!initNative()) {
-            throw new RuntimeException("Could not init BluetoothA2dpService");
-        }
-
-        mAdapter = BluetoothAdapter.getDefaultAdapter();
-
-        mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
-        mIntentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
-        mIntentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
-        mIntentFilter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
-        mContext.registerReceiver(mReceiver, mIntentFilter);
-
-        mAudioDevices = new HashMap<BluetoothDevice, Integer>();
-
-        if (mBluetoothService.isEnabled())
-            onBluetoothEnable();
-        mTargetA2dpState = -1;
-        mBluetoothService.setA2dpService(this);
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            cleanupNative();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    private int convertBluezSinkStringToState(String value) {
-        if (value.equalsIgnoreCase("disconnected"))
-            return BluetoothA2dp.STATE_DISCONNECTED;
-        if (value.equalsIgnoreCase("connecting"))
-            return BluetoothA2dp.STATE_CONNECTING;
-        if (value.equalsIgnoreCase("connected"))
-            return BluetoothA2dp.STATE_CONNECTED;
-        if (value.equalsIgnoreCase("playing"))
-            return BluetoothA2dp.STATE_PLAYING;
-        return -1;
-    }
-
-    private boolean isSinkDevice(BluetoothDevice device) {
-        ParcelUuid[] uuids = mBluetoothService.getRemoteUuids(device.getAddress());
-        if (uuids != null && BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink)) {
-            return true;
-        }
-        return false;
-    }
-
-    private synchronized void addAudioSink(BluetoothDevice device) {
-        if (mAudioDevices.get(device) == null) {
-            mAudioDevices.put(device, BluetoothA2dp.STATE_DISCONNECTED);
-        }
-    }
-
-    private synchronized void onBluetoothEnable() {
-        String devices = mBluetoothService.getProperty("Devices", true);
-        if (devices != null) {
-            String [] paths = devices.split(",");
-            for (String path: paths) {
-                String address = mBluetoothService.getAddressFromObjectPath(path);
-                BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                ParcelUuid[] remoteUuids = mBluetoothService.getRemoteUuids(address);
-                if (remoteUuids != null)
-                    if (BluetoothUuid.containsAnyUuid(remoteUuids,
-                            new ParcelUuid[] {BluetoothUuid.AudioSink,
-                                                BluetoothUuid.AdvAudioDist})) {
-                        addAudioSink(device);
-                    }
-                }
-        }
-        mAudioManager.setParameters(BLUETOOTH_ENABLED+"=true");
-        mAudioManager.setParameters("A2dpSuspended=false");
-    }
-
-    private synchronized void onBluetoothDisable() {
-        if (!mAudioDevices.isEmpty()) {
-            BluetoothDevice[] devices = new BluetoothDevice[mAudioDevices.size()];
-            devices = mAudioDevices.keySet().toArray(devices);
-            for (BluetoothDevice device : devices) {
-                int state = getConnectionState(device);
-                switch (state) {
-                    case BluetoothA2dp.STATE_CONNECTING:
-                    case BluetoothA2dp.STATE_CONNECTED:
-                    case BluetoothA2dp.STATE_PLAYING:
-                        disconnectSinkNative(mBluetoothService.getObjectPathFromAddress(
-                                device.getAddress()));
-                        handleSinkStateChange(device, state, BluetoothA2dp.STATE_DISCONNECTED);
-                        break;
-                    case BluetoothA2dp.STATE_DISCONNECTING:
-                        handleSinkStateChange(device, BluetoothA2dp.STATE_DISCONNECTING,
-                                              BluetoothA2dp.STATE_DISCONNECTED);
-                        break;
-                }
-            }
-            mAudioDevices.clear();
-        }
-
-        mAudioManager.setParameters(BLUETOOTH_ENABLED + "=false");
-    }
-
-    private synchronized boolean isConnectSinkFeasible(BluetoothDevice device) {
-        if (!mBluetoothService.isEnabled() || !isSinkDevice(device) ||
-                getPriority(device) == BluetoothA2dp.PRIORITY_OFF) {
-            return false;
-        }
-
-        addAudioSink(device);
-
-        String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        if (path == null) {
-            return false;
-        }
-        return true;
-    }
-
-    public synchronized boolean isA2dpPlaying(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-            "Need BLUETOOTH_ADMIN permission");
-        if (DBG) log("isA2dpPlaying(" + device + ")");
-        if (device.equals(mPlayingA2dpDevice)) return true;
-        return false;
-    }
-
-    public synchronized boolean connect(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (DBG) log("connectSink(" + device + ")");
-        if (!isConnectSinkFeasible(device)) return false;
-
-        for (BluetoothDevice sinkDevice : mAudioDevices.keySet()) {
-            if (getConnectionState(sinkDevice) != BluetoothProfile.STATE_DISCONNECTED) {
-                disconnect(sinkDevice);
-            }
-        }
-
-        return mBluetoothService.connectSink(device.getAddress());
-    }
-
-    public synchronized boolean connectSinkInternal(BluetoothDevice device) {
-        if (!mBluetoothService.isEnabled()) return false;
-
-        int state = mAudioDevices.get(device);
-
-        // ignore if there are any active sinks
-        if (getDevicesMatchingConnectionStates(new int[] {
-                BluetoothA2dp.STATE_CONNECTING,
-                BluetoothA2dp.STATE_CONNECTED,
-                BluetoothA2dp.STATE_DISCONNECTING}).size() != 0) {
-            return false;
-        }
-
-        switch (state) {
-        case BluetoothA2dp.STATE_CONNECTED:
-        case BluetoothA2dp.STATE_DISCONNECTING:
-            return false;
-        case BluetoothA2dp.STATE_CONNECTING:
-            return true;
-        }
-
-        String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-
-        // State is DISCONNECTED and we are connecting.
-        if (getPriority(device) < BluetoothA2dp.PRIORITY_AUTO_CONNECT) {
-            setPriority(device, BluetoothA2dp.PRIORITY_AUTO_CONNECT);
-        }
-        handleSinkStateChange(device, state, BluetoothA2dp.STATE_CONNECTING);
-
-        if (!connectSinkNative(path)) {
-            // Restore previous state
-            handleSinkStateChange(device, mAudioDevices.get(device), state);
-            return false;
-        }
-        return true;
-    }
-
-    private synchronized boolean isDisconnectSinkFeasible(BluetoothDevice device) {
-        String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        if (path == null) {
-            return false;
-        }
-
-        int state = getConnectionState(device);
-        switch (state) {
-        case BluetoothA2dp.STATE_DISCONNECTED:
-        case BluetoothA2dp.STATE_DISCONNECTING:
-            return false;
-        }
-        return true;
-    }
-
-    public synchronized boolean disconnect(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (DBG) log("disconnectSink(" + device + ")");
-        if (!isDisconnectSinkFeasible(device)) return false;
-        return mBluetoothService.disconnectSink(device.getAddress());
-    }
-
-    public synchronized boolean disconnectSinkInternal(BluetoothDevice device) {
-        int state = getConnectionState(device);
-        String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-
-        switch (state) {
-            case BluetoothA2dp.STATE_DISCONNECTED:
-            case BluetoothA2dp.STATE_DISCONNECTING:
-                return false;
-        }
-        // State is CONNECTING or CONNECTED or PLAYING
-        handleSinkStateChange(device, state, BluetoothA2dp.STATE_DISCONNECTING);
-        if (!disconnectSinkNative(path)) {
-            // Restore previous state
-            handleSinkStateChange(device, mAudioDevices.get(device), state);
-            return false;
-        }
-        return true;
-    }
-
-    public synchronized boolean suspendSink(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                            "Need BLUETOOTH_ADMIN permission");
-        if (DBG) log("suspendSink(" + device + "), mTargetA2dpState: "+mTargetA2dpState);
-        if (device == null || mAudioDevices == null) {
-            return false;
-        }
-        String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        Integer state = mAudioDevices.get(device);
-        if (path == null || state == null) {
-            return false;
-        }
-
-        mTargetA2dpState = BluetoothA2dp.STATE_CONNECTED;
-        return checkSinkSuspendState(state.intValue());
-    }
-
-    public synchronized boolean resumeSink(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                            "Need BLUETOOTH_ADMIN permission");
-        if (DBG) log("resumeSink(" + device + "), mTargetA2dpState: "+mTargetA2dpState);
-        if (device == null || mAudioDevices == null) {
-            return false;
-        }
-        String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        Integer state = mAudioDevices.get(device);
-        if (path == null || state == null) {
-            return false;
-        }
-        mTargetA2dpState = BluetoothA2dp.STATE_PLAYING;
-        return checkSinkSuspendState(state.intValue());
-    }
-
-    public synchronized int getConnectionState(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        Integer state = mAudioDevices.get(device);
-        if (state == null)
-            return BluetoothA2dp.STATE_DISCONNECTED;
-        return state;
-    }
-
-    public synchronized List<BluetoothDevice> getConnectedDevices() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        List<BluetoothDevice> sinks = getDevicesMatchingConnectionStates(
-                new int[] {BluetoothA2dp.STATE_CONNECTED});
-        return sinks;
-    }
-
-    public synchronized List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        ArrayList<BluetoothDevice> sinks = new ArrayList<BluetoothDevice>();
-        for (BluetoothDevice device: mAudioDevices.keySet()) {
-            int sinkState = getConnectionState(device);
-            for (int state : states) {
-                if (state == sinkState) {
-                    sinks.add(device);
-                    break;
-                }
-            }
-        }
-        return sinks;
-    }
-
-    public synchronized int getPriority(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        return Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()),
-                BluetoothA2dp.PRIORITY_UNDEFINED);
-    }
-
-    public synchronized boolean setPriority(BluetoothDevice device, int priority) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        return Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()), priority);
-    }
-
-    public synchronized boolean allowIncomingConnect(BluetoothDevice device, boolean value) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        String address = device.getAddress();
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-        Integer data = mBluetoothService.getAuthorizationAgentRequestData(address);
-        if (data == null) {
-            Log.w(TAG, "allowIncomingConnect(" + device + ") called but no native data available");
-            return false;
-        }
-        log("allowIncomingConnect: A2DP: " + device + ":" + value);
-        return mBluetoothService.setAuthorizationNative(address, value, data.intValue());
-    }
-
-    /**
-     * Called by native code on a PropertyChanged signal from
-     * org.bluez.AudioSink.
-     *
-     * @param path the object path for the changed device
-     * @param propValues a string array containing the key and one or more
-     *  values.
-     */
-    private synchronized void onSinkPropertyChanged(String path, String[] propValues) {
-        if (!mBluetoothService.isEnabled()) {
-            return;
-        }
-
-        String name = propValues[0];
-        String address = mBluetoothService.getAddressFromObjectPath(path);
-        if (address == null) {
-            Log.e(TAG, "onSinkPropertyChanged: Address of the remote device in null");
-            return;
-        }
-
-        BluetoothDevice device = mAdapter.getRemoteDevice(address);
-
-        if (name.equals(PROPERTY_STATE)) {
-            int state = convertBluezSinkStringToState(propValues[1]);
-            log("A2DP: onSinkPropertyChanged newState is: " + state + "mPlayingA2dpDevice: " + mPlayingA2dpDevice);
-
-            if (mAudioDevices.get(device) == null) {
-                // This is for an incoming connection for a device not known to us.
-                // We have authorized it and bluez state has changed.
-                addAudioSink(device);
-                handleSinkStateChange(device, BluetoothA2dp.STATE_DISCONNECTED, state);
-            } else {
-                if (state == BluetoothA2dp.STATE_PLAYING && mPlayingA2dpDevice == null) {
-                   mPlayingA2dpDevice = device;
-                   handleSinkPlayingStateChange(device, state, BluetoothA2dp.STATE_NOT_PLAYING);
-                } else if (state == BluetoothA2dp.STATE_CONNECTED && mPlayingA2dpDevice != null) {
-                    mPlayingA2dpDevice = null;
-                    handleSinkPlayingStateChange(device, BluetoothA2dp.STATE_NOT_PLAYING,
-                        BluetoothA2dp.STATE_PLAYING);
-                } else {
-                   mPlayingA2dpDevice = null;
-                   int prevState = mAudioDevices.get(device);
-                   handleSinkStateChange(device, prevState, state);
-                }
-            }
-        }
-    }
-
-    private void handleSinkStateChange(BluetoothDevice device, int prevState, int state) {
-        if (state != prevState) {
-            mAudioDevices.put(device, state);
-
-            checkSinkSuspendState(state);
-            mTargetA2dpState = -1;
-
-            if (getPriority(device) > BluetoothA2dp.PRIORITY_OFF &&
-                    state == BluetoothA2dp.STATE_CONNECTED) {
-                // We have connected or attempting to connect.
-                // Bump priority
-                setPriority(device, BluetoothA2dp.PRIORITY_AUTO_CONNECT);
-                // We will only have 1 device with AUTO_CONNECT priority
-                // To be backward compatible set everyone else to have PRIORITY_ON
-                adjustOtherSinkPriorities(device);
-            }
-
-            int delay = mAudioManager.setBluetoothA2dpDeviceConnectionState(device, state);
-
-            mWakeLock.acquire();
-            mIntentBroadcastHandler.sendMessageDelayed(mIntentBroadcastHandler.obtainMessage(
-                                                            MSG_CONNECTION_STATE_CHANGED,
-                                                            prevState,
-                                                            state,
-                                                            device),
-                                                       delay);
-        }
-    }
-
-    private void handleSinkPlayingStateChange(BluetoothDevice device, int state, int prevState) {
-        Intent intent = new Intent(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
-        intent.putExtra(BluetoothProfile.EXTRA_STATE, state);
-        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-
-        if (DBG) log("A2DP Playing state : device: " + device + " State:" + prevState + "->" + state);
-    }
-
-    private void adjustOtherSinkPriorities(BluetoothDevice connectedDevice) {
-        for (BluetoothDevice device : mAdapter.getBondedDevices()) {
-            if (getPriority(device) >= BluetoothA2dp.PRIORITY_AUTO_CONNECT &&
-                !device.equals(connectedDevice)) {
-                setPriority(device, BluetoothA2dp.PRIORITY_ON);
-            }
-        }
-    }
-
-    private boolean checkSinkSuspendState(int state) {
-        boolean result = true;
-
-        if (state != mTargetA2dpState) {
-            if (state == BluetoothA2dp.STATE_PLAYING &&
-                mTargetA2dpState == BluetoothA2dp.STATE_CONNECTED) {
-                mAudioManager.setParameters("A2dpSuspended=true");
-            } else if (state == BluetoothA2dp.STATE_CONNECTED &&
-                mTargetA2dpState == BluetoothA2dp.STATE_PLAYING) {
-                mAudioManager.setParameters("A2dpSuspended=false");
-            } else {
-                result = false;
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Called by native code for the async response to a Connect
-     * method call to org.bluez.AudioSink.
-     *
-     * @param deviceObjectPath the object path for the connecting device
-     * @param result true on success; false on error
-     */
-    private void onConnectSinkResult(String deviceObjectPath, boolean result) {
-        // If the call was a success, ignore we will update the state
-        // when we a Sink Property Change
-        if (!result) {
-            if (deviceObjectPath != null) {
-                String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
-                if (address == null) return;
-                BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                int state = getConnectionState(device);
-                handleSinkStateChange(device, state, BluetoothA2dp.STATE_DISCONNECTED);
-            }
-        }
-    }
-
-    /** Handles A2DP connection state change intent broadcasts. */
-    private class IntentBroadcastHandler extends Handler {
-
-        private void onConnectionStateChanged(BluetoothDevice device, int prevState, int state) {
-            Intent intent = new Intent(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
-            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-            intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
-            intent.putExtra(BluetoothProfile.EXTRA_STATE, state);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-
-            if (DBG) log("A2DP state : device: " + device + " State:" + prevState + "->" + state);
-
-            mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.A2DP, state,
-                                                        prevState);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_CONNECTION_STATE_CHANGED:
-                    onConnectionStateChanged((BluetoothDevice) msg.obj, msg.arg1, msg.arg2);
-                    mWakeLock.release();
-                    break;
-            }
-        }
-    }
-
-    @Override
-    protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
-
-        if (mAudioDevices.isEmpty()) return;
-        pw.println("Cached audio devices:");
-        for (BluetoothDevice device : mAudioDevices.keySet()) {
-            int state = mAudioDevices.get(device);
-            pw.println(device + " " + BluetoothA2dp.stateToString(state));
-        }
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-
-    private native boolean initNative();
-    private native void cleanupNative();
-    private synchronized native boolean connectSinkNative(String path);
-    private synchronized native boolean disconnectSinkNative(String path);
-    private synchronized native boolean suspendSinkNative(String path);
-    private synchronized native boolean resumeSinkNative(String path);
-    private synchronized native Object []getSinkPropertiesNative(String path);
-    private synchronized native boolean avrcpVolumeUpNative(String path);
-    private synchronized native boolean avrcpVolumeDownNative(String path);
-}
diff --git a/core/java/android/server/BluetoothAdapterProperties.java b/core/java/android/server/BluetoothAdapterProperties.java
deleted file mode 100644
index 9723f60..0000000
--- a/core/java/android/server/BluetoothAdapterProperties.java
+++ /dev/null
@@ -1,105 +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.
- */
-
-package android.server;
-
-import android.content.Context;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.Map;
-
-class BluetoothAdapterProperties {
-
-    private static final String TAG = "BluetoothAdapterProperties";
-
-    private final Map<String, String> mPropertiesMap;
-    private final Context mContext;
-    private final BluetoothService mService;
-
-    BluetoothAdapterProperties(Context context, BluetoothService service) {
-        mPropertiesMap = new HashMap<String, String>();
-        mContext = context;
-        mService = service;
-    }
-
-    synchronized String getProperty(String name) {
-        if (mPropertiesMap.isEmpty()) {
-            getAllProperties();
-        }
-        return mPropertiesMap.get(name);
-    }
-
-    String getObjectPath() {
-        return getProperty("ObjectPath");
-    }
-
-    synchronized void clear() {
-        mPropertiesMap.clear();
-    }
-
-    synchronized boolean isEmpty() {
-        return mPropertiesMap.isEmpty();
-    }
-
-    synchronized void setProperty(String name, String value) {
-        mPropertiesMap.put(name, value);
-    }
-
-    synchronized void getAllProperties() {
-        mContext.enforceCallingOrSelfPermission(
-                BluetoothService.BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        mPropertiesMap.clear();
-
-        String properties[] = (String[]) mService
-                .getAdapterPropertiesNative();
-        // The String Array consists of key-value pairs.
-        if (properties == null) {
-            Log.e(TAG, "*Error*: GetAdapterProperties returned NULL");
-            return;
-        }
-
-        for (int i = 0; i < properties.length; i++) {
-            String name = properties[i];
-            String newValue = null;
-            if (name == null) {
-                Log.e(TAG, "Error:Adapter Property at index " + i + " is null");
-                continue;
-            }
-            if (name.equals("Devices") || name.equals("UUIDs")) {
-                StringBuilder str = new StringBuilder();
-                int len = Integer.valueOf(properties[++i]);
-                for (int j = 0; j < len; j++) {
-                    str.append(properties[++i]);
-                    str.append(",");
-                }
-                if (len > 0) {
-                    newValue = str.toString();
-                }
-            } else {
-                newValue = properties[++i];
-            }
-            mPropertiesMap.put(name, newValue);
-        }
-
-        // Add adapter object path property.
-        String adapterPath = mService.getAdapterPathNative();
-        if (adapterPath != null) {
-            mPropertiesMap.put("ObjectPath", adapterPath + "/dev_");
-        }
-    }
-}
diff --git a/core/java/android/server/BluetoothAdapterStateMachine.java b/core/java/android/server/BluetoothAdapterStateMachine.java
deleted file mode 100644
index 1de1839..0000000
--- a/core/java/android/server/BluetoothAdapterStateMachine.java
+++ /dev/null
@@ -1,822 +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.
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.IBluetoothStateChangeCallback;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.Message;
-import android.os.RemoteException;
-import android.provider.Settings;
-import android.util.Log;
-
-import com.android.internal.util.IState;
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-
-import java.io.PrintWriter;
-
-/**
- * Bluetooth Adapter StateMachine
- * All the states are at the same level, ie, no hierarchy.
- *                         (BluetootOn)<----------------------<-
- *                           |    ^    -------------------->-  |
- *                           |    |                         |  |
- *            USER_TURN_OFF  |    | SCAN_MODE_CHANGED    m1 |  | USER_TURN_ON
- *         AIRPLANE_MODE_ON  |    |                         |  |
- *                           V    |                         |  |
- *                         (Switching)                   (PerProcessState)
- *                           |    ^                         |  |
- *     POWER_STATE_CHANGED & |    | TURN_ON(_CONTINUE)      |  |
- * ALL_DEVICES_DISCONNECTED  |    |                     m2  |  |
- *                           V    |------------------------<   | SCAN_MODE_CHANGED
- *                          (HotOff)-------------------------->- PER_PROCESS_TURN_ON
- *                           /    ^
- *                          /     |  SERVICE_RECORD_LOADED
- *                         |      |
- *              TURN_COLD  |   (Warmup)
- *                         \      ^
- *                          \     |  TURN_HOT/TURN_ON
- *                           |    |  AIRPLANE_MODE_OFF(when Bluetooth was on before)
- *                           V    |
- *                           (PowerOff)   <----- initial state
- *
- * Legend:
- * m1 = TURN_HOT
- * m2 = Transition to HotOff when number of process wanting BT on is 0.
- *      POWER_STATE_CHANGED will make the transition.
- * Note:
- * The diagram above shows all the states and messages that trigger normal state changes.
- * The diagram above does not capture everything:
- *   The diagram does not capture following messages.
- *   - messages that do not trigger state changes
- *     For example, PER_PROCESS_TURN_ON received in BluetoothOn state
- *   - unhandled messages
- *     For example, USER_TURN_ON received in BluetoothOn state
- *   - timeout messages
- *   The diagram does not capture error conditions and state recoveries.
- *   - For example POWER_STATE_CHANGED received in BluetoothOn state
- */
-final class BluetoothAdapterStateMachine extends StateMachine {
-    private static final String TAG = "BluetoothAdapterStateMachine";
-    private static final boolean DBG = false;
-
-    // Message(what) to take an action
-    //
-    // We get this message when user tries to turn on BT
-    static final int USER_TURN_ON = 1;
-    // We get this message when user tries to turn off BT
-    static final int USER_TURN_OFF = 2;
-    // Per process enable / disable messages
-    static final int PER_PROCESS_TURN_ON = 3;
-    static final int PER_PROCESS_TURN_OFF = 4;
-
-    // Turn on Bluetooth Module, Load firmware, and do all the preparation
-    // needed to get the Bluetooth Module ready but keep it not discoverable
-    // and not connectable. This way the Bluetooth Module can be quickly
-    // switched on if needed
-    static final int TURN_HOT = 5;
-
-    // Message(what) to report a event that the state machine need to respond to
-    //
-    // Event indicates sevice records have been loaded
-    static final int SERVICE_RECORD_LOADED = 51;
-    // Event indicates all the remote Bluetooth devices has been disconnected
-    static final int ALL_DEVICES_DISCONNECTED = 52;
-    // Event indicates the Bluetooth scan mode has changed
-    static final int SCAN_MODE_CHANGED = 53;
-    // Event indicates the powered state has changed
-    static final int POWER_STATE_CHANGED = 54;
-    // Event indicates airplane mode is turned on
-    static final int AIRPLANE_MODE_ON = 55;
-    // Event indicates airplane mode is turned off
-    static final int AIRPLANE_MODE_OFF = 56;
-
-    // private internal messages
-    //
-    // USER_TURN_ON is changed to TURN_ON_CONTINUE after we broadcast the
-    // state change intent so that we will not broadcast the intent again in
-    // other state
-    private static final int TURN_ON_CONTINUE = 101;
-    // Unload firmware, turning off Bluetooth module power
-    private static final int TURN_COLD = 102;
-    // Device disconnecting timeout happens
-    private static final int DEVICES_DISCONNECT_TIMEOUT = 103;
-    // Prepare Bluetooth timeout happens
-    private static final int PREPARE_BLUETOOTH_TIMEOUT = 104;
-    // Bluetooth turn off wait timeout happens
-    private static final int TURN_OFF_TIMEOUT = 105;
-    // Bluetooth device power off wait timeout happens
-    private static final int POWER_DOWN_TIMEOUT = 106;
-
-    private Context mContext;
-    private BluetoothService mBluetoothService;
-    private BluetoothEventLoop mEventLoop;
-
-    private BluetoothOn mBluetoothOn;
-    private Switching mSwitching;
-    private HotOff mHotOff;
-    private WarmUp mWarmUp;
-    private PowerOff mPowerOff;
-    private PerProcessState mPerProcessState;
-
-    // this is the BluetoothAdapter state that reported externally
-    private int mPublicState;
-    // When turning off, broadcast STATE_OFF in the last HotOff state
-    // This is because we do HotOff -> PowerOff -> HotOff for USER_TURN_OFF
-    private boolean mDelayBroadcastStateOff;
-
-    // timeout value waiting for all the devices to be disconnected
-    private static final int DEVICES_DISCONNECT_TIMEOUT_TIME = 3000;
-
-    private static final int PREPARE_BLUETOOTH_TIMEOUT_TIME = 10000;
-
-    private static final int TURN_OFF_TIMEOUT_TIME = 5000;
-    private static final int POWER_DOWN_TIMEOUT_TIME = 20;
-
-    BluetoothAdapterStateMachine(Context context, BluetoothService bluetoothService,
-                                 BluetoothAdapter bluetoothAdapter) {
-        super(TAG);
-        mContext = context;
-        mBluetoothService = bluetoothService;
-        mEventLoop = new BluetoothEventLoop(context, bluetoothAdapter, bluetoothService, this);
-
-        mBluetoothOn = new BluetoothOn();
-        mSwitching = new Switching();
-        mHotOff = new HotOff();
-        mWarmUp = new WarmUp();
-        mPowerOff = new PowerOff();
-        mPerProcessState = new PerProcessState();
-
-        addState(mBluetoothOn);
-        addState(mSwitching);
-        addState(mHotOff);
-        addState(mWarmUp);
-        addState(mPowerOff);
-        addState(mPerProcessState);
-
-        setInitialState(mPowerOff);
-        mPublicState = BluetoothAdapter.STATE_OFF;
-        mDelayBroadcastStateOff = false;
-    }
-
-    /**
-     * Bluetooth module's power is off, firmware is not loaded.
-     */
-    private class PowerOff extends State {
-        @Override
-        public void enter() {
-            if (DBG) log("Enter PowerOff: " + getCurrentMessage().what);
-        }
-        @Override
-        public boolean processMessage(Message message) {
-            log("PowerOff process message: " + message.what);
-
-            boolean retValue = HANDLED;
-            switch(message.what) {
-                case USER_TURN_ON:
-                    // starts turning on BT module, broadcast this out
-                    broadcastState(BluetoothAdapter.STATE_TURNING_ON);
-                    transitionTo(mWarmUp);
-                    if (prepareBluetooth()) {
-                        // this is user request, save the setting
-                        if ((Boolean) message.obj) {
-                            persistSwitchSetting(true);
-                        }
-                        // We will continue turn the BT on all the way to the BluetoothOn state
-                        deferMessage(obtainMessage(TURN_ON_CONTINUE));
-                    } else {
-                        Log.e(TAG, "failed to prepare bluetooth, abort turning on");
-                        transitionTo(mPowerOff);
-                        broadcastState(BluetoothAdapter.STATE_OFF);
-                    }
-                    break;
-                case TURN_HOT:
-                    if (prepareBluetooth()) {
-                        transitionTo(mWarmUp);
-                    }
-                    break;
-                case AIRPLANE_MODE_OFF:
-                    if (getBluetoothPersistedSetting()) {
-                        // starts turning on BT module, broadcast this out
-                        broadcastState(BluetoothAdapter.STATE_TURNING_ON);
-                        transitionTo(mWarmUp);
-                        if (prepareBluetooth()) {
-                            // We will continue turn the BT on all the way to the BluetoothOn state
-                            deferMessage(obtainMessage(TURN_ON_CONTINUE));
-                            transitionTo(mWarmUp);
-                        } else {
-                            Log.e(TAG, "failed to prepare bluetooth, abort turning on");
-                            transitionTo(mPowerOff);
-                            broadcastState(BluetoothAdapter.STATE_OFF);
-                        }
-                    } else if (mContext.getResources().getBoolean
-                            (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
-                        sendMessage(TURN_HOT);
-                    }
-                    break;
-                case PER_PROCESS_TURN_ON:
-                    if (prepareBluetooth()) {
-                        transitionTo(mWarmUp);
-                    }
-                    deferMessage(obtainMessage(PER_PROCESS_TURN_ON));
-                    break;
-                case PER_PROCESS_TURN_OFF:
-                    perProcessCallback(false, (IBluetoothStateChangeCallback) message.obj);
-                    break;
-                case USER_TURN_OFF:
-                    Log.w(TAG, "PowerOff received: " + message.what);
-                case AIRPLANE_MODE_ON: // ignore
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return retValue;
-        }
-
-        /**
-         * Turn on Bluetooth Module, Load firmware, and do all the preparation
-         * needed to get the Bluetooth Module ready but keep it not discoverable
-         * and not connectable.
-         * The last step of this method sets up the local service record DB.
-         * There will be a event reporting the status of the SDP setup.
-         */
-        private boolean prepareBluetooth() {
-            if (mBluetoothService.enableNative() != 0) {
-                return false;
-            }
-
-            // try to start event loop, give 2 attempts
-            int retryCount = 2;
-            boolean eventLoopStarted = false;
-            while ((retryCount-- > 0) && !eventLoopStarted) {
-                mEventLoop.start();
-                // it may take a moment for the other thread to do its
-                // thing.  Check periodically for a while.
-                int pollCount = 5;
-                while ((pollCount-- > 0) && !eventLoopStarted) {
-                    if (mEventLoop.isEventLoopRunning()) {
-                        eventLoopStarted = true;
-                        break;
-                    }
-                    try {
-                        Thread.sleep(100);
-                    } catch (InterruptedException e) {
-                        log("prepareBluetooth sleep interrupted: " + pollCount);
-                        break;
-                    }
-                }
-            }
-
-            if (!eventLoopStarted) {
-                mBluetoothService.disableNative();
-                return false;
-            }
-
-            // get BluetoothService ready
-            if (!mBluetoothService.prepareBluetooth()) {
-                mEventLoop.stop();
-                mBluetoothService.disableNative();
-                return false;
-            }
-
-            sendMessageDelayed(PREPARE_BLUETOOTH_TIMEOUT, PREPARE_BLUETOOTH_TIMEOUT_TIME);
-            return true;
-        }
-    }
-
-    /**
-     * Turning on Bluetooth module's power, loading firmware, starting
-     * event loop thread to listen on Bluetooth module event changes.
-     */
-    private class WarmUp extends State {
-
-        @Override
-        public void enter() {
-            if (DBG) log("Enter WarmUp: " + getCurrentMessage().what);
-        }
-
-        @Override
-        public boolean processMessage(Message message) {
-            log("WarmUp process message: " + message.what);
-
-            boolean retValue = HANDLED;
-            switch(message.what) {
-                case SERVICE_RECORD_LOADED:
-                    removeMessages(PREPARE_BLUETOOTH_TIMEOUT);
-                    transitionTo(mHotOff);
-                    if (mDelayBroadcastStateOff) {
-                        broadcastState(BluetoothAdapter.STATE_OFF);
-                        mDelayBroadcastStateOff = false;
-                    }
-                    break;
-                case PREPARE_BLUETOOTH_TIMEOUT:
-                    Log.e(TAG, "Bluetooth adapter SDP failed to load");
-                    shutoffBluetooth();
-                    transitionTo(mPowerOff);
-                    broadcastState(BluetoothAdapter.STATE_OFF);
-                    break;
-                case USER_TURN_ON: // handle this at HotOff state
-                case TURN_ON_CONTINUE: // Once in HotOff state, continue turn bluetooth
-                                       // on to the BluetoothOn state
-                case AIRPLANE_MODE_ON:
-                case AIRPLANE_MODE_OFF:
-                case PER_PROCESS_TURN_ON:
-                case PER_PROCESS_TURN_OFF:
-                    deferMessage(message);
-                    break;
-                case USER_TURN_OFF:
-                    Log.w(TAG, "WarmUp received: " + message.what);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return retValue;
-        }
-
-    }
-
-    /**
-     * Bluetooth Module has powered, firmware loaded, event loop started,
-     * SDP loaded, but the modules stays non-discoverable and
-     * non-connectable.
-     */
-    private class HotOff extends State {
-        @Override
-        public void enter() {
-            if (DBG) log("Enter HotOff: " + getCurrentMessage().what);
-        }
-
-        @Override
-        public boolean processMessage(Message message) {
-            log("HotOff process message: " + message.what);
-
-            boolean retValue = HANDLED;
-            switch(message.what) {
-                case USER_TURN_ON:
-                    broadcastState(BluetoothAdapter.STATE_TURNING_ON);
-                    if ((Boolean) message.obj) {
-                        persistSwitchSetting(true);
-                    }
-                    // let it fall to TURN_ON_CONTINUE:
-                    //$FALL-THROUGH$
-                case TURN_ON_CONTINUE:
-                    mBluetoothService.switchConnectable(true);
-                    transitionTo(mSwitching);
-                    break;
-                case AIRPLANE_MODE_ON:
-                case TURN_COLD:
-                    shutoffBluetooth();
-                    // we cannot go to power off state yet, we need wait for the Bluetooth
-                    // device power off. Unfortunately the stack does not give a event back
-                    // so we wait a little bit here
-                    sendMessageDelayed(POWER_DOWN_TIMEOUT,
-                                       POWER_DOWN_TIMEOUT_TIME);
-                    break;
-                case POWER_DOWN_TIMEOUT:
-                    transitionTo(mPowerOff);
-                    if (!mDelayBroadcastStateOff) {
-                        broadcastState(BluetoothAdapter.STATE_OFF);
-                    }
-                    break;
-                case AIRPLANE_MODE_OFF:
-                    if (getBluetoothPersistedSetting()) {
-                        broadcastState(BluetoothAdapter.STATE_TURNING_ON);
-                        transitionTo(mSwitching);
-                        mBluetoothService.switchConnectable(true);
-                    }
-                    break;
-                case PER_PROCESS_TURN_ON:
-                    transitionTo(mPerProcessState);
-
-                    // Resend the PER_PROCESS_TURN_ON message so that the callback
-                    // can be sent through.
-                    deferMessage(message);
-
-                    mBluetoothService.switchConnectable(true);
-                    break;
-                case PER_PROCESS_TURN_OFF:
-                    perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
-                    break;
-                case USER_TURN_OFF: // ignore
-                    break;
-                case POWER_STATE_CHANGED:
-                    if ((Boolean) message.obj) {
-                        recoverStateMachine(TURN_HOT, null);
-                    }
-                    break;
-                case TURN_HOT:
-                    deferMessage(message);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return retValue;
-        }
-
-    }
-
-    private class Switching extends State {
-
-        @Override
-        public void enter() {
-            if (DBG) log("Enter Switching: " + getCurrentMessage().what);
-        }
-        @Override
-        public boolean processMessage(Message message) {
-            log("Switching process message: " + message.what);
-
-            boolean retValue = HANDLED;
-            switch(message.what) {
-                case SCAN_MODE_CHANGED:
-                    // This event matches mBluetoothService.switchConnectable action
-                    if (mPublicState == BluetoothAdapter.STATE_TURNING_ON) {
-                        // set pairable if it's not
-                        mBluetoothService.setPairable();
-                        mBluetoothService.initBluetoothAfterTurningOn();
-                        transitionTo(mBluetoothOn);
-                        broadcastState(BluetoothAdapter.STATE_ON);
-                        // run bluetooth now that it's turned on
-                        // Note runBluetooth should be called only in adapter STATE_ON
-                        mBluetoothService.runBluetooth();
-                    }
-                    break;
-                case POWER_STATE_CHANGED:
-                    removeMessages(TURN_OFF_TIMEOUT);
-                    if (!((Boolean) message.obj)) {
-                        if (mPublicState == BluetoothAdapter.STATE_TURNING_OFF) {
-                            transitionTo(mHotOff);
-                            mBluetoothService.finishDisable();
-                            mBluetoothService.cleanupAfterFinishDisable();
-                            deferMessage(obtainMessage(TURN_COLD));
-                            if (mContext.getResources().getBoolean
-                                (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch) &&
-                                !mBluetoothService.isAirplaneModeOn()) {
-                                deferMessage(obtainMessage(TURN_HOT));
-                                mDelayBroadcastStateOff = true;
-                            }
-                        }
-                    } else {
-                        if (mPublicState != BluetoothAdapter.STATE_TURNING_ON) {
-                            if (mContext.getResources().getBoolean
-                            (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
-                                recoverStateMachine(TURN_HOT, null);
-                            } else {
-                                recoverStateMachine(TURN_COLD, null);
-                            }
-                        }
-                    }
-                    break;
-                case ALL_DEVICES_DISCONNECTED:
-                    removeMessages(DEVICES_DISCONNECT_TIMEOUT);
-                    mBluetoothService.switchConnectable(false);
-                    sendMessageDelayed(TURN_OFF_TIMEOUT, TURN_OFF_TIMEOUT_TIME);
-                    break;
-                case DEVICES_DISCONNECT_TIMEOUT:
-                    sendMessage(ALL_DEVICES_DISCONNECTED);
-                    // reset the hardware for error recovery
-                    Log.e(TAG, "Devices failed to disconnect, reseting...");
-                    deferMessage(obtainMessage(TURN_COLD));
-                    if (mContext.getResources().getBoolean
-                        (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
-                        deferMessage(obtainMessage(TURN_HOT));
-                    }
-                    break;
-                case TURN_OFF_TIMEOUT:
-                    transitionTo(mHotOff);
-                    finishSwitchingOff();
-                    // reset the hardware for error recovery
-                    Log.e(TAG, "Devices failed to power down, reseting...");
-                    deferMessage(obtainMessage(TURN_COLD));
-                    if (mContext.getResources().getBoolean
-                        (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
-                        deferMessage(obtainMessage(TURN_HOT));
-                    }
-                    break;
-                case USER_TURN_ON:
-                case AIRPLANE_MODE_OFF:
-                case AIRPLANE_MODE_ON:
-                case PER_PROCESS_TURN_ON:
-                case PER_PROCESS_TURN_OFF:
-                case USER_TURN_OFF:
-                    deferMessage(message);
-                    break;
-
-                default:
-                    return NOT_HANDLED;
-            }
-            return retValue;
-        }
-    }
-
-    private class BluetoothOn extends State {
-
-        @Override
-        public void enter() {
-            if (DBG) log("Enter BluetoothOn: " + getCurrentMessage().what);
-        }
-        @Override
-        public boolean processMessage(Message message) {
-            log("BluetoothOn process message: " + message.what);
-
-            boolean retValue = HANDLED;
-            switch(message.what) {
-                case USER_TURN_OFF:
-                    if ((Boolean) message.obj) {
-                        persistSwitchSetting(false);
-                    }
-
-                    if (mBluetoothService.isDiscovering()) {
-                        mBluetoothService.cancelDiscovery();
-                    }
-                    if (!mBluetoothService.isApplicationStateChangeTrackerEmpty()) {
-                        transitionTo(mPerProcessState);
-                        deferMessage(obtainMessage(TURN_HOT));
-                        break;
-                    }
-                    //$FALL-THROUGH$ to AIRPLANE_MODE_ON
-                case AIRPLANE_MODE_ON:
-                    broadcastState(BluetoothAdapter.STATE_TURNING_OFF);
-                    transitionTo(mSwitching);
-                    if (mBluetoothService.getAdapterConnectionState() !=
-                        BluetoothAdapter.STATE_DISCONNECTED) {
-                        mBluetoothService.disconnectDevices();
-                        sendMessageDelayed(DEVICES_DISCONNECT_TIMEOUT,
-                                           DEVICES_DISCONNECT_TIMEOUT_TIME);
-                    } else {
-                        mBluetoothService.switchConnectable(false);
-                        sendMessageDelayed(TURN_OFF_TIMEOUT, TURN_OFF_TIMEOUT_TIME);
-                    }
-
-                    if (message.what == AIRPLANE_MODE_ON || mBluetoothService.isAirplaneModeOn()) {
-                        // We inform all the per process callbacks
-                        allProcessesCallback(false);
-                    }
-                    break;
-                case AIRPLANE_MODE_OFF:
-                case USER_TURN_ON:
-                    Log.w(TAG, "BluetoothOn received: " + message.what);
-                    break;
-                case PER_PROCESS_TURN_ON:
-                    perProcessCallback(true, (IBluetoothStateChangeCallback)message.obj);
-                    break;
-                case PER_PROCESS_TURN_OFF:
-                    perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
-                    break;
-                case POWER_STATE_CHANGED:
-                    if ((Boolean) message.obj) {
-                        // reset the state machine and send it TURN_ON_CONTINUE message
-                        recoverStateMachine(USER_TURN_ON, false);
-                    }
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return retValue;
-        }
-
-    }
-
-
-    private class PerProcessState extends State {
-        IBluetoothStateChangeCallback mCallback = null;
-        boolean isTurningOn = false;
-
-        @Override
-        public void enter() {
-            int what = getCurrentMessage().what;
-            if (DBG) log("Enter PerProcessState: " + what);
-
-            if (what == PER_PROCESS_TURN_ON) {
-                isTurningOn = true;
-            } else if (what == USER_TURN_OFF) {
-                isTurningOn = false;
-            } else {
-                Log.e(TAG, "enter PerProcessState: wrong msg: " + what);
-            }
-        }
-
-        @Override
-        public boolean processMessage(Message message) {
-            log("PerProcessState process message: " + message.what);
-
-            boolean retValue = HANDLED;
-            switch (message.what) {
-                case PER_PROCESS_TURN_ON:
-                    mCallback = (IBluetoothStateChangeCallback)getCurrentMessage().obj;
-
-                    // If this is not the first application call the callback.
-                    if (mBluetoothService.getNumberOfApplicationStateChangeTrackers() > 1) {
-                        perProcessCallback(true, mCallback);
-                    }
-                    break;
-                case SCAN_MODE_CHANGED:
-                    if (isTurningOn) {
-                        perProcessCallback(true, mCallback);
-                        isTurningOn = false;
-                    }
-                    break;
-                case POWER_STATE_CHANGED:
-                    removeMessages(TURN_OFF_TIMEOUT);
-                    if (!((Boolean) message.obj)) {
-                        transitionTo(mHotOff);
-                        if (!mContext.getResources().getBoolean
-                            (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
-                            deferMessage(obtainMessage(TURN_COLD));
-                        }
-                    } else {
-                        if (!isTurningOn) {
-                            recoverStateMachine(TURN_COLD, null);
-                            for (IBluetoothStateChangeCallback c:
-                                     mBluetoothService.getApplicationStateChangeCallbacks()) {
-                                perProcessCallback(false, c);
-                                deferMessage(obtainMessage(PER_PROCESS_TURN_ON, c));
-                            }
-                        }
-                    }
-                    break;
-                case TURN_OFF_TIMEOUT:
-                    transitionTo(mHotOff);
-                    Log.e(TAG, "Power-down timed out, resetting...");
-                    deferMessage(obtainMessage(TURN_COLD));
-                    if (mContext.getResources().getBoolean
-                        (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
-                        deferMessage(obtainMessage(TURN_HOT));
-                    }
-                    break;
-                case USER_TURN_ON:
-                    broadcastState(BluetoothAdapter.STATE_TURNING_ON);
-                    persistSwitchSetting(true);
-                    mBluetoothService.initBluetoothAfterTurningOn();
-                    transitionTo(mBluetoothOn);
-                    broadcastState(BluetoothAdapter.STATE_ON);
-                    // run bluetooth now that it's turned on
-                    mBluetoothService.runBluetooth();
-                    break;
-                case TURN_HOT:
-                    broadcastState(BluetoothAdapter.STATE_TURNING_OFF);
-                    if (mBluetoothService.getAdapterConnectionState() !=
-                        BluetoothAdapter.STATE_DISCONNECTED) {
-                        mBluetoothService.disconnectDevices();
-                        sendMessageDelayed(DEVICES_DISCONNECT_TIMEOUT,
-                                           DEVICES_DISCONNECT_TIMEOUT_TIME);
-                        break;
-                    }
-                    //$FALL-THROUGH$ all devices are already disconnected
-                case ALL_DEVICES_DISCONNECTED:
-                    removeMessages(DEVICES_DISCONNECT_TIMEOUT);
-                    finishSwitchingOff();
-                    break;
-                case DEVICES_DISCONNECT_TIMEOUT:
-                    finishSwitchingOff();
-                    Log.e(TAG, "Devices fail to disconnect, reseting...");
-                    transitionTo(mHotOff);
-                    deferMessage(obtainMessage(TURN_COLD));
-                    for (IBluetoothStateChangeCallback c:
-                             mBluetoothService.getApplicationStateChangeCallbacks()) {
-                        perProcessCallback(false, c);
-                        deferMessage(obtainMessage(PER_PROCESS_TURN_ON, c));
-                    }
-                    break;
-                case PER_PROCESS_TURN_OFF:
-                    perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
-                    if (mBluetoothService.isApplicationStateChangeTrackerEmpty()) {
-                        mBluetoothService.switchConnectable(false);
-                        sendMessageDelayed(TURN_OFF_TIMEOUT, TURN_OFF_TIMEOUT_TIME);
-                    }
-                    break;
-                case AIRPLANE_MODE_ON:
-                    mBluetoothService.switchConnectable(false);
-                    sendMessageDelayed(TURN_OFF_TIMEOUT, TURN_OFF_TIMEOUT_TIME);
-                    allProcessesCallback(false);
-                    break;
-                case USER_TURN_OFF:
-                    Log.w(TAG, "PerProcessState received: " + message.what);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return retValue;
-        }
-    }
-
-    private void finishSwitchingOff() {
-        mBluetoothService.finishDisable();
-        broadcastState(BluetoothAdapter.STATE_OFF);
-        mBluetoothService.cleanupAfterFinishDisable();
-    }
-
-    private void shutoffBluetooth() {
-        mBluetoothService.shutoffBluetooth();
-        mEventLoop.stop();
-        mBluetoothService.cleanNativeAfterShutoffBluetooth();
-    }
-
-    private void perProcessCallback(boolean on, IBluetoothStateChangeCallback c) {
-        if (c == null) return;
-
-        try {
-            c.onBluetoothStateChange(on);
-        } catch (RemoteException e) {}
-    }
-
-    private void allProcessesCallback(boolean on) {
-        for (IBluetoothStateChangeCallback c:
-             mBluetoothService.getApplicationStateChangeCallbacks()) {
-            perProcessCallback(on, c);
-        }
-        if (!on) {
-            mBluetoothService.clearApplicationStateChangeTracker();
-        }
-    }
-
-    /**
-     * Return the public BluetoothAdapter state
-     */
-    int getBluetoothAdapterState() {
-        return mPublicState;
-    }
-
-    BluetoothEventLoop getBluetoothEventLoop() {
-        return mEventLoop;
-    }
-
-    private void persistSwitchSetting(boolean setOn) {
-        long origCallerIdentityToken = Binder.clearCallingIdentity();
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                               Settings.Secure.BLUETOOTH_ON,
-                               setOn ? 1 : 0);
-        Binder.restoreCallingIdentity(origCallerIdentityToken);
-    }
-
-    private boolean getBluetoothPersistedSetting() {
-        ContentResolver contentResolver = mContext.getContentResolver();
-        return (Settings.Secure.getInt(contentResolver,
-                                       Settings.Secure.BLUETOOTH_ON, 0) > 0);
-    }
-
-    private void broadcastState(int newState) {
-
-        log("Bluetooth state " + mPublicState + " -> " + newState);
-        if (mPublicState == newState) {
-            return;
-        }
-
-        Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
-        intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, mPublicState);
-        intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
-        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        mPublicState = newState;
-
-        mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
-    }
-
-    /**
-     * bluetoothd has crashed and recovered, the adapter state machine has to
-     * reset itself and try to return to previous state
-     */
-    private void recoverStateMachine(int what, Object obj) {
-        Log.e(TAG, "Get unexpected power on event, reset with: " + what);
-        transitionTo(mHotOff);
-        deferMessage(obtainMessage(TURN_COLD));
-        deferMessage(obtainMessage(what, obj));
-    }
-
-    private void dump(PrintWriter pw) {
-        IState currentState = getCurrentState();
-        if (currentState == mPowerOff) {
-            pw.println("Bluetooth OFF - power down\n");
-        } else if (currentState == mWarmUp) {
-            pw.println("Bluetooth OFF - warm up\n");
-        } else if (currentState == mHotOff) {
-            pw.println("Bluetooth OFF - hot but off\n");
-        } else if (currentState == mSwitching) {
-            pw.println("Bluetooth Switching\n");
-        } else if (currentState == mBluetoothOn) {
-            pw.println("Bluetooth ON\n");
-        } else {
-            pw.println("ERROR: Bluetooth UNKNOWN STATE ");
-        }
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-}
diff --git a/core/java/android/server/BluetoothBondState.java b/core/java/android/server/BluetoothBondState.java
deleted file mode 100644
index 0446f02..0000000
--- a/core/java/android/server/BluetoothBondState.java
+++ /dev/null
@@ -1,497 +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.
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothHeadset;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.provider.Settings;
-import android.util.Log;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.DataInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Local cache of bonding state.
- * We keep our own state to track the intermediate state BONDING, which
- * bluez does not track.
- * All addresses must be passed in upper case.
- */
-class BluetoothBondState {
-    private static final String TAG = "BluetoothBondState";
-    private static final boolean DBG =  true;
-
-    private final HashMap<String, Integer> mState = new HashMap<String, Integer>();
-    private final HashMap<String, Integer> mPinAttempt = new HashMap<String, Integer>();
-
-    private static final String AUTO_PAIRING_BLACKLIST =
-        "/etc/bluetooth/auto_pairing.conf";
-    private static final String DYNAMIC_AUTO_PAIRING_BLACKLIST =
-        "/data/misc/bluetooth/dynamic_auto_pairing.conf";
-    private ArrayList<String> mAutoPairingAddressBlacklist;
-    private ArrayList<String> mAutoPairingExactNameBlacklist;
-    private ArrayList<String> mAutoPairingPartialNameBlacklist;
-    private ArrayList<String> mAutoPairingFixedPinZerosKeyboardList;
-    // Addresses added to blacklist dynamically based on usage.
-    private ArrayList<String> mAutoPairingDynamicAddressBlacklist;
-
-    // If this is an outgoing connection, store the address.
-    // There can be only 1 pending outgoing connection at a time,
-    private String mPendingOutgoingBonding;
-
-    private final Context mContext;
-    private final BluetoothService mService;
-    private final BluetoothInputProfileHandler mBluetoothInputProfileHandler;
-    private BluetoothA2dp mA2dpProxy;
-    private BluetoothHeadset mHeadsetProxy;
-
-    private ArrayList<String> mPairingRequestRcvd = new ArrayList<String>();
-
-    BluetoothBondState(Context context, BluetoothService service) {
-        mContext = context;
-        mService = service;
-        mBluetoothInputProfileHandler =
-            BluetoothInputProfileHandler.getInstance(mContext, mService);
-
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        mContext.registerReceiver(mReceiver, filter);
-        readAutoPairingData();
-    }
-
-    synchronized void setPendingOutgoingBonding(String address) {
-        mPendingOutgoingBonding = address;
-    }
-
-    public synchronized String getPendingOutgoingBonding() {
-        return mPendingOutgoingBonding;
-    }
-
-    public synchronized void initBondState() {
-        getProfileProxy();
-        loadBondState();
-    }
-
-    private void loadBondState() {
-        if (mService.getBluetoothStateInternal() !=
-                BluetoothAdapter.STATE_TURNING_ON) {
-            return;
-        }
-        String val = mService.getAdapterProperties().getProperty("Devices");
-        if (val == null) {
-            return;
-        }
-        String[] bonds = val.split(",");
-        if (bonds == null) {
-            return;
-        }
-        mState.clear();
-        if (DBG) Log.d(TAG, "found " + bonds.length + " bonded devices");
-        for (String device : bonds) {
-            mState.put(mService.getAddressFromObjectPath(device).toUpperCase(),
-                    BluetoothDevice.BOND_BONDED);
-        }
-    }
-
-    public synchronized void setBondState(String address, int state) {
-        setBondState(address, state, 0);
-    }
-
-    /** reason is ignored unless state == BOND_NOT_BONDED */
-    public synchronized void setBondState(String address, int state, int reason) {
-        if (DBG) Log.d(TAG, "setBondState " + "address" + " " + state + "reason: " + reason);
-
-        int oldState = getBondState(address);
-        if (oldState == state) {
-            return;
-        }
-
-        // Check if this was a pending outgoing bonding.
-        // If yes, reset the state.
-        if (oldState == BluetoothDevice.BOND_BONDING) {
-            if (address.equals(mPendingOutgoingBonding)) {
-                mPendingOutgoingBonding = null;
-            }
-        }
-
-        if (state == BluetoothDevice.BOND_BONDED) {
-            boolean setTrust = false;
-            if (mPairingRequestRcvd.contains(address)) setTrust = true;
-
-            mService.addProfileState(address, setTrust);
-            mPairingRequestRcvd.remove(address);
-
-        } else if (state == BluetoothDevice.BOND_BONDING) {
-            if (mA2dpProxy == null || mHeadsetProxy == null) {
-                getProfileProxy();
-            }
-        } else if (state == BluetoothDevice.BOND_NONE) {
-            mPairingRequestRcvd.remove(address);
-        }
-
-        setProfilePriorities(address, state);
-
-        if (DBG) {
-            Log.d(TAG, address + " bond state " + oldState + " -> " + state
-                + " (" + reason + ")");
-        }
-        Intent intent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mService.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, state);
-        intent.putExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, oldState);
-        if (state == BluetoothDevice.BOND_NONE) {
-            if (reason <= 0) {
-                Log.w(TAG, "setBondState() called to unbond device, but reason code is " +
-                      "invalid. Overriding reason code with BOND_RESULT_REMOVED");
-                reason = BluetoothDevice.UNBOND_REASON_REMOVED;
-            }
-            intent.putExtra(BluetoothDevice.EXTRA_REASON, reason);
-            mState.remove(address);
-        } else {
-            mState.put(address, state);
-        }
-
-        mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
-    }
-
-    public boolean isAutoPairingBlacklisted(String address) {
-        if (mAutoPairingAddressBlacklist != null) {
-            for (String blacklistAddress : mAutoPairingAddressBlacklist) {
-                if (address.startsWith(blacklistAddress)) return true;
-            }
-        }
-
-        if (mAutoPairingDynamicAddressBlacklist != null) {
-            for (String blacklistAddress: mAutoPairingDynamicAddressBlacklist) {
-                if (address.equals(blacklistAddress)) return true;
-            }
-        }
-
-        String name = mService.getRemoteName(address);
-        if (name != null) {
-            if (mAutoPairingExactNameBlacklist != null) {
-                for (String blacklistName : mAutoPairingExactNameBlacklist) {
-                    if (name.equals(blacklistName)) return true;
-                }
-            }
-
-            if (mAutoPairingPartialNameBlacklist != null) {
-                for (String blacklistName : mAutoPairingPartialNameBlacklist) {
-                    if (name.startsWith(blacklistName)) return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    public boolean isFixedPinZerosAutoPairKeyboard(String address) {
-        // Note: the meaning of blacklist is reversed in this case.
-        // If its in the list, we can go ahead and auto pair since
-        // by default keyboard should have a variable PIN that we don't
-        // auto pair using 0000.
-        if (mAutoPairingFixedPinZerosKeyboardList != null) {
-            for (String blacklistAddress : mAutoPairingFixedPinZerosKeyboardList) {
-                if (address.startsWith(blacklistAddress)) return true;
-            }
-        }
-        return false;
-    }
-
-    public synchronized int getBondState(String address) {
-        Integer state = mState.get(address);
-        if (state == null) {
-            return BluetoothDevice.BOND_NONE;
-        }
-        return state.intValue();
-    }
-
-    /*package*/ synchronized String[] listInState(int state) {
-        ArrayList<String> result = new ArrayList<String>(mState.size());
-        for (Map.Entry<String, Integer> e : mState.entrySet()) {
-            if (e.getValue().intValue() == state) {
-                result.add(e.getKey());
-            }
-        }
-        return result.toArray(new String[result.size()]);
-    }
-
-    public synchronized void addAutoPairingFailure(String address) {
-        if (mAutoPairingDynamicAddressBlacklist == null) {
-            mAutoPairingDynamicAddressBlacklist = new ArrayList<String>();
-        }
-
-        updateAutoPairingData(address);
-        mAutoPairingDynamicAddressBlacklist.add(address);
-    }
-
-    public synchronized boolean isAutoPairingAttemptsInProgress(String address) {
-        return getAttempt(address) != 0;
-    }
-
-    public synchronized void clearPinAttempts(String address) {
-        if (DBG) Log.d(TAG, "clearPinAttempts: " + address);
-
-        mPinAttempt.remove(address);
-    }
-
-    public synchronized boolean hasAutoPairingFailed(String address) {
-        if (mAutoPairingDynamicAddressBlacklist == null) return false;
-
-        return mAutoPairingDynamicAddressBlacklist.contains(address);
-    }
-
-    public synchronized int getAttempt(String address) {
-        Integer attempt = mPinAttempt.get(address);
-        if (attempt == null) {
-            return 0;
-        }
-        return attempt.intValue();
-    }
-
-    public synchronized void attempt(String address) {
-        Integer attempt = mPinAttempt.get(address);
-        int newAttempt;
-        if (attempt == null) {
-            newAttempt = 1;
-        } else {
-            newAttempt = attempt.intValue() + 1;
-        }
-        if (DBG) Log.d(TAG, "attemp newAttempt: " + newAttempt);
-
-        mPinAttempt.put(address, new Integer(newAttempt));
-    }
-
-    private void getProfileProxy() {
-        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
-
-        if (mA2dpProxy == null) {
-            bluetoothAdapter.getProfileProxy(mContext, mProfileServiceListener,
-                                             BluetoothProfile.A2DP);
-        }
-
-        if (mHeadsetProxy == null) {
-            bluetoothAdapter.getProfileProxy(mContext, mProfileServiceListener,
-                                             BluetoothProfile.HEADSET);
-        }
-    }
-
-    private void closeProfileProxy() {
-        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
-
-        if (mA2dpProxy != null) {
-            bluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, mA2dpProxy);
-        }
-
-        if (mHeadsetProxy != null) {
-            bluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mHeadsetProxy);
-        }
-    }
-
-    private BluetoothProfile.ServiceListener mProfileServiceListener =
-        new BluetoothProfile.ServiceListener() {
-
-        public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (profile == BluetoothProfile.A2DP) {
-                mA2dpProxy = (BluetoothA2dp) proxy;
-            } else if (profile == BluetoothProfile.HEADSET) {
-                mHeadsetProxy = (BluetoothHeadset) proxy;
-            }
-        }
-
-        public void onServiceDisconnected(int profile) {
-            if (profile == BluetoothProfile.A2DP) {
-                mA2dpProxy = null;
-            } else if (profile == BluetoothProfile.HEADSET) {
-                mHeadsetProxy = null;
-            }
-        }
-    };
-
-    private void copyAutoPairingData() {
-        FileInputStream in = null;
-        FileOutputStream out = null;
-        try {
-            File file = new File(DYNAMIC_AUTO_PAIRING_BLACKLIST);
-            if (file.exists()) return;
-
-            in = new FileInputStream(AUTO_PAIRING_BLACKLIST);
-            out= new FileOutputStream(DYNAMIC_AUTO_PAIRING_BLACKLIST);
-
-            byte[] buf = new byte[1024];
-            int len;
-            while ((len = in.read(buf)) > 0) {
-                out.write(buf, 0, len);
-            }
-        } catch (FileNotFoundException e) {
-            Log.e(TAG, "FileNotFoundException: copyAutoPairingData " + e);
-        } catch (IOException e) {
-            Log.e(TAG, "IOException: copyAutoPairingData " + e);
-        } finally {
-             try {
-                 if (in != null) in.close();
-                 if (out != null) out.close();
-             } catch (IOException e) {}
-        }
-    }
-
-    synchronized public void readAutoPairingData() {
-        if (mAutoPairingAddressBlacklist != null) return;
-        copyAutoPairingData();
-        FileInputStream fstream = null;
-        try {
-            fstream = new FileInputStream(DYNAMIC_AUTO_PAIRING_BLACKLIST);
-            DataInputStream in = new DataInputStream(fstream);
-            BufferedReader file = new BufferedReader(new InputStreamReader(in));
-            String line;
-            while((line = file.readLine()) != null) {
-                line = line.trim();
-                if (line.length() == 0 || line.startsWith("//")) continue;
-                String[] value = line.split("=");
-                if (value != null && value.length == 2) {
-                    String[] val = value[1].split(",");
-                    if (value[0].equalsIgnoreCase("AddressBlacklist")) {
-                        mAutoPairingAddressBlacklist =
-                            new ArrayList<String>(Arrays.asList(val));
-                    } else if (value[0].equalsIgnoreCase("ExactNameBlacklist")) {
-                        mAutoPairingExactNameBlacklist =
-                            new ArrayList<String>(Arrays.asList(val));
-                    } else if (value[0].equalsIgnoreCase("PartialNameBlacklist")) {
-                        mAutoPairingPartialNameBlacklist =
-                            new ArrayList<String>(Arrays.asList(val));
-                    } else if (value[0].equalsIgnoreCase("FixedPinZerosKeyboardBlacklist")) {
-                        mAutoPairingFixedPinZerosKeyboardList =
-                            new ArrayList<String>(Arrays.asList(val));
-                    } else if (value[0].equalsIgnoreCase("DynamicAddressBlacklist")) {
-                        mAutoPairingDynamicAddressBlacklist =
-                            new ArrayList<String>(Arrays.asList(val));
-                    } else {
-                        Log.e(TAG, "Error parsing Auto pairing blacklist file");
-                    }
-                }
-            }
-        } catch (FileNotFoundException e) {
-            Log.e(TAG, "FileNotFoundException: readAutoPairingData " + e);
-        } catch (IOException e) {
-            Log.e(TAG, "IOException: readAutoPairingData " + e);
-        } finally {
-            if (fstream != null) {
-                try {
-                    fstream.close();
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
-        }
-    }
-
-    // This function adds a bluetooth address to the auto pairing blacklist
-    // file. These addresses are added to DynamicAddressBlacklistSection
-    private void updateAutoPairingData(String address) {
-        BufferedWriter out = null;
-        try {
-            out = new BufferedWriter(new FileWriter(DYNAMIC_AUTO_PAIRING_BLACKLIST, true));
-            StringBuilder str = new StringBuilder();
-            if (mAutoPairingDynamicAddressBlacklist.size() == 0) {
-                str.append("DynamicAddressBlacklist=");
-            }
-            str.append(address);
-            str.append(",");
-            out.write(str.toString());
-        } catch (FileNotFoundException e) {
-            Log.e(TAG, "FileNotFoundException: updateAutoPairingData " + e);
-        } catch (IOException e) {
-            Log.e(TAG, "IOException: updateAutoPairingData " + e);
-        } finally {
-            if (out != null) {
-                try {
-                    out.close();
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
-        }
-    }
-
-    // Set service priority of Hid, A2DP and Headset profiles depending on
-    // the bond state change
-    private void setProfilePriorities(String address, int state) {
-        BluetoothDevice remoteDevice = mService.getRemoteDevice(address);
-        // HID is handled by BluetoothService
-        mBluetoothInputProfileHandler.setInitialInputDevicePriority(remoteDevice, state);
-
-        // Set service priority of A2DP and Headset
-        // We used to do the priority change in the 2 services after the broadcast
-        //   intent reach them. But that left a small time gap that could reject
-        //   incoming connection due to undefined priorities.
-        if (state == BluetoothDevice.BOND_BONDED) {
-            if (mA2dpProxy != null &&
-                  mA2dpProxy.getPriority(remoteDevice) == BluetoothProfile.PRIORITY_UNDEFINED) {
-                mA2dpProxy.setPriority(remoteDevice, BluetoothProfile.PRIORITY_ON);
-            }
-
-            if (mHeadsetProxy != null &&
-                  mHeadsetProxy.getPriority(remoteDevice) == BluetoothProfile.PRIORITY_UNDEFINED) {
-                mHeadsetProxy.setPriority(remoteDevice, BluetoothProfile.PRIORITY_ON);
-            }
-        } else if (state == BluetoothDevice.BOND_NONE) {
-            if (mA2dpProxy != null) {
-                mA2dpProxy.setPriority(remoteDevice, BluetoothProfile.PRIORITY_UNDEFINED);
-            }
-            if (mHeadsetProxy != null) {
-                mHeadsetProxy.setPriority(remoteDevice, BluetoothProfile.PRIORITY_UNDEFINED);
-            }
-        }
-
-        if (mA2dpProxy == null || mHeadsetProxy == null) {
-            Log.e(TAG, "Proxy is null:" + mA2dpProxy + ":" + mHeadsetProxy);
-        }
-    }
-
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (intent == null) return;
-
-            String action = intent.getAction();
-            if (action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) {
-                BluetoothDevice dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-                String address = dev.getAddress();
-                mPairingRequestRcvd.add(address);
-            }
-        }
-    };
-}
diff --git a/core/java/android/server/BluetoothDeviceProperties.java b/core/java/android/server/BluetoothDeviceProperties.java
deleted file mode 100644
index fe3ef79..0000000
--- a/core/java/android/server/BluetoothDeviceProperties.java
+++ /dev/null
@@ -1,140 +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.
- */
-
-package android.server;
-
-import android.os.ParcelUuid;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-class BluetoothDeviceProperties {
-
-    private static final String TAG = "BluetoothDeviceProperties";
-
-    private final HashMap<String, Map<String, String>> mPropertiesMap;
-    private final BluetoothService mService;
-
-    BluetoothDeviceProperties(BluetoothService service) {
-        mPropertiesMap = new HashMap<String, Map<String, String>>();
-        mService = service;
-    }
-
-    Map<String, String> addProperties(String address, String[] properties) {
-        /*
-         * We get a DeviceFound signal every time RSSI changes or name changes.
-         * Don't create a new Map object every time.
-         */
-        Map<String, String> propertyValues;
-        synchronized(mPropertiesMap) {
-            propertyValues = mPropertiesMap.get(address);
-            if (propertyValues == null) {
-                propertyValues = new HashMap<String, String>();
-            }
-
-            for (int i = 0; i < properties.length; i++) {
-                String name = properties[i];
-                String newValue = null;
-                int len;
-                if (name == null) {
-                    Log.e(TAG, "Error: Remote Device Property at index "
-                        + i + " is null");
-                    continue;
-                }
-                if (name.equals("UUIDs") || name.equals("Nodes")) {
-                    StringBuilder str = new StringBuilder();
-                    len = Integer.valueOf(properties[++i]);
-                    for (int j = 0; j < len; j++) {
-                        str.append(properties[++i]);
-                        str.append(",");
-                    }
-                    if (len > 0) {
-                        newValue = str.toString();
-                    }
-                } else {
-                    newValue = properties[++i];
-                }
-
-                propertyValues.put(name, newValue);
-            }
-            mPropertiesMap.put(address, propertyValues);
-        }
-
-        // We have added a new remote device or updated its properties.
-        // Also update the serviceChannel cache.
-        mService.updateDeviceServiceChannelCache(address);
-        return propertyValues;
-    }
-
-    void setProperty(String address, String name, String value) {
-        synchronized(mPropertiesMap) {
-            Map <String, String> propVal = mPropertiesMap.get(address);
-            if (propVal != null) {
-                propVal.put(name, value);
-                mPropertiesMap.put(address, propVal);
-            } else {
-                Log.e(TAG, "setRemoteDeviceProperty for a device not in cache:" + address);
-            }
-        }
-    }
-
-    boolean isInCache(String address) {
-        synchronized (mPropertiesMap) {
-            return (mPropertiesMap.get(address) != null);
-        }
-    }
-
-    boolean isEmpty() {
-        synchronized (mPropertiesMap) {
-            return mPropertiesMap.isEmpty();
-        }
-    }
-
-    Set<String> keySet() {
-        synchronized (mPropertiesMap) {
-            return mPropertiesMap.keySet();
-        }
-    }
-
-    String getProperty(String address, String property) {
-        synchronized(mPropertiesMap) {
-            Map<String, String> properties = mPropertiesMap.get(address);
-            if (properties != null) {
-                return properties.get(property);
-            } else {
-                // Query for remote device properties, again.
-                // We will need to reload the cache when we switch Bluetooth on / off
-                // or if we crash.
-                properties = updateCache(address);
-                if (properties != null) {
-                    return properties.get(property);
-                }
-            }
-        }
-        Log.e(TAG, "getRemoteDeviceProperty: " + property + " not present: " + address);
-        return null;
-    }
-
-    Map<String, String> updateCache(String address) {
-        String[] propValues = mService.getRemoteDeviceProperties(address);
-        if (propValues != null) {
-            return addProperties(address, propValues);
-        }
-        return null;
-    }
-}
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
deleted file mode 100644
index b758e7fa..0000000
--- a/core/java/android/server/BluetoothEventLoop.java
+++ /dev/null
@@ -1,1067 +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.
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothClass;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHealth;
-import android.bluetooth.BluetoothInputDevice;
-import android.bluetooth.BluetoothPan;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothUuid;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.Message;
-import android.os.ParcelUuid;
-import android.os.PowerManager;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.List;
-
-
-/**
- * @hide
- */
-class BluetoothEventLoop {
-    private static final String TAG = "BluetoothEventLoop";
-    private static final boolean DBG = false;
-
-    private int mNativeData;
-    private Thread mThread;
-    private boolean mStarted;
-    private boolean mInterrupted;
-
-    private final HashMap<String, Integer> mPasskeyAgentRequestData;
-    private final HashMap<String, Integer> mAuthorizationAgentRequestData;
-    private final BluetoothService mBluetoothService;
-    private final BluetoothAdapter mAdapter;
-    private final BluetoothAdapterStateMachine mBluetoothState;
-    private BluetoothA2dp mA2dp;
-    private final Context mContext;
-    // The WakeLock is used for bringing up the LCD during a pairing request
-    // from remote device when Android is in Suspend state.
-    private PowerManager.WakeLock mWakeLock;
-
-    private static final int EVENT_PAIRING_CONSENT_DELAYED_ACCEPT = 1;
-    private static final int EVENT_AGENT_CANCEL = 2;
-
-    private static final int CREATE_DEVICE_ALREADY_EXISTS = 1;
-    private static final int CREATE_DEVICE_SUCCESS = 0;
-    private static final int CREATE_DEVICE_FAILED = -1;
-
-    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
-    private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
-
-    private final Handler mHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            String address = null;
-            switch (msg.what) {
-            case EVENT_PAIRING_CONSENT_DELAYED_ACCEPT:
-                address = (String)msg.obj;
-                if (address != null) {
-                    mBluetoothService.setPairingConfirmation(address, true);
-                }
-                break;
-            case EVENT_AGENT_CANCEL:
-                // Set the Bond State to BOND_NONE.
-                // We always have only 1 device in BONDING state.
-                String[] devices = mBluetoothService.listInState(BluetoothDevice.BOND_BONDING);
-                if (devices.length == 0) {
-                    break;
-                } else if (devices.length > 1) {
-                    Log.e(TAG, " There is more than one device in the Bonding State");
-                    break;
-                }
-                address = devices[0];
-                mBluetoothService.setBondState(address,
-                        BluetoothDevice.BOND_NONE,
-                        BluetoothDevice.UNBOND_REASON_REMOTE_AUTH_CANCELED);
-                break;
-            }
-        }
-    };
-
-    static { classInitNative(); }
-    private static native void classInitNative();
-
-    /* package */ BluetoothEventLoop(Context context, BluetoothAdapter adapter,
-                                     BluetoothService bluetoothService,
-                                     BluetoothAdapterStateMachine bluetoothState) {
-        mBluetoothService = bluetoothService;
-        mContext = context;
-        mBluetoothState = bluetoothState;
-        mPasskeyAgentRequestData = new HashMap<String, Integer>();
-        mAuthorizationAgentRequestData = new HashMap<String, Integer>();
-        mAdapter = adapter;
-        //WakeLock instantiation in BluetoothEventLoop class
-        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP
-                | PowerManager.ON_AFTER_RELEASE, TAG);
-        mWakeLock.setReferenceCounted(false);
-        initializeNativeDataNative();
-    }
-
-    /*package*/ void getProfileProxy() {
-        mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.A2DP);
-        mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.INPUT_DEVICE);
-    }
-
-    private BluetoothProfile.ServiceListener mProfileServiceListener =
-        new BluetoothProfile.ServiceListener() {
-        public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (profile == BluetoothProfile.A2DP) {
-                mA2dp = (BluetoothA2dp) proxy;
-            }
-        }
-        public void onServiceDisconnected(int profile) {
-            if (profile == BluetoothProfile.A2DP) {
-                mA2dp = null;
-            }
-        }
-    };
-
-
-    protected void finalize() throws Throwable {
-        try {
-            cleanupNativeDataNative();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    /* package */ HashMap<String, Integer> getPasskeyAgentRequestData() {
-        return mPasskeyAgentRequestData;
-    }
-
-    /* package */ HashMap<String, Integer> getAuthorizationAgentRequestData() {
-        return mAuthorizationAgentRequestData;
-    }
-
-    /* package */ void start() {
-
-        if (!isEventLoopRunningNative()) {
-            if (DBG) log("Starting Event Loop thread");
-            startEventLoopNative();
-        }
-    }
-
-    public void stop() {
-        if (isEventLoopRunningNative()) {
-            if (DBG) log("Stopping Event Loop thread");
-            stopEventLoopNative();
-        }
-    }
-
-    public boolean isEventLoopRunning() {
-        return isEventLoopRunningNative();
-    }
-
-    private void addDevice(String address, String[] properties) {
-        BluetoothDeviceProperties deviceProperties =
-                mBluetoothService.getDeviceProperties();
-        deviceProperties.addProperties(address, properties);
-        String rssi = deviceProperties.getProperty(address, "RSSI");
-        String classValue = deviceProperties.getProperty(address, "Class");
-        String name = deviceProperties.getProperty(address, "Name");
-        short rssiValue;
-        // For incoming connections, we don't get the RSSI value. Use a default of MIN_VALUE.
-        // If we accept the pairing, we will automatically show it at the top of the list.
-        if (rssi != null) {
-            rssiValue = (short)Integer.valueOf(rssi).intValue();
-        } else {
-            rssiValue = Short.MIN_VALUE;
-        }
-        if (classValue != null) {
-            Intent intent = new Intent(BluetoothDevice.ACTION_FOUND);
-            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-            intent.putExtra(BluetoothDevice.EXTRA_CLASS,
-                    new BluetoothClass(Integer.valueOf(classValue)));
-            intent.putExtra(BluetoothDevice.EXTRA_RSSI, rssiValue);
-            intent.putExtra(BluetoothDevice.EXTRA_NAME, name);
-
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-        } else {
-            log ("ClassValue: " + classValue + " for remote device: " + address + " is null");
-        }
-    }
-
-    /**
-     * Called by native code on a DeviceFound signal from org.bluez.Adapter.
-     *
-     * @param address the MAC address of the new device
-     * @param properties an array of property keys and value strings
-     *
-     * @see BluetoothDeviceProperties#addProperties(String, String[])
-     */
-    private void onDeviceFound(String address, String[] properties) {
-        if (properties == null) {
-            Log.e(TAG, "ERROR: Remote device properties are null");
-            return;
-        }
-        addDevice(address, properties);
-    }
-
-    /**
-     * Called by native code on a DeviceDisappeared signal from
-     * org.bluez.Adapter.
-     *
-     * @param address the MAC address of the disappeared device
-     */
-    private void onDeviceDisappeared(String address) {
-        Intent intent = new Intent(BluetoothDevice.ACTION_DISAPPEARED);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-    }
-
-    /**
-     * Called by native code on a DisconnectRequested signal from
-     * org.bluez.Device.
-     *
-     * @param deviceObjectPath the object path for the disconnecting device
-     */
-    private void onDeviceDisconnectRequested(String deviceObjectPath) {
-        String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
-        if (address == null) {
-            Log.e(TAG, "onDeviceDisconnectRequested: Address of the remote device in null");
-            return;
-        }
-        Intent intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-    }
-
-    /**
-     * Called by native code for the async response to a CreatePairedDevice
-     * method call to org.bluez.Adapter.
-     *
-     * @param address the MAC address of the device to pair
-     * @param result success or error result for the pairing operation
-     */
-    private void onCreatePairedDeviceResult(String address, int result) {
-        address = address.toUpperCase();
-        mBluetoothService.onCreatePairedDeviceResult(address, result);
-    }
-
-    /**
-     * Called by native code on a DeviceCreated signal from org.bluez.Adapter.
-     *
-     * @param deviceObjectPath the object path for the created device
-     */
-    private void onDeviceCreated(String deviceObjectPath) {
-        String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
-        if (address == null) {
-            Log.e(TAG, "onDeviceCreated: device address null!" + " deviceObjectPath: " +
-                  deviceObjectPath);
-            return;
-        }
-        if (!mBluetoothService.isRemoteDeviceInCache(address)) {
-            // Incoming connection, we haven't seen this device, add to cache.
-            String[] properties = mBluetoothService.getRemoteDeviceProperties(address);
-            if (properties != null) {
-                addDevice(address, properties);
-            }
-        }
-    }
-
-    /**
-     * Called by native code on a DeviceRemoved signal from org.bluez.Adapter.
-     *
-     * @param deviceObjectPath the object path for the removed device
-     */
-    private void onDeviceRemoved(String deviceObjectPath) {
-        String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
-        if (address != null) {
-            mBluetoothService.setBondState(address.toUpperCase(), BluetoothDevice.BOND_NONE,
-                BluetoothDevice.UNBOND_REASON_REMOVED);
-            mBluetoothService.setRemoteDeviceProperty(address, "UUIDs", null);
-        }
-    }
-
-    /**
-     * Called by native code on a PropertyChanged signal from
-     * org.bluez.Adapter. This method is also called from
-     * {@link BluetoothAdapterStateMachine} to set the "Pairable"
-     * property when Bluetooth is enabled.
-     *
-     * @param propValues a string array containing the key and one or more
-     *  values.
-     */
-    /*package*/ void onPropertyChanged(String[] propValues) {
-        BluetoothAdapterProperties adapterProperties =
-                mBluetoothService.getAdapterProperties();
-
-        if (adapterProperties.isEmpty()) {
-            // We have got a property change before
-            // we filled up our cache.
-            adapterProperties.getAllProperties();
-        }
-        log("Property Changed: " + propValues[0] + " : " + propValues[1]);
-        String name = propValues[0];
-        if (name.equals("Name")) {
-            adapterProperties.setProperty(name, propValues[1]);
-            Intent intent = new Intent(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
-            intent.putExtra(BluetoothAdapter.EXTRA_LOCAL_NAME, propValues[1]);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-        } else if (name.equals("Pairable") || name.equals("Discoverable")) {
-            adapterProperties.setProperty(name, propValues[1]);
-
-            if (name.equals("Discoverable")) {
-                mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SCAN_MODE_CHANGED);
-            }
-
-            String pairable = name.equals("Pairable") ? propValues[1] :
-                adapterProperties.getProperty("Pairable");
-            String discoverable = name.equals("Discoverable") ? propValues[1] :
-                adapterProperties.getProperty("Discoverable");
-
-            // This shouldn't happen, unless Adapter Properties are null.
-            if (pairable == null || discoverable == null)
-                return;
-
-            int mode = BluetoothService.bluezStringToScanMode(
-                    pairable.equals("true"),
-                    discoverable.equals("true"));
-            if (mode >= 0) {
-                Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
-                intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, mode);
-                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-                mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-            }
-        } else if (name.equals("Discovering")) {
-            Intent intent;
-            adapterProperties.setProperty(name, propValues[1]);
-            if (propValues[1].equals("true")) {
-                intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
-            } else {
-                // Stop the discovery.
-                mBluetoothService.cancelDiscovery();
-                intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
-            }
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-        } else if (name.equals("Devices") || name.equals("UUIDs")) {
-            String value = null;
-            int len = Integer.valueOf(propValues[1]);
-            if (len > 0) {
-                StringBuilder str = new StringBuilder();
-                for (int i = 2; i < propValues.length; i++) {
-                    str.append(propValues[i]);
-                    str.append(",");
-                }
-                value = str.toString();
-            }
-            adapterProperties.setProperty(name, value);
-            if (name.equals("UUIDs")) {
-                mBluetoothService.updateBluetoothState(value);
-            }
-        } else if (name.equals("Powered")) {
-            mBluetoothState.sendMessage(BluetoothAdapterStateMachine.POWER_STATE_CHANGED,
-                propValues[1].equals("true") ? new Boolean(true) : new Boolean(false));
-        } else if (name.equals("DiscoverableTimeout")) {
-            adapterProperties.setProperty(name, propValues[1]);
-        }
-    }
-
-    /**
-     * Called by native code on a PropertyChanged signal from
-     * org.bluez.Device.
-     *
-     * @param deviceObjectPath the object path for the changed device
-     * @param propValues a string array containing the key and one or more
-     *  values.
-     */
-    private void onDevicePropertyChanged(String deviceObjectPath, String[] propValues) {
-        String name = propValues[0];
-        String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
-        if (address == null) {
-            Log.e(TAG, "onDevicePropertyChanged: Address of the remote device in null");
-            return;
-        }
-        log("Device property changed: " + address + " property: "
-            + name + " value: " + propValues[1]);
-
-        BluetoothDevice device = mAdapter.getRemoteDevice(address);
-        if (name.equals("Name")) {
-            mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
-            Intent intent = new Intent(BluetoothDevice.ACTION_NAME_CHANGED);
-            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-            intent.putExtra(BluetoothDevice.EXTRA_NAME, propValues[1]);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-        } else if (name.equals("Alias")) {
-            mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
-            Intent intent = new Intent(BluetoothDevice.ACTION_ALIAS_CHANGED);
-            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-        } else if (name.equals("Class")) {
-            mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
-            Intent intent = new Intent(BluetoothDevice.ACTION_CLASS_CHANGED);
-            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-            intent.putExtra(BluetoothDevice.EXTRA_CLASS,
-                    new BluetoothClass(Integer.valueOf(propValues[1])));
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-        } else if (name.equals("Connected")) {
-            mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
-            Intent intent = null;
-            if (propValues[1].equals("true")) {
-                intent = new Intent(BluetoothDevice.ACTION_ACL_CONNECTED);
-                // Set the link timeout to 8000 slots (5 sec timeout)
-                // for bluetooth docks.
-                if (mBluetoothService.isBluetoothDock(address)) {
-                    mBluetoothService.setLinkTimeout(address, 8000);
-                }
-            } else {
-                intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECTED);
-            }
-            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-        } else if (name.equals("UUIDs")) {
-            String uuid = null;
-            int len = Integer.valueOf(propValues[1]);
-            if (len > 0) {
-                StringBuilder str = new StringBuilder();
-                for (int i = 2; i < propValues.length; i++) {
-                    str.append(propValues[i]);
-                    str.append(",");
-                }
-                uuid = str.toString();
-            }
-            mBluetoothService.setRemoteDeviceProperty(address, name, uuid);
-
-            // UUIDs have changed, query remote service channel and update cache.
-            mBluetoothService.updateDeviceServiceChannelCache(address);
-
-            mBluetoothService.sendUuidIntent(address);
-        } else if (name.equals("Paired")) {
-            if (propValues[1].equals("true")) {
-                // If locally initiated pairing, we will
-                // not go to BOND_BONDED state until we have received a
-                // successful return value in onCreatePairedDeviceResult
-                if (null == mBluetoothService.getPendingOutgoingBonding()) {
-                    mBluetoothService.setBondState(address, BluetoothDevice.BOND_BONDED);
-                }
-            } else {
-                mBluetoothService.setBondState(address, BluetoothDevice.BOND_NONE);
-                mBluetoothService.setRemoteDeviceProperty(address, "Trusted", "false");
-            }
-        } else if (name.equals("Trusted")) {
-            if (DBG)
-                log("set trust state succeeded, value is: " + propValues[1]);
-            mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
-        }
-    }
-
-    /**
-     * Called by native code on a PropertyChanged signal from
-     * org.bluez.Input.
-     *
-     * @param path the object path for the changed input device
-     * @param propValues a string array containing the key and one or more
-     *  values.
-     */
-    private void onInputDevicePropertyChanged(String path, String[] propValues) {
-        String address = mBluetoothService.getAddressFromObjectPath(path);
-        if (address == null) {
-            Log.e(TAG, "onInputDevicePropertyChanged: Address of the remote device is null");
-            return;
-        }
-        log("Input Device : Name of Property is: " + propValues[0]);
-        boolean state = false;
-        if (propValues[1].equals("true")) {
-            state = true;
-        }
-        mBluetoothService.handleInputDevicePropertyChange(address, state);
-    }
-
-    /**
-     * Called by native code on a PropertyChanged signal from
-     * org.bluez.Network.
-     *
-     * @param deviceObjectPath the object path for the changed PAN device
-     * @param propValues a string array containing the key and one or more
-     *  values.
-     */
-    private void onPanDevicePropertyChanged(String deviceObjectPath, String[] propValues) {
-        String name = propValues[0];
-        String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
-        if (address == null) {
-            Log.e(TAG, "onPanDevicePropertyChanged: Address of the remote device in null");
-            return;
-        }
-        if (DBG) {
-            log("Pan Device property changed: " + address + "  property: "
-                    + name + " value: "+ propValues[1]);
-        }
-        BluetoothDevice device = mAdapter.getRemoteDevice(address);
-        if (name.equals("Connected")) {
-            if (propValues[1].equals("false")) {
-                mBluetoothService.handlePanDeviceStateChange(device,
-                                          BluetoothPan.STATE_DISCONNECTED,
-                                          BluetoothPan.LOCAL_PANU_ROLE);
-            }
-        } else if (name.equals("Interface")) {
-            String iface = propValues[1];
-            if (!iface.equals("")) {
-                mBluetoothService.handlePanDeviceStateChange(device, iface,
-                                              BluetoothPan.STATE_CONNECTED,
-                                              BluetoothPan.LOCAL_PANU_ROLE);
-            }
-        }
-    }
-
-    private String checkPairingRequestAndGetAddress(String objectPath, int nativeData) {
-        String address = mBluetoothService.getAddressFromObjectPath(objectPath);
-        if (address == null) {
-            Log.e(TAG, "Unable to get device address in checkPairingRequestAndGetAddress, " +
-                  "returning null");
-            return null;
-        }
-        address = address.toUpperCase();
-        mPasskeyAgentRequestData.put(address, new Integer(nativeData));
-
-        if (mBluetoothService.getBluetoothState() == BluetoothAdapter.STATE_TURNING_OFF) {
-            // shutdown path
-            mBluetoothService.cancelPairingUserInput(address);
-            return null;
-        }
-        // Set state to BONDING. For incoming connections it will be set here.
-        // For outgoing connections, it gets set when we call createBond.
-        // Also set it only when the state is not already Bonded, we can sometimes
-        // get an authorization request from the remote end if it doesn't have the link key
-        // while we still have it.
-        if (mBluetoothService.getBondState(address) != BluetoothDevice.BOND_BONDED)
-            mBluetoothService.setBondState(address, BluetoothDevice.BOND_BONDING);
-        return address;
-    }
-
-    /**
-     * Called by native code on a RequestPairingConsent method call to
-     * org.bluez.Agent.
-     *
-     * @param objectPath the path of the device to request pairing consent for
-     * @param nativeData a native pointer to the original D-Bus message
-     */
-    private void onRequestPairingConsent(String objectPath, int nativeData) {
-        String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
-        if (address == null) return;
-
-        /* The link key will not be stored if the incoming request has MITM
-         * protection switched on. Unfortunately, some devices have MITM
-         * switched on even though their capabilities are NoInputNoOutput,
-         * so we may get this request many times. Also if we respond immediately,
-         * the other end is unable to handle it. Delay sending the message.
-         */
-        if (mBluetoothService.getBondState(address) == BluetoothDevice.BOND_BONDED) {
-            Message message = mHandler.obtainMessage(EVENT_PAIRING_CONSENT_DELAYED_ACCEPT);
-            message.obj = address;
-            mHandler.sendMessageDelayed(message, 1500);
-            return;
-        }
-        // Acquire wakelock during PIN code request to bring up LCD display
-        mWakeLock.acquire();
-        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
-                        BluetoothDevice.PAIRING_VARIANT_CONSENT);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-        // Release wakelock to allow the LCD to go off after the PIN popup notification.
-        mWakeLock.release();
-        return;
-    }
-
-    /**
-     * Called by native code on a RequestConfirmation method call to
-     * org.bluez.Agent.
-     *
-     * @param objectPath the path of the device to confirm the passkey for
-     * @param passkey an integer containing the 6-digit passkey to confirm
-     * @param nativeData a native pointer to the original D-Bus message
-     */
-    private void onRequestPasskeyConfirmation(String objectPath, int passkey, int nativeData) {
-        String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
-        if (address == null) return;
-        // Acquire wakelock during PIN code request to bring up LCD display
-        mWakeLock.acquire();
-        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, passkey);
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
-                BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-        // Release wakelock to allow the LCD to go off after the PIN popup notification.
-        mWakeLock.release();
-        return;
-    }
-
-    /**
-     * Called by native code on a RequestPasskey method call to
-     * org.bluez.Agent.
-     *
-     * @param objectPath the path of the device requesting a passkey
-     * @param nativeData a native pointer to the original D-Bus message
-     */
-    private void onRequestPasskey(String objectPath, int nativeData) {
-        String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
-        if (address == null) return;
-        // Acquire wakelock during PIN code request to bring up LCD display
-        mWakeLock.acquire();
-        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
-                BluetoothDevice.PAIRING_VARIANT_PASSKEY);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-        // Release wakelock to allow the LCD to go off after the PIN popup notification.
-        mWakeLock.release();
-        return;
-    }
-
-    /**
-     * Called by native code on a RequestPinCode method call to
-     * org.bluez.Agent.
-     *
-     * @param objectPath the path of the device requesting a PIN code
-     * @param nativeData a native pointer to the original D-Bus message
-     */
-    private void onRequestPinCode(String objectPath, int nativeData) {
-        String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
-        if (address == null) return;
-
-        String pendingOutgoingAddress =
-                mBluetoothService.getPendingOutgoingBonding();
-        BluetoothClass btClass = new BluetoothClass(mBluetoothService.getRemoteClass(address));
-        int btDeviceClass = btClass.getDeviceClass();
-
-        if (address.equals(pendingOutgoingAddress)) {
-            // we initiated the bonding
-
-            // Check if its a dock
-            if (mBluetoothService.isBluetoothDock(address)) {
-                String pin = mBluetoothService.getDockPin();
-                mBluetoothService.setPin(address, BluetoothDevice.convertPinToBytes(pin));
-                return;
-            }
-
-            // try 0000 once if the device looks dumb
-            switch (btDeviceClass) {
-            case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
-            case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
-            case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES:
-            case BluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO:
-            case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO:
-                if (mBluetoothService.attemptAutoPair(address)) return;
-           }
-        }
-
-        if (btDeviceClass == BluetoothClass.Device.PERIPHERAL_KEYBOARD ||
-            btDeviceClass == BluetoothClass.Device.PERIPHERAL_KEYBOARD_POINTING) {
-            // Its a keyboard. Follow the HID spec recommendation of creating the
-            // passkey and displaying it to the user. If the keyboard doesn't follow
-            // the spec recommendation, check if the keyboard has a fixed PIN zero
-            // and pair.
-            if (mBluetoothService.isFixedPinZerosAutoPairKeyboard(address)) {
-                mBluetoothService.setPin(address, BluetoothDevice.convertPinToBytes("0000"));
-                return;
-            }
-
-            // Generate a variable PIN. This is not truly random but good enough.
-            int pin = (int) Math.floor(Math.random() * 10000);
-            sendDisplayPinIntent(address, pin);
-            return;
-        }
-        // Acquire wakelock during PIN code request to bring up LCD display
-        mWakeLock.acquire();
-        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.PAIRING_VARIANT_PIN);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-        // Release wakelock to allow the LCD to go off after the PIN popup notification.
-        mWakeLock.release();
-        return;
-    }
-
-    /**
-     * Called by native code on a DisplayPasskey method call to
-     * org.bluez.Agent.
-     *
-     * @param objectPath the path of the device to display the passkey for
-     * @param passkey an integer containing the 6-digit passkey
-     * @param nativeData a native pointer to the original D-Bus message
-     */
-    private void onDisplayPasskey(String objectPath, int passkey, int nativeData) {
-        String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
-        if (address == null) return;
-
-        // Acquire wakelock during PIN code request to bring up LCD display
-        mWakeLock.acquire();
-        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, passkey);
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
-                        BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-        //Release wakelock to allow the LCD to go off after the PIN popup notification.
-        mWakeLock.release();
-    }
-
-    private void sendDisplayPinIntent(String address, int pin) {
-        // Acquire wakelock during PIN code request to bring up LCD display
-        mWakeLock.acquire();
-        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, pin);
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
-                        BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-        //Release wakelock to allow the LCD to go off after the PIN popup notifcation.
-        mWakeLock.release();
-    }
-
-    /**
-     * Called by native code on a RequestOobData method call to
-     * org.bluez.Agent.
-     *
-     * @param objectPath the path of the device requesting OOB data
-     * @param nativeData a native pointer to the original D-Bus message
-     */
-    private void onRequestOobData(String objectPath, int nativeData) {
-        String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
-        if (address == null) return;
-
-        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
-                BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-    }
-
-    /**
-     * Called by native code on an Authorize method call to org.bluez.Agent.
-     *
-     * @param objectPath the path of the device requesting to be authorized
-     * @param deviceUuid the UUID of the requesting device
-     * @param nativeData reference for native data
-     */
-    private void  onAgentAuthorize(String objectPath, String deviceUuid, int nativeData) {
-        if (!mBluetoothService.isEnabled()) return;
-
-        String address = mBluetoothService.getAddressFromObjectPath(objectPath);
-        if (address == null) {
-            Log.e(TAG, "Unable to get device address in onAuthAgentAuthorize");
-            return;
-        }
-
-        boolean authorized = false;
-        ParcelUuid uuid = ParcelUuid.fromString(deviceUuid);
-
-        BluetoothDevice device = mAdapter.getRemoteDevice(address);
-        mAuthorizationAgentRequestData.put(address, new Integer(nativeData));
-
-        // Bluez sends the UUID of the local service being accessed, _not_ the
-        // remote service
-        if (mA2dp != null &&
-            (BluetoothUuid.isAudioSource(uuid) || BluetoothUuid.isAvrcpTarget(uuid)
-              || BluetoothUuid.isAdvAudioDist(uuid)) &&
-              !isOtherSinkInNonDisconnectedState(address)) {
-            authorized = mA2dp.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
-            if (authorized && !BluetoothUuid.isAvrcpTarget(uuid)) {
-                Log.i(TAG, "First check pass for incoming A2DP / AVRCP connection from " + address);
-                // Some headsets try to connect AVCTP before AVDTP - against the recommendation
-                // If AVCTP connection fails, we get stuck in IncomingA2DP state in the state
-                // machine.  We don't handle AVCTP signals currently. We only send
-                // intents for AVDTP state changes. We need to handle both of them in
-                // some cases. For now, just don't move to incoming state in this case.
-                mBluetoothService.notifyIncomingA2dpConnection(address, false);
-            } else {
-                Log.i(TAG, "" + authorized +
-                      "Incoming A2DP / AVRCP connection from " + address);
-                mA2dp.allowIncomingConnect(device, authorized);
-                mBluetoothService.notifyIncomingA2dpConnection(address, true);
-            }
-        } else if (BluetoothUuid.isInputDevice(uuid)) {
-            // We can have more than 1 input device connected.
-            authorized = mBluetoothService.getInputDevicePriority(device) >
-                    BluetoothInputDevice.PRIORITY_OFF;
-            if (authorized) {
-                Log.i(TAG, "First check pass for incoming HID connection from " + address);
-                // notify profile state change
-                mBluetoothService.notifyIncomingHidConnection(address);
-            } else {
-                Log.i(TAG, "Rejecting incoming HID connection from " + address);
-                mBluetoothService.allowIncomingProfileConnect(device, authorized);
-            }
-        } else if (BluetoothUuid.isBnep(uuid)) {
-            // PAN doesn't go to the state machine, accept or reject from here
-            authorized = mBluetoothService.allowIncomingTethering();
-            mBluetoothService.allowIncomingProfileConnect(device, authorized);
-        } else {
-            Log.i(TAG, "Rejecting incoming " + deviceUuid + " connection from " + address);
-            mBluetoothService.allowIncomingProfileConnect(device, authorized);
-        }
-        log("onAgentAuthorize(" + objectPath + ", " + deviceUuid + ") = " + authorized);
-    }
-
-    private boolean onAgentOutOfBandDataAvailable(String objectPath) {
-        if (!mBluetoothService.isEnabled()) return false;
-
-        String address = mBluetoothService.getAddressFromObjectPath(objectPath);
-        if (address == null) return false;
-
-        if (mBluetoothService.getDeviceOutOfBandData(
-            mAdapter.getRemoteDevice(address)) != null) {
-            return true;
-        }
-        return false;
-    }
-
-    private boolean isOtherSinkInNonDisconnectedState(String address) {
-        List<BluetoothDevice> devices =
-            mA2dp.getDevicesMatchingConnectionStates(new int[] {BluetoothA2dp.STATE_CONNECTED,
-                                                     BluetoothA2dp.STATE_CONNECTING,
-                                                     BluetoothA2dp.STATE_DISCONNECTING});
-
-        if (devices.size() == 0) return false;
-        for (BluetoothDevice dev: devices) {
-            if (!dev.getAddress().equals(address)) return true;
-        }
-        return false;
-    }
-
-    /**
-     * Called by native code on a Cancel method call to org.bluez.Agent.
-     */
-    private void onAgentCancel() {
-        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_CANCEL);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-
-        mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_AGENT_CANCEL),
-                   1500);
-
-        return;
-    }
-
-    /**
-     * Called by native code for the async response to a DiscoverServices
-     * method call to org.bluez.Adapter.
-     *
-     * @param deviceObjectPath the path for the specified device
-     * @param result true for success; false on error
-     */
-    private void onDiscoverServicesResult(String deviceObjectPath, boolean result) {
-        String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
-        if (address == null) return;
-
-        // We don't parse the xml here, instead just query Bluez for the properties.
-        if (result) {
-            mBluetoothService.updateRemoteDevicePropertiesCache(address);
-        }
-        mBluetoothService.sendUuidIntent(address);
-        mBluetoothService.makeServiceChannelCallbacks(address);
-    }
-
-    /**
-     * Called by native code for the async response to a CreateDevice
-     * method call to org.bluez.Adapter.
-     *
-     * @param address the MAC address of the device to create
-     * @param result {@link #CREATE_DEVICE_SUCCESS},
-     *  {@link #CREATE_DEVICE_ALREADY_EXISTS} or {@link #CREATE_DEVICE_FAILED}}
-     */
-    private void onCreateDeviceResult(String address, int result) {
-        if (DBG) log("Result of onCreateDeviceResult:" + result);
-
-        switch (result) {
-        case CREATE_DEVICE_ALREADY_EXISTS:
-            String path = mBluetoothService.getObjectPathFromAddress(address);
-            if (path != null) {
-                mBluetoothService.discoverServicesNative(path, "");
-                break;
-            }
-            Log.w(TAG, "Device exists, but we don't have the bluez path, failing");
-            // fall-through
-        case CREATE_DEVICE_FAILED:
-            mBluetoothService.sendUuidIntent(address);
-            mBluetoothService.makeServiceChannelCallbacks(address);
-            break;
-        case CREATE_DEVICE_SUCCESS:
-            // nothing to do, UUID intent's will be sent via property changed
-        }
-    }
-
-    /**
-     * Called by native code for the async response to a Connect
-     * method call to org.bluez.Input.
-     *
-     * @param path the path of the specified input device
-     * @param result Result code of the operation.
-     */
-    private void onInputDeviceConnectionResult(String path, int result) {
-        // Success case gets handled by Property Change signal
-        if (result != BluetoothInputDevice.INPUT_OPERATION_SUCCESS) {
-            String address = mBluetoothService.getAddressFromObjectPath(path);
-            if (address == null) return;
-
-            boolean connected = false;
-            BluetoothDevice device = mAdapter.getRemoteDevice(address);
-            int state = mBluetoothService.getInputDeviceConnectionState(device);
-            if (state == BluetoothInputDevice.STATE_CONNECTING) {
-                if (result == BluetoothInputDevice.INPUT_CONNECT_FAILED_ALREADY_CONNECTED) {
-                    connected = true;
-                } else {
-                    connected = false;
-                }
-            } else if (state == BluetoothInputDevice.STATE_DISCONNECTING) {
-                if (result == BluetoothInputDevice.INPUT_DISCONNECT_FAILED_NOT_CONNECTED) {
-                    connected = false;
-                } else {
-                    // There is no better way to handle this, this shouldn't happen
-                    connected = true;
-                }
-            } else {
-                Log.e(TAG, "Error onInputDeviceConnectionResult. State is:" + state);
-            }
-            mBluetoothService.handleInputDevicePropertyChange(address, connected);
-        }
-    }
-
-    /**
-     * Called by native code for the async response to a Connect
-     * method call to org.bluez.Network.
-     *
-     * @param path the path of the specified PAN device
-     * @param result Result code of the operation.
-     */
-    private void onPanDeviceConnectionResult(String path, int result) {
-        log ("onPanDeviceConnectionResult " + path + " " + result);
-        // Success case gets handled by Property Change signal
-        if (result != BluetoothPan.PAN_OPERATION_SUCCESS) {
-            String address = mBluetoothService.getAddressFromObjectPath(path);
-            if (address == null) return;
-
-            boolean connected = false;
-            BluetoothDevice device = mAdapter.getRemoteDevice(address);
-            int state = mBluetoothService.getPanDeviceConnectionState(device);
-            if (state == BluetoothPan.STATE_CONNECTING) {
-                if (result == BluetoothPan.PAN_CONNECT_FAILED_ALREADY_CONNECTED) {
-                    connected = true;
-                } else {
-                    connected = false;
-                }
-            } else if (state == BluetoothPan.STATE_DISCONNECTING) {
-                if (result == BluetoothPan.PAN_DISCONNECT_FAILED_NOT_CONNECTED) {
-                    connected = false;
-                } else {
-                    // There is no better way to handle this, this shouldn't happen
-                    connected = true;
-                }
-            } else {
-                Log.e(TAG, "Error onPanDeviceConnectionResult. State is: "
-                        + state + " result: "+ result);
-            }
-            int newState = connected? BluetoothPan.STATE_CONNECTED :
-                BluetoothPan.STATE_DISCONNECTED;
-            mBluetoothService.handlePanDeviceStateChange(device, newState,
-                                                  BluetoothPan.LOCAL_PANU_ROLE);
-        }
-    }
-
-    /**
-     * Called by native code for the async response to a Connect
-     * method call to org.bluez.Health
-     *
-     * @param chanCode The internal id of the channel
-     * @param result Result code of the operation.
-     */
-    private void onHealthDeviceConnectionResult(int chanCode, int result) {
-        log ("onHealthDeviceConnectionResult " + chanCode + " " + result);
-        // Success case gets handled by Property Change signal
-        if (result != BluetoothHealth.HEALTH_OPERATION_SUCCESS) {
-            mBluetoothService.onHealthDeviceChannelConnectionError(chanCode,
-                                                 BluetoothHealth.STATE_CHANNEL_DISCONNECTED);
-        }
-    }
-
-    /**
-     * Called by native code on a DeviceDisconnected signal from
-     * org.bluez.NetworkServer.
-     *
-     * @param address the MAC address of the disconnected device
-     */
-    private void onNetworkDeviceDisconnected(String address) {
-        BluetoothDevice device = mAdapter.getRemoteDevice(address);
-        mBluetoothService.handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTED,
-                                                      BluetoothPan.LOCAL_NAP_ROLE);
-    }
-
-    /**
-     * Called by native code on a DeviceConnected signal from
-     * org.bluez.NetworkServer.
-     *
-     * @param address the MAC address of the connected device
-     * @param iface interface of remote network
-     * @param destUuid unused UUID parameter
-     */
-    private void onNetworkDeviceConnected(String address, String iface, int destUuid) {
-        BluetoothDevice device = mAdapter.getRemoteDevice(address);
-        mBluetoothService.handlePanDeviceStateChange(device, iface, BluetoothPan.STATE_CONNECTED,
-                                                      BluetoothPan.LOCAL_NAP_ROLE);
-    }
-
-    /**
-     * Called by native code on a PropertyChanged signal from
-     * org.bluez.HealthDevice.
-     *
-     * @param devicePath the object path of the remote device
-     * @param propValues Properties (Name-Value) of the Health Device.
-     */
-    private void onHealthDevicePropertyChanged(String devicePath, String[] propValues) {
-        log("Health Device : Name of Property is: " + propValues[0] + " Value:" + propValues[1]);
-        mBluetoothService.onHealthDevicePropertyChanged(devicePath, propValues[1]);
-    }
-
-    /**
-     * Called by native code on a ChannelCreated/Deleted signal from
-     * org.bluez.HealthDevice.
-     *
-     * @param devicePath the object path of the remote device
-     * @param channelPath the path of the health channel.
-     * @param exists Boolean to indicate if the channel was created or deleted.
-     */
-    private void onHealthDeviceChannelChanged(String devicePath, String channelPath,
-            boolean exists) {
-        log("Health Device : devicePath: " + devicePath + ":channelPath:" + channelPath +
-                ":exists" + exists);
-        mBluetoothService.onHealthDeviceChannelChanged(devicePath, channelPath, exists);
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-
-    private native void initializeNativeDataNative();
-    private native void startEventLoopNative();
-    private native void stopEventLoopNative();
-    private native boolean isEventLoopRunningNative();
-    private native void cleanupNativeDataNative();
-}
diff --git a/core/java/android/server/BluetoothHealthProfileHandler.java b/core/java/android/server/BluetoothHealthProfileHandler.java
deleted file mode 100644
index 5e93b81..0000000
--- a/core/java/android/server/BluetoothHealthProfileHandler.java
+++ /dev/null
@@ -1,671 +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.
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHealth;
-import android.bluetooth.BluetoothHealthAppConfiguration;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.IBluetoothHealthCallback;
-import android.content.Context;
-import android.os.Handler;
-import android.os.Message;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * This handles all the operations on the Bluetooth Health profile.
- * All functions are called by BluetoothService, as Bluetooth Service
- * is the Service handler for the HDP profile.
- *
- * @hide
- */
-final class BluetoothHealthProfileHandler {
-    private static final String TAG = "BluetoothHealthProfileHandler";
-    private static final boolean DBG = false;
-
-    private static BluetoothHealthProfileHandler sInstance;
-    private BluetoothService mBluetoothService;
-    private ArrayList<HealthChannel> mHealthChannels;
-    private HashMap <BluetoothHealthAppConfiguration, String> mHealthAppConfigs;
-    private HashMap <BluetoothDevice, Integer> mHealthDevices;
-    private HashMap <BluetoothHealthAppConfiguration, IBluetoothHealthCallback> mCallbacks;
-
-    private static final int MESSAGE_REGISTER_APPLICATION = 0;
-    private static final int MESSAGE_UNREGISTER_APPLICATION = 1;
-    private static final int MESSAGE_CONNECT_CHANNEL = 2;
-    private static final AtomicInteger sChannelId = new AtomicInteger();
-
-    class HealthChannel {
-        private ParcelFileDescriptor mChannelFd;
-        private boolean mMainChannel;
-        private String mChannelPath;
-        private BluetoothDevice mDevice;
-        private BluetoothHealthAppConfiguration mConfig;
-        private int mState;
-        private int mChannelType;
-        private int mId;
-
-        HealthChannel(BluetoothDevice device, BluetoothHealthAppConfiguration config,
-                ParcelFileDescriptor fd, boolean mainChannel, String channelPath) {
-             mChannelFd = fd;
-             mMainChannel = mainChannel;
-             mChannelPath = channelPath;
-             mDevice = device;
-             mConfig = config;
-             mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
-             mId = getChannelId();
-        }
-    }
-
-    private final Handler mHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-            case MESSAGE_REGISTER_APPLICATION:
-                BluetoothHealthAppConfiguration registerApp =
-                    (BluetoothHealthAppConfiguration) msg.obj;
-                int role = registerApp.getRole();
-                String path = null;
-
-                if (role == BluetoothHealth.SINK_ROLE) {
-                    path = mBluetoothService.registerHealthApplicationNative(
-                            registerApp.getDataType(), getStringRole(role), registerApp.getName());
-                } else {
-                    path = mBluetoothService.registerHealthApplicationNative(
-                            registerApp.getDataType(), getStringRole(role), registerApp.getName(),
-                            getStringChannelType(registerApp.getChannelType()));
-                }
-
-                if (path == null) {
-                    callHealthApplicationStatusCallback(registerApp,
-                            BluetoothHealth.APP_CONFIG_REGISTRATION_FAILURE);
-                    mCallbacks.remove(registerApp);
-                } else {
-                    mHealthAppConfigs.put(registerApp, path);
-                    callHealthApplicationStatusCallback(registerApp,
-                            BluetoothHealth.APP_CONFIG_REGISTRATION_SUCCESS);
-                }
-
-                break;
-            case MESSAGE_UNREGISTER_APPLICATION:
-                BluetoothHealthAppConfiguration unregisterApp =
-                    (BluetoothHealthAppConfiguration) msg.obj;
-
-                // Disconnect all the channels
-                for (HealthChannel chan : mHealthChannels) {
-                    if (chan.mConfig.equals(unregisterApp) &&
-                            chan.mState != BluetoothHealth.STATE_CHANNEL_DISCONNECTED) {
-                        disconnectChannel(chan.mDevice, unregisterApp, chan.mId);
-                    }
-                }
-
-                boolean result = mBluetoothService.unregisterHealthApplicationNative(
-                        mHealthAppConfigs.get(unregisterApp));
-                if (result) {
-                    callHealthApplicationStatusCallback(unregisterApp,
-                            BluetoothHealth.APP_CONFIG_UNREGISTRATION_SUCCESS);
-                    mCallbacks.remove(unregisterApp);
-                    mHealthAppConfigs.remove(unregisterApp);
-                } else {
-                    callHealthApplicationStatusCallback(unregisterApp,
-                            BluetoothHealth.APP_CONFIG_UNREGISTRATION_FAILURE);
-                }
-                break;
-            case MESSAGE_CONNECT_CHANNEL:
-                HealthChannel chan = (HealthChannel)msg.obj;
-                String deviceObjectPath =
-                    mBluetoothService.getObjectPathFromAddress(chan.mDevice.getAddress());
-                String configPath = mHealthAppConfigs.get(chan.mConfig);
-                String channelType = getStringChannelType(chan.mChannelType);
-
-                if (!mBluetoothService.createChannelNative(deviceObjectPath, configPath,
-                          channelType, chan.mId)) {
-                    int prevState = chan.mState;
-                    int state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
-                    callHealthChannelCallback(chan.mConfig, chan.mDevice, prevState, state, null,
-                            chan.mId);
-                    mHealthChannels.remove(chan);
-                }
-            }
-        }
-    };
-
-    private BluetoothHealthProfileHandler(Context context, BluetoothService service) {
-        mBluetoothService = service;
-        mHealthAppConfigs = new HashMap<BluetoothHealthAppConfiguration, String>();
-        mHealthChannels = new ArrayList<HealthChannel>();
-        mHealthDevices = new HashMap<BluetoothDevice, Integer>();
-        mCallbacks = new HashMap<BluetoothHealthAppConfiguration, IBluetoothHealthCallback>();
-    }
-
-    static synchronized BluetoothHealthProfileHandler getInstance(Context context,
-            BluetoothService service) {
-        if (sInstance == null) sInstance = new BluetoothHealthProfileHandler(context, service);
-        return sInstance;
-    }
-
-    boolean registerAppConfiguration(BluetoothHealthAppConfiguration config,
-                                     IBluetoothHealthCallback callback) {
-        Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_APPLICATION);
-        msg.obj = config;
-        mHandler.sendMessage(msg);
-        mCallbacks.put(config, callback);
-        return true;
-    }
-
-    boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
-        String path = mHealthAppConfigs.get(config);
-        if (path == null) return false;
-
-        Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_APPLICATION);
-        msg.obj = config;
-        mHandler.sendMessage(msg);
-        return true;
-    }
-
-    boolean connectChannelToSource(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config) {
-        return connectChannel(device, config, BluetoothHealth.CHANNEL_TYPE_ANY);
-    }
-
-    private HealthChannel getMainChannel(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config) {
-        for (HealthChannel chan: mHealthChannels) {
-            if (chan.mDevice.equals(device) && chan.mConfig.equals(config)) {
-                if (chan.mMainChannel) return chan;
-            }
-        }
-        return null;
-    }
-
-    boolean connectChannel(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config, int channelType) {
-        String deviceObjectPath =
-            mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        if (deviceObjectPath == null) return false;
-
-        String configPath = mHealthAppConfigs.get(config);
-        if (configPath == null) return false;
-
-        HealthChannel chan = new HealthChannel(device, config, null, false, null);
-        chan.mState = BluetoothHealth.STATE_CHANNEL_CONNECTING;
-        chan.mChannelType = channelType;
-        mHealthChannels.add(chan);
-
-        int prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
-        int state = BluetoothHealth.STATE_CHANNEL_CONNECTING;
-        callHealthChannelCallback(config, device, prevState, state, null, chan.mId);
-
-        Message msg = mHandler.obtainMessage(MESSAGE_CONNECT_CHANNEL);
-        msg.obj = chan;
-        mHandler.sendMessage(msg);
-
-        return true;
-    }
-
-    private String getStringChannelType(int type) {
-        if (type == BluetoothHealth.CHANNEL_TYPE_RELIABLE) {
-            return "Reliable";
-        } else if (type == BluetoothHealth.CHANNEL_TYPE_STREAMING) {
-            return "Streaming";
-        } else {
-            return "Any";
-        }
-    }
-
-    private String getStringRole(int role) {
-        if (role == BluetoothHealth.SINK_ROLE) {
-            return "Sink";
-        } else if (role == BluetoothHealth.SOURCE_ROLE) {
-            return "Streaming";
-        } else {
-            return null;
-        }
-    }
-
-    private int getChannelId() {
-        // The function doesn't need to be synchronized, as the health profile handler
-        // will only allow one health channel object creation at a time.
-        // In the worst case the while loop will have to break out at some point of
-        // time, because only a limited number of L2CAP channels are possible.
-        int id;
-        boolean found;
-        do {
-            id = sChannelId.incrementAndGet();
-            found = false;
-            for (HealthChannel chan: mHealthChannels) {
-                if (chan.mId == id) found = true;
-            }
-        } while (found);
-        return id;
-    }
-
-    boolean disconnectChannel(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config, int id) {
-        HealthChannel chan = findChannelById(id);
-        if (chan == null) {
-          return false;
-        }
-
-        String deviceObjectPath =
-                mBluetoothService.getObjectPathFromAddress(device.getAddress());
-
-        mBluetoothService.releaseChannelFdNative(chan.mChannelPath);
-
-        int prevState = chan.mState;
-        chan.mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTING;
-        callHealthChannelCallback(config, device, prevState, chan.mState,
-                null, chan.mId);
-
-        if (!mBluetoothService.destroyChannelNative(deviceObjectPath, chan.mChannelPath,
-                                                    chan.mId)) {
-            prevState = chan.mState;
-            chan.mState = BluetoothHealth.STATE_CHANNEL_CONNECTED;
-            callHealthChannelCallback(config, device, prevState, chan.mState,
-                    chan.mChannelFd, chan.mId);
-            return false;
-        } else {
-            return true;
-        }
-    }
-
-    private HealthChannel findChannelById(int id) {
-        for (HealthChannel chan : mHealthChannels) {
-            if (chan.mId == id) return chan;
-        }
-        return null;
-    }
-
-    private HealthChannel findChannelByPath(BluetoothDevice device, String path) {
-        for (HealthChannel chan : mHealthChannels) {
-            if (path.equals(chan.mChannelPath) && device.equals(chan.mDevice)) return chan;
-        }
-        return null;
-    }
-
-    private List<HealthChannel> findChannelByStates(BluetoothDevice device, int[] states) {
-        List<HealthChannel> channels = new ArrayList<HealthChannel>();
-        for (HealthChannel chan: mHealthChannels) {
-            if (chan.mDevice.equals(device)) {
-                for (int state : states) {
-                    if (chan.mState == state) {
-                        channels.add(chan);
-                    }
-                }
-            }
-        }
-        return channels;
-    }
-
-    private HealthChannel findConnectingChannel(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config) {
-        for (HealthChannel chan : mHealthChannels) {
-            if (chan.mDevice.equals(device) && chan.mConfig.equals(config) &&
-                chan.mState == BluetoothHealth.STATE_CHANNEL_CONNECTING) return chan;
-        }
-        return null;
-    }
-
-    ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config) {
-        HealthChannel chan = getMainChannel(device, config);
-        if (chan != null) {
-            ParcelFileDescriptor pfd =  null;
-            try {
-                pfd = chan.mChannelFd.dup();
-                return pfd;
-            } catch (IOException e) {
-                return null;
-            }
-        }
-
-        String objectPath =
-                mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        if (objectPath == null) return null;
-
-        String mainChannelPath = mBluetoothService.getMainChannelNative(objectPath);
-        if (mainChannelPath == null) return null;
-
-        // We had no record of the main channel but querying Bluez we got a
-        // main channel. We might not have received the PropertyChanged yet for
-        // the main channel creation so update our data structure here.
-        chan = findChannelByPath(device, mainChannelPath);
-        if (chan == null) {
-            errorLog("Main Channel present but we don't have any account of it:" +
-                    device +":" + config);
-            return null;
-        }
-        chan.mMainChannel = true;
-        try {
-            return chan.mChannelFd.dup();
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    /*package*/ void onHealthDevicePropertyChanged(String devicePath,
-            String channelPath) {
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        String address = mBluetoothService.getAddressFromObjectPath(devicePath);
-        if (address == null) return;
-
-        //TODO: Fix this in Bluez
-        if (channelPath.equals("/")) {
-            // This means that the main channel is being destroyed.
-            return;
-        }
-
-        BluetoothDevice device = adapter.getRemoteDevice(address);
-        BluetoothHealthAppConfiguration config = findHealthApplication(device,
-                channelPath);
-        if (config != null) {
-            HealthChannel chan = findChannelByPath(device, channelPath);
-            if (chan == null) {
-                errorLog("Health Channel is not present:" + channelPath);
-            } else {
-                chan.mMainChannel = true;
-            }
-        }
-    }
-
-    /*package*/ void onHealthDeviceChannelConnectionError(int chanCode,
-                                                          int state) {
-        HealthChannel channel = findChannelById(chanCode);
-        if (channel == null) errorLog("No record of this channel:" + chanCode);
-
-        callHealthChannelCallback(channel.mConfig, channel.mDevice, channel.mState, state, null,
-                chanCode);
-    }
-
-    private BluetoothHealthAppConfiguration findHealthApplication(
-            BluetoothDevice device, String channelPath) {
-        BluetoothHealthAppConfiguration config = null;
-        HealthChannel chan = findChannelByPath(device, channelPath);
-
-        if (chan != null) {
-            config = chan.mConfig;
-        } else {
-            String configPath = mBluetoothService.getChannelApplicationNative(channelPath);
-            if (configPath == null) {
-                errorLog("Config path is null for application");
-            } else {
-                for (Entry<BluetoothHealthAppConfiguration, String> e :
-                        mHealthAppConfigs.entrySet()) {
-                    if (e.getValue().equals(configPath)) {
-                        config = e.getKey();
-                    }
-                }
-                if (config == null) errorLog("No associated application for path:" + configPath);
-            }
-        }
-        return config;
-    }
-
-    /*package*/ void onHealthDeviceChannelChanged(String devicePath,
-            String channelPath, boolean exists) {
-        debugLog("onHealthDeviceChannelChanged: devicePath: " + devicePath +
-                "ChannelPath: " + channelPath + "Exists: " + exists);
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        String address = mBluetoothService.getAddressFromObjectPath(devicePath);
-        if (address == null) return;
-
-        BluetoothDevice device = adapter.getRemoteDevice(address);
-        BluetoothHealthAppConfiguration config;
-        int state, prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
-        ParcelFileDescriptor fd;
-        HealthChannel channel;
-        config = findHealthApplication(device, channelPath);
-
-        if (exists) {
-            channel = findConnectingChannel(device, config);
-            if (channel == null) {
-               channel = new HealthChannel(device, config, null, false,
-                       channelPath);
-               channel.mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
-               mHealthChannels.add(channel);
-            }
-            channel.mChannelPath = channelPath;
-
-            fd = mBluetoothService.getChannelFdNative(channelPath);
-            if (fd == null) {
-                errorLog("Error obtaining fd for channel:" + channelPath);
-                disconnectChannel(device, config, channel.mId);
-                return;
-            }
-            boolean mainChannel =
-                    getMainChannel(device, config) == null ? false : true;
-            if (!mainChannel) {
-                String mainChannelPath =
-                        mBluetoothService.getMainChannelNative(devicePath);
-                if (mainChannelPath == null) {
-                    errorLog("Main Channel Path is null for devicePath:" + devicePath);
-                    return;
-                }
-                if (mainChannelPath.equals(channelPath)) mainChannel = true;
-            }
-
-            channel.mChannelFd = fd;
-            channel.mMainChannel = mainChannel;
-            prevState = channel.mState;
-            state = BluetoothHealth.STATE_CHANNEL_CONNECTED;
-        } else {
-            channel = findChannelByPath(device, channelPath);
-            if (channel == null) {
-                errorLog("Channel not found:" + config + ":" + channelPath);
-                return;
-            }
-            mHealthChannels.remove(channel);
-
-            channel.mChannelFd = null;
-            prevState = channel.mState;
-            state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
-        }
-        channel.mState = state;
-        callHealthChannelCallback(config, device, prevState, state, channel.mChannelFd,
-                channel.mId);
-    }
-
-    private void callHealthChannelCallback(BluetoothHealthAppConfiguration config,
-            BluetoothDevice device, int prevState, int state, ParcelFileDescriptor fd, int id) {
-        broadcastHealthDeviceStateChange(device, prevState, state);
-
-        debugLog("Health Device Callback: " + device + " State Change: "
-                + prevState + "->" + state);
-
-        ParcelFileDescriptor dupedFd = null;
-        if (fd != null) {
-            try {
-                dupedFd = fd.dup();
-            } catch (IOException e) {
-                dupedFd = null;
-                errorLog("Exception while duping: " + e);
-            }
-        }
-
-        IBluetoothHealthCallback callback = mCallbacks.get(config);
-        if (callback != null) {
-            try {
-                callback.onHealthChannelStateChange(config, device, prevState, state, dupedFd, id);
-            } catch (RemoteException e) {
-                errorLog("Remote Exception:" + e);
-            }
-        }
-    }
-
-    private void callHealthApplicationStatusCallback(
-            BluetoothHealthAppConfiguration config, int status) {
-        debugLog("Health Device Application: " + config + " State Change: status:"
-                + status);
-        IBluetoothHealthCallback callback = mCallbacks.get(config);
-        if (callback != null) {
-            try {
-                callback.onHealthAppConfigurationStatusChange(config, status);
-            } catch (RemoteException e) {
-                errorLog("Remote Exception:" + e);
-            }
-        }
-    }
-
-    int getHealthDeviceConnectionState(BluetoothDevice device) {
-        if (mHealthDevices.get(device) == null) {
-            return BluetoothHealth.STATE_DISCONNECTED;
-        }
-        return mHealthDevices.get(device);
-    }
-
-    List<BluetoothDevice> getConnectedHealthDevices() {
-        List<BluetoothDevice> devices = lookupHealthDevicesMatchingStates(
-                    new int[] {BluetoothHealth.STATE_CONNECTED});
-        return devices;
-    }
-
-    List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(int[] states) {
-        List<BluetoothDevice> devices = lookupHealthDevicesMatchingStates(states);
-        return devices;
-    }
-
-    List<BluetoothDevice> lookupHealthDevicesMatchingStates(int[] states) {
-        List<BluetoothDevice> healthDevices = new ArrayList<BluetoothDevice>();
-
-        for (BluetoothDevice device: mHealthDevices.keySet()) {
-            int healthDeviceState = getHealthDeviceConnectionState(device);
-            for (int state : states) {
-                if (state == healthDeviceState) {
-                    healthDevices.add(device);
-                    break;
-                }
-            }
-        }
-        return healthDevices;
-    }
-
-    /**
-     * This function sends the intent for the updates on the connection status to the remote device.
-     * Note that multiple channels can be connected to the remote device by multiple applications.
-     * This sends an intent for the update to the device connection status and not the channel
-     * connection status. Only the following state transitions are possible:
-     *
-     * {@link BluetoothHealth#STATE_DISCONNECTED} to {@link BluetoothHealth#STATE_CONNECTING}
-     * {@link BluetoothHealth#STATE_CONNECTING} to {@link BluetoothHealth#STATE_CONNECTED}
-     * {@link BluetoothHealth#STATE_CONNECTED} to {@link BluetoothHealth#STATE_DISCONNECTING}
-     * {@link BluetoothHealth#STATE_DISCONNECTING} to {@link BluetoothHealth#STATE_DISCONNECTED}
-     * {@link BluetoothHealth#STATE_DISCONNECTED} to {@link BluetoothHealth#STATE_CONNECTED}
-     * {@link BluetoothHealth#STATE_CONNECTED} to {@link BluetoothHealth#STATE_DISCONNECTED}
-     * {@link BluetoothHealth#STATE_CONNECTING} to {{@link BluetoothHealth#STATE_DISCONNECTED}
-     *
-     * @param device
-     * @param prevChannelState
-     * @param newChannelState
-     * @hide
-     */
-    private void broadcastHealthDeviceStateChange(BluetoothDevice device, int prevChannelState,
-            int newChannelState) {
-        if (mHealthDevices.get(device) == null) {
-            mHealthDevices.put(device, BluetoothHealth.STATE_DISCONNECTED);
-        }
-
-        int currDeviceState = mHealthDevices.get(device);
-        int newDeviceState = convertState(newChannelState);
-
-        if (currDeviceState != newDeviceState) {
-            List<HealthChannel> chan;
-            switch (currDeviceState) {
-                case BluetoothHealth.STATE_DISCONNECTED:
-                    updateAndSendIntent(device, currDeviceState, newDeviceState);
-                    break;
-                case BluetoothHealth.STATE_CONNECTING:
-                    // Channel got connected.
-                    if (newDeviceState == BluetoothHealth.STATE_CONNECTED) {
-                        updateAndSendIntent(device, currDeviceState, newDeviceState);
-                    } else {
-                        // Channel got disconnected
-                        chan = findChannelByStates(device, new int [] {
-                                    BluetoothHealth.STATE_CHANNEL_CONNECTING,
-                                    BluetoothHealth.STATE_CHANNEL_DISCONNECTING});
-                        if (chan.isEmpty()) {
-                            updateAndSendIntent(device, currDeviceState, newDeviceState);
-                        }
-                    }
-                    break;
-                case BluetoothHealth.STATE_CONNECTED:
-                    // Channel got disconnected or is in disconnecting state.
-                    chan = findChannelByStates(device, new int [] {
-                                BluetoothHealth.STATE_CHANNEL_CONNECTING,
-                                BluetoothHealth.STATE_CHANNEL_CONNECTED});
-                    if (chan.isEmpty()) {
-                        updateAndSendIntent(device, currDeviceState, newDeviceState);
-                    }
-                    break;
-                case BluetoothHealth.STATE_DISCONNECTING:
-                    // Channel got disconnected.
-                    chan = findChannelByStates(device, new int [] {
-                                BluetoothHealth.STATE_CHANNEL_CONNECTING,
-                                BluetoothHealth.STATE_CHANNEL_DISCONNECTING});
-                    if (chan.isEmpty()) {
-                        updateAndSendIntent(device, currDeviceState, newDeviceState);
-                    }
-                    break;
-            }
-        }
-    }
-
-    private void updateAndSendIntent(BluetoothDevice device, int prevDeviceState,
-            int newDeviceState) {
-        mHealthDevices.put(device, newDeviceState);
-        mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.HEALTH,
-                                                    newDeviceState, prevDeviceState);
-    }
-
-    /**
-     * This function converts the channel connection state to device connection state.
-     *
-     * @param state
-     * @return
-     */
-    private int convertState(int state) {
-        switch (state) {
-            case BluetoothHealth.STATE_CHANNEL_CONNECTED:
-                return BluetoothHealth.STATE_CONNECTED;
-            case BluetoothHealth.STATE_CHANNEL_CONNECTING:
-                return BluetoothHealth.STATE_CONNECTING;
-            case BluetoothHealth.STATE_CHANNEL_DISCONNECTING:
-                return BluetoothHealth.STATE_DISCONNECTING;
-            case BluetoothHealth.STATE_CHANNEL_DISCONNECTED:
-                return BluetoothHealth.STATE_DISCONNECTED;
-        }
-        errorLog("Mismatch in Channel and Health Device State");
-        return -1;
-    }
-
-    private static void debugLog(String msg) {
-        if (DBG) Log.d(TAG, msg);
-    }
-
-    private static void errorLog(String msg) {
-        Log.e(TAG, msg);
-    }
-}
diff --git a/core/java/android/server/BluetoothInputProfileHandler.java b/core/java/android/server/BluetoothInputProfileHandler.java
deleted file mode 100644
index 31764b0..0000000
--- a/core/java/android/server/BluetoothInputProfileHandler.java
+++ /dev/null
@@ -1,227 +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.
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothDeviceProfileState;
-import android.bluetooth.BluetoothInputDevice;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothProfileState;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Message;
-import android.provider.Settings;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * This handles all the operations on the HID profile.
- * All functions are called by BluetoothService, as Bluetooth Service
- * is the Service handler for the HID profile.
- */
-final class BluetoothInputProfileHandler {
-    private static final String TAG = "BluetoothInputProfileHandler";
-    private static final boolean DBG = true;
-
-    public static BluetoothInputProfileHandler sInstance;
-    private Context mContext;
-    private BluetoothService mBluetoothService;
-    private final HashMap<BluetoothDevice, Integer> mInputDevices;
-    private final BluetoothProfileState mHidProfileState;
-
-    private BluetoothInputProfileHandler(Context context, BluetoothService service) {
-        mContext = context;
-        mBluetoothService = service;
-        mInputDevices = new HashMap<BluetoothDevice, Integer>();
-        mHidProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HID);
-        mHidProfileState.start();
-    }
-
-    static synchronized BluetoothInputProfileHandler getInstance(Context context,
-            BluetoothService service) {
-        if (sInstance == null) sInstance = new BluetoothInputProfileHandler(context, service);
-        return sInstance;
-    }
-
-    boolean connectInputDevice(BluetoothDevice device,
-                                            BluetoothDeviceProfileState state) {
-        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        if (objectPath == null ||
-            getInputDeviceConnectionState(device) != BluetoothInputDevice.STATE_DISCONNECTED ||
-            getInputDevicePriority(device) == BluetoothInputDevice.PRIORITY_OFF) {
-            return false;
-        }
-        if (state != null) {
-            Message msg = new Message();
-            msg.arg1 = BluetoothDeviceProfileState.CONNECT_HID_OUTGOING;
-            msg.obj = state;
-            mHidProfileState.sendMessage(msg);
-            return true;
-        }
-        return false;
-    }
-
-    boolean connectInputDeviceInternal(BluetoothDevice device) {
-        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_CONNECTING);
-        if (!mBluetoothService.connectInputDeviceNative(objectPath)) {
-            handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_DISCONNECTED);
-            return false;
-        }
-        return true;
-    }
-
-    boolean disconnectInputDevice(BluetoothDevice device,
-                                               BluetoothDeviceProfileState state) {
-        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        if (objectPath == null ||
-                getInputDeviceConnectionState(device) == BluetoothInputDevice.STATE_DISCONNECTED) {
-            return false;
-        }
-        if (state != null) {
-            Message msg = new Message();
-            msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_HID_OUTGOING;
-            msg.obj = state;
-            mHidProfileState.sendMessage(msg);
-            return true;
-        }
-        return false;
-    }
-
-    boolean disconnectInputDeviceInternal(BluetoothDevice device) {
-        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_DISCONNECTING);
-        if (!mBluetoothService.disconnectInputDeviceNative(objectPath)) {
-            handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_CONNECTED);
-            return false;
-        }
-        return true;
-    }
-
-    int getInputDeviceConnectionState(BluetoothDevice device) {
-        if (mInputDevices.get(device) == null) {
-            return BluetoothInputDevice.STATE_DISCONNECTED;
-        }
-        return mInputDevices.get(device);
-    }
-
-    List<BluetoothDevice> getConnectedInputDevices() {
-        List<BluetoothDevice> devices = lookupInputDevicesMatchingStates(
-            new int[] {BluetoothInputDevice.STATE_CONNECTED});
-        return devices;
-    }
-
-    List<BluetoothDevice> getInputDevicesMatchingConnectionStates(int[] states) {
-        List<BluetoothDevice> devices = lookupInputDevicesMatchingStates(states);
-        return devices;
-    }
-
-    int getInputDevicePriority(BluetoothDevice device) {
-        return Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()),
-                BluetoothInputDevice.PRIORITY_UNDEFINED);
-    }
-
-    boolean setInputDevicePriority(BluetoothDevice device, int priority) {
-        if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
-            return false;
-        }
-        return Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()),
-                priority);
-    }
-
-    List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) {
-        List<BluetoothDevice> inputDevices = new ArrayList<BluetoothDevice>();
-
-        for (BluetoothDevice device: mInputDevices.keySet()) {
-            int inputDeviceState = getInputDeviceConnectionState(device);
-            for (int state : states) {
-                if (state == inputDeviceState) {
-                    inputDevices.add(device);
-                    break;
-                }
-            }
-        }
-        return inputDevices;
-    }
-
-    private void handleInputDeviceStateChange(BluetoothDevice device, int state) {
-        int prevState;
-        if (mInputDevices.get(device) == null) {
-            prevState = BluetoothInputDevice.STATE_DISCONNECTED;
-        } else {
-            prevState = mInputDevices.get(device);
-        }
-        if (prevState == state) return;
-
-        mInputDevices.put(device, state);
-
-        if (getInputDevicePriority(device) >
-              BluetoothInputDevice.PRIORITY_OFF &&
-            state == BluetoothInputDevice.STATE_CONNECTING ||
-            state == BluetoothInputDevice.STATE_CONNECTED) {
-            // We have connected or attempting to connect.
-            // Bump priority
-            setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_AUTO_CONNECT);
-        }
-
-        Intent intent = new Intent(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-        intent.putExtra(BluetoothInputDevice.EXTRA_PREVIOUS_STATE, prevState);
-        intent.putExtra(BluetoothInputDevice.EXTRA_STATE, state);
-        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
-
-        debugLog("InputDevice state : device: " + device + " State:" + prevState + "->" + state);
-        mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.INPUT_DEVICE, state,
-                                                    prevState);
-    }
-
-    void handleInputDevicePropertyChange(String address, boolean connected) {
-        int state = connected ? BluetoothInputDevice.STATE_CONNECTED :
-            BluetoothInputDevice.STATE_DISCONNECTED;
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        BluetoothDevice device = adapter.getRemoteDevice(address);
-        handleInputDeviceStateChange(device, state);
-    }
-
-    void setInitialInputDevicePriority(BluetoothDevice device, int state) {
-        switch (state) {
-            case BluetoothDevice.BOND_BONDED:
-                if (getInputDevicePriority(device) == BluetoothInputDevice.PRIORITY_UNDEFINED) {
-                    setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_ON);
-                }
-                break;
-            case BluetoothDevice.BOND_NONE:
-                setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_UNDEFINED);
-                break;
-        }
-    }
-
-    private static void debugLog(String msg) {
-        if (DBG) Log.d(TAG, msg);
-    }
-
-    private static void errorLog(String msg) {
-        Log.e(TAG, msg);
-    }
-}
diff --git a/core/java/android/server/BluetoothPanProfileHandler.java b/core/java/android/server/BluetoothPanProfileHandler.java
deleted file mode 100644
index 41bb87f..0000000
--- a/core/java/android/server/BluetoothPanProfileHandler.java
+++ /dev/null
@@ -1,409 +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.
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothPan;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothTetheringDataTracker;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Resources.NotFoundException;
-import android.net.ConnectivityManager;
-import android.net.InterfaceConfiguration;
-import android.net.LinkAddress;
-import android.net.NetworkUtils;
-import android.os.IBinder;
-import android.os.INetworkManagementService;
-import android.os.ServiceManager;
-import android.util.Log;
-
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * This handles the PAN profile. All calls into this are made
- * from Bluetooth Service.
- */
-final class BluetoothPanProfileHandler {
-    private static final String TAG = "BluetoothPanProfileHandler";
-    private static final boolean DBG = true;
-
-    private ArrayList<String> mBluetoothIfaceAddresses;
-    private int mMaxPanDevices;
-
-    private static final String BLUETOOTH_IFACE_ADDR_START= "192.168.44.1";
-    private static final int BLUETOOTH_MAX_PAN_CONNECTIONS = 5;
-    private static final int BLUETOOTH_PREFIX_LENGTH        = 24;
-    public static BluetoothPanProfileHandler sInstance;
-    private final HashMap<BluetoothDevice, BluetoothPanDevice> mPanDevices;
-    private boolean mTetheringOn;
-    private Context mContext;
-    private BluetoothService mBluetoothService;
-
-    static final String NAP_ROLE = "nap";
-    static final String NAP_BRIDGE = "pan1";
-
-    private BluetoothPanProfileHandler(Context context, BluetoothService service) {
-        mContext = context;
-        mPanDevices = new HashMap<BluetoothDevice, BluetoothPanDevice>();
-        mBluetoothService = service;
-        mTetheringOn = false;
-        mBluetoothIfaceAddresses = new ArrayList<String>();
-        try {
-            mMaxPanDevices = context.getResources().getInteger(
-                            com.android.internal.R.integer.config_max_pan_devices);
-        } catch (NotFoundException e) {
-            mMaxPanDevices = BLUETOOTH_MAX_PAN_CONNECTIONS;
-        }
-    }
-
-    static BluetoothPanProfileHandler getInstance(Context context,
-            BluetoothService service) {
-        if (sInstance == null) sInstance = new BluetoothPanProfileHandler(context, service);
-        return sInstance;
-    }
-
-    boolean isTetheringOn() {
-        return mTetheringOn;
-    }
-
-    boolean allowIncomingTethering() {
-        if (isTetheringOn() && getConnectedPanDevices().size() < mMaxPanDevices)
-            return true;
-        return false;
-    }
-
-    private BroadcastReceiver mTetheringReceiver = null;
-
-    void setBluetoothTethering(boolean value) {
-        if (!value) {
-            disconnectPanServerDevices();
-        }
-
-        if (mBluetoothService.getBluetoothState() != BluetoothAdapter.STATE_ON && value) {
-            IntentFilter filter = new IntentFilter();
-            filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
-            mTetheringReceiver = new BroadcastReceiver() {
-                @Override
-                public void onReceive(Context context, Intent intent) {
-                    if (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF)
-                            == BluetoothAdapter.STATE_ON) {
-                        mTetheringOn = true;
-                        mContext.unregisterReceiver(mTetheringReceiver);
-                    }
-                }
-            };
-            mContext.registerReceiver(mTetheringReceiver, filter);
-        } else {
-            mTetheringOn = value;
-        }
-    }
-
-    int getPanDeviceConnectionState(BluetoothDevice device) {
-        BluetoothPanDevice panDevice = mPanDevices.get(device);
-        if (panDevice == null) {
-            return BluetoothPan.STATE_DISCONNECTED;
-        }
-        return panDevice.mState;
-    }
-
-    boolean connectPanDevice(BluetoothDevice device) {
-        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        if (DBG) Log.d(TAG, "connect PAN(" + objectPath + ")");
-        if (getPanDeviceConnectionState(device) != BluetoothPan.STATE_DISCONNECTED) {
-            errorLog(device + " already connected to PAN");
-        }
-
-        int connectedCount = 0;
-        for (BluetoothDevice panDevice: mPanDevices.keySet()) {
-            if (getPanDeviceConnectionState(panDevice) == BluetoothPan.STATE_CONNECTED) {
-                connectedCount ++;
-            }
-        }
-        if (connectedCount > 8) {
-            debugLog(device + " could not connect to PAN because 8 other devices are"
-                    + "already connected");
-            return false;
-        }
-
-        // Send interface as null as it is not known
-        handlePanDeviceStateChange(device, null, BluetoothPan.STATE_CONNECTING,
-                                           BluetoothPan.LOCAL_PANU_ROLE);
-        if (mBluetoothService.connectPanDeviceNative(objectPath, "nap")) {
-            debugLog("connecting to PAN");
-            return true;
-        } else {
-            handlePanDeviceStateChange(device, null, BluetoothPan.STATE_DISCONNECTED,
-                                                BluetoothPan.LOCAL_PANU_ROLE);
-            errorLog("could not connect to PAN");
-            return false;
-        }
-    }
-
-    private boolean disconnectPanServerDevices() {
-        debugLog("disconnect all PAN devices");
-
-        for (BluetoothDevice device: mPanDevices.keySet()) {
-            BluetoothPanDevice panDevice = mPanDevices.get(device);
-            int state = panDevice.mState;
-            if (state == BluetoothPan.STATE_CONNECTED &&
-                    panDevice.mLocalRole == BluetoothPan.LOCAL_NAP_ROLE) {
-                String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-
-                handlePanDeviceStateChange(device, panDevice.mIface,
-                        BluetoothPan.STATE_DISCONNECTING, panDevice.mLocalRole);
-
-                if (!mBluetoothService.disconnectPanServerDeviceNative(objectPath,
-                        device.getAddress(),
-                        panDevice.mIface)) {
-                    errorLog("could not disconnect Pan Server Device "+device.getAddress());
-
-                    // Restore prev state
-                    handlePanDeviceStateChange(device, panDevice.mIface, state,
-                            panDevice.mLocalRole);
-
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    List<BluetoothDevice> getConnectedPanDevices() {
-        List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
-
-        for (BluetoothDevice device: mPanDevices.keySet()) {
-            if (getPanDeviceConnectionState(device) == BluetoothPan.STATE_CONNECTED) {
-                devices.add(device);
-            }
-        }
-        return devices;
-    }
-
-    List<BluetoothDevice> getPanDevicesMatchingConnectionStates(int[] states) {
-        List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
-
-        for (BluetoothDevice device: mPanDevices.keySet()) {
-            int panDeviceState = getPanDeviceConnectionState(device);
-            for (int state : states) {
-                if (state == panDeviceState) {
-                    devices.add(device);
-                    break;
-                }
-            }
-        }
-        return devices;
-    }
-
-    boolean disconnectPanDevice(BluetoothDevice device) {
-        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
-        debugLog("disconnect PAN(" + objectPath + ")");
-
-        int state = getPanDeviceConnectionState(device);
-        if (state != BluetoothPan.STATE_CONNECTED) {
-            debugLog(device + " already disconnected from PAN");
-            return false;
-        }
-
-        BluetoothPanDevice panDevice = mPanDevices.get(device);
-
-        if (panDevice == null) {
-            errorLog("No record for this Pan device:" + device);
-            return false;
-        }
-
-        handlePanDeviceStateChange(device, panDevice.mIface, BluetoothPan.STATE_DISCONNECTING,
-                                    panDevice.mLocalRole);
-        if (panDevice.mLocalRole == BluetoothPan.LOCAL_NAP_ROLE) {
-            if (!mBluetoothService.disconnectPanServerDeviceNative(objectPath, device.getAddress(),
-                    panDevice.mIface)) {
-                // Restore prev state, this shouldn't happen
-                handlePanDeviceStateChange(device, panDevice.mIface, state, panDevice.mLocalRole);
-                return false;
-            }
-        } else {
-            if (!mBluetoothService.disconnectPanDeviceNative(objectPath)) {
-                // Restore prev state, this shouldn't happen
-                handlePanDeviceStateChange(device, panDevice.mIface, state, panDevice.mLocalRole);
-                return false;
-            }
-        }
-        return true;
-    }
-
-    void handlePanDeviceStateChange(BluetoothDevice device,
-                                                 String iface, int state, int role) {
-        int prevState;
-        String ifaceAddr = null;
-        BluetoothPanDevice panDevice = mPanDevices.get(device);
-
-        if (panDevice == null) {
-            prevState = BluetoothPan.STATE_DISCONNECTED;
-        } else {
-            prevState = panDevice.mState;
-            ifaceAddr = panDevice.mIfaceAddr;
-        }
-        if (prevState == state) return;
-
-        if (role == BluetoothPan.LOCAL_NAP_ROLE) {
-            if (state == BluetoothPan.STATE_CONNECTED) {
-                ifaceAddr = enableTethering(iface);
-                if (ifaceAddr == null) Log.e(TAG, "Error seting up tether interface");
-            } else if (state == BluetoothPan.STATE_DISCONNECTED) {
-                if (ifaceAddr != null) {
-                    mBluetoothIfaceAddresses.remove(ifaceAddr);
-                    ifaceAddr = null;
-                }
-            }
-        } else {
-            // PANU Role = reverse Tether
-            if (state == BluetoothPan.STATE_CONNECTED) {
-                BluetoothTetheringDataTracker.getInstance().startReverseTether(iface, device);
-            } else if (state == BluetoothPan.STATE_DISCONNECTED &&
-                  (prevState == BluetoothPan.STATE_CONNECTED ||
-                  prevState == BluetoothPan.STATE_DISCONNECTING)) {
-                BluetoothTetheringDataTracker.getInstance().stopReverseTether(panDevice.mIface);
-            }
-        }
-
-        if (panDevice == null) {
-            panDevice = new BluetoothPanDevice(state, ifaceAddr, iface, role);
-            mPanDevices.put(device, panDevice);
-        } else {
-            panDevice.mState = state;
-            panDevice.mIfaceAddr = ifaceAddr;
-            panDevice.mLocalRole = role;
-            panDevice.mIface = iface;
-        }
-
-        Intent intent = new Intent(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-        intent.putExtra(BluetoothPan.EXTRA_PREVIOUS_STATE, prevState);
-        intent.putExtra(BluetoothPan.EXTRA_STATE, state);
-        intent.putExtra(BluetoothPan.EXTRA_LOCAL_ROLE, role);
-        mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
-
-        debugLog("Pan Device state : device: " + device + " State:" + prevState + "->" + state);
-        mBluetoothService.sendConnectionStateChange(device, BluetoothProfile.PAN, state,
-                                                    prevState);
-    }
-
-    private class BluetoothPanDevice {
-        private int mState;
-        private String mIfaceAddr;
-        private String mIface;
-        private int mLocalRole; // Which local role is this PAN device bound to
-
-        BluetoothPanDevice(int state, String ifaceAddr, String iface, int localRole) {
-            mState = state;
-            mIfaceAddr = ifaceAddr;
-            mIface = iface;
-            mLocalRole = localRole;
-        }
-    }
-
-    private String createNewTetheringAddressLocked() {
-        if (getConnectedPanDevices().size() == mMaxPanDevices) {
-            debugLog ("Max PAN device connections reached");
-            return null;
-        }
-        String address = BLUETOOTH_IFACE_ADDR_START;
-        while (true) {
-            if (mBluetoothIfaceAddresses.contains(address)) {
-                String[] addr = address.split("\\.");
-                Integer newIp = Integer.parseInt(addr[2]) + 1;
-                address = address.replace(addr[2], newIp.toString());
-            } else {
-                break;
-            }
-        }
-        mBluetoothIfaceAddresses.add(address);
-        return address;
-    }
-
-    // configured when we start tethering
-    private String enableTethering(String iface) {
-        debugLog("updateTetherState:" + iface);
-
-        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
-        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
-        ConnectivityManager cm =
-            (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
-        String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs();
-
-        // bring toggle the interfaces
-        String[] currentIfaces = new String[0];
-        try {
-            currentIfaces = service.listInterfaces();
-        } catch (Exception e) {
-            Log.e(TAG, "Error listing Interfaces :" + e);
-            return null;
-        }
-
-        boolean found = false;
-        for (String currIface: currentIfaces) {
-            if (currIface.equals(iface)) {
-                found = true;
-                break;
-            }
-        }
-
-        if (!found) return null;
-
-        String address = createNewTetheringAddressLocked();
-        if (address == null) return null;
-
-        InterfaceConfiguration ifcg = null;
-        try {
-            ifcg = service.getInterfaceConfig(iface);
-            if (ifcg != null) {
-                final LinkAddress linkAddr = ifcg.getLinkAddress();
-                InetAddress addr = null;
-                if (linkAddr == null || (addr = linkAddr.getAddress()) == null ||
-                        addr.equals(NetworkUtils.numericToInetAddress("0.0.0.0")) ||
-                        addr.equals(NetworkUtils.numericToInetAddress("::0"))) {
-                    addr = NetworkUtils.numericToInetAddress(address);
-                }
-                ifcg.setInterfaceUp();
-                ifcg.clearFlag("running");
-                ifcg.setLinkAddress(new LinkAddress(addr, BLUETOOTH_PREFIX_LENGTH));
-                service.setInterfaceConfig(iface, ifcg);
-                if (cm.tether(iface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
-                    Log.e(TAG, "Error tethering "+iface);
-                }
-            }
-        } catch (Exception e) {
-            Log.e(TAG, "Error configuring interface " + iface + ", :" + e);
-            return null;
-        }
-        return address;
-    }
-
-    private static void debugLog(String msg) {
-        if (DBG) Log.d(TAG, msg);
-    }
-
-    private static void errorLog(String msg) {
-        Log.e(TAG, msg);
-    }
-}
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
deleted file mode 100755
index 6296b11..0000000
--- a/core/java/android/server/BluetoothService.java
+++ /dev/null
@@ -1,2924 +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.
- */
-
-/**
- * TODO: Move this to
- * java/services/com/android/server/BluetoothService.java
- * and make the contructor package private again.
- *
- * @hide
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothClass;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothDeviceProfileState;
-import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothHealthAppConfiguration;
-import android.bluetooth.BluetoothInputDevice;
-import android.bluetooth.BluetoothPan;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothProfileState;
-import android.bluetooth.BluetoothSocket;
-import android.bluetooth.BluetoothUuid;
-import android.bluetooth.IBluetooth;
-import android.bluetooth.IBluetoothCallback;
-import android.bluetooth.IBluetoothHealthCallback;
-import android.bluetooth.IBluetoothStateChangeCallback;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-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;
-import android.os.Message;
-import android.os.ParcelFileDescriptor;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.provider.Settings;
-import android.util.Log;
-import android.util.Pair;
-
-import com.android.internal.app.IBatteryStats;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.DataInputStream;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.io.RandomAccessFile;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-public class BluetoothService extends IBluetooth.Stub {
-    private static final String TAG = "BluetoothService";
-    private static final boolean DBG = true;
-
-    private int mNativeData;
-    private BluetoothEventLoop mEventLoop;
-    private BluetoothHeadset mHeadsetProxy;
-    private BluetoothInputDevice mInputDevice;
-    private BluetoothPan mPan;
-    private boolean mIsAirplaneSensitive;
-    private boolean mIsAirplaneToggleable;
-    private BluetoothAdapterStateMachine mBluetoothState;
-    private int[] mAdapterSdpHandles;
-    private ParcelUuid[] mAdapterUuids;
-
-    private BluetoothAdapter mAdapter;  // constant after init()
-    private final BluetoothBondState mBondState;  // local cache of bondings
-    private final IBatteryStats mBatteryStats;
-    private final Context mContext;
-    private Map<Integer, IBluetoothStateChangeCallback> mStateChangeTracker =
-        Collections.synchronizedMap(new HashMap<Integer, IBluetoothStateChangeCallback>());
-
-    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
-    static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
-
-    private static final String DOCK_ADDRESS_PATH = "/sys/class/switch/dock/bt_addr";
-    private static final String DOCK_PIN_PATH = "/sys/class/switch/dock/bt_pin";
-
-    private static final String SHARED_PREFERENCE_DOCK_ADDRESS = "dock_bluetooth_address";
-    private static final String SHARED_PREFERENCES_NAME = "bluetooth_service_settings";
-
-    private static final int MESSAGE_UUID_INTENT = 1;
-    private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 2;
-    private static final int MESSAGE_REMOVE_SERVICE_RECORD = 3;
-
-    private static final int RFCOMM_RECORD_REAPER = 10;
-    private static final int STATE_CHANGE_REAPER = 11;
-
-    // The time (in millisecs) to delay the pairing attempt after the first
-    // auto pairing attempt fails. We use an exponential delay with
-    // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the initial value and
-    // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the max value.
-    private static final long INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3000;
-    private static final long MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 12000;
-
-    // The timeout used to sent the UUIDs Intent
-    // This timeout should be greater than the page timeout
-    private static final int UUID_INTENT_DELAY = 6000;
-
-    /** Always retrieve RFCOMM channel for these SDP UUIDs */
-    private static final ParcelUuid[] RFCOMM_UUIDS = {
-            BluetoothUuid.Handsfree,
-            BluetoothUuid.HSP,
-            BluetoothUuid.ObexObjectPush };
-
-    private final BluetoothAdapterProperties mAdapterProperties;
-    private final BluetoothDeviceProperties mDeviceProperties;
-
-    private final HashMap<String, Map<ParcelUuid, Integer>> mDeviceServiceChannelCache;
-    private final ArrayList<String> mUuidIntentTracker;
-    private final HashMap<RemoteService, IBluetoothCallback> mUuidCallbackTracker;
-
-    private static class ServiceRecordClient {
-        int pid;
-        IBinder binder;
-        IBinder.DeathRecipient death;
-    }
-    private final HashMap<Integer, ServiceRecordClient> mServiceRecordToPid;
-
-    private final HashMap<String, BluetoothDeviceProfileState> mDeviceProfileState;
-    private final BluetoothProfileState mA2dpProfileState;
-    private final BluetoothProfileState mHfpProfileState;
-
-    private BluetoothA2dpService mA2dpService;
-    private final HashMap<String, Pair<byte[], byte[]>> mDeviceOobData;
-
-    private int mProfilesConnected = 0, mProfilesConnecting = 0, mProfilesDisconnecting = 0;
-
-    private static String mDockAddress;
-    private String mDockPin;
-
-    private boolean mAllowConnect = true;
-
-    private int mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
-    private BluetoothPanProfileHandler mBluetoothPanProfileHandler;
-    private BluetoothInputProfileHandler mBluetoothInputProfileHandler;
-    private BluetoothHealthProfileHandler mBluetoothHealthProfileHandler;
-    private static final String INCOMING_CONNECTION_FILE =
-      "/data/misc/bluetooth/incoming_connection.conf";
-    private HashMap<String, Pair<Integer, String>> mIncomingConnections;
-    private HashMap<Integer, Pair<Integer, Integer>> mProfileConnectionState;
-
-    private static class RemoteService {
-        public String address;
-        public ParcelUuid uuid;
-        public RemoteService(String address, ParcelUuid uuid) {
-            this.address = address;
-            this.uuid = uuid;
-        }
-        @Override
-        public boolean equals(Object o) {
-            if (o instanceof RemoteService) {
-                RemoteService service = (RemoteService)o;
-                return address.equals(service.address) && uuid.equals(service.uuid);
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            int hash = 1;
-            hash = hash * 31 + (address == null ? 0 : address.hashCode());
-            hash = hash * 31 + (uuid == null ? 0 : uuid.hashCode());
-            return hash;
-        }
-    }
-
-    static {
-        classInitNative();
-    }
-
-    public BluetoothService(Context context) {
-        mContext = context;
-
-        // Need to do this in place of:
-        // mBatteryStats = BatteryStatsService.getService();
-        // Since we can not import BatteryStatsService from here. This class really needs to be
-        // moved to java/services/com/android/server/
-        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
-
-        initializeNativeDataNative();
-
-        if (isEnabledNative() == 1) {
-            Log.w(TAG, "Bluetooth daemons already running - runtime restart? ");
-            disableNative();
-        }
-
-        mBondState = new BluetoothBondState(context, this);
-        mAdapterProperties = new BluetoothAdapterProperties(context, this);
-        mDeviceProperties = new BluetoothDeviceProperties(this);
-
-        mDeviceServiceChannelCache = new HashMap<String, Map<ParcelUuid, Integer>>();
-        mDeviceOobData = new HashMap<String, Pair<byte[], byte[]>>();
-        mUuidIntentTracker = new ArrayList<String>();
-        mUuidCallbackTracker = new HashMap<RemoteService, IBluetoothCallback>();
-        mServiceRecordToPid = new HashMap<Integer, ServiceRecordClient>();
-        mDeviceProfileState = new HashMap<String, BluetoothDeviceProfileState>();
-        mA2dpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.A2DP);
-        mHfpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HFP);
-
-        mHfpProfileState.start();
-        mA2dpProfileState.start();
-
-        IntentFilter filter = new IntentFilter();
-        registerForAirplaneMode(filter);
-
-        filter.addAction(Intent.ACTION_DOCK_EVENT);
-        mContext.registerReceiver(mReceiver, filter);
-        mBluetoothInputProfileHandler = BluetoothInputProfileHandler.getInstance(mContext, this);
-        mBluetoothPanProfileHandler = BluetoothPanProfileHandler.getInstance(mContext, this);
-        mBluetoothHealthProfileHandler = BluetoothHealthProfileHandler.getInstance(mContext, this);
-        mIncomingConnections = new HashMap<String, Pair<Integer, String>>();
-        mProfileConnectionState = new HashMap<Integer, Pair<Integer, Integer>>();
-    }
-
-    public static synchronized String readDockBluetoothAddress() {
-        if (mDockAddress != null) return mDockAddress;
-
-        BufferedInputStream file = null;
-        String dockAddress;
-        try {
-            file = new BufferedInputStream(new FileInputStream(DOCK_ADDRESS_PATH));
-            byte[] address = new byte[17];
-            file.read(address);
-            dockAddress = new String(address);
-            dockAddress = dockAddress.toUpperCase();
-            if (BluetoothAdapter.checkBluetoothAddress(dockAddress)) {
-                mDockAddress = dockAddress;
-                return mDockAddress;
-            } else {
-                Log.e(TAG, "CheckBluetoothAddress failed for car dock address: "
-                        + dockAddress);
-            }
-        } catch (FileNotFoundException e) {
-            Log.e(TAG, "FileNotFoundException while trying to read dock address");
-        } catch (IOException e) {
-            Log.e(TAG, "IOException while trying to read dock address");
-        } finally {
-            if (file != null) {
-                try {
-                    file.close();
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
-        }
-        mDockAddress = null;
-        return null;
-    }
-
-    private synchronized boolean writeDockPin() {
-        BufferedWriter out = null;
-        try {
-            out = new BufferedWriter(new FileWriter(DOCK_PIN_PATH));
-
-            // Generate a random 4 digit pin between 0000 and 9999
-            // This is not truly random but good enough for our purposes.
-            int pin = (int) Math.floor(Math.random() * 10000);
-
-            mDockPin = String.format("%04d", pin);
-            out.write(mDockPin);
-            return true;
-        } catch (FileNotFoundException e) {
-            Log.e(TAG, "FileNotFoundException while trying to write dock pairing pin");
-        } catch (IOException e) {
-            Log.e(TAG, "IOException while while trying to write dock pairing pin");
-        } finally {
-            if (out != null) {
-                try {
-                    out.close();
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
-        }
-        mDockPin = null;
-        return false;
-    }
-
-    /*package*/ synchronized String getDockPin() {
-        return mDockPin;
-    }
-
-    public synchronized void initAfterRegistration() {
-        mAdapter = BluetoothAdapter.getDefaultAdapter();
-        mBluetoothState = new BluetoothAdapterStateMachine(mContext, this, mAdapter);
-        mBluetoothState.start();
-        if (mContext.getResources().getBoolean
-            (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
-            mBluetoothState.sendMessage(BluetoothAdapterStateMachine.TURN_HOT);
-        }
-        mEventLoop = mBluetoothState.getBluetoothEventLoop();
-    }
-
-    public synchronized void initAfterA2dpRegistration() {
-        mEventLoop.getProfileProxy();
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        mContext.unregisterReceiver(mReceiver);
-        try {
-            cleanupNativeDataNative();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    public boolean isEnabled() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        return isEnabledInternal();
-    }
-
-    private boolean isEnabledInternal() {
-        return (getBluetoothStateInternal() == BluetoothAdapter.STATE_ON);
-    }
-
-    public int getBluetoothState() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        return getBluetoothStateInternal();
-    }
-
-    int getBluetoothStateInternal() {
-        return mBluetoothState.getBluetoothAdapterState();
-    }
-
-    /**
-     * Bring down bluetooth and disable BT in settings. Returns true on success.
-     */
-    public boolean disable() {
-        return disable(true);
-    }
-
-    /**
-     * Bring down bluetooth. Returns true on success.
-     *
-     * @param saveSetting If true, persist the new setting
-     */
-    public synchronized boolean disable(boolean saveSetting) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
-
-        int adapterState = getBluetoothStateInternal();
-
-        switch (adapterState) {
-        case BluetoothAdapter.STATE_OFF:
-            return true;
-        case BluetoothAdapter.STATE_ON:
-            break;
-        default:
-            return false;
-        }
-
-        mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_OFF, saveSetting);
-        return true;
-    }
-
-    synchronized void disconnectDevices() {
-        // Disconnect devices handled by BluetoothService.
-        for (BluetoothDevice device: getConnectedInputDevices()) {
-            disconnectInputDevice(device);
-        }
-
-        for (BluetoothDevice device: getConnectedPanDevices()) {
-            disconnectPanDevice(device);
-        }
-    }
-
-    /**
-     * The Bluetooth has been turned off, but hot. Do bonding, profile cleanup
-     */
-    synchronized void finishDisable() {
-        // mark in progress bondings as cancelled
-        for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) {
-            mBondState.setBondState(address, BluetoothDevice.BOND_NONE,
-                                    BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
-        }
-
-        // Stop the profile state machine for bonded devices.
-        for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDED)) {
-            removeProfileState(address);
-        }
-
-        // update mode
-        Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
-        intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.SCAN_MODE_NONE);
-        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-    }
-
-    /**
-     * Local clean up after broadcasting STATE_OFF intent
-     */
-    synchronized void cleanupAfterFinishDisable() {
-        mAdapterProperties.clear();
-
-        for (Integer srHandle : mServiceRecordToPid.keySet()) {
-            removeServiceRecordNative(srHandle);
-        }
-        mServiceRecordToPid.clear();
-
-        mProfilesConnected = 0;
-        mProfilesConnecting = 0;
-        mProfilesDisconnecting = 0;
-        mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
-        mAdapterUuids = null;
-        mAdapterSdpHandles = null;
-
-        // Log bluetooth off to battery stats.
-        long ident = Binder.clearCallingIdentity();
-        try {
-            mBatteryStats.noteBluetoothOff();
-        } catch (RemoteException e) {
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
-    /**
-     * power off Bluetooth
-     */
-    synchronized void shutoffBluetooth() {
-        if (mAdapterSdpHandles != null) removeReservedServiceRecordsNative(mAdapterSdpHandles);
-        setBluetoothTetheringNative(false, BluetoothPanProfileHandler.NAP_ROLE,
-                BluetoothPanProfileHandler.NAP_BRIDGE);
-        tearDownNativeDataNative();
-    }
-
-    /**
-     * Data clean up after Bluetooth shutoff
-     */
-    synchronized void cleanNativeAfterShutoffBluetooth() {
-        // Ths method is called after shutdown of event loop in the Bluetooth shut down
-        // procedure
-
-        // the adapter property could be changed before event loop is stoped, clear it again
-        mAdapterProperties.clear();
-        disableNative();
-    }
-
-    /** Bring up BT and persist BT on in settings */
-    public boolean enable() {
-        return enable(true, true);
-    }
-
-    /**
-     * Enable this Bluetooth device, asynchronously.
-     * This turns on/off the underlying hardware.
-     *
-     * @param saveSetting If true, persist the new state of BT in settings
-     * @param allowConnect If true, auto-connects device when BT is turned on
-     *                     and allows incoming A2DP/HSP connections
-     * @return True on success (so far)
-     */
-    public synchronized boolean enable(boolean saveSetting, boolean allowConnect) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-
-        // Airplane mode can prevent Bluetooth radio from being turned on.
-        if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) {
-            return false;
-        }
-        mAllowConnect = allowConnect;
-        mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_ON, saveSetting);
-        return true;
-    }
-
-    /**
-     * Enable this Bluetooth device, asynchronously, but does not
-     * auto-connect devices. In this state the Bluetooth adapter
-     * also does not allow incoming A2DP/HSP connections (that
-     * must go through this service), but does allow communication
-     * on RFCOMM sockets implemented outside of this service (ie BTOPP).
-     * This method is used to temporarily enable Bluetooth
-     * for data transfer, without changing
-     *
-     * This turns on/off the underlying hardware.
-     *
-     * @return True on success (so far)
-     */
-    public boolean enableNoAutoConnect() {
-        return enable(false, false);
-    }
-
-    /**
-     * Turn on Bluetooth Module, Load firmware, and do all the preparation
-     * needed to get the Bluetooth Module ready but keep it not discoverable
-     * and not connectable.
-     */
-    /* package */ synchronized boolean prepareBluetooth() {
-        if (!setupNativeDataNative()) {
-            return false;
-        }
-        switchConnectable(false);
-
-        // Bluetooth stack needs a small delay here before adding
-        // SDP records, otherwise dbus stalls for over 30 seconds 1 out of 50 runs
-        try {
-            Thread.sleep(50);
-        } catch (InterruptedException e) {}
-        updateSdpRecords();
-        return true;
-    }
-
-    private final Handler mHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-            case MESSAGE_UUID_INTENT:
-                String address = (String)msg.obj;
-                if (address != null) {
-                    sendUuidIntent(address);
-                    makeServiceChannelCallbacks(address);
-                }
-                break;
-            case MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY:
-                address = (String)msg.obj;
-                if (address == null) return;
-                int attempt = mBondState.getAttempt(address);
-
-                // Try only if attemps are in progress and cap it 2 attempts
-                // The 2 attempts cap is a fail safe if the stack returns
-                // an incorrect error code for bonding failures and if the pin
-                // is entered wrongly twice we should abort.
-                if (attempt > 0 && attempt <= 2) {
-                    mBondState.attempt(address);
-                    createBond(address);
-                    return;
-                }
-                if (attempt > 0) mBondState.clearPinAttempts(address);
-                break;
-            case MESSAGE_REMOVE_SERVICE_RECORD:
-                Pair<Integer, Integer> pair = (Pair<Integer, Integer>) msg.obj;
-                checkAndRemoveRecord(pair.first, pair.second);
-                break;
-            }
-        }
-    };
-
-    private synchronized void addReservedSdpRecords(final ArrayList<ParcelUuid> uuids) {
-        //Register SDP records.
-        int[] svcIdentifiers = new int[uuids.size()];
-        for (int i = 0; i < uuids.size(); i++) {
-            svcIdentifiers[i] = BluetoothUuid.getServiceIdentifierFromParcelUuid(uuids.get(i));
-        }
-        mAdapterSdpHandles = addReservedServiceRecordsNative(svcIdentifiers);
-    }
-
-    private synchronized void updateSdpRecords() {
-        ArrayList<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
-
-        Resources R = mContext.getResources();
-
-        // 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);
-        }
-
-        // Add SDP records for profiles maintained by Android userspace
-        addReservedSdpRecords(uuids);
-
-        // Bluetooth stack need some a small delay here before adding more
-        // SDP records, otherwise dbus stalls for over 30 seconds 1 out of 50 runs
-        try {
-            Thread.sleep(50);
-        } catch (InterruptedException e) {}
-
-        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);
-        }
-
-        // Cannot cast uuids.toArray directly since ParcelUuid is parcelable
-        mAdapterUuids = new ParcelUuid[uuids.size()];
-        for (int i = 0; i < uuids.size(); i++) {
-            mAdapterUuids[i] = uuids.get(i);
-        }
-    }
-
-    /**
-     * This function is called from Bluetooth Event Loop when onPropertyChanged
-     * for adapter comes in with UUID property.
-     * @param uuidsThe uuids of adapter as reported by Bluez.
-     */
-    /*package*/ synchronized void updateBluetoothState(String uuids) {
-        ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids);
-
-        if (mAdapterUuids != null &&
-            BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) {
-            mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SERVICE_RECORD_LOADED);
-        }
-    }
-
-    /**
-     * This method is called immediately before Bluetooth module is turned on after
-     * the adapter became pariable.
-     * It inits bond state and profile state before STATE_ON intent is broadcasted.
-     */
-    /*package*/ void initBluetoothAfterTurningOn() {
-        String discoverable = getProperty("Discoverable", false);
-        String timeout = getProperty("DiscoverableTimeout", false);
-        if (timeout == null) {
-            Log.w(TAG, "Null DiscoverableTimeout property");
-            // assign a number, anything not 0
-            timeout = "1";
-        }
-        if (discoverable.equals("true") && Integer.valueOf(timeout) != 0) {
-            setAdapterPropertyBooleanNative("Discoverable", 0);
-        }
-        mBondState.initBondState();
-        initProfileState();
-        getProfileProxy();
-    }
-
-    /**
-     * This method is called immediately after Bluetooth module is turned on.
-     * It starts auto-connection and places bluetooth on sign onto the battery
-     * stats
-     */
-    /*package*/ void runBluetooth() {
-        autoConnect();
-
-        // Log bluetooth on to battery stats.
-        long ident = Binder.clearCallingIdentity();
-        try {
-            mBatteryStats.noteBluetoothOn();
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
-    /*package*/ synchronized boolean attemptAutoPair(String address) {
-        if (!mBondState.hasAutoPairingFailed(address) &&
-                !mBondState.isAutoPairingBlacklisted(address)) {
-            mBondState.attempt(address);
-            setPin(address, BluetoothDevice.convertPinToBytes("0000"));
-            return true;
-        }
-        return false;
-    }
-
-    /*package*/ synchronized boolean isFixedPinZerosAutoPairKeyboard(String address) {
-        // Check for keyboards which have fixed PIN 0000 as the pairing pin
-        return mBondState.isFixedPinZerosAutoPairKeyboard(address);
-    }
-
-    /*package*/ synchronized void onCreatePairedDeviceResult(String address, int result) {
-        if (result == BluetoothDevice.BOND_SUCCESS) {
-            setBondState(address, BluetoothDevice.BOND_BONDED);
-            if (mBondState.isAutoPairingAttemptsInProgress(address)) {
-                mBondState.clearPinAttempts(address);
-            }
-        } else if (result == BluetoothDevice.UNBOND_REASON_AUTH_FAILED &&
-                mBondState.getAttempt(address) == 1) {
-            mBondState.addAutoPairingFailure(address);
-            pairingAttempt(address, result);
-        } else if (result == BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN &&
-              mBondState.isAutoPairingAttemptsInProgress(address)) {
-            pairingAttempt(address, result);
-        } else {
-            setBondState(address, BluetoothDevice.BOND_NONE, result);
-            if (mBondState.isAutoPairingAttemptsInProgress(address)) {
-                mBondState.clearPinAttempts(address);
-            }
-        }
-    }
-
-    /*package*/ synchronized String getPendingOutgoingBonding() {
-        return mBondState.getPendingOutgoingBonding();
-    }
-
-    private void pairingAttempt(String address, int result) {
-        // This happens when our initial guess of "0000" as the pass key
-        // fails. Try to create the bond again and display the pin dialog
-        // to the user. Use back-off while posting the delayed
-        // message. The initial value is
-        // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY and the max value is
-        // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY. If the max value is
-        // reached, display an error to the user.
-        int attempt = mBondState.getAttempt(address);
-        if (attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY >
-                    MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY) {
-            mBondState.clearPinAttempts(address);
-            setBondState(address, BluetoothDevice.BOND_NONE, result);
-            return;
-        }
-
-        Message message = mHandler.obtainMessage(MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY);
-        message.obj = address;
-        boolean postResult =  mHandler.sendMessageDelayed(message,
-                                        attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY);
-        if (!postResult) {
-            mBondState.clearPinAttempts(address);
-            setBondState(address,
-                    BluetoothDevice.BOND_NONE, result);
-            return;
-        }
-    }
-
-    /*package*/ BluetoothDevice getRemoteDevice(String address) {
-        return mAdapter.getRemoteDevice(address);
-    }
-
-    private static String toBondStateString(int bondState) {
-        switch (bondState) {
-        case BluetoothDevice.BOND_NONE:
-            return "not bonded";
-        case BluetoothDevice.BOND_BONDING:
-            return "bonding";
-        case BluetoothDevice.BOND_BONDED:
-            return "bonded";
-        default:
-            return "??????";
-        }
-    }
-
-    public synchronized boolean setName(String name) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (name == null) {
-            return false;
-        }
-        return setPropertyString("Name", name);
-    }
-
-    //TODO(): setPropertyString, setPropertyInteger, setPropertyBoolean
-    // Either have a single property function with Object as the parameter
-    // or have a function for each property and then obfuscate in the JNI layer.
-    // The following looks dirty.
-    private boolean setPropertyString(String key, String value) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!isEnabledInternal()) return false;
-        return setAdapterPropertyStringNative(key, value);
-    }
-
-    private boolean setPropertyInteger(String key, int value) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!isEnabledInternal()) return false;
-        return setAdapterPropertyIntegerNative(key, value);
-    }
-
-    private boolean setPropertyBoolean(String key, boolean value) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!isEnabledInternal()) return false;
-        return setAdapterPropertyBooleanNative(key, value ? 1 : 0);
-    }
-
-    /**
-     * Set the discoverability window for the device.  A timeout of zero
-     * makes the device permanently discoverable (if the device is
-     * discoverable).  Setting the timeout to a nonzero value does not make
-     * a device discoverable; you need to call setMode() to make the device
-     * explicitly discoverable.
-     *
-     * @param timeout The discoverable timeout in seconds.
-     */
-    public synchronized boolean setDiscoverableTimeout(int timeout) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        return setPropertyInteger("DiscoverableTimeout", timeout);
-    }
-
-    public synchronized boolean setScanMode(int mode, int duration) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
-                                                "Need WRITE_SECURE_SETTINGS permission");
-        boolean pairable;
-        boolean discoverable;
-
-        switch (mode) {
-        case BluetoothAdapter.SCAN_MODE_NONE:
-            pairable = false;
-            discoverable = false;
-            break;
-        case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
-            pairable = true;
-            discoverable = false;
-            break;
-        case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
-            pairable = true;
-            discoverable = true;
-            if (DBG) Log.d(TAG, "BT Discoverable for " + duration + " seconds");
-            break;
-        default:
-            Log.w(TAG, "Requested invalid scan mode " + mode);
-            return false;
-        }
-
-        setPropertyBoolean("Discoverable", discoverable);
-        setPropertyBoolean("Pairable", pairable);
-        return true;
-    }
-
-    /**
-     * @param on true set the local Bluetooth module to be connectable
-     *                The dicoverability is recovered to what it was before
-     *                switchConnectable(false) call
-     *           false set the local Bluetooth module to be not connectable
-     *                 and not dicoverable
-     */
-    /*package*/ synchronized void switchConnectable(boolean on) {
-        setAdapterPropertyBooleanNative("Powered", on ? 1 : 0);
-    }
-
-    /*package*/ synchronized void setPairable() {
-        String pairableString = getProperty("Pairable", false);
-        if (pairableString == null) {
-            Log.e(TAG, "null pairableString");
-            return;
-        }
-        if (pairableString.equals("false")) {
-            setAdapterPropertyBooleanNative("Pairable", 1);
-        }
-    }
-
-    /*package*/ String getProperty(String name, boolean checkState) {
-        // If checkState is false, check if the event loop is running.
-        // before making the call to Bluez
-        if (checkState) {
-            if (!isEnabledInternal()) return null;
-        } else if (!mEventLoop.isEventLoopRunning()) {
-            return null;
-        }
-
-        return mAdapterProperties.getProperty(name);
-    }
-
-    BluetoothAdapterProperties getAdapterProperties() {
-        return mAdapterProperties;
-    }
-
-    BluetoothDeviceProperties getDeviceProperties() {
-        return mDeviceProperties;
-    }
-
-    boolean isRemoteDeviceInCache(String address) {
-        return mDeviceProperties.isInCache(address);
-    }
-
-    void setRemoteDeviceProperty(String address, String name, String value) {
-        mDeviceProperties.setProperty(address, name, value);
-    }
-
-    void updateRemoteDevicePropertiesCache(String address) {
-        mDeviceProperties.updateCache(address);
-    }
-
-    public synchronized String getAddress() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        // Don't check state since we want to provide address, even if BT is off
-        return getProperty("Address", false);
-    }
-
-    public synchronized String getName() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        // Don't check state since we want to provide name, even if BT is off
-        return getProperty("Name", false);
-    }
-
-    public ParcelUuid[] getUuids() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        String value =  getProperty("UUIDs", true);
-        if (value == null) return null;
-        return convertStringToParcelUuid(value);
-    }
-
-    private ParcelUuid[] convertStringToParcelUuid(String value) {
-        String[] uuidStrings = null;
-        // The UUIDs are stored as a "," separated string.
-        uuidStrings = value.split(",");
-        ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length];
-
-        for (int i = 0; i < uuidStrings.length; i++) {
-            uuids[i] = ParcelUuid.fromString(uuidStrings[i]);
-        }
-        return uuids;
-    }
-
-    /**
-     * Returns the user-friendly name of a remote device.  This value is
-     * returned from our local cache, which is updated when onPropertyChange
-     * event is received.
-     * Do not expect to retrieve the updated remote name immediately after
-     * changing the name on the remote device.
-     *
-     * @param address Bluetooth address of remote device.
-     *
-     * @return The user-friendly name of the specified remote device.
-     */
-    public synchronized String getRemoteName(String address) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return null;
-        }
-        return mDeviceProperties.getProperty(address, "Name");
-    }
-
-    /**
-     * Returns alias of a remote device.  This value is returned from our
-     * local cache, which is updated when onPropertyChange event is received.
-     *
-     * @param address Bluetooth address of remote device.
-     *
-     * @return The alias of the specified remote device.
-     */
-    public synchronized String getRemoteAlias(String address) {
-
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return null;
-        }
-        return mDeviceProperties.getProperty(address, "Alias");
-    }
-
-    /**
-     * Set the alias of a remote device.
-     *
-     * @param address Bluetooth address of remote device.
-     * @param alias new alias to change to
-     * @return true on success, false on error
-     */
-    public synchronized boolean setRemoteAlias(String address, String alias) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-
-        return setDevicePropertyStringNative(getObjectPathFromAddress(address),
-                                             "Alias", alias);
-    }
-
-    /**
-     * Get the discoverability window for the device.  A timeout of zero
-     * means that the device is permanently discoverable (if the device is
-     * in the discoverable mode).
-     *
-     * @return The discoverability window of the device, in seconds.  A negative
-     *         value indicates an error.
-     */
-    public int getDiscoverableTimeout() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        String timeout = getProperty("DiscoverableTimeout", true);
-        if (timeout != null)
-           return Integer.valueOf(timeout);
-        else
-            return -1;
-    }
-
-    public int getScanMode() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!isEnabledInternal())
-            return BluetoothAdapter.SCAN_MODE_NONE;
-
-        boolean pairable = getProperty("Pairable", true).equals("true");
-        boolean discoverable = getProperty("Discoverable", true).equals("true");
-        return bluezStringToScanMode (pairable, discoverable);
-    }
-
-    public synchronized boolean startDiscovery() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        return startDiscoveryNative();
-    }
-
-    public synchronized boolean cancelDiscovery() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        return stopDiscoveryNative();
-    }
-
-    public boolean isDiscovering() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-
-        String discoveringProperty = getProperty("Discovering", false);
-        if (discoveringProperty == null) {
-            return false;
-        }
-
-        return discoveringProperty.equals("true");
-    }
-
-    private boolean isBondingFeasible(String address) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-        address = address.toUpperCase();
-
-        if (mBondState.getPendingOutgoingBonding() != null) {
-            Log.d(TAG, "Ignoring createBond(): another device is bonding");
-            // a different device is currently bonding, fail
-            return false;
-        }
-
-        // Check for bond state only if we are not performing auto
-        // pairing exponential back-off attempts.
-        if (!mBondState.isAutoPairingAttemptsInProgress(address) &&
-                mBondState.getBondState(address) != BluetoothDevice.BOND_NONE) {
-            Log.d(TAG, "Ignoring createBond(): this device is already bonding or bonded");
-            return false;
-        }
-
-        if (address.equals(mDockAddress)) {
-            if (!writeDockPin()) {
-                Log.e(TAG, "Error while writing Pin for the dock");
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public synchronized boolean createBond(String address) {
-        if (!isBondingFeasible(address)) return false;
-
-        if (!createPairedDeviceNative(address, 60000  /*1 minute*/ )) {
-            return false;
-        }
-
-        mBondState.setPendingOutgoingBonding(address);
-        mBondState.setBondState(address, BluetoothDevice.BOND_BONDING);
-
-        return true;
-    }
-
-    public synchronized boolean createBondOutOfBand(String address, byte[] hash,
-                                                    byte[] randomizer) {
-        if (!isBondingFeasible(address)) return false;
-
-        if (!createPairedDeviceOutOfBandNative(address, 60000 /* 1 minute */)) {
-            return false;
-        }
-
-        setDeviceOutOfBandData(address, hash, randomizer);
-        mBondState.setPendingOutgoingBonding(address);
-        mBondState.setBondState(address, BluetoothDevice.BOND_BONDING);
-
-        return true;
-    }
-
-    public synchronized boolean setDeviceOutOfBandData(String address, byte[] hash,
-            byte[] randomizer) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        Pair <byte[], byte[]> value = new Pair<byte[], byte[]>(hash, randomizer);
-
-        if (DBG) {
-            Log.d(TAG, "Setting out of band data for: " + address + ":" +
-                  Arrays.toString(hash) + ":" + Arrays.toString(randomizer));
-        }
-
-        mDeviceOobData.put(address, value);
-        return true;
-    }
-
-    Pair<byte[], byte[]> getDeviceOutOfBandData(BluetoothDevice device) {
-        return mDeviceOobData.get(device.getAddress());
-    }
-
-
-    public synchronized byte[] readOutOfBandData() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                                                "Need BLUETOOTH permission");
-        if (!isEnabledInternal()) return null;
-
-        return readAdapterOutOfBandDataNative();
-    }
-
-    public synchronized boolean cancelBondProcess(String address) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-        address = address.toUpperCase();
-        if (mBondState.getBondState(address) != BluetoothDevice.BOND_BONDING) {
-            return false;
-        }
-
-        mBondState.setBondState(address, BluetoothDevice.BOND_NONE,
-                                BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
-        cancelDeviceCreationNative(address);
-        return true;
-    }
-
-    public synchronized boolean removeBond(String address) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state != null) {
-            state.sendMessage(BluetoothDeviceProfileState.UNPAIR);
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    public synchronized boolean removeBondInternal(String address) {
-        // Unset the trusted device state and then unpair
-        setTrust(address, false);
-        return removeDeviceNative(getObjectPathFromAddress(address));
-    }
-
-    public synchronized String[] listBonds() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        return mBondState.listInState(BluetoothDevice.BOND_BONDED);
-    }
-
-    /*package*/ synchronized String[] listInState(int state) {
-      return mBondState.listInState(state);
-    }
-
-    public synchronized int getBondState(String address) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return BluetoothDevice.ERROR;
-        }
-        return mBondState.getBondState(address.toUpperCase());
-    }
-
-    /*package*/ synchronized boolean setBondState(String address, int state) {
-        return setBondState(address, state, 0);
-    }
-
-    /*package*/ synchronized boolean setBondState(String address, int state, int reason) {
-        mBondState.setBondState(address.toUpperCase(), state, reason);
-        return true;
-    }
-
-    public synchronized boolean isBluetoothDock(String address) {
-        SharedPreferences sp = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME,
-                Context.MODE_PRIVATE);
-
-        return sp.contains(SHARED_PREFERENCE_DOCK_ADDRESS + address);
-    }
-
-    /*package*/ String[] getRemoteDeviceProperties(String address) {
-        if (!isEnabledInternal()) return null;
-
-        String objectPath = getObjectPathFromAddress(address);
-        return (String [])getDevicePropertiesNative(objectPath);
-    }
-
-    /**
-     * Sets the remote device trust state.
-     *
-     * @return boolean to indicate operation success or fail
-     */
-    public synchronized boolean setTrust(String address, boolean value) {
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                    "Need BLUETOOTH_ADMIN permission");
-            return false;
-        }
-
-        if (!isEnabledInternal()) return false;
-
-        return setDevicePropertyBooleanNative(
-                getObjectPathFromAddress(address), "Trusted", value ? 1 : 0);
-    }
-
-    /**
-     * Gets the remote device trust state as boolean.
-     * Note: this value may be
-     * retrieved from cache if we retrieved the data before *
-     *
-     * @return boolean to indicate trusted or untrusted state
-     */
-    public synchronized boolean getTrustState(String address) {
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-            return false;
-        }
-
-        String val = mDeviceProperties.getProperty(address, "Trusted");
-        if (val == null) {
-            return false;
-        } else {
-            return val.equals("true");
-        }
-    }
-
-    /**
-     * Gets the remote major, minor classes encoded as a 32-bit
-     * integer.
-     *
-     * Note: this value is retrieved from cache, because we get it during
-     *       remote-device discovery.
-     *
-     * @return 32-bit integer encoding the remote major, minor, and service
-     *         classes.
-     */
-    public synchronized int getRemoteClass(String address) {
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-            return BluetoothClass.ERROR;
-        }
-        String val = mDeviceProperties.getProperty(address, "Class");
-        if (val == null)
-            return BluetoothClass.ERROR;
-        else {
-            return Integer.valueOf(val);
-        }
-    }
-
-
-    /**
-     * Gets the UUIDs supported by the remote device
-     *
-     * @return array of 128bit ParcelUuids
-     */
-    public synchronized ParcelUuid[] getRemoteUuids(String address) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return null;
-        }
-        return getUuidFromCache(address);
-    }
-
-    ParcelUuid[] getUuidFromCache(String address) {
-        String value = mDeviceProperties.getProperty(address, "UUIDs");
-        if (value == null) return null;
-
-        String[] uuidStrings = null;
-        // The UUIDs are stored as a "," separated string.
-        uuidStrings = value.split(",");
-        ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length];
-
-        for (int i = 0; i < uuidStrings.length; i++) {
-            uuids[i] = ParcelUuid.fromString(uuidStrings[i]);
-        }
-        return uuids;
-    }
-
-    /**
-     * Connect and fetch new UUID's using SDP.
-     * The UUID's found are broadcast as intents.
-     * Optionally takes a uuid and callback to fetch the RFCOMM channel for the
-     * a given uuid.
-     * TODO: Don't wait UUID_INTENT_DELAY to broadcast UUID intents on success
-     * TODO: Don't wait UUID_INTENT_DELAY to handle the failure case for
-     * callback and broadcast intents.
-     */
-    public synchronized boolean fetchRemoteUuids(String address, ParcelUuid uuid,
-            IBluetoothCallback callback) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!isEnabledInternal()) return false;
-
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-
-        RemoteService service = new RemoteService(address, uuid);
-        if (uuid != null && mUuidCallbackTracker.get(service) != null) {
-            // An SDP query for this address & uuid is already in progress
-            // Do not add this callback for the uuid
-            return false;
-        }
-
-        if (mUuidIntentTracker.contains(address)) {
-            // An SDP query for this address is already in progress
-            // Add this uuid onto the in-progress SDP query
-            if (uuid != null) {
-                mUuidCallbackTracker.put(new RemoteService(address, uuid), callback);
-            }
-            return true;
-        }
-
-        // If the device is already created, we will
-        // do the SDP on the callback of createDeviceNative.
-        boolean ret= createDeviceNative(address);
-
-        mUuidIntentTracker.add(address);
-        if (uuid != null) {
-            mUuidCallbackTracker.put(new RemoteService(address, uuid), callback);
-        }
-
-        Message message = mHandler.obtainMessage(MESSAGE_UUID_INTENT);
-        message.obj = address;
-        mHandler.sendMessageDelayed(message, UUID_INTENT_DELAY);
-        return ret;
-    }
-
-    /**
-     * Gets the rfcomm channel associated with the UUID.
-     * Pulls records from the cache only.
-     *
-     * @param address Address of the remote device
-     * @param uuid ParcelUuid of the service attribute
-     *
-     * @return rfcomm channel associated with the service attribute
-     *         -1 on error
-     */
-    public int getRemoteServiceChannel(String address, ParcelUuid uuid) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!isEnabledInternal()) return -1;
-
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return BluetoothDevice.ERROR;
-        }
-        // Check if we are recovering from a crash.
-        if (mDeviceProperties.isEmpty()) {
-            if (mDeviceProperties.updateCache(address) == null)
-                return -1;
-        }
-
-        Map<ParcelUuid, Integer> value = mDeviceServiceChannelCache.get(address);
-        if (value != null && value.containsKey(uuid))
-            return value.get(uuid);
-        return -1;
-    }
-
-    public synchronized boolean setPin(String address, byte[] pin) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        if (pin == null || pin.length <= 0 || pin.length > 16 ||
-            !BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-        address = address.toUpperCase();
-        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
-        if (data == null) {
-            Log.w(TAG, "setPin(" + address + ") called but no native data available, " +
-                  "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
-                  " or by bluez.\n");
-            return false;
-        }
-        // bluez API wants pin as a string
-        String pinString;
-        try {
-            pinString = new String(pin, "UTF8");
-        } catch (UnsupportedEncodingException uee) {
-            Log.e(TAG, "UTF8 not supported?!?");
-            return false;
-        }
-        return setPinNative(address, pinString, data.intValue());
-    }
-
-    public synchronized boolean setPasskey(String address, int passkey) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        if (passkey < 0 || passkey > 999999 || !BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-        address = address.toUpperCase();
-        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
-        if (data == null) {
-            Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " +
-                  "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
-                  " or by bluez.\n");
-            return false;
-        }
-        return setPasskeyNative(address, passkey, data.intValue());
-    }
-
-    public synchronized boolean setPairingConfirmation(String address, boolean confirm) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        address = address.toUpperCase();
-        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
-        if (data == null) {
-            Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " +
-                  "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
-                  " or by bluez.\n");
-            return false;
-        }
-        return setPairingConfirmationNative(address, confirm, data.intValue());
-    }
-
-    public synchronized boolean setRemoteOutOfBandData(String address) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-        address = address.toUpperCase();
-        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
-        if (data == null) {
-            Log.w(TAG, "setRemoteOobData(" + address + ") called but no native data available, " +
-                  "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
-                  " or by bluez.\n");
-            return false;
-        }
-
-        Pair<byte[], byte[]> val = mDeviceOobData.get(address);
-        byte[] hash, randomizer;
-        if (val == null) {
-            // TODO: check what should be passed in this case.
-            hash = new byte[16];
-            randomizer = new byte[16];
-        } else {
-            hash = val.first;
-            randomizer = val.second;
-        }
-        return setRemoteOutOfBandDataNative(address, hash, randomizer, data.intValue());
-    }
-
-    public synchronized boolean cancelPairingUserInput(String address) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!isEnabledInternal()) return false;
-
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-        mBondState.setBondState(address, BluetoothDevice.BOND_NONE,
-                BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
-        address = address.toUpperCase();
-        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
-        if (data == null) {
-            Log.w(TAG, "cancelUserInputNative(" + address + ") called but no native data " +
-                "available, ignoring. Maybe the PasskeyAgent Request was already cancelled " +
-                "by the remote or by bluez.\n");
-            return false;
-        }
-        return cancelPairingUserInputNative(address, data.intValue());
-    }
-
-    /*package*/ void updateDeviceServiceChannelCache(String address) {
-        if (DBG) Log.d(TAG, "updateDeviceServiceChannelCache(" + address + ")");
-
-        // We are storing the rfcomm channel numbers only for the uuids
-        // we are interested in.
-        ParcelUuid[] deviceUuids = getRemoteUuids(address);
-
-        ArrayList<ParcelUuid> applicationUuids = new ArrayList<ParcelUuid>();
-
-        synchronized (this) {
-            for (RemoteService service : mUuidCallbackTracker.keySet()) {
-                if (service.address.equals(address)) {
-                    applicationUuids.add(service.uuid);
-                }
-            }
-        }
-
-        Map <ParcelUuid, Integer> uuidToChannelMap = new HashMap<ParcelUuid, Integer>();
-
-        // Retrieve RFCOMM channel for default uuids
-        for (ParcelUuid uuid : RFCOMM_UUIDS) {
-            if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) {
-                int channel = getDeviceServiceChannelForUuid(address, uuid);
-                uuidToChannelMap.put(uuid, channel);
-                if (DBG) Log.d(TAG, "\tuuid(system): " + uuid + " " + channel);
-            }
-        }
-        // Retrieve RFCOMM channel for application requested uuids
-        for (ParcelUuid uuid : applicationUuids) {
-            if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) {
-                int channel = getDeviceServiceChannelForUuid(address, uuid);
-                uuidToChannelMap.put(uuid, channel);
-                if (DBG) Log.d(TAG, "\tuuid(application): " + uuid + " " + channel);
-            }
-        }
-
-        synchronized (this) {
-            // Make application callbacks
-            for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator();
-                    iter.hasNext();) {
-                RemoteService service = iter.next();
-                if (service.address.equals(address)) {
-                    if (uuidToChannelMap.containsKey(service.uuid)) {
-                        int channel = uuidToChannelMap.get(service.uuid);
-
-                        if (DBG) Log.d(TAG, "Making callback for " + service.uuid +
-                                    " with result " + channel);
-                        IBluetoothCallback callback = mUuidCallbackTracker.get(service);
-                        if (callback != null) {
-                            try {
-                                callback.onRfcommChannelFound(channel);
-                            } catch (RemoteException e) {Log.e(TAG, "", e);}
-                        }
-
-                        iter.remove();
-                    }
-                }
-            }
-
-            // Update cache
-            mDeviceServiceChannelCache.put(address, uuidToChannelMap);
-        }
-    }
-
-    private int getDeviceServiceChannelForUuid(String address,
-            ParcelUuid uuid) {
-        return getDeviceServiceChannelNative(getObjectPathFromAddress(address),
-                uuid.toString(), 0x0004);
-    }
-
-    /**
-     * b is a handle to a Binder instance, so that this service can be notified
-     * for Applications that terminate unexpectedly, to clean there service
-     * records
-     */
-    public synchronized int addRfcommServiceRecord(String serviceName, ParcelUuid uuid,
-            int channel, IBinder b) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (!isEnabledInternal()) return -1;
-
-        if (serviceName == null || uuid == null || channel < 1 ||
-                channel > BluetoothSocket.MAX_RFCOMM_CHANNEL) {
-            return -1;
-        }
-        if (BluetoothUuid.isUuidPresent(BluetoothUuid.RESERVED_UUIDS, uuid)) {
-            Log.w(TAG, "Attempted to register a reserved UUID: " + uuid);
-            return -1;
-        }
-        int handle = addRfcommServiceRecordNative(serviceName,
-                uuid.getUuid().getMostSignificantBits(), uuid.getUuid().getLeastSignificantBits(),
-                (short)channel);
-        if (DBG) Log.d(TAG, "new handle " + Integer.toHexString(handle));
-        if (handle == -1) {
-            return -1;
-        }
-
-        ServiceRecordClient client = new ServiceRecordClient();
-        client.pid = Binder.getCallingPid();
-        client.binder = b;
-        client.death = new Reaper(handle, client.pid, RFCOMM_RECORD_REAPER);
-        mServiceRecordToPid.put(new Integer(handle), client);
-        try {
-            b.linkToDeath(client.death, 0);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            client.death = null;
-        }
-        return handle;
-    }
-
-    public void removeServiceRecord(int handle) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                                                "Need BLUETOOTH permission");
-        // Since this is a binder call check if Bluetooth is off
-        if (getBluetoothStateInternal() == BluetoothAdapter.STATE_OFF) return;
-        Message message = mHandler.obtainMessage(MESSAGE_REMOVE_SERVICE_RECORD);
-        message.obj = new Pair<Integer, Integer>(handle, Binder.getCallingPid());
-        mHandler.sendMessage(message);
-    }
-
-    private synchronized void checkAndRemoveRecord(int handle, int pid) {
-        ServiceRecordClient client = mServiceRecordToPid.get(handle);
-        if (client != null && pid == client.pid) {
-            if (DBG) Log.d(TAG, "Removing service record " +
-                Integer.toHexString(handle) + " for pid " + pid);
-
-            if (client.death != null) {
-                client.binder.unlinkToDeath(client.death, 0);
-            }
-
-            mServiceRecordToPid.remove(handle);
-            removeServiceRecordNative(handle);
-        }
-    }
-
-    private class Reaper implements IBinder.DeathRecipient {
-        int mPid;
-        int mHandle;
-        int mType;
-
-        Reaper(int handle, int pid, int type) {
-            mPid = pid;
-            mHandle = handle;
-            mType = type;
-        }
-
-        Reaper(int pid, int type) {
-            mPid = pid;
-            mType = type;
-        }
-
-        @Override
-        public void binderDied() {
-            synchronized (BluetoothService.this) {
-                if (DBG) Log.d(TAG, "Tracked app " + mPid + " died" + "Type:" + mType);
-                if (mType == RFCOMM_RECORD_REAPER) {
-                    checkAndRemoveRecord(mHandle, mPid);
-                } else if (mType == STATE_CHANGE_REAPER) {
-                    mStateChangeTracker.remove(mPid);
-                }
-            }
-        }
-    }
-
-
-    @Override
-    public boolean changeApplicationBluetoothState(boolean on,
-            IBluetoothStateChangeCallback callback, IBinder binder) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-
-        int pid = Binder.getCallingPid();
-        //mStateChangeTracker is a synchronized map
-        if (!mStateChangeTracker.containsKey(pid)) {
-            if (on) {
-                mStateChangeTracker.put(pid, callback);
-            } else {
-                return false;
-            }
-        } else if (!on) {
-            mStateChangeTracker.remove(pid);
-        }
-
-        if (binder != null) {
-            try {
-                binder.linkToDeath(new Reaper(pid, STATE_CHANGE_REAPER), 0);
-            } catch (RemoteException e) {
-                Log.e(TAG, "", e);
-                return false;
-            }
-        }
-
-        int type;
-        if (on) {
-            type = BluetoothAdapterStateMachine.PER_PROCESS_TURN_ON;
-        } else {
-            type = BluetoothAdapterStateMachine.PER_PROCESS_TURN_OFF;
-        }
-
-        mBluetoothState.sendMessage(type, callback);
-        return true;
-    }
-
-    boolean isApplicationStateChangeTrackerEmpty() {
-        return mStateChangeTracker.isEmpty();
-    }
-
-    void clearApplicationStateChangeTracker() {
-        mStateChangeTracker.clear();
-    }
-
-    Collection<IBluetoothStateChangeCallback> getApplicationStateChangeCallbacks() {
-        return mStateChangeTracker.values();
-    }
-
-    int getNumberOfApplicationStateChangeTrackers() {
-        return mStateChangeTracker.size();
-    }
-
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (intent == null) return;
-
-            String action = intent.getAction();
-            if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
-                ContentResolver resolver = context.getContentResolver();
-                // Query the airplane mode from Settings.System just to make sure that
-                // some random app is not sending this intent and disabling bluetooth
-                if (isAirplaneModeOn()) {
-                    mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_ON);
-                } else {
-                    mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_OFF);
-                }
-            } else if (Intent.ACTION_DOCK_EVENT.equals(action)) {
-                int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
-                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
-                if (DBG) Log.v(TAG, "Received ACTION_DOCK_EVENT with State:" + state);
-                if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
-                    mDockAddress = null;
-                    mDockPin = null;
-                } else {
-                    SharedPreferences.Editor editor =
-                        mContext.getSharedPreferences(SHARED_PREFERENCES_NAME,
-                                mContext.MODE_PRIVATE).edit();
-                    editor.putBoolean(SHARED_PREFERENCE_DOCK_ADDRESS + mDockAddress, true);
-                    editor.apply();
-                }
-            }
-        }
-    };
-
-    private void registerForAirplaneMode(IntentFilter filter) {
-        final ContentResolver resolver = mContext.getContentResolver();
-        final String airplaneModeRadios = Settings.System.getString(resolver,
-                Settings.System.AIRPLANE_MODE_RADIOS);
-        final String toggleableRadios = Settings.System.getString(resolver,
-                Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
-
-        mIsAirplaneSensitive = airplaneModeRadios == null ? true :
-                airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH);
-        mIsAirplaneToggleable = toggleableRadios == null ? false :
-                toggleableRadios.contains(Settings.System.RADIO_BLUETOOTH);
-
-        if (mIsAirplaneSensitive) {
-            filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
-        }
-    }
-
-    /* Returns true if airplane mode is currently on */
-    /*package*/ final boolean isAirplaneModeOn() {
-        return Settings.System.getInt(mContext.getContentResolver(),
-                Settings.System.AIRPLANE_MODE_ON, 0) == 1;
-    }
-
-    /* Broadcast the Uuid intent */
-    /*package*/ synchronized void sendUuidIntent(String address) {
-        ParcelUuid[] uuid = getUuidFromCache(address);
-        Intent intent = new Intent(BluetoothDevice.ACTION_UUID);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_UUID, uuid);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-        mUuidIntentTracker.remove(address);
-    }
-
-    /*package*/ synchronized void makeServiceChannelCallbacks(String address) {
-        for (Iterator<RemoteService> iter = mUuidCallbackTracker.keySet().iterator();
-                iter.hasNext();) {
-            RemoteService service = iter.next();
-            if (service.address.equals(address)) {
-                if (DBG) Log.d(TAG, "Cleaning up failed UUID channel lookup: "
-                    + service.address + " " + service.uuid);
-                IBluetoothCallback callback = mUuidCallbackTracker.get(service);
-                if (callback != null) {
-                    try {
-                        callback.onRfcommChannelFound(-1);
-                    } catch (RemoteException e) {Log.e(TAG, "", e);}
-                }
-
-                iter.remove();
-            }
-        }
-    }
-
-    @Override
-    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
-
-        if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) {
-            return;
-        }
-
-        pw.println("mIsAirplaneSensitive = " + mIsAirplaneSensitive);
-        pw.println("mIsAirplaneToggleable = " + mIsAirplaneToggleable);
-
-        pw.println("Local address = " + getAddress());
-        pw.println("Local name = " + getName());
-        pw.println("isDiscovering() = " + isDiscovering());
-
-        mAdapter.getProfileProxy(mContext,
-                                 mBluetoothProfileServiceListener, BluetoothProfile.HEADSET);
-        mAdapter.getProfileProxy(mContext,
-                mBluetoothProfileServiceListener, BluetoothProfile.INPUT_DEVICE);
-        mAdapter.getProfileProxy(mContext,
-                mBluetoothProfileServiceListener, BluetoothProfile.PAN);
-
-        dumpKnownDevices(pw);
-        dumpAclConnectedDevices(pw);
-        dumpHeadsetService(pw);
-        dumpInputDeviceProfile(pw);
-        dumpPanProfile(pw);
-        dumpApplicationServiceRecords(pw);
-        dumpProfileState(pw);
-    }
-
-    private void dumpProfileState(PrintWriter pw) {
-        pw.println("\n--Profile State dump--");
-        pw.println("\n Headset profile state:" +
-                mAdapter.getProfileConnectionState(BluetoothProfile.HEADSET));
-        pw.println("\n A2dp profile state:" +
-                mAdapter.getProfileConnectionState(BluetoothProfile.A2DP));
-        pw.println("\n HID profile state:" +
-                mAdapter.getProfileConnectionState(BluetoothProfile.INPUT_DEVICE));
-        pw.println("\n PAN profile state:" +
-                mAdapter.getProfileConnectionState(BluetoothProfile.PAN));
-    }
-
-    private void dumpHeadsetService(PrintWriter pw) {
-        pw.println("\n--Headset Service--");
-        if (mHeadsetProxy != null) {
-            List<BluetoothDevice> deviceList = mHeadsetProxy.getConnectedDevices();
-            if (deviceList.size() == 0) {
-                pw.println("No headsets connected");
-            } else {
-                BluetoothDevice device = deviceList.get(0);
-                pw.println("\ngetConnectedDevices[0] = " + device);
-                dumpHeadsetConnectionState(pw, device);
-                pw.println("getBatteryUsageHint() = " +
-                             mHeadsetProxy.getBatteryUsageHint(device));
-            }
-
-            deviceList.clear();
-            deviceList = mHeadsetProxy.getDevicesMatchingConnectionStates(new int[] {
-                     BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED});
-            pw.println("--Connected and Disconnected Headsets");
-            for (BluetoothDevice device: deviceList) {
-                pw.println(device);
-                if (mHeadsetProxy.isAudioConnected(device)) {
-                    pw.println("SCO audio connected to device:" + device);
-                }
-            }
-        }
-    }
-
-    private void dumpInputDeviceProfile(PrintWriter pw) {
-        pw.println("\n--Bluetooth Service- Input Device Profile");
-        if (mInputDevice != null) {
-            List<BluetoothDevice> deviceList = mInputDevice.getConnectedDevices();
-            if (deviceList.size() == 0) {
-                pw.println("No input devices connected");
-            } else {
-                pw.println("Number of connected devices:" + deviceList.size());
-                BluetoothDevice device = deviceList.get(0);
-                pw.println("getConnectedDevices[0] = " + device);
-                pw.println("Priority of Connected device = " + mInputDevice.getPriority(device));
-
-                switch (mInputDevice.getConnectionState(device)) {
-                    case BluetoothInputDevice.STATE_CONNECTING:
-                        pw.println("getConnectionState() = STATE_CONNECTING");
-                        break;
-                    case BluetoothInputDevice.STATE_CONNECTED:
-                        pw.println("getConnectionState() = STATE_CONNECTED");
-                        break;
-                    case BluetoothInputDevice.STATE_DISCONNECTING:
-                        pw.println("getConnectionState() = STATE_DISCONNECTING");
-                        break;
-                }
-            }
-            deviceList.clear();
-            deviceList = mInputDevice.getDevicesMatchingConnectionStates(new int[] {
-                     BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED});
-            pw.println("--Connected and Disconnected input devices");
-            for (BluetoothDevice device: deviceList) {
-                pw.println(device);
-            }
-        }
-    }
-
-    private void dumpPanProfile(PrintWriter pw) {
-        pw.println("\n--Bluetooth Service- Pan Profile");
-        if (mPan != null) {
-            List<BluetoothDevice> deviceList = mPan.getConnectedDevices();
-            if (deviceList.size() == 0) {
-                pw.println("No Pan devices connected");
-            } else {
-                pw.println("Number of connected devices:" + deviceList.size());
-                BluetoothDevice device = deviceList.get(0);
-                pw.println("getConnectedDevices[0] = " + device);
-
-                switch (mPan.getConnectionState(device)) {
-                    case BluetoothInputDevice.STATE_CONNECTING:
-                        pw.println("getConnectionState() = STATE_CONNECTING");
-                        break;
-                    case BluetoothInputDevice.STATE_CONNECTED:
-                        pw.println("getConnectionState() = STATE_CONNECTED");
-                        break;
-                    case BluetoothInputDevice.STATE_DISCONNECTING:
-                        pw.println("getConnectionState() = STATE_DISCONNECTING");
-                        break;
-                }
-            }
-            deviceList.clear();
-            deviceList = mPan.getDevicesMatchingConnectionStates(new int[] {
-                     BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED});
-            pw.println("--Connected and Disconnected Pan devices");
-            for (BluetoothDevice device: deviceList) {
-                pw.println(device);
-            }
-        }
-    }
-
-    private void dumpHeadsetConnectionState(PrintWriter pw,
-            BluetoothDevice device) {
-        switch (mHeadsetProxy.getConnectionState(device)) {
-            case BluetoothHeadset.STATE_CONNECTING:
-                pw.println("getConnectionState() = STATE_CONNECTING");
-                break;
-            case BluetoothHeadset.STATE_CONNECTED:
-                pw.println("getConnectionState() = STATE_CONNECTED");
-                break;
-            case BluetoothHeadset.STATE_DISCONNECTING:
-                pw.println("getConnectionState() = STATE_DISCONNECTING");
-                break;
-            case BluetoothHeadset.STATE_AUDIO_CONNECTED:
-                pw.println("getConnectionState() = STATE_AUDIO_CONNECTED");
-                break;
-        }
-    }
-
-    private void dumpApplicationServiceRecords(PrintWriter pw) {
-        pw.println("\n--Application Service Records--");
-        for (Integer handle : mServiceRecordToPid.keySet()) {
-            Integer pid = mServiceRecordToPid.get(handle).pid;
-            pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle));
-        }
-    }
-
-    private void dumpAclConnectedDevices(PrintWriter pw) {
-        String[] devicesObjectPath = getKnownDevices();
-        pw.println("\n--ACL connected devices--");
-        if (devicesObjectPath != null) {
-            for (String device : devicesObjectPath) {
-                pw.println(getAddressFromObjectPath(device));
-            }
-        }
-    }
-
-    private void dumpKnownDevices(PrintWriter pw) {
-        pw.println("\n--Known devices--");
-        for (String address : mDeviceProperties.keySet()) {
-            int bondState = mBondState.getBondState(address);
-            pw.printf("%s %10s (%d) %s\n", address,
-                       toBondStateString(bondState),
-                       mBondState.getAttempt(address),
-                       getRemoteName(address));
-
-            Map<ParcelUuid, Integer> uuidChannels = mDeviceServiceChannelCache.get(address);
-            if (uuidChannels == null) {
-                pw.println("\tuuids = null");
-            } else {
-                for (ParcelUuid uuid : uuidChannels.keySet()) {
-                    Integer channel = uuidChannels.get(uuid);
-                    if (channel == null) {
-                        pw.println("\t" + uuid);
-                    } else {
-                        pw.println("\t" + uuid + " RFCOMM channel = " + channel);
-                    }
-                }
-            }
-            for (RemoteService service : mUuidCallbackTracker.keySet()) {
-                if (service.address.equals(address)) {
-                    pw.println("\tPENDING CALLBACK: " + service.uuid);
-                }
-            }
-        }
-    }
-
-    private void getProfileProxy() {
-        mAdapter.getProfileProxy(mContext,
-                                 mBluetoothProfileServiceListener, BluetoothProfile.HEADSET);
-    }
-
-    private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
-        new BluetoothProfile.ServiceListener() {
-        public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (profile == BluetoothProfile.HEADSET) {
-                mHeadsetProxy = (BluetoothHeadset) proxy;
-            } else if (profile == BluetoothProfile.INPUT_DEVICE) {
-                mInputDevice = (BluetoothInputDevice) proxy;
-            } else if (profile == BluetoothProfile.PAN) {
-                mPan = (BluetoothPan) proxy;
-            }
-        }
-        public void onServiceDisconnected(int profile) {
-            if (profile == BluetoothProfile.HEADSET) {
-                mHeadsetProxy = null;
-            } else if (profile == BluetoothProfile.INPUT_DEVICE) {
-                mInputDevice = null;
-            } else if (profile == BluetoothProfile.PAN) {
-                mPan = null;
-            }
-        }
-    };
-
-    /* package */ static int bluezStringToScanMode(boolean pairable, boolean discoverable) {
-        if (pairable && discoverable)
-            return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
-        else if (pairable && !discoverable)
-            return BluetoothAdapter.SCAN_MODE_CONNECTABLE;
-        else
-            return BluetoothAdapter.SCAN_MODE_NONE;
-    }
-
-    /* package */ static String scanModeToBluezString(int mode) {
-        switch (mode) {
-        case BluetoothAdapter.SCAN_MODE_NONE:
-            return "off";
-        case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
-            return "connectable";
-        case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
-            return "discoverable";
-        }
-        return null;
-    }
-
-    /*package*/ String getAddressFromObjectPath(String objectPath) {
-        String adapterObjectPath = mAdapterProperties.getObjectPath();
-        if (adapterObjectPath == null || objectPath == null) {
-            Log.e(TAG, "getAddressFromObjectPath: AdapterObjectPath:" + adapterObjectPath +
-                    "  or deviceObjectPath:" + objectPath + " is null");
-            return null;
-        }
-        if (!objectPath.startsWith(adapterObjectPath)) {
-            Log.e(TAG, "getAddressFromObjectPath: AdapterObjectPath:" + adapterObjectPath +
-                    "  is not a prefix of deviceObjectPath:" + objectPath +
-                    "bluetoothd crashed ?");
-            return null;
-        }
-        String address = objectPath.substring(adapterObjectPath.length());
-        if (address != null) return address.replace('_', ':');
-
-        Log.e(TAG, "getAddressFromObjectPath: Address being returned is null");
-        return null;
-    }
-
-    /*package*/ String getObjectPathFromAddress(String address) {
-        String path = mAdapterProperties.getObjectPath();
-        if (path == null) {
-            Log.e(TAG, "Error: Object Path is null");
-            return null;
-        }
-        path = path + address.replace(":", "_");
-        return path;
-    }
-
-    /*package */ void setLinkTimeout(String address, int num_slots) {
-        String path = getObjectPathFromAddress(address);
-        boolean result = setLinkTimeoutNative(path, num_slots);
-
-        if (!result) Log.d(TAG, "Set Link Timeout to " + num_slots + " slots failed");
-    }
-
-    /**** Handlers for PAN  Profile ****/
-    // TODO: This needs to be converted to a state machine.
-
-    public boolean isTetheringOn() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothPanProfileHandler) {
-            return mBluetoothPanProfileHandler.isTetheringOn();
-        }
-    }
-
-    /*package*/boolean allowIncomingTethering() {
-        synchronized (mBluetoothPanProfileHandler) {
-            return mBluetoothPanProfileHandler.allowIncomingTethering();
-        }
-    }
-
-    public void setBluetoothTethering(boolean value) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothPanProfileHandler) {
-            mBluetoothPanProfileHandler.setBluetoothTethering(value);
-        }
-    }
-
-    public int getPanDeviceConnectionState(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothPanProfileHandler) {
-            return mBluetoothPanProfileHandler.getPanDeviceConnectionState(device);
-        }
-    }
-
-    public boolean connectPanDevice(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-            "Need BLUETOOTH_ADMIN permission");
-        synchronized (mBluetoothPanProfileHandler) {
-            return mBluetoothPanProfileHandler.connectPanDevice(device);
-        }
-    }
-
-    public List<BluetoothDevice> getConnectedPanDevices() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothPanProfileHandler) {
-            return mBluetoothPanProfileHandler.getConnectedPanDevices();
-        }
-    }
-
-    public List<BluetoothDevice> getPanDevicesMatchingConnectionStates(
-            int[] states) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothPanProfileHandler) {
-            return mBluetoothPanProfileHandler.getPanDevicesMatchingConnectionStates(states);
-        }
-    }
-
-    public boolean disconnectPanDevice(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-            "Need BLUETOOTH_ADMIN permission");
-        synchronized (mBluetoothPanProfileHandler) {
-            return mBluetoothPanProfileHandler.disconnectPanDevice(device);
-        }
-    }
-
-    /*package*/void handlePanDeviceStateChange(BluetoothDevice device,
-                                                             String iface,
-                                                             int state,
-                                                             int role) {
-        synchronized (mBluetoothPanProfileHandler) {
-            mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, iface, state, role);
-        }
-    }
-
-    /*package*/void handlePanDeviceStateChange(BluetoothDevice device,
-                                                             int state, int role) {
-        synchronized (mBluetoothPanProfileHandler) {
-            mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, null, state, role);
-        }
-    }
-
-    /**** Handlers for Input Device Profile ****/
-    // This needs to be converted to state machine
-
-    public boolean connectInputDevice(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress());
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.connectInputDevice(device, state);
-        }
-    }
-
-    public boolean connectInputDeviceInternal(BluetoothDevice device) {
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.connectInputDeviceInternal(device);
-        }
-    }
-
-    public boolean disconnectInputDevice(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress());
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.disconnectInputDevice(device, state);
-        }
-    }
-
-    public boolean disconnectInputDeviceInternal(BluetoothDevice device) {
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.disconnectInputDeviceInternal(device);
-        }
-    }
-
-    public int getInputDeviceConnectionState(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.getInputDeviceConnectionState(device);
-        }
-    }
-
-    public List<BluetoothDevice> getConnectedInputDevices() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.getConnectedInputDevices();
-        }
-    }
-
-    public List<BluetoothDevice> getInputDevicesMatchingConnectionStates(
-            int[] states) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.getInputDevicesMatchingConnectionStates(states);
-        }
-    }
-
-
-    public int getInputDevicePriority(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.getInputDevicePriority(device);
-        }
-    }
-
-    public boolean setInputDevicePriority(BluetoothDevice device, int priority) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.setInputDevicePriority(device, priority);
-        }
-    }
-
-    /**
-     * Handle incoming profile acceptance for profiles handled by Bluetooth Service,
-     * currently PAN and HID. This also is the catch all for all rejections for profiles
-     * that is not supported.
-     *
-     * @param device - Bluetooth Device
-     * @param allow - true / false
-     * @return
-     */
-    public boolean allowIncomingProfileConnect(BluetoothDevice device, boolean allow) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        String address = device.getAddress();
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            return false;
-        }
-
-        Integer data = getAuthorizationAgentRequestData(address);
-        if (data == null) {
-            Log.w(TAG, "allowIncomingProfileConnect(" + device +
-                  ") called but no native data available");
-            return false;
-        }
-        if (DBG) log("allowIncomingProfileConnect: " + device + " : " + allow + " : " + data);
-        return setAuthorizationNative(address, allow, data.intValue());
-    }
-
-    /*package*/List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) {
-        synchronized (mBluetoothInputProfileHandler) {
-            return mBluetoothInputProfileHandler.lookupInputDevicesMatchingStates(states);
-        }
-    }
-
-    /*package*/void handleInputDevicePropertyChange(String address, boolean connected) {
-        synchronized (mBluetoothInputProfileHandler) {
-            mBluetoothInputProfileHandler.handleInputDevicePropertyChange(address, connected);
-        }
-    }
-
-    /**** Handlers for Health Device Profile ****/
-    // TODO: All these need to be converted to a state machine.
-
-    public boolean registerAppConfiguration(BluetoothHealthAppConfiguration config,
-                                            IBluetoothHealthCallback callback) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-                return mBluetoothHealthProfileHandler.registerAppConfiguration(config, callback);
-        }
-    }
-
-    public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-                return mBluetoothHealthProfileHandler.unregisterAppConfiguration(config);
-        }
-    }
-
-
-    public boolean connectChannelToSource(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-            return mBluetoothHealthProfileHandler.connectChannelToSource(device,
-                    config);
-        }
-    }
-
-    public boolean connectChannelToSink(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config, int channelType) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                                                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-            return mBluetoothHealthProfileHandler.connectChannel(device, config,
-                    channelType);
-        }
-    }
-
-    public boolean disconnectChannel(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config, int id) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-            return mBluetoothHealthProfileHandler.disconnectChannel(device, config, id);
-        }
-    }
-
-    public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-            return mBluetoothHealthProfileHandler.getMainChannelFd(device, config);
-        }
-    }
-
-    /*package*/ void onHealthDevicePropertyChanged(String devicePath,
-            String channelPath) {
-        synchronized (mBluetoothHealthProfileHandler) {
-            mBluetoothHealthProfileHandler.onHealthDevicePropertyChanged(devicePath,
-                    channelPath);
-        }
-    }
-
-    /*package*/ void onHealthDeviceChannelChanged(String devicePath,
-            String channelPath, boolean exists) {
-        synchronized(mBluetoothHealthProfileHandler) {
-            mBluetoothHealthProfileHandler.onHealthDeviceChannelChanged(devicePath,
-                    channelPath, exists);
-        }
-    }
-
-    /*package*/ void onHealthDeviceChannelConnectionError(int channelCode,
-            int newState) {
-        synchronized(mBluetoothHealthProfileHandler) {
-            mBluetoothHealthProfileHandler.onHealthDeviceChannelConnectionError(channelCode,
-                                                                                newState);
-        }
-    }
-
-    public int getHealthDeviceConnectionState(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-            return mBluetoothHealthProfileHandler.getHealthDeviceConnectionState(device);
-        }
-    }
-
-    public List<BluetoothDevice> getConnectedHealthDevices() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-            return mBluetoothHealthProfileHandler.getConnectedHealthDevices();
-        }
-    }
-
-    public List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(
-            int[] states) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                "Need BLUETOOTH permission");
-        synchronized (mBluetoothHealthProfileHandler) {
-            return mBluetoothHealthProfileHandler.
-                    getHealthDevicesMatchingConnectionStates(states);
-        }
-    }
-
-    /*package*/boolean notifyIncomingHidConnection(String address) {
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state == null) {
-            return false;
-        }
-        Message msg = new Message();
-        msg.what = BluetoothDeviceProfileState.CONNECT_HID_INCOMING;
-        state.sendMessage(msg);
-        return true;
-    }
-
-    public boolean connectHeadset(String address) {
-        if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false;
-
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state != null) {
-            Message msg = new Message();
-            msg.arg1 = BluetoothDeviceProfileState.CONNECT_HFP_OUTGOING;
-            msg.obj = state;
-            mHfpProfileState.sendMessage(msg);
-            return true;
-        }
-        return false;
-    }
-
-    public boolean disconnectHeadset(String address) {
-        if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false;
-
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state != null) {
-            Message msg = new Message();
-            msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_HFP_OUTGOING;
-            msg.obj = state;
-            mHfpProfileState.sendMessage(msg);
-            return true;
-        }
-        return false;
-    }
-
-    public boolean connectSink(String address) {
-        if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false;
-
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state != null) {
-            Message msg = new Message();
-            msg.arg1 = BluetoothDeviceProfileState.CONNECT_A2DP_OUTGOING;
-            msg.obj = state;
-            mA2dpProfileState.sendMessage(msg);
-            return true;
-        }
-        return false;
-    }
-
-    public boolean disconnectSink(String address) {
-        if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false;
-
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state != null) {
-            Message msg = new Message();
-            msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_A2DP_OUTGOING;
-            msg.obj = state;
-            mA2dpProfileState.sendMessage(msg);
-            return true;
-        }
-        return false;
-    }
-
-    BluetoothDeviceProfileState addProfileState(String address, boolean setTrust) {
-        BluetoothDeviceProfileState state =
-            new BluetoothDeviceProfileState(mContext, address, this, mA2dpService, setTrust);
-        mDeviceProfileState.put(address, state);
-        state.start();
-        return state;
-    }
-
-    void removeProfileState(String address) {
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state == null) return;
-
-        state.doQuit();
-        mDeviceProfileState.remove(address);
-    }
-
-    String[] getKnownDevices() {
-        String[] bonds = null;
-        String val = getProperty("Devices", true);
-        if (val != null) {
-            bonds = val.split(",");
-        }
-        return bonds;
-    }
-
-    private void initProfileState() {
-        String[] bonds = null;
-        String val = getProperty("Devices", false);
-        if (val != null) {
-            bonds = val.split(",");
-        }
-        if (bonds == null) {
-            return;
-        }
-        for (String path : bonds) {
-            String address = getAddressFromObjectPath(path);
-            BluetoothDeviceProfileState state = addProfileState(address, false);
-        }
-    }
-
-    private void autoConnect() {
-        synchronized (this) {
-            if (!mAllowConnect) {
-                Log.d(TAG, "Not auto-connecting devices because of temporary BT on state.");
-                return;
-            }
-        }
-
-        String[] bonds = getKnownDevices();
-        if (bonds == null) {
-            return;
-        }
-        for (String path : bonds) {
-            String address = getAddressFromObjectPath(path);
-            BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-            if (state != null) {
-                Message msg = new Message();
-                msg.what = BluetoothDeviceProfileState.AUTO_CONNECT_PROFILES;
-                state.sendMessage(msg);
-            }
-        }
-    }
-
-    public boolean notifyIncomingConnection(String address, boolean rejected) {
-        synchronized (this) {
-            if (!mAllowConnect) {
-                Log.d(TAG, "Not allowing incoming connection because of temporary BT on state.");
-                return false;
-            }
-        }
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-        if (state != null) {
-            Message msg = new Message();
-            if (rejected) {
-                if (mA2dpService.getPriority(getRemoteDevice(address)) >=
-                    BluetoothProfile.PRIORITY_ON) {
-                    msg.what = BluetoothDeviceProfileState.CONNECT_OTHER_PROFILES;
-                    msg.arg1 = BluetoothDeviceProfileState.CONNECT_A2DP_OUTGOING;
-                    state.sendMessageDelayed(msg,
-                        BluetoothDeviceProfileState.CONNECT_OTHER_PROFILES_DELAY);
-                }
-            } else {
-                msg.what = BluetoothDeviceProfileState.CONNECT_HFP_INCOMING;
-                state.sendMessage(msg);
-            }
-            return true;
-        }
-        return false;
-    }
-
-    /*package*/ boolean notifyIncomingA2dpConnection(String address, boolean rejected) {
-        synchronized (this) {
-            if (!mAllowConnect) {
-                Log.d(TAG, "Not allowing a2dp connection because of temporary BT on state.");
-                return false;
-            }
-        }
-
-       BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
-       if (state != null) {
-           Message msg = new Message();
-           if (rejected) {
-               if (mHeadsetProxy.getPriority(getRemoteDevice(address)) >=
-                   BluetoothProfile.PRIORITY_ON) {
-                   msg.what = BluetoothDeviceProfileState.CONNECT_OTHER_PROFILES;
-                   msg.arg1 = BluetoothDeviceProfileState.CONNECT_HFP_OUTGOING;
-                   state.sendMessageDelayed(msg,
-                             BluetoothDeviceProfileState.CONNECT_OTHER_PROFILES_DELAY);
-               }
-           } else {
-               msg.what = BluetoothDeviceProfileState.CONNECT_A2DP_INCOMING;
-               state.sendMessage(msg);
-           }
-           return true;
-       }
-       return false;
-    }
-
-    /*package*/ void setA2dpService(BluetoothA2dpService a2dpService) {
-        mA2dpService = a2dpService;
-    }
-
-    /*package*/ Integer getAuthorizationAgentRequestData(String address) {
-        Integer data = mEventLoop.getAuthorizationAgentRequestData().remove(address);
-        return data;
-    }
-
-    public void sendProfileStateMessage(int profile, int cmd) {
-        Message msg = new Message();
-        msg.what = cmd;
-        if (profile == BluetoothProfileState.HFP) {
-            mHfpProfileState.sendMessage(msg);
-        } else if (profile == BluetoothProfileState.A2DP) {
-            mA2dpProfileState.sendMessage(msg);
-        }
-    }
-
-    public int getAdapterConnectionState() {
-        return mAdapterConnectionState;
-    }
-
-    public int getProfileConnectionState(int profile) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-
-        Pair<Integer, Integer> state = mProfileConnectionState.get(profile);
-        if (state == null) return BluetoothProfile.STATE_DISCONNECTED;
-
-        return state.first;
-    }
-
-    private void updateProfileConnectionState(int profile, int newState, int oldState) {
-        // mProfileConnectionState is a hashmap -
-        // <Integer, Pair<Integer, Integer>>
-        // The key is the profile, the value is a pair. first element
-        // is the state and the second element is the number of devices
-        // in that state.
-        int numDev = 1;
-        int newHashState = newState;
-        boolean update = true;
-
-        // The following conditions are considered in this function:
-        // 1. If there is no record of profile and state - update
-        // 2. If a new device's state is current hash state - increment
-        //    number of devices in the state.
-        // 3. If a state change has happened to Connected or Connecting
-        //    (if current state is not connected), update.
-        // 4. If numDevices is 1 and that device state is being updated, update
-        // 5. If numDevices is > 1 and one of the devices is changing state,
-        //    decrement numDevices but maintain oldState if it is Connected or
-        //    Connecting
-        Pair<Integer, Integer> stateNumDev = mProfileConnectionState.get(profile);
-        if (stateNumDev != null) {
-            int currHashState = stateNumDev.first;
-            numDev = stateNumDev.second;
-
-            if (newState == currHashState) {
-                numDev ++;
-            } else if (newState == BluetoothProfile.STATE_CONNECTED ||
-                   (newState == BluetoothProfile.STATE_CONNECTING &&
-                    currHashState != BluetoothProfile.STATE_CONNECTED)) {
-                 numDev = 1;
-            } else if (numDev == 1 && oldState == currHashState) {
-                 update = true;
-            } else if (numDev > 1 && oldState == currHashState) {
-                 numDev --;
-
-                 if (currHashState == BluetoothProfile.STATE_CONNECTED ||
-                     currHashState == BluetoothProfile.STATE_CONNECTING) {
-                    newHashState = currHashState;
-                 }
-            } else {
-                 update = false;
-            }
-        }
-
-        if (update) {
-            mProfileConnectionState.put(profile, new Pair<Integer, Integer>(newHashState,
-                    numDev));
-        }
-    }
-
-    public synchronized void sendConnectionStateChange(BluetoothDevice
-            device, int profile, int state, int prevState) {
-        // Since this is a binder call check if Bluetooth is on still
-        if (getBluetoothStateInternal() == BluetoothAdapter.STATE_OFF) return;
-
-        if (!validateProfileConnectionState(state) ||
-                !validateProfileConnectionState(prevState)) {
-            // Previously, an invalid state was broadcast anyway,
-            // with the invalid state converted to -1 in the intent.
-            // Better to log an error and not send an intent with
-            // invalid contents or set mAdapterConnectionState to -1.
-            Log.e(TAG, "Error in sendConnectionStateChange: "
-                    + "prevState " + prevState + " state " + state);
-            return;
-        }
-
-        updateProfileConnectionState(profile, state, prevState);
-
-        if (updateCountersAndCheckForConnectionStateChange(state, prevState)) {
-            mAdapterConnectionState = state;
-
-            if (state == BluetoothProfile.STATE_DISCONNECTED) {
-                mBluetoothState.sendMessage(BluetoothAdapterStateMachine.ALL_DEVICES_DISCONNECTED);
-            }
-
-            Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
-            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-            intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
-                    convertToAdapterState(state));
-            intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE,
-                    convertToAdapterState(prevState));
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-            Log.d(TAG, "CONNECTION_STATE_CHANGE: " + device + ": "
-                    + prevState + " -> " + state);
-        }
-    }
-
-    private boolean validateProfileConnectionState(int state) {
-        return (state == BluetoothProfile.STATE_DISCONNECTED ||
-                state == BluetoothProfile.STATE_CONNECTING ||
-                state == BluetoothProfile.STATE_CONNECTED ||
-                state == BluetoothProfile.STATE_DISCONNECTING);
-    }
-
-    private int convertToAdapterState(int state) {
-        switch (state) {
-            case BluetoothProfile.STATE_DISCONNECTED:
-                return BluetoothAdapter.STATE_DISCONNECTED;
-            case BluetoothProfile.STATE_DISCONNECTING:
-                return BluetoothAdapter.STATE_DISCONNECTING;
-            case BluetoothProfile.STATE_CONNECTED:
-                return BluetoothAdapter.STATE_CONNECTED;
-            case BluetoothProfile.STATE_CONNECTING:
-                return BluetoothAdapter.STATE_CONNECTING;
-        }
-        Log.e(TAG, "Error in convertToAdapterState");
-        return -1;
-    }
-
-    private boolean updateCountersAndCheckForConnectionStateChange(int state, int prevState) {
-        switch (prevState) {
-            case BluetoothProfile.STATE_CONNECTING:
-                mProfilesConnecting--;
-                break;
-
-            case BluetoothProfile.STATE_CONNECTED:
-                mProfilesConnected--;
-                break;
-
-            case BluetoothProfile.STATE_DISCONNECTING:
-                mProfilesDisconnecting--;
-                break;
-        }
-
-        switch (state) {
-            case BluetoothProfile.STATE_CONNECTING:
-                mProfilesConnecting++;
-                return (mProfilesConnected == 0 && mProfilesConnecting == 1);
-
-            case BluetoothProfile.STATE_CONNECTED:
-                mProfilesConnected++;
-                return (mProfilesConnected == 1);
-
-            case BluetoothProfile.STATE_DISCONNECTING:
-                mProfilesDisconnecting++;
-                return (mProfilesConnected == 0 && mProfilesDisconnecting == 1);
-
-            case BluetoothProfile.STATE_DISCONNECTED:
-                return (mProfilesConnected == 0 && mProfilesConnecting == 0);
-
-            default:
-                return true;
-        }
-    }
-
-    private void createIncomingConnectionStateFile() {
-        File f = new File(INCOMING_CONNECTION_FILE);
-        if (!f.exists()) {
-            try {
-                f.createNewFile();
-            } catch (IOException e) {
-                Log.e(TAG, "IOException: cannot create file");
-            }
-        }
-    }
-
-    /** @hide */
-    public Pair<Integer, String> getIncomingState(String address) {
-        if (mIncomingConnections.isEmpty()) {
-            createIncomingConnectionStateFile();
-            readIncomingConnectionState();
-        }
-        return mIncomingConnections.get(address);
-    }
-
-    private void readIncomingConnectionState() {
-        synchronized(mIncomingConnections) {
-            FileInputStream fstream = null;
-            try {
-              fstream = new FileInputStream(INCOMING_CONNECTION_FILE);
-              DataInputStream in = new DataInputStream(fstream);
-              BufferedReader file = new BufferedReader(new InputStreamReader(in));
-              String line;
-              while((line = file.readLine()) != null) {
-                  line = line.trim();
-                  if (line.length() == 0) continue;
-                  String[] value = line.split(",");
-                  if (value != null && value.length == 3) {
-                      Integer val1 = Integer.parseInt(value[1]);
-                      Pair<Integer, String> val = new Pair(val1, value[2]);
-                      mIncomingConnections.put(value[0], val);
-                  }
-              }
-            } catch (FileNotFoundException e) {
-                log("FileNotFoundException: readIncomingConnectionState" + e.toString());
-            } catch (IOException e) {
-                log("IOException: readIncomingConnectionState" + e.toString());
-            } finally {
-                if (fstream != null) {
-                    try {
-                        fstream.close();
-                    } catch (IOException e) {
-                        // Ignore
-                    }
-                }
-            }
-        }
-    }
-
-    private void truncateIncomingConnectionFile() {
-        RandomAccessFile r = null;
-        try {
-            r = new RandomAccessFile(INCOMING_CONNECTION_FILE, "rw");
-            r.setLength(0);
-        } catch (FileNotFoundException e) {
-            log("FileNotFoundException: truncateIncomingConnectionState" + e.toString());
-        } catch (IOException e) {
-            log("IOException: truncateIncomingConnectionState" + e.toString());
-        } finally {
-            if (r != null) {
-                try {
-                    r.close();
-                } catch (IOException e) {
-                    // ignore
-                 }
-            }
-        }
-    }
-
-    /** @hide */
-    public void writeIncomingConnectionState(String address, Pair<Integer, String> data) {
-        synchronized(mIncomingConnections) {
-            mIncomingConnections.put(address, data);
-
-            truncateIncomingConnectionFile();
-            BufferedWriter out = null;
-            StringBuilder value = new StringBuilder();
-            try {
-                out = new BufferedWriter(new FileWriter(INCOMING_CONNECTION_FILE, true));
-                for (String devAddress: mIncomingConnections.keySet()) {
-                  Pair<Integer, String> val = mIncomingConnections.get(devAddress);
-                  value.append(devAddress);
-                  value.append(",");
-                  value.append(val.first.toString());
-                  value.append(",");
-                  value.append(val.second);
-                  value.append("\n");
-                }
-                out.write(value.toString());
-            } catch (FileNotFoundException e) {
-                log("FileNotFoundException: writeIncomingConnectionState" + e.toString());
-            } catch (IOException e) {
-                log("IOException: writeIncomingConnectionState" + e.toString());
-            } finally {
-                if (out != null) {
-                    try {
-                        out.close();
-                    } catch (IOException e) {
-                        // Ignore
-                    }
-                }
-            }
-        }
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-
-    private native static void classInitNative();
-    private native void initializeNativeDataNative();
-    private native boolean setupNativeDataNative();
-    private native boolean tearDownNativeDataNative();
-    private native void cleanupNativeDataNative();
-    /*package*/ native String getAdapterPathNative();
-
-    private native int isEnabledNative();
-    /*package*/ native int enableNative();
-    /*package*/ native int disableNative();
-
-    /*package*/ native Object[] getAdapterPropertiesNative();
-    private native Object[] getDevicePropertiesNative(String objectPath);
-    private native boolean setAdapterPropertyStringNative(String key, String value);
-    private native boolean setAdapterPropertyIntegerNative(String key, int value);
-    private native boolean setAdapterPropertyBooleanNative(String key, int value);
-
-    private native boolean startDiscoveryNative();
-    private native boolean stopDiscoveryNative();
-
-    private native boolean createPairedDeviceNative(String address, int timeout_ms);
-    private native boolean createPairedDeviceOutOfBandNative(String address, int timeout_ms);
-    private native byte[] readAdapterOutOfBandDataNative();
-
-    private native boolean cancelDeviceCreationNative(String address);
-    private native boolean removeDeviceNative(String objectPath);
-    private native int getDeviceServiceChannelNative(String objectPath, String uuid,
-            int attributeId);
-
-    private native boolean cancelPairingUserInputNative(String address, int nativeData);
-    private native boolean setPinNative(String address, String pin, int nativeData);
-    private native boolean setPasskeyNative(String address, int passkey, int nativeData);
-    private native boolean setPairingConfirmationNative(String address, boolean confirm,
-            int nativeData);
-    private native boolean setRemoteOutOfBandDataNative(String address, byte[] hash,
-                                                        byte[] randomizer, int nativeData);
-
-    private native boolean setDevicePropertyBooleanNative(String objectPath, String key,
-            int value);
-    private native boolean setDevicePropertyStringNative(String objectPath, String key,
-            String value);
-    private native boolean createDeviceNative(String address);
-    /*package*/ native boolean discoverServicesNative(String objectPath, String pattern);
-
-    private native int addRfcommServiceRecordNative(String name, long uuidMsb, long uuidLsb,
-            short channel);
-    private native boolean removeServiceRecordNative(int handle);
-    private native boolean setLinkTimeoutNative(String path, int num_slots);
-
-    native boolean connectInputDeviceNative(String path);
-    native boolean disconnectInputDeviceNative(String path);
-
-    native boolean setBluetoothTetheringNative(boolean value, String nap, String bridge);
-    native boolean connectPanDeviceNative(String path, String dstRole);
-    native boolean disconnectPanDeviceNative(String path);
-    native boolean disconnectPanServerDeviceNative(String path,
-            String address, String iface);
-
-    private native int[] addReservedServiceRecordsNative(int[] uuuids);
-    private native boolean removeReservedServiceRecordsNative(int[] handles);
-
-    // Health API
-    native String registerHealthApplicationNative(int dataType, String role, String name,
-            String channelType);
-    native String registerHealthApplicationNative(int dataType, String role, String name);
-    native boolean unregisterHealthApplicationNative(String path);
-    native boolean createChannelNative(String devicePath, String appPath, String channelType,
-                                       int code);
-    native boolean destroyChannelNative(String devicePath, String channelpath, int code);
-    native String getMainChannelNative(String path);
-    native String getChannelApplicationNative(String channelPath);
-    native ParcelFileDescriptor getChannelFdNative(String channelPath);
-    native boolean releaseChannelFdNative(String channelPath);
-    native boolean setAuthorizationNative(String address, boolean value, int data);
-}
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index c783e6a..4a21374 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -17,7 +17,11 @@
 package android.server.search;
 
 import com.android.internal.content.PackageMonitor;
+import com.android.internal.util.IndentingPrintWriter;
 
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
 import android.app.ISearchManager;
 import android.app.SearchManager;
 import android.app.SearchableInfo;
@@ -27,12 +31,22 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.database.ContentObserver;
+import android.os.Binder;
 import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.List;
 
 /**
@@ -48,9 +62,7 @@
     private final Context mContext;
 
     // This field is initialized lazily in getSearchables(), and then never modified.
-    private Searchables mSearchables;
-
-    private ContentObserver mGlobalSearchObserver;
+    private final SparseArray<Searchables> mSearchables = new SparseArray<Searchables>();
 
     /**
      * Initializes the Search Manager service in the provided system context.
@@ -62,18 +74,39 @@
         mContext = context;
         mContext.registerReceiver(new BootCompletedReceiver(),
                 new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
-        mGlobalSearchObserver = new GlobalSearchProviderObserver(
-                mContext.getContentResolver());
+        mContext.registerReceiver(new UserReceiver(),
+                new IntentFilter(Intent.ACTION_USER_REMOVED));
+        new MyPackageMonitor().register(context, null, UserHandle.ALL, true);
     }
 
-    private synchronized Searchables getSearchables() {
-        if (mSearchables == null) {
-            Log.i(TAG, "Building list of searchable activities");
-            new MyPackageMonitor().register(mContext, null, true);
-            mSearchables = new Searchables(mContext);
-            mSearchables.buildSearchableList();
+    private Searchables getSearchables(int userId) {
+        long origId = Binder.clearCallingIdentity();
+        try {
+            boolean userExists = ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
+                    .getUserInfo(userId) != null;
+            if (!userExists) return null;
+        } finally {
+            Binder.restoreCallingIdentity(origId);
         }
-        return mSearchables;
+        synchronized (mSearchables) {
+            Searchables searchables = mSearchables.get(userId);
+
+            if (searchables == null) {
+                Log.i(TAG, "Building list of searchable activities for userId=" + userId);
+                searchables = new Searchables(mContext, userId);
+                searchables.buildSearchableList();
+                mSearchables.append(userId, searchables);
+            }
+            return searchables;
+        }
+    }
+
+    private void onUserRemoved(int userId) {
+        if (userId != UserHandle.USER_OWNER) {
+            synchronized (mSearchables) {
+                mSearchables.remove(userId);
+            }
+        }
     }
 
     /**
@@ -87,12 +120,19 @@
                 public void run() {
                     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                     mContext.unregisterReceiver(BootCompletedReceiver.this);
-                    getSearchables();
+                    getSearchables(0);
                 }
             }.start();
         }
     }
 
+    private final class UserReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_OWNER));
+        }
+    }
+
     /**
      * Refreshes the "searchables" list when packages are added/removed.
      */
@@ -109,12 +149,21 @@
         }
 
         private void updateSearchables() {
-            // Update list of searchable activities
-            getSearchables().buildSearchableList();
+            final int changingUserId = getChangingUserId();
+            synchronized (mSearchables) {
+                // Update list of searchable activities
+                for (int i = 0; i < mSearchables.size(); i++) {
+                    if (changingUserId == mSearchables.keyAt(i)) {
+                        getSearchables(mSearchables.keyAt(i)).buildSearchableList();
+                        break;
+                    }
+                }
+            }
             // Inform all listeners that the list of searchables has been updated.
             Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
-            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
-            mContext.sendBroadcast(intent);
+            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
+                    | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+            mContext.sendBroadcastAsUser(intent, new UserHandle(changingUserId));
         }
     }
 
@@ -132,10 +181,14 @@
 
         @Override
         public void onChange(boolean selfChange) {
-            getSearchables().buildSearchableList();
+            synchronized (mSearchables) {
+                for (int i = 0; i < mSearchables.size(); i++) {
+                    getSearchables(mSearchables.keyAt(i)).buildSearchableList();
+                }
+            }
             Intent intent = new Intent(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
-            mContext.sendBroadcast(intent);
+            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
         }
 
     }
@@ -156,32 +209,91 @@
             Log.e(TAG, "getSearchableInfo(), activity == null");
             return null;
         }
-        return getSearchables().getSearchableInfo(launchActivity);
+        return getSearchables(UserHandle.getCallingUserId()).getSearchableInfo(launchActivity);
     }
 
     /**
      * Returns a list of the searchable activities that can be included in global search.
      */
     public List<SearchableInfo> getSearchablesInGlobalSearch() {
-        return getSearchables().getSearchablesInGlobalSearchList();
+        return getSearchables(UserHandle.getCallingUserId()).getSearchablesInGlobalSearchList();
     }
 
     public List<ResolveInfo> getGlobalSearchActivities() {
-        return getSearchables().getGlobalSearchActivities();
+        return getSearchables(UserHandle.getCallingUserId()).getGlobalSearchActivities();
     }
 
     /**
      * Gets the name of the global search activity.
      */
     public ComponentName getGlobalSearchActivity() {
-        return getSearchables().getGlobalSearchActivity();
+        return getSearchables(UserHandle.getCallingUserId()).getGlobalSearchActivity();
     }
 
     /**
      * Gets the name of the web search activity.
      */
     public ComponentName getWebSearchActivity() {
-        return getSearchables().getWebSearchActivity();
+        return getSearchables(UserHandle.getCallingUserId()).getWebSearchActivity();
     }
 
+    @Override
+    public ComponentName getAssistIntent(int userHandle) {
+        try {
+            if (userHandle != UserHandle.getCallingUserId()) {
+                // Requesting a different user, make sure that they have the permission
+                if (ActivityManager.checkComponentPermission(
+                        android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                        Binder.getCallingUid(), -1, true)
+                        == PackageManager.PERMISSION_GRANTED) {
+                    // Translate to the current user id, if caller wasn't aware
+                    if (userHandle == UserHandle.USER_CURRENT) {
+                        long identity = Binder.clearCallingIdentity();
+                        userHandle = ActivityManagerNative.getDefault().getCurrentUser().id;
+                        Binder.restoreCallingIdentity(identity);
+                    }
+                } else {
+                    String msg = "Permission Denial: "
+                            + "Request to getAssistIntent for " + userHandle
+                            + " but is calling from user " + UserHandle.getCallingUserId()
+                            + "; this requires "
+                            + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+                    Slog.w(TAG, msg);
+                    return null;
+                }
+            }
+            IPackageManager pm = AppGlobals.getPackageManager();
+            Intent assistIntent = new Intent(Intent.ACTION_ASSIST);
+            ResolveInfo info =
+                    pm.resolveIntent(assistIntent,
+                    assistIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                    PackageManager.MATCH_DEFAULT_ONLY, userHandle);
+            if (info != null) {
+                return new ComponentName(
+                        info.activityInfo.applicationInfo.packageName,
+                        info.activityInfo.name);
+            }
+        } catch (RemoteException re) {
+            // Local call
+            Log.e(TAG, "RemoteException in getAssistIntent: " + re);
+        } catch (Exception e) {
+            Log.e(TAG, "Exception in getAssistIntent: " + e);
+        }
+        return null;
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+
+        IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
+        synchronized (mSearchables) {
+            for (int i = 0; i < mSearchables.size(); i++) {
+                ipw.print("\nUser: "); ipw.println(mSearchables.keyAt(i));
+                ipw.increaseIndent();
+                mSearchables.valueAt(i).dump(fd, ipw, args);
+                ipw.decreaseIndent();
+            }
+        }
+    }
 }
diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java
index f24d52f..a0095d6 100644
--- a/core/java/android/server/search/Searchables.java
+++ b/core/java/android/server/search/Searchables.java
@@ -16,6 +16,7 @@
 
 package android.server.search;
 
+import android.app.AppGlobals;
 import android.app.SearchManager;
 import android.app.SearchableInfo;
 import android.content.ComponentName;
@@ -23,13 +24,18 @@
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.os.Binder;
 import android.os.Bundle;
+import android.os.RemoteException;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -38,6 +44,7 @@
 
 /**
  * This class maintains the information about all searchable activities.
+ * This is a hidden class.
  */
 public class Searchables {
 
@@ -65,12 +72,19 @@
     public static String ENHANCED_GOOGLE_SEARCH_COMPONENT_NAME =
             "com.google.android.providers.enhancedgooglesearch/.Launcher";
 
+    // Cache the package manager instance
+    final private IPackageManager mPm;
+    // User for which this Searchables caches information
+    private int mUserId;
+
     /**
      *
      * @param context Context to use for looking up activities etc.
      */
-    public Searchables (Context context) {
+    public Searchables (Context context, int userId) {
         mContext = context;
+        mUserId = userId;
+        mPm = AppGlobals.getPackageManager();
     }
 
     /**
@@ -115,50 +129,50 @@
 
         ActivityInfo ai = null;
         try {
-            ai = mContext.getPackageManager().
-                       getActivityInfo(activity, PackageManager.GET_META_DATA );
-            String refActivityName = null;
+            ai = mPm.getActivityInfo(activity, PackageManager.GET_META_DATA, mUserId);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error getting activity info " + re);
+            return null;
+        }
+        String refActivityName = null;
 
-            // First look for activity-specific reference
-            Bundle md = ai.metaData;
+        // First look for activity-specific reference
+        Bundle md = ai.metaData;
+        if (md != null) {
+            refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE);
+        }
+        // If not found, try for app-wide reference
+        if (refActivityName == null) {
+            md = ai.applicationInfo.metaData;
             if (md != null) {
                 refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE);
             }
-            // If not found, try for app-wide reference
-            if (refActivityName == null) {
-                md = ai.applicationInfo.metaData;
-                if (md != null) {
-                    refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE);
-                }
+        }
+
+        // Irrespective of source, if a reference was found, follow it.
+        if (refActivityName != null)
+        {
+            // This value is deprecated, return null
+            if (refActivityName.equals(MD_SEARCHABLE_SYSTEM_SEARCH)) {
+                return null;
+            }
+            String pkg = activity.getPackageName();
+            ComponentName referredActivity;
+            if (refActivityName.charAt(0) == '.') {
+                referredActivity = new ComponentName(pkg, pkg + refActivityName);
+            } else {
+                referredActivity = new ComponentName(pkg, refActivityName);
             }
 
-            // Irrespective of source, if a reference was found, follow it.
-            if (refActivityName != null)
-            {
-                // This value is deprecated, return null
-                if (refActivityName.equals(MD_SEARCHABLE_SYSTEM_SEARCH)) {
-                    return null;
-                }
-                String pkg = activity.getPackageName();
-                ComponentName referredActivity;
-                if (refActivityName.charAt(0) == '.') {
-                    referredActivity = new ComponentName(pkg, pkg + refActivityName);
-                } else {
-                    referredActivity = new ComponentName(pkg, refActivityName);
-                }
-
-                // Now try the referred activity, and if found, cache
-                // it against the original name so we can skip the check
-                synchronized (this) {
-                    result = mSearchablesMap.get(referredActivity);
-                    if (result != null) {
-                        mSearchablesMap.put(activity, result);
-                        return result;
-                    }
+            // Now try the referred activity, and if found, cache
+            // it against the original name so we can skip the check
+            synchronized (this) {
+                result = mSearchablesMap.get(referredActivity);
+                if (result != null) {
+                    mSearchablesMap.put(activity, result);
+                    return result;
                 }
             }
-        } catch (PackageManager.NameNotFoundException e) {
-            // case 3: no metadata
         }
 
         // Step 3.  None found. Return null.
@@ -195,61 +209,67 @@
         ArrayList<SearchableInfo> newSearchablesInGlobalSearchList
                                 = new ArrayList<SearchableInfo>();
 
-        final PackageManager pm = mContext.getPackageManager();
-
         // Use intent resolver to generate list of ACTION_SEARCH & ACTION_WEB_SEARCH receivers.
         List<ResolveInfo> searchList;
         final Intent intent = new Intent(Intent.ACTION_SEARCH);
-        searchList = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
 
-        List<ResolveInfo> webSearchInfoList;
-        final Intent webSearchIntent = new Intent(Intent.ACTION_WEB_SEARCH);
-        webSearchInfoList = pm.queryIntentActivities(webSearchIntent, PackageManager.GET_META_DATA);
+        long ident = Binder.clearCallingIdentity();
+        try {
+            searchList = queryIntentActivities(intent, PackageManager.GET_META_DATA);
 
-        // analyze each one, generate a Searchables record, and record
-        if (searchList != null || webSearchInfoList != null) {
-            int search_count = (searchList == null ? 0 : searchList.size());
-            int web_search_count = (webSearchInfoList == null ? 0 : webSearchInfoList.size());
-            int count = search_count + web_search_count;
-            for (int ii = 0; ii < count; ii++) {
-                // for each component, try to find metadata
-                ResolveInfo info = (ii < search_count)
-                        ? searchList.get(ii)
-                        : webSearchInfoList.get(ii - search_count);
-                ActivityInfo ai = info.activityInfo;
-                // Check first to avoid duplicate entries.
-                if (newSearchablesMap.get(new ComponentName(ai.packageName, ai.name)) == null) {
-                    SearchableInfo searchable = SearchableInfo.getActivityMetaData(mContext, ai);
-                    if (searchable != null) {
-                        newSearchablesList.add(searchable);
-                        newSearchablesMap.put(searchable.getSearchActivity(), searchable);
-                        if (searchable.shouldIncludeInGlobalSearch()) {
-                            newSearchablesInGlobalSearchList.add(searchable);
+            List<ResolveInfo> webSearchInfoList;
+            final Intent webSearchIntent = new Intent(Intent.ACTION_WEB_SEARCH);
+            webSearchInfoList = queryIntentActivities(webSearchIntent, PackageManager.GET_META_DATA);
+
+            // analyze each one, generate a Searchables record, and record
+            if (searchList != null || webSearchInfoList != null) {
+                int search_count = (searchList == null ? 0 : searchList.size());
+                int web_search_count = (webSearchInfoList == null ? 0 : webSearchInfoList.size());
+                int count = search_count + web_search_count;
+                for (int ii = 0; ii < count; ii++) {
+                    // for each component, try to find metadata
+                    ResolveInfo info = (ii < search_count)
+                            ? searchList.get(ii)
+                            : webSearchInfoList.get(ii - search_count);
+                    ActivityInfo ai = info.activityInfo;
+                    // Check first to avoid duplicate entries.
+                    if (newSearchablesMap.get(new ComponentName(ai.packageName, ai.name)) == null) {
+                        SearchableInfo searchable = SearchableInfo.getActivityMetaData(mContext, ai,
+                                mUserId);
+                        if (searchable != null) {
+                            newSearchablesList.add(searchable);
+                            newSearchablesMap.put(searchable.getSearchActivity(), searchable);
+                            if (searchable.shouldIncludeInGlobalSearch()) {
+                                newSearchablesInGlobalSearchList.add(searchable);
+                            }
                         }
                     }
                 }
             }
-        }
 
-        List<ResolveInfo> newGlobalSearchActivities = findGlobalSearchActivities();
+            List<ResolveInfo> newGlobalSearchActivities = findGlobalSearchActivities();
 
-        // Find the global search activity
-        ComponentName newGlobalSearchActivity = findGlobalSearchActivity(
-                newGlobalSearchActivities);
+            // Find the global search activity
+            ComponentName newGlobalSearchActivity = findGlobalSearchActivity(
+                    newGlobalSearchActivities);
 
-        // Find the web search activity
-        ComponentName newWebSearchActivity = findWebSearchActivity(newGlobalSearchActivity);
+            // Find the web search activity
+            ComponentName newWebSearchActivity = findWebSearchActivity(newGlobalSearchActivity);
 
-        // Store a consistent set of new values
-        synchronized (this) {
-            mSearchablesMap = newSearchablesMap;
-            mSearchablesList = newSearchablesList;
-            mSearchablesInGlobalSearchList = newSearchablesInGlobalSearchList;
-            mGlobalSearchActivities = newGlobalSearchActivities;
-            mCurrentGlobalSearchActivity = newGlobalSearchActivity;
-            mWebSearchActivity = newWebSearchActivity;
+            // Store a consistent set of new values
+            synchronized (this) {
+                mSearchablesMap = newSearchablesMap;
+                mSearchablesList = newSearchablesList;
+                mSearchablesInGlobalSearchList = newSearchablesInGlobalSearchList;
+                mGlobalSearchActivities = newGlobalSearchActivities;
+                mCurrentGlobalSearchActivity = newGlobalSearchActivity;
+                mWebSearchActivity = newWebSearchActivity;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
+
     /**
      * Returns a sorted list of installed search providers as per
      * the following heuristics:
@@ -262,10 +282,8 @@
         // Step 1 : Query the package manager for a list
         // of activities that can handle the GLOBAL_SEARCH intent.
         Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
-        PackageManager pm = mContext.getPackageManager();
         List<ResolveInfo> activities =
-                pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
-
+                    queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
         if (activities != null && !activities.isEmpty()) {
             // Step 2: Rank matching activities according to our heuristics.
             Collections.sort(activities, GLOBAL_SEARCH_RANKER);
@@ -301,10 +319,8 @@
         Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
         intent.setComponent(globalSearch);
 
-        PackageManager pm = mContext.getPackageManager();
-        List<ResolveInfo> activities =
-                pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
-
+        List<ResolveInfo> activities = queryIntentActivities(intent,
+                PackageManager.MATCH_DEFAULT_ONLY);
         if (activities != null && !activities.isEmpty()) {
             return true;
         }
@@ -374,9 +390,8 @@
         }
         Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
         intent.setPackage(globalSearchActivity.getPackageName());
-        PackageManager pm = mContext.getPackageManager();
         List<ResolveInfo> activities =
-                pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+                queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
 
         if (activities != null && !activities.isEmpty()) {
             ActivityInfo ai = activities.get(0).activityInfo;
@@ -387,6 +402,19 @@
         return null;
     }
 
+    private List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
+        List<ResolveInfo> activities = null;
+        try {
+            activities =
+                    mPm.queryIntentActivities(intent,
+                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                    flags, mUserId);
+        } catch (RemoteException re) {
+            // Local call
+        }
+        return activities;
+    }
+
     /**
      * Returns the list of searchable activities.
      */
@@ -422,4 +450,15 @@
     public synchronized ComponentName getWebSearchActivity() {
         return mWebSearchActivity;
     }
+
+    void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("Searchable authorities:");
+        synchronized (this) {
+            if (mSearchablesList != null) {
+                for (SearchableInfo info: mSearchablesList) {
+                    pw.print("  "); pw.println(info.getSuggestAuthority());
+                }
+            }
+        }
+    }
 }
diff --git a/core/java/android/service/dreams/Dream.java b/core/java/android/service/dreams/Dream.java
deleted file mode 100644
index 83464c9..0000000
--- a/core/java/android/service/dreams/Dream.java
+++ /dev/null
@@ -1,392 +0,0 @@
-/**
- * 
- */
-package android.service.dreams;
-
-import com.android.internal.policy.PolicyManager;
-
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.graphics.drawable.ColorDrawable;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.Slog;
-import android.view.ActionMode;
-import android.view.IWindowManager;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager.LayoutParams;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.WindowManager;
-import android.view.WindowManagerImpl;
-
-/**
- * @hide
- *
- */
-public class Dream extends Service implements Window.Callback {
-    private final static boolean DEBUG = true;
-    private final static String TAG = "Dream";
-    
-    /**
-     * The {@link Intent} that must be declared as handled by the service.
-     * To be supported, the service must also require the
-     * {@link android.Manifest.permission#BIND_WALLPAPER} permission so
-     * that other applications can not abuse it.
-     */
-    @SdkConstant(SdkConstantType.SERVICE_ACTION)
-    public static final String SERVICE_INTERFACE =
-            "android.service.dreams.Dream";
-
-    private Window mWindow;
-
-    private WindowManager mWindowManager;
-    private IDreamManager mSandman;
-    
-    private boolean mInteractive;
-    
-    final Handler mHandler = new Handler();
-    
-    boolean mFinished = false;
-    
-    // begin Window.Callback methods
-    @Override
-    public boolean dispatchKeyEvent(KeyEvent event) {
-        if (!mInteractive) { 
-            finish();
-            return true;
-        }
-        return mWindow.superDispatchKeyEvent(event);
-    }
-
-    @Override
-    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
-        if (!mInteractive) { 
-            finish();
-            return true;
-        }
-        return mWindow.superDispatchKeyShortcutEvent(event);
-    }
-
-    @Override
-    public boolean dispatchTouchEvent(MotionEvent event) {
-        if (!mInteractive) { 
-            finish();
-            return true;
-        }
-        return mWindow.superDispatchTouchEvent(event);
-    }
-
-    @Override
-    public boolean dispatchTrackballEvent(MotionEvent event) {
-        if (!mInteractive) { 
-            finish();
-            return true;
-        }
-        return mWindow.superDispatchTrackballEvent(event);
-    }
-
-    @Override
-    public boolean dispatchGenericMotionEvent(MotionEvent event) {
-        if (!mInteractive) { 
-            finish();
-            return true;
-        }
-        return mWindow.superDispatchGenericMotionEvent(event);
-    }
-
-    @Override
-    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
-        return false;
-    }
-
-    @Override
-    public View onCreatePanelView(int featureId) {
-        return null;
-    }
-
-    @Override
-    public boolean onCreatePanelMenu(int featureId, Menu menu) {
-        return false;
-    }
-
-    @Override
-    public boolean onPreparePanel(int featureId, View view, Menu menu) {
-        return false;
-    }
-
-    @Override
-    public boolean onMenuOpened(int featureId, Menu menu) {
-        return false;
-    }
-
-    @Override
-    public boolean onMenuItemSelected(int featureId, MenuItem item) {
-        return false;
-    }
-
-    @Override
-    public void onWindowAttributesChanged(LayoutParams attrs) {
-
-    }
-
-    @Override
-    public void onContentChanged() {
-
-    }
-
-    @Override
-    public void onWindowFocusChanged(boolean hasFocus) {
-
-    }
-
-    @Override
-    public void onAttachedToWindow() {
-        mWindow.addFlags(
-                WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
-                | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
-        );
-        lightsOut();
-    }
-
-    @Override
-    public void onDetachedFromWindow() {
-    }
-
-    @Override
-    public void onPanelClosed(int featureId, Menu menu) {
-    }
-
-    @Override
-    public boolean onSearchRequested() {
-        return false;
-    }
-
-    @Override
-    public ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback callback) {
-        return null;
-    }
-
-    @Override
-    public void onActionModeStarted(ActionMode mode) {
-    }
-
-    @Override
-    public void onActionModeFinished(ActionMode mode) {
-    }
-    // end Window.Callback methods
-
-    public WindowManager getWindowManager() {
-        return mWindowManager;
-    }
-
-    public Window getWindow() {
-        return mWindow;
-    }
-    
-    /**
-     * Called when this Dream is constructed. Place your initialization here.
-     * 
-     * Subclasses must call through to the superclass implementation.
-     */
-    @Override
-    public void onCreate() {
-        super.onCreate();
-
-        if (DEBUG) Slog.v(TAG, "Dream created on thread " + Thread.currentThread().getId());
-
-        mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams"));
-    }
-    
-    /**
-     * Called when this Dream is started. Place your initialization here.
-     * 
-     * Subclasses must call through to the superclass implementation.
-     * 
-     * XXX(dsandler) Might want to make this final and have a different method for clients to override 
-     */
-    @Override
-    public int onStartCommand(Intent intent, int flags, int startId) {
-        return super.onStartCommand(intent, flags, startId);
-    }
-    
-   /**
-     * Inflate a layout resource and set it to be the content view for this Dream.
-     * Behaves similarly to {@link android.app.Activity#setContentView(int)}.
-     *
-     * @param layoutResID Resource ID to be inflated.
-     * 
-     * @see #setContentView(android.view.View)
-     * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
-     */
-    public void setContentView(int layoutResID) {
-        getWindow().setContentView(layoutResID);
-    }
-
-    /**
-     * Set a view to be the content view for this Dream.
-     * Behaves similarly to {@link android.app.Activity#setContentView(android.view.View)},
-     * including using {@link ViewGroup.LayoutParams#MATCH_PARENT} as the layout height and width of the view.
-     * 
-     * @param view The desired content to display.
-     *
-     * @see #setContentView(int)
-     * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
-     */
-    public void setContentView(View view) {
-        getWindow().setContentView(view);
-    }
-
-    /**
-     * Set a view to be the content view for this Dream.
-     * Behaves similarly to 
-     * {@link android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}.
-     *
-     * @param view The desired content to display.
-     * @param params Layout parameters for the view.
-     *
-     * @see #setContentView(android.view.View)
-     * @see #setContentView(int)
-     */
-    public void setContentView(View view, ViewGroup.LayoutParams params) {
-        getWindow().setContentView(view, params);
-    }
-
-    /**
-     * Add a view to the Dream's window, leaving other content views in place.
-     * 
-     * @param view The desired content to display.
-     * @param params Layout parameters for the view.
-     */
-    public void addContentView(View view, ViewGroup.LayoutParams params) {
-        getWindow().addContentView(view, params);
-    }
-    
-    /**
-     * @param mInteractive the mInteractive to set
-     */
-    public void setInteractive(boolean mInteractive) {
-        this.mInteractive = mInteractive;
-    }
-
-    /**
-     * @return the mInteractive
-     */
-    public boolean isInteractive() {
-        return mInteractive;
-    }
-    
-    /** Convenience method for setting View.SYSTEM_UI_FLAG_LOW_PROFILE on the content view. */
-    protected void lightsOut() {
-        // turn the lights down low
-        final View v = mWindow.getDecorView();
-        if (v != null) {
-            v.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
-        }
-    }
-
-    /**
-     * Finds a view that was identified by the id attribute from the XML that
-     * was processed in {@link #onCreate}.
-     *
-     * @return The view if found or null otherwise.
-     */
-    public View findViewById(int id) {
-        return getWindow().findViewById(id);
-    }
-    
-    /**
-     * Called when this Dream is being removed from the screen and stopped.
-     */
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-        mWindowManager.removeView(mWindow.getDecorView());
-    }
-
-    /**
-     * Creates a new dream window, attaches the current content view, and shows it.
-     * 
-     * @param windowToken Binder to attach to the window to allow access to the correct window type.
-     * @hide
-     */
-    final /*package*/ void attach(IBinder windowToken) {
-        if (DEBUG) Slog.v(TAG, "Dream attached on thread " + Thread.currentThread().getId());
-        
-        mWindow = PolicyManager.makeNewWindow(this);
-        mWindow.setCallback(this);
-        mWindow.requestFeature(Window.FEATURE_NO_TITLE);
-        mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
-
-        if (DEBUG) Slog.v(TAG, "attaching window token: " + windowToken 
-                + " to window of type " + WindowManager.LayoutParams.TYPE_DREAM);
-
-        WindowManager.LayoutParams lp = mWindow.getAttributes();
-        lp.type = WindowManager.LayoutParams.TYPE_DREAM;
-        lp.token = windowToken;
-        lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
-        
-        //WindowManagerImpl.getDefault().addView(mWindow.getDecorView(), lp);
-        
-        if (DEBUG) Slog.v(TAG, "created and attached window: " + mWindow);
-
-        mWindow.setWindowManager(null, windowToken, "dream", true);
-        mWindowManager = mWindow.getWindowManager();
-        
-        // now make it visible
-        mHandler.post(new Runnable(){
-            @Override
-            public void run() {
-                if (DEBUG) Slog.v(TAG, "Dream window added on thread " + Thread.currentThread().getId());
-                
-                getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
-            }});        
-    }
-    
-    /**
-     * Stop the dream and wake up.
-     * 
-     * After this method is called, the service will be stopped.
-     */
-    public void finish() {
-        if (mFinished) return;
-        try {
-            mSandman.awaken(); // assuming we were started by the DreamManager
-            stopSelf(); // if launched via any other means
-            mFinished = true;
-        } catch (RemoteException ex) {
-            // sigh
-        }
-    }
-
-    class IDreamServiceWrapper extends IDreamService.Stub {
-        public IDreamServiceWrapper() {
-        }
-
-        public void attach(IBinder windowToken) {
-            Dream.this.attach(windowToken);
-        }
-    }
-
-    /**
-     * Implement to return the implementation of the internal accessibility
-     * service interface.  Subclasses should not override.
-     */
-    @Override
-    public final IBinder onBind(Intent intent) {
-        return new IDreamServiceWrapper();
-    }
-}
diff --git a/core/java/android/service/dreams/DreamManagerService.java b/core/java/android/service/dreams/DreamManagerService.java
deleted file mode 100644
index 4a14ced..0000000
--- a/core/java/android/service/dreams/DreamManagerService.java
+++ /dev/null
@@ -1,184 +0,0 @@
-package android.service.dreams;
-
-import static android.provider.Settings.Secure.SCREENSAVER_COMPONENT;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-import com.android.internal.view.IInputMethod;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.PackageManager;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.util.Log;
-import android.util.Slog;
-import android.view.IWindowManager;
-import android.view.WindowManager;
-
-/**
- * 
- * @hide
- *
- */
-
-public class DreamManagerService 
-        extends IDreamManager.Stub 
-        implements ServiceConnection
-{
-    private static final boolean DEBUG = true;
-    private static final String TAG = "DreamManagerService";
-    
-    final Object mLock = new Object[0];
-
-    private Context mContext;
-    private IWindowManager mIWindowManager;
-    
-    private ComponentName mCurrentDreamComponent;
-    private IDreamService mCurrentDream;
-    private Binder mCurrentDreamToken; 
-
-    public DreamManagerService(Context context) {
-        if (DEBUG) Slog.v(TAG, "DreamManagerService startup");
-        mContext = context;
-        mIWindowManager = IWindowManager.Stub.asInterface(
-                ServiceManager.getService(Context.WINDOW_SERVICE));
-    }
-
-    private void checkPermission(String permission) {
-        if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(permission)) {
-            throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
-                    + ", must have permission " + permission);
-        }
-    }
-
-    // IDreamManager method
-    public void dream() {
-        ComponentName name = getDreamComponent();
-        if (name != null) {
-            synchronized (mLock) {
-                final long ident = Binder.clearCallingIdentity();
-                try {
-                    bindDreamComponentL(name, false);
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
-            }
-        }
-    }
-
-    // IDreamManager method
-    public void setDreamComponent(ComponentName name) {
-        Settings.Secure.putString(mContext.getContentResolver(), SCREENSAVER_COMPONENT, name.flattenToString());
-    }
-    
-    // IDreamManager method
-    public ComponentName getDreamComponent() {
-        // TODO(dsandler) don't load this every time, watch the value  
-        String component = Settings.Secure.getString(mContext.getContentResolver(), SCREENSAVER_COMPONENT);
-        if (component == null) {
-            component = mContext.getResources().getString(
-                com.android.internal.R.string.config_defaultDreamComponent);
-        }
-        if (component != null) {
-            return ComponentName.unflattenFromString(component);
-        } else {
-            return null;
-        }
-    }
-    
-    // IDreamManager method
-    public void testDream(ComponentName name) {
-        if (DEBUG) Slog.v(TAG, "startDream name=" + name
-                + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
-//        checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
-        synchronized (mLock) {
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                bindDreamComponentL(name, true);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-    }
-
-    // IDreamManager method
-    public void awaken() {
-        if (DEBUG) Slog.v(TAG, "awaken()");
-        synchronized (mLock) {
-            if (mCurrentDream != null) {
-                mContext.unbindService(this);
-            }
-        }
-    }
-
-    public void bindDreamComponentL(ComponentName componentName, boolean test) {
-        if (DEBUG) Slog.v(TAG, "bindDreamComponent: componentName=" + componentName
-                + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
-
-        Intent intent = new Intent(Intent.ACTION_MAIN)
-            .setComponent(componentName)
-            .addFlags(
-                Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
-                )
-            .putExtra("android.dreams.TEST", test);
-        
-        if (!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE)) {
-            Slog.w(TAG, "unable to bind service: " + componentName);
-            return;
-        }
-        mCurrentDreamComponent = componentName;
-        mCurrentDreamToken = new Binder();
-        try {
-            if (DEBUG) Slog.v(TAG, "Adding window token: " + mCurrentDreamToken 
-                    + " for window type: " + WindowManager.LayoutParams.TYPE_DREAM);
-            mIWindowManager.addWindowToken(mCurrentDreamToken,
-                    WindowManager.LayoutParams.TYPE_DREAM);
-        } catch (RemoteException e) {
-            Slog.w(TAG, "Unable to add window token. Proceed at your own risk.");
-        }
-        
-    }
-
-    @Override
-    public void onServiceConnected(ComponentName name, IBinder service) {
-        if (DEBUG) Slog.v(TAG, "connected to dream: " + name + " binder=" + service + " thread=" + Thread.currentThread().getId());
-
-        mCurrentDream = IDreamService.Stub.asInterface(service);
-        try {
-            if (DEBUG) Slog.v(TAG, "attaching with token:" + mCurrentDreamToken);
-            mCurrentDream.attach(mCurrentDreamToken);
-        } catch (RemoteException ex) {
-            Slog.w(TAG, "Unable to send window token to dream:" + ex);
-        }
-    }
-
-    @Override
-    public void onServiceDisconnected(ComponentName name) {
-        if (DEBUG) Slog.v(TAG, "disconnected: " + name + " service: " + mCurrentDream);
-        mCurrentDream = null;
-        mCurrentDreamToken = null;
-    }
-    
-    @Override
-    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
-
-        pw.println("Dreamland:");
-        pw.print("  component="); pw.println(mCurrentDreamComponent);
-        pw.print("  token="); pw.println(mCurrentDreamToken);
-        pw.print("  dream="); pw.println(mCurrentDream);
-    }
-
-    public void systemReady() {
-        if (DEBUG) Slog.v(TAG, "ready to dream!");
-    }
-
-}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
new file mode 100644
index 0000000..6c9290b
--- /dev/null
+++ b/core/java/android/service/dreams/DreamService.java
@@ -0,0 +1,770 @@
+/**
+ * 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.service.dreams;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.app.Service;
+import android.content.Intent;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.util.Slog;
+import android.view.ActionMode;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+import android.view.WindowManager.LayoutParams;
+import android.view.accessibility.AccessibilityEvent;
+
+import com.android.internal.policy.PolicyManager;
+
+/**
+ * Extend this class to implement a custom Dream (displayed to the user as a "Sleep Mode").
+ *
+ * <p>Dreams are interactive screensavers launched when a charging device is idle, or docked in a
+ * desk dock. Dreams provide another modality for apps to express themselves, tailored for
+ * an exhibition/lean-back experience.</p>
+ *
+ * <p>The Dream lifecycle is as follows:</p>
+ * <ol>
+ *   <li>{@link #onAttachedToWindow}
+ *     <p>Use this for initial setup, such as calling {@link #setContentView setContentView()}.</li>
+ *   <li>{@link #onDreamingStarted}
+ *     <p>Your dream has started, so you should begin animations or other behaviors here.</li>
+ *   <li>{@link #onDreamingStopped}
+ *     <p>Use this to stop the things you started in {@link #onDreamingStarted}.</li>
+ *   <li>{@link #onDetachedFromWindow}
+ *     <p>Use this to dismantle resources your dream set up. For example, detach from handlers
+ *        and listeners.</li>
+ * </ol>
+ *
+ * <p>In addition, onCreate and onDestroy (from the Service interface) will also be called, but
+ * initialization and teardown should be done by overriding the hooks above.</p>
+ *
+ * <p>To be available to the system, Dreams should be declared in the manifest as follows:</p>
+ * <pre>
+ * &lt;service
+ *     android:name=".MyDream"
+ *     android:exported="true"
+ *     android:icon="@drawable/my_icon"
+ *     android:label="@string/my_dream_label" >
+ *
+ *     &lt;intent-filter>
+ *         &lt;action android:name="android.service.dreams.DreamService" />
+ *         &lt;category android:name="android.intent.category.DEFAULT" />
+ *     &lt;/intent-filter>
+ *
+ *     &lt;!-- Point to additional information for this dream (optional) -->
+ *     &lt;meta-data
+ *         android:name="android.service.dream"
+ *         android:resource="@xml/my_dream" />
+ * &lt;/service>
+ * </pre>
+ *
+ * <p>If specified with the {@code &lt;meta-data&gt;} element,
+ * additional information for the dream is defined using the
+ * {@link android.R.styleable#Dream &lt;dream&gt;} element in a separate XML file.
+ * Currently, the only addtional
+ * information you can provide is for a settings activity that allows the user to configure
+ * the dream behavior. For example:</p>
+ * <p class="code-caption">res/xml/my_dream.xml</p>
+ * <pre>
+ * &lt;dream xmlns:android="http://schemas.android.com/apk/res/android"
+ *     android:settingsActivity="com.example.app/.MyDreamSettingsActivity" />
+ * </pre>
+ * <p>This makes a Settings button available alongside your dream's listing in the
+ * system settings, which when pressed opens the specified activity.</p>
+ *
+ *
+ * <p>To specify your dream layout, call {@link #setContentView}, typically during the
+ * {@link #onAttachedToWindow} callback. For example:</p>
+ * <pre>
+ * public class MyDream extends DreamService {
+ *
+ *     &#64;Override
+ *     public void onAttachedToWindow() {
+ *         super.onAttachedToWindow();
+ *
+ *         // Exit dream upon user touch
+ *         setInteractive(false);
+ *         // Hide system UI
+ *         setFullscreen(true);
+ *         // Set the dream layout
+ *         setContentView(R.layout.dream);
+ *     }
+ * }
+ * </pre>
+ */
+public class DreamService extends Service implements Window.Callback {
+    private final String TAG = DreamService.class.getSimpleName() + "[" + getClass().getSimpleName() + "]";
+
+    /**
+     * The name of the dream manager service.
+     * @hide
+     */
+    public static final String DREAM_SERVICE = "dreams";
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    @SdkConstant(SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE =
+            "android.service.dreams.DreamService";
+
+    /**
+     * Name under which a Dream publishes information about itself.
+     * This meta-data must reference an XML resource containing
+     * a <code>&lt;{@link android.R.styleable#Dream dream}&gt;</code>
+     * tag.
+     */
+    public static final String DREAM_META_DATA = "android.service.dream";
+
+    private final Handler mHandler = new Handler();
+    private IBinder mWindowToken;
+    private Window mWindow;
+    private WindowManager mWindowManager;
+    private IDreamManager mSandman;
+    private boolean mInteractive = false;
+    private boolean mLowProfile = true;
+    private boolean mFullscreen = false;
+    private boolean mScreenBright = true;
+    private boolean mFinished;
+
+    private boolean mDebug = false;
+
+    /**
+     * @hide
+     */
+    public void setDebug(boolean dbg) {
+        mDebug = dbg;
+    }
+
+    // begin Window.Callback methods
+    /** {@inheritDoc} */
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        // TODO: create more flexible version of mInteractive that allows use of KEYCODE_BACK
+        if (!mInteractive) {
+            if (mDebug) Slog.v(TAG, "Finishing on keyEvent");
+            safelyFinish();
+            return true;
+        } else if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+            if (mDebug) Slog.v(TAG, "Finishing on back key");
+            safelyFinish();
+            return true;
+        }
+        return mWindow.superDispatchKeyEvent(event);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
+        if (!mInteractive) {
+            if (mDebug) Slog.v(TAG, "Finishing on keyShortcutEvent");
+            safelyFinish();
+            return true;
+        }
+        return mWindow.superDispatchKeyShortcutEvent(event);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent event) {
+        // TODO: create more flexible version of mInteractive that allows clicks
+        // but finish()es on any other kind of activity
+        if (!mInteractive) {
+            if (mDebug) Slog.v(TAG, "Finishing on touchEvent");
+            safelyFinish();
+            return true;
+        }
+        return mWindow.superDispatchTouchEvent(event);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean dispatchTrackballEvent(MotionEvent event) {
+        if (!mInteractive) {
+            if (mDebug) Slog.v(TAG, "Finishing on trackballEvent");
+            safelyFinish();
+            return true;
+        }
+        return mWindow.superDispatchTrackballEvent(event);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean dispatchGenericMotionEvent(MotionEvent event) {
+        if (!mInteractive) {
+            if (mDebug) Slog.v(TAG, "Finishing on genericMotionEvent");
+            safelyFinish();
+            return true;
+        }
+        return mWindow.superDispatchGenericMotionEvent(event);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public View onCreatePanelView(int featureId) {
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onCreatePanelMenu(int featureId, Menu menu) {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onPreparePanel(int featureId, View view, Menu menu) {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onMenuOpened(int featureId, Menu menu) {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onMenuItemSelected(int featureId, MenuItem item) {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onWindowAttributesChanged(LayoutParams attrs) {
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onContentChanged() {
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) {
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onAttachedToWindow() {
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onDetachedFromWindow() {
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onPanelClosed(int featureId, Menu menu) {
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onSearchRequested() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback callback) {
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onActionModeStarted(ActionMode mode) {
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onActionModeFinished(ActionMode mode) {
+    }
+    // end Window.Callback methods
+
+    // begin public api
+    /**
+     * Retrieves the current {@link android.view.WindowManager} for the dream.
+     * Behaves similarly to {@link android.app.Activity#getWindowManager()}.
+     *
+     * @return The current window manager, or null if the dream is not started.
+     */
+    public WindowManager getWindowManager() {
+        return mWindowManager;
+    }
+
+    /**
+     * Retrieves the current {@link android.view.Window} for the dream.
+     * Behaves similarly to {@link android.app.Activity#getWindow()}.
+     *
+     * @return The current window, or null if the dream is not started.
+     */
+    public Window getWindow() {
+        return mWindow;
+    }
+
+   /**
+     * Inflates a layout resource and set it to be the content view for this Dream.
+     * Behaves similarly to {@link android.app.Activity#setContentView(int)}.
+     *
+     * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
+     *
+     * @param layoutResID Resource ID to be inflated.
+     *
+     * @see #setContentView(android.view.View)
+     * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
+     */
+    public void setContentView(int layoutResID) {
+        getWindow().setContentView(layoutResID);
+    }
+
+    /**
+     * Sets a view to be the content view for this Dream.
+     * Behaves similarly to {@link android.app.Activity#setContentView(android.view.View)} in an activity,
+     * including using {@link ViewGroup.LayoutParams#MATCH_PARENT} as the layout height and width of the view.
+     *
+     * <p>Note: This requires a window, so you should usually call it during
+     * {@link #onAttachedToWindow()} and never earlier (you <strong>cannot</strong> call it
+     * during {@link #onCreate}).</p>
+     *
+     * @see #setContentView(int)
+     * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
+     */
+    public void setContentView(View view) {
+        getWindow().setContentView(view);
+    }
+
+    /**
+     * Sets a view to be the content view for this Dream.
+     * Behaves similarly to
+     * {@link android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}
+     * in an activity.
+     *
+     * <p>Note: This requires a window, so you should usually call it during
+     * {@link #onAttachedToWindow()} and never earlier (you <strong>cannot</strong> call it
+     * during {@link #onCreate}).</p>
+     *
+     * @param view The desired content to display.
+     * @param params Layout parameters for the view.
+     *
+     * @see #setContentView(android.view.View)
+     * @see #setContentView(int)
+     */
+    public void setContentView(View view, ViewGroup.LayoutParams params) {
+        getWindow().setContentView(view, params);
+    }
+
+    /**
+     * Adds a view to the Dream's window, leaving other content views in place.
+     *
+     * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
+     *
+     * @param view The desired content to display.
+     * @param params Layout parameters for the view.
+     */
+    public void addContentView(View view, ViewGroup.LayoutParams params) {
+        getWindow().addContentView(view, params);
+    }
+
+    /**
+     * Finds a view that was identified by the id attribute from the XML that
+     * was processed in {@link #onCreate}.
+     *
+     * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
+     *
+     * @return The view if found or null otherwise.
+     */
+    public View findViewById(int id) {
+        return getWindow().findViewById(id);
+    }
+
+    /**
+     * Marks this dream as interactive to receive input events.
+     *
+     * <p>Non-interactive dreams (default) will dismiss on the first input event.</p>
+     *
+     * <p>Interactive dreams should call {@link #finish()} to dismiss themselves.</p>
+     *
+     * @param interactive True if this dream will handle input events.
+     */
+    public void setInteractive(boolean interactive) {
+        mInteractive = interactive;
+    }
+
+    /**
+     * Returns whether or not this dream is interactive.  Defaults to false.
+     *
+     * @see #setInteractive(boolean)
+     */
+    public boolean isInteractive() {
+        return mInteractive;
+    }
+
+    /**
+     * Sets View.SYSTEM_UI_FLAG_LOW_PROFILE on the content view.
+     *
+     * @param lowProfile True to set View.SYSTEM_UI_FLAG_LOW_PROFILE
+     * @hide There is no reason to have this -- dreams can set this flag
+     * on their own content view, and from there can actually do the
+     * correct interactions with it (seeing when it is cleared etc).
+     */
+    public void setLowProfile(boolean lowProfile) {
+        mLowProfile = lowProfile;
+        int flag = View.SYSTEM_UI_FLAG_LOW_PROFILE;
+        applySystemUiVisibilityFlags(mLowProfile ? flag : 0, flag);
+    }
+
+    /**
+     * Returns whether or not this dream is in low profile mode. Defaults to true.
+     *
+     * @see #setLowProfile(boolean)
+     * @hide
+     */
+    public boolean isLowProfile() {
+        return getSystemUiVisibilityFlagValue(View.SYSTEM_UI_FLAG_LOW_PROFILE, mLowProfile);
+    }
+
+    /**
+     * Controls {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN}
+     * on the dream's window.
+     *
+     * @param fullscreen If true, the fullscreen flag will be set; else it
+     * will be cleared.
+     */
+    public void setFullscreen(boolean fullscreen) {
+        mFullscreen = fullscreen;
+        int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;
+        applyWindowFlags(mFullscreen ? flag : 0, flag);
+    }
+
+    /**
+     * Returns whether or not this dream is in fullscreen mode. Defaults to false.
+     *
+     * @see #setFullscreen(boolean)
+     */
+    public boolean isFullscreen() {
+        return mFullscreen;
+    }
+
+    /**
+     * Marks this dream as keeping the screen bright while dreaming.
+     *
+     * @param screenBright True to keep the screen bright while dreaming.
+     */
+    public void setScreenBright(boolean screenBright) {
+        mScreenBright = screenBright;
+        int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+        applyWindowFlags(mScreenBright ? flag : 0, flag);
+    }
+
+    /**
+     * Returns whether or not this dream keeps the screen bright while dreaming. Defaults to false,
+     * allowing the screen to dim if necessary.
+     *
+     * @see #setScreenBright(boolean)
+     */
+    public boolean isScreenBright() {
+        return getWindowFlagValue(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, mScreenBright);
+    }
+
+    /**
+     * Called when this Dream is constructed.
+     */
+    @Override
+    public void onCreate() {
+        if (mDebug) Slog.v(TAG, "onCreate() on thread " + Thread.currentThread().getId());
+        super.onCreate();
+    }
+
+    /**
+     * Called when the dream's window has been created and is visible and animation may now begin.
+     */
+    public void onDreamingStarted() {
+        if (mDebug) Slog.v(TAG, "onDreamingStarted()");
+        // hook for subclasses
+    }
+
+    /**
+     * Called when this Dream is stopped, either by external request or by calling finish(),
+     * before the window has been removed.
+     */
+    public void onDreamingStopped() {
+        if (mDebug) Slog.v(TAG, "onDreamingStopped()");
+        // hook for subclasses
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public final IBinder onBind(Intent intent) {
+        if (mDebug) Slog.v(TAG, "onBind() intent = " + intent);
+        return new DreamServiceWrapper();
+    }
+
+    /**
+     * Stops the dream, detaches from the window, and wakes up.
+     */
+    public final void finish() {
+        if (mDebug) Slog.v(TAG, "finish()");
+        finishInternal();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onDestroy() {
+        if (mDebug) Slog.v(TAG, "onDestroy()");
+        // hook for subclasses
+
+        // Just in case destroy came in before detach, let's take care of that now
+        detach();
+
+        super.onDestroy();
+    }
+
+    // end public api
+
+    private void loadSandman() {
+        mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
+    }
+
+    /**
+     * Called by DreamController.stopDream() when the Dream is about to be unbound and destroyed.
+     *
+     * Must run on mHandler.
+     */
+    private final void detach() {
+        if (mWindow == null) {
+            // already detached!
+            return;
+        }
+
+        try {
+            onDreamingStopped();
+        } catch (Throwable t) {
+            Slog.w(TAG, "Crashed in onDreamingStopped()", t);
+            // we were going to stop anyway
+        }
+
+        if (mDebug) Slog.v(TAG, "detach(): Removing window from window manager");
+        try {
+            // force our window to be removed synchronously
+            mWindowManager.removeViewImmediate(mWindow.getDecorView());
+            // the following will print a log message if it finds any other leaked windows
+            WindowManagerGlobal.getInstance().closeAll(mWindowToken,
+                    this.getClass().getName(), "Dream");
+        } catch (Throwable t) {
+            Slog.w(TAG, "Crashed removing window view", t);
+        }
+
+        mWindow = null;
+        mWindowToken = null;
+    }
+
+    /**
+     * Called when the Dream is ready to be shown.
+     *
+     * Must run on mHandler.
+     *
+     * @param windowToken A window token that will allow a window to be created in the correct layer.
+     */
+    private final void attach(IBinder windowToken) {
+        if (mWindowToken != null) {
+            Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken);
+            return;
+        }
+
+        if (mDebug) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId());
+
+        if (mSandman == null) {
+            loadSandman();
+        }
+        mWindowToken = windowToken;
+        mWindow = PolicyManager.makeNewWindow(this);
+        mWindow.setCallback(this);
+        mWindow.requestFeature(Window.FEATURE_NO_TITLE);
+        mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
+        mWindow.setFormat(PixelFormat.OPAQUE);
+
+        if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
+                windowToken, WindowManager.LayoutParams.TYPE_DREAM));
+
+        WindowManager.LayoutParams lp = mWindow.getAttributes();
+        lp.type = WindowManager.LayoutParams.TYPE_DREAM;
+        lp.token = windowToken;
+        lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
+        lp.flags |= ( WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                    | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
+                    | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+                    | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
+                    | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
+                    | (mFullscreen ? WindowManager.LayoutParams.FLAG_FULLSCREEN : 0)
+                    | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0)
+                    );
+        mWindow.setAttributes(lp);
+
+        if (mDebug) Slog.v(TAG, "Created and attached window: " + mWindow);
+
+        mWindow.setWindowManager(null, windowToken, "dream", true);
+        mWindowManager = mWindow.getWindowManager();
+
+        if (mDebug) Slog.v(TAG, "Window added on thread " + Thread.currentThread().getId());
+        try {
+            applySystemUiVisibilityFlags(
+                    (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0),
+                    View.SYSTEM_UI_FLAG_LOW_PROFILE);
+            getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
+        } catch (Throwable t) {
+            Slog.w(TAG, "Crashed adding window view", t);
+            safelyFinish();
+            return;
+        }
+
+        // start it up
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    onDreamingStarted();
+                } catch (Throwable t) {
+                    Slog.w(TAG, "Crashed in onDreamingStarted()", t);
+                    safelyFinish();
+                }
+            }
+        });
+    }
+
+    private void safelyFinish() {
+        if (mDebug) Slog.v(TAG, "safelyFinish()");
+        try {
+            finish();
+        } catch (Throwable t) {
+            Slog.w(TAG, "Crashed in safelyFinish()", t);
+            finishInternal();
+            return;
+        }
+
+        if (!mFinished) {
+            Slog.w(TAG, "Bad dream, did not call super.finish()");
+            finishInternal();
+        }
+    }
+
+    private void finishInternal() {
+        if (mDebug) Slog.v(TAG, "finishInternal() mFinished = " + mFinished);
+        if (mFinished) return;
+        try {
+            mFinished = true;
+
+            if (mSandman != null) {
+                mSandman.finishSelf(mWindowToken);
+            } else {
+                Slog.w(TAG, "No dream manager found");
+            }
+            stopSelf(); // if launched via any other means
+
+        } catch (Throwable t) {
+            Slog.w(TAG, "Crashed in finishInternal()", t);
+        }
+    }
+
+    private boolean getWindowFlagValue(int flag, boolean defaultValue) {
+        return mWindow == null ? defaultValue : (mWindow.getAttributes().flags & flag) != 0;
+    }
+
+    private void applyWindowFlags(int flags, int mask) {
+        if (mWindow != null) {
+            WindowManager.LayoutParams lp = mWindow.getAttributes();
+            lp.flags = applyFlags(lp.flags, flags, mask);
+            mWindow.setAttributes(lp);
+            mWindowManager.updateViewLayout(mWindow.getDecorView(), lp);
+        }
+    }
+
+    private boolean getSystemUiVisibilityFlagValue(int flag, boolean defaultValue) {
+        View v = mWindow == null ? null : mWindow.getDecorView();
+        return v == null ? defaultValue : (v.getSystemUiVisibility() & flag) != 0;
+    }
+
+    private void applySystemUiVisibilityFlags(int flags, int mask) {
+        View v = mWindow == null ? null : mWindow.getDecorView();
+        if (v != null) {
+            v.setSystemUiVisibility(applyFlags(v.getSystemUiVisibility(), flags, mask));
+        }
+    }
+
+    private int applyFlags(int oldFlags, int flags, int mask) {
+        return (oldFlags&~mask) | (flags&mask);
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        super.dump(fd, pw, args);
+
+        pw.print(TAG + ": ");
+        if (mWindowToken == null) {
+            pw.println("stopped");
+        } else {
+            pw.println("running (token=" + mWindowToken + ")");
+        }
+        pw.println("  window: " + mWindow);
+        pw.print("  flags:");
+        if (isInteractive()) pw.print(" interactive");
+        if (isLowProfile()) pw.print(" lowprofile");
+        if (isFullscreen()) pw.print(" fullscreen");
+        if (isScreenBright()) pw.print(" bright");
+        pw.println();
+    }
+
+    private class DreamServiceWrapper extends IDreamService.Stub {
+        public void attach(final IBinder windowToken) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    DreamService.this.attach(windowToken);
+                }
+            });
+        }
+        public void detach() {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    DreamService.this.detach();
+                }
+            });
+        }
+    }
+
+}
diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl
index 7225013..1c1b390 100644
--- a/core/java/android/service/dreams/IDreamManager.aidl
+++ b/core/java/android/service/dreams/IDreamManager.aidl
@@ -19,12 +19,16 @@
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.content.ComponentName;
+import android.os.IBinder;
 
 /** @hide */
 interface IDreamManager {
     void dream();
     void awaken();
-    void setDreamComponent(in ComponentName componentName);
-    ComponentName getDreamComponent();
+    void setDreamComponents(in ComponentName[] componentNames);
+    ComponentName[] getDreamComponents();
+    ComponentName getDefaultDreamComponent();
     void testDream(in ComponentName componentName);
+    boolean isDreaming();
+    void finishSelf(in IBinder token);
 }
\ No newline at end of file
diff --git a/core/java/android/service/dreams/IDreamService.aidl b/core/java/android/service/dreams/IDreamService.aidl
index 1bb241a..99dc0b7 100644
--- a/core/java/android/service/dreams/IDreamService.aidl
+++ b/core/java/android/service/dreams/IDreamService.aidl
@@ -21,4 +21,5 @@
  */
 oneway interface IDreamService {
     void attach(IBinder windowToken);
+    void detach();
 }
diff --git a/core/java/android/service/dreams/Sandman.java b/core/java/android/service/dreams/Sandman.java
new file mode 100644
index 0000000..5f5b079
--- /dev/null
+++ b/core/java/android/service/dreams/Sandman.java
@@ -0,0 +1,123 @@
+/*
+ * 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.service.dreams;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Slog;
+
+/**
+ * Internal helper for launching dreams to ensure consistency between the
+ * <code>UiModeManagerService</code> system service and the <code>Somnambulator</code> activity.
+ *
+ * @hide
+ */
+public final class Sandman {
+    private static final String TAG = "Sandman";
+
+    // The component name of a special dock app that merely launches a dream.
+    // We don't want to launch this app when docked because it causes an unnecessary
+    // activity transition.  We just want to start the dream.
+    private static final ComponentName SOMNAMBULATOR_COMPONENT =
+            new ComponentName("com.android.systemui", "com.android.systemui.Somnambulator");
+
+
+    // The sandman is eternal.  No one instantiates him.
+    private Sandman() {
+    }
+
+    /**
+     * Returns true if the specified dock app intent should be started.
+     * False if we should dream instead, if appropriate.
+     */
+    public static boolean shouldStartDockApp(Context context, Intent intent) {
+        ComponentName name = intent.resolveActivity(context.getPackageManager());
+        return name != null && !name.equals(SOMNAMBULATOR_COMPONENT);
+    }
+
+    /**
+     * Starts a dream manually.
+     */
+    public static void startDreamByUserRequest(Context context) {
+        startDream(context, false);
+    }
+
+    /**
+     * Starts a dream when docked if the system has been configured to do so,
+     * otherwise does nothing.
+     */
+    public static void startDreamWhenDockedIfAppropriate(Context context) {
+        if (!isScreenSaverEnabled(context)
+                || !isScreenSaverActivatedOnDock(context)) {
+            Slog.i(TAG, "Dreams currently disabled for docks.");
+            return;
+        }
+
+        startDream(context, true);
+    }
+
+    private static void startDream(Context context, boolean docked) {
+        try {
+            IDreamManager dreamManagerService = IDreamManager.Stub.asInterface(
+                    ServiceManager.getService(DreamService.DREAM_SERVICE));
+            if (dreamManagerService != null && !dreamManagerService.isDreaming()) {
+                if (docked) {
+                    Slog.i(TAG, "Activating dream while docked.");
+
+                    // Wake up.
+                    // The power manager will wake up the system automatically when it starts
+                    // receiving power from a dock but there is a race between that happening
+                    // and the UI mode manager starting a dream.  We want the system to already
+                    // be awake by the time this happens.  Otherwise the dream may not start.
+                    PowerManager powerManager =
+                            (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+                    powerManager.wakeUp(SystemClock.uptimeMillis());
+                } else {
+                    Slog.i(TAG, "Activating dream by user request.");
+                }
+
+                // Dream.
+                dreamManagerService.dream();
+            }
+        } catch (RemoteException ex) {
+            Slog.e(TAG, "Could not start dream when docked.", ex);
+        }
+    }
+
+    private static boolean isScreenSaverEnabled(Context context) {
+        int def = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_dreamsEnabledByDefault) ? 1 : 0;
+        return Settings.Secure.getIntForUser(context.getContentResolver(),
+                Settings.Secure.SCREENSAVER_ENABLED, def,
+                UserHandle.USER_CURRENT) != 0;
+    }
+
+    private static boolean isScreenSaverActivatedOnDock(Context context) {
+        int def = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault) ? 1 : 0;
+        return Settings.Secure.getIntForUser(context.getContentResolver(),
+                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, def,
+                UserHandle.USER_CURRENT) != 0;
+    }
+}
diff --git a/core/java/android/service/wallpaper/IWallpaperConnection.aidl b/core/java/android/service/wallpaper/IWallpaperConnection.aidl
index b09ccab..f9c5aaa 100644
--- a/core/java/android/service/wallpaper/IWallpaperConnection.aidl
+++ b/core/java/android/service/wallpaper/IWallpaperConnection.aidl
@@ -24,5 +24,6 @@
  */
 interface IWallpaperConnection {
 	void attachEngine(IWallpaperEngine engine);
+	void engineShown(IWallpaperEngine engine);
     ParcelFileDescriptor setWallpaper(String name);
 }
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 3e0942c..6d5705d 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -36,10 +36,10 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
-import android.os.Process;
 import android.os.RemoteException;
 import android.util.Log;
 import android.util.LogPrinter;
+import android.view.Display;
 import android.view.Gravity;
 import android.view.IWindowSession;
 import android.view.InputChannel;
@@ -50,9 +50,8 @@
 import android.view.SurfaceHolder;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewRootImpl;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+import android.view.WindowManagerGlobal;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -98,6 +97,7 @@
     private static final int MSG_WALLPAPER_OFFSETS = 10020;
     private static final int MSG_WALLPAPER_COMMAND = 10025;
     private static final int MSG_WINDOW_RESIZED = 10030;
+    private static final int MSG_WINDOW_MOVED = 10035;
     private static final int MSG_TOUCH_EVENT = 10040;
     
     private Looper mCallbackLooper;
@@ -253,13 +253,19 @@
 
         final BaseIWindow mWindow = new BaseIWindow() {
             @Override
-            public void resized(int w, int h, Rect contentInsets,
+            public void resized(Rect frame, Rect contentInsets,
                     Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
                 Message msg = mCaller.obtainMessageI(MSG_WINDOW_RESIZED,
                         reportDraw ? 1 : 0);
                 mCaller.sendMessage(msg);
             }
-            
+
+            @Override
+            public void moved(int newX, int newY) {
+                Message msg = mCaller.obtainMessageII(MSG_WINDOW_MOVED, newX, newY);
+                mCaller.sendMessage(msg);
+            }
+
             @Override
             public void dispatchAppVisibility(boolean visible) {
                 // We don't do this in preview mode; we'll let the preview
@@ -290,7 +296,8 @@
                     }
                 }
             }
-            
+
+            @Override
             public void dispatchWallpaperCommand(String action, int x, int y,
                     int z, Bundle extras, boolean sync) {
                 synchronized (mLock) {
@@ -567,7 +574,8 @@
             final boolean flagsChanged = mCurWindowFlags != mWindowFlags ||
                     mCurWindowPrivateFlags != mWindowPrivateFlags;
             if (forceRelayout || creating || surfaceCreating || formatChanged || sizeChanged
-                    || typeChanged || flagsChanged || redrawNeeded) {
+                    || typeChanged || flagsChanged || redrawNeeded
+                    || !mIWallpaperEngine.mShownReported) {
 
                 if (DEBUG) Log.v(TAG, "Changes: creating=" + creating
                         + " format=" + formatChanged + " size=" + sizeChanged);
@@ -599,13 +607,13 @@
 
                     if (!mCreated) {
                         mLayout.type = mIWallpaperEngine.mWindowType;
-                        mLayout.gravity = Gravity.LEFT|Gravity.TOP;
+                        mLayout.gravity = Gravity.START|Gravity.TOP;
                         mLayout.setTitle(WallpaperService.this.getClass().getName());
                         mLayout.windowAnimations =
                                 com.android.internal.R.style.Animation_Wallpaper;
                         mInputChannel = new InputChannel();
-                        if (mSession.add(mWindow, mWindow.mSeq, mLayout, View.VISIBLE, mContentInsets,
-                                mInputChannel) < 0) {
+                        if (mSession.addToDisplay(mWindow, mWindow.mSeq, mLayout, View.VISIBLE,
+                            Display.DEFAULT_DISPLAY, mContentInsets, mInputChannel) < 0) {
                             Log.w(TAG, "Failed to add window while updating wallpaper surface.");
                             return;
                         }
@@ -665,8 +673,8 @@
                             }
                         }
 
-                        redrawNeeded |= creating
-                                || (relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0;
+                        redrawNeeded |= creating || (relayoutResult
+                                & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
 
                         if (forceReport || creating || surfaceCreating
                                 || formatChanged || sizeChanged) {
@@ -732,6 +740,7 @@
                         if (redrawNeeded) {
                             mSession.finishDrawing(mWindow);
                         }
+                        mIWallpaperEngine.reportShown();
                     }
                 } catch (RemoteException ex) {
                 }
@@ -753,7 +762,7 @@
             mWindowToken = wrapper.mWindowToken;
             mSurfaceHolder.setSizeFromLayout();
             mInitializing = true;
-            mSession = ViewRootImpl.getWindowSession(getMainLooper());
+            mSession = WindowManagerGlobal.getWindowSession(getMainLooper());
             
             mWindow.setSession(mSession);
 
@@ -943,6 +952,7 @@
         final IBinder mWindowToken;
         final int mWindowType;
         final boolean mIsPreview;
+        boolean mShownReported;
         int mReqWidth;
         int mReqHeight;
         
@@ -995,6 +1005,18 @@
             }
         }
 
+        public void reportShown() {
+            if (!mShownReported) {
+                mShownReported = true;
+                try {
+                    mConnection.engineShown(this);
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Wallpaper host disappeared", e);
+                    return;
+                }
+            }
+        }
+
         public void destroy() {
             Message msg = mCaller.obtainMessage(DO_DETACH);
             mCaller.sendMessage(msg);
@@ -1044,6 +1066,9 @@
                     mEngine.updateSurface(true, false, reportDraw);
                     mEngine.doOffsetsChanged(true);
                 } break;
+                case MSG_WINDOW_MOVED: {
+                    // Do nothing. What does it mean for a Wallpaper to move?
+                } break;
                 case MSG_TOUCH_EVENT: {
                     boolean skip = false;
                     MotionEvent ev = (MotionEvent)message.obj;
diff --git a/core/java/android/speech/tts/BlockingAudioTrack.java b/core/java/android/speech/tts/BlockingAudioTrack.java
index fcadad7..186cb49 100644
--- a/core/java/android/speech/tts/BlockingAudioTrack.java
+++ b/core/java/android/speech/tts/BlockingAudioTrack.java
@@ -67,12 +67,11 @@
     private int mAudioBufferSize;
     private int mBytesWritten = 0;
 
+    // Need to be seen by stop() which can be called from another thread. mAudioTrack will be
+    // set to null only after waitAndRelease().
+    private Object mAudioTrackLock = new Object();
     private AudioTrack mAudioTrack;
     private volatile boolean mStopped;
-    // Locks the initialization / uninitialization of the audio track.
-    // This is required because stop() will throw an illegal state exception
-    // if called before init() or after mAudioTrack.release().
-    private final Object mAudioTrackLock = new Object();
 
     BlockingAudioTrack(int streamType, int sampleRate,
             int audioFormat, int channelCount,
@@ -93,12 +92,17 @@
         mStopped = false;
     }
 
-    public void init() {
+    public boolean init() {
         AudioTrack track = createStreamingAudioTrack();
-
         synchronized (mAudioTrackLock) {
             mAudioTrack = track;
         }
+
+        if (track == null) {
+            return false;
+        } else {
+            return true;
+        }
     }
 
     public void stop() {
@@ -106,20 +110,35 @@
             if (mAudioTrack != null) {
                 mAudioTrack.stop();
             }
+            mStopped = true;
         }
-        mStopped = true;
     }
 
     public int write(byte[] data) {
-        if (mAudioTrack == null || mStopped) {
+        AudioTrack track = null;
+        synchronized (mAudioTrackLock) {
+            track = mAudioTrack;
+        }
+
+        if (track == null || mStopped) {
             return -1;
         }
-        final int bytesWritten = writeToAudioTrack(mAudioTrack, data);
+        final int bytesWritten = writeToAudioTrack(track, data);
+
         mBytesWritten += bytesWritten;
         return bytesWritten;
     }
 
     public void waitAndRelease() {
+        AudioTrack track = null;
+        synchronized (mAudioTrackLock) {
+            track = mAudioTrack;
+        }
+        if (track == null) {
+            if (DBG) Log.d(TAG, "Audio track null [duplicate call to waitAndRelease ?]");
+            return;
+        }
+
         // For "small" audio tracks, we have to stop() them to make them mixable,
         // else the audio subsystem will wait indefinitely for us to fill the buffer
         // before rendering the track mixable.
@@ -129,11 +148,11 @@
         if (mBytesWritten < mAudioBufferSize && !mStopped) {
             if (DBG) {
                 Log.d(TAG, "Stopping audio track to flush audio, state was : " +
-                        mAudioTrack.getPlayState() + ",stopped= " + mStopped);
+                        track.getPlayState() + ",stopped= " + mStopped);
             }
 
             mIsShortUtterance = true;
-            mAudioTrack.stop();
+            track.stop();
         }
 
         // Block until the audio track is done only if we haven't stopped yet.
@@ -145,11 +164,11 @@
         // The last call to AudioTrack.write( ) will return only after
         // all data from the audioTrack has been sent to the mixer, so
         // it's safe to release at this point.
-        if (DBG) Log.d(TAG, "Releasing audio track [" + mAudioTrack.hashCode() + "]");
-        synchronized (mAudioTrackLock) {
-            mAudioTrack.release();
+        if (DBG) Log.d(TAG, "Releasing audio track [" + track.hashCode() + "]");
+        synchronized(mAudioTrackLock) {
             mAudioTrack = null;
         }
+        track.release();
     }
 
 
diff --git a/core/java/android/speech/tts/FileSynthesisCallback.java b/core/java/android/speech/tts/FileSynthesisCallback.java
index 04c3377..3e33e8e 100644
--- a/core/java/android/speech/tts/FileSynthesisCallback.java
+++ b/core/java/android/speech/tts/FileSynthesisCallback.java
@@ -95,6 +95,22 @@
         }
     }
 
+    /**
+     * Checks whether a given file exists, and deletes it if it does.
+     */
+    private boolean maybeCleanupExistingFile(File file) {
+        if (file.exists()) {
+            Log.v(TAG, "File " + file + " exists, deleting.");
+            if (!file.delete()) {
+                Log.e(TAG, "Failed to delete " + file);
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+
     @Override
     public int getMaxBufferSize() {
         return MAX_AUDIO_BUFFER_SIZE;
@@ -120,6 +136,11 @@
                 cleanUp();
                 throw new IllegalArgumentException("FileSynthesisRequest.start() called twice");
             }
+
+            if (!maybeCleanupExistingFile(mFileName)) {
+                return TextToSpeech.ERROR;
+            }
+
             mSampleRateInHz = sampleRateInHz;
             mAudioFormat = audioFormat;
             mChannelCount = channelCount;
@@ -166,6 +187,12 @@
     public int done() {
         if (DBG) Log.d(TAG, "FileSynthesisRequest.done()");
         synchronized (mStateLock) {
+            if (mDone) {
+                if (DBG) Log.d(TAG, "Duplicate call to done()");
+                // This preserves existing behaviour. Earlier, if done was called twice
+                // we'd return ERROR because mFile == null and we'd add to logspam.
+                return TextToSpeech.ERROR;
+            }
             if (mStopped) {
                 if (DBG) Log.d(TAG, "Request has been aborted.");
                 return TextToSpeech.ERROR;
diff --git a/core/java/android/speech/tts/SynthesisPlaybackQueueItem.java b/core/java/android/speech/tts/SynthesisPlaybackQueueItem.java
index d299d70..e853c9e 100644
--- a/core/java/android/speech/tts/SynthesisPlaybackQueueItem.java
+++ b/core/java/android/speech/tts/SynthesisPlaybackQueueItem.java
@@ -87,7 +87,10 @@
         dispatcher.dispatchOnStart();
 
 
-        mAudioTrack.init();
+        if (!mAudioTrack.init()) {
+            dispatcher.dispatchOnError();
+            return;
+        }
 
         try {
             byte[] buffer = null;
@@ -242,4 +245,3 @@
         }
     }
 }
-
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 7a174af..5e367cb 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -1282,6 +1282,7 @@
             }
         };
 
+        @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
             Log.i(TAG, "Connected to " + name);
             synchronized(mStartLock) {
@@ -1305,6 +1306,7 @@
             return mCallback;
         }
 
+        @Override
         public void onServiceDisconnected(ComponentName name) {
             synchronized(mStartLock) {
                 mService = null;
@@ -1317,24 +1319,33 @@
 
         public void disconnect() {
             mContext.unbindService(this);
+
+            synchronized (mStartLock) {
+                mService = null;
+                // If this is the active connection, clear it
+                if (mServiceConnection == this) {
+                    mServiceConnection = null;
+                }
+
+            }
         }
 
         public <R> R runAction(Action<R> action, R errorResult, String method, boolean reconnect) {
-            try {
-                synchronized (mStartLock) {
+            synchronized (mStartLock) {
+                try {
                     if (mService == null) {
                         Log.w(TAG, method + " failed: not connected to TTS engine");
                         return errorResult;
                     }
                     return action.run(mService);
+                } catch (RemoteException ex) {
+                    Log.e(TAG, method + " failed", ex);
+                    if (reconnect) {
+                        disconnect();
+                        initTts();
+                    }
+                    return errorResult;
                 }
-            } catch (RemoteException ex) {
-                Log.e(TAG, method + " failed", ex);
-                if (reconnect) {
-                    disconnect();
-                    initTts();
-                }
-                return errorResult;
             }
         }
     }
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 4c1a0af..d124e68 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -549,7 +549,7 @@
         @Override
         public boolean isValid() {
             if (mText == null) {
-                Log.wtf(TAG, "Got null text");
+                Log.e(TAG, "null synthesis text");
                 return false;
             }
             if (mText.length() >= MAX_SPEECH_ITEM_CHAR_LENGTH) {
@@ -641,14 +641,6 @@
         }
 
         @Override
-        public boolean isValid() {
-            if (!super.isValid()) {
-                return false;
-            }
-            return checkFile(mFile);
-        }
-
-        @Override
         protected AbstractSynthesisCallback createSynthesisCallback() {
             return new FileSynthesisCallback(mFile);
         }
@@ -664,33 +656,6 @@
             }
             return status;
         }
-
-        /**
-         * Checks that the given file can be used for synthesis output.
-         */
-        private boolean checkFile(File file) {
-            try {
-                if (file.exists()) {
-                    Log.v(TAG, "File " + file + " exists, deleting.");
-                    if (!file.delete()) {
-                        Log.e(TAG, "Failed to delete " + file);
-                        return false;
-                    }
-                }
-                if (!file.createNewFile()) {
-                    Log.e(TAG, "Can't create file " + file);
-                    return false;
-                }
-                if (!file.delete()) {
-                    Log.e(TAG, "Failed to delete " + file);
-                    return false;
-                }
-                return true;
-            } catch (IOException e) {
-                Log.e(TAG, "Can't use " + file + " due to exception " + e);
-                return false;
-            }
-        }
     }
 
     private class AudioSpeechItem extends SpeechItem {
diff --git a/core/java/android/test/AndroidTestCase.java b/core/java/android/test/AndroidTestCase.java
index 1015506..0c8cbe6 100644
--- a/core/java/android/test/AndroidTestCase.java
+++ b/core/java/android/test/AndroidTestCase.java
@@ -135,7 +135,8 @@
             fail("expected SecurityException requiring " + permission);
         } catch (SecurityException expected) {
             assertNotNull("security exception's error message.", expected.getMessage());
-            assertTrue("error message should contain " + permission + ".",
+            assertTrue("error message should contain \"" + permission + "\". Got: \""
+                    + expected.getMessage() + "\".",
                     expected.getMessage().contains(permission));
         }
     }
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
index 35e2e4a..1aab911 100644
--- a/core/java/android/text/Html.java
+++ b/core/java/android/text/Html.java
@@ -221,10 +221,10 @@
                 false /* no info */);
         switch(paraDir) {
             case Layout.DIR_RIGHT_TO_LEFT:
-                return "<p dir=rtl>";
+                return "<p dir=\"rtl\">";
             case Layout.DIR_LEFT_TO_RIGHT:
             default:
-                return "<p dir=ltr>";
+                return "<p dir=\"ltr\">";
         }
     }
 
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index d2bed48..123acca 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -475,10 +475,14 @@
         Alignment align = getParagraphAlignment(line);
         int dir = getParagraphDirection(line);
 
-        int x;
         if (align == Alignment.ALIGN_LEFT) {
-            x = left;
-        } else if (align == Alignment.ALIGN_NORMAL) {
+            align = (dir == DIR_LEFT_TO_RIGHT) ? Alignment.ALIGN_NORMAL : Alignment.ALIGN_OPPOSITE;
+        } else if (align == Alignment.ALIGN_RIGHT) {
+            align = (dir == DIR_LEFT_TO_RIGHT) ? Alignment.ALIGN_OPPOSITE : Alignment.ALIGN_NORMAL;
+        }
+
+        int x;
+        if (align == Alignment.ALIGN_NORMAL) {
             if (dir == DIR_LEFT_TO_RIGHT) {
                 x = left;
             } else {
@@ -498,12 +502,11 @@
                 }
             }
             int max = (int)getLineExtent(line, tabStops, false);
-            if (align == Alignment.ALIGN_RIGHT) {
-                x = right - max;
-            } else if (align == Alignment.ALIGN_OPPOSITE) {
+            if (align == Alignment.ALIGN_OPPOSITE) {
                 if (dir == DIR_LEFT_TO_RIGHT) {
                     x = right - max;
                 } else {
+                    // max is negative here
                     x = left - max;
                 }
             } else { // Alignment.ALIGN_CENTER
diff --git a/core/java/android/text/Spanned.java b/core/java/android/text/Spanned.java
index 2b73763..b4622e0 100644
--- a/core/java/android/text/Spanned.java
+++ b/core/java/android/text/Spanned.java
@@ -30,8 +30,19 @@
      * of spans.
      *
      * MARK and POINT are conceptually located <i>between</i> two adjacent characters.
-     * A MARK is "attached" to the character on the left hand side, while a POINT
-     * tends to stick to the character on the right hand side.
+     * A MARK is "attached" to the character before, while a POINT will stick to the character
+     * after. The insertion cursor is conceptually located between the MARK and the POINT.
+     *
+     * As a result, inserting a new character between a MARK and a POINT will leave the MARK
+     * unchanged, while the POINT will be shifted, now located after the inserted character and
+     * still glued to the same character after it.
+     *
+     * Depending on whether the insertion happens at the beginning or the end of a span, the span
+     * will hence be expanded to <i>include</i> the new character (when the span is using a MARK at
+     * its beginning or a POINT at its end) or it will be <i>excluded</i>.
+     *
+     * Note that <i>before</i> and <i>after</i> here refer to offsets in the String, which are
+     * independent from the visual representation of the text (left-to-right or right-to-left).
      */
     public static final int SPAN_POINT_MARK_MASK = 0x33;
     
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 6a619af..9051285 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -150,8 +150,8 @@
 
         mColumns = COLUMNS_ELLIPSIZE;
         mLines = new int[ArrayUtils.idealIntArraySize(2 * mColumns)];
-        mLineDirections = new Directions[
-                             ArrayUtils.idealIntArraySize(2 * mColumns)];
+        mLineDirections = new Directions[ArrayUtils.idealIntArraySize(2 * mColumns)];
+        // FIXME This is never recycled
         mMeasured = MeasuredText.obtain();
     }
 
@@ -340,7 +340,9 @@
                         w += widths[j - paraStart];
                     }
 
-                    if (w <= width) {
+                    boolean isSpaceOrTab = c == CHAR_SPACE || c == CHAR_TAB;
+
+                    if (w <= width || isSpaceOrTab) {
                         fitWidth = w;
                         fit = j + 1;
 
@@ -353,30 +355,17 @@
                         if (fmBottom > fitBottom)
                             fitBottom = fmBottom;
 
-                        /*
-                         * From the Unicode Line Breaking Algorithm:
-                         * (at least approximately)
-                         *
-                         * .,:; are class IS: breakpoints
-                         *      except when adjacent to digits
-                         * /    is class SY: a breakpoint
-                         *      except when followed by a digit.
-                         * -    is class HY: a breakpoint
-                         *      except when followed by a digit.
-                         *
-                         * Ideographs are class ID: breakpoints when adjacent,
-                         * except for NS (non-starters), which can be broken
-                         * after but not before.
-                         */
-                        if (c == CHAR_SPACE || c == CHAR_TAB ||
-                            ((c == CHAR_DOT || c == CHAR_COMMA ||
-                                    c == CHAR_COLON || c == CHAR_SEMICOLON) &&
-                             (j - 1 < here || !Character.isDigit(chs[j - 1 - paraStart])) &&
-                             (j + 1 >= spanEnd || !Character.isDigit(chs[j + 1 - paraStart]))) ||
-                            ((c == CHAR_SLASH || c == CHAR_HYPHEN) &&
-                             (j + 1 >= spanEnd || !Character.isDigit(chs[j + 1 - paraStart]))) ||
-                            (c >= CHAR_FIRST_CJK && isIdeographic(c, true) &&
-                             j + 1 < spanEnd && isIdeographic(chs[j + 1 - paraStart], false))) {
+                        // From the Unicode Line Breaking Algorithm (at least approximately)
+                        boolean isLineBreak = isSpaceOrTab ||
+                                // / is class SY and - is class HY, except when followed by a digit
+                                ((c == CHAR_SLASH || c == CHAR_HYPHEN) &&
+                                (j + 1 >= spanEnd || !Character.isDigit(chs[j + 1 - paraStart]))) ||
+                                // Ideographs are class ID: breakpoints when adjacent, except for NS
+                                // (non-starters), which can be broken after but not before
+                                (c >= CHAR_FIRST_CJK && isIdeographic(c, true) &&
+                                j + 1 < spanEnd && isIdeographic(chs[j + 1 - paraStart], false));
+
+                        if (isLineBreak) {
                             okWidth = w;
                             ok = j + 1;
 
@@ -396,13 +385,6 @@
                         float currentTextWidth;
 
                         if (ok != here) {
-                            // If it is a space that makes the length exceed width, cut here
-                            if (c == CHAR_SPACE) ok = j + 1;
-
-                            while (ok < spanEnd && chs[ok - paraStart] == CHAR_SPACE) {
-                                ok++;
-                            }
-
                             endPos = ok;
                             above = okAscent;
                             below = okDescent;
@@ -450,10 +432,10 @@
                             spanEnd = here;
                             break;
                         }
-                    }
-                    // FIXME This should be moved in the above else block which changes mLineCount
-                    if (mLineCount >= mMaximumVisibleLineCount) {
-                        break;
+
+                        if (mLineCount >= mMaximumVisibleLineCount) {
+                            break;
+                        }
                     }
                 }
             }
@@ -972,10 +954,6 @@
     private static final char CHAR_NEW_LINE = '\n';
     private static final char CHAR_TAB = '\t';
     private static final char CHAR_SPACE = ' ';
-    private static final char CHAR_DOT = '.';
-    private static final char CHAR_COMMA = ',';
-    private static final char CHAR_COLON = ':';
-    private static final char CHAR_SEMICOLON = ';';
     private static final char CHAR_SLASH = '/';
     private static final char CHAR_HYPHEN = '-';
 
diff --git a/core/java/android/text/TextDirectionHeuristics.java b/core/java/android/text/TextDirectionHeuristics.java
index be2840b..df8c4c6 100644
--- a/core/java/android/text/TextDirectionHeuristics.java
+++ b/core/java/android/text/TextDirectionHeuristics.java
@@ -17,11 +17,11 @@
 package android.text;
 
 
-import android.util.LocaleUtil;
 import android.view.View;
 
 /**
  * Some objects that implement TextDirectionHeuristic.
+ *
  * @hide
  */
 public class TextDirectionHeuristics {
@@ -241,7 +241,7 @@
 
         @Override
         protected boolean defaultIsRtl() {
-            final int dir = LocaleUtil.getLayoutDirectionFromLocale(java.util.Locale.getDefault());
+            final int dir = TextUtils.getLayoutDirectionFromLocale(java.util.Locale.getDefault());
             return (dir == View.LAYOUT_DIRECTION_RTL);
         }
 
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 0d2835a..1fecf81 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -939,27 +939,22 @@
                 continue;
             }
 
-            if (c == null) {
-                x += handleText(wp, i, mlimit, i, inext, runIsRtl, c, x, top,
-                        y, bottom, fmi, needWidth || mlimit < measureLimit);
-            } else {
-                for (int j = i, jnext; j < mlimit; j = jnext) {
-                    jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + mlimit) -
-                            mStart;
+            for (int j = i, jnext; j < mlimit; j = jnext) {
+                jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + mlimit) -
+                        mStart;
 
-                    wp.set(mPaint);
-                    for (int k = 0; k < mCharacterStyleSpanSet.numberOfSpans; k++) {
-                        // Intentionally using >= and <= as explained above
-                        if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + jnext) ||
-                                (mCharacterStyleSpanSet.spanEnds[k] <= mStart + j)) continue;
+                wp.set(mPaint);
+                for (int k = 0; k < mCharacterStyleSpanSet.numberOfSpans; k++) {
+                    // Intentionally using >= and <= as explained above
+                    if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + jnext) ||
+                            (mCharacterStyleSpanSet.spanEnds[k] <= mStart + j)) continue;
 
-                        CharacterStyle span = mCharacterStyleSpanSet.spans[k];
-                        span.updateDrawState(wp);
-                    }
-
-                    x += handleText(wp, j, jnext, i, inext, runIsRtl, c, x,
-                            top, y, bottom, fmi, needWidth || jnext < measureLimit);
+                    CharacterStyle span = mCharacterStyleSpanSet.spans[k];
+                    span.updateDrawState(wp);
                 }
+
+                x += handleText(wp, j, jnext, i, inext, runIsRtl, c, x,
+                        top, y, bottom, fmi, needWidth || jnext < measureLimit);
             }
         }
 
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 270624c..1508d10 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -27,6 +27,7 @@
 import android.text.style.EasyEditSpan;
 import android.text.style.ForegroundColorSpan;
 import android.text.style.LeadingMarginSpan;
+import android.text.style.LocaleSpan;
 import android.text.style.MetricAffectingSpan;
 import android.text.style.QuoteSpan;
 import android.text.style.RelativeSizeSpan;
@@ -45,11 +46,14 @@
 import android.text.style.UnderlineSpan;
 import android.util.Printer;
 
+import android.view.View;
 import com.android.internal.R;
 import com.android.internal.util.ArrayUtils;
+import libcore.icu.ICU;
 
 import java.lang.reflect.Array;
 import java.util.Iterator;
+import java.util.Locale;
 import java.util.regex.Pattern;
 
 public class TextUtils {
@@ -587,6 +591,8 @@
     public static final int SUGGESTION_RANGE_SPAN = 21;
     /** @hide */
     public static final int EASY_EDIT_SPAN = 22;
+    /** @hide */
+    public static final int LOCALE_SPAN = 23;
 
     /**
      * Flatten a CharSequence and whatever styles can be copied across processes
@@ -754,6 +760,10 @@
                     readSpan(p, sp, new EasyEditSpan());
                     break;
 
+                case LOCALE_SPAN:
+                    readSpan(p, sp, new LocaleSpan(p));
+                    break;
+
                 default:
                     throw new RuntimeException("bogus span encoding " + kind);
                 }
@@ -1042,9 +1052,14 @@
                                          float avail, TruncateAt where,
                                          boolean preserveLength,
                                          EllipsizeCallback callback) {
+
+        final String ellipsis = (where == TruncateAt.END_SMALL) ?
+                Resources.getSystem().getString(R.string.ellipsis_two_dots) :
+                Resources.getSystem().getString(R.string.ellipsis);
+
         return ellipsize(text, paint, avail, where, preserveLength, callback,
                 TextDirectionHeuristics.FIRSTSTRONG_LTR,
-                (where == TruncateAt.END_SMALL) ? ELLIPSIS_TWO_DOTS : ELLIPSIS_NORMAL);
+                ellipsis);
     }
 
     /**
@@ -1694,15 +1709,64 @@
         return (int) (range & 0x00000000FFFFFFFFL);
     }
 
+    /**
+     * Return the layout direction for a given Locale
+     *
+     * @param locale the Locale for which we want the layout direction. Can be null.
+     * @return the layout direction. This may be one of:
+     * {@link android.view.View#LAYOUT_DIRECTION_LTR} or
+     * {@link android.view.View#LAYOUT_DIRECTION_RTL}.
+     *
+     * Be careful: this code will need to be updated when vertical scripts will be supported
+     */
+    public static int getLayoutDirectionFromLocale(Locale locale) {
+        if (locale != null && !locale.equals(Locale.ROOT)) {
+            final String scriptSubtag = ICU.getScript(ICU.addLikelySubtags(locale.toString()));
+            if (scriptSubtag == null) return getLayoutDirectionFromFirstChar(locale);
+
+            if (scriptSubtag.equalsIgnoreCase(ARAB_SCRIPT_SUBTAG) ||
+                    scriptSubtag.equalsIgnoreCase(HEBR_SCRIPT_SUBTAG)) {
+                return View.LAYOUT_DIRECTION_RTL;
+            }
+        }
+
+        return View.LAYOUT_DIRECTION_LTR;
+    }
+
+    /**
+     * Fallback algorithm to detect the locale direction. Rely on the fist char of the
+     * localized locale name. This will not work if the localized locale name is in English
+     * (this is the case for ICU 4.4 and "Urdu" script)
+     *
+     * @param locale
+     * @return the layout direction. This may be one of:
+     * {@link View#LAYOUT_DIRECTION_LTR} or
+     * {@link View#LAYOUT_DIRECTION_RTL}.
+     *
+     * Be careful: this code will need to be updated when vertical scripts will be supported
+     *
+     * @hide
+     */
+    private static int getLayoutDirectionFromFirstChar(Locale locale) {
+        switch(Character.getDirectionality(locale.getDisplayName(locale).charAt(0))) {
+            case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
+            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
+                return View.LAYOUT_DIRECTION_RTL;
+
+            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
+            default:
+                return View.LAYOUT_DIRECTION_LTR;
+        }
+    }
+
     private static Object sLock = new Object();
+
     private static char[] sTemp = null;
 
     private static String[] EMPTY_STRING_ARRAY = new String[]{};
 
     private static final char ZWNBS_CHAR = '\uFEFF';
 
-    private static final String ELLIPSIS_NORMAL = Resources.getSystem().getString(
-            R.string.ellipsis);
-    private static final String ELLIPSIS_TWO_DOTS = Resources.getSystem().getString(
-            R.string.ellipsis_two_dots);
+    private static String ARAB_SCRIPT_SUBTAG = "Arab";
+    private static String HEBR_SCRIPT_SUBTAG = "Hebr";
 }
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index 524f941..3c984b5 100644
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -35,10 +35,18 @@
     Utility class for producing strings with formatted date/time.
 
     <p>
-    This class takes as inputs a format string and a representation of a date/time.
-    The format string controls how the output is generated.
+    Most callers should avoid supplying their own format strings to this
+    class' {@code format} methods and rely on the correctly localized ones
+    supplied by the system. This class' factory methods return
+    appropriately-localized {@link java.text.DateFormat} instances, suitable
+    for both formatting and parsing dates. For the canonical documentation
+    of format strings, see {@link java.text.SimpleDateFormat}.
     </p>
     <p>
+    The format methods in this class takes as inputs a format string and a representation of a date/time.
+    The format string controls how the output is generated.
+    This class only supports a subset of the full Unicode specification.
+    Use {@link java.text.SimpleDateFormat} if you need more.
     Formatting characters may be repeated in order to get more detailed representations
     of that field.  For instance, the format character &apos;M&apos; is used to
     represent the month.  Depending on how many times that character is repeated
@@ -152,7 +160,8 @@
     public  static final char    MINUTE                 =    'm';
 
     /**
-        This designator indicates the month of the year
+        This designator indicates the month of the year. See also
+        {@link #STANDALONE_MONTH}.
      
         Examples for September:
         M -> 9
@@ -163,6 +172,14 @@
     public  static final char    MONTH                  =    'M';
 
     /**
+        This designator indicates the standalone month of the year,
+        necessary in some format strings in some languages. For
+        example, Russian distinguishes between the "June" in
+        "June" and that in "June 2010".
+     */
+    public  static final char    STANDALONE_MONTH       =    'L';
+
+    /**
         This designator indicates the seconds of the minute.
      
         Examples for 7 seconds past the minute:
@@ -232,12 +249,13 @@
 
             synchronized (sLocaleLock) {
                 sIs24HourLocale = locale;
-                sIs24Hour = !value.equals("12");
+                sIs24Hour = value.equals("24");
             }
+
+            return sIs24Hour;
         }
 
-        boolean b24 =  !(value == null || value.equals("12"));
-        return b24;
+        return value.equals("24");
     }
 
     /**
@@ -246,7 +264,7 @@
      * @param context the application context
      * @return the {@link java.text.DateFormat} object that properly formats the time.
      */
-    public static final java.text.DateFormat getTimeFormat(Context context) {
+    public static java.text.DateFormat getTimeFormat(Context context) {
         boolean b24 = is24HourFormat(context);
         int res;
 
@@ -266,7 +284,7 @@
      * @param context the application context
      * @return the {@link java.text.DateFormat} object that properly formats the date.
      */
-    public static final java.text.DateFormat getDateFormat(Context context) {
+    public static java.text.DateFormat getDateFormat(Context context) {
         String value = Settings.System.getString(context.getContentResolver(),
                 Settings.System.DATE_FORMAT);
 
@@ -336,7 +354,7 @@
      * @param context the application context
      * @return the {@link java.text.DateFormat} object that formats the date in long form.
      */
-    public static final java.text.DateFormat getLongDateFormat(Context context) {
+    public static java.text.DateFormat getLongDateFormat(Context context) {
         return java.text.DateFormat.getDateInstance(java.text.DateFormat.LONG);
     }
 
@@ -346,7 +364,7 @@
      * @param context the application context
      * @return the {@link java.text.DateFormat} object that formats the date in long form.
      */
-    public static final java.text.DateFormat getMediumDateFormat(Context context) {
+    public static java.text.DateFormat getMediumDateFormat(Context context) {
         return java.text.DateFormat.getDateInstance(java.text.DateFormat.MEDIUM);
     }
 
@@ -359,7 +377,7 @@
      * not just the day, month, and year, and not necessarily in the same
      * order returned here.
      */    
-    public static final char[] getDateFormatOrder(Context context) {
+    public static char[] getDateFormatOrder(Context context) {
         char[] order = new char[] {DATE, MONTH, YEAR};
         String value = getDateFormatString(context);
         int index = 0;
@@ -374,7 +392,7 @@
                 index++;
             }
 
-            if (!foundMonth && (c == MONTH)) {
+            if (!foundMonth && (c == MONTH || c == STANDALONE_MONTH)) {
                 foundMonth = true;
                 order[index] = MONTH;
                 index++;
@@ -403,7 +421,7 @@
      * @param inTimeInMillis in milliseconds since Jan 1, 1970 GMT
      * @return a {@link CharSequence} containing the requested text
      */
-    public static final CharSequence format(CharSequence inFormat, long inTimeInMillis) {
+    public static CharSequence format(CharSequence inFormat, long inTimeInMillis) {
         return format(inFormat, new Date(inTimeInMillis));
     }
 
@@ -414,7 +432,7 @@
      * @param inDate the date to format
      * @return a {@link CharSequence} containing the requested text
      */
-    public static final CharSequence format(CharSequence inFormat, Date inDate) {
+    public static CharSequence format(CharSequence inFormat, Date inDate) {
         Calendar    c = new GregorianCalendar();
         
         c.setTime(inDate);
@@ -423,13 +441,75 @@
     }
 
     /**
+     * Indicates whether the specified format string contains seconds.
+     * 
+     * Always returns false if the input format is null.
+     * 
+     * @param inFormat the format string, as described in {@link android.text.format.DateFormat}
+     *                 
+     * @return true if the format string contains {@link #SECONDS}, false otherwise
+     * 
+     * @hide
+     */
+    public static boolean hasSeconds(CharSequence inFormat) {
+        if (inFormat == null) return false;
+
+        final int length = inFormat.length();
+
+        int c;
+        int count;
+
+        for (int i = 0; i < length; i += count) {
+            count = 1;
+            c = inFormat.charAt(i);
+
+            if (c == QUOTE) {
+                count = skipQuotedText(inFormat, i, length);
+            } else if (c == SECONDS) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private static int skipQuotedText(CharSequence s, int i, int len) {
+        if (i + 1 < len && s.charAt(i + 1) == QUOTE) {
+            return 2;
+        }
+
+        int count = 1;
+        // skip leading quote
+        i++;
+
+        while (i < len) {
+            char c = s.charAt(i);
+
+            if (c == QUOTE) {
+                count++;
+                //  QUOTEQUOTE -> QUOTE
+                if (i + 1 < len && s.charAt(i + 1) == QUOTE) {
+                    i++;
+                } else {
+                    break;
+                }
+            } else {
+                i++;
+                count++;
+            }
+        }
+
+        return count;
+    }
+
+    /**
      * Given a format string and a {@link java.util.Calendar} object, returns a CharSequence 
      * containing the requested date.
      * @param inFormat the format string, as described in {@link android.text.format.DateFormat}
      * @param inDate the date to format
      * @return a {@link CharSequence} containing the requested text
      */
-    public static final CharSequence format(CharSequence inFormat, Calendar inDate) {
+    public static CharSequence format(CharSequence inFormat, Calendar inDate) {
         SpannableStringBuilder      s = new SpannableStringBuilder(inFormat);
         int             c;
         int             count;
@@ -494,9 +574,10 @@
                     break;
                     
                 case MONTH:
-                    replacement = getMonthString(inDate, count);
+                case STANDALONE_MONTH:
+                    replacement = getMonthString(inDate, count, c);
                     break;
-                    
+
                 case SECONDS:
                     replacement = zeroPad(inDate.get(Calendar.SECOND), count);
                     break;
@@ -527,20 +608,25 @@
             return s.toString();
     }
     
-    private static final String getMonthString(Calendar inDate, int count) {
+    private static String getMonthString(Calendar inDate, int count, int kind) {
+        boolean standalone = (kind == STANDALONE_MONTH);
         int month = inDate.get(Calendar.MONTH);
         
-        if (count >= 4)
-            return DateUtils.getMonthString(month, DateUtils.LENGTH_LONG);
-        else if (count == 3)
-            return DateUtils.getMonthString(month, DateUtils.LENGTH_MEDIUM);
-        else {
+        if (count >= 4) {
+            return standalone
+                ? DateUtils.getStandaloneMonthString(month, DateUtils.LENGTH_LONG)
+                : DateUtils.getMonthString(month, DateUtils.LENGTH_LONG);
+        } else if (count == 3) {
+            return standalone
+                ? DateUtils.getStandaloneMonthString(month, DateUtils.LENGTH_MEDIUM)
+                : DateUtils.getMonthString(month, DateUtils.LENGTH_MEDIUM);
+        } else {
             // Calendar.JANUARY == 0, so add 1 to month.
             return zeroPad(month+1, count);
         }
     }
         
-    private static final String getTimeZoneString(Calendar inDate, int count) {
+    private static String getTimeZoneString(Calendar inDate, int count) {
         TimeZone tz = inDate.getTimeZone();
         
         if (count < 2) { // FIXME: shouldn't this be <= 2 ?
@@ -553,7 +639,7 @@
         }
     }
 
-    private static final String formatZoneOffset(int offset, int count) {
+    private static String formatZoneOffset(int offset, int count) {
         offset /= 1000; // milliseconds to seconds
         StringBuilder tb = new StringBuilder();
 
@@ -572,12 +658,13 @@
         return tb.toString();
     }
     
-    private static final String getYearString(Calendar inDate, int count) {
+    private static String getYearString(Calendar inDate, int count) {
         int year = inDate.get(Calendar.YEAR);
-        return (count <= 2) ? zeroPad(year % 100, 2) : String.valueOf(year);
+        return (count <= 2) ? zeroPad(year % 100, 2)
+                            : String.format(Locale.getDefault(), "%d", year);
     }
    
-    private static final int appendQuotedText(SpannableStringBuilder s, int i, int len) {
+    private static int appendQuotedText(SpannableStringBuilder s, int i, int len) {
         if (i + 1 < len && s.charAt(i + 1) == QUOTE) {
             s.delete(i, i + 1);
             return 1;
@@ -614,18 +701,7 @@
         return count;
     }
 
-    private static final String zeroPad(int inValue, int inMinDigits) {
-        String val = String.valueOf(inValue);
-
-        if (val.length() < inMinDigits) {
-            char[] buf = new char[inMinDigits];
-
-            for (int i = 0; i < inMinDigits; i++)
-                buf[i] = '0';
-
-            val.getChars(0, val.length(), buf, inMinDigits - val.length());
-            val = new String(buf);
-        }
-        return val;
+    private static String zeroPad(int inValue, int inMinDigits) {
+        return String.format(Locale.getDefault(), "%0" + inMinDigits + "d", inValue);
     }
 }
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index 2e962a0..1060bd8 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -29,6 +29,8 @@
 import java.util.Locale;
 import java.util.TimeZone;
 
+import libcore.icu.LocaleData;
+
 /**
  * This class contains various date-related utilities for creating text for things like
  * elapsed time and date ranges, strings for days of the week and months, and AM/PM text etc.
@@ -36,102 +38,6 @@
 public class DateUtils
 {
     private static final Object sLock = new Object();
-    private static final int[] sDaysLong = new int[] {
-            com.android.internal.R.string.day_of_week_long_sunday,
-            com.android.internal.R.string.day_of_week_long_monday,
-            com.android.internal.R.string.day_of_week_long_tuesday,
-            com.android.internal.R.string.day_of_week_long_wednesday,
-            com.android.internal.R.string.day_of_week_long_thursday,
-            com.android.internal.R.string.day_of_week_long_friday,
-            com.android.internal.R.string.day_of_week_long_saturday,
-        };
-    private static final int[] sDaysMedium = new int[] {
-            com.android.internal.R.string.day_of_week_medium_sunday,
-            com.android.internal.R.string.day_of_week_medium_monday,
-            com.android.internal.R.string.day_of_week_medium_tuesday,
-            com.android.internal.R.string.day_of_week_medium_wednesday,
-            com.android.internal.R.string.day_of_week_medium_thursday,
-            com.android.internal.R.string.day_of_week_medium_friday,
-            com.android.internal.R.string.day_of_week_medium_saturday,
-        };
-    private static final int[] sDaysShort = new int[] {
-            com.android.internal.R.string.day_of_week_short_sunday,
-            com.android.internal.R.string.day_of_week_short_monday,
-            com.android.internal.R.string.day_of_week_short_tuesday,
-            com.android.internal.R.string.day_of_week_short_wednesday,
-            com.android.internal.R.string.day_of_week_short_thursday,
-            com.android.internal.R.string.day_of_week_short_friday,
-            com.android.internal.R.string.day_of_week_short_saturday,
-        };
-    private static final int[] sDaysShortest = new int[] {
-            com.android.internal.R.string.day_of_week_shortest_sunday,
-            com.android.internal.R.string.day_of_week_shortest_monday,
-            com.android.internal.R.string.day_of_week_shortest_tuesday,
-            com.android.internal.R.string.day_of_week_shortest_wednesday,
-            com.android.internal.R.string.day_of_week_shortest_thursday,
-            com.android.internal.R.string.day_of_week_shortest_friday,
-            com.android.internal.R.string.day_of_week_shortest_saturday,
-        };
-    private static final int[] sMonthsStandaloneLong = new int [] {
-            com.android.internal.R.string.month_long_standalone_january,
-            com.android.internal.R.string.month_long_standalone_february,
-            com.android.internal.R.string.month_long_standalone_march,
-            com.android.internal.R.string.month_long_standalone_april,
-            com.android.internal.R.string.month_long_standalone_may,
-            com.android.internal.R.string.month_long_standalone_june,
-            com.android.internal.R.string.month_long_standalone_july,
-            com.android.internal.R.string.month_long_standalone_august,
-            com.android.internal.R.string.month_long_standalone_september,
-            com.android.internal.R.string.month_long_standalone_october,
-            com.android.internal.R.string.month_long_standalone_november,
-            com.android.internal.R.string.month_long_standalone_december,
-        };
-    private static final int[] sMonthsLong = new int [] {
-            com.android.internal.R.string.month_long_january,
-            com.android.internal.R.string.month_long_february,
-            com.android.internal.R.string.month_long_march,
-            com.android.internal.R.string.month_long_april,
-            com.android.internal.R.string.month_long_may,
-            com.android.internal.R.string.month_long_june,
-            com.android.internal.R.string.month_long_july,
-            com.android.internal.R.string.month_long_august,
-            com.android.internal.R.string.month_long_september,
-            com.android.internal.R.string.month_long_october,
-            com.android.internal.R.string.month_long_november,
-            com.android.internal.R.string.month_long_december,
-        };
-    private static final int[] sMonthsMedium = new int [] {
-            com.android.internal.R.string.month_medium_january,
-            com.android.internal.R.string.month_medium_february,
-            com.android.internal.R.string.month_medium_march,
-            com.android.internal.R.string.month_medium_april,
-            com.android.internal.R.string.month_medium_may,
-            com.android.internal.R.string.month_medium_june,
-            com.android.internal.R.string.month_medium_july,
-            com.android.internal.R.string.month_medium_august,
-            com.android.internal.R.string.month_medium_september,
-            com.android.internal.R.string.month_medium_october,
-            com.android.internal.R.string.month_medium_november,
-            com.android.internal.R.string.month_medium_december,
-        };
-    private static final int[] sMonthsShortest = new int [] {
-            com.android.internal.R.string.month_shortest_january,
-            com.android.internal.R.string.month_shortest_february,
-            com.android.internal.R.string.month_shortest_march,
-            com.android.internal.R.string.month_shortest_april,
-            com.android.internal.R.string.month_shortest_may,
-            com.android.internal.R.string.month_shortest_june,
-            com.android.internal.R.string.month_shortest_july,
-            com.android.internal.R.string.month_shortest_august,
-            com.android.internal.R.string.month_shortest_september,
-            com.android.internal.R.string.month_shortest_october,
-            com.android.internal.R.string.month_shortest_november,
-            com.android.internal.R.string.month_shortest_december,
-        };
-    private static final int[] sAmPm = new int[] {
-            com.android.internal.R.string.am,
-            com.android.internal.R.string.pm,
-        };
     private static Configuration sLastConfig;
     private static java.text.DateFormat sStatusTimeFormat;
     private static String sElapsedFormatMMSS;
@@ -139,7 +45,6 @@
 
     private static final String FAST_FORMAT_HMMSS = "%1$d:%2$02d:%3$02d";
     private static final String FAST_FORMAT_MMSS = "%1$02d:%2$02d";
-    private static final char TIME_PADDING = '0';
     private static final char TIME_SEPARATOR = ':';
 
 
@@ -336,18 +241,17 @@
      */
     @Deprecated
     public static String getDayOfWeekString(int dayOfWeek, int abbrev) {
-        int[] list;
+        LocaleData d = LocaleData.get(Locale.getDefault());
+        String[] names;
         switch (abbrev) {
-            case LENGTH_LONG:       list = sDaysLong;       break;
-            case LENGTH_MEDIUM:     list = sDaysMedium;     break;
-            case LENGTH_SHORT:      list = sDaysShort;      break;
-            case LENGTH_SHORTER:    list = sDaysShort;      break;
-            case LENGTH_SHORTEST:   list = sDaysShortest;   break;
-            default:                list = sDaysMedium;     break;
+            case LENGTH_LONG:       names = d.longWeekdayNames;  break;
+            case LENGTH_MEDIUM:     names = d.shortWeekdayNames; break;
+            case LENGTH_SHORT:      names = d.shortWeekdayNames; break; // TODO
+            case LENGTH_SHORTER:    names = d.shortWeekdayNames; break; // TODO
+            case LENGTH_SHORTEST:   names = d.tinyWeekdayNames;  break;
+            default:                names = d.shortWeekdayNames; break;
         }
-
-        Resources r = Resources.getSystem();
-        return r.getString(list[dayOfWeek - Calendar.SUNDAY]);
+        return names[dayOfWeek];
     }
 
     /**
@@ -359,8 +263,7 @@
      */
     @Deprecated
     public static String getAMPMString(int ampm) {
-        Resources r = Resources.getSystem();
-        return r.getString(sAmPm[ampm - Calendar.AM]);
+        return LocaleData.get(Locale.getDefault()).amPm[ampm - Calendar.AM];
     }
 
     /**
@@ -376,22 +279,21 @@
      */
     @Deprecated
     public static String getMonthString(int month, int abbrev) {
-        // Note that here we use sMonthsMedium for MEDIUM, SHORT and SHORTER.
+        // Note that here we use d.shortMonthNames for MEDIUM, SHORT and SHORTER.
         // This is a shortcut to not spam the translators with too many variations
         // of the same string.  If we find that in a language the distinction
         // is necessary, we can can add more without changing this API.
-        int[] list;
+        LocaleData d = LocaleData.get(Locale.getDefault());
+        String[] names;
         switch (abbrev) {
-            case LENGTH_LONG:       list = sMonthsLong;     break;
-            case LENGTH_MEDIUM:     list = sMonthsMedium;   break;
-            case LENGTH_SHORT:      list = sMonthsMedium;   break;
-            case LENGTH_SHORTER:    list = sMonthsMedium;   break;
-            case LENGTH_SHORTEST:   list = sMonthsShortest; break;
-            default:                list = sMonthsMedium;   break;
+            case LENGTH_LONG:       names = d.longMonthNames;  break;
+            case LENGTH_MEDIUM:     names = d.shortMonthNames; break;
+            case LENGTH_SHORT:      names = d.shortMonthNames; break;
+            case LENGTH_SHORTER:    names = d.shortMonthNames; break;
+            case LENGTH_SHORTEST:   names = d.tinyMonthNames;  break;
+            default:                names = d.shortMonthNames; break;
         }
-
-        Resources r = Resources.getSystem();
-        return r.getString(list[month - Calendar.JANUARY]);
+        return names[month];
     }
 
     /**
@@ -411,23 +313,22 @@
      */
     @Deprecated
     public static String getStandaloneMonthString(int month, int abbrev) {
-        // Note that here we use sMonthsMedium for MEDIUM, SHORT and SHORTER.
+        // Note that here we use d.shortMonthNames for MEDIUM, SHORT and SHORTER.
         // This is a shortcut to not spam the translators with too many variations
         // of the same string.  If we find that in a language the distinction
         // is necessary, we can can add more without changing this API.
-        int[] list;
+        LocaleData d = LocaleData.get(Locale.getDefault());
+        String[] names;
         switch (abbrev) {
-            case LENGTH_LONG:       list = sMonthsStandaloneLong;
+            case LENGTH_LONG:       names = d.longStandAloneMonthNames;
                                                             break;
-            case LENGTH_MEDIUM:     list = sMonthsMedium;   break;
-            case LENGTH_SHORT:      list = sMonthsMedium;   break;
-            case LENGTH_SHORTER:    list = sMonthsMedium;   break;
-            case LENGTH_SHORTEST:   list = sMonthsShortest; break;
-            default:                list = sMonthsMedium;   break;
+            case LENGTH_MEDIUM:     names = d.shortMonthNames; break;
+            case LENGTH_SHORT:      names = d.shortMonthNames; break;
+            case LENGTH_SHORTER:    names = d.shortMonthNames; break;
+            case LENGTH_SHORTEST:   names = d.tinyMonthNames;  break;
+            default:                names = d.shortMonthNames; break;
         }
-
-        Resources r = Resources.getSystem();
-        return r.getString(list[month - Calendar.JANUARY]);
+        return names[month];
     }
 
     /**
@@ -650,14 +551,19 @@
         int days = Math.abs(currentDay - startDay);
         boolean past = (today > day);
 
+        // TODO: some locales name other days too, such as de_DE's "Vorgestern" (today - 2).
+        Locale locale = r.getConfiguration().locale;
+        if (locale == null) {
+            locale = Locale.getDefault();
+        }
         if (days == 1) {
             if (past) {
-                return r.getString(com.android.internal.R.string.yesterday);
+                return LocaleData.get(locale).yesterday;
             } else {
-                return r.getString(com.android.internal.R.string.tomorrow);
+                return LocaleData.get(locale).tomorrow;
             }
         } else if (days == 0) {
-            return r.getString(com.android.internal.R.string.today);
+            return LocaleData.get(locale).today;
         }
 
         int resId;
@@ -741,33 +647,36 @@
         }
     }
 
+    private static void append(StringBuilder sb, long value, boolean pad, char zeroDigit) {
+        if (value < 10) {
+            if (pad) {
+                sb.append(zeroDigit);
+            }
+        } else {
+            sb.append((char) (zeroDigit + (value / 10)));
+        }
+        sb.append((char) (zeroDigit + (value % 10)));
+    }
+
     /**
-     * Fast formatting of h:mm:ss
+     * Fast formatting of h:mm:ss.
      */
     private static String formatElapsedTime(StringBuilder recycle, String format, long hours,
             long minutes, long seconds) {
         if (FAST_FORMAT_HMMSS.equals(format)) {
+            char zeroDigit = LocaleData.get(Locale.getDefault()).zeroDigit;
+
             StringBuilder sb = recycle;
             if (sb == null) {
                 sb = new StringBuilder(8);
             } else {
                 sb.setLength(0);
             }
-            sb.append(hours);
+            append(sb, hours, false, zeroDigit);
             sb.append(TIME_SEPARATOR);
-            if (minutes < 10) {
-                sb.append(TIME_PADDING);
-            } else {
-                sb.append(toDigitChar(minutes / 10));
-            }
-            sb.append(toDigitChar(minutes % 10));
+            append(sb, minutes, true, zeroDigit);
             sb.append(TIME_SEPARATOR);
-            if (seconds < 10) {
-                sb.append(TIME_PADDING);
-            } else {
-                sb.append(toDigitChar(seconds / 10));
-            }
-            sb.append(toDigitChar(seconds % 10));
+            append(sb, seconds, true, zeroDigit);
             return sb.toString();
         } else {
             return String.format(format, hours, minutes, seconds);
@@ -775,40 +684,28 @@
     }
 
     /**
-     * Fast formatting of m:ss
+     * Fast formatting of mm:ss.
      */
     private static String formatElapsedTime(StringBuilder recycle, String format, long minutes,
             long seconds) {
         if (FAST_FORMAT_MMSS.equals(format)) {
+            char zeroDigit = LocaleData.get(Locale.getDefault()).zeroDigit;
+
             StringBuilder sb = recycle;
             if (sb == null) {
                 sb = new StringBuilder(8);
             } else {
                 sb.setLength(0);
             }
-            if (minutes < 10) {
-                sb.append(TIME_PADDING);
-            } else {
-                sb.append(toDigitChar(minutes / 10));
-            }
-            sb.append(toDigitChar(minutes % 10));
+            append(sb, minutes, false, zeroDigit);
             sb.append(TIME_SEPARATOR);
-            if (seconds < 10) {
-                sb.append(TIME_PADDING);
-            } else {
-                sb.append(toDigitChar(seconds / 10));
-            }
-            sb.append(toDigitChar(seconds % 10));
+            append(sb, seconds, true, zeroDigit);
             return sb.toString();
         } else {
             return String.format(format, minutes, seconds);
         }
     }
 
-    private static char toDigitChar(long digit) {
-        return (char) (digit + '0');
-    }
-
     /**
      * Format a date / time such that if the then is on the same day as now, it shows
      * just the time and if it's a different day, it shows just the date.
@@ -1480,6 +1377,14 @@
         String endMonthDayString = isInstant ? null : endDate.format(MONTH_DAY_FORMAT);
         String endYearString = isInstant ? null : endDate.format(YEAR_FORMAT);
 
+        String startStandaloneMonthString = startMonthString;
+        String endStandaloneMonthString = endMonthString;
+        // We need standalone months for these strings in Persian (fa): http://b/6811327
+        if (!numericDate && !abbrevMonth && Locale.getDefault().getLanguage().equals("fa")) {
+            startStandaloneMonthString = startDate.format("%-B");
+            endStandaloneMonthString = endDate.format("%-B");
+        }
+
         if (startMonthNum != endMonthNum) {
             // Same year, different month.
             // Example: "October 28 - November 3"
@@ -1500,7 +1405,8 @@
                     startWeekDayString, startMonthString, startMonthDayString,
                     startYearString, startTimeString,
                     endWeekDayString, endMonthString, endMonthDayString,
-                    endYearString, endTimeString);
+                    endYearString, endTimeString,
+                    startStandaloneMonthString, endStandaloneMonthString);
         }
 
         if (startDay != endDay) {
@@ -1519,7 +1425,8 @@
                     startWeekDayString, startMonthString, startMonthDayString,
                     startYearString, startTimeString,
                     endWeekDayString, endMonthString, endMonthDayString,
-                    endYearString, endTimeString);
+                    endYearString, endTimeString,
+                    startStandaloneMonthString, endStandaloneMonthString);
         }
 
         // Same start and end day
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index e9b0d32..5ef86b1 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -21,6 +21,8 @@
 import java.util.Locale;
 import java.util.TimeZone;
 
+import libcore.icu.LocaleData;
+
 /**
  * An alternative to the {@link java.util.Calendar} and
  * {@link java.util.GregorianCalendar} classes. An instance of the Time class represents
@@ -149,6 +151,9 @@
     private static String sDateTimeFormat;
     private static String sAm;
     private static String sPm;
+    private static char sZeroDigit;
+
+    // Referenced by native code.
     private static String sDateCommand = "%a %b %e %H:%M:%S %Z %Y";
 
     /**
@@ -317,83 +322,52 @@
             Locale locale = Locale.getDefault();
 
             if (sLocale == null || locale == null || !(locale.equals(sLocale))) {
-                Resources r = Resources.getSystem();
+                LocaleData localeData = LocaleData.get(locale);
 
-                sShortMonths = new String[] {
-                    r.getString(com.android.internal.R.string.month_medium_january),
-                    r.getString(com.android.internal.R.string.month_medium_february),
-                    r.getString(com.android.internal.R.string.month_medium_march),
-                    r.getString(com.android.internal.R.string.month_medium_april),
-                    r.getString(com.android.internal.R.string.month_medium_may),
-                    r.getString(com.android.internal.R.string.month_medium_june),
-                    r.getString(com.android.internal.R.string.month_medium_july),
-                    r.getString(com.android.internal.R.string.month_medium_august),
-                    r.getString(com.android.internal.R.string.month_medium_september),
-                    r.getString(com.android.internal.R.string.month_medium_october),
-                    r.getString(com.android.internal.R.string.month_medium_november),
-                    r.getString(com.android.internal.R.string.month_medium_december),
-                };
-                sLongMonths = new String[] {
-                    r.getString(com.android.internal.R.string.month_long_january),
-                    r.getString(com.android.internal.R.string.month_long_february),
-                    r.getString(com.android.internal.R.string.month_long_march),
-                    r.getString(com.android.internal.R.string.month_long_april),
-                    r.getString(com.android.internal.R.string.month_long_may),
-                    r.getString(com.android.internal.R.string.month_long_june),
-                    r.getString(com.android.internal.R.string.month_long_july),
-                    r.getString(com.android.internal.R.string.month_long_august),
-                    r.getString(com.android.internal.R.string.month_long_september),
-                    r.getString(com.android.internal.R.string.month_long_october),
-                    r.getString(com.android.internal.R.string.month_long_november),
-                    r.getString(com.android.internal.R.string.month_long_december),
-                };
-                sLongStandaloneMonths = new String[] {
-                    r.getString(com.android.internal.R.string.month_long_standalone_january),
-                    r.getString(com.android.internal.R.string.month_long_standalone_february),
-                    r.getString(com.android.internal.R.string.month_long_standalone_march),
-                    r.getString(com.android.internal.R.string.month_long_standalone_april),
-                    r.getString(com.android.internal.R.string.month_long_standalone_may),
-                    r.getString(com.android.internal.R.string.month_long_standalone_june),
-                    r.getString(com.android.internal.R.string.month_long_standalone_july),
-                    r.getString(com.android.internal.R.string.month_long_standalone_august),
-                    r.getString(com.android.internal.R.string.month_long_standalone_september),
-                    r.getString(com.android.internal.R.string.month_long_standalone_october),
-                    r.getString(com.android.internal.R.string.month_long_standalone_november),
-                    r.getString(com.android.internal.R.string.month_long_standalone_december),
-                };
-                sShortWeekdays = new String[] {
-                    r.getString(com.android.internal.R.string.day_of_week_medium_sunday),
-                    r.getString(com.android.internal.R.string.day_of_week_medium_monday),
-                    r.getString(com.android.internal.R.string.day_of_week_medium_tuesday),
-                    r.getString(com.android.internal.R.string.day_of_week_medium_wednesday),
-                    r.getString(com.android.internal.R.string.day_of_week_medium_thursday),
-                    r.getString(com.android.internal.R.string.day_of_week_medium_friday),
-                    r.getString(com.android.internal.R.string.day_of_week_medium_saturday),
-                };
-                sLongWeekdays = new String[] {
-                    r.getString(com.android.internal.R.string.day_of_week_long_sunday),
-                    r.getString(com.android.internal.R.string.day_of_week_long_monday),
-                    r.getString(com.android.internal.R.string.day_of_week_long_tuesday),
-                    r.getString(com.android.internal.R.string.day_of_week_long_wednesday),
-                    r.getString(com.android.internal.R.string.day_of_week_long_thursday),
-                    r.getString(com.android.internal.R.string.day_of_week_long_friday),
-                    r.getString(com.android.internal.R.string.day_of_week_long_saturday),
-                };
+                sAm = localeData.amPm[0];
+                sPm = localeData.amPm[1];
+                sZeroDigit = localeData.zeroDigit;
+
+                sShortMonths = localeData.shortMonthNames;
+                sLongMonths = localeData.longMonthNames;
+                sLongStandaloneMonths = localeData.longStandAloneMonthNames;
+                sShortWeekdays = localeData.shortWeekdayNames;
+                sLongWeekdays = localeData.longWeekdayNames;
+
+                Resources r = Resources.getSystem();
                 sTimeOnlyFormat = r.getString(com.android.internal.R.string.time_of_day);
                 sDateOnlyFormat = r.getString(com.android.internal.R.string.month_day_year);
                 sDateTimeFormat = r.getString(com.android.internal.R.string.date_and_time);
-                sAm = r.getString(com.android.internal.R.string.am);
-                sPm = r.getString(com.android.internal.R.string.pm);
 
                 sLocale = locale;
             }
 
-            return format1(format);
+            String result = format1(format);
+            if (sZeroDigit != '0') {
+                result = localizeDigits(result);
+            }
+            return result;
         }
     }
 
     native private String format1(String format);
 
+    // TODO: unify this with java.util.Formatter's copy.
+    private String localizeDigits(String s) {
+        int length = s.length();
+        int offsetToLocalizedDigits = sZeroDigit - '0';
+        StringBuilder result = new StringBuilder(length);
+        for (int i = 0; i < length; ++i) {
+            char ch = s.charAt(i);
+            if (ch >= '0' && ch <= '9') {
+                ch += offsetToLocalizedDigits;
+            }
+            result.append(ch);
+        }
+        return result.toString();
+    }
+
+
     /**
      * Return the current time in YYYYMMDDTHHMMSS<tz> format
      */
@@ -437,6 +411,9 @@
      * @throws android.util.TimeFormatException if s cannot be parsed.
      */
     public boolean parse(String s) {
+        if (s == null) {
+            throw new NullPointerException("time string is null");
+        }
         if (nativeParse(s)) {
             timezone = TIMEZONE_UTC;
             return true;
@@ -720,7 +697,7 @@
             int minutes = (offset % 3600) / 60;
             int hours = offset / 3600;
 
-            return String.format("%s%s%02d:%02d", base, sign, hours, minutes);
+            return String.format(Locale.US, "%s%s%02d:%02d", base, sign, hours, minutes);
         }
     }
 
diff --git a/core/java/android/text/style/LocaleSpan.java b/core/java/android/text/style/LocaleSpan.java
new file mode 100644
index 0000000..a12c42f
--- /dev/null
+++ b/core/java/android/text/style/LocaleSpan.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.style;
+
+import android.graphics.Paint;
+import android.os.Parcel;
+import android.text.ParcelableSpan;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import java.util.Locale;
+
+/**
+ * Changes the {@link Locale} of the text to which the span is attached.
+ */
+public class LocaleSpan extends MetricAffectingSpan implements ParcelableSpan {
+    private final Locale mLocale;
+
+    /**
+     * Creates a LocaleSpan.
+     * @param locale The {@link Locale} of the text to which the span is
+     * attached.
+     */
+    public LocaleSpan(Locale locale) {
+        mLocale = locale;
+    }
+
+    public LocaleSpan(Parcel src) {
+        mLocale = new Locale(src.readString(), src.readString(), src.readString());
+    }
+
+    @Override
+    public int getSpanTypeId() {
+        return TextUtils.LOCALE_SPAN;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mLocale.getLanguage());
+        dest.writeString(mLocale.getCountry());
+        dest.writeString(mLocale.getVariant());
+    }
+
+    /**
+     * Returns the {@link Locale}.
+     *
+     * @return The {@link Locale} for this span.
+     */
+    public Locale getLocale() {
+        return mLocale;
+    }
+
+    @Override
+    public void updateDrawState(TextPaint ds) {
+        apply(ds, mLocale);
+    }
+
+    @Override
+    public void updateMeasureState(TextPaint paint) {
+        apply(paint, mLocale);
+    }
+
+    private static void apply(Paint paint, Locale locale) {
+        paint.setTextLocale(locale);
+    }
+}
diff --git a/core/java/android/util/AtomicFile.java b/core/java/android/util/AtomicFile.java
new file mode 100644
index 0000000..4fca570
--- /dev/null
+++ b/core/java/android/util/AtomicFile.java
@@ -0,0 +1,233 @@
+/*
+ * 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.
+ */
+
+package android.util;
+
+import android.os.FileUtils;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * Helper class for performing atomic operations on a file by creating a
+ * backup file until a write has successfully completed.  If you need this
+ * on older versions of the platform you can use
+ * {@link android.support.v4.util.AtomicFile} in the v4 support library.
+ * <p>
+ * Atomic file guarantees file integrity by ensuring that a file has
+ * been completely written and sync'd to disk before removing its backup.
+ * As long as the backup file exists, the original file is considered
+ * to be invalid (left over from a previous attempt to write the file).
+ * </p><p>
+ * Atomic file does not confer any file locking semantics.
+ * Do not use this class when the file may be accessed or modified concurrently
+ * by multiple threads or processes.  The caller is responsible for ensuring
+ * appropriate mutual exclusion invariants whenever it accesses the file.
+ * </p>
+ */
+public class AtomicFile {
+    private final File mBaseName;
+    private final File mBackupName;
+
+    /**
+     * Create a new AtomicFile for a file located at the given File path.
+     * The secondary backup file will be the same file path with ".bak" appended.
+     */
+    public AtomicFile(File baseName) {
+        mBaseName = baseName;
+        mBackupName = new File(baseName.getPath() + ".bak");
+    }
+
+    /**
+     * Return the path to the base file.  You should not generally use this,
+     * as the data at that path may not be valid.
+     */
+    public File getBaseFile() {
+        return mBaseName;
+    }
+
+    /**
+     * Delete the atomic file.  This deletes both the base and backup files.
+     */
+    public void delete() {
+        mBaseName.delete();
+        mBackupName.delete();
+    }
+
+    /**
+     * Start a new write operation on the file.  This returns a FileOutputStream
+     * to which you can write the new file data.  The existing file is replaced
+     * with the new data.  You <em>must not</em> directly close the given
+     * FileOutputStream; instead call either {@link #finishWrite(FileOutputStream)}
+     * or {@link #failWrite(FileOutputStream)}.
+     *
+     * <p>Note that if another thread is currently performing
+     * a write, this will simply replace whatever that thread is writing
+     * with the new file being written by this thread, and when the other
+     * thread finishes the write the new write operation will no longer be
+     * safe (or will be lost).  You must do your own threading protection for
+     * access to AtomicFile.
+     */
+    public FileOutputStream startWrite() throws IOException {
+        // Rename the current file so it may be used as a backup during the next read
+        if (mBaseName.exists()) {
+            if (!mBackupName.exists()) {
+                if (!mBaseName.renameTo(mBackupName)) {
+                    Log.w("AtomicFile", "Couldn't rename file " + mBaseName
+                            + " to backup file " + mBackupName);
+                }
+            } else {
+                mBaseName.delete();
+            }
+        }
+        FileOutputStream str = null;
+        try {
+            str = new FileOutputStream(mBaseName);
+        } catch (FileNotFoundException e) {
+            File parent = mBaseName.getParentFile();
+            if (!parent.mkdir()) {
+                throw new IOException("Couldn't create directory " + mBaseName);
+            }
+            FileUtils.setPermissions(
+                parent.getPath(),
+                FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
+                -1, -1);
+            try {
+                str = new FileOutputStream(mBaseName);
+            } catch (FileNotFoundException e2) {
+                throw new IOException("Couldn't create " + mBaseName);
+            }
+        }
+        return str;
+    }
+
+    /**
+     * Call when you have successfully finished writing to the stream
+     * returned by {@link #startWrite()}.  This will close, sync, and
+     * commit the new data.  The next attempt to read the atomic file
+     * will return the new file stream.
+     */
+    public void finishWrite(FileOutputStream str) {
+        if (str != null) {
+            FileUtils.sync(str);
+            try {
+                str.close();
+                mBackupName.delete();
+            } catch (IOException e) {
+                Log.w("AtomicFile", "finishWrite: Got exception:", e);
+            }
+        }
+    }
+
+    /**
+     * Call when you have failed for some reason at writing to the stream
+     * returned by {@link #startWrite()}.  This will close the current
+     * write stream, and roll back to the previous state of the file.
+     */
+    public void failWrite(FileOutputStream str) {
+        if (str != null) {
+            FileUtils.sync(str);
+            try {
+                str.close();
+                mBaseName.delete();
+                mBackupName.renameTo(mBaseName);
+            } catch (IOException e) {
+                Log.w("AtomicFile", "failWrite: Got exception:", e);
+            }
+        }
+    }
+
+    /** @hide
+     * @deprecated This is not safe.
+     */
+    @Deprecated public void truncate() throws IOException {
+        try {
+            FileOutputStream fos = new FileOutputStream(mBaseName);
+            FileUtils.sync(fos);
+            fos.close();
+        } catch (FileNotFoundException e) {
+            throw new IOException("Couldn't append " + mBaseName);
+        } catch (IOException e) {
+        }
+    }
+
+    /** @hide
+     * @deprecated This is not safe.
+     */
+    @Deprecated public FileOutputStream openAppend() throws IOException {
+        try {
+            return new FileOutputStream(mBaseName, true);
+        } catch (FileNotFoundException e) {
+            throw new IOException("Couldn't append " + mBaseName);
+        }
+    }
+
+    /**
+     * Open the atomic file for reading.  If there previously was an
+     * incomplete write, this will roll back to the last good data before
+     * opening for read.  You should call close() on the FileInputStream when
+     * you are done reading from it.
+     *
+     * <p>Note that if another thread is currently performing
+     * a write, this will incorrectly consider it to be in the state of a bad
+     * write and roll back, causing the new data currently being written to
+     * be dropped.  You must do your own threading protection for access to
+     * AtomicFile.
+     */
+    public FileInputStream openRead() throws FileNotFoundException {
+        if (mBackupName.exists()) {
+            mBaseName.delete();
+            mBackupName.renameTo(mBaseName);
+        }
+        return new FileInputStream(mBaseName);
+    }
+
+    /**
+     * A convenience for {@link #openRead()} that also reads all of the
+     * file contents into a byte array which is returned.
+     */
+    public byte[] readFully() throws IOException {
+        FileInputStream stream = openRead();
+        try {
+            int pos = 0;
+            int avail = stream.available();
+            byte[] data = new byte[avail];
+            while (true) {
+                int amt = stream.read(data, pos, data.length-pos);
+                //Log.i("foo", "Read " + amt + " bytes at " + pos
+                //        + " of avail " + data.length);
+                if (amt <= 0) {
+                    //Log.i("foo", "**** FINISHED READING: pos=" + pos
+                    //        + " len=" + data.length);
+                    return data;
+                }
+                pos += amt;
+                avail = stream.available();
+                if (avail > data.length-pos) {
+                    byte[] newData = new byte[pos+avail];
+                    System.arraycopy(data, 0, newData, 0, pos);
+                    data = newData;
+                }
+            }
+        } finally {
+            stream.close();
+        }
+    }
+}
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 80da0b2..85e4b9d 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -79,11 +79,20 @@
     public static final int DENSITY_DEFAULT = DENSITY_MEDIUM;
 
     /**
-     * The device's density.
-     * @hide becase eventually this should be able to change while
-     * running, so shouldn't be a constant.
+     * Scaling factor to convert a density in DPI units to the density scale.
+     * @hide
      */
-    public static final int DENSITY_DEVICE = getDeviceDensity();
+    public static final float DENSITY_DEFAULT_SCALE = 1.0f / DENSITY_DEFAULT;
+
+    /**
+     * The device's density.
+     * @hide because eventually this should be able to change while
+     * running, so shouldn't be a constant.
+     * @deprecated There is no longer a static density; you can find the
+     * density for a display in {@link #densityDpi}.
+     */
+    @Deprecated
+    public static int DENSITY_DEVICE = getDeviceDensity();
 
     /**
      * The absolute width of the display in pixels.
@@ -150,6 +159,12 @@
      */
     public float noncompatDensity;
     /**
+     * The reported display density prior to any compatibility mode scaling
+     * being applied.
+     * @hide
+     */
+    public int noncompatDensityDpi;
+    /**
      * The reported scaled density prior to any compatibility mode scaling
      * being applied.
      * @hide
@@ -182,6 +197,7 @@
         noncompatWidthPixels = o.noncompatWidthPixels;
         noncompatHeightPixels = o.noncompatHeightPixels;
         noncompatDensity = o.noncompatDensity;
+        noncompatDensityDpi = o.noncompatDensityDpi;
         noncompatScaledDensity = o.noncompatScaledDensity;
         noncompatXdpi = o.noncompatXdpi;
         noncompatYdpi = o.noncompatYdpi;
@@ -190,13 +206,52 @@
     public void setToDefaults() {
         widthPixels = 0;
         heightPixels = 0;
-        density = DENSITY_DEVICE / (float) DENSITY_DEFAULT;
-        densityDpi = DENSITY_DEVICE;
+        density =  DENSITY_DEVICE / (float) DENSITY_DEFAULT;
+        densityDpi =  DENSITY_DEVICE;
         scaledDensity = density;
         xdpi = DENSITY_DEVICE;
         ydpi = DENSITY_DEVICE;
-        noncompatWidthPixels = 0;
-        noncompatHeightPixels = 0;
+        noncompatWidthPixels = widthPixels;
+        noncompatHeightPixels = heightPixels;
+        noncompatDensity = density;
+        noncompatDensityDpi = densityDpi;
+        noncompatScaledDensity = scaledDensity;
+        noncompatXdpi = xdpi;
+        noncompatYdpi = ydpi;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o instanceof DisplayMetrics && equals((DisplayMetrics)o);
+    }
+
+    /**
+     * Returns true if these display metrics equal the other display metrics.
+     *
+     * @param other The display metrics with which to compare.
+     * @return True if the display metrics are equal.
+     */
+    public boolean equals(DisplayMetrics other) {
+        return other != null
+                && widthPixels == other.widthPixels
+                && heightPixels == other.heightPixels
+                && density == other.density
+                && densityDpi == other.densityDpi
+                && scaledDensity == other.scaledDensity
+                && xdpi == other.xdpi
+                && ydpi == other.ydpi
+                && noncompatWidthPixels == other.noncompatWidthPixels
+                && noncompatHeightPixels == other.noncompatHeightPixels
+                && noncompatDensity == other.noncompatDensity
+                && noncompatDensityDpi == other.noncompatDensityDpi
+                && noncompatScaledDensity == other.noncompatScaledDensity
+                && noncompatXdpi == other.noncompatXdpi
+                && noncompatYdpi == other.noncompatYdpi;
+    }
+
+    @Override
+    public int hashCode() {
+        return widthPixels * heightPixels * densityDpi;
     }
 
     @Override
diff --git a/core/java/android/util/FloatMath.java b/core/java/android/util/FloatMath.java
index 6216638..9556223 100644
--- a/core/java/android/util/FloatMath.java
+++ b/core/java/android/util/FloatMath.java
@@ -71,4 +71,33 @@
      * @return the square root of value
      */
     public static native float sqrt(float value);
+
+    /**
+     * Returns the closest float approximation of the raising "e" to the power
+     * of the argument.
+     *
+     * @param value to compute the exponential of
+     * @return the exponential of value
+     */
+    public static native float exp(float value);
+
+    /**
+     * Returns the closest float approximation of the result of raising {@code
+     * x} to the power of {@code y}.
+     *
+     * @param x the base of the operation.
+     * @param y the exponent of the operation.
+     * @return {@code x} to the power of {@code y}.
+     */
+    public static native float pow(float x, float y);
+
+    /**
+     * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +} <i>
+     * {@code y}</i><sup>{@code 2}</sup>{@code )}.
+     *
+     * @param x a float number
+     * @param y a float number
+     * @return the hypotenuse
+     */
+    public static native float hypot(float x, float y);
 }
diff --git a/core/java/android/util/LocaleUtil.java b/core/java/android/util/LocaleUtil.java
deleted file mode 100644
index 93f5cd3..0000000
--- a/core/java/android/util/LocaleUtil.java
+++ /dev/null
@@ -1,85 +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.
- */
-
-package android.util;
-
-import java.util.Locale;
-
-import android.view.View;
-import libcore.icu.ICU;
-
-/**
- * Various utilities for Locales
- *
- * @hide
- */
-public class LocaleUtil {
-
-    private LocaleUtil() { /* cannot be instantiated */ }
-
-    private static String ARAB_SCRIPT_SUBTAG = "Arab";
-    private static String HEBR_SCRIPT_SUBTAG = "Hebr";
-
-    /**
-     * Return the layout direction for a given Locale
-     *
-     * @param locale the Locale for which we want the layout direction. Can be null.
-     * @return the layout direction. This may be one of:
-     * {@link View#LAYOUT_DIRECTION_LTR} or
-     * {@link View#LAYOUT_DIRECTION_RTL}.
-     *
-     * Warning: this code does not support vertical scripts.
-     * @hide
-     */
-    public static int getLayoutDirectionFromLocale(Locale locale) {
-        if (locale != null && !locale.equals(Locale.ROOT)) {
-            final String scriptSubtag = ICU.getScript(ICU.addLikelySubtags(locale.toString()));
-            if (scriptSubtag == null) return getLayoutDirectionFromFirstChar(locale);
-
-            if (scriptSubtag.equalsIgnoreCase(ARAB_SCRIPT_SUBTAG) ||
-                    scriptSubtag.equalsIgnoreCase(HEBR_SCRIPT_SUBTAG)) {
-                return View.LAYOUT_DIRECTION_RTL;
-            }
-        }
-
-        return View.LAYOUT_DIRECTION_LTR;
-    }
-
-    /**
-     * Fallback algorithm to detect the locale direction. Rely on the fist char of the
-     * localized locale name. This will not work if the localized locale name is in English
-     * (this is the case for ICU 4.4 and "Urdu" script)
-     *
-     * @param locale
-     * @return the layout direction. This may be one of:
-     * {@link View#LAYOUT_DIRECTION_LTR} or
-     * {@link View#LAYOUT_DIRECTION_RTL}.
-     *
-     * Warning: this code does not support vertical scripts.
-     * @hide
-     */
-    private static int getLayoutDirectionFromFirstChar(Locale locale) {
-        switch(Character.getDirectionality(locale.getDisplayName(locale).charAt(0))) {
-            case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
-            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
-                return View.LAYOUT_DIRECTION_RTL;
-
-            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
-            default:
-                return View.LAYOUT_DIRECTION_LTR;
-        }
-    }
-}
diff --git a/core/java/android/util/LruCache.java b/core/java/android/util/LruCache.java
index 51e373c..dd504c1 100644
--- a/core/java/android/util/LruCache.java
+++ b/core/java/android/util/LruCache.java
@@ -186,10 +186,13 @@
     }
 
     /**
+     * Remove the eldest entries until the total of remaining entries is at or
+     * below the requested size.
+     *
      * @param maxSize the maximum size of the cache before returning. May be -1
-     *     to evict even 0-sized elements.
+     *            to evict even 0-sized elements.
      */
-    private void trimToSize(int maxSize) {
+    public void trimToSize(int maxSize) {
         while (true) {
             K key;
             V value;
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index 2179ff3..602a68c 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -59,10 +59,10 @@
             final long defaultTimeout = res.getInteger(
                     com.android.internal.R.integer.config_ntpTimeout);
 
-            final String secureServer = Settings.Secure.getString(
-                    resolver, Settings.Secure.NTP_SERVER);
-            final long timeout = Settings.Secure.getLong(
-                    resolver, Settings.Secure.NTP_TIMEOUT, defaultTimeout);
+            final String secureServer = Settings.Global.getString(
+                    resolver, Settings.Global.NTP_SERVER);
+            final long timeout = Settings.Global.getLong(
+                    resolver, Settings.Global.NTP_TIMEOUT, defaultTimeout);
 
             final String server = secureServer != null ? secureServer : defaultServer;
             sSingleton = new NtpTrustedTime(server, timeout);
@@ -71,7 +71,7 @@
         return sSingleton;
     }
 
-    /** {@inheritDoc} */
+    @Override
     public boolean forceRefresh() {
         if (mServer == null) {
             // missing server, so no trusted time available
@@ -91,12 +91,12 @@
         }
     }
 
-    /** {@inheritDoc} */
+    @Override
     public boolean hasCache() {
         return mHasCache;
     }
 
-    /** {@inheritDoc} */
+    @Override
     public long getCacheAge() {
         if (mHasCache) {
             return SystemClock.elapsedRealtime() - mCachedNtpElapsedRealtime;
@@ -105,7 +105,7 @@
         }
     }
 
-    /** {@inheritDoc} */
+    @Override
     public long getCacheCertainty() {
         if (mHasCache) {
             return mCachedNtpCertainty;
@@ -114,7 +114,7 @@
         }
     }
 
-    /** {@inheritDoc} */
+    @Override
     public long currentTimeMillis() {
         if (!mHasCache) {
             throw new IllegalStateException("Missing authoritative time source");
diff --git a/core/java/android/util/Pair.java b/core/java/android/util/Pair.java
index bf25306..6027d08 100644
--- a/core/java/android/util/Pair.java
+++ b/core/java/android/util/Pair.java
@@ -16,6 +16,8 @@
 
 package android.util;
 
+import libcore.util.Objects;
+
 /**
  * Container to ease passing around a tuple of two objects. This object provides a sensible
  * implementation of equals(), returning true if equals() is true on each of the contained
@@ -26,8 +28,8 @@
     public final S second;
 
     /**
-     * Constructor for a Pair. If either are null then equals() and hashCode() will throw
-     * a NullPointerException.
+     * Constructor for a Pair.
+     *
      * @param first the first object in the Pair
      * @param second the second object in the pair
      */
@@ -37,31 +39,30 @@
     }
 
     /**
-     * Checks the two objects for equality by delegating to their respective equals() methods.
-     * @param o the Pair to which this one is to be checked for equality
-     * @return true if the underlying objects of the Pair are both considered equals()
+     * Checks the two objects for equality by delegating to their respective
+     * {@link Object#equals(Object)} methods.
+     *
+     * @param o the {@link Pair} to which this one is to be checked for equality
+     * @return true if the underlying objects of the Pair are both considered
+     *         equal
      */
+    @Override
     public boolean equals(Object o) {
-        if (o == this) return true;
-        if (!(o instanceof Pair)) return false;
-        final Pair<F, S> other;
-        try {
-            other = (Pair<F, S>) o;
-        } catch (ClassCastException e) {
+        if (!(o instanceof Pair)) {
             return false;
         }
-        return first.equals(other.first) && second.equals(other.second);
+        Pair<?, ?> p = (Pair<?, ?>) o;
+        return Objects.equal(p.first, first) && Objects.equal(p.second, second);
     }
 
     /**
      * Compute a hash code using the hash codes of the underlying objects
+     *
      * @return a hashcode of the Pair
      */
+    @Override
     public int hashCode() {
-        int result = 17;
-        result = 31 * result + first.hashCode();
-        result = 31 * result + second.hashCode();
-        return result;
+        return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
     }
 
     /**
diff --git a/core/java/android/util/Spline.java b/core/java/android/util/Spline.java
new file mode 100644
index 0000000..ed027eb
--- /dev/null
+++ b/core/java/android/util/Spline.java
@@ -0,0 +1,156 @@
+/*
+ * 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.util;
+
+/**
+ * Performs spline interpolation given a set of control points.
+ * @hide
+ */
+public final class Spline {
+    private final float[] mX;
+    private final float[] mY;
+    private final float[] mM;
+
+    private Spline(float[] x, float[] y, float[] m) {
+        mX = x;
+        mY = y;
+        mM = m;
+    }
+
+    /**
+     * Creates a monotone cubic spline from a given set of control points.
+     *
+     * The spline is guaranteed to pass through each control point exactly.
+     * Moreover, assuming the control points are monotonic (Y is non-decreasing or
+     * non-increasing) then the interpolated values will also be monotonic.
+     *
+     * This function uses the Fritsch-Carlson method for computing the spline parameters.
+     * http://en.wikipedia.org/wiki/Monotone_cubic_interpolation
+     *
+     * @param x The X component of the control points, strictly increasing.
+     * @param y The Y component of the control points, monotonic.
+     * @return
+     *
+     * @throws IllegalArgumentException if the X or Y arrays are null, have
+     * different lengths or have fewer than 2 values.
+     * @throws IllegalArgumentException if the control points are not monotonic.
+     */
+    public static Spline createMonotoneCubicSpline(float[] x, float[] y) {
+        if (x == null || y == null || x.length != y.length || x.length < 2) {
+            throw new IllegalArgumentException("There must be at least two control "
+                    + "points and the arrays must be of equal length.");
+        }
+
+        final int n = x.length;
+        float[] d = new float[n - 1]; // could optimize this out
+        float[] m = new float[n];
+
+        // Compute slopes of secant lines between successive points.
+        for (int i = 0; i < n - 1; i++) {
+            float h = x[i + 1] - x[i];
+            if (h <= 0f) {
+                throw new IllegalArgumentException("The control points must all "
+                        + "have strictly increasing X values.");
+            }
+            d[i] = (y[i + 1] - y[i]) / h;
+        }
+
+        // Initialize the tangents as the average of the secants.
+        m[0] = d[0];
+        for (int i = 1; i < n - 1; i++) {
+            m[i] = (d[i - 1] + d[i]) * 0.5f;
+        }
+        m[n - 1] = d[n - 2];
+
+        // Update the tangents to preserve monotonicity.
+        for (int i = 0; i < n - 1; i++) {
+            if (d[i] == 0f) { // successive Y values are equal
+                m[i] = 0f;
+                m[i + 1] = 0f;
+            } else {
+                float a = m[i] / d[i];
+                float b = m[i + 1] / d[i];
+                if (a < 0f || b < 0f) {
+                    throw new IllegalArgumentException("The control points must have "
+                            + "monotonic Y values.");
+                }
+                float h = FloatMath.hypot(a, b);
+                if (h > 9f) {
+                    float t = 3f / h;
+                    m[i] = t * a * d[i];
+                    m[i + 1] = t * b * d[i];
+                }
+            }
+        }
+        return new Spline(x, y, m);
+    }
+
+    /**
+     * Interpolates the value of Y = f(X) for given X.
+     * Clamps X to the domain of the spline.
+     *
+     * @param x The X value.
+     * @return The interpolated Y = f(X) value.
+     */
+    public float interpolate(float x) {
+        // Handle the boundary cases.
+        final int n = mX.length;
+        if (Float.isNaN(x)) {
+            return x;
+        }
+        if (x <= mX[0]) {
+            return mY[0];
+        }
+        if (x >= mX[n - 1]) {
+            return mY[n - 1];
+        }
+
+        // Find the index 'i' of the last point with smaller X.
+        // We know this will be within the spline due to the boundary tests.
+        int i = 0;
+        while (x >= mX[i + 1]) {
+            i += 1;
+            if (x == mX[i]) {
+                return mY[i];
+            }
+        }
+
+        // Perform cubic Hermite spline interpolation.
+        float h = mX[i + 1] - mX[i];
+        float t = (x - mX[i]) / h;
+        return (mY[i] * (1 + 2 * t) + h * mM[i] * t) * (1 - t) * (1 - t)
+                + (mY[i + 1] * (3 - 2 * t) + h * mM[i + 1] * (t - 1)) * t * t;
+    }
+
+    // For debugging.
+    @Override
+    public String toString() {
+        StringBuilder str = new StringBuilder();
+        final int n = mX.length;
+        str.append("[");
+        for (int i = 0; i < n; i++) {
+            if (i != 0) {
+                str.append(", ");
+            }
+            str.append("(").append(mX[i]);
+            str.append(", ").append(mY[i]);
+            str.append(": ").append(mM[i]).append(")");
+        }
+        str.append("]");
+        return str.toString();
+    }
+}
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index c4ebec4..5a4f322 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -18,8 +18,11 @@
 
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
+import android.os.SystemClock;
+import android.text.format.DateUtils;
 
-import libcore.util.ZoneInfoDB;
+import com.android.internal.util.XmlUtils;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -28,10 +31,10 @@
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collection;
-import java.util.TimeZone;
 import java.util.Date;
+import java.util.TimeZone;
 
-import com.android.internal.util.XmlUtils;
+import libcore.util.ZoneInfoDB;
 
 /**
  * A class containing utility methods related to time zones.
@@ -245,6 +248,8 @@
     private static final Object sFormatSync = new Object();
     private static char[] sFormatStr = new char[HUNDRED_DAY_FIELD_LEN+5];
 
+    private static final long LARGEST_DURATION = (1000 * DateUtils.DAY_IN_MILLIS) - 1;
+
     static private int accumField(int amt, int suffix, boolean always, int zeropad) {
         if (amt > 99 || (always && zeropad >= 3)) {
             return 3+suffix;
@@ -307,6 +312,10 @@
             duration = -duration;
         }
 
+        if (duration > LARGEST_DURATION) {
+            duration = LARGEST_DURATION;
+        }
+
         int millis = (int)(duration%1000);
         int seconds = (int) Math.floor(duration / 1000);
         int days = 0, hours = 0, minutes = 0;
@@ -383,6 +392,18 @@
         formatDuration(time-now, pw, 0);
     }
 
+    /** @hide Just for debugging; not internationalized. */
+    public static String formatUptime(long time) {
+        final long diff = time - SystemClock.uptimeMillis();
+        if (diff > 0) {
+            return time + " (in " + diff + " ms)";
+        }
+        if (diff < 0) {
+            return time + " (" + -diff + " ms ago)";
+        }
+        return time + " (now)";
+    }
+
     /**
      * Convert a System.currentTimeMillis() value to a time of day value like
      * that printed in logs. MM-DD HH:MM:SS.MMM
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 0aabc44..9bee4bf 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -18,22 +18,21 @@
 
 import static android.view.accessibility.AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS;
 
+import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
-import android.util.Pool;
-import android.util.Poolable;
-import android.util.PoolableManager;
-import android.util.Pools;
 import android.util.SparseLongArray;
 import android.view.accessibility.AccessibilityInteractionClient;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
 
+import com.android.internal.os.SomeArgs;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -47,7 +46,6 @@
  * UI thread.
  */
 final class AccessibilityInteractionController {
-    private static final int POOL_SIZE = 5;
 
     private ArrayList<AccessibilityNodeInfo> mTempAccessibilityNodeInfoList =
         new ArrayList<AccessibilityNodeInfo>();
@@ -64,6 +62,8 @@
 
     private final ArrayList<View> mTempArrayList = new ArrayList<View>();
 
+    private final Rect mTempRect = new Rect();
+
     public AccessibilityInteractionController(ViewRootImpl viewRootImpl) {
         Looper looper =  viewRootImpl.mHandler.getLooper();
         mMyLooperThreadId = looper.getThread().getId();
@@ -73,60 +73,6 @@
         mPrefetcher = new AccessibilityNodePrefetcher();
     }
 
-    // Reusable poolable arguments for interacting with the view hierarchy
-    // to fit more arguments than Message and to avoid sharing objects between
-    // two messages since several threads can send messages concurrently.
-    private final Pool<SomeArgs> mPool = Pools.synchronizedPool(Pools.finitePool(
-            new PoolableManager<SomeArgs>() {
-                public SomeArgs newInstance() {
-                    return new SomeArgs();
-                }
-
-                public void onAcquired(SomeArgs info) {
-                    /* do nothing */
-                }
-
-                public void onReleased(SomeArgs info) {
-                    info.clear();
-                }
-            }, POOL_SIZE)
-    );
-
-    private class SomeArgs implements Poolable<SomeArgs> {
-        private SomeArgs mNext;
-        private boolean mIsPooled;
-
-        public Object arg1;
-        public Object arg2;
-        public int argi1;
-        public int argi2;
-        public int argi3;
-
-        public SomeArgs getNextPoolable() {
-            return mNext;
-        }
-
-        public boolean isPooled() {
-            return mIsPooled;
-        }
-
-        public void setNextPoolable(SomeArgs args) {
-            mNext = args;
-        }
-
-        public void setPooled(boolean isPooled) {
-            mIsPooled = isPooled;
-        }
-
-        private void clear() {
-            arg1 = null;
-            arg2 = null;
-            argi1 = 0;
-            argi2 = 0;
-            argi3 = 0;
-        }
-    }
-
     private boolean isShown(View view) {
         // The first two checks are made also made by isShown() which
         // however traverses the tree up to the parent to catch that.
@@ -138,24 +84,18 @@
     }
 
     public void findAccessibilityNodeInfoByAccessibilityIdClientThread(
-            long accessibilityNodeId, int windowLeft, int windowTop, int interactionId,
+            long accessibilityNodeId, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
             long interrogatingTid) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID;
         message.arg1 = flags;
 
-        SomeArgs args = mPool.acquire();
+        SomeArgs args = SomeArgs.obtain();
         args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
         args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
         args.argi3 = interactionId;
         args.arg1 = callback;
-
-        SomeArgs moreArgs = mPool.acquire();
-        moreArgs.argi1 = windowLeft;
-        moreArgs.argi2 = windowTop;
-        args.arg2 = moreArgs;
-
         message.obj = args;
 
         // If the interrogation is performed by the same thread as the main UI
@@ -180,12 +120,7 @@
         final IAccessibilityInteractionConnectionCallback callback =
             (IAccessibilityInteractionConnectionCallback) args.arg1;
 
-        SomeArgs moreArgs = (SomeArgs) args.arg2;
-        mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1;
-        mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2;
-
-        mPool.release(moreArgs);
-        mPool.release(args);
+        args.recycle();
 
         List<AccessibilityNodeInfo> infos = mTempAccessibilityNodeInfoList;
         infos.clear();
@@ -207,6 +142,7 @@
         } finally {
             try {
                 mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
+                applyApplicationScaleIfNeeded(infos);
                 callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
                 infos.clear();
             } catch (RemoteException re) {
@@ -216,24 +152,18 @@
     }
 
     public void findAccessibilityNodeInfoByViewIdClientThread(long accessibilityNodeId,
-            int viewId, int windowLeft, int windowTop, int interactionId,
-            IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
-            long interrogatingTid) {
+            int viewId, int interactionId, IAccessibilityInteractionConnectionCallback callback,
+            int flags, int interrogatingPid, long interrogatingTid) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID;
         message.arg1 = flags;
         message.arg2 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
 
-        SomeArgs args = mPool.acquire();
+        SomeArgs args = SomeArgs.obtain();
         args.argi1 = viewId;
         args.argi2 = interactionId;
         args.arg1 = callback;
 
-        SomeArgs moreArgs = mPool.acquire();
-        moreArgs.argi1 = windowLeft;
-        moreArgs.argi2 = windowTop;
-        args.arg2 = moreArgs;
-
         message.obj = args;
 
         // If the interrogation is performed by the same thread as the main UI
@@ -258,12 +188,7 @@
         final IAccessibilityInteractionConnectionCallback callback =
             (IAccessibilityInteractionConnectionCallback) args.arg1;
 
-        SomeArgs moreArgs = (SomeArgs) args.arg2;
-        mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1;
-        mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2;
-
-        mPool.release(moreArgs);
-        mPool.release(args);
+        args.recycle();
 
         AccessibilityNodeInfo info = null;
         try {
@@ -287,6 +212,7 @@
         } finally {
             try {
                 mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
+                applyApplicationScaleIfNeeded(info);
                 callback.setFindAccessibilityNodeInfoResult(info, interactionId);
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
@@ -295,25 +221,19 @@
     }
 
     public void findAccessibilityNodeInfosByTextClientThread(long accessibilityNodeId,
-            String text, int windowLeft, int windowTop, int interactionId,
-            IAccessibilityInteractionConnectionCallback callback, int flags,
-            int interrogatingPid, long interrogatingTid) {
+            String text, int interactionId, IAccessibilityInteractionConnectionCallback callback,
+            int flags, int interrogatingPid, long interrogatingTid) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT;
         message.arg1 = flags;
 
-        SomeArgs args = mPool.acquire();
+        SomeArgs args = SomeArgs.obtain();
         args.arg1 = text;
+        args.arg2 = callback;
         args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
         args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
         args.argi3 = interactionId;
 
-        SomeArgs moreArgs = mPool.acquire();
-        moreArgs.arg1 = callback;
-        moreArgs.argi1 = windowLeft;
-        moreArgs.argi2 = windowTop;
-        args.arg2 = moreArgs;
-
         message.obj = args;
 
         // If the interrogation is performed by the same thread as the main UI
@@ -333,18 +253,12 @@
 
         SomeArgs args = (SomeArgs) message.obj;
         final String text = (String) args.arg1;
+        final IAccessibilityInteractionConnectionCallback callback =
+            (IAccessibilityInteractionConnectionCallback) args.arg2;
         final int accessibilityViewId = args.argi1;
         final int virtualDescendantId = args.argi2;
         final int interactionId = args.argi3;
-
-        SomeArgs moreArgs = (SomeArgs) args.arg2;
-        final IAccessibilityInteractionConnectionCallback callback =
-            (IAccessibilityInteractionConnectionCallback) moreArgs.arg1;
-        mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1;
-        mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2;
-
-        mPool.release(moreArgs);
-        mPool.release(args);
+        args.recycle();
 
         List<AccessibilityNodeInfo> infos = null;
         try {
@@ -396,6 +310,7 @@
         } finally {
             try {
                 mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
+                applyApplicationScaleIfNeeded(infos);
                 callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
@@ -403,25 +318,20 @@
         }
     }
 
-    public void findFocusClientThread(long accessibilityNodeId, int focusType, int windowLeft,
-            int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback,
-            int flags, int interogatingPid, long interrogatingTid) {
+    public void findFocusClientThread(long accessibilityNodeId, int focusType, int interactionId,
+            IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid,
+            long interrogatingTid) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FIND_FOCUS;
         message.arg1 = flags;
         message.arg2 = focusType;
 
-        SomeArgs args = mPool.acquire();
+        SomeArgs args = SomeArgs.obtain();
         args.argi1 = interactionId;
         args.argi2 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
         args.argi3 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
         args.arg1 = callback;
 
-        SomeArgs moreArgs = mPool.acquire();
-        moreArgs.argi1 = windowLeft;
-        moreArgs.argi2 = windowTop;
-        args.arg2 = moreArgs;
-
         message.obj = args;
 
         // If the interrogation is performed by the same thread as the main UI
@@ -447,12 +357,7 @@
         final IAccessibilityInteractionConnectionCallback callback =
             (IAccessibilityInteractionConnectionCallback) args.arg1;
 
-        SomeArgs moreArgs = (SomeArgs) args.arg2;
-        mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1;
-        mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2;
-
-        mPool.release(moreArgs);
-        mPool.release(args);
+        args.recycle();
 
         AccessibilityNodeInfo focused = null;
         try {
@@ -502,6 +407,7 @@
         } finally {
             try {
                 mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
+                applyApplicationScaleIfNeeded(focused);
                 callback.setFindAccessibilityNodeInfoResult(focused, interactionId);
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
@@ -509,25 +415,19 @@
         }
     }
 
-    public void focusSearchClientThread(long accessibilityNodeId, int direction, int windowLeft,
-            int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback,
-            int flags, int interogatingPid, long interrogatingTid) {
+    public void focusSearchClientThread(long accessibilityNodeId, int direction, int interactionId,
+            IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid,
+            long interrogatingTid) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FOCUS_SEARCH;
         message.arg1 = flags;
         message.arg2 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
 
-        SomeArgs args = mPool.acquire();
-        args.argi1 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
+        SomeArgs args = SomeArgs.obtain();
         args.argi2 = direction;
         args.argi3 = interactionId;
         args.arg1 = callback;
 
-        SomeArgs moreArgs = mPool.acquire();
-        moreArgs.argi1 = windowLeft;
-        moreArgs.argi2 = windowTop;
-        args.arg2 = moreArgs;
-
         message.obj = args;
 
         // If the interrogation is performed by the same thread as the main UI
@@ -547,18 +447,12 @@
         final int accessibilityViewId = message.arg2;
 
         SomeArgs args = (SomeArgs) message.obj;
-        final int virtualDescendantId = args.argi1;
         final int direction = args.argi2;
         final int interactionId = args.argi3;
         final IAccessibilityInteractionConnectionCallback callback =
             (IAccessibilityInteractionConnectionCallback) args.arg1;
 
-        SomeArgs moreArgs = (SomeArgs) args.arg2;
-        mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1;
-        mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2;
-
-        mPool.release(moreArgs);
-        mPool.release(args);
+        args.recycle();
 
         AccessibilityNodeInfo next = null;
         try {
@@ -574,43 +468,15 @@
                 root = mViewRootImpl.mView;
             }
             if (root != null && isShown(root)) {
-                if ((direction & View.FOCUS_ACCESSIBILITY) ==  View.FOCUS_ACCESSIBILITY) {
-                    AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
-                    if (provider != null) {
-                        next = provider.accessibilityFocusSearch(direction, virtualDescendantId);
-                        if (next != null) {
-                            return;
-                        }
-                    }
-                    View nextView = root.focusSearch(direction);
-                    while (nextView != null) {
-                        // If the focus search reached a node with a provider
-                        // we delegate to the provider to find the next one.
-                        // If the provider does not return a virtual view to
-                        // take accessibility focus we try the next view found
-                        // by the focus search algorithm.
-                        provider = nextView.getAccessibilityNodeProvider();
-                        if (provider != null) {
-                            next = provider.accessibilityFocusSearch(direction, View.NO_ID);
-                            if (next != null) {
-                                break;
-                            }
-                            nextView = nextView.focusSearch(direction);
-                        } else {
-                            next = nextView.createAccessibilityNodeInfo();
-                            break;
-                        }
-                    }
-                } else {
-                    View nextView = root.focusSearch(direction);
-                    if (nextView != null) {
-                        next = nextView.createAccessibilityNodeInfo();
-                    }
+                View nextView = root.focusSearch(direction);
+                if (nextView != null) {
+                    next = nextView.createAccessibilityNodeInfo();
                 }
             }
         } finally {
             try {
                 mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
+                applyApplicationScaleIfNeeded(next);
                 callback.setFindAccessibilityNodeInfoResult(next, interactionId);
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
@@ -627,7 +493,7 @@
         message.arg1 = flags;
         message.arg2 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
 
-        SomeArgs args = mPool.acquire();
+        SomeArgs args = SomeArgs.obtain();
         args.argi1 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
         args.argi2 = action;
         args.argi3 = interactionId;
@@ -660,7 +526,7 @@
             (IAccessibilityInteractionConnectionCallback) args.arg1;
         Bundle arguments = (Bundle) args.arg2;
 
-        mPool.release(args);
+        args.recycle();
 
         boolean succeeded = false;
         try {
@@ -706,6 +572,39 @@
         return foundView;
     }
 
+    private void applyApplicationScaleIfNeeded(List<AccessibilityNodeInfo> infos) {
+        if (infos == null) {
+            return;
+        }
+        final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale;
+        if (applicationScale != 1.0f) {
+            final int infoCount = infos.size();
+            for (int i = 0; i < infoCount; i++) {
+                AccessibilityNodeInfo info = infos.get(i);
+                applyApplicationScaleIfNeeded(info);
+            }
+        }
+    }
+
+    private void applyApplicationScaleIfNeeded(AccessibilityNodeInfo info) {
+        if (info == null) {
+            return;
+        }
+        final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale;
+        if (applicationScale != 1.0f) {
+            Rect bounds = mTempRect;
+
+            info.getBoundsInParent(bounds);
+            bounds.scale(applicationScale);
+            info.setBoundsInParent(bounds);
+
+            info.getBoundsInScreen(bounds);
+            bounds.scale(applicationScale);
+            info.setBoundsInScreen(bounds);
+        }
+    }
+
+
     /**
      * This class encapsulates a prefetching strategy for the accessibility APIs for
      * querying window content. It is responsible to prefetch a batch of
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 78dc86f..b661748 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.hardware.display.DisplayManagerGlobal;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -164,8 +165,8 @@
         mHandler = new FrameHandler(looper);
         mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;
         mLastFrameTimeNanos = Long.MIN_VALUE;
-        mFrameIntervalNanos = (long)(1000000000 /
-                new Display(Display.DEFAULT_DISPLAY, null).getRefreshRate());
+
+        mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
 
         mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
         for (int i = 0; i <= CALLBACK_LAST; i++) {
@@ -173,6 +174,12 @@
         }
     }
 
+    private static float getRefreshRate() {
+        DisplayInfo di = DisplayManagerGlobal.getInstance().getDisplayInfo(
+                Display.DEFAULT_DISPLAY);
+        return di.refreshRate;
+    }
+
     /**
      * Gets the choreographer for the calling thread.  Must be called from
      * a thread that already has a {@link android.os.Looper} associated with it.
@@ -677,7 +684,24 @@
         }
 
         @Override
-        public void onVsync(long timestampNanos, int frame) {
+        public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
+            // Ignore vsync from secondary display.
+            // This can be problematic because the call to scheduleVsync() is a one-shot.
+            // We need to ensure that we will still receive the vsync from the primary
+            // display which is the one we really care about.  Ideally we should schedule
+            // vsync for a particular display.
+            // At this time Surface Flinger won't send us vsyncs for secondary displays
+            // but that could change in the future so let's log a message to help us remember
+            // that we need to fix this.
+            if (builtInDisplayId != Surface.BUILT_IN_DISPLAY_ID_MAIN) {
+                Log.d(TAG, "Received vsync from secondary display, but we don't support "
+                        + "this case yet.  Choreographer needs a way to explicitly request "
+                        + "vsync for a specific display to ensure it doesn't lose track "
+                        + "of its scheduled vsync.");
+                scheduleVsync();
+                return;
+            }
+
             // Post the vsync event to the Handler.
             // The idea is to prevent incoming vsync events from completely starving
             // the message queue.  If there are no messages in the queue with timestamps
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index 626f385..6c733f9 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.ContextWrapper;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.os.Build;
 
@@ -30,6 +31,8 @@
     private int mThemeResource;
     private Resources.Theme mTheme;
     private LayoutInflater mInflater;
+    private Configuration mOverrideConfiguration;
+    private Resources mResources;
 
     public ContextThemeWrapper() {
         super(null);
@@ -45,6 +48,41 @@
         super.attachBaseContext(newBase);
         mBase = newBase;
     }
+
+    /**
+     * Call to set an "override configuration" on this context -- this is
+     * a configuration that replies one or more values of the standard
+     * configuration that is applied to the context.  See
+     * {@link Context#createConfigurationContext(Configuration)} for more
+     * information.
+     *
+     * <p>This method can only be called once, and must be called before any
+     * calls to {@link #getResources()} are made.
+     */
+    public void applyOverrideConfiguration(Configuration overrideConfiguration) {
+        if (mResources != null) {
+            throw new IllegalStateException("getResources() has already been called");
+        }
+        if (mOverrideConfiguration != null) {
+            throw new IllegalStateException("Override configuration has already been set");
+        }
+        mOverrideConfiguration = new Configuration(overrideConfiguration);
+    }
+
+    @Override
+    public Resources getResources() {
+        if (mResources != null) {
+            return mResources;
+        }
+        if (mOverrideConfiguration == null) {
+            mResources = super.getResources();
+            return mResources;
+        } else {
+            Context resc = createConfigurationContext(mOverrideConfiguration);
+            mResources = resc.getResources();
+            return mResources;
+        }
+    }
     
     @Override public void setTheme(int resid) {
         mThemeResource = resid;
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index c947312..758abb5 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -16,61 +16,309 @@
 
 package android.view;
 
-import android.content.res.CompatibilityInfo;
+import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.os.RemoteException;
-import android.os.ServiceManager;
+import android.hardware.display.DisplayManagerGlobal;
 import android.os.SystemClock;
 import android.util.DisplayMetrics;
-import android.util.Slog;
+import android.util.Log;
 
 /**
- * Provides information about the display size and density.
+ * Provides information about the size and density of a logical display.
+ * <p>
+ * The display area is described in two different ways.
+ * <ul>
+ * <li>The application display area specifies the part of the display that may contain
+ * an application window, excluding the system decorations.  The application display area may
+ * be smaller than the real display area because the system subtracts the space needed
+ * for decor elements such as the status bar.  Use the following methods to query the
+ * application display area: {@link #getSize}, {@link #getRectSize} and {@link #getMetrics}.</li>
+ * <li>The real display area specifies the part of the display that contains content
+ * including the system decorations.  Even so, the real display area may be smaller than the
+ * physical size of the display if the window manager is emulating a smaller display
+ * using (adb shell am display-size).  Use the following methods to query the
+ * real display area: {@link #getRealSize}, {@link #getRealMetrics}.</li>
+ * </ul>
+ * </p><p>
+ * A logical display does not necessarily represent a particular physical display device
+ * such as the built-in screen or an external monitor.  The contents of a logical
+ * display may be presented on one or more physical displays according to the devices
+ * that are currently attached and whether mirroring has been enabled.
+ * </p>
  */
-public class Display {
-    static final String TAG = "Display";
-    static final boolean DEBUG_DISPLAY_SIZE = false;
+public final class Display {
+    private static final String TAG = "Display";
+    private static final boolean DEBUG = false;
+
+    private final DisplayManagerGlobal mGlobal;
+    private final int mDisplayId;
+    private final int mLayerStack;
+    private final int mFlags;
+    private final int mType;
+    private final String mAddress;
+    private final CompatibilityInfoHolder mCompatibilityInfo;
+
+    private DisplayInfo mDisplayInfo; // never null
+    private boolean mIsValid;
+
+    // Temporary display metrics structure used for compatibility mode.
+    private final DisplayMetrics mTempMetrics = new DisplayMetrics();
+
+    // We cache the app width and height properties briefly between calls
+    // to getHeight() and getWidth() to ensure that applications perceive
+    // consistent results when the size changes (most of the time).
+    // Applications should now be using getSize() instead.
+    private static final int CACHED_APP_SIZE_DURATION_MILLIS = 20;
+    private long mLastCachedAppSizeUpdate;
+    private int mCachedAppWidthCompat;
+    private int mCachedAppHeightCompat;
 
     /**
-     * The default Display id.
+     * The default Display id, which is the id of the built-in primary display
+     * assuming there is one.
      */
     public static final int DEFAULT_DISPLAY = 0;
 
     /**
-     * Use {@link android.view.WindowManager#getDefaultDisplay()
-     * WindowManager.getDefaultDisplay()} to create a Display object.
-     * Display gives you access to some information about a particular display
-     * connected to the device.
+     * Display flag: Indicates that the display supports compositing content
+     * that is stored in protected graphics buffers.
+     * <p>
+     * If this flag is set then the display device supports compositing protected buffers.
+     * </p><p>
+     * If this flag is not set then the display device may not support compositing
+     * protected buffers; the user may see a blank region on the screen instead of
+     * the protected content.
+     * </p><p>
+     * Secure (DRM) video decoders may allocate protected graphics buffers to request that
+     * a hardware-protected path be provided between the video decoder and the external
+     * display sink.  If a hardware-protected path is not available, then content stored
+     * in protected graphics buffers may not be composited.
+     * </p><p>
+     * An application can use the absence of this flag as a hint that it should not use protected
+     * buffers for this display because the content may not be visible.  For example,
+     * if the flag is not set then the application may choose not to show content on this
+     * display, show an informative error message, select an alternate content stream
+     * or adopt a different strategy for decoding content that does not rely on
+     * protected buffers.
+     * </p>
+     *
+     * @see #getFlags
      */
-    Display(int display, CompatibilityInfoHolder compatInfo) {
-        // initalize the statics when this class is first instansiated. This is
-        // done here instead of in the static block because Zygote
-        synchronized (sStaticInit) {
-            if (!sInitialized) {
-                nativeClassInit();
-                sInitialized = true;
-            }
-        }
-        mCompatibilityInfo = compatInfo != null ? compatInfo : new CompatibilityInfoHolder();
-        mDisplay = display;
-        init(display);
+    public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 0;
+
+    /**
+     * Display flag: Indicates that the display has a secure video output and
+     * supports compositing secure surfaces.
+     * <p>
+     * If this flag is set then the display device has a secure video output
+     * and is capable of showing secure surfaces.  It may also be capable of
+     * showing {@link #FLAG_SUPPORTS_PROTECTED_BUFFERS protected buffers}.
+     * </p><p>
+     * If this flag is not set then the display device may not have a secure video
+     * output; the user may see a blank region on the screen instead of
+     * the contents of secure surfaces or protected buffers.
+     * </p><p>
+     * Secure surfaces are used to prevent content rendered into those surfaces
+     * by applications from appearing in screenshots or from being viewed
+     * on non-secure displays.  Protected buffers are used by secure video decoders
+     * for a similar purpose.
+     * </p><p>
+     * An application creates a window with a secure surface by specifying the
+     * {@link WindowManager.LayoutParams#FLAG_SECURE} window flag.
+     * Likewise, an application creates a {@link SurfaceView} with a secure surface
+     * by calling {@link SurfaceView#setSecure} before attaching the secure view to
+     * its containing window.
+     * </p><p>
+     * An application can use the absence of this flag as a hint that it should not create
+     * secure surfaces or protected buffers on this display because the content may
+     * not be visible.  For example, if the flag is not set then the application may
+     * choose not to show content on this display, show an informative error message,
+     * select an alternate content stream or adopt a different strategy for decoding
+     * content that does not rely on secure surfaces or protected buffers.
+     * </p>
+     *
+     * @see #getFlags
+     */
+    public static final int FLAG_SECURE = 1 << 1;
+
+    /**
+     * Display type: Unknown display type.
+     * @hide
+     */
+    public static final int TYPE_UNKNOWN = 0;
+
+    /**
+     * Display type: Built-in display.
+     * @hide
+     */
+    public static final int TYPE_BUILT_IN = 1;
+
+    /**
+     * Display type: HDMI display.
+     * @hide
+     */
+    public static final int TYPE_HDMI = 2;
+
+    /**
+     * Display type: WiFi display.
+     * @hide
+     */
+    public static final int TYPE_WIFI = 3;
+
+    /**
+     * Display type: Overlay display.
+     * @hide
+     */
+    public static final int TYPE_OVERLAY = 4;
+
+    /**
+     * Internal method to create a display.
+     * Applications should use {@link android.view.WindowManager#getDefaultDisplay()}
+     * or {@link android.hardware.display.DisplayManager#getDisplay}
+     * to get a display object.
+     *
+     * @hide
+     */
+    public Display(DisplayManagerGlobal global,
+            int displayId, DisplayInfo displayInfo /*not null*/,
+            CompatibilityInfoHolder compatibilityInfo) {
+        mGlobal = global;
+        mDisplayId = displayId;
+        mDisplayInfo = displayInfo;
+        mCompatibilityInfo = compatibilityInfo;
+        mIsValid = true;
+
+        // Cache properties that cannot change as long as the display is valid.
+        mLayerStack = displayInfo.layerStack;
+        mFlags = displayInfo.flags;
+        mType = displayInfo.type;
+        mAddress = displayInfo.address;
     }
 
     /**
-     * Returns the index of this display.  This is currently undefined; do
-     * not use.
+     * Gets the display id.
+     * <p>
+     * Each logical display has a unique id.
+     * The default display has id {@link #DEFAULT_DISPLAY}.
+     * </p>
      */
     public int getDisplayId() {
-        return mDisplay;
+        return mDisplayId;
     }
 
     /**
-     * Returns the number of displays connected to the device.  This is
-     * currently undefined; do not use.
+     * Returns true if this display is still valid, false if the display has been removed.
+     *
+     * If the display is invalid, then the methods of this class will
+     * continue to report the most recently observed display information.
+     * However, it is unwise (and rather fruitless) to continue using a
+     * {@link Display} object after the display's demise.
+     *
+     * It's possible for a display that was previously invalid to become
+     * valid again if a display with the same id is reconnected.
+     *
+     * @return True if the display is still valid.
      */
-    native static int getDisplayCount();
-    
+    public boolean isValid() {
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            return mIsValid;
+        }
+    }
+
+    /**
+     * Gets a full copy of the display information.
+     *
+     * @param outDisplayInfo The object to receive the copy of the display information.
+     * @return True if the display is still valid.
+     * @hide
+     */
+    public boolean getDisplayInfo(DisplayInfo outDisplayInfo) {
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            outDisplayInfo.copyFrom(mDisplayInfo);
+            return mIsValid;
+        }
+    }
+
+    /**
+     * Gets the display's layer stack.
+     *
+     * Each display has its own independent layer stack upon which surfaces
+     * are placed to be managed by surface flinger.
+     *
+     * @return The display's layer stack number.
+     * @hide
+     */
+    public int getLayerStack() {
+        return mLayerStack;
+    }
+
+    /**
+     * Returns a combination of flags that describe the capabilities of the display.
+     *
+     * @return The display flags.
+     *
+     * @see #FLAG_SUPPORTS_PROTECTED_BUFFERS
+     * @see #FLAG_SECURE
+     */
+    public int getFlags() {
+        return mFlags;
+    }
+
+    /**
+     * Gets the display type.
+     *
+     * @return The display type.
+     *
+     * @see #TYPE_UNKNOWN
+     * @see #TYPE_BUILT_IN
+     * @see #TYPE_HDMI
+     * @see #TYPE_WIFI
+     * @see #TYPE_OVERLAY
+     * @hide
+     */
+    public int getType() {
+        return mType;
+    }
+
+    /**
+     * Gets the display address, or null if none.
+     * Interpretation varies by display type.
+     *
+     * @return The display address.
+     * @hide
+     */
+    public String getAddress() {
+        return mAddress;
+    }
+
+    /**
+     * Gets the compatibility info used by this display instance.
+     *
+     * @return The compatibility info holder, or null if none is required.
+     * @hide
+     */
+    public CompatibilityInfoHolder getCompatibilityInfo() {
+        return mCompatibilityInfo;
+    }
+
+    /**
+     * Gets the name of the display.
+     * <p>
+     * Note that some displays may be renamed by the user.
+     * </p>
+     *
+     * @return The display's name.
+     */
+    public String getName() {
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            return mDisplayInfo.name;
+        }
+    }
+
     /**
      * Gets the size of the display, in pixels.
      * <p>
@@ -84,7 +332,7 @@
      * </p><p>
      * The size returned by this method does not necessarily represent the
      * actual raw size (native resolution) of the display.  The returned size may
-     * be adjusted to exclude certain system decor elements that are always visible.
+     * be adjusted to exclude certain system decoration elements that are always visible.
      * It may also be scaled to provide compatibility with older applications that
      * were originally designed for smaller displays.
      * </p>
@@ -92,43 +340,14 @@
      * @param outSize A {@link Point} object to receive the size information.
      */
     public void getSize(Point outSize) {
-        getSizeInternal(outSize, true);
-    }
-
-    private void getSizeInternal(Point outSize, boolean doCompat) {
-        try {
-            IWindowManager wm = getWindowManager();
-            if (wm != null) {
-                wm.getDisplaySize(outSize);
-                CompatibilityInfo ci;
-                if (doCompat && (ci=mCompatibilityInfo.getIfNeeded()) != null) {
-                    synchronized (mTmpMetrics) {
-                        mTmpMetrics.noncompatWidthPixels = outSize.x;
-                        mTmpMetrics.noncompatHeightPixels = outSize.y;
-                        mTmpMetrics.density = mDensity;
-                        ci.applyToDisplayMetrics(mTmpMetrics);
-                        outSize.x = mTmpMetrics.widthPixels;
-                        outSize.y = mTmpMetrics.heightPixels;
-                    }
-                }
-            } else {
-                // This is just for boot-strapping, initializing the
-                // system process before the window manager is up.
-                outSize.x = getRawWidth();
-                outSize.y = getRawHeight();
-            }
-            if (false) {
-                RuntimeException here = new RuntimeException("here");
-                here.fillInStackTrace();
-                Slog.v(TAG, "Returning display size: " + outSize, here);
-            }
-            if (DEBUG_DISPLAY_SIZE && doCompat) Slog.v(
-                    TAG, "Returning display size: " + outSize);
-        } catch (RemoteException e) {
-            Slog.w("Display", "Unable to get display size", e);
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+            outSize.x = mTempMetrics.widthPixels;
+            outSize.y = mTempMetrics.heightPixels;
         }
     }
-    
+
     /**
      * Gets the size of the display as a rectangle, in pixels.
      *
@@ -136,9 +355,10 @@
      * @see #getSize(Point)
      */
     public void getRectSize(Rect outSize) {
-        synchronized (mTmpPoint) {
-            getSizeInternal(mTmpPoint, true);
-            outSize.set(0, 0, mTmpPoint.x, mTmpPoint.y);
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+            outSize.set(0, 0, mTempMetrics.widthPixels, mTempMetrics.heightPixels);
         }
     }
 
@@ -173,15 +393,12 @@
      * for example, screen decorations like the status bar are being hidden.
      */
     public void getCurrentSizeRange(Point outSmallestSize, Point outLargestSize) {
-        try {
-            IWindowManager wm = getWindowManager();
-            wm.getCurrentSizeRange(outSmallestSize, outLargestSize);
-        } catch (RemoteException e) {
-            Slog.w("Display", "Unable to get display size range", e);
-            outSmallestSize.x = 0;
-            outSmallestSize.y = 0;
-            outLargestSize.x = 0;
-            outLargestSize.y = 0;
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            outSmallestSize.x = mDisplayInfo.smallestNominalAppWidth;
+            outSmallestSize.y = mDisplayInfo.smallestNominalAppHeight;
+            outLargestSize.x = mDisplayInfo.largestNominalAppWidth;
+            outLargestSize.y = mDisplayInfo.largestNominalAppHeight;
         }
     }
 
@@ -191,12 +408,9 @@
      * @hide
      */
     public int getMaximumSizeDimension() {
-        try {
-            IWindowManager wm = getWindowManager();
-            return wm.getMaximumSizeDimension();
-        } catch (RemoteException e) {
-            Slog.w("Display", "Unable to get display maximum size dimension", e);
-            return 0;
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            return Math.max(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
         }
     }
 
@@ -205,13 +419,9 @@
      */
     @Deprecated
     public int getWidth() {
-        synchronized (mTmpPoint) {
-            long now = SystemClock.uptimeMillis();
-            if (now > (mLastGetTime+20)) {
-                getSizeInternal(mTmpPoint, true);
-                mLastGetTime = now;
-            }
-            return mTmpPoint.x;
+        synchronized (this) {
+            updateCachedAppSizeIfNeededLocked();
+            return mCachedAppWidthCompat;
         }
     }
 
@@ -220,76 +430,13 @@
      */
     @Deprecated
     public int getHeight() {
-        synchronized (mTmpPoint) {
-            long now = SystemClock.uptimeMillis();
-            if (now > (mLastGetTime+20)) {
-                getSizeInternal(mTmpPoint, true);
-                mLastGetTime = now;
-            }
-            return mTmpPoint.y;
+        synchronized (this) {
+            updateCachedAppSizeIfNeededLocked();
+            return mCachedAppHeightCompat;
         }
     }
 
     /**
-     * Gets the real size of the display without subtracting any window decor or
-     * applying any compatibility scale factors.
-     * <p>
-     * The real size may be smaller than the raw size when the window manager
-     * is emulating a smaller display (using adb shell am display-size).
-     * </p><p>
-     * The size is adjusted based on the current rotation of the display.
-     * </p>
-     * @hide
-     */
-    public void getRealSize(Point outSize) {
-        try {
-            IWindowManager wm = getWindowManager();
-            if (wm != null) {
-                wm.getRealDisplaySize(outSize);
-            } else {
-                // This is just for boot-strapping, initializing the
-                // system process before the window manager is up.
-                outSize.x = getRawWidth();
-                outSize.y = getRawHeight();
-            }
-            if (DEBUG_DISPLAY_SIZE) Slog.v(
-                    TAG, "Returning real display size: " + outSize);
-        } catch (RemoteException e) {
-            Slog.w("Display", "Unable to get real display size", e);
-        }
-    }
-
-    /**
-     * Gets the raw width of the display, in pixels.
-     * <p>
-     * The size is adjusted based on the current rotation of the display.
-     * </p>
-     * @hide
-     */
-    public int getRawWidth() {
-        int w = getRawWidthNative();
-        if (DEBUG_DISPLAY_SIZE) Slog.v(
-                TAG, "Returning raw display width: " + w);
-        return w;
-    }
-    private native int getRawWidthNative();
-
-    /**
-     * Gets the raw height of the display, in pixels.
-     * <p>
-     * The size is adjusted based on the current rotation of the display.
-     * </p>
-     * @hide
-     */
-    public int getRawHeight() {
-        int h = getRawHeightNative();
-        if (DEBUG_DISPLAY_SIZE) Slog.v(
-                TAG, "Returning raw display height: " + h);
-        return h;
-    }
-    private native int getRawHeightNative();
-    
-    /**
      * Returns the rotation of the screen from its "natural" orientation.
      * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0}
      * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90},
@@ -307,30 +454,43 @@
      * {@link Surface#ROTATION_90 Surface.ROTATION_90}.
      */
     public int getRotation() {
-        return getOrientation();
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            return mDisplayInfo.rotation;
+        }
     }
-    
+
     /**
      * @deprecated use {@link #getRotation}
      * @return orientation of this display.
      */
-    @Deprecated native public int getOrientation();
+    @Deprecated
+    public int getOrientation() {
+        return getRotation();
+    }
 
     /**
-     * Return the native pixel format of the display.  The returned value
-     * may be one of the constants int {@link android.graphics.PixelFormat}.
+     * Gets the pixel format of the display.
+     * @return One of the constants defined in {@link android.graphics.PixelFormat}.
+     *
+     * @deprecated This method is no longer supported.
+     * The result is always {@link PixelFormat#RGBA_8888}.
      */
+    @Deprecated
     public int getPixelFormat() {
-        return mPixelFormat;
+        return PixelFormat.RGBA_8888;
     }
-    
+
     /**
-     * Return the refresh rate of this display in frames per second.
+     * Gets the refresh rate of this display in frames per second.
      */
     public float getRefreshRate() {
-        return mRefreshRate;
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            return mDisplayInfo.refreshRate;
+        }
     }
-    
+
     /**
      * Gets display metrics that describe the size and density of this display.
      * <p>
@@ -346,117 +506,113 @@
      * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
      */
     public void getMetrics(DisplayMetrics outMetrics) {
-        synchronized (mTmpPoint) {
-            getSizeInternal(mTmpPoint, false);
-            getMetricsWithSize(outMetrics, mTmpPoint.x, mTmpPoint.y);
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            mDisplayInfo.getAppMetrics(outMetrics, mCompatibilityInfo);
         }
+    }
 
-        CompatibilityInfo ci = mCompatibilityInfo.getIfNeeded();
-        if (ci != null) {
-            ci.applyToDisplayMetrics(outMetrics);
+    /**
+     * Gets the real size of the display without subtracting any window decor or
+     * applying any compatibility scale factors.
+     * <p>
+     * The size is adjusted based on the current rotation of the display.
+     * </p><p>
+     * The real size may be smaller than the physical size of the screen when the
+     * window manager is emulating a smaller display (using adb shell am display-size).
+     * </p>
+     *
+     * @param outSize Set to the real size of the display.
+     */
+    public void getRealSize(Point outSize) {
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            outSize.x = mDisplayInfo.logicalWidth;
+            outSize.y = mDisplayInfo.logicalHeight;
         }
-
-        if (DEBUG_DISPLAY_SIZE) Slog.v(TAG, "Returning DisplayMetrics: "
-                + outMetrics.widthPixels + "x" + outMetrics.heightPixels
-                + " " + outMetrics.density);
     }
 
     /**
      * Gets display metrics based on the real size of this display.
-     * @hide
+     * <p>
+     * The size is adjusted based on the current rotation of the display.
+     * </p><p>
+     * The real size may be smaller than the physical size of the screen when the
+     * window manager is emulating a smaller display (using adb shell am display-size).
+     * </p>
+     *
+     * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
      */
     public void getRealMetrics(DisplayMetrics outMetrics) {
-        synchronized (mTmpPoint) {
-            getRealSize(mTmpPoint);
-            getMetricsWithSize(outMetrics, mTmpPoint.x, mTmpPoint.y);
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            mDisplayInfo.getLogicalMetrics(outMetrics, null);
         }
     }
 
-    /**
-     * If the display is mirrored to an external HDMI display, returns the
-     * width of that display.
-     * @hide
-     */
-    public int getRawExternalWidth() {
-        return 1280;
-    }
-
-    /**
-     * If the display is mirrored to an external HDMI display, returns the
-     * height of that display.
-     * @hide
-     */
-    public int getRawExternalHeight() {
-        return 720;
-    }
-
-    /**
-     * If the display is mirrored to an external HDMI display, returns the
-     * rotation of that display relative to its natural orientation.
-     * @hide
-     */
-    public int getExternalRotation() {
-        return Surface.ROTATION_0;
-    }
-
-    /**
-     * Gets display metrics based on an explicit assumed display size.
-     * @hide
-     */
-    public void getMetricsWithSize(DisplayMetrics outMetrics,
-            int width, int height) {
-        outMetrics.densityDpi   = (int)((mDensity*DisplayMetrics.DENSITY_DEFAULT)+.5f);
-
-        outMetrics.noncompatWidthPixels  = outMetrics.widthPixels = width;
-        outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
-
-        outMetrics.density = outMetrics.noncompatDensity = mDensity;
-        outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
-        outMetrics.xdpi = outMetrics.noncompatXdpi = mDpiX;
-        outMetrics.ydpi = outMetrics.noncompatYdpi = mDpiY;
-    }
-
-    static IWindowManager getWindowManager() {
-        synchronized (sStaticInit) {
-            if (sWindowManager == null) {
-                sWindowManager = IWindowManager.Stub.asInterface(
-                        ServiceManager.getService("window"));
+    private void updateDisplayInfoLocked() {
+        // Note: The display manager caches display info objects on our behalf.
+        DisplayInfo newInfo = mGlobal.getDisplayInfo(mDisplayId);
+        if (newInfo == null) {
+            // Preserve the old mDisplayInfo after the display is removed.
+            if (mIsValid) {
+                mIsValid = false;
+                if (DEBUG) {
+                    Log.d(TAG, "Logical display " + mDisplayId + " was removed.");
+                }
             }
-            return sWindowManager;
+        } else {
+            // Use the new display info.  (It might be the same object if nothing changed.)
+            mDisplayInfo = newInfo;
+            if (!mIsValid) {
+                mIsValid = true;
+                if (DEBUG) {
+                    Log.d(TAG, "Logical display " + mDisplayId + " was recreated.");
+                }
+            }
         }
     }
 
-    /*
-     * We use a class initializer to allow the native code to cache some
-     * field offsets.
-     */
-    native private static void nativeClassInit();
-    
-    private native void init(int display);
+    private void updateCachedAppSizeIfNeededLocked() {
+        long now = SystemClock.uptimeMillis();
+        if (now > mLastCachedAppSizeUpdate + CACHED_APP_SIZE_DURATION_MILLIS) {
+            updateDisplayInfoLocked();
+            mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+            mCachedAppWidthCompat = mTempMetrics.widthPixels;
+            mCachedAppHeightCompat = mTempMetrics.heightPixels;
+            mLastCachedAppSizeUpdate = now;
+        }
+    }
 
-    private final CompatibilityInfoHolder mCompatibilityInfo;
-    private final int   mDisplay;
-    // Following fields are initialized from native code
-    private int         mPixelFormat;
-    private float       mRefreshRate;
-    /*package*/ float   mDensity;
-    /*package*/ float   mDpiX;
-    /*package*/ float   mDpiY;
-    
-    private final Point mTmpPoint = new Point();
-    private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
-    private float mLastGetTime;
-
-    private static final Object sStaticInit = new Object();
-    private static boolean sInitialized = false;
-    private static IWindowManager sWindowManager;
+    // For debugging purposes
+    @Override
+    public String toString() {
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+            return "Display id " + mDisplayId + ": " + mDisplayInfo
+                    + ", " + mTempMetrics + ", isValid=" + mIsValid;
+        }
+    }
 
     /**
-     * Returns a display object which uses the metric's width/height instead.
      * @hide
      */
-    public static Display createCompatibleDisplay(int displayId, CompatibilityInfoHolder compat) {
-        return new Display(displayId, compat);
+    public static String typeToString(int type) {
+        switch (type) {
+            case TYPE_UNKNOWN:
+                return "UNKNOWN";
+            case TYPE_BUILT_IN:
+                return "BUILT_IN";
+            case TYPE_HDMI:
+                return "HDMI";
+            case TYPE_WIFI:
+                return "WIFI";
+            case TYPE_OVERLAY:
+                return "OVERLAY";
+            default:
+                return Integer.toString(type);
+        }
     }
 }
 
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index 6c2e540..a919ffc 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -66,7 +66,7 @@
     @Override
     protected void finalize() throws Throwable {
         try {
-            dispose();
+            dispose(true);
         } finally {
             super.finalize();
         }
@@ -76,9 +76,17 @@
      * Disposes the receiver.
      */
     public void dispose() {
+        dispose(false);
+    }
+
+    private void dispose(boolean finalized) {
         if (mCloseGuard != null) {
+            if (finalized) {
+                mCloseGuard.warnIfOpen();
+            }
             mCloseGuard.close();
         }
+
         if (mReceiverPtr != 0) {
             nativeDispose(mReceiverPtr);
             mReceiverPtr = 0;
@@ -93,9 +101,23 @@
      *
      * @param timestampNanos The timestamp of the pulse, in the {@link System#nanoTime()}
      * timebase.
+     * @param builtInDisplayId The surface flinger built-in display id such as
+     * {@link Surface#BUILT_IN_DISPLAY_ID_MAIN}.
      * @param frame The frame number.  Increases by one for each vertical sync interval.
      */
-    public void onVsync(long timestampNanos, int frame) {
+    public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
+    }
+
+    /**
+     * Called when a display hotplug event is received.
+     *
+     * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
+     * timebase.
+     * @param builtInDisplayId The surface flinger built-in display id such as
+     * {@link Surface#BUILT_IN_DISPLAY_ID_HDMI}.
+     * @param connected True if the display is connected, false if it disconnected.
+     */
+    public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
     }
 
     /**
@@ -113,7 +135,13 @@
 
     // Called from native code.
     @SuppressWarnings("unused")
-    private void dispatchVsync(long timestampNanos, int frame) {
-        onVsync(timestampNanos, frame);
+    private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
+        onVsync(timestampNanos, builtInDisplayId, frame);
+    }
+
+    // Called from native code.
+    @SuppressWarnings("unused")
+    private void dispatchHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
+        onHotplug(timestampNanos, builtInDisplayId, connected);
     }
 }
diff --git a/core/java/android/view/DisplayInfo.aidl b/core/java/android/view/DisplayInfo.aidl
new file mode 100644
index 0000000..e679208
--- /dev/null
+++ b/core/java/android/view/DisplayInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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;
+
+parcelable DisplayInfo;
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
new file mode 100644
index 0000000..f3841d5
--- /dev/null
+++ b/core/java/android/view/DisplayInfo.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.content.res.CompatibilityInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.DisplayMetrics;
+
+import libcore.util.Objects;
+
+/**
+ * Describes the characteristics of a particular logical display.
+ * @hide
+ */
+public final class DisplayInfo implements Parcelable {
+    /**
+     * The surface flinger layer stack associated with this logical display.
+     */
+    public int layerStack;
+
+    /**
+     * Display flags.
+     */
+    public int flags;
+
+    /**
+     * Display type.
+     */
+    public int type;
+
+    /**
+     * Display address, or null if none.
+     * Interpretation varies by display type.
+     */
+    public String address;
+
+    /**
+     * The human-readable name of the display.
+     */
+    public String name;
+
+    /**
+     * The width of the portion of the display that is available to applications, in pixels.
+     * Represents the size of the display minus any system decorations.
+     */
+    public int appWidth;
+
+    /**
+     * The height of the portion of the display that is available to applications, in pixels.
+     * Represents the size of the display minus any system decorations.
+     */
+    public int appHeight;
+
+    /**
+     * The smallest value of {@link #appWidth} that an application is likely to encounter,
+     * in pixels, excepting cases where the width may be even smaller due to the presence
+     * of a soft keyboard, for example.
+     */
+    public int smallestNominalAppWidth;
+
+    /**
+     * The smallest value of {@link #appHeight} that an application is likely to encounter,
+     * in pixels, excepting cases where the height may be even smaller due to the presence
+     * of a soft keyboard, for example.
+     */
+    public int smallestNominalAppHeight;
+
+    /**
+     * The largest value of {@link #appWidth} that an application is likely to encounter,
+     * in pixels, excepting cases where the width may be even larger due to system decorations
+     * such as the status bar being hidden, for example.
+     */
+    public int largestNominalAppWidth;
+
+    /**
+     * The largest value of {@link #appHeight} that an application is likely to encounter,
+     * in pixels, excepting cases where the height may be even larger due to system decorations
+     * such as the status bar being hidden, for example.
+     */
+    public int largestNominalAppHeight;
+
+    /**
+     * The logical width of the display, in pixels.
+     * Represents the usable size of the display which may be smaller than the
+     * physical size when the system is emulating a smaller display.
+     */
+    public int logicalWidth;
+
+    /**
+     * The logical height of the display, in pixels.
+     * Represents the usable size of the display which may be smaller than the
+     * physical size when the system is emulating a smaller display.
+     */
+    public int logicalHeight;
+
+    /**
+     * The rotation of the display relative to its natural orientation.
+     * May be one of {@link android.view.Surface#ROTATION_0},
+     * {@link android.view.Surface#ROTATION_90}, {@link android.view.Surface#ROTATION_180},
+     * {@link android.view.Surface#ROTATION_270}.
+     * <p>
+     * The value of this field is indeterminate if the logical display is presented on
+     * more than one physical display.
+     * </p>
+     */
+    public int rotation;
+
+    /**
+     * The refresh rate of this display in frames per second.
+     * <p>
+     * The value of this field is indeterminate if the logical display is presented on
+     * more than one physical display.
+     * </p>
+     */
+    public float refreshRate;
+
+    /**
+     * The logical display density which is the basis for density-independent
+     * pixels.
+     */
+    public int logicalDensityDpi;
+
+    /**
+     * The exact physical pixels per inch of the screen in the X dimension.
+     * <p>
+     * The value of this field is indeterminate if the logical display is presented on
+     * more than one physical display.
+     * </p>
+     */
+    public float physicalXDpi;
+
+    /**
+     * The exact physical pixels per inch of the screen in the Y dimension.
+     * <p>
+     * The value of this field is indeterminate if the logical display is presented on
+     * more than one physical display.
+     * </p>
+     */
+    public float physicalYDpi;
+
+    public static final Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
+        @Override
+        public DisplayInfo createFromParcel(Parcel source) {
+            return new DisplayInfo(source);
+        }
+
+        @Override
+        public DisplayInfo[] newArray(int size) {
+            return new DisplayInfo[size];
+        }
+    };
+
+    public DisplayInfo() {
+    }
+
+    public DisplayInfo(DisplayInfo other) {
+        copyFrom(other);
+    }
+
+    private DisplayInfo(Parcel source) {
+        readFromParcel(source);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o instanceof DisplayInfo && equals((DisplayInfo)o);
+    }
+
+    public boolean equals(DisplayInfo other) {
+        return other != null
+                && layerStack == other.layerStack
+                && flags == other.flags
+                && type == other.type
+                && Objects.equal(address, other.address)
+                && Objects.equal(name, other.name)
+                && appWidth == other.appWidth
+                && appHeight == other.appHeight
+                && smallestNominalAppWidth == other.smallestNominalAppWidth
+                && smallestNominalAppHeight == other.smallestNominalAppHeight
+                && largestNominalAppWidth == other.largestNominalAppWidth
+                && largestNominalAppHeight == other.largestNominalAppHeight
+                && logicalWidth == other.logicalWidth
+                && logicalHeight == other.logicalHeight
+                && rotation == other.rotation
+                && refreshRate == other.refreshRate
+                && logicalDensityDpi == other.logicalDensityDpi
+                && physicalXDpi == other.physicalXDpi
+                && physicalYDpi == other.physicalYDpi;
+    }
+
+    @Override
+    public int hashCode() {
+        return 0; // don't care
+    }
+
+    public void copyFrom(DisplayInfo other) {
+        layerStack = other.layerStack;
+        flags = other.flags;
+        type = other.type;
+        address = other.address;
+        name = other.name;
+        appWidth = other.appWidth;
+        appHeight = other.appHeight;
+        smallestNominalAppWidth = other.smallestNominalAppWidth;
+        smallestNominalAppHeight = other.smallestNominalAppHeight;
+        largestNominalAppWidth = other.largestNominalAppWidth;
+        largestNominalAppHeight = other.largestNominalAppHeight;
+        logicalWidth = other.logicalWidth;
+        logicalHeight = other.logicalHeight;
+        rotation = other.rotation;
+        refreshRate = other.refreshRate;
+        logicalDensityDpi = other.logicalDensityDpi;
+        physicalXDpi = other.physicalXDpi;
+        physicalYDpi = other.physicalYDpi;
+    }
+
+    public void readFromParcel(Parcel source) {
+        layerStack = source.readInt();
+        flags = source.readInt();
+        type = source.readInt();
+        address = source.readString();
+        name = source.readString();
+        appWidth = source.readInt();
+        appHeight = source.readInt();
+        smallestNominalAppWidth = source.readInt();
+        smallestNominalAppHeight = source.readInt();
+        largestNominalAppWidth = source.readInt();
+        largestNominalAppHeight = source.readInt();
+        logicalWidth = source.readInt();
+        logicalHeight = source.readInt();
+        rotation = source.readInt();
+        refreshRate = source.readFloat();
+        logicalDensityDpi = source.readInt();
+        physicalXDpi = source.readFloat();
+        physicalYDpi = source.readFloat();
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(layerStack);
+        dest.writeInt(this.flags);
+        dest.writeInt(type);
+        dest.writeString(address);
+        dest.writeString(name);
+        dest.writeInt(appWidth);
+        dest.writeInt(appHeight);
+        dest.writeInt(smallestNominalAppWidth);
+        dest.writeInt(smallestNominalAppHeight);
+        dest.writeInt(largestNominalAppWidth);
+        dest.writeInt(largestNominalAppHeight);
+        dest.writeInt(logicalWidth);
+        dest.writeInt(logicalHeight);
+        dest.writeInt(rotation);
+        dest.writeFloat(refreshRate);
+        dest.writeInt(logicalDensityDpi);
+        dest.writeFloat(physicalXDpi);
+        dest.writeFloat(physicalYDpi);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih) {
+        getMetricsWithSize(outMetrics, cih, appWidth, appHeight);
+    }
+
+    public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih) {
+        getMetricsWithSize(outMetrics, cih, logicalWidth, logicalHeight);
+    }
+
+    private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfoHolder cih,
+            int width, int height) {
+        outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi;
+        outMetrics.noncompatWidthPixels  = outMetrics.widthPixels = width;
+        outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
+
+        outMetrics.density = outMetrics.noncompatDensity =
+                logicalDensityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+        outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
+        outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi;
+        outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi;
+
+        if (cih != null) {
+            CompatibilityInfo ci = cih.getIfNeeded();
+            if (ci != null) {
+                ci.applyToDisplayMetrics(outMetrics);
+            }
+        }
+    }
+
+    // For debugging purposes
+    @Override
+    public String toString() {
+        return "DisplayInfo{\"" + name + "\", app " + appWidth + " x " + appHeight
+                + ", real " + logicalWidth + " x " + logicalHeight
+                + ", largest app " + largestNominalAppWidth + " x " + largestNominalAppHeight
+                + ", smallest app " + smallestNominalAppWidth + " x " + smallestNominalAppHeight
+                + ", " + refreshRate + " fps"
+                + ", rotation " + rotation
+                + ", density " + logicalDensityDpi
+                + ", " + physicalXDpi + " x " + physicalYDpi + " dpi"
+                + ", layerStack " + layerStack
+                + ", type " + Display.typeToString(type)
+                + ", address " + address
+                + flagsToString(flags) + "}";
+    }
+
+    private static String flagsToString(int flags) {
+        StringBuilder result = new StringBuilder();
+        if ((flags & Display.FLAG_SECURE) != 0) {
+            result.append(", FLAG_SECURE");
+        }
+        if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
+            result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
+        }
+        return result.toString();
+    }
+}
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index a42e156..5e34a36 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -332,4 +332,11 @@
      * @see View#offsetTopAndBottom(int)
      */
     public abstract void offsetTopBottom(int offset);
+
+    /**
+     * Reset native resources. This is called when cleaning up the state of DisplayLists
+     * during destruction of hardware resources, to ensure that we do not hold onto
+     * obsolete resources after related resources are gone.
+     */
+    public abstract void reset();
 }
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index 31a9f05..b2988ed 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -79,17 +79,9 @@
     }
 
     private View findNextFocus(ViewGroup root, View focused, Rect focusedRect, int direction) {
-        if ((direction & View.FOCUS_ACCESSIBILITY) != View.FOCUS_ACCESSIBILITY) {
-            return findNextInputFocus(root, focused, focusedRect, direction);
-        } else {
-            return findNextAccessibilityFocus(root, focused, focusedRect, direction);
-        }
-    }
-
-    private View findNextInputFocus(ViewGroup root, View focused, Rect focusedRect, int direction) {
         View next = null;
         if (focused != null) {
-            next = findNextUserSpecifiedInputFocus(root, focused, direction);
+            next = findNextUserSpecifiedFocus(root, focused, direction);
         }
         if (next != null) {
             return next;
@@ -107,7 +99,7 @@
         return next;
     }
 
-    private View findNextUserSpecifiedInputFocus(ViewGroup root, View focused, int direction) {
+    private View findNextUserSpecifiedFocus(ViewGroup root, View focused, int direction) {
         // check for user specified next focus
         View userSetNextFocus = focused.findUserSetNextFocus(root, direction);
         if (userSetNextFocus != null && userSetNextFocus.isFocusable()
@@ -120,7 +112,6 @@
 
     private View findNextFocus(ViewGroup root, View focused, Rect focusedRect,
             int direction, ArrayList<View> focusables) {
-        final int directionMasked = (direction & ~View.FOCUS_ACCESSIBILITY);
         if (focused != null) {
             if (focusedRect == null) {
                 focusedRect = mFocusedRect;
@@ -132,7 +123,7 @@
             if (focusedRect == null) {
                 focusedRect = mFocusedRect;
                 // make up a rect at top left or bottom right of root
-                switch (directionMasked) {
+                switch (direction) {
                     case View.FOCUS_RIGHT:
                     case View.FOCUS_DOWN:
                         setFocusTopLeft(root, focusedRect);
@@ -160,37 +151,23 @@
             }
         }
 
-        switch (directionMasked) {
+        switch (direction) {
             case View.FOCUS_FORWARD:
             case View.FOCUS_BACKWARD:
-                return findNextInputFocusInRelativeDirection(focusables, root, focused, focusedRect,
-                        directionMasked);
+                return findNextFocusInRelativeDirection(focusables, root, focused, focusedRect,
+                        direction);
             case View.FOCUS_UP:
             case View.FOCUS_DOWN:
             case View.FOCUS_LEFT:
             case View.FOCUS_RIGHT:
-                return findNextInputFocusInAbsoluteDirection(focusables, root, focused,
-                        focusedRect, directionMasked);
+                return findNextFocusInAbsoluteDirection(focusables, root, focused,
+                        focusedRect, direction);
             default:
-                throw new IllegalArgumentException("Unknown direction: " + directionMasked);
+                throw new IllegalArgumentException("Unknown direction: " + direction);
         }
     }
 
-    private View findNextAccessibilityFocus(ViewGroup root, View focused,
-            Rect focusedRect, int direction) {
-        ArrayList<View> focusables = mTempList;
-        try {
-            focusables.clear();
-            root.addFocusables(focusables, direction, View.FOCUSABLES_ACCESSIBILITY);
-            View next = findNextFocus(root, focused, focusedRect, direction,
-                    focusables);
-            return next;
-        } finally {
-            focusables.clear();
-        }
-    }
-
-    private View findNextInputFocusInRelativeDirection(ArrayList<View> focusables, ViewGroup root,
+    private View findNextFocusInRelativeDirection(ArrayList<View> focusables, ViewGroup root,
             View focused, Rect focusedRect, int direction) {
         try {
             // Note: This sort is stable.
@@ -222,7 +199,7 @@
         focusedRect.set(rootLeft, rootTop, rootLeft, rootTop);
     }
 
-    View findNextInputFocusInAbsoluteDirection(ArrayList<View> focusables, ViewGroup root, View focused,
+    View findNextFocusInAbsoluteDirection(ArrayList<View> focusables, ViewGroup root, View focused,
             Rect focusedRect, int direction) {
         // initialize the best candidate to something impossible
         // (so the first plausible view will become the best choice)
@@ -251,7 +228,7 @@
             if (focusable == focused || focusable == root) continue;
 
             // get focus bounds of other view in same coordinate system
-            focusable.getFocusRect(mOtherRect);
+            focusable.getFocusedRect(mOtherRect);
             root.offsetDescendantRectToMyCoords(focusable, mOtherRect);
 
             if (isBetterCandidate(direction, focusedRect, mOtherRect, mBestCandidateRect)) {
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 055aee3..b64a06e 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -147,20 +147,36 @@
     ///////////////////////////////////////////////////////////////////////////
     // Hardware layers
     ///////////////////////////////////////////////////////////////////////////
-    
+
+    @Override
+    void pushLayerUpdate(HardwareLayer layer) {
+        nPushLayerUpdate(mRenderer, ((GLES20RenderLayer) layer).mLayer);
+    }
+
+    @Override
+    void clearLayerUpdates() {
+        nClearLayerUpdates(mRenderer);
+    }
+
     static native int nCreateTextureLayer(boolean opaque, int[] layerInfo);
     static native int nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo);
-    static native void nResizeLayer(int layerId, int width, int height, int[] layerInfo);
+    static native boolean nResizeLayer(int layerId, int width, int height, int[] layerInfo);
+    static native void nSetOpaqueLayer(int layerId, boolean isOpaque);
+    static native void nSetLayerPaint(int layerId, int nativePaint);
+    static native void nSetLayerColorFilter(int layerId, int nativeColorFilter);
     static native void nUpdateTextureLayer(int layerId, int width, int height, boolean opaque,
             SurfaceTexture surface);
+    static native void nClearLayerTexture(int layerId);
     static native void nSetTextureLayerTransform(int layerId, int matrix);
     static native void nDestroyLayer(int layerId);
     static native void nDestroyLayerDeferred(int layerId);
-    static native void nFlushLayer(int layerId);
     static native void nUpdateRenderLayer(int layerId, int renderer, int displayList,
             int left, int top, int right, int bottom);
     static native boolean nCopyLayer(int layerId, int bitmap);
 
+    private static native void nClearLayerUpdates(int renderer);
+    private static native void nPushLayerUpdate(int renderer, int layer);
+
     ///////////////////////////////////////////////////////////////////////////
     // Canvas management
     ///////////////////////////////////////////////////////////////////////////
@@ -394,13 +410,8 @@
     
     void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
         final GLES20Layer glLayer = (GLES20Layer) layer;
-        int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
-        try {
-            final int nativePaint = paint == null ? 0 : paint.mNativePaint;
-            nDrawLayer(mRenderer, glLayer.getLayer(), x, y, nativePaint);
-        } finally {
-            if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
-        }
+        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
+        nDrawLayer(mRenderer, glLayer.getLayer(), x, y, nativePaint);
     }
 
     private static native void nDrawLayer(int renderer, int layer, float x, float y, int paint);
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index 2d2e8e4..e9bd0c4 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -25,9 +25,12 @@
  * An implementation of display list for OpenGL ES 2.0.
  */
 class GLES20DisplayList extends DisplayList {
-    // These lists ensure that any Bitmaps recorded by a DisplayList are kept alive as long
-    // as the DisplayList is alive.  The Bitmaps are populated by the GLES20RecordingCanvas.
+    // These lists ensure that any Bitmaps and DisplayLists recorded by a DisplayList are kept
+    // alive as long as the DisplayList is alive.  The Bitmap and DisplayList lists
+    // are populated by the GLES20RecordingCanvas during appropriate drawing calls and are
+    // cleared at the start of a new drawing frame or when the view is detached from the window.
     final ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(5);
+    final ArrayList<DisplayList> mChildDisplayLists = new ArrayList<DisplayList>();
 
     private GLES20RecordingCanvas mCanvas;
     private boolean mValid;
@@ -79,6 +82,14 @@
     public void clear() {
         if (!mValid) {
             mBitmaps.clear();
+            mChildDisplayLists.clear();
+        }
+    }
+
+    @Override
+    public void reset() {
+        if (hasNativeDisplayList()) {
+            nReset(mFinalizer.mNativeDisplayList);
         }
     }
 
@@ -290,6 +301,7 @@
         }
     }
 
+    private static native void nReset(int displayList);
     private static native void nOffsetTopBottom(int displayList, int offset);
     private static native void nOffsetLeftRight(int displayList, int offset);
     private static native void nSetLeftTopRightBottom(int displayList, int left, int top,
diff --git a/core/java/android/view/GLES20Layer.java b/core/java/android/view/GLES20Layer.java
index 4f25792..812fb97 100644
--- a/core/java/android/view/GLES20Layer.java
+++ b/core/java/android/view/GLES20Layer.java
@@ -18,6 +18,7 @@
 package android.view;
 
 import android.graphics.Bitmap;
+import android.graphics.Paint;
 
 /**
  * An OpenGL ES 2.0 implementation of {@link HardwareLayer}.
@@ -43,14 +44,18 @@
     }
 
     @Override
+    void setLayerPaint(Paint paint) {
+        if (paint != null) {
+            GLES20Canvas.nSetLayerPaint(mLayer, paint.mNativePaint);
+            GLES20Canvas.nSetLayerColorFilter(mLayer, paint.getColorFilter() != null ?
+                    paint.getColorFilter().nativeColorFilter : 0);
+        }
+    }
+
+    @Override
     boolean copyInto(Bitmap bitmap) {
         return GLES20Canvas.nCopyLayer(mLayer, bitmap.mNativeBitmap);
     }
-    
-    @Override
-    void update(int width, int height, boolean isOpaque) {
-        super.update(width, height, isOpaque);
-    }
 
     @Override
     void destroy() {
@@ -60,12 +65,10 @@
         }
         mLayer = 0;
     }
-    
+
     @Override
-    void flush() {
-        if (mLayer != 0) {
-            GLES20Canvas.nFlushLayer(mLayer);
-        }
+    void clearStorage() {
+        if (mLayer != 0) GLES20Canvas.nClearLayerTexture(mLayer);
     }
 
     static class Finalizer {
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
index c9ba65f..d2df45a 100644
--- a/core/java/android/view/GLES20RecordingCanvas.java
+++ b/core/java/android/view/GLES20RecordingCanvas.java
@@ -76,6 +76,7 @@
 
     void start() {
         mDisplayList.mBitmaps.clear();
+        mDisplayList.mChildDisplayLists.clear();
     }
 
     int end(int nativeDisplayList) {
@@ -156,6 +157,13 @@
     }
 
     @Override
+    public int drawDisplayList(DisplayList displayList, Rect dirty, int flags) {
+        int status = super.drawDisplayList(displayList, dirty, flags);
+        mDisplayList.mChildDisplayLists.add(displayList);
+        return status;
+    }
+
+    @Override
     public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
         super.drawLine(startX, startY, stopX, stopY, paint);
         recordShaderBitmap(paint);
@@ -228,18 +236,6 @@
     }
 
     @Override
-    public void drawRect(Rect r, Paint paint) {
-        super.drawRect(r, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawRect(RectF r, Paint paint) {
-        super.drawRect(r, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
     public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
         super.drawRoundRect(rect, rx, ry, paint);
         recordShaderBitmap(paint);
diff --git a/core/java/android/view/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java
index c727a36..44d4719 100644
--- a/core/java/android/view/GLES20RenderLayer.java
+++ b/core/java/android/view/GLES20RenderLayer.java
@@ -54,8 +54,8 @@
     }
 
     @Override
-    void resize(int width, int height) {
-        if (!isValid() || width <= 0 || height <= 0) return;
+    boolean resize(int width, int height) {
+        if (!isValid() || width <= 0 || height <= 0) return false;
 
         mWidth = width;
         mHeight = height;
@@ -63,11 +63,23 @@
         if (width != mLayerWidth || height != mLayerHeight) {
             int[] layerInfo = new int[2];
 
-            GLES20Canvas.nResizeLayer(mLayer, width, height, layerInfo);
-
-            mLayerWidth = layerInfo[0];
-            mLayerHeight = layerInfo[1];
+            if (GLES20Canvas.nResizeLayer(mLayer, width, height, layerInfo)) {
+                mLayerWidth = layerInfo[0];
+                mLayerHeight = layerInfo[1];
+            } else {
+                // Failure: not enough GPU resources for requested size
+                mLayer = 0;
+                mLayerWidth = 0;
+                mLayerHeight = 0;
+            }
         }
+        return isValid();
+    }
+
+    @Override
+    void setOpaque(boolean isOpaque) {
+        mOpaque = isOpaque;
+        GLES20Canvas.nSetOpaqueLayer(mLayer, isOpaque);
     }
 
     @Override
@@ -98,7 +110,7 @@
     }
 
     @Override
-    void redraw(DisplayList displayList, Rect dirtyRect) {
+    void redrawLater(DisplayList displayList, Rect dirtyRect) {
         GLES20Canvas.nUpdateRenderLayer(mLayer, mCanvas.getRenderer(),
                 ((GLES20DisplayList) displayList).getNativeDisplayList(),
                 dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom);
diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java
index 16a13cf..e863e49 100644
--- a/core/java/android/view/GLES20TextureLayer.java
+++ b/core/java/android/view/GLES20TextureLayer.java
@@ -39,13 +39,7 @@
             mFinalizer = new Finalizer(mLayer);
         } else {
             mFinalizer = null;
-        }        
-    }
-
-    GLES20TextureLayer(SurfaceTexture surface, boolean isOpaque) {
-        this(isOpaque);
-        mSurface = surface;
-        mSurface.attachToGLContext(mTexture);
+        }
     }
 
     @Override
@@ -54,7 +48,8 @@
     }
 
     @Override
-    void resize(int width, int height) {
+    boolean resize(int width, int height) {
+        return isValid();
     }
 
     @Override
@@ -93,11 +88,16 @@
     }
 
     @Override
+    void setOpaque(boolean isOpaque) {
+        throw new UnsupportedOperationException("Use update(int, int, boolean) instead");
+    }
+
+    @Override
     void setTransform(Matrix matrix) {
         GLES20Canvas.nSetTextureLayerTransform(mLayer, matrix.native_instance);
     }
 
     @Override
-    void redraw(DisplayList displayList, Rect dirtyRect) {
+    void redrawLater(DisplayList displayList, Rect dirtyRect) {
     }
 }
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
index 4bbdd4e..9ddb32e 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -482,6 +482,27 @@
         case MotionEvent.ACTION_POINTER_UP:
             mDownFocusX = mLastFocusX = focusX;
             mDownFocusY = mLastFocusY = focusY;
+
+            // Check the dot product of current velocities.
+            // If the pointer that left was opposing another velocity vector, clear.
+            mVelocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity);
+            final int upIndex = ev.getActionIndex();
+            final int id1 = ev.getPointerId(upIndex);
+            final float x1 = mVelocityTracker.getXVelocity(id1);
+            final float y1 = mVelocityTracker.getYVelocity(id1);
+            for (int i = 0; i < count; i++) {
+                if (i == upIndex) continue;
+
+                final int id2 = ev.getPointerId(i);
+                final float x = x1 * mVelocityTracker.getXVelocity(id2);
+                final float y = y1 * mVelocityTracker.getYVelocity(id2);
+
+                final float dot = x + y;
+                if (dot < 0) {
+                    mVelocityTracker.clear();
+                    break;
+                }
+            }
             break;
 
         case MotionEvent.ACTION_DOWN:
diff --git a/core/java/android/view/Gravity.java b/core/java/android/view/Gravity.java
index 4547aa6..9a89fa5 100644
--- a/core/java/android/view/Gravity.java
+++ b/core/java/android/view/Gravity.java
@@ -153,9 +153,8 @@
      *                container.
      * @param layoutDirection The layout direction.
      *
-     * @see {@link View#LAYOUT_DIRECTION_LTR}
-     * @see {@link View#LAYOUT_DIRECTION_RTL}
-     * @hide
+     * @see View#LAYOUT_DIRECTION_LTR
+     * @see View#LAYOUT_DIRECTION_RTL
      */
     public static void apply(int gravity, int w, int h, Rect container,
             Rect outRect, int layoutDirection) {
@@ -291,9 +290,8 @@
      *                container.
      * @param layoutDirection The layout direction.
      *
-     * @see {@link View#LAYOUT_DIRECTION_LTR}
-     * @see {@link View#LAYOUT_DIRECTION_RTL}
-     * @hide
+     * @see View#LAYOUT_DIRECTION_LTR
+     * @see View#LAYOUT_DIRECTION_RTL
      */
     public static void apply(int gravity, int w, int h, Rect container,
                              int xAdj, int yAdj, Rect outRect, int layoutDirection) {
@@ -372,9 +370,8 @@
      * modified if needed to fit in the display.
      * @param layoutDirection The layout direction.
      *
-     * @see {@link View#LAYOUT_DIRECTION_LTR}
-     * @see {@link View#LAYOUT_DIRECTION_RTL}
-     * @hide
+     * @see View#LAYOUT_DIRECTION_LTR
+     * @see View#LAYOUT_DIRECTION_RTL
      */
     public static void applyDisplay(int gravity, Rect display, Rect inoutObj, int layoutDirection) {
         int absGravity = getAbsoluteGravity(gravity, layoutDirection);
@@ -411,7 +408,6 @@
      * @param gravity The gravity to convert to absolute (horizontal) values.
      * @param layoutDirection The layout direction.
      * @return gravity converted to absolute (horizontal) values.
-     * @hide
      */
     public static int getAbsoluteGravity(int gravity, int layoutDirection) {
         int result = gravity;
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index 777552a..eeae3ed 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -132,4 +132,20 @@
      * @see #detachFunctor(int) 
      */
     abstract void attachFunctor(int functor);
+
+    /**
+     * Indicates that the specified layer must be updated as soon as possible.
+     * 
+     * @param layer The layer to update
+     *
+     * @see #clearLayerUpdates()
+     */
+    abstract void pushLayerUpdate(HardwareLayer layer);
+
+    /**
+     * Removes all enqueued layer updates.
+     * 
+     * @see #pushLayerUpdate(HardwareLayer) 
+     */
+    abstract void clearLayerUpdates();
 }
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index e73f7bf..d3bc35a 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -19,6 +19,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
+import android.graphics.Paint;
 import android.graphics.Rect;
 
 /**
@@ -62,6 +63,14 @@
     }
 
     /**
+     * Update the paint used when drawing this layer.
+     *
+     * @param paint The paint used when the layer is drawn into the destination canvas.
+     * @see View#setLayerPaint(android.graphics.Paint)
+     */
+    void setLayerPaint(Paint paint) {}
+
+    /**
      * Returns the minimum width of the layer.
      * 
      * @return The minimum desired width of the hardware layer 
@@ -107,6 +116,13 @@
     }
 
     /**
+     * Sets whether or not this layer should be considered opaque.
+     * 
+     * @param isOpaque True if the layer is opaque, false otherwise
+     */
+    abstract void setOpaque(boolean isOpaque);
+
+    /**
      * Indicates whether this layer can be rendered.
      * 
      * @return True if the layer can be rendered into, false otherwise
@@ -119,8 +135,9 @@
      * 
      * @param width The new desired minimum width for this layer
      * @param height The new desired minimum height for this layer
+     * @return True if the resulting layer is valid, false otherwise
      */
-    abstract void resize(int width, int height);
+    abstract boolean resize(int width, int height);
 
     /**
      * Returns a hardware canvas that can be used to render onto
@@ -136,11 +153,6 @@
     abstract void destroy();
 
     /**
-     * Flush the render queue associated with this layer.
-     */
-    abstract void flush();
-
-    /**
      * This must be invoked before drawing onto this layer.
      * @param currentCanvas
      */
@@ -191,5 +203,10 @@
      *                    execute in this layer
      * @param dirtyRect The dirty region of the layer that needs to be redrawn
      */
-    abstract void redraw(DisplayList displayList, Rect dirtyRect);
+    abstract void redrawLater(DisplayList displayList, Rect dirtyRect);
+
+    /**
+     * Indicates that this layer has lost its underlying storage.
+     */
+    abstract void clearStorage();
 }
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index dab48b1..1c613245 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -21,6 +21,7 @@
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
+import android.opengl.EGL14;
 import android.opengl.GLUtils;
 import android.opengl.ManagedEGLContext;
 import android.os.Handler;
@@ -135,7 +136,30 @@
      * @hide
      */
     public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions";
-    
+
+    /**
+     * Turn on to flash hardware layers when they update.
+     *
+     * Possible values:
+     * "true", to enable hardware layers updates debugging
+     * "false", to disable hardware layers updates debugging
+     *
+     * @hide
+     */
+    public static final String DEBUG_SHOW_LAYERS_UPDATES_PROPERTY =
+            "debug.hwui.show_layers_updates";
+
+    /**
+     * Turn on to show overdraw level.
+     *
+     * Possible values:
+     * "true", to enable overdraw debugging
+     * "false", to disable overdraw debugging
+     *
+     * @hide
+     */
+    public static final String DEBUG_SHOW_OVERDRAW_PROPERTY = "debug.hwui.show_overdraw";
+
     /**
      * A process can set this flag to false to prevent the use of hardware
      * rendering.
@@ -197,18 +221,18 @@
     /**
      * Initializes the hardware renderer for the specified surface.
      * 
-     * @param holder The holder for the surface to hardware accelerate.
+     * @param surface The surface to hardware accelerate
      * 
      * @return True if the initialization was successful, false otherwise.
      */
-    abstract boolean initialize(SurfaceHolder holder) throws Surface.OutOfResourcesException;
+    abstract boolean initialize(Surface surface) throws Surface.OutOfResourcesException;
     
     /**
      * Updates the hardware renderer for the specified surface.
-     * 
-     * @param holder The holder for the surface to hardware accelerate
+     *
+     * @param surface The surface to hardware accelerate
      */
-    abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException;
+    abstract void updateSurface(Surface surface) throws Surface.OutOfResourcesException;
 
     /**
      * Destroys the layers used by the specified view hierarchy.
@@ -228,10 +252,10 @@
     /**
      * This method should be invoked whenever the current hardware renderer
      * context should be reset.
-     * 
-     * @param holder The holder for the surface to hardware accelerate
+     *
+     * @param surface The surface to hardware accelerate
      */
-    abstract void invalidate(SurfaceHolder holder);
+    abstract void invalidate(Surface surface);
 
     /**
      * This method should be invoked to ensure the hardware renderer is in
@@ -358,6 +382,14 @@
     private static native void nDisableVsync();
 
     /**
+     * Indicates that the specified hardware layer needs to be updated
+     * as soon as possible.
+     * 
+     * @param layer The hardware layer that needs an update
+     */
+    abstract void pushLayerUpdate(HardwareLayer layer);
+
+    /**
      * Interface used to receive callbacks whenever a view is drawn by
      * a hardware renderer instance.
      */
@@ -474,18 +506,23 @@
      *
      * @param width The width of the drawing surface.
      * @param height The height of the drawing surface.
-     * @param holder The target surface
+     * @param surface The surface to hardware accelerate
+     *                
+     * @return true if the surface was initialized, false otherwise. Returning
+     *         false might mean that the surface was already initialized.
      */
-    void initializeIfNeeded(int width, int height, SurfaceHolder holder)
+    boolean initializeIfNeeded(int width, int height, Surface surface)
             throws Surface.OutOfResourcesException {
         if (isRequested()) {
             // We lost the gl context, so recreate it.
             if (!isEnabled()) {
-                if (initialize(holder)) {
+                if (initialize(surface)) {
                     setup(width, height);
+                    return true;
                 }
             }
-        }        
+        }
+        return false;
     }
 
     /**
@@ -577,12 +614,6 @@
 
     @SuppressWarnings({"deprecation"})
     static abstract class GlRenderer extends HardwareRenderer {
-        // These values are not exposed in our EGL APIs
-        static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
-        static final int EGL_OPENGL_ES2_BIT = 4;
-        static final int EGL_SURFACE_TYPE = 0x3033;
-        static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;        
-
         static final int SURFACE_STATE_ERROR = 0;
         static final int SURFACE_STATE_SUCCESS = 1;
         static final int SURFACE_STATE_UPDATED = 2;
@@ -629,6 +660,7 @@
         int mProfileCurrentFrame = -PROFILE_FRAME_DATA_COUNT;
         
         final boolean mDebugDirtyRegions;
+        final boolean mShowOverdraw;
 
         final int mGlVersion;
         final boolean mTranslucent;
@@ -678,6 +710,9 @@
             if (mDebugDirtyRegions) {
                 Log.d(LOG_TAG, "Debugging dirty regions");
             }
+
+            mShowOverdraw = SystemProperties.getBoolean(
+                    HardwareRenderer.DEBUG_SHOW_OVERDRAW_PROPERTY, false);
         }
 
         @Override
@@ -721,13 +756,17 @@
          */
         void checkEglErrors() {
             if (isEnabled()) {
-                int error = sEgl.eglGetError();
-                if (error != EGL_SUCCESS) {
-                    // something bad has happened revert to
-                    // normal rendering.
-                    Log.w(LOG_TAG, "EGL error: " + GLUtils.getEGLErrorString(error));
-                    fallback(error != EGL11.EGL_CONTEXT_LOST);
-                }
+                checkEglErrorsForced();
+            }
+        }
+
+        private void checkEglErrorsForced() {
+            int error = sEgl.eglGetError();
+            if (error != EGL_SUCCESS) {
+                // something bad has happened revert to
+                // normal rendering.
+                Log.w(LOG_TAG, "EGL error: " + GLUtils.getEGLErrorString(error));
+                fallback(error != EGL11.EGL_CONTEXT_LOST);
             }
         }
 
@@ -742,10 +781,10 @@
         }
 
         @Override
-        boolean initialize(SurfaceHolder holder) throws Surface.OutOfResourcesException {
+        boolean initialize(Surface surface) throws Surface.OutOfResourcesException {
             if (isRequested() && !isEnabled()) {
                 initializeEgl();
-                mGl = createEglSurface(holder);
+                mGl = createEglSurface(surface);
                 mDestroyed = false;
 
                 if (mGl != null) {
@@ -771,9 +810,9 @@
         }
         
         @Override
-        void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException {
+        void updateSurface(Surface surface) throws Surface.OutOfResourcesException {
             if (isRequested() && isEnabled()) {
-                createEglSurface(holder);
+                createEglSurface(surface);
             }
         }
 
@@ -800,7 +839,9 @@
                         throw new RuntimeException("eglInitialize failed " +
                                 GLUtils.getEGLErrorString(sEgl.eglGetError()));
                     }
-        
+
+                    checkEglErrorsForced();
+
                     sEglConfig = chooseEglConfig();
                     if (sEglConfig == null) {
                         // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
@@ -884,11 +925,20 @@
             sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_STENCIL_SIZE, value);
             Log.d(LOG_TAG, "  STENCIL_SIZE = " + value[0]);
 
+            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SAMPLE_BUFFERS, value);
+            Log.d(LOG_TAG, "  SAMPLE_BUFFERS = " + value[0]);
+
+            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SAMPLES, value);
+            Log.d(LOG_TAG, "  SAMPLES = " + value[0]);
+
             sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SURFACE_TYPE, value);
             Log.d(LOG_TAG, "  SURFACE_TYPE = 0x" + Integer.toHexString(value[0]));
+
+            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_CONFIG_CAVEAT, value);
+            Log.d(LOG_TAG, "  CONFIG_CAVEAT = 0x" + Integer.toHexString(value[0]));
         }
 
-        GL createEglSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException {
+        GL createEglSurface(Surface surface) throws Surface.OutOfResourcesException {
             // Check preconditions.
             if (sEgl == null) {
                 throw new RuntimeException("egl not initialized");
@@ -908,23 +958,12 @@
             destroySurface();
 
             // Create an EGL surface we can render into.
-            if (!createSurface(holder)) {
+            if (!createSurface(surface)) {
                 return null;
             }
 
-            /*
-             * Before we can issue GL commands, we need to make sure
-             * the context is current and bound to a surface.
-             */
-            if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
-                throw new Surface.OutOfResourcesException("eglMakeCurrent failed "
-                        + GLUtils.getEGLErrorString(sEgl.eglGetError()));
-            }
-            
             initCaches();
 
-            enableDirtyRegions();
-
             return mEglContext.getGL();
         }
 
@@ -949,10 +988,17 @@
         abstract void initCaches();
 
         EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
-            int[] attribs = { EGL_CONTEXT_CLIENT_VERSION, mGlVersion, EGL_NONE };
+            int[] attribs = { EGL14.EGL_CONTEXT_CLIENT_VERSION, mGlVersion, EGL_NONE };
 
-            return egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT,
-                    mGlVersion != 0 ? attribs : null);            
+            EGLContext context = egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT,
+                    mGlVersion != 0 ? attribs : null);
+            if (context == null || context == EGL_NO_CONTEXT) {
+                //noinspection ConstantConditions
+                throw new IllegalStateException(
+                        "Could not create an EGL context. eglCreateContext failed with error: " +
+                        GLUtils.getEGLErrorString(sEgl.eglGetError()));
+            }
+            return context;
         }
 
         @Override
@@ -982,7 +1028,7 @@
         }
 
         @Override
-        void invalidate(SurfaceHolder holder) {
+        void invalidate(Surface surface) {
             // Cancels any existing buffer to ensure we'll get a buffer
             // of the right size before we call eglSwapBuffers
             sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
@@ -993,8 +1039,8 @@
                 setEnabled(false);
             }
 
-            if (holder.getSurface().isValid()) {
-                if (!createSurface(holder)) {
+            if (surface.isValid()) {
+                if (!createSurface(surface)) {
                     return;
                 }
 
@@ -1006,8 +1052,8 @@
             }
         }
 
-        private boolean createSurface(SurfaceHolder holder) {
-            mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, holder, null);
+        private boolean createSurface(Surface surface) {
+            mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, surface, null);
 
             if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
                 int error = sEgl.eglGetError();
@@ -1018,6 +1064,14 @@
                 throw new RuntimeException("createWindowSurface failed "
                         + GLUtils.getEGLErrorString(error));
             }
+
+            if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
+                throw new IllegalStateException("eglMakeCurrent failed " +
+                        GLUtils.getEGLErrorString(sEgl.eglGetError()));
+            }
+
+            enableDirtyRegions();
+
             return true;
         }
 
@@ -1089,7 +1143,7 @@
                 attachInfo.mIgnoreDirtyState = true;
                 attachInfo.mDrawingTime = SystemClock.uptimeMillis();
 
-                view.mPrivateFlags |= View.DRAWN;
+                view.mPrivateFlags |= View.PFLAG_DRAWN;
 
                 final int surfaceState = checkCurrent();
                 if (surfaceState != SURFACE_STATE_ERROR) {
@@ -1118,14 +1172,13 @@
                         }
                     }
 
-                    int status = onPreDraw(dirty);
-                    int saveCount = canvas.save();
-                    callbacks.onHardwarePreDraw(canvas);
+                    int saveCount = 0;
+                    int status = DisplayList.STATUS_DONE;
 
                     try {
-                        view.mRecreateDisplayList =
-                                (view.mPrivateFlags & View.INVALIDATED) == View.INVALIDATED;
-                        view.mPrivateFlags &= ~View.INVALIDATED;
+                        view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
+                                == View.PFLAG_INVALIDATED;
+                        view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
 
                         long getDisplayListStartTime = 0;
                         if (mProfileEnabled) {
@@ -1137,8 +1190,9 @@
                             getDisplayListStartTime = System.nanoTime();
                         }
 
-                        DisplayList displayList;
+                        canvas.clearLayerUpdates();
 
+                        DisplayList displayList;
                         Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
                         try {
                             displayList = view.getDisplayList();
@@ -1146,6 +1200,15 @@
                             Trace.traceEnd(Trace.TRACE_TAG_VIEW);
                         }
 
+                        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "prepareFrame");
+                        try {
+                            status = onPreDraw(dirty);
+                        } finally {
+                            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+                        }
+                        saveCount = canvas.save();
+                        callbacks.onHardwarePreDraw(canvas);
+
                         if (mProfileEnabled) {
                             long now = System.nanoTime();
                             float total = (now - getDisplayListStartTime) * 0.000001f;
@@ -1378,15 +1441,17 @@
         @Override
         int[] getConfig(boolean dirtyRegions) {
             return new int[] {
-                    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+                    EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
                     EGL_RED_SIZE, 8,
                     EGL_GREEN_SIZE, 8,
                     EGL_BLUE_SIZE, 8,
                     EGL_ALPHA_SIZE, 8,
                     EGL_DEPTH_SIZE, 0,
-                    EGL_STENCIL_SIZE, GLES20Canvas.getStencilSize(),
+                    EGL_CONFIG_CAVEAT, EGL_NONE,
+                    // TODO: Find a better way to choose the stencil size
+                    EGL_STENCIL_SIZE, mShowOverdraw ? GLES20Canvas.getStencilSize() : 0,
                     EGL_SURFACE_TYPE, EGL_WINDOW_BIT |
-                            (dirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0),
+                            (dirtyRegions ? EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0),
                     EGL_NONE
             };
         }
@@ -1431,6 +1496,11 @@
         }
 
         @Override
+        void pushLayerUpdate(HardwareLayer layer) {
+            mGlCanvas.pushLayerUpdate(layer);
+        }
+
+        @Override
         public DisplayList createDisplayList(String name) {
             return new GLES20DisplayList(name);
         }
@@ -1456,27 +1526,6 @@
         }
 
         @Override
-        void destroyLayers(View view) {
-            if (view != null && isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) {
-                destroyHardwareLayer(view);
-                GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
-            }
-        }
-
-        private static void destroyHardwareLayer(View view) {
-            view.destroyLayer(true);
-
-            if (view instanceof ViewGroup) {
-                ViewGroup group = (ViewGroup) view;
-
-                int count = group.getChildCount();
-                for (int i = 0; i < count; i++) {
-                    destroyHardwareLayer(group.getChildAt(i));
-                }
-            }
-        }
-
-        @Override
         boolean safelyRun(Runnable action) {
             boolean needsContext = true;
             if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false;
@@ -1501,11 +1550,43 @@
         }
 
         @Override
+        void destroyLayers(final View view) {
+            if (view != null) {
+                safelyRun(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (mCanvas != null) {
+                            mCanvas.clearLayerUpdates();
+                        }
+                        destroyHardwareLayer(view);
+                        GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
+                    }
+                });
+            }
+        }
+
+        private static void destroyHardwareLayer(View view) {
+            view.destroyLayer(true);
+
+            if (view instanceof ViewGroup) {
+                ViewGroup group = (ViewGroup) view;
+
+                int count = group.getChildCount();
+                for (int i = 0; i < count; i++) {
+                    destroyHardwareLayer(group.getChildAt(i));
+                }
+            }
+        }
+
+        @Override
         void destroyHardwareResources(final View view) {
             if (view != null) {
                 safelyRun(new Runnable() {
                     @Override
                     public void run() {
+                        if (mCanvas != null) {
+                            mCanvas.clearLayerUpdates();
+                        }
                         destroyResources(view);
                         GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
                     }
diff --git a/core/java/android/view/IDisplayContentChangeListener.aidl b/core/java/android/view/IDisplayContentChangeListener.aidl
new file mode 100644
index 0000000..ef7edea
--- /dev/null
+++ b/core/java/android/view/IDisplayContentChangeListener.aidl
@@ -0,0 +1,33 @@
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.view;
+
+import android.os.IBinder;
+import android.view.WindowInfo;
+import android.graphics.Rect;
+
+/**
+ * Interface for observing content changes on a display.
+ *
+ * {@hide}
+ */
+oneway interface IDisplayContentChangeListener {
+    void onWindowTransition(int displayId, int transition, in WindowInfo info);
+    void onRectangleOnScreenRequested(int displayId, in Rect rectangle, boolean immediate);
+    void onWindowLayersChanged(int displayId);
+    void onRotationChanged(int rotation);
+}
diff --git a/core/java/android/view/IInputFilter.aidl b/core/java/android/view/IInputFilter.aidl
new file mode 100644
index 0000000..fead5f6
--- /dev/null
+++ b/core/java/android/view/IInputFilter.aidl
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.view.IInputFilterHost;
+import android.view.InputEvent;
+
+/**
+ * Interface for implementing an filter which observes and
+ * potentially transforms the input event stream in the system.
+ *
+ * @hide
+ */
+oneway interface IInputFilter {
+    void install(IInputFilterHost host);
+    void uninstall();
+    void filterInputEvent(in InputEvent event, int policyFlags);
+}
diff --git a/core/java/android/view/IInputFilterHost.aidl b/core/java/android/view/IInputFilterHost.aidl
new file mode 100644
index 0000000..93b8239
--- /dev/null
+++ b/core/java/android/view/IInputFilterHost.aidl
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.view.InputEvent;
+
+/**
+ * Interface for calls from an input filter to its host.
+ *
+ * @hide
+ */
+oneway interface IInputFilterHost {
+    void sendInputEvent(in InputEvent event, int policyFlags);
+}
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index b4caad3..15bd46c 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -45,8 +45,9 @@
      */
     void executeCommand(String command, String parameters, in ParcelFileDescriptor descriptor);
 
-    void resized(int w, int h, in Rect contentInsets,
+    void resized(in Rect frame, in Rect contentInsets,
             in Rect visibleInsets, boolean reportDraw, in Configuration newConfig);
+    void moved(int newX, int newY);
     void dispatchAppVisibility(boolean visible);
     void dispatchGetNewSurface();
     void dispatchScreenState(boolean on);
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 4d4eec7..0fe2a8e3 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -1,16 +1,16 @@
 /*
 ** Copyright 2006, The Android Open Source Project
 **
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
+** 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 
+**     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 
+** 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.
 */
 
@@ -23,8 +23,11 @@
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Bundle;
 import android.os.IRemoteCallback;
 import android.view.IApplicationToken;
+import android.view.IDisplayContentChangeListener;
 import android.view.IOnKeyguardExitResult;
 import android.view.IRotationWatcher;
 import android.view.IWindowSession;
@@ -33,6 +36,8 @@
 import android.view.MotionEvent;
 import android.view.InputChannel;
 import android.view.InputDevice;
+import android.view.IInputFilter;
+import android.view.WindowInfo;
 
 /**
  * System private interface to the window manager.
@@ -54,14 +59,11 @@
     IWindowSession openSession(in IInputMethodClient client,
             in IInputContext inputContext);
     boolean inputMethodClientHasFocus(IInputMethodClient client);
-    
-    void getDisplaySize(out Point size);
-    void getRealDisplaySize(out Point size);
-    int getMaximumSizeDimension();
-    void getCurrentSizeRange(out Point smallestSize, out Point largestSize);
 
-    void setForcedDisplaySize(int longDimen, int shortDimen);
-    void clearForcedDisplaySize();
+    void setForcedDisplaySize(int displayId, int width, int height);
+    void clearForcedDisplaySize(int displayId);
+    void setForcedDisplayDensity(int displayId, int density);
+    void clearForcedDisplayDensity(int displayId);
 
     // Is the device configured to have a full system bar for larger screens?
     boolean hasSystemNavBar();
@@ -73,7 +75,7 @@
     void addWindowToken(IBinder token, int type);
     void removeWindowToken(IBinder token);
     void addAppToken(int addPos, IApplicationToken token,
-            int groupId, int requestedOrientation, boolean fullscreen);
+            int groupId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked);
     void setAppGroupId(IBinder token, int groupId);
     void setAppOrientation(IApplicationToken token, int requestedOrientation);
     int getAppOrientation(IApplicationToken token);
@@ -85,7 +87,7 @@
     void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
             int startHeight);
     void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
-            IRemoteCallback startedCallback, boolean delayed);
+            IRemoteCallback startedCallback, boolean scaleUp);
     void executeAppTransition();
     void setAppStartingWindow(IBinder token, String pkg, int theme,
             in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
@@ -105,7 +107,10 @@
     Configuration updateOrientationFromAppTokens(in Configuration currentConfig,
             IBinder freezeThisOneIfNeeded);
     void setNewConfiguration(in Configuration config);
-    
+
+    void startFreezingScreen(int exitAnim, int enterAnim);
+    void stopFreezingScreen();
+
     // these require DISABLE_KEYGUARD permission
     void disableKeyguard(IBinder token, String tag);
     void reenableKeyguard(IBinder token);
@@ -116,13 +121,13 @@
     void dismissKeyguard();
 
     void closeSystemDialogs(String reason);
-    
+
     // These can only be called with the SET_ANIMATON_SCALE permission.
     float getAnimationScale(int which);
     float[] getAnimationScales();
     void setAnimationScale(int which, float scale);
     void setAnimationScales(in float[] scales);
-    
+
     // For testing
     void setInTouchMode(boolean showFocus);
 
@@ -156,7 +161,7 @@
      * {@link android.view.Surface}.
      */
     int getRotation();
-    
+
     /**
      * Watch the rotation of the screen.  Returns the current rotation,
      * calls back when it changes.
@@ -170,24 +175,24 @@
      */
     int getPreferredOptionsPanelGravity();
 
-	/**
-	 * Lock the device orientation to the specified rotation, or to the
-	 * current rotation if -1.  Sensor input will be ignored until
-	 * thawRotation() is called.
-	 * @hide
-	 */
-	void freezeRotation(int rotation);
+    /**
+     * Lock the device orientation to the specified rotation, or to the
+     * current rotation if -1.  Sensor input will be ignored until
+     * thawRotation() is called.
+     * @hide
+     */
+    void freezeRotation(int rotation);
 
-	/**
-	 * Release the orientation lock imposed by freezeRotation().
-	 * @hide
-	 */
-	void thawRotation();
+    /**
+     * Release the orientation lock imposed by freezeRotation().
+     * @hide
+     */
+    void thawRotation();
 
-	/**
-	 * Create a screenshot of the applications currently displayed.
-	 */
-	Bitmap screenshotApplications(IBinder appToken, int maxWidth, int maxHeight);
+    /**
+     * Create a screenshot of the applications currently displayed.
+     */
+    Bitmap screenshotApplications(IBinder appToken, int displayId, int maxWidth, int maxHeight);
 
     /**
      * Called by the status bar to notify Views of changes to System UI visiblity.
@@ -196,8 +201,9 @@
 
     /**
      * Block until the given window has been drawn to the screen.
+     * Returns true if really waiting, false if the window does not exist.
      */
-    void waitForWindowDrawn(IBinder token, in IRemoteCallback callback);
+    boolean waitForWindowDrawn(IBinder token, in IRemoteCallback callback);
 
     /**
      * Device has a software navigation bar (separate from the status bar).
@@ -205,7 +211,58 @@
     boolean hasNavigationBar();
 
     /**
-     * Lock the device immediately.
+     * Lock the device immediately with the specified options (can be null).
      */
-    void lockNow();
+    void lockNow(in Bundle options);
+
+    /**
+     * Gets the token for the focused window.
+     */
+    IBinder getFocusedWindowToken();
+
+    /**
+     * Gets the compatibility scale of e window given its token.
+     */
+    float getWindowCompatibilityScale(IBinder windowToken);
+
+    /**
+     * Sets an input filter for manipulating the input event stream.
+     */
+    void setInputFilter(in IInputFilter filter);
+
+    /**
+     * Sets the scale and offset for implementing accessibility magnification.
+     */
+    void magnifyDisplay(int dipslayId, float scale, float offsetX, float offsetY);
+
+    /**
+     * Adds a listener for display content changes.
+     */
+    void addDisplayContentChangeListener(int displayId, IDisplayContentChangeListener listener);
+
+    /**
+     * Removes a listener for display content changes.
+     */
+    void removeDisplayContentChangeListener(int displayId, IDisplayContentChangeListener listener);
+
+    /**
+     * Gets the info for a window given its token.
+     */
+    WindowInfo getWindowInfo(IBinder token);
+
+    /**
+     * Gets the infos for all visible windows.
+     */
+    void getVisibleWindowsForDisplay(int displayId, out List<WindowInfo> outInfos);
+
+    /**
+     * Device is in safe mode.
+     */
+    boolean isSafeModeEnabled();
+
+    /**
+     * Tell keyguard to show the assistant (Intent.ACTION_ASSIST) after asking for the user's
+     * credentials.
+     */
+    void showAssistant();
 }
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index d4a03ce..ff9dcce 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -37,8 +37,13 @@
     int add(IWindow window, int seq, in WindowManager.LayoutParams attrs,
             in int viewVisibility, out Rect outContentInsets,
             out InputChannel outInputChannel);
+    int addToDisplay(IWindow window, int seq, in WindowManager.LayoutParams attrs,
+            in int viewVisibility, in int layerStackId, out Rect outContentInsets,
+            out InputChannel outInputChannel);
     int addWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs,
             in int viewVisibility, out Rect outContentInsets);
+    int addToDisplayWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs,
+            in int viewVisibility, in int layerStackId, out Rect outContentInsets);
     void remove(IWindow window);
     
     /**
@@ -54,8 +59,8 @@
      * @param requestedWidth The width the window wants to be.
      * @param requestedHeight The height the window wants to be.
      * @param viewVisibility Window root view's visibility.
-     * @param flags Request flags: {@link WindowManagerImpl#RELAYOUT_INSETS_PENDING},
-     * {@link WindowManagerImpl#RELAYOUT_DEFER_SURFACE_DESTROY}.
+     * @param flags Request flags: {@link WindowManagerGlobal#RELAYOUT_INSETS_PENDING},
+     * {@link WindowManagerGlobal#RELAYOUT_DEFER_SURFACE_DESTROY}.
      * @param outFrame Rect in which is placed the new position/size on
      * screen.
      * @param outContentInsets Rect in which is placed the offsets from
@@ -74,8 +79,8 @@
      * was last displayed.
      * @param outSurface Object in which is placed the new display surface.
      * 
-     * @return int Result flags: {@link WindowManagerImpl#RELAYOUT_SHOW_FOCUS},
-     * {@link WindowManagerImpl#RELAYOUT_FIRST_TIME}.
+     * @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_SHOW_FOCUS},
+     * {@link WindowManagerGlobal#RELAYOUT_FIRST_TIME}.
      */
     int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs,
             int requestedWidth, int requestedHeight, int viewVisibility,
@@ -172,4 +177,12 @@
             int z, in Bundle extras, boolean sync);
     
     void wallpaperCommandComplete(IBinder window, in Bundle result);
+
+    void setUniverseTransform(IBinder window, float alpha, float offx, float offy,
+            float dsdx, float dtdx, float dsdy, float dtdy);
+
+    /**
+     * Notifies that a rectangle on the screen has been requested.
+     */
+    void onRectangleOnScreenRequested(IBinder token, in Rect rectangle, boolean immediate);
 }
diff --git a/core/java/android/view/InputEventConsistencyVerifier.java b/core/java/android/view/InputEventConsistencyVerifier.java
index fafe416..5dda934 100644
--- a/core/java/android/view/InputEventConsistencyVerifier.java
+++ b/core/java/android/view/InputEventConsistencyVerifier.java
@@ -322,7 +322,7 @@
 
         final int action = event.getAction();
         final boolean newStream = action == MotionEvent.ACTION_DOWN
-                || action == MotionEvent.ACTION_CANCEL;
+                || action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_OUTSIDE;
         if (newStream && (mTouchEventStreamIsTainted || mTouchEventStreamUnhandled)) {
             mTouchEventStreamIsTainted = false;
             mTouchEventStreamUnhandled = false;
diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java
index 9c56782..117c10183 100644
--- a/core/java/android/view/InputEventReceiver.java
+++ b/core/java/android/view/InputEventReceiver.java
@@ -73,7 +73,7 @@
     @Override
     protected void finalize() throws Throwable {
         try {
-            dispose();
+            dispose(true);
         } finally {
             super.finalize();
         }
@@ -83,9 +83,17 @@
      * Disposes the receiver.
      */
     public void dispose() {
+        dispose(false);
+    }
+
+    private void dispose(boolean finalized) {
         if (mCloseGuard != null) {
+            if (finalized) {
+                mCloseGuard.warnIfOpen();
+            }
             mCloseGuard.close();
         }
+
         if (mReceiverPtr != 0) {
             nativeDispose(mReceiverPtr);
             mReceiverPtr = 0;
diff --git a/core/java/android/view/InputFilter.java b/core/java/android/view/InputFilter.java
new file mode 100644
index 0000000..c25b87b
--- /dev/null
+++ b/core/java/android/view/InputFilter.java
@@ -0,0 +1,261 @@
+/*
+ * 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.
+ */
+
+package android.view;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.view.IInputFilter;
+import android.view.InputEvent;
+import android.view.InputEventConsistencyVerifier;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.WindowManagerPolicy;
+
+/**
+ * Filters input events before they are dispatched to the system.
+ * <p>
+ * At most one input filter can be installed by calling
+ * {@link WindowManagerService#setInputFilter}.  When an input filter is installed, the
+ * system's behavior changes as follows:
+ * <ul>
+ * <li>Input events are first delivered to the {@link WindowManagerPolicy}
+ * interception methods before queuing as usual.  This critical step takes care of managing
+ * the power state of the device and handling wake keys.</li>
+ * <li>Input events are then asynchronously delivered to the input filter's
+ * {@link #onInputEvent(InputEvent)} method instead of being enqueued for dispatch to
+ * applications as usual.  The input filter only receives input events that were
+ * generated by input device; the input filter will not receive input events that were
+ * injected into the system by other means, such as by instrumentation.</li>
+ * <li>The input filter processes and optionally transforms the stream of events.  For example,
+ * it may transform a sequence of motion events representing an accessibility gesture into
+ * a different sequence of motion events, key presses or other system-level interactions.
+ * The input filter can send events to be dispatched by calling
+ * {@link #sendInputEvent(InputEvent)} and passing appropriate policy flags for the
+ * input event.</li>
+ * </ul>
+ * </p>
+ * <h3>The importance of input event consistency</h3>
+ * <p>
+ * The input filter mechanism is very low-level.  At a minimum, it needs to ensure that it
+ * sends an internally consistent stream of input events to the dispatcher.  There are
+ * very important invariants to be maintained.
+ * </p><p>
+ * For example, if a key down is sent, a corresponding key up should also be sent eventually.
+ * Likewise, for touch events, each pointer must individually go down with
+ * {@link MotionEvent#ACTION_DOWN} or {@link MotionEvent#ACTION_POINTER_DOWN} and then
+ * individually go up with {@link MotionEvent#ACTION_POINTER_UP} or {@link MotionEvent#ACTION_UP}
+ * and the sequence of pointer ids used must be consistent throughout the gesture.
+ * </p><p>
+ * Sometimes a filter may wish to cancel a previously dispatched key or motion.  It should
+ * use {@link KeyEvent#FLAG_CANCELED} or {@link MotionEvent#ACTION_CANCEL} accordingly.
+ * </p><p>
+ * The input filter must take into account the fact that the input events coming from different
+ * devices or even different sources all consist of distinct streams of input.
+ * Use {@link InputEvent#getDeviceId()} and {@link InputEvent#getSource()} to identify
+ * the source of the event and its semantics.  There are be multiple sources of keys,
+ * touches and other input: they must be kept separate.
+ * </p>
+ * <h3>Policy flags</h3>
+ * <p>
+ * Input events received from the dispatcher and sent to the dispatcher have policy flags
+ * associated with them.  Policy flags control some functions of the dispatcher.
+ * </p><p>
+ * The early policy interception decides whether an input event should be delivered
+ * to applications or dropped.  The policy indicates its decision by setting the
+ * {@link WindowManagerPolicy#FLAG_PASS_TO_USER} policy flag.  The input filter may
+ * sometimes receive events that do not have this flag set.  It should take note of
+ * the fact that the policy intends to drop the event, clean up its state, and
+ * then send appropriate cancellation events to the dispatcher if needed.
+ * </p><p>
+ * For example, suppose the input filter is processing a gesture and one of the touch events
+ * it receives does not have the {@link WindowManagerPolicy#FLAG_PASS_TO_USER} flag set.
+ * The input filter should clear its internal state about the gesture and then send key or
+ * motion events to the dispatcher to cancel any keys or pointers that are down.
+ * </p><p>
+ * Corollary: Events that set sent to the dispatcher should usually include the
+ * {@link WindowManagerPolicy#FLAG_PASS_TO_USER} flag.  Otherwise, they will be dropped!
+ * </p><p>
+ * It may be prudent to disable automatic key repeating for synthetic key events
+ * by setting the {@link WindowManagerPolicy#FLAG_DISABLE_KEY_REPEAT} policy flag.
+ * </p>
+ *
+ * @hide
+ */
+public abstract class InputFilter extends IInputFilter.Stub {
+    private static final int MSG_INSTALL = 1;
+    private static final int MSG_UNINSTALL = 2;
+    private static final int MSG_INPUT_EVENT = 3;
+
+    // Consistency verifiers for debugging purposes.
+    private final InputEventConsistencyVerifier mInboundInputEventConsistencyVerifier =
+            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
+                    new InputEventConsistencyVerifier(this,
+                            InputEventConsistencyVerifier.FLAG_RAW_DEVICE_INPUT,
+                            "InputFilter#InboundInputEventConsistencyVerifier") : null;
+    private final InputEventConsistencyVerifier mOutboundInputEventConsistencyVerifier =
+            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
+                    new InputEventConsistencyVerifier(this,
+                            InputEventConsistencyVerifier.FLAG_RAW_DEVICE_INPUT,
+                            "InputFilter#OutboundInputEventConsistencyVerifier") : null;
+
+    private final H mH;
+
+    private IInputFilterHost mHost;
+
+    /**
+     * Creates the input filter.
+     *
+     * @param looper The looper to run callbacks on.
+     */
+    public InputFilter(Looper looper) {
+        mH = new H(looper);
+    }
+
+    /**
+     * Called when the input filter is installed.
+     * This method is guaranteed to be non-reentrant.
+     *
+     * @param host The input filter host environment.
+     */
+    public final void install(IInputFilterHost host) {
+        mH.obtainMessage(MSG_INSTALL, host).sendToTarget();
+    }
+
+    /**
+     * Called when the input filter is uninstalled.
+     * This method is guaranteed to be non-reentrant.
+     */
+    public final void uninstall() {
+        mH.obtainMessage(MSG_UNINSTALL).sendToTarget();
+    }
+
+    /**
+     * Called to enqueue the input event for filtering.
+     * The event will be recycled after the input filter processes it.
+     * This method is guaranteed to be non-reentrant.
+     *
+     * @param event The input event to enqueue.
+     */
+    final public void filterInputEvent(InputEvent event, int policyFlags) {
+        mH.obtainMessage(MSG_INPUT_EVENT, policyFlags, 0, event).sendToTarget();
+    }
+
+    /**
+     * Sends an input event to the dispatcher.
+     *
+     * @param event The input event to publish.
+     * @param policyFlags The input event policy flags.
+     */
+    public void sendInputEvent(InputEvent event, int policyFlags) {
+        if (event == null) {
+            throw new IllegalArgumentException("event must not be null");
+        }
+        if (mHost == null) {
+            throw new IllegalStateException("Cannot send input event because the input filter " +
+                    "is not installed.");
+        }
+        if (mOutboundInputEventConsistencyVerifier != null) {
+            mOutboundInputEventConsistencyVerifier.onInputEvent(event, 0);
+        }
+        try {
+            mHost.sendInputEvent(event, policyFlags);
+        } catch (RemoteException re) {
+            /* ignore */
+        }
+    }
+
+    /**
+     * Called when an input event has been received from the dispatcher.
+     * <p>
+     * The default implementation sends the input event back to the dispatcher, unchanged.
+     * </p><p>
+     * The event will be recycled when this method returns.  If you want to keep it around,
+     * make a copy!
+     * </p>
+     *
+     * @param event The input event that was received.
+     * @param policyFlags The input event policy flags.
+     */
+    public void onInputEvent(InputEvent event, int policyFlags) {
+        sendInputEvent(event, policyFlags);
+    }
+
+    /**
+     * Called when the filter is installed into the dispatch pipeline.
+     * <p>
+     * This method is called before the input filter receives any input events.
+     * The input filter should take this opportunity to prepare itself.
+     * </p>
+     */
+    public void onInstalled() {
+    }
+
+    /**
+     * Called when the filter is uninstalled from the dispatch pipeline.
+     * <p>
+     * This method is called after the input filter receives its last input event.
+     * The input filter should take this opportunity to clean up.
+     * </p>
+     */
+    public void onUninstalled() {
+    }
+
+    private final class H extends Handler {
+        public H(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_INSTALL:
+                    mHost = (IInputFilterHost) msg.obj;
+                    if (mInboundInputEventConsistencyVerifier != null) {
+                        mInboundInputEventConsistencyVerifier.reset();
+                    }
+                    if (mOutboundInputEventConsistencyVerifier != null) {
+                        mOutboundInputEventConsistencyVerifier.reset();
+                    }
+                    onInstalled();
+                    break;
+
+                case MSG_UNINSTALL:
+                    try {
+                        onUninstalled();
+                    } finally {
+                        mHost = null;
+                    }
+                    break;
+
+                case MSG_INPUT_EVENT: {
+                    final InputEvent event = (InputEvent)msg.obj;
+                    try {
+                        if (mInboundInputEventConsistencyVerifier != null) {
+                            mInboundInputEventConsistencyVerifier.onInputEvent(event, 0);
+                        }
+                        onInputEvent(event, msg.arg1);
+                    } finally {
+                        event.recycle();
+                    }
+                    break;
+                }
+            }
+        }
+    }
+}
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index bcb8800..ee3f5d8 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -17,6 +17,8 @@
 package android.view;
 
 import android.content.Context;
+import android.content.res.Resources;
+import android.os.SystemClock;
 import android.util.FloatMath;
 
 /**
@@ -137,6 +139,18 @@
     private long mPrevTime;
     private boolean mInProgress;
     private int mSpanSlop;
+    private int mMinSpan;
+
+    // Bounds for recently seen values
+    private float mTouchUpper;
+    private float mTouchLower;
+    private float mTouchHistoryLastAccepted;
+    private int mTouchHistoryDirection;
+    private long mTouchHistoryLastAcceptedTime;
+    private int mTouchMinMajor;
+
+    private static final long TOUCH_STABILIZE_TIME = 128; // ms
+    private static final int TOUCH_MIN_MAJOR = 48; // dp
 
     /**
      * Consistency verifier for debugging purposes.
@@ -149,6 +163,83 @@
         mContext = context;
         mListener = listener;
         mSpanSlop = ViewConfiguration.get(context).getScaledTouchSlop() * 2;
+
+        final Resources res = context.getResources();
+        mTouchMinMajor = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.config_minScalingTouchMajor);
+        mMinSpan = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.config_minScalingSpan);
+    }
+
+    /**
+     * The touchMajor/touchMinor elements of a MotionEvent can flutter/jitter on
+     * some hardware/driver combos. Smooth it out to get kinder, gentler behavior.
+     * @param ev MotionEvent to add to the ongoing history
+     */
+    private void addTouchHistory(MotionEvent ev) {
+        final long currentTime = SystemClock.uptimeMillis();
+        final int count = ev.getPointerCount();
+        boolean accept = currentTime - mTouchHistoryLastAcceptedTime >= TOUCH_STABILIZE_TIME;
+        float total = 0;
+        int sampleCount = 0;
+        for (int i = 0; i < count; i++) {
+            final boolean hasLastAccepted = !Float.isNaN(mTouchHistoryLastAccepted);
+            final int historySize = ev.getHistorySize();
+            final int pointerSampleCount = historySize + 1;
+            for (int h = 0; h < pointerSampleCount; h++) {
+                float major;
+                if (h < historySize) {
+                    major = ev.getHistoricalTouchMajor(i, h);
+                } else {
+                    major = ev.getTouchMajor(i);
+                }
+                if (major < mTouchMinMajor) major = mTouchMinMajor;
+                total += major;
+
+                if (Float.isNaN(mTouchUpper) || major > mTouchUpper) {
+                    mTouchUpper = major;
+                }
+                if (Float.isNaN(mTouchLower) || major < mTouchLower) {
+                    mTouchLower = major;
+                }
+
+                if (hasLastAccepted) {
+                    final int directionSig = (int) Math.signum(major - mTouchHistoryLastAccepted);
+                    if (directionSig != mTouchHistoryDirection ||
+                            (directionSig == 0 && mTouchHistoryDirection == 0)) {
+                        mTouchHistoryDirection = directionSig;
+                        final long time = h < historySize ? ev.getHistoricalEventTime(h)
+                                : ev.getEventTime();
+                        mTouchHistoryLastAcceptedTime = time;
+                        accept = false;
+                    }
+                }
+            }
+            sampleCount += pointerSampleCount;
+        }
+
+        final float avg = total / sampleCount;
+
+        if (accept) {
+            float newAccepted = (mTouchUpper + mTouchLower + avg) / 3;
+            mTouchUpper = (mTouchUpper + newAccepted) / 2;
+            mTouchLower = (mTouchLower + newAccepted) / 2;
+            mTouchHistoryLastAccepted = newAccepted;
+            mTouchHistoryDirection = 0;
+            mTouchHistoryLastAcceptedTime = ev.getEventTime();
+        }
+    }
+
+    /**
+     * Clear all touch history tracking. Useful in ACTION_CANCEL or ACTION_UP.
+     * @see #addTouchHistory(MotionEvent)
+     */
+    private void clearTouchHistory() {
+        mTouchUpper = Float.NaN;
+        mTouchLower = Float.NaN;
+        mTouchHistoryLastAccepted = Float.NaN;
+        mTouchHistoryDirection = 0;
+        mTouchHistoryLastAcceptedTime = 0;
     }
 
     /**
@@ -183,11 +274,12 @@
             }
 
             if (streamComplete) {
+                clearTouchHistory();
                 return true;
             }
         }
 
-        final boolean configChanged =
+        final boolean configChanged = action == MotionEvent.ACTION_DOWN ||
                 action == MotionEvent.ACTION_POINTER_UP ||
                 action == MotionEvent.ACTION_POINTER_DOWN;
         final boolean pointerUp = action == MotionEvent.ACTION_POINTER_UP;
@@ -205,12 +297,18 @@
         final float focusX = sumX / div;
         final float focusY = sumY / div;
 
+
+        addTouchHistory(event);
+
         // Determine average deviation from focal point
         float devSumX = 0, devSumY = 0;
         for (int i = 0; i < count; i++) {
             if (skipIndex == i) continue;
-            devSumX += Math.abs(event.getX(i) - focusX);
-            devSumY += Math.abs(event.getY(i) - focusY);
+
+            // Convert the resulting diameter into a radius.
+            final float touchSize = mTouchHistoryLastAccepted / 2;
+            devSumX += Math.abs(event.getX(i) - focusX) + touchSize;
+            devSumY += Math.abs(event.getY(i) - focusY) + touchSize;
         }
         final float devX = devSumX / div;
         final float devY = devSumY / div;
@@ -228,7 +326,7 @@
         final boolean wasInProgress = mInProgress;
         mFocusX = focusX;
         mFocusY = focusY;
-        if (mInProgress && (span == 0 || configChanged)) {
+        if (mInProgress && (span < mMinSpan || configChanged)) {
             mListener.onScaleEnd(this);
             mInProgress = false;
             mInitialSpan = span;
@@ -238,7 +336,7 @@
             mPrevSpanY = mCurrSpanY = spanY;
             mInitialSpan = mPrevSpan = mCurrSpan = span;
         }
-        if (!mInProgress && span != 0 &&
+        if (!mInProgress && span >= mMinSpan &&
                 (wasInProgress || Math.abs(span - mInitialSpan) > mSpanSlop)) {
             mPrevSpanX = mCurrSpanX = spanX;
             mPrevSpanY = mCurrSpanY = spanY;
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index a968768..550a740 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -16,8 +16,16 @@
 
 package android.view;
 
+import dalvik.system.CloseGuard;
+
 import android.content.res.CompatibilityInfo.Translator;
-import android.graphics.*;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.graphics.SurfaceTexture;
+import android.os.IBinder;
 import android.os.Parcelable;
 import android.os.Parcel;
 import android.os.SystemProperties;
@@ -27,212 +35,187 @@
  * Handle onto a raw buffer that is being managed by the screen compositor.
  */
 public class Surface implements Parcelable {
-    private static final String LOG_TAG = "Surface";
-    private static final boolean DEBUG_RELEASE = false;
-    
-    /* orientations for setOrientation() */
-    public static final int ROTATION_0       = 0;
-    public static final int ROTATION_90      = 1;
-    public static final int ROTATION_180     = 2;
-    public static final int ROTATION_270     = 3;
+    private static final String TAG = "Surface";
 
-    private static final boolean headless = "1".equals(
+    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");
+    public static final Parcelable.Creator<Surface> CREATOR =
+            new Parcelable.Creator<Surface>() {
+        public Surface createFromParcel(Parcel source) {
+            try {
+                Surface s = new Surface();
+                s.readFromParcel(source);
+                return s;
+            } catch (Exception e) {
+                Log.e(TAG, "Exception creating surface from parcel", e);
+                return null;
+            }
         }
-    }
+
+        public Surface[] newArray(int size) {
+            return new Surface[size];
+        }
+    };
 
     /**
-     * Create Surface from a {@link SurfaceTexture}.
-     *
-     * Images drawn to the Surface will be made available to the {@link
-     * SurfaceTexture}, which can attach them an OpenGL ES texture via {@link
-     * SurfaceTexture#updateTexImage}.
-     *
-     * @param surfaceTexture The {@link SurfaceTexture} that is updated by this
-     * Surface.
+     * Rotation constant: 0 degree rotation (natural orientation)
      */
-    public Surface(SurfaceTexture surfaceTexture) {
-        checkHeadless();
-
-        if (DEBUG_RELEASE) {
-            mCreationStack = new Exception();
-        }
-        mCanvas = new CompatibleCanvas();
-        initFromSurfaceTexture(surfaceTexture);
-    }
+    public static final int ROTATION_0 = 0;
 
     /**
-     * Does this object hold a valid surface?  Returns true if it holds
-     * a physical surface, so lockCanvas() will succeed.  Otherwise
-     * returns false.
+     * Rotation constant: 90 degree rotation.
      */
-    public native   boolean isValid();
-
-    /** Release the local reference to the server-side surface.  
-     * Always call release() when you're done with a Surface. This will
-     * make the surface invalid.
-     */
-    public native void release();
-
-    /** draw into a surface */
-    public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException, IllegalArgumentException {
-        /*
-         * the dirty rectangle may be expanded to the surface's size, if for
-         * instance it has been resized or if the bits were lost, since the last
-         * call.
-         */
-        return lockCanvasNative(dirty);
-    }
-
-    /** unlock the surface and asks a page flip */
-    public native   void unlockCanvasAndPost(Canvas canvas);
-
-    /** 
-     * unlock the surface. the screen won't be updated until
-     * post() or postAll() is called
-     */
-    public native   void unlockCanvas(Canvas canvas);
-
-    @Override
-    public String toString() {
-        return "Surface(name=" + mName + ", identity=" + getIdentity() + ")";
-    }
-
-    public int describeContents() {
-        return 0;
-    }
-
-    public native   void readFromParcel(Parcel source);
-    public native   void writeToParcel(Parcel dest, int flags);
+    public static final int ROTATION_90 = 1;
 
     /**
-     * Exception thrown when a surface couldn't be created or resized
+     * Rotation constant: 180 degree rotation.
      */
-    public static class OutOfResourcesException extends Exception {
-        public OutOfResourcesException() {
-        }
-        public OutOfResourcesException(String name) {
-            super(name);
-        }
-    }
-    
-    /*
-     * -----------------------------------------------------------------------
-     * No user serviceable parts beyond this point
-     * -----------------------------------------------------------------------
+    public static final int ROTATION_180 = 2;
+
+    /**
+     * Rotation constant: 270 degree rotation.
      */
+    public static final int ROTATION_270 = 3;
 
-    /* flags used in constructor (keep in sync with ISurfaceComposer.h) */
+    /* built-in physical display ids (keep in sync with ISurfaceComposer.h)
+     * these are different from the logical display ids used elsewhere in the framework */
 
-    /** Surface is created hidden @hide */
-    public static final int HIDDEN              = 0x00000004;
+    /**
+     * Built-in physical display id: Main display.
+     * Use only with {@link #getBuiltInDisplay()}.
+     * @hide
+     */
+    public static final int BUILT_IN_DISPLAY_ID_MAIN = 0;
 
-    /** The surface contains secure content, special measures will
-     * be taken to disallow the surface's content to be copied from
-     * another process. In particular, screenshots and VNC servers will
+    /**
+     * Built-in physical display id: Attached HDMI display.
+     * Use only with {@link #getBuiltInDisplay()}.
+     * @hide
+     */
+    public static final int BUILT_IN_DISPLAY_ID_HDMI = 1;
+
+    /* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */
+
+    /**
+     * Surface creation flag: Surface is created hidden
+     * @hide */
+    public static final int HIDDEN = 0x00000004;
+
+    /**
+     * Surface creation flag: The surface contains secure content, special
+     * measures will be taken to disallow the surface's content to be copied
+     * from another process. In particular, screenshots and VNC servers will
      * be disabled, but other measures can take place, for instance the
      * surface might not be hardware accelerated. 
-     * @hide*/
-    public static final int SECURE              = 0x00000080;
-    
-    /** Creates a surface where color components are interpreted as 
-     *  "non pre-multiplied" by their alpha channel. Of course this flag is
-     *  meaningless for surfaces without an alpha channel. By default
-     *  surfaces are pre-multiplied, which means that each color component is
-     *  already multiplied by its alpha value. In this case the blending
-     *  equation used is:
-     *  
-     *    DEST = SRC + DEST * (1-SRC_ALPHA)
-     *    
-     *  By contrast, non pre-multiplied surfaces use the following equation:
-     *  
-     *    DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA)
-     *    
-     *  pre-multiplied surfaces must always be used if transparent pixels are
-     *  composited on top of each-other into the surface. A pre-multiplied
-     *  surface can never lower the value of the alpha component of a given
-     *  pixel.
-     *  
-     *  In some rare situations, a non pre-multiplied surface is preferable.
-     *  
-     *  @hide
+     * @hide
      */
-    public static final int NON_PREMULTIPLIED   = 0x00000100;
-    
+    public static final int SECURE = 0x00000080;
+
     /**
-     * Indicates that the surface must be considered opaque, even if its
-     * pixel format is set to translucent. This can be useful if an
+     * Surface creation flag: Creates a surface where color components are interpreted
+     * as "non pre-multiplied" by their alpha channel. Of course this flag is
+     * meaningless for surfaces without an alpha channel. By default
+     * surfaces are pre-multiplied, which means that each color component is
+     * already multiplied by its alpha value. In this case the blending
+     * equation used is:
+     *
+     *    DEST = SRC + DEST * (1-SRC_ALPHA)
+     *
+     * By contrast, non pre-multiplied surfaces use the following equation:
+     *
+     *    DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA)
+     *
+     * pre-multiplied surfaces must always be used if transparent pixels are
+     * composited on top of each-other into the surface. A pre-multiplied
+     * surface can never lower the value of the alpha component of a given
+     * pixel.
+     *
+     * In some rare situations, a non pre-multiplied surface is preferable.
+     * @hide
+     */
+    public static final int NON_PREMULTIPLIED = 0x00000100;
+
+    /**
+     * Surface creation flag: Indicates that the surface must be considered opaque,
+     * even if its pixel format is set to translucent. This can be useful if an
      * application needs full RGBA 8888 support for instance but will
      * still draw every pixel opaque.
-     * 
      * @hide
      */
-    public static final int OPAQUE              = 0x00000400;
-    
+    public static final int OPAQUE = 0x00000400;
+
     /**
-     * Application requires a hardware-protected path to an
+     * Surface creation flag: Application requires a hardware-protected path to an
      * external display sink. If a hardware-protected path is not available,
      * then this surface will not be displayed on the external sink.
-     *
      * @hide
      */
-    public static final int PROTECTED_APP       = 0x00000800;
+    public static final int PROTECTED_APP = 0x00000800;
 
     // 0x1000 is reserved for an independent DRM protected flag in framework
 
-    /** Creates a normal surface. This is the default. @hide */
+    /**
+     * Surface creation flag: Creates a normal surface.
+     * This is the default.
+     * @hide
+     */
     public static final int FX_SURFACE_NORMAL   = 0x00000000;
-    
-    /** Creates a Blur surface. Everything behind this surface is blurred
-     * by some amount. The quality and refresh speed of the blur effect
-     * is not settable or guaranteed.
-     * It is an error to lock a Blur surface, since it doesn't have
-     * a backing store.
+
+    /**
+     * Surface creation flag: Creates a Blur surface.
+     * Everything behind this surface is blurred by some amount.
+     * The quality and refresh speed of the blur effect is not settable or guaranteed.
+     * It is an error to lock a Blur surface, since it doesn't have a backing store.
      * @hide
      * @deprecated
      */
     @Deprecated
-    public static final int FX_SURFACE_BLUR     = 0x00010000;
-    
-    /** Creates a Dim surface. Everything behind this surface is dimmed
-     * by the amount specified in {@link #setAlpha}.
-     * It is an error to lock a Dim surface, since it doesn't have
-     * a backing store.
+    public static final int FX_SURFACE_BLUR = 0x00010000;
+
+    /**
+     * Surface creation flag: Creates a Dim surface.
+     * Everything behind this surface is dimmed by the amount specified
+     * in {@link #setAlpha}.  It is an error to lock a Dim surface, since it
+     * doesn't have a backing store.
      * @hide
      */
-    public static final int FX_SURFACE_DIM     = 0x00020000;
+    public static final int FX_SURFACE_DIM = 0x00020000;
 
-    /** @hide */
-    public static final int FX_SURFACE_SCREENSHOT   = 0x00030000;
+    /**
+     * @hide
+     */
+    public static final int FX_SURFACE_SCREENSHOT = 0x00030000;
 
-    /** Mask used for FX values above @hide */
-    public static final int FX_SURFACE_MASK     = 0x000F0000;
+    /**
+     * Mask used for FX values above.
+     * @hide
+     */
+    public static final int FX_SURFACE_MASK = 0x000F0000;
 
     /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */
     
-    /** Hide the surface. Equivalent to calling hide(). @hide */
-    public static final int SURFACE_HIDDEN    = 0x01;
-    
-    /** Freeze the surface. Equivalent to calling freeze(). @hide */
-    public static final int SURFACE_FROZEN     = 0x02;
+    /**
+     * Surface flag: Hide the surface.
+     * Equivalent to calling hide().
+     * @hide
+     */
+    public static final int SURFACE_HIDDEN = 0x01;
 
-    /** Enable dithering when compositing this surface @hide */
-    public static final int SURFACE_DITHER    = 0x04;
 
+    private final CloseGuard mCloseGuard = CloseGuard.get();
+    private String mName;
+
+    // Note: These fields are accessed by native code.
     // The mSurfaceControl will only be present for Surfaces used by the window
     // server or system processes. When this class is parceled we defer to the
     // mSurfaceControl to do the parceling. Otherwise we parcel the
     // mNativeSurface.
-    private int mSurfaceControl;
-    private int mSaveCount;
-    private Canvas mCanvas;
-    private int mNativeSurface;
-    private int mSurfaceGenerationId;
-    private String mName;
+    private int mNativeSurface; // Surface*
+    private int mNativeSurfaceControl; // SurfaceControl*
+    private int mGenerationId; // incremented each time mNativeSurface changes
+    private final Canvas mCanvas = new CompatibleCanvas();
+    private int mCanvasSaveCount; // Canvas save count at time of lockCanvas()
 
     // The Translator for density compatibility mode.  This is used for scaling
     // the canvas to perform the appropriate density transformation.
@@ -242,59 +225,441 @@
     // non compatibility mode.
     private Matrix mCompatibleMatrix;
 
-    private Exception mCreationStack;
+    private native void nativeCreate(SurfaceSession session, String name,
+            int w, int h, int format, int flags)
+            throws OutOfResourcesException;
+    private native void nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture)
+            throws OutOfResourcesException;
+    private native void nativeRelease();
+    private native void nativeDestroy();
 
+    private native boolean nativeIsValid();
+    private native int nativeGetIdentity();
+    private native boolean nativeIsConsumerRunningBehind();
 
-    /*
-     * We use a class initializer to allow the native code to cache some
-     * field offsets.
-     */
-    native private static void nativeClassInit();
-    static { nativeClassInit(); }
+    private native Canvas nativeLockCanvas(Rect dirty);
+    private native void nativeUnlockCanvasAndPost(Canvas canvas);
 
-    /** create a surface @hide */
-    public Surface(SurfaceSession s,
-            int pid, int display, int w, int h, int format, int flags)
-        throws OutOfResourcesException {
-        checkHeadless();
+    private static native Bitmap nativeScreenshot(IBinder displayToken,
+            int width, int height, int minLayer, int maxLayer, boolean allLayers);
 
-        if (DEBUG_RELEASE) {
-            mCreationStack = new Exception();
-        }
-        mCanvas = new CompatibleCanvas();
-        init(s,pid,null,display,w,h,format,flags);
-    }
+    private static native void nativeOpenTransaction();
+    private static native void nativeCloseTransaction();
+    private static native void nativeSetAnimationTransaction();
 
-    /** create a surface with a name @hide */
-    public Surface(SurfaceSession s,
-            int pid, String name, int display, int w, int h, int format, int flags)
-        throws OutOfResourcesException {
-        checkHeadless();
+    private native void nativeSetLayer(int zorder);
+    private native void nativeSetPosition(float x, float y);
+    private native void nativeSetSize(int w, int h);
+    private native void nativeSetTransparentRegionHint(Region region);
+    private native void nativeSetAlpha(float alpha);
+    private native void nativeSetMatrix(float dsdx, float dtdx, float dsdy, float dtdy);
+    private native void nativeSetFlags(int flags, int mask);
+    private native void nativeSetWindowCrop(Rect crop);
+    private native void nativeSetLayerStack(int layerStack);
 
-        if (DEBUG_RELEASE) {
-            mCreationStack = new Exception();
-        }
-        mCanvas = new CompatibleCanvas();
-        init(s,pid,name,display,w,h,format,flags);
-        mName = name;
-    }
+    private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
+    private static native IBinder nativeCreateDisplay(String name, boolean secure);
+    private static native void nativeSetDisplaySurface(
+            IBinder displayToken, Surface surface);
+    private static native void nativeSetDisplayLayerStack(
+            IBinder displayToken, int layerStack);
+    private static native void nativeSetDisplayProjection(
+            IBinder displayToken, int orientation, Rect layerStackRect, Rect displayRect);
+    private static native boolean nativeGetDisplayInfo(
+            IBinder displayToken, PhysicalDisplayInfo outInfo);
+    private static native void nativeBlankDisplay(IBinder displayToken);
+    private static native void nativeUnblankDisplay(IBinder displayToken);
+
+    private native void nativeCopyFrom(Surface other);
+    private native void nativeTransferFrom(Surface other);
+    private native void nativeReadFromParcel(Parcel source);
+    private native void nativeWriteToParcel(Parcel dest);
+
 
     /**
-     * Create an empty surface, which will later be filled in by
-     * readFromParcel().
+     * Create an empty surface, which will later be filled in by readFromParcel().
      * @hide
      */
     public Surface() {
         checkHeadless();
 
-        if (DEBUG_RELEASE) {
-            mCreationStack = new Exception();
-        }
-        mCanvas = new CompatibleCanvas();
+        mCloseGuard.open("release");
     }
 
-    private Surface(Parcel source) throws OutOfResourcesException {
-        init(source);
+    /**
+     * Create a surface with a name.
+     *
+     * The surface creation flags specify what kind of surface to create and
+     * certain options such as whether the surface can be assumed to be opaque
+     * and whether it should be initially hidden.  Surfaces should always be
+     * created with the {@link #HIDDEN} flag set to ensure that they are not
+     * made visible prematurely before all of the surface's properties have been
+     * configured.
+     *
+     * Good practice is to first create the surface with the {@link #HIDDEN} flag
+     * specified, open a transaction, set the surface layer, layer stack, alpha,
+     * and position, call {@link #show} if appropriate, and close the transaction.
+     *
+     * @param session The surface session, must not be null.
+     * @param name The surface name, must not be null.
+     * @param w The surface initial width.
+     * @param h The surface initial height.
+     * @param flags The surface creation flags.  Should always include {@link #HIDDEN}
+     * in the creation flags.
+     * @hide
+     */
+    public Surface(SurfaceSession session,
+            String name, int w, int h, int format, int flags)
+            throws OutOfResourcesException {
+        if (session == null) {
+            throw new IllegalArgumentException("session must not be null");
+        }
+        if (name == null) {
+            throw new IllegalArgumentException("name must not be null");
+        }
+
+        if ((flags & HIDDEN) == 0) {
+            Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set "
+                    + "to ensure that they are not made visible prematurely before "
+                    + "all of the surface's properties have been configured.  "
+                    + "Set the other properties and make the surface visible within "
+                    + "a transaction.  New surface name: " + name,
+                    new Throwable());
+        }
+
+        checkHeadless();
+
+        mName = name;
+        nativeCreate(session, name, w, h, format, flags);
+
+        mCloseGuard.open("release");
+    }
+
+    /**
+     * Create Surface from a {@link SurfaceTexture}.
+     *
+     * Images drawn to the Surface will be made available to the {@link
+     * SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link
+     * SurfaceTexture#updateTexImage}.
+     *
+     * @param surfaceTexture The {@link SurfaceTexture} that is updated by this
+     * Surface.
+     */
+    public Surface(SurfaceTexture surfaceTexture) {
+        if (surfaceTexture == null) {
+            throw new IllegalArgumentException("surfaceTexture must not be null");
+        }
+
+        checkHeadless();
+
+        mName = surfaceTexture.toString();
+        try {
+            nativeCreateFromSurfaceTexture(surfaceTexture);
+        } catch (OutOfResourcesException ex) {
+            // We can't throw OutOfResourcesException because it would be an API change.
+            throw new RuntimeException(ex);
+        }
+
+        mCloseGuard.open("release");
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            if (mCloseGuard != null) {
+                mCloseGuard.warnIfOpen();
+            }
+            nativeRelease();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * Release the local reference to the server-side surface.
+     * Always call release() when you're done with a Surface.
+     * This will make the surface invalid.
+     */
+    public void release() {
+        nativeRelease();
+        mCloseGuard.close();
+    }
+
+    /**
+     * Free all server-side state associated with this surface and
+     * release this object's reference.  This method can only be
+     * called from the process that created the service.
+     * @hide
+     */
+    public void destroy() {
+        nativeDestroy();
+        mCloseGuard.close();
+    }
+
+    /**
+     * Returns true if this object holds a valid surface.
+     *
+     * @return True if it holds a physical surface, so lockCanvas() will succeed.
+     * Otherwise returns false.
+     */
+    public boolean isValid() {
+        return nativeIsValid();
+    }
+
+    /**
+     * Gets the generation number of this surface, incremented each time
+     * the native surface contained within this object changes.
+     *
+     * @return The current generation number.
+     * @hide
+     */
+    public int getGenerationId() {
+        return mGenerationId;
+    }
+
+    /**
+     * Returns true if the consumer of this Surface is running behind the producer.
+     *
+     * @return True if the consumer is more than one buffer ahead of the producer.
+     * @hide
+     */
+    public boolean isConsumerRunningBehind() {
+        return nativeIsConsumerRunningBehind();
+    }
+
+    /**
+     * Gets a {@link Canvas} for drawing into this surface.
+     *
+     * After drawing into the provided {@link Canvas}, the caller should
+     * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
+     *
+     * @param dirty A rectangle that represents the dirty region that the caller wants
+     * to redraw.  This function may choose to expand the dirty rectangle if for example
+     * the surface has been resized or if the previous contents of the surface were
+     * not available.  The caller should redraw the entire dirty region as represented
+     * by the contents of the dirty rect upon return from this function.
+     * The caller may also pass <code>null</code> instead, in the case where the
+     * entire surface should be redrawn.
+     * @return A canvas for drawing into the surface.
+     */
+    public Canvas lockCanvas(Rect dirty)
+            throws OutOfResourcesException, IllegalArgumentException {
+        return nativeLockCanvas(dirty);
+    }
+
+    /**
+     * Posts the new contents of the {@link Canvas} to the surface and
+     * releases the {@link Canvas}.
+     *
+     * @param canvas The canvas previously obtained from {@link #lockCanvas}.
+     */
+    public void unlockCanvasAndPost(Canvas canvas) {
+        nativeUnlockCanvasAndPost(canvas);
+    }
+
+    /** 
+     * @deprecated This API has been removed and is not supported.  Do not use.
+     */
+    @Deprecated
+    public void unlockCanvas(Canvas canvas) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Sets the translator used to scale canvas's width/height in compatibility
+     * mode.
+     */
+    void setCompatibilityTranslator(Translator translator) {
+        if (translator != null) {
+            float appScale = translator.applicationScale;
+            mCompatibleMatrix = new Matrix();
+            mCompatibleMatrix.setScale(appScale, appScale);
+        }
+    }
+
+    /**
+     * Like {@link #screenshot(int, int, int, int)} but includes all
+     * Surfaces in the screenshot.
+     *
+     * @hide
+     */
+    public static Bitmap screenshot(int width, int height) {
+        // TODO: should take the display as a parameter
+        IBinder displayToken = getBuiltInDisplay(BUILT_IN_DISPLAY_ID_MAIN);
+        return nativeScreenshot(displayToken, width, height, 0, 0, true);
+    }
+
+    /**
+     * Copy the current screen contents into a bitmap and return it.
+     *
+     * @param width The desired width of the returned bitmap; the raw
+     * screen will be scaled down to this size.
+     * @param height The desired height of the returned bitmap; the raw
+     * screen will be scaled down to this size.
+     * @param minLayer The lowest (bottom-most Z order) surface layer to
+     * include in the screenshot.
+     * @param maxLayer The highest (top-most Z order) surface layer to
+     * include in the screenshot.
+     * @return Returns a Bitmap containing the screen contents, or null
+     * if an error occurs.
+     *
+     * @hide
+     */
+    public static Bitmap screenshot(int width, int height, int minLayer, int maxLayer) {
+        // TODO: should take the display as a parameter
+        IBinder displayToken = getBuiltInDisplay(BUILT_IN_DISPLAY_ID_MAIN);
+        return nativeScreenshot(displayToken, width, height, minLayer, maxLayer, false);
+    }
+
+    /*
+     * set surface parameters.
+     * needs to be inside open/closeTransaction block
+     */
+
+    /** start a transaction @hide */
+    public static void openTransaction() {
+        nativeOpenTransaction();
+    }
+
+    /** end a transaction @hide */
+    public static void closeTransaction() {
+        nativeCloseTransaction();
+    }
+
+    /** flag the transaction as an animation @hide */
+    public static void setAnimationTransaction() {
+        nativeSetAnimationTransaction();
+    }
+
+    /** @hide */
+    public void setLayer(int zorder) {
+        nativeSetLayer(zorder);
+    }
+
+    /** @hide */
+    public void setPosition(int x, int y) {
+        nativeSetPosition((float)x, (float)y);
+    }
+
+    /** @hide */
+    public void setPosition(float x, float y) {
+        nativeSetPosition(x, y);
+    }
+
+    /** @hide */
+    public void setSize(int w, int h) {
+        nativeSetSize(w, h);
+    }
+
+    /** @hide */
+    public void hide() {
+        nativeSetFlags(SURFACE_HIDDEN, SURFACE_HIDDEN);
+    }
+
+    /** @hide */
+    public void show() {
+        nativeSetFlags(0, SURFACE_HIDDEN);
+    }
+
+    /** @hide */
+    public void setTransparentRegionHint(Region region) {
+        nativeSetTransparentRegionHint(region);
+    }
+
+    /** @hide */
+    public void setAlpha(float alpha) {
+        nativeSetAlpha(alpha);
+    }
+
+    /** @hide */
+    public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+        nativeSetMatrix(dsdx, dtdx, dsdy, dtdy);
+    }
+
+    /** @hide */
+    public void setFlags(int flags, int mask) {
+        nativeSetFlags(flags, mask);
+    }
+
+    /** @hide */
+    public void setWindowCrop(Rect crop) {
+        nativeSetWindowCrop(crop);
+    }
+
+    /** @hide */
+    public void setLayerStack(int layerStack) {
+        nativeSetLayerStack(layerStack);
+    }
+
+    /** @hide */
+    public static IBinder getBuiltInDisplay(int builtInDisplayId) {
+        return nativeGetBuiltInDisplay(builtInDisplayId);
+    }
+
+    /** @hide */
+    public static IBinder createDisplay(String name, boolean secure) {
+        if (name == null) {
+            throw new IllegalArgumentException("name must not be null");
+        }
+        return nativeCreateDisplay(name, secure);
+    }
+
+    /** @hide */
+    public static void setDisplaySurface(IBinder displayToken, Surface surface) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        nativeSetDisplaySurface(displayToken, surface);
+    }
+
+    /** @hide */
+    public static void setDisplayLayerStack(IBinder displayToken, int layerStack) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        nativeSetDisplayLayerStack(displayToken, layerStack);
+    }
+
+    /** @hide */
+    public static void setDisplayProjection(IBinder displayToken,
+            int orientation, Rect layerStackRect, Rect displayRect) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        if (layerStackRect == null) {
+            throw new IllegalArgumentException("layerStackRect must not be null");
+        }
+        if (displayRect == null) {
+            throw new IllegalArgumentException("displayRect must not be null");
+        }
+        nativeSetDisplayProjection(displayToken, orientation, layerStackRect, displayRect);
+    }
+
+    /** @hide */
+    public static boolean getDisplayInfo(IBinder displayToken, PhysicalDisplayInfo outInfo) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        if (outInfo == null) {
+            throw new IllegalArgumentException("outInfo must not be null");
+        }
+        return nativeGetDisplayInfo(displayToken, outInfo);
+    }
+
+    /** @hide */
+    public static void blankDisplay(IBinder displayToken) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        nativeBlankDisplay(displayToken);
+    }
+
+    /** @hide */
+    public static void unblankDisplay(IBinder displayToken) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        nativeUnblankDisplay(displayToken);
     }
 
     /**
@@ -306,35 +671,145 @@
      * in to it.
      * @hide
      */
-    public native void copyFrom(Surface o);
+    public void copyFrom(Surface other) {
+        if (other == null) {
+            throw new IllegalArgumentException("other must not be null");
+        }
+        if (other != this) {
+            nativeCopyFrom(other);
+        }
+    }
 
     /**
-     * Transfer the native state from 'o' to this surface, releasing it
-     * from 'o'.  This is for use in the client side for drawing into a
+     * Transfer the native state from 'other' to this surface, releasing it
+     * from 'other'.  This is for use in the client side for drawing into a
      * surface; not guaranteed to work on the window manager side.
      * This is for use by the client to move the underlying surface from
      * one Surface object to another, in particular in SurfaceFlinger.
      * @hide.
      */
-    public native void transferFrom(Surface o);
-
-    /** @hide */
-    public int getGenerationId() {
-        return mSurfaceGenerationId;
+    public void transferFrom(Surface other) {
+        if (other == null) {
+            throw new IllegalArgumentException("other must not be null");
+        }
+        if (other != this) {
+            nativeTransferFrom(other);
+        }
     }
 
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public void readFromParcel(Parcel source) {
+        if (source == null) {
+            throw new IllegalArgumentException("source must not be null");
+        }
+
+        mName = source.readString();
+        nativeReadFromParcel(source);
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (dest == null) {
+            throw new IllegalArgumentException("dest must not be null");
+        }
+
+        dest.writeString(mName);
+        nativeWriteToParcel(dest);
+        if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
+            release();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "Surface(name=" + mName + ", identity=" + nativeGetIdentity() + ")";
+    }
+
+    private static void checkHeadless() {
+        if (HEADLESS) {
+            throw new UnsupportedOperationException("Device is headless");
+        }
+    }
 
     /**
-     * Whether the consumer of this Surface is running behind the producer;
-     * that is, isConsumerRunningBehind() returns true if the consumer is more
-     * than one buffer ahead of the producer.
+     * Exception thrown when a surface couldn't be created or resized.
+     */
+    public static class OutOfResourcesException extends Exception {
+        public OutOfResourcesException() {
+        }
+
+        public OutOfResourcesException(String name) {
+            super(name);
+        }
+    }
+
+    /**
+     * Describes the properties of a physical display known to surface flinger.
      * @hide
      */
-    public native boolean isConsumerRunningBehind();
+    public static final class PhysicalDisplayInfo {
+        public int width;
+        public int height;
+        public float refreshRate;
+        public float density;
+        public float xDpi;
+        public float yDpi;
+        public boolean secure;
+
+        public PhysicalDisplayInfo() {
+        }
+
+        public PhysicalDisplayInfo(PhysicalDisplayInfo other) {
+            copyFrom(other);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o);
+        }
+
+        public boolean equals(PhysicalDisplayInfo other) {
+            return other != null
+                    && width == other.width
+                    && height == other.height
+                    && refreshRate == other.refreshRate
+                    && density == other.density
+                    && xDpi == other.xDpi
+                    && yDpi == other.yDpi
+                    && secure == other.secure;
+        }
+
+        @Override
+        public int hashCode() {
+            return 0; // don't care
+        }
+
+        public void copyFrom(PhysicalDisplayInfo other) {
+            width = other.width;
+            height = other.height;
+            refreshRate = other.refreshRate;
+            density = other.density;
+            xDpi = other.xDpi;
+            yDpi = other.yDpi;
+            secure = other.secure;
+        }
+
+        // For debugging purposes
+        @Override
+        public String toString() {
+            return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, "
+                    + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure
+                    + "}";
+        }
+    }
 
     /**
-     * A Canvas class that can handle the compatibility mode. This does two
-     * things differently.
+     * A Canvas class that can handle the compatibility mode.
+     * This does two things differently.
      * <ul>
      * <li>Returns the width and height of the target metrics, rather than
      * native. For example, the canvas returns 320x480 even if an app is running
@@ -347,7 +822,7 @@
      * that this model does not work, but we hope this works for many apps.
      * </ul>
      */
-    private class CompatibleCanvas extends Canvas {
+    private final class CompatibleCanvas extends Canvas {
         // A temp matrix to remember what an application obtained via {@link getMatrix}
         private Matrix mOrigMatrix = null;
 
@@ -391,172 +866,4 @@
             mOrigMatrix.set(m);
         }
     }
-
-    /**
-     * Sets the translator used to scale canvas's width/height in compatibility
-     * mode.
-     */
-    void setCompatibilityTranslator(Translator translator) {
-        if (translator != null) {
-            float appScale = translator.applicationScale;
-            mCompatibleMatrix = new Matrix();
-            mCompatibleMatrix.setScale(appScale, appScale);
-        }
-    }
-    
-    /** Free all server-side state associated with this surface and
-     * release this object's reference. @hide */
-    public native void destroy();
-    
-    private native Canvas lockCanvasNative(Rect dirty);   
-    
-    /*
-     * set display parameters & screenshots
-     */
-    
-    /**
-     * Freezes the specified display, No updating of the screen will occur
-     * until unfreezeDisplay() is called. Everything else works as usual though,
-     * in particular transactions.
-     * @param display
-     * @hide
-     */
-    public static native   void freezeDisplay(int display);
-
-    /**
-     * resume updating the specified display.
-     * @param display
-     * @hide
-     */
-    public static native   void unfreezeDisplay(int display);
-
-    /**
-     * set the orientation of the given display.
-     * @param display
-     * @param orientation
-     * @param flags Currently unused, set to 0.
-     * @hide
-     */
-    public static native   void setOrientation(int display, int orientation, int flags);
-
-    /**
-     * set the orientation of the given display.
-     * @param display
-     * @param orientation
-     * @hide
-     */
-    public static void setOrientation(int display, int orientation) {
-        setOrientation(display, orientation, 0);
-    }
-    
-    /**
-     * Like {@link #screenshot(int, int, int, int)} but includes all
-     * Surfaces in the screenshot.
-     *
-     * @hide
-     */
-    public static native Bitmap screenshot(int width, int height);
-    
-    /**
-     * Copy the current screen contents into a bitmap and return it.
-     *
-     * @param width The desired width of the returned bitmap; the raw
-     * screen will be scaled down to this size.
-     * @param height The desired height of the returned bitmap; the raw
-     * screen will be scaled down to this size.
-     * @param minLayer The lowest (bottom-most Z order) surface layer to
-     * include in the screenshot.
-     * @param maxLayer The highest (top-most Z order) surface layer to
-     * include in the screenshot.
-     * @return Returns a Bitmap containing the screen contents.
-     *
-     * @hide
-     */
-    public static native Bitmap screenshot(int width, int height, int minLayer, int maxLayer);
-
-    
-    /*
-     * set surface parameters.
-     * needs to be inside open/closeTransaction block
-     */
-    
-    /** start a transaction @hide */
-    public static native   void openTransaction();
-    /** end a transaction @hide */
-    public static native   void closeTransaction();
-    /** @hide */
-    public native   void setLayer(int zorder);
-    /** @hide */
-    public void setPosition(int x, int y) { setPosition((float)x, (float)y); }
-    /** @hide */
-    public native   void setPosition(float x, float y);
-    /** @hide */
-    public native   void setSize(int w, int h);
-    /** @hide */
-    public native   void hide();
-    /** @hide */
-    public native   void show();
-    /** @hide */
-    public native   void setTransparentRegionHint(Region region);
-    /** @hide */
-    public native   void setAlpha(float alpha);
-    /** @hide */
-    public native   void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy);
-    /** @hide */
-    public native   void freeze();
-    /** @hide */
-    public native   void unfreeze();
-    /** @hide */
-    public native   void setFreezeTint(int tint);
-    /** @hide */
-    public native   void setFlags(int flags, int mask);
-    /** @hide */
-    public native   void setWindowCrop(Rect crop);
-
-
-   
-    public static final Parcelable.Creator<Surface> CREATOR
-            = new Parcelable.Creator<Surface>()
-    {
-        public Surface createFromParcel(Parcel source) {
-            try {
-                return new Surface(source);
-            } catch (Exception e) {
-                Log.e(LOG_TAG, "Exception creating surface from parcel", e);
-            }
-            return null;
-        }
-
-        public Surface[] newArray(int size) {
-            return new Surface[size];
-        }
-    };
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            super.finalize();
-        } finally {
-            if (mNativeSurface != 0 || mSurfaceControl != 0) {
-                if (DEBUG_RELEASE) {
-                    Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() (" 
-                            + mNativeSurface + ", " + mSurfaceControl + ")", mCreationStack);
-                } else {
-                    Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() (" 
-                            + mNativeSurface + ", " + mSurfaceControl + ")");
-                }
-            }
-            release();            
-        }
-    }
-    
-    private native void init(SurfaceSession s,
-            int pid, String name, int display, int w, int h, int format, int flags)
-            throws OutOfResourcesException;
-
-    private native void init(Parcel source);
-
-    private native void initFromSurfaceTexture(SurfaceTexture surfaceTexture);
-
-    private native int getIdentity();
 }
diff --git a/core/java/android/view/SurfaceSession.java b/core/java/android/view/SurfaceSession.java
index 2a04675..0dfd94a 100644
--- a/core/java/android/view/SurfaceSession.java
+++ b/core/java/android/view/SurfaceSession.java
@@ -16,34 +16,44 @@
 
 package android.view;
 
-
 /**
  * An instance of this class represents a connection to the surface
- * flinger, in which you can create one or more Surface instances that will
+ * flinger, from which you can create one or more Surface instances that will
  * be composited to the screen.
  * {@hide}
  */
-public class SurfaceSession {
+public final class SurfaceSession {
+    // Note: This field is accessed by native code.
+    private int mNativeClient; // SurfaceComposerClient*
+
+    private static native int nativeCreate();
+    private static native void nativeDestroy(int ptr);
+    private static native void nativeKill(int ptr);
+
     /** Create a new connection with the surface flinger. */
     public SurfaceSession() {
-        init();
+        mNativeClient = nativeCreate();
     }
 
-    /** Forcibly detach native resources associated with this object.
-     *  Unlike destroy(), after this call any surfaces that were created
-     *  from the session will no longer work. The session itself is destroyed.
-     */
-    public native void kill();
-
     /* no user serviceable parts here ... */
     @Override
     protected void finalize() throws Throwable {
-        destroy();
+        try {
+            if (mNativeClient != 0) {
+                nativeDestroy(mNativeClient);
+            }
+        } finally {
+            super.finalize();
+        }
     }
-    
-    private native void init();
-    private native void destroy();
-    
-    private int mClient;
+
+    /**
+     * Forcibly detach native resources associated with this object.
+     * Unlike destroy(), after this call any surfaces that were created
+     * from the session will no longer work.
+     */
+    public void kill() {
+        nativeKill(mNativeClient);
+    }
 }
 
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index ed4c75c..9008521 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -46,13 +46,18 @@
  * 
  * <p>The surface is Z ordered so that it is behind the window holding its
  * SurfaceView; the SurfaceView punches a hole in its window to allow its
- * surface to be displayed.  The view hierarchy will take care of correctly
+ * surface to be displayed. The view hierarchy will take care of correctly
  * compositing with the Surface any siblings of the SurfaceView that would
- * normally appear on top of it.  This can be used to place overlays such as
+ * normally appear on top of it. This can be used to place overlays such as
  * buttons on top of the Surface, though note however that it can have an
  * impact on performance since a full alpha-blended composite will be performed
  * each time the Surface changes.
  * 
+ * <p> The transparent region that makes the surface visible is based on the
+ * layout positions in the view hierarchy. If the post-layout transform
+ * properties are used to draw a sibling view on top of the SurfaceView, the
+ * view may not be properly composited with the surface.
+ *
  * <p>Access to the underlying surface is provided via the SurfaceHolder interface,
  * which can be retrieved by calling {@link #getHolder}.
  * 
@@ -62,14 +67,14 @@
  * Surface is created and destroyed as the window is shown and hidden.
  * 
  * <p>One of the purposes of this class is to provide a surface in which a
- * secondary thread can render into the screen.  If you are going to use it
+ * secondary thread can render into the screen. If you are going to use it
  * this way, you need to be aware of some threading semantics:
  * 
  * <ul>
  * <li> All SurfaceView and
  * {@link SurfaceHolder.Callback SurfaceHolder.Callback} methods will be called
  * from the thread running the SurfaceView's window (typically the main thread
- * of the application).  They thus need to correctly synchronize with any
+ * of the application). They thus need to correctly synchronize with any
  * state that is also touched by the drawing thread.
  * <li> You must ensure that the drawing thread only touches the underlying
  * Surface while it is valid -- between
@@ -296,7 +301,7 @@
         }
         
         boolean opaque = true;
-        if ((mPrivateFlags & SKIP_DRAW) == 0) {
+        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
             // this view draws, remove it from the transparent region
             opaque = super.gatherTransparentRegion(region);
         } else if (region != null) {
@@ -320,7 +325,7 @@
     public void draw(Canvas canvas) {
         if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
             // draw() is not called when SKIP_DRAW is set
-            if ((mPrivateFlags & SKIP_DRAW) == 0) {
+            if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
                 // punch a whole in the view-hierarchy below us
                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
             }
@@ -332,7 +337,7 @@
     protected void dispatchDraw(Canvas canvas) {
         if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
             // if SKIP_DRAW is cleared, draw() has already punched a hole
-            if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+            if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                 // punch a whole in the view-hierarchy below us
                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
             }
@@ -380,7 +385,27 @@
             mLayout.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         }
     }
-    
+
+    /**
+     * Control whether the surface view's content should be treated as secure,
+     * preventing it from appearing in screenshots or from being viewed on
+     * non-secure displays.
+     *
+     * <p>Note that this must be set before the surface view's containing
+     * window is attached to the window manager.
+     *
+     * <p>See {@link android.view.Display#FLAG_SECURE} for details.
+     *
+     * @param isSecure True if the surface view is secure.
+     */
+    public void setSecure(boolean isSecure) {
+        if (isSecure) {
+            mLayout.flags |= WindowManager.LayoutParams.FLAG_SECURE;
+        } else {
+            mLayout.flags &= ~WindowManager.LayoutParams.FLAG_SECURE;
+        }
+    }
+
     /**
      * Hack to allow special layering of windows.  The type is one of the
      * types in WindowManager.LayoutParams.  This is a hack so:
@@ -456,11 +481,12 @@
                 }
 
                 if (mWindow == null) {
+                    Display display = getDisplay();
                     mWindow = new MyWindow(this);
                     mLayout.type = mWindowType;
-                    mLayout.gravity = Gravity.LEFT|Gravity.TOP;
-                    mSession.addWithoutInputChannel(mWindow, mWindow.mSeq, mLayout,
-                            mVisible ? VISIBLE : GONE, mContentInsets);
+                    mLayout.gravity = Gravity.START|Gravity.TOP;
+                    mSession.addToDisplayWithoutInputChannel(mWindow, mWindow.mSeq, mLayout,
+                            mVisible ? VISIBLE : GONE, display.getDisplayId(), mContentInsets);
                 }
                 
                 boolean realSizeChanged;
@@ -480,10 +506,10 @@
                     relayoutResult = mSession.relayout(
                         mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
                             visible ? VISIBLE : GONE,
-                            WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY,
+                            WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY,
                             mWinFrame, mContentInsets,
                             mVisibleInsets, mConfiguration, mNewSurface);
-                    if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
+                    if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
                         mReportDrawNeeded = true;
                     }
 
@@ -516,8 +542,8 @@
 
                     SurfaceHolder.Callback callbacks[] = null;
 
-                    final boolean surfaceChanged =
-                            (relayoutResult&WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED) != 0;
+                    final boolean surfaceChanged = (relayoutResult
+                            & WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED) != 0;
                     if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {
                         mSurfaceCreated = false;
                         if (mSurface.isValid()) {
@@ -615,21 +641,22 @@
             mSurfaceView = new WeakReference<SurfaceView>(surfaceView);
         }
 
-        public void resized(int w, int h, Rect contentInsets,
+        @Override
+        public void resized(Rect frame, Rect contentInsets,
                 Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
             SurfaceView surfaceView = mSurfaceView.get();
             if (surfaceView != null) {
                 if (DEBUG) Log.v(
-                        "SurfaceView", surfaceView + " got resized: w=" +
-                                w + " h=" + h + ", cur w=" + mCurWidth + " h=" + mCurHeight);
+                        "SurfaceView", surfaceView + " got resized: w=" + frame.width()
+                        + " h=" + frame.height() + ", cur w=" + mCurWidth + " h=" + mCurHeight);
                 surfaceView.mSurfaceLock.lock();
                 try {
                     if (reportDraw) {
                         surfaceView.mUpdateWindowNeeded = true;
                         surfaceView.mReportDrawNeeded = true;
                         surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);
-                    } else if (surfaceView.mWinFrame.width() != w
-                            || surfaceView.mWinFrame.height() != h) {
+                    } else if (surfaceView.mWinFrame.width() != frame.width()
+                            || surfaceView.mWinFrame.height() != frame.height()) {
                         surfaceView.mUpdateWindowNeeded = true;
                         surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);
                     }
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index a719a01..230f426 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -189,7 +189,7 @@
         if (opaque != mOpaque) {
             mOpaque = opaque;
             if (mLayer != null) {
-                updateLayer();
+                updateLayerAndInvalidate();
             }
         }
     }
@@ -224,6 +224,9 @@
     private void destroySurface() {
         if (mLayer != null) {
             mSurface.detachFromGLContext();
+            // SurfaceTexture owns the texture name and detachFromGLContext
+            // should have deleted it
+            mLayer.clearStorage();
 
             boolean shouldRelease = true;
             if (mListener != null) {
@@ -290,6 +293,9 @@
      */
     @Override
     public final void draw(Canvas canvas) {
+        // NOTE: Maintain this carefully (see View.java)
+        mPrivateFlags = (mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
+
         applyUpdate();
         applyTransformMatrix();
     }
@@ -309,6 +315,7 @@
         super.onSizeChanged(w, h, oldw, oldh);
         if (mSurface != null) {
             nSetDefaultBufferSize(mSurface, getWidth(), getHeight());
+            updateLayer();
             if (mListener != null) {
                 mListener.onSurfaceTextureSizeChanged(mSurface, getWidth(), getHeight());
             }
@@ -333,6 +340,10 @@
 
     @Override
     HardwareLayer getHardwareLayer() {
+        // NOTE: Maintain these two lines very carefully (see View.java)
+        mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
+        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
+
         if (mLayer == null) {
             if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
                 return null;
@@ -351,9 +362,7 @@
                 public void onFrameAvailable(SurfaceTexture surfaceTexture) {
                     // Per SurfaceTexture's documentation, the callback may be invoked
                     // from an arbitrary thread
-                    synchronized (mLock) {
-                        mUpdateLayer = true;
-                    }
+                    updateLayer();
 
                     if (Looper.myLooper() == Looper.getMainLooper()) {
                         invalidate();
@@ -367,6 +376,7 @@
             if (mListener != null && !mUpdateSurface) {
                 mListener.onSurfaceTextureAvailable(mSurface, getWidth(), getHeight());
             }
+            mLayer.setLayerPaint(mLayerPaint);
         }
 
         if (mUpdateSurface) {
@@ -377,9 +387,7 @@
 
             // Since we are updating the layer, force an update to ensure its
             // parameters are correct (width, height, transform, etc.)
-            synchronized (mLock) {
-                mUpdateLayer = true;
-            }
+            updateLayer();
             mMatrixChanged = true;
 
             mAttachInfo.mHardwareRenderer.setSurfaceTexture(mLayer, mSurface);
@@ -402,7 +410,7 @@
             // updates listener
             if (visibility == VISIBLE) {
                 mSurface.setOnFrameAvailableListener(mUpdateListener);
-                updateLayer();
+                updateLayerAndInvalidate();
             } else {
                 mSurface.setOnFrameAvailableListener(null);
             }
@@ -410,7 +418,15 @@
     }
 
     private void updateLayer() {
-        mUpdateLayer = true;
+        synchronized (mLock) {
+            mUpdateLayer = true;
+        }
+    }
+
+    private void updateLayerAndInvalidate() {
+        synchronized (mLock) {
+            mUpdateLayer = true;
+        }
         invalidate();
     }
 
@@ -534,7 +550,8 @@
      */
     public Bitmap getBitmap(int width, int height) {
         if (isAvailable() && width > 0 && height > 0) {
-            return getBitmap(Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888));
+            return getBitmap(Bitmap.createBitmap(getResources().getDisplayMetrics(),
+                    width, height, Bitmap.Config.ARGB_8888));
         }
         return null;
     }
@@ -765,6 +782,7 @@
          * Invoked when the specified {@link SurfaceTexture} is about to be destroyed.
          * If returns true, no rendering should happen inside the surface texture after this method
          * is invoked. If returns false, the client needs to call {@link SurfaceTexture#release()}.
+         * Most applications should return true.
          * 
          * @param surface The surface about to be destroyed
          */
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f2a80d0..ff44475 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -39,6 +39,7 @@
 import android.graphics.Shader;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManagerGlobal;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -47,9 +48,9 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
-import android.util.LocaleUtil;
 import android.util.Log;
 import android.util.Pool;
 import android.util.Poolable;
@@ -82,14 +83,21 @@
 import com.android.internal.R;
 import com.android.internal.util.Predicate;
 import com.android.internal.view.menu.MenuBuilder;
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
 
 import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.Locale;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * <p>
@@ -343,9 +351,10 @@
  * Padding can be used to offset the content of the view by a specific amount of
  * pixels. For instance, a left padding of 2 will push the view's content by
  * 2 pixels to the right of the left edge. Padding can be set using the
- * {@link #setPadding(int, int, int, int)} method and queried by calling
- * {@link #getPaddingLeft()}, {@link #getPaddingTop()}, {@link #getPaddingRight()},
- * {@link #getPaddingBottom()}.
+ * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
+ * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
+ * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
+ * {@link #getPaddingEnd()}.
  * </p>
  *
  * <p>
@@ -627,6 +636,8 @@
  * @attr ref android.R.styleable#View_paddingLeft
  * @attr ref android.R.styleable#View_paddingRight
  * @attr ref android.R.styleable#View_paddingTop
+ * @attr ref android.R.styleable#View_paddingStart
+ * @attr ref android.R.styleable#View_paddingEnd
  * @attr ref android.R.styleable#View_saveEnabled
  * @attr ref android.R.styleable#View_rotation
  * @attr ref android.R.styleable#View_rotationX
@@ -648,6 +659,7 @@
  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
  * @attr ref android.R.styleable#View_soundEffectsEnabled
  * @attr ref android.R.styleable#View_tag
+ * @attr ref android.R.styleable#View_textAlignment
  * @attr ref android.R.styleable#View_transformPivotX
  * @attr ref android.R.styleable#View_transformPivotY
  * @attr ref android.R.styleable#View_translationX
@@ -656,7 +668,7 @@
  *
  * @see android.view.ViewGroup
  */
-public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Callback,
+public class View implements Drawable.Callback, KeyEvent.Callback,
         AccessibilityEventSource {
     private static final boolean DBG = false;
 
@@ -1003,14 +1015,6 @@
     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
 
     /**
-     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
-     * should add only accessibility focusable Views.
-     *
-     * @hide
-     */
-    public static final int FOCUSABLES_ACCESSIBILITY = 0x00000002;
-
-    /**
      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
      * item.
      */
@@ -1042,58 +1046,6 @@
      */
     public static final int FOCUS_DOWN = 0x00000082;
 
-    // Accessibility focus directions.
-
-    /**
-     * The accessibility focus which is the current user position when
-     * interacting with the accessibility framework.
-     *
-     * @hide
-     */
-    public static final int FOCUS_ACCESSIBILITY =  0x00001000;
-
-    /**
-     * Use with {@link #focusSearch(int)}. Move acessibility focus left.
-     *
-     * @hide
-     */
-    public static final int ACCESSIBILITY_FOCUS_LEFT = FOCUS_LEFT | FOCUS_ACCESSIBILITY;
-
-    /**
-     * Use with {@link #focusSearch(int)}. Move acessibility focus up.
-     *
-     * @hide
-     */
-    public static final int ACCESSIBILITY_FOCUS_UP = FOCUS_UP | FOCUS_ACCESSIBILITY;
-
-    /**
-     * Use with {@link #focusSearch(int)}. Move acessibility focus right.
-     *
-     * @hide
-     */
-    public static final int ACCESSIBILITY_FOCUS_RIGHT = FOCUS_RIGHT | FOCUS_ACCESSIBILITY;
-
-    /**
-     * Use with {@link #focusSearch(int)}. Move acessibility focus down.
-     *
-     * @hide
-     */
-    public static final int ACCESSIBILITY_FOCUS_DOWN = FOCUS_DOWN | FOCUS_ACCESSIBILITY;
-
-    /**
-     * Use with {@link #focusSearch(int)}. Move acessibility focus forward.
-     *
-     * @hide
-     */
-    public static final int ACCESSIBILITY_FOCUS_FORWARD = FOCUS_FORWARD | FOCUS_ACCESSIBILITY;
-
-    /**
-     * Use with {@link #focusSearch(int)}. Move acessibility focus backward.
-     *
-     * @hide
-     */
-    public static final int ACCESSIBILITY_FOCUS_BACKWARD = FOCUS_BACKWARD | FOCUS_ACCESSIBILITY;
-
     /**
      * Bits of {@link #getMeasuredWidthAndState()} and
      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
@@ -1557,7 +1509,7 @@
     private SparseArray<Object> mKeyedTags;
 
     /**
-     * The next available accessiiblity id.
+     * The next available accessibility id.
      */
     private static int sNextAccessibilityViewId;
 
@@ -1623,17 +1575,17 @@
 
     // for mPrivateFlags:
     /** {@hide} */
-    static final int WANTS_FOCUS                    = 0x00000001;
+    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
     /** {@hide} */
-    static final int FOCUSED                        = 0x00000002;
+    static final int PFLAG_FOCUSED                     = 0x00000002;
     /** {@hide} */
-    static final int SELECTED                       = 0x00000004;
+    static final int PFLAG_SELECTED                    = 0x00000004;
     /** {@hide} */
-    static final int IS_ROOT_NAMESPACE              = 0x00000008;
+    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
     /** {@hide} */
-    static final int HAS_BOUNDS                     = 0x00000010;
+    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
     /** {@hide} */
-    static final int DRAWN                          = 0x00000020;
+    static final int PFLAG_DRAWN                       = 0x00000020;
     /**
      * When this flag is set, this view is running an animation on behalf of its
      * children and should therefore not cancel invalidate requests, even if they
@@ -1641,58 +1593,58 @@
      *
      * {@hide}
      */
-    static final int DRAW_ANIMATION                 = 0x00000040;
+    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
     /** {@hide} */
-    static final int SKIP_DRAW                      = 0x00000080;
+    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
     /** {@hide} */
-    static final int ONLY_DRAWS_BACKGROUND          = 0x00000100;
+    static final int PFLAG_ONLY_DRAWS_BACKGROUND       = 0x00000100;
     /** {@hide} */
-    static final int REQUEST_TRANSPARENT_REGIONS    = 0x00000200;
+    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
     /** {@hide} */
-    static final int DRAWABLE_STATE_DIRTY           = 0x00000400;
+    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
     /** {@hide} */
-    static final int MEASURED_DIMENSION_SET         = 0x00000800;
+    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
     /** {@hide} */
-    static final int FORCE_LAYOUT                   = 0x00001000;
+    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
     /** {@hide} */
-    static final int LAYOUT_REQUIRED                = 0x00002000;
+    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
 
-    private static final int PRESSED                = 0x00004000;
+    private static final int PFLAG_PRESSED             = 0x00004000;
 
     /** {@hide} */
-    static final int DRAWING_CACHE_VALID            = 0x00008000;
+    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
     /**
      * Flag used to indicate that this view should be drawn once more (and only once
      * more) after its animation has completed.
      * {@hide}
      */
-    static final int ANIMATION_STARTED              = 0x00010000;
+    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
 
-    private static final int SAVE_STATE_CALLED      = 0x00020000;
+    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
 
     /**
      * Indicates that the View returned true when onSetAlpha() was called and that
      * the alpha must be restored.
      * {@hide}
      */
-    static final int ALPHA_SET                      = 0x00040000;
+    static final int PFLAG_ALPHA_SET                   = 0x00040000;
 
     /**
      * Set by {@link #setScrollContainer(boolean)}.
      */
-    static final int SCROLL_CONTAINER               = 0x00080000;
+    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
 
     /**
      * Set by {@link #setScrollContainer(boolean)}.
      */
-    static final int SCROLL_CONTAINER_ADDED         = 0x00100000;
+    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
 
     /**
      * View flag indicating whether this view was invalidated (fully or partially.)
      *
      * @hide
      */
-    static final int DIRTY                          = 0x00200000;
+    static final int PFLAG_DIRTY                       = 0x00200000;
 
     /**
      * View flag indicating whether this view was invalidated by an opaque
@@ -1700,35 +1652,35 @@
      *
      * @hide
      */
-    static final int DIRTY_OPAQUE                   = 0x00400000;
+    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
 
     /**
-     * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}.
+     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
      *
      * @hide
      */
-    static final int DIRTY_MASK                     = 0x00600000;
+    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
 
     /**
      * Indicates whether the background is opaque.
      *
      * @hide
      */
-    static final int OPAQUE_BACKGROUND              = 0x00800000;
+    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
 
     /**
      * Indicates whether the scrollbars are opaque.
      *
      * @hide
      */
-    static final int OPAQUE_SCROLLBARS              = 0x01000000;
+    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
 
     /**
      * Indicates whether the view is opaque.
      *
      * @hide
      */
-    static final int OPAQUE_MASK                    = 0x01800000;
+    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
 
     /**
      * Indicates a prepressed state;
@@ -1738,27 +1690,27 @@
      *
      * @hide
      */
-    private static final int PREPRESSED             = 0x02000000;
+    private static final int PFLAG_PREPRESSED          = 0x02000000;
 
     /**
      * Indicates whether the view is temporarily detached.
      *
      * @hide
      */
-    static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
+    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
 
     /**
      * Indicates that we should awaken scroll bars once attached
      *
      * @hide
      */
-    private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
+    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
 
     /**
      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
      * @hide
      */
-    private static final int HOVERED              = 0x10000000;
+    private static final int PFLAG_HOVERED             = 0x10000000;
 
     /**
      * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
@@ -1766,10 +1718,10 @@
      *
      * @hide
      */
-    private static final int PIVOT_EXPLICITLY_SET = 0x20000000;
+    private static final int PFLAG_PIVOT_EXPLICITLY_SET = 0x20000000;
 
     /** {@hide} */
-    static final int ACTIVATED                    = 0x40000000;
+    static final int PFLAG_ACTIVATED                   = 0x40000000;
 
     /**
      * Indicates that this view was specifically invalidated, not just dirtied because some
@@ -1779,16 +1731,60 @@
      *
      * @hide
      */
-    static final int INVALIDATED                  = 0x80000000;
+    static final int PFLAG_INVALIDATED                 = 0x80000000;
 
-    /* Masks for mPrivateFlags2 */
+    /**
+     * Masks for mPrivateFlags2, as generated by dumpFlags():
+     *
+     * -------|-------|-------|-------|
+     *                                  PFLAG2_TEXT_ALIGNMENT_FLAGS[0]
+     *                                  PFLAG2_TEXT_DIRECTION_FLAGS[0]
+     *                                1 PFLAG2_DRAG_CAN_ACCEPT
+     *                               1  PFLAG2_DRAG_HOVERED
+     *                               1  PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT
+     *                              11  PFLAG2_TEXT_DIRECTION_MASK_SHIFT
+     *                             1 1  PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT
+     *                             11   PFLAG2_LAYOUT_DIRECTION_MASK
+     *                             11 1 PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
+     *                            1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
+     *                            1   1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT
+     *                            1 1   PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT
+     *                           1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
+     *                           11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
+     *                          1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
+     *                         1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
+     *                         11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
+     *                        1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
+     *                        1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
+     *                        111       PFLAG2_TEXT_DIRECTION_MASK
+     *                       1          PFLAG2_TEXT_DIRECTION_RESOLVED
+     *                      1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
+     *                    111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
+     *                   1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
+     *                  1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
+     *                  11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
+     *                 1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
+     *                 1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
+     *                 11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
+     *                 111              PFLAG2_TEXT_ALIGNMENT_MASK
+     *                1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
+     *               1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
+     *             111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
+     *           11                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
+     *          1                       PFLAG2_HAS_TRANSIENT_STATE
+     *      1                           PFLAG2_ACCESSIBILITY_FOCUSED
+     *     1                            PFLAG2_ACCESSIBILITY_STATE_CHANGED
+     *    1                             PFLAG2_VIEW_QUICK_REJECTED
+     *   1                              PFLAG2_PADDING_RESOLVED
+     * -------|-------|-------|-------|
+     */
 
     /**
      * Indicates that this view has reported that it can accept the current drag's content.
      * Cleared when the drag operation concludes.
      * @hide
      */
-    static final int DRAG_CAN_ACCEPT              = 0x00000001;
+    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
 
     /**
      * Indicates that this view is currently directly under the drag location in a
@@ -1796,33 +1792,29 @@
      * the drag exits the view, or when the drag operation concludes.
      * @hide
      */
-    static final int DRAG_HOVERED                 = 0x00000002;
+    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
 
     /**
      * Horizontal layout direction of this view is from Left to Right.
      * Use with {@link #setLayoutDirection}.
-     * @hide
      */
     public static final int LAYOUT_DIRECTION_LTR = 0;
 
     /**
      * Horizontal layout direction of this view is from Right to Left.
      * Use with {@link #setLayoutDirection}.
-     * @hide
      */
     public static final int LAYOUT_DIRECTION_RTL = 1;
 
     /**
      * Horizontal layout direction of this view is inherited from its parent.
      * Use with {@link #setLayoutDirection}.
-     * @hide
      */
     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}.
-     * @hide
      */
     public static final int LAYOUT_DIRECTION_LOCALE = 3;
 
@@ -1830,32 +1822,33 @@
      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
      * @hide
      */
-    static final int LAYOUT_DIRECTION_MASK_SHIFT = 2;
+    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
 
     /**
      * Mask for use with private flags indicating bits used for horizontal layout direction.
      * @hide
      */
-    static final int LAYOUT_DIRECTION_MASK = 0x00000003 << LAYOUT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
 
     /**
      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
      * right-to-left direction.
      * @hide
      */
-    static final int LAYOUT_DIRECTION_RESOLVED_RTL = 4 << LAYOUT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
 
     /**
      * Indicates whether the view horizontal layout direction has been resolved.
      * @hide
      */
-    static final int LAYOUT_DIRECTION_RESOLVED = 8 << LAYOUT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
 
     /**
      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
      * @hide
      */
-    static final int LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C << LAYOUT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
+            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
 
     /*
      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
@@ -1871,7 +1864,6 @@
 
     /**
      * Default horizontal layout direction.
-     * @hide
      */
     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
 
@@ -1882,12 +1874,10 @@
      *
      * @hide
      */
-    static final int HAS_TRANSIENT_STATE = 0x00000100;
-
+    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x1 << 22;
 
     /**
      * Text direction is inherited thru {@link ViewGroup}
-     * @hide
      */
     public static final int TEXT_DIRECTION_INHERIT = 0;
 
@@ -1895,7 +1885,6 @@
      * 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.
-     * @hide
      */
     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
 
@@ -1903,89 +1892,86 @@
      * 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.
-     * @hide
      */
     public static final int TEXT_DIRECTION_ANY_RTL = 2;
 
     /**
      * Text direction is forced to LTR.
-     * @hide
      */
     public static final int TEXT_DIRECTION_LTR = 3;
 
     /**
      * Text direction is forced to RTL.
-     * @hide
      */
     public static final int TEXT_DIRECTION_RTL = 4;
 
     /**
      * Text direction is coming from the system Locale.
-     * @hide
      */
     public static final int TEXT_DIRECTION_LOCALE = 5;
 
     /**
      * Default text direction is inherited
-     * @hide
      */
-    protected static int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
+    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
 
     /**
      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
      * @hide
      */
-    static final int TEXT_DIRECTION_MASK_SHIFT = 6;
+    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
 
     /**
      * Mask for use with private flags indicating bits used for text direction.
      * @hide
      */
-    static final int TEXT_DIRECTION_MASK = 0x00000007 << TEXT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
+            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
 
     /**
      * Array of text direction flags for mapping attribute "textDirection" to correct
      * flag value.
      * @hide
      */
-    private static final int[] TEXT_DIRECTION_FLAGS = {
-            TEXT_DIRECTION_INHERIT << TEXT_DIRECTION_MASK_SHIFT,
-            TEXT_DIRECTION_FIRST_STRONG << TEXT_DIRECTION_MASK_SHIFT,
-            TEXT_DIRECTION_ANY_RTL << TEXT_DIRECTION_MASK_SHIFT,
-            TEXT_DIRECTION_LTR << TEXT_DIRECTION_MASK_SHIFT,
-            TEXT_DIRECTION_RTL << TEXT_DIRECTION_MASK_SHIFT,
-            TEXT_DIRECTION_LOCALE << TEXT_DIRECTION_MASK_SHIFT
+    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
+            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
     };
 
     /**
      * Indicates whether the view text direction has been resolved.
      * @hide
      */
-    static final int TEXT_DIRECTION_RESOLVED = 0x00000008 << TEXT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
+            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
 
     /**
      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
      * @hide
      */
-    static final int TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
+    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
 
     /**
      * Mask for use with private flags indicating bits used for resolved text direction.
      * @hide
      */
-    static final int TEXT_DIRECTION_RESOLVED_MASK = 0x00000007 << TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
+    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
+            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
 
     /**
      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
      * @hide
      */
-    static final int TEXT_DIRECTION_RESOLVED_DEFAULT =
-            TEXT_DIRECTION_FIRST_STRONG << TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
+    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
+            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
 
     /*
      * Default text alignment. The text alignment of this View is inherited from its parent.
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_INHERIT = 0;
 
@@ -1994,7 +1980,6 @@
      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
      *
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
 
@@ -2002,7 +1987,6 @@
      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
      *
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
 
@@ -2010,7 +1994,6 @@
      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
      *
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
 
@@ -2018,7 +2001,6 @@
      * Center the paragraph, e.g. ALIGN_CENTER.
      *
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_CENTER = 4;
 
@@ -2027,7 +2009,6 @@
      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
      *
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
 
@@ -2036,66 +2017,65 @@
      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
      *
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
 
     /**
      * Default text alignment is inherited
-     * @hide
      */
-    protected static int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
+    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
 
     /**
       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
       * @hide
       */
-    static final int TEXT_ALIGNMENT_MASK_SHIFT = 13;
+    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
 
     /**
       * Mask for use with private flags indicating bits used for text alignment.
       * @hide
       */
-    static final int TEXT_ALIGNMENT_MASK = 0x00000007 << TEXT_ALIGNMENT_MASK_SHIFT;
+    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
 
     /**
      * Array of text direction flags for mapping attribute "textAlignment" to correct
      * flag value.
      * @hide
      */
-    private static final int[] TEXT_ALIGNMENT_FLAGS = {
-            TEXT_ALIGNMENT_INHERIT << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_GRAVITY << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_TEXT_START << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_TEXT_END << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_CENTER << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_VIEW_START << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_VIEW_END << TEXT_ALIGNMENT_MASK_SHIFT
+    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
+            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
     };
 
     /**
      * Indicates whether the view text alignment has been resolved.
      * @hide
      */
-    static final int TEXT_ALIGNMENT_RESOLVED = 0x00000008 << TEXT_ALIGNMENT_MASK_SHIFT;
+    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
 
     /**
      * Bit shift to get the resolved text alignment.
      * @hide
      */
-    static final int TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
+    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
 
     /**
      * Mask for use with private flags indicating bits used for text alignment.
      * @hide
      */
-    static final int TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007 << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
+    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
+            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
 
     /**
      * Indicates whether if the view text alignment has been resolved to gravity
      */
-    public static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT =
-            TEXT_ALIGNMENT_GRAVITY << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
+    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
+            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
 
     // Accessiblity constants for mPrivateFlags2
 
@@ -2103,7 +2083,7 @@
      * Shift for the bits in {@link #mPrivateFlags2} related to the
      * "importantForAccessibility" attribute.
      */
-    static final int IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
+    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
 
     /**
      * Automatically determine whether a view is important for accessibility.
@@ -2121,7 +2101,7 @@
     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
 
     /**
-     * The default whether the view is important for accessiblity.
+     * The default whether the view is important for accessibility.
      */
     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
 
@@ -2129,92 +2109,52 @@
      * Mask for obtainig the bits which specify how to determine
      * whether a view is important for accessibility.
      */
-    static final int IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
+    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO)
-        << IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
 
     /**
      * Flag indicating whether a view has accessibility focus.
      */
-    static final int ACCESSIBILITY_FOCUSED = 0x00000040 << IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x00000040 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
 
     /**
      * Flag indicating whether a view state for accessibility has changed.
      */
-    static final int ACCESSIBILITY_STATE_CHANGED = 0x00000080 << IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+    static final int PFLAG2_ACCESSIBILITY_STATE_CHANGED = 0x00000080
+            << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
 
     /**
      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
      * is used to check whether later changes to the view's transform should invalidate the
      * view to force the quickReject test to run again.
      */
-    static final int VIEW_QUICK_REJECTED = 0x10000000;
-
-    // Accessiblity constants for mPrivateFlags2
+    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
 
     /**
-     * Shift for the bits in {@link #mPrivateFlags2} related to the
-     * "accessibilityFocusable" attribute.
+     * Flag indicating that start/end padding has been resolved into left/right padding
+     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
+     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
+     * during measurement. In some special cases this is required such as when an adapter-based
+     * view measures prospective children without attaching them to a window.
      */
-    static final int ACCESSIBILITY_FOCUSABLE_SHIFT = 29;
+    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
 
     /**
-     * The system determines whether the view can take accessibility focus - default (recommended).
-     * <p>
-     * Such a view is consideted by the focus search if it is:
-     * <ul>
-     * <li>
-     * Important for accessibility and actionable (clickable, long clickable, focusable)
-     * </li>
-     * <li>
-     * Important for accessibility, not actionable (clickable, long clickable, focusable),
-     * and does not have an actionable predecessor.
-     * </li>
-     * </ul>
-     * An accessibility srvice can request putting accessibility focus on such a view.
-     * </p>
-     *
-     * @hide
+     * Flag indicating that the start/end drawables has been resolved into left/right ones.
      */
-    public static final int ACCESSIBILITY_FOCUSABLE_AUTO = 0x00000000;
+    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
 
     /**
-     * The view can take accessibility focus.
-     * <p>
-     * A view that can take accessibility focus is always considered during focus
-     * search and an accessibility service can request putting accessibility focus
-     * on it.
-     * </p>
-     *
-     * @hide
+     * Group of bits indicating that RTL properties resolution is done.
      */
-    public static final int ACCESSIBILITY_FOCUSABLE_YES = 0x00000001;
+    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
+            PFLAG2_TEXT_DIRECTION_RESOLVED |
+            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
+            PFLAG2_PADDING_RESOLVED |
+            PFLAG2_DRAWABLE_RESOLVED;
 
-    /**
-     * The view can not take accessibility focus.
-     * <p>
-     * A view that can not take accessibility focus is never considered during focus
-     * search and an accessibility service can not request putting accessibility focus
-     * on it.
-     * </p>
-     *
-     * @hide
-     */
-    public static final int ACCESSIBILITY_FOCUSABLE_NO = 0x00000002;
-
-    /**
-     * The default whether the view is accessiblity focusable.
-     */
-    static final int ACCESSIBILITY_FOCUSABLE_DEFAULT = ACCESSIBILITY_FOCUSABLE_AUTO;
-
-    /**
-     * Mask for obtainig the bits which specifies how to determine
-     * whether a view is accessibility focusable.
-     */
-    static final int ACCESSIBILITY_FOCUSABLE_MASK = (ACCESSIBILITY_FOCUSABLE_AUTO
-        | ACCESSIBILITY_FOCUSABLE_YES | ACCESSIBILITY_FOCUSABLE_NO)
-        << ACCESSIBILITY_FOCUSABLE_SHIFT;
-
+    // There are a couple of flags left in mPrivateFlags2
 
     /* End of masks for mPrivateFlags2 */
 
@@ -2225,19 +2165,19 @@
      * an animation is cleared between successive frames, in order to tell the associated
      * DisplayList to clear its animation matrix.
      */
-    static final int VIEW_IS_ANIMATING_TRANSFORM = 0x1;
+    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
 
     /**
      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
      * animation is cleared between successive frames, in order to tell the associated
      * DisplayList to restore its alpha value.
      */
-    static final int VIEW_IS_ANIMATING_ALPHA = 0x2;
+    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
 
 
     /* End of masks for mPrivateFlags3 */
 
-    static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
+    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
 
     /**
      * Always allow a user to over-scroll this view, provided it is a
@@ -2511,6 +2451,17 @@
 
     /**
      * @hide
+     *
+     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
+     * out of the public fields to keep the undefined bits out of the developer's way.
+     *
+     * Flag to disable the global search gesture. Don't use this
+     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
+     */
+    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
+
+    /**
+     * @hide
      */
     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
 
@@ -2604,16 +2555,16 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(flagMapping = {
-        @ViewDebug.FlagToString(mask = FORCE_LAYOUT, equals = FORCE_LAYOUT,
+        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
                 name = "FORCE_LAYOUT"),
-        @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED,
+        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
                 name = "LAYOUT_REQUIRED"),
-        @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID,
+        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
             name = "DRAWING_CACHE_INVALID", outputIf = false),
-        @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true),
-        @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false),
-        @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
-        @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY")
+        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
+        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
+        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
+        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
     })
     int mPrivateFlags;
     int mPrivateFlags2;
@@ -2846,14 +2797,14 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(category = "padding")
-    protected int mPaddingLeft;
+    protected int mPaddingLeft = 0;
     /**
      * The right padding in pixels, that is the distance in pixels between the
      * right edge of this view and the right edge of its content.
      * {@hide}
      */
     @ViewDebug.ExportedProperty(category = "padding")
-    protected int mPaddingRight;
+    protected int mPaddingRight = 0;
     /**
      * The top padding in pixels, that is the distance in pixels between the
      * top edge of this view and the top edge of its content.
@@ -2881,6 +2832,23 @@
     private CharSequence mContentDescription;
 
     /**
+     * Specifies the id of a view for which this view serves as a label for
+     * accessibility purposes.
+     */
+    private int mLabelForId = View.NO_ID;
+
+    /**
+     * Predicate for matching labeled view id with its label for
+     * accessibility purposes.
+     */
+    private MatchLabelForPredicate mMatchLabelForPredicate;
+
+    /**
+     * Predicate for matching a view by its id.
+     */
+    private MatchIdPredicate mMatchIdPredicate;
+
+    /**
      * Cache the paddingRight set by the user to append to the scrollbar's size.
      *
      * @hide
@@ -2905,13 +2873,6 @@
     protected int mUserPaddingLeft;
 
     /**
-     * Cache if the user padding is relative.
-     *
-     */
-    @ViewDebug.ExportedProperty(category = "padding")
-    boolean mUserPaddingRelative;
-
-    /**
      * Cache the paddingStart set by the user to append to the scrollbar's size.
      *
      */
@@ -2926,6 +2887,25 @@
     int mUserPaddingEnd;
 
     /**
+     * Cache initial left padding.
+     *
+     * @hide
+     */
+    int mUserPaddingLeftInitial = 0;
+
+    /**
+     * Cache initial right padding.
+     *
+     * @hide
+     */
+    int mUserPaddingRightInitial = 0;
+
+    /**
+     * Default undefined padding
+     */
+    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
+
+    /**
      * @hide
      */
     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
@@ -2934,6 +2914,7 @@
      */
     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
 
+    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
     private Drawable mBackground;
 
     private int mBackgroundResource;
@@ -3218,30 +3199,7 @@
     private boolean mSendingHoverAccessibilityEvents;
 
     /**
-     * Simple constructor to use when creating a view from code.
-     *
-     * @param context The Context the view is running in, through which it can
-     *        access the current theme, resources, etc.
-     */
-    public View(Context context) {
-        mContext = context;
-        mResources = context != null ? context.getResources() : null;
-        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
-        // Set layout and text direction defaults
-        mPrivateFlags2 = (LAYOUT_DIRECTION_DEFAULT << LAYOUT_DIRECTION_MASK_SHIFT) |
-                (TEXT_DIRECTION_DEFAULT << TEXT_DIRECTION_MASK_SHIFT) |
-                (TEXT_ALIGNMENT_DEFAULT << TEXT_ALIGNMENT_MASK_SHIFT) |
-                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << IMPORTANT_FOR_ACCESSIBILITY_SHIFT) |
-                (ACCESSIBILITY_FOCUSABLE_DEFAULT << ACCESSIBILITY_FOCUSABLE_SHIFT);
-        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
-        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
-        mUserPaddingStart = -1;
-        mUserPaddingEnd = -1;
-        mUserPaddingRelative = false;
-    }
-
-    /**
-     * Delegate for injecting accessiblity functionality.
+     * Delegate for injecting accessibility functionality.
      */
     AccessibilityDelegate mAccessibilityDelegate;
 
@@ -3253,6 +3211,32 @@
             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
                     new InputEventConsistencyVerifier(this, 0) : null;
 
+    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
+
+    /**
+     * Simple constructor to use when creating a view from code.
+     *
+     * @param context The Context the view is running in, through which it can
+     *        access the current theme, resources, etc.
+     */
+    public View(Context context) {
+        mContext = context;
+        mResources = context != null ? context.getResources() : null;
+        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
+        // Set some flags defaults
+        mPrivateFlags2 =
+                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
+                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
+                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
+                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
+                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
+                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
+        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
+        mUserPaddingStart = UNDEFINED_PADDING;
+        mUserPaddingEnd = UNDEFINED_PADDING;
+    }
+
     /**
      * Constructor that is called when inflating a view from XML. This is called
      * when a view is being constructed from an XML file, supplying attributes
@@ -3303,8 +3287,8 @@
         int topPadding = -1;
         int rightPadding = -1;
         int bottomPadding = -1;
-        int startPadding = -1;
-        int endPadding = -1;
+        int startPadding = UNDEFINED_PADDING;
+        int endPadding = UNDEFINED_PADDING;
 
         int padding = -1;
 
@@ -3326,8 +3310,16 @@
         boolean transformSet = false;
 
         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
-
         int overScrollMode = mOverScrollMode;
+        boolean initializeScrollbars = false;
+
+        boolean leftPaddingDefined = false;
+        boolean rightPaddingDefined = false;
+        boolean startPaddingDefined = false;
+        boolean endPaddingDefined = false;
+
+        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
+
         final int N = a.getIndexCount();
         for (int i = 0; i < N; i++) {
             int attr = a.getIndex(i);
@@ -3337,24 +3329,34 @@
                     break;
                 case com.android.internal.R.styleable.View_padding:
                     padding = a.getDimensionPixelSize(attr, -1);
+                    mUserPaddingLeftInitial = padding;
+                    mUserPaddingRightInitial = padding;
+                    leftPaddingDefined = true;
+                    rightPaddingDefined = true;
                     break;
                  case com.android.internal.R.styleable.View_paddingLeft:
                     leftPadding = a.getDimensionPixelSize(attr, -1);
+                    mUserPaddingLeftInitial = leftPadding;
+                    leftPaddingDefined = true;
                     break;
                 case com.android.internal.R.styleable.View_paddingTop:
                     topPadding = a.getDimensionPixelSize(attr, -1);
                     break;
                 case com.android.internal.R.styleable.View_paddingRight:
                     rightPadding = a.getDimensionPixelSize(attr, -1);
+                    mUserPaddingRightInitial = rightPadding;
+                    rightPaddingDefined = true;
                     break;
                 case com.android.internal.R.styleable.View_paddingBottom:
                     bottomPadding = a.getDimensionPixelSize(attr, -1);
                     break;
                 case com.android.internal.R.styleable.View_paddingStart:
-                    startPadding = a.getDimensionPixelSize(attr, -1);
+                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
+                    startPaddingDefined = true;
                     break;
                 case com.android.internal.R.styleable.View_paddingEnd:
-                    endPadding = a.getDimensionPixelSize(attr, -1);
+                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
+                    endPaddingDefined = true;
                     break;
                 case com.android.internal.R.styleable.View_scrollX:
                     x = a.getDimensionPixelOffset(attr, 0);
@@ -3456,12 +3458,13 @@
                     break;
                 case com.android.internal.R.styleable.View_layoutDirection:
                     // Clear any layout direction flags (included resolved bits) already set
-                    mPrivateFlags2 &= ~(LAYOUT_DIRECTION_MASK | LAYOUT_DIRECTION_RESOLVED_MASK);
+                    mPrivateFlags2 &=
+                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
                     // Set the layout direction flags depending on the value of the attribute
                     final int layoutDirection = a.getInt(attr, -1);
                     final int value = (layoutDirection != -1) ?
                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
-                    mPrivateFlags2 |= (value << LAYOUT_DIRECTION_MASK_SHIFT);
+                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
                     break;
                 case com.android.internal.R.styleable.View_drawingCacheQuality:
                     final int cacheQuality = a.getInt(attr, 0);
@@ -3473,6 +3476,9 @@
                 case com.android.internal.R.styleable.View_contentDescription:
                     setContentDescription(a.getString(attr));
                     break;
+                case com.android.internal.R.styleable.View_labelFor:
+                    setLabelFor(a.getResourceId(attr, NO_ID));
+                    break;
                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
                     if (!a.getBoolean(attr, true)) {
                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
@@ -3490,12 +3496,12 @@
                     if (scrollbars != SCROLLBARS_NONE) {
                         viewFlagValues |= scrollbars;
                         viewFlagMasks |= SCROLLBARS_MASK;
-                        initializeScrollbars(a);
+                        initializeScrollbars = true;
                     }
                     break;
                 //noinspection deprecation
                 case R.styleable.View_fadingEdge:
-                    if (context.getApplicationInfo().targetSdkVersion >= ICE_CREAM_SANDWICH) {
+                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
                         // Ignore the attribute starting with ICS
                         break;
                     }
@@ -3606,19 +3612,19 @@
                     break;
                 case R.styleable.View_textDirection:
                     // Clear any text direction flag already set
-                    mPrivateFlags2 &= ~TEXT_DIRECTION_MASK;
+                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
                     // Set the text direction flags depending on the value of the attribute
                     final int textDirection = a.getInt(attr, -1);
                     if (textDirection != -1) {
-                        mPrivateFlags2 |= TEXT_DIRECTION_FLAGS[textDirection];
+                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
                     }
                     break;
                 case R.styleable.View_textAlignment:
                     // Clear any text alignment flag already set
-                    mPrivateFlags2 &= ~TEXT_ALIGNMENT_MASK;
+                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
                     // Set the text alignment flag depending on the value of the attribute
                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
-                    mPrivateFlags2 |= TEXT_ALIGNMENT_FLAGS[textAlignment];
+                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
                     break;
                 case R.styleable.View_importantForAccessibility:
                     setImportantForAccessibility(a.getInt(attr,
@@ -3627,41 +3633,73 @@
             }
         }
 
-        a.recycle();
-
         setOverScrollMode(overScrollMode);
 
+        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
+        // the resolved layout direction). Those cached values will be used later during padding
+        // resolution.
+        mUserPaddingStart = startPadding;
+        mUserPaddingEnd = endPadding;
+
         if (background != null) {
             setBackground(background);
         }
 
-        // Cache user padding as we cannot fully resolve padding here (we dont have yet the resolved
-        // layout direction). Those cached values will be used later during padding resolution.
-        mUserPaddingStart = startPadding;
-        mUserPaddingEnd = endPadding;
-
-        updateUserPaddingRelative();
-
         if (padding >= 0) {
             leftPadding = padding;
             topPadding = padding;
             rightPadding = padding;
             bottomPadding = padding;
+            mUserPaddingLeftInitial = padding;
+            mUserPaddingRightInitial = padding;
         }
 
-        // If the user specified the padding (either with android:padding or
-        // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
-        // use the default padding or the padding from the background drawable
-        // (stored at this point in mPadding*)
-        setPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
+        if (isRtlCompatibilityMode()) {
+            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
+            // left / right padding are used if defined (meaning here nothing to do). If they are not
+            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
+            // start / end and resolve them as left / right (layout direction is not taken into account).
+            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
+            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
+            // defined.
+            if (!leftPaddingDefined && startPaddingDefined) {
+                leftPadding = startPadding;
+            }
+            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
+            if (!rightPaddingDefined && endPaddingDefined) {
+                rightPadding = endPadding;
+            }
+            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
+        } else {
+            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
+            // values defined. Otherwise, left /right values are used.
+            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
+            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
+            // defined.
+            if (leftPaddingDefined) {
+                mUserPaddingLeftInitial = leftPadding;
+            }
+            if (rightPaddingDefined) {
+                mUserPaddingRightInitial = rightPadding;
+            }
+        }
+
+        internalSetPadding(
+                mUserPaddingLeftInitial,
                 topPadding >= 0 ? topPadding : mPaddingTop,
-                rightPadding >= 0 ? rightPadding : mPaddingRight,
+                mUserPaddingRightInitial,
                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
 
         if (viewFlagMasks != 0) {
             setFlags(viewFlagValues, viewFlagMasks);
         }
 
+        if (initializeScrollbars) {
+            initializeScrollbars(a);
+        }
+
+        a.recycle();
+
         // Needs to be called after mViewFlags is set
         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
             recomputePadding();
@@ -3688,10 +3726,6 @@
         computeOpaqueFlags();
     }
 
-    private void updateUserPaddingRelative() {
-        mUserPaddingRelative = (mUserPaddingStart >= 0 || mUserPaddingEnd >= 0);
-    }
-
     /**
      * Non-public constructor for use in testing
      */
@@ -3699,6 +3733,81 @@
         mResources = null;
     }
 
+    public String toString() {
+        StringBuilder out = new StringBuilder(128);
+        out.append(getClass().getName());
+        out.append('{');
+        out.append(Integer.toHexString(System.identityHashCode(this)));
+        out.append(' ');
+        switch (mViewFlags&VISIBILITY_MASK) {
+            case VISIBLE: out.append('V'); break;
+            case INVISIBLE: out.append('I'); break;
+            case GONE: out.append('G'); break;
+            default: out.append('.'); break;
+        }
+        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
+        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
+        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
+        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
+        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
+        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
+        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
+        out.append(' ');
+        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
+        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
+        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
+        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
+            out.append('p');
+        } else {
+            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
+        }
+        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
+        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
+        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
+        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
+        out.append(' ');
+        out.append(mLeft);
+        out.append(',');
+        out.append(mTop);
+        out.append('-');
+        out.append(mRight);
+        out.append(',');
+        out.append(mBottom);
+        final int id = getId();
+        if (id != NO_ID) {
+            out.append(" #");
+            out.append(Integer.toHexString(id));
+            final Resources r = mResources;
+            if (id != 0 && r != null) {
+                try {
+                    String pkgname;
+                    switch (id&0xff000000) {
+                        case 0x7f000000:
+                            pkgname="app";
+                            break;
+                        case 0x01000000:
+                            pkgname="android";
+                            break;
+                        default:
+                            pkgname = r.getResourcePackageName(id);
+                            break;
+                    }
+                    String typename = r.getResourceTypeName(id);
+                    String entryname = r.getResourceEntryName(id);
+                    out.append(" ");
+                    out.append(pkgname);
+                    out.append(":");
+                    out.append(typename);
+                    out.append("/");
+                    out.append(entryname);
+                } catch (Resources.NotFoundException e) {
+                }
+            }
+        }
+        out.append("}");
+        return out.toString();
+    }
+
     /**
      * <p>
      * Initializes the fading edges from a given set of styled attributes. This
@@ -3881,6 +3990,15 @@
             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
         }
 
+        // Apply layout direction to the new Drawables if needed
+        final int layoutDirection = getLayoutDirection();
+        if (track != null) {
+            track.setLayoutDirection(layoutDirection);
+        }
+        if (thumb != null) {
+            thumb.setLayoutDirection(layoutDirection);
+        }
+
         // Re-apply user/background padding so that scrollbar(s) get added
         resolvePadding();
     }
@@ -4247,8 +4365,8 @@
             System.out.println(this + " requestFocus()");
         }
 
-        if ((mPrivateFlags & FOCUSED) == 0) {
-            mPrivateFlags |= FOCUSED;
+        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
+            mPrivateFlags |= PFLAG_FOCUSED;
 
             if (mParent != null) {
                 mParent.requestChildFocus(this, this);
@@ -4294,25 +4412,42 @@
      * @return Whether any parent scrolled.
      */
     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
+        if (mParent == null) {
+            return false;
+        }
+
         View child = this;
+
+        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
+        position.set(rectangle);
+
         ViewParent parent = mParent;
         boolean scrolled = false;
         while (parent != null) {
+            rectangle.set((int) position.left, (int) position.top,
+                    (int) position.right, (int) position.bottom);
+
             scrolled |= parent.requestChildRectangleOnScreen(child,
                     rectangle, immediate);
 
-            // offset rect so next call has the rectangle in the
-            // coordinate system of its direct child.
-            rectangle.offset(child.getLeft(), child.getTop());
-            rectangle.offset(-child.getScrollX(), -child.getScrollY());
+            if (!child.hasIdentityMatrix()) {
+                child.getMatrix().mapRect(position);
+            }
+
+            position.offset(child.mLeft, child.mTop);
 
             if (!(parent instanceof View)) {
                 break;
             }
 
-            child = (View) parent;
+            View parentView = (View) parent;
+
+            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
+
+            child = parentView;
             parent = child.getParent();
         }
+
         return scrolled;
     }
 
@@ -4332,8 +4467,8 @@
             System.out.println(this + " clearFocus()");
         }
 
-        if ((mPrivateFlags & FOCUSED) != 0) {
-            mPrivateFlags &= ~FOCUSED;
+        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
+            mPrivateFlags &= ~PFLAG_FOCUSED;
 
             if (mParent != null) {
                 mParent.clearChildFocus(this);
@@ -4367,8 +4502,8 @@
             System.out.println(this + " unFocus()");
         }
 
-        if ((mPrivateFlags & FOCUSED) != 0) {
-            mPrivateFlags &= ~FOCUSED;
+        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
+            mPrivateFlags &= ~PFLAG_FOCUSED;
 
             onFocusChanged(false, 0, null);
             refreshDrawableState();
@@ -4387,7 +4522,7 @@
      */
     @ViewDebug.ExportedProperty(category = "focus")
     public boolean hasFocus() {
-        return (mPrivateFlags & FOCUSED) != 0;
+        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
     }
 
     /**
@@ -4458,7 +4593,7 @@
     }
 
     /**
-     * Sends an accessibility event of the given type. If accessiiblity is
+     * Sends an accessibility event of the given type. If accessibility is
      * not enabled this method has no effect. The default implementation calls
      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
      * to populate information about the event source (this View), then calls
@@ -4502,11 +4637,13 @@
      * @param text The announcement text.
      */
     public void announceForAccessibility(CharSequence text) {
-        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
             AccessibilityEvent event = AccessibilityEvent.obtain(
                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
+            onInitializeAccessibilityEvent(event);
             event.getText().add(text);
-            sendAccessibilityEventUnchecked(event);
+            event.setContentDescription(null);
+            mParent.requestSendAccessibilityEvent(this, event);
         }
     }
 
@@ -4779,7 +4916,7 @@
      *
      * @param outRect The output location
      */
-    private void getBoundsOnScreen(Rect outRect) {
+    void getBoundsOnScreen(Rect outRect) {
         if (mAttachInfo == null) {
             return;
         }
@@ -4826,6 +4963,7 @@
      */
     void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         Rect bounds = mAttachInfo.mTmpInvalRect;
+
         getDrawingRect(bounds);
         info.setBoundsInParent(bounds);
 
@@ -4837,6 +4975,28 @@
             info.setParent((View) parent);
         }
 
+        if (mID != View.NO_ID) {
+            View rootView = getRootView();
+            if (rootView == null) {
+                rootView = this;
+            }
+            View label = rootView.findLabelForView(this, mID);
+            if (label != null) {
+                info.setLabeledBy(label);
+            }
+        }
+
+        if (mLabelForId != View.NO_ID) {
+            View rootView = getRootView();
+            if (rootView == null) {
+                rootView = this;
+            }
+            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
+            if (labeled != null) {
+                info.setLabelFor(labeled);
+            }
+        }
+
         info.setVisibleToUser(isVisibleToUser());
 
         info.setPackageName(mContext.getPackageName());
@@ -4852,7 +5012,7 @@
         info.setLongClickable(isLongClickable());
 
         // TODO: These make sense only if we are in an AdapterView but all
-        // views can be selected. Maybe from accessiiblity perspective
+        // views can be selected. Maybe from accessibility perspective
         // we should report as selectable view in an AdapterView.
         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
@@ -4866,10 +5026,7 @@
         }
 
         if (!isAccessibilityFocused()) {
-            final int mode = getAccessibilityFocusable();
-            if (mode == ACCESSIBILITY_FOCUSABLE_YES || mode == ACCESSIBILITY_FOCUSABLE_AUTO) {
-                info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
-            }
+            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
         } else {
             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
         }
@@ -4891,28 +5048,12 @@
         }
     }
 
-    /**
-     * Returns the delta between the actual and last reported window left.
-     *
-     * @hide
-     */
-    public int getActualAndReportedWindowLeftDelta() {
-        if (mAttachInfo != null) {
-            return mAttachInfo.mActualWindowLeft - mAttachInfo.mWindowLeft; 
+    private View findLabelForView(View view, int labeledId) {
+        if (mMatchLabelForPredicate == null) {
+            mMatchLabelForPredicate = new MatchLabelForPredicate();
         }
-        return 0;
-    }
-
-    /**
-     * Returns the delta between the actual and last reported window top.
-     *
-     * @hide
-     */
-    public int getActualAndReportedWindowTopDelta() {
-        if (mAttachInfo != null) {
-            return mAttachInfo.mActualWindowTop - mAttachInfo.mWindowTop;
-        }
-        return 0;
+        mMatchLabelForPredicate.mLabeledId = labeledId;
+        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
     }
 
     /**
@@ -4929,9 +5070,10 @@
     }
 
     /**
-     * Computes whether the given portion of this view is visible to the user. Such a view is
-     * attached, visible, all its predecessors are visible, has an alpha greater than zero, and
-     * the specified portion is not clipped entirely by its predecessors.
+     * Computes whether the given portion of this view is visible to the user.
+     * Such a view is attached, visible, all its predecessors are visible,
+     * has an alpha greater than zero, and the specified portion is not
+     * clipped entirely by its predecessors.
      *
      * @param boundInView the portion of the view to test; coordinates should be relative; may be
      *                    <code>null</code>, and the entire view will be tested in this case.
@@ -4945,26 +5087,53 @@
      * @hide
      */
     protected boolean isVisibleToUser(Rect boundInView) {
-        Rect visibleRect = mAttachInfo.mTmpInvalRect;
-        Point offset = mAttachInfo.mPoint;
-        // The first two checks are made also made by isShown() which
-        // however traverses the tree up to the parent to catch that.
-        // Therefore, we do some fail fast check to minimize the up
-        // tree traversal.
-        boolean isVisible = mAttachInfo != null
-            && mAttachInfo.mWindowVisibility == View.VISIBLE
-            && getAlpha() > 0
-            && isShown()
-            && getGlobalVisibleRect(visibleRect, offset);
-            if (isVisible && boundInView != null) {
-                visibleRect.offset(-offset.x, -offset.y);
-                isVisible &= boundInView.intersect(visibleRect);
+        if (mAttachInfo != null) {
+            // Attached to invisible window means this view is not visible.
+            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
+                return false;
             }
-            return isVisible;
+            // An invisible predecessor or one with alpha zero means
+            // that this view is not visible to the user.
+            Object current = this;
+            while (current instanceof View) {
+                View view = (View) current;
+                // We have attach info so this view is attached and there is no
+                // need to check whether we reach to ViewRootImpl on the way up.
+                if (view.getAlpha() <= 0 || view.getVisibility() != VISIBLE) {
+                    return false;
+                }
+                current = view.mParent;
+            }
+            // Check if the view is entirely covered by its predecessors.
+            Rect visibleRect = mAttachInfo.mTmpInvalRect;
+            Point offset = mAttachInfo.mPoint;
+            if (!getGlobalVisibleRect(visibleRect, offset)) {
+                return false;
+            }
+            // Check if the visible portion intersects the rectangle of interest.
+            if (boundInView != null) {
+                visibleRect.offset(-offset.x, -offset.y);
+                return boundInView.intersect(visibleRect);
+            }
+            return true;
+        }
+        return false;
     }
 
     /**
-     * Sets a delegate for implementing accessibility support via compositon as
+     * Returns the delegate for implementing accessibility support via
+     * composition. For more details see {@link AccessibilityDelegate}.
+     *
+     * @return The delegate, or null if none set.
+     *
+     * @hide
+     */
+    public AccessibilityDelegate getAccessibilityDelegate() {
+        return mAccessibilityDelegate;
+    }
+
+    /**
+     * Sets a delegate for implementing accessibility support via composition as
      * opposed to inheritance. The delegate's primary use is for implementing
      * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
      *
@@ -5061,11 +5230,45 @@
      */
     @RemotableViewMethod
     public void setContentDescription(CharSequence contentDescription) {
+        if (mContentDescription == null) {
+            if (contentDescription == null) {
+                return;
+            }
+        } else if (mContentDescription.equals(contentDescription)) {
+            return;
+        }
         mContentDescription = contentDescription;
         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
              setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
         }
+        notifyAccessibilityStateChanged();
+    }
+
+    /**
+     * Gets the id of a view for which this view serves as a label for
+     * accessibility purposes.
+     *
+     * @return The labeled view id.
+     */
+    @ViewDebug.ExportedProperty(category = "accessibility")
+    public int getLabelFor() {
+        return mLabelForId;
+    }
+
+    /**
+     * Sets the id of a view for which this view serves as a label for
+     * accessibility purposes.
+     *
+     * @param id The labeled view id.
+     */
+    @RemotableViewMethod
+    public void setLabelFor(int id) {
+        mLabelForId = id;
+        if (mLabelForId != View.NO_ID
+                && mID == View.NO_ID) {
+            mID = generateViewId();
+        }
     }
 
     /**
@@ -5106,7 +5309,7 @@
      */
     @ViewDebug.ExportedProperty(category = "focus")
     public boolean isFocused() {
-        return (mPrivateFlags & FOCUSED) != 0;
+        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
     }
 
     /**
@@ -5117,7 +5320,7 @@
      *         be found.
      */
     public View findFocus() {
-        return (mPrivateFlags & FOCUSED) != 0 ? this : null;
+        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
     }
 
     /**
@@ -5130,7 +5333,7 @@
      * @attr ref android.R.styleable#View_isScrollContainer
      */
     public boolean isScrollContainer() {
-        return (mPrivateFlags & SCROLL_CONTAINER_ADDED) != 0;
+        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
     }
 
     /**
@@ -5144,16 +5347,16 @@
      */
     public void setScrollContainer(boolean isScrollContainer) {
         if (isScrollContainer) {
-            if (mAttachInfo != null && (mPrivateFlags&SCROLL_CONTAINER_ADDED) == 0) {
+            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
                 mAttachInfo.mScrollContainers.add(this);
-                mPrivateFlags |= SCROLL_CONTAINER_ADDED;
+                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
             }
-            mPrivateFlags |= SCROLL_CONTAINER;
+            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
         } else {
-            if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
+            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
                 mAttachInfo.mScrollContainers.remove(this);
             }
-            mPrivateFlags &= ~(SCROLL_CONTAINER|SCROLL_CONTAINER_ADDED);
+            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
         }
     }
 
@@ -5403,14 +5606,13 @@
      * @return Return true if this view applied the insets and it should not
      * continue propagating further down the hierarchy, false otherwise.
      * @see #getFitsSystemWindows()
-     * @see #setFitsSystemWindows()
+     * @see #setFitsSystemWindows(boolean) 
      * @see #setSystemUiVisibility(int)
      */
     protected boolean fitSystemWindows(Rect insets) {
         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
-            mUserPaddingStart = -1;
-            mUserPaddingEnd = -1;
-            mUserPaddingRelative = false;
+            mUserPaddingStart = UNDEFINED_PADDING;
+            mUserPaddingEnd = UNDEFINED_PADDING;
             if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
                     || mAttachInfo == null
                     || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
@@ -5652,8 +5854,8 @@
      *   {@link #LAYOUT_DIRECTION_RTL},
      *   {@link #LAYOUT_DIRECTION_INHERIT} or
      *   {@link #LAYOUT_DIRECTION_LOCALE}.
-     *
      * @attr ref android.R.styleable#View_layoutDirection
+     *
      * @hide
      */
     @ViewDebug.ExportedProperty(category = "layout", mapping = {
@@ -5662,32 +5864,40 @@
         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
     })
-    public int getLayoutDirection() {
-        return (mPrivateFlags2 & LAYOUT_DIRECTION_MASK) >> LAYOUT_DIRECTION_MASK_SHIFT;
+    public int getRawLayoutDirection() {
+        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
     }
 
     /**
      * Set the layout direction for this view. This will propagate a reset of layout direction
      * resolution to the view's children and resolve layout direction for this view.
      *
-     * @param layoutDirection One of {@link #LAYOUT_DIRECTION_LTR},
-     *   {@link #LAYOUT_DIRECTION_RTL},
-     *   {@link #LAYOUT_DIRECTION_INHERIT} or
-     *   {@link #LAYOUT_DIRECTION_LOCALE}.
+     * @param layoutDirection the layout direction to set. Should be one of:
+     *
+     * {@link #LAYOUT_DIRECTION_LTR},
+     * {@link #LAYOUT_DIRECTION_RTL},
+     * {@link #LAYOUT_DIRECTION_INHERIT},
+     * {@link #LAYOUT_DIRECTION_LOCALE}.
+     *
+     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
+     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
+     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
      *
      * @attr ref android.R.styleable#View_layoutDirection
-     * @hide
      */
     @RemotableViewMethod
     public void setLayoutDirection(int layoutDirection) {
-        if (getLayoutDirection() != layoutDirection) {
+        if (getRawLayoutDirection() != layoutDirection) {
             // Reset the current layout direction and the resolved one
-            mPrivateFlags2 &= ~LAYOUT_DIRECTION_MASK;
-            resetResolvedLayoutDirection();
-            // Set the new layout direction (filtered) and ask for a layout pass
+            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
+            resetRtlProperties();
+            // Set the new layout direction (filtered)
             mPrivateFlags2 |=
-                    ((layoutDirection << LAYOUT_DIRECTION_MASK_SHIFT) & LAYOUT_DIRECTION_MASK);
+                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
+            // We need to resolve all RTL properties as they all depend on layout direction
+            resolveRtlPropertiesIfNeeded();
             requestLayout();
+            invalidate(true);
         }
     }
 
@@ -5696,19 +5906,22 @@
      *
      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
-     * @hide
+     *
+     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
+     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
      */
     @ViewDebug.ExportedProperty(category = "layout", mapping = {
         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
     })
-    public int getResolvedLayoutDirection() {
-        // The layout diretion will be resolved only if needed
-        if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) != LAYOUT_DIRECTION_RESOLVED) {
-            resolveLayoutDirection();
+    public int getLayoutDirection() {
+        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
+        if (targetSdkVersion < JELLY_BEAN_MR1) {
+            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
+            return LAYOUT_DIRECTION_LTR;
         }
-        return ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED_RTL) == LAYOUT_DIRECTION_RESOLVED_RTL) ?
-                LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
+        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
+                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
     }
 
     /**
@@ -5716,11 +5929,12 @@
      * layout attribute and/or the inherited value from the parent
      *
      * @return true if the layout is right-to-left.
+     *
      * @hide
      */
     @ViewDebug.ExportedProperty(category = "layout")
     public boolean isLayoutRtl() {
-        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
+        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
     }
 
     /**
@@ -5737,7 +5951,7 @@
      */
     @ViewDebug.ExportedProperty(category = "layout")
     public boolean hasTransientState() {
-        return (mPrivateFlags2 & HAS_TRANSIENT_STATE) == HAS_TRANSIENT_STATE;
+        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
     }
 
     /**
@@ -5764,8 +5978,8 @@
         if ((hasTransientState && mTransientStateCount == 1) ||
                 (!hasTransientState && mTransientStateCount == 0)) {
             // update flag if we've just incremented up from 0 or decremented down to 0
-            mPrivateFlags2 = (mPrivateFlags2 & ~HAS_TRANSIENT_STATE) |
-                    (hasTransientState ? HAS_TRANSIENT_STATE : 0);
+            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
+                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
             if (mParent != null) {
                 try {
                     mParent.childHasTransientStateChanged(this, hasTransientState);
@@ -5888,12 +6102,12 @@
      *        the View's internal state from a previously set "pressed" state.
      */
     public void setPressed(boolean pressed) {
-        final boolean needsRefresh = pressed != ((mPrivateFlags & PRESSED) == PRESSED);
+        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
 
         if (pressed) {
-            mPrivateFlags |= PRESSED;
+            mPrivateFlags |= PFLAG_PRESSED;
         } else {
-            mPrivateFlags &= ~PRESSED;
+            mPrivateFlags &= ~PFLAG_PRESSED;
         }
 
         if (needsRefresh) {
@@ -5924,7 +6138,7 @@
      * @return true if the view is currently pressed, false otherwise
      */
     public boolean isPressed() {
-        return (mPrivateFlags & PRESSED) == PRESSED;
+        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
     }
 
     /**
@@ -6117,17 +6331,14 @@
         return null;
     }
 
-    private View findViewInsideOutShouldExist(View root, final int childViewId) {
-        View result = root.findViewByPredicateInsideOut(this, new Predicate<View>() {
-            @Override
-            public boolean apply(View t) {
-                return t.mID == childViewId;
-            }
-        });
-
+    private View findViewInsideOutShouldExist(View root, int id) {
+        if (mMatchIdPredicate == null) {
+            mMatchIdPredicate = new MatchIdPredicate();
+        }
+        mMatchIdPredicate.mId = id;
+        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
         if (result == null) {
-            Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified "
-                    + "by user for id " + childViewId);
+            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
         }
         return result;
     }
@@ -6177,12 +6388,6 @@
         if (views == null) {
             return;
         }
-        if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
-            if (isAccessibilityFocusable()) {
-                views.add(this);
-                return;
-            }
-        }
         if (!isFocusable()) {
             return;
         }
@@ -6257,7 +6462,7 @@
      * @return True if this View is accessibility focused.
      */
     boolean isAccessibilityFocused() {
-        return (mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0;
+        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
     }
 
     /**
@@ -6282,8 +6487,8 @@
         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
             return false;
         }
-        if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) == 0) {
-            mPrivateFlags2 |= ACCESSIBILITY_FOCUSED;
+        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
+            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
             ViewRootImpl viewRootImpl = getViewRootImpl();
             if (viewRootImpl != null) {
                 viewRootImpl.setAccessibilityFocus(this, null);
@@ -6305,8 +6510,8 @@
      * @hide
      */
     public void clearAccessibilityFocus() {
-        if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0) {
-            mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSED;
+        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
+            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
             invalidate();
             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
             notifyAccessibilityStateChanged();
@@ -6347,29 +6552,6 @@
         }
     }
 
-    private void requestAccessibilityFocusFromHover() {
-        if (includeForAccessibility() && isActionableForAccessibility()) {
-            requestAccessibilityFocus();
-        } else {
-            if (mParent != null) {
-                View nextFocus = mParent.findViewToTakeAccessibilityFocusFromHover(this, this);
-                if (nextFocus != null) {
-                    nextFocus.requestAccessibilityFocus();
-                }
-            }
-        }
-    }
-
-    private boolean canTakeAccessibilityFocusFromHover() {
-        if (includeForAccessibility() && isActionableForAccessibility()) {
-            return true;
-        }
-        if (mParent != null) {
-            return (mParent.findViewToTakeAccessibilityFocusFromHover(this, this) == this);
-        }
-        return false;
-    }
-
     /**
      * Clears accessibility focus without calling any callback methods
      * normally invoked in {@link #clearAccessibilityFocus()}. This method
@@ -6377,8 +6559,8 @@
      * another view.
      */
     void clearAccessibilityFocusNoCallbacks() {
-        if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0) {
-            mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSED;
+        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
+            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
             invalidate();
         }
     }
@@ -6535,8 +6717,8 @@
             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no")
         })
     public int getImportantForAccessibility() {
-        return (mPrivateFlags2 & IMPORTANT_FOR_ACCESSIBILITY_MASK)
-                >> IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
+                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
     }
 
     /**
@@ -6554,9 +6736,9 @@
      */
     public void setImportantForAccessibility(int mode) {
         if (mode != getImportantForAccessibility()) {
-            mPrivateFlags2 &= ~IMPORTANT_FOR_ACCESSIBILITY_MASK;
-            mPrivateFlags2 |= (mode << IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
-                    & IMPORTANT_FOR_ACCESSIBILITY_MASK;
+            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
+            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
+                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
             notifyAccessibilityStateChanged();
         }
     }
@@ -6569,15 +6751,16 @@
      * @hide
      */
     public boolean isImportantForAccessibility() {
-        final int mode = (mPrivateFlags2 & IMPORTANT_FOR_ACCESSIBILITY_MASK)
-                >> IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
+                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
         switch (mode) {
             case IMPORTANT_FOR_ACCESSIBILITY_YES:
                 return true;
             case IMPORTANT_FOR_ACCESSIBILITY_NO:
                 return false;
             case IMPORTANT_FOR_ACCESSIBILITY_AUTO:
-                return isActionableForAccessibility() || hasListenersForAccessibility();
+                return isActionableForAccessibility() || hasListenersForAccessibility()
+                        || getAccessibilityNodeProvider() != null;
             default:
                 throw new IllegalArgumentException("Unknow important for accessibility mode: "
                         + mode);
@@ -6585,73 +6768,6 @@
     }
 
     /**
-     * Gets the mode for determining whether this View can take accessibility focus.
-     *
-     * @return The mode for determining whether a View can take accessibility focus.
-     *
-     * @attr ref android.R.styleable#View_accessibilityFocusable
-     *
-     * @see #ACCESSIBILITY_FOCUSABLE_YES
-     * @see #ACCESSIBILITY_FOCUSABLE_NO
-     * @see #ACCESSIBILITY_FOCUSABLE_AUTO
-     *
-     * @hide
-     */
-    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
-            @ViewDebug.IntToString(from = ACCESSIBILITY_FOCUSABLE_AUTO, to = "auto"),
-            @ViewDebug.IntToString(from = ACCESSIBILITY_FOCUSABLE_YES, to = "yes"),
-            @ViewDebug.IntToString(from = ACCESSIBILITY_FOCUSABLE_NO, to = "no")
-        })
-    public int getAccessibilityFocusable() {
-        return (mPrivateFlags2 & ACCESSIBILITY_FOCUSABLE_MASK) >>> ACCESSIBILITY_FOCUSABLE_SHIFT;
-    }
-
-    /**
-     * Sets how to determine whether this view can take accessibility focus.
-     *
-     * @param mode How to determine whether this view can take accessibility focus.
-     *
-     * @attr ref android.R.styleable#View_accessibilityFocusable
-     *
-     * @see #ACCESSIBILITY_FOCUSABLE_YES
-     * @see #ACCESSIBILITY_FOCUSABLE_NO
-     * @see #ACCESSIBILITY_FOCUSABLE_AUTO
-     *
-     * @hide
-     */
-    public void setAccessibilityFocusable(int mode) {
-        if (mode != getAccessibilityFocusable()) {
-            mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSABLE_MASK;
-            mPrivateFlags2 |= (mode << ACCESSIBILITY_FOCUSABLE_SHIFT)
-                    & ACCESSIBILITY_FOCUSABLE_MASK;
-            notifyAccessibilityStateChanged();
-        }
-    }
-
-    /**
-     * Gets whether this view can take accessibility focus.
-     *
-     * @return Whether the view can take accessibility focus.
-     *
-     * @hide
-     */
-    public boolean isAccessibilityFocusable() {
-        final int mode = (mPrivateFlags2 & ACCESSIBILITY_FOCUSABLE_MASK)
-                >>> ACCESSIBILITY_FOCUSABLE_SHIFT;
-        switch (mode) {
-            case ACCESSIBILITY_FOCUSABLE_YES:
-                return true;
-            case ACCESSIBILITY_FOCUSABLE_NO:
-                return false;
-            case ACCESSIBILITY_FOCUSABLE_AUTO:
-                return canTakeAccessibilityFocusFromHover()
-                        || getAccessibilityNodeProvider() != null;
-            default:
-                throw new IllegalArgumentException("Unknow accessibility focusable mode: " + mode);
-        }
-    }
-
-    /**
      * Gets the parent for accessibility purposes. Note that the parent for
      * accessibility is not necessary the immediate parent. It is the first
      * predecessor that is important for accessibility.
@@ -6696,10 +6812,7 @@
      */
     public boolean includeForAccessibility() {
         if (mAttachInfo != null) {
-            if (!mAttachInfo.mIncludeNotImportantViews) {
-                return isImportantForAccessibility();
-            }
-            return true;
+            return mAttachInfo.mIncludeNotImportantViews || isImportantForAccessibility();
         }
         return false;
     }
@@ -6707,7 +6820,7 @@
     /**
      * Returns whether the View is considered actionable from
      * accessibility perspective. Such view are important for
-     * accessiiblity.
+     * accessibility.
      *
      * @return True if the view is actionable for accessibility.
      *
@@ -6719,7 +6832,7 @@
 
     /**
      * Returns whether the View has registered callbacks wich makes it
-     * important for accessiiblity.
+     * important for accessibility.
      *
      * @return True if the view is actionable for accessibility.
      */
@@ -6748,8 +6861,8 @@
         if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
             return;
         }
-        if ((mPrivateFlags2 & ACCESSIBILITY_STATE_CHANGED) == 0) {
-            mPrivateFlags2 |= ACCESSIBILITY_STATE_CHANGED;
+        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_STATE_CHANGED) == 0) {
+            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_STATE_CHANGED;
             if (mParent != null) {
                 mParent.childAccessibilityStateChanged(this);
             }
@@ -6758,23 +6871,23 @@
 
     /**
      * Reset the state indicating the this view has requested clients
-     * interested in its accessiblity state to be notified.
+     * interested in its accessibility state to be notified.
      *
      * @hide
      */
     public void resetAccessibilityStateChanged() {
-        mPrivateFlags2 &= ~ACCESSIBILITY_STATE_CHANGED;
+        mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_STATE_CHANGED;
     }
 
     /**
      * Performs the specified accessibility action on the view. For
      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
-    * <p>
-    * If an {@link AccessibilityDelegate} has been specified via calling
-    * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
-    * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
-    * is responsible for handling this call.
-    * </p>
+     * <p>
+     * If an {@link AccessibilityDelegate} has been specified via calling
+     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
+     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
+     * is responsible for handling this call.
+     * </p>
      *
      * @param action The action to perform.
      * @param arguments Optional action arguments.
@@ -6797,12 +6910,14 @@
         switch (action) {
             case AccessibilityNodeInfo.ACTION_CLICK: {
                 if (isClickable()) {
-                    return performClick();
+                    performClick();
+                    return true;
                 }
             } break;
             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
                 if (isLongClickable()) {
-                    return performLongClick();
+                    performLongClick();
+                    return true;
                 }
             } break;
             case AccessibilityNodeInfo.ACTION_FOCUS: {
@@ -6832,10 +6947,7 @@
                 }
             } break;
             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
-                final int mode = getAccessibilityFocusable();
-                if (!isAccessibilityFocused()
-                        && (mode == ACCESSIBILITY_FOCUSABLE_YES
-                                || mode == ACCESSIBILITY_FOCUSABLE_AUTO)) {
+                if (!isAccessibilityFocused()) {
                     return requestAccessibilityFocus();
                 }
             } break;
@@ -6929,7 +7041,7 @@
      * @hide
      */
     public CharSequence getIterableTextForAccessibility() {
-        return mContentDescription;
+        return getContentDescription();
     }
 
     /**
@@ -7018,7 +7130,7 @@
      */
     public void onStartTemporaryDetach() {
         removeUnsetPressCallback();
-        mPrivateFlags |= CANCEL_NEXT_UP_EVENT;
+        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
     }
 
     /**
@@ -7337,13 +7449,13 @@
             if (isPressed()) {
                 setPressed(false);
             }
-            if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
+            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
                 imm.focusOut(this);
             }
             removeLongPressCallback();
             removeTapCallback();
             onFocusLost();
-        } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
+        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
             imm.focusIn(this);
         }
         refreshDrawableState();
@@ -7383,7 +7495,7 @@
             if (mAttachInfo != null) {
                 initialAwakenScrollBars();
             } else {
-                mPrivateFlags |= AWAKEN_SCROLL_BARS_ON_ATTACH;
+                mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
             }
         }
     }
@@ -7484,7 +7596,9 @@
             outRect.bottom -= insets.bottom;
             return;
         }
-        Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
+        // The view is not attached to a display so we don't have a context.
+        // Make a best guess about the display size.
+        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
         d.getRectSize(outRect);
     }
 
@@ -7537,7 +7651,7 @@
 
     void needGlobalAttributesUpdate(boolean force) {
         final AttachInfo ai = mAttachInfo;
-        if (ai != null) {
+        if (ai != null && !ai.mRecomputeGlobalAttributes) {
             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
                     || ai.mHasSystemUiListeners) {
                 ai.mRecomputeGlobalAttributes = true;
@@ -7983,7 +8097,7 @@
      */
     @ViewDebug.ExportedProperty
     public boolean isHovered() {
-        return (mPrivateFlags & HOVERED) != 0;
+        return (mPrivateFlags & PFLAG_HOVERED) != 0;
     }
 
     /**
@@ -8003,14 +8117,14 @@
      */
     public void setHovered(boolean hovered) {
         if (hovered) {
-            if ((mPrivateFlags & HOVERED) == 0) {
-                mPrivateFlags |= HOVERED;
+            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
+                mPrivateFlags |= PFLAG_HOVERED;
                 refreshDrawableState();
                 onHoverChanged(true);
             }
         } else {
-            if ((mPrivateFlags & HOVERED) != 0) {
-                mPrivateFlags &= ~HOVERED;
+            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
+                mPrivateFlags &= ~PFLAG_HOVERED;
                 refreshDrawableState();
                 onHoverChanged(false);
             }
@@ -8042,7 +8156,7 @@
         final int viewFlags = mViewFlags;
 
         if ((viewFlags & ENABLED_MASK) == DISABLED) {
-            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PRESSED) != 0) {
+            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
                 setPressed(false);
             }
             // A disabled view that is clickable still consumes the touch
@@ -8061,8 +8175,8 @@
                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
             switch (event.getAction()) {
                 case MotionEvent.ACTION_UP:
-                    boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;
-                    if ((mPrivateFlags & PRESSED) != 0 || prepressed) {
+                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
+                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
                         // take focus if we don't have it already and we should in
                         // touch mode.
                         boolean focusTaken = false;
@@ -8124,7 +8238,7 @@
                     // For views inside a scrolling container, delay the pressed feedback for
                     // a short period in case this is a scroll.
                     if (isInScrollingContainer) {
-                        mPrivateFlags |= PREPRESSED;
+                        mPrivateFlags |= PFLAG_PREPRESSED;
                         if (mPendingCheckForTap == null) {
                             mPendingCheckForTap = new CheckForTap();
                         }
@@ -8139,6 +8253,7 @@
                 case MotionEvent.ACTION_CANCEL:
                     setPressed(false);
                     removeTapCallback();
+                    removeLongPressCallback();
                     break;
 
                 case MotionEvent.ACTION_MOVE:
@@ -8149,7 +8264,7 @@
                     if (!pointInView(x, y, mTouchSlop)) {
                         // Outside button
                         removeTapCallback();
-                        if ((mPrivateFlags & PRESSED) != 0) {
+                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
                             // Remove any future long press/tap checks
                             removeLongPressCallback();
 
@@ -8200,7 +8315,7 @@
      * Remove the prepress detection timer.
      */
     private void removeUnsetPressCallback() {
-        if ((mPrivateFlags & PRESSED) != 0 && mUnsetPressedState != null) {
+        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
             setPressed(false);
             removeCallbacks(mUnsetPressedState);
         }
@@ -8211,7 +8326,7 @@
      */
     private void removeTapCallback() {
         if (mPendingCheckForTap != null) {
-            mPrivateFlags &= ~PREPRESSED;
+            mPrivateFlags &= ~PFLAG_PREPRESSED;
             removeCallbacks(mPendingCheckForTap);
         }
     }
@@ -8276,13 +8391,13 @@
 
         /* Check if the FOCUSABLE bit has changed */
         if (((changed & FOCUSABLE_MASK) != 0) &&
-                ((privateFlags & HAS_BOUNDS) !=0)) {
+                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
             if (((old & FOCUSABLE_MASK) == FOCUSABLE)
-                    && ((privateFlags & FOCUSED) != 0)) {
+                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
                 /* Give up focus if we are no longer focusable */
                 clearFocus();
             } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
-                    && ((privateFlags & FOCUSED) == 0)) {
+                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
                 /*
                  * Tell the view system that we are now available to take focus
                  * if no one else already has it.
@@ -8301,7 +8416,7 @@
                  * it was not visible. Marking it drawn ensures that the invalidation will
                  * go through.
                  */
-                mPrivateFlags |= DRAWN;
+                mPrivateFlags |= PFLAG_DRAWN;
                 invalidate(true);
 
                 needGlobalAttributesUpdate(true);
@@ -8331,7 +8446,7 @@
                 }
                 // Mark the view drawn to ensure that it gets invalidated properly the next
                 // time it is visible and gets invalidated
-                mPrivateFlags |= DRAWN;
+                mPrivateFlags |= PFLAG_DRAWN;
             }
             if (mAttachInfo != null) {
                 mAttachInfo.mViewVisibilityChanged = true;
@@ -8345,7 +8460,7 @@
              * If this view is becoming invisible, set the DRAWN flag so that
              * the next invalidate() will not be skipped.
              */
-            mPrivateFlags |= DRAWN;
+            mPrivateFlags |= PFLAG_DRAWN;
 
             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
                 // root view becoming invisible shouldn't clear focus and accessibility focus
@@ -8376,25 +8491,25 @@
 
         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
             destroyDrawingCache();
-            mPrivateFlags &= ~DRAWING_CACHE_VALID;
+            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
             invalidateParentCaches();
         }
 
         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
             destroyDrawingCache();
-            mPrivateFlags &= ~DRAWING_CACHE_VALID;
+            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
         }
 
         if ((changed & DRAW_MASK) != 0) {
             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
                 if (mBackground != null) {
-                    mPrivateFlags &= ~SKIP_DRAW;
-                    mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
+                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
+                    mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
                 } else {
-                    mPrivateFlags |= SKIP_DRAW;
+                    mPrivateFlags |= PFLAG_SKIP_DRAW;
                 }
             } else {
-                mPrivateFlags &= ~SKIP_DRAW;
+                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
             }
             requestLayout();
             invalidate(true);
@@ -8568,7 +8683,9 @@
     /**
      * Return the visible drawing bounds of your view. Fills in the output
      * rectangle with the values from getScrollX(), getScrollY(),
-     * getWidth(), and getHeight().
+     * getWidth(), and getHeight(). These bounds do not account for any
+     * transformation properties currently set on the view, such as
+     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
      *
      * @param outRect The (scrolled) drawing bounds of the view.
      */
@@ -8702,7 +8819,7 @@
             // asked for the matrix; recalculate it with the current values
 
             // Figure out if we need to update the pivot point
-            if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+            if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
                 if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
                     info.mPrevWidth = mRight - mLeft;
                     info.mPrevHeight = mBottom - mTop;
@@ -8736,18 +8853,6 @@
         }
     }
 
-    /**
-     * When searching for a view to focus this rectangle is used when considering if this view is
-     * a good candidate for receiving focus.
-     *
-     * By default, the rectangle is the {@link #getDrawingRect}) of the view.
-     *
-     * @param r The rectangle to fill in, in this view's coordinates.
-     */
-    public void getFocusRect(Rect r) {
-        getDrawingRect(r);
-    }
-
    /**
      * Utility method to retrieve the inverse of the current mMatrix property.
      * We cache the matrix to avoid recalculating it when transform properties
@@ -8846,7 +8951,7 @@
         if (mDisplayList != null) {
             mDisplayList.setCameraDistance(-Math.abs(distance) / dpi);
         }
-        if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
             // View was rejected last time it was drawn by its parent; this may have changed
             invalidateParentIfNeeded();
         }
@@ -8892,7 +8997,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setRotation(rotation);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -8943,7 +9048,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setRotationY(rotationY);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -8994,7 +9099,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setRotationX(rotationX);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9037,7 +9142,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setScaleX(scaleX);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9080,7 +9185,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setScaleY(scaleY);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9121,7 +9226,7 @@
      */
     public void setPivotX(float pivotX) {
         ensureTransformationInfo();
-        mPrivateFlags |= PIVOT_EXPLICITLY_SET;
+        mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
         final TransformationInfo info = mTransformationInfo;
         if (info.mPivotX != pivotX) {
             invalidateViewProperty(true, false);
@@ -9131,7 +9236,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setPivotX(pivotX);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9171,7 +9276,7 @@
      */
     public void setPivotY(float pivotY) {
         ensureTransformationInfo();
-        mPrivateFlags |= PIVOT_EXPLICITLY_SET;
+        mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
         final TransformationInfo info = mTransformationInfo;
         if (info.mPivotY != pivotY) {
             invalidateViewProperty(true, false);
@@ -9181,7 +9286,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setPivotY(pivotY);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9241,12 +9346,12 @@
         if (mTransformationInfo.mAlpha != alpha) {
             mTransformationInfo.mAlpha = alpha;
             if (onSetAlpha((int) (alpha * 255))) {
-                mPrivateFlags |= ALPHA_SET;
+                mPrivateFlags |= PFLAG_ALPHA_SET;
                 // subclass is handling alpha - don't optimize rendering cache invalidation
                 invalidateParentCaches();
                 invalidate(true);
             } else {
-                mPrivateFlags &= ~ALPHA_SET;
+                mPrivateFlags &= ~PFLAG_ALPHA_SET;
                 invalidateViewProperty(true, false);
                 if (mDisplayList != null) {
                     mDisplayList.setAlpha(alpha);
@@ -9271,10 +9376,10 @@
             mTransformationInfo.mAlpha = alpha;
             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
             if (subclassHandlesAlpha) {
-                mPrivateFlags |= ALPHA_SET;
+                mPrivateFlags |= PFLAG_ALPHA_SET;
                 return true;
             } else {
-                mPrivateFlags &= ~ALPHA_SET;
+                mPrivateFlags &= ~PFLAG_ALPHA_SET;
                 if (mDisplayList != null) {
                     mDisplayList.setAlpha(alpha);
                 }
@@ -9334,16 +9439,16 @@
             onSizeChanged(width, mBottom - mTop, width, oldHeight);
 
             if (!matrixIsIdentity) {
-                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
                     // A change in dimension means an auto-centered pivot point changes, too
                     mTransformationInfo.mMatrixDirty = true;
                 }
-                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
                 invalidate(true);
             }
             mBackgroundSizeChanged = true;
             invalidateParentIfNeeded();
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9366,7 +9471,7 @@
      * @return The dirty state of this view.
      */
     public boolean isDirty() {
-        return (mPrivateFlags & DIRTY_MASK) != 0;
+        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
     }
 
     /**
@@ -9407,16 +9512,16 @@
             onSizeChanged(width, mBottom - mTop, width, oldHeight);
 
             if (!matrixIsIdentity) {
-                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
                     // A change in dimension means an auto-centered pivot point changes, too
                     mTransformationInfo.mMatrixDirty = true;
                 }
-                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
                 invalidate(true);
             }
             mBackgroundSizeChanged = true;
             invalidateParentIfNeeded();
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9474,16 +9579,16 @@
             onSizeChanged(mRight - mLeft, height, oldWidth, height);
 
             if (!matrixIsIdentity) {
-                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
                     // A change in dimension means an auto-centered pivot point changes, too
                     mTransformationInfo.mMatrixDirty = true;
                 }
-                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
                 invalidate(true);
             }
             mBackgroundSizeChanged = true;
             invalidateParentIfNeeded();
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9538,16 +9643,16 @@
             onSizeChanged(mRight - mLeft, height, oldWidth, height);
 
             if (!matrixIsIdentity) {
-                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
                     // A change in dimension means an auto-centered pivot point changes, too
                     mTransformationInfo.mMatrixDirty = true;
                 }
-                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
                 invalidate(true);
             }
             mBackgroundSizeChanged = true;
             invalidateParentIfNeeded();
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9635,7 +9740,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setTranslationX(translationX);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9676,7 +9781,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setTranslationY(translationY);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9726,7 +9831,7 @@
      * When a view has focus and the user navigates away from it, the next view is searched for
      * starting from the rectangle filled in by this method.
      *
-     * By default, the rectange is the {@link #getDrawingRect(android.graphics.Rect)})
+     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
      * of the view.  However, if your view maintains some idea of internal selection,
      * such as a cursor, or a selected row or column, you should override this method and
      * fill in a more specific rectangle.
@@ -9910,6 +10015,7 @@
             throw new NullPointerException("Layout parameters cannot be null");
         }
         mLayoutParams = params;
+        resolveLayoutParams();
         if (mParent instanceof ViewGroup) {
             ((ViewGroup) mParent).onSetLayoutParams(this, params);
         }
@@ -9917,6 +10023,17 @@
     }
 
     /**
+     * Resolve the layout parameters depending on the resolved layout direction
+     *
+     * @hide
+     */
+    public void resolveLayoutParams() {
+        if (mLayoutParams != null) {
+            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
+        }
+    }
+
+    /**
      * Set the scrolled position of your view. This will cause a call to
      * {@link #onScrollChanged(int, int, int, int)} and the view will be
      * invalidated.
@@ -10137,12 +10254,12 @@
         if (skipInvalidate()) {
             return;
         }
-        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
-                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
-                (mPrivateFlags & INVALIDATED) != INVALIDATED) {
-            mPrivateFlags &= ~DRAWING_CACHE_VALID;
-            mPrivateFlags |= INVALIDATED;
-            mPrivateFlags |= DIRTY;
+        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
+                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
+                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
+            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
+            mPrivateFlags |= PFLAG_INVALIDATED;
+            mPrivateFlags |= PFLAG_DIRTY;
             final ViewParent p = mParent;
             final AttachInfo ai = mAttachInfo;
             //noinspection PointlessBooleanExpression,ConstantConditions
@@ -10180,12 +10297,12 @@
         if (skipInvalidate()) {
             return;
         }
-        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
-                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
-                (mPrivateFlags & INVALIDATED) != INVALIDATED) {
-            mPrivateFlags &= ~DRAWING_CACHE_VALID;
-            mPrivateFlags |= INVALIDATED;
-            mPrivateFlags |= DIRTY;
+        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
+                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
+                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
+            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
+            mPrivateFlags |= PFLAG_INVALIDATED;
+            mPrivateFlags |= PFLAG_DIRTY;
             final ViewParent p = mParent;
             final AttachInfo ai = mAttachInfo;
             //noinspection PointlessBooleanExpression,ConstantConditions
@@ -10232,15 +10349,15 @@
         if (skipInvalidate()) {
             return;
         }
-        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
-                (invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) ||
-                (mPrivateFlags & INVALIDATED) != INVALIDATED || isOpaque() != mLastIsOpaque) {
+        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
+                (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) ||
+                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED || isOpaque() != mLastIsOpaque) {
             mLastIsOpaque = isOpaque();
-            mPrivateFlags &= ~DRAWN;
-            mPrivateFlags |= DIRTY;
+            mPrivateFlags &= ~PFLAG_DRAWN;
+            mPrivateFlags |= PFLAG_DIRTY;
             if (invalidateCache) {
-                mPrivateFlags |= INVALIDATED;
-                mPrivateFlags &= ~DRAWING_CACHE_VALID;
+                mPrivateFlags |= PFLAG_INVALIDATED;
+                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
             }
             final AttachInfo ai = mAttachInfo;
             final ViewParent p = mParent;
@@ -10281,12 +10398,12 @@
      * list properties are not being used in this view
      */
     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
-        if (mDisplayList == null || (mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) {
+        if (mDisplayList == null || (mPrivateFlags & PFLAG_DRAW_ANIMATION) == PFLAG_DRAW_ANIMATION) {
             if (invalidateParent) {
                 invalidateParentCaches();
             }
             if (forceRedraw) {
-                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
             }
             invalidate(false);
         } else {
@@ -10330,7 +10447,7 @@
      */
     protected void invalidateParentCaches() {
         if (mParent instanceof View) {
-            ((View) mParent).mPrivateFlags |= INVALIDATED;
+            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
         }
     }
 
@@ -10362,9 +10479,8 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public boolean isOpaque() {
-        return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK &&
-                ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1)
-                        >= 1.0f - ViewConfiguration.ALPHA_THRESHOLD);
+        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
+                ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1.0f) >= 1.0f);
     }
 
     /**
@@ -10377,17 +10493,17 @@
         //   - Doesn't have scrollbars or scrollbars are inside overlay
 
         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
-            mPrivateFlags |= OPAQUE_BACKGROUND;
+            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
         } else {
-            mPrivateFlags &= ~OPAQUE_BACKGROUND;
+            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
         }
 
         final int flags = mViewFlags;
         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
-            mPrivateFlags |= OPAQUE_SCROLLBARS;
+            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
         } else {
-            mPrivateFlags &= ~OPAQUE_SCROLLBARS;
+            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
         }
     }
 
@@ -10395,7 +10511,7 @@
      * @hide
      */
     protected boolean hasOpaqueScrollbars() {
-        return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
+        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
     }
 
     /**
@@ -10425,9 +10541,6 @@
      * <p>Causes the Runnable to be added to the message queue.
      * The runnable will be run on the user interface thread.</p>
      *
-     * <p>This method can be invoked from outside of the UI thread
-     * only when this View is attached to a window.</p>
-     *
      * @param action The Runnable that will be executed.
      *
      * @return Returns true if the Runnable was successfully placed in to the
@@ -10452,9 +10565,6 @@
      * after the specified amount of time elapses.
      * The runnable will be run on the user interface thread.</p>
      *
-     * <p>This method can be invoked from outside of the UI thread
-     * only when this View is attached to a window.</p>
-     *
      * @param action The Runnable that will be executed.
      * @param delayMillis The delay (in milliseconds) until the Runnable
      *        will be executed.
@@ -10483,9 +10593,6 @@
      * <p>Causes the Runnable to execute on the next animation time step.
      * The runnable will be run on the user interface thread.</p>
      *
-     * <p>This method can be invoked from outside of the UI thread
-     * only when this View is attached to a window.</p>
-     *
      * @param action The Runnable that will be executed.
      *
      * @see #postOnAnimationDelayed
@@ -10507,9 +10614,6 @@
      * after the specified amount of time elapses.
      * The runnable will be run on the user interface thread.</p>
      *
-     * <p>This method can be invoked from outside of the UI thread
-     * only when this View is attached to a window.</p>
-     *
      * @param action The Runnable that will be executed.
      * @param delayMillis The delay (in milliseconds) until the Runnable
      *        will be executed.
@@ -10531,9 +10635,6 @@
     /**
      * <p>Removes the specified Runnable from the message queue.</p>
      *
-     * <p>This method can be invoked from outside of the UI thread
-     * only when this View is attached to a window.</p>
-     *
      * @param action The Runnable to remove from the message handling queue
      *
      * @return true if this view could ask the Handler to remove the Runnable,
@@ -10923,7 +11024,7 @@
      * @hide
      */
     protected void recomputePadding() {
-        setPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
+        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
     }
 
     /**
@@ -11331,9 +11432,13 @@
                     scrollBar.setParameters(computeVerticalScrollRange(),
                                             computeVerticalScrollOffset(),
                                             computeVerticalScrollExtent(), true);
-                    switch (mVerticalScrollbarPosition) {
+                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
+                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
+                        verticalScrollbarPosition = isLayoutRtl() ?
+                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
+                    }
+                    switch (verticalScrollbarPosition) {
                         default:
-                        case SCROLLBAR_POSITION_DEFAULT:
                         case SCROLLBAR_POSITION_RIGHT:
                             left = scrollX + width - size - (mUserPaddingRight & inside);
                             break;
@@ -11436,24 +11541,17 @@
      * @see #onDetachedFromWindow()
      */
     protected void onAttachedToWindow() {
-        if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
+        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
             mParent.requestTransparentRegion(this);
         }
 
-        if ((mPrivateFlags & AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
+        if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
             initialAwakenScrollBars();
-            mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
+            mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
         }
 
         jumpDrawablesToCurrentState();
 
-        // Order is important here: LayoutDirection MUST be resolved before Padding
-        // and TextDirection
-        resolveLayoutDirection();
-        resolvePadding();
-        resolveTextDirection();
-        resolveTextAlignment();
-
         clearAccessibilityFocus();
         if (isFocused()) {
             InputMethodManager imm = InputMethodManager.peekInstance();
@@ -11466,6 +11564,48 @@
     }
 
     /**
+     * Resolve all RTL related properties.
+     *
+     * @hide
+     */
+    public void resolveRtlPropertiesIfNeeded() {
+        if (!needRtlPropertiesResolution()) return;
+
+        // Order is important here: LayoutDirection MUST be resolved first
+        if (!isLayoutDirectionResolved()) {
+            resolveLayoutDirection();
+            resolveLayoutParams();
+        }
+        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
+        if (!isTextDirectionResolved()) {
+            resolveTextDirection();
+        }
+        if (!isTextAlignmentResolved()) {
+            resolveTextAlignment();
+        }
+        if (!isPaddingResolved()) {
+            resolvePadding();
+        }
+        if (!isDrawablesResolved()) {
+            resolveDrawables();
+        }
+        onRtlPropertiesChanged(getLayoutDirection());
+    }
+
+    /**
+     * Reset resolution of all RTL related properties.
+     *
+     * @hide
+     */
+    public void resetRtlProperties() {
+        resetResolvedLayoutDirection();
+        resetResolvedTextDirection();
+        resetResolvedTextAlignment();
+        resetResolvedPadding();
+        resetResolvedDrawables();
+    }
+
+    /**
      * @see #onScreenStateChanged(int)
      */
     void dispatchScreenStateChanged(int screenState) {
@@ -11492,36 +11632,74 @@
     }
 
     /**
+     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
+     * RTL not supported)
+     */
+    private boolean isRtlCompatibilityMode() {
+        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
+        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
+    }
+
+    /**
+     * @return true if RTL properties need resolution.
+     */
+    private boolean needRtlPropertiesResolution() {
+        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
+    }
+
+    /**
+     * Called when any RTL property (layout direction or text direction or text alignment) has
+     * been changed.
+     *
+     * Subclasses need to override this method to take care of cached information that depends on the
+     * resolved layout direction, or to inform child views that inherit their layout direction.
+     *
+     * The default implementation does nothing.
+     *
+     * @param layoutDirection the direction of the layout
+     *
+     * @see #LAYOUT_DIRECTION_LTR
+     * @see #LAYOUT_DIRECTION_RTL
+     */
+    public void onRtlPropertiesChanged(int layoutDirection) {
+    }
+
+    /**
      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
      * that the parent directionality can and will be resolved before its children.
-     * Will call {@link View#onResolvedLayoutDirectionChanged} when resolution is done.
+     *
+     * @return true if resolution has been done, false otherwise.
+     *
      * @hide
      */
-    public void resolveLayoutDirection() {
+    public boolean resolveLayoutDirection() {
         // Clear any previous layout direction resolution
-        mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_MASK;
+        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
 
         if (hasRtlSupport()) {
             // Set resolved depending on layout direction
-            switch (getLayoutDirection()) {
+            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
+                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
                 case LAYOUT_DIRECTION_INHERIT:
-                    // If this is root view, no need to look at parent's layout dir.
-                    if (canResolveLayoutDirection()) {
-                        ViewGroup viewGroup = ((ViewGroup) mParent);
+                    // We cannot resolve yet. LTR is by default and let the resolution happen again
+                    // later to get the correct resolved value
+                    if (!canResolveLayoutDirection()) return false;
 
-                        if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
-                            mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
-                        }
-                    } else {
-                        // Nothing to do, LTR by default
+                    View parent = ((View) mParent);
+                    // Parent has not yet resolved, LTR is still the default
+                    if (!parent.isLayoutDirectionResolved()) return false;
+
+                    if (parent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
                     }
                     break;
                 case LAYOUT_DIRECTION_RTL:
-                    mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
+                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
                     break;
                 case LAYOUT_DIRECTION_LOCALE:
-                    if(isLayoutDirectionRtl(Locale.getDefault())) {
-                        mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
+                    if((LAYOUT_DIRECTION_RTL ==
+                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
+                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
                     }
                     break;
                 default:
@@ -11530,137 +11708,115 @@
         }
 
         // Set to resolved
-        mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
-        onResolvedLayoutDirectionChanged();
-        // Resolve padding
-        resolvePadding();
-    }
-
-    /**
-     * Called when layout direction has been resolved.
-     *
-     * The default implementation does nothing.
-     * @hide
-     */
-    public void onResolvedLayoutDirectionChanged() {
-    }
-
-    /**
-     * Resolve padding depending on layout direction.
-     * @hide
-     */
-    public void resolvePadding() {
-        // If the user specified the absolute padding (either with android:padding or
-        // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
-        // use the default padding or the padding from the background drawable
-        // (stored at this point in mPadding*)
-        int resolvedLayoutDirection = getResolvedLayoutDirection();
-        switch (resolvedLayoutDirection) {
-            case LAYOUT_DIRECTION_RTL:
-                // Start user padding override Right user padding. Otherwise, if Right user
-                // padding is not defined, use the default Right padding. If Right user padding
-                // is defined, just use it.
-                if (mUserPaddingStart >= 0) {
-                    mUserPaddingRight = mUserPaddingStart;
-                } else if (mUserPaddingRight < 0) {
-                    mUserPaddingRight = mPaddingRight;
-                }
-                if (mUserPaddingEnd >= 0) {
-                    mUserPaddingLeft = mUserPaddingEnd;
-                } else if (mUserPaddingLeft < 0) {
-                    mUserPaddingLeft = mPaddingLeft;
-                }
-                break;
-            case LAYOUT_DIRECTION_LTR:
-            default:
-                // Start user padding override Left user padding. Otherwise, if Left user
-                // padding is not defined, use the default left padding. If Left user padding
-                // is defined, just use it.
-                if (mUserPaddingStart >= 0) {
-                    mUserPaddingLeft = mUserPaddingStart;
-                } else if (mUserPaddingLeft < 0) {
-                    mUserPaddingLeft = mPaddingLeft;
-                }
-                if (mUserPaddingEnd >= 0) {
-                    mUserPaddingRight = mUserPaddingEnd;
-                } else if (mUserPaddingRight < 0) {
-                    mUserPaddingRight = mPaddingRight;
-                }
-        }
-
-        mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
-
-        if(isPaddingRelative()) {
-            setPaddingRelative(mUserPaddingStart, mPaddingTop, mUserPaddingEnd, mUserPaddingBottom);
-        } else {
-            recomputePadding();
-        }
-        onPaddingChanged(resolvedLayoutDirection);
-    }
-
-    /**
-     * Resolve padding depending on the layout direction. Subclasses that care about
-     * padding resolution should override this method. The default implementation does
-     * nothing.
-     *
-     * @param layoutDirection the direction of the layout
-     *
-     * @see {@link #LAYOUT_DIRECTION_LTR}
-     * @see {@link #LAYOUT_DIRECTION_RTL}
-     * @hide
-     */
-    public void onPaddingChanged(int layoutDirection) {
+        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
+        return true;
     }
 
     /**
      * Check if layout direction resolution can be done.
      *
      * @return true if layout direction resolution can be done otherwise return false.
+     *
      * @hide
      */
     public boolean canResolveLayoutDirection() {
-        switch (getLayoutDirection()) {
+        switch (getRawLayoutDirection()) {
             case LAYOUT_DIRECTION_INHERIT:
-                return (mParent != null) && (mParent instanceof ViewGroup);
+                return (mParent != null) && (mParent instanceof ViewGroup) &&
+                       ((ViewGroup) mParent).canResolveLayoutDirection();
             default:
                 return true;
         }
     }
 
     /**
-     * Reset the resolved layout direction. Will call {@link View#onResolvedLayoutDirectionReset}
-     * when reset is done.
+     * Reset the resolved layout direction. Layout direction will be resolved during a call to
+     * {@link #onMeasure(int, int)}.
+     *
      * @hide
      */
     public void resetResolvedLayoutDirection() {
         // Reset the current resolved bits
-        mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_MASK;
-        onResolvedLayoutDirectionReset();
-        // Reset also the text direction
-        resetResolvedTextDirection();
+        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
     }
 
     /**
-     * Called during reset of resolved layout direction.
+     * @return true if the layout direction is inherited.
      *
-     * Subclasses need to override this method to clear cached information that depends on the
-     * resolved layout direction, or to inform child views that inherit their layout direction.
-     *
-     * The default implementation does nothing.
      * @hide
      */
-    public void onResolvedLayoutDirectionReset() {
+    public boolean isLayoutDirectionInherited() {
+        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
     }
 
     /**
-     * Check if a Locale uses an RTL script.
+     * @return true if layout direction has been resolved.
+     */
+    private boolean isLayoutDirectionResolved() {
+        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
+    }
+
+    /**
+     * Return if padding has been resolved
      *
-     * @param locale Locale to check
-     * @return true if the Locale uses an RTL script.
      * @hide
      */
-    protected static boolean isLayoutDirectionRtl(Locale locale) {
-        return (LAYOUT_DIRECTION_RTL == LocaleUtil.getLayoutDirectionFromLocale(locale));
+    boolean isPaddingResolved() {
+        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
+    }
+
+    /**
+     * Resolve padding depending on layout direction.
+     *
+     * @hide
+     */
+    public void resolvePadding() {
+        if (!isRtlCompatibilityMode()) {
+            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
+            // If start / end padding are defined, they will be resolved (hence overriding) to
+            // left / right or right / left depending on the resolved layout direction.
+            // If start / end padding are not defined, use the left / right ones.
+            int resolvedLayoutDirection = getLayoutDirection();
+            // Set user padding to initial values ...
+            mUserPaddingLeft = mUserPaddingLeftInitial;
+            mUserPaddingRight = mUserPaddingRightInitial;
+            // ... then resolve it.
+            switch (resolvedLayoutDirection) {
+                case LAYOUT_DIRECTION_RTL:
+                    if (mUserPaddingStart != UNDEFINED_PADDING) {
+                        mUserPaddingRight = mUserPaddingStart;
+                    }
+                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
+                        mUserPaddingLeft = mUserPaddingEnd;
+                    }
+                    break;
+                case LAYOUT_DIRECTION_LTR:
+                default:
+                    if (mUserPaddingStart != UNDEFINED_PADDING) {
+                        mUserPaddingLeft = mUserPaddingStart;
+                    }
+                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
+                        mUserPaddingRight = mUserPaddingEnd;
+                    }
+            }
+
+            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
+
+            internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
+                    mUserPaddingBottom);
+            onRtlPropertiesChanged(resolvedLayoutDirection);
+        }
+
+        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
+    }
+
+    /**
+     * Reset the resolved layout direction.
+     *
+     * @hide
+     */
+    public void resetResolvedPadding() {
+        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
     }
 
     /**
@@ -11670,7 +11826,7 @@
      * @see #onAttachedToWindow()
      */
     protected void onDetachedFromWindow() {
-        mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
+        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
 
         removeUnsetPressCallback();
         removeLongPressCallback();
@@ -11693,8 +11849,8 @@
 
         mCurrentAnimation = null;
 
-        resetResolvedLayoutDirection();
-        resetResolvedTextAlignment();
+        resetRtlProperties();
+        onRtlPropertiesChanged(LAYOUT_DIRECTION_DEFAULT);
         resetAccessibilityStateChanged();
     }
 
@@ -11737,6 +11893,15 @@
     }
 
     /**
+     * Gets the logical display to which the view's window has been attached.
+     *
+     * @return The logical display, or null if the view is not currently attached to a window.
+     */
+    public Display getDisplay() {
+        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
+    }
+
+    /**
      * Retrieve private session object this view hierarchy is using to
      * communicate with the window manager.
      * @return the session object to communicate with the window manager
@@ -11754,14 +11919,14 @@
         mAttachInfo = info;
         mWindowAttachCount++;
         // We will need to evaluate the drawable state at least once.
-        mPrivateFlags |= DRAWABLE_STATE_DIRTY;
+        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
         if (mFloatingTreeObserver != null) {
             info.mTreeObserver.merge(mFloatingTreeObserver);
             mFloatingTreeObserver = null;
         }
-        if ((mPrivateFlags&SCROLL_CONTAINER) != 0) {
+        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
             mAttachInfo.mScrollContainers.add(this);
-            mPrivateFlags |= SCROLL_CONTAINER_ADDED;
+            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
         }
         performCollectViewAttributes(mAttachInfo, visibility);
         onAttachedToWindow();
@@ -11783,10 +11948,11 @@
         if (vis != GONE) {
             onWindowVisibilityChanged(vis);
         }
-        if ((mPrivateFlags&DRAWABLE_STATE_DIRTY) != 0) {
+        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
             // If nobody has evaluated the drawable state yet, then do it now.
             refreshDrawableState();
         }
+        needGlobalAttributesUpdate(false);
     }
 
     void dispatchDetachedFromWindow() {
@@ -11813,9 +11979,9 @@
             }
         }
 
-        if ((mPrivateFlags & SCROLL_CONTAINER_ADDED) != 0) {
+        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
             mAttachInfo.mScrollContainers.remove(this);
-            mPrivateFlags &= ~SCROLL_CONTAINER_ADDED;
+            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
         }
 
         mAttachInfo = null;
@@ -11847,9 +12013,9 @@
      */
     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
-            mPrivateFlags &= ~SAVE_STATE_CALLED;
+            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
             Parcelable state = onSaveInstanceState();
-            if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
+            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
                 throw new IllegalStateException(
                         "Derived class did not call super.onSaveInstanceState()");
             }
@@ -11883,7 +12049,7 @@
      * @see #setSaveEnabled(boolean)
      */
     protected Parcelable onSaveInstanceState() {
-        mPrivateFlags |= SAVE_STATE_CALLED;
+        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
         return BaseSavedState.EMPTY_STATE;
     }
 
@@ -11918,9 +12084,9 @@
             if (state != null) {
                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
                 // + ": " + state);
-                mPrivateFlags &= ~SAVE_STATE_CALLED;
+                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
                 onRestoreInstanceState(state);
-                if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
+                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
                     throw new IllegalStateException(
                             "Derived class did not call super.onRestoreInstanceState()");
                 }
@@ -11941,7 +12107,7 @@
      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
      */
     protected void onRestoreInstanceState(Parcelable state) {
-        mPrivateFlags |= SAVE_STATE_CALLED;
+        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
         if (state != BaseSavedState.EMPTY_STATE && state != null) {
             throw new IllegalArgumentException("Wrong state class, expecting View State but "
                     + "received " + state.getClass().toString() + " instead. This usually happens "
@@ -12016,13 +12182,13 @@
      * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
      * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
      * equivalent to setting a hardware layer on this view and providing a paint with
-     * the desired alpha value.<p>
+     * the desired alpha value.</p>
      *
      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
      * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
      * for more information on when and how to use layers.</p>
      *
-     * @param layerType The ype of layer to use with this view, must be one of
+     * @param layerType The type of layer to use with this view, must be one of
      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
      *        {@link #LAYER_TYPE_HARDWARE}
      * @param paint The paint used to compose the layer. This argument is optional
@@ -12074,6 +12240,50 @@
     }
 
     /**
+     * Updates the {@link Paint} object used with the current layer (used only if the current
+     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
+     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
+     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
+     * ensure that the view gets redrawn immediately.
+     *
+     * <p>A layer is associated with an optional {@link android.graphics.Paint}
+     * instance that controls how the layer is composed on screen. The following
+     * properties of the paint are taken into account when composing the layer:</p>
+     * <ul>
+     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
+     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
+     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
+     * </ul>
+     *
+     * <p>If this view has an alpha value set to < 1.0 by calling
+     * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
+     * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
+     * equivalent to setting a hardware layer on this view and providing a paint with
+     * the desired alpha value.</p>
+     *
+     * @param paint The paint used to compose the layer. This argument is optional
+     *        and can be null. It is ignored when the layer type is
+     *        {@link #LAYER_TYPE_NONE}
+     *
+     * @see #setLayerType(int, android.graphics.Paint)
+     */
+    public void setLayerPaint(Paint paint) {
+        int layerType = getLayerType();
+        if (layerType != LAYER_TYPE_NONE) {
+            mLayerPaint = paint == null ? new Paint() : paint;
+            if (layerType == LAYER_TYPE_HARDWARE) {
+                HardwareLayer layer = getHardwareLayer();
+                if (layer != null) {
+                    layer.setLayerPaint(paint);
+                }
+                invalidateViewProperty(false, false);
+            } else {
+                invalidate();
+            }
+        }
+    }
+
+    /**
      * Indicates whether this view has a static layer. A view with layer type
      * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
      * dynamic.
@@ -12135,13 +12345,6 @@
         }
     }
 
-    // Make sure the HardwareRenderer.validate() was invoked before calling this method
-    void flushLayer() {
-        if (mLayerType == LAYER_TYPE_HARDWARE && mHardwareLayer != null) {
-            mHardwareLayer.flush();
-        }
-    }
-
     /**
      * <p>Returns a hardware layer that can be used to draw this view again
      * without executing its draw method.</p>
@@ -12163,14 +12366,30 @@
             return null;
         }
 
-        if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
+        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
             if (mHardwareLayer == null) {
                 mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
                         width, height, isOpaque());
                 mLocalDirtyRect.set(0, 0, width, height);
-            } else if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
-                mHardwareLayer.resize(width, height);
-                mLocalDirtyRect.set(0, 0, width, height);
+            } else {
+                if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
+                    if (mHardwareLayer.resize(width, height)) {
+                        mLocalDirtyRect.set(0, 0, width, height);
+                    }
+                }
+
+                // This should not be necessary but applications that change
+                // the parameters of their background drawable without calling
+                // this.setBackground(Drawable) can leave the view in a bad state
+                // (for instance isOpaque() returns true, but the background is
+                // not opaque.)
+                computeOpaqueFlags();
+
+                final boolean opaque = isOpaque();
+                if (mHardwareLayer.isValid() && mHardwareLayer.isOpaque() != opaque) {
+                    mHardwareLayer.setOpaque(opaque);
+                    mLocalDirtyRect.set(0, 0, width, height);
+                }
             }
 
             // The layer is not valid if the underlying GPU resources cannot be allocated
@@ -12178,7 +12397,11 @@
                 return null;
             }
 
-            mHardwareLayer.redraw(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect);
+            mHardwareLayer.setLayerPaint(mLayerPaint);
+            mHardwareLayer.redrawLater(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect);
+            ViewRootImpl viewRoot = getViewRootImpl();
+            if (viewRoot != null) viewRoot.pushHardwareLayerUpdate(mHardwareLayer);
+
             mLocalDirtyRect.setEmpty();
         }
 
@@ -12202,6 +12425,9 @@
                 mHardwareLayer.destroy();
                 mHardwareLayer = null;
 
+                if (mDisplayList != null) {
+                    mDisplayList.reset();
+                }
                 invalidate(true);
                 invalidateParentCaches();
             }
@@ -12278,10 +12504,10 @@
      */
     @SuppressWarnings({"UnusedDeclaration"})
     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
-        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.DIRTY_MASK) +
-                ") DRAWN(" + (mPrivateFlags & DRAWN) + ")" + " CACHE_VALID(" +
-                (mPrivateFlags & View.DRAWING_CACHE_VALID) +
-                ") INVALIDATED(" + (mPrivateFlags & INVALIDATED) + ")");
+        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
+                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
+                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
+                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
         if (clear) {
             mPrivateFlags &= clearMask;
         }
@@ -12345,15 +12571,15 @@
             return null;
         }
 
-        if (((mPrivateFlags & DRAWING_CACHE_VALID) == 0 ||
+        if (((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 ||
                 displayList == null || !displayList.isValid() ||
                 (!isLayer && mRecreateDisplayList))) {
             // Don't need to recreate the display list, just need to tell our
             // children to restore/recreate theirs
             if (displayList != null && displayList.isValid() &&
                     !isLayer && !mRecreateDisplayList) {
-                mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
-                mPrivateFlags &= ~DIRTY_MASK;
+                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
+                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                 dispatchGetDisplayList();
 
                 return displayList;
@@ -12382,9 +12608,7 @@
                 canvas.setViewport(width, height);
                 // The dirty rect should always be null for a display list
                 canvas.onPreDraw(null);
-                int layerType = (
-                        !(mParent instanceof ViewGroup) || ((ViewGroup)mParent).mDrawLayers) ?
-                        getLayerType() : LAYER_TYPE_NONE;
+                int layerType = getLayerType();
                 if (!isLayer && layerType != LAYER_TYPE_NONE) {
                     if (layerType == LAYER_TYPE_HARDWARE) {
                         final HardwareLayer layer = getHardwareLayer();
@@ -12410,12 +12634,12 @@
 
                     canvas.translate(-mScrollX, -mScrollY);
                     if (!isLayer) {
-                        mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
-                        mPrivateFlags &= ~DIRTY_MASK;
+                        mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
+                        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                     }
 
                     // Fast path for layouts with no backgrounds
-                    if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                         dispatchDraw(canvas);
                     } else {
                         draw(canvas);
@@ -12433,8 +12657,8 @@
                 }
             }
         } else if (!isLayer) {
-            mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
-            mPrivateFlags &= ~DIRTY_MASK;
+            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
+            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
         }
 
         return displayList;
@@ -12556,7 +12780,7 @@
     public void setDrawingCacheBackgroundColor(int color) {
         if (color != mDrawingCacheBackgroundColor) {
             mDrawingCacheBackgroundColor = color;
-            mPrivateFlags &= ~DRAWING_CACHE_VALID;
+            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
         }
     }
 
@@ -12602,7 +12826,7 @@
      * @see #destroyDrawingCache()
      */
     public void buildDrawingCache(boolean autoScale) {
-        if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ?
+        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
             mCachingFailed = false;
 
@@ -12621,10 +12845,15 @@
             final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
             final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
 
-            if (width <= 0 || height <= 0 ||
-                     // Projected bitmap size in bytes
-                    (width * height * (opaque && !use32BitCache ? 2 : 4) >
-                            ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {
+            final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
+            final long drawingCacheSize =
+                    ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
+            if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
+                if (width > 0 && height > 0) {
+                    Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
+                            + projectedBitmapSize + " bytes, only "
+                            + drawingCacheSize + " available");
+                }
                 destroyDrawingCache();
                 mCachingFailed = true;
                 return;
@@ -12662,7 +12891,8 @@
                 if (bitmap != null) bitmap.recycle();
 
                 try {
-                    bitmap = Bitmap.createBitmap(width, height, quality);
+                    bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
+                            width, height, quality);
                     bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
                     if (autoScale) {
                         mDrawingCache = bitmap;
@@ -12717,15 +12947,15 @@
 
             canvas.translate(-mScrollX, -mScrollY);
 
-            mPrivateFlags |= DRAWN;
+            mPrivateFlags |= PFLAG_DRAWN;
             if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
                     mLayerType != LAYER_TYPE_NONE) {
-                mPrivateFlags |= DRAWING_CACHE_VALID;
+                mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
             }
 
             // Fast path for layouts with no backgrounds
-            if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
-                mPrivateFlags &= ~DIRTY_MASK;
+            if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
+                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                 dispatchDraw(canvas);
             } else {
                 draw(canvas);
@@ -12754,7 +12984,8 @@
         width = (int) ((width * scale) + 0.5f);
         height = (int) ((height * scale) + 0.5f);
 
-        Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1, height > 0 ? height : 1, quality);
+        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
+                width > 0 ? width : 1, height > 0 ? height : 1, quality);
         if (bitmap == null) {
             throw new OutOfMemoryError();
         }
@@ -12792,10 +13023,10 @@
 
         // Temporarily remove the dirty mask
         int flags = mPrivateFlags;
-        mPrivateFlags &= ~DIRTY_MASK;
+        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
 
         // Fast path for layouts with no backgrounds
-        if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
             dispatchDraw(canvas);
         } else {
             draw(canvas);
@@ -12979,13 +13210,13 @@
 
         if (more) {
             if (!a.willChangeBounds()) {
-                if ((flags & (parent.FLAG_OPTIMIZE_INVALIDATE | parent.FLAG_ANIMATION_DONE)) ==
-                        parent.FLAG_OPTIMIZE_INVALIDATE) {
-                    parent.mGroupFlags |= parent.FLAG_INVALIDATE_REQUIRED;
-                } else if ((flags & parent.FLAG_INVALIDATE_REQUIRED) == 0) {
+                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
+                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
+                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
+                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
                     // The child need to draw an animation, potentially offscreen, so
                     // make sure we do not cancel invalidate requests
-                    parent.mPrivateFlags |= DRAW_ANIMATION;
+                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
                     parent.invalidate(mLeft, mTop, mRight, mBottom);
                 }
             } else {
@@ -12998,7 +13229,7 @@
 
                 // The child need to draw an animation, potentially offscreen, so
                 // make sure we do not cancel invalidate requests
-                parent.mPrivateFlags |= DRAW_ANIMATION;
+                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
 
                 final int left = mLeft + (int) region.left;
                 final int top = mTop + (int) region.top;
@@ -13060,7 +13291,7 @@
                     mTransformationInfo.matrix3D = new Matrix();
                 }
                 displayList.setCameraDistance(mTransformationInfo.mCamera.getLocationZ());
-                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == PIVOT_EXPLICITLY_SET) {
+                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == PFLAG_PIVOT_EXPLICITLY_SET) {
                     displayList.setPivotX(getPivotX());
                     displayList.setPivotY(getPivotY());
                 }
@@ -13091,7 +13322,7 @@
 
         boolean scalingRequired = false;
         boolean caching;
-        int layerType = parent.mDrawLayers ? getLayerType() : LAYER_TYPE_NONE;
+        int layerType = getLayerType();
 
         final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
         if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
@@ -13108,15 +13339,15 @@
             more = drawAnimation(parent, drawingTime, a, scalingRequired);
             concatMatrix = a.willChangeTransformationMatrix();
             if (concatMatrix) {
-                mPrivateFlags3 |= VIEW_IS_ANIMATING_TRANSFORM;
+                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
             }
             transformToApply = parent.mChildTransformation;
         } else {
-            if ((mPrivateFlags3 & VIEW_IS_ANIMATING_TRANSFORM) == VIEW_IS_ANIMATING_TRANSFORM &&
+            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) == PFLAG3_VIEW_IS_ANIMATING_TRANSFORM &&
                     mDisplayList != null) {
                 // No longer animating: clear out old animation matrix
                 mDisplayList.setAnimationMatrix(null);
-                mPrivateFlags3 &= ~VIEW_IS_ANIMATING_TRANSFORM;
+                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
             }
             if (!useDisplayListProperties &&
                     (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
@@ -13135,27 +13366,25 @@
 
         // Sets the flag as early as possible to allow draw() implementations
         // to call invalidate() successfully when doing animations
-        mPrivateFlags |= DRAWN;
+        mPrivateFlags |= PFLAG_DRAWN;
 
-        if (!concatMatrix && canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
-                (mPrivateFlags & DRAW_ANIMATION) == 0) {
-            mPrivateFlags2 |= VIEW_QUICK_REJECTED;
+        if (!concatMatrix &&
+                (flags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
+                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
+                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
+                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
+            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
             return more;
         }
-        mPrivateFlags2 &= ~VIEW_QUICK_REJECTED;
+        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
 
         if (hardwareAccelerated) {
             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
             // retain the flag's value temporarily in the mRecreateDisplayList flag
-            mRecreateDisplayList = (mPrivateFlags & INVALIDATED) == INVALIDATED;
-            mPrivateFlags &= ~INVALIDATED;
+            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
+            mPrivateFlags &= ~PFLAG_INVALIDATED;
         }
 
-        computeScroll();
-
-        final int sx = mScrollX;
-        final int sy = mScrollY;
-
         DisplayList displayList = null;
         Bitmap cache = null;
         boolean hasDisplayList = false;
@@ -13202,6 +13431,14 @@
             }
         }
 
+        int sx = 0;
+        int sy = 0;
+        if (!hasDisplayList) {
+            computeScroll();
+            sx = mScrollX;
+            sy = mScrollY;
+        }
+
         final boolean hasNoCache = cache == null || hasDisplayList;
         final boolean offsetForScroll = cache == null && !hasDisplayList &&
                 layerType != LAYER_TYPE_HARDWARE;
@@ -13229,7 +13466,7 @@
 
         float alpha = useDisplayListProperties ? 1 : getAlpha();
         if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() ||
-                (mPrivateFlags3 & VIEW_IS_ANIMATING_ALPHA) == VIEW_IS_ANIMATING_ALPHA) {
+                (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
             if (transformToApply != null || !childHasIdentityMatrix) {
                 int transX = 0;
                 int transY = 0;
@@ -13269,11 +13506,11 @@
 
             // Deal with alpha if it is or used to be <1
             if (alpha < 1 ||
-                    (mPrivateFlags3 & VIEW_IS_ANIMATING_ALPHA) == VIEW_IS_ANIMATING_ALPHA) {
+                    (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
                 if (alpha < 1) {
-                    mPrivateFlags3 |= VIEW_IS_ANIMATING_ALPHA;
+                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
                 } else {
-                    mPrivateFlags3 &= ~VIEW_IS_ANIMATING_ALPHA;
+                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
                 }
                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
                 if (hasNoCache) {
@@ -13294,13 +13531,13 @@
                         }
                     } else {
                         // Alpha is handled by the child directly, clobber the layer's alpha
-                        mPrivateFlags |= ALPHA_SET;
+                        mPrivateFlags |= PFLAG_ALPHA_SET;
                     }
                 }
             }
-        } else if ((mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
+        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
             onSetAlpha(255);
-            mPrivateFlags &= ~ALPHA_SET;
+            mPrivateFlags &= ~PFLAG_ALPHA_SET;
         }
 
         if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN &&
@@ -13347,19 +13584,19 @@
             if (!layerRendered) {
                 if (!hasDisplayList) {
                     // Fast path for layouts with no backgrounds
-                    if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
-                        mPrivateFlags &= ~DIRTY_MASK;
+                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
+                        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                         dispatchDraw(canvas);
                     } else {
                         draw(canvas);
                     }
                 } else {
-                    mPrivateFlags &= ~DIRTY_MASK;
+                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                     ((HardwareCanvas) canvas).drawDisplayList(displayList, null, flags);
                 }
             }
         } else if (cache != null) {
-            mPrivateFlags &= ~DIRTY_MASK;
+            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
             Paint cachePaint;
 
             if (layerType == LAYER_TYPE_NONE) {
@@ -13399,7 +13636,7 @@
             // display lists to render, force an invalidate to allow the animation to
             // continue drawing another frame
             parent.invalidate(true);
-            if (a.hasAlpha() && (mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
+            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
                 // alpha animations should cause the child to recreate its display list
                 invalidate(true);
             }
@@ -13421,9 +13658,9 @@
      */
     public void draw(Canvas canvas) {
         final int privateFlags = mPrivateFlags;
-        final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&
+        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
-        mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN;
+        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
 
         /*
          * Draw traversal performs several drawing steps which must be executed
@@ -13678,12 +13915,12 @@
         String output = "";
         int numFlags = 0;
 
-        if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) {
+        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
             output += "WANTS_FOCUS";
             numFlags++;
         }
 
-        if ((privateFlags & FOCUSED) == FOCUSED) {
+        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
             if (numFlags > 0) {
                 output += " ";
             }
@@ -13691,7 +13928,7 @@
             numFlags++;
         }
 
-        if ((privateFlags & SELECTED) == SELECTED) {
+        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
             if (numFlags > 0) {
                 output += " ";
             }
@@ -13699,7 +13936,7 @@
             numFlags++;
         }
 
-        if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) {
+        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
             if (numFlags > 0) {
                 output += " ";
             }
@@ -13707,7 +13944,7 @@
             numFlags++;
         }
 
-        if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
             if (numFlags > 0) {
                 output += " ";
             }
@@ -13715,7 +13952,7 @@
             numFlags++;
         }
 
-        if ((privateFlags & DRAWN) == DRAWN) {
+        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
             if (numFlags > 0) {
                 output += " ";
             }
@@ -13732,7 +13969,7 @@
      * @return true if the layout will be forced during next layout pass
      */
     public boolean isLayoutRequested() {
-        return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT;
+        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
     }
 
     /**
@@ -13762,9 +13999,9 @@
         int oldB = mBottom;
         int oldR = mRight;
         boolean changed = setFrame(l, t, r, b);
-        if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
+        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
             onLayout(changed, l, t, r, b);
-            mPrivateFlags &= ~LAYOUT_REQUIRED;
+            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
 
             ListenerInfo li = mListenerInfo;
             if (li != null && li.mOnLayoutChangeListeners != null) {
@@ -13776,7 +14013,7 @@
                 }
             }
         }
-        mPrivateFlags &= ~FORCE_LAYOUT;
+        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
     }
 
     /**
@@ -13820,7 +14057,7 @@
             changed = true;
 
             // Remember our drawn bit
-            int drawn = mPrivateFlags & DRAWN;
+            int drawn = mPrivateFlags & PFLAG_DRAWN;
 
             int oldWidth = mRight - mLeft;
             int oldHeight = mBottom - mTop;
@@ -13839,11 +14076,11 @@
                 mDisplayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
             }
 
-            mPrivateFlags |= HAS_BOUNDS;
+            mPrivateFlags |= PFLAG_HAS_BOUNDS;
 
 
             if (sizeChanged) {
-                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
                     // A change in dimension means an auto-centered pivot point changes, too
                     if (mTransformationInfo != null) {
                         mTransformationInfo.mMatrixDirty = true;
@@ -13858,7 +14095,7 @@
                 // This is because someone may have invalidated this view
                 // before this call to setFrame came in, thereby clearing
                 // the DRAWN bit.
-                mPrivateFlags |= DRAWN;
+                mPrivateFlags |= PFLAG_DRAWN;
                 invalidate(sizeChanged);
                 // parent display list may need to be recreated based on a change in the bounds
                 // of any child
@@ -13963,13 +14200,47 @@
     }
 
     /**
-    * Return the layout direction of a given Drawable.
-    *
-    * @param who the Drawable to query
-    * @hide
-    */
-    public int getResolvedLayoutDirection(Drawable who) {
-        return (who == mBackground) ? getResolvedLayoutDirection() : LAYOUT_DIRECTION_DEFAULT;
+     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
+     * that the View directionality can and will be resolved before its Drawables.
+     *
+     * Will call {@link View#onResolveDrawables} when resolution is done.
+     *
+     * @hide
+     */
+    protected void resolveDrawables() {
+        if (canResolveLayoutDirection()) {
+            if (mBackground != null) {
+                mBackground.setLayoutDirection(getLayoutDirection());
+            }
+            mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
+            onResolveDrawables(getLayoutDirection());
+        }
+    }
+
+    /**
+     * Called when layout direction has been resolved.
+     *
+     * The default implementation does nothing.
+     *
+     * @param layoutDirection The resolved layout direction.
+     *
+     * @see #LAYOUT_DIRECTION_LTR
+     * @see #LAYOUT_DIRECTION_RTL
+     *
+     * @hide
+     */
+    public void onResolveDrawables(int layoutDirection) {
+    }
+
+    /**
+     * @hide
+     */
+    protected void resetResolvedDrawables() {
+        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
+    }
+
+    private boolean isDrawablesResolved() {
+        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
     }
 
     /**
@@ -14020,7 +14291,7 @@
      * @see #getDrawableState
      */
     public void refreshDrawableState() {
-        mPrivateFlags |= DRAWABLE_STATE_DIRTY;
+        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
         drawableStateChanged();
 
         ViewParent parent = mParent;
@@ -14040,11 +14311,11 @@
      * @see #onCreateDrawableState(int)
      */
     public final int[] getDrawableState() {
-        if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {
+        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
             return mDrawableState;
         } else {
             mDrawableState = onCreateDrawableState(0);
-            mPrivateFlags &= ~DRAWABLE_STATE_DIRTY;
+            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
             return mDrawableState;
         }
     }
@@ -14075,12 +14346,12 @@
         int privateFlags = mPrivateFlags;
 
         int viewStateIndex = 0;
-        if ((privateFlags & PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
+        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
         if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
-        if ((privateFlags & SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
+        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
         if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
-        if ((privateFlags & ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
+        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
                 HardwareRenderer.isAvailable()) {
             // This is set if HW acceleration is requested, even if the current
@@ -14088,11 +14359,11 @@
             // windows to better match their app.
             viewStateIndex |= VIEW_STATE_ACCELERATED;
         }
-        if ((privateFlags & HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
+        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
 
         final int privateFlags2 = mPrivateFlags2;
-        if ((privateFlags2 & DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
-        if ((privateFlags2 & DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
+        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
+        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
 
         drawableState = VIEW_STATE_SETS[viewStateIndex];
 
@@ -14100,10 +14371,10 @@
         if (false) {
             Log.i("View", "drawableStateIndex=" + viewStateIndex);
             Log.i("View", toString()
-                    + " pressed=" + ((privateFlags & PRESSED) != 0)
+                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
                     + " fo=" + hasFocus()
-                    + " sl=" + ((privateFlags & SELECTED) != 0)
+                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
                     + " wf=" + hasWindowFocus()
                     + ": " + Arrays.toString(drawableState));
         }
@@ -14167,7 +14438,8 @@
     @RemotableViewMethod
     public void setBackgroundColor(int color) {
         if (mBackground instanceof ColorDrawable) {
-            ((ColorDrawable) mBackground).setColor(color);
+            ((ColorDrawable) mBackground.mutate()).setColor(color);
+            computeOpaqueFlags();
         } else {
             setBackground(new ColorDrawable(color));
         }
@@ -14215,6 +14487,8 @@
      */
     @Deprecated
     public void setBackgroundDrawable(Drawable background) {
+        computeOpaqueFlags();
+
         if (background == mBackground) {
             return;
         }
@@ -14238,14 +14512,21 @@
                 padding = new Rect();
                 sThreadLocal.set(padding);
             }
+            resetResolvedDrawables();
+            background.setLayoutDirection(getLayoutDirection());
             if (background.getPadding(padding)) {
-                switch (background.getResolvedLayoutDirectionSelf()) {
+                resetResolvedPadding();
+                switch (background.getLayoutDirection()) {
                     case LAYOUT_DIRECTION_RTL:
-                        setPadding(padding.right, padding.top, padding.left, padding.bottom);
+                        mUserPaddingLeftInitial = padding.right;
+                        mUserPaddingRightInitial = padding.left;
+                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
                         break;
                     case LAYOUT_DIRECTION_LTR:
                     default:
-                        setPadding(padding.left, padding.top, padding.right, padding.bottom);
+                        mUserPaddingLeftInitial = padding.left;
+                        mUserPaddingRightInitial = padding.right;
+                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
                 }
             }
 
@@ -14263,23 +14544,23 @@
             background.setVisible(getVisibility() == VISIBLE, false);
             mBackground = background;
 
-            if ((mPrivateFlags & SKIP_DRAW) != 0) {
-                mPrivateFlags &= ~SKIP_DRAW;
-                mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
+            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
+                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
+                mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
                 requestLayout = true;
             }
         } else {
             /* Remove the background */
             mBackground = null;
 
-            if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
+            if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
                 /*
                  * This view ONLY drew the background before and we're removing
                  * the background, so now it won't draw anything
                  * (hence we SKIP_DRAW)
                  */
-                mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;
-                mPrivateFlags |= SKIP_DRAW;
+                mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
+                mPrivateFlags |= PFLAG_SKIP_DRAW;
             }
 
             /*
@@ -14335,14 +14616,21 @@
      * @param bottom the bottom padding in pixels
      */
     public void setPadding(int left, int top, int right, int bottom) {
-        mUserPaddingStart = -1;
-        mUserPaddingEnd = -1;
-        mUserPaddingRelative = false;
+        resetResolvedPadding();
+
+        mUserPaddingStart = UNDEFINED_PADDING;
+        mUserPaddingEnd = UNDEFINED_PADDING;
+
+        mUserPaddingLeftInitial = left;
+        mUserPaddingRightInitial = right;
 
         internalSetPadding(left, top, right, bottom);
     }
 
-    private void internalSetPadding(int left, int top, int right, int bottom) {
+    /**
+     * @hide
+     */
+    protected void internalSetPadding(int left, int top, int right, int bottom) {
         mUserPaddingLeft = left;
         mUserPaddingRight = right;
         mUserPaddingBottom = bottom;
@@ -14357,7 +14645,7 @@
                         ? 0 : getVerticalScrollbarWidth();
                 switch (mVerticalScrollbarPosition) {
                     case SCROLLBAR_POSITION_DEFAULT:
-                        if (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+                        if (isLayoutRtl()) {
                             left += offset;
                         } else {
                             right += offset;
@@ -14402,25 +14690,36 @@
     /**
      * Sets the relative padding. The view may add on the space required to display
      * the scrollbars, depending on the style and visibility of the scrollbars.
+     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
+     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
      * from the values set in this call.
      *
+     * @attr ref android.R.styleable#View_padding
+     * @attr ref android.R.styleable#View_paddingBottom
+     * @attr ref android.R.styleable#View_paddingStart
+     * @attr ref android.R.styleable#View_paddingEnd
+     * @attr ref android.R.styleable#View_paddingTop
      * @param start the start padding in pixels
      * @param top the top padding in pixels
      * @param end the end padding in pixels
      * @param bottom the bottom padding in pixels
-     * @hide
      */
     public void setPaddingRelative(int start, int top, int end, int bottom) {
+        resetResolvedPadding();
+
         mUserPaddingStart = start;
         mUserPaddingEnd = end;
-        mUserPaddingRelative = true;
 
-        switch(getResolvedLayoutDirection()) {
+        switch(getLayoutDirection()) {
             case LAYOUT_DIRECTION_RTL:
+                mUserPaddingLeftInitial = end;
+                mUserPaddingRightInitial = start;
                 internalSetPadding(end, top, start, bottom);
                 break;
             case LAYOUT_DIRECTION_LTR:
             default:
+                mUserPaddingLeftInitial = start;
+                mUserPaddingRightInitial = end;
                 internalSetPadding(start, top, end, bottom);
         }
     }
@@ -14453,6 +14752,9 @@
      * @return the left padding in pixels
      */
     public int getPaddingLeft() {
+        if (!isPaddingResolved()) {
+            resolvePadding();
+        }
         return mPaddingLeft;
     }
 
@@ -14462,10 +14764,12 @@
      * required to display the scrollbars as well.
      *
      * @return the start padding in pixels
-     * @hide
      */
     public int getPaddingStart() {
-        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
+        if (!isPaddingResolved()) {
+            resolvePadding();
+        }
+        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
                 mPaddingRight : mPaddingLeft;
     }
 
@@ -14477,6 +14781,9 @@
      * @return the right padding in pixels
      */
     public int getPaddingRight() {
+        if (!isPaddingResolved()) {
+            resolvePadding();
+        }
         return mPaddingRight;
     }
 
@@ -14486,22 +14793,43 @@
      * required to display the scrollbars as well.
      *
      * @return the end padding in pixels
-     * @hide
      */
     public int getPaddingEnd() {
-        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
+        if (!isPaddingResolved()) {
+            resolvePadding();
+        }
+        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
                 mPaddingLeft : mPaddingRight;
     }
 
     /**
      * Return if the padding as been set thru relative values
-     * {@link #setPaddingRelative(int, int, int, int)}
+     * {@link #setPaddingRelative(int, int, int, int)} or thru
+     * @attr ref android.R.styleable#View_paddingStart or
+     * @attr ref android.R.styleable#View_paddingEnd
      *
      * @return true if the padding is relative or false if it is not.
-     * @hide
      */
     public boolean isPaddingRelative() {
-        return mUserPaddingRelative;
+        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
+    }
+
+    /**
+     * @hide
+     */
+    public void resetPaddingToInitialValues() {
+        if (isRtlCompatibilityMode()) {
+            mPaddingLeft = mUserPaddingLeftInitial;
+            mPaddingRight = mUserPaddingRightInitial;
+            return;
+        }
+        if (isLayoutRtl()) {
+            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
+            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
+        } else {
+            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
+            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
+        }
     }
 
     /**
@@ -14530,8 +14858,8 @@
      * @param selected true if the view must be selected, false otherwise
      */
     public void setSelected(boolean selected) {
-        if (((mPrivateFlags & SELECTED) != 0) != selected) {
-            mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0);
+        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
+            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
             if (!selected) resetPressedState();
             invalidate(true);
             refreshDrawableState();
@@ -14559,7 +14887,7 @@
      */
     @ViewDebug.ExportedProperty
     public boolean isSelected() {
-        return (mPrivateFlags & SELECTED) != 0;
+        return (mPrivateFlags & PFLAG_SELECTED) != 0;
     }
 
     /**
@@ -14576,8 +14904,8 @@
      * @param activated true if the view must be activated, false otherwise
      */
     public void setActivated(boolean activated) {
-        if (((mPrivateFlags & ACTIVATED) != 0) != activated) {
-            mPrivateFlags = (mPrivateFlags & ~ACTIVATED) | (activated ? ACTIVATED : 0);
+        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
+            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
             invalidate(true);
             refreshDrawableState();
             dispatchSetActivated(activated);
@@ -14601,7 +14929,7 @@
      */
     @ViewDebug.ExportedProperty
     public boolean isActivated() {
-        return (mPrivateFlags & ACTIVATED) != 0;
+        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
     }
 
     /**
@@ -14879,6 +15207,9 @@
      */
     public void setId(int id) {
         mID = id;
+        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
+            mID = generateViewId();
+        }
     }
 
     /**
@@ -14889,9 +15220,9 @@
      */
     public void setIsRootNamespace(boolean isRoot) {
         if (isRoot) {
-            mPrivateFlags |= IS_ROOT_NAMESPACE;
+            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
         } else {
-            mPrivateFlags &= ~IS_ROOT_NAMESPACE;
+            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
         }
     }
 
@@ -14901,7 +15232,7 @@
      * @return true if the view belongs to the root namespace, false otherwise
      */
     public boolean isRootNamespace() {
-        return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0;
+        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
     }
 
     /**
@@ -15050,7 +15381,7 @@
         }
         Log.d(VIEW_LOG_TAG, output);
 
-        if ((mPrivateFlags & FOCUSED) != 0) {
+        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
             output = debugIndent(depth) + " FOCUSED";
             Log.d(VIEW_LOG_TAG, output);
         }
@@ -15130,12 +15461,8 @@
      * tree.
      */
     public void requestLayout() {
-        mPrivateFlags |= FORCE_LAYOUT;
-        mPrivateFlags |= INVALIDATED;
-
-        if (mLayoutParams != null) {
-            mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
-        }
+        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
+        mPrivateFlags |= PFLAG_INVALIDATED;
 
         if (mParent != null && !mParent.isLayoutRequested()) {
             mParent.requestLayout();
@@ -15148,8 +15475,8 @@
      * on the parent.
      */
     public void forceLayout() {
-        mPrivateFlags |= FORCE_LAYOUT;
-        mPrivateFlags |= INVALIDATED;
+        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
+        mPrivateFlags |= PFLAG_INVALIDATED;
     }
 
     /**
@@ -15173,25 +15500,27 @@
      * @see #onMeasure(int, int)
      */
     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
-        if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
+        if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
                 widthMeasureSpec != mOldWidthMeasureSpec ||
                 heightMeasureSpec != mOldHeightMeasureSpec) {
 
             // first clears the measured dimension flag
-            mPrivateFlags &= ~MEASURED_DIMENSION_SET;
+            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
+
+            resolveRtlPropertiesIfNeeded();
 
             // measure ourselves, this should set the measured dimension flag back
             onMeasure(widthMeasureSpec, heightMeasureSpec);
 
             // flag not set, setMeasuredDimension() was not invoked, we raise
             // an exception to warn the developer
-            if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
+            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
                 throw new IllegalStateException("onMeasure() did not set the"
                         + " measured dimension by calling"
                         + " setMeasuredDimension()");
             }
 
-            mPrivateFlags |= LAYOUT_REQUIRED;
+            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
         }
 
         mOldWidthMeasureSpec = widthMeasureSpec;
@@ -15265,7 +15594,7 @@
         mMeasuredWidth = measuredWidth;
         mMeasuredHeight = measuredHeight;
 
-        mPrivateFlags |= MEASURED_DIMENSION_SET;
+        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
     }
 
     /**
@@ -15509,7 +15838,7 @@
      * @see #getAnimation()
      */
     protected void onAnimationStart() {
-        mPrivateFlags |= ANIMATION_STARTED;
+        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
     }
 
     /**
@@ -15521,7 +15850,7 @@
      * @see #getAnimation()
      */
     protected void onAnimationEnd() {
-        mPrivateFlags &= ~ANIMATION_STARTED;
+        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
     }
 
     /**
@@ -15558,14 +15887,14 @@
         final AttachInfo attachInfo = mAttachInfo;
         if (region != null && attachInfo != null) {
             final int pflags = mPrivateFlags;
-            if ((pflags & SKIP_DRAW) == 0) {
+            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
                 // remove it from the transparent region.
                 final int[] location = attachInfo.mTransparentLocation;
                 getLocationInWindow(location);
                 region.op(location[0], location[1], location[0] + mRight - mLeft,
                         location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
-            } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) {
+            } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) {
                 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
                 // exists, so we remove the background drawable's non-transparent
                 // parts from this transparent region.
@@ -16042,7 +16371,7 @@
     }
 
     boolean canAcceptDrag() {
-        return (mPrivateFlags2 & DRAG_CAN_ACCEPT) != 0;
+        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
     }
 
     /**
@@ -16297,6 +16626,7 @@
      * {@link #TEXT_DIRECTION_LTR},
      * {@link #TEXT_DIRECTION_RTL},
      * {@link #TEXT_DIRECTION_LOCALE}
+     *
      * @hide
      */
     @ViewDebug.ExportedProperty(category = "text", mapping = {
@@ -16307,8 +16637,8 @@
             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
     })
-    public int getTextDirection() {
-        return (mPrivateFlags2 & TEXT_DIRECTION_MASK) >> TEXT_DIRECTION_MASK_SHIFT;
+    public int getRawTextDirection() {
+        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
     }
 
     /**
@@ -16322,15 +16652,22 @@
      * {@link #TEXT_DIRECTION_LTR},
      * {@link #TEXT_DIRECTION_RTL},
      * {@link #TEXT_DIRECTION_LOCALE}
-     * @hide
+     *
+     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
+     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
+     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
      */
     public void setTextDirection(int textDirection) {
-        if (getTextDirection() != textDirection) {
+        if (getRawTextDirection() != textDirection) {
             // Reset the current text direction and the resolved one
-            mPrivateFlags2 &= ~TEXT_DIRECTION_MASK;
+            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
             resetResolvedTextDirection();
             // Set the new text direction
-            mPrivateFlags2 |= ((textDirection << TEXT_DIRECTION_MASK_SHIFT) & TEXT_DIRECTION_MASK);
+            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
+            // Do resolution
+            resolveTextDirection();
+            // Notify change
+            onRtlPropertiesChanged(getLayoutDirection());
             // Refresh
             requestLayout();
             invalidate(true);
@@ -16340,11 +16677,6 @@
     /**
      * Return the resolved text direction.
      *
-     * 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}
@@ -16352,51 +16684,56 @@
      * {@link #TEXT_DIRECTION_LTR},
      * {@link #TEXT_DIRECTION_RTL},
      * {@link #TEXT_DIRECTION_LOCALE}
-     * @hide
      */
-    public int getResolvedTextDirection() {
-        // The text direction will be resolved only if needed
-        if ((mPrivateFlags2 & TEXT_DIRECTION_RESOLVED) != TEXT_DIRECTION_RESOLVED) {
-            resolveTextDirection();
-        }
-        return (mPrivateFlags2 & TEXT_DIRECTION_RESOLVED_MASK) >> TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
+    public int getTextDirection() {
+        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
     }
 
     /**
-     * Resolve the text direction. Will call {@link View#onResolvedTextDirectionChanged} when
-     * resolution is done.
+     * Resolve the text direction.
+     *
+     * @return true if resolution has been done, false otherwise.
+     *
      * @hide
      */
-    public void resolveTextDirection() {
+    public boolean resolveTextDirection() {
         // Reset any previous text direction resolution
-        mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
+        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
 
         if (hasRtlSupport()) {
             // Set resolved text direction flag depending on text direction flag
-            final int textDirection = getTextDirection();
+            final int textDirection = getRawTextDirection();
             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 {
+                    if (!canResolveTextDirection()) {
                         // We cannot do the resolution if there is no parent, so use the default one
-                        mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
+                        // Resolution will need to happen again later
+                        return false;
+                    }
+
+                    View parent = ((View) mParent);
+                    // Parent has not yet resolved, so we still return the default
+                    if (!parent.isTextDirectionResolved()) {
+                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
+                        // Resolution will need to happen again later
+                        return false;
+                    }
+
+                    // Set current resolved direction to the same value as the parent's one
+                    final int parentResolvedDirection = parent.getTextDirection();
+                    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 << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
+                            break;
+                        default:
+                            // Default resolved direction is "first strong" heuristic
+                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
                     }
                     break;
                 case TEXT_DIRECTION_FIRST_STRONG:
@@ -16405,65 +16742,64 @@
                 case TEXT_DIRECTION_RTL:
                 case TEXT_DIRECTION_LOCALE:
                     // Resolved direction is the same as text direction
-                    mPrivateFlags2 |= (textDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
+                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
                     break;
                 default:
                     // Default resolved direction is "first strong" heuristic
-                    mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
             }
         } else {
             // Default resolved direction is "first strong" heuristic
-            mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
         }
 
         // Set to resolved
-        mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED;
-        onResolvedTextDirectionChanged();
-    }
-
-    /**
-     * Called when text direction has been resolved. Subclasses that care about text direction
-     * resolution should override this method.
-     *
-     * The default implementation does nothing.
-     * @hide
-     */
-    public void onResolvedTextDirectionChanged() {
+        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
+        return true;
     }
 
     /**
      * Check if text direction resolution can be done.
      *
      * @return true if text direction resolution can be done otherwise return false.
-     * @hide
      */
-    public boolean canResolveTextDirection() {
-        switch (getTextDirection()) {
+    private boolean canResolveTextDirection() {
+        switch (getRawTextDirection()) {
             case TEXT_DIRECTION_INHERIT:
-                return (mParent != null) && (mParent instanceof ViewGroup);
+                return (mParent != null) && (mParent instanceof View) &&
+                       ((View) mParent).canResolveTextDirection();
             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.
+     * Reset resolved text direction. Text direction will be resolved during a call to
+     * {@link #onMeasure(int, int)}.
+     *
      * @hide
      */
     public void resetResolvedTextDirection() {
-        mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
-        onResolvedTextDirectionReset();
+        // Reset any previous text direction resolution
+        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
+        // Set to default value
+        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
     }
 
     /**
-     * Called when text direction is reset. Subclasses that care about text direction reset should
-     * override this method and do a reset of the text direction of their children. The default
-     * implementation does nothing.
+     * @return true if text direction is inherited.
+     *
      * @hide
      */
-    public void onResolvedTextDirectionReset() {
+    public boolean isTextDirectionInherited() {
+        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
+    }
+
+    /**
+     * @return true if text direction is resolved.
+     */
+    private boolean isTextDirectionResolved() {
+        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
     }
 
     /**
@@ -16479,6 +16815,7 @@
      * {@link #TEXT_ALIGNMENT_TEXT_END},
      * {@link #TEXT_ALIGNMENT_VIEW_START},
      * {@link #TEXT_ALIGNMENT_VIEW_END}
+     *
      * @hide
      */
     @ViewDebug.ExportedProperty(category = "text", mapping = {
@@ -16490,8 +16827,8 @@
             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
     })
-    public int getTextAlignment() {
-        return (mPrivateFlags2 & TEXT_ALIGNMENT_MASK) >> TEXT_ALIGNMENT_MASK_SHIFT;
+    public int getRawTextAlignment() {
+        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
     }
 
     /**
@@ -16507,16 +16844,24 @@
      * {@link #TEXT_ALIGNMENT_VIEW_START},
      * {@link #TEXT_ALIGNMENT_VIEW_END}
      *
+     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
+     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
+     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
+     *
      * @attr ref android.R.styleable#View_textAlignment
-     * @hide
      */
     public void setTextAlignment(int textAlignment) {
-        if (textAlignment != getTextAlignment()) {
+        if (textAlignment != getRawTextAlignment()) {
             // Reset the current and resolved text alignment
-            mPrivateFlags2 &= ~TEXT_ALIGNMENT_MASK;
+            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
             resetResolvedTextAlignment();
             // Set the new text alignment
-            mPrivateFlags2 |= ((textAlignment << TEXT_ALIGNMENT_MASK_SHIFT) & TEXT_ALIGNMENT_MASK);
+            mPrivateFlags2 |=
+                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
+            // Do resolution
+            resolveTextAlignment();
+            // Notify change
+            onRtlPropertiesChanged(getLayoutDirection());
             // Refresh
             requestLayout();
             invalidate(true);
@@ -16526,10 +16871,6 @@
     /**
      * Return the resolved text alignment.
      *
-     * The resolved text alignment. This needs resolution if the value is
-     * TEXT_ALIGNMENT_INHERIT. The resolution matches {@link #setTextAlignment(int)}  if it is
-     * not TEXT_ALIGNMENT_INHERIT, otherwise resolution proceeds up the parent chain of the view.
-     *
      * @return the resolved text alignment. Returns one of:
      *
      * {@link #TEXT_ALIGNMENT_GRAVITY},
@@ -16538,7 +16879,6 @@
      * {@link #TEXT_ALIGNMENT_TEXT_END},
      * {@link #TEXT_ALIGNMENT_VIEW_START},
      * {@link #TEXT_ALIGNMENT_VIEW_END}
-     * @hide
      */
     @ViewDebug.ExportedProperty(category = "text", mapping = {
             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
@@ -16549,53 +16889,59 @@
             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
     })
-    public int getResolvedTextAlignment() {
-        // If text alignment is not resolved, then resolve it
-        if ((mPrivateFlags2 & TEXT_ALIGNMENT_RESOLVED) != TEXT_ALIGNMENT_RESOLVED) {
-            resolveTextAlignment();
-        }
-        return (mPrivateFlags2 & TEXT_ALIGNMENT_RESOLVED_MASK) >> TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
+    public int getTextAlignment() {
+        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
+                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
     }
 
     /**
-     * Resolve the text alignment. Will call {@link View#onResolvedTextAlignmentChanged} when
-     * resolution is done.
+     * Resolve the text alignment.
+     *
+     * @return true if resolution has been done, false otherwise.
+     *
      * @hide
      */
-    public void resolveTextAlignment() {
+    public boolean resolveTextAlignment() {
         // Reset any previous text alignment resolution
-        mPrivateFlags2 &= ~(TEXT_ALIGNMENT_RESOLVED | TEXT_ALIGNMENT_RESOLVED_MASK);
+        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
 
         if (hasRtlSupport()) {
             // Set resolved text alignment flag depending on text alignment flag
-            final int textAlignment = getTextAlignment();
+            final int textAlignment = getRawTextAlignment();
             switch (textAlignment) {
                 case TEXT_ALIGNMENT_INHERIT:
                     // Check if we can resolve the text alignment
-                    if (canResolveLayoutDirection() && mParent instanceof View) {
-                        View view = (View) mParent;
-
-                        final int parentResolvedTextAlignment = view.getResolvedTextAlignment();
-                        switch (parentResolvedTextAlignment) {
-                            case TEXT_ALIGNMENT_GRAVITY:
-                            case TEXT_ALIGNMENT_TEXT_START:
-                            case TEXT_ALIGNMENT_TEXT_END:
-                            case TEXT_ALIGNMENT_CENTER:
-                            case TEXT_ALIGNMENT_VIEW_START:
-                            case TEXT_ALIGNMENT_VIEW_END:
-                                // Resolved text alignment is the same as the parent resolved
-                                // text alignment
-                                mPrivateFlags2 |=
-                                        (parentResolvedTextAlignment << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
-                                break;
-                            default:
-                                // Use default resolved text alignment
-                                mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
-                        }
-                    }
-                    else {
+                    if (!canResolveTextAlignment()) {
                         // We cannot do the resolution if there is no parent so use the default
-                        mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+                        // Resolution will need to happen again later
+                        return false;
+                    }
+                    View parent = (View) mParent;
+
+                    // Parent has not yet resolved, so we still return the default
+                    if (!parent.isTextAlignmentResolved()) {
+                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+                        // Resolution will need to happen again later
+                        return false;
+                    }
+
+                    final int parentResolvedTextAlignment = parent.getTextAlignment();
+                    switch (parentResolvedTextAlignment) {
+                        case TEXT_ALIGNMENT_GRAVITY:
+                        case TEXT_ALIGNMENT_TEXT_START:
+                        case TEXT_ALIGNMENT_TEXT_END:
+                        case TEXT_ALIGNMENT_CENTER:
+                        case TEXT_ALIGNMENT_VIEW_START:
+                        case TEXT_ALIGNMENT_VIEW_END:
+                            // Resolved text alignment is the same as the parent resolved
+                            // text alignment
+                            mPrivateFlags2 |=
+                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
+                            break;
+                        default:
+                            // Use default resolved text alignment
+                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
                     }
                     break;
                 case TEXT_ALIGNMENT_GRAVITY:
@@ -16605,66 +16951,82 @@
                 case TEXT_ALIGNMENT_VIEW_START:
                 case TEXT_ALIGNMENT_VIEW_END:
                     // Resolved text alignment is the same as text alignment
-                    mPrivateFlags2 |= (textAlignment << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
+                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
                     break;
                 default:
                     // Use default resolved text alignment
-                    mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
             }
         } else {
             // Use default resolved text alignment
-            mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
         }
 
         // Set the resolved
-        mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED;
-        onResolvedTextAlignmentChanged();
+        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
+        return true;
     }
 
     /**
      * Check if text alignment resolution can be done.
      *
      * @return true if text alignment resolution can be done otherwise return false.
-     * @hide
      */
-    public boolean canResolveTextAlignment() {
-        switch (getTextAlignment()) {
+    private boolean canResolveTextAlignment() {
+        switch (getRawTextAlignment()) {
             case TEXT_DIRECTION_INHERIT:
-                return (mParent != null);
+                return (mParent != null) && (mParent instanceof View) &&
+                       ((View) mParent).canResolveTextAlignment();
             default:
                 return true;
         }
     }
 
     /**
-     * Called when text alignment has been resolved. Subclasses that care about text alignment
-     * resolution should override this method.
+     * Reset resolved text alignment. Text alignment will be resolved during a call to
+     * {@link #onMeasure(int, int)}.
      *
-     * The default implementation does nothing.
-     * @hide
-     */
-    public void onResolvedTextAlignmentChanged() {
-    }
-
-    /**
-     * Reset resolved text alignment. Text alignment can be resolved with a call to
-     * getResolvedTextAlignment(). Will call {@link View#onResolvedTextAlignmentReset} when
-     * reset is done.
      * @hide
      */
     public void resetResolvedTextAlignment() {
         // Reset any previous text alignment resolution
-        mPrivateFlags2 &= ~(TEXT_ALIGNMENT_RESOLVED | TEXT_ALIGNMENT_RESOLVED_MASK);
-        onResolvedTextAlignmentReset();
+        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
+        // Set to default
+        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
     }
 
     /**
-     * Called when text alignment is reset. Subclasses that care about text alignment reset should
-     * override this method and do a reset of the text alignment of their children. The default
-     * implementation does nothing.
+     * @return true if text alignment is inherited.
+     *
      * @hide
      */
-    public void onResolvedTextAlignmentReset() {
+    public boolean isTextAlignmentInherited() {
+        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
+    }
+
+    /**
+     * @return true if text alignment is resolved.
+     */
+    private boolean isTextAlignmentResolved() {
+        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
+    }
+
+    /**
+     * Generate a value suitable for use in {@link #setId(int)}.
+     * This value will not collide with ID values generated at build time by aapt for R.id.
+     *
+     * @return a generated ID value
+     */
+    public static int generateViewId() {
+        for (;;) {
+            final int result = sNextGeneratedId.get();
+            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
+            int newValue = result + 1;
+            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
+            if (sNextGeneratedId.compareAndSet(result, newValue)) {
+                return result;
+            }
+        }
     }
 
     //
@@ -16967,7 +17329,7 @@
 
     private final class CheckForTap implements Runnable {
         public void run() {
-            mPrivateFlags &= ~PREPRESSED;
+            mPrivateFlags &= ~PFLAG_PREPRESSED;
             setPressed(true);
             checkForLongClick(ViewConfiguration.getTapTimeout());
         }
@@ -17315,6 +17677,8 @@
 
         final IBinder mWindowToken;
 
+        final Display mDisplay;
+
         final Callbacks mRootCallbacks;
 
         HardwareCanvas mHardwareCanvas;
@@ -17344,7 +17708,7 @@
         boolean mScalingRequired;
 
         /**
-         * If set, ViewAncestor doesn't use its lame animation for when the window resizes.
+         * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
          */
         boolean mTurnOffWindowResizeAnim;
 
@@ -17359,20 +17723,6 @@
         int mWindowTop;
 
         /**
-         * Left actual position of this view's window.
-         *
-         * TODO: This is a workaround for 6623031. Remove when fixed.
-         */
-        int mActualWindowLeft;
-
-        /**
-         * Actual top position of this view's window.
-         *
-         * TODO: This is a workaround for 6623031. Remove when fixed.
-         */
-        int mActualWindowTop;
-
-        /**
          * Indicates whether views need to use 32-bit drawing caches
          */
         boolean mUse32BitDrawingCache;
@@ -17542,6 +17892,16 @@
         final RectF mTmpTransformRect = new RectF();
 
         /**
+         * Temporary for use in transforming invalidation rect
+         */
+        final Matrix mTmpMatrix = new Matrix();
+
+        /**
+         * Temporary for use in transforming invalidation rect
+         */
+        final Transformation mTmpTransformation = new Transformation();
+
+        /**
          * Temporary list for use in collecting focusable descendents of a view.
          */
         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
@@ -17578,11 +17938,12 @@
          *
          * @param handler the events handler the view must use
          */
-        AttachInfo(IWindowSession session, IWindow window,
+        AttachInfo(IWindowSession session, IWindow window, Display display,
                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
             mSession = session;
             mWindow = window;
             mWindowToken = window.asBinder();
+            mDisplay = display;
             mViewRootImpl = viewRootImpl;
             mHandler = handler;
             mRootCallbacks = effectPlayer;
@@ -17656,23 +18017,27 @@
             // use use a height of 1, and then wack the matrix each time we
             // actually use it.
             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
-
             paint.setShader(shader);
             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+
             this.host = host;
         }
 
         public void setFadeColor(int color) {
-            if (color != 0 && color != mLastColor) {
+            if (color != mLastColor) {
                 mLastColor = color;
-                color |= 0xFF000000;
 
-                shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
-                        color & 0x00FFFFFF, Shader.TileMode.CLAMP);
-
-                paint.setShader(shader);
-                // Restore the default transfer mode (src_over)
-                paint.setXfermode(null);
+                if (color != 0) {
+                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
+                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
+                    paint.setShader(shader);
+                    // Restore the default transfer mode (src_over)
+                    paint.setXfermode(null);
+                } else {
+                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
+                    paint.setShader(shader);
+                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+                }
             }
         }
 
@@ -17960,4 +18325,64 @@
             return null;
         }
     }
+
+    private class MatchIdPredicate implements Predicate<View> {
+        public int mId;
+
+        @Override
+        public boolean apply(View view) {
+            return (view.mID == mId);
+        }
+    }
+
+    private class MatchLabelForPredicate implements Predicate<View> {
+        private int mLabeledId;
+
+        @Override
+        public boolean apply(View view) {
+            return (view.mLabelForId == mLabeledId);
+        }
+    }
+
+    /**
+     * Dump all private flags in readable format, useful for documentation and
+     * sanity checking.
+     */
+    private static void dumpFlags() {
+        final HashMap<String, String> found = Maps.newHashMap();
+        try {
+            for (Field field : View.class.getDeclaredFields()) {
+                final int modifiers = field.getModifiers();
+                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
+                    if (field.getType().equals(int.class)) {
+                        final int value = field.getInt(null);
+                        dumpFlag(found, field.getName(), value);
+                    } else if (field.getType().equals(int[].class)) {
+                        final int[] values = (int[]) field.get(null);
+                        for (int i = 0; i < values.length; i++) {
+                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
+                        }
+                    }
+                }
+            }
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException(e);
+        }
+
+        final ArrayList<String> keys = Lists.newArrayList();
+        keys.addAll(found.keySet());
+        Collections.sort(keys);
+        for (String key : keys) {
+            Log.d(VIEW_LOG_TAG, found.get(key));
+        }
+    }
+
+    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
+        // Sort flags by prefix, then by bits, always keeping unique keys
+        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
+        final int prefix = name.indexOf('_');
+        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
+        final String output = bits + " " + name;
+        found.put(key, output);
+    }
 }
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 823befb..499075e 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.Point;
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.util.DisplayMetrics;
@@ -30,24 +31,6 @@
  */
 public class ViewConfiguration {
     /**
-     * Expected bit depth of the display panel.
-     *
-     * @hide
-     */
-    public static final float PANEL_BIT_DEPTH = 24;
-
-    /**
-     * Minimum alpha required for a view to draw.
-     *
-     * @hide
-     */
-    public static final float ALPHA_THRESHOLD = 0.5f / PANEL_BIT_DEPTH;
-    /**
-     * @hide
-     */
-    public static final float ALPHA_THRESHOLD_INT = 0x7f / PANEL_BIT_DEPTH;
-
-    /**
      * Defines the width of the horizontal scrollbar and the height of the vertical scrollbar in
      * dips
      */
@@ -295,15 +278,18 @@
         mDoubleTapSlop = (int) (sizeAndDensity * DOUBLE_TAP_SLOP + 0.5f);
         mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f);
 
-        final Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
         // Size of the screen in bytes, in ARGB_8888 format
-        mMaximumDrawingCacheSize = 4 * display.getRawWidth() * display.getRawHeight();
+        final WindowManager win = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+        final Display display = win.getDefaultDisplay();
+        final Point size = new Point();
+        display.getRealSize(size);
+        mMaximumDrawingCacheSize = 4 * size.x * size.y;
 
         mOverscrollDistance = (int) (sizeAndDensity * OVERSCROLL_DISTANCE + 0.5f);
         mOverflingDistance = (int) (sizeAndDensity * OVERFLING_DISTANCE + 0.5f);
 
         if (!sHasPermanentMenuKeySet) {
-            IWindowManager wm = Display.getWindowManager();
+            IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
             try {
                 sHasPermanentMenuKey = !wm.hasSystemNavBar() && !wm.hasNavigationBar();
                 sHasPermanentMenuKeySet = true;
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index dd671dc..023e58f 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -255,6 +255,35 @@
         boolean retrieveReturn() default false;
     }
 
+    /**
+     * Allows a View to inject custom children into HierarchyViewer. For example,
+     * WebView uses this to add its internal layer tree as a child to itself
+     * @hide
+     */
+    public interface HierarchyHandler {
+        /**
+         * Dumps custom children to hierarchy viewer.
+         * See ViewDebug.dumpViewWithProperties(Context, View, BufferedWriter, int)
+         * for the format
+         *
+         * An empty implementation should simply do nothing
+         *
+         * @param out The output writer
+         * @param level The indentation level
+         */
+        public void dumpViewHierarchyWithProperties(BufferedWriter out, int level);
+
+        /**
+         * Returns a View to enable grabbing screenshots from custom children
+         * returned in dumpViewHierarchyWithProperties.
+         *
+         * @param className The className of the view to find
+         * @param hashCode The hashCode of the view to find
+         * @return the View to capture from, or null if not found
+         */
+        public View findHierarchyView(String className, int hashCode);
+    }
+
     private static HashMap<Class<?>, Method[]> mCapturedViewMethodsForClasses = null;
     private static HashMap<Class<?>, Field[]> mCapturedViewFieldsForClasses = null;
 
@@ -468,8 +497,8 @@
             throws IOException {
 
         long durationMeasure =
-                (root || (view.mPrivateFlags & View.MEASURED_DIMENSION_SET) != 0) ? profileViewOperation(
-                        view, new ViewOperation<Void>() {
+                (root || (view.mPrivateFlags & View.PFLAG_MEASURED_DIMENSION_SET) != 0)
+                ? profileViewOperation(view, new ViewOperation<Void>() {
                             public Void[] pre() {
                                 forceLayout(view);
                                 return null;
@@ -495,8 +524,8 @@
                         })
                         : 0;
         long durationLayout =
-                (root || (view.mPrivateFlags & View.LAYOUT_REQUIRED) != 0) ? profileViewOperation(
-                        view, new ViewOperation<Void>() {
+                (root || (view.mPrivateFlags & View.PFLAG_LAYOUT_REQUIRED) != 0)
+                ? profileViewOperation(view, new ViewOperation<Void>() {
                             public Void[] pre() {
                                 return null;
                             }
@@ -509,15 +538,14 @@
                             }
                         }) : 0;
         long durationDraw =
-                (root || !view.willNotDraw() || (view.mPrivateFlags & View.DRAWN) != 0) ? profileViewOperation(
-                        view,
-                        new ViewOperation<Object>() {
+                (root || !view.willNotDraw() || (view.mPrivateFlags & View.PFLAG_DRAWN) != 0)
+                ? profileViewOperation(view, new ViewOperation<Object>() {
                             public Object[] pre() {
                                 final DisplayMetrics metrics =
                                         (view != null && view.getResources() != null) ?
                                                 view.getResources().getDisplayMetrics() : null;
                                 final Bitmap bitmap = metrics != null ?
-                                        Bitmap.createBitmap(metrics.widthPixels,
+                                        Bitmap.createBitmap(metrics, metrics.widthPixels,
                                                 metrics.heightPixels, Bitmap.Config.RGB_565) : null;
                                 final Canvas canvas = bitmap != null ? new Canvas(bitmap) : null;
                                 return new Object[] {
@@ -622,7 +650,7 @@
 
         final boolean localVisible = view.getVisibility() == View.VISIBLE && visible;
 
-        if ((view.mPrivateFlags & View.SKIP_DRAW) != View.SKIP_DRAW) {
+        if ((view.mPrivateFlags & View.PFLAG_SKIP_DRAW) != View.PFLAG_SKIP_DRAW) {
             final int id = view.getId();
             String name = view.getClass().getSimpleName();
             if (id != View.NO_ID) {
@@ -677,7 +705,8 @@
             Log.w("View", "Failed to create capture bitmap!");
             // Send an empty one so that it doesn't get stuck waiting for
             // something.
-            b = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+            b = Bitmap.createBitmap(root.getResources().getDisplayMetrics(),
+                    1, 1, Bitmap.Config.ARGB_8888);
         }
 
         BufferedOutputStream out = null;
@@ -759,6 +788,13 @@
             } else if (isRequestedView(view, className, hashCode)) {
                 return view;
             }
+            if (view instanceof HierarchyHandler) {
+                final View found = ((HierarchyHandler)view)
+                        .findHierarchyView(className, hashCode);
+                if (found != null) {
+                    return found;
+                }
+            }
         }
 
         return null;
@@ -783,6 +819,9 @@
                 dumpViewWithProperties(context, view, out, level + 1);
             }
         }
+        if (group instanceof HierarchyHandler) {
+            ((HierarchyHandler)group).dumpViewHierarchyWithProperties(out, level + 1);
+        }
     }
 
     private static boolean dumpViewWithProperties(Context context, View view,
@@ -884,8 +923,12 @@
     private static void dumpViewProperties(Context context, Object view,
             BufferedWriter out, String prefix) throws IOException {
 
-        Class<?> klass = view.getClass();
+        if (view == null) {
+            out.write(prefix + "=4,null ");
+            return;
+        }
 
+        Class<?> klass = view.getClass();
         do {
             exportFields(context, view, out, klass, prefix);
             exportMethods(context, view, out, klass, prefix);
@@ -1025,8 +1068,8 @@
                     return;
                 } else if (!type.isPrimitive()) {
                     if (property.deepExport()) {
-                        dumpViewProperties(context, field.get(view), out, prefix
-                                + property.prefix());
+                        dumpViewProperties(context, field.get(view), out, prefix +
+                                property.prefix());
                         continue;
                     }
                 }
@@ -1139,10 +1182,14 @@
 
     private static void writeValue(BufferedWriter out, Object value) throws IOException {
         if (value != null) {
-            String output = value.toString().replace("\n", "\\n");
-            out.write(String.valueOf(output.length()));
-            out.write(",");
-            out.write(output);
+            String output = "[EXCEPTION]";
+            try {
+                output = value.toString().replace("\n", "\\n");
+            } finally {
+                out.write(String.valueOf(output.length()));
+                out.write(",");
+                out.write(output);
+            }
         } else {
             out.write("4,null");
         }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 0c83a73..00723f3 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -170,6 +170,14 @@
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
+    @ViewDebug.ExportedProperty(flagMapping = {
+            @ViewDebug.FlagToString(mask = FLAG_CLIP_CHILDREN, equals = FLAG_CLIP_CHILDREN,
+                    name = "CLIP_CHILDREN"),
+            @ViewDebug.FlagToString(mask = FLAG_CLIP_TO_PADDING, equals = FLAG_CLIP_TO_PADDING,
+                    name = "CLIP_TO_PADDING"),
+            @ViewDebug.FlagToString(mask = FLAG_PADDING_NOT_NULL, equals = FLAG_PADDING_NOT_NULL,
+                    name = "PADDING_NOT_NULL")
+    })
     protected int mGroupFlags;
 
     /*
@@ -404,10 +412,6 @@
     // views during a transition when they otherwise would have become gone/invisible
     private ArrayList<View> mVisibilityChangingChildren;
 
-    // Indicates whether this container will use its children layers to draw
-    @ViewDebug.ExportedProperty(category = "drawing")
-    boolean mDrawLayers = true;
-
     // Indicates how many of this container's child subtrees contain transient state
     @ViewDebug.ExportedProperty(category = "layout")
     private int mChildCountWithTransientState = 0;
@@ -628,11 +632,7 @@
      *        FOCUS_RIGHT, or 0 for not applicable.
      */
     public View focusSearch(View focused, int direction) {
-        // If we are moving accessibility focus we want to consider all
-        // views no matter if they are on the screen. It is responsibility
-        // of the accessibility service to check whether the result is in
-        // the screen.
-        if (isRootNamespace() && (direction & FOCUS_ACCESSIBILITY) == 0) {
+        if (isRootNamespace()) {
             // root namespace means we should consider ourselves the top of the
             // tree for focus searching; otherwise we could be focus searching
             // into other tabs.  see LocalActivityManager and TabHost for more info
@@ -804,7 +804,7 @@
      */
     @Override
     public boolean hasFocus() {
-        return (mPrivateFlags & FOCUSED) != 0 || mFocused != null;
+        return (mPrivateFlags & PFLAG_FOCUSED) != 0 || mFocused != null;
     }
 
     /*
@@ -867,8 +867,7 @@
 
         final int descendantFocusability = getDescendantFocusability();
 
-        if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS
-                || (focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
+        if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
             final int count = mChildrenCount;
             final View[] children = mChildren;
 
@@ -886,9 +885,7 @@
         // among the focusable children would be more interesting.
         if (descendantFocusability != FOCUS_AFTER_DESCENDANTS
                 // No focusable descendants
-                || (focusableCount == views.size())
-                // We are collecting accessibility focusables.
-                || (focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
+                || (focusableCount == views.size())) {
             super.addFocusables(views, direction, focusableMode);
         }
     }
@@ -901,7 +898,7 @@
         for (int i = 0; i < childrenCount; i++) {
             View child = children[i];
             if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
-                    && (child.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
+                    && (child.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
                 child.findViewsWithText(outViews, text, flags);
             }
         }
@@ -1180,7 +1177,7 @@
                     final View view = mCurrentDragView;
                     event.mAction = DragEvent.ACTION_DRAG_EXITED;
                     view.dispatchDragEvent(event);
-                    view.mPrivateFlags2 &= ~View.DRAG_HOVERED;
+                    view.mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
                     view.refreshDrawableState();
                 }
                 mCurrentDragView = target;
@@ -1189,7 +1186,7 @@
                 if (target != null) {
                     event.mAction = DragEvent.ACTION_DRAG_ENTERED;
                     target.dispatchDragEvent(event);
-                    target.mPrivateFlags2 |= View.DRAG_HOVERED;
+                    target.mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
                     target.refreshDrawableState();
                 }
                 event.mAction = action;  // restore the event's original state
@@ -1223,7 +1220,7 @@
             if (mCurrentDragView != null) {
                 final View view = mCurrentDragView;
                 view.dispatchDragEvent(event);
-                view.mPrivateFlags2 &= ~View.DRAG_HOVERED;
+                view.mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
                 view.refreshDrawableState();
 
                 mCurrentDragView = null;
@@ -1284,7 +1281,7 @@
             mDragNotifiedChildren.add(child);
             canAccept = child.dispatchDragEvent(mCurrentDrag);
             if (canAccept && !child.canAcceptDrag()) {
-                child.mPrivateFlags2 |= View.DRAG_CAN_ACCEPT;
+                child.mPrivateFlags2 |= View.PFLAG2_DRAG_CAN_ACCEPT;
                 child.refreshDrawableState();
             }
         }
@@ -1333,9 +1330,11 @@
      */
     @Override
     public boolean dispatchKeyEventPreIme(KeyEvent event) {
-        if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
+        if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
+                == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
             return super.dispatchKeyEventPreIme(event);
-        } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+        } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
+                == PFLAG_HAS_BOUNDS) {
             return mFocused.dispatchKeyEventPreIme(event);
         }
         return false;
@@ -1350,11 +1349,13 @@
             mInputEventConsistencyVerifier.onKeyEvent(event, 1);
         }
 
-        if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
+        if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
+                == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
             if (super.dispatchKeyEvent(event)) {
                 return true;
             }
-        } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+        } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
+                == PFLAG_HAS_BOUNDS) {
             if (mFocused.dispatchKeyEvent(event)) {
                 return true;
             }
@@ -1371,9 +1372,11 @@
      */
     @Override
     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
-        if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
+        if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
+                == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
             return super.dispatchKeyShortcutEvent(event);
-        } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+        } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
+                == PFLAG_HAS_BOUNDS) {
             return mFocused.dispatchKeyShortcutEvent(event);
         }
         return false;
@@ -1388,11 +1391,13 @@
             mInputEventConsistencyVerifier.onTrackballEvent(event, 1);
         }
 
-        if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
+        if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
+                == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
             if (super.dispatchTrackballEvent(event)) {
                 return true;
             }
-        } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+        } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
+                == PFLAG_HAS_BOUNDS) {
             if (mFocused.dispatchTrackballEvent(event)) {
                 return true;
             }
@@ -1658,20 +1663,6 @@
     }
 
     /**
-     * @hide
-     */
-    @Override
-    public View findViewToTakeAccessibilityFocusFromHover(View child, View descendant) {
-        if (includeForAccessibility() && isActionableForAccessibility()) {
-            return this;
-        }
-        if (mParent != null) {
-            return mParent.findViewToTakeAccessibilityFocusFromHover(this, descendant);
-        }
-        return null;
-    }
-
-    /**
      * Implement this method to intercept hover events before they are handled
      * by child views.
      * <p>
@@ -1732,8 +1723,10 @@
             final float x = event.getX();
             final float y = event.getY();
 
+            final boolean customOrder = isChildrenDrawingOrderEnabled();
             for (int i = childrenCount - 1; i >= 0; i--) {
-                final View child = children[i];
+                final int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;
+                final View child = children[childIndex];
                 if (!canViewReceivePointerEvents(child)
                         || !isTransformedTouchPointInView(x, y, child, null)) {
                     continue;
@@ -1755,9 +1748,11 @@
     @Override
     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
         // Send the event to the focused child or to this view group if it has focus.
-        if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
+        if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
+                == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
             return super.dispatchGenericFocusedEvent(event);
-        } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+        } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
+                == PFLAG_HAS_BOUNDS) {
             return mFocused.dispatchGenericMotionEvent(event);
         }
         return false;
@@ -1858,8 +1853,11 @@
                         final float x = ev.getX(actionIndex);
                         final float y = ev.getY(actionIndex);
 
+                        final boolean customOrder = isChildrenDrawingOrderEnabled();
                         for (int i = childrenCount - 1; i >= 0; i--) {
-                            final View child = children[i];
+                            final int childIndex = customOrder ?
+                                    getChildDrawingOrder(childrenCount, i) : i;
+                            final View child = children[childIndex];
                             if (!canViewReceivePointerEvents(child)
                                     || !isTransformedTouchPointInView(x, y, child, null)) {
                                 continue;
@@ -1877,7 +1875,7 @@
                             if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
                                 // Child wants to receive touch within its bounds.
                                 mLastTouchDownTime = ev.getDownTime();
-                                mLastTouchDownIndex = i;
+                                mLastTouchDownIndex = childIndex;
                                 mLastTouchDownX = ev.getX();
                                 mLastTouchDownY = ev.getY();
                                 newTouchTarget = addTouchTarget(child, idBitsToAssign);
@@ -1968,8 +1966,8 @@
      * Returns true if the flag was previously set.
      */
     private static boolean resetCancelNextUpFlag(View view) {
-        if ((view.mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
-            view.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
+        if ((view.mPrivateFlags & PFLAG_CANCEL_NEXT_UP_EVENT) != 0) {
+            view.mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
             return true;
         }
         return false;
@@ -2535,11 +2533,11 @@
     }
 
     /**
-     * {@inheritDoc}
+     * @hide
      */
     @Override
-    public void setPadding(int left, int top, int right, int bottom) {
-        super.setPadding(left, top, right, bottom);
+    protected void internalSetPadding(int left, int top, int right, int bottom) {
+        super.internalSetPadding(left, top, right, bottom);
 
         if ((mPaddingLeft | mPaddingTop | mPaddingRight | mPaddingBottom) != 0) {
             mGroupFlags |= FLAG_PADDING_NOT_NULL;
@@ -2786,7 +2784,7 @@
         }
 
         // We will draw our child's animation, let's reset the flag
-        mPrivateFlags &= ~DRAW_ANIMATION;
+        mPrivateFlags &= ~PFLAG_DRAW_ANIMATION;
         mGroupFlags &= ~FLAG_INVALIDATE_REQUIRED;
 
         boolean more = false;
@@ -2906,8 +2904,9 @@
             final View child = children[i];
             if (((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) &&
                     child.hasStaticLayer()) {
-                child.mRecreateDisplayList = (child.mPrivateFlags & INVALIDATED) == INVALIDATED;
-                child.mPrivateFlags &= ~INVALIDATED;
+                child.mRecreateDisplayList = (child.mPrivateFlags & PFLAG_INVALIDATED)
+                        == PFLAG_INVALIDATED;
+                child.mPrivateFlags &= ~PFLAG_INVALIDATED;
                 child.getDisplayList();
                 child.mRecreateDisplayList = false;
             }
@@ -2930,45 +2929,6 @@
     }
 
     /**
-     * 
-     * @param enabled True if children should be drawn with layers, false otherwise.
-     * 
-     * @hide
-     */
-    public void setChildrenLayersEnabled(boolean enabled) {
-        if (enabled != mDrawLayers) {
-            mDrawLayers = enabled;
-            invalidate(true);
-
-            boolean flushLayers = !enabled;
-            AttachInfo info = mAttachInfo;
-            if (info != null && info.mHardwareRenderer != null &&
-                    info.mHardwareRenderer.isEnabled()) {
-                if (!info.mHardwareRenderer.validate()) {
-                    flushLayers = false;
-                }
-            } else {
-                flushLayers = false;
-            }
-
-            // We need to invalidate any child with a layer. For instance,
-            // if a child is backed by a hardware layer and we disable layers
-            // the child is marked as not dirty (flags cleared the last time
-            // the child was drawn inside its layer.) However, that child might
-            // never have created its own display list or have an obsolete
-            // display list. By invalidating the child we ensure the display
-            // list is in sync with the content of the hardware layer.
-            for (int i = 0; i < mChildrenCount; i++) {
-                View child = mChildren[i];
-                if (child.mLayerType != LAYER_TYPE_NONE) {
-                    if (flushLayers) child.flushLayer();
-                    child.invalidate(true);
-                }
-            }
-        }
-    }
-
-    /**
      * By default, children are clipped to their bounds before drawing. This
      * allows view groups to override this behavior for animations, etc.
      *
@@ -3052,7 +3012,7 @@
      *
      * @param enabled True to enable static transformations on children, false otherwise.
      *
-     * @see #FLAG_SUPPORT_STATIC_TRANSFORMATIONS
+     * @see #getChildStaticTransformation(View, android.view.animation.Transformation)
      */
     protected void setStaticTransformationsEnabled(boolean enabled) {
         setBooleanFlag(FLAG_SUPPORT_STATIC_TRANSFORMATIONS, enabled);
@@ -3062,7 +3022,8 @@
      * Sets  <code>t</code> to be the static transformation of the child, if set, returning a
      * boolean to indicate whether a static transform was set. The default implementation
      * simply returns <code>false</code>; subclasses may override this method for different
-     * behavior.
+     * behavior. {@link #setStaticTransformationsEnabled(boolean)} must be set to true
+     * for this method to be called.
      *
      * @param child The child view whose static transform is being requested
      * @param t The Transformation which will hold the result
@@ -3088,7 +3049,7 @@
         for (int i = 0; i < len; i++) {
             View v = where[i];
 
-            if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
+            if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
                 v = v.findViewById(id);
 
                 if (v != null) {
@@ -3115,7 +3076,7 @@
         for (int i = 0; i < len; i++) {
             View v = where[i];
 
-            if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
+            if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
                 v = v.findViewWithTag(tag);
 
                 if (v != null) {
@@ -3142,7 +3103,7 @@
         for (int i = 0; i < len; i++) {
             View v = where[i];
 
-            if (v != childToSkip && (v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
+            if (v != childToSkip && (v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
                 v = v.findViewByPredicate(predicate);
 
                 if (v != null) {
@@ -3352,7 +3313,7 @@
             boolean preventRequestLayout) {
         child.mParent = null;
         addViewInner(child, index, params, preventRequestLayout);
-        child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK) | DRAWN;
+        child.mPrivateFlags = (child.mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
         return true;
     }
 
@@ -3362,7 +3323,7 @@
      * @param child the child on which to perform the cleanup
      */
     protected void cleanupLayoutState(View child) {
-        child.mPrivateFlags &= ~View.FORCE_LAYOUT;
+        child.mPrivateFlags &= ~View.PFLAG_FORCE_LAYOUT;
     }
 
     private void addViewInner(View child, int index, LayoutParams params,
@@ -3421,6 +3382,10 @@
             ai.mKeepScreenOn = lastKeepOn;
         }
 
+        if (child.isLayoutDirectionInherited()) {
+            child.resetRtlProperties();
+        }
+
         onViewAdded(child);
 
         if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) {
@@ -3655,6 +3620,8 @@
             childHasTransientStateChanged(view, false);
         }
 
+        view.resetRtlProperties();
+
         onViewRemoved(view);
 
         needGlobalAttributesUpdate(false);
@@ -3838,6 +3805,13 @@
     /**
      * Finishes the removal of a detached view. This method will dispatch the detached from
      * window event and notify the hierarchy change listener.
+     * <p>
+     * This method is intended to be lightweight and makes no assumptions about whether the
+     * parent or child should be redrawn. Proper use of this method will include also making
+     * any appropriate {@link #requestLayout()} or {@link #invalidate()} calls.
+     * For example, callers can {@link #post(Runnable) post} a {@link Runnable}
+     * which performs a {@link #requestLayout()} on the next frame, after all detach/remove
+     * calls are finished, causing layout to be run prior to redrawing the view hierarchy.
      *
      * @param child the child to be definitely removed from the view hierarchy
      * @param animate if true and the view has an animation, the view is placed in the
@@ -3878,10 +3852,17 @@
 
     /**
      * Attaches a view to this view group. Attaching a view assigns this group as the parent,
-     * sets the layout parameters and puts the view in the list of children so it can be retrieved
-     * by calling {@link #getChildAt(int)}.
-     *
-     * This method should be called only for view which were detached from their parent.
+     * sets the layout parameters and puts the view in the list of children so that
+     * it can be retrieved by calling {@link #getChildAt(int)}.
+     * <p>
+     * This method is intended to be lightweight and makes no assumptions about whether the
+     * parent or child should be redrawn. Proper use of this method will include also making
+     * any appropriate {@link #requestLayout()} or {@link #invalidate()} calls.
+     * For example, callers can {@link #post(Runnable) post} a {@link Runnable}
+     * which performs a {@link #requestLayout()} on the next frame, after all detach/attach
+     * calls are finished, causing layout to be run prior to redrawing the view hierarchy.
+     * <p>
+     * This method should be called only for views which were detached from their parent.
      *
      * @param child the child to attach
      * @param index the index at which the child should be attached
@@ -3902,9 +3883,10 @@
         addInArray(child, index);
 
         child.mParent = this;
-        child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK & ~DRAWING_CACHE_VALID) |
-                DRAWN | INVALIDATED;
-        this.mPrivateFlags |= INVALIDATED;
+        child.mPrivateFlags = (child.mPrivateFlags & ~PFLAG_DIRTY_MASK
+                        & ~PFLAG_DRAWING_CACHE_VALID)
+                | PFLAG_DRAWN | PFLAG_INVALIDATED;
+        this.mPrivateFlags |= PFLAG_INVALIDATED;
 
         if (child.hasFocus()) {
             requestChildFocus(child, child.findFocus());
@@ -3912,10 +3894,13 @@
     }
 
     /**
-     * Detaches a view from its parent. Detaching a view should be temporary and followed
-     * either by a call to {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)}
-     * or a call to {@link #removeDetachedView(View, boolean)}. When a view is detached,
-     * its parent is null and cannot be retrieved by a call to {@link #getChildAt(int)}.
+     * Detaches a view from its parent. Detaching a view should be followed
+     * either by a call to
+     * {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)}
+     * or a call to {@link #removeDetachedView(View, boolean)}. Detachment should only be
+     * temporary; reattachment or removal should happen within the same drawing cycle as
+     * detachment. When a view is detached, its parent is null and cannot be retrieved by a
+     * call to {@link #getChildAt(int)}.
      *
      * @param child the child to detach
      *
@@ -3930,10 +3915,13 @@
     }
 
     /**
-     * Detaches a view from its parent. Detaching a view should be temporary and followed
-     * either by a call to {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)}
-     * or a call to {@link #removeDetachedView(View, boolean)}. When a view is detached,
-     * its parent is null and cannot be retrieved by a call to {@link #getChildAt(int)}.
+     * Detaches a view from its parent. Detaching a view should be followed
+     * either by a call to
+     * {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)}
+     * or a call to {@link #removeDetachedView(View, boolean)}. Detachment should only be
+     * temporary; reattachment or removal should happen within the same drawing cycle as
+     * detachment. When a view is detached, its parent is null and cannot be retrieved by a
+     * call to {@link #getChildAt(int)}.
      *
      * @param index the index of the child to detach
      *
@@ -3948,10 +3936,13 @@
     }
 
     /**
-     * Detaches a range of view from their parent. Detaching a view should be temporary and followed
-     * either by a call to {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)}
-     * or a call to {@link #removeDetachedView(View, boolean)}. When a view is detached, its
-     * parent is null and cannot be retrieved by a call to {@link #getChildAt(int)}.
+     * Detaches a range of views from their parents. Detaching a view should be followed
+     * either by a call to
+     * {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)}
+     * or a call to {@link #removeDetachedView(View, boolean)}. Detachment should only be
+     * temporary; reattachment or removal should happen within the same drawing cycle as
+     * detachment. When a view is detached, its parent is null and cannot be retrieved by a
+     * call to {@link #getChildAt(int)}.
      *
      * @param start the first index of the childrend range to detach
      * @param count the number of children to detach
@@ -3967,10 +3958,13 @@
     }
 
     /**
-     * Detaches all views from the parent. Detaching a view should be temporary and followed
-     * either by a call to {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)}
-     * or a call to {@link #removeDetachedView(View, boolean)}. When a view is detached,
-     * its parent is null and cannot be retrieved by a call to {@link #getChildAt(int)}.
+     * Detaches all views from the parent. Detaching a view should be followed
+     * either by a call to
+     * {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)}
+     * or a call to {@link #removeDetachedView(View, boolean)}. Detachment should only be
+     * temporary; reattachment or removal should happen within the same drawing cycle as
+     * detachment. When a view is detached, its parent is null and cannot be retrieved by a
+     * call to {@link #getChildAt(int)}.
      *
      * @see #detachViewFromParent(View)
      * @see #detachViewFromParent(int)
@@ -4005,7 +3999,8 @@
             // If the child is drawing an animation, we want to copy this flag onto
             // ourselves and the parent to make sure the invalidate request goes
             // through
-            final boolean drawAnimation = (child.mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION;
+            final boolean drawAnimation = (child.mPrivateFlags & PFLAG_DRAW_ANIMATION)
+                    == PFLAG_DRAW_ANIMATION;
 
             // Check whether the child that requests the invalidate is fully opaque
             // Views being animated or transformed are not considered opaque because we may
@@ -4015,22 +4010,38 @@
                     child.getAnimation() == null && childMatrix.isIdentity();
             // Mark the child as dirty, using the appropriate flag
             // Make sure we do not set both flags at the same time
-            int opaqueFlag = isOpaque ? DIRTY_OPAQUE : DIRTY;
+            int opaqueFlag = isOpaque ? PFLAG_DIRTY_OPAQUE : PFLAG_DIRTY;
 
             if (child.mLayerType != LAYER_TYPE_NONE) {
-                mPrivateFlags |= INVALIDATED;
-                mPrivateFlags &= ~DRAWING_CACHE_VALID;
+                mPrivateFlags |= PFLAG_INVALIDATED;
+                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
                 child.mLocalDirtyRect.union(dirty);
             }
 
             final int[] location = attachInfo.mInvalidateChildLocation;
             location[CHILD_LEFT_INDEX] = child.mLeft;
             location[CHILD_TOP_INDEX] = child.mTop;
-            if (!childMatrix.isIdentity()) {
+            if (!childMatrix.isIdentity() ||
+                    (mGroupFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
                 RectF boundingRect = attachInfo.mTmpTransformRect;
                 boundingRect.set(dirty);
-                //boundingRect.inset(-0.5f, -0.5f);
-                childMatrix.mapRect(boundingRect);
+                Matrix transformMatrix;
+                if ((mGroupFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
+                    Transformation t = attachInfo.mTmpTransformation;
+                    boolean transformed = getChildStaticTransformation(child, t);
+                    if (transformed) {
+                        transformMatrix = attachInfo.mTmpMatrix;
+                        transformMatrix.set(t.getMatrix());
+                        if (!childMatrix.isIdentity()) {
+                            transformMatrix.preConcat(childMatrix);
+                        }
+                    } else {
+                        transformMatrix = childMatrix;
+                    }
+                } else {
+                    transformMatrix = childMatrix;
+                }
+                transformMatrix.mapRect(boundingRect);
                 dirty.set((int) (boundingRect.left - 0.5f),
                         (int) (boundingRect.top - 0.5f),
                         (int) (boundingRect.right + 0.5f),
@@ -4045,7 +4056,7 @@
 
                 if (drawAnimation) {
                     if (view != null) {
-                        view.mPrivateFlags |= DRAW_ANIMATION;
+                        view.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
                     } else if (parent instanceof ViewRootImpl) {
                         ((ViewRootImpl) parent).mIsAnimating = true;
                     }
@@ -4056,10 +4067,10 @@
                 if (view != null) {
                     if ((view.mViewFlags & FADING_EDGE_MASK) != 0 &&
                             view.getSolidColor() == 0) {
-                        opaqueFlag = DIRTY;
+                        opaqueFlag = PFLAG_DIRTY;
                     }
-                    if ((view.mPrivateFlags & DIRTY_MASK) != DIRTY) {
-                        view.mPrivateFlags = (view.mPrivateFlags & ~DIRTY_MASK) | opaqueFlag;
+                    if ((view.mPrivateFlags & PFLAG_DIRTY_MASK) != PFLAG_DIRTY) {
+                        view.mPrivateFlags = (view.mPrivateFlags & ~PFLAG_DIRTY_MASK) | opaqueFlag;
                     }
                 }
 
@@ -4090,8 +4101,8 @@
      * does not intersect with this ViewGroup's bounds.
      */
     public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {
-        if ((mPrivateFlags & DRAWN) == DRAWN ||
-                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
+        if ((mPrivateFlags & PFLAG_DRAWN) == PFLAG_DRAWN ||
+                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) {
             if ((mGroupFlags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) !=
                         FLAG_OPTIMIZE_INVALIDATE) {
                 dirty.offset(location[CHILD_LEFT_INDEX] - mScrollX,
@@ -4105,20 +4116,20 @@
                         dirty.setEmpty();
                     }
                 }
-                mPrivateFlags &= ~DRAWING_CACHE_VALID;
+                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
 
                 location[CHILD_LEFT_INDEX] = left;
                 location[CHILD_TOP_INDEX] = top;
 
                 if (mLayerType != LAYER_TYPE_NONE) {
-                    mPrivateFlags |= INVALIDATED;
+                    mPrivateFlags |= PFLAG_INVALIDATED;
                     mLocalDirtyRect.union(dirty);
                 }
 
                 return mParent;
 
             } else {
-                mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID;
+                mPrivateFlags &= ~PFLAG_DRAWN & ~PFLAG_DRAWING_CACHE_VALID;
 
                 location[CHILD_LEFT_INDEX] = mLeft;
                 location[CHILD_TOP_INDEX] = mTop;
@@ -4130,7 +4141,7 @@
                 }
 
                 if (mLayerType != LAYER_TYPE_NONE) {
-                    mPrivateFlags |= INVALIDATED;
+                    mPrivateFlags |= PFLAG_INVALIDATED;
                     mLocalDirtyRect.union(dirty);
                 }
 
@@ -4192,8 +4203,8 @@
      * coordinate system, pruning the invalidation if the parent has already been invalidated.
      */
     private ViewParent invalidateChildInParentFast(int left, int top, final Rect dirty) {
-        if ((mPrivateFlags & DRAWN) == DRAWN ||
-                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
+        if ((mPrivateFlags & PFLAG_DRAWN) == PFLAG_DRAWN ||
+                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) {
             dirty.offset(left - mScrollX, top - mScrollY);
 
             if ((mGroupFlags & FLAG_CLIP_CHILDREN) == 0 ||
@@ -4956,11 +4967,11 @@
             view.clearAnimation();
         }
 
-        if ((view.mPrivateFlags & ANIMATION_STARTED) == ANIMATION_STARTED) {
+        if ((view.mPrivateFlags & PFLAG_ANIMATION_STARTED) == PFLAG_ANIMATION_STARTED) {
             view.onAnimationEnd();
             // Should be performed by onAnimationEnd() but this avoid an infinite loop,
             // so we'd rather be safe than sorry
-            view.mPrivateFlags &= ~ANIMATION_STARTED;
+            view.mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
             // Draw one more frame after the animation is done
             mGroupFlags |= FLAG_INVALIDATE_REQUIRED;
         }
@@ -5059,7 +5070,7 @@
     @Override
     public boolean gatherTransparentRegion(Region region) {
         // If no transparent regions requested, we are always opaque.
-        final boolean meOpaque = (mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) == 0;
+        final boolean meOpaque = (mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0;
         if (meOpaque && region == null) {
             // The caller doesn't care about the region, so stop now.
             return true;
@@ -5084,7 +5095,7 @@
      */
     public void requestTransparentRegion(View child) {
         if (child != null) {
-            child.mPrivateFlags |= View.REQUEST_TRANSPARENT_REGIONS;
+            child.mPrivateFlags |= View.PFLAG_REQUEST_TRANSPARENT_REGIONS;
             if (mParent != null) {
                 mParent.requestTransparentRegion(this);
             }
@@ -5249,12 +5260,140 @@
      * @hide
      */
     @Override
-    public void onResolvedLayoutDirectionReset() {
-        // Take care of resetting the children resolution too
-        final int count = getChildCount();
+    public void resolveRtlPropertiesIfNeeded() {
+        super.resolveRtlPropertiesIfNeeded();
+        int count = getChildCount();
         for (int i = 0; i < count; i++) {
             final View child = getChildAt(i);
-            if (child.getLayoutDirection() == LAYOUT_DIRECTION_INHERIT) {
+            if (child.isLayoutDirectionInherited()) {
+                child.resolveRtlPropertiesIfNeeded();
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public boolean resolveLayoutDirection() {
+        final boolean result = super.resolveLayoutDirection();
+        if (result) {
+            int count = getChildCount();
+            for (int i = 0; i < count; i++) {
+                final View child = getChildAt(i);
+                if (child.isLayoutDirectionInherited()) {
+                    child.resolveLayoutDirection();
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public boolean resolveTextDirection() {
+        final boolean result = super.resolveTextDirection();
+        if (result) {
+            int count = getChildCount();
+            for (int i = 0; i < count; i++) {
+                final View child = getChildAt(i);
+                if (child.isTextDirectionInherited()) {
+                    child.resolveTextDirection();
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public boolean resolveTextAlignment() {
+        final boolean result = super.resolveTextAlignment();
+        if (result) {
+            int count = getChildCount();
+            for (int i = 0; i < count; i++) {
+                final View child = getChildAt(i);
+                if (child.isTextAlignmentInherited()) {
+                    child.resolveTextAlignment();
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void resolvePadding() {
+        super.resolvePadding();
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.isLayoutDirectionInherited()) {
+                child.resolvePadding();
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    protected void resolveDrawables() {
+        super.resolveDrawables();
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.isLayoutDirectionInherited()) {
+                child.resolveDrawables();
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void resolveLayoutParams() {
+        super.resolveLayoutParams();
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            child.resolveLayoutParams();
+        }
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void resetRtlProperties() {
+        super.resetRtlProperties();
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.isLayoutDirectionInherited()) {
+                child.resetRtlProperties();
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void resetResolvedLayoutDirection() {
+        super.resetResolvedLayoutDirection();
+
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.isLayoutDirectionInherited()) {
                 child.resetResolvedLayoutDirection();
             }
         }
@@ -5264,12 +5403,13 @@
      * @hide
      */
     @Override
-    public void onResolvedTextDirectionReset() {
-        // Take care of resetting the children resolution too
-        final int count = getChildCount();
+    public void resetResolvedTextDirection() {
+        super.resetResolvedTextDirection();
+
+        int count = getChildCount();
         for (int i = 0; i < count; i++) {
             final View child = getChildAt(i);
-            if (child.getTextDirection() == TEXT_DIRECTION_INHERIT) {
+            if (child.isTextDirectionInherited()) {
                 child.resetResolvedTextDirection();
             }
         }
@@ -5279,18 +5419,51 @@
      * @hide
      */
     @Override
-    public void onResolvedTextAlignmentReset() {
-        // Take care of resetting the children resolution too
-        final int count = getChildCount();
+    public void resetResolvedTextAlignment() {
+        super.resetResolvedTextAlignment();
+
+        int count = getChildCount();
         for (int i = 0; i < count; i++) {
             final View child = getChildAt(i);
-            if (child.getTextAlignment() == TEXT_ALIGNMENT_INHERIT) {
+            if (child.isTextAlignmentInherited()) {
                 child.resetResolvedTextAlignment();
             }
         }
     }
 
     /**
+     * @hide
+     */
+    @Override
+    public void resetResolvedPadding() {
+        super.resetResolvedPadding();
+
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.isLayoutDirectionInherited()) {
+                child.resetResolvedPadding();
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    protected void resetResolvedDrawables() {
+        super.resetResolvedDrawables();
+
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.isLayoutDirectionInherited()) {
+                child.resetResolvedDrawables();
+            }
+        }
+    }
+
+    /**
      * Return true if the pressed state should be delayed for children or descendants of this
      * ViewGroup. Generally, this should be done for containers that can scroll, such as a List.
      * This prevents the pressed state from appearing when the user is actually trying to scroll
@@ -5468,9 +5641,8 @@
          *
          * {@link View#LAYOUT_DIRECTION_LTR}
          * {@link View#LAYOUT_DIRECTION_RTL}
-         * @hide
          */
-        public void onResolveLayoutDirection(int layoutDirection) {
+        public void resolveLayoutDirection(int layoutDirection) {
         }
 
         /**
@@ -5560,24 +5732,31 @@
          * The start margin in pixels of the child.
          * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value
          * to this field.
-         * @hide
          */
         @ViewDebug.ExportedProperty(category = "layout")
-        public int startMargin = DEFAULT_RELATIVE;
+        private int startMargin = DEFAULT_RELATIVE;
 
         /**
          * The end margin in pixels of the child.
          * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value
          * to this field.
-         * @hide
          */
         @ViewDebug.ExportedProperty(category = "layout")
-        public int endMargin = DEFAULT_RELATIVE;
+        private int endMargin = DEFAULT_RELATIVE;
 
         /**
          * The default start and end margin.
+         * @hide
          */
-        static private final int DEFAULT_RELATIVE = Integer.MIN_VALUE;
+        public static final int DEFAULT_RELATIVE = Integer.MIN_VALUE;
+
+        private int initialLeftMargin;
+        private int initialRightMargin;
+
+        private static int LAYOUT_DIRECTION_UNDEFINED = -1;
+
+        // Layout direction undefined by default
+        private int layoutDirection = LAYOUT_DIRECTION_UNDEFINED;
 
         /**
          * Creates a new set of layout parameters. The values are extracted from
@@ -5617,6 +5796,9 @@
                         R.styleable.ViewGroup_MarginLayout_layout_marginEnd, DEFAULT_RELATIVE);
             }
 
+            initialLeftMargin = leftMargin;
+            initialRightMargin = rightMargin;
+
             a.recycle();
         }
 
@@ -5642,6 +5824,11 @@
             this.bottomMargin = source.bottomMargin;
             this.startMargin = source.startMargin;
             this.endMargin = source.endMargin;
+
+            this.initialLeftMargin = source.leftMargin;
+            this.initialRightMargin = source.rightMargin;
+
+            setLayoutDirection(source.layoutDirection);
         }
 
         /**
@@ -5671,6 +5858,8 @@
             topMargin = top;
             rightMargin = right;
             bottomMargin = bottom;
+            initialLeftMargin = left;
+            initialRightMargin = right;
         }
 
         /**
@@ -5688,6 +5877,7 @@
          * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginTop
          * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
          * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginBottom
+         *
          * @hide
          */
         public void setMarginsRelative(int start, int top, int end, int bottom) {
@@ -5695,6 +5885,19 @@
             topMargin = top;
             endMargin = end;
             bottomMargin = bottom;
+            initialLeftMargin = 0;
+            initialRightMargin = 0;
+        }
+
+        /**
+         * Sets the relative start margin.
+         *
+         * @param start the start margin size
+         *
+         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginStart
+         */
+        public void setMarginStart(int start) {
+            startMargin = start;
         }
 
         /**
@@ -5703,10 +5906,27 @@
          * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginStart
          *
          * @return the start margin in pixels.
-         * @hide
          */
         public int getMarginStart() {
-            return startMargin;
+            if (startMargin != DEFAULT_RELATIVE) return startMargin;
+            switch(layoutDirection) {
+                case View.LAYOUT_DIRECTION_RTL:
+                    return rightMargin;
+                case View.LAYOUT_DIRECTION_LTR:
+                default:
+                    return leftMargin;
+            }
+        }
+
+        /**
+         * Sets the relative end margin.
+         *
+         * @param end the end margin size
+         *
+         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
+         */
+        public void setMarginEnd(int end) {
+            endMargin = end;
         }
 
         /**
@@ -5715,10 +5935,16 @@
          * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
          *
          * @return the end margin in pixels.
-         * @hide
          */
         public int getMarginEnd() {
-            return endMargin;
+            if (endMargin != DEFAULT_RELATIVE) return endMargin;
+            switch(layoutDirection) {
+                case View.LAYOUT_DIRECTION_RTL:
+                    return leftMargin;
+                case View.LAYOUT_DIRECTION_LTR:
+                default:
+                    return rightMargin;
+            }
         }
 
         /**
@@ -5727,29 +5953,53 @@
          * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginStart
          * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
          *
-         * @return true if either marginStart or marginEnd has been set
-         * @hide
+         * @return true if either marginStart or marginEnd has been set.
          */
         public boolean isMarginRelative() {
             return (startMargin != DEFAULT_RELATIVE) || (endMargin != DEFAULT_RELATIVE);
         }
 
         /**
+         * Set the layout direction
+         * @param layoutDirection the layout direction.
+         *        Should be either {@link View#LAYOUT_DIRECTION_LTR}
+         *                     or {@link View#LAYOUT_DIRECTION_RTL}.
+         */
+        public void setLayoutDirection(int layoutDirection) {
+            if (layoutDirection != View.LAYOUT_DIRECTION_LTR &&
+                    layoutDirection != View.LAYOUT_DIRECTION_RTL) return;
+            this.layoutDirection = layoutDirection;
+        }
+
+        /**
+         * Retuns the layout direction. Can be either {@link View#LAYOUT_DIRECTION_LTR} or
+         * {@link View#LAYOUT_DIRECTION_RTL}.
+         *
+         * @return the layout direction.
+         */
+        public int getLayoutDirection() {
+            return layoutDirection;
+        }
+
+        /**
          * This will be called by {@link android.view.View#requestLayout()}. Left and Right margins
          * may be overridden depending on layout direction.
-         * @hide
          */
         @Override
-        public void onResolveLayoutDirection(int layoutDirection) {
+        public void resolveLayoutDirection(int layoutDirection) {
+            setLayoutDirection(layoutDirection);
+
+            if (!isMarginRelative()) return;
+
             switch(layoutDirection) {
                 case View.LAYOUT_DIRECTION_RTL:
-                    leftMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : leftMargin;
-                    rightMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : rightMargin;
+                    leftMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : initialLeftMargin;
+                    rightMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : initialRightMargin;
                     break;
                 case View.LAYOUT_DIRECTION_LTR:
                 default:
-                    leftMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : leftMargin;
-                    rightMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : rightMargin;
+                    leftMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : initialLeftMargin;
+                    rightMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : initialRightMargin;
                     break;
             }
         }
@@ -5757,6 +6007,13 @@
         /**
          * @hide
          */
+        public boolean isLayoutRtl() {
+            return (layoutDirection == View.LAYOUT_DIRECTION_RTL);
+        }
+
+        /**
+         * @hide
+         */
         @Override
         public void onDebugDraw(View view, Canvas canvas) {
             drawRect(canvas,
@@ -6080,7 +6337,7 @@
             view.getDrawingRect(viewLocation);
             root.offsetDescendantRectToMyCoords(view, viewLocation);
             mView = view;
-            mLayoutDirection = root.getResolvedLayoutDirection();
+            mLayoutDirection = root.getLayoutDirection();
         }
 
         private void clear() {
diff --git a/core/java/android/view/ViewManager.java b/core/java/android/view/ViewManager.java
index 7f318c1..ab6856f 100644
--- a/core/java/android/view/ViewManager.java
+++ b/core/java/android/view/ViewManager.java
@@ -21,6 +21,16 @@
   */
 public interface ViewManager
 {
+    /**
+     * Assign the passed LayoutParams to the passed View and add the view to the window.
+     * <p>Throws {@link android.view.WindowManager.BadTokenException} for certain programming
+     * errors, such as adding a second view to a window without removing the first view.
+     * <p>Throws {@link android.view.WindowManager.InvalidDisplayException} if the window is on a
+     * secondary {@link Display} and the specified display can't be found
+     * (see {@link android.app.Presentation}).
+     * @param view The view to be added to this window.
+     * @param params The LayoutParams to assign to view.
+     */
     public void addView(View view, ViewGroup.LayoutParams params);
     public void updateViewLayout(View view, ViewGroup.LayoutParams params);
     public void removeView(View view);
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index d93b996..ddff91d 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -295,16 +295,4 @@
      * @hide
      */
     public void childAccessibilityStateChanged(View child);
-
-    /**
-     * A descendant requests this view to find a candidate to take accessibility
-     * focus from hover.
-     *
-     * @param child The child making the call.
-     * @param descendant The descendant that made the initial request.
-     * @return A view to take accessibility focus.
-     *
-     * @hide
-     */
-    public View findViewToTakeAccessibilityFocusFromHover(View child, View descendant);
 }
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index ce6f4c5..d8db14c 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -1036,7 +1036,7 @@
             if ((propertyMask & TRANSFORM_MASK) != 0) {
                 mView.mTransformationInfo.mMatrixDirty = true;
                 if (!useDisplayListProperties) {
-                    mView.mPrivateFlags |= View.DRAWN; // force another invalidation
+                    mView.mPrivateFlags |= View.PFLAG_DRAWN; // force another invalidation
                 }
             }
             // invalidate(false) in all cases except if alphaHandled gets set to true
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ad850da..b6016e9 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -18,7 +18,6 @@
 
 import android.Manifest;
 import android.animation.LayoutTransition;
-import android.animation.ValueAnimator;
 import android.app.ActivityManagerNative;
 import android.content.ClipDescription;
 import android.content.ComponentCallbacks;
@@ -74,10 +73,9 @@
 import android.widget.Scroller;
 
 import com.android.internal.R;
+import com.android.internal.os.SomeArgs;
 import com.android.internal.policy.PolicyManager;
 import com.android.internal.view.BaseSurfaceHolder;
-import com.android.internal.view.IInputMethodCallback;
-import com.android.internal.view.IInputMethodSession;
 import com.android.internal.view.RootViewSurfaceTaker;
 
 import java.io.IOException;
@@ -89,7 +87,7 @@
 /**
  * The top of a view hierarchy, implementing the needed protocol between View
  * and the WindowManager.  This is for the most part an internal implementation
- * detail of {@link WindowManagerImpl}.
+ * detail of {@link WindowManagerGlobal}.
  *
  * {@hide}
  */
@@ -111,7 +109,7 @@
     private static final boolean DEBUG_FPS = false;
 
     private static final boolean USE_RENDER_THREAD = false;
-    
+
     /**
      * Set this system property to true to force the view hierarchy to render
      * at 60 Hz. This can be used to measure the potential framerate.
@@ -127,11 +125,6 @@
      */
     static final int MAX_TRACKBALL_DELAY = 250;
 
-    static IWindowSession sWindowSession;
-
-    static final Object mStaticInit = new Object();
-    static boolean mInitialized = false;
-
     static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<RunQueue>();
 
     static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList<Runnable>();
@@ -144,6 +137,9 @@
     private static boolean sRenderThreadQueried = false;
     private static final Object[] sRenderThreadQueryLock = new Object[0];
 
+    final IWindowSession mWindowSession;
+    final Display mDisplay;
+
     long mLastTrackballTime = 0;
     final TrackballAxis mTrackballAxisX = new TrackballAxis();
     final TrackballAxis mTrackballAxisY = new TrackballAxis();
@@ -218,6 +214,9 @@
     boolean mTraversalScheduled;
     int mTraversalBarrier;
     boolean mWillDrawSoon;
+    /** Set to true while in performTraversals for detecting when die(true) is called from internal
+     * callbacks such as onMeasure, onPreDraw, onDraw and deferring doDie() until later. */
+    boolean mIsInTraversal;
     boolean mFitSystemWindowsRequested;
     boolean mLayoutRequested;
     boolean mFirst;
@@ -251,9 +250,7 @@
     boolean mAdded;
     boolean mAddedTouchMode;
 
-    CompatibilityInfoHolder mCompatibilityInfo;
-
-    /*package*/ int mAddNesting;
+    final CompatibilityInfoHolder mCompatibilityInfo;
 
     // These are accessed by multiple threads.
     final Rect mWinFrame; // frame given by window manager.
@@ -268,12 +265,6 @@
     final Configuration mLastConfiguration = new Configuration();
     final Configuration mPendingConfiguration = new Configuration();
 
-    class ResizedInfo {
-        Rect contentInsets;
-        Rect visibleInsets;
-        Configuration newConfig;
-    }
-    
     boolean mScrollMayChange;
     int mSoftInputMode;
     View mLastScrolledFocus;
@@ -322,6 +313,9 @@
     HashSet<View> mTempHashSet;
 
     private final int mDensity;
+    private final int mNoncompatDensity;
+
+    private int mViewLayoutDirectionInitial;
 
     /**
      * Consistency verifier for debugging purposes.
@@ -330,24 +324,6 @@
             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
                     new InputEventConsistencyVerifier(this, 0) : null;
 
-    public static IWindowSession getWindowSession(Looper mainLooper) {
-        synchronized (mStaticInit) {
-            if (!mInitialized) {
-                try {
-                    InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
-                    IWindowManager windowManager = Display.getWindowManager();
-                    sWindowSession = windowManager.openSession(
-                            imm.getClient(), imm.getInputContext());
-                    float animatorScale = windowManager.getAnimationScale(2);
-                    ValueAnimator.setDurationScale(animatorScale);
-                    mInitialized = true;
-                } catch (RemoteException e) {
-                }
-            }
-            return sWindowSession;
-        }
-    }
-
     static final class SystemUiVisibilityInfo {
         int seq;
         int globalVisibility;
@@ -355,7 +331,7 @@
         int localChanges;
     }
     
-    public ViewRootImpl(Context context) {
+    public ViewRootImpl(Context context, Display display) {
         super();
 
         if (MEASURE_LATENCY) {
@@ -367,7 +343,11 @@
         // Initialize the statics when this class is first instantiated. This is
         // done here instead of in the static block because Zygote does not
         // allow the spawning of threads.
-        getWindowSession(context.getMainLooper());
+        mWindowSession = WindowManagerGlobal.getWindowSession(context.getMainLooper());
+        mDisplay = display;
+
+        CompatibilityInfoHolder cih = display.getCompatibilityInfo();
+        mCompatibilityInfo = cih != null ? cih : new CompatibilityInfoHolder();
 
         mThread = Thread.currentThread();
         mLocation = new WindowLeaked(null);
@@ -391,9 +371,10 @@
             new AccessibilityInteractionConnectionManager();
         mAccessibilityManager.addAccessibilityStateChangeListener(
                 mAccessibilityInteractionConnectionManager);
-        mAttachInfo = new View.AttachInfo(sWindowSession, mWindow, this, mHandler, this);
+        mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);
         mViewConfiguration = ViewConfiguration.get(context);
         mDensity = context.getResources().getDisplayMetrics().densityDpi;
+        mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
         mFallbackEventHandler = PolicyManager.makeNewFallbackEventHandler(context);
         mProfileRendering = Boolean.parseBoolean(
                 SystemProperties.get(PROPERTY_PROFILE_RENDERING, "false"));
@@ -467,9 +448,10 @@
      * @hide
      */
     static boolean isInTouchMode() {
-        if (mInitialized) {
+        IWindowSession windowSession = WindowManagerGlobal.peekWindowSession();
+        if (windowSession != null) {
             try {
-                return sWindowSession.getInTouchMode();
+                return windowSession.getInTouchMode();
             } catch (RemoteException e) {
             }
         }
@@ -483,6 +465,7 @@
         synchronized (this) {
             if (mView == null) {
                 mView = view;
+                mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
                 mFallbackEventHandler.setView(view);
                 mWindowAttributes.copyFrom(attrs);
                 attrs = mWindowAttributes;
@@ -548,9 +531,9 @@
                     mOrigWindowType = mWindowAttributes.type;
                     mAttachInfo.mRecomputeGlobalAttributes = true;
                     collectViewAttributes();
-                    res = sWindowSession.add(mWindow, mSeq, mWindowAttributes,
-                            getHostVisibility(), mAttachInfo.mContentInsets,
-                            mInputChannel);
+                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
+                            getHostVisibility(), mDisplay.getDisplayId(),
+                            mAttachInfo.mContentInsets, mInputChannel);
                 } catch (RemoteException e) {
                     mAdded = false;
                     mView = null;
@@ -572,43 +555,46 @@
                 mPendingContentInsets.set(mAttachInfo.mContentInsets);
                 mPendingVisibleInsets.set(0, 0, 0, 0);
                 if (DEBUG_LAYOUT) Log.v(TAG, "Added window " + mWindow);
-                if (res < WindowManagerImpl.ADD_OKAY) {
-                    mView = null;
+                if (res < WindowManagerGlobal.ADD_OKAY) {
                     mAttachInfo.mRootView = null;
                     mAdded = false;
                     mFallbackEventHandler.setView(null);
                     unscheduleTraversals();
                     setAccessibilityFocus(null, null);
                     switch (res) {
-                        case WindowManagerImpl.ADD_BAD_APP_TOKEN:
-                        case WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_BAD_APP_TOKEN:
+                        case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window -- token " + attrs.token
                                 + " is not valid; is your activity running?");
-                        case WindowManagerImpl.ADD_NOT_APP_TOKEN:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_NOT_APP_TOKEN:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window -- token " + attrs.token
                                 + " is not for an application");
-                        case WindowManagerImpl.ADD_APP_EXITING:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_APP_EXITING:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window -- app for token " + attrs.token
                                 + " is exiting");
-                        case WindowManagerImpl.ADD_DUPLICATE_ADD:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_DUPLICATE_ADD:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window -- window " + mWindow
                                 + " has already been added");
-                        case WindowManagerImpl.ADD_STARTING_NOT_NEEDED:
+                        case WindowManagerGlobal.ADD_STARTING_NOT_NEEDED:
                             // Silently ignore -- we would have just removed it
                             // right away, anyway.
                             return;
-                        case WindowManagerImpl.ADD_MULTIPLE_SINGLETON:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_MULTIPLE_SINGLETON:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window " + mWindow +
                                 " -- another window of this type already exists");
-                        case WindowManagerImpl.ADD_PERMISSION_DENIED:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_PERMISSION_DENIED:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window " + mWindow +
                                 " -- permission denied for this window type");
+                        case WindowManagerGlobal.ADD_INVALID_DISPLAY:
+                            throw new WindowManager.InvalidDisplayException(
+                                "Unable to add window " + mWindow +
+                                " -- the specified display can not be found");
                     }
                     throw new RuntimeException(
                         "Unable to add window -- unknown error code " + res);
@@ -629,8 +615,8 @@
                 }
 
                 view.assignParent(this);
-                mAddedTouchMode = (res&WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE) != 0;
-                mAppVisible = (res&WindowManagerImpl.ADD_FLAG_APP_VISIBLE) != 0;
+                mAddedTouchMode = (res & WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE) != 0;
+                mAppVisible = (res & WindowManagerGlobal.ADD_FLAG_APP_VISIBLE) != 0;
 
                 if (mAccessibilityManager.isEnabled()) {
                     mAccessibilityInteractionConnectionManager.ensureConnection();
@@ -673,6 +659,12 @@
         }
     }
 
+    void pushHardwareLayerUpdate(HardwareLayer layer) {
+        if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
+            mAttachInfo.mHardwareRenderer.pushLayerUpdate(layer);
+        }
+    }
+
     public boolean attachFunctor(int functor) {
         //noinspection SimplifiableIfStatement
         if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
@@ -819,27 +811,21 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void requestFitSystemWindows() {
         checkThread();
         mFitSystemWindowsRequested = true;
         scheduleTraversals();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void requestLayout() {
         checkThread();
         mLayoutRequested = true;
         scheduleTraversals();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public boolean isLayoutRequested() {
         return mLayoutRequested;
     }
@@ -852,13 +838,14 @@
     void invalidateWorld(View view) {
         view.invalidate();
         if (view instanceof ViewGroup) {
-            ViewGroup parent = (ViewGroup)view;
-            for (int i=0; i<parent.getChildCount(); i++) {
+            ViewGroup parent = (ViewGroup) view;
+            for (int i = 0; i < parent.getChildCount(); i++) {
                 invalidateWorld(parent.getChildAt(i));
             }
         }
     }
 
+    @Override
     public void invalidateChild(View child, Rect dirty) {
         invalidateChildInParent(null, dirty);
     }
@@ -870,7 +857,7 @@
         if (dirty == null) {
             invalidate();
             return null;
-        } else if (dirty.isEmpty()) {
+        } else if (dirty.isEmpty() && !mIsAnimating) {
             return null;
         }
 
@@ -899,10 +886,12 @@
         // Intersect with the bounds of the window to skip
         // updates that lie outside of the visible region
         final float appScale = mAttachInfo.mApplicationScale;
-        localDirty.intersect(0, 0,
+        final boolean intersected = localDirty.intersect(0, 0,
                 (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
-
-        if (!mWillDrawSoon) {
+        if (!intersected) {
+            localDirty.setEmpty();
+        }
+        if (!mWillDrawSoon && (intersected || mIsAnimating)) {
             scheduleTraversals();
         }
 
@@ -1027,17 +1016,15 @@
             //Log.i(TAG, "Computing view hierarchy attributes!");
             attachInfo.mRecomputeGlobalAttributes = false;
             boolean oldScreenOn = attachInfo.mKeepScreenOn;
-            int oldVis = attachInfo.mSystemUiVisibility;
-            boolean oldHasSystemUiListeners = attachInfo.mHasSystemUiListeners;
             attachInfo.mKeepScreenOn = false;
             attachInfo.mSystemUiVisibility = 0;
             attachInfo.mHasSystemUiListeners = false;
             mView.dispatchCollectViewAttributes(attachInfo, 0);
             attachInfo.mSystemUiVisibility &= ~attachInfo.mDisabledSystemUiVisibility;
+            WindowManager.LayoutParams params = mWindowAttributes;
             if (attachInfo.mKeepScreenOn != oldScreenOn
-                    || attachInfo.mSystemUiVisibility != oldVis
-                    || attachInfo.mHasSystemUiListeners != oldHasSystemUiListeners) {
-                WindowManager.LayoutParams params = mWindowAttributes;
+                    || attachInfo.mSystemUiVisibility != params.subtreeSystemUiVisibility
+                    || attachInfo.mHasSystemUiListeners != params.hasSystemUiListeners) {
                 applyKeepScreenOnFlag(params);
                 params.subtreeSystemUiVisibility = attachInfo.mSystemUiVisibility;
                 params.hasSystemUiListeners = attachInfo.mHasSystemUiListeners;
@@ -1127,6 +1114,7 @@
         if (host == null || !mAdded)
             return;
 
+        mIsInTraversal = true;
         mWillDrawSoon = true;
         boolean windowSizeMayChange = false;
         boolean newSurface = false;
@@ -1171,9 +1159,8 @@
 
             if (lp.type == WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL) {
                 // NOTE -- system code, won't try to do compat mode.
-                Display disp = WindowManagerImpl.getDefault().getDefaultDisplay();
                 Point size = new Point();
-                disp.getRealSize(size);
+                mDisplay.getRealSize(size);
                 desiredWindowWidth = size.x;
                 desiredWindowHeight = size.y;
             } else {
@@ -1198,6 +1185,10 @@
             viewVisibilityChanged = false;
             mLastConfiguration.setTo(host.getResources().getConfiguration());
             mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
+            // Set the layout direction if it has not been set before (inherit is the default)
+            if (mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
+                host.setLayoutDirection(mLastConfiguration.getLayoutDirection());
+            }
             host.dispatchAttachedToWindow(attachInfo, 0);
             mFitSystemWindowsInsets.set(mAttachInfo.mContentInsets);
             host.fitSystemWindows(mFitSystemWindowsInsets);
@@ -1258,9 +1249,8 @@
 
                     if (lp.type == WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL) {
                         // NOTE -- system code, won't try to do compat mode.
-                        Display disp = WindowManagerImpl.getDefault().getDefaultDisplay();
                         Point size = new Point();
-                        disp.getRealSize(size);
+                        mDisplay.getRealSize(size);
                         desiredWindowWidth = size.x;
                         desiredWindowHeight = size.y;
                     } else {
@@ -1310,7 +1300,7 @@
             }
         }
 
-        if (params != null && (host.mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) != 0) {
+        if (params != null && (host.mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
             if (!PixelFormat.formatHasAlpha(params.format)) {
                 params.format = PixelFormat.TRANSLUCENT;
             }
@@ -1425,12 +1415,11 @@
                                     mResizeBuffer.getHeight() != mHeight) {
                                 mResizeBuffer.resize(mWidth, mHeight);
                             }
+                            // TODO: should handle create/resize failure
                             layerCanvas = mResizeBuffer.start(hwRendererCanvas);
                             layerCanvas.setViewport(mWidth, mHeight);
                             layerCanvas.onPreDraw(null);
                             final int restoreCount = layerCanvas.save();
-                            
-                            layerCanvas.drawColor(0xff000000, PorterDuff.Mode.SRC);
 
                             int yoff;
                             final boolean scrolling = mScroller != null
@@ -1447,7 +1436,13 @@
                                 mTranslator.translateCanvas(layerCanvas);
                             }
 
-                            mView.draw(layerCanvas);
+                            DisplayList displayList = mView.mDisplayList;
+                            if (displayList != null) {
+                                layerCanvas.drawDisplayList(displayList, null,
+                                        DisplayList.FLAG_CLIP_CHILDREN);
+                            } else {
+                                mView.draw(layerCanvas);
+                            }
 
                             drawAccessibilityFocusedDrawableIfNeeded(layerCanvas);
 
@@ -1504,11 +1499,13 @@
 
                         if (mAttachInfo.mHardwareRenderer != null) {
                             try {
-                                hwInitialized = mAttachInfo.mHardwareRenderer.initialize(mHolder);
+                                hwInitialized = mAttachInfo.mHardwareRenderer.initialize(
+                                        mHolder.getSurface());
                             } catch (Surface.OutOfResourcesException e) {
                                 Log.e(TAG, "OutOfResourcesException initializing HW surface", e);
                                 try {
-                                    if (!sWindowSession.outOfMemory(mWindow)) {
+                                    if (!mWindowSession.outOfMemory(mWindow) &&
+                                            Process.myUid() != Process.SYSTEM_UID) {
                                         Slog.w(TAG, "No processes killed for memory; killing self");
                                         Process.killProcess(Process.myPid());
                                     }
@@ -1537,11 +1534,11 @@
                         mSurfaceHolder == null && mAttachInfo.mHardwareRenderer != null) {
                     mFullRedrawNeeded = true;
                     try {
-                        mAttachInfo.mHardwareRenderer.updateSurface(mHolder);
+                        mAttachInfo.mHardwareRenderer.updateSurface(mHolder.getSurface());
                     } catch (Surface.OutOfResourcesException e) {
                         Log.e(TAG, "OutOfResourcesException updating HW surface", e);
                         try {
-                            if (!sWindowSession.outOfMemory(mWindow)) {
+                            if (!mWindowSession.outOfMemory(mWindow)) {
                                 Slog.w(TAG, "No processes killed for memory; killing self");
                                 Process.killProcess(Process.myPid());
                             }
@@ -1628,14 +1625,15 @@
                         mHeight != mAttachInfo.mHardwareRenderer.getHeight()) {
                     mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight);
                     if (!hwInitialized) {
-                        mAttachInfo.mHardwareRenderer.invalidate(mHolder);
+                        mAttachInfo.mHardwareRenderer.invalidate(mHolder.getSurface());
+                        mFullRedrawNeeded = true;
                     }
                 }
             }
 
             if (!mStopped) {
                 boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
-                        (relayoutResult&WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
+                        (relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
                 if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
                         || mHeight != host.getMeasuredHeight() || contentInsetsChanged) {
                     int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
@@ -1680,6 +1678,30 @@
                     layoutRequested = true;
                 }
             }
+        } else {
+            // Not the first pass and no window/insets/visibility change but the window
+            // may have moved and we need check that and if so to update the left and right
+            // in the attach info. We translate only the window frame since on window move
+            // the window manager tells us only for the new frame but the insets are the
+            // same and we do not want to translate them more than once.
+
+            // TODO: Well, we are checking whether the frame has changed similarly
+            // to how this is done for the insets. This is however incorrect since
+            // the insets and the frame are translated. For example, the old frame
+            // was (1, 1 - 1, 1) and was translated to say (2, 2 - 2, 2), now the new
+            // reported frame is (2, 2 - 2, 2) which implies no change but this is not
+            // true since we are comparing a not translated value to a translated one.
+            // This scenario is rare but we may want to fix that.
+
+            final boolean windowMoved = (attachInfo.mWindowLeft != frame.left
+                    || attachInfo.mWindowTop != frame.top);
+            if (windowMoved) {
+                if (mTranslator != null) {
+                    mTranslator.translateRectInScreenToAppWinFrame(frame);
+                }
+                attachInfo.mWindowLeft = frame.left;
+                attachInfo.mWindowTop = frame.top;
+            }
         }
 
         final boolean didLayout = layoutRequested && !mStopped;
@@ -1691,7 +1713,7 @@
             // By this point all views have been sized and positionned
             // We can compute the transparent area
 
-            if ((host.mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) != 0) {
+            if ((host.mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
                 // start out transparent
                 // TODO: AVOID THAT CALL BY CACHING THE RESULT?
                 host.getLocationInWindow(mTmpLocation);
@@ -1708,7 +1730,7 @@
                     mPreviousTransparentRegion.set(mTransparentRegion);
                     // reconfigure window manager
                     try {
-                        sWindowSession.setTransparentRegion(mWindow, mTransparentRegion);
+                        mWindowSession.setTransparentRegion(mWindow, mTransparentRegion);
                     } catch (RemoteException e) {
                     }
                 }
@@ -1757,7 +1779,7 @@
                 }
 
                 try {
-                    sWindowSession.setInsets(mWindow, insets.mTouchableInsets,
+                    mWindowSession.setInsets(mWindow, insets.mTouchableInsets,
                             contentInsets, visibleInsets, touchableRegion);
                 } catch (RemoteException e) {
                 }
@@ -1782,7 +1804,7 @@
                             + mRealFocusedView);
                 }
             }
-            if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_ANIMATING) != 0) {
+            if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_ANIMATING) != 0) {
                 // The first time we relayout the window, if the system is
                 // doing window animations, we want to hold of on any future
                 // draws until the animation is done.
@@ -1813,7 +1835,7 @@
         }
 
         // Remember if we must report the next draw.
-        if ((relayoutResult & WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
+        if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
             mReportNextDraw = true;
         }
 
@@ -1842,6 +1864,8 @@
                 mPendingTransitions.clear();
             }
         }
+
+        mIsInTraversal = false;
     }
 
     private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
@@ -1875,7 +1899,7 @@
         // the test below should not fail unless someone is messing with us
         checkThread();
         if (mView == child) {
-            mView.mPrivateFlags |= View.REQUEST_TRANSPARENT_REGIONS;
+            mView.mPrivateFlags |= View.PFLAG_REQUEST_TRANSPARENT_REGIONS;
             // Need to make sure we re-evaluate the window attributes next
             // time around, to ensure the window has the correct format.
             mWindowAttributesChanged = true;
@@ -2043,7 +2067,7 @@
                 }
             }
             try {
-                sWindowSession.finishDrawing(mWindow);
+                mWindowSession.finishDrawing(mWindow);
             } catch (RemoteException e) {
             }
         }
@@ -2199,7 +2223,7 @@
         } catch (Surface.OutOfResourcesException e) {
             Log.e(TAG, "OutOfResourcesException locking surface", e);
             try {
-                if (!sWindowSession.outOfMemory(mWindow)) {
+                if (!mWindowSession.outOfMemory(mWindow)) {
                     Slog.w(TAG, "No processes killed for memory; killing self");
                     Process.killProcess(Process.myPid());
                 }
@@ -2238,7 +2262,7 @@
             dirty.setEmpty();
             mIsAnimating = false;
             attachInfo.mDrawingTime = SystemClock.uptimeMillis();
-            mView.mPrivateFlags |= View.DRAWN;
+            mView.mPrivateFlags |= View.PFLAG_DRAWN;
 
             if (DEBUG_DRAW) {
                 Context cxt = mView.getContext();
@@ -2251,8 +2275,7 @@
                 if (mTranslator != null) {
                     mTranslator.translateCanvas(canvas);
                 }
-                canvas.setScreenDensity(scalingRequired
-                        ? DisplayMetrics.DENSITY_DEVICE : 0);
+                canvas.setScreenDensity(scalingRequired ? mNoncompatDensity : 0);
                 attachInfo.mSetIgnoreDirtyState = false;
 
                 mView.draw(canvas);
@@ -2281,14 +2304,6 @@
         return true;
     }
 
-    @Override
-    public View findViewToTakeAccessibilityFocusFromHover(View child, View descendant) {
-        if (descendant.includeForAccessibility()) {
-            return descendant;
-        }
-        return null;
-    }
-
     /**
      * We want to draw a highlight around the current accessibility focused.
      * Since adding a style for all possible view is not a viable option we
@@ -2315,18 +2330,15 @@
             mAccessibilityFocusedHost.getAccessibilityNodeProvider();
         Rect bounds = mView.mAttachInfo.mTmpInvalRect;
         if (provider == null) {
-            mAccessibilityFocusedHost.getDrawingRect(bounds);
-            if (mView instanceof ViewGroup) {
-                ViewGroup viewGroup = (ViewGroup) mView;
-                viewGroup.offsetDescendantRectToMyCoords(mAccessibilityFocusedHost, bounds);
-            }
+            mAccessibilityFocusedHost.getBoundsOnScreen(bounds);
         } else {
             if (mAccessibilityFocusedVirtualView == null) {
                 return;
             }
             mAccessibilityFocusedVirtualView.getBoundsInScreen(bounds);
-            bounds.offset(-mAttachInfo.mWindowLeft, -mAttachInfo.mWindowTop);
         }
+        bounds.offset(-mAttachInfo.mWindowLeft, -mAttachInfo.mWindowTop);
+        bounds.intersect(0, 0, mAttachInfo.mViewRootImpl.mWidth, mAttachInfo.mViewRootImpl.mHeight);
         drawable.setBounds(bounds);
         drawable.draw(canvas);
     }
@@ -2637,7 +2649,7 @@
             mInputEventReceiver = null;
         }
         try {
-            sWindowSession.remove(mWindow);
+            mWindowSession.remove(mWindow);
         } catch (RemoteException e) {
         }
         
@@ -2660,7 +2672,7 @@
         CompatibilityInfo ci = mCompatibilityInfo.getIfNeeded();
         if (ci != null) {
             config = new Configuration(config);
-            ci.applyToConfiguration(config);
+            ci.applyToConfiguration(mNoncompatDensity, config);
         }
 
         synchronized (sConfigCallbacks) {
@@ -2671,10 +2683,16 @@
         if (mView != null) {
             // At this point the resources have been updated to
             // have the most recent config, whatever that is.  Use
-            // the on in them which may be newer.
+            // the one in them which may be newer.
             config = mView.getResources().getConfiguration();
             if (force || mLastConfiguration.diff(config) != 0) {
+                final int lastLayoutDirection = mLastConfiguration.getLayoutDirection();
+                final int currentLayoutDirection = config.getLayoutDirection();
                 mLastConfiguration.setTo(config);
+                if (lastLayoutDirection != currentLayoutDirection &&
+                        mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
+                    mView.setLayoutDirection(currentLayoutDirection);
+                }
                 mView.dispatchConfigurationChanged(config);
             }
         }
@@ -2727,6 +2745,7 @@
     private final static int MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST = 22;
     private final static int MSG_DISPATCH_DONE_ANIMATING = 23;
     private final static int MSG_INVALIDATE_WORLD = 24;
+    private final static int MSG_WINDOW_MOVED = 25;
 
     final class ViewRootHandler extends Handler {
         @Override
@@ -2778,6 +2797,8 @@
                     return "MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST";
                 case MSG_DISPATCH_DONE_ANIMATING:
                     return "MSG_DISPATCH_DONE_ANIMATING";
+                case MSG_WINDOW_MOVED:
+                    return "MSG_WINDOW_MOVED";
             }
             return super.getMessageName(message);
         }
@@ -2806,28 +2827,31 @@
             case MSG_DISPATCH_GET_NEW_SURFACE:
                 handleGetNewSurface();
                 break;
-            case MSG_RESIZED:
-                ResizedInfo ri = (ResizedInfo)msg.obj;
-
-                if (mWinFrame.width() == msg.arg1 && mWinFrame.height() == msg.arg2
-                        && mPendingContentInsets.equals(ri.contentInsets)
-                        && mPendingVisibleInsets.equals(ri.visibleInsets)
-                        && ((ResizedInfo)msg.obj).newConfig == null) {
+            case MSG_RESIZED: {
+                // Recycled in the fall through...
+                SomeArgs args = (SomeArgs) msg.obj;
+                if (mWinFrame.equals(args.arg1)
+                        && mPendingContentInsets.equals(args.arg2)
+                        && mPendingVisibleInsets.equals(args.arg3)
+                        && args.arg4 == null) {
                     break;
                 }
-                // fall through...
+                } // fall through...
             case MSG_RESIZED_REPORT:
                 if (mAdded) {
-                    Configuration config = ((ResizedInfo)msg.obj).newConfig;
+                    SomeArgs args = (SomeArgs) msg.obj;
+
+                    Configuration config = (Configuration) args.arg4;
                     if (config != null) {
                         updateConfiguration(config, false);
                     }
-                    mWinFrame.left = 0;
-                    mWinFrame.right = msg.arg1;
-                    mWinFrame.top = 0;
-                    mWinFrame.bottom = msg.arg2;
-                    mPendingContentInsets.set(((ResizedInfo)msg.obj).contentInsets);
-                    mPendingVisibleInsets.set(((ResizedInfo)msg.obj).visibleInsets);
+
+                    mWinFrame.set((Rect) args.arg1);
+                    mPendingContentInsets.set((Rect) args.arg2);
+                    mPendingVisibleInsets.set((Rect) args.arg3);
+
+                    args.recycle();
+
                     if (msg.what == MSG_RESIZED_REPORT) {
                         mReportNextDraw = true;
                     }
@@ -2835,6 +2859,24 @@
                     if (mView != null) {
                         forceLayout(mView);
                     }
+
+                    requestLayout();
+                }
+                break;
+            case MSG_WINDOW_MOVED:
+                if (mAdded) {
+                    final int w = mWinFrame.width();
+                    final int h = mWinFrame.height();
+                    final int l = msg.arg1;
+                    final int t = msg.arg2;
+                    mWinFrame.left = l;
+                    mWinFrame.right = l + w;
+                    mWinFrame.top = t;
+                    mWinFrame.bottom = t + h;
+
+                    if (mView != null) {
+                        forceLayout(mView);
+                    }
                     requestLayout();
                 }
                 break;
@@ -2853,12 +2895,14 @@
                                 mSurface != null && mSurface.isValid()) {
                             mFullRedrawNeeded = true;
                             try {
-                                mAttachInfo.mHardwareRenderer.initializeIfNeeded(mWidth, mHeight,
-                                        mHolder);
+                                if (mAttachInfo.mHardwareRenderer.initializeIfNeeded(
+                                        mWidth, mHeight, mHolder.getSurface())) {
+                                    mFullRedrawNeeded = true;
+                                }
                             } catch (Surface.OutOfResourcesException e) {
                                 Log.e(TAG, "OutOfResourcesException locking surface", e);
                                 try {
-                                    if (!sWindowSession.outOfMemory(mWindow)) {
+                                    if (!mWindowSession.outOfMemory(mWindow)) {
                                         Slog.w(TAG, "No processes killed for memory; killing self");
                                         Process.killProcess(Process.myPid());
                                     }
@@ -2979,7 +3023,9 @@
                 handleDispatchDoneAnimating();
             } break;
             case MSG_INVALIDATE_WORLD: {
-                invalidateWorld(mView);
+                if (mView != null) {
+                    invalidateWorld(mView);
+                }
             } break;
             }
         }
@@ -3003,7 +3049,7 @@
 
         // tell the window manager
         try {
-            sWindowSession.setInTouchMode(inTouchMode);
+            mWindowSession.setInTouchMode(inTouchMode);
         } catch (RemoteException e) {
             throw new RuntimeException(e);
         }
@@ -3190,6 +3236,33 @@
             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
         }
 
+        if (mView != null && mAdded && (q.mFlags & QueuedInputEvent.FLAG_DELIVER_POST_IME) == 0) {
+            if (LOCAL_LOGV)
+                Log.v(TAG, "Dispatching trackball " + event + " to " + mView);
+
+            // Dispatch to the IME before propagating down the view hierarchy.
+            // The IME will eventually call back into handleImeFinishedEvent.
+            if (mLastWasImTarget) {
+                InputMethodManager imm = InputMethodManager.peekInstance();
+                if (imm != null) {
+                    final int seq = event.getSequenceNumber();
+                    if (DEBUG_IMF)
+                        Log.v(TAG, "Sending trackball event to IME: seq="
+                                + seq + " event=" + event);
+                    imm.dispatchTrackballEvent(mView.getContext(), seq, event,
+                            mInputMethodCallback);
+                    return;
+                }
+            }
+        }
+
+        // Not dispatching to IME, continue with post IME actions.
+        deliverTrackballEventPostIme(q);
+    }
+
+    private void deliverTrackballEventPostIme(QueuedInputEvent q) {
+        final MotionEvent event = (MotionEvent) q.mEvent;
+
         // If there is no view, then the event will not be handled.
         if (mView == null || !mAdded) {
             finishInputEvent(q, false);
@@ -3323,8 +3396,33 @@
             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
         }
 
-        final int source = event.getSource();
-        final boolean isJoystick = (source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0;
+        if (mView != null && mAdded && (q.mFlags & QueuedInputEvent.FLAG_DELIVER_POST_IME) == 0) {
+            if (LOCAL_LOGV)
+                Log.v(TAG, "Dispatching generic motion " + event + " to " + mView);
+
+            // Dispatch to the IME before propagating down the view hierarchy.
+            // The IME will eventually call back into handleImeFinishedEvent.
+            if (mLastWasImTarget) {
+                InputMethodManager imm = InputMethodManager.peekInstance();
+                if (imm != null) {
+                    final int seq = event.getSequenceNumber();
+                    if (DEBUG_IMF)
+                        Log.v(TAG, "Sending generic motion event to IME: seq="
+                                + seq + " event=" + event);
+                    imm.dispatchGenericMotionEvent(mView.getContext(), seq, event,
+                            mInputMethodCallback);
+                    return;
+                }
+            }
+        }
+
+        // Not dispatching to IME, continue with post IME actions.
+        deliverGenericMotionEventPostIme(q);
+    }
+
+    private void deliverGenericMotionEventPostIme(QueuedInputEvent q) {
+        final MotionEvent event = (MotionEvent) q.mEvent;
+        final boolean isJoystick = (event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0;
 
         // If there is no view, then the event will not be handled.
         if (mView == null || !mAdded) {
@@ -3345,7 +3443,8 @@
         }
 
         if (isJoystick) {
-            // Translate the joystick event into DPAD keys and try to deliver those.
+            // Translate the joystick event into DPAD keys and try to deliver
+            // those.
             updateJoystickDirection(event, true);
             finishInputEvent(q, true);
         } else {
@@ -3500,13 +3599,7 @@
             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
         }
 
-        if ((q.mFlags & QueuedInputEvent.FLAG_DELIVER_POST_IME) == 0) {
-            // If there is no view, then the event will not be handled.
-            if (mView == null || !mAdded) {
-                finishInputEvent(q, false);
-                return;
-            }
-
+        if (mView != null && mAdded && (q.mFlags & QueuedInputEvent.FLAG_DELIVER_POST_IME) == 0) {
             if (LOCAL_LOGV) Log.v(TAG, "Dispatching key " + event + " to " + mView);
 
             // Perform predispatching before the IME.
@@ -3536,15 +3629,46 @@
     void handleImeFinishedEvent(int seq, boolean handled) {
         final QueuedInputEvent q = mCurrentInputEvent;
         if (q != null && q.mEvent.getSequenceNumber() == seq) {
-            final KeyEvent event = (KeyEvent)q.mEvent;
             if (DEBUG_IMF) {
                 Log.v(TAG, "IME finished event: seq=" + seq
-                        + " handled=" + handled + " event=" + event);
+                        + " handled=" + handled + " event=" + q);
             }
             if (handled) {
                 finishInputEvent(q, true);
             } else {
-                deliverKeyEventPostIme(q);
+                if (q.mEvent instanceof KeyEvent) {
+                    KeyEvent event = (KeyEvent)q.mEvent;
+                    if (event.getAction() != KeyEvent.ACTION_UP) {
+                        // If the window doesn't currently have input focus, then drop
+                        // this event.  This could be an event that came back from the
+                        // IME dispatch but the window has lost focus in the meantime.
+                        if (!mAttachInfo.mHasWindowFocus) {
+                            Slog.w(TAG, "Dropping event due to no window focus: " + event);
+                            finishInputEvent(q, true);
+                            return;
+                        }
+                    }
+                    deliverKeyEventPostIme(q);
+                } else {
+                    MotionEvent event = (MotionEvent)q.mEvent;
+                    if (event.getAction() != MotionEvent.ACTION_CANCEL
+                            && event.getAction() != MotionEvent.ACTION_UP) {
+                        // If the window doesn't currently have input focus, then drop
+                        // this event.  This could be an event that came back from the
+                        // IME dispatch but the window has lost focus in the meantime.
+                        if (!mAttachInfo.mHasWindowFocus) {
+                            Slog.w(TAG, "Dropping event due to no window focus: " + event);
+                            finishInputEvent(q, true);
+                            return;
+                        }
+                    }
+                    final int source = q.mEvent.getSource();
+                    if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
+                        deliverTrackballEventPostIme(q);
+                    } else {
+                        deliverGenericMotionEventPostIme(q);
+                    }
+                }
             }
         } else {
             if (DEBUG_IMF) {
@@ -3717,10 +3841,10 @@
                 if (prevDragView != mCurrentDragView) {
                     try {
                         if (prevDragView != null) {
-                            sWindowSession.dragRecipientExited(mWindow);
+                            mWindowSession.dragRecipientExited(mWindow);
                         }
                         if (mCurrentDragView != null) {
-                            sWindowSession.dragRecipientEntered(mWindow);
+                            mWindowSession.dragRecipientEntered(mWindow);
                         }
                     } catch (RemoteException e) {
                         Slog.e(TAG, "Unable to note drag target change");
@@ -3732,7 +3856,7 @@
                     mDragDescription = null;
                     try {
                         Log.i(TAG, "Reporting drop result: " + result);
-                        sWindowSession.reportDropResult(mWindow, result);
+                        mWindowSession.reportDropResult(mWindow, result);
                     } catch (RemoteException e) {
                         Log.e(TAG, "Unable to report drop result");
                     }
@@ -3834,11 +3958,11 @@
                 params.type = mOrigWindowType;
             }
         }
-        int relayoutResult = sWindowSession.relayout(
+        int relayoutResult = mWindowSession.relayout(
                 mWindow, mSeq, params,
                 (int) (mView.getMeasuredWidth() * appScale + 0.5f),
                 (int) (mView.getMeasuredHeight() * appScale + 0.5f),
-                viewVisibility, insetsPending ? WindowManagerImpl.RELAYOUT_INSETS_PENDING : 0,
+                viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
                 mWinFrame, mPendingContentInsets, mPendingVisibleInsets,
                 mPendingConfiguration, mSurface);
         //Log.d(TAG, "<<<<<< BACK FROM relayout");
@@ -3895,7 +4019,7 @@
      */
     public boolean performHapticFeedback(int effectId, boolean always) {
         try {
-            return sWindowSession.performHapticFeedback(mWindow, effectId, always);
+            return mWindowSession.performHapticFeedback(mWindow, effectId, always);
         } catch (RemoteException e) {
             return false;
         }
@@ -3941,7 +4065,9 @@
     }
 
     public void die(boolean immediate) {
-        if (immediate) {
+        // Make sure we do execute immediately if we are in the middle of a traversal or the damage
+        // done by dispatchDetachedFromWindow will cause havoc on return.
+        if (immediate && !mIsInTraversal) {
             doDie();
         } else {
             if (!mIsDrawing) {
@@ -3974,8 +4100,8 @@
                         // animation info.
                         try {
                             if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
-                                    & WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
-                                sWindowSession.finishDrawing(mWindow);
+                                    & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
+                                mWindowSession.finishDrawing(mWindow);
                             }
                         } catch (RemoteException e) {
                         }
@@ -4034,26 +4160,37 @@
         mHandler.sendMessage(msg);
     }
 
-    public void dispatchResized(int w, int h, Rect contentInsets,
+    public void dispatchResized(Rect frame, Rect contentInsets,
             Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
-        if (DEBUG_LAYOUT) Log.v(TAG, "Resizing " + this + ": w=" + w
-                + " h=" + h + " contentInsets=" + contentInsets.toShortString()
+        if (DEBUG_LAYOUT) Log.v(TAG, "Resizing " + this + ": frame=" + frame.toShortString()
+                + " contentInsets=" + contentInsets.toShortString()
                 + " visibleInsets=" + visibleInsets.toShortString()
                 + " reportDraw=" + reportDraw);
-        Message msg = mHandler.obtainMessage(reportDraw ? MSG_RESIZED_REPORT :MSG_RESIZED);
+        Message msg = mHandler.obtainMessage(reportDraw ? MSG_RESIZED_REPORT : MSG_RESIZED);
         if (mTranslator != null) {
+            mTranslator.translateRectInScreenToAppWindow(frame);
             mTranslator.translateRectInScreenToAppWindow(contentInsets);
             mTranslator.translateRectInScreenToAppWindow(visibleInsets);
-            w *= mTranslator.applicationInvertedScale;
-            h *= mTranslator.applicationInvertedScale;
         }
-        msg.arg1 = w;
-        msg.arg2 = h;
-        ResizedInfo ri = new ResizedInfo();
-        ri.contentInsets = new Rect(contentInsets);
-        ri.visibleInsets = new Rect(visibleInsets);
-        ri.newConfig = newConfig;
-        msg.obj = ri;
+        SomeArgs args = SomeArgs.obtain();
+        final boolean sameProcessCall = (Binder.getCallingPid() == android.os.Process.myPid());
+        args.arg1 = sameProcessCall ? new Rect(frame) : frame;
+        args.arg2 = sameProcessCall ? new Rect(contentInsets) : contentInsets;
+        args.arg3 = sameProcessCall ? new Rect(visibleInsets) : visibleInsets;
+        args.arg4 = sameProcessCall && newConfig != null ? new Configuration(newConfig) : newConfig;
+        msg.obj = args;
+        mHandler.sendMessage(msg);
+    }
+
+    public void dispatchMoved(int newX, int newY) {
+        if (DEBUG_LAYOUT) Log.v(TAG, "Window moved " + this + ": newX=" + newX + " newY=" + newY);
+        if (mTranslator != null) {
+            PointF point = new PointF(newX, newY);
+            mTranslator.translatePointInScreenToAppWindow(point);
+            newX = (int) (point.x + 0.5);
+            newY = (int) (point.y + 0.5);
+        }
+        Message msg = mHandler.obtainMessage(MSG_WINDOW_MOVED, newX, newY);
         mHandler.sendMessage(msg);
     }
 
@@ -4615,9 +4752,19 @@
         // ViewAncestor never intercepts touch event, so this can be a no-op
     }
 
-    public boolean requestChildRectangleOnScreen(View child, Rect rectangle,
-            boolean immediate) {
-        return scrollToRectOrFocus(rectangle, immediate);
+    public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
+        final boolean scrolled = scrollToRectOrFocus(rectangle, immediate);
+        if (rectangle != null) {
+            mTempRect.set(rectangle);
+            mTempRect.offset(0, -mCurScrollY);
+            mTempRect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
+            try {
+                mWindowSession.onRectangleOnScreenRequested(mWindow, mTempRect, immediate);
+            } catch (RemoteException re) {
+                /* ignore */
+            }
+        }
+        return scrolled;
     }
 
     public void childHasTransientStateChanged(View child, boolean hasTransientState) {
@@ -4664,41 +4811,48 @@
         }
     }
     
-    static class InputMethodCallback extends IInputMethodCallback.Stub {
+    static final class InputMethodCallback implements InputMethodManager.FinishedEventCallback {
         private WeakReference<ViewRootImpl> mViewAncestor;
 
         public InputMethodCallback(ViewRootImpl viewAncestor) {
             mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
         }
 
+        @Override
         public void finishedEvent(int seq, boolean handled) {
             final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
                 viewAncestor.dispatchImeFinishedEvent(seq, handled);
             }
         }
-
-        public void sessionCreated(IInputMethodSession session) {
-            // Stub -- not for use in the client.
-        }
     }
 
     static class W extends IWindow.Stub {
         private final WeakReference<ViewRootImpl> mViewAncestor;
+        private final IWindowSession mWindowSession;
 
         W(ViewRootImpl viewAncestor) {
             mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
+            mWindowSession = viewAncestor.mWindowSession;
         }
 
-        public void resized(int w, int h, Rect contentInsets,
+        public void resized(Rect frame, Rect contentInsets,
                 Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
             final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
-                viewAncestor.dispatchResized(w, h, contentInsets,
+                viewAncestor.dispatchResized(frame, contentInsets,
                         visibleInsets, reportDraw, newConfig);
             }
         }
 
+        @Override
+        public void moved(int newX, int newY) {
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
+            if (viewAncestor != null) {
+                viewAncestor.dispatchMoved(newX, newY);
+            }
+        }
+
         public void dispatchAppVisibility(boolean visible) {
             final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
@@ -4778,7 +4932,7 @@
                 boolean sync) {
             if (sync) {
                 try {
-                    sWindowSession.wallpaperOffsetsComplete(asBinder());
+                    mWindowSession.wallpaperOffsetsComplete(asBinder());
                 } catch (RemoteException e) {
                 }
             }
@@ -4788,7 +4942,7 @@
                 int z, Bundle extras, boolean sync) {
             if (sync) {
                 try {
-                    sWindowSession.wallpaperCommandComplete(asBinder(), null);
+                    mWindowSession.wallpaperCommandComplete(asBinder(), null);
                 } catch (RemoteException e) {
                 }
             }
@@ -5186,15 +5340,13 @@
 
         @Override
         public void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId,
-                int windowLeft, int windowTop, int interactionId,
-                IAccessibilityInteractionConnectionCallback callback, int flags,
+                int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
                     .findAccessibilityNodeInfoByAccessibilityIdClientThread(accessibilityNodeId,
-                            windowLeft, windowTop, interactionId, callback, flags, interrogatingPid,
-                            interrogatingTid);
+                            interactionId, callback, flags, interrogatingPid, interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -5227,15 +5379,13 @@
 
         @Override
         public void findAccessibilityNodeInfoByViewId(long accessibilityNodeId, int viewId,
-                int windowLeft, int windowTop, int interactionId,
-                IAccessibilityInteractionConnectionCallback callback, int flags,
+                int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
                     .findAccessibilityNodeInfoByViewIdClientThread(accessibilityNodeId, viewId,
-                            windowLeft, windowTop, interactionId, callback, flags, interrogatingPid,
-                            interrogatingTid);
+                            interactionId, callback, flags, interrogatingPid, interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -5248,15 +5398,13 @@
 
         @Override
         public void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text,
-                int windowLeft, int windowTop, int interactionId,
-                IAccessibilityInteractionConnectionCallback callback, int flags,
+                int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
                     .findAccessibilityNodeInfosByTextClientThread(accessibilityNodeId, text,
-                            windowLeft, windowTop, interactionId, callback, flags, interrogatingPid,
-                            interrogatingTid);
+                            interactionId, callback, flags, interrogatingPid, interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -5268,15 +5416,14 @@
         }
 
         @Override
-        public void findFocus(long accessibilityNodeId, int focusType, int windowLeft,
-                int windowTop, int interactionId,
+        public void findFocus(long accessibilityNodeId, int focusType, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
-                    .findFocusClientThread(accessibilityNodeId, focusType, windowLeft, windowTop,
-                            interactionId, callback, flags, interrogatingPid, interrogatingTid);
+                    .findFocusClientThread(accessibilityNodeId, focusType, interactionId, callback,
+                            flags, interrogatingPid, interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -5288,15 +5435,14 @@
         }
 
         @Override
-        public void focusSearch(long accessibilityNodeId, int direction, int windowLeft,
-                int windowTop, int interactionId,
+        public void focusSearch(long accessibilityNodeId, int direction, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
-                    .focusSearchClientThread(accessibilityNodeId, direction, windowLeft, windowTop,
-                            interactionId, callback, flags, interrogatingPid, interrogatingTid);
+                    .focusSearchClientThread(accessibilityNodeId, direction, interactionId,
+                            callback, flags, interrogatingPid, interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index 1c5d436..cfcf3c0 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -32,12 +32,18 @@
  * for more information.
  */
 public final class ViewTreeObserver {
+    // Recursive listeners use CopyOnWriteArrayList
     private CopyOnWriteArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners;
-    private CopyOnWriteArrayList<OnGlobalLayoutListener> mOnGlobalLayoutListeners;
     private CopyOnWriteArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners;
-    private CopyOnWriteArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners;
-    private CopyOnWriteArrayList<OnScrollChangedListener> mOnScrollChangedListeners;
-    private ArrayList<OnPreDrawListener> mOnPreDrawListeners;
+
+    // Non-recursive listeners use CopyOnWriteArray
+    // Any listener invoked from ViewRootImpl.performTraversals() should not be recursive
+    private CopyOnWriteArray<OnGlobalLayoutListener> mOnGlobalLayoutListeners;
+    private CopyOnWriteArray<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners;
+    private CopyOnWriteArray<OnScrollChangedListener> mOnScrollChangedListeners;
+    private CopyOnWriteArray<OnPreDrawListener> mOnPreDrawListeners;
+
+    // These listeners cannot be mutated during dispatch
     private ArrayList<OnDrawListener> mOnDrawListeners;
 
     private boolean mAlive = true;
@@ -147,7 +153,7 @@
          * windows behind it should be placed.
          */
         public final Rect contentInsets = new Rect();
-        
+
         /**
          * Offsets from the frame of the window at which windows behind it
          * are visible.
@@ -166,13 +172,13 @@
          * can be touched.
          */
         public static final int TOUCHABLE_INSETS_FRAME = 0;
-        
+
         /**
          * Option for {@link #setTouchableInsets(int)}: the area inside of
          * the content insets can be touched.
          */
         public static final int TOUCHABLE_INSETS_CONTENT = 1;
-        
+
         /**
          * Option for {@link #setTouchableInsets(int)}: the area inside of
          * the visible insets can be touched.
@@ -195,7 +201,7 @@
         }
 
         int mTouchableInsets;
-        
+
         void reset() {
             contentInsets.setEmpty();
             visibleInsets.setEmpty();
@@ -231,7 +237,7 @@
             mTouchableInsets = other.mTouchableInsets;
         }
     }
-    
+
     /**
      * Interface definition for a callback to be invoked when layout has
      * completed and the client can compute its interior insets.
@@ -363,7 +369,7 @@
         checkIsAlive();
 
         if (mOnGlobalLayoutListeners == null) {
-            mOnGlobalLayoutListeners = new CopyOnWriteArrayList<OnGlobalLayoutListener>();
+            mOnGlobalLayoutListeners = new CopyOnWriteArray<OnGlobalLayoutListener>();
         }
 
         mOnGlobalLayoutListeners.add(listener);
@@ -413,7 +419,7 @@
         checkIsAlive();
 
         if (mOnPreDrawListeners == null) {
-            mOnPreDrawListeners = new ArrayList<OnPreDrawListener>();
+            mOnPreDrawListeners = new CopyOnWriteArray<OnPreDrawListener>();
         }
 
         mOnPreDrawListeners.add(listener);
@@ -485,7 +491,7 @@
         checkIsAlive();
 
         if (mOnScrollChangedListeners == null) {
-            mOnScrollChangedListeners = new CopyOnWriteArrayList<OnScrollChangedListener>();
+            mOnScrollChangedListeners = new CopyOnWriteArray<OnScrollChangedListener>();
         }
 
         mOnScrollChangedListeners.add(listener);
@@ -558,7 +564,7 @@
 
         if (mOnComputeInternalInsetsListeners == null) {
             mOnComputeInternalInsetsListeners =
-                    new CopyOnWriteArrayList<OnComputeInternalInsetsListener>();
+                    new CopyOnWriteArray<OnComputeInternalInsetsListener>();
         }
 
         mOnComputeInternalInsetsListeners.add(listener);
@@ -640,10 +646,16 @@
         // perform the dispatching. The iterator is a safe guard against listeners that
         // could mutate the list by calling the various add/remove methods. This prevents
         // the array from being modified while we iterate it.
-        final CopyOnWriteArrayList<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners;
+        final CopyOnWriteArray<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners;
         if (listeners != null && listeners.size() > 0) {
-            for (OnGlobalLayoutListener listener : listeners) {
-                listener.onGlobalLayout();
+            CopyOnWriteArray.Access<OnGlobalLayoutListener> access = listeners.start();
+            try {
+                int count = access.size();
+                for (int i = 0; i < count; i++) {
+                    access.get(i).onGlobalLayout();
+                }
+            } finally {
+                listeners.end();
             }
         }
     }
@@ -658,17 +670,17 @@
      */
     @SuppressWarnings("unchecked")
     public final boolean dispatchOnPreDraw() {
-        // NOTE: we *must* clone the listener list to perform the dispatching.
-        // The clone is a safe guard against listeners that
-        // could mutate the list by calling the various add/remove methods. This prevents
-        // the array from being modified while we process it.
         boolean cancelDraw = false;
-        if (mOnPreDrawListeners != null && mOnPreDrawListeners.size() > 0) {
-            final ArrayList<OnPreDrawListener> listeners =
-                    (ArrayList<OnPreDrawListener>) mOnPreDrawListeners.clone();
-            int numListeners = listeners.size();
-            for (int i = 0; i < numListeners; ++i) {
-                cancelDraw |= !(listeners.get(i).onPreDraw());
+        final CopyOnWriteArray<OnPreDrawListener> listeners = mOnPreDrawListeners;
+        if (listeners != null && listeners.size() > 0) {
+            CopyOnWriteArray.Access<OnPreDrawListener> access = listeners.start();
+            try {
+                int count = access.size();
+                for (int i = 0; i < count; i++) {
+                    cancelDraw |= !(access.get(i).onPreDraw());
+                }
+            } finally {
+                listeners.end();
             }
         }
         return cancelDraw;
@@ -710,10 +722,16 @@
         // perform the dispatching. The iterator is a safe guard against listeners that
         // could mutate the list by calling the various add/remove methods. This prevents
         // the array from being modified while we iterate it.
-        final CopyOnWriteArrayList<OnScrollChangedListener> listeners = mOnScrollChangedListeners;
+        final CopyOnWriteArray<OnScrollChangedListener> listeners = mOnScrollChangedListeners;
         if (listeners != null && listeners.size() > 0) {
-            for (OnScrollChangedListener listener : listeners) {
-                listener.onScrollChanged();
+            CopyOnWriteArray.Access<OnScrollChangedListener> access = listeners.start();
+            try {
+                int count = access.size();
+                for (int i = 0; i < count; i++) {
+                    access.get(i).onScrollChanged();
+                }
+            } finally {
+                listeners.end();
             }
         }
     }
@@ -722,11 +740,11 @@
      * Returns whether there are listeners for computing internal insets.
      */
     final boolean hasComputeInternalInsetsListeners() {
-        final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners =
+        final CopyOnWriteArray<OnComputeInternalInsetsListener> listeners =
                 mOnComputeInternalInsetsListeners;
         return (listeners != null && listeners.size() > 0);
     }
-    
+
     /**
      * Calls all listeners to compute the current insets.
      */
@@ -735,12 +753,105 @@
         // perform the dispatching. The iterator is a safe guard against listeners that
         // could mutate the list by calling the various add/remove methods. This prevents
         // the array from being modified while we iterate it.
-        final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners =
+        final CopyOnWriteArray<OnComputeInternalInsetsListener> listeners =
                 mOnComputeInternalInsetsListeners;
         if (listeners != null && listeners.size() > 0) {
-            for (OnComputeInternalInsetsListener listener : listeners) {
-                listener.onComputeInternalInsets(inoutInfo);
+            CopyOnWriteArray.Access<OnComputeInternalInsetsListener> access = listeners.start();
+            try {
+                int count = access.size();
+                for (int i = 0; i < count; i++) {
+                    access.get(i).onComputeInternalInsets(inoutInfo);
+                }
+            } finally {
+                listeners.end();
             }
         }
     }
+
+    /**
+     * Copy on write array. This array is not thread safe, and only one loop can
+     * iterate over this array at any given time. This class avoids allocations
+     * until a concurrent modification happens.
+     * 
+     * Usage:
+     * 
+     * CopyOnWriteArray.Access<MyData> access = array.start();
+     * try {
+     *     for (int i = 0; i < access.size(); i++) {
+     *         MyData d = access.get(i);
+     *     }
+     * } finally {
+     *     access.end();
+     * }
+     */
+    static class CopyOnWriteArray<T> {
+        private ArrayList<T> mData = new ArrayList<T>();
+        private ArrayList<T> mDataCopy;
+
+        private final Access<T> mAccess = new Access<T>();
+
+        private boolean mStart;
+
+        static class Access<T> {
+            private ArrayList<T> mData;
+            private int mSize;
+
+            T get(int index) {
+                return mData.get(index);
+            }
+
+            int size() {
+                return mSize;
+            }
+        }
+
+        CopyOnWriteArray() {
+        }
+
+        private ArrayList<T> getArray() {
+            if (mStart) {
+                if (mDataCopy == null) mDataCopy = new ArrayList<T>(mData);
+                return mDataCopy;
+            }
+            return mData;
+        }
+
+        Access<T> start() {
+            if (mStart) throw new IllegalStateException("Iteration already started");
+            mStart = true;
+            mDataCopy = null;
+            mAccess.mData = mData;
+            mAccess.mSize = mData.size();
+            return mAccess;
+        }
+
+        void end() {
+            if (!mStart) throw new IllegalStateException("Iteration not started");
+            mStart = false;
+            if (mDataCopy != null) {
+                mData = mDataCopy;
+            }
+            mDataCopy = null;
+        }
+
+        int size() {
+            return getArray().size();
+        }
+
+        void add(T item) {
+            getArray().add(item);
+        }
+
+        void addAll(CopyOnWriteArray<T> array) {
+            getArray().addAll(array.mData);
+        }
+
+        void remove(T item) {
+            getArray().remove(item);
+        }
+
+        void clear() {
+            getArray().clear();
+        }
+    }
 }
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index cf9bcdd..d7c7f46 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.R;
 
+import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.DialogInterface.OnDismissListener;
 import android.content.BroadcastReceiver;
@@ -92,6 +93,7 @@
     private static final int MSG_REMOTE_VOLUME_CHANGED = 8;
     private static final int MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN = 9;
     private static final int MSG_SLIDER_VISIBILITY_CHANGED = 10;
+    private static final int MSG_DISPLAY_SAFE_VOLUME_WARNING = 11;
 
     // Pseudo stream type for master volume
     private static final int STREAM_MASTER = -100;
@@ -104,6 +106,9 @@
     private boolean mShowCombinedVolumes;
     private boolean mVoiceCapable;
 
+    // True if we want to play tones on the system stream when the master stream is specified.
+    private final boolean mPlayMasterStreamTones;
+
     /** Dialog containing all the sliders */
     private final Dialog mDialog;
     /** Dialog's content view */
@@ -208,6 +213,38 @@
     private ToneGenerator mToneGenerators[];
     private Vibrator mVibrator;
 
+    private static AlertDialog sConfirmSafeVolumeDialog;
+    private static Object sConfirmSafeVolumeLock = new Object();
+
+    private static class WarningDialogReceiver extends BroadcastReceiver
+            implements DialogInterface.OnDismissListener {
+        private Context mContext;
+        private Dialog mDialog;
+
+        WarningDialogReceiver(Context context, Dialog dialog) {
+            mContext = context;
+            mDialog = dialog;
+            IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+            context.registerReceiver(this, filter);
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            mDialog.cancel();
+            synchronized (sConfirmSafeVolumeLock) {
+                sConfirmSafeVolumeDialog = null;
+            }
+        }
+
+        public void onDismiss(DialogInterface unused) {
+            mContext.unregisterReceiver(this);
+            synchronized (sConfirmSafeVolumeLock) {
+                sConfirmSafeVolumeDialog = null;
+            }
+        }
+    }
+
+
     public VolumePanel(final Context context, AudioService volumeService) {
         mContext = context;
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
@@ -282,6 +319,13 @@
             mMoreButton.setOnClickListener(this);
         }
 
+        boolean masterVolumeOnly = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_useMasterVolume);
+        boolean masterVolumeKeySounds = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_useVolumeKeySounds);
+
+        mPlayMasterStreamTones = masterVolumeOnly && masterVolumeKeySounds;
+
         listenToRingerMode();
     }
 
@@ -518,6 +562,11 @@
         postMuteChanged(STREAM_MASTER, flags);
     }
 
+    public void postDisplaySafeVolumeWarning() {
+        if (hasMessages(MSG_DISPLAY_SAFE_VOLUME_WARNING)) return;
+        obtainMessage(MSG_DISPLAY_SAFE_VOLUME_WARNING, 0, 0).sendToTarget();
+    }
+
     /**
      * Override this if you have other work to do when the volume changes (for
      * example, vibrating, playing a sound, etc.). Make sure to call through to
@@ -650,9 +699,12 @@
             if (sc.seekbarView.getMax() != max) {
                 sc.seekbarView.setMax(max);
             }
+
             sc.seekbarView.setProgress(index);
-            if (streamType != mAudioManager.getMasterStreamType()
-                    && streamType != AudioService.STREAM_REMOTE_MUSIC && isMuted(streamType)) {
+            if (((flags & AudioManager.FLAG_FIXED_VOLUME) != 0) ||
+                    (streamType != mAudioManager.getMasterStreamType() &&
+                     streamType != AudioService.STREAM_REMOTE_MUSIC &&
+                     isMuted(streamType))) {
                 sc.seekbarView.setEnabled(false);
             } else {
                 sc.seekbarView.setEnabled(true);
@@ -786,11 +838,46 @@
         }
     }
 
+    protected void onDisplaySafeVolumeWarning() {
+        synchronized (sConfirmSafeVolumeLock) {
+            if (sConfirmSafeVolumeDialog != null) {
+                return;
+            }
+            sConfirmSafeVolumeDialog = new AlertDialog.Builder(mContext)
+                    .setMessage(com.android.internal.R.string.safe_media_volume_warning)
+                    .setPositiveButton(com.android.internal.R.string.yes,
+                                        new DialogInterface.OnClickListener() {
+                        public void onClick(DialogInterface dialog, int which) {
+                            mAudioService.disableSafeMediaVolume();
+                        }
+                    })
+                    .setNegativeButton(com.android.internal.R.string.no, null)
+                    .setIconAttribute(android.R.attr.alertDialogIcon)
+                    .create();
+            final WarningDialogReceiver warning = new WarningDialogReceiver(mContext,
+                    sConfirmSafeVolumeDialog);
+
+            sConfirmSafeVolumeDialog.setOnDismissListener(warning);
+            sConfirmSafeVolumeDialog.getWindow().setType(
+                                                    WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+            sConfirmSafeVolumeDialog.show();
+        }
+    }
+
     /**
      * Lock on this VolumePanel instance as long as you use the returned ToneGenerator.
      */
     private ToneGenerator getOrCreateToneGenerator(int streamType) {
-        if (streamType == STREAM_MASTER) return null;
+        if (streamType == STREAM_MASTER) {
+            // For devices that use the master volume setting only but still want to
+            // play a volume-changed tone, direct the master volume pseudostream to
+            // the system stream's tone generator.
+            if (mPlayMasterStreamTones) {
+                streamType = AudioManager.STREAM_SYSTEM;
+            } else {
+                return null;
+            }
+        }
         synchronized (this) {
             if (mToneGenerators[streamType] == null) {
                 try {
@@ -891,6 +978,10 @@
             case MSG_SLIDER_VISIBILITY_CHANGED:
                 onSliderVisibilityChanged(msg.arg1, msg.arg2);
                 break;
+
+            case MSG_DISPLAY_SAFE_VOLUME_WARNING:
+                onDisplaySafeVolumeWarning();
+                break;
         }
     }
 
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index b0e90db..06974d3 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -16,9 +16,7 @@
 
 package android.view;
 
-import android.app.Application;
 import android.content.Context;
-import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.PixelFormat;
@@ -27,7 +25,6 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.SystemProperties;
-import android.util.Slog;
 import android.view.accessibility.AccessibilityEvent;
 
 /**
@@ -92,6 +89,13 @@
      * If overlay is enabled, the action mode UI will be allowed to cover existing window content.
      */
     public static final int FEATURE_ACTION_MODE_OVERLAY = 10;
+
+    /**
+     * Max value used as a feature ID
+     * @hide
+     */
+    public static final int FEATURE_MAX = FEATURE_ACTION_MODE_OVERLAY;
+
     /** Flag for setting the progress bar's visibility to VISIBLE */
     public static final int PROGRESS_VISIBILITY_ON = -1;
     /** Flag for setting the progress bar's visibility to GONE */
@@ -119,6 +123,8 @@
      */
     public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content;
 
+    private static final String PROPERTY_HARDWARE_UI = "persist.sys.ui.hw";
+
     private final Context mContext;
     
     private TypedArray mWindowStyle;
@@ -126,6 +132,7 @@
     private WindowManager mWindowManager;
     private IBinder mAppToken;
     private String mAppName;
+    private boolean mHardwareAccelerated;
     private Window mContainer;
     private Window mActiveChild;
     private boolean mIsActive = false;
@@ -454,7 +461,7 @@
      * display panels.  This is <em>not</em> used for displaying the
      * Window itself -- that must be done by the client.
      *
-     * @param wm The ViewManager for adding new windows.
+     * @param wm The window manager for adding new windows.
      */
     public void setWindowManager(WindowManager wm, IBinder appToken, String appName) {
         setWindowManager(wm, appToken, appName, false);
@@ -465,86 +472,64 @@
      * display panels.  This is <em>not</em> used for displaying the
      * Window itself -- that must be done by the client.
      *
-     * @param wm The ViewManager for adding new windows.
+     * @param wm The window manager for adding new windows.
      */
     public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
             boolean hardwareAccelerated) {
         mAppToken = appToken;
         mAppName = appName;
+        mHardwareAccelerated = hardwareAccelerated
+                || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
         if (wm == null) {
-            wm = WindowManagerImpl.getDefault();
+            wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
         }
-        mWindowManager = new LocalWindowManager(wm, hardwareAccelerated);
+        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
     }
 
-    static CompatibilityInfoHolder getCompatInfo(Context context) {
-        Application app = (Application)context.getApplicationContext();
-        return app != null ? app.mLoadedApk.mCompatibilityInfo : new CompatibilityInfoHolder();
-    }
-
-    private class LocalWindowManager extends WindowManagerImpl.CompatModeWrapper {
-        private static final String PROPERTY_HARDWARE_UI = "persist.sys.ui.hw";
-
-        private final boolean mHardwareAccelerated;
-
-        LocalWindowManager(WindowManager wm, boolean hardwareAccelerated) {
-            super(wm, getCompatInfo(mContext));
-            mHardwareAccelerated = hardwareAccelerated ||
-                    SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
-        }
-
-        public boolean isHardwareAccelerated() {
-            return mHardwareAccelerated;
-        }
-        
-        public final void addView(View view, ViewGroup.LayoutParams params) {
-            // Let this throw an exception on a bad params.
-            WindowManager.LayoutParams wp = (WindowManager.LayoutParams)params;
-            CharSequence curTitle = wp.getTitle();
-            if (wp.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
-                wp.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
-                if (wp.token == null) {
-                    View decor = peekDecorView();
-                    if (decor != null) {
-                        wp.token = decor.getWindowToken();
-                    }
+    void adjustLayoutParamsForSubWindow(WindowManager.LayoutParams wp) {
+        CharSequence curTitle = wp.getTitle();
+        if (wp.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
+            wp.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+            if (wp.token == null) {
+                View decor = peekDecorView();
+                if (decor != null) {
+                    wp.token = decor.getWindowToken();
                 }
-                if (curTitle == null || curTitle.length() == 0) {
-                    String title;
-                    if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA) {
-                        title="Media";
-                    } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY) {
-                        title="MediaOvr";
-                    } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
-                        title="Panel";
-                    } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL) {
-                        title="SubPanel";
-                    } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG) {
-                        title="AtchDlg";
-                    } else {
-                        title=Integer.toString(wp.type);
-                    }
-                    if (mAppName != null) {
-                        title += ":" + mAppName;
-                    }
-                    wp.setTitle(title);
-                }
-            } else {
-                if (wp.token == null) {
-                    wp.token = mContainer == null ? mAppToken : mContainer.mAppToken;
-                }
-                if ((curTitle == null || curTitle.length() == 0)
-                        && mAppName != null) {
-                    wp.setTitle(mAppName);
-                }
-           }
-            if (wp.packageName == null) {
-                wp.packageName = mContext.getPackageName();
             }
-            if (mHardwareAccelerated) {
-                wp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+            if (curTitle == null || curTitle.length() == 0) {
+                String title;
+                if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA) {
+                    title="Media";
+                } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY) {
+                    title="MediaOvr";
+                } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+                    title="Panel";
+                } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL) {
+                    title="SubPanel";
+                } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG) {
+                    title="AtchDlg";
+                } else {
+                    title=Integer.toString(wp.type);
+                }
+                if (mAppName != null) {
+                    title += ":" + mAppName;
+                }
+                wp.setTitle(title);
             }
-            super.addView(view, params);
+        } else {
+            if (wp.token == null) {
+                wp.token = mContainer == null ? mAppToken : mContainer.mAppToken;
+            }
+            if ((curTitle == null || curTitle.length() == 0)
+                    && mAppName != null) {
+                wp.setTitle(mAppName);
+            }
+        }
+        if (wp.packageName == null) {
+            wp.packageName = mContext.getPackageName();
+        }
+        if (mHardwareAccelerated) {
+            wp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
         }
     }
 
@@ -718,6 +703,7 @@
      * per {@link #setFlags}.
      * @param flags The flag bits to be set.
      * @see #setFlags
+     * @see #clearFlags
      */
     public void addFlags(int flags) {
         setFlags(flags, flags);
@@ -728,6 +714,7 @@
      * per {@link #setFlags}.
      * @param flags The flag bits to be cleared.
      * @see #setFlags
+     * @see #addFlags
      */
     public void clearFlags(int flags) {
         setFlags(0, flags);
@@ -749,6 +736,8 @@
      *
      * @param flags The new window flags (see WindowManager.LayoutParams).
      * @param mask Which of the window flag bits to modify.
+     * @see #addFlags
+     * @see #clearFlags
      */
     public void setFlags(int flags, int mask) {
         final WindowManager.LayoutParams attrs = getAttributes();
diff --git a/core/java/android/view/WindowInfo.aidl b/core/java/android/view/WindowInfo.aidl
new file mode 100644
index 0000000..23e927a
--- /dev/null
+++ b/core/java/android/view/WindowInfo.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.view;
+
+parcelable WindowInfo;
diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java
new file mode 100644
index 0000000..7d16e14
--- /dev/null
+++ b/core/java/android/view/WindowInfo.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.graphics.Rect;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Information the state of a window.
+ *
+ * @hide
+ */
+public class WindowInfo implements Parcelable {
+
+    private static final int MAX_POOL_SIZE = 20;
+
+    private static int UNDEFINED = -1;
+
+    private static Object sPoolLock = new Object();
+    private static WindowInfo sPool;
+    private static int sPoolSize;
+
+    private WindowInfo mNext;
+    private boolean mInPool;
+
+    public IBinder token;
+
+    public final Rect frame = new Rect();
+
+    public final Rect touchableRegion = new Rect();
+
+    public int type = UNDEFINED;
+
+    public float compatibilityScale = UNDEFINED;
+
+    public boolean visible;
+
+    public int displayId = UNDEFINED;
+
+    public int layer = UNDEFINED;
+
+    private WindowInfo() {
+        /* do nothing - reduce visibility */
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeStrongBinder(token);
+        parcel.writeParcelable(frame, 0);
+        parcel.writeParcelable(touchableRegion, 0);
+        parcel.writeInt(type);
+        parcel.writeFloat(compatibilityScale);
+        parcel.writeInt(visible ? 1 : 0);
+        parcel.writeInt(displayId);
+        parcel.writeInt(layer);
+        recycle();
+    }
+
+    private void initFromParcel(Parcel parcel) {
+        token = parcel.readStrongBinder();
+        frame.set((Rect) parcel.readParcelable(null));
+        touchableRegion.set((Rect) parcel.readParcelable(null));
+        type = parcel.readInt();
+        compatibilityScale = parcel.readFloat();
+        visible = (parcel.readInt() == 1);
+        displayId = parcel.readInt();
+        layer = parcel.readInt();
+    }
+
+    public static WindowInfo obtain(WindowInfo other) {
+        WindowInfo info = obtain();
+        info.token = other.token;
+        info.frame.set(other.frame);
+        info.touchableRegion.set(other.touchableRegion);
+        info.type = other.type;
+        info.compatibilityScale = other.compatibilityScale;
+        info.visible = other.visible;
+        info.displayId = other.displayId;
+        info.layer = other.layer;
+        return info;
+    }
+
+    public static WindowInfo obtain() {
+        synchronized (sPoolLock) {
+            if (sPoolSize > 0) {
+                WindowInfo info = sPool;
+                sPool = info.mNext;
+                info.mNext = null;
+                info.mInPool = false;
+                sPoolSize--;
+                return info;
+            } else {
+                return new WindowInfo();
+            }
+        }
+    }
+
+    public void recycle() {
+        if (mInPool) {
+            throw new IllegalStateException("Already recycled.");
+        }
+        clear();
+        synchronized (sPoolLock) {
+            if (sPoolSize < MAX_POOL_SIZE) {
+                mNext = sPool;
+                sPool = this;
+                mInPool = true;
+                sPoolSize++;
+            }
+        }
+    }
+
+    private void clear() {
+        token = null;
+        frame.setEmpty();
+        touchableRegion.setEmpty();
+        type = UNDEFINED;
+        compatibilityScale = UNDEFINED;
+        visible = false;
+        displayId = UNDEFINED;
+        layer = UNDEFINED;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("Window [token:").append((token != null) ? token.hashCode() : null);
+        builder.append(", displayId:").append(displayId);
+        builder.append(", type:").append(type);
+        builder.append(", visible:").append(visible);
+        builder.append(", layer:").append(layer);
+        builder.append(", compatibilityScale:").append(compatibilityScale);
+        builder.append(", frame:").append(frame);
+        builder.append(", touchableRegion:").append(touchableRegion);
+        builder.append("]");
+        return builder.toString();
+    }
+
+    /**
+     * @see Parcelable.Creator
+     */
+    public static final Parcelable.Creator<WindowInfo> CREATOR =
+            new Parcelable.Creator<WindowInfo>() {
+        public WindowInfo createFromParcel(Parcel parcel) {
+            WindowInfo info = WindowInfo.obtain();
+            info.initFromParcel(parcel);
+            return info;
+        }
+
+        public WindowInfo[] newArray(int size) {
+            return new WindowInfo[size];
+        }
+    };
+}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index d94275b..3b31ff6 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -16,6 +16,8 @@
 
 package android.view;
 
+import android.app.Presentation;
+import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.graphics.PixelFormat;
 import android.os.IBinder;
@@ -29,6 +31,17 @@
  * The interface that apps use to talk to the window manager.
  * <p>
  * Use <code>Context.getSystemService(Context.WINDOW_SERVICE)</code> to get one of these.
+ * </p><p>
+ * Each window manager instance is bound to a particular {@link Display}.
+ * To obtain a {@link WindowManager} for a different display, use
+ * {@link Context#createDisplayContext} to obtain a {@link Context} for that
+ * display, then use <code>Context.getSystemService(Context.WINDOW_SERVICE)</code>
+ * to get the WindowManager.
+ * </p><p>
+ * The simplest way to show a window on another display is to create a
+ * {@link Presentation}.  The presentation will automatically obtain a
+ * {@link WindowManager} and {@link Context} for that display.
+ * </p>
  *
  * @see android.content.Context#getSystemService
  * @see android.content.Context#WINDOW_SERVICE
@@ -49,12 +62,37 @@
     }
 
     /**
-     * Use this method to get the default Display object.
-     * 
-     * @return default Display object
+     * Exception that is thrown when calling {@link #addView} to a secondary display that cannot
+     * be found. See {@link android.app.Presentation} for more information on secondary displays.
+     */
+    public static class InvalidDisplayException extends RuntimeException {
+        public InvalidDisplayException() {
+        }
+
+        public InvalidDisplayException(String name) {
+            super(name);
+        }
+    }
+
+    /**
+     * Returns the {@link Display} upon which this {@link WindowManager} instance
+     * will create new windows.
+     * <p>
+     * Despite the name of this method, the display that is returned is not
+     * necessarily the primary display of the system (see {@link Display#DEFAULT_DISPLAY}).
+     * The returned display could instead be a secondary display that this
+     * window manager instance is managing.  Think of it as the display that
+     * this {@link WindowManager} instance uses by default.
+     * </p><p>
+     * To create windows on a different display, you need to obtain a
+     * {@link WindowManager} for that {@link Display}.  (See the {@link WindowManager}
+     * class documentation for more information.)
+     * </p>
+     *
+     * @return The display that this window manager is managing.
      */
     public Display getDefaultDisplay();
-    
+
     /**
      * Special variation of {@link #removeView} that immediately invokes
      * the given view hierarchy's {@link View#onDetachedFromWindow()
@@ -64,15 +102,7 @@
      * @param view The view to be removed.
      */
     public void removeViewImmediate(View view);
-    
-    /**
-     * Return true if this window manager is configured to request hardware
-     * accelerated windows.  This does <em>not</em> guarantee that they will
-     * actually be accelerated, since that depends on the device supporting them.
-     * @hide
-     */
-    public boolean isHardwareAccelerated();
-    
+
     public static class LayoutParams extends ViewGroup.LayoutParams
             implements Parcelable {
         /**
@@ -162,6 +192,7 @@
             @ViewDebug.IntToString(from = TYPE_APPLICATION_MEDIA, to = "TYPE_APPLICATION_MEDIA"),
             @ViewDebug.IntToString(from = TYPE_APPLICATION_SUB_PANEL, to = "TYPE_APPLICATION_SUB_PANEL"),
             @ViewDebug.IntToString(from = TYPE_APPLICATION_ATTACHED_DIALOG, to = "TYPE_APPLICATION_ATTACHED_DIALOG"),
+            @ViewDebug.IntToString(from = TYPE_APPLICATION_MEDIA_OVERLAY, to = "TYPE_APPLICATION_MEDIA_OVERLAY"),
             @ViewDebug.IntToString(from = TYPE_STATUS_BAR, to = "TYPE_STATUS_BAR"),
             @ViewDebug.IntToString(from = TYPE_SEARCH_BAR, to = "TYPE_SEARCH_BAR"),
             @ViewDebug.IntToString(from = TYPE_PHONE, to = "TYPE_PHONE"),
@@ -170,8 +201,6 @@
             @ViewDebug.IntToString(from = TYPE_TOAST, to = "TYPE_TOAST"),
             @ViewDebug.IntToString(from = TYPE_SYSTEM_OVERLAY, to = "TYPE_SYSTEM_OVERLAY"),
             @ViewDebug.IntToString(from = TYPE_PRIORITY_PHONE, to = "TYPE_PRIORITY_PHONE"),
-            @ViewDebug.IntToString(from = TYPE_STATUS_BAR_PANEL, to = "TYPE_STATUS_BAR_PANEL"),
-            @ViewDebug.IntToString(from = TYPE_STATUS_BAR_SUB_PANEL, to = "TYPE_STATUS_BAR_SUB_PANEL"),
             @ViewDebug.IntToString(from = TYPE_SYSTEM_DIALOG, to = "TYPE_SYSTEM_DIALOG"),
             @ViewDebug.IntToString(from = TYPE_KEYGUARD_DIALOG, to = "TYPE_KEYGUARD_DIALOG"),
             @ViewDebug.IntToString(from = TYPE_SYSTEM_ERROR, to = "TYPE_SYSTEM_ERROR"),
@@ -185,7 +214,12 @@
             @ViewDebug.IntToString(from = TYPE_POINTER, to = "TYPE_POINTER"),
             @ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR, to = "TYPE_NAVIGATION_BAR"),
             @ViewDebug.IntToString(from = TYPE_VOLUME_OVERLAY, to = "TYPE_VOLUME_OVERLAY"),
-            @ViewDebug.IntToString(from = TYPE_BOOT_PROGRESS, to = "TYPE_BOOT_PROGRESS")
+            @ViewDebug.IntToString(from = TYPE_BOOT_PROGRESS, to = "TYPE_BOOT_PROGRESS"),
+            @ViewDebug.IntToString(from = TYPE_HIDDEN_NAV_CONSUMER, to = "TYPE_HIDDEN_NAV_CONSUMER"),
+            @ViewDebug.IntToString(from = TYPE_DREAM, to = "TYPE_DREAM"),
+            @ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR_PANEL, to = "TYPE_NAVIGATION_BAR_PANEL"),
+            @ViewDebug.IntToString(from = TYPE_DISPLAY_OVERLAY, to = "TYPE_DISPLAY_OVERLAY"),
+            @ViewDebug.IntToString(from = TYPE_MAGNIFICATION_OVERLAY, to = "TYPE_MAGNIFICATION_OVERLAY")
         })
         public int type;
     
@@ -198,12 +232,14 @@
          * Window type: an application window that serves as the "base" window
          * of the overall application; all other application windows will
          * appear on top of it.
+         * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_BASE_APPLICATION   = 1;
         
         /**
          * Window type: a normal application window.  The {@link #token} must be
          * an Activity token identifying who the window belongs to.
+         * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_APPLICATION        = 2;
     
@@ -212,6 +248,7 @@
          * application is starting.  Not for use by applications themselves;
          * this is used by the system to display something until the
          * application can show its own windows.
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_APPLICATION_STARTING = 3;
     
@@ -277,12 +314,14 @@
          * Window type: the status bar.  There can be only one status bar
          * window; it is placed at the top of the screen, and all other
          * windows are shifted down so they are below it.
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW;
     
         /**
          * Window type: the search bar.  There can be only one search bar
          * window; it is placed at the top of the screen.
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1;
     
@@ -291,22 +330,26 @@
          * user interaction with the phone (in particular incoming calls).
          * These windows are normally placed above all applications, but behind
          * the status bar.
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2;
     
         /**
          * Window type: system window, such as low power alert. These windows
          * are always on top of application windows.
+         * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3;
         
         /**
          * Window type: keyguard window.
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4;
         
         /**
          * Window type: transient notifications.
+         * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5;
         
@@ -314,6 +357,7 @@
          * Window type: system overlay windows, which need to be displayed
          * on top of everything else.  These windows must not take input
          * focus, or they will interfere with the keyguard.
+         * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6;
         
@@ -321,22 +365,26 @@
          * Window type: priority phone UI, which needs to be displayed even if
          * the keyguard is active.  These windows must not take input
          * focus, or they will interfere with the keyguard.
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7;
         
         /**
          * Window type: panel that slides out from the status bar
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8;
     
         /**
          * Window type: dialogs that the keyguard shows
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_KEYGUARD_DIALOG    = FIRST_SYSTEM_WINDOW+9;
         
         /**
          * Window type: internal system error windows, appear on top of
          * everything they can.
+         * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_SYSTEM_ERROR       = FIRST_SYSTEM_WINDOW+10;
         
@@ -344,23 +392,27 @@
          * Window type: internal input methods windows, which appear above
          * the normal UI.  Application windows may be resized or panned to keep
          * the input focus visible while this window is displayed.
+         * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_INPUT_METHOD       = FIRST_SYSTEM_WINDOW+11;
 
         /**
          * Window type: internal input methods dialog windows, which appear above
          * the current input method window.
+         * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12;
 
         /**
          * Window type: wallpaper window, placed behind any window that wants
          * to sit on top of the wallpaper.
+         * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13;
 
         /**
          * Window type: panel that slides out from over the status bar
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+14;
 
@@ -372,6 +424,8 @@
          * This is exactly like {@link #TYPE_SYSTEM_OVERLAY} except that only the
          * system itself is allowed to create these overlays.  Applications cannot
          * obtain permission to create secure system overlays.
+         *
+         * In multiuser systems shows only on the owning user's window.
          * @hide
          */
         public static final int TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15;
@@ -379,24 +433,28 @@
         /**
          * Window type: the drag-and-drop pseudowindow.  There is only one
          * drag layer (at most), and it is placed on top of all other windows.
+         * In multiuser systems shows only on the owning user's window.
          * @hide
          */
         public static final int TYPE_DRAG               = FIRST_SYSTEM_WINDOW+16;
 
         /**
          * Window type: panel that slides out from under the status bar
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17;
 
         /**
          * Window type: (mouse) pointer
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_POINTER = FIRST_SYSTEM_WINDOW+18;
 
         /**
          * Window type: Navigation bar (when distinct from status bar)
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19;
@@ -404,6 +462,7 @@
         /**
          * Window type: The volume level overlay/dialog shown when the user
          * changes the system volume.
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20;
@@ -411,6 +470,7 @@
         /**
          * Window type: The boot progress dialog, goes on top of everything
          * in the world.
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21;
@@ -418,23 +478,56 @@
         /**
          * Window type: Fake window to consume touch events when the navigation
          * bar is hidden.
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_HIDDEN_NAV_CONSUMER = FIRST_SYSTEM_WINDOW+22;
 
         /**
          * Window type: Dreams (screen saver) window, just above keyguard.
+         * In multiuser systems shows only on the owning user's window.
          * @hide
          */
         public static final int TYPE_DREAM = FIRST_SYSTEM_WINDOW+23;
 
         /**
          * Window type: Navigation bar panel (when navigation bar is distinct from status bar)
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24;
 
         /**
+         * Window type: Behind the universe of the real windows.
+         * In multiuser systems shows on all users' windows.
+         * @hide
+         */
+        public static final int TYPE_UNIVERSE_BACKGROUND = FIRST_SYSTEM_WINDOW+25;
+
+        /**
+         * Window type: Display overlay window.  Used to simulate secondary display devices.
+         * In multiuser systems shows on all users' windows.
+         * @hide
+         */
+        public static final int TYPE_DISPLAY_OVERLAY = FIRST_SYSTEM_WINDOW+26;
+
+        /**
+         * Window type: Magnification overlay window. Used to highlight the magnified
+         * portion of a display when accessibility magnification is enabled.
+         * In multiuser systems shows on all users' windows.
+         * @hide
+         */
+        public static final int TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27;
+
+        /**
+         * Window type: Recents. Same layer as {@link #TYPE_SYSTEM_DIALOG} but only appears on
+         * one user's screen.
+         * In multiuser systems shows on all users' windows.
+         * @hide
+         */
+        public static final int TYPE_RECENTS_OVERLAY = FIRST_SYSTEM_WINDOW+28;
+
+        /**
          * End of types of system windows.
          */
         public static final int LAST_SYSTEM_WINDOW      = 2999;
@@ -530,11 +623,18 @@
         public static final int FLAG_FORCE_NOT_FULLSCREEN   = 0x00000800;
         
         /** Window flag: turn on dithering when compositing this window to
-         *  the screen. */
+         *  the screen.
+         * @deprecated This flag is no longer used. */
+        @Deprecated
         public static final int FLAG_DITHER             = 0x00001000;
         
-        /** Window flag: don't allow screen shots while this window is
-         * displayed. Maps to Surface.SECURE. */
+        /** Window flag: Treat the content of the window as secure, preventing
+         * it from appearing in screenshots or from being viewed on non-secure
+         * displays.
+         *
+         * <p>See {@link android.view.Display#FLAG_SECURE} for more details about
+         * secure surfaces and secure displays.
+         */
         public static final int FLAG_SECURE             = 0x00002000;
         
         /** Window flag: a special mode where the layout parameters are used
@@ -718,7 +818,6 @@
          * @see #FLAG_LAYOUT_NO_LIMITS
          * @see #FLAG_FULLSCREEN
          * @see #FLAG_FORCE_NOT_FULLSCREEN
-         * @see #FLAG_DITHER
          * @see #FLAG_SECURE
          * @see #FLAG_SCALED
          * @see #FLAG_IGNORE_CHEEK_PRESSES
@@ -838,6 +937,14 @@
          */
         public static final int PRIVATE_FLAG_SET_NEEDS_MENU_KEY = 0x00000008;
 
+        /** In a multiuser system if this flag is set and the owner is a system process then this
+         * window will appear on all user screens. This overrides the default behavior of window
+         * types that normally only appear on the owning user's screen. Refer to each window type
+         * to determine its default behavior.
+         *
+         * {@hide} */
+        public static final int PRIVATE_FLAG_SHOW_FOR_ALL_USERS = 0x00000010;
+
         /**
          * Control flags that are private to the platform.
          * @hide
@@ -1135,14 +1242,42 @@
         public static final int INPUT_FEATURE_NO_INPUT_CHANNEL = 0x00000002;
 
         /**
+         * When this window has focus, does not call user activity for all input events so
+         * the application will have to do it itself.  Should only be used by
+         * the keyguard and phone app.
+         * <p>
+         * Should only be used by the keyguard and phone app.
+         * </p>
+         *
+         * @hide
+         */
+        public static final int INPUT_FEATURE_DISABLE_USER_ACTIVITY = 0x00000004;
+
+        /**
          * Control special features of the input subsystem.
          *
          * @see #INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES
          * @see #INPUT_FEATURE_NO_INPUT_CHANNEL
+         * @see #INPUT_FEATURE_DISABLE_USER_ACTIVITY
          * @hide
          */
         public int inputFeatures;
 
+        /**
+         * Sets the number of milliseconds before the user activity timeout occurs
+         * when this window has focus.  A value of -1 uses the standard timeout.
+         * A value of 0 uses the minimum support display timeout.
+         * <p>
+         * This property can only be used to reduce the user specified display timeout;
+         * it can never make the timeout longer than it normally would be.
+         * </p><p>
+         * Should only be used by the keyguard and phone app.
+         * </p>
+         *
+         * @hide
+         */
+        public long userActivityTimeout = -1;
+
         public LayoutParams() {
             super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
             type = TYPE_APPLICATION;
@@ -1227,6 +1362,7 @@
             out.writeInt(subtreeSystemUiVisibility);
             out.writeInt(hasSystemUiListeners ? 1 : 0);
             out.writeInt(inputFeatures);
+            out.writeLong(userActivityTimeout);
         }
         
         public static final Parcelable.Creator<LayoutParams> CREATOR
@@ -1267,6 +1403,7 @@
             subtreeSystemUiVisibility = in.readInt();
             hasSystemUiListeners = in.readInt() != 0;
             inputFeatures = in.readInt();
+            userActivityTimeout = in.readLong();
         }
     
         @SuppressWarnings({"PointlessBitwiseExpression"})
@@ -1293,6 +1430,8 @@
         /** {@hide} */
         public static final int PRIVATE_FLAGS_CHANGED = 1<<16;
         /** {@hide} */
+        public static final int USER_ACTIVITY_TIMEOUT_CHANGED = 1<<17;
+        /** {@hide} */
         public static final int EVERYTHING_CHANGED = 0xffffffff;
 
         // internal buffer to backup/restore parameters under compatibility mode.
@@ -1414,6 +1553,11 @@
                 changes |= INPUT_FEATURES_CHANGED;
             }
 
+            if (userActivityTimeout != o.userActivityTimeout) {
+                userActivityTimeout = o.userActivityTimeout;
+                changes |= USER_ACTIVITY_TIMEOUT_CHANGED;
+            }
+
             return changes;
         }
     
@@ -1506,6 +1650,9 @@
             if (inputFeatures != 0) {
                 sb.append(" if=0x").append(Integer.toHexString(inputFeatures));
             }
+            if (userActivityTimeout >= 0) {
+                sb.append(" userActivityTimeout=").append(userActivityTimeout);
+            }
             sb.append('}');
             return sb.toString();
         }
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
new file mode 100644
index 0000000..e8945aa
--- /dev/null
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -0,0 +1,526 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.animation.ValueAnimator;
+import android.app.ActivityManager;
+import android.content.ComponentCallbacks2;
+import android.content.res.Configuration;
+import android.opengl.ManagedEGLContext;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.util.AndroidRuntimeException;
+import android.util.Log;
+import android.view.inputmethod.InputMethodManager;
+
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+
+/**
+ * Provides low-level communication with the system window manager for
+ * operations that are not associated with any particular context.
+ *
+ * This class is only used internally to implement global functions where
+ * the caller already knows the display and relevant compatibility information
+ * for the operation.  For most purposes, you should use {@link WindowManager} instead
+ * since it is bound to a context.
+ *
+ * @see WindowManagerImpl
+ * @hide
+ */
+public final class WindowManagerGlobal {
+    private static final String TAG = "WindowManager";
+
+    /**
+     * The user is navigating with keys (not the touch screen), so
+     * navigational focus should be shown.
+     */
+    public static final int RELAYOUT_RES_IN_TOUCH_MODE = 0x1;
+
+    /**
+     * This is the first time the window is being drawn,
+     * so the client must call drawingFinished() when done
+     */
+    public static final int RELAYOUT_RES_FIRST_TIME = 0x2;
+
+    /**
+     * The window manager has changed the surface from the last call.
+     */
+    public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4;
+
+    /**
+     * The window manager is currently animating.  It will call
+     * IWindow.doneAnimating() when done.
+     */
+    public static final int RELAYOUT_RES_ANIMATING = 0x8;
+
+    /**
+     * Flag for relayout: the client will be later giving
+     * internal insets; as a result, the window will not impact other window
+     * layouts until the insets are given.
+     */
+    public static final int RELAYOUT_INSETS_PENDING = 0x1;
+
+    /**
+     * Flag for relayout: the client may be currently using the current surface,
+     * so if it is to be destroyed as a part of the relayout the destroy must
+     * be deferred until later.  The client will call performDeferredDestroy()
+     * when it is okay.
+     */
+    public static final int RELAYOUT_DEFER_SURFACE_DESTROY = 0x2;
+
+    public static final int ADD_FLAG_APP_VISIBLE = 0x2;
+    public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_RES_IN_TOUCH_MODE;
+
+    public static final int ADD_OKAY = 0;
+    public static final int ADD_BAD_APP_TOKEN = -1;
+    public static final int ADD_BAD_SUBWINDOW_TOKEN = -2;
+    public static final int ADD_NOT_APP_TOKEN = -3;
+    public static final int ADD_APP_EXITING = -4;
+    public static final int ADD_DUPLICATE_ADD = -5;
+    public static final int ADD_STARTING_NOT_NEEDED = -6;
+    public static final int ADD_MULTIPLE_SINGLETON = -7;
+    public static final int ADD_PERMISSION_DENIED = -8;
+    public static final int ADD_INVALID_DISPLAY = -9;
+
+    private static WindowManagerGlobal sDefaultWindowManager;
+    private static IWindowManager sWindowManagerService;
+    private static IWindowSession sWindowSession;
+
+    private final Object mLock = new Object();
+
+    private View[] mViews;
+    private ViewRootImpl[] mRoots;
+    private WindowManager.LayoutParams[] mParams;
+    private boolean mNeedsEglTerminate;
+
+    private Runnable mSystemPropertyUpdater;
+
+    private WindowManagerGlobal() {
+    }
+
+    public static WindowManagerGlobal getInstance() {
+        synchronized (WindowManagerGlobal.class) {
+            if (sDefaultWindowManager == null) {
+                sDefaultWindowManager = new WindowManagerGlobal();
+            }
+            return sDefaultWindowManager;
+        }
+    }
+
+    public static IWindowManager getWindowManagerService() {
+        synchronized (WindowManagerGlobal.class) {
+            if (sWindowManagerService == null) {
+                sWindowManagerService = IWindowManager.Stub.asInterface(
+                        ServiceManager.getService("window"));
+            }
+            return sWindowManagerService;
+        }
+    }
+
+    public static IWindowSession getWindowSession(Looper mainLooper) {
+        synchronized (WindowManagerGlobal.class) {
+            if (sWindowSession == null) {
+                try {
+                    InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
+                    IWindowManager windowManager = getWindowManagerService();
+                    sWindowSession = windowManager.openSession(
+                            imm.getClient(), imm.getInputContext());
+                    float animatorScale = windowManager.getAnimationScale(2);
+                    ValueAnimator.setDurationScale(animatorScale);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Failed to open window session", e);
+                }
+            }
+            return sWindowSession;
+        }
+    }
+
+    public static IWindowSession peekWindowSession() {
+        synchronized (WindowManagerGlobal.class) {
+            return sWindowSession;
+        }
+    }
+
+    public void addView(View view, ViewGroup.LayoutParams params,
+            Display display, Window parentWindow) {
+        if (view == null) {
+            throw new IllegalArgumentException("view must not be null");
+        }
+        if (display == null) {
+            throw new IllegalArgumentException("display must not be null");
+        }
+        if (!(params instanceof WindowManager.LayoutParams)) {
+            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
+        }
+
+        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
+        if (parentWindow != null) {
+            parentWindow.adjustLayoutParamsForSubWindow(wparams);
+        }
+
+        ViewRootImpl root;
+        View panelParentView = null;
+
+        synchronized (mLock) {
+            // Start watching for system property changes.
+            if (mSystemPropertyUpdater == null) {
+                mSystemPropertyUpdater = new Runnable() {
+                    @Override public void run() {
+                        synchronized (mLock) {
+                            for (ViewRootImpl viewRoot : mRoots) {
+                                viewRoot.loadSystemProperties();
+                            }
+                        }
+                    }
+                };
+                SystemProperties.addChangeCallback(mSystemPropertyUpdater);
+            }
+
+            int index = findViewLocked(view, false);
+            if (index >= 0) {
+                throw new IllegalStateException("View " + view
+                        + " has already been added to the window manager.");
+            }
+
+            // If this is a panel window, then find the window it is being
+            // attached to for future reference.
+            if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
+                    wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+                final int count = mViews != null ? mViews.length : 0;
+                for (int i=0; i<count; i++) {
+                    if (mRoots[i].mWindow.asBinder() == wparams.token) {
+                        panelParentView = mViews[i];
+                    }
+                }
+            }
+
+            root = new ViewRootImpl(view.getContext(), display);
+
+            view.setLayoutParams(wparams);
+
+            if (mViews == null) {
+                index = 1;
+                mViews = new View[1];
+                mRoots = new ViewRootImpl[1];
+                mParams = new WindowManager.LayoutParams[1];
+            } else {
+                index = mViews.length + 1;
+                Object[] old = mViews;
+                mViews = new View[index];
+                System.arraycopy(old, 0, mViews, 0, index-1);
+                old = mRoots;
+                mRoots = new ViewRootImpl[index];
+                System.arraycopy(old, 0, mRoots, 0, index-1);
+                old = mParams;
+                mParams = new WindowManager.LayoutParams[index];
+                System.arraycopy(old, 0, mParams, 0, index-1);
+            }
+            index--;
+
+            mViews[index] = view;
+            mRoots[index] = root;
+            mParams[index] = wparams;
+        }
+
+        // do this last because it fires off messages to start doing things
+        try {
+            root.setView(view, wparams, panelParentView);
+        } catch (RuntimeException e) {
+            // BadTokenException or InvalidDisplayException, clean up.
+            synchronized (mLock) {
+                final int index = findViewLocked(view, false);
+                if (index >= 0) {
+                    removeViewLocked(index, true);
+                }
+            }
+            throw e;
+        }
+    }
+
+    public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
+        if (view == null) {
+            throw new IllegalArgumentException("view must not be null");
+        }
+        if (!(params instanceof WindowManager.LayoutParams)) {
+            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
+        }
+
+        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
+
+        view.setLayoutParams(wparams);
+
+        synchronized (mLock) {
+            int index = findViewLocked(view, true);
+            ViewRootImpl root = mRoots[index];
+            mParams[index] = wparams;
+            root.setLayoutParams(wparams, false);
+        }
+    }
+
+    public void removeView(View view, boolean immediate) {
+        if (view == null) {
+            throw new IllegalArgumentException("view must not be null");
+        }
+
+        synchronized (mLock) {
+            int index = findViewLocked(view, true);
+            View curView = removeViewLocked(index, immediate);
+            if (curView == view) {
+                return;
+            }
+
+            throw new IllegalStateException("Calling with view " + view
+                    + " but the ViewAncestor is attached to " + curView);
+        }
+    }
+
+    public void closeAll(IBinder token, String who, String what) {
+        synchronized (mLock) {
+            if (mViews == null)
+                return;
+
+            int count = mViews.length;
+            //Log.i("foo", "Closing all windows of " + token);
+            for (int i=0; i<count; i++) {
+                //Log.i("foo", "@ " + i + " token " + mParams[i].token
+                //        + " view " + mRoots[i].getView());
+                if (token == null || mParams[i].token == token) {
+                    ViewRootImpl root = mRoots[i];
+
+                    //Log.i("foo", "Force closing " + root);
+                    if (who != null) {
+                        WindowLeaked leak = new WindowLeaked(
+                                what + " " + who + " has leaked window "
+                                + root.getView() + " that was originally added here");
+                        leak.setStackTrace(root.getLocation().getStackTrace());
+                        Log.e(TAG, leak.getMessage(), leak);
+                    }
+
+                    removeViewLocked(i, false);
+                    i--;
+                    count--;
+                }
+            }
+        }
+    }
+
+    private View removeViewLocked(int index, boolean immediate) {
+        ViewRootImpl root = mRoots[index];
+        View view = root.getView();
+
+        if (view != null) {
+            InputMethodManager imm = InputMethodManager.getInstance(view.getContext());
+            if (imm != null) {
+                imm.windowDismissed(mViews[index].getWindowToken());
+            }
+        }
+        root.die(immediate);
+
+        final int count = mViews.length;
+
+        // remove it from the list
+        View[] tmpViews = new View[count-1];
+        removeItem(tmpViews, mViews, index);
+        mViews = tmpViews;
+
+        ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1];
+        removeItem(tmpRoots, mRoots, index);
+        mRoots = tmpRoots;
+
+        WindowManager.LayoutParams[] tmpParams
+                = new WindowManager.LayoutParams[count-1];
+        removeItem(tmpParams, mParams, index);
+        mParams = tmpParams;
+
+        if (view != null) {
+            view.assignParent(null);
+            // func doesn't allow null...  does it matter if we clear them?
+            //view.setLayoutParams(null);
+        }
+        return view;
+    }
+
+    private static void removeItem(Object[] dst, Object[] src, int index) {
+        if (dst.length > 0) {
+            if (index > 0) {
+                System.arraycopy(src, 0, dst, 0, index);
+            }
+            if (index < dst.length) {
+                System.arraycopy(src, index+1, dst, index, src.length-index-1);
+            }
+        }
+    }
+
+    private int findViewLocked(View view, boolean required) {
+        if (mViews != null) {
+            final int count = mViews.length;
+            for (int i = 0; i < count; i++) {
+                if (mViews[i] == view) {
+                    return i;
+                }
+            }
+        }
+        if (required) {
+            throw new IllegalArgumentException("View not attached to window manager");
+        }
+        return -1;
+    }
+
+    public void startTrimMemory(int level) {
+        if (HardwareRenderer.isAvailable()) {
+            // On low-end gfx devices we trim when memory is moderate;
+            // on high-end devices we do this when low.
+            if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
+                    || (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE
+                            && !ActivityManager.isHighEndGfx())) {
+                // Destroy all hardware surfaces and resources associated to
+                // known windows
+                synchronized (mLock) {
+                    if (mViews == null) return;
+                    int count = mViews.length;
+                    for (int i = 0; i < count; i++) {
+                        mRoots[i].terminateHardwareResources();
+                    }
+                }
+                // Force a full memory flush
+                mNeedsEglTerminate = true;
+                HardwareRenderer.startTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
+                return;
+            }
+
+            HardwareRenderer.startTrimMemory(level);
+        }
+    }
+
+    public void endTrimMemory() {
+        HardwareRenderer.endTrimMemory();
+
+        if (mNeedsEglTerminate) {
+            ManagedEGLContext.doTerminate();
+            mNeedsEglTerminate = false;
+        }
+    }
+
+    public void trimLocalMemory() {
+        synchronized (mLock) {
+            if (mViews == null) return;
+            int count = mViews.length;
+            for (int i = 0; i < count; i++) {
+                mRoots[i].destroyHardwareLayers();
+            }
+        }
+    }
+
+    public void dumpGfxInfo(FileDescriptor fd) {
+        FileOutputStream fout = new FileOutputStream(fd);
+        PrintWriter pw = new PrintWriter(fout);
+        try {
+            synchronized (mLock) {
+                if (mViews != null) {
+                    final int count = mViews.length;
+
+                    pw.println("Profile data in ms:");
+
+                    for (int i = 0; i < count; i++) {
+                        ViewRootImpl root = mRoots[i];
+                        String name = getWindowName(root);
+                        pw.printf("\n\t%s", name);
+
+                        HardwareRenderer renderer =
+                                root.getView().mAttachInfo.mHardwareRenderer;
+                        if (renderer != null) {
+                            renderer.dumpGfxInfo(pw);
+                        }
+                    }
+
+                    pw.println("\nView hierarchy:\n");
+
+                    int viewsCount = 0;
+                    int displayListsSize = 0;
+                    int[] info = new int[2];
+
+                    for (int i = 0; i < count; i++) {
+                        ViewRootImpl root = mRoots[i];
+                        root.dumpGfxInfo(info);
+
+                        String name = getWindowName(root);
+                        pw.printf("  %s\n  %d views, %.2f kB of display lists",
+                                name, info[0], info[1] / 1024.0f);
+                        HardwareRenderer renderer =
+                                root.getView().mAttachInfo.mHardwareRenderer;
+                        if (renderer != null) {
+                            pw.printf(", %d frames rendered", renderer.getFrameCount());
+                        }
+                        pw.printf("\n\n");
+
+                        viewsCount += info[0];
+                        displayListsSize += info[1];
+                    }
+
+                    pw.printf("\nTotal ViewRootImpl: %d\n", count);
+                    pw.printf("Total Views:        %d\n", viewsCount);
+                    pw.printf("Total DisplayList:  %.2f kB\n\n", displayListsSize / 1024.0f);
+                }
+            }
+        } finally {
+            pw.flush();
+        }
+    }
+
+    private static String getWindowName(ViewRootImpl root) {
+        return root.mWindowAttributes.getTitle() + "/" +
+                root.getClass().getName() + '@' + Integer.toHexString(root.hashCode());
+    }
+
+    public void setStoppedState(IBinder token, boolean stopped) {
+        synchronized (mLock) {
+            if (mViews != null) {
+                int count = mViews.length;
+                for (int i=0; i < count; i++) {
+                    if (token == null || mParams[i].token == token) {
+                        ViewRootImpl root = mRoots[i];
+                        root.setStopped(stopped);
+                    }
+                }
+            }
+        }
+    }
+
+    public void reportNewConfiguration(Configuration config) {
+        synchronized (mLock) {
+            if (mViews != null) {
+                int count = mViews.length;
+                config = new Configuration(config);
+                for (int i=0; i < count; i++) {
+                    ViewRootImpl root = mRoots[i];
+                    root.requestUpdateConfiguration(config);
+                }
+            }
+        }
+    }
+}
+
+final class WindowLeaked extends AndroidRuntimeException {
+    public WindowLeaked(String msg) {
+        super(msg);
+    }
+}
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index dd6b537..52d79f8 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -16,36 +16,17 @@
 
 package android.view;
 
-import android.app.ActivityManager;
-import android.content.ComponentCallbacks2;
-import android.content.res.CompatibilityInfo;
-import android.content.res.Configuration;
-import android.graphics.PixelFormat;
-import android.opengl.ManagedEGLContext;
-import android.os.IBinder;
-import android.os.SystemProperties;
-import android.util.AndroidRuntimeException;
-import android.util.Log;
-import android.view.inputmethod.InputMethodManager;
-
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.PrintWriter;
-import java.util.HashMap;
-
-final class WindowLeaked extends AndroidRuntimeException {
-    public WindowLeaked(String msg) {
-        super(msg);
-    }
-}
-
 /**
- * Low-level communication with the global system window manager.  It implements
- * the ViewManager interface, allowing you to add any View subclass as a
- * top-level window on the screen. Additional window manager specific layout
- * parameters are defined for control over how windows are displayed.
- * It also implemens the WindowManager interface, allowing you to control the
- * displays attached to the device.
+ * Provides low-level communication with the system window manager for
+ * operations that are bound to a particular context, display or parent window.
+ * Instances of this object are sensitive to the compatibility info associated
+ * with the running application.
+ *
+ * This object implements the {@link ViewManager} interface,
+ * allowing you to add any View subclass as a top-level window on the screen.
+ * Additional window manager specific layout parameters are defined for
+ * control over how windows are displayed.  It also implements the {@link WindowManager}
+ * interface, allowing you to control the displays attached to the device.
  * 
  * <p>Applications will not normally use WindowManager directly, instead relying
  * on the higher-level facilities in {@link android.app.Activity} and
@@ -53,607 +34,58 @@
  * 
  * <p>Even for low-level window manager access, it is almost never correct to use
  * this class.  For example, {@link android.app.Activity#getWindowManager}
- * provides a ViewManager for adding windows that are associated with that
+ * provides a window manager for adding windows that are associated with that
  * activity -- the window manager will not normally allow you to add arbitrary
  * windows that are not associated with an activity.
- * 
+ *
+ * @see WindowManager
+ * @see WindowManagerGlobal
  * @hide
  */
-public class WindowManagerImpl implements WindowManager {
-    /**
-     * The user is navigating with keys (not the touch screen), so
-     * navigational focus should be shown.
-     */
-    public static final int RELAYOUT_RES_IN_TOUCH_MODE = 0x1;
-    /**
-     * This is the first time the window is being drawn,
-     * so the client must call drawingFinished() when done
-     */
-    public static final int RELAYOUT_RES_FIRST_TIME = 0x2;
-    /**
-     * The window manager has changed the surface from the last call.
-     */
-    public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4;
-    /**
-     * The window manager is currently animating.  It will call
-     * IWindow.doneAnimating() when done.
-     */
-    public static final int RELAYOUT_RES_ANIMATING = 0x8;
+public final class WindowManagerImpl implements WindowManager {
+    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
+    private final Display mDisplay;
+    private final Window mParentWindow;
 
-    /**
-     * Flag for relayout: the client will be later giving
-     * internal insets; as a result, the window will not impact other window
-     * layouts until the insets are given.
-     */
-    public static final int RELAYOUT_INSETS_PENDING = 0x1;
-
-    /**
-     * Flag for relayout: the client may be currently using the current surface,
-     * so if it is to be destroyed as a part of the relayout the destroy must
-     * be deferred until later.  The client will call performDeferredDestroy()
-     * when it is okay.
-     */
-    public static final int RELAYOUT_DEFER_SURFACE_DESTROY = 0x2;
-
-    public static final int ADD_FLAG_APP_VISIBLE = 0x2;
-    public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_RES_IN_TOUCH_MODE;
-    
-    public static final int ADD_OKAY = 0;
-    public static final int ADD_BAD_APP_TOKEN = -1;
-    public static final int ADD_BAD_SUBWINDOW_TOKEN = -2;
-    public static final int ADD_NOT_APP_TOKEN = -3;
-    public static final int ADD_APP_EXITING = -4;
-    public static final int ADD_DUPLICATE_ADD = -5;
-    public static final int ADD_STARTING_NOT_NEEDED = -6;
-    public static final int ADD_MULTIPLE_SINGLETON = -7;
-    public static final int ADD_PERMISSION_DENIED = -8;
-
-    private View[] mViews;
-    private ViewRootImpl[] mRoots;
-    private WindowManager.LayoutParams[] mParams;
-    private boolean mNeedsEglTerminate;
-
-    private Runnable mSystemPropertyUpdater = null;
-
-    private final static Object sLock = new Object();
-    private final static WindowManagerImpl sWindowManager = new WindowManagerImpl();
-    private final static HashMap<CompatibilityInfo, WindowManager> sCompatWindowManagers
-            = new HashMap<CompatibilityInfo, WindowManager>();
-
-    static class CompatModeWrapper implements WindowManager {
-        private final WindowManagerImpl mWindowManager;
-        private final Display mDefaultDisplay;
-        private final CompatibilityInfoHolder mCompatibilityInfo;
-
-        CompatModeWrapper(WindowManager wm, CompatibilityInfoHolder ci) {
-            mWindowManager = wm instanceof CompatModeWrapper
-                    ? ((CompatModeWrapper)wm).mWindowManager : (WindowManagerImpl)wm;
-
-            // Use the original display if there is no compatibility mode
-            // to apply, or the underlying window manager is already a
-            // compatibility mode wrapper.  (We assume that if it is a
-            // wrapper, it is applying the same compatibility mode.)
-            if (ci == null) {
-                mDefaultDisplay = mWindowManager.getDefaultDisplay();
-            } else {
-                //mDefaultDisplay = mWindowManager.getDefaultDisplay();
-                mDefaultDisplay = Display.createCompatibleDisplay(
-                        mWindowManager.getDefaultDisplay().getDisplayId(), ci);
-            }
-
-            mCompatibilityInfo = ci;
-        }
-
-        @Override
-        public void addView(View view, android.view.ViewGroup.LayoutParams params) {
-            mWindowManager.addView(view, params, mCompatibilityInfo);
-        }
-
-        @Override
-        public void updateViewLayout(View view, android.view.ViewGroup.LayoutParams params) {
-            mWindowManager.updateViewLayout(view, params);
-
-        }
-
-        @Override
-        public void removeView(View view) {
-            mWindowManager.removeView(view);
-        }
-
-        @Override
-        public Display getDefaultDisplay() {
-            return mDefaultDisplay;
-        }
-
-        @Override
-        public void removeViewImmediate(View view) {
-            mWindowManager.removeViewImmediate(view);
-        }
-
-        @Override
-        public boolean isHardwareAccelerated() {
-            return mWindowManager.isHardwareAccelerated();
-        }
-
+    public WindowManagerImpl(Display display) {
+        this(display, null);
     }
 
-    public static WindowManagerImpl getDefault() {
-        return sWindowManager;
+    private WindowManagerImpl(Display display, Window parentWindow) {
+        mDisplay = display;
+        mParentWindow = parentWindow;
     }
 
-    public static WindowManager getDefault(CompatibilityInfo compatInfo) {
-        CompatibilityInfoHolder cih = new CompatibilityInfoHolder();
-        cih.set(compatInfo);
-        if (cih.getIfNeeded() == null) {
-            return sWindowManager;
-        }
-
-        synchronized (sLock) {
-            // NOTE: It would be cleaner to move the implementation of
-            // WindowManagerImpl into a static inner class, and have this
-            // public impl just call into that.  Then we can make multiple
-            // instances of WindowManagerImpl for compat mode rather than
-            // having to make wrappers.
-            WindowManager wm = sCompatWindowManagers.get(compatInfo);
-            if (wm == null) {
-                wm = new CompatModeWrapper(sWindowManager, cih);
-                sCompatWindowManagers.put(compatInfo, wm);
-            }
-            return wm;
-        }
+    public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
+        return new WindowManagerImpl(mDisplay, parentWindow);
     }
 
-    public static WindowManager getDefault(CompatibilityInfoHolder compatInfo) {
-        return new CompatModeWrapper(sWindowManager, compatInfo);
-    }
-    
-    public boolean isHardwareAccelerated() {
-        return false;
-    }
-    
-    public void addView(View view) {
-        addView(view, new WindowManager.LayoutParams(
-            WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.OPAQUE));
+    public WindowManagerImpl createPresentationWindowManager(Display display) {
+        return new WindowManagerImpl(display, mParentWindow);
     }
 
+    @Override
     public void addView(View view, ViewGroup.LayoutParams params) {
-        addView(view, params, null, false);
-    }
-    
-    public void addView(View view, ViewGroup.LayoutParams params, CompatibilityInfoHolder cih) {
-        addView(view, params, cih, false);
-    }
-    
-    private void addView(View view, ViewGroup.LayoutParams params,
-            CompatibilityInfoHolder cih, boolean nest) {
-        if (false) Log.v("WindowManager", "addView view=" + view);
-
-        if (!(params instanceof WindowManager.LayoutParams)) {
-            throw new IllegalArgumentException(
-                    "Params must be WindowManager.LayoutParams");
-        }
-
-        final WindowManager.LayoutParams wparams
-                = (WindowManager.LayoutParams)params;
-        
-        ViewRootImpl root;
-        View panelParentView = null;
-        
-        synchronized (this) {
-            // Start watching for system property changes.
-            if (mSystemPropertyUpdater == null) {
-                mSystemPropertyUpdater = new Runnable() {
-                    @Override public void run() {
-                        synchronized (this) {
-                            synchronized (this) {
-                                for (ViewRootImpl root : mRoots) {
-                                    root.loadSystemProperties();
-                                }
-                            }
-                        }
-                    }
-                };
-                SystemProperties.addChangeCallback(mSystemPropertyUpdater);
-            }
-
-            // Here's an odd/questionable case: if someone tries to add a
-            // view multiple times, then we simply bump up a nesting count
-            // and they need to remove the view the corresponding number of
-            // times to have it actually removed from the window manager.
-            // This is useful specifically for the notification manager,
-            // which can continually add/remove the same view as a
-            // notification gets updated.
-            int index = findViewLocked(view, false);
-            if (index >= 0) {
-                if (!nest) {
-                    throw new IllegalStateException("View " + view
-                            + " has already been added to the window manager.");
-                }
-                root = mRoots[index];
-                root.mAddNesting++;
-                // Update layout parameters.
-                view.setLayoutParams(wparams);
-                root.setLayoutParams(wparams, true);
-                return;
-            }
-            
-            // If this is a panel window, then find the window it is being
-            // attached to for future reference.
-            if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
-                    wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
-                final int count = mViews != null ? mViews.length : 0;
-                for (int i=0; i<count; i++) {
-                    if (mRoots[i].mWindow.asBinder() == wparams.token) {
-                        panelParentView = mViews[i];
-                    }
-                }
-            }
-            
-            root = new ViewRootImpl(view.getContext());
-            root.mAddNesting = 1;
-            if (cih == null) {
-                root.mCompatibilityInfo = new CompatibilityInfoHolder();
-            } else {
-                root.mCompatibilityInfo = cih;
-            }
-
-            view.setLayoutParams(wparams);
-            
-            if (mViews == null) {
-                index = 1;
-                mViews = new View[1];
-                mRoots = new ViewRootImpl[1];
-                mParams = new WindowManager.LayoutParams[1];
-            } else {
-                index = mViews.length + 1;
-                Object[] old = mViews;
-                mViews = new View[index];
-                System.arraycopy(old, 0, mViews, 0, index-1);
-                old = mRoots;
-                mRoots = new ViewRootImpl[index];
-                System.arraycopy(old, 0, mRoots, 0, index-1);
-                old = mParams;
-                mParams = new WindowManager.LayoutParams[index];
-                System.arraycopy(old, 0, mParams, 0, index-1);
-            }
-            index--;
-
-            mViews[index] = view;
-            mRoots[index] = root;
-            mParams[index] = wparams;
-        }
-        // do this last because it fires off messages to start doing things
-        root.setView(view, wparams, panelParentView);
+        mGlobal.addView(view, params, mDisplay, mParentWindow);
     }
 
+    @Override
     public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
-        if (!(params instanceof WindowManager.LayoutParams)) {
-            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
-        }
-
-        final WindowManager.LayoutParams wparams
-                = (WindowManager.LayoutParams)params;
-        
-        view.setLayoutParams(wparams);
-
-        synchronized (this) {
-            int index = findViewLocked(view, true);
-            ViewRootImpl root = mRoots[index];
-            mParams[index] = wparams;
-            root.setLayoutParams(wparams, false);
-        }
+        mGlobal.updateViewLayout(view, params);
     }
 
+    @Override
     public void removeView(View view) {
-        synchronized (this) {
-            int index = findViewLocked(view, true);
-            View curView = removeViewLocked(index);
-            if (curView == view) {
-                return;
-            }
-            
-            throw new IllegalStateException("Calling with view " + view
-                    + " but the ViewAncestor is attached to " + curView);
-        }
+        mGlobal.removeView(view, false);
     }
 
+    @Override
     public void removeViewImmediate(View view) {
-        synchronized (this) {
-            int index = findViewLocked(view, true);
-            ViewRootImpl root = mRoots[index];
-            View curView = root.getView();
-            
-            root.mAddNesting = 0;
-
-            if (view != null) {
-                InputMethodManager imm = InputMethodManager.getInstance(view.getContext());
-                if (imm != null) {
-                    imm.windowDismissed(mViews[index].getWindowToken());
-                }
-            }
-
-            root.die(true);
-            finishRemoveViewLocked(curView, index);
-            if (curView == view) {
-                return;
-            }
-            
-            throw new IllegalStateException("Calling with view " + view
-                    + " but the ViewAncestor is attached to " + curView);
-        }
-    }
-    
-    View removeViewLocked(int index) {
-        ViewRootImpl root = mRoots[index];
-        View view = root.getView();
-
-        // Don't really remove until we have matched all calls to add().
-        root.mAddNesting--;
-        if (root.mAddNesting > 0) {
-            return view;
-        }
-
-        if (view != null) {
-            InputMethodManager imm = InputMethodManager.getInstance(view.getContext());
-            if (imm != null) {
-                imm.windowDismissed(mViews[index].getWindowToken());
-            }
-        }
-        root.die(false);
-        finishRemoveViewLocked(view, index);
-        return view;
-    }
-    
-    void finishRemoveViewLocked(View view, int index) {
-        final int count = mViews.length;
-
-        // remove it from the list
-        View[] tmpViews = new View[count-1];
-        removeItem(tmpViews, mViews, index);
-        mViews = tmpViews;
-        
-        ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1];
-        removeItem(tmpRoots, mRoots, index);
-        mRoots = tmpRoots;
-        
-        WindowManager.LayoutParams[] tmpParams
-                = new WindowManager.LayoutParams[count-1];
-        removeItem(tmpParams, mParams, index);
-        mParams = tmpParams;
-
-        if (view != null) {
-            view.assignParent(null);
-            // func doesn't allow null...  does it matter if we clear them?
-            //view.setLayoutParams(null);
-        }
+        mGlobal.removeView(view, true);
     }
 
-    public void closeAll(IBinder token, String who, String what) {
-        synchronized (this) {
-            if (mViews == null)
-                return;
-            
-            int count = mViews.length;
-            //Log.i("foo", "Closing all windows of " + token);
-            for (int i=0; i<count; i++) {
-                //Log.i("foo", "@ " + i + " token " + mParams[i].token
-                //        + " view " + mRoots[i].getView());
-                if (token == null || mParams[i].token == token) {
-                    ViewRootImpl root = mRoots[i];
-                    root.mAddNesting = 1;
-                    
-                    //Log.i("foo", "Force closing " + root);
-                    if (who != null) {
-                        WindowLeaked leak = new WindowLeaked(
-                                what + " " + who + " has leaked window "
-                                + root.getView() + " that was originally added here");
-                        leak.setStackTrace(root.getLocation().getStackTrace());
-                        Log.e("WindowManager", leak.getMessage(), leak);
-                    }
-
-                    removeViewLocked(i);
-                    i--;
-                    count--;
-                }
-            }
-        }
-    }
-
-    /**
-     * @param level See {@link android.content.ComponentCallbacks}
-     *
-     * @hide
-     */
-    public void startTrimMemory(int level) {
-        if (HardwareRenderer.isAvailable()) {
-            // On low-end gfx devices we trim when memory is moderate;
-            // on high-end devices we do this when low.
-            if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
-                    || (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE
-                            && !ActivityManager.isHighEndGfx(getDefaultDisplay()))) {
-                // Destroy all hardware surfaces and resources associated to
-                // known windows
-                synchronized (this) {
-                    if (mViews == null) return;
-                    int count = mViews.length;
-                    for (int i = 0; i < count; i++) {
-                        mRoots[i].terminateHardwareResources();
-                    }
-                }
-                // Force a full memory flush
-                mNeedsEglTerminate = true;
-                HardwareRenderer.startTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
-                return;
-            }
-
-            HardwareRenderer.startTrimMemory(level);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void endTrimMemory() {
-        HardwareRenderer.endTrimMemory();
-
-        if (mNeedsEglTerminate) {
-            ManagedEGLContext.doTerminate();
-            mNeedsEglTerminate = false;
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void trimLocalMemory() {
-        synchronized (this) {
-            if (mViews == null) return;
-            int count = mViews.length;
-            for (int i = 0; i < count; i++) {
-                mRoots[i].destroyHardwareLayers();
-            }
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void dumpGfxInfo(FileDescriptor fd) {
-        FileOutputStream fout = new FileOutputStream(fd);
-        PrintWriter pw = new PrintWriter(fout);
-        try {
-            synchronized (this) {
-                if (mViews != null) {
-                    final int count = mViews.length;
-                    
-                    pw.println("Profile data in ms:");
-
-                    for (int i = 0; i < count; i++) {
-                        ViewRootImpl root = mRoots[i];
-                        String name = getWindowName(root);
-                        pw.printf("\n\t%s", name);
-
-                        HardwareRenderer renderer = root.getView().mAttachInfo.mHardwareRenderer;
-                        if (renderer != null) {
-                            renderer.dumpGfxInfo(pw);
-                        }
-                    }
-
-                    pw.println("\nView hierarchy:\n");
-
-                    int viewsCount = 0;
-                    int displayListsSize = 0;
-                    int[] info = new int[2];
-
-                    for (int i = 0; i < count; i++) {
-                        ViewRootImpl root = mRoots[i];
-                        root.dumpGfxInfo(info);
-
-                        String name = getWindowName(root);
-                        pw.printf("  %s\n  %d views, %.2f kB of display lists",
-                                name, info[0], info[1] / 1024.0f);
-                        HardwareRenderer renderer = root.getView().mAttachInfo.mHardwareRenderer;
-                        if (renderer != null) {
-                            pw.printf(", %d frames rendered", renderer.getFrameCount());
-                        }
-                        pw.printf("\n\n");
-
-                        viewsCount += info[0];
-                        displayListsSize += info[1];
-                    }
-
-                    pw.printf("\nTotal ViewRootImpl: %d\n", count);
-                    pw.printf("Total Views:        %d\n", viewsCount);                    
-                    pw.printf("Total DisplayList:  %.2f kB\n\n", displayListsSize / 1024.0f);                    
-                }
-            }
-        } finally {
-            pw.flush();
-        }        
-    }
-
-    private static String getWindowName(ViewRootImpl root) {
-        return root.mWindowAttributes.getTitle() + "/" +
-                root.getClass().getName() + '@' + Integer.toHexString(root.hashCode());
-    }
-
-    public void setStoppedState(IBinder token, boolean stopped) {
-        synchronized (this) {
-            if (mViews == null)
-                return;
-            int count = mViews.length;
-            for (int i=0; i<count; i++) {
-                if (token == null || mParams[i].token == token) {
-                    ViewRootImpl root = mRoots[i];
-                    root.setStopped(stopped);
-                }
-            }
-        }
-    }
-    
-    public void reportNewConfiguration(Configuration config) {
-        synchronized (this) {
-            int count = mViews.length;
-            config = new Configuration(config);
-            for (int i=0; i<count; i++) {
-                ViewRootImpl root = mRoots[i];
-                root.requestUpdateConfiguration(config);
-            }
-        }
-    }
-
-    public WindowManager.LayoutParams getRootViewLayoutParameter(View view) {
-        ViewParent vp = view.getParent();
-        while (vp != null && !(vp instanceof ViewRootImpl)) {
-            vp = vp.getParent();
-        }
-        
-        if (vp == null) return null;
-        
-        ViewRootImpl vr = (ViewRootImpl)vp;
-        
-        int N = mRoots.length;
-        for (int i = 0; i < N; ++i) {
-            if (mRoots[i] == vr) {
-                return mParams[i];
-            }
-        }
-        
-        return null;
-    }
-    
-    public void closeAll() {
-        closeAll(null, null, null);
-    }
-    
+    @Override
     public Display getDefaultDisplay() {
-        return new Display(Display.DEFAULT_DISPLAY, null);
-    }
-
-    private static void removeItem(Object[] dst, Object[] src, int index) {
-        if (dst.length > 0) {
-            if (index > 0) {
-                System.arraycopy(src, 0, dst, 0, index);
-            }
-            if (index < dst.length) {
-                System.arraycopy(src, index+1, dst, index, src.length-index-1);
-            }
-        }
-    }
-
-    private int findViewLocked(View view, boolean required) {
-        synchronized (this) {
-            final int count = mViews != null ? mViews.length : 0;
-            for (int i=0; i<count; i++) {
-                if (mViews[i] == view) {
-                    return i;
-                }
-            }
-            if (required) {
-                throw new IllegalArgumentException(
-                        "View not attached to window manager");
-            }
-            return -1;
-        }
+        return mDisplay;
     }
 }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 09948b8..26739b3 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -21,8 +21,8 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.os.Bundle;
 import android.os.IBinder;
-import android.os.LocalPowerManager;
 import android.os.Looper;
 import android.view.animation.Animation;
 
@@ -115,16 +115,16 @@
     public final static int ACTION_PASS_TO_USER = 0x00000001;
 
     /**
-     * This key event should extend the user activity timeout and turn the lights on.
+     * This key event should wake the device.
      * To be returned from {@link #interceptKeyBeforeQueueing}.
      * Do not return this and {@link #ACTION_GO_TO_SLEEP} or {@link #ACTION_PASS_TO_USER}.
      */
-    public final static int ACTION_POKE_USER_ACTIVITY = 0x00000002;
+    public final static int ACTION_WAKE_UP = 0x00000002;
 
     /**
      * This key event should put the device to sleep (and engage keyguard if necessary)
      * To be returned from {@link #interceptKeyBeforeQueueing}.
-     * Do not return this and {@link #ACTION_POKE_USER_ACTIVITY} or {@link #ACTION_PASS_TO_USER}.
+     * Do not return this and {@link #ACTION_WAKE_UP} or {@link #ACTION_PASS_TO_USER}.
      */
     public final static int ACTION_GO_TO_SLEEP = 0x00000004;
 
@@ -339,6 +339,12 @@
          * Check whether the process hosting this window is currently alive.
          */
         public boolean isAlive();
+
+        /**
+         * Check if window is on {@link Display#DEFAULT_DISPLAY}.
+         * @return true if window is on default display.
+         */
+        public boolean isDefaultDisplay();
     }
 
     /**
@@ -391,8 +397,8 @@
          */
         public void switchKeyboardLayout(int deviceId, int direction);
 
-        public void shutdown();
-        public void rebootSafeMode();
+        public void shutdown(boolean confirm);
+        public void rebootSafeMode(boolean confirm);
     }
 
     /**
@@ -473,30 +479,38 @@
      * Perform initialization of the policy.
      * 
      * @param context The system context we are running in.
-     * @param powerManager 
      */
     public void init(Context context, IWindowManager windowManager,
-            WindowManagerFuncs windowManagerFuncs,
-            LocalPowerManager powerManager);
+            WindowManagerFuncs windowManagerFuncs);
 
     /**
      * Called by window manager once it has the initial, default native
      * display dimensions.
      */
-    public void setInitialDisplaySize(Display display, int width, int height);
+    public void setInitialDisplaySize(Display display, int width, int height, int density);
 
     /**
      * Check permissions when adding a window.
      * 
      * @param attrs The window's LayoutParams. 
      *  
-     * @return {@link WindowManagerImpl#ADD_OKAY} if the add can proceed;
+     * @return {@link WindowManagerGlobal#ADD_OKAY} if the add can proceed;
      *      else an error code, usually
-     *      {@link WindowManagerImpl#ADD_PERMISSION_DENIED}, to abort the add.
+     *      {@link WindowManagerGlobal#ADD_PERMISSION_DENIED}, to abort the add.
      */
     public int checkAddPermission(WindowManager.LayoutParams attrs);
 
     /**
+     * Check permissions when adding a window.
+     *
+     * @param attrs The window's LayoutParams.
+     *
+     * @return True if the window may only be shown to the current user, false if the window can
+     * be shown on all users' windows.
+     */
+    public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs);
+
+    /**
      * Sanitize the layout parameters coming from a client.  Allows the policy
      * to do things like ensure that windows of a specific type can't take
      * input focus.
@@ -553,7 +567,14 @@
      * allowed to be in.
      */
     public int getMaxWallpaperLayer();
-    
+
+    /**
+     * Return the window layer at which windows appear above the normal
+     * universe (that is no longer impacted by the universe background
+     * transform).
+     */
+    public int getAboveUniverseLayer();
+
     /**
      * Return true if the policy desires a full unified system nav bar.  Otherwise,
      * it is a phone-style status bar with optional nav bar.
@@ -658,7 +679,7 @@
      * @param win The window being added.
      * @param attrs The window's LayoutParams. 
      *  
-     * @return {@link WindowManagerImpl#ADD_OKAY} if the add can proceed, else an 
+     * @return {@link WindowManagerGlobal#ADD_OKAY} if the add can proceed, else an
      *         error code to abort the add.
      */
     public int prepareAddWindowLw(WindowState win,
@@ -703,7 +724,7 @@
      * @param isScreenOn True if the screen is already on
      *
      * @return The bitwise or of the {@link #ACTION_PASS_TO_USER},
-     *          {@link #ACTION_POKE_USER_ACTIVITY} and {@link #ACTION_GO_TO_SLEEP} flags.
+     *      {@link #ACTION_WAKE_UP} and {@link #ACTION_GO_TO_SLEEP} flags.
      */
     public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn);
 
@@ -717,7 +738,7 @@
      * @param policyFlags The policy flags associated with the motion.
      *
      * @return The bitwise or of the {@link #ACTION_PASS_TO_USER},
-     *          {@link #ACTION_POKE_USER_ACTIVITY} and {@link #ACTION_GO_TO_SLEEP} flags.
+     *      {@link #ACTION_WAKE_UP} and {@link #ACTION_GO_TO_SLEEP} flags.
      */
     public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags);
 
@@ -758,12 +779,14 @@
     /**
      * Called when layout of the windows is about to start.
      * 
+     * @param isDefaultDisplay true if window is on {@link Display#DEFAULT_DISPLAY}.
      * @param displayWidth The current full width of the screen.
      * @param displayHeight The current full height of the screen.
      * @param displayRotation The current rotation being applied to the base
      * window.
      */
-    public void beginLayoutLw(int displayWidth, int displayHeight, int displayRotation);
+    public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
+                              int displayRotation);
 
     /**
      * Return the rectangle of the screen currently covered by system decorations.
@@ -823,32 +846,33 @@
     static final int FINISH_LAYOUT_REDO_ANIM = 0x0008;
     
     /**
-     * Called when animation of the windows is about to start.
+     * Called following layout of all windows before each window has policy applied.
      * 
      * @param displayWidth The current full width of the screen.
      * @param displayHeight The current full height of the screen.
      */
-    public void beginAnimationLw(int displayWidth, int displayHeight);
+    public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight);
 
     /**
-     * Called each time a window is animating.
+     * Called following layout of all window to apply policy to each window.
      * 
      * @param win The window being positioned.
      * @param attrs The LayoutParams of the window. 
      */
-    public void animatingWindowLw(WindowState win,
+    public void applyPostLayoutPolicyLw(WindowState win,
             WindowManager.LayoutParams attrs);
 
     /**
-     * Called when animation of the windows is finished.  If in this function you do 
-     * something that may have modified the animation state of another window, 
-     * be sure to return true in order to perform another animation frame. 
+     * Called following layout of all windows and after policy has been applied
+     * to each window. If in this function you do
+     * something that may have modified the animation state of another window,
+     * be sure to return non-zero in order to perform another pass through layout.
      *  
      * @return Return any bit set of {@link #FINISH_LAYOUT_REDO_LAYOUT},
      * {@link #FINISH_LAYOUT_REDO_CONFIG}, {@link #FINISH_LAYOUT_REDO_WALLPAPER},
      * or {@link #FINISH_LAYOUT_REDO_ANIM}.
      */
-    public int finishAnimationLw();
+    public int finishPostLayoutPolicyLw();
 
     /**
      * Return true if it is okay to perform animations for an app transition
@@ -1044,26 +1068,21 @@
      * Called when we have started keeping the screen on because a window
      * requesting this has become visible.
      */
-    public void screenOnStartedLw();
+    public void keepScreenOnStartedLw();
 
     /**
      * Called when we have stopped keeping the screen on because the last window
      * requesting this is no longer visible.
      */
-    public void screenOnStoppedLw();
-
-    /**
-     * Return false to disable key repeat events from being generated.
-     */
-    public boolean allowKeyRepeat();
+    public void keepScreenOnStoppedLw();
 
     /**
      * Inform the policy that the user has chosen a preferred orientation ("rotation lock"). 
      *
      * @param mode One of {@link WindowManagerPolicy#USER_ROTATION_LOCKED} or
-     *             {@link * WindowManagerPolicy#USER_ROTATION_FREE}. 
+     *             {@link WindowManagerPolicy#USER_ROTATION_FREE}. 
      * @param rotation One of {@link Surface#ROTATION_0}, {@link Surface#ROTATION_90},
-     *                 {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}. 
+     *                 {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}.
      */
     public void setUserRotationMode(int mode, int rotation);
 
@@ -1083,32 +1102,7 @@
     /**
      * Lock the device now.
      */
-    public void lockNow();
-
-    /**
-     * Check to see if a screensaver should be run instead of powering off the screen on timeout. 
-     * 
-     * @return true if the screensaver should run, false if the screen should turn off.
-     * 
-     * @hide
-     */
-    public boolean isScreenSaverEnabled();
-
-    /**
-     * Start the screensaver (if it is enabled and not yet running).
-     * 
-     * @return Whether the screensaver was successfully started.
-     * 
-     * @hide
-     */
-    public boolean startScreenSaver();
-
-    /**
-     * Stop the screensaver if it is running.
-     * 
-     * @hide
-     */
-    public void stopScreenSaver();
+    public void lockNow(Bundle options);
 
     /**
      * Set the last used input method window state. This state is used to make IME transition
@@ -1118,6 +1112,22 @@
     public void setLastInputMethodWindowLw(WindowState ime, WindowState target);
 
     /**
+     * Returns whether magnification can be applied to the given window type.
+     *
+     * @param attrs The window's LayoutParams.
+     * @return Whether magnification can be applied.
+     */
+    public boolean canMagnifyWindowLw(WindowManager.LayoutParams attrs);
+
+    /**
+     * Called when the current user changes. Guaranteed to be called before the broadcast
+     * of the new user id is made to all listeners.
+     *
+     * @param newUserId The id of the incoming user.
+     */
+    public void setCurrentUserLw(int newUserId);
+
+    /**
      * Print the WindowManagerPolicy's state into the given stream.
      *
      * @param prefix Text to print at the front of each line.
@@ -1126,4 +1136,10 @@
      * @param args additional arguments to the dump request.
      */
     public void dump(String prefix, PrintWriter writer, String[] args);
+
+    /**
+     * Ask keyguard to invoke the assist intent after dismissing keyguard
+     * {@link android.content.Intent#ACTION_ASSIST}
+     */
+    public void showAssistant();
 }
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 1a2a194..1500905 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -424,6 +424,28 @@
  * </ul>
  * </p>
  * <p>
+ * <b>Touch interaction start</b> - represents the event of starting a touch
+ * interaction, which is the user starts touching the screen.</br>
+ * <em>Type:</em> {@link #TYPE_TOUCH_INTERACTION_START}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ *   <li>{@link #getEventType()} - The type of the event.</li>
+ * </ul>
+ * <em>Note:</em> This event is fired only by the system and is not passed to the
+ * view tree to be populated.</br>
+ * </p>
+ * <p>
+ * <b>Touch interaction end</b> - represents the event of ending a touch
+ * interaction, which is the user stops touching the screen.</br>
+ * <em>Type:</em> {@link #TYPE_TOUCH_INTERACTION_END}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ *   <li>{@link #getEventType()} - The type of the event.</li>
+ * </ul>
+ * <em>Note:</em> This event is fired only by the system and is not passed to the
+ * view tree to be populated.</br>
+ * </p>
+ * <p>
  * <b>Touch exploration gesture start</b> - represents the event of starting a touch
  * exploring gesture.</br>
  * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_START}</br>
@@ -431,15 +453,8 @@
  * <ul>
  *   <li>{@link #getEventType()} - The type of the event.</li>
  * </ul>
- * <em>Note:</em> This event type is not dispatched to descendants though
- * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
- * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
- * source {@link android.view.View} and the sub-tree rooted at it will not receive
- * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
- * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
- * text content to such events is by setting the
- * {@link android.R.styleable#View_contentDescription contentDescription} of the source
- * view.</br>
+ * <em>Note:</em> This event is fired only by the system and is not passed to the
+ * view tree to be populated.</br>
  * </p>
  * <p>
  * <b>Touch exploration gesture end</b> - represents the event of ending a touch
@@ -449,15 +464,30 @@
  * <ul>
  *   <li>{@link #getEventType()} - The type of the event.</li>
  * </ul>
- * <em>Note:</em> This event type is not dispatched to descendants though
- * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
- * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
- * source {@link android.view.View} and the sub-tree rooted at it will not receive
- * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
- * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
- * text content to such events is by setting the
- * {@link android.R.styleable#View_contentDescription contentDescription} of the source
- * view.</br>
+ * <em>Note:</em> This event is fired only by the system and is not passed to the
+ * view tree to be populated.</br>
+ * </p>
+ * <p>
+ * <b>Touch gesture detection start</b> - represents the event of starting a user
+ * gesture detection.</br>
+ * <em>Type:</em> {@link #TYPE_GESTURE_DETECTION_START}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ *   <li>{@link #getEventType()} - The type of the event.</li>
+ * </ul>
+ * <em>Note:</em> This event is fired only by the system and is not passed to the
+ * view tree to be populated.</br>
+ * </p>
+ * <p>
+ * <b>Touch gesture detection end</b> - represents the event of ending a user
+ * gesture detection.</br>
+ * <em>Type:</em> {@link #TYPE_GESTURE_DETECTION_END}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ *   <li>{@link #getEventType()} - The type of the event.</li>
+ * </ul>
+ * <em>Note:</em> This event is fired only by the system and is not passed to the
+ * view tree to be populated.</br>
  * </p>
  * <p>
  * <b>MISCELLANEOUS TYPES</b></br>
@@ -610,6 +640,26 @@
     public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 0x00020000;
 
     /**
+     * Represents the event of beginning gesture detection.
+     */
+    public static final int TYPE_GESTURE_DETECTION_START = 0x00040000;
+
+    /**
+     * Represents the event of ending gesture detection.
+     */
+    public static final int TYPE_GESTURE_DETECTION_END = 0x00080000;
+
+    /**
+     * Represents the event of the user starting to touch the screen.
+     */
+    public static final int TYPE_TOUCH_INTERACTION_START = 0x00100000;
+
+    /**
+     * Represents the event of the user ending to touch the screen.
+     */
+    public static final int TYPE_TOUCH_INTERACTION_END = 0x00200000;
+
+    /**
      * Mask for {@link AccessibilityEvent} all types.
      *
      * @see #TYPE_VIEW_CLICKED
@@ -628,6 +678,10 @@
      * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED
      * @see #TYPE_ANNOUNCEMENT
      * @see #TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+     * @see #TYPE_GESTURE_DETECTION_START
+     * @see #TYPE_GESTURE_DETECTION_END
+     * @see #TYPE_TOUCH_INTERACTION_START
+     * @see #TYPE_TOUCH_INTERACTION_END
      */
     public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
 
@@ -1120,6 +1174,14 @@
                 return "TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED";
             case TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY:
                 return "TYPE_CURRENT_AT_GRANULARITY_MOVEMENT_CHANGED";
+            case TYPE_GESTURE_DETECTION_START:
+                return "TYPE_GESTURE_DETECTION_START";
+            case TYPE_GESTURE_DETECTION_END:
+                return "TYPE_GESTURE_DETECTION_END";
+            case TYPE_TOUCH_INTERACTION_START:
+                return "TYPE_TOUCH_INTERACTION_START";
+            case TYPE_TOUCH_INTERACTION_END:
+                return "TYPE_TOUCH_INTERACTION_END";
             default:
                 return null;
         }
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 77fd12a..732699b 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -27,6 +27,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.util.Log;
 import android.view.IWindow;
 import android.view.View;
@@ -79,6 +80,8 @@
 
     final IAccessibilityManager mService;
 
+    final int mUserId;
+
     final Handler mHandler;
 
     boolean mIsEnabled;
@@ -129,35 +132,72 @@
     }
 
     /**
+     * Creates the singleton AccessibilityManager to be shared across users. This
+     * has to be called before the local AccessibilityManager is created to ensure
+     * it registers itself in the system correctly.
+     * <p>
+     * Note: Calling this method requires INTERACT_ACROSS_USERS_FULL or
+     *       INTERACT_ACROSS_USERS permission.
+     * </p>
+     * @param context Context in which this manager operates.
+     * @throws IllegalStateException if not called before the local
+     *     AccessibilityManager is instantiated.
+     *
+     * @hide
+     */
+    public static void createAsSharedAcrossUsers(Context context) {
+        synchronized (sInstanceSync) {
+            if (sInstance != null) {
+                throw new IllegalStateException("AccessibilityManager already created.");
+            }
+            createSingletonInstance(context, UserHandle.USER_CURRENT);
+        }
+    }
+
+    /**
      * Get an AccessibilityManager instance (create one if necessary).
      *
+     * @param context Context in which this manager operates.
+     *
      * @hide
      */
     public static AccessibilityManager getInstance(Context context) {
         synchronized (sInstanceSync) {
             if (sInstance == null) {
-                IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
-                IAccessibilityManager service = IAccessibilityManager.Stub.asInterface(iBinder);
-                sInstance = new AccessibilityManager(context, service);
+                createSingletonInstance(context, UserHandle.myUserId());
             }
         }
         return sInstance;
     }
 
     /**
+     * Creates the singleton instance.
+     *
+     * @param context Context in which this manager operates.
+     * @param userId The user id under which to operate.
+     */
+    private static void createSingletonInstance(Context context, int userId) {
+        IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
+        IAccessibilityManager service = IAccessibilityManager.Stub.asInterface(iBinder);
+        sInstance = new AccessibilityManager(context, service, userId);
+    }
+
+    /**
      * Create an instance.
      *
      * @param context A {@link Context}.
      * @param service An interface to the backing service.
+     * @param userId User id under which to run.
      *
      * @hide
      */
-    public AccessibilityManager(Context context, IAccessibilityManager service) {
+    public AccessibilityManager(Context context, IAccessibilityManager service, int userId) {
         mHandler = new MyHandler(context.getMainLooper());
         mService = service;
+        mUserId = userId;
 
         try {
-            final int stateFlags = mService.addClient(mClient);
+            final int stateFlags = mService.addClient(mClient, userId);
             setState(stateFlags);
         } catch (RemoteException re) {
             Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
@@ -222,7 +262,7 @@
             // client using it is called through Binder from another process. Example: MMS
             // app adds a SMS notification and the NotificationManagerService calls this method
             long identityToken = Binder.clearCallingIdentity();
-            doRecycle = mService.sendAccessibilityEvent(event);
+            doRecycle = mService.sendAccessibilityEvent(event, mUserId);
             Binder.restoreCallingIdentity(identityToken);
             if (DEBUG) {
                 Log.i(LOG_TAG, event + " sent");
@@ -244,7 +284,7 @@
             throw new IllegalStateException("Accessibility off. Did you forget to check that?");
         }
         try {
-            mService.interrupt();
+            mService.interrupt(mUserId);
             if (DEBUG) {
                 Log.i(LOG_TAG, "Requested interrupt from all services");
             }
@@ -280,7 +320,7 @@
     public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() {
         List<AccessibilityServiceInfo> services = null;
         try {
-            services = mService.getInstalledAccessibilityServiceList();
+            services = mService.getInstalledAccessibilityServiceList(mUserId);
             if (DEBUG) {
                 Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
             }
@@ -307,7 +347,7 @@
             int feedbackTypeFlags) {
         List<AccessibilityServiceInfo> services = null;
         try {
-            services = mService.getEnabledAccessibilityServiceList(feedbackTypeFlags);
+            services = mService.getEnabledAccessibilityServiceList(feedbackTypeFlags, mUserId);
             if (DEBUG) {
                 Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
             }
@@ -385,7 +425,7 @@
     public int addAccessibilityInteractionConnection(IWindow windowToken,
             IAccessibilityInteractionConnection connection) {
         try {
-            return mService.addAccessibilityInteractionConnection(windowToken, connection);
+            return mService.addAccessibilityInteractionConnection(windowToken, connection, mUserId);
         } catch (RemoteException re) {
             Log.e(LOG_TAG, "Error while adding an accessibility interaction connection. ", re);
         }
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 3ad3a55..1dc2487 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -365,6 +365,8 @@
     private int mWindowId = UNDEFINED;
     private long mSourceNodeId = ROOT_NODE_ID;
     private long mParentNodeId = ROOT_NODE_ID;
+    private long mLabelForId = ROOT_NODE_ID;
+    private long mLabeledById = ROOT_NODE_ID;
 
     private int mBooleanProperties;
     private final Rect mBoundsInParent = new Rect();
@@ -382,10 +384,6 @@
 
     private int mConnectionId = UNDEFINED;
 
-    // TODO: These are a workaround for 6623031. Remove when fixed.
-    private int mActualAndReportedWindowLeftDelta;
-    private int mActualAndReportedWindowTopDelta;
-
     /**
      * Hide constructor from clients.
      */
@@ -432,10 +430,6 @@
         final int rootAccessibilityViewId =
             (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
         mSourceNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
-        if (root != null) {
-            mActualAndReportedWindowLeftDelta = root.getActualAndReportedWindowLeftDelta();
-            mActualAndReportedWindowTopDelta = root.getActualAndReportedWindowTopDelta();
-        }
     }
 
     /**
@@ -833,7 +827,6 @@
     public void setBoundsInScreen(Rect bounds) {
         enforceNotSealed();
         mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
-        mBoundsInScreen.offset(mActualAndReportedWindowLeftDelta, mActualAndReportedWindowTopDelta);
     }
 
     /**
@@ -1242,6 +1235,120 @@
     }
 
     /**
+     * Sets the view for which the view represented by this info serves as a
+     * label for accessibility purposes.
+     *
+     * @param labeled The view for which this info serves as a label.
+     */
+    public void setLabelFor(View labeled) {
+        setLabelFor(labeled, UNDEFINED);
+    }
+
+    /**
+     * Sets the view for which the view represented by this info serves as a
+     * label for accessibility purposes. If <code>virtualDescendantId</code>
+     * is {@link View#NO_ID} the root is set as the labeled.
+     * <p>
+     * A virtual descendant is an imaginary View that is reported as a part of the view
+     * hierarchy for accessibility purposes. This enables custom views that draw complex
+     * content to report themselves as a tree of virtual views, thus conveying their
+     * logical structure.
+     * </p>
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param root The root whose virtual descendant serves as a label.
+     * @param virtualDescendantId The id of the virtual descendant.
+     */
+    public void setLabelFor(View root, int virtualDescendantId) {
+        enforceNotSealed();
+        final int rootAccessibilityViewId = (root != null)
+                ? root.getAccessibilityViewId() : UNDEFINED;
+        mLabelForId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
+    }
+
+    /**
+     * Gets the node info for which the view represented by this info serves as
+     * a label for accessibility purposes.
+     * <p>
+     *   <strong>Note:</strong> It is a client responsibility to recycle the
+     *     received info by calling {@link AccessibilityNodeInfo#recycle()}
+     *     to avoid creating of multiple instances.
+     * </p>
+     *
+     * @return The labeled info.
+     */
+    public AccessibilityNodeInfo getLabelFor() {
+        enforceSealed();
+        if (!canPerformRequestOverConnection(mLabelForId)) {
+            return null;
+        }
+        AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
+        return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
+                mWindowId, mLabelForId, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
+    }
+
+    /**
+     * Sets the view which serves as the label of the view represented by
+     * this info for accessibility purposes.
+     *
+     * @param label The view that labels this node's source.
+     */
+    public void setLabeledBy(View label) {
+        setLabeledBy(label, UNDEFINED);
+    }
+
+    /**
+     * Sets the view which serves as the label of the view represented by
+     * this info for accessibility purposes. If <code>virtualDescendantId</code>
+     * is {@link View#NO_ID} the root is set as the label.
+     * <p>
+     * A virtual descendant is an imaginary View that is reported as a part of the view
+     * hierarchy for accessibility purposes. This enables custom views that draw complex
+     * content to report themselves as a tree of virtual views, thus conveying their
+     * logical structure.
+     * </p>
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param root The root whose virtual descendant labels this node's source.
+     * @param virtualDescendantId The id of the virtual descendant.
+     */
+    public void setLabeledBy(View root, int virtualDescendantId) {
+        enforceNotSealed();
+        final int rootAccessibilityViewId = (root != null)
+                ? root.getAccessibilityViewId() : UNDEFINED;
+        mLabeledById = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
+    }
+
+    /**
+     * Gets the node info which serves as the label of the view represented by
+     * this info for accessibility purposes.
+     * <p>
+     *   <strong>Note:</strong> It is a client responsibility to recycle the
+     *     received info by calling {@link AccessibilityNodeInfo#recycle()}
+     *     to avoid creating of multiple instances.
+     * </p>
+     *
+     * @return The label.
+     */
+    public AccessibilityNodeInfo getLabeledBy() {
+        enforceSealed();
+        if (!canPerformRequestOverConnection(mLabeledById)) {
+            return null;
+        }
+        AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
+        return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
+                mWindowId, mLabeledById, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
+    }
+
+    /**
      * Gets the value of a boolean property.
      *
      * @param property The property.
@@ -1343,12 +1450,6 @@
             case View.FOCUS_RIGHT:
             case View.FOCUS_FORWARD:
             case View.FOCUS_BACKWARD:
-            case View.ACCESSIBILITY_FOCUS_DOWN:
-            case View.ACCESSIBILITY_FOCUS_UP:
-            case View.ACCESSIBILITY_FOCUS_LEFT:
-            case View.ACCESSIBILITY_FOCUS_RIGHT:
-            case View.ACCESSIBILITY_FOCUS_FORWARD:
-            case View.ACCESSIBILITY_FOCUS_BACKWARD:
                 return;
             default:
                 throw new IllegalArgumentException("Unknown direction: " + direction);
@@ -1477,6 +1578,8 @@
         parcel.writeLong(mSourceNodeId);
         parcel.writeInt(mWindowId);
         parcel.writeLong(mParentNodeId);
+        parcel.writeLong(mLabelForId);
+        parcel.writeLong(mLabeledById);
         parcel.writeInt(mConnectionId);
 
         SparseLongArray childIds = mChildNodeIds;
@@ -1522,6 +1625,8 @@
         mSealed = other.mSealed;
         mSourceNodeId = other.mSourceNodeId;
         mParentNodeId = other.mParentNodeId;
+        mLabelForId = other.mLabelForId;
+        mLabeledById = other.mLabeledById;
         mWindowId = other.mWindowId;
         mConnectionId = other.mConnectionId;
         mBoundsInParent.set(other.mBoundsInParent);
@@ -1549,6 +1654,8 @@
         mSourceNodeId = parcel.readLong();
         mWindowId = parcel.readInt();
         mParentNodeId = parcel.readLong();
+        mLabelForId = parcel.readLong();
+        mLabeledById = parcel.readLong();
         mConnectionId = parcel.readInt();
 
         SparseLongArray childIds = mChildNodeIds;
@@ -1587,6 +1694,8 @@
         mSealed = false;
         mSourceNodeId = ROOT_NODE_ID;
         mParentNodeId = ROOT_NODE_ID;
+        mLabelForId = ROOT_NODE_ID;
+        mLabeledById = ROOT_NODE_ID;
         mWindowId = UNDEFINED;
         mConnectionId = UNDEFINED;
         mMovementGranularities = 0;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeProvider.java b/core/java/android/view/accessibility/AccessibilityNodeProvider.java
index b3f3cee..688cbdf 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeProvider.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeProvider.java
@@ -132,60 +132,4 @@
             int virtualViewId) {
         return null;
     }
-
-    /**
-     * Finds the accessibility focused {@link AccessibilityNodeInfo}. The search is
-     * relative to the virtual view, i.e. a descendant of the host View, with the
-     * given <code>virtualViewId</code> or the host View itself
-     * <code>virtualViewId</code> equals to {@link View#NO_ID}.
-     *
-     * <strong>Note:</strong> Normally the system is responsible to transparently find
-     *     accessibility focused view starting from a given root but for virtual view
-     *     hierarchies it is a responsibility of this provider's implementor to find
-     *     the accessibility focused virtual view.
-     *
-     * @param virtualViewId A client defined virtual view id which defined
-     *     the root of the tree in which to perform the search.
-     * @return A list of node info.
-     *
-     * @see #createAccessibilityNodeInfo(int)
-     * @see AccessibilityNodeInfo
-     *
-     * @hide
-     */
-    public AccessibilityNodeInfo findAccessibilityFocus(int virtualViewId) {
-        return null;
-    }
-
-    /**
-     * Finds {@link AccessibilityNodeInfo} to take accessibility focus in the given
-     * <code>direction</code>. The search is relative to the virtual view, i.e. a
-     * descendant of the host View, with the given <code>virtualViewId</code> or
-     * the host View itself <code>virtualViewId</code> equals to {@link View#NO_ID}.
-     *
-     * <strong>Note:</strong> Normally the system is responsible to transparently find
-     *     the next view to take accessibility focus but for virtual view hierarchies
-     *     it is a responsibility of this provider's implementor to compute the next
-     *     focusable.
-     *
-     * @param direction The direction in which to search for a focus candidate.
-     *     Values are
-     *     {@link View#ACCESSIBILITY_FOCUS_FORWARD},
-     *     {@link View#ACCESSIBILITY_FOCUS_BACKWARD},
-     *     {@link View#ACCESSIBILITY_FOCUS_UP},
-     *     {@link View#ACCESSIBILITY_FOCUS_DOWN},
-     *     {@link View#ACCESSIBILITY_FOCUS_LEFT},
-     *     {@link View#ACCESSIBILITY_FOCUS_RIGHT}.
-     * @param virtualViewId A client defined virtual view id which defined
-     *     the root of the tree in which to perform the search.
-     * @return A list of node info.
-     *
-     * @see #createAccessibilityNodeInfo(int)
-     * @see AccessibilityNodeInfo
-     *
-     * @hide
-     */
-    public AccessibilityNodeInfo accessibilityFocusSearch(int direction, int virtualViewId) {
-        return null;
-    }
 }
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 5c60a12..7147c57 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -168,6 +168,17 @@
     }
 
     /**
+     * Sets the window id.
+     *
+     * @param windowId The window id.
+     *
+     * @hide
+     */
+    public void setWindowId(int windowId) {
+        mSourceWindowId = windowId;
+    }
+
+    /**
      * Gets the id of the window from which the event comes from.
      *
      * @return The window id.
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index 292702a..9b39300 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -28,25 +28,25 @@
  */
 oneway interface IAccessibilityInteractionConnection {
 
-    void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, int windowLeft,
-        int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback,
-        int flags, int interrogatingPid, long interrogatingTid);
+    void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, int interactionId,
+        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
+        long interrogatingTid);
 
-    void findAccessibilityNodeInfoByViewId(long accessibilityNodeId, int viewId, int windowLeft,
-        int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback,
-        int flags, int interrogatingPid, long interrogatingTid);
+    void findAccessibilityNodeInfoByViewId(long accessibilityNodeId, int viewId, int interactionId,
+        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
+        long interrogatingTid);
 
-    void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, int windowLeft,
-        int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback,
-        int flags, int interrogatingPid, long interrogatingTid);
+    void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, int interactionId,
+        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
+        long interrogatingTid);
 
-    void findFocus(long accessibilityNodeId, int focusType, int windowLeft, int windowTop,
-        int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
-        int interrogatingPid, long interrogatingTid);
+    void findFocus(long accessibilityNodeId, int focusType, int interactionId,
+        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
+        long interrogatingTid);
 
-    void focusSearch(long accessibilityNodeId, int direction, int windowLeft, int windowTop,
-        int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
-        int interrogatingPid, long interrogatingTid);
+    void focusSearch(long accessibilityNodeId, int direction, int interactionId,
+        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
+        long interrogatingTid);
 
     void performAccessibilityAction(long accessibilityNodeId, int action, in Bundle arguments,
         int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 5b5134a..c3ef54c 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -20,6 +20,7 @@
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.accessibilityservice.IAccessibilityServiceClient;
+import android.content.ComponentName;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.IAccessibilityInteractionConnection;
@@ -34,18 +35,18 @@
  */
 interface IAccessibilityManager {
 
-    int addClient(IAccessibilityManagerClient client);
+    int addClient(IAccessibilityManagerClient client, int userId);
 
-    boolean sendAccessibilityEvent(in AccessibilityEvent uiEvent);
+    boolean sendAccessibilityEvent(in AccessibilityEvent uiEvent, int userId);
 
-    List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
+    List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId);
 
-    List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType);
+    List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, int userId);
 
-    void interrupt();
+    void interrupt(int userId);
 
     int addAccessibilityInteractionConnection(IWindow windowToken,
-        in IAccessibilityInteractionConnection connection);
+        in IAccessibilityInteractionConnection connection, int userId);
 
     void removeAccessibilityInteractionConnection(IWindow windowToken);
 
@@ -53,4 +54,7 @@
         in AccessibilityServiceInfo info);
 
     void unregisterUiTestAutomationService(IAccessibilityServiceClient client);
+
+    void temporaryEnableAccessibilityStateUntilKeyguardRemoved(in ComponentName service,
+            boolean touchExplorationEnabled);
 }
diff --git a/core/java/android/view/animation/RotateAnimation.java b/core/java/android/view/animation/RotateAnimation.java
index 67e0374..3c325d9 100644
--- a/core/java/android/view/animation/RotateAnimation.java
+++ b/core/java/android/view/animation/RotateAnimation.java
@@ -22,7 +22,7 @@
 
 /**
  * An animation that controls the rotation of an object. This rotation takes
- * place int the X-Y plane. You can specify the point to use for the center of
+ * place in the X-Y plane. You can specify the point to use for the center of
  * the rotation, where (0,0) is the top left point. If not specified, (0,0) is
  * the default rotation point.
  * 
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 131f0ae..08e30aa 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -34,6 +34,7 @@
 import android.os.Parcelable;
 import android.util.AttributeSet;
 import android.util.Printer;
+import android.util.Slog;
 import android.util.Xml;
 
 import java.io.IOException;
@@ -169,7 +170,10 @@
                             a.getBoolean(com.android.internal.R.styleable
                                     .InputMethod_Subtype_isAuxiliary, false),
                             a.getBoolean(com.android.internal.R.styleable
-                                    .InputMethod_Subtype_overridesImplicitlyEnabledSubtype, false));
+                                    .InputMethod_Subtype_overridesImplicitlyEnabledSubtype, false),
+                            a.getInt(com.android.internal.R.styleable
+                                    .InputMethod_Subtype_subtypeId, 0 /* use Arrays.hashCode */)
+                            );
                     if (!subtype.isAuxiliary()) {
                         mIsAuxIme = false;
                     }
@@ -194,6 +198,9 @@
                 final InputMethodSubtype subtype = additionalSubtypes.get(i);
                 if (!mSubtypes.contains(subtype)) {
                     mSubtypes.add(subtype);
+                } else {
+                    Slog.w(TAG, "Duplicated subtype definition found: "
+                            + subtype.getLocale() + ", " + subtype.getMode());
                 }
             }
         }
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index d2cc2d8..4a3f846 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -16,7 +16,7 @@
 
 package android.view.inputmethod;
 
-import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.SomeArgs;
 import com.android.internal.view.IInputConnectionWrapper;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodCallback;
@@ -35,6 +35,7 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.text.style.SuggestionSpan;
 import android.util.Log;
 import android.util.PrintWriterPrinter;
@@ -225,6 +226,13 @@
      */
     public static final int CONTROL_START_INITIAL = 1<<8;
 
+    /**
+     * Timeout in milliseconds for delivering a key to an IME.
+     */
+    static final long INPUT_METHOD_NOT_RESPONDING_TIMEOUT = 2500;
+
+    private static final int MAX_PENDING_EVENT_POOL_SIZE = 4;
+
     final IInputMethodManager mService;
     final Looper mMainLooper;
     
@@ -312,12 +320,17 @@
      */
     IInputMethodSession mCurMethod;
 
+    PendingEvent mPendingEventPool;
+    int mPendingEventPoolSize;
+    PendingEvent mFirstPendingEvent;
+
     // -----------------------------------------------------------
     
     static final int MSG_DUMP = 1;
     static final int MSG_BIND = 2;
     static final int MSG_UNBIND = 3;
     static final int MSG_SET_ACTIVE = 4;
+    static final int MSG_EVENT_TIMEOUT = 5;
     
     class H extends Handler {
         H(Looper looper) {
@@ -328,7 +341,7 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_DUMP: {
-                    HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
+                    SomeArgs args = (SomeArgs)msg.obj;
                     try {
                         doDump((FileDescriptor)args.arg1,
                                 (PrintWriter)args.arg2, (String[])args.arg3);
@@ -338,10 +351,14 @@
                     synchronized (args.arg4) {
                         ((CountDownLatch)args.arg4).countDown();
                     }
+                    args.recycle();
                     return;
                 }
                 case MSG_BIND: {
                     final InputBindResult res = (InputBindResult)msg.obj;
+                    if (DEBUG) {
+                        Log.i(TAG, "handleMessage: MSG_BIND " + res.sequence + "," + res.id);
+                    }
                     synchronized (mH) {
                         if (mBindSequence < 0 || mBindSequence != res.sequence) {
                             Log.w(TAG, "Ignoring onBind: cur seq=" + mBindSequence
@@ -358,6 +375,9 @@
                 }
                 case MSG_UNBIND: {
                     final int sequence = msg.arg1;
+                    if (DEBUG) {
+                        Log.i(TAG, "handleMessage: MSG_UNBIND " + sequence);
+                    }
                     boolean startInput = false;
                     synchronized (mH) {
                         if (mBindSequence == sequence) {
@@ -390,6 +410,9 @@
                 }
                 case MSG_SET_ACTIVE: {
                     final boolean active = msg.arg1 != 0;
+                    if (DEBUG) {
+                        Log.i(TAG, "handleMessage: MSG_SET_ACTIVE " + active + ", was " + mActive);
+                    }
                     synchronized (mH) {
                         mActive = active;
                         mFullscreenMode = false;
@@ -407,12 +430,32 @@
                             // Check focus again in case that "onWindowFocus" is called before
                             // handling this message.
                             if (mServedView != null && mServedView.hasWindowFocus()) {
-                                checkFocus(mHasBeenInactive);
+                                // "finishComposingText" has been already called above. So we
+                                // should not call mServedInputConnection.finishComposingText here.
+                                // Also, please note that this handler thread could be different
+                                // from a thread that created mServedView. That could happen
+                                // the current activity is running in the system process.
+                                // In that case, we really should not call
+                                // mServedInputConnection.finishComposingText.
+                                if (checkFocusNoStartInput(mHasBeenInactive, false)) {
+                                    startInputInner(null, 0, 0, 0);
+                                }
                             }
                         }
                     }
                     return;
                 }
+                case MSG_EVENT_TIMEOUT: {
+                    // Even though the message contains both the sequence number
+                    // and the PendingEvent object itself, we only pass the
+                    // sequence number to the timeoutEvent function because it's
+                    // possible for the PendingEvent object to be dequeued and
+                    // recycled concurrently.  To avoid a possible race, we make
+                    // a point of always looking up the PendingEvent within the
+                    // queue given only the sequence number of the event.
+                    timeoutEvent(msg.arg1);
+                    return;
+                }
             }
         }
     }
@@ -444,7 +487,7 @@
             // interface to the system.
             
             CountDownLatch latch = new CountDownLatch(1);
-            HandlerCaller.SomeArgs sargs = new HandlerCaller.SomeArgs();
+            SomeArgs sargs = SomeArgs.obtain();
             sargs.arg1 = fd;
             sargs.arg2 = fout;
             sargs.arg3 = args;
@@ -476,6 +519,18 @@
     };    
     
     final InputConnection mDummyInputConnection = new BaseInputConnection(this, false);
+
+    final IInputMethodCallback mInputMethodCallback = new IInputMethodCallback.Stub() {
+        @Override
+        public void finishedEvent(int seq, boolean handled) {
+            InputMethodManager.this.finishedEvent(seq, handled);
+        }
+
+        @Override
+        public void sessionCreated(IInputMethodSession session) {
+            // Stub -- not for use in the client.
+        }
+    };
     
     InputMethodManager(IInputMethodManager service, Looper looper) {
         mService = service;
@@ -1023,8 +1078,11 @@
         Handler vh = view.getHandler();
         if (vh == null) {
             // If the view doesn't have a handler, something has changed out
-            // from under us, so just bail.
-            if (DEBUG) Log.v(TAG, "ABORT input: no handler for view!");
+            // from under us, so just close the current input.
+            // If we don't close the current input, the current input method can remain on the
+            // screen without a connection.
+            if (DEBUG) Log.v(TAG, "ABORT input: no handler for view! Close current input.");
+            closeCurrentInput();
             return false;
         }
         if (vh.getLooper() != Looper.myLooper()) {
@@ -1105,6 +1163,7 @@
                     if (res.id != null) {
                         mBindSequence = res.sequence;
                         mCurMethod = res.method;
+                        mCurId = res.id;
                     } else if (mCurMethod == null) {
                         // This means there is no input method available.
                         if (DEBUG) Log.v(TAG, "ABORT input: no input method!");
@@ -1194,20 +1253,16 @@
         }
     }
 
-    private void checkFocus(boolean forceNewFocus) {
-        if (checkFocusNoStartInput(forceNewFocus)) {
-            startInputInner(null, 0, 0, 0);
-        }
-    }
-
     /**
      * @hide
      */
     public void checkFocus() {
-        checkFocus(false);
+        if (checkFocusNoStartInput(false, true)) {
+            startInputInner(null, 0, 0, 0);
+        }
     }
 
-    private boolean checkFocusNoStartInput(boolean forceNewFocus) {
+    private boolean checkFocusNoStartInput(boolean forceNewFocus, boolean finishComposingText) {
         // This is called a lot, so short-circuit before locking.
         if (mServedView == mNextServedView && !forceNewFocus) {
             return false;
@@ -1241,7 +1296,7 @@
             mServedConnecting = true;
         }
 
-        if (ic != null) {
+        if (finishComposingText && ic != null) {
             ic.finishComposingText();
         }
 
@@ -1286,7 +1341,7 @@
             controlFlags |= CONTROL_WINDOW_FIRST;
         }
         
-        if (checkFocusNoStartInput(forceNewFocus)) {
+        if (checkFocusNoStartInput(forceNewFocus, true)) {
             // We need to restart input on the current focus view.  This
             // should be done in conjunction with telling the system service
             // about the window gaining focus, to help make the transition
@@ -1511,76 +1566,184 @@
      * @hide
      */
     public void dispatchKeyEvent(Context context, int seq, KeyEvent key,
-            IInputMethodCallback callback) {
+            FinishedEventCallback callback) {
+        boolean handled = false;
         synchronized (mH) {
             if (DEBUG) Log.d(TAG, "dispatchKeyEvent");
-    
-            if (mCurMethod == null) {
-                try {
-                    callback.finishedEvent(seq, false);
-                } catch (RemoteException e) {
-                }
-                return;
-            }
-    
-            if (key.getAction() == KeyEvent.ACTION_DOWN
-                    && key.getKeyCode() == KeyEvent.KEYCODE_SYM) {
-                showInputMethodPicker();
-                try {
-                    callback.finishedEvent(seq, true);
-                } catch (RemoteException e) {
-                }
-                return;
-            }
-            try {
-                if (DEBUG) Log.v(TAG, "DISPATCH KEY: " + mCurMethod);
-                mCurMethod.dispatchKeyEvent(seq, key, callback);
-            } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId + " dropping: " + key, e);
-                try {
-                    callback.finishedEvent(seq, false);
-                } catch (RemoteException ex) {
+
+            if (mCurMethod != null) {
+                if (key.getAction() == KeyEvent.ACTION_DOWN
+                        && key.getKeyCode() == KeyEvent.KEYCODE_SYM) {
+                    showInputMethodPickerLocked();
+                    handled = true;
+                } else {
+                    try {
+                        if (DEBUG) Log.v(TAG, "DISPATCH KEY: " + mCurMethod);
+                        final long startTime = SystemClock.uptimeMillis();
+                        enqueuePendingEventLocked(startTime, seq, mCurId, callback);
+                        mCurMethod.dispatchKeyEvent(seq, key, mInputMethodCallback);
+                        return;
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "IME died: " + mCurId + " dropping: " + key, e);
+                    }
                 }
             }
         }
+
+        callback.finishedEvent(seq, handled);
     }
 
     /**
      * @hide
      */
-    void dispatchTrackballEvent(Context context, int seq, MotionEvent motion,
-            IInputMethodCallback callback) {
+    public void dispatchTrackballEvent(Context context, int seq, MotionEvent motion,
+            FinishedEventCallback callback) {
         synchronized (mH) {
             if (DEBUG) Log.d(TAG, "dispatchTrackballEvent");
-    
-            if (mCurMethod == null || mCurrentTextBoxAttribute == null) {
+
+            if (mCurMethod != null && mCurrentTextBoxAttribute != null) {
                 try {
-                    callback.finishedEvent(seq, false);
+                    if (DEBUG) Log.v(TAG, "DISPATCH TRACKBALL: " + mCurMethod);
+                    final long startTime = SystemClock.uptimeMillis();
+                    enqueuePendingEventLocked(startTime, seq, mCurId, callback);
+                    mCurMethod.dispatchTrackballEvent(seq, motion, mInputMethodCallback);
+                    return;
                 } catch (RemoteException e) {
+                    Log.w(TAG, "IME died: " + mCurId + " dropping trackball: " + motion, e);
                 }
-                return;
             }
-    
-            try {
-                if (DEBUG) Log.v(TAG, "DISPATCH TRACKBALL: " + mCurMethod);
-                mCurMethod.dispatchTrackballEvent(seq, motion, callback);
-            } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId + " dropping trackball: " + motion, e);
+        }
+
+        callback.finishedEvent(seq, false);
+    }
+
+    /**
+     * @hide
+     */
+    public void dispatchGenericMotionEvent(Context context, int seq, MotionEvent motion,
+            FinishedEventCallback callback) {
+        synchronized (mH) {
+            if (DEBUG) Log.d(TAG, "dispatchGenericMotionEvent");
+
+            if (mCurMethod != null && mCurrentTextBoxAttribute != null) {
                 try {
-                    callback.finishedEvent(seq, false);
-                } catch (RemoteException ex) {
+                    if (DEBUG) Log.v(TAG, "DISPATCH GENERIC MOTION: " + mCurMethod);
+                    final long startTime = SystemClock.uptimeMillis();
+                    enqueuePendingEventLocked(startTime, seq, mCurId, callback);
+                    mCurMethod.dispatchGenericMotionEvent(seq, motion, mInputMethodCallback);
+                    return;
+                } catch (RemoteException e) {
+                    Log.w(TAG, "IME died: " + mCurId + " dropping generic motion: " + motion, e);
                 }
             }
         }
+
+        callback.finishedEvent(seq, false);
+    }
+
+    void finishedEvent(int seq, boolean handled) {
+        final FinishedEventCallback callback;
+        synchronized (mH) {
+            PendingEvent p = dequeuePendingEventLocked(seq);
+            if (p == null) {
+                return; // spurious, event already finished or timed out
+            }
+            mH.removeMessages(MSG_EVENT_TIMEOUT, p);
+            callback = p.mCallback;
+            recyclePendingEventLocked(p);
+        }
+        callback.finishedEvent(seq, handled);
+    }
+
+    void timeoutEvent(int seq) {
+        final FinishedEventCallback callback;
+        synchronized (mH) {
+            PendingEvent p = dequeuePendingEventLocked(seq);
+            if (p == null) {
+                return; // spurious, event already finished or timed out
+            }
+            long delay = SystemClock.uptimeMillis() - p.mStartTime;
+            Log.w(TAG, "Timeout waiting for IME to handle input event after "
+                    + delay + "ms: " + p.mInputMethodId);
+            callback = p.mCallback;
+            recyclePendingEventLocked(p);
+        }
+        callback.finishedEvent(seq, false);
+    }
+
+    private void enqueuePendingEventLocked(
+            long startTime, int seq, String inputMethodId, FinishedEventCallback callback) {
+        PendingEvent p = obtainPendingEventLocked(startTime, seq, inputMethodId, callback);
+        p.mNext = mFirstPendingEvent;
+        mFirstPendingEvent = p;
+
+        Message msg = mH.obtainMessage(MSG_EVENT_TIMEOUT, seq, 0, p);
+        msg.setAsynchronous(true);
+        mH.sendMessageDelayed(msg, INPUT_METHOD_NOT_RESPONDING_TIMEOUT);
+    }
+
+    private PendingEvent dequeuePendingEventLocked(int seq) {
+        PendingEvent p = mFirstPendingEvent;
+        if (p == null) {
+            return null;
+        }
+        if (p.mSeq == seq) {
+            mFirstPendingEvent = p.mNext;
+        } else {
+            PendingEvent prev;
+            do {
+                prev = p;
+                p = p.mNext;
+                if (p == null) {
+                    return null;
+                }
+            } while (p.mSeq != seq);
+            prev.mNext = p.mNext;
+        }
+        p.mNext = null;
+        return p;
+    }
+
+    private PendingEvent obtainPendingEventLocked(
+            long startTime, int seq, String inputMethodId, FinishedEventCallback callback) {
+        PendingEvent p = mPendingEventPool;
+        if (p != null) {
+            mPendingEventPoolSize -= 1;
+            mPendingEventPool = p.mNext;
+            p.mNext = null;
+        } else {
+            p = new PendingEvent();
+        }
+
+        p.mStartTime = startTime;
+        p.mSeq = seq;
+        p.mInputMethodId = inputMethodId;
+        p.mCallback = callback;
+        return p;
+    }
+
+    private void recyclePendingEventLocked(PendingEvent p) {
+        p.mInputMethodId = null;
+        p.mCallback = null;
+
+        if (mPendingEventPoolSize < MAX_PENDING_EVENT_POOL_SIZE) {
+            mPendingEventPoolSize += 1;
+            p.mNext = mPendingEventPool;
+            mPendingEventPool = p;
+        }
     }
 
     public void showInputMethodPicker() {
         synchronized (mH) {
-            try {
-                mService.showInputMethodPickerFromClient(mClient);
-            } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId, e);
-            }
+            showInputMethodPickerLocked();
+        }
+    }
+
+    private void showInputMethodPickerLocked() {
+        try {
+            mService.showInputMethodPickerFromClient(mClient);
+        } catch (RemoteException e) {
+            Log.w(TAG, "IME died: " + mCurId, e);
         }
     }
 
@@ -1773,4 +1936,22 @@
                 + " mCursorCandStart=" + mCursorCandStart
                 + " mCursorCandEnd=" + mCursorCandEnd);
     }
+
+    /**
+     * Callback that is invoked when an input event that was dispatched to
+     * the IME has been finished.
+     * @hide
+     */
+    public interface FinishedEventCallback {
+        public void finishedEvent(int seq, boolean handled);
+    }
+
+    private static final class PendingEvent {
+        public PendingEvent mNext;
+
+        public long mStartTime;
+        public int mSeq;
+        public String mInputMethodId;
+        public FinishedEventCallback mCallback;
+    }
 }
diff --git a/core/java/android/view/inputmethod/InputMethodSession.java b/core/java/android/view/inputmethod/InputMethodSession.java
index ea6f5ee..6386299 100644
--- a/core/java/android/view/inputmethod/InputMethodSession.java
+++ b/core/java/android/view/inputmethod/InputMethodSession.java
@@ -138,6 +138,21 @@
     public void dispatchTrackballEvent(int seq, MotionEvent event, EventCallback callback);
 
     /**
+     * This method is called when there is a generic motion event.
+     *
+     * <p>
+     * If the input method wants to handle this event, return true, otherwise
+     * return false and the caller (i.e. the application) will handle the event.
+     *
+     * @param event The motion event.
+     *
+     * @return Whether the input method wants to handle this event.
+     *
+     * @see android.view.MotionEvent
+     */
+    public void dispatchGenericMotionEvent(int seq, MotionEvent event, EventCallback callback);
+
+    /**
      * Process a private command sent from the application to the input method.
      * This can be used to provide domain-specific features that are
      * only known between certain input methods and their clients.
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index b7c94a3..7895e6f 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -55,13 +55,14 @@
     private final int mSubtypeHashCode;
     private final int mSubtypeIconResId;
     private final int mSubtypeNameResId;
+    private final int mSubtypeId;
     private final String mSubtypeLocale;
     private final String mSubtypeMode;
     private final String mSubtypeExtraValue;
     private volatile HashMap<String, String> mExtraValueHashMapCache;
 
     /**
-     * Constructor.
+     * Constructor with no subtype ID specified, overridesImplicitlyEnabledSubtype not specified.
      * @param nameId Resource ID of the subtype name string. The string resource may have exactly
      * one %s in it. If there is, the %s part will be replaced with the locale's display name by
      * the formatter. Please refer to {@link #getDisplayName} for details.
@@ -87,7 +88,7 @@
     }
 
     /**
-     * Constructor.
+     * Constructor with no subtype ID specified.
      * @param nameId Resource ID of the subtype name string. The string resource may have exactly
      * one %s in it. If there is, the %s part will be replaced with the locale's display name by
      * the formatter. Please refer to {@link #getDisplayName} for details.
@@ -112,6 +113,41 @@
      */
     public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
             boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) {
+        this(nameId, iconId, locale, mode, extraValue, isAuxiliary,
+                overridesImplicitlyEnabledSubtype, 0);
+    }
+
+    /**
+     * Constructor.
+     * @param nameId Resource ID of the subtype name string. The string resource may have exactly
+     * one %s in it. If there is, the %s part will be replaced with the locale's display name by
+     * the formatter. Please refer to {@link #getDisplayName} for details.
+     * @param iconId Resource ID of the subtype icon drawable.
+     * @param locale The locale supported by the subtype
+     * @param mode The mode supported by the subtype
+     * @param extraValue The extra value of the subtype. This string is free-form, but the API
+     * supplies tools to deal with a key-value comma-separated list; see
+     * {@link #containsExtraValueKey} and {@link #getExtraValueOf}.
+     * @param isAuxiliary true when this subtype is auxiliary, false otherwise. An auxiliary
+     * subtype will not be shown in the list of enabled IMEs for choosing the current IME in
+     * the Settings even when this subtype is enabled. Please note that this subtype will still
+     * be shown in the list of IMEs in the IME switcher to allow the user to tentatively switch
+     * to this subtype while an IME is shown. The framework will never switch the current IME to
+     * this subtype by {@link android.view.inputmethod.InputMethodManager#switchToLastInputMethod}.
+     * The intent of having this flag is to allow for IMEs that are invoked in a one-shot way as
+     * auxiliary input mode, and return to the previous IME once it is finished (e.g. voice input).
+     * @param overridesImplicitlyEnabledSubtype true when this subtype should be enabled by default
+     * if no other subtypes in the IME are enabled explicitly. Note that a subtype with this
+     * parameter being true will not be shown in the list of subtypes in each IME's subtype enabler.
+     * Having an "automatic" subtype is an example use of this flag.
+     * @param id The unique ID for the subtype. The input method framework keeps track of enabled
+     * subtypes by ID. When the IME package gets upgraded, enabled IDs will stay enabled even if
+     * other attributes are different. If the ID is unspecified or 0,
+     * Arrays.hashCode(new Object[] {locale, mode, extraValue,
+     * isAuxiliary, overridesImplicitlyEnabledSubtype}) will be used instead.
+     */
+    public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
+            boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, int id) {
         mSubtypeNameResId = nameId;
         mSubtypeIconResId = iconId;
         mSubtypeLocale = locale != null ? locale : "";
@@ -119,8 +155,11 @@
         mSubtypeExtraValue = extraValue != null ? extraValue : "";
         mIsAuxiliary = isAuxiliary;
         mOverridesImplicitlyEnabledSubtype = overridesImplicitlyEnabledSubtype;
-        mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue,
-                mIsAuxiliary, mOverridesImplicitlyEnabledSubtype);
+        // If hashCode() of this subtype is 0 and you want to specify it as an id of this subtype,
+        // just specify 0 as this subtype's id. Then, this subtype's id is treated as 0.
+        mSubtypeHashCode = id != 0 ? id : hashCodeInternal(mSubtypeLocale, mSubtypeMode,
+                mSubtypeExtraValue, mIsAuxiliary, mOverridesImplicitlyEnabledSubtype);
+        mSubtypeId = id;
     }
 
     InputMethodSubtype(Parcel source) {
@@ -135,8 +174,8 @@
         mSubtypeExtraValue = s != null ? s : "";
         mIsAuxiliary = (source.readInt() == 1);
         mOverridesImplicitlyEnabledSubtype = (source.readInt() == 1);
-        mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue,
-                mIsAuxiliary, mOverridesImplicitlyEnabledSubtype);
+        mSubtypeHashCode = source.readInt();
+        mSubtypeId = source.readInt();
     }
 
     /**
@@ -288,6 +327,9 @@
     public boolean equals(Object o) {
         if (o instanceof InputMethodSubtype) {
             InputMethodSubtype subtype = (InputMethodSubtype) o;
+            if (subtype.mSubtypeId != 0 || mSubtypeId != 0) {
+                return (subtype.hashCode() == hashCode());
+            }
             return (subtype.hashCode() == hashCode())
                 && (subtype.getNameResId() == getNameResId())
                 && (subtype.getMode().equals(getMode()))
@@ -313,6 +355,8 @@
         dest.writeString(mSubtypeExtraValue);
         dest.writeInt(mIsAuxiliary ? 1 : 0);
         dest.writeInt(mOverridesImplicitlyEnabledSubtype ? 1 : 0);
+        dest.writeInt(mSubtypeHashCode);
+        dest.writeInt(mSubtypeId);
     }
 
     public static final Parcelable.Creator<InputMethodSubtype> CREATOR
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index 81b36db..e0e19b9 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -217,6 +217,12 @@
     public SpellCheckerSubtype getCurrentSpellCheckerSubtype(
             boolean allowImplicitlySelectedSubtype) {
         try {
+            if (sService == null) {
+                // TODO: This is a workaround. Needs to investigate why sService could be null
+                // here.
+                Log.e(TAG, "sService is null.");
+                return null;
+            }
             // Passing null as a locale until we support multiple enabled spell checker subtypes.
             return sService.getCurrentSpellCheckerSubtype(null, allowImplicitlySelectedSubtype);
         } catch (RemoteException e) {
diff --git a/core/java/android/webkit/AccessibilityInjector.java b/core/java/android/webkit/AccessibilityInjector.java
index c3654bd..008a615 100644
--- a/core/java/android/webkit/AccessibilityInjector.java
+++ b/core/java/android/webkit/AccessibilityInjector.java
@@ -18,9 +18,14 @@
 
 import android.content.Context;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.speech.tts.TextToSpeech;
+import android.speech.tts.TextToSpeech.Engine;
+import android.speech.tts.TextToSpeech.OnInitListener;
+import android.speech.tts.UtteranceProgressListener;
+import android.util.Log;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.accessibility.AccessibilityManager;
@@ -44,6 +49,10 @@
  * APIs.
  */
 class AccessibilityInjector {
+    private static final String TAG = AccessibilityInjector.class.getSimpleName();
+
+    private static boolean DEBUG = false;
+
     // The WebViewClassic this injector is responsible for managing.
     private final WebViewClassic mWebViewClassic;
 
@@ -88,7 +97,32 @@
 
     // Template for JavaScript that performs AndroidVox actions.
     private static final String ACCESSIBILITY_ANDROIDVOX_TEMPLATE =
-            "cvox.AndroidVox.performAction('%1s')";
+            "(function() {" +
+                    "  if ((typeof(cvox) != 'undefined')" +
+                    "      && (cvox != null)" +
+                    "      && (typeof(cvox.ChromeVox) != 'undefined')" +
+                    "      && (cvox.ChromeVox != null)" +
+                    "      && (typeof(cvox.AndroidVox) != 'undefined')" +
+                    "      && (cvox.AndroidVox != null)" +
+                    "      && cvox.ChromeVox.isActive) {" +
+                    "    return cvox.AndroidVox.performAction('%1s');" +
+                    "  } else {" +
+                    "    return false;" +
+                    "  }" +
+                    "})()";
+
+    // JS code used to shut down an active AndroidVox instance.
+    private static final String TOGGLE_CVOX_TEMPLATE =
+            "javascript:(function() {" +
+                    "  if ((typeof(cvox) != 'undefined')" +
+                    "      && (cvox != null)" +
+                    "      && (typeof(cvox.ChromeVox) != 'undefined')" +
+                    "      && (cvox.ChromeVox != null)" +
+                    "      && (typeof(cvox.ChromeVox.host) != 'undefined')" +
+                    "      && (cvox.ChromeVox.host != null)) {" +
+                    "    cvox.ChromeVox.host.activateOrDeactivateChromeVox(%b);" +
+                    "  }" +
+                    "})();";
 
     /**
      * Creates an instance of the AccessibilityInjector based on
@@ -105,10 +139,26 @@
     }
 
     /**
+     * If JavaScript is enabled, pauses or resumes AndroidVox.
+     *
+     * @param enabled Whether feedback should be enabled.
+     */
+    public void toggleAccessibilityFeedback(boolean enabled) {
+        if (!isAccessibilityEnabled() || !isJavaScriptEnabled()) {
+            return;
+        }
+
+        toggleAndroidVox(enabled);
+
+        if (!enabled && (mTextToSpeech != null)) {
+            mTextToSpeech.stop();
+        }
+    }
+
+    /**
      * Attempts to load scripting interfaces for accessibility.
      * <p>
-     * This should be called when the window is attached.
-     * </p>
+     * This should only be called before a page loads.
      */
     public void addAccessibilityApisIfNecessary() {
         if (!isAccessibilityEnabled() || !isJavaScriptEnabled()) {
@@ -122,15 +172,37 @@
     /**
      * Attempts to unload scripting interfaces for accessibility.
      * <p>
-     * This should be called when the window is detached.
-     * </p>
+     * This should only be called before a page loads.
      */
-    public void removeAccessibilityApisIfNecessary() {
+    private void removeAccessibilityApisIfNecessary() {
         removeTtsApis();
         removeCallbackApis();
     }
 
     /**
+     * Destroys this accessibility injector.
+     */
+    public void destroy() {
+        if (mTextToSpeech != null) {
+            mTextToSpeech.shutdown();
+            mTextToSpeech = null;
+        }
+
+        if (mCallback != null) {
+            mCallback = null;
+        }
+    }
+
+    private void toggleAndroidVox(boolean state) {
+        if (!mAccessibilityScriptInjected) {
+            return;
+        }
+
+        final String code = String.format(TOGGLE_CVOX_TEMPLATE, state);
+        mWebView.loadUrl(code);
+    }
+
+    /**
      * Initializes an {@link AccessibilityNodeInfo} with the actions and
      * movement granularity levels supported by this
      * {@link AccessibilityInjector}.
@@ -196,7 +268,7 @@
         if (mAccessibilityScriptInjected) {
             return sendActionToAndroidVox(action, arguments);
         }
-        
+
         if (mAccessibilityInjectorFallback != null) {
             return mAccessibilityInjectorFallback.performAccessibilityAction(action, arguments);
         }
@@ -262,6 +334,10 @@
      */
     public void onPageStarted(String url) {
         mAccessibilityScriptInjected = false;
+        if (DEBUG) {
+            Log.w(TAG, "[" + mWebView.hashCode() + "] Started loading new page");
+        }
+        addAccessibilityApisIfNecessary();
     }
 
     /**
@@ -274,22 +350,75 @@
      */
     public void onPageFinished(String url) {
         if (!isAccessibilityEnabled()) {
-            mAccessibilityScriptInjected = false;
             toggleFallbackAccessibilityInjector(false);
             return;
         }
 
-        if (!shouldInjectJavaScript(url)) {
-            toggleFallbackAccessibilityInjector(true);
-            return;
-        }
+        toggleFallbackAccessibilityInjector(true);
 
+        if (shouldInjectJavaScript(url)) {
+            // If we're supposed to use the JS screen reader, request a
+            // callback to confirm that CallbackHandler is working.
+            if (DEBUG) {
+                Log.d(TAG, "[" + mWebView.hashCode() + "] Request callback ");
+            }
+
+            mCallback.requestCallback(mWebView, mInjectScriptRunnable);
+        }
+    }
+
+    /**
+     * Runnable used to inject the JavaScript-based screen reader if the
+     * {@link CallbackHandler} API was successfully exposed to JavaScript.
+     */
+    private Runnable mInjectScriptRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (DEBUG) {
+                Log.d(TAG, "[" + mWebView.hashCode() + "] Received callback");
+            }
+
+            injectJavaScript();
+        }
+    };
+
+    /**
+     * Called by {@link #mInjectScriptRunnable} to inject the JavaScript-based
+     * screen reader after confirming that the {@link CallbackHandler} API is
+     * functional.
+     */
+    private void injectJavaScript() {
         toggleFallbackAccessibilityInjector(false);
 
-        final String injectionUrl = getScreenReaderInjectionUrl();
-        mWebView.loadUrl(injectionUrl);
+        if (!mAccessibilityScriptInjected) {
+            mAccessibilityScriptInjected = true;
+            final String injectionUrl = getScreenReaderInjectionUrl();
+            mWebView.loadUrl(injectionUrl);
+            if (DEBUG) {
+                Log.d(TAG, "[" + mWebView.hashCode() + "] Loading screen reader into WebView");
+            }
+        } else {
+            if (DEBUG) {
+                Log.w(TAG, "[" + mWebView.hashCode() + "] Attempted to inject screen reader twice");
+            }
+        }
+    }
 
-        mAccessibilityScriptInjected = true;
+    /**
+     * Adjusts the accessibility injection state to reflect changes in the
+     * JavaScript enabled state.
+     *
+     * @param enabled Whether JavaScript is enabled.
+     */
+    public void updateJavaScriptEnabled(boolean enabled) {
+        if (enabled) {
+            addAccessibilityApisIfNecessary();
+        } else {
+            removeAccessibilityApisIfNecessary();
+        }
+
+        // We have to reload the page after adding or removing APIs.
+        mWebView.reload();
     }
 
     /**
@@ -347,11 +476,11 @@
      * been done.
      */
     private void addTtsApis() {
-        if (mTextToSpeech != null) {
-            return;
+        if (mTextToSpeech == null) {
+            mTextToSpeech = new TextToSpeechWrapper(mContext);
         }
-        mTextToSpeech = new TextToSpeechWrapper(mContext);
-        mWebViewClassic.addJavascriptInterface(mTextToSpeech, ALIAS_TTS_JS_INTERFACE, true);
+
+        mWebView.addJavascriptInterface(mTextToSpeech, ALIAS_TTS_JS_INTERFACE);
     }
 
     /**
@@ -359,32 +488,29 @@
      * already been done.
      */
     private void removeTtsApis() {
-        if (mTextToSpeech == null) {
-            return;
+        if (mTextToSpeech != null) {
+            mTextToSpeech.stop();
+            mTextToSpeech.shutdown();
+            mTextToSpeech = null;
         }
 
         mWebView.removeJavascriptInterface(ALIAS_TTS_JS_INTERFACE);
-        mTextToSpeech.stop();
-        mTextToSpeech.shutdown();
-        mTextToSpeech = null;
     }
 
     private void addCallbackApis() {
-        if (mCallback != null) {
-            return;
+        if (mCallback == null) {
+            mCallback = new CallbackHandler(ALIAS_TRAVERSAL_JS_INTERFACE);
         }
 
-        mCallback = new CallbackHandler(ALIAS_TRAVERSAL_JS_INTERFACE);
-        mWebViewClassic.addJavascriptInterface(mCallback, ALIAS_TRAVERSAL_JS_INTERFACE, true);
+        mWebView.addJavascriptInterface(mCallback, ALIAS_TRAVERSAL_JS_INTERFACE);
     }
 
     private void removeCallbackApis() {
-        if (mCallback == null) {
-            return;
+        if (mCallback != null) {
+            mCallback = null;
         }
 
         mWebView.removeJavascriptInterface(ALIAS_TRAVERSAL_JS_INTERFACE);
-        mCallback = null;
     }
 
     /**
@@ -410,6 +536,8 @@
             }
         } catch (URISyntaxException e) {
             // Do nothing.
+        } catch (IllegalArgumentException e) {
+            // Catch badly-formed URLs.
         }
 
         return ACCESSIBILITY_SCRIPT_INJECTION_UNDEFINED;
@@ -446,7 +574,12 @@
      *         settings.
      */
     private boolean isJavaScriptEnabled() {
-        return mWebView.getSettings().getJavaScriptEnabled();
+        final WebSettings settings = mWebView.getSettings();
+        if (settings == null) {
+            return false;
+        }
+
+        return settings.getJavaScriptEnabled();
     }
 
     /**
@@ -502,7 +635,6 @@
 
         final String jsonString = mAccessibilityJSONObject.toString();
         final String jsCode = String.format(ACCESSIBILITY_ANDROIDVOX_TEMPLATE, jsonString);
-        if (mCallback == null) return false;
         return mCallback.performAction(mWebView, jsCode);
     }
 
@@ -510,35 +642,151 @@
      * Used to protect the TextToSpeech class, only exposing the methods we want to expose.
      */
     private static class TextToSpeechWrapper {
-        private TextToSpeech mTextToSpeech;
+        private static final String WRAP_TAG = TextToSpeechWrapper.class.getSimpleName();
+
+        private final HashMap<String, String> mTtsParams;
+        private final TextToSpeech mTextToSpeech;
+
+        /**
+         * Whether this wrapper is ready to speak. If this is {@code true} then
+         * {@link #mShutdown} is guaranteed to be {@code false}.
+         */
+        private volatile boolean mReady;
+
+        /**
+         * Whether this wrapper was shut down. If this is {@code true} then
+         * {@link #mReady} is guaranteed to be {@code false}.
+         */
+        private volatile boolean mShutdown;
 
         public TextToSpeechWrapper(Context context) {
+            if (DEBUG) {
+                Log.d(WRAP_TAG, "[" + hashCode() + "] Initializing text-to-speech on thread "
+                        + Thread.currentThread().getId() + "...");
+            }
+
             final String pkgName = context.getPackageName();
-            mTextToSpeech = new TextToSpeech(context, null, null, pkgName + ".**webview**", true);
+
+            mReady = false;
+            mShutdown = false;
+
+            mTtsParams = new HashMap<String, String>();
+            mTtsParams.put(Engine.KEY_PARAM_UTTERANCE_ID, WRAP_TAG);
+
+            mTextToSpeech = new TextToSpeech(
+                    context, mInitListener, null, pkgName + ".**webview**", true);
+            mTextToSpeech.setOnUtteranceProgressListener(mErrorListener);
         }
 
         @JavascriptInterface
         @SuppressWarnings("unused")
         public boolean isSpeaking() {
-            return mTextToSpeech.isSpeaking();
+            synchronized (mTextToSpeech) {
+                if (!mReady) {
+                    return false;
+                }
+
+                return mTextToSpeech.isSpeaking();
+            }
         }
 
         @JavascriptInterface
         @SuppressWarnings("unused")
         public int speak(String text, int queueMode, HashMap<String, String> params) {
-            return mTextToSpeech.speak(text, queueMode, params);
+            synchronized (mTextToSpeech) {
+                if (!mReady) {
+                    if (DEBUG) {
+                        Log.w(WRAP_TAG, "[" + hashCode() + "] Attempted to speak before TTS init");
+                    }
+                    return TextToSpeech.ERROR;
+                } else {
+                    if (DEBUG) {
+                        Log.i(WRAP_TAG, "[" + hashCode() + "] Speak called from JS binder");
+                    }
+                }
+
+                return mTextToSpeech.speak(text, queueMode, params);
+            }
         }
 
         @JavascriptInterface
         @SuppressWarnings("unused")
         public int stop() {
-            return mTextToSpeech.stop();
+            synchronized (mTextToSpeech) {
+                if (!mReady) {
+                    if (DEBUG) {
+                        Log.w(WRAP_TAG, "[" + hashCode() + "] Attempted to stop before initialize");
+                    }
+                    return TextToSpeech.ERROR;
+                } else {
+                    if (DEBUG) {
+                        Log.i(WRAP_TAG, "[" + hashCode() + "] Stop called from JS binder");
+                    }
+                }
+
+                return mTextToSpeech.stop();
+            }
         }
 
         @SuppressWarnings("unused")
         protected void shutdown() {
-            mTextToSpeech.shutdown();
+            synchronized (mTextToSpeech) {
+                if (!mReady) {
+                    if (DEBUG) {
+                        Log.w(WRAP_TAG, "[" + hashCode() + "] Called shutdown before initialize");
+                    }
+                } else {
+                    if (DEBUG) {
+                        Log.i(WRAP_TAG, "[" + hashCode() + "] Shutting down text-to-speech from "
+                                + "thread " + Thread.currentThread().getId() + "...");
+                    }
+                }
+                mShutdown = true;
+                mReady = false;
+                mTextToSpeech.shutdown();
+            }
         }
+
+        private final OnInitListener mInitListener = new OnInitListener() {
+            @Override
+            public void onInit(int status) {
+                synchronized (mTextToSpeech) {
+                    if (!mShutdown && (status == TextToSpeech.SUCCESS)) {
+                        if (DEBUG) {
+                            Log.d(WRAP_TAG, "[" + TextToSpeechWrapper.this.hashCode()
+                                    + "] Initialized successfully");
+                        }
+                        mReady = true;
+                    } else {
+                        if (DEBUG) {
+                            Log.w(WRAP_TAG, "[" + TextToSpeechWrapper.this.hashCode()
+                                    + "] Failed to initialize");
+                        }
+                        mReady = false;
+                    }
+                }
+            }
+        };
+
+        private final UtteranceProgressListener mErrorListener = new UtteranceProgressListener() {
+            @Override
+            public void onStart(String utteranceId) {
+                // Do nothing.
+            }
+
+            @Override
+            public void onError(String utteranceId) {
+                if (DEBUG) {
+                    Log.w(WRAP_TAG, "[" + TextToSpeechWrapper.this.hashCode()
+                            + "] Failed to speak utterance");
+                }
+            }
+
+            @Override
+            public void onDone(String utteranceId) {
+                // Do nothing.
+            }
+        };
     }
 
     /**
@@ -554,12 +802,16 @@
         private final AtomicInteger mResultIdCounter = new AtomicInteger();
         private final Object mResultLock = new Object();
         private final String mInterfaceName;
+        private final Handler mMainHandler;
+
+        private Runnable mCallbackRunnable;
 
         private boolean mResult = false;
-        private long mResultId = -1;
+        private int mResultId = -1;
 
         private CallbackHandler(String interfaceName) {
             mInterfaceName = interfaceName;
+            mMainHandler = new Handler();
         }
 
         /**
@@ -608,24 +860,53 @@
          * @return Whether the result was received.
          */
         private boolean waitForResultTimedLocked(int resultId) {
-            long waitTimeMillis = RESULT_TIMEOUT;
             final long startTimeMillis = SystemClock.uptimeMillis();
+
+            if (DEBUG) {
+                Log.d(TAG, "Waiting for CVOX result with ID " + resultId + "...");
+            }
+
             while (true) {
+                // Fail if we received a callback from the future.
+                if (mResultId > resultId) {
+                    if (DEBUG) {
+                        Log.w(TAG, "Aborted CVOX result");
+                    }
+                    return false;
+                }
+
+                final long elapsedTimeMillis = (SystemClock.uptimeMillis() - startTimeMillis);
+
+                // Succeed if we received the callback we were expecting.
+                if (DEBUG) {
+                    Log.w(TAG, "Check " + mResultId + " versus expected " + resultId);
+                }
+                if (mResultId == resultId) {
+                    if (DEBUG) {
+                        Log.w(TAG, "Received CVOX result after " + elapsedTimeMillis + " ms");
+                    }
+                    return true;
+                }
+
+                final long waitTimeMillis = (RESULT_TIMEOUT - elapsedTimeMillis);
+
+                // Fail if we've already exceeded the timeout.
+                if (waitTimeMillis <= 0) {
+                    if (DEBUG) {
+                        Log.w(TAG, "Timed out while waiting for CVOX result");
+                    }
+                    return false;
+                }
+
                 try {
-                    if (mResultId == resultId) {
-                        return true;
-                    }
-                    if (mResultId > resultId) {
-                        return false;
-                    }
-                    final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
-                    waitTimeMillis = RESULT_TIMEOUT - elapsedTimeMillis;
-                    if (waitTimeMillis <= 0) {
-                        return false;
+                    if (DEBUG) {
+                        Log.w(TAG, "Start waiting...");
                     }
                     mResultLock.wait(waitTimeMillis);
                 } catch (InterruptedException ie) {
-                    /* ignore */
+                    if (DEBUG) {
+                        Log.w(TAG, "Interrupted while waiting for CVOX result");
+                    }
                 }
             }
         }
@@ -640,10 +921,13 @@
         @JavascriptInterface
         @SuppressWarnings("unused")
         public void onResult(String id, String result) {
-            final long resultId;
+            if (DEBUG) {
+                Log.w(TAG, "Saw CVOX result of '" + result + "' for ID " + id);
+            }
+            final int resultId;
 
             try {
-                resultId = Long.parseLong(id);
+                resultId = Integer.parseInt(id);
             } catch (NumberFormatException e) {
                 return;
             }
@@ -652,9 +936,35 @@
                 if (resultId > mResultId) {
                     mResult = Boolean.parseBoolean(result);
                     mResultId = resultId;
+                } else {
+                    if (DEBUG) {
+                        Log.w(TAG, "Result with ID " + resultId + " was stale vesus " + mResultId);
+                    }
                 }
                 mResultLock.notifyAll();
             }
         }
+
+        /**
+         * Requests a callback to ensure that the JavaScript interface for this
+         * object has been added successfully.
+         *
+         * @param webView The web view to request a callback from.
+         * @param callbackRunnable Runnable to execute if a callback is received.
+         */
+        public void requestCallback(WebView webView, Runnable callbackRunnable) {
+            mCallbackRunnable = callbackRunnable;
+
+            webView.loadUrl("javascript:(function() { " + mInterfaceName + ".callback(); })();");
+        }
+
+        @JavascriptInterface
+        @SuppressWarnings("unused")
+        public void callback() {
+            if (mCallbackRunnable != null) {
+                mMainHandler.post(mCallbackRunnable);
+                mCallbackRunnable = null;
+            }
+        }
     }
 }
diff --git a/core/java/android/webkit/BrowserDownloadListener.java b/core/java/android/webkit/BrowserDownloadListener.java
new file mode 100644
index 0000000..724cc62
--- /dev/null
+++ b/core/java/android/webkit/BrowserDownloadListener.java
@@ -0,0 +1,57 @@
+/*
+ * 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.webkit;
+
+/**
+ * An abstract download listener that allows passing extra information as
+ * part of onDownloadStart callback.
+ * @hide
+ */
+public abstract class BrowserDownloadListener implements DownloadListener {
+
+    /**
+     * Notify the host application that a file should be downloaded
+     * @param url The full url to the content that should be downloaded
+     * @param userAgent the user agent to be used for the download.
+     * @param contentDisposition Content-disposition http header, if
+     *                           present.
+     * @param mimetype The mimetype of the content reported by the server
+     * @param referer The referer associated with this url
+     * @param contentLength The file size reported by the server
+     */
+    public abstract void onDownloadStart(String url, String userAgent,
+            String contentDisposition, String mimetype, String referer,
+            long contentLength);
+
+
+    /**
+     * Notify the host application that a file should be downloaded
+     * @param url The full url to the content that should be downloaded
+     * @param userAgent the user agent to be used for the download.
+     * @param contentDisposition Content-disposition http header, if
+     *                           present.
+     * @param mimetype The mimetype of the content reported by the server
+     * @param contentLength The file size reported by the server
+     */
+    @Override
+    public void onDownloadStart(String url, String userAgent,
+            String contentDisposition, String mimetype, long contentLength) {
+
+        onDownloadStart(url, userAgent, contentDisposition, mimetype, null,
+                      contentLength);
+    }
+}
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 9e454a7..4dbca23 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -74,6 +74,7 @@
     private final CallbackProxy mCallbackProxy;
     private final WebSettingsClassic mSettings;
     private final Context mContext;
+    private final WebViewDatabaseClassic mDatabase;
     private final WebViewCore mWebViewCore;
     /* package */ boolean mLoadInitFromJava;
     private int mLoadType;
@@ -106,9 +107,6 @@
     // Key store handler when Chromium HTTP stack is used.
     private KeyStoreHandler mKeyStoreHandler = null;
 
-    // Implementation of the searchbox API.
-    private final SearchBoxImpl mSearchBox;
-
     // message ids
     // a message posted when a frame loading is completed
     static final int FRAME_COMPLETED = 1001;
@@ -251,10 +249,9 @@
         mSettings = settings;
         mContext = context;
         mCallbackProxy = proxy;
+        mDatabase = WebViewDatabaseClassic.getInstance(appContext);
         mWebViewCore = w;
 
-        mSearchBox = new SearchBoxImpl(mWebViewCore, mCallbackProxy);
-
         AssetManager am = context.getAssets();
         nativeCreateFrame(w, am, proxy.getBackForwardList());
 
@@ -432,8 +429,7 @@
             if (h != null) {
                 String url = WebTextView.urlForAutoCompleteData(h.getUrl());
                 if (url != null) {
-                    WebViewDatabaseClassic.getInstance(mContext).setFormData(
-                            url, data);
+                    mDatabase.setFormData(url, data);
                 }
             }
         }
@@ -505,9 +501,8 @@
                     if (item != null) {
                         WebAddress uri = new WebAddress(item.getUrl());
                         String schemePlusHost = uri.getScheme() + uri.getHost();
-                        String[] up =
-                                WebViewDatabaseClassic.getInstance(mContext)
-                                        .getUsernamePassword(schemePlusHost);
+                        String[] up = mDatabase.getUsernamePassword(
+                                schemePlusHost);
                         if (up != null && up[0] != null) {
                             setUsernamePassword(up[0], up[1]);
                         }
@@ -613,9 +608,11 @@
      * is to allow access to inherited methods (no annotation needed). This is only
      * used when js objects are passed through a constructor (via a hidden constructor).
      *
+     * @TODO change the default behavior to be compatible with the public addjavascriptinterface
      */
     private void addJavaScriptObjects(Map<String, Object> javascriptInterfaces) {
 
+        // TODO in a separate CL provide logic to enable annotations for API level JB_MR1 and above.
         if (javascriptInterfaces == null) return;
         Iterator<String> iter = javascriptInterfaces.keySet().iterator();
         while (iter.hasNext())  {
@@ -825,10 +822,10 @@
             // the post data (there could be another form on the
             // page and that was posted instead.
             String postString = new String(postData);
-            WebViewDatabaseClassic db = WebViewDatabaseClassic.getInstance(mContext);
             if (postString.contains(URLEncoder.encode(username)) &&
                     postString.contains(URLEncoder.encode(password))) {
-                String[] saved = db.getUsernamePassword(schemePlusHost);
+                String[] saved = mDatabase.getUsernamePassword(
+                        schemePlusHost);
                 if (saved != null) {
                     // null username implies that user has chosen not to
                     // save password
@@ -836,8 +833,7 @@
                         // non-null username implies that user has
                         // chosen to save password, so update the
                         // recorded password
-                        db.setUsernamePassword(schemePlusHost, username,
-                                password);
+                        mDatabase.setUsernamePassword(schemePlusHost, username, password);
                     }
                 } else {
                     // CallbackProxy will handle creating the resume
@@ -1029,7 +1025,7 @@
     }
 
     private float density() {
-        return mContext.getResources().getDisplayMetrics().density;
+        return WebViewCore.getFixedDisplayDensity(mContext);
     }
 
     /**
@@ -1163,7 +1159,7 @@
      * DownloadListener.
      */
     private void downloadStart(String url, String userAgent,
-            String contentDisposition, String mimeType, long contentLength) {
+            String contentDisposition, String mimeType, String referer, long contentLength) {
         // This will only work if the url ends with the filename
         if (mimeType.isEmpty()) {
             try {
@@ -1183,7 +1179,7 @@
             mKeyStoreHandler = new KeyStoreHandler(mimeType);
         } else {
             mCallbackProxy.onDownloadStart(url, userAgent,
-                contentDisposition, mimeType, contentLength);
+                contentDisposition, mimeType, referer, contentLength);
         }
     }
 
@@ -1216,10 +1212,6 @@
         }
     }
 
-    /*package*/ SearchBox getSearchBox() {
-        return mSearchBox;
-    }
-
     /**
      * Called by JNI when processing the X-Auto-Login header.
      */
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index f0e6ff0..52f41e6 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -32,6 +32,7 @@
 /**
  * Manages the HTTP cache used by an application's {@link WebView} instances.
  * @deprecated Access to the HTTP cache will be removed in a future release.
+ * @hide Since {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
  */
 // The class CacheManager provides the persistent cache of content that is
 // received over the network. The component handles parsing of HTTP headers and
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 2d9f60d..a326da2 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -71,7 +71,7 @@
     // Start with 100 to indicate it is not in load for the empty page.
     private volatile int mLatestProgress = 100;
     // Back/Forward list
-    private final WebBackForwardList mBackForwardList;
+    private final WebBackForwardListClassic mBackForwardList;
     // Back/Forward list client
     private volatile WebBackForwardListClient mWebBackForwardListClient;
     // Used to call startActivity during url override.
@@ -117,12 +117,8 @@
     private static final int ADD_HISTORY_ITEM                     = 135;
     private static final int HISTORY_INDEX_CHANGED                = 136;
     private static final int AUTH_CREDENTIALS                     = 137;
-    private static final int SET_INSTALLABLE_WEBAPP               = 138;
-    private static final int NOTIFY_SEARCHBOX_LISTENERS           = 139;
     private static final int AUTO_LOGIN                           = 140;
     private static final int CLIENT_CERT_REQUEST                  = 141;
-    private static final int SEARCHBOX_IS_SUPPORTED_CALLBACK      = 142;
-    private static final int SEARCHBOX_DISPATCH_COMPLETE_CALLBACK = 143;
     private static final int PROCEEDED_AFTER_SSL_ERROR            = 144;
 
     // Message triggered by the client to resume execution
@@ -188,7 +184,7 @@
         // Used to start a default activity.
         mContext = context;
         mWebView = w;
-        mBackForwardList = new WebBackForwardList(this);
+        mBackForwardList = new WebBackForwardListClassic(this);
     }
 
     protected synchronized void blockMessages() {
@@ -249,7 +245,7 @@
      * Get the Back/Forward list to return to the user or to update the cached
      * history list.
      */
-    public WebBackForwardList getBackForwardList() {
+    public WebBackForwardListClassic getBackForwardList() {
         return mBackForwardList;
     }
 
@@ -403,17 +399,18 @@
                 break;
 
             case PROCEEDED_AFTER_SSL_ERROR:
-                if (mWebViewClient != null) {
-                    mWebViewClient.onProceededAfterSslError(mWebView.getWebView(),
+                if (mWebViewClient != null && mWebViewClient instanceof WebViewClientClassicExt) {
+                    ((WebViewClientClassicExt) mWebViewClient).onProceededAfterSslError(
+                            mWebView.getWebView(),
                             (SslError) msg.obj);
                 }
                 break;
 
             case CLIENT_CERT_REQUEST:
-                if (mWebViewClient != null) {
-                    HashMap<String, Object> map =
-                        (HashMap<String, Object>) msg.obj;
-                    mWebViewClient.onReceivedClientCertRequest(mWebView.getWebView(),
+                if (mWebViewClient != null  && mWebViewClient instanceof WebViewClientClassicExt) {
+                    HashMap<String, Object> map = (HashMap<String, Object>) msg.obj;
+                    ((WebViewClientClassicExt) mWebViewClient).onReceivedClientCertRequest(
+                            mWebView.getWebView(),
                             (ClientCertRequestHandler) map.get("handler"),
                             (String) map.get("host_and_port"));
                 }
@@ -452,10 +449,16 @@
                     String contentDisposition =
                         msg.getData().getString("contentDisposition");
                     String mimetype = msg.getData().getString("mimetype");
+                    String referer = msg.getData().getString("referer");
                     Long contentLength = msg.getData().getLong("contentLength");
 
-                    mDownloadListener.onDownloadStart(url, userAgent,
-                            contentDisposition, mimetype, contentLength);
+                    if (mDownloadListener instanceof BrowserDownloadListener) {
+                        ((BrowserDownloadListener) mDownloadListener).onDownloadStart(url,
+                             userAgent, contentDisposition, mimetype, referer, contentLength);
+                    } else {
+                        mDownloadListener.onDownloadStart(url, userAgent,
+                             contentDisposition, mimetype, contentLength);
+                    }
                 }
                 break;
 
@@ -736,6 +739,14 @@
                                                 res.cancel();
                                             }
                                         })
+                                .setOnCancelListener(
+                                        new DialogInterface.OnCancelListener() {
+                                            @Override
+                                            public void onCancel(
+                                                    DialogInterface dialog) {
+                                                res.cancel();
+                                            }
+                                        })
                                 .show();
                     }
                     receiver.setReady();
@@ -857,19 +868,6 @@
                         host, realm, username, password);
                 break;
             }
-            case SET_INSTALLABLE_WEBAPP:
-                if (mWebChromeClient != null) {
-                    mWebChromeClient.setInstallableWebApp();
-                }
-                break;
-            case NOTIFY_SEARCHBOX_LISTENERS: {
-                SearchBoxImpl searchBox = (SearchBoxImpl) mWebView.getSearchBox();
-
-                @SuppressWarnings("unchecked")
-                List<String> suggestions = (List<String>) msg.obj;
-                searchBox.handleSuggestions(msg.getData().getString("query"), suggestions);
-                break;
-            }
             case AUTO_LOGIN: {
                 if (mWebViewClient != null) {
                     String realm = msg.getData().getString("realm");
@@ -880,19 +878,6 @@
                 }
                 break;
             }
-            case SEARCHBOX_IS_SUPPORTED_CALLBACK: {
-                SearchBoxImpl searchBox = (SearchBoxImpl) mWebView.getSearchBox();
-                Boolean supported = (Boolean) msg.obj;
-                searchBox.handleIsSupportedCallback(supported);
-                break;
-            }
-            case SEARCHBOX_DISPATCH_COMPLETE_CALLBACK: {
-                SearchBoxImpl searchBox = (SearchBoxImpl) mWebView.getSearchBox();
-                Boolean success = (Boolean) msg.obj;
-                searchBox.handleDispatchCompleteCallback(msg.getData().getString("function"),
-                        msg.getData().getInt("id"), success);
-                break;
-            }
         }
     }
 
@@ -1081,7 +1066,7 @@
     }
 
     public void onProceededAfterSslError(SslError error) {
-        if (mWebViewClient == null) {
+        if (mWebViewClient == null || !(mWebViewClient instanceof WebViewClientClassicExt)) {
             return;
         }
         Message msg = obtainMessage(PROCEEDED_AFTER_SSL_ERROR);
@@ -1092,7 +1077,7 @@
     public void onReceivedClientCertRequest(ClientCertRequestHandler handler, String host_and_port) {
         // Do an unsynchronized quick check to avoid posting if no callback has
         // been set.
-        if (mWebViewClient == null) {
+        if (mWebViewClient == null || !(mWebViewClient instanceof WebViewClientClassicExt)) {
             handler.cancel();
             return;
         }
@@ -1176,7 +1161,8 @@
      * return false.
      */
     public boolean onDownloadStart(String url, String userAgent,
-            String contentDisposition, String mimetype, long contentLength) {
+            String contentDisposition, String mimetype, String referer,
+            long contentLength) {
         // Do an unsynchronized quick check to avoid posting if no callback has
         // been set.
         if (mDownloadListener == null) {
@@ -1189,6 +1175,7 @@
         bundle.putString("url", url);
         bundle.putString("userAgent", userAgent);
         bundle.putString("mimetype", mimetype);
+        bundle.putString("referer", referer);
         bundle.putLong("contentLength", contentLength);
         bundle.putString("contentDisposition", contentDisposition);
         sendMessage(msg);
@@ -1301,7 +1288,7 @@
     public void onReceivedIcon(Bitmap icon) {
         // The current item might be null if the icon was already stored in the
         // database and this is a new WebView.
-        WebHistoryItem i = mBackForwardList.getCurrentItem();
+        WebHistoryItemClassic i = mBackForwardList.getCurrentItem();
         if (i != null) {
             i.setFavicon(icon);
         }
@@ -1316,7 +1303,7 @@
     /* package */ void onReceivedTouchIconUrl(String url, boolean precomposed) {
         // We should have a current item but we do not want to crash so check
         // for null.
-        WebHistoryItem i = mBackForwardList.getCurrentItem();
+        WebHistoryItemClassic i = mBackForwardList.getCurrentItem();
         if (i != null) {
             i.setTouchIconUrl(url, precomposed);
         }
@@ -1608,13 +1595,6 @@
         sendMessage(msg);
     }
 
-    void setInstallableWebApp() {
-        if (mWebChromeClient == null) {
-            return;
-        }
-        sendMessage(obtainMessage(SET_INSTALLABLE_WEBAPP));
-    }
-
     boolean canShowAlertDialog() {
         // We can only display the alert dialog if mContext is
         // an Activity context.
@@ -1625,29 +1605,6 @@
         return mContext instanceof Activity;
     }
 
-    void onSearchboxSuggestionsReceived(String query, List<String> suggestions) {
-        Message msg = obtainMessage(NOTIFY_SEARCHBOX_LISTENERS);
-        msg.obj = suggestions;
-        msg.getData().putString("query", query);
-
-        sendMessage(msg);
-    }
-
-    void onIsSupportedCallback(boolean isSupported) {
-        Message msg = obtainMessage(SEARCHBOX_IS_SUPPORTED_CALLBACK);
-        msg.obj = Boolean.valueOf(isSupported);
-        sendMessage(msg);
-    }
-
-    void onSearchboxDispatchCompleteCallback(String function, int id, boolean success) {
-        Message msg = obtainMessage(SEARCHBOX_DISPATCH_COMPLETE_CALLBACK);
-        msg.obj = Boolean.valueOf(success);
-        msg.getData().putString("function", function);
-        msg.getData().putInt("id", id);
-
-        sendMessage(msg);
-    }
-
     private synchronized void sendMessageToUiThreadSync(Message msg) {
         sendMessage(msg);
         WebCoreThreadWatchdog.pause();
diff --git a/core/java/android/webkit/CertTool.java b/core/java/android/webkit/CertTool.java
index a2325c3..e4d09a9 100644
--- a/core/java/android/webkit/CertTool.java
+++ b/core/java/android/webkit/CertTool.java
@@ -16,6 +16,7 @@
 
 package android.webkit;
 
+import com.android.org.bouncycastle.asn1.ASN1Encoding;
 import com.android.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
 import com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
 import com.android.org.bouncycastle.jce.netscape.NetscapeCertRequest;
@@ -57,7 +58,7 @@
             NetscapeCertRequest request = new NetscapeCertRequest(challenge,
                     MD5_WITH_RSA, pair.getPublic());
             request.sign(pair.getPrivate());
-            byte[] signed = request.toASN1Object().getDEREncoded();
+            byte[] signed = request.toASN1Primitive().getEncoded(ASN1Encoding.DER);
 
             Credentials.getInstance().install(context, pair);
             return new String(Base64.encode(signed));
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index 30c713e..2b75d83 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -37,8 +37,8 @@
     /**
      * Gets the singleton CookieManager instance. If this method is used
      * before the application instantiates a {@link WebView} instance,
-     * {@link CookieSyncManager#createInstance(Context)} must be called
-     * first.
+     * {@link CookieSyncManager#createInstance CookieSyncManager.createInstance(Context)}
+     * must be called first.
      *
      * @return the singleton CookieManager instance
      */
diff --git a/core/java/android/webkit/CookieSyncManager.java b/core/java/android/webkit/CookieSyncManager.java
index 4e99335..276bcae 100644
--- a/core/java/android/webkit/CookieSyncManager.java
+++ b/core/java/android/webkit/CookieSyncManager.java
@@ -86,10 +86,8 @@
             throw new IllegalArgumentException("Invalid context argument");
         }
 
-        JniUtil.setContext(context);
-        Context appContext = context.getApplicationContext();
         if (sRef == null) {
-            sRef = new CookieSyncManager(appContext);
+            sRef = new CookieSyncManager(context);
         }
         return sRef;
     }
diff --git a/core/java/android/webkit/DateSorter.java b/core/java/android/webkit/DateSorter.java
index 0e8ad7e..82c13ae 100644
--- a/core/java/android/webkit/DateSorter.java
+++ b/core/java/android/webkit/DateSorter.java
@@ -21,6 +21,9 @@
 
 import java.util.Calendar;
 import java.util.Date;
+import java.util.Locale;
+
+import libcore.icu.LocaleData;
 
 /**
  * Sorts dates into the following groups:
@@ -63,8 +66,13 @@
         mBins[3] = c.getTimeInMillis();  // One month ago
 
         // build labels
-        mLabels[0] = context.getText(com.android.internal.R.string.today).toString();
-        mLabels[1] = context.getText(com.android.internal.R.string.yesterday).toString();
+        Locale locale = resources.getConfiguration().locale;
+        if (locale == null) {
+            locale = Locale.getDefault();
+        }
+        LocaleData localeData = LocaleData.get(locale);
+        mLabels[0] = localeData.today;
+        mLabels[1] = localeData.yesterday;
 
         int resId = com.android.internal.R.plurals.last_num_days;
         String format = resources.getQuantityString(resId, NUM_DAYS_AGO);
diff --git a/core/java/android/webkit/DeviceOrientationService.java b/core/java/android/webkit/DeviceOrientationService.java
index 2e8656c..a4d240d 100755
--- a/core/java/android/webkit/DeviceOrientationService.java
+++ b/core/java/android/webkit/DeviceOrientationService.java
@@ -123,7 +123,7 @@
         // The angles are in radians
         float[] rotationAngles = new float[3];
         SensorManager.getOrientation(deviceRotationMatrix, rotationAngles);
-        double alpha = Math.toDegrees(-rotationAngles[0]) - 90.0;
+        double alpha = Math.toDegrees(-rotationAngles[0]);
         while (alpha < 0.0) { alpha += 360.0; } // [0, 360)
         double beta = Math.toDegrees(-rotationAngles[1]);
         while (beta < -180.0) { beta += 360.0; } // [-180, 180)
diff --git a/core/java/android/webkit/HTML5VideoFullScreen.java b/core/java/android/webkit/HTML5VideoFullScreen.java
index 33eaad6..9b93805 100644
--- a/core/java/android/webkit/HTML5VideoFullScreen.java
+++ b/core/java/android/webkit/HTML5VideoFullScreen.java
@@ -1,3 +1,18 @@
+/*
+ * 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.webkit;
 
@@ -75,9 +90,10 @@
     // ratio is correct.
     private int mVideoWidth;
     private int mVideoHeight;
-
+    private boolean mPlayingWhenDestroyed = false;
     SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback()
     {
+        @Override
         public void surfaceChanged(SurfaceHolder holder, int format,
                                     int w, int h)
         {
@@ -91,6 +107,7 @@
             }
         }
 
+        @Override
         public void surfaceCreated(SurfaceHolder holder)
         {
             mSurfaceHolder = holder;
@@ -99,14 +116,14 @@
             prepareForFullScreen();
         }
 
+        @Override
         public void surfaceDestroyed(SurfaceHolder holder)
         {
-            // After we return from this we can't use the surface any more.
-            // The current Video View will be destroy when we play a new video.
+            mPlayingWhenDestroyed = mPlayer.isPlaying();
             pauseAndDispatch(mProxy);
-            // TODO: handle full screen->inline mode transition without a reload.
-            mPlayer.release();
-            mPlayer = null;
+            // We need to set the display to null before switching into inline
+            // mode to avoid error.
+            mPlayer.setDisplay(null);
             mSurfaceHolder = null;
             if (mMediaController != null) {
                 mMediaController.hide();
@@ -194,18 +211,6 @@
             mCanPause = mCanSeekBack = mCanSeekForward = true;
         }
 
-        if (mProgressView != null) {
-            mProgressView.setVisibility(View.GONE);
-        }
-
-        mVideoWidth = mp.getVideoWidth();
-        mVideoHeight = mp.getVideoHeight();
-        // This will trigger the onMeasure to get the display size right.
-        mVideoSurfaceView.getHolder().setFixedSize(mVideoWidth, mVideoHeight);
-        // Call into the native to ask for the state, if still in play mode,
-        // this will trigger the video to play.
-        mProxy.dispatchOnRestoreState();
-
         if (getStartWhenPrepared()) {
             mPlayer.start();
             // Clear the flag.
@@ -219,20 +224,31 @@
             mMediaController.setEnabled(true);
             mMediaController.show();
         }
+
+        if (mProgressView != null) {
+            mProgressView.setVisibility(View.GONE);
+        }
+
+        mVideoWidth = mp.getVideoWidth();
+        mVideoHeight = mp.getVideoHeight();
+        // This will trigger the onMeasure to get the display size right.
+        mVideoSurfaceView.getHolder().setFixedSize(mVideoWidth, mVideoHeight);
+
     }
 
+    @Override
     public boolean fullScreenExited() {
         return (mLayout == null);
     }
 
     private final WebChromeClient.CustomViewCallback mCallback =
         new WebChromeClient.CustomViewCallback() {
+            @Override
             public void onCustomViewHidden() {
                 // It listens to SurfaceHolder.Callback.SurfaceDestroyed event
                 // which happens when the video view is detached from its parent
                 // view. This happens in the WebChromeClient before this method
                 // is invoked.
-                mProxy.dispatchOnStopFullScreen();
                 mLayout.removeView(getSurfaceView());
 
                 if (mProgressView != null) {
@@ -242,12 +258,11 @@
                 mLayout = null;
                 // Re enable plugin views.
                 mProxy.getWebView().getViewManager().showAll();
-
-                mProxy = null;
-
                 // Don't show the controller after exiting the full screen.
                 mMediaController = null;
-                mCurrentState = STATE_RESETTED;
+                // Continue the inline mode playing if necessary.
+                mProxy.dispatchOnStopFullScreen(mPlayingWhenDestroyed);
+                mProxy = null;
             }
         };
 
@@ -264,7 +279,7 @@
         mVideoSurfaceView.setFocusable(true);
         mVideoSurfaceView.setFocusableInTouchMode(true);
         mVideoSurfaceView.requestFocus();
-
+        mVideoSurfaceView.setOnKeyListener(mProxy);
         // Create a FrameLayout that will contain the VideoView and the
         // progress view (if any).
         mLayout = new FrameLayout(mProxy.getContext());
@@ -296,6 +311,7 @@
      * @return true when we are in full screen mode, even the surface not fully
      * created.
      */
+    @Override
     public boolean isFullScreenMode() {
         return true;
     }
@@ -334,6 +350,7 @@
     // Other listeners functions:
     private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener =
         new MediaPlayer.OnBufferingUpdateListener() {
+        @Override
         public void onBufferingUpdate(MediaPlayer mp, int percent) {
             mCurrentBufferPercentage = percent;
         }
diff --git a/core/java/android/webkit/HTML5VideoInline.java b/core/java/android/webkit/HTML5VideoInline.java
index 2c7ea5d..2ab2ab9 100644
--- a/core/java/android/webkit/HTML5VideoInline.java
+++ b/core/java/android/webkit/HTML5VideoInline.java
@@ -1,10 +1,24 @@
+/*
+ * 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.webkit;
 
 import android.Manifest.permission;
 import android.content.pm.PackageManager;
 import android.graphics.SurfaceTexture;
-import android.media.MediaPlayer;
 import android.webkit.HTML5VideoView;
 import android.webkit.HTML5VideoViewProxy;
 import android.view.Surface;
@@ -34,8 +48,8 @@
         }
     }
 
-    HTML5VideoInline(int videoLayerId, int position) {
-        init(videoLayerId, position, false);
+    HTML5VideoInline(int videoLayerId, int position, boolean skipPrepare) {
+        init(videoLayerId, position, skipPrepare);
     }
 
     @Override
@@ -84,7 +98,7 @@
         return mSurfaceTexture;
     }
 
-    public boolean surfaceTextureDeleted() {
+    public static boolean surfaceTextureDeleted() {
         return (mSurfaceTexture == null);
     }
 
@@ -110,7 +124,9 @@
     }
 
     private void setFrameAvailableListener(SurfaceTexture.OnFrameAvailableListener l) {
-        mSurfaceTexture.setOnFrameAvailableListener(l);
+        if (mSurfaceTexture != null) {
+            mSurfaceTexture.setOnFrameAvailableListener(l);
+        }
     }
 
 }
diff --git a/core/java/android/webkit/HTML5VideoView.java b/core/java/android/webkit/HTML5VideoView.java
index 371feea..0e8a5db 100644
--- a/core/java/android/webkit/HTML5VideoView.java
+++ b/core/java/android/webkit/HTML5VideoView.java
@@ -1,11 +1,23 @@
+/*
+ * 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.webkit;
 
-import android.graphics.SurfaceTexture;
 import android.media.MediaPlayer;
 import android.net.Uri;
-import android.util.Log;
-import android.view.SurfaceView;
 import android.webkit.HTML5VideoViewProxy;
 import java.io.IOException;
 import java.util.HashMap;
@@ -35,6 +47,7 @@
     static final int STATE_PREPARED           = 2;
     static final int STATE_PLAYING            = 3;
     static final int STATE_RESETTED           = 4;
+    static final int STATE_RELEASED           = 5;
 
     protected HTML5VideoViewProxy mProxy;
 
@@ -126,7 +139,7 @@
     }
 
     public void reset() {
-        if (mCurrentState != STATE_RESETTED) {
+        if (mCurrentState < STATE_RESETTED) {
             mPlayer.reset();
         }
         mCurrentState = STATE_RESETTED;
@@ -138,6 +151,18 @@
         }
     }
 
+    public static void release() {
+        if (mPlayer != null && mCurrentState != STATE_RELEASED) {
+            mPlayer.release();
+            mPlayer = null;
+        }
+        mCurrentState = STATE_RELEASED;
+    }
+
+    public boolean isReleased() {
+        return mCurrentState == STATE_RELEASED;
+    }
+
     public boolean getPauseDuringPreparing() {
         return mPauseDuringPreparing;
     }
@@ -337,11 +362,6 @@
         // Only used in HTML5VideoFullScreen
     }
 
-    public boolean surfaceTextureDeleted() {
-        // Only meaningful for HTML5VideoInline
-        return false;
-    }
-
     public boolean fullScreenExited() {
         // Only meaningful for HTML5VideoFullScreen
         return false;
diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java
index ab884df..a3d62ae 100644
--- a/core/java/android/webkit/HTML5VideoViewProxy.java
+++ b/core/java/android/webkit/HTML5VideoViewProxy.java
@@ -31,6 +31,8 @@
 import android.os.Looper;
 import android.os.Message;
 import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -47,7 +49,8 @@
                           MediaPlayer.OnCompletionListener,
                           MediaPlayer.OnErrorListener,
                           MediaPlayer.OnInfoListener,
-                          SurfaceTexture.OnFrameAvailableListener {
+                          SurfaceTexture.OnFrameAvailableListener,
+                          View.OnKeyListener {
     // Logging tag.
     private static final String LOGTAG = "HTML5VideoViewProxy";
 
@@ -59,6 +62,7 @@
     private static final int LOAD_DEFAULT_POSTER = 104;
     private static final int BUFFERING_START     = 105;
     private static final int BUFFERING_END       = 106;
+    private static final int ENTER_FULLSCREEN    = 107;
 
     // Message Ids to be handled on the WebCore thread
     private static final int PREPARED          = 200;
@@ -93,9 +97,6 @@
         private static HTML5VideoView mHTML5VideoView;
 
         private static boolean isVideoSelfEnded = false;
-        // By using the baseLayer and the current video Layer ID, we can
-        // identify the exact layer on the UI thread to use the SurfaceTexture.
-        private static int mBaseLayer = 0;
 
         private static void setPlayerBuffering(boolean playerBuffering) {
             mHTML5VideoView.setPlayerBuffering(playerBuffering);
@@ -108,9 +109,7 @@
             // Don't do this for full screen mode.
             if (mHTML5VideoView != null
                 && !mHTML5VideoView.isFullScreenMode()
-                && !mHTML5VideoView.surfaceTextureDeleted()) {
-                mBaseLayer = layer;
-
+                && !mHTML5VideoView.isReleased()) {
                 int currentVideoLayerId = mHTML5VideoView.getVideoLayerId();
                 SurfaceTexture surfTexture =
                         HTML5VideoInline.getSurfaceTexture(currentVideoLayerId);
@@ -126,7 +125,6 @@
                     if (playerState >= HTML5VideoView.STATE_PREPARED
                             && !foundInTree) {
                         mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
-                        mHTML5VideoView.deleteSurfaceTexture();
                     }
                 }
             }
@@ -136,9 +134,6 @@
         public static void pauseAndDispatch() {
             if (mHTML5VideoView != null) {
                 mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
-                // When switching out, clean the video content on the old page
-                // by telling the layer not readyToUseSurfTex.
-                setBaseLayer(mBaseLayer);
             }
         }
 
@@ -217,9 +212,16 @@
                 }
             }
 
+            boolean skipPrepare = false;
+            boolean createInlineView = false;
             if (backFromFullScreenMode
+                && currentVideoLayerId == videoLayerId
+                && !mHTML5VideoView.isReleased()) {
+                skipPrepare = true;
+                createInlineView = true;
+            } else if(backFromFullScreenMode
                 || currentVideoLayerId != videoLayerId
-                || mHTML5VideoView.surfaceTextureDeleted()) {
+                || HTML5VideoInline.surfaceTextureDeleted()) {
                 // Here, we handle the case when switching to a new video,
                 // either inside a WebView or across WebViews
                 // For switching videos within a WebView or across the WebView,
@@ -231,12 +233,18 @@
                     }
                     mHTML5VideoView.reset();
                 }
+                createInlineView = true;
+            }
+            if (createInlineView) {
                 mCurrentProxy = proxy;
-                mHTML5VideoView = new HTML5VideoInline(videoLayerId, time);
+                mHTML5VideoView = new HTML5VideoInline(videoLayerId, time, skipPrepare);
 
                 mHTML5VideoView.setVideoURI(url, mCurrentProxy);
                 mHTML5VideoView.prepareDataAndDisplayMode(proxy);
-            } else if (mCurrentProxy == proxy) {
+                return;
+            }
+
+            if (mCurrentProxy == proxy) {
                 // Here, we handle the case when we keep playing with one video
                 if (!mHTML5VideoView.isPlaying()) {
                     mHTML5VideoView.seekTo(time);
@@ -278,9 +286,6 @@
             if (!mHTML5VideoView.isFullScreenMode()) {
                 mHTML5VideoView.start();
             }
-            if (mBaseLayer != 0) {
-                setBaseLayer(mBaseLayer);
-            }
         }
 
         public static void end() {
@@ -297,6 +302,7 @@
 
     // A bunch event listeners for our VideoView
     // MediaPlayer.OnPreparedListener
+    @Override
     public void onPrepared(MediaPlayer mp) {
         VideoPlayer.onPrepared();
         Message msg = Message.obtain(mWebCoreHandler, PREPARED);
@@ -309,6 +315,7 @@
     }
 
     // MediaPlayer.OnCompletionListener;
+    @Override
     public void onCompletion(MediaPlayer mp) {
         // The video ended by itself, so we need to
         // send a message to the UI thread to dismiss
@@ -318,6 +325,7 @@
     }
 
     // MediaPlayer.OnErrorListener
+    @Override
     public boolean onError(MediaPlayer mp, int what, int extra) {
         sendMessage(obtainMessage(ERROR));
         return false;
@@ -333,8 +341,9 @@
         mWebCoreHandler.sendMessage(msg);
     }
 
-    public void dispatchOnStopFullScreen() {
+    public void dispatchOnStopFullScreen(boolean stillPlaying) {
         Message msg = Message.obtain(mWebCoreHandler, STOPFULLSCREEN);
+        msg.arg1 = stillPlaying ? 1 : 0;
         mWebCoreHandler.sendMessage(msg);
     }
 
@@ -369,6 +378,15 @@
                 }
                 break;
             }
+            case ENTER_FULLSCREEN:{
+                String url = (String) msg.obj;
+                WebChromeClient client = mWebView.getWebChromeClient();
+                int videoLayerID = msg.arg1;
+                if (client != null) {
+                    VideoPlayer.enterFullScreenVideo(videoLayerID, url, this, mWebView);
+                }
+                break;
+            }
             case SEEK: {
                 Integer time = (Integer) msg.obj;
                 mSeekPosition = time;
@@ -473,6 +491,7 @@
             releaseQueue();
         }
         // EventHandler methods. Executed on the network thread.
+        @Override
         public void status(int major_version,
                 int minor_version,
                 int code,
@@ -480,10 +499,12 @@
             mStatusCode = code;
         }
 
+        @Override
         public void headers(Headers headers) {
             mHeaders = headers;
         }
 
+        @Override
         public void data(byte[] data, int len) {
             if (mPosterBytes == null) {
                 mPosterBytes = new ByteArrayOutputStream();
@@ -491,6 +512,7 @@
             mPosterBytes.write(data, 0, len);
         }
 
+        @Override
         public void endData() {
             if (mStatusCode == 200) {
                 if (mPosterBytes.size() > 0) {
@@ -508,6 +530,7 @@
                 }
                 if (mUrl != null) {
                     mHandler.post(new Runnable() {
+                       @Override
                        public void run() {
                            if (mRequestHandle != null) {
                                mRequestHandle.setupRedirect(mUrl.toString(), mStatusCode,
@@ -519,14 +542,17 @@
             }
         }
 
+        @Override
         public void certificate(SslCertificate certificate) {
             // Don't care.
         }
 
+        @Override
         public void error(int id, String description) {
             cleanup();
         }
 
+        @Override
         public boolean handleSslErrorRequest(SslError error) {
             // Don't care. If this happens, data() will never be called so
             // mPosterBytes will never be created, so no need to call cleanup.
@@ -613,7 +639,7 @@
                         nativeOnTimeupdate(msg.arg1, mNativePointer);
                         break;
                     case STOPFULLSCREEN:
-                        nativeOnStopFullscreen(mNativePointer);
+                        nativeOnStopFullscreen(msg.arg1, mNativePointer);
                         break;
                     case RESTORESTATE:
                         nativeOnRestoreState(mNativePointer);
@@ -664,6 +690,21 @@
     }
 
     /**
+     * Play a video stream in full screen mode.
+     * @param url is the URL of the video stream.
+     */
+    public void enterFullscreenForVideoLayer(String url, int videoLayerID) {
+        if (url == null) {
+            return;
+        }
+
+        Message message = obtainMessage(ENTER_FULLSCREEN);
+        message.arg1 = videoLayerID;
+        message.obj = url;
+        sendMessage(message);
+    }
+
+    /**
      * Seek into the video stream.
      * @param  time is the position in the video stream.
      */
@@ -748,7 +789,7 @@
     private native void nativeOnPaused(int nativePointer);
     private native void nativeOnPosterFetched(Bitmap poster, int nativePointer);
     private native void nativeOnTimeupdate(int position, int nativePointer);
-    private native void nativeOnStopFullscreen(int nativePointer);
+    private native void nativeOnStopFullscreen(int stillPlaying, int nativePointer);
     private native void nativeOnRestoreState(int nativePointer);
     private native static boolean nativeSendSurfaceTexture(SurfaceTexture texture,
             int baseLayer, int videoLayerId, int textureName,
@@ -763,4 +804,17 @@
         }
         return false;
     }
+
+    @Override
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+            if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                return true;
+            } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled()) {
+                VideoPlayer.exitFullScreenVideo(this, mWebView);
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/core/java/android/webkit/HttpAuthHandler.java b/core/java/android/webkit/HttpAuthHandler.java
index 2fbd1d0..296d960 100644
--- a/core/java/android/webkit/HttpAuthHandler.java
+++ b/core/java/android/webkit/HttpAuthHandler.java
@@ -19,40 +19,51 @@
 import android.os.Handler;
 
 /**
- * HTTP authentication request that must be handled by the user interface.
- * WebView creates the object and hands it to the current {@link WebViewClient},
- * which must call either {@link #proceed(String, String)} or {@link #cancel()}.
+ * Represents a request for HTTP authentication. Instances of this class are
+ * created by the WebView and passed to
+ * {@link WebViewClient#onReceivedHttpAuthRequest}. The host application must
+ * call either {@link #proceed} or {@link #cancel} to set the WebView's
+ * response to the request.
  */
 public class HttpAuthHandler extends Handler {
 
     /**
-     * Package-private constructor needed for API compatibility.
+     * @hide Only for use by WebViewProvider implementations.
      */
-    HttpAuthHandler() {
+    public HttpAuthHandler() {
     }
 
     /**
-     * @return True if we can use user credentials on record
-     * (ie, if we did not fail trying to use them last time)
+     * Gets whether the credentials stored for the current host (i.e. the host
+     * for which {@link WebViewClient#onReceivedHttpAuthRequest} was called)
+     * are suitable for use. Credentials are not suitable if they have
+     * previously been rejected by the server for the current request.
+     *
+     * @return whether the credentials are suitable for use
+     * @see Webview#getHttpAuthUsernamePassword
      */
     public boolean useHttpAuthUsernamePassword() {
         return false;
     }
 
     /**
-     * Cancel the authorization request.
+     * Instructs the WebView to cancel the authentication request.
      */
     public void cancel() {
     }
 
     /**
-     * Proceed with the authorization with the given credentials.
+     * Instructs the WebView to proceed with the authentication with the given
+     * credentials. Credentials for use with this method can be retrieved from
+     * the WebView's store using {@link WebView#getHttpAuthUsernamePassword}.
      */
     public void proceed(String username, String password) {
     }
 
     /**
-     * return true if the prompt dialog should be suppressed.
+     * Gets whether the prompt dialog should be suppressed.
+     *
+     * @return whether the prompt dialog should be suppressed
      * @hide
      */
     public boolean suppressDialog() {
diff --git a/core/java/android/webkit/JavascriptInterface.java b/core/java/android/webkit/JavascriptInterface.java
index a5312a2..6cd2a7b 100644
--- a/core/java/android/webkit/JavascriptInterface.java
+++ b/core/java/android/webkit/JavascriptInterface.java
@@ -22,9 +22,11 @@
 import java.lang.annotation.Target;
 
 /**
- * Annotation that allows exposing methods to JavaScript.
+ * Annotation that allows exposing methods to JavaScript. Starting from API level
+ * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} and above, only methods explicitly
+ * marked with this annotation are available to the Javascript code. See
+ * {@link android.webkit.WebView#addJavascriptInterface} for more information about it.
  *
- * @hide
  */
 @SuppressWarnings("javadoc")
 @Retention(RetentionPolicy.RUNTIME)
diff --git a/core/java/android/webkit/JniUtil.java b/core/java/android/webkit/JniUtil.java
index e3e6092..01a81c4 100644
--- a/core/java/android/webkit/JniUtil.java
+++ b/core/java/android/webkit/JniUtil.java
@@ -173,8 +173,8 @@
         checkInitialized();
         // If the device has not checked in it won't have pulled down the system setting for the
         // Autofill Url. In that case we will not make autofill server requests.
-        return Settings.Secure.getString(sContext.getContentResolver(),
-                Settings.Secure.WEB_AUTOFILL_QUERY_URL);
+        return Settings.Global.getString(sContext.getContentResolver(),
+                Settings.Global.WEB_AUTOFILL_QUERY_URL);
     }
 
     private static boolean canSatisfyMemoryAllocation(long bytesRequested) {
diff --git a/core/java/android/webkit/MockGeolocation.java b/core/java/android/webkit/MockGeolocation.java
index fbda4924..885c6c2 100644
--- a/core/java/android/webkit/MockGeolocation.java
+++ b/core/java/android/webkit/MockGeolocation.java
@@ -17,21 +17,29 @@
 package android.webkit;
 
 /**
- * This class is simply a container for the methods used to configure WebKit's
- * mock Geolocation service for use in LayoutTests.
+ * Used to configure the mock Geolocation client for the LayoutTests.
  * @hide
  */
 public final class MockGeolocation {
+    private WebViewCore mWebViewCore;
 
-    // Global instance of a MockGeolocation
-    private static MockGeolocation sMockGeolocation;
+    public MockGeolocation(WebViewCore webViewCore) {
+        mWebViewCore = webViewCore;
+    }
+
+    /**
+     * Sets use of the mock Geolocation client. Also resets that client.
+     */
+    public void setUseMock() {
+        nativeSetUseMock(mWebViewCore);
+    }
 
     /**
      * Set the position for the mock Geolocation service.
      */
     public void setPosition(double latitude, double longitude, double accuracy) {
         // This should only ever be called on the WebKit thread.
-        nativeSetPosition(latitude, longitude, accuracy);
+        nativeSetPosition(mWebViewCore, latitude, longitude, accuracy);
     }
 
     /**
@@ -39,21 +47,18 @@
      */
     public void setError(int code, String message) {
         // This should only ever be called on the WebKit thread.
-        nativeSetError(code, message);
+        nativeSetError(mWebViewCore, code, message);
     }
 
-    /**
-     * Get the global instance of MockGeolocation.
-     * @return The global MockGeolocation instance.
-     */
-    public static MockGeolocation getInstance() {
-      if (sMockGeolocation == null) {
-          sMockGeolocation = new MockGeolocation();
-      }
-      return sMockGeolocation;
+    public void setPermission(boolean allow) {
+        // This should only ever be called on the WebKit thread.
+        nativeSetPermission(mWebViewCore, allow);
     }
 
     // Native functions
-    private static native void nativeSetPosition(double latitude, double longitude, double accuracy);
-    private static native void nativeSetError(int code, String message);
+    private static native void nativeSetUseMock(WebViewCore webViewCore);
+    private static native void nativeSetPosition(WebViewCore webViewCore, double latitude,
+            double longitude, double accuracy);
+    private static native void nativeSetError(WebViewCore webViewCore, int code, String message);
+    private static native void nativeSetPermission(WebViewCore webViewCore, boolean allow);
 }
diff --git a/core/java/android/webkit/SearchBox.java b/core/java/android/webkit/SearchBox.java
deleted file mode 100644
index 38a1740..0000000
--- a/core/java/android/webkit/SearchBox.java
+++ /dev/null
@@ -1,109 +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.
- */
-
-
-package android.webkit;
-
-import java.util.List;
-
-/**
- * Defines the interaction between the browser/renderer and the page running on
- * a given WebView frame, if the page supports the chromium SearchBox API.
- *
- * http://dev.chromium.org/searchbox
- *
- * The browser or container app can query the page for search results using
- * SearchBox.query() and receive suggestions by registering a listener on the
- * SearchBox object.
- *
- * @hide
- */
-public interface SearchBox {
-    /**
-     * Sets the current searchbox query. Note that the caller must call
-     * onchange() to ensure that the search page processes this query.
-     */
-    void setQuery(String query);
-
-    /**
-     * Verbatim is true if the caller suggests that the search page
-     * treat the current query as a verbatim search query (as opposed to a
-     * partially typed search query). As with setQuery, onchange() must be
-     * called to ensure that the search page processes the query.
-     */
-    void setVerbatim(boolean verbatim);
-
-    /**
-     * These attributes must contain the offset to the characters that immediately
-     * follow the start and end of the selection in the search box. If there is
-     * no such selection, then both selectionStart and selectionEnd must be the offset
-     * to the character that immediately follows the text entry cursor. In the case
-     * that there is no explicit text entry cursor, the cursor is
-     * implicitly at the end of the input.
-     */
-    void setSelection(int selectionStart, int selectionEnd);
-
-    /**
-     * Sets the dimensions of the view (if any) that overlaps the current
-     * window object. This is to ensure that the page renders results in
-     * a manner that allows them to not be obscured by such a view. Note
-     * that a call to onresize() is required if these dimensions change.
-     */
-    void setDimensions(int x, int y, int width, int height);
-
-    /**
-     * Notify the search page of any changes to the searchbox. Such as
-     * a change in the typed query (onchange), the user commiting a given query
-     * (onsubmit), or a change in size of a suggestions dropdown (onresize).
-     *
-     * @param listener an optional listener to notify of the success of the operation,
-     *      indicating if the javascript function existed and could be called or not.
-     *      It will be called on the UI thread.
-     */
-    void onchange(SearchBoxListener listener);
-    void onsubmit(SearchBoxListener listener);
-    void onresize(SearchBoxListener listener);
-    void oncancel(SearchBoxListener listener);
-
-    /**
-     * Add and remove listeners to the given Searchbox. Listeners are notified
-     * of any suggestions to the query that the underlying search engine might
-     * provide.
-     */
-    void addSearchBoxListener(SearchBoxListener l);
-    void removeSearchBoxListener(SearchBoxListener l);
-
-    /**
-     * Indicates if the searchbox API is supported in the current page.
-     */
-    void isSupported(IsSupportedCallback callback);
-
-    /**
-     * Listeners (if any) will be called on the thread that created the
-     * webview.
-     */
-    public abstract class SearchBoxListener {
-        public void onSuggestionsReceived(String query, List<String> suggestions) {}
-        public void onChangeComplete(boolean called) {}
-        public void onSubmitComplete(boolean called) {}
-        public void onResizeComplete(boolean called) {}
-        public void onCancelComplete(boolean called) {}
-    }
-
-    interface IsSupportedCallback {
-        void searchBoxIsSupported(boolean supported);
-    }
-}
diff --git a/core/java/android/webkit/SearchBoxImpl.java b/core/java/android/webkit/SearchBoxImpl.java
deleted file mode 100644
index 9942d25..0000000
--- a/core/java/android/webkit/SearchBoxImpl.java
+++ /dev/null
@@ -1,304 +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.
- */
-
-package android.webkit;
-
-import android.text.TextUtils;
-import android.util.Log;
-import android.webkit.WebViewCore.EventHub;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONStringer;
-
-/**
- * The default implementation of the SearchBox interface. Implemented
- * as a java bridge object and a javascript adapter that is called into
- * by the page hosted in the frame.
- */
-final class SearchBoxImpl implements SearchBox {
-    private static final String TAG = "WebKit.SearchBoxImpl";
-
-    /* package */ static final String JS_INTERFACE_NAME = "searchBoxJavaBridge_";
-
-    /* package */ static final String JS_BRIDGE
-            = "(function()"
-            + "{"
-            + "if (!window.chrome) {"
-            + "  window.chrome = {};"
-            + "}"
-            + "if (!window.chrome.searchBox) {"
-            + "  var sb = window.chrome.searchBox = {};"
-            + "  sb.setSuggestions = function(suggestions) {"
-            + "    if (window.searchBoxJavaBridge_) {"
-            + "      window.searchBoxJavaBridge_.setSuggestions(JSON.stringify(suggestions));"
-            + "    }"
-            + "  };"
-            + "  sb.setValue = function(valueArray) { sb.value = valueArray[0]; };"
-            + "  sb.value = '';"
-            + "  sb.x = 0;"
-            + "  sb.y = 0;"
-            + "  sb.width = 0;"
-            + "  sb.height = 0;"
-            + "  sb.selectionStart = 0;"
-            + "  sb.selectionEnd = 0;"
-            + "  sb.verbatim = false;"
-            + "}"
-            + "})();";
-
-    private static final String SET_QUERY_SCRIPT
-            = "if (window.chrome && window.chrome.searchBox) {"
-            + "  window.chrome.searchBox.setValue(%s);"
-            + "}";
-
-    private static final String SET_VERBATIM_SCRIPT
-            =  "if (window.chrome && window.chrome.searchBox) {"
-            + "  window.chrome.searchBox.verbatim = %1$s;"
-            + "}";
-
-    private static final String SET_SELECTION_SCRIPT
-            = "if (window.chrome && window.chrome.searchBox) {"
-            + "  var f = window.chrome.searchBox;"
-            + "  f.selectionStart = %d"
-            + "  f.selectionEnd = %d"
-            + "}";
-
-    private static final String SET_DIMENSIONS_SCRIPT
-            = "if (window.chrome && window.chrome.searchBox) { "
-            + "  var f = window.chrome.searchBox;"
-            + "  f.x = %d;"
-            + "  f.y = %d;"
-            + "  f.width = %d;"
-            + "  f.height = %d;"
-            + "}";
-
-    private static final String DISPATCH_EVENT_SCRIPT
-            = "if (window.chrome && window.chrome.searchBox && window.chrome.searchBox.on%1$s) {"
-            + "  window.chrome.searchBox.on%1$s();"
-            + "  window.searchBoxJavaBridge_.dispatchCompleteCallback('%1$s', %2$d, true);"
-            + "} else {"
-            + "  window.searchBoxJavaBridge_.dispatchCompleteCallback('%1$s', %2$d, false);"
-            + "}";
-
-    private static final String EVENT_CHANGE = "change";
-    private static final String EVENT_SUBMIT = "submit";
-    private static final String EVENT_RESIZE = "resize";
-    private static final String EVENT_CANCEL = "cancel";
-
-    private static final String IS_SUPPORTED_SCRIPT
-            = "if (window.searchBoxJavaBridge_) {"
-            + "  if (window.chrome && window.chrome.sv) {"
-            + "    window.searchBoxJavaBridge_.isSupportedCallback(true);"
-            + "  } else {"
-            + "    window.searchBoxJavaBridge_.isSupportedCallback(false);"
-            + "  }}";
-
-    private final List<SearchBoxListener> mListeners;
-    private final WebViewCore mWebViewCore;
-    private final CallbackProxy mCallbackProxy;
-    private IsSupportedCallback mSupportedCallback;
-    private int mNextEventId = 1;
-    private final HashMap<Integer, SearchBoxListener> mEventCallbacks;
-
-    SearchBoxImpl(WebViewCore webViewCore, CallbackProxy callbackProxy) {
-        mListeners = new ArrayList<SearchBoxListener>();
-        mWebViewCore = webViewCore;
-        mCallbackProxy = callbackProxy;
-        mEventCallbacks = new HashMap<Integer, SearchBoxListener>();
-    }
-
-    @Override
-    public void setQuery(String query) {
-        final String formattedQuery = jsonSerialize(query);
-        if (formattedQuery != null) {
-            final String js = String.format(SET_QUERY_SCRIPT, formattedQuery);
-            dispatchJs(js);
-        }
-    }
-
-    @Override
-    public void setVerbatim(boolean verbatim) {
-        final String js = String.format(SET_VERBATIM_SCRIPT, String.valueOf(verbatim));
-        dispatchJs(js);
-    }
-
-
-    @Override
-    public void setSelection(int selectionStart, int selectionEnd) {
-        final String js = String.format(SET_SELECTION_SCRIPT, selectionStart, selectionEnd);
-        dispatchJs(js);
-    }
-
-    @Override
-    public void setDimensions(int x, int y, int width, int height) {
-        final String js = String.format(SET_DIMENSIONS_SCRIPT, x, y, width, height);
-        dispatchJs(js);
-    }
-
-    @Override
-    public void onchange(SearchBoxListener callback) {
-        dispatchEvent(EVENT_CHANGE, callback);
-    }
-
-    @Override
-    public void onsubmit(SearchBoxListener callback) {
-        dispatchEvent(EVENT_SUBMIT, callback);
-    }
-
-    @Override
-    public void onresize(SearchBoxListener callback) {
-        dispatchEvent(EVENT_RESIZE, callback);
-    }
-
-    @Override
-    public void oncancel(SearchBoxListener callback) {
-        dispatchEvent(EVENT_CANCEL, callback);
-    }
-
-    private void dispatchEvent(String eventName, SearchBoxListener callback) {
-        int eventId;
-        if (callback != null) {
-            synchronized(this) {
-                eventId = mNextEventId++;
-                mEventCallbacks.put(eventId, callback);
-            }
-        } else {
-            eventId = 0;
-        }
-        final String js = String.format(DISPATCH_EVENT_SCRIPT, eventName, eventId);
-        dispatchJs(js);
-    }
-
-    private void dispatchJs(String js) {
-        mWebViewCore.sendMessage(EventHub.EXECUTE_JS, js);
-    }
-
-    @Override
-    public void addSearchBoxListener(SearchBoxListener l) {
-        synchronized (mListeners) {
-            mListeners.add(l);
-        }
-    }
-
-    @Override
-    public void removeSearchBoxListener(SearchBoxListener l) {
-        synchronized (mListeners) {
-            mListeners.remove(l);
-        }
-    }
-
-    @Override
-    public void isSupported(IsSupportedCallback callback) {
-        mSupportedCallback = callback;
-        dispatchJs(IS_SUPPORTED_SCRIPT);
-    }
-
-    // Called by Javascript through the Java bridge.
-    public void isSupportedCallback(boolean isSupported) {
-        mCallbackProxy.onIsSupportedCallback(isSupported);
-    }
-
-    public void handleIsSupportedCallback(boolean isSupported) {
-        IsSupportedCallback callback = mSupportedCallback;
-        mSupportedCallback = null;
-        if (callback != null) {
-            callback.searchBoxIsSupported(isSupported);
-        }
-    }
-
-    // Called by Javascript through the Java bridge.
-    public void dispatchCompleteCallback(String function, int id, boolean successful) {
-        mCallbackProxy.onSearchboxDispatchCompleteCallback(function, id, successful);
-    }
-
-    public void handleDispatchCompleteCallback(String function, int id, boolean successful) {
-        if (id != 0) {
-            SearchBoxListener listener;
-            synchronized(this) {
-                listener = mEventCallbacks.get(id);
-                mEventCallbacks.remove(id);
-            }
-            if (listener != null) {
-                if (TextUtils.equals(EVENT_CHANGE, function)) {
-                    listener.onChangeComplete(successful);
-                } else if (TextUtils.equals(EVENT_SUBMIT, function)) {
-                    listener.onSubmitComplete(successful);
-                } else if (TextUtils.equals(EVENT_RESIZE, function)) {
-                    listener.onResizeComplete(successful);
-                } else if (TextUtils.equals(EVENT_CANCEL, function)) {
-                    listener.onCancelComplete(successful);
-                }
-            }
-        }
-    }
-
-    // This is used as a hackish alternative to javascript escaping.
-    // There appears to be no such functionality in the core framework.
-    private static String jsonSerialize(String query) {
-        JSONStringer stringer = new JSONStringer();
-        try {
-            stringer.array().value(query).endArray();
-        } catch (JSONException e) {
-            Log.w(TAG, "Error serializing query : " + query);
-            return null;
-        }
-        return stringer.toString();
-    }
-
-    // Called by Javascript through the Java bridge.
-    public void setSuggestions(String jsonArguments) {
-        if (jsonArguments == null) {
-            return;
-        }
-
-        String query = null;
-        List<String> suggestions = new ArrayList<String>();
-        try {
-            JSONObject suggestionsJson = new JSONObject(jsonArguments);
-            query = suggestionsJson.getString("query");
-
-            final JSONArray suggestionsArray = suggestionsJson.getJSONArray("suggestions");
-            for (int i = 0; i < suggestionsArray.length(); ++i) {
-                final JSONObject suggestion = suggestionsArray.getJSONObject(i);
-                final String value = suggestion.getString("value");
-                if (value != null) {
-                    suggestions.add(value);
-                }
-                // We currently ignore the "type" of the suggestion. This isn't
-                // documented anywhere in the API documents.
-                // final String type = suggestions.getString("type");
-            }
-        } catch (JSONException je) {
-            Log.w(TAG, "Error parsing json [" + jsonArguments + "], exception = " + je);
-            return;
-        }
-
-        mCallbackProxy.onSearchboxSuggestionsReceived(query, suggestions);
-    }
-
-    /* package */ void handleSuggestions(String query, List<String> suggestions) {
-        synchronized (mListeners) {
-            for (int i = mListeners.size() - 1; i >= 0; i--) {
-                mListeners.get(i).onSuggestionsReceived(query, suggestions);
-            }
-        }
-    }
-}
diff --git a/core/java/android/webkit/SslErrorHandler.java b/core/java/android/webkit/SslErrorHandler.java
index 426145a..3a43950 100644
--- a/core/java/android/webkit/SslErrorHandler.java
+++ b/core/java/android/webkit/SslErrorHandler.java
@@ -26,9 +26,9 @@
 public class SslErrorHandler extends Handler {
 
     /**
-     * Package-private constructor needed for API compatibility.
+     * @hide Only for use by WebViewProvider implementations.
      */
-    SslErrorHandler() {}
+    public SslErrorHandler() {}
 
     /**
      * Proceed with the SSL certificate.
diff --git a/core/java/android/webkit/ViewStateSerializer.java b/core/java/android/webkit/ViewStateSerializer.java
index c161085..096d4cda 100644
--- a/core/java/android/webkit/ViewStateSerializer.java
+++ b/core/java/android/webkit/ViewStateSerializer.java
@@ -16,7 +16,6 @@
 package android.webkit;
 
 import android.graphics.Point;
-import android.graphics.Region;
 import android.webkit.WebViewCore.DrawData;
 
 import java.io.DataInputStream;
@@ -68,6 +67,15 @@
         return draw;
     }
 
+    public static void dumpLayerHierarchy(int baseLayer, OutputStream out, int level) {
+        nativeDumpLayerHierarchy(baseLayer, level, out,
+                new byte[WORKING_STREAM_STORAGE]);
+    }
+
+
+    private static native void nativeDumpLayerHierarchy(int baseLayer, int level,
+            OutputStream out, byte[] storage);
+
     private static native boolean nativeSerializeViewState(int baseLayer,
             OutputStream stream, byte[] storage);
 
diff --git a/core/java/android/webkit/WebBackForwardList.java b/core/java/android/webkit/WebBackForwardList.java
index 79e634e..bfef2e7 100644
--- a/core/java/android/webkit/WebBackForwardList.java
+++ b/core/java/android/webkit/WebBackForwardList.java
@@ -17,7 +17,6 @@
 package android.webkit;
 
 import java.io.Serializable;
-import java.util.ArrayList;
 
 /**
  * This class contains the back/forward list for a WebView.
@@ -25,22 +24,11 @@
  * inspect the entries in the list.
  */
 public class WebBackForwardList implements Cloneable, Serializable {
-    // Current position in the list.
-    private int mCurrentIndex;
-    // ArrayList of WebHistoryItems for maintaining our copy.
-    private ArrayList<WebHistoryItem> mArray;
-    // Flag to indicate that the list is invalid
-    private boolean mClearPending;
-    // CallbackProxy to issue client callbacks.
-    private final CallbackProxy mCallbackProxy;
 
     /**
-     * Construct a back/forward list used by clients of WebView.
+     *  @hide
      */
-    /*package*/ WebBackForwardList(CallbackProxy proxy) {
-        mCurrentIndex = -1;
-        mArray = new ArrayList<WebHistoryItem>();
-        mCallbackProxy = proxy;
+    public WebBackForwardList() {
     }
 
     /**
@@ -49,7 +37,7 @@
      * @return The current history item.
      */
     public synchronized WebHistoryItem getCurrentItem() {
-        return getItemAtIndex(mCurrentIndex);
+        throw new MustOverrideException();
     }
 
     /**
@@ -58,7 +46,7 @@
      * @return The current index from 0...n or -1 if the list is empty.
      */
     public synchronized int getCurrentIndex() {
-        return mCurrentIndex;
+        throw new MustOverrideException();
     }
 
     /**
@@ -67,10 +55,7 @@
      * @param index The index to retrieve.
      */
     public synchronized WebHistoryItem getItemAtIndex(int index) {
-        if (index < 0 || index >= getSize()) {
-            return null;
-        }
-        return mArray.get(index);
+        throw new MustOverrideException();
     }
 
     /**
@@ -78,78 +63,7 @@
      * @return The size of the list.
      */
     public synchronized int getSize() {
-        return mArray.size();
-    }
-
-    /**
-     * Mark the back/forward list as having a pending clear. This is used on the
-     * UI side to mark the list as being invalid during the clearHistory method.
-     */
-    /*package*/ synchronized void setClearPending() {
-        mClearPending = true;
-    }
-
-    /**
-     * Return the status of the clear flag. This is used on the UI side to
-     * determine if the list is valid for checking things like canGoBack.
-     */
-    /*package*/ synchronized boolean getClearPending() {
-        return mClearPending;
-    }
-
-    /**
-     * Add a new history item to the list. This will remove all items after the
-     * current item and append the new item to the end of the list. Called from
-     * the WebCore thread only. Synchronized because the UI thread may be
-     * reading the array or the current index.
-     * @param item A new history item.
-     */
-    /*package*/ synchronized void addHistoryItem(WebHistoryItem item) {
-        // Update the current position because we are going to add the new item
-        // in that slot.
-        ++mCurrentIndex;
-        // If the current position is not at the end, remove all history items
-        // after the current item.
-        final int size = mArray.size();
-        final int newPos = mCurrentIndex;
-        if (newPos != size) {
-            for (int i = size - 1; i >= newPos; i--) {
-                final WebHistoryItem h = mArray.remove(i);
-            }
-        }
-        // Add the item to the list.
-        mArray.add(item);
-        if (mCallbackProxy != null) {
-            mCallbackProxy.onNewHistoryItem(item);
-        }
-    }
-
-    /**
-     * Clear the back/forward list. Called from the WebCore thread.
-     */
-    /*package*/ synchronized void close(int nativeFrame) {
-        // Clear the array first because nativeClose will call addHistoryItem
-        // with the current item.
-        mArray.clear();
-        mCurrentIndex = -1;
-        nativeClose(nativeFrame);
-        // Reset the clear flag
-        mClearPending = false;
-    }
-
-    /* Remove the item at the given index. Called by JNI only. */
-    private synchronized void removeHistoryItem(int index) {
-        // XXX: This is a special case. Since the callback is only triggered
-        // when removing the first item, we can assert that the index is 0.
-        // This lets us change the current index without having to query the
-        // native BackForwardList.
-        if (DebugFlags.WEB_BACK_FORWARD_LIST && (index != 0)) {
-            throw new AssertionError();
-        }
-        final WebHistoryItem h = mArray.remove(index);
-        // XXX: If we ever add another callback for removing history items at
-        // any index, this will no longer be valid.
-        mCurrentIndex--;
+        throw new MustOverrideException();
     }
 
     /**
@@ -158,39 +72,7 @@
      * webkit package classes.
      */
     protected synchronized WebBackForwardList clone() {
-        WebBackForwardList l = new WebBackForwardList(null);
-        if (mClearPending) {
-            // If a clear is pending, return a copy with only the current item.
-            l.addHistoryItem(getCurrentItem());
-            return l;
-        }
-        l.mCurrentIndex = mCurrentIndex;
-        int size = getSize();
-        l.mArray = new ArrayList<WebHistoryItem>(size);
-        for (int i = 0; i < size; i++) {
-            // Add a copy of each WebHistoryItem
-            l.mArray.add(mArray.get(i).clone());
-        }
-        return l;
+        throw new MustOverrideException();
     }
 
-    /**
-     * Set the new history index.
-     * @param newIndex The new history index.
-     */
-    /*package*/ synchronized void setCurrentIndex(int newIndex) {
-        mCurrentIndex = newIndex;
-        if (mCallbackProxy != null) {
-            mCallbackProxy.onIndexChanged(getItemAtIndex(newIndex), newIndex);
-        }
-    }
-
-    /**
-     * Restore the history index.
-     */
-    /*package*/ static native synchronized void restoreIndex(int nativeFrame,
-            int index);
-
-    /* Close the native list. */
-    private static native void nativeClose(int nativeFrame);
 }
diff --git a/core/java/android/webkit/WebBackForwardListClassic.java b/core/java/android/webkit/WebBackForwardListClassic.java
new file mode 100644
index 0000000..2a14e6b
--- /dev/null
+++ b/core/java/android/webkit/WebBackForwardListClassic.java
@@ -0,0 +1,166 @@
+/*
+ * 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.webkit;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+
+/* package */ class WebBackForwardListClassic extends WebBackForwardList implements Cloneable,
+        Serializable {
+
+    // Current position in the list.
+    private int mCurrentIndex;
+    // ArrayList of WebHistoryItems for maintaining our copy.
+    private ArrayList<WebHistoryItemClassic> mArray;
+    // Flag to indicate that the list is invalid
+    private boolean mClearPending;
+    // CallbackProxy to issue client callbacks.
+    private final CallbackProxy mCallbackProxy;
+
+    /*package*/ WebBackForwardListClassic(CallbackProxy proxy) {
+        mCurrentIndex = -1;
+        mArray = new ArrayList<WebHistoryItemClassic>();
+        mCallbackProxy = proxy;
+    }
+
+    public synchronized WebHistoryItemClassic getCurrentItem() {
+        return getItemAtIndex(mCurrentIndex);
+    }
+
+    public synchronized int getCurrentIndex() {
+        return mCurrentIndex;
+    }
+
+    public synchronized WebHistoryItemClassic getItemAtIndex(int index) {
+        if (index < 0 || index >= getSize()) {
+            return null;
+        }
+        return mArray.get(index);
+    }
+
+    public synchronized int getSize() {
+        return mArray.size();
+    }
+
+    /**
+     * Mark the back/forward list as having a pending clear. This is used on the
+     * UI side to mark the list as being invalid during the clearHistory method.
+     */
+    /*package*/ synchronized void setClearPending() {
+        mClearPending = true;
+    }
+
+    /**
+     * Return the status of the clear flag. This is used on the UI side to
+     * determine if the list is valid for checking things like canGoBack.
+     */
+    /*package*/ synchronized boolean getClearPending() {
+        return mClearPending;
+    }
+
+    /**
+     * Add a new history item to the list. This will remove all items after the
+     * current item and append the new item to the end of the list. Called from
+     * the WebCore thread only. Synchronized because the UI thread may be
+     * reading the array or the current index.
+     * @param item A new history item.
+     */
+    /*package*/ synchronized void addHistoryItem(WebHistoryItem item) {
+        // Update the current position because we are going to add the new item
+        // in that slot.
+        ++mCurrentIndex;
+        // If the current position is not at the end, remove all history items
+        // after the current item.
+        final int size = mArray.size();
+        final int newPos = mCurrentIndex;
+        if (newPos != size) {
+            for (int i = size - 1; i >= newPos; i--) {
+                final WebHistoryItem h = mArray.remove(i);
+            }
+        }
+        // Add the item to the list.
+        mArray.add((WebHistoryItemClassic) item);
+        if (mCallbackProxy != null) {
+            mCallbackProxy.onNewHistoryItem(item);
+        }
+    }
+
+    /**
+     * Clear the back/forward list. Called from the WebCore thread.
+     */
+    /*package*/ synchronized void close(int nativeFrame) {
+        // Clear the array first because nativeClose will call addHistoryItem
+        // with the current item.
+        mArray.clear();
+        mCurrentIndex = -1;
+        nativeClose(nativeFrame);
+        // Reset the clear flag
+        mClearPending = false;
+    }
+
+    /* Remove the item at the given index. Called by JNI only. */
+    private synchronized void removeHistoryItem(int index) {
+        // XXX: This is a special case. Since the callback is only triggered
+        // when removing the first item, we can assert that the index is 0.
+        // This lets us change the current index without having to query the
+        // native BackForwardList.
+        if (DebugFlags.WEB_BACK_FORWARD_LIST && (index != 0)) {
+            throw new AssertionError();
+        }
+        final WebHistoryItem h = mArray.remove(index);
+        // XXX: If we ever add another callback for removing history items at
+        // any index, this will no longer be valid.
+        mCurrentIndex--;
+    }
+
+    public synchronized WebBackForwardListClassic clone() {
+        WebBackForwardListClassic l = new WebBackForwardListClassic(null);
+        if (mClearPending) {
+            // If a clear is pending, return a copy with only the current item.
+            l.addHistoryItem(getCurrentItem());
+            return l;
+        }
+        l.mCurrentIndex = mCurrentIndex;
+        int size = getSize();
+        l.mArray = new ArrayList<WebHistoryItemClassic>(size);
+        for (int i = 0; i < size; i++) {
+            // Add a copy of each WebHistoryItem
+            l.mArray.add(mArray.get(i).clone());
+        }
+        return l;
+    }
+
+    /**
+     * Set the new history index.
+     * @param newIndex The new history index.
+     */
+    /*package*/ synchronized void setCurrentIndex(int newIndex) {
+        mCurrentIndex = newIndex;
+        if (mCallbackProxy != null) {
+            mCallbackProxy.onIndexChanged(getItemAtIndex(newIndex), newIndex);
+        }
+    }
+
+    /**
+     * Restore the history index.
+     */
+    /*package*/ static native synchronized void restoreIndex(int nativeFrame,
+            int index);
+
+    /* Close the native list. */
+    private static native void nativeClose(int nativeFrame);
+}
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 4e8790b..e93db09 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -245,8 +245,8 @@
     }
 
    /**
-    * Tell the client that the quota has been reached for the Application Cache
-    * API and request a new quota. The client must respond by invoking the
+    * Notify the host application that the Application Cache has reached the
+    * maximum size. The client must respond by invoking the
     * {@link WebStorage.QuotaUpdater#updateQuota(long) updateQuota(long)}
     * method of the supplied {@link WebStorage.QuotaUpdater} instance. The
     * minimum value that can be set for the new quota is the current quota. The
@@ -255,7 +255,7 @@
     * @param requiredStorage The amount of storage required by the Application
     *                        Cache operation that triggered this notification,
     *                        in bytes.
-    * @param quota The quota, in bytes
+    * @param quota the current maximum Application Cache size, in bytes
     * @param quotaUpdater An instance of {@link WebStorage.QuotaUpdater} which
     *                     must be used to inform the WebView of the new quota.
     */
@@ -297,7 +297,12 @@
      * will continue to occur if the script does not finish at the next check
      * point.
      * @return boolean Whether the JavaScript execution should be interrupted.
+     * @deprecated This method is no longer supported and will not be invoked.
      */
+    // This method was only called when using the JSC javascript engine. V8 became
+    // the default JS engine with Froyo and support for building with JSC was
+    // removed in b/5495373. V8 does not have a mechanism for making a callback such
+    // as this.
     public boolean onJsTimeout() {
         return true;
     }
@@ -372,13 +377,6 @@
     }
 
     /**
-     * Tell the client that the page being viewed is web app capable,
-     * i.e. has specified the fullscreen-web-app-capable meta tag.
-     * @hide
-     */
-    public void setInstallableWebApp() { }
-
-    /**
      * Tell the client that the page being viewed has an autofillable
      * form and the user would like to set a profile up.
      * @param msg A Message to send once the user has successfully
diff --git a/core/java/android/webkit/WebHistoryItem.java b/core/java/android/webkit/WebHistoryItem.java
index 788d05c..9a588e4 100644
--- a/core/java/android/webkit/WebHistoryItem.java
+++ b/core/java/android/webkit/WebHistoryItem.java
@@ -18,9 +18,6 @@
 
 import android.graphics.Bitmap;
 
-import java.net.MalformedURLException;
-import java.net.URL;
-
 /**
  * A convenience class for accessing fields in an entry in the back/forward list
  * of a WebView. Each WebHistoryItem is a snapshot of the requested history
@@ -28,67 +25,11 @@
  * @see WebBackForwardList
  */
 public class WebHistoryItem implements Cloneable {
-    // Global identifier count.
-    private static int sNextId = 0;
-    // Unique identifier.
-    private final int mId;
-    // A point to a native WebHistoryItem instance which contains the actual data
-    private int mNativeBridge;
-    // The favicon for this item.
-    private Bitmap mFavicon;
-    // The pre-flattened data used for saving the state.
-    private byte[] mFlattenedData;
-    // The apple-touch-icon url for use when adding the site to the home screen,
-    // as obtained from a <link> element in the page.
-    private String mTouchIconUrlFromLink;
-    // If no <link> is specified, this holds the default location of the
-    // apple-touch-icon.
-    private String mTouchIconUrlServerDefault;
-    // Custom client data that is not flattened or read by native code.
-    private Object mCustomData;
 
     /**
-     * Basic constructor that assigns a unique id to the item. Called by JNI
-     * only.
+     * @hide
      */
-    private WebHistoryItem(int nativeBridge) {
-        synchronized (WebHistoryItem.class) {
-            mId = sNextId++;
-        }
-        mNativeBridge = nativeBridge;
-        nativeRef(mNativeBridge);
-    }
-
-    protected void finalize() throws Throwable {
-        if (mNativeBridge != 0) {
-            nativeUnref(mNativeBridge);
-            mNativeBridge = 0;
-        }
-    }
-
-    /**
-     * Construct a new WebHistoryItem with initial flattened data.
-     * @param data The pre-flattened data coming from restoreState.
-     */
-    /*package*/ WebHistoryItem(byte[] data) {
-        mFlattenedData = data;
-        synchronized (WebHistoryItem.class) {
-            mId = sNextId++;
-        }
-    }
-
-    /**
-     * Construct a clone of a WebHistoryItem from the given item.
-     * @param item The history item to clone.
-     */
-    private WebHistoryItem(WebHistoryItem item) {
-        mFlattenedData = item.mFlattenedData;
-        mId = item.mId;
-        mFavicon = item.mFavicon;
-        mNativeBridge = item.mNativeBridge;
-        if (mNativeBridge != 0) {
-            nativeRef(mNativeBridge);
-        }
+    public WebHistoryItem() {
     }
 
     /**
@@ -97,10 +38,11 @@
      * same object.
      * @return The id for this item.
      * @deprecated This method is now obsolete.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
     public int getId() {
-        return mId;
+        throw new MustOverrideException();
     }
 
     /**
@@ -112,8 +54,7 @@
      * to synchronize this method.
      */
     public String getUrl() {
-        if (mNativeBridge == 0) return null;
-        return nativeGetUrl(mNativeBridge);
+        throw new MustOverrideException();
     }
 
     /**
@@ -123,8 +64,7 @@
      * @return The original url of this history item.
      */
     public String getOriginalUrl() {
-        if (mNativeBridge == 0) return null;
-        return nativeGetOriginalUrl(mNativeBridge);
+        throw new MustOverrideException();
     }
     
     /**
@@ -134,8 +74,7 @@
      * to synchronize this method.
      */
     public String getTitle() {
-        if (mNativeBridge == 0) return null;
-        return nativeGetTitle(mNativeBridge);
+        throw new MustOverrideException();
     }
 
     /**
@@ -145,119 +84,14 @@
      * to synchronize this method.
      */
     public Bitmap getFavicon() {
-        if (mFavicon == null && mNativeBridge != 0) {
-            mFavicon = nativeGetFavicon(mNativeBridge);
-        }
-        return mFavicon;
-    }
-
-    /**
-     * Return the touch icon url.
-     * If no touch icon <link> tag was specified, returns
-     * <host>/apple-touch-icon.png. The DownloadTouchIcon class that
-     * attempts to retrieve the touch icon will handle the case where
-     * that file does not exist. An icon set by a <link> tag is always
-     * used in preference to an icon saved on the server.
-     * @hide
-     */
-    public String getTouchIconUrl() {
-        if (mTouchIconUrlFromLink != null) {
-            return mTouchIconUrlFromLink;
-        } else if (mTouchIconUrlServerDefault != null) {
-            return mTouchIconUrlServerDefault;
-        }
-
-        try {
-            URL url = new URL(getOriginalUrl());
-            mTouchIconUrlServerDefault = new URL(url.getProtocol(), url.getHost(), url.getPort(),
-                    "/apple-touch-icon.png").toString();
-        } catch (MalformedURLException e) {
-            return null;
-        }
-        return mTouchIconUrlServerDefault;
-    }
-
-    /**
-     * Return the custom data provided by the client.
-     * @hide
-     */
-    public Object getCustomData() {
-        return mCustomData;
-    }
-
-    /**
-     * Set the custom data field.
-     * @param data An Object containing any data the client wishes to associate
-     *             with the item.
-     * @hide
-     */
-    public void setCustomData(Object data) {
-        // NOTE: WebHistoryItems are used in multiple threads. However, the
-        // public facing apis are all getters with the exception of this one
-        // api. Since this api is exclusive to clients, we don't make any
-        // promises about thread safety.
-        mCustomData = data;
-    }
-
-    /**
-     * Set the favicon.
-     * @param icon A Bitmap containing the favicon for this history item.
-     * Note: The VM ensures 32-bit atomic read/write operations so we don't have
-     * to synchronize this method.
-     */
-    /*package*/ void setFavicon(Bitmap icon) {
-        mFavicon = icon;
-    }
-
-    /**
-     * Set the touch icon url. Will not overwrite an icon that has been
-     * set already from a <link> tag, unless the new icon is precomposed.
-     * @hide
-     */
-    /*package*/ void setTouchIconUrl(String url, boolean precomposed) {
-        if (precomposed || mTouchIconUrlFromLink == null) {
-            mTouchIconUrlFromLink = url;
-        }
-    }
-
-    /**
-     * Get the pre-flattened data.
-     * Note: The VM ensures 32-bit atomic read/write operations so we don't have
-     * to synchronize this method.
-     */
-    /*package*/ byte[] getFlattenedData() {
-        if (mNativeBridge != 0) {
-            return nativeGetFlattenedData(mNativeBridge);
-        }
-        return mFlattenedData;
-    }
-
-    /**
-     * Inflate this item.
-     * Note: The VM ensures 32-bit atomic read/write operations so we don't have
-     * to synchronize this method.
-     */
-    /*package*/ void inflate(int nativeFrame) {
-        mNativeBridge = inflate(nativeFrame, mFlattenedData);
-        mFlattenedData = null;
+        throw new MustOverrideException();
     }
 
     /**
      * Clone the history item for use by clients of WebView.
      */
     protected synchronized WebHistoryItem clone() {
-        return new WebHistoryItem(this);
+        throw new MustOverrideException();
     }
 
-    /* Natively inflate this item, this method is called in the WebCore thread.
-     */
-    private native int inflate(int nativeFrame, byte[] data);
-    private native void nativeRef(int nptr);
-    private native void nativeUnref(int nptr);
-    private native String nativeGetTitle(int nptr);
-    private native String nativeGetUrl(int nptr);
-    private native String nativeGetOriginalUrl(int nptr);
-    private native byte[] nativeGetFlattenedData(int nptr);
-    private native Bitmap nativeGetFavicon(int nptr);
-
 }
diff --git a/core/java/android/webkit/WebHistoryItemClassic.java b/core/java/android/webkit/WebHistoryItemClassic.java
new file mode 100644
index 0000000..1620fbf
--- /dev/null
+++ b/core/java/android/webkit/WebHistoryItemClassic.java
@@ -0,0 +1,221 @@
+/*
+ * 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.webkit;
+
+import android.graphics.Bitmap;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/* package */ class WebHistoryItemClassic extends WebHistoryItem implements Cloneable {
+    // Global identifier count.
+    private static int sNextId = 0;
+    // Unique identifier.
+    private final int mId;
+    // A point to a native WebHistoryItem instance which contains the actual data
+    private int mNativeBridge;
+    // The favicon for this item.
+    private Bitmap mFavicon;
+    // The pre-flattened data used for saving the state.
+    private byte[] mFlattenedData;
+    // The apple-touch-icon url for use when adding the site to the home screen,
+    // as obtained from a <link> element in the page.
+    private String mTouchIconUrlFromLink;
+    // If no <link> is specified, this holds the default location of the
+    // apple-touch-icon.
+    private String mTouchIconUrlServerDefault;
+    // Custom client data that is not flattened or read by native code.
+    private Object mCustomData;
+
+    /**
+     * Basic constructor that assigns a unique id to the item. Called by JNI
+     * only.
+     */
+    private WebHistoryItemClassic(int nativeBridge) {
+        synchronized (WebHistoryItemClassic.class) {
+            mId = sNextId++;
+        }
+        mNativeBridge = nativeBridge;
+        nativeRef(mNativeBridge);
+    }
+
+    protected void finalize() throws Throwable {
+        if (mNativeBridge != 0) {
+            nativeUnref(mNativeBridge);
+            mNativeBridge = 0;
+        }
+    }
+
+    /**
+     * Construct a new WebHistoryItem with initial flattened data.
+     * @param data The pre-flattened data coming from restoreState.
+     */
+    /*package*/ WebHistoryItemClassic(byte[] data) {
+        mFlattenedData = data;
+        synchronized (WebHistoryItemClassic.class) {
+            mId = sNextId++;
+        }
+    }
+
+    /**
+     * Construct a clone of a WebHistoryItem from the given item.
+     * @param item The history item to clone.
+     */
+    private WebHistoryItemClassic(WebHistoryItemClassic item) {
+        mFlattenedData = item.mFlattenedData;
+        mId = item.mId;
+        mFavicon = item.mFavicon;
+        mNativeBridge = item.mNativeBridge;
+        if (mNativeBridge != 0) {
+            nativeRef(mNativeBridge);
+        }
+    }
+
+    @Deprecated
+    public int getId() {
+        return mId;
+    }
+
+    public String getUrl() {
+        if (mNativeBridge == 0) return null;
+        return nativeGetUrl(mNativeBridge);
+    }
+
+    public String getOriginalUrl() {
+        if (mNativeBridge == 0) return null;
+        return nativeGetOriginalUrl(mNativeBridge);
+    }
+
+    public String getTitle() {
+        if (mNativeBridge == 0) return null;
+        return nativeGetTitle(mNativeBridge);
+    }
+
+    public Bitmap getFavicon() {
+        if (mFavicon == null && mNativeBridge != 0) {
+            mFavicon = nativeGetFavicon(mNativeBridge);
+        }
+        return mFavicon;
+    }
+
+    /**
+     * Return the touch icon url.
+     * If no touch icon <link> tag was specified, returns
+     * <host>/apple-touch-icon.png. The DownloadTouchIcon class that
+     * attempts to retrieve the touch icon will handle the case where
+     * that file does not exist. An icon set by a <link> tag is always
+     * used in preference to an icon saved on the server.
+     * @hide
+     */
+    public String getTouchIconUrl() {
+        if (mTouchIconUrlFromLink != null) {
+            return mTouchIconUrlFromLink;
+        } else if (mTouchIconUrlServerDefault != null) {
+            return mTouchIconUrlServerDefault;
+        }
+
+        try {
+            URL url = new URL(getOriginalUrl());
+            mTouchIconUrlServerDefault = new URL(url.getProtocol(), url.getHost(), url.getPort(),
+                    "/apple-touch-icon.png").toString();
+        } catch (MalformedURLException e) {
+            return null;
+        }
+        return mTouchIconUrlServerDefault;
+    }
+
+    /**
+     * Return the custom data provided by the client.
+     * @hide
+     */
+    public Object getCustomData() {
+        return mCustomData;
+    }
+
+    /**
+     * Set the custom data field.
+     * @param data An Object containing any data the client wishes to associate
+     *             with the item.
+     * @hide
+     */
+    public void setCustomData(Object data) {
+        // NOTE: WebHistoryItems are used in multiple threads. However, the
+        // public facing apis are all getters with the exception of this one
+        // api. Since this api is exclusive to clients, we don't make any
+        // promises about thread safety.
+        mCustomData = data;
+    }
+
+    /**
+     * Set the favicon.
+     * @param icon A Bitmap containing the favicon for this history item.
+     * Note: The VM ensures 32-bit atomic read/write operations so we don't have
+     * to synchronize this method.
+     */
+    /*package*/ void setFavicon(Bitmap icon) {
+        mFavicon = icon;
+    }
+
+    /**
+     * Set the touch icon url. Will not overwrite an icon that has been
+     * set already from a <link> tag, unless the new icon is precomposed.
+     * @hide
+     */
+    /*package*/ void setTouchIconUrl(String url, boolean precomposed) {
+        if (precomposed || mTouchIconUrlFromLink == null) {
+            mTouchIconUrlFromLink = url;
+        }
+    }
+
+    /**
+     * Get the pre-flattened data.
+     * Note: The VM ensures 32-bit atomic read/write operations so we don't have
+     * to synchronize this method.
+     */
+    /*package*/ byte[] getFlattenedData() {
+        if (mNativeBridge != 0) {
+            return nativeGetFlattenedData(mNativeBridge);
+        }
+        return mFlattenedData;
+    }
+
+    /**
+     * Inflate this item.
+     * Note: The VM ensures 32-bit atomic read/write operations so we don't have
+     * to synchronize this method.
+     */
+    /*package*/ void inflate(int nativeFrame) {
+        mNativeBridge = inflate(nativeFrame, mFlattenedData);
+        mFlattenedData = null;
+    }
+
+    public synchronized WebHistoryItemClassic clone() {
+        return new WebHistoryItemClassic(this);
+    }
+
+    /* Natively inflate this item, this method is called in the WebCore thread.
+     */
+    private native int inflate(int nativeFrame, byte[] data);
+    private native void nativeRef(int nptr);
+    private native void nativeUnref(int nptr);
+    private native String nativeGetTitle(int nptr);
+    private native String nativeGetUrl(int nptr);
+    private native String nativeGetOriginalUrl(int nptr);
+    private native byte[] nativeGetFlattenedData(int nptr);
+    private native Bitmap nativeGetFavicon(int nptr);
+
+}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index fa3cb20..aa68904 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -16,8 +16,7 @@
 
 package android.webkit;
 
-import android.os.Message;
-import android.os.Build;
+import android.content.Context;
 
 /**
  * Manages settings state for a WebView. When a WebView is first created, it
@@ -94,30 +93,38 @@
     }
 
     /**
-     * Default cache usage pattern. Use with {@link #setCacheMode}.
+     * Default cache usage mode. If the navigation type doesn't impose any
+     * specific behavior, use cached resources when they are available
+     * and not expired, otherwise load resources from the network.
+     * Use with {@link #setCacheMode}.
      */
     public static final int LOAD_DEFAULT = -1;
 
     /**
-     * Normal cache usage pattern. Use with {@link #setCacheMode}.
+     * Normal cache usage mode. Use with {@link #setCacheMode}.
+     *
+     * @deprecated This value is obsolete, as from API level
+     * {@link android.os.Build.VERSION_CODES#HONEYCOMB} and onwards it has the
+     * same effect as {@link #LOAD_DEFAULT}.
      */
+    @Deprecated
     public static final int LOAD_NORMAL = 0;
 
     /**
-     * Use cache if content is there, even if expired (eg, history nav).
-     * If it is not in the cache, load from network.
+     * Use cached resources when they are available, even if they have expired.
+     * Otherwise load resources from the network.
      * Use with {@link #setCacheMode}.
      */
     public static final int LOAD_CACHE_ELSE_NETWORK = 1;
 
     /**
-     * Don't use the cache, load from network.
+     * Don't use the cache, load from the network.
      * Use with {@link #setCacheMode}.
      */
     public static final int LOAD_NO_CACHE = 2;
 
     /**
-     * Don't use the network, load from cache only.
+     * Don't use the network, load from the cache.
      * Use with {@link #setCacheMode}.
      */
     public static final int LOAD_CACHE_ONLY = 3;
@@ -153,9 +160,11 @@
     }
 
     /**
-     * Enables dumping the pages navigation cache to a text file.
+     * Enables dumping the pages navigation cache to a text file. The default
+     * is false.
      *
      * @deprecated This method is now obsolete.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
     public void setNavDump(boolean enabled) {
@@ -165,7 +174,10 @@
     /**
      * Gets whether dumping the navigation cache is enabled.
      *
+     * @return whether dumping the navigation cache is enabled
+     * @see #setNavDump
      * @deprecated This method is now obsolete.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
     public boolean getNavDump() {
@@ -196,6 +208,26 @@
     }
 
     /**
+     * Sets whether the WebView requires a user gesture to play media.
+     * The default is true.
+     *
+     * @param require whether the WebView requires a user gesture to play media
+     */
+    public void setMediaPlaybackRequiresUserGesture(boolean require) {
+        throw new MustOverrideException();
+    }
+
+    /**
+     * Gets whether the WebView requires a user gesture to play media.
+     *
+     * @return true if the WebView requires a user gesture to play media
+     * @see #setMediaPlaybackRequiresUserGesture
+     */
+    public boolean getMediaPlaybackRequiresUserGesture() {
+        throw new MustOverrideException();
+    }
+
+    /**
      * Sets whether the WebView should use its built-in zoom mechanisms. The
      * built-in zoom mechanisms comprise on-screen zoom controls, which are
      * displayed over the WebView's content, and the use of a pinch gesture to
@@ -285,14 +317,18 @@
     }
 
     /**
-     * Sets whether the WebView loads a page with overview mode.
+     * Sets whether the WebView loads pages in overview mode. The default is
+     * false.
      */
     public void setLoadWithOverviewMode(boolean overview) {
         throw new MustOverrideException();
     }
 
     /**
-     * Gets whether this WebView loads pages with overview mode.
+     * Gets whether this WebView loads pages in overview mode.
+     *
+     * @return whether this WebView loads pages in overview mode
+     * @see #setLoadWithOverviewMode
      */
     public boolean getLoadWithOverviewMode() {
         throw new MustOverrideException();
@@ -304,7 +340,10 @@
      * If it is true, WebView will choose a solution to maximize the performance.
      * e.g. the WebView's content may not be updated during the transition.
      * If it is false, WebView will keep its fidelity. The default value is false.
+     *
+     * @deprecated This method is now obsolete, and will become a no-op in future.
      */
+    @Deprecated
     public void setEnableSmoothTransition(boolean enable) {
         throw new MustOverrideException();
     }
@@ -314,7 +353,10 @@
      * zooming.
      *
      * @see #setEnableSmoothTransition
+     *
+     * @deprecated This method is now obsolete, and will become a no-op in future.
      */
+    @Deprecated
     public boolean enableSmoothTransition() {
         throw new MustOverrideException();
     }
@@ -325,6 +367,7 @@
      * internal pattern. Default is true.
      *
      * @deprecated This method is now obsolete.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
     public void setUseWebViewBackgroundForOverscrollBackground(boolean view) {
@@ -337,6 +380,7 @@
      *
      * @see #setUseWebViewBackgroundForOverscrollBackground
      * @deprecated This method is now obsolete.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
     public boolean getUseWebViewBackgroundForOverscrollBackground() {
@@ -344,38 +388,45 @@
     }
 
     /**
-     * Sets whether the WebView is saving form data.
+     * Sets whether the WebView should save form data. The default is true,
+     * unless in private browsing mode, when the value is always false.
      */
     public void setSaveFormData(boolean save) {
         throw new MustOverrideException();
     }
 
     /**
-     * Gets whether the WebView is saving form data and displaying prior
-     * entries/autofill++.  Always false in private browsing mode.
+     * Gets whether the WebView saves form data. Always false in private
+     * browsing mode.
+     *
+     * @return whether the WebView saves form data
+     * @see #setSaveFormData
      */
     public boolean getSaveFormData() {
         throw new MustOverrideException();
     }
 
     /**
-     * Stores whether the WebView is saving password.
+     * Sets whether the WebView should save passwords. The default is true.
      */
     public void setSavePassword(boolean save) {
         throw new MustOverrideException();
     }
 
     /**
-     * Gets whether the WebView is saving password.
+     * Gets whether the WebView saves passwords.
+     *
+     * @return whether the WebView saves passwords
+     * @see #setSavePassword
      */
     public boolean getSavePassword() {
         throw new MustOverrideException();
     }
 
     /**
-     * Sets the text zoom of the page in percent. Default is 100.
+     * Sets the text zoom of the page in percent. The default is 100.
      *
-     * @param textZoom the percent value for increasing or decreasing the text
+     * @param textZoom the text zoom in percent
      */
     public synchronized void setTextZoom(int textZoom) {
         throw new MustOverrideException();
@@ -384,53 +435,65 @@
     /**
      * Gets the text zoom of the page in percent.
      *
-     * @return a percent value describing the text zoom
-     * @see #setTextSizeZoom
+     * @return the text zoom of the page in percent
+     * @see #setTextZoom
      */
     public synchronized int getTextZoom() {
         throw new MustOverrideException();
     }
 
     /**
-     * Sets the text size of the page.
+     * Sets the text size of the page. The default is {@link TextSize#NORMAL}.
      *
-     * @param t the TextSize value for increasing or decreasing the text
-     * @see WebSettings.TextSize
-     * @deprecated Use {@link #setTextZoom(int)} instead.
+     * @param t the text size as a {@link TextSize} value
+     * @deprecated Use {@link #setTextZoom} instead.
      */
     public synchronized void setTextSize(TextSize t) {
-        throw new MustOverrideException();
+        setTextZoom(t.value);
     }
 
     /**
      * Gets the text size of the page. If the text size was previously specified
-     * in percent using {@link #setTextZoom(int)}, this will return
-     * the closest matching {@link TextSize}.
+     * in percent using {@link #setTextZoom}, this will return the closest
+     * matching {@link TextSize}.
      *
-     * @return a TextSize enum value describing the text size
-     * @see WebSettings.TextSize
-     * @deprecated Use {@link #getTextZoom()} instead.
+     * @return the text size as a {@link TextSize} value
+     * @see #setTextSize
+     * @deprecated Use {@link #getTextZoom} instead.
      */
     public synchronized TextSize getTextSize() {
-        throw new MustOverrideException();
+        TextSize closestSize = null;
+        int smallestDelta = Integer.MAX_VALUE;
+        int textSize = getTextZoom();
+        for (TextSize size : TextSize.values()) {
+            int delta = Math.abs(textSize - size.value);
+            if (delta == 0) {
+                return size;
+            }
+            if (delta < smallestDelta) {
+                smallestDelta = delta;
+                closestSize = size;
+            }
+        }
+        return closestSize != null ? closestSize : TextSize.NORMAL;
     }
 
     /**
-     * Sets the default zoom density of the page. This should be called from UI
-     * thread.
+     * Sets the default zoom density of the page. This must be called from the UI
+     * thread. The default is {@link ZoomDensity#MEDIUM}.
      *
-     * @param zoom a ZoomDensity value
-     * @see WebSettings.ZoomDensity
+     * @param zoom the zoom density
      */
     public void setDefaultZoom(ZoomDensity zoom) {
         throw new MustOverrideException();
     }
 
     /**
-     * Gets the default zoom density of the page. This should be called from UI
-     * thread.
-     * @return a ZoomDensity value
-     * @see WebSettings.ZoomDensity
+     * Gets the default zoom density of the page. This should be called from
+     * the UI thread.
+     *
+     * @return the zoom density
+     * @see #setDefaultZoom
      */
     public ZoomDensity getDefaultZoom() {
         throw new MustOverrideException();
@@ -438,6 +501,7 @@
 
     /**
      * Enables using light touches to make a selection and activate mouseovers.
+     * The default is false.
      */
     public void setLightTouchEnabled(boolean enabled) {
         throw new MustOverrideException();
@@ -445,6 +509,9 @@
 
     /**
      * Gets whether light touches are enabled.
+     *
+     * @return whether light touches are enabled
+     * @see #setLightTouchEnabled
      */
     public boolean getLightTouchEnabled() {
         throw new MustOverrideException();
@@ -455,6 +522,7 @@
      * it now has no effect.
      *
      * @deprecated This setting now has no effect.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
     public synchronized void setUseDoubleTree(boolean use) {
@@ -466,6 +534,7 @@
      * it now has no effect.
      *
      * @deprecated This setting now has no effect.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
     public synchronized boolean getUseDoubleTree() {
@@ -474,11 +543,17 @@
     }
 
     /**
-     * Tells the WebView about user-agent string.
+     * Sets the user-agent string using an integer code.
+     * <ul>
+     *   <li>0 means the WebView should use an Android user-agent string</li>
+     *   <li>1 means the WebView should use a desktop user-agent string</li>
+     * </ul>
+     * Other values are ignored. The default is an Android user-agent string,
+     * i.e. code value 0.
      *
-     * @param ua 0 if the WebView should use an Android user-agent string,
-     *           1 if the WebView should use a desktop user-agent string
-     * @deprecated Please use setUserAgentString instead.
+     * @param ua the integer code for the user-agent string
+     * @deprecated Please use {@link #setUserAgentString} instead.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
     public synchronized void setUserAgent(int ua) {
@@ -486,12 +561,18 @@
     }
 
     /**
-     * Gets the user-agent as an int.
+     * Gets the user-agent as an integer code.
+     * <ul>
+     *   <li>-1 means the WebView is using a custom user-agent string set with
+     *   {@link #setUserAgentString}</li>
+     *   <li>0 means the WebView should use an Android user-agent string</li>
+     *   <li>1 means the WebView should use a desktop user-agent string</li>
+     * </ul>
      *
-     * @return 0 if the WebView is using an Android user-agent string,
-     *         1 if the WebView is using a desktop user-agent string,
-     *         -1 if the WebView is using user defined user-agent string
-     * @deprecated Please use getUserAgentString instead.
+     * @return the integer code for the user-agent string
+     * @see #setUserAgent
+     * @deprecated Please use {@link #getUserAgentString} instead.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
     public synchronized int getUserAgent() {
@@ -499,7 +580,9 @@
     }
 
     /**
-     * Tells the WebView to use the wide viewport.
+     * Tells the WebView to use a wide viewport. The default is false.
+     *
+     * @param use whether to use a wide viewport
      */
     public synchronized void setUseWideViewPort(boolean use) {
         throw new MustOverrideException();
@@ -509,26 +592,28 @@
      * Gets whether the WebView is using a wide viewport.
      *
      * @return true if the WebView is using a wide viewport
+     * @see #setUseWideViewPort
      */
     public synchronized boolean getUseWideViewPort() {
         throw new MustOverrideException();
     }
 
     /**
-     * Tells the WebView whether it supports multiple windows. TRUE means
-     * that {@link WebChromeClient#onCreateWindow(WebView, boolean,
-     * boolean, Message)} is implemented by the host application.
+     * Sets whether the WebView whether supports multiple windows. If set to
+     * true, {@link WebChromeClient#onCreateWindow} must be implemented by the
+     * host application. The default is false.
+     *
+     * @param support whether to suport multiple windows
      */
     public synchronized void setSupportMultipleWindows(boolean support) {
         throw new MustOverrideException();
     }
 
     /**
-     * Gets whether the WebView is supporting multiple windows.
+     * Gets whether the WebView supports multiple windows.
      *
-     * @return true if the WebView is supporting multiple windows. This means
-     *         that {@link WebChromeClient#onCreateWindow(WebView, boolean,
-     *         boolean, Message)} is implemented by the host application.
+     * @return true if the WebView supports multiple windows
+     * @see #setSupportMultipleWindows
      */
     public synchronized boolean supportMultipleWindows() {
         throw new MustOverrideException();
@@ -536,10 +621,9 @@
 
     /**
      * Sets the underlying layout algorithm. This will cause a relayout of the
-     * WebView. The default is NARROW_COLUMNS.
+     * WebView. The default is {@link LayoutAlgorithm#NARROW_COLUMNS}.
      *
-     * @param l a LayoutAlgorithm enum specifying the algorithm to use
-     * @see WebSettings.LayoutAlgorithm
+     * @param l the layout algorithm to use, as a {@link LayoutAlgorithm} value
      */
     public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) {
         throw new MustOverrideException();
@@ -548,10 +632,8 @@
     /**
      * Gets the current layout algorithm.
      *
-     * @return a LayoutAlgorithm enum value describing the layout algorithm
-     *         being used
+     * @return the layout algorithm in use, as a {@link LayoutAlgorithm} value
      * @see #setLayoutAlgorithm
-     * @see WebSettings.LayoutAlgorithm
      */
     public synchronized LayoutAlgorithm getLayoutAlgorithm() {
         throw new MustOverrideException();
@@ -596,7 +678,7 @@
     }
 
     /**
-     * Sets the sans-serif font family name.
+     * Sets the sans-serif font family name. The default is "sans-serif".
      *
      * @param font a font family name
      */
@@ -608,6 +690,7 @@
      * Gets the sans-serif font family name.
      *
      * @return the sans-serif font family name as a string
+     * @see #setSansSerifFontFamily
      */
     public synchronized String getSansSerifFontFamily() {
         throw new MustOverrideException();
@@ -883,9 +966,9 @@
     public abstract void setAllowFileAccessFromFileURLs(boolean flag);
 
     /**
-     * Tells the WebView to enable plugins.
+     * Sets whether the WebView should enable plugins. The default is false.
      *
-     * @param flag true if the WebView should load plugins
+     * @param flag true if plugins should be enabled
      * @deprecated This method has been deprecated in favor of
      *             {@link #setPluginState}
      */
@@ -898,7 +981,8 @@
      * Tells the WebView to enable, disable, or have plugins on demand. On
      * demand mode means that if a plugin exists that can handle the embedded
      * content, a placeholder icon will be shown instead of the plugin. When
-     * the placeholder is clicked, the plugin will be enabled.
+     * the placeholder is clicked, the plugin will be enabled. The default is
+     * {@link PluginState#OFF}.
      *
      * @param state a PluginState value
      */
@@ -921,23 +1005,27 @@
 
     /**
      * Sets the path to where database storage API databases should be saved.
-     * Note that the WebCore Database Tracker only allows the path to be set once.
+     * In order for the database storage API to function correctly, this method
+     * must be called with a path to which the application can write. This
+     * method should only be called once: repeated calls are ignored.
      *
-     * @param databasePath a String path to the directory where databases should
-     *                     be saved. May be the empty string but should never
-     *                     be null.
+     * @param databasePath a path to the directory where databases should be
+     *                     saved.
      */
     // This will update WebCore when the Sync runs in the C++ side.
+    // Note that the WebCore Database Tracker only allows the path to be set
+    // once.
     public synchronized void setDatabasePath(String databasePath) {
         throw new MustOverrideException();
     }
 
     /**
-     * Sets the path where the Geolocation permissions database should be saved.
+     * Sets the path where the Geolocation databases should be saved. In order
+     * for Geolocation permissions and cached positions to be persisted, this
+     * method must be called with a path to which the application can write.
      *
-     * @param databasePath a String path to the directory where the Geolocation
-     *                     permissions database should be saved. May be the
-     *                     empty string but should never be null.
+     * @param databasePath a path to the directory where databases should be
+     *                     saved.
      */
     // This will update WebCore when the Sync runs in the C++ side.
     public synchronized void setGeolocationDatabasePath(String databasePath) {
@@ -945,7 +1033,10 @@
     }
 
     /**
-     * Tells the WebView to enable Application Caches API.
+     * Sets whether the Application Caches API should be enabled. The default
+     * is false. Note that in order for the Application Caches API to be
+     * enabled, a valid database path must also be supplied to
+     * {@link #setAppCachePath}.
      *
      * @param flag true if the WebView should enable Application Caches
      */
@@ -954,20 +1045,25 @@
     }
 
     /**
-     * Sets a custom path to the Application Caches files. The client
-     * must ensure it exists before this call.
+     * Sets the path to the Application Caches files. In order for the
+     * Application Caches API to be enabled, this method must be called with a
+     * path to which the application can write. This method should only be
+     * called once: repeated calls are ignored.
      *
      * @param appCachePath a String path to the directory containing
-     *                     Application Caches files. The appCache path can be
-     *                     the empty string but should not be null. Passing
-     *                     null for this parameter will result in a no-op.
+     *                     Application Caches files.
+     * @see setAppCacheEnabled
      */
     public synchronized void setAppCachePath(String appCachePath) {
         throw new MustOverrideException();
     }
 
     /**
-     * Sets the maximum size for the Application Caches content.
+     * Sets the maximum size for the Application Cache content. The passed size
+     * will be rounded to the nearest value that the database can support, so
+     * this should be viewed as a guide, not a hard limit. Setting the
+     * size to a value less than current database size does not cause the
+     * database to be trimmed. The default size is {@link Long#MAX_VALUE}.
      *
      * @param appCacheMaxSize the maximum size in bytes
      */
@@ -976,7 +1072,9 @@
     }
 
     /**
-     * Sets whether the database storage API is enabled.
+     * Sets whether the database storage API is enabled. The default value is
+     * false. See also {@link #setDatabasePath} for how to correctly set up the
+     * database storage API.
      *
      * @param flag true if the WebView should use the database storage API
      */
@@ -985,7 +1083,7 @@
     }
 
     /**
-     * Sets whether the DOM storage API is enabled.
+     * Sets whether the DOM storage API is enabled. The default value is false.
      *
      * @param flag true if the WebView should use the DOM storage API
      */
@@ -997,15 +1095,16 @@
      * Gets whether the DOM Storage APIs are enabled.
      *
      * @return true if the DOM Storage APIs are enabled
+     * @see #setDomStorageEnabled
      */
     public synchronized boolean getDomStorageEnabled() {
         throw new MustOverrideException();
     }
     /**
-     * Gets the path to where database storage API databases are saved for
-     * the current WebView.
+     * Gets the path to where database storage API databases are saved.
      *
      * @return the String path to the database storage API databases
+     * @see #setDatabasePath
      */
     public synchronized String getDatabasePath() {
         throw new MustOverrideException();
@@ -1015,13 +1114,16 @@
      * Gets whether the database storage API is enabled.
      *
      * @return true if the database storage API is enabled
+     * @see #setDatabaseEnabled
      */
     public synchronized boolean getDatabaseEnabled() {
         throw new MustOverrideException();
     }
 
     /**
-     * Sets whether Geolocation is enabled.
+     * Sets whether Geolocation is enabled. The default is true. See also
+     * {@link #setGeolocationDatabasePath} for how to correctly set up
+     * Geolocation.
      *
      * @param flag whether Geolocation should be enabled
      */
@@ -1064,6 +1166,7 @@
      * Gets whether plugins are enabled.
      *
      * @return true if plugins are enabled
+     * @see #setPluginsEnabled
      * @deprecated This method has been replaced by {@link #getPluginState}
      */
     @Deprecated
@@ -1072,9 +1175,10 @@
     }
 
     /**
-     * Gets the current plugin state.
+     * Gets the current state regarding whether plugins are enabled.
      *
-     * @return a value corresponding to the enum PluginState
+     * @return the plugin state as a {@link PluginState} value
+     * @see #setPluginState
      */
     public synchronized PluginState getPluginState() {
         throw new MustOverrideException();
@@ -1135,8 +1239,8 @@
     }
 
     /**
-     * Sets the WebView's user-agent string. If the string "ua" is null or empty,
-     * it will use the system default user-agent string.
+     * Sets the WebView's user-agent string. If the string is null or empty,
+     * the system default value will be used.
      */
     public synchronized void setUserAgentString(String ua) {
         throw new MustOverrideException();
@@ -1144,14 +1248,29 @@
 
     /**
      * Gets the WebView's user-agent string.
+     *
+     * @return the WebView's user-agent string
+     * @see #setUserAgentString
      */
     public synchronized String getUserAgentString() {
         throw new MustOverrideException();
     }
 
     /**
+     * Returns the default User-Agent used by a WebView.
+     * An instance of WebView could use a different User-Agent if a call
+     * is made to {@link WebSettings#setUserAgentString(String)}.
+     *
+     * @param context a Context object used to access application assets
+     */
+    public static String getDefaultUserAgent(Context context) {
+        return WebViewFactory.getProvider().getStatics().getDefaultUserAgent(context);
+    }
+
+    /**
      * Tells the WebView whether it needs to set a node to have focus when
-     * {@link WebView#requestFocus(int, android.graphics.Rect)} is called.
+     * {@link WebView#requestFocus(int, android.graphics.Rect)} is called. The
+     * default value is true.
      *
      * @param flag whether the WebView needs to set a node
      */
@@ -1161,9 +1280,10 @@
 
     /**
      * Sets the priority of the Render thread. Unlike the other settings, this
-     * one only needs to be called once per process. The default is NORMAL.
+     * one only needs to be called once per process. The default value is
+     * {@link RenderPriority#NORMAL}.
      *
-     * @param priority a RenderPriority
+     * @param priority the priority
      */
     public synchronized void setRenderPriority(RenderPriority priority) {
         throw new MustOverrideException();
@@ -1171,20 +1291,25 @@
 
     /**
      * Overrides the way the cache is used. The way the cache is used is based
-     * on the navigation option. For a normal page load, the cache is checked
+     * on the navigation type. For a normal page load, the cache is checked
      * and content is re-validated as needed. When navigating back, content is
-     * not revalidated, instead the content is just pulled from the cache.
-     * This function allows the client to override this behavior.
+     * not revalidated, instead the content is just retrieved from the cache.
+     * This method allows the client to override this behavior by specifying
+     * one of {@link #LOAD_DEFAULT}, {@link #LOAD_NORMAL},
+     * {@link #LOAD_CACHE_ELSE_NETWORK}, {@link #LOAD_NO_CACHE} or
+     * {@link #LOAD_CACHE_ONLY}. The default value is {@link #LOAD_DEFAULT}.
      *
-     * @param mode one of the LOAD_ values
+     * @param mode the mode to use
      */
     public void setCacheMode(int mode) {
         throw new MustOverrideException();
     }
 
     /**
-     * Gets the current setting for overriding the cache mode. For a full
-     * description, see the {@link #setCacheMode(int)} function.
+     * Gets the current setting for overriding the cache mode.
+     *
+     * @return the current setting for overriding the cache mode
+     * @see #setCacheMode
      */
     public int getCacheMode() {
         throw new MustOverrideException();
diff --git a/core/java/android/webkit/WebSettingsClassic.java b/core/java/android/webkit/WebSettingsClassic.java
index 1288613..1bbe7bb 100644
--- a/core/java/android/webkit/WebSettingsClassic.java
+++ b/core/java/android/webkit/WebSettingsClassic.java
@@ -34,7 +34,7 @@
  */
 public class WebSettingsClassic extends WebSettings {
     // TODO: Keep this up to date
-    private static final String PREVIOUS_VERSION = "4.0.4";
+    private static final String PREVIOUS_VERSION = "4.1.1";
 
     // WebView associated with this WebSettings.
     private WebViewClassic mWebView;
@@ -116,6 +116,7 @@
     private boolean         mNeedInitialFocus = true;
     private boolean         mNavDump = false;
     private boolean         mSupportZoom = true;
+    private boolean         mMediaPlaybackRequiresUserGesture = true;
     private boolean         mBuiltInZoomControls = false;
     private boolean         mDisplayZoomControls = true;
     private boolean         mAllowFileAccess = true;
@@ -373,6 +374,21 @@
         synchronized(sLockForLocaleSettings) {
             locale = sLocale;
         }
+        return getDefaultUserAgentForLocale(mContext, locale);
+    }
+
+    /**
+     * Returns the default User-Agent used by a WebView.
+     * An instance of WebView could use a different User-Agent if a call
+     * is made to {@link WebSettings#setUserAgent(int)} or
+     * {@link WebSettings#setUserAgentString(String)}.
+     *
+     * @param context a Context object used to access application assets
+     * @param locale The Locale to use in the User-Agent string.
+     * @see WebViewFactoryProvider#getDefaultUserAgent(Context)
+     * @see WebView#getDefaultUserAgent(Context)
+     */
+    public static String getDefaultUserAgentForLocale(Context context, Locale locale) {
         StringBuffer buffer = new StringBuffer();
         // Add version
         final String version = Build.VERSION.RELEASE;
@@ -416,9 +432,9 @@
             buffer.append(" Build/");
             buffer.append(id);
         }
-        String mobile = mContext.getResources().getText(
+        String mobile = context.getResources().getText(
             com.android.internal.R.string.web_user_agent_target_content).toString();
-        final String base = mContext.getResources().getText(
+        final String base = context.getResources().getText(
                 com.android.internal.R.string.web_user_agent).toString();
         return String.format(base, buffer, mobile);
     }
@@ -459,6 +475,25 @@
     }
 
     /**
+     * @see android.webkit.WebSettings#setMediaPlaybackRequiresUserGesture(boolean)
+     */
+    @Override
+    public void setMediaPlaybackRequiresUserGesture(boolean support) {
+        if (mMediaPlaybackRequiresUserGesture != support) {
+            mMediaPlaybackRequiresUserGesture = support;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getMediaPlaybackRequiresUserGesture()
+     */
+    @Override
+    public boolean getMediaPlaybackRequiresUserGesture() {
+        return mMediaPlaybackRequiresUserGesture;
+    }
+
+    /**
      * @see android.webkit.WebSettings#setBuiltInZoomControls(boolean)
      */
     @Override
@@ -630,34 +665,6 @@
     }
 
     /**
-     * @see android.webkit.WebSettings#setTextSize(android.webkit.WebSettingsClassic.TextSize)
-     */
-    @Override
-    public synchronized void setTextSize(TextSize t) {
-        setTextZoom(t.value);
-    }
-
-    /**
-     * @see android.webkit.WebSettings#getTextSize()
-     */
-    @Override
-    public synchronized TextSize getTextSize() {
-        TextSize closestSize = null;
-        int smallestDelta = Integer.MAX_VALUE;
-        for (TextSize size : TextSize.values()) {
-            int delta = Math.abs(mTextSize - size.value);
-            if (delta == 0) {
-                return size;
-            }
-            if (delta < smallestDelta) {
-                smallestDelta = delta;
-                closestSize = size;
-            }
-        }
-        return closestSize != null ? closestSize : TextSize.NORMAL;
-    }
-
-    /**
      * Set the double-tap zoom of the page in percent. Default is 100.
      * @param doubleTapZoom A percent value for increasing or decreasing the double-tap zoom.
      */
@@ -1115,6 +1122,7 @@
         if (mJavaScriptEnabled != flag) {
             mJavaScriptEnabled = flag;
             postSync();
+            mWebView.updateJavaScriptEnabled(flag);
         }
     }
 
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java
index 76674f4..1e955bd 100644
--- a/core/java/android/webkit/WebStorage.java
+++ b/core/java/android/webkit/WebStorage.java
@@ -23,17 +23,22 @@
  * {@link WebView}. It manages the Application Cache API, the Web SQL Database
  * API and the HTML5 Web Storage API.
  *
- * The Web SQL Database API provides storage which is private to a given
- * origin, where an origin comprises the host, scheme and port of a URI.
- * Similarly, use of the Application Cache API can be attributed to an origin.
- * This class provides access to the storage use and quotas for these APIs for
- * a given origin. Origins are represented using {@link WebStorage.Origin}.
+ * The Application Cache API provides a mechanism to create and maintain an
+ * application cache to power offline Web applications. Use of the Application
+ * Cache API can be attributed to an origin {@link WebStorage.Origin}, however
+ * it is not possible to set per-origin quotas. Note that there can be only
+ * one application cache per application.
+ *
+ * The Web SQL Database API provides storage which is private to a given origin.
+ * Similar to the Application Cache, use of the Web SQL Database can be attributed
+ * to an origin. It is also possible to set per-origin quotas.
  */
 public class WebStorage {
 
     /**
      * Encapsulates a callback function which is used to provide a new quota
-     * for a JavaScript storage API. See
+     * for a JavaScript storage API.
+     * See
      * {@link WebChromeClient#onExceededDatabaseQuota} and
      * {@link WebChromeClient#onReachedMaxAppCacheSize}.
      */
@@ -54,6 +59,7 @@
     /**
      * This class encapsulates information about the amount of storage
      * currently used by an origin for the JavaScript storage APIs.
+     * An origin comprises the host, scheme and port of a URI.
      * See {@link WebStorage} for details.
      */
     public static class Origin {
diff --git a/core/java/android/webkit/WebSyncManager.java b/core/java/android/webkit/WebSyncManager.java
index 38b5e5c..d3ec603 100644
--- a/core/java/android/webkit/WebSyncManager.java
+++ b/core/java/android/webkit/WebSyncManager.java
@@ -37,9 +37,6 @@
     // handler of the sync thread
     protected Handler mHandler;
     // database for the persistent storage
-    // Note that this remains uninitialised as it is unused. We cannot remove
-    // the member as it leaked into the public API via CookieSyncManager.
-    // TODO: hide this member, ditto for mHandler.
     protected WebViewDatabase mDataBase;
     // Ref count for calls to start/stop sync
     private int mStartSyncRefCount;
@@ -65,6 +62,7 @@
     protected WebSyncManager(Context context, String name) {
         mThreadName = name;
         if (context != null) {
+            mDataBase = WebViewDatabase.getInstance(context);
             mSyncThread = new Thread(this);
             mSyncThread.setName(mThreadName);
             mSyncThread.start();
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index e493653..6df7820 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -35,8 +35,8 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewDebug;
 import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
 import android.view.ViewTreeObserver;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -44,6 +44,7 @@
 import android.view.inputmethod.InputConnection;
 import android.widget.AbsoluteLayout;
 
+import java.io.BufferedWriter;
 import java.io.File;
 import java.util.Map;
 
@@ -163,10 +164,7 @@
  *
  * <p>For obvious security reasons, your application has its own
  * cache, cookie store etc.&mdash;it does not share the Browser
- * application's data. Cookies are managed on a separate thread, so
- * operations like index building don't block the UI
- * thread. Follow the instructions in {@link android.webkit.CookieSyncManager}
- * if you want to use cookies in your application.
+ * application's data.
  * </p>
  *
  * <p>By default, requests by the HTML to open new windows are
@@ -263,7 +261,7 @@
 @Widget
 public class WebView extends AbsoluteLayout
         implements ViewTreeObserver.OnGlobalFocusChangeListener,
-        ViewGroup.OnHierarchyChangeListener {
+        ViewGroup.OnHierarchyChangeListener, ViewDebug.HierarchyHandler {
 
     private static final String LOGTAG = "webview_proxy";
 
@@ -312,15 +310,15 @@
         /**
          * Notifies the listener about progress made by a find operation.
          *
-         * @param numberOfMatches how many matches have been found
          * @param activeMatchOrdinal the zero-based ordinal of the currently selected match
+         * @param numberOfMatches how many matches have been found
          * @param isDoneCounting whether the find operation has actually completed. The listener
          *                       may be notified multiple times while the
          *                       operation is underway, and the numberOfMatches
          *                       value should not be considered final unless
          *                       isDoneCounting is true.
          */
-        public void onFindResultReceived(int numberOfMatches, int activeMatchOrdinal,
+        public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
             boolean isDoneCounting);
     }
 
@@ -332,16 +330,12 @@
     @Deprecated
     public interface PictureListener {
         /**
-         * Notifies the listener that the picture has changed.
+         * Used to provide notification that the WebView's picture has changed.
+         * See {@link WebView#capturePicture} for details of the picture.
          *
          * @param view the WebView that owns the picture
          * @param picture the new picture
-         * @deprecated Due to internal changes, the picture does not include
-         *             composited layers such as fixed position elements or
-         *             scrollable divs. While the PictureListener API can still
-         *             be used to detect changes in the WebView content, you
-         *             are advised against its usage until a replacement is
-         *             provided in a future Android release.
+         * @deprecated Deprecated due to internal changes.
          */
         @Deprecated
         public void onNewPicture(WebView view, Picture picture);
@@ -475,7 +469,13 @@
      * @param defStyle the default style resource ID
      * @param privateBrowsing whether this WebView will be initialized in
      *                        private mode
+     *
+     * @deprecated Private browsing is no longer supported directly via 
+     * WebView and will be removed in a future release. Prefer using
+     * {@link WebSettings}, {@link WebViewDatabase}, {@link CookieManager}
+     * and {@link WebStorage} for fine-grained control of privacy data.
      */
+    @Deprecated
     public WebView(Context context, AttributeSet attrs, int defStyle,
             boolean privateBrowsing) {
         this(context, attrs, defStyle, null, privateBrowsing);
@@ -555,6 +555,7 @@
      * Gets the visible height (in pixels) of the embedded title bar (if any).
      *
      * @deprecated This method is now obsolete.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     public int getVisibleTitleHeight() {
         checkThread();
@@ -574,7 +575,11 @@
 
     /**
      * Sets the SSL certificate for the main top-level page.
+     *
+     * @deprecated Calling this function has no useful effect, and will be
+     * ignored in future releases.
      */
+    @Deprecated
     public void setCertificate(SslCertificate certificate) {
         checkThread();
         mProvider.setCertificate(certificate);
@@ -585,12 +590,16 @@
     //-------------------------------------------------------------------------
 
     /**
-     * Saves the username and password for a particular host in this WebView's
-     * internal database.
+     * Sets a username and password pair for the specified host. This data is
+     * used by the Webview to autocomplete username and password fields in web
+     * forms. Note that this is unrelated to the credentials used for HTTP
+     * authentication.
      *
      * @param host the host that required the credentials
      * @param username the username for the given host
      * @param password the password for the given host
+     * @see WebViewDatabase#clearUsernamePassword
+     * @see WebViewDatabase#hasUsernamePassword
      */
     public void savePassword(String host, String username, String password) {
         checkThread();
@@ -598,13 +607,17 @@
     }
 
     /**
-     * Sets the HTTP authentication credentials for a given host and realm.
+     * Stores HTTP authentication credentials for a given host and realm. This
+     * method is intended to be used with
+     * {@link WebViewClient#onReceivedHttpAuthRequest}.
      *
-     * @param host the host for the credentials
-     * @param realm the realm for the credentials
-     * @param username the username for the password. If it is null, it means
-     *                 password can't be saved.
+     * @param host the host to which the credentials apply
+     * @param realm the realm to which the credentials apply
+     * @param username the username
      * @param password the password
+     * @see getHttpAuthUsernamePassword
+     * @see WebViewDatabase#hasHttpAuthUsernamePassword
+     * @see WebViewDatabase#clearHttpAuthUsernamePassword
      */
     public void setHttpAuthUsernamePassword(String host, String realm,
             String username, String password) {
@@ -613,13 +626,18 @@
     }
 
     /**
-     * Retrieves the HTTP authentication username and password for a given
-     * host and realm pair
+     * Retrieves HTTP authentication credentials for a given host and realm.
+     * This method is intended to be used with
+     * {@link WebViewClient#onReceivedHttpAuthRequest}.
      *
-     * @param host the host for which the credentials apply
-     * @param realm the realm for which the credentials apply
-     * @return String[] if found. String[0] is username, which can be null and
-     *         String[1] is password. Return null if it can't find anything.
+     * @param host the host to which the credentials apply
+     * @param realm the realm to which the credentials apply
+     * @return the credentials as a String array, if found. The first element
+     *         is the username and the second element is the password. Null if
+     *         no credentials are found.
+     * @see setHttpAuthUsernamePassword
+     * @see WebViewDatabase#hasHttpAuthUsernamePassword
+     * @see WebViewDatabase#clearHttpAuthUsernamePassword
      */
     public String[] getHttpAuthUsernamePassword(String host, String realm) {
         checkThread();
@@ -641,6 +659,7 @@
      * Notifications are enabled by default.
      *
      * @deprecated This method is now obsolete.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
     public static void enablePlatformNotifications() {
@@ -653,6 +672,7 @@
      * Notifications are enabled by default.
      *
      * @deprecated This method is now obsolete.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
     public static void disablePlatformNotifications() {
@@ -677,14 +697,11 @@
      * {@link android.app.Activity#onSaveInstanceState}. Please note that this
      * method no longer stores the display data for this WebView. The previous
      * behavior could potentially leak files if {@link #restoreState} was never
-     * called. See {@link #savePicture} and {@link #restorePicture} for saving
-     * and restoring the display data.
+     * called.
      *
      * @param outState the Bundle to store this WebView's state
      * @return the same copy of the back/forward list used to save the state. If
      *         saveState fails, the returned list will be null.
-     * @see #savePicture
-     * @see #restorePicture
      */
     public WebBackForwardList saveState(Bundle outState) {
         checkThread();
@@ -699,6 +716,7 @@
      *             overwritten with this WebView's picture data.
      * @return true if the picture was successfully saved
      * @deprecated This method is now obsolete.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
     public boolean savePicture(Bundle b, final File dest) {
@@ -715,6 +733,7 @@
      * @param src the file where the picture data was stored
      * @return true if the picture was successfully restored
      * @deprecated This method is now obsolete.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
     public boolean restorePicture(Bundle b, File src) {
@@ -723,19 +742,16 @@
     }
 
     /**
-     * Restores the state of this WebView from the given map used in
-     * {@link android.app.Activity#onRestoreInstanceState}. This method should
-     * be called to restore the state of this WebView before using the object. If
+     * Restores the state of this WebView from the given Bundle. This method is
+     * intended for use in {@link android.app.Activity#onRestoreInstanceState}
+     * and should be called to restore the state of this WebView. If
      * it is called after this WebView has had a chance to build state (load
      * pages, create a back/forward list, etc.) there may be undesirable
      * side-effects. Please note that this method no longer restores the
-     * display data for this WebView. See {@link #savePicture} and {@link
-     * #restorePicture} for saving and restoring the display data.
+     * display data for this WebView.
      *
      * @param inState the incoming Bundle of state
      * @return the restored back/forward list or null if restoreState failed
-     * @see #savePicture
-     * @see #restorePicture
      */
     public WebBackForwardList restoreState(Bundle inState) {
         checkThread();
@@ -791,11 +807,13 @@
      * #loadDataWithBaseURL(String,String,String,String,String)
      * loadDataWithBaseURL()} with an appropriate base URL.
      * <p>
-     * If the value of the encoding parameter is 'base64', then the data must
-     * be encoded as base64. Otherwise, the data must use ASCII encoding for
+     * The encoding parameter specifies whether the data is base64 or URL
+     * encoded. If the data is base64 encoded, the value of the encoding
+     * parameter must be 'base64'. For all other values of the parameter,
+     * including null, it is assumed that the data uses ASCII encoding for
      * octets inside the range of safe URL characters and use the standard %xx
-     * hex encoding of URLs for octets outside that range. For example,
-     * '#', '%', '\', '?' should be replaced by %23, %25, %27, %3f respectively.
+     * hex encoding of URLs for octets outside that range. For example, '#',
+     * '%', '\', '?' should be replaced by %23, %25, %27, %3f respectively.
      * <p>
      * The 'data' scheme URL formed by this method uses the default US-ASCII
      * charset. If you need need to set a different charset, you should form a
@@ -986,13 +1004,18 @@
     }
 
     /**
-     * Gets a new picture that captures the current display of this WebView.
-     * This is a copy of the display, and will be unaffected if this WebView
-     * later loads a different URL.
+     * Gets a new picture that captures the current contents of this WebView.
+     * The picture is of the entire document being displayed, and is not
+     * limited to the area currently displayed by this WebView. Also, the
+     * picture is a static copy and is unaffected by later changes to the
+     * content being displayed.
+     * <p>
+     * Note that due to internal changes, for API levels between
+     * {@link android.os.Build.VERSION_CODES#HONEYCOMB} and
+     * {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH} inclusive, the
+     * picture does not include fixed position elements or scrollable divs.
      *
-     * @return a picture containing the current contents of this WebView. Note
-     *         this picture is of the entire document, and is not restricted to
-     *         the bounds of the view.
+     * @return a picture that captures the current contents of this WebView
      */
     public Picture capturePicture() {
         checkThread();
@@ -1003,7 +1026,13 @@
      * Gets the current scale of this WebView.
      *
      * @return the current scale
+     *
+     * @deprecated This method is prone to inaccuracy due to race conditions
+     * between the web rendering and UI threads; prefer
+     * {@link WebViewClient#onScaleChanged}.
      */
+    @Deprecated
+    @ViewDebug.ExportedProperty(category = "webview")
     public float getScale() {
         checkThread();
         return mProvider.getScale();
@@ -1094,6 +1123,7 @@
      *
      * @return the URL for the current page
      */
+    @ViewDebug.ExportedProperty(category = "webview")
     public String getUrl() {
         checkThread();
         return mProvider.getUrl();
@@ -1108,6 +1138,7 @@
      *
      * @return the URL that was originally requested for the current page
      */
+    @ViewDebug.ExportedProperty(category = "webview")
     public String getOriginalUrl() {
         checkThread();
         return mProvider.getOriginalUrl();
@@ -1119,6 +1150,7 @@
      *
      * @return the title for the current page
      */
+    @ViewDebug.ExportedProperty(category = "webview")
     public String getTitle() {
         checkThread();
         return mProvider.getTitle();
@@ -1161,6 +1193,7 @@
      *
      * @return the height of the HTML content
      */
+    @ViewDebug.ExportedProperty(category = "webview")
     public int getContentHeight() {
         checkThread();
         return mProvider.getContentHeight();
@@ -1172,6 +1205,7 @@
      * @return the width of the HTML content
      * @hide
      */
+    @ViewDebug.ExportedProperty(category = "webview")
     public int getContentWidth() {
         return mProvider.getContentWidth();
     }
@@ -1246,8 +1280,10 @@
     }
 
     /**
-     * Makes sure that clearing the form data removes the adapter from the
-     * currently focused textfield if there is one.
+     * Removes the autocomplete popup from the currently focused form field, if
+     * present. Note this only affects the display of the autocomplete popup,
+     * it does not remove any saved form data from this WebView's store. To do
+     * that, use {@link WebViewDatabase#clearFormData}.
      */
     public void clearFormData() {
         checkThread();
@@ -1297,12 +1333,11 @@
     }
 
     /**
-     * Highlights and scrolls to the next match found by {@link #findAll} or
+     * Highlights and scrolls to the next match found by
      * {@link #findAllAsync}, wrapping around page boundaries as necessary.
-     * Notifies any registered {@link FindListener}. If neither
-     * {@link #findAll} nor {@link #findAllAsync(String)} has been called yet,
-     * or if {@link #clearMatches} has been called since the last find
-     * operation, this function does nothing.
+     * Notifies any registered {@link FindListener}. If {@link #findAllAsync(String)}
+     * has not been called yet, or if {@link #clearMatches} has been called since the
+     * last find operation, this function does nothing.
      *
      * @param forward the direction to search
      * @see #setFindListener
@@ -1331,8 +1366,7 @@
     /**
      * Finds all instances of find on the page and highlights them,
      * asynchronously. Notifies any registered {@link FindListener}.
-     * Successive calls to this or {@link #findAll} will cancel any
-     * pending searches.
+     * Successive calls to this will cancel any pending searches.
      *
      * @param find the string to find.
      * @see #setFindListener
@@ -1381,13 +1415,12 @@
      * @return the address, or if no address is found, null
      */
     public static String findAddress(String addr) {
-        checkThread();
         return getFactory().getStatics().findAddress(addr);
     }
 
     /**
      * Clears the highlighting surrounding text matches created by
-     * {@link #findAll} or {@link #findAllAsync}.
+     * {@link #findAllAsync}.
      */
     public void clearMatches() {
         checkThread();
@@ -1457,10 +1490,22 @@
     /**
      * Injects the supplied Java object into this WebView. The object is
      * injected into the JavaScript context of the main frame, using the
-     * supplied name. This allows the Java object's public methods to be
-     * accessed from JavaScript. Note that that injected objects will not
+     * supplied name. This allows the Java object's methods to be
+     * accessed from JavaScript. For applications targeted to API
+     * level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
+     * and above, only public methods that are annotated with
+     * {@link android.webkit.JavascriptInterface} can be accessed from JavaScript.
+     * For applications targeted to API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN} or below,
+     * all public methods (including the inherited ones) can be accessed, see the
+     * important security note below for implications.
+     * <p> Note that injected objects will not
      * appear in JavaScript until the page is next (re)loaded. For example:
-     * <pre> webView.addJavascriptInterface(new Object(), "injectedObject");
+     * <pre>
+     * class JsObject {
+     *    {@literal @}JavascriptInterface
+     *    public String toString() { return "injectedObject"; }
+     * }
+     * webView.addJavascriptInterface(new JsObject(), "injectedObject");
      * webView.loadData("<!DOCTYPE html><title></title>", "text/html", null);
      * webView.loadUrl("javascript:alert(injectedObject.toString())");</pre>
      * <p>
@@ -1468,7 +1513,9 @@
      * <ul>
      * <li> This method can be used to allow JavaScript to control the host
      * application. This is a powerful feature, but also presents a security
-     * risk, particularly as JavaScript could use reflection to access an
+     * risk for applications targeted to API level
+     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} or below, because
+     * JavaScript could use reflection to access an
      * injected object's public fields. Use of this method in a WebView
      * containing untrusted content could allow an attacker to manipulate the
      * host application in unintended ways, executing Java code with the
@@ -1477,6 +1524,7 @@
      * <li> JavaScript interacts with Java object on a private, background
      * thread of this WebView. Care is therefore required to maintain thread
      * safety.</li>
+     * <li> The Java object's fields are not accessible.</li>
      * </ul>
      *
      * @param object the Java object to inject into this WebView's JavaScript
@@ -1539,11 +1587,11 @@
      * functionality; it will be deprecated in the future.
      *
      * @deprecated This method is now obsolete.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
     public void emulateShiftHeld() {
         checkThread();
-        mProvider.emulateShiftHeld();
     }
 
     /**
@@ -1574,6 +1622,10 @@
     public void onGlobalFocusChanged(View oldFocus, View newFocus) {
     }
 
+    /**
+     * @deprecated Only the default case, true, will be supported in a future version.
+     */
+    @Deprecated
     public void setMapTrackballToArrowKeys(boolean setMap) {
         checkThread();
         mProvider.setMapTrackballToArrowKeys(setMap);
@@ -1607,7 +1659,12 @@
      * Gets whether this WebView can be zoomed in.
      *
      * @return true if this WebView can be zoomed in
+     *
+     * @deprecated This method is prone to inaccuracy due to race conditions
+     * between the web rendering and UI threads; prefer
+     * {@link WebViewClient#onScaleChanged}.
      */
+    @Deprecated
     public boolean canZoomIn() {
         checkThread();
         return mProvider.canZoomIn();
@@ -1617,7 +1674,12 @@
      * Gets whether this WebView can be zoomed out.
      *
      * @return true if this WebView can be zoomed out
+     *
+     * @deprecated This method is prone to inaccuracy due to race conditions
+     * between the web rendering and UI threads; prefer
+     * {@link WebViewClient#onScaleChanged}.
      */
+    @Deprecated
     public boolean canZoomOut() {
         checkThread();
         return mProvider.canZoomOut();
@@ -1645,11 +1707,29 @@
 
     /**
      * @deprecated This method is now obsolete.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
     public void debugDump() {
         checkThread();
-        mProvider.debugDump();
+    }
+
+    /**
+     * See {@link ViewDebug.HierarchyHandler#dumpViewHierarchyWithProperties(BufferedWriter, int)}
+     * @hide
+     */
+    @Override
+    public void dumpViewHierarchyWithProperties(BufferedWriter out, int level) {
+        mProvider.dumpViewHierarchyWithProperties(out, level);
+    }
+
+    /**
+     * See {@link ViewDebug.HierarchyHandler#findHierarchyView(String, int)}
+     * @hide
+     */
+    @Override
+    public View findHierarchyView(String className, int hashCode) {
+        return mProvider.findHierarchyView(className, hashCode);
     }
 
     //-------------------------------------------------------------------------
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index c624a87..ae56e6b 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -16,6 +16,7 @@
 
 package android.webkit;
 
+import android.accessibilityservice.AccessibilityServiceInfo;
 import android.animation.ObjectAnimator;
 import android.annotation.Widget;
 import android.app.ActivityManager;
@@ -26,7 +27,6 @@
 import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
@@ -55,6 +55,7 @@
 import android.net.Uri;
 import android.net.http.SslCertificate;
 import android.os.AsyncTask;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -68,7 +69,6 @@
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
-import android.view.Display;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
 import android.view.HardwareCanvas;
@@ -86,7 +86,6 @@
 import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.view.ViewRootImpl;
-import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -117,6 +116,8 @@
 
 import junit.framework.Assert;
 
+import java.io.BufferedWriter;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -129,11 +130,10 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.Vector;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 /**
  * Implements a backend provider for the {@link WebView} public API.
@@ -275,7 +275,6 @@
             super.setComposingText(limitedText, newCursorPosition);
             updateSelection();
             if (limitedText != text) {
-                restartInput();
                 int lastCaret = start + limitedText.length();
                 finishComposingText();
                 setSelection(lastCaret, lastCaret);
@@ -376,28 +375,26 @@
                     imeOptions |= EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS;
                 }
             }
+            int action = EditorInfo.IME_ACTION_GO;
             switch (type) {
                 case WebTextView.NORMAL_TEXT_FIELD:
-                    imeOptions |= EditorInfo.IME_ACTION_GO;
                     break;
                 case WebTextView.TEXT_AREA:
                     inputType |= InputType.TYPE_TEXT_FLAG_MULTI_LINE
                             | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
                             | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
-                    imeOptions |= EditorInfo.IME_ACTION_NONE;
+                    action = EditorInfo.IME_ACTION_NONE;
                     break;
                 case WebTextView.PASSWORD:
                     inputType |= EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD;
-                    imeOptions |= EditorInfo.IME_ACTION_GO;
                     break;
                 case WebTextView.SEARCH:
-                    imeOptions |= EditorInfo.IME_ACTION_SEARCH;
+                    action = EditorInfo.IME_ACTION_SEARCH;
                     break;
                 case WebTextView.EMAIL:
                     // inputType needs to be overwritten because of the different text variation.
                     inputType = InputType.TYPE_CLASS_TEXT
                             | InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS;
-                    imeOptions |= EditorInfo.IME_ACTION_GO;
                     break;
                 case WebTextView.NUMBER:
                     // inputType needs to be overwritten because of the different class.
@@ -405,23 +402,20 @@
                             | InputType.TYPE_NUMBER_FLAG_SIGNED | InputType.TYPE_NUMBER_FLAG_DECIMAL;
                     // Number and telephone do not have both a Tab key and an
                     // action, so set the action to NEXT
-                    imeOptions |= EditorInfo.IME_ACTION_NEXT;
                     break;
                 case WebTextView.TELEPHONE:
                     // inputType needs to be overwritten because of the different class.
                     inputType = InputType.TYPE_CLASS_PHONE;
-                    imeOptions |= EditorInfo.IME_ACTION_NEXT;
                     break;
                 case WebTextView.URL:
                     // TYPE_TEXT_VARIATION_URI prevents Tab key from showing, so
                     // exclude it for now.
-                    imeOptions |= EditorInfo.IME_ACTION_GO;
                     inputType |= InputType.TYPE_TEXT_VARIATION_URI;
                     break;
                 default:
-                    imeOptions |= EditorInfo.IME_ACTION_GO;
                     break;
             }
+            imeOptions |= action;
             mHint = initData.mLabel;
             mInputType = inputType;
             mImeOptions = imeOptions;
@@ -679,6 +673,8 @@
     // after resize.
     static private final int EDIT_RECT_BUFFER = 10;
 
+    static private final long SELECTION_HANDLE_ANIMATION_MS = 150;
+
     // true means redraw the screen all-the-time. Only with AUTO_REDRAW_HACK
     private boolean mAutoRedraw;
 
@@ -742,12 +738,12 @@
             // the existing GL resources for the html5 video will be destroyed
             // at native side.
             // Here we just need to clean up the Surface Texture which is static.
-            if (level >= TRIM_MEMORY_UI_HIDDEN) {
+            if (level > TRIM_MEMORY_UI_HIDDEN) {
                 HTML5VideoInline.cleanupSurfaceTexture();
+                HTML5VideoView.release();
             }
             WebViewClassic.nativeOnTrimMemory(level);
         }
-
     }
 
     // A final CallbackProxy shared by WebViewCore and BrowserFrame.
@@ -949,21 +945,20 @@
     private Drawable mSelectHandleLeft;
     private Drawable mSelectHandleRight;
     private Drawable mSelectHandleCenter;
-    private Point mSelectHandleLeftOffset;
-    private Point mSelectHandleRightOffset;
-    private Point mSelectHandleCenterOffset;
-    private Point mSelectCursorLeft = new Point();
-    private int mSelectCursorLeftLayerId;
-    private QuadF mSelectCursorLeftTextQuad = new QuadF();
-    private Point mSelectCursorRight = new Point();
-    private int mSelectCursorRightLayerId;
-    private QuadF mSelectCursorRightTextQuad = new QuadF();
+    private Point mSelectOffset;
+    private Point mSelectCursorBase = new Point();
+    private Rect mSelectHandleBaseBounds = new Rect();
+    private int mSelectCursorBaseLayerId;
+    private QuadF mSelectCursorBaseTextQuad = new QuadF();
+    private Point mSelectCursorExtent = new Point();
+    private Rect mSelectHandleExtentBounds = new Rect();
+    private int mSelectCursorExtentLayerId;
+    private QuadF mSelectCursorExtentTextQuad = new QuadF();
     private Point mSelectDraggingCursor;
-    private Point mSelectDraggingOffset;
     private QuadF mSelectDraggingTextQuad;
     private boolean mIsCaretSelection;
-    static final int HANDLE_ID_LEFT = 0;
-    static final int HANDLE_ID_RIGHT = 1;
+    static final int HANDLE_ID_BASE = 0;
+    static final int HANDLE_ID_EXTENT = 1;
 
     // the color used to highlight the touch rectangles
     static final int HIGHLIGHT_COLOR = 0x6633b5e5;
@@ -1037,7 +1032,6 @@
     static final int AUTOFILL_COMPLETE                  = 134;
 
     static final int SCREEN_ON                          = 136;
-    static final int ENTER_FULLSCREEN_VIDEO             = 137;
     static final int UPDATE_ZOOM_DENSITY                = 139;
     static final int EXIT_FULLSCREEN_VIDEO              = 140;
 
@@ -1053,6 +1047,7 @@
     static final int EDIT_TEXT_SIZE_CHANGED             = 150;
     static final int SHOW_CARET_HANDLE                  = 151;
     static final int UPDATE_CONTENT_BOUNDS              = 152;
+    static final int SCROLL_HANDLE_INTO_VIEW            = 153;
 
     private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID;
     private static final int LAST_PACKAGE_MSG_ID = HIT_TEST_RESULT;
@@ -1313,6 +1308,12 @@
         public WebViewDatabase getWebViewDatabase(Context context) {
             return WebViewDatabaseClassic.getInstance(context);
         }
+
+        @Override
+        public String getDefaultUserAgent(Context context) {
+            return WebSettingsClassic.getDefaultUserAgentForLocale(context,
+                    Locale.getDefault());
+        }
     }
 
     private void onHandleUiEvent(MotionEvent event, int eventType, int flags) {
@@ -1646,6 +1647,12 @@
         mZoomManager.updateMultiTouchSupport(context);
     }
 
+    void updateJavaScriptEnabled(boolean enabled) {
+        if (isAccessibilityInjectionEnabled()) {
+            getAccessibilityInjector().updateJavaScriptEnabled(enabled);
+        }
+    }
+
     private void init() {
         OnTrimMemoryListener.init(mContext);
         mWebView.setWillNotDraw(false);
@@ -1657,7 +1664,7 @@
         mTouchSlopSquare = slop * slop;
         slop = configuration.getScaledDoubleTapSlop();
         mDoubleTapSlopSquare = slop * slop;
-        final float density = mContext.getResources().getDisplayMetrics().density;
+        final float density = WebViewCore.getFixedDisplayDensity(mContext);
         // use one line height, 16 based on our current default font, for how
         // far we allow a touch be away from the edge of a link
         mNavSlop = (int) (16 * density);
@@ -1759,8 +1766,21 @@
         event.setMaxScrollY(Math.max(convertedContentHeight - adjustedViewHeight, 0));
     }
 
-    private boolean isAccessibilityEnabled() {
-        return AccessibilityManager.getInstance(mContext).isEnabled();
+    private boolean isAccessibilityInjectionEnabled() {
+        final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
+        if (!manager.isEnabled()) {
+            return false;
+        }
+
+        // Accessibility scripts should be injected only when a speaking service
+        // is enabled. This may need to change later to accommodate Braille.
+        final List<AccessibilityServiceInfo> services = manager.getEnabledAccessibilityServiceList(
+                AccessibilityServiceInfo.FEEDBACK_SPOKEN);
+        if (services.isEmpty()) {
+            return false;
+        }
+
+        return true;
     }
 
     private AccessibilityInjector getAccessibilityInjector() {
@@ -1789,7 +1809,7 @@
     }
 
     /* package */ void adjustDefaultZoomDensity(int zoomDensity) {
-        final float density = mContext.getResources().getDisplayMetrics().density
+        final float density = WebViewCore.getFixedDisplayDensity(mContext)
                 * 100 / zoomDensity;
         updateDefaultZoomDensity(density);
     }
@@ -1866,9 +1886,9 @@
                             mSavePasswordDialog = null;
                         }
                     })
-                    .setOnCancelListener(new OnCancelListener() {
+                    .setOnDismissListener(new DialogInterface.OnDismissListener() {
                         @Override
-                        public void onCancel(DialogInterface dialog) {
+                        public void onDismiss(DialogInterface dialog) {
                             if (mResumeMsg != null) {
                                 resumeMsg.sendToTarget();
                                 mResumeMsg = null;
@@ -2073,14 +2093,18 @@
         hideSoftKeyboard();
         clearActionModes();
         dismissFullScreenMode();
-        cancelSelectDialog();
+        cancelDialogs();
     }
 
-    private void cancelSelectDialog() {
+    private void cancelDialogs() {
         if (mListBoxDialog != null) {
             mListBoxDialog.cancel();
             mListBoxDialog = null;
         }
+        if (mSavePasswordDialog != null) {
+            mSavePasswordDialog.dismiss();
+            mSavePasswordDialog = null;
+        }
     }
 
     /**
@@ -2108,14 +2132,9 @@
 
     private void destroyJava() {
         mCallbackProxy.blockMessages();
-        clearHelpers();
-        if (mListBoxDialog != null) {
-            mListBoxDialog.dismiss();
-            mListBoxDialog = null;
-        }
-        if (mSavePasswordDialog != null) {
-            mSavePasswordDialog.dismiss();
-            mSavePasswordDialog = null;
+        if (mAccessibilityInjector != null) {
+            mAccessibilityInjector.destroy();
+            mAccessibilityInjector = null;
         }
         if (mWebViewCore != null) {
             // Tell WebViewCore to destroy itself
@@ -2223,7 +2242,7 @@
         }
         // We grab a copy of the back/forward list because a client of WebView
         // may have invalidated the history list by calling clearHistory.
-        WebBackForwardList list = copyBackForwardList();
+        WebBackForwardListClassic list = copyBackForwardList();
         final int currentIndex = list.getCurrentIndex();
         final int size = list.getSize();
         // We should fail saving the state if the list is empty or the index is
@@ -2237,7 +2256,7 @@
         // arrays.
         ArrayList<byte[]> history = new ArrayList<byte[]>(size);
         for (int i = 0; i < size; i++) {
-            WebHistoryItem item = list.getItemAtIndex(i);
+            WebHistoryItemClassic item = list.getItemAtIndex(i);
             if (null == item) {
                 // FIXME: this shouldn't happen
                 // need to determine how item got set to null
@@ -2436,7 +2455,7 @@
      */
     @Override
     public WebBackForwardList restoreState(Bundle inState) {
-        WebBackForwardList returnList = null;
+        WebBackForwardListClassic returnList = null;
         if (inState == null) {
             return returnList;
         }
@@ -2444,7 +2463,7 @@
             mCertificate = SslCertificate.restoreState(
                 inState.getBundle("certificate"));
 
-            final WebBackForwardList list = mCallbackProxy.getBackForwardList();
+            final WebBackForwardListClassic list = mCallbackProxy.getBackForwardList();
             final int index = inState.getInt("index");
             // We can't use a clone of the list because we need to modify the
             // shared copy, so synchronize instead to prevent concurrent
@@ -2465,7 +2484,7 @@
                         // the item and thus our history list cannot be rebuilt.
                         return null;
                     }
-                    WebHistoryItem item = new WebHistoryItem(data);
+                    WebHistoryItem item = new WebHistoryItemClassic(data);
                     list.addHistoryItem(item);
                 }
                 // Grab the most recent copy to return to the caller.
@@ -2481,6 +2500,9 @@
             // Remove all pending messages because we are restoring previous
             // state.
             mWebViewCore.removeMessages();
+            if (isAccessibilityInjectionEnabled()) {
+                getAccessibilityInjector().addAccessibilityApisIfNecessary();
+            }
             // Send a restore state message.
             mWebViewCore.sendMessage(EventHub.RESTORE_STATE, index);
         }
@@ -2638,7 +2660,7 @@
      */
     @Override
     public boolean canGoBack() {
-        WebBackForwardList l = mCallbackProxy.getBackForwardList();
+        WebBackForwardListClassic l = mCallbackProxy.getBackForwardList();
         synchronized (l) {
             if (l.getClearPending()) {
                 return false;
@@ -2661,7 +2683,7 @@
      */
     @Override
     public boolean canGoForward() {
-        WebBackForwardList l = mCallbackProxy.getBackForwardList();
+        WebBackForwardListClassic l = mCallbackProxy.getBackForwardList();
         synchronized (l) {
             if (l.getClearPending()) {
                 return false;
@@ -2684,7 +2706,7 @@
      */
     @Override
     public boolean canGoBackOrForward(int steps) {
-        WebBackForwardList l = mCallbackProxy.getBackForwardList();
+        WebBackForwardListClassic l = mCallbackProxy.getBackForwardList();
         synchronized (l) {
             if (l.getClearPending()) {
                 return false;
@@ -3332,6 +3354,7 @@
         }
         if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
             scrollLayerTo(scrollX, scrollY);
+            animateHandles();
             return;
         }
         mInOverScrollMode = false;
@@ -3352,6 +3375,8 @@
 
         mWebViewPrivate.super_scrollTo(scrollX, scrollY);
 
+        animateHandles();
+
         if (mOverScrollGlow != null) {
             mOverScrollGlow.pullGlow(getScrollX(), getScrollY(), oldX, oldY, maxX, maxY);
         }
@@ -3398,7 +3423,7 @@
      */
     @Override
     public String getTouchIconUrl() {
-        WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
+        WebHistoryItemClassic h = mCallbackProxy.getBackForwardList().getCurrentItem();
         return h != null ? h.getTouchIconUrl() : null;
     }
 
@@ -3464,7 +3489,7 @@
                 nativeSetPauseDrawing(mNativeClass, true);
             }
 
-            cancelSelectDialog();
+            cancelDialogs();
             WebCoreThreadWatchdog.pause();
         }
     }
@@ -3562,7 +3587,7 @@
      * See {@link WebView#copyBackForwardList()}
      */
     @Override
-    public WebBackForwardList copyBackForwardList() {
+    public WebBackForwardListClassic copyBackForwardList() {
         return mCallbackProxy.getBackForwardList().clone();
     }
 
@@ -3570,7 +3595,8 @@
      * See {@link WebView#setFindListener(WebView.FindListener)}.
      * @hide
      */
-     public void setFindListener(WebView.FindListener listener) {
+     @Override
+    public void setFindListener(WebView.FindListener listener) {
          mFindListener = listener;
      }
 
@@ -3593,6 +3619,7 @@
         return findAllBody(find, false);
     }
 
+    @Override
     public void findAllAsync(String find) {
         findAllBody(find, true);
     }
@@ -3631,6 +3658,7 @@
      *             If false and text is non-null, perform a find all.
      * @return boolean True if the find dialog is shown, false otherwise.
      */
+    @Override
     public boolean showFindDialog(String text, boolean showIme) {
         FindActionModeCallback callback = new FindActionModeCallback(mContext);
         if (mWebView.getParent() == null || mWebView.startActionMode(callback) == null) {
@@ -3846,17 +3874,14 @@
             return;
         }
         if (mSelectingText) {
-            if (mSelectCursorLeftLayerId == mCurrentScrollingLayerId) {
-                mSelectCursorLeft.offset(dx, dy);
-                mSelectCursorLeftTextQuad.offset(dx, dy);
+            if (mSelectCursorBaseLayerId == mCurrentScrollingLayerId) {
+                mSelectCursorBase.offset(dx, dy);
+                mSelectCursorBaseTextQuad.offset(dx, dy);
             }
-            if (mSelectCursorRightLayerId == mCurrentScrollingLayerId) {
-                mSelectCursorRight.offset(dx, dy);
-                mSelectCursorRightTextQuad.offset(dx, dy);
+            if (mSelectCursorExtentLayerId == mCurrentScrollingLayerId) {
+                mSelectCursorExtent.offset(dx, dy);
+                mSelectCursorExtentTextQuad.offset(dx, dy);
             }
-        } else if (mHandleAlpha.getAlpha() > 0) {
-            // stop fading as we're not going to move with the layer.
-            mHandleAlphaAnimator.end();
         }
         if (mAutoCompletePopup != null &&
                 mCurrentScrollingLayerId == mEditTextLayerId) {
@@ -3949,9 +3974,7 @@
         // null, and that will be the case
         mWebView.setCertificate(null);
 
-        // reset the flag since we set to true in if need after
-        // loading is see onPageFinished(Url)
-        if (isAccessibilityEnabled()) {
+        if (isAccessibilityInjectionEnabled()) {
             getAccessibilityInjector().onPageStarted(url);
         }
 
@@ -3966,7 +3989,7 @@
     /* package */ void onPageFinished(String url) {
         mZoomManager.onPageFinished(url);
 
-        if (isAccessibilityEnabled()) {
+        if (isAccessibilityInjectionEnabled()) {
             getAccessibilityInjector().onPageFinished(url);
         }
     }
@@ -4097,20 +4120,22 @@
      */
     @Override
     public void addJavascriptInterface(Object object, String name) {
-        addJavascriptInterface(object, name, false);
-    }
 
-    /**
-     * @hide
-     */
-    public void addJavascriptInterface(Object object, String name, boolean requireAnnotation) {
         if (object == null) {
             return;
         }
         WebViewCore.JSInterfaceData arg = new WebViewCore.JSInterfaceData();
+
         arg.mObject = object;
         arg.mInterfaceName = name;
-        arg.mRequireAnnotation = requireAnnotation;
+
+        // starting with JELLY_BEAN_MR1, annotations are mandatory for enabling access to
+        // methods that are accessible from JS.
+        if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            arg.mRequireAnnotation = true;
+        } else {
+            arg.mRequireAnnotation = false;
+        }
         mWebViewCore.sendMessage(EventHub.ADD_JS_INTERFACE, arg);
     }
 
@@ -4480,9 +4505,6 @@
     }
 
     private void onZoomAnimationStart() {
-        if (!mSelectingText && mHandleAlpha.getAlpha() > 0) {
-            mHandleAlphaAnimator.end();
-        }
     }
 
     private void onZoomAnimationEnd() {
@@ -4515,34 +4537,63 @@
 
     private class SelectionHandleAlpha {
         private int mAlpha = 0;
+        private int mTargetAlpha = 0;
+
         public void setAlpha(int alpha) {
             mAlpha = alpha;
-            if (mSelectHandleCenter != null) {
-                mSelectHandleCenter.setAlpha(alpha);
-                mSelectHandleLeft.setAlpha(alpha);
-                mSelectHandleRight.setAlpha(alpha);
-                // TODO: Use partial invalidate
-                invalidate();
-            }
+            // TODO: Use partial invalidate
+            invalidate();
         }
 
         public int getAlpha() {
             return mAlpha;
         }
 
+        public void setTargetAlpha(int alpha) {
+            mTargetAlpha = alpha;
+        }
+
+        public int getTargetAlpha() {
+            return mTargetAlpha;
+        }
+
     }
 
     private void startSelectingText() {
         mSelectingText = true;
         mShowTextSelectionExtra = true;
-        mHandleAlphaAnimator.setIntValues(255);
-        mHandleAlphaAnimator.start();
+        animateHandles();
     }
+
+    private void animateHandle(boolean canShow, ObjectAnimator animator,
+            Point selectionPoint, int selectionLayerId,
+            SelectionHandleAlpha alpha) {
+        boolean isVisible = canShow && mSelectingText
+                && ((mSelectionStarted && mSelectDraggingCursor == selectionPoint)
+                || isHandleVisible(selectionPoint, selectionLayerId));
+        int targetValue = isVisible ? 255 : 0;
+        if (targetValue != alpha.getTargetAlpha()) {
+            alpha.setTargetAlpha(targetValue);
+            animator.setIntValues(targetValue);
+            animator.setDuration(SELECTION_HANDLE_ANIMATION_MS);
+            animator.start();
+        }
+    }
+
+    private void animateHandles() {
+        boolean canShowBase = mSelectingText;
+        boolean canShowExtent = mSelectingText && !mIsCaretSelection;
+        animateHandle(canShowBase, mBaseHandleAlphaAnimator, mSelectCursorBase,
+                mSelectCursorBaseLayerId, mBaseAlpha);
+        animateHandle(canShowExtent, mExtentHandleAlphaAnimator,
+                mSelectCursorExtent, mSelectCursorExtentLayerId,
+                mExtentAlpha);
+    }
+
     private void endSelectingText() {
         mSelectingText = false;
         mShowTextSelectionExtra = false;
-        mHandleAlphaAnimator.setIntValues(0);
-        mHandleAlphaAnimator.start();
+        animateHandles();
     }
 
     private void ensureSelectionHandles() {
@@ -4553,66 +4604,87 @@
                     com.android.internal.R.drawable.text_select_handle_left).mutate();
             mSelectHandleRight = mContext.getResources().getDrawable(
                     com.android.internal.R.drawable.text_select_handle_right).mutate();
-            mHandleAlpha.setAlpha(mHandleAlpha.getAlpha());
-            mSelectHandleCenterOffset = new Point(0,
-                    -mSelectHandleCenter.getIntrinsicHeight());
-            mSelectHandleLeftOffset = new Point(0,
+            // All handles have the same height, so we can save effort with
+            // this assumption.
+            mSelectOffset = new Point(0,
                     -mSelectHandleLeft.getIntrinsicHeight());
-            mSelectHandleRightOffset = new Point(
-                    -mSelectHandleLeft.getIntrinsicWidth() / 2,
-                    -mSelectHandleRight.getIntrinsicHeight());
         }
     }
 
+    private void drawHandle(Point point, int handleId, Rect bounds,
+            int alpha, Canvas canvas) {
+        int offset;
+        int width;
+        int height;
+        Drawable drawable;
+        boolean isLeft = nativeIsHandleLeft(mNativeClass, handleId);
+        if (isLeft) {
+            drawable = mSelectHandleLeft;
+            width = mSelectHandleLeft.getIntrinsicWidth();
+            height = mSelectHandleLeft.getIntrinsicHeight();
+            // Magic formula copied from TextView
+            offset = (width * 3) / 4;
+        } else {
+            drawable = mSelectHandleRight;
+            width = mSelectHandleRight.getIntrinsicWidth();
+            height = mSelectHandleRight.getIntrinsicHeight();
+            // Magic formula copied from TextView
+            offset = width / 4;
+        }
+        int x = contentToViewDimension(point.x);
+        int y = contentToViewDimension(point.y);
+        bounds.set(x - offset, y, x - offset + width, y + height);
+        drawable.setBounds(bounds);
+        drawable.setAlpha(alpha);
+        drawable.draw(canvas);
+    }
+
     private void drawTextSelectionHandles(Canvas canvas) {
-        if (mHandleAlpha.getAlpha() == 0) {
+        if (mBaseAlpha.getAlpha() == 0 && mExtentAlpha.getAlpha() == 0) {
             return;
         }
         ensureSelectionHandles();
-        if (mSelectingText) {
-            int[] handles = new int[4];
-            getSelectionHandles(handles);
-            int start_x = contentToViewDimension(handles[0]);
-            int start_y = contentToViewDimension(handles[1]);
-            int end_x = contentToViewDimension(handles[2]);
-            int end_y = contentToViewDimension(handles[3]);
-
-            if (mIsCaretSelection) {
-                // Caret handle is centered
-                start_x -= (mSelectHandleCenter.getIntrinsicWidth() / 2);
-                mSelectHandleCenter.setBounds(start_x, start_y,
-                        start_x + mSelectHandleCenter.getIntrinsicWidth(),
-                        start_y + mSelectHandleCenter.getIntrinsicHeight());
-            } else {
-                // Magic formula copied from TextView
-                start_x -= (mSelectHandleLeft.getIntrinsicWidth() * 3) / 4;
-                mSelectHandleLeft.setBounds(start_x, start_y,
-                        start_x + mSelectHandleLeft.getIntrinsicWidth(),
-                        start_y + mSelectHandleLeft.getIntrinsicHeight());
-                end_x -= mSelectHandleRight.getIntrinsicWidth() / 4;
-                mSelectHandleRight.setBounds(end_x, end_y,
-                        end_x + mSelectHandleRight.getIntrinsicWidth(),
-                        end_y + mSelectHandleRight.getIntrinsicHeight());
-            }
-        }
-
         if (mIsCaretSelection) {
+            // Caret handle is centered
+            int x = contentToViewDimension(mSelectCursorBase.x) -
+                    (mSelectHandleCenter.getIntrinsicWidth() / 2);
+            int y = contentToViewDimension(mSelectCursorBase.y);
+            mSelectHandleBaseBounds.set(x, y,
+                    x + mSelectHandleCenter.getIntrinsicWidth(),
+                    y + mSelectHandleCenter.getIntrinsicHeight());
+            mSelectHandleCenter.setBounds(mSelectHandleBaseBounds);
+            mSelectHandleCenter.setAlpha(mBaseAlpha.getAlpha());
             mSelectHandleCenter.draw(canvas);
         } else {
-            mSelectHandleLeft.draw(canvas);
-            mSelectHandleRight.draw(canvas);
+            drawHandle(mSelectCursorBase, HANDLE_ID_BASE,
+                    mSelectHandleBaseBounds, mBaseAlpha.getAlpha(), canvas);
+            drawHandle(mSelectCursorExtent, HANDLE_ID_EXTENT,
+                    mSelectHandleExtentBounds, mExtentAlpha.getAlpha(), canvas);
         }
     }
 
+    private boolean isHandleVisible(Point selectionPoint, int layerId) {
+        boolean isVisible = true;
+        if (mIsEditingText) {
+            isVisible = mEditTextContentBounds.contains(selectionPoint.x,
+                    selectionPoint.y);
+        }
+        if (isVisible) {
+            isVisible = nativeIsPointVisible(mNativeClass, layerId,
+                    selectionPoint.x, selectionPoint.y);
+        }
+        return isVisible;
+    }
+
     /**
      * Takes an int[4] array as an output param with the values being
      * startX, startY, endX, endY
      */
     private void getSelectionHandles(int[] handles) {
-        handles[0] = mSelectCursorLeft.x;
-        handles[1] = mSelectCursorLeft.y;
-        handles[2] = mSelectCursorRight.x;
-        handles[3] = mSelectCursorRight.y;
+        handles[0] = mSelectCursorBase.x;
+        handles[1] = mSelectCursorBase.y;
+        handles[2] = mSelectCursorExtent.x;
+        handles[3] = mSelectCursorExtent.y;
     }
 
     // draw history
@@ -4847,6 +4919,43 @@
     }
 
     /**
+     * Sets use of the Geolocation mock client. Also resets that client. Called
+     * by DRT on UI thread, need to proxy to WebCore thread.
+     *
+     * debug only
+     */
+    public void setUseMockGeolocation() {
+        mWebViewCore.sendMessage(EventHub.SET_USE_MOCK_GEOLOCATION);
+    }
+
+    /**
+     * Called by DRT on WebCore thread.
+     *
+     * debug only
+     */
+    public void setMockGeolocationPosition(double latitude, double longitude, double accuracy) {
+        mWebViewCore.setMockGeolocationPosition(latitude, longitude, accuracy);
+    }
+
+    /**
+     * Called by DRT on WebCore thread.
+     *
+     * debug only
+     */
+    public void setMockGeolocationError(int code, String message) {
+        mWebViewCore.setMockGeolocationError(code, message);
+    }
+
+    /**
+     * Called by DRT on WebCore thread.
+     *
+     * debug only
+     */
+    public void setMockGeolocationPermission(boolean allow) {
+        mWebViewCore.setMockGeolocationPermission(allow);
+    }
+
+    /**
      * Called by DRT on WebCore thread.
      *
      * debug only
@@ -4931,7 +5040,7 @@
         }
 
         // See if the accessibility injector needs to handle this event.
-        if (isAccessibilityEnabled()
+        if (isAccessibilityInjectionEnabled()
                 && getAccessibilityInjector().handleKeyEventIfNecessary(event)) {
             return true;
         }
@@ -5038,7 +5147,7 @@
         }
 
         // See if the accessibility injector needs to handle this event.
-        if (isAccessibilityEnabled()
+        if (isAccessibilityInjectionEnabled()
                 && getAccessibilityInjector().handleKeyEventIfNecessary(event)) {
             return true;
         }
@@ -5079,9 +5188,9 @@
         ClipboardManager cm = (ClipboardManager)(mContext
                 .getSystemService(Context.CLIPBOARD_SERVICE));
         if (cm.hasPrimaryClip()) {
-            Point cursorPoint = new Point(contentToViewX(mSelectCursorLeft.x),
-                    contentToViewY(mSelectCursorLeft.y));
-            Point cursorTop = calculateCaretTop();
+            Point cursorPoint = new Point(contentToViewX(mSelectCursorBase.x),
+                    contentToViewY(mSelectCursorBase.y));
+            Point cursorTop = calculateBaseCaretTop();
             cursorTop.set(contentToViewX(cursorTop.x),
                     contentToViewY(cursorTop.y));
 
@@ -5125,17 +5234,22 @@
         return scale;
     }
 
+    private Point calculateBaseCaretTop() {
+        return calculateCaretTop(mSelectCursorBase, mSelectCursorBaseTextQuad);
+    }
+
+    private Point calculateDraggingCaretTop() {
+        return calculateCaretTop(mSelectDraggingCursor, mSelectDraggingTextQuad);
+    }
+
     /**
      * Assuming arbitrary shape of a quadralateral forming text bounds, this
      * calculates the top of a caret.
      */
-    private Point calculateCaretTop() {
-        float scale = scaleAlongSegment(mSelectCursorLeft.x, mSelectCursorLeft.y,
-                mSelectCursorLeftTextQuad.p4, mSelectCursorLeftTextQuad.p3);
-        int x = Math.round(scaleCoordinate(scale,
-                mSelectCursorLeftTextQuad.p1.x, mSelectCursorLeftTextQuad.p2.x));
-        int y = Math.round(scaleCoordinate(scale,
-                mSelectCursorLeftTextQuad.p1.y, mSelectCursorLeftTextQuad.p2.y));
+    private static Point calculateCaretTop(Point base, QuadF quad) {
+        float scale = scaleAlongSegment(base.x, base.y, quad.p4, quad.p3);
+        int x = Math.round(scaleCoordinate(scale, quad.p1.x, quad.p2.x));
+        int y = Math.round(scaleCoordinate(scale, quad.p1.y, quad.p2.y));
         return new Point(x, y);
     }
 
@@ -5146,50 +5260,12 @@
     }
 
     private void syncSelectionCursors() {
-        mSelectCursorLeftLayerId =
-                nativeGetHandleLayerId(mNativeClass, HANDLE_ID_LEFT,
-                        mSelectCursorLeft, mSelectCursorLeftTextQuad);
-        mSelectCursorRightLayerId =
-                nativeGetHandleLayerId(mNativeClass, HANDLE_ID_RIGHT,
-                        mSelectCursorRight, mSelectCursorRightTextQuad);
-    }
-
-    private void adjustSelectionCursors() {
-        if (mIsCaretSelection) {
-            syncSelectionCursors();
-            return; // no need to swap left and right handles.
-        }
-
-        boolean wasDraggingLeft = (mSelectDraggingCursor == mSelectCursorLeft);
-        int oldX = mSelectDraggingCursor.x;
-        int oldY = mSelectDraggingCursor.y;
-        int oldLeftX = mSelectCursorLeft.x;
-        int oldLeftY = mSelectCursorLeft.y;
-        int oldRightX = mSelectCursorRight.x;
-        int oldRightY = mSelectCursorRight.y;
-        syncSelectionCursors();
-
-        boolean rightChanged = (oldRightX != mSelectCursorRight.x
-                || oldRightY != mSelectCursorRight.y);
-        boolean leftChanged = (oldLeftX != mSelectCursorLeft.x
-                || oldLeftY != mSelectCursorLeft.y);
-        if (leftChanged && rightChanged) {
-            // Left and right switched places, so swap dragging cursor
-            boolean draggingLeft = !wasDraggingLeft;
-            mSelectDraggingCursor = (draggingLeft
-                    ? mSelectCursorLeft : mSelectCursorRight);
-            mSelectDraggingTextQuad = (draggingLeft
-                    ? mSelectCursorLeftTextQuad : mSelectCursorRightTextQuad);
-            mSelectDraggingOffset = (draggingLeft
-                    ? mSelectHandleLeftOffset : mSelectHandleRightOffset);
-        }
-        mSelectDraggingCursor.set(oldX, oldY);
-    }
-
-    private float distanceSquared(int x, int y, Point p) {
-        float dx = p.x - x;
-        float dy = p.y - y;
-        return (dx * dx) + (dy * dy);
+        mSelectCursorBaseLayerId =
+                nativeGetHandleLayerId(mNativeClass, HANDLE_ID_BASE,
+                        mSelectCursorBase, mSelectCursorBaseTextQuad);
+        mSelectCursorExtentLayerId =
+                nativeGetHandleLayerId(mNativeClass, HANDLE_ID_EXTENT,
+                        mSelectCursorExtent, mSelectCursorExtentTextQuad);
     }
 
     private boolean setupWebkitSelect() {
@@ -5203,19 +5279,20 @@
         return true;
     }
 
-    private void updateWebkitSelection() {
-        int[] handles = null;
-        if (mIsCaretSelection) {
-            mSelectCursorRight.set(mSelectCursorLeft.x, mSelectCursorLeft.y);
-        }
-        if (mSelectingText) {
-            handles = new int[4];
-            getSelectionHandles(handles);
-        } else {
-            nativeSetTextSelection(mNativeClass, 0);
+    private void updateWebkitSelection(boolean isSnapped) {
+        int handleId = (mSelectDraggingCursor == mSelectCursorBase)
+                ? HANDLE_ID_BASE : HANDLE_ID_EXTENT;
+        int x = mSelectDraggingCursor.x;
+        int y = mSelectDraggingCursor.y;
+        if (isSnapped) {
+            // "center" the cursor in the snapping quad
+            Point top = calculateDraggingCaretTop();
+            x = Math.round((top.x + x) / 2);
+            y = Math.round((top.y + y) / 2);
         }
         mWebViewCore.removeMessages(EventHub.SELECT_TEXT);
-        mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SELECT_TEXT, handles);
+        mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SELECT_TEXT,
+                x, y, (Integer)handleId);
     }
 
     private void resetCaretTimer() {
@@ -5227,14 +5304,6 @@
     }
 
     /**
-     * See {@link WebView#emulateShiftHeld()}
-     */
-    @Override
-    @Deprecated
-    public void emulateShiftHeld() {
-    }
-
-    /**
      * Select all of the text in this WebView.
      *
      * This is an implementation detail.
@@ -5321,16 +5390,6 @@
     }
 
     /**
-     * This is an implementation detail.
-     */
-    public SearchBox getSearchBox() {
-        if ((mWebViewCore == null) || (mWebViewCore.getBrowserFrame() == null)) {
-            return null;
-        }
-        return mWebViewCore.getBrowserFrame().getSearchBox();
-    }
-
-    /**
      * Returns the currently highlighted text as a string.
      */
     String getSelection() {
@@ -5342,8 +5401,8 @@
     public void onAttachedToWindow() {
         if (mWebView.hasWindowFocus()) setActive(true);
 
-        if (isAccessibilityEnabled()) {
-            getAccessibilityInjector().addAccessibilityApisIfNecessary();
+        if (isAccessibilityInjectionEnabled()) {
+            getAccessibilityInjector().toggleAccessibilityFeedback(true);
         }
 
         updateHwAccelerated();
@@ -5355,12 +5414,8 @@
         mZoomManager.dismissZoomPicker();
         if (mWebView.hasWindowFocus()) setActive(false);
 
-        if (isAccessibilityEnabled()) {
-            getAccessibilityInjector().removeAccessibilityApisIfNecessary();
-        } else {
-            // Ensure the injector is cleared if we're detaching from the window
-            // and accessibility is disabled.
-            mAccessibilityInjector = null;
+        if (isAccessibilityInjectionEnabled()) {
+            getAccessibilityInjector().toggleAccessibilityFeedback(false);
         }
 
         updateHwAccelerated();
@@ -5575,24 +5630,24 @@
                 Math.max(0, mEditTextContentBounds.top - buffer),
                 mEditTextContentBounds.right + buffer,
                 mEditTextContentBounds.bottom + buffer);
-        Point caretTop = calculateCaretTop();
+        Point caretTop = calculateBaseCaretTop();
         if (visibleRect.width() < mEditTextContentBounds.width()) {
             // The whole edit won't fit in the width, so use the caret rect
-            if (mSelectCursorLeft.x < caretTop.x) {
-                showRect.left = Math.max(0, mSelectCursorLeft.x - buffer);
+            if (mSelectCursorBase.x < caretTop.x) {
+                showRect.left = Math.max(0, mSelectCursorBase.x - buffer);
                 showRect.right = caretTop.x + buffer;
             } else {
                 showRect.left = Math.max(0, caretTop.x - buffer);
-                showRect.right = mSelectCursorLeft.x + buffer;
+                showRect.right = mSelectCursorBase.x + buffer;
             }
         }
         if (visibleRect.height() < mEditTextContentBounds.height()) {
             // The whole edit won't fit in the height, so use the caret rect
-            if (mSelectCursorLeft.y > caretTop.y) {
+            if (mSelectCursorBase.y > caretTop.y) {
                 showRect.top = Math.max(0, caretTop.y - buffer);
-                showRect.bottom = mSelectCursorLeft.y + buffer;
+                showRect.bottom = mSelectCursorBase.y + buffer;
             } else {
-                showRect.top = Math.max(0, mSelectCursorLeft.y - buffer);
+                showRect.top = Math.max(0, mSelectCursorBase.y - buffer);
                 showRect.bottom = caretTop.y + buffer;
             }
         }
@@ -5836,28 +5891,19 @@
                         ensureSelectionHandles();
                         int shiftedY = y - getTitleHeight() + getScrollY();
                         int shiftedX = x + getScrollX();
-                        if (mSelectHandleCenter != null && mSelectHandleCenter.getBounds()
+                        if (mSelectHandleBaseBounds.contains(shiftedX, shiftedY)) {
+                            mSelectionStarted = true;
+                            mSelectDraggingCursor = mSelectCursorBase;
+                            mSelectDraggingTextQuad = mSelectCursorBaseTextQuad;
+                            if (mIsCaretSelection) {
+                                mPrivateHandler.removeMessages(CLEAR_CARET_HANDLE);
+                                hidePasteButton();
+                            }
+                        } else if (mSelectHandleExtentBounds
                                 .contains(shiftedX, shiftedY)) {
                             mSelectionStarted = true;
-                            mSelectDraggingCursor = mSelectCursorLeft;
-                            mSelectDraggingOffset = mSelectHandleCenterOffset;
-                            mSelectDraggingTextQuad = mSelectCursorLeftTextQuad;
-                            mPrivateHandler.removeMessages(CLEAR_CARET_HANDLE);
-                            hidePasteButton();
-                        } else if (mSelectHandleLeft != null
-                                && mSelectHandleLeft.getBounds()
-                                    .contains(shiftedX, shiftedY)) {
-                            mSelectionStarted = true;
-                            mSelectDraggingOffset = mSelectHandleLeftOffset;
-                            mSelectDraggingCursor = mSelectCursorLeft;
-                            mSelectDraggingTextQuad = mSelectCursorLeftTextQuad;
-                        } else if (mSelectHandleRight != null
-                                && mSelectHandleRight.getBounds()
-                                .contains(shiftedX, shiftedY)) {
-                            mSelectionStarted = true;
-                            mSelectDraggingOffset = mSelectHandleRightOffset;
-                            mSelectDraggingCursor = mSelectCursorRight;
-                            mSelectDraggingTextQuad = mSelectCursorRightTextQuad;
+                            mSelectDraggingCursor = mSelectCursorExtent;
+                            mSelectDraggingTextQuad = mSelectCursorExtentTextQuad;
                         } else if (mIsCaretSelection) {
                             selectionDone();
                         }
@@ -5902,9 +5948,9 @@
                     }
                     if (deltaX != 0 || deltaY != 0) {
                         int handleX = contentX +
-                                viewToContentDimension(mSelectDraggingOffset.x);
+                                viewToContentDimension(mSelectOffset.x);
                         int handleY = contentY +
-                                viewToContentDimension(mSelectDraggingOffset.y);
+                                viewToContentDimension(mSelectOffset.y);
                         mSelectDraggingCursor.set(handleX, handleY);
                         boolean inCursorText =
                                 mSelectDraggingTextQuad.containsPoint(handleX, handleY);
@@ -5915,10 +5961,12 @@
                         } else {
                             endScrollEdit();
                         }
+                        boolean snapped = false;
                         if (inCursorText || (mIsEditingText && !inEditBounds)) {
                             snapDraggingCursor();
+                            snapped = true;
                         }
-                        updateWebkitSelection();
+                        updateWebkitSelection(snapped);
                         if (!inCursorText && mIsEditingText && inEditBounds) {
                             // Visually snap even if we have moved the handle.
                             snapDraggingCursor();
@@ -6041,12 +6089,15 @@
                 break;
             }
             case MotionEvent.ACTION_UP: {
-                endScrollEdit();
-                if (!mConfirmMove && mIsEditingText && mSelectionStarted &&
-                        mIsCaretSelection) {
-                    showPasteWindow();
-                    stopTouch();
-                    break;
+                if (mIsEditingText && mSelectionStarted) {
+                    endScrollEdit();
+                    mPrivateHandler.sendEmptyMessageDelayed(SCROLL_HANDLE_INTO_VIEW,
+                            TEXT_SCROLL_FIRST_SCROLL_MS);
+                    if (!mConfirmMove && mIsCaretSelection) {
+                        showPasteWindow();
+                        stopTouch();
+                        break;
+                    }
                 }
                 mLastTouchUpTime = eventTime;
                 if (mSentAutoScrollMessage) {
@@ -6153,6 +6204,10 @@
         }
     }
 
+    private static int getSelectionCoordinate(int coordinate, int min, int max) {
+        return Math.max(Math.min(coordinate, max), min);
+    }
+
     private void beginScrollEdit() {
         if (mLastEditScroll == 0) {
             mLastEditScroll = SystemClock.uptimeMillis() -
@@ -6161,10 +6216,37 @@
         }
     }
 
+    private void scrollDraggedSelectionHandleIntoView() {
+        if (mSelectDraggingCursor == null) {
+            return;
+        }
+        int x = mSelectDraggingCursor.x;
+        int y = mSelectDraggingCursor.y;
+        if (!mEditTextContentBounds.contains(x,y)) {
+            int left = Math.min(0, x - mEditTextContentBounds.left - EDIT_RECT_BUFFER);
+            int right = Math.max(0, x - mEditTextContentBounds.right + EDIT_RECT_BUFFER);
+            int deltaX = left + right;
+            int above = Math.min(0, y - mEditTextContentBounds.top - EDIT_RECT_BUFFER);
+            int below = Math.max(0, y - mEditTextContentBounds.bottom + EDIT_RECT_BUFFER);
+            int deltaY = above + below;
+            if (deltaX != 0 || deltaY != 0) {
+                int scrollX = getTextScrollX() + deltaX;
+                int scrollY = getTextScrollY() + deltaY;
+                scrollX = clampBetween(scrollX, 0, getMaxTextScrollX());
+                scrollY = clampBetween(scrollY, 0, getMaxTextScrollY());
+                scrollEditText(scrollX, scrollY);
+            }
+        }
+    }
+
     private void endScrollEdit() {
         mLastEditScroll = 0;
     }
 
+    private static int clampBetween(int value, int min, int max) {
+        return Math.max(min, Math.min(value, max));
+    }
+
     private static int getTextScrollDelta(float speed, long deltaT) {
         float distance = speed * deltaT;
         int intDistance = (int)Math.floor(distance);
@@ -6180,10 +6262,10 @@
      */
     private void scrollEditWithCursor() {
         if (mLastEditScroll != 0) {
-            int x = viewToContentX(mLastTouchX + getScrollX() + mSelectDraggingOffset.x);
+            int x = viewToContentX(mLastTouchX + getScrollX() + mSelectOffset.x);
             float scrollSpeedX = getTextScrollSpeed(x, mEditTextContentBounds.left,
                     mEditTextContentBounds.right);
-            int y = viewToContentY(mLastTouchY + getScrollY() + mSelectDraggingOffset.y);
+            int y = viewToContentY(mLastTouchY + getScrollY() + mSelectOffset.y);
             float scrollSpeedY = getTextScrollSpeed(y, mEditTextContentBounds.top,
                     mEditTextContentBounds.bottom);
             if (scrollSpeedX == 0.0f && scrollSpeedY == 0.0f) {
@@ -6193,24 +6275,27 @@
                 long timeSinceLastUpdate = currentTime - mLastEditScroll;
                 int deltaX = getTextScrollDelta(scrollSpeedX, timeSinceLastUpdate);
                 int deltaY = getTextScrollDelta(scrollSpeedY, timeSinceLastUpdate);
+                int scrollX = getTextScrollX() + deltaX;
+                scrollX = clampBetween(scrollX, 0, getMaxTextScrollX());
+                int scrollY = getTextScrollY() + deltaY;
+                scrollY = clampBetween(scrollY, 0, getMaxTextScrollY());
+
                 mLastEditScroll = currentTime;
-                if (deltaX == 0 && deltaY == 0) {
+                if (scrollX == getTextScrollX() && scrollY == getTextScrollY()) {
                     // By probability no text scroll this time. Try again later.
                     mPrivateHandler.sendEmptyMessageDelayed(SCROLL_EDIT_TEXT,
                             TEXT_SCROLL_FIRST_SCROLL_MS);
                 } else {
-                    int scrollX = getTextScrollX() + deltaX;
-                    scrollX = Math.min(getMaxTextScrollX(), scrollX);
-                    scrollX = Math.max(0, scrollX);
-                    int scrollY = getTextScrollY() + deltaY;
-                    scrollY = Math.min(getMaxTextScrollY(), scrollY);
-                    scrollY = Math.max(0, scrollY);
+                    int selectionX = getSelectionCoordinate(x,
+                            mEditTextContentBounds.left, mEditTextContentBounds.right);
+                    int selectionY = getSelectionCoordinate(y,
+                            mEditTextContentBounds.top, mEditTextContentBounds.bottom);
+                    int oldX = mSelectDraggingCursor.x;
+                    int oldY = mSelectDraggingCursor.y;
+                    mSelectDraggingCursor.set(selectionX, selectionY);
+                    updateWebkitSelection(false);
                     scrollEditText(scrollX, scrollY);
-                    int cursorX = mSelectDraggingCursor.x;
-                    int cursorY = mSelectDraggingCursor.y;
-                    mSelectDraggingCursor.set(x - deltaX, y - deltaY);
-                    updateWebkitSelection();
-                    mSelectDraggingCursor.set(cursorX, cursorY);
+                    mSelectDraggingCursor.set(oldX, oldY);
                 }
             }
         }
@@ -6266,10 +6351,10 @@
                 // scrolling.  The rectangle is in document coordinates.
                 final int maxX = mScrollingLayerRect.right;
                 final int maxY = mScrollingLayerRect.bottom;
-                final int resultX = Math.max(0,
-                        Math.min(mScrollingLayerRect.left + contentX, maxX));
-                final int resultY = Math.max(0,
-                        Math.min(mScrollingLayerRect.top + contentY, maxY));
+                final int resultX = clampBetween(maxX, 0,
+                        mScrollingLayerRect.left + contentX);
+                final int resultY = clampBetween(maxY, 0,
+                        mScrollingLayerRect.top + contentY);
 
                 if (resultX != mScrollingLayerRect.left
                         || resultY != mScrollingLayerRect.top
@@ -6370,10 +6455,10 @@
         int x = Math.round(newX);
         int y = Math.round(newY);
         if (mIsEditingText) {
-            x = Math.max(mEditTextContentBounds.left,
-                    Math.min(mEditTextContentBounds.right, x));
-            y = Math.max(mEditTextContentBounds.top,
-                    Math.min(mEditTextContentBounds.bottom, y));
+            x = clampBetween(x, mEditTextContentBounds.left,
+                    mEditTextContentBounds.right);
+            y = clampBetween(y, mEditTextContentBounds.top,
+                    mEditTextContentBounds.bottom);
         }
         mSelectDraggingCursor.set(x, y);
     }
@@ -6402,9 +6487,13 @@
                                 mWebViewPrivate.getVerticalScrollFactor());
                         final int hdelta = (int) (hscroll *
                                 mWebViewPrivate.getHorizontalScrollFactor());
-                        if (pinScrollBy(hdelta, vdelta, false, 0)) {
-                            return true;
-                        }
+
+                        abortAnimation();
+                        int oldTouchMode = mTouchMode;
+                        startScrollingLayer(event.getX(), event.getY());
+                        doDrag(hdelta, vdelta);
+                        mTouchMode = oldTouchMode;
+                        return true;
                     }
                 }
             }
@@ -6436,9 +6525,12 @@
     private long mTrackballUpTime = 0;
     private long mLastCursorTime = 0;
     private Rect mLastCursorBounds;
-    private SelectionHandleAlpha mHandleAlpha = new SelectionHandleAlpha();
-    private ObjectAnimator mHandleAlphaAnimator =
-            ObjectAnimator.ofInt(mHandleAlpha, "alpha", 0);
+    private SelectionHandleAlpha mBaseAlpha = new SelectionHandleAlpha();
+    private SelectionHandleAlpha mExtentAlpha = new SelectionHandleAlpha();
+    private ObjectAnimator mBaseHandleAlphaAnimator =
+            ObjectAnimator.ofInt(mBaseAlpha, "alpha", 0);
+    private ObjectAnimator mExtentHandleAlphaAnimator =
+            ObjectAnimator.ofInt(mExtentAlpha, "alpha", 0);
 
     // Set by default; BrowserActivity clears to interpret trackball data
     // directly for movement. Currently, the framework only passes
@@ -6448,6 +6540,7 @@
     private DrawData mDelaySetPicture;
     private DrawData mLoadedPicture;
 
+    @Override
     public void setMapTrackballToArrowKeys(boolean setMap) {
         mMapTrackballToArrowKeys = setMap;
     }
@@ -6674,6 +6767,7 @@
         }
     }
 
+    @Override
     public void flingScroll(int vx, int vy) {
         mScroller.fling(getScrollX(), getScrollY(), vx, vy, 0, computeMaxScrollX(), 0,
                 computeMaxScrollY(), mOverflingDistance, mOverflingDistance);
@@ -6926,6 +7020,8 @@
 
     @Override
     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
+        // Check if we are destroyed
+        if (mWebViewCore == null) return false;
         // FIXME: If a subwindow is showing find, and the user touches the
         // background window, it can steal focus.
         if (mFindIsUp) return false;
@@ -7235,11 +7331,7 @@
                     // nativeCreate sets mNativeClass to a non-zero value
                     String drawableDir = BrowserFrame.getRawResFilename(
                             BrowserFrame.DRAWABLEDIR, mContext);
-                    WindowManager windowManager =
-                            (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
-                    Display display = windowManager.getDefaultDisplay();
-                    nativeCreate(msg.arg1, drawableDir,
-                            ActivityManager.isHighEndGfx(display));
+                    nativeCreate(msg.arg1, drawableDir, ActivityManager.isHighEndGfx());
                     if (mDelaySetPicture != null) {
                         setNewPicture(mDelaySetPicture, true);
                         mDelaySetPicture = null;
@@ -7325,15 +7417,6 @@
                     mWebView.setKeepScreenOn(msg.arg1 == 1);
                     break;
 
-                case ENTER_FULLSCREEN_VIDEO:
-                    int layerId = msg.arg1;
-
-                    String url = (String) msg.obj;
-                    if (mHTML5VideoViewProxy != null) {
-                        mHTML5VideoViewProxy.enterFullScreenVideo(layerId, url);
-                    }
-                    break;
-
                 case EXIT_FULLSCREEN_VIDEO:
                     if (mHTML5VideoViewProxy != null) {
                         mHTML5VideoViewProxy.exitFullScreenVideo();
@@ -7413,7 +7496,7 @@
                     break;
 
                 case SELECTION_STRING_CHANGED:
-                    if (isAccessibilityEnabled()) {
+                    if (isAccessibilityInjectionEnabled()) {
                         getAccessibilityInjector()
                                 .handleSelectionChangedIfNecessary((String) msg.obj);
                     }
@@ -7472,7 +7555,7 @@
                         mEditTextLayerId = initData.mNodeLayerId;
                         nativeMapLayerRect(mNativeClass, mEditTextLayerId,
                                 mEditTextContentBounds);
-                        mEditTextContent.set(initData.mContentRect);
+                        mEditTextContent.set(initData.mClientRect);
                         relocateAutoCompletePopup();
                     }
                     break;
@@ -7553,6 +7636,10 @@
                     scrollEditWithCursor();
                     break;
 
+                case SCROLL_HANDLE_INTO_VIEW:
+                    scrollDraggedSelectionHandleIntoView();
+                    break;
+
                 default:
                     super.handleMessage(msg);
                     break;
@@ -7588,8 +7675,8 @@
                         .contains(x, y);
             } else {
                 isPressingHandle =
-                        mSelectHandleLeft.getBounds().contains(x, y)
-                        || mSelectHandleRight.getBounds().contains(x, y);
+                        mSelectHandleBaseBounds.contains(x, y)
+                        || mSelectHandleExtentBounds.contains(x, y);
             }
             return isPressingHandle;
         }
@@ -7877,7 +7964,9 @@
         int functor = 0;
         boolean forceInval = isPictureAfterFirstLayout;
         ViewRootImpl viewRoot = mWebView.getViewRootImpl();
-        if (mWebView.isHardwareAccelerated() && viewRoot != null) {
+        if (mWebView.isHardwareAccelerated()
+                && mWebView.getLayerType() != View.LAYER_TYPE_SOFTWARE
+                && viewRoot != null) {
             functor = nativeGetDrawGLFunction(mNativeClass);
             if (functor != 0) {
                 // force an invalidate if functor attach not successful
@@ -7936,8 +8025,10 @@
 
         if (data.mSelectTextPtr != 0 &&
                 (data.mStart != data.mEnd ||
-                (mFieldPointer == nodePointer && mFieldPointer != 0))) {
-            mIsCaretSelection = (data.mStart == data.mEnd);
+                (mFieldPointer == nodePointer && mFieldPointer != 0) ||
+                (nodePointer == 0 && data.mStart == 0 && data.mEnd == 0))) {
+            mIsEditingText = (mFieldPointer == nodePointer) && nodePointer != 0;
+            mIsCaretSelection = (data.mStart == data.mEnd && nodePointer != 0);
             if (mIsCaretSelection &&
                     (mInputConnection == null ||
                     mInputConnection.getEditable().length() == 0)) {
@@ -7946,11 +8037,10 @@
             } else {
                 if (!mSelectingText) {
                     setupWebkitSelect();
-                } else if (!mSelectionStarted) {
-                    syncSelectionCursors();
                 } else {
-                    adjustSelectionCursors();
+                    syncSelectionCursors();
                 }
+                animateHandles();
                 if (mIsCaretSelection) {
                     resetCaretTimer();
                 }
@@ -7966,8 +8056,10 @@
         float maxScrollX = getMaxTextScrollX();
         float scrollPercentX = ((float)scrollX)/maxScrollX;
         mEditTextContent.offsetTo(-scrollX, -scrollY);
-        mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SCROLL_TEXT_INPUT, 0,
+        mWebViewCore.removeMessages(EventHub.SCROLL_TEXT_INPUT);
+        mWebViewCore.sendMessage(EventHub.SCROLL_TEXT_INPUT, 0,
                 scrollY, (Float)scrollPercentX);
+        animateHandles();
     }
 
     private void beginTextBatch() {
@@ -8412,14 +8504,6 @@
     }
 
     /**
-     * See {@link WebView#debugDump()}
-     */
-    @Override
-    @Deprecated
-    public void debugDump() {
-    }
-
-    /**
      * Enable the communication b/t the webView and VideoViewProxy
      *
      * only used by the Browser
@@ -8553,6 +8637,54 @@
         WebViewCore.setShouldMonitorWebCoreThread();
     }
 
+    @Override
+    public void dumpViewHierarchyWithProperties(BufferedWriter out, int level) {
+        int layer = getBaseLayer();
+        if (layer != 0) {
+            try {
+                ByteArrayOutputStream stream = new ByteArrayOutputStream();
+                ViewStateSerializer.dumpLayerHierarchy(layer, stream, level);
+                stream.close();
+                byte[] buf = stream.toByteArray();
+                out.write(new String(buf, "ascii"));
+            } catch (IOException e) {}
+        }
+    }
+
+    @Override
+    public View findHierarchyView(String className, int hashCode) {
+        if (mNativeClass == 0) return null;
+        Picture pic = new Picture();
+        if (!nativeDumpLayerContentToPicture(mNativeClass, className, hashCode, pic)) {
+            return null;
+        }
+        return new PictureWrapperView(getContext(), pic, mWebView);
+    }
+
+    private static class PictureWrapperView extends View {
+        Picture mPicture;
+        WebView mWebView;
+
+        public PictureWrapperView(Context context, Picture picture, WebView parent) {
+            super(context);
+            mPicture = picture;
+            mWebView = parent;
+            setWillNotDraw(false);
+            setRight(mPicture.getWidth());
+            setBottom(mPicture.getHeight());
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            canvas.drawPicture(mPicture);
+        }
+
+        @Override
+        public boolean post(Runnable action) {
+            return mWebView.post(action);
+        }
+    }
+
     private native void     nativeCreate(int ptr, String drawableDir, boolean isHighEndGfx);
     private native void     nativeDebugDump();
     private static native void nativeDestroy(int ptr);
@@ -8573,6 +8705,8 @@
             int scrollingLayer);
     private native int      nativeGetBaseLayer(int nativeInstance);
     private native void     nativeCopyBaseContentToPicture(Picture pict);
+    private native boolean     nativeDumpLayerContentToPicture(int nativeInstance,
+            String className, int layerId, Picture pict);
     private native boolean  nativeHasContent();
     private native void     nativeStopGL(int ptr);
     private native void     nativeDiscardAllTextures();
@@ -8616,4 +8750,7 @@
     private static native int nativeSetHwAccelerated(int instance, boolean hwAccelerated);
     private static native void nativeFindMaxVisibleRect(int instance, int layerId,
             Rect visibleContentRect);
+    private static native boolean nativeIsHandleLeft(int instance, int handleId);
+    private static native boolean nativeIsPointVisible(int instance,
+            int layerId, int contentX, int contentY);
 }
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 6aff10a..08a046a 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -204,43 +204,16 @@
     }
 
     /**
-     * Notify the host application that an SSL error occurred while loading a
-     * resource, but the WebView chose to proceed anyway based on a
-     * decision retained from a previous response to onReceivedSslError().
-     * @hide
-     */
-    public void onProceededAfterSslError(WebView view, SslError error) {
-    }
-
-    /**
-     * Notify the host application to handle a SSL client certificate
-     * request (display the request to the user and ask whether to
-     * proceed with a client certificate or not). The host application
-     * has to call either handler.cancel() or handler.proceed() as the
-     * connection is suspended and waiting for the response. The
-     * default behavior is to cancel, returning no client certificate.
+     * Notifies the host application that the WebView received an HTTP
+     * authentication request. The host application can use the supplied
+     * {@link HttpAuthHandler} to set the WebView's response to the request.
+     * The default behavior is to cancel the request.
      *
-     * @param view The WebView that is initiating the callback.
-     * @param handler A ClientCertRequestHandler object that will
-     *            handle the user's response.
-     * @param host_and_port The host and port of the requesting server.
-     *
-     * @hide
-     */
-    public void onReceivedClientCertRequest(WebView view,
-            ClientCertRequestHandler handler, String host_and_port) {
-        handler.cancel();
-    }
-
-    /**
-     * Notify the host application to handle an authentication request. The
-     * default behavior is to cancel the request.
-     *
-     * @param view The WebView that is initiating the callback.
-     * @param handler The HttpAuthHandler that will handle the user's response.
-     * @param host The host requiring authentication.
-     * @param realm A description to help store user credentials for future
-     *            visits.
+     * @param view the WebView that is initiating the callback
+     * @param handler the HttpAuthHandler used to set the WebView's response
+     * @param host the host requiring authentication
+     * @param realm the realm for which authentication is required
+     * @see Webview#getHttpAuthUsernamePassword
      */
     public void onReceivedHttpAuthRequest(WebView view,
             HttpAuthHandler handler, String host, String realm) {
diff --git a/core/java/android/webkit/WebViewClientClassicExt.java b/core/java/android/webkit/WebViewClientClassicExt.java
new file mode 100644
index 0000000..a873585
--- /dev/null
+++ b/core/java/android/webkit/WebViewClientClassicExt.java
@@ -0,0 +1,53 @@
+/*
+ * 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.webkit;
+
+import android.net.http.SslError;
+
+/**
+ * Adds WebViewClassic specific extension methods to the WebViewClient callback class.
+ * These are not part of the public WebView API, so the class is hidden.
+ * @hide
+ */
+public class WebViewClientClassicExt extends WebViewClient {
+
+    /**
+     * Notify the host application that an SSL error occurred while loading a
+     * resource, but the WebView chose to proceed anyway based on a
+     * decision retained from a previous response to onReceivedSslError().
+     */
+    public void onProceededAfterSslError(WebView view, SslError error) {
+    }
+
+    /**
+     * Notify the host application to handle a SSL client certificate
+     * request (display the request to the user and ask whether to
+     * proceed with a client certificate or not). The host application
+     * has to call either handler.cancel() or handler.proceed() as the
+     * connection is suspended and waiting for the response. The
+     * default behavior is to cancel, returning no client certificate.
+     *
+     * @param view The WebView that is initiating the callback.
+     * @param handler A ClientCertRequestHandler object that will
+     *            handle the user's response.
+     * @param host_and_port The host and port of the requesting server.
+     */
+    public void onReceivedClientCertRequest(WebView view,
+            ClientCertRequestHandler handler, String host_and_port) {
+        handler.cancel();
+    }
+}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index ae49202..3fb3ec6 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -132,6 +132,8 @@
     private int mRestoredX = 0;
     private int mRestoredY = 0;
 
+    private MockGeolocation mMockGeolocation = new MockGeolocation(this);
+
     private DeviceMotionAndOrientationManager mDeviceMotionAndOrientationManager =
             new DeviceMotionAndOrientationManager(this);
     private DeviceMotionService mDeviceMotionService;
@@ -441,7 +443,7 @@
     }
 
     /**
-     * Notify the browser that the origin has exceeded it's database quota.
+     * Notify the embedding application that the origin has exceeded it's database quota.
      * @param url The URL that caused the overflow.
      * @param databaseIdentifier The identifier of the database.
      * @param quota The current quota for the origin.
@@ -466,12 +468,15 @@
     }
 
     /**
-     * Notify the browser that the appcache has exceeded its max size.
+     * Notify the embedding application that the appcache has reached or exceeded its maximum
+     * allowed storage size.
+     *
      * @param requiredStorage is the amount of storage, in bytes, that would be
      * needed in order for the last appcache operation to succeed.
+     * @param maxSize maximum allowed Application Cache database size, in bytes.
      */
-    protected void reachedMaxAppCacheSize(long requiredStorage) {
-        mCallbackProxy.onReachedMaxAppCacheSize(requiredStorage, getUsedQuota(),
+    protected void reachedMaxAppCacheSize(long requiredStorage, long maxSize) {
+        mCallbackProxy.onReachedMaxAppCacheSize(requiredStorage, maxSize,
                 new WebStorage.QuotaUpdater() {
                     @Override
                     public void updateQuota(long newQuota) {
@@ -560,24 +565,6 @@
     }
 
     /**
-     * Notify the webview that this is an installable web app.
-     */
-    protected void setInstallableWebApp() {
-        mCallbackProxy.setInstallableWebApp();
-    }
-
-    /**
-     * Notify the webview that we want to display the video layer fullscreen.
-     */
-    protected void enterFullscreenForVideoLayer(int layerId, String url) {
-        if (mWebViewClassic == null) return;
-        Message message = Message.obtain(mWebViewClassic.mPrivateHandler,
-                       WebViewClassic.ENTER_FULLSCREEN_VIDEO, layerId, 0);
-        message.obj = url;
-        message.sendToTarget();
-    }
-
-    /**
      * Notify the webview that we want to exit the video fullscreen.
      * This is called through JNI by webcore.
      */
@@ -619,8 +606,6 @@
      */
     private native void nativeNotifyAnimationStarted(int nativeClass);
 
-    private native boolean nativeFocusBoundsChanged(int nativeClass);
-
     private native boolean nativeKey(int nativeClass, int keyCode,
             int unichar, int repeatCount, boolean isShift, boolean isAlt,
             boolean isSym, boolean isDown);
@@ -961,7 +946,7 @@
         public int mMaxLength;
         public Rect mContentBounds;
         public int mNodeLayerId;
-        public Rect mContentRect;
+        public Rect mClientRect;
     }
 
     // mAction of TouchEventData can be MotionEvent.getAction() which uses the
@@ -1200,6 +1185,7 @@
         static final int SET_INITIAL_FOCUS = 224;
 
         static final int SAVE_VIEW_STATE = 225;
+        static final int SET_USE_MOCK_GEOLOCATION = 226;
 
         // Private handler for WebCore messages.
         private Handler mHandler;
@@ -1307,13 +1293,8 @@
                             } else {
                                 xPercent = ((Float) msg.obj).floatValue();
                             }
-                            Rect contentBounds = new Rect();
                             nativeScrollFocusedTextInput(mNativeClass, xPercent,
-                                    msg.arg2, contentBounds);
-                            Message.obtain(
-                                    mWebViewClassic.mPrivateHandler,
-                                    WebViewClassic.UPDATE_CONTENT_BOUNDS,
-                                    contentBounds).sendToTarget();
+                                    msg.arg2);
                             break;
 
                         case LOAD_URL: {
@@ -1661,6 +1642,10 @@
                                     (Set<String>) msg.obj);
                             break;
 
+                        case SET_USE_MOCK_GEOLOCATION:
+                            setUseMockGeolocation();
+                            break;
+
                         case SET_USE_MOCK_DEVICE_ORIENTATION:
                             setUseMockDeviceOrientation();
                             break;
@@ -1709,13 +1694,9 @@
                             nativeInsertText(mNativeClass, (String) msg.obj);
                             break;
                         case SELECT_TEXT: {
-                            int[] args = (int[]) msg.obj;
-                            if (args == null) {
-                                nativeClearTextSelection(mNativeClass);
-                            } else {
-                                nativeSelectText(mNativeClass, args[0],
-                                        args[1], args[2], args[3]);
-                            }
+                            int handleId = (Integer) msg.obj;
+                            nativeSelectText(mNativeClass, handleId,
+                                    msg.arg1, msg.arg2);
                             break;
                         }
                         case SELECT_WORD_AT: {
@@ -2140,8 +2121,8 @@
         return width;
     }
 
-    // Utility method for exceededDatabaseQuota and reachedMaxAppCacheSize
-    // callbacks. Computes the sum of database quota for all origins.
+    // Utility method for exceededDatabaseQuota callback. Computes the sum
+    // of WebSQL database quota for all origins.
     private long getUsedQuota() {
         WebStorageClassic webStorage = WebStorageClassic.getInstance();
         Collection<WebStorage.Origin> origins = webStorage.getOriginsSync();
@@ -2193,7 +2174,6 @@
         // only non-null if it is for the first picture set after the first layout
         ViewState mViewState;
         boolean mFirstLayoutForNonStandardLoad;
-        boolean mFocusSizeChanged;
     }
 
     DrawData mLastDrawData = null;
@@ -2248,7 +2228,6 @@
 
     private void webkitDraw(DrawData draw) {
         if (mWebViewClassic != null) {
-            draw.mFocusSizeChanged = nativeFocusBoundsChanged(mNativeClass);
             draw.mViewSize = new Point(mCurrentViewWidth, mCurrentViewHeight);
             if (mSettings.getUseWideViewPort()) {
                 draw.mMinPrefWidth = Math.max(
@@ -2331,7 +2310,6 @@
                     Log.w(LOGTAG, "Cannot pauseUpdatePicture, core destroyed or not initialized!");
                     return;
                 }
-                core.nativeSetIsPaused(core.mNativeClass, true);
                 core.mDrawIsPaused = true;
             }
         }
@@ -2349,7 +2327,6 @@
                     Log.w(LOGTAG, "Cannot resumeUpdatePicture, core destroyed!");
                     return;
                 }
-                core.nativeSetIsPaused(core.mNativeClass, false);
                 core.mDrawIsPaused = false;
                 // always redraw on resume to reenable gif animations
                 core.mDrawIsScheduled = false;
@@ -2364,13 +2341,13 @@
     //////////////////////////////////////////////////////////////////////////
 
     private void restoreState(int index) {
-        WebBackForwardList list = mCallbackProxy.getBackForwardList();
+        WebBackForwardListClassic list = mCallbackProxy.getBackForwardList();
         int size = list.getSize();
         for (int i = 0; i < size; i++) {
             list.getItemAtIndex(i).inflate(mBrowserFrame.mNativeFrame);
         }
         mBrowserFrame.mLoadInitFromJava = true;
-        list.restoreIndex(mBrowserFrame.mNativeFrame, index);
+        WebBackForwardListClassic.restoreIndex(mBrowserFrame.mNativeFrame, index);
         mBrowserFrame.mLoadInitFromJava = false;
     }
 
@@ -2502,6 +2479,13 @@
         setupViewport(true);
     }
 
+    static float getFixedDisplayDensity(Context context) {
+        // We make bad assumptions about multiplying and dividing density by 100,
+        // force them to be true with this hack
+        float density = context.getResources().getDisplayMetrics().density;
+        return ((int) (density * 100)) / 100.0f;
+    }
+
     private void setupViewport(boolean updateViewState) {
         if (mWebViewClassic == null || mSettings == null) {
             // We've been destroyed or are being destroyed, return early
@@ -2546,11 +2530,13 @@
         // adjust the default scale to match the densityDpi
         float adjust = 1.0f;
         if (mViewportDensityDpi == -1) {
-            adjust = mContext.getResources().getDisplayMetrics().density;
+            adjust = getFixedDisplayDensity(mContext);
         } else if (mViewportDensityDpi > 0) {
             adjust = (float) mContext.getResources().getDisplayMetrics().densityDpi
                     / mViewportDensityDpi;
+            adjust = ((int) (adjust * 100)) / 100.0f;
         }
+
         // Remove any update density messages in flight.
         // If the density is indeed different from WebView's default scale,
         // a new message will be queued.
@@ -2788,14 +2774,11 @@
     }
 
     // called by JNI
-    private void updateTextfield(int ptr, boolean changeToPassword,
-            String text, int textGeneration) {
+    private void updateTextfield(int ptr, String text, int textGeneration) {
         if (mWebViewClassic != null) {
-            Message msg = Message.obtain(mWebViewClassic.mPrivateHandler,
+            Message.obtain(mWebViewClassic.mPrivateHandler,
                     WebViewClassic.UPDATE_TEXTFIELD_TEXT_MSG_ID, ptr,
-                    textGeneration, text);
-            msg.getData().putBoolean("password", changeToPassword);
-            msg.sendToTarget();
+                    textGeneration, text).sendToTarget();
         }
     }
 
@@ -2856,7 +2839,7 @@
      * Scroll the focused textfield to (xPercent, y) in document space
      */
     private native void nativeScrollFocusedTextInput(int nativeClass,
-            float xPercent, int y, Rect contentBounds);
+            float xPercent, int y);
 
     // these must be in document space (i.e. not scaled/zoomed).
     private native void nativeSetScrollOffset(int nativeClass,
@@ -3064,6 +3047,22 @@
         mDeviceMotionAndOrientationManager.setUseMock();
     }
 
+    private void setUseMockGeolocation() {
+        mMockGeolocation.setUseMock();
+    }
+
+    public void setMockGeolocationPosition(double latitude, double longitude, double accuracy) {
+        mMockGeolocation.setPosition(latitude, longitude, accuracy);
+    }
+
+    public void setMockGeolocationError(int code, String message) {
+        mMockGeolocation.setError(code, message);
+    }
+
+    public void setMockGeolocationPermission(boolean allow) {
+        mMockGeolocation.setPermission(allow);
+    }
+
     public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
             boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma) {
         mDeviceMotionAndOrientationManager.setMockOrientation(canProvideAlpha, alpha,
@@ -3090,7 +3089,6 @@
         sShouldMonitorWebCoreThread = true;
     }
 
-    private native void nativeSetIsPaused(int nativeClass, boolean isPaused);
     private native void nativePause(int nativeClass);
     private native void nativeResume(int nativeClass);
     private native void nativeFreeMemory(int nativeClass);
@@ -3136,7 +3134,7 @@
     private native String nativeGetText(int nativeClass,
             int startX, int startY, int endX, int endY);
     private native void nativeSelectText(int nativeClass,
-            int startX, int startY, int endX, int endY);
+            int handleId, int x, int y);
     private native void nativeClearTextSelection(int nativeClass);
     private native boolean nativeSelectWordAt(int nativeClass, int x, int y);
     private native void nativeSelectAll(int nativeClass);
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index 9d10d67..5597259 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -23,13 +23,15 @@
  * application has stored any of the following types of browsing data and
  * to clear any such stored data for all WebViews in the application.
  * <ul>
- *  <li>Username/password pairs entered into web forms</li>
+ *  <li>Username/password pairs for web forms</li>
  *  <li>HTTP authentication username/password pairs</li>
  *  <li>Data entered into text fields (e.g. for autocomplete suggestions)</li>
  * </ul>
  */
 public class WebViewDatabase {
-    // TODO: deprecate/hide this.
+    /**
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
+     */
     protected static final String LOGTAG = "webviewdatabase";
 
     /**
@@ -38,55 +40,70 @@
     protected WebViewDatabase() {
     }
 
-    public static synchronized WebViewDatabase getInstance(Context context) {
+    public static WebViewDatabase getInstance(Context context) {
         return WebViewFactory.getProvider().getWebViewDatabase(context);
     }
 
     /**
-     * Gets whether there are any username/password combinations
-     * from web pages saved.
+     * Gets whether there are any saved username/password pairs for web forms.
+     * Note that these are unrelated to HTTP authentication credentials.
      *
-     * @return true if there are any username/passwords used in web
-     *         forms saved
+     * @return true if there are any saved username/password pairs
+     * @see WebView#savePassword
+     * @see clearUsernamePassword
      */
     public boolean hasUsernamePassword() {
         throw new MustOverrideException();
     }
 
     /**
-     * Clears any username/password combinations saved from web forms.
+     * Clears any saved username/password pairs for web forms.
+     * Note that these are unrelated to HTTP authentication credentials.
+     *
+     * @see WebView#savePassword
+     * @see hasUsernamePassword
      */
     public void clearUsernamePassword() {
         throw new MustOverrideException();
     }
 
     /**
-     * Gets whether there are any HTTP authentication username/password combinations saved.
+     * Gets whether there are any saved credentials for HTTP authentication.
      *
-     * @return true if there are any HTTP authentication username/passwords saved
+     * @return whether there are any saved credentials
+     * @see Webview#getHttpAuthUsernamePassword
+     * @see Webview#setHttpAuthUsernamePassword
+     * @see clearHttpAuthUsernamePassword
      */
     public boolean hasHttpAuthUsernamePassword() {
         throw new MustOverrideException();
     }
 
     /**
-     * Clears any HTTP authentication username/passwords that are saved.
+     * Clears any saved credentials for HTTP authentication.
+     *
+     * @see Webview#getHttpAuthUsernamePassword
+     * @see Webview#setHttpAuthUsernamePassword
+     * @see hasHttpAuthUsernamePassword
      */
     public void clearHttpAuthUsernamePassword() {
         throw new MustOverrideException();
     }
 
     /**
-     * Gets whether there is any previously-entered form data saved.
+     * Gets whether there is any saved data for web forms.
      *
-     * @return true if there is form data saved
+     * @return whether there is any saved data for web forms
+     * @see clearFormData
      */
     public boolean hasFormData() {
         throw new MustOverrideException();
     }
 
     /**
-     * Clears any stored previously-entered form data.
+     * Clears any saved data for web forms.
+     *
+     * @see hasFormData
      */
     public void clearFormData() {
         throw new MustOverrideException();
diff --git a/core/java/android/webkit/WebViewDatabaseClassic.java b/core/java/android/webkit/WebViewDatabaseClassic.java
index 9b1d4cb..be01028 100644
--- a/core/java/android/webkit/WebViewDatabaseClassic.java
+++ b/core/java/android/webkit/WebViewDatabaseClassic.java
@@ -52,6 +52,7 @@
     //          implemented for b/5265606.
 
     private static WebViewDatabaseClassic sInstance = null;
+    private static final Object sInstanceLock = new Object();
 
     private static SQLiteDatabase sDatabase = null;
 
@@ -99,7 +100,8 @@
     // Initially true until the background thread completes.
     private boolean mInitialized = false;
 
-    WebViewDatabaseClassic(final Context context) {
+    private WebViewDatabaseClassic(final Context context) {
+        JniUtil.setContext(context);
         new Thread() {
             @Override
             public void run() {
@@ -110,11 +112,13 @@
         // Singleton only, use getInstance()
     }
 
-    public static synchronized WebViewDatabaseClassic getInstance(Context context) {
-        if (sInstance == null) {
-            sInstance = new WebViewDatabaseClassic(context);
+    public static WebViewDatabaseClassic getInstance(Context context) {
+        synchronized (sInstanceLock) {
+            if (sInstance == null) {
+                sInstance = new WebViewDatabaseClassic(context);
+            }
+            return sInstance;
         }
-        return sInstance;
     }
 
     private synchronized void init(Context context) {
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 73ae910..b833a01 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -16,14 +16,23 @@
 
 package android.webkit;
 
+import android.os.Build;
+import android.os.StrictMode;
+import android.os.SystemProperties;
 import android.util.Log;
 
+import dalvik.system.PathClassLoader;
+
 /**
  * Top level factory, used creating all the main WebView implementation classes.
  */
 class WebViewFactory {
     // Default Provider factory class name.
-    private static final String DEFAULT_WEB_VIEW_FACTORY = "android.webkit.WebViewClassic$Factory";
+    // TODO: When the Chromium powered WebView is ready, it should be the default factory class.
+    private static final String DEFAULT_WEBVIEW_FACTORY = "android.webkit.WebViewClassic$Factory";
+    private static final String CHROMIUM_WEBVIEW_FACTORY =
+            "com.android.webviewchromium.WebViewChromiumFactoryProvider";
+    private static final String CHROMIUM_WEBVIEW_JAR = "/system/framework/webviewchromium.jar";
 
     private static final String LOGTAG = "WebViewFactory";
 
@@ -32,24 +41,54 @@
     // Cache the factory both for efficiency, and ensure any one process gets all webviews from the
     // same provider.
     private static WebViewFactoryProvider sProviderInstance;
+    private static final Object sProviderLock = new Object();
 
-    static synchronized WebViewFactoryProvider getProvider() {
-        // For now the main purpose of this function (and the factory abstraction) is to keep
-        // us honest and minimize usage of WebViewClassic internals when binding the proxy.
-        if (sProviderInstance != null) return sProviderInstance;
+    static WebViewFactoryProvider getProvider() {
+        synchronized (sProviderLock) {
+            // For now the main purpose of this function (and the factory abstraction) is to keep
+            // us honest and minimize usage of WebViewClassic internals when binding the proxy.
+            if (sProviderInstance != null) return sProviderInstance;
 
-        sProviderInstance = getFactoryByName(DEFAULT_WEB_VIEW_FACTORY);
-        if (sProviderInstance == null) {
-            if (DEBUG) Log.v(LOGTAG, "Falling back to explicit linkage");
-            sProviderInstance = new WebViewClassic.Factory();
+            // For debug builds, we allow a system property to specify that we should use the
+            // Chromium powered WebView. This enables us to switch between implementations
+            // at runtime. For user (release) builds, don't allow this.
+            if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("webview.use_chromium", false)) {
+                StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+                try {
+                    sProviderInstance = loadChromiumProvider();
+                    if (DEBUG) Log.v(LOGTAG, "Loaded Chromium provider: " + sProviderInstance);
+                } finally {
+                    StrictMode.setThreadPolicy(oldPolicy);
+                }
+            }
+
+            if (sProviderInstance == null) {
+                if (DEBUG) Log.v(LOGTAG, "Falling back to default provider: "
+                        + DEFAULT_WEBVIEW_FACTORY);
+                sProviderInstance = getFactoryByName(DEFAULT_WEBVIEW_FACTORY,
+                        WebViewFactory.class.getClassLoader());
+                if (sProviderInstance == null) {
+                    if (DEBUG) Log.v(LOGTAG, "Falling back to explicit linkage");
+                    sProviderInstance = new WebViewClassic.Factory();
+                }
+            }
+            return sProviderInstance;
         }
-        return sProviderInstance;
     }
 
-    private static WebViewFactoryProvider getFactoryByName(String providerName) {
+    // TODO: This allows us to have the legacy and Chromium WebView coexist for development
+    // and side-by-side testing. After transition, remove this when no longer required.
+    private static WebViewFactoryProvider loadChromiumProvider() {
+        ClassLoader clazzLoader = new PathClassLoader(CHROMIUM_WEBVIEW_JAR, null,
+                WebViewFactory.class.getClassLoader());
+        return getFactoryByName(CHROMIUM_WEBVIEW_FACTORY, clazzLoader);
+    }
+
+    private static WebViewFactoryProvider getFactoryByName(String providerName,
+            ClassLoader loader) {
         try {
             if (DEBUG) Log.v(LOGTAG, "attempt to load class " + providerName);
-            Class<?> c = Class.forName(providerName);
+            Class<?> c = Class.forName(providerName, true, loader);
             if (DEBUG) Log.v(LOGTAG, "instantiating factory");
             return (WebViewFactoryProvider) c.newInstance();
         } catch (ClassNotFoundException e) {
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
index 1d302f1..934ef83 100644
--- a/core/java/android/webkit/WebViewFactoryProvider.java
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -42,6 +42,12 @@
          * {@link android.webkit.WebView#disablePlatformNotifications()}
          */
         void setPlatformNotificationsEnabled(boolean enable);
+
+        /**
+         * Implements the API method:
+         * {@link android.webkit.WebSettings#getDefaultUserAgent(Context) }
+         */
+        String getDefaultUserAgent(Context context);
     }
 
     Statics getStatics();
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 867ee54..c9f9fbd 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -37,6 +37,7 @@
 import android.webkit.WebView.HitTestResult;
 import android.webkit.WebView.PictureListener;
 
+import java.io.BufferedWriter;
 import java.io.File;
 import java.util.Map;
 
@@ -220,8 +221,6 @@
 
     public WebSettings getSettings();
 
-    public void emulateShiftHeld();
-
     public void setMapTrackballToArrowKeys(boolean setMap);
 
     public void flingScroll(int vx, int vy);
@@ -236,7 +235,9 @@
 
     public boolean zoomOut();
 
-    public void debugDump();
+    public void dumpViewHierarchyWithProperties(BufferedWriter out, int level);
+
+    public View findHierarchyView(String className, int hashCode);
 
     //-------------------------------------------------------------------------
     // Provider glue methods
diff --git a/core/java/android/webkit/ZoomControlEmbedded.java b/core/java/android/webkit/ZoomControlEmbedded.java
index d2a0561..ae19832 100644
--- a/core/java/android/webkit/ZoomControlEmbedded.java
+++ b/core/java/android/webkit/ZoomControlEmbedded.java
@@ -90,7 +90,7 @@
             View controls = mZoomButtonsController.getZoomControls();
             ViewGroup.LayoutParams params = controls.getLayoutParams();
             if (params instanceof FrameLayout.LayoutParams) {
-                ((FrameLayout.LayoutParams) params).gravity = Gravity.RIGHT;
+                ((FrameLayout.LayoutParams) params).gravity = Gravity.END;
             }
         }
         return mZoomButtonsController;
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 80a6782..1d864e5 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -287,6 +287,7 @@
         if (!exceedsMinScaleIncrement(mMinZoomScale, mMaxZoomScale)) {
             mMaxZoomScale = mMinZoomScale;
         }
+        sanitizeMinMaxScales();
     }
 
     public final float getScale() {
@@ -909,6 +910,14 @@
         }
     }
 
+    private void sanitizeMinMaxScales() {
+        if (mMinZoomScale > mMaxZoomScale) {
+            Log.w(LOGTAG, "mMinZoom > mMaxZoom!!! " + mMinZoomScale + " > " + mMaxZoomScale,
+                    new Exception());
+            mMaxZoomScale = mMinZoomScale;
+        }
+    }
+
     public void onSizeChanged(int w, int h, int ow, int oh) {
         // reset zoom and anchor to the top left corner of the screen
         // unless we are already zooming
@@ -933,6 +942,7 @@
             if (mInitialScale > 0 && mInitialScale < mMinZoomScale) {
                 mMinZoomScale = mInitialScale;
             }
+            sanitizeMinMaxScales();
         }
 
         dismissZoomPicker();
@@ -1004,6 +1014,7 @@
         } else {
             mMaxZoomScale = viewState.mMaxScale;
         }
+        sanitizeMinMaxScales();
     }
 
     /**
@@ -1033,6 +1044,7 @@
         if (!mMinZoomScaleFixed || settings.getUseWideViewPort()) {
             mMinZoomScale = newZoomOverviewScale;
             mMaxZoomScale = Math.max(mMaxZoomScale, mMinZoomScale);
+            sanitizeMinMaxScales();
         }
         // fit the content width to the current view for the first new picture
         // after first layout.
@@ -1113,6 +1125,7 @@
             mMinZoomScale = (mInitialScale > 0) ?
                     Math.min(mInitialScale, overviewScale) : overviewScale;
             mMaxZoomScale = Math.max(mMaxZoomScale, mMinZoomScale);
+            sanitizeMinMaxScales();
         }
 
         if (!mWebView.drawHistory()) {
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 437da59..33a8531 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -40,7 +40,6 @@
 import android.util.StateSet;
 import android.view.ActionMode;
 import android.view.ContextMenu.ContextMenuInfo;
-import android.view.FocusFinder;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
 import android.view.InputDevice;
@@ -66,6 +65,7 @@
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputConnectionWrapper;
 import android.view.inputmethod.InputMethodManager;
+import android.widget.RemoteViews.OnClickHandler;
 
 import com.android.internal.R;
 
@@ -676,6 +676,14 @@
     static final Interpolator sLinearInterpolator = new LinearInterpolator();
 
     /**
+     * The saved state that we will be restoring from when we next sync.
+     * Kept here so that if we happen to be asked to save our state before
+     * the sync happens, we can return this existing data rather than losing
+     * it.
+     */
+    private SavedState mPendingSync;
+
+    /**
      * Interface definition for a callback to be invoked when the list or grid
      * has been scrolled.
      */
@@ -974,6 +982,12 @@
 
         // Start selection mode if needed. We don't need to if we're unchecking something.
         if (value && mChoiceMode == CHOICE_MODE_MULTIPLE_MODAL && mChoiceActionMode == null) {
+            if (mMultiChoiceModeCallback == null ||
+                    !mMultiChoiceModeCallback.hasWrappedCallback()) {
+                throw new IllegalStateException("AbsListView: attempted to start selection mode " +
+                        "for CHOICE_MODE_MULTIPLE_MODAL but no choice mode callback was " +
+                        "supplied. Call setMultiChoiceModeListener to set a callback.");
+            }
             mChoiceActionMode = startActionMode(mMultiChoiceModeCallback);
         }
 
@@ -1041,29 +1055,29 @@
 
             if (mChoiceMode == CHOICE_MODE_MULTIPLE ||
                     (mChoiceMode == CHOICE_MODE_MULTIPLE_MODAL && mChoiceActionMode != null)) {
-                boolean newValue = !mCheckStates.get(position, false);
-                mCheckStates.put(position, newValue);
+                boolean checked = !mCheckStates.get(position, false);
+                mCheckStates.put(position, checked);
                 if (mCheckedIdStates != null && mAdapter.hasStableIds()) {
-                    if (newValue) {
+                    if (checked) {
                         mCheckedIdStates.put(mAdapter.getItemId(position), position);
                     } else {
                         mCheckedIdStates.delete(mAdapter.getItemId(position));
                     }
                 }
-                if (newValue) {
+                if (checked) {
                     mCheckedItemCount++;
                 } else {
                     mCheckedItemCount--;
                 }
                 if (mChoiceActionMode != null) {
                     mMultiChoiceModeCallback.onItemCheckedStateChanged(mChoiceActionMode,
-                            position, id, newValue);
+                            position, id, checked);
                     dispatchItemClick = false;
                 }
                 checkedStateChanged = true;
             } else if (mChoiceMode == CHOICE_MODE_SINGLE) {
-                boolean newValue = !mCheckStates.get(position, false);
-                if (newValue) {
+                boolean checked = !mCheckStates.get(position, false);
+                if (checked) {
                     mCheckStates.clear();
                     mCheckStates.put(position, true);
                     if (mCheckedIdStates != null && mAdapter.hasStableIds()) {
@@ -1329,150 +1343,6 @@
     }
 
     @Override
-    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
-        if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
-            switch(direction) {
-                case ACCESSIBILITY_FOCUS_BACKWARD: {
-                    View focusable = (getChildCount() > 0) ? getChildAt(getChildCount() - 1) : this;
-                    if (focusable.isAccessibilityFocusable()) {
-                        views.add(focusable);
-                    }
-                } return;
-                case ACCESSIBILITY_FOCUS_FORWARD: {
-                    if (isAccessibilityFocusable()) {
-                        views.add(this);
-                    }
-                } return;
-            }
-        }
-        super.addFocusables(views, direction, focusableMode);
-    }
-
-    @Override
-    public View focusSearch(int direction) {
-        return focusSearch(this, direction);
-    }
-
-    @Override
-    public View focusSearch(View focused, int direction) {
-        switch (direction) {
-            case ACCESSIBILITY_FOCUS_FORWARD: {
-                // If we are the focused view try giving it to the first child.
-                if (focused == this) {
-                    final int childCount = getChildCount();
-                    for (int i = 0; i < childCount; i++) {
-                        View child = getChildAt(i);
-                        if (child.getVisibility() == View.VISIBLE) {
-                            return child;
-                        }
-                    }
-                    return super.focusSearch(this, direction);
-                }
-                // Find the item that has the focused view.
-                final int currentPosition = getPositionForView(focused);
-                if (currentPosition < 0 || currentPosition >= getCount()) {
-                    return super.focusSearch(this, direction);
-                }
-                // Try to advance focus in the current item.
-                View currentItem = getChildAt(currentPosition - getFirstVisiblePosition());
-                if (currentItem.getVisibility() == View.VISIBLE) {
-                    if (currentItem instanceof ViewGroup) {
-                        ViewGroup currentItemGroup = (ViewGroup) currentItem;
-                        View nextFocus = FocusFinder.getInstance().findNextFocus(currentItemGroup,
-                                    focused, direction);
-                        if (nextFocus != null && nextFocus != currentItemGroup
-                                && nextFocus != focused) {
-                            return nextFocus;
-                        }
-                    }
-                }
-                // Try to move focus to the next item.
-                final int nextPosition = currentPosition - getFirstVisiblePosition() + 1;
-                for (int i = nextPosition; i < getChildCount(); i++) {
-                    View child = getChildAt(i);
-                    if (child.getVisibility() == View.VISIBLE) {
-                        return child;
-                    }
-                }
-                // No next item start searching from the list.
-                return super.focusSearch(this, direction);
-            }
-            case ACCESSIBILITY_FOCUS_BACKWARD: {
-                // If we are the focused search from the view that is
-                // as closer to the bottom as possible.
-                if (focused == this) {
-                    final int childCount = getChildCount();
-                    for (int i = childCount - 1; i >= 0; i--) {
-                        View child = getChildAt(i);
-                        if (child.getVisibility() == View.VISIBLE) {
-                            return super.focusSearch(child, direction);
-                        }
-                    }
-                    return super.focusSearch(this, direction);
-                }
-                // Find the item that has the focused view.
-                final int currentPosition = getPositionForView(focused);
-                if (currentPosition < 0 || currentPosition >= getCount()) {
-                    return super.focusSearch(this, direction);
-                }
-
-                View currentItem = getChildAt(currentPosition - getFirstVisiblePosition());
-
-                // If a list item is the focused view we try to find a view
-                // in the previous item since in reverse the item contents
-                // get accessibility focus before the item itself.
-                if (currentItem == focused) {
-                    currentItem = null;
-                    focused = null;
-                    // This list gets accessibility focus after the last item.
-                    final int previousPosition = currentPosition - getFirstVisiblePosition() - 1;
-                    for (int i = previousPosition; i >= 0; i--) {
-                        View child = getChildAt(i);
-                        if (child.getVisibility() == View.VISIBLE) {
-                            currentItem = child;
-                            break;
-                        }
-                    }
-                    if (currentItem == null) {
-                        return this;
-                    }
-                }
-
-                if (currentItem.getVisibility() == View.VISIBLE) {
-                    // Search into the item.
-                    if (currentItem instanceof ViewGroup) {
-                        ViewGroup currentItemGroup = (ViewGroup) currentItem;
-                        View nextFocus = FocusFinder.getInstance().findNextFocus(currentItemGroup,
-                                    focused, direction);
-                        if (nextFocus != null && nextFocus != currentItemGroup
-                                && nextFocus != focused) {
-                            return nextFocus;
-                        }
-                    }
-
-                    // If not item content wants focus we give it to the item.
-                    return currentItem;
-                }
-
-                return super.focusSearch(this, direction);
-            }
-        }
-        return super.focusSearch(focused, direction);
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public View findViewToTakeAccessibilityFocusFromHover(View child, View descendant) {
-        final int position = getPositionForView(child);
-        if (position != INVALID_POSITION) {
-            return getChildAt(position - mFirstPosition);
-        }
-        return super.findViewToTakeAccessibilityFocusFromHover(child, descendant);
-    }
-
-    @Override
     public void sendAccessibilityEvent(int eventType) {
         // Since this class calls onScrollChanged even if the mFirstPosition and the
         // child count have not changed we will avoid sending duplicate accessibility
@@ -1751,6 +1621,21 @@
 
         SavedState ss = new SavedState(superState);
 
+        if (mPendingSync != null) {
+            // Just keep what we last restored.
+            ss.selectedId = mPendingSync.selectedId;
+            ss.firstId = mPendingSync.firstId;
+            ss.viewTop = mPendingSync.viewTop;
+            ss.position = mPendingSync.position;
+            ss.height = mPendingSync.height;
+            ss.filter = mPendingSync.filter;
+            ss.inActionMode = mPendingSync.inActionMode;
+            ss.checkedItemCount = mPendingSync.checkedItemCount;
+            ss.checkState = mPendingSync.checkState;
+            ss.checkIdState = mPendingSync.checkIdState;
+            return ss;
+        }
+
         boolean haveChildren = getChildCount() > 0 && mItemCount > 0;
         long selectedId = getSelectedItemId();
         ss.selectedId = selectedId;
@@ -1831,6 +1716,7 @@
 
         if (ss.selectedId >= 0) {
             mNeedSync = true;
+            mPendingSync = ss;
             mSyncRowId = ss.selectedId;
             mSyncPosition = ss.position;
             mSpecificTop = ss.viewTop;
@@ -1841,6 +1727,7 @@
             setNextSelectedPositionInt(INVALID_POSITION);
             mSelectorPosition = INVALID_POSITION;
             mNeedSync = true;
+            mPendingSync = ss;
             mSyncRowId = ss.firstId;
             mSyncPosition = ss.position;
             mSpecificTop = ss.viewTop;
@@ -1942,6 +1829,7 @@
         mDataChanged = false;
         mPositionScrollAfterLayout = null;
         mNeedSync = false;
+        mPendingSync = null;
         mOldSelectedPosition = INVALID_POSITION;
         mOldSelectedRowId = INVALID_ROW_ID;
         setSelectedPositionInt(INVALID_POSITION);
@@ -2297,7 +2185,9 @@
             if (mAccessibilityDelegate == null) {
                 mAccessibilityDelegate = new ListItemAccessibilityDelegate();
             }
-            child.setAccessibilityDelegate(mAccessibilityDelegate);
+            if (child.getAccessibilityDelegate() == null) {
+                child.setAccessibilityDelegate(mAccessibilityDelegate);
+            }
         }
 
         return child;
@@ -5346,6 +5236,7 @@
             if (mNeedSync) {
                 // Update this first, since setNextSelectedPositionInt inspects it
                 mNeedSync = false;
+                mPendingSync = null;
 
                 if (mTranscriptMode == TRANSCRIPT_MODE_ALWAYS_SCROLL) {
                     mLayoutMode = LAYOUT_FORCE_BOTTOM;
@@ -5461,6 +5352,7 @@
         mNextSelectedPosition = INVALID_POSITION;
         mNextSelectedRowId = INVALID_ROW_ID;
         mNeedSync = false;
+        mPendingSync = null;
         mSelectorPosition = INVALID_POSITION;
         checkSelectionChanged();
     }
@@ -5984,6 +5876,21 @@
     }
 
     /**
+     * Sets up the onClickHandler to be used by the RemoteViewsAdapter when inflating RemoteViews
+     * 
+     * @param handler The OnClickHandler to use when inflating RemoteViews.
+     * 
+     * @hide
+     */
+    public void setRemoteViewsOnClickHandler(OnClickHandler handler) {
+        // Ensure that we don't already have a RemoteViewsAdapter that is bound to an existing
+        // service handling the specified intent.
+        if (mRemoteAdapter != null) {
+            mRemoteAdapter.setRemoteViewsOnClickHandler(handler);
+        }
+    }
+
+    /**
      * This defers a notifyDataSetChanged on the pending RemoteViewsAdapter if it has not
      * connected yet.
      */
@@ -6090,6 +5997,10 @@
             mWrapped = wrapped;
         }
 
+        public boolean hasWrappedCallback() {
+            return mWrapped != null;
+        }
+
         public boolean onCreateActionMode(ActionMode mode, Menu menu) {
             if (mWrapped.onCreateActionMode(mode, menu)) {
                 // Initialize checked graphic state?
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index e217e4f..3b5e75b 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -107,6 +107,9 @@
         }
         if (thumb != null) {
             thumb.setCallback(this);
+            if (canResolveLayoutDirection()) {
+                thumb.setLayoutDirection(getLayoutDirection());
+            }
 
             // Assuming the thumb drawable is symmetric, set the thumb offset
             // such that the thumb will hang halfway off either edge of the
@@ -238,6 +241,7 @@
     
     @Override
     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
         updateThumbPos(w, h);
     }
 
@@ -301,9 +305,22 @@
         }
         
         // Canvas will be translated, so 0,0 is where we start drawing
-        thumb.setBounds(thumbPos, topBound, thumbPos + thumbWidth, bottomBound);
+        final int left = isLayoutRtl() ? available - thumbPos : thumbPos;
+        thumb.setBounds(left, topBound, left + thumbWidth, bottomBound);
     }
-    
+
+    /**
+     * @hide
+     */
+    @Override
+    public void onResolveDrawables(int layoutDirection) {
+        super.onResolveDrawables(layoutDirection);
+
+        if (mThumb != null) {
+            mThumb.setLayoutDirection(layoutDirection);
+        }
+    }
+
     @Override
     protected synchronized void onDraw(Canvas canvas) {
         super.onDraw(canvas);
@@ -409,15 +426,25 @@
         int x = (int)event.getX();
         float scale;
         float progress = 0;
-        if (x < mPaddingLeft) {
-            scale = 0.0f;
-        } else if (x > width - mPaddingRight) {
-            scale = 1.0f;
+        if (isLayoutRtl()) {
+            if (x > width - mPaddingRight) {
+                scale = 0.0f;
+            } else if (x < mPaddingLeft) {
+                scale = 1.0f;
+            } else {
+                scale = (float)(available - x + mPaddingLeft) / (float)available;
+                progress = mTouchProgressOffset;
+            }
         } else {
-            scale = (float)(x - mPaddingLeft) / (float)available;
-            progress = mTouchProgressOffset;
+            if (x < mPaddingLeft) {
+                scale = 0.0f;
+            } else if (x > width - mPaddingRight) {
+                scale = 1.0f;
+            } else {
+                scale = (float)(x - mPaddingLeft) / (float)available;
+                progress = mTouchProgressOffset;
+            }
         }
-        
         final int max = getMax();
         progress += scale * max;
         
@@ -529,4 +556,23 @@
         }
         return false;
     }
+
+    @Override
+    public void onRtlPropertiesChanged(int layoutDirection) {
+        super.onRtlPropertiesChanged(layoutDirection);
+
+        int max = getMax();
+        float scale = max > 0 ? (float) getProgress() / (float) max : 0;
+
+        Drawable thumb = mThumb;
+        if (thumb != null) {
+            setThumbPos(getWidth(), thumb, scale, Integer.MIN_VALUE);
+            /*
+             * Since we draw translated, the drawable's bounds that it signals
+             * for invalidation won't be the actual bounds we want invalidated,
+             * so just invalidate this whole view.
+             */
+            invalidate();
+        }
+    }
 }
diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java
index fe6c4f5..736566e4 100644
--- a/core/java/android/widget/ActivityChooserModel.java
+++ b/core/java/android/widget/ActivityChooserModel.java
@@ -21,7 +21,6 @@
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
 import android.database.DataSetObservable;
-import android.database.DataSetObserver;
 import android.os.AsyncTask;
 import android.text.TextUtils;
 import android.util.Log;
@@ -458,13 +457,18 @@
      * </p>
      *
      * @return An {@link Intent} for launching the activity or null if the
-     *         policy has consumed the intent.
+     *         policy has consumed the intent or there is not current intent
+     *         set via {@link #setIntent(Intent)}.
      *
      * @see HistoricalRecord
      * @see OnChooseActivityListener
      */
     public Intent chooseActivity(int index) {
         synchronized (mInstanceLock) {
+            if (mIntent == null) {
+                return null;
+            }
+
             ensureConsistentState();
 
             ActivityResolveInfo chosenActivity = mActivities.get(index);
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index 4eb169b..2037c3a 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -497,7 +497,7 @@
         // Default activity button.
         final int activityCount = mAdapter.getActivityCount();
         final int historySize = mAdapter.getHistorySize();
-        if (activityCount > 0 && historySize > 0) {
+        if (activityCount==1 || activityCount > 1 && historySize > 0) {
             mDefaultActivityButton.setVisibility(VISIBLE);
             ResolveInfo activity = mAdapter.getDefaultActivity();
             PackageManager packageManager = mContext.getPackageManager();
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index 2266cea..90e949a 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -31,6 +31,7 @@
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.RemoteViews.OnClickHandler;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -992,6 +993,21 @@
         }
     }
 
+    /**
+     * Sets up the onClickHandler to be used by the RemoteViewsAdapter when inflating RemoteViews
+     * 
+     * @param handler The OnClickHandler to use when inflating RemoteViews.
+     * 
+     * @hide
+     */
+    public void setRemoteViewsOnClickHandler(OnClickHandler handler) {
+        // Ensure that we don't already have a RemoteViewsAdapter that is bound to an existing
+        // service handling the specified intent.
+        if (mRemoteViewsAdapter != null) {
+            mRemoteViewsAdapter.setRemoteViewsOnClickHandler(handler);
+        }
+    }
+
     @Override
     public void setSelection(int position) {
         setDisplayedChild(position);
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index 988760d..06dadb0 100755
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -18,17 +18,23 @@
 
 import com.android.internal.R;
 
+import android.app.AlertDialog;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PackageParser;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
 import android.graphics.drawable.Drawable;
+import android.os.Parcel;
+import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
+import android.util.AttributeSet;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 
 import java.text.Collator;
 import java.util.ArrayList;
@@ -36,7 +42,6 @@
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -52,102 +57,270 @@
  * 
  * {@hide}
  */
-public class AppSecurityPermissions  implements View.OnClickListener {
+public class AppSecurityPermissions {
 
-    private enum State {
-        NO_PERMS,
-        DANGEROUS_ONLY,
-        NORMAL_ONLY,
-        BOTH
-    }
+    public static final int WHICH_PERSONAL = 1<<0;
+    public static final int WHICH_DEVICE = 1<<1;
+    public static final int WHICH_NEW = 1<<2;
+    public static final int WHICH_ALL = 0xffff;
 
     private final static String TAG = "AppSecurityPermissions";
-    private boolean localLOGV = false;
+    private final static boolean localLOGV = false;
     private Context mContext;
     private LayoutInflater mInflater;
     private PackageManager mPm;
-    private LinearLayout mPermsView;
-    private Map<String, String> mDangerousMap;
-    private Map<String, String> mNormalMap;
-    private List<PermissionInfo> mPermsList;
-    private String mDefaultGrpLabel;
-    private String mDefaultGrpName="DefaultGrp";
-    private String mPermFormat;
+    private PackageInfo mInstalledPackageInfo;
+    private final Map<String, MyPermissionGroupInfo> mPermGroups
+            = new HashMap<String, MyPermissionGroupInfo>();
+    private final List<MyPermissionGroupInfo> mPermGroupsList
+            = new ArrayList<MyPermissionGroupInfo>();
+    private final PermissionGroupInfoComparator mPermGroupComparator;
+    private final PermissionInfoComparator mPermComparator;
+    private List<MyPermissionInfo> mPermsList;
+    private CharSequence mNewPermPrefix;
     private Drawable mNormalIcon;
     private Drawable mDangerousIcon;
-    private boolean mExpanded;
-    private Drawable mShowMaxIcon;
-    private Drawable mShowMinIcon;
-    private View mShowMore;
-    private TextView mShowMoreText;
-    private ImageView mShowMoreIcon;
-    private State mCurrentState;
-    private LinearLayout mNonDangerousList;
-    private LinearLayout mDangerousList;
-    private HashMap<String, CharSequence> mGroupLabelCache;
-    private View mNoPermsView;
-    
+
+    static class MyPermissionGroupInfo extends PermissionGroupInfo {
+        CharSequence mLabel;
+
+        final ArrayList<MyPermissionInfo> mNewPermissions = new ArrayList<MyPermissionInfo>();
+        final ArrayList<MyPermissionInfo> mPersonalPermissions = new ArrayList<MyPermissionInfo>();
+        final ArrayList<MyPermissionInfo> mDevicePermissions = new ArrayList<MyPermissionInfo>();
+        final ArrayList<MyPermissionInfo> mAllPermissions = new ArrayList<MyPermissionInfo>();
+
+        MyPermissionGroupInfo(PermissionInfo perm) {
+            name = perm.packageName;
+            packageName = perm.packageName;
+        }
+
+        MyPermissionGroupInfo(PermissionGroupInfo info) {
+            super(info);
+        }
+
+        public Drawable loadGroupIcon(PackageManager pm) {
+            if (icon != 0) {
+                return loadIcon(pm);
+            } else {
+                ApplicationInfo appInfo;
+                try {
+                    appInfo = pm.getApplicationInfo(packageName, 0);
+                    return appInfo.loadIcon(pm);
+                } catch (NameNotFoundException e) {
+                }
+            }
+            return null;
+        }
+    }
+
+    static class MyPermissionInfo extends PermissionInfo {
+        CharSequence mLabel;
+
+        /**
+         * PackageInfo.requestedPermissionsFlags for the new package being installed.
+         */
+        int mNewReqFlags;
+
+        /**
+         * PackageInfo.requestedPermissionsFlags for the currently installed
+         * package, if it is installed.
+         */
+        int mExistingReqFlags;
+
+        /**
+         * True if this should be considered a new permission.
+         */
+        boolean mNew;
+
+        MyPermissionInfo() {
+        }
+
+        MyPermissionInfo(PermissionInfo info) {
+            super(info);
+        }
+
+        MyPermissionInfo(MyPermissionInfo info) {
+            super(info);
+            mNewReqFlags = info.mNewReqFlags;
+            mExistingReqFlags = info.mExistingReqFlags;
+            mNew = info.mNew;
+        }
+    }
+
+    public static class PermissionItemView extends LinearLayout implements View.OnClickListener {
+        MyPermissionGroupInfo mGroup;
+        MyPermissionInfo mPerm;
+        AlertDialog mDialog;
+
+        public PermissionItemView(Context context, AttributeSet attrs) {
+            super(context, attrs);
+            setClickable(true);
+        }
+
+        public void setPermission(MyPermissionGroupInfo grp, MyPermissionInfo perm,
+                boolean first, CharSequence newPermPrefix) {
+            mGroup = grp;
+            mPerm = perm;
+
+            ImageView permGrpIcon = (ImageView) findViewById(R.id.perm_icon);
+            TextView permNameView = (TextView) findViewById(R.id.perm_name);
+
+            PackageManager pm = getContext().getPackageManager();
+            Drawable icon = null;
+            if (first) {
+                icon = grp.loadGroupIcon(pm);
+            }
+            CharSequence label = perm.mLabel;
+            if (perm.mNew && newPermPrefix != null) {
+                // If this is a new permission, format it appropriately.
+                SpannableStringBuilder builder = new SpannableStringBuilder();
+                Parcel parcel = Parcel.obtain();
+                TextUtils.writeToParcel(newPermPrefix, parcel, 0);
+                parcel.setDataPosition(0);
+                CharSequence newStr = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
+                parcel.recycle();
+                builder.append(newStr);
+                builder.append(label);
+                label = builder;
+            }
+
+            permGrpIcon.setImageDrawable(icon);
+            permNameView.setText(label);
+            setOnClickListener(this);
+            if (localLOGV) Log.i(TAG, "Made perm item " + perm.name
+                    + ": " + label + " in group " + grp.name);
+        }
+
+        @Override
+        public void onClick(View v) {
+            if (mGroup != null && mPerm != null) {
+                if (mDialog != null) {
+                    mDialog.dismiss();
+                }
+                PackageManager pm = getContext().getPackageManager();
+                AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+                builder.setTitle(mGroup.mLabel);
+                if (mPerm.descriptionRes != 0) {
+                    builder.setMessage(mPerm.loadDescription(pm));
+                } else {
+                    CharSequence appName;
+                    try {
+                        ApplicationInfo app = pm.getApplicationInfo(mPerm.packageName, 0);
+                        appName = app.loadLabel(pm);
+                    } catch (NameNotFoundException e) {
+                        appName = mPerm.packageName;
+                    }
+                    StringBuilder sbuilder = new StringBuilder(128);
+                    sbuilder.append(getContext().getString(
+                            R.string.perms_description_app, appName));
+                    sbuilder.append("\n\n");
+                    sbuilder.append(mPerm.name);
+                    builder.setMessage(sbuilder.toString());
+                }
+                builder.setCancelable(true);
+                builder.setIcon(mGroup.loadGroupIcon(pm));
+                mDialog = builder.show();
+                mDialog.setCanceledOnTouchOutside(true);
+            }
+        }
+
+        @Override
+        protected void onDetachedFromWindow() {
+            super.onDetachedFromWindow();
+            if (mDialog != null) {
+                mDialog.dismiss();
+            }
+        }
+    }
+
     public AppSecurityPermissions(Context context, List<PermissionInfo> permList) {
         mContext = context;
         mPm = mContext.getPackageManager();
-        mPermsList = permList;
+        loadResources();
+        mPermComparator = new PermissionInfoComparator();
+        mPermGroupComparator = new PermissionGroupInfoComparator();
+        for (PermissionInfo pi : permList) {
+            mPermsList.add(new MyPermissionInfo(pi));
+        }
+        setPermissions(mPermsList);
     }
     
     public AppSecurityPermissions(Context context, String packageName) {
         mContext = context;
         mPm = mContext.getPackageManager();
-        mPermsList = new ArrayList<PermissionInfo>();
-        Set<PermissionInfo> permSet = new HashSet<PermissionInfo>();
+        loadResources();
+        mPermComparator = new PermissionInfoComparator();
+        mPermGroupComparator = new PermissionGroupInfoComparator();
+        mPermsList = new ArrayList<MyPermissionInfo>();
+        Set<MyPermissionInfo> permSet = new HashSet<MyPermissionInfo>();
         PackageInfo pkgInfo;
         try {
             pkgInfo = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
         } catch (NameNotFoundException e) {
-            Log.w(TAG, "Could'nt retrieve permissions for package:"+packageName);
+            Log.w(TAG, "Couldn't retrieve permissions for package:"+packageName);
             return;
         }
         // Extract all user permissions
         if((pkgInfo.applicationInfo != null) && (pkgInfo.applicationInfo.uid != -1)) {
             getAllUsedPermissions(pkgInfo.applicationInfo.uid, permSet);
         }
-        for(PermissionInfo tmpInfo : permSet) {
+        for(MyPermissionInfo tmpInfo : permSet) {
             mPermsList.add(tmpInfo);
         }
+        setPermissions(mPermsList);
     }
-    
-    public AppSecurityPermissions(Context context, PackageParser.Package pkg) {
+
+    public AppSecurityPermissions(Context context, PackageInfo info) {
         mContext = context;
         mPm = mContext.getPackageManager();
-        mPermsList = new ArrayList<PermissionInfo>();
-        Set<PermissionInfo> permSet = new HashSet<PermissionInfo>();
-        if(pkg == null) {
+        loadResources();
+        mPermComparator = new PermissionInfoComparator();
+        mPermGroupComparator = new PermissionGroupInfoComparator();
+        mPermsList = new ArrayList<MyPermissionInfo>();
+        Set<MyPermissionInfo> permSet = new HashSet<MyPermissionInfo>();
+        if(info == null) {
             return;
         }
+
+        // Convert to a PackageInfo
+        PackageInfo installedPkgInfo = null;
         // Get requested permissions
-        if (pkg.requestedPermissions != null) {
-            ArrayList<String> strList = pkg.requestedPermissions;
-            int size = strList.size();
-            if (size > 0) {
-                extractPerms(strList.toArray(new String[size]), permSet);
+        if (info.requestedPermissions != null) {
+            try {
+                installedPkgInfo = mPm.getPackageInfo(info.packageName,
+                        PackageManager.GET_PERMISSIONS);
+            } catch (NameNotFoundException e) {
             }
+            extractPerms(info, permSet, installedPkgInfo);
         }
         // Get permissions related to  shared user if any
-        if(pkg.mSharedUserId != null) {
+        if (info.sharedUserId != null) {
             int sharedUid;
             try {
-                sharedUid = mPm.getUidForSharedUser(pkg.mSharedUserId);
+                sharedUid = mPm.getUidForSharedUser(info.sharedUserId);
                 getAllUsedPermissions(sharedUid, permSet);
             } catch (NameNotFoundException e) {
-                Log.w(TAG, "Could'nt retrieve shared user id for:"+pkg.packageName);
+                Log.w(TAG, "Could'nt retrieve shared user id for:"+info.packageName);
             }
         }
         // Retrieve list of permissions
-        for(PermissionInfo tmpInfo : permSet) {
+        for (MyPermissionInfo tmpInfo : permSet) {
             mPermsList.add(tmpInfo);
         }
+        setPermissions(mPermsList);
     }
-    
+
+    private void loadResources() {
+        // Pick up from framework resources instead.
+        mNewPermPrefix = mContext.getText(R.string.perms_new_perm_prefix);
+        mNormalIcon = mContext.getResources().getDrawable(R.drawable.ic_text_dot);
+        mDangerousIcon = mContext.getResources().getDrawable(R.drawable.ic_bullet_key_permission);
+    }
+
     /**
-     * Utility to retrieve a view displaying a single permission.
+     * Utility to retrieve a view displaying a single permission.  This provides
+     * the old UI layout for permissions; it is only here for the device admin
+     * settings to continue to use.
      */
     public static View getPermissionItemView(Context context,
             CharSequence grpName, CharSequence description, boolean dangerous) {
@@ -155,11 +328,15 @@
                 Context.LAYOUT_INFLATER_SERVICE);
         Drawable icon = context.getResources().getDrawable(dangerous
                 ? R.drawable.ic_bullet_key_permission : R.drawable.ic_text_dot);
-        return getPermissionItemView(context, inflater, grpName,
+        return getPermissionItemViewOld(context, inflater, grpName,
                 description, dangerous, icon);
     }
     
-    private void getAllUsedPermissions(int sharedUid, Set<PermissionInfo> permSet) {
+    public PackageInfo getInstalledPackageInfo() {
+        return mInstalledPackageInfo;
+    }
+
+    private void getAllUsedPermissions(int sharedUid, Set<MyPermissionInfo> permSet) {
         String sharedPkgList[] = mPm.getPackagesForUid(sharedUid);
         if(sharedPkgList == null || (sharedPkgList.length == 0)) {
             return;
@@ -170,29 +347,95 @@
     }
     
     private void getPermissionsForPackage(String packageName, 
-            Set<PermissionInfo> permSet) {
+            Set<MyPermissionInfo> permSet) {
         PackageInfo pkgInfo;
         try {
             pkgInfo = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
         } catch (NameNotFoundException e) {
-            Log.w(TAG, "Could'nt retrieve permissions for package:"+packageName);
+            Log.w(TAG, "Couldn't retrieve permissions for package:"+packageName);
             return;
         }
         if ((pkgInfo != null) && (pkgInfo.requestedPermissions != null)) {
-            extractPerms(pkgInfo.requestedPermissions, permSet);
+            extractPerms(pkgInfo, permSet, pkgInfo);
         }
     }
-    
-    private void extractPerms(String strList[], Set<PermissionInfo> permSet) {
-        if((strList == null) || (strList.length == 0)) {
+
+    private void extractPerms(PackageInfo info, Set<MyPermissionInfo> permSet,
+            PackageInfo installedPkgInfo) {
+        String[] strList = info.requestedPermissions;
+        int[] flagsList = info.requestedPermissionsFlags;
+        if ((strList == null) || (strList.length == 0)) {
             return;
         }
-        for(String permName:strList) {
+        mInstalledPackageInfo = installedPkgInfo;
+        for (int i=0; i<strList.length; i++) {
+            String permName = strList[i];
+            // If we are only looking at an existing app, then we only
+            // care about permissions that have actually been granted to it.
+            if (installedPkgInfo != null && info == installedPkgInfo) {
+                if ((flagsList[i]&PackageInfo.REQUESTED_PERMISSION_GRANTED) == 0) {
+                    continue;
+                }
+            }
             try {
                 PermissionInfo tmpPermInfo = mPm.getPermissionInfo(permName, 0);
-                if(tmpPermInfo != null) {
-                    permSet.add(tmpPermInfo);
+                if (tmpPermInfo == null) {
+                    continue;
                 }
+                int existingIndex = -1;
+                if (installedPkgInfo != null
+                        && installedPkgInfo.requestedPermissions != null) {
+                    for (int j=0; j<installedPkgInfo.requestedPermissions.length; j++) {
+                        if (permName.equals(installedPkgInfo.requestedPermissions[j])) {
+                            existingIndex = j;
+                            break;
+                        }
+                    }
+                }
+                final int existingFlags = existingIndex >= 0 ?
+                        installedPkgInfo.requestedPermissionsFlags[existingIndex] : 0;
+                if (!isDisplayablePermission(tmpPermInfo, flagsList[i], existingFlags)) {
+                    // This is not a permission that is interesting for the user
+                    // to see, so skip it.
+                    continue;
+                }
+                final String origGroupName = tmpPermInfo.group;
+                String groupName = origGroupName;
+                if (groupName == null) {
+                    groupName = tmpPermInfo.packageName;
+                    tmpPermInfo.group = groupName;
+                }
+                MyPermissionGroupInfo group = mPermGroups.get(groupName);
+                if (group == null) {
+                    PermissionGroupInfo grp = null;
+                    if (origGroupName != null) {
+                        grp = mPm.getPermissionGroupInfo(origGroupName, 0);
+                    }
+                    if (grp != null) {
+                        group = new MyPermissionGroupInfo(grp);
+                    } else {
+                        // We could be here either because the permission
+                        // didn't originally specify a group or the group it
+                        // gave couldn't be found.  In either case, we consider
+                        // its group to be the permission's package name.
+                        tmpPermInfo.group = tmpPermInfo.packageName;
+                        group = mPermGroups.get(tmpPermInfo.group);
+                        if (group == null) {
+                            group = new MyPermissionGroupInfo(tmpPermInfo);
+                        }
+                        group = new MyPermissionGroupInfo(tmpPermInfo);
+                    }
+                    mPermGroups.put(tmpPermInfo.group, group);
+                }
+                final boolean newPerm = installedPkgInfo != null
+                        && (existingFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) == 0;
+                MyPermissionInfo myPerm = new MyPermissionInfo(tmpPermInfo);
+                myPerm.mNewReqFlags = flagsList[i];
+                myPerm.mExistingReqFlags = existingFlags;
+                // This is a new permission if the app is already installed and
+                // doesn't currently hold this permission.
+                myPerm.mNew = newPerm;
+                permSet.add(myPerm);
             } catch (NameNotFoundException e) {
                 Log.i(TAG, "Ignoring unknown permission:"+permName);
             }
@@ -200,131 +443,101 @@
     }
     
     public int getPermissionCount() {
-        return mPermsList.size();
+        return getPermissionCount(WHICH_ALL);
+    }
+
+    private List<MyPermissionInfo> getPermissionList(MyPermissionGroupInfo grp, int which) {
+        if (which == WHICH_NEW) {
+            return grp.mNewPermissions;
+        } else if (which == WHICH_PERSONAL) {
+            return grp.mPersonalPermissions;
+        } else if (which == WHICH_DEVICE) {
+            return grp.mDevicePermissions;
+        } else {
+            return grp.mAllPermissions;
+        }
+    }
+
+    public int getPermissionCount(int which) {
+        int N = 0;
+        for (int i=0; i<mPermGroupsList.size(); i++) {
+            N += getPermissionList(mPermGroupsList.get(i), which).size();
+        }
+        return N;
     }
 
     public View getPermissionsView() {
-        
+        return getPermissionsView(WHICH_ALL);
+    }
+
+    public View getPermissionsView(int which) {
         mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        mPermsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
-        mShowMore = mPermsView.findViewById(R.id.show_more);
-        mShowMoreIcon = (ImageView) mShowMore.findViewById(R.id.show_more_icon);
-        mShowMoreText = (TextView) mShowMore.findViewById(R.id.show_more_text);
-        mDangerousList = (LinearLayout) mPermsView.findViewById(R.id.dangerous_perms_list);
-        mNonDangerousList = (LinearLayout) mPermsView.findViewById(R.id.non_dangerous_perms_list);
-        mNoPermsView = mPermsView.findViewById(R.id.no_permissions);
 
-        // Set up the LinearLayout that acts like a list item.
-        mShowMore.setClickable(true);
-        mShowMore.setOnClickListener(this);
-        mShowMore.setFocusable(true);
+        LinearLayout permsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
+        LinearLayout displayList = (LinearLayout) permsView.findViewById(R.id.perms_list);
+        View noPermsView = permsView.findViewById(R.id.no_permissions);
 
-        // Pick up from framework resources instead.
-        mDefaultGrpLabel = mContext.getString(R.string.default_permission_group);
-        mPermFormat = mContext.getString(R.string.permissions_format);
-        mNormalIcon = mContext.getResources().getDrawable(R.drawable.ic_text_dot);
-        mDangerousIcon = mContext.getResources().getDrawable(R.drawable.ic_bullet_key_permission);
-        mShowMaxIcon = mContext.getResources().getDrawable(R.drawable.expander_close_holo_dark);
-        mShowMinIcon = mContext.getResources().getDrawable(R.drawable.expander_open_holo_dark);
-        
-        // Set permissions view
-        setPermissions(mPermsList);
-        return mPermsView;
-    }
+        displayPermissions(mPermGroupsList, displayList, which);
+        if (displayList.getChildCount() <= 0) {
+            noPermsView.setVisibility(View.VISIBLE);
+        }
 
-    /**
-     * Canonicalizes the group description before it is displayed to the user.
-     *
-     * TODO check for internationalization issues remove trailing '.' in str1
-     */
-    private String canonicalizeGroupDesc(String groupDesc) {
-        if ((groupDesc == null) || (groupDesc.length() == 0)) {
-            return null;
-        }
-        // Both str1 and str2 are non-null and are non-zero in size.
-        int len = groupDesc.length();
-        if(groupDesc.charAt(len-1) == '.') {
-            groupDesc = groupDesc.substring(0, len-1);
-        }
-        return groupDesc;
-    }
-
-    /**
-     * Utility method that concatenates two strings defined by mPermFormat.
-     * a null value is returned if both str1 and str2 are null, if one of the strings
-     * is null the other non null value is returned without formatting
-     * this is to placate initial error checks
-     */
-    private String formatPermissions(String groupDesc, CharSequence permDesc) {
-        if(groupDesc == null) {
-            if(permDesc == null) {
-                return null;
-            }
-            return permDesc.toString();
-        }
-        groupDesc = canonicalizeGroupDesc(groupDesc);
-        if(permDesc == null) {
-            return groupDesc;
-        }
-        // groupDesc and permDesc are non null
-        return String.format(mPermFormat, groupDesc, permDesc.toString());
-    }
-
-    private CharSequence getGroupLabel(String grpName) {
-        if (grpName == null) {
-            //return default label
-            return mDefaultGrpLabel;
-        }
-        CharSequence cachedLabel = mGroupLabelCache.get(grpName);
-        if (cachedLabel != null) {
-            return cachedLabel;
-        }
-        PermissionGroupInfo pgi;
-        try {
-            pgi = mPm.getPermissionGroupInfo(grpName, 0);
-        } catch (NameNotFoundException e) {
-            Log.i(TAG, "Invalid group name:" + grpName);
-            return null;
-        }
-        CharSequence label = pgi.loadLabel(mPm).toString();
-        mGroupLabelCache.put(grpName, label);
-        return label;
+        return permsView;
     }
 
     /**
      * Utility method that displays permissions from a map containing group name and
      * list of permission descriptions.
      */
-    private void displayPermissions(boolean dangerous) {
-        Map<String, String> permInfoMap = dangerous ? mDangerousMap : mNormalMap;
-        LinearLayout permListView = dangerous ? mDangerousList : mNonDangerousList;
+    private void displayPermissions(List<MyPermissionGroupInfo> groups,
+            LinearLayout permListView, int which) {
         permListView.removeAllViews();
 
-        Set<String> permInfoStrSet = permInfoMap.keySet();
-        for (String loopPermGrpInfoStr : permInfoStrSet) {
-            CharSequence grpLabel = getGroupLabel(loopPermGrpInfoStr);
-            //guaranteed that grpLabel wont be null since permissions without groups
-            //will belong to the default group
-            if(localLOGV) Log.i(TAG, "Adding view group:" + grpLabel + ", desc:"
-                    + permInfoMap.get(loopPermGrpInfoStr));
-            permListView.addView(getPermissionItemView(grpLabel,
-                    permInfoMap.get(loopPermGrpInfoStr), dangerous));
+        int spacing = (int)(8*mContext.getResources().getDisplayMetrics().density);
+
+        for (int i=0; i<groups.size(); i++) {
+            MyPermissionGroupInfo grp = groups.get(i);
+            final List<MyPermissionInfo> perms = getPermissionList(grp, which);
+            for (int j=0; j<perms.size(); j++) {
+                MyPermissionInfo perm = perms.get(j);
+                View view = getPermissionItemView(grp, perm, j == 0,
+                        which != WHICH_NEW ? mNewPermPrefix : null);
+                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+                        ViewGroup.LayoutParams.MATCH_PARENT,
+                        ViewGroup.LayoutParams.WRAP_CONTENT);
+                if (j == 0) {
+                    lp.topMargin = spacing;
+                }
+                if (j == grp.mAllPermissions.size()-1) {
+                    lp.bottomMargin = spacing;
+                }
+                if (permListView.getChildCount() == 0) {
+                    lp.topMargin *= 2;
+                }
+                permListView.addView(view, lp);
+            }
         }
     }
 
-    private void displayNoPermissions() {
-        mNoPermsView.setVisibility(View.VISIBLE);
+    private PermissionItemView getPermissionItemView(MyPermissionGroupInfo grp,
+            MyPermissionInfo perm, boolean first, CharSequence newPermPrefix) {
+        return getPermissionItemView(mContext, mInflater, grp, perm, first, newPermPrefix);
     }
 
-    private View getPermissionItemView(CharSequence grpName, CharSequence permList,
-            boolean dangerous) {
-        return getPermissionItemView(mContext, mInflater, grpName, permList,
-                dangerous, dangerous ? mDangerousIcon : mNormalIcon);
+    private static PermissionItemView getPermissionItemView(Context context, LayoutInflater inflater,
+            MyPermissionGroupInfo grp, MyPermissionInfo perm, boolean first,
+            CharSequence newPermPrefix) {
+        PermissionItemView permView = (PermissionItemView)inflater.inflate(
+                (perm.flags & PermissionInfo.FLAG_COSTS_MONEY) != 0
+                        ? R.layout.app_permission_item_money : R.layout.app_permission_item,
+                null);
+        permView.setPermission(grp, perm, first, newPermPrefix);
+        return permView;
     }
 
-    private static View getPermissionItemView(Context context, LayoutInflater inflater,
+    private static View getPermissionItemViewOld(Context context, LayoutInflater inflater,
             CharSequence grpName, CharSequence permList, boolean dangerous, Drawable icon) {
-        View permView = inflater.inflate(R.layout.app_permission_item, null);
+        View permView = inflater.inflate(R.layout.app_permission_item_old, null);
 
         TextView permGrpView = (TextView) permView.findViewById(R.id.permission_group);
         TextView permDescView = (TextView) permView.findViewById(R.id.permission_list);
@@ -341,159 +554,109 @@
         return permView;
     }
 
-    private void showPermissions() {
-
-        switch(mCurrentState) {
-        case NO_PERMS:
-            displayNoPermissions();
-            break;
-
-        case DANGEROUS_ONLY:
-            displayPermissions(true);
-            break;
-
-        case NORMAL_ONLY:
-            displayPermissions(false);
-            break;
-
-        case BOTH:
-            displayPermissions(true);
-            if (mExpanded) {
-                displayPermissions(false);
-                mShowMoreIcon.setImageDrawable(mShowMaxIcon);
-                mShowMoreText.setText(R.string.perms_hide);
-                mNonDangerousList.setVisibility(View.VISIBLE);
-            } else {
-                mShowMoreIcon.setImageDrawable(mShowMinIcon);
-                mShowMoreText.setText(R.string.perms_show_all);
-                mNonDangerousList.setVisibility(View.GONE);
-            }
-            mShowMore.setVisibility(View.VISIBLE);
-            break;
+    private boolean isDisplayablePermission(PermissionInfo pInfo, int newReqFlags,
+            int existingReqFlags) {
+        final int base = pInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
+        // Dangerous and normal permissions are always shown to the user.
+        if (base == PermissionInfo.PROTECTION_DANGEROUS ||
+                base == PermissionInfo.PROTECTION_NORMAL) {
+            return true;
         }
-    }
-    
-    private boolean isDisplayablePermission(PermissionInfo pInfo) {
-        if(pInfo.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS ||
-                pInfo.protectionLevel == PermissionInfo.PROTECTION_NORMAL) {
+        // Development permissions are only shown to the user if they are already
+        // granted to the app -- if we are installing an app and they are not
+        // already granted, they will not be granted as part of the install.
+        if ((existingReqFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0
+                && (pInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
+            if (localLOGV) Log.i(TAG, "Special perm " + pInfo.name
+                    + ": protlevel=0x" + Integer.toHexString(pInfo.protectionLevel));
             return true;
         }
         return false;
     }
     
-    /*
-     * Utility method that aggregates all permission descriptions categorized by group
-     * Say group1 has perm11, perm12, perm13, the group description will be
-     * perm11_Desc, perm12_Desc, perm13_Desc
-     */
-    private void aggregateGroupDescs(
-            Map<String, List<PermissionInfo> > map, Map<String, String> retMap) {
-        if(map == null) {
-            return;
-        }
-        if(retMap == null) {
-           return;
-        }
-        Set<String> grpNames = map.keySet();
-        Iterator<String> grpNamesIter = grpNames.iterator();
-        while(grpNamesIter.hasNext()) {
-            String grpDesc = null;
-            String grpNameKey = grpNamesIter.next();
-            List<PermissionInfo> grpPermsList = map.get(grpNameKey);
-            if(grpPermsList == null) {
-                continue;
-            }
-            for(PermissionInfo permInfo: grpPermsList) {
-                CharSequence permDesc = permInfo.loadLabel(mPm);
-                grpDesc = formatPermissions(grpDesc, permDesc);
-            }
-            // Insert grpDesc into map
-            if(grpDesc != null) {
-                if(localLOGV) Log.i(TAG, "Group:"+grpNameKey+" description:"+grpDesc.toString());
-                retMap.put(grpNameKey, grpDesc.toString());
-            }
-        }
-    }
-    
-    private static class PermissionInfoComparator implements Comparator<PermissionInfo> {
-        private PackageManager mPm;
+    private static class PermissionGroupInfoComparator implements Comparator<MyPermissionGroupInfo> {
         private final Collator sCollator = Collator.getInstance();
-        PermissionInfoComparator(PackageManager pm) {
-            mPm = pm;
+        PermissionGroupInfoComparator() {
         }
-        public final int compare(PermissionInfo a, PermissionInfo b) {
-            CharSequence sa = a.loadLabel(mPm);
-            CharSequence sb = b.loadLabel(mPm);
-            return sCollator.compare(sa, sb);
+        public final int compare(MyPermissionGroupInfo a, MyPermissionGroupInfo b) {
+            if (((a.flags^b.flags)&PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0) {
+                return ((a.flags&PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0) ? -1 : 1;
+            }
+            if (a.priority != b.priority) {
+                return a.priority > b.priority ? -1 : 1;
+            }
+            return sCollator.compare(a.mLabel, b.mLabel);
         }
     }
     
-    private void setPermissions(List<PermissionInfo> permList) {
-        mGroupLabelCache = new HashMap<String, CharSequence>();
-        //add the default label so that uncategorized permissions can go here
-        mGroupLabelCache.put(mDefaultGrpName, mDefaultGrpLabel);
-        
-        // Map containing group names and a list of permissions under that group
-        // categorized as dangerous
-        mDangerousMap = new HashMap<String, String>();
-        // Map containing group names and a list of permissions under that group
-        // categorized as normal
-        mNormalMap = new HashMap<String, String>();
-        
-        // Additional structures needed to ensure that permissions are unique under 
-        // each group
-        Map<String, List<PermissionInfo>> dangerousMap = 
-            new HashMap<String,  List<PermissionInfo>>();
-        Map<String, List<PermissionInfo> > normalMap = 
-            new HashMap<String,  List<PermissionInfo>>();
-        PermissionInfoComparator permComparator = new PermissionInfoComparator(mPm);
-        
+    private static class PermissionInfoComparator implements Comparator<MyPermissionInfo> {
+        private final Collator sCollator = Collator.getInstance();
+        PermissionInfoComparator() {
+        }
+        public final int compare(MyPermissionInfo a, MyPermissionInfo b) {
+            return sCollator.compare(a.mLabel, b.mLabel);
+        }
+    }
+
+    private void addPermToList(List<MyPermissionInfo> permList,
+            MyPermissionInfo pInfo) {
+        if (pInfo.mLabel == null) {
+            pInfo.mLabel = pInfo.loadLabel(mPm);
+        }
+        int idx = Collections.binarySearch(permList, pInfo, mPermComparator);
+        if(localLOGV) Log.i(TAG, "idx="+idx+", list.size="+permList.size());
+        if (idx < 0) {
+            idx = -idx-1;
+            permList.add(idx, pInfo);
+        }
+    }
+
+    private void setPermissions(List<MyPermissionInfo> permList) {
         if (permList != null) {
             // First pass to group permissions
-            for (PermissionInfo pInfo : permList) {
+            for (MyPermissionInfo pInfo : permList) {
                 if(localLOGV) Log.i(TAG, "Processing permission:"+pInfo.name);
-                if(!isDisplayablePermission(pInfo)) {
+                if(!isDisplayablePermission(pInfo, pInfo.mNewReqFlags, pInfo.mExistingReqFlags)) {
                     if(localLOGV) Log.i(TAG, "Permission:"+pInfo.name+" is not displayable");
                     continue;
                 }
-                Map<String, List<PermissionInfo> > permInfoMap =
-                    (pInfo.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) ?
-                            dangerousMap : normalMap;
-                String grpName = (pInfo.group == null) ? mDefaultGrpName : pInfo.group;
-                if(localLOGV) Log.i(TAG, "Permission:"+pInfo.name+" belongs to group:"+grpName);
-                List<PermissionInfo> grpPermsList = permInfoMap.get(grpName);
-                if(grpPermsList == null) {
-                    grpPermsList = new ArrayList<PermissionInfo>();
-                    permInfoMap.put(grpName, grpPermsList);
-                    grpPermsList.add(pInfo);
-                } else {
-                    int idx = Collections.binarySearch(grpPermsList, pInfo, permComparator);
-                    if(localLOGV) Log.i(TAG, "idx="+idx+", list.size="+grpPermsList.size());
-                    if (idx < 0) {
-                        idx = -idx-1;
-                        grpPermsList.add(idx, pInfo);
+                MyPermissionGroupInfo group = mPermGroups.get(pInfo.group);
+                if (group != null) {
+                    pInfo.mLabel = pInfo.loadLabel(mPm);
+                    addPermToList(group.mAllPermissions, pInfo);
+                    if (pInfo.mNew) {
+                        addPermToList(group.mNewPermissions, pInfo);
+                    }
+                    if ((group.flags&PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0) {
+                        addPermToList(group.mPersonalPermissions, pInfo);
+                    } else {
+                        addPermToList(group.mDevicePermissions, pInfo);
                     }
                 }
             }
-            // Second pass to actually form the descriptions
-            // Look at dangerous permissions first
-            aggregateGroupDescs(dangerousMap, mDangerousMap);
-            aggregateGroupDescs(normalMap, mNormalMap);
         }
 
-        mCurrentState = State.NO_PERMS;
-        if(mDangerousMap.size() > 0) {
-            mCurrentState = (mNormalMap.size() > 0) ? State.BOTH : State.DANGEROUS_ONLY;
-        } else if(mNormalMap.size() > 0) {
-            mCurrentState = State.NORMAL_ONLY;
+        for (MyPermissionGroupInfo pgrp : mPermGroups.values()) {
+            if (pgrp.labelRes != 0 || pgrp.nonLocalizedLabel != null) {
+                pgrp.mLabel = pgrp.loadLabel(mPm);
+            } else {
+                ApplicationInfo app;
+                try {
+                    app = mPm.getApplicationInfo(pgrp.packageName, 0);
+                    pgrp.mLabel = app.loadLabel(mPm);
+                } catch (NameNotFoundException e) {
+                    pgrp.mLabel = pgrp.loadLabel(mPm);
+                }
+            }
+            mPermGroupsList.add(pgrp);
         }
-        if(localLOGV) Log.i(TAG, "mCurrentState=" + mCurrentState);
-        showPermissions();
-    }
-
-    public void onClick(View v) {
-        if(localLOGV) Log.i(TAG, "mExpanded="+mExpanded);
-        mExpanded = !mExpanded;
-        showPermissions();
+        Collections.sort(mPermGroupsList, mPermGroupComparator);
+        if (localLOGV) {
+            for (MyPermissionGroupInfo grp : mPermGroupsList) {
+                Log.i(TAG, "Group " + grp.name + " personal="
+                        + ((grp.flags&PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0)
+                        + " priority=" + grp.priority);
+            }
+        }
     }
 }
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 30dd17d..f0eb94f 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -579,6 +579,23 @@
     }
 
     /**
+     * Set a listener that will be invoked whenever the AutoCompleteTextView's
+     * list of completions is dismissed.
+     * @param dismissListener Listener to invoke when completions are dismissed
+     */
+    public void setOnDismissListener(final OnDismissListener dismissListener) {
+        PopupWindow.OnDismissListener wrappedListener = null;
+        if (dismissListener != null) {
+            wrappedListener = new PopupWindow.OnDismissListener() {
+                @Override public void onDismiss() {
+                    dismissListener.onDismiss();
+                }
+            };
+        }
+        mPopup.setOnDismissListener(wrappedListener);
+    }
+
+    /**
      * <p>Returns a filterable list adapter used for auto completion.</p>
      *
      * @return a data adapter used for auto completion
@@ -904,8 +921,6 @@
      *
      * @param filter If <code>false</code>, no filtering will be performed
      *        as a result of this call.
-     * 
-     * @hide Pending API council approval.
      */
     public void setText(CharSequence text, boolean filter) {
         if (filter) {
@@ -1208,6 +1223,19 @@
     }
     
     /**
+     * Listener to respond to the AutoCompleteTextView's completion list being dismissed.
+     * @see AutoCompleteTextView#setOnDismissListener(OnDismissListener)
+     */
+    public interface OnDismissListener {
+        /**
+         * This method will be invoked whenever the AutoCompleteTextView's list
+         * of completion options has been dismissed and is no longer available
+         * for user interaction.
+         */
+        void onDismiss();
+    }
+
+    /**
      * Allows us a private hook into the on click event without preventing users from setting
      * their own click listener.
      */
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index b06da06..361eca4 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -1573,7 +1573,8 @@
             // If we're showing the week number calculate it based on Monday
             int i = 0;
             if (mShowWeekNumber) {
-                mDayNumbers[0] = Integer.toString(mTempDate.get(Calendar.WEEK_OF_YEAR));
+                mDayNumbers[0] = String.format(Locale.getDefault(), "%d",
+                        mTempDate.get(Calendar.WEEK_OF_YEAR));
                 i++;
             }
 
@@ -1594,7 +1595,8 @@
                 if (mTempDate.before(mMinDate) || mTempDate.after(mMaxDate)) {
                     mDayNumbers[i] = "";
                 } else {
-                    mDayNumbers[i] = Integer.toString(mTempDate.get(Calendar.DAY_OF_MONTH));
+                    mDayNumbers[i] = String.format(Locale.getDefault(), "%d",
+                            mTempDate.get(Calendar.DAY_OF_MONTH));
                 }
                 mTempDate.add(Calendar.DAY_OF_MONTH, 1);
             }
@@ -1609,7 +1611,7 @@
         }
 
         /**
-         * Initialize the paint isntances.
+         * Initialize the paint instances.
          */
         private void initilaizePaints() {
             mDrawPaint.setFakeBoldText(false);
@@ -1620,6 +1622,7 @@
             mMonthNumDrawPaint.setAntiAlias(true);
             mMonthNumDrawPaint.setStyle(Style.FILL);
             mMonthNumDrawPaint.setTextAlign(Align.CENTER);
+            mMonthNumDrawPaint.setTextSize(mDateTextSize);
         }
 
         /**
@@ -1657,16 +1660,34 @@
          * @return True if a day was found for the given location.
          */
         public boolean getDayFromLocation(float x, Calendar outCalendar) {
-            int dayStart = mShowWeekNumber ? mWidth / mNumCells : 0;
-            if (x < dayStart || x > mWidth) {
+            final boolean isLayoutRtl = isLayoutRtl();
+
+            int start;
+            int end;
+
+            if (isLayoutRtl) {
+                start = 0;
+                end = mShowWeekNumber ? mWidth - mWidth / mNumCells : mWidth;
+            } else {
+                start = mShowWeekNumber ? mWidth / mNumCells : 0;
+                end = mWidth;
+            }
+
+            if (x < start || x > end) {
                 outCalendar.clear();
                 return false;
             }
-            // Selection is (x - start) / (pixels/day) == (x -s) * day / pixels
-            int dayPosition = (int) ((x - dayStart) * mDaysPerWeek
-                    / (mWidth - dayStart));
+
+            // Selection is (x - start) / (pixels/day) which is (x - start) * day / pixels
+            int dayPosition = (int) ((x - start) * mDaysPerWeek / (end - start));
+
+            if (isLayoutRtl) {
+                dayPosition = mDaysPerWeek - 1 - dayPosition;
+            }
+
             outCalendar.setTimeInMillis(mFirstDay.getTimeInMillis());
             outCalendar.add(Calendar.DAY_OF_MONTH, dayPosition);
+
             return true;
         }
 
@@ -1691,12 +1712,25 @@
 
             mTempRect.top = mWeekSeperatorLineWidth;
             mTempRect.bottom = mHeight;
-            mTempRect.left = mShowWeekNumber ? mWidth / mNumCells : 0;
-            mTempRect.right = mSelectedLeft - 2;
+
+            final boolean isLayoutRtl = isLayoutRtl();
+
+            if (isLayoutRtl) {
+                mTempRect.left = 0;
+                mTempRect.right = mSelectedLeft - 2;
+            } else {
+                mTempRect.left = mShowWeekNumber ? mWidth / mNumCells : 0;
+                mTempRect.right = mSelectedLeft - 2;
+            }
             canvas.drawRect(mTempRect, mDrawPaint);
 
-            mTempRect.left = mSelectedRight + 3;
-            mTempRect.right = mWidth;
+            if (isLayoutRtl) {
+                mTempRect.left = mSelectedRight + 3;
+                mTempRect.right = mShowWeekNumber ? mWidth - mWidth / mNumCells : mWidth;
+            } else {
+                mTempRect.left = mSelectedRight + 3;
+                mTempRect.right = mWidth;
+            }
             canvas.drawRect(mTempRect, mDrawPaint);
         }
 
@@ -1706,25 +1740,41 @@
          * @param canvas The canvas to draw on
          */
         private void drawWeekNumbersAndDates(Canvas canvas) {
-            float textHeight = mDrawPaint.getTextSize();
-            int y = (int) ((mHeight + textHeight) / 2) - mWeekSeperatorLineWidth;
-            int nDays = mNumCells;
+            final float textHeight = mDrawPaint.getTextSize();
+            final int y = (int) ((mHeight + textHeight) / 2) - mWeekSeperatorLineWidth;
+            final int nDays = mNumCells;
+            final int divisor = 2 * nDays;
 
             mDrawPaint.setTextAlign(Align.CENTER);
             mDrawPaint.setTextSize(mDateTextSize);
+
             int i = 0;
-            int divisor = 2 * nDays;
-            if (mShowWeekNumber) {
-                mDrawPaint.setColor(mWeekNumberColor);
-                int x = mWidth / divisor;
-                canvas.drawText(mDayNumbers[0], x, y, mDrawPaint);
-                i++;
-            }
-            for (; i < nDays; i++) {
-                mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor
-                        : mUnfocusedMonthDateColor);
-                int x = (2 * i + 1) * mWidth / divisor;
-                canvas.drawText(mDayNumbers[i], x, y, mMonthNumDrawPaint);
+
+            if (isLayoutRtl()) {
+                for (; i < nDays - 1; i++) {
+                    mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor
+                            : mUnfocusedMonthDateColor);
+                    int x = (2 * i + 1) * mWidth / divisor;
+                    canvas.drawText(mDayNumbers[nDays - 1 - i], x, y, mMonthNumDrawPaint);
+                }
+                if (mShowWeekNumber) {
+                    mDrawPaint.setColor(mWeekNumberColor);
+                    int x = mWidth - mWidth / divisor;
+                    canvas.drawText(mDayNumbers[0], x, y, mDrawPaint);
+                }
+            } else {
+                if (mShowWeekNumber) {
+                    mDrawPaint.setColor(mWeekNumberColor);
+                    int x = mWidth / divisor;
+                    canvas.drawText(mDayNumbers[0], x, y, mDrawPaint);
+                    i++;
+                }
+                for (; i < nDays; i++) {
+                    mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor
+                            : mUnfocusedMonthDateColor);
+                    int x = (2 * i + 1) * mWidth / divisor;
+                    canvas.drawText(mDayNumbers[i], x, y, mMonthNumDrawPaint);
+                }
             }
         }
 
@@ -1744,8 +1794,16 @@
             }
             mDrawPaint.setColor(mWeekSeparatorLineColor);
             mDrawPaint.setStrokeWidth(mWeekSeperatorLineWidth);
-            float x = mShowWeekNumber ? mWidth / mNumCells : 0;
-            canvas.drawLine(x, 0, mWidth, 0, mDrawPaint);
+            float startX;
+            float stopX;
+            if (isLayoutRtl()) {
+                startX = 0;
+                stopX = mShowWeekNumber ? mWidth - mWidth / mNumCells : mWidth;
+            } else {
+                startX = mShowWeekNumber ? mWidth / mNumCells : 0;
+                stopX = mWidth;
+            }
+            canvas.drawLine(startX, 0, stopX, 0, mDrawPaint);
         }
 
         /**
@@ -1778,15 +1836,21 @@
          */
         private void updateSelectionPositions() {
             if (mHasSelectedDay) {
+                final boolean isLayoutRtl = isLayoutRtl();
                 int selectedPosition = mSelectedDay - mFirstDayOfWeek;
                 if (selectedPosition < 0) {
                     selectedPosition += 7;
                 }
-                if (mShowWeekNumber) {
+                if (mShowWeekNumber && !isLayoutRtl) {
                     selectedPosition++;
                 }
-                mSelectedLeft = selectedPosition * mWidth / mNumCells;
-                mSelectedRight = (selectedPosition + 1) * mWidth / mNumCells;
+                if (isLayoutRtl) {
+                    mSelectedLeft = (mDaysPerWeek - 1 - selectedPosition) * mWidth / mNumCells;
+
+                } else {
+                    mSelectedLeft = selectedPosition * mWidth / mNumCells;
+                }
+                mSelectedRight = mSelectedLeft + mWidth / mNumCells;
             }
         }
 
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 61935c2..de8b80d 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -55,7 +55,7 @@
     }
 
     public CheckedTextView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
+        this(context, attrs, R.attr.checkedTextViewStyle);
     }
 
     public CheckedTextView(Context context, AttributeSet attrs, int defStyle) {
@@ -101,7 +101,7 @@
     /**
      * Set the checkmark to a given Drawable, identified by its resourece id. This will be drawn
      * when {@link #isChecked()} is true.
-     * 
+     *
      * @param resid The Drawable to use for the checkmark.
      *
      * @see #setCheckMarkDrawable(Drawable)
@@ -144,14 +144,14 @@
             d.setVisible(getVisibility() == VISIBLE, false);
             d.setState(CHECKED_STATE_SET);
             setMinHeight(d.getIntrinsicHeight());
-            
+
             mCheckMarkWidth = d.getIntrinsicWidth();
             d.setState(getDrawableState());
         } else {
             mCheckMarkWidth = 0;
         }
         mCheckMarkDrawable = d;
-        // Do padding resolution. This will call setPadding() and do a requestLayout() if needed.
+        // Do padding resolution. This will call internalSetPadding() and do a requestLayout() if needed.
         resolvePadding();
     }
 
@@ -169,28 +169,44 @@
         return mCheckMarkDrawable;
     }
 
+    /**
+     * @hide
+     */
     @Override
-    public void onPaddingChanged(int layoutDirection) {
+    protected void internalSetPadding(int left, int top, int right, int bottom) {
+        super.internalSetPadding(left, top, right, bottom);
+        setBasePadding(isLayoutRtl());
+    }
+
+    @Override
+    public void onRtlPropertiesChanged(int layoutDirection) {
+        super.onRtlPropertiesChanged(layoutDirection);
+        updatePadding();
+    }
+
+    private void updatePadding() {
+        resetPaddingToInitialValues();
         int newPadding = (mCheckMarkDrawable != null) ?
                 mCheckMarkWidth + mBasePadding : mBasePadding;
-        mNeedRequestlayout |= (mPaddingRight != newPadding);
-        mPaddingRight = newPadding;
+        if (isLayoutRtl()) {
+            mNeedRequestlayout |= (mPaddingLeft != newPadding);
+            mPaddingLeft = newPadding;
+        } else {
+            mNeedRequestlayout |= (mPaddingRight != newPadding);
+            mPaddingRight = newPadding;
+        }
         if (mNeedRequestlayout) {
             requestLayout();
             mNeedRequestlayout = false;
         }
     }
-    
-    @Override
-    public void setPadding(int left, int top, int right, int bottom) {
-        super.setPadding(left, top, right, bottom);
-        mBasePadding = mPaddingRight;
-    }
 
-    @Override
-    public void setPaddingRelative(int start, int top, int end, int bottom) {
-        super.setPaddingRelative(start, top, end, bottom);
-        mBasePadding = getPaddingEnd();
+    private void setBasePadding(boolean isLayoutRtl) {
+        if (isLayoutRtl) {
+            mBasePadding = mPaddingLeft;
+        } else {
+            mBasePadding = mPaddingRight;
+        }
     }
 
     @Override
@@ -213,12 +229,20 @@
                     break;
             }
             
-            int right = getWidth();
-            checkMarkDrawable.setBounds(
-                    right - mPaddingRight,
-                    y, 
-                    right - mPaddingRight + mCheckMarkWidth,
-                    y + height);
+            final boolean isLayoutRtl = isLayoutRtl();
+            final int width = getWidth();
+            final int top = y;
+            final int bottom = top + height;
+            final int left;
+            final int right;
+            if (isLayoutRtl) {
+                left = mBasePadding;
+                right = left + mCheckMarkWidth;
+            } else {
+                right = width - mBasePadding;
+                left = right - mCheckMarkWidth;
+            }
+            checkMarkDrawable.setBounds( left, top, right, bottom);
             checkMarkDrawable.draw(canvas);
         }
     }
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 0a71c5a..421a324 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -225,26 +225,53 @@
     }
 
     @Override
+    public int getCompoundPaddingLeft() {
+        int padding = super.getCompoundPaddingLeft();
+        if (!isLayoutRtl()) {
+            final Drawable buttonDrawable = mButtonDrawable;
+            if (buttonDrawable != null) {
+                padding += buttonDrawable.getIntrinsicWidth();
+            }
+        }
+        return padding;
+    }
+
+    @Override
+    public int getCompoundPaddingRight() {
+        int padding = super.getCompoundPaddingRight();
+        if (isLayoutRtl()) {
+            final Drawable buttonDrawable = mButtonDrawable;
+            if (buttonDrawable != null) {
+                padding += buttonDrawable.getIntrinsicWidth();
+            }
+        }
+        return padding;
+    }
+
+    @Override
     protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
 
         final Drawable buttonDrawable = mButtonDrawable;
         if (buttonDrawable != null) {
             final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
-            final int height = buttonDrawable.getIntrinsicHeight();
+            final int drawableHeight = buttonDrawable.getIntrinsicHeight();
+            final int drawableWidth = buttonDrawable.getIntrinsicWidth();
 
-            int y = 0;
-
+            int top = 0;
             switch (verticalGravity) {
                 case Gravity.BOTTOM:
-                    y = getHeight() - height;
+                    top = getHeight() - drawableHeight;
                     break;
                 case Gravity.CENTER_VERTICAL:
-                    y = (getHeight() - height) / 2;
+                    top = (getHeight() - drawableHeight) / 2;
                     break;
             }
+            int bottom = top + drawableHeight;
+            int left = isLayoutRtl() ? getWidth() - drawableWidth : 0;
+            int right = isLayoutRtl() ? getWidth() : drawableWidth;
 
-            buttonDrawable.setBounds(0, y, buttonDrawable.getIntrinsicWidth(), y + height);
+            buttonDrawable.setBounds(left, top, right, bottom);
             buttonDrawable.draw(canvas);
         }
     }
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index ac3bedb..07d3a7a 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -220,7 +220,7 @@
 
         // day
         mDaySpinner = (NumberPicker) findViewById(R.id.day);
-        mDaySpinner.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
+        mDaySpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
         mDaySpinner.setOnLongPressUpdateInterval(100);
         mDaySpinner.setOnValueChangedListener(onChangeListener);
         mDaySpinnerInput = (EditText) mDaySpinner.findViewById(R.id.numberpicker_input);
diff --git a/core/java/android/widget/DigitalClock.java b/core/java/android/widget/DigitalClock.java
index add9d9b..c6b6dd6 100644
--- a/core/java/android/widget/DigitalClock.java
+++ b/core/java/android/widget/DigitalClock.java
@@ -17,7 +17,6 @@
 package android.widget;
 
 import android.content.Context;
-import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.os.Handler;
 import android.os.SystemClock;
@@ -32,15 +31,17 @@
 /**
  * Like AnalogClock, but digital.  Shows seconds.
  *
- * FIXME: implement separate views for hours/minutes/seconds, so
- * proportional fonts don't shake rendering
+ * @deprecated It is recommended you use {@link TextClock} instead.
  */
-
+@Deprecated
 public class DigitalClock extends TextView {
+    // FIXME: implement separate views for hours/minutes/seconds, so
+    // proportional fonts don't shake rendering
 
     Calendar mCalendar;
     private final static String m12 = "h:mm:ss aa";
     private final static String m24 = "k:mm:ss";
+    @SuppressWarnings("FieldCanBeLocal") // We must keep a reference to this observer
     private FormatChangeObserver mFormatChangeObserver;
 
     private Runnable mTicker;
@@ -52,17 +53,15 @@
 
     public DigitalClock(Context context) {
         super(context);
-        initClock(context);
+        initClock();
     }
 
     public DigitalClock(Context context, AttributeSet attrs) {
         super(context, attrs);
-        initClock(context);
+        initClock();
     }
 
-    private void initClock(Context context) {
-        Resources r = mContext.getResources();
-
+    private void initClock() {
         if (mCalendar == null) {
             mCalendar = Calendar.getInstance();
         }
@@ -84,16 +83,16 @@
          * requests a tick on the next hard-second boundary
          */
         mTicker = new Runnable() {
-                public void run() {
-                    if (mTickerStopped) return;
-                    mCalendar.setTimeInMillis(System.currentTimeMillis());
-                    setText(DateFormat.format(mFormat, mCalendar));
-                    invalidate();
-                    long now = SystemClock.uptimeMillis();
-                    long next = now + (1000 - now % 1000);
-                    mHandler.postAtTime(mTicker, next);
-                }
-            };
+            public void run() {
+                if (mTickerStopped) return;
+                mCalendar.setTimeInMillis(System.currentTimeMillis());
+                setText(DateFormat.format(mFormat, mCalendar));
+                invalidate();
+                long now = SystemClock.uptimeMillis();
+                long next = now + (1000 - now % 1000);
+                mHandler.postAtTime(mTicker, next);
+            }
+        };
         mTicker.run();
     }
 
@@ -132,12 +131,14 @@
     @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
+        //noinspection deprecation
         event.setClassName(DigitalClock.class.getName());
     }
 
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
+        //noinspection deprecation
         info.setClassName(DigitalClock.class.getName());
     }
 }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index c29dd58..b1a44c5 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -88,9 +88,6 @@
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.AdapterView.OnItemClickListener;
-import android.widget.Editor.InputContentType;
-import android.widget.Editor.InputMethodState;
-import android.widget.Editor.SelectionModifierCursorController;
 import android.widget.TextView.Drawables;
 import android.widget.TextView.OnEditorActionListener;
 
@@ -125,6 +122,7 @@
     InputMethodState mInputMethodState;
 
     DisplayList[] mTextDisplayLists;
+    int mLastLayoutHeight;
 
     boolean mFrozenWithFocus;
     boolean mSelectionMoved;
@@ -146,6 +144,7 @@
     CharSequence mError;
     boolean mErrorWasChanged;
     ErrorPopup mErrorPopup;
+
     /**
      * This flag is set if the TextView tries to display an error before it
      * is attached to the window (so its position is still unknown).
@@ -290,22 +289,6 @@
     public void setError(CharSequence error, Drawable icon) {
         mError = TextUtils.stringOrSpannedString(error);
         mErrorWasChanged = true;
-        final Drawables dr = mTextView.mDrawables;
-        if (dr != null) {
-            switch (mTextView.getResolvedLayoutDirection()) {
-                default:
-                case View.LAYOUT_DIRECTION_LTR:
-                    mTextView.setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon,
-                            dr.mDrawableBottom);
-                    break;
-                case View.LAYOUT_DIRECTION_RTL:
-                    mTextView.setCompoundDrawables(icon, dr.mDrawableTop, dr.mDrawableRight,
-                            dr.mDrawableBottom);
-                    break;
-            }
-        } else {
-            mTextView.setCompoundDrawables(null, null, icon, null);
-        }
 
         if (mError == null) {
             if (mErrorPopup != null) {
@@ -315,10 +298,21 @@
 
                 mErrorPopup = null;
             }
+
+            setErrorIcon(null);
+        } else if (mTextView.isFocused()) {
+            showError();
+            setErrorIcon(icon);
+        }
+    }
+
+    private void setErrorIcon(Drawable icon) {
+        final Drawables dr = mTextView.mDrawables;
+        if (dr != null) {
+            mTextView.setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon,
+                    dr.mDrawableBottom);
         } else {
-            if (mTextView.isFocused()) {
-                showError();
-            }
+            mTextView.setCompoundDrawables(null, null, icon, null);
         }
     }
 
@@ -327,6 +321,8 @@
             if (mErrorPopup.isShowing()) {
                 mErrorPopup.dismiss();
             }
+
+            setErrorIcon(null);
         }
 
         mShowErrorAfterAttach = false;
@@ -978,8 +974,8 @@
                 mSuggestionsPopupWindow.onParentLostFocus();
             }
 
-            // Don't leave us in the middle of a batch edit.
-            mTextView.onEndBatchEdit();
+            // Don't leave us in the middle of a batch edit. Same as in onFocusChanged
+            ensureEndedBatchEdit();
         }
     }
 
@@ -1261,6 +1257,16 @@
                 mTextDisplayLists = new DisplayList[ArrayUtils.idealObjectArraySize(0)];
             }
 
+            // If the height of the layout changes (usually when inserting or deleting a line,
+            // but could be changes within a span), invalidate everything. We could optimize
+            // more aggressively (for example, adding offsets to blocks) but it would be more
+            // complex and we would only get the benefit in some cases.
+            int layoutHeight = layout.getHeight();
+            if (mLastLayoutHeight != layoutHeight) {
+                invalidateTextDisplayList();
+                mLastLayoutHeight = layoutHeight;
+            }
+
             DynamicLayout dynamicLayout = (DynamicLayout) layout;
             int[] blockEndLines = dynamicLayout.getBlockEndLines();
             int[] blockIndices = dynamicLayout.getBlockIndices();
@@ -1801,13 +1807,13 @@
             mTextView.deleteText_internal(dragSourceStart, dragSourceEnd);
 
             // Make sure we do not leave two adjacent spaces.
-            CharSequence t = mTextView.getTransformedText(dragSourceStart - 1, dragSourceStart + 1);
-            if ( (dragSourceStart == 0 || Character.isSpaceChar(t.charAt(0))) &&
-                    (dragSourceStart == mTextView.getText().length() ||
-                    Character.isSpaceChar(t.charAt(1))) ) {
-                final int pos = dragSourceStart == mTextView.getText().length() ?
-                        dragSourceStart - 1 : dragSourceStart;
-                mTextView.deleteText_internal(pos, pos + 1);
+            final int prevCharIdx = Math.max(0,  dragSourceStart - 1);
+            final int nextCharIdx = Math.min(mTextView.getText().length(), dragSourceStart + 1);
+            if (nextCharIdx > prevCharIdx + 1) {
+                CharSequence t = mTextView.getTransformedText(prevCharIdx, nextCharIdx);
+                if (Character.isSpaceChar(t.charAt(0)) && Character.isSpaceChar(t.charAt(1))) {
+                    mTextView.deleteText_internal(prevCharIdx, prevCharIdx + 1);
+                }
             }
         }
     }
@@ -2282,14 +2288,11 @@
                 final SuggestionInfo suggestionInfo = mSuggestionInfos[position];
                 textView.setText(suggestionInfo.text);
 
-                if (suggestionInfo.suggestionIndex == ADD_TO_DICTIONARY) {
-                    textView.setCompoundDrawablesWithIntrinsicBounds(
-                            com.android.internal.R.drawable.ic_suggestions_add, 0, 0, 0);
-                } else if (suggestionInfo.suggestionIndex == DELETE_TEXT) {
-                    textView.setCompoundDrawablesWithIntrinsicBounds(
-                            com.android.internal.R.drawable.ic_suggestions_delete, 0, 0, 0);
+                if (suggestionInfo.suggestionIndex == ADD_TO_DICTIONARY ||
+                suggestionInfo.suggestionIndex == DELETE_TEXT) {
+                    textView.setBackgroundColor(Color.TRANSPARENT);
                 } else {
-                    textView.setCompoundDrawables(null, null, null, null);
+                    textView.setBackgroundColor(Color.WHITE);
                 }
 
                 return textView;
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 083a952..d2139af 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -181,10 +181,13 @@
     }
 
     public void setScrollbarPosition(int position) {
+        if (position == View.SCROLLBAR_POSITION_DEFAULT) {
+            position = mList.isLayoutRtl() ?
+                    View.SCROLLBAR_POSITION_LEFT : View.SCROLLBAR_POSITION_RIGHT;
+        }
         mPosition = position;
         switch (position) {
             default:
-            case View.SCROLLBAR_POSITION_DEFAULT:
             case View.SCROLLBAR_POSITION_RIGHT:
                 mOverlayDrawable = mOverlayDrawableRight;
                 break;
@@ -229,7 +232,6 @@
         final int viewWidth = mList.getWidth();
         // Bounds are always top right. Y coordinate get's translated during draw
         switch (mPosition) {
-            case View.SCROLLBAR_POSITION_DEFAULT:
             case View.SCROLLBAR_POSITION_RIGHT:
                 mThumbDrawable.setBounds(viewWidth - mThumbW, 0, viewWidth, mThumbH);
                 break;
@@ -327,7 +329,6 @@
             }
             int left = 0;
             switch (mPosition) {
-                case View.SCROLLBAR_POSITION_DEFAULT:
                 case View.SCROLLBAR_POSITION_RIGHT:
                     left = viewWidth - (mThumbW * alpha) / ScrollFade.ALPHA_MAX;
                     break;
@@ -360,7 +361,6 @@
                 int left = 0;
                 switch (mPosition) {
                     default:
-                    case View.SCROLLBAR_POSITION_DEFAULT:
                     case View.SCROLLBAR_POSITION_RIGHT:
                         left = Math.max(0,
                                 mThumbDrawable.getBounds().left - mThumbW - mOverlaySize);
@@ -410,7 +410,6 @@
         if (mThumbDrawable != null) {
             switch (mPosition) {
                 default:
-                case View.SCROLLBAR_POSITION_DEFAULT:
                 case View.SCROLLBAR_POSITION_RIGHT:
                     mThumbDrawable.setBounds(w - mThumbW, 0, w, mThumbH);
                     break;
@@ -820,7 +819,6 @@
         boolean inTrack = false;
         switch (mPosition) {
             default:
-            case View.SCROLLBAR_POSITION_DEFAULT:
             case View.SCROLLBAR_POSITION_RIGHT:
                 inTrack = x > mList.getWidth() - mThumbW;
                 break;
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index d019d8c7..738f63b 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -55,7 +55,7 @@
  */
 @RemoteView
 public class FrameLayout extends ViewGroup {
-    private static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.LEFT;
+    private static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.START;
 
     @ViewDebug.ExportedProperty(category = "measurement")
     boolean mMeasureAllChildren = false;
@@ -411,7 +411,7 @@
                     gravity = DEFAULT_CHILD_GRAVITY;
                 }
 
-                final int layoutDirection = getResolvedLayoutDirection();
+                final int layoutDirection = getLayoutDirection();
                 final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
                 final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
 
@@ -483,7 +483,7 @@
                     selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);
                 }
 
-                final int layoutDirection = getResolvedLayoutDirection();
+                final int layoutDirection = getLayoutDirection();
                 Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds,
                         layoutDirection);
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index b72b8cb..e0c5bbd 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -182,6 +182,12 @@
      */
     private boolean mIsRtl = true;
     
+    /**
+     * Offset between the center of the selected child view and the center of the Gallery.
+     * Used to reset position correctly during layout.
+     */
+    private int mSelectedCenterOffset;
+
     public Gallery(Context context) {
         this(context, null);
     }
@@ -395,6 +401,14 @@
         
         setSelectionToCenterChild();
 
+        final View selChild = mSelectedChild;
+        if (selChild != null) {
+            final int childLeft = selChild.getLeft();
+            final int childCenter = selChild.getWidth() / 2;
+            final int galleryCenter = getWidth() / 2;
+            mSelectedCenterOffset = childLeft + childCenter - galleryCenter;
+        }
+
         onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
 
         invalidate();
@@ -537,6 +551,7 @@
             // We haven't been callbacking during the fling, so do it now
             super.selectionChanged();
         }
+        mSelectedCenterOffset = 0;
         invalidate();
     }
     
@@ -650,7 +665,8 @@
         View sel = makeAndAddView(mSelectedPosition, 0, 0, true);
         
         // Put the selected child in the center
-        int selectedOffset = childrenLeft + (childrenWidth / 2) - (sel.getWidth() / 2);
+        int selectedOffset = childrenLeft + (childrenWidth / 2) - (sel.getWidth() / 2) +
+                mSelectedCenterOffset;
         sel.offsetLeftAndRight(selectedOffset);
 
         fillToGalleryRight();
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 37e0b90..63147dd 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -94,7 +94,7 @@
     private View mReferenceView = null;
     private View mReferenceViewInSelectedRow = null;
 
-    private int mGravity = Gravity.LEFT;
+    private int mGravity = Gravity.START;
 
     private final Rect mTempRect = new Rect();
 
@@ -300,9 +300,18 @@
         final int columnWidth = mColumnWidth;
         final int horizontalSpacing = mHorizontalSpacing;
 
+        final boolean isLayoutRtl = isLayoutRtl();
+
         int last;
-        int nextLeft = mListPadding.left +
-                ((mStretchMode == STRETCH_SPACING_UNIFORM) ? horizontalSpacing : 0);
+        int nextLeft;
+
+        if (isLayoutRtl) {
+            nextLeft = getWidth() - mListPadding.right - columnWidth -
+                    ((mStretchMode == STRETCH_SPACING_UNIFORM) ? horizontalSpacing : 0);
+        } else {
+            nextLeft = mListPadding.left +
+                    ((mStretchMode == STRETCH_SPACING_UNIFORM) ? horizontalSpacing : 0);
+        }
 
         if (!mStackFromBottom) {
             last = Math.min(startPos + mNumColumns, mItemCount);
@@ -311,7 +320,8 @@
             startPos = Math.max(0, startPos - mNumColumns + 1);
 
             if (last - startPos < mNumColumns) {
-                nextLeft += (mNumColumns - (last - startPos)) * (columnWidth + horizontalSpacing);
+                final int deltaLeft = (mNumColumns - (last - startPos)) * (columnWidth + horizontalSpacing);
+                nextLeft += (isLayoutRtl ? -1 : +1) * deltaLeft;
             }
         }
 
@@ -330,7 +340,7 @@
             final int where = flow ? -1 : pos - startPos;
             child = makeAndAddView(pos, y, flow, nextLeft, selected, where);
 
-            nextLeft += columnWidth;
+            nextLeft += (isLayoutRtl ? -1 : +1) * columnWidth;
             if (pos < last - 1) {
                 nextLeft += horizontalSpacing;
             }
@@ -1415,7 +1425,7 @@
         int childLeft;
         final int childTop = flow ? y : y - h;
 
-        final int layoutDirection = getResolvedLayoutDirection();
+        final int layoutDirection = getLayoutDirection();
         final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
         switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
             case Gravity.LEFT:
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index cf28da4..87396fb 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -193,15 +193,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
-    @Override
-    public int getResolvedLayoutDirection(Drawable dr) {
-        return (dr == mDrawable) ?
-                getResolvedLayoutDirection() : super.getResolvedLayoutDirection(dr);
-    }
-
     @Override
     public boolean hasOverlappingRendering() {
         return (getBackground() != null);
@@ -351,8 +342,15 @@
             updateDrawable(null);
             mResource = resId;
             mUri = null;
+
+            final int oldWidth = mDrawableWidth;
+            final int oldHeight = mDrawableHeight;
+
             resolveUri();
-            requestLayout();
+
+            if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
+                requestLayout();
+            }
             invalidate();
         }
     }
@@ -376,8 +374,15 @@
             updateDrawable(null);
             mResource = 0;
             mUri = uri;
+
+            final int oldWidth = mDrawableWidth;
+            final int oldHeight = mDrawableHeight;
+
             resolveUri();
-            requestLayout();
+
+            if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
+                requestLayout();
+            }
             invalidate();
         }
     }
@@ -392,8 +397,8 @@
             mResource = 0;
             mUri = null;
 
-            int oldWidth = mDrawableWidth;
-            int oldHeight = mDrawableHeight;
+            final int oldWidth = mDrawableWidth;
+            final int oldHeight = mDrawableHeight;
 
             updateDrawable(drawable);
 
@@ -675,6 +680,7 @@
                 d.setState(getDrawableState());
             }
             d.setLevel(mLevel);
+            d.setLayoutDirection(getLayoutDirection());
             mDrawableWidth = d.getIntrinsicWidth();
             mDrawableHeight = d.getIntrinsicHeight();
             applyColorMod();
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 09c0129..b6f0862 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -345,28 +345,42 @@
 
     void drawDividersHorizontal(Canvas canvas) {
         final int count = getVirtualChildCount();
+        final boolean isLayoutRtl = isLayoutRtl();
         for (int i = 0; i < count; i++) {
             final View child = getVirtualChildAt(i);
 
             if (child != null && child.getVisibility() != GONE) {
                 if (hasDividerBeforeChildAt(i)) {
                     final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-                    final int left = child.getLeft() - lp.leftMargin - mDividerWidth;
-                    drawVerticalDivider(canvas, left);
+                    final int position;
+                    if (isLayoutRtl) {
+                        position = child.getRight() + lp.rightMargin;
+                    } else {
+                        position = child.getLeft() - lp.leftMargin - mDividerWidth;
+                    }
+                    drawVerticalDivider(canvas, position);
                 }
             }
         }
 
         if (hasDividerBeforeChildAt(count)) {
             final View child = getVirtualChildAt(count - 1);
-            int right = 0;
+            int position;
             if (child == null) {
-                right = getWidth() - getPaddingRight() - mDividerWidth;
+                if (isLayoutRtl) {
+                    position = getPaddingLeft();
+                } else {
+                    position = getWidth() - getPaddingRight() - mDividerWidth;
+                }
             } else {
                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-                right = child.getRight() + lp.rightMargin;
+                if (isLayoutRtl) {
+                    position = child.getLeft() - lp.leftMargin - mDividerWidth;
+                } else {
+                    position = child.getRight() + lp.rightMargin;
+                }
             }
-            drawVerticalDivider(canvas, right);
+            drawVerticalDivider(canvas, position);
         }
     }
 
@@ -1481,7 +1495,7 @@
                 if (gravity < 0) {
                     gravity = minorGravity;
                 }
-                final int layoutDirection = getResolvedLayoutDirection();
+                final int layoutDirection = getLayoutDirection();
                 final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
                 switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
                     case Gravity.CENTER_HORIZONTAL:
@@ -1545,7 +1559,7 @@
         final int[] maxAscent = mMaxAscent;
         final int[] maxDescent = mMaxDescent;
 
-        final int layoutDirection = getResolvedLayoutDirection();
+        final int layoutDirection = getLayoutDirection();
         switch (Gravity.getAbsoluteGravity(majorGravity, layoutDirection)) {
             case Gravity.RIGHT:
                 // mTotalLength contains the padding already
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 1d966b3..3d6b69e 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -21,6 +21,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -31,6 +32,8 @@
 import android.view.ViewGroup;
 import android.view.ViewParent;
 
+import java.util.Locale;
+
 /**
  * A ListPopupWindow anchors itself to a host view and displays a
  * list of choices.
@@ -92,6 +95,8 @@
 
     private boolean mModal;
 
+    private int mLayoutDirection;
+
     /**
      * The provided prompt view should appear above list content.
      * 
@@ -193,6 +198,9 @@
         mContext = context;
         mPopup = new PopupWindow(context, attrs, defStyleAttr, defStyleRes);
         mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
+        // Set the default layout direction to match the default locale one
+        final Locale locale = mContext.getResources().getConfiguration().locale;
+        mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(locale);
     }
 
     /**
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index e011c13..03507b5 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -29,6 +29,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.util.MathUtils;
 import android.util.SparseBooleanArray;
 import android.view.FocusFinder;
 import android.view.KeyEvent;
@@ -37,6 +38,7 @@
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewParent;
+import android.view.ViewRootImpl;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.RemoteViews.RemoteView;
@@ -1490,6 +1492,10 @@
 
             View focusLayoutRestoreView = null;
 
+            AccessibilityNodeInfo accessibilityFocusLayoutRestoreNode = null;
+            View accessibilityFocusLayoutRestoreView = null;
+            int accessibilityFocusPosition = INVALID_POSITION;
+
             // Remember stuff we will need down below
             switch (mLayoutMode) {
             case LAYOUT_SET_SELECTION:
@@ -1584,6 +1590,30 @@
                 requestFocus();
             }
 
+            // Remember which child, if any, had accessibility focus.
+            final ViewRootImpl viewRootImpl = getViewRootImpl();
+            if (viewRootImpl != null) {
+                final View accessFocusedView = viewRootImpl.getAccessibilityFocusedHost();
+                if (accessFocusedView != null) {
+                    final View accessFocusedChild = findAccessibilityFocusedChild(
+                            accessFocusedView);
+                    if (accessFocusedChild != null) {
+                        if (!dataChanged || isDirectChildHeaderOrFooter(accessFocusedChild)) {
+                            // If the views won't be changing, try to maintain
+                            // focus on the current view host and (if
+                            // applicable) its virtual view.
+                            accessibilityFocusLayoutRestoreView = accessFocusedView;
+                            accessibilityFocusLayoutRestoreNode = viewRootImpl
+                                    .getAccessibilityFocusedVirtualView();
+                        } else {
+                            // Otherwise, try to maintain focus at the same
+                            // position.
+                            accessibilityFocusPosition = getPositionForView(accessFocusedChild);
+                        }
+                    }
+                }
+            }
+
             // Clear out old views
             detachAllViewsFromParent();
             recycleBin.removeSkippedScrap();
@@ -1682,6 +1712,22 @@
                 }
             }
 
+            // Attempt to restore accessibility focus.
+            if (accessibilityFocusLayoutRestoreNode != null) {
+                accessibilityFocusLayoutRestoreNode.performAction(
+                        AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
+            } else if (accessibilityFocusLayoutRestoreView != null) {
+                accessibilityFocusLayoutRestoreView.requestAccessibilityFocus();
+            } else if (accessibilityFocusPosition != INVALID_POSITION) {
+                // Bound the position within the visible children.
+                final int position = MathUtils.constrain(
+                        (accessibilityFocusPosition - mFirstPosition), 0, (getChildCount() - 1));
+                final View restoreView = getChildAt(position);
+                if (restoreView != null) {
+                    restoreView.requestAccessibilityFocus();
+                }
+            }
+
             // tell focus view we are done mucking with it, if it is still in
             // our view hierarchy.
             if (focusLayoutRestoreView != null
@@ -1713,6 +1759,22 @@
     }
 
     /**
+     * @param focusedView the view that has accessibility focus.
+     * @return the direct child that contains accessibility focus.
+     */
+    private View findAccessibilityFocusedChild(View focusedView) {
+        ViewParent viewParent = focusedView.getParent();
+        while ((viewParent instanceof View) && (viewParent != this)) {
+            focusedView = (View) viewParent;
+            viewParent = viewParent.getParent();
+        }
+        if (!(viewParent instanceof View)) {
+            return null;
+        }
+        return focusedView;
+    }
+
+    /**
      * @param child a direct child of this list.
      * @return Whether child is a header or footer view.
      */
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index a458f57..4918e48 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -51,10 +51,12 @@
 import android.view.inputmethod.InputMethodManager;
 
 import com.android.internal.R;
+import libcore.icu.LocaleData;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Locale;
 
 /**
  * A widget that enables the user to select a number form a predefined range.
@@ -138,13 +140,6 @@
     private static final int DEFAULT_LAYOUT_RESOURCE_ID = R.layout.number_picker;
 
     /**
-     * The numbers accepted by the input text's {@link Filter}
-     */
-    private static final char[] DIGIT_CHARACTERS = new char[] {
-            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
-    };
-
-    /**
      * Constant for unspecified size.
      */
     private static final int SIZE_UNSPECIFIED = -1;
@@ -154,23 +149,53 @@
      * strings like "01". Keeping a static formatter etc. is the most efficient
      * way to do this; it avoids creating temporary objects on every call to
      * format().
-     *
-     * @hide
      */
-    public static final NumberPicker.Formatter TWO_DIGIT_FORMATTER = new NumberPicker.Formatter() {
+    private static class TwoDigitFormatter implements NumberPicker.Formatter {
         final StringBuilder mBuilder = new StringBuilder();
 
-        final java.util.Formatter mFmt = new java.util.Formatter(mBuilder, java.util.Locale.US);
+        char mZeroDigit;
+        java.util.Formatter mFmt;
 
         final Object[] mArgs = new Object[1];
 
+        TwoDigitFormatter() {
+            final Locale locale = Locale.getDefault();
+            init(locale);
+        }
+
+        private void init(Locale locale) {
+            mFmt = createFormatter(locale);
+            mZeroDigit = getZeroDigit(locale);
+        }
+
         public String format(int value) {
+            final Locale currentLocale = Locale.getDefault();
+            if (mZeroDigit != getZeroDigit(currentLocale)) {
+                init(currentLocale);
+            }
             mArgs[0] = value;
             mBuilder.delete(0, mBuilder.length());
             mFmt.format("%02d", mArgs);
             return mFmt.toString();
         }
-    };
+
+        private static char getZeroDigit(Locale locale) {
+            return LocaleData.get(locale).zeroDigit;
+        }
+
+        private java.util.Formatter createFormatter(Locale locale) {
+            return new java.util.Formatter(mBuilder, locale);
+        }
+    }
+
+    private static final TwoDigitFormatter sTwoDigitFormatter = new TwoDigitFormatter();
+
+    /**
+     * @hide
+     */
+    public static final Formatter getTwoDigitFormatter() {
+        return sTwoDigitFormatter;
+    }
 
     /**
      * The increment button.
@@ -1156,7 +1181,7 @@
         if (mDisplayedValues == null) {
             float maxDigitWidth = 0;
             for (int i = 0; i <= 9; i++) {
-                final float digitWidth = mSelectorWheelPaint.measureText(String.valueOf(i));
+                final float digitWidth = mSelectorWheelPaint.measureText(formatNumberWithLocale(i));
                 if (digitWidth > maxDigitWidth) {
                     maxDigitWidth = digitWidth;
                 }
@@ -1336,6 +1361,14 @@
             // Allow text entry rather than strictly numeric entry.
             mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT
                     | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
+            // Make sure the min, max, respect the size of the displayed
+            // values. This will take care of the current value as well.
+            if (getMinValue() >= displayedValues.length) {
+                setMinValue(0);
+            }
+            if (getMaxValue() >= displayedValues.length) {
+                setMaxValue(displayedValues.length - 1);
+            }
         } else {
             mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
         }
@@ -1417,19 +1450,6 @@
     }
 
     @Override
-    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
-        // We do not want the real descendant to be considered focus search
-        // since it is managed by the accessibility node provider.
-        if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
-            if (isAccessibilityFocusable()) {
-                views.add(this);
-                return;
-            }
-        }
-        super.addFocusables(views, direction, focusableMode);
-    }
-
-    @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
         event.setClassName(NumberPicker.class.getName());
@@ -1702,7 +1722,7 @@
     }
 
     private String formatNumber(int value) {
-        return (mFormatter != null) ? mFormatter.format(value) : String.valueOf(value);
+        return (mFormatter != null) ? mFormatter.format(value) : formatNumberWithLocale(value);
     }
 
     private void validateInputTextView(View v) {
@@ -1862,6 +1882,20 @@
     }
 
     /**
+     * The numbers accepted by the input text's {@link Filter}
+     */
+    private static final char[] DIGIT_CHARACTERS = new char[] {
+            // Latin digits are the common case
+            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+            // Arabic-Indic
+            '\u0660', '\u0661', '\u0662', '\u0663', '\u0664', '\u0665', '\u0666', '\u0667', '\u0668'
+            , '\u0669',
+            // Extended Arabic-Indic
+            '\u06f0', '\u06f1', '\u06f2', '\u06f3', '\u06f4', '\u06f5', '\u06f6', '\u06f7', '\u06f8'
+            , '\u06f9'
+    };
+
+    /**
      * Filter for accepting only valid indices or prefixes of the string
      * representation of valid indices.
      */
@@ -2297,78 +2331,6 @@
             return super.performAction(virtualViewId, action, arguments);
         }
 
-        @Override
-        public AccessibilityNodeInfo findAccessibilityFocus(int virtualViewId) {
-            return createAccessibilityNodeInfo(mAccessibilityFocusedView);
-        }
-
-        @Override
-        public AccessibilityNodeInfo accessibilityFocusSearch(int direction, int virtualViewId) {
-            switch (direction) {
-                case View.ACCESSIBILITY_FOCUS_DOWN:
-                case View.ACCESSIBILITY_FOCUS_FORWARD: {
-                    switch (mAccessibilityFocusedView) {
-                        case UNDEFINED: {
-                            return createAccessibilityNodeInfo(View.NO_ID);
-                        }
-                        case View.NO_ID: {
-                            if (hasVirtualDecrementButton()) {
-                                return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_DECREMENT);
-                            }
-                        }
-                        //$FALL-THROUGH$
-                        case VIRTUAL_VIEW_ID_DECREMENT: {
-                            return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INPUT);
-                        }
-                        case VIRTUAL_VIEW_ID_INPUT: {
-                            if (hasVirtualIncrementButton()) {
-                                return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INCREMENT);
-                            }
-                        }
-                        //$FALL-THROUGH$
-                        case VIRTUAL_VIEW_ID_INCREMENT: {
-                            View nextFocus = NumberPicker.this.focusSearch(direction);
-                            if (nextFocus != null) {
-                                return nextFocus.createAccessibilityNodeInfo();
-                            }
-                            return null;
-                        }
-                    }
-                } break;
-                case View.ACCESSIBILITY_FOCUS_UP:
-                case View.ACCESSIBILITY_FOCUS_BACKWARD: {
-                    switch (mAccessibilityFocusedView) {
-                        case UNDEFINED: {
-                            return createAccessibilityNodeInfo(View.NO_ID);
-                        }
-                        case View.NO_ID: {
-                            if (hasVirtualIncrementButton()) {
-                                return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INCREMENT);
-                            }
-                        }
-                        //$FALL-THROUGH$
-                        case VIRTUAL_VIEW_ID_INCREMENT: {
-                            return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INPUT);
-                        }
-                        case VIRTUAL_VIEW_ID_INPUT: {
-                            if (hasVirtualDecrementButton()) {
-                                return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_DECREMENT);
-                            }
-                        }
-                        //$FALL-THROUGH$
-                        case VIRTUAL_VIEW_ID_DECREMENT: {
-                            View nextFocus = NumberPicker.this.focusSearch(direction);
-                            if (nextFocus != null) {
-                                return nextFocus.createAccessibilityNodeInfo();
-                            }
-                            return null;
-                        }
-                    }
-                } break;
-            }
-            return null;
-        }
-
         public void sendAccessibilityEventForVirtualView(int virtualViewId, int eventType) {
             switch (virtualViewId) {
                 case VIRTUAL_VIEW_ID_DECREMENT: {
@@ -2390,22 +2352,26 @@
         }
 
         private void sendAccessibilityEventForVirtualText(int eventType) {
-            AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
-            mInputText.onInitializeAccessibilityEvent(event);
-            mInputText.onPopulateAccessibilityEvent(event);
-            event.setSource(NumberPicker.this, VIRTUAL_VIEW_ID_INPUT);
-            requestSendAccessibilityEvent(NumberPicker.this, event);
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
+                mInputText.onInitializeAccessibilityEvent(event);
+                mInputText.onPopulateAccessibilityEvent(event);
+                event.setSource(NumberPicker.this, VIRTUAL_VIEW_ID_INPUT);
+                requestSendAccessibilityEvent(NumberPicker.this, event);
+            }
         }
 
         private void sendAccessibilityEventForVirtualButton(int virtualViewId, int eventType,
                 String text) {
-            AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
-            event.setClassName(Button.class.getName());
-            event.setPackageName(mContext.getPackageName());
-            event.getText().add(text);
-            event.setEnabled(NumberPicker.this.isEnabled());
-            event.setSource(NumberPicker.this, virtualViewId);
-            requestSendAccessibilityEvent(NumberPicker.this, event);
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
+                event.setClassName(Button.class.getName());
+                event.setPackageName(mContext.getPackageName());
+                event.getText().add(text);
+                event.setEnabled(NumberPicker.this.isEnabled());
+                event.setSource(NumberPicker.this, virtualViewId);
+                requestSendAccessibilityEvent(NumberPicker.this, event);
+            }
         }
 
         private void findAccessibilityNodeInfosByTextInChild(String searchedLowerCase,
@@ -2506,14 +2472,22 @@
             info.setParent((View) getParentForAccessibility());
             info.setEnabled(NumberPicker.this.isEnabled());
             info.setScrollable(true);
+
+            final float applicationScale =
+                getContext().getResources().getCompatibilityInfo().applicationScale;
+
             Rect boundsInParent = mTempRect;
             boundsInParent.set(left, top, right, bottom);
+            boundsInParent.scale(applicationScale);
             info.setBoundsInParent(boundsInParent);
+
             info.setVisibleToUser(isVisibleToUser());
+
             Rect boundsInScreen = boundsInParent;
             int[] locationOnScreen = mTempArray;
             getLocationOnScreen(locationOnScreen);
             boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]);
+            boundsInScreen.scale(applicationScale);
             info.setBoundsInScreen(boundsInScreen);
 
             if (mAccessibilityFocusedView != View.NO_ID) {
@@ -2566,4 +2540,8 @@
             return null;
         }
     }
+
+    static private String formatNumberWithLocale(int value) {
+        return String.format(Locale.getDefault(), "%d", value);
+    }
 }
diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java
index 1c72a0d..f218199 100644
--- a/core/java/android/widget/OverScroller.java
+++ b/core/java/android/widget/OverScroller.java
@@ -72,10 +72,8 @@
     public OverScroller(Context context, Interpolator interpolator, boolean flywheel) {
         mInterpolator = interpolator;
         mFlywheel = flywheel;
-        mScrollerX = new SplineOverScroller();
-        mScrollerY = new SplineOverScroller();
-
-        SplineOverScroller.initFromContext(context);
+        mScrollerX = new SplineOverScroller(context);
+        mScrollerY = new SplineOverScroller(context);
     }
 
     /**
@@ -585,8 +583,8 @@
         // Constant gravity value, used in the deceleration phase.
         private static final float GRAVITY = 2000.0f;
 
-        // A device specific coefficient adjusted to physical values.
-        private static float PHYSICAL_COEF;
+        // A context-specific coefficient adjusted to physical values.
+        private float mPhysicalCoeff;
 
         private static float DECELERATION_RATE = (float) (Math.log(0.78) / Math.log(0.9));
         private static final float INFLEXION = 0.35f; // Tension lines cross at (INFLEXION, 1)
@@ -636,20 +634,17 @@
             SPLINE_POSITION[NB_SAMPLES] = SPLINE_TIME[NB_SAMPLES] = 1.0f;
         }
 
-        static void initFromContext(Context context) {
-            final float ppi = context.getResources().getDisplayMetrics().density * 160.0f;
-            PHYSICAL_COEF = SensorManager.GRAVITY_EARTH // g (m/s^2)
-                    * 39.37f // inch/meter
-                    * ppi
-                    * 0.84f; // look and feel tuning
-        }
-
         void setFriction(float friction) {
             mFlingFriction = friction;
         }
 
-        SplineOverScroller() {
+        SplineOverScroller(Context context) {
             mFinished = true;
+            final float ppi = context.getResources().getDisplayMetrics().density * 160.0f;
+            mPhysicalCoeff = SensorManager.GRAVITY_EARTH // g (m/s^2)
+                    * 39.37f // inch/meter
+                    * ppi
+                    * 0.84f; // look and feel tuning
         }
 
         void updateScroll(float q) {
@@ -785,13 +780,13 @@
         }
 
         private double getSplineDeceleration(int velocity) {
-            return Math.log(INFLEXION * Math.abs(velocity) / (mFlingFriction * PHYSICAL_COEF));
+            return Math.log(INFLEXION * Math.abs(velocity) / (mFlingFriction * mPhysicalCoeff));
         }
 
         private double getSplineFlingDistance(int velocity) {
             final double l = getSplineDeceleration(velocity);
             final double decelMinusOne = DECELERATION_RATE - 1.0;
-            return mFlingFriction * PHYSICAL_COEF * Math.exp(DECELERATION_RATE / decelMinusOne * l);
+            return mFlingFriction * mPhysicalCoeff * Math.exp(DECELERATION_RATE / decelMinusOne * l);
         }
 
         /* Returns the duration, expressed in milliseconds */
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index f442912..b71649a 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -142,6 +142,8 @@
         };
     private int mAnchorXoff, mAnchorYoff;
 
+    private boolean mPopupViewInitialLayoutDirectionInherited;
+
     /**
      * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
      *
@@ -835,7 +837,7 @@
        
         preparePopup(p);
         if (gravity == Gravity.NO_GRAVITY) {
-            gravity = Gravity.TOP | Gravity.LEFT;
+            gravity = Gravity.TOP | Gravity.START;
         }
         p.gravity = gravity;
         p.x = x;
@@ -968,6 +970,8 @@
         } else {
             mPopupView = mContentView;
         }
+        mPopupViewInitialLayoutDirectionInherited =
+                (mPopupView.getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT);
         mPopupWidth = p.width;
         mPopupHeight = p.height;
     }
@@ -985,9 +989,19 @@
             p.packageName = mContext.getPackageName();
         }
         mPopupView.setFitsSystemWindows(mLayoutInsetDecor);
+        setLayoutDirectionFromAnchor();
         mWindowManager.addView(mPopupView, p);
     }
 
+    private void setLayoutDirectionFromAnchor() {
+        if (mAnchor != null) {
+            View anchor = mAnchor.get();
+            if (anchor != null && mPopupViewInitialLayoutDirectionInherited) {
+                mPopupView.setLayoutDirection(anchor.getLayoutDirection());
+            }
+        }
+    }
+
     /**
      * <p>Generate the layout parameters for the popup window.</p>
      *
@@ -1003,7 +1017,7 @@
         // screen. The view is then positioned to the appropriate location
         // by setting the x and y offsets to match the anchor's bottom
         // left corner
-        p.gravity = Gravity.LEFT | Gravity.TOP;
+        p.gravity = Gravity.START | Gravity.TOP;
         p.width = mLastWidth = mWidth;
         p.height = mLastHeight = mHeight;
         if (mBackground != null) {
@@ -1100,7 +1114,7 @@
         
         boolean onTop = false;
 
-        p.gravity = Gravity.LEFT | Gravity.TOP;
+        p.gravity = Gravity.START | Gravity.TOP;
         
         anchor.getLocationOnScreen(mScreenLocation);
         final Rect displayFrame = new Rect();
@@ -1134,7 +1148,7 @@
             onTop = (displayFrame.bottom - mScreenLocation[1] - anchor.getHeight() - yoff) <
                     (mScreenLocation[1] - yoff - displayFrame.top);
             if (onTop) {
-                p.gravity = Gravity.LEFT | Gravity.BOTTOM;
+                p.gravity = Gravity.START | Gravity.BOTTOM;
                 p.y = root.getHeight() - mDrawingLocation[1] + yoff;
             } else {
                 p.y = mDrawingLocation[1] + anchor.getHeight() + yoff;
@@ -1304,8 +1318,9 @@
             p.flags = newFlags;
             update = true;
         }
-        
+
         if (update) {
+            setLayoutDirectionFromAnchor();
             mWindowManager.updateViewLayout(mPopupView, p);
         }
     }
@@ -1406,6 +1421,7 @@
         }
 
         if (update) {
+            setLayoutDirectionFromAnchor();
             mWindowManager.updateViewLayout(mPopupView, p);
         }
     }
@@ -1482,7 +1498,7 @@
         } else {
             updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff));            
         }
-        
+
         update(p.x, p.y, width, height, x != p.x || y != p.y);
     }
 
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index f3f18d5..ea50e2e 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -478,6 +478,9 @@
             d.setCallback(this);
         }
         mIndeterminateDrawable = d;
+        if (mIndeterminateDrawable != null && canResolveLayoutDirection()) {
+            mIndeterminateDrawable.setLayoutDirection(getLayoutDirection());
+        }
         if (mIndeterminate) {
             mCurrentDrawable = d;
             postInvalidate();
@@ -517,6 +520,9 @@
 
         if (d != null) {
             d.setCallback(this);
+            if (canResolveLayoutDirection()) {
+                d.setLayoutDirection(getLayoutDirection());
+            }
 
             // Make sure the ProgressBar is always tall enough
             int drawableHeight = d.getMinimumHeight();
@@ -559,6 +565,23 @@
         if (mIndeterminateDrawable != null) mIndeterminateDrawable.jumpToCurrentState();
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public void onResolveDrawables(int layoutDirection) {
+        final Drawable d = mCurrentDrawable;
+        if (d != null) {
+            d.setLayoutDirection(layoutDirection);
+        }
+        if (mIndeterminateDrawable != null) {
+            mIndeterminateDrawable.setLayoutDirection(layoutDirection);
+        }
+        if (mProgressDrawable != null) {
+            mProgressDrawable.setLayoutDirection(layoutDirection);
+        }
+    }
+
     @Override
     public void postInvalidate() {
         if (!mNoInvalidate) {
@@ -648,6 +671,9 @@
 
             if (d instanceof LayerDrawable) {
                 progressDrawable = ((LayerDrawable) d).findDrawableByLayerId(id);
+                if (progressDrawable != null && canResolveLayoutDirection()) {
+                    progressDrawable.setLayoutDirection(getLayoutDirection());
+                }
             }
 
             final int level = (int) (scale * MAX_LEVEL);
@@ -975,24 +1001,19 @@
         }
     }
 
-    /**
-     * @hide
-     */
-    @Override
-    public int getResolvedLayoutDirection(Drawable who) {
-        return (who == mProgressDrawable || who == mIndeterminateDrawable) ?
-            getResolvedLayoutDirection() : super.getResolvedLayoutDirection(who);
-    }
-
     @Override
     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
         updateDrawableBounds(w, h);
     }
 
     private void updateDrawableBounds(int w, int h) {
-        // onDraw will translate the canvas so we draw starting at 0,0
-        int right = w - mPaddingRight - mPaddingLeft;
-        int bottom = h - mPaddingBottom - mPaddingTop;
+        // onDraw will translate the canvas so we draw starting at 0,0.
+        // Subtract out padding for the purposes of the calculations below.
+        w -= mPaddingRight + mPaddingLeft;
+        h -= mPaddingTop + mPaddingBottom;
+
+        int right = w;
+        int bottom = h;
         int top = 0;
         int left = 0;
 
@@ -1019,6 +1040,11 @@
                     }
                 }
             }
+            if (isLayoutRtl()) {
+                int tempLeft = left;
+                left = w - right;
+                right = w - tempLeft;
+            }
             mIndeterminateDrawable.setBounds(left, top, right, bottom);
         }
         
@@ -1036,7 +1062,12 @@
             // Translate canvas so a indeterminate circular progress bar with padding
             // rotates properly in its animation
             canvas.save();
-            canvas.translate(mPaddingLeft, mPaddingTop);
+            if(isLayoutRtl()) {
+                canvas.translate(getWidth() - mPaddingRight, mPaddingTop);
+                canvas.scale(-1.0f, 1.0f);
+            } else {
+                canvas.translate(mPaddingLeft, mPaddingTop);
+            }
             long time = getDrawingTime();
             if (mHasAnimation) {
                 mAnimation.getTransformation(time, mTransformation);
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index f217c9c..78d05b0 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -376,7 +376,7 @@
                 int id = child.getId();
                 // generates an id if it's missing
                 if (id == View.NO_ID) {
-                    id = child.hashCode();
+                    id = View.generateViewId();
                     child.setId(id);
                 }
                 ((RadioButton) child).setOnCheckedChangeWidgetListener(
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 569cf99..e52e84d 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -149,8 +149,34 @@
      * bounds of its RelativeLayout parent.
      */
     public static final int CENTER_VERTICAL          = 15;
+    /**
+     * Rule that aligns a child's end edge with another child's start edge.
+     */
+    public static final int START_OF                 = 16;
+    /**
+     * Rule that aligns a child's start edge with another child's end edge.
+     */
+    public static final int END_OF                   = 17;
+    /**
+     * Rule that aligns a child's start edge with another child's start edge.
+     */
+    public static final int ALIGN_START              = 18;
+    /**
+     * Rule that aligns a child's end edge with another child's end edge.
+     */
+    public static final int ALIGN_END                = 19;
+    /**
+     * Rule that aligns the child's start edge with its RelativeLayout
+     * parent's start edge.
+     */
+    public static final int ALIGN_PARENT_START       = 20;
+    /**
+     * Rule that aligns the child's end edge with its RelativeLayout
+     * parent's end edge.
+     */
+    public static final int ALIGN_PARENT_END         = 21;
 
-    private static final int VERB_COUNT              = 16;
+    private static final int VERB_COUNT              = 22;
 
 
     private static final int[] RULES_VERTICAL = {
@@ -158,13 +184,13 @@
     };
 
     private static final int[] RULES_HORIZONTAL = {
-            LEFT_OF, RIGHT_OF, ALIGN_LEFT, ALIGN_RIGHT
+            LEFT_OF, RIGHT_OF, ALIGN_LEFT, ALIGN_RIGHT, START_OF, END_OF, ALIGN_START, ALIGN_END
     };
 
     private View mBaselineView = null;
     private boolean mHasBaselineAlignedChild;
 
-    private int mGravity = Gravity.LEFT | Gravity.TOP;
+    private int mGravity = Gravity.START | Gravity.TOP;
     private final Rect mContentBounds = new Rect();
     private final Rect mSelfBounds = new Rect();
     private int mIgnoreGravity;
@@ -204,7 +230,7 @@
 
     /**
      * Defines which View is ignored when the gravity is applied. This setting has no
-     * effect if the gravity is <code>Gravity.LEFT | Gravity.TOP</code>.
+     * effect if the gravity is <code>Gravity.START | Gravity.TOP</code>.
      *
      * @param viewId The id of the View to be ignored by gravity, or 0 if no View
      *        should be ignored.
@@ -234,7 +260,7 @@
 
     /**
      * Describes how the child views are positioned. Defaults to
-     * <code>Gravity.LEFT | Gravity.TOP</code>.
+     * <code>Gravity.START | Gravity.TOP</code>.
      *
      * <p>Note that since RelativeLayout considers the positioning of each child
      * relative to one another to be significant, setting gravity will affect
@@ -369,7 +395,7 @@
 
         View ignore = null;
         int gravity = mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
-        final boolean horizontalGravity = gravity != Gravity.LEFT && gravity != 0;
+        final boolean horizontalGravity = gravity != Gravity.START && gravity != 0;
         gravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
         final boolean verticalGravity = gravity != Gravity.TOP && gravity != 0;
 
@@ -457,6 +483,8 @@
             }
         }
 
+        final int layoutDirection = getLayoutDirection();
+
         if (isWrapContentWidth) {
             // Width already has left padding in it since it was calculated by looking at
             // the right of each child view
@@ -474,7 +502,7 @@
                     View child = getChildAt(i);
                     if (child.getVisibility() != GONE) {
                         LayoutParams params = (LayoutParams) child.getLayoutParams();
-                        final int[] rules = params.getRules();
+                        final int[] rules = params.getRules(layoutDirection);
                         if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_HORIZONTAL] != 0) {
                             centerHorizontal(child, params, width);
                         } else if (rules[ALIGN_PARENT_RIGHT] != 0) {
@@ -504,7 +532,7 @@
                     View child = getChildAt(i);
                     if (child.getVisibility() != GONE) {
                         LayoutParams params = (LayoutParams) child.getLayoutParams();
-                        final int[] rules = params.getRules();
+                        final int[] rules = params.getRules(layoutDirection);
                         if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) {
                             centerVertical(child, params, height);
                         } else if (rules[ALIGN_PARENT_BOTTOM] != 0) {
@@ -523,7 +551,6 @@
                     height - mPaddingBottom);
 
             final Rect contentBounds = mContentBounds;
-            final int layoutDirection = getResolvedLayoutDirection();
             Gravity.apply(mGravity, right - left, bottom - top, selfBounds, contentBounds,
                     layoutDirection);
 
@@ -551,7 +578,8 @@
     }
 
     private void alignBaseline(View child, LayoutParams params) {
-        int[] rules = params.getRules();
+        final int layoutDirection = getLayoutDirection();
+        int[] rules = params.getRules(layoutDirection);
         int anchorBaseline = getRelatedViewBaseline(rules, ALIGN_BASELINE);
 
         if (anchorBaseline != -1) {
@@ -619,7 +647,7 @@
 
     /**
      * Get a measure spec that accounts for all of the constraints on this view.
-     * This includes size contstraints imposed by the RelativeLayout as well as
+     * This includes size constraints imposed by the RelativeLayout as well as
      * the View's desired dimension.
      *
      * @param childStart The left or top field of the child's layout params
@@ -672,7 +700,7 @@
                     childSpecSize = childSize;
                 }
             } else if (childSize == LayoutParams.MATCH_PARENT) {
-                // Child wanted to be as big as possible. Give all availble
+                // Child wanted to be as big as possible. Give all available
                 // space
                 childSpecMode = MeasureSpec.EXACTLY;
                 childSpecSize = maxAvailable;
@@ -681,7 +709,7 @@
                 // to communicate available space if we know
                 // our max size
                 if (maxAvailable >= 0) {
-                    // We have a maxmum size in this dimension.
+                    // We have a maximum size in this dimension.
                     childSpecMode = MeasureSpec.AT_MOST;
                     childSpecSize = maxAvailable;
                 } else {
@@ -699,7 +727,8 @@
     private boolean positionChildHorizontal(View child, LayoutParams params, int myWidth,
             boolean wrapContent) {
 
-        int[] rules = params.getRules();
+        final int layoutDirection = getLayoutDirection();
+        int[] rules = params.getRules(layoutDirection);
 
         if (params.mLeft < 0 && params.mRight >= 0) {
             // Right is fixed, but left varies
@@ -718,11 +747,18 @@
                 }
                 return true;
             } else {
-                params.mLeft = mPaddingLeft + params.leftMargin;
-                params.mRight = params.mLeft + child.getMeasuredWidth();
+                // This is the default case. For RTL we start from the right and for LTR we start
+                // from the left. This will give LEFT/TOP for LTR and RIGHT/TOP for RTL.
+                if (isLayoutRtl()) {
+                    params.mRight = myWidth - mPaddingRight- params.rightMargin;
+                    params.mLeft = params.mRight - child.getMeasuredWidth();
+                } else {
+                    params.mLeft = mPaddingLeft + params.leftMargin;
+                    params.mRight = params.mLeft + child.getMeasuredWidth();
+                }
             }
         }
-        return rules[ALIGN_PARENT_RIGHT] != 0;
+        return rules[ALIGN_PARENT_END] != 0;
     }
 
     private boolean positionChildVertical(View child, LayoutParams params, int myHeight,
@@ -755,7 +791,8 @@
     }
 
     private void applyHorizontalSizeRules(LayoutParams childParams, int myWidth) {
-        int[] rules = childParams.getRules();
+        final int layoutDirection = getLayoutDirection();
+        int[] rules = childParams.getRules(layoutDirection);
         RelativeLayout.LayoutParams anchorParams;
 
         // -1 indicated a "soft requirement" in that direction. For example:
@@ -946,7 +983,6 @@
                 RelativeLayout.LayoutParams st =
                         (RelativeLayout.LayoutParams) child.getLayoutParams();
                 child.layout(st.mLeft, st.mTop, st.mRight, st.mBottom);
-
             }
         }
     }
@@ -1061,6 +1097,12 @@
      * @attr ref android.R.styleable#RelativeLayout_Layout_layout_centerInParent
      * @attr ref android.R.styleable#RelativeLayout_Layout_layout_centerHorizontal
      * @attr ref android.R.styleable#RelativeLayout_Layout_layout_centerVertical
+     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_toStartOf
+     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_toEndOf
+     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignStart
+     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignEnd
+     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentStart
+     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentEnd
      */
     public static class LayoutParams extends ViewGroup.MarginLayoutParams {
         @ViewDebug.ExportedProperty(category = "layout", resolveId = true, indexMapping = {
@@ -1079,15 +1121,28 @@
             @ViewDebug.IntToString(from = CENTER_IN_PARENT,    to = "center"),
             @ViewDebug.IntToString(from = CENTER_VERTICAL,     to = "centerVertical"),
             @ViewDebug.IntToString(from = LEFT_OF,             to = "leftOf"),
-            @ViewDebug.IntToString(from = RIGHT_OF,            to = "rightOf")
+            @ViewDebug.IntToString(from = RIGHT_OF,            to = "rightOf"),
+            @ViewDebug.IntToString(from = ALIGN_START,         to = "alignStart"),
+            @ViewDebug.IntToString(from = ALIGN_END,           to = "alignEnd"),
+            @ViewDebug.IntToString(from = ALIGN_PARENT_START,  to = "alignParentStart"),
+            @ViewDebug.IntToString(from = ALIGN_PARENT_END,    to = "alignParentEnd"),
+            @ViewDebug.IntToString(from = START_OF,            to = "startOf"),
+            @ViewDebug.IntToString(from = END_OF,              to = "endOf")
         }, mapping = {
             @ViewDebug.IntToString(from = TRUE, to = "true"),
             @ViewDebug.IntToString(from = 0,    to = "false/NO_ID")
         })
+
         private int[] mRules = new int[VERB_COUNT];
+        private int[] mInitialRules = new int[VERB_COUNT];
 
         private int mLeft, mTop, mRight, mBottom;
 
+        private int mStart = DEFAULT_RELATIVE;
+        private int mEnd = DEFAULT_RELATIVE;
+
+        private boolean mRulesChanged = false;
+
         /**
          * When true, uses the parent as the anchor if the anchor doesn't exist or if
          * the anchor's visibility is GONE.
@@ -1102,6 +1157,7 @@
                     com.android.internal.R.styleable.RelativeLayout_Layout);
 
             final int[] rules = mRules;
+            final int[] initialRules = mInitialRules;
 
             final int N = a.getIndexCount();
             for (int i = 0; i < N; i++) {
@@ -1158,9 +1214,31 @@
                     case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerVertical:
                         rules[CENTER_VERTICAL] = a.getBoolean(attr, false) ? TRUE : 0;
                        break;
+                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toStartOf:
+                        rules[START_OF] = a.getResourceId(attr, 0);
+                        break;
+                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toEndOf:
+                        rules[END_OF] = a.getResourceId(attr, 0);
+                        break;
+                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignStart:
+                        rules[ALIGN_START] = a.getResourceId(attr, 0);
+                        break;
+                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignEnd:
+                        rules[ALIGN_END] = a.getResourceId(attr, 0);
+                        break;
+                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentStart:
+                        rules[ALIGN_PARENT_START] = a.getBoolean(attr, false) ? TRUE : 0;
+                        break;
+                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentEnd:
+                        rules[ALIGN_PARENT_END] = a.getBoolean(attr, false) ? TRUE : 0;
+                        break;
                 }
             }
 
+            for (int n = LEFT_OF; n < VERB_COUNT; n++) {
+                initialRules[n] = rules[n];
+            }
+
             a.recycle();
         }
 
@@ -1192,7 +1270,7 @@
          * Adds a layout rule to be interpreted by the RelativeLayout. This
          * method should only be used for constraints that don't refer to another sibling
          * (e.g., CENTER_IN_PARENT) or take a boolean value ({@link RelativeLayout#TRUE}
-         * for true or - for false). To specify a verb that takes a subject, use
+         * for true or 0 for false). To specify a verb that takes a subject, use
          * {@link #addRule(int, int)} instead.
          *
          * @param verb One of the verbs defined by
@@ -1202,6 +1280,8 @@
          */
         public void addRule(int verb) {
             mRules[verb] = TRUE;
+            mInitialRules[verb] = TRUE;
+            mRulesChanged = true;
         }
 
         /**
@@ -1220,12 +1300,88 @@
          */
         public void addRule(int verb, int anchor) {
             mRules[verb] = anchor;
+            mInitialRules[verb] = anchor;
+            mRulesChanged = true;
+        }
+
+        /**
+         * Removes a layout rule to be interpreted by the RelativeLayout.
+         *
+         * @param verb One of the verbs defined by
+         *        {@link android.widget.RelativeLayout RelativeLayout}, such as
+         *         ALIGN_WITH_PARENT_LEFT.
+         * @see #addRule(int)
+         * @see #addRule(int, int)
+         */
+        public void removeRule(int verb) {
+            mRules[verb] = 0;
+            mInitialRules[verb] = 0;
+            mRulesChanged = true;
+        }
+
+        private boolean hasRelativeRules() {
+            return (mInitialRules[START_OF] != 0 || mInitialRules[END_OF] != 0 ||
+                    mInitialRules[ALIGN_START] != 0 || mInitialRules[ALIGN_END] != 0 ||
+                    mInitialRules[ALIGN_PARENT_START] != 0 || mInitialRules[ALIGN_PARENT_END] != 0);
+        }
+
+        private void resolveRules(int layoutDirection) {
+            final boolean isLayoutRtl = (layoutDirection == View.LAYOUT_DIRECTION_RTL);
+            // Reset to initial state
+            for (int n = LEFT_OF; n < VERB_COUNT; n++) {
+                mRules[n] = mInitialRules[n];
+            }
+            // Apply rules depending on direction
+            if (mRules[ALIGN_START] != 0) {
+                mRules[isLayoutRtl ? ALIGN_RIGHT : ALIGN_LEFT] = mRules[ALIGN_START];
+            }
+            if (mRules[ALIGN_END] != 0) {
+                mRules[isLayoutRtl ? ALIGN_LEFT : ALIGN_RIGHT] = mRules[ALIGN_END];
+            }
+            if (mRules[START_OF] != 0) {
+                mRules[isLayoutRtl ? RIGHT_OF : LEFT_OF] = mRules[START_OF];
+            }
+            if (mRules[END_OF] != 0) {
+                mRules[isLayoutRtl ? LEFT_OF : RIGHT_OF] = mRules[END_OF];
+            }
+            if (mRules[ALIGN_PARENT_START] != 0) {
+                mRules[isLayoutRtl ? ALIGN_PARENT_RIGHT : ALIGN_PARENT_LEFT] = mRules[ALIGN_PARENT_START];
+            }
+            if (mRules[ALIGN_PARENT_END] != 0) {
+                mRules[isLayoutRtl ? ALIGN_PARENT_LEFT : ALIGN_PARENT_RIGHT] = mRules[ALIGN_PARENT_END];
+            }
+            mRulesChanged = false;
         }
 
         /**
          * Retrieves a complete list of all supported rules, where the index is the rule
          * verb, and the element value is the value specified, or "false" if it was never
-         * set.
+         * set. If there are relative rules defined (*_START / *_END), they will be resolved
+         * depending on the layout direction.
+         *
+         * @param layoutDirection the direction of the layout.
+         *                        Should be either {@link View#LAYOUT_DIRECTION_LTR}
+         *                        or {@link View#LAYOUT_DIRECTION_RTL}
+         * @return the supported rules
+         * @see #addRule(int, int)
+         *
+         * @hide
+         */
+        public int[] getRules(int layoutDirection) {
+            if (hasRelativeRules() &&
+                    (mRulesChanged || layoutDirection != getLayoutDirection())) {
+                resolveRules(layoutDirection);
+                if (layoutDirection != getLayoutDirection()) {
+                    setLayoutDirection(layoutDirection);
+                }
+            }
+            return mRules;
+        }
+
+        /**
+         * Retrieves a complete list of all supported rules, where the index is the rule
+         * verb, and the element value is the value specified, or "false" if it was never
+         * set. There will be no resolution of relative rules done.
          *
          * @return the supported rules
          * @see #addRule(int, int)
@@ -1233,6 +1389,24 @@
         public int[] getRules() {
             return mRules;
         }
+
+        @Override
+        public void resolveLayoutDirection(int layoutDirection) {
+            final boolean isLayoutRtl = isLayoutRtl();
+            if (isLayoutRtl) {
+                if (mStart != DEFAULT_RELATIVE) mRight = mStart;
+                if (mEnd != DEFAULT_RELATIVE) mLeft = mEnd;
+            } else {
+                if (mStart != DEFAULT_RELATIVE) mLeft = mStart;
+                if (mEnd != DEFAULT_RELATIVE) mRight = mEnd;
+            }
+
+            if (hasRelativeRules() && layoutDirection != getLayoutDirection()) {
+                resolveRules(layoutDirection);
+            }
+            // This will set the layout direction
+            super.resolveLayoutDirection(layoutDirection);
+        }
     }
 
     private static class DependencyGraph {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 4710798f..8d1be53 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -23,7 +23,6 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
@@ -35,9 +34,9 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.LayoutInflater.Filter;
 import android.view.RemotableViewMethod;
@@ -52,6 +51,7 @@
 import java.lang.annotation.Target;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.HashMap;
 
 
 /**
@@ -61,9 +61,9 @@
  * the content of the inflated hierarchy.
  */
 public class RemoteViews implements Parcelable, Filter {
-    
+
     private static final String LOG_TAG = "RemoteViews";
-    
+
     /**
      * The intent extra that contains the appWidgetId.
      * @hide
@@ -71,11 +71,18 @@
     static final String EXTRA_REMOTEADAPTER_APPWIDGET_ID = "remoteAdapterAppWidgetId";
 
     /**
-     * The package name of the package containing the layout 
+     * User that these views should be applied as. Requires
+     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} when
+     * crossing user boundaries.
+     */
+    private UserHandle mUser = android.os.Process.myUserHandle();
+
+    /**
+     * The package name of the package containing the layout
      * resource. (Added to the parcel)
      */
     private final String mPackage;
-    
+
     /**
      * The resource ID of the layout file. (Added to the parcel)
      */
@@ -86,7 +93,7 @@
      * inflated
      */
     private ArrayList<Action> mActions;
-    
+
     /**
      * A class to keep track of memory usage by this RemoteViews
      */
@@ -187,6 +194,10 @@
         public abstract void apply(View root, ViewGroup rootParent,
                 OnClickHandler handler) throws ActionException;
 
+        public static final int MERGE_REPLACE = 0;
+        public static final int MERGE_APPEND = 1;
+        public static final int MERGE_IGNORE = 2;
+
         public int describeContents() {
             return 0;
         }
@@ -203,6 +214,67 @@
         public void setBitmapCache(BitmapCache bitmapCache) {
             // Do nothing
         }
+
+        public int mergeBehavior() {
+            return MERGE_REPLACE;
+        }
+
+        public abstract String getActionName();
+
+        public String getUniqueKey() {
+            return (getActionName() + viewId);
+        }
+
+        int viewId;
+    }
+
+    /**
+     * Merges the passed RemoteViews actions with this RemoteViews actions according to
+     * action-specific merge rules.
+     * 
+     * @param newRv
+     * 
+     * @hide
+     */
+    public void mergeRemoteViews(RemoteViews newRv) {
+        if (newRv == null) return;
+        // We first copy the new RemoteViews, as the process of merging modifies the way the actions
+        // reference the bitmap cache. We don't want to modify the object as it may need to
+        // be merged and applied multiple times.
+        RemoteViews copy = newRv.clone();
+
+        HashMap<String, Action> map = new HashMap<String, Action>();
+        if (mActions == null) {
+            mActions = new ArrayList<Action>();
+        }
+
+        int count = mActions.size();
+        for (int i = 0; i < count; i++) {
+            Action a = mActions.get(i);
+            map.put(a.getUniqueKey(), a);
+        }
+
+        ArrayList<Action> newActions = copy.mActions;
+        if (newActions == null) return;
+        count = newActions.size();
+        for (int i = 0; i < count; i++) {
+            Action a = newActions.get(i);
+            String key = newActions.get(i).getUniqueKey();
+            int mergeBehavior = newActions.get(i).mergeBehavior();
+            if (map.containsKey(key) && mergeBehavior == Action.MERGE_REPLACE) {
+                mActions.remove(map.get(key));
+                map.remove(key);
+            }
+
+            // If the merge behavior is ignore, we don't bother keeping the extra action
+            if (mergeBehavior == Action.MERGE_REPLACE || mergeBehavior == Action.MERGE_APPEND) {
+                mActions.add(a);
+            }
+        }
+
+        // Because pruning can remove the need for bitmaps, we reconstruct the bitmap cache
+        mBitmapCache = new BitmapCache();
+        setBitmapCache(mBitmapCache);
     }
 
     private class SetEmptyView extends Action {
@@ -239,6 +311,10 @@
 
             adapterView.setEmptyView(emptyView);
         }
+
+        public String getActionName() {
+            return "SetEmptyView";
+        }
     }
 
     private class SetOnClickFillInIntent extends Action {
@@ -275,12 +351,12 @@
                     public void onClick(View v) {
                         // Insure that this view is a child of an AdapterView
                         View parent = (View) v.getParent();
-                        while (!(parent instanceof AdapterView<?>)
+                        while (parent != null && !(parent instanceof AdapterView<?>)
                                 && !(parent instanceof AppWidgetHostView)) {
                             parent = (View) parent.getParent();
                         }
 
-                        if (parent instanceof AppWidgetHostView) {
+                        if (parent instanceof AppWidgetHostView || parent == null) {
                             // Somehow they've managed to get this far without having
                             // and AdapterView as a parent.
                             Log.e("RemoteViews", "Collection item doesn't have AdapterView parent");
@@ -316,7 +392,10 @@
             }
         }
 
-        int viewId;
+        public String getActionName() {
+            return "SetOnClickFillInIntent";
+        }
+
         Intent fillInIntent;
 
         public final static int TAG = 9;
@@ -399,7 +478,10 @@
             }
         }
 
-        int viewId;
+        public String getActionName() {
+            return "SetPendingIntentTemplate";
+        }
+
         PendingIntent pendingIntentTemplate;
 
         public final static int TAG = 8;
@@ -447,13 +529,18 @@
             if (target instanceof AbsListView) {
                 AbsListView v = (AbsListView) target;
                 v.setRemoteViewsAdapter(intent);
+                v.setRemoteViewsOnClickHandler(handler);
             } else if (target instanceof AdapterViewAnimator) {
                 AdapterViewAnimator v = (AdapterViewAnimator) target;
                 v.setRemoteViewsAdapter(intent);
+                v.setRemoteViewsOnClickHandler(handler);
             }
         }
 
-        int viewId;
+        public String getActionName() {
+            return "SetRemoteViewsAdapterIntent";
+        }
+
         Intent intent;
 
         public final static int TAG = 10;
@@ -522,13 +609,13 @@
                                     .getCompatibilityInfo().applicationScale;
                             final int[] pos = new int[2];
                             v.getLocationOnScreen(pos);
-    
+
                             final Rect rect = new Rect();
                             rect.left = (int) (pos[0] * appScale + 0.5f);
                             rect.top = (int) (pos[1] * appScale + 0.5f);
                             rect.right = (int) ((pos[0] + v.getWidth()) * appScale + 0.5f);
                             rect.bottom = (int) ((pos[1] + v.getHeight()) * appScale + 0.5f);
-    
+
                             final Intent intent = new Intent();
                             intent.setSourceBounds(rect);
                             handler.onClickHandler(v, pendingIntent, intent);
@@ -539,7 +626,10 @@
             }
         }
 
-        int viewId;
+        public String getActionName() {
+            return "SetOnClickPendingIntent";
+        }
+
         PendingIntent pendingIntent;
 
         public final static int TAG = 1;
@@ -567,7 +657,7 @@
             this.filterMode = mode;
             this.level = level;
         }
-        
+
         public SetDrawableParameters(Parcel parcel) {
             viewId = parcel.readInt();
             targetBackground = parcel.readInt() != 0;
@@ -581,7 +671,7 @@
             }
             level = parcel.readInt();
         }
-        
+
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(TAG);
             dest.writeInt(viewId);
@@ -596,12 +686,12 @@
             }
             dest.writeInt(level);
         }
-        
+
         @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
-            
+
             // Pick the correct drawable to modify for this view
             Drawable targetDrawable = null;
             if (targetBackground) {
@@ -610,7 +700,7 @@
                 ImageView imageView = (ImageView) target;
                 targetDrawable = imageView.getDrawable();
             }
-            
+
             if (targetDrawable != null) {
                 // Perform modifications only if values are set correctly
                 if (alpha != -1) {
@@ -625,7 +715,10 @@
             }
         }
 
-        int viewId;
+        public String getActionName() {
+            return "SetDrawableParameters";
+        }
+
         boolean targetBackground;
         int alpha;
         int colorFilter;
@@ -634,9 +727,8 @@
 
         public final static int TAG = 3;
     }
-    
+
     private class ReflectionActionWithoutParams extends Action {
-        int viewId;
         String methodName;
 
         public final static int TAG = 5;
@@ -688,6 +780,19 @@
                 throw new ActionException(ex);
             }
         }
+
+        public int mergeBehavior() {
+            // we don't need to build up showNext or showPrevious calls
+            if (methodName.equals("showNext") || methodName.equals("showPrevious")) {
+                return MERGE_IGNORE;
+            } else {
+                return MERGE_REPLACE;
+            }
+        }
+
+        public String getActionName() {
+            return "ReflectionActionWithoutParams";
+        }
     }
 
     private static class BitmapCache {
@@ -755,7 +860,6 @@
 
     private class BitmapReflectionAction extends Action {
         int bitmapId;
-        int viewId;
         Bitmap bitmap;
         String methodName;
 
@@ -794,6 +898,10 @@
             bitmapId = bitmapCache.getBitmapId(bitmap);
         }
 
+        public String getActionName() {
+            return "BitmapReflectionAction";
+        }
+
         public final static int TAG = 12;
     }
 
@@ -814,11 +922,12 @@
         static final int STRING = 9;
         static final int CHAR_SEQUENCE = 10;
         static final int URI = 11;
+        // BITMAP actions are never stored in the list of actions. They are only used locally
+        // to implement BitmapReflectionAction, which eliminates duplicates using BitmapCache.
         static final int BITMAP = 12;
         static final int BUNDLE = 13;
         static final int INTENT = 14;
 
-        int viewId;
         String methodName;
         int type;
         Object value;
@@ -938,7 +1047,7 @@
                     out.writeString((String)this.value);
                     break;
                 case CHAR_SEQUENCE:
-                    TextUtils.writeToParcel((CharSequence)this.value, out, flags);   
+                    TextUtils.writeToParcel((CharSequence)this.value, out, flags);
                     break;
                 case URI:
                     out.writeInt(this.value != null ? 1 : 0);
@@ -1041,20 +1150,20 @@
             }
         }
 
-        @Override
-        public void updateMemoryUsageEstimate(MemoryUsageCounter counter) {
-            // We currently only calculate Bitmap memory usage
-            switch (this.type) {
-                case BITMAP:
-                    if (this.value != null) {
-                        final Bitmap b = (Bitmap) this.value;
-                        counter.addBitmapMemory(b);
-                    }
-                    break;
-                default:
-                    break;
+        public int mergeBehavior() {
+            // smoothScrollBy is cumulative, everything else overwites.
+            if (methodName.equals("smoothScrollBy")) {
+                return MERGE_APPEND;
+            } else {
+                return MERGE_REPLACE;
             }
         }
+
+        public String getActionName() {
+            // Each type of reflection action corresponds to a setter, so each should be seen as
+            // unique from the standpoint of merging.
+            return "ReflectionAction" + this.methodName + this.type;
+        }
     }
 
     private void configureRemoteViewsAsChild(RemoteViews rv) {
@@ -1131,7 +1240,14 @@
             }
         }
 
-        int viewId;
+        public String getActionName() {
+            return "ViewGroupAction" + this.nestedViews == null ? "Remove" : "Add";
+        }
+
+        public int mergeBehavior() {
+            return MERGE_APPEND;
+        }
+
         RemoteViews nestedViews;
 
         public final static int TAG = 4;
@@ -1182,7 +1298,10 @@
             }
         }
 
-        int viewId;
+        public String getActionName() {
+            return "TextViewDrawableAction";
+        }
+
         boolean isRelative = false;
         int d1, d2, d3, d4;
 
@@ -1220,7 +1339,10 @@
             target.setTextSize(units, size);
         }
 
-        int viewId;
+        public String getActionName() {
+            return "TextViewSizeAction";
+        }
+
         int units;
         float size;
 
@@ -1264,7 +1386,10 @@
             target.setPadding(left, top, right, bottom);
         }
 
-        int viewId;
+        public String getActionName() {
+            return "ViewPaddingAction";
+        }
+
         int left, top, right, bottom;
 
         public final static int TAG = 14;
@@ -1314,7 +1439,7 @@
     /**
      * Create a new RemoteViews object that will display the views contained
      * in the specified layout file.
-     * 
+     *
      * @param packageName Name of the package that contains the layout resource
      * @param layoutId The id of the layout resource
      */
@@ -1328,11 +1453,16 @@
         recalculateMemoryUsage();
     }
 
+    /** {@hide} */
+    public void setUser(UserHandle user) {
+        mUser = user;
+    }
+
     private boolean hasLandscapeAndPortraitLayouts() {
         return (mLandscape != null) && (mPortrait != null);
     }
 
-     /**
+    /**
      * Create a new RemoteViews object that will inflate as the specified
      * landspace or portrait RemoteViews, depending on the current configuration.
      *
@@ -1364,7 +1494,7 @@
 
     /**
      * Reads a RemoteViews object from a parcel.
-     * 
+     *
      * @param parcel
      */
     public RemoteViews(Parcel parcel) {
@@ -1450,23 +1580,12 @@
         recalculateMemoryUsage();
     }
 
-    @Override
-    public RemoteViews clone() {
-        RemoteViews that;
-        if (!hasLandscapeAndPortraitLayouts()) {
-            that = new RemoteViews(mPackage, mLayoutId);
 
-            if (mActions != null) {
-                that.mActions = (ArrayList<Action>)mActions.clone();
-            }
-        } else {
-            RemoteViews land = mLandscape.clone();
-            RemoteViews port = mPortrait.clone();
-            that = new RemoteViews(land, port);
-        }
-        // update the memory usage stats of the cloned RemoteViews
-        that.recalculateMemoryUsage();
-        return that;
+    public RemoteViews clone() {
+        Parcel p = Parcel.obtain();
+        writeToParcel(p, 0);
+        p.setDataPosition(0);
+        return new RemoteViews(p);
     }
 
     public String getPackage() {
@@ -1547,7 +1666,7 @@
 
     /**
      * Add an action to be executed on the remote side when apply is called.
-     * 
+     *
      * @param a The action to add
      */
     private void addAction(Action a) {
@@ -1619,7 +1738,7 @@
 
     /**
      * Equivalent to calling View.setVisibility
-     * 
+     *
      * @param viewId The id of the view whose visibility should change
      * @param visibility The new visibility for the view
      */
@@ -1629,7 +1748,7 @@
 
     /**
      * Equivalent to calling TextView.setText
-     * 
+     *
      * @param viewId The id of the view whose text should change
      * @param text The new text for the view
      */
@@ -1639,7 +1758,7 @@
 
     /**
      * Equivalent to calling {@link TextView#setTextSize(int, float)}
-     * 
+     *
      * @param viewId The id of the view whose text size should change
      * @param units The units of size (e.g. COMPLEX_UNIT_SP)
      * @param size The size of the text
@@ -1649,20 +1768,23 @@
     }
 
     /**
-     * Equivalent to calling 
+     * Equivalent to calling
      * {@link TextView#setCompoundDrawablesWithIntrinsicBounds(int, int, int, int)}.
      *
      * @param viewId The id of the view whose text should change
      * @param left The id of a drawable to place to the left of the text, or 0
      * @param top The id of a drawable to place above the text, or 0
      * @param right The id of a drawable to place to the right of the text, or 0
-     * @param bottom The id of a drawable to place below the text, or 0 
+     * @param bottom The id of a drawable to place below the text, or 0
      */
     public void setTextViewCompoundDrawables(int viewId, int left, int top, int right, int bottom) {
         addAction(new TextViewDrawableAction(viewId, false, left, top, right, bottom));
     }
 
     /**
+     * Equivalent to calling {@link
+     * TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int)}.
+     *
      * @param viewId The id of the view whose text should change
      * @param start The id of a drawable to place before the text (relative to the
      * layout direction), or 0
@@ -1676,17 +1798,17 @@
 
     /**
      * Equivalent to calling ImageView.setImageResource
-     * 
+     *
      * @param viewId The id of the view whose drawable should change
      * @param srcId The new resource id for the drawable
      */
-    public void setImageViewResource(int viewId, int srcId) {   
+    public void setImageViewResource(int viewId, int srcId) {
         setInt(viewId, "setImageResource", srcId);
     }
 
     /**
      * Equivalent to calling ImageView.setImageURI
-     * 
+     *
      * @param viewId The id of the view whose drawable should change
      * @param uri The Uri for the image
      */
@@ -1696,7 +1818,7 @@
 
     /**
      * Equivalent to calling ImageView.setImageBitmap
-     * 
+     *
      * @param viewId The id of the view whose bitmap should change
      * @param bitmap The new Bitmap for the drawable
      */
@@ -1719,7 +1841,7 @@
      * {@link Chronometer#setFormat Chronometer.setFormat},
      * and {@link Chronometer#start Chronometer.start()} or
      * {@link Chronometer#stop Chronometer.stop()}.
-     * 
+     *
      * @param viewId The id of the {@link Chronometer} to change
      * @param base The time at which the timer would have read 0:00.  This
      *             time should be based off of
@@ -1733,21 +1855,21 @@
         setString(viewId, "setFormat", format);
         setBoolean(viewId, "setStarted", started);
     }
-    
+
     /**
      * Equivalent to calling {@link ProgressBar#setMax ProgressBar.setMax},
      * {@link ProgressBar#setProgress ProgressBar.setProgress}, and
      * {@link ProgressBar#setIndeterminate ProgressBar.setIndeterminate}
      *
      * If indeterminate is true, then the values for max and progress are ignored.
-     * 
+     *
      * @param viewId The id of the {@link ProgressBar} to change
      * @param max The 100% value for the progress bar
      * @param progress The current value of the progress bar.
-     * @param indeterminate True if the progress bar is indeterminate, 
+     * @param indeterminate True if the progress bar is indeterminate,
      *                false if not.
      */
-    public void setProgressBar(int viewId, int max, int progress, 
+    public void setProgressBar(int viewId, int max, int progress,
             boolean indeterminate) {
         setBoolean(viewId, "setIndeterminate", indeterminate);
         if (!indeterminate) {
@@ -1755,12 +1877,12 @@
             setInt(viewId, "setProgress", progress);
         }
     }
-    
+
     /**
      * Equivalent to calling
      * {@link android.view.View#setOnClickListener(android.view.View.OnClickListener)}
      * to launch the provided {@link PendingIntent}.
-     * 
+     *
      * When setting the on-click action of items within collections (eg. {@link ListView},
      * {@link StackView} etc.), this method will not work. Instead, use {@link
      * RemoteViews#setPendingIntentTemplate(int, PendingIntent) in conjunction with
@@ -1820,7 +1942,7 @@
      * view.
      * <p>
      * You can omit specific calls by marking their values with null or -1.
-     * 
+     *
      * @param viewId The id of the view that contains the target
      *            {@link Drawable}
      * @param targetBackground If true, apply these parameters to the
@@ -1846,7 +1968,7 @@
 
     /**
      * Equivalent to calling {@link android.widget.TextView#setTextColor(int)}.
-     * 
+     *
      * @param viewId The id of the view whose text color should change
      * @param color Sets the text color for all the states (normal, selected,
      *            focused) to be this color.
@@ -2034,6 +2156,8 @@
      * @param value The value to pass to the method.
      */
     public void setUri(int viewId, String methodName, Uri value) {
+        // Resolve any filesystem path before sending remotely
+        value = value.getCanonicalUri();
         addAction(new ReflectionAction(viewId, methodName, ReflectionAction.URI, value));
     }
 
@@ -2074,15 +2198,25 @@
     }
 
     /**
-     * Equivalent to calling View.setContentDescription
+     * Equivalent to calling View.setContentDescription(CharSequence).
      *
-     * @param viewId The id of the view whose content description should change
-     * @param contentDescription The new content description for the view
+     * @param viewId The id of the view whose content description should change.
+     * @param contentDescription The new content description for the view.
      */
     public void setContentDescription(int viewId, CharSequence contentDescription) {
         setCharSequence(viewId, "setContentDescription", contentDescription);
     }
 
+    /**
+     * Equivalent to calling View.setLabelFor(int).
+     *
+     * @param viewId The id of the view whose property to set.
+     * @param labeledId The id of a view for which this view serves as a label.
+     */
+    public void setLabelFor(int viewId, int labeledId) {
+        setInt(viewId, "setLabelFor", labeledId);
+    }
+
     private RemoteViews getRemoteViewsToApply(Context context) {
         if (hasLandscapeAndPortraitLayouts()) {
             int orientation = context.getResources().getConfiguration().orientation;
@@ -2098,16 +2232,16 @@
     /**
      * Inflates the view hierarchy represented by this object and applies
      * all of the actions.
-     * 
+     *
      * <p><strong>Caller beware: this may throw</strong>
-     * 
+     *
      * @param context Default context to use
      * @param parent Parent that the resulting view hierarchy will be attached to. This method
      * does <strong>not</strong> attach the hierarchy. The caller should do so when appropriate.
      * @return The inflated view hierarchy
      */
     public View apply(Context context, ViewGroup parent) {
-        return apply(context, parent, DEFAULT_ON_CLICK_HANDLER);
+        return apply(context, parent, null);
     }
 
     /** @hide */
@@ -2135,12 +2269,12 @@
      * Applies all of the actions to the provided view.
      *
      * <p><strong>Caller beware: this may throw</strong>
-     * 
+     *
      * @param v The view to apply the actions to.  This should be the result of
      * the {@link #apply(Context,ViewGroup)} call.
      */
     public void reapply(Context context, View v) {
-        reapply(context, v, DEFAULT_ON_CLICK_HANDLER);
+        reapply(context, v, null);
     }
 
     /** @hide */
@@ -2163,6 +2297,7 @@
 
     private void performApply(View v, ViewGroup parent, OnClickHandler handler) {
         if (mActions != null) {
+            handler = handler == null ? DEFAULT_ON_CLICK_HANDLER : handler;
             final int count = mActions.size();
             for (int i = 0; i < count; i++) {
                 Action a = mActions.get(i);
@@ -2177,7 +2312,8 @@
 
         if (packageName != null) {
             try {
-                c = context.createPackageContext(packageName, Context.CONTEXT_RESTRICTED);
+                c = context.createPackageContextAsUser(
+                        packageName, Context.CONTEXT_RESTRICTED, mUser);
             } catch (NameNotFoundException e) {
                 Log.e(LOG_TAG, "Package name " + packageName + " not found");
                 c = context;
@@ -2191,7 +2327,7 @@
 
     /* (non-Javadoc)
      * Used to restrict the views which can be inflated
-     * 
+     *
      * @see android.view.LayoutInflater.Filter#onLoadClass(java.lang.Class)
      */
     public boolean onLoadClass(Class clazz) {
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index f0109ce..e481702 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -36,6 +36,7 @@
 import android.view.View;
 import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
+import android.widget.RemoteViews.OnClickHandler;
 
 import com.android.internal.widget.IRemoteViewsAdapterConnection;
 import com.android.internal.widget.IRemoteViewsFactory;
@@ -68,6 +69,7 @@
     private LayoutInflater mLayoutInflater;
     private RemoteViewsAdapterServiceConnection mServiceConnection;
     private WeakReference<RemoteAdapterConnectionCallback> mCallback;
+    private OnClickHandler mRemoteViewsOnClickHandler;
     private FixedSizeRemoteViewsCache mCache;
     private int mVisibleWindowLowerBound;
     private int mVisibleWindowUpperBound;
@@ -277,11 +279,11 @@
          * @param view the RemoteViews that was loaded. If null, the RemoteViews was not loaded
          *             successfully.
          */
-        public void onRemoteViewsLoaded(RemoteViews view) {
+        public void onRemoteViewsLoaded(RemoteViews view, OnClickHandler handler) {
             try {
                 // Remove all the children of this layout first
                 removeAllViews();
-                addView(view.apply(getContext(), this));
+                addView(view.apply(getContext(), this, handler));
             } catch (Exception e) {
                 Log.e(TAG, "Failed to apply RemoteViews.");
             }
@@ -330,7 +332,7 @@
                 // Notify all the references for that position of the newly loaded RemoteViews
                 final LinkedList<RemoteViewsFrameLayout> refs = mReferences.get(pos);
                 for (final RemoteViewsFrameLayout ref : refs) {
-                    ref.onRemoteViewsLoaded(view);
+                    ref.onRemoteViewsLoaded(view, mRemoteViewsOnClickHandler);
                 }
                 refs.clear();
 
@@ -421,7 +423,8 @@
         }
 
         private RemoteViewsFrameLayout createLoadingView(int position, View convertView,
-                ViewGroup parent, Object lock, LayoutInflater layoutInflater) {
+                ViewGroup parent, Object lock, LayoutInflater layoutInflater, OnClickHandler
+                handler) {
             // Create and return a new FrameLayout, and setup the references for this position
             final Context context = parent.getContext();
             RemoteViewsFrameLayout layout = new RemoteViewsFrameLayout(context);
@@ -433,7 +436,8 @@
                 if (mUserLoadingView != null) {
                     // Try to inflate user-specified loading view
                     try {
-                        View loadingView = mUserLoadingView.apply(parent.getContext(), parent);
+                        View loadingView = mUserLoadingView.apply(parent.getContext(), parent,
+                                handler);
                         loadingView.setTagInternal(com.android.internal.R.id.rowTypeId,
                                 new Integer(0));
                         layout.addView(loadingView);
@@ -448,7 +452,7 @@
                     // Use the size of the first row as a guide for the size of the loading view
                     if (mFirstViewHeight < 0) {
                         try {
-                            View firstView = mFirstView.apply(parent.getContext(), parent);
+                            View firstView = mFirstView.apply(parent.getContext(), parent, handler);
                             firstView.measure(
                                     MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
                                     MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
@@ -815,6 +819,10 @@
         return mDataReady;
     }
 
+    public void setRemoteViewsOnClickHandler(OnClickHandler handler) {
+        mRemoteViewsOnClickHandler = handler;
+    }
+
     public void saveRemoteViewsCache() {
         final Pair<Intent.FilterComparison, Integer> key = new Pair<Intent.FilterComparison,
                 Integer> (new Intent.FilterComparison(mIntent), mAppWidgetId);
@@ -1102,7 +1110,7 @@
                     // Reuse the convert view where possible
                     if (layout != null) {
                         if (convertViewTypeId == typeId) {
-                            rv.reapply(context, convertViewChild);
+                            rv.reapply(context, convertViewChild, mRemoteViewsOnClickHandler);
                             return layout;
                         }
                         layout.removeAllViews();
@@ -1111,7 +1119,7 @@
                     }
 
                     // Otherwise, create a new view to be returned
-                    View newView = rv.apply(context, parent);
+                    View newView = rv.apply(context, parent, mRemoteViewsOnClickHandler);
                     newView.setTagInternal(com.android.internal.R.id.rowTypeId,
                             new Integer(typeId));
                     layout.addView(newView);
@@ -1127,7 +1135,7 @@
                     final RemoteViewsMetaData metaData = mCache.getMetaData();
                     synchronized (metaData) {
                         loadingView = metaData.createLoadingView(position, convertView, parent,
-                                mCache, mLayoutInflater);
+                                mCache, mLayoutInflater, mRemoteViewsOnClickHandler);
                     }
                     return loadingView;
                 } finally {
@@ -1140,7 +1148,7 @@
                 final RemoteViewsMetaData metaData = mCache.getMetaData();
                 synchronized (metaData) {
                     loadingView = metaData.createLoadingView(position, convertView, parent,
-                            mCache, mLayoutInflater);
+                            mCache, mLayoutInflater, mRemoteViewsOnClickHandler);
                 }
 
                 mRequestedViews.add(position, loadingView);
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 8747dc3..bc41931 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -463,6 +463,13 @@
             return true;
         }
 
+        /*
+         * Don't try to intercept touch if we can't scroll anyway.
+         */
+        if (getScrollY() == 0 && !canScrollVertically(1)) {
+            return false;
+        }
+
         switch (action & MotionEvent.ACTION_MASK) {
             case MotionEvent.ACTION_MOVE: {
                 /*
diff --git a/core/java/android/widget/Scroller.java b/core/java/android/widget/Scroller.java
index a6e83f0..3a28e75e 100644
--- a/core/java/android/widget/Scroller.java
+++ b/core/java/android/widget/Scroller.java
@@ -57,45 +57,70 @@
     private boolean mFlywheel;
 
     private float mVelocity;
+    private float mCurrVelocity;
+    private int mDistance;
+
+    private float mFlingFriction = ViewConfiguration.getScrollFriction();
 
     private static final int DEFAULT_DURATION = 250;
     private static final int SCROLL_MODE = 0;
     private static final int FLING_MODE = 1;
 
-    private static float DECELERATION_RATE = (float) (Math.log(0.75) / Math.log(0.9));
-    private static float ALPHA = 800; // pixels / seconds
-    private static float START_TENSION = 0.4f; // Tension at start: (0.4 * total T, 1.0 * Distance)
-    private static float END_TENSION = 1.0f - START_TENSION;
+    private static float DECELERATION_RATE = (float) (Math.log(0.78) / Math.log(0.9));
+    private static final float INFLEXION = 0.35f; // Tension lines cross at (INFLEXION, 1)
+    private static final float START_TENSION = 0.5f;
+    private static final float END_TENSION = 1.0f;
+    private static final float P1 = START_TENSION * INFLEXION;
+    private static final float P2 = 1.0f - END_TENSION * (1.0f - INFLEXION);
+
     private static final int NB_SAMPLES = 100;
-    private static final float[] SPLINE = new float[NB_SAMPLES + 1];
+    private static final float[] SPLINE_POSITION = new float[NB_SAMPLES + 1];
+    private static final float[] SPLINE_TIME = new float[NB_SAMPLES + 1];
 
     private float mDeceleration;
     private final float mPpi;
 
+    // A context-specific coefficient adjusted to physical values.
+    private float mPhysicalCoeff;
+
     static {
         float x_min = 0.0f;
-        for (int i = 0; i <= NB_SAMPLES; i++) {
-            final float t = (float) i / NB_SAMPLES;
+        float y_min = 0.0f;
+        for (int i = 0; i < NB_SAMPLES; i++) {
+            final float alpha = (float) i / NB_SAMPLES;
+
             float x_max = 1.0f;
             float x, tx, coef;
             while (true) {
                 x = x_min + (x_max - x_min) / 2.0f;
                 coef = 3.0f * x * (1.0f - x);
-                tx = coef * ((1.0f - x) * START_TENSION + x * END_TENSION) + x * x * x;
-                if (Math.abs(tx - t) < 1E-5) break;
-                if (tx > t) x_max = x;
+                tx = coef * ((1.0f - x) * P1 + x * P2) + x * x * x;
+                if (Math.abs(tx - alpha) < 1E-5) break;
+                if (tx > alpha) x_max = x;
                 else x_min = x;
             }
-            final float d = coef + x * x * x;
-            SPLINE[i] = d;
+            SPLINE_POSITION[i] = coef * ((1.0f - x) * START_TENSION + x) + x * x * x;
+
+            float y_max = 1.0f;
+            float y, dy;
+            while (true) {
+                y = y_min + (y_max - y_min) / 2.0f;
+                coef = 3.0f * y * (1.0f - y);
+                dy = coef * ((1.0f - y) * START_TENSION + y) + y * y * y;
+                if (Math.abs(dy - alpha) < 1E-5) break;
+                if (dy > alpha) y_max = y;
+                else y_min = y;
+            }
+            SPLINE_TIME[i] = coef * ((1.0f - y) * P1 + y * P2) + y * y * y;
         }
-        SPLINE[NB_SAMPLES] = 1.0f;
+        SPLINE_POSITION[NB_SAMPLES] = SPLINE_TIME[NB_SAMPLES] = 1.0f;
 
         // This controls the viscous fluid effect (how much of it)
         sViscousFluidScale = 8.0f;
         // must be set to 1.0 (used in viscousFluid())
         sViscousFluidNormalize = 1.0f;
         sViscousFluidNormalize = 1.0f / viscousFluid(1.0f);
+
     }
 
     private static float sViscousFluidScale;
@@ -129,6 +154,8 @@
         mPpi = context.getResources().getDisplayMetrics().density * 160.0f;
         mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction());
         mFlywheel = flywheel;
+
+        mPhysicalCoeff = computeDeceleration(0.84f); // look and feel tuning
     }
 
     /**
@@ -140,6 +167,7 @@
      */
     public final void setFriction(float friction) {
         mDeceleration = computeDeceleration(friction);
+        mFlingFriction = friction;
     }
     
     private float computeDeceleration(float friction) {
@@ -202,7 +230,8 @@
      * negative.
      */
     public float getCurrVelocity() {
-        return mVelocity - mDeceleration * timePassed() / 2000.0f;
+        return mMode == FLING_MODE ?
+                mCurrVelocity : mVelocity - mDeceleration * timePassed() / 2000.0f;
     }
 
     /**
@@ -269,11 +298,18 @@
             case FLING_MODE:
                 final float t = (float) timePassed / mDuration;
                 final int index = (int) (NB_SAMPLES * t);
-                final float t_inf = (float) index / NB_SAMPLES;
-                final float t_sup = (float) (index + 1) / NB_SAMPLES;
-                final float d_inf = SPLINE[index];
-                final float d_sup = SPLINE[index + 1];
-                final float distanceCoef = d_inf + (t - t_inf) / (t_sup - t_inf) * (d_sup - d_inf);
+                float distanceCoef = 1.f;
+                float velocityCoef = 0.f;
+                if (index < NB_SAMPLES) {
+                    final float t_inf = (float) index / NB_SAMPLES;
+                    final float t_sup = (float) (index + 1) / NB_SAMPLES;
+                    final float d_inf = SPLINE_POSITION[index];
+                    final float d_sup = SPLINE_POSITION[index + 1];
+                    velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);
+                    distanceCoef = d_inf + (t - t_inf) * velocityCoef;
+                }
+
+                mCurrVelocity = velocityCoef * mDistance / mDuration * 1000.0f;
                 
                 mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));
                 // Pin to mMinX <= mCurrX <= mMaxX
@@ -392,8 +428,7 @@
         float velocity = FloatMath.sqrt(velocityX * velocityX + velocityY * velocityY);
      
         mVelocity = velocity;
-        final double l = Math.log(START_TENSION * velocity / ALPHA);
-        mDuration = (int) (1000.0 * Math.exp(l / (DECELERATION_RATE - 1.0)));
+        mDuration = getSplineFlingDuration(velocity);
         mStartTime = AnimationUtils.currentAnimationTimeMillis();
         mStartX = startX;
         mStartY = startY;
@@ -401,25 +436,41 @@
         float coeffX = velocity == 0 ? 1.0f : velocityX / velocity;
         float coeffY = velocity == 0 ? 1.0f : velocityY / velocity;
 
-        int totalDistance =
-                (int) (ALPHA * Math.exp(DECELERATION_RATE / (DECELERATION_RATE - 1.0) * l));
+        double totalDistance = getSplineFlingDistance(velocity);
+        mDistance = (int) (totalDistance * Math.signum(velocity));
         
         mMinX = minX;
         mMaxX = maxX;
         mMinY = minY;
         mMaxY = maxY;
 
-        mFinalX = startX + Math.round(totalDistance * coeffX);
+        mFinalX = startX + (int) Math.round(totalDistance * coeffX);
         // Pin to mMinX <= mFinalX <= mMaxX
         mFinalX = Math.min(mFinalX, mMaxX);
         mFinalX = Math.max(mFinalX, mMinX);
         
-        mFinalY = startY + Math.round(totalDistance * coeffY);
+        mFinalY = startY + (int) Math.round(totalDistance * coeffY);
         // Pin to mMinY <= mFinalY <= mMaxY
         mFinalY = Math.min(mFinalY, mMaxY);
         mFinalY = Math.max(mFinalY, mMinY);
     }
     
+    private double getSplineDeceleration(float velocity) {
+        return Math.log(INFLEXION * Math.abs(velocity) / (mFlingFriction * mPhysicalCoeff));
+    }
+
+    private int getSplineFlingDuration(float velocity) {
+        final double l = getSplineDeceleration(velocity);
+        final double decelMinusOne = DECELERATION_RATE - 1.0;
+        return (int) (1000.0 * Math.exp(l / decelMinusOne));
+    }
+
+    private double getSplineFlingDistance(float velocity) {
+        final double l = getSplineDeceleration(velocity);
+        final double decelMinusOne = DECELERATION_RATE - 1.0;
+        return mFlingFriction * mPhysicalCoeff * Math.exp(DECELERATION_RATE / decelMinusOne * l);
+    }
+
     static float viscousFluid(float x)
     {
         x *= sViscousFluidScale;
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 86433d4..cd8638da 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -326,7 +326,6 @@
                         int oldLeft, int oldTop, int oldRight, int oldBottom) {
                     adjustDropDownSizeAndPosition();
                 }
-
             });
         }
 
@@ -1285,15 +1284,22 @@
             Resources res = getContext().getResources();
             int anchorPadding = mSearchPlate.getPaddingLeft();
             Rect dropDownPadding = new Rect();
+            final boolean isLayoutRtl = isLayoutRtl();
             int iconOffset = mIconifiedByDefault
                     ? res.getDimensionPixelSize(R.dimen.dropdownitem_icon_width)
                     + res.getDimensionPixelSize(R.dimen.dropdownitem_text_padding_left)
                     : 0;
             mQueryTextView.getDropDownBackground().getPadding(dropDownPadding);
-            mQueryTextView.setDropDownHorizontalOffset(-(dropDownPadding.left + iconOffset)
-                    + anchorPadding);
-            mQueryTextView.setDropDownWidth(mDropDownAnchor.getWidth() + dropDownPadding.left
-                    + dropDownPadding.right + iconOffset - (anchorPadding));
+            int offset;
+            if (isLayoutRtl) {
+                offset = - dropDownPadding.left;
+            } else {
+                offset = anchorPadding - (dropDownPadding.left + iconOffset);
+            }
+            mQueryTextView.setDropDownHorizontalOffset(offset);
+            final int width = mDropDownAnchor.getWidth() + dropDownPadding.left
+                    + dropDownPadding.right + iconOffset - anchorPadding;
+            mQueryTextView.setDropDownWidth(width);
         }
     }
 
@@ -1347,6 +1353,11 @@
         }
     };
 
+    @Override
+    public void onRtlPropertiesChanged(int layoutDirection) {
+        mQueryTextView.setLayoutDirection(layoutDirection);
+    }
+
     /**
      * Query rewriting.
      */
diff --git a/core/java/android/widget/SimpleExpandableListAdapter.java b/core/java/android/widget/SimpleExpandableListAdapter.java
index f514374..015c169 100644
--- a/core/java/android/widget/SimpleExpandableListAdapter.java
+++ b/core/java/android/widget/SimpleExpandableListAdapter.java
@@ -38,8 +38,6 @@
  */
 public class SimpleExpandableListAdapter extends BaseExpandableListAdapter {
     private List<? extends Map<String, ?>> mGroupData;
-    // Keeps track of if a group is currently expanded or not
-    private boolean[] mIsGroupExpanded;
     private int mExpandedGroupLayout;
     private int mCollapsedGroupLayout;
     private String[] mGroupFrom;
@@ -198,8 +196,6 @@
             int childLayout, int lastChildLayout, String[] childFrom,
             int[] childTo) {
         mGroupData = groupData;
-        // Initially all groups are not expanded
-        mIsGroupExpanded = new boolean[groupData.size()];
         mExpandedGroupLayout = expandedGroupLayout;
         mCollapsedGroupLayout = collapsedGroupLayout;
         mGroupFrom = groupFrom;
@@ -302,52 +298,4 @@
         return true;
     }
 
-    /**
-     * {@inheritDoc}
-     * @return 1 for the last child in a group, 0 for the other children.
-     */
-    @Override
-    public int getChildType(int groupPosition, int childPosition) {
-        final int childrenInGroup = getChildrenCount(groupPosition);
-        return childPosition == childrenInGroup - 1 ? 1 : 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @return 2, one type for the last child in a group, one for the other children.
-     */
-    @Override
-    public int getChildTypeCount() {
-        return 2;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @return 1 for an expanded group view, 0 for a collapsed one.
-     */
-    @Override
-    public int getGroupType(int groupPosition) {
-        return mIsGroupExpanded[groupPosition] ? 1 : 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @return 2, one for a collapsed group view, one for an expanded one.
-     */
-    @Override
-    public int getGroupTypeCount() {
-        return 2;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public void onGroupCollapsed(int groupPosition) {
-        mIsGroupExpanded[groupPosition] = false;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public void onGroupExpanded(int groupPosition) {
-        mIsGroupExpanded[groupPosition] = true;
-    }
 }
diff --git a/core/java/android/widget/SlidingDrawer.java b/core/java/android/widget/SlidingDrawer.java
index 14edd10..517246b 100644
--- a/core/java/android/widget/SlidingDrawer.java
+++ b/core/java/android/widget/SlidingDrawer.java
@@ -78,7 +78,12 @@
  * @attr ref android.R.styleable#SlidingDrawer_orientation
  * @attr ref android.R.styleable#SlidingDrawer_allowSingleTap
  * @attr ref android.R.styleable#SlidingDrawer_animateOnClick
+ * 
+ * @deprecated This class is not supported anymore. It is recommended you
+ * base your own implementation on the source code for the Android Open
+ * Source Project if you must use it in your application.
  */
+@Deprecated
 public class SlidingDrawer extends ViewGroup {
     public static final int ORIENTATION_HORIZONTAL = 0;
     public static final int ORIENTATION_VERTICAL = 1;
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 64834b2..925864c 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -30,8 +30,11 @@
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.PopupWindow.OnDismissListener;
 
 
 /**
@@ -355,7 +358,7 @@
     public void setGravity(int gravity) {
         if (mGravity != gravity) {
             if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
-                gravity |= Gravity.LEFT;
+                gravity |= Gravity.START;
             }
             mGravity = gravity;
             requestLayout();
@@ -460,7 +463,7 @@
     /**
      * Creates and positions all views for this Spinner.
      *
-     * @param delta Change in the selected position. +1 moves selection is moving to the right,
+     * @param delta Change in the selected position. +1 means selection is moving to the right,
      * so views are scrolling to the left. -1 means selection is moving to the left.
      */
     @Override
@@ -492,7 +495,9 @@
         View sel = makeAndAddView(mSelectedPosition);
         int width = sel.getMeasuredWidth();
         int selectedOffset = childrenLeft;
-        switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+        final int layoutDirection = getLayoutDirection();
+        final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
+        switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
             case Gravity.CENTER_HORIZONTAL:
                 selectedOffset = childrenLeft + (childrenWidth / 2) - (width / 2);
                 break;
@@ -939,19 +944,18 @@
         @Override
         public void show() {
             final Drawable background = getBackground();
-            int bgOffset = 0;
+            int hOffset = 0;
             if (background != null) {
                 background.getPadding(mTempRect);
-                bgOffset = -mTempRect.left;
+                hOffset = isLayoutRtl() ? mTempRect.right : -mTempRect.left;
             } else {
                 mTempRect.left = mTempRect.right = 0;
             }
 
             final int spinnerPaddingLeft = Spinner.this.getPaddingLeft();
+            final int spinnerPaddingRight = Spinner.this.getPaddingRight();
+            final int spinnerWidth = Spinner.this.getWidth();
             if (mDropDownWidth == WRAP_CONTENT) {
-                final int spinnerWidth = Spinner.this.getWidth();
-                final int spinnerPaddingRight = Spinner.this.getPaddingRight();
-
                 int contentWidth =  measureContentWidth(
                         (SpinnerAdapter) mAdapter, getBackground());
                 final int contentWidthLimit = mContext.getResources()
@@ -959,21 +963,48 @@
                 if (contentWidth > contentWidthLimit) {
                     contentWidth = contentWidthLimit;
                 }
-
                 setContentWidth(Math.max(
                        contentWidth, spinnerWidth - spinnerPaddingLeft - spinnerPaddingRight));
             } else if (mDropDownWidth == MATCH_PARENT) {
-                final int spinnerWidth = Spinner.this.getWidth();
-                final int spinnerPaddingRight = Spinner.this.getPaddingRight();
                 setContentWidth(spinnerWidth - spinnerPaddingLeft - spinnerPaddingRight);
             } else {
                 setContentWidth(mDropDownWidth);
             }
-            setHorizontalOffset(bgOffset + spinnerPaddingLeft);
+
+            if (isLayoutRtl()) {
+                hOffset += spinnerWidth - spinnerPaddingRight - getWidth();
+            } else {
+                hOffset += spinnerPaddingLeft;
+            }
+            setHorizontalOffset(hOffset);
             setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
             super.show();
             getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
             setSelection(Spinner.this.getSelectedItemPosition());
+
+            // Make sure we hide if our anchor goes away.
+            // TODO: This might be appropriate to push all the way down to PopupWindow,
+            // but it may have other side effects to investigate first. (Text editing handles, etc.)
+            final ViewTreeObserver vto = getViewTreeObserver();
+            if (vto != null) {
+                final OnGlobalLayoutListener layoutListener = new OnGlobalLayoutListener() {
+                    @Override
+                    public void onGlobalLayout() {
+                        if (!Spinner.this.isVisibleToUser()) {
+                            dismiss();
+                        }
+                    }
+                };
+                vto.addOnGlobalLayoutListener(layoutListener);
+                setOnDismissListener(new OnDismissListener() {
+                    @Override public void onDismiss() {
+                        final ViewTreeObserver vto = getViewTreeObserver();
+                        if (vto != null) {
+                            vto.removeOnGlobalLayoutListener(layoutListener);
+                        }
+                    }
+                });
+            }
         }
     }
 }
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 293eda1..6853660 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -1412,8 +1412,8 @@
                 return null;
             }
 
-            Bitmap bitmap = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(),
-                    Bitmap.Config.ARGB_8888);
+            Bitmap bitmap = Bitmap.createBitmap(v.getResources().getDisplayMetrics(),
+                    v.getMeasuredWidth(), v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
             mCanvas.setBitmap(bitmap);
 
             float rotationX = v.getRotationX();
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index cea613f..e754c17 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -480,12 +480,6 @@
 
     @Override
     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
-        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
-        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
-
         if (mOnLayout == null) {
             mOnLayout = makeLayout(mTextOn);
         }
@@ -501,34 +495,6 @@
 
         mThumbWidth = maxTextWidth + mThumbTextPadding * 2;
 
-        switch (widthMode) {
-            case MeasureSpec.AT_MOST:
-                widthSize = Math.min(widthSize, switchWidth);
-                break;
-
-            case MeasureSpec.UNSPECIFIED:
-                widthSize = switchWidth;
-                break;
-
-            case MeasureSpec.EXACTLY:
-                // Just use what we were given
-                break;
-        }
-
-        switch (heightMode) {
-            case MeasureSpec.AT_MOST:
-                heightSize = Math.min(heightSize, switchHeight);
-                break;
-
-            case MeasureSpec.UNSPECIFIED:
-                heightSize = switchHeight;
-                break;
-
-            case MeasureSpec.EXACTLY:
-                // Just use what we were given
-                break;
-        }
-
         mSwitchWidth = switchWidth;
         mSwitchHeight = switchHeight;
 
@@ -542,9 +508,9 @@
     @Override
     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
         super.onPopulateAccessibilityEvent(event);
-        CharSequence text = isChecked() ? mOnLayout.getText() : mOffLayout.getText();
-        if (!TextUtils.isEmpty(text)) {
-            event.getText().add(text);
+        Layout layout =  isChecked() ? mOnLayout : mOffLayout;
+        if (layout != null && !TextUtils.isEmpty(layout.getText())) {
+            event.getText().add(layout.getText());
         }
     }
 
@@ -662,7 +628,7 @@
             mVelocityTracker.computeCurrentVelocity(1000);
             float xvel = mVelocityTracker.getXVelocity();
             if (Math.abs(xvel) > mMinFlingVelocity) {
-                newState = xvel > 0;
+                newState = isLayoutRtl() ? (xvel < 0) : (xvel > 0);
             } else {
                 newState = getTargetCheckedState();
             }
@@ -680,13 +646,25 @@
     }
 
     private boolean getTargetCheckedState() {
-        return mThumbPosition >= getThumbScrollRange() / 2;
+        if (isLayoutRtl()) {
+            return mThumbPosition <= getThumbScrollRange() / 2;
+        } else {
+            return mThumbPosition >= getThumbScrollRange() / 2;
+        }
+    }
+
+    private void setThumbPosition(boolean checked) {
+        if (isLayoutRtl()) {
+            mThumbPosition = checked ? 0 : getThumbScrollRange();
+        } else {
+            mThumbPosition = checked ? getThumbScrollRange() : 0;
+        }
     }
 
     @Override
     public void setChecked(boolean checked) {
         super.setChecked(checked);
-        mThumbPosition = isChecked() ? getThumbScrollRange() : 0;
+        setThumbPosition(isChecked());
         invalidate();
     }
 
@@ -694,10 +672,19 @@
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
 
-        mThumbPosition = isChecked() ? getThumbScrollRange() : 0;
+        setThumbPosition(isChecked());
 
-        int switchRight = getWidth() - getPaddingRight();
-        int switchLeft = switchRight - mSwitchWidth;
+        int switchRight;
+        int switchLeft;
+
+        if (isLayoutRtl()) {
+            switchLeft = getPaddingLeft();
+            switchRight = switchLeft + mSwitchWidth;
+        } else {
+            switchRight = getWidth() - getPaddingRight();
+            switchLeft = switchRight - mSwitchWidth;
+        }
+
         int switchTop = 0;
         int switchBottom = 0;
         switch (getGravity() & Gravity.VERTICAL_GRAVITY_MASK) {
@@ -763,16 +750,32 @@
         mTextPaint.drawableState = getDrawableState();
 
         Layout switchText = getTargetCheckedState() ? mOnLayout : mOffLayout;
-
-        canvas.translate((thumbLeft + thumbRight) / 2 - switchText.getWidth() / 2,
-                (switchInnerTop + switchInnerBottom) / 2 - switchText.getHeight() / 2);
-        switchText.draw(canvas);
+        if (switchText != null) {
+            canvas.translate((thumbLeft + thumbRight) / 2 - switchText.getWidth() / 2,
+                    (switchInnerTop + switchInnerBottom) / 2 - switchText.getHeight() / 2);
+            switchText.draw(canvas);
+        }
 
         canvas.restore();
     }
 
     @Override
+    public int getCompoundPaddingLeft() {
+        if (!isLayoutRtl()) {
+            return super.getCompoundPaddingLeft();
+        }
+        int padding = super.getCompoundPaddingLeft() + mSwitchWidth;
+        if (!TextUtils.isEmpty(getText())) {
+            padding += mSwitchPadding;
+        }
+        return padding;
+    }
+
+    @Override
     public int getCompoundPaddingRight() {
+        if (isLayoutRtl()) {
+            return super.getCompoundPaddingRight();
+        }
         int padding = super.getCompoundPaddingRight() + mSwitchWidth;
         if (!TextUtils.isEmpty(getText())) {
             padding += mSwitchPadding;
diff --git a/core/java/android/widget/TableLayout.java b/core/java/android/widget/TableLayout.java
index 78e9453..399b4fa 100644
--- a/core/java/android/widget/TableLayout.java
+++ b/core/java/android/widget/TableLayout.java
@@ -184,6 +184,10 @@
             mShrinkableColumns = new SparseBooleanArray();
         }
 
+        // TableLayouts are always in vertical orientation; keep this tracked
+        // for shared LinearLayout code.
+        setOrientation(VERTICAL);
+
         mPassThroughListener = new PassThroughHierarchyChangeListener();
         // make sure to call the parent class method to avoid potential
         // infinite loops
@@ -737,7 +741,8 @@
          * @param heightAttr the height attribute to fetch
          */
         @Override
-        protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
+        protected void setBaseAttributes(TypedArray a,
+                int widthAttr, int heightAttr) {
             this.width = MATCH_PARENT;
             if (a.hasValue(heightAttr)) {
                 this.height = a.getLayoutDimension(heightAttr, "layout_height");
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index 01c4c2c..35927e0 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -226,7 +226,7 @@
                 final int childWidth = child.getMeasuredWidth();
                 lp.mOffset[LayoutParams.LOCATION_NEXT] = columnWidth - childWidth;
 
-                final int layoutDirection = getResolvedLayoutDirection();
+                final int layoutDirection = getLayoutDirection();
                 final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
                 switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
                     case Gravity.LEFT:
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
new file mode 100644
index 0000000..290d9b5
--- /dev/null
+++ b/core/java/android/widget/TextClock.java
@@ -0,0 +1,482 @@
+/*
+ * 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.widget;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.TypedArray;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.text.format.DateFormat;
+import android.util.AttributeSet;
+import android.view.RemotableViewMethod;
+
+import com.android.internal.R;
+
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import static android.view.ViewDebug.ExportedProperty;
+import static android.widget.RemoteViews.*;
+
+/**
+ * <p><code>TextClock</code> can display the current date and/or time as
+ * a formatted string.</p>
+ * 
+ * <p>This view honors the 24-hour format system setting. As such, it is
+ * possible and recommended to provide two different formatting patterns:
+ * one to display the date/time in 24-hour mode and one to display the
+ * date/time in 12-hour mode.</p>
+ * 
+ * <p>It is possible to determine whether the system is currently in
+ * 24-hour mode by calling {@link #is24HourModeEnabled()}.</p>
+ * 
+ * <p>The rules used by this widget to decide how to format the date and
+ * time are the following:</p>
+ * <ul>
+ *     <li>In 24-hour mode:
+ *         <ul>
+ *             <li>Use the value returned by {@link #getFormat24Hour()} when non-null</li>
+ *             <li>Otherwise, use the value returned by {@link #getFormat12Hour()} when non-null</li>
+ *             <li>Otherwise, use {@link #DEFAULT_FORMAT_24_HOUR}</li>
+ *         </ul>
+ *     </li>
+ *     <li>In 12-hour mode:
+ *         <ul>
+ *             <li>Use the value returned by {@link #getFormat12Hour()} when non-null</li>
+ *             <li>Otherwise, use the value returned by {@link #getFormat24Hour()} when non-null</li>
+ *             <li>Otherwise, use {@link #DEFAULT_FORMAT_12_HOUR}</li>
+ *         </ul>
+ *     </li>
+ * </ul>
+ * 
+ * <p>The {@link CharSequence} instances used as formatting patterns when calling either
+ * {@link #setFormat24Hour(CharSequence)} or {@link #setFormat12Hour(CharSequence)} can
+ * contain styling information. To do so, use a {@link android.text.Spanned} object.</p>
+ * 
+ * @attr ref android.R.styleable#TextClock_format12Hour
+ * @attr ref android.R.styleable#TextClock_format24Hour
+ * @attr ref android.R.styleable#TextClock_timeZone
+ */
+@RemoteView
+public class TextClock extends TextView {
+    /**
+     * The default formatting pattern in 12-hour mode. This pattenr is used
+     * if {@link #setFormat12Hour(CharSequence)} is called with a null pattern
+     * or if no pattern was specified when creating an instance of this class.
+     * 
+     * This default pattern shows only the time, hours and minutes, and an am/pm
+     * indicator.
+     *
+     * @see #setFormat12Hour(CharSequence)
+     * @see #getFormat12Hour()
+     */
+    public static final CharSequence DEFAULT_FORMAT_12_HOUR = "h:mm aa";
+
+    /**
+     * The default formatting pattern in 24-hour mode. This pattenr is used
+     * if {@link #setFormat24Hour(CharSequence)} is called with a null pattern
+     * or if no pattern was specified when creating an instance of this class.
+     *
+     * This default pattern shows only the time, hours and minutes.
+     * 
+     * @see #setFormat24Hour(CharSequence) 
+     * @see #getFormat24Hour() 
+     */
+    public static final CharSequence DEFAULT_FORMAT_24_HOUR = "k:mm";
+
+    private CharSequence mFormat12 = DEFAULT_FORMAT_12_HOUR;
+    private CharSequence mFormat24 = DEFAULT_FORMAT_24_HOUR;
+
+    @ExportedProperty
+    private CharSequence mFormat;
+    @ExportedProperty
+    private boolean mHasSeconds;
+
+    private boolean mAttached;
+
+    private Calendar mTime;
+    private String mTimeZone;
+
+    private final ContentObserver mFormatChangeObserver = new ContentObserver(new Handler()) {
+        @Override
+        public void onChange(boolean selfChange) {
+            chooseFormat();
+            onTimeChanged();
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            chooseFormat();
+            onTimeChanged();
+        }
+    };
+
+    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (mTimeZone == null && Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
+                final String timeZone = intent.getStringExtra("time-zone");
+                createTime(timeZone);
+            }
+            onTimeChanged();
+        }
+    };
+
+    private final Runnable mTicker = new Runnable() {
+        public void run() {
+            onTimeChanged();
+
+            long now = SystemClock.uptimeMillis();
+            long next = now + (1000 - now % 1000);
+
+            getHandler().postAtTime(mTicker, next);
+        }
+    };
+
+    /**
+     * Creates a new clock using the default patterns
+     * {@link #DEFAULT_FORMAT_24_HOUR} and {@link #DEFAULT_FORMAT_12_HOUR}
+     * respectively for the 24-hour and 12-hour modes.
+     * 
+     * @param context The Context the view is running in, through which it can
+     *        access the current theme, resources, etc.
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    public TextClock(Context context) {
+        super(context);
+        init();
+    }
+
+    /**
+     * Creates a new clock inflated from XML. This object's properties are
+     * intialized from the attributes specified in XML.
+     * 
+     * This constructor uses a default style of 0, so the only attribute values
+     * applied are those in the Context's Theme and the given AttributeSet.
+     *
+     * @param context The Context the view is running in, through which it can
+     *        access the current theme, resources, etc.
+     * @param attrs The attributes of the XML tag that is inflating the view
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    public TextClock(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    /**
+     * Creates a new clock inflated from XML. This object's properties are
+     * intialized from the attributes specified in XML.
+     *
+     * @param context The Context the view is running in, through which it can
+     *        access the current theme, resources, etc.
+     * @param attrs The attributes of the XML tag that is inflating the view
+     * @param defStyle The default style to apply to this view. If 0, no style
+     *        will be applied (beyond what is included in the theme). This may
+     *        either be an attribute resource, whose value will be retrieved
+     *        from the current theme, or an explicit style resource
+     */
+    public TextClock(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextClock, defStyle, 0);
+        try {
+            CharSequence format;
+
+            format = a.getText(R.styleable.TextClock_format12Hour);
+            mFormat12 = format == null ? DEFAULT_FORMAT_12_HOUR : format;
+
+            format = a.getText(R.styleable.TextClock_format24Hour);
+            mFormat24 = format == null ? DEFAULT_FORMAT_24_HOUR : format;
+
+            mTimeZone = a.getString(R.styleable.TextClock_timeZone);
+        } finally {
+            a.recycle();
+        }
+
+        init();
+    }
+
+    private void init() {
+        createTime(mTimeZone);
+        // Wait until onAttachedToWindow() to handle the ticker
+        chooseFormat(false);
+    }
+
+    private void createTime(String timeZone) {
+        if (timeZone != null) {
+            mTime = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
+        } else {
+            mTime = Calendar.getInstance();
+        }
+    }
+
+    /**
+     * Returns the formatting pattern used to display the date and/or time
+     * in 12-hour mode. The formatting pattern syntax is described in
+     * {@link DateFormat}.
+     * 
+     * @return A {@link CharSequence} or null.
+     * 
+     * @see #setFormat12Hour(CharSequence) 
+     * @see #is24HourModeEnabled() 
+     */
+    @ExportedProperty
+    public CharSequence getFormat12Hour() {
+        return mFormat12;
+    }
+
+    /**
+     * Specifies the formatting pattern used to display the date and/or time
+     * in 12-hour mode. The formatting pattern syntax is described in
+     * {@link DateFormat}.
+     *
+     * If this pattern is set to null, {@link #getFormat24Hour()} will be used
+     * even in 12-hour mode. If both 24-hour and 12-hour formatting patterns
+     * are set to null, {@link #DEFAULT_FORMAT_24_HOUR} and
+     * {@link #DEFAULT_FORMAT_12_HOUR} will be used instead.
+     *
+     * @param format A date/time formatting pattern as described in {@link DateFormat}
+     * 
+     * @see #getFormat12Hour()
+     * @see #is24HourModeEnabled()
+     * @see #DEFAULT_FORMAT_12_HOUR
+     * @see DateFormat
+     * 
+     * @attr ref android.R.styleable#TextClock_format12Hour
+     */
+    @RemotableViewMethod
+    public void setFormat12Hour(CharSequence format) {
+        mFormat12 = format;
+
+        chooseFormat();
+        onTimeChanged();
+    }
+
+    /**
+     * Returns the formatting pattern used to display the date and/or time
+     * in 24-hour mode. The formatting pattern syntax is described in
+     * {@link DateFormat}.
+     *
+     * @return A {@link CharSequence} or null.
+     *
+     * @see #setFormat24Hour(CharSequence)
+     * @see #is24HourModeEnabled()
+     */
+    @ExportedProperty
+    public CharSequence getFormat24Hour() {
+        return mFormat24;
+    }
+
+    /**
+     * Specifies the formatting pattern used to display the date and/or time
+     * in 24-hour mode. The formatting pattern syntax is described in
+     * {@link DateFormat}.
+     * 
+     * If this pattern is set to null, {@link #getFormat12Hour()} will be used
+     * even in 24-hour mode. If both 24-hour and 12-hour formatting patterns
+     * are set to null, {@link #DEFAULT_FORMAT_24_HOUR} and
+     * {@link #DEFAULT_FORMAT_12_HOUR} will be used instead.
+     *
+     * @param format A date/time formatting pattern as described in {@link DateFormat}
+     *
+     * @see #getFormat24Hour()
+     * @see #is24HourModeEnabled() 
+     * @see #DEFAULT_FORMAT_24_HOUR
+     * @see DateFormat
+     *
+     * @attr ref android.R.styleable#TextClock_format24Hour
+     */
+    @RemotableViewMethod
+    public void setFormat24Hour(CharSequence format) {
+        mFormat24 = format;
+
+        chooseFormat();
+        onTimeChanged();
+    }
+
+    /**
+     * Indicates whether the system is currently using the 24-hour mode.
+     * 
+     * When the system is in 24-hour mode, this view will use the pattern
+     * returned by {@link #getFormat24Hour()}. In 12-hour mode, the pattern
+     * returned by {@link #getFormat12Hour()} is used instead.
+     * 
+     * If either one of the formats is null, the other format is used. If
+     * both formats are null, the default values {@link #DEFAULT_FORMAT_12_HOUR}
+     * and {@link #DEFAULT_FORMAT_24_HOUR} are used instead.
+     * 
+     * @return true if time should be displayed in 24-hour format, false if it
+     *         should be displayed in 12-hour format.
+     * 
+     * @see #setFormat12Hour(CharSequence)
+     * @see #getFormat12Hour() 
+     * @see #setFormat24Hour(CharSequence)
+     * @see #getFormat24Hour() 
+     */
+    public boolean is24HourModeEnabled() {
+        return DateFormat.is24HourFormat(getContext());
+    }
+
+    /**
+     * Indicates which time zone is currently used by this view.
+     * 
+     * @return The ID of the current time zone or null if the default time zone,
+     *         as set by the user, must be used
+     *
+     * @see TimeZone
+     * @see java.util.TimeZone#getAvailableIDs()
+     * @see #setTimeZone(String) 
+     */
+    public String getTimeZone() {
+        return mTimeZone;
+    }
+
+    /**
+     * Sets the specified time zone to use in this clock. When the time zone
+     * is set through this method, system time zone changes (when the user
+     * sets the time zone in settings for instance) will be ignored.
+     *
+     * @param timeZone The desired time zone's ID as specified in {@link TimeZone}
+     *                 or null to user the time zone specified by the user
+     *                 (system time zone)
+     *
+     * @see #getTimeZone()
+     * @see java.util.TimeZone#getAvailableIDs()
+     * @see TimeZone#getTimeZone(String)
+     *
+     * @attr ref android.R.styleable#TextClock_timeZone
+     */
+    @RemotableViewMethod
+    public void setTimeZone(String timeZone) {
+        mTimeZone = timeZone;
+
+        createTime(timeZone);
+        onTimeChanged();
+    }
+
+    /**
+     * Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
+     * depending on whether the user has selected 24-hour format.
+     * 
+     * Calling this method does not schedule or unschedule the time ticker.
+     */
+    private void chooseFormat() {
+        chooseFormat(true);
+    }
+
+    /**
+     * Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
+     * depending on whether the user has selected 24-hour format.
+     * 
+     * @param handleTicker true if calling this method should schedule/unschedule the
+     *                     time ticker, false otherwise
+     */
+    private void chooseFormat(boolean handleTicker) {
+        final boolean format24Requested = is24HourModeEnabled();
+
+        if (format24Requested) {
+            mFormat = abc(mFormat24, mFormat12, DEFAULT_FORMAT_24_HOUR);
+        } else {
+            mFormat = abc(mFormat12, mFormat24, DEFAULT_FORMAT_12_HOUR);
+        }
+
+        boolean hadSeconds = mHasSeconds;
+        mHasSeconds = DateFormat.hasSeconds(mFormat);
+
+        if (handleTicker && mAttached && hadSeconds != mHasSeconds) {
+            if (hadSeconds) getHandler().removeCallbacks(mTicker);
+            else mTicker.run();
+        }
+    }
+
+    /**
+     * Returns a if not null, else return b if not null, else return c.
+     */
+    private static CharSequence abc(CharSequence a, CharSequence b, CharSequence c) {
+        return a == null ? (b == null ? c : b) : a;
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+
+        if (!mAttached) {
+            mAttached = true;
+
+            registerReceiver();
+            registerObserver();
+
+            createTime(mTimeZone);
+
+            if (mHasSeconds) {
+                mTicker.run();
+            } else {
+                onTimeChanged();
+            }
+        }
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+
+        if (mAttached) {
+            unregisterReceiver();
+            unregisterObserver();
+
+            getHandler().removeCallbacks(mTicker);
+
+            mAttached = false;
+        }
+    }
+
+    private void registerReceiver() {
+        final IntentFilter filter = new IntentFilter();
+
+        filter.addAction(Intent.ACTION_TIME_TICK);
+        filter.addAction(Intent.ACTION_TIME_CHANGED);
+        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+
+        getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());
+    }
+
+    private void registerObserver() {
+        final ContentResolver resolver = getContext().getContentResolver();
+        resolver.registerContentObserver(Settings.System.CONTENT_URI, true, mFormatChangeObserver);
+    }
+
+    private void unregisterReceiver() {
+        getContext().unregisterReceiver(mIntentReceiver);
+    }
+
+    private void unregisterObserver() {
+        final ContentResolver resolver = getContext().getContentResolver();
+        resolver.unregisterContentObserver(mFormatChangeObserver);
+    }
+
+    private void onTimeChanged() {
+        mTime.setTimeInMillis(System.currentTimeMillis());
+        setText(DateFormat.format(mFormat, mTime));
+    }
+}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 01617da..5d90400 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -33,6 +33,7 @@
 import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
 import android.inputmethodservice.ExtractEditText;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -132,6 +133,7 @@
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Locale;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * Displays text to the user and optionally allows them to edit it.  A TextView
@@ -302,8 +304,9 @@
 
     // The alignment to pass to Layout, or null if not resolved.
     private Layout.Alignment mLayoutAlignment;
+    private int mResolvedTextAlignment;
 
-    private boolean mResolvedDrawables;
+    private int mLastLayoutDirection = -1;
 
     /**
      * On some devices the fading edges add a performance penalty if used
@@ -364,6 +367,7 @@
     private boolean mSingleLine;
     private int mDesiredHeightAtMeasure = -1;
     private boolean mIncludePad = true;
+    private int mDeferScroll = -1;
 
     // tmp primitives, so we don't alloc them on each draw
     private Rect mTempRect;
@@ -377,6 +381,9 @@
 
     private InputFilter[] mFilters = NO_FILTERS;
 
+    private volatile Locale mCurrentTextServicesLocaleCache;
+    private final ReentrantLock mCurrentTextServicesLocaleLock = new ReentrantLock();
+
     // It is possible to have a selection even when mEditor is null (programmatically set, like when
     // a link is pressed). These highlight-related fields do not go in mEditor.
     int mHighlightColor = 0x6633B5E5;
@@ -1542,11 +1549,10 @@
     /**
      * Returns the start padding of the view, plus space for the start
      * Drawable if any.
-     * @hide
      */
     public int getCompoundPaddingStart() {
         resolveDrawables();
-        switch(getResolvedLayoutDirection()) {
+        switch(getLayoutDirection()) {
             default:
             case LAYOUT_DIRECTION_LTR:
                 return getCompoundPaddingLeft();
@@ -1558,11 +1564,10 @@
     /**
      * Returns the end padding of the view, plus space for the end
      * Drawable if any.
-     * @hide
      */
     public int getCompoundPaddingEnd() {
         resolveDrawables();
-        switch(getResolvedLayoutDirection()) {
+        switch(getLayoutDirection()) {
             default:
             case LAYOUT_DIRECTION_LTR:
                 return getCompoundPaddingRight();
@@ -1656,7 +1661,6 @@
     /**
      * Returns the total start padding of the view, including the start
      * Drawable if any.
-     * @hide
      */
     public int getTotalPaddingStart() {
         return getCompoundPaddingStart();
@@ -1665,7 +1669,6 @@
     /**
      * Returns the total end padding of the view, including the end
      * Drawable if any.
-     * @hide
      */
     public int getTotalPaddingEnd() {
         return getCompoundPaddingEnd();
@@ -1868,7 +1871,6 @@
      * @attr ref android.R.styleable#TextView_drawableTop
      * @attr ref android.R.styleable#TextView_drawableEnd
      * @attr ref android.R.styleable#TextView_drawableBottom
-     * @hide
      */
     public void setCompoundDrawablesRelative(Drawable start, Drawable top,
                                      Drawable end, Drawable bottom) {
@@ -1990,7 +1992,6 @@
      * @attr ref android.R.styleable#TextView_drawableTop
      * @attr ref android.R.styleable#TextView_drawableEnd
      * @attr ref android.R.styleable#TextView_drawableBottom
-     * @hide
      */
     @android.view.RemotableViewMethod
     public void setCompoundDrawablesRelativeWithIntrinsicBounds(int start, int top, int end,
@@ -2014,7 +2015,6 @@
      * @attr ref android.R.styleable#TextView_drawableTop
      * @attr ref android.R.styleable#TextView_drawableEnd
      * @attr ref android.R.styleable#TextView_drawableBottom
-     * @hide
      */
     public void setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top,
             Drawable end, Drawable bottom) {
@@ -2061,7 +2061,6 @@
      * @attr ref android.R.styleable#TextView_drawableTop
      * @attr ref android.R.styleable#TextView_drawableEnd
      * @attr ref android.R.styleable#TextView_drawableBottom
-     * @hide
      */
     public Drawable[] getCompoundDrawablesRelative() {
         final Drawables dr = mDrawables;
@@ -2211,6 +2210,27 @@
     }
 
     /**
+     * Get the default {@link Locale} of the text in this TextView.
+     * @return the default {@link Locale} of the text in this TextView.
+     */
+    public Locale getTextLocale() {
+        return mTextPaint.getTextLocale();
+    }
+
+    /**
+     * Set the default {@link Locale} of the text in this TextView to the given value. This value
+     * is used to choose appropriate typefaces for ambiguous characters. Typically used for CJK
+     * locales to disambiguate Hanzi/Kanji/Hanja characters.
+     *
+     * @param locale the {@link Locale} for drawing text, must not be null.
+     *
+     * @see Paint#setTextLocale
+     */
+    public void setTextLocale(Locale locale) {
+        mTextPaint.setTextLocale(locale);
+    }
+
+    /**
      * @return the size (in pixels) of the default text size in this TextView.
      */
     @ViewDebug.ExportedProperty(category = "text")
@@ -4449,9 +4469,6 @@
 
         mTemporaryDetach = false;
 
-        // Resolve drawables as the layout direction has been resolved
-        resolveDrawables();
-
         if (mEditor != null) mEditor.onAttachedToWindow();
     }
 
@@ -4586,23 +4603,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
-    @Override
-    public int getResolvedLayoutDirection(Drawable who) {
-        if (who == null) return View.LAYOUT_DIRECTION_LTR;
-        if (mDrawables != null) {
-            final Drawables drawables = mDrawables;
-            if (who == drawables.mDrawableLeft || who == drawables.mDrawableRight ||
-                who == drawables.mDrawableTop || who == drawables.mDrawableBottom ||
-                who == drawables.mDrawableStart || who == drawables.mDrawableEnd) {
-                return getResolvedLayoutDirection();
-            }
-        }
-        return super.getResolvedLayoutDirection(who);
-    }
-
     @Override
     public boolean hasOverlappingRendering() {
         return (getBackground() != null || mText instanceof Spannable || hasSelection());
@@ -4862,18 +4862,23 @@
         }
         canvas.translate(compoundPaddingLeft, extendedPaddingTop + voffsetText);
 
-        final int layoutDirection = getResolvedLayoutDirection();
+        final boolean isLayoutRtl = isLayoutRtl();
+
+        final int layoutDirection = getLayoutDirection();
         final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
         if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
                 mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
             if (!mSingleLine && getLineCount() == 1 && canMarquee() &&
                     (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) {
-                canvas.translate(mLayout.getLineRight(0) - (mRight - mLeft -
-                        getCompoundPaddingLeft() - getCompoundPaddingRight()), 0.0f);
+                final int width = mRight - mLeft;
+                final int padding = getCompoundPaddingLeft() + getCompoundPaddingRight();
+                final float dx = mLayout.getLineRight(0) - (width - padding);
+                canvas.translate(isLayoutRtl ? -dx : +dx, 0.0f);
             }
 
             if (mMarquee != null && mMarquee.isRunning()) {
-                canvas.translate(-mMarquee.mScroll, 0.0f);
+                final float dx = -mMarquee.getScroll();
+                canvas.translate(isLayoutRtl ? -dx : +dx, 0.0f);
             }
         }
 
@@ -4887,7 +4892,8 @@
         }
 
         if (mMarquee != null && mMarquee.shouldDrawGhost()) {
-            canvas.translate((int) mMarquee.getGhostOffset(), 0.0f);
+            final int dx = (int) mMarquee.getGhostOffset();
+            canvas.translate(isLayoutRtl ? -dx : dx, 0.0f);
             layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical);
         }
 
@@ -5634,13 +5640,11 @@
                       physicalWidth, false);
     }
 
-    /** @hide */
     @Override
-    public void onResolvedLayoutDirectionReset() {
+    public void onRtlPropertiesChanged(int layoutDirection) {
         if (mLayoutAlignment != null) {
-            int resolvedTextAlignment = getResolvedTextAlignment();
-            if (resolvedTextAlignment == TEXT_ALIGNMENT_VIEW_START ||
-                 resolvedTextAlignment == TEXT_ALIGNMENT_VIEW_END) {
+            if (mResolvedTextAlignment == TEXT_ALIGNMENT_VIEW_START ||
+                    mResolvedTextAlignment == TEXT_ALIGNMENT_VIEW_END) {
                 mLayoutAlignment = null;
             }
         }
@@ -5648,8 +5652,8 @@
 
     private Layout.Alignment getLayoutAlignment() {
         if (mLayoutAlignment == null) {
-            int textAlign = getResolvedTextAlignment();
-            switch (textAlign) {
+            mResolvedTextAlignment = getTextAlignment();
+            switch (mResolvedTextAlignment) {
                 case TEXT_ALIGNMENT_GRAVITY:
                     switch (mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) {
                         case Gravity.START:
@@ -5682,11 +5686,11 @@
                     mLayoutAlignment = Layout.Alignment.ALIGN_CENTER;
                     break;
                 case TEXT_ALIGNMENT_VIEW_START:
-                    mLayoutAlignment = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
+                    mLayoutAlignment = (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
                             Layout.Alignment.ALIGN_RIGHT : Layout.Alignment.ALIGN_LEFT;
                     break;
                 case TEXT_ALIGNMENT_VIEW_END:
-                    mLayoutAlignment = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
+                    mLayoutAlignment = (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
                             Layout.Alignment.ALIGN_LEFT : Layout.Alignment.ALIGN_RIGHT;
                     break;
                 case TEXT_ALIGNMENT_INHERIT:
@@ -5735,7 +5739,7 @@
         }
 
         if (mTextDir == null) {
-            resolveTextDirection();
+            mTextDir = getTextDirectionHeuristic();
         }
 
         mLayout = makeSingleLayout(wantWidth, boring, ellipsisWidth, alignment, shouldEllipsize,
@@ -5997,7 +6001,7 @@
         BoringLayout.Metrics hintBoring = UNKNOWN_BORING;
 
         if (mTextDir == null) {
-            resolveTextDirection();
+            getTextDirectionHeuristic();
         }
 
         int des = -1;
@@ -6314,6 +6318,11 @@
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
+        if (mDeferScroll >= 0) {
+            int curs = mDeferScroll;
+            mDeferScroll = -1;
+            bringPointIntoView(Math.min(curs, mText.length()));
+        }
         if (changed && mEditor != null) mEditor.invalidateTextDisplayList();
     }
 
@@ -6396,6 +6405,10 @@
      * This has to be called after layout. Returns true if anything changed.
      */
     public boolean bringPointIntoView(int offset) {
+        if (isLayoutRequested()) {
+            mDeferScroll = offset;
+            return false;
+        }
         boolean changed = false;
 
         Layout layout = isShowingHint() ? mHintLayout: mLayout;
@@ -7105,13 +7118,13 @@
             registerForPreDraw();
         }
 
+        checkForResize();
+
         if (curs >= 0) {
             mHighlightPathBogus = true;
             if (mEditor != null) mEditor.makeBlink();
             bringPointIntoView(curs);
         }
-
-        checkForResize();
     }
 
     /**
@@ -7158,6 +7171,7 @@
 
             if (oldStart >= 0 || newStart >= 0) {
                 invalidateCursor(Selection.getSelectionStart(buf), oldStart, newStart);
+                checkForResize();
                 registerForPreDraw();
                 if (mEditor != null) mEditor.makeBlink();
             }
@@ -7481,12 +7495,13 @@
             if (mMarquee != null && !mMarquee.isStopped()) {
                 final Marquee marquee = mMarquee;
                 if (marquee.shouldDrawLeftFade()) {
-                    return marquee.mScroll / getHorizontalFadingEdgeLength();
+                    final float scroll = marquee.getScroll();
+                    return scroll / getHorizontalFadingEdgeLength();
                 } else {
                     return 0.0f;
                 }
             } else if (getLineCount() == 1) {
-                final int layoutDirection = getResolvedLayoutDirection();
+                final int layoutDirection = getLayoutDirection();
                 final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
                 switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
                     case Gravity.LEFT:
@@ -7509,9 +7524,11 @@
                 mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
             if (mMarquee != null && !mMarquee.isStopped()) {
                 final Marquee marquee = mMarquee;
-                return (marquee.mMaxFadeScroll - marquee.mScroll) / getHorizontalFadingEdgeLength();
+                final float maxFadeScroll = marquee.getMaxFadeScroll();
+                final float scroll = marquee.getScroll();
+                return (maxFadeScroll - scroll) / getHorizontalFadingEdgeLength();
             } else if (getLineCount() == 1) {
-                final int layoutDirection = getResolvedLayoutDirection();
+                final int layoutDirection = getLayoutDirection();
                 final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
                 switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
                     case Gravity.LEFT:
@@ -7674,13 +7691,43 @@
 
     /**
      * This is a temporary method. Future versions may support multi-locale text.
+     * Caveat: This method may not return the latest text services locale, but this should be
+     * acceptable and it's more important to make this method asynchronous.
      *
      * @return The locale that should be used for a word iterator and a spell checker
      * in this TextView, based on the current spell checker settings,
      * the current IME's locale, or the system default locale.
      * @hide
      */
+    // TODO: Support multi-locale
+    // TODO: Update the text services locale immediately after the keyboard locale is switched
+    // by catching intent of keyboard switch event
     public Locale getTextServicesLocale() {
+        if (mCurrentTextServicesLocaleCache == null) {
+            // If there is no cached text services locale, just return the default locale.
+            mCurrentTextServicesLocaleCache = Locale.getDefault();
+        }
+        // Start fetching the text services locale asynchronously.
+        updateTextServicesLocaleAsync();
+        return mCurrentTextServicesLocaleCache;
+    }
+
+    private void updateTextServicesLocaleAsync() {
+        AsyncTask.execute(new Runnable() {
+            @Override
+            public void run() {
+                if (mCurrentTextServicesLocaleLock.tryLock()) {
+                    try {
+                        updateTextServicesLocaleLocked();
+                    } finally {
+                        mCurrentTextServicesLocaleLock.unlock();
+                    }
+                }
+            }
+        });
+    }
+
+    private void updateTextServicesLocaleLocked() {
         Locale locale = Locale.getDefault();
         final TextServicesManager textServicesManager = (TextServicesManager)
                 mContext.getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
@@ -7688,7 +7735,7 @@
         if (subtype != null) {
             locale = SpellCheckerSubtype.constructLocaleFromString(subtype.getLocale());
         }
-        return locale;
+        mCurrentTextServicesLocaleCache = locale;
     }
 
     void onLocaleChanged() {
@@ -8180,65 +8227,54 @@
         return mEditor.mInBatchEditControllers;
     }
 
-    /** @hide */
-    @Override
-    public void onResolvedTextDirectionChanged() {
+    TextDirectionHeuristic getTextDirectionHeuristic() {
         if (hasPasswordTransformationMethod()) {
             // TODO: take care of the content direction to show the password text and dots justified
             // to the left or to the right
-            mTextDir = TextDirectionHeuristics.LOCALE;
-            return;
+            return TextDirectionHeuristics.LOCALE;
         }
 
         // Always need to resolve layout direction first
-        final boolean defaultIsRtl = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
+        final boolean defaultIsRtl = (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
 
         // Now, we can select the heuristic
-        int textDir = getResolvedTextDirection();
-        switch (textDir) {
+        switch (getTextDirection()) {
             default:
             case TEXT_DIRECTION_FIRST_STRONG:
-                mTextDir = (defaultIsRtl ? TextDirectionHeuristics.FIRSTSTRONG_RTL :
+                return (defaultIsRtl ? TextDirectionHeuristics.FIRSTSTRONG_RTL :
                         TextDirectionHeuristics.FIRSTSTRONG_LTR);
-                break;
             case TEXT_DIRECTION_ANY_RTL:
-                mTextDir = TextDirectionHeuristics.ANYRTL_LTR;
-                break;
+                return TextDirectionHeuristics.ANYRTL_LTR;
             case TEXT_DIRECTION_LTR:
-                mTextDir = TextDirectionHeuristics.LTR;
-                break;
+                return TextDirectionHeuristics.LTR;
             case TEXT_DIRECTION_RTL:
-                mTextDir = TextDirectionHeuristics.RTL;
-                break;
+                return TextDirectionHeuristics.RTL;
             case TEXT_DIRECTION_LOCALE:
-                mTextDir = TextDirectionHeuristics.LOCALE;
-                break;
+                return TextDirectionHeuristics.LOCALE;
         }
     }
 
     /**
-     * Subclasses will need to override this method to implement their own way of resolving
-     * drawables depending on the layout direction.
-     *
-     * A call to the super method will be required from the subclasses implementation.
+     * @hide
      */
-    protected void resolveDrawables() {
+    @Override
+    public void onResolveDrawables(int layoutDirection) {
         // No need to resolve twice
-        if (mResolvedDrawables) {
+        if (mLastLayoutDirection == layoutDirection) {
             return;
         }
+        mLastLayoutDirection = layoutDirection;
         // No drawable to resolve
         if (mDrawables == null) {
             return;
         }
         // No relative drawable to resolve
         if (mDrawables.mDrawableStart == null && mDrawables.mDrawableEnd == null) {
-            mResolvedDrawables = true;
             return;
         }
 
         Drawables dr = mDrawables;
-        switch(getResolvedLayoutDirection()) {
+        switch(layoutDirection) {
             case LAYOUT_DIRECTION_RTL:
                 if (dr.mDrawableStart != null) {
                     dr.mDrawableRight = dr.mDrawableStart;
@@ -8270,11 +8306,29 @@
                 }
                 break;
         }
-        mResolvedDrawables = true;
+        updateDrawablesLayoutDirection(dr, layoutDirection);
     }
 
+    private void updateDrawablesLayoutDirection(Drawables dr, int layoutDirection) {
+        if (dr.mDrawableLeft != null) {
+            dr.mDrawableLeft.setLayoutDirection(layoutDirection);
+        }
+        if (dr.mDrawableRight != null) {
+            dr.mDrawableRight.setLayoutDirection(layoutDirection);
+        }
+        if (dr.mDrawableTop != null) {
+            dr.mDrawableTop.setLayoutDirection(layoutDirection);
+        }
+        if (dr.mDrawableBottom != null) {
+            dr.mDrawableBottom.setLayoutDirection(layoutDirection);
+        }
+    }
+
+    /**
+     * @hide
+     */
     protected void resetResolvedDrawables() {
-        mResolvedDrawables = false;
+        mLastLayoutDirection = -1;
     }
 
     /**
@@ -8341,7 +8395,7 @@
      */
     @Override
     public CharSequence getIterableTextForAccessibility() {
-        if (getContentDescription() == null) {
+        if (!TextUtils.isEmpty(mText)) {
             if (!(mText instanceof Spannable)) {
                 setText(mText, BufferType.SPANNABLE);
             }
@@ -8593,13 +8647,13 @@
         private byte mStatus = MARQUEE_STOPPED;
         private final float mScrollUnit;
         private float mMaxScroll;
-        float mMaxFadeScroll;
+        private float mMaxFadeScroll;
         private float mGhostStart;
         private float mGhostOffset;
         private float mFadeStop;
         private int mRepeatLimit;
 
-        float mScroll;
+        private float mScroll;
 
         Marquee(TextView v) {
             final float density = v.getContext().getResources().getDisplayMetrics().density;
@@ -8691,6 +8745,14 @@
             return mGhostOffset;
         }
 
+        float getScroll() {
+            return mScroll;
+        }
+
+        float getMaxFadeScroll() {
+            return mMaxFadeScroll;
+        }
+
         boolean shouldDrawLeftFade() {
             return mScroll <= mFadeStop;
         }
@@ -8718,8 +8780,8 @@
                     + " before=" + before + " after=" + after + ": " + buffer);
 
             if (AccessibilityManager.getInstance(mContext).isEnabled()
-                    && !isPasswordInputType(getInputType())
-                    && !hasPasswordTransformationMethod()) {
+                    && ((!isPasswordInputType(getInputType()) && !hasPasswordTransformationMethod())
+                            || shouldSpeakPasswordsForAccessibility())) {
                 mBeforeText = buffer.toString();
             }
 
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index cb9ed61..e6796cb 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -172,7 +172,7 @@
         mMinuteSpinner.setMinValue(0);
         mMinuteSpinner.setMaxValue(59);
         mMinuteSpinner.setOnLongPressUpdateInterval(100);
-        mMinuteSpinner.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
+        mMinuteSpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
         mMinuteSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
             public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
                 updateInputState();
@@ -500,7 +500,7 @@
         if (is24HourView()) {
             mHourSpinner.setMinValue(0);
             mHourSpinner.setMaxValue(23);
-            mHourSpinner.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
+            mHourSpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
         } else {
             mHourSpinner.setMinValue(1);
             mHourSpinner.setMaxValue(12);
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index fafc113..485bd37 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -19,6 +19,7 @@
 import android.app.INotificationManager;
 import android.app.ITransientNotification;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.PixelFormat;
 import android.os.Handler;
@@ -29,7 +30,6 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 
@@ -305,12 +305,14 @@
 
     private static class TN extends ITransientNotification.Stub {
         final Runnable mShow = new Runnable() {
+            @Override
             public void run() {
                 handleShow();
             }
         };
 
         final Runnable mHide = new Runnable() {
+            @Override
             public void run() {
                 handleHide();
                 // Don't do this in handleHide() because it is also invoked by handleShow()
@@ -329,8 +331,8 @@
        
         View mView;
         View mNextView;
-        
-        WindowManagerImpl mWM;
+
+        WindowManager mWM;
 
         TN() {
             // XXX This should be changed to use a Dialog, with a Theme.Toast
@@ -350,6 +352,7 @@
         /**
          * schedule handleShow into the right thread
          */
+        @Override
         public void show() {
             if (localLOGV) Log.v(TAG, "SHOW: " + this);
             mHandler.post(mShow);
@@ -358,6 +361,7 @@
         /**
          * schedule handleHide into the right thread
          */
+        @Override
         public void hide() {
             if (localLOGV) Log.v(TAG, "HIDE: " + this);
             mHandler.post(mHide);
@@ -370,8 +374,12 @@
                 // remove the old view if necessary
                 handleHide();
                 mView = mNextView;
-                mWM = WindowManagerImpl.getDefault();
-                final int gravity = mGravity;
+                mWM = (WindowManager)mView.getContext().getApplicationContext()
+                        .getSystemService(Context.WINDOW_SERVICE);
+                // We can resolve the Gravity here by using the Locale for getting
+                // the layout direction
+                final Configuration config = mView.getContext().getResources().getConfiguration();
+                final int gravity = Gravity.getAbsoluteGravity(mGravity, config.getLayoutDirection());
                 mParams.gravity = gravity;
                 if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
                     mParams.horizontalWeight = 1.0f;
diff --git a/core/java/android/widget/TwoLineListItem.java b/core/java/android/widget/TwoLineListItem.java
index e707ea3..f7e5266 100644
--- a/core/java/android/widget/TwoLineListItem.java
+++ b/core/java/android/widget/TwoLineListItem.java
@@ -37,7 +37,11 @@
  * layout for this object.
  * 
  * @attr ref android.R.styleable#TwoLineListItem_mode
+ * 
+ * @deprecated This class can be implemented easily by apps using a {@link RelativeLayout}
+ * or a {@link LinearLayout}.
  */
+@Deprecated
 @Widget
 public class TwoLineListItem extends RelativeLayout {
 
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index 0fba498..7c8196d 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -26,6 +26,7 @@
 import android.media.Metadata;
 import android.media.MediaPlayer.OnCompletionListener;
 import android.media.MediaPlayer.OnErrorListener;
+import android.media.MediaPlayer.OnInfoListener;
 import android.net.Uri;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -84,6 +85,7 @@
     private MediaPlayer.OnPreparedListener mOnPreparedListener;
     private int         mCurrentBufferPercentage;
     private OnErrorListener mOnErrorListener;
+    private OnInfoListener  mOnInfoListener;
     private int         mSeekWhenPrepared;  // recording the seek position while preparing
     private boolean     mCanPause;
     private boolean     mCanSeekBack;
@@ -230,6 +232,7 @@
             mDuration = -1;
             mMediaPlayer.setOnCompletionListener(mCompletionListener);
             mMediaPlayer.setOnErrorListener(mErrorListener);
+            mMediaPlayer.setOnInfoListener(mOnInfoListener);
             mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
             mCurrentBufferPercentage = 0;
             mMediaPlayer.setDataSource(mContext, mUri, mHeaders);
@@ -281,6 +284,7 @@
                 mVideoHeight = mp.getVideoHeight();
                 if (mVideoWidth != 0 && mVideoHeight != 0) {
                     getHolder().setFixedSize(mVideoWidth, mVideoHeight);
+                    requestLayout();
                 }
             }
     };
@@ -455,6 +459,16 @@
         mOnErrorListener = l;
     }
 
+    /**
+     * Register a callback to be invoked when an informational event
+     * occurs during playback or setup.
+     *
+     * @param l The callback that will be run
+     */
+    public void setOnInfoListener(OnInfoListener l) {
+        mOnInfoListener = l;
+    }
+
     SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback()
     {
         public void surfaceChanged(SurfaceHolder holder, int format,
diff --git a/core/java/android/widget/ViewAnimator.java b/core/java/android/widget/ViewAnimator.java
index 6a68240..eee914e 100644
--- a/core/java/android/widget/ViewAnimator.java
+++ b/core/java/android/widget/ViewAnimator.java
@@ -329,8 +329,21 @@
     }
 
     /**
+     * Returns whether the current View should be animated the first time the ViewAnimator
+     * is displayed.
+     *
+     * @return true if the current View will be animated the first time it is displayed,
+     * false otherwise.
+     *
+     * @see #setAnimateFirstView(boolean)
+     */
+    public boolean getAnimateFirstView() {
+        return mAnimateFirstTime;
+    }
+
+    /**
      * Indicates whether the current View should be animated the first time
-     * the ViewAnimation is displayed.
+     * the ViewAnimator is displayed.
      *
      * @param animate True to animate the current View the first time it is displayed,
      *                false otherwise.
diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java
index 02dc27b..a89c9c1 100644
--- a/core/java/android/widget/ZoomButtonsController.java
+++ b/core/java/android/widget/ZoomButtonsController.java
@@ -242,7 +242,7 @@
     private FrameLayout createContainer() {
         LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
         // Controls are positioned BOTTOM | CENTER with respect to the owner view.
-        lp.gravity = Gravity.TOP | Gravity.LEFT;
+        lp.gravity = Gravity.TOP | Gravity.START;
         lp.flags = LayoutParams.FLAG_NOT_TOUCHABLE |
                 LayoutParams.FLAG_NOT_FOCUSABLE |
                 LayoutParams.FLAG_LAYOUT_NO_LIMITS |
diff --git a/core/java/android/widget/package.html b/core/java/android/widget/package.html
index 7d94a4b..91d327c 100644
--- a/core/java/android/widget/package.html
+++ b/core/java/android/widget/package.html
@@ -1,11 +1,16 @@
 <HTML>
 <BODY>
+<p>
 The widget package contains (mostly visual) UI elements to use
-on your Application screen. You can design your own <p>
+on your Application screen. You can also design your own.
+</p>
+
+<p>
 To create your own widget, extend {@link android.view.View} or a subclass. To
 use your widget in layout XML, there are two additional files for you to
 create. Here is a list of files you'll need to create to implement a custom
 widget:
+</p>
 <ul>
 <li><b>Java implementation file</b> - This is the file that implements the
 behavior of the widget. If you can instantiate the object from layout XML,
@@ -19,14 +24,16 @@
 res/layout/ that describes the layout of your widget. You could also do
 this in code in your Java file.</li>
 </ul>
+
+<p>
 ApiDemos sample application has an example of creating a custom layout XML
 tag, LabelView. See the following files that demonstrate implementing and using
-a custom widget:</p>
+a custom widget:
+</p>
 <ul>
-    <li><strong>LabelView.java</strong> - The implentation file</li>
+    <li><strong>LabelView.java</strong> - The implementation file</li>
     <li><strong>res/values/attrs.xml</strong> - Definition file</li>
-    <li><strong>res/layout/custom_view_1.xml</strong> - Layout
-file</li>
+    <li><strong>res/layout/custom_view_1.xml</strong> - Layout file</li>
 </ul>
 </BODY>
 </HTML>
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 56b5937..43a02cf 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -764,6 +764,7 @@
         public DialogInterface.OnClickListener mNeutralButtonListener;
         public boolean mCancelable;
         public DialogInterface.OnCancelListener mOnCancelListener;
+        public DialogInterface.OnDismissListener mOnDismissListener;
         public DialogInterface.OnKeyListener mOnKeyListener;
         public CharSequence[] mItems;
         public ListAdapter mAdapter;
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 6a0cd36..1a76461 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -58,14 +58,14 @@
     void noteBluetoothOff();
     void noteFullWifiLockAcquired(int uid);
     void noteFullWifiLockReleased(int uid);
-    void noteScanWifiLockAcquired(int uid);
-    void noteScanWifiLockReleased(int uid);
+    void noteWifiScanStarted(int uid);
+    void noteWifiScanStopped(int uid);
     void noteWifiMulticastEnabled(int uid);
     void noteWifiMulticastDisabled(int uid);
     void noteFullWifiLockAcquiredFromSource(in WorkSource ws);
     void noteFullWifiLockReleasedFromSource(in WorkSource ws);
-    void noteScanWifiLockAcquiredFromSource(in WorkSource ws);
-    void noteScanWifiLockReleasedFromSource(in WorkSource ws);
+    void noteWifiScanStartedFromSource(in WorkSource ws);
+    void noteWifiScanStoppedFromSource(in WorkSource ws);
     void noteWifiMulticastEnabledFromSource(in WorkSource ws);
     void noteWifiMulticastDisabledFromSource(in WorkSource ws);
     void noteNetworkInterfaceType(String iface, int type);
diff --git a/core/java/com/android/internal/app/IMediaContainerService.aidl b/core/java/com/android/internal/app/IMediaContainerService.aidl
index c82834f7..03d3b22 100755
--- a/core/java/com/android/internal/app/IMediaContainerService.aidl
+++ b/core/java/com/android/internal/app/IMediaContainerService.aidl
@@ -36,4 +36,5 @@
     /** Return file system stats: [0] is total bytes, [1] is available bytes */
     long[] getFileSystemStats(in String path);
     void clearDirectory(in String directory);
+    long calculateInstalledSize(in String packagePath, boolean isForwardLocked);
 }
diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java
index 52cb679..f173327 100644
--- a/core/java/com/android/internal/app/LocalePicker.java
+++ b/core/java/com/android/internal/app/LocalePicker.java
@@ -28,9 +28,12 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.util.Log;
+import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 import android.widget.ListView;
+import android.widget.TextView;
 
 import java.text.Collator;
 import java.util.Arrays;
@@ -86,7 +89,7 @@
     }
 
     public static ArrayAdapter<LocaleInfo> constructAdapter(Context context,
-            int layoutId, int fieldId) {
+            final int layoutId, final int fieldId) {
         final Resources resources = context.getResources();
         final String[] locales = Resources.getSystem().getAssets().getLocales();
         final String[] specialLocaleCodes = resources.getStringArray(R.array.special_locale_codes);
@@ -154,7 +157,29 @@
             localeInfos[i] = preprocess[i];
         }
         Arrays.sort(localeInfos);
-        return new ArrayAdapter<LocaleInfo>(context, layoutId, fieldId, localeInfos);
+
+        final LayoutInflater inflater =
+                (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        return new ArrayAdapter<LocaleInfo>(context, layoutId, fieldId, localeInfos) {
+            @Override
+            public View getView(int position, View convertView, ViewGroup parent) {
+                View view;
+                TextView text;
+                if (convertView == null) {
+                    view = inflater.inflate(layoutId, parent, false);
+                    text = (TextView) view.findViewById(fieldId);
+                    view.setTag(text);
+                } else {
+                    view = convertView;
+                    text = (TextView) view.getTag();
+                }
+                LocaleInfo item = getItem(position);
+                text.setText(item.toString());
+                text.setTextLocale(item.getLocale());
+
+                return view;
+            }
+        };
     }
 
     private static String toTitleCase(String s) {
@@ -218,10 +243,9 @@
             IActivityManager am = ActivityManagerNative.getDefault();
             Configuration config = am.getConfiguration();
 
-            config.locale = locale;
-
-            // indicate this isn't some passing default - the user wants this remembered
-            config.userSetLocale = true;
+            // Will set userSetLocale to indicate this isn't some passing default - the user
+            // wants this remembered
+            config.setLocale(locale);
 
             am.updateConfiguration(config);
             // Trigger the dirty bit for the Settings Provider.
@@ -230,4 +254,4 @@
             // Intentionally left blank
         }
     }
-}
\ No newline at end of file
+}
diff --git a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
index f010d7b..386f387 100644
--- a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
+++ b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
@@ -25,7 +25,7 @@
 import android.app.MediaRouteButton;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
-import android.media.AudioManager;
+import android.hardware.display.DisplayManager;
 import android.media.MediaRouter;
 import android.media.MediaRouter.RouteCategory;
 import android.media.MediaRouter.RouteGroup;
@@ -70,6 +70,7 @@
     };
 
     MediaRouter mRouter;
+    DisplayManager mDisplayService;
     private int mRouteTypes;
 
     private LayoutInflater mInflater;
@@ -97,6 +98,7 @@
     public void onAttach(Activity activity) {
         super.onAttach(activity);
         mRouter = (MediaRouter) activity.getSystemService(Context.MEDIA_ROUTER_SERVICE);
+        mDisplayService = (DisplayManager) activity.getSystemService(Context.DISPLAY_SERVICE);
     }
 
     @Override
@@ -119,6 +121,15 @@
 
     public void setRouteTypes(int types) {
         mRouteTypes = types;
+        if ((mRouteTypes & MediaRouter.ROUTE_TYPE_LIVE_VIDEO) != 0 && mDisplayService == null) {
+            final Context activity = getActivity();
+            if (activity != null) {
+                mDisplayService = (DisplayManager) activity.getSystemService(
+                        Context.DISPLAY_SERVICE);
+            }
+        } else {
+            mDisplayService = null;
+        }
     }
 
     void updateVolume() {
@@ -194,6 +205,9 @@
     @Override
     public void onResume() {
         super.onResume();
+        if (mDisplayService != null) {
+            mDisplayService.scanWifiDisplays();
+        }
     }
 
     private static class ViewHolder {
@@ -253,7 +267,9 @@
                 final RouteCategory cat = mRouter.getCategoryAt(i);
                 routes = cat.getRoutes(mCatRouteList);
 
-                mItems.add(cat);
+                if (!cat.isSystem()) {
+                    mItems.add(cat);
+                }
 
                 if (cat == mCategoryEditingGroups) {
                     addGroupEditingCategoryRoutes(routes);
@@ -370,6 +386,7 @@
         public boolean isEnabled(int position) {
             switch (getItemViewType(position)) {
                 case VIEW_ROUTE:
+                    return ((RouteInfo) mItems.get(position)).isEnabled();
                 case VIEW_GROUPING_ROUTE:
                 case VIEW_GROUPING_DONE:
                     return true;
@@ -434,6 +451,7 @@
             }
 
             convertView.setActivated(position == mSelectedItemPosition);
+            convertView.setEnabled(isEnabled(position));
 
             return convertView;
         }
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 7334ac3..e63c57f 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -37,7 +37,7 @@
 import android.os.PatternMatcher;
 import android.os.Process;
 import android.os.RemoteException;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -76,6 +76,7 @@
     private int mIconDpi;
     private int mIconSize;
     private int mMaxColumns;
+    private int mLastSelected = GridView.INVALID_POSITION;
 
     private boolean mRegistered;
     private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@@ -132,7 +133,7 @@
         mAdapter = new ResolveListAdapter(this, intent, initialIntents, rList,
                 mLaunchedFromUid);
         int count = mAdapter.getCount();
-        if (mLaunchedFromUid < 0 || UserId.isIsolated(mLaunchedFromUid)) {
+        if (mLaunchedFromUid < 0 || UserHandle.isIsolated(mLaunchedFromUid)) {
             // Gulp!
             finish();
             return;
@@ -247,6 +248,7 @@
         if (mAlwaysUseOption) {
             final int checkedPos = mGrid.getCheckedItemPosition();
             final boolean enabled = checkedPos != GridView.INVALID_POSITION;
+            mLastSelected = checkedPos;
             mAlwaysButton.setEnabled(enabled);
             mOnceButton.setEnabled(enabled);
             if (enabled) {
@@ -257,14 +259,15 @@
 
     @Override
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-        if (mAlwaysUseOption) {
-            final int checkedPos = mGrid.getCheckedItemPosition();
-            final boolean enabled = checkedPos != GridView.INVALID_POSITION;
-            mAlwaysButton.setEnabled(enabled);
-            mOnceButton.setEnabled(enabled);
-            if (enabled) {
+        final int checkedPos = mGrid.getCheckedItemPosition();
+        final boolean hasValidSelection = checkedPos != GridView.INVALID_POSITION;
+        if (mAlwaysUseOption && (!hasValidSelection || mLastSelected != checkedPos)) {
+            mAlwaysButton.setEnabled(hasValidSelection);
+            mOnceButton.setEnabled(hasValidSelection);
+            if (hasValidSelection) {
                 mGrid.smoothScrollToPosition(checkedPos);
             }
+            mLastSelected = checkedPos;
         } else {
             startSelected(position, false);
         }
@@ -371,7 +374,8 @@
 
     void showAppDetails(ResolveInfo ri) {
         Intent in = new Intent().setAction("android.settings.APPLICATION_DETAILS_SETTINGS")
-                .setData(Uri.fromParts("package", ri.activityInfo.packageName, null));
+                .setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
+                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
         startActivity(in);
     }
 
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl b/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl
index 216d985..78b4466 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl
@@ -24,6 +24,7 @@
 oneway interface IAppWidgetHost {
     void updateAppWidget(int appWidgetId, in RemoteViews views);
     void providerChanged(int appWidgetId, in AppWidgetProviderInfo info);
+    void providersChanged();
     void viewDataChanged(int appWidgetId, int viewId);
 }
 
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index 7df45cf..cfb16fa 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -52,9 +52,9 @@
     AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId);
     boolean hasBindAppWidgetPermission(in String packageName);
     void setBindAppWidgetPermission(in String packageName, in boolean permission);
-    void bindAppWidgetId(int appWidgetId, in ComponentName provider);
+    void bindAppWidgetId(int appWidgetId, in ComponentName provider, in Bundle options);
     boolean bindAppWidgetIdIfAllowed(
-            in String packageName, int appWidgetId, in ComponentName provider);
+            in String packageName, int appWidgetId, in ComponentName provider, in Bundle options);
     void bindRemoteViewsService(int appWidgetId, in Intent intent, in IBinder connection);
     void unbindRemoteViewsService(int appWidgetId, in Intent intent);
     int[] getAppWidgetIds(in ComponentName provider);
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index 246b0c9..c5e7d9d 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -49,6 +49,7 @@
     public static final int RECOMMEND_FAILED_ALREADY_EXISTS = -4;
     public static final int RECOMMEND_MEDIA_UNAVAILABLE = -5;
     public static final int RECOMMEND_FAILED_INVALID_URI = -6;
+    public static final int RECOMMEND_FAILED_VERSION_DOWNGRADE = -7;
 
     private static final boolean localLOGV = true;
     private static final String TAG = "PackageHelper";
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index f41fcc6..20ecace 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -24,6 +24,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.UserHandle;
 
 import java.util.HashSet;
 
@@ -49,6 +50,7 @@
         sPackageFilt.addAction(Intent.ACTION_UID_REMOVED);
         sPackageFilt.addDataScheme("package");
         sNonDataFilt.addAction(Intent.ACTION_UID_REMOVED);
+        sNonDataFilt.addAction(Intent.ACTION_USER_STOPPED);
         sExternalFilt.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
         sExternalFilt.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
     }
@@ -61,11 +63,17 @@
     String[] mAppearingPackages;
     String[] mModifiedPackages;
     int mChangeType;
+    int mChangeUserId = UserHandle.USER_NULL;
     boolean mSomePackagesChanged;
-    
+
     String[] mTempArray = new String[1];
-    
+
     public void register(Context context, Looper thread, boolean externalStorage) {
+        register(context, thread, null, externalStorage);
+    }
+
+    public void register(Context context, Looper thread, UserHandle user,
+            boolean externalStorage) {
         if (mRegisteredContext != null) {
             throw new IllegalStateException("Already registered");
         }
@@ -83,10 +91,19 @@
         } else {
             mRegisteredHandler = new Handler(thread);
         }
-        context.registerReceiver(this, sPackageFilt, null, mRegisteredHandler);
-        context.registerReceiver(this, sNonDataFilt, null, mRegisteredHandler);
-        if (externalStorage) {
-            context.registerReceiver(this, sExternalFilt, null, mRegisteredHandler);
+        if (user != null) {
+            context.registerReceiverAsUser(this, user, sPackageFilt, null, mRegisteredHandler);
+            context.registerReceiverAsUser(this, user, sNonDataFilt, null, mRegisteredHandler);
+            if (externalStorage) {
+                context.registerReceiverAsUser(this, user, sExternalFilt, null,
+                        mRegisteredHandler);
+            }
+        } else {
+            context.registerReceiver(this, sPackageFilt, null, mRegisteredHandler);
+            context.registerReceiver(this, sNonDataFilt, null, mRegisteredHandler);
+            if (externalStorage) {
+                context.registerReceiver(this, sExternalFilt, null, mRegisteredHandler);
+            }
         }
     }
 
@@ -111,16 +128,29 @@
     
     public void onBeginPackageChanges() {
     }
-    
+
+    /**
+     * Called when a package is really added (and not replaced).
+     */
     public void onPackageAdded(String packageName, int uid) {
     }
-    
+
+    /**
+     * Called when a package is really removed (and not replaced).
+     */
     public void onPackageRemoved(String packageName, int uid) {
     }
-    
+
+    /**
+     * Called when a package is really removed (and not replaced) for
+     * all users on the device.
+     */
+    public void onPackageRemovedAllUsers(String packageName, int uid) {
+    }
+
     public void onPackageUpdateStarted(String packageName, int uid) {
     }
-    
+
     public void onPackageUpdateFinished(String packageName, int uid) {
     }
     
@@ -130,6 +160,9 @@
     public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
         return false;
     }
+
+    public void onHandleUserStop(Intent intent, int userHandle) {
+    }
     
     public void onUidRemoved(int uid) {
     }
@@ -144,10 +177,16 @@
     public static final int PACKAGE_UPDATING = 1;
     public static final int PACKAGE_TEMPORARY_CHANGE = 2;
     public static final int PACKAGE_PERMANENT_CHANGE = 3;
-    
+
+    /**
+     * Called when a package disappears for any reason.
+     */
     public void onPackageDisappeared(String packageName, int reason) {
     }
-    
+
+    /**
+     * Called when a package appears for any reason.
+     */
     public void onPackageAppeared(String packageName, int reason) {
     }
     
@@ -204,7 +243,11 @@
     
     public void onFinishPackageChanges() {
     }
-    
+
+    public int getChangingUserId() {
+        return mChangeUserId;
+    }
+
     String getPackageName(Intent intent) {
         Uri uri = intent.getData();
         String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
@@ -213,6 +256,12 @@
     
     @Override
     public void onReceive(Context context, Intent intent) {
+        mChangeUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+                UserHandle.USER_NULL);
+        if (mChangeUserId == UserHandle.USER_NULL) {
+            throw new IllegalArgumentException(
+                    "Intent broadcast does not contain user handle: " + intent);
+        }
         onBeginPackageChanges();
         
         mDisappearingPackages = mAppearingPackages = null;
@@ -265,6 +314,9 @@
                     // it when it is re-added.
                     mSomePackagesChanged = true;
                     onPackageRemoved(pkg, uid);
+                    if (intent.getBooleanExtra(Intent.EXTRA_REMOVED_FOR_ALL_USERS, false)) {
+                        onPackageRemovedAllUsers(pkg, uid);
+                    }
                 }
                 onPackageDisappeared(pkg, mChangeType);
             }
@@ -295,6 +347,10 @@
                     intent.getIntExtra(Intent.EXTRA_UID, 0), true);
         } else if (Intent.ACTION_UID_REMOVED.equals(action)) {
             onUidRemoved(intent.getIntExtra(Intent.EXTRA_UID, 0));
+        } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
+            if (intent.hasExtra(Intent.EXTRA_USER_HANDLE)) {
+                onHandleUserStop(intent, intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+            }
         } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
             String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
             mAppearingPackages = pkgList;
@@ -324,5 +380,6 @@
         }
         
         onFinishPackageChanges();
+        mChangeUserId = UserHandle.USER_NULL;
     }
 }
diff --git a/core/java/com/android/internal/net/LegacyVpnInfo.java b/core/java/com/android/internal/net/LegacyVpnInfo.java
index b620abac..d6f6d0b 100644
--- a/core/java/com/android/internal/net/LegacyVpnInfo.java
+++ b/core/java/com/android/internal/net/LegacyVpnInfo.java
@@ -17,8 +17,10 @@
 package com.android.internal.net;
 
 import android.app.PendingIntent;
+import android.net.NetworkInfo;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.Log;
 
 /**
  * A simple container used to carry information of the ongoing legacy VPN.
@@ -27,6 +29,8 @@
  * @hide
  */
 public class LegacyVpnInfo implements Parcelable {
+    private static final String TAG = "LegacyVpnInfo";
+
     public static final int STATE_DISCONNECTED = 0;
     public static final int STATE_INITIALIZING = 1;
     public static final int STATE_CONNECTING = 2;
@@ -66,4 +70,25 @@
             return new LegacyVpnInfo[size];
         }
     };
+
+    /**
+     * Return best matching {@link LegacyVpnInfo} state based on given
+     * {@link NetworkInfo}.
+     */
+    public static int stateFromNetworkInfo(NetworkInfo info) {
+        switch (info.getDetailedState()) {
+            case CONNECTING:
+                return STATE_CONNECTING;
+            case CONNECTED:
+                return STATE_CONNECTED;
+            case DISCONNECTED:
+                return STATE_DISCONNECTED;
+            case FAILED:
+                return STATE_FAILED;
+            default:
+                Log.w(TAG, "Unhandled state " + info.getDetailedState()
+                        + " ; treating as disconnected");
+                return STATE_DISCONNECTED;
+        }
+    }
 }
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index d6f9e07..956653b 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -22,6 +22,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.util.Preconditions;
+
 import java.util.List;
 
 /**
@@ -45,13 +47,14 @@
     }
 
     public static PendingIntent getIntentForStatusPanel(Context context, VpnConfig config) {
+        Preconditions.checkNotNull(config);
+
         Intent intent = new Intent();
         intent.setClassName(DIALOGS_PACKAGE, DIALOGS_PACKAGE + ".ManageDialog");
         intent.putExtra("config", config);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY |
                 Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-        return PendingIntent.getActivity(context, 0, intent, (config == null) ?
-                PendingIntent.FLAG_NO_CREATE : PendingIntent.FLAG_CANCEL_CURRENT);
+        return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
     }
 
     public String user;
@@ -64,6 +67,7 @@
     public List<String> searchDomains;
     public PendingIntent configureIntent;
     public long startTime = -1;
+    public boolean legacy;
 
     @Override
     public int describeContents() {
@@ -82,6 +86,7 @@
         out.writeStringList(searchDomains);
         out.writeParcelable(configureIntent, flags);
         out.writeLong(startTime);
+        out.writeInt(legacy ? 1 : 0);
     }
 
     public static final Parcelable.Creator<VpnConfig> CREATOR =
@@ -99,6 +104,7 @@
             config.searchDomains = in.createStringArrayList();
             config.configureIntent = in.readParcelable(null);
             config.startTime = in.readLong();
+            config.legacy = in.readInt() != 0;
             return config;
         }
 
diff --git a/core/java/com/android/internal/net/VpnProfile.aidl b/core/java/com/android/internal/net/VpnProfile.aidl
new file mode 100644
index 0000000..a072160
--- /dev/null
+++ b/core/java/com/android/internal/net/VpnProfile.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.internal.net;
+
+parcelable VpnProfile;
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
new file mode 100644
index 0000000..c9b7cb3
--- /dev/null
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -0,0 +1,215 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.net.InetAddress;
+import java.nio.charset.Charsets;
+
+/**
+ * Parcel-like entity class for VPN profiles. To keep things simple, all
+ * fields are package private. Methods are provided for serialization, so
+ * storage can be implemented easily. Two rules are set for this class.
+ * First, all fields must be kept non-null. Second, always make a copy
+ * using clone() before modifying.
+ *
+ * @hide
+ */
+public class VpnProfile implements Cloneable, Parcelable {
+    private static final String TAG = "VpnProfile";
+
+    // Match these constants with R.array.vpn_types.
+    public static final int TYPE_PPTP = 0;
+    public static final int TYPE_L2TP_IPSEC_PSK = 1;
+    public static final int TYPE_L2TP_IPSEC_RSA = 2;
+    public static final int TYPE_IPSEC_XAUTH_PSK = 3;
+    public static final int TYPE_IPSEC_XAUTH_RSA = 4;
+    public static final int TYPE_IPSEC_HYBRID_RSA = 5;
+    public static final int TYPE_MAX = 5;
+
+    // Entity fields.
+    public final String key;           // -1
+    public String name = "";           // 0
+    public int type = TYPE_PPTP;       // 1
+    public String server = "";         // 2
+    public String username = "";       // 3
+    public String password = "";       // 4
+    public String dnsServers = "";     // 5
+    public String searchDomains = "";  // 6
+    public String routes = "";         // 7
+    public boolean mppe = true;        // 8
+    public String l2tpSecret = "";     // 9
+    public String ipsecIdentifier = "";// 10
+    public String ipsecSecret = "";    // 11
+    public String ipsecUserCert = "";  // 12
+    public String ipsecCaCert = "";    // 13
+    public String ipsecServerCert = "";// 14
+
+    // Helper fields.
+    public boolean saveLogin = false;
+
+    public VpnProfile(String key) {
+        this.key = key;
+    }
+
+    public VpnProfile(Parcel in) {
+        key = in.readString();
+        name = in.readString();
+        type = in.readInt();
+        server = in.readString();
+        username = in.readString();
+        password = in.readString();
+        dnsServers = in.readString();
+        searchDomains = in.readString();
+        routes = in.readString();
+        mppe = in.readInt() != 0;
+        l2tpSecret = in.readString();
+        ipsecIdentifier = in.readString();
+        ipsecSecret = in.readString();
+        ipsecUserCert = in.readString();
+        ipsecCaCert = in.readString();
+        ipsecServerCert = in.readString();
+        saveLogin = in.readInt() != 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(key);
+        out.writeString(name);
+        out.writeInt(type);
+        out.writeString(server);
+        out.writeString(username);
+        out.writeString(password);
+        out.writeString(dnsServers);
+        out.writeString(searchDomains);
+        out.writeString(routes);
+        out.writeInt(mppe ? 1 : 0);
+        out.writeString(l2tpSecret);
+        out.writeString(ipsecIdentifier);
+        out.writeString(ipsecSecret);
+        out.writeString(ipsecUserCert);
+        out.writeString(ipsecCaCert);
+        out.writeString(ipsecServerCert);
+        out.writeInt(saveLogin ? 1 : 0);
+    }
+
+    public static VpnProfile decode(String key, byte[] value) {
+        try {
+            if (key == null) {
+                return null;
+            }
+
+            String[] values = new String(value, Charsets.UTF_8).split("\0", -1);
+            // There can be 14 or 15 values in ICS MR1.
+            if (values.length < 14 || values.length > 15) {
+                return null;
+            }
+
+            VpnProfile profile = new VpnProfile(key);
+            profile.name = values[0];
+            profile.type = Integer.valueOf(values[1]);
+            if (profile.type < 0 || profile.type > TYPE_MAX) {
+                return null;
+            }
+            profile.server = values[2];
+            profile.username = values[3];
+            profile.password = values[4];
+            profile.dnsServers = values[5];
+            profile.searchDomains = values[6];
+            profile.routes = values[7];
+            profile.mppe = Boolean.valueOf(values[8]);
+            profile.l2tpSecret = values[9];
+            profile.ipsecIdentifier = values[10];
+            profile.ipsecSecret = values[11];
+            profile.ipsecUserCert = values[12];
+            profile.ipsecCaCert = values[13];
+            profile.ipsecServerCert = (values.length > 14) ? values[14] : "";
+
+            profile.saveLogin = !profile.username.isEmpty() || !profile.password.isEmpty();
+            return profile;
+        } catch (Exception e) {
+            // ignore
+        }
+        return null;
+    }
+
+    public byte[] encode() {
+        StringBuilder builder = new StringBuilder(name);
+        builder.append('\0').append(type);
+        builder.append('\0').append(server);
+        builder.append('\0').append(saveLogin ? username : "");
+        builder.append('\0').append(saveLogin ? password : "");
+        builder.append('\0').append(dnsServers);
+        builder.append('\0').append(searchDomains);
+        builder.append('\0').append(routes);
+        builder.append('\0').append(mppe);
+        builder.append('\0').append(l2tpSecret);
+        builder.append('\0').append(ipsecIdentifier);
+        builder.append('\0').append(ipsecSecret);
+        builder.append('\0').append(ipsecUserCert);
+        builder.append('\0').append(ipsecCaCert);
+        builder.append('\0').append(ipsecServerCert);
+        return builder.toString().getBytes(Charsets.UTF_8);
+    }
+
+    /**
+     * Test if profile is valid for lockdown, which requires IPv4 address for
+     * both server and DNS. Server hostnames would require using DNS before
+     * connection.
+     */
+    public boolean isValidLockdownProfile() {
+        try {
+            InetAddress.parseNumericAddress(server);
+
+            for (String dnsServer : dnsServers.split(" +")) {
+                InetAddress.parseNumericAddress(this.dnsServers);
+            }
+            if (TextUtils.isEmpty(dnsServers)) {
+                Log.w(TAG, "DNS required");
+                return false;
+            }
+
+            // Everything checked out above
+            return true;
+
+        } catch (IllegalArgumentException e) {
+            Log.w(TAG, "Invalid address", e);
+            return false;
+        }
+    }
+
+    public static final Creator<VpnProfile> CREATOR = new Creator<VpnProfile>() {
+        @Override
+        public VpnProfile createFromParcel(Parcel in) {
+            return new VpnProfile(in);
+        }
+
+        @Override
+        public VpnProfile[] newArray(int size) {
+            return new VpnProfile[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index db752e9..94e7a06 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -87,7 +87,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 61 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 62 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -159,8 +159,8 @@
             = new SparseArray<ArrayList<StopwatchTimer>>();
     final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<StopwatchTimer>();
     final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<StopwatchTimer>();
-    final ArrayList<StopwatchTimer> mScanWifiLockTimers = new ArrayList<StopwatchTimer>();
     final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<StopwatchTimer>();
+    final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<StopwatchTimer>();
 
     // Last partial timers we use for distributing CPU usage.
     final ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<StopwatchTimer>();
@@ -320,6 +320,18 @@
         Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 5: totalTime
     };
 
+    private static final int[] WAKEUP_SOURCES_FORMAT = new int[] {
+        Process.PROC_TAB_TERM|Process.PROC_OUT_STRING,                // 0: name
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE|
+                              Process.PROC_OUT_LONG,                  // 1: count
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE
+                             |Process.PROC_OUT_LONG,                  // 6: totalTime
+    };
+
     private final String[] mProcWakelocksName = new String[3];
     private final long[] mProcWakelocksData = new long[3];
 
@@ -1028,34 +1040,44 @@
 
     private final Map<String, KernelWakelockStats> readKernelWakelockStats() {
 
+        FileInputStream is;
         byte[] buffer = new byte[8192];
         int len;
+        boolean wakeup_sources = false;
 
         try {
-            FileInputStream is = new FileInputStream("/proc/wakelocks");
-            len = is.read(buffer);
-            is.close();
-
-            if (len > 0) {
-                int i;
-                for (i=0; i<len; i++) {
-                    if (buffer[i] == '\0') {
-                        len = i;
-                        break;
-                    }
+            try {
+                is = new FileInputStream("/proc/wakelocks");
+            } catch (java.io.FileNotFoundException e) {
+                try {
+                    is = new FileInputStream("/d/wakeup_sources");
+                    wakeup_sources = true;
+                } catch (java.io.FileNotFoundException e2) {
+                    return null;
                 }
             }
-        } catch (java.io.FileNotFoundException e) {
-            return null;
+
+            len = is.read(buffer);
+            is.close();
         } catch (java.io.IOException e) {
             return null;
         }
 
-        return parseProcWakelocks(buffer, len);
+        if (len > 0) {
+            int i;
+            for (i=0; i<len; i++) {
+                if (buffer[i] == '\0') {
+                    len = i;
+                    break;
+                }
+            }
+        }
+
+        return parseProcWakelocks(buffer, len, wakeup_sources);
     }
 
     private final Map<String, KernelWakelockStats> parseProcWakelocks(
-            byte[] wlBuffer, int len) {
+            byte[] wlBuffer, int len, boolean wakeup_sources) {
         String name;
         int count;
         long totalTime;
@@ -1092,12 +1114,20 @@
                     if ((wlBuffer[j] & 0x80) != 0) wlBuffer[j] = (byte) '?';
                 }
                 boolean parsed = Process.parseProcLine(wlBuffer, startIndex, endIndex,
-                        PROC_WAKELOCKS_FORMAT, nameStringArray, wlData, null);
+                        wakeup_sources ? WAKEUP_SOURCES_FORMAT :
+                                         PROC_WAKELOCKS_FORMAT,
+                        nameStringArray, wlData, null);
 
                 name = nameStringArray[0];
                 count = (int) wlData[1];
-                // convert nanoseconds to microseconds with rounding.
-                totalTime = (wlData[2] + 500) / 1000;
+
+                if (wakeup_sources) {
+                        // convert milliseconds to microseconds
+                        totalTime = wlData[2] * 1000;
+                } else {
+                        // convert nanoseconds to microseconds with rounding.
+                        totalTime = (wlData[2] + 500) / 1000;
+                }
 
                 if (parsed && name.length() > 0) {
                     if (!m.containsKey(name)) {
@@ -2174,28 +2204,28 @@
         getUidStatsLocked(uid).noteFullWifiLockReleasedLocked();
     }
 
-    int mWifiScanLockNesting = 0;
+    int mWifiScanNesting = 0;
 
-    public void noteScanWifiLockAcquiredLocked(int uid) {
-        if (mWifiScanLockNesting == 0) {
-            mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG;
-            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan lock on to: "
+    public void noteWifiScanStartedLocked(int uid) {
+        if (mWifiScanNesting == 0) {
+            mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
+            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(SystemClock.elapsedRealtime());
         }
-        mWifiScanLockNesting++;
-        getUidStatsLocked(uid).noteScanWifiLockAcquiredLocked();
+        mWifiScanNesting++;
+        getUidStatsLocked(uid).noteWifiScanStartedLocked();
     }
 
-    public void noteScanWifiLockReleasedLocked(int uid) {
-        mWifiScanLockNesting--;
-        if (mWifiScanLockNesting == 0) {
-            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG;
-            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan lock off to: "
+    public void noteWifiScanStoppedLocked(int uid) {
+        mWifiScanNesting--;
+        if (mWifiScanNesting == 0) {
+            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
+            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(SystemClock.elapsedRealtime());
         }
-        getUidStatsLocked(uid).noteScanWifiLockReleasedLocked();
+        getUidStatsLocked(uid).noteWifiScanStoppedLocked();
     }
 
     int mWifiMulticastNesting = 0;
@@ -2236,17 +2266,17 @@
         }
     }
 
-    public void noteScanWifiLockAcquiredFromSourceLocked(WorkSource ws) {
+    public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
         int N = ws.size();
         for (int i=0; i<N; i++) {
-            noteScanWifiLockAcquiredLocked(ws.get(i));
+            noteWifiScanStartedLocked(ws.get(i));
         }
     }
 
-    public void noteScanWifiLockReleasedFromSourceLocked(WorkSource ws) {
+    public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
         int N = ws.size();
         for (int i=0; i<N; i++) {
-            noteScanWifiLockReleasedLocked(ws.get(i));
+            noteWifiScanStoppedLocked(ws.get(i));
         }
     }
 
@@ -2360,8 +2390,8 @@
         boolean mFullWifiLockOut;
         StopwatchTimer mFullWifiLockTimer;
 
-        boolean mScanWifiLockOut;
-        StopwatchTimer mScanWifiLockTimer;
+        boolean mWifiScanStarted;
+        StopwatchTimer mWifiScanTimer;
 
         boolean mWifiMulticastEnabled;
         StopwatchTimer mWifiMulticastTimer;
@@ -2405,8 +2435,8 @@
                     mWifiRunningTimers, mUnpluggables);
             mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
                     mFullWifiLockTimers, mUnpluggables);
-            mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
-                    mScanWifiLockTimers, mUnpluggables);
+            mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
+                    mWifiScanTimers, mUnpluggables);
             mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
                     mWifiMulticastTimers, mUnpluggables);
             mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
@@ -2518,22 +2548,22 @@
         }
 
         @Override
-        public void noteScanWifiLockAcquiredLocked() {
-            if (!mScanWifiLockOut) {
-                mScanWifiLockOut = true;
-                if (mScanWifiLockTimer == null) {
-                    mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
-                            mScanWifiLockTimers, mUnpluggables);
+        public void noteWifiScanStartedLocked() {
+            if (!mWifiScanStarted) {
+                mWifiScanStarted = true;
+                if (mWifiScanTimer == null) {
+                    mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
+                            mWifiScanTimers, mUnpluggables);
                 }
-                mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
+                mWifiScanTimer.startRunningLocked(BatteryStatsImpl.this);
             }
         }
 
         @Override
-        public void noteScanWifiLockReleasedLocked() {
-            if (mScanWifiLockOut) {
-                mScanWifiLockOut = false;
-                mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
+        public void noteWifiScanStoppedLocked() {
+            if (mWifiScanStarted) {
+                mWifiScanStarted = false;
+                mWifiScanTimer.stopRunningLocked(BatteryStatsImpl.this);
             }
         }
 
@@ -2614,11 +2644,11 @@
         }
 
         @Override
-        public long getScanWifiLockTime(long batteryRealtime, int which) {
-            if (mScanWifiLockTimer == null) {
+        public long getWifiScanTime(long batteryRealtime, int which) {
+            if (mWifiScanTimer == null) {
                 return 0;
             }
-            return mScanWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
+            return mWifiScanTimer.getTotalTimeLocked(batteryRealtime, which);
         }
 
         @Override
@@ -2651,9 +2681,12 @@
             if (mUserActivityCounters == null) {
                 initUserActivityLocked();
             }
-            if (type < 0) type = 0;
-            else if (type >= NUM_USER_ACTIVITY_TYPES) type = NUM_USER_ACTIVITY_TYPES-1;
-            mUserActivityCounters[type].stepAtomic();
+            if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
+                mUserActivityCounters[type].stepAtomic();
+            } else {
+                Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
+                        new Throwable());
+            }
         }
 
         @Override
@@ -2698,9 +2731,9 @@
                 active |= !mFullWifiLockTimer.reset(BatteryStatsImpl.this, false);
                 active |= mFullWifiLockOut;
             }
-            if (mScanWifiLockTimer != null) {
-                active |= !mScanWifiLockTimer.reset(BatteryStatsImpl.this, false);
-                active |= mScanWifiLockOut;
+            if (mWifiScanTimer != null) {
+                active |= !mWifiScanTimer.reset(BatteryStatsImpl.this, false);
+                active |= mWifiScanStarted;
             }
             if (mWifiMulticastTimer != null) {
                 active |= !mWifiMulticastTimer.reset(BatteryStatsImpl.this, false);
@@ -2791,8 +2824,8 @@
                 if (mFullWifiLockTimer != null) {
                     mFullWifiLockTimer.detach();
                 }
-                if (mScanWifiLockTimer != null) {
-                    mScanWifiLockTimer.detach();
+                if (mWifiScanTimer != null) {
+                    mWifiScanTimer.detach();
                 }
                 if (mWifiMulticastTimer != null) {
                     mWifiMulticastTimer.detach();
@@ -2860,9 +2893,9 @@
             } else {
                 out.writeInt(0);
             }
-            if (mScanWifiLockTimer != null) {
+            if (mWifiScanTimer != null) {
                 out.writeInt(1);
-                mScanWifiLockTimer.writeToParcel(out, batteryRealtime);
+                mWifiScanTimer.writeToParcel(out, batteryRealtime);
             } else {
                 out.writeInt(0);
             }
@@ -2954,12 +2987,12 @@
             } else {
                 mFullWifiLockTimer = null;
             }
-            mScanWifiLockOut = false;
+            mWifiScanStarted = false;
             if (in.readInt() != 0) {
-                mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
-                        mScanWifiLockTimers, mUnpluggables, in);
+                mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
+                        mWifiScanTimers, mUnpluggables, in);
             } else {
-                mScanWifiLockTimer = null;
+                mWifiScanTimer = null;
             }
             mWifiMulticastEnabled = false;
             if (in.readInt() != 0) {
@@ -5118,9 +5151,9 @@
             if (in.readInt() != 0) {
                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
             }
-            u.mScanWifiLockOut = false;
+            u.mWifiScanStarted = false;
             if (in.readInt() != 0) {
-                u.mScanWifiLockTimer.readSummaryFromParcelLocked(in);
+                u.mWifiScanTimer.readSummaryFromParcelLocked(in);
             }
             u.mWifiMulticastEnabled = false;
             if (in.readInt() != 0) {
@@ -5310,9 +5343,9 @@
             } else {
                 out.writeInt(0);
             }
-            if (u.mScanWifiLockTimer != null) {
+            if (u.mWifiScanTimer != null) {
                 out.writeInt(1);
-                u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+                u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL);
             } else {
                 out.writeInt(0);
             }
@@ -5537,7 +5570,7 @@
         mWindowTimers.clear();
         mWifiRunningTimers.clear();
         mFullWifiLockTimers.clear();
-        mScanWifiLockTimers.clear();
+        mWifiScanTimers.clear();
         mWifiMulticastTimers.clear();
 
         sNumSpeedSteps = in.readInt();
diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java
index a94fb1e..84699dc 100644
--- a/core/java/com/android/internal/os/HandlerCaller.java
+++ b/core/java/com/android/internal/os/HandlerCaller.java
@@ -22,35 +22,14 @@
 import android.os.Message;
 
 public class HandlerCaller {
-    private static final String TAG = "HandlerCaller";
-    private static final boolean DEBUG = false;
-    
+
     public final Context mContext;
     
     final Looper mMainLooper;
     final Handler mH;
 
     final Callback mCallback;
-    
-    public static class SomeArgs {
-        SomeArgs next;
-        
-        public Object arg1;
-        public Object arg2;
-        public Object arg3;
-        public Object arg4;
-        public int argi1;
-        public int argi2;
-        public int argi3;
-        public int argi4;
-        public int argi5;
-        public int argi6;
-    }
-    
-    static final int ARGS_POOL_MAX_SIZE = 10;
-    int mArgsPoolSize;
-    SomeArgs mArgsPool;
-    
+
     class MyHandler extends Handler {
         MyHandler(Looper looper) {
             super(looper);
@@ -80,29 +59,6 @@
         mCallback = callback;
     }
 
-    public SomeArgs obtainArgs() {
-        synchronized (mH) {
-            SomeArgs args = mArgsPool;
-            if (args != null) {
-                mArgsPool = args.next;
-                args.next = null;
-                mArgsPoolSize--;
-                return args;
-            }
-        }
-        return new SomeArgs();
-    }
-    
-    public void recycleArgs(SomeArgs args) {
-        synchronized (mH) {
-            if (mArgsPoolSize < ARGS_POOL_MAX_SIZE) {
-                args.next = mArgsPool;
-                mArgsPool = args;
-                mArgsPoolSize++;
-            }
-        }
-    }
-    
     public void executeOrSendMessage(Message msg) {
         // If we are calling this from the main thread, then we can call
         // right through.  Otherwise, we need to send the message to the
@@ -141,7 +97,7 @@
     }
     
     public Message obtainMessageBOO(int what, boolean arg1, Object arg2, Object arg3) {
-        SomeArgs args = obtainArgs();
+        SomeArgs args = SomeArgs.obtain();
         args.arg1 = arg2;
         args.arg2 = arg3;
         return mH.obtainMessage(what, arg1 ? 1 : 0, 0, args);
@@ -169,28 +125,28 @@
     
     public Message obtainMessageIIOO(int what, int arg1, int arg2,
             Object arg3, Object arg4) {
-        SomeArgs args = obtainArgs();
+        SomeArgs args = SomeArgs.obtain();
         args.arg1 = arg3;
         args.arg2 = arg4;
         return mH.obtainMessage(what, arg1, arg2, args);
     }
     
     public Message obtainMessageIOO(int what, int arg1, Object arg2, Object arg3) {
-        SomeArgs args = obtainArgs();
+        SomeArgs args = SomeArgs.obtain();
         args.arg1 = arg2;
         args.arg2 = arg3;
         return mH.obtainMessage(what, arg1, 0, args);
     }
     
     public Message obtainMessageOO(int what, Object arg1, Object arg2) {
-        SomeArgs args = obtainArgs();
+        SomeArgs args = SomeArgs.obtain();
         args.arg1 = arg1;
         args.arg2 = arg2;
         return mH.obtainMessage(what, 0, 0, args);
     }
     
     public Message obtainMessageOOO(int what, Object arg1, Object arg2, Object arg3) {
-        SomeArgs args = obtainArgs();
+        SomeArgs args = SomeArgs.obtain();
         args.arg1 = arg1;
         args.arg2 = arg2;
         args.arg3 = arg3;
@@ -199,7 +155,7 @@
     
     public Message obtainMessageOOOO(int what, Object arg1, Object arg2,
             Object arg3, Object arg4) {
-        SomeArgs args = obtainArgs();
+        SomeArgs args = SomeArgs.obtain();
         args.arg1 = arg1;
         args.arg2 = arg2;
         args.arg3 = arg3;
@@ -209,7 +165,7 @@
     
     public Message obtainMessageIIII(int what, int arg1, int arg2,
             int arg3, int arg4) {
-        SomeArgs args = obtainArgs();
+        SomeArgs args = SomeArgs.obtain();
         args.argi1 = arg1;
         args.argi2 = arg2;
         args.argi3 = arg3;
@@ -219,7 +175,7 @@
     
     public Message obtainMessageIIIIII(int what, int arg1, int arg2,
             int arg3, int arg4, int arg5, int arg6) {
-        SomeArgs args = obtainArgs();
+        SomeArgs args = SomeArgs.obtain();
         args.argi1 = arg1;
         args.argi2 = arg2;
         args.argi3 = arg3;
@@ -231,7 +187,7 @@
     
     public Message obtainMessageIIIIO(int what, int arg1, int arg2,
             int arg3, int arg4, Object arg5) {
-        SomeArgs args = obtainArgs();
+        SomeArgs args = SomeArgs.obtain();
         args.arg1 = arg5;
         args.argi1 = arg1;
         args.argi2 = arg2;
diff --git a/core/java/com/android/internal/os/SomeArgs.java b/core/java/com/android/internal/os/SomeArgs.java
new file mode 100644
index 0000000..88e58dc
--- /dev/null
+++ b/core/java/com/android/internal/os/SomeArgs.java
@@ -0,0 +1,95 @@
+/*
+ * 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.internal.os;
+
+/**
+ * Helper class for passing more arguments though a message
+ * and avoiding allocation of a custom class for wrapping the
+ * arguments. This class maintains a pool of instances and
+ * it is responsibility of the client to recycle and instance
+ * once it is no longer used.
+ */
+public final class SomeArgs {
+
+    private static final int MAX_POOL_SIZE = 10;
+
+    private static SomeArgs sPool;
+    private static int sPoolSize;
+    private static Object sPoolLock = new Object();
+
+    private SomeArgs mNext;
+
+    private boolean mInPool;
+
+    public Object arg1;
+    public Object arg2;
+    public Object arg3;
+    public Object arg4;
+    public int argi1;
+    public int argi2;
+    public int argi3;
+    public int argi4;
+    public int argi5;
+    public int argi6;
+
+    private SomeArgs() {
+        /* do nothing - reduce visibility */
+    }
+
+    public static SomeArgs obtain() {
+        synchronized (sPoolLock) {
+            if (sPoolSize > 0) {
+                SomeArgs args = sPool;
+                sPool = sPool.mNext;
+                args.mNext = null;
+                args.mInPool = false;
+                sPoolSize--;
+                return args;
+            } else {
+                return new SomeArgs();
+            }
+        }
+    }
+
+    public void recycle() {
+        if (mInPool) {
+            throw new IllegalStateException("Already recycled.");
+        }
+        synchronized (sPoolLock) {
+            clear();
+            if (sPoolSize < MAX_POOL_SIZE) {
+                mNext = sPool;
+                mInPool = true;
+                sPool = this;
+                sPoolSize++;
+            }
+        }
+    }
+
+    private void clear() {
+        arg1 = null;
+        arg2 = null;
+        arg3 = null;
+        arg4 = null;
+        argi1 = 0;
+        argi2 = 0;
+        argi3 = 0;
+        argi4 = 0;
+        argi5 = 0;
+        argi6 = 0;
+    }
+}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index b016e99..d24513a3 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -18,16 +18,14 @@
 
 import android.net.Credentials;
 import android.net.LocalSocket;
-import android.os.Build;
 import android.os.Process;
+import android.os.SELinux;
 import android.os.SystemProperties;
 import android.util.Log;
 
 import dalvik.system.PathClassLoader;
 import dalvik.system.Zygote;
 
-import android.os.SELinux;
-
 import java.io.BufferedReader;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
@@ -234,9 +232,9 @@
                 ZygoteInit.setCloseOnExec(serverPipeFd, true);
             }
 
-            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
-                    parsedArgs.gids, parsedArgs.debugFlags, rlimits,
-                    parsedArgs.seInfo, parsedArgs.niceName);
+            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
+                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
+                    parsedArgs.niceName);
         } catch (IOException ex) {
             logAndPrintError(newStderr, "Exception creating pipe", ex);
         } catch (ErrnoException ex) {
@@ -341,6 +339,9 @@
          */
         int debugFlags;
 
+        /** From --mount-external */
+        int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
+
         /** from --target-sdk-version. */
         int targetSdkVersion;
         boolean targetSdkVersionSpecified;
@@ -526,6 +527,10 @@
                                 "Duplicate arg specified");
                     }
                     niceName = arg.substring(arg.indexOf('=') + 1);
+                } else if (arg.equals("--mount-external-multiuser")) {
+                    mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
+                } else if (arg.equals("--mount-external-multiuser-all")) {
+                    mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
                 } else {
                     break;
                 }
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 4924326..9e43749 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -386,7 +386,12 @@
                 Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
             }
             if (id != 0) {
-                mResources.getColorStateList(id);
+                if (mResources.getColorStateList(id) == null) {
+                    throw new IllegalArgumentException(
+                            "Unable to find preloaded color resource #0x"
+                            + Integer.toHexString(id)
+                            + " (" + ar.getString(i) + ")");
+                }
             }
         }
         return N;
@@ -409,11 +414,11 @@
                 Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
             }
             if (id != 0) {
-                Drawable dr = mResources.getDrawable(id);
-                if ((dr.getChangingConfigurations()&~ActivityInfo.CONFIG_FONT_SCALE) != 0) {
-                    Log.w(TAG, "Preloaded drawable resource #0x"
+                if (mResources.getDrawable(id) == null) {
+                    throw new IllegalArgumentException(
+                            "Unable to find preloaded drawable resource #0x"
                             + Integer.toHexString(id)
-                            + " (" + ar.getString(i) + ") that varies with configuration!!");
+                            + " (" + ar.getString(i) + ")");
                 }
             }
         }
diff --git a/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java b/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java
index 3905c88..fb7f215 100644
--- a/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java
+++ b/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java
@@ -122,7 +122,7 @@
     public void onCancel(DialogInterface dialog) {
         IMountService mountService = getMountService();
         String extStoragePath = mStorageVolume == null ?
-                Environment.getExternalStorageDirectory().toString() :
+                Environment.getLegacyExternalStorageDirectory().toString() :
                 mStorageVolume.getPath();
         try {
             mountService.mountVolume(extStoragePath);
@@ -149,7 +149,7 @@
             updateProgressDialog(R.string.progress_unmounting);
             IMountService mountService = getMountService();
             final String extStoragePath = mStorageVolume == null ?
-                    Environment.getExternalStorageDirectory().toString() :
+                    Environment.getLegacyExternalStorageDirectory().toString() :
                     mStorageVolume.getPath();
             try {
                 // Remove encryption mapping if this is an unmount for a factory reset.
@@ -163,7 +163,7 @@
             updateProgressDialog(R.string.progress_erasing);
             final IMountService mountService = getMountService();
             final String extStoragePath = mStorageVolume == null ?
-                    Environment.getExternalStorageDirectory().toString() :
+                    Environment.getLegacyExternalStorageDirectory().toString() :
                     mStorageVolume.getPath();
             if (mountService != null) {
                 new Thread() {
diff --git a/core/java/com/android/internal/policy/IFaceLockCallback.aidl b/core/java/com/android/internal/policy/IFaceLockCallback.aidl
index eb902fd..280e4d5 100644
--- a/core/java/com/android/internal/policy/IFaceLockCallback.aidl
+++ b/core/java/com/android/internal/policy/IFaceLockCallback.aidl
@@ -22,6 +22,5 @@
     void unlock();
     void cancel();
     void reportFailedAttempt();
-    void exposeFallback();
     void pokeWakelock(int millis);
 }
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 294d4c4..780f5b3 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -28,8 +28,9 @@
     void updateNotification(IBinder key, in StatusBarNotification notification);
     void removeNotification(IBinder key);
     void disable(int state);
-    void animateExpand();
-    void animateCollapse();
+    void animateExpandNotificationsPanel();
+    void animateExpandSettingsPanel();
+    void animateCollapsePanels();
     void setSystemUiVisibility(int vis, int mask);
     void topAppWindowChanged(boolean menuVisible);
     void setImeWindowStatus(in IBinder token, int vis, int backDisposition);
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index c64f170..04e5bc9 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -24,14 +24,16 @@
 /** @hide */
 interface IStatusBarService
 {
-    void expand();
-    void collapse();
+    void expandNotificationsPanel();
+    void collapsePanels();
     void disable(int what, IBinder token, String pkg);
     void setIcon(String slot, String iconPackage, int iconId, int iconLevel, String contentDescription);
     void setIconVisibility(String slot, boolean visible);
     void removeIcon(String slot);
     void topAppWindowChanged(boolean menuVisible);
     void setImeWindowStatus(in IBinder token, int vis, int backDisposition);
+    void expandSettingsPanel();
+    void setCurrentUser(int newUserId);
 
     // ---- Methods below are for use by the status bar policy services ----
     // You need the STATUS_BAR_SERVICE permission
diff --git a/core/java/com/android/internal/statusbar/StatusBarIcon.java b/core/java/com/android/internal/statusbar/StatusBarIcon.java
index 3333c82..e0792cb 100644
--- a/core/java/com/android/internal/statusbar/StatusBarIcon.java
+++ b/core/java/com/android/internal/statusbar/StatusBarIcon.java
@@ -18,18 +18,21 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
 
 public class StatusBarIcon implements Parcelable {
     public String iconPackage;
+    public UserHandle user;
     public int iconId;
     public int iconLevel;
     public boolean visible = true;
     public int number;
     public CharSequence contentDescription;
 
-    public StatusBarIcon(String iconPackage, int iconId, int iconLevel, int number,
+    public StatusBarIcon(String iconPackage, UserHandle user, int iconId, int iconLevel, int number,
             CharSequence contentDescription) {
         this.iconPackage = iconPackage;
+        this.user = user;
         this.iconId = iconId;
         this.iconLevel = iconLevel;
         this.number = number;
@@ -38,15 +41,16 @@
 
     @Override
     public String toString() {
-        return "StatusBarIcon(pkg=" + this.iconPackage + " id=0x" + Integer.toHexString(this.iconId)
+        return "StatusBarIcon(pkg=" + this.iconPackage + "user=" + user.getIdentifier()
+                + " id=0x" + Integer.toHexString(this.iconId)
                 + " level=" + this.iconLevel + " visible=" + visible
                 + " num=" + this.number + " )";
     }
 
     @Override
     public StatusBarIcon clone() {
-        StatusBarIcon that = new StatusBarIcon(this.iconPackage, this.iconId, this.iconLevel,
-                this.number, this.contentDescription);
+        StatusBarIcon that = new StatusBarIcon(this.iconPackage, this.user, this.iconId,
+                this.iconLevel, this.number, this.contentDescription);
         that.visible = this.visible;
         return that;
     }
@@ -60,6 +64,7 @@
 
     public void readFromParcel(Parcel in) {
         this.iconPackage = in.readString();
+        this.user = (UserHandle) in.readParcelable(null);
         this.iconId = in.readInt();
         this.iconLevel = in.readInt();
         this.visible = in.readInt() != 0;
@@ -69,6 +74,7 @@
 
     public void writeToParcel(Parcel out, int flags) {
         out.writeString(this.iconPackage);
+        out.writeParcelable(this.user, 0);
         out.writeInt(this.iconId);
         out.writeInt(this.iconLevel);
         out.writeInt(this.visible ? 1 : 0);
diff --git a/core/java/com/android/internal/statusbar/StatusBarNotification.java b/core/java/com/android/internal/statusbar/StatusBarNotification.java
index d443523..a91aa3c 100644
--- a/core/java/com/android/internal/statusbar/StatusBarNotification.java
+++ b/core/java/com/android/internal/statusbar/StatusBarNotification.java
@@ -19,8 +19,7 @@
 import android.app.Notification;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.widget.RemoteViews;
-
+import android.os.UserHandle;
 
 /*
 boolean clearable = !n.ongoingEvent && ((notification.flags & Notification.FLAG_NO_CLEAR) == 0);
@@ -38,19 +37,26 @@
  * Class encapsulating a Notification. Sent by the NotificationManagerService to the IStatusBar (in System UI).
  */
 public class StatusBarNotification implements Parcelable {
-    public String pkg;
-    public int id;
-    public String tag;
-    public int uid;
-    public int initialPid;
-    public Notification notification;
-    public int score;
-    
-    public StatusBarNotification() {
+    public final String pkg;
+    public final int id;
+    public final String tag;
+    public final int uid;
+    public final int initialPid;
+    // TODO: make this field private and move callers to an accessor that
+    // ensures sourceUser is applied.
+    public final Notification notification;
+    public final int score;
+    public final UserHandle user;
+
+    /** This is temporarily needed for the JB MR1 PDK. */
+    @Deprecated
+    public StatusBarNotification(String pkg, int id, String tag, int uid, int initialPid, int score,
+            Notification notification) {
+        this(pkg, id, tag, uid, initialPid, score, notification, UserHandle.OWNER);
     }
 
-    public StatusBarNotification(String pkg, int id, String tag,
-            int uid, int initialPid, int score, Notification notification) {
+    public StatusBarNotification(String pkg, int id, String tag, int uid, int initialPid, int score,
+            Notification notification, UserHandle user) {
         if (pkg == null) throw new NullPointerException();
         if (notification == null) throw new NullPointerException();
 
@@ -61,13 +67,11 @@
         this.initialPid = initialPid;
         this.score = score;
         this.notification = notification;
+        this.user = user;
+        this.notification.setUser(user);
     }
 
     public StatusBarNotification(Parcel in) {
-        readFromParcel(in);
-    }
-
-    public void readFromParcel(Parcel in) {
         this.pkg = in.readString();
         this.id = in.readInt();
         if (in.readInt() != 0) {
@@ -79,6 +83,8 @@
         this.initialPid = in.readInt();
         this.score = in.readInt();
         this.notification = new Notification(in);
+        this.user = UserHandle.readFromParcel(in);
+        this.notification.setUser(user);
     }
 
     public void writeToParcel(Parcel out, int flags) {
@@ -94,6 +100,7 @@
         out.writeInt(this.initialPid);
         out.writeInt(this.score);
         this.notification.writeToParcel(out, flags);
+        user.writeToParcel(out, flags);
     }
 
     public int describeContents() {
@@ -114,14 +121,16 @@
         }
     };
 
+    @Override
     public StatusBarNotification clone() {
-        return new StatusBarNotification(this.pkg, this.id, this.tag,
-                this.uid, this.initialPid, this.score, this.notification.clone());
+        return new StatusBarNotification(this.pkg, this.id, this.tag, this.uid, this.initialPid,
+                this.score, this.notification.clone(), this.user);
     }
 
+    @Override
     public String toString() {
-        return "StatusBarNotification(pkg=" + pkg + " id=" + id + " tag=" + tag
-                + " score=" + score + " notn=" + notification + ")";
+        return "StatusBarNotification(pkg=" + pkg + " id=" + id + " tag=" + tag + " score=" + score
+                + " notn=" + notification + " user=" + user + ")";
     }
 
     public boolean isOngoing() {
@@ -132,6 +141,9 @@
         return ((notification.flags & Notification.FLAG_ONGOING_EVENT) == 0)
                 && ((notification.flags & Notification.FLAG_NO_CLEAR) == 0);
     }
+
+    /** Returns a userHandle for the instance of the app that posted this notification. */
+    public int getUserId() {
+        return this.user.getIdentifier();
+    }
 }
-
-
diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java
new file mode 100644
index 0000000..7b8c582
--- /dev/null
+++ b/core/java/com/android/internal/util/DumpUtils.java
@@ -0,0 +1,57 @@
+/*
+ * 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.internal.util;
+
+import android.os.Handler;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * Helper functions for dumping the state of system services.
+ */
+public final class DumpUtils {
+    private DumpUtils() {
+    }
+
+    /**
+     * Helper for dumping state owned by a handler thread.
+     *
+     * Because the caller might be holding an important lock that the handler is
+     * trying to acquire, we use a short timeout to avoid deadlocks.  The process
+     * is inelegant but this function is only used for debugging purposes.
+     */
+    public static void dumpAsync(Handler handler, final Dump dump, PrintWriter pw, long timeout) {
+        final StringWriter sw = new StringWriter();
+        if (handler.runWithScissors(new Runnable() {
+            @Override
+            public void run() {
+                PrintWriter lpw = new PrintWriter(sw);
+                dump.dump(lpw);
+                lpw.close();
+            }
+        }, timeout)) {
+            pw.print(sw.toString());
+        } else {
+            pw.println("... timed out");
+        }
+    }
+
+    public interface Dump {
+        void dump(PrintWriter pw);
+    }
+}
diff --git a/core/java/com/android/internal/util/IndentingPrintWriter.java b/core/java/com/android/internal/util/IndentingPrintWriter.java
index 699e9b30..dd5918b 100644
--- a/core/java/com/android/internal/util/IndentingPrintWriter.java
+++ b/core/java/com/android/internal/util/IndentingPrintWriter.java
@@ -28,7 +28,7 @@
     private final String mIndent;
 
     private StringBuilder mBuilder = new StringBuilder();
-    private String mCurrent = new String();
+    private char[] mCurrent;
     private boolean mEmptyLine = true;
 
     public IndentingPrintWriter(Writer writer, String indent) {
@@ -38,12 +38,12 @@
 
     public void increaseIndent() {
         mBuilder.append(mIndent);
-        mCurrent = mBuilder.toString();
+        mCurrent = null;
     }
 
     public void decreaseIndent() {
         mBuilder.delete(0, mIndent.length());
-        mCurrent = mBuilder.toString();
+        mCurrent = null;
     }
 
     public void printPair(String key, Object value) {
@@ -51,17 +51,35 @@
     }
 
     @Override
-    public void println() {
-        super.println();
-        mEmptyLine = true;
+    public void write(char[] buf, int offset, int count) {
+        final int bufferEnd = offset + count;
+        int lineStart = offset;
+        int lineEnd = offset;
+        while (lineEnd < bufferEnd) {
+            char ch = buf[lineEnd++];
+            if (ch == '\n') {
+                writeIndent();
+                super.write(buf, lineStart, lineEnd - lineStart);
+                lineStart = lineEnd;
+                mEmptyLine = true;
+            }
+        }
+
+        if (lineStart != lineEnd) {
+            writeIndent();
+            super.write(buf, lineStart, lineEnd - lineStart);
+        }
     }
 
-    @Override
-    public void write(char[] buf, int offset, int count) {
+    private void writeIndent() {
         if (mEmptyLine) {
             mEmptyLine = false;
-            super.print(mCurrent);
+            if (mBuilder.length() != 0) {
+                if (mCurrent == null) {
+                    mCurrent = mBuilder.toString().toCharArray();
+                }
+                super.write(mCurrent, 0, mCurrent.length);
+            }
         }
-        super.write(buf, offset, count);
     }
 }
diff --git a/core/java/com/android/internal/util/JournaledFile.java b/core/java/com/android/internal/util/JournaledFile.java
index af0c6c6..eeffc16 100644
--- a/core/java/com/android/internal/util/JournaledFile.java
+++ b/core/java/com/android/internal/util/JournaledFile.java
@@ -19,6 +19,15 @@
 import java.io.File;
 import java.io.IOException;
 
+/**
+ * @Deprecated Use {@link com.android.internal.os.AtomicFile} instead.  It would
+ * be nice to update all existing uses of this to switch to AtomicFile, but since
+ * their on-file semantics are slightly different that would run the risk of losing
+ * data if at the point of the platform upgrade to the new code it would need to
+ * roll back to the backup file.  This can be solved...  but is it worth it and
+ * all of the testing needed to make sure it is correct?
+ */
+@Deprecated
 public class JournaledFile {
     File mReal;
     File mTemp;
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
index a53a9c0..a327adc 100644
--- a/core/java/com/android/internal/util/Preconditions.java
+++ b/core/java/com/android/internal/util/Preconditions.java
@@ -54,4 +54,16 @@
         return reference;
     }
 
+    /**
+     * Ensures the truth of an expression involving the state of the calling
+     * instance, but not involving any parameters to the calling method.
+     *
+     * @param expression a boolean expression
+     * @throws IllegalStateException if {@code expression} is false
+     */
+    public static void checkState(boolean expression) {
+        if (!expression) {
+            throw new IllegalStateException();
+        }
+    }
 }
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 4c34d73..b76e89d 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -28,12 +28,13 @@
 public class BaseIWindow extends IWindow.Stub {
     private IWindowSession mSession;
     public int mSeq;
-    
+
     public void setSession(IWindowSession session) {
         mSession = session;
     }
-    
-    public void resized(int w, int h, Rect contentInsets,
+
+    @Override
+    public void resized(Rect frame, Rect contentInsets,
             Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
         if (reportDraw) {
             try {
@@ -43,24 +44,35 @@
         }
     }
 
+    @Override
+    public void moved(int newX, int newY) {
+    }
+
+    @Override
     public void dispatchAppVisibility(boolean visible) {
     }
 
+    @Override
     public void dispatchGetNewSurface() {
     }
 
+    @Override
     public void dispatchScreenState(boolean on) {
     }
 
+    @Override
     public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
     }
 
+    @Override
     public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
     }
-    
+
+    @Override
     public void closeSystemDialogs(String reason) {
     }
-    
+
+    @Override
     public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, boolean sync) {
         if (sync) {
             try {
@@ -70,14 +82,17 @@
         }
     }
 
+    @Override
     public void dispatchDragEvent(DragEvent event) {
     }
 
+    @Override
     public void dispatchSystemUiVisibilityChanged(int seq, int globalUi,
             int localValue, int localChanges) {
         mSeq = seq;
     }
 
+    @Override
     public void dispatchWallpaperCommand(String action, int x, int y,
             int z, Bundle extras, boolean sync) {
         if (sync) {
@@ -88,6 +103,7 @@
         }
     }
 
+    @Override
     public void doneAnimating() {
     }
 }
diff --git a/core/java/com/android/internal/view/IInputMethodSession.aidl b/core/java/com/android/internal/view/IInputMethodSession.aidl
index f875cbd..cdec254 100644
--- a/core/java/com/android/internal/view/IInputMethodSession.aidl
+++ b/core/java/com/android/internal/view/IInputMethodSession.aidl
@@ -47,6 +47,8 @@
 
     void dispatchTrackballEvent(int seq, in MotionEvent event, IInputMethodCallback callback);
 
+    void dispatchGenericMotionEvent(int seq, in MotionEvent event, IInputMethodCallback callback);
+
     void appPrivateCommand(String action, in Bundle data);
 
     void toggleSoftInput(int showFlags, int hideFlags);
diff --git a/core/java/com/android/internal/view/RotationPolicy.java b/core/java/com/android/internal/view/RotationPolicy.java
index af512a3..95130c8 100644
--- a/core/java/com/android/internal/view/RotationPolicy.java
+++ b/core/java/com/android/internal/view/RotationPolicy.java
@@ -23,10 +23,12 @@
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
 import android.view.IWindowManager;
 import android.view.Surface;
+import android.view.WindowManagerGlobal;
 
 /**
  * Provides helper functions for configuring the display rotation policy.
@@ -54,16 +56,17 @@
      */
     public static boolean isRotationLockToggleVisible(Context context) {
         return isRotationLockToggleSupported(context) &&
-                Settings.System.getInt(context.getContentResolver(),
-                        Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0) == 0;
+                Settings.System.getIntForUser(context.getContentResolver(),
+                        Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0,
+                        UserHandle.USER_CURRENT) == 0;
     }
 
     /**
      * Returns true if rotation lock is enabled.
      */
     public static boolean isRotationLocked(Context context) {
-        return Settings.System.getInt(context.getContentResolver(),
-                Settings.System.ACCELEROMETER_ROTATION, 0) == 0;
+        return Settings.System.getIntForUser(context.getContentResolver(),
+                Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) == 0;
     }
 
     /**
@@ -72,15 +75,15 @@
      * Should be used by the rotation lock toggle.
      */
     public static void setRotationLock(Context context, final boolean enabled) {
-        Settings.System.putInt(context.getContentResolver(),
-                Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0);
+        Settings.System.putIntForUser(context.getContentResolver(),
+                Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0,
+                UserHandle.USER_CURRENT);
 
         AsyncTask.execute(new Runnable() {
             @Override
             public void run() {
                 try {
-                    IWindowManager wm = IWindowManager.Stub.asInterface(
-                            ServiceManager.getService(Context.WINDOW_SERVICE));
+                    IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
                     if (enabled) {
                         wm.freezeRotation(-1);
                     } else {
@@ -100,15 +103,15 @@
      * Should be used by Display settings and Accessibility settings.
      */
     public static void setRotationLockForAccessibility(Context context, final boolean enabled) {
-        Settings.System.putInt(context.getContentResolver(),
-                Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, enabled ? 1 : 0);
+        Settings.System.putIntForUser(context.getContentResolver(),
+                Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, enabled ? 1 : 0,
+                        UserHandle.USER_CURRENT);
 
         AsyncTask.execute(new Runnable() {
             @Override
             public void run() {
                 try {
-                    IWindowManager wm = IWindowManager.Stub.asInterface(
-                            ServiceManager.getService(Context.WINDOW_SERVICE));
+                    IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
                     if (enabled) {
                         wm.freezeRotation(Surface.ROTATION_0);
                     } else {
@@ -122,16 +125,25 @@
     }
 
     /**
-     * Registers a listener for rotation policy changes.
+     * Registers a listener for rotation policy changes affecting the caller's user
      */
     public static void registerRotationPolicyListener(Context context,
             RotationPolicyListener listener) {
+        registerRotationPolicyListener(context, listener, UserHandle.getCallingUserId());
+    }
+
+    /**
+     * Registers a listener for rotation policy changes affecting a specific user,
+     * or USER_ALL for all users.
+     */
+    public static void registerRotationPolicyListener(Context context,
+            RotationPolicyListener listener, int userHandle) {
         context.getContentResolver().registerContentObserver(Settings.System.getUriFor(
                 Settings.System.ACCELEROMETER_ROTATION),
-                false, listener.mObserver);
+                false, listener.mObserver, userHandle);
         context.getContentResolver().registerContentObserver(Settings.System.getUriFor(
                 Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY),
-                false, listener.mObserver);
+                false, listener.mObserver, userHandle);
     }
 
     /**
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index 449194b..238a9c0 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -17,6 +17,7 @@
 package com.android.internal.view.menu;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
@@ -48,6 +49,9 @@
     private int mMinWidth;
     private int mSavedPaddingLeft;
 
+    private static final int MAX_ICON_SIZE = 32; // dp
+    private int mMaxIconSize;
+
     public ActionMenuItemView(Context context) {
         this(context, null);
     }
@@ -67,6 +71,9 @@
                 com.android.internal.R.styleable.ActionMenuItemView_minWidth, 0);
         a.recycle();
 
+        final float density = res.getDisplayMetrics().density;
+        mMaxIconSize = (int) (MAX_ICON_SIZE * density + 0.5f);
+
         setOnClickListener(this);
         setOnLongClickListener(this);
 
@@ -74,6 +81,15 @@
     }
 
     @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+
+        mAllowTextWithIcon = getContext().getResources().getBoolean(
+                com.android.internal.R.bool.config_allowActionMenuItemTextWithIcon);
+        updateTextButtonVisibility();
+    }
+
+    @Override
     public void setPadding(int l, int t, int r, int b) {
         mSavedPaddingLeft = l;
         super.setPadding(l, t, r, b);
@@ -135,7 +151,22 @@
 
     public void setIcon(Drawable icon) {
         mIcon = icon;
-        setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
+        if (icon != null) {
+            int width = icon.getIntrinsicWidth();
+            int height = icon.getIntrinsicHeight();
+            if (width > mMaxIconSize) {
+                final float scale = (float) mMaxIconSize / width;
+                width = mMaxIconSize;
+                height *= scale;
+            }
+            if (height > mMaxIconSize) {
+                final float scale = (float) mMaxIconSize / height;
+                height = mMaxIconSize;
+                width *= scale;
+            }
+            icon.setBounds(0, 0, width, height);
+        }
+        setCompoundDrawables(icon, null, null, null);
 
         updateTextButtonVisibility();
     }
@@ -209,7 +240,7 @@
         Toast cheatSheet = Toast.makeText(context, mItemData.getTitle(), Toast.LENGTH_SHORT);
         if (midy < displayFrame.height()) {
             // Show along the top; follow action buttons
-            cheatSheet.setGravity(Gravity.TOP | Gravity.RIGHT,
+            cheatSheet.setGravity(Gravity.TOP | Gravity.END,
                     screenWidth - screenPos[0] - width / 2, height);
         } else {
             // Show along the bottom center
@@ -221,6 +252,11 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
+            // Fill all available height.
+            heightMeasureSpec = MeasureSpec.makeMeasureSpec(
+                    MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY);
+        }
         final boolean textVisible = hasText();
         if (textVisible && mSavedPaddingLeft >= 0) {
             super.setPadding(mSavedPaddingLeft, getPaddingTop(),
@@ -245,7 +281,7 @@
             // TextView won't center compound drawables in both dimensions without
             // a little coercion. Pad in to center the icon after we've measured.
             final int w = getMeasuredWidth();
-            final int dw = mIcon.getIntrinsicWidth();
+            final int dw = mIcon.getBounds().width();
             super.setPadding((w - dw) / 2, getPaddingTop(), getPaddingRight(), getPaddingBottom());
         }
     }
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index cf6029e..4bb6d0694 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -476,6 +476,9 @@
                 if (isAction) maxActions--;
 
                 item.setIsActionButton(isAction);
+            } else {
+                // Neither requires nor requests an action button.
+                item.setIsActionButton(false);
             }
         }
         return true;
@@ -576,6 +579,16 @@
         public boolean needsDividerAfter() {
             return false;
         }
+
+        @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
+                // Fill available height
+                heightMeasureSpec = MeasureSpec.makeMeasureSpec(
+                        MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY);
+            }
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        }
     }
 
     private class OverflowPopup extends MenuPopupHelper {
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index cef6a8f..34ade74 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -15,6 +15,8 @@
  */
 package com.android.internal.view.menu;
 
+import com.android.internal.R;
+
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
@@ -26,8 +28,6 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.LinearLayout;
 
-import com.android.internal.R;
-
 /**
  * @hide
  */
@@ -73,6 +73,11 @@
         return mFormatItems;
     }
 
+    public void setMaxItemHeight(int maxItemHeight) {
+        mMaxItemHeight = maxItemHeight;
+        requestLayout();
+    }
+
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
@@ -395,6 +400,7 @@
         int nonOverflowCount = 0;
         int widthRemaining = right - left - getPaddingRight() - getPaddingLeft();
         boolean hasOverflow = false;
+        final boolean isLayoutRtl = isLayoutRtl();
         for (int i = 0; i < childCount; i++) {
             final View v = getChildAt(i);
             if (v.getVisibility() == GONE) {
@@ -409,8 +415,15 @@
                 }
 
                 int height = v.getMeasuredHeight();
-                int r = getWidth() - getPaddingRight() - p.rightMargin;
-                int l = r - overflowWidth;
+                int r;
+                int l;
+                if (isLayoutRtl) {
+                    l = getPaddingLeft() + p.leftMargin;
+                    r = l + overflowWidth;
+                } else {
+                    r = getWidth() - getPaddingRight() - p.rightMargin;
+                    l = r - overflowWidth;
+                }
                 int t = midVertical - (height / 2);
                 int b = t + height;
                 v.layout(l, t, r, b);
@@ -443,20 +456,38 @@
         final int spacerCount = nonOverflowCount - (hasOverflow ? 0 : 1);
         final int spacerSize = Math.max(0, spacerCount > 0 ? widthRemaining / spacerCount : 0);
 
-        int startLeft = getPaddingLeft();
-        for (int i = 0; i < childCount; i++) {
-            final View v = getChildAt(i);
-            final LayoutParams lp = (LayoutParams) v.getLayoutParams();
-            if (v.getVisibility() == GONE || lp.isOverflowButton) {
-                continue;
-            }
+        if (isLayoutRtl) {
+            int startRight = getWidth() - getPaddingRight();
+            for (int i = 0; i < childCount; i++) {
+                final View v = getChildAt(i);
+                final LayoutParams lp = (LayoutParams) v.getLayoutParams();
+                if (v.getVisibility() == GONE || lp.isOverflowButton) {
+                    continue;
+                }
 
-            startLeft += lp.leftMargin;
-            int width = v.getMeasuredWidth();
-            int height = v.getMeasuredHeight();
-            int t = midVertical - height / 2;
-            v.layout(startLeft, t, startLeft + width, t + height);
-            startLeft += width + lp.rightMargin + spacerSize;
+                startRight -= lp.rightMargin;
+                int width = v.getMeasuredWidth();
+                int height = v.getMeasuredHeight();
+                int t = midVertical - height / 2;
+                v.layout(startRight - width, t, startRight, t + height);
+                startRight -= width + lp.leftMargin + spacerSize;
+            }
+        } else {
+            int startLeft = getPaddingLeft();
+            for (int i = 0; i < childCount; i++) {
+                final View v = getChildAt(i);
+                final LayoutParams lp = (LayoutParams) v.getLayoutParams();
+                if (v.getVisibility() == GONE || lp.isOverflowButton) {
+                    continue;
+                }
+
+                startLeft += lp.leftMargin;
+                int width = v.getMeasuredWidth();
+                int height = v.getMeasuredHeight();
+                int t = midVertical - height / 2;
+                v.layout(startLeft, t, startLeft + width, t + height);
+                startLeft += width + lp.rightMargin + spacerSize;
+            }
         }
     }
 
@@ -489,8 +520,10 @@
 
     @Override
     protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
-        if (p instanceof LayoutParams) {
-            LayoutParams result = new LayoutParams((LayoutParams) p);
+        if (p != null) {
+            final LayoutParams result = p instanceof LayoutParams
+                    ? new LayoutParams((LayoutParams) p)
+                    : new LayoutParams(p);
             if (result.gravity <= Gravity.NO_GRAVITY) {
                 result.gravity = Gravity.CENTER_VERTICAL;
             }
@@ -566,6 +599,10 @@
             super(c, attrs);
         }
 
+        public LayoutParams(ViewGroup.LayoutParams other) {
+            super(other);
+        }
+
         public LayoutParams(LayoutParams other) {
             super((LinearLayout.LayoutParams) other);
             isOverflowButton = other.isOverflowButton;
diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java
index a743cfa..5d0b25f 100644
--- a/core/java/com/android/internal/view/menu/IconMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java
@@ -281,8 +281,8 @@
         Rect tmpRect = mPositionIconOutput;
         getLineBounds(0, tmpRect);
         mPositionIconAvailable.set(0, 0, getWidth(), tmpRect.top);
-        final int layoutDirection = getResolvedLayoutDirection();
-        Gravity.apply(Gravity.CENTER_VERTICAL | Gravity.LEFT, mIcon.getIntrinsicWidth(), mIcon
+        final int layoutDirection = getLayoutDirection();
+        Gravity.apply(Gravity.CENTER_VERTICAL | Gravity.START, mIcon.getIntrinsicWidth(), mIcon
                 .getIntrinsicHeight(), mPositionIconAvailable, mPositionIconOutput,
                 layoutDirection);
         mIcon.setBounds(mPositionIconOutput);
diff --git a/core/java/com/android/internal/widget/AbsActionBarView.java b/core/java/com/android/internal/widget/AbsActionBarView.java
index 25a9c54..ca7f5d0 100644
--- a/core/java/com/android/internal/widget/AbsActionBarView.java
+++ b/core/java/com/android/internal/widget/AbsActionBarView.java
@@ -95,6 +95,9 @@
 
     public void setContentHeight(int height) {
         mContentHeight = height;
+        if (mMenuView != null) {
+            mMenuView.setMaxItemHeight(mContentHeight);
+        }
         requestLayout();
     }
 
@@ -219,24 +222,22 @@
         return Math.max(0, availableWidth);
     }
 
-    protected int positionChild(View child, int x, int y, int contentHeight) {
-        int childWidth = child.getMeasuredWidth();
-        int childHeight = child.getMeasuredHeight();
-        int childTop = y + (contentHeight - childHeight) / 2;
-
-        child.layout(x, childTop, x + childWidth, childTop + childHeight);
-
-        return childWidth;
+    static protected int next(int x, int val, boolean isRtl) {
+        return isRtl ? x - val : x + val;
     }
 
-    protected int positionChildInverse(View child, int x, int y, int contentHeight) {
+    protected int positionChild(View child, int x, int y, int contentHeight, boolean reverse) {
         int childWidth = child.getMeasuredWidth();
         int childHeight = child.getMeasuredHeight();
         int childTop = y + (contentHeight - childHeight) / 2;
 
-        child.layout(x - childWidth, childTop, x, childTop + childHeight);
+        if (reverse) {
+            child.layout(x - childWidth, childTop, x, childTop + childHeight);
+        } else {
+            child.layout(x, childTop, x + childWidth, childTop + childHeight);
+        }
 
-        return childWidth;
+        return  (reverse ? -childWidth : childWidth);
     }
 
     protected class VisibilityAnimListener implements Animator.AnimatorListener {
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index 0c572705..0cfe4fd 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -77,20 +77,107 @@
     }
 
     public void setPrimaryBackground(Drawable bg) {
+        if (mBackground != null) {
+            mBackground.setCallback(null);
+            unscheduleDrawable(mBackground);
+        }
         mBackground = bg;
+        if (bg != null) {
+            bg.setCallback(this);
+        }
+        setWillNotDraw(mIsSplit ? mSplitBackground == null :
+                mBackground == null && mStackedBackground == null);
         invalidate();
     }
 
     public void setStackedBackground(Drawable bg) {
+        if (mStackedBackground != null) {
+            mStackedBackground.setCallback(null);
+            unscheduleDrawable(mStackedBackground);
+        }
         mStackedBackground = bg;
+        if (bg != null) {
+            bg.setCallback(this);
+        }
+        setWillNotDraw(mIsSplit ? mSplitBackground == null :
+                mBackground == null && mStackedBackground == null);
         invalidate();
     }
 
     public void setSplitBackground(Drawable bg) {
+        if (mSplitBackground != null) {
+            mSplitBackground.setCallback(null);
+            unscheduleDrawable(mSplitBackground);
+        }
         mSplitBackground = bg;
+        if (bg != null) {
+            bg.setCallback(this);
+        }
+        setWillNotDraw(mIsSplit ? mSplitBackground == null :
+                mBackground == null && mStackedBackground == null);
         invalidate();
     }
 
+    @Override
+    public void setVisibility(int visibility) {
+        super.setVisibility(visibility);
+        final boolean isVisible = visibility == VISIBLE;
+        if (mBackground != null) mBackground.setVisible(isVisible, false);
+        if (mStackedBackground != null) mStackedBackground.setVisible(isVisible, false);
+        if (mSplitBackground != null) mSplitBackground.setVisible(isVisible, false);
+    }
+
+    @Override
+    protected boolean verifyDrawable(Drawable who) {
+        return (who == mBackground && !mIsSplit) || (who == mStackedBackground && mIsStacked) ||
+                (who == mSplitBackground && mIsSplit) || super.verifyDrawable(who);
+    }
+
+    @Override
+    protected void drawableStateChanged() {
+        super.drawableStateChanged();
+        if (mBackground != null && mBackground.isStateful()) {
+            mBackground.setState(getDrawableState());
+        }
+        if (mStackedBackground != null && mStackedBackground.isStateful()) {
+            mStackedBackground.setState(getDrawableState());
+        }
+        if (mSplitBackground != null && mSplitBackground.isStateful()) {
+            mSplitBackground.setState(getDrawableState());
+        }
+    }
+
+    @Override
+    public void jumpDrawablesToCurrentState() {
+        super.jumpDrawablesToCurrentState();
+        if (mBackground != null) {
+            mBackground.jumpToCurrentState();
+        }
+        if (mStackedBackground != null) {
+            mStackedBackground.jumpToCurrentState();
+        }
+        if (mSplitBackground != null) {
+            mSplitBackground.jumpToCurrentState();
+        }
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void onResolveDrawables(int layoutDirection) {
+        super.onResolveDrawables(layoutDirection);
+        if (mBackground != null) {
+            mBackground.setLayoutDirection(layoutDirection);
+        }
+        if (mStackedBackground != null) {
+            mStackedBackground.setLayoutDirection(layoutDirection);
+        }
+        if (mSplitBackground != null) {
+            mSplitBackground.setLayoutDirection(layoutDirection);
+        }
+    }
+
     /**
      * Set the action bar into a "transitioning" state. While transitioning
      * the bar will block focus and touch from all of its descendants. This
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 16f08f5..8bc1081a 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -454,15 +454,18 @@
 
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        int x = getPaddingLeft();
+        final boolean isLayoutRtl = isLayoutRtl();
+        int x = isLayoutRtl ? r - l - getPaddingRight() : getPaddingLeft();
         final int y = getPaddingTop();
         final int contentHeight = b - t - getPaddingTop() - getPaddingBottom();
         
         if (mClose != null && mClose.getVisibility() != GONE) {
             MarginLayoutParams lp = (MarginLayoutParams) mClose.getLayoutParams();
-            x += lp.leftMargin;
-            x += positionChild(mClose, x, y, contentHeight);
-            x += lp.rightMargin;
+            final int startMargin = (isLayoutRtl ? lp.rightMargin : lp.leftMargin);
+            final int endMargin = (isLayoutRtl ? lp.leftMargin : lp.rightMargin);
+            x = next(x, startMargin, isLayoutRtl);
+            x += positionChild(mClose, x, y, contentHeight, isLayoutRtl);
+            x = next(x, endMargin, isLayoutRtl);
 
             if (mAnimateInOnLayout) {
                 mAnimationMode = ANIMATE_IN;
@@ -473,17 +476,17 @@
         }
 
         if (mTitleLayout != null && mCustomView == null && mTitleLayout.getVisibility() != GONE) {
-            x += positionChild(mTitleLayout, x, y, contentHeight);
+            x += positionChild(mTitleLayout, x, y, contentHeight, isLayoutRtl);
         }
         
         if (mCustomView != null) {
-            x += positionChild(mCustomView, x, y, contentHeight);
+            x += positionChild(mCustomView, x, y, contentHeight, isLayoutRtl);
         }
-        
-        x = r - l - getPaddingRight();
+
+        x = isLayoutRtl ? getPaddingLeft() : r - l - getPaddingRight();
 
         if (mMenuView != null) {
-            x -= positionChildInverse(mMenuView, x, y, contentHeight);
+            x += positionChild(mMenuView, x, y, contentHeight, !isLayoutRtl);
         }
     }
 
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 450f418..6fb459c 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -26,6 +26,7 @@
 import com.android.internal.view.menu.MenuView;
 import com.android.internal.view.menu.SubMenuBuilder;
 
+import android.animation.LayoutTransition;
 import android.app.ActionBar;
 import android.app.ActionBar.OnNavigationListener;
 import android.app.Activity;
@@ -84,7 +85,7 @@
             ActionBar.DISPLAY_SHOW_CUSTOM |
             ActionBar.DISPLAY_SHOW_TITLE;
 
-    private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.LEFT | Gravity.CENTER_VERTICAL;
+    private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.START | Gravity.CENTER_VERTICAL;
     
     private int mNavigationMode;
     private int mDisplayOptions = -1;
@@ -555,12 +556,16 @@
         // Make sure the home button has an accurate content description for accessibility.
         if (!enable) {
             mHomeLayout.setContentDescription(null);
-        } else if ((mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
-            mHomeLayout.setContentDescription(mContext.getResources().getText(
-                    R.string.action_bar_up_description));
+            mHomeLayout.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
         } else {
-            mHomeLayout.setContentDescription(mContext.getResources().getText(
-                    R.string.action_bar_home_description));
+            mHomeLayout.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+            if ((mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
+                mHomeLayout.setContentDescription(mContext.getResources().getText(
+                        R.string.action_bar_up_description));
+            } else {
+                mHomeLayout.setContentDescription(mContext.getResources().getText(
+                        R.string.action_bar_home_description));
+            }
         }
     }
 
@@ -623,12 +628,16 @@
         // Make sure the home button has an accurate content description for accessibility.
         if (!mHomeLayout.isEnabled()) {
             mHomeLayout.setContentDescription(null);
-        } else if ((options & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
-            mHomeLayout.setContentDescription(mContext.getResources().getText(
-                    R.string.action_bar_up_description));
+            mHomeLayout.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
         } else {
-            mHomeLayout.setContentDescription(mContext.getResources().getText(
-                    R.string.action_bar_home_description));
+            mHomeLayout.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+            if ((options & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
+                mHomeLayout.setContentDescription(mContext.getResources().getText(
+                        R.string.action_bar_up_description));
+            } else {
+                mHomeLayout.setContentDescription(mContext.getResources().getText(
+                        R.string.action_bar_home_description));
+            }
         }
     }
 
@@ -847,7 +856,7 @@
 
         int contentWidth = MeasureSpec.getSize(widthMeasureSpec);
 
-        int maxHeight = mContentHeight > 0 ?
+        int maxHeight = mContentHeight >= 0 ?
                 mContentHeight : MeasureSpec.getSize(heightMeasureSpec);
         
         final int verticalPadding = getPaddingTop() + getPaddingBottom();
@@ -855,6 +864,7 @@
         final int paddingRight = getPaddingRight();
         final int height = maxHeight - verticalPadding;
         final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
+        final int exactHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
 
         int availableWidth = contentWidth - paddingLeft - paddingRight;
         int leftOfCenter = availableWidth / 2;
@@ -870,16 +880,14 @@
             } else {
                 homeWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
             }
-            homeLayout.measure(homeWidthSpec,
-                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
-            final int homeWidth = homeLayout.getMeasuredWidth() + homeLayout.getLeftOffset();
+            homeLayout.measure(homeWidthSpec, exactHeightSpec);
+            final int homeWidth = homeLayout.getMeasuredWidth() + homeLayout.getStartOffset();
             availableWidth = Math.max(0, availableWidth - homeWidth);
             leftOfCenter = Math.max(0, availableWidth - homeWidth);
         }
         
         if (mMenuView != null && mMenuView.getParent() == this) {
-            availableWidth = measureChildView(mMenuView, availableWidth,
-                    childSpecHeight, 0);
+            availableWidth = measureChildView(mMenuView, availableWidth, exactHeightSpec, 0);
             rightOfCenter = Math.max(0, rightOfCenter - mMenuView.getMeasuredWidth());
         }
 
@@ -1010,8 +1018,6 @@
 
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        int x = getPaddingLeft();
-        final int y = getPaddingTop();
         final int contentHeight = b - t - getPaddingTop() - getPaddingBottom();
 
         if (contentHeight <= 0) {
@@ -1019,13 +1025,23 @@
             return;
         }
 
+        final boolean isLayoutRtl = isLayoutRtl();
+        final int direction = isLayoutRtl ? +1 : -1;
+        int menuStart = isLayoutRtl ? getPaddingLeft() : r - l - getPaddingRight();
+        // In LTR mode, we start from left padding and go to the right; in RTL mode, we start
+        // from the padding right and go to the left (in reverse way)
+        int x = isLayoutRtl ? r - l - getPaddingRight() : getPaddingLeft();
+        final int y = getPaddingTop();
+
         HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
         boolean needsTouchDelegate = false;
         int homeSlop = mMaxHomeSlop;
         int homeRight = 0;
         if (homeLayout.getVisibility() != GONE) {
-            final int leftOffset = homeLayout.getLeftOffset();
-            x += positionChild(homeLayout, x + leftOffset, y, contentHeight) + leftOffset;
+            final int startOffset = homeLayout.getStartOffset();
+            x += positionChild(homeLayout,
+                            next(x, startOffset, isLayoutRtl), y, contentHeight, isLayoutRtl);
+            x = next(x, startOffset, isLayoutRtl);
             needsTouchDelegate = homeLayout == mHomeLayout;
             homeRight = x;
         }
@@ -1034,7 +1050,7 @@
             final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
                     (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
             if (showTitle) {
-                x += positionChild(mTitleLayout, x, y, contentHeight);
+                x += positionChild(mTitleLayout, x, y, contentHeight, isLayoutRtl);
             }
 
             switch (mNavigationMode) {
@@ -1042,31 +1058,34 @@
                     break;
                 case ActionBar.NAVIGATION_MODE_LIST:
                     if (mListNavLayout != null) {
-                        if (showTitle) x += mItemPadding;
+                        if (showTitle) {
+                            x = next(x, mItemPadding, isLayoutRtl);
+                        }
                         homeSlop = Math.min(homeSlop, Math.max(x - homeRight, 0));
-                        x += positionChild(mListNavLayout, x, y, contentHeight) + mItemPadding;
+                        x += positionChild(mListNavLayout, x, y, contentHeight, isLayoutRtl);
+                        x = next(x, mItemPadding, isLayoutRtl);
                     }
                     break;
                 case ActionBar.NAVIGATION_MODE_TABS:
                     if (mTabScrollView != null) {
-                        if (showTitle) x += mItemPadding;
+                        if (showTitle) x = next(x, mItemPadding, isLayoutRtl);
                         homeSlop = Math.min(homeSlop, Math.max(x - homeRight, 0));
-                        x += positionChild(mTabScrollView, x, y, contentHeight) + mItemPadding;
+                        x += positionChild(mTabScrollView, x, y, contentHeight, isLayoutRtl);
+                        x = next(x, mItemPadding, isLayoutRtl);
                     }
                     break;
             }
         }
 
-        int menuLeft = r - l - getPaddingRight();
         if (mMenuView != null && mMenuView.getParent() == this) {
-            positionChildInverse(mMenuView, menuLeft, y, contentHeight);
-            menuLeft -= mMenuView.getMeasuredWidth();
+            positionChild(mMenuView, menuStart, y, contentHeight, !isLayoutRtl);
+            menuStart += direction * mMenuView.getMeasuredWidth();
         }
 
         if (mIndeterminateProgressView != null &&
                 mIndeterminateProgressView.getVisibility() != GONE) {
-            positionChildInverse(mIndeterminateProgressView, menuLeft, y, contentHeight);
-            menuLeft -= mIndeterminateProgressView.getMeasuredWidth();
+            positionChild(mIndeterminateProgressView, menuStart, y, contentHeight, !isLayoutRtl);
+            menuStart += direction * mIndeterminateProgressView.getMeasuredWidth();
         }
 
         View customView = null;
@@ -1077,51 +1096,63 @@
             customView = mCustomNavView;
         }
         if (customView != null) {
+            final int layoutDirection = getLayoutDirection();
             ViewGroup.LayoutParams lp = customView.getLayoutParams();
             final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
                     (ActionBar.LayoutParams) lp : null;
-
             final int gravity = ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY;
             final int navWidth = customView.getMeasuredWidth();
 
             int topMargin = 0;
             int bottomMargin = 0;
             if (ablp != null) {
-                x += ablp.leftMargin;
-                menuLeft -= ablp.rightMargin;
+                x = next(x, ablp.getMarginStart(), isLayoutRtl);
+                menuStart += direction * ablp.getMarginEnd();
                 topMargin = ablp.topMargin;
                 bottomMargin = ablp.bottomMargin;
             }
 
-            int hgravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+            int hgravity = gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
             // See if we actually have room to truly center; if not push against left or right.
             if (hgravity == Gravity.CENTER_HORIZONTAL) {
                 final int centeredLeft = ((mRight - mLeft) - navWidth) / 2;
-                if (centeredLeft < x) {
-                    hgravity = Gravity.LEFT;
-                } else if (centeredLeft + navWidth > menuLeft) {
-                    hgravity = Gravity.RIGHT;
+                if (isLayoutRtl) {
+                    final int centeredStart = centeredLeft + navWidth;
+                    final int centeredEnd = centeredLeft;
+                    if (centeredStart > x) {
+                        hgravity = Gravity.RIGHT;
+                    } else if (centeredEnd < menuStart) {
+                        hgravity = Gravity.LEFT;
+                    }
+                } else {
+                    final int centeredStart = centeredLeft;
+                    final int centeredEnd = centeredLeft + navWidth;
+                    if (centeredStart < x) {
+                        hgravity = Gravity.LEFT;
+                    } else if (centeredEnd > menuStart) {
+                        hgravity = Gravity.RIGHT;
+                    }
                 }
-            } else if (gravity == -1) {
-                hgravity = Gravity.LEFT;
+            } else if (gravity == Gravity.NO_GRAVITY) {
+                hgravity = Gravity.START;
             }
 
             int xpos = 0;
-            switch (hgravity) {
+            switch (Gravity.getAbsoluteGravity(hgravity, layoutDirection)) {
                 case Gravity.CENTER_HORIZONTAL:
                     xpos = ((mRight - mLeft) - navWidth) / 2;
                     break;
                 case Gravity.LEFT:
-                    xpos = x;
+                    xpos = isLayoutRtl ? menuStart : x;
                     break;
                 case Gravity.RIGHT:
-                    xpos = menuLeft - navWidth;
+                    xpos = isLayoutRtl ? x - navWidth : menuStart - navWidth;
                     break;
             }
 
             int vgravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
 
-            if (gravity == -1) {
+            if (gravity == Gravity.NO_GRAVITY) {
                 vgravity = Gravity.CENTER_VERTICAL;
             }
 
@@ -1144,7 +1175,7 @@
             customView.layout(xpos, ypos, xpos + customWidth,
                     ypos + customView.getMeasuredHeight());
             homeSlop = Math.min(homeSlop, Math.max(xpos - homeRight, 0));
-            x += customWidth;
+            x = next(x, customWidth, isLayoutRtl);
         }
 
         if (mProgressView != null) {
@@ -1247,12 +1278,19 @@
         private ImageView mIconView;
         private int mUpWidth;
 
+        private static final long DEFAULT_TRANSITION_DURATION = 150;
+
         public HomeView(Context context) {
             this(context, null);
         }
 
         public HomeView(Context context, AttributeSet attrs) {
             super(context, attrs);
+            LayoutTransition t = getLayoutTransition();
+            if (t != null) {
+                // Set a lower duration than the default
+                t.setDuration(DEFAULT_TRANSITION_DURATION);
+            }
         }
 
         public void setUp(boolean isUp) {
@@ -1290,7 +1328,7 @@
             mIconView = (ImageView) findViewById(com.android.internal.R.id.home);
         }
 
-        public int getLeftOffset() {
+        public int getStartOffset() {
             return mUpView.getVisibility() == GONE ? mUpWidth : 0;
         }
 
@@ -1340,25 +1378,48 @@
         @Override
         protected void onLayout(boolean changed, int l, int t, int r, int b) {
             final int vCenter = (b - t) / 2;
-            int width = r - l;
+            final boolean isLayoutRtl = isLayoutRtl();
+            final int width = getWidth();
             int upOffset = 0;
             if (mUpView.getVisibility() != GONE) {
                 final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
                 final int upHeight = mUpView.getMeasuredHeight();
                 final int upWidth = mUpView.getMeasuredWidth();
-                final int upTop = vCenter - upHeight / 2;
-                mUpView.layout(0, upTop, upWidth, upTop + upHeight);
                 upOffset = upLp.leftMargin + upWidth + upLp.rightMargin;
-                width -= upOffset;
-                l += upOffset;
+                final int upTop = vCenter - upHeight / 2;
+                final int upBottom = upTop + upHeight;
+                final int upRight;
+                final int upLeft;
+                if (isLayoutRtl) {
+                    upRight = width;
+                    upLeft = upRight - upWidth;
+                    r -= upOffset;
+                } else {
+                    upRight = upWidth;
+                    upLeft = 0;
+                    l += upOffset;
+                }
+                mUpView.layout(upLeft, upTop, upRight, upBottom);
             }
+
             final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
             final int iconHeight = mIconView.getMeasuredHeight();
             final int iconWidth = mIconView.getMeasuredWidth();
             final int hCenter = (r - l) / 2;
-            final int iconLeft = upOffset + Math.max(iconLp.leftMargin, hCenter - iconWidth / 2);
             final int iconTop = Math.max(iconLp.topMargin, vCenter - iconHeight / 2);
-            mIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight);
+            final int iconBottom = iconTop + iconHeight;
+            final int iconLeft;
+            final int iconRight;
+            int marginStart = iconLp.getMarginStart();
+            final int delta = Math.max(marginStart, hCenter - iconWidth / 2);
+            if (isLayoutRtl) {
+                iconRight = width - upOffset - delta;
+                iconLeft = iconRight - iconWidth;
+            } else {
+                iconLeft = upOffset + delta;
+                iconRight = iconLeft + iconWidth;
+            }
+            mIconView.layout(iconLeft, iconTop, iconRight, iconBottom);
         }
     }
 
diff --git a/core/java/com/android/internal/widget/FaceUnlockView.java b/core/java/com/android/internal/widget/FaceUnlockView.java
new file mode 100644
index 0000000..e3c1247
--- /dev/null
+++ b/core/java/com/android/internal/widget/FaceUnlockView.java
@@ -0,0 +1,69 @@
+/*
+ * 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.internal.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.RelativeLayout;
+
+public class FaceUnlockView extends RelativeLayout {
+    private static final String TAG = "FaceUnlockView";
+
+    public FaceUnlockView(Context context) {
+        this(context, null);
+    }
+
+    public FaceUnlockView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    private int resolveMeasured(int measureSpec, int desired)
+    {
+        int result = 0;
+        int specSize = MeasureSpec.getSize(measureSpec);
+        switch (MeasureSpec.getMode(measureSpec)) {
+            case MeasureSpec.UNSPECIFIED:
+                result = desired;
+                break;
+            case MeasureSpec.AT_MOST:
+                result = Math.max(specSize, desired);
+                break;
+            case MeasureSpec.EXACTLY:
+            default:
+                result = specSize;
+        }
+        return result;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        final int minimumWidth = getSuggestedMinimumWidth();
+        final int minimumHeight = getSuggestedMinimumHeight();
+        int viewWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
+        int viewHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
+
+        final int chosenSize = Math.min(viewWidth, viewHeight);
+        final int newWidthMeasureSpec =
+                MeasureSpec.makeMeasureSpec(chosenSize, MeasureSpec.AT_MOST);
+        final int newHeightMeasureSpec =
+                MeasureSpec.makeMeasureSpec(chosenSize, MeasureSpec.AT_MOST);
+
+        super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec);
+    }
+}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index f77e8f3..75fef24 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -16,44 +16,38 @@
 
 package com.android.internal.widget;
 
-import com.android.internal.R;
-import com.android.internal.telephony.ITelephony;
-import com.google.android.collect.Lists;
-
+import android.app.ActivityManagerNative;
 import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
+import android.appwidget.AppWidgetManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.os.Binder;
-import android.os.FileObserver;
+import android.os.Bundle;
 import android.os.IBinder;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.os.storage.IMountService;
 import android.provider.Settings;
 import android.security.KeyStore;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
+import android.view.IWindowManager;
 import android.view.View;
 import android.widget.Button;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.RandomAccessFile;
+import com.android.internal.R;
+import com.android.internal.telephony.ITelephony;
+import com.google.android.collect.Lists;
+
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
-import java.util.Arrays;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Utilities for the lock pattern and its settings.
@@ -107,11 +101,41 @@
     public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE;
 
     /**
+     * Tells the keyguard to show the user switcher when the keyguard is created.
+     */
+    public static final String KEYGUARD_SHOW_USER_SWITCHER = "showuserswitcher";
+
+    /**
+     * Tells the keyguard to show the security challenge when the keyguard is created.
+     */
+    public static final String KEYGUARD_SHOW_SECURITY_CHALLENGE = "showsecuritychallenge";
+
+    /**
+     * Tells the keyguard to show the widget with the specified id when the keyguard is created.
+     */
+    public static final String KEYGUARD_SHOW_APPWIDGET = "showappwidget";
+
+    /**
+     * Options used to lock the device upon user switch.
+     */
+    public static final Bundle USER_SWITCH_LOCK_OPTIONS = new Bundle();
+
+    static {
+        USER_SWITCH_LOCK_OPTIONS.putBoolean(KEYGUARD_SHOW_USER_SWITCHER, true);
+        USER_SWITCH_LOCK_OPTIONS.putBoolean(KEYGUARD_SHOW_SECURITY_CHALLENGE, true);
+    }
+
+    /**
      * The bit in LOCK_BIOMETRIC_WEAK_FLAGS to be used to indicate whether liveliness should
      * be used
      */
     public static final int FLAG_BIOMETRIC_WEAK_LIVELINESS = 0x1;
 
+    /**
+     * Pseudo-appwidget id we use to represent the default clock status widget
+     */
+    public static final int ID_DEFAULT_STATUS_WIDGET = -2;
+
     protected final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
     protected final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
     protected final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
@@ -133,7 +157,9 @@
     private final ContentResolver mContentResolver;
     private DevicePolicyManager mDevicePolicyManager;
     private ILockSettings mLockSettingsService;
-    private int mCurrentUserId = 0;
+
+    // The current user is set by KeyguardViewMediator and shared by all LockPatternUtils.
+    private static volatile int sCurrentUserId = UserHandle.USER_NULL;
 
     public DevicePolicyManager getDevicePolicyManager() {
         if (mDevicePolicyManager == null) {
@@ -164,7 +190,7 @@
     }
 
     public int getRequestedMinimumPasswordLength() {
-        return getDevicePolicyManager().getPasswordMinimumLength(null);
+        return getDevicePolicyManager().getPasswordMinimumLength(null, getCurrentOrCallingUserId());
     }
 
     /**
@@ -172,81 +198,88 @@
      * MODE_PATTERN which allows the user to choose anything.
      */
     public int getRequestedPasswordQuality() {
-        return getDevicePolicyManager().getPasswordQuality(null);
+        return getDevicePolicyManager().getPasswordQuality(null, getCurrentOrCallingUserId());
     }
 
     public int getRequestedPasswordHistoryLength() {
-        return getDevicePolicyManager().getPasswordHistoryLength(null);
+        return getDevicePolicyManager().getPasswordHistoryLength(null, getCurrentOrCallingUserId());
     }
 
     public int getRequestedPasswordMinimumLetters() {
-        return getDevicePolicyManager().getPasswordMinimumLetters(null);
+        return getDevicePolicyManager().getPasswordMinimumLetters(null,
+                getCurrentOrCallingUserId());
     }
 
     public int getRequestedPasswordMinimumUpperCase() {
-        return getDevicePolicyManager().getPasswordMinimumUpperCase(null);
+        return getDevicePolicyManager().getPasswordMinimumUpperCase(null,
+                getCurrentOrCallingUserId());
     }
 
     public int getRequestedPasswordMinimumLowerCase() {
-        return getDevicePolicyManager().getPasswordMinimumLowerCase(null);
+        return getDevicePolicyManager().getPasswordMinimumLowerCase(null,
+                getCurrentOrCallingUserId());
     }
 
     public int getRequestedPasswordMinimumNumeric() {
-        return getDevicePolicyManager().getPasswordMinimumNumeric(null);
+        return getDevicePolicyManager().getPasswordMinimumNumeric(null,
+                getCurrentOrCallingUserId());
     }
 
     public int getRequestedPasswordMinimumSymbols() {
-        return getDevicePolicyManager().getPasswordMinimumSymbols(null);
+        return getDevicePolicyManager().getPasswordMinimumSymbols(null,
+                getCurrentOrCallingUserId());
     }
 
     public int getRequestedPasswordMinimumNonLetter() {
-        return getDevicePolicyManager().getPasswordMinimumNonLetter(null);
+        return getDevicePolicyManager().getPasswordMinimumNonLetter(null,
+                getCurrentOrCallingUserId());
     }
+
     /**
      * Returns the actual password mode, as set by keyguard after updating the password.
      *
      * @return
      */
     public void reportFailedPasswordAttempt() {
-        getDevicePolicyManager().reportFailedPasswordAttempt();
+        getDevicePolicyManager().reportFailedPasswordAttempt(getCurrentOrCallingUserId());
     }
 
     public void reportSuccessfulPasswordAttempt() {
-        getDevicePolicyManager().reportSuccessfulPasswordAttempt();
+        getDevicePolicyManager().reportSuccessfulPasswordAttempt(getCurrentOrCallingUserId());
     }
 
     public void setCurrentUser(int userId) {
-        if (Process.myUid() == Process.SYSTEM_UID) {
-            mCurrentUserId = userId;
-        } else {
-            throw new SecurityException("Only the system process can set the current user");
-        }
+        sCurrentUserId = userId;
     }
 
     public int getCurrentUser() {
-        if (Process.myUid() == Process.SYSTEM_UID) {
-            return mCurrentUserId;
-        } else {
-            throw new SecurityException("Only the system process can get the current user");
+        if (sCurrentUserId != UserHandle.USER_NULL) {
+            // Someone is regularly updating using setCurrentUser() use that value.
+            return sCurrentUserId;
+        }
+        try {
+            return ActivityManagerNative.getDefault().getCurrentUser().id;
+        } catch (RemoteException re) {
+            return UserHandle.USER_OWNER;
         }
     }
 
     public void removeUser(int userId) {
-        if (Process.myUid() == Process.SYSTEM_UID) {
-            try {
-                getLockSettings().removeUser(userId);
-            } catch (RemoteException re) {
-                Log.e(TAG, "Couldn't remove lock settings for user " + userId);
-            }
+        try {
+            getLockSettings().removeUser(userId);
+        } catch (RemoteException re) {
+            Log.e(TAG, "Couldn't remove lock settings for user " + userId);
         }
     }
 
     private int getCurrentOrCallingUserId() {
         int callingUid = Binder.getCallingUid();
         if (callingUid == android.os.Process.SYSTEM_UID) {
-            return mCurrentUserId;
+            // TODO: This is a little inefficient. See if all users of this are able to
+            // handle USER_CURRENT and pass that instead.
+            return getCurrentUser();
         } else {
-            return UserId.getUserId(callingUid);
+            return UserHandle.getUserId(callingUid);
         }
     }
 
@@ -257,9 +290,13 @@
      * @return Whether the pattern matches the stored one.
      */
     public boolean checkPattern(List<LockPatternView.Cell> pattern) {
-        int userId = getCurrentOrCallingUserId();
+        final int userId = getCurrentOrCallingUserId();
         try {
-            return getLockSettings().checkPattern(patternToHash(pattern), userId);
+            final boolean matched = getLockSettings().checkPattern(patternToHash(pattern), userId);
+            if (matched && (userId == UserHandle.USER_OWNER)) {
+                KeyStore.getInstance().password(patternToString(pattern));
+            }
+            return matched;
         } catch (RemoteException re) {
             return true;
         }
@@ -272,9 +309,14 @@
      * @return Whether the password matches the stored one.
      */
     public boolean checkPassword(String password) {
-        int userId = getCurrentOrCallingUserId();
+        final int userId = getCurrentOrCallingUserId();
         try {
-            return getLockSettings().checkPassword(passwordToHash(password), userId);
+            final boolean matched = getLockSettings().checkPassword(passwordToHash(password),
+                    userId);
+            if (matched && (userId == UserHandle.USER_OWNER)) {
+                KeyStore.getInstance().password(password);
+            }
+            return matched;
         } catch (RemoteException re) {
             return true;
         }
@@ -476,21 +518,21 @@
                     deleteGallery();
                     setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
                     dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
-                            pattern.size(), 0, 0, 0, 0, 0, 0);
+                            pattern.size(), 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId());
                 } else {
                     setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK);
                     setLong(PASSWORD_TYPE_ALTERNATE_KEY,
                             DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
                     finishBiometricWeak();
                     dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
-                            0, 0, 0, 0, 0, 0, 0);
+                            0, 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId());
                 }
             } else {
                 if (keyStore.isEmpty()) {
                     keyStore.reset();
                 }
                 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0,
-                        0, 0, 0, 0, 0);
+                        0, 0, 0, 0, 0, getCurrentOrCallingUserId());
             }
         } catch (RemoteException re) {
             Log.e(TAG, "Couldn't save lock pattern " + re);
@@ -527,7 +569,8 @@
     /** Update the encryption password if it is enabled **/
     private void updateEncryptionPassword(String password) {
         DevicePolicyManager dpm = getDevicePolicyManager();
-        if (dpm.getStorageEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE) {
+        if (dpm.getStorageEncryptionStatus(getCurrentOrCallingUserId())
+                != DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE) {
             return;
         }
 
@@ -553,7 +596,7 @@
      * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
      */
     public void saveLockPassword(String password, int quality) {
-        this.saveLockPassword(password, quality, false);
+        this.saveLockPassword(password, quality, false, getCurrentOrCallingUserId());
     }
 
     /**
@@ -565,23 +608,38 @@
      * @param isFallback Specifies if this is a fallback to biometric weak
      */
     public void saveLockPassword(String password, int quality, boolean isFallback) {
+        saveLockPassword(password, quality, isFallback, getCurrentOrCallingUserId());
+    }
+
+    /**
+     * Save a lock password.  Does not ensure that the password is as good
+     * as the requested mode, but will adjust the mode to be as good as the
+     * pattern.
+     * @param password The password to save
+     * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
+     * @param isFallback Specifies if this is a fallback to biometric weak
+     * @param userHandle The userId of the user to change the password for
+     */
+    public void saveLockPassword(String password, int quality, boolean isFallback, int userHandle) {
         // Compute the hash
         final byte[] hash = passwordToHash(password);
         try {
-            getLockSettings().setLockPassword(hash, getCurrentOrCallingUserId());
+            getLockSettings().setLockPassword(hash, userHandle);
             DevicePolicyManager dpm = getDevicePolicyManager();
             KeyStore keyStore = KeyStore.getInstance();
             if (password != null) {
-                // Update the encryption password.
-                updateEncryptionPassword(password);
+                if (userHandle == UserHandle.USER_OWNER) {
+                    // Update the encryption password.
+                    updateEncryptionPassword(password);
 
-                // Update the keystore password
-                keyStore.password(password);
+                    // Update the keystore password
+                    keyStore.password(password);
+                }
 
                 int computedQuality = computePasswordQuality(password);
                 if (!isFallback) {
                     deleteGallery();
-                    setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality));
+                    setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle);
                     if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
                         int letters = 0;
                         int uppercase = 0;
@@ -607,25 +665,27 @@
                         }
                         dpm.setActivePasswordState(Math.max(quality, computedQuality),
                                 password.length(), letters, uppercase, lowercase,
-                                numbers, symbols, nonletter);
+                                numbers, symbols, nonletter, userHandle);
                     } else {
                         // The password is not anything.
                         dpm.setActivePasswordState(
                                 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
-                                0, 0, 0, 0, 0, 0, 0);
+                                0, 0, 0, 0, 0, 0, 0, userHandle);
                     }
                 } else {
                     // Case where it's a fallback for biometric weak
-                    setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK);
-                    setLong(PASSWORD_TYPE_ALTERNATE_KEY, Math.max(quality, computedQuality));
+                    setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
+                            userHandle);
+                    setLong(PASSWORD_TYPE_ALTERNATE_KEY, Math.max(quality, computedQuality),
+                            userHandle);
                     finishBiometricWeak();
                     dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
-                            0, 0, 0, 0, 0, 0, 0);
+                            0, 0, 0, 0, 0, 0, 0, userHandle);
                 }
                 // Add the password to the password history. We assume all
                 // password
                 // hashes have the same length for simplicity of implementation.
-                String passwordHistory = getString(PASSWORD_HISTORY_KEY);
+                String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
                 if (passwordHistory == null) {
                     passwordHistory = new String();
                 }
@@ -640,7 +700,7 @@
                             * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory
                             .length()));
                 }
-                setString(PASSWORD_HISTORY_KEY, passwordHistory);
+                setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle);
             } else {
                 // Conditionally reset the keystore if empty. If
                 // non-empty, we are just switching key guard type
@@ -648,7 +708,8 @@
                     keyStore.reset();
                 }
                 dpm.setActivePasswordState(
-                        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0);
+                        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0,
+                        userHandle);
             }
         } catch (RemoteException re) {
             // Cant do much
@@ -844,7 +905,7 @@
         if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)) {
             return false;
         }
-        if (getDevicePolicyManager().getCameraDisabled(null)) {
+        if (getDevicePolicyManager().getCameraDisabled(null, getCurrentOrCallingUserId())) {
             return false;
         }
 
@@ -899,14 +960,8 @@
      * @return Whether tactile feedback for the pattern is enabled.
      */
     public boolean isTactileFeedbackEnabled() {
-        return getBoolean(Settings.Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, false);
-    }
-
-    /**
-     * Set whether tactile feedback for the pattern is enabled.
-     */
-    public void setTactileFeedbackEnabled(boolean enabled) {
-        setBoolean(Settings.Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, enabled);
+        return Settings.System.getIntForUser(mContentResolver,
+                Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
     }
 
     /**
@@ -975,8 +1030,8 @@
      *   or null if there is no next alarm.
      */
     public String getNextAlarm() {
-        String nextAlarm = Settings.System.getString(mContentResolver,
-                Settings.System.NEXT_ALARM_FORMATTED);
+        String nextAlarm = Settings.System.getStringForUser(mContentResolver,
+                Settings.System.NEXT_ALARM_FORMATTED, UserHandle.USER_CURRENT);
         if (nextAlarm == null || TextUtils.isEmpty(nextAlarm)) {
             return null;
         }
@@ -1001,6 +1056,137 @@
         }
     }
 
+    public int[] getAppWidgets() {
+        String appWidgetIdString = Settings.Secure.getStringForUser(
+                mContentResolver, Settings.Secure.LOCK_SCREEN_APPWIDGET_IDS,
+                UserHandle.USER_CURRENT);
+        String delims = ",";
+        if (appWidgetIdString != null && appWidgetIdString.length() > 0) {
+            String[] appWidgetStringIds = appWidgetIdString.split(delims);
+            int[] appWidgetIds = new int[appWidgetStringIds.length];
+            for (int i = 0; i < appWidgetStringIds.length; i++) {
+                String appWidget = appWidgetStringIds[i];
+                try {
+                    appWidgetIds[i] = Integer.decode(appWidget);
+                } catch (NumberFormatException e) {
+                    Log.d(TAG, "Error when parsing widget id " + appWidget);
+                    return null;
+                }
+            }
+            return appWidgetIds;
+        }
+        return new int[0];
+    }
+
+    private static String combineStrings(int[] list, String separator) {
+        int listLength = list.length;
+
+        switch (listLength) {
+            case 0: {
+                return "";
+            }
+            case 1: {
+                return Integer.toString(list[0]);
+            }
+        }
+
+        int strLength = 0;
+        int separatorLength = separator.length();
+
+        String[] stringList = new String[list.length];
+        for (int i = 0; i < listLength; i++) {
+            stringList[i] = Integer.toString(list[i]);
+            strLength += stringList[i].length();
+            if (i < listLength - 1) {
+                strLength += separatorLength;
+            }
+        }
+
+        StringBuilder sb = new StringBuilder(strLength);
+
+        for (int i = 0; i < listLength; i++) {
+            sb.append(list[i]);
+            if (i < listLength - 1) {
+                sb.append(separator);
+            }
+        }
+
+        return sb.toString();
+    }
+
+    // appwidget used when appwidgets are disabled (we make an exception for
+    // default clock widget)
+    public void writeFallbackAppWidgetId(int appWidgetId) {
+        Settings.Secure.putIntForUser(mContentResolver,
+                Settings.Secure.LOCK_SCREEN_FALLBACK_APPWIDGET_ID,
+                appWidgetId,
+                UserHandle.USER_CURRENT);
+    }
+
+    // appwidget used when appwidgets are disabled (we make an exception for
+    // default clock widget)
+    public int getFallbackAppWidgetId() {
+        return Settings.Secure.getIntForUser(
+                mContentResolver,
+                Settings.Secure.LOCK_SCREEN_FALLBACK_APPWIDGET_ID,
+                AppWidgetManager.INVALID_APPWIDGET_ID,
+                UserHandle.USER_CURRENT);
+    }
+
+    private void writeAppWidgets(int[] appWidgetIds) {
+        Settings.Secure.putStringForUser(mContentResolver,
+                        Settings.Secure.LOCK_SCREEN_APPWIDGET_IDS,
+                        combineStrings(appWidgetIds, ","),
+                        UserHandle.USER_CURRENT);
+    }
+
+    // TODO: log an error if this returns false
+    public boolean addAppWidget(int widgetId, int index) {
+        int[] widgets = getAppWidgets();
+        if (widgets == null) {
+            return false;
+        }
+        if (index < 0 || index > widgets.length) {
+            return false;
+        }
+        int[] newWidgets = new int[widgets.length + 1];
+        for (int i = 0, j = 0; i < newWidgets.length; i++) {
+            if (index == i) {
+                newWidgets[i] = widgetId;
+                i++;
+            }
+            if (i < newWidgets.length) {
+                newWidgets[i] = widgets[j];
+                j++;
+            }
+        }
+        writeAppWidgets(newWidgets);
+        return true;
+    }
+
+    public boolean removeAppWidget(int widgetId) {
+        int[] widgets = getAppWidgets();
+
+        if (widgets.length == 0) {
+            return false;
+        }
+
+        int[] newWidgets = new int[widgets.length - 1];
+        for (int i = 0, j = 0; i < widgets.length; i++) {
+            if (widgets[i] == widgetId) {
+                // continue...
+            } else if (j >= newWidgets.length) {
+                // we couldn't find the widget
+                return false;
+            } else {
+                newWidgets[j] = widgets[i];
+                j++;
+            }
+        }
+        writeAppWidgets(newWidgets);
+        return true;
+    }
+
     private long getLong(String secureSettingKey, long defaultValue) {
         try {
             return getLockSettings().getLong(secureSettingKey, defaultValue,
@@ -1011,6 +1197,10 @@
     }
 
     private void setLong(String secureSettingKey, long value) {
+        setLong(secureSettingKey, value, getCurrentOrCallingUserId());
+    }
+
+    private void setLong(String secureSettingKey, long value, int userHandle) {
         try {
             getLockSettings().setLong(secureSettingKey, value, getCurrentOrCallingUserId());
         } catch (RemoteException re) {
@@ -1020,17 +1210,20 @@
     }
 
     private String getString(String secureSettingKey) {
+        return getString(secureSettingKey, getCurrentOrCallingUserId());
+    }
+
+    private String getString(String secureSettingKey, int userHandle) {
         try {
-            return getLockSettings().getString(secureSettingKey, null,
-                    getCurrentOrCallingUserId());
+            return getLockSettings().getString(secureSettingKey, null, userHandle);
         } catch (RemoteException re) {
             return null;
         }
     }
 
-    private void setString(String secureSettingKey, String value) {
+    private void setString(String secureSettingKey, String value, int userHandle) {
         try {
-            getLockSettings().setString(secureSettingKey, value, getCurrentOrCallingUserId());
+            getLockSettings().setString(secureSettingKey, value, userHandle);
         } catch (RemoteException re) {
             // What can we do?
             Log.e(TAG, "Couldn't write string " + secureSettingKey + re);
@@ -1062,8 +1255,13 @@
      *  {@link TelephonyManager#CALL_STATE_RINGING}
      *  {@link TelephonyManager#CALL_STATE_OFFHOOK}
      * @param shown indicates whether the given screen wants the emergency button to show at all
+     * @param button
+     * @param phoneState
+     * @param shown shown if true; hidden if false
+     * @param upperCase if true, converts button label string to upper case
      */
-    public void updateEmergencyCallButtonState(Button button, int  phoneState, boolean shown) {
+    public void updateEmergencyCallButtonState(Button button, int  phoneState, boolean shown,
+            boolean upperCase, boolean showIcon) {
         if (isEmergencyCallCapable() && shown) {
             button.setVisibility(View.VISIBLE);
         } else {
@@ -1075,14 +1273,30 @@
         if (phoneState == TelephonyManager.CALL_STATE_OFFHOOK) {
             // show "return to call" text and show phone icon
             textId = R.string.lockscreen_return_to_call;
-            int phoneCallIcon = R.drawable.stat_sys_phone_call;
+            int phoneCallIcon = showIcon ? R.drawable.stat_sys_phone_call : 0;
             button.setCompoundDrawablesWithIntrinsicBounds(phoneCallIcon, 0, 0, 0);
         } else {
             textId = R.string.lockscreen_emergency_call;
-            int emergencyIcon = R.drawable.ic_emergency;
+            int emergencyIcon = showIcon ? R.drawable.ic_emergency : 0;
             button.setCompoundDrawablesWithIntrinsicBounds(emergencyIcon, 0, 0, 0);
         }
-        button.setText(textId);
+        if (upperCase) {
+            CharSequence original = mContext.getResources().getText(textId);
+            String upper = original != null ? original.toString().toUpperCase() : null;
+            button.setText(upper);
+        } else {
+            button.setText(textId);
+        }
+    }
+
+    /**
+     * @deprecated
+     * @param button
+     * @param phoneState
+     * @param shown
+     */
+    public void updateEmergencyCallButtonState(Button button, int  phoneState, boolean shown) {
+        updateEmergencyCallButtonState(button, phoneState, shown, false, true);
     }
 
     /**
@@ -1122,4 +1336,14 @@
         return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true);
     }
 
+    public static boolean isSafeModeEnabled() {
+        try {
+            return IWindowManager.Stub.asInterface(
+                    ServiceManager.getService("window")).isSafeModeEnabled();
+        } catch (RemoteException e) {
+            // Shouldn't happen!
+        }
+        return false;
+    }
+
 }
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 0d9cf9a..7a76ab0 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -18,7 +18,6 @@
 
 
 import android.content.Context;
-import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -33,11 +32,9 @@
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.HapticFeedbackConstants;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 
 import com.android.internal.R;
@@ -375,31 +372,31 @@
     }
 
     private void notifyCellAdded() {
+        sendAccessEvent(R.string.lockscreen_access_pattern_cell_added);
         if (mOnPatternListener != null) {
             mOnPatternListener.onPatternCellAdded(mPattern);
         }
-        sendAccessEvent(R.string.lockscreen_access_pattern_cell_added);
     }
 
     private void notifyPatternStarted() {
+        sendAccessEvent(R.string.lockscreen_access_pattern_start);
         if (mOnPatternListener != null) {
             mOnPatternListener.onPatternStart();
         }
-        sendAccessEvent(R.string.lockscreen_access_pattern_start);
     }
 
     private void notifyPatternDetected() {
+        sendAccessEvent(R.string.lockscreen_access_pattern_detected);
         if (mOnPatternListener != null) {
             mOnPatternListener.onPatternDetected(mPattern);
         }
-        sendAccessEvent(R.string.lockscreen_access_pattern_detected);
     }
 
     private void notifyPatternCleared() {
+        sendAccessEvent(R.string.lockscreen_access_pattern_cleared);
         if (mOnPatternListener != null) {
             mOnPatternListener.onPatternCleared();
         }
-        sendAccessEvent(R.string.lockscreen_access_pattern_cleared);
     }
 
     /**
@@ -657,9 +654,11 @@
                 handleActionMove(event);
                 return true;
             case MotionEvent.ACTION_CANCEL:
-                resetPattern();
-                mPatternInProgress = false;
-                notifyPatternCleared();
+                if (mPatternInProgress) {
+                    mPatternInProgress = false;
+                    resetPattern();
+                    notifyPatternCleared();
+                }
                 if (PROFILE_DRAWING) {
                     if (mDrawingProfilingStarted) {
                         Debug.stopMethodTracing();
@@ -799,9 +798,7 @@
     }
 
     private void sendAccessEvent(int resId) {
-        setContentDescription(mContext.getString(resId));
-        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
-        setContentDescription(null);
+        announceForAccessibility(mContext.getString(resId));
     }
 
     private void handleActionUp(MotionEvent event) {
@@ -828,7 +825,7 @@
             mPatternInProgress = true;
             mPatternDisplayMode = DisplayMode.Correct;
             notifyPatternStarted();
-        } else {
+        } else if (mPatternInProgress) {
             mPatternInProgress = false;
             notifyPatternCleared();
         }
diff --git a/core/java/com/android/internal/widget/LockSettingsService.java b/core/java/com/android/internal/widget/LockSettingsService.java
index 24c7161..4ecbd16 100644
--- a/core/java/com/android/internal/widget/LockSettingsService.java
+++ b/core/java/com/android/internal/widget/LockSettingsService.java
@@ -23,8 +23,10 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.os.Binder;
+import android.os.Environment;
 import android.os.RemoteException;
-import android.os.UserId;
+import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.text.TextUtils;
@@ -96,7 +98,7 @@
 
     private static final void checkWritePermission(int userId) {
         final int callingUid = Binder.getCallingUid();
-        if (UserId.getAppId(callingUid) != android.os.Process.SYSTEM_UID) {
+        if (UserHandle.getAppId(callingUid) != android.os.Process.SYSTEM_UID) {
             throw new SecurityException("uid=" + callingUid
                     + " not authorized to write lock settings");
         }
@@ -104,7 +106,7 @@
 
     private static final void checkPasswordReadPermission(int userId) {
         final int callingUid = Binder.getCallingUid();
-        if (UserId.getAppId(callingUid) != android.os.Process.SYSTEM_UID) {
+        if (UserHandle.getAppId(callingUid) != android.os.Process.SYSTEM_UID) {
             throw new SecurityException("uid=" + callingUid
                     + " not authorized to read lock password");
         }
@@ -112,8 +114,8 @@
 
     private static final void checkReadPermission(int userId) {
         final int callingUid = Binder.getCallingUid();
-        if (UserId.getAppId(callingUid) != android.os.Process.SYSTEM_UID
-                && UserId.getUserId(callingUid) != userId) {
+        if (UserHandle.getAppId(callingUid) != android.os.Process.SYSTEM_UID
+                && UserHandle.getUserId(callingUid) != userId) {
             throw new SecurityException("uid=" + callingUid
                     + " not authorized to read settings of user " + userId);
         }
@@ -172,7 +174,8 @@
             // Leave it in the same place for user 0
             return dataSystemDirectory + LOCK_PATTERN_FILE;
         } else {
-            return  dataSystemDirectory + "users/" + userId + "/" + LOCK_PATTERN_FILE;
+            return  new File(Environment.getUserSystemDirectory(userId), LOCK_PATTERN_FILE)
+                    .getAbsolutePath();
         }
     }
 
@@ -184,7 +187,8 @@
             // Leave it in the same place for user 0
             return dataSystemDirectory + LOCK_PASSWORD_FILE;
         } else {
-            return  dataSystemDirectory + "users/" + userId + "/" + LOCK_PASSWORD_FILE;
+            return  new File(Environment.getUserSystemDirectory(userId), LOCK_PASSWORD_FILE)
+                    .getAbsolutePath();
         }
     }
 
@@ -303,12 +307,15 @@
     }
 
     private void writeToDb(String key, String value, int userId) {
+        writeToDb(mOpenHelper.getWritableDatabase(), key, value, userId);
+    }
+
+    private void writeToDb(SQLiteDatabase db, String key, String value, int userId) {
         ContentValues cv = new ContentValues();
         cv.put(COLUMN_KEY, key);
         cv.put(COLUMN_USERID, userId);
         cv.put(COLUMN_VALUE, value);
 
-        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
         db.beginTransaction();
         try {
             db.delete(TABLE, COLUMN_KEY + "=? AND " + COLUMN_USERID + "=?",
@@ -359,6 +366,16 @@
         @Override
         public void onCreate(SQLiteDatabase db) {
             createTable(db);
+            initializeDefaults(db);
+        }
+
+        private void initializeDefaults(SQLiteDatabase db) {
+            // Get the lockscreen default from a system property, if available
+            boolean lockScreenDisable = SystemProperties.getBoolean("ro.lockscreen.disable.default",
+                    false);
+            if (lockScreenDisable) {
+                writeToDb(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
+            }
         }
 
         @Override
diff --git a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
index 26518eb..f8332c4 100644
--- a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
+++ b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
@@ -31,6 +31,7 @@
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
 import android.view.ViewRootImpl;
 import com.android.internal.R;
 
@@ -55,23 +56,56 @@
     private long[] mVibratePattern;
     private boolean mEnableHaptics = false;
 
+    private static final int NUMERIC = 0;
+    private static final int QWERTY = 1;
+    private static final int QWERTY_SHIFTED = 2;
+    private static final int SYMBOLS = 3;
+    private static final int SYMBOLS_SHIFTED = 4;
+
+    int mLayouts[] = new int[] {
+            R.xml.password_kbd_numeric,
+            R.xml.password_kbd_qwerty,
+            R.xml.password_kbd_qwerty_shifted,
+            R.xml.password_kbd_symbols,
+            R.xml.password_kbd_symbols_shift
+            };
+
+    private boolean mUsingScreenWidth;
+
     public PasswordEntryKeyboardHelper(Context context, KeyboardView keyboardView, View targetView) {
-        this(context, keyboardView, targetView, true);
+        this(context, keyboardView, targetView, true, null);
     }
 
     public PasswordEntryKeyboardHelper(Context context, KeyboardView keyboardView, View targetView,
             boolean useFullScreenWidth) {
+        this(context, keyboardView, targetView, useFullScreenWidth, null);
+    }
+
+    public PasswordEntryKeyboardHelper(Context context, KeyboardView keyboardView, View targetView,
+            boolean useFullScreenWidth, int layouts[]) {
         mContext = context;
         mTargetView = targetView;
         mKeyboardView = keyboardView;
-        if (useFullScreenWidth
-                || mKeyboardView.getLayoutParams().width == ViewGroup.LayoutParams.MATCH_PARENT) {
-            createKeyboards();
-        } else {
-            createKeyboardsWithSpecificSize(mKeyboardView.getLayoutParams().width,
-                    mKeyboardView.getLayoutParams().height);
-        }
         mKeyboardView.setOnKeyboardActionListener(this);
+        mUsingScreenWidth = useFullScreenWidth;
+        if (layouts != null) {
+            if (layouts.length != mLayouts.length) {
+                throw new RuntimeException("Wrong number of layouts");
+            }
+            for (int i = 0; i < mLayouts.length; i++) {
+                mLayouts[i] = layouts[i];
+            }
+        }
+        createKeyboards();
+    }
+
+    public void createKeyboards() {
+        LayoutParams lp = mKeyboardView.getLayoutParams();
+        if (mUsingScreenWidth || lp.width == ViewGroup.LayoutParams.MATCH_PARENT) {
+            createKeyboardsWithDefaultWidth();
+        } else {
+            createKeyboardsWithSpecificSize(lp.width, lp.height);
+        }
     }
 
     public void setEnableHaptics(boolean enabled) {
@@ -82,46 +116,40 @@
         return mKeyboardMode == KEYBOARD_MODE_ALPHA;
     }
 
-    private void createKeyboardsWithSpecificSize(int viewWidth, int viewHeight) {
-        mNumericKeyboard = new PasswordEntryKeyboard(mContext, R.xml.password_kbd_numeric,
-                viewWidth, viewHeight);
-        mQwertyKeyboard = new PasswordEntryKeyboard(mContext,
-                R.xml.password_kbd_qwerty, R.id.mode_normal, viewWidth, viewHeight);
+    private void createKeyboardsWithSpecificSize(int width, int height) {
+        mNumericKeyboard = new PasswordEntryKeyboard(mContext, mLayouts[NUMERIC], width, height);
+        mQwertyKeyboard = new PasswordEntryKeyboard(mContext, mLayouts[QWERTY], R.id.mode_normal,
+                width, height);
         mQwertyKeyboard.enableShiftLock();
 
-        mQwertyKeyboardShifted = new PasswordEntryKeyboard(mContext,
-                R.xml.password_kbd_qwerty_shifted,
-                R.id.mode_normal, viewWidth, viewHeight);
+        mQwertyKeyboardShifted = new PasswordEntryKeyboard(mContext, mLayouts[QWERTY_SHIFTED],
+                R.id.mode_normal, width, height);
         mQwertyKeyboardShifted.enableShiftLock();
         mQwertyKeyboardShifted.setShifted(true); // always shifted.
 
-        mSymbolsKeyboard = new PasswordEntryKeyboard(mContext, R.xml.password_kbd_symbols,
-                viewWidth, viewHeight);
+        mSymbolsKeyboard = new PasswordEntryKeyboard(mContext, mLayouts[SYMBOLS], width, height);
         mSymbolsKeyboard.enableShiftLock();
 
-        mSymbolsKeyboardShifted = new PasswordEntryKeyboard(mContext,
-                R.xml.password_kbd_symbols_shift, viewWidth, viewHeight);
+        mSymbolsKeyboardShifted = new PasswordEntryKeyboard(mContext, mLayouts[SYMBOLS_SHIFTED],
+                width, height);
         mSymbolsKeyboardShifted.enableShiftLock();
         mSymbolsKeyboardShifted.setShifted(true); // always shifted
     }
 
-    private void createKeyboards() {
-        mNumericKeyboard = new PasswordEntryKeyboard(mContext, R.xml.password_kbd_numeric);
-        mQwertyKeyboard = new PasswordEntryKeyboard(mContext,
-                R.xml.password_kbd_qwerty, R.id.mode_normal);
+    private void createKeyboardsWithDefaultWidth() {
+        mNumericKeyboard = new PasswordEntryKeyboard(mContext, mLayouts[NUMERIC]);
+        mQwertyKeyboard = new PasswordEntryKeyboard(mContext, mLayouts[QWERTY], R.id.mode_normal);
         mQwertyKeyboard.enableShiftLock();
 
-        mQwertyKeyboardShifted = new PasswordEntryKeyboard(mContext,
-                R.xml.password_kbd_qwerty_shifted,
+        mQwertyKeyboardShifted = new PasswordEntryKeyboard(mContext, mLayouts[QWERTY_SHIFTED],
                 R.id.mode_normal);
         mQwertyKeyboardShifted.enableShiftLock();
         mQwertyKeyboardShifted.setShifted(true); // always shifted.
 
-        mSymbolsKeyboard = new PasswordEntryKeyboard(mContext, R.xml.password_kbd_symbols);
+        mSymbolsKeyboard = new PasswordEntryKeyboard(mContext, mLayouts[SYMBOLS]);
         mSymbolsKeyboard.enableShiftLock();
 
-        mSymbolsKeyboardShifted = new PasswordEntryKeyboard(mContext,
-                R.xml.password_kbd_symbols_shift);
+        mSymbolsKeyboardShifted = new PasswordEntryKeyboard(mContext, mLayouts[SYMBOLS_SHIFTED]);
         mSymbolsKeyboardShifted.enableShiftLock();
         mSymbolsKeyboardShifted.setShifted(true); // always shifted
     }
diff --git a/core/java/com/android/internal/widget/RotarySelector.java b/core/java/com/android/internal/widget/RotarySelector.java
index a2a38dc..4e405f4 100644
--- a/core/java/com/android/internal/widget/RotarySelector.java
+++ b/core/java/com/android/internal/widget/RotarySelector.java
@@ -25,7 +25,9 @@
 import android.graphics.BitmapFactory;
 import android.graphics.Matrix;
 import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
 import android.os.Vibrator;
+import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.MotionEvent;
@@ -667,11 +669,16 @@
      * Triggers haptic feedback.
      */
     private synchronized void vibrate(long duration) {
-        if (mVibrator == null) {
-            mVibrator = (android.os.Vibrator)
-                    getContext().getSystemService(Context.VIBRATOR_SERVICE);
+        final boolean hapticEnabled = Settings.System.getIntForUser(
+                mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 1,
+                UserHandle.USER_CURRENT) != 0;
+        if (hapticEnabled) {
+            if (mVibrator == null) {
+                mVibrator = (android.os.Vibrator) getContext()
+                        .getSystemService(Context.VIBRATOR_SERVICE);
+            }
+            mVibrator.vibrate(duration);
         }
-        mVibrator.vibrate(duration);
     }
 
     /**
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index 83ac8968..b620568 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -23,7 +23,9 @@
 import android.app.ActionBar;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
 import android.text.TextUtils.TruncateAt;
 import android.view.Gravity;
 import android.view.View;
@@ -38,6 +40,7 @@
 import android.widget.ListView;
 import android.widget.Spinner;
 import android.widget.TextView;
+import android.widget.Toast;
 
 /**
  * This widget implements the dynamic action bar tab behavior that can change
@@ -352,7 +355,7 @@
         tabView.getTab().select();
     }
 
-    private class TabView extends LinearLayout {
+    private class TabView extends LinearLayout implements OnLongClickListener {
         private ActionBar.Tab mTab;
         private TextView mTextView;
         private ImageView mIconView;
@@ -363,7 +366,7 @@
             mTab = tab;
 
             if (forList) {
-                setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
+                setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
             }
 
             update();
@@ -426,7 +429,8 @@
                     mIconView.setImageDrawable(null);
                 }
 
-                if (text != null) {
+                final boolean hasText = !TextUtils.isEmpty(text);
+                if (hasText) {
                     if (mTextView == null) {
                         TextView textView = new TextView(getContext(), null,
                                 com.android.internal.R.attr.actionBarTabTextStyle);
@@ -448,9 +452,35 @@
                 if (mIconView != null) {
                     mIconView.setContentDescription(tab.getContentDescription());
                 }
+
+                if (!hasText && !TextUtils.isEmpty(tab.getContentDescription())) {
+                    setOnLongClickListener(this);
+                } else {
+                    setOnLongClickListener(null);
+                    setLongClickable(false);
+                }
             }
         }
 
+        public boolean onLongClick(View v) {
+            final int[] screenPos = new int[2];
+            getLocationOnScreen(screenPos);
+
+            final Context context = getContext();
+            final int width = getWidth();
+            final int height = getHeight();
+            final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
+
+            Toast cheatSheet = Toast.makeText(context, mTab.getContentDescription(),
+                    Toast.LENGTH_SHORT);
+            // Show under the tab
+            cheatSheet.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL,
+                    (screenPos[0] + width / 2) - screenWidth / 2, height);
+
+            cheatSheet.show();
+            return true;
+        }
+
         public ActionBar.Tab getTab() {
             return mTab;
         }
diff --git a/core/java/com/android/internal/widget/SlidingTab.java b/core/java/com/android/internal/widget/SlidingTab.java
index f535a08..aebc4f6 100644
--- a/core/java/com/android/internal/widget/SlidingTab.java
+++ b/core/java/com/android/internal/widget/SlidingTab.java
@@ -21,7 +21,9 @@
 import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
 import android.os.Vibrator;
+import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.Gravity;
@@ -811,11 +813,16 @@
      * Triggers haptic feedback.
      */
     private synchronized void vibrate(long duration) {
-        if (mVibrator == null) {
-            mVibrator = (android.os.Vibrator)
-                    getContext().getSystemService(Context.VIBRATOR_SERVICE);
+        final boolean hapticEnabled = Settings.System.getIntForUser(
+                mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 1,
+                UserHandle.USER_CURRENT) != 0;
+        if (hapticEnabled) {
+            if (mVibrator == null) {
+                mVibrator = (android.os.Vibrator) getContext()
+                        .getSystemService(Context.VIBRATOR_SERVICE);
+            }
+            mVibrator.vibrate(duration);
         }
-        mVibrator.vibrate(duration);
     }
 
     /**
diff --git a/core/java/com/android/internal/widget/TextProgressBar.java b/core/java/com/android/internal/widget/TextProgressBar.java
index e113dd8..e898aa4 100644
--- a/core/java/com/android/internal/widget/TextProgressBar.java
+++ b/core/java/com/android/internal/widget/TextProgressBar.java
@@ -155,7 +155,7 @@
             // Calculate any adjustment based on gravity
             int adjustLeft = 0;
             int textWidth = mChronometer.getWidth();
-            if (mChronometerGravity == Gravity.RIGHT) {
+            if (mChronometerGravity == Gravity.END) {
                 adjustLeft = -textWidth;
             } else if (mChronometerGravity == Gravity.CENTER_HORIZONTAL) {
                 adjustLeft = -(textWidth / 2);
diff --git a/core/java/com/android/internal/widget/TransportControlView.java b/core/java/com/android/internal/widget/TransportControlView.java
index 2f52585..c33f038 100644
--- a/core/java/com/android/internal/widget/TransportControlView.java
+++ b/core/java/com/android/internal/widget/TransportControlView.java
@@ -23,7 +23,6 @@
 
 import android.app.PendingIntent;
 import android.app.PendingIntent.CanceledException;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
@@ -193,7 +192,7 @@
 
     public TransportControlView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        Log.v(TAG, "Create TCV " + this);
+        if (DEBUG) Log.v(TAG, "Create TCV " + this);
         mAudioManager = new AudioManager(mContext);
         mCurrentPlayState = RemoteControlClient.PLAYSTATE_NONE; // until we get a callback
         mIRCD = new IRemoteControlDisplayWeak(mHandler);
diff --git a/core/java/com/android/internal/widget/WaveView.java b/core/java/com/android/internal/widget/WaveView.java
index 2d89234..d33d50c 100644
--- a/core/java/com/android/internal/widget/WaveView.java
+++ b/core/java/com/android/internal/widget/WaveView.java
@@ -25,7 +25,9 @@
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.drawable.BitmapDrawable;
+import android.os.UserHandle;
 import android.os.Vibrator;
+import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -573,11 +575,16 @@
      * Triggers haptic feedback.
      */
     private synchronized void vibrate(long duration) {
-        if (mVibrator == null) {
-            mVibrator = (android.os.Vibrator)
-                    getContext().getSystemService(Context.VIBRATOR_SERVICE);
+        final boolean hapticEnabled = Settings.System.getIntForUser(
+                mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 1,
+                UserHandle.USER_CURRENT) != 0;
+        if (hapticEnabled) {
+            if (mVibrator == null) {
+                mVibrator = (android.os.Vibrator) getContext()
+                        .getSystemService(Context.VIBRATOR_SERVICE);
+            }
+            mVibrator.vibrate(duration);
         }
-        mVibrator.vibrate(duration);
     }
 
     /**
diff --git a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
index 4e60b75..aad285a 100644
--- a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
@@ -31,7 +31,9 @@
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.os.Vibrator;
+import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -39,7 +41,6 @@
 import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 
 import com.android.internal.R;
@@ -112,9 +113,13 @@
     private float mWaveCenterY;
     private int mMaxTargetHeight;
     private int mMaxTargetWidth;
+    private float mRingScaleFactor = 1f;
+    private boolean mAllowScaling;
 
     private float mOuterRadius = 0.0f;
     private float mSnapMargin = 0.0f;
+    private float mFirstItemOffset = 0.0f;
+    private boolean mMagneticTargets = false;
     private boolean mDragging;
     private int mNewTargetResources;
 
@@ -197,6 +202,7 @@
     private Tweener mBackgroundAnimator;
     private PointCloud mPointCloud;
     private float mInnerRadius;
+    private int mPointerId;
 
     public GlowPadView(Context context) {
         this(context, null);
@@ -210,17 +216,22 @@
         mInnerRadius = a.getDimension(R.styleable.GlowPadView_innerRadius, mInnerRadius);
         mOuterRadius = a.getDimension(R.styleable.GlowPadView_outerRadius, mOuterRadius);
         mSnapMargin = a.getDimension(R.styleable.GlowPadView_snapMargin, mSnapMargin);
+        mFirstItemOffset = (float) Math.toRadians(
+                a.getFloat(R.styleable.GlowPadView_firstItemOffset,
+                        (float) Math.toDegrees(mFirstItemOffset)));
         mVibrationDuration = a.getInt(R.styleable.GlowPadView_vibrationDuration,
                 mVibrationDuration);
         mFeedbackCount = a.getInt(R.styleable.GlowPadView_feedbackCount,
                 mFeedbackCount);
-        mHandleDrawable = new TargetDrawable(res,
-                a.peekValue(R.styleable.GlowPadView_handleDrawable).resourceId);
+        mAllowScaling = a.getBoolean(R.styleable.GlowPadView_allowScaling, false);
+        TypedValue handle = a.peekValue(R.styleable.GlowPadView_handleDrawable);
+        mHandleDrawable = new TargetDrawable(res, handle != null ? handle.resourceId : 0);
         mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
         mOuterRing = new TargetDrawable(res,
                 getResourceId(a, R.styleable.GlowPadView_outerRingDrawable));
 
         mAlwaysTrackFinger = a.getBoolean(R.styleable.GlowPadView_alwaysTrackFinger, false);
+        mMagneticTargets = a.getBoolean(R.styleable.GlowPadView_magneticTargets, mMagneticTargets);
 
         int pointId = getResourceId(a, R.styleable.GlowPadView_pointDrawable);
         Drawable pointDrawable = pointId != 0 ? res.getDrawable(pointId) : null;
@@ -254,11 +265,8 @@
             setDirectionDescriptionsResourceId(resourceId);
         }
 
-        a.recycle();
+        mGravity = a.getInt(R.styleable.GlowPadView_gravity, Gravity.TOP);
 
-        // Use gravity attribute from LinearLayout
-        a = context.obtainStyledAttributes(attrs, android.R.styleable.LinearLayout);
-        mGravity = a.getInt(android.R.styleable.LinearLayout_gravity, Gravity.TOP);
         a.recycle();
 
         setVibrateEnabled(mVibrationDuration > 0);
@@ -314,6 +322,22 @@
         return (int) (Math.max(mOuterRing.getHeight(), 2 * mOuterRadius) + mMaxTargetHeight);
     }
 
+    /**
+     * This gets the suggested width accounting for the ring's scale factor.
+     */
+    protected int getScaledSuggestedMinimumWidth() {
+        return (int) (mRingScaleFactor * Math.max(mOuterRing.getWidth(), 2 * mOuterRadius)
+                + mMaxTargetWidth);
+    }
+
+    /**
+     * This gets the suggested height accounting for the ring's scale factor.
+     */
+    protected int getScaledSuggestedMinimumHeight() {
+        return (int) (mRingScaleFactor * Math.max(mOuterRing.getHeight(), 2 * mOuterRadius)
+                + mMaxTargetHeight);
+    }
+
     private int resolveMeasured(int measureSpec, int desired)
     {
         int result = 0;
@@ -332,16 +356,6 @@
         return result;
     }
 
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        final int minimumWidth = getSuggestedMinimumWidth();
-        final int minimumHeight = getSuggestedMinimumHeight();
-        int computedWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
-        int computedHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
-        computeInsets((computedWidth - minimumWidth), (computedHeight - minimumHeight));
-        setMeasuredDimension(computedWidth, computedHeight);
-    }
-
     private void switchToState(int state, float x, float y) {
         switch (state) {
             case STATE_IDLE:
@@ -499,8 +513,9 @@
                     "onUpdate", mUpdateListener));
         }
 
-        final float ringScaleTarget = expanded ?
+        float ringScaleTarget = expanded ?
                 RING_SCALE_EXPANDED : RING_SCALE_COLLAPSED;
+        ringScaleTarget *= mRingScaleFactor;
         mTargetAnimations.add(Tweener.to(mOuterRing, duration,
                 "ease", interpolator,
                 "alpha", 0.0f,
@@ -530,11 +545,13 @@
                     "delay", delay,
                     "onUpdate", mUpdateListener));
         }
+
+        float ringScale = mRingScaleFactor * RING_SCALE_EXPANDED;
         mTargetAnimations.add(Tweener.to(mOuterRing, duration,
                 "ease", Ease.Cubic.easeOut,
                 "alpha", 1.0f,
-                "scaleX", 1.0f,
-                "scaleY", 1.0f,
+                "scaleX", ringScale,
+                "scaleY", ringScale,
                 "delay", delay,
                 "onUpdate", mUpdateListener,
                 "onComplete", mTargetUpdateListener));
@@ -543,7 +560,10 @@
     }
 
     private void vibrate() {
-        if (mVibrator != null) {
+        final boolean hapticEnabled = Settings.System.getIntForUser(
+                mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 1,
+                UserHandle.USER_CURRENT) != 0;
+        if (mVibrator != null && hapticEnabled) {
             mVibrator.vibrate(mVibrationDuration);
         }
     }
@@ -717,7 +737,7 @@
         startBackgroundAnimation(0, 0.0f);
         stopAndHideWaveAnimation();
         hideTargets(animate, false);
-        hideGlow(0, 0, 1.0f, null);
+        hideGlow(0, 0, 0.0f, null);
         Tweener.reset();
     }
 
@@ -737,9 +757,10 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
-        final int action = event.getAction();
+        final int action = event.getActionMasked();
         boolean handled = false;
         switch (action) {
+            case MotionEvent.ACTION_POINTER_DOWN:
             case MotionEvent.ACTION_DOWN:
                 if (DEBUG) Log.v(TAG, "*** DOWN ***");
                 handleDown(event);
@@ -753,6 +774,7 @@
                 handled = true;
                 break;
 
+            case MotionEvent.ACTION_POINTER_UP:
             case MotionEvent.ACTION_UP:
                 if (DEBUG) Log.v(TAG, "*** UP ***");
                 handleMove(event);
@@ -766,43 +788,51 @@
                 handleCancel(event);
                 handled = true;
                 break;
+
         }
         invalidate();
         return handled ? true : super.onTouchEvent(event);
     }
 
     private void updateGlowPosition(float x, float y) {
-        mPointCloud.glowManager.setX(x);
-        mPointCloud.glowManager.setY(y);
+        float dx = x - mOuterRing.getX();
+        float dy = y - mOuterRing.getY();
+        dx *= 1f / mRingScaleFactor;
+        dy *= 1f / mRingScaleFactor;
+        mPointCloud.glowManager.setX(mOuterRing.getX() + dx);
+        mPointCloud.glowManager.setY(mOuterRing.getY() + dy);
     }
 
     private void handleDown(MotionEvent event) {
-        float eventX = event.getX();
-        float eventY = event.getY();
+        int actionIndex = event.getActionIndex();
+        float eventX = event.getX(actionIndex);
+        float eventY = event.getY(actionIndex);
         switchToState(STATE_START, eventX, eventY);
         if (!trySwitchToFirstTouchState(eventX, eventY)) {
             mDragging = false;
         } else {
+            mPointerId = event.getPointerId(actionIndex);
             updateGlowPosition(eventX, eventY);
         }
     }
 
     private void handleUp(MotionEvent event) {
         if (DEBUG && mDragging) Log.v(TAG, "** Handle RELEASE");
-        switchToState(STATE_FINISH, event.getX(), event.getY());
+        int actionIndex = event.getActionIndex();
+        if (event.getPointerId(actionIndex) == mPointerId) {
+            switchToState(STATE_FINISH, event.getX(actionIndex), event.getY(actionIndex));
+        }
     }
 
     private void handleCancel(MotionEvent event) {
         if (DEBUG && mDragging) Log.v(TAG, "** Handle CANCEL");
 
-        // We should drop the active target here but it interferes with
-        // moving off the screen in the direction of the navigation bar. At some point we may
-        // want to revisit how we handle this. For now we'll allow a canceled event to
-        // activate the current target.
+        // Drop the active target if canceled.
+        mActiveTarget = -1; 
 
-        // mActiveTarget = -1; // Drop the active target if canceled.
-
-        switchToState(STATE_FINISH, event.getX(), event.getY());
+        int actionIndex = event.findPointerIndex(mPointerId);
+        actionIndex = actionIndex == -1 ? 0 : actionIndex;
+        switchToState(STATE_FINISH, event.getX(actionIndex), event.getY(actionIndex));
     }
 
     private void handleMove(MotionEvent event) {
@@ -812,9 +842,18 @@
         int ntargets = targets.size();
         float x = 0.0f;
         float y = 0.0f;
+        float activeAngle = 0.0f;
+        int actionIndex = event.findPointerIndex(mPointerId);
+
+        if (actionIndex == -1) {
+            return;  // no data for this pointer
+        }
+
         for (int k = 0; k < historySize + 1; k++) {
-            float eventX = k < historySize ? event.getHistoricalX(k) : event.getX();
-            float eventY = k < historySize ? event.getHistoricalY(k) : event.getY();
+            float eventX = k < historySize ? event.getHistoricalX(actionIndex, k)
+                    : event.getX(actionIndex);
+            float eventY = k < historySize ? event.getHistoricalY(actionIndex, k)
+                    : event.getY(actionIndex);
             // tx and ty are relative to wave center
             float tx = eventX - mWaveCenterX;
             float ty = eventY - mWaveCenterY;
@@ -830,21 +869,24 @@
 
             if (mDragging) {
                 // For multiple targets, snap to the one that matches
-                final float snapRadius = mOuterRadius - mSnapMargin;
+                final float snapRadius = mRingScaleFactor * mOuterRadius - mSnapMargin;
                 final float snapDistance2 = snapRadius * snapRadius;
                 // Find first target in range
                 for (int i = 0; i < ntargets; i++) {
                     TargetDrawable target = targets.get(i);
 
-                    double targetMinRad = (i - 0.5) * 2 * Math.PI / ntargets;
-                    double targetMaxRad = (i + 0.5) * 2 * Math.PI / ntargets;
+                    double targetMinRad = mFirstItemOffset + (i - 0.5) * 2 * Math.PI / ntargets;
+                    double targetMaxRad = mFirstItemOffset + (i + 0.5) * 2 * Math.PI / ntargets;
                     if (target.isEnabled()) {
                         boolean angleMatches =
                             (angleRad > targetMinRad && angleRad <= targetMaxRad) ||
                             (angleRad + 2 * Math.PI > targetMinRad &&
-                             angleRad + 2 * Math.PI <= targetMaxRad);
+                             angleRad + 2 * Math.PI <= targetMaxRad) ||
+                            (angleRad - 2 * Math.PI > targetMinRad &&
+                             angleRad - 2 * Math.PI <= targetMaxRad);
                         if (angleMatches && (dist2(tx, ty) > snapDistance2)) {
                             activeTarget = i;
+                            activeAngle = (float) -angleRad;
                         }
                     }
                 }
@@ -872,6 +914,9 @@
                 if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
                     target.setState(TargetDrawable.STATE_INACTIVE);
                 }
+                if (mMagneticTargets) {
+                    updateTargetPosition(mActiveTarget, mWaveCenterX, mWaveCenterY);
+                }
             }
             // Focus the new target
             if (activeTarget != -1) {
@@ -879,6 +924,9 @@
                 if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
                     target.setState(TargetDrawable.STATE_FOCUSED);
                 }
+                if (mMagneticTargets) {
+                    updateTargetPosition(activeTarget, mWaveCenterX, mWaveCenterY, activeAngle);
+                }
                 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
                     String targetContentDescription = getTargetDescription(activeTarget);
                     announceForAccessibility(targetContentDescription);
@@ -906,7 +954,8 @@
             onTouchEvent(event);
             event.setAction(action);
         }
-        return super.onHoverEvent(event);
+        super.onHoverEvent(event);
+        return true;
     }
 
     /**
@@ -957,7 +1006,7 @@
     }
 
     private void computeInsets(int dx, int dy) {
-        final int layoutDirection = getResolvedLayoutDirection();
+        final int layoutDirection = getLayoutDirection();
         final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
 
         switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
@@ -986,6 +1035,78 @@
         }
     }
 
+    /**
+     * Given the desired width and height of the ring and the allocated width and height, compute
+     * how much we need to scale the ring.
+     */
+    private float computeScaleFactor(int desiredWidth, int desiredHeight,
+            int actualWidth, int actualHeight) {
+
+        // Return unity if scaling is not allowed.
+        if (!mAllowScaling) return 1f;
+
+        final int layoutDirection = getLayoutDirection();
+        final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
+
+        float scaleX = 1f;
+        float scaleY = 1f;
+
+        // We use the gravity as a cue for whether we want to scale on a particular axis.
+        // We only scale to fit horizontally if we're not pinned to the left or right. Likewise,
+        // we only scale to fit vertically if we're not pinned to the top or bottom. In these
+        // cases, we want the ring to hang off the side or top/bottom, respectively.
+        switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+            case Gravity.LEFT:
+            case Gravity.RIGHT:
+                break;
+            case Gravity.CENTER_HORIZONTAL:
+            default:
+                if (desiredWidth > actualWidth) {
+                    scaleX = (1f * actualWidth - mMaxTargetWidth) /
+                            (desiredWidth - mMaxTargetWidth);
+                }
+                break;
+        }
+        switch (absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK) {
+            case Gravity.TOP:
+            case Gravity.BOTTOM:
+                break;
+            case Gravity.CENTER_VERTICAL:
+            default:
+                if (desiredHeight > actualHeight) {
+                    scaleY = (1f * actualHeight - mMaxTargetHeight) /
+                            (desiredHeight - mMaxTargetHeight);
+                }
+                break;
+        }
+        return Math.min(scaleX, scaleY);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        final int minimumWidth = getSuggestedMinimumWidth();
+        final int minimumHeight = getSuggestedMinimumHeight();
+        int computedWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
+        int computedHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
+
+        mRingScaleFactor = computeScaleFactor(minimumWidth, minimumHeight,
+                computedWidth, computedHeight);
+
+        int scaledWidth = getScaledSuggestedMinimumWidth();
+        int scaledHeight = getScaledSuggestedMinimumHeight();
+
+        computeInsets(computedWidth - scaledWidth, computedHeight - scaledHeight);
+        setMeasuredDimension(computedWidth, computedHeight);
+    }
+
+    private float getRingWidth() {
+        return mRingScaleFactor * Math.max(mOuterRing.getWidth(), 2 * mOuterRadius);
+    }
+
+    private float getRingHeight() {
+        return mRingScaleFactor * Math.max(mOuterRing.getHeight(), 2 * mOuterRadius);
+    }
+
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
@@ -994,8 +1115,8 @@
 
         // Target placement width/height. This puts the targets on the greater of the ring
         // width or the specified outer radius.
-        final float placementWidth = Math.max(mOuterRing.getWidth(), 2 * mOuterRadius);
-        final float placementHeight = Math.max(mOuterRing.getHeight(), 2 * mOuterRadius);
+        final float placementWidth = getRingWidth();
+        final float placementHeight = getRingHeight();
         float newWaveCenterX = mHorizontalInset
                 + Math.max(width, mMaxTargetWidth + placementWidth) / 2;
         float newWaveCenterY = mVerticalInset
@@ -1010,6 +1131,8 @@
         mOuterRing.setPositionX(newWaveCenterX);
         mOuterRing.setPositionY(newWaveCenterY);
 
+        mPointCloud.setScale(mRingScaleFactor);
+
         mHandleDrawable.setPositionX(newWaveCenterX);
         mHandleDrawable.setPositionY(newWaveCenterY);
 
@@ -1023,21 +1146,47 @@
         if (DEBUG) dump();
     }
 
-    private void updateTargetPositions(float centerX, float centerY) {
-        // Reposition the target drawables if the view changed.
-        ArrayList<TargetDrawable> targets = mTargetDrawables;
-        final int size = targets.size();
-        final float alpha = (float) (-2.0f * Math.PI / size);
-        for (int i = 0; i < size; i++) {
+    private void updateTargetPosition(int i, float centerX, float centerY) {
+        final float angle = getAngle(getSliceAngle(), i);
+        updateTargetPosition(i, centerX, centerY, angle);
+    }
+
+    private void updateTargetPosition(int i, float centerX, float centerY, float angle) {
+        final float placementRadiusX = getRingWidth() / 2;
+        final float placementRadiusY = getRingHeight() / 2;
+        if (i >= 0) {
+            ArrayList<TargetDrawable> targets = mTargetDrawables;
             final TargetDrawable targetIcon = targets.get(i);
-            final float angle = alpha * i;
             targetIcon.setPositionX(centerX);
             targetIcon.setPositionY(centerY);
-            targetIcon.setX(mOuterRadius * (float) Math.cos(angle));
-            targetIcon.setY(mOuterRadius * (float) Math.sin(angle));
+            targetIcon.setX(placementRadiusX * (float) Math.cos(angle));
+            targetIcon.setY(placementRadiusY * (float) Math.sin(angle));
         }
     }
 
+    private void updateTargetPositions(float centerX, float centerY) {
+        updateTargetPositions(centerX, centerY, false);
+    }
+
+    private void updateTargetPositions(float centerX, float centerY, boolean skipActive) {
+        final int size = mTargetDrawables.size();
+        final float alpha = getSliceAngle();
+        // Reposition the target drawables if the view changed.
+        for (int i = 0; i < size; i++) {
+            if (!skipActive || i != mActiveTarget) {
+                updateTargetPosition(i, centerX, centerY, getAngle(alpha, i));
+            }
+        }
+    }
+
+    private float getAngle(float alpha, int i) {
+        return mFirstItemOffset + alpha * i;
+    }
+
+    private float getSliceAngle() {
+        return (float) (-2.0f * Math.PI / mTargetDrawables.size());
+    }
+
     private void updatePointCloudPosition(float centerX, float centerY) {
         mPointCloud.setCenter(centerX, centerY);
     }
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index 10804c0..e22d1e8 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -19,7 +19,6 @@
 import android.animation.Animator;
 import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
@@ -33,7 +32,9 @@
 import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.os.Vibrator;
+import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -594,7 +595,10 @@
     }
 
     private void vibrate() {
-        if (mVibrator != null) {
+        final boolean hapticEnabled = Settings.System.getIntForUser(
+                mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 1,
+                UserHandle.USER_CURRENT) != 0;
+        if (mVibrator != null && hapticEnabled) {
             mVibrator.vibrate(mVibrationDuration);
         }
     }
@@ -970,7 +974,7 @@
     }
 
     private void computeInsets(int dx, int dy) {
-        final int layoutDirection = getResolvedLayoutDirection();
+        final int layoutDirection = getLayoutDirection();
         final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
 
         switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 6f3653d..3ca085b 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -32,6 +32,7 @@
 	com_google_android_gles_jni_EGLImpl.cpp \
 	com_google_android_gles_jni_GLImpl.cpp.arm \
 	android_app_NativeActivity.cpp \
+	android_opengl_EGL14.cpp \
 	android_opengl_GLES10.cpp \
 	android_opengl_GLES10Ext.cpp \
 	android_opengl_GLES11.cpp \
@@ -43,9 +44,9 @@
 	android_database_SQLiteGlobal.cpp \
 	android_database_SQLiteDebug.cpp \
 	android_emoji_EmojiFactory.cpp \
-	android_view_Display.cpp \
 	android_view_DisplayEventReceiver.cpp \
 	android_view_Surface.cpp \
+	android_view_SurfaceSession.cpp \
 	android_view_TextureView.cpp \
 	android_view_InputChannel.cpp \
 	android_view_InputDevice.cpp \
@@ -125,6 +126,7 @@
 	android_media_AudioSystem.cpp \
 	android_media_AudioTrack.cpp \
 	android_media_JetPlayer.cpp \
+	android_media_RemoteDisplay.cpp \
 	android_media_ToneGenerator.cpp \
 	android_hardware_Camera.cpp \
 	android_hardware_SensorManager.cpp \
@@ -136,14 +138,6 @@
 	android_util_FileObserver.cpp \
 	android/opengl/poly_clip.cpp.arm \
 	android/opengl/util.cpp.arm \
-	android_bluetooth_HeadsetBase.cpp \
-	android_bluetooth_common.cpp \
-	android_bluetooth_BluetoothAudioGateway.cpp \
-	android_bluetooth_BluetoothSocket.cpp \
-	android_bluetooth_c.c \
-	android_server_BluetoothService.cpp \
-	android_server_BluetoothEventLoop.cpp \
-	android_server_BluetoothA2dpService.cpp \
 	android_server_NetworkManagementSocketTagger.cpp \
 	android_server_Watchdog.cpp \
 	android_ddm_DdmHandleNativeHeap.cpp \
@@ -169,6 +163,7 @@
 	external/skia/include/core \
 	external/skia/include/effects \
 	external/skia/include/images \
+	external/skia/include/ports \
 	external/skia/src/ports \
 	external/skia/include/utils \
 	external/sqlite/dist \
@@ -228,14 +223,6 @@
 	LOCAL_SHARED_LIBRARIES += libhwui
 endif
 
-ifeq ($(BOARD_HAVE_BLUETOOTH),true)
-LOCAL_C_INCLUDES += \
-	external/dbus \
-	system/bluetooth/bluez-clean-headers
-LOCAL_CFLAGS += -DHAVE_BLUETOOTH
-LOCAL_SHARED_LIBRARIES += libbluedroid libdbus
-endif
-
 LOCAL_SHARED_LIBRARIES += \
 	libdl
 # we need to access the private Bionic header
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index d08e651..9820e60 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -68,6 +68,7 @@
 
 extern int register_com_google_android_gles_jni_EGLImpl(JNIEnv* env);
 extern int register_com_google_android_gles_jni_GLImpl(JNIEnv* env);
+extern int register_android_opengl_jni_EGL14(JNIEnv* env);
 extern int register_android_opengl_jni_GLES10(JNIEnv* env);
 extern int register_android_opengl_jni_GLES10Ext(JNIEnv* env);
 extern int register_android_opengl_jni_GLES11(JNIEnv* env);
@@ -115,12 +116,12 @@
 extern int register_android_graphics_SurfaceTexture(JNIEnv* env);
 extern int register_android_graphics_Xfermode(JNIEnv* env);
 extern int register_android_graphics_PixelFormat(JNIEnv* env);
-extern int register_android_view_Display(JNIEnv* env);
 extern int register_android_view_DisplayEventReceiver(JNIEnv* env);
 extern int register_android_view_GLES20DisplayList(JNIEnv* env);
 extern int register_android_view_GLES20Canvas(JNIEnv* env);
 extern int register_android_view_HardwareRenderer(JNIEnv* env);
 extern int register_android_view_Surface(JNIEnv* env);
+extern int register_android_view_SurfaceSession(JNIEnv* env);
 extern int register_android_view_TextureView(JNIEnv* env);
 extern int register_android_database_CursorWindow(JNIEnv* env);
 extern int register_android_database_SQLiteConnection(JNIEnv* env);
@@ -148,12 +149,6 @@
 extern int register_android_text_AndroidCharacter(JNIEnv *env);
 extern int register_android_text_AndroidBidi(JNIEnv *env);
 extern int register_android_opengl_classes(JNIEnv *env);
-extern int register_android_bluetooth_HeadsetBase(JNIEnv* env);
-extern int register_android_bluetooth_BluetoothAudioGateway(JNIEnv* env);
-extern int register_android_bluetooth_BluetoothSocket(JNIEnv *env);
-extern int register_android_server_BluetoothService(JNIEnv* env);
-extern int register_android_server_BluetoothEventLoop(JNIEnv *env);
-extern int register_android_server_BluetoothA2dpService(JNIEnv* env);
 extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env);
 extern int register_android_server_Watchdog(JNIEnv* env);
 extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
@@ -165,6 +160,7 @@
 extern int register_android_app_backup_FullBackup(JNIEnv *env);
 extern int register_android_app_ActivityThread(JNIEnv *env);
 extern int register_android_app_NativeActivity(JNIEnv *env);
+extern int register_android_media_RemoteDisplay(JNIEnv *env);
 extern int register_android_view_InputChannel(JNIEnv* env);
 extern int register_android_view_InputDevice(JNIEnv* env);
 extern int register_android_view_InputEventReceiver(JNIEnv* env);
@@ -457,6 +453,9 @@
     char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
     char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
     char heapgrowthlimitOptsBuf[sizeof("-XX:HeapGrowthLimit=")-1 + PROPERTY_VALUE_MAX];
+    char heapminfreeOptsBuf[sizeof("-XX:HeapMinFree=")-1 + PROPERTY_VALUE_MAX];
+    char heapmaxfreeOptsBuf[sizeof("-XX:HeapMaxFree=")-1 + PROPERTY_VALUE_MAX];
+    char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
     char extraOptsBuf[PROPERTY_VALUE_MAX];
     char* stackTraceFile = NULL;
     bool checkJni = false;
@@ -559,6 +558,27 @@
         mOptions.add(opt);
     }
 
+    strcpy(heapminfreeOptsBuf, "-XX:HeapMinFree=");
+    property_get("dalvik.vm.heapminfree", heapminfreeOptsBuf+16, "");
+    if (heapminfreeOptsBuf[16] != '\0') {
+        opt.optionString = heapminfreeOptsBuf;
+        mOptions.add(opt);
+    }
+
+    strcpy(heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");
+    property_get("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf+16, "");
+    if (heapmaxfreeOptsBuf[16] != '\0') {
+        opt.optionString = heapmaxfreeOptsBuf;
+        mOptions.add(opt);
+    }
+
+    strcpy(heaptargetutilizationOptsBuf, "-XX:HeapTargetUtilization=");
+    property_get("dalvik.vm.heaptargetutilization", heaptargetutilizationOptsBuf+26, "");
+    if (heaptargetutilizationOptsBuf[26] != '\0') {
+        opt.optionString = heaptargetutilizationOptsBuf;
+        mOptions.add(opt);
+    }
+
     /*
      * Enable or disable dexopt features, such as bytecode verification and
      * calculation of register maps for precise GC.
@@ -1092,7 +1112,6 @@
     REG_JNI(register_android_os_SystemProperties),
     REG_JNI(register_android_os_Binder),
     REG_JNI(register_android_os_Parcel),
-    REG_JNI(register_android_view_Display),
     REG_JNI(register_android_view_DisplayEventReceiver),
     REG_JNI(register_android_nio_utils),
     REG_JNI(register_android_graphics_PixelFormat),
@@ -1101,9 +1120,11 @@
     REG_JNI(register_android_view_GLES20Canvas),
     REG_JNI(register_android_view_HardwareRenderer),
     REG_JNI(register_android_view_Surface),
+    REG_JNI(register_android_view_SurfaceSession),
     REG_JNI(register_android_view_TextureView),
     REG_JNI(register_com_google_android_gles_jni_EGLImpl),
     REG_JNI(register_com_google_android_gles_jni_GLImpl),
+    REG_JNI(register_android_opengl_jni_EGL14),
     REG_JNI(register_android_opengl_jni_GLES10),
     REG_JNI(register_android_opengl_jni_GLES10Ext),
     REG_JNI(register_android_opengl_jni_GLES11),
@@ -1165,15 +1186,10 @@
     REG_JNI(register_android_media_AudioSystem),
     REG_JNI(register_android_media_AudioTrack),
     REG_JNI(register_android_media_JetPlayer),
+    REG_JNI(register_android_media_RemoteDisplay),
     REG_JNI(register_android_media_ToneGenerator),
 
     REG_JNI(register_android_opengl_classes),
-    REG_JNI(register_android_bluetooth_HeadsetBase),
-    REG_JNI(register_android_bluetooth_BluetoothAudioGateway),
-    REG_JNI(register_android_bluetooth_BluetoothSocket),
-    REG_JNI(register_android_server_BluetoothService),
-    REG_JNI(register_android_server_BluetoothEventLoop),
-    REG_JNI(register_android_server_BluetoothA2dpService),
     REG_JNI(register_android_server_NetworkManagementSocketTagger),
     REG_JNI(register_android_server_Watchdog),
     REG_JNI(register_android_ddm_DdmHandleNativeHeap),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 1bba5b4..63683b4 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -7,7 +7,7 @@
 #include "SkUnPreMultiply.h"

 

 #include <binder/Parcel.h>

-#include "android_os_Parcel.h"
+#include "android_os_Parcel.h"

 #include "android_util_Binder.h"

 #include "android_nio_utils.h"

 #include "CreateJavaOutputStreamAdaptor.h"

@@ -145,7 +145,7 @@
 static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,

                                  SkColorTable*) {

     SkASSERT(width > 0);

-    const SkPMColor* s = (const SkPMColor*)src;

+    const SkPMColor16* s = (const SkPMColor16*)src;

     do {

         SkPMColor c = SkPixel4444ToPixel32(*s++);

         *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),

@@ -261,14 +261,14 @@
     delete bitmap;

 }

 

-static void Bitmap_recycle(JNIEnv* env, jobject, SkBitmap* bitmap) {

+static jboolean Bitmap_recycle(JNIEnv* env, jobject, SkBitmap* bitmap) {

 #ifdef USE_OPENGL_RENDERER

     if (android::uirenderer::Caches::hasInstance()) {

-        android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap);

-        return;

+        return android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap);

     }

 #endif // USE_OPENGL_RENDERER

     bitmap->setPixels(NULL, NULL);

+    return true;

 }

 

 // These must match the int values in Bitmap.java

@@ -353,6 +353,15 @@
     bitmap->setIsOpaque(!hasAlpha);

 }

 

+static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, SkBitmap* bitmap) {

+    return bitmap->hasHardwareMipMap();

+}

+

+static void Bitmap_setHasMipMap(JNIEnv* env, jobject, SkBitmap* bitmap,

+                                jboolean hasMipMap) {

+    bitmap->setHasHardwareMipMap(hasMipMap);

+}

+

 ///////////////////////////////////////////////////////////////////////////////

 

 static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {

@@ -656,7 +665,7 @@
     {   "nativeCopy",               "(IIZ)Landroid/graphics/Bitmap;",

         (void*)Bitmap_copy },

     {   "nativeDestructor",         "(I)V", (void*)Bitmap_destructor },

-    {   "nativeRecycle",            "(I)V", (void*)Bitmap_recycle },

+    {   "nativeRecycle",            "(I)Z", (void*)Bitmap_recycle },

     {   "nativeCompress",           "(IIILjava/io/OutputStream;[B)Z",

         (void*)Bitmap_compress },

     {   "nativeErase",              "(II)V", (void*)Bitmap_erase },

@@ -666,6 +675,8 @@
     {   "nativeConfig",             "(I)I", (void*)Bitmap_config },

     {   "nativeHasAlpha",           "(I)Z", (void*)Bitmap_hasAlpha },

     {   "nativeSetHasAlpha",        "(IZ)V", (void*)Bitmap_setHasAlpha },

+    {   "nativeHasMipMap",          "(I)Z", (void*)Bitmap_hasMipMap },

+    {   "nativeSetHasMipMap",       "(IZ)V", (void*)Bitmap_setHasMipMap },

     {   "nativeCreateFromParcel",

         "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",

         (void*)Bitmap_createFromParcel },

diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 69ef080..8823328 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -340,7 +340,9 @@
 
         bitmap->setConfig(config, scaledWidth, scaledHeight);
         bitmap->setIsOpaque(decoded->isOpaque());
-        bitmap->allocPixels(&javaAllocator, NULL);
+        if (!bitmap->allocPixels(&javaAllocator, NULL)) {
+            return nullObjectReturn("allocation failed for scaled bitmap");
+        }
         bitmap->eraseColor(0);
 
         SkPaint paint;
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 6b74705..5d6f738 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -20,6 +20,7 @@
 
 #include "SkCanvas.h"
 #include "SkDevice.h"
+#include "SkDrawFilter.h"
 #include "SkGraphics.h"
 #include "SkImageRef_GlobalPool.h"
 #include "SkPorterDuff.h"
@@ -766,15 +767,72 @@
         if (value == NULL) {
             return;
         }
-        doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(), x, y, flags, paint);
+        SkPaint::Align align = paint->getTextAlign();
+        if (align == SkPaint::kCenter_Align) {
+            x -= 0.5 * value->getTotalAdvance();
+        } else if (align == SkPaint::kRight_Align) {
+            x -= value->getTotalAdvance();
+        }
+        paint->setTextAlign(SkPaint::kLeft_Align);
+        doDrawGlyphsPos(canvas, value->getGlyphs(), value->getPos(), 0, value->getGlyphsCount(), x, y, flags, paint);
+        doDrawTextDecorations(canvas, x, y, value->getTotalAdvance(), paint);
+        paint->setTextAlign(align);
     }
 
+// Same values used by Skia
+#define kStdStrikeThru_Offset   (-6.0f / 21.0f)
+#define kStdUnderline_Offset    (1.0f / 9.0f)
+#define kStdUnderline_Thickness (1.0f / 18.0f)
+
+static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat length, SkPaint* paint) {
+    uint32_t flags;
+    SkDrawFilter* drawFilter = canvas->getDrawFilter();
+    if (drawFilter) {
+        SkPaint paintCopy(*paint);
+        drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
+        flags = paintCopy.getFlags();
+    } else {
+        flags = paint->getFlags();
+    }
+    if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
+        SkScalar left = SkFloatToScalar(x);
+        SkScalar right = SkFloatToScalar(x + length);
+        float textSize = paint->getTextSize();
+        float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
+        if (flags & SkPaint::kUnderlineText_Flag) {
+            SkScalar top = SkFloatToScalar(y + textSize * kStdUnderline_Offset
+                    - 0.5f * strokeWidth);
+            SkScalar bottom = SkFloatToScalar(y + textSize * kStdUnderline_Offset
+                    + 0.5f * strokeWidth);
+            canvas->drawRectCoords(left, top, right, bottom, *paint);
+        }
+        if (flags & SkPaint::kStrikeThruText_Flag) {
+            SkScalar top = SkFloatToScalar(y + textSize * kStdStrikeThru_Offset
+                    - 0.5f * strokeWidth);
+            SkScalar bottom = SkFloatToScalar(y + textSize * kStdStrikeThru_Offset
+                    + 0.5f * strokeWidth);
+            canvas->drawRectCoords(left, top, right, bottom, *paint);
+        }
+    }
+}
+
     static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count,
             jfloat x, jfloat y, int flags, SkPaint* paint) {
         // Beware: this needs Glyph encoding (already done on the Paint constructor)
         canvas->drawText(glyphArray + index * 2, count * 2, x, y, *paint);
     }
 
+    static void doDrawGlyphsPos(SkCanvas* canvas, const jchar* glyphArray, const jfloat* posArray,
+            int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) {
+        SkPoint* posPtr = new SkPoint[count];
+        for (int indx = 0; indx < count; indx++) {
+            posPtr[indx].fX = SkFloatToScalar(x + posArray[indx * 2]);
+            posPtr[indx].fY = SkFloatToScalar(y + posArray[indx * 2 + 1]);
+        }
+        canvas->drawPosText(glyphArray, count << 1, posPtr, *paint);
+        delete[] posPtr;
+    }
+
     static void drawTextRun___CIIIIFFIPaint(
         JNIEnv* env, jobject, SkCanvas* canvas, jcharArray text, int index,
         int count, int contextIndex, int contextCount,
@@ -882,6 +940,9 @@
         SkIRect ir;
         bool     result = canvas->getClipBounds(&r, SkCanvas::kBW_EdgeType);
 
+        if (!result) {
+            r.setEmpty();
+        }
         r.round(&ir);
         (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
         return result;
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index a4d5477..150caf3 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -22,6 +22,7 @@
 #include "jni.h"
 #include "GraphicsJNI.h"
 #include <android_runtime/AndroidRuntime.h>
+#include <ScopedUtfChars.h>
 
 #include "SkBlurDrawLooper.h"
 #include "SkColorFilter.h"
@@ -30,6 +31,7 @@
 #include "SkShader.h"
 #include "SkTypeface.h"
 #include "SkXfermode.h"
+#include "unicode/uloc.h"
 #include "unicode/ushape.h"
 #include "TextLayout.h"
 
@@ -254,11 +256,51 @@
         obj->setTextAlign(align);
     }
 
+    // generate bcp47 identifier for the supplied locale
+    static void toLanguageTag(char* output, size_t outSize,
+            const char* locale) {
+        if (output == NULL || outSize <= 0) {
+            return;
+        }
+        if (locale == NULL) {
+            output[0] = '\0';
+            return;
+        }
+        char canonicalChars[ULOC_FULLNAME_CAPACITY];
+        UErrorCode uErr = U_ZERO_ERROR;
+        uloc_canonicalize(locale, canonicalChars, ULOC_FULLNAME_CAPACITY,
+                &uErr);
+        if (U_SUCCESS(uErr)) {
+            char likelyChars[ULOC_FULLNAME_CAPACITY];
+            uErr = U_ZERO_ERROR;
+            uloc_addLikelySubtags(canonicalChars, likelyChars,
+                    ULOC_FULLNAME_CAPACITY, &uErr);
+            if (U_SUCCESS(uErr)) {
+                uErr = U_ZERO_ERROR;
+                uloc_toLanguageTag(likelyChars, output, outSize, FALSE, &uErr);
+                if (U_SUCCESS(uErr)) {
+                    return;
+                } else {
+                    ALOGD("uloc_toLanguageTag(\"%s\") failed: %s", likelyChars,
+                            u_errorName(uErr));
+                }
+            } else {
+                ALOGD("uloc_addLikelySubtags(\"%s\") failed: %s",
+                        canonicalChars, u_errorName(uErr));
+            }
+        } else {
+            ALOGD("uloc_canonicalize(\"%s\") failed: %s", locale,
+                    u_errorName(uErr));
+        }
+        // unable to build a proper language identifier
+        output[0] = '\0';
+    }
+
     static void setTextLocale(JNIEnv* env, jobject clazz, SkPaint* obj, jstring locale) {
-        const char* localeArray = env->GetStringUTFChars(locale, NULL);
-        SkString skLocale(localeArray);
-        obj->setTextLocale(skLocale);
-        env->ReleaseStringUTFChars(locale, localeArray);
+        ScopedUtfChars localeChars(env, locale);
+        char langTag[ULOC_FULLNAME_CAPACITY];
+        toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, localeChars.c_str());
+        obj->setLanguage(SkLanguage(langTag));
     }
 
     static jfloat getTextSize(JNIEnv* env, jobject paint) {
@@ -587,7 +629,7 @@
             jint count, jint flags, jint offset, jint opt) {
         jfloat scalarArray[count];
 
-        TextLayout::getTextRunAdvances(paint, text, start, count, count, flags,
+        TextLayout::getTextRunAdvances(paint, text, start, count, start + count, flags,
                 scalarArray, NULL /* dont need totalAdvance */);
 
         jint pos = offset - start;
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index f4cc9e4..6323ab3 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -150,19 +150,35 @@
     jfloat* storedBounds = new jfloat[4];
     storedBounds[0] = x0; storedBounds[1] = y0;
     storedBounds[2] = x1; storedBounds[3] = y1;
-    jfloat* storedPositions = new jfloat[count];
-    uint32_t* storedColors = new uint32_t[count];
-    for (size_t i = 0; i < count; i++) {
-        storedColors[i] = static_cast<uint32_t>(colorValues[i]);
-    }
+    
+    bool missFirst = false;
+    bool missLast = false;
+    size_t stopCount = count;
 
+    jfloat* storedPositions = NULL;
     if (posArray) {
         AutoJavaFloatArray autoPos(env, posArray, count);
         const float* posValues = autoPos.ptr();
-        for (size_t i = 0; i < count; i++) {
-            storedPositions[i] = posValues[i];
+
+        missFirst = posValues[0] != 0.0f;
+        missLast = posValues[count - 1] != 1.0f;
+
+        stopCount += missFirst + missLast;
+        storedPositions = new jfloat[stopCount];
+
+        if (missFirst) {
+            storedPositions[0] = 0.0f;
+        }
+
+        for (size_t i = missFirst; i < count + missFirst; i++) {
+            storedPositions[i] = posValues[i - missFirst];
+        }
+
+        if (missLast) {
+            storedPositions[stopCount - 1] = 1.0f;
         }
     } else {
+        storedPositions = new jfloat[count];
         storedPositions[0] = 0.0f;
         const jfloat step = 1.0f / (count - 1);
         for (size_t i = 1; i < count - 1; i++) {
@@ -171,8 +187,22 @@
         storedPositions[count - 1] = 1.0f;
     }
 
+    uint32_t* storedColors = new uint32_t[stopCount];
+
+    if (missFirst) {
+        storedColors[0] = static_cast<uint32_t>(colorValues[0]);
+    }
+
+    for (size_t i = missFirst; i < count + missFirst; i++) {
+        storedColors[i] = static_cast<uint32_t>(colorValues[i - missFirst]);
+    }
+
+    if (missLast) {
+        storedColors[stopCount - 1] = static_cast<uint32_t>(colorValues[count - 1]);
+    }
+
     SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors,
-            storedPositions, count, shader, static_cast<SkShader::TileMode>(tileMode), NULL,
+            storedPositions, stopCount, shader, static_cast<SkShader::TileMode>(tileMode), NULL,
             (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
 
     env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 35f82a8..4669c37 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -19,6 +19,7 @@
 #include "TextLayoutCache.h"
 #include "TextLayout.h"
 #include "SkFontHost.h"
+#include "SkTypeface_android.h"
 #include <unicode/unistr.h>
 #include <unicode/normlzr.h>
 #include <unicode/uchar.h>
@@ -30,14 +31,6 @@
 namespace android {
 
 //--------------------------------------------------------------------------------------------------
-#define TYPEFACE_ARABIC "/system/fonts/DroidNaskh-Regular-SystemUI.ttf"
-#define TYPE_FACE_HEBREW_REGULAR "/system/fonts/DroidSansHebrew-Regular.ttf"
-#define TYPE_FACE_HEBREW_BOLD "/system/fonts/DroidSansHebrew-Bold.ttf"
-#define TYPEFACE_BENGALI "/system/fonts/Lohit-Bengali.ttf"
-#define TYPEFACE_DEVANAGARI_REGULAR "/system/fonts/DroidSansDevanagari-Regular.ttf"
-#define TYPEFACE_TAMIL_REGULAR "/system/fonts/DroidSansTamil-Regular.ttf"
-#define TYPEFACE_TAMIL_BOLD "/system/fonts/DroidSansTamil-Bold.ttf"
-#define TYPEFACE_THAI "/system/fonts/DroidSansThai.ttf"
 
 ANDROID_SINGLETON_STATIC_INSTANCE(TextLayoutEngine);
 
@@ -85,8 +78,10 @@
 /*
  * Cache clearing
  */
-void TextLayoutCache::clear() {
+void TextLayoutCache::purgeCaches() {
+    AutoMutex _l(mLock);
     mCache.clear();
+    mShaper->purgeCaches();
 }
 
 /*
@@ -116,7 +111,7 @@
 
         // Compute advances and store them
         mShaper->computeValues(value.get(), paint,
-                reinterpret_cast<const UChar*>(text), start, count,
+                reinterpret_cast<const UChar*>(key.getText()), start, count,
                 size_t(contextCount), int(dirFlags));
 
         if (mDebugEnabled) {
@@ -144,15 +139,12 @@
             // Update current cache size
             mSize += size;
 
-            // Copy the text when we insert the new entry
-            key.internalTextCopy();
-
             bool putOne = mCache.put(key, value);
             LOG_ALWAYS_FATAL_IF(!putOne, "Failed to put an entry into the cache.  "
                     "This indicates that the cache already has an entry with the "
                     "same key but it should not since we checked earlier!"
                     " - start = %d, count = %d, contextCount = %d - Text = '%s'",
-                    start, count, contextCount, String8(text + start, count).string());
+                    start, count, contextCount, String8(key.getText() + start, count).string());
 
             if (mDebugEnabled) {
                 nsecs_t totalTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
@@ -163,7 +155,7 @@
                         value.get(), start, count, contextCount, size, mMaxSize - mSize,
                         value->getElapsedTime() * 0.000001f,
                         (totalTime - value->getElapsedTime()) * 0.000001f,
-                        String8(text + start, count).string());
+                        String8(key.getText() + start, count).string());
             }
         } else {
             if (mDebugEnabled) {
@@ -173,7 +165,7 @@
                         " - Compute time %0.6f ms - Text = '%s'",
                         start, count, contextCount, size, mMaxSize - mSize,
                         value->getElapsedTime() * 0.000001f,
-                        String8(text + start, count).string());
+                        String8(key.getText() + start, count).string());
             }
         }
     } else {
@@ -193,7 +185,7 @@
                         value->getElapsedTime() * 0.000001f,
                         elapsedTimeThruCacheGet * 0.000001f,
                         deltaPercent,
-                        String8(text + start, count).string());
+                        String8(key.getText() + start, count).string());
             }
             if (mCacheHitCount % DEFAULT_DUMP_STATS_CACHE_HIT_INTERVAL == 0) {
                 dumpCacheStats();
@@ -230,25 +222,27 @@
 /**
  * TextLayoutCacheKey
  */
-TextLayoutCacheKey::TextLayoutCacheKey(): text(NULL), start(0), count(0), contextCount(0),
+TextLayoutCacheKey::TextLayoutCacheKey(): start(0), count(0), contextCount(0),
         dirFlags(0), typeface(NULL), textSize(0), textSkewX(0), textScaleX(0), flags(0),
-        hinting(SkPaint::kNo_Hinting)  {
+        hinting(SkPaint::kNo_Hinting), variant(SkPaint::kDefault_Variant), language()  {
 }
 
 TextLayoutCacheKey::TextLayoutCacheKey(const SkPaint* paint, const UChar* text,
         size_t start, size_t count, size_t contextCount, int dirFlags) :
-            text(text), start(start), count(count), contextCount(contextCount),
+            start(start), count(count), contextCount(contextCount),
             dirFlags(dirFlags) {
+    textCopy.setTo(text, contextCount);
     typeface = paint->getTypeface();
     textSize = paint->getTextSize();
     textSkewX = paint->getTextSkewX();
     textScaleX = paint->getTextScaleX();
     flags = paint->getFlags();
     hinting = paint->getHinting();
+    variant = paint->getFontVariant();
+    language = paint->getLanguage();
 }
 
 TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) :
-        text(NULL),
         textCopy(other.textCopy),
         start(other.start),
         count(other.count),
@@ -259,10 +253,9 @@
         textSkewX(other.textSkewX),
         textScaleX(other.textScaleX),
         flags(other.flags),
-        hinting(other.hinting) {
-    if (other.text) {
-        textCopy.setTo(other.text, other.contextCount);
-    }
+        hinting(other.hinting),
+        variant(other.variant),
+        language(other.language) {
 }
 
 int TextLayoutCacheKey::compare(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
@@ -296,12 +289,13 @@
     deltaInt = lhs.dirFlags - rhs.dirFlags;
     if (deltaInt) return (deltaInt);
 
-    return memcmp(lhs.getText(), rhs.getText(), lhs.contextCount * sizeof(UChar));
-}
+    deltaInt = lhs.variant - rhs.variant;
+    if (deltaInt) return (deltaInt);
 
-void TextLayoutCacheKey::internalTextCopy() {
-    textCopy.setTo(text, contextCount);
-    text = NULL;
+    if (lhs.language < rhs.language) return -1;
+    if (lhs.language > rhs.language) return +1;
+
+    return memcmp(lhs.getText(), rhs.getText(), lhs.contextCount * sizeof(UChar));
 }
 
 size_t TextLayoutCacheKey::getSize() const {
@@ -316,11 +310,12 @@
     // Give a hint for advances and glyphs vectors size
     mAdvances.setCapacity(contextCount);
     mGlyphs.setCapacity(contextCount);
+    mPos.setCapacity(contextCount * 2);
 }
 
 size_t TextLayoutValue::getSize() const {
     return sizeof(TextLayoutValue) + sizeof(jfloat) * mAdvances.capacity() +
-            sizeof(jchar) * mGlyphs.capacity();
+            sizeof(jchar) * mGlyphs.capacity() + sizeof(jfloat) * mPos.capacity();
 }
 
 void TextLayoutValue::setElapsedTime(uint32_t time) {
@@ -337,13 +332,9 @@
     mFontRec.klass = &harfbuzzSkiaClass;
     mFontRec.userData = 0;
 
-    // The values which harfbuzzSkiaClass returns are already scaled to
-    // pixel units, so we just set all these to one to disable further
-    // scaling.
-    mFontRec.x_ppem = 1;
-    mFontRec.y_ppem = 1;
-    mFontRec.x_scale = 1;
-    mFontRec.y_scale = 1;
+    // Note that the scaling values (x_ and y_ppem, x_ and y_scale) will be set
+    // below, when the paint transform and em unit of the actual shaping font
+    // are known.
 
     memset(&mShaperItem, 0, sizeof(mShaperItem));
 
@@ -353,26 +344,10 @@
 
 void TextLayoutShaper::init() {
     mDefaultTypeface = SkFontHost::CreateTypeface(NULL, NULL, NULL, 0, SkTypeface::kNormal);
-    mArabicTypeface = NULL;
-    mHebrewRegularTypeface = NULL;
-    mHebrewBoldTypeface = NULL;
-    mBengaliTypeface = NULL;
-    mThaiTypeface = NULL;
-    mDevanagariRegularTypeface = NULL;
-    mTamilRegularTypeface = NULL;
-    mTamilBoldTypeface = NULL;
 }
 
 void TextLayoutShaper::unrefTypefaces() {
     SkSafeUnref(mDefaultTypeface);
-    SkSafeUnref(mArabicTypeface);
-    SkSafeUnref(mHebrewRegularTypeface);
-    SkSafeUnref(mHebrewBoldTypeface);
-    SkSafeUnref(mBengaliTypeface);
-    SkSafeUnref(mThaiTypeface);
-    SkSafeUnref(mDevanagariRegularTypeface);
-    SkSafeUnref(mTamilRegularTypeface);
-    SkSafeUnref(mTamilBoldTypeface);
 }
 
 TextLayoutShaper::~TextLayoutShaper() {
@@ -384,7 +359,7 @@
         size_t start, size_t count, size_t contextCount, int dirFlags) {
 
     computeValues(paint, chars, start, count, contextCount, dirFlags,
-            &value->mAdvances, &value->mTotalAdvance, &value->mGlyphs);
+            &value->mAdvances, &value->mTotalAdvance, &value->mGlyphs, &value->mPos);
 #if DEBUG_ADVANCES
     ALOGD("Advances - start = %d, count = %d, contextCount = %d, totalAdvance = %f", start, count,
             contextCount, value->mTotalAdvance);
@@ -394,9 +369,9 @@
 void TextLayoutShaper::computeValues(const SkPaint* paint, const UChar* chars,
         size_t start, size_t count, size_t contextCount, int dirFlags,
         Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
-        Vector<jchar>* const outGlyphs) {
+        Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos) {
+        *outTotalAdvance = 0;
         if (!count) {
-            *outTotalAdvance = 0;
             return;
         }
 
@@ -461,6 +436,7 @@
                                 ALOGW("Visual run is not valid");
                                 outGlyphs->clear();
                                 outAdvances->clear();
+                                outPos->clear();
                                 *outTotalAdvance = 0;
                                 isRTL = (paraDir == 1);
                                 useSingleRun = true;
@@ -483,15 +459,13 @@
 
                             lengthRun = endRun - startRun;
                             isRTL = (runDir == UBIDI_RTL);
-                            jfloat runTotalAdvance = 0;
 #if DEBUG_GLYPHS
                             ALOGD("Processing Bidi Run = %d -- run-start = %d, run-len = %d, isRTL = %d",
                                     i, startRun, lengthRun, isRTL);
 #endif
                             computeRunValues(paint, chars + startRun, lengthRun, isRTL,
-                                    outAdvances, &runTotalAdvance, outGlyphs);
+                                    outAdvances, outTotalAdvance, outGlyphs, outPos);
 
-                            *outTotalAdvance += runTotalAdvance;
                         }
                     }
                 } else {
@@ -514,7 +488,7 @@
                     "-- run-start = %d, run-len = %d, isRTL = %d", start, count, isRTL);
 #endif
             computeRunValues(paint, chars + start, count, isRTL,
-                    outAdvances, outTotalAdvance, outGlyphs);
+                    outAdvances, outTotalAdvance, outGlyphs, outPos);
         }
 
 #if DEBUG_GLYPHS
@@ -536,10 +510,9 @@
 void TextLayoutShaper::computeRunValues(const SkPaint* paint, const UChar* chars,
         size_t count, bool isRTL,
         Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
-        Vector<jchar>* const outGlyphs) {
+        Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos) {
     if (!count) {
         // We cannot shape an empty run.
-        *outTotalAdvance = 0;
         return;
     }
 
@@ -639,16 +612,19 @@
 
     // Define shaping paint properties
     mShapingPaint.setTextSize(paint->getTextSize());
-    mShapingPaint.setTextSkewX(paint->getTextSkewX());
+    float skewX = paint->getTextSkewX();
+    mShapingPaint.setTextSkewX(skewX);
     mShapingPaint.setTextScaleX(paint->getTextScaleX());
     mShapingPaint.setFlags(paint->getFlags());
     mShapingPaint.setHinting(paint->getHinting());
+    mShapingPaint.setFontVariant(paint->getFontVariant());
+    mShapingPaint.setLanguage(paint->getLanguage());
 
     // Split the BiDi run into Script runs. Harfbuzz will populate the pos, length and script
     // into the shaperItem
     ssize_t indexFontRun = isRTL ? mShaperItem.stringLength - 1 : 0;
     unsigned numCodePoints = 0;
-    jfloat totalAdvance = 0;
+    jfloat totalAdvance = *outTotalAdvance;
     while ((isRTL) ?
             hb_utf16_script_run_prev(&numCodePoints, &mShaperItem.item, mShaperItem.string,
                     mShaperItem.stringLength, &indexFontRun):
@@ -699,24 +675,24 @@
                     i, HBFixedToFloat(mShaperItem.advances[i]));
         }
 #endif
-        // Get Advances and their total
-        jfloat currentAdvance = HBFixedToFloat(mShaperItem.advances[mShaperItem.log_clusters[0]]);
-        jfloat totalFontRunAdvance = currentAdvance;
-        outAdvances->replaceAt(currentAdvance, startScriptRun);
-        for (size_t i = 1; i < countScriptRun; i++) {
-            size_t clusterPrevious = mShaperItem.log_clusters[i - 1];
+        jfloat totalFontRunAdvance = 0;
+        size_t clusterStart = 0;
+        for (size_t i = 0; i < countScriptRun; i++) {
             size_t cluster = mShaperItem.log_clusters[i];
-            if (cluster != clusterPrevious) {
-                currentAdvance = HBFixedToFloat(mShaperItem.advances[mShaperItem.log_clusters[i]]);
-                outAdvances->replaceAt(currentAdvance, startScriptRun + i);
+            size_t clusterNext = i == countScriptRun - 1 ? mShaperItem.num_glyphs :
+                mShaperItem.log_clusters[i + 1];
+            if (cluster != clusterNext) {
+                jfloat advance = 0;
+                // The advance for the cluster is the sum of the advances of all glyphs within
+                // the cluster.
+                for (size_t j = cluster; j < clusterNext; j++) {
+                    advance += HBFixedToFloat(mShaperItem.advances[j]);
+                }
+                totalFontRunAdvance += advance;
+                outAdvances->replaceAt(advance, startScriptRun + clusterStart);
+                clusterStart = i + 1;
             }
         }
-        // TODO: can be removed and go back in the previous loop when Harfbuzz log clusters are fixed
-        for (size_t i = 1; i < mShaperItem.num_glyphs; i++) {
-            currentAdvance = HBFixedToFloat(mShaperItem.advances[i]);
-            totalFontRunAdvance += currentAdvance;
-        }
-        totalAdvance += totalFontRunAdvance;
 
 #if DEBUG_ADVANCES
         ALOGD("Returned advances");
@@ -741,6 +717,30 @@
                 outGlyphs->add(glyph);
             }
         }
+
+        // Get glyph positions (and reverse them in place if RTL)
+        if (outPos) {
+            size_t countGlyphs = mShaperItem.num_glyphs;
+            jfloat x = totalAdvance;
+            for (size_t i = 0; i < countGlyphs; i++) {
+                size_t index = (!isRTL) ? i : countGlyphs - 1 - i;
+                float xo = HBFixedToFloat(mShaperItem.offsets[index].x);
+                float yo = HBFixedToFloat(mShaperItem.offsets[index].y);
+                // Apply skewX component of transform to position offsets. Note
+                // that scale has already been applied through x_ and y_scale
+                // set in the mFontRec.
+                outPos->add(x + xo + yo * skewX);
+                outPos->add(yo);
+#if DEBUG_GLYPHS
+                ALOGD("         -- hb adv[%d] = %f, log_cluster[%d] = %d",
+                        index, HBFixedToFloat(mShaperItem.advances[index]),
+                        index, mShaperItem.log_clusters[index]);
+#endif
+                x += HBFixedToFloat(mShaperItem.advances[index]);
+            }
+        }
+
+        totalAdvance += totalFontRunAdvance;
     }
 
     *outTotalAdvance = totalAdvance;
@@ -758,105 +758,32 @@
  * assumption is that its lifetime is managed elsewhere - in particular, the fallback typefaces
  * for the default font live in a global cache.
  */
-SkTypeface* TextLayoutShaper::typefaceForUnichar(const SkPaint* paint, SkTypeface* typeface,
-        SkUnichar unichar, HB_Script script) {
-    // Set the correct Typeface depending on the script
-    switch (script) {
-    case HB_Script_Arabic:
-        typeface = getCachedTypeface(&mArabicTypeface, TYPEFACE_ARABIC);
-#if DEBUG_GLYPHS
-        ALOGD("Using Arabic Typeface");
-#endif
-        break;
-
-    case HB_Script_Hebrew:
-        if (typeface) {
-            switch (typeface->style()) {
-            case SkTypeface::kBold:
-            case SkTypeface::kBoldItalic:
-                typeface = getCachedTypeface(&mHebrewBoldTypeface, TYPE_FACE_HEBREW_BOLD);
-#if DEBUG_GLYPHS
-                ALOGD("Using Hebrew Bold/BoldItalic Typeface");
-#endif
-                break;
-
-            case SkTypeface::kNormal:
-            case SkTypeface::kItalic:
-            default:
-                typeface = getCachedTypeface(&mHebrewRegularTypeface, TYPE_FACE_HEBREW_REGULAR);
-#if DEBUG_GLYPHS
-                ALOGD("Using Hebrew Regular/Italic Typeface");
-#endif
-                break;
-            }
-        } else {
-            typeface = getCachedTypeface(&mHebrewRegularTypeface, TYPE_FACE_HEBREW_REGULAR);
-#if DEBUG_GLYPHS
-            ALOGD("Using Hebrew Regular Typeface");
-#endif
-        }
-        break;
-
-    case HB_Script_Bengali:
-        typeface = getCachedTypeface(&mBengaliTypeface, TYPEFACE_BENGALI);
-#if DEBUG_GLYPHS
-        ALOGD("Using Bengali Typeface");
-#endif
-        break;
-
-    case HB_Script_Thai:
-        typeface = getCachedTypeface(&mThaiTypeface, TYPEFACE_THAI);
-#if DEBUG_GLYPHS
-        ALOGD("Using Thai Typeface");
-#endif
-        break;
-
-    case HB_Script_Devanagari:
-       typeface = getCachedTypeface(&mDevanagariRegularTypeface, TYPEFACE_DEVANAGARI_REGULAR);
-#if DEBUG_GLYPHS
-       ALOGD("Using Devanagari Regular Typeface");
-#endif
-        break;
-
-    case HB_Script_Tamil:
-        if (typeface) {
-            switch (typeface->style()) {
-            case SkTypeface::kBold:
-            case SkTypeface::kBoldItalic:
-                typeface = getCachedTypeface(&mTamilBoldTypeface, TYPEFACE_TAMIL_BOLD);
-#if DEBUG_GLYPHS
-                ALOGD("Using Tamil Bold Typeface");
-#endif
-                break;
-
-            case SkTypeface::kNormal:
-            case SkTypeface::kItalic:
-            default:
-                typeface = getCachedTypeface(&mTamilRegularTypeface, TYPEFACE_TAMIL_REGULAR);
-#if DEBUG_GLYPHS
-                ALOGD("Using Tamil Regular Typeface");
-#endif
-                break;
-            }
-        } else {
-            typeface = getCachedTypeface(&mTamilRegularTypeface, TYPEFACE_TAMIL_REGULAR);
-#if DEBUG_GLYPHS
-            ALOGD("Using Tamil Regular Typeface");
-#endif
-        }
-        break;
-
-    default:
-#if DEBUG_GLYPHS
-        if (typeface) {
-            ALOGD("Using Paint Typeface");
-        }
-#endif
-        break;
+SkTypeface* TextLayoutShaper::typefaceForScript(const SkPaint* paint, SkTypeface* typeface,
+        HB_Script script) {
+    SkTypeface::Style currentStyle = SkTypeface::kNormal;
+    if (typeface) {
+        currentStyle = typeface->style();
     }
+    typeface = SkCreateTypefaceForScript(script, currentStyle);
+#if DEBUG_GLYPHS
+    ALOGD("Using Harfbuzz Script %d, Style %d", script, currentStyle);
+#endif
     return typeface;
 }
 
+bool TextLayoutShaper::isComplexScript(HB_Script script) {
+    switch (script) {
+    case HB_Script_Common:
+    case HB_Script_Greek:
+    case HB_Script_Cyrillic:
+    case HB_Script_Hangul:
+    case HB_Script_Inherited:
+        return false;
+    default:
+        return true;
+    }
+}
+
 size_t TextLayoutShaper::shapeFontRun(const SkPaint* paint, bool isRTL) {
     // Reset kerning
     mShaperItem.kerning_applied = false;
@@ -872,63 +799,76 @@
     // If we are a "common" script we dont need to shift
     size_t baseGlyphCount = 0;
     SkUnichar firstUnichar = 0;
-    switch (mShaperItem.item.script) {
-    case HB_Script_Arabic:
-    case HB_Script_Hebrew:
-    case HB_Script_Bengali:
-    case HB_Script_Devanagari:
-    case HB_Script_Tamil:
-    case HB_Script_Thai:{
-        const uint16_t* text16 = (const uint16_t*)(mShaperItem.string + mShaperItem.item.pos);
+    if (isComplexScript(mShaperItem.item.script)) {
+        const uint16_t* text16 = (const uint16_t*) (mShaperItem.string + mShaperItem.item.pos);
         const uint16_t* text16End = text16 + mShaperItem.item.length;
         firstUnichar = SkUTF16_NextUnichar(&text16);
         while (firstUnichar == ' ' && text16 < text16End) {
             firstUnichar = SkUTF16_NextUnichar(&text16);
         }
         baseGlyphCount = paint->getBaseGlyphCount(firstUnichar);
-        break;
-    }
-    default:
-        break;
     }
 
-    // We test the baseGlyphCount to see if the typeface supports the requested script
     if (baseGlyphCount != 0) {
-        typeface = typefaceForUnichar(paint, typeface, firstUnichar, mShaperItem.item.script);
+        typeface = typefaceForScript(paint, typeface, mShaperItem.item.script);
+        if (!typeface) {
+            typeface = mDefaultTypeface;
+            SkSafeRef(typeface);
+#if DEBUG_GLYPHS
+            ALOGD("Using Default Typeface");
+#endif
+        }
+    } else {
+        if (!typeface) {
+            typeface = mDefaultTypeface;
+#if DEBUG_GLYPHS
+            ALOGD("Using Default Typeface");
+#endif
+        }
+        SkSafeRef(typeface);
     }
 
-    if (!typeface) {
-        typeface = mDefaultTypeface;
-#if DEBUG_GLYPHS
-        ALOGD("Using Default Typeface");
-#endif
-    }
     mShapingPaint.setTypeface(typeface);
     mShaperItem.face = getCachedHBFace(typeface);
 
+    int textSize = paint->getTextSize();
+    float scaleX = paint->getTextScaleX();
+    mFontRec.x_ppem = floor(scaleX * textSize + 0.5);
+    mFontRec.y_ppem = textSize;
+    uint32_t unitsPerEm = SkFontHost::GetUnitsPerEm(typeface->uniqueID());
+    // x_ and y_scale are the conversion factors from font design space
+    // (unitsPerEm) to 1/64th of device pixels in 16.16 format.
+    const int kDevicePixelFraction = 64;
+    const int kMultiplyFor16Dot16 = 1 << 16;
+    float emScale = kDevicePixelFraction * kMultiplyFor16Dot16 / (float)unitsPerEm;
+    mFontRec.x_scale = emScale * scaleX * textSize;
+    mFontRec.y_scale = emScale * textSize;
+
 #if DEBUG_GLYPHS
     ALOGD("Run typeface = %p, uniqueID = %d, hb_face = %p",
             typeface, typeface->uniqueID(), mShaperItem.face);
 #endif
+    SkSafeUnref(typeface);
 
     // Shape
     assert(mShaperItem.item.length > 0); // Harfbuzz will overwrite other memory if length is 0.
-    ensureShaperItemGlyphArrays(mShaperItem.item.length * 3 / 2);
-    mShaperItem.num_glyphs = mShaperItemGlyphArraySize;
-    while (!HB_ShapeItem(&mShaperItem)) {
+    size_t size = mShaperItem.item.length * 3 / 2;
+    while (!doShaping(size)) {
         // We overflowed our glyph arrays. Resize and retry.
         // HB_ShapeItem fills in shaperItem.num_glyphs with the needed size.
-        ensureShaperItemGlyphArrays(mShaperItem.num_glyphs * 2);
-        mShaperItem.num_glyphs = mShaperItemGlyphArraySize;
+        size = mShaperItem.num_glyphs * 2;
     }
     return baseGlyphCount;
 }
 
-void TextLayoutShaper::ensureShaperItemGlyphArrays(size_t size) {
+bool TextLayoutShaper::doShaping(size_t size) {
     if (size > mShaperItemGlyphArraySize) {
         deleteShaperItemGlyphArrays();
         createShaperItemGlyphArrays(size);
     }
+    mShaperItem.num_glyphs = mShaperItemGlyphArraySize;
+    memset(mShaperItem.offsets, 0, mShaperItem.num_glyphs * sizeof(HB_FixedPoint));
+    return HB_ShapeItem(&mShaperItem);
 }
 
 void TextLayoutShaper::createShaperItemGlyphArrays(size_t size) {
@@ -957,24 +897,6 @@
     delete[] mShaperItem.log_clusters;
 }
 
-SkTypeface* TextLayoutShaper::getCachedTypeface(SkTypeface** typeface, const char path[]) {
-    if (!*typeface) {
-        *typeface = SkTypeface::CreateFromFile(path);
-        // CreateFromFile(path) can return NULL if the path is non existing
-        if (!*typeface) {
-#if DEBUG_GLYPHS
-        ALOGD("Font path '%s' is not valid, will use default font", path);
-#endif
-            return mDefaultTypeface;
-        }
-        (*typeface)->ref();
-#if DEBUG_GLYPHS
-        ALOGD("Created SkTypeface from file '%s' with uniqueID = %d", path, (*typeface)->uniqueID());
-#endif
-    }
-    return *typeface;
-}
-
 HB_Face TextLayoutShaper::getCachedHBFace(SkTypeface* typeface) {
     SkFontID fontId = typeface->uniqueID();
     ssize_t index = mCachedHBFaces.indexOfKey(fontId);
@@ -1035,8 +957,7 @@
 
 void TextLayoutEngine::purgeCaches() {
 #if USE_TEXT_LAYOUT_CACHE
-    mTextLayoutCache->clear();
-    mShaper->purgeCaches();
+    mTextLayoutCache->purgeCaches();
 #if DEBUG_GLYPHS
     ALOGD("Purged TextLayoutEngine caches");
 #endif
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
index cb15a2a..9994393 100644
--- a/core/jni/android/graphics/TextLayoutCache.h
+++ b/core/jni/android/graphics/TextLayoutCache.h
@@ -32,6 +32,7 @@
 #include <SkTemplates.h>
 #include <SkUtils.h>
 #include <SkAutoKern.h>
+#include <SkLanguage.h>
 
 #include <unicode/ubidi.h>
 #include <unicode/ushape.h>
@@ -56,7 +57,7 @@
 #define MB(s) s * 1024 * 1024
 
 // Define the default cache size in Mb
-#define DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB 0.250f
+#define DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB 0.500f
 
 // Define the interval in number of cache hits between two statistics dump
 #define DEFAULT_DUMP_STATS_CACHE_HIT_INTERVAL 100
@@ -76,20 +77,15 @@
     TextLayoutCacheKey(const TextLayoutCacheKey& other);
 
     /**
-     * We need to copy the text when we insert the key into the cache itself.
-     * We don't need to copy the text when we are only comparing keys.
-     */
-    void internalTextCopy();
-
-    /**
      * Get the size of the Cache key.
      */
     size_t getSize() const;
 
     static int compare(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs);
 
+    inline const UChar* getText() const { return textCopy.string(); }
+
 private:
-    const UChar* text; // if text is NULL, use textCopy
     String16 textCopy;
     size_t start;
     size_t count;
@@ -101,8 +97,8 @@
     SkScalar textScaleX;
     uint32_t flags;
     SkPaint::Hinting hinting;
-
-    inline const UChar* getText() const { return text ? text : textCopy.string(); }
+    SkPaint::FontVariant variant;
+    SkLanguage language;
 
 }; // TextLayoutCacheKey
 
@@ -129,6 +125,8 @@
     inline jfloat getTotalAdvance() const { return mTotalAdvance; }
     inline const jchar* getGlyphs() const { return mGlyphs.array(); }
     inline size_t getGlyphsCount() const { return mGlyphs.size(); }
+    inline const jfloat* getPos() const { return mPos.array(); }
+    inline size_t getPosCount() const { return mPos.size(); }
 
     /**
      * Advances vector
@@ -146,6 +144,11 @@
     Vector<jchar> mGlyphs;
 
     /**
+     * Pos vector (2 * i is x pos, 2 * i + 1 is y pos, same as drawPosText)
+     */
+    Vector<jfloat> mPos;
+
+    /**
      * Get the size of the Cache entry
      */
     size_t getSize() const;
@@ -188,17 +191,9 @@
     SkPaint mShapingPaint;
 
     /**
-     * Skia typefaces cached for shaping
+     * Skia default typeface to be returned if we cannot resolve script
      */
     SkTypeface* mDefaultTypeface;
-    SkTypeface* mArabicTypeface;
-    SkTypeface* mHebrewRegularTypeface;
-    SkTypeface* mHebrewBoldTypeface;
-    SkTypeface* mBengaliTypeface;
-    SkTypeface* mThaiTypeface;
-    SkTypeface* mDevanagariRegularTypeface;
-    SkTypeface* mTamilRegularTypeface;
-    SkTypeface* mTamilBoldTypeface;
 
     /**
      * Cache of Harfbuzz faces
@@ -223,27 +218,28 @@
     void init();
     void unrefTypefaces();
 
-    SkTypeface* typefaceForUnichar(const SkPaint* paint, SkTypeface* typeface,
-        SkUnichar unichar, HB_Script script);
+    SkTypeface* typefaceForScript(const SkPaint* paint, SkTypeface* typeface,
+        HB_Script script);
 
     size_t shapeFontRun(const SkPaint* paint, bool isRTL);
 
     void computeValues(const SkPaint* paint, const UChar* chars,
             size_t start, size_t count, size_t contextCount, int dirFlags,
             Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
-            Vector<jchar>* const outGlyphs);
+            Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos);
 
     void computeRunValues(const SkPaint* paint, const UChar* chars,
             size_t count, bool isRTL,
             Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
-            Vector<jchar>* const outGlyphs);
+            Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos);
 
-    SkTypeface* getCachedTypeface(SkTypeface** typeface, const char path[]);
+    SkTypeface* getCachedTypeface(SkTypeface** typeface, HB_Script script, SkTypeface::Style style);
     HB_Face getCachedHBFace(SkTypeface* typeface);
 
-    void ensureShaperItemGlyphArrays(size_t size);
+    bool doShaping(size_t size);
     void createShaperItemGlyphArrays(size_t size);
     void deleteShaperItemGlyphArrays();
+    bool isComplexScript(HB_Script script);
 
 }; // TextLayoutShaper
 
@@ -273,7 +269,7 @@
     /**
      * Clear the cache
      */
-    void clear();
+    void purgeCaches();
 
 private:
     TextLayoutShaper* mShaper;
@@ -313,6 +309,12 @@
     TextLayoutEngine();
     virtual ~TextLayoutEngine();
 
+    /**
+     * Note: this method currently does a defensive copy of the text argument, in case
+     * there is concurrent mutation of it. The contract may change, and may in the
+     * future require the caller to guarantee that the contents will not change during
+     * the call. Be careful of this when doing optimization.
+     **/
     sp<TextLayoutValue> getValue(const SkPaint* paint, const jchar* text, jint start,
             jint count, jint contextCount, jint dirFlags);
 
diff --git a/core/jni/android/graphics/YuvToJpegEncoder.cpp b/core/jni/android/graphics/YuvToJpegEncoder.cpp
index 8333e00..f386905 100644
--- a/core/jni/android/graphics/YuvToJpegEncoder.cpp
+++ b/core/jni/android/graphics/YuvToJpegEncoder.cpp
@@ -90,8 +90,9 @@
     // process 16 lines of Y and 8 lines of U/V each time.
     while (cinfo->next_scanline < cinfo->image_height) {
         //deitnerleave u and v
-        deinterleave(vuPlanar, uRows, vRows, cinfo->next_scanline, width);
+        deinterleave(vuPlanar, uRows, vRows, cinfo->next_scanline, width, height);
 
+        // Jpeg library ignores the rows whose indices are greater than height.
         for (int i = 0; i < 16; i++) {
             // y row
             y[i] = yPlanar + (cinfo->next_scanline + i) * fStrides[0];
@@ -112,8 +113,10 @@
 }
 
 void Yuv420SpToJpegEncoder::deinterleave(uint8_t* vuPlanar, uint8_t* uRows,
-        uint8_t* vRows, int rowIndex, int width) {
-    for (int row = 0; row < 8; ++row) {
+        uint8_t* vRows, int rowIndex, int width, int height) {
+    int numRows = (height - rowIndex) / 2;
+    if (numRows > 8) numRows = 8;
+    for (int row = 0; row < numRows; ++row) {
         int offset = ((rowIndex >> 1) + row) * fStrides[1];
         uint8_t* vu = vuPlanar + offset;
         for (int i = 0; i < (width >> 1); ++i) {
@@ -164,6 +167,7 @@
     while (cinfo->next_scanline < cinfo->image_height) {
         deinterleave(yuvOffset, yRows, uRows, vRows, cinfo->next_scanline, width, height);
 
+        // Jpeg library ignores the rows whose indices are greater than height.
         for (int i = 0; i < 16; i++) {
             // y row
             y[i] = yRows + i * width;
@@ -185,7 +189,9 @@
 
 void Yuv422IToJpegEncoder::deinterleave(uint8_t* yuv, uint8_t* yRows, uint8_t* uRows,
         uint8_t* vRows, int rowIndex, int width, int height) {
-    for (int row = 0; row < 16; ++row) {
+    int numRows = height - rowIndex;
+    if (numRows > 16) numRows = 16;
+    for (int row = 0; row < numRows; ++row) {
         uint8_t* yuvSeg = yuv + (rowIndex + row) * fStrides[0];
         for (int i = 0; i < (width >> 1); ++i) {
             int indexY = row * width + (i << 1);
diff --git a/core/jni/android/graphics/YuvToJpegEncoder.h b/core/jni/android/graphics/YuvToJpegEncoder.h
index 97106ce..0d418ed 100644
--- a/core/jni/android/graphics/YuvToJpegEncoder.h
+++ b/core/jni/android/graphics/YuvToJpegEncoder.h
@@ -55,7 +55,7 @@
      void deinterleaveYuv(uint8_t* yuv, int width, int height,
             uint8_t*& yPlanar, uint8_t*& uPlanar, uint8_t*& vPlanar);
      void deinterleave(uint8_t* vuPlanar, uint8_t* uRows, uint8_t* vRows,
-             int rowIndex, int width);
+             int rowIndex, int width, int height);
      void compress(jpeg_compress_struct* cinfo, uint8_t* yuv, int* offsets);
 };
 
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 074afa3..21162f4 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -436,7 +436,7 @@
     
     void setSurface(jobject _surface) {
         if (_surface != NULL) {
-            nativeWindow = android_Surface_getNativeWindow(env, _surface);
+            nativeWindow = android_view_Surface_getNativeWindow(env, _surface);
         } else {
             nativeWindow = NULL;
         }
diff --git a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp b/core/jni/android_bluetooth_BluetoothAudioGateway.cpp
deleted file mode 100644
index 294c626..0000000
--- a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "BluetoothAudioGateway.cpp"
-
-#include "android_bluetooth_common.h"
-#include "android_bluetooth_c.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "JNIHelp.h"
-#include "jni.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
-
-#define USE_ACCEPT_DIRECTLY (0)
-#define USE_SELECT (0) /* 1 for select(), 0 for poll(); used only when
-                          USE_ACCEPT_DIRECTLY == 0 */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/uio.h>
-#include <ctype.h>
-
-#if USE_SELECT
-#include <sys/select.h>
-#else
-#include <sys/poll.h>
-#endif
-
-#ifdef HAVE_BLUETOOTH
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/sco.h>
-#endif
-
-namespace android {
-
-#ifdef HAVE_BLUETOOTH
-static jfieldID field_mNativeData;
-    /* in */
-static jfieldID field_mHandsfreeAgRfcommChannel;
-static jfieldID field_mHeadsetAgRfcommChannel;
-    /* out */
-static jfieldID field_mTimeoutRemainingMs; /* out */
-
-static jfieldID field_mConnectingHeadsetAddress;
-static jfieldID field_mConnectingHeadsetRfcommChannel; /* -1 when not connected */
-static jfieldID field_mConnectingHeadsetSocketFd;
-
-static jfieldID field_mConnectingHandsfreeAddress;
-static jfieldID field_mConnectingHandsfreeRfcommChannel; /* -1 when not connected */
-static jfieldID field_mConnectingHandsfreeSocketFd;
-
-
-typedef struct {
-    int hcidev;
-    int hf_ag_rfcomm_channel;
-    int hs_ag_rfcomm_channel;
-    int hf_ag_rfcomm_sock;
-    int hs_ag_rfcomm_sock;
-} native_data_t;
-
-static inline native_data_t * get_native_data(JNIEnv *env, jobject object) {
-    return (native_data_t *)(env->GetIntField(object,
-                                                 field_mNativeData));
-}
-
-static int setup_listening_socket(int dev, int channel);
-#endif
-
-static void classInitNative(JNIEnv* env, jclass clazz) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-
-    /* in */
-    field_mNativeData = get_field(env, clazz, "mNativeData", "I");
-    field_mHandsfreeAgRfcommChannel =
-        get_field(env, clazz, "mHandsfreeAgRfcommChannel", "I");
-    field_mHeadsetAgRfcommChannel =
-        get_field(env, clazz, "mHeadsetAgRfcommChannel", "I");
-
-    /* out */
-    field_mConnectingHeadsetAddress =
-        get_field(env, clazz,
-                  "mConnectingHeadsetAddress", "Ljava/lang/String;");
-    field_mConnectingHeadsetRfcommChannel =
-        get_field(env, clazz, "mConnectingHeadsetRfcommChannel", "I");
-    field_mConnectingHeadsetSocketFd =
-        get_field(env, clazz, "mConnectingHeadsetSocketFd", "I");
-
-    field_mConnectingHandsfreeAddress =
-        get_field(env, clazz,
-                  "mConnectingHandsfreeAddress", "Ljava/lang/String;");
-    field_mConnectingHandsfreeRfcommChannel =
-        get_field(env, clazz, "mConnectingHandsfreeRfcommChannel", "I");
-    field_mConnectingHandsfreeSocketFd =
-        get_field(env, clazz, "mConnectingHandsfreeSocketFd", "I");
-
-    field_mTimeoutRemainingMs =
-        get_field(env, clazz, "mTimeoutRemainingMs", "I");
-#endif
-}
-
-static void initializeNativeDataNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t));
-    if (NULL == nat) {
-        ALOGE("%s: out of memory!", __FUNCTION__);
-        return;
-    }
-
-    nat->hcidev = BLUETOOTH_ADAPTER_HCI_NUM;
-
-    env->SetIntField(object, field_mNativeData, (jint)nat);
-    nat->hf_ag_rfcomm_channel =
-        env->GetIntField(object, field_mHandsfreeAgRfcommChannel);
-    nat->hs_ag_rfcomm_channel =
-        env->GetIntField(object, field_mHeadsetAgRfcommChannel);
-    ALOGV("HF RFCOMM channel = %d.", nat->hf_ag_rfcomm_channel);
-    ALOGV("HS RFCOMM channel = %d.", nat->hs_ag_rfcomm_channel);
-
-    /* Set the default values of these to -1. */
-    env->SetIntField(object, field_mConnectingHeadsetRfcommChannel, -1);
-    env->SetIntField(object, field_mConnectingHandsfreeRfcommChannel, -1);
-
-    nat->hf_ag_rfcomm_sock = -1;
-    nat->hs_ag_rfcomm_sock = -1;
-#endif
-}
-
-static void cleanupNativeDataNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        free(nat);
-    }
-#endif
-}
-
-#ifdef HAVE_BLUETOOTH
-
-#if USE_ACCEPT_DIRECTLY==0
-static int set_nb(int sk, bool nb) {
-    int flags = fcntl(sk, F_GETFL);
-    if (flags < 0) {
-        ALOGE("Can't get socket flags with fcntl(): %s (%d)",
-             strerror(errno), errno);
-        close(sk);
-        return -1;
-    }
-    flags &= ~O_NONBLOCK;
-    if (nb) flags |= O_NONBLOCK;
-    int status = fcntl(sk, F_SETFL, flags);
-    if (status < 0) {
-        ALOGE("Can't set socket to nonblocking mode with fcntl(): %s (%d)",
-             strerror(errno), errno);
-        close(sk);
-        return -1;
-    }
-    return 0;
-}
-#endif /*USE_ACCEPT_DIRECTLY==0*/
-
-static int do_accept(JNIEnv* env, jobject object, int ag_fd,
-                     jfieldID out_fd,
-                     jfieldID out_address,
-                     jfieldID out_channel) {
-
-#if USE_ACCEPT_DIRECTLY==0
-    if (set_nb(ag_fd, true) < 0)
-        return -1;
-#endif
-
-    struct sockaddr_rc raddr;
-    int alen = sizeof(raddr);
-    int nsk = TEMP_FAILURE_RETRY(accept(ag_fd, (struct sockaddr *) &raddr, &alen));
-    if (nsk < 0) {
-        ALOGE("Error on accept from socket fd %d: %s (%d).",
-             ag_fd,
-             strerror(errno),
-             errno);
-#if USE_ACCEPT_DIRECTLY==0
-        set_nb(ag_fd, false);
-#endif
-        return -1;
-    }
-
-    env->SetIntField(object, out_fd, nsk);
-    env->SetIntField(object, out_channel, raddr.rc_channel);
-
-    char addr[BTADDR_SIZE];
-    get_bdaddr_as_string(&raddr.rc_bdaddr, addr);
-    env->SetObjectField(object, out_address, env->NewStringUTF(addr));
-
-    ALOGI("Successful accept() on AG socket %d: new socket %d, address %s, RFCOMM channel %d",
-         ag_fd,
-         nsk,
-         addr,
-         raddr.rc_channel);
-#if USE_ACCEPT_DIRECTLY==0
-    set_nb(ag_fd, false);
-#endif
-    return 0;
-}
-
-#if USE_SELECT
-static inline int on_accept_set_fields(JNIEnv* env, jobject object,
-                                       fd_set *rset, int ag_fd,
-                                       jfieldID out_fd,
-                                       jfieldID out_address,
-                                       jfieldID out_channel) {
-
-    env->SetIntField(object, out_channel, -1);
-
-    if (ag_fd >= 0 && FD_ISSET(ag_fd, &rset)) {
-        return do_accept(env, object, ag_fd,
-                         out_fd, out_address, out_channel);
-    }
-    else {
-        ALOGI("fd = %d, FD_ISSET() = %d",
-             ag_fd,
-             FD_ISSET(ag_fd, &rset));
-        if (ag_fd >= 0 && !FD_ISSET(ag_fd, &rset)) {
-            ALOGE("WTF???");
-            return -1;
-        }
-    }
-
-    return 0;
-}
-#endif
-#endif /* HAVE_BLUETOOTH */
-
-static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object,
-                                              jint timeout_ms) {
-//    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-
-    env->SetIntField(object, field_mTimeoutRemainingMs, timeout_ms);
-
-    int n = 0;
-    native_data_t *nat = get_native_data(env, object);
-#if USE_ACCEPT_DIRECTLY
-    if (nat->hf_ag_rfcomm_channel > 0) {
-        ALOGI("Setting HF AG server socket to RFCOMM port %d!",
-             nat->hf_ag_rfcomm_channel);
-        struct timeval tv;
-        int len = sizeof(tv);
-        if (getsockopt(nat->hf_ag_rfcomm_channel,
-                       SOL_SOCKET, SO_RCVTIMEO, &tv, &len) < 0) {
-            ALOGE("getsockopt(%d, SOL_SOCKET, SO_RCVTIMEO): %s (%d)",
-                 nat->hf_ag_rfcomm_channel,
-                 strerror(errno),
-                 errno);
-            return JNI_FALSE;
-        }
-        ALOGI("Current HF AG server socket RCVTIMEO is (%d(s), %d(us))!",
-             (int)tv.tv_sec, (int)tv.tv_usec);
-        if (timeout_ms >= 0) {
-            tv.tv_sec = timeout_ms / 1000;
-            tv.tv_usec = 1000 * (timeout_ms % 1000);
-            if (setsockopt(nat->hf_ag_rfcomm_channel,
-                           SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
-                ALOGE("setsockopt(%d, SOL_SOCKET, SO_RCVTIMEO): %s (%d)",
-                     nat->hf_ag_rfcomm_channel,
-                     strerror(errno),
-                     errno);
-                return JNI_FALSE;
-            }
-            ALOGI("Changed HF AG server socket RCVTIMEO to (%d(s), %d(us))!",
-                 (int)tv.tv_sec, (int)tv.tv_usec);
-        }
-
-        if (!do_accept(env, object, nat->hf_ag_rfcomm_sock,
-                       field_mConnectingHandsfreeSocketFd,
-                       field_mConnectingHandsfreeAddress,
-                       field_mConnectingHandsfreeRfcommChannel))
-        {
-            env->SetIntField(object, field_mTimeoutRemainingMs, 0);
-            return JNI_TRUE;
-        }
-        return JNI_FALSE;
-    }
-#else
-#if USE_SELECT
-    fd_set rset;
-    FD_ZERO(&rset);
-    int cnt = 0;
-    if (nat->hf_ag_rfcomm_channel > 0) {
-        ALOGI("Setting HF AG server socket to RFCOMM port %d!",
-             nat->hf_ag_rfcomm_channel);
-        cnt++;
-        FD_SET(nat->hf_ag_rfcomm_sock, &rset);
-    }
-    if (nat->hs_ag_rfcomm_channel > 0) {
-        ALOGI("Setting HS AG server socket to RFCOMM port %d!",
-             nat->hs_ag_rfcomm_channel);
-        cnt++;
-        FD_SET(nat->hs_ag_rfcomm_sock, &rset);
-    }
-    if (cnt == 0) {
-        ALOGE("Neither HF nor HS listening sockets are open!");
-        return JNI_FALSE;
-    }
-
-    struct timeval to;
-    if (timeout_ms >= 0) {
-        to.tv_sec = timeout_ms / 1000;
-        to.tv_usec = 1000 * (timeout_ms % 1000);
-    }
-    n = TEMP_FAILURE_RETRY(select(
-                   MAX(nat->hf_ag_rfcomm_sock, nat->hs_ag_rfcomm_sock) + 1,
-                   &rset,
-                   NULL,
-                   NULL,
-                   (timeout_ms < 0 ? NULL : &to)));
-    if (timeout_ms > 0) {
-        jint remaining = to.tv_sec*1000 + to.tv_usec/1000;
-        ALOGI("Remaining time %ldms", (long)remaining);
-        env->SetIntField(object, field_mTimeoutRemainingMs,
-                         remaining);
-    }
-
-    ALOGI("listening select() returned %d", n);
-
-    if (n <= 0) {
-        if (n < 0)  {
-            ALOGE("listening select() on RFCOMM sockets: %s (%d)",
-                 strerror(errno),
-                 errno);
-        }
-        return JNI_FALSE;
-    }
-
-    n = on_accept_set_fields(env, object,
-                             &rset, nat->hf_ag_rfcomm_sock,
-                             field_mConnectingHandsfreeSocketFd,
-                             field_mConnectingHandsfreeAddress,
-                             field_mConnectingHandsfreeRfcommChannel);
-
-    n += on_accept_set_fields(env, object,
-                              &rset, nat->hs_ag_rfcomm_sock,
-                              field_mConnectingHeadsetSocketFd,
-                              field_mConnectingHeadsetAddress,
-                              field_mConnectingHeadsetRfcommChannel);
-
-    return !n ? JNI_TRUE : JNI_FALSE;
-#else
-    struct pollfd fds[2];
-    int cnt = 0;
-    if (nat->hf_ag_rfcomm_channel > 0) {
-//        ALOGI("Setting HF AG server socket %d to RFCOMM port %d!",
-//             nat->hf_ag_rfcomm_sock,
-//             nat->hf_ag_rfcomm_channel);
-        fds[cnt].fd = nat->hf_ag_rfcomm_sock;
-        fds[cnt].events = POLLIN | POLLPRI | POLLOUT | POLLERR;
-        cnt++;
-    }
-    if (nat->hs_ag_rfcomm_channel > 0) {
-//        ALOGI("Setting HS AG server socket %d to RFCOMM port %d!",
-//             nat->hs_ag_rfcomm_sock,
-//             nat->hs_ag_rfcomm_channel);
-        fds[cnt].fd = nat->hs_ag_rfcomm_sock;
-        fds[cnt].events = POLLIN | POLLPRI | POLLOUT | POLLERR;
-        cnt++;
-    }
-    if (cnt == 0) {
-        ALOGE("Neither HF nor HS listening sockets are open!");
-        return JNI_FALSE;
-    }
-    n = TEMP_FAILURE_RETRY(poll(fds, cnt, timeout_ms));
-    if (n <= 0) {
-        if (n < 0)  {
-            ALOGE("listening poll() on RFCOMM sockets: %s (%d)",
-                 strerror(errno),
-                 errno);
-        }
-        else {
-            env->SetIntField(object, field_mTimeoutRemainingMs, 0);
-//            ALOGI("listening poll() on RFCOMM socket timed out");
-        }
-        return JNI_FALSE;
-    }
-
-    //ALOGI("listening poll() on RFCOMM socket returned %d", n);
-    int err = 0;
-    for (cnt = 0; cnt < (int)(sizeof(fds)/sizeof(fds[0])); cnt++) {
-        //ALOGI("Poll on fd %d revent = %d.", fds[cnt].fd, fds[cnt].revents);
-        if (fds[cnt].fd == nat->hf_ag_rfcomm_sock) {
-            if (fds[cnt].revents & (POLLIN | POLLPRI | POLLOUT)) {
-                ALOGI("Accepting HF connection.\n");
-                err += do_accept(env, object, fds[cnt].fd,
-                               field_mConnectingHandsfreeSocketFd,
-                               field_mConnectingHandsfreeAddress,
-                               field_mConnectingHandsfreeRfcommChannel);
-                n--;
-            }
-        }
-        else if (fds[cnt].fd == nat->hs_ag_rfcomm_sock) {
-            if (fds[cnt].revents & (POLLIN | POLLPRI | POLLOUT)) {
-                ALOGI("Accepting HS connection.\n");
-                err += do_accept(env, object, fds[cnt].fd,
-                               field_mConnectingHeadsetSocketFd,
-                               field_mConnectingHeadsetAddress,
-                               field_mConnectingHeadsetRfcommChannel);
-                n--;
-            }
-        }
-    } /* for */
-
-    if (n != 0) {
-        ALOGI("Bogus poll(): %d fake pollfd entrie(s)!", n);
-        return JNI_FALSE;
-    }
-
-    return !err ? JNI_TRUE : JNI_FALSE;
-#endif /* USE_SELECT */
-#endif /* USE_ACCEPT_DIRECTLY */
-#else
-    return JNI_FALSE;
-#endif /* HAVE_BLUETOOTH */
-}
-
-static jboolean setUpListeningSocketsNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-
-    nat->hf_ag_rfcomm_sock =
-        setup_listening_socket(nat->hcidev, nat->hf_ag_rfcomm_channel);
-    if (nat->hf_ag_rfcomm_sock < 0)
-        return JNI_FALSE;
-
-    nat->hs_ag_rfcomm_sock =
-        setup_listening_socket(nat->hcidev, nat->hs_ag_rfcomm_channel);
-    if (nat->hs_ag_rfcomm_sock < 0) {
-        close(nat->hf_ag_rfcomm_sock);
-        nat->hf_ag_rfcomm_sock = -1;
-        return JNI_FALSE;
-    }
-
-    return JNI_TRUE;
-#else
-    return JNI_FALSE;
-#endif /* HAVE_BLUETOOTH */
-}
-
-#ifdef HAVE_BLUETOOTH
-static int setup_listening_socket(int dev, int channel) {
-    struct sockaddr_rc laddr;
-    int sk, lm;
-
-    sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
-    if (sk < 0) {
-        ALOGE("Can't create RFCOMM socket");
-        return -1;
-    }
-
-    if (debug_no_encrypt()) {
-        lm = RFCOMM_LM_AUTH;
-    } else {
-        lm = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT;
-    }
-
-    if (lm && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) {
-        ALOGE("Can't set RFCOMM link mode");
-        close(sk);
-        return -1;
-    }
-
-    laddr.rc_family = AF_BLUETOOTH;
-    bdaddr_t any = android_bluetooth_bdaddr_any();
-    memcpy(&laddr.rc_bdaddr, &any, sizeof(bdaddr_t));
-    laddr.rc_channel = channel;
-
-    if (bind(sk, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) {
-        ALOGE("Can't bind RFCOMM socket");
-        close(sk);
-        return -1;
-    }
-
-    listen(sk, 10);
-    return sk;
-}
-#endif /* HAVE_BLUETOOTH */
-
-/*
-    private native void tearDownListeningSocketsNative();
-*/
-static void tearDownListeningSocketsNative(JNIEnv *env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-
-    if (nat->hf_ag_rfcomm_sock > 0) {
-        if (close(nat->hf_ag_rfcomm_sock) < 0) {
-            ALOGE("Could not close HF server socket: %s (%d)\n",
-                 strerror(errno), errno);
-        }
-        nat->hf_ag_rfcomm_sock = -1;
-    }
-    if (nat->hs_ag_rfcomm_sock > 0) {
-        if (close(nat->hs_ag_rfcomm_sock) < 0) {
-            ALOGE("Could not close HS server socket: %s (%d)\n",
-                 strerror(errno), errno);
-        }
-        nat->hs_ag_rfcomm_sock = -1;
-    }
-#endif /* HAVE_BLUETOOTH */
-}
-
-static JNINativeMethod sMethods[] = {
-     /* name, signature, funcPtr */
-
-    {"classInitNative", "()V", (void*)classInitNative},
-    {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative},
-    {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative},
-
-    {"setUpListeningSocketsNative", "()Z", (void *)setUpListeningSocketsNative},
-    {"tearDownListeningSocketsNative", "()V", (void *)tearDownListeningSocketsNative},
-    {"waitForHandsfreeConnectNative", "(I)Z", (void *)waitForHandsfreeConnectNative},
-};
-
-int register_android_bluetooth_BluetoothAudioGateway(JNIEnv *env) {
-    return AndroidRuntime::registerNativeMethods(env,
-            "android/bluetooth/BluetoothAudioGateway", sMethods,
-            NELEM(sMethods));
-}
-
-} /* namespace android */
diff --git a/core/jni/android_bluetooth_BluetoothSocket.cpp b/core/jni/android_bluetooth_BluetoothSocket.cpp
deleted file mode 100644
index d9ff36a..0000000
--- a/core/jni/android_bluetooth_BluetoothSocket.cpp
+++ /dev/null
@@ -1,588 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#define LOG_TAG "BluetoothSocket.cpp"
-
-#include "android_bluetooth_common.h"
-#include "android_bluetooth_c.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "JNIHelp.h"
-#include "utils/Log.h"
-#include "cutils/abort_socket.h"
-
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-
-#ifdef HAVE_BLUETOOTH
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/l2cap.h>
-#include <bluetooth/sco.h>
-#endif
-
-#define TYPE_AS_STR(t) \
-    ((t) == TYPE_RFCOMM ? "RFCOMM" : ((t) == TYPE_SCO ? "SCO" : "L2CAP"))
-
-namespace android {
-
-static jfieldID  field_mAuth;     /* read-only */
-static jfieldID  field_mEncrypt;  /* read-only */
-static jfieldID  field_mType;     /* read-only */
-static jfieldID  field_mAddress;  /* read-only */
-static jfieldID  field_mPort;     /* read-only */
-static jfieldID  field_mSocketData;
-static jmethodID method_BluetoothSocket_ctor;
-static jclass    class_BluetoothSocket;
-
-/* Keep TYPE_RFCOMM etc in sync with BluetoothSocket.java */
-static const int TYPE_RFCOMM = 1;
-static const int TYPE_SCO = 2;
-static const int TYPE_L2CAP = 3;  // TODO: Test l2cap code paths
-
-static const int RFCOMM_SO_SNDBUF = 70 * 1024;  // 70 KB send buffer
-
-static void abortNative(JNIEnv *env, jobject obj);
-static void destroyNative(JNIEnv *env, jobject obj);
-
-static struct asocket *get_socketData(JNIEnv *env, jobject obj) {
-    struct asocket *s =
-            (struct asocket *) env->GetIntField(obj, field_mSocketData);
-    if (!s)
-        jniThrowException(env, "java/io/IOException", "null socketData");
-    return s;
-}
-
-static void initSocketFromFdNative(JNIEnv *env, jobject obj, jint fd) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-
-    struct asocket *s = asocket_init(fd);
-
-    if (!s) {
-        ALOGV("asocket_init() failed, throwing");
-        jniThrowIOException(env, errno);
-        return;
-    }
-
-    env->SetIntField(obj, field_mSocketData, (jint)s);
-
-    return;
-#endif
-    jniThrowIOException(env, ENOSYS);
-}
-
-static void initSocketNative(JNIEnv *env, jobject obj) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-
-    int fd;
-    int lm = 0;
-    int sndbuf;
-    jboolean auth;
-    jboolean encrypt;
-    jint type;
-
-    type = env->GetIntField(obj, field_mType);
-
-    switch (type) {
-    case TYPE_RFCOMM:
-        fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
-        break;
-    case TYPE_SCO:
-        fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
-        break;
-    case TYPE_L2CAP:
-        fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
-        break;
-    default:
-        jniThrowIOException(env, ENOSYS);
-        return;
-    }
-
-    if (fd < 0) {
-        ALOGV("socket() failed, throwing");
-        jniThrowIOException(env, errno);
-        return;
-    }
-
-    auth = env->GetBooleanField(obj, field_mAuth);
-    encrypt = env->GetBooleanField(obj, field_mEncrypt);
-
-    /* kernel does not yet support LM for SCO */
-    switch (type) {
-    case TYPE_RFCOMM:
-        lm |= auth ? RFCOMM_LM_AUTH : 0;
-        lm |= encrypt ? RFCOMM_LM_ENCRYPT : 0;
-        lm |= (auth && encrypt) ? RFCOMM_LM_SECURE : 0;
-        break;
-    case TYPE_L2CAP:
-        lm |= auth ? L2CAP_LM_AUTH : 0;
-        lm |= encrypt ? L2CAP_LM_ENCRYPT : 0;
-        lm |= (auth && encrypt) ? L2CAP_LM_SECURE : 0;
-        break;
-    }
-
-    if (lm) {
-        if (setsockopt(fd, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm))) {
-            ALOGV("setsockopt(RFCOMM_LM) failed, throwing");
-            jniThrowIOException(env, errno);
-            return;
-        }
-    }
-
-    if (type == TYPE_RFCOMM) {
-        sndbuf = RFCOMM_SO_SNDBUF;
-        if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf))) {
-            ALOGV("setsockopt(SO_SNDBUF) failed, throwing");
-            jniThrowIOException(env, errno);
-            return;
-        }
-    }
-
-    ALOGV("...fd %d created (%s, lm = %x)", fd, TYPE_AS_STR(type), lm);
-
-    initSocketFromFdNative(env, obj, fd);
-    return;
-#endif
-    jniThrowIOException(env, ENOSYS);
-}
-
-static void connectNative(JNIEnv *env, jobject obj) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-
-    int ret;
-    jint type;
-    const char *c_address;
-    jstring address;
-    bdaddr_t bdaddress;
-    socklen_t addr_sz;
-    struct sockaddr *addr;
-    struct asocket *s = get_socketData(env, obj);
-    int retry = 0;
-
-    if (!s)
-        return;
-
-    type = env->GetIntField(obj, field_mType);
-
-    /* parse address into bdaddress */
-    address = (jstring) env->GetObjectField(obj, field_mAddress);
-    c_address = env->GetStringUTFChars(address, NULL);
-    if (get_bdaddr(c_address, &bdaddress)) {
-        env->ReleaseStringUTFChars(address, c_address);
-        jniThrowIOException(env, EINVAL);
-        return;
-    }
-    env->ReleaseStringUTFChars(address, c_address);
-
-    switch (type) {
-    case TYPE_RFCOMM:
-        struct sockaddr_rc addr_rc;
-        addr = (struct sockaddr *)&addr_rc;
-        addr_sz = sizeof(addr_rc);
-
-        memset(addr, 0, addr_sz);
-        addr_rc.rc_family = AF_BLUETOOTH;
-        addr_rc.rc_channel = env->GetIntField(obj, field_mPort);
-        memcpy(&addr_rc.rc_bdaddr, &bdaddress, sizeof(bdaddr_t));
-
-        break;
-    case TYPE_SCO:
-        struct sockaddr_sco addr_sco;
-        addr = (struct sockaddr *)&addr_sco;
-        addr_sz = sizeof(addr_sco);
-
-        memset(addr, 0, addr_sz);
-        addr_sco.sco_family = AF_BLUETOOTH;
-        memcpy(&addr_sco.sco_bdaddr, &bdaddress, sizeof(bdaddr_t));
-
-        break;
-    case TYPE_L2CAP:
-        struct sockaddr_l2 addr_l2;
-        addr = (struct sockaddr *)&addr_l2;
-        addr_sz = sizeof(addr_l2);
-
-        memset(addr, 0, addr_sz);
-        addr_l2.l2_family = AF_BLUETOOTH;
-        addr_l2.l2_psm = env->GetIntField(obj, field_mPort);
-        memcpy(&addr_l2.l2_bdaddr, &bdaddress, sizeof(bdaddr_t));
-
-        break;
-    default:
-        jniThrowIOException(env, ENOSYS);
-        return;
-    }
-
-connect:
-    ret = asocket_connect(s, addr, addr_sz, -1);
-    ALOGV("...connect(%d, %s) = %d (errno %d)",
-            s->fd, TYPE_AS_STR(type), ret, errno);
-
-    if (ret && errno == EALREADY && retry < 2) {
-        /* workaround for bug 5082381 (EALREADY on ACL collision):
-         * retry the connect. Unfortunately we have to create a new fd.
-         * It's not ideal to switch the fd underneath the object, but
-         * is currently safe */
-        ALOGD("Hit bug 5082381 (EALREADY on ACL collision), trying workaround");
-        usleep(100000);
-        retry++;
-        abortNative(env, obj);
-        destroyNative(env, obj);
-        initSocketNative(env, obj);
-        if (env->ExceptionOccurred()) {
-            return;
-        }
-        goto connect;
-    }
-    if (!ret && retry > 0)
-        ALOGD("...workaround ok");
-
-    if (ret)
-        jniThrowIOException(env, errno);
-
-    return;
-#endif
-    jniThrowIOException(env, ENOSYS);
-}
-
-/* Returns errno instead of throwing, so java can check errno */
-static int bindListenNative(JNIEnv *env, jobject obj) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-
-    jint type;
-    socklen_t addr_sz;
-    struct sockaddr *addr;
-    bdaddr_t bdaddr = android_bluetooth_bdaddr_any();
-    struct asocket *s = get_socketData(env, obj);
-
-    if (!s)
-        return EINVAL;
-
-    type = env->GetIntField(obj, field_mType);
-
-    switch (type) {
-    case TYPE_RFCOMM:
-        struct sockaddr_rc addr_rc;
-        addr = (struct sockaddr *)&addr_rc;
-        addr_sz = sizeof(addr_rc);
-
-        memset(addr, 0, addr_sz);
-        addr_rc.rc_family = AF_BLUETOOTH;
-        addr_rc.rc_channel = env->GetIntField(obj, field_mPort);
-        memcpy(&addr_rc.rc_bdaddr, &bdaddr, sizeof(bdaddr_t));
-        break;
-    case TYPE_SCO:
-        struct sockaddr_sco addr_sco;
-        addr = (struct sockaddr *)&addr_sco;
-        addr_sz = sizeof(addr_sco);
-
-        memset(addr, 0, addr_sz);
-        addr_sco.sco_family = AF_BLUETOOTH;
-        memcpy(&addr_sco.sco_bdaddr, &bdaddr, sizeof(bdaddr_t));
-        break;
-    case TYPE_L2CAP:
-        struct sockaddr_l2 addr_l2;
-        addr = (struct sockaddr *)&addr_l2;
-        addr_sz = sizeof(addr_l2);
-
-        memset(addr, 0, addr_sz);
-        addr_l2.l2_family = AF_BLUETOOTH;
-        addr_l2.l2_psm = env->GetIntField(obj, field_mPort);
-        memcpy(&addr_l2.l2_bdaddr, &bdaddr, sizeof(bdaddr_t));
-        break;
-    default:
-        return ENOSYS;
-    }
-
-    if (bind(s->fd, addr, addr_sz)) {
-        ALOGV("...bind(%d) gave errno %d", s->fd, errno);
-        return errno;
-    }
-
-    if (listen(s->fd, 1)) {
-        ALOGV("...listen(%d) gave errno %d", s->fd, errno);
-        return errno;
-    }
-
-    ALOGV("...bindListenNative(%d) success", s->fd);
-
-    return 0;
-
-#endif
-    return ENOSYS;
-}
-
-static jobject acceptNative(JNIEnv *env, jobject obj, int timeout) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-
-    int fd;
-    jint type;
-    struct sockaddr *addr;
-    socklen_t addr_sz;
-    jstring addr_jstr;
-    char addr_cstr[BTADDR_SIZE];
-    bdaddr_t *bdaddr;
-    jboolean auth;
-    jboolean encrypt;
-
-    struct asocket *s = get_socketData(env, obj);
-
-    if (!s)
-        return NULL;
-
-    type = env->GetIntField(obj, field_mType);
-
-    switch (type) {
-    case TYPE_RFCOMM:
-        struct sockaddr_rc addr_rc;
-        addr = (struct sockaddr *)&addr_rc;
-        addr_sz = sizeof(addr_rc);
-        bdaddr = &addr_rc.rc_bdaddr;
-        memset(addr, 0, addr_sz);
-        break;
-    case TYPE_SCO:
-        struct sockaddr_sco addr_sco;
-        addr = (struct sockaddr *)&addr_sco;
-        addr_sz = sizeof(addr_sco);
-        bdaddr = &addr_sco.sco_bdaddr;
-        memset(addr, 0, addr_sz);
-        break;
-    case TYPE_L2CAP:
-        struct sockaddr_l2 addr_l2;
-        addr = (struct sockaddr *)&addr_l2;
-        addr_sz = sizeof(addr_l2);
-        bdaddr = &addr_l2.l2_bdaddr;
-        memset(addr, 0, addr_sz);
-        break;
-    default:
-        jniThrowIOException(env, ENOSYS);
-        return NULL;
-    }
-
-    fd = asocket_accept(s, addr, &addr_sz, timeout);
-
-    ALOGV("...accept(%d, %s) = %d (errno %d)",
-            s->fd, TYPE_AS_STR(type), fd, errno);
-
-    if (fd < 0) {
-        jniThrowIOException(env, errno);
-        return NULL;
-    }
-
-    /* Connected - return new BluetoothSocket */
-    auth = env->GetBooleanField(obj, field_mAuth);
-    encrypt = env->GetBooleanField(obj, field_mEncrypt);
-
-    get_bdaddr_as_string(bdaddr, addr_cstr);
-
-    addr_jstr = env->NewStringUTF(addr_cstr);
-    return env->NewObject(class_BluetoothSocket, method_BluetoothSocket_ctor,
-            type, fd, auth, encrypt, addr_jstr, -1);
-
-#endif
-    jniThrowIOException(env, ENOSYS);
-    return NULL;
-}
-
-static jint availableNative(JNIEnv *env, jobject obj) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-
-    int available;
-    struct asocket *s = get_socketData(env, obj);
-
-    if (!s)
-        return -1;
-
-    if (ioctl(s->fd, FIONREAD, &available) < 0) {
-        jniThrowIOException(env, errno);
-        return -1;
-    }
-
-    return available;
-
-#endif
-    jniThrowIOException(env, ENOSYS);
-    return -1;
-}
-
-static jint readNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset,
-        jint length) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-
-    int ret;
-    jbyte *b;
-    int sz;
-    struct asocket *s = get_socketData(env, obj);
-
-    if (!s)
-        return -1;
-    if (jb == NULL) {
-        jniThrowIOException(env, EINVAL);
-        return -1;
-    }
-    sz = env->GetArrayLength(jb);
-    if (offset < 0 || length < 0 || offset + length > sz) {
-        jniThrowIOException(env, EINVAL);
-        return -1;
-    }
-
-    b = env->GetByteArrayElements(jb, NULL);
-    if (b == NULL) {
-        jniThrowIOException(env, EINVAL);
-        return -1;
-    }
-
-    ret = asocket_read(s, &b[offset], length, -1);
-    if (ret < 0) {
-        jniThrowIOException(env, errno);
-        env->ReleaseByteArrayElements(jb, b, JNI_ABORT);
-        return -1;
-    }
-
-    env->ReleaseByteArrayElements(jb, b, 0);
-    return (jint)ret;
-
-#endif
-    jniThrowIOException(env, ENOSYS);
-    return -1;
-}
-
-static jint writeNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset,
-        jint length) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-
-    int ret, total;
-    jbyte *b;
-    int sz;
-    struct asocket *s = get_socketData(env, obj);
-
-    if (!s)
-        return -1;
-    if (jb == NULL) {
-        jniThrowIOException(env, EINVAL);
-        return -1;
-    }
-    sz = env->GetArrayLength(jb);
-    if (offset < 0 || length < 0 || offset + length > sz) {
-        jniThrowIOException(env, EINVAL);
-        return -1;
-    }
-
-    b = env->GetByteArrayElements(jb, NULL);
-    if (b == NULL) {
-        jniThrowIOException(env, EINVAL);
-        return -1;
-    }
-
-    total = 0;
-    while (length > 0) {
-        ret = asocket_write(s, &b[offset], length, -1);
-        if (ret < 0) {
-            jniThrowIOException(env, errno);
-            env->ReleaseByteArrayElements(jb, b, JNI_ABORT);
-            return -1;
-        }
-        offset += ret;
-        total += ret;
-        length -= ret;
-    }
-
-    env->ReleaseByteArrayElements(jb, b, JNI_ABORT);  // no need to commit
-    return (jint)total;
-
-#endif
-    jniThrowIOException(env, ENOSYS);
-    return -1;
-}
-
-static void abortNative(JNIEnv *env, jobject obj) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    struct asocket *s = get_socketData(env, obj);
-
-    if (!s)
-        return;
-
-    asocket_abort(s);
-
-    ALOGV("...asocket_abort(%d) complete", s->fd);
-    return;
-#endif
-    jniThrowIOException(env, ENOSYS);
-}
-
-static void destroyNative(JNIEnv *env, jobject obj) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    struct asocket *s = get_socketData(env, obj);
-    int fd = s->fd;
-
-    if (!s)
-        return;
-
-    asocket_destroy(s);
-
-    ALOGV("...asocket_destroy(%d) complete", fd);
-    return;
-#endif
-    jniThrowIOException(env, ENOSYS);
-}
-
-static void throwErrnoNative(JNIEnv *env, jobject obj, jint err) {
-    jniThrowIOException(env, err);
-}
-
-static JNINativeMethod sMethods[] = {
-    {"initSocketNative", "()V",  (void*) initSocketNative},
-    {"initSocketFromFdNative", "(I)V",  (void*) initSocketFromFdNative},
-    {"connectNative", "()V", (void *) connectNative},
-    {"bindListenNative", "()I", (void *) bindListenNative},
-    {"acceptNative", "(I)Landroid/bluetooth/BluetoothSocket;", (void *) acceptNative},
-    {"availableNative", "()I",    (void *) availableNative},
-    {"readNative", "([BII)I",    (void *) readNative},
-    {"writeNative", "([BII)I",    (void *) writeNative},
-    {"abortNative", "()V",    (void *) abortNative},
-    {"destroyNative", "()V",    (void *) destroyNative},
-    {"throwErrnoNative", "(I)V",    (void *) throwErrnoNative},
-};
-
-int register_android_bluetooth_BluetoothSocket(JNIEnv *env) {
-    jclass clazz = env->FindClass("android/bluetooth/BluetoothSocket");
-    if (clazz == NULL)
-        return -1;
-    class_BluetoothSocket = (jclass) env->NewGlobalRef(clazz);
-    field_mType = env->GetFieldID(clazz, "mType", "I");
-    field_mAddress = env->GetFieldID(clazz, "mAddress", "Ljava/lang/String;");
-    field_mPort = env->GetFieldID(clazz, "mPort", "I");
-    field_mAuth = env->GetFieldID(clazz, "mAuth", "Z");
-    field_mEncrypt = env->GetFieldID(clazz, "mEncrypt", "Z");
-    field_mSocketData = env->GetFieldID(clazz, "mSocketData", "I");
-    method_BluetoothSocket_ctor = env->GetMethodID(clazz, "<init>", "(IIZZLjava/lang/String;I)V");
-    return AndroidRuntime::registerNativeMethods(env,
-        "android/bluetooth/BluetoothSocket", sMethods, NELEM(sMethods));
-}
-
-} /* namespace android */
-
diff --git a/core/jni/android_bluetooth_HeadsetBase.cpp b/core/jni/android_bluetooth_HeadsetBase.cpp
deleted file mode 100644
index 34447ef..0000000
--- a/core/jni/android_bluetooth_HeadsetBase.cpp
+++ /dev/null
@@ -1,567 +0,0 @@
-/*
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "BT HSHFP"
-
-#include "android_bluetooth_common.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "JNIHelp.h"
-#include "jni.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <sys/poll.h>
-
-#ifdef HAVE_BLUETOOTH
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/sco.h>
-#endif
-
-namespace android {
-
-#ifdef HAVE_BLUETOOTH
-static jfieldID field_mNativeData;
-static jfieldID field_mAddress;
-static jfieldID field_mRfcommChannel;
-static jfieldID field_mTimeoutRemainingMs;
-
-typedef struct {
-    jstring address;
-    const char *c_address;
-    int rfcomm_channel;
-    int last_read_err;
-    int rfcomm_sock;
-    int rfcomm_connected; // -1 in progress, 0 not connected, 1 connected
-    int rfcomm_sock_flags;
-} native_data_t;
-
-static inline native_data_t * get_native_data(JNIEnv *env, jobject object) {
-    return (native_data_t *)(env->GetIntField(object, field_mNativeData));
-}
-
-static const char CRLF[] = "\xd\xa";
-static const int CRLF_LEN = 2;
-
-static inline int write_error_check(int fd, const char* line, int len) {
-    int ret;
-    errno = 0;
-    ret = write(fd, line, len);
-    if (ret < 0) {
-        ALOGE("%s: write() failed: %s (%d)", __FUNCTION__, strerror(errno),
-             errno);
-        return -1;
-    }
-    if (ret != len) {
-        ALOGE("%s: write() only wrote %d of %d bytes", __FUNCTION__, ret, len);
-        return -1;
-    }
-    return 0;
-}
-
-static int send_line(int fd, const char* line) {
-    int nw;
-    int len = strlen(line);
-    int llen = len + CRLF_LEN * 2 + 1;
-    char *buffer = (char *)calloc(llen, sizeof(char));
-
-    snprintf(buffer, llen, "%s%s%s", CRLF, line, CRLF);
-
-    if (write_error_check(fd, buffer, llen - 1)) {
-        free(buffer);
-        return -1;
-    }
-    free(buffer);
-    return 0;
-}
-
-static void mask_eighth_bit(char *line)
-{
-   for (;;line++) {
-     if (0 == *line) return;
-     *line &= 0x7F;
-   }
-}
-
-static const char* get_line(int fd, char *buf, int len, int timeout_ms,
-                            int *err) {
-    char *bufit=buf;
-    int fd_flags = fcntl(fd, F_GETFL, 0);
-    struct pollfd pfd;
-
-again:
-    *bufit = 0;
-    pfd.fd = fd;
-    pfd.events = POLLIN;
-    *err = errno = 0;
-    int ret = TEMP_FAILURE_RETRY(poll(&pfd, 1, timeout_ms));
-    if (ret < 0) {
-        ALOGE("poll() error\n");
-        *err = errno;
-        return NULL;
-    }
-    if (ret == 0) {
-        return NULL;
-    }
-
-    if (pfd.revents & (POLLHUP | POLLERR | POLLNVAL)) {
-        ALOGW("RFCOMM poll() returned  success (%d), "
-             "but with an unexpected revents bitmask: %#x\n", ret, pfd.revents);
-        errno = EIO;
-        *err = errno;
-        return NULL;
-    }
-
-    while ((int)(bufit - buf) < (len - 1))
-    {
-        errno = 0;
-        int rc = TEMP_FAILURE_RETRY(read(fd, bufit, 1));
-
-        if (!rc)
-            break;
-
-        if (rc < 0) {
-            if (errno == EBUSY) {
-                ALOGI("read() error %s (%d): repeating read()...",
-                     strerror(errno), errno);
-                goto again;
-            }
-            *err = errno;
-            ALOGE("read() error %s (%d)", strerror(errno), errno);
-            return NULL;
-        }
-
-
-        if (*bufit=='\xd') {
-            break;
-        }
-
-        if (*bufit=='\xa')
-            bufit = buf;
-        else
-            bufit++;
-    }
-
-    *bufit = 0;
-
-    // According to ITU V.250 section 5.1, IA5 7 bit chars are used, 
-    //   the eighth bit or higher bits are ignored if they exists
-    // We mask out only eighth bit, no higher bit, since we do char
-    // string here, not wide char.
-    // We added this processing due to 2 real world problems.
-    // 1 BMW 2005 E46 which sends binary junk
-    // 2 Audi 2010 A3, dial command use 0xAD (soft-hyphen) as number 
-    //   formater, which was rejected by the AT handler
-    mask_eighth_bit(buf);
-
-    return buf;
-}
-#endif
-
-static void classInitNative(JNIEnv* env, jclass clazz) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    field_mNativeData = get_field(env, clazz, "mNativeData", "I");
-    field_mAddress = get_field(env, clazz, "mAddress", "Ljava/lang/String;");
-    field_mTimeoutRemainingMs = get_field(env, clazz, "mTimeoutRemainingMs", "I");
-    field_mRfcommChannel = get_field(env, clazz, "mRfcommChannel", "I");
-#endif
-}
-
-static void initializeNativeDataNative(JNIEnv* env, jobject object,
-                                       jint socketFd) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t));
-    if (NULL == nat) {
-        ALOGE("%s: out of memory!", __FUNCTION__);
-        return;
-    }
-
-    env->SetIntField(object, field_mNativeData, (jint)nat);
-    nat->address =
-        (jstring)env->NewGlobalRef(env->GetObjectField(object,
-                                                       field_mAddress));
-    nat->c_address = env->GetStringUTFChars(nat->address, NULL);
-    nat->rfcomm_channel = env->GetIntField(object, field_mRfcommChannel);
-    nat->rfcomm_sock = socketFd;
-    nat->rfcomm_connected = socketFd >= 0;
-    if (nat->rfcomm_connected)
-        ALOGI("%s: ALREADY CONNECTED!", __FUNCTION__);
-#endif
-}
-
-static void cleanupNativeDataNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat =
-        (native_data_t *)env->GetIntField(object, field_mNativeData);
-    env->ReleaseStringUTFChars(nat->address, nat->c_address);
-    env->DeleteGlobalRef(nat->address);
-    if (nat)
-        free(nat);
-#endif
-}
-
-static jboolean connectNative(JNIEnv *env, jobject obj)
-{
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    int lm;
-    struct sockaddr_rc addr;
-    native_data_t *nat = get_native_data(env, obj);
-
-    nat->rfcomm_sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
-
-    if (nat->rfcomm_sock < 0) {
-        ALOGE("%s: Could not create RFCOMM socket: %s\n", __FUNCTION__,
-             strerror(errno));
-        return JNI_FALSE;
-    }
-
-    if (debug_no_encrypt()) {
-        lm = RFCOMM_LM_AUTH;
-    } else {
-        lm = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT;
-    }
-
-    if (lm && setsockopt(nat->rfcomm_sock, SOL_RFCOMM, RFCOMM_LM, &lm,
-                sizeof(lm)) < 0) {
-        ALOGE("%s: Can't set RFCOMM link mode", __FUNCTION__);
-        close(nat->rfcomm_sock);
-        return JNI_FALSE;
-    }
-
-    memset(&addr, 0, sizeof(struct sockaddr_rc));
-    get_bdaddr(nat->c_address, &addr.rc_bdaddr);
-    addr.rc_channel = nat->rfcomm_channel;
-    addr.rc_family = AF_BLUETOOTH;
-    nat->rfcomm_connected = 0;
-    while (nat->rfcomm_connected == 0) {
-        if (connect(nat->rfcomm_sock, (struct sockaddr *)&addr,
-                      sizeof(addr)) < 0) {
-            if (errno == EINTR) continue;
-            ALOGE("%s: connect() failed: %s\n", __FUNCTION__, strerror(errno));
-            close(nat->rfcomm_sock);
-            nat->rfcomm_sock = -1;
-            return JNI_FALSE;
-        } else {
-            nat->rfcomm_connected = 1;
-        }
-    }
-
-    return JNI_TRUE;
-#else
-    return JNI_FALSE;
-#endif
-}
-
-static jint connectAsyncNative(JNIEnv *env, jobject obj) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    struct sockaddr_rc addr;
-    native_data_t *nat = get_native_data(env, obj);
-
-    if (nat->rfcomm_connected) {
-        ALOGV("RFCOMM socket is already connected or connection is in progress.");
-        return 0;
-    }
-
-    if (nat->rfcomm_sock < 0) {
-        int lm;
-
-        nat->rfcomm_sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
-        if (nat->rfcomm_sock < 0) {
-            ALOGE("%s: Could not create RFCOMM socket: %s\n", __FUNCTION__,
-                 strerror(errno));
-            return -1;
-        }
-
-        if (debug_no_encrypt()) {
-            lm = RFCOMM_LM_AUTH;
-        } else {
-            lm = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT;
-        }
-
-        if (lm && setsockopt(nat->rfcomm_sock, SOL_RFCOMM, RFCOMM_LM, &lm,
-                    sizeof(lm)) < 0) {
-            ALOGE("%s: Can't set RFCOMM link mode", __FUNCTION__);
-            close(nat->rfcomm_sock);
-            return -1;
-        }
-        ALOGI("Created RFCOMM socket fd %d.", nat->rfcomm_sock);
-    }
-
-    memset(&addr, 0, sizeof(struct sockaddr_rc));
-    get_bdaddr(nat->c_address, &addr.rc_bdaddr);
-    addr.rc_channel = nat->rfcomm_channel;
-    addr.rc_family = AF_BLUETOOTH;
-    if (nat->rfcomm_sock_flags >= 0) {
-        nat->rfcomm_sock_flags = fcntl(nat->rfcomm_sock, F_GETFL, 0);
-        if (fcntl(nat->rfcomm_sock,
-                  F_SETFL, nat->rfcomm_sock_flags | O_NONBLOCK) >= 0) {
-            int rc;
-            nat->rfcomm_connected = 0;
-            errno = 0;
-            rc = connect(nat->rfcomm_sock,
-                        (struct sockaddr *)&addr,
-                         sizeof(addr));
-
-            if (rc >= 0) {
-                nat->rfcomm_connected = 1;
-                ALOGI("async connect successful");
-                return 0;
-            }
-            else if (rc < 0) {
-                if (errno == EINPROGRESS || errno == EAGAIN)
-                {
-                    ALOGI("async connect is in progress (%s)",
-                         strerror(errno));
-                    nat->rfcomm_connected = -1;
-                    return 0;
-                }
-                else
-                {
-                    ALOGE("async connect error: %s (%d)", strerror(errno), errno);
-                    close(nat->rfcomm_sock);
-                    nat->rfcomm_sock = -1;
-                    return -errno;
-                }
-            }
-        } // fcntl(nat->rfcomm_sock ...)
-    } // if (nat->rfcomm_sock_flags >= 0)
-#endif
-    return -1;
-}
-
-static jint waitForAsyncConnectNative(JNIEnv *env, jobject obj,
-                                           jint timeout_ms) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    struct sockaddr_rc addr;
-    native_data_t *nat = get_native_data(env, obj);
-
-    env->SetIntField(obj, field_mTimeoutRemainingMs, timeout_ms);
-
-    if (nat->rfcomm_connected > 0) {
-        ALOGI("RFCOMM is already connected!");
-        return 1;
-    }
-
-    if (nat->rfcomm_sock >= 0 && nat->rfcomm_connected == 0) {
-        ALOGI("Re-opening RFCOMM socket.");
-        close(nat->rfcomm_sock);
-        nat->rfcomm_sock = -1;
-    }
-    int ret = connectAsyncNative(env, obj);
-
-    if (ret < 0) {
-        ALOGI("Failed to re-open RFCOMM socket!");
-        return ret;
-    }
-
-    if (nat->rfcomm_sock >= 0) {
-        /* Do an asynchronous select() */
-        int n;
-        fd_set rset, wset;
-        struct timeval to;
-
-        FD_ZERO(&rset);
-        FD_ZERO(&wset);
-        FD_SET(nat->rfcomm_sock, &rset);
-        FD_SET(nat->rfcomm_sock, &wset);
-        if (timeout_ms >= 0) {
-            to.tv_sec = timeout_ms / 1000;
-            to.tv_usec = 1000 * (timeout_ms % 1000);
-        }
-        n = select(nat->rfcomm_sock + 1,
-                   &rset,
-                   &wset,
-                   NULL,
-                   (timeout_ms < 0 ? NULL : &to));
-
-        if (timeout_ms > 0) {
-            jint remaining = to.tv_sec*1000 + to.tv_usec/1000;
-            ALOGV("Remaining time %ldms", (long)remaining);
-            env->SetIntField(obj, field_mTimeoutRemainingMs,
-                             remaining);
-        }
-
-        if (n <= 0) {
-            if (n < 0)  {
-                ALOGE("select() on RFCOMM socket: %s (%d)",
-                     strerror(errno),
-                     errno);
-                return -errno;
-            }
-            return 0;
-        }
-        /* n must be equal to 1 and either rset or wset must have the
-           file descriptor set. */
-        ALOGV("select() returned %d.", n);
-        if (FD_ISSET(nat->rfcomm_sock, &rset) ||
-            FD_ISSET(nat->rfcomm_sock, &wset))
-        {
-            /* A trial async read() will tell us if everything is OK. */
-            {
-                char ch;
-                errno = 0;
-                int nr = TEMP_FAILURE_RETRY(read(nat->rfcomm_sock, &ch, 1));
-                /* It should be that nr != 1 because we just opened a socket
-                   and we haven't sent anything over it for the other side to
-                   respond... but one can't be paranoid enough.
-                */
-                if (nr >= 0 || errno != EAGAIN) {
-                    ALOGE("RFCOMM async connect() error: %s (%d), nr = %d\n",
-                         strerror(errno),
-                         errno,
-                         nr);
-                    /* Clear the rfcomm_connected flag to cause this function
-                       to re-create the socket and re-attempt the connect()
-                       the next time it is called.
-                    */
-                    nat->rfcomm_connected = 0;
-                    /* Restore the blocking properties of the socket. */
-                    fcntl(nat->rfcomm_sock, F_SETFL, nat->rfcomm_sock_flags);
-                    close(nat->rfcomm_sock);
-                    nat->rfcomm_sock = -1;
-                    return -errno;
-                }
-            }
-            /* Restore the blocking properties of the socket. */
-            fcntl(nat->rfcomm_sock, F_SETFL, nat->rfcomm_sock_flags);
-            ALOGI("Successful RFCOMM socket connect.");
-            nat->rfcomm_connected = 1;
-            return 1;
-        }
-    }
-    else ALOGE("RFCOMM socket file descriptor %d is bad!",
-              nat->rfcomm_sock);
-#endif
-    return -1;
-}
-
-static void disconnectNative(JNIEnv *env, jobject obj) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, obj);
-    if (nat->rfcomm_sock >= 0) {
-        close(nat->rfcomm_sock);
-        nat->rfcomm_sock = -1;
-        nat->rfcomm_connected = 0;
-    }
-#endif
-}
-
-static void pretty_log_urc(const char *urc) {
-    size_t i;
-    bool in_line_break = false;
-    char *buf = (char *)calloc(strlen(urc) + 1, sizeof(char));
-
-    strcpy(buf, urc);
-    for (i = 0; i < strlen(buf); i++) {
-        switch(buf[i]) {
-        case '\r':
-        case '\n':
-            in_line_break = true;
-            buf[i] = ' ';
-            break;
-        default:
-            if (in_line_break) {
-                in_line_break = false;
-                buf[i-1] = '\n';
-            }
-        }
-    }
-    IF_ALOGV() ALOG(LOG_VERBOSE, "Bluetooth AT sent", "%s", buf);
-
-    free(buf);
-}
-
-static jboolean sendURCNative(JNIEnv *env, jobject obj, jstring urc) {
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, obj);
-    if (nat->rfcomm_connected) {
-        const char *c_urc = env->GetStringUTFChars(urc, NULL);
-        jboolean ret = send_line(nat->rfcomm_sock, c_urc) == 0 ? JNI_TRUE : JNI_FALSE;
-        if (ret == JNI_TRUE) pretty_log_urc(c_urc);
-        env->ReleaseStringUTFChars(urc, c_urc);
-        return ret;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jstring readNative(JNIEnv *env, jobject obj, jint timeout_ms) {
-#ifdef HAVE_BLUETOOTH
-    {
-        native_data_t *nat = get_native_data(env, obj);
-        if (nat->rfcomm_connected) {
-            char buf[256];
-            const char *ret = get_line(nat->rfcomm_sock,
-                                       buf, sizeof(buf),
-                                       timeout_ms,
-                                       &nat->last_read_err);
-            return ret ? env->NewStringUTF(ret) : NULL;
-        }
-        return NULL;
-    }
-#else
-    return NULL;
-#endif
-}
-
-static jint getLastReadStatusNative(JNIEnv *env, jobject obj) {
-#ifdef HAVE_BLUETOOTH
-    {
-        native_data_t *nat = get_native_data(env, obj);
-        if (nat->rfcomm_connected)
-            return (jint)nat->last_read_err;
-        return 0;
-    }
-#else
-    return 0;
-#endif
-}
-
-static JNINativeMethod sMethods[] = {
-     /* name, signature, funcPtr */
-    {"classInitNative", "()V", (void*)classInitNative},
-    {"initializeNativeDataNative", "(I)V", (void *)initializeNativeDataNative},
-    {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative},
-    {"connectNative", "()Z", (void *)connectNative},
-    {"connectAsyncNative", "()I", (void *)connectAsyncNative},
-    {"waitForAsyncConnectNative", "(I)I", (void *)waitForAsyncConnectNative},
-    {"disconnectNative", "()V", (void *)disconnectNative},
-    {"sendURCNative", "(Ljava/lang/String;)Z", (void *)sendURCNative},
-    {"readNative", "(I)Ljava/lang/String;", (void *)readNative},
-    {"getLastReadStatusNative", "()I", (void *)getLastReadStatusNative},
-};
-
-int register_android_bluetooth_HeadsetBase(JNIEnv *env) {
-    return AndroidRuntime::registerNativeMethods(env,
-            "android/bluetooth/HeadsetBase", sMethods, NELEM(sMethods));
-}
-
-} /* namespace android */
diff --git a/core/jni/android_bluetooth_c.c b/core/jni/android_bluetooth_c.c
deleted file mode 100644
index b4c6727..0000000
--- a/core/jni/android_bluetooth_c.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-** Copyright 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.
-*/
-
-#ifdef HAVE_BLUETOOTH
-
-#include "android_bluetooth_c.h"
-
-/*
- * A C helper for creating a bdaddr_t object with the value BDADDR_ANY.
- * We have to do this in C because the macro BDADDR_ANY in bluetooth.h
- * is not valid C++ code.
- */
-bdaddr_t android_bluetooth_bdaddr_any(void)
-{
-  bdaddr_t any = *BDADDR_ANY;
-  return any;
-}
-#endif
diff --git a/core/jni/android_bluetooth_c.h b/core/jni/android_bluetooth_c.h
deleted file mode 100644
index e890244..0000000
--- a/core/jni/android_bluetooth_c.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-** Copyright 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_BLUETOOTH_C_H
-#define ANDROID_BLUETOOTH_C_H
-#ifdef HAVE_BLUETOOTH
-
-#include <bluetooth/bluetooth.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * A C helper for creating a bdaddr_t object with the value BDADDR_ANY.
- * We have to do this in C because the macro BDADDR_ANY in bluetooth.h
- * is not valid C++ code.
- */
-bdaddr_t android_bluetooth_bdaddr_any(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*HAVE_BLUETOOTH*/
-#endif /*ANDROID_BLUETOOTH_C_H*/
diff --git a/core/jni/android_bluetooth_common.cpp b/core/jni/android_bluetooth_common.cpp
deleted file mode 100644
index 5cdaa6c..0000000
--- a/core/jni/android_bluetooth_common.cpp
+++ /dev/null
@@ -1,867 +0,0 @@
-/*
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "bluetooth_common.cpp"
-
-#include "android_bluetooth_common.h"
-#include "JNIHelp.h"
-#include "jni.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <cutils/properties.h>
-
-#ifdef HAVE_BLUETOOTH
-#include <dbus/dbus.h>
-#endif
-
-namespace android {
-
-#ifdef HAVE_BLUETOOTH
-
-static Properties remote_device_properties[] = {
-    {"Address",  DBUS_TYPE_STRING},
-    {"Name", DBUS_TYPE_STRING},
-    {"Icon", DBUS_TYPE_STRING},
-    {"Class", DBUS_TYPE_UINT32},
-    {"UUIDs", DBUS_TYPE_ARRAY},
-    {"Services", DBUS_TYPE_ARRAY},
-    {"Paired", DBUS_TYPE_BOOLEAN},
-    {"Connected", DBUS_TYPE_BOOLEAN},
-    {"Trusted", DBUS_TYPE_BOOLEAN},
-    {"Blocked", DBUS_TYPE_BOOLEAN},
-    {"Alias", DBUS_TYPE_STRING},
-    {"Nodes", DBUS_TYPE_ARRAY},
-    {"Adapter", DBUS_TYPE_OBJECT_PATH},
-    {"LegacyPairing", DBUS_TYPE_BOOLEAN},
-    {"RSSI", DBUS_TYPE_INT16},
-    {"TX", DBUS_TYPE_UINT32},
-    {"Broadcaster", DBUS_TYPE_BOOLEAN}
-};
-
-static Properties adapter_properties[] = {
-    {"Address", DBUS_TYPE_STRING},
-    {"Name", DBUS_TYPE_STRING},
-    {"Class", DBUS_TYPE_UINT32},
-    {"Powered", DBUS_TYPE_BOOLEAN},
-    {"Discoverable", DBUS_TYPE_BOOLEAN},
-    {"DiscoverableTimeout", DBUS_TYPE_UINT32},
-    {"Pairable", DBUS_TYPE_BOOLEAN},
-    {"PairableTimeout", DBUS_TYPE_UINT32},
-    {"Discovering", DBUS_TYPE_BOOLEAN},
-    {"Devices", DBUS_TYPE_ARRAY},
-    {"UUIDs", DBUS_TYPE_ARRAY},
-};
-
-static Properties input_properties[] = {
-    {"Connected", DBUS_TYPE_BOOLEAN},
-};
-
-static Properties pan_properties[] = {
-    {"Connected", DBUS_TYPE_BOOLEAN},
-    {"Interface", DBUS_TYPE_STRING},
-    {"UUID", DBUS_TYPE_STRING},
-};
-
-static Properties health_device_properties[] = {
-    {"MainChannel", DBUS_TYPE_OBJECT_PATH},
-};
-
-static Properties health_channel_properties[] = {
-    {"Type", DBUS_TYPE_STRING},
-    {"Device", DBUS_TYPE_OBJECT_PATH},
-    {"Application", DBUS_TYPE_OBJECT_PATH},
-};
-
-typedef union {
-    char *str_val;
-    int int_val;
-    char **array_val;
-} property_value;
-
-jfieldID get_field(JNIEnv *env, jclass clazz, const char *member,
-                   const char *mtype) {
-    jfieldID field = env->GetFieldID(clazz, member, mtype);
-    if (field == NULL) {
-        ALOGE("Can't find member %s", member);
-    }
-    return field;
-}
-
-typedef struct {
-    void (*user_cb)(DBusMessage *, void *, void *);
-    void *user;
-    void *nat;
-    JNIEnv *env;
-} dbus_async_call_t;
-
-void dbus_func_args_async_callback(DBusPendingCall *call, void *data) {
-
-    dbus_async_call_t *req = (dbus_async_call_t *)data;
-    DBusMessage *msg;
-
-    /* This is guaranteed to be non-NULL, because this function is called only
-       when once the remote method invokation returns. */
-    msg = dbus_pending_call_steal_reply(call);
-
-    if (msg) {
-        if (req->user_cb) {
-            // The user may not deref the message object.
-            req->user_cb(msg, req->user, req->nat);
-        }
-        dbus_message_unref(msg);
-    }
-
-    //dbus_message_unref(req->method);
-    dbus_pending_call_cancel(call);
-    dbus_pending_call_unref(call);
-    free(req);
-}
-
-static dbus_bool_t dbus_func_args_async_valist(JNIEnv *env,
-                                        DBusConnection *conn,
-                                        int timeout_ms,
-                                        void (*user_cb)(DBusMessage *,
-                                                        void *,
-                                                        void*),
-                                        void *user,
-                                        void *nat,
-                                        const char *path,
-                                        const char *ifc,
-                                        const char *func,
-                                        int first_arg_type,
-                                        va_list args) {
-    DBusMessage *msg = NULL;
-    const char *name;
-    dbus_async_call_t *pending;
-    dbus_bool_t reply = FALSE;
-
-    /* Compose the command */
-    msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, path, ifc, func);
-
-    if (msg == NULL) {
-        ALOGE("Could not allocate D-Bus message object!");
-        goto done;
-    }
-
-    /* append arguments */
-    if (!dbus_message_append_args_valist(msg, first_arg_type, args)) {
-        ALOGE("Could not append argument to method call!");
-        goto done;
-    }
-
-    /* Make the call. */
-    pending = (dbus_async_call_t *)malloc(sizeof(dbus_async_call_t));
-    if (pending) {
-        DBusPendingCall *call;
-
-        pending->env = env;
-        pending->user_cb = user_cb;
-        pending->user = user;
-        pending->nat = nat;
-        //pending->method = msg;
-
-        reply = dbus_connection_send_with_reply(conn, msg,
-                                                &call,
-                                                timeout_ms);
-        if (reply == TRUE) {
-            dbus_pending_call_set_notify(call,
-                                         dbus_func_args_async_callback,
-                                         pending,
-                                         NULL);
-        }
-    }
-
-done:
-    if (msg) dbus_message_unref(msg);
-    return reply;
-}
-
-dbus_bool_t dbus_func_args_async(JNIEnv *env,
-                                 DBusConnection *conn,
-                                 int timeout_ms,
-                                 void (*reply)(DBusMessage *, void *, void*),
-                                 void *user,
-                                 void *nat,
-                                 const char *path,
-                                 const char *ifc,
-                                 const char *func,
-                                 int first_arg_type,
-                                 ...) {
-    dbus_bool_t ret;
-    va_list lst;
-    va_start(lst, first_arg_type);
-
-    ret = dbus_func_args_async_valist(env, conn,
-                                      timeout_ms,
-                                      reply, user, nat,
-                                      path, ifc, func,
-                                      first_arg_type, lst);
-    va_end(lst);
-    return ret;
-}
-
-// If err is NULL, then any errors will be ALOGE'd, and free'd and the reply
-// will be NULL.
-// If err is not NULL, then it is assumed that dbus_error_init was already
-// called, and error's will be returned to the caller without logging. The
-// return value is NULL iff an error was set. The client must free the error if
-// set.
-DBusMessage * dbus_func_args_timeout_valist(JNIEnv *env,
-                                            DBusConnection *conn,
-                                            int timeout_ms,
-                                            DBusError *err,
-                                            const char *path,
-                                            const char *ifc,
-                                            const char *func,
-                                            int first_arg_type,
-                                            va_list args) {
-
-    DBusMessage *msg = NULL, *reply = NULL;
-    const char *name;
-    bool return_error = (err != NULL);
-
-    if (!return_error) {
-        err = (DBusError*)malloc(sizeof(DBusError));
-        dbus_error_init(err);
-    }
-
-    /* Compose the command */
-    msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, path, ifc, func);
-
-    if (msg == NULL) {
-        ALOGE("Could not allocate D-Bus message object!");
-        goto done;
-    }
-
-    /* append arguments */
-    if (!dbus_message_append_args_valist(msg, first_arg_type, args)) {
-        ALOGE("Could not append argument to method call!");
-        goto done;
-    }
-
-    /* Make the call. */
-    reply = dbus_connection_send_with_reply_and_block(conn, msg, timeout_ms, err);
-    if (!return_error && dbus_error_is_set(err)) {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(err, msg);
-    }
-
-done:
-    if (!return_error) {
-        free(err);
-    }
-    if (msg) dbus_message_unref(msg);
-    return reply;
-}
-
-DBusMessage * dbus_func_args_timeout(JNIEnv *env,
-                                     DBusConnection *conn,
-                                     int timeout_ms,
-                                     const char *path,
-                                     const char *ifc,
-                                     const char *func,
-                                     int first_arg_type,
-                                     ...) {
-    DBusMessage *ret;
-    va_list lst;
-    va_start(lst, first_arg_type);
-    ret = dbus_func_args_timeout_valist(env, conn, timeout_ms, NULL,
-                                        path, ifc, func,
-                                        first_arg_type, lst);
-    va_end(lst);
-    return ret;
-}
-
-DBusMessage * dbus_func_args(JNIEnv *env,
-                             DBusConnection *conn,
-                             const char *path,
-                             const char *ifc,
-                             const char *func,
-                             int first_arg_type,
-                             ...) {
-    DBusMessage *ret;
-    va_list lst;
-    va_start(lst, first_arg_type);
-    ret = dbus_func_args_timeout_valist(env, conn, -1, NULL,
-                                        path, ifc, func,
-                                        first_arg_type, lst);
-    va_end(lst);
-    return ret;
-}
-
-DBusMessage * dbus_func_args_error(JNIEnv *env,
-                                   DBusConnection *conn,
-                                   DBusError *err,
-                                   const char *path,
-                                   const char *ifc,
-                                   const char *func,
-                                   int first_arg_type,
-                                   ...) {
-    DBusMessage *ret;
-    va_list lst;
-    va_start(lst, first_arg_type);
-    ret = dbus_func_args_timeout_valist(env, conn, -1, err,
-                                        path, ifc, func,
-                                        first_arg_type, lst);
-    va_end(lst);
-    return ret;
-}
-
-jint dbus_returns_unixfd(JNIEnv *env, DBusMessage *reply) {
-
-    DBusError err;
-    jint ret = -1;
-
-    dbus_error_init(&err);
-    if (!dbus_message_get_args(reply, &err,
-                               DBUS_TYPE_UNIX_FD, &ret,
-                               DBUS_TYPE_INVALID)) {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-    }
-    dbus_message_unref(reply);
-    return ret;
-}
-
-
-jint dbus_returns_int32(JNIEnv *env, DBusMessage *reply) {
-
-    DBusError err;
-    jint ret = -1;
-
-    dbus_error_init(&err);
-    if (!dbus_message_get_args(reply, &err,
-                               DBUS_TYPE_INT32, &ret,
-                               DBUS_TYPE_INVALID)) {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-    }
-    dbus_message_unref(reply);
-    return ret;
-}
-
-jint dbus_returns_uint32(JNIEnv *env, DBusMessage *reply) {
-
-    DBusError err;
-    jint ret = -1;
-
-    dbus_error_init(&err);
-    if (!dbus_message_get_args(reply, &err,
-                               DBUS_TYPE_UINT32, &ret,
-                               DBUS_TYPE_INVALID)) {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-    }
-    dbus_message_unref(reply);
-    return ret;
-}
-
-jstring dbus_returns_string(JNIEnv *env, DBusMessage *reply) {
-
-    DBusError err;
-    jstring ret = NULL;
-    const char *name;
-
-    dbus_error_init(&err);
-    if (dbus_message_get_args(reply, &err,
-                               DBUS_TYPE_STRING, &name,
-                               DBUS_TYPE_INVALID)) {
-        ret = env->NewStringUTF(name);
-    } else {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-    }
-    dbus_message_unref(reply);
-
-    return ret;
-}
-
-jboolean dbus_returns_boolean(JNIEnv *env, DBusMessage *reply) {
-    DBusError err;
-    jboolean ret = JNI_FALSE;
-    dbus_bool_t val = FALSE;
-
-    dbus_error_init(&err);
-
-    /* Check the return value. */
-    if (dbus_message_get_args(reply, &err,
-                               DBUS_TYPE_BOOLEAN, &val,
-                               DBUS_TYPE_INVALID)) {
-        ret = val == TRUE ? JNI_TRUE : JNI_FALSE;
-    } else {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-    }
-
-    dbus_message_unref(reply);
-    return ret;
-}
-
-static void set_object_array_element(JNIEnv *env, jobjectArray strArray,
-                                     const char *value, int index) {
-    jstring obj;
-    obj = env->NewStringUTF(value);
-    env->SetObjectArrayElement(strArray, index, obj);
-    env->DeleteLocalRef(obj);
-}
-
-jobjectArray dbus_returns_array_of_object_path(JNIEnv *env,
-                                               DBusMessage *reply) {
-
-    DBusError err;
-    char **list;
-    int i, len;
-    jobjectArray strArray = NULL;
-
-    dbus_error_init(&err);
-    if (dbus_message_get_args (reply,
-                               &err,
-                               DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH,
-                               &list, &len,
-                               DBUS_TYPE_INVALID)) {
-        jclass stringClass;
-        jstring classNameStr;
-
-        stringClass = env->FindClass("java/lang/String");
-        strArray = env->NewObjectArray(len, stringClass, NULL);
-
-        for (i = 0; i < len; i++)
-            set_object_array_element(env, strArray, list[i], i);
-    } else {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-    }
-
-    dbus_message_unref(reply);
-    return strArray;
-}
-
-jobjectArray dbus_returns_array_of_strings(JNIEnv *env, DBusMessage *reply) {
-
-    DBusError err;
-    char **list;
-    int i, len;
-    jobjectArray strArray = NULL;
-
-    dbus_error_init(&err);
-    if (dbus_message_get_args (reply,
-                               &err,
-                               DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
-                               &list, &len,
-                               DBUS_TYPE_INVALID)) {
-        jclass stringClass;
-        jstring classNameStr;
-
-        //ALOGV("%s: there are %d elements in string array!", __FUNCTION__, len);
-
-        stringClass = env->FindClass("java/lang/String");
-        strArray = env->NewObjectArray(len, stringClass, NULL);
-
-        for (i = 0; i < len; i++)
-            set_object_array_element(env, strArray, list[i], i);
-    } else {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-    }
-
-    dbus_message_unref(reply);
-    return strArray;
-}
-
-jbyteArray dbus_returns_array_of_bytes(JNIEnv *env, DBusMessage *reply) {
-
-    DBusError err;
-    int i, len;
-    jbyte *list;
-    jbyteArray byteArray = NULL;
-
-    dbus_error_init(&err);
-    if (dbus_message_get_args(reply, &err,
-                              DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &list, &len,
-                              DBUS_TYPE_INVALID)) {
-        //ALOGV("%s: there are %d elements in byte array!", __FUNCTION__, len);
-        byteArray = env->NewByteArray(len);
-        if (byteArray)
-            env->SetByteArrayRegion(byteArray, 0, len, list);
-
-    } else {
-        LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-    }
-
-    dbus_message_unref(reply);
-    return byteArray;
-}
-
-void append_variant(DBusMessageIter *iter, int type, void *val)
-{
-    DBusMessageIter value_iter;
-    char var_type[2] = { type, '\0'};
-    dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, var_type, &value_iter);
-    dbus_message_iter_append_basic(&value_iter, type, val);
-    dbus_message_iter_close_container(iter, &value_iter);
-}
-
-static void dict_append_entry(DBusMessageIter *dict,
-                        const char *key, int type, void *val)
-{
-        DBusMessageIter dict_entry;
-        dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
-                                                        NULL, &dict_entry);
-
-        dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &key);
-        append_variant(&dict_entry, type, val);
-        dbus_message_iter_close_container(dict, &dict_entry);
-}
-
-static void append_dict_valist(DBusMessageIter *iterator, const char *first_key,
-                                va_list var_args)
-{
-        DBusMessageIter dict;
-        int val_type;
-        const char *val_key;
-        void *val;
-
-        dbus_message_iter_open_container(iterator, DBUS_TYPE_ARRAY,
-                        DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
-                        DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
-                        DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
-        val_key = first_key;
-        while (val_key) {
-                val_type = va_arg(var_args, int);
-                val = va_arg(var_args, void *);
-                dict_append_entry(&dict, val_key, val_type, val);
-                val_key = va_arg(var_args, char *);
-        }
-
-        dbus_message_iter_close_container(iterator, &dict);
-}
-
-void append_dict_args(DBusMessage *reply, const char *first_key, ...)
-{
-        DBusMessageIter iter;
-        va_list var_args;
-
-        dbus_message_iter_init_append(reply, &iter);
-
-        va_start(var_args, first_key);
-        append_dict_valist(&iter, first_key, var_args);
-        va_end(var_args);
-}
-
-
-int get_property(DBusMessageIter iter, Properties *properties,
-                  int max_num_properties, int *prop_index, property_value *value, int *len) {
-    DBusMessageIter prop_val, array_val_iter;
-    char *property = NULL;
-    uint32_t array_type;
-    char *str_val;
-    int i, j, type, int_val;
-
-    if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
-        return -1;
-    dbus_message_iter_get_basic(&iter, &property);
-    if (!dbus_message_iter_next(&iter))
-        return -1;
-    if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
-        return -1;
-    for (i = 0; i <  max_num_properties; i++) {
-        if (!strncmp(property, properties[i].name, strlen(property)))
-            break;
-    }
-    *prop_index = i;
-    if (i == max_num_properties)
-        return -1;
-
-    dbus_message_iter_recurse(&iter, &prop_val);
-    type = properties[*prop_index].type;
-    if (dbus_message_iter_get_arg_type(&prop_val) != type) {
-        ALOGE("Property type mismatch in get_property: %d, expected:%d, index:%d",
-             dbus_message_iter_get_arg_type(&prop_val), type, *prop_index);
-        return -1;
-    }
-
-    switch(type) {
-    case DBUS_TYPE_STRING:
-    case DBUS_TYPE_OBJECT_PATH:
-        dbus_message_iter_get_basic(&prop_val, &value->str_val);
-        *len = 1;
-        break;
-    case DBUS_TYPE_UINT32:
-    case DBUS_TYPE_INT16:
-    case DBUS_TYPE_BOOLEAN:
-        dbus_message_iter_get_basic(&prop_val, &int_val);
-        value->int_val = int_val;
-        *len = 1;
-        break;
-    case DBUS_TYPE_ARRAY:
-        dbus_message_iter_recurse(&prop_val, &array_val_iter);
-        array_type = dbus_message_iter_get_arg_type(&array_val_iter);
-        *len = 0;
-        value->array_val = NULL;
-        if (array_type == DBUS_TYPE_OBJECT_PATH ||
-            array_type == DBUS_TYPE_STRING){
-            j = 0;
-            do {
-               j ++;
-            } while(dbus_message_iter_next(&array_val_iter));
-            dbus_message_iter_recurse(&prop_val, &array_val_iter);
-            // Allocate  an array of char *
-            *len = j;
-            char **tmp = (char **)malloc(sizeof(char *) * *len);
-            if (!tmp)
-                return -1;
-            j = 0;
-            do {
-               dbus_message_iter_get_basic(&array_val_iter, &tmp[j]);
-               j ++;
-            } while(dbus_message_iter_next(&array_val_iter));
-            value->array_val = tmp;
-        }
-        break;
-    default:
-        return -1;
-    }
-    return 0;
-}
-
-void create_prop_array(JNIEnv *env, jobjectArray strArray, Properties *property,
-                       property_value *value, int len, int *array_index ) {
-    char **prop_val = NULL;
-    char buf[32] = {'\0'}, buf1[32] = {'\0'};
-    int i;
-
-    char *name = property->name;
-    int prop_type = property->type;
-
-    set_object_array_element(env, strArray, name, *array_index);
-    *array_index += 1;
-
-    if (prop_type == DBUS_TYPE_UINT32 || prop_type == DBUS_TYPE_INT16) {
-        sprintf(buf, "%d", value->int_val);
-        set_object_array_element(env, strArray, buf, *array_index);
-        *array_index += 1;
-    } else if (prop_type == DBUS_TYPE_BOOLEAN) {
-        sprintf(buf, "%s", value->int_val ? "true" : "false");
-
-        set_object_array_element(env, strArray, buf, *array_index);
-        *array_index += 1;
-    } else if (prop_type == DBUS_TYPE_ARRAY) {
-        // Write the length first
-        sprintf(buf1, "%d", len);
-        set_object_array_element(env, strArray, buf1, *array_index);
-        *array_index += 1;
-
-        prop_val = value->array_val;
-        for (i = 0; i < len; i++) {
-            set_object_array_element(env, strArray, prop_val[i], *array_index);
-            *array_index += 1;
-        }
-    } else {
-        set_object_array_element(env, strArray, (const char *) value->str_val, *array_index);
-        *array_index += 1;
-    }
-}
-
-jobjectArray parse_properties(JNIEnv *env, DBusMessageIter *iter, Properties *properties,
-                              const int max_num_properties) {
-    DBusMessageIter dict_entry, dict;
-    jobjectArray strArray = NULL;
-    property_value value;
-    int i, size = 0,array_index = 0;
-    int len = 0, prop_type = DBUS_TYPE_INVALID, prop_index = -1, type;
-    struct {
-        property_value value;
-        int len;
-        bool used;
-    } values[max_num_properties];
-    int t, j;
-
-    jclass stringClass = env->FindClass("java/lang/String");
-    DBusError err;
-    dbus_error_init(&err);
-
-    for (i = 0; i < max_num_properties; i++) {
-        values[i].used = false;
-    }
-
-    if(dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
-        goto failure;
-    dbus_message_iter_recurse(iter, &dict);
-    do {
-        len = 0;
-        if (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_DICT_ENTRY)
-            goto failure;
-        dbus_message_iter_recurse(&dict, &dict_entry);
-
-        if (!get_property(dict_entry, properties, max_num_properties, &prop_index,
-                          &value, &len)) {
-            size += 2;
-            if (properties[prop_index].type == DBUS_TYPE_ARRAY)
-                size += len;
-            values[prop_index].value = value;
-            values[prop_index].len = len;
-            values[prop_index].used = true;
-        } else {
-            goto failure;
-        }
-    } while(dbus_message_iter_next(&dict));
-
-    strArray = env->NewObjectArray(size, stringClass, NULL);
-
-    for (i = 0; i < max_num_properties; i++) {
-        if (values[i].used) {
-            create_prop_array(env, strArray, &properties[i], &values[i].value, values[i].len,
-                              &array_index);
-
-            if (properties[i].type == DBUS_TYPE_ARRAY && values[i].used
-                   && values[i].value.array_val != NULL)
-                free(values[i].value.array_val);
-        }
-
-    }
-    return strArray;
-
-failure:
-    if (dbus_error_is_set(&err))
-        LOG_AND_FREE_DBUS_ERROR(&err);
-    for (i = 0; i < max_num_properties; i++)
-        if (properties[i].type == DBUS_TYPE_ARRAY && values[i].used == true
-                                        && values[i].value.array_val != NULL)
-            free(values[i].value.array_val);
-    return NULL;
-}
-
-jobjectArray parse_property_change(JNIEnv *env, DBusMessage *msg,
-                           Properties *properties, int max_num_properties) {
-    DBusMessageIter iter;
-    DBusError err;
-    jobjectArray strArray = NULL;
-    jclass stringClass= env->FindClass("java/lang/String");
-    int len = 0, prop_index = -1;
-    int array_index = 0, size = 0;
-    property_value value;
-
-    dbus_error_init(&err);
-    if (!dbus_message_iter_init(msg, &iter))
-        goto failure;
-
-    if (!get_property(iter, properties, max_num_properties,
-                      &prop_index, &value, &len)) {
-        size += 2;
-        if (properties[prop_index].type == DBUS_TYPE_ARRAY)
-            size += len;
-        strArray = env->NewObjectArray(size, stringClass, NULL);
-
-        create_prop_array(env, strArray, &properties[prop_index],
-                          &value, len, &array_index);
-
-        if (properties[prop_index].type == DBUS_TYPE_ARRAY && value.array_val != NULL)
-             free(value.array_val);
-
-        return strArray;
-    }
-failure:
-    LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-    return NULL;
-}
-
-jobjectArray parse_adapter_property_change(JNIEnv *env, DBusMessage *msg) {
-    return parse_property_change(env, msg, (Properties *) &adapter_properties,
-                    sizeof(adapter_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_remote_device_property_change(JNIEnv *env, DBusMessage *msg) {
-    return parse_property_change(env, msg, (Properties *) &remote_device_properties,
-                    sizeof(remote_device_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_input_property_change(JNIEnv *env, DBusMessage *msg) {
-    return parse_property_change(env, msg, (Properties *) &input_properties,
-                    sizeof(input_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_pan_property_change(JNIEnv *env, DBusMessage *msg) {
-    return parse_property_change(env, msg, (Properties *) &pan_properties,
-                    sizeof(pan_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_adapter_properties(JNIEnv *env, DBusMessageIter *iter) {
-    return parse_properties(env, iter, (Properties *) &adapter_properties,
-                            sizeof(adapter_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_remote_device_properties(JNIEnv *env, DBusMessageIter *iter) {
-    return parse_properties(env, iter, (Properties *) &remote_device_properties,
-                          sizeof(remote_device_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_input_properties(JNIEnv *env, DBusMessageIter *iter) {
-    return parse_properties(env, iter, (Properties *) &input_properties,
-                          sizeof(input_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_health_device_properties(JNIEnv *env, DBusMessageIter *iter) {
-    return parse_properties(env, iter, (Properties *) &health_device_properties,
-                          sizeof(health_device_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_health_device_property_change(JNIEnv *env, DBusMessage *msg) {
-    return parse_property_change(env, msg, (Properties *) &health_device_properties,
-                    sizeof(health_device_properties) / sizeof(Properties));
-}
-
-jobjectArray parse_health_channel_properties(JNIEnv *env, DBusMessageIter *iter) {
-    return parse_properties(env, iter, (Properties *) &health_channel_properties,
-                          sizeof(health_channel_properties) / sizeof(Properties));
-}
-
-int get_bdaddr(const char *str, bdaddr_t *ba) {
-    char *d = ((char *)ba) + 5, *endp;
-    int i;
-    for(i = 0; i < 6; i++) {
-        *d-- = strtol(str, &endp, 16);
-        if (*endp != ':' && i != 5) {
-            memset(ba, 0, sizeof(bdaddr_t));
-            return -1;
-        }
-        str = endp + 1;
-    }
-    return 0;
-}
-
-void get_bdaddr_as_string(const bdaddr_t *ba, char *str) {
-    const uint8_t *b = (const uint8_t *)ba;
-    sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
-            b[5], b[4], b[3], b[2], b[1], b[0]);
-}
-
-bool debug_no_encrypt() {
-    return false;
-#if 0
-    char value[PROPERTY_VALUE_MAX] = "";
-
-    property_get("debug.bt.no_encrypt", value, "");
-    if (!strncmp("true", value, PROPERTY_VALUE_MAX) ||
-        !strncmp("1", value, PROPERTY_VALUE_MAX)) {
-        ALOGD("mandatory bluetooth encryption disabled");
-        return true;
-    } else {
-        return false;
-    }
-#endif
-}
-#endif
-
-} /* namespace android */
diff --git a/core/jni/android_bluetooth_common.h b/core/jni/android_bluetooth_common.h
deleted file mode 100644
index daf4bb2..0000000
--- a/core/jni/android_bluetooth_common.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_BLUETOOTH_COMMON_H
-#define ANDROID_BLUETOOTH_COMMON_H
-
-// Set to 0 to enable verbose bluetooth logging
-#define LOG_NDEBUG 1
-
-#include "jni.h"
-#include "utils/Log.h"
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdint.h>
-#include <sys/poll.h>
-
-#ifdef HAVE_BLUETOOTH
-#include <dbus/dbus.h>
-#include <bluetooth/bluetooth.h>
-#endif
-
-namespace android {
-
-#ifdef HAVE_BLUETOOTH
-#define BLUEZ_DBUS_BASE_PATH      "/org/bluez"
-#define BLUEZ_DBUS_BASE_IFC       "org.bluez"
-#define BLUEZ_ERROR_IFC           "org.bluez.Error"
-
-// It would be nicer to retrieve this from bluez using GetDefaultAdapter,
-// but this is only possible when the adapter is up (and hcid is running).
-// It is much easier just to hardcode bluetooth adapter to hci0
-#define BLUETOOTH_ADAPTER_HCI_NUM 0
-#define BLUEZ_ADAPTER_OBJECT_NAME BLUEZ_DBUS_BASE_PATH "/hci0"
-
-#define BTADDR_SIZE 18   // size of BT address character array (including null)
-
-// size of the dbus event loops pollfd structure, hopefully never to be grown
-#define DEFAULT_INITIAL_POLLFD_COUNT 8
-
-jfieldID get_field(JNIEnv *env,
-                   jclass clazz,
-                   const char *member,
-                   const char *mtype);
-
-// ALOGE and free a D-Bus error
-// Using #define so that __FUNCTION__ resolves usefully
-#define LOG_AND_FREE_DBUS_ERROR_WITH_MSG(err, msg) \
-    {   ALOGE("%s: D-Bus error in %s: %s (%s)", __FUNCTION__, \
-        dbus_message_get_member((msg)), (err)->name, (err)->message); \
-         dbus_error_free((err)); }
-#define LOG_AND_FREE_DBUS_ERROR(err) \
-    {   ALOGE("%s: D-Bus error: %s (%s)", __FUNCTION__, \
-        (err)->name, (err)->message); \
-        dbus_error_free((err)); }
-
-struct event_loop_native_data_t {
-    DBusConnection *conn;
-    const char *adapter;
-
-    /* protects the thread */
-    pthread_mutex_t thread_mutex;
-    pthread_t thread;
-    /* our comms socket */
-    /* mem for the list of sockets to listen to */
-    struct pollfd *pollData;
-    int pollMemberCount;
-    int pollDataSize;
-    /* mem for matching set of dbus watch ptrs */
-    DBusWatch **watchData;
-    /* pair of sockets for event loop control, Reader and Writer */
-    int controlFdR;
-    int controlFdW;
-    /* our vm and env Version for future env generation */
-    JavaVM *vm;
-    int envVer;
-    /* reference to our java self */
-    jobject me;
-    /* flag to indicate if the event loop thread is running */
-    bool running;
-};
-
-struct _Properties {
-    char name[32];
-    int type;
-};
-typedef struct _Properties Properties;
-
-dbus_bool_t dbus_func_args_async(JNIEnv *env,
-                                 DBusConnection *conn,
-                                 int timeout_ms,
-                                 void (*reply)(DBusMessage *, void *, void *),
-                                 void *user,
-                                 void *nat,
-                                 const char *path,
-                                 const char *ifc,
-                                 const char *func,
-                                 int first_arg_type,
-                                 ...);
-
-DBusMessage * dbus_func_args(JNIEnv *env,
-                             DBusConnection *conn,
-                             const char *path,
-                             const char *ifc,
-                             const char *func,
-                             int first_arg_type,
-                             ...);
-
-DBusMessage * dbus_func_args_error(JNIEnv *env,
-                                   DBusConnection *conn,
-                                   DBusError *err,
-                                   const char *path,
-                                   const char *ifc,
-                                   const char *func,
-                                   int first_arg_type,
-                                   ...);
-
-DBusMessage * dbus_func_args_timeout(JNIEnv *env,
-                                     DBusConnection *conn,
-                                     int timeout_ms,
-                                     const char *path,
-                                     const char *ifc,
-                                     const char *func,
-                                     int first_arg_type,
-                                     ...);
-
-DBusMessage * dbus_func_args_timeout_valist(JNIEnv *env,
-                                            DBusConnection *conn,
-                                            int timeout_ms,
-                                            DBusError *err,
-                                            const char *path,
-                                            const char *ifc,
-                                            const char *func,
-                                            int first_arg_type,
-                                            va_list args);
-
-jint dbus_returns_int32(JNIEnv *env, DBusMessage *reply);
-jint dbus_returns_uint32(JNIEnv *env, DBusMessage *reply);
-jint dbus_returns_unixfd(JNIEnv *env, DBusMessage *reply);
-jstring dbus_returns_string(JNIEnv *env, DBusMessage *reply);
-jboolean dbus_returns_boolean(JNIEnv *env, DBusMessage *reply);
-jobjectArray dbus_returns_array_of_strings(JNIEnv *env, DBusMessage *reply);
-jobjectArray dbus_returns_array_of_object_path(JNIEnv *env, DBusMessage *reply);
-jbyteArray dbus_returns_array_of_bytes(JNIEnv *env, DBusMessage *reply);
-
-jobjectArray parse_properties(JNIEnv *env, DBusMessageIter *iter, Properties *properties,
-                              const int max_num_properties);
-jobjectArray parse_property_change(JNIEnv *env, DBusMessage *msg,
-                                   Properties *properties, int max_num_properties);
-jobjectArray parse_adapter_properties(JNIEnv *env, DBusMessageIter *iter);
-jobjectArray parse_remote_device_properties(JNIEnv *env, DBusMessageIter *iter);
-jobjectArray parse_remote_device_property_change(JNIEnv *env, DBusMessage *msg);
-jobjectArray parse_adapter_property_change(JNIEnv *env, DBusMessage *msg);
-jobjectArray parse_input_properties(JNIEnv *env, DBusMessageIter *iter);
-jobjectArray parse_health_device_properties(JNIEnv *env, DBusMessageIter *iter);
-jobjectArray parse_health_channel_properties(JNIEnv *env, DBusMessageIter *iter);
-jobjectArray parse_input_property_change(JNIEnv *env, DBusMessage *msg);
-jobjectArray parse_pan_property_change(JNIEnv *env, DBusMessage *msg);
-jobjectArray parse_health_device_property_change(JNIEnv *env, DBusMessage *msg);
-
-void append_dict_args(DBusMessage *reply, const char *first_key, ...);
-void append_variant(DBusMessageIter *iter, int type, void *val);
-int get_bdaddr(const char *str, bdaddr_t *ba);
-void get_bdaddr_as_string(const bdaddr_t *ba, char *str);
-
-bool debug_no_encrypt();
-
-
-// Result codes from Bluez DBus calls
-#define BOND_RESULT_ERROR                      -1
-#define BOND_RESULT_SUCCESS                     0
-#define BOND_RESULT_AUTH_FAILED                 1
-#define BOND_RESULT_AUTH_REJECTED               2
-#define BOND_RESULT_AUTH_CANCELED               3
-#define BOND_RESULT_REMOTE_DEVICE_DOWN          4
-#define BOND_RESULT_DISCOVERY_IN_PROGRESS       5
-#define BOND_RESULT_AUTH_TIMEOUT                6
-#define BOND_RESULT_REPEATED_ATTEMPTS           7
-
-#define PAN_DISCONNECT_FAILED_NOT_CONNECTED  1000
-#define PAN_CONNECT_FAILED_ALREADY_CONNECTED 1001
-#define PAN_CONNECT_FAILED_ATTEMPT_FAILED    1002
-#define PAN_OPERATION_GENERIC_FAILURE        1003
-#define PAN_OPERATION_SUCCESS                1004
-
-#define INPUT_DISCONNECT_FAILED_NOT_CONNECTED  5000
-#define INPUT_CONNECT_FAILED_ALREADY_CONNECTED 5001
-#define INPUT_CONNECT_FAILED_ATTEMPT_FAILED    5002
-#define INPUT_OPERATION_GENERIC_FAILURE        5003
-#define INPUT_OPERATION_SUCCESS                5004
-
-#define HEALTH_OPERATION_SUCCESS               6000
-#define HEALTH_OPERATION_ERROR                 6001
-#define HEALTH_OPERATION_INVALID_ARGS          6002
-#define HEALTH_OPERATION_GENERIC_FAILURE       6003
-#define HEALTH_OPERATION_NOT_FOUND             6004
-#define HEALTH_OPERATION_NOT_ALLOWED           6005
-
-#endif
-} /* namespace android */
-
-#endif/*ANDROID_BLUETOOTH_COMMON_H*/
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 6cd8955..67d831c 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -23,6 +23,7 @@
 #include "JNIHelp.h"
 #include "android_runtime/AndroidRuntime.h"
 
+#include <cutils/properties.h>
 #include <utils/Vector.h>
 
 #include <gui/SurfaceTexture.h>
@@ -38,6 +39,7 @@
     jfieldID    surfaceTexture;
     jfieldID    facing;
     jfieldID    orientation;
+    jfieldID    canDisableShutterSound;
     jfieldID    face_rect;
     jfieldID    face_score;
     jfieldID    rect_left;
@@ -453,6 +455,12 @@
     }
     env->SetIntField(info_obj, fields.facing, cameraInfo.facing);
     env->SetIntField(info_obj, fields.orientation, cameraInfo.orientation);
+
+    char value[PROPERTY_VALUE_MAX];
+    property_get("ro.camera.sound.forced", value, "0");
+    jboolean canDisableShutterSound = (strncmp(value, "0", 2) == 0);
+    env->SetBooleanField(info_obj, fields.canDisableShutterSound,
+            canDisableShutterSound);
 }
 
 // connect to camera service
@@ -781,6 +789,25 @@
     }
 }
 
+static jboolean android_hardware_Camera_enableShutterSound(JNIEnv *env, jobject thiz,
+        jboolean enabled)
+{
+    ALOGV("enableShutterSound");
+    sp<Camera> camera = get_native_camera(env, thiz, NULL);
+    if (camera == 0) return JNI_FALSE;
+
+    int32_t value = (enabled == JNI_TRUE) ? 1 : 0;
+    status_t rc = camera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, value, 0);
+    if (rc == NO_ERROR) {
+        return JNI_TRUE;
+    } else if (rc == PERMISSION_DENIED) {
+        return JNI_FALSE;
+    } else {
+        jniThrowRuntimeException(env, "enable shutter sound failed");
+        return JNI_FALSE;
+    }
+}
+
 static void android_hardware_Camera_startFaceDetection(JNIEnv *env, jobject thiz,
         jint type)
 {
@@ -827,7 +854,7 @@
   { "getNumberOfCameras",
     "()I",
     (void *)android_hardware_Camera_getNumberOfCameras },
-  { "getCameraInfo",
+  { "_getCameraInfo",
     "(ILandroid/hardware/Camera$CameraInfo;)V",
     (void*)android_hardware_Camera_getCameraInfo },
   { "native_setup",
@@ -890,6 +917,9 @@
   { "setDisplayOrientation",
     "(I)V",
     (void *)android_hardware_Camera_setDisplayOrientation },
+  { "_enableShutterSound",
+    "(Z)Z",
+    (void *)android_hardware_Camera_enableShutterSound },
   { "_startFaceDetection",
     "(I)V",
     (void *)android_hardware_Camera_startFaceDetection },
@@ -940,6 +970,8 @@
           ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "I", &fields.surfaceTexture },
         { "android/hardware/Camera$CameraInfo", "facing",   "I", &fields.facing },
         { "android/hardware/Camera$CameraInfo", "orientation",   "I", &fields.orientation },
+        { "android/hardware/Camera$CameraInfo", "canDisableShutterSound",   "Z",
+          &fields.canDisableShutterSound },
         { "android/hardware/Camera$Face", "rect", "Landroid/graphics/Rect;", &fields.face_rect },
         { "android/hardware/Camera$Face", "score", "I", &fields.face_score },
         { "android/graphics/Rect", "left", "I", &fields.rect_left },
diff --git a/core/jni/android_hardware_UsbRequest.cpp b/core/jni/android_hardware_UsbRequest.cpp
index 1398968..32d5135 100644
--- a/core/jni/android_hardware_UsbRequest.cpp
+++ b/core/jni/android_hardware_UsbRequest.cpp
@@ -90,6 +90,7 @@
         request->buffer = malloc(length);
         if (!request->buffer)
             return false;
+        memset(request->buffer, 0, length);
         if (out) {
             // copy data from Java buffer to native buffer
             env->GetByteArrayRegion(buffer, 0, length, (jbyte *)request->buffer);
@@ -113,14 +114,14 @@
     }
 }
 
-static void
+static int
 android_hardware_UsbRequest_dequeue_array(JNIEnv *env, jobject thiz,
         jbyteArray buffer, jint length, jboolean out)
 {
     struct usb_request* request = get_request_from_object(env, thiz);
     if (!request) {
         ALOGE("request is closed in native_dequeue");
-        return;
+        return -1;
     }
 
     if (buffer && length && request->buffer && !out) {
@@ -129,7 +130,7 @@
     }
     free(request->buffer);
     env->DeleteGlobalRef((jobject)request->client_data);
-
+    return request->actual_length;
 }
 
 static jboolean
@@ -163,16 +164,17 @@
     }
 }
 
-static void
+static int
 android_hardware_UsbRequest_dequeue_direct(JNIEnv *env, jobject thiz)
 {
     struct usb_request* request = get_request_from_object(env, thiz);
     if (!request) {
         ALOGE("request is closed in native_dequeue");
-        return;
+        return -1;
     }
     // all we need to do is delete our global ref
     env->DeleteGlobalRef((jobject)request->client_data);
+    return request->actual_length;
 }
 
 static jboolean
@@ -191,10 +193,10 @@
                                             (void *)android_hardware_UsbRequest_init},
     {"native_close",            "()V",      (void *)android_hardware_UsbRequest_close},
     {"native_queue_array",      "([BIZ)Z",  (void *)android_hardware_UsbRequest_queue_array},
-    {"native_dequeue_array",    "([BIZ)V",  (void *)android_hardware_UsbRequest_dequeue_array},
+    {"native_dequeue_array",    "([BIZ)I",  (void *)android_hardware_UsbRequest_dequeue_array},
     {"native_queue_direct",     "(Ljava/nio/ByteBuffer;IZ)Z",
                                             (void *)android_hardware_UsbRequest_queue_direct},
-    {"native_dequeue_direct",   "()V",      (void *)android_hardware_UsbRequest_dequeue_direct},
+    {"native_dequeue_direct",   "()I",      (void *)android_hardware_UsbRequest_dequeue_direct},
     {"native_cancel",           "()Z",      (void *)android_hardware_UsbRequest_cancel},
 };
 
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 0f04e6f..c76cb64 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -242,7 +242,6 @@
         format,        // word length, PCM
         channels,
         frameCount,
-        (AudioRecord::record_flags) 0,  // flags
         recorderCallback,// callback_t
         lpCallbackData,// void* user
         0,             // notificationFrames,
@@ -517,7 +516,7 @@
             sampleRateInHertz,
             (audioFormat == javaAudioRecordFields.PCM16 ?
                 AUDIO_FORMAT_PCM_16_BIT : AUDIO_FORMAT_PCM_8_BIT),
-            nbChannels);
+            audio_channel_in_mask_from_count(nbChannels));
 
     if (result == BAD_VALUE) {
         return 0;
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index f522a9a..631cdae 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -75,6 +75,14 @@
     return state;
 }
 
+static jboolean
+android_media_AudioSystem_isSourceActive(JNIEnv *env, jobject thiz, jint source)
+{
+    bool state = false;
+    AudioSystem::isSourceActive((audio_source_t) source, &state);
+    return state;
+}
+
 static int
 android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
 {
@@ -242,6 +250,18 @@
     return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream));
 }
 
+static jint
+android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
+{
+    return (jint) AudioSystem::getPrimaryOutputSamplingRate();
+}
+
+static jint
+android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz)
+{
+    return (jint) AudioSystem::getPrimaryOutputFrameCount();
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
@@ -249,7 +269,8 @@
     {"getParameters",        "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
     {"muteMicrophone",      "(Z)I",     (void *)android_media_AudioSystem_muteMicrophone},
     {"isMicrophoneMuted",   "()Z",      (void *)android_media_AudioSystem_isMicrophoneMuted},
-    {"isStreamActive",      "(II)Z",     (void *)android_media_AudioSystem_isStreamActive},
+    {"isStreamActive",      "(II)Z",    (void *)android_media_AudioSystem_isStreamActive},
+    {"isSourceActive",      "(I)Z",     (void *)android_media_AudioSystem_isSourceActive},
     {"setDeviceConnectionState", "(IILjava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
     {"getDeviceConnectionState", "(ILjava/lang/String;)I",  (void *)android_media_AudioSystem_getDeviceConnectionState},
     {"setPhoneState",       "(I)I",     (void *)android_media_AudioSystem_setPhoneState},
@@ -263,6 +284,8 @@
     {"setMasterMute",       "(Z)I",     (void *)android_media_AudioSystem_setMasterMute},
     {"getMasterMute",       "()Z",      (void *)android_media_AudioSystem_getMasterMute},
     {"getDevicesForStream", "(I)I",     (void *)android_media_AudioSystem_getDevicesForStream},
+    {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
+    {"getPrimaryOutputFrameCount",   "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
 };
 
 int register_android_media_AudioSystem(JNIEnv *env)
diff --git a/core/jni/android_media_RemoteDisplay.cpp b/core/jni/android_media_RemoteDisplay.cpp
new file mode 100644
index 0000000..5d24f61
--- /dev/null
+++ b/core/jni/android_media_RemoteDisplay.cpp
@@ -0,0 +1,182 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "RemoteDisplay"
+
+#include "jni.h"
+#include "JNIHelp.h"
+
+#include "android_os_Parcel.h"
+#include "android_util_Binder.h"
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_view_Surface.h>
+
+#include <binder/IServiceManager.h>
+
+#include <gui/ISurfaceTexture.h>
+
+#include <media/IMediaPlayerService.h>
+#include <media/IRemoteDisplay.h>
+#include <media/IRemoteDisplayClient.h>
+
+#include <utils/Log.h>
+
+#include <ScopedUtfChars.h>
+
+namespace android {
+
+static struct {
+    jmethodID notifyDisplayConnected;
+    jmethodID notifyDisplayDisconnected;
+    jmethodID notifyDisplayError;
+} gRemoteDisplayClassInfo;
+
+// ----------------------------------------------------------------------------
+
+class NativeRemoteDisplayClient : public BnRemoteDisplayClient {
+public:
+    NativeRemoteDisplayClient(JNIEnv* env, jobject remoteDisplayObj) :
+            mRemoteDisplayObjGlobal(env->NewGlobalRef(remoteDisplayObj)) {
+    }
+
+protected:
+    ~NativeRemoteDisplayClient() {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+        env->DeleteGlobalRef(mRemoteDisplayObjGlobal);
+    }
+
+public:
+    virtual void onDisplayConnected(const sp<ISurfaceTexture>& surfaceTexture,
+            uint32_t width, uint32_t height, uint32_t flags) {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+        jobject surfaceObj = android_view_Surface_createFromISurfaceTexture(env, surfaceTexture);
+        if (surfaceObj == NULL) {
+            ALOGE("Could not create Surface from surface texture %p provided by media server.",
+                    surfaceTexture.get());
+            return;
+        }
+
+        env->CallVoidMethod(mRemoteDisplayObjGlobal,
+                gRemoteDisplayClassInfo.notifyDisplayConnected,
+                surfaceObj, width, height, flags);
+        env->DeleteLocalRef(surfaceObj);
+        checkAndClearExceptionFromCallback(env, "notifyDisplayConnected");
+    }
+
+    virtual void onDisplayDisconnected() {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+        env->CallVoidMethod(mRemoteDisplayObjGlobal,
+                gRemoteDisplayClassInfo.notifyDisplayDisconnected);
+        checkAndClearExceptionFromCallback(env, "notifyDisplayDisconnected");
+    }
+
+    virtual void onDisplayError(int32_t error) {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+        env->CallVoidMethod(mRemoteDisplayObjGlobal,
+                gRemoteDisplayClassInfo.notifyDisplayError, error);
+        checkAndClearExceptionFromCallback(env, "notifyDisplayError");
+    }
+
+private:
+    jobject mRemoteDisplayObjGlobal;
+
+    static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
+        if (env->ExceptionCheck()) {
+            ALOGE("An exception was thrown by callback '%s'.", methodName);
+            LOGE_EX(env);
+            env->ExceptionClear();
+        }
+    }
+};
+
+class NativeRemoteDisplay {
+public:
+    NativeRemoteDisplay(const sp<IRemoteDisplay>& display,
+            const sp<NativeRemoteDisplayClient>& client) :
+            mDisplay(display), mClient(client) {
+    }
+
+    ~NativeRemoteDisplay() {
+        mDisplay->dispose();
+    }
+
+private:
+    sp<IRemoteDisplay> mDisplay;
+    sp<NativeRemoteDisplayClient> mClient;
+};
+
+
+// ----------------------------------------------------------------------------
+
+static jint nativeListen(JNIEnv* env, jobject remoteDisplayObj, jstring ifaceStr) {
+    ScopedUtfChars iface(env, ifaceStr);
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(
+            sm->getService(String16("media.player")));
+    if (service == NULL) {
+        ALOGE("Could not obtain IMediaPlayerService from service manager");
+        return 0;
+    }
+
+    sp<NativeRemoteDisplayClient> client(new NativeRemoteDisplayClient(env, remoteDisplayObj));
+    sp<IRemoteDisplay> display = service->listenForRemoteDisplay(
+            client, String8(iface.c_str()));
+    if (display == NULL) {
+        ALOGE("Media player service rejected request to listen for remote display '%s'.",
+                iface.c_str());
+        return 0;
+    }
+
+    NativeRemoteDisplay* wrapper = new NativeRemoteDisplay(display, client);
+    return reinterpret_cast<jint>(wrapper);
+}
+
+static void nativeDispose(JNIEnv* env, jobject remoteDisplayObj, jint ptr) {
+    NativeRemoteDisplay* wrapper = reinterpret_cast<NativeRemoteDisplay*>(ptr);
+    delete wrapper;
+}
+
+// ----------------------------------------------------------------------------
+
+static JNINativeMethod gMethods[] = {
+    {"nativeListen", "(Ljava/lang/String;)I",
+            (void*)nativeListen },
+    {"nativeDispose", "(I)V",
+            (void*)nativeDispose },
+};
+
+int register_android_media_RemoteDisplay(JNIEnv* env)
+{
+    int err = AndroidRuntime::registerNativeMethods(env, "android/media/RemoteDisplay",
+            gMethods, NELEM(gMethods));
+
+    jclass clazz = env->FindClass("android/media/RemoteDisplay");
+    gRemoteDisplayClassInfo.notifyDisplayConnected =
+            env->GetMethodID(clazz, "notifyDisplayConnected",
+                    "(Landroid/view/Surface;III)V");
+    gRemoteDisplayClassInfo.notifyDisplayDisconnected =
+            env->GetMethodID(clazz, "notifyDisplayDisconnected", "()V");
+    gRemoteDisplayClassInfo.notifyDisplayError =
+            env->GetMethodID(clazz, "notifyDisplayError", "(I)V");
+    return err;
+}
+
+};
diff --git a/core/jni/android_opengl_EGL14.cpp b/core/jni/android_opengl_EGL14.cpp
new file mode 100644
index 0000000..b1664c6
--- /dev/null
+++ b/core/jni/android_opengl_EGL14.cpp
@@ -0,0 +1,1247 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+// This source file is automatically generated
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_view_Surface.h>
+#include <android_runtime/android_graphics_SurfaceTexture.h>
+#include <utils/misc.h>
+
+#include <assert.h>
+#include <EGL/egl.h>
+
+#include <gui/Surface.h>
+#include <gui/SurfaceTexture.h>
+#include <gui/SurfaceTextureClient.h>
+
+#include <ui/ANativeObjectBase.h>
+
+static int initialized = 0;
+
+static jclass egldisplayClass;
+static jclass eglcontextClass;
+static jclass eglsurfaceClass;
+static jclass eglconfigClass;
+
+static jmethodID egldisplayGetHandleID;
+static jmethodID eglcontextGetHandleID;
+static jmethodID eglsurfaceGetHandleID;
+static jmethodID eglconfigGetHandleID;
+
+static jmethodID egldisplayConstructor;
+static jmethodID eglcontextConstructor;
+static jmethodID eglsurfaceConstructor;
+static jmethodID eglconfigConstructor;
+
+static jobject eglNoContextObject;
+static jobject eglNoDisplayObject;
+static jobject eglNoSurfaceObject;
+
+
+
+/* Cache method IDs each time the class is loaded. */
+
+static void
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
+{
+    jclass egldisplayClassLocal = _env->FindClass("android/opengl/EGLDisplay");
+    egldisplayClass = (jclass) _env->NewGlobalRef(egldisplayClassLocal);
+    jclass eglcontextClassLocal = _env->FindClass("android/opengl/EGLContext");
+    eglcontextClass = (jclass) _env->NewGlobalRef(eglcontextClassLocal);
+    jclass eglsurfaceClassLocal = _env->FindClass("android/opengl/EGLSurface");
+    eglsurfaceClass = (jclass) _env->NewGlobalRef(eglsurfaceClassLocal);
+    jclass eglconfigClassLocal = _env->FindClass("android/opengl/EGLConfig");
+    eglconfigClass = (jclass) _env->NewGlobalRef(eglconfigClassLocal);
+
+    egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getHandle", "()I");
+    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getHandle", "()I");
+    eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getHandle", "()I");
+    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getHandle", "()I");
+
+
+    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(I)V");
+    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(I)V");
+    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(I)V");
+    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(I)V");
+
+    jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, (jint)EGL_NO_CONTEXT);
+    eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject);
+    jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, (jint)EGL_NO_DISPLAY);
+    eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject);
+    jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, (jint)EGL_NO_SURFACE);
+    eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject);
+
+
+    jclass eglClass = _env->FindClass("android/opengl/EGL14");
+    jfieldID noContextFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_CONTEXT", "Landroid/opengl/EGLContext;");
+    _env->SetStaticObjectField(eglClass, noContextFieldID, eglNoContextObject);
+
+    jfieldID noDisplayFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_DISPLAY", "Landroid/opengl/EGLDisplay;");
+    _env->SetStaticObjectField(eglClass, noDisplayFieldID, eglNoDisplayObject);
+
+    jfieldID noSurfaceFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_SURFACE", "Landroid/opengl/EGLSurface;");
+    _env->SetStaticObjectField(eglClass, noSurfaceFieldID, eglNoSurfaceObject);
+}
+
+static void *
+fromEGLHandle(JNIEnv *_env, jmethodID mid, jobject obj) {
+    if (obj == NULL){
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Object is set to null.");
+    }
+
+    return (void*) (_env->CallIntMethod(obj, mid));
+}
+
+static jobject
+toEGLHandle(JNIEnv *_env, jclass cls, jmethodID con, void * handle) {
+    if (cls == eglcontextClass &&
+       (EGLContext)handle == EGL_NO_CONTEXT) {
+           return eglNoContextObject;
+    }
+
+    if (cls == egldisplayClass &&
+       (EGLDisplay)handle == EGL_NO_DISPLAY) {
+           return eglNoDisplayObject;
+    }
+
+    if (cls == eglsurfaceClass &&
+       (EGLSurface)handle == EGL_NO_SURFACE) {
+           return eglNoSurfaceObject;
+    }
+
+    return _env->NewObject(cls, con, (jint)handle);
+}
+
+// --------------------------------------------------------------------------
+/* EGLint eglGetError ( void ) */
+static jint
+android_eglGetError
+  (JNIEnv *_env, jobject _this) {
+    EGLint _returnValue = (EGLint) 0;
+    _returnValue = eglGetError();
+    return _returnValue;
+}
+
+/* EGLDisplay eglGetDisplay ( EGLNativeDisplayType display_id ) */
+static jobject
+android_eglGetDisplay
+  (JNIEnv *_env, jobject _this, jint display_id) {
+    EGLDisplay _returnValue = (EGLDisplay) 0;
+    _returnValue = eglGetDisplay(
+        (EGLNativeDisplayType)display_id
+    );
+    return toEGLHandle(_env, egldisplayClass, egldisplayConstructor, _returnValue);
+}
+
+/* EGLBoolean eglInitialize ( EGLDisplay dpy, EGLint *major, EGLint *minor ) */
+static jboolean
+android_eglInitialize
+  (JNIEnv *_env, jobject _this, jobject dpy, jintArray major_ref, jint majorOffset, jintArray minor_ref, jint minorOffset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLint *major_base = (EGLint *) 0;
+    jint _majorRemaining;
+    EGLint *major = (EGLint *) 0;
+    EGLint *minor_base = (EGLint *) 0;
+    jint _minorRemaining;
+    EGLint *minor = (EGLint *) 0;
+
+    if (!major_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "major == null";
+        goto exit;
+    }
+    if (majorOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "majorOffset < 0";
+        goto exit;
+    }
+    _majorRemaining = _env->GetArrayLength(major_ref) - majorOffset;
+    if (_majorRemaining < 1) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - majorOffset < 1 < needed";
+        goto exit;
+    }
+    major_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(major_ref, (jboolean *)0);
+    major = major_base + majorOffset;
+
+    if (!minor_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "minor == null";
+        goto exit;
+    }
+    if (minorOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "minorOffset < 0";
+        goto exit;
+    }
+    _minorRemaining = _env->GetArrayLength(minor_ref) - minorOffset;
+    if (_minorRemaining < 1) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - minorOffset < 1 < needed";
+        goto exit;
+    }
+    minor_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(minor_ref, (jboolean *)0);
+    minor = minor_base + minorOffset;
+
+    _returnValue = eglInitialize(
+        (EGLDisplay)dpy_native,
+        (EGLint *)major,
+        (EGLint *)minor
+    );
+
+exit:
+    if (minor_base) {
+        _env->ReleasePrimitiveArrayCritical(minor_ref, minor_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (major_base) {
+        _env->ReleasePrimitiveArrayCritical(major_ref, major_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return _returnValue;
+}
+
+/* EGLBoolean eglTerminate ( EGLDisplay dpy ) */
+static jboolean
+android_eglTerminate
+  (JNIEnv *_env, jobject _this, jobject dpy) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+
+    _returnValue = eglTerminate(
+        (EGLDisplay)dpy_native
+    );
+    return _returnValue;
+}
+
+/* const char * eglQueryString ( EGLDisplay dpy, EGLint name ) */
+static jstring
+android_eglQueryString__Landroind_opengl_EGLDisplay_2I
+  (JNIEnv *_env, jobject _this, jobject dpy, jint name) {
+    const char* chars = (const char*) eglQueryString(
+        (EGLDisplay)fromEGLHandle(_env, egldisplayGetHandleID, dpy),
+        (EGLint)name
+    );
+    return _env->NewStringUTF(chars);
+}
+/* EGLBoolean eglGetConfigs ( EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config ) */
+static jboolean
+android_eglGetConfigs
+  (JNIEnv *_env, jobject _this, jobject dpy, jobjectArray configs_ref, jint configsOffset, jint config_size, jintArray num_config_ref, jint num_configOffset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    jint _configsRemaining;
+    EGLConfig *configs = (EGLConfig *) 0;
+    EGLint *num_config_base = (EGLint *) 0;
+    jint _num_configRemaining;
+    EGLint *num_config = (EGLint *) 0;
+
+    if (!configs_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "configs == null";
+        goto exit;
+    }
+    if (configsOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "configsOffset < 0";
+        goto exit;
+    }
+    _configsRemaining = _env->GetArrayLength(configs_ref) - configsOffset;
+    if (_configsRemaining < config_size) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - configsOffset < config_size < needed";
+        goto exit;
+    }
+    configs = new EGLConfig[_configsRemaining];
+
+    if (!num_config_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "num_config == null";
+        goto exit;
+    }
+    if (num_configOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "num_configOffset < 0";
+        goto exit;
+    }
+    _num_configRemaining = _env->GetArrayLength(num_config_ref) - num_configOffset;
+    num_config_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(num_config_ref, (jboolean *)0);
+    num_config = num_config_base + num_configOffset;
+
+    _returnValue = eglGetConfigs(
+        (EGLDisplay)dpy_native,
+        (EGLConfig *)configs,
+        (EGLint)config_size,
+        (EGLint *)num_config
+    );
+
+exit:
+    if (num_config_base) {
+        _env->ReleasePrimitiveArrayCritical(num_config_ref, num_config_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (configs) {
+        for (int i = 0; i < _configsRemaining; i++) {
+            jobject configs_new = toEGLHandle(_env, eglconfigClass, eglconfigConstructor, configs[i]);
+            _env->SetObjectArrayElement(configs_ref, i + configsOffset, configs_new);
+        }
+        delete[] configs;
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return _returnValue;
+}
+
+/* EGLBoolean eglChooseConfig ( EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config ) */
+static jboolean
+android_eglChooseConfig
+  (JNIEnv *_env, jobject _this, jobject dpy, jintArray attrib_list_ref, jint attrib_listOffset, jobjectArray configs_ref, jint configsOffset, jint config_size, jintArray num_config_ref, jint num_configOffset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    bool attrib_list_sentinel = false;
+    EGLint *attrib_list_base = (EGLint *) 0;
+    jint _attrib_listRemaining;
+    EGLint *attrib_list = (EGLint *) 0;
+    jint _configsRemaining;
+    EGLConfig *configs = (EGLConfig *) 0;
+    EGLint *num_config_base = (EGLint *) 0;
+    jint _num_configRemaining;
+    EGLint *num_config = (EGLint *) 0;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (attrib_listOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_listOffset < 0";
+        goto exit;
+    }
+    _attrib_listRemaining = _env->GetArrayLength(attrib_list_ref) - attrib_listOffset;
+    attrib_list_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + attrib_listOffset;
+    attrib_list_sentinel = false;
+    for (int i = _attrib_listRemaining - 1; i >= 0; i--)  {
+        if (attrib_list[i] == EGL_NONE){
+            attrib_list_sentinel = true;
+            break;
+        }
+    }
+    if (attrib_list_sentinel == false) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list must contain EGL_NONE!";
+        goto exit;
+    }
+
+    if (!configs_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "configs == null";
+        goto exit;
+    }
+    if (configsOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "configsOffset < 0";
+        goto exit;
+    }
+    _configsRemaining = _env->GetArrayLength(configs_ref) - configsOffset;
+    if (_configsRemaining < config_size) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - configsOffset < config_size < needed";
+        goto exit;
+    }
+    configs = new EGLConfig[_configsRemaining];
+
+    if (!num_config_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "num_config == null";
+        goto exit;
+    }
+    if (num_configOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "num_configOffset < 0";
+        goto exit;
+    }
+    _num_configRemaining = _env->GetArrayLength(num_config_ref) - num_configOffset;
+    if (_num_configRemaining < 1) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - num_configOffset < 1 < needed";
+        goto exit;
+    }
+    num_config_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(num_config_ref, (jboolean *)0);
+    num_config = num_config_base + num_configOffset;
+
+    _returnValue = eglChooseConfig(
+        (EGLDisplay)dpy_native,
+        (EGLint *)attrib_list,
+        (EGLConfig *)configs,
+        (EGLint)config_size,
+        (EGLint *)num_config
+    );
+
+exit:
+    if (num_config_base) {
+        _env->ReleasePrimitiveArrayCritical(num_config_ref, num_config_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (attrib_list_base) {
+        _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+            JNI_ABORT);
+    }
+    if (configs) {
+        for (int i = 0; i < _configsRemaining; i++) {
+            jobject configs_new = toEGLHandle(_env, eglconfigClass, eglconfigConstructor, configs[i]);
+            _env->SetObjectArrayElement(configs_ref, i + configsOffset, configs_new);
+        }
+        delete[] configs;
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return _returnValue;
+}
+
+/* EGLBoolean eglGetConfigAttrib ( EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value ) */
+static jboolean
+android_eglGetConfigAttrib
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jint attribute, jintArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    EGLint *value_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *value = (EGLint *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    if (_remaining < 1) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
+        goto exit;
+    }
+    value_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    _returnValue = eglGetConfigAttrib(
+        (EGLDisplay)dpy_native,
+        (EGLConfig)config_native,
+        (EGLint)attribute,
+        (EGLint *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return _returnValue;
+}
+
+/* EGLSurface eglCreateWindowSurface ( EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list ) */
+static jobject
+android_eglCreateWindowSurface
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jobject win, jintArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = "";
+    const char * _exceptionMessage = "";
+    EGLSurface _returnValue = (EGLSurface) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    int attrib_list_sentinel = 0;
+    EGLint *attrib_list_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *attrib_list = (EGLint *) 0;
+    android::sp<ANativeWindow> window;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    if (win == NULL) {
+not_valid_surface:
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "Make sure the SurfaceView or associated SurfaceHolder has a valid Surface";
+        goto exit;
+    }
+
+    window = android::android_view_Surface_getNativeWindow(_env, win);
+
+    if (window == NULL)
+        goto not_valid_surface;
+
+    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + offset;
+    attrib_list_sentinel = 0;
+    for (int i = _remaining - 1; i >= 0; i--)  {
+        if (*((EGLint*)(attrib_list + i)) == EGL_NONE){
+            attrib_list_sentinel = 1;
+            break;
+        }
+    }
+    if (attrib_list_sentinel == 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list must contain EGL_NONE!";
+        goto exit;
+    }
+
+    _returnValue = eglCreateWindowSurface(
+        (EGLDisplay)dpy_native,
+        (EGLConfig)config_native,
+        (EGLNativeWindowType)window.get(),
+        (EGLint *)attrib_list
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+}
+
+/* EGLSurface eglCreateWindowSurface ( EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list ) */
+static jobject
+android_eglCreateWindowSurfaceTexture
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jobject win, jintArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = "";
+    const char * _exceptionMessage = "";
+    EGLSurface _returnValue = (EGLSurface) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    int attrib_list_sentinel = 0;
+    EGLint *attrib_list_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *attrib_list = (EGLint *) 0;
+    android::sp<ANativeWindow> window;
+    android::sp<android::SurfaceTexture> surfaceTexture;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    if (win == NULL) {
+not_valid_surface:
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "Make sure the SurfaceView or associated SurfaceHolder has a valid Surface";
+        goto exit;
+    }
+    surfaceTexture = android::SurfaceTexture_getSurfaceTexture(_env, win);
+    window = new android::SurfaceTextureClient(surfaceTexture);
+
+    if (window == NULL)
+        goto not_valid_surface;
+
+    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + offset;
+    attrib_list_sentinel = 0;
+    for (int i = _remaining - 1; i >= 0; i--)  {
+        if (*((EGLint*)(attrib_list + i)) == EGL_NONE){
+            attrib_list_sentinel = 1;
+            break;
+        }
+    }
+    if (attrib_list_sentinel == 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list must contain EGL_NONE!";
+        goto exit;
+    }
+
+    _returnValue = eglCreateWindowSurface(
+        (EGLDisplay)dpy_native,
+        (EGLConfig)config_native,
+        (EGLNativeWindowType)window.get(),
+        (EGLint *)attrib_list
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+}
+/* EGLSurface eglCreatePbufferSurface ( EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list ) */
+static jobject
+android_eglCreatePbufferSurface
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jintArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLSurface _returnValue = (EGLSurface) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    bool attrib_list_sentinel = false;
+    EGLint *attrib_list_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *attrib_list = (EGLint *) 0;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + offset;
+    attrib_list_sentinel = false;
+    for (int i = _remaining - 1; i >= 0; i--)  {
+        if (attrib_list[i] == EGL_NONE){
+            attrib_list_sentinel = true;
+            break;
+        }
+    }
+    if (attrib_list_sentinel == false) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list must contain EGL_NONE!";
+        goto exit;
+    }
+
+    _returnValue = eglCreatePbufferSurface(
+        (EGLDisplay)dpy_native,
+        (EGLConfig)config_native,
+        (EGLint *)attrib_list
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+}
+
+/* EGLSurface eglCreatePixmapSurface ( EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list ) */
+static jobject
+android_eglCreatePixmapSurface
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jint pixmap, jintArray attrib_list_ref, jint offset) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException",
+        "eglCreatePixmapSurface");
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, (EGLSurface) 0);
+}
+
+/* EGLBoolean eglDestroySurface ( EGLDisplay dpy, EGLSurface surface ) */
+static jboolean
+android_eglDestroySurface
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject surface) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSurface surface_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, surface);
+
+    _returnValue = eglDestroySurface(
+        (EGLDisplay)dpy_native,
+        (EGLSurface)surface_native
+    );
+    return _returnValue;
+}
+
+/* EGLBoolean eglQuerySurface ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value ) */
+static jboolean
+android_eglQuerySurface
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject surface, jint attribute, jintArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSurface surface_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, surface);
+    EGLint *value_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *value = (EGLint *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    if (_remaining < 1) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
+        goto exit;
+    }
+    value_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    _returnValue = eglQuerySurface(
+        (EGLDisplay)dpy_native,
+        (EGLSurface)surface_native,
+        (EGLint)attribute,
+        (EGLint *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return _returnValue;
+}
+
+/* EGLBoolean eglBindAPI ( EGLenum api ) */
+static jboolean
+android_eglBindAPI
+  (JNIEnv *_env, jobject _this, jint api) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    _returnValue = eglBindAPI(
+        (EGLenum)api
+    );
+    return _returnValue;
+}
+
+/* EGLenum eglQueryAPI ( void ) */
+static jint
+android_eglQueryAPI
+  (JNIEnv *_env, jobject _this) {
+    EGLenum _returnValue = (EGLenum) 0;
+    _returnValue = eglQueryAPI();
+    return _returnValue;
+}
+
+/* EGLBoolean eglWaitClient ( void ) */
+static jboolean
+android_eglWaitClient
+  (JNIEnv *_env, jobject _this) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    _returnValue = eglWaitClient();
+    return _returnValue;
+}
+
+/* EGLBoolean eglReleaseThread ( void ) */
+static jboolean
+android_eglReleaseThread
+  (JNIEnv *_env, jobject _this) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    _returnValue = eglReleaseThread();
+    return _returnValue;
+}
+
+/* EGLSurface eglCreatePbufferFromClientBuffer ( EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list ) */
+static jobject
+android_eglCreatePbufferFromClientBuffer
+  (JNIEnv *_env, jobject _this, jobject dpy, jint buftype, jint buffer, jobject config, jintArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLSurface _returnValue = (EGLSurface) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    bool attrib_list_sentinel = false;
+    EGLint *attrib_list_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *attrib_list = (EGLint *) 0;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + offset;
+    attrib_list_sentinel = false;
+    for (int i = _remaining - 1; i >= 0; i--)  {
+        if (attrib_list[i] == EGL_NONE){
+            attrib_list_sentinel = true;
+            break;
+        }
+    }
+    if (attrib_list_sentinel == false) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list must contain EGL_NONE!";
+        goto exit;
+    }
+
+    _returnValue = eglCreatePbufferFromClientBuffer(
+        (EGLDisplay)dpy_native,
+        (EGLenum)buftype,
+        (EGLClientBuffer)buffer,
+        (EGLConfig)config_native,
+        (EGLint *)attrib_list
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+}
+
+/* EGLBoolean eglSurfaceAttrib ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value ) */
+static jboolean
+android_eglSurfaceAttrib
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject surface, jint attribute, jint value) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSurface surface_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, surface);
+
+    _returnValue = eglSurfaceAttrib(
+        (EGLDisplay)dpy_native,
+        (EGLSurface)surface_native,
+        (EGLint)attribute,
+        (EGLint)value
+    );
+    return _returnValue;
+}
+
+/* EGLBoolean eglBindTexImage ( EGLDisplay dpy, EGLSurface surface, EGLint buffer ) */
+static jboolean
+android_eglBindTexImage
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject surface, jint buffer) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSurface surface_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, surface);
+
+    _returnValue = eglBindTexImage(
+        (EGLDisplay)dpy_native,
+        (EGLSurface)surface_native,
+        (EGLint)buffer
+    );
+    return _returnValue;
+}
+
+/* EGLBoolean eglReleaseTexImage ( EGLDisplay dpy, EGLSurface surface, EGLint buffer ) */
+static jboolean
+android_eglReleaseTexImage
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject surface, jint buffer) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSurface surface_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, surface);
+
+    _returnValue = eglReleaseTexImage(
+        (EGLDisplay)dpy_native,
+        (EGLSurface)surface_native,
+        (EGLint)buffer
+    );
+    return _returnValue;
+}
+
+/* EGLBoolean eglSwapInterval ( EGLDisplay dpy, EGLint interval ) */
+static jboolean
+android_eglSwapInterval
+  (JNIEnv *_env, jobject _this, jobject dpy, jint interval) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+
+    _returnValue = eglSwapInterval(
+        (EGLDisplay)dpy_native,
+        (EGLint)interval
+    );
+    return _returnValue;
+}
+
+/* EGLContext eglCreateContext ( EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list ) */
+static jobject
+android_eglCreateContext
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jobject share_context, jintArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLContext _returnValue = (EGLContext) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    EGLContext share_context_native = (EGLContext) fromEGLHandle(_env, eglcontextGetHandleID, share_context);
+    bool attrib_list_sentinel = false;
+    EGLint *attrib_list_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *attrib_list = (EGLint *) 0;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + offset;
+    attrib_list_sentinel = false;
+    for (int i = _remaining - 1; i >= 0; i--)  {
+        if (attrib_list[i] == EGL_NONE){
+            attrib_list_sentinel = true;
+            break;
+        }
+    }
+    if (attrib_list_sentinel == false) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list must contain EGL_NONE!";
+        goto exit;
+    }
+
+    _returnValue = eglCreateContext(
+        (EGLDisplay)dpy_native,
+        (EGLConfig)config_native,
+        (EGLContext)share_context_native,
+        (EGLint *)attrib_list
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return toEGLHandle(_env, eglcontextClass, eglcontextConstructor, _returnValue);
+}
+
+/* EGLBoolean eglDestroyContext ( EGLDisplay dpy, EGLContext ctx ) */
+static jboolean
+android_eglDestroyContext
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject ctx) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLContext ctx_native = (EGLContext) fromEGLHandle(_env, eglcontextGetHandleID, ctx);
+
+    _returnValue = eglDestroyContext(
+        (EGLDisplay)dpy_native,
+        (EGLContext)ctx_native
+    );
+    return _returnValue;
+}
+
+/* EGLBoolean eglMakeCurrent ( EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx ) */
+static jboolean
+android_eglMakeCurrent
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject draw, jobject read, jobject ctx) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSurface draw_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, draw);
+    EGLSurface read_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, read);
+    EGLContext ctx_native = (EGLContext) fromEGLHandle(_env, eglcontextGetHandleID, ctx);
+
+    _returnValue = eglMakeCurrent(
+        (EGLDisplay)dpy_native,
+        (EGLSurface)draw_native,
+        (EGLSurface)read_native,
+        (EGLContext)ctx_native
+    );
+    return _returnValue;
+}
+
+/* EGLContext eglGetCurrentContext ( void ) */
+static jobject
+android_eglGetCurrentContext
+  (JNIEnv *_env, jobject _this) {
+    EGLContext _returnValue = (EGLContext) 0;
+    _returnValue = eglGetCurrentContext();
+    return toEGLHandle(_env, eglcontextClass, eglcontextConstructor, _returnValue);
+}
+
+/* EGLSurface eglGetCurrentSurface ( EGLint readdraw ) */
+static jobject
+android_eglGetCurrentSurface
+  (JNIEnv *_env, jobject _this, jint readdraw) {
+    EGLSurface _returnValue = (EGLSurface) 0;
+    _returnValue = eglGetCurrentSurface(
+        (EGLint)readdraw
+    );
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+}
+
+/* EGLDisplay eglGetCurrentDisplay ( void ) */
+static jobject
+android_eglGetCurrentDisplay
+  (JNIEnv *_env, jobject _this) {
+    EGLDisplay _returnValue = (EGLDisplay) 0;
+    _returnValue = eglGetCurrentDisplay();
+    return toEGLHandle(_env, egldisplayClass, egldisplayConstructor, _returnValue);
+}
+
+/* EGLBoolean eglQueryContext ( EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value ) */
+static jboolean
+android_eglQueryContext
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject ctx, jint attribute, jintArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLContext ctx_native = (EGLContext) fromEGLHandle(_env, eglcontextGetHandleID, ctx);
+    EGLint *value_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *value = (EGLint *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    if (_remaining < 1) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
+        goto exit;
+    }
+    value_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    _returnValue = eglQueryContext(
+        (EGLDisplay)dpy_native,
+        (EGLContext)ctx_native,
+        (EGLint)attribute,
+        (EGLint *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return _returnValue;
+}
+
+/* EGLBoolean eglWaitGL ( void ) */
+static jboolean
+android_eglWaitGL
+  (JNIEnv *_env, jobject _this) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    _returnValue = eglWaitGL();
+    return _returnValue;
+}
+
+/* EGLBoolean eglWaitNative ( EGLint engine ) */
+static jboolean
+android_eglWaitNative
+  (JNIEnv *_env, jobject _this, jint engine) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    _returnValue = eglWaitNative(
+        (EGLint)engine
+    );
+    return _returnValue;
+}
+
+/* EGLBoolean eglSwapBuffers ( EGLDisplay dpy, EGLSurface surface ) */
+static jboolean
+android_eglSwapBuffers
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject surface) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSurface surface_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, surface);
+
+    _returnValue = eglSwapBuffers(
+        (EGLDisplay)dpy_native,
+        (EGLSurface)surface_native
+    );
+    return _returnValue;
+}
+
+/* EGLBoolean eglCopyBuffers ( EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target ) */
+static jboolean
+android_eglCopyBuffers
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject surface, jint target) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException",
+        "eglCopyBuffers");
+    return (EGLBoolean) 0;
+}
+
+static const char *classPathName = "android/opengl/EGL14";
+
+static JNINativeMethod methods[] = {
+{"_nativeClassInit", "()V", (void*)nativeClassInit },
+{"eglGetError", "()I", (void *) android_eglGetError },
+{"eglGetDisplay", "(I)Landroid/opengl/EGLDisplay;", (void *) android_eglGetDisplay },
+{"eglInitialize", "(Landroid/opengl/EGLDisplay;[II[II)Z", (void *) android_eglInitialize },
+{"eglTerminate", "(Landroid/opengl/EGLDisplay;)Z", (void *) android_eglTerminate },
+{"eglQueryString", "(Landroid/opengl/EGLDisplay;I)Ljava/lang/String;", (void *) android_eglQueryString__Landroind_opengl_EGLDisplay_2I },
+{"eglGetConfigs", "(Landroid/opengl/EGLDisplay;[Landroid/opengl/EGLConfig;II[II)Z", (void *) android_eglGetConfigs },
+{"eglChooseConfig", "(Landroid/opengl/EGLDisplay;[II[Landroid/opengl/EGLConfig;II[II)Z", (void *) android_eglChooseConfig },
+{"eglGetConfigAttrib", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;I[II)Z", (void *) android_eglGetConfigAttrib },
+{"_eglCreateWindowSurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;Ljava/lang/Object;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreateWindowSurface },
+{"_eglCreateWindowSurfaceTexture", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;Ljava/lang/Object;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreateWindowSurfaceTexture },
+{"eglCreatePbufferSurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePbufferSurface },
+{"eglCreatePixmapSurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;I[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePixmapSurface },
+{"eglDestroySurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;)Z", (void *) android_eglDestroySurface },
+{"eglQuerySurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;I[II)Z", (void *) android_eglQuerySurface },
+{"eglBindAPI", "(I)Z", (void *) android_eglBindAPI },
+{"eglQueryAPI", "()I", (void *) android_eglQueryAPI },
+{"eglWaitClient", "()Z", (void *) android_eglWaitClient },
+{"eglReleaseThread", "()Z", (void *) android_eglReleaseThread },
+{"eglCreatePbufferFromClientBuffer", "(Landroid/opengl/EGLDisplay;IILandroid/opengl/EGLConfig;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePbufferFromClientBuffer },
+{"eglSurfaceAttrib", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;II)Z", (void *) android_eglSurfaceAttrib },
+{"eglBindTexImage", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;I)Z", (void *) android_eglBindTexImage },
+{"eglReleaseTexImage", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;I)Z", (void *) android_eglReleaseTexImage },
+{"eglSwapInterval", "(Landroid/opengl/EGLDisplay;I)Z", (void *) android_eglSwapInterval },
+{"eglCreateContext", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;Landroid/opengl/EGLContext;[II)Landroid/opengl/EGLContext;", (void *) android_eglCreateContext },
+{"eglDestroyContext", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLContext;)Z", (void *) android_eglDestroyContext },
+{"eglMakeCurrent", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;Landroid/opengl/EGLSurface;Landroid/opengl/EGLContext;)Z", (void *) android_eglMakeCurrent },
+{"eglGetCurrentContext", "()Landroid/opengl/EGLContext;", (void *) android_eglGetCurrentContext },
+{"eglGetCurrentSurface", "(I)Landroid/opengl/EGLSurface;", (void *) android_eglGetCurrentSurface },
+{"eglGetCurrentDisplay", "()Landroid/opengl/EGLDisplay;", (void *) android_eglGetCurrentDisplay },
+{"eglQueryContext", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLContext;I[II)Z", (void *) android_eglQueryContext },
+{"eglWaitGL", "()Z", (void *) android_eglWaitGL },
+{"eglWaitNative", "(I)Z", (void *) android_eglWaitNative },
+{"eglSwapBuffers", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;)Z", (void *) android_eglSwapBuffers },
+{"eglCopyBuffers", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;I)Z", (void *) android_eglCopyBuffers },
+};
+
+int register_android_opengl_jni_EGL14(JNIEnv *_env)
+{
+    int err;
+    err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));
+    return err;
+}
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index 6c29d6c..571f579 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -75,14 +75,12 @@
 }
 
 static void *
-getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
 {
     jint position;
     jint limit;
     jint elementSizeShift;
     jlong pointer;
-    jint offset;
-    void *data;
 
     position = _env->GetIntField(buffer, positionID);
     limit = _env->GetIntField(buffer, limitID);
@@ -97,11 +95,10 @@
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
-    offset = _env->CallStaticIntMethod(nioAccessClass,
+    *offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
-    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
 
-    return (void *) ((char *) data + offset);
+    return NULL;
 }
 
 static void
@@ -292,6 +289,7 @@
 android_glColorPointerBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -315,10 +313,15 @@
 android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint imageSize, jobject data_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glCompressedTexImage2D(
         (GLenum)target,
         (GLint)level,
@@ -339,10 +342,15 @@
 android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint imageSize, jobject data_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glCompressedTexSubImage2D(
         (GLenum)target,
         (GLint)level,
@@ -404,21 +412,30 @@
 static void
 android_glDeleteTextures__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray textures_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *textures_base = (GLuint *) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
     if (!textures_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "textures == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     textures_base = (GLuint *)
@@ -435,21 +452,34 @@
         _env->ReleasePrimitiveArrayCritical(textures_ref, textures_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteTextures ( GLsizei n, const GLuint *textures ) */
 static void
 android_glDeleteTextures__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject textures_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
-    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
+    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (textures == NULL) {
+        char * _texturesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        textures = (GLuint *) (_texturesBase + _bufferOffset);
+    }
     glDeleteTextures(
         (GLsizei)n,
         (GLuint *)textures
@@ -459,6 +489,9 @@
     if (_array) {
         releasePointer(_env, _array, textures, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDepthFunc ( GLenum func ) */
@@ -532,15 +565,25 @@
 static void
 android_glDrawElements__IIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint mode, jint count, jint type, jobject indices_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *indices = (GLvoid *) 0;
 
-    indices = (GLvoid *)getPointer(_env, indices_buf, &_array, &_remaining);
+    indices = (GLvoid *)getPointer(_env, indices_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < count) {
-        jniThrowException(_env, "java/lang/ArrayIndexOutOfBoundsException", "remaining() < count");
+        _exception = 1;
+        _exceptionType = "java/lang/ArrayIndexOutOfBoundsException";
+        _exceptionMessage = "remaining() < count < needed";
         goto exit;
     }
+    if (indices == NULL) {
+        char * _indicesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        indices = (GLvoid *) (_indicesBase + _bufferOffset);
+    }
     glDrawElements(
         (GLenum)mode,
         (GLsizei)count,
@@ -552,6 +595,9 @@
     if (_array) {
         releasePointer(_env, _array, indices, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glEnable ( GLenum cap ) */
@@ -600,16 +646,23 @@
 static void
 android_glFogfv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -639,7 +692,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -656,17 +711,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFogfv ( GLenum pname, const GLfloat *params ) */
 static void
 android_glFogfv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_FOG_MODE)
@@ -693,9 +755,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glFogfv(
         (GLenum)pname,
         (GLfloat *)params
@@ -705,6 +773,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFogx ( GLenum pname, GLfixed param ) */
@@ -721,16 +792,23 @@
 static void
 android_glFogxv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -760,7 +838,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -777,17 +857,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFogxv ( GLenum pname, const GLfixed *params ) */
 static void
 android_glFogxv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_FOG_MODE)
@@ -814,9 +901,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glFogxv(
         (GLenum)pname,
         (GLfixed *)params
@@ -826,6 +919,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFrontFace ( GLenum mode ) */
@@ -870,24 +966,29 @@
 android_glGenTextures__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray textures_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *textures_base = (GLuint *) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
     if (!textures_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "textures == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     textures_base = (GLuint *)
@@ -904,6 +1005,9 @@
         _env->ReleasePrimitiveArrayCritical(textures_ref, textures_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenTextures ( GLsizei n, GLuint *textures ) */
@@ -911,16 +1015,24 @@
 android_glGenTextures__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject textures_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
-    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
+    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (textures == NULL) {
+        char * _texturesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        textures = (GLuint *) (_texturesBase + _bufferOffset);
+    }
     glGenTextures(
         (GLsizei)n,
         (GLuint *)textures
@@ -930,6 +1042,9 @@
     if (_array) {
         releasePointer(_env, _array, textures, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* GLenum glGetError ( void ) */
@@ -946,18 +1061,22 @@
 android_glGetIntegerv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1294,7 +1413,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -1311,6 +1431,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetIntegerv ( GLenum pname, GLint *params ) */
@@ -1318,11 +1441,14 @@
 android_glGetIntegerv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_ALPHA_BITS)
@@ -1656,9 +1782,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetIntegerv(
         (GLenum)pname,
         (GLint *)params
@@ -1668,6 +1799,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* const GLubyte * glGetString ( GLenum name ) */
@@ -1699,16 +1833,23 @@
 static void
 android_glLightModelfv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1729,7 +1870,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1746,17 +1889,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightModelfv ( GLenum pname, const GLfloat *params ) */
 static void
 android_glLightModelfv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_LIGHT_MODEL_TWO_SIDE)
@@ -1774,9 +1924,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glLightModelfv(
         (GLenum)pname,
         (GLfloat *)params
@@ -1786,6 +1942,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightModelx ( GLenum pname, GLfixed param ) */
@@ -1802,16 +1961,23 @@
 static void
 android_glLightModelxv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1832,7 +1998,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1849,17 +2017,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightModelxv ( GLenum pname, const GLfixed *params ) */
 static void
 android_glLightModelxv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_LIGHT_MODEL_TWO_SIDE)
@@ -1877,9 +2052,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glLightModelxv(
         (GLenum)pname,
         (GLfixed *)params
@@ -1889,6 +2070,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightf ( GLenum light, GLenum pname, GLfloat param ) */
@@ -1906,16 +2090,23 @@
 static void
 android_glLightfv__II_3FI
   (JNIEnv *_env, jobject _this, jint light, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1962,7 +2153,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1980,17 +2173,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightfv ( GLenum light, GLenum pname, const GLfloat *params ) */
 static void
 android_glLightfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SPOT_EXPONENT)
@@ -2034,9 +2234,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glLightfv(
         (GLenum)light,
         (GLenum)pname,
@@ -2047,6 +2253,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightx ( GLenum light, GLenum pname, GLfixed param ) */
@@ -2064,16 +2273,23 @@
 static void
 android_glLightxv__II_3II
   (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2120,7 +2336,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2138,17 +2356,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightxv ( GLenum light, GLenum pname, const GLfixed *params ) */
 static void
 android_glLightxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SPOT_EXPONENT)
@@ -2192,9 +2417,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glLightxv(
         (GLenum)light,
         (GLenum)pname,
@@ -2205,6 +2436,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLineWidth ( GLfloat width ) */
@@ -2236,16 +2470,23 @@
 static void
 android_glLoadMatrixf___3FI
   (JNIEnv *_env, jobject _this, jfloatArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *m_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *m = (GLfloat *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2262,6 +2503,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLoadMatrixf ( const GLfloat *m ) */
@@ -2269,10 +2513,15 @@
 android_glLoadMatrixf__Ljava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *m = (GLfloat *) 0;
 
-    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfloat *) (_mBase + _bufferOffset);
+    }
     glLoadMatrixf(
         (GLfloat *)m
     );
@@ -2285,16 +2534,23 @@
 static void
 android_glLoadMatrixx___3II
   (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *m_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2311,6 +2567,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLoadMatrixx ( const GLfixed *m ) */
@@ -2318,10 +2577,15 @@
 android_glLoadMatrixx__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
-    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfixed *) (_mBase + _bufferOffset);
+    }
     glLoadMatrixx(
         (GLfixed *)m
     );
@@ -2354,16 +2618,23 @@
 static void
 android_glMaterialfv__II_3FI
   (JNIEnv *_env, jobject _this, jint face, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2396,7 +2667,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -2414,17 +2687,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMaterialfv ( GLenum face, GLenum pname, const GLfloat *params ) */
 static void
 android_glMaterialfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SHININESS)
@@ -2454,9 +2734,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glMaterialfv(
         (GLenum)face,
         (GLenum)pname,
@@ -2467,6 +2753,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMaterialx ( GLenum face, GLenum pname, GLfixed param ) */
@@ -2484,16 +2773,23 @@
 static void
 android_glMaterialxv__II_3II
   (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2526,7 +2822,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2544,17 +2842,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMaterialxv ( GLenum face, GLenum pname, const GLfixed *params ) */
 static void
 android_glMaterialxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SHININESS)
@@ -2584,9 +2889,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glMaterialxv(
         (GLenum)face,
         (GLenum)pname,
@@ -2597,6 +2908,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMatrixMode ( GLenum mode ) */
@@ -2612,16 +2926,23 @@
 static void
 android_glMultMatrixf___3FI
   (JNIEnv *_env, jobject _this, jfloatArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *m_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *m = (GLfloat *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2638,6 +2959,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMultMatrixf ( const GLfloat *m ) */
@@ -2645,10 +2969,15 @@
 android_glMultMatrixf__Ljava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *m = (GLfloat *) 0;
 
-    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfloat *) (_mBase + _bufferOffset);
+    }
     glMultMatrixf(
         (GLfloat *)m
     );
@@ -2661,16 +2990,23 @@
 static void
 android_glMultMatrixx___3II
   (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *m_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2687,6 +3023,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMultMatrixx ( const GLfixed *m ) */
@@ -2694,10 +3033,15 @@
 android_glMultMatrixx__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
-    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfixed *) (_mBase + _bufferOffset);
+    }
     glMultMatrixx(
         (GLfixed *)m
     );
@@ -2759,6 +3103,7 @@
 android_glNormalPointerBounds__IILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -2870,12 +3215,16 @@
 static void
 android_glReadPixels__IIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint x, jint y, jint width, jint height, jint format, jint type, jobject pixels_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
-    pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+    pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    if (pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
+    }
     glReadPixels(
         (GLint)x,
         (GLint)y,
@@ -2886,7 +3235,7 @@
         (GLvoid *)pixels
     );
     if (_array) {
-        releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, pixels, JNI_TRUE);
     }
 }
 
@@ -3013,6 +3362,7 @@
 android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -3046,16 +3396,23 @@
 static void
 android_glTexEnvfv__II_3FI
   (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3082,7 +3439,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -3100,17 +3459,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnvfv ( GLenum target, GLenum pname, const GLfloat *params ) */
 static void
 android_glTexEnvfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -3134,9 +3500,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glTexEnvfv(
         (GLenum)target,
         (GLenum)pname,
@@ -3147,6 +3519,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnvx ( GLenum target, GLenum pname, GLfixed param ) */
@@ -3164,16 +3539,23 @@
 static void
 android_glTexEnvxv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3200,7 +3582,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -3218,17 +3602,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnvxv ( GLenum target, GLenum pname, const GLfixed *params ) */
 static void
 android_glTexEnvxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -3252,9 +3643,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glTexEnvxv(
         (GLenum)target,
         (GLenum)pname,
@@ -3265,6 +3662,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexImage2D ( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) */
@@ -3272,11 +3672,16 @@
 android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint format, jint type, jobject pixels_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
     if (pixels_buf) {
-        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    }
+    if (pixels_buf && pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
     }
     glTexImage2D(
         (GLenum)target,
@@ -3321,11 +3726,16 @@
 android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint type, jobject pixels_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
     if (pixels_buf) {
-        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    }
+    if (pixels_buf && pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
     }
     glTexSubImage2D(
         (GLenum)target,
@@ -3370,6 +3780,7 @@
 android_glVertexPointerBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
diff --git a/core/jni/android_opengl_GLES10Ext.cpp b/core/jni/android_opengl_GLES10Ext.cpp
index 1154cef..1cd8e44 100644
--- a/core/jni/android_opengl_GLES10Ext.cpp
+++ b/core/jni/android_opengl_GLES10Ext.cpp
@@ -63,14 +63,12 @@
 
 
 static void *
-getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
 {
     jint position;
     jint limit;
     jint elementSizeShift;
     jlong pointer;
-    jint offset;
-    void *data;
 
     position = _env->GetIntField(buffer, positionID);
     limit = _env->GetIntField(buffer, limitID);
@@ -85,11 +83,10 @@
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
-    offset = _env->CallStaticIntMethod(nioAccessClass,
+    *offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
-    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
 
-    return (void *) ((char *) data + offset);
+    return NULL;
 }
 
 
@@ -106,6 +103,8 @@
 android_glQueryMatrixxOES___3II_3II
   (JNIEnv *_env, jobject _this, jintArray mantissa_ref, jint mantissaOffset, jintArray exponent_ref, jint exponentOffset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLbitfield _returnValue = -1;
     GLfixed *mantissa_base = (GLfixed *) 0;
     jint _mantissaRemaining;
@@ -116,18 +115,21 @@
 
     if (!mantissa_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "mantissa == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "mantissa == null";
         goto exit;
     }
     if (mantissaOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "mantissaOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "mantissaOffset < 0";
         goto exit;
     }
     _mantissaRemaining = _env->GetArrayLength(mantissa_ref) - mantissaOffset;
     if (_mantissaRemaining < 16) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - mantissaOffset < 16");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - mantissaOffset < 16 < needed";
         goto exit;
     }
     mantissa_base = (GLfixed *)
@@ -136,18 +138,21 @@
 
     if (!exponent_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "exponent == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "exponent == null";
         goto exit;
     }
     if (exponentOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "exponentOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "exponentOffset < 0";
         goto exit;
     }
     _exponentRemaining = _env->GetArrayLength(exponent_ref) - exponentOffset;
     if (_exponentRemaining < 16) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - exponentOffset < 16");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - exponentOffset < 16 < needed";
         goto exit;
     }
     exponent_base = (GLint *)
@@ -168,6 +173,9 @@
         _env->ReleasePrimitiveArrayCritical(mantissa_ref, mantissa_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
     return _returnValue;
 }
 
@@ -176,37 +184,54 @@
 android_glQueryMatrixxOES__Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject mantissa_buf, jobject exponent_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _mantissaArray = (jarray) 0;
+    jint _mantissaBufferOffset = (jint) 0;
     jarray _exponentArray = (jarray) 0;
+    jint _exponentBufferOffset = (jint) 0;
     GLbitfield _returnValue = -1;
     jint _mantissaRemaining;
     GLfixed *mantissa = (GLfixed *) 0;
     jint _exponentRemaining;
     GLint *exponent = (GLint *) 0;
 
-    mantissa = (GLfixed *)getPointer(_env, mantissa_buf, &_mantissaArray, &_mantissaRemaining);
+    mantissa = (GLfixed *)getPointer(_env, mantissa_buf, &_mantissaArray, &_mantissaRemaining, &_mantissaBufferOffset);
     if (_mantissaRemaining < 16) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 16");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 16 < needed";
         goto exit;
     }
-    exponent = (GLint *)getPointer(_env, exponent_buf, &_exponentArray, &_exponentRemaining);
+    exponent = (GLint *)getPointer(_env, exponent_buf, &_exponentArray, &_exponentRemaining, &_exponentBufferOffset);
     if (_exponentRemaining < 16) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 16");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 16 < needed";
         goto exit;
     }
+    if (mantissa == NULL) {
+        char * _mantissaBase = (char *)_env->GetPrimitiveArrayCritical(_mantissaArray, (jboolean *) 0);
+        mantissa = (GLfixed *) (_mantissaBase + _mantissaBufferOffset);
+    }
+    if (exponent == NULL) {
+        char * _exponentBase = (char *)_env->GetPrimitiveArrayCritical(_exponentArray, (jboolean *) 0);
+        exponent = (GLint *) (_exponentBase + _exponentBufferOffset);
+    }
     _returnValue = glQueryMatrixxOES(
         (GLfixed *)mantissa,
         (GLint *)exponent
     );
 
 exit:
-    if (_mantissaArray) {
-        releasePointer(_env, _mantissaArray, exponent, _exception ? JNI_FALSE : JNI_TRUE);
-    }
     if (_exponentArray) {
-        releasePointer(_env, _exponentArray, mantissa, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _exponentArray, exponent, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+    if (_mantissaArray) {
+        releasePointer(_env, _mantissaArray, mantissa, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
     }
     return _returnValue;
 }
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
index d038f20..1e6ceb3 100644
--- a/core/jni/android_opengl_GLES11.cpp
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -70,14 +70,12 @@
 
 
 static void *
-getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
 {
     jint position;
     jint limit;
     jint elementSizeShift;
     jlong pointer;
-    jint offset;
-    void *data;
 
     position = _env->GetIntField(buffer, positionID);
     limit = _env->GetIntField(buffer, limitID);
@@ -92,11 +90,10 @@
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
-    offset = _env->CallStaticIntMethod(nioAccessClass,
+    *offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
-    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
 
-    return (void *) ((char *) data + offset);
+    return NULL;
 }
 
 
@@ -136,17 +133,27 @@
 static void
 android_glBufferData__IILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint target, jint size, jobject data_buf, jint usage) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
     if (data_buf) {
-        data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+        data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
         if (_remaining < size) {
-            jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "remaining() < size < needed";
             goto exit;
         }
     }
+    if (data_buf && data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glBufferData(
         (GLenum)target,
         (GLsizeiptr)size,
@@ -158,21 +165,34 @@
     if (_array) {
         releasePointer(_env, _array, data, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glBufferSubData ( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data ) */
 static void
 android_glBufferSubData__IIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint offset, jint size, jobject data_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < size) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < size < needed";
         goto exit;
     }
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glBufferSubData(
         (GLenum)target,
         (GLintptr)offset,
@@ -184,22 +204,32 @@
     if (_array) {
         releasePointer(_env, _array, data, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
 static void
 android_glClipPlanef__I_3FI
   (JNIEnv *_env, jobject _this, jint plane, jfloatArray equation_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *equation_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *equation = (GLfloat *) 0;
 
     if (!equation_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "equation == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
@@ -217,17 +247,28 @@
         _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
 static void
 android_glClipPlanef__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *equation = (GLfloat *) 0;
 
-    equation = (GLfloat *)getPointer(_env, equation_buf, &_array, &_remaining);
+    equation = (GLfloat *)getPointer(_env, equation_buf, &_array, &_remaining, &_bufferOffset);
+    if (equation == NULL) {
+        char * _equationBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        equation = (GLfloat *) (_equationBase + _bufferOffset);
+    }
     glClipPlanef(
         (GLenum)plane,
         (GLfloat *)equation
@@ -235,22 +276,32 @@
     if (_array) {
         releasePointer(_env, _array, equation, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanex ( GLenum plane, const GLfixed *equation ) */
 static void
 android_glClipPlanex__I_3II
   (JNIEnv *_env, jobject _this, jint plane, jintArray equation_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *equation_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *equation = (GLfixed *) 0;
 
     if (!equation_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "equation == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
@@ -268,17 +319,28 @@
         _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanex ( GLenum plane, const GLfixed *equation ) */
 static void
 android_glClipPlanex__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *equation = (GLfixed *) 0;
 
-    equation = (GLfixed *)getPointer(_env, equation_buf, &_array, &_remaining);
+    equation = (GLfixed *)getPointer(_env, equation_buf, &_array, &_remaining, &_bufferOffset);
+    if (equation == NULL) {
+        char * _equationBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        equation = (GLfixed *) (_equationBase + _bufferOffset);
+    }
     glClipPlanex(
         (GLenum)plane,
         (GLfixed *)equation
@@ -286,6 +348,9 @@
     if (_array) {
         releasePointer(_env, _array, equation, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glColor4ub ( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha ) */
@@ -316,21 +381,30 @@
 static void
 android_glDeleteBuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray buffers_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *buffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
     if (!buffers_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "buffers == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -347,21 +421,34 @@
         _env->ReleasePrimitiveArrayCritical(buffers_ref, buffers_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteBuffers ( GLsizei n, const GLuint *buffers ) */
 static void
 android_glDeleteBuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject buffers_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
-    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
+    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (buffers == NULL) {
+        char * _buffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        buffers = (GLuint *) (_buffersBase + _bufferOffset);
+    }
     glDeleteBuffers(
         (GLsizei)n,
         (GLuint *)buffers
@@ -371,18 +458,27 @@
     if (_array) {
         releasePointer(_env, _array, buffers, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawElements ( GLenum mode, GLsizei count, GLenum type, GLint offset ) */
 static void
 android_glDrawElements__IIII
   (JNIEnv *_env, jobject _this, jint mode, jint count, jint type, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     glDrawElements(
         (GLenum)mode,
         (GLsizei)count,
         (GLenum)type,
         (const GLvoid *)offset
     );
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenBuffers ( GLsizei n, GLuint *buffers ) */
@@ -390,24 +486,29 @@
 android_glGenBuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray buffers_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *buffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
     if (!buffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "buffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -424,6 +525,9 @@
         _env->ReleasePrimitiveArrayCritical(buffers_ref, buffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenBuffers ( GLsizei n, GLuint *buffers ) */
@@ -431,16 +535,24 @@
 android_glGenBuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject buffers_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
-    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
+    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (buffers == NULL) {
+        char * _buffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        buffers = (GLuint *) (_buffersBase + _bufferOffset);
+    }
     glGenBuffers(
         (GLsizei)n,
         (GLuint *)buffers
@@ -450,6 +562,9 @@
     if (_array) {
         releasePointer(_env, _array, buffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetBooleanv ( GLenum pname, GLboolean *params ) */
@@ -457,18 +572,22 @@
 android_glGetBooleanv__I_3ZI
   (JNIEnv *_env, jobject _this, jint pname, jbooleanArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLboolean *params_base = (GLboolean *) 0;
     jint _remaining;
     GLboolean *params = (GLboolean *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -486,24 +605,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetBooleanv ( GLenum pname, GLboolean *params ) */
 static void
 android_glGetBooleanv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLboolean *params = (GLboolean *) 0;
 
-    params = (GLboolean *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLboolean *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLboolean *) (_paramsBase + _bufferOffset);
+    }
     glGetBooleanv(
         (GLenum)pname,
         (GLboolean *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -512,24 +638,29 @@
 android_glGetBufferParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -547,6 +678,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetBufferParameteriv ( GLenum target, GLenum pname, GLint *params ) */
@@ -554,16 +688,24 @@
 android_glGetBufferParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetBufferParameteriv(
         (GLenum)target,
         (GLenum)pname,
@@ -574,6 +716,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetClipPlanef ( GLenum pname, GLfloat *eqn ) */
@@ -581,18 +726,22 @@
 android_glGetClipPlanef__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray eqn_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *eqn_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *eqn = (GLfloat *) 0;
 
     if (!eqn_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "eqn == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
@@ -610,24 +759,31 @@
         _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetClipPlanef ( GLenum pname, GLfloat *eqn ) */
 static void
 android_glGetClipPlanef__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *eqn = (GLfloat *) 0;
 
-    eqn = (GLfloat *)getPointer(_env, eqn_buf, &_array, &_remaining);
+    eqn = (GLfloat *)getPointer(_env, eqn_buf, &_array, &_remaining, &_bufferOffset);
+    if (eqn == NULL) {
+        char * _eqnBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        eqn = (GLfloat *) (_eqnBase + _bufferOffset);
+    }
     glGetClipPlanef(
         (GLenum)pname,
         (GLfloat *)eqn
     );
     if (_array) {
-        releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, eqn, JNI_TRUE);
     }
 }
 
@@ -636,18 +792,22 @@
 android_glGetClipPlanex__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray eqn_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *eqn_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *eqn = (GLfixed *) 0;
 
     if (!eqn_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "eqn == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
@@ -665,24 +825,31 @@
         _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetClipPlanex ( GLenum pname, GLfixed *eqn ) */
 static void
 android_glGetClipPlanex__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *eqn = (GLfixed *) 0;
 
-    eqn = (GLfixed *)getPointer(_env, eqn_buf, &_array, &_remaining);
+    eqn = (GLfixed *)getPointer(_env, eqn_buf, &_array, &_remaining, &_bufferOffset);
+    if (eqn == NULL) {
+        char * _eqnBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        eqn = (GLfixed *) (_eqnBase + _bufferOffset);
+    }
     glGetClipPlanex(
         (GLenum)pname,
         (GLfixed *)eqn
     );
     if (_array) {
-        releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, eqn, JNI_TRUE);
     }
 }
 
@@ -691,18 +858,22 @@
 android_glGetFixedv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -720,24 +891,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFixedv ( GLenum pname, GLfixed *params ) */
 static void
 android_glGetFixedv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetFixedv(
         (GLenum)pname,
         (GLfixed *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -746,18 +924,22 @@
 android_glGetFloatv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -775,24 +957,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFloatv ( GLenum pname, GLfloat *params ) */
 static void
 android_glGetFloatv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetFloatv(
         (GLenum)pname,
         (GLfloat *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -801,18 +990,22 @@
 android_glGetLightfv__II_3FI
   (JNIEnv *_env, jobject _this, jint light, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -860,7 +1053,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -878,6 +1072,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetLightfv ( GLenum light, GLenum pname, GLfloat *params ) */
@@ -885,11 +1082,14 @@
 android_glGetLightfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SPOT_EXPONENT)
@@ -934,9 +1134,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetLightfv(
         (GLenum)light,
         (GLenum)pname,
@@ -947,6 +1152,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetLightxv ( GLenum light, GLenum pname, GLfixed *params ) */
@@ -954,18 +1162,22 @@
 android_glGetLightxv__II_3II
   (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1013,7 +1225,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1031,6 +1244,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetLightxv ( GLenum light, GLenum pname, GLfixed *params ) */
@@ -1038,11 +1254,14 @@
 android_glGetLightxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SPOT_EXPONENT)
@@ -1087,9 +1306,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetLightxv(
         (GLenum)light,
         (GLenum)pname,
@@ -1100,6 +1324,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialfv ( GLenum face, GLenum pname, GLfloat *params ) */
@@ -1107,18 +1334,22 @@
 android_glGetMaterialfv__II_3FI
   (JNIEnv *_env, jobject _this, jint face, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1152,7 +1383,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1170,6 +1402,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialfv ( GLenum face, GLenum pname, GLfloat *params ) */
@@ -1177,11 +1412,14 @@
 android_glGetMaterialfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SHININESS)
@@ -1212,9 +1450,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetMaterialfv(
         (GLenum)face,
         (GLenum)pname,
@@ -1225,6 +1468,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialxv ( GLenum face, GLenum pname, GLfixed *params ) */
@@ -1232,18 +1478,22 @@
 android_glGetMaterialxv__II_3II
   (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1277,7 +1527,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1295,6 +1546,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialxv ( GLenum face, GLenum pname, GLfixed *params ) */
@@ -1302,11 +1556,14 @@
 android_glGetMaterialxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SHININESS)
@@ -1337,9 +1594,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetMaterialxv(
         (GLenum)face,
         (GLenum)pname,
@@ -1350,6 +1612,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnvfv ( GLenum env, GLenum pname, GLfloat *params ) */
@@ -1357,18 +1622,22 @@
 android_glGetTexEnvfv__II_3FI
   (JNIEnv *_env, jobject _this, jint env, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1396,7 +1665,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1414,6 +1684,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnvfv ( GLenum env, GLenum pname, GLfloat *params ) */
@@ -1421,11 +1694,14 @@
 android_glGetTexEnvfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -1450,9 +1726,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetTexEnvfv(
         (GLenum)env,
         (GLenum)pname,
@@ -1463,6 +1744,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnviv ( GLenum env, GLenum pname, GLint *params ) */
@@ -1470,18 +1754,22 @@
 android_glGetTexEnviv__II_3II
   (JNIEnv *_env, jobject _this, jint env, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1509,7 +1797,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -1527,6 +1816,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnviv ( GLenum env, GLenum pname, GLint *params ) */
@@ -1534,11 +1826,14 @@
 android_glGetTexEnviv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -1563,9 +1858,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetTexEnviv(
         (GLenum)env,
         (GLenum)pname,
@@ -1576,6 +1876,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnvxv ( GLenum env, GLenum pname, GLfixed *params ) */
@@ -1583,18 +1886,22 @@
 android_glGetTexEnvxv__II_3II
   (JNIEnv *_env, jobject _this, jint env, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1622,7 +1929,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1640,6 +1948,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnvxv ( GLenum env, GLenum pname, GLfixed *params ) */
@@ -1647,11 +1958,14 @@
 android_glGetTexEnvxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -1676,9 +1990,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetTexEnvxv(
         (GLenum)env,
         (GLenum)pname,
@@ -1689,6 +2008,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params ) */
@@ -1696,24 +2018,29 @@
 android_glGetTexParameterfv__II_3FI
   (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1731,6 +2058,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params ) */
@@ -1738,16 +2068,24 @@
 android_glGetTexParameterfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameterfv(
         (GLenum)target,
         (GLenum)pname,
@@ -1758,6 +2096,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params ) */
@@ -1765,24 +2106,29 @@
 android_glGetTexParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -1800,6 +2146,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params ) */
@@ -1807,16 +2156,24 @@
 android_glGetTexParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameteriv(
         (GLenum)target,
         (GLenum)pname,
@@ -1827,6 +2184,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterxv ( GLenum target, GLenum pname, GLfixed *params ) */
@@ -1834,24 +2194,29 @@
 android_glGetTexParameterxv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1869,6 +2234,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterxv ( GLenum target, GLenum pname, GLfixed *params ) */
@@ -1876,16 +2244,24 @@
 android_glGetTexParameterxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameterxv(
         (GLenum)target,
         (GLenum)pname,
@@ -1896,6 +2272,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* GLboolean glIsBuffer ( GLuint buffer ) */
@@ -1956,21 +2335,30 @@
 static void
 android_glPointParameterfv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1987,21 +2375,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointParameterfv ( GLenum pname, const GLfloat *params ) */
 static void
 android_glPointParameterfv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glPointParameterfv(
         (GLenum)pname,
         (GLfloat *)params
@@ -2011,6 +2412,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointParameterx ( GLenum pname, GLfixed param ) */
@@ -2027,21 +2431,30 @@
 static void
 android_glPointParameterxv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2058,21 +2471,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointParameterxv ( GLenum pname, const GLfixed *params ) */
 static void
 android_glPointParameterxv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glPointParameterxv(
         (GLenum)pname,
         (GLfixed *)params
@@ -2082,6 +2508,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointSizePointerOES ( GLenum type, GLsizei stride, const GLvoid *pointer ) */
@@ -2089,6 +2518,7 @@
 android_glPointSizePointerOESBounds__IILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -2133,16 +2563,23 @@
 static void
 android_glTexEnviv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2169,7 +2606,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -2187,17 +2626,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnviv ( GLenum target, GLenum pname, const GLint *params ) */
 static void
 android_glTexEnviv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -2221,9 +2667,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glTexEnviv(
         (GLenum)target,
         (GLenum)pname,
@@ -2234,27 +2686,39 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params ) */
 static void
 android_glTexParameterfv__II_3FI
   (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -2272,21 +2736,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params ) */
 static void
 android_glTexParameterfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glTexParameterfv(
         (GLenum)target,
         (GLenum)pname,
@@ -2297,6 +2774,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameteri ( GLenum target, GLenum pname, GLint param ) */
@@ -2314,21 +2794,30 @@
 static void
 android_glTexParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -2346,21 +2835,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameteriv ( GLenum target, GLenum pname, const GLint *params ) */
 static void
 android_glTexParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glTexParameteriv(
         (GLenum)target,
         (GLenum)pname,
@@ -2371,27 +2873,39 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterxv ( GLenum target, GLenum pname, const GLfixed *params ) */
 static void
 android_glTexParameterxv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2409,21 +2923,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterxv ( GLenum target, GLenum pname, const GLfixed *params ) */
 static void
 android_glTexParameterxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glTexParameterxv(
         (GLenum)target,
         (GLenum)pname,
@@ -2434,6 +2961,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glVertexPointer ( GLint size, GLenum type, GLsizei stride, GLint offset ) */
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
index d6dc0fe..073bbb2 100644
--- a/core/jni/android_opengl_GLES11Ext.cpp
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -72,14 +72,12 @@
 
 
 static void *
-getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
 {
     jint position;
     jint limit;
     jint elementSizeShift;
     jlong pointer;
-    jint offset;
-    void *data;
 
     position = _env->GetIntField(buffer, positionID);
     limit = _env->GetIntField(buffer, limitID);
@@ -94,11 +92,9 @@
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
-    offset = _env->CallStaticIntMethod(nioAccessClass,
+    *offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
-    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-
-    return (void *) ((char *) data + offset);
+    return NULL;
 }
 
 
@@ -197,21 +193,30 @@
 static void
 android_glDrawTexsvOES___3SI
   (JNIEnv *_env, jobject _this, jshortArray coords_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLshort *coords_base = (GLshort *) 0;
     jint _remaining;
     GLshort *coords = (GLshort *) 0;
 
     if (!coords_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "coords == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 5 < needed";
         goto exit;
     }
     coords_base = (GLshort *)
@@ -227,21 +232,34 @@
         _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexsvOES ( const GLshort *coords ) */
 static void
 android_glDrawTexsvOES__Ljava_nio_ShortBuffer_2
   (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLshort *coords = (GLshort *) 0;
 
-    coords = (GLshort *)getPointer(_env, coords_buf, &_array, &_remaining);
+    coords = (GLshort *)getPointer(_env, coords_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 5 < needed";
         goto exit;
     }
+    if (coords == NULL) {
+        char * _coordsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        coords = (GLshort *) (_coordsBase + _bufferOffset);
+    }
     glDrawTexsvOES(
         (GLshort *)coords
     );
@@ -250,27 +268,39 @@
     if (_array) {
         releasePointer(_env, _array, coords, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexivOES ( const GLint *coords ) */
 static void
 android_glDrawTexivOES___3II
   (JNIEnv *_env, jobject _this, jintArray coords_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *coords_base = (GLint *) 0;
     jint _remaining;
     GLint *coords = (GLint *) 0;
 
     if (!coords_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "coords == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 5 < needed";
         goto exit;
     }
     coords_base = (GLint *)
@@ -286,21 +316,34 @@
         _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexivOES ( const GLint *coords ) */
 static void
 android_glDrawTexivOES__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *coords = (GLint *) 0;
 
-    coords = (GLint *)getPointer(_env, coords_buf, &_array, &_remaining);
+    coords = (GLint *)getPointer(_env, coords_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 5 < needed";
         goto exit;
     }
+    if (coords == NULL) {
+        char * _coordsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        coords = (GLint *) (_coordsBase + _bufferOffset);
+    }
     glDrawTexivOES(
         (GLint *)coords
     );
@@ -309,27 +352,39 @@
     if (_array) {
         releasePointer(_env, _array, coords, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexxvOES ( const GLfixed *coords ) */
 static void
 android_glDrawTexxvOES___3II
   (JNIEnv *_env, jobject _this, jintArray coords_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *coords_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *coords = (GLfixed *) 0;
 
     if (!coords_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "coords == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 5 < needed";
         goto exit;
     }
     coords_base = (GLfixed *)
@@ -345,21 +400,34 @@
         _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexxvOES ( const GLfixed *coords ) */
 static void
 android_glDrawTexxvOES__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *coords = (GLfixed *) 0;
 
-    coords = (GLfixed *)getPointer(_env, coords_buf, &_array, &_remaining);
+    coords = (GLfixed *)getPointer(_env, coords_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 5 < needed";
         goto exit;
     }
+    if (coords == NULL) {
+        char * _coordsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        coords = (GLfixed *) (_coordsBase + _bufferOffset);
+    }
     glDrawTexxvOES(
         (GLfixed *)coords
     );
@@ -368,6 +436,9 @@
     if (_array) {
         releasePointer(_env, _array, coords, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexfOES ( GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height ) */
@@ -387,21 +458,30 @@
 static void
 android_glDrawTexfvOES___3FI
   (JNIEnv *_env, jobject _this, jfloatArray coords_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *coords_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *coords = (GLfloat *) 0;
 
     if (!coords_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "coords == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 5 < needed";
         goto exit;
     }
     coords_base = (GLfloat *)
@@ -417,21 +497,34 @@
         _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexfvOES ( const GLfloat *coords ) */
 static void
 android_glDrawTexfvOES__Ljava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *coords = (GLfloat *) 0;
 
-    coords = (GLfloat *)getPointer(_env, coords_buf, &_array, &_remaining);
+    coords = (GLfloat *)getPointer(_env, coords_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 5 < needed";
         goto exit;
     }
+    if (coords == NULL) {
+        char * _coordsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        coords = (GLfloat *) (_coordsBase + _bufferOffset);
+    }
     glDrawTexfvOES(
         (GLfloat *)coords
     );
@@ -440,24 +533,31 @@
     if (_array) {
         releasePointer(_env, _array, coords, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glEGLImageTargetTexture2DOES ( GLenum target, GLeglImageOES image ) */
 static void
 android_glEGLImageTargetTexture2DOES__ILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jobject image_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLeglImageOES image = (GLeglImageOES) 0;
 
-    image = (GLeglImageOES)getPointer(_env, image_buf, &_array, &_remaining);
+    image = (GLeglImageOES)getPointer(_env, image_buf, &_array, &_remaining, &_bufferOffset);
+    if (image == NULL) {
+        char * _imageBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        image = (GLeglImageOES) (_imageBase + _bufferOffset);
+    }
     glEGLImageTargetTexture2DOES(
         (GLenum)target,
         (GLeglImageOES)image
     );
     if (_array) {
-        releasePointer(_env, _array, image, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, image, JNI_TRUE);
     }
 }
 
@@ -465,18 +565,22 @@
 static void
 android_glEGLImageTargetRenderbufferStorageOES__ILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jobject image_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLeglImageOES image = (GLeglImageOES) 0;
 
-    image = (GLeglImageOES)getPointer(_env, image_buf, &_array, &_remaining);
+    image = (GLeglImageOES)getPointer(_env, image_buf, &_array, &_remaining, &_bufferOffset);
+    if (image == NULL) {
+        char * _imageBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        image = (GLeglImageOES) (_imageBase + _bufferOffset);
+    }
     glEGLImageTargetRenderbufferStorageOES(
         (GLenum)target,
         (GLeglImageOES)image
     );
     if (_array) {
-        releasePointer(_env, _array, image, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, image, JNI_TRUE);
     }
 }
 
@@ -515,16 +619,23 @@
 static void
 android_glClipPlanexOES__I_3II
   (JNIEnv *_env, jobject _this, jint plane, jintArray equation_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *equation_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *equation = (GLfixed *) 0;
 
     if (!equation_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "equation == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
@@ -542,6 +653,9 @@
         _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanexOES ( GLenum plane, const GLfixed *equation ) */
@@ -549,10 +663,15 @@
 android_glClipPlanexOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *equation = (GLfixed *) 0;
 
-    equation = (GLfixed *)getPointer(_env, equation_buf, &_array, &_remaining);
+    equation = (GLfixed *)getPointer(_env, equation_buf, &_array, &_remaining, &_bufferOffset);
+    if (equation == NULL) {
+        char * _equationBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        equation = (GLfixed *) (_equationBase + _bufferOffset);
+    }
     glClipPlanexOES(
         (GLenum)plane,
         (GLfixed *)equation
@@ -598,16 +717,23 @@
 static void
 android_glFogxvOES__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -625,6 +751,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFogxvOES ( GLenum pname, const GLfixed *params ) */
@@ -632,10 +761,15 @@
 android_glFogxvOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glFogxvOES(
         (GLenum)pname,
         (GLfixed *)params
@@ -664,24 +798,29 @@
 android_glGetClipPlanexOES__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray eqn_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *eqn_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *eqn = (GLfixed *) 0;
 
     if (!eqn_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "eqn == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
     if (_remaining < 4) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 4");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 4 < needed";
         goto exit;
     }
     eqn_base = (GLfixed *)
@@ -698,6 +837,9 @@
         _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetClipPlanexOES ( GLenum pname, GLfixed *eqn ) */
@@ -705,16 +847,24 @@
 android_glGetClipPlanexOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *eqn = (GLfixed *) 0;
 
-    eqn = (GLfixed *)getPointer(_env, eqn_buf, &_array, &_remaining);
+    eqn = (GLfixed *)getPointer(_env, eqn_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 4) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 4");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 4 < needed";
         goto exit;
     }
+    if (eqn == NULL) {
+        char * _eqnBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        eqn = (GLfixed *) (_eqnBase + _bufferOffset);
+    }
     glGetClipPlanexOES(
         (GLenum)pname,
         (GLfixed *)eqn
@@ -724,6 +874,9 @@
     if (_array) {
         releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFixedvOES ( GLenum pname, GLfixed *params ) */
@@ -731,18 +884,22 @@
 android_glGetFixedvOES__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -760,24 +917,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFixedvOES ( GLenum pname, GLfixed *params ) */
 static void
 android_glGetFixedvOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetFixedvOES(
         (GLenum)pname,
         (GLfixed *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -786,18 +950,22 @@
 android_glGetLightxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -816,25 +984,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetLightxvOES ( GLenum light, GLenum pname, GLfixed *params ) */
 static void
 android_glGetLightxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetLightxvOES(
         (GLenum)light,
         (GLenum)pname,
         (GLfixed *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -843,18 +1018,22 @@
 android_glGetMaterialxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -873,25 +1052,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialxvOES ( GLenum face, GLenum pname, GLfixed *params ) */
 static void
 android_glGetMaterialxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetMaterialxvOES(
         (GLenum)face,
         (GLenum)pname,
         (GLfixed *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -900,18 +1086,22 @@
 android_glGetTexEnvxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint env, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -930,25 +1120,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnvxvOES ( GLenum env, GLenum pname, GLfixed *params ) */
 static void
 android_glGetTexEnvxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetTexEnvxvOES(
         (GLenum)env,
         (GLenum)pname,
         (GLfixed *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -957,18 +1154,22 @@
 android_glGetTexParameterxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -987,25 +1188,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterxvOES ( GLenum target, GLenum pname, GLfixed *params ) */
 static void
 android_glGetTexParameterxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameterxvOES(
         (GLenum)target,
         (GLenum)pname,
         (GLfixed *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -1023,16 +1231,23 @@
 static void
 android_glLightModelxvOES__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1050,6 +1265,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightModelxvOES ( GLenum pname, const GLfixed *params ) */
@@ -1057,10 +1275,15 @@
 android_glLightModelxvOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glLightModelxvOES(
         (GLenum)pname,
         (GLfixed *)params
@@ -1085,16 +1308,23 @@
 static void
 android_glLightxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1113,6 +1343,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightxvOES ( GLenum light, GLenum pname, const GLfixed *params ) */
@@ -1120,10 +1353,15 @@
 android_glLightxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glLightxvOES(
         (GLenum)light,
         (GLenum)pname,
@@ -1147,16 +1385,23 @@
 static void
 android_glLoadMatrixxOES___3II
   (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *m_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -1173,6 +1418,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLoadMatrixxOES ( const GLfixed *m ) */
@@ -1180,10 +1428,15 @@
 android_glLoadMatrixxOES__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
-    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfixed *) (_mBase + _bufferOffset);
+    }
     glLoadMatrixxOES(
         (GLfixed *)m
     );
@@ -1207,16 +1460,23 @@
 static void
 android_glMaterialxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1235,6 +1495,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMaterialxvOES ( GLenum face, GLenum pname, const GLfixed *params ) */
@@ -1242,10 +1505,15 @@
 android_glMaterialxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glMaterialxvOES(
         (GLenum)face,
         (GLenum)pname,
@@ -1260,16 +1528,23 @@
 static void
 android_glMultMatrixxOES___3II
   (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *m_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -1286,6 +1561,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMultMatrixxOES ( const GLfixed *m ) */
@@ -1293,10 +1571,15 @@
 android_glMultMatrixxOES__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
-    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfixed *) (_mBase + _bufferOffset);
+    }
     glMultMatrixxOES(
         (GLfixed *)m
     );
@@ -1357,16 +1640,23 @@
 static void
 android_glPointParameterxvOES__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1384,6 +1674,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointParameterxvOES ( GLenum pname, const GLfixed *params ) */
@@ -1391,10 +1684,15 @@
 android_glPointParameterxvOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glPointParameterxvOES(
         (GLenum)pname,
         (GLfixed *)params
@@ -1471,16 +1769,23 @@
 static void
 android_glTexEnvxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1499,6 +1804,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnvxvOES ( GLenum target, GLenum pname, const GLfixed *params ) */
@@ -1506,10 +1814,15 @@
 android_glTexEnvxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glTexEnvxvOES(
         (GLenum)target,
         (GLenum)pname,
@@ -1535,16 +1848,23 @@
 static void
 android_glTexParameterxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1563,6 +1883,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterxvOES ( GLenum target, GLenum pname, const GLfixed *params ) */
@@ -1570,10 +1893,15 @@
 android_glTexParameterxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glTexParameterxvOES(
         (GLenum)target,
         (GLenum)pname,
@@ -1620,21 +1948,30 @@
 static void
 android_glDeleteRenderbuffersOES__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *renderbuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
     if (!renderbuffers_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "renderbuffers == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     renderbuffers_base = (GLuint *)
@@ -1651,21 +1988,34 @@
         _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteRenderbuffersOES ( GLsizei n, const GLuint *renderbuffers ) */
 static void
 android_glDeleteRenderbuffersOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
-    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (renderbuffers == NULL) {
+        char * _renderbuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        renderbuffers = (GLuint *) (_renderbuffersBase + _bufferOffset);
+    }
     glDeleteRenderbuffersOES(
         (GLsizei)n,
         (GLuint *)renderbuffers
@@ -1675,6 +2025,9 @@
     if (_array) {
         releasePointer(_env, _array, renderbuffers, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenRenderbuffersOES ( GLsizei n, GLuint *renderbuffers ) */
@@ -1682,24 +2035,29 @@
 android_glGenRenderbuffersOES__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *renderbuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
     if (!renderbuffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "renderbuffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     renderbuffers_base = (GLuint *)
@@ -1716,6 +2074,9 @@
         _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenRenderbuffersOES ( GLsizei n, GLuint *renderbuffers ) */
@@ -1723,16 +2084,24 @@
 android_glGenRenderbuffersOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
-    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (renderbuffers == NULL) {
+        char * _renderbuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        renderbuffers = (GLuint *) (_renderbuffersBase + _bufferOffset);
+    }
     glGenRenderbuffersOES(
         (GLsizei)n,
         (GLuint *)renderbuffers
@@ -1742,6 +2111,9 @@
     if (_array) {
         releasePointer(_env, _array, renderbuffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glRenderbufferStorageOES ( GLenum target, GLenum internalformat, GLsizei width, GLsizei height ) */
@@ -1761,24 +2133,29 @@
 android_glGetRenderbufferParameterivOES__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -1796,6 +2173,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetRenderbufferParameterivOES ( GLenum target, GLenum pname, GLint *params ) */
@@ -1803,16 +2183,24 @@
 android_glGetRenderbufferParameterivOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetRenderbufferParameterivOES(
         (GLenum)target,
         (GLenum)pname,
@@ -1823,6 +2211,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* GLboolean glIsFramebufferOES ( GLuint framebuffer ) */
@@ -1850,21 +2241,30 @@
 static void
 android_glDeleteFramebuffersOES__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *framebuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
     if (!framebuffers_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "framebuffers == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     framebuffers_base = (GLuint *)
@@ -1881,21 +2281,34 @@
         _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteFramebuffersOES ( GLsizei n, const GLuint *framebuffers ) */
 static void
 android_glDeleteFramebuffersOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
-    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (framebuffers == NULL) {
+        char * _framebuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        framebuffers = (GLuint *) (_framebuffersBase + _bufferOffset);
+    }
     glDeleteFramebuffersOES(
         (GLsizei)n,
         (GLuint *)framebuffers
@@ -1905,6 +2318,9 @@
     if (_array) {
         releasePointer(_env, _array, framebuffers, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenFramebuffersOES ( GLsizei n, GLuint *framebuffers ) */
@@ -1912,24 +2328,29 @@
 android_glGenFramebuffersOES__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *framebuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
     if (!framebuffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "framebuffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     framebuffers_base = (GLuint *)
@@ -1946,6 +2367,9 @@
         _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenFramebuffersOES ( GLsizei n, GLuint *framebuffers ) */
@@ -1953,16 +2377,24 @@
 android_glGenFramebuffersOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
-    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (framebuffers == NULL) {
+        char * _framebuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        framebuffers = (GLuint *) (_framebuffersBase + _bufferOffset);
+    }
     glGenFramebuffersOES(
         (GLsizei)n,
         (GLuint *)framebuffers
@@ -1972,6 +2404,9 @@
     if (_array) {
         releasePointer(_env, _array, framebuffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* GLenum glCheckFramebufferStatusOES ( GLenum target ) */
@@ -2015,24 +2450,29 @@
 android_glGetFramebufferAttachmentParameterivOES__III_3II
   (JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -2051,6 +2491,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFramebufferAttachmentParameterivOES ( GLenum target, GLenum attachment, GLenum pname, GLint *params ) */
@@ -2058,16 +2501,24 @@
 android_glGetFramebufferAttachmentParameterivOES__IIILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetFramebufferAttachmentParameterivOES(
         (GLenum)target,
         (GLenum)attachment,
@@ -2079,6 +2530,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenerateMipmapOES ( GLenum target ) */
@@ -2111,6 +2565,7 @@
 android_glMatrixIndexPointerOESBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -2134,6 +2589,7 @@
 android_glWeightPointerOESBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -2194,16 +2650,23 @@
 static void
 android_glClipPlanefOES__I_3FI
   (JNIEnv *_env, jobject _this, jint plane, jfloatArray equation_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *equation_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *equation = (GLfloat *) 0;
 
     if (!equation_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "equation == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
@@ -2221,6 +2684,9 @@
         _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanefOES ( GLenum plane, const GLfloat *equation ) */
@@ -2228,10 +2694,15 @@
 android_glClipPlanefOES__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *equation = (GLfloat *) 0;
 
-    equation = (GLfloat *)getPointer(_env, equation_buf, &_array, &_remaining);
+    equation = (GLfloat *)getPointer(_env, equation_buf, &_array, &_remaining, &_bufferOffset);
+    if (equation == NULL) {
+        char * _equationBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        equation = (GLfloat *) (_equationBase + _bufferOffset);
+    }
     glClipPlanefOES(
         (GLenum)plane,
         (GLfloat *)equation
@@ -2246,24 +2717,29 @@
 android_glGetClipPlanefOES__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray eqn_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *eqn_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *eqn = (GLfloat *) 0;
 
     if (!eqn_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "eqn == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
     if (_remaining < 4) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 4");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 4 < needed";
         goto exit;
     }
     eqn_base = (GLfloat *)
@@ -2280,6 +2756,9 @@
         _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetClipPlanefOES ( GLenum pname, GLfloat *eqn ) */
@@ -2287,16 +2766,24 @@
 android_glGetClipPlanefOES__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *eqn = (GLfloat *) 0;
 
-    eqn = (GLfloat *)getPointer(_env, eqn_buf, &_array, &_remaining);
+    eqn = (GLfloat *)getPointer(_env, eqn_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 4) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 4");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 4 < needed";
         goto exit;
     }
+    if (eqn == NULL) {
+        char * _eqnBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        eqn = (GLfloat *) (_eqnBase + _bufferOffset);
+    }
     glGetClipPlanefOES(
         (GLenum)pname,
         (GLfloat *)eqn
@@ -2306,6 +2793,9 @@
     if (_array) {
         releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClearDepthfOES ( GLclampf depth ) */
@@ -2332,16 +2822,23 @@
 static void
 android_glTexGenfvOES__II_3FI
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2360,6 +2857,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexGenfvOES ( GLenum coord, GLenum pname, const GLfloat *params ) */
@@ -2367,10 +2867,15 @@
 android_glTexGenfvOES__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glTexGenfvOES(
         (GLenum)coord,
         (GLenum)pname,
@@ -2396,16 +2901,23 @@
 static void
 android_glTexGenivOES__II_3II
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2424,6 +2936,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexGenivOES ( GLenum coord, GLenum pname, const GLint *params ) */
@@ -2431,10 +2946,15 @@
 android_glTexGenivOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glTexGenivOES(
         (GLenum)coord,
         (GLenum)pname,
@@ -2460,16 +2980,23 @@
 static void
 android_glTexGenxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2488,6 +3015,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexGenxvOES ( GLenum coord, GLenum pname, const GLfixed *params ) */
@@ -2495,10 +3025,15 @@
 android_glTexGenxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glTexGenxvOES(
         (GLenum)coord,
         (GLenum)pname,
@@ -2514,18 +3049,22 @@
 android_glGetTexGenfvOES__II_3FI
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2544,25 +3083,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexGenfvOES ( GLenum coord, GLenum pname, GLfloat *params ) */
 static void
 android_glGetTexGenfvOES__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetTexGenfvOES(
         (GLenum)coord,
         (GLenum)pname,
         (GLfloat *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -2571,18 +3117,22 @@
 android_glGetTexGenivOES__II_3II
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2601,25 +3151,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexGenivOES ( GLenum coord, GLenum pname, GLint *params ) */
 static void
 android_glGetTexGenivOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetTexGenivOES(
         (GLenum)coord,
         (GLenum)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -2628,18 +3185,22 @@
 android_glGetTexGenxvOES__II_3II
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2658,25 +3219,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexGenxvOES ( GLenum coord, GLenum pname, GLfixed *params ) */
 static void
 android_glGetTexGenxvOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetTexGenxvOES(
         (GLenum)coord,
         (GLenum)pname,
         (GLfixed *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index a53e4d7..c530117 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -63,14 +63,12 @@
 
 
 static void *
-getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
 {
     jint position;
     jint limit;
     jint elementSizeShift;
     jlong pointer;
-    jint offset;
-    void *data;
 
     position = _env->GetIntField(buffer, positionID);
     limit = _env->GetIntField(buffer, limitID);
@@ -85,11 +83,10 @@
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
-    offset = _env->CallStaticIntMethod(nioAccessClass,
+    *offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
-    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
 
-    return (void *) ((char *) data + offset);
+    return NULL;
 }
 
 
@@ -150,10 +147,14 @@
 static void
 android_glBindAttribLocation__IILjava_lang_String_2
   (JNIEnv *_env, jobject _this, jint program, jint index, jstring name) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     const char* _nativename = 0;
 
     if (!name) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "name == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "name == null";
         goto exit;
     }
     _nativename = _env->GetStringUTFChars(name, 0);
@@ -169,6 +170,9 @@
         _env->ReleaseStringUTFChars(name, _nativename);
     }
 
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glBindBuffer ( GLenum target, GLuint buffer ) */
@@ -268,17 +272,27 @@
 static void
 android_glBufferData__IILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint target, jint size, jobject data_buf, jint usage) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
     if (data_buf) {
-        data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+        data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
         if (_remaining < size) {
-            jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "remaining() < size < needed";
             goto exit;
         }
     }
+    if (data_buf && data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glBufferData(
         (GLenum)target,
         (GLsizeiptr)size,
@@ -290,21 +304,34 @@
     if (_array) {
         releasePointer(_env, _array, data, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glBufferSubData ( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data ) */
 static void
 android_glBufferSubData__IIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint offset, jint size, jobject data_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < size) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < size < needed";
         goto exit;
     }
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glBufferSubData(
         (GLenum)target,
         (GLintptr)offset,
@@ -316,6 +343,9 @@
     if (_array) {
         releasePointer(_env, _array, data, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* GLenum glCheckFramebufferStatus ( GLenum target ) */
@@ -394,10 +424,15 @@
 android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint imageSize, jobject data_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glCompressedTexImage2D(
         (GLenum)target,
         (GLint)level,
@@ -418,10 +453,15 @@
 android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint imageSize, jobject data_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glCompressedTexSubImage2D(
         (GLenum)target,
         (GLint)level,
@@ -503,21 +543,30 @@
 static void
 android_glDeleteBuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray buffers_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *buffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
     if (!buffers_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "buffers == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -534,21 +583,34 @@
         _env->ReleasePrimitiveArrayCritical(buffers_ref, buffers_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteBuffers ( GLsizei n, const GLuint *buffers ) */
 static void
 android_glDeleteBuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject buffers_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
-    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
+    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (buffers == NULL) {
+        char * _buffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        buffers = (GLuint *) (_buffersBase + _bufferOffset);
+    }
     glDeleteBuffers(
         (GLsizei)n,
         (GLuint *)buffers
@@ -558,22 +620,32 @@
     if (_array) {
         releasePointer(_env, _array, buffers, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteFramebuffers ( GLsizei n, const GLuint *framebuffers ) */
 static void
 android_glDeleteFramebuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *framebuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
     if (!framebuffers_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "framebuffers == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
@@ -591,6 +663,9 @@
         _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteFramebuffers ( GLsizei n, const GLuint *framebuffers ) */
@@ -598,10 +673,15 @@
 android_glDeleteFramebuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
-    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining, &_bufferOffset);
+    if (framebuffers == NULL) {
+        char * _framebuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        framebuffers = (GLuint *) (_framebuffersBase + _bufferOffset);
+    }
     glDeleteFramebuffers(
         (GLsizei)n,
         (GLuint *)framebuffers
@@ -624,16 +704,23 @@
 static void
 android_glDeleteRenderbuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *renderbuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
     if (!renderbuffers_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "renderbuffers == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
@@ -651,6 +738,9 @@
         _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteRenderbuffers ( GLsizei n, const GLuint *renderbuffers ) */
@@ -658,10 +748,15 @@
 android_glDeleteRenderbuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
-    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining, &_bufferOffset);
+    if (renderbuffers == NULL) {
+        char * _renderbuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        renderbuffers = (GLuint *) (_renderbuffersBase + _bufferOffset);
+    }
     glDeleteRenderbuffers(
         (GLsizei)n,
         (GLuint *)renderbuffers
@@ -684,21 +779,30 @@
 static void
 android_glDeleteTextures__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray textures_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *textures_base = (GLuint *) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
     if (!textures_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "textures == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     textures_base = (GLuint *)
@@ -715,21 +819,34 @@
         _env->ReleasePrimitiveArrayCritical(textures_ref, textures_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteTextures ( GLsizei n, const GLuint *textures ) */
 static void
 android_glDeleteTextures__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject textures_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
-    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
+    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (textures == NULL) {
+        char * _texturesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        textures = (GLuint *) (_texturesBase + _bufferOffset);
+    }
     glDeleteTextures(
         (GLsizei)n,
         (GLuint *)textures
@@ -739,6 +856,9 @@
     if (_array) {
         releasePointer(_env, _array, textures, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDepthFunc ( GLenum func ) */
@@ -812,27 +932,43 @@
 static void
 android_glDrawElements__IIII
   (JNIEnv *_env, jobject _this, jint mode, jint count, jint type, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     glDrawElements(
         (GLenum)mode,
         (GLsizei)count,
         (GLenum)type,
         (const GLvoid *)offset
     );
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawElements ( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices ) */
 static void
 android_glDrawElements__IIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint mode, jint count, jint type, jobject indices_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *indices = (GLvoid *) 0;
 
-    indices = (GLvoid *)getPointer(_env, indices_buf, &_array, &_remaining);
+    indices = (GLvoid *)getPointer(_env, indices_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < count) {
-        jniThrowException(_env, "java/lang/ArrayIndexOutOfBoundsException", "remaining() < count");
+        _exception = 1;
+        _exceptionType = "java/lang/ArrayIndexOutOfBoundsException";
+        _exceptionMessage = "remaining() < count < needed";
         goto exit;
     }
+    if (indices == NULL) {
+        char * _indicesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        indices = (GLvoid *) (_indicesBase + _bufferOffset);
+    }
     glDrawElements(
         (GLenum)mode,
         (GLsizei)count,
@@ -844,6 +980,9 @@
     if (_array) {
         releasePointer(_env, _array, indices, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glEnable ( GLenum cap ) */
@@ -917,24 +1056,29 @@
 android_glGenBuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray buffers_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *buffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
     if (!buffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "buffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -951,6 +1095,9 @@
         _env->ReleasePrimitiveArrayCritical(buffers_ref, buffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenBuffers ( GLsizei n, GLuint *buffers ) */
@@ -958,16 +1105,24 @@
 android_glGenBuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject buffers_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
-    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
+    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (buffers == NULL) {
+        char * _buffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        buffers = (GLuint *) (_buffersBase + _bufferOffset);
+    }
     glGenBuffers(
         (GLsizei)n,
         (GLuint *)buffers
@@ -977,6 +1132,9 @@
     if (_array) {
         releasePointer(_env, _array, buffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenerateMipmap ( GLenum target ) */
@@ -993,18 +1151,22 @@
 android_glGenFramebuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *framebuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
     if (!framebuffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "framebuffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
@@ -1022,24 +1184,31 @@
         _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenFramebuffers ( GLsizei n, GLuint *framebuffers ) */
 static void
 android_glGenFramebuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
-    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining, &_bufferOffset);
+    if (framebuffers == NULL) {
+        char * _framebuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        framebuffers = (GLuint *) (_framebuffersBase + _bufferOffset);
+    }
     glGenFramebuffers(
         (GLsizei)n,
         (GLuint *)framebuffers
     );
     if (_array) {
-        releasePointer(_env, _array, framebuffers, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, framebuffers, JNI_TRUE);
     }
 }
 
@@ -1048,18 +1217,22 @@
 android_glGenRenderbuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *renderbuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
     if (!renderbuffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "renderbuffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
@@ -1077,24 +1250,31 @@
         _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenRenderbuffers ( GLsizei n, GLuint *renderbuffers ) */
 static void
 android_glGenRenderbuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
-    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining, &_bufferOffset);
+    if (renderbuffers == NULL) {
+        char * _renderbuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        renderbuffers = (GLuint *) (_renderbuffersBase + _bufferOffset);
+    }
     glGenRenderbuffers(
         (GLsizei)n,
         (GLuint *)renderbuffers
     );
     if (_array) {
-        releasePointer(_env, _array, renderbuffers, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, renderbuffers, JNI_TRUE);
     }
 }
 
@@ -1103,24 +1283,29 @@
 android_glGenTextures__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray textures_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *textures_base = (GLuint *) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
     if (!textures_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "textures == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     textures_base = (GLuint *)
@@ -1137,6 +1322,9 @@
         _env->ReleasePrimitiveArrayCritical(textures_ref, textures_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenTextures ( GLsizei n, GLuint *textures ) */
@@ -1144,16 +1332,24 @@
 android_glGenTextures__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject textures_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
-    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
+    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (textures == NULL) {
+        char * _texturesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        textures = (GLuint *) (_texturesBase + _bufferOffset);
+    }
     glGenTextures(
         (GLsizei)n,
         (GLuint *)textures
@@ -1163,6 +1359,9 @@
     if (_array) {
         releasePointer(_env, _array, textures, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetActiveAttrib ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) */
@@ -1170,6 +1369,8 @@
 android_glGetActiveAttrib__III_3II_3II_3II_3BI
   (JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jintArray length_ref, jint lengthOffset, jintArray size_ref, jint sizeOffset, jintArray type_ref, jint typeOffset, jbyteArray name_ref, jint nameOffset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLsizei *length_base = (GLsizei *) 0;
     jint _lengthRemaining;
     GLsizei *length = (GLsizei *) 0;
@@ -1185,12 +1386,14 @@
 
     if (!length_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length == null";
         goto exit;
     }
     if (lengthOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "lengthOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "lengthOffset < 0";
         goto exit;
     }
     _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
@@ -1200,12 +1403,14 @@
 
     if (!size_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "size == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "size == null";
         goto exit;
     }
     if (sizeOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "sizeOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "sizeOffset < 0";
         goto exit;
     }
     _sizeRemaining = _env->GetArrayLength(size_ref) - sizeOffset;
@@ -1215,12 +1420,14 @@
 
     if (!type_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "type == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "type == null";
         goto exit;
     }
     if (typeOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "typeOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "typeOffset < 0";
         goto exit;
     }
     _typeRemaining = _env->GetArrayLength(type_ref) - typeOffset;
@@ -1230,12 +1437,14 @@
 
     if (!name_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "name == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "name == null";
         goto exit;
     }
     if (nameOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "nameOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "nameOffset < 0";
         goto exit;
     }
     _nameRemaining = _env->GetArrayLength(name_ref) - nameOffset;
@@ -1270,16 +1479,21 @@
         _env->ReleasePrimitiveArrayCritical(length_ref, length_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetActiveAttrib ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) */
 static void
 android_glGetActiveAttrib__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B
   (JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jbyte name) {
-    jint _exception = 0;
     jarray _lengthArray = (jarray) 0;
+    jint _lengthBufferOffset = (jint) 0;
     jarray _sizeArray = (jarray) 0;
+    jint _sizeBufferOffset = (jint) 0;
     jarray _typeArray = (jarray) 0;
+    jint _typeBufferOffset = (jint) 0;
     jint _lengthRemaining;
     GLsizei *length = (GLsizei *) 0;
     jint _sizeRemaining;
@@ -1287,9 +1501,21 @@
     jint _typeRemaining;
     GLenum *type = (GLenum *) 0;
 
-    length = (GLsizei *)getPointer(_env, length_buf, &_lengthArray, &_lengthRemaining);
-    size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining);
-    type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining);
+    length = (GLsizei *)getPointer(_env, length_buf, &_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
+    size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
+    type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining, &_typeBufferOffset);
+    if (length == NULL) {
+        char * _lengthBase = (char *)_env->GetPrimitiveArrayCritical(_lengthArray, (jboolean *) 0);
+        length = (GLsizei *) (_lengthBase + _lengthBufferOffset);
+    }
+    if (size == NULL) {
+        char * _sizeBase = (char *)_env->GetPrimitiveArrayCritical(_sizeArray, (jboolean *) 0);
+        size = (GLint *) (_sizeBase + _sizeBufferOffset);
+    }
+    if (type == NULL) {
+        char * _typeBase = (char *)_env->GetPrimitiveArrayCritical(_typeArray, (jboolean *) 0);
+        type = (GLenum *) (_typeBase + _typeBufferOffset);
+    }
     glGetActiveAttrib(
         (GLuint)program,
         (GLuint)index,
@@ -1299,22 +1525,180 @@
         (GLenum *)type,
         (char *)name
     );
-    if (_lengthArray) {
-        releasePointer(_env, _lengthArray, type, _exception ? JNI_FALSE : JNI_TRUE);
+    if (_typeArray) {
+        releasePointer(_env, _typeArray, type, JNI_TRUE);
     }
     if (_sizeArray) {
-        releasePointer(_env, _sizeArray, size, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _sizeArray, size, JNI_TRUE);
     }
-    if (_typeArray) {
-        releasePointer(_env, _typeArray, length, _exception ? JNI_FALSE : JNI_TRUE);
+    if (_lengthArray) {
+        releasePointer(_env, _lengthArray, length, JNI_TRUE);
     }
 }
 
+/* void glGetActiveAttrib ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) */
+static jstring
+android_glGetActiveAttrib1
+  (JNIEnv *_env, jobject _this, jint program, jint index, jintArray size_ref, jint sizeOffset, jintArray type_ref, jint typeOffset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    GLint *size_base = (GLint *) 0;
+    jint _sizeRemaining;
+    GLint *size = (GLint *) 0;
+    GLenum *type_base = (GLenum *) 0;
+    jint _typeRemaining;
+    GLenum *type = (GLenum *) 0;
+
+    jstring result = 0;
+
+    GLint len = 0;
+    glGetProgramiv((GLuint)program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &len);
+    if (!len) {
+        return _env->NewStringUTF("");
+    }
+    char* buf = (char*) malloc(len);
+
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "out of memory");
+        return NULL;
+    }
+    if (!size_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "size == null";
+        goto exit;
+    }
+    if (sizeOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "sizeOffset < 0";
+        goto exit;
+    }
+    _sizeRemaining = _env->GetArrayLength(size_ref) - sizeOffset;
+    size_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(size_ref, (jboolean *)0);
+    size = size_base + sizeOffset;
+
+    if (!type_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "type == null";
+        goto exit;
+    }
+    if (typeOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "typeOffset < 0";
+        goto exit;
+    }
+    _typeRemaining = _env->GetArrayLength(type_ref) - typeOffset;
+    type_base = (GLenum *)
+        _env->GetPrimitiveArrayCritical(type_ref, (jboolean *)0);
+    type = type_base + typeOffset;
+
+    glGetActiveAttrib(
+        (GLuint)program,
+        (GLuint)index,
+        (GLsizei)len,
+        NULL,
+        (GLint *)size,
+        (GLenum *)type,
+        (char *)buf
+    );
+exit:
+    if (type_base) {
+        _env->ReleasePrimitiveArrayCritical(type_ref, type_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (size_base) {
+        _env->ReleasePrimitiveArrayCritical(size_ref, size_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception != 1) {
+        result = _env->NewStringUTF(buf);
+    }
+    if (buf) {
+        free(buf);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    if (result == 0) {
+        result = _env->NewStringUTF("");
+    }
+
+    return result;
+}
+
+/* void glGetActiveAttrib ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) */
+static jstring
+android_glGetActiveAttrib2
+  (JNIEnv *_env, jobject _this, jint program, jint index, jobject size_buf, jobject type_buf) {
+    jarray _sizeArray = (jarray) 0;
+    jint _sizeBufferOffset = (jint) 0;
+    jarray _typeArray = (jarray) 0;
+    jint _typeBufferOffset = (jint) 0;
+    jint _lengthRemaining;
+    GLsizei *length = (GLsizei *) 0;
+    jint _sizeRemaining;
+    GLint *size = (GLint *) 0;
+    jint _typeRemaining;
+    GLenum *type = (GLenum *) 0;
+
+    jstring result = 0;
+
+    GLint len = 0;
+    glGetProgramiv((GLuint)program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &len);
+    if (!len) {
+        return _env->NewStringUTF("");
+    }
+    char* buf = (char*) malloc(len);
+
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "out of memory");
+        return NULL;
+    }
+
+    size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
+    type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining, &_typeBufferOffset);
+    if (size == NULL) {
+        char * _sizeBase = (char *)_env->GetPrimitiveArrayCritical(_sizeArray, (jboolean *) 0);
+        size = (GLint *) (_sizeBase + _sizeBufferOffset);
+    }
+    if (type == NULL) {
+        char * _typeBase = (char *)_env->GetPrimitiveArrayCritical(_typeArray, (jboolean *) 0);
+        type = (GLenum *) (_typeBase + _typeBufferOffset);
+    }
+    glGetActiveAttrib(
+        (GLuint)program,
+        (GLuint)index,
+        (GLsizei)len,
+        NULL,
+        (GLint *)size,
+        (GLenum *)type,
+        (char *)buf
+    );
+
+    if (_typeArray) {
+        releasePointer(_env, _typeArray, type, JNI_TRUE);
+    }
+    if (_sizeArray) {
+        releasePointer(_env, _sizeArray, size, JNI_TRUE);
+    }
+    result = _env->NewStringUTF(buf);
+    if (buf) {
+        free(buf);
+    }
+    return result;
+}
 /* void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) */
 static void
 android_glGetActiveUniform__III_3II_3II_3II_3BI
   (JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jintArray length_ref, jint lengthOffset, jintArray size_ref, jint sizeOffset, jintArray type_ref, jint typeOffset, jbyteArray name_ref, jint nameOffset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLsizei *length_base = (GLsizei *) 0;
     jint _lengthRemaining;
     GLsizei *length = (GLsizei *) 0;
@@ -1330,12 +1714,14 @@
 
     if (!length_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length == null";
         goto exit;
     }
     if (lengthOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "lengthOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "lengthOffset < 0";
         goto exit;
     }
     _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
@@ -1345,12 +1731,14 @@
 
     if (!size_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "size == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "size == null";
         goto exit;
     }
     if (sizeOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "sizeOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "sizeOffset < 0";
         goto exit;
     }
     _sizeRemaining = _env->GetArrayLength(size_ref) - sizeOffset;
@@ -1360,12 +1748,14 @@
 
     if (!type_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "type == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "type == null";
         goto exit;
     }
     if (typeOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "typeOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "typeOffset < 0";
         goto exit;
     }
     _typeRemaining = _env->GetArrayLength(type_ref) - typeOffset;
@@ -1375,12 +1765,14 @@
 
     if (!name_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "name == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "name == null";
         goto exit;
     }
     if (nameOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "nameOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "nameOffset < 0";
         goto exit;
     }
     _nameRemaining = _env->GetArrayLength(name_ref) - nameOffset;
@@ -1415,16 +1807,21 @@
         _env->ReleasePrimitiveArrayCritical(length_ref, length_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) */
 static void
 android_glGetActiveUniform__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B
   (JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jbyte name) {
-    jint _exception = 0;
     jarray _lengthArray = (jarray) 0;
+    jint _lengthBufferOffset = (jint) 0;
     jarray _sizeArray = (jarray) 0;
+    jint _sizeBufferOffset = (jint) 0;
     jarray _typeArray = (jarray) 0;
+    jint _typeBufferOffset = (jint) 0;
     jint _lengthRemaining;
     GLsizei *length = (GLsizei *) 0;
     jint _sizeRemaining;
@@ -1432,9 +1829,21 @@
     jint _typeRemaining;
     GLenum *type = (GLenum *) 0;
 
-    length = (GLsizei *)getPointer(_env, length_buf, &_lengthArray, &_lengthRemaining);
-    size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining);
-    type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining);
+    length = (GLsizei *)getPointer(_env, length_buf, &_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
+    size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
+    type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining, &_typeBufferOffset);
+    if (length == NULL) {
+        char * _lengthBase = (char *)_env->GetPrimitiveArrayCritical(_lengthArray, (jboolean *) 0);
+        length = (GLsizei *) (_lengthBase + _lengthBufferOffset);
+    }
+    if (size == NULL) {
+        char * _sizeBase = (char *)_env->GetPrimitiveArrayCritical(_sizeArray, (jboolean *) 0);
+        size = (GLint *) (_sizeBase + _sizeBufferOffset);
+    }
+    if (type == NULL) {
+        char * _typeBase = (char *)_env->GetPrimitiveArrayCritical(_typeArray, (jboolean *) 0);
+        type = (GLenum *) (_typeBase + _typeBufferOffset);
+    }
     glGetActiveUniform(
         (GLuint)program,
         (GLuint)index,
@@ -1444,22 +1853,181 @@
         (GLenum *)type,
         (char *)name
     );
-    if (_lengthArray) {
-        releasePointer(_env, _lengthArray, type, _exception ? JNI_FALSE : JNI_TRUE);
+    if (_typeArray) {
+        releasePointer(_env, _typeArray, type, JNI_TRUE);
     }
     if (_sizeArray) {
-        releasePointer(_env, _sizeArray, size, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _sizeArray, size, JNI_TRUE);
     }
-    if (_typeArray) {
-        releasePointer(_env, _typeArray, length, _exception ? JNI_FALSE : JNI_TRUE);
+    if (_lengthArray) {
+        releasePointer(_env, _lengthArray, length, JNI_TRUE);
     }
 }
 
+/* void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) */
+static jstring
+android_glGetActiveUniform1
+  (JNIEnv *_env, jobject _this, jint program, jint index, jintArray size_ref, jint sizeOffset, jintArray type_ref, jint typeOffset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+
+    GLint *size_base = (GLint *) 0;
+    jint _sizeRemaining;
+    GLint *size = (GLint *) 0;
+
+    GLenum *type_base = (GLenum *) 0;
+    jint _typeRemaining;
+    GLenum *type = (GLenum *) 0;
+
+    jstring result = 0;
+
+    GLint len = 0;
+    glGetProgramiv((GLuint)program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &len);
+    if (!len) {
+        return _env->NewStringUTF("");
+    }
+    char* buf = (char*) malloc(len);
+
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "out of memory");
+        return NULL;
+    }
+
+    if (!size_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "size == null";
+        goto exit;
+    }
+    if (sizeOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "sizeOffset < 0";
+        goto exit;
+    }
+    _sizeRemaining = _env->GetArrayLength(size_ref) - sizeOffset;
+    size_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(size_ref, (jboolean *)0);
+    size = size_base + sizeOffset;
+
+    if (!type_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "type == null";
+        goto exit;
+    }
+    if (typeOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "typeOffset < 0";
+        goto exit;
+    }
+    _typeRemaining = _env->GetArrayLength(type_ref) - typeOffset;
+    type_base = (GLenum *)
+        _env->GetPrimitiveArrayCritical(type_ref, (jboolean *)0);
+    type = type_base + typeOffset;
+
+    glGetActiveUniform(
+        (GLuint)program,
+        (GLuint)index,
+        (GLsizei)len,
+        NULL,
+        (GLint *)size,
+        (GLenum *)type,
+        (char *)buf
+    );
+
+exit:
+    if (type_base) {
+        _env->ReleasePrimitiveArrayCritical(type_ref, type_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (size_base) {
+        _env->ReleasePrimitiveArrayCritical(size_ref, size_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception != 1) {
+        result = _env->NewStringUTF(buf);
+    }
+    if (buf) {
+        free(buf);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    if (result == 0) {
+        result = _env->NewStringUTF("");
+    }
+    return result;
+}
+
+/* void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) */
+static jstring
+android_glGetActiveUniform2
+  (JNIEnv *_env, jobject _this, jint program, jint index, jobject size_buf, jobject type_buf) {
+    jarray _sizeArray = (jarray) 0;
+    jint _sizeBufferOffset = (jint) 0;
+    jarray _typeArray = (jarray) 0;
+    jint _typeBufferOffset = (jint) 0;
+    jint _sizeRemaining;
+    GLint *size = (GLint *) 0;
+    jint _typeRemaining;
+    GLenum *type = (GLenum *) 0;
+
+    jstring result = 0;
+    GLint len = 0;
+    glGetProgramiv((GLuint)program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &len);
+    if (!len) {
+        return _env->NewStringUTF("");
+    }
+    char* buf = (char*) malloc(len);
+
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "out of memory");
+        return NULL;
+    }
+
+    size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
+    type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining, &_typeBufferOffset);
+
+    if (size == NULL) {
+        char * _sizeBase = (char *)_env->GetPrimitiveArrayCritical(_sizeArray, (jboolean *) 0);
+        size = (GLint *) (_sizeBase + _sizeBufferOffset);
+    }
+    if (type == NULL) {
+        char * _typeBase = (char *)_env->GetPrimitiveArrayCritical(_typeArray, (jboolean *) 0);
+        type = (GLenum *) (_typeBase + _typeBufferOffset);
+    }
+    glGetActiveUniform(
+        (GLuint)program,
+        (GLuint)index,
+        len,
+        NULL,
+        (GLint *)size,
+        (GLenum *)type,
+        (char *)buf
+    );
+
+    if (_typeArray) {
+        releasePointer(_env, _typeArray, type, JNI_TRUE);
+    }
+    if (_sizeArray) {
+        releasePointer(_env, _sizeArray, size, JNI_TRUE);
+    }
+    result = _env->NewStringUTF(buf);
+    if (buf) {
+        free(buf);
+    }
+    return result;
+}
 /* void glGetAttachedShaders ( GLuint program, GLsizei maxcount, GLsizei *count, GLuint *shaders ) */
 static void
 android_glGetAttachedShaders__II_3II_3II
   (JNIEnv *_env, jobject _this, jint program, jint maxcount, jintArray count_ref, jint countOffset, jintArray shaders_ref, jint shadersOffset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLsizei *count_base = (GLsizei *) 0;
     jint _countRemaining;
     GLsizei *count = (GLsizei *) 0;
@@ -1469,12 +2037,14 @@
 
     if (!count_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "count == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "count == null";
         goto exit;
     }
     if (countOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "countOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "countOffset < 0";
         goto exit;
     }
     _countRemaining = _env->GetArrayLength(count_ref) - countOffset;
@@ -1484,12 +2054,14 @@
 
     if (!shaders_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "shaders == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "shaders == null";
         goto exit;
     }
     if (shadersOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "shadersOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "shadersOffset < 0";
         goto exit;
     }
     _shadersRemaining = _env->GetArrayLength(shaders_ref) - shadersOffset;
@@ -1513,33 +2085,45 @@
         _env->ReleasePrimitiveArrayCritical(count_ref, count_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetAttachedShaders ( GLuint program, GLsizei maxcount, GLsizei *count, GLuint *shaders ) */
 static void
 android_glGetAttachedShaders__IILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint program, jint maxcount, jobject count_buf, jobject shaders_buf) {
-    jint _exception = 0;
     jarray _countArray = (jarray) 0;
+    jint _countBufferOffset = (jint) 0;
     jarray _shadersArray = (jarray) 0;
+    jint _shadersBufferOffset = (jint) 0;
     jint _countRemaining;
     GLsizei *count = (GLsizei *) 0;
     jint _shadersRemaining;
     GLuint *shaders = (GLuint *) 0;
 
-    count = (GLsizei *)getPointer(_env, count_buf, &_countArray, &_countRemaining);
-    shaders = (GLuint *)getPointer(_env, shaders_buf, &_shadersArray, &_shadersRemaining);
+    count = (GLsizei *)getPointer(_env, count_buf, &_countArray, &_countRemaining, &_countBufferOffset);
+    shaders = (GLuint *)getPointer(_env, shaders_buf, &_shadersArray, &_shadersRemaining, &_shadersBufferOffset);
+    if (count == NULL) {
+        char * _countBase = (char *)_env->GetPrimitiveArrayCritical(_countArray, (jboolean *) 0);
+        count = (GLsizei *) (_countBase + _countBufferOffset);
+    }
+    if (shaders == NULL) {
+        char * _shadersBase = (char *)_env->GetPrimitiveArrayCritical(_shadersArray, (jboolean *) 0);
+        shaders = (GLuint *) (_shadersBase + _shadersBufferOffset);
+    }
     glGetAttachedShaders(
         (GLuint)program,
         (GLsizei)maxcount,
         (GLsizei *)count,
         (GLuint *)shaders
     );
-    if (_countArray) {
-        releasePointer(_env, _countArray, shaders, _exception ? JNI_FALSE : JNI_TRUE);
-    }
     if (_shadersArray) {
-        releasePointer(_env, _shadersArray, count, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _shadersArray, shaders, JNI_TRUE);
+    }
+    if (_countArray) {
+        releasePointer(_env, _countArray, count, JNI_TRUE);
     }
 }
 
@@ -1547,11 +2131,15 @@
 static jint
 android_glGetAttribLocation__ILjava_lang_String_2
   (JNIEnv *_env, jobject _this, jint program, jstring name) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     int _returnValue = 0;
     const char* _nativename = 0;
 
     if (!name) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "name == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "name == null";
         goto exit;
     }
     _nativename = _env->GetStringUTFChars(name, 0);
@@ -1566,6 +2154,9 @@
         _env->ReleaseStringUTFChars(name, _nativename);
     }
 
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
     return _returnValue;
 }
 
@@ -1574,18 +2165,22 @@
 android_glGetBooleanv__I_3ZI
   (JNIEnv *_env, jobject _this, jint pname, jbooleanArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLboolean *params_base = (GLboolean *) 0;
     jint _remaining;
     GLboolean *params = (GLboolean *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1603,24 +2198,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetBooleanv ( GLenum pname, GLboolean *params ) */
 static void
 android_glGetBooleanv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLboolean *params = (GLboolean *) 0;
 
-    params = (GLboolean *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLboolean *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLboolean *) (_paramsBase + _bufferOffset);
+    }
     glGetBooleanv(
         (GLenum)pname,
         (GLboolean *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -1629,24 +2231,29 @@
 android_glGetBufferParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -1664,6 +2271,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetBufferParameteriv ( GLenum target, GLenum pname, GLint *params ) */
@@ -1671,16 +2281,24 @@
 android_glGetBufferParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetBufferParameteriv(
         (GLenum)target,
         (GLenum)pname,
@@ -1691,6 +2309,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* GLenum glGetError ( void ) */
@@ -1707,18 +2328,22 @@
 android_glGetFloatv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1736,24 +2361,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFloatv ( GLenum pname, GLfloat *params ) */
 static void
 android_glGetFloatv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetFloatv(
         (GLenum)pname,
         (GLfloat *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -1762,18 +2394,22 @@
 android_glGetFramebufferAttachmentParameteriv__III_3II
   (JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1793,18 +2429,25 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFramebufferAttachmentParameteriv ( GLenum target, GLenum attachment, GLenum pname, GLint *params ) */
 static void
 android_glGetFramebufferAttachmentParameteriv__IIILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetFramebufferAttachmentParameteriv(
         (GLenum)target,
         (GLenum)attachment,
@@ -1812,7 +2455,7 @@
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -1821,18 +2464,22 @@
 android_glGetIntegerv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2169,7 +2816,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -2186,6 +2834,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetIntegerv ( GLenum pname, GLint *params ) */
@@ -2193,11 +2844,14 @@
 android_glGetIntegerv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_ALPHA_BITS)
@@ -2531,9 +3185,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetIntegerv(
         (GLenum)pname,
         (GLint *)params
@@ -2543,6 +3202,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetProgramiv ( GLuint program, GLenum pname, GLint *params ) */
@@ -2550,18 +3212,22 @@
 android_glGetProgramiv__II_3II
   (JNIEnv *_env, jobject _this, jint program, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2580,25 +3246,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetProgramiv ( GLuint program, GLenum pname, GLint *params ) */
 static void
 android_glGetProgramiv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint program, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetProgramiv(
         (GLuint)program,
         (GLenum)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -2626,18 +3299,22 @@
 android_glGetRenderbufferParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2656,25 +3333,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetRenderbufferParameteriv ( GLenum target, GLenum pname, GLint *params ) */
 static void
 android_glGetRenderbufferParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetRenderbufferParameteriv(
         (GLenum)target,
         (GLenum)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -2683,18 +3367,22 @@
 android_glGetShaderiv__II_3II
   (JNIEnv *_env, jobject _this, jint shader, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2713,25 +3401,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetShaderiv ( GLuint shader, GLenum pname, GLint *params ) */
 static void
 android_glGetShaderiv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint shader, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetShaderiv(
         (GLuint)shader,
         (GLenum)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -2759,6 +3454,8 @@
 android_glGetShaderPrecisionFormat__II_3II_3II
   (JNIEnv *_env, jobject _this, jint shadertype, jint precisiontype, jintArray range_ref, jint rangeOffset, jintArray precision_ref, jint precisionOffset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *range_base = (GLint *) 0;
     jint _rangeRemaining;
     GLint *range = (GLint *) 0;
@@ -2768,12 +3465,14 @@
 
     if (!range_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "range == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "range == null";
         goto exit;
     }
     if (rangeOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "rangeOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "rangeOffset < 0";
         goto exit;
     }
     _rangeRemaining = _env->GetArrayLength(range_ref) - rangeOffset;
@@ -2783,12 +3482,14 @@
 
     if (!precision_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "precision == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "precision == null";
         goto exit;
     }
     if (precisionOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "precisionOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "precisionOffset < 0";
         goto exit;
     }
     _precisionRemaining = _env->GetArrayLength(precision_ref) - precisionOffset;
@@ -2812,33 +3513,45 @@
         _env->ReleasePrimitiveArrayCritical(range_ref, range_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetShaderPrecisionFormat ( GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision ) */
 static void
 android_glGetShaderPrecisionFormat__IILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint shadertype, jint precisiontype, jobject range_buf, jobject precision_buf) {
-    jint _exception = 0;
     jarray _rangeArray = (jarray) 0;
+    jint _rangeBufferOffset = (jint) 0;
     jarray _precisionArray = (jarray) 0;
+    jint _precisionBufferOffset = (jint) 0;
     jint _rangeRemaining;
     GLint *range = (GLint *) 0;
     jint _precisionRemaining;
     GLint *precision = (GLint *) 0;
 
-    range = (GLint *)getPointer(_env, range_buf, &_rangeArray, &_rangeRemaining);
-    precision = (GLint *)getPointer(_env, precision_buf, &_precisionArray, &_precisionRemaining);
+    range = (GLint *)getPointer(_env, range_buf, &_rangeArray, &_rangeRemaining, &_rangeBufferOffset);
+    precision = (GLint *)getPointer(_env, precision_buf, &_precisionArray, &_precisionRemaining, &_precisionBufferOffset);
+    if (range == NULL) {
+        char * _rangeBase = (char *)_env->GetPrimitiveArrayCritical(_rangeArray, (jboolean *) 0);
+        range = (GLint *) (_rangeBase + _rangeBufferOffset);
+    }
+    if (precision == NULL) {
+        char * _precisionBase = (char *)_env->GetPrimitiveArrayCritical(_precisionArray, (jboolean *) 0);
+        precision = (GLint *) (_precisionBase + _precisionBufferOffset);
+    }
     glGetShaderPrecisionFormat(
         (GLenum)shadertype,
         (GLenum)precisiontype,
         (GLint *)range,
         (GLint *)precision
     );
-    if (_rangeArray) {
-        releasePointer(_env, _rangeArray, precision, _exception ? JNI_FALSE : JNI_TRUE);
-    }
     if (_precisionArray) {
-        releasePointer(_env, _precisionArray, range, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _precisionArray, precision, JNI_TRUE);
+    }
+    if (_rangeArray) {
+        releasePointer(_env, _rangeArray, range, JNI_TRUE);
     }
 }
 
@@ -2847,6 +3560,8 @@
 android_glGetShaderSource__II_3II_3BI
   (JNIEnv *_env, jobject _this, jint shader, jint bufsize, jintArray length_ref, jint lengthOffset, jbyteArray source_ref, jint sourceOffset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLsizei *length_base = (GLsizei *) 0;
     jint _lengthRemaining;
     GLsizei *length = (GLsizei *) 0;
@@ -2856,12 +3571,14 @@
 
     if (!length_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length == null";
         goto exit;
     }
     if (lengthOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "lengthOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "lengthOffset < 0";
         goto exit;
     }
     _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
@@ -2871,12 +3588,14 @@
 
     if (!source_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "source == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "source == null";
         goto exit;
     }
     if (sourceOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "sourceOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "sourceOffset < 0";
         goto exit;
     }
     _sourceRemaining = _env->GetArrayLength(source_ref) - sourceOffset;
@@ -2900,18 +3619,25 @@
         _env->ReleasePrimitiveArrayCritical(length_ref, length_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetShaderSource ( GLuint shader, GLsizei bufsize, GLsizei *length, char *source ) */
 static void
 android_glGetShaderSource__IILjava_nio_IntBuffer_2B
   (JNIEnv *_env, jobject _this, jint shader, jint bufsize, jobject length_buf, jbyte source) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLsizei *length = (GLsizei *) 0;
 
-    length = (GLsizei *)getPointer(_env, length_buf, &_array, &_remaining);
+    length = (GLsizei *)getPointer(_env, length_buf, &_array, &_remaining, &_bufferOffset);
+    if (length == NULL) {
+        char * _lengthBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        length = (GLsizei *) (_lengthBase + _bufferOffset);
+    }
     glGetShaderSource(
         (GLuint)shader,
         (GLsizei)bufsize,
@@ -2919,10 +3645,27 @@
         (char *)source
     );
     if (_array) {
-        releasePointer(_env, _array, length, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, length, JNI_TRUE);
     }
 }
 
+/* void glGetShaderSource ( GLuint shader, GLsizei bufsize, GLsizei *length, char *source ) */
+static jstring android_glGetShaderSource(JNIEnv *_env, jobject, jint shader) {
+    GLint shaderLen = 0;
+    glGetShaderiv((GLuint)shader, GL_SHADER_SOURCE_LENGTH, &shaderLen);
+    if (!shaderLen) {
+        return _env->NewStringUTF("");
+    }
+    char* buf = (char*) malloc(shaderLen);
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "out of memory");
+        return NULL;
+    }
+    glGetShaderSource(shader, shaderLen, NULL, buf);
+    jstring result = _env->NewStringUTF(buf);
+    free(buf);
+    return result;
+}
 /* const GLubyte * glGetString ( GLenum name ) */
 static jstring android_glGetString(JNIEnv* _env, jobject, jint name) {
     const char* chars = (const char*) glGetString((GLenum) name);
@@ -2933,24 +3676,29 @@
 android_glGetTexParameterfv__II_3FI
   (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -2968,6 +3716,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params ) */
@@ -2975,16 +3726,24 @@
 android_glGetTexParameterfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameterfv(
         (GLenum)target,
         (GLenum)pname,
@@ -2995,6 +3754,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params ) */
@@ -3002,24 +3764,29 @@
 android_glGetTexParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -3037,6 +3804,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params ) */
@@ -3044,16 +3814,24 @@
 android_glGetTexParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameteriv(
         (GLenum)target,
         (GLenum)pname,
@@ -3064,6 +3842,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetUniformfv ( GLuint program, GLint location, GLfloat *params ) */
@@ -3071,18 +3852,22 @@
 android_glGetUniformfv__II_3FI
   (JNIEnv *_env, jobject _this, jint program, jint location, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3101,25 +3886,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetUniformfv ( GLuint program, GLint location, GLfloat *params ) */
 static void
 android_glGetUniformfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint program, jint location, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetUniformfv(
         (GLuint)program,
         (GLint)location,
         (GLfloat *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -3128,18 +3920,22 @@
 android_glGetUniformiv__II_3II
   (JNIEnv *_env, jobject _this, jint program, jint location, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3158,25 +3954,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetUniformiv ( GLuint program, GLint location, GLint *params ) */
 static void
 android_glGetUniformiv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint program, jint location, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetUniformiv(
         (GLuint)program,
         (GLint)location,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -3184,11 +3987,15 @@
 static jint
 android_glGetUniformLocation__ILjava_lang_String_2
   (JNIEnv *_env, jobject _this, jint program, jstring name) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     int _returnValue = 0;
     const char* _nativename = 0;
 
     if (!name) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "name == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "name == null";
         goto exit;
     }
     _nativename = _env->GetStringUTFChars(name, 0);
@@ -3203,6 +4010,9 @@
         _env->ReleaseStringUTFChars(name, _nativename);
     }
 
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
     return _returnValue;
 }
 
@@ -3211,18 +4021,22 @@
 android_glGetVertexAttribfv__II_3FI
   (JNIEnv *_env, jobject _this, jint index, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3241,25 +4055,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetVertexAttribfv ( GLuint index, GLenum pname, GLfloat *params ) */
 static void
 android_glGetVertexAttribfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint index, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetVertexAttribfv(
         (GLuint)index,
         (GLenum)pname,
         (GLfloat *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -3268,18 +4089,22 @@
 android_glGetVertexAttribiv__II_3II
   (JNIEnv *_env, jobject _this, jint index, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3298,25 +4123,32 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetVertexAttribiv ( GLuint index, GLenum pname, GLint *params ) */
 static void
 android_glGetVertexAttribiv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint index, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetVertexAttribiv(
         (GLuint)index,
         (GLenum)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -3449,12 +4281,16 @@
 static void
 android_glReadPixels__IIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint x, jint y, jint width, jint height, jint format, jint type, jobject pixels_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
-    pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+    pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    if (pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
+    }
     glReadPixels(
         (GLint)x,
         (GLint)y,
@@ -3465,7 +4301,7 @@
         (GLvoid *)pixels
     );
     if (_array) {
-        releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, pixels, JNI_TRUE);
     }
 }
 
@@ -3514,7 +4350,11 @@
 static void
 android_glShaderBinary__I_3IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint n, jintArray shaders_ref, jint offset, jint binaryformat, jobject binary_buf, jint length) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     GLuint *shaders_base = (GLuint *) 0;
     jint _shadersRemaining;
     GLuint *shaders = (GLuint *) 0;
@@ -3522,11 +4362,15 @@
     GLvoid *binary = (GLvoid *) 0;
 
     if (!shaders_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "shaders == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "shaders == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _shadersRemaining = _env->GetArrayLength(shaders_ref) - offset;
@@ -3534,7 +4378,11 @@
         _env->GetPrimitiveArrayCritical(shaders_ref, (jboolean *)0);
     shaders = shaders_base + offset;
 
-    binary = (GLvoid *)getPointer(_env, binary_buf, &_array, &_binaryRemaining);
+    binary = (GLvoid *)getPointer(_env, binary_buf, &_array, &_binaryRemaining, &_bufferOffset);
+    if (binary == NULL) {
+        char * _binaryBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        binary = (GLvoid *) (_binaryBase + _bufferOffset);
+    }
     glShaderBinary(
         (GLsizei)n,
         (GLuint *)shaders,
@@ -3551,6 +4399,9 @@
         _env->ReleasePrimitiveArrayCritical(shaders_ref, shaders_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glShaderBinary ( GLsizei n, const GLuint *shaders, GLenum binaryformat, const GLvoid *binary, GLsizei length ) */
@@ -3558,14 +4409,24 @@
 android_glShaderBinary__ILjava_nio_IntBuffer_2ILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint n, jobject shaders_buf, jint binaryformat, jobject binary_buf, jint length) {
     jarray _shadersArray = (jarray) 0;
+    jint _shadersBufferOffset = (jint) 0;
     jarray _binaryArray = (jarray) 0;
+    jint _binaryBufferOffset = (jint) 0;
     jint _shadersRemaining;
     GLuint *shaders = (GLuint *) 0;
     jint _binaryRemaining;
     GLvoid *binary = (GLvoid *) 0;
 
-    shaders = (GLuint *)getPointer(_env, shaders_buf, &_shadersArray, &_shadersRemaining);
-    binary = (GLvoid *)getPointer(_env, binary_buf, &_binaryArray, &_binaryRemaining);
+    shaders = (GLuint *)getPointer(_env, shaders_buf, &_shadersArray, &_shadersRemaining, &_shadersBufferOffset);
+    binary = (GLvoid *)getPointer(_env, binary_buf, &_binaryArray, &_binaryRemaining, &_binaryBufferOffset);
+    if (shaders == NULL) {
+        char * _shadersBase = (char *)_env->GetPrimitiveArrayCritical(_shadersArray, (jboolean *) 0);
+        shaders = (GLuint *) (_shadersBase + _shadersBufferOffset);
+    }
+    if (binary == NULL) {
+        char * _binaryBase = (char *)_env->GetPrimitiveArrayCritical(_binaryArray, (jboolean *) 0);
+        binary = (GLvoid *) (_binaryBase + _binaryBufferOffset);
+    }
     glShaderBinary(
         (GLsizei)n,
         (GLuint *)shaders,
@@ -3573,11 +4434,11 @@
         (GLvoid *)binary,
         (GLsizei)length
     );
-    if (_shadersArray) {
-        releasePointer(_env, _shadersArray, binary, JNI_FALSE);
-    }
     if (_binaryArray) {
-        releasePointer(_env, _binaryArray, shaders, JNI_FALSE);
+        releasePointer(_env, _binaryArray, binary, JNI_FALSE);
+    }
+    if (_shadersArray) {
+        releasePointer(_env, _shadersArray, shaders, JNI_FALSE);
     }
 }
 
@@ -3668,11 +4529,16 @@
 android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint format, jint type, jobject pixels_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
     if (pixels_buf) {
-        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    }
+    if (pixels_buf && pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
     }
     glTexImage2D(
         (GLenum)target,
@@ -3705,21 +4571,30 @@
 static void
 android_glTexParameterfv__II_3FI
   (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -3737,21 +4612,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params ) */
 static void
 android_glTexParameterfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glTexParameterfv(
         (GLenum)target,
         (GLenum)pname,
@@ -3762,6 +4650,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameteri ( GLenum target, GLenum pname, GLint param ) */
@@ -3779,21 +4670,30 @@
 static void
 android_glTexParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -3811,21 +4711,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameteriv ( GLenum target, GLenum pname, const GLint *params ) */
 static void
 android_glTexParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glTexParameteriv(
         (GLenum)target,
         (GLenum)pname,
@@ -3836,6 +4749,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ) */
@@ -3843,11 +4759,16 @@
 android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint type, jobject pixels_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
     if (pixels_buf) {
-        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    }
+    if (pixels_buf && pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
     }
     glTexSubImage2D(
         (GLenum)target,
@@ -3879,16 +4800,23 @@
 static void
 android_glUniform1fv__II_3FI
   (JNIEnv *_env, jobject _this, jint location, jint count, jfloatArray v_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *v_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *v = (GLfloat *) 0;
 
     if (!v_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "v == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -3907,6 +4835,9 @@
         _env->ReleasePrimitiveArrayCritical(v_ref, v_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniform1fv ( GLint location, GLsizei count, const GLfloat *v ) */
@@ -3914,10 +4845,15 @@
 android_glUniform1fv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jobject v_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *v = (GLfloat *) 0;
 
-    v = (GLfloat *)getPointer(_env, v_buf, &_array, &_remaining);
+    v = (GLfloat *)getPointer(_env, v_buf, &_array, &_remaining, &_bufferOffset);
+    if (v == NULL) {
+        char * _vBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        v = (GLfloat *) (_vBase + _bufferOffset);
+    }
     glUniform1fv(
         (GLint)location,
         (GLsizei)count,
@@ -3942,16 +4878,23 @@
 static void
 android_glUniform1iv__II_3II
   (JNIEnv *_env, jobject _this, jint location, jint count, jintArray v_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *v_base = (GLint *) 0;
     jint _remaining;
     GLint *v = (GLint *) 0;
 
     if (!v_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "v == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -3970,6 +4913,9 @@
         _env->ReleasePrimitiveArrayCritical(v_ref, v_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniform1iv ( GLint location, GLsizei count, const GLint *v ) */
@@ -3977,10 +4923,15 @@
 android_glUniform1iv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jobject v_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *v = (GLint *) 0;
 
-    v = (GLint *)getPointer(_env, v_buf, &_array, &_remaining);
+    v = (GLint *)getPointer(_env, v_buf, &_array, &_remaining, &_bufferOffset);
+    if (v == NULL) {
+        char * _vBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        v = (GLint *) (_vBase + _bufferOffset);
+    }
     glUniform1iv(
         (GLint)location,
         (GLsizei)count,
@@ -4006,16 +4957,23 @@
 static void
 android_glUniform2fv__II_3FI
   (JNIEnv *_env, jobject _this, jint location, jint count, jfloatArray v_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *v_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *v = (GLfloat *) 0;
 
     if (!v_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "v == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4034,6 +4992,9 @@
         _env->ReleasePrimitiveArrayCritical(v_ref, v_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniform2fv ( GLint location, GLsizei count, const GLfloat *v ) */
@@ -4041,10 +5002,15 @@
 android_glUniform2fv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jobject v_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *v = (GLfloat *) 0;
 
-    v = (GLfloat *)getPointer(_env, v_buf, &_array, &_remaining);
+    v = (GLfloat *)getPointer(_env, v_buf, &_array, &_remaining, &_bufferOffset);
+    if (v == NULL) {
+        char * _vBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        v = (GLfloat *) (_vBase + _bufferOffset);
+    }
     glUniform2fv(
         (GLint)location,
         (GLsizei)count,
@@ -4070,16 +5036,23 @@
 static void
 android_glUniform2iv__II_3II
   (JNIEnv *_env, jobject _this, jint location, jint count, jintArray v_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *v_base = (GLint *) 0;
     jint _remaining;
     GLint *v = (GLint *) 0;
 
     if (!v_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "v == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4098,6 +5071,9 @@
         _env->ReleasePrimitiveArrayCritical(v_ref, v_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniform2iv ( GLint location, GLsizei count, const GLint *v ) */
@@ -4105,10 +5081,15 @@
 android_glUniform2iv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jobject v_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *v = (GLint *) 0;
 
-    v = (GLint *)getPointer(_env, v_buf, &_array, &_remaining);
+    v = (GLint *)getPointer(_env, v_buf, &_array, &_remaining, &_bufferOffset);
+    if (v == NULL) {
+        char * _vBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        v = (GLint *) (_vBase + _bufferOffset);
+    }
     glUniform2iv(
         (GLint)location,
         (GLsizei)count,
@@ -4135,16 +5116,23 @@
 static void
 android_glUniform3fv__II_3FI
   (JNIEnv *_env, jobject _this, jint location, jint count, jfloatArray v_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *v_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *v = (GLfloat *) 0;
 
     if (!v_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "v == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4163,6 +5151,9 @@
         _env->ReleasePrimitiveArrayCritical(v_ref, v_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniform3fv ( GLint location, GLsizei count, const GLfloat *v ) */
@@ -4170,10 +5161,15 @@
 android_glUniform3fv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jobject v_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *v = (GLfloat *) 0;
 
-    v = (GLfloat *)getPointer(_env, v_buf, &_array, &_remaining);
+    v = (GLfloat *)getPointer(_env, v_buf, &_array, &_remaining, &_bufferOffset);
+    if (v == NULL) {
+        char * _vBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        v = (GLfloat *) (_vBase + _bufferOffset);
+    }
     glUniform3fv(
         (GLint)location,
         (GLsizei)count,
@@ -4200,16 +5196,23 @@
 static void
 android_glUniform3iv__II_3II
   (JNIEnv *_env, jobject _this, jint location, jint count, jintArray v_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *v_base = (GLint *) 0;
     jint _remaining;
     GLint *v = (GLint *) 0;
 
     if (!v_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "v == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4228,6 +5231,9 @@
         _env->ReleasePrimitiveArrayCritical(v_ref, v_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniform3iv ( GLint location, GLsizei count, const GLint *v ) */
@@ -4235,10 +5241,15 @@
 android_glUniform3iv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jobject v_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *v = (GLint *) 0;
 
-    v = (GLint *)getPointer(_env, v_buf, &_array, &_remaining);
+    v = (GLint *)getPointer(_env, v_buf, &_array, &_remaining, &_bufferOffset);
+    if (v == NULL) {
+        char * _vBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        v = (GLint *) (_vBase + _bufferOffset);
+    }
     glUniform3iv(
         (GLint)location,
         (GLsizei)count,
@@ -4266,16 +5277,23 @@
 static void
 android_glUniform4fv__II_3FI
   (JNIEnv *_env, jobject _this, jint location, jint count, jfloatArray v_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *v_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *v = (GLfloat *) 0;
 
     if (!v_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "v == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4294,6 +5312,9 @@
         _env->ReleasePrimitiveArrayCritical(v_ref, v_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniform4fv ( GLint location, GLsizei count, const GLfloat *v ) */
@@ -4301,10 +5322,15 @@
 android_glUniform4fv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jobject v_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *v = (GLfloat *) 0;
 
-    v = (GLfloat *)getPointer(_env, v_buf, &_array, &_remaining);
+    v = (GLfloat *)getPointer(_env, v_buf, &_array, &_remaining, &_bufferOffset);
+    if (v == NULL) {
+        char * _vBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        v = (GLfloat *) (_vBase + _bufferOffset);
+    }
     glUniform4fv(
         (GLint)location,
         (GLsizei)count,
@@ -4332,16 +5358,23 @@
 static void
 android_glUniform4iv__II_3II
   (JNIEnv *_env, jobject _this, jint location, jint count, jintArray v_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *v_base = (GLint *) 0;
     jint _remaining;
     GLint *v = (GLint *) 0;
 
     if (!v_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "v == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4360,6 +5393,9 @@
         _env->ReleasePrimitiveArrayCritical(v_ref, v_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniform4iv ( GLint location, GLsizei count, const GLint *v ) */
@@ -4367,10 +5403,15 @@
 android_glUniform4iv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jobject v_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *v = (GLint *) 0;
 
-    v = (GLint *)getPointer(_env, v_buf, &_array, &_remaining);
+    v = (GLint *)getPointer(_env, v_buf, &_array, &_remaining, &_bufferOffset);
+    if (v == NULL) {
+        char * _vBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        v = (GLint *) (_vBase + _bufferOffset);
+    }
     glUniform4iv(
         (GLint)location,
         (GLsizei)count,
@@ -4385,16 +5426,23 @@
 static void
 android_glUniformMatrix2fv__IIZ_3FI
   (JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *value_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *value = (GLfloat *) 0;
 
     if (!value_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "value == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(value_ref) - offset;
@@ -4414,6 +5462,9 @@
         _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniformMatrix2fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -4421,10 +5472,15 @@
 android_glUniformMatrix2fv__IIZLjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *value = (GLfloat *) 0;
 
-    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining);
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
     glUniformMatrix2fv(
         (GLint)location,
         (GLsizei)count,
@@ -4440,16 +5496,23 @@
 static void
 android_glUniformMatrix3fv__IIZ_3FI
   (JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *value_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *value = (GLfloat *) 0;
 
     if (!value_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "value == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(value_ref) - offset;
@@ -4469,6 +5532,9 @@
         _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniformMatrix3fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -4476,10 +5542,15 @@
 android_glUniformMatrix3fv__IIZLjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *value = (GLfloat *) 0;
 
-    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining);
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
     glUniformMatrix3fv(
         (GLint)location,
         (GLsizei)count,
@@ -4495,16 +5566,23 @@
 static void
 android_glUniformMatrix4fv__IIZ_3FI
   (JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *value_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *value = (GLfloat *) 0;
 
     if (!value_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "value == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(value_ref) - offset;
@@ -4524,6 +5602,9 @@
         _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glUniformMatrix4fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -4531,10 +5612,15 @@
 android_glUniformMatrix4fv__IIZLjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *value = (GLfloat *) 0;
 
-    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining);
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
     glUniformMatrix4fv(
         (GLint)location,
         (GLsizei)count,
@@ -4578,16 +5664,23 @@
 static void
 android_glVertexAttrib1fv__I_3FI
   (JNIEnv *_env, jobject _this, jint indx, jfloatArray values_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *values_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *values = (GLfloat *) 0;
 
     if (!values_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "values == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "values == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(values_ref) - offset;
@@ -4605,6 +5698,9 @@
         _env->ReleasePrimitiveArrayCritical(values_ref, values_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glVertexAttrib1fv ( GLuint indx, const GLfloat *values ) */
@@ -4612,10 +5708,15 @@
 android_glVertexAttrib1fv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint indx, jobject values_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *values = (GLfloat *) 0;
 
-    values = (GLfloat *)getPointer(_env, values_buf, &_array, &_remaining);
+    values = (GLfloat *)getPointer(_env, values_buf, &_array, &_remaining, &_bufferOffset);
+    if (values == NULL) {
+        char * _valuesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        values = (GLfloat *) (_valuesBase + _bufferOffset);
+    }
     glVertexAttrib1fv(
         (GLuint)indx,
         (GLfloat *)values
@@ -4640,16 +5741,23 @@
 static void
 android_glVertexAttrib2fv__I_3FI
   (JNIEnv *_env, jobject _this, jint indx, jfloatArray values_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *values_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *values = (GLfloat *) 0;
 
     if (!values_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "values == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "values == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(values_ref) - offset;
@@ -4667,6 +5775,9 @@
         _env->ReleasePrimitiveArrayCritical(values_ref, values_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glVertexAttrib2fv ( GLuint indx, const GLfloat *values ) */
@@ -4674,10 +5785,15 @@
 android_glVertexAttrib2fv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint indx, jobject values_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *values = (GLfloat *) 0;
 
-    values = (GLfloat *)getPointer(_env, values_buf, &_array, &_remaining);
+    values = (GLfloat *)getPointer(_env, values_buf, &_array, &_remaining, &_bufferOffset);
+    if (values == NULL) {
+        char * _valuesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        values = (GLfloat *) (_valuesBase + _bufferOffset);
+    }
     glVertexAttrib2fv(
         (GLuint)indx,
         (GLfloat *)values
@@ -4703,16 +5819,23 @@
 static void
 android_glVertexAttrib3fv__I_3FI
   (JNIEnv *_env, jobject _this, jint indx, jfloatArray values_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *values_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *values = (GLfloat *) 0;
 
     if (!values_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "values == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "values == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(values_ref) - offset;
@@ -4730,6 +5853,9 @@
         _env->ReleasePrimitiveArrayCritical(values_ref, values_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glVertexAttrib3fv ( GLuint indx, const GLfloat *values ) */
@@ -4737,10 +5863,15 @@
 android_glVertexAttrib3fv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint indx, jobject values_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *values = (GLfloat *) 0;
 
-    values = (GLfloat *)getPointer(_env, values_buf, &_array, &_remaining);
+    values = (GLfloat *)getPointer(_env, values_buf, &_array, &_remaining, &_bufferOffset);
+    if (values == NULL) {
+        char * _valuesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        values = (GLfloat *) (_valuesBase + _bufferOffset);
+    }
     glVertexAttrib3fv(
         (GLuint)indx,
         (GLfloat *)values
@@ -4767,16 +5898,23 @@
 static void
 android_glVertexAttrib4fv__I_3FI
   (JNIEnv *_env, jobject _this, jint indx, jfloatArray values_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *values_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *values = (GLfloat *) 0;
 
     if (!values_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "values == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "values == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(values_ref) - offset;
@@ -4794,6 +5932,9 @@
         _env->ReleasePrimitiveArrayCritical(values_ref, values_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glVertexAttrib4fv ( GLuint indx, const GLfloat *values ) */
@@ -4801,10 +5942,15 @@
 android_glVertexAttrib4fv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint indx, jobject values_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *values = (GLfloat *) 0;
 
-    values = (GLfloat *)getPointer(_env, values_buf, &_array, &_remaining);
+    values = (GLfloat *)getPointer(_env, values_buf, &_array, &_remaining, &_bufferOffset);
+    if (values == NULL) {
+        char * _valuesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        values = (GLfloat *) (_valuesBase + _bufferOffset);
+    }
     glVertexAttrib4fv(
         (GLuint)indx,
         (GLfloat *)values
@@ -4833,6 +5979,7 @@
 android_glVertexAttribPointerBounds__IIIZILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint indx, jint size, jint type, jboolean normalized, jint stride, jobject ptr_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *ptr = (GLvoid *) 0;
 
@@ -4934,8 +6081,12 @@
 {"glGenTextures", "(ILjava/nio/IntBuffer;)V", (void *) android_glGenTextures__ILjava_nio_IntBuffer_2 },
 {"glGetActiveAttrib", "(III[II[II[II[BI)V", (void *) android_glGetActiveAttrib__III_3II_3II_3II_3BI },
 {"glGetActiveAttrib", "(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;B)V", (void *) android_glGetActiveAttrib__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B },
+{"glGetActiveAttrib", "(II[II[II)Ljava/lang/String;", (void *) android_glGetActiveAttrib1 },
+{"glGetActiveAttrib", "(IILjava/nio/IntBuffer;Ljava/nio/IntBuffer;)Ljava/lang/String;", (void *) android_glGetActiveAttrib2 },
 {"glGetActiveUniform", "(III[II[II[II[BI)V", (void *) android_glGetActiveUniform__III_3II_3II_3II_3BI },
+{"glGetActiveUniform", "(II[II[II)Ljava/lang/String;", (void *) android_glGetActiveUniform1 },
 {"glGetActiveUniform", "(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;B)V", (void *) android_glGetActiveUniform__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B },
+{"glGetActiveUniform", "(IILjava/nio/IntBuffer;Ljava/nio/IntBuffer;)Ljava/lang/String;", (void *) android_glGetActiveUniform2 },
 {"glGetAttachedShaders", "(II[II[II)V", (void *) android_glGetAttachedShaders__II_3II_3II },
 {"glGetAttachedShaders", "(IILjava/nio/IntBuffer;Ljava/nio/IntBuffer;)V", (void *) android_glGetAttachedShaders__IILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2 },
 {"glGetAttribLocation", "(ILjava/lang/String;)I", (void *) android_glGetAttribLocation__ILjava_lang_String_2 },
@@ -4962,6 +6113,7 @@
 {"glGetShaderPrecisionFormat", "(IILjava/nio/IntBuffer;Ljava/nio/IntBuffer;)V", (void *) android_glGetShaderPrecisionFormat__IILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2 },
 {"glGetShaderSource", "(II[II[BI)V", (void *) android_glGetShaderSource__II_3II_3BI },
 {"glGetShaderSource", "(IILjava/nio/IntBuffer;B)V", (void *) android_glGetShaderSource__IILjava_nio_IntBuffer_2B },
+{"glGetShaderSource", "(I)Ljava/lang/String;", (void *) android_glGetShaderSource },
 {"glGetString", "(I)Ljava/lang/String;", (void *) android_glGetString },
 {"glGetTexParameterfv", "(II[FI)V", (void *) android_glGetTexParameterfv__II_3FI },
 {"glGetTexParameterfv", "(IILjava/nio/FloatBuffer;)V", (void *) android_glGetTexParameterfv__IILjava_nio_FloatBuffer_2 },
diff --git a/core/jni/android_os_SystemClock.cpp b/core/jni/android_os_SystemClock.cpp
index 66d58cd..5c135ee 100644
--- a/core/jni/android_os_SystemClock.cpp
+++ b/core/jni/android_os_SystemClock.cpp
@@ -112,6 +112,15 @@
 }
 
 /*
+ * public static native long elapsedRealtimeNano();
+ */
+static jlong android_os_SystemClock_elapsedRealtimeNano(JNIEnv* env,
+        jobject clazz)
+{
+    return (jlong)elapsedRealtimeNano();
+}
+
+/*
  * JNI registration.
  */
 static JNINativeMethod gMethods[] = {
@@ -128,6 +137,8 @@
             (void*) android_os_SystemClock_currentThreadTimeMicro },
     { "currentTimeMicro",             "()J",
             (void*) android_os_SystemClock_currentTimeMicro },
+    { "elapsedRealtimeNanos",      "()J",
+            (void*) android_os_SystemClock_elapsedRealtimeNano },
 };
 int register_android_os_SystemClock(JNIEnv* env)
 {
diff --git a/core/jni/android_os_UEventObserver.cpp b/core/jni/android_os_UEventObserver.cpp
index 5639f4f..3f7c7d2 100644
--- a/core/jni/android_os_UEventObserver.cpp
+++ b/core/jni/android_os_UEventObserver.cpp
@@ -15,6 +15,8 @@
  */
 
 #define LOG_TAG "UEventObserver"
+//#define LOG_NDEBUG 0
+
 #include "utils/Log.h"
 
 #include "hardware_legacy/uevent.h"
@@ -22,34 +24,94 @@
 #include "JNIHelp.h"
 #include "android_runtime/AndroidRuntime.h"
 
-namespace android
-{
+#include <utils/Mutex.h>
+#include <utils/Vector.h>
+#include <utils/String8.h>
+#include <ScopedUtfChars.h>
 
-static void
-android_os_UEventObserver_native_setup(JNIEnv *env, jclass clazz)
-{
+namespace android {
+
+static Mutex gMatchesMutex;
+static Vector<String8> gMatches;
+
+static void nativeSetup(JNIEnv *env, jclass clazz) {
     if (!uevent_init()) {
         jniThrowException(env, "java/lang/RuntimeException",
-                          "Unable to open socket for UEventObserver");
+                "Unable to open socket for UEventObserver");
     }
 }
 
-static int
-android_os_UEventObserver_next_event(JNIEnv *env, jclass clazz, jbyteArray jbuffer)
-{
-    int buf_sz = env->GetArrayLength(jbuffer);
-    char *buffer = (char*)env->GetByteArrayElements(jbuffer, NULL);
+static bool isMatch(const char* buffer, size_t length) {
+    AutoMutex _l(gMatchesMutex);
 
-    int length = uevent_next_event(buffer, buf_sz - 1);
+    for (size_t i = 0; i < gMatches.size(); i++) {
+        const String8& match = gMatches.itemAt(i);
 
-    env->ReleaseByteArrayElements(jbuffer, (jbyte*)buffer, 0);
+        // Consider all zero-delimited fields of the buffer.
+        const char* field = buffer;
+        const char* end = buffer + length + 1;
+        do {
+            if (strstr(field, match.string())) {
+                ALOGV("Matched uevent message with pattern: %s", match.string());
+                return true;
+            }
+            field += strlen(field) + 1;
+        } while (field != end);
+    }
+    return false;
+}
 
-    return length;
+static jstring nativeWaitForNextEvent(JNIEnv *env, jclass clazz) {
+    char buffer[1024];
+
+    for (;;) {
+        int length = uevent_next_event(buffer, sizeof(buffer) - 1);
+        if (length <= 0) {
+            return NULL;
+        }
+        buffer[length] = '\0';
+
+        ALOGV("Received uevent message: %s", buffer);
+
+        if (isMatch(buffer, length)) {
+            // Assume the message is ASCII.
+            jchar message[length];
+            for (int i = 0; i < length; i++) {
+                message[i] = buffer[i];
+            }
+            return env->NewString(message, length);
+        }
+    }
+}
+
+static void nativeAddMatch(JNIEnv* env, jclass clazz, jstring matchStr) {
+    ScopedUtfChars match(env, matchStr);
+
+    AutoMutex _l(gMatchesMutex);
+    gMatches.add(String8(match.c_str()));
+}
+
+static void nativeRemoveMatch(JNIEnv* env, jclass clazz, jstring matchStr) {
+    ScopedUtfChars match(env, matchStr);
+
+    AutoMutex _l(gMatchesMutex);
+    for (size_t i = 0; i < gMatches.size(); i++) {
+        if (gMatches.itemAt(i) == match.c_str()) {
+            gMatches.removeAt(i);
+            break; // only remove first occurrence
+        }
+    }
 }
 
 static JNINativeMethod gMethods[] = {
-    {"native_setup", "()V",   (void *)android_os_UEventObserver_native_setup},
-    {"next_event",   "([B)I", (void *)android_os_UEventObserver_next_event},
+    { "nativeSetup", "()V",
+            (void *)nativeSetup },
+    { "nativeWaitForNextEvent", "()Ljava/lang/String;",
+            (void *)nativeWaitForNextEvent },
+    { "nativeAddMatch", "(Ljava/lang/String;)V",
+            (void *)nativeAddMatch },
+    { "nativeRemoveMatch", "(Ljava/lang/String;)V",
+            (void *)nativeRemoveMatch },
 };
 
 
@@ -64,7 +126,7 @@
     }
 
     return AndroidRuntime::registerNativeMethods(env,
-                "android/os/UEventObserver", gMethods, NELEM(gMethods));
+            "android/os/UEventObserver", gMethods, NELEM(gMethods));
 }
 
 }   // namespace android
diff --git a/core/jni/android_server_BluetoothA2dpService.cpp b/core/jni/android_server_BluetoothA2dpService.cpp
deleted file mode 100644
index d065a9e..0000000
--- a/core/jni/android_server_BluetoothA2dpService.cpp
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
-** Copyright 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.
-*/
-
-#define LOG_TAG "BluetoothA2dpService.cpp"
-
-#include "android_bluetooth_common.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "JNIHelp.h"
-#include "jni.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#ifdef HAVE_BLUETOOTH
-#include <dbus/dbus.h>
-#endif
-
-namespace android {
-
-#ifdef HAVE_BLUETOOTH
-static jmethodID method_onSinkPropertyChanged;
-static jmethodID method_onConnectSinkResult;
-
-typedef struct {
-    JavaVM *vm;
-    int envVer;
-    DBusConnection *conn;
-    jobject me;  // for callbacks to java
-} native_data_t;
-
-static native_data_t *nat = NULL;  // global native data
-static void onConnectSinkResult(DBusMessage *msg, void *user, void *n);
-
-static Properties sink_properties[] = {
-        {"State", DBUS_TYPE_STRING},
-        {"Connected", DBUS_TYPE_BOOLEAN},
-        {"Playing", DBUS_TYPE_BOOLEAN},
-      };
-#endif
-
-/* Returns true on success (even if adapter is present but disabled).
- * Return false if dbus is down, or another serious error (out of memory)
-*/
-static bool initNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    nat = (native_data_t *)calloc(1, sizeof(native_data_t));
-    if (NULL == nat) {
-        ALOGE("%s: out of memory!", __FUNCTION__);
-        return false;
-    }
-    env->GetJavaVM( &(nat->vm) );
-    nat->envVer = env->GetVersion();
-    nat->me = env->NewGlobalRef(object);
-
-    DBusError err;
-    dbus_error_init(&err);
-    dbus_threads_init_default();
-    nat->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
-    if (dbus_error_is_set(&err)) {
-        ALOGE("Could not get onto the system bus: %s", err.message);
-        dbus_error_free(&err);
-        return false;
-    }
-    dbus_connection_set_exit_on_disconnect(nat->conn, FALSE);
-#endif  /*HAVE_BLUETOOTH*/
-    return true;
-}
-
-static void cleanupNative(JNIEnv* env, jobject object) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    if (nat) {
-        dbus_connection_close(nat->conn);
-        env->DeleteGlobalRef(nat->me);
-        free(nat);
-        nat = NULL;
-    }
-#endif
-}
-
-static jobjectArray getSinkPropertiesNative(JNIEnv *env, jobject object,
-                                            jstring path) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    if (nat) {
-        DBusMessage *msg, *reply;
-        DBusError err;
-        dbus_error_init(&err);
-
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        reply = dbus_func_args_timeout(env,
-                                   nat->conn, -1, c_path,
-                                   "org.bluez.AudioSink", "GetProperties",
-                                   DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(path, c_path);
-        if (!reply && dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-            return NULL;
-        } else if (!reply) {
-            ALOGE("DBus reply is NULL in function %s", __FUNCTION__);
-            return NULL;
-        }
-        DBusMessageIter iter;
-        if (dbus_message_iter_init(reply, &iter))
-            return parse_properties(env, &iter, (Properties *)&sink_properties,
-                                 sizeof(sink_properties) / sizeof(Properties));
-    }
-#endif
-    return NULL;
-}
-
-
-static jboolean connectSinkNative(JNIEnv *env, jobject object, jstring path) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    if (nat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        int len = env->GetStringLength(path) + 1;
-        char *context_path = (char *)calloc(len, sizeof(char));
-        strlcpy(context_path, c_path, len);  // for callback
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1, onConnectSinkResult, context_path,
-                                    nat, c_path, "org.bluez.AudioSink", "Connect",
-                                    DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean disconnectSinkNative(JNIEnv *env, jobject object,
-                                     jstring path) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    if (nat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
-                                    c_path, "org.bluez.AudioSink", "Disconnect",
-                                    DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean suspendSinkNative(JNIEnv *env, jobject object,
-                                     jstring path) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    if (nat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
-                           c_path, "org.bluez.audio.Sink", "Suspend",
-                           DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean resumeSinkNative(JNIEnv *env, jobject object,
-                                     jstring path) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    if (nat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
-                           c_path, "org.bluez.audio.Sink", "Resume",
-                           DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean avrcpVolumeUpNative(JNIEnv *env, jobject object,
-                                     jstring path) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    if (nat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
-                           c_path, "org.bluez.Control", "VolumeUp",
-                           DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean avrcpVolumeDownNative(JNIEnv *env, jobject object,
-                                     jstring path) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    if (nat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
-                           c_path, "org.bluez.Control", "VolumeDown",
-                           DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-#ifdef HAVE_BLUETOOTH
-DBusHandlerResult a2dp_event_filter(DBusMessage *msg, JNIEnv *env) {
-    DBusError err;
-
-    if (!nat) {
-        ALOGV("... skipping %s\n", __FUNCTION__);
-        ALOGV("... ignored\n");
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-    }
-
-    dbus_error_init(&err);
-
-    if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) {
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-    }
-
-    DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
-    if (dbus_message_is_signal(msg, "org.bluez.AudioSink",
-                                      "PropertyChanged")) {
-        jobjectArray str_array =
-                    parse_property_change(env, msg, (Properties *)&sink_properties,
-                                sizeof(sink_properties) / sizeof(Properties));
-        const char *c_path = dbus_message_get_path(msg);
-        jstring path = env->NewStringUTF(c_path);
-        env->CallVoidMethod(nat->me,
-                            method_onSinkPropertyChanged,
-                            path,
-                            str_array);
-        env->DeleteLocalRef(path);
-        result = DBUS_HANDLER_RESULT_HANDLED;
-        return result;
-    } else {
-        ALOGV("... ignored");
-    }
-    if (env->ExceptionCheck()) {
-        ALOGE("VM Exception occurred while handling %s.%s (%s) in %s,"
-             " leaving for VM",
-             dbus_message_get_interface(msg), dbus_message_get_member(msg),
-             dbus_message_get_path(msg), __FUNCTION__);
-    }
-
-    return result;
-}
-
-void onConnectSinkResult(DBusMessage *msg, void *user, void *n) {
-    ALOGV("%s", __FUNCTION__);
-
-    native_data_t *nat = (native_data_t *)n;
-    const char *path = (const char *)user;
-    DBusError err;
-    dbus_error_init(&err);
-    JNIEnv *env;
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-
-
-    bool result = JNI_TRUE;
-    if (dbus_set_error_from_message(&err, msg)) {
-        LOG_AND_FREE_DBUS_ERROR(&err);
-        result = JNI_FALSE;
-    }
-    ALOGV("... Device Path = %s, result = %d", path, result);
-
-    jstring jPath = env->NewStringUTF(path);
-    env->CallVoidMethod(nat->me,
-                        method_onConnectSinkResult,
-                        jPath,
-                        result);
-    env->DeleteLocalRef(jPath);
-    free(user);
-}
-
-
-#endif
-
-
-static JNINativeMethod sMethods[] = {
-    {"initNative", "()Z", (void *)initNative},
-    {"cleanupNative", "()V", (void *)cleanupNative},
-
-    /* Bluez audio 4.47 API */
-    {"connectSinkNative", "(Ljava/lang/String;)Z", (void *)connectSinkNative},
-    {"disconnectSinkNative", "(Ljava/lang/String;)Z", (void *)disconnectSinkNative},
-    {"suspendSinkNative", "(Ljava/lang/String;)Z", (void*)suspendSinkNative},
-    {"resumeSinkNative", "(Ljava/lang/String;)Z", (void*)resumeSinkNative},
-    {"getSinkPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;",
-                                    (void *)getSinkPropertiesNative},
-    {"avrcpVolumeUpNative", "(Ljava/lang/String;)Z", (void*)avrcpVolumeUpNative},
-    {"avrcpVolumeDownNative", "(Ljava/lang/String;)Z", (void*)avrcpVolumeDownNative},
-};
-
-int register_android_server_BluetoothA2dpService(JNIEnv *env) {
-    jclass clazz = env->FindClass("android/server/BluetoothA2dpService");
-    if (clazz == NULL) {
-        ALOGE("Can't find android/server/BluetoothA2dpService");
-        return -1;
-    }
-
-#ifdef HAVE_BLUETOOTH
-    method_onSinkPropertyChanged = env->GetMethodID(clazz, "onSinkPropertyChanged",
-                                          "(Ljava/lang/String;[Ljava/lang/String;)V");
-    method_onConnectSinkResult = env->GetMethodID(clazz, "onConnectSinkResult",
-                                                         "(Ljava/lang/String;Z)V");
-#endif
-
-    return AndroidRuntime::registerNativeMethods(env,
-                "android/server/BluetoothA2dpService", sMethods, NELEM(sMethods));
-}
-
-} /* namespace android */
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
deleted file mode 100644
index 8a69ba4..0000000
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ /dev/null
@@ -1,1585 +0,0 @@
-/*
-** Copyright 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.
-*/
-
-#define LOG_TAG "BluetoothEventLoop.cpp"
-
-#include "android_bluetooth_common.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "cutils/sockets.h"
-#include "JNIHelp.h"
-#include "jni.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-
-#ifdef HAVE_BLUETOOTH
-#include <dbus/dbus.h>
-#endif
-
-namespace android {
-
-#define CREATE_DEVICE_ALREADY_EXISTS 1
-#define CREATE_DEVICE_SUCCESS 0
-#define CREATE_DEVICE_FAILED -1
-
-#ifdef HAVE_BLUETOOTH
-static jfieldID field_mNativeData;
-
-static jmethodID method_onPropertyChanged;
-static jmethodID method_onDevicePropertyChanged;
-static jmethodID method_onDeviceFound;
-static jmethodID method_onDeviceDisappeared;
-static jmethodID method_onDeviceCreated;
-static jmethodID method_onDeviceRemoved;
-static jmethodID method_onDeviceDisconnectRequested;
-static jmethodID method_onNetworkDeviceDisconnected;
-static jmethodID method_onNetworkDeviceConnected;
-
-static jmethodID method_onCreatePairedDeviceResult;
-static jmethodID method_onCreateDeviceResult;
-static jmethodID method_onDiscoverServicesResult;
-static jmethodID method_onGetDeviceServiceChannelResult;
-
-static jmethodID method_onRequestPinCode;
-static jmethodID method_onRequestPasskey;
-static jmethodID method_onRequestPasskeyConfirmation;
-static jmethodID method_onRequestPairingConsent;
-static jmethodID method_onDisplayPasskey;
-static jmethodID method_onRequestOobData;
-static jmethodID method_onAgentOutOfBandDataAvailable;
-static jmethodID method_onAgentAuthorize;
-static jmethodID method_onAgentCancel;
-
-static jmethodID method_onInputDevicePropertyChanged;
-static jmethodID method_onInputDeviceConnectionResult;
-static jmethodID method_onPanDevicePropertyChanged;
-static jmethodID method_onPanDeviceConnectionResult;
-static jmethodID method_onHealthDevicePropertyChanged;
-static jmethodID method_onHealthDeviceChannelChanged;
-static jmethodID method_onHealthDeviceConnectionResult;
-
-typedef event_loop_native_data_t native_data_t;
-
-#define EVENT_LOOP_REFS 10
-
-static inline native_data_t * get_native_data(JNIEnv *env, jobject object) {
-    return (native_data_t *)(env->GetIntField(object,
-                                                 field_mNativeData));
-}
-
-native_data_t *get_EventLoop_native_data(JNIEnv *env, jobject object) {
-    return get_native_data(env, object);
-}
-
-#endif
-static void classInitNative(JNIEnv* env, jclass clazz) {
-    ALOGV("%s", __FUNCTION__);
-
-#ifdef HAVE_BLUETOOTH
-    method_onPropertyChanged = env->GetMethodID(clazz, "onPropertyChanged",
-                                                "([Ljava/lang/String;)V");
-    method_onDevicePropertyChanged = env->GetMethodID(clazz,
-                                                      "onDevicePropertyChanged",
-                                                      "(Ljava/lang/String;[Ljava/lang/String;)V");
-    method_onDeviceFound = env->GetMethodID(clazz, "onDeviceFound",
-                                            "(Ljava/lang/String;[Ljava/lang/String;)V");
-    method_onDeviceDisappeared = env->GetMethodID(clazz, "onDeviceDisappeared",
-                                                  "(Ljava/lang/String;)V");
-    method_onDeviceCreated = env->GetMethodID(clazz, "onDeviceCreated", "(Ljava/lang/String;)V");
-    method_onDeviceRemoved = env->GetMethodID(clazz, "onDeviceRemoved", "(Ljava/lang/String;)V");
-    method_onDeviceDisconnectRequested = env->GetMethodID(clazz, "onDeviceDisconnectRequested",
-                                                        "(Ljava/lang/String;)V");
-    method_onNetworkDeviceConnected = env->GetMethodID(clazz, "onNetworkDeviceConnected",
-                                                     "(Ljava/lang/String;Ljava/lang/String;I)V");
-    method_onNetworkDeviceDisconnected = env->GetMethodID(clazz, "onNetworkDeviceDisconnected",
-                                                              "(Ljava/lang/String;)V");
-
-    method_onCreatePairedDeviceResult = env->GetMethodID(clazz, "onCreatePairedDeviceResult",
-                                                         "(Ljava/lang/String;I)V");
-    method_onCreateDeviceResult = env->GetMethodID(clazz, "onCreateDeviceResult",
-                                                         "(Ljava/lang/String;I)V");
-    method_onDiscoverServicesResult = env->GetMethodID(clazz, "onDiscoverServicesResult",
-                                                         "(Ljava/lang/String;Z)V");
-
-    method_onAgentAuthorize = env->GetMethodID(clazz, "onAgentAuthorize",
-                                               "(Ljava/lang/String;Ljava/lang/String;I)V");
-    method_onAgentOutOfBandDataAvailable = env->GetMethodID(clazz, "onAgentOutOfBandDataAvailable",
-                                               "(Ljava/lang/String;)Z");
-    method_onAgentCancel = env->GetMethodID(clazz, "onAgentCancel", "()V");
-    method_onRequestPinCode = env->GetMethodID(clazz, "onRequestPinCode",
-                                               "(Ljava/lang/String;I)V");
-    method_onRequestPasskey = env->GetMethodID(clazz, "onRequestPasskey",
-                                               "(Ljava/lang/String;I)V");
-    method_onRequestPasskeyConfirmation = env->GetMethodID(clazz, "onRequestPasskeyConfirmation",
-                                               "(Ljava/lang/String;II)V");
-    method_onRequestPairingConsent = env->GetMethodID(clazz, "onRequestPairingConsent",
-                                               "(Ljava/lang/String;I)V");
-    method_onDisplayPasskey = env->GetMethodID(clazz, "onDisplayPasskey",
-                                               "(Ljava/lang/String;II)V");
-    method_onInputDevicePropertyChanged = env->GetMethodID(clazz, "onInputDevicePropertyChanged",
-                                               "(Ljava/lang/String;[Ljava/lang/String;)V");
-    method_onInputDeviceConnectionResult = env->GetMethodID(clazz, "onInputDeviceConnectionResult",
-                                               "(Ljava/lang/String;I)V");
-    method_onPanDevicePropertyChanged = env->GetMethodID(clazz, "onPanDevicePropertyChanged",
-                                               "(Ljava/lang/String;[Ljava/lang/String;)V");
-    method_onPanDeviceConnectionResult = env->GetMethodID(clazz, "onPanDeviceConnectionResult",
-                                               "(Ljava/lang/String;I)V");
-    method_onHealthDeviceConnectionResult = env->GetMethodID(clazz,
-                                                             "onHealthDeviceConnectionResult",
-                                                             "(II)V");
-    method_onHealthDevicePropertyChanged = env->GetMethodID(clazz, "onHealthDevicePropertyChanged",
-                                               "(Ljava/lang/String;[Ljava/lang/String;)V");
-    method_onHealthDeviceChannelChanged = env->GetMethodID(clazz, "onHealthDeviceChannelChanged",
-                                               "(Ljava/lang/String;Ljava/lang/String;Z)V");
-    method_onRequestOobData = env->GetMethodID(clazz, "onRequestOobData",
-                                               "(Ljava/lang/String;I)V");
-
-    field_mNativeData = env->GetFieldID(clazz, "mNativeData", "I");
-#endif
-}
-
-static void initializeNativeDataNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t));
-    if (NULL == nat) {
-        ALOGE("%s: out of memory!", __FUNCTION__);
-        return;
-    }
-
-    pthread_mutex_init(&(nat->thread_mutex), NULL);
-
-    env->SetIntField(object, field_mNativeData, (jint)nat);
-
-    {
-        DBusError err;
-        dbus_error_init(&err);
-        dbus_threads_init_default();
-        nat->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
-        if (dbus_error_is_set(&err)) {
-            ALOGE("%s: Could not get onto the system bus!", __FUNCTION__);
-            dbus_error_free(&err);
-        }
-        dbus_connection_set_exit_on_disconnect(nat->conn, FALSE);
-    }
-#endif
-}
-
-static void cleanupNativeDataNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat =
-            (native_data_t *)env->GetIntField(object, field_mNativeData);
-
-    pthread_mutex_destroy(&(nat->thread_mutex));
-
-    if (nat) {
-        free(nat);
-    }
-#endif
-}
-
-#ifdef HAVE_BLUETOOTH
-static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg,
-                                      void *data);
-DBusHandlerResult agent_event_filter(DBusConnection *conn,
-                                     DBusMessage *msg,
-                                     void *data);
-static int register_agent(native_data_t *nat,
-                          const char *agent_path, const char *capabilities);
-
-static const DBusObjectPathVTable agent_vtable = {
-    NULL, agent_event_filter, NULL, NULL, NULL, NULL
-};
-
-static unsigned int unix_events_to_dbus_flags(short events) {
-    return (events & DBUS_WATCH_READABLE ? POLLIN : 0) |
-           (events & DBUS_WATCH_WRITABLE ? POLLOUT : 0) |
-           (events & DBUS_WATCH_ERROR ? POLLERR : 0) |
-           (events & DBUS_WATCH_HANGUP ? POLLHUP : 0);
-}
-
-static short dbus_flags_to_unix_events(unsigned int flags) {
-    return (flags & POLLIN ? DBUS_WATCH_READABLE : 0) |
-           (flags & POLLOUT ? DBUS_WATCH_WRITABLE : 0) |
-           (flags & POLLERR ? DBUS_WATCH_ERROR : 0) |
-           (flags & POLLHUP ? DBUS_WATCH_HANGUP : 0);
-}
-
-static jboolean setUpEventLoop(native_data_t *nat) {
-    ALOGV("%s", __FUNCTION__);
-
-    if (nat != NULL && nat->conn != NULL) {
-        dbus_threads_init_default();
-        DBusError err;
-        dbus_error_init(&err);
-
-        const char *agent_path = "/android/bluetooth/agent";
-        const char *capabilities = "DisplayYesNo";
-        if (register_agent(nat, agent_path, capabilities) < 0) {
-            dbus_connection_unregister_object_path (nat->conn, agent_path);
-            return JNI_FALSE;
-        }
-
-        // Add a filter for all incoming messages
-        if (!dbus_connection_add_filter(nat->conn, event_filter, nat, NULL)){
-            return JNI_FALSE;
-        }
-
-        // Set which messages will be processed by this dbus connection
-        dbus_bus_add_match(nat->conn,
-                "type='signal',interface='org.freedesktop.DBus'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-            return JNI_FALSE;
-        }
-        dbus_bus_add_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Adapter'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-            return JNI_FALSE;
-        }
-        dbus_bus_add_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Device'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-            return JNI_FALSE;
-        }
-        dbus_bus_add_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Input'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-            return JNI_FALSE;
-        }
-        dbus_bus_add_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Network'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-            return JNI_FALSE;
-        }
-        dbus_bus_add_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".NetworkServer'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-            return JNI_FALSE;
-        }
-
-        dbus_bus_add_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".HealthDevice'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-            return JNI_FALSE;
-        }
-
-        dbus_bus_add_match(nat->conn,
-                "type='signal',interface='org.bluez.AudioSink'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-            return JNI_FALSE;
-        }
-
-        return JNI_TRUE;
-    }
-    return JNI_FALSE;
-}
-
-
-const char * get_adapter_path(DBusConnection *conn) {
-    DBusMessage *msg = NULL, *reply = NULL;
-    DBusError err;
-    const char *device_path = NULL;
-    int attempt = 0;
-
-    for (attempt = 0; attempt < 1000 && reply == NULL; attempt ++) {
-        msg = dbus_message_new_method_call("org.bluez", "/",
-              "org.bluez.Manager", "DefaultAdapter");
-        if (!msg) {
-            ALOGE("%s: Can't allocate new method call for get_adapter_path!",
-                  __FUNCTION__);
-            return NULL;
-        }
-        dbus_message_append_args(msg, DBUS_TYPE_INVALID);
-        dbus_error_init(&err);
-        reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);
-
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                if (dbus_error_has_name(&err,
-                    "org.freedesktop.DBus.Error.ServiceUnknown")) {
-                    // bluetoothd is still down, retry
-                    LOG_AND_FREE_DBUS_ERROR(&err);
-                    usleep(10000);  // 10 ms
-                    continue;
-                } else {
-                    // Some other error we weren't expecting
-                    LOG_AND_FREE_DBUS_ERROR(&err);
-                }
-            }
-            goto failed;
-        }
-    }
-    if (attempt == 1000) {
-        ALOGE("Time out while trying to get Adapter path, is bluetoothd up ?");
-        goto failed;
-    }
-
-    if (!dbus_message_get_args(reply, &err, DBUS_TYPE_OBJECT_PATH,
-                               &device_path, DBUS_TYPE_INVALID)
-                               || !device_path){
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        goto failed;
-    }
-    dbus_message_unref(msg);
-    return device_path;
-
-failed:
-    dbus_message_unref(msg);
-    return NULL;
-}
-
-static int register_agent(native_data_t *nat,
-                          const char * agent_path, const char * capabilities)
-{
-    DBusMessage *msg, *reply;
-    DBusError err;
-    dbus_bool_t oob = TRUE;
-
-    if (!dbus_connection_register_object_path(nat->conn, agent_path,
-            &agent_vtable, nat)) {
-        ALOGE("%s: Can't register object path %s for agent!",
-              __FUNCTION__, agent_path);
-        return -1;
-    }
-
-    nat->adapter = get_adapter_path(nat->conn);
-    if (nat->adapter == NULL) {
-        return -1;
-    }
-    msg = dbus_message_new_method_call("org.bluez", nat->adapter,
-          "org.bluez.Adapter", "RegisterAgent");
-    if (!msg) {
-        ALOGE("%s: Can't allocate new method call for agent!",
-              __FUNCTION__);
-        return -1;
-    }
-    dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent_path,
-                             DBUS_TYPE_STRING, &capabilities,
-                             DBUS_TYPE_INVALID);
-
-    dbus_error_init(&err);
-    reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err);
-    dbus_message_unref(msg);
-
-    if (!reply) {
-        ALOGE("%s: Can't register agent!", __FUNCTION__);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        return -1;
-    }
-
-    dbus_message_unref(reply);
-    dbus_connection_flush(nat->conn);
-
-    return 0;
-}
-
-static void tearDownEventLoop(native_data_t *nat) {
-    ALOGV("%s", __FUNCTION__);
-    if (nat != NULL && nat->conn != NULL) {
-
-        DBusMessage *msg, *reply;
-        DBusError err;
-        dbus_error_init(&err);
-        const char * agent_path = "/android/bluetooth/agent";
-
-        msg = dbus_message_new_method_call("org.bluez",
-                                           nat->adapter,
-                                           "org.bluez.Adapter",
-                                           "UnregisterAgent");
-        if (msg != NULL) {
-            dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent_path,
-                                     DBUS_TYPE_INVALID);
-            reply = dbus_connection_send_with_reply_and_block(nat->conn,
-                                                              msg, -1, &err);
-
-            if (!reply) {
-                if (dbus_error_is_set(&err)) {
-                    LOG_AND_FREE_DBUS_ERROR(&err);
-                    dbus_error_free(&err);
-                }
-            } else {
-                dbus_message_unref(reply);
-            }
-            dbus_message_unref(msg);
-        } else {
-             ALOGE("%s: Can't create new method call!", __FUNCTION__);
-        }
-
-        dbus_connection_flush(nat->conn);
-        dbus_connection_unregister_object_path(nat->conn, agent_path);
-
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".AudioSink'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Device'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Input'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Network'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".NetworkServer'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".HealthDevice'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='org.bluez.audio.Manager'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Adapter'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-        dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='org.freedesktop.DBus'",
-                &err);
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR(&err);
-        }
-
-        dbus_connection_remove_filter(nat->conn, event_filter, nat);
-    }
-}
-
-
-#define EVENT_LOOP_EXIT 1
-#define EVENT_LOOP_ADD  2
-#define EVENT_LOOP_REMOVE 3
-#define EVENT_LOOP_WAKEUP 4
-
-dbus_bool_t dbusAddWatch(DBusWatch *watch, void *data) {
-    native_data_t *nat = (native_data_t *)data;
-
-    if (dbus_watch_get_enabled(watch)) {
-        // note that we can't just send the watch and inspect it later
-        // because we may get a removeWatch call before this data is reacted
-        // to by our eventloop and remove this watch..  reading the add first
-        // and then inspecting the recently deceased watch would be bad.
-        char control = EVENT_LOOP_ADD;
-        write(nat->controlFdW, &control, sizeof(char));
-
-        int fd = dbus_watch_get_fd(watch);
-        write(nat->controlFdW, &fd, sizeof(int));
-
-        unsigned int flags = dbus_watch_get_flags(watch);
-        write(nat->controlFdW, &flags, sizeof(unsigned int));
-
-        write(nat->controlFdW, &watch, sizeof(DBusWatch*));
-    }
-    return true;
-}
-
-void dbusRemoveWatch(DBusWatch *watch, void *data) {
-    native_data_t *nat = (native_data_t *)data;
-
-    char control = EVENT_LOOP_REMOVE;
-    write(nat->controlFdW, &control, sizeof(char));
-
-    int fd = dbus_watch_get_fd(watch);
-    write(nat->controlFdW, &fd, sizeof(int));
-
-    unsigned int flags = dbus_watch_get_flags(watch);
-    write(nat->controlFdW, &flags, sizeof(unsigned int));
-}
-
-void dbusToggleWatch(DBusWatch *watch, void *data) {
-    if (dbus_watch_get_enabled(watch)) {
-        dbusAddWatch(watch, data);
-    } else {
-        dbusRemoveWatch(watch, data);
-    }
-}
-
-void dbusWakeup(void *data) {
-    native_data_t *nat = (native_data_t *)data;
-
-    char control = EVENT_LOOP_WAKEUP;
-    write(nat->controlFdW, &control, sizeof(char));
-}
-
-static void handleWatchAdd(native_data_t *nat) {
-    DBusWatch *watch;
-    int newFD;
-    unsigned int flags;
-
-    read(nat->controlFdR, &newFD, sizeof(int));
-    read(nat->controlFdR, &flags, sizeof(unsigned int));
-    read(nat->controlFdR, &watch, sizeof(DBusWatch *));
-    short events = dbus_flags_to_unix_events(flags);
-
-    for (int y = 0; y<nat->pollMemberCount; y++) {
-        if ((nat->pollData[y].fd == newFD) &&
-                (nat->pollData[y].events == events)) {
-            ALOGV("DBusWatch duplicate add");
-            return;
-        }
-    }
-    if (nat->pollMemberCount == nat->pollDataSize) {
-        ALOGV("Bluetooth EventLoop poll struct growing");
-        struct pollfd *temp = (struct pollfd *)malloc(
-                sizeof(struct pollfd) * (nat->pollMemberCount+1));
-        if (!temp) {
-            return;
-        }
-        memcpy(temp, nat->pollData, sizeof(struct pollfd) *
-                nat->pollMemberCount);
-        free(nat->pollData);
-        nat->pollData = temp;
-        DBusWatch **temp2 = (DBusWatch **)malloc(sizeof(DBusWatch *) *
-                (nat->pollMemberCount+1));
-        if (!temp2) {
-            return;
-        }
-        memcpy(temp2, nat->watchData, sizeof(DBusWatch *) *
-                nat->pollMemberCount);
-        free(nat->watchData);
-        nat->watchData = temp2;
-        nat->pollDataSize++;
-    }
-    nat->pollData[nat->pollMemberCount].fd = newFD;
-    nat->pollData[nat->pollMemberCount].revents = 0;
-    nat->pollData[nat->pollMemberCount].events = events;
-    nat->watchData[nat->pollMemberCount] = watch;
-    nat->pollMemberCount++;
-}
-
-static void handleWatchRemove(native_data_t *nat) {
-    int removeFD;
-    unsigned int flags;
-
-    read(nat->controlFdR, &removeFD, sizeof(int));
-    read(nat->controlFdR, &flags, sizeof(unsigned int));
-    short events = dbus_flags_to_unix_events(flags);
-
-    for (int y = 0; y < nat->pollMemberCount; y++) {
-        if ((nat->pollData[y].fd == removeFD) &&
-                (nat->pollData[y].events == events)) {
-            int newCount = --nat->pollMemberCount;
-            // copy the last live member over this one
-            nat->pollData[y].fd = nat->pollData[newCount].fd;
-            nat->pollData[y].events = nat->pollData[newCount].events;
-            nat->pollData[y].revents = nat->pollData[newCount].revents;
-            nat->watchData[y] = nat->watchData[newCount];
-            return;
-        }
-    }
-    ALOGW("WatchRemove given with unknown watch");
-}
-
-static void *eventLoopMain(void *ptr) {
-    native_data_t *nat = (native_data_t *)ptr;
-    JNIEnv *env;
-
-    JavaVMAttachArgs args;
-    char name[] = "BT EventLoop";
-    args.version = nat->envVer;
-    args.name = name;
-    args.group = NULL;
-
-    nat->vm->AttachCurrentThread(&env, &args);
-
-    dbus_connection_set_watch_functions(nat->conn, dbusAddWatch,
-            dbusRemoveWatch, dbusToggleWatch, ptr, NULL);
-    dbus_connection_set_wakeup_main_function(nat->conn, dbusWakeup, ptr, NULL);
-
-    nat->running = true;
-
-    while (1) {
-        for (int i = 0; i < nat->pollMemberCount; i++) {
-            if (!nat->pollData[i].revents) {
-                continue;
-            }
-            if (nat->pollData[i].fd == nat->controlFdR) {
-                char data;
-                while (recv(nat->controlFdR, &data, sizeof(char), MSG_DONTWAIT)
-                        != -1) {
-                    switch (data) {
-                    case EVENT_LOOP_EXIT:
-                    {
-                        dbus_connection_set_watch_functions(nat->conn,
-                                NULL, NULL, NULL, NULL, NULL);
-                        tearDownEventLoop(nat);
-                        nat->vm->DetachCurrentThread();
-
-                        int fd = nat->controlFdR;
-                        nat->controlFdR = 0;
-                        close(fd);
-                        return NULL;
-                    }
-                    case EVENT_LOOP_ADD:
-                    {
-                        handleWatchAdd(nat);
-                        break;
-                    }
-                    case EVENT_LOOP_REMOVE:
-                    {
-                        handleWatchRemove(nat);
-                        break;
-                    }
-                    case EVENT_LOOP_WAKEUP:
-                    {
-                        // noop
-                        break;
-                    }
-                    }
-                }
-            } else {
-                short events = nat->pollData[i].revents;
-                unsigned int flags = unix_events_to_dbus_flags(events);
-                dbus_watch_handle(nat->watchData[i], flags);
-                nat->pollData[i].revents = 0;
-                // can only do one - it may have caused a 'remove'
-                break;
-            }
-        }
-        while (dbus_connection_dispatch(nat->conn) ==
-                DBUS_DISPATCH_DATA_REMAINS) {
-        }
-
-        poll(nat->pollData, nat->pollMemberCount, -1);
-    }
-}
-#endif // HAVE_BLUETOOTH
-
-static jboolean startEventLoopNative(JNIEnv *env, jobject object) {
-    jboolean result = JNI_FALSE;
-#ifdef HAVE_BLUETOOTH
-    event_loop_native_data_t *nat = get_native_data(env, object);
-
-    pthread_mutex_lock(&(nat->thread_mutex));
-
-    nat->running = false;
-
-    if (nat->pollData) {
-        ALOGW("trying to start EventLoop a second time!");
-        pthread_mutex_unlock( &(nat->thread_mutex) );
-        return JNI_FALSE;
-    }
-
-    nat->pollData = (struct pollfd *)calloc(
-            DEFAULT_INITIAL_POLLFD_COUNT, sizeof(struct pollfd));
-    if (!nat->pollData) {
-        ALOGE("out of memory error starting EventLoop!");
-        goto done;
-    }
-
-    nat->watchData = (DBusWatch **)calloc(
-            DEFAULT_INITIAL_POLLFD_COUNT, sizeof(DBusWatch *));
-    if (!nat->watchData) {
-        ALOGE("out of memory error starting EventLoop!");
-        goto done;
-    }
-
-    nat->pollDataSize = DEFAULT_INITIAL_POLLFD_COUNT;
-    nat->pollMemberCount = 1;
-
-    if (socketpair(AF_LOCAL, SOCK_STREAM, 0, &(nat->controlFdR))) {
-        ALOGE("Error getting BT control socket");
-        goto done;
-    }
-    nat->pollData[0].fd = nat->controlFdR;
-    nat->pollData[0].events = POLLIN;
-
-    env->GetJavaVM( &(nat->vm) );
-    nat->envVer = env->GetVersion();
-
-    nat->me = env->NewGlobalRef(object);
-
-    if (setUpEventLoop(nat) != JNI_TRUE) {
-        ALOGE("failure setting up Event Loop!");
-        goto done;
-    }
-
-    pthread_create(&(nat->thread), NULL, eventLoopMain, nat);
-    result = JNI_TRUE;
-
-done:
-    if (JNI_FALSE == result) {
-        if (nat->controlFdW) {
-            close(nat->controlFdW);
-            nat->controlFdW = 0;
-        }
-        if (nat->controlFdR) {
-            close(nat->controlFdR);
-            nat->controlFdR = 0;
-        }
-        if (nat->me) env->DeleteGlobalRef(nat->me);
-        nat->me = NULL;
-        if (nat->pollData) free(nat->pollData);
-        nat->pollData = NULL;
-        if (nat->watchData) free(nat->watchData);
-        nat->watchData = NULL;
-        nat->pollDataSize = 0;
-        nat->pollMemberCount = 0;
-    }
-
-    pthread_mutex_unlock(&(nat->thread_mutex));
-#endif // HAVE_BLUETOOTH
-    return result;
-}
-
-static void stopEventLoopNative(JNIEnv *env, jobject object) {
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-
-    pthread_mutex_lock(&(nat->thread_mutex));
-    if (nat->pollData) {
-        char data = EVENT_LOOP_EXIT;
-        ssize_t t = write(nat->controlFdW, &data, sizeof(char));
-        void *ret;
-        pthread_join(nat->thread, &ret);
-
-        env->DeleteGlobalRef(nat->me);
-        nat->me = NULL;
-        free(nat->pollData);
-        nat->pollData = NULL;
-        free(nat->watchData);
-        nat->watchData = NULL;
-        nat->pollDataSize = 0;
-        nat->pollMemberCount = 0;
-
-        int fd = nat->controlFdW;
-        nat->controlFdW = 0;
-        close(fd);
-    }
-    nat->running = false;
-    pthread_mutex_unlock(&(nat->thread_mutex));
-#endif // HAVE_BLUETOOTH
-}
-
-static jboolean isEventLoopRunningNative(JNIEnv *env, jobject object) {
-    jboolean result = JNI_FALSE;
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-
-    pthread_mutex_lock(&(nat->thread_mutex));
-    if (nat->running) {
-        result = JNI_TRUE;
-    }
-    pthread_mutex_unlock(&(nat->thread_mutex));
-
-#endif // HAVE_BLUETOOTH
-    return result;
-}
-
-#ifdef HAVE_BLUETOOTH
-extern DBusHandlerResult a2dp_event_filter(DBusMessage *msg, JNIEnv *env);
-
-// Called by dbus during WaitForAndDispatchEventNative()
-static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg,
-                                      void *data) {
-    native_data_t *nat;
-    JNIEnv *env;
-    DBusError err;
-    DBusHandlerResult ret;
-
-    dbus_error_init(&err);
-
-    nat = (native_data_t *)data;
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-    if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) {
-        ALOGV("%s: not interested (not a signal).", __FUNCTION__);
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-    }
-
-    ALOGV("%s: Received signal %s:%s from %s", __FUNCTION__,
-        dbus_message_get_interface(msg), dbus_message_get_member(msg),
-        dbus_message_get_path(msg));
-
-    env->PushLocalFrame(EVENT_LOOP_REFS);
-    if (dbus_message_is_signal(msg,
-                               "org.bluez.Adapter",
-                               "DeviceFound")) {
-        char *c_address;
-        DBusMessageIter iter;
-        jobjectArray str_array = NULL;
-        if (dbus_message_iter_init(msg, &iter)) {
-            dbus_message_iter_get_basic(&iter, &c_address);
-            if (dbus_message_iter_next(&iter))
-                str_array =
-                    parse_remote_device_properties(env, &iter);
-        }
-        if (str_array != NULL) {
-            env->CallVoidMethod(nat->me,
-                                method_onDeviceFound,
-                                env->NewStringUTF(c_address),
-                                str_array);
-        } else
-            LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.Adapter",
-                                     "DeviceDisappeared")) {
-        char *c_address;
-        if (dbus_message_get_args(msg, &err,
-                                  DBUS_TYPE_STRING, &c_address,
-                                  DBUS_TYPE_INVALID)) {
-            ALOGV("... address = %s", c_address);
-            env->CallVoidMethod(nat->me, method_onDeviceDisappeared,
-                                env->NewStringUTF(c_address));
-        } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.Adapter",
-                                     "DeviceCreated")) {
-        char *c_object_path;
-        if (dbus_message_get_args(msg, &err,
-                                  DBUS_TYPE_OBJECT_PATH, &c_object_path,
-                                  DBUS_TYPE_INVALID)) {
-            ALOGV("... address = %s", c_object_path);
-            env->CallVoidMethod(nat->me,
-                                method_onDeviceCreated,
-                                env->NewStringUTF(c_object_path));
-        } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.Adapter",
-                                     "DeviceRemoved")) {
-        char *c_object_path;
-        if (dbus_message_get_args(msg, &err,
-                                 DBUS_TYPE_OBJECT_PATH, &c_object_path,
-                                 DBUS_TYPE_INVALID)) {
-           ALOGV("... Object Path = %s", c_object_path);
-           env->CallVoidMethod(nat->me,
-                               method_onDeviceRemoved,
-                               env->NewStringUTF(c_object_path));
-        } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        goto success;
-    } else if (dbus_message_is_signal(msg,
-                                      "org.bluez.Adapter",
-                                      "PropertyChanged")) {
-        jobjectArray str_array = parse_adapter_property_change(env, msg);
-        if (str_array != NULL) {
-            /* Check if bluetoothd has (re)started, if so update the path. */
-            jstring property =(jstring) env->GetObjectArrayElement(str_array, 0);
-            const char *c_property = env->GetStringUTFChars(property, NULL);
-            if (!strncmp(c_property, "Powered", strlen("Powered"))) {
-                jstring value =
-                    (jstring) env->GetObjectArrayElement(str_array, 1);
-                const char *c_value = env->GetStringUTFChars(value, NULL);
-                if (!strncmp(c_value, "true", strlen("true")))
-                    nat->adapter = get_adapter_path(nat->conn);
-                env->ReleaseStringUTFChars(value, c_value);
-            }
-            env->ReleaseStringUTFChars(property, c_property);
-
-            env->CallVoidMethod(nat->me,
-                              method_onPropertyChanged,
-                              str_array);
-        } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        goto success;
-    } else if (dbus_message_is_signal(msg,
-                                      "org.bluez.Device",
-                                      "PropertyChanged")) {
-        jobjectArray str_array = parse_remote_device_property_change(env, msg);
-        if (str_array != NULL) {
-            const char *remote_device_path = dbus_message_get_path(msg);
-            env->CallVoidMethod(nat->me,
-                            method_onDevicePropertyChanged,
-                            env->NewStringUTF(remote_device_path),
-                            str_array);
-        } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        goto success;
-    } else if (dbus_message_is_signal(msg,
-                                      "org.bluez.Device",
-                                      "DisconnectRequested")) {
-        const char *remote_device_path = dbus_message_get_path(msg);
-        env->CallVoidMethod(nat->me,
-                            method_onDeviceDisconnectRequested,
-                            env->NewStringUTF(remote_device_path));
-        goto success;
-    } else if (dbus_message_is_signal(msg,
-                                      "org.bluez.Input",
-                                      "PropertyChanged")) {
-
-        jobjectArray str_array =
-                    parse_input_property_change(env, msg);
-        if (str_array != NULL) {
-            const char *c_path = dbus_message_get_path(msg);
-            env->CallVoidMethod(nat->me,
-                                method_onInputDevicePropertyChanged,
-                                env->NewStringUTF(c_path),
-                                str_array);
-        } else {
-            LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        }
-        goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.Network",
-                                     "PropertyChanged")) {
-
-       jobjectArray str_array =
-                   parse_pan_property_change(env, msg);
-       if (str_array != NULL) {
-           const char *c_path = dbus_message_get_path(msg);
-           env->CallVoidMethod(nat->me,
-                               method_onPanDevicePropertyChanged,
-                               env->NewStringUTF(c_path),
-                               str_array);
-       } else {
-           LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-       }
-       goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.NetworkServer",
-                                     "DeviceDisconnected")) {
-       char *c_address;
-       if (dbus_message_get_args(msg, &err,
-                                  DBUS_TYPE_STRING, &c_address,
-                                  DBUS_TYPE_INVALID)) {
-           env->CallVoidMethod(nat->me,
-                               method_onNetworkDeviceDisconnected,
-                               env->NewStringUTF(c_address));
-       } else {
-           LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-       }
-       goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.NetworkServer",
-                                     "DeviceConnected")) {
-       char *c_address;
-       char *c_iface;
-       uint16_t uuid;
-
-       if (dbus_message_get_args(msg, &err,
-                                  DBUS_TYPE_STRING, &c_address,
-                                  DBUS_TYPE_STRING, &c_iface,
-                                  DBUS_TYPE_UINT16, &uuid,
-                                  DBUS_TYPE_INVALID)) {
-           env->CallVoidMethod(nat->me,
-                               method_onNetworkDeviceConnected,
-                               env->NewStringUTF(c_address),
-                               env->NewStringUTF(c_iface),
-                               uuid);
-       } else {
-           LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-       }
-       goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.HealthDevice",
-                                     "ChannelConnected")) {
-       const char *c_path = dbus_message_get_path(msg);
-       const char *c_channel_path;
-       jboolean exists = JNI_TRUE;
-       if (dbus_message_get_args(msg, &err,
-                                  DBUS_TYPE_OBJECT_PATH, &c_channel_path,
-                                  DBUS_TYPE_INVALID)) {
-           env->CallVoidMethod(nat->me,
-                               method_onHealthDeviceChannelChanged,
-                               env->NewStringUTF(c_path),
-                               env->NewStringUTF(c_channel_path),
-                               exists);
-       } else {
-           LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-       }
-       goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.HealthDevice",
-                                     "ChannelDeleted")) {
-
-       const char *c_path = dbus_message_get_path(msg);
-       const char *c_channel_path;
-       jboolean exists = JNI_FALSE;
-       if (dbus_message_get_args(msg, &err,
-                                  DBUS_TYPE_OBJECT_PATH, &c_channel_path,
-                                  DBUS_TYPE_INVALID)) {
-           env->CallVoidMethod(nat->me,
-                               method_onHealthDeviceChannelChanged,
-                               env->NewStringUTF(c_path),
-                               env->NewStringUTF(c_channel_path),
-                               exists);
-       } else {
-           LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-       }
-       goto success;
-    } else if (dbus_message_is_signal(msg,
-                                     "org.bluez.HealthDevice",
-                                     "PropertyChanged")) {
-        jobjectArray str_array =
-                    parse_health_device_property_change(env, msg);
-        if (str_array != NULL) {
-            const char *c_path = dbus_message_get_path(msg);
-            env->CallVoidMethod(nat->me,
-                                method_onHealthDevicePropertyChanged,
-                                env->NewStringUTF(c_path),
-                                str_array);
-       } else {
-           LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-       }
-       goto success;
-    }
-
-    ret = a2dp_event_filter(msg, env);
-    env->PopLocalFrame(NULL);
-    return ret;
-
-success:
-    env->PopLocalFrame(NULL);
-    return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-// Called by dbus during WaitForAndDispatchEventNative()
-DBusHandlerResult agent_event_filter(DBusConnection *conn,
-                                     DBusMessage *msg, void *data) {
-    native_data_t *nat = (native_data_t *)data;
-    JNIEnv *env;
-    if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
-        ALOGV("%s: not interested (not a method call).", __FUNCTION__);
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-    }
-    ALOGI("%s: Received method %s:%s", __FUNCTION__,
-         dbus_message_get_interface(msg), dbus_message_get_member(msg));
-
-    if (nat == NULL) return DBUS_HANDLER_RESULT_HANDLED;
-
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-    env->PushLocalFrame(EVENT_LOOP_REFS);
-
-    if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "Cancel")) {
-        env->CallVoidMethod(nat->me, method_onAgentCancel);
-        // reply
-        DBusMessage *reply = dbus_message_new_method_return(msg);
-        if (!reply) {
-            ALOGE("%s: Cannot create message reply\n", __FUNCTION__);
-            goto failure;
-        }
-        dbus_connection_send(nat->conn, reply, NULL);
-        dbus_message_unref(reply);
-        goto success;
-
-    } else if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "Authorize")) {
-        char *object_path;
-        const char *uuid;
-        if (!dbus_message_get_args(msg, NULL,
-                                   DBUS_TYPE_OBJECT_PATH, &object_path,
-                                   DBUS_TYPE_STRING, &uuid,
-                                   DBUS_TYPE_INVALID)) {
-            ALOGE("%s: Invalid arguments for Authorize() method", __FUNCTION__);
-            goto failure;
-        }
-
-        ALOGV("... object_path = %s", object_path);
-        ALOGV("... uuid = %s", uuid);
-
-        dbus_message_ref(msg);  // increment refcount because we pass to java
-        env->CallVoidMethod(nat->me, method_onAgentAuthorize,
-                env->NewStringUTF(object_path), env->NewStringUTF(uuid),
-                int(msg));
-
-        goto success;
-    } else if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "OutOfBandAvailable")) {
-        char *object_path;
-        if (!dbus_message_get_args(msg, NULL,
-                                   DBUS_TYPE_OBJECT_PATH, &object_path,
-                                   DBUS_TYPE_INVALID)) {
-            ALOGE("%s: Invalid arguments for OutOfBandData available() method", __FUNCTION__);
-            goto failure;
-        }
-
-        ALOGV("... object_path = %s", object_path);
-
-        bool available =
-            env->CallBooleanMethod(nat->me, method_onAgentOutOfBandDataAvailable,
-                env->NewStringUTF(object_path));
-
-
-        // reply
-        if (available) {
-            DBusMessage *reply = dbus_message_new_method_return(msg);
-            if (!reply) {
-                ALOGE("%s: Cannot create message reply\n", __FUNCTION__);
-                goto failure;
-            }
-            dbus_connection_send(nat->conn, reply, NULL);
-            dbus_message_unref(reply);
-        } else {
-            DBusMessage *reply = dbus_message_new_error(msg,
-                    "org.bluez.Error.DoesNotExist", "OutofBand data not available");
-            if (!reply) {
-                ALOGE("%s: Cannot create message reply\n", __FUNCTION__);
-                goto failure;
-            }
-            dbus_connection_send(nat->conn, reply, NULL);
-            dbus_message_unref(reply);
-        }
-        goto success;
-    } else if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "RequestPinCode")) {
-        char *object_path;
-        if (!dbus_message_get_args(msg, NULL,
-                                   DBUS_TYPE_OBJECT_PATH, &object_path,
-                                   DBUS_TYPE_INVALID)) {
-            ALOGE("%s: Invalid arguments for RequestPinCode() method", __FUNCTION__);
-            goto failure;
-        }
-
-        dbus_message_ref(msg);  // increment refcount because we pass to java
-        env->CallVoidMethod(nat->me, method_onRequestPinCode,
-                                       env->NewStringUTF(object_path),
-                                       int(msg));
-        goto success;
-    } else if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "RequestPasskey")) {
-        char *object_path;
-        if (!dbus_message_get_args(msg, NULL,
-                                   DBUS_TYPE_OBJECT_PATH, &object_path,
-                                   DBUS_TYPE_INVALID)) {
-            ALOGE("%s: Invalid arguments for RequestPasskey() method", __FUNCTION__);
-            goto failure;
-        }
-
-        dbus_message_ref(msg);  // increment refcount because we pass to java
-        env->CallVoidMethod(nat->me, method_onRequestPasskey,
-                                       env->NewStringUTF(object_path),
-                                       int(msg));
-        goto success;
-    } else if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "RequestOobData")) {
-        char *object_path;
-        if (!dbus_message_get_args(msg, NULL,
-                                   DBUS_TYPE_OBJECT_PATH, &object_path,
-                                   DBUS_TYPE_INVALID)) {
-            ALOGE("%s: Invalid arguments for RequestOobData() method", __FUNCTION__);
-            goto failure;
-        }
-
-        dbus_message_ref(msg);  // increment refcount because we pass to java
-        env->CallVoidMethod(nat->me, method_onRequestOobData,
-                                       env->NewStringUTF(object_path),
-                                       int(msg));
-        goto success;
-    } else if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "DisplayPasskey")) {
-        char *object_path;
-        uint32_t passkey;
-        if (!dbus_message_get_args(msg, NULL,
-                                   DBUS_TYPE_OBJECT_PATH, &object_path,
-                                   DBUS_TYPE_UINT32, &passkey,
-                                   DBUS_TYPE_INVALID)) {
-            ALOGE("%s: Invalid arguments for RequestPasskey() method", __FUNCTION__);
-            goto failure;
-        }
-
-        dbus_message_ref(msg);  // increment refcount because we pass to java
-        env->CallVoidMethod(nat->me, method_onDisplayPasskey,
-                                       env->NewStringUTF(object_path),
-                                       passkey,
-                                       int(msg));
-        goto success;
-    } else if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "RequestConfirmation")) {
-        char *object_path;
-        uint32_t passkey;
-        if (!dbus_message_get_args(msg, NULL,
-                                   DBUS_TYPE_OBJECT_PATH, &object_path,
-                                   DBUS_TYPE_UINT32, &passkey,
-                                   DBUS_TYPE_INVALID)) {
-            ALOGE("%s: Invalid arguments for RequestConfirmation() method", __FUNCTION__);
-            goto failure;
-        }
-
-        dbus_message_ref(msg);  // increment refcount because we pass to java
-        env->CallVoidMethod(nat->me, method_onRequestPasskeyConfirmation,
-                                       env->NewStringUTF(object_path),
-                                       passkey,
-                                       int(msg));
-        goto success;
-    } else if (dbus_message_is_method_call(msg,
-            "org.bluez.Agent", "RequestPairingConsent")) {
-        char *object_path;
-        if (!dbus_message_get_args(msg, NULL,
-                                   DBUS_TYPE_OBJECT_PATH, &object_path,
-                                   DBUS_TYPE_INVALID)) {
-            ALOGE("%s: Invalid arguments for RequestPairingConsent() method", __FUNCTION__);
-            goto failure;
-        }
-
-        dbus_message_ref(msg);  // increment refcount because we pass to java
-        env->CallVoidMethod(nat->me, method_onRequestPairingConsent,
-                                       env->NewStringUTF(object_path),
-                                       int(msg));
-        goto success;
-    } else if (dbus_message_is_method_call(msg,
-                  "org.bluez.Agent", "Release")) {
-        // reply
-        DBusMessage *reply = dbus_message_new_method_return(msg);
-        if (!reply) {
-            ALOGE("%s: Cannot create message reply\n", __FUNCTION__);
-            goto failure;
-        }
-        dbus_connection_send(nat->conn, reply, NULL);
-        dbus_message_unref(reply);
-        goto success;
-    } else {
-        ALOGV("%s:%s is ignored", dbus_message_get_interface(msg), dbus_message_get_member(msg));
-    }
-
-failure:
-    env->PopLocalFrame(NULL);
-    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
-success:
-    env->PopLocalFrame(NULL);
-    return DBUS_HANDLER_RESULT_HANDLED;
-
-}
-#endif
-
-
-#ifdef HAVE_BLUETOOTH
-
-void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *n) {
-    ALOGV("%s", __FUNCTION__);
-
-    native_data_t *nat = (native_data_t *)n;
-    const char *address = (const char *)user;
-    DBusError err;
-    dbus_error_init(&err);
-    JNIEnv *env;
-    jstring addr;
-
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-
-    ALOGV("... address = %s", address);
-
-    jint result = BOND_RESULT_SUCCESS;
-    if (dbus_set_error_from_message(&err, msg)) {
-        if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationFailed")) {
-            // Pins did not match, or remote device did not respond to pin
-            // request in time
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            result = BOND_RESULT_AUTH_FAILED;
-        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationRejected")) {
-            // We rejected pairing, or the remote side rejected pairing. This
-            // happens if either side presses 'cancel' at the pairing dialog.
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            result = BOND_RESULT_AUTH_REJECTED;
-        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationCanceled")) {
-            // Not sure if this happens
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            result = BOND_RESULT_AUTH_CANCELED;
-        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.ConnectionAttemptFailed")) {
-            // Other device is not responding at all
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            result = BOND_RESULT_REMOTE_DEVICE_DOWN;
-        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AlreadyExists")) {
-            // already bonded
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            result = BOND_RESULT_SUCCESS;
-        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.InProgress") &&
-                   !strcmp(err.message, "Bonding in progress")) {
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            goto done;
-        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.InProgress") &&
-                   !strcmp(err.message, "Discover in progress")) {
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            result = BOND_RESULT_DISCOVERY_IN_PROGRESS;
-        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.RepeatedAttempts")) {
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            result = BOND_RESULT_REPEATED_ATTEMPTS;
-        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationTimeout")) {
-            ALOGV("... error = %s (%s)\n", err.name, err.message);
-            result = BOND_RESULT_AUTH_TIMEOUT;
-        } else {
-            ALOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message);
-            result = BOND_RESULT_ERROR;
-        }
-    }
-
-    addr = env->NewStringUTF(address);
-    env->CallVoidMethod(nat->me,
-                        method_onCreatePairedDeviceResult,
-                        addr,
-                        result);
-    env->DeleteLocalRef(addr);
-done:
-    dbus_error_free(&err);
-    free(user);
-}
-
-void onCreateDeviceResult(DBusMessage *msg, void *user, void *n) {
-    ALOGV("%s", __FUNCTION__);
-
-    native_data_t *nat = (native_data_t *)n;
-    const char *address= (const char *)user;
-    DBusError err;
-    dbus_error_init(&err);
-    JNIEnv *env;
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-
-    ALOGV("... Address = %s", address);
-
-    jint result = CREATE_DEVICE_SUCCESS;
-    if (dbus_set_error_from_message(&err, msg)) {
-        if (dbus_error_has_name(&err, "org.bluez.Error.AlreadyExists")) {
-            result = CREATE_DEVICE_ALREADY_EXISTS;
-        } else {
-            result = CREATE_DEVICE_FAILED;
-        }
-        LOG_AND_FREE_DBUS_ERROR(&err);
-    }
-    jstring addr = env->NewStringUTF(address);
-    env->CallVoidMethod(nat->me,
-                        method_onCreateDeviceResult,
-                        addr,
-                        result);
-    env->DeleteLocalRef(addr);
-    free(user);
-}
-
-void onDiscoverServicesResult(DBusMessage *msg, void *user, void *n) {
-    ALOGV("%s", __FUNCTION__);
-
-    native_data_t *nat = (native_data_t *)n;
-    const char *path = (const char *)user;
-    DBusError err;
-    dbus_error_init(&err);
-    JNIEnv *env;
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-
-    ALOGV("... Device Path = %s", path);
-
-    bool result = JNI_TRUE;
-    if (dbus_set_error_from_message(&err, msg)) {
-        LOG_AND_FREE_DBUS_ERROR(&err);
-        result = JNI_FALSE;
-    }
-    jstring jPath = env->NewStringUTF(path);
-    env->CallVoidMethod(nat->me,
-                        method_onDiscoverServicesResult,
-                        jPath,
-                        result);
-    env->DeleteLocalRef(jPath);
-    free(user);
-}
-
-void onGetDeviceServiceChannelResult(DBusMessage *msg, void *user, void *n) {
-    ALOGV("%s", __FUNCTION__);
-
-    const char *address = (const char *) user;
-    native_data_t *nat = (native_data_t *) n;
-
-    DBusError err;
-    dbus_error_init(&err);
-    JNIEnv *env;
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-
-    jint channel = -2;
-
-    ALOGV("... address = %s", address);
-
-    if (dbus_set_error_from_message(&err, msg) ||
-        !dbus_message_get_args(msg, &err,
-                               DBUS_TYPE_INT32, &channel,
-                               DBUS_TYPE_INVALID)) {
-        ALOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message);
-        dbus_error_free(&err);
-    }
-
-done:
-    jstring addr = env->NewStringUTF(address);
-    env->CallVoidMethod(nat->me,
-                        method_onGetDeviceServiceChannelResult,
-                        addr,
-                        channel);
-    env->DeleteLocalRef(addr);
-    free(user);
-}
-
-void onInputDeviceConnectionResult(DBusMessage *msg, void *user, void *n) {
-    ALOGV("%s", __FUNCTION__);
-
-    native_data_t *nat = (native_data_t *)n;
-    const char *path = (const char *)user;
-    DBusError err;
-    dbus_error_init(&err);
-    JNIEnv *env;
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-
-    jint result = INPUT_OPERATION_SUCCESS;
-    if (dbus_set_error_from_message(&err, msg)) {
-        if (!strcmp(err.name, BLUEZ_ERROR_IFC ".ConnectionAttemptFailed")) {
-            result = INPUT_CONNECT_FAILED_ATTEMPT_FAILED;
-        } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".AlreadyConnected")) {
-            result = INPUT_CONNECT_FAILED_ALREADY_CONNECTED;
-        } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".Failed")) {
-            // TODO():This is flaky, need to change Bluez to add new error codes
-            if (!strcmp(err.message, "Transport endpoint is not connected")) {
-              result = INPUT_DISCONNECT_FAILED_NOT_CONNECTED;
-            } else {
-              result = INPUT_OPERATION_GENERIC_FAILURE;
-            }
-        } else {
-            result = INPUT_OPERATION_GENERIC_FAILURE;
-        }
-        LOG_AND_FREE_DBUS_ERROR(&err);
-    }
-
-    ALOGV("... Device Path = %s, result = %d", path, result);
-    jstring jPath = env->NewStringUTF(path);
-    env->CallVoidMethod(nat->me,
-                        method_onInputDeviceConnectionResult,
-                        jPath,
-                        result);
-    env->DeleteLocalRef(jPath);
-    free(user);
-}
-
-void onPanDeviceConnectionResult(DBusMessage *msg, void *user, void *n) {
-    ALOGV("%s", __FUNCTION__);
-
-    native_data_t *nat = (native_data_t *)n;
-    const char *path = (const char *)user;
-    DBusError err;
-    dbus_error_init(&err);
-    JNIEnv *env;
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-
-    jint result = PAN_OPERATION_SUCCESS;
-    if (dbus_set_error_from_message(&err, msg)) {
-        if (!strcmp(err.name, BLUEZ_ERROR_IFC ".ConnectionAttemptFailed")) {
-            result = PAN_CONNECT_FAILED_ATTEMPT_FAILED;
-        } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".Failed")) {
-            // TODO():This is flaky, need to change Bluez to add new error codes
-            if (!strcmp(err.message, "Device already connected")) {
-                result = PAN_CONNECT_FAILED_ALREADY_CONNECTED;
-            } else if (!strcmp(err.message, "Device not connected")) {
-                result = PAN_DISCONNECT_FAILED_NOT_CONNECTED;
-            } else {
-                result = PAN_OPERATION_GENERIC_FAILURE;
-            }
-        } else {
-            result = PAN_OPERATION_GENERIC_FAILURE;
-        }
-        LOG_AND_FREE_DBUS_ERROR(&err);
-    }
-
-    ALOGV("... Pan Device Path = %s, result = %d", path, result);
-    jstring jPath = env->NewStringUTF(path);
-    env->CallVoidMethod(nat->me,
-                        method_onPanDeviceConnectionResult,
-                        jPath,
-                        result);
-    env->DeleteLocalRef(jPath);
-    free(user);
-}
-
-void onHealthDeviceConnectionResult(DBusMessage *msg, void *user, void *n) {
-    ALOGV("%s", __FUNCTION__);
-
-    native_data_t *nat = (native_data_t *)n;
-    DBusError err;
-    dbus_error_init(&err);
-    JNIEnv *env;
-    nat->vm->GetEnv((void**)&env, nat->envVer);
-
-    jint result = HEALTH_OPERATION_SUCCESS;
-    if (dbus_set_error_from_message(&err, msg)) {
-        if (!strcmp(err.name, BLUEZ_ERROR_IFC ".InvalidArgs")) {
-            result = HEALTH_OPERATION_INVALID_ARGS;
-        } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".HealthError")) {
-            result = HEALTH_OPERATION_ERROR;
-        } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".NotFound")) {
-            result = HEALTH_OPERATION_NOT_FOUND;
-        } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".NotAllowed")) {
-            result = HEALTH_OPERATION_NOT_ALLOWED;
-        } else {
-            result = HEALTH_OPERATION_GENERIC_FAILURE;
-        }
-        LOG_AND_FREE_DBUS_ERROR(&err);
-    }
-
-    jint code = *(int *) user;
-    ALOGV("... Health Device Code = %d, result = %d", code, result);
-    env->CallVoidMethod(nat->me,
-                        method_onHealthDeviceConnectionResult,
-                        code,
-                        result);
-    free(user);
-}
-#endif
-
-static JNINativeMethod sMethods[] = {
-     /* name, signature, funcPtr */
-    {"classInitNative", "()V", (void *)classInitNative},
-    {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative},
-    {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative},
-    {"startEventLoopNative", "()V", (void *)startEventLoopNative},
-    {"stopEventLoopNative", "()V", (void *)stopEventLoopNative},
-    {"isEventLoopRunningNative", "()Z", (void *)isEventLoopRunningNative}
-};
-
-int register_android_server_BluetoothEventLoop(JNIEnv *env) {
-    return AndroidRuntime::registerNativeMethods(env,
-            "android/server/BluetoothEventLoop", sMethods, NELEM(sMethods));
-}
-
-} /* namespace android */
diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
deleted file mode 100644
index 6c11121..0000000
--- a/core/jni/android_server_BluetoothService.cpp
+++ /dev/null
@@ -1,1785 +0,0 @@
-/*
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define DBUS_ADAPTER_IFACE BLUEZ_DBUS_BASE_IFC ".Adapter"
-#define DBUS_DEVICE_IFACE BLUEZ_DBUS_BASE_IFC ".Device"
-#define DBUS_INPUT_IFACE BLUEZ_DBUS_BASE_IFC ".Input"
-#define DBUS_NETWORK_IFACE BLUEZ_DBUS_BASE_IFC ".Network"
-#define DBUS_NETWORKSERVER_IFACE BLUEZ_DBUS_BASE_IFC ".NetworkServer"
-#define DBUS_HEALTH_MANAGER_PATH "/org/bluez"
-#define DBUS_HEALTH_MANAGER_IFACE BLUEZ_DBUS_BASE_IFC ".HealthManager"
-#define DBUS_HEALTH_DEVICE_IFACE BLUEZ_DBUS_BASE_IFC ".HealthDevice"
-#define DBUS_HEALTH_CHANNEL_IFACE BLUEZ_DBUS_BASE_IFC ".HealthChannel"
-
-#define LOG_TAG "BluetoothService.cpp"
-
-#include "android_bluetooth_common.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "android_util_Binder.h"
-#include "JNIHelp.h"
-#include "jni.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
-
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-
-#ifdef HAVE_BLUETOOTH
-#include <dbus/dbus.h>
-#include <bluedroid/bluetooth.h>
-#endif
-
-#include <cutils/properties.h>
-
-namespace android {
-
-#define BLUETOOTH_CLASS_ERROR 0xFF000000
-#define PROPERTIES_NREFS 10
-
-#ifdef HAVE_BLUETOOTH
-// We initialize these variables when we load class
-// android.server.BluetoothService
-static jfieldID field_mNativeData;
-static jfieldID field_mEventLoop;
-
-typedef struct {
-    JNIEnv *env;
-    DBusConnection *conn;
-    const char *adapter;  // dbus object name of the local adapter
-} native_data_t;
-
-extern event_loop_native_data_t *get_EventLoop_native_data(JNIEnv *,
-                                                           jobject);
-extern DBusHandlerResult agent_event_filter(DBusConnection *conn,
-                                            DBusMessage *msg,
-                                            void *data);
-void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *nat);
-void onDiscoverServicesResult(DBusMessage *msg, void *user, void *nat);
-void onCreateDeviceResult(DBusMessage *msg, void *user, void *nat);
-void onInputDeviceConnectionResult(DBusMessage *msg, void *user, void *nat);
-void onPanDeviceConnectionResult(DBusMessage *msg, void *user, void *nat);
-void onHealthDeviceConnectionResult(DBusMessage *msg, void *user, void *nat);
-
-
-/** Get native data stored in the opaque (Java code maintained) pointer mNativeData
- *  Perform quick sanity check, if there are any problems return NULL
- */
-static inline native_data_t * get_native_data(JNIEnv *env, jobject object) {
-    native_data_t *nat =
-            (native_data_t *)(env->GetIntField(object, field_mNativeData));
-    if (nat == NULL || nat->conn == NULL) {
-        ALOGE("Uninitialized native data\n");
-        return NULL;
-    }
-    return nat;
-}
-#endif
-
-static void classInitNative(JNIEnv* env, jclass clazz) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    field_mNativeData = get_field(env, clazz, "mNativeData", "I");
-    field_mEventLoop = get_field(env, clazz, "mEventLoop",
-            "Landroid/server/BluetoothEventLoop;");
-#endif
-}
-
-/* Returns true on success (even if adapter is present but disabled).
- * Return false if dbus is down, or another serious error (out of memory)
-*/
-static bool initializeNativeDataNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t));
-    if (NULL == nat) {
-        ALOGE("%s: out of memory!", __FUNCTION__);
-        return false;
-    }
-    nat->env = env;
-
-    env->SetIntField(object, field_mNativeData, (jint)nat);
-    DBusError err;
-    dbus_error_init(&err);
-    dbus_threads_init_default();
-    nat->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
-    if (dbus_error_is_set(&err)) {
-        ALOGE("Could not get onto the system bus: %s", err.message);
-        dbus_error_free(&err);
-        return false;
-    }
-    dbus_connection_set_exit_on_disconnect(nat->conn, FALSE);
-#endif  /*HAVE_BLUETOOTH*/
-    return true;
-}
-
-static const char *get_adapter_path(JNIEnv* env, jobject object) {
-#ifdef HAVE_BLUETOOTH
-    event_loop_native_data_t *event_nat =
-        get_EventLoop_native_data(env, env->GetObjectField(object,
-                                                           field_mEventLoop));
-    if (event_nat == NULL)
-        return NULL;
-    return event_nat->adapter;
-#else
-    return NULL;
-#endif
-}
-
-// This function is called when the adapter is enabled.
-static jboolean setupNativeDataNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat =
-        (native_data_t *)env->GetIntField(object, field_mNativeData);
-    event_loop_native_data_t *event_nat =
-        get_EventLoop_native_data(env, env->GetObjectField(object,
-                                                           field_mEventLoop));
-    // Register agent for remote devices.
-    const char *device_agent_path = "/android/bluetooth/remote_device_agent";
-    static const DBusObjectPathVTable agent_vtable = {
-                 NULL, agent_event_filter, NULL, NULL, NULL, NULL };
-
-    if (!dbus_connection_register_object_path(nat->conn, device_agent_path,
-                                              &agent_vtable, event_nat)) {
-        ALOGE("%s: Can't register object path %s for remote device agent!",
-                               __FUNCTION__, device_agent_path);
-        return JNI_FALSE;
-    }
-#endif /*HAVE_BLUETOOTH*/
-    return JNI_TRUE;
-}
-
-static jboolean tearDownNativeDataNative(JNIEnv *env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat =
-               (native_data_t *)env->GetIntField(object, field_mNativeData);
-    if (nat != NULL) {
-        const char *device_agent_path =
-            "/android/bluetooth/remote_device_agent";
-        dbus_connection_unregister_object_path (nat->conn, device_agent_path);
-    }
-#endif /*HAVE_BLUETOOTH*/
-    return JNI_TRUE;
-}
-
-static void cleanupNativeDataNative(JNIEnv* env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat =
-        (native_data_t *)env->GetIntField(object, field_mNativeData);
-    if (nat) {
-        free(nat);
-        nat = NULL;
-    }
-#endif
-}
-
-static jstring getAdapterPathNative(JNIEnv *env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        return (env->NewStringUTF(get_adapter_path(env, object)));
-    }
-#endif
-    return NULL;
-}
-
-
-static jboolean startDiscoveryNative(JNIEnv *env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    DBusMessage *msg = NULL;
-    DBusMessage *reply = NULL;
-    DBusError err;
-    const char *name;
-    jboolean ret = JNI_FALSE;
-
-    native_data_t *nat = get_native_data(env, object);
-    if (nat == NULL) {
-        goto done;
-    }
-
-    dbus_error_init(&err);
-
-    /* Compose the command */
-    msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC,
-                                       get_adapter_path(env, object),
-                                       DBUS_ADAPTER_IFACE, "StartDiscovery");
-
-    if (msg == NULL) {
-        if (dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        }
-        goto done;
-    }
-
-    /* Send the command. */
-    reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err);
-    if (dbus_error_is_set(&err)) {
-         LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-         ret = JNI_FALSE;
-         goto done;
-    }
-
-    ret = JNI_TRUE;
-done:
-    if (reply) dbus_message_unref(reply);
-    if (msg) dbus_message_unref(msg);
-    return ret;
-#else
-    return JNI_FALSE;
-#endif
-}
-
-static jboolean stopDiscoveryNative(JNIEnv *env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    DBusMessage *msg = NULL;
-    DBusMessage *reply = NULL;
-    DBusError err;
-    const char *name;
-    native_data_t *nat;
-    jboolean ret = JNI_FALSE;
-
-    dbus_error_init(&err);
-
-    nat = get_native_data(env, object);
-    if (nat == NULL) {
-        goto done;
-    }
-
-    /* Compose the command */
-    msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC,
-                                       get_adapter_path(env, object),
-                                       DBUS_ADAPTER_IFACE, "StopDiscovery");
-    if (msg == NULL) {
-        if (dbus_error_is_set(&err))
-            LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        goto done;
-    }
-
-    /* Send the command. */
-    reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err);
-    if (dbus_error_is_set(&err)) {
-        if(strncmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.NotAuthorized",
-                   strlen(BLUEZ_DBUS_BASE_IFC ".Error.NotAuthorized")) == 0) {
-            // hcid sends this if there is no active discovery to cancel
-            ALOGV("%s: There was no active discovery to cancel", __FUNCTION__);
-            dbus_error_free(&err);
-        } else {
-            LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        }
-        goto done;
-    }
-
-    ret = JNI_TRUE;
-done:
-    if (msg) dbus_message_unref(msg);
-    if (reply) dbus_message_unref(reply);
-    return ret;
-#else
-    return JNI_FALSE;
-#endif
-}
-
-static jbyteArray readAdapterOutOfBandDataNative(JNIEnv *env, jobject object) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    DBusError err;
-    jbyte *hash, *randomizer;
-    jbyteArray byteArray = NULL;
-    int hash_len, r_len;
-    if (nat) {
-       DBusMessage *reply = dbus_func_args(env, nat->conn,
-                           get_adapter_path(env, object),
-                           DBUS_ADAPTER_IFACE, "ReadLocalOutOfBandData",
-                           DBUS_TYPE_INVALID);
-       if (!reply) return NULL;
-
-       dbus_error_init(&err);
-       if (dbus_message_get_args(reply, &err,
-                                DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash, &hash_len,
-                                DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer, &r_len,
-                                DBUS_TYPE_INVALID)) {
-          if (hash_len == 16 && r_len == 16) {
-               byteArray = env->NewByteArray(32);
-               if (byteArray) {
-                   env->SetByteArrayRegion(byteArray, 0, 16, hash);
-                   env->SetByteArrayRegion(byteArray, 16, 16, randomizer);
-               }
-           } else {
-               ALOGE("readAdapterOutOfBandDataNative: Hash len = %d, R len = %d",
-                                                                  hash_len, r_len);
-           }
-       } else {
-          LOG_AND_FREE_DBUS_ERROR(&err);
-       }
-       dbus_message_unref(reply);
-       return byteArray;
-    }
-#endif
-    return NULL;
-}
-
-static jboolean createPairedDeviceNative(JNIEnv *env, jobject object,
-                                         jstring address, jint timeout_ms) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_address = env->GetStringUTFChars(address, NULL);
-        ALOGV("... address = %s", c_address);
-        char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char));
-        const char *capabilities = "DisplayYesNo";
-        const char *agent_path = "/android/bluetooth/remote_device_agent";
-
-        strlcpy(context_address, c_address, BTADDR_SIZE);  // for callback
-        bool ret = dbus_func_args_async(env, nat->conn, (int)timeout_ms,
-                                        onCreatePairedDeviceResult, // callback
-                                        context_address,
-                                        eventLoopNat,
-                                        get_adapter_path(env, object),
-                                        DBUS_ADAPTER_IFACE,
-                                        "CreatePairedDevice",
-                                        DBUS_TYPE_STRING, &c_address,
-                                        DBUS_TYPE_OBJECT_PATH, &agent_path,
-                                        DBUS_TYPE_STRING, &capabilities,
-                                        DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(address, c_address);
-        return ret ? JNI_TRUE : JNI_FALSE;
-
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean createPairedDeviceOutOfBandNative(JNIEnv *env, jobject object,
-                                                jstring address, jint timeout_ms) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_address = env->GetStringUTFChars(address, NULL);
-        ALOGV("... address = %s", c_address);
-        char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char));
-        const char *capabilities = "DisplayYesNo";
-        const char *agent_path = "/android/bluetooth/remote_device_agent";
-
-        strlcpy(context_address, c_address, BTADDR_SIZE);  // for callback
-        bool ret = dbus_func_args_async(env, nat->conn, (int)timeout_ms,
-                                        onCreatePairedDeviceResult, // callback
-                                        context_address,
-                                        eventLoopNat,
-                                        get_adapter_path(env, object),
-                                        DBUS_ADAPTER_IFACE,
-                                        "CreatePairedDeviceOutOfBand",
-                                        DBUS_TYPE_STRING, &c_address,
-                                        DBUS_TYPE_OBJECT_PATH, &agent_path,
-                                        DBUS_TYPE_STRING, &capabilities,
-                                        DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(address, c_address);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jint getDeviceServiceChannelNative(JNIEnv *env, jobject object,
-                                          jstring path,
-                                          jstring pattern, jint attr_id) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-    if (nat && eventLoopNat) {
-        const char *c_pattern = env->GetStringUTFChars(pattern, NULL);
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        ALOGV("... pattern = %s", c_pattern);
-        ALOGV("... attr_id = %#X", attr_id);
-        DBusMessage *reply =
-            dbus_func_args(env, nat->conn, c_path,
-                           DBUS_DEVICE_IFACE, "GetServiceAttributeValue",
-                           DBUS_TYPE_STRING, &c_pattern,
-                           DBUS_TYPE_UINT16, &attr_id,
-                           DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(pattern, c_pattern);
-        env->ReleaseStringUTFChars(path, c_path);
-        return reply ? dbus_returns_int32(env, reply) : -1;
-    }
-#endif
-    return -1;
-}
-
-static jboolean cancelDeviceCreationNative(JNIEnv *env, jobject object,
-                                           jstring address) {
-    ALOGV("%s", __FUNCTION__);
-    jboolean result = JNI_FALSE;
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_address = env->GetStringUTFChars(address, NULL);
-        DBusError err;
-        dbus_error_init(&err);
-        ALOGV("... address = %s", c_address);
-        DBusMessage *reply =
-            dbus_func_args_timeout(env, nat->conn, -1,
-                                   get_adapter_path(env, object),
-                                   DBUS_ADAPTER_IFACE, "CancelDeviceCreation",
-                                   DBUS_TYPE_STRING, &c_address,
-                                   DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(address, c_address);
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            } else
-                ALOGE("DBus reply is NULL in function %s", __FUNCTION__);
-            return JNI_FALSE;
-        } else {
-            result = JNI_TRUE;
-        }
-        dbus_message_unref(reply);
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean removeDeviceNative(JNIEnv *env, jobject object, jstring object_path) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_object_path = env->GetStringUTFChars(object_path, NULL);
-        bool ret = dbus_func_args_async(env, nat->conn, -1,
-                                        NULL,
-                                        NULL,
-                                        NULL,
-                                        get_adapter_path(env, object),
-                                        DBUS_ADAPTER_IFACE,
-                                        "RemoveDevice",
-                                        DBUS_TYPE_OBJECT_PATH, &c_object_path,
-                                        DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(object_path, c_object_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jint enableNative(JNIEnv *env, jobject object) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    return bt_enable();
-#endif
-    return -1;
-}
-
-static jint disableNative(JNIEnv *env, jobject object) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    return bt_disable();
-#endif
-    return -1;
-}
-
-static jint isEnabledNative(JNIEnv *env, jobject object) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    return bt_is_enabled();
-#endif
-    return -1;
-}
-
-static jboolean setPairingConfirmationNative(JNIEnv *env, jobject object,
-                                             jstring address, bool confirm,
-                                             int nativeData) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg = (DBusMessage *)nativeData;
-        DBusMessage *reply;
-        if (confirm) {
-            reply = dbus_message_new_method_return(msg);
-        } else {
-            reply = dbus_message_new_error(msg,
-                "org.bluez.Error.Rejected", "User rejected confirmation");
-        }
-
-        if (!reply) {
-            ALOGE("%s: Cannot create message reply to RequestPasskeyConfirmation or"
-                  "RequestPairingConsent to D-Bus\n", __FUNCTION__);
-            dbus_message_unref(msg);
-            return JNI_FALSE;
-        }
-
-        dbus_connection_send(nat->conn, reply, NULL);
-        dbus_message_unref(msg);
-        dbus_message_unref(reply);
-        return JNI_TRUE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean setPasskeyNative(JNIEnv *env, jobject object, jstring address,
-                         int passkey, int nativeData) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg = (DBusMessage *)nativeData;
-        DBusMessage *reply = dbus_message_new_method_return(msg);
-        if (!reply) {
-            ALOGE("%s: Cannot create message reply to return Passkey code to "
-                 "D-Bus\n", __FUNCTION__);
-            dbus_message_unref(msg);
-            return JNI_FALSE;
-        }
-
-        dbus_message_append_args(reply, DBUS_TYPE_UINT32, (uint32_t *)&passkey,
-                                 DBUS_TYPE_INVALID);
-
-        dbus_connection_send(nat->conn, reply, NULL);
-        dbus_message_unref(msg);
-        dbus_message_unref(reply);
-        return JNI_TRUE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean setRemoteOutOfBandDataNative(JNIEnv *env, jobject object, jstring address,
-                         jbyteArray hash, jbyteArray randomizer, int nativeData) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg = (DBusMessage *)nativeData;
-        DBusMessage *reply = dbus_message_new_method_return(msg);
-        jbyte *h_ptr = env->GetByteArrayElements(hash, NULL);
-        jbyte *r_ptr = env->GetByteArrayElements(randomizer, NULL);
-        if (!reply) {
-            ALOGE("%s: Cannot create message reply to return remote OOB data to "
-                 "D-Bus\n", __FUNCTION__);
-            dbus_message_unref(msg);
-            return JNI_FALSE;
-        }
-
-        dbus_message_append_args(reply,
-                                DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &h_ptr, 16,
-                                DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &r_ptr, 16,
-                                DBUS_TYPE_INVALID);
-
-        env->ReleaseByteArrayElements(hash, h_ptr, 0);
-        env->ReleaseByteArrayElements(randomizer, r_ptr, 0);
-
-        dbus_connection_send(nat->conn, reply, NULL);
-        dbus_message_unref(msg);
-        dbus_message_unref(reply);
-        return JNI_TRUE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean setAuthorizationNative(JNIEnv *env, jobject object, jstring address,
-                         jboolean val, int nativeData) {
-#ifdef HAVE_BLUETOOTH
-  ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg = (DBusMessage *)nativeData;
-        DBusMessage *reply;
-        if (val) {
-            reply = dbus_message_new_method_return(msg);
-        } else {
-            reply = dbus_message_new_error(msg,
-                    "org.bluez.Error.Rejected", "Authorization rejected");
-        }
-        if (!reply) {
-            ALOGE("%s: Cannot create message reply D-Bus\n", __FUNCTION__);
-            dbus_message_unref(msg);
-            return JNI_FALSE;
-        }
-
-        dbus_connection_send(nat->conn, reply, NULL);
-        dbus_message_unref(msg);
-        dbus_message_unref(reply);
-        return JNI_TRUE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean setPinNative(JNIEnv *env, jobject object, jstring address,
-                         jstring pin, int nativeData) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg = (DBusMessage *)nativeData;
-        DBusMessage *reply = dbus_message_new_method_return(msg);
-        if (!reply) {
-            ALOGE("%s: Cannot create message reply to return PIN code to "
-                 "D-Bus\n", __FUNCTION__);
-            dbus_message_unref(msg);
-            return JNI_FALSE;
-        }
-
-        const char *c_pin = env->GetStringUTFChars(pin, NULL);
-
-        dbus_message_append_args(reply, DBUS_TYPE_STRING, &c_pin,
-                                 DBUS_TYPE_INVALID);
-
-        dbus_connection_send(nat->conn, reply, NULL);
-        dbus_message_unref(msg);
-        dbus_message_unref(reply);
-        env->ReleaseStringUTFChars(pin, c_pin);
-        return JNI_TRUE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean cancelPairingUserInputNative(JNIEnv *env, jobject object,
-                                            jstring address, int nativeData) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg = (DBusMessage *)nativeData;
-        DBusMessage *reply = dbus_message_new_error(msg,
-                "org.bluez.Error.Canceled", "Pairing User Input was canceled");
-        if (!reply) {
-            ALOGE("%s: Cannot create message reply to return cancelUserInput to"
-                 "D-BUS\n", __FUNCTION__);
-            dbus_message_unref(msg);
-            return JNI_FALSE;
-        }
-
-        dbus_connection_send(nat->conn, reply, NULL);
-        dbus_message_unref(msg);
-        dbus_message_unref(reply);
-        return JNI_TRUE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jobjectArray getDevicePropertiesNative(JNIEnv *env, jobject object,
-                                                    jstring path)
-{
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg, *reply;
-        DBusError err;
-        dbus_error_init(&err);
-
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        reply = dbus_func_args_timeout(env,
-                                   nat->conn, -1, c_path,
-                                   DBUS_DEVICE_IFACE, "GetProperties",
-                                   DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(path, c_path);
-
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            } else
-                ALOGE("DBus reply is NULL in function %s", __FUNCTION__);
-            return NULL;
-        }
-        env->PushLocalFrame(PROPERTIES_NREFS);
-
-        DBusMessageIter iter;
-        jobjectArray str_array = NULL;
-        if (dbus_message_iter_init(reply, &iter))
-           str_array =  parse_remote_device_properties(env, &iter);
-        dbus_message_unref(reply);
-
-        return (jobjectArray) env->PopLocalFrame(str_array);
-    }
-#endif
-    return NULL;
-}
-
-static jobjectArray getAdapterPropertiesNative(JNIEnv *env, jobject object) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg, *reply;
-        DBusError err;
-        dbus_error_init(&err);
-
-        reply = dbus_func_args_timeout(env,
-                                   nat->conn, -1, get_adapter_path(env, object),
-                                   DBUS_ADAPTER_IFACE, "GetProperties",
-                                   DBUS_TYPE_INVALID);
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            } else
-                ALOGE("DBus reply is NULL in function %s", __FUNCTION__);
-            return NULL;
-        }
-        env->PushLocalFrame(PROPERTIES_NREFS);
-
-        DBusMessageIter iter;
-        jobjectArray str_array = NULL;
-        if (dbus_message_iter_init(reply, &iter))
-            str_array = parse_adapter_properties(env, &iter);
-        dbus_message_unref(reply);
-
-        return (jobjectArray) env->PopLocalFrame(str_array);
-    }
-#endif
-    return NULL;
-}
-
-static jboolean setAdapterPropertyNative(JNIEnv *env, jobject object, jstring key,
-                                         void *value, jint type) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg;
-        DBusMessageIter iter;
-        dbus_bool_t reply = JNI_FALSE;
-        const char *c_key = env->GetStringUTFChars(key, NULL);
-
-        msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC,
-                                           get_adapter_path(env, object),
-                                           DBUS_ADAPTER_IFACE, "SetProperty");
-        if (!msg) {
-            ALOGE("%s: Can't allocate new method call for GetProperties!",
-                  __FUNCTION__);
-            env->ReleaseStringUTFChars(key, c_key);
-            return JNI_FALSE;
-        }
-
-        dbus_message_append_args(msg, DBUS_TYPE_STRING, &c_key, DBUS_TYPE_INVALID);
-        dbus_message_iter_init_append(msg, &iter);
-        append_variant(&iter, type, value);
-
-        // Asynchronous call - the callbacks come via propertyChange
-        reply = dbus_connection_send_with_reply(nat->conn, msg, NULL, -1);
-        dbus_message_unref(msg);
-
-        env->ReleaseStringUTFChars(key, c_key);
-        return reply ? JNI_TRUE : JNI_FALSE;
-
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean setAdapterPropertyStringNative(JNIEnv *env, jobject object, jstring key,
-                                               jstring value) {
-#ifdef HAVE_BLUETOOTH
-    const char *c_value = env->GetStringUTFChars(value, NULL);
-    jboolean ret =  setAdapterPropertyNative(env, object, key, (void *)&c_value, DBUS_TYPE_STRING);
-    env->ReleaseStringUTFChars(value, (char *)c_value);
-    return ret;
-#else
-    return JNI_FALSE;
-#endif
-}
-
-static jboolean setAdapterPropertyIntegerNative(JNIEnv *env, jobject object, jstring key,
-                                               jint value) {
-#ifdef HAVE_BLUETOOTH
-    return setAdapterPropertyNative(env, object, key, (void *)&value, DBUS_TYPE_UINT32);
-#else
-    return JNI_FALSE;
-#endif
-}
-
-static jboolean setAdapterPropertyBooleanNative(JNIEnv *env, jobject object, jstring key,
-                                               jint value) {
-#ifdef HAVE_BLUETOOTH
-    return setAdapterPropertyNative(env, object, key, (void *)&value, DBUS_TYPE_BOOLEAN);
-#else
-    return JNI_FALSE;
-#endif
-}
-
-static jboolean setDevicePropertyNative(JNIEnv *env, jobject object, jstring path,
-                                               jstring key, void *value, jint type) {
-#ifdef HAVE_BLUETOOTH
-    ALOGV("%s", __FUNCTION__);
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *msg;
-        DBusMessageIter iter;
-        dbus_bool_t reply = JNI_FALSE;
-
-        const char *c_key = env->GetStringUTFChars(key, NULL);
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-
-        msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC,
-                                          c_path, DBUS_DEVICE_IFACE, "SetProperty");
-        if (!msg) {
-            ALOGE("%s: Can't allocate new method call for device SetProperty!", __FUNCTION__);
-            env->ReleaseStringUTFChars(key, c_key);
-            env->ReleaseStringUTFChars(path, c_path);
-            return JNI_FALSE;
-        }
-
-        dbus_message_append_args(msg, DBUS_TYPE_STRING, &c_key, DBUS_TYPE_INVALID);
-        dbus_message_iter_init_append(msg, &iter);
-        append_variant(&iter, type, value);
-
-        // Asynchronous call - the callbacks come via Device propertyChange
-        reply = dbus_connection_send_with_reply(nat->conn, msg, NULL, -1);
-        dbus_message_unref(msg);
-
-        env->ReleaseStringUTFChars(path, c_path);
-        env->ReleaseStringUTFChars(key, c_key);
-
-        return reply ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean setDevicePropertyBooleanNative(JNIEnv *env, jobject object,
-                                                     jstring path, jstring key, jint value) {
-#ifdef HAVE_BLUETOOTH
-    return setDevicePropertyNative(env, object, path, key,
-                                        (void *)&value, DBUS_TYPE_BOOLEAN);
-#else
-    return JNI_FALSE;
-#endif
-}
-
-static jboolean setDevicePropertyStringNative(JNIEnv *env, jobject object,
-                                              jstring path, jstring key, jstring value) {
-#ifdef HAVE_BLUETOOTH
-    const char *c_value = env->GetStringUTFChars(value, NULL);
-    jboolean ret = setDevicePropertyNative(env, object, path, key,
-                                           (void *)&c_value, DBUS_TYPE_STRING);
-    env->ReleaseStringUTFChars(value, (char *)c_value);
-    return ret;
-#else
-    return JNI_FALSE;
-#endif
-}
-
-static jboolean createDeviceNative(JNIEnv *env, jobject object,
-                                                jstring address) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_address = env->GetStringUTFChars(address, NULL);
-        ALOGV("... address = %s", c_address);
-        char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char));
-        strlcpy(context_address, c_address, BTADDR_SIZE);  // for callback
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1,
-                                        onCreateDeviceResult,
-                                        context_address,
-                                        eventLoopNat,
-                                        get_adapter_path(env, object),
-                                        DBUS_ADAPTER_IFACE,
-                                        "CreateDevice",
-                                        DBUS_TYPE_STRING, &c_address,
-                                        DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(address, c_address);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean discoverServicesNative(JNIEnv *env, jobject object,
-                                               jstring path, jstring pattern) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        const char *c_pattern = env->GetStringUTFChars(pattern, NULL);
-        int len = env->GetStringLength(path) + 1;
-        char *context_path = (char *)calloc(len, sizeof(char));
-        strlcpy(context_path, c_path, len);  // for callback
-
-        ALOGV("... Object Path = %s", c_path);
-        ALOGV("... Pattern = %s, strlen = %d", c_pattern, strlen(c_pattern));
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1,
-                                        onDiscoverServicesResult,
-                                        context_path,
-                                        eventLoopNat,
-                                        c_path,
-                                        DBUS_DEVICE_IFACE,
-                                        "DiscoverServices",
-                                        DBUS_TYPE_STRING, &c_pattern,
-                                        DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(path, c_path);
-        env->ReleaseStringUTFChars(pattern, c_pattern);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-#ifdef HAVE_BLUETOOTH
-static jintArray extract_handles(JNIEnv *env, DBusMessage *reply) {
-    jint *handles;
-    jintArray handleArray = NULL;
-    int len;
-
-    DBusError err;
-    dbus_error_init(&err);
-
-    if (dbus_message_get_args(reply, &err,
-                              DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &handles, &len,
-                              DBUS_TYPE_INVALID)) {
-        handleArray = env->NewIntArray(len);
-        if (handleArray) {
-            env->SetIntArrayRegion(handleArray, 0, len, handles);
-        } else {
-            ALOGE("Null array in extract_handles");
-        }
-    } else {
-        LOG_AND_FREE_DBUS_ERROR(&err);
-    }
-    return handleArray;
-}
-#endif
-
-static jintArray addReservedServiceRecordsNative(JNIEnv *env, jobject object,
-                                                jintArray uuids) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    DBusMessage *reply = NULL;
-
-    native_data_t *nat = get_native_data(env, object);
-
-    jint* svc_classes = env->GetIntArrayElements(uuids, NULL);
-    if (!svc_classes) return NULL;
-
-    int len = env->GetArrayLength(uuids);
-    reply = dbus_func_args(env, nat->conn,
-                            get_adapter_path(env, object),
-                            DBUS_ADAPTER_IFACE, "AddReservedServiceRecords",
-                            DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
-                            &svc_classes, len, DBUS_TYPE_INVALID);
-    env->ReleaseIntArrayElements(uuids, svc_classes, 0);
-    return reply ? extract_handles(env, reply) : NULL;
-
-#endif
-    return NULL;
-}
-
-static jboolean removeReservedServiceRecordsNative(JNIEnv *env, jobject object,
-                                                   jintArray handles) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jint *values = env->GetIntArrayElements(handles, NULL);
-    DBusMessage *msg = NULL;
-    DBusMessage *reply = NULL;
-    if (values == NULL) return JNI_FALSE;
-
-    jsize len = env->GetArrayLength(handles);
-
-    reply = dbus_func_args(env, nat->conn,
-                            get_adapter_path(env, object),
-                            DBUS_ADAPTER_IFACE, "RemoveReservedServiceRecords",
-                            DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
-                            &values, len, DBUS_TYPE_INVALID);
-    env->ReleaseIntArrayElements(handles, values, 0);
-    return reply ? JNI_TRUE : JNI_FALSE;
-#endif
-    return JNI_FALSE;
-}
-
-static jint addRfcommServiceRecordNative(JNIEnv *env, jobject object,
-        jstring name, jlong uuidMsb, jlong uuidLsb, jshort channel) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_name = env->GetStringUTFChars(name, NULL);
-        ALOGV("... name = %s", c_name);
-        ALOGV("... uuid1 = %llX", uuidMsb);
-        ALOGV("... uuid2 = %llX", uuidLsb);
-        ALOGV("... channel = %d", channel);
-        DBusMessage *reply = dbus_func_args(env, nat->conn,
-                           get_adapter_path(env, object),
-                           DBUS_ADAPTER_IFACE, "AddRfcommServiceRecord",
-                           DBUS_TYPE_STRING, &c_name,
-                           DBUS_TYPE_UINT64, &uuidMsb,
-                           DBUS_TYPE_UINT64, &uuidLsb,
-                           DBUS_TYPE_UINT16, &channel,
-                           DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(name, c_name);
-        return reply ? dbus_returns_uint32(env, reply) : -1;
-    }
-#endif
-    return -1;
-}
-
-static jboolean removeServiceRecordNative(JNIEnv *env, jobject object, jint handle) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        ALOGV("... handle = %X", handle);
-        DBusMessage *reply = dbus_func_args(env, nat->conn,
-                           get_adapter_path(env, object),
-                           DBUS_ADAPTER_IFACE, "RemoveServiceRecord",
-                           DBUS_TYPE_UINT32, &handle,
-                           DBUS_TYPE_INVALID);
-        return reply ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean setLinkTimeoutNative(JNIEnv *env, jobject object, jstring object_path,
-                                     jint num_slots) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_object_path = env->GetStringUTFChars(object_path, NULL);
-        DBusMessage *reply = dbus_func_args(env, nat->conn,
-                           get_adapter_path(env, object),
-                           DBUS_ADAPTER_IFACE, "SetLinkTimeout",
-                           DBUS_TYPE_OBJECT_PATH, &c_object_path,
-                           DBUS_TYPE_UINT32, &num_slots,
-                           DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(object_path, c_object_path);
-        return reply ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean connectInputDeviceNative(JNIEnv *env, jobject object, jstring path) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-
-        int len = env->GetStringLength(path) + 1;
-        char *context_path = (char *)calloc(len, sizeof(char));
-        strlcpy(context_path, c_path, len);  // for callback
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1, onInputDeviceConnectionResult,
-                                        context_path, eventLoopNat, c_path, DBUS_INPUT_IFACE,
-                                        "Connect",
-                                        DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean disconnectInputDeviceNative(JNIEnv *env, jobject object,
-                                     jstring path) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-
-        int len = env->GetStringLength(path) + 1;
-        char *context_path = (char *)calloc(len, sizeof(char));
-        strlcpy(context_path, c_path, len);  // for callback
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1, onInputDeviceConnectionResult,
-                                        context_path, eventLoopNat, c_path, DBUS_INPUT_IFACE,
-                                        "Disconnect",
-                                        DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean setBluetoothTetheringNative(JNIEnv *env, jobject object, jboolean value,
-                                            jstring src_role, jstring bridge) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        DBusMessage *reply;
-        const char *c_role = env->GetStringUTFChars(src_role, NULL);
-        const char *c_bridge = env->GetStringUTFChars(bridge, NULL);
-        if (value) {
-            ALOGE("setBluetoothTetheringNative true");
-            reply = dbus_func_args(env, nat->conn,
-                                  get_adapter_path(env, object),
-                                  DBUS_NETWORKSERVER_IFACE,
-                                  "Register",
-                                  DBUS_TYPE_STRING, &c_role,
-                                  DBUS_TYPE_STRING, &c_bridge,
-                                  DBUS_TYPE_INVALID);
-        } else {
-            ALOGE("setBluetoothTetheringNative false");
-            reply = dbus_func_args(env, nat->conn,
-                                  get_adapter_path(env, object),
-                                  DBUS_NETWORKSERVER_IFACE,
-                                  "Unregister",
-                                  DBUS_TYPE_STRING, &c_role,
-                                  DBUS_TYPE_INVALID);
-        }
-        env->ReleaseStringUTFChars(src_role, c_role);
-        env->ReleaseStringUTFChars(bridge, c_bridge);
-        return reply ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean connectPanDeviceNative(JNIEnv *env, jobject object, jstring path,
-                                       jstring dstRole) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    ALOGE("connectPanDeviceNative");
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        const char *dst = env->GetStringUTFChars(dstRole, NULL);
-
-        int len = env->GetStringLength(path) + 1;
-        char *context_path = (char *)calloc(len, sizeof(char));
-        strlcpy(context_path, c_path, len);  // for callback
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1,onPanDeviceConnectionResult,
-                                    context_path, eventLoopNat, c_path,
-                                    DBUS_NETWORK_IFACE, "Connect",
-                                    DBUS_TYPE_STRING, &dst,
-                                    DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(path, c_path);
-        env->ReleaseStringUTFChars(dstRole, dst);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean disconnectPanDeviceNative(JNIEnv *env, jobject object,
-                                     jstring path) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    ALOGE("disconnectPanDeviceNative");
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-
-        int len = env->GetStringLength(path) + 1;
-        char *context_path = (char *)calloc(len, sizeof(char));
-        strlcpy(context_path, c_path, len);  // for callback
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1,onPanDeviceConnectionResult,
-                                        context_path, eventLoopNat, c_path,
-                                        DBUS_NETWORK_IFACE, "Disconnect",
-                                        DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean disconnectPanServerDeviceNative(JNIEnv *env, jobject object,
-                                                jstring path, jstring address,
-                                                jstring iface) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    ALOGE("disconnectPanServerDeviceNative");
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_address = env->GetStringUTFChars(address, NULL);
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        const char *c_iface = env->GetStringUTFChars(iface, NULL);
-
-        int len = env->GetStringLength(path) + 1;
-        char *context_path = (char *)calloc(len, sizeof(char));
-        strlcpy(context_path, c_path, len);  // for callback
-
-        bool ret = dbus_func_args_async(env, nat->conn, -1,
-                                        onPanDeviceConnectionResult,
-                                        context_path, eventLoopNat,
-                                        get_adapter_path(env, object),
-                                        DBUS_NETWORKSERVER_IFACE,
-                                        "DisconnectDevice",
-                                        DBUS_TYPE_STRING, &c_address,
-                                        DBUS_TYPE_STRING, &c_iface,
-                                        DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(address, c_address);
-        env->ReleaseStringUTFChars(iface, c_iface);
-        env->ReleaseStringUTFChars(path, c_path);
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jstring registerHealthApplicationNative(JNIEnv *env, jobject object,
-                                           jint dataType, jstring role,
-                                           jstring name, jstring channelType) {
-    ALOGV("%s", __FUNCTION__);
-    jstring path = NULL;
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_role = env->GetStringUTFChars(role, NULL);
-        const char *c_name = env->GetStringUTFChars(name, NULL);
-        const char *c_channel_type = env->GetStringUTFChars(channelType, NULL);
-        char *c_path;
-        DBusMessage *msg, *reply;
-        DBusError err;
-        dbus_error_init(&err);
-
-        msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC,
-                                            DBUS_HEALTH_MANAGER_PATH,
-                                            DBUS_HEALTH_MANAGER_IFACE,
-                                            "CreateApplication");
-
-        if (msg == NULL) {
-            ALOGE("Could not allocate D-Bus message object!");
-            return NULL;
-        }
-
-        /* append arguments */
-        append_dict_args(msg,
-                         "DataType", DBUS_TYPE_UINT16, &dataType,
-                         "Role", DBUS_TYPE_STRING, &c_role,
-                         "Description", DBUS_TYPE_STRING, &c_name,
-                         "ChannelType", DBUS_TYPE_STRING, &c_channel_type,
-                         DBUS_TYPE_INVALID);
-
-
-        /* Make the call. */
-        reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err);
-
-        env->ReleaseStringUTFChars(role, c_role);
-        env->ReleaseStringUTFChars(name, c_name);
-        env->ReleaseStringUTFChars(channelType, c_channel_type);
-
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            }
-        } else {
-            if (!dbus_message_get_args(reply, &err,
-                                      DBUS_TYPE_OBJECT_PATH, &c_path,
-                                      DBUS_TYPE_INVALID)) {
-                if (dbus_error_is_set(&err)) {
-                    LOG_AND_FREE_DBUS_ERROR(&err);
-                }
-            } else {
-               path = env->NewStringUTF(c_path);
-            }
-            dbus_message_unref(reply);
-        }
-    }
-#endif
-    return path;
-}
-
-static jstring registerSinkHealthApplicationNative(JNIEnv *env, jobject object,
-                                           jint dataType, jstring role,
-                                           jstring name) {
-    ALOGV("%s", __FUNCTION__);
-    jstring path = NULL;
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_role = env->GetStringUTFChars(role, NULL);
-        const char *c_name = env->GetStringUTFChars(name, NULL);
-        char *c_path;
-
-        DBusMessage *msg, *reply;
-        DBusError err;
-        dbus_error_init(&err);
-
-        msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC,
-                                            DBUS_HEALTH_MANAGER_PATH,
-                                            DBUS_HEALTH_MANAGER_IFACE,
-                                            "CreateApplication");
-
-        if (msg == NULL) {
-            ALOGE("Could not allocate D-Bus message object!");
-            return NULL;
-        }
-
-        /* append arguments */
-        append_dict_args(msg,
-                         "DataType", DBUS_TYPE_UINT16, &dataType,
-                         "Role", DBUS_TYPE_STRING, &c_role,
-                         "Description", DBUS_TYPE_STRING, &c_name,
-                         DBUS_TYPE_INVALID);
-
-
-        /* Make the call. */
-        reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err);
-
-        env->ReleaseStringUTFChars(role, c_role);
-        env->ReleaseStringUTFChars(name, c_name);
-
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            }
-        } else {
-            if (!dbus_message_get_args(reply, &err,
-                                      DBUS_TYPE_OBJECT_PATH, &c_path,
-                                      DBUS_TYPE_INVALID)) {
-                if (dbus_error_is_set(&err)) {
-                    LOG_AND_FREE_DBUS_ERROR(&err);
-                }
-            } else {
-                path = env->NewStringUTF(c_path);
-            }
-            dbus_message_unref(reply);
-        }
-    }
-#endif
-    return path;
-}
-
-static jboolean unregisterHealthApplicationNative(JNIEnv *env, jobject object,
-                                                    jstring path) {
-    ALOGV("%s", __FUNCTION__);
-    jboolean result = JNI_FALSE;
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_path = env->GetStringUTFChars(path, NULL);
-        DBusError err;
-        dbus_error_init(&err);
-        DBusMessage *reply =
-            dbus_func_args_timeout(env, nat->conn, -1,
-                                   DBUS_HEALTH_MANAGER_PATH,
-                                   DBUS_HEALTH_MANAGER_IFACE, "DestroyApplication",
-                                   DBUS_TYPE_OBJECT_PATH, &c_path,
-                                   DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(path, c_path);
-
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            }
-        } else {
-            result = JNI_TRUE;
-        }
-    }
-#endif
-    return result;
-}
-
-static jboolean createChannelNative(JNIEnv *env, jobject object,
-                                       jstring devicePath, jstring appPath, jstring config,
-                                       jint code) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_device_path = env->GetStringUTFChars(devicePath, NULL);
-        const char *c_app_path = env->GetStringUTFChars(appPath, NULL);
-        const char *c_config = env->GetStringUTFChars(config, NULL);
-        int *data = (int *) malloc(sizeof(int));
-        if (data == NULL) return JNI_FALSE;
-
-        *data = code;
-        bool ret = dbus_func_args_async(env, nat->conn, -1, onHealthDeviceConnectionResult,
-                                        data, eventLoopNat, c_device_path,
-                                        DBUS_HEALTH_DEVICE_IFACE, "CreateChannel",
-                                        DBUS_TYPE_OBJECT_PATH, &c_app_path,
-                                        DBUS_TYPE_STRING, &c_config,
-                                        DBUS_TYPE_INVALID);
-
-
-        env->ReleaseStringUTFChars(devicePath, c_device_path);
-        env->ReleaseStringUTFChars(appPath, c_app_path);
-        env->ReleaseStringUTFChars(config, c_config);
-
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jboolean destroyChannelNative(JNIEnv *env, jobject object, jstring devicePath,
-                                     jstring channelPath, jint code) {
-    ALOGE("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
-    struct event_loop_native_data_t *eventLoopNat =
-            get_EventLoop_native_data(env, eventLoop);
-
-    if (nat && eventLoopNat) {
-        const char *c_device_path = env->GetStringUTFChars(devicePath, NULL);
-        const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL);
-        int *data = (int *) malloc(sizeof(int));
-        if (data == NULL) return JNI_FALSE;
-
-        *data = code;
-        bool ret = dbus_func_args_async(env, nat->conn, -1, onHealthDeviceConnectionResult,
-                                        data, eventLoopNat, c_device_path,
-                                        DBUS_HEALTH_DEVICE_IFACE, "DestroyChannel",
-                                        DBUS_TYPE_OBJECT_PATH, &c_channel_path,
-                                        DBUS_TYPE_INVALID);
-
-        env->ReleaseStringUTFChars(devicePath, c_device_path);
-        env->ReleaseStringUTFChars(channelPath, c_channel_path);
-
-        return ret ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jstring getMainChannelNative(JNIEnv *env, jobject object, jstring devicePath) {
-    ALOGE("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_device_path = env->GetStringUTFChars(devicePath, NULL);
-        DBusError err;
-        dbus_error_init(&err);
-
-        DBusMessage *reply = dbus_func_args(env, nat->conn,
-                           c_device_path,
-                           DBUS_HEALTH_DEVICE_IFACE, "GetProperties",
-                           DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(devicePath, c_device_path);
-
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            }
-        } else {
-            DBusMessageIter iter;
-            jobjectArray str_array = NULL;
-            if (dbus_message_iter_init(reply, &iter))
-                str_array = parse_health_device_properties(env, &iter);
-            dbus_message_unref(reply);
-            jstring path = (jstring) env->GetObjectArrayElement(str_array, 1);
-
-            return path;
-        }
-    }
-#endif
-    return NULL;
-}
-
-static jstring getChannelApplicationNative(JNIEnv *env, jobject object, jstring channelPath) {
-    ALOGE("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL);
-        DBusError err;
-        dbus_error_init(&err);
-
-        DBusMessage *reply = dbus_func_args(env, nat->conn,
-                                            c_channel_path,
-                                            DBUS_HEALTH_CHANNEL_IFACE, "GetProperties",
-                                            DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(channelPath, c_channel_path);
-
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            }
-        } else {
-            DBusMessageIter iter;
-            jobjectArray str_array = NULL;
-            if (dbus_message_iter_init(reply, &iter))
-                str_array = parse_health_channel_properties(env, &iter);
-            dbus_message_unref(reply);
-
-            jint len = env->GetArrayLength(str_array);
-
-            jstring name, path;
-            const char *c_name;
-
-            for (int i = 0; i < len; i+=2) {
-                name = (jstring) env->GetObjectArrayElement(str_array, i);
-                c_name = env->GetStringUTFChars(name, NULL);
-
-                if (!strcmp(c_name, "Application")) {
-                    path = (jstring) env->GetObjectArrayElement(str_array, i+1);
-                    env->ReleaseStringUTFChars(name, c_name);
-                    return path;
-                }
-                env->ReleaseStringUTFChars(name, c_name);
-            }
-        }
-    }
-#endif
-    return NULL;
-}
-
-static jboolean releaseChannelFdNative(JNIEnv *env, jobject object, jstring channelPath) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL);
-        DBusError err;
-        dbus_error_init(&err);
-
-        DBusMessage *reply = dbus_func_args(env, nat->conn,
-                                            c_channel_path,
-                                            DBUS_HEALTH_CHANNEL_IFACE, "Release",
-                                            DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(channelPath, c_channel_path);
-
-        return reply ? JNI_TRUE : JNI_FALSE;
-    }
-#endif
-    return JNI_FALSE;
-}
-
-static jobject getChannelFdNative(JNIEnv *env, jobject object, jstring channelPath) {
-    ALOGV("%s", __FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
-    if (nat) {
-        const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL);
-        int32_t fd;
-        DBusError err;
-        dbus_error_init(&err);
-
-        DBusMessage *reply = dbus_func_args(env, nat->conn,
-                                            c_channel_path,
-                                            DBUS_HEALTH_CHANNEL_IFACE, "Acquire",
-                                            DBUS_TYPE_INVALID);
-        env->ReleaseStringUTFChars(channelPath, c_channel_path);
-
-        if (!reply) {
-            if (dbus_error_is_set(&err)) {
-                LOG_AND_FREE_DBUS_ERROR(&err);
-            }
-            return NULL;
-        }
-
-        fd = dbus_returns_unixfd(env, reply);
-        if (fd == -1) return NULL;
-
-        int flags = fcntl(fd, F_GETFL);
-        if (flags < 0) {
-           ALOGE("Can't get flags with fcntl(): %s (%d)",
-                                strerror(errno), errno);
-           releaseChannelFdNative(env, object, channelPath);
-           close(fd);
-           return NULL;
-        }
-
-        flags &= ~O_NONBLOCK;
-        int status = fcntl(fd, F_SETFL, flags);
-        if (status < 0) {
-           ALOGE("Can't set flags with fcntl(): %s (%d)",
-               strerror(errno), errno);
-           releaseChannelFdNative(env, object, channelPath);
-           close(fd);
-           return NULL;
-        }
-
-        // Create FileDescriptor object
-        jobject fileDesc = jniCreateFileDescriptor(env, fd);
-        if (fileDesc == NULL) {
-            // FileDescriptor constructor has thrown an exception
-            releaseChannelFdNative(env, object, channelPath);
-            close(fd);
-            return NULL;
-        }
-
-        // Wrap it in a ParcelFileDescriptor
-        jobject parcelFileDesc = newParcelFileDescriptor(env, fileDesc);
-        if (parcelFileDesc == NULL) {
-            // ParcelFileDescriptor constructor has thrown an exception
-            releaseChannelFdNative(env, object, channelPath);
-            close(fd);
-            return NULL;
-        }
-
-        return parcelFileDesc;
-    }
-#endif
-    return NULL;
-}
-
-
-
-static JNINativeMethod sMethods[] = {
-     /* name, signature, funcPtr */
-    {"classInitNative", "()V", (void*)classInitNative},
-    {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative},
-    {"setupNativeDataNative", "()Z", (void *)setupNativeDataNative},
-    {"tearDownNativeDataNative", "()Z", (void *)tearDownNativeDataNative},
-    {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative},
-    {"getAdapterPathNative", "()Ljava/lang/String;", (void*)getAdapterPathNative},
-
-    {"isEnabledNative", "()I", (void *)isEnabledNative},
-    {"enableNative", "()I", (void *)enableNative},
-    {"disableNative", "()I", (void *)disableNative},
-
-    {"getAdapterPropertiesNative", "()[Ljava/lang/Object;", (void *)getAdapterPropertiesNative},
-    {"getDevicePropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;",
-      (void *)getDevicePropertiesNative},
-    {"setAdapterPropertyStringNative", "(Ljava/lang/String;Ljava/lang/String;)Z",
-      (void *)setAdapterPropertyStringNative},
-    {"setAdapterPropertyBooleanNative", "(Ljava/lang/String;I)Z",
-      (void *)setAdapterPropertyBooleanNative},
-    {"setAdapterPropertyIntegerNative", "(Ljava/lang/String;I)Z",
-      (void *)setAdapterPropertyIntegerNative},
-
-    {"startDiscoveryNative", "()Z", (void*)startDiscoveryNative},
-    {"stopDiscoveryNative", "()Z", (void *)stopDiscoveryNative},
-
-    {"readAdapterOutOfBandDataNative", "()[B", (void *)readAdapterOutOfBandDataNative},
-    {"createPairedDeviceNative", "(Ljava/lang/String;I)Z", (void *)createPairedDeviceNative},
-    {"createPairedDeviceOutOfBandNative", "(Ljava/lang/String;I)Z",
-                                    (void *)createPairedDeviceOutOfBandNative},
-    {"cancelDeviceCreationNative", "(Ljava/lang/String;)Z", (void *)cancelDeviceCreationNative},
-    {"removeDeviceNative", "(Ljava/lang/String;)Z", (void *)removeDeviceNative},
-    {"getDeviceServiceChannelNative", "(Ljava/lang/String;Ljava/lang/String;I)I",
-      (void *)getDeviceServiceChannelNative},
-
-    {"setPairingConfirmationNative", "(Ljava/lang/String;ZI)Z",
-            (void *)setPairingConfirmationNative},
-    {"setPasskeyNative", "(Ljava/lang/String;II)Z", (void *)setPasskeyNative},
-    {"setRemoteOutOfBandDataNative", "(Ljava/lang/String;[B[BI)Z", (void *)setRemoteOutOfBandDataNative},
-    {"setAuthorizationNative", "(Ljava/lang/String;ZI)Z", (void *)setAuthorizationNative},
-    {"setPinNative", "(Ljava/lang/String;Ljava/lang/String;I)Z", (void *)setPinNative},
-    {"cancelPairingUserInputNative", "(Ljava/lang/String;I)Z",
-            (void *)cancelPairingUserInputNative},
-    {"setDevicePropertyBooleanNative", "(Ljava/lang/String;Ljava/lang/String;I)Z",
-            (void *)setDevicePropertyBooleanNative},
-    {"setDevicePropertyStringNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
-            (void *)setDevicePropertyStringNative},
-    {"createDeviceNative", "(Ljava/lang/String;)Z", (void *)createDeviceNative},
-    {"discoverServicesNative", "(Ljava/lang/String;Ljava/lang/String;)Z", (void *)discoverServicesNative},
-    {"addRfcommServiceRecordNative", "(Ljava/lang/String;JJS)I", (void *)addRfcommServiceRecordNative},
-    {"removeServiceRecordNative", "(I)Z", (void *)removeServiceRecordNative},
-    {"addReservedServiceRecordsNative", "([I)[I", (void *) addReservedServiceRecordsNative},
-    {"removeReservedServiceRecordsNative", "([I)Z", (void *) removeReservedServiceRecordsNative},
-    {"setLinkTimeoutNative", "(Ljava/lang/String;I)Z", (void *)setLinkTimeoutNative},
-    // HID functions
-    {"connectInputDeviceNative", "(Ljava/lang/String;)Z", (void *)connectInputDeviceNative},
-    {"disconnectInputDeviceNative", "(Ljava/lang/String;)Z", (void *)disconnectInputDeviceNative},
-
-    {"setBluetoothTetheringNative", "(ZLjava/lang/String;Ljava/lang/String;)Z",
-              (void *)setBluetoothTetheringNative},
-    {"connectPanDeviceNative", "(Ljava/lang/String;Ljava/lang/String;)Z",
-              (void *)connectPanDeviceNative},
-    {"disconnectPanDeviceNative", "(Ljava/lang/String;)Z", (void *)disconnectPanDeviceNative},
-    {"disconnectPanServerDeviceNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
-              (void *)disconnectPanServerDeviceNative},
-    // Health function
-    {"registerHealthApplicationNative",
-              "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
-              (void *)registerHealthApplicationNative},
-    {"registerHealthApplicationNative",
-            "(ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
-            (void *)registerSinkHealthApplicationNative},
-
-    {"unregisterHealthApplicationNative", "(Ljava/lang/String;)Z",
-              (void *)unregisterHealthApplicationNative},
-    {"createChannelNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)Z",
-              (void *)createChannelNative},
-    {"destroyChannelNative", "(Ljava/lang/String;Ljava/lang/String;I)Z",
-              (void *)destroyChannelNative},
-    {"getMainChannelNative", "(Ljava/lang/String;)Ljava/lang/String;", (void *)getMainChannelNative},
-    {"getChannelApplicationNative", "(Ljava/lang/String;)Ljava/lang/String;",
-              (void *)getChannelApplicationNative},
-    {"getChannelFdNative", "(Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;", (void *)getChannelFdNative},
-    {"releaseChannelFdNative", "(Ljava/lang/String;)Z", (void *)releaseChannelFdNative},
-};
-
-
-int register_android_server_BluetoothService(JNIEnv *env) {
-    return AndroidRuntime::registerNativeMethods(env,
-                "android/server/BluetoothService", sMethods, NELEM(sMethods));
-}
-
-} /* namespace android */
diff --git a/core/jni/android_text_AndroidCharacter.cpp b/core/jni/android_text_AndroidCharacter.cpp
index dacbe41..8b85a7b7 100644
--- a/core/jni/android_text_AndroidCharacter.cpp
+++ b/core/jni/android_text_AndroidCharacter.cpp
@@ -157,6 +157,7 @@
         return false;
     }
 
+    bool ret = false;
     for (int i = start; i < start + count; i++) {
         // XXX this thinks it knows that surrogates are never mirrored
 
@@ -165,10 +166,10 @@
 
         if (c1 != c2) {
             data[i] = c2;
-            return true;
+            ret = true;
         }
     }
-    return false;
+    return ret;
 }
 
 static jchar getMirror(JNIEnv* env, jobject obj, jchar c)
diff --git a/core/jni/android_text_format_Time.cpp b/core/jni/android_text_format_Time.cpp
index 776733c..aa2c5f39 100644
--- a/core/jni/android_text_format_Time.cpp
+++ b/core/jni/android_text_format_Time.cpp
@@ -23,6 +23,7 @@
 #include "jni.h"
 #include "utils/misc.h"
 #include "android_runtime/AndroidRuntime.h"
+#include "ScopedStringChars.h"
 #include "TimeUtils.h"
 #include <nativehelper/JNIHelp.h>
 #include <cutils/tztime.h>
@@ -71,11 +72,10 @@
     t->t.tm_gmtoff = env->GetLongField(o, g_gmtoffField);
     bool allDay = env->GetBooleanField(o, g_allDayField);
     if (allDay &&
-	((t->t.tm_sec !=0) || (t->t.tm_min != 0) || (t->t.tm_hour != 0))) {
-        char msg[100];
-	sprintf(msg, "allDay is true but sec, min, hour are not 0.");
-	jniThrowException(env, "java/lang/IllegalArgumentException", msg);
-	return false;
+       ((t->t.tm_sec !=0) || (t->t.tm_min != 0) || (t->t.tm_hour != 0))) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                          "allDay is true but sec, min, hour are not 0.");
+        return false;
     }
     return true;
 }
@@ -239,31 +239,36 @@
         jobjectArray ja;
         ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_shortMonthsField);
         for (int i = 0; i < 12; i++) {
+            // Calendar.JANUARY == 0.
             js_mon[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i));
             locale.mon[i] = env->GetStringUTFChars(js_mon[i], NULL);
         }
 
         ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_longMonthsField);
         for (int i = 0; i < 12; i++) {
+            // Calendar.JANUARY == 0.
             js_month[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i));
             locale.month[i] = env->GetStringUTFChars(js_month[i], NULL);
         }
 
         ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_longStandaloneMonthsField);
         for (int i = 0; i < 12; i++) {
+            // Calendar.JANUARY == 0.
             js_standalone_month[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i));
             locale.standalone_month[i] = env->GetStringUTFChars(js_standalone_month[i], NULL);
         }
 
         ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_shortWeekdaysField);
         for (int i = 0; i < 7; i++) {
-            js_wday[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i));
+            // Calendar.SUNDAY == 1, and there's an empty string in element 0.
+            js_wday[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i + 1));
             locale.wday[i] = env->GetStringUTFChars(js_wday[i], NULL);
         }
 
         ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_longWeekdaysField);
         for (int i = 0; i < 7; i++) {
-            js_weekday[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i));
+            // Calendar.SUNDAY == 1, and there's an empty string in element 0.
+            js_weekday[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i + 1));
             locale.weekday[i] = env->GetStringUTFChars(js_weekday[i], NULL);
         }
 
@@ -308,7 +313,7 @@
 static jstring android_text_format_Time_toString(JNIEnv* env, jobject This)
 {
     Time t;
-    if (!java2time(env, &t, This)) return env->NewStringUTF("");;
+    if (!java2time(env, &t, This)) return env->NewStringUTF("");
     ACQUIRE_TIMEZONE(This, t)
 
     String8 r = t.toString();
@@ -360,32 +365,30 @@
 // ============================================================================
 // Just do this here because it's not worth recreating the strings
 
-static int get_char(JNIEnv* env, const jchar *s, int spos, int mul,
-                    bool *thrown)
+static int get_char(JNIEnv* env, const ScopedStringChars& s, int spos, int mul,
+                    bool* thrown)
 {
     jchar c = s[spos];
     if (c >= '0' && c <= '9') {
         return (c - '0') * mul;
     } else {
         if (!*thrown) {
-            char msg[100];
-            sprintf(msg, "Parse error at pos=%d", spos);
-            jniThrowException(env, "android/util/TimeFormatException", msg);
+            jniThrowExceptionFmt(env, "android/util/TimeFormatException",
+                                 "Parse error at pos=%d", spos);
             *thrown = true;
         }
         return 0;
     }
 }
 
-static bool check_char(JNIEnv* env, const jchar *s, int spos, jchar expected)
+static bool check_char(JNIEnv* env, const ScopedStringChars& s, int spos, jchar expected)
 {
     jchar c = s[spos];
     if (c != expected) {
-        char msg[100];
-	sprintf(msg, "Unexpected character 0x%02x at pos=%d.  Expected %c.", c, spos,
-		expected);
-	jniThrowException(env, "android/util/TimeFormatException", msg);
-	return false;
+        jniThrowExceptionFmt(env, "android/util/TimeFormatException",
+                             "Unexpected character 0x%02x at pos=%d.  Expected %c.",
+                             c, spos, expected);
+        return false;
     }
     return true;
 }
@@ -394,20 +397,19 @@
 static jboolean android_text_format_Time_parse(JNIEnv* env, jobject This, jstring strObj)
 {
     jsize len = env->GetStringLength(strObj);
-    const jchar *s = env->GetStringChars(strObj, NULL);
-
-    bool thrown = false;
-    int n;
-    jboolean inUtc = false;
-
     if (len < 8) {
-        char msg[100];
-        sprintf(msg, "String too short -- expected at least 8 characters.");
-	jniThrowException(env, "android/util/TimeFormatException", msg);
-	return false;
+        jniThrowException(env, "android/util/TimeFormatException",
+                          "String too short -- expected at least 8 characters.");
+        return false;
     }
 
+    jboolean inUtc = false;
+
+    ScopedStringChars s(env, strObj);
+
     // year
+    int n;
+    bool thrown = false;
     n = get_char(env, s, 0, 1000, &thrown);
     n += get_char(env, s, 1, 100, &thrown);
     n += get_char(env, s, 2, 10, &thrown);
@@ -454,7 +456,7 @@
         if (len > 15) {
             // Z
             if (!check_char(env, s, 15, 'Z')) return false;
-	    inUtc = true;
+            inUtc = true;
         }
     } else {
         env->SetBooleanField(This, g_allDayField, JNI_TRUE);
@@ -467,8 +469,7 @@
     env->SetIntField(This, g_ydayField, 0);
     env->SetIntField(This, g_isdstField, -1);
     env->SetLongField(This, g_gmtoffField, 0);
-    
-    env->ReleaseStringChars(strObj, s);
+
     return inUtc;
 }
 
@@ -477,19 +478,19 @@
                                            jstring strObj)
 {
     jsize len = env->GetStringLength(strObj);
-    const jchar *s = env->GetStringChars(strObj, NULL);
-
-    bool thrown = false;
-    int n;
-    jboolean inUtc = false;
-
     if (len < 10) {
         jniThrowException(env, "android/util/TimeFormatException",
-                "Time input is too short; must be at least 10 characters");
+                          "String too short --- expected at least 10 characters.");
         return false;
     }
 
+    jboolean inUtc = false;
+
+    ScopedStringChars s(env, strObj);
+
     // year
+    int n;
+    bool thrown = false;
     n = get_char(env, s, 0, 1000, &thrown);    
     n += get_char(env, s, 1, 100, &thrown);
     n += get_char(env, s, 2, 10, &thrown);
@@ -520,28 +521,28 @@
         // T
         if (!check_char(env, s, 10, 'T')) return false;
 
-	env->SetBooleanField(This, g_allDayField, JNI_FALSE);
+        env->SetBooleanField(This, g_allDayField, JNI_FALSE);
         // hour
         n = get_char(env, s, 11, 10, &thrown);
         n += get_char(env, s, 12, 1, &thrown);
         if (thrown) return false;
-	int hour = n;
+        int hour = n;
         // env->SetIntField(This, g_hourField, n);
-	
-	// :
-	if (!check_char(env, s, 13, ':')) return false;
 
-	// minute
+        // :
+        if (!check_char(env, s, 13, ':')) return false;
+
+        // minute
         n = get_char(env, s, 14, 10, &thrown);
         n += get_char(env, s, 15, 1, &thrown);
         if (thrown) return false;
-	int minute = n;
+        int minute = n;
         // env->SetIntField(This, g_minField, n);
 
-	// :
-	if (!check_char(env, s, 16, ':')) return false;
+        // :
+        if (!check_char(env, s, 16, ':')) return false;
 
-	// second
+        // second
         n = get_char(env, s, 17, 10, &thrown);
         n += get_char(env, s, 18, 1, &thrown);
         if (thrown) return false;
@@ -561,64 +562,63 @@
         if (len > tz_index) {
             char c = s[tz_index];
 
-	    // NOTE: the offset is meant to be subtracted to get from local time
-	    // to UTC.  we therefore use 1 for '-' and -1 for '+'.
-	    switch (c) {
-	    case 'Z':
-	        // Zulu time -- UTC
-	        offset = 0;
-		break;
-	    case '-': 
+            // NOTE: the offset is meant to be subtracted to get from local time
+            // to UTC.  we therefore use 1 for '-' and -1 for '+'.
+            switch (c) {
+            case 'Z':
+                // Zulu time -- UTC
+                offset = 0;
+                break;
+            case '-': 
                 offset = 1;
-	        break;
-	    case '+': 
+                break;
+            case '+': 
                 offset = -1;
-	        break;
-	    default:
-	        char msg[100];
-	        sprintf(msg, "Unexpected character 0x%02x at position %d.  Expected + or -",
-			c, tz_index);
-	        jniThrowException(env, "android/util/TimeFormatException", msg);
-	        return false;
-	    }
+                break;
+            default:
+                jniThrowExceptionFmt(env, "android/util/TimeFormatException",
+                                     "Unexpected character 0x%02x at position %d.  Expected + or -",
+                                     c, tz_index);
+                return false;
+            }
             inUtc = true;
 
-	    if (offset != 0) {
-	        if (len < tz_index + 6) {
-	            char msg[100];
-	            sprintf(msg, "Unexpected length; should be %d characters", tz_index + 6);
-	            jniThrowException(env, "android/util/TimeFormatException", msg);
-	            return false;
-	        }
+            if (offset != 0) {
+                if (len < tz_index + 6) {
+                    jniThrowExceptionFmt(env, "android/util/TimeFormatException",
+                                         "Unexpected length; should be %d characters",
+                                         tz_index + 6);
+                    return false;
+                }
 
-	        // hour
-	        n = get_char(env, s, tz_index + 1, 10, &thrown);
-		n += get_char(env, s, tz_index + 2, 1, &thrown);
-		if (thrown) return false;
-		n *= offset;
-		hour += n;
+                // hour
+                n = get_char(env, s, tz_index + 1, 10, &thrown);
+                n += get_char(env, s, tz_index + 2, 1, &thrown);
+                if (thrown) return false;
+                n *= offset;
+                hour += n;
 
-		// :
-		if (!check_char(env, s, tz_index + 3, ':')) return false;
-	    
-		// minute
-		n = get_char(env, s, tz_index + 4, 10, &thrown);
-		n += get_char(env, s, tz_index + 5, 1, &thrown);
-		if (thrown) return false;
-		n *= offset;
-		minute += n;
-	    }
-	}
-	env->SetIntField(This, g_hourField, hour);
+                // :
+                if (!check_char(env, s, tz_index + 3, ':')) return false;
+            
+                // minute
+                n = get_char(env, s, tz_index + 4, 10, &thrown);
+                n += get_char(env, s, tz_index + 5, 1, &thrown);
+                if (thrown) return false;
+                n *= offset;
+                minute += n;
+            }
+        }
+        env->SetIntField(This, g_hourField, hour);
         env->SetIntField(This, g_minField, minute);
 
-	if (offset != 0) {
-	    // we need to normalize after applying the hour and minute offsets
-	    android_text_format_Time_normalize(env, This, false /* use isdst */);
-	    // The timezone is set to UTC in the calling Java code.
-	}
+        if (offset != 0) {
+            // we need to normalize after applying the hour and minute offsets
+            android_text_format_Time_normalize(env, This, false /* use isdst */);
+            // The timezone is set to UTC in the calling Java code.
+        }
     } else {
-	env->SetBooleanField(This, g_allDayField, JNI_TRUE);
+        env->SetBooleanField(This, g_allDayField, JNI_TRUE);
         env->SetIntField(This, g_hourField, 0);
         env->SetIntField(This, g_minField, 0);
         env->SetIntField(This, g_secField, 0);
@@ -628,8 +628,7 @@
     env->SetIntField(This, g_ydayField, 0);
     env->SetIntField(This, g_isdstField, -1);
     env->SetLongField(This, g_gmtoffField, 0);
-    
-    env->ReleaseStringChars(strObj, s);
+
     return inUtc;
 }
 
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 04dc49f..881d9a0 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -729,11 +729,6 @@
     return IPCThreadState::self()->getCallingUid();
 }
 
-static jint android_os_Binder_getOrigCallingUid(JNIEnv* env, jobject clazz)
-{
-    return IPCThreadState::self()->getOrigCallingUid();
-}
-
 static jlong android_os_Binder_clearCallingIdentity(JNIEnv* env, jobject clazz)
 {
     return IPCThreadState::self()->clearCallingIdentity();
@@ -805,7 +800,6 @@
      /* name, signature, funcPtr */
     { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid },
     { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
-    { "getOrigCallingUidNative", "()I", (void*)android_os_Binder_getOrigCallingUid },
     { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
     { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
     { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
diff --git a/core/jni/android_util_FloatMath.cpp b/core/jni/android_util_FloatMath.cpp
index f38faa9..73b7a6f 100644
--- a/core/jni/android_util_FloatMath.cpp
+++ b/core/jni/android_util_FloatMath.cpp
@@ -25,6 +25,18 @@
     static float SqrtF(JNIEnv* env, jobject clazz, float x) {
         return sqrtf(x);
     }
+
+    static float ExpF(JNIEnv* env, jobject clazz, float x) {
+        return expf(x);
+    }
+
+    static float PowF(JNIEnv* env, jobject clazz, float x, float y) {
+        return powf(x, y);
+    }
+
+    static float HypotF(JNIEnv* env, jobject clazz, float x, float y) {
+        return hypotf(x, y);
+    }
 };
 
 static JNINativeMethod gMathUtilsMethods[] = {
@@ -32,7 +44,10 @@
     {"ceil", "(F)F", (void*) MathUtilsGlue::CeilF},
     {"sin", "(F)F", (void*) MathUtilsGlue::SinF},
     {"cos", "(F)F", (void*) MathUtilsGlue::CosF},
-    {"sqrt", "(F)F", (void*) MathUtilsGlue::SqrtF}
+    {"sqrt", "(F)F", (void*) MathUtilsGlue::SqrtF},
+    {"exp", "(F)F", (void*) MathUtilsGlue::ExpF},
+    {"pow", "(FF)F", (void*) MathUtilsGlue::PowF},
+    {"hypot", "(FF)F", (void*) MathUtilsGlue::HypotF},
 };
 
 int register_android_util_FloatMath(JNIEnv* env)
diff --git a/core/jni/android_view_Display.cpp b/core/jni/android_view_Display.cpp
deleted file mode 100644
index aedf1e4..0000000
--- a/core/jni/android_view_Display.cpp
+++ /dev/null
@@ -1,151 +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.
- */
-
-#include <stdio.h>
-#include <assert.h>
-
-#include <cutils/properties.h>
-
-#include <gui/SurfaceComposerClient.h>
-#include <ui/PixelFormat.h>
-#include <ui/DisplayInfo.h>
-
-#include "jni.h"
-#include "JNIHelp.h"
-#include <android_runtime/AndroidRuntime.h>
-#include <utils/misc.h>
-#include <utils/Log.h>
-#include <cutils/properties.h>
-
-// ----------------------------------------------------------------------------
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-struct offsets_t {
-    jfieldID display;
-    jfieldID pixelFormat;
-    jfieldID fps;
-    jfieldID density;
-    jfieldID xdpi;
-    jfieldID ydpi;
-};
-static offsets_t offsets;
-static bool headless = false;
-
-// ----------------------------------------------------------------------------
-
-static void android_view_Display_init(
-        JNIEnv* env, jobject clazz, jint dpy)
-{
-    DisplayInfo info;
-    if (headless) {
-        // initialize dummy display with reasonable values
-        info.pixelFormatInfo.format = 1; // RGB_8888
-        info.fps = 60;
-        info.density = 160;
-        info.xdpi = 160;
-        info.ydpi = 160;
-    } else {
-        status_t err = SurfaceComposerClient::getDisplayInfo(DisplayID(dpy), &info);
-        if (err < 0) {
-            jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
-            return;
-        }
-    }
-    env->SetIntField(clazz, offsets.pixelFormat,info.pixelFormatInfo.format);
-    env->SetFloatField(clazz, offsets.fps,      info.fps);
-    env->SetFloatField(clazz, offsets.density,  info.density);
-    env->SetFloatField(clazz, offsets.xdpi,     info.xdpi);
-    env->SetFloatField(clazz, offsets.ydpi,     info.ydpi);
-}
-
-static jint android_view_Display_getRawWidthNative(
-        JNIEnv* env, jobject clazz)
-{
-    if (headless) return 640;
-    DisplayID dpy = env->GetIntField(clazz, offsets.display);
-    return SurfaceComposerClient::getDisplayWidth(dpy);
-}
-
-static jint android_view_Display_getRawHeightNative(
-        JNIEnv* env, jobject clazz)
-{
-    if (headless) return 480;
-    DisplayID dpy = env->GetIntField(clazz, offsets.display);
-    return SurfaceComposerClient::getDisplayHeight(dpy);
-}
-
-static jint android_view_Display_getOrientation(
-        JNIEnv* env, jobject clazz)
-{
-    if (headless) return 0; // Surface.ROTATION_0
-    DisplayID dpy = env->GetIntField(clazz, offsets.display);
-    return SurfaceComposerClient::getDisplayOrientation(dpy);
-}
-
-static jint android_view_Display_getDisplayCount(
-        JNIEnv* env, jclass clazz)
-{
-    if (headless) return 1;
-    return SurfaceComposerClient::getNumberOfDisplays();
-}
-
-// ----------------------------------------------------------------------------
-
-const char* const kClassPathName = "android/view/Display";
-
-static void nativeClassInit(JNIEnv* env, jclass clazz);
-
-static JNINativeMethod gMethods[] = {
-    {   "nativeClassInit", "()V",
-            (void*)nativeClassInit },
-    {   "getDisplayCount", "()I",
-            (void*)android_view_Display_getDisplayCount },
-	{   "init", "(I)V",
-            (void*)android_view_Display_init },
-    {   "getRawWidthNative", "()I",
-            (void*)android_view_Display_getRawWidthNative },
-    {   "getRawHeightNative", "()I",
-            (void*)android_view_Display_getRawHeightNative },
-    {   "getOrientation", "()I",
-            (void*)android_view_Display_getOrientation }
-};
-
-void nativeClassInit(JNIEnv* env, jclass clazz)
-{
-    char value[PROPERTY_VALUE_MAX];
-
-    property_get("ro.config.headless", value, "0");
-    if (strcmp(value, "1") == 0)
-        headless = true;
-
-    offsets.display     = env->GetFieldID(clazz, "mDisplay", "I");
-    offsets.pixelFormat = env->GetFieldID(clazz, "mPixelFormat", "I");
-    offsets.fps         = env->GetFieldID(clazz, "mRefreshRate", "F");
-    offsets.density     = env->GetFieldID(clazz, "mDensity", "F");
-    offsets.xdpi        = env->GetFieldID(clazz, "mDpiX", "F");
-    offsets.ydpi        = env->GetFieldID(clazz, "mDpiY", "F");
-}
-
-int register_android_view_Display(JNIEnv* env)
-{
-    return AndroidRuntime::registerNativeMethods(env,
-            kClassPathName, gMethods, NELEM(gMethods));
-}
-
-};
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index 89058a7..3d9d005 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -39,6 +39,7 @@
     jclass clazz;
 
     jmethodID dispatchVsync;
+    jmethodID dispatchHotplug;
 } gDisplayEventReceiverClassInfo;
 
 
@@ -61,7 +62,9 @@
     bool mWaitingForVsync;
 
     virtual int handleEvent(int receiveFd, int events, void* data);
-    bool readLastVsyncMessage(nsecs_t* outTimestamp, uint32_t* outCount);
+    bool readLastVsyncMessage(nsecs_t* outTimestamp, int32_t* id, uint32_t* outCount);
+    void dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count);
+    void dispatchHotplug(nsecs_t timestamp, int32_t id, bool connected);
 };
 
 
@@ -106,8 +109,9 @@
 
         // Drain all pending events.
         nsecs_t vsyncTimestamp;
+        int32_t vsyncDisplayId;
         uint32_t vsyncCount;
-        readLastVsyncMessage(&vsyncTimestamp, &vsyncCount);
+        readLastVsyncMessage(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount);
 
         status_t status = mReceiver.requestNextVsync();
         if (status) {
@@ -135,39 +139,39 @@
 
     // Drain all pending events, keep the last vsync.
     nsecs_t vsyncTimestamp;
+    int32_t vsyncDisplayId;
     uint32_t vsyncCount;
-    if (!readLastVsyncMessage(&vsyncTimestamp, &vsyncCount)) {
+    if (!readLastVsyncMessage(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
         ALOGV("receiver %p ~ Woke up but there was no vsync pulse!", this);
         return 1; // keep the callback, did not obtain a vsync pulse
     }
 
-    ALOGV("receiver %p ~ Vsync pulse: timestamp=%lld, count=%d",
-            this, vsyncTimestamp, vsyncCount);
+    ALOGV("receiver %p ~ Vsync pulse: timestamp=%lld, id=%d, count=%d",
+            this, vsyncTimestamp, vsyncDisplayId, vsyncCount);
     mWaitingForVsync = false;
 
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-
-    ALOGV("receiver %p ~ Invoking vsync handler.", this);
-    env->CallVoidMethod(mReceiverObjGlobal,
-            gDisplayEventReceiverClassInfo.dispatchVsync, vsyncTimestamp, vsyncCount);
-    ALOGV("receiver %p ~ Returned from vsync handler.", this);
-
-    mMessageQueue->raiseAndClearException(env, "dispatchVsync");
+    dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
     return 1; // keep the callback
 }
 
 bool NativeDisplayEventReceiver::readLastVsyncMessage(
-        nsecs_t* outTimestamp, uint32_t* outCount) {
+        nsecs_t* outTimestamp, int32_t* outId, uint32_t* outCount) {
     DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
     ssize_t n;
     while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
         ALOGV("receiver %p ~ Read %d events.", this, int(n));
         while (n-- > 0) {
-            if (buf[n].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
-                *outTimestamp = buf[n].header.timestamp;
-                *outCount = buf[n].vsync.count;
+            const DisplayEventReceiver::Event& ev = buf[n];
+            if (ev.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
+                *outTimestamp = ev.header.timestamp;
+                *outId = ev.header.id;
+                *outCount = ev.vsync.count;
                 return true; // stop at last vsync in the buffer
             }
+
+            if (ev.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) {
+                dispatchHotplug(ev.header.timestamp, ev.header.id, ev.hotplug.connected);
+            }
         }
     }
     if (n < 0) {
@@ -176,6 +180,28 @@
     return false;
 }
 
+void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+    ALOGV("receiver %p ~ Invoking vsync handler.", this);
+    env->CallVoidMethod(mReceiverObjGlobal,
+            gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, id, count);
+    ALOGV("receiver %p ~ Returned from vsync handler.", this);
+
+    mMessageQueue->raiseAndClearException(env, "dispatchVsync");
+}
+
+void NativeDisplayEventReceiver::dispatchHotplug(nsecs_t timestamp, int32_t id, bool connected) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+    ALOGV("receiver %p ~ Invoking hotplug handler.", this);
+    env->CallVoidMethod(mReceiverObjGlobal,
+            gDisplayEventReceiverClassInfo.dispatchHotplug, timestamp, id, connected);
+    ALOGV("receiver %p ~ Returned from hotplug handler.", this);
+
+    mMessageQueue->raiseAndClearException(env, "dispatchHotplug");
+}
+
 
 static jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj,
         jobject messageQueueObj) {
@@ -248,7 +274,10 @@
 
     GET_METHOD_ID(gDisplayEventReceiverClassInfo.dispatchVsync,
             gDisplayEventReceiverClassInfo.clazz,
-            "dispatchVsync", "(JI)V");
+            "dispatchVsync", "(JII)V");
+    GET_METHOD_ID(gDisplayEventReceiverClassInfo.dispatchHotplug,
+            gDisplayEventReceiverClassInfo.clazz,
+            "dispatchHotplug", "(JIZ)V");
     return 0;
 }
 
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index a51b77e..5d306d2 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -46,6 +46,7 @@
 #include <OpenGLRenderer.h>
 #include <SkiaShader.h>
 #include <SkiaColorFilter.h>
+#include <Stencil.h>
 #include <Rect.h>
 
 #include <TextLayout.h>
@@ -115,7 +116,9 @@
 
 static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject clazz) {
     RENDERER_LOGD("Create OpenGLRenderer");
-    return new OpenGLRenderer;
+    OpenGLRenderer* renderer = new OpenGLRenderer();
+    renderer->initProperties();
+    return renderer;
 }
 
 static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
@@ -150,7 +153,7 @@
 }
 
 static jint android_view_GLES20Canvas_getStencilSize(JNIEnv* env, jobject clazz) {
-    return OpenGLRenderer::getStencilSize();
+    return Stencil::getStencilSize();
 }
 
 // ----------------------------------------------------------------------------
@@ -528,8 +531,11 @@
     }
     const jchar* glyphs = value->getGlyphs();
     size_t glyphsCount = value->getGlyphsCount();
+    jfloat totalAdvance = value->getTotalAdvance();
+    const float* positions = value->getPos();
     int bytesCount = glyphsCount * sizeof(jchar);
-    renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y, paint);
+    renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y,
+            positions, paint, totalAdvance);
 }
 
 static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int count,
@@ -556,8 +562,11 @@
     }
     const jchar* glyphs = value->getGlyphs();
     size_t glyphsCount = value->getGlyphsCount();
+    jfloat totalAdvance = value->getTotalAdvance();
+    const float* positions = value->getPos();
     int bytesCount = glyphsCount * sizeof(jchar);
-    renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y, paint);
+    renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y,
+            positions, paint, totalAdvance);
 }
 
 static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz,
@@ -727,7 +736,9 @@
 static OpenGLRenderer* android_view_GLES20Canvas_createLayerRenderer(JNIEnv* env,
         jobject clazz, Layer* layer) {
     if (layer) {
-        return new LayerRenderer(layer);
+        OpenGLRenderer* renderer = new LayerRenderer(layer);
+        renderer->initProperties();
+        return renderer;
     }
     return NULL;
 }
@@ -759,14 +770,37 @@
     return layer;
 }
 
-static void android_view_GLES20Canvas_resizeLayer(JNIEnv* env, jobject clazz,
+static bool android_view_GLES20Canvas_resizeLayer(JNIEnv* env, jobject clazz,
         Layer* layer, jint width, jint height, jintArray layerInfo) {
-    LayerRenderer::resizeLayer(layer, width, height);
+    if (LayerRenderer::resizeLayer(layer, width, height)) {
+        jint* storage = env->GetIntArrayElements(layerInfo, NULL);
+        storage[0] = layer->getWidth();
+        storage[1] = layer->getHeight();
+        env->ReleaseIntArrayElements(layerInfo, storage, 0);
+        return true;
+    }
+    return false;
+}
 
-    jint* storage = env->GetIntArrayElements(layerInfo, NULL);
-    storage[0] = layer->getWidth();
-    storage[1] = layer->getHeight();
-    env->ReleaseIntArrayElements(layerInfo, storage, 0);
+static void android_view_GLES20Canvas_setLayerPaint(JNIEnv* env, jobject clazz,
+        Layer* layer, SkPaint* paint) {
+    if (layer) {
+        layer->setPaint(paint);
+    }
+}
+
+static void android_view_GLES20Canvas_setLayerColorFilter(JNIEnv* env, jobject clazz,
+        Layer* layer, SkiaColorFilter* colorFilter) {
+    if (layer) {
+        layer->setColorFilter(colorFilter);
+    }
+}
+
+static void android_view_GLES20Canvas_setOpaqueLayer(JNIEnv* env, jobject clazz,
+        Layer* layer, jboolean isOpaque) {
+    if (layer) {
+        layer->setBlend(!isOpaque);
+    }
 }
 
 static void android_view_GLES20Canvas_updateTextureLayer(JNIEnv* env, jobject clazz,
@@ -788,9 +822,13 @@
     layer->updateDeferred(renderer, displayList, left, top, right, bottom);
 }
 
+static void android_view_GLES20Canvas_clearLayerTexture(JNIEnv* env, jobject clazz,
+        Layer* layer) {
+    layer->clearTexture();
+}
+
 static void android_view_GLES20Canvas_setTextureLayerTransform(JNIEnv* env, jobject clazz,
         Layer* layer, SkMatrix* matrix) {
-
     layer->getTransform().load(*matrix);
 }
 
@@ -803,10 +841,6 @@
     LayerRenderer::destroyLayerDeferred(layer);
 }
 
-static void android_view_GLES20Canvas_flushLayer(JNIEnv* env, jobject clazz, Layer* layer) {
-    LayerRenderer::flushLayer(layer);
-}
-
 static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, Layer* layer, jfloat x, jfloat y, SkPaint* paint) {
     renderer->drawLayer(layer, x, y, paint);
@@ -817,6 +851,16 @@
     return LayerRenderer::copyLayer(layer, bitmap);
 }
 
+static void android_view_GLES20Canvas_pushLayerUpdate(JNIEnv* env, jobject clazz,
+        OpenGLRenderer* renderer, Layer* layer) {
+    renderer->pushLayerUpdate(layer);
+}
+
+static void android_view_GLES20Canvas_clearLayerUpdates(JNIEnv* env, jobject clazz,
+        OpenGLRenderer* renderer) {
+    renderer->clearLayerUpdates();
+}
+
 #endif // USE_OPENGL_RENDERER
 
 // ----------------------------------------------------------------------------
@@ -968,16 +1012,21 @@
 
     { "nCreateLayerRenderer",    "(I)I",       (void*) android_view_GLES20Canvas_createLayerRenderer },
     { "nCreateLayer",            "(IIZ[I)I",   (void*) android_view_GLES20Canvas_createLayer },
-    { "nResizeLayer",            "(III[I)V" ,  (void*) android_view_GLES20Canvas_resizeLayer },
+    { "nResizeLayer",            "(III[I)Z" ,  (void*) android_view_GLES20Canvas_resizeLayer },
+    { "nSetLayerPaint",          "(II)V",      (void*) android_view_GLES20Canvas_setLayerPaint },
+    { "nSetLayerColorFilter",    "(II)V",      (void*) android_view_GLES20Canvas_setLayerColorFilter },
+    { "nSetOpaqueLayer",         "(IZ)V",      (void*) android_view_GLES20Canvas_setOpaqueLayer },
     { "nCreateTextureLayer",     "(Z[I)I",     (void*) android_view_GLES20Canvas_createTextureLayer },
     { "nUpdateTextureLayer",     "(IIIZLandroid/graphics/SurfaceTexture;)V",
             (void*) android_view_GLES20Canvas_updateTextureLayer },
     { "nUpdateRenderLayer",      "(IIIIIII)V", (void*) android_view_GLES20Canvas_updateRenderLayer },
+    { "nClearLayerTexture",      "(I)V",       (void*) android_view_GLES20Canvas_clearLayerTexture },
     { "nDestroyLayer",           "(I)V",       (void*) android_view_GLES20Canvas_destroyLayer },
     { "nDestroyLayerDeferred",   "(I)V",       (void*) android_view_GLES20Canvas_destroyLayerDeferred },
-    { "nFlushLayer",             "(I)V",       (void*) android_view_GLES20Canvas_flushLayer },
     { "nDrawLayer",              "(IIFFI)V",   (void*) android_view_GLES20Canvas_drawLayer },
     { "nCopyLayer",              "(II)Z",      (void*) android_view_GLES20Canvas_copyLayer },
+    { "nClearLayerUpdates",      "(I)V",       (void*) android_view_GLES20Canvas_clearLayerUpdates },
+    { "nPushLayerUpdate",        "(II)V",      (void*) android_view_GLES20Canvas_pushLayerUpdate },
 
     { "nSetTextureLayerTransform", "(II)V",    (void*) android_view_GLES20Canvas_setTextureLayerTransform },
 
diff --git a/core/jni/android_view_GLES20DisplayList.cpp b/core/jni/android_view_GLES20DisplayList.cpp
index b307a2f..c5f52df 100644
--- a/core/jni/android_view_GLES20DisplayList.cpp
+++ b/core/jni/android_view_GLES20DisplayList.cpp
@@ -36,6 +36,11 @@
  */
 #ifdef USE_OPENGL_RENDERER
 
+static void android_view_GLES20DisplayList_reset(JNIEnv* env,
+        jobject clazz, DisplayList* displayList) {
+    displayList->reset();
+}
+
 // ----------------------------------------------------------------------------
 // DisplayList view properties
 // ----------------------------------------------------------------------------
@@ -185,6 +190,7 @@
 
 static JNINativeMethod gMethods[] = {
 #ifdef USE_OPENGL_RENDERER
+    { "nReset",                "(I)V",   (void*) android_view_GLES20DisplayList_reset },
     { "nSetCaching",           "(IZ)V",  (void*) android_view_GLES20DisplayList_setCaching },
     { "nSetStaticMatrix",      "(II)V",  (void*) android_view_GLES20DisplayList_setStaticMatrix },
     { "nSetAnimationMatrix",   "(II)V",  (void*) android_view_GLES20DisplayList_setAnimationMatrix },
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 5739cbe..2767e94 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -18,15 +18,19 @@
 
 #include <stdio.h>
 
+#include "android_os_Parcel.h"
 #include "android_util_Binder.h"
 #include "android/graphics/GraphicsJNI.h"
+#include "android/graphics/Region.h"
 
 #include <binder/IMemory.h>
 
+#include <gui/ISurfaceComposer.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 #include <gui/SurfaceTexture.h>
 
+#include <ui/DisplayInfo.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
 
@@ -41,463 +45,53 @@
 #include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/android_view_Surface.h>
+#include <android_runtime/android_view_SurfaceSession.h>
 #include <android_runtime/android_graphics_SurfaceTexture.h>
 #include <utils/misc.h>
+#include <utils/Log.h>
+
+#include <ScopedUtfChars.h>
 
 
 // ----------------------------------------------------------------------------
 
 namespace android {
 
-enum {
-    // should match Parcelable.java
-    PARCELABLE_WRITE_RETURN_VALUE = 0x0001
-};
-
-// ----------------------------------------------------------------------------
-
 static const char* const OutOfResourcesException =
     "android/view/Surface$OutOfResourcesException";
 
-const char* const kSurfaceSessionClassPathName = "android/view/SurfaceSession";
-const char* const kSurfaceClassPathName = "android/view/Surface";
+static struct {
+    jclass clazz;
+    jfieldID mNativeSurface;
+    jfieldID mNativeSurfaceControl;
+    jfieldID mGenerationId;
+    jfieldID mCanvas;
+    jfieldID mCanvasSaveCount;
+    jmethodID ctor;
+} gSurfaceClassInfo;
 
-struct sso_t {
-    jfieldID client;
-};
-static sso_t sso;
+static struct {
+    jfieldID left;
+    jfieldID top;
+    jfieldID right;
+    jfieldID bottom;
+} gRectClassInfo;
 
-struct so_t {
-    jfieldID surfaceControl;
-    jfieldID surfaceGenerationId;
-    jfieldID surface;
-    jfieldID saveCount;
-    jfieldID canvas;
-};
-static so_t so;
+static struct {
+    jfieldID mNativeCanvas;
+    jfieldID mSurfaceFormat;
+} gCanvasClassInfo;
 
-struct ro_t {
-    jfieldID l;
-    jfieldID t;
-    jfieldID r;
-    jfieldID b;
-};
-static ro_t ro;
+static struct {
+    jfieldID width;
+    jfieldID height;
+    jfieldID refreshRate;
+    jfieldID density;
+    jfieldID xDpi;
+    jfieldID yDpi;
+    jfieldID secure;
+} gPhysicalDisplayInfoClassInfo;
 
-struct po_t {
-    jfieldID x;
-    jfieldID y;
-};
-static po_t po;
-
-struct co_t {
-    jfieldID surfaceFormat;
-};
-static co_t co;
-
-struct no_t {
-    jfieldID native_canvas;
-    jfieldID native_region;
-    jfieldID native_parcel;
-};
-static no_t no;
-
-
-// ----------------------------------------------------------------------------
-// ----------------------------------------------------------------------------
-// ----------------------------------------------------------------------------
-
-static void SurfaceSession_init(JNIEnv* env, jobject clazz)
-{
-    sp<SurfaceComposerClient> client = new SurfaceComposerClient;
-    client->incStrong(clazz);
-    env->SetIntField(clazz, sso.client, (int)client.get());
-}
-
-static void SurfaceSession_destroy(JNIEnv* env, jobject clazz)
-{
-    SurfaceComposerClient* client =
-            (SurfaceComposerClient*)env->GetIntField(clazz, sso.client);
-    if (client != 0) {
-        client->decStrong(clazz);
-        env->SetIntField(clazz, sso.client, 0);
-    }
-}
-
-static void SurfaceSession_kill(JNIEnv* env, jobject clazz)
-{
-    SurfaceComposerClient* client =
-            (SurfaceComposerClient*)env->GetIntField(clazz, sso.client);
-    if (client != 0) {
-        client->dispose();
-        client->decStrong(clazz);
-        env->SetIntField(clazz, sso.client, 0);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject clazz)
-{
-    SurfaceControl* const p =
-        (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
-    return sp<SurfaceControl>(p);
-}
-
-static void setSurfaceControl(JNIEnv* env, jobject clazz,
-        const sp<SurfaceControl>& surface)
-{
-    SurfaceControl* const p =
-        (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
-    if (surface.get()) {
-        surface->incStrong(clazz);
-    }
-    if (p) {
-        p->decStrong(clazz);
-    }
-    env->SetIntField(clazz, so.surfaceControl, (int)surface.get());
-}
-
-static sp<Surface> getSurface(JNIEnv* env, jobject clazz)
-{
-    sp<Surface> result(Surface_getSurface(env, clazz));
-    if (result == 0) {
-        /*
-         * if this method is called from the WindowManager's process, it means
-         * the client is is not remote, and therefore is allowed to have
-         * a Surface (data), so we create it here.
-         * If we don't have a SurfaceControl, it means we're in a different
-         * process.
-         */
-
-        SurfaceControl* const control =
-            (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
-        if (control) {
-            result = control->getSurface();
-            if (result != 0) {
-                result->incStrong(clazz);
-                env->SetIntField(clazz, so.surface, (int)result.get());
-            }
-        }
-    }
-    return result;
-}
-
-sp<ANativeWindow> android_Surface_getNativeWindow(
-        JNIEnv* env, jobject clazz) {
-    return getSurface(env, clazz);
-}
-
-bool android_Surface_isInstanceOf(JNIEnv* env, jobject obj) {
-    jclass surfaceClass = env->FindClass(kSurfaceClassPathName);
-    return env->IsInstanceOf(obj, surfaceClass);
-}
-
-sp<Surface> Surface_getSurface(JNIEnv* env, jobject clazz) {
-    sp<Surface> surface((Surface*)env->GetIntField(clazz, so.surface));
-    return surface;
-}
-
-void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface)
-{
-    Surface* const p = (Surface*)env->GetIntField(clazz, so.surface);
-    if (surface.get()) {
-        surface->incStrong(clazz);
-    }
-    if (p) {
-        p->decStrong(clazz);
-    }
-    env->SetIntField(clazz, so.surface, (int)surface.get());
-    // This test is conservative and it would be better to compare the ISurfaces
-    if (p && p != surface.get()) {
-        jint generationId = env->GetIntField(clazz, so.surfaceGenerationId);
-        generationId++;
-        env->SetIntField(clazz, so.surfaceGenerationId, generationId);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-static void Surface_init(
-        JNIEnv* env, jobject clazz,
-        jobject session,
-        jint, jstring jname, jint dpy, jint w, jint h, jint format, jint flags)
-{
-    if (session == NULL) {
-        doThrowNPE(env);
-        return;
-    }
-
-    SurfaceComposerClient* client =
-            (SurfaceComposerClient*)env->GetIntField(session, sso.client);
-
-    sp<SurfaceControl> surface;
-    if (jname == NULL) {
-        surface = client->createSurface(dpy, w, h, format, flags);
-    } else {
-        const jchar* str = env->GetStringCritical(jname, 0);
-        const String8 name(str, env->GetStringLength(jname));
-        env->ReleaseStringCritical(jname, str);
-        surface = client->createSurface(name, dpy, w, h, format, flags);
-    }
-
-    if (surface == 0) {
-        jniThrowException(env, OutOfResourcesException, NULL);
-        return;
-    }
-    setSurfaceControl(env, clazz, surface);
-}
-
-static void Surface_initFromSurfaceTexture(
-        JNIEnv* env, jobject clazz, jobject jst)
-{
-    sp<SurfaceTexture> st(SurfaceTexture_getSurfaceTexture(env, jst));
-
-    if (st == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException",
-                "SurfaceTexture has already been released");
-        return;
-    }
-    sp<ISurfaceTexture> bq = st->getBufferQueue();
-
-    sp<Surface> surface(new Surface(bq));
-    if (surface == NULL) {
-        jniThrowException(env, OutOfResourcesException, NULL);
-        return;
-    }
-    setSurfaceControl(env, clazz, NULL);
-    setSurface(env, clazz, surface);
-}
-
-static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel)
-{
-    Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel);
-    if (parcel == NULL) {
-        doThrowNPE(env);
-        return;
-    }
-
-    sp<Surface> sur(Surface::readFromParcel(*parcel));
-    setSurface(env, clazz, sur);
-}
-
-static jint Surface_getIdentity(JNIEnv* env, jobject clazz)
-{
-    const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
-    if (control != 0) return (jint) control->getIdentity();
-    const sp<Surface>& surface(getSurface(env, clazz));
-    if (surface != 0) return (jint) surface->getIdentity();
-    return -1;
-}
-
-static void Surface_destroy(JNIEnv* env, jobject clazz, uintptr_t *ostack)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (SurfaceControl::isValid(surface)) {
-        surface->clear();
-    }
-    setSurfaceControl(env, clazz, 0);
-    setSurface(env, clazz, 0);
-}
-
-static void Surface_release(JNIEnv* env, jobject clazz, uintptr_t *ostack)
-{
-    setSurfaceControl(env, clazz, 0);
-    setSurface(env, clazz, 0);
-}
-
-static jboolean Surface_isValid(JNIEnv* env, jobject clazz)
-{
-    const sp<SurfaceControl>& surfaceControl(getSurfaceControl(env, clazz));
-    if (surfaceControl != 0) {
-        return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE;
-    }
-    const sp<Surface>& surface(getSurface(env, clazz));
-    return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean Surface_isConsumerRunningBehind(JNIEnv* env, jobject clazz)
-{
-    int value = 0;
-    const sp<Surface>& surface(getSurface(env, clazz));
-    if (!Surface::isValid(surface)) {
-        doThrowIAE(env);
-        return 0;
-    }
-    ANativeWindow* anw = static_cast<ANativeWindow *>(surface.get());
-    anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value);
-    return (jboolean)value;
-}
-
-static inline SkBitmap::Config convertPixelFormat(PixelFormat format)
-{
-    /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
-        we can map to SkBitmap::kARGB_8888_Config, and optionally call
-        bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
-    */
-    switch (format) {
-    case PIXEL_FORMAT_RGBX_8888:    return SkBitmap::kARGB_8888_Config;
-    case PIXEL_FORMAT_RGBA_8888:    return SkBitmap::kARGB_8888_Config;
-    case PIXEL_FORMAT_RGBA_4444:    return SkBitmap::kARGB_4444_Config;
-    case PIXEL_FORMAT_RGB_565:      return SkBitmap::kRGB_565_Config;
-    case PIXEL_FORMAT_A_8:          return SkBitmap::kA8_Config;
-    default:                        return SkBitmap::kNo_Config;
-    }
-}
-
-static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect)
-{
-    const sp<Surface>& surface(getSurface(env, clazz));
-    if (!Surface::isValid(surface)) {
-        doThrowIAE(env);
-        return 0;
-    }
-
-    // get dirty region
-    Region dirtyRegion;
-    if (dirtyRect) {
-        Rect dirty;
-        dirty.left  = env->GetIntField(dirtyRect, ro.l);
-        dirty.top   = env->GetIntField(dirtyRect, ro.t);
-        dirty.right = env->GetIntField(dirtyRect, ro.r);
-        dirty.bottom= env->GetIntField(dirtyRect, ro.b);
-        if (!dirty.isEmpty()) {
-            dirtyRegion.set(dirty);
-        }
-    } else {
-        dirtyRegion.set(Rect(0x3FFF,0x3FFF));
-    }
-
-    Surface::SurfaceInfo info;
-    status_t err = surface->lock(&info, &dirtyRegion);
-    if (err < 0) {
-        const char* const exception = (err == NO_MEMORY) ?
-            OutOfResourcesException :
-            "java/lang/IllegalArgumentException";
-        jniThrowException(env, exception, NULL);
-        return 0;
-    }
-
-    // Associate a SkCanvas object to this surface
-    jobject canvas = env->GetObjectField(clazz, so.canvas);
-    env->SetIntField(canvas, co.surfaceFormat, info.format);
-
-    SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
-    SkBitmap bitmap;
-    ssize_t bpr = info.s * bytesPerPixel(info.format);
-    bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
-    if (info.format == PIXEL_FORMAT_RGBX_8888) {
-        bitmap.setIsOpaque(true);
-    }
-    if (info.w > 0 && info.h > 0) {
-        bitmap.setPixels(info.bits);
-    } else {
-        // be safe with an empty bitmap.
-        bitmap.setPixels(NULL);
-    }
-    nativeCanvas->setBitmapDevice(bitmap);
-
-    SkRegion clipReg;
-    if (dirtyRegion.isRect()) { // very common case
-        const Rect b(dirtyRegion.getBounds());
-        clipReg.setRect(b.left, b.top, b.right, b.bottom);
-    } else {
-        size_t count;
-        Rect const* r = dirtyRegion.getArray(&count);
-        while (count) {
-            clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op);
-            r++, count--;
-        }
-    }
-
-    nativeCanvas->clipRegion(clipReg);
-
-    int saveCount = nativeCanvas->save();
-    env->SetIntField(clazz, so.saveCount, saveCount);
-
-    if (dirtyRect) {
-        const Rect& bounds(dirtyRegion.getBounds());
-        env->SetIntField(dirtyRect, ro.l, bounds.left);
-        env->SetIntField(dirtyRect, ro.t, bounds.top);
-        env->SetIntField(dirtyRect, ro.r, bounds.right);
-        env->SetIntField(dirtyRect, ro.b, bounds.bottom);
-    }
-
-    return canvas;
-}
-
-static void Surface_unlockCanvasAndPost(
-        JNIEnv* env, jobject clazz, jobject argCanvas)
-{
-    jobject canvas = env->GetObjectField(clazz, so.canvas);
-    if (env->IsSameObject(canvas, argCanvas) == JNI_FALSE) {
-        doThrowIAE(env);
-        return;
-    }
-
-    const sp<Surface>& surface(getSurface(env, clazz));
-    if (!Surface::isValid(surface))
-        return;
-
-    // detach the canvas from the surface
-    SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
-    int saveCount = env->GetIntField(clazz, so.saveCount);
-    nativeCanvas->restoreToCount(saveCount);
-    nativeCanvas->setBitmapDevice(SkBitmap());
-    env->SetIntField(clazz, so.saveCount, 0);
-
-    // unlock surface
-    status_t err = surface->unlockAndPost();
-    if (err < 0) {
-        doThrowIAE(env);
-    }
-}
-
-static void Surface_unlockCanvas(
-        JNIEnv* env, jobject clazz, jobject argCanvas)
-{
-    // XXX: this API has been removed
-    doThrowIAE(env);
-}
-
-static void Surface_openTransaction(
-        JNIEnv* env, jobject clazz)
-{
-    SurfaceComposerClient::openGlobalTransaction();
-}
-
-static void Surface_closeTransaction(
-        JNIEnv* env, jobject clazz)
-{
-    SurfaceComposerClient::closeGlobalTransaction();
-}
-
-static void Surface_setOrientation(
-        JNIEnv* env, jobject clazz, jint display, jint orientation, jint flags)
-{
-    int err = SurfaceComposerClient::setOrientation(display, orientation, flags);
-    if (err < 0) {
-        doThrowIAE(env);
-    }
-}
-
-static void Surface_freezeDisplay(
-        JNIEnv* env, jobject clazz, jint display)
-{
-    int err = SurfaceComposerClient::freezeDisplay(display, 0);
-    if (err < 0) {
-        doThrowIAE(env);
-    }
-}
-
-static void Surface_unfreezeDisplay(
-        JNIEnv* env, jobject clazz, jint display)
-{
-    int err = SurfaceComposerClient::unfreezeDisplay(display, 0);
-    if (err < 0) {
-        doThrowIAE(env);
-    }
-}
 
 class ScreenshotPixelRef : public SkPixelRef {
 public:
@@ -506,16 +100,18 @@
         SkSafeRef(ctable);
         setImmutable();
     }
+
     virtual ~ScreenshotPixelRef() {
         SkSafeUnref(fCTable);
     }
 
-    status_t update(int width, int height, int minLayer, int maxLayer, bool allLayers) {
+    status_t update(const sp<IBinder>& display, int width, int height,
+            int minLayer, int maxLayer, bool allLayers) {
         status_t res = (width > 0 && height > 0)
                 ? (allLayers
-                        ? mScreenshot.update(width, height)
-                        : mScreenshot.update(width, height, minLayer, maxLayer))
-                : mScreenshot.update();
+                        ? mScreenshot.update(display, width, height)
+                        : mScreenshot.update(display, width, height, minLayer, maxLayer))
+                : mScreenshot.update(display);
         if (res != NO_ERROR) {
             return res;
         }
@@ -556,13 +152,347 @@
     typedef SkPixelRef INHERITED;
 };
 
-static jobject doScreenshot(JNIEnv* env, jobject clazz, jint width, jint height,
-        jint minLayer, jint maxLayer, bool allLayers)
-{
+
+// ----------------------------------------------------------------------------
+
+static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject surfaceObj) {
+    return reinterpret_cast<SurfaceControl*>(
+            env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl));
+}
+
+static void setSurfaceControl(JNIEnv* env, jobject surfaceObj,
+        const sp<SurfaceControl>& surface) {
+    SurfaceControl* const p = reinterpret_cast<SurfaceControl*>(
+            env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl));
+    if (surface.get()) {
+        surface->incStrong(surfaceObj);
+    }
+    if (p) {
+        p->decStrong(surfaceObj);
+    }
+    env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl,
+            reinterpret_cast<jint>(surface.get()));
+}
+
+static sp<Surface> getSurface(JNIEnv* env, jobject surfaceObj) {
+    sp<Surface> result(android_view_Surface_getSurface(env, surfaceObj));
+    if (result == NULL) {
+        /*
+         * if this method is called from the WindowManager's process, it means
+         * the client is is not remote, and therefore is allowed to have
+         * a Surface (data), so we create it here.
+         * If we don't have a SurfaceControl, it means we're in a different
+         * process.
+         */
+
+        SurfaceControl* const control = reinterpret_cast<SurfaceControl*>(
+                env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl));
+        if (control) {
+            result = control->getSurface();
+            if (result != NULL) {
+                result->incStrong(surfaceObj);
+                env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface,
+                        reinterpret_cast<jint>(result.get()));
+            }
+        }
+    }
+    return result;
+}
+
+sp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) {
+    return getSurface(env, surfaceObj);
+}
+
+bool android_view_Surface_isInstanceOf(JNIEnv* env, jobject obj) {
+    return env->IsInstanceOf(obj, gSurfaceClassInfo.clazz);
+}
+
+sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) {
+    return reinterpret_cast<Surface*>(
+            env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface));
+}
+
+static void setSurface(JNIEnv* env, jobject surfaceObj, const sp<Surface>& surface) {
+    Surface* const p = reinterpret_cast<Surface*>(
+            env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface));
+    if (surface.get()) {
+        surface->incStrong(surfaceObj);
+    }
+    if (p) {
+        p->decStrong(surfaceObj);
+    }
+    env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface,
+            reinterpret_cast<jint>(surface.get()));
+
+    // This test is conservative and it would be better to compare the ISurfaces
+    if (p && p != surface.get()) {
+        jint generationId = env->GetIntField(surfaceObj,
+                gSurfaceClassInfo.mGenerationId);
+        generationId++;
+        env->SetIntField(surfaceObj,
+                gSurfaceClassInfo.mGenerationId, generationId);
+    }
+}
+
+static sp<ISurfaceTexture> getISurfaceTexture(JNIEnv* env, jobject surfaceObj) {
+    if (surfaceObj) {
+        sp<Surface> surface(getSurface(env, surfaceObj));
+        if (surface != NULL) {
+            return surface->getSurfaceTexture();
+        }
+    }
+    return NULL;
+}
+
+jobject android_view_Surface_createFromISurfaceTexture(JNIEnv* env,
+        const sp<ISurfaceTexture>& surfaceTexture) {
+    if (surfaceTexture == NULL) {
+        return NULL;
+    }
+
+    sp<Surface> surface(new Surface(surfaceTexture));
+    if (surface == NULL) {
+        return NULL;
+    }
+
+    jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz, gSurfaceClassInfo.ctor);
+    if (surfaceObj == NULL) {
+        if (env->ExceptionCheck()) {
+            ALOGE("Could not create instance of Surface from ISurfaceTexture.");
+            LOGE_EX(env);
+            env->ExceptionClear();
+        }
+        return NULL;
+    }
+
+    setSurface(env, surfaceObj, surface);
+    return surfaceObj;
+}
+
+
+// ----------------------------------------------------------------------------
+
+static void nativeCreate(JNIEnv* env, jobject surfaceObj, jobject sessionObj,
+        jstring nameStr, jint w, jint h, jint format, jint flags) {
+    ScopedUtfChars name(env, nameStr);
+    sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
+
+    sp<SurfaceControl> surface = client->createSurface(
+            String8(name.c_str()), w, h, format, flags);
+    if (surface == NULL) {
+        jniThrowException(env, OutOfResourcesException, NULL);
+        return;
+    }
+
+    setSurfaceControl(env, surfaceObj, surface);
+}
+
+static void nativeCreateFromSurfaceTexture(JNIEnv* env, jobject surfaceObj,
+        jobject surfaceTextureObj) {
+    sp<SurfaceTexture> st(SurfaceTexture_getSurfaceTexture(env, surfaceTextureObj));
+    if (st == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                "SurfaceTexture has already been released");
+        return;
+    }
+
+    sp<ISurfaceTexture> bq = st->getBufferQueue();
+
+    sp<Surface> surface(new Surface(bq));
+    if (surface == NULL) {
+        jniThrowException(env, OutOfResourcesException, NULL);
+        return;
+    }
+
+    setSurface(env, surfaceObj, surface);
+}
+
+static void nativeRelease(JNIEnv* env, jobject surfaceObj) {
+    setSurfaceControl(env, surfaceObj, NULL);
+    setSurface(env, surfaceObj, NULL);
+}
+
+static void nativeDestroy(JNIEnv* env, jobject surfaceObj) {
+    sp<SurfaceControl> surfaceControl(getSurfaceControl(env, surfaceObj));
+    if (SurfaceControl::isValid(surfaceControl)) {
+        surfaceControl->clear();
+    }
+    setSurfaceControl(env, surfaceObj, NULL);
+    setSurface(env, surfaceObj, NULL);
+}
+
+static jboolean nativeIsValid(JNIEnv* env, jobject surfaceObj) {
+    sp<SurfaceControl> surfaceControl(getSurfaceControl(env, surfaceObj));
+    if (surfaceControl != NULL) {
+        return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE;
+    }
+
+    sp<Surface> surface(getSurface(env, surfaceObj));
+    return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jint nativeGetIdentity(JNIEnv* env, jobject surfaceObj) {
+    sp<SurfaceControl> control(getSurfaceControl(env, surfaceObj));
+    if (control != NULL) {
+        return jint(control->getIdentity());
+    }
+
+    sp<Surface> surface(getSurface(env, surfaceObj));
+    if (surface != NULL) {
+        return jint(surface->getIdentity());
+    }
+
+    return -1;
+}
+
+static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jobject surfaceObj) {
+    sp<Surface> surface(getSurface(env, surfaceObj));
+    if (!Surface::isValid(surface)) {
+        doThrowIAE(env);
+        return JNI_FALSE;
+    }
+
+    int value = 0;
+    ANativeWindow* anw = static_cast<ANativeWindow*>(surface.get());
+    anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value);
+    return value;
+}
+
+static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
+    /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
+        we can map to SkBitmap::kARGB_8888_Config, and optionally call
+        bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
+    */
+    switch (format) {
+    case PIXEL_FORMAT_RGBX_8888:    return SkBitmap::kARGB_8888_Config;
+    case PIXEL_FORMAT_RGBA_8888:    return SkBitmap::kARGB_8888_Config;
+    case PIXEL_FORMAT_RGBA_4444:    return SkBitmap::kARGB_4444_Config;
+    case PIXEL_FORMAT_RGB_565:      return SkBitmap::kRGB_565_Config;
+    case PIXEL_FORMAT_A_8:          return SkBitmap::kA8_Config;
+    default:                        return SkBitmap::kNo_Config;
+    }
+}
+
+static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jobject dirtyRectObj) {
+    sp<Surface> surface(getSurface(env, surfaceObj));
+    if (!Surface::isValid(surface)) {
+        doThrowIAE(env);
+        return NULL;
+    }
+
+    // get dirty region
+    Region dirtyRegion;
+    if (dirtyRectObj) {
+        Rect dirty;
+        dirty.left = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
+        dirty.top = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
+        dirty.right = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
+        dirty.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
+        if (!dirty.isEmpty()) {
+            dirtyRegion.set(dirty);
+        }
+    } else {
+        dirtyRegion.set(Rect(0x3FFF, 0x3FFF));
+    }
+
+    Surface::SurfaceInfo info;
+    status_t err = surface->lock(&info, &dirtyRegion);
+    if (err < 0) {
+        const char* const exception = (err == NO_MEMORY) ?
+                OutOfResourcesException :
+                "java/lang/IllegalArgumentException";
+        jniThrowException(env, exception, NULL);
+        return NULL;
+    }
+
+    // Associate a SkCanvas object to this surface
+    jobject canvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas);
+    env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, info.format);
+
+    SkCanvas* nativeCanvas = reinterpret_cast<SkCanvas*>(
+            env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
+    SkBitmap bitmap;
+    ssize_t bpr = info.s * bytesPerPixel(info.format);
+    bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
+    if (info.format == PIXEL_FORMAT_RGBX_8888) {
+        bitmap.setIsOpaque(true);
+    }
+    if (info.w > 0 && info.h > 0) {
+        bitmap.setPixels(info.bits);
+    } else {
+        // be safe with an empty bitmap.
+        bitmap.setPixels(NULL);
+    }
+    nativeCanvas->setBitmapDevice(bitmap);
+
+    SkRegion clipReg;
+    if (dirtyRegion.isRect()) { // very common case
+        const Rect b(dirtyRegion.getBounds());
+        clipReg.setRect(b.left, b.top, b.right, b.bottom);
+    } else {
+        size_t count;
+        Rect const* r = dirtyRegion.getArray(&count);
+        while (count) {
+            clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op);
+            r++, count--;
+        }
+    }
+
+    nativeCanvas->clipRegion(clipReg);
+
+    int saveCount = nativeCanvas->save();
+    env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, saveCount);
+
+    if (dirtyRectObj) {
+        const Rect& bounds(dirtyRegion.getBounds());
+        env->SetIntField(dirtyRectObj, gRectClassInfo.left, bounds.left);
+        env->SetIntField(dirtyRectObj, gRectClassInfo.top, bounds.top);
+        env->SetIntField(dirtyRectObj, gRectClassInfo.right, bounds.right);
+        env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, bounds.bottom);
+    }
+
+    return canvasObj;
+}
+
+static void nativeUnlockCanvasAndPost(JNIEnv* env, jobject surfaceObj, jobject canvasObj) {
+    jobject ownCanvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas);
+    if (!env->IsSameObject(ownCanvasObj, canvasObj)) {
+        doThrowIAE(env);
+        return;
+    }
+
+    sp<Surface> surface(getSurface(env, surfaceObj));
+    if (!Surface::isValid(surface)) {
+        return;
+    }
+
+    // detach the canvas from the surface
+    SkCanvas* nativeCanvas = reinterpret_cast<SkCanvas*>(
+            env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
+    int saveCount = env->GetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount);
+    nativeCanvas->restoreToCount(saveCount);
+    nativeCanvas->setBitmapDevice(SkBitmap());
+    env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, 0);
+
+    // unlock surface
+    status_t err = surface->unlockAndPost();
+    if (err < 0) {
+        doThrowIAE(env);
+    }
+}
+
+static jobject nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj,
+        jint width, jint height, jint minLayer, jint maxLayer, bool allLayers) {
+    sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
+    if (displayToken == NULL) {
+        return NULL;
+    }
+
     ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL);
-    if (pixels->update(width, height, minLayer, maxLayer, allLayers) != NO_ERROR) {
+    if (pixels->update(displayToken, width, height,
+            minLayer, maxLayer, allLayers) != NO_ERROR) {
         delete pixels;
-        return 0;
+        return NULL;
     }
 
     uint32_t w = pixels->getWidth();
@@ -589,116 +519,72 @@
     return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
 }
 
-static jobject Surface_screenshotAll(JNIEnv* env, jobject clazz, jint width, jint height)
-{
-    return doScreenshot(env, clazz, width, height, 0, 0, true);
+static void nativeOpenTransaction(JNIEnv* env, jclass clazz) {
+    SurfaceComposerClient::openGlobalTransaction();
 }
 
-static jobject Surface_screenshot(JNIEnv* env, jobject clazz, jint width, jint height,
-        jint minLayer, jint maxLayer)
-{
-    return doScreenshot(env, clazz, width, height, minLayer, maxLayer, false);
+static void nativeCloseTransaction(JNIEnv* env, jclass clazz) {
+    SurfaceComposerClient::closeGlobalTransaction();
 }
 
-static void Surface_setLayer(
-        JNIEnv* env, jobject clazz, jint zorder)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
+static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) {
+    SurfaceComposerClient::setAnimationTransaction();
+}
+
+static void nativeSetLayer(JNIEnv* env, jobject surfaceObj, jint zorder) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
+
     status_t err = surface->setLayer(zorder);
-    if (err<0 && err!=NO_INIT) {
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
-static void Surface_setPosition(
-        JNIEnv* env, jobject clazz, jfloat x, jfloat y)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
+static void nativeSetPosition(JNIEnv* env, jobject surfaceObj, jfloat x, jfloat y) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
+
     status_t err = surface->setPosition(x, y);
-    if (err<0 && err!=NO_INIT) {
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
-static void Surface_setSize(
-        JNIEnv* env, jobject clazz, jint w, jint h)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
+static void nativeSetSize(JNIEnv* env, jobject surfaceObj, jint w, jint h) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
+
     status_t err = surface->setSize(w, h);
-    if (err<0 && err!=NO_INIT) {
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
-static void Surface_hide(
-        JNIEnv* env, jobject clazz)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
-    status_t err = surface->hide();
-    if (err<0 && err!=NO_INIT) {
-        doThrowIAE(env);
-    }
-}
+static void nativeSetFlags(JNIEnv* env, jobject surfaceObj, jint flags, jint mask) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
 
-static void Surface_show(
-        JNIEnv* env, jobject clazz)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
-    status_t err = surface->show();
-    if (err<0 && err!=NO_INIT) {
-        doThrowIAE(env);
-    }
-}
-
-static void Surface_freeze(
-        JNIEnv* env, jobject clazz)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
-    status_t err = surface->freeze();
-    if (err<0 && err!=NO_INIT) {
-        doThrowIAE(env);
-    }
-}
-
-static void Surface_unfreeze(
-        JNIEnv* env, jobject clazz)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
-    status_t err = surface->unfreeze();
-    if (err<0 && err!=NO_INIT) {
-        doThrowIAE(env);
-    }
-}
-
-static void Surface_setFlags(
-        JNIEnv* env, jobject clazz, jint flags, jint mask)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
     status_t err = surface->setFlags(flags, mask);
-    if (err<0 && err!=NO_INIT) {
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
-static void Surface_setTransparentRegion(
-        JNIEnv* env, jobject clazz, jobject argRegion)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
-    SkRegion* nativeRegion = (SkRegion*)env->GetIntField(argRegion, no.native_region);
+static void nativeSetTransparentRegionHint(JNIEnv* env, jobject surfaceObj, jobject regionObj) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
 
-    const SkIRect& b(nativeRegion->getBounds());
+    SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
+    if (!region) {
+        doThrowIAE(env);
+        return;
+    }
+
+    const SkIRect& b(region->getBounds());
     Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom));
-    if (nativeRegion->isComplex()) {
-        SkRegion::Iterator it(*nativeRegion);
+    if (region->isComplex()) {
+        SkRegion::Iterator it(*region);
         while (!it.done()) {
             const SkIRect& r(it.rect());
             reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom);
@@ -707,134 +593,189 @@
     }
 
     status_t err = surface->setTransparentRegionHint(reg);
-    if (err<0 && err!=NO_INIT) {
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
-static void Surface_setAlpha(
-        JNIEnv* env, jobject clazz, jfloat alpha)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
+static void nativeSetAlpha(JNIEnv* env, jobject surfaceObj, jfloat alpha) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
+
     status_t err = surface->setAlpha(alpha);
-    if (err<0 && err!=NO_INIT) {
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
-static void Surface_setMatrix(
-        JNIEnv* env, jobject clazz,
-        jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
+static void nativeSetMatrix(JNIEnv* env, jobject surfaceObj,
+        jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
+
     status_t err = surface->setMatrix(dsdx, dtdx, dsdy, dtdy);
-    if (err<0 && err!=NO_INIT) {
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
-static void Surface_setFreezeTint(
-        JNIEnv* env, jobject clazz,
-        jint tint)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
-    status_t err = surface->setFreezeTint(tint);
-    if (err<0 && err!=NO_INIT) {
-        doThrowIAE(env);
-    }
-}
+static void nativeSetWindowCrop(JNIEnv* env, jobject surfaceObj, jobject cropObj) {
+    const sp<SurfaceControl>& surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
 
-static void Surface_setWindowCrop(JNIEnv* env, jobject thiz, jobject crop)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, thiz));
-    if (surface == 0) return;
-
-    Rect nativeCrop;
-    if (crop) {
-        nativeCrop.left  = env->GetIntField(crop, ro.l);
-        nativeCrop.top   = env->GetIntField(crop, ro.t);
-        nativeCrop.right = env->GetIntField(crop, ro.r);
-        nativeCrop.bottom= env->GetIntField(crop, ro.b);
+    Rect crop;
+    if (cropObj) {
+        crop.left = env->GetIntField(cropObj, gRectClassInfo.left);
+        crop.top = env->GetIntField(cropObj, gRectClassInfo.top);
+        crop.right = env->GetIntField(cropObj, gRectClassInfo.right);
+        crop.bottom = env->GetIntField(cropObj, gRectClassInfo.bottom);
     } else {
-        nativeCrop.left = nativeCrop.top = nativeCrop.right =
-                nativeCrop.bottom = 0;
+        crop.left = crop.top = crop.right = crop.bottom = 0;
     }
 
-    status_t err = surface->setCrop(nativeCrop);
-    if (err<0 && err!=NO_INIT) {
+    status_t err = surface->setCrop(crop);
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
+static void nativeSetLayerStack(JNIEnv* env, jobject surfaceObj, jint layerStack) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
+
+    status_t err = surface->setLayerStack(layerStack);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) {
+    sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id));
+    return javaObjectForIBinder(env, token);
+}
+
+static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj,
+        jboolean secure) {
+    ScopedUtfChars name(env, nameObj);
+    sp<IBinder> token(SurfaceComposerClient::createDisplay(
+            String8(name.c_str()), bool(secure)));
+    return javaObjectForIBinder(env, token);
+}
+
+static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jobject surfaceObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    sp<ISurfaceTexture> surfaceTexture(getISurfaceTexture(env, surfaceObj));
+    SurfaceComposerClient::setDisplaySurface(token, surfaceTexture);
+}
+
+static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jint layerStack) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    SurfaceComposerClient::setDisplayLayerStack(token, layerStack);
+}
+
+static void nativeSetDisplayProjection(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jint orientation, jobject layerStackRectObj, jobject displayRectObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    Rect layerStackRect;
+    layerStackRect.left = env->GetIntField(layerStackRectObj, gRectClassInfo.left);
+    layerStackRect.top = env->GetIntField(layerStackRectObj, gRectClassInfo.top);
+    layerStackRect.right = env->GetIntField(layerStackRectObj, gRectClassInfo.right);
+    layerStackRect.bottom = env->GetIntField(layerStackRectObj, gRectClassInfo.bottom);
+
+    Rect displayRect;
+    displayRect.left = env->GetIntField(displayRectObj, gRectClassInfo.left);
+    displayRect.top = env->GetIntField(displayRectObj, gRectClassInfo.top);
+    displayRect.right = env->GetIntField(displayRectObj, gRectClassInfo.right);
+    displayRect.bottom = env->GetIntField(displayRectObj, gRectClassInfo.bottom);
+
+    SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect);
+}
+
+static jboolean nativeGetDisplayInfo(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jobject infoObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return JNI_FALSE;
+
+    DisplayInfo info;
+    if (SurfaceComposerClient::getDisplayInfo(token, &info)) {
+        return JNI_FALSE;
+    }
+
+    env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w);
+    env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h);
+    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps);
+    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density);
+    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi);
+    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi);
+    env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure);
+    return JNI_TRUE;
+}
+
+static void nativeBlankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    ALOGD_IF_SLOW(100, "Excessive delay in blankDisplay() while turning screen off");
+    SurfaceComposerClient::blankDisplay(token);
+}
+
+static void nativeUnblankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    ALOGD_IF_SLOW(100, "Excessive delay in unblankDisplay() while turning screen on");
+    SurfaceComposerClient::unblankDisplay(token);
+}
+
 // ----------------------------------------------------------------------------
 
-static void Surface_copyFrom(
-        JNIEnv* env, jobject clazz, jobject other)
-{
-    if (clazz == other)
-        return;
-
-    if (other == NULL) {
-        doThrowNPE(env);
-        return;
-    }
-
+static void nativeCopyFrom(JNIEnv* env, jobject surfaceObj, jobject otherObj) {
     /*
      * This is used by the WindowManagerService just after constructing
      * a Surface and is necessary for returning the Surface reference to
      * the caller. At this point, we should only have a SurfaceControl.
      */
 
-    const sp<SurfaceControl>& surface = getSurfaceControl(env, clazz);
-    const sp<SurfaceControl>& rhs = getSurfaceControl(env, other);
-    if (!SurfaceControl::isSameSurface(surface, rhs)) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    sp<SurfaceControl> other(getSurfaceControl(env, otherObj));
+    if (!SurfaceControl::isSameSurface(surface, other)) {
         // we reassign the surface only if it's a different one
         // otherwise we would loose our client-side state.
-        setSurfaceControl(env, clazz, rhs);
+        setSurfaceControl(env, surfaceObj, other);
     }
 }
 
-static void Surface_transferFrom(
-        JNIEnv* env, jobject clazz, jobject other)
-{
-    if (clazz == other)
-        return;
-
-    if (other == NULL) {
-        doThrowNPE(env);
-        return;
-    }
-
-    sp<SurfaceControl> control(getSurfaceControl(env, other));
-    sp<Surface> surface(Surface_getSurface(env, other));
-    setSurfaceControl(env, clazz, control);
-    setSurface(env, clazz, surface);
-    setSurfaceControl(env, other, 0);
-    setSurface(env, other, 0);
+static void nativeTransferFrom(JNIEnv* env, jobject surfaceObj, jobject otherObj) {
+    sp<SurfaceControl> control(getSurfaceControl(env, otherObj));
+    sp<Surface> surface(android_view_Surface_getSurface(env, otherObj));
+    setSurfaceControl(env, surfaceObj, control);
+    setSurface(env, surfaceObj, surface);
+    setSurfaceControl(env, otherObj, NULL);
+    setSurface(env, otherObj, NULL);
 }
 
-static void Surface_readFromParcel(
-        JNIEnv* env, jobject clazz, jobject argParcel)
-{
-    Parcel* parcel = (Parcel*)env->GetIntField( argParcel, no.native_parcel);
+static void nativeReadFromParcel(JNIEnv* env, jobject surfaceObj, jobject parcelObj) {
+    Parcel* parcel = parcelForJavaObject(env, parcelObj);
     if (parcel == NULL) {
         doThrowNPE(env);
         return;
     }
 
-    sp<Surface> sur(Surface::readFromParcel(*parcel));
-    setSurface(env, clazz, sur);
+    sp<Surface> surface(Surface::readFromParcel(*parcel));
+    setSurfaceControl(env, surfaceObj, NULL);
+    setSurface(env, surfaceObj, surface);
 }
 
-static void Surface_writeToParcel(
-        JNIEnv* env, jobject clazz, jobject argParcel, jint flags)
-{
-    Parcel* parcel = (Parcel*)env->GetIntField(
-            argParcel, no.native_parcel);
-
+static void nativeWriteToParcel(JNIEnv* env, jobject surfaceObj, jobject parcelObj) {
+    Parcel* parcel = parcelForJavaObject(env, parcelObj);
     if (parcel == NULL) {
         doThrowNPE(env);
         return;
@@ -846,114 +787,129 @@
     // available we let it parcel itself. Finally, if the Surface is also
     // NULL we fall back to using the SurfaceControl path which sends an
     // empty surface; this matches legacy behavior.
-    const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
+    sp<SurfaceControl> control(getSurfaceControl(env, surfaceObj));
     if (control != NULL) {
         SurfaceControl::writeSurfaceToParcel(control, parcel);
     } else {
-        sp<Surface> surface(Surface_getSurface(env, clazz));
+        sp<Surface> surface(android_view_Surface_getSurface(env, surfaceObj));
         if (surface != NULL) {
             Surface::writeToParcel(surface, parcel);
         } else {
             SurfaceControl::writeSurfaceToParcel(NULL, parcel);
         }
     }
-    if (flags & PARCELABLE_WRITE_RETURN_VALUE) {
-        setSurfaceControl(env, clazz, NULL);
-        setSurface(env, clazz, NULL);
-    }
 }
 
 // ----------------------------------------------------------------------------
-// ----------------------------------------------------------------------------
-// ----------------------------------------------------------------------------
-
-static void nativeClassInit(JNIEnv* env, jclass clazz);
-
-static JNINativeMethod gSurfaceSessionMethods[] = {
-    {"init",     "()V",  (void*)SurfaceSession_init },
-    {"destroy",  "()V",  (void*)SurfaceSession_destroy },
-    {"kill",     "()V",  (void*)SurfaceSession_kill },
-};
 
 static JNINativeMethod gSurfaceMethods[] = {
-    {"nativeClassInit",     "()V",  (void*)nativeClassInit },
-    {"init",                "(Landroid/view/SurfaceSession;ILjava/lang/String;IIIII)V",  (void*)Surface_init },
-    {"init",                "(Landroid/os/Parcel;)V",  (void*)Surface_initParcel },
-    {"initFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V", (void*)Surface_initFromSurfaceTexture },
-    {"getIdentity",         "()I",  (void*)Surface_getIdentity },
-    {"destroy",             "()V",  (void*)Surface_destroy },
-    {"release",             "()V",  (void*)Surface_release },
-    {"copyFrom",            "(Landroid/view/Surface;)V",  (void*)Surface_copyFrom },
-    {"transferFrom",        "(Landroid/view/Surface;)V",  (void*)Surface_transferFrom },
-    {"isValid",             "()Z",  (void*)Surface_isValid },
-    {"lockCanvasNative",    "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;",  (void*)Surface_lockCanvas },
-    {"unlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvasAndPost },
-    {"unlockCanvas",        "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvas },
-    {"openTransaction",     "()V",  (void*)Surface_openTransaction },
-    {"closeTransaction",    "()V",  (void*)Surface_closeTransaction },
-    {"setOrientation",      "(III)V", (void*)Surface_setOrientation },
-    {"freezeDisplay",       "(I)V", (void*)Surface_freezeDisplay },
-    {"unfreezeDisplay",     "(I)V", (void*)Surface_unfreezeDisplay },
-    {"screenshot",          "(II)Landroid/graphics/Bitmap;", (void*)Surface_screenshotAll },
-    {"screenshot",          "(IIII)Landroid/graphics/Bitmap;", (void*)Surface_screenshot },
-    {"setLayer",            "(I)V", (void*)Surface_setLayer },
-    {"setPosition",         "(FF)V",(void*)Surface_setPosition },
-    {"setSize",             "(II)V",(void*)Surface_setSize },
-    {"hide",                "()V",  (void*)Surface_hide },
-    {"show",                "()V",  (void*)Surface_show },
-    {"freeze",              "()V",  (void*)Surface_freeze },
-    {"unfreeze",            "()V",  (void*)Surface_unfreeze },
-    {"setFlags",            "(II)V",(void*)Surface_setFlags },
-    {"setTransparentRegionHint","(Landroid/graphics/Region;)V", (void*)Surface_setTransparentRegion },
-    {"setAlpha",            "(F)V", (void*)Surface_setAlpha },
-    {"setMatrix",           "(FFFF)V",  (void*)Surface_setMatrix },
-    {"setFreezeTint",       "(I)V",  (void*)Surface_setFreezeTint },
-    {"readFromParcel",      "(Landroid/os/Parcel;)V", (void*)Surface_readFromParcel },
-    {"writeToParcel",       "(Landroid/os/Parcel;I)V", (void*)Surface_writeToParcel },
-    {"isConsumerRunningBehind", "()Z", (void*)Surface_isConsumerRunningBehind },
-    {"setWindowCrop",       "(Landroid/graphics/Rect;)V", (void*)Surface_setWindowCrop },
+    {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)V",
+            (void*)nativeCreate },
+    {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V",
+            (void*)nativeCreateFromSurfaceTexture },
+    {"nativeRelease", "()V",
+            (void*)nativeRelease },
+    {"nativeDestroy", "()V",
+            (void*)nativeDestroy },
+    {"nativeIsValid", "()Z",
+            (void*)nativeIsValid },
+    {"nativeGetIdentity", "()I",
+            (void*)nativeGetIdentity },
+    {"nativeIsConsumerRunningBehind", "()Z",
+            (void*)nativeIsConsumerRunningBehind },
+    {"nativeLockCanvas", "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;",
+            (void*)nativeLockCanvas },
+    {"nativeUnlockCanvasAndPost", "(Landroid/graphics/Canvas;)V",
+            (void*)nativeUnlockCanvasAndPost },
+    {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZ)Landroid/graphics/Bitmap;",
+            (void*)nativeScreenshot },
+    {"nativeOpenTransaction", "()V",
+            (void*)nativeOpenTransaction },
+    {"nativeCloseTransaction", "()V",
+            (void*)nativeCloseTransaction },
+    {"nativeSetAnimationTransaction", "()V",
+            (void*)nativeSetAnimationTransaction },
+    {"nativeSetLayer", "(I)V",
+            (void*)nativeSetLayer },
+    {"nativeSetPosition", "(FF)V",
+            (void*)nativeSetPosition },
+    {"nativeSetSize", "(II)V",
+            (void*)nativeSetSize },
+    {"nativeSetTransparentRegionHint", "(Landroid/graphics/Region;)V",
+            (void*)nativeSetTransparentRegionHint },
+    {"nativeSetAlpha", "(F)V",
+            (void*)nativeSetAlpha },
+    {"nativeSetMatrix", "(FFFF)V",
+            (void*)nativeSetMatrix },
+    {"nativeSetFlags", "(II)V",
+            (void*)nativeSetFlags },
+    {"nativeSetWindowCrop", "(Landroid/graphics/Rect;)V",
+            (void*)nativeSetWindowCrop },
+    {"nativeSetLayerStack", "(I)V",
+            (void*)nativeSetLayerStack },
+    {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;",
+            (void*)nativeGetBuiltInDisplay },
+    {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;",
+            (void*)nativeCreateDisplay },
+    {"nativeSetDisplaySurface", "(Landroid/os/IBinder;Landroid/view/Surface;)V",
+            (void*)nativeSetDisplaySurface },
+    {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V",
+            (void*)nativeSetDisplayLayerStack },
+    {"nativeSetDisplayProjection", "(Landroid/os/IBinder;ILandroid/graphics/Rect;Landroid/graphics/Rect;)V",
+            (void*)nativeSetDisplayProjection },
+    {"nativeGetDisplayInfo", "(Landroid/os/IBinder;Landroid/view/Surface$PhysicalDisplayInfo;)Z",
+            (void*)nativeGetDisplayInfo },
+    {"nativeBlankDisplay", "(Landroid/os/IBinder;)V",
+            (void*)nativeBlankDisplay },
+    {"nativeUnblankDisplay", "(Landroid/os/IBinder;)V",
+            (void*)nativeUnblankDisplay },
+    {"nativeCopyFrom", "(Landroid/view/Surface;)V",
+            (void*)nativeCopyFrom },
+    {"nativeTransferFrom", "(Landroid/view/Surface;)V",
+            (void*)nativeTransferFrom },
+    {"nativeReadFromParcel", "(Landroid/os/Parcel;)V",
+            (void*)nativeReadFromParcel },
+    {"nativeWriteToParcel", "(Landroid/os/Parcel;)V",
+            (void*)nativeWriteToParcel },
 };
 
-void nativeClassInit(JNIEnv* env, jclass clazz)
-{
-    so.surface = env->GetFieldID(clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I");
-    so.surfaceGenerationId = env->GetFieldID(clazz, "mSurfaceGenerationId", "I");
-    so.surfaceControl = env->GetFieldID(clazz, "mSurfaceControl", "I");
-    so.saveCount = env->GetFieldID(clazz, "mSaveCount", "I");
-    so.canvas    = env->GetFieldID(clazz, "mCanvas", "Landroid/graphics/Canvas;");
-
-    jclass surfaceSession = env->FindClass("android/view/SurfaceSession");
-    sso.client = env->GetFieldID(surfaceSession, "mClient", "I");
-
-    jclass canvas = env->FindClass("android/graphics/Canvas");
-    no.native_canvas = env->GetFieldID(canvas, "mNativeCanvas", "I");
-    co.surfaceFormat = env->GetFieldID(canvas, "mSurfaceFormat", "I");
-
-    jclass region = env->FindClass("android/graphics/Region");
-    no.native_region = env->GetFieldID(region, "mNativeRegion", "I");
-
-    jclass parcel = env->FindClass("android/os/Parcel");
-    no.native_parcel = env->GetFieldID(parcel, "mNativePtr", "I");
-
-    jclass rect = env->FindClass("android/graphics/Rect");
-    ro.l = env->GetFieldID(rect, "left", "I");
-    ro.t = env->GetFieldID(rect, "top", "I");
-    ro.r = env->GetFieldID(rect, "right", "I");
-    ro.b = env->GetFieldID(rect, "bottom", "I");
-
-    jclass point = env->FindClass("android/graphics/Point");
-    po.x = env->GetFieldID(point, "x", "I");
-    po.y = env->GetFieldID(point, "y", "I");
-}
-
 int register_android_view_Surface(JNIEnv* env)
 {
-    int err;
-    err = AndroidRuntime::registerNativeMethods(env, kSurfaceSessionClassPathName,
-            gSurfaceSessionMethods, NELEM(gSurfaceSessionMethods));
-
-    err |= AndroidRuntime::registerNativeMethods(env, kSurfaceClassPathName,
+    int err = AndroidRuntime::registerNativeMethods(env, "android/view/Surface",
             gSurfaceMethods, NELEM(gSurfaceMethods));
+
+    jclass clazz = env->FindClass("android/view/Surface");
+    gSurfaceClassInfo.clazz = jclass(env->NewGlobalRef(clazz));
+    gSurfaceClassInfo.mNativeSurface =
+            env->GetFieldID(gSurfaceClassInfo.clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I");
+    gSurfaceClassInfo.mNativeSurfaceControl =
+            env->GetFieldID(gSurfaceClassInfo.clazz, "mNativeSurfaceControl", "I");
+    gSurfaceClassInfo.mGenerationId =
+            env->GetFieldID(gSurfaceClassInfo.clazz, "mGenerationId", "I");
+    gSurfaceClassInfo.mCanvas =
+            env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvas", "Landroid/graphics/Canvas;");
+    gSurfaceClassInfo.mCanvasSaveCount =
+            env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvasSaveCount", "I");
+    gSurfaceClassInfo.ctor = env->GetMethodID(gSurfaceClassInfo.clazz, "<init>", "()V");
+
+    clazz = env->FindClass("android/graphics/Canvas");
+    gCanvasClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "I");
+    gCanvasClassInfo.mSurfaceFormat = env->GetFieldID(clazz, "mSurfaceFormat", "I");
+
+    clazz = env->FindClass("android/graphics/Rect");
+    gRectClassInfo.left = env->GetFieldID(clazz, "left", "I");
+    gRectClassInfo.top = env->GetFieldID(clazz, "top", "I");
+    gRectClassInfo.right = env->GetFieldID(clazz, "right", "I");
+    gRectClassInfo.bottom = env->GetFieldID(clazz, "bottom", "I");
+
+    clazz = env->FindClass("android/view/Surface$PhysicalDisplayInfo");
+    gPhysicalDisplayInfoClassInfo.width = env->GetFieldID(clazz, "width", "I");
+    gPhysicalDisplayInfoClassInfo.height = env->GetFieldID(clazz, "height", "I");
+    gPhysicalDisplayInfoClassInfo.refreshRate = env->GetFieldID(clazz, "refreshRate", "F");
+    gPhysicalDisplayInfoClassInfo.density = env->GetFieldID(clazz, "density", "F");
+    gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F");
+    gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F");
+    gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z");
     return err;
 }
 
diff --git a/core/jni/android_view_SurfaceSession.cpp b/core/jni/android_view_SurfaceSession.cpp
new file mode 100644
index 0000000..1494bc5
--- /dev/null
+++ b/core/jni/android_view_SurfaceSession.cpp
@@ -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.
+ */
+
+#define LOG_TAG "SurfaceSession"
+
+#include "JNIHelp.h"
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_view_SurfaceSession.h>
+#include <utils/Log.h>
+#include <utils/RefBase.h>
+
+#include <gui/SurfaceComposerClient.h>
+
+namespace android {
+
+static struct {
+    jfieldID mNativeClient;
+} gSurfaceSessionClassInfo;
+
+
+sp<SurfaceComposerClient> android_view_SurfaceSession_getClient(
+        JNIEnv* env, jobject surfaceSessionObj) {
+    return reinterpret_cast<SurfaceComposerClient*>(
+            env->GetIntField(surfaceSessionObj, gSurfaceSessionClassInfo.mNativeClient));
+}
+
+
+static jint nativeCreate(JNIEnv* env, jclass clazz) {
+    SurfaceComposerClient* client = new SurfaceComposerClient();
+    client->incStrong(clazz);
+    return reinterpret_cast<jint>(client);
+}
+
+static void nativeDestroy(JNIEnv* env, jclass clazz, jint ptr) {
+    SurfaceComposerClient* client = reinterpret_cast<SurfaceComposerClient*>(ptr);
+    client->decStrong(clazz);
+}
+
+static void nativeKill(JNIEnv* env, jclass clazz, jint ptr) {
+    SurfaceComposerClient* client = reinterpret_cast<SurfaceComposerClient*>(ptr);
+    client->dispose();
+}
+
+
+static JNINativeMethod gMethods[] = {
+    /* name, signature, funcPtr */
+    { "nativeCreate", "()I",
+            (void*)nativeCreate },
+    { "nativeDestroy", "(I)V",
+            (void*)nativeDestroy },
+    { "nativeKill", "(I)V",
+            (void*)nativeKill }
+};
+
+int register_android_view_SurfaceSession(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, "android/view/SurfaceSession",
+            gMethods, NELEM(gMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    jclass clazz = env->FindClass("android/view/SurfaceSession");
+    gSurfaceSessionClassInfo.mNativeClient = env->GetFieldID(clazz, "mNativeClient", "I");
+    return 0;
+}
+
+} // namespace android
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index 9c6c7de..f8904bd 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -326,7 +326,7 @@
         return 0;
     }
 
-    window = android_Surface_getNativeWindow(_env, native_window);
+    window = android_view_Surface_getNativeWindow(_env, native_window);
     if (window == NULL)
         goto not_valid_surface;
 
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index 8777131f..3f9942e 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -114,14 +114,12 @@
 }
 
 static void *
-getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
 {
     jint position;
     jint limit;
     jint elementSizeShift;
     jlong pointer;
-    jint offset;
-    void *data;
 
     position = _env->GetIntField(buffer, positionID);
     limit = _env->GetIntField(buffer, limitID);
@@ -139,11 +137,10 @@
     if (*array == NULL) {
         return (void*) NULL;
     }
-    offset = _env->CallStaticIntMethod(nioAccessClass,
+    *offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
-    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
 
-    return (void *) ((char *) data + offset);
+    return NULL;
 }
 
 static void
@@ -181,10 +178,12 @@
         if (allowIndirectBuffers(_env)) {
             jarray array = 0;
             jint remaining;
-            buf = getPointer(_env, buffer, &array, &remaining);
+            jint offset;
+            buf = getPointer(_env, buffer, &array, &remaining, &offset);
             if (array) {
                 releasePointer(_env, array, buf, 0);
             }
+            buf = buf + offset;
         } else {
             jniThrowException(_env, "java/lang/IllegalArgumentException",
                               "Must use a native order direct Buffer");
@@ -418,6 +417,7 @@
 android_glColorPointerBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -441,10 +441,15 @@
 android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint imageSize, jobject data_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glCompressedTexImage2D(
         (GLenum)target,
         (GLint)level,
@@ -465,10 +470,15 @@
 android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint imageSize, jobject data_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glCompressedTexSubImage2D(
         (GLenum)target,
         (GLint)level,
@@ -530,21 +540,30 @@
 static void
 android_glDeleteTextures__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray textures_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *textures_base = (GLuint *) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
     if (!textures_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "textures == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     textures_base = (GLuint *)
@@ -561,21 +580,34 @@
         _env->ReleasePrimitiveArrayCritical(textures_ref, textures_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteTextures ( GLsizei n, const GLuint *textures ) */
 static void
 android_glDeleteTextures__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject textures_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
-    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
+    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (textures == NULL) {
+        char * _texturesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        textures = (GLuint *) (_texturesBase + _bufferOffset);
+    }
     glDeleteTextures(
         (GLsizei)n,
         (GLuint *)textures
@@ -585,6 +617,9 @@
     if (_array) {
         releasePointer(_env, _array, textures, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDepthFunc ( GLenum func ) */
@@ -658,15 +693,25 @@
 static void
 android_glDrawElements__IIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint mode, jint count, jint type, jobject indices_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *indices = (GLvoid *) 0;
 
-    indices = (GLvoid *)getPointer(_env, indices_buf, &_array, &_remaining);
+    indices = (GLvoid *)getPointer(_env, indices_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < count) {
-        jniThrowException(_env, "java/lang/ArrayIndexOutOfBoundsException", "remaining() < count");
+        _exception = 1;
+        _exceptionType = "java/lang/ArrayIndexOutOfBoundsException";
+        _exceptionMessage = "remaining() < count < needed";
         goto exit;
     }
+    if (indices == NULL) {
+        char * _indicesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        indices = (GLvoid *) (_indicesBase + _bufferOffset);
+    }
     glDrawElements(
         (GLenum)mode,
         (GLsizei)count,
@@ -678,6 +723,9 @@
     if (_array) {
         releasePointer(_env, _array, indices, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glEnable ( GLenum cap ) */
@@ -726,16 +774,23 @@
 static void
 android_glFogfv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -765,7 +820,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -782,17 +839,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFogfv ( GLenum pname, const GLfloat *params ) */
 static void
 android_glFogfv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_FOG_MODE)
@@ -819,9 +883,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glFogfv(
         (GLenum)pname,
         (GLfloat *)params
@@ -831,6 +901,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFogx ( GLenum pname, GLfixed param ) */
@@ -847,16 +920,23 @@
 static void
 android_glFogxv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -886,7 +966,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -903,17 +985,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFogxv ( GLenum pname, const GLfixed *params ) */
 static void
 android_glFogxv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_FOG_MODE)
@@ -940,9 +1029,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glFogxv(
         (GLenum)pname,
         (GLfixed *)params
@@ -952,6 +1047,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFrontFace ( GLenum mode ) */
@@ -996,24 +1094,29 @@
 android_glGenTextures__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray textures_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *textures_base = (GLuint *) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
     if (!textures_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "textures == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     textures_base = (GLuint *)
@@ -1030,6 +1133,9 @@
         _env->ReleasePrimitiveArrayCritical(textures_ref, textures_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenTextures ( GLsizei n, GLuint *textures ) */
@@ -1037,16 +1143,24 @@
 android_glGenTextures__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject textures_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *textures = (GLuint *) 0;
 
-    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
+    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (textures == NULL) {
+        char * _texturesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        textures = (GLuint *) (_texturesBase + _bufferOffset);
+    }
     glGenTextures(
         (GLsizei)n,
         (GLuint *)textures
@@ -1056,6 +1170,9 @@
     if (_array) {
         releasePointer(_env, _array, textures, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* GLenum glGetError ( void ) */
@@ -1072,18 +1189,22 @@
 android_glGetIntegerv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1420,7 +1541,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -1437,6 +1559,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetIntegerv ( GLenum pname, GLint *params ) */
@@ -1444,11 +1569,14 @@
 android_glGetIntegerv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_ALPHA_BITS)
@@ -1782,9 +1910,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetIntegerv(
         (GLenum)pname,
         (GLint *)params
@@ -1794,6 +1927,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* const GLubyte * glGetString ( GLenum name ) */
@@ -1825,16 +1961,23 @@
 static void
 android_glLightModelfv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1855,7 +1998,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1872,17 +2017,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightModelfv ( GLenum pname, const GLfloat *params ) */
 static void
 android_glLightModelfv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_LIGHT_MODEL_TWO_SIDE)
@@ -1900,9 +2052,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glLightModelfv(
         (GLenum)pname,
         (GLfloat *)params
@@ -1912,6 +2070,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightModelx ( GLenum pname, GLfixed param ) */
@@ -1928,16 +2089,23 @@
 static void
 android_glLightModelxv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1958,7 +2126,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1975,17 +2145,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightModelxv ( GLenum pname, const GLfixed *params ) */
 static void
 android_glLightModelxv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_LIGHT_MODEL_TWO_SIDE)
@@ -2003,9 +2180,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glLightModelxv(
         (GLenum)pname,
         (GLfixed *)params
@@ -2015,6 +2198,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightf ( GLenum light, GLenum pname, GLfloat param ) */
@@ -2032,16 +2218,23 @@
 static void
 android_glLightfv__II_3FI
   (JNIEnv *_env, jobject _this, jint light, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2088,7 +2281,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -2106,17 +2301,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightfv ( GLenum light, GLenum pname, const GLfloat *params ) */
 static void
 android_glLightfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SPOT_EXPONENT)
@@ -2160,9 +2362,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glLightfv(
         (GLenum)light,
         (GLenum)pname,
@@ -2173,6 +2381,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightx ( GLenum light, GLenum pname, GLfixed param ) */
@@ -2190,16 +2401,23 @@
 static void
 android_glLightxv__II_3II
   (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2246,7 +2464,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2264,17 +2484,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLightxv ( GLenum light, GLenum pname, const GLfixed *params ) */
 static void
 android_glLightxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SPOT_EXPONENT)
@@ -2318,9 +2545,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glLightxv(
         (GLenum)light,
         (GLenum)pname,
@@ -2331,6 +2564,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLineWidth ( GLfloat width ) */
@@ -2362,16 +2598,23 @@
 static void
 android_glLoadMatrixf___3FI
   (JNIEnv *_env, jobject _this, jfloatArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *m_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *m = (GLfloat *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2388,6 +2631,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLoadMatrixf ( const GLfloat *m ) */
@@ -2395,10 +2641,15 @@
 android_glLoadMatrixf__Ljava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *m = (GLfloat *) 0;
 
-    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfloat *) (_mBase + _bufferOffset);
+    }
     glLoadMatrixf(
         (GLfloat *)m
     );
@@ -2411,16 +2662,23 @@
 static void
 android_glLoadMatrixx___3II
   (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *m_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2437,6 +2695,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLoadMatrixx ( const GLfixed *m ) */
@@ -2444,10 +2705,15 @@
 android_glLoadMatrixx__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
-    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfixed *) (_mBase + _bufferOffset);
+    }
     glLoadMatrixx(
         (GLfixed *)m
     );
@@ -2480,16 +2746,23 @@
 static void
 android_glMaterialfv__II_3FI
   (JNIEnv *_env, jobject _this, jint face, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2522,7 +2795,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -2540,17 +2815,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMaterialfv ( GLenum face, GLenum pname, const GLfloat *params ) */
 static void
 android_glMaterialfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SHININESS)
@@ -2580,9 +2862,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glMaterialfv(
         (GLenum)face,
         (GLenum)pname,
@@ -2593,6 +2881,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMaterialx ( GLenum face, GLenum pname, GLfixed param ) */
@@ -2610,16 +2901,23 @@
 static void
 android_glMaterialxv__II_3II
   (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2652,7 +2950,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2670,17 +2970,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMaterialxv ( GLenum face, GLenum pname, const GLfixed *params ) */
 static void
 android_glMaterialxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SHININESS)
@@ -2710,9 +3017,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glMaterialxv(
         (GLenum)face,
         (GLenum)pname,
@@ -2723,6 +3036,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMatrixMode ( GLenum mode ) */
@@ -2738,16 +3054,23 @@
 static void
 android_glMultMatrixf___3FI
   (JNIEnv *_env, jobject _this, jfloatArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *m_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *m = (GLfloat *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2764,6 +3087,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMultMatrixf ( const GLfloat *m ) */
@@ -2771,10 +3097,15 @@
 android_glMultMatrixf__Ljava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *m = (GLfloat *) 0;
 
-    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfloat *) (_mBase + _bufferOffset);
+    }
     glMultMatrixf(
         (GLfloat *)m
     );
@@ -2787,16 +3118,23 @@
 static void
 android_glMultMatrixx___3II
   (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *m_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "m == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2813,6 +3151,9 @@
         _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glMultMatrixx ( const GLfixed *m ) */
@@ -2820,10 +3161,15 @@
 android_glMultMatrixx__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject m_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *m = (GLfixed *) 0;
 
-    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining);
+    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining, &_bufferOffset);
+    if (m == NULL) {
+        char * _mBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        m = (GLfixed *) (_mBase + _bufferOffset);
+    }
     glMultMatrixx(
         (GLfixed *)m
     );
@@ -2885,6 +3231,7 @@
 android_glNormalPointerBounds__IILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -2996,12 +3343,16 @@
 static void
 android_glReadPixels__IIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint x, jint y, jint width, jint height, jint format, jint type, jobject pixels_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
-    pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+    pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    if (pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
+    }
     glReadPixels(
         (GLint)x,
         (GLint)y,
@@ -3012,7 +3363,7 @@
         (GLvoid *)pixels
     );
     if (_array) {
-        releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, pixels, JNI_TRUE);
     }
 }
 
@@ -3139,6 +3490,7 @@
 android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -3172,16 +3524,23 @@
 static void
 android_glTexEnvfv__II_3FI
   (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3208,7 +3567,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -3226,17 +3587,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnvfv ( GLenum target, GLenum pname, const GLfloat *params ) */
 static void
 android_glTexEnvfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -3260,9 +3628,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glTexEnvfv(
         (GLenum)target,
         (GLenum)pname,
@@ -3273,6 +3647,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnvx ( GLenum target, GLenum pname, GLfixed param ) */
@@ -3290,16 +3667,23 @@
 static void
 android_glTexEnvxv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3326,7 +3710,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -3344,17 +3730,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnvxv ( GLenum target, GLenum pname, const GLfixed *params ) */
 static void
 android_glTexEnvxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -3378,9 +3771,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glTexEnvxv(
         (GLenum)target,
         (GLenum)pname,
@@ -3391,6 +3790,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexImage2D ( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) */
@@ -3398,11 +3800,16 @@
 android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint format, jint type, jobject pixels_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
     if (pixels_buf) {
-        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    }
+    if (pixels_buf && pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
     }
     glTexImage2D(
         (GLenum)target,
@@ -3447,11 +3854,16 @@
 android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint type, jobject pixels_buf) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pixels = (GLvoid *) 0;
 
     if (pixels_buf) {
-        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining, &_bufferOffset);
+    }
+    if (pixels_buf && pixels == NULL) {
+        char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
     }
     glTexSubImage2D(
         (GLenum)target,
@@ -3496,6 +3908,7 @@
 android_glVertexPointerBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -3531,6 +3944,8 @@
 android_glQueryMatrixxOES___3II_3II
   (JNIEnv *_env, jobject _this, jintArray mantissa_ref, jint mantissaOffset, jintArray exponent_ref, jint exponentOffset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLbitfield _returnValue = -1;
     GLfixed *mantissa_base = (GLfixed *) 0;
     jint _mantissaRemaining;
@@ -3541,18 +3956,21 @@
 
     if (!mantissa_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "mantissa == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "mantissa == null";
         goto exit;
     }
     if (mantissaOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "mantissaOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "mantissaOffset < 0";
         goto exit;
     }
     _mantissaRemaining = _env->GetArrayLength(mantissa_ref) - mantissaOffset;
     if (_mantissaRemaining < 16) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - mantissaOffset < 16");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - mantissaOffset < 16 < needed";
         goto exit;
     }
     mantissa_base = (GLfixed *)
@@ -3561,18 +3979,21 @@
 
     if (!exponent_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "exponent == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "exponent == null";
         goto exit;
     }
     if (exponentOffset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "exponentOffset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "exponentOffset < 0";
         goto exit;
     }
     _exponentRemaining = _env->GetArrayLength(exponent_ref) - exponentOffset;
     if (_exponentRemaining < 16) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - exponentOffset < 16");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - exponentOffset < 16 < needed";
         goto exit;
     }
     exponent_base = (GLint *)
@@ -3593,6 +4014,9 @@
         _env->ReleasePrimitiveArrayCritical(mantissa_ref, mantissa_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
     return _returnValue;
 }
 
@@ -3601,37 +4025,54 @@
 android_glQueryMatrixxOES__Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject mantissa_buf, jobject exponent_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _mantissaArray = (jarray) 0;
+    jint _mantissaBufferOffset = (jint) 0;
     jarray _exponentArray = (jarray) 0;
+    jint _exponentBufferOffset = (jint) 0;
     GLbitfield _returnValue = -1;
     jint _mantissaRemaining;
     GLfixed *mantissa = (GLfixed *) 0;
     jint _exponentRemaining;
     GLint *exponent = (GLint *) 0;
 
-    mantissa = (GLfixed *)getPointer(_env, mantissa_buf, &_mantissaArray, &_mantissaRemaining);
+    mantissa = (GLfixed *)getPointer(_env, mantissa_buf, &_mantissaArray, &_mantissaRemaining, &_mantissaBufferOffset);
     if (_mantissaRemaining < 16) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 16");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 16 < needed";
         goto exit;
     }
-    exponent = (GLint *)getPointer(_env, exponent_buf, &_exponentArray, &_exponentRemaining);
+    exponent = (GLint *)getPointer(_env, exponent_buf, &_exponentArray, &_exponentRemaining, &_exponentBufferOffset);
     if (_exponentRemaining < 16) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 16");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 16 < needed";
         goto exit;
     }
+    if (mantissa == NULL) {
+        char * _mantissaBase = (char *)_env->GetPrimitiveArrayCritical(_mantissaArray, (jboolean *) 0);
+        mantissa = (GLfixed *) (_mantissaBase + _mantissaBufferOffset);
+    }
+    if (exponent == NULL) {
+        char * _exponentBase = (char *)_env->GetPrimitiveArrayCritical(_exponentArray, (jboolean *) 0);
+        exponent = (GLint *) (_exponentBase + _exponentBufferOffset);
+    }
     _returnValue = glQueryMatrixxOES(
         (GLfixed *)mantissa,
         (GLint *)exponent
     );
 
 exit:
-    if (_mantissaArray) {
-        releasePointer(_env, _mantissaArray, exponent, _exception ? JNI_FALSE : JNI_TRUE);
-    }
     if (_exponentArray) {
-        releasePointer(_env, _exponentArray, mantissa, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _exponentArray, exponent, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+    if (_mantissaArray) {
+        releasePointer(_env, _mantissaArray, mantissa, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
     }
     return _returnValue;
 }
@@ -3650,17 +4091,27 @@
 static void
 android_glBufferData__IILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint target, jint size, jobject data_buf, jint usage) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
     if (data_buf) {
-        data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+        data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
         if (_remaining < size) {
-            jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "remaining() < size < needed";
             goto exit;
         }
     }
+    if (data_buf && data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glBufferData(
         (GLenum)target,
         (GLsizeiptr)size,
@@ -3672,21 +4123,34 @@
     if (_array) {
         releasePointer(_env, _array, data, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glBufferSubData ( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data ) */
 static void
 android_glBufferSubData__IIILjava_nio_Buffer_2
   (JNIEnv *_env, jobject _this, jint target, jint offset, jint size, jobject data_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *data = (GLvoid *) 0;
 
-    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < size) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < size < needed";
         goto exit;
     }
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLvoid *) (_dataBase + _bufferOffset);
+    }
     glBufferSubData(
         (GLenum)target,
         (GLintptr)offset,
@@ -3698,27 +4162,39 @@
     if (_array) {
         releasePointer(_env, _array, data, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
 static void
 android_glClipPlanef__I_3FI
   (JNIEnv *_env, jobject _this, jint plane, jfloatArray equation_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *equation_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *equation = (GLfloat *) 0;
 
     if (!equation_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "equation == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
     if (_remaining < 4) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 4");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 4 < needed";
         goto exit;
     }
     equation_base = (GLfloat *)
@@ -3735,21 +4211,34 @@
         _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
 static void
 android_glClipPlanef__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *equation = (GLfloat *) 0;
 
-    equation = (GLfloat *)getPointer(_env, equation_buf, &_array, &_remaining);
+    equation = (GLfloat *)getPointer(_env, equation_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 4) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 4");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 4 < needed";
         goto exit;
     }
+    if (equation == NULL) {
+        char * _equationBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        equation = (GLfloat *) (_equationBase + _bufferOffset);
+    }
     glClipPlanef(
         (GLenum)plane,
         (GLfloat *)equation
@@ -3759,27 +4248,39 @@
     if (_array) {
         releasePointer(_env, _array, equation, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanex ( GLenum plane, const GLfixed *equation ) */
 static void
 android_glClipPlanex__I_3II
   (JNIEnv *_env, jobject _this, jint plane, jintArray equation_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *equation_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *equation = (GLfixed *) 0;
 
     if (!equation_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "equation == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
     if (_remaining < 4) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 4");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 4 < needed";
         goto exit;
     }
     equation_base = (GLfixed *)
@@ -3796,21 +4297,34 @@
         _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glClipPlanex ( GLenum plane, const GLfixed *equation ) */
 static void
 android_glClipPlanex__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *equation = (GLfixed *) 0;
 
-    equation = (GLfixed *)getPointer(_env, equation_buf, &_array, &_remaining);
+    equation = (GLfixed *)getPointer(_env, equation_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 4) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 4");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 4 < needed";
         goto exit;
     }
+    if (equation == NULL) {
+        char * _equationBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        equation = (GLfixed *) (_equationBase + _bufferOffset);
+    }
     glClipPlanex(
         (GLenum)plane,
         (GLfixed *)equation
@@ -3820,6 +4334,9 @@
     if (_array) {
         releasePointer(_env, _array, equation, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glColor4ub ( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha ) */
@@ -3850,21 +4367,30 @@
 static void
 android_glDeleteBuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray buffers_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *buffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
     if (!buffers_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "buffers == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -3881,21 +4407,34 @@
         _env->ReleasePrimitiveArrayCritical(buffers_ref, buffers_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteBuffers ( GLsizei n, const GLuint *buffers ) */
 static void
 android_glDeleteBuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject buffers_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
-    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
+    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (buffers == NULL) {
+        char * _buffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        buffers = (GLuint *) (_buffersBase + _bufferOffset);
+    }
     glDeleteBuffers(
         (GLsizei)n,
         (GLuint *)buffers
@@ -3905,18 +4444,27 @@
     if (_array) {
         releasePointer(_env, _array, buffers, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawElements ( GLenum mode, GLsizei count, GLenum type, GLint offset ) */
 static void
 android_glDrawElements__IIII
   (JNIEnv *_env, jobject _this, jint mode, jint count, jint type, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     glDrawElements(
         (GLenum)mode,
         (GLsizei)count,
         (GLenum)type,
         (const GLvoid *)offset
     );
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenBuffers ( GLsizei n, GLuint *buffers ) */
@@ -3924,24 +4472,29 @@
 android_glGenBuffers__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray buffers_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *buffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
     if (!buffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "buffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -3958,6 +4511,9 @@
         _env->ReleasePrimitiveArrayCritical(buffers_ref, buffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenBuffers ( GLsizei n, GLuint *buffers ) */
@@ -3965,16 +4521,24 @@
 android_glGenBuffers__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject buffers_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *buffers = (GLuint *) 0;
 
-    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
+    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (buffers == NULL) {
+        char * _buffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        buffers = (GLuint *) (_buffersBase + _bufferOffset);
+    }
     glGenBuffers(
         (GLsizei)n,
         (GLuint *)buffers
@@ -3984,6 +4548,9 @@
     if (_array) {
         releasePointer(_env, _array, buffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetBooleanv ( GLenum pname, GLboolean *params ) */
@@ -3991,18 +4558,22 @@
 android_glGetBooleanv__I_3ZI
   (JNIEnv *_env, jobject _this, jint pname, jbooleanArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLboolean *params_base = (GLboolean *) 0;
     jint _remaining;
     GLboolean *params = (GLboolean *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4020,24 +4591,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetBooleanv ( GLenum pname, GLboolean *params ) */
 static void
 android_glGetBooleanv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLboolean *params = (GLboolean *) 0;
 
-    params = (GLboolean *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLboolean *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLboolean *) (_paramsBase + _bufferOffset);
+    }
     glGetBooleanv(
         (GLenum)pname,
         (GLboolean *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -4062,18 +4640,22 @@
 android_glGetClipPlanef__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray eqn_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *eqn_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *eqn = (GLfloat *) 0;
 
     if (!eqn_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "eqn == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
@@ -4091,24 +4673,31 @@
         _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetClipPlanef ( GLenum pname, GLfloat *eqn ) */
 static void
 android_glGetClipPlanef__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *eqn = (GLfloat *) 0;
 
-    eqn = (GLfloat *)getPointer(_env, eqn_buf, &_array, &_remaining);
+    eqn = (GLfloat *)getPointer(_env, eqn_buf, &_array, &_remaining, &_bufferOffset);
+    if (eqn == NULL) {
+        char * _eqnBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        eqn = (GLfloat *) (_eqnBase + _bufferOffset);
+    }
     glGetClipPlanef(
         (GLenum)pname,
         (GLfloat *)eqn
     );
     if (_array) {
-        releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, eqn, JNI_TRUE);
     }
 }
 
@@ -4117,18 +4706,22 @@
 android_glGetClipPlanex__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray eqn_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *eqn_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *eqn = (GLfixed *) 0;
 
     if (!eqn_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "eqn == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
@@ -4146,24 +4739,31 @@
         _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetClipPlanex ( GLenum pname, GLfixed *eqn ) */
 static void
 android_glGetClipPlanex__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *eqn = (GLfixed *) 0;
 
-    eqn = (GLfixed *)getPointer(_env, eqn_buf, &_array, &_remaining);
+    eqn = (GLfixed *)getPointer(_env, eqn_buf, &_array, &_remaining, &_bufferOffset);
+    if (eqn == NULL) {
+        char * _eqnBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        eqn = (GLfixed *) (_eqnBase + _bufferOffset);
+    }
     glGetClipPlanex(
         (GLenum)pname,
         (GLfixed *)eqn
     );
     if (_array) {
-        releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, eqn, JNI_TRUE);
     }
 }
 
@@ -4172,18 +4772,22 @@
 android_glGetFixedv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4201,24 +4805,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFixedv ( GLenum pname, GLfixed *params ) */
 static void
 android_glGetFixedv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetFixedv(
         (GLenum)pname,
         (GLfixed *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -4227,18 +4838,22 @@
 android_glGetFloatv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4256,24 +4871,31 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFloatv ( GLenum pname, GLfloat *params ) */
 static void
 android_glGetFloatv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetFloatv(
         (GLenum)pname,
         (GLfloat *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -4282,18 +4904,22 @@
 android_glGetLightfv__II_3FI
   (JNIEnv *_env, jobject _this, jint light, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4341,7 +4967,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -4359,6 +4986,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetLightfv ( GLenum light, GLenum pname, GLfloat *params ) */
@@ -4366,11 +4996,14 @@
 android_glGetLightfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SPOT_EXPONENT)
@@ -4415,9 +5048,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetLightfv(
         (GLenum)light,
         (GLenum)pname,
@@ -4428,6 +5066,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetLightxv ( GLenum light, GLenum pname, GLfixed *params ) */
@@ -4435,18 +5076,22 @@
 android_glGetLightxv__II_3II
   (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4494,7 +5139,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -4512,6 +5158,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetLightxv ( GLenum light, GLenum pname, GLfixed *params ) */
@@ -4519,11 +5168,14 @@
 android_glGetLightxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SPOT_EXPONENT)
@@ -4568,9 +5220,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetLightxv(
         (GLenum)light,
         (GLenum)pname,
@@ -4581,6 +5238,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialfv ( GLenum face, GLenum pname, GLfloat *params ) */
@@ -4588,18 +5248,22 @@
 android_glGetMaterialfv__II_3FI
   (JNIEnv *_env, jobject _this, jint face, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4633,7 +5297,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -4651,6 +5316,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialfv ( GLenum face, GLenum pname, GLfloat *params ) */
@@ -4658,11 +5326,14 @@
 android_glGetMaterialfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SHININESS)
@@ -4693,9 +5364,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetMaterialfv(
         (GLenum)face,
         (GLenum)pname,
@@ -4706,6 +5382,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialxv ( GLenum face, GLenum pname, GLfixed *params ) */
@@ -4713,18 +5392,22 @@
 android_glGetMaterialxv__II_3II
   (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4758,7 +5441,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -4776,6 +5460,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetMaterialxv ( GLenum face, GLenum pname, GLfixed *params ) */
@@ -4783,11 +5470,14 @@
 android_glGetMaterialxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_SHININESS)
@@ -4818,9 +5508,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetMaterialxv(
         (GLenum)face,
         (GLenum)pname,
@@ -4831,6 +5526,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnviv ( GLenum env, GLenum pname, GLint *params ) */
@@ -4838,18 +5536,22 @@
 android_glGetTexEnviv__II_3II
   (JNIEnv *_env, jobject _this, jint env, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4877,7 +5579,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -4895,6 +5598,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnviv ( GLenum env, GLenum pname, GLint *params ) */
@@ -4902,11 +5608,14 @@
 android_glGetTexEnviv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -4931,9 +5640,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetTexEnviv(
         (GLenum)env,
         (GLenum)pname,
@@ -4944,6 +5658,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnvxv ( GLenum env, GLenum pname, GLfixed *params ) */
@@ -4951,18 +5668,22 @@
 android_glGetTexEnvxv__II_3II
   (JNIEnv *_env, jobject _this, jint env, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4990,7 +5711,8 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -5008,6 +5730,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexEnvxv ( GLenum env, GLenum pname, GLfixed *params ) */
@@ -5015,11 +5740,14 @@
 android_glGetTexEnvxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -5044,9 +5772,14 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetTexEnvxv(
         (GLenum)env,
         (GLenum)pname,
@@ -5057,6 +5790,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params ) */
@@ -5064,24 +5800,29 @@
 android_glGetTexParameterfv__II_3FI
   (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -5099,6 +5840,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params ) */
@@ -5106,16 +5850,24 @@
 android_glGetTexParameterfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameterfv(
         (GLenum)target,
         (GLenum)pname,
@@ -5126,6 +5878,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params ) */
@@ -5133,24 +5888,29 @@
 android_glGetTexParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -5168,6 +5928,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params ) */
@@ -5175,16 +5938,24 @@
 android_glGetTexParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameteriv(
         (GLenum)target,
         (GLenum)pname,
@@ -5195,6 +5966,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterxv ( GLenum target, GLenum pname, GLfixed *params ) */
@@ -5202,24 +5976,29 @@
 android_glGetTexParameterxv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -5237,6 +6016,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexParameterxv ( GLenum target, GLenum pname, GLfixed *params ) */
@@ -5244,16 +6026,24 @@
 android_glGetTexParameterxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glGetTexParameterxv(
         (GLenum)target,
         (GLenum)pname,
@@ -5264,6 +6054,9 @@
     if (_array) {
         releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* GLboolean glIsBuffer ( GLuint buffer ) */
@@ -5324,21 +6117,30 @@
 static void
 android_glPointParameterfv__I_3FI
   (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -5355,21 +6157,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointParameterfv ( GLenum pname, const GLfloat *params ) */
 static void
 android_glPointParameterfv__ILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glPointParameterfv(
         (GLenum)pname,
         (GLfloat *)params
@@ -5379,6 +6194,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointParameterx ( GLenum pname, GLfixed param ) */
@@ -5395,21 +6213,30 @@
 static void
 android_glPointParameterxv__I_3II
   (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -5426,21 +6253,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointParameterxv ( GLenum pname, const GLfixed *params ) */
 static void
 android_glPointParameterxv__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glPointParameterxv(
         (GLenum)pname,
         (GLfixed *)params
@@ -5450,6 +6290,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glPointSizePointerOES ( GLenum type, GLsizei stride, const GLvoid *pointer ) */
@@ -5457,6 +6300,7 @@
 android_glPointSizePointerOESBounds__IILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -5501,16 +6345,23 @@
 static void
 android_glTexEnviv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -5537,7 +6388,9 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -5555,17 +6408,24 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexEnviv ( GLenum target, GLenum pname, const GLint *params ) */
 static void
 android_glTexEnviv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     int _needed;
     switch (pname) {
 #if defined(GL_TEXTURE_ENV_MODE)
@@ -5589,9 +6449,15 @@
             break;
     }
     if (_remaining < _needed) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glTexEnviv(
         (GLenum)target,
         (GLenum)pname,
@@ -5602,27 +6468,39 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params ) */
 static void
 android_glTexParameterfv__II_3FI
   (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfloat *)
@@ -5640,21 +6518,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params ) */
 static void
 android_glTexParameterfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glTexParameterfv(
         (GLenum)target,
         (GLenum)pname,
@@ -5665,6 +6556,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameteri ( GLenum target, GLenum pname, GLint param ) */
@@ -5682,21 +6576,30 @@
 static void
 android_glTexParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLint *)
@@ -5714,21 +6617,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameteriv ( GLenum target, GLenum pname, const GLint *params ) */
 static void
 android_glTexParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glTexParameteriv(
         (GLenum)target,
         (GLenum)pname,
@@ -5739,27 +6655,39 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterxv ( GLenum target, GLenum pname, const GLfixed *params ) */
 static void
 android_glTexParameterxv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *params_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 1 < needed";
         goto exit;
     }
     params_base = (GLfixed *)
@@ -5777,21 +6705,34 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexParameterxv ( GLenum target, GLenum pname, const GLfixed *params ) */
 static void
 android_glTexParameterxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *params = (GLfixed *) 0;
 
-    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 1) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 1 < needed";
         goto exit;
     }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfixed *) (_paramsBase + _bufferOffset);
+    }
     glTexParameterxv(
         (GLenum)target,
         (GLenum)pname,
@@ -5802,6 +6743,9 @@
     if (_array) {
         releasePointer(_env, _array, params, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glVertexPointer ( GLint size, GLenum type, GLsizei stride, GLint offset ) */
@@ -5842,21 +6786,30 @@
 static void
 android_glDrawTexfvOES___3FI
   (JNIEnv *_env, jobject _this, jfloatArray coords_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *coords_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *coords = (GLfloat *) 0;
 
     if (!coords_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "coords == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 5 < needed";
         goto exit;
     }
     coords_base = (GLfloat *)
@@ -5872,21 +6825,34 @@
         _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexfvOES ( const GLfloat *coords ) */
 static void
 android_glDrawTexfvOES__Ljava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *coords = (GLfloat *) 0;
 
-    coords = (GLfloat *)getPointer(_env, coords_buf, &_array, &_remaining);
+    coords = (GLfloat *)getPointer(_env, coords_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 5 < needed";
         goto exit;
     }
+    if (coords == NULL) {
+        char * _coordsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        coords = (GLfloat *) (_coordsBase + _bufferOffset);
+    }
     glDrawTexfvOES(
         (GLfloat *)coords
     );
@@ -5895,6 +6861,9 @@
     if (_array) {
         releasePointer(_env, _array, coords, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexiOES ( GLint x, GLint y, GLint z, GLint width, GLint height ) */
@@ -5914,21 +6883,30 @@
 static void
 android_glDrawTexivOES___3II
   (JNIEnv *_env, jobject _this, jintArray coords_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *coords_base = (GLint *) 0;
     jint _remaining;
     GLint *coords = (GLint *) 0;
 
     if (!coords_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "coords == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 5 < needed";
         goto exit;
     }
     coords_base = (GLint *)
@@ -5944,21 +6922,34 @@
         _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexivOES ( const GLint *coords ) */
 static void
 android_glDrawTexivOES__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *coords = (GLint *) 0;
 
-    coords = (GLint *)getPointer(_env, coords_buf, &_array, &_remaining);
+    coords = (GLint *)getPointer(_env, coords_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 5 < needed";
         goto exit;
     }
+    if (coords == NULL) {
+        char * _coordsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        coords = (GLint *) (_coordsBase + _bufferOffset);
+    }
     glDrawTexivOES(
         (GLint *)coords
     );
@@ -5967,6 +6958,9 @@
     if (_array) {
         releasePointer(_env, _array, coords, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexsOES ( GLshort x, GLshort y, GLshort z, GLshort width, GLshort height ) */
@@ -5986,21 +6980,30 @@
 static void
 android_glDrawTexsvOES___3SI
   (JNIEnv *_env, jobject _this, jshortArray coords_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLshort *coords_base = (GLshort *) 0;
     jint _remaining;
     GLshort *coords = (GLshort *) 0;
 
     if (!coords_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "coords == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 5 < needed";
         goto exit;
     }
     coords_base = (GLshort *)
@@ -6016,21 +7019,34 @@
         _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexsvOES ( const GLshort *coords ) */
 static void
 android_glDrawTexsvOES__Ljava_nio_ShortBuffer_2
   (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLshort *coords = (GLshort *) 0;
 
-    coords = (GLshort *)getPointer(_env, coords_buf, &_array, &_remaining);
+    coords = (GLshort *)getPointer(_env, coords_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 5 < needed";
         goto exit;
     }
+    if (coords == NULL) {
+        char * _coordsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        coords = (GLshort *) (_coordsBase + _bufferOffset);
+    }
     glDrawTexsvOES(
         (GLshort *)coords
     );
@@ -6039,6 +7055,9 @@
     if (_array) {
         releasePointer(_env, _array, coords, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexxOES ( GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height ) */
@@ -6058,21 +7077,30 @@
 static void
 android_glDrawTexxvOES___3II
   (JNIEnv *_env, jobject _this, jintArray coords_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfixed *coords_base = (GLfixed *) 0;
     jint _remaining;
     GLfixed *coords = (GLfixed *) 0;
 
     if (!coords_ref) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "coords == null";
         goto exit;
     }
     if (offset < 0) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < 5 < needed";
         goto exit;
     }
     coords_base = (GLfixed *)
@@ -6088,21 +7116,34 @@
         _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
             JNI_ABORT);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDrawTexxvOES ( const GLfixed *coords ) */
 static void
 android_glDrawTexxvOES__Ljava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfixed *coords = (GLfixed *) 0;
 
-    coords = (GLfixed *)getPointer(_env, coords_buf, &_array, &_remaining);
+    coords = (GLfixed *)getPointer(_env, coords_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < 5) {
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < 5 < needed";
         goto exit;
     }
+    if (coords == NULL) {
+        char * _coordsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        coords = (GLfixed *) (_coordsBase + _bufferOffset);
+    }
     glDrawTexxvOES(
         (GLfixed *)coords
     );
@@ -6111,6 +7152,9 @@
     if (_array) {
         releasePointer(_env, _array, coords, JNI_FALSE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glLoadPaletteFromModelViewMatrixOES ( void ) */
@@ -6125,6 +7169,7 @@
 android_glMatrixIndexPointerOESBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -6160,6 +7205,7 @@
 android_glWeightPointerOESBounds__IIILjava_nio_Buffer_2I
   (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLvoid *pointer = (GLvoid *) 0;
 
@@ -6273,7 +7319,7 @@
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
         jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glCheckFramebufferStatusOES");
-            return 0;
+    return 0;
     }
     GLint _returnValue = 0;
     _returnValue = glCheckFramebufferStatusOES(
@@ -6292,24 +7338,29 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *framebuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
     if (!framebuffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "framebuffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     framebuffers_base = (GLuint *)
@@ -6326,6 +7377,9 @@
         _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteFramebuffersOES ( GLint n, GLuint *framebuffers ) */
@@ -6338,16 +7392,24 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
-    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (framebuffers == NULL) {
+        char * _framebuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        framebuffers = (GLuint *) (_framebuffersBase + _bufferOffset);
+    }
     glDeleteFramebuffersOES(
         (GLint)n,
         (GLuint *)framebuffers
@@ -6357,6 +7419,9 @@
     if (_array) {
         releasePointer(_env, _array, framebuffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteRenderbuffersOES ( GLint n, GLuint *renderbuffers ) */
@@ -6369,24 +7434,29 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *renderbuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
     if (!renderbuffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "renderbuffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     renderbuffers_base = (GLuint *)
@@ -6403,6 +7473,9 @@
         _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glDeleteRenderbuffersOES ( GLint n, GLuint *renderbuffers ) */
@@ -6415,16 +7488,24 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
-    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (renderbuffers == NULL) {
+        char * _renderbuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        renderbuffers = (GLuint *) (_renderbuffersBase + _bufferOffset);
+    }
     glDeleteRenderbuffersOES(
         (GLint)n,
         (GLuint *)renderbuffers
@@ -6434,6 +7515,9 @@
     if (_array) {
         releasePointer(_env, _array, renderbuffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glFramebufferRenderbufferOES ( GLint target, GLint attachment, GLint renderbuffertarget, GLint renderbuffer ) */
@@ -6495,24 +7579,29 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *framebuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
     if (!framebuffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "framebuffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     framebuffers_base = (GLuint *)
@@ -6529,6 +7618,9 @@
         _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenFramebuffersOES ( GLint n, GLuint *framebuffers ) */
@@ -6541,16 +7633,24 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *framebuffers = (GLuint *) 0;
 
-    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+    framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (framebuffers == NULL) {
+        char * _framebuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        framebuffers = (GLuint *) (_framebuffersBase + _bufferOffset);
+    }
     glGenFramebuffersOES(
         (GLint)n,
         (GLuint *)framebuffers
@@ -6560,6 +7660,9 @@
     if (_array) {
         releasePointer(_env, _array, framebuffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenRenderbuffersOES ( GLint n, GLuint *renderbuffers ) */
@@ -6572,24 +7675,29 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLuint *renderbuffers_base = (GLuint *) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
     if (!renderbuffers_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "renderbuffers == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < n < needed";
         goto exit;
     }
     renderbuffers_base = (GLuint *)
@@ -6606,6 +7714,9 @@
         _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGenRenderbuffersOES ( GLint n, GLuint *renderbuffers ) */
@@ -6618,16 +7729,24 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLuint *renderbuffers = (GLuint *) 0;
 
-    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+    renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining, &_bufferOffset);
     if (_remaining < n) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < n < needed";
         goto exit;
     }
+    if (renderbuffers == NULL) {
+        char * _renderbuffersBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        renderbuffers = (GLuint *) (_renderbuffersBase + _bufferOffset);
+    }
     glGenRenderbuffersOES(
         (GLint)n,
         (GLuint *)renderbuffers
@@ -6637,6 +7756,9 @@
     if (_array) {
         releasePointer(_env, _array, renderbuffers, _exception ? JNI_FALSE : JNI_TRUE);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFramebufferAttachmentParameterivOES ( GLint target, GLint attachment, GLint pname, GLint *params ) */
@@ -6649,18 +7771,22 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -6680,6 +7806,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetFramebufferAttachmentParameterivOES ( GLint target, GLint attachment, GLint pname, GLint *params ) */
@@ -6691,12 +7820,16 @@
             "glGetFramebufferAttachmentParameterivOES");
             return;
     }
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetFramebufferAttachmentParameterivOES(
         (GLint)target,
         (GLint)attachment,
@@ -6704,7 +7837,7 @@
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -6718,18 +7851,22 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -6748,6 +7885,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetRenderbufferParameterivOES ( GLint target, GLint pname, GLint *params ) */
@@ -6759,19 +7899,23 @@
             "glGetRenderbufferParameterivOES");
             return;
     }
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetRenderbufferParameterivOES(
         (GLint)target,
         (GLint)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -6785,18 +7929,22 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -6815,6 +7963,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexGenfv ( GLint coord, GLint pname, GLfloat *params ) */
@@ -6826,19 +7977,23 @@
             "glGetTexGenfv");
             return;
     }
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glGetTexGenfv(
         (GLint)coord,
         (GLint)pname,
         (GLfloat *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -6852,18 +8007,22 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -6882,6 +8041,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexGeniv ( GLint coord, GLint pname, GLint *params ) */
@@ -6893,19 +8055,23 @@
             "glGetTexGeniv");
             return;
     }
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetTexGeniv(
         (GLint)coord,
         (GLint)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -6919,18 +8085,22 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -6949,6 +8119,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glGetTexGenxv ( GLint coord, GLint pname, GLint *params ) */
@@ -6960,19 +8133,23 @@
             "glGetTexGenxv");
             return;
     }
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glGetTexGenxv(
         (GLint)coord,
         (GLint)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -6983,7 +8160,7 @@
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
         jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glIsFramebufferOES");
-            return JNI_FALSE;
+    return JNI_FALSE;
     }
     GLboolean _returnValue = JNI_FALSE;
     _returnValue = glIsFramebufferOES(
@@ -6999,7 +8176,7 @@
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
         jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glIsRenderbufferOES");
-            return JNI_FALSE;
+    return JNI_FALSE;
     }
     GLboolean _returnValue = JNI_FALSE;
     _returnValue = glIsRenderbufferOES(
@@ -7051,18 +8228,22 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLfloat *params_base = (GLfloat *) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -7081,6 +8262,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexGenfv ( GLint coord, GLint pname, GLfloat *params ) */
@@ -7092,19 +8276,23 @@
             "glTexGenfv");
             return;
     }
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLfloat *params = (GLfloat *) 0;
 
-    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
     glTexGenfv(
         (GLint)coord,
         (GLint)pname,
         (GLfloat *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -7134,18 +8322,22 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -7164,6 +8356,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexGeniv ( GLint coord, GLint pname, GLint *params ) */
@@ -7175,19 +8370,23 @@
             "glTexGeniv");
             return;
     }
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glTexGeniv(
         (GLint)coord,
         (GLint)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
@@ -7217,18 +8416,22 @@
             return;
     }
     jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
     GLint *params_base = (GLint *) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -7247,6 +8450,9 @@
         _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
             _exception ? JNI_ABORT: 0);
     }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
 }
 
 /* void glTexGenxv ( GLint coord, GLint pname, GLint *params ) */
@@ -7258,19 +8464,23 @@
             "glTexGenxv");
             return;
     }
-    jint _exception = 0;
     jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
     jint _remaining;
     GLint *params = (GLint *) 0;
 
-    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
     glTexGenxv(
         (GLint)coord,
         (GLint)pname,
         (GLint *)params
     );
     if (_array) {
-        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+        releasePointer(_env, _array, params, JNI_TRUE);
     }
 }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9a6b006..7971ccb 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -43,7 +43,9 @@
     <protected-broadcast android:name="android.intent.action.PACKAGE_DATA_CLEARED" />
     <protected-broadcast android:name="android.intent.action.PACKAGE_FIRST_LAUNCH" />
     <protected-broadcast android:name="android.intent.action.PACKAGE_NEEDS_VERIFICATION" />
+    <protected-broadcast android:name="android.intent.action.PACKAGE_VERIFIED" />
     <protected-broadcast android:name="android.intent.action.UID_REMOVED" />
+    <protected-broadcast android:name="android.intent.action.QUERY_PACKAGE_RESTART" />
     <protected-broadcast android:name="android.intent.action.CONFIGURATION_CHANGED" />
     <protected-broadcast android:name="android.intent.action.LOCALE_CHANGED" />
     <protected-broadcast android:name="android.intent.action.BATTERY_CHANGED" />
@@ -62,6 +64,9 @@
     <protected-broadcast android:name="android.intent.action.MASTER_CLEAR_NOTIFICATION" />
     <protected-broadcast android:name="android.intent.action.USER_ADDED" />
     <protected-broadcast android:name="android.intent.action.USER_REMOVED" />
+    <protected-broadcast android:name="android.intent.action.USER_STOPPED" />
+    <protected-broadcast android:name="android.intent.action.USER_BACKGROUND" />
+    <protected-broadcast android:name="android.intent.action.USER_FOREGROUND" />
     <protected-broadcast android:name="android.intent.action.USER_SWITCHED" />
 
     <protected-broadcast android:name="android.app.action.ENTER_CAR_MODE" />
@@ -106,6 +111,8 @@
     <protected-broadcast
         android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
 
+    <protected-broadcast android:name="android.hardware.display.action.WIFI_DISPLAY_STATUS_CHANGED" />
+
     <protected-broadcast android:name="android.hardware.usb.action.USB_STATE" />
     <protected-broadcast android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
     <protected-broadcast android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
@@ -121,6 +128,7 @@
 
     <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE" />
     <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE_IMMEDIATE" />
+    <protected-broadcast android:name="android.net.conn.DATA_ACTIVITY_CHANGE" />
 
     <protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
     <protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_ON_DETECTED" />
@@ -133,45 +141,20 @@
 
     <protected-broadcast android:name="android.os.UpdateLock.UPDATE_LOCK_CHANGED" />
 
+    <protected-broadcast android:name="android.intent.action.DREAMING_STARTED" />
+    <protected-broadcast android:name="android.intent.action.DREAMING_STOPPED" />
+
     <!-- ====================================== -->
     <!-- Permissions for things that cost money -->
     <!-- ====================================== -->
     <eat-comment />
 
     <!-- Used for permissions that can be used to make the user spend money
-         without their direct involvement.  For example, this is the group
-         for permissions that allow you to directly place phone calls,
-         directly send SMS messages, etc. -->
+         without their direct involvement. -->
     <permission-group android:name="android.permission-group.COST_MONEY"
         android:label="@string/permgrouplab_costMoney"
         android:description="@string/permgroupdesc_costMoney" />
 
-
-    <!-- Allows an application to send SMS messages. -->
-    <permission android:name="android.permission.SEND_SMS"
-        android:permissionGroup="android.permission-group.COST_MONEY"
-        android:protectionLevel="dangerous"
-        android:label="@string/permlab_sendSms"
-        android:description="@string/permdesc_sendSms" />
-
-    <!-- Allows an application to send SMS messages via the Messaging app with no user
-         input or confirmation.
-         @hide -->
-    <permission android:name="android.permission.SEND_SMS_NO_CONFIRMATION"
-        android:permissionGroup="android.permission-group.COST_MONEY"
-        android:protectionLevel="signature|system"
-        android:label="@string/permlab_sendSmsNoConfirmation"
-        android:description="@string/permdesc_sendSmsNoConfirmation" />
-
-    <!-- Allows an application to initiate a phone call without going through
-         the Dialer user interface for the user to confirm the call
-         being placed. -->
-    <permission android:name="android.permission.CALL_PHONE"
-        android:permissionGroup="android.permission-group.COST_MONEY"
-        android:protectionLevel="dangerous"
-        android:label="@string/permlab_callPhone"
-        android:description="@string/permdesc_callPhone" />
-
     <!-- ================================== -->
     <!-- Permissions for accessing messages -->
     <!-- ================================== -->
@@ -183,7 +166,27 @@
          receiving or reading an MMS. -->
     <permission-group android:name="android.permission-group.MESSAGES"
         android:label="@string/permgrouplab_messages"
-        android:description="@string/permgroupdesc_messages" />
+        android:icon="@drawable/perm_group_messages"
+        android:description="@string/permgroupdesc_messages"
+        android:permissionGroupFlags="personalInfo"
+        android:priority="360"/>
+
+  <!-- Allows an application to send SMS messages. -->
+    <permission android:name="android.permission.SEND_SMS"
+        android:permissionGroup="android.permission-group.MESSAGES"
+        android:protectionLevel="dangerous"
+        android:permissionFlags="costsMoney"
+        android:label="@string/permlab_sendSms"
+        android:description="@string/permdesc_sendSms" />
+
+    <!-- Allows an application to send SMS messages via the Messaging app with no user
+         input or confirmation.
+         @hide -->
+    <permission android:name="android.permission.SEND_SMS_NO_CONFIRMATION"
+        android:permissionGroup="android.permission-group.MESSAGES"
+        android:protectionLevel="signature|system"
+        android:label="@string/permlab_sendSmsNoConfirmation"
+        android:description="@string/permdesc_sendSmsNoConfirmation" />
 
     <!-- Allows an application to monitor incoming SMS messages, to record
          or perform processing on them. -->
@@ -249,22 +252,25 @@
         android:description="@string/permdesc_receiveWapPush" />
 
     <!-- =============================================================== -->
-    <!-- Permissions for accessing personal info (contacts and calendar) -->
+    <!-- Permissions for accessing social info (contacts and social) -->
     <!-- =============================================================== -->
     <eat-comment />
 
-    <!-- Used for permissions that provide access to the user's private data,
-         such as contacts, calendar events, e-mail messages, etc.  This includes
+    <!-- Used for permissions that provide access to the user's social connections,
+         such as contacts, call logs, social stream, etc.  This includes
          both reading and writing of this data (which should generally be
          expressed as two distinct permissions). -->
 
-    <permission-group android:name="android.permission-group.PERSONAL_INFO"
-        android:label="@string/permgrouplab_personalInfo"
-        android:description="@string/permgroupdesc_personalInfo" />
+    <permission-group android:name="android.permission-group.SOCIAL_INFO"
+        android:label="@string/permgrouplab_socialInfo"
+        android:icon="@drawable/perm_group_social_info"
+        android:description="@string/permgroupdesc_socialInfo"
+        android:permissionGroupFlags="personalInfo"
+        android:priority="320" />
 
     <!-- Allows an application to read the user's contacts data. -->
     <permission android:name="android.permission.READ_CONTACTS"
-        android:permissionGroup="android.permission-group.PERSONAL_INFO"
+        android:permissionGroup="android.permission-group.SOCIAL_INFO"
         android:protectionLevel="dangerous"
         android:label="@string/permlab_readContacts"
         android:description="@string/permdesc_readContacts" />
@@ -272,26 +278,82 @@
     <!-- Allows an application to write (but not read) the user's
          contacts data. -->
     <permission android:name="android.permission.WRITE_CONTACTS"
-        android:permissionGroup="android.permission-group.PERSONAL_INFO"
+        android:permissionGroup="android.permission-group.SOCIAL_INFO"
         android:protectionLevel="dangerous"
         android:label="@string/permlab_writeContacts"
         android:description="@string/permdesc_writeContacts" />
 
-    <!-- Allows an application to read the user's call log. -->
-    <permission android:name="android.permission.READ_CALL_LOG"
+    <!-- Allows an application to execute contacts directory search.
+         This should only be used by ContactsProvider. -->
+    <!-- @hide -->
+    <permission android:name="android.permission.BIND_DIRECTORY_SEARCH"
         android:permissionGroup="android.permission-group.PERSONAL_INFO"
+        android:protectionLevel="signature|system" />
+
+    <!-- Allows an application to read the user's call log.
+         <p class="note"><strong>Note:</strong> If your app uses the
+         {@link #READ_CONTACTS} permission and <em>both</em> your <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+         minSdkVersion}</a> and <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+         targetSdkVersion}</a> values are set to 15 or lower, the system implicitly
+         grants your app this permission. If you don't need this permission, be sure your <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+         targetSdkVersion}</a> is 16 or higher.</p> -->
+    <permission android:name="android.permission.READ_CALL_LOG"
+        android:permissionGroup="android.permission-group.SOCIAL_INFO"
         android:protectionLevel="dangerous"
         android:label="@string/permlab_readCallLog"
         android:description="@string/permdesc_readCallLog" />
 
     <!-- Allows an application to write (but not read) the user's
-         contacts data. -->
+         contacts data.
+         <p class="note"><strong>Note:</strong> If your app uses the
+         {@link #WRITE_CONTACTS} permission and <em>both</em> your <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+         minSdkVersion}</a> and <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+         targetSdkVersion}</a> values are set to 15 or lower, the system implicitly
+         grants your app this permission. If you don't need this permission, be sure your <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+         targetSdkVersion}</a> is 16 or higher.</p>  -->
     <permission android:name="android.permission.WRITE_CALL_LOG"
-        android:permissionGroup="android.permission-group.PERSONAL_INFO"
+        android:permissionGroup="android.permission-group.SOCIAL_INFO"
         android:protectionLevel="dangerous"
         android:label="@string/permlab_writeCallLog"
         android:description="@string/permdesc_writeCallLog" />
 
+  <!-- Allows an application to read from the user's social stream. -->
+    <permission android:name="android.permission.READ_SOCIAL_STREAM"
+        android:permissionGroup="android.permission-group.SOCIAL_INFO"
+        android:protectionLevel="dangerous"
+        android:label="@string/permlab_readSocialStream"
+        android:description="@string/permdesc_readSocialStream" />
+
+    <!-- Allows an application to write (but not read) the user's
+         social stream data. -->
+    <permission android:name="android.permission.WRITE_SOCIAL_STREAM"
+        android:permissionGroup="android.permission-group.SOCIAL_INFO"
+        android:protectionLevel="dangerous"
+        android:label="@string/permlab_writeSocialStream"
+        android:description="@string/permdesc_writeSocialStream" />
+
+    <!-- =============================================================== -->
+    <!-- Permissions for accessing information about the device owner    -->
+    <!-- =============================================================== -->
+    <eat-comment />
+
+    <!-- Used for permissions that provide access to information about the device
+         user such as profile information.  This includes both reading and
+         writing of this data (which should generally be expressed as two
+         distinct permissions). -->
+    <permission-group android:name="android.permission-group.PERSONAL_INFO"
+        android:label="@string/permgrouplab_personalInfo"
+        android:icon="@drawable/perm_group_personal_info"
+        android:description="@string/permgroupdesc_personalInfo"
+        android:permissionGroupFlags="personalInfo"
+        android:priority="310" />
+
     <!-- Allows an application to read the user's personal profile data. -->
     <permission android:name="android.permission.READ_PROFILE"
         android:permissionGroup="android.permission-group.PERSONAL_INFO"
@@ -307,20 +369,19 @@
         android:label="@string/permlab_writeProfile"
         android:description="@string/permdesc_writeProfile" />
 
-    <!-- Allows an application to read from the user's social stream. -->
-    <permission android:name="android.permission.READ_SOCIAL_STREAM"
-        android:permissionGroup="android.permission-group.PERSONAL_INFO"
-        android:protectionLevel="dangerous"
-        android:label="@string/permlab_readSocialStream"
-        android:description="@string/permdesc_readSocialStream" />
+    <!-- =============================================================== -->
+    <!-- Permissions for accessing the device calendar                   -->
+    <!-- =============================================================== -->
+    <eat-comment />
 
-    <!-- Allows an application to write (but not read) the user's
-         social stream data. -->
-    <permission android:name="android.permission.WRITE_SOCIAL_STREAM"
-        android:permissionGroup="android.permission-group.PERSONAL_INFO"
-        android:protectionLevel="dangerous"
-        android:label="@string/permlab_writeSocialStream"
-        android:description="@string/permdesc_writeSocialStream" />
+    <!-- Used for permissions that provide access to the device
+         calendar to create / view events.-->
+    <permission-group android:name="android.permission-group.CALENDAR"
+        android:label="@string/permgrouplab_calendar"
+        android:icon="@drawable/perm_group_calendar"
+        android:description="@string/permgroupdesc_calendar"
+        android:permissionGroupFlags="personalInfo"
+        android:priority="290" />
 
     <!-- Allows an application to read the user's calendar data. -->
     <permission android:name="android.permission.READ_CALENDAR"
@@ -337,26 +398,62 @@
         android:label="@string/permlab_writeCalendar"
         android:description="@string/permdesc_writeCalendar" />
 
+    <!-- =============================================================== -->
+    <!-- Permissions for accessing the user dictionary-->
+    <!-- =============================================================== -->
+    <eat-comment />
+
+    <!-- Used for permissions that provide access to the user
+         calendar to create / view events.-->
+    <permission-group android:name="android.permission-group.USER_DICTIONARY"
+        android:label="@string/permgrouplab_dictionary"
+        android:icon="@drawable/perm_group_user_dictionary"
+        android:description="@string/permgroupdesc_dictionary"
+        android:permissionGroupFlags="personalInfo"
+        android:priority="170" />
+
     <!-- Allows an application to read the user dictionary. This should
          really only be required by an IME, or a dictionary editor like
          the Settings app. -->
     <permission android:name="android.permission.READ_USER_DICTIONARY"
-        android:permissionGroup="android.permission-group.PERSONAL_INFO"
+        android:permissionGroup="android.permission-group.USER_DICTIONARY"
         android:protectionLevel="dangerous"
         android:label="@string/permlab_readDictionary"
         android:description="@string/permdesc_readDictionary" />
 
+    <!-- Used for permissions that provide access to the user
+         calendar to create / view events.-->
+    <permission-group android:name="android.permission-group.WRITE_USER_DICTIONARY"
+        android:label="@string/permgrouplab_writeDictionary"
+        android:icon="@drawable/perm_group_user_dictionary_write"
+        android:description="@string/permgroupdesc_writeDictionary"
+        android:priority="160" />
+
     <!-- Allows an application to write to the user dictionary. -->
     <permission android:name="android.permission.WRITE_USER_DICTIONARY"
-        android:permissionGroup="android.permission-group.PERSONAL_INFO"
+        android:permissionGroup="android.permission-group.WRITE_USER_DICTIONARY"
         android:protectionLevel="normal"
         android:label="@string/permlab_writeDictionary"
         android:description="@string/permdesc_writeDictionary" />
 
+    <!-- =============================================================== -->
+    <!-- Permissions for accessing the user bookmarks                    -->
+    <!-- =============================================================== -->
+    <eat-comment />
+
+    <!-- Used for permissions that provide access to the user
+         bookmarks and browser history.-->
+    <permission-group android:name="android.permission-group.BOOKMARKS"
+        android:label="@string/permgrouplab_bookmarks"
+        android:icon="@drawable/perm_group_bookmarks"
+        android:description="@string/permgroupdesc_bookmarks"
+        android:permissionGroupFlags="personalInfo"
+        android:priority="300" />
+
     <!-- Allows an application to read (but not write) the user's
         browsing history and bookmarks. -->
     <permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"
-        android:permissionGroup="android.permission-group.PERSONAL_INFO"
+        android:permissionGroup="android.permission-group.BOOKMARKS"
         android:label="@string/permlab_readHistoryBookmarks"
         android:description="@string/permdesc_readHistoryBookmarks"
         android:protectionLevel="dangerous" />
@@ -364,23 +461,48 @@
     <!-- Allows an application to write (but not read) the user's
         browsing history and bookmarks. -->
     <permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"
-        android:permissionGroup="android.permission-group.PERSONAL_INFO"
+        android:permissionGroup="android.permission-group.BOOKMARKS"
         android:label="@string/permlab_writeHistoryBookmarks"
         android:description="@string/permdesc_writeHistoryBookmarks"
         android:protectionLevel="dangerous" />
 
+    <!-- =============================================================== -->
+    <!-- Permissions for setting the device alarm                        -->
+    <!-- =============================================================== -->
+    <eat-comment />
+
+    <!-- Used for permissions that provide access to the user voicemail box. -->
+    <permission-group android:name="android.permission-group.DEVICE_ALARMS"
+        android:label="@string/permgrouplab_deviceAlarms"
+        android:icon="@drawable/perm_group_device_alarms"
+        android:description="@string/permgroupdesc_deviceAlarms"
+        android:permissionGroupFlags="personalInfo"
+        android:priority="210" />
+
     <!-- Allows an application to broadcast an Intent to set an alarm for the
          user. -->
     <permission android:name="com.android.alarm.permission.SET_ALARM"
-        android:permissionGroup="android.permission-group.PERSONAL_INFO"
+        android:permissionGroup="android.permission-group.DEVICE_ALARMS"
         android:label="@string/permlab_setAlarm"
         android:description="@string/permdesc_setAlarm"
         android:protectionLevel="normal" />
 
+    <!-- =============================================================== -->
+    <!-- Permissions for accessing the user voicemail                    -->
+    <!-- =============================================================== -->
+    <eat-comment />
+
+    <!-- Used for permissions that provide access to the user voicemail box. -->
+    <permission-group android:name="android.permission-group.VOICEMAIL"
+        android:label="@string/permgrouplab_voicemail"
+        android:icon="@drawable/perm_group_voicemail"
+        android:description="@string/permgroupdesc_voicemail"
+        android:permissionGroupFlags="personalInfo"
+        android:priority="280" />
 
    <!-- Allows an application to add voicemails into the system. -->
     <permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL"
-        android:permissionGroup="android.permission-group.PERSONAL_INFO"
+        android:permissionGroup="android.permission-group.VOICEMAIL"
         android:protectionLevel="dangerous"
         android:label="@string/permlab_addVoicemail"
         android:description="@string/permdesc_addVoicemail" />
@@ -395,16 +517,20 @@
     <permission-group android:name="android.permission-group.LOCATION"
         android:label="@string/permgrouplab_location"
         android:icon="@drawable/perm_group_location"
-        android:description="@string/permgroupdesc_location" />
+        android:description="@string/permgroupdesc_location"
+        android:permissionGroupFlags="personalInfo"
+        android:priority="330" />
 
-    <!-- Allows an application to access fine (e.g., GPS) location -->
+    <!-- Allows an app to access precise location from location sources such
+         as GPS, cell towers, and Wi-Fi. -->
     <permission android:name="android.permission.ACCESS_FINE_LOCATION"
         android:permissionGroup="android.permission-group.LOCATION"
         android:protectionLevel="dangerous"
         android:label="@string/permlab_accessFineLocation"
         android:description="@string/permdesc_accessFineLocation" />
 
-    <!-- Allows an application to access coarse (e.g., Cell-ID, WiFi) location -->
+    <!-- Allows an app to access approximate location derived from network location
+         sources such as cell towers and Wi-Fi. -->
     <permission android:name="android.permission.ACCESS_COARSE_LOCATION"
         android:permissionGroup="android.permission-group.LOCATION"
         android:protectionLevel="dangerous"
@@ -413,14 +539,14 @@
 
     <!-- Allows an application to create mock location providers for testing -->
     <permission android:name="android.permission.ACCESS_MOCK_LOCATION"
-        android:permissionGroup="android.permission-group.LOCATION"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
         android:protectionLevel="dangerous"
         android:label="@string/permlab_accessMockLocation"
         android:description="@string/permdesc_accessMockLocation" />
 
     <!-- Allows an application to access extra location provider commands -->
     <permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"
-        android:permissionGroup="android.permission-group.LOCATION"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
         android:protectionLevel="normal"
         android:label="@string/permlab_accessLocationExtraCommands"
         android:description="@string/permdesc_accessLocationExtraCommands" />
@@ -442,7 +568,9 @@
          or other related network operations. -->
     <permission-group android:name="android.permission-group.NETWORK"
         android:label="@string/permgrouplab_network"
-        android:description="@string/permgroupdesc_network" />
+        android:icon="@drawable/perm_group_network"
+        android:description="@string/permgroupdesc_network"
+        android:priority="270" />
 
     <!-- Allows applications to open network sockets. -->
     <permission android:name="android.permission.INTERNET"
@@ -464,6 +592,13 @@
         android:protectionLevel="normal"
         android:description="@string/permdesc_accessWifiState"
         android:label="@string/permlab_accessWifiState" />
+        
+    <!-- Allows applications to change Wi-Fi connectivity state -->
+    <permission android:name="android.permission.CHANGE_WIFI_STATE"
+        android:permissionGroup="android.permission-group.NETWORK"
+        android:protectionLevel="dangerous"
+        android:description="@string/permdesc_changeWifiState"
+        android:label="@string/permlab_changeWifiState" />
 
     <!-- @hide -->
     <permission android:name="android.permission.ACCESS_WIMAX_STATE"
@@ -472,12 +607,45 @@
         android:description="@string/permdesc_accessWimaxState"
         android:label="@string/permlab_accessWimaxState" />
 
-     <!-- Allows applications to connect to paired bluetooth devices -->
-    <permission android:name="android.permission.BLUETOOTH"
+    <!-- @hide -->
+    <permission android:name="android.permission.CHANGE_WIMAX_STATE"
         android:permissionGroup="android.permission-group.NETWORK"
         android:protectionLevel="dangerous"
+        android:description="@string/permdesc_changeWimaxState"
+        android:label="@string/permlab_changeWimaxState" />
+
+    <!-- ======================================= -->
+    <!-- Permissions for short range, peripheral networks -->
+    <!-- ======================================= -->
+    <eat-comment />
+
+    <!-- Used for permissions that provide access to other devices through Bluetooth.-->
+    <permission-group android:name="android.permission-group.BLUETOOTH_NETWORK"
+        android:label="@string/permgrouplab_bluetoothNetwork"
+        android:icon="@drawable/perm_group_bluetooth"
+        android:description="@string/permgroupdesc_bluetoothNetwork"
+        android:priority="260" />
+
+    <!-- Allows applications to connect to paired bluetooth devices -->
+    <permission android:name="android.permission.BLUETOOTH"
+        android:permissionGroup="android.permission-group.BLUETOOTH_NETWORK"
+        android:protectionLevel="dangerous"
         android:description="@string/permdesc_bluetooth"
         android:label="@string/permlab_bluetooth" />
+        
+    <!-- Allows applications to discover and pair bluetooth devices -->
+    <permission android:name="android.permission.BLUETOOTH_ADMIN"
+        android:permissionGroup="android.permission-group.BLUETOOTH_NETWORK"
+        android:protectionLevel="dangerous"
+        android:description="@string/permdesc_bluetoothAdmin"
+        android:label="@string/permlab_bluetoothAdmin" />
+   
+    <!-- Allows bluetooth stack to access files
+         @hide This should only be used by Bluetooth apk.
+    -->
+    <permission android:name="android.permission.BLUETOOTH_STACK"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature" />
 
     <!-- Allows applications to perform I/O operations over NFC -->
     <permission android:name="android.permission.NFC"
@@ -486,28 +654,17 @@
         android:description="@string/permdesc_nfc"
         android:label="@string/permlab_nfc" />
 
-    <!-- Allows an application to use SIP service -->
-    <permission android:name="android.permission.USE_SIP"
-        android:permissionGroup="android.permission-group.NETWORK"
-        android:protectionLevel="dangerous"
-        android:description="@string/permdesc_use_sip"
-        android:label="@string/permlab_use_sip" />
-
-    <!-- Allows applications to call into AccountAuthenticators. Only
-    the system can get this permission. -->
-    <permission android:name="android.permission.ACCOUNT_MANAGER"
-        android:permissionGroup="android.permission-group.ACCOUNTS"
-        android:protectionLevel="signature"
-        android:description="@string/permdesc_accountManagerService"
-        android:label="@string/permlab_accountManagerService" />
-
-    <!-- Allows an internal user to use privileged ConnectivityManager
-    APIs.
+    <!-- Allows an internal user to use privileged ConnectivityManager APIs.
         @hide -->
     <permission android:name="android.permission.CONNECTIVITY_INTERNAL"
         android:permissionGroup="android.permission-group.NETWORK"
         android:protectionLevel="signature|system" />
 
+    <!-- @hide -->
+    <permission android:name="android.permission.RECEIVE_DATA_ACTIVITY_CHANGE"
+        android:permissionGroup="android.permission-group.NETWORK"
+        android:protectionLevel="signature|system" />
+
     <!-- ================================== -->
     <!-- Permissions for accessing accounts -->
     <!-- ================================== -->
@@ -517,7 +674,10 @@
          by the Account Manager. -->
     <permission-group android:name="android.permission-group.ACCOUNTS"
         android:label="@string/permgrouplab_accounts"
-        android:description="@string/permgroupdesc_accounts" />
+        android:icon="@drawable/perm_group_accounts"
+        android:description="@string/permgroupdesc_accounts"
+        android:permissionGroupFlags="personalInfo"
+        android:priority="200" />
 
     <!-- Allows access to the list of accounts in the Accounts Service -->
     <permission android:name="android.permission.GET_ACCOUNTS"
@@ -548,6 +708,77 @@
         android:label="@string/permlab_manageAccounts"
         android:description="@string/permdesc_manageAccounts" />
 
+    <!-- Allows applications to call into AccountAuthenticators. Only
+         the system can get this permission. -->
+    <permission android:name="android.permission.ACCOUNT_MANAGER"
+        android:permissionGroup="android.permission-group.ACCOUNTS"
+        android:protectionLevel="signature"
+        android:description="@string/permdesc_accountManagerService"
+        android:label="@string/permlab_accountManagerService" />
+
+    <!-- ================================== -->
+    <!-- Permissions for accessing hardware that may effect battery life-->
+    <!-- ================================== -->
+    <eat-comment />
+
+    <!-- Used for permissions that provide direct access to the hardware on
+         the device that has an effect on battery life.  This includes vibrator,
+         flashlight,  etc. -->
+
+    <permission-group android:name="android.permission-group.AFFECTS_BATTERY"
+        android:label="@string/permgrouplab_affectsBattery"
+        android:icon="@drawable/perm_group_affects_battery"
+        android:description="@string/permgroupdesc_affectsBattery"
+        android:priority="180" />
+
+    <!-- Allows applications to enter Wi-Fi Multicast mode -->
+    <permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"
+        android:permissionGroup="android.permission-group.AFFECTS_BATTERY"
+        android:protectionLevel="dangerous"
+        android:description="@string/permdesc_changeWifiMulticastState"
+        android:label="@string/permlab_changeWifiMulticastState" />
+
+    <!-- Allows access to the vibrator -->
+    <permission android:name="android.permission.VIBRATE"
+        android:permissionGroup="android.permission-group.AFFECTS_BATTERY"
+        android:protectionLevel="normal"
+        android:label="@string/permlab_vibrate"
+        android:description="@string/permdesc_vibrate" />
+
+    <!-- Allows access to the flashlight -->
+    <permission android:name="android.permission.FLASHLIGHT"
+        android:permissionGroup="android.permission-group.AFFECTS_BATTERY"
+        android:protectionLevel="normal"
+        android:label="@string/permlab_flashlight"
+        android:description="@string/permdesc_flashlight" />
+
+    <!-- Allows using PowerManager WakeLocks to keep processor from sleeping or screen
+         from dimming -->
+    <permission android:name="android.permission.WAKE_LOCK"
+        android:permissionGroup="android.permission-group.AFFECTS_BATTERY"
+        android:protectionLevel="normal"
+        android:label="@string/permlab_wakeLock"
+        android:description="@string/permdesc_wakeLock" />
+
+    <!-- ==================================================== -->
+    <!-- Permissions related to changing audio settings   -->
+    <!-- ==================================================== -->
+
+    <!-- Used for permissions that provide direct access to speaker settings
+         the device. -->
+    <permission-group android:name="android.permission-group.AUDIO_SETTINGS"
+        android:label="@string/permgrouplab_audioSettings"
+        android:icon="@drawable/perm_group_audio_settings"
+        android:description="@string/permgroupdesc_audioSettings"
+        android:priority="130" />
+
+    <!-- Allows an application to modify global audio settings -->
+    <permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"
+        android:permissionGroup="android.permission-group.AUDIO_SETTINGS"
+        android:protectionLevel="normal"
+        android:label="@string/permlab_modifyAudioSettings"
+        android:description="@string/permdesc_modifyAudioSettings" />
+
     <!-- ================================== -->
     <!-- Permissions for accessing hardware -->
     <!-- ================================== -->
@@ -557,49 +788,8 @@
          the device.  This includes audio, the camera, vibrator, etc. -->
     <permission-group android:name="android.permission-group.HARDWARE_CONTROLS"
         android:label="@string/permgrouplab_hardwareControls"
-        android:description="@string/permgroupdesc_hardwareControls" />
-
-
-    <!-- Allows an application to modify global audio settings -->
-    <permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"
-        android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
-        android:protectionLevel="dangerous"
-        android:label="@string/permlab_modifyAudioSettings"
-        android:description="@string/permdesc_modifyAudioSettings" />
-
-    <!-- Allows an application to record audio -->
-    <permission android:name="android.permission.RECORD_AUDIO"
-        android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
-        android:protectionLevel="dangerous"
-        android:label="@string/permlab_recordAudio"
-        android:description="@string/permdesc_recordAudio" />
-
-    <!-- Required to be able to access the camera device.
-         <p>This will automatically enforce the <a
-         href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code
-         &lt;uses-feature&gt;}</a> manifest element for <em>all</em> camera features.
-         If you do not require all camera features or can properly operate if a camera
-         is not available, then you must modify your manifest as appropriate in order to
-         install on devices that don't support all camera features.</p> -->
-    <permission android:name="android.permission.CAMERA"
-        android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
-        android:protectionLevel="dangerous"
-        android:label="@string/permlab_camera"
-        android:description="@string/permdesc_camera" />
-
-    <!-- Allows access to the vibrator -->
-    <permission android:name="android.permission.VIBRATE"
-        android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
-        android:protectionLevel="normal"
-        android:label="@string/permlab_vibrate"
-        android:description="@string/permdesc_vibrate" />
-
-    <!-- Allows access to the flashlight -->
-    <permission android:name="android.permission.FLASHLIGHT"
-        android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
-        android:protectionLevel="normal"
-        android:label="@string/permlab_flashlight"
-        android:description="@string/permdesc_flashlight" />
+        android:description="@string/permgroupdesc_hardwareControls"
+        android:priority="260"/>
 
     <!-- Allows an application to manage preferences and permissions for USB devices
          @hide -->
@@ -637,18 +827,68 @@
         android:protectionLevel="signature" />
 
     <!-- =========================================== -->
+    <!-- Permissions associated with audio capture -->
+    <!-- =========================================== -->
+    <eat-comment />
+
+    <!-- Used for permissions that are associated with accessing
+         microphone audio from the device. Note that phone calls also capture audio
+         but are in a separate (more visible) permission group. -->
+    <permission-group android:name="android.permission-group.MICROPHONE"
+        android:label="@string/permgrouplab_microphone"
+        android:icon="@drawable/perm_group_microphone"
+        android:description="@string/permgroupdesc_microphone"
+        android:permissionGroupFlags="personalInfo"
+        android:priority="340" />
+
+    <!-- Allows an application to record audio -->
+    <permission android:name="android.permission.RECORD_AUDIO"
+        android:permissionGroup="android.permission-group.MICROPHONE"
+        android:protectionLevel="dangerous"
+        android:label="@string/permlab_recordAudio" />
+
+
+    <!-- =========================================== -->
+    <!-- Permissions associated with camera and image capture -->
+    <!-- =========================================== -->
+    <eat-comment />
+
+    <!-- Used for permissions that are associated with accessing
+         camera or capturing images/video from the device. -->
+    <permission-group android:name="android.permission-group.CAMERA"
+        android:label="@string/permgrouplab_camera"
+        android:icon="@drawable/perm_group_camera"
+        android:description="@string/permgroupdesc_camera"
+        android:permissionGroupFlags="personalInfo"
+        android:priority="350" />
+
+    <!-- Required to be able to access the camera device.
+         <p>This will automatically enforce the <a
+         href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code
+         &lt;uses-feature&gt;}</a> manifest element for <em>all</em> camera features.
+         If you do not require all camera features or can properly operate if a camera
+         is not available, then you must modify your manifest as appropriate in order to
+         install on devices that don't support all camera features.</p> -->
+    <permission android:name="android.permission.CAMERA"
+        android:permissionGroup="android.permission-group.CAMERA"
+        android:protectionLevel="dangerous"
+        android:label="@string/permlab_camera"
+        android:description="@string/permdesc_camera" />
+
+    <!-- =========================================== -->
     <!-- Permissions associated with telephony state -->
     <!-- =========================================== -->
     <eat-comment />
 
     <!-- Used for permissions that are associated with accessing and modifyign
-         telephony state: intercepting outgoing calls, reading
-         and modifying the phone state.  Note that
-         placing phone calls is not in this group, since that is in the
-         more important "takin' yer moneys" group. -->
+         telephony state: placing calls, intercepting outgoing calls, reading
+         and modifying the phone state. -->
     <permission-group android:name="android.permission-group.PHONE_CALLS"
         android:label="@string/permgrouplab_phoneCalls"
-        android:description="@string/permgroupdesc_phoneCalls" />
+        android:icon="@drawable/perm_group_phone_calls"
+        android:description="@string/permgroupdesc_phoneCalls"
+        android:permissionGroupFlags="personalInfo"
+        android:priority="370" />
 
     <!-- Allows an application to monitor, modify, or abort outgoing
          calls. -->
@@ -666,7 +906,15 @@
         android:label="@string/permlab_modifyPhoneState"
         android:description="@string/permdesc_modifyPhoneState" />
 
-    <!-- Allows read only access to phone state. -->
+    <!-- Allows read only access to phone state.
+         <p class="note"><strong>Note:</strong> If <em>both</em> your <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+         minSdkVersion}</a> and <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+         targetSdkVersion}</a> values are set to 3 or lower, the system implicitly
+         grants your app this permission. If you don't need this permission, be sure your <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+         targetSdkVersion}</a> is 4 or higher. -->
     <permission android:name="android.permission.READ_PHONE_STATE"
         android:permissionGroup="android.permission-group.PHONE_CALLS"
         android:protectionLevel="dangerous"
@@ -679,6 +927,23 @@
         android:permissionGroup="android.permission-group.PHONE_CALLS"
         android:protectionLevel="signature|system" />
 
+     <!-- Allows an application to initiate a phone call without going through
+         the Dialer user interface for the user to confirm the call
+         being placed. -->
+    <permission android:name="android.permission.CALL_PHONE"
+        android:permissionGroup="android.permission-group.PHONE_CALLS"
+        android:protectionLevel="dangerous"
+        android:permissionFlags="costsMoney"
+        android:label="@string/permlab_callPhone"
+        android:description="@string/permdesc_callPhone" />
+
+    <!-- Allows an application to use SIP service -->
+    <permission android:name="android.permission.USE_SIP"
+        android:permissionGroup="android.permission-group.PHONE_CALLS"
+        android:protectionLevel="dangerous"
+        android:description="@string/permdesc_use_sip"
+        android:label="@string/permlab_use_sip" />
+
     <!-- ================================== -->
     <!-- Permissions for sdcard interaction -->
     <!-- ================================== -->
@@ -687,16 +952,46 @@
     <!-- Group of permissions that are related to SD card access. -->
     <permission-group android:name="android.permission-group.STORAGE"
         android:label="@string/permgrouplab_storage"
-        android:description="@string/permgroupdesc_storage" />
+        android:icon="@drawable/perm_group_storage"
+        android:description="@string/permgroupdesc_storage"
+        android:permissionGroupFlags="personalInfo"
+        android:priority="240" />
 
-    <!-- Allows an application to read from external storage -->
+    <!-- Allows an application to read from external storage.
+         <p>Any app that declares the {@link #WRITE_EXTERNAL_STORAGE} permission is implicitly
+         granted this permission.</p>
+         <p>Currently, this permission is not enforced and all apps still have access to read from
+         external storage without this permission. That will change in a future release and apps
+         will require this permission to read from external storage. So if your
+         app reads from the external storage, you should add this permission to your app now
+         to ensure that it continues to work on future versions of Android.</p>
+         <p>You can test your app with the permission enforced by either running your app on the
+         Android Emulator when running Android 4.1 or higher, or enabling <em>Protect USB
+         storage</em> under Developer options in the Settings app on a device running Android 4.1 or
+         higher.</p>
+         <p class="note"><strong>Note:</strong> If <em>both</em> your <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+         minSdkVersion}</a> and <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+         targetSdkVersion}</a> values are set to 3 or lower, the system implicitly
+         grants your app this permission. If you don't need this permission, be sure your <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+         targetSdkVersion}</a> is 4 or higher.-->
     <permission android:name="android.permission.READ_EXTERNAL_STORAGE"
-        android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
         android:label="@string/permlab_sdcardRead"
         android:description="@string/permdesc_sdcardRead"
         android:protectionLevel="normal" />
 
-    <!-- Allows an application to write to external storage -->
+    <!-- Allows an application to write to external storage.
+         <p class="note"><strong>Note:</strong> If <em>both</em> your <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+         minSdkVersion}</a> and <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+         targetSdkVersion}</a> values are set to 3 or lower, the system implicitly
+         grants your app this permission. If you don't need this permission, be sure your <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+         targetSdkVersion}</a> is 4 or higher. -->
     <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
         android:permissionGroup="android.permission-group.STORAGE"
         android:label="@string/permlab_sdcardWrite"
@@ -711,6 +1006,250 @@
         android:description="@string/permdesc_mediaStorageWrite"
         android:protectionLevel="signature|system" />
 
+    <!-- ================================== -->
+    <!-- Permissions for screenlock         -->
+    <!-- ================================== -->
+    <eat-comment />
+
+    <!-- Group of permissions that are related to the screenlock. -->
+    <permission-group android:name="android.permission-group.SCREENLOCK"
+        android:label="@string/permgrouplab_storage"
+        android:icon="@drawable/perm_group_screenlock"
+        android:permissionGroupFlags="personalInfo"
+        android:description="@string/permgroupdesc_storage"
+        android:priority="230" />
+
+    <!-- Allows applications to disable the keyguard -->
+    <permission android:name="android.permission.DISABLE_KEYGUARD"
+        android:permissionGroup="android.permission-group.SCREENLOCK"
+        android:protectionLevel="dangerous"
+        android:description="@string/permdesc_disableKeyguard"
+        android:label="@string/permlab_disableKeyguard" />
+
+    <!-- ================================== -->
+    <!-- Permissions to access other installed applications  -->
+    <!-- ================================== -->
+    <eat-comment />
+
+    <!-- Group of permissions that are related to the other applications
+         installed on the system.  Examples include such as listing
+         running apps, or killing background processes. -->
+    <permission-group android:name="android.permission-group.APP_INFO"
+        android:label="@string/permgrouplab_appInfo"
+        android:icon="@drawable/perm_group_app_info"
+        android:description="@string/permgroupdesc_appInfo"
+        android:priority="220" />
+
+    <!-- Allows an application to get information about the currently
+         or recently running tasks. -->
+    <permission android:name="android.permission.GET_TASKS"
+        android:permissionGroup="android.permission-group.APP_INFO"
+        android:protectionLevel="dangerous"
+        android:label="@string/permlab_getTasks"
+        android:description="@string/permdesc_getTasks" />
+    <!-- @hide Allows an application to call APIs that allow it to do interactions
+         across the users on the device, using singleton services and
+         user-targeted broadcasts.  This permission is not available to
+         third party applications. -->
+    <permission android:name="android.permission.INTERACT_ACROSS_USERS"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature|system|development"
+        android:label="@string/permlab_interactAcrossUsers"
+        android:description="@string/permdesc_interactAcrossUsers" />
+
+    <!-- @hide Fuller form of {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
+         that removes restrictions on where broadcasts can be sent and allows other
+         types of interactions. -->
+    <permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature"
+        android:label="@string/permlab_interactAcrossUsersFull"
+        android:description="@string/permdesc_interactAcrossUsersFull" />
+
+    <!-- @hide Allows an application to call APIs that allow it to query and manage
+         users on the device. This permission is not available to
+         third party applications. -->
+    <permission android:name="android.permission.MANAGE_USERS"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature|system"
+        android:label="@string/permlab_manageUsers"
+        android:description="@string/permdesc_manageUsers" />
+    
+    <!-- Allows an application to get full detailed information about
+         recently running tasks, with full fidelity to the real state.
+         @hide -->
+    <permission android:name="android.permission.GET_DETAILED_TASKS"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature"
+        android:label="@string/permlab_getDetailedTasks"
+        android:description="@string/permdesc_getDetailedTasks" />
+
+    <!-- Allows an application to change the Z-order of tasks -->
+    <permission android:name="android.permission.REORDER_TASKS"
+        android:permissionGroup="android.permission-group.APP_INFO"
+        android:protectionLevel="normal"
+        android:label="@string/permlab_reorderTasks"
+        android:description="@string/permdesc_reorderTasks" />
+
+    <!-- @hide Allows an application to change to remove/kill tasks -->
+    <permission android:name="android.permission.REMOVE_TASKS"
+        android:permissionGroup="android.permission-group.APP_INFO"
+        android:protectionLevel="signature"
+        android:label="@string/permlab_removeTasks"
+        android:description="@string/permdesc_removeTasks" />
+
+    <!-- Allows an application to start any activity, regardless of permission
+         protection or exported state. @hide -->
+    <permission android:name="android.permission.START_ANY_ACTIVITY"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature"
+        android:label="@string/permlab_startAnyActivity"
+        android:description="@string/permdesc_startAnyActivity" />
+
+    <!-- @deprecated The {@link android.app.ActivityManager#restartPackage}
+        API is no longer supported. -->
+    <permission android:name="android.permission.RESTART_PACKAGES"
+        android:permissionGroup="android.permission-group.APP_INFO"
+        android:protectionLevel="normal"
+        android:label="@string/permlab_killBackgroundProcesses"
+        android:description="@string/permdesc_killBackgroundProcesses" />
+
+    <!-- Allows an application to call
+        {@link android.app.ActivityManager#killBackgroundProcesses}. -->
+    <permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"
+        android:permissionGroup="android.permission-group.APP_INFO"
+        android:protectionLevel="normal"
+        android:label="@string/permlab_killBackgroundProcesses"
+        android:description="@string/permdesc_killBackgroundProcesses" />
+
+    <!-- ================================== -->
+    <!-- Permissions affecting the display of other applications  -->
+    <!-- ================================== -->
+    <eat-comment />
+
+    <!-- Group of permissions that allow manipulation of how
+         another application displays UI to the user. -->
+    <permission-group android:name="android.permission-group.DISPLAY"
+        android:label="@string/permgrouplab_display"
+        android:icon="@drawable/perm_group_display"
+        android:description="@string/permgroupdesc_display"
+        android:priority="190"/>
+
+    <!-- Allows an application to open windows using the type
+         {@link android.view.WindowManager.LayoutParams#TYPE_SYSTEM_ALERT},
+         shown on top of all other applications.  Very few applications
+         should use this permission; these windows are intended for
+         system-level interaction with the user. -->
+    <permission android:name="android.permission.SYSTEM_ALERT_WINDOW"
+        android:permissionGroup="android.permission-group.DISPLAY"
+        android:protectionLevel="dangerous"
+        android:label="@string/permlab_systemAlertWindow"
+        android:description="@string/permdesc_systemAlertWindow" />
+
+    <!-- ================================== -->
+    <!-- Permissions affecting the system wallpaper -->
+    <!-- ================================== -->
+    <eat-comment />
+
+    <!-- Group of permissions that allow manipulation of how
+         another application displays UI to the user. -->
+    <permission-group android:name="android.permission-group.WALLPAPER"
+        android:label="@string/permgrouplab_wallpaper"
+        android:icon="@drawable/perm_group_wallpaper"
+        android:description="@string/permgroupdesc_wallpaper"
+        android:priority="150" />
+
+    <!-- Allows applications to set the wallpaper -->
+    <permission android:name="android.permission.SET_WALLPAPER"
+        android:permissionGroup="android.permission-group.WALLPAPER"
+        android:protectionLevel="normal"
+        android:label="@string/permlab_setWallpaper"
+        android:description="@string/permdesc_setWallpaper" />
+
+    <!-- Allows applications to set the wallpaper hints -->
+    <permission android:name="android.permission.SET_WALLPAPER_HINTS"
+        android:permissionGroup="android.permission-group.WALLPAPER"
+        android:protectionLevel="normal"
+        android:label="@string/permlab_setWallpaperHints"
+        android:description="@string/permdesc_setWallpaperHints" />
+
+    <!-- ============================================ -->
+    <!-- Permissions for changing the system clock -->
+    <!-- ============================================ -->
+    <eat-comment />
+
+    <!-- Group of permissions that are related to system clock. -->
+    <permission-group android:name="android.permission-group.SYSTEM_CLOCK"
+        android:label="@string/permgrouplab_systemClock"
+        android:icon="@drawable/perm_group_system_clock"
+        android:description="@string/permgroupdesc_systemClock"
+        android:priority="140" />
+
+    <!-- Allows applications to set the system time -->
+    <permission android:name="android.permission.SET_TIME"
+        android:protectionLevel="signature|system"
+        android:label="@string/permlab_setTime"
+        android:description="@string/permdesc_setTime" />
+
+    <!-- Allows applications to set the system time zone -->
+    <permission android:name="android.permission.SET_TIME_ZONE"
+        android:permissionGroup="android.permission-group.SYSTEM_CLOCK"
+        android:protectionLevel="normal"
+        android:label="@string/permlab_setTimeZone"
+        android:description="@string/permdesc_setTimeZone" />
+
+    <!-- ==================================================== -->
+    <!-- Permissions related to changing status bar   -->
+    <!-- ==================================================== -->
+
+    <!-- Used for permissions that change the status bar -->
+    <permission-group android:name="android.permission-group.STATUS_BAR"
+        android:label="@string/permgrouplab_statusBar"
+        android:icon="@drawable/perm_group_status_bar"
+        android:description="@string/permgroupdesc_statusBar"
+        android:priority="110" />
+
+    <!-- Allows an application to expand or collapse the status bar. -->
+    <permission android:name="android.permission.EXPAND_STATUS_BAR"
+        android:permissionGroup="android.permission-group.STATUS_BAR"
+        android:protectionLevel="normal"
+        android:label="@string/permlab_expandStatusBar"
+        android:description="@string/permdesc_expandStatusBar" />
+
+    <!-- ==================================================== -->
+    <!-- Permissions related to accessing sync settings   -->
+    <!-- ==================================================== -->
+
+    <!-- Used for permissions that access the sync settings or sync
+         related information. -->
+    <permission-group android:name="android.permission-group.SYNC_SETTINGS"
+        android:label="@string/permgrouplab_syncSettings"
+        android:icon="@drawable/perm_group_sync_settings"
+        android:description="@string/permgroupdesc_syncSettings"
+        android:priority="120" />
+
+    <!-- Allows applications to read the sync settings -->
+    <permission android:name="android.permission.READ_SYNC_SETTINGS"
+        android:permissionGroup="android.permission-group.SYNC_SETTINGS"
+        android:protectionLevel="normal"
+        android:description="@string/permdesc_readSyncSettings"
+        android:label="@string/permlab_readSyncSettings" />
+
+    <!-- Allows applications to write the sync settings -->
+    <permission android:name="android.permission.WRITE_SYNC_SETTINGS"
+        android:permissionGroup="android.permission-group.SYNC_SETTINGS"
+        android:protectionLevel="normal"
+        android:description="@string/permdesc_writeSyncSettings"
+        android:label="@string/permlab_writeSyncSettings" />
+
+    <!-- Allows applications to read the sync stats -->
+    <permission android:name="android.permission.READ_SYNC_STATS"
+        android:permissionGroup="android.permission-group.SYNC_SETTINGS"
+        android:protectionLevel="normal"
+        android:description="@string/permdesc_readSyncStats"
+        android:label="@string/permlab_readSyncStats" />
+
+
     <!-- ============================================ -->
     <!-- Permissions for low-level system interaction -->
     <!-- ============================================ -->
@@ -724,12 +1263,36 @@
          such as writing the global system settings. -->
     <permission-group android:name="android.permission-group.SYSTEM_TOOLS"
         android:label="@string/permgrouplab_systemTools"
-        android:description="@string/permgroupdesc_systemTools" />
+        android:icon="@drawable/perm_group_system_tools"
+        android:description="@string/permgroupdesc_systemTools"
+        android:priority="100" />
+
+    <!-- @hide Change the screen compatibility mode of applications -->
+    <permission android:name="android.permission.SET_SCREEN_COMPATIBILITY"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature"
+        android:label="@string/permlab_setScreenCompatibility"
+        android:description="@string/permdesc_setScreenCompatibility" />
+
+    <!-- Allows an application to access all multi-user external storage @hide -->
+    <permission android:name="android.permission.ACCESS_ALL_EXTERNAL_STORAGE"
+        android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS"
+        android:label="@string/permlab_sdcardAccessAll"
+        android:description="@string/permdesc_sdcardAccessAll"
+        android:protectionLevel="signature" />
+
+    <!-- Allows an application to modify the current configuration, such
+         as locale. -->
+    <permission android:name="android.permission.CHANGE_CONFIGURATION"
+        android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS"
+        android:protectionLevel="signature|system|development"
+        android:label="@string/permlab_changeConfiguration"
+        android:description="@string/permdesc_changeConfiguration" />
 
     <!-- Allows an application to read or write the system settings. -->
     <permission android:name="android.permission.WRITE_SETTINGS"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
+        android:protectionLevel="normal"
         android:label="@string/permlab_writeSettings"
         android:description="@string/permdesc_writeSettings" />
 
@@ -739,52 +1302,6 @@
         android:label="@string/permlab_writeGservices"
         android:description="@string/permdesc_writeGservices" />
 
-    <!-- Allows an application to expand or collapse the status bar. -->
-    <permission android:name="android.permission.EXPAND_STATUS_BAR"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="normal"
-        android:label="@string/permlab_expandStatusBar"
-        android:description="@string/permdesc_expandStatusBar" />
-
-    <!-- Allows an application to get information about the currently
-         or recently running tasks. -->
-    <permission android:name="android.permission.GET_TASKS"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
-        android:label="@string/permlab_getTasks"
-        android:description="@string/permdesc_getTasks" />
-
-    <!-- Allows an application to get full detailed information about
-         recently running tasks, with full fidelity to the real state.
-         @hide -->
-    <permission android:name="android.permission.GET_DETAILED_TASKS"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="signature"
-        android:label="@string/permlab_getDetailedTasks"
-        android:description="@string/permdesc_getDetailedTasks" />
-
-    <!-- Allows an application to change the Z-order of tasks -->
-    <permission android:name="android.permission.REORDER_TASKS"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
-        android:label="@string/permlab_reorderTasks"
-        android:description="@string/permdesc_reorderTasks" />
-
-    <!-- @hide Allows an application to change to remove/kill tasks -->
-    <permission android:name="android.permission.REMOVE_TASKS"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="signature"
-        android:label="@string/permlab_removeTasks"
-        android:description="@string/permdesc_removeTasks" />
-
-    <!-- Allows an application to start any activity, regardless of permission
-         protection or exported state. @hide -->
-    <permission android:name="android.permission.START_ANY_ACTIVITY"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="signature"
-        android:label="@string/permlab_startAnyActivity"
-        android:description="@string/permdesc_startAnyActivity" />
-
     <!-- @hide Change the screen compatibility mode of applications -->
     <permission android:name="android.permission.SET_SCREEN_COMPATIBILITY"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
@@ -796,26 +1313,10 @@
          as locale. -->
     <permission android:name="android.permission.CHANGE_CONFIGURATION"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
+        android:protectionLevel="system|signature"
         android:label="@string/permlab_changeConfiguration"
         android:description="@string/permdesc_changeConfiguration" />
 
-    <!-- @deprecated The {@link android.app.ActivityManager#restartPackage}
-        API is no longer supported. -->
-    <permission android:name="android.permission.RESTART_PACKAGES"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="normal"
-        android:label="@string/permlab_killBackgroundProcesses"
-        android:description="@string/permdesc_killBackgroundProcesses" />
-
-    <!-- Allows an application to call
-        {@link android.app.ActivityManager#killBackgroundProcesses}. -->
-    <permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="normal"
-        android:label="@string/permlab_killBackgroundProcesses"
-        android:description="@string/permdesc_killBackgroundProcesses" />
-
     <!-- Allows an application to call
         {@link android.app.ActivityManager#forceStopPackage}.
         @hide -->
@@ -833,17 +1334,6 @@
         android:label="@string/permlab_retrieve_window_content"
         android:description="@string/permdesc_retrieve_window_content" />
 
-    <!-- Allows an application to open windows using the type
-         {@link android.view.WindowManager.LayoutParams#TYPE_SYSTEM_ALERT},
-         shown on top of all other applications.  Very few applications
-         should use this permission; these windows are intended for
-         system-level interaction with the user. -->
-    <permission android:name="android.permission.SYSTEM_ALERT_WINDOW"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
-        android:label="@string/permlab_systemAlertWindow"
-        android:description="@string/permdesc_systemAlertWindow" />
-
     <!-- Modify the global animation scaling factor. -->
     <permission android:name="android.permission.SET_ANIMATION_SCALE"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
@@ -854,8 +1344,8 @@
     <!-- @deprecated This functionality will be removed in the future; please do
          not use. Allow an application to make its activities persistent. -->
     <permission android:name="android.permission.PERSISTENT_ACTIVITY"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
+        android:permissionGroup="android.permission-group.APP_INFO"
+        android:protectionLevel="normal"
         android:label="@string/permlab_persistentActivity"
         android:description="@string/permdesc_persistentActivity" />
 
@@ -887,7 +1377,7 @@
          explicitly declare your use of this facility to make that visible
          to the user. -->
     <permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:permissionGroup="android.permission-group.APP_INFO"
         android:protectionLevel="normal"
         android:label="@string/permlab_receiveBootCompleted"
         android:description="@string/permdesc_receiveBootCompleted" />
@@ -902,52 +1392,17 @@
         android:label="@string/permlab_broadcastSticky"
         android:description="@string/permdesc_broadcastSticky" />
 
-    <!-- Allows using PowerManager WakeLocks to keep processor from sleeping or screen
-         from dimming -->
-    <permission android:name="android.permission.WAKE_LOCK"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
-        android:label="@string/permlab_wakeLock"
-        android:description="@string/permdesc_wakeLock" />
-
-    <!-- Allows applications to set the wallpaper -->
-    <permission android:name="android.permission.SET_WALLPAPER"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="normal"
-        android:label="@string/permlab_setWallpaper"
-        android:description="@string/permdesc_setWallpaper" />
-
-    <!-- Allows applications to set the wallpaper hints -->
-    <permission android:name="android.permission.SET_WALLPAPER_HINTS"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="normal"
-        android:label="@string/permlab_setWallpaperHints"
-        android:description="@string/permdesc_setWallpaperHints" />
-
-    <!-- Allows applications to set the system time -->
-    <permission android:name="android.permission.SET_TIME"
-        android:protectionLevel="signature|system"
-        android:label="@string/permlab_setTime"
-        android:description="@string/permdesc_setTime" />
-
-    <!-- Allows applications to set the system time zone -->
-    <permission android:name="android.permission.SET_TIME_ZONE"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
-        android:label="@string/permlab_setTimeZone"
-        android:description="@string/permdesc_setTimeZone" />
-
     <!-- Allows mounting and unmounting file systems for removable storage. -->
     <permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
+        android:protectionLevel="system|signature"
         android:label="@string/permlab_mount_unmount_filesystems"
         android:description="@string/permdesc_mount_unmount_filesystems" />
 
     <!-- Allows formatting file systems for removable storage. -->
     <permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
+        android:protectionLevel="system|signature"
         android:label="@string/permlab_mount_format_filesystems"
         android:description="@string/permdesc_mount_format_filesystems" />
 
@@ -991,34 +1446,6 @@
         android:label="@string/permlab_asec_rename"
         android:description="@string/permdesc_asec_rename" />
 
-    <!-- Allows applications to disable the keyguard -->
-    <permission android:name="android.permission.DISABLE_KEYGUARD"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
-        android:description="@string/permdesc_disableKeyguard"
-        android:label="@string/permlab_disableKeyguard" />
-
-    <!-- Allows applications to read the sync settings -->
-    <permission android:name="android.permission.READ_SYNC_SETTINGS"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="normal"
-        android:description="@string/permdesc_readSyncSettings"
-        android:label="@string/permlab_readSyncSettings" />
-
-    <!-- Allows applications to write the sync settings -->
-    <permission android:name="android.permission.WRITE_SYNC_SETTINGS"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
-        android:description="@string/permdesc_writeSyncSettings"
-        android:label="@string/permlab_writeSyncSettings" />
-
-    <!-- Allows applications to read the sync stats -->
-    <permission android:name="android.permission.READ_SYNC_STATS"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="normal"
-        android:description="@string/permdesc_readSyncStats"
-        android:label="@string/permlab_readSyncStats" />
-
     <!-- Allows applications to write the apn settings -->
     <permission android:name="android.permission.WRITE_APN_SETTINGS"
                 android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
@@ -1041,42 +1468,11 @@
 
     <!-- Allows applications to change network connectivity state -->
     <permission android:name="android.permission.CHANGE_NETWORK_STATE"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
+        android:permissionGroup="android.permission-group.NETWORK"
+        android:protectionLevel="normal"
         android:description="@string/permdesc_changeNetworkState"
         android:label="@string/permlab_changeNetworkState" />
 
-    <!-- Allows applications to change Wi-Fi connectivity state -->
-    <permission android:name="android.permission.CHANGE_WIFI_STATE"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
-        android:description="@string/permdesc_changeWifiState"
-        android:label="@string/permlab_changeWifiState" />
-
-
-    <!-- @hide -->
-    <permission android:name="android.permission.CHANGE_WIMAX_STATE"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
-        android:description="@string/permdesc_changeWimaxState"
-        android:label="@string/permlab_changeWimaxState" />
-
-
-
-    <!-- Allows applications to enter Wi-Fi Multicast mode -->
-    <permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
-        android:description="@string/permdesc_changeWifiMulticastState"
-        android:label="@string/permlab_changeWifiMulticastState" />
-
-    <!-- Allows applications to discover and pair bluetooth devices -->
-    <permission android:name="android.permission.BLUETOOTH_ADMIN"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
-        android:description="@string/permdesc_bluetoothAdmin"
-        android:label="@string/permlab_bluetoothAdmin" />
-
     <!-- Allows an application to clear the caches of all installed
          applications on the device.  -->
     <permission android:name="android.permission.CLEAR_APP_CACHE"
@@ -1103,7 +1499,8 @@
          purposes. -->
     <permission-group android:name="android.permission-group.DEVELOPMENT_TOOLS"
         android:label="@string/permgrouplab_developmentTools"
-        android:description="@string/permgroupdesc_developmentTools" />
+        android:description="@string/permgroupdesc_developmentTools"
+        android:priority="310" />
 
     <!-- Allows an application to read or write the secure system settings. -->
     <permission android:name="android.permission.WRITE_SECURE_SETTINGS"
@@ -1195,8 +1592,8 @@
     <!-- Allows an application to update device statistics. Not for
          use by third party apps. -->
     <permission android:name="android.permission.UPDATE_DEVICE_STATS"
-        android:label="@string/permlab_batteryStats"
-        android:description="@string/permdesc_batteryStats"
+        android:label="@string/permlab_updateBatteryStats"
+        android:description="@string/permdesc_updateBatteryStats"
         android:protectionLevel="signature|system" />
 
     <!-- Allows an application to open windows that are for use by parts
@@ -1214,6 +1611,13 @@
         android:description="@string/permdesc_manageAppTokens"
         android:protectionLevel="signature" />
 
+    <!-- @hide Allows the application to temporarily freeze the screen for a
+         full-screen transition. -->
+    <permission android:name="android.permission.FREEZE_SCREEN"
+        android:label="@string/permlab_freezeScreen"
+        android:description="@string/permdesc_freezeScreen"
+        android:protectionLevel="signature" />
+    
     <!-- Allows an application to inject user events (keys, touch, trackball)
          into the event stream and deliver them to ANY window.  Without this
          permission, you can only deliver events to windows in your own process.
@@ -1223,6 +1627,31 @@
         android:description="@string/permdesc_injectEvents"
         android:protectionLevel="signature" />
 
+    <!-- @hide Allows an application to register an input filter which filters the stream
+         of user events (keys, touch, trackball) before they are dispatched to any window. -->
+    <permission android:name="android.permission.FILTER_EVENTS"
+        android:label="@string/permlab_filter_events"
+        android:description="@string/permdesc_filter_events"
+        android:protectionLevel="signature" />
+
+    <!-- @hide Allows an application to retrieve info for a window from the window manager. -->
+    <permission android:name="android.permission.RETRIEVE_WINDOW_INFO"
+        android:label="@string/permlab_retrieve_window_info"
+        android:description="@string/permdesc_retrieve_window_info"
+        android:protectionLevel="signature" />
+
+    <!-- @hide Allows an application to temporary enable accessibility on the device. -->
+    <permission android:name="android.permission.TEMPORARY_ENABLE_ACCESSIBILITY"
+        android:label="@string/permlab_temporary_enable_accessibility"
+        android:description="@string/permdesc_temporary_enable_accessibility"
+        android:protectionLevel="signature" />
+
+    <!-- @hide Allows an application to magnify the content of a display. -->
+    <permission android:name="android.permission.MAGNIFY_DISPLAY"
+        android:label="@string/permlab_magnify_display"
+        android:description="@string/permdesc_magnify_display"
+        android:protectionLevel="signature" />
+
     <!-- Allows an application to watch and control how activities are
          started globally in the system.  Only for is in debugging
          (usually the monkey command). -->
@@ -1378,6 +1807,22 @@
         android:description="@string/permdesc_readFrameBuffer"
         android:protectionLevel="signature|system" />
 
+    <!-- Allows an application to configure and connect to Wifi displays
+         @hide -->
+    <permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY"
+        android:label="@string/permlab_configureWifiDisplay"
+        android:description="@string/permdesc_configureWifiDisplay"
+        android:protectionLevel="signature" />
+
+    <!-- Allows an application to control low-level features of Wifi displays
+         such as opening an RTSP socket.  This permission should only be used
+         by the display manager.
+         @hide -->
+    <permission android:name="android.permission.CONTROL_WIFI_DISPLAY"
+        android:label="@string/permlab_controlWifiDisplay"
+        android:description="@string/permdesc_controlWifiDisplay"
+        android:protectionLevel="signature" />
+
     <!-- Required to be able to disable the device (very dangerous!). -->
     <permission android:name="android.permission.BRICK"
         android:label="@string/permlab_brick"
@@ -1396,6 +1841,11 @@
         android:description="@string/permdesc_devicePower"
         android:protectionLevel="signature" />
 
+   <!-- @hide Allows low-level access to tun tap driver -->
+    <permission android:name="android.permission.NET_TUNNELING"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature" />
+
     <!-- Run as a manufacturer test application, running as the root user.
          Only available when the device is running in manufacturer test mode. -->
     <permission android:name="android.permission.FACTORY_TEST"
@@ -1467,9 +1917,10 @@
 
     <!-- Allows an application to collect battery statistics -->
     <permission android:name="android.permission.BATTERY_STATS"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
         android:label="@string/permlab_batteryStats"
         android:description="@string/permdesc_batteryStats"
-        android:protectionLevel="normal" />
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to control the backup and restore process
          @hide pending API council -->
@@ -1505,6 +1956,13 @@
         android:description="@string/permdesc_bindGadget"
         android:protectionLevel="signature|system" />
 
+    <!-- Private permission, to restrict who can bring up a dialog to add a new
+         keyguard widget
+         @hide -->
+    <permission android:name="android.permission.BIND_KEYGUARD_APPWIDGET"
+        android:permissionGroup="android.permission-group.PERSONAL_INFO"
+        android:protectionLevel="signature|system" />
+
     <!-- Internal permission allowing an application to query/set which
          applications can bind AppWidgets.
          @hide -->
@@ -1550,6 +2008,18 @@
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
         android:protectionLevel="signature|system" />
 
+    <!-- Allows applications to read dream settings and dream state.
+         @hide -->
+    <permission android:name="android.permission.READ_DREAM_STATE"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature" />
+
+    <!-- Allows applications to write dream settings, and start or stop dreaming.
+         @hide -->
+    <permission android:name="android.permission.WRITE_DREAM_STATE"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature" />
+
     <!-- Allow an application to read and write the cache partition.
          @hide -->
     <permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM"
@@ -1602,9 +2072,8 @@
           android:protectionLevel="signature" />
     <uses-permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"/>
 
-    <!-- Package verifier needs to have this permission before the PackageManager will
+    <!-- @hide Package verifier needs to have this permission before the PackageManager will
          trust it to verify packages.
-         @hide
     -->
     <permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT"
         android:label="@string/permlab_packageVerificationAgent"
@@ -1656,7 +2125,8 @@
                  android:allowClearUserData="false"
                  android:backupAgent="com.android.server.SystemBackupAgent"
                  android:killAfterRestore="false"
-                 android:icon="@drawable/ic_launcher_android">
+                 android:icon="@drawable/ic_launcher_android"
+                 android:supportsRtl="true">
         <activity android:name="com.android.internal.app.ChooserActivity"
                 android:theme="@style/Theme.Holo.Dialog.Alert"
                 android:finishOnCloseSystemDialogs="true"
@@ -1702,7 +2172,7 @@
 
         <activity android:name="android.accounts.ChooseAccountTypeActivity"
                 android:excludeFromRecents="true"
-                android:theme="@android:style/Theme.Holo.DialogWhenLarge.NoActionBar"
+                android:theme="@android:style/Theme.Holo.Dialog"
                 android:label="@string/choose_account_label"
                 android:process=":ui">
         </activity>
@@ -1739,12 +2209,25 @@
                 android:process=":ui">
         </activity>
 
-        <receiver android:name="com.android.server.BootReceiver" >
+        <receiver android:name="com.android.server.BootReceiver"
+                android:primaryUserOnly="true">
             <intent-filter>
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
             </intent-filter>
         </receiver>
 
+        <receiver android:name="com.android.server.updates.CertPinInstallReceiver" >
+            <intent-filter>
+                <action android:name="android.intent.action.UPDATE_PINS" />
+            </intent-filter>
+        </receiver>
+
+        <receiver android:name="com.android.server.updates.SmsShortCodesInstallReceiver" >
+            <intent-filter>
+                <action android:name="android.intent.action.UPDATE_SMS_SHORT_CODES" />
+            </intent-filter>
+        </receiver>
+
         <receiver android:name="com.android.server.MasterClearReceiver"
             android:permission="android.permission.MASTER_CLEAR"
             android:priority="100" >
diff --git a/core/res/res/anim/keyguard_action_assist_enter.xml b/core/res/res/anim/keyguard_action_assist_enter.xml
new file mode 100644
index 0000000..f3333b7
--- /dev/null
+++ b/core/res/res/anim/keyguard_action_assist_enter.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+        android:shareInterpolator="false" android:zAdjustment="top">
+
+    <alpha android:fromAlpha="0" android:toAlpha="1.0"
+            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+            android:interpolator="@android:interpolator/decelerate_cubic"
+            android:duration="300"/>
+
+    <translate android:fromYDelta="100%" android:toYDelta="0"
+            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+            android:interpolator="@android:interpolator/decelerate_cubic"
+            android:duration="300" />
+</set>
diff --git a/core/res/res/anim/keyguard_action_assist_exit.xml b/core/res/res/anim/keyguard_action_assist_exit.xml
new file mode 100644
index 0000000..b4ed278
--- /dev/null
+++ b/core/res/res/anim/keyguard_action_assist_exit.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<translate xmlns:android="http://schemas.android.com/apk/res/android"
+       android:interpolator="@android:anim/accelerate_interpolator"
+       android:fromXDelta="0" android:toXDelta="0"
+       android:duration="300" />
diff --git a/core/res/res/anim/keyguard_security_animate_in.xml b/core/res/res/anim/keyguard_security_animate_in.xml
new file mode 100644
index 0000000..4ee30c3
--- /dev/null
+++ b/core/res/res/anim/keyguard_security_animate_in.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">
+
+    <scale
+        android:interpolator="@android:anim/decelerate_interpolator"
+        android:fromXScale="0.0"
+        android:toXScale="1.0"
+        android:fromYScale="1.0"
+        android:toYScale="1.0"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillEnabled="true"
+        android:fillAfter="true"
+        android:duration="@integer/kg_security_flip_duration"
+        android:startOffset="@integer/kg_security_flip_duration" />
+
+</set>
+
diff --git a/core/res/res/anim/keyguard_security_animate_out.xml b/core/res/res/anim/keyguard_security_animate_out.xml
new file mode 100644
index 0000000..76d065c
--- /dev/null
+++ b/core/res/res/anim/keyguard_security_animate_out.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">
+
+    <scale
+        android:interpolator="@android:anim/accelerate_interpolator"
+        android:fromXScale="1.0"
+        android:toXScale="0.0"
+        android:fromYScale="1.0"
+        android:toYScale="1.0"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillEnabled="true"
+        android:fillAfter="true"
+        android:duration="@integer/kg_security_flip_duration" />
+
+</set>
+
diff --git a/core/res/res/anim/keyguard_security_fade_in.xml b/core/res/res/anim/keyguard_security_fade_in.xml
new file mode 100644
index 0000000..6293432
--- /dev/null
+++ b/core/res/res/anim/keyguard_security_fade_in.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:interpolator/decelerate_quad"
+    android:fromAlpha="0.0" android:toAlpha="1.0"
+    android:duration="@*android:integer/kg_security_fade_duration" />
+
+
diff --git a/core/res/res/anim/keyguard_security_fade_out.xml b/core/res/res/anim/keyguard_security_fade_out.xml
new file mode 100644
index 0000000..4ab0229
--- /dev/null
+++ b/core/res/res/anim/keyguard_security_fade_out.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:interpolator/accelerate_quad"
+    android:fromAlpha="1.0"
+    android:toAlpha="0.0"
+    android:duration="@*android:integer/kg_security_fade_duration"
+/>
diff --git a/core/res/res/anim/screen_user_enter.xml b/core/res/res/anim/screen_user_enter.xml
new file mode 100644
index 0000000..cb0a634
--- /dev/null
+++ b/core/res/res/anim/screen_user_enter.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 20012, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+            android:duration="500"
+            android:interpolator="@interpolator/decelerate_quad" />
+</set>
diff --git a/core/res/res/anim/screen_user_exit.xml b/core/res/res/anim/screen_user_exit.xml
new file mode 100644
index 0000000..3d465be
--- /dev/null
+++ b/core/res/res/anim/screen_user_exit.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 20012, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+            android:duration="500"
+            android:interpolator="@interpolator/decelerate_quad" />
+</set>
diff --git a/core/res/res/anim-port/task_close_enter.xml b/core/res/res/anim/task_close_enter.xml
similarity index 100%
rename from core/res/res/anim-port/task_close_enter.xml
rename to core/res/res/anim/task_close_enter.xml
diff --git a/core/res/res/anim-port/task_close_exit.xml b/core/res/res/anim/task_close_exit.xml
similarity index 100%
rename from core/res/res/anim-port/task_close_exit.xml
rename to core/res/res/anim/task_close_exit.xml
diff --git a/core/res/res/anim-port/task_open_enter.xml b/core/res/res/anim/task_open_enter.xml
similarity index 100%
rename from core/res/res/anim-port/task_open_enter.xml
rename to core/res/res/anim/task_open_enter.xml
diff --git a/core/res/res/anim-port/task_open_exit.xml b/core/res/res/anim/task_open_exit.xml
similarity index 100%
rename from core/res/res/anim-port/task_open_exit.xml
rename to core/res/res/anim/task_open_exit.xml
diff --git a/core/res/res/anim/wallpaper_enter.xml b/core/res/res/anim/wallpaper_enter.xml
index 2993a2d..eb826b8 100644
--- a/core/res/res/anim/wallpaper_enter.xml
+++ b/core/res/res/anim/wallpaper_enter.xml
@@ -19,10 +19,12 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@interpolator/decelerate_quad">
+    <!-- Having trouble avoiding this when switching users, so simple fade for now
     <scale android:fromXScale="3.0" android:toXScale="1.0"
            android:fromYScale="3.0" android:toYScale="1.0"
            android:pivotX="50%" android:pivotY="50%"
            android:duration="@android:integer/config_longAnimTime" />
+    -->
     <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
             android:duration="@android:integer/config_longAnimTime" />
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/wallpaper_exit.xml b/core/res/res/anim/wallpaper_exit.xml
index 5d5b38a..d675afb 100644
--- a/core/res/res/anim/wallpaper_exit.xml
+++ b/core/res/res/anim/wallpaper_exit.xml
@@ -19,10 +19,12 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@interpolator/accelerate_quad">
+    <!-- Having trouble avoiding this when switching users, so simple fade for now
     <scale android:fromXScale="1.0" android:toXScale="3.0"
            android:fromYScale="1.0" android:toYScale="3.0"
            android:pivotX="50%" android:pivotY="50%"
            android:duration="@android:integer/config_longAnimTime" />
+    -->
     <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
             android:duration="@android:integer/config_longAnimTime"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
index 13ab8f7..3b64f47 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
index 13ab8f7..3b64f47 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
index 1d76bb5..0437c31 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
index 8ebd761..6a2a92c 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
index 8ebd761..6a2a92c 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
index b405d81..882ed61 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
index fee599a..b9266a6 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
index fee599a..b9266a6 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
index dddfc26..dbcede7 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
index ab40fa7..42fc83c 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
index 8077921..42fc83c 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
index 0d8f8ba..958d023 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
index baf7018..3464f3d 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
index baf7018..3464f3d 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
index 7a24c9b..17acfc5 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_light.9.png
index 7a24c9b..17acfc5 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_dark.9.png
index 93c6d1b..9b8ca22 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_light.9.png
index 93c6d1b..9b8ca22 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_dark.9.png
index 120f963..bc20f6c 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_light.9.png
index 120f963..bc20f6c 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_dark.9.png
index 6b106fb..571819b 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_light.9.png
index 6b106fb..571819b 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_dark.9.png
index a1b7003..677069a 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_light.9.png
index a1b7003..677069a 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
index 7176a6b..1f83b5a 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_light.9.png
index 7176a6b..1f83b5a 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_dark.9.png
index 7fba6a5..733cf45 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_light.9.png
index 7fba6a5..733cf45 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_dark.9.png
index 8bbfe9f..2265de4 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_light.9.png
index 8bbfe9f..2265de4 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_dark.9.png
index 28f0ee6..f3ada58 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_light.9.png
index 28f0ee6..f3ada58 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_dark.9.png
index c4c41a3..6b5fa5a 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_light.9.png
index c4c41a3..6b5fa5a 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
index 256067d..9eaf9d5 100644
--- a/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
index 2338175..55a125e 100644
--- a/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
index 79e56f5..13205f0 100644
--- a/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
index e029f21..6f5dcc1 100644
--- a/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
index 8ee0072..be3f7a1 100644
--- a/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
index df030c1..2e92a6d 100644
--- a/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
index 50534a1..0e5444b 100644
--- a/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
index 0b84155..32ca205 100644
--- a/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_coins_s.png b/core/res/res/drawable-hdpi/ic_coins_s.png
new file mode 100644
index 0000000..0ada1d0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_coins_s.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_alarm.png b/core/res/res/drawable-hdpi/ic_lockscreen_alarm.png
new file mode 100644
index 0000000..d7a8cfc
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png
deleted file mode 100644
index bc718b5..0000000
--- a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_left.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_left.png
deleted file mode 100644
index 0892c31..0000000
--- a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_left.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_right.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_right.png
deleted file mode 100644
index 04cc0a2..0000000
--- a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_right.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png
deleted file mode 100644
index bb553b1..0000000
--- a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_sim.png b/core/res/res/drawable-hdpi/ic_lockscreen_sim.png
new file mode 100644
index 0000000..7cf9e36
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_sim.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_dark.png
new file mode 100644
index 0000000..10fc8da
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_light.png
new file mode 100644
index 0000000..a0e5060
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_dark.png
new file mode 100644
index 0000000..8364a36
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_light.png
new file mode 100644
index 0000000..44b89e1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_dark.png
new file mode 100644
index 0000000..770bf78
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_light.png
new file mode 100644
index 0000000..2a2467b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-hdpi/ic_notify_wifidisplay.png
new file mode 100644
index 0000000..35f27df
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_notify_wifidisplay.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_suggestions_add.png b/core/res/res/drawable-hdpi/ic_suggestions_add.png
deleted file mode 100644
index 919872c..0000000
--- a/core/res/res/drawable-hdpi/ic_suggestions_add.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_suggestions_delete.png b/core/res/res/drawable-hdpi/ic_suggestions_delete.png
deleted file mode 100644
index fa42db0..0000000
--- a/core/res/res/drawable-hdpi/ic_suggestions_delete.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/kg_add_widget.png b/core/res/res/drawable-hdpi/kg_add_widget.png
new file mode 100644
index 0000000..723d97a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/kg_add_widget.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/kg_bouncer_bg_white.9.png b/core/res/res/drawable-hdpi/kg_bouncer_bg_white.9.png
new file mode 100644
index 0000000..cfd5db3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/kg_bouncer_bg_white.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/kg_security_grip.9.png b/core/res/res/drawable-hdpi/kg_security_grip.9.png
new file mode 100644
index 0000000..1e40aef
--- /dev/null
+++ b/core/res/res/drawable-hdpi/kg_security_grip.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/kg_security_lock.png b/core/res/res/drawable-hdpi/kg_security_lock.png
new file mode 100644
index 0000000..c3c94c4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/kg_security_lock.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/kg_security_lock_focused.png b/core/res/res/drawable-hdpi/kg_security_lock_focused.png
new file mode 100644
index 0000000..abcf683
--- /dev/null
+++ b/core/res/res/drawable-hdpi/kg_security_lock_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/kg_security_lock_normal.png b/core/res/res/drawable-hdpi/kg_security_lock_normal.png
new file mode 100644
index 0000000..e8cff24
--- /dev/null
+++ b/core/res/res/drawable-hdpi/kg_security_lock_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/kg_security_lock_pressed.png b/core/res/res/drawable-hdpi/kg_security_lock_pressed.png
new file mode 100644
index 0000000..3214dcb
--- /dev/null
+++ b/core/res/res/drawable-hdpi/kg_security_lock_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/kg_widget_bg_padded.9.png b/core/res/res/drawable-hdpi/kg_widget_bg_padded.9.png
new file mode 100644
index 0000000..dff1dfa
--- /dev/null
+++ b/core/res/res/drawable-hdpi/kg_widget_bg_padded.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/kg_widget_delete_drop_target.png b/core/res/res/drawable-hdpi/kg_widget_delete_drop_target.png
new file mode 100644
index 0000000..84549ff
--- /dev/null
+++ b/core/res/res/drawable-hdpi/kg_widget_delete_drop_target.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/lockscreen_protection_pattern.png b/core/res/res/drawable-hdpi/lockscreen_protection_pattern.png
new file mode 100644
index 0000000..681d8be
--- /dev/null
+++ b/core/res/res/drawable-hdpi/lockscreen_protection_pattern.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/magnified_region_frame.9.png b/core/res/res/drawable-hdpi/magnified_region_frame.9.png
new file mode 100644
index 0000000..29bdc42
--- /dev/null
+++ b/core/res/res/drawable-hdpi/magnified_region_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
index 4d3d208..e83b346 100644
--- a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
index 924a99d..fd4fbf8 100644
--- a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_dark.9.png b/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_dark.9.png
index 53871a05..8aee55a 100644
--- a/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_light.9.png b/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_light.9.png
index e3a0313..2ebb7a2 100644
--- a/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/panel_bg_holo_dark.9.png b/core/res/res/drawable-hdpi/panel_bg_holo_dark.9.png
index 1b4fed8..a5ac279 100644
--- a/core/res/res/drawable-hdpi/panel_bg_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/panel_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/panel_bg_holo_light.9.png b/core/res/res/drawable-hdpi/panel_bg_holo_light.9.png
index c8b3177..583865e 100644
--- a/core/res/res/drawable-hdpi/panel_bg_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/panel_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_default_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_ab_default_holo_dark.9.png
index eb28ff9..88f8765 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_default_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_ab_default_holo_light.9.png
index d281adb..fa68a13 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_dark.9.png
index b298586..78c63cb 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_light.9.png
index 4215396..e13a9f80 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_ab_focused_holo_dark.9.png
index a280eab..26d2e16 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_focused_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_ab_focused_holo_light.9.png
index f8d619b..00ae92a 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark.9.png
index 955a2f3..dc20a8d 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light.9.png
index 6c22e22..272a2a1 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_default_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_default_holo_dark.9.png
index 34a88df..78e583c 100644
--- a/core/res/res/drawable-hdpi/spinner_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_default_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_default_holo_light.9.png
index b03842d..fb54f22 100644
--- a/core/res/res/drawable-hdpi/spinner_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_disabled_holo_dark.9.png
index 2d306d9..210832c 100644
--- a/core/res/res/drawable-hdpi/spinner_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_disabled_holo_light.9.png
index 720c417..d0d9419 100644
--- a/core/res/res/drawable-hdpi/spinner_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_focused_holo_dark.9.png
index b038fba..be365ec 100644
--- a/core/res/res/drawable-hdpi/spinner_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_focused_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_focused_holo_light.9.png
index ccffda9..cd7b803 100644
--- a/core/res/res/drawable-hdpi/spinner_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_pressed_holo_dark.9.png
index f638d5e..84560c5 100644
--- a/core/res/res/drawable-hdpi/spinner_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_pressed_holo_light.9.png
index 0aedd25..e101d50 100644
--- a/core/res/res/drawable-hdpi/spinner_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_rssi_in_range.png b/core/res/res/drawable-hdpi/stat_notify_rssi_in_range.png
new file mode 100644
index 0000000..74977e6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_notify_rssi_in_range.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_delete.png b/core/res/res/drawable-hdpi/sym_keyboard_delete.png
old mode 100755
new mode 100644
index 59d78be..476d902
--- a/core/res/res/drawable-hdpi/sym_keyboard_delete.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_delete.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_enter.png b/core/res/res/drawable-hdpi/sym_keyboard_enter.png
new file mode 100644
index 0000000..d118af2
--- /dev/null
+++ b/core/res/res/drawable-hdpi/sym_keyboard_enter.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num0_no_plus.png b/core/res/res/drawable-hdpi/sym_keyboard_num0_no_plus.png
index 0e5f1e2..ad81bb3 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_num0_no_plus.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num0_no_plus.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num1.png b/core/res/res/drawable-hdpi/sym_keyboard_num1.png
old mode 100755
new mode 100644
index 0fc03ef..8d2468c
--- a/core/res/res/drawable-hdpi/sym_keyboard_num1.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num2.png b/core/res/res/drawable-hdpi/sym_keyboard_num2.png
old mode 100755
new mode 100644
index 283560b..cfa972b
--- a/core/res/res/drawable-hdpi/sym_keyboard_num2.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num3.png b/core/res/res/drawable-hdpi/sym_keyboard_num3.png
old mode 100755
new mode 100644
index 9a3b329..141833a
--- a/core/res/res/drawable-hdpi/sym_keyboard_num3.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num4.png b/core/res/res/drawable-hdpi/sym_keyboard_num4.png
old mode 100755
new mode 100644
index f13ff1a..07df14d
--- a/core/res/res/drawable-hdpi/sym_keyboard_num4.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num4.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num5.png b/core/res/res/drawable-hdpi/sym_keyboard_num5.png
old mode 100755
new mode 100644
index c251329..fbcc9bf
--- a/core/res/res/drawable-hdpi/sym_keyboard_num5.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num5.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num6.png b/core/res/res/drawable-hdpi/sym_keyboard_num6.png
old mode 100755
new mode 100644
index 4acba4c..9513b33
--- a/core/res/res/drawable-hdpi/sym_keyboard_num6.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num6.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num7.png b/core/res/res/drawable-hdpi/sym_keyboard_num7.png
old mode 100755
new mode 100644
index 14931c1..5ad25d8
--- a/core/res/res/drawable-hdpi/sym_keyboard_num7.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num7.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num8.png b/core/res/res/drawable-hdpi/sym_keyboard_num8.png
old mode 100755
new mode 100644
index d4973fd..97d5c0e
--- a/core/res/res/drawable-hdpi/sym_keyboard_num8.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num8.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num9.png b/core/res/res/drawable-hdpi/sym_keyboard_num9.png
old mode 100755
new mode 100644
index 49cec66..a7d6a83
--- a/core/res/res/drawable-hdpi/sym_keyboard_num9.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_return_holo.png b/core/res/res/drawable-hdpi/sym_keyboard_return_holo.png
new file mode 100644
index 0000000..f1bcf48
--- /dev/null
+++ b/core/res/res/drawable-hdpi/sym_keyboard_return_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_activated_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_activated_holo_dark.9.png
index 56481ce..b7c5dcd 100644
--- a/core/res/res/drawable-hdpi/textfield_activated_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_activated_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_activated_holo_light.9.png
index 56481ce..1aaa9ae 100644
--- a/core/res/res/drawable-hdpi/textfield_activated_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_default_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_default_holo_dark.9.png
index d15f9a6..e6ef296 100644
--- a/core/res/res/drawable-hdpi/textfield_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_default_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_default_holo_light.9.png
index 073f91e..7368261 100644
--- a/core/res/res/drawable-hdpi/textfield_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_disabled_focused_holo_dark.9.png
index fe75315..29e33e3 100644
--- a/core/res/res/drawable-hdpi/textfield_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_disabled_focused_holo_light.9.png
index d7f78ab..b70db4e 100644
--- a/core/res/res/drawable-hdpi/textfield_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_disabled_holo_dark.9.png
index 769bc0a..73ec37c 100644
--- a/core/res/res/drawable-hdpi/textfield_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_disabled_holo_light.9.png
index 312a0f4..a77d66d 100644
--- a/core/res/res/drawable-hdpi/textfield_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_activated_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_multiline_activated_holo_dark.9.png
index 56481ce..3141caf 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_activated_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_activated_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_multiline_activated_holo_light.9.png
index 56481ce..df7f7708 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_activated_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_default_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_multiline_default_holo_dark.9.png
index e27b409b..ab381a6 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_default_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_multiline_default_holo_light.9.png
index 073f91e..ed1306c 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_multiline_disabled_focused_holo_dark.9.png
index f33763b..269e6b3 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_multiline_disabled_focused_holo_light.9.png
index d7f78ab..e0a83fe 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_multiline_disabled_holo_dark.9.png
index 2e50f72..9f14a06 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_multiline_disabled_holo_light.9.png
index 312a0f4..c458698 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_multiline_focused_holo_dark.9.png
index 6784032..180d85c 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_focused_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_multiline_focused_holo_light.9.png
index 74746cb..e075149 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/ic_ab_back_holo_dark.png b/core/res/res/drawable-ldrtl-hdpi/ic_ab_back_holo_dark.png
new file mode 100644
index 0000000..9beeb0f
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/ic_ab_back_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/ic_ab_back_holo_light.png b/core/res/res/drawable-ldrtl-hdpi/ic_ab_back_holo_light.png
new file mode 100644
index 0000000..844e38b
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/ic_ab_back_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/ic_ab_back_holo_dark.png b/core/res/res/drawable-ldrtl-mdpi/ic_ab_back_holo_dark.png
new file mode 100644
index 0000000..c22dc90
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/ic_ab_back_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/ic_ab_back_holo_light.png b/core/res/res/drawable-ldrtl-mdpi/ic_ab_back_holo_light.png
new file mode 100644
index 0000000..f49b715
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/ic_ab_back_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/ic_ab_back_holo_dark.png b/core/res/res/drawable-ldrtl-xhdpi/ic_ab_back_holo_dark.png
new file mode 100644
index 0000000..8dfb7d8
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/ic_ab_back_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/ic_ab_back_holo_light.png b/core/res/res/drawable-ldrtl-xhdpi/ic_ab_back_holo_light.png
new file mode 100644
index 0000000..29852ad
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/ic_ab_back_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
index 38d00db..87933fa 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
index 38d00db..87933fa 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
index 85c2c4f..77f6492 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
index 4a6351a..d424a0e 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
index 4a6351a..d424a0e 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
index 89d7a0e..683f128 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
index 39950f6..0763868 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
index 39950f6..0763868 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
index 0895d57..0e0da34 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
index 54c6354..accc761 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
index 50070ed..accc761 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
index 6a1b6a1..eb7a1fd 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
index 13a1fdd..7e4eb5e 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
index 13a1fdd..7e4eb5e 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
index 88da06e..3fdd3bc 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_light.9.png
index 88da06e..3fdd3bc 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_dark.9.png
index ae2c2c4..eaa02b3 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_light.9.png
index ae2c2c4..eaa02b3 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_dark.9.png
index db0f9ab..28c8b94 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_light.9.png
index db0f9ab..28c8b94 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_dark.9.png
index 7abaf3e..6090cce 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_light.9.png
index 7abaf3e..6090cce 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_dark.9.png
index 354fd0e..045dc9a 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_light.9.png
index 354fd0e..045dc9a 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
index d311c80..3f2e982 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_light.9.png
index d311c80..3f2e982 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_dark.9.png
index d0fd585..14b958b 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_light.9.png
index d0fd585..14b958b 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_dark.9.png
index e27b3de..4db22d4 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_light.9.png
index e27b3de..4db22d4 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_dark.9.png
index cbed62f..a11e1c7 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_light.9.png
index cbed62f..a11e1c7 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_dark.9.png
index 16fa332..6c4aa16 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_light.9.png
index 16fa332..6c4aa16 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
index 611d538..f874d66 100644
--- a/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
index cf2f01b..0d6c715 100644
--- a/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
index fb3660e..63144ae 100644
--- a/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
index f18050e..953ba78 100644
--- a/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
index b620341..0c57ffc 100644
--- a/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
index 4035428..c6be52e 100644
--- a/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
index 4d99748..7e9f258 100644
--- a/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
index 6f5f149..11cc5a4 100644
--- a/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_coins_s.png b/core/res/res/drawable-mdpi/ic_coins_s.png
new file mode 100644
index 0000000..3b8fd8a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_coins_s.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_alarm.png b/core/res/res/drawable-mdpi/ic_lockscreen_alarm.png
new file mode 100644
index 0000000..330ade1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png
deleted file mode 100644
index 308fe8a..0000000
--- a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_left.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_left.png
deleted file mode 100644
index 9a25634..0000000
--- a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_left.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_right.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_right.png
deleted file mode 100644
index 77240d0..0000000
--- a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_right.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png
deleted file mode 100644
index e0b0134..0000000
--- a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_sim.png b/core/res/res/drawable-mdpi/ic_lockscreen_sim.png
new file mode 100644
index 0000000..2e259c3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_sim.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_dark.png
new file mode 100644
index 0000000..fb2ac25
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_light.png
new file mode 100644
index 0000000..0c20091
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_dark.png
new file mode 100644
index 0000000..2f70cee
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_light.png
new file mode 100644
index 0000000..0b76d8e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_dark.png
new file mode 100644
index 0000000..ae7b105
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_light.png
new file mode 100644
index 0000000..8d37b99
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-mdpi/ic_notify_wifidisplay.png
new file mode 100644
index 0000000..f9c8678
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_notify_wifidisplay.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_suggestions_add.png b/core/res/res/drawable-mdpi/ic_suggestions_add.png
deleted file mode 100644
index e98bdf8..0000000
--- a/core/res/res/drawable-mdpi/ic_suggestions_add.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_suggestions_delete.png b/core/res/res/drawable-mdpi/ic_suggestions_delete.png
deleted file mode 100644
index 78e6ec1..0000000
--- a/core/res/res/drawable-mdpi/ic_suggestions_delete.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_add_widget.png b/core/res/res/drawable-mdpi/kg_add_widget.png
new file mode 100644
index 0000000..5b0a5a4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/kg_add_widget.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_bouncer_bg_white.9.png b/core/res/res/drawable-mdpi/kg_bouncer_bg_white.9.png
new file mode 100644
index 0000000..e3cb6db
--- /dev/null
+++ b/core/res/res/drawable-mdpi/kg_bouncer_bg_white.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_security_grip.9.png b/core/res/res/drawable-mdpi/kg_security_grip.9.png
new file mode 100644
index 0000000..334a39b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/kg_security_grip.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_security_lock.png b/core/res/res/drawable-mdpi/kg_security_lock.png
new file mode 100644
index 0000000..a39f380
--- /dev/null
+++ b/core/res/res/drawable-mdpi/kg_security_lock.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_security_lock_focused.png b/core/res/res/drawable-mdpi/kg_security_lock_focused.png
new file mode 100644
index 0000000..c567a82
--- /dev/null
+++ b/core/res/res/drawable-mdpi/kg_security_lock_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_security_lock_normal.png b/core/res/res/drawable-mdpi/kg_security_lock_normal.png
new file mode 100644
index 0000000..6fbecc1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/kg_security_lock_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_security_lock_pressed.png b/core/res/res/drawable-mdpi/kg_security_lock_pressed.png
new file mode 100644
index 0000000..a883258
--- /dev/null
+++ b/core/res/res/drawable-mdpi/kg_security_lock_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_widget_bg_padded.9.png b/core/res/res/drawable-mdpi/kg_widget_bg_padded.9.png
new file mode 100644
index 0000000..c313df1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/kg_widget_bg_padded.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_widget_delete_drop_target.png b/core/res/res/drawable-mdpi/kg_widget_delete_drop_target.png
new file mode 100644
index 0000000..219f3e5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/kg_widget_delete_drop_target.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/lockscreen_protection_pattern.png b/core/res/res/drawable-mdpi/lockscreen_protection_pattern.png
new file mode 100644
index 0000000..30bcea5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/lockscreen_protection_pattern.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/magnified_region_frame.9.png b/core/res/res/drawable-mdpi/magnified_region_frame.9.png
new file mode 100644
index 0000000..a61cbea
--- /dev/null
+++ b/core/res/res/drawable-mdpi/magnified_region_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
index 460ec46..9583c9b 100644
--- a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
index e84adf2..54d2cd0 100644
--- a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_dark.9.png b/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_dark.9.png
index 9d80b77..ce48b33 100644
--- a/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_light.9.png b/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_light.9.png
index efa4325..1f313af 100644
--- a/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/panel_bg_holo_dark.9.png b/core/res/res/drawable-mdpi/panel_bg_holo_dark.9.png
index 8c51b01..588eb3c 100644
--- a/core/res/res/drawable-mdpi/panel_bg_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/panel_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/panel_bg_holo_light.9.png b/core/res/res/drawable-mdpi/panel_bg_holo_light.9.png
index f4a25bc..c1cdbc7 100644
--- a/core/res/res/drawable-mdpi/panel_bg_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/panel_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_default_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_ab_default_holo_dark.9.png
index 29aff4d4..8d75946 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_default_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_ab_default_holo_light.9.png
index 4055f70..716560b 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_dark.9.png
index ea4ee04..c3ba89c 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_light.9.png
index f74c02b..67c5358 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_ab_focused_holo_dark.9.png
index 09a2992..c015f43 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_focused_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_ab_focused_holo_light.9.png
index 6536ee6..487edc2 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark.9.png
index 202b5b7..2fa15e7 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light.9.png
index 6de0ba88..a964b22 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_default_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_default_holo_dark.9.png
index 48af192..5ac84dd 100644
--- a/core/res/res/drawable-mdpi/spinner_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_default_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_default_holo_light.9.png
index b3180cb..3eeebc4 100644
--- a/core/res/res/drawable-mdpi/spinner_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_disabled_holo_dark.9.png
index 22eddd8..2734f20 100644
--- a/core/res/res/drawable-mdpi/spinner_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_disabled_holo_light.9.png
index dad0ec9a..a78d6c0 100644
--- a/core/res/res/drawable-mdpi/spinner_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_focused_holo_dark.9.png
index 2cdd273..7d91915 100644
--- a/core/res/res/drawable-mdpi/spinner_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_focused_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_focused_holo_light.9.png
index f605db8..d7c4b87 100644
--- a/core/res/res/drawable-mdpi/spinner_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_pressed_holo_dark.9.png
index a699924..b82d1ac 100644
--- a/core/res/res/drawable-mdpi/spinner_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_pressed_holo_light.9.png
index f3c12d7..f9b5f64 100644
--- a/core/res/res/drawable-mdpi/spinner_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_rssi_in_range.png b/core/res/res/drawable-mdpi/stat_notify_rssi_in_range.png
new file mode 100644
index 0000000..62e4fe9
--- /dev/null
+++ b/core/res/res/drawable-mdpi/stat_notify_rssi_in_range.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_delete.png b/core/res/res/drawable-mdpi/sym_keyboard_delete.png
index 43a033ea..74b836a 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_delete.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_delete.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_enter.png b/core/res/res/drawable-mdpi/sym_keyboard_enter.png
new file mode 100644
index 0000000..0fa53ac
--- /dev/null
+++ b/core/res/res/drawable-mdpi/sym_keyboard_enter.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num0_no_plus.png b/core/res/res/drawable-mdpi/sym_keyboard_num0_no_plus.png
index d23114d..9fefaea 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num0_no_plus.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num0_no_plus.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num1.png b/core/res/res/drawable-mdpi/sym_keyboard_num1.png
index aaac11b..1f37e32 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num1.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num2.png b/core/res/res/drawable-mdpi/sym_keyboard_num2.png
index 4372eb8..f899f78 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num2.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num3.png b/core/res/res/drawable-mdpi/sym_keyboard_num3.png
index 6f54c85..6a0f5ef 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num3.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num3.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num4.png b/core/res/res/drawable-mdpi/sym_keyboard_num4.png
index 3e50bb9..3a25bcd 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num4.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num4.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num5.png b/core/res/res/drawable-mdpi/sym_keyboard_num5.png
index c39ef44..064d4bf 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num5.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num5.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num6.png b/core/res/res/drawable-mdpi/sym_keyboard_num6.png
index ea88ceb..61ee0a6 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num6.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num6.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num7.png b/core/res/res/drawable-mdpi/sym_keyboard_num7.png
index ce800ba..b931d7b 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num7.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num7.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num8.png b/core/res/res/drawable-mdpi/sym_keyboard_num8.png
index 1a8ff94..f8d2891 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num8.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num8.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num9.png b/core/res/res/drawable-mdpi/sym_keyboard_num9.png
index 8b344c0..056d067 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num9.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_return_holo.png b/core/res/res/drawable-mdpi/sym_keyboard_return_holo.png
new file mode 100644
index 0000000..d5a7708
--- /dev/null
+++ b/core/res/res/drawable-mdpi/sym_keyboard_return_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_activated_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_activated_holo_dark.9.png
index b69c3f0..33f798d 100644
--- a/core/res/res/drawable-mdpi/textfield_activated_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_activated_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_activated_holo_light.9.png
index b69c3f0..622c684 100644
--- a/core/res/res/drawable-mdpi/textfield_activated_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_default_holo_dark.9.png
index 6b4bba0..82fea5e 100644
--- a/core/res/res/drawable-mdpi/textfield_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_default_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_default_holo_light.9.png
index 3d8898e..c780d7d 100644
--- a/core/res/res/drawable-mdpi/textfield_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_disabled_focused_holo_dark.9.png
index e922f71..24bdf71 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_disabled_focused_holo_light.9.png
index 3b92894..0d5ea83 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_disabled_holo_dark.9.png
index 7e44919..709f5ef 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_disabled_holo_light.9.png
index 09b5616..ea6d2f7 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_focused_holo_dark.9.png
index efbaef8..2d8dd23 100644
--- a/core/res/res/drawable-mdpi/textfield_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_focused_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_focused_holo_light.9.png
index efbaef8..2d8dd23 100644
--- a/core/res/res/drawable-mdpi/textfield_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_activated_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_multiline_activated_holo_dark.9.png
index b69c3f0..371d6e9 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_activated_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_activated_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_multiline_activated_holo_light.9.png
index b69c3f0..225317f 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_activated_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_multiline_default_holo_dark.9.png
index 6b4bba0..4bd6f9f 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_default_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_multiline_default_holo_light.9.png
index 3d8898e..4b837b0 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_multiline_disabled_focused_holo_dark.9.png
index e922f71..51cf919 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_multiline_disabled_focused_holo_light.9.png
index 3b92894..af8d7e1 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_multiline_disabled_holo_dark.9.png
index 7e44919..d0fb869 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_multiline_disabled_holo_light.9.png
index 09b5616..a0e233e 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_multiline_focused_holo_dark.9.png
index 2a78e8c..2ed4985 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_focused_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_multiline_focused_holo_light.9.png
index 632d9fc..0603348 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/background_holo_dark.png b/core/res/res/drawable-nodpi/background_holo_dark.png
deleted file mode 100644
index 85bd6f7..0000000
--- a/core/res/res/drawable-nodpi/background_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-nodpi/background_holo_light.png b/core/res/res/drawable-nodpi/background_holo_light.png
deleted file mode 100644
index 5fb4a9d..0000000
--- a/core/res/res/drawable-nodpi/background_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-hdpi/sym_keyboard_return_holo.png b/core/res/res/drawable-sw600dp-hdpi/sym_keyboard_return_holo.png
new file mode 100644
index 0000000..f1bcf48
--- /dev/null
+++ b/core/res/res/drawable-sw600dp-hdpi/sym_keyboard_return_holo.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-mdpi/sym_keyboard_return_holo.png b/core/res/res/drawable-sw600dp-mdpi/sym_keyboard_return_holo.png
new file mode 100644
index 0000000..d5a7708
--- /dev/null
+++ b/core/res/res/drawable-sw600dp-mdpi/sym_keyboard_return_holo.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-xhdpi/sym_keyboard_return_holo.png b/core/res/res/drawable-sw600dp-xhdpi/sym_keyboard_return_holo.png
new file mode 100644
index 0000000..55174e0
--- /dev/null
+++ b/core/res/res/drawable-sw600dp-xhdpi/sym_keyboard_return_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png
index b7707c6f..d591bf8 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png
index b7707c6f..d591bf8 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
index 2ed6386..df2a621 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png
index ffee5e2..b410d23 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png
index ffee5e2..b410d23 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
index 702ebc6..392cee4 100644
--- a/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png
index 30bfa30..aed57c6 100644
--- a/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png
index 30bfa30..aed57c6 100644
--- a/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
index 89ce2df..92a49db 100644
--- a/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png
index 745d53e..38f8c01 100644
--- a/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png
index c509934..38f8c01 100644
--- a/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
index b1eab79..a0d64a3 100644
--- a/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png
index 417152b..930b5f2 100644
--- a/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png
index 417152b..930b5f2 100644
--- a/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
index c271216..c08deab 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_light.9.png
index c271216..c08deab 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_dark.9.png
index a2d3ecd..8b1a55c 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_light.9.png
index a2d3ecd..8b1a55c 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_dark.9.png
index 80cbb05..77cd1fa 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_light.9.png
index 80cbb05..77cd1fa 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_dark.9.png
index db2cfc5..e0e3540 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_light.9.png
index db2cfc5..e0e3540 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_dark.9.png
index 5086f46..9d16f32 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_light.9.png
index 5086f46..9d16f32 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
index 0f5851b..324e490 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_light.9.png
index 0f5851b..324e490 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_dark.9.png
index 74c853f..e126cc6 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_light.9.png
index 74c853f..e126cc6 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_dark.9.png
index 7bd7af5..4c1f1b9 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_light.9.png
index 7bd7af5..4c1f1b9 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_dark.9.png
index 71dad92..219d37b 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_light.9.png
index 71dad92..219d37b 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_dark.9.png
index 1f62eff..fde3ac3 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_light.9.png
index 1f62eff..fde3ac3 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/default_wallpaper.jpg b/core/res/res/drawable-xhdpi/default_wallpaper.jpg
index 5b8d1d5..da9fa91 100644
--- a/core/res/res/drawable-xhdpi/default_wallpaper.jpg
+++ b/core/res/res/drawable-xhdpi/default_wallpaper.jpg
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png
index 94bb8e1..467ea1f 100644
--- a/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png
index ef58e29..74929a3 100644
--- a/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png
index f4970ad..a8ab305 100644
--- a/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png
index 172fc3b..a8f02d66 100644
--- a/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png
index 2bab67a..97eb217 100644
--- a/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png
index 6b5f467..1300c19 100644
--- a/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png
index e1c602f..f82e26b 100644
--- a/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png
index 59db99c..8bd32a3 100644
--- a/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_coins_s.png b/core/res/res/drawable-xhdpi/ic_coins_s.png
new file mode 100644
index 0000000..13d134e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_coins_s.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_alarm.png b/core/res/res/drawable-xhdpi/ic_lockscreen_alarm.png
new file mode 100644
index 0000000..e6cceef
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png
deleted file mode 100644
index b8e5733..0000000
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_left.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_left.png
deleted file mode 100644
index ce5da43..0000000
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_left.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_right.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_right.png
deleted file mode 100644
index c16f143..0000000
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_right.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png
deleted file mode 100644
index 9bed39a..0000000
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_sim.png b/core/res/res/drawable-xhdpi/ic_lockscreen_sim.png
new file mode 100644
index 0000000..f4de96a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_sim.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_dark.png
new file mode 100644
index 0000000..483b612
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_light.png
new file mode 100644
index 0000000..c3507dc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_dark.png
new file mode 100644
index 0000000..24c6519
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_light.png
new file mode 100644
index 0000000..2be0380
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_dark.png
new file mode 100644
index 0000000..4fd69bd
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_light.png
new file mode 100644
index 0000000..51588564
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-xhdpi/ic_notify_wifidisplay.png
new file mode 100644
index 0000000..4cc0ee8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_notify_wifidisplay.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_suggestions_add.png b/core/res/res/drawable-xhdpi/ic_suggestions_add.png
deleted file mode 100644
index b1edef7..0000000
--- a/core/res/res/drawable-xhdpi/ic_suggestions_add.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_suggestions_delete.png b/core/res/res/drawable-xhdpi/ic_suggestions_delete.png
deleted file mode 100644
index 6b1f447..0000000
--- a/core/res/res/drawable-xhdpi/ic_suggestions_delete.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_add_widget.png b/core/res/res/drawable-xhdpi/kg_add_widget.png
new file mode 100644
index 0000000..9c84de2
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/kg_add_widget.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_bouncer_bg_white.9.png b/core/res/res/drawable-xhdpi/kg_bouncer_bg_white.9.png
new file mode 100644
index 0000000..b9e30e2
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/kg_bouncer_bg_white.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_security_grip.9.png b/core/res/res/drawable-xhdpi/kg_security_grip.9.png
new file mode 100644
index 0000000..c33b9d3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/kg_security_grip.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_security_lock.png b/core/res/res/drawable-xhdpi/kg_security_lock.png
new file mode 100644
index 0000000..81d577e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/kg_security_lock.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_security_lock_focused.png b/core/res/res/drawable-xhdpi/kg_security_lock_focused.png
new file mode 100644
index 0000000..ee21647
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/kg_security_lock_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_security_lock_normal.png b/core/res/res/drawable-xhdpi/kg_security_lock_normal.png
new file mode 100644
index 0000000..eae7d8c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/kg_security_lock_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_security_lock_pressed.png b/core/res/res/drawable-xhdpi/kg_security_lock_pressed.png
new file mode 100644
index 0000000..5e9a52b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/kg_security_lock_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_widget_bg_padded.9.png b/core/res/res/drawable-xhdpi/kg_widget_bg_padded.9.png
new file mode 100644
index 0000000..a84bfa3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/kg_widget_bg_padded.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_widget_delete_drop_target.png b/core/res/res/drawable-xhdpi/kg_widget_delete_drop_target.png
new file mode 100644
index 0000000..d4965d9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/kg_widget_delete_drop_target.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/lockscreen_protection_pattern.png b/core/res/res/drawable-xhdpi/lockscreen_protection_pattern.png
new file mode 100644
index 0000000..c13afe2
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/lockscreen_protection_pattern.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/magnified_region_frame.9.png b/core/res/res/drawable-xhdpi/magnified_region_frame.9.png
new file mode 100644
index 0000000..424b3d9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/magnified_region_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png
index e2aff72..f67e609 100644
--- a/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png
index 93066c8..ed71eda 100644
--- a/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_dark.9.png b/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_dark.9.png
index 521e2d9..585bccc 100644
--- a/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_light.9.png b/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_light.9.png
index 92e117d..a0669b9 100644
--- a/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/panel_bg_holo_dark.9.png b/core/res/res/drawable-xhdpi/panel_bg_holo_dark.9.png
index 0cf7ac8..aaf6d8b 100644
--- a/core/res/res/drawable-xhdpi/panel_bg_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/panel_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/panel_bg_holo_light.9.png b/core/res/res/drawable-xhdpi/panel_bg_holo_light.9.png
index 9bdf3f1..6ea7615 100644
--- a/core/res/res/drawable-xhdpi/panel_bg_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/panel_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_ab_default_holo_dark.9.png
index d8929fc..c43293d 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_default_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_default_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_ab_default_holo_light.9.png
index 9174c4e..3dc481e 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_default_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_dark.9.png
index 3015d30..9a7b173 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_light.9.png
index 126637d..6888fdc 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_dark.9.png
index d45c7a8..9408b47 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_light.9.png
index 29036b90..1cb95d1 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark.9.png
index 2cb34d7..a3c7711 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light.9.png
index 82f752f..2a21210 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_default_holo_dark.9.png
index e94ce80..fadfb5d 100644
--- a/core/res/res/drawable-xhdpi/spinner_default_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_default_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_default_holo_light.9.png
index f006541b..5a4ec3b 100644
--- a/core/res/res/drawable-xhdpi/spinner_default_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_disabled_holo_dark.9.png
index 7bfab99..7c3c49b 100644
--- a/core/res/res/drawable-xhdpi/spinner_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_disabled_holo_light.9.png
index 1edcc81..fe54126 100644
--- a/core/res/res/drawable-xhdpi/spinner_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_focused_holo_dark.9.png
index ff7b959..9ea957e 100644
--- a/core/res/res/drawable-xhdpi/spinner_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_focused_holo_light.9.png
index 156b5ab..8cb2fd8 100644
--- a/core/res/res/drawable-xhdpi/spinner_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_pressed_holo_dark.9.png
index d0ce6e4..aecf6bd 100644
--- a/core/res/res/drawable-xhdpi/spinner_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_pressed_holo_light.9.png
index 9e9617e..3273a22 100644
--- a/core/res/res/drawable-xhdpi/spinner_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_rssi_in_range.png b/core/res/res/drawable-xhdpi/stat_notify_rssi_in_range.png
new file mode 100644
index 0000000..c0586d8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/stat_notify_rssi_in_range.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_delete.png b/core/res/res/drawable-xhdpi/sym_keyboard_delete.png
index ca936d1..45c14aa 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_delete.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_delete.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_enter.png b/core/res/res/drawable-xhdpi/sym_keyboard_enter.png
new file mode 100644
index 0000000..3b034fd
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_enter.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num0_no_plus.png b/core/res/res/drawable-xhdpi/sym_keyboard_num0_no_plus.png
index 95b542d..cdd256d 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num0_no_plus.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num0_no_plus.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num1.png b/core/res/res/drawable-xhdpi/sym_keyboard_num1.png
index decd584..d81d4b5 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num1.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num1.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num2.png b/core/res/res/drawable-xhdpi/sym_keyboard_num2.png
index 37948fb..8ae9faf 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num2.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num2.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num3.png b/core/res/res/drawable-xhdpi/sym_keyboard_num3.png
index 0e36ff2..ed6e90a 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num3.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num3.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num4.png b/core/res/res/drawable-xhdpi/sym_keyboard_num4.png
index f469a4a8..5cff39f 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num4.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num4.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num5.png b/core/res/res/drawable-xhdpi/sym_keyboard_num5.png
index 941f877..1c9358e 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num5.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num5.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num6.png b/core/res/res/drawable-xhdpi/sym_keyboard_num6.png
index eceec553..9a5cb6f 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num6.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num6.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num7.png b/core/res/res/drawable-xhdpi/sym_keyboard_num7.png
index 5b5d205..1bd5c6b 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num7.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num7.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num8.png b/core/res/res/drawable-xhdpi/sym_keyboard_num8.png
index ea776eb..9a33152 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num8.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num8.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num9.png b/core/res/res/drawable-xhdpi/sym_keyboard_num9.png
index 29047fb..caa3113 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num9.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_return_holo.png b/core/res/res/drawable-xhdpi/sym_keyboard_return_holo.png
new file mode 100644
index 0000000..55174e0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_return_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_activated_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_activated_holo_dark.9.png
index b3f8cd6..653b7dc 100644
--- a/core/res/res/drawable-xhdpi/textfield_activated_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_activated_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_activated_holo_light.9.png
index b3f8cd6..08fcc5e 100644
--- a/core/res/res/drawable-xhdpi/textfield_activated_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_default_holo_dark.9.png
index b5c5907..3f63c3fc 100644
--- a/core/res/res/drawable-xhdpi/textfield_default_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_default_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_default_holo_light.9.png
index 30052e9..dbb9924 100644
--- a/core/res/res/drawable-xhdpi/textfield_default_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_disabled_focused_holo_dark.9.png
index 16be839..a9767fc 100644
--- a/core/res/res/drawable-xhdpi/textfield_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_disabled_focused_holo_light.9.png
index ddd0559..40a28cf 100644
--- a/core/res/res/drawable-xhdpi/textfield_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_disabled_holo_dark.9.png
index 3d143b9..d78b10d 100644
--- a/core/res/res/drawable-xhdpi/textfield_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_disabled_holo_light.9.png
index dfb2185..4ffdd86 100644
--- a/core/res/res/drawable-xhdpi/textfield_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_activated_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_activated_holo_dark.9.png
index b3f8cd6..e12da1b 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_activated_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_activated_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_activated_holo_light.9.png
index b3f8cd6..557788b 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_activated_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_default_holo_dark.9.png
index b5c5907..9a367c9 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_default_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_default_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_default_holo_light.9.png
index 30052e9..147ac58 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_default_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_disabled_focused_holo_dark.9.png
index 16be839..f89316a 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_disabled_focused_holo_light.9.png
index ddd0559..06173a4 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_disabled_holo_dark.9.png
index 3d143b9..1463e5d 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_disabled_holo_light.9.png
index dfb2185..e1c7e8c 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_focused_holo_dark.9.png
index 7f0dc65..9247353 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_focused_holo_light.9.png
index 7f0dc65..cab8e9f 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable/background_holo_dark.xml b/core/res/res/drawable/background_holo_dark.xml
new file mode 100644
index 0000000..7cfae4d
--- /dev/null
+++ b/core/res/res/drawable/background_holo_dark.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <gradient
+            android:startColor="#ff000000"
+            android:endColor="#ff272d33"
+            android:angle="270" />
+</shape>
diff --git a/core/res/res/drawable/background_holo_light.xml b/core/res/res/drawable/background_holo_light.xml
new file mode 100644
index 0000000..4e863ea
--- /dev/null
+++ b/core/res/res/drawable/background_holo_light.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <gradient
+            android:startColor="#ffe8e8e8"
+            android:endColor="#ffffffff"
+            android:angle="270" />
+</shape>
diff --git a/core/res/res/drawable/ic_media_route_connecting_holo_dark.xml b/core/res/res/drawable/ic_media_route_connecting_holo_dark.xml
new file mode 100644
index 0000000..36e01f6
--- /dev/null
+++ b/core/res/res/drawable/ic_media_route_connecting_holo_dark.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<animation-list
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:oneshot="false">
+    <item android:drawable="@drawable/ic_media_route_on_0_holo_dark" android:duration="500" />
+    <item android:drawable="@drawable/ic_media_route_on_1_holo_dark" android:duration="500" />
+    <item android:drawable="@drawable/ic_media_route_on_2_holo_dark" android:duration="500" />
+    <item android:drawable="@drawable/ic_media_route_on_holo_dark" android:duration="500" />
+    <item android:drawable="@drawable/ic_media_route_on_2_holo_dark" android:duration="500" />
+    <item android:drawable="@drawable/ic_media_route_on_1_holo_dark" android:duration="500" />
+</animation-list>
diff --git a/core/res/res/drawable/ic_media_route_connecting_holo_light.xml b/core/res/res/drawable/ic_media_route_connecting_holo_light.xml
new file mode 100644
index 0000000..6683db8
--- /dev/null
+++ b/core/res/res/drawable/ic_media_route_connecting_holo_light.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<animation-list
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:oneshot="false">
+    <item android:drawable="@drawable/ic_media_route_on_0_holo_light" android:duration="500" />
+    <item android:drawable="@drawable/ic_media_route_on_1_holo_light" android:duration="500" />
+    <item android:drawable="@drawable/ic_media_route_on_2_holo_light" android:duration="500" />
+    <item android:drawable="@drawable/ic_media_route_on_holo_light" android:duration="500" />
+    <item android:drawable="@drawable/ic_media_route_on_2_holo_light" android:duration="500" />
+    <item android:drawable="@drawable/ic_media_route_on_1_holo_light" android:duration="500" />
+</animation-list>
diff --git a/core/res/res/drawable/ic_media_route_holo_dark.xml b/core/res/res/drawable/ic_media_route_holo_dark.xml
index 0b267d7..b4c1fac 100644
--- a/core/res/res/drawable/ic_media_route_holo_dark.xml
+++ b/core/res/res/drawable/ic_media_route_holo_dark.xml
@@ -15,6 +15,7 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:state_enabled="true" android:drawable="@android:drawable/ic_media_route_connecting_holo_dark" />
     <item android:state_activated="true" android:state_enabled="true" android:drawable="@android:drawable/ic_media_route_on_holo_dark" />
     <item android:state_enabled="true" android:drawable="@android:drawable/ic_media_route_off_holo_dark" />
     <item android:drawable="@android:drawable/ic_media_route_disabled_holo_dark" />
diff --git a/core/res/res/drawable/ic_media_route_holo_light.xml b/core/res/res/drawable/ic_media_route_holo_light.xml
index 377253a..553721d6 100644
--- a/core/res/res/drawable/ic_media_route_holo_light.xml
+++ b/core/res/res/drawable/ic_media_route_holo_light.xml
@@ -15,6 +15,7 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:state_enabled="true" android:drawable="@android:drawable/ic_media_route_connecting_holo_light" />
     <item android:state_activated="true" android:state_enabled="true" android:drawable="@android:drawable/ic_media_route_on_holo_light" />
     <item android:state_enabled="true" android:drawable="@android:drawable/ic_media_route_off_holo_light" />
     <item android:drawable="@android:drawable/ic_media_route_disabled_holo_light" />
diff --git a/core/res/res/drawable/keyguard_expand_challenge_handle.xml b/core/res/res/drawable/keyguard_expand_challenge_handle.xml
new file mode 100644
index 0000000..3e0780b
--- /dev/null
+++ b/core/res/res/drawable/keyguard_expand_challenge_handle.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_focused="true" android:drawable="@drawable/kg_security_lock_focused" />
+    <item android:state_pressed="true" android:drawable="@drawable/kg_security_lock_pressed" />
+    <item android:drawable="@drawable/kg_security_lock_normal" />
+</selector>
diff --git a/core/res/res/drawable/scrubber_progress_horizontal_holo_dark.xml b/core/res/res/drawable/scrubber_progress_horizontal_holo_dark.xml
index b117bb8..97cd513 100644
--- a/core/res/res/drawable/scrubber_progress_horizontal_holo_dark.xml
+++ b/core/res/res/drawable/scrubber_progress_horizontal_holo_dark.xml
@@ -19,10 +19,10 @@
             android:drawable="@android:drawable/scrubber_track_holo_dark" />
     <item android:id="@android:id/secondaryProgress">
         <scale android:scaleWidth="100%"
-                android:drawable="@android:drawable/scrubber_secondary_holo" />
+               android:drawable="@android:drawable/scrubber_secondary_holo" />
     </item>
     <item android:id="@android:id/progress">
         <scale android:scaleWidth="100%"
-                android:drawable="@android:drawable/scrubber_primary_holo" />
+               android:drawable="@android:drawable/scrubber_primary_holo" />
     </item>
 </layer-list>
diff --git a/core/res/res/drawable/scrubber_progress_horizontal_holo_light.xml b/core/res/res/drawable/scrubber_progress_horizontal_holo_light.xml
index 6cd08ea..14e19f4 100644
--- a/core/res/res/drawable/scrubber_progress_horizontal_holo_light.xml
+++ b/core/res/res/drawable/scrubber_progress_horizontal_holo_light.xml
@@ -19,10 +19,10 @@
             android:drawable="@android:drawable/scrubber_track_holo_light" />
     <item android:id="@android:id/secondaryProgress">
         <scale android:scaleWidth="100%"
-                android:drawable="@android:drawable/scrubber_secondary_holo" />
+               android:drawable="@android:drawable/scrubber_secondary_holo" />
     </item>
     <item android:id="@android:id/progress">
         <scale android:scaleWidth="100%"
-                android:drawable="@android:drawable/scrubber_primary_holo" />
+               android:drawable="@android:drawable/scrubber_primary_holo" />
     </item>
 </layer-list>
diff --git a/core/res/res/layout-land/keyguard_glow_pad_container.xml b/core/res/res/layout-land/keyguard_glow_pad_container.xml
new file mode 100644
index 0000000..f8364f1
--- /dev/null
+++ b/core/res/res/layout-land/keyguard_glow_pad_container.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <include layout="@layout/keyguard_glow_pad_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center" />
+</merge>
\ No newline at end of file
diff --git a/core/res/res/layout-land/keyguard_host_view.xml b/core/res/res/layout-land/keyguard_host_view.xml
new file mode 100644
index 0000000..6b36235
--- /dev/null
+++ b/core/res/res/layout-land/keyguard_host_view.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is the host view that generally contains two sub views: the widget view
+    and the security view. -->
+<com.android.internal.policy.impl.keyguard.KeyguardHostView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_host_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal">
+
+    <com.android.internal.policy.impl.keyguard.MultiPaneChallengeLayout
+        android:id="@+id/multi_pane_challenge"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:clipChildren="false">
+
+        <include layout="@layout/keyguard_widget_remove_drop_target"
+            android:id="@+id/keyguard_widget_pager_delete_target"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="top|center_horizontal"
+            androidprv:layout_childType="pageDeleteDropTarget" />
+
+        <include layout="@layout/keyguard_widget_pager"
+            android:id="@+id/app_widget_container"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            androidprv:layout_centerWithinArea="0.55"
+            androidprv:layout_childType="widget"
+            androidprv:layout_maxWidth="480dp"
+            androidprv:layout_maxHeight="480dp" />
+        <include layout="@layout/keyguard_multi_user_selector"/>
+
+        <View android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              androidprv:layout_childType="scrim"
+              android:background="#99000000" />
+
+        <com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer
+            android:id="@+id/keyguard_security_container"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            androidprv:layout_childType="challenge"
+            androidprv:layout_centerWithinArea="0.55">
+            <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper
+                android:id="@+id/view_flipper"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:clipChildren="false"
+                android:clipToPadding="false"
+                android:paddingLeft="@dimen/keyguard_security_view_margin"
+                android:paddingTop="@dimen/keyguard_security_view_margin"
+                android:paddingRight="@dimen/keyguard_security_view_margin"
+                android:paddingBottom="@dimen/keyguard_security_view_margin"
+                android:gravity="center">
+            </com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper>
+        </com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer>
+
+    </com.android.internal.policy.impl.keyguard.MultiPaneChallengeLayout>
+</com.android.internal.policy.impl.keyguard.KeyguardHostView>
+
diff --git a/core/res/res/layout-land/keyguard_status_area.xml b/core/res/res/layout-land/keyguard_status_area.xml
new file mode 100644
index 0000000..51ee740
--- /dev/null
+++ b/core/res/res/layout-land/keyguard_status_area.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<!-- This is a view that shows general status information in Keyguard. -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_status_area"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="end"
+    android:layout_marginTop="-16dp"
+    android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/date"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="end"
+        android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/kg_status_date_font_size"
+        />
+
+    <TextView
+        android:id="@+id/alarm_status"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="end"
+        android:layout_marginTop="28dp"
+        android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearance"
+        android:textSize="@dimen/kg_status_line_font_size"
+        android:drawablePadding="4dip"
+        />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/layout-land/keyguard_widget_pager.xml b/core/res/res/layout-land/keyguard_widget_pager.xml
new file mode 100644
index 0000000..02c6d0e
--- /dev/null
+++ b/core/res/res/layout-land/keyguard_widget_pager.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is the selector widget that allows the user to select an action. -->
+<com.android.internal.policy.impl.keyguard.KeyguardWidgetCarousel
+    xmlns:androidprv="http://schemas.android.com/apk/res/android"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:paddingLeft="25dp"
+    android:paddingRight="25dp"
+    android:paddingTop="25dp"
+    android:paddingBottom="25dp"
+    android:clipToPadding="false"
+    androidprv:pageSpacing="10dp">
+</com.android.internal.policy.impl.keyguard.KeyguardWidgetCarousel>
\ No newline at end of file
diff --git a/core/res/res/layout-land/ssl_certificate.xml b/core/res/res/layout-land/ssl_certificate.xml
index 4f8bd8e..c6c8dd4 100644
--- a/core/res/res/layout-land/ssl_certificate.xml
+++ b/core/res/res/layout-land/ssl_certificate.xml
@@ -23,7 +23,7 @@
         android:id="@+id/body"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:gravity="left"
+        android:gravity="start"
         android:orientation="vertical" >
 
         <!-- Placeholder for the success message or one or more warnings -->
@@ -43,8 +43,8 @@
             android:scaleType="fitXY"
             android:layout_weight="1"
             android:gravity="fill_horizontal"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"/>
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"/>
 
         <TableLayout
             android:layout_width="match_parent"
@@ -60,8 +60,8 @@
                 android:layout_height="wrap_content"
                 android:layout_width="match_parent"
                 android:layout_marginTop="12dip"
-                android:layout_marginLeft="20dip"
-                android:layout_marginRight="20dip"
+                android:layout_marginStart="20dip"
+                android:layout_marginEnd="20dip"
                 android:layout_marginBottom="7dip" />
 
             <!-- Common name: -->
@@ -69,12 +69,12 @@
                 <TextView
                     android:id="@+id/to_common_header"
                     android:text="@string/common_name"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/to_common"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
             </TableRow>
 
@@ -83,12 +83,12 @@
                 <TextView
                     android:id="@+id/to_org_header"
                     android:text="@string/org_name"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/to_org"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
             </TableRow>
 
@@ -97,12 +97,12 @@
                 <TextView
                     android:id="@+id/to_org_unit_header"
                     android:text="@string/org_unit"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/to_org_unit"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
             </TableRow>
 
@@ -111,12 +111,12 @@
                 <TextView
                     android:id="@+id/serial_number_header"
                     android:text="@string/serial_number"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/serial_number"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
             </TableRow>
 
@@ -128,8 +128,8 @@
                 android:layout_height="wrap_content"
                 android:layout_width="match_parent"
                 android:layout_marginTop="12dip"
-                android:layout_marginLeft="20dip"
-                android:layout_marginRight="20dip"
+                android:layout_marginStart="20dip"
+                android:layout_marginEnd="20dip"
                 android:layout_marginBottom="7dip" />
 
             <!-- Common name: -->
@@ -137,12 +137,12 @@
                 <TextView
                     android:id="@+id/by_common_header"
                     android:text="@string/common_name"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/by_common"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
             </TableRow>
 
@@ -151,12 +151,12 @@
                 <TextView
                     android:id="@+id/by_org_header"
                     android:text="@string/org_name"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/by_org"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
             </TableRow>
 
@@ -165,12 +165,12 @@
                 <TextView
                     android:id="@+id/by_org_unit_header"
                     android:text="@string/org_unit"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/by_org_unit"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
             </TableRow>
 
@@ -182,8 +182,8 @@
                 android:text="@string/validity_period"
                 android:textStyle="bold"
                 android:layout_marginTop="12dip"
-                android:layout_marginLeft="20dip"
-                android:layout_marginRight="20dip"
+                android:layout_marginStart="20dip"
+                android:layout_marginEnd="20dip"
                 android:layout_marginBottom="7dip" />
 
             <!-- Issued On: -->
@@ -193,14 +193,14 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/issued_on"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/issued_on"
                     android:layout_height="wrap_content"
                     android:layout_width="match_parent"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
 
             </TableRow>
@@ -212,14 +212,14 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/expires_on"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/expires_on"
                     android:layout_height="wrap_content"
                     android:layout_width="match_parent"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
             </TableRow>
 
@@ -231,8 +231,8 @@
                 android:text="@string/fingerprints"
                 android:textStyle="bold"
                 android:layout_marginTop="12dip"
-                android:layout_marginLeft="20dip"
-                android:layout_marginRight="20dip"
+                android:layout_marginStart="20dip"
+                android:layout_marginEnd="20dip"
                 android:layout_marginBottom="7dip" />
 
             <!-- SHA-256 fingerprint: -->
@@ -242,14 +242,14 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/sha256_fingerprint"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/sha256_fingerprint"
                     android:layout_height="wrap_content"
                     android:layout_width="match_parent"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
 
             </TableRow>
@@ -261,14 +261,14 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/sha1_fingerprint"
-                    android:layout_marginLeft="20dip" />
+                    android:layout_marginStart="20dip" />
 
                 <TextView
                     android:id="@+id/sha1_fingerprint"
                     android:layout_height="wrap_content"
                     android:layout_width="match_parent"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginRight="20dip"
+                    android:layout_marginStart="10dip"
+                    android:layout_marginEnd="20dip"
                     android:layout_marginBottom="7dip" />
 
             </TableRow>
diff --git a/core/res/res/layout-land/usb_storage_activity.xml b/core/res/res/layout-land/usb_storage_activity.xml
index 50ca569..d52f0a5 100644
--- a/core/res/res/layout-land/usb_storage_activity.xml
+++ b/core/res/res/layout-land/usb_storage_activity.xml
@@ -52,16 +52,16 @@
             <Button android:id="@+id/mount_button" 
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:paddingLeft="18dip"
-                android:paddingRight="18dip"
+                android:paddingStart="18dip"
+                android:paddingEnd="18dip"
                 android:text="@string/usb_storage_button_mount"
                 />
             <Button android:id="@+id/unmount_button"
                 android:visibility="gone"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:paddingLeft="18dip"
-                android:paddingRight="18dip"
+                android:paddingStart="18dip"
+                android:paddingEnd="18dip"
                 android:text="@string/usb_storage_stop_button_mount"
                 />
             <ProgressBar android:id="@+id/progress"
diff --git a/core/res/res/layout-large/action_mode_close_item.xml b/core/res/res/layout-large/action_mode_close_item.xml
index f8b397a..df06de6 100644
--- a/core/res/res/layout-large/action_mode_close_item.xml
+++ b/core/res/res/layout-large/action_mode_close_item.xml
@@ -18,11 +18,11 @@
         android:id="@+id/action_mode_close_button"
         android:focusable="true"
         android:clickable="true"
-        android:paddingLeft="8dip"
+        android:paddingStart="8dip"
         style="?android:attr/actionModeCloseButtonStyle"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
-        android:layout_marginRight="16dip">
+        android:layout_marginEnd="16dip">
     <ImageView android:layout_width="48dip"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
@@ -31,8 +31,8 @@
     <TextView android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:layout_gravity="center"
-              android:layout_marginLeft="4dip"
-              android:layout_marginRight="16dip"
+              android:layout_marginStart="4dip"
+              android:layout_marginEnd="16dip"
               android:textAppearance="?android:attr/textAppearanceSmall"
               android:textColor="?android:attr/actionMenuTextColor"
               android:textSize="12sp"
diff --git a/core/res/res/layout-port/keyguard_host_view.xml b/core/res/res/layout-port/keyguard_host_view.xml
new file mode 100644
index 0000000..fb25f9c
--- /dev/null
+++ b/core/res/res/layout-port/keyguard_host_view.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is the host view that generally contains two sub views: the widget view
+    and the security view. -->
+<com.android.internal.policy.impl.keyguard.KeyguardHostView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_host_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="center_horizontal"
+    android:orientation="vertical">
+
+    <com.android.internal.policy.impl.keyguard.SlidingChallengeLayout
+        android:id="@+id/sliding_layout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            androidprv:layout_childType="pageDeleteDropTarget">
+            <include layout="@layout/keyguard_widget_remove_drop_target"
+                android:id="@+id/keyguard_widget_pager_delete_target"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="top|center_horizontal" />
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            androidprv:layout_childType="widgets">
+            <include layout="@layout/keyguard_widget_pager"
+                android:id="@+id/app_widget_container"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="center"/>
+        </FrameLayout>
+
+        <View android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              androidprv:layout_childType="scrim"
+              android:background="#99000000" />
+
+        <com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer
+            android:id="@+id/keyguard_security_container"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_maxHeight="@dimen/keyguard_security_height"
+            androidprv:layout_childType="challenge"
+            android:padding="0dp"
+            android:gravity="bottom|center_horizontal">
+            <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper
+                android:id="@+id/view_flipper"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:clipChildren="false"
+                android:clipToPadding="false"
+                android:paddingTop="@dimen/keyguard_security_view_margin"
+                android:gravity="center">
+            </com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper>
+        </com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer>
+
+        <ImageButton
+              android:layout_width="match_parent"
+              android:layout_height="@dimen/kg_widget_pager_bottom_padding"
+              androidprv:layout_childType="expandChallengeHandle"
+              android:focusable="true"
+              android:background="@null"
+              android:src="@drawable/keyguard_expand_challenge_handle"
+              android:scaleType="center"
+              android:contentDescription="@string/keyguard_accessibility_expand_lock_area" />
+
+    </com.android.internal.policy.impl.keyguard.SlidingChallengeLayout>
+</com.android.internal.policy.impl.keyguard.KeyguardHostView>
+
diff --git a/core/res/res/layout-port/keyguard_status_area.xml b/core/res/res/layout-port/keyguard_status_area.xml
new file mode 100644
index 0000000..d274457
--- /dev/null
+++ b/core/res/res/layout-port/keyguard_status_area.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<!-- This is a view that shows general status information in Keyguard. -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_status_area"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="right"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="0dp"
+        android:layout_gravity="right">
+        <TextView
+            android:id="@+id/date"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="@dimen/kg_status_date_font_size"
+            />
+
+        <TextView
+            android:id="@+id/alarm_status"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:textAppearance="?android:attr/textAppearance"
+            android:textSize="@dimen/kg_status_line_font_size"
+            android:drawablePadding="4dip"
+            />
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/core/res/res/layout-port/keyguard_widget_pager.xml b/core/res/res/layout-port/keyguard_widget_pager.xml
new file mode 100644
index 0000000..7f22709
--- /dev/null
+++ b/core/res/res/layout-port/keyguard_widget_pager.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is the selector widget that allows the user to select an action. -->
+<com.android.internal.policy.impl.keyguard.KeyguardWidgetPager
+    xmlns:androidprv="http://schemas.android.com/apk/res/android"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/app_widget_container"
+    android:paddingLeft="25dp"
+    android:paddingRight="25dp"
+    android:paddingTop="25dp"
+    android:paddingBottom="@dimen/kg_widget_pager_bottom_padding"
+    android:clipToPadding="false"
+    androidprv:pageSpacing="10dp">
+</com.android.internal.policy.impl.keyguard.KeyguardWidgetPager>
diff --git a/core/res/res/layout-sw600dp-port/keyguard_host_view.xml b/core/res/res/layout-sw600dp-port/keyguard_host_view.xml
new file mode 100644
index 0000000..e3d577d
--- /dev/null
+++ b/core/res/res/layout-sw600dp-port/keyguard_host_view.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is the host view that generally contains two sub views: the widget view
+    and the security view. -->
+<com.android.internal.policy.impl.keyguard.KeyguardHostView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_host_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal">
+
+    <com.android.internal.policy.impl.keyguard.MultiPaneChallengeLayout
+        android:id="@+id/multi_pane_challenge"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:clipChildren="false"
+        android:orientation="vertical">
+
+        <include layout="@layout/keyguard_widget_remove_drop_target"
+            android:id="@+id/keyguard_widget_pager_delete_target"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="top|center_horizontal"
+            androidprv:layout_childType="pageDeleteDropTarget" />
+
+        <include layout="@layout/keyguard_widget_pager"
+            android:id="@+id/app_widget_container"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            androidprv:layout_centerWithinArea="0.5"
+            androidprv:layout_childType="widget"
+            androidprv:layout_maxWidth="480dp"
+            androidprv:layout_maxHeight="480dp" />
+
+        <include layout="@layout/keyguard_multi_user_selector"/>
+
+        <View android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              androidprv:layout_childType="scrim"
+              android:background="#99000000" />
+
+        <com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer
+            android:id="@+id/keyguard_security_container"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            androidprv:layout_centerWithinArea="0.5"
+            androidprv:layout_childType="challenge"
+            android:layout_gravity="center_horizontal|bottom">
+            <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper
+                android:id="@+id/view_flipper"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:clipChildren="false"
+                android:clipToPadding="false"
+                android:paddingLeft="@dimen/keyguard_security_view_margin"
+                android:paddingTop="@dimen/keyguard_security_view_margin"
+                android:paddingRight="@dimen/keyguard_security_view_margin"
+                android:paddingBottom="@dimen/keyguard_security_view_margin"
+                android:gravity="center">
+            </com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper>
+        </com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer>
+
+    </com.android.internal.policy.impl.keyguard.MultiPaneChallengeLayout>
+</com.android.internal.policy.impl.keyguard.KeyguardHostView>
diff --git a/core/res/res/layout-sw600dp-port/keyguard_status_area.xml b/core/res/res/layout-sw600dp-port/keyguard_status_area.xml
new file mode 100644
index 0000000..88dd760
--- /dev/null
+++ b/core/res/res/layout-sw600dp-port/keyguard_status_area.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<!-- This is a view that shows general status information in Keyguard. -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_status_area"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="end"
+    android:layout_marginTop="-16dp"
+    android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/date"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="end"
+        android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/kg_status_date_font_size"
+        />
+
+    <TextView
+        android:id="@+id/alarm_status"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="end"
+        android:layout_marginTop="28dp"
+        android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearance"
+        android:textSize="@dimen/kg_status_line_font_size"
+        android:drawablePadding="4dip"
+        />
+
+</LinearLayout>
diff --git a/core/res/res/layout-sw600dp/keyguard.xml b/core/res/res/layout-sw600dp/keyguard.xml
index ca629f8..f8f482d 100644
--- a/core/res/res/layout-sw600dp/keyguard.xml
+++ b/core/res/res/layout-sw600dp/keyguard.xml
@@ -19,9 +19,9 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
-    android:paddingLeft="20dip"
+    android:paddingStart="20dip"
     android:paddingTop="20dip"
-    android:paddingRight="20dip"
+    android:paddingEnd="20dip"
     android:paddingBottom="20dip"
     android:orientation="vertical" 
     android:layout_width="wrap_content"
diff --git a/core/res/res/layout-sw600dp/keyguard_glow_pad_container.xml b/core/res/res/layout-sw600dp/keyguard_glow_pad_container.xml
new file mode 100644
index 0000000..930b14e
--- /dev/null
+++ b/core/res/res/layout-sw600dp/keyguard_glow_pad_container.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <include layout="@layout/keyguard_glow_pad_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center" />
+</merge>
\ No newline at end of file
diff --git a/core/res/res/layout-sw600dp/keyguard_navigation.xml b/core/res/res/layout-sw600dp/keyguard_navigation.xml
new file mode 100644
index 0000000..2e6fa37
--- /dev/null
+++ b/core/res/res/layout-sw600dp/keyguard_navigation.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <include layout="@layout/default_navigation" />
+</merge>
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_glogin_unlock.xml b/core/res/res/layout-sw600dp/keyguard_screen_glogin_unlock.xml
index 56c832c..a0b1aaa 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_glogin_unlock.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_glogin_unlock.xml
@@ -36,7 +36,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="64dip"
                 android:layout_alignParentTop="true"
-                android:layout_marginLeft="4dip"
+                android:layout_marginStart="4dip"
                 android:textAppearance="?android:attr/textAppearanceMedium"
                 android:gravity="center_vertical"
                 android:drawableLeft="@drawable/ic_lock_idle_lock"
@@ -57,7 +57,7 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@+id/spacerTop"
                 android:layout_marginTop="8dip"
-                android:layout_marginLeft="9dip"
+                android:layout_marginStart="9dip"
                 android:textAppearance="?android:attr/textAppearanceSmall"
                 android:text="@android:string/lockscreen_glogin_instructions"
                 />
@@ -68,8 +68,8 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@id/instructions"
                 android:layout_marginTop="8dip"
-                android:layout_marginLeft="7dip"
-                android:layout_marginRight="7dip"
+                android:layout_marginStart="7dip"
+                android:layout_marginEnd="7dip"
                 android:hint="@android:string/lockscreen_glogin_username_hint"
                 android:inputType="textEmailAddress"
                 />
@@ -80,8 +80,8 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@id/login"
                 android:layout_marginTop="15dip"
-                android:layout_marginLeft="7dip"
-                android:layout_marginRight="7dip"
+                android:layout_marginStart="7dip"
+                android:layout_marginEnd="7dip"
                 android:inputType="textPassword"
                 android:hint="@android:string/lockscreen_glogin_password_hint"
                 android:nextFocusRight="@+id/ok"
@@ -95,8 +95,8 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@id/password"
                 android:layout_marginTop="7dip"
-                android:layout_marginRight="7dip"
-                android:layout_alignParentRight="true"
+                android:layout_marginEnd="7dip"
+                android:layout_alignParentEnd="true"
                 android:text="@android:string/lockscreen_glogin_submit_button"
                 />
 
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_lock.xml b/core/res/res/layout-sw600dp/keyguard_screen_lock.xml
index c7aa654..ea061ff 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_lock.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_lock.xml
@@ -33,8 +33,8 @@
         android:layout_height="wrap_content"
         android:layout_gravity="center"
         android:layout_marginBottom="15dip"
-        android:layout_marginLeft="15dip"
-        android:layout_marginRight="15dip"
+        android:layout_marginStart="15dip"
+        android:layout_marginEnd="15dip"
         android:paddingTop="20dip"
         android:paddingBottom="20dip"
         android:background="@android:drawable/popup_full_dark"
@@ -107,7 +107,7 @@
             <ImageView android:id="@+id/batteryInfoIcon"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="6dip"
+                android:layout_marginEnd="6dip"
                 android:baselineAligned="true"
                 android:gravity="center"
             />
@@ -142,7 +142,7 @@
             <ImageView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="6dip"
+                android:layout_marginEnd="6dip"
                 android:baselineAligned="true"
                 android:src="@android:drawable/ic_lock_idle_alarm"
                 android:gravity="center"
@@ -176,7 +176,7 @@
             <ImageView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="6dip"
+                android:layout_marginEnd="6dip"
                 android:baselineAligned="true"
                 android:src="@android:drawable/ic_lock_idle_lock"
                 android:gravity="center"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
index 8d5d404..47d4728 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
@@ -39,12 +39,12 @@
             <include layout="@layout/keyguard_screen_status_land"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="50dip"
+                android:layout_marginStart="50dip"
                 android:layout_marginTop="50dip"
                 android:layout_marginBottom="50dip"
-                android:layout_marginRight="64dip"
+                android:layout_marginEnd="64dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentLeft="true"/>
+                android:layout_alignParentStart="true"/>
 
             <!-- Music transport control -->
             <include android:id="@+id/transport"
@@ -89,7 +89,6 @@
                     android:layout_weight="1"
                     android:gravity="center"
                     android:layout_gravity="center"
-                    android:layout_marginLeft="@dimen/keyguard_lockscreen_pin_margin_left"
                     android:singleLine="true"
                     android:textStyle="normal"
                     android:inputType="textPassword"
@@ -154,7 +153,7 @@
 
         <!-- Area to overlay FaceLock -->
         <RelativeLayout
-            android:id="@+id/faceLockAreaView"
+            android:id="@+id/face_unlock_area_view"
             android:visibility="invisible"
             android:layout_width="530dip"
             android:layout_height="530dip"
@@ -174,7 +173,7 @@
                 android:layout_height="wrap_content"
                 android:padding="5dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentRight="true"
+                android:layout_alignParentEnd="true"
                 android:src="@drawable/ic_facial_backup"
             />
 
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
index 95c15e5..6dd85cb 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
@@ -38,11 +38,11 @@
             <include layout="@layout/keyguard_screen_status_port"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="50dip"
+                android:layout_marginStart="50dip"
                 android:layout_marginTop="50dip"
-                android:layout_marginRight="64dip"
+                android:layout_marginEnd="64dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentLeft="true"/>
+                android:layout_alignParentStart="true"/>
 
             <!-- Music transport control -->
             <include android:id="@+id/transport"
@@ -93,7 +93,6 @@
                     android:inputType="textPassword"
                     android:gravity="center"
                     android:layout_gravity="center"
-                    android:layout_marginLeft="@dimen/keyguard_lockscreen_pin_margin_left"
                     android:textSize="24sp"
                     android:textAppearance="?android:attr/textAppearanceMedium"
                     android:background="@null"
@@ -157,7 +156,7 @@
 
         <!-- Area to overlay FaceLock -->
         <RelativeLayout
-            android:id="@+id/faceLockAreaView"
+            android:id="@+id/face_unlock_area_view"
             android:visibility="invisible"
             android:layout_width="440dip"
             android:layout_height="440dip"
@@ -177,7 +176,7 @@
                 android:layout_height="wrap_content"
                 android:padding="5dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentRight="true"
+                android:layout_alignParentEnd="true"
                 android:src="@drawable/ic_facial_backup"
             />
 
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml
index 0b94fc1..efb9e2a 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml
@@ -41,7 +41,7 @@
         android:layout_height="wrap_content"
         android:layout_above="@+id/pinDisplayGroup"
         android:layout_marginTop="9dip"
-        android:gravity="left|bottom"
+        android:gravity="start|bottom"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -56,9 +56,9 @@
         android:addStatesFromChildren="true"
         android:gravity="center_vertical"
         android:baselineAligned="false"
-        android:paddingRight="0dip"
-        android:layout_marginRight="30dip"
-        android:layout_marginLeft="30dip"
+        android:paddingEnd="0dip"
+        android:layout_marginEnd="30dip"
+        android:layout_marginStart="30dip"
         android:background="@android:drawable/edit_text"
     >
 
@@ -77,7 +77,7 @@
              android:layout_width="wrap_content"
              android:layout_height="match_parent"
              android:layout_marginTop="2dip"
-             android:layout_marginRight="2dip"
+             android:layout_marginEnd="2dip"
              android:layout_marginBottom="2dip"
              android:gravity="center"
             />
@@ -90,8 +90,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="8dip"
-        android:layout_marginLeft="8dip"
-        android:layout_marginRight="8dip">
+        android:layout_marginStart="8dip"
+        android:layout_marginEnd="8dip">
 
         <Button android:id="@+id/emergencyCallButton"
             android:text="@android:string/lockscreen_emergency_call"
@@ -101,7 +101,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="1.0"
             android:layout_marginBottom="8dip"
-            android:layout_marginRight="8dip"
+            android:layout_marginEnd="8dip"
             android:textSize="18sp"
             android:drawableLeft="@drawable/ic_emergency"
             android:drawablePadding="8dip"
@@ -114,7 +114,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="1.0"
             android:layout_marginBottom="8dip"
-            android:layout_marginLeft="8dip"
+            android:layout_marginStart="8dip"
             android:textSize="18sp"
         />
     </LinearLayout>
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_portrait.xml
index 1be4462..db84156 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_portrait.xml
@@ -51,8 +51,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            android:layout_marginRight="6dip"
-            android:layout_marginLeft="6dip"
+            android:layout_marginEnd="6dip"
+            android:layout_marginStart="6dip"
             android:gravity="center_vertical"
             android:background="@android:drawable/edit_text">
 
@@ -72,7 +72,7 @@
                 android:src="@android:drawable/ic_input_delete"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="-3dip"
+                android:layout_marginEnd="-3dip"
                 android:layout_marginBottom="-3dip"
             />
         </LinearLayout>
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
index 4fafc3c..c6ddd1b 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
@@ -23,7 +23,7 @@
         android:orientation="vertical"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:gravity="right">
+        android:gravity="end">
 
     <TextView
         android:id="@+id/carrier"
@@ -66,7 +66,7 @@
             android:textSize="@dimen/keyguard_pattern_unlock_clock_font_size"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="@color/lockscreen_clock_foreground"
-            android:layout_alignLeft="@id/timeDisplayBackground"
+            android:layout_alignStart="@id/timeDisplayBackground"
             android:layout_alignTop="@id/timeDisplayBackground"
             android:layout_marginBottom="6dip"
             />
@@ -91,7 +91,7 @@
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="16dip"
+            android:layout_marginStart="16dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:drawablePadding="4dip"
             android:textSize="16sp"/>
@@ -109,7 +109,7 @@
         />
 
     <TextView
-        android:id="@+id/propertyOf"
+        android:id="@+id/owner_info"
         android:lineSpacingExtra="8dip"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
index dfab3e3..765dc95 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
@@ -24,7 +24,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="20dip"
-        android:gravity="right"
+        android:gravity="end"
         >
 
     <TextView
@@ -68,7 +68,7 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="@color/lockscreen_clock_foreground"
             android:layout_marginBottom="6dip"
-            android:layout_alignLeft="@id/timeDisplayBackground"
+            android:layout_alignStart="@id/timeDisplayBackground"
             android:layout_alignTop="@id/timeDisplayBackground"
             />
 
@@ -92,7 +92,7 @@
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="16dip"
+            android:layout_marginStart="16dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:drawablePadding="4dip"
             android:textSize="16sp"/>
@@ -109,7 +109,7 @@
         />
 
     <TextView
-        android:id="@+id/propertyOf"
+        android:id="@+id/owner_info"
         android:lineSpacingExtra="8dip"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
index af7d011..4f6b62a 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
@@ -44,10 +44,10 @@
             <include layout="@layout/keyguard_screen_status_port"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="50dip"
+                android:layout_marginStart="50dip"
                 android:layout_marginTop="50dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentLeft="true"/>
+                android:layout_alignParentStart="true"/>
 
             <!-- Music transport control -->
             <include android:id="@+id/transport"
@@ -76,7 +76,7 @@
             android:id="@+id/screenLocked"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="24dip"
+            android:layout_marginStart="24dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:layout_marginTop="12dip"
             android:drawablePadding="4dip"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
index 2a2dc31..d5201ec 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
@@ -42,11 +42,11 @@
             <include layout="@layout/keyguard_screen_status_land"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="50dip"
+                android:layout_marginStart="50dip"
                 android:layout_marginTop="50dip"
-                android:layout_marginRight="64dip"
+                android:layout_marginEnd="64dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentLeft="true"/>
+                android:layout_alignParentStart="true"/>
 
             <!-- Music transport control -->
             <include android:id="@+id/transport"
@@ -78,7 +78,7 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:gravity="center"
             android:layout_marginTop="12dip"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:layout_alignParentTop="true"
             android:drawablePadding="4dip"/>
 
@@ -87,7 +87,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_rowSpan="7"
-            android:layout_gravity="center_vertical|right"
+            android:layout_gravity="center_vertical|end"
             android:gravity="center"
             android:focusable="true"
 
@@ -110,9 +110,9 @@
             android:id="@+id/emergencyCallButton"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginRight="80dip"
+            android:layout_marginEnd="80dip"
             android:layout_marginBottom="80dip"
-            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
             android:layout_alignParentBottom="true"
             android:drawableLeft="@drawable/ic_emergency"
             style="@style/Widget.Button.Transparent"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml
index 0153a2e..a71ef30 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml
@@ -43,12 +43,12 @@
             <include layout="@layout/keyguard_screen_status_land"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="50dip"
+                android:layout_marginStart="50dip"
                 android:layout_marginTop="50dip"
                 android:layout_marginBottom="50dip"
-                android:layout_marginRight="64dip"
+                android:layout_marginEnd="64dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentLeft="true"/>
+                android:layout_alignParentStart="true"/>
 
             <!-- Music transport control -->
             <include android:id="@+id/transport"
@@ -91,8 +91,8 @@
                 android:layout_height="wrap_content"
                 android:orientation="horizontal"
                 android:layout_below="@id/lockPattern"
-                android:layout_alignLeft="@id/lockPattern"
-                android:layout_alignRight="@id/lockPattern"
+                android:layout_alignStart="@id/lockPattern"
+                android:layout_alignEnd="@id/lockPattern"
                 android:layout_marginTop="28dip"
                 style="?android:attr/buttonBarStyle"
                 android:gravity="center"
@@ -126,7 +126,7 @@
 
         <!-- Area to overlay FaceLock -->
         <RelativeLayout
-            android:id="@+id/faceLockAreaView"
+            android:id="@+id/face_unlock_area_view"
             android:visibility="invisible"
             android:layout_width="530dip"
             android:layout_height="530dip"
@@ -146,7 +146,7 @@
                 android:layout_height="wrap_content"
                 android:padding="5dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentRight="true"
+                android:layout_alignParentEnd="true"
                 android:src="@drawable/ic_facial_backup"
             />
 
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
index 7231ead..0c4a2c7 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
@@ -39,11 +39,11 @@
             <include layout="@layout/keyguard_screen_status_land"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="50dip"
+                android:layout_marginStart="50dip"
                 android:layout_marginTop="50dip"
-                android:layout_marginRight="64dip"
+                android:layout_marginEnd="64dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentLeft="true"/>
+                android:layout_alignParentStart="true"/>
 
             <!-- Music transport control -->
             <include android:id="@+id/transport"
@@ -85,8 +85,8 @@
                 android:layout_height="wrap_content"
                 android:orientation="horizontal"
                 android:layout_below="@id/lockPattern"
-                android:layout_alignLeft="@id/lockPattern"
-                android:layout_alignRight="@id/lockPattern"
+                android:layout_alignStart="@id/lockPattern"
+                android:layout_alignEnd="@id/lockPattern"
                 style="?android:attr/buttonBarStyle"
                 android:gravity="center"
                 android:weightSum="2">
@@ -119,7 +119,7 @@
 
         <!-- Area to overlay FaceLock -->
         <RelativeLayout
-            android:id="@+id/faceLockAreaView"
+            android:id="@+id/face_unlock_area_view"
             android:visibility="invisible"
             android:layout_width="440dip"
             android:layout_height="440dip"
@@ -139,7 +139,7 @@
                 android:layout_height="wrap_content"
                 android:padding="5dip"
                 android:layout_alignParentTop="true"
-                android:layout_alignParentRight="true"
+                android:layout_alignParentEnd="true"
                 android:src="@drawable/ic_facial_backup"
             />
 
diff --git a/core/res/res/layout-sw600dp/keyguard_sim_puk_pin_navigation.xml b/core/res/res/layout-sw600dp/keyguard_sim_puk_pin_navigation.xml
new file mode 100644
index 0000000..2e6fa37
--- /dev/null
+++ b/core/res/res/layout-sw600dp/keyguard_sim_puk_pin_navigation.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <include layout="@layout/default_navigation" />
+</merge>
diff --git a/core/res/res/layout-sw600dp/keyguard_transport_control.xml b/core/res/res/layout-sw600dp/keyguard_transport_control.xml
index 86b103e..f864339 100644
--- a/core/res/res/layout-sw600dp/keyguard_transport_control.xml
+++ b/core/res/res/layout-sw600dp/keyguard_transport_control.xml
@@ -48,8 +48,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_marginTop="8dip"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip"
+            android:layout_marginStart="16dip"
+            android:layout_marginEnd="16dip"
             android:gravity="center_horizontal"
             android:singleLine="true"
             android:ellipsize="end"
diff --git a/core/res/res/layout-sw720dp/status_bar_latest_event_ticker.xml b/core/res/res/layout-sw720dp/status_bar_latest_event_ticker.xml
index 269e086..a09ad0c 100644
--- a/core/res/res/layout-sw720dp/status_bar_latest_event_ticker.xml
+++ b/core/res/res/layout-sw720dp/status_bar_latest_event_ticker.xml
@@ -13,7 +13,7 @@
         android:layout_gravity="center_vertical"
         android:layout_weight="1"
         android:orientation="vertical"
-        android:paddingLeft="16dp"
+        android:paddingStart="16dp"
         >
         <TextView android:id="@+id/title"
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
diff --git a/core/res/res/layout-sw720dp/status_bar_latest_event_ticker_large_icon.xml b/core/res/res/layout-sw720dp/status_bar_latest_event_ticker_large_icon.xml
index 69eac92..09ff1c8 100644
--- a/core/res/res/layout-sw720dp/status_bar_latest_event_ticker_large_icon.xml
+++ b/core/res/res/layout-sw720dp/status_bar_latest_event_ticker_large_icon.xml
@@ -8,7 +8,7 @@
         android:layout_gravity="center_vertical"
         android:layout_weight="1"
         android:orientation="vertical"
-        android:paddingLeft="16dp"
+        android:paddingStart="16dp"
         >
         <TextView android:id="@+id/title"
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
@@ -43,8 +43,8 @@
         android:layout_gravity="bottom"
         android:layout_marginBottom="13dip"
         android:scaleType="center"
-        android:layout_marginRight="4dip"
-        android:layout_marginLeft="16dip"
+        android:layout_marginEnd="4dip"
+        android:layout_marginStart="16dip"
         />
 </LinearLayout>
 
diff --git a/core/res/res/layout-w600dp/preference_list_content_single.xml b/core/res/res/layout-w600dp/preference_list_content_single.xml
index bbad296..d2fa5b9 100644
--- a/core/res/res/layout-w600dp/preference_list_content_single.xml
+++ b/core/res/res/layout-w600dp/preference_list_content_single.xml
@@ -34,8 +34,8 @@
             android:orientation="vertical"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:paddingLeft="32dip"
-            android:paddingRight="32dip"
+            android:paddingStart="32dip"
+            android:paddingEnd="32dip"
             android:paddingTop="32dip"
             android:paddingBottom="32dip" >
 
@@ -67,14 +67,14 @@
             android:layout_width="150dip"
             android:layout_height="wrap_content"
             android:layout_margin="5dip"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:text="@string/back_button_label"
         />
         <LinearLayout
             android:orientation="horizontal"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_alignParentRight="true">
+            android:layout_alignParentEnd="true">
 
             <Button android:id="@+id/skip_button"
                 android:layout_width="150dip"
diff --git a/core/res/res/layout-xlarge/activity_list.xml b/core/res/res/layout-xlarge/activity_list.xml
index 5093a5e..edf6ee6 100644
--- a/core/res/res/layout-xlarge/activity_list.xml
+++ b/core/res/res/layout-xlarge/activity_list.xml
@@ -22,8 +22,8 @@
     android:orientation="vertical"
     android:paddingTop="9dip"
     android:paddingBottom="3dip"
-    android:paddingLeft="3dip"
-    android:paddingRight="1dip"
+    android:paddingStart="3dip"
+    android:paddingEnd="1dip"
     android:majorWeightMin="0.45"
     android:minorWeightMin="0.72"
     android:majorWeightMax="0.45"
@@ -37,14 +37,14 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            android:gravity="center_vertical|left"
+            android:gravity="center_vertical|start"
             android:minHeight="60dip"
-            android:layout_marginLeft="32dip"
-            android:layout_marginRight="32dip">
+            android:layout_marginStart="32dip"
+            android:layout_marginEnd="32dip">
             <ImageView android:id="@+id/icon"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:paddingRight="16dip"
+                android:paddingEnd="16dip"
                 android:src="@null"
                 android:visibility="gone" />
             <com.android.internal.widget.DialogTitle android:id="@+id/alertTitle"
@@ -104,7 +104,7 @@
                 android:visibility="gone" />
             <Button android:id="@+id/button1"
                 android:layout_width="0dip"
-                android:layout_gravity="left"
+                android:layout_gravity="start"
                 android:layout_weight="1"
                 android:maxLines="2"
                 android:text="@string/cancel"
diff --git a/core/res/res/layout-xlarge/breadcrumbs_in_fragment.xml b/core/res/res/layout-xlarge/breadcrumbs_in_fragment.xml
index 384c4fe..8e86427 100644
--- a/core/res/res/layout-xlarge/breadcrumbs_in_fragment.xml
+++ b/core/res/res/layout-xlarge/breadcrumbs_in_fragment.xml
@@ -15,11 +15,12 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+android:id/breadcrumb_section"
         android:orientation="vertical"
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
-        android:layout_marginLeft="@dimen/preference_fragment_padding_side"
-        android:layout_marginRight="@dimen/preference_fragment_padding_side"
+        android:layout_marginStart="@dimen/preference_fragment_padding_side"
+        android:layout_marginEnd="@dimen/preference_fragment_padding_side"
     >
     <android.app.FragmentBreadCrumbs
             android:id="@android:id/title"
@@ -27,7 +28,7 @@
             android:layout_width="match_parent"
             android:paddingTop="16dip"
             android:paddingBottom="8dip"
-            android:gravity="center_vertical|left"
+            android:gravity="center_vertical|start"
         />
 
     <ImageView
diff --git a/core/res/res/layout-xlarge/select_dialog_holo.xml b/core/res/res/layout-xlarge/select_dialog_holo.xml
deleted file mode 100644
index 7c95693..0000000
--- a/core/res/res/layout-xlarge/select_dialog_holo.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-
-<!--
-    This layout file is used by the AlertDialog when displaying a list of items.
-    This layout file is inflated and used as the ListView to display the items.
-    Assign an ID so its state will be saved/restored.
--->
-<view class="com.android.internal.app.AlertController$RecycleListView"
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+android:id/select_dialog_listview"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_marginTop="5dip"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
-    android:cacheColorHint="@null"
-    android:divider="?android:attr/listDividerAlertDialog"
-    android:scrollbars="vertical"
-    android:overScrollMode="ifContentScrolls" />
diff --git a/core/res/res/layout-xlarge/select_dialog_item_holo.xml b/core/res/res/layout-xlarge/select_dialog_item_holo.xml
index 396092e..5f14e36 100644
--- a/core/res/res/layout-xlarge/select_dialog_item_holo.xml
+++ b/core/res/res/layout-xlarge/select_dialog_item_holo.xml
@@ -30,7 +30,7 @@
     android:textAppearance="?android:attr/textAppearanceMedium"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout-xlarge/select_dialog_multichoice_holo.xml b/core/res/res/layout-xlarge/select_dialog_multichoice_holo.xml
index 8027035..63edc86 100644
--- a/core/res/res/layout-xlarge/select_dialog_multichoice_holo.xml
+++ b/core/res/res/layout-xlarge/select_dialog_multichoice_holo.xml
@@ -22,8 +22,8 @@
     android:textAppearance="?android:attr/textAppearanceMedium"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:checkMark="?android:attr/listChoiceIndicatorMultiple"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout-xlarge/select_dialog_singlechoice_holo.xml b/core/res/res/layout-xlarge/select_dialog_singlechoice_holo.xml
index cab519f..6a00d0d 100644
--- a/core/res/res/layout-xlarge/select_dialog_singlechoice_holo.xml
+++ b/core/res/res/layout-xlarge/select_dialog_singlechoice_holo.xml
@@ -22,8 +22,8 @@
     android:textAppearance="?android:attr/textAppearanceMedium"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:checkMark="?android:attr/listChoiceIndicatorSingle"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout/action_bar_home.xml b/core/res/res/layout/action_bar_home.xml
index 96467d0..fe58215 100644
--- a/core/res/res/layout/action_bar_home.xml
+++ b/core/res/res/layout/action_bar_home.xml
@@ -18,18 +18,19 @@
       class="com.android.internal.widget.ActionBarView$HomeView"
       android:layout_width="wrap_content"
       android:layout_height="match_parent"
-      android:background="?android:attr/actionBarItemBackground" >
+      android:background="?android:attr/actionBarItemBackground"
+      android:animateLayoutChanges="true">
     <ImageView android:id="@android:id/up"
                android:src="?android:attr/homeAsUpIndicator"
-               android:layout_gravity="center_vertical|left"
+               android:layout_gravity="center_vertical|start"
                android:visibility="gone"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
-               android:layout_marginRight="-8dip" />
+               android:layout_marginEnd="-8dip" />
     <ImageView android:id="@android:id/home"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
-               android:layout_marginRight="8dip"
+               android:layout_marginEnd="8dip"
                android:layout_marginTop="@android:dimen/action_bar_icon_vertical_padding"
                android:layout_marginBottom="@android:dimen/action_bar_icon_vertical_padding"
                android:layout_gravity="center"
diff --git a/core/res/res/layout/action_bar_title_item.xml b/core/res/res/layout/action_bar_title_item.xml
index 2e21383..df773eb 100644
--- a/core/res/res/layout/action_bar_title_item.xml
+++ b/core/res/res/layout/action_bar_title_item.xml
@@ -18,20 +18,20 @@
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:orientation="horizontal"
-              android:paddingRight="8dip"
+              android:paddingEnd="8dip"
               android:background="?android:attr/actionBarItemBackground"
               android:enabled="false">
 
     <ImageView android:id="@android:id/up"
                android:src="?android:attr/homeAsUpIndicator"
-               android:layout_gravity="center_vertical|left"
+               android:layout_gravity="center_vertical|start"
                android:visibility="gone"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
 
     <LinearLayout android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
-                  android:layout_gravity="center_vertical|left"
+                  android:layout_gravity="center_vertical|start"
                   android:orientation="vertical">
         <TextView android:id="@+id/action_bar_title"
                   android:layout_width="wrap_content"
@@ -42,7 +42,6 @@
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:layout_marginTop="@dimen/action_bar_subtitle_top_margin"
-                  android:layout_marginBottom="@dimen/action_bar_subtitle_bottom_margin"
                   android:singleLine="true"
                   android:ellipsize="end"
                   android:visibility="gone" />
diff --git a/core/res/res/layout/action_menu_item_layout.xml b/core/res/res/layout/action_menu_item_layout.xml
index ba7cf3b..04d1f7b 100644
--- a/core/res/res/layout/action_menu_item_layout.xml
+++ b/core/res/res/layout/action_menu_item_layout.xml
@@ -22,8 +22,8 @@
     android:focusable="true"
     android:paddingTop="4dip"
     android:paddingBottom="4dip"
-    android:paddingLeft="8dip"
-    android:paddingRight="8dip"
+    android:paddingStart="8dip"
+    android:paddingEnd="8dip"
     android:textAppearance="?attr/actionMenuTextAppearance"
     android:textColor="?attr/actionMenuTextColor"
     style="?android:attr/actionButtonStyle" />
diff --git a/core/res/res/layout/action_mode_close_item.xml b/core/res/res/layout/action_mode_close_item.xml
index 8cd0cdd..3df83d0 100644
--- a/core/res/res/layout/action_mode_close_item.xml
+++ b/core/res/res/layout/action_mode_close_item.xml
@@ -18,12 +18,12 @@
         android:id="@+id/action_mode_close_button"
         android:focusable="true"
         android:clickable="true"
-        android:paddingLeft="8dip"
+        android:paddingStart="8dip"
         android:contentDescription="@string/action_mode_done"
         style="?android:attr/actionModeCloseButtonStyle"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
-        android:layout_marginRight="16dip">
+        android:layout_marginEnd="16dip">
     <ImageView android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
diff --git a/core/res/res/layout/activity_chooser_view.xml b/core/res/res/layout/activity_chooser_view.xml
index 4057441..bef17d0 100644
--- a/core/res/res/layout/activity_chooser_view.xml
+++ b/core/res/res/layout/activity_chooser_view.xml
@@ -38,8 +38,8 @@
             android:layout_gravity="center"
             android:layout_marginTop="2dip"
             android:layout_marginBottom="2dip"
-            android:layout_marginLeft="12dip"
-            android:layout_marginRight="12dip"
+            android:layout_marginStart="12dip"
+            android:layout_marginEnd="12dip"
             android:scaleType="fitCenter"
             android:adjustViewBounds="true" />
 
@@ -60,8 +60,8 @@
             android:layout_gravity="center"
             android:layout_marginTop="2dip"
             android:layout_marginBottom="2dip"
-            android:layout_marginLeft="12dip"
-            android:layout_marginRight="12dip"
+            android:layout_marginStart="12dip"
+            android:layout_marginEnd="12dip"
             android:scaleType="fitCenter"
             android:adjustViewBounds="true" />
 
diff --git a/core/res/res/layout/activity_chooser_view_list_item.xml b/core/res/res/layout/activity_chooser_view_list_item.xml
index 88498d9..af70234 100644
--- a/core/res/res/layout/activity_chooser_view_list_item.xml
+++ b/core/res/res/layout/activity_chooser_view_list_item.xml
@@ -18,8 +18,8 @@
     android:id="@+id/list_item"
     android:layout_width="match_parent"
     android:layout_height="?android:attr/dropdownListPreferredItemHeight"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:minWidth="196dip"
     android:background="?android:attr/activatedBackgroundIndicator"
     android:orientation="vertical" >
@@ -34,7 +34,7 @@
             android:layout_width="32dip"
             android:layout_height="32dip"
             android:layout_gravity="center_vertical"
-            android:layout_marginRight="8dip"
+            android:layout_marginEnd="8dip"
             android:duplicateParentState="true" />
 
         <TextView
diff --git a/core/res/res/layout/activity_list_item.xml b/core/res/res/layout/activity_list_item.xml
index 572caf0..d639aa0 100644
--- a/core/res/res/layout/activity_list_item.xml
+++ b/core/res/res/layout/activity_list_item.xml
@@ -22,8 +22,8 @@
     android:layout_height="wrap_content"
     android:paddingTop="1dip"
     android:paddingBottom="1dip"
-    android:paddingLeft="8dip"
-    android:paddingRight="8dip">
+    android:paddingStart="8dip"
+    android:paddingEnd="8dip">
 
     <ImageView android:id="@+id/icon"
         android:layout_width="24dip"
@@ -33,6 +33,6 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_horizontal"
-        android:paddingLeft="?android:attr/listPreferredItemPaddingLeft" />
+        android:paddingStart="?android:attr/listPreferredItemPaddingStart" />
 </LinearLayout>
 
diff --git a/core/res/res/layout/activity_list_item_2.xml b/core/res/res/layout/activity_list_item_2.xml
index a58ebfc..a5a4cf9 100644
--- a/core/res/res/layout/activity_list_item_2.xml
+++ b/core/res/res/layout/activity_list_item_2.xml
@@ -21,5 +21,5 @@
     android:textAppearance="?android:attr/textAppearanceListItemSmall"
     android:gravity="center_vertical"
     android:drawablePadding="14dip"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip" />
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip" />
diff --git a/core/res/res/layout/adaptive_notification_wrapper.xml b/core/res/res/layout/adaptive_notification_wrapper.xml
index df9d720..2583339 100644
--- a/core/res/res/layout/adaptive_notification_wrapper.xml
+++ b/core/res/res/layout/adaptive_notification_wrapper.xml
@@ -21,9 +21,9 @@
     android:id="@android:id/text1"
     android:textAppearance="?android:attr/dropDownHintAppearance"
     android:singleLine="true"
-    android:layout_marginLeft="3dip"
+    android:layout_marginStart="3dip"
     android:layout_marginTop="3dip"
-    android:layout_marginRight="3dip"
+    android:layout_marginEnd="3dip"
     android:layout_marginBottom="3dip"
     android:layout_width="match_parent"
     android:layout_height="wrap_content" />
diff --git a/core/res/res/layout/alert_dialog.xml b/core/res/res/layout/alert_dialog.xml
index 4477e07..35552d3 100644
--- a/core/res/res/layout/alert_dialog.xml
+++ b/core/res/res/layout/alert_dialog.xml
@@ -26,8 +26,8 @@
     android:orientation="vertical"
     android:paddingTop="9dip"
     android:paddingBottom="3dip"
-    android:paddingLeft="3dip"
-    android:paddingRight="1dip">
+    android:paddingStart="3dip"
+    android:paddingEnd="1dip">
 
     <LinearLayout android:id="@+id/topPanel"
         android:layout_width="match_parent"
@@ -41,14 +41,14 @@
             android:gravity="center_vertical"
             android:layout_marginTop="6dip"
             android:layout_marginBottom="9dip"
-            android:layout_marginLeft="10dip"
-            android:layout_marginRight="10dip">
+            android:layout_marginStart="10dip"
+            android:layout_marginEnd="10dip">
             <ImageView android:id="@+id/icon"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="top"
                 android:paddingTop="6dip"
-                android:paddingRight="10dip"
+                android:paddingEnd="10dip"
                 android:src="@drawable/ic_dialog_info" />
             <com.android.internal.widget.DialogTitle android:id="@+id/alertTitle"
                 style="?android:attr/textAppearanceLarge"
@@ -77,8 +77,8 @@
             android:layout_height="wrap_content"
             android:paddingTop="2dip"
             android:paddingBottom="12dip"
-            android:paddingLeft="14dip"
-            android:paddingRight="10dip"
+            android:paddingStart="14dip"
+            android:paddingEnd="10dip"
             android:overScrollMode="ifContentScrolls">
             <TextView android:id="@+id/message"
                 style="?android:attr/textAppearanceMedium"
@@ -110,8 +110,8 @@
             android:layout_height="wrap_content"
             android:orientation="horizontal"
             android:paddingTop="4dip"
-            android:paddingLeft="2dip"
-            android:paddingRight="2dip"
+            android:paddingStart="2dip"
+            android:paddingEnd="2dip"
             android:measureWithLargestChild="true">
             <LinearLayout android:id="@+id/leftSpacer"
                 android:layout_weight="0.25"
@@ -121,7 +121,7 @@
                 android:visibility="gone" />
             <Button android:id="@+id/button1"
                 android:layout_width="0dip"
-                android:layout_gravity="left"
+                android:layout_gravity="start"
                 android:layout_weight="1"
                 style="?android:attr/buttonBarButtonStyle"
                 android:maxLines="2"
@@ -135,7 +135,7 @@
                 android:layout_height="wrap_content" />
             <Button android:id="@+id/button2"
                 android:layout_width="0dip"
-                android:layout_gravity="right"
+                android:layout_gravity="end"
                 android:layout_weight="1"
                 style="?android:attr/buttonBarButtonStyle"
                 android:maxLines="2"
diff --git a/core/res/res/layout/alert_dialog_holo.xml b/core/res/res/layout/alert_dialog_holo.xml
index 173efa7..3f1fa3c 100644
--- a/core/res/res/layout/alert_dialog_holo.xml
+++ b/core/res/res/layout/alert_dialog_holo.xml
@@ -22,8 +22,8 @@
     android:id="@+id/parentPanel"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_marginLeft="8dip"
-    android:layout_marginRight="8dip"
+    android:layout_marginStart="8dip"
+    android:layout_marginEnd="8dip"
     android:orientation="vertical">
 
     <LinearLayout android:id="@+id/topPanel"
@@ -39,14 +39,14 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            android:gravity="center_vertical|left"
+            android:gravity="center_vertical|start"
             android:minHeight="@dimen/alert_dialog_title_height"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip">
+            android:layout_marginStart="16dip"
+            android:layout_marginEnd="16dip">
             <ImageView android:id="@+id/icon"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:paddingRight="8dip"
+                android:paddingEnd="8dip"
                 android:src="@null" />
             <com.android.internal.widget.DialogTitle android:id="@+id/alertTitle"
                 style="?android:attr/windowTitleStyle"
@@ -67,7 +67,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_weight="1"
-        android:orientation="vertical">
+        android:orientation="vertical"
+        android:minHeight="64dp">
         <ScrollView android:id="@+id/scrollView"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -76,8 +77,8 @@
                 style="?android:attr/textAppearanceMedium"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:paddingLeft="16dip"
-                android:paddingRight="16dip"
+                android:paddingStart="16dip"
+                android:paddingEnd="16dip"
                 android:paddingTop="8dip"
                 android:paddingBottom="8dip"/>
         </ScrollView>
@@ -86,7 +87,8 @@
     <FrameLayout android:id="@+id/customPanel"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_weight="1">
+        android:layout_weight="1"
+        android:minHeight="64dp">
         <FrameLayout android:id="@+android:id/custom"
             android:layout_width="match_parent"
             android:layout_height="wrap_content" />
@@ -109,7 +111,7 @@
             android:measureWithLargestChild="true">
             <Button android:id="@+id/button2"
                 android:layout_width="wrap_content"
-                android:layout_gravity="left"
+                android:layout_gravity="start"
                 android:layout_weight="1"
                 android:maxLines="2"
                 style="?android:attr/buttonBarButtonStyle"
@@ -127,7 +129,7 @@
                 android:layout_height="wrap_content" />
             <Button android:id="@+id/button1"
                 android:layout_width="wrap_content"
-                android:layout_gravity="right"
+                android:layout_gravity="end"
                 android:layout_weight="1"
                 android:maxLines="2"
                 android:minHeight="@dimen/alert_dialog_button_bar_height"
diff --git a/core/res/res/layout/alert_dialog_progress.xml b/core/res/res/layout/alert_dialog_progress.xml
index ac95cdb..fe06b65 100644
--- a/core/res/res/layout/alert_dialog_progress.xml
+++ b/core/res/res/layout/alert_dialog_progress.xml
@@ -22,17 +22,17 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="12dip"
             android:layout_marginBottom="1dip"
-            android:layout_marginLeft="10dip"
-            android:layout_marginRight="10dip"
+            android:layout_marginStart="10dip"
+            android:layout_marginEnd="10dip"
             android:layout_centerHorizontal="true" />
         <TextView
             android:id="@+id/progress_percent"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:paddingBottom="12dip"
-            android:layout_marginLeft="10dip"
-            android:layout_marginRight="10dip"
-            android:layout_alignParentLeft="true"
+            android:layout_marginStart="10dip"
+            android:layout_marginEnd="10dip"
+            android:layout_alignParentStart="true"
             android:layout_below="@id/progress"
         />
         <TextView
@@ -40,9 +40,9 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:paddingBottom="12dip"
-            android:layout_marginLeft="10dip"
-            android:layout_marginRight="10dip"
-            android:layout_alignParentRight="true"
+            android:layout_marginStart="10dip"
+            android:layout_marginEnd="10dip"
+            android:layout_alignParentEnd="true"
             android:layout_below="@id/progress"
         />
 </RelativeLayout>
diff --git a/core/res/res/layout/alert_dialog_progress_holo.xml b/core/res/res/layout/alert_dialog_progress_holo.xml
index 94dbb2b..41773d2 100644
--- a/core/res/res/layout/alert_dialog_progress_holo.xml
+++ b/core/res/res/layout/alert_dialog_progress_holo.xml
@@ -22,17 +22,17 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="16dip"
             android:layout_marginBottom="1dip"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip"
+            android:layout_marginStart="16dip"
+            android:layout_marginEnd="16dip"
             android:layout_centerHorizontal="true" />
         <TextView
             android:id="@+id/progress_percent"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:paddingBottom="16dip"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip"
-            android:layout_alignParentLeft="true"
+            android:layout_marginStart="16dip"
+            android:layout_marginEnd="16dip"
+            android:layout_alignParentStart="true"
             android:layout_below="@id/progress"
         />
         <TextView
@@ -40,9 +40,9 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:paddingBottom="16dip"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip"
-            android:layout_alignParentRight="true"
+            android:layout_marginStart="16dip"
+            android:layout_marginEnd="16dip"
+            android:layout_alignParentEnd="true"
             android:layout_below="@id/progress"
         />
 </RelativeLayout>
diff --git a/core/res/res/layout/always_use_checkbox.xml b/core/res/res/layout/always_use_checkbox.xml
index a955352..16a1bb2d 100644
--- a/core/res/res/layout/always_use_checkbox.xml
+++ b/core/res/res/layout/always_use_checkbox.xml
@@ -20,8 +20,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:paddingLeft="14dip"
-    android:paddingRight="15dip"
+    android:paddingStart="14dip"
+    android:paddingEnd="15dip"
     android:orientation="vertical">
     
     <CheckBox
@@ -36,7 +36,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:textAppearance="?android:attr/textAppearanceSmall"
-        android:paddingLeft="36dip"
+        android:paddingStart="36dip"
         android:visibility="gone"
         android:text="@string/clearDefaultHintMsg" />
 </LinearLayout>
diff --git a/core/res/res/layout/am_compat_mode_dialog.xml b/core/res/res/layout/am_compat_mode_dialog.xml
index a8d39cf..8a0975d 100644
--- a/core/res/res/layout/am_compat_mode_dialog.xml
+++ b/core/res/res/layout/am_compat_mode_dialog.xml
@@ -17,7 +17,7 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent" android:layout_height="match_parent"
-        android:layout_marginLeft="40dp" android:layout_marginRight="40dp"
+        android:layout_marginStart="40dp" android:layout_marginEnd="40dp"
         android:layout_marginTop="15dp" android:layout_marginBottom="15dp"
         android:orientation="vertical">
     <LinearLayout
@@ -25,7 +25,7 @@
             android:layout_gravity="center_horizontal"
             android:orientation="horizontal" android:baselineAligned="true">
         <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
-                android:layout_marginLeft="10dp" android:layout_marginRight="10dp"
+                android:layout_marginStart="10dp" android:layout_marginEnd="10dp"
                 android:textColor="?android:attr/textColorPrimary"
                 android:textSize="18sp"
                 android:text="@string/screen_compat_mode_scale"
@@ -35,7 +35,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_vertical"
-                android:layout_marginRight="10dp"
+                android:layout_marginEnd="10dp"
                 />
     </LinearLayout>
 
diff --git a/core/res/res/layout/app_permission_item.xml b/core/res/res/layout/app_permission_item.xml
index 1bd267f..e2ffffb 100644
--- a/core/res/res/layout/app_permission_item.xml
+++ b/core/res/res/layout/app_permission_item.xml
@@ -16,40 +16,35 @@
 
 <!--
   Defines the layout of a single permission item.
-  Contains the group name and a list of permission labels under the group.
 -->
 
-<RelativeLayout
+<view class="android.widget.AppSecurityPermissions$PermissionItemView"
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content">
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:background="?android:attr/selectableItemBackground">
 
     <ImageView
         android:id="@+id/perm_icon"
-        android:layout_width="30dip"
-        android:layout_height="30dip"
-        android:layout_alignParentLeft="true" 
+        android:layout_width="32dp"
+        android:layout_height="32dp"
+        android:layout_marginStart="16dp"
+        android:layout_marginEnd="8dp"
         android:scaleType="fitCenter" />
 
-
-    <TextView
-        android:id="@+id/permission_group"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textStyle="bold"
-        android:paddingLeft="6dip"
-        android:layout_toRightOf="@id/perm_icon"
+    <ImageView
         android:layout_width="wrap_content"
-        android:layout_height="wrap_content" />
+        android:layout_height="match_parent"
+        android:background="?android:attr/dividerVertical" />
 
     <TextView
-        android:id="@+id/permission_list"
+        android:id="@+id/perm_name"
         android:textAppearance="?android:attr/textAppearanceSmall"
-        android:layout_marginTop="-4dip"
-        android:paddingBottom="8dip"
-        android:paddingLeft="6dip"
-        android:layout_below="@id/permission_group"
-        android:layout_toRightOf="@id/perm_icon"
+        android:textSize="16sp"
+        android:layout_marginStart="8dp"
         android:layout_width="wrap_content"
-        android:layout_height="wrap_content" />
+        android:layout_height="wrap_content"
+        android:layout_gravity="top|left" />
 
-</RelativeLayout>
+</view>
diff --git a/core/res/res/layout/app_permission_item_money.xml b/core/res/res/layout/app_permission_item_money.xml
new file mode 100644
index 0000000..3fa4653
--- /dev/null
+++ b/core/res/res/layout/app_permission_item_money.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!--
+  Defines the layout of a single permission item that costs money.
+-->
+
+<view class="android.widget.AppSecurityPermissions$PermissionItemView"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:background="?android:attr/selectableItemBackground">
+
+    <ImageView
+        android:id="@+id/perm_icon"
+        android:layout_width="32dp"
+        android:layout_height="32dp"
+        android:layout_marginStart="16dp"
+        android:layout_marginEnd="8dp"
+        android:scaleType="fitCenter" />
+
+    <ImageView
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:background="?android:attr/dividerVertical" />
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="8dp">
+        <TextView
+            android:id="@+id/perm_name"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textSize="16sp"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentStart="true"
+            android:layout_alignParentTop="true" />
+        <ImageView
+            android:id="@+id/perm_money_icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentStart="true"
+            android:layout_alignBottom="@+id/perm_money_label"
+            android:scaleType="fitCenter"
+            android:src="@android:drawable/ic_coins_s" />
+        <TextView
+            android:id="@+id/perm_money_label"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textSize="16sp"
+            android:textColor="@color/perms_costs_money"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_toEndOf="@id/perm_money_icon"
+            android:layout_below="@id/perm_name"
+            android:layout_marginStart="8dp"
+            android:text="@string/perm_costs_money" />
+    </RelativeLayout>
+
+</view>
diff --git a/core/res/res/layout/app_permission_item_old.xml b/core/res/res/layout/app_permission_item_old.xml
index 1bd267f..ce0cd42 100644
--- a/core/res/res/layout/app_permission_item_old.xml
+++ b/core/res/res/layout/app_permission_item_old.xml
@@ -28,7 +28,7 @@
         android:id="@+id/perm_icon"
         android:layout_width="30dip"
         android:layout_height="30dip"
-        android:layout_alignParentLeft="true" 
+        android:layout_alignParentStart="true"
         android:scaleType="fitCenter" />
 
 
@@ -36,8 +36,8 @@
         android:id="@+id/permission_group"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textStyle="bold"
-        android:paddingLeft="6dip"
-        android:layout_toRightOf="@id/perm_icon"
+        android:paddingStart="6dip"
+        android:layout_toEndOf="@id/perm_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
@@ -46,9 +46,9 @@
         android:textAppearance="?android:attr/textAppearanceSmall"
         android:layout_marginTop="-4dip"
         android:paddingBottom="8dip"
-        android:paddingLeft="6dip"
+        android:paddingStart="6dip"
         android:layout_below="@id/permission_group"
-        android:layout_toRightOf="@id/perm_icon"
+        android:layout_toEndOf="@id/perm_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
diff --git a/core/res/res/layout/app_perms_summary.xml b/core/res/res/layout/app_perms_summary.xml
index 3f99dde..b8d93ac 100755
--- a/core/res/res/layout/app_perms_summary.xml
+++ b/core/res/res/layout/app_perms_summary.xml
@@ -26,79 +26,17 @@
         android:id="@+id/no_permissions"
         android:text="@string/no_permissions"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:paddingLeft="16dip"
-        android:paddingRight="12dip"
+        android:paddingStart="8dp"
+        android:paddingEnd="8dp"
         android:visibility="gone"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
-    <!-- List view containing list of dangerous permissions categorized by groups. -->
+    <!-- Populated with all permissions. -->
     <LinearLayout
-        android:id="@+id/dangerous_perms_list"
+        android:id="@+id/perms_list"
         android:orientation="vertical"
         android:layout_width="match_parent"
-        android:paddingLeft="16dip"
-        android:paddingRight="12dip"
-        android:layout_height="wrap_content" />
-
-    <!-- Clickable area letting user display additional permissions. -->
-    <LinearLayout
-        android:id="@+id/show_more"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:visibility="gone"
-        android:layout_marginTop="12dip"
-        android:layout_marginBottom="16dip">
-
-        <View
-            android:layout_width="match_parent"
-            android:layout_height="1dip"
-            android:background="?android:attr/listDivider" />
-
-        <LinearLayout
-            android:orientation="horizontal"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingTop="16dip"
-            android:paddingBottom="12dip"
-            android:paddingLeft="16dip"
-            android:duplicateParentState="true"
-            android:background="?android:attr/selectableItemBackground">
-
-            <TextView
-                android:id="@+id/show_more_text"
-                android:textAppearance="?android:attr/textAppearanceMedium"
-                android:duplicateParentState="true"
-                android:layout_alignTop="@+id/show_more_icon"
-                android:layout_gravity="center_vertical"
-                android:paddingLeft="36dip"
-                android:layout_weight="1"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
-
-            <ImageView
-                android:id="@id/show_more_icon"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginRight="12dip" />
-
-        </LinearLayout>
-
-        <View
-            android:layout_width="match_parent"
-            android:layout_height="1dip"
-            android:background="?android:attr/listDivider" />
-
-    </LinearLayout>
-
-    <!-- List view containing list of permissions that aren't dangerous. -->
-    <LinearLayout
-        android:id="@+id/non_dangerous_perms_list"
-        android:orientation="vertical"
-        android:paddingLeft="16dip"
-        android:paddingRight="12dip"
-        android:layout_width="match_parent"
         android:layout_height="wrap_content" />
 
 </LinearLayout>
diff --git a/core/res/res/layout/auto_complete_list.xml b/core/res/res/layout/auto_complete_list.xml
index 8ad5dbb..72beb2b 100644
--- a/core/res/res/layout/auto_complete_list.xml
+++ b/core/res/res/layout/auto_complete_list.xml
@@ -27,7 +27,7 @@
         android:orientation="vertical"
         android:layout_width="match_parent" 
         android:layout_height="wrap_content"
-        android:paddingRight="0dip"
+        android:paddingEnd="0dip"
     />
 
     <AutoCompleteTextView android:id="@+id/edit"
diff --git a/core/res/res/layout/browser_link_context_header.xml b/core/res/res/layout/browser_link_context_header.xml
index b09ee1f..fef01b3 100644
--- a/core/res/res/layout/browser_link_context_header.xml
+++ b/core/res/res/layout/browser_link_context_header.xml
@@ -21,6 +21,6 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:maxLines="2"
-    android:paddingLeft="10dip"
-    android:paddingRight="10dip"
+    android:paddingStart="10dip"
+    android:paddingEnd="10dip"
     />
diff --git a/core/res/res/layout/calendar_view.xml b/core/res/res/layout/calendar_view.xml
index 176bb8b..bccb056 100644
--- a/core/res/res/layout/calendar_view.xml
+++ b/core/res/res/layout/calendar_view.xml
@@ -35,8 +35,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="6dip"
-        android:layout_marginRight="2dip"
-        android:layout_marginLeft="2dip"
+        android:layout_marginEnd="2dip"
+        android:layout_marginStart="2dip"
         android:gravity="center" >
 
         <TextView android:layout_width="0dip"
diff --git a/core/res/res/layout/character_picker.xml b/core/res/res/layout/character_picker.xml
index 2508f72..3ddbbb2c 100644
--- a/core/res/res/layout/character_picker.xml
+++ b/core/res/res/layout/character_picker.xml
@@ -28,7 +28,7 @@
         android:padding="4dp"
         android:verticalSpacing="8dp"
         android:horizontalSpacing="8dp"
-        android:gravity="left"
+        android:gravity="start"
         android:drawSelectorOnTop="false"
         android:numColumns="4"
         android:columnWidth="48dp"
@@ -41,8 +41,8 @@
         android:id="@+id/cancel"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="12dp"
-        android:layout_marginRight="12dp"
+        android:layout_marginStart="12dp"
+        android:layout_marginEnd="12dp"
         android:background="@drawable/btn_close"
         android:layout_gravity="center_vertical"
     />
diff --git a/core/res/res/layout/choose_account.xml b/core/res/res/layout/choose_account.xml
index c37a949..45a944e 100644
--- a/core/res/res/layout/choose_account.xml
+++ b/core/res/res/layout/choose_account.xml
@@ -21,8 +21,8 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip">
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip">
 
     <ListView xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@android:id/list"
diff --git a/core/res/res/layout/choose_account_row.xml b/core/res/res/layout/choose_account_row.xml
index 33764a3..c4247b6 100644
--- a/core/res/res/layout/choose_account_row.xml
+++ b/core/res/res/layout/choose_account_row.xml
@@ -18,14 +18,14 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:orientation="horizontal" >
 
    <ImageView android:id="@+id/account_row_icon"
         android:layout_width="wrap_content"
         android:layout_height="fill_parent"
-        android:paddingRight="8dip" />
+        android:paddingEnd="8dip" />
 
     <TextView xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/account_row_text"
diff --git a/core/res/res/layout/choose_account_type.xml b/core/res/res/layout/choose_account_type.xml
index db96dc1..87d1dde 100644
--- a/core/res/res/layout/choose_account_type.xml
+++ b/core/res/res/layout/choose_account_type.xml
@@ -20,20 +20,7 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip">
-
-    <TextView android:id="@+id/title"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:layout_gravity="left"
-        android:text="@string/add_account_label"
-        android:paddingTop="16dip"
-        android:paddingBottom="16dip"
-        android:textColor="@android:color/holo_blue_light"
-    />
+    android:orientation="vertical">
 
     <View android:layout_height="3dip"
           android:layout_width="match_parent"
diff --git a/core/res/res/layout/choose_type_and_account.xml b/core/res/res/layout/choose_type_and_account.xml
index 9d1d284..bf06054 100644
--- a/core/res/res/layout/choose_type_and_account.xml
+++ b/core/res/res/layout/choose_type_and_account.xml
@@ -27,11 +27,11 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:layout_gravity="left|center_vertical"
+        android:layout_gravity="start|center_vertical"
         android:paddingTop="16dip"
         android:paddingBottom="16dip"
-        android:paddingLeft="16dip"
-        android:paddingRight="16dip"
+        android:paddingStart="16dip"
+        android:paddingEnd="16dip"
     />
 
     <!-- List of accounts, with "Add new account" as the last item -->
diff --git a/core/res/res/layout/date_picker.xml b/core/res/res/layout/date_picker.xml
index 9c1def2..303ab30 100644
--- a/core/res/res/layout/date_picker.xml
+++ b/core/res/res/layout/date_picker.xml
@@ -41,8 +41,8 @@
             android:id="@+id/month"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="1dip"
-            android:layout_marginRight="1dip"
+            android:layout_marginStart="1dip"
+            android:layout_marginEnd="1dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -52,8 +52,8 @@
             android:id="@+id/day"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="1dip"
-            android:layout_marginRight="1dip"
+            android:layout_marginStart="1dip"
+            android:layout_marginEnd="1dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -63,8 +63,8 @@
             android:id="@+id/year"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="1dip"
-            android:layout_marginRight="1dip"
+            android:layout_marginStart="1dip"
+            android:layout_marginEnd="1dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -76,7 +76,7 @@
         android:id="@+id/calendar_view"
         android:layout_width="245dip"
         android:layout_height="280dip"
-        android:layout_marginLeft="44dip"
+        android:layout_marginStart="44dip"
         android:layout_weight="1"
         android:focusable="true"
         android:focusableInTouchMode="true"
diff --git a/core/res/res/layout/date_picker_holo.xml b/core/res/res/layout/date_picker_holo.xml
index 8008682..b465d97 100644
--- a/core/res/res/layout/date_picker_holo.xml
+++ b/core/res/res/layout/date_picker_holo.xml
@@ -43,8 +43,8 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="16dip"
             android:layout_marginBottom="16dip"
-            android:layout_marginLeft="8dip"
-            android:layout_marginRight="8dip"
+            android:layout_marginStart="8dip"
+            android:layout_marginEnd="8dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -56,8 +56,8 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="16dip"
             android:layout_marginBottom="16dip"
-            android:layout_marginLeft="8dip"
-            android:layout_marginRight="8dip"
+            android:layout_marginStart="8dip"
+            android:layout_marginEnd="8dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -69,8 +69,8 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="16dip"
             android:layout_marginBottom="16dip"
-            android:layout_marginLeft="8dip"
-            android:layout_marginRight="16dip"
+            android:layout_marginStart="8dip"
+            android:layout_marginEnd="16dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -82,8 +82,8 @@
         android:id="@+id/calendar_view"
         android:layout_width="245dip"
         android:layout_height="280dip"
-        android:layout_marginLeft="16dip"
-        android:layout_marginRight="16dip"
+        android:layout_marginStart="16dip"
+        android:layout_marginEnd="16dip"
         android:layout_weight="1"
         android:focusable="true"
         android:focusableInTouchMode="true"
diff --git a/core/res/res/layout/default_navigation.xml b/core/res/res/layout/default_navigation.xml
new file mode 100644
index 0000000..b216ded
--- /dev/null
+++ b/core/res/res/layout/default_navigation.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_click_area"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:gravity="center">
+
+    <!-- message area for security screen -->
+    <TextView
+        android:id="@+id/keyguard_message_area"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="start"
+        android:ellipsize="marquee"
+        android:layout_marginEnd="4dip"
+        android:layout_marginStart="4dip"
+        android:textSize="22dip"
+        android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/dialog_custom_title.xml b/core/res/res/layout/dialog_custom_title.xml
index 3784c59..2dda5e5 100644
--- a/core/res/res/layout/dialog_custom_title.xml
+++ b/core/res/res/layout/dialog_custom_title.xml
@@ -37,8 +37,8 @@
             android:layout_height="match_parent"
             android:paddingTop="6dip"
             android:paddingBottom="10dip"
-            android:paddingLeft="10dip"
-            android:paddingRight="10dip" />
+            android:paddingStart="10dip"
+            android:paddingEnd="10dip" />
     </FrameLayout>
 </LinearLayout>
 
diff --git a/core/res/res/layout/dialog_custom_title_holo.xml b/core/res/res/layout/dialog_custom_title_holo.xml
index cf71197..f8a2bf7 100644
--- a/core/res/res/layout/dialog_custom_title_holo.xml
+++ b/core/res/res/layout/dialog_custom_title_holo.xml
@@ -25,7 +25,7 @@
         android:layout_width="match_parent"
         android:layout_height="@dimen/alert_dialog_title_height"
         android:layout_weight="0"
-        android:gravity="center_vertical|left"
+        android:gravity="center_vertical|start"
         style="?android:attr/windowTitleBackgroundStyle">
     </FrameLayout>
     <View android:id="@+id/titleDivider"
diff --git a/core/res/res/layout/dialog_title.xml b/core/res/res/layout/dialog_title.xml
index 949f86e..40eb385 100644
--- a/core/res/res/layout/dialog_title.xml
+++ b/core/res/res/layout/dialog_title.xml
@@ -30,8 +30,8 @@
         android:minHeight="53dip"
         android:paddingTop="9dip"
         android:paddingBottom="9dip"
-        android:paddingLeft="10dip"
-        android:paddingRight="10dip" />
+        android:paddingStart="10dip"
+        android:paddingEnd="10dip" />
     <FrameLayout
         android:layout_width="match_parent" android:layout_height="wrap_content"
         android:layout_weight="1"
diff --git a/core/res/res/layout/dialog_title_holo.xml b/core/res/res/layout/dialog_title_holo.xml
index 50bb0ba..0a692ee 100644
--- a/core/res/res/layout/dialog_title_holo.xml
+++ b/core/res/res/layout/dialog_title_holo.xml
@@ -27,9 +27,9 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:minHeight="@android:dimen/alert_dialog_title_height"
-        android:paddingLeft="16dip"
-        android:paddingRight="16dip"
-        android:gravity="center_vertical|left" />
+        android:paddingStart="16dip"
+        android:paddingEnd="16dip"
+        android:gravity="center_vertical|start" />
     <View android:id="@+id/titleDivider"
             android:layout_width="match_parent"
             android:layout_height="2dip"
diff --git a/core/res/res/layout/dialog_title_icons.xml b/core/res/res/layout/dialog_title_icons.xml
index 0ca6706..a86a76c 100644
--- a/core/res/res/layout/dialog_title_icons.xml
+++ b/core/res/res/layout/dialog_title_icons.xml
@@ -31,8 +31,8 @@
         android:minHeight="53dip"
         android:paddingTop="6dip"
         android:paddingBottom="9dip"
-        android:paddingLeft="10dip"
-        android:paddingRight="10dip">
+        android:paddingStart="10dip"
+        android:paddingEnd="10dip">
         <ImageView android:id="@+id/left_icon"
             android:layout_width="32dip"
             android:layout_height="32dip"
@@ -46,8 +46,8 @@
             android:layout_weight="0"
             android:paddingTop="2dip"
             android:paddingBottom="1dip"
-            android:paddingLeft="14dip"
-            android:paddingRight="14dip" />
+            android:paddingStart="14dip"
+            android:paddingEnd="14dip" />
         <ImageView android:id="@+id/right_icon"
             android:layout_width="32dip"
             android:layout_height="32dip"
diff --git a/core/res/res/layout/dialog_title_icons_holo.xml b/core/res/res/layout/dialog_title_icons_holo.xml
index 7d7959f..e3d771c 100644
--- a/core/res/res/layout/dialog_title_icons_holo.xml
+++ b/core/res/res/layout/dialog_title_icons_holo.xml
@@ -29,13 +29,13 @@
         android:orientation="horizontal"
         android:gravity="center_vertical"
         android:minHeight="@android:dimen/alert_dialog_title_height"
-        android:paddingLeft="16dip"
-        android:paddingRight="16dip">
+        android:paddingStart="16dip"
+        android:paddingEnd="16dip">
         <ImageView android:id="@+id/left_icon"
             android:layout_width="32dip"
             android:layout_height="32dip"
             android:scaleType="fitCenter"
-            android:layout_marginRight="8dip" />
+            android:layout_marginEnd="8dip" />
         <TextView android:id="@android:id/title"
             style="?android:attr/windowTitleStyle"
             android:layout_width="wrap_content"
@@ -45,7 +45,7 @@
             android:layout_width="32dip"
             android:layout_height="32dip"
             android:scaleType="fitCenter"
-            android:layout_marginLeft="8dip" />
+            android:layout_marginStart="8dip" />
     </LinearLayout>
 
     <View android:id="@+id/titleDivider"
diff --git a/core/res/res/layout/fragment_bread_crumb_item.xml b/core/res/res/layout/fragment_bread_crumb_item.xml
index dbbb9a5..ee4344f 100644
--- a/core/res/res/layout/fragment_bread_crumb_item.xml
+++ b/core/res/res/layout/fragment_bread_crumb_item.xml
@@ -32,8 +32,8 @@
             android:id="@+id/title"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:paddingLeft="8dip"
-            android:paddingRight="8dip"
+            android:paddingStart="8dip"
+            android:paddingEnd="8dip"
             android:gravity="center_vertical"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:background="?android:attr/selectableItemBackground"
diff --git a/core/res/res/layout/global_actions_item.xml b/core/res/res/layout/global_actions_item.xml
index 694301e..b3a5aa2 100644
--- a/core/res/res/layout/global_actions_item.xml
+++ b/core/res/res/layout/global_actions_item.xml
@@ -22,16 +22,16 @@
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:orientation="horizontal"
 
-    android:paddingLeft="16dip"
+    android:paddingStart="8dip"
     android:paddingTop="6dip"
     android:paddingBottom="6dip"
     >
     <ImageView android:id="@+id/icon"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
+        android:layout_width="56dp"
+        android:layout_height="56dp"
         android:layout_gravity="center"
-        android:layout_marginRight="16dip"
-        />
+        android:layout_marginEnd="8dip"
+        android:scaleType="center"/>
 
     <LinearLayout
         android:orientation="vertical"
diff --git a/core/res/res/layout/global_actions_silent_mode.xml b/core/res/res/layout/global_actions_silent_mode.xml
index 18b4715..79401af 100644
--- a/core/res/res/layout/global_actions_silent_mode.xml
+++ b/core/res/res/layout/global_actions_silent_mode.xml
@@ -33,8 +33,8 @@
             android:layout_width="48dp"
             android:layout_height="match_parent"
             android:layout_gravity="center"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:layout_marginTop="6dp"
             android:layout_marginBottom="6dp"
             android:src="@drawable/ic_audio_vol_mute"
@@ -61,8 +61,8 @@
             android:layout_width="48dp"
             android:layout_height="match_parent"
             android:layout_gravity="center"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:layout_marginTop="6dp"
             android:layout_marginBottom="6dp"
             android:src="@drawable/ic_audio_ring_notif_vibrate"
@@ -90,8 +90,8 @@
             android:layout_width="48dp"
             android:layout_height="match_parent"
             android:layout_gravity="center"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:layout_marginTop="6dp"
             android:layout_marginBottom="6dp"
             android:src="@drawable/ic_audio_vol"
diff --git a/core/res/res/layout/grant_credentials_permission.xml b/core/res/res/layout/grant_credentials_permission.xml
index dd85b33..e7ec539 100644
--- a/core/res/res/layout/grant_credentials_permission.xml
+++ b/core/res/res/layout/grant_credentials_permission.xml
@@ -47,20 +47,20 @@
                 android:layout_height="wrap_content"
                 android:text="@string/grant_credentials_permission_message_header"
                 android:textAppearance="?android:attr/textAppearanceMedium"
-                android:paddingLeft="19dip"
+                android:paddingStart="19dip"
                 android:paddingBottom="12dip" />
 
             <LinearLayout
                 android:id="@+id/packages_list"
                 android:orientation="vertical"
-                android:paddingLeft="16dip"
-                android:paddingRight="12dip"
+                android:paddingStart="16dip"
+                android:paddingEnd="12dip"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content" />
 
             <RelativeLayout
-                android:paddingLeft="16dip"
-                android:paddingRight="12dip"
+                android:paddingStart="16dip"
+                android:paddingEnd="12dip"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content">
 
@@ -69,7 +69,7 @@
                     android:layout_width="30dip"
                     android:layout_height="30dip"
                     android:src="@drawable/ic_bullet_key_permission"
-                    android:layout_alignParentLeft="true"
+                    android:layout_alignParentStart="true"
                     android:scaleType="fitCenter" />
 
                 <TextView
@@ -77,8 +77,8 @@
                     android:textAppearance="?android:attr/textAppearanceMedium"
                     android:textColor="@color/perms_dangerous_perm_color"
                     android:textStyle="bold"
-                    android:paddingLeft="16dip"
-                    android:layout_toRightOf="@id/permission_icon"
+                    android:paddingStart="16dip"
+                    android:layout_toEndOf="@id/permission_icon"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content" />
 
@@ -88,9 +88,9 @@
                     android:textColor="@color/perms_dangerous_perm_color"
                     android:layout_marginTop="-4dip"
                     android:paddingBottom="8dip"
-                    android:paddingLeft="16dip"
+                    android:paddingStart="16dip"
                     android:layout_below="@id/account_type"
-                    android:layout_toRightOf="@id/permission_icon"
+                    android:layout_toEndOf="@id/permission_icon"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content" />
 
@@ -101,9 +101,9 @@
                     android:textStyle="bold"
                     android:layout_marginTop="-4dip"
                     android:paddingBottom="8dip"
-                    android:paddingLeft="16dip"
+                    android:paddingStart="16dip"
                     android:layout_below="@id/account_name"
-                    android:layout_toRightOf="@id/permission_icon"
+                    android:layout_toEndOf="@id/permission_icon"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content" />
             </RelativeLayout>
@@ -114,7 +114,7 @@
                 android:layout_height="wrap_content"
                 android:text="@string/grant_credentials_permission_message_footer"
                 android:textAppearance="?android:attr/textAppearanceMedium"
-                android:paddingLeft="19dip"
+                android:paddingStart="19dip"
                 android:paddingBottom="12dip" />
         </LinearLayout>
     </ScrollView>
diff --git a/core/res/res/layout/heavy_weight_switcher.xml b/core/res/res/layout/heavy_weight_switcher.xml
index 9acf009..c17e555 100644
--- a/core/res/res/layout/heavy_weight_switcher.xml
+++ b/core/res/res/layout/heavy_weight_switcher.xml
@@ -36,8 +36,8 @@
         android:minHeight="?android:attr/listPreferredItemHeight"
         android:orientation="horizontal"
         android:background="@android:drawable/list_selector_background"
-        android:paddingRight="3dip"
-        android:paddingLeft="3dip"
+        android:paddingEnd="3dip"
+        android:paddingStart="3dip"
         android:paddingTop="5dip"
         android:paddingBottom="14dip"
         android:gravity="center_vertical"
@@ -46,7 +46,7 @@
         <ImageView android:id="@+id/old_app_icon"
             android:layout_width="@android:dimen/app_icon_size"
             android:layout_height="@android:dimen/app_icon_size"
-            android:layout_marginRight="11dip"
+            android:layout_marginEnd="11dip"
             android:layout_gravity="center_vertical"
             android:scaleType="fitCenter"/>
     
@@ -84,8 +84,8 @@
         android:minHeight="?android:attr/listPreferredItemHeight"
         android:orientation="horizontal"
         android:background="@android:drawable/list_selector_background"
-        android:paddingRight="3dip"
-        android:paddingLeft="3dip"
+        android:paddingEnd="3dip"
+        android:paddingStart="3dip"
         android:paddingTop="5dip"
         android:paddingBottom="8dip"
         android:gravity="center_vertical"
@@ -94,7 +94,7 @@
         <ImageView android:id="@+id/new_app_icon"
             android:layout_width="@android:dimen/app_icon_size"
             android:layout_height="@android:dimen/app_icon_size"
-            android:layout_marginRight="11dip"
+            android:layout_marginEnd="11dip"
             android:layout_gravity="center_vertical"
             android:scaleType="fitCenter"/>
     
@@ -132,8 +132,8 @@
         android:minHeight="?android:attr/listPreferredItemHeight"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:background="@android:drawable/list_selector_background"
-        android:paddingRight="6dip"
-        android:paddingLeft="6dip"
+        android:paddingEnd="6dip"
+        android:paddingStart="6dip"
         android:paddingTop="5dip"
         android:paddingBottom="8dip"
         android:textStyle="bold"
diff --git a/core/res/res/layout/icon_menu_item_layout.xml b/core/res/res/layout/icon_menu_item_layout.xml
index a73dccc..cdb5bfa 100644
--- a/core/res/res/layout/icon_menu_item_layout.xml
+++ b/core/res/res/layout/icon_menu_item_layout.xml
@@ -19,8 +19,8 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:paddingBottom="1dip"
-    android:paddingLeft="3dip"
-    android:paddingRight="3dip"
+    android:paddingStart="3dip"
+    android:paddingEnd="3dip"
     android:singleLine="true"
     android:ellipsize="marquee"
     android:fadingEdge="horizontal" />
diff --git a/core/res/res/layout/input_method_extract_view.xml b/core/res/res/layout/input_method_extract_view.xml
index a3e4961..269ff85 100644
--- a/core/res/res/layout/input_method_extract_view.xml
+++ b/core/res/res/layout/input_method_extract_view.xml
@@ -38,8 +38,8 @@
             android:id="@+id/inputExtractAccessories"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:paddingLeft="8dip"
-            android:paddingRight="8dip"
+            android:paddingStart="8dip"
+            android:paddingEnd="8dip"
         >
         
         <android.inputmethodservice.ExtractButton android:id="@+id/inputExtractAction"
diff --git a/core/res/res/layout/input_method_switch_dialog_title.xml b/core/res/res/layout/input_method_switch_dialog_title.xml
index 7032bd3..e11a523 100644
--- a/core/res/res/layout/input_method_switch_dialog_title.xml
+++ b/core/res/res/layout/input_method_switch_dialog_title.xml
@@ -25,8 +25,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="9dip"
-        android:layout_marginLeft="20dip"
-        android:layout_marginRight="10dip"
+        android:layout_marginStart="20dip"
+        android:layout_marginEnd="10dip"
         android:layout_marginTop="6dip"
         android:gravity="center_vertical"
         android:orientation="vertical" >
@@ -69,8 +69,8 @@
                 android:minHeight="?android:attr/listPreferredItemHeightSmall"
                 android:orientation="vertical"
                 android:paddingBottom="5dip"
-                android:paddingLeft="16dip"
-                android:paddingRight="0dip"
+                android:paddingStart="16dip"
+                android:paddingEnd="0dip"
                 android:paddingTop="5dip" >
 
                 <TextView
@@ -95,7 +95,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_vertical"
-                android:layout_marginRight="12dip" />
+                android:layout_marginEnd="12dip" />
         </LinearLayout>
     </LinearLayout>
 
diff --git a/core/res/res/layout/keyboard_popup_keyboard.xml b/core/res/res/layout/keyboard_popup_keyboard.xml
index 5eb2732..6f222bf 100644
--- a/core/res/res/layout/keyboard_popup_keyboard.xml
+++ b/core/res/res/layout/keyboard_popup_keyboard.xml
@@ -41,7 +41,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
-        android:layout_marginLeft="8dp"
+        android:layout_marginStart="8dp"
         android:clickable="true"
         />
 </LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/keyguard.xml b/core/res/res/layout/keyguard.xml
index ca629f8..f8f482d 100644
--- a/core/res/res/layout/keyguard.xml
+++ b/core/res/res/layout/keyguard.xml
@@ -19,9 +19,9 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
-    android:paddingLeft="20dip"
+    android:paddingStart="20dip"
     android:paddingTop="20dip"
-    android:paddingRight="20dip"
+    android:paddingEnd="20dip"
     android:paddingBottom="20dip"
     android:orientation="vertical" 
     android:layout_width="wrap_content"
diff --git a/core/res/res/layout/keyguard_account_view.xml b/core/res/res/layout/keyguard_account_view.xml
new file mode 100644
index 0000000..fa36371
--- /dev/null
+++ b/core/res/res/layout/keyguard_account_view.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<com.android.internal.policy.impl.keyguard.KeyguardAccountView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_account_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_maxWidth="@dimen/keyguard_security_width"
+    android:layout_maxHeight="@dimen/keyguard_security_height"
+    android:orientation="vertical">
+
+    <include layout="@layout/keyguard_message_area"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1">
+
+        <EditText
+            android:id="@+id/login"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="8dip"
+            android:layout_marginStart="7dip"
+            android:layout_marginEnd="7dip"
+            android:layout_alignParentTop="true"
+            android:hint="@string/kg_login_username_hint"
+            android:inputType="textEmailAddress"
+            />
+
+        <EditText
+            android:id="@+id/password"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/login"
+            android:layout_toLeftOf="@+id/ok"
+            android:layout_marginTop="15dip"
+            android:layout_marginStart="7dip"
+            android:layout_marginEnd="7dip"
+            android:inputType="textPassword"
+            android:hint="@string/kg_login_password_hint"
+            android:nextFocusRight="@+id/ok"
+            android:nextFocusDown="@+id/ok"
+            />
+
+        <!-- ok below password, aligned to right of screen -->
+        <Button
+            android:id="@+id/ok"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_margin="7dip"
+            android:layout_alignParentEnd="true"
+            android:layout_below="@id/login"
+            android:text="@string/kg_login_submit_button"
+            />
+
+    </RelativeLayout>
+
+    <!--  no room for ECA on this screen right now
+    <include layout="@layout/keyguard_eca"
+        android:id="@+id/keyguard_selector_fade_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:layout_gravity="bottom|center_horizontal"
+        android:gravity="center_horizontal" />
+    -->
+
+</com.android.internal.policy.impl.keyguard.KeyguardAccountView>
diff --git a/core/res/res/layout/keyguard_add_widget.xml b/core/res/res/layout/keyguard_add_widget.xml
new file mode 100644
index 0000000..db166ac
--- /dev/null
+++ b/core/res/res/layout/keyguard_add_widget.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<!-- This is a view that shows general status information in Keyguard. -->
+<com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_add_widget"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+    <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:contentDescription="@string/keyguard_accessibility_widget_empty_slot"
+            >
+        <ImageView
+            android:id="@+id/keyguard_add_widget_view"
+            android:clickable="true"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:padding="24dp"
+            android:src="@drawable/kg_add_widget"
+            android:contentDescription="@string/keyguard_accessibility_add_widget"/>
+    </FrameLayout>
+</com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame>
diff --git a/core/res/res/layout/keyguard_emergency_carrier_area.xml b/core/res/res/layout/keyguard_emergency_carrier_area.xml
new file mode 100644
index 0000000..52adc04
--- /dev/null
+++ b/core/res/res/layout/keyguard_emergency_carrier_area.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This contains emergency call button and carrier as shared by pin/pattern/password screens -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:gravity="center"
+    android:layout_gravity="center_horizontal"
+    android:layout_alignParentBottom="true"
+    android:clickable="true">
+
+    <com.android.internal.policy.impl.keyguard.CarrierText
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/kg_status_line_font_size"
+        android:textColor="?android:attr/textColorSecondary"/>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="-10dip"
+        style="?android:attr/buttonBarStyle"
+        android:orientation="horizontal"
+        android:gravity="center"
+        android:weightSum="2">
+
+        <com.android.internal.policy.impl.keyguard.EmergencyButton
+            android:id="@+id/emergency_call_button"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:drawableLeft="@*android:drawable/lockscreen_emergency_button"
+            android:text="@string/kg_emergency_call_label"
+            style="?android:attr/buttonBarButtonStyle"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="@dimen/kg_status_line_font_size"
+            android:textColor="?android:attr/textColorSecondary"
+            android:drawablePadding="8dip" />
+
+        <Button android:id="@+id/forgot_password_button"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:drawableLeft="@*android:drawable/lockscreen_forgot_password_button"
+            style="?android:attr/buttonBarButtonStyle"
+            android:textSize="@dimen/kg_status_line_font_size"
+            android:textColor="?android:attr/textColorSecondary"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:drawablePadding="8dip"
+            android:visibility="gone"/>
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/core/res/res/layout/keyguard_emergency_carrier_area_empty.xml b/core/res/res/layout/keyguard_emergency_carrier_area_empty.xml
new file mode 100644
index 0000000..2f4adae
--- /dev/null
+++ b/core/res/res/layout/keyguard_emergency_carrier_area_empty.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is a blank layout to simplify implementation on landscape on phones
+     it is referenced indirectly by keyguard_eca -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="0dip"
+    android:layout_height="0dip"
+    android:orientation="vertical"
+    android:gravity="center"
+    android:layout_gravity="center_horizontal"
+    android:layout_alignParentBottom="true">
+
+</LinearLayout>
diff --git a/core/res/res/layout/keyguard_face_unlock_view.xml b/core/res/res/layout/keyguard_face_unlock_view.xml
new file mode 100644
index 0000000..c9f1176
--- /dev/null
+++ b/core/res/res/layout/keyguard_face_unlock_view.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is the screen that allows the user to unlock by showing their face.  -->
+<com.android.internal.policy.impl.keyguard.KeyguardFaceUnlockView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_face_unlock_view"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_maxWidth="@dimen/keyguard_security_width"
+    android:layout_maxHeight="@dimen/keyguard_security_height"
+    android:contentDescription="@string/keyguard_accessibility_face_unlock">
+
+    <include layout="@layout/keyguard_message_area"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        />
+
+    <FrameLayout
+       android:id="@+id/keyguard_bouncer_frame"
+       android:background="@*android:drawable/kg_bouncer_bg_white"
+       android:layout_width="match_parent"
+       android:layout_height="0dp"
+       android:layout_weight="1"
+       >
+       <com.android.internal.widget.FaceUnlockView
+           android:id="@+id/face_unlock_area_view"
+           android:layout_width="match_parent"
+           android:layout_height="match_parent"
+           android:layout_gravity="center_horizontal"
+           android:background="@*android:drawable/intro_bg"
+           android:gravity="center">
+
+           <View
+               android:id="@+id/spotlightMask"
+               android:layout_width="match_parent"
+               android:layout_height="match_parent"
+               android:background="@*android:color/facelock_spotlight_mask"
+           />
+
+           <ImageButton
+               android:id="@+id/face_unlock_cancel_button"
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:padding="5dip"
+               android:layout_alignParentTop="true"
+               android:layout_alignParentEnd="true"
+               android:background="#00000000"
+               android:src="@*android:drawable/ic_facial_backup"
+           />
+       </com.android.internal.widget.FaceUnlockView>
+    </FrameLayout>
+
+    <include layout="@layout/keyguard_eca"
+        android:id="@+id/keyguard_selector_fade_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:layout_gravity="bottom|center_horizontal"
+        android:gravity="center_horizontal" />
+</com.android.internal.policy.impl.keyguard.KeyguardFaceUnlockView>
diff --git a/core/res/res/layout/keyguard_glow_pad_container.xml b/core/res/res/layout/keyguard_glow_pad_container.xml
new file mode 100644
index 0000000..d86707f
--- /dev/null
+++ b/core/res/res/layout/keyguard_glow_pad_container.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <include layout="@layout/keyguard_glow_pad_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom|center_horizontal"
+        android:layout_marginBottom="-60dp"/>
+</merge>
\ No newline at end of file
diff --git a/core/res/res/layout/keyguard_glow_pad_view.xml b/core/res/res/layout/keyguard_glow_pad_view.xml
new file mode 100644
index 0000000..cfd8160
--- /dev/null
+++ b/core/res/res/layout/keyguard_glow_pad_view.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is the selector widget that allows the user to select an action. -->
+<com.android.internal.widget.multiwaveview.GlowPadView
+    xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/glow_pad_view"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:orientation="horizontal"
+    android:gravity="@integer/kg_selector_gravity"
+    android:contentDescription="@string/keyguard_accessibility_slide_area"
+
+    prvandroid:targetDrawables="@array/lockscreen_targets_unlock_only"
+    prvandroid:targetDescriptions="@array/lockscreen_target_descriptions_unlock_only"
+    prvandroid:directionDescriptions="@*android:array/lockscreen_direction_descriptions"
+    prvandroid:handleDrawable="@*android:drawable/ic_lockscreen_handle"
+    prvandroid:outerRingDrawable="@*android:drawable/ic_lockscreen_outerring"
+    prvandroid:outerRadius="@*android:dimen/glowpadview_target_placement_radius"
+    prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
+    prvandroid:snapMargin="@*android:dimen/glowpadview_snap_margin"
+    prvandroid:firstItemOffset="@integer/kg_glowpad_rotation_offset"
+    prvandroid:magneticTargets="true"
+    prvandroid:feedbackCount="1"
+    prvandroid:vibrationDuration="20"
+    prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius"
+    prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot"
+    prvandroid:allowScaling="true" />
diff --git a/core/res/res/layout/keyguard_message_area.xml b/core/res/res/layout/keyguard_message_area.xml
new file mode 100644
index 0000000..37463cf
--- /dev/null
+++ b/core/res/res/layout/keyguard_message_area.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This contains emergency call button and carrier as shared by pin/pattern/password screens -->
+<com.android.internal.policy.impl.keyguard.KeyguardMessageArea
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center"
+    android:id="@+id/keyguard_message_area"
+    android:singleLine="true"
+    android:ellipsize="marquee"
+    android:textAppearance="?android:attr/textAppearance"
+    android:textSize="@dimen/kg_status_line_font_size"
+    android:textColor="?android:attr/textColorSecondary"
+    android:clickable="true" />
+
diff --git a/core/res/res/layout/keyguard_message_area_large.xml b/core/res/res/layout/keyguard_message_area_large.xml
new file mode 100644
index 0000000..584cec4
--- /dev/null
+++ b/core/res/res/layout/keyguard_message_area_large.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This contains emergency call button and carrier as shared by pin/pattern/password screens -->
+<com.android.internal.policy.impl.keyguard.KeyguardMessageArea
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center"
+    android:id="@+id/keyguard_message_area"
+    android:maxLines="4"
+    android:textAppearance="?android:attr/textAppearance"
+    android:textSize="@dimen/kg_status_line_font_size"
+    android:textColor="?android:attr/textColorSecondary" />
+
diff --git a/core/res/res/layout/keyguard_multi_user_avatar.xml b/core/res/res/layout/keyguard_multi_user_avatar.xml
new file mode 100644
index 0000000..2d8f02d
--- /dev/null
+++ b/core/res/res/layout/keyguard_multi_user_avatar.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<!-- This is a view that shows general status information in Keyguard. -->
+<com.android.internal.policy.impl.keyguard.KeyguardMultiUserAvatar
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="@dimen/keyguard_avatar_size"
+    android:layout_height="@dimen/keyguard_avatar_size"
+    android:background="#00000000"
+    android:gravity="center_horizontal">
+    <ImageView
+        android:id="@+id/keyguard_user_avatar"
+        android:scaleType="center"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_gravity="center"/>
+    <TextView
+       android:id="@+id/keyguard_user_name"
+       android:layout_width="match_parent"
+       android:layout_height="wrap_content"
+       android:layout_gravity="bottom"
+       android:gravity="center"
+       android:textSize="@dimen/keyguard_avatar_name_size"
+       android:textColor="#ffffff"
+       android:singleLine="true"
+       android:ellipsize="end"
+       android:paddingLeft="2dp"
+       android:paddingRight="2dp" />
+</com.android.internal.policy.impl.keyguard.KeyguardMultiUserAvatar>
diff --git a/core/res/res/layout/keyguard_multi_user_selector.xml b/core/res/res/layout/keyguard_multi_user_selector.xml
new file mode 100644
index 0000000..ee01285
--- /dev/null
+++ b/core/res/res/layout/keyguard_multi_user_selector.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+<com.android.internal.policy.impl.keyguard.KeyguardMultiUserSelectorView
+    xmlns:androidprv="http://schemas.android.com/apk/res/android"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    androidprv:layout_childType="userSwitcher"
+    android:id="@+id/keyguard_user_selector"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_gravity="bottom"
+    android:contentDescription="@*android:string/keyguard_accessibility_user_selector"
+    android:visibility="gone">
+
+    <com.android.internal.policy.impl.keyguard.KeyguardLinearLayout
+        android:id="@+id/keyguard_users_grid"
+        android:orientation="horizontal"
+        android:layout_width="wrap_content"
+        android:layout_marginBottom="@dimen/keyguard_muliuser_selector_margin"
+        android:layout_height="@dimen/keyguard_avatar_size"
+        android:layout_gravity="center|bottom" />
+
+</com.android.internal.policy.impl.keyguard.KeyguardMultiUserSelectorView>
diff --git a/core/res/res/layout/keyguard_multi_user_selector_widget.xml b/core/res/res/layout/keyguard_multi_user_selector_widget.xml
new file mode 100644
index 0000000..fc126fe
--- /dev/null
+++ b/core/res/res/layout/keyguard_multi_user_selector_widget.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<!-- This is a view that shows general status information in Keyguard. -->
+<com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_multi_user_selector"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+</com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame>
\ No newline at end of file
diff --git a/core/res/res/layout/keyguard_password_view.xml b/core/res/res/layout/keyguard_password_view.xml
new file mode 100644
index 0000000..aab54c3
--- /dev/null
+++ b/core/res/res/layout/keyguard_password_view.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+<com.android.internal.policy.impl.keyguard.KeyguardPasswordView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_password_view"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_maxWidth="@dimen/keyguard_security_width"
+    android:layout_maxHeight="@dimen/keyguard_security_height"
+    android:gravity="bottom"
+    android:contentDescription="@string/keyguard_accessibility_password_unlock"
+    >
+
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        />
+
+    <include layout="@layout/keyguard_message_area"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <!-- Password entry field -->
+    <!-- Note: the entire container is styled to look like the edit field,
+         since the backspace/IME switcher looks better inside -->
+      <FrameLayout
+         android:id="@+id/keyguard_bouncer_frame"
+         android:background="@*android:drawable/kg_bouncer_bg_white"
+         android:layout_height="wrap_content"
+         android:layout_width="match_parent"
+         >
+         <LinearLayout
+             android:layout_height="wrap_content"
+             android:layout_width="match_parent"
+             android:orientation="horizontal"
+             android:background="#70000000"
+             android:layout_marginTop="8dp"
+             android:layout_marginBottom="8dp"
+             >
+
+             <EditText android:id="@+id/passwordEntry"
+                 android:layout_width="0dip"
+                 android:layout_height="wrap_content"
+                 android:layout_weight="1"
+                 android:gravity="center_horizontal"
+                 android:layout_gravity="center_vertical"
+                 android:layout_marginStart="@*android:dimen/keyguard_lockscreen_pin_margin_left"
+                 android:singleLine="true"
+                 android:textStyle="normal"
+                 android:inputType="textPassword"
+                 android:textSize="36sp"
+                 android:background="@null"
+                 android:textAppearance="?android:attr/textAppearanceMedium"
+                 android:textColor="#ffffffff"
+                 android:imeOptions="flagForceAscii|actionDone"
+                 />
+
+             <ImageView android:id="@+id/switch_ime_button"
+                 android:layout_width="wrap_content"
+                 android:layout_height="wrap_content"
+                 android:src="@*android:drawable/ic_lockscreen_ime"
+                 android:clickable="true"
+                 android:padding="8dip"
+                 android:layout_gravity="center"
+                 android:background="?android:attr/selectableItemBackground"
+                 android:visibility="gone"
+                 />
+
+            </LinearLayout>
+       </FrameLayout>
+
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        />
+
+    <include layout="@layout/keyguard_eca"
+             android:id="@+id/keyguard_selector_fade_container"
+             android:layout_width="match_parent"
+             android:layout_height="wrap_content"
+             android:orientation="vertical"
+             android:layout_gravity="bottom|center_horizontal"
+             android:gravity="center_horizontal" />
+
+</com.android.internal.policy.impl.keyguard.KeyguardPasswordView>
diff --git a/core/res/res/layout/keyguard_pattern_view.xml b/core/res/res/layout/keyguard_pattern_view.xml
new file mode 100644
index 0000000..1bd3e4e
--- /dev/null
+++ b/core/res/res/layout/keyguard_pattern_view.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is the screen that shows the 9 circle unlock widget and instructs
+     the user how to unlock their device, or make an emergency call.  This
+     is the portrait layout.  -->
+<com.android.internal.policy.impl.keyguard.KeyguardPatternView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_pattern_view"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_maxWidth="@dimen/keyguard_security_width"
+    android:layout_maxHeight="@dimen/keyguard_security_height"
+    android:gravity="center_horizontal"
+    android:contentDescription="@string/keyguard_accessibility_pattern_unlock">
+
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <LinearLayout
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:orientation="vertical"
+            android:layout_gravity="center">
+
+            <include layout="@layout/keyguard_message_area"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+               />
+
+          <FrameLayout
+             android:id="@+id/keyguard_bouncer_frame"
+             android:background="@*android:drawable/kg_bouncer_bg_white"
+             android:layout_width="match_parent"
+             android:layout_height="0dp"
+             android:layout_weight="1"
+             >
+            <com.android.internal.widget.LockPatternView
+                android:id="@+id/lockPatternView"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:layout_marginEnd="8dip"
+                android:layout_marginBottom="4dip"
+                android:layout_marginStart="8dip"
+                android:layout_gravity="center_horizontal"
+                android:gravity="center"
+                android:contentDescription="@string/keyguard_accessibility_pattern_area" />
+          </FrameLayout>
+          <include layout="@layout/keyguard_eca"
+              android:id="@+id/keyguard_selector_fade_container"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:orientation="vertical"
+              android:layout_gravity="bottom|center_horizontal"
+              android:gravity="center_horizontal" />
+        </LinearLayout>
+    </FrameLayout>
+
+</com.android.internal.policy.impl.keyguard.KeyguardPatternView>
diff --git a/core/res/res/layout/keyguard_pin_view.xml b/core/res/res/layout/keyguard_pin_view.xml
new file mode 100644
index 0000000..e494b69
--- /dev/null
+++ b/core/res/res/layout/keyguard_pin_view.xml
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<com.android.internal.policy.impl.keyguard.KeyguardPINView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_pin_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_maxWidth="@dimen/keyguard_security_width"
+    android:layout_maxHeight="@dimen/keyguard_security_height"
+    android:orientation="vertical"
+    android:contentDescription="@string/keyguard_accessibility_pin_unlock"
+    >
+    <include layout="@layout/keyguard_message_area"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        />
+    <LinearLayout
+       android:id="@+id/keyguard_bouncer_frame"
+       android:background="@*android:drawable/kg_bouncer_bg_white"
+       android:layout_width="match_parent"
+       android:layout_height="0dp"
+       android:orientation="vertical"
+       android:layout_weight="1"
+       >
+       <LinearLayout
+          android:layout_width="match_parent"
+          android:layout_height="0dp"
+          android:orientation="horizontal"
+          android:layout_weight="1"
+          >
+          <TextView android:id="@+id/pinEntry"
+               android:editable="true"
+               android:layout_width="0dip"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               android:gravity="center"
+               android:layout_marginStart="@*android:dimen/keyguard_lockscreen_pin_margin_left"
+               android:singleLine="true"
+               android:cursorVisible="false"
+               android:background="@null"
+               android:textAppearance="@style/TextAppearance.NumPadKey"
+               android:imeOptions="flagForceAscii|actionDone"
+               />
+           <ImageButton android:id="@+id/delete_button"
+               android:layout_width="wrap_content"
+               android:layout_height="match_parent"
+               android:gravity="center_vertical"
+               android:src="@*android:drawable/ic_input_delete"
+               android:clickable="true"
+               android:paddingTop="8dip"
+               android:paddingBottom="8dip"
+               android:paddingLeft="24dp"
+               android:paddingRight="24dp"
+               android:background="?android:attr/selectableItemBackground"
+               android:contentDescription="@string/keyboardview_keycode_delete"
+               />
+       </LinearLayout>
+       <View
+           android:layout_width="wrap_content"
+           android:layout_height="1dp"
+           android:background="#55FFFFFF"
+           />
+       <LinearLayout
+           android:layout_width="match_parent"
+           android:layout_height="0dp"
+           android:layout_weight="1"
+           android:orientation="horizontal"
+           >
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key1"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="1"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key2"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="2"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key3"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="3"
+               />
+       </LinearLayout>
+       <LinearLayout
+           android:layout_width="match_parent"
+           android:layout_height="0dp"
+           android:layout_weight="1"
+           android:orientation="horizontal"
+           >
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key4"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="4"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key5"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="5"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key6"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="6"
+               />
+       </LinearLayout>
+       <LinearLayout
+           android:layout_width="match_parent"
+           android:layout_height="0dp"
+           android:orientation="horizontal"
+           android:layout_weight="1"
+           >
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key7"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="7"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key8"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="8"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key9"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="9"
+               />
+       </LinearLayout>
+       <LinearLayout
+           android:layout_width="match_parent"
+           android:layout_height="0dp"
+           android:layout_weight="1"
+           android:orientation="horizontal"
+           >
+           <Space
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key0"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="0"
+               />
+           <ImageButton
+               android:id="@+id/key_enter"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               android:paddingRight="30dp"
+               android:src="@drawable/sym_keyboard_return_holo"
+               android:contentDescription="@string/keyboardview_keycode_enter"
+               />
+       </LinearLayout>
+    </LinearLayout>
+    <include layout="@layout/keyguard_eca"
+                   android:id="@+id/keyguard_selector_fade_container"
+                   android:layout_width="match_parent"
+                   android:layout_height="wrap_content"
+                   android:orientation="vertical"
+                   android:layout_gravity="bottom|center_horizontal"
+                   android:gravity="center_horizontal" />
+
+</com.android.internal.policy.impl.keyguard.KeyguardPINView>
diff --git a/core/res/res/layout/keyguard_screen_glogin_unlock.xml b/core/res/res/layout/keyguard_screen_glogin_unlock.xml
index 35d113c..db920b4 100644
--- a/core/res/res/layout/keyguard_screen_glogin_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_glogin_unlock.xml
@@ -37,7 +37,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="64dip"
                 android:layout_alignParentTop="true"
-                android:layout_marginLeft="4dip"
+                android:layout_marginStart="4dip"
                 android:textAppearance="?android:attr/textAppearanceMedium"
                 android:gravity="center_vertical"
                 android:drawableLeft="@drawable/ic_lock_idle_lock"
@@ -58,7 +58,7 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@+id/spacerTop"
                 android:layout_marginTop="8dip"
-                android:layout_marginLeft="9dip"
+                android:layout_marginStart="9dip"
                 android:textAppearance="?android:attr/textAppearanceSmall"
                 android:text="@android:string/lockscreen_glogin_instructions"
                 />
@@ -69,8 +69,8 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@id/instructions"
                 android:layout_marginTop="8dip"
-                android:layout_marginLeft="7dip"
-                android:layout_marginRight="7dip"
+                android:layout_marginStart="7dip"
+                android:layout_marginEnd="7dip"
                 android:hint="@android:string/lockscreen_glogin_username_hint"
                 android:inputType="textEmailAddress"
                 />
@@ -81,8 +81,8 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@id/login"
                 android:layout_marginTop="15dip"
-                android:layout_marginLeft="7dip"
-                android:layout_marginRight="7dip"
+                android:layout_marginStart="7dip"
+                android:layout_marginEnd="7dip"
                 android:inputType="textPassword"
                 android:hint="@android:string/lockscreen_glogin_password_hint"
                 android:nextFocusRight="@+id/ok"
@@ -96,8 +96,8 @@
                 android:layout_height="wrap_content"
                 android:layout_below="@id/password"
                 android:layout_marginTop="7dip"
-                android:layout_marginRight="7dip"
-                android:layout_alignParentRight="true"
+                android:layout_marginEnd="7dip"
+                android:layout_alignParentEnd="true"
                 android:text="@android:string/lockscreen_glogin_submit_button"
                 />
         
diff --git a/core/res/res/layout/keyguard_screen_lock.xml b/core/res/res/layout/keyguard_screen_lock.xml
index 43867f4d..8c178b1 100644
--- a/core/res/res/layout/keyguard_screen_lock.xml
+++ b/core/res/res/layout/keyguard_screen_lock.xml
@@ -34,8 +34,8 @@
         android:layout_height="wrap_content"
         android:layout_gravity="center"
         android:layout_marginBottom="15dip"
-        android:layout_marginLeft="15dip"
-        android:layout_marginRight="15dip"
+        android:layout_marginStart="15dip"
+        android:layout_marginEnd="15dip"
         android:paddingTop="20dip"
         android:paddingBottom="20dip"
         android:background="@android:drawable/popup_full_dark"
@@ -108,7 +108,7 @@
             <ImageView android:id="@+id/batteryInfoIcon"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="6dip"
+                android:layout_marginEnd="6dip"
                 android:baselineAligned="true"
                 android:gravity="center"
             />
@@ -143,7 +143,7 @@
             <ImageView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="6dip"
+                android:layout_marginEnd="6dip"
                 android:baselineAligned="true"
                 android:src="@android:drawable/ic_lock_idle_alarm"
                 android:gravity="center"
@@ -177,7 +177,7 @@
             <ImageView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="6dip"
+                android:layout_marginEnd="6dip"
                 android:baselineAligned="true"
                 android:src="@android:drawable/ic_lock_idle_lock"
                 android:gravity="center"
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index 3bea16c..80d9d61 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -33,7 +33,7 @@
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
         android:layout_marginTop="8dip"
         android:layout_marginBottom="8dip"
-        android:layout_gravity="right"
+        android:layout_gravity="end"
         android:layout_rowSpan="2">
 
        <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
@@ -58,7 +58,7 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:layout_marginBottom="6dip"
             android:textColor="@color/lockscreen_clock_foreground"
-            android:layout_alignLeft="@id/timeDisplayBackground"
+            android:layout_alignStart="@id/timeDisplayBackground"
             android:layout_alignTop="@id/timeDisplayBackground"
             />
 
@@ -68,7 +68,7 @@
         android:id="@+id/date"
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
-        android:gravity="right"
+        android:gravity="end"
         android:layout_below="@id/time"
         android:layout_marginTop="6dip"
         android:singleLine="true"
@@ -85,14 +85,14 @@
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
         android:layout_marginTop="4dip"
-        android:layout_gravity="right"
+        android:layout_gravity="end"
         />
 
     <TextView
         android:id="@+id/status1"
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
-        android:gravity="right"
+        android:gravity="end"
         android:layout_marginTop="4dip"
         android:singleLine="true"
         android:ellipsize="marquee"
@@ -107,7 +107,7 @@
         android:id="@+id/carrier"
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
-        android:gravity="right"
+        android:gravity="end"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -117,7 +117,7 @@
 
     <Button
         android:id="@+id/emergencyCallButton"
-        android:layout_gravity="right"
+        android:layout_gravity="end"
         android:drawableLeft="@drawable/lockscreen_emergency_button"
         android:text="@string/lockscreen_emergency_call"
         style="?android:attr/buttonBarButtonStyle"
@@ -143,7 +143,6 @@
             android:layout_width="0dip"
             android:layout_weight="1"
             android:gravity="center"
-            android:layout_marginLeft="@dimen/keyguard_lockscreen_pin_margin_left"
             android:layout_gravity="center_vertical"
             android:singleLine="true"
             android:textStyle="normal"
@@ -185,8 +184,8 @@
     <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
         android:layout_width="270dip"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="4dip"
-        android:layout_marginRight="4dip"
+        android:layout_marginStart="4dip"
+        android:layout_marginEnd="4dip"
         android:background="#40000000"
         android:layout_marginTop="5dip"
         android:keyBackground="@*android:drawable/btn_keyboard_key_ics"
@@ -209,7 +208,7 @@
 
     <!-- Area to overlay FaceLock -->
     <RelativeLayout
-        android:id="@+id/faceLockAreaView"
+        android:id="@+id/face_unlock_area_view"
         android:visibility="invisible"
         android:layout_row="0"
         android:layout_column="2"
@@ -233,7 +232,7 @@
             android:layout_height="wrap_content"
             android:padding="5dip"
             android:layout_alignParentTop="true"
-            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
             android:src="@drawable/ic_facial_backup"
         />
 
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index 6b409aa..3d61bae 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -25,8 +25,8 @@
 
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
         android:layout_marginBottom="18dip"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
-        android:layout_gravity="right">
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+        android:layout_gravity="end">
 
         <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
         top of the other. Hence the redundant layout... -->
@@ -56,8 +56,8 @@
 
     <LinearLayout
         android:orientation="horizontal"
-        android:layout_gravity="right"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin">
+        android:layout_gravity="end"
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin">
 
         <TextView
             android:id="@+id/date"
@@ -73,7 +73,7 @@
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="16dip"
+            android:layout_marginStart="16dip"
             android:singleLine="true"
             android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
@@ -85,8 +85,8 @@
 
     <TextView
         android:id="@+id/status1"
-        android:layout_gravity="right"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+        android:layout_gravity="end"
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -102,16 +102,14 @@
         android:layout_gravity="center_vertical|fill_horizontal"
         android:orientation="horizontal"
         android:background="@drawable/lockscreen_password_field_dark"
-        android:layout_marginLeft="16dip"
-        android:layout_marginRight="16dip">
+        android:layout_marginStart="16dip"
+        android:layout_marginEnd="16dip">
 
         <EditText android:id="@+id/passwordEntry"
-            android:layout_width="0dip"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_weight="1"
             android:gravity="center_horizontal"
             android:layout_gravity="center_vertical"
-            android:layout_marginLeft="@dimen/keyguard_lockscreen_pin_margin_left"
             android:singleLine="true"
             android:textStyle="normal"
             android:inputType="textPassword"
@@ -150,8 +148,8 @@
     <!-- Numeric keyboard -->
     <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
         android:layout_width="match_parent"
-        android:layout_marginLeft="4dip"
-        android:layout_marginRight="4dip"
+        android:layout_marginStart="4dip"
+        android:layout_marginEnd="4dip"
         android:paddingTop="4dip"
         android:paddingBottom="4dip"
         android:background="#40000000"
@@ -200,7 +198,7 @@
 
     <!-- Area to overlay FaceLock -->
     <RelativeLayout
-        android:id="@+id/faceLockAreaView"
+        android:id="@+id/face_unlock_area_view"
         android:visibility="invisible"
         android:layout_row="3"
         android:layout_column="0"
@@ -224,7 +222,7 @@
             android:layout_height="wrap_content"
             android:padding="5dip"
             android:layout_alignParentTop="true"
-            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
             android:src="@drawable/ic_facial_backup"
         />
 
diff --git a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
index 3cb19c3..3738766 100644
--- a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
@@ -39,7 +39,7 @@
         android:layout_height="wrap_content"
         android:layout_above="@+id/pinDisplayGroup"
         android:layout_marginTop="9dip"
-        android:gravity="left|bottom"
+        android:gravity="start|bottom"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -54,9 +54,9 @@
         android:addStatesFromChildren="true"
         android:gravity="center_vertical"
         android:baselineAligned="false"
-        android:paddingRight="0dip"
-        android:layout_marginRight="30dip"
-        android:layout_marginLeft="30dip"
+        android:paddingEnd="0dip"
+        android:layout_marginEnd="30dip"
+        android:layout_marginStart="30dip"
         android:background="@android:drawable/edit_text"
     >
 
@@ -75,7 +75,7 @@
              android:layout_width="wrap_content"
              android:layout_height="match_parent"
              android:layout_marginTop="2dip"
-             android:layout_marginRight="2dip"
+             android:layout_marginEnd="2dip"
              android:layout_marginBottom="2dip"
              android:gravity="center"
             />
@@ -88,8 +88,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="8dip"
-        android:layout_marginLeft="8dip"
-        android:layout_marginRight="8dip">
+        android:layout_marginStart="8dip"
+        android:layout_marginEnd="8dip">
 
         <Button android:id="@+id/emergencyCallButton"
             android:text="@android:string/lockscreen_emergency_call"
@@ -99,7 +99,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="1.0"
             android:layout_marginBottom="8dip"
-            android:layout_marginRight="8dip"
+            android:layout_marginEnd="8dip"
             android:textSize="18sp"
             android:drawableLeft="@drawable/ic_emergency"
             android:drawablePadding="4dip"
@@ -112,7 +112,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="1.0"
             android:layout_marginBottom="8dip"
-            android:layout_marginLeft="8dip"
+            android:layout_marginStart="8dip"
             android:textSize="18sp"
         />
     </LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml b/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
index 9ca351c..20c21421 100644
--- a/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
@@ -51,8 +51,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            android:layout_marginRight="6dip"
-            android:layout_marginLeft="6dip"
+            android:layout_marginEnd="6dip"
+            android:layout_marginStart="6dip"
             android:gravity="center_vertical"
             android:background="@android:drawable/edit_text">
 
@@ -72,7 +72,7 @@
                 android:src="@android:drawable/ic_input_delete"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="-3dip"
+                android:layout_marginEnd="-3dip"
                 android:layout_marginBottom="-3dip"
             />
         </LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml b/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
index 56e6426..fd6dc26 100644
--- a/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
@@ -55,8 +55,8 @@
                 android:orientation="vertical"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
-                android:layout_marginRight="10dip"
-                android:layout_marginLeft="10dip">
+                android:layout_marginEnd="10dip"
+                android:layout_marginStart="10dip">
                 <TextView android:id="@+id/enter_puk"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
@@ -78,16 +78,16 @@
                   android:layout_width="wrap_content"
                   android:layout_weight="1"
                   android:layout_height="match_parent"
-                  android:paddingRight="0dip"
-                  android:layout_marginRight="10dip"
-                  android:layout_marginLeft="10dip">
+                  android:paddingEnd="0dip"
+                  android:layout_marginEnd="10dip"
+                  android:layout_marginStart="10dip">
 
                   <LinearLayout
                       android:layout_width="match_parent"
                       android:layout_height="wrap_content"
                       android:orientation="horizontal"
-                      android:layout_marginRight="6dip"
-                      android:layout_marginLeft="6dip"
+                      android:layout_marginEnd="6dip"
+                      android:layout_marginStart="6dip"
                       android:gravity="center_vertical"
                       android:background="@android:drawable/edit_text">
 
@@ -106,7 +106,7 @@
                           android:src="@android:drawable/ic_input_delete"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
-                          android:layout_marginRight="-3dip"
+                          android:layout_marginEnd="-3dip"
                           android:layout_marginBottom="-3dip"
                       />
                   </LinearLayout>
@@ -116,8 +116,8 @@
                       android:layout_width="match_parent"
                       android:layout_height="wrap_content"
                       android:orientation="horizontal"
-                      android:layout_marginRight="6dip"
-                      android:layout_marginLeft="6dip"
+                      android:layout_marginEnd="6dip"
+                      android:layout_marginStart="6dip"
                       android:gravity="center_vertical"
                       android:background="@android:drawable/edit_text">
 
@@ -138,7 +138,7 @@
                           android:src="@android:drawable/ic_input_delete"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
-                          android:layout_marginRight="-3dip"
+                          android:layout_marginEnd="-3dip"
                           android:layout_marginBottom="-3dip"
                       />
                   </LinearLayout>
@@ -152,8 +152,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="8dip"
-        android:layout_marginLeft="8dip"
-        android:layout_marginRight="8dip">
+        android:layout_marginStart="8dip"
+        android:layout_marginEnd="8dip">
 
         <Button android:id="@+id/emergencyCallButton"
             android:text="@android:string/lockscreen_emergency_call"
@@ -163,7 +163,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="1.0"
             android:layout_marginBottom="8dip"
-            android:layout_marginRight="8dip"
+            android:layout_marginEnd="8dip"
             android:textSize="18sp"
             android:drawableLeft="@drawable/ic_emergency"
             android:drawablePadding="4dip"
@@ -176,7 +176,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="1.0"
             android:layout_marginBottom="8dip"
-            android:layout_marginLeft="8dip"
+            android:layout_marginStart="8dip"
             android:textSize="18sp"
         />
     </LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml b/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml
index 8b039f7..5397e62 100644
--- a/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml
@@ -35,8 +35,8 @@
             android:gravity="center"
             android:singleLine="true"
             android:ellipsize="marquee"
-            android:layout_marginRight="6dip"
-            android:layout_marginLeft="6dip"
+            android:layout_marginEnd="6dip"
+            android:layout_marginStart="6dip"
             android:textAppearance="?android:attr/textAppearanceLarge"/>
 
         <!-- Carrier info -->
@@ -47,8 +47,8 @@
             android:gravity="center"
             android:singleLine="true"
             android:ellipsize="marquee"
-            android:layout_marginRight="6dip"
-            android:layout_marginLeft="6dip"
+            android:layout_marginEnd="6dip"
+            android:layout_marginStart="6dip"
             android:textAppearance="?android:attr/textAppearanceMedium"/>
 
         <LinearLayout
@@ -61,16 +61,16 @@
                   android:layout_width="wrap_content"
                   android:layout_weight="1"
                   android:layout_height="match_parent"
-                  android:paddingRight="0dip"
-                  android:layout_marginRight="10dip"
-                  android:layout_marginLeft="10dip">
+                  android:paddingEnd="0dip"
+                  android:layout_marginEnd="10dip"
+                  android:layout_marginStart="10dip">
 
                   <LinearLayout
                       android:layout_width="match_parent"
                       android:layout_height="wrap_content"
                       android:orientation="horizontal"
-                      android:layout_marginRight="6dip"
-                      android:layout_marginLeft="6dip"
+                      android:layout_marginEnd="6dip"
+                      android:layout_marginStart="6dip"
                       android:gravity="center_vertical"
                       android:background="@android:drawable/edit_text">
 
@@ -90,7 +90,7 @@
                           android:src="@android:drawable/ic_input_delete"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
-                          android:layout_marginRight="-3dip"
+                          android:layout_marginEnd="-3dip"
                           android:layout_marginBottom="-3dip"
                       />
                   </LinearLayout>
@@ -100,8 +100,8 @@
                       android:layout_width="match_parent"
                       android:layout_height="wrap_content"
                       android:orientation="horizontal"
-                      android:layout_marginRight="6dip"
-                      android:layout_marginLeft="6dip"
+                      android:layout_marginEnd="6dip"
+                      android:layout_marginStart="6dip"
                       android:gravity="center_vertical"
                       android:background="@android:drawable/edit_text">
 
@@ -121,7 +121,7 @@
                           android:src="@android:drawable/ic_input_delete"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
-                          android:layout_marginRight="-3dip"
+                          android:layout_marginEnd="-3dip"
                           android:layout_marginBottom="-3dip"
                       />
                   </LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 81166222..54381ee 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -31,8 +31,8 @@
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
         android:layout_marginTop="@dimen/keyguard_lockscreen_status_line_clockfont_top_margin"
         android:layout_marginBottom="12dip"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
-        android:layout_gravity="right">
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+        android:layout_gravity="end">
 
         <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
         top of the other. Hence the redundant layout... -->
@@ -56,7 +56,7 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:layout_marginBottom="6dip"
             android:textColor="@color/lockscreen_clock_foreground"
-            android:layout_alignLeft="@id/timeDisplayBackground"
+            android:layout_alignStart="@id/timeDisplayBackground"
             android:layout_alignTop="@id/timeDisplayBackground"
             />
 
@@ -64,8 +64,8 @@
 
     <LinearLayout
         android:orientation="horizontal"
-        android:layout_gravity="right"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin">
+        android:layout_gravity="end"
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin">
 
         <TextView
             android:id="@+id/date"
@@ -81,7 +81,7 @@
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="16dip"
+            android:layout_marginStart="16dip"
             android:singleLine="true"
             android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
@@ -93,8 +93,8 @@
 
     <TextView
         android:id="@+id/status1"
-        android:layout_gravity="right"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+        android:layout_gravity="end"
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -110,8 +110,8 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="4dip"
-        android:layout_marginRight="16dip"
-        android:layout_gravity="right"
+        android:layout_marginEnd="16dip"
+        android:layout_gravity="end"
         android:drawableLeft="@*android:drawable/lockscreen_emergency_button"
         style="?android:attr/buttonBarButtonStyle"
         android:drawablePadding="4dip"
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index 35e4d11..7ef9d8b 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -32,7 +32,7 @@
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
         android:layout_marginTop="80dip"
         android:layout_marginBottom="8dip"
-        android:layout_gravity="right">
+        android:layout_gravity="end">
 
        <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
         top of the other. Hence the redundant layout... -->
@@ -56,7 +56,7 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:layout_marginBottom="6dip"
             android:textColor="@color/lockscreen_clock_foreground"
-            android:layout_alignLeft="@id/timeDisplayBackground"
+            android:layout_alignStart="@id/timeDisplayBackground"
             android:layout_alignTop="@id/timeDisplayBackground"
             />
 
@@ -66,7 +66,7 @@
         android:id="@+id/date"
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
-        android:gravity="right"
+        android:gravity="end"
         android:layout_marginTop="6dip"
         android:singleLine="true"
         android:ellipsize="marquee"
@@ -82,14 +82,14 @@
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
         android:layout_marginTop="4dip"
-        android:layout_gravity="right"
+        android:layout_gravity="end"
         />
 
     <TextView
         android:id="@+id/status1"
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
-        android:gravity="right"
+        android:gravity="end"
         android:layout_marginTop="4dip"
         android:singleLine="true"
         android:ellipsize="marquee"
@@ -105,7 +105,7 @@
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
         android:layout_marginBottom="12dip"
-        android:gravity="right"
+        android:gravity="end"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -117,7 +117,7 @@
         android:id="@+id/emergencyCallButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_gravity="right"
+        android:layout_gravity="end"
         android:drawableLeft="@*android:drawable/lockscreen_emergency_button"
         android:text="@*android:string/lockscreen_emergency_call"
         style="?android:attr/buttonBarButtonStyle"
@@ -134,7 +134,7 @@
         android:layout_width="302dip"
         android:layout_height="match_parent"
         android:layout_rowSpan="7"
-        android:gravity="left|center_vertical"
+        android:gravity="start|center_vertical"
         android:focusable="true"
 
         android:targetDrawables="@array/lockscreen_targets_with_camera"
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index 7f9aaa0..27f6629 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -32,7 +32,7 @@
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
         android:layout_marginTop="8dip"
         android:layout_marginBottom="12dip"
-        android:layout_gravity="right">
+        android:layout_gravity="end">
 
         <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
         top of the other. Hence the redundant layout... -->
@@ -55,7 +55,7 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
             android:layout_marginBottom="6dip"
-            android:layout_alignLeft="@id/timeDisplayBackground"
+            android:layout_alignStart="@id/timeDisplayBackground"
             android:layout_alignTop="@id/timeDisplayBackground"
             android:textColor="@color/lockscreen_clock_foreground"
             />
@@ -66,7 +66,7 @@
         android:id="@+id/date"
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
-        android:gravity="right"
+        android:gravity="end"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -79,7 +79,7 @@
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
-        android:layout_gravity="right"
+        android:layout_gravity="end"
         android:drawablePadding="4dip"
         />
 
@@ -87,7 +87,7 @@
         android:id="@+id/status1"
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
-        android:gravity="right"
+        android:gravity="end"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -99,7 +99,7 @@
     <TextView android:id="@+id/carrier"
         android:layout_width="0dip"
         android:layout_gravity="fill_horizontal"
-        android:gravity="right"
+        android:gravity="end"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -109,11 +109,11 @@
     <LinearLayout
         style="?android:attr/buttonBarStyle"
         android:orientation="vertical"
-        android:layout_gravity="right">
+        android:layout_gravity="end">
 
         <Button android:id="@+id/emergencyCallButton"
             style="?android:attr/buttonBarButtonStyle"
-            android:layout_gravity="right"
+            android:layout_gravity="end"
             android:layout_width="wrap_content"
             android:layout_height="0dip"
             android:layout_weight="1"
@@ -125,7 +125,7 @@
 
         <Button android:id="@+id/forgotPatternButton"
             style="?android:attr/buttonBarButtonStyle"
-            android:layout_gravity="right"
+            android:layout_gravity="end"
             android:layout_width="wrap_content"
             android:layout_height="0dip"
             android:layout_weight="1"
@@ -142,9 +142,9 @@
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:layout_marginTop="8dip"
-         android:layout_marginRight="8dip"
+         android:layout_marginEnd="8dip"
          android:layout_marginBottom="8dip"
-         android:layout_marginLeft="8dip"
+         android:layout_marginStart="8dip"
          android:layout_rowSpan="7"/>
 
 
@@ -162,14 +162,14 @@
 
     <!-- Area to overlay FaceLock -->
     <RelativeLayout
-        android:id="@+id/faceLockAreaView"
+        android:id="@+id/face_unlock_area_view"
         android:visibility="invisible"
         android:layout_row="0"
         android:layout_column="1"
         android:layout_rowSpan="7"
         android:layout_columnSpan="1"
         android:layout_gravity="fill"
-        android:layout_marginLeft="8dip"
+        android:layout_marginStart="8dip"
         android:layout_width="0dip"
         android:layout_height="0dip"
         android:background="@drawable/intro_bg">
@@ -187,7 +187,7 @@
             android:layout_height="wrap_content"
             android:padding="5dip"
             android:layout_alignParentTop="true"
-            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
             android:src="@drawable/ic_facial_backup"
         />
 
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index c235289..de94451 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -30,8 +30,8 @@
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
         android:layout_marginTop="@dimen/keyguard_lockscreen_status_line_clockfont_top_margin"
         android:layout_marginBottom="@dimen/keyguard_lockscreen_status_line_clockfont_bottom_margin"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
-        android:layout_gravity="right">
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+        android:layout_gravity="end">
 
         <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
         top of the other. Hence the redundant layout... -->
@@ -59,8 +59,8 @@
 
     <LinearLayout
         android:orientation="horizontal"
-        android:layout_gravity="right"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin">
+        android:layout_gravity="end"
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin">
 
         <TextView
             android:id="@+id/date"
@@ -76,7 +76,7 @@
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="16dip"
+            android:layout_marginStart="16dip"
             android:singleLine="true"
             android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
@@ -89,8 +89,8 @@
 
     <TextView
         android:id="@+id/status1"
-        android:layout_gravity="right"
-        android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+        android:layout_gravity="end"
+        android:layout_marginEnd="@dimen/keyguard_lockscreen_status_line_font_right_margin"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -108,9 +108,9 @@
         android:id="@+id/lockPattern"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:layout_marginRight="8dip"
+        android:layout_marginEnd="8dip"
         android:layout_marginBottom="4dip"
-        android:layout_marginLeft="8dip"
+        android:layout_marginStart="8dip"
         android:layout_gravity="center_horizontal"
      />
 
@@ -171,7 +171,7 @@
 
     <!-- Area to overlay FaceLock -->
     <RelativeLayout
-        android:id="@+id/faceLockAreaView"
+        android:id="@+id/face_unlock_area_view"
         android:visibility="invisible"
         android:layout_row="4"
         android:layout_column="0"
@@ -196,7 +196,7 @@
             android:layout_height="wrap_content"
             android:padding="5dip"
             android:layout_alignParentTop="true"
-            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
             android:src="@drawable/ic_facial_backup"
         />
 
diff --git a/core/res/res/layout/keyguard_selector_view.xml b/core/res/res/layout/keyguard_selector_view.xml
new file mode 100644
index 0000000..dfacb6a
--- /dev/null
+++ b/core/res/res/layout/keyguard_selector_view.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is the selector widget that allows the user to select an action. -->
+<com.android.internal.policy.impl.keyguard.KeyguardSelectorView
+    xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_selector_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_maxWidth="420dp"
+    android:layout_maxHeight="@dimen/keyguard_security_height"
+    android:clipChildren="false"
+    android:clipToPadding="false"
+    android:orientation="vertical"
+    android:contentDescription="@string/keyguard_accessibility_slide_unlock">
+
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_gravity="center"
+        android:clipChildren="false"
+        android:clipToPadding="false"
+        android:gravity="center">
+
+        <include layout="@layout/keyguard_message_area"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+
+        <View
+            android:id="@+id/keyguard_selector_view_frame"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="16dp"
+            android:layout_marginRight="16dp"
+            android:background="@*android:drawable/kg_bouncer_bg_white"/>
+
+        <include layout="@layout/keyguard_glow_pad_container" />
+
+        <include layout="@layout/keyguard_eca"
+            android:id="@+id/keyguard_selector_fade_container"
+            android:layout_width="match_parent"
+            android:layout_height="48dp"
+            android:layout_gravity="bottom|center_horizontal" />
+    </FrameLayout>
+
+</com.android.internal.policy.impl.keyguard.KeyguardSelectorView>
+
diff --git a/core/res/res/layout/keyguard_sim_pin_view.xml b/core/res/res/layout/keyguard_sim_pin_view.xml
new file mode 100644
index 0000000..026b025
--- /dev/null
+++ b/core/res/res/layout/keyguard_sim_pin_view.xml
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<!-- This is the SIM PIN view that allows the user to enter a SIM PIN to unlock the device. -->
+<com.android.internal.policy.impl.keyguard.KeyguardSimPinView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_sim_pin_view"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_maxWidth="@dimen/keyguard_security_width"
+    android:layout_maxHeight="@dimen/keyguard_security_height"
+    android:gravity="center_horizontal">
+
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:src="@drawable/ic_lockscreen_sim"/>
+
+    <include layout="@layout/keyguard_message_area"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        />
+    <LinearLayout
+       android:id="@+id/keyguard_bouncer_frame"
+       android:background="@*android:drawable/kg_bouncer_bg_white"
+       android:layout_width="match_parent"
+       android:layout_height="0dp"
+       android:orientation="vertical"
+       android:layout_weight="1"
+       >
+       <LinearLayout
+           android:layout_width="match_parent"
+           android:layout_height="0dp"
+           android:orientation="horizontal"
+           android:layout_weight="1"
+           >
+           <TextView android:id="@+id/pinEntry"
+               android:editable="true"
+               android:layout_width="0dip"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               android:gravity="center"
+               android:layout_marginStart="@*android:dimen/keyguard_lockscreen_pin_margin_left"
+               android:singleLine="true"
+               android:cursorVisible="false"
+               android:background="@null"
+               android:textAppearance="@style/TextAppearance.NumPadKey"
+               android:imeOptions="flagForceAscii|actionDone"
+               />
+           <ImageButton android:id="@+id/delete_button"
+               android:layout_width="wrap_content"
+               android:layout_height="match_parent"
+               android:gravity="center_vertical"
+               android:src="@*android:drawable/ic_input_delete"
+               android:clickable="true"
+               android:paddingTop="8dip"
+               android:paddingBottom="8dip"
+               android:paddingLeft="24dp"
+               android:paddingRight="24dp"
+               android:background="?android:attr/selectableItemBackground"
+               android:contentDescription="@string/keyboardview_keycode_delete"
+               />
+       </LinearLayout>
+       <View
+           android:layout_width="wrap_content"
+           android:layout_height="1dp"
+           android:background="#55FFFFFF"
+           />
+       <LinearLayout
+           android:layout_width="match_parent"
+           android:layout_height="0dp"
+           android:layout_weight="1"
+           android:orientation="horizontal"
+           >
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key1"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="1"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key2"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="2"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key3"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="3"
+               />
+       </LinearLayout>
+       <LinearLayout
+           android:layout_width="match_parent"
+           android:layout_height="0dp"
+           android:layout_weight="1"
+           android:orientation="horizontal"
+           >
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key4"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="4"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key5"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="5"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key6"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="6"
+               />
+       </LinearLayout>
+       <LinearLayout
+           android:layout_width="match_parent"
+           android:layout_height="0dp"
+           android:orientation="horizontal"
+           android:layout_weight="1"
+           >
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key7"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="7"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key8"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="8"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key9"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="9"
+               />
+       </LinearLayout>
+       <LinearLayout
+           android:layout_width="match_parent"
+           android:layout_height="0dp"
+           android:layout_weight="1"
+           android:orientation="horizontal"
+           >
+           <Space
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key0"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="0"
+               />
+           <ImageButton
+               android:id="@+id/key_enter"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               android:paddingRight="30dp"
+               android:src="@drawable/sym_keyboard_return_holo"
+               android:contentDescription="@string/keyboardview_keycode_enter"
+               />
+       </LinearLayout>
+    </LinearLayout>
+
+    <include layout="@layout/keyguard_eca"
+                   android:id="@+id/keyguard_selector_fade_container"
+                   android:layout_width="match_parent"
+                   android:layout_height="wrap_content"
+                   android:orientation="vertical"
+                   android:layout_gravity="bottom|center_horizontal"
+                   android:gravity="center_horizontal" />
+
+</com.android.internal.policy.impl.keyguard.KeyguardSimPinView>
diff --git a/core/res/res/layout/keyguard_sim_puk_pin_account_navigation.xml b/core/res/res/layout/keyguard_sim_puk_pin_account_navigation.xml
new file mode 100644
index 0000000..2e6fa37
--- /dev/null
+++ b/core/res/res/layout/keyguard_sim_puk_pin_account_navigation.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <include layout="@layout/default_navigation" />
+</merge>
diff --git a/core/res/res/layout/keyguard_sim_puk_view.xml b/core/res/res/layout/keyguard_sim_puk_view.xml
new file mode 100644
index 0000000..28a9f9a
--- /dev/null
+++ b/core/res/res/layout/keyguard_sim_puk_view.xml
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+<!-- This is the SIM PUK view that allows the user to recover their device by entering the
+    carrier-provided PUK code and entering a new SIM PIN for it. -->
+<com.android.internal.policy.impl.keyguard.KeyguardSimPukView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_sim_puk_view"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_maxWidth="@dimen/keyguard_security_width"
+    android:layout_maxHeight="@dimen/keyguard_security_height"
+    android:gravity="center_horizontal">
+
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:src="@drawable/ic_lockscreen_sim"/>
+
+    <include layout="@layout/keyguard_message_area"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        />
+    <LinearLayout
+       android:id="@+id/keyguard_bouncer_frame"
+       android:background="@*android:drawable/kg_bouncer_bg_white"
+       android:layout_width="match_parent"
+       android:layout_height="0dp"
+       android:orientation="vertical"
+       android:layout_weight="1"
+       >
+       <LinearLayout
+           android:layout_width="match_parent"
+           android:layout_height="0dp"
+           android:orientation="horizontal"
+           android:layout_weight="1"
+           >
+           <TextView android:id="@+id/pinEntry"
+               android:editable="true"
+               android:layout_width="0dip"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               android:gravity="center"
+               android:layout_marginStart="@*android:dimen/keyguard_lockscreen_pin_margin_left"
+               android:singleLine="true"
+               android:cursorVisible="false"
+               android:background="@null"
+               android:textAppearance="@style/TextAppearance.NumPadKey"
+               android:imeOptions="flagForceAscii|actionDone"
+               />
+           <ImageButton android:id="@+id/delete_button"
+               android:layout_width="wrap_content"
+               android:layout_height="match_parent"
+               android:gravity="center_vertical"
+               android:src="@*android:drawable/ic_input_delete"
+               android:clickable="true"
+               android:paddingTop="8dip"
+               android:paddingBottom="8dip"
+               android:paddingLeft="24dp"
+               android:paddingRight="24dp"
+               android:background="?android:attr/selectableItemBackground"
+               android:contentDescription="@string/keyboardview_keycode_delete"
+               />
+       </LinearLayout>
+       <View
+           android:layout_width="wrap_content"
+           android:layout_height="1dp"
+           android:background="#55FFFFFF"
+           />
+       <LinearLayout
+           android:layout_width="match_parent"
+           android:layout_height="0dp"
+           android:layout_weight="1"
+           android:orientation="horizontal"
+           >
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key1"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="1"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key2"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="2"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key3"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="3"
+               />
+       </LinearLayout>
+       <LinearLayout
+           android:layout_width="match_parent"
+           android:layout_height="0dp"
+           android:layout_weight="1"
+           android:orientation="horizontal"
+           >
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key4"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="4"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key5"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="5"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key6"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="6"
+               />
+       </LinearLayout>
+       <LinearLayout
+           android:layout_width="match_parent"
+           android:layout_height="0dp"
+           android:orientation="horizontal"
+           android:layout_weight="1"
+           >
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key7"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="7"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key8"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="8"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key9"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="9"
+               />
+       </LinearLayout>
+       <LinearLayout
+           android:layout_width="match_parent"
+           android:layout_height="0dp"
+           android:layout_weight="1"
+           android:orientation="horizontal"
+           >
+           <Space
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               />
+           <view class="com.android.internal.policy.impl.keyguard.NumPadKey"
+               android:id="@+id/key0"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               androidprv:textView="@+id/pinEntry"
+               androidprv:digit="0"
+               />
+           <ImageButton
+               android:id="@+id/key_enter"
+               style="@style/Widget.Button.NumPadKey"
+               android:layout_width="0px"
+               android:layout_height="match_parent"
+               android:layout_weight="1"
+               android:paddingRight="30dp"
+               android:src="@drawable/sym_keyboard_return_holo"
+               android:contentDescription="@string/keyboardview_keycode_enter"
+               />
+       </LinearLayout>
+    </LinearLayout>
+
+    <include layout="@layout/keyguard_eca"
+                   android:id="@+id/keyguard_selector_fade_container"
+                   android:layout_width="match_parent"
+                   android:layout_height="wrap_content"
+                   android:orientation="vertical"
+                   android:layout_gravity="bottom|center_horizontal"
+                   android:gravity="center_horizontal" />
+</com.android.internal.policy.impl.keyguard.KeyguardSimPukView>
diff --git a/core/res/res/layout/keyguard_status_view.xml b/core/res/res/layout/keyguard_status_view.xml
new file mode 100644
index 0000000..9e36df3
--- /dev/null
+++ b/core/res/res/layout/keyguard_status_view.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<!-- This is a view that shows general status information in Keyguard. -->
+<com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_status_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_maxWidth="@dimen/keyguard_security_width"
+    android:layout_maxHeight="@dimen/keyguard_security_height"
+    android:gravity="center_horizontal">
+
+    <com.android.internal.policy.impl.keyguard.KeyguardStatusView
+        android:id="@+id/keyguard_status_view_face_palm"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center_horizontal|top"
+        android:contentDescription="@android:string/keyguard_accessibility_status">
+
+        <LinearLayout android:layout_width="match_parent"
+                      android:layout_height="wrap_content"
+                      android:layout_gravity="center_horizontal|top"
+                      android:orientation="vertical"
+                      android:focusable="true">
+            <com.android.internal.policy.impl.keyguard.ClockView
+                android:id="@+id/clock_view"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
+                android:layout_gravity="right">
+
+                <TextView android:id="@+id/clock_text"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:singleLine="true"
+                          android:ellipsize="none"
+                          android:textSize="@dimen/kg_status_clock_font_size"
+                          android:textAppearance="?android:attr/textAppearanceMedium"
+                          android:textColor="#ffffffff"
+                          android:drawablePadding="2dip"
+                          />
+
+            </com.android.internal.policy.impl.keyguard.ClockView>
+
+            <include layout="@layout/keyguard_status_area" />
+        </LinearLayout>
+
+    </com.android.internal.policy.impl.keyguard.KeyguardStatusView>
+</com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame>
diff --git a/core/res/res/layout/keyguard_transport_control.xml b/core/res/res/layout/keyguard_transport_control.xml
deleted file mode 100644
index 7e2a31c..0000000
--- a/core/res/res/layout/keyguard_transport_control.xml
+++ /dev/null
@@ -1,110 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<!-- Note: This file is meant to be included in various password unlock screens. As such,
-     LayoutParams (layout_*) for TransportControlView should *NOT* be specified here,
-     but rather as include tags for this file or the layout will break. -->
-<com.android.internal.widget.TransportControlView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/transport_controls">
-
-    <!-- FrameLayout used as scrim to show between album art and buttons -->
-    <FrameLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:foreground="@drawable/ic_lockscreen_player_background">
-        <!-- We use ImageView for its cropping features, otherwise could be android:background -->
-        <ImageView
-            android:id="@+id/albumart"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_gravity="fill"
-            android:scaleType="centerCrop"
-            android:adjustViewBounds="false"
-        />
-    </FrameLayout>
-
-    <LinearLayout
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="bottom">
-        <TextView
-            android:id="@+id/title"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="8dip"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip"
-            android:gravity="center_horizontal"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-        />
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            android:layout_marginTop="5dip">
-            <FrameLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_weight="1">
-                <ImageView
-                    android:id="@+id/btn_prev"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center"
-                    android:src="@drawable/ic_media_previous"
-                    android:clickable="true"
-                    android:background="?android:attr/selectableItemBackground"
-                    android:padding="10dip"
-                    android:contentDescription="@string/lockscreen_transport_prev_description"/>
-            </FrameLayout>
-            <FrameLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_weight="1">
-                <ImageView
-                    android:id="@+id/btn_play"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center"
-                    android:clickable="true"
-                    android:src="@drawable/ic_media_play"
-                    android:background="?android:attr/selectableItemBackground"
-                    android:padding="10dip"
-                    android:contentDescription="@string/lockscreen_transport_play_description"/>
-            </FrameLayout>
-            <FrameLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_weight="1">
-                <ImageView
-                    android:id="@+id/btn_next"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center"
-                    android:clickable="true"
-                    android:src="@drawable/ic_media_next"
-                    android:background="?android:attr/selectableItemBackground"
-                    android:padding="10dip"
-                    android:contentDescription="@string/lockscreen_transport_next_description"/>
-            </FrameLayout>
-        </LinearLayout>
-    </LinearLayout>
-
-</com.android.internal.widget.TransportControlView>
diff --git a/core/res/res/layout/keyguard_transport_control_view.xml b/core/res/res/layout/keyguard_transport_control_view.xml
new file mode 100644
index 0000000..532322c
--- /dev/null
+++ b/core/res/res/layout/keyguard_transport_control_view.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- This is a view to control music playback in keyguard. -->
+<com.android.internal.policy.impl.keyguard.KeyguardTransportControlView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:gravity="center_horizontal"
+    android:id="@+id/keyguard_transport_control">
+
+    <!-- FrameLayout used as scrim to show between album art and buttons -->
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:foreground="@*android:drawable/ic_lockscreen_player_background"
+        android:contentDescription="@*android:string/keygaurd_accessibility_media_controls">
+        <!-- Use ImageView for its cropping features; otherwise could be android:background -->
+        <ImageView
+            android:id="@+id/albumart"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="fill"
+            android:scaleType="centerCrop"
+            android:adjustViewBounds="false"
+        />
+    </FrameLayout>
+
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom">
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="8dip"
+            android:layout_marginStart="16dip"
+            android:layout_marginEnd="16dip"
+            android:gravity="center_horizontal"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+        />
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:layout_marginTop="5dip">
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1">
+                <ImageView
+                    android:id="@+id/btn_prev"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:src="@*android:drawable/ic_media_previous"
+                    android:clickable="true"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:padding="10dip"
+                    android:contentDescription="@*android:string/lockscreen_transport_prev_description"/>
+            </FrameLayout>
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1">
+                <ImageView
+                    android:id="@+id/btn_play"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:clickable="true"
+                    android:src="@*android:drawable/ic_media_play"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:padding="10dip"
+                    android:contentDescription="@*android:string/lockscreen_transport_play_description"/>
+            </FrameLayout>
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1">
+                <ImageView
+                    android:id="@+id/btn_next"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:clickable="true"
+                    android:src="@*android:drawable/ic_media_next"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:padding="10dip"
+                    android:contentDescription="@*android:string/lockscreen_transport_next_description"/>
+            </FrameLayout>
+        </LinearLayout>
+    </LinearLayout>
+
+</com.android.internal.policy.impl.keyguard.KeyguardTransportControlView>
\ No newline at end of file
diff --git a/core/res/res/layout/keyguard_widget_remove_drop_target.xml b/core/res/res/layout/keyguard_widget_remove_drop_target.xml
new file mode 100644
index 0000000..294c386
--- /dev/null
+++ b/core/res/res/layout/keyguard_widget_remove_drop_target.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:gravity="center"
+    android:padding="30dp"
+    android:paddingLeft="60dp"
+    android:paddingRight="60dp"
+    android:drawableLeft="@drawable/kg_widget_delete_drop_target"
+    android:drawablePadding="4dp"
+    android:text="@string/kg_reordering_delete_drop_target_text"
+    android:textColor="#FFF"
+    android:textSize="13sp"
+    android:shadowColor="#000"
+    android:shadowDy="1.0"
+    android:shadowRadius="1.0"
+    android:visibility="gone" />
diff --git a/core/res/res/layout/list_menu_item_icon.xml b/core/res/res/layout/list_menu_item_icon.xml
index 27dd9b8..a30be6a 100644
--- a/core/res/res/layout/list_menu_item_icon.xml
+++ b/core/res/res/layout/list_menu_item_icon.xml
@@ -19,8 +19,8 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center_vertical"
-    android:layout_marginLeft="8dip"
-    android:layout_marginRight="-8dip"
+    android:layout_marginStart="8dip"
+    android:layout_marginEnd="-8dip"
     android:layout_marginTop="8dip"
     android:layout_marginBottom="8dip"
     android:scaleType="centerInside"
diff --git a/core/res/res/layout/list_menu_item_layout.xml b/core/res/res/layout/list_menu_item_layout.xml
index 680eca7..0f37c71 100644
--- a/core/res/res/layout/list_menu_item_layout.xml
+++ b/core/res/res/layout/list_menu_item_layout.xml
@@ -26,8 +26,8 @@
         android:layout_weight="1"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
-        android:layout_marginLeft="?android:attr/listPreferredItemPaddingLeft"
-        android:layout_marginRight="?android:attr/listPreferredItemPaddingRight"
+        android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
+        android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
         android:duplicateParentState="true">
         
         <TextView 
@@ -35,7 +35,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_alignParentTop="true"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:textAppearance="?android:attr/textAppearanceListItemSmall"
             android:singleLine="true"
             android:duplicateParentState="true"
@@ -47,7 +47,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@id/title"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:singleLine="true"
             android:duplicateParentState="true" />
diff --git a/core/res/res/layout/locale_picker_item.xml b/core/res/res/layout/locale_picker_item.xml
index 19c0dee..94c9baf 100644
--- a/core/res/res/layout/locale_picker_item.xml
+++ b/core/res/res/layout/locale_picker_item.xml
@@ -20,10 +20,10 @@
     android:layout_width="match_parent"
     android:gravity="center_vertical"
     android:minHeight="?android:attr/listPreferredItemHeight"
-    android:paddingLeft="16dp"
+    android:paddingStart="16dp"
     android:paddingTop="8dp"
     android:paddingBottom="8dp"
-    android:paddingRight="16dp">
+    android:paddingEnd="16dp">
 
     <TextView android:id="@+id/locale"
         android:layout_width="wrap_content"
diff --git a/core/res/res/layout/media_controller.xml b/core/res/res/layout/media_controller.xml
index 313806cd..ad74a3a 100644
--- a/core/res/res/layout/media_controller.xml
+++ b/core/res/res/layout/media_controller.xml
@@ -44,11 +44,11 @@
             android:textSize="14sp"
             android:textStyle="bold"
             android:paddingTop="4dip"
-            android:paddingLeft="4dip"
+            android:paddingStart="4dip"
             android:layout_gravity="center_horizontal"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:paddingRight="4dip" />
+            android:paddingEnd="4dip" />
 
         <SeekBar
             android:id="@+id/mediacontroller_progress"
@@ -56,18 +56,18 @@
             android:layout_width="0dip"
             android:layout_weight="1"
             android:layout_height="32dip"
-            android:layout_alignParentLeft="true"
-            android:layout_alignParentRight="true" />
+            android:layout_alignParentStart="true"
+            android:layout_alignParentEnd="true" />
 
         <TextView android:id="@+id/time"
             android:textSize="14sp"
             android:textStyle="bold"
             android:paddingTop="4dip"
-            android:paddingRight="4dip"
+            android:paddingEnd="4dip"
             android:layout_gravity="center_horizontal"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:paddingLeft="4dip" />
+            android:paddingStart="4dip" />
     </LinearLayout>
 
 </LinearLayout>
diff --git a/core/res/res/layout/media_route_chooser_layout.xml b/core/res/res/layout/media_route_chooser_layout.xml
index 731c0d0..5fcb8c8 100644
--- a/core/res/res/layout/media_route_chooser_layout.xml
+++ b/core/res/res/layout/media_route_chooser_layout.xml
@@ -33,8 +33,8 @@
                  android:layout_width="0dp"
                  android:layout_height="wrap_content"
                  android:layout_weight="1"
-                 android:layout_marginLeft="8dp"
-                 android:layout_marginRight="8dp" />
+                 android:layout_marginStart="8dp"
+                 android:layout_marginEnd="8dp" />
         <ImageButton android:id="@+id/extended_settings"
                      android:layout_width="48dp"
                      android:layout_height="48dp"
diff --git a/core/res/res/layout/media_route_list_item.xml b/core/res/res/layout/media_route_list_item.xml
index 8ce6327..423d544 100644
--- a/core/res/res/layout/media_route_list_item.xml
+++ b/core/res/res/layout/media_route_list_item.xml
@@ -24,29 +24,33 @@
                android:layout_height="56dp"
                android:scaleType="center"
                android:id="@+id/icon"
-               android:visibility="gone" />
+               android:visibility="gone"
+               android:duplicateParentState="true" />
 
     <LinearLayout android:layout_width="0dp"
                   android:layout_height="match_parent"
                   android:layout_weight="1"
                   android:orientation="vertical"
-                  android:gravity="left|center_vertical"
-                  android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-                  android:paddingRight="?android:attr/listPreferredItemPaddingRight">
+                  android:gravity="start|center_vertical"
+                  android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+                  android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+                  android:duplicateParentState="true">
 
         <TextView android:id="@android:id/text1"
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content"
                   android:singleLine="true"
                   android:ellipsize="marquee"
-                  android:textAppearance="?android:attr/textAppearanceMedium" />
+                  android:textAppearance="?android:attr/textAppearanceMedium"
+                  android:duplicateParentState="true" />
 
         <TextView android:id="@android:id/text2"
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content"
                   android:singleLine="true"
                   android:ellipsize="marquee"
-                  android:textAppearance="?android:attr/textAppearanceSmall" />
+                  android:textAppearance="?android:attr/textAppearanceSmall"
+                  android:duplicateParentState="true" />
     </LinearLayout>
 
     <ImageButton
@@ -56,6 +60,7 @@
         android:background="?android:attr/selectableItemBackground"
         android:src="@drawable/ic_media_group_expand"
         android:scaleType="center"
-        android:visibility="gone" />
+        android:visibility="gone"
+        android:duplicateParentState="true" />
 
 </LinearLayout>
diff --git a/core/res/res/layout/media_route_list_item_checkable.xml b/core/res/res/layout/media_route_list_item_checkable.xml
index d0bffb6..5fb82f71 100644
--- a/core/res/res/layout/media_route_list_item_checkable.xml
+++ b/core/res/res/layout/media_route_list_item_checkable.xml
@@ -30,9 +30,9 @@
                   android:layout_height="match_parent"
                   android:layout_weight="1"
                   android:orientation="vertical"
-                  android:gravity="left|center_vertical"
-                  android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-                  android:paddingRight="?android:attr/listPreferredItemPaddingRight">
+                  android:gravity="start|center_vertical"
+                  android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+                  android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
 
         <TextView android:id="@android:id/text1"
                   android:layout_width="match_parent"
@@ -52,7 +52,7 @@
     <CheckBox
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginRight="16dp"
+        android:layout_marginEnd="16dp"
         android:id="@+id/check"
         android:focusable="false"
         android:clickable="false" />
diff --git a/core/res/res/layout/media_route_list_item_collapse_group.xml b/core/res/res/layout/media_route_list_item_collapse_group.xml
index d605c18..323e24d 100644
--- a/core/res/res/layout/media_route_list_item_collapse_group.xml
+++ b/core/res/res/layout/media_route_list_item_collapse_group.xml
@@ -22,8 +22,8 @@
         android:layout_width="match_parent"
         android:layout_height="?android:attr/listPreferredItemHeightSmall"
         android:background="#19ffffff"
-        android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-        android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
         android:gravity="center_vertical">
 
         <TextView android:layout_width="0dp"
diff --git a/core/res/res/layout/media_route_list_item_section_header.xml b/core/res/res/layout/media_route_list_item_section_header.xml
index 04bd0ea..949635f 100644
--- a/core/res/res/layout/media_route_list_item_section_header.xml
+++ b/core/res/res/layout/media_route_list_item_section_header.xml
@@ -27,8 +27,8 @@
         android:textStyle="bold"
         android:textAllCaps="true"
         android:gravity="center_vertical"
-        android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-        android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
         android:minHeight="24dp"
         />
 </FrameLayout>
diff --git a/core/res/res/layout/media_route_list_item_top_header.xml b/core/res/res/layout/media_route_list_item_top_header.xml
index 75decd3..0c49b24 100644
--- a/core/res/res/layout/media_route_list_item_top_header.xml
+++ b/core/res/res/layout/media_route_list_item_top_header.xml
@@ -23,7 +23,7 @@
     android:textStyle="bold"
     android:textAllCaps="true"
     android:gravity="center_vertical"
-    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
     android:minHeight="24dp"
 />
diff --git a/core/res/res/layout/menu_item.xml b/core/res/res/layout/menu_item.xml
index 7e9859f..df6462e 100644
--- a/core/res/res/layout/menu_item.xml
+++ b/core/res/res/layout/menu_item.xml
@@ -20,26 +20,26 @@
 <MenuItemView xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:focusable="true" >
 
     <TextView android:id="@+id/index"
-        android:paddingLeft="0dip" android:paddingTop="1dip"
-        android:paddingRight="8dip" android:paddingBottom="0dip"
+        android:paddingStart="0dip" android:paddingTop="1dip"
+        android:paddingEnd="8dip" android:paddingBottom="0dip"
         android:layout_width="17dip" android:layout_height="wrap_content"
         android:includeFontPadding="false" />
 
     <ImageView android:id="@+id/check"
-        android:paddingLeft="3dip" android:paddingTop="3dip"
-        android:paddingRight="3dip" android:paddingBottom="0dip"
+        android:paddingStart="3dip" android:paddingTop="3dip"
+        android:paddingEnd="3dip" android:paddingBottom="0dip"
         android:src="@drawable/menuitem_checkbox" android:scaleType="fitCenter"
         android:layout_width="wrap_content" android:layout_height="wrap_content" />
 
     <TextView android:id="@+id/title"
-        android:paddingLeft="0dip" android:paddingTop="1dip"
-        android:paddingRight="0dip" android:paddingBottom="2dip"
+        android:paddingStart="0dip" android:paddingTop="1dip"
+        android:paddingEnd="0dip" android:paddingBottom="2dip"
         android:layout_width="wrap_content" android:layout_height="wrap_content"
         android:layout_weight="1" android:includeFontPadding="false" />
 
     <TextView android:id="@+id/shortcut"
-        android:paddingLeft="8dip" android:paddingTop="0dip"
-        android:paddingRight="0dip" android:paddingBottom="0dip"
+        android:paddingStart="8dip" android:paddingTop="0dip"
+        android:paddingEnd="0dip" android:paddingBottom="0dip"
         android:layout_width="20dip" android:layout_height="wrap_content"
         android:gravity="center_horizontal"  android:includeFontPadding="true"/>
 
diff --git a/core/res/res/layout/notification_action.xml b/core/res/res/layout/notification_action.xml
index 33cbab9..4e7c74c 100644
--- a/core/res/res/layout/notification_action.xml
+++ b/core/res/res/layout/notification_action.xml
@@ -20,9 +20,9 @@
     android:layout_width="0dp"
     android:layout_height="48dp"
     android:layout_weight="1"
-    android:gravity="left|center_vertical"
+    android:gravity="start|center_vertical"
     android:drawablePadding="8dp"
-    android:paddingLeft="8dp"
+    android:paddingStart="8dp"
     android:textColor="#ccc"
     android:textSize="14dp"
     android:singleLine="true"
diff --git a/core/res/res/layout/notification_action_list.xml b/core/res/res/layout/notification_action_list.xml
index 591c9ea..400decc 100644
--- a/core/res/res/layout/notification_action_list.xml
+++ b/core/res/res/layout/notification_action_list.xml
@@ -21,6 +21,7 @@
     android:layout_height="wrap_content"
     android:orientation="horizontal"
     android:visibility="gone"
+    android:layout_marginBottom="8dp"
     android:showDividers="middle"
     android:divider="?android:attr/listDivider"
     android:dividerPadding="12dp"
diff --git a/core/res/res/layout/notification_action_tombstone.xml b/core/res/res/layout/notification_action_tombstone.xml
index 992b37c..9977cfe 100644
--- a/core/res/res/layout/notification_action_tombstone.xml
+++ b/core/res/res/layout/notification_action_tombstone.xml
@@ -20,9 +20,9 @@
     android:layout_width="0dp"
     android:layout_height="48dp"
     android:layout_weight="1"
-    android:gravity="left|center_vertical"
+    android:gravity="start|center_vertical"
     android:drawablePadding="8dp"
-    android:paddingLeft="8dp"
+    android:paddingStart="8dp"
     android:textColor="#ccc"
     android:textSize="14dp"
     android:singleLine="true"
diff --git a/core/res/res/layout/notification_intruder_content.xml b/core/res/res/layout/notification_intruder_content.xml
index 7f37032..ffd84d4 100644
--- a/core/res/res/layout/notification_intruder_content.xml
+++ b/core/res/res/layout/notification_intruder_content.xml
@@ -13,7 +13,7 @@
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="40dp"
-        android:layout_marginLeft="40dp"
+        android:layout_marginStart="40dp"
         android:orientation="vertical"
         >
         <TextView android:id="@+id/title"
diff --git a/core/res/res/layout/notification_template_base.xml b/core/res/res/layout/notification_template_base.xml
index 47bbbde..134f45e 100644
--- a/core/res/res/layout/notification_template_base.xml
+++ b/core/res/res/layout/notification_template_base.xml
@@ -33,10 +33,10 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="fill_vertical"
-        android:layout_marginLeft="@dimen/notification_large_icon_width"
+        android:layout_marginStart="@dimen/notification_large_icon_width"
         android:minHeight="@dimen/notification_large_icon_height"
         android:orientation="vertical"
-        android:paddingRight="8dp"
+        android:paddingEnd="8dp"
         android:paddingTop="2dp"
         android:paddingBottom="2dp"
         android:gravity="top"
@@ -46,7 +46,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:paddingTop="6dp"
-            android:layout_marginLeft="8dp"
+            android:layout_marginStart="8dp"
             android:orientation="horizontal"
             >
             <TextView android:id="@+id/title"
@@ -81,7 +81,7 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="-2dp"
             android:layout_marginBottom="-2dp"
-            android:layout_marginLeft="8dp"
+            android:layout_marginStart="8dp"
             android:singleLine="true"
             android:fadingEdge="horizontal"
             android:ellipsize="marquee"
@@ -91,7 +91,7 @@
             android:id="@android:id/progress"
             android:layout_width="match_parent"
             android:layout_height="12dp"
-            android:layout_marginLeft="8dp"
+            android:layout_marginStart="8dp"
             android:visibility="gone"
             style="?android:attr/progressBarStyleHorizontal"
             />
@@ -101,7 +101,7 @@
             android:layout_height="wrap_content"
             android:orientation="horizontal"
             android:gravity="center_vertical"
-            android:layout_marginLeft="8dp"
+            android:layout_marginStart="8dp"
             >
             <TextView android:id="@+id/text"
                 android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
@@ -121,14 +121,14 @@
                 android:layout_weight="0"
                 android:singleLine="true"
                 android:gravity="center"
-                android:paddingLeft="8dp"
+                android:paddingStart="8dp"
                 />
             <ImageView android:id="@+id/right_icon"
                 android:layout_width="16dp"
                 android:layout_height="16dp"
                 android:layout_gravity="center"
                 android:layout_weight="0"
-                android:layout_marginLeft="8dp"
+                android:layout_marginStart="8dp"
                 android:scaleType="centerInside"
                 android:visibility="gone"
                 android:drawableAlpha="153"
diff --git a/core/res/res/layout/notification_template_big_base.xml b/core/res/res/layout/notification_template_big_base.xml
index 69f0a24..b5da486 100644
--- a/core/res/res/layout/notification_template_big_base.xml
+++ b/core/res/res/layout/notification_template_big_base.xml
@@ -40,7 +40,7 @@
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="@dimen/notification_large_icon_width"
+            android:layout_marginStart="@dimen/notification_large_icon_width"
             android:minHeight="@dimen/notification_large_icon_height"
             android:paddingTop="2dp"
             android:orientation="vertical"
@@ -50,8 +50,8 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:paddingTop="6dp"
-                android:layout_marginRight="8dp"
-                android:layout_marginLeft="8dp"
+                android:layout_marginEnd="8dp"
+                android:layout_marginStart="8dp"
                 android:orientation="horizontal"
                 >
                 <TextView android:id="@+id/title"
@@ -86,8 +86,8 @@
                 android:layout_height="wrap_content"
                 android:layout_marginTop="-2dp"
                 android:layout_marginBottom="-2dp"
-                android:layout_marginLeft="8dp"
-                android:layout_marginRight="8dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
                 android:singleLine="true"
                 android:fadingEdge="horizontal"
                 android:ellipsize="marquee"
@@ -97,8 +97,8 @@
                 android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="8dp"
-                android:layout_marginRight="8dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
                 android:singleLine="false"
                 android:visibility="gone"
                 />
@@ -106,8 +106,8 @@
                 android:id="@+id/line3"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="8dp"
-                android:layout_marginRight="8dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
                 android:orientation="horizontal"
                 android:gravity="center_vertical"
                 >
@@ -129,14 +129,14 @@
                     android:layout_weight="0"
                     android:singleLine="true"
                     android:gravity="center"
-                    android:paddingLeft="8dp"
+                    android:paddingStart="8dp"
                     />
                 <ImageView android:id="@+id/right_icon"
                     android:layout_width="16dp"
                     android:layout_height="16dp"
                     android:layout_gravity="center"
                     android:layout_weight="0"
-                    android:layout_marginLeft="8dp"
+                    android:layout_marginStart="8dp"
                     android:scaleType="centerInside"
                     android:visibility="gone"
                     android:drawableAlpha="153"
@@ -147,8 +147,8 @@
                 android:layout_width="match_parent"
                 android:layout_height="12dp"
                 android:layout_marginBottom="8dp"
-                android:layout_marginLeft="8dp"
-                android:layout_marginRight="8dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
                 android:visibility="gone"
                 style="?android:attr/progressBarStyleHorizontal"
                 />
@@ -163,7 +163,7 @@
             layout="@layout/notification_action_list"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="@dimen/notification_large_icon_width"
+            android:layout_marginStart="@dimen/notification_large_icon_width"
             />
     </LinearLayout>
 </FrameLayout>
diff --git a/core/res/res/layout/notification_template_big_picture.xml b/core/res/res/layout/notification_template_big_picture.xml
index 172dfe5..f3f3951 100644
--- a/core/res/res/layout/notification_template_big_picture.xml
+++ b/core/res/res/layout/notification_template_big_picture.xml
@@ -46,7 +46,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginTop="208dp"
-        android:paddingLeft="64dp"
+        android:paddingStart="64dp"
         android:layout_gravity="bottom"
         android:background="#CC111111"
         >
diff --git a/core/res/res/layout/notification_template_big_text.xml b/core/res/res/layout/notification_template_big_text.xml
index 0b3386b..01f1acf 100644
--- a/core/res/res/layout/notification_template_big_text.xml
+++ b/core/res/res/layout/notification_template_big_text.xml
@@ -32,25 +32,26 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="fill_vertical"
-        android:layout_marginLeft="@dimen/notification_large_icon_width"
+        android:layout_marginStart="@dimen/notification_large_icon_width"
         android:orientation="vertical"
-        android:paddingTop="2dp"
+        android:paddingTop="0dp"
         android:paddingBottom="2dp"
         android:gravity="top"
         >
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:minHeight="@dimen/notification_large_icon_height"
             android:orientation="vertical"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:layout_weight="1"
             >
             <LinearLayout
                 android:id="@+id/line1"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:paddingTop="6dp"
+                android:paddingTop="8dp"
                 android:orientation="horizontal"
                 android:layout_gravity="top"
                 android:layout_weight="0"
@@ -87,7 +88,7 @@
                 android:layout_height="wrap_content"
                 android:layout_marginTop="-2dp"
                 android:layout_marginBottom="-2dp"
-                android:layout_marginRight="8dp"
+                android:layout_marginEnd="8dp"
                 android:singleLine="true"
                 android:fadingEdge="horizontal"
                 android:ellipsize="marquee"
@@ -99,7 +100,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="12dp"
                 android:layout_marginBottom="8dp"
-                android:layout_marginRight="8dp"
+                android:layout_marginEnd="8dp"
                 android:visibility="gone"
                 android:layout_weight="0"
                 style="?android:attr/progressBarStyleHorizontal"
@@ -109,7 +110,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="0dp"
                 android:layout_marginBottom="10dp"
-                android:layout_marginRight="8dp"
+                android:layout_marginEnd="8dp"
                 android:singleLine="false"
                 android:visibility="gone"
                 android:maxLines="8"
@@ -142,9 +143,9 @@
             android:id="@+id/line3"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="8dp"
+            android:layout_marginStart="8dp"
             android:layout_marginBottom="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginEnd="8dp"
             android:orientation="horizontal"
             android:layout_weight="0"
             android:gravity="center_vertical"
@@ -167,14 +168,14 @@
                 android:layout_weight="0"
                 android:singleLine="true"
                 android:gravity="center"
-                android:paddingLeft="8dp"
+                android:paddingStart="8dp"
                 />
             <ImageView android:id="@+id/right_icon"
                 android:layout_width="16dp"
                 android:layout_height="16dp"
                 android:layout_gravity="center"
                 android:layout_weight="0"
-                android:layout_marginLeft="8dp"
+                android:layout_marginStart="8dp"
                 android:scaleType="centerInside"
                 android:visibility="gone"
                 android:drawableAlpha="153"
diff --git a/core/res/res/layout/notification_template_inbox.xml b/core/res/res/layout/notification_template_inbox.xml
index 8ee6263..1b7e659 100644
--- a/core/res/res/layout/notification_template_inbox.xml
+++ b/core/res/res/layout/notification_template_inbox.xml
@@ -33,166 +33,181 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="fill_vertical"
-        android:layout_marginLeft="@dimen/notification_large_icon_width"
+        android:layout_marginStart="@dimen/notification_large_icon_width"
         android:minHeight="@dimen/notification_large_icon_height"
         android:orientation="vertical"
-        android:paddingTop="2dp"
+        android:paddingTop="0dp"
         android:paddingBottom="2dp"
         android:gravity="top"
         >
         <LinearLayout
-            android:id="@+id/line1"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
-            android:paddingTop="6dp"
-            android:orientation="horizontal"
-            android:layout_weight="0"
+            android:minHeight="@dimen/notification_large_icon_height"
+            android:paddingTop="2dp"
+            android:orientation="vertical"
             >
-            <TextView android:id="@+id/title"
-                android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
+            <LinearLayout
+                android:id="@+id/line1"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:paddingTop="6dp"
+                android:orientation="horizontal"
+                android:layout_weight="0"
+                >
+                <TextView android:id="@+id/title"
+                    android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:fadingEdge="horizontal"
+                    android:layout_weight="1"
+                    />
+                <ViewStub android:id="@+id/time"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_time"
+                    />
+                <ViewStub android:id="@+id/chronometer"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_chronometer"
+                    />
+            </LinearLayout>
+            <TextView android:id="@+id/text2"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Line2"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="-2dp"
+                android:layout_marginBottom="-2dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
                 android:singleLine="true"
-                android:ellipsize="marquee"
                 android:fadingEdge="horizontal"
+                android:ellipsize="marquee"
+                android:visibility="gone"
+                android:layout_weight="0"
+                />
+            <ProgressBar
+                android:id="@android:id/progress"
+                android:layout_width="match_parent"
+                android:layout_height="12dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:visibility="gone"
+                android:layout_weight="0"
+                style="?android:attr/progressBarStyleHorizontal"
+                />
+            <TextView android:id="@+id/inbox_text0"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
                 android:layout_weight="1"
                 />
-            <ViewStub android:id="@+id/time"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center"
-                android:layout_weight="0"
+            <TextView android:id="@+id/inbox_text1"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
                 android:visibility="gone"
-                android:layout="@layout/notification_template_part_time"
+                android:layout_weight="1"
                 />
-            <ViewStub android:id="@+id/chronometer"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center"
-                android:layout_weight="0"
+            <TextView android:id="@+id/inbox_text2"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
                 android:visibility="gone"
-                android:layout="@layout/notification_template_part_chronometer"
+                android:layout_weight="1"
                 />
+            <TextView android:id="@+id/inbox_text3"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text4"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text5"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text6"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_more"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                android:text="@android:string/ellipsis"
+                />
+            <FrameLayout 
+                android:id="@+id/inbox_end_pad"
+                android:layout_width="match_parent"
+                android:layout_height="8dip"
+                android:visibility="gone"
+                android:layout_weight="0"
+            />
         </LinearLayout>
-        <TextView android:id="@+id/text2"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Line2"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="-2dp"
-            android:layout_marginBottom="-2dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
-            android:singleLine="true"
-            android:fadingEdge="horizontal"
-            android:ellipsize="marquee"
-            android:visibility="gone"
-            android:layout_weight="0"
-            />
-        <ProgressBar
-            android:id="@android:id/progress"
-            android:layout_width="match_parent"
-            android:layout_height="12dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
-            android:visibility="gone"
-            android:layout_weight="0"
-            style="?android:attr/progressBarStyleHorizontal"
-            />
-        <TextView android:id="@+id/inbox_text0"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text1"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text2"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text3"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text4"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text5"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text6"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_more"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            android:text="@android:string/ellipsis"
-            />
         <ImageView
             android:layout_width="match_parent"
-            android:layout_height="1px"
+            android:layout_height="1dip"
+            android:layout_marginTop="-1px"
             android:id="@+id/action_divider"
-            android:visibility="gone"
             android:background="?android:attr/dividerHorizontal" />
         <include
             layout="@layout/notification_action_list"
@@ -202,9 +217,9 @@
             />
         <ImageView
             android:layout_width="match_parent"
-            android:layout_height="1px"
+            android:layout_height="1dip"
+            android:layout_marginTop="-1px"
             android:id="@+id/overflow_divider"
-            android:layout_marginTop="8dp"
             android:visibility="visible"
             android:background="?android:attr/dividerHorizontal" />
         <LinearLayout
@@ -212,9 +227,9 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_marginTop="8dp"
-            android:layout_marginLeft="8dp"
+            android:layout_marginStart="8dp"
             android:layout_marginBottom="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginEnd="8dp"
             android:orientation="horizontal"
             android:layout_weight="0"
             android:gravity="center_vertical"
@@ -237,14 +252,14 @@
                 android:layout_weight="0"
                 android:singleLine="true"
                 android:gravity="center"
-                android:paddingLeft="8dp"
+                android:paddingStart="8dp"
                 />
             <ImageView android:id="@+id/right_icon"
                 android:layout_width="16dp"
                 android:layout_height="16dp"
                 android:layout_gravity="center"
                 android:layout_weight="0"
-                android:layout_marginLeft="8dp"
+                android:layout_marginStart="8dp"
                 android:scaleType="centerInside"
                 android:visibility="gone"
                 android:drawableAlpha="153"
diff --git a/core/res/res/layout/notification_template_part_chronometer.xml b/core/res/res/layout/notification_template_part_chronometer.xml
index 382b0e4..aa9c4dc 100644
--- a/core/res/res/layout/notification_template_part_chronometer.xml
+++ b/core/res/res/layout/notification_template_part_chronometer.xml
@@ -22,5 +22,5 @@
     android:layout_weight="0"
     android:singleLine="true"
     android:gravity="center"
-    android:paddingLeft="8dp"
+    android:paddingStart="8dp"
     />
diff --git a/core/res/res/layout/notification_template_part_time.xml b/core/res/res/layout/notification_template_part_time.xml
index 410fcaf..2bd6c3f 100644
--- a/core/res/res/layout/notification_template_part_time.xml
+++ b/core/res/res/layout/notification_template_part_time.xml
@@ -22,5 +22,5 @@
     android:layout_weight="0"
     android:singleLine="true"
     android:gravity="center"
-    android:paddingLeft="8dp"
+    android:paddingStart="8dp"
     />
diff --git a/core/res/res/layout/overlay_display_window.xml b/core/res/res/layout/overlay_display_window.xml
new file mode 100644
index 0000000..36b4a0d
--- /dev/null
+++ b/core/res/res/layout/overlay_display_window.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="match_parent"
+      android:layout_height="match_parent"
+      android:background="#000000">
+    <TextureView android:id="@+id/overlay_display_window_texture"
+               android:layout_width="0px"
+               android:layout_height="0px" />
+    <TextView android:id="@+id/overlay_display_window_title"
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:layout_gravity="top|center_horizontal" />
+</FrameLayout>
diff --git a/core/res/res/layout/permissions_account_and_authtokentype.xml b/core/res/res/layout/permissions_account_and_authtokentype.xml
index 833572603..ac5b08a 100644
--- a/core/res/res/layout/permissions_account_and_authtokentype.xml
+++ b/core/res/res/layout/permissions_account_and_authtokentype.xml
@@ -29,7 +29,7 @@
         android:layout_width="30dip"
         android:layout_height="30dip"
         android:drawable="@drawable/ic_bullet_key_permission"
-        android:layout_alignParentLeft="true"
+        android:layout_alignParentStart="true"
         android:scaleType="fitCenter" />
 
 
@@ -37,8 +37,8 @@
         android:id="@+id/account_type"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textStyle="bold"
-        android:paddingLeft="6dip"
-        android:layout_toRightOf="@id/permission_icon"
+        android:paddingStart="6dip"
+        android:layout_toEndOf="@id/permission_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
@@ -47,9 +47,9 @@
         android:textAppearance="?android:attr/textAppearanceSmall"
         android:layout_marginTop="-4dip"
         android:paddingBottom="8dip"
-        android:paddingLeft="6dip"
+        android:paddingStart="6dip"
         android:layout_below="@id/account_type"
-        android:layout_toRightOf="@id/permission_icon"
+        android:layout_toEndOf="@id/permission_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
@@ -58,9 +58,9 @@
         android:textAppearance="?android:attr/textAppearanceSmall"
         android:layout_marginTop="-4dip"
         android:paddingBottom="8dip"
-        android:paddingLeft="6dip"
+        android:paddingStart="6dip"
         android:layout_below="@id/account_name"
-        android:layout_toRightOf="@id/permission_icon"
+        android:layout_toEndOf="@id/permission_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
diff --git a/core/res/res/layout/permissions_package_list_item.xml b/core/res/res/layout/permissions_package_list_item.xml
index 3c9570e..75ce0a7 100644
--- a/core/res/res/layout/permissions_package_list_item.xml
+++ b/core/res/res/layout/permissions_package_list_item.xml
@@ -28,7 +28,7 @@
         android:id="@+id/package_icon"
         android:layout_width="30dip"
         android:layout_height="30dip"
-        android:layout_alignParentLeft="true"
+        android:layout_alignParentStart="true"
         android:src="@drawable/ic_text_dot"
         android:scaleType="fitCenter" />
 
@@ -37,8 +37,8 @@
         android:id="@+id/package_label"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textStyle="bold"
-        android:paddingLeft="6dip"
-        android:layout_toRightOf="@id/package_icon"
+        android:paddingStart="6dip"
+        android:layout_toEndOf="@id/package_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
diff --git a/core/res/res/layout/popup_menu_item_layout.xml b/core/res/res/layout/popup_menu_item_layout.xml
index 1a12c01..f67ed4e 100644
--- a/core/res/res/layout/popup_menu_item_layout.xml
+++ b/core/res/res/layout/popup_menu_item_layout.xml
@@ -18,7 +18,7 @@
     android:layout_width="match_parent"
     android:layout_height="?android:attr/dropdownListPreferredItemHeight"
     android:minWidth="196dip"
-    android:paddingRight="16dip">
+    android:paddingEnd="16dip">
     
     <!-- Icon will be inserted here. -->
     
@@ -28,7 +28,7 @@
         android:layout_weight="1"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
-        android:layout_marginLeft="16dip"
+        android:layout_marginStart="16dip"
         android:duplicateParentState="true">
         
         <TextView 
@@ -36,7 +36,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_alignParentTop="true"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
             android:singleLine="true"
             android:duplicateParentState="true"
@@ -48,7 +48,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@id/title"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:textAppearance="?android:attr/textAppearanceSmallPopupMenu"
             android:singleLine="true"
             android:duplicateParentState="true" />
diff --git a/core/res/res/layout/preference.xml b/core/res/res/layout/preference.xml
index 448f89a..824ca93 100644
--- a/core/res/res/layout/preference.xml
+++ b/core/res/res/layout/preference.xml
@@ -22,7 +22,7 @@
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center_vertical"
-    android:paddingRight="?android:attr/scrollbarSize"
+    android:paddingEnd="?android:attr/scrollbarSize"
     android:background="?android:attr/selectableItemBackground" >
 
     <ImageView
@@ -35,8 +35,8 @@
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="15dip"
-        android:layout_marginRight="6dip"
+        android:layout_marginStart="15dip"
+        android:layout_marginEnd="6dip"
         android:layout_marginTop="6dip"
         android:layout_marginBottom="6dip"
         android:layout_weight="1">
@@ -53,7 +53,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="?android:attr/textColorSecondary"
             android:maxLines="4" />
diff --git a/core/res/res/layout/preference_category_holo.xml b/core/res/res/layout/preference_category_holo.xml
index 81e595c..f2c63ae6 100644
--- a/core/res/res/layout/preference_category_holo.xml
+++ b/core/res/res/layout/preference_category_holo.xml
@@ -18,5 +18,5 @@
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
     style="?android:attr/listSeparatorTextViewStyle"
     android:id="@+android:id/title"
-    android:paddingLeft="@dimen/preference_item_padding_side"
-    android:paddingRight="@dimen/preference_item_padding_side" />
+    android:paddingStart="@dimen/preference_item_padding_side"
+    android:paddingEnd="@dimen/preference_item_padding_side" />
diff --git a/core/res/res/layout/preference_child.xml b/core/res/res/layout/preference_child.xml
index e9b50e0..6323c0e 100644
--- a/core/res/res/layout/preference_child.xml
+++ b/core/res/res/layout/preference_child.xml
@@ -20,8 +20,8 @@
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center_vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="?android:attr/scrollbarSize">
+    android:paddingStart="16dip"
+    android:paddingEnd="?android:attr/scrollbarSize">
 
     <LinearLayout
         android:layout_width="wrap_content"
@@ -40,7 +40,7 @@
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginRight="6dip"
+        android:layout_marginEnd="6dip"
         android:layout_marginTop="6dip"
         android:layout_marginBottom="6dip"
         android:layout_weight="1">
@@ -57,7 +57,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="?android:attr/textColorSecondary"
             android:maxLines="4" />
diff --git a/core/res/res/layout/preference_child_holo.xml b/core/res/res/layout/preference_child_holo.xml
index 41678628..17f97fd 100644
--- a/core/res/res/layout/preference_child_holo.xml
+++ b/core/res/res/layout/preference_child_holo.xml
@@ -20,8 +20,8 @@
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center_vertical"
-    android:paddingLeft="@dimen/preference_child_padding_side"
-    android:paddingRight="?android:attr/scrollbarSize">
+    android:paddingStart="@dimen/preference_child_padding_side"
+    android:paddingEnd="?android:attr/scrollbarSize">
 
     <LinearLayout
         android:layout_width="wrap_content"
@@ -34,14 +34,14 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center"
-            android:paddingRight="@dimen/preference_item_padding_inner" />
+            android:paddingEnd="@dimen/preference_item_padding_inner" />
     </LinearLayout>
 
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_weight="1"
-        android:paddingRight="@dimen/preference_item_padding_inner"
+        android:paddingEnd="@dimen/preference_item_padding_inner"
         android:paddingTop="6dip"
         android:paddingBottom="6dip">
 
@@ -57,7 +57,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="?android:attr/textColorSecondary"
             android:maxLines="10" />
diff --git a/core/res/res/layout/preference_header_item.xml b/core/res/res/layout/preference_header_item.xml
index a987de3..0d582a0 100644
--- a/core/res/res/layout/preference_header_item.xml
+++ b/core/res/res/layout/preference_header_item.xml
@@ -21,21 +21,21 @@
     android:minHeight="48dp"
     android:background="?android:attr/activatedBackgroundIndicator"
     android:gravity="center_vertical"
-    android:paddingRight="?android:attr/scrollbarSize">
+    android:paddingEnd="?android:attr/scrollbarSize">
 
     <ImageView
         android:id="@+id/icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="6dip"
-        android:layout_marginRight="6dip"
+        android:layout_marginStart="6dip"
+        android:layout_marginEnd="6dip"
         android:layout_gravity="center" />
 
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="2dip"
-        android:layout_marginRight="6dip"
+        android:layout_marginStart="2dip"
+        android:layout_marginEnd="6dip"
         android:layout_marginTop="6dip"
         android:layout_marginBottom="6dip"
         android:layout_weight="1">
@@ -52,7 +52,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:ellipsize="end"
             android:maxLines="2" />
diff --git a/core/res/res/layout/preference_holo.xml b/core/res/res/layout/preference_holo.xml
index e574219..1cc803b 100644
--- a/core/res/res/layout/preference_holo.xml
+++ b/core/res/res/layout/preference_holo.xml
@@ -22,8 +22,8 @@
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center_vertical"
-    android:paddingLeft="@dimen/preference_item_padding_side"
-    android:paddingRight="?android:attr/scrollbarSize">
+    android:paddingStart="@dimen/preference_item_padding_side"
+    android:paddingEnd="?android:attr/scrollbarSize">
 
     <LinearLayout
         android:layout_width="wrap_content"
@@ -33,18 +33,20 @@
         android:orientation="horizontal">
         <ImageView
             android:id="@+android:id/icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
             android:layout_gravity="center"
             android:minWidth="48dp"
-            android:paddingRight="@dimen/preference_item_padding_inner" />
+            android:scaleType="centerInside"
+            android:layout_marginEnd="@dimen/preference_item_padding_inner"
+             />
     </LinearLayout>
 
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_weight="1"
-        android:paddingRight="@dimen/preference_item_padding_inner"
+        android:paddingEnd="@dimen/preference_item_padding_inner"
         android:paddingTop="6dip"
         android:paddingBottom="6dip">
 
@@ -55,12 +57,12 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:ellipsize="marquee"
             android:fadingEdge="horizontal" />
-            
+
         <TextView android:id="@+android:id/summary"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="?android:attr/textColorSecondary"
             android:maxLines="10" />
diff --git a/core/res/res/layout/preference_information.xml b/core/res/res/layout/preference_information.xml
index 32cbb90..e3be382 100644
--- a/core/res/res/layout/preference_information.xml
+++ b/core/res/res/layout/preference_information.xml
@@ -22,13 +22,13 @@
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center_vertical"
-    android:paddingRight="?android:attr/scrollbarSize">
+    android:paddingEnd="?android:attr/scrollbarSize">
 
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="16sp"
-        android:layout_marginRight="6sp"
+        android:layout_marginStart="16sp"
+        android:layout_marginEnd="6sp"
         android:layout_marginTop="6sp"
         android:layout_marginBottom="6sp"
         android:layout_weight="1">
@@ -44,7 +44,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="?android:attr/textColorSecondary"
             android:maxLines="2" />
diff --git a/core/res/res/layout/preference_information_holo.xml b/core/res/res/layout/preference_information_holo.xml
index 5e03cfb..d0d446c 100644
--- a/core/res/res/layout/preference_information_holo.xml
+++ b/core/res/res/layout/preference_information_holo.xml
@@ -22,8 +22,8 @@
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center_vertical"
-    android:paddingLeft="@dimen/preference_item_padding_side"
-    android:paddingRight="?android:attr/scrollbarSize">
+    android:paddingStart="@dimen/preference_item_padding_side"
+    android:paddingEnd="?android:attr/scrollbarSize">
 
     <LinearLayout
         android:layout_width="wrap_content"
@@ -36,14 +36,14 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center"
-            android:paddingRight="@dimen/preference_item_padding_inner" />
+            android:paddingEnd="@dimen/preference_item_padding_inner" />
     </LinearLayout>
 
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_weight="1"
-        android:paddingRight="@dimen/preference_item_padding_inner"
+        android:paddingEnd="@dimen/preference_item_padding_inner"
         android:paddingTop="6dip"
         android:paddingBottom="6dip">
 
@@ -58,7 +58,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="?android:attr/textColorSecondary"
             android:maxLines="10" />
diff --git a/core/res/res/layout/preference_list_content.xml b/core/res/res/layout/preference_list_content.xml
index 70bc59a..5812053 100644
--- a/core/res/res/layout/preference_list_content.xml
+++ b/core/res/res/layout/preference_list_content.xml
@@ -34,16 +34,16 @@
             android:orientation="vertical"
             android:layout_width="0px"
             android:layout_height="match_parent"
-            android:layout_marginRight="@dimen/preference_screen_side_margin_negative"
-            android:layout_marginLeft="@dimen/preference_screen_side_margin"
+            android:layout_marginEnd="@dimen/preference_screen_side_margin_negative"
+            android:layout_marginStart="@dimen/preference_screen_side_margin"
             android:layout_weight="@integer/preferences_left_pane_weight">
 
             <ListView android:id="@android:id/list"
                 android:layout_width="match_parent"
                 android:layout_height="0px"
                 android:layout_weight="1"
-                android:paddingLeft="@dimen/preference_screen_header_padding_side"
-                android:paddingRight="@dimen/preference_screen_header_padding_side"
+                android:paddingStart="@dimen/preference_screen_header_padding_side"
+                android:paddingEnd="@dimen/preference_screen_header_padding_side"
                 android:paddingTop="@dimen/preference_screen_header_vertical_padding"
                 android:paddingBottom="@dimen/preference_screen_header_vertical_padding"
                 android:clipToPadding="false"
@@ -92,14 +92,14 @@
             android:layout_width="150dip"
             android:layout_height="wrap_content"
             android:layout_margin="5dip"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:text="@string/back_button_label"
         />
         <LinearLayout
             android:orientation="horizontal"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_alignParentRight="true">
+            android:layout_alignParentEnd="true">
 
             <Button android:id="@+id/skip_button"
                 android:layout_width="150dip"
diff --git a/core/res/res/layout/preference_list_content_single.xml b/core/res/res/layout/preference_list_content_single.xml
index 16afe13..726ce78 100644
--- a/core/res/res/layout/preference_list_content_single.xml
+++ b/core/res/res/layout/preference_list_content_single.xml
@@ -64,14 +64,14 @@
             android:layout_width="150dip"
             android:layout_height="wrap_content"
             android:layout_margin="5dip"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:text="@string/back_button_label"
         />
         <LinearLayout
             android:orientation="horizontal"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_alignParentRight="true">
+            android:layout_alignParentEnd="true">
 
             <Button android:id="@+id/skip_button"
                 android:layout_width="150dip"
diff --git a/core/res/res/layout/preference_list_fragment.xml b/core/res/res/layout/preference_list_fragment.xml
index fdef4fc..abfb1f2 100644
--- a/core/res/res/layout/preference_list_fragment.xml
+++ b/core/res/res/layout/preference_list_fragment.xml
@@ -30,8 +30,8 @@
         android:layout_weight="1"
         android:paddingTop="0dip"
         android:paddingBottom="@dimen/preference_fragment_padding_bottom"
-        android:paddingLeft="@dimen/preference_fragment_padding_side"
-        android:paddingRight="@dimen/preference_fragment_padding_side"
+        android:paddingStart="@dimen/preference_fragment_padding_side"
+        android:paddingEnd="@dimen/preference_fragment_padding_side"
         android:scrollbarStyle="@integer/preference_fragment_scrollbarStyle"
         android:clipToPadding="false"
         android:drawSelectorOnTop="false"
@@ -55,14 +55,14 @@
             android:layout_width="150dip"
             android:layout_height="wrap_content"
             android:layout_margin="5dip"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:text="@string/back_button_label"
         />
         <LinearLayout
             android:orientation="horizontal"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_alignParentRight="true">
+            android:layout_alignParentEnd="true">
 
             <Button android:id="@+id/skip_button"
                 android:layout_width="150dip"
diff --git a/core/res/res/layout/preference_widget_seekbar.xml b/core/res/res/layout/preference_widget_seekbar.xml
index e4cf86d..c427965 100644
--- a/core/res/res/layout/preference_widget_seekbar.xml
+++ b/core/res/res/layout/preference_widget_seekbar.xml
@@ -22,7 +22,7 @@
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center_vertical"
-    android:paddingRight="?android:attr/scrollbarSize">
+    android:paddingEnd="?android:attr/scrollbarSize">
 
     <LinearLayout
         android:layout_width="wrap_content"
@@ -42,8 +42,8 @@
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="16dip"
-        android:layout_marginRight="8dip"
+        android:layout_marginStart="16dip"
+        android:layout_marginEnd="8dip"
         android:layout_marginTop="6dip"
         android:layout_marginBottom="6dip"
         android:layout_weight="1">
@@ -60,7 +60,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="?android:attr/textColorSecondary"
             android:maxLines="4" />
@@ -70,7 +70,7 @@
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
             android:layout_below="@android:id/summary"
-            android:layout_alignLeft="@android:id/title"
+            android:layout_alignStart="@android:id/title"
             android:minWidth="@dimen/preference_widget_width"
             android:gravity="center"
             android:orientation="vertical" />
@@ -79,8 +79,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/summary"
-            android:layout_toRightOf="@android:id/widget_frame"
-            android:layout_alignParentRight="true" />
+            android:layout_toEndOf="@android:id/widget_frame"
+            android:layout_alignParentEnd="true" />
 
     </RelativeLayout>
 
diff --git a/core/res/res/layout/preferences.xml b/core/res/res/layout/preferences.xml
index f0c2535..c631f6c 100644
--- a/core/res/res/layout/preferences.xml
+++ b/core/res/res/layout/preferences.xml
@@ -19,7 +19,7 @@
 <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:layout_marginRight="4dip"
+    android:layout_marginEnd="4dip"
     android:layout_gravity="center_vertical"
     android:background="@drawable/btn_circle"
     android:src="@drawable/ic_btn_round_more" />
diff --git a/core/res/res/layout/progress_dialog.xml b/core/res/res/layout/progress_dialog.xml
index 08e720f..0d3cd4a 100644
--- a/core/res/res/layout/progress_dialog.xml
+++ b/core/res/res/layout/progress_dialog.xml
@@ -27,9 +27,9 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:baselineAligned="false"
-        android:paddingLeft="8dip"
+        android:paddingStart="8dip"
         android:paddingTop="10dip"
-        android:paddingRight="8dip"
+        android:paddingEnd="8dip"
         android:paddingBottom="10dip">
 
         <ProgressBar android:id="@android:id/progress"
@@ -37,7 +37,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:max="10000"
-            android:layout_marginRight="12dip" />
+            android:layout_marginEnd="12dip" />
 
         <TextView android:id="@+id/message"
             android:layout_width="match_parent"
diff --git a/core/res/res/layout/progress_dialog_holo.xml b/core/res/res/layout/progress_dialog_holo.xml
index 9631efd..6aad9ea 100644
--- a/core/res/res/layout/progress_dialog_holo.xml
+++ b/core/res/res/layout/progress_dialog_holo.xml
@@ -33,7 +33,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:max="10000"
-            android:layout_marginRight="16dip" />
+            android:layout_marginEnd="16dip" />
 
         <TextView android:id="@+id/message"
             android:layout_width="match_parent"
diff --git a/core/res/res/layout/resolve_list_item.xml b/core/res/res/layout/resolve_list_item.xml
index 1d464aa..61cecae 100644
--- a/core/res/res/layout/resolve_list_item.xml
+++ b/core/res/res/layout/resolve_list_item.xml
@@ -33,8 +33,8 @@
               android:gravity="center"
               android:minLines="2"
               android:maxLines="2"
-              android:paddingLeft="4dip"
-              android:paddingRight="4dip" />
+              android:paddingStart="4dip"
+              android:paddingEnd="4dip" />
 
     <!-- Activity icon when presenting dialog
          Size will be filled in by ResolverActivity -->
@@ -51,7 +51,7 @@
               android:gravity="center"
               android:minLines="2"
               android:maxLines="2"
-              android:paddingLeft="4dip"
-              android:paddingRight="4dip" />
+              android:paddingStart="4dip"
+              android:paddingEnd="4dip" />
 </LinearLayout>
 
diff --git a/core/res/res/layout/resolver_grid.xml b/core/res/res/layout/resolver_grid.xml
index 4a0e84a..d271c1a 100644
--- a/core/res/res/layout/resolver_grid.xml
+++ b/core/res/res/layout/resolver_grid.xml
@@ -48,7 +48,7 @@
         android:measureWithLargestChild="true">
         <Button android:id="@+id/button_always"
                 android:layout_width="wrap_content"
-                android:layout_gravity="right"
+                android:layout_gravity="end"
                 android:layout_weight="1"
                 android:maxLines="2"
                 android:minHeight="@dimen/alert_dialog_button_bar_height"
@@ -60,7 +60,7 @@
                 android:onClick="onButtonClick" />
         <Button android:id="@+id/button_once"
                 android:layout_width="wrap_content"
-                android:layout_gravity="left"
+                android:layout_gravity="start"
                 android:layout_weight="1"
                 android:maxLines="2"
                 style="?android:attr/buttonBarButtonStyle"
diff --git a/core/res/res/layout/screen.xml b/core/res/res/layout/screen.xml
index 72f7392..902a797 100644
--- a/core/res/res/layout/screen.xml
+++ b/core/res/res/layout/screen.xml
@@ -41,8 +41,8 @@
         <ImageView android:id="@android:id/left_icon"
             android:layout_width="16dip"
             android:layout_height="16dip"
-            android:layout_marginRight="5dip"
-            android:layout_alignParentLeft="true"
+            android:layout_marginEnd="5dip"
+            android:layout_alignParentStart="true"
             android:layout_centerVertical="true"
             android:visibility="gone"
             android:scaleType="fitCenter"
@@ -50,13 +50,13 @@
         <LinearLayout android:id="@+android:id/right_container"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
             android:layout_centerVertical="true"
         >
             <ImageView android:id="@android:id/right_icon"
                 android:layout_width="16dip"
                 android:layout_height="16dip"
-                android:layout_marginLeft="5dip"
+                android:layout_marginStart="5dip"
                 android:layout_gravity="center_vertical"
                 android:visibility="gone"
                 android:scaleType="fitCenter"
@@ -65,7 +65,7 @@
                 style="?android:attr/progressBarStyleSmallTitle"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="5dip"
+                android:layout_marginStart="5dip"
                 android:layout_gravity="center_vertical"
                 android:visibility="gone"
                 android:max="10000"
@@ -75,9 +75,9 @@
             style="?android:attr/progressBarStyleHorizontal"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="2dip"
-            android:layout_toLeftOf="@android:id/right_container"
-            android:layout_toRightOf="@android:id/left_icon"
+            android:layout_marginStart="2dip"
+            android:layout_toStartOf="@android:id/right_container"
+            android:layout_toEndOf="@android:id/left_icon"
             android:layout_centerVertical="true"
             android:visibility="gone"
             android:max="10000"
@@ -90,8 +90,8 @@
             android:fadingEdge="horizontal"
             android:scrollHorizontally="true"
             android:gravity="center_vertical"
-            android:layout_toLeftOf="@android:id/right_container"
-            android:layout_toRightOf="@id/left_icon"
+            android:layout_toStartOf="@android:id/right_container"
+            android:layout_toEndOf="@id/left_icon"
         />
     </RelativeLayout>
 
diff --git a/core/res/res/layout/screen_progress.xml b/core/res/res/layout/screen_progress.xml
index c3f41fa..1f04d35 100644
--- a/core/res/res/layout/screen_progress.xml
+++ b/core/res/res/layout/screen_progress.xml
@@ -42,8 +42,8 @@
             style="?android:attr/progressBarStyleSmallTitle"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="5dip"
-            android:layout_alignParentRight="true"
+            android:layout_marginStart="5dip"
+            android:layout_alignParentEnd="true"
             android:layout_centerVertical="true"
             android:visibility="gone"
             android:max="10000"
@@ -52,9 +52,9 @@
             style="?android:attr/progressBarStyleHorizontal"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="2dip"
-            android:layout_alignParentLeft="true"
-            android:layout_toLeftOf="@android:id/progress_circular"
+            android:layout_marginStart="2dip"
+            android:layout_alignParentStart="true"
+            android:layout_toStartOf="@android:id/progress_circular"
             android:layout_centerVertical="true"
             android:visibility="gone"
             android:max="10000" 
@@ -63,8 +63,8 @@
             style="?android:attr/windowTitleStyle"
             android:layout_width="match_parent" 
             android:layout_height="match_parent"
-            android:layout_alignParentLeft="true"
-            android:layout_toLeftOf="@android:id/progress_circular"
+            android:layout_alignParentStart="true"
+            android:layout_toStartOf="@android:id/progress_circular"
             android:background="@null"
             android:fadingEdge="horizontal"
             android:gravity="center_vertical"
diff --git a/core/res/res/layout/screen_title_icons.xml b/core/res/res/layout/screen_title_icons.xml
index 51d6a15..b866e57 100644
--- a/core/res/res/layout/screen_title_icons.xml
+++ b/core/res/res/layout/screen_title_icons.xml
@@ -36,19 +36,19 @@
         <!-- The title background has 9px left padding. -->
         <ImageView android:id="@android:id/left_icon"
             android:visibility="gone"
-            android:layout_marginRight="9dip"
+            android:layout_marginEnd="9dip"
             android:layout_width="16dip"
             android:layout_height="16dip"
             android:scaleType="fitCenter"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:layout_centerVertical="true" />
         <ProgressBar android:id="@+id/progress_circular"
             style="?android:attr/progressBarStyleSmallTitle"
             android:visibility="gone"
             android:max="10000"
             android:layout_centerVertical="true"
-            android:layout_alignParentRight="true"
-            android:layout_marginLeft="6dip"
+            android:layout_alignParentEnd="true"
+            android:layout_marginStart="6dip"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content" />
         <!-- There are 6dip between this and the circular progress on the right, we
@@ -59,9 +59,9 @@
             style="?android:attr/progressBarStyleHorizontal"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="-3dip"
-            android:layout_toLeftOf="@android:id/progress_circular"
-            android:layout_toRightOf="@android:id/left_icon"
+            android:layout_marginStart="-3dip"
+            android:layout_toStartOf="@android:id/progress_circular"
+            android:layout_toEndOf="@android:id/left_icon"
             android:layout_centerVertical="true"
             android:visibility="gone"
             android:max="10000" />
@@ -69,8 +69,8 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:orientation="horizontal"
-            android:layout_toLeftOf="@id/progress_circular"
-            android:layout_toRightOf="@android:id/left_icon"
+            android:layout_toStartOf="@id/progress_circular"
+            android:layout_toEndOf="@android:id/left_icon"
             >
             <TextView android:id="@android:id/title"
                 style="?android:attr/windowTitleStyle"
@@ -81,7 +81,7 @@
                 android:fadingEdge="horizontal"
                 android:scrollHorizontally="true"
                 android:gravity="center_vertical"
-                android:layout_marginRight="2dip"
+                android:layout_marginEnd="2dip"
                 />
             <!-- 2dip between the icon and the title text, if icon is present. -->
             <ImageView android:id="@android:id/right_icon"
diff --git a/core/res/res/layout/search_dropdown_item_icons_2line.xml b/core/res/res/layout/search_dropdown_item_icons_2line.xml
index acef2cc..730d606 100644
--- a/core/res/res/layout/search_dropdown_item_icons_2line.xml
+++ b/core/res/res/layout/search_dropdown_item_icons_2line.xml
@@ -19,8 +19,8 @@
 -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:paddingLeft="@dimen/dropdownitem_text_padding_left"
-    android:paddingRight="4dip"
+    android:paddingStart="@dimen/dropdownitem_text_padding_left"
+    android:paddingEnd="4dip"
     android:layout_width="match_parent"
     android:layout_height="?android:attr/searchResultListItemHeight" >
 
@@ -30,7 +30,7 @@
         android:layout_width="@dimen/dropdownitem_icon_width"
         android:layout_height="48dip"
         android:scaleType="centerInside"
-        android:layout_alignParentLeft="true"
+        android:layout_alignParentStart="true"
         android:layout_alignParentTop="true"
         android:layout_alignParentBottom="true"
         android:visibility="invisible" />
@@ -39,7 +39,7 @@
         android:layout_width="48dip"
         android:layout_height="48dip"
         android:scaleType="centerInside"
-        android:layout_alignParentRight="true"
+        android:layout_alignParentEnd="true"
         android:layout_alignParentTop="true"
         android:layout_alignParentBottom="true"
         android:src="?attr/searchViewEditQuery"
@@ -51,7 +51,7 @@
         android:layout_height="48dip"
         android:scaleType="centerInside"
         android:layout_alignWithParentIfMissing="true"
-        android:layout_toLeftOf="@id/edit_query"
+        android:layout_toStartOf="@id/edit_query"
         android:layout_alignParentTop="true"
         android:layout_alignParentBottom="true"
         android:visibility="gone" />
@@ -67,8 +67,8 @@
         android:layout_height="29dip"
         android:paddingBottom="4dip"
         android:gravity="top"
-        android:layout_toRightOf="@android:id/icon1"
-        android:layout_toLeftOf="@android:id/icon2"
+        android:layout_toEndOf="@android:id/icon1"
+        android:layout_toStartOf="@android:id/icon2"
         android:layout_alignWithParentIfMissing="true"
         android:layout_alignParentBottom="true"
         android:visibility="gone" />
@@ -82,8 +82,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_centerVertical="true"
-        android:layout_toRightOf="@android:id/icon1"
-        android:layout_toLeftOf="@android:id/icon2"
+        android:layout_toEndOf="@android:id/icon1"
+        android:layout_toStartOf="@android:id/icon2"
         android:layout_above="@android:id/text2" />
 
 </RelativeLayout>
diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml
index ca1dc88..a281fcc 100644
--- a/core/res/res/layout/search_view.xml
+++ b/core/res/res/layout/search_view.xml
@@ -56,8 +56,8 @@
         android:layout_gravity="center_vertical"
         android:layout_marginTop="4dip"
         android:layout_marginBottom="4dip"
-        android:layout_marginLeft="8dip"
-        android:layout_marginRight="8dip"
+        android:layout_marginStart="8dip"
+        android:layout_marginEnd="8dip"
         android:orientation="horizontal">
 
         <ImageView
@@ -65,7 +65,7 @@
             android:layout_width="@dimen/dropdownitem_icon_width"
             android:layout_height="wrap_content"
             android:scaleType="centerInside"
-            android:layout_marginLeft="@dimen/dropdownitem_text_padding_left"
+            android:layout_marginStart="@dimen/dropdownitem_text_padding_left"
             android:layout_gravity="center_vertical"
             android:src="?android:attr/searchViewSearchIcon"
             android:visibility="gone"
@@ -88,8 +88,8 @@
                 android:layout_weight="1"
                 android:minWidth="@dimen/search_view_text_min_width"
                 android:layout_gravity="bottom"
-                android:paddingLeft="@dimen/dropdownitem_text_padding_left"
-                android:paddingRight="@dimen/dropdownitem_text_padding_right"
+                android:paddingStart="@dimen/dropdownitem_text_padding_left"
+                android:paddingEnd="@dimen/dropdownitem_text_padding_right"
                 android:singleLine="true"
                 android:ellipsize="end"
                 android:background="@null"
@@ -106,8 +106,8 @@
                 android:id="@+id/search_close_btn"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
-                android:paddingLeft="8dip"
-                android:paddingRight="8dip"
+                android:paddingStart="8dip"
+                android:paddingEnd="8dip"
                 android:layout_gravity="center_vertical"
                 android:background="?android:attr/selectableItemBackground"
                 android:src="?android:attr/searchViewCloseIcon"
@@ -129,8 +129,8 @@
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
                 android:layout_gravity="center_vertical"
-                android:paddingLeft="16dip"
-                android:paddingRight="16dip"
+                android:paddingStart="16dip"
+                android:paddingEnd="16dip"
                 android:background="?android:attr/selectableItemBackground"
                 android:src="?android:attr/searchViewGoIcon"
                 android:visibility="gone"
@@ -143,8 +143,8 @@
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
                 android:layout_gravity="center_vertical"
-                android:paddingLeft="16dip"
-                android:paddingRight="16dip"
+                android:paddingStart="16dip"
+                android:paddingEnd="16dip"
                 android:src="?android:attr/searchViewVoiceIcon"
                 android:background="?android:attr/selectableItemBackground"
                 android:visibility="gone"
diff --git a/core/res/res/layout/select_dialog_item.xml b/core/res/res/layout/select_dialog_item.xml
index 96fdcc6..835c433 100644
--- a/core/res/res/layout/select_dialog_item.xml
+++ b/core/res/res/layout/select_dialog_item.xml
@@ -31,7 +31,7 @@
     android:textAppearance="?android:attr/textAppearanceLarge"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="14dip"
-    android:paddingRight="15dip"
+    android:paddingStart="14dip"
+    android:paddingEnd="15dip"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout/select_dialog_item_holo.xml b/core/res/res/layout/select_dialog_item_holo.xml
index 3d19c06..62be406 100644
--- a/core/res/res/layout/select_dialog_item_holo.xml
+++ b/core/res/res/layout/select_dialog_item_holo.xml
@@ -30,7 +30,7 @@
     android:textAppearance="?android:attr/textAppearanceListItemSmall"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout/select_dialog_multichoice.xml b/core/res/res/layout/select_dialog_multichoice.xml
index a9be014..2dd83a3 100644
--- a/core/res/res/layout/select_dialog_multichoice.xml
+++ b/core/res/res/layout/select_dialog_multichoice.xml
@@ -22,8 +22,8 @@
     android:textAppearance="?android:attr/textAppearanceLarge"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="12dip"
-    android:paddingRight="7dip"
+    android:paddingStart="12dip"
+    android:paddingEnd="7dip"
     android:checkMark="?android:attr/listChoiceIndicatorMultiple"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout/select_dialog_multichoice_holo.xml b/core/res/res/layout/select_dialog_multichoice_holo.xml
index 683151c..40125b7 100644
--- a/core/res/res/layout/select_dialog_multichoice_holo.xml
+++ b/core/res/res/layout/select_dialog_multichoice_holo.xml
@@ -22,8 +22,8 @@
     android:textAppearance="?android:attr/textAppearanceMedium"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:checkMark="?android:attr/listChoiceIndicatorMultiple"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout/select_dialog_singlechoice.xml b/core/res/res/layout/select_dialog_singlechoice.xml
index 1b9c973..1e18b44 100644
--- a/core/res/res/layout/select_dialog_singlechoice.xml
+++ b/core/res/res/layout/select_dialog_singlechoice.xml
@@ -22,8 +22,8 @@
     android:textAppearance="?android:attr/textAppearanceLarge"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="12dip"
-    android:paddingRight="7dip"
+    android:paddingStart="12dip"
+    android:paddingEnd="7dip"
     android:checkMark="?android:attr/listChoiceIndicatorSingle"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout/select_dialog_singlechoice_holo.xml b/core/res/res/layout/select_dialog_singlechoice_holo.xml
index 52782d0..545ec60 100644
--- a/core/res/res/layout/select_dialog_singlechoice_holo.xml
+++ b/core/res/res/layout/select_dialog_singlechoice_holo.xml
@@ -22,8 +22,8 @@
     android:textAppearance="?android:attr/textAppearanceMedium"
     android:textColor="?android:attr/textColorAlertDialogListItem"
     android:gravity="center_vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:checkMark="?android:attr/listChoiceIndicatorSingle"
     android:ellipsize="marquee"
 />
diff --git a/core/res/res/layout/simple_dropdown_hint.xml b/core/res/res/layout/simple_dropdown_hint.xml
index df9d720..2583339 100644
--- a/core/res/res/layout/simple_dropdown_hint.xml
+++ b/core/res/res/layout/simple_dropdown_hint.xml
@@ -21,9 +21,9 @@
     android:id="@android:id/text1"
     android:textAppearance="?android:attr/dropDownHintAppearance"
     android:singleLine="true"
-    android:layout_marginLeft="3dip"
+    android:layout_marginStart="3dip"
     android:layout_marginTop="3dip"
-    android:layout_marginRight="3dip"
+    android:layout_marginEnd="3dip"
     android:layout_marginBottom="3dip"
     android:layout_width="match_parent"
     android:layout_height="wrap_content" />
diff --git a/core/res/res/layout/simple_dropdown_item_2line.xml b/core/res/res/layout/simple_dropdown_item_2line.xml
index d6f911a..c7093b4 100644
--- a/core/res/res/layout/simple_dropdown_item_2line.xml
+++ b/core/res/res/layout/simple_dropdown_item_2line.xml
@@ -51,7 +51,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_below="@android:id/text1"
-            android:layout_alignLeft="@android:id/text1" />
+            android:layout_alignStart="@android:id/text1" />
     
     </TwoLineListItem>
 
diff --git a/core/res/res/layout/simple_expandable_list_item_1.xml b/core/res/res/layout/simple_expandable_list_item_1.xml
index df4324b..9810a60 100644
--- a/core/res/res/layout/simple_expandable_list_item_1.xml
+++ b/core/res/res/layout/simple_expandable_list_item_1.xml
@@ -18,7 +18,7 @@
     android:id="@android:id/text1"
     android:layout_width="match_parent"
     android:layout_height="?android:attr/listPreferredItemHeight"
-    android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft"
+    android:paddingStart="?android:attr/expandableListPreferredItemPaddingLeft"
     android:textAppearance="?android:attr/textAppearanceListItem"
     android:gravity="center_vertical"
 />
diff --git a/core/res/res/layout/simple_expandable_list_item_2.xml b/core/res/res/layout/simple_expandable_list_item_2.xml
index c0935fa..ed845f8 100644
--- a/core/res/res/layout/simple_expandable_list_item_2.xml
+++ b/core/res/res/layout/simple_expandable_list_item_2.xml
@@ -19,7 +19,7 @@
     android:layout_height="?android:attr/listPreferredItemHeight"
     android:paddingTop="2dip"
     android:paddingBottom="2dip"
-    android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft"
+    android:paddingStart="?android:attr/expandableListPreferredItemPaddingLeft"
     android:mode="twoLine"
 >
 
@@ -34,7 +34,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_below="@android:id/text1"
-        android:layout_alignLeft="@android:id/text1"
+        android:layout_alignStart="@android:id/text1"
         android:textAppearance="?android:attr/textAppearanceSmall"
     />
 
diff --git a/core/res/res/layout/simple_list_item_1.xml b/core/res/res/layout/simple_list_item_1.xml
index c5e3efc..4249d10 100644
--- a/core/res/res/layout/simple_list_item_1.xml
+++ b/core/res/res/layout/simple_list_item_1.xml
@@ -20,7 +20,7 @@
     android:layout_height="wrap_content"
     android:textAppearance="?android:attr/textAppearanceListItemSmall"
     android:gravity="center_vertical"
-    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
     android:minHeight="?android:attr/listPreferredItemHeightSmall"
 />
diff --git a/core/res/res/layout/simple_list_item_2.xml b/core/res/res/layout/simple_list_item_2.xml
index 9369876..8c6c9d3 100644
--- a/core/res/res/layout/simple_list_item_2.xml
+++ b/core/res/res/layout/simple_list_item_2.xml
@@ -24,7 +24,7 @@
 	<TextView android:id="@android:id/text1"
 		android:layout_width="match_parent"
 		android:layout_height="wrap_content"
-    android:layout_marginLeft="?android:attr/listPreferredItemPaddingLeft"
+    android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
     android:layout_marginTop="8dip"
 		android:textAppearance="?android:attr/textAppearanceListItem"
 	/>
@@ -33,7 +33,7 @@
 		android:layout_width="match_parent"
 		android:layout_height="wrap_content"
 		android:layout_below="@android:id/text1"
-    android:layout_alignLeft="@android:id/text1"
+    android:layout_alignStart="@android:id/text1"
 		android:textAppearance="?android:attr/textAppearanceSmall"
 	/>
 
diff --git a/core/res/res/layout/simple_list_item_2_single_choice.xml b/core/res/res/layout/simple_list_item_2_single_choice.xml
index 90dfe37..5629567 100644
--- a/core/res/res/layout/simple_list_item_2_single_choice.xml
+++ b/core/res/res/layout/simple_list_item_2_single_choice.xml
@@ -19,8 +19,8 @@
     android:layout_height="wrap_content"
     android:orientation="horizontal"
     android:gravity="center_vertical"
-    android:paddingLeft="16dip"
-    android:paddingRight="12dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="12dip"
     android:minHeight="?android:attr/listPreferredItemHeightSmall">
     <LinearLayout
         android:layout_width="wrap_content"
@@ -33,7 +33,7 @@
             android:layout_height="wrap_content"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="?android:attr/textColorAlertDialogListItem"
-            android:gravity="center_vertical|left"
+            android:gravity="center_vertical|start"
             android:singleLine="true"
             android:ellipsize="marquee"
         />
@@ -42,7 +42,7 @@
             android:layout_height="wrap_content"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="?android:attr/textColorAlertDialogListItem"
-            android:gravity="center_vertical|left"
+            android:gravity="center_vertical|start"
             android:singleLine="true"
             android:ellipsize="marquee"
         />
@@ -51,7 +51,7 @@
         android:id="@+id/radio"
         android:layout_width="35dip"
         android:layout_height="wrap_content"
-        android:paddingRight="12dip"
+        android:paddingEnd="12dip"
         android:gravity="center_vertical"
         android:focusable="false"
         android:clickable="false"
diff --git a/core/res/res/layout/simple_list_item_activated_1.xml b/core/res/res/layout/simple_list_item_activated_1.xml
index a5fb5d1..41155e4 100644
--- a/core/res/res/layout/simple_list_item_activated_1.xml
+++ b/core/res/res/layout/simple_list_item_activated_1.xml
@@ -20,8 +20,8 @@
     android:layout_height="wrap_content"
     android:textAppearance="?android:attr/textAppearanceListItemSmall"
     android:gravity="center_vertical"
-    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
     android:background="?android:attr/activatedBackgroundIndicator"
     android:minHeight="?android:attr/listPreferredItemHeightSmall"
 />
diff --git a/core/res/res/layout/simple_list_item_activated_2.xml b/core/res/res/layout/simple_list_item_activated_2.xml
index 8746f6f..725697d 100644
--- a/core/res/res/layout/simple_list_item_activated_2.xml
+++ b/core/res/res/layout/simple_list_item_activated_2.xml
@@ -27,7 +27,7 @@
     <TextView android:id="@android:id/text1"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="?android:attr/listPreferredItemPaddingLeft"
+        android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
         android:layout_marginTop="6dip"
         android:textAppearance="?android:attr/textAppearanceListItem"
     />
@@ -36,7 +36,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_below="@android:id/text1"
-        android:layout_alignLeft="@android:id/text1"
+        android:layout_alignStart="@android:id/text1"
         android:textAppearance="?android:attr/textAppearanceSmall"
     />
 
diff --git a/core/res/res/layout/simple_list_item_checked.xml b/core/res/res/layout/simple_list_item_checked.xml
index c9153f8..0c497d6 100644
--- a/core/res/res/layout/simple_list_item_checked.xml
+++ b/core/res/res/layout/simple_list_item_checked.xml
@@ -21,6 +21,6 @@
     android:textAppearance="?android:attr/textAppearanceListItemSmall"
     android:gravity="center_vertical"
     android:checkMark="?android:attr/textCheckMark"
-    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
 />
diff --git a/core/res/res/layout/simple_list_item_multiple_choice.xml b/core/res/res/layout/simple_list_item_multiple_choice.xml
index cb23dfd..076d8c6 100644
--- a/core/res/res/layout/simple_list_item_multiple_choice.xml
+++ b/core/res/res/layout/simple_list_item_multiple_choice.xml
@@ -21,6 +21,6 @@
     android:textAppearance="?android:attr/textAppearanceListItemSmall"
     android:gravity="center_vertical"
     android:checkMark="?android:attr/listChoiceIndicatorMultiple"
-    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
 />
diff --git a/core/res/res/layout/simple_list_item_single_choice.xml b/core/res/res/layout/simple_list_item_single_choice.xml
index 4a6cefa..4c1af09 100644
--- a/core/res/res/layout/simple_list_item_single_choice.xml
+++ b/core/res/res/layout/simple_list_item_single_choice.xml
@@ -21,6 +21,6 @@
     android:textAppearance="?android:attr/textAppearanceListItemSmall"
     android:gravity="center_vertical"
     android:checkMark="?android:attr/listChoiceIndicatorSingle"
-    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
 />
diff --git a/core/res/res/layout/simple_selectable_list_item.xml b/core/res/res/layout/simple_selectable_list_item.xml
index 6ce22d6..40f0ed6 100644
--- a/core/res/res/layout/simple_selectable_list_item.xml
+++ b/core/res/res/layout/simple_selectable_list_item.xml
@@ -21,6 +21,6 @@
     android:textAppearance="?android:attr/textAppearanceListItem"
     android:gravity="center_vertical"
     android:background="?android:attr/listChoiceBackgroundIndicator"
-    android:paddingLeft="8dip"
-    android:paddingRight="8dip"
+    android:paddingStart="8dip"
+    android:paddingEnd="8dip"
 />
diff --git a/core/res/res/layout/sms_short_code_confirmation_dialog.xml b/core/res/res/layout/sms_short_code_confirmation_dialog.xml
new file mode 100644
index 0000000..ec39d97
--- /dev/null
+++ b/core/res/res/layout/sms_short_code_confirmation_dialog.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012 The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/parentPanel"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginLeft="8dip"
+    android:layout_marginRight="8dip"
+    android:orientation="vertical">
+
+    <TextView android:id="@+id/sms_short_code_confirm_message"
+        style="?android:attr/textAppearanceMedium"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingLeft="16dip"
+        android:paddingRight="16dip"
+        android:paddingTop="8dip"
+        android:paddingBottom="16dip" />
+
+    <TableLayout android:id="@+id/sms_short_code_detail_layout"
+        android:shrinkColumns="1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingLeft="16dip"
+        android:paddingRight="16dip">
+
+        <TableRow
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" >
+
+            <ImageView android:id="@+id/sms_short_code_coins_icon"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingLeft="8dip"
+                android:paddingRight="8dip"
+                android:src="@null" />
+            <TextView android:id="@+id/sms_short_code_detail_message"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" />
+        </TableRow>
+
+        <TableRow
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" >
+
+            <CheckBox android:id="@+id/sms_short_code_remember_choice_checkbox"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingRight="8dip" />
+            <TextView android:id="@+id/sms_short_code_remember_choice_text"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/sms_short_code_remember_choice" />
+        </TableRow>
+
+        <TableRow
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" >
+
+            <Space android:layout_gravity="fill" />
+            <TextView android:id="@+id/sms_short_code_remember_undo_instruction"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+        </TableRow>
+
+    </TableLayout>
+
+</LinearLayout>
diff --git a/core/res/res/layout/ssl_certificate.xml b/core/res/res/layout/ssl_certificate.xml
index dd89a2d..a69d2a3 100644
--- a/core/res/res/layout/ssl_certificate.xml
+++ b/core/res/res/layout/ssl_certificate.xml
@@ -23,7 +23,7 @@
         android:id="@+id/body"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:gravity="left"
+        android:gravity="start"
         android:orientation="vertical" >
 
         <!-- Placeholder for the success message or one or more warnings -->
@@ -43,8 +43,8 @@
             android:scaleType="fitXY"
             android:layout_weight="1"
             android:gravity="fill_horizontal"
-            android:layout_marginRight="20dip"
-            android:layout_marginLeft="20dip"/>
+            android:layout_marginEnd="20dip"
+            android:layout_marginStart="20dip"/>
 
         <!-- Issued to: -->
         <TextView
@@ -54,8 +54,8 @@
             android:text="@string/issued_to"
             android:textStyle="bold"
             android:layout_marginTop="12dip"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Common name: -->
@@ -64,15 +64,15 @@
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:text="@string/common_name"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/to_common"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Organization: -->
@@ -81,15 +81,15 @@
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:text="@string/org_name"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/to_org"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Organizational unit: -->
@@ -98,15 +98,15 @@
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:text="@string/org_unit"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/to_org_unit"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Serial number: -->
@@ -115,15 +115,15 @@
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:text="@string/serial_number"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/serial_number"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Issued by: -->
@@ -134,8 +134,8 @@
             android:text="@string/issued_by"
             android:textStyle="bold"
             android:layout_marginTop="12dip"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Common name: -->
@@ -144,15 +144,15 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/common_name"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/by_common"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Organization: -->
@@ -161,15 +161,15 @@
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:text="@string/org_name"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/by_org"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Organizational unit: -->
@@ -178,15 +178,15 @@
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:text="@string/org_unit"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/by_org_unit"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Validity Dates: -->
@@ -197,8 +197,8 @@
             android:text="@string/validity_period"
             android:textStyle="bold"
             android:layout_marginTop="12dip"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Issued On: -->
@@ -207,15 +207,15 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/issued_on"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/issued_on"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Expires On: -->
@@ -224,15 +224,15 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/expires_on"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/expires_on"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- Fingerprints: -->
@@ -243,8 +243,8 @@
             android:text="@string/fingerprints"
             android:textStyle="bold"
             android:layout_marginTop="12dip"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- SHA-256 fingerprint: -->
@@ -253,15 +253,15 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/sha256_fingerprint"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/sha256_fingerprint"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
         <!-- SHA-1 fingerprint: -->
@@ -270,15 +270,15 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/sha1_fingerprint"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip" />
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip" />
 
         <TextView
             android:id="@+id/sha1_fingerprint"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginLeft="20dip"
-            android:layout_marginRight="20dip"
+            android:layout_marginStart="20dip"
+            android:layout_marginEnd="20dip"
             android:layout_marginBottom="7dip" />
 
     </LinearLayout>
diff --git a/core/res/res/layout/tab_indicator.xml b/core/res/res/layout/tab_indicator.xml
index bc657c3..55ab1d8 100644
--- a/core/res/res/layout/tab_indicator.xml
+++ b/core/res/res/layout/tab_indicator.xml
@@ -18,8 +18,8 @@
     android:layout_width="0dip"
     android:layout_height="64dip"
     android:layout_weight="1"
-    android:layout_marginLeft="-3dip"
-    android:layout_marginRight="-3dip"
+    android:layout_marginStart="-3dip"
+    android:layout_marginEnd="-3dip"
     android:background="@android:drawable/tab_indicator">
 
     <ImageView android:id="@+id/icon"
diff --git a/core/res/res/layout/text_edit_action_popup_text.xml b/core/res/res/layout/text_edit_action_popup_text.xml
index 42e6f2e..16bf30e 100644
--- a/core/res/res/layout/text_edit_action_popup_text.xml
+++ b/core/res/res/layout/text_edit_action_popup_text.xml
@@ -17,8 +17,8 @@
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:paddingTop="8dip"
     android:paddingBottom="8dip"
     android:gravity="center"
diff --git a/core/res/res/layout/text_edit_no_paste_window.xml b/core/res/res/layout/text_edit_no_paste_window.xml
index c4c0b8a..10a752c 100644
--- a/core/res/res/layout/text_edit_no_paste_window.xml
+++ b/core/res/res/layout/text_edit_no_paste_window.xml
@@ -21,8 +21,8 @@
     <TextView android:id="@+id/title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:paddingLeft="16dip"
-        android:paddingRight="16dip"
+        android:paddingStart="16dip"
+        android:paddingEnd="16dip"
         android:paddingTop="8dip"
         android:paddingBottom="8dip"
         android:drawablePadding="8dip"
diff --git a/core/res/res/layout/text_edit_paste_window.xml b/core/res/res/layout/text_edit_paste_window.xml
index adfe56b..3b8dbf2 100644
--- a/core/res/res/layout/text_edit_paste_window.xml
+++ b/core/res/res/layout/text_edit_paste_window.xml
@@ -21,8 +21,8 @@
     <TextView android:id="@+id/title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:paddingLeft="16dip"
-        android:paddingRight="16dip"
+        android:paddingStart="16dip"
+        android:paddingEnd="16dip"
         android:paddingTop="8dip"
         android:paddingBottom="12dip"
         android:drawablePadding="8dip"
diff --git a/core/res/res/layout/text_edit_side_no_paste_window.xml b/core/res/res/layout/text_edit_side_no_paste_window.xml
index 78423a7..aa695cd 100644
--- a/core/res/res/layout/text_edit_side_no_paste_window.xml
+++ b/core/res/res/layout/text_edit_side_no_paste_window.xml
@@ -21,8 +21,8 @@
     <TextView android:id="@+id/title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:paddingLeft="16dip"
-        android:paddingRight="16dip"
+        android:paddingStart="16dip"
+        android:paddingEnd="16dip"
         android:paddingTop="8dip"
         android:paddingBottom="8dip"
         android:drawablePadding="8dip"
diff --git a/core/res/res/layout/text_edit_side_paste_window.xml b/core/res/res/layout/text_edit_side_paste_window.xml
index 37b774d..c947a19 100644
--- a/core/res/res/layout/text_edit_side_paste_window.xml
+++ b/core/res/res/layout/text_edit_side_paste_window.xml
@@ -21,8 +21,8 @@
     <TextView android:id="@+id/title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:paddingLeft="16dip"
-        android:paddingRight="16dip"
+        android:paddingStart="16dip"
+        android:paddingEnd="16dip"
         android:paddingTop="8dip"
         android:paddingBottom="8dip"
         android:drawablePadding="8dip"
diff --git a/core/res/res/layout/text_edit_suggestion_item.xml b/core/res/res/layout/text_edit_suggestion_item.xml
index 1fdc1bf..a965ddd 100644
--- a/core/res/res/layout/text_edit_suggestion_item.xml
+++ b/core/res/res/layout/text_edit_suggestion_item.xml
@@ -17,11 +17,11 @@
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
-          android:paddingLeft="16dip"
-          android:paddingRight="16dip"
+          android:paddingStart="16dip"
+          android:paddingEnd="16dip"
           android:paddingTop="8dip"
           android:paddingBottom="8dip"
-          android:layout_gravity="left|center_vertical"
+          android:layout_gravity="start|center_vertical"
           android:singleLine="true"
           android:drawablePadding="8dip"
           android:ellipsize="marquee"
diff --git a/core/res/res/layout/time_picker.xml b/core/res/res/layout/time_picker.xml
index df46db4..a78cd85 100644
--- a/core/res/res/layout/time_picker.xml
+++ b/core/res/res/layout/time_picker.xml
@@ -25,24 +25,31 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content">
 
-    <!-- hour -->
-    <NumberPicker
-        android:id="@+id/hour"
-        android:layout_width="70dip"
+    <LinearLayout android:orientation="horizontal"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:focusable="true"
-        android:focusableInTouchMode="true"
-        />
+        android:layoutDirection="ltr">
 
-    <!-- minute -->
-    <NumberPicker
-        android:id="@+id/minute"
-        android:layout_width="70dip"
-        android:layout_height="wrap_content"
-        android:layout_marginLeft="5dip"
-        android:focusable="true"
-        android:focusableInTouchMode="true"
-        />
+        <!-- hour -->
+        <NumberPicker
+            android:id="@+id/hour"
+            android:layout_width="70dip"
+            android:layout_height="wrap_content"
+            android:focusable="true"
+            android:focusableInTouchMode="true"
+            />
+
+        <!-- minute -->
+        <NumberPicker
+            android:id="@+id/minute"
+            android:layout_width="70dip"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="5dip"
+            android:focusable="true"
+            android:focusableInTouchMode="true"
+            />
+
+    </LinearLayout>
 
     <!-- AM / PM -->
     <Button
@@ -50,9 +57,9 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="43dip"
-        android:layout_marginLeft="5dip"
-        android:paddingLeft="20dip"
-        android:paddingRight="20dip"
+        android:layout_marginStart="5dip"
+        android:paddingStart="20dip"
+        android:paddingEnd="20dip"
         style="?android:attr/textAppearanceLargeInverse"
         android:textColor="@android:color/primary_text_light_nodisable"
         />
diff --git a/core/res/res/layout/time_picker_holo.xml b/core/res/res/layout/time_picker_holo.xml
index 7b91022..7d8900e 100644
--- a/core/res/res/layout/time_picker_holo.xml
+++ b/core/res/res/layout/time_picker_holo.xml
@@ -25,40 +25,47 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content">
 
-    <!-- hour -->
-    <NumberPicker
-        android:id="@+id/hour"
+    <LinearLayout android:orientation="horizontal"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginTop="16dip"
-        android:layout_marginBottom="16dip"
-        android:layout_marginLeft="16dip"
-        android:layout_marginRight="6dip"
-        android:focusable="true"
-        android:focusableInTouchMode="true"
-        />
+        android:layoutDirection="ltr">
 
-    <!-- divider -->
-    <TextView
-        android:id="@+id/divider"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical"
-        android:importantForAccessibility="no"
-        />
+        <!-- hour -->
+        <NumberPicker
+            android:id="@+id/hour"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dip"
+            android:layout_marginBottom="16dip"
+            android:layout_marginStart="16dip"
+            android:layout_marginEnd="6dip"
+            android:focusable="true"
+            android:focusableInTouchMode="true"
+            />
 
-    <!-- minute -->
-    <NumberPicker
-        android:id="@+id/minute"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="16dip"
-        android:layout_marginBottom="16dip"
-        android:layout_marginLeft="6dip"
-        android:layout_marginRight="8dip"
-        android:focusable="true"
-        android:focusableInTouchMode="true"
-        />
+        <!-- divider -->
+        <TextView
+            android:id="@+id/divider"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:importantForAccessibility="no"
+            />
+
+        <!-- minute -->
+        <NumberPicker
+            android:id="@+id/minute"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dip"
+            android:layout_marginBottom="16dip"
+            android:layout_marginStart="6dip"
+            android:layout_marginEnd="8dip"
+            android:focusable="true"
+            android:focusableInTouchMode="true"
+            />
+
+    </LinearLayout>
 
     <!-- AM / PM -->
     <NumberPicker
@@ -67,8 +74,8 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="16dip"
         android:layout_marginBottom="16dip"
-        android:layout_marginLeft="8dip"
-        android:layout_marginRight="16dip"
+        android:layout_marginStart="8dip"
+        android:layout_marginEnd="16dip"
         android:focusable="true"
         android:focusableInTouchMode="true"
         />
diff --git a/core/res/res/layout/twelve_key_entry.xml b/core/res/res/layout/twelve_key_entry.xml
index 09c749d..7b41b50 100644
--- a/core/res/res/layout/twelve_key_entry.xml
+++ b/core/res/res/layout/twelve_key_entry.xml
@@ -24,16 +24,16 @@
     <LinearLayout
         android:layout_width="fill_parent"
         android:layout_height="64dip"
-        android:layout_marginLeft="2dip"
-        android:layout_marginRight="2dip"
+        android:layout_marginStart="2dip"
+        android:layout_marginEnd="2dip"
         android:orientation="horizontal">
 
         <Button android:id="@+id/one"
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -42,8 +42,8 @@
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -52,8 +52,8 @@
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -63,16 +63,16 @@
     <LinearLayout
         android:layout_width="fill_parent"
         android:layout_height="64dip"
-        android:layout_marginLeft="2dip"
-        android:layout_marginRight="2dip"
+        android:layout_marginStart="2dip"
+        android:layout_marginEnd="2dip"
         android:orientation="horizontal">
 
         <Button android:id="@+id/four"
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -81,8 +81,8 @@
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -91,8 +91,8 @@
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -101,16 +101,16 @@
     <LinearLayout
         android:layout_width="fill_parent"
         android:layout_height="64dip"
-        android:layout_marginLeft="2dip"
-        android:layout_marginRight="2dip"
+        android:layout_marginStart="2dip"
+        android:layout_marginEnd="2dip"
         android:orientation="horizontal">
 
         <Button android:id="@+id/seven"
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -119,8 +119,8 @@
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -129,8 +129,8 @@
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -140,16 +140,16 @@
     <LinearLayout
         android:layout_width="fill_parent"
         android:layout_height="64dip"
-        android:layout_marginLeft="2dip"
-        android:layout_marginRight="2dip"
+        android:layout_marginStart="2dip"
+        android:layout_marginEnd="2dip"
         android:orientation="horizontal">
 
         <Button android:id="@+id/cancel"
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textStyle="bold"
             android:text="@android:string/cancel"
@@ -159,8 +159,8 @@
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:textStyle="bold"
         />
@@ -169,8 +169,8 @@
             android:layout_width="0sp"
             android:layout_height="fill_parent"
             android:layout_weight="1"
-            android:layout_marginLeft="2dip"
-            android:layout_marginRight="2dip"
+            android:layout_marginStart="2dip"
+            android:layout_marginEnd="2dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textStyle="bold"
             android:text="@android:string/ok"
diff --git a/core/res/res/layout/usb_storage_activity.xml b/core/res/res/layout/usb_storage_activity.xml
index 76c30fd..6dae0f9 100644
--- a/core/res/res/layout/usb_storage_activity.xml
+++ b/core/res/res/layout/usb_storage_activity.xml
@@ -44,16 +44,16 @@
         <Button android:id="@+id/mount_button" 
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:paddingLeft="18dip"
-            android:paddingRight="18dip"
+            android:paddingStart="18dip"
+            android:paddingEnd="18dip"
             android:text="@string/usb_storage_button_mount"
             />
         <Button android:id="@+id/unmount_button"
             android:visibility="gone"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:paddingLeft="18dip"
-            android:paddingRight="18dip"
+            android:paddingStart="18dip"
+            android:paddingEnd="18dip"
             android:text="@string/usb_storage_stop_button_mount"
             />
         <ProgressBar android:id="@+id/progress"
diff --git a/core/res/res/layout/volume_adjust_item.xml b/core/res/res/layout/volume_adjust_item.xml
index d3fa7e9..4a0fbaf 100644
--- a/core/res/res/layout/volume_adjust_item.xml
+++ b/core/res/res/layout/volume_adjust_item.xml
@@ -20,7 +20,7 @@
     android:orientation="horizontal"
     android:layout_marginTop="8dip"
     android:layout_marginBottom="8dip"
-    android:gravity="left|center_vertical">
+    android:gravity="start|center_vertical">
 
     <ImageView
         android:id="@+id/stream_icon"
@@ -37,6 +37,6 @@
         android:layout_height="wrap_content"
         android:layout_weight="1"
         android:padding="16dip"
-        android:layout_marginRight="16dip" />
+        android:layout_marginEnd="16dip" />
 
 </LinearLayout>
diff --git a/core/res/res/layout/webview_find.xml b/core/res/res/layout/webview_find.xml
index a628ac8..da16043 100644
--- a/core/res/res/layout/webview_find.xml
+++ b/core/res/res/layout/webview_find.xml
@@ -27,7 +27,7 @@
         android:inputType="text"
         android:hint="@string/find_on_page"
         android:imeOptions="actionDone|flagNoExtractUi|flagNoFullscreen"
-        android:layout_marginRight="10dip"
+        android:layout_marginEnd="10dip"
         />
     <TextView android:id="@+id/matches"
         android:layout_width="wrap_content"
diff --git a/core/res/res/layout/wifi_p2p_dialog.xml b/core/res/res/layout/wifi_p2p_dialog.xml
index 8234187..86dcbfa 100644
--- a/core/res/res/layout/wifi_p2p_dialog.xml
+++ b/core/res/res/layout/wifi_p2p_dialog.xml
@@ -37,8 +37,10 @@
                     style="@style/wifi_item_label" />
 
                 <EditText android:id="@+id/wifi_p2p_wps_pin"
-                    android:inputType="textNoSuggestions"
-                    style="@style/wifi_item_content" />
+                        android:singleLine="true"
+                        android:maxLines="8"
+                        android:inputType="number"
+                        style="@style/wifi_item_content" />
             </LinearLayout>
         </LinearLayout>
     </LinearLayout>
diff --git a/core/res/res/layout/zoom_browser_accessory_buttons.xml b/core/res/res/layout/zoom_browser_accessory_buttons.xml
index 4bf2bdf..a264288 100644
--- a/core/res/res/layout/zoom_browser_accessory_buttons.xml
+++ b/core/res/res/layout/zoom_browser_accessory_buttons.xml
@@ -22,14 +22,14 @@
         android:background="@android:drawable/btn_browser_zoom_fit_page"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_gravity="bottom|left"
-        android:layout_marginLeft="7dip"
+        android:layout_gravity="bottom|start"
+        android:layout_marginStart="7dip"
         />
     <ImageView android:id="@+id/zoom_page_overview" 
         android:background="@android:drawable/btn_browser_zoom_page_overview"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_gravity="bottom|right"
-        android:layout_marginRight="7dip"
+        android:layout_gravity="bottom|end"
+        android:layout_marginEnd="7dip"
         />
 </merge>
diff --git a/core/res/res/layout/zoom_magnify.xml b/core/res/res/layout/zoom_magnify.xml
index 374819e..562257c 100644
--- a/core/res/res/layout/zoom_magnify.xml
+++ b/core/res/res/layout/zoom_magnify.xml
@@ -26,8 +26,8 @@
         />
     <ImageView android:id="@+id/zoomMagnify"
         android:focusable="true"
-        android:layout_gravity="bottom|right"
-        android:paddingRight="2dip"
+        android:layout_gravity="bottom|end"
+        android:paddingEnd="2dip"
         android:src="@drawable/btn_zoom_page"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
diff --git a/core/res/res/menu/webview_find.xml b/core/res/res/menu/webview_find.xml
index 1770bd9..54f25d2 100644
--- a/core/res/res/menu/webview_find.xml
+++ b/core/res/res/menu/webview_find.xml
@@ -18,9 +18,11 @@
     <item android:id="@+id/find_prev"
         android:icon="?android:attr/findOnPagePreviousDrawable"
         android:showAsAction="always"
+        android:title="@string/find_previous"
         />
     <item android:id="@+id/find_next"
         android:icon="?android:attr/findOnPageNextDrawable"
         android:showAsAction="always"
+        android:title="@string/find_next"
         />
 </menu>
diff --git a/core/res/res/values-af/donottranslate-cldr.xml b/core/res/res/values-af/donottranslate-cldr.xml
index 9d38717..77b7f7c 100644
--- a/core/res/res/values-af/donottranslate-cldr.xml
+++ b/core/res/res/values-af/donottranslate-cldr.xml
@@ -1,93 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Januarie</string>
-    <string name="month_long_standalone_february">Februarie</string>
-    <string name="month_long_standalone_march">Maart</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">Mei</string>
-    <string name="month_long_standalone_june">Junie</string>
-    <string name="month_long_standalone_july">Julie</string>
-    <string name="month_long_standalone_august">Augustus</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">Oktober</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">Desember</string>
-
-    <string name="month_long_january">Januarie</string>
-    <string name="month_long_february">Februarie</string>
-    <string name="month_long_march">Maart</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">Mei</string>
-    <string name="month_long_june">Junie</string>
-    <string name="month_long_july">Julie</string>
-    <string name="month_long_august">Augustus</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">Oktober</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">Desember</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mar</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">Mei</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aug</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Okt</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Des</string>
-
-    <string name="month_shortest_january">1</string>
-    <string name="month_shortest_february">2</string>
-    <string name="month_shortest_march">3</string>
-    <string name="month_shortest_april">4</string>
-    <string name="month_shortest_may">5</string>
-    <string name="month_shortest_june">6</string>
-    <string name="month_shortest_july">7</string>
-    <string name="month_shortest_august">8</string>
-    <string name="month_shortest_september">9</string>
-    <string name="month_shortest_october">10</string>
-    <string name="month_shortest_november">11</string>
-    <string name="month_shortest_december">12</string>
-
-    <string name="day_of_week_long_sunday">Sondag</string>
-    <string name="day_of_week_long_monday">Maandag</string>
-    <string name="day_of_week_long_tuesday">Dinsdag</string>
-    <string name="day_of_week_long_wednesday">Woensdag</string>
-    <string name="day_of_week_long_thursday">Donderdag</string>
-    <string name="day_of_week_long_friday">Vrydag</string>
-    <string name="day_of_week_long_saturday">Saterdag</string>
-
-    <string name="day_of_week_medium_sunday">So</string>
-    <string name="day_of_week_medium_monday">Ma</string>
-    <string name="day_of_week_medium_tuesday">Di</string>
-    <string name="day_of_week_medium_wednesday">Wo</string>
-    <string name="day_of_week_medium_thursday">Do</string>
-    <string name="day_of_week_medium_friday">Vr</string>
-    <string name="day_of_week_medium_saturday">Sa</string>
-
-    <string name="day_of_week_short_sunday">So</string>
-    <string name="day_of_week_short_monday">Ma</string>
-    <string name="day_of_week_short_tuesday">Di</string>
-    <string name="day_of_week_short_wednesday">Wo</string>
-    <string name="day_of_week_short_thursday">Do</string>
-    <string name="day_of_week_short_friday">Vr</string>
-    <string name="day_of_week_short_saturday">Sa</string>
-
-    <string name="day_of_week_shortest_sunday">1</string>
-    <string name="day_of_week_shortest_monday">2</string>
-    <string name="day_of_week_shortest_tuesday">3</string>
-    <string name="day_of_week_shortest_wednesday">4</string>
-    <string name="day_of_week_shortest_thursday">5</string>
-    <string name="day_of_week_shortest_friday">6</string>
-    <string name="day_of_week_shortest_saturday">7</string>
-
-    <string name="am">vm.</string>
-    <string name="pm">nm.</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 29c23e9..51d23e8 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Foonopsies"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Skermslot"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Sit af"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Foutverslag"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Neem foutverslag"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Dit sal inligting oor die huidige toestand van jou toestel insamel om as \'n e-posboodskap te stuur. Dit sal \'n tydjie neem vandat die foutverslag begin is totdat dit reg is om gestuur te word; wees asseblief geduldig."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Stilmodus"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Klank is AF"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Klank is AAN"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Jou boodskappe"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Lees en skryf jou SMS, e-pos en ander boodskappe."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Jou persoonlike inligting"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Direkte toegang tot jou kontakte en kalender wat op die tablet gestoor is."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Direkte toegang tot jou kontakte en kalender wat op die foon gestoor is."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Direkte toegang tot inligting oor jou, gestoor in jou kontakkaart."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Jou sosiale inligting"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Direkte toegang tot inligting oor jou kontakte en sosiale verbindings."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Jou ligging"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Monitor jou fisiese ligging."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Netwerkkommunikasie"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Kry toegang tot verskeie netwerkfunksies."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Kry toegang tot toestelle en netwerke deur Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Oudio-instellings"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Verander oudio-instellings."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Affekteer battery"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Gebruik kenmerke wat vinnig die battery opgebruik."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalender"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Direkte toegang tot kalender en gebeurtenisse."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Lees gebruikerswoordeboek"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Lees woorde in die gebruikerswoordeboek."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Skryf gebruikerswoordeboek"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Voeg woorde by die gebruikerswoordeboek."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Boekmerke en geskiedenis"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Direkte toegang tot boekmerke en blaaiergeskiedenis."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Wekker"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Stel die wekker."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Stemboodskapdiens"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Direkte toegang tot stemboodskapdiens."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofoon"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Direkte toegang tot die mikrofoon om oudio op te neem."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Direkte toegang tot kamera vir die neem van foto of video."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Jou programme-inligting"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Vermoë om die gedrag van ander programme op jou toestel te beïnvloed."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Muurpapier"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Verander die toestel se muurpapier-instellings."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Klok"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Verander die toestel se tyd of tydsone."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Statusbalk"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Verander die toestel se statusbalk-instellings."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Sinkronisasie-instellings"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Gaan in by die sinkronisasie-instellings."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Jou rekeninge"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Kry toegang tot beskikbare rekeninge."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Hardewarekontroles"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Laervlak-toegang en -beheer van die stelsel."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Ontwikkelingshulpmiddels"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Kenmerke net nodig vir programontwikkelaars."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Ander program-UI"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Affekteer ander programme se UI"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Stoor"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Gebruik die USB-berging."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Lees die SD-kaart."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Laat die program toe om WAP-boodskappe te ontvang en te verwerk. Hierdie toestemming sluit ook in dat boodskappe wat na jou toestel gestuur is, gemonitor of uitgevee kan word, sonder dat jy dit gesien het."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"haal lopende programme op"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Laat die program toe om inligting oor die huidig- en onlangslopende take op te haal. Dit kan moontlik die program toelaat om inligting oor watter programme op die toestel gebruik word, te ontdek."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interaksie tussen gebruikers"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Laat die program toe om aksies vir verskillende gebruikers op die toestel uit te voer. Kwaadwillige programme kan dit gebruik om die beskerming tussen gebruikers te skend."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"volle lisensie vir interaksie tussen gebruikers"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Laat alle moontlike interaksies tussen gebruikers toe."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"bestuur gebruikers"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Laat programme toe om gebruikers op die toestel te bestuur, insluitend navrae, skepping en uitvee."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"haal besonderhede van lopende programme op"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Laat die program toe om inligting op te haal oor huidige en onlangse lopende take. Kwaadwillige programme kan dalk private inligting oor ander programme ontdek."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"herrangskik lopende programme"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Laat die program toe om die interne status van die stelsel op te haal. Kwaadwillige programme kan \'n verskeidenheid privaat en beveiligde inligting ophaal wat hulle gewoonlik nooit nodig het nie."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"haal skerminhoud op"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Laat die program toe om die inhoud van die aktiewe venster op te haal. Kwaadwillige programme kan die hele venster se inhoud ophaal, en al die teks ondersoek, behalwe wagwoorde."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"aktiveer toeganklikheid tydelik"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Laat \'n program toe om toeganklikheid tydelik op die toestel te aktiveer. Kwaadwillige programme kan sonder die toestemming van die gebruiker toeganklikheid verkry."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"haal vensterinligting op"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Laat \'n program toe om inligting oor vensters vanaf die vensterbestuurder op te haal. Kwaadwillige programme kan moontlik inligting ophaal wat vir interne stelselgebruik bedoel is."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filter gebeure"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Laat \'n program toe om \'n invoerfilter te registreer wat die stroom van alle gebruikergebeure filter voordat dit versend word. Kwaadwillige programme kan moontlik die stelsel-UI beheer sonder gebruikers se tussentrede."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"vergroot skerm"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Laat \'n program toe om die inhoud van \'n skerm te vergroot. Kwaadwillige programme kan die skerminhoud so omskep dat die toestel onbruikbaar word."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"gedeeltelike afskakeling"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Plaas die aktiwiteitbestuurder in \'n afsluitingstatus. Doen nie \'n volledige afsluiting nie."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"verhoed program-oorskakelings"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Laat die program toe om die maksimum getal prosesse te beheer wat sal loop. Nooit nodig vir normale programme nie."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"dwing agtergrondprogramme om te sluit"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Laat die program toe om te beheer of aktiwiteite altyd klaar maak sodra hulle na die agtergrond beweeg. Nooit nodig vir normale programme nie."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"verander batterystatistiek"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Laat die program toe om battery-statistieke te versamel. Nie vir gebruik deur normale programme nie."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"lees batterystatistieke"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Laat \'n program toe om die huidige lae-vlak batteryverbruikdata te lees. Kan die program toelaat om gedetailleerde inligting te vind oor watter programme jy gebruik."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"verander batterystatistieke"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Laat die program toe om versamelde battery-statistieke te verander. Nie vir gebruik deur normale programme nie."</string>
     <string name="permlab_backup" msgid="470013022865453920">"beheerstelsel-rugsteun en -teruglaai"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Laat die program toe om die stelsel se rugsteun-en-teruglaai-meganisme te beheer. Nie vir gebruik deur normale programme nie."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"bevestig \'n volledige rugsteun- of teruglaaihandeling"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"wys ongemagtigde vensters"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Laat die program toe om vensters te skep wat bedoel is om deur die interne stelsel se gebruikerkoppelvlak gebruik te word. Nie vir gebruik deur normale programme nie."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"teken oor ander programme"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Laat die program toe om stelsel-opletberigvensters te wys. Sommige opletberigvensters kan moontlik die hele skerm oorneem."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Laat die program toe om bo-oor ande programme of dele van die gebruikerkoppelvlak te teken. Hulle kan met jou gebruik van die koppelvlak in enige program inmeng, of verander wat jy dink jy in ander programme sien."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"verander globale animasiespoed"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Laat die program toe om die globale animasiespoed te eniger tyd te verander (vinniger of stadiger animasie)."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"bestuur programtokens"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Laat die program toe om sy eie tokens te skep en te bestuur, deur hul normale Z-volgorde te omseil. Dit moet nooit vir normale programme nodig wees nie."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"vries skerm"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Laat die program toe om tydelik die skerm te vries vir \'n volskermoorgang."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"druk sleutels en beheerknoppies"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Laat die program toe om sy eie invoergebeure na ander programme te stuur (soos om sleutels te druk). Kwaadwillige programme kan dit dalk gebruik om beheer van die tablet oor te neem."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Laat die program toe om sy eie invoergebeure na ander programme te stuur (soos om sleutels te druk). Kwaadwillige programme kan dit dalk gebruik om beheer van die foon oor te neem."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"installeer programme direk"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Laat die program toe om nuwe of opgedateerde Android-pakkette te installeer. Kwaadwillige programme kan dit dalk gebruik om nuwe programme by te voeg met arbitrêr kragtige toestemmings."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"vee alle programkasdata uit"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Laat die program toe om tabletgeheue beskikbaar te stel deur lêers uit te vee in die programkasgids. Toegang tot stelselproses is gewoonlik baie beperk."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Laat die program toe om vrye foongeheue beskikbaar te stel deur lêers uit te vee in die programkasgids. Toegang tot stelselproses is gewoonlik baie beperk."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Laat die program toe om tabletberging oop te maak deur lêers in die kas-gidse van ander programme uit te vee. Dit kan veroorsaak dat ander programme stadiger begin omdat hulle hulle data moet herophaal."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Laat die program toe om foonberging oop te maak deur lêers in die kas-gidse van ander programme uit te vee. Dit kan veroorsaak dat ander programme stadiger begin omdat hulle hulle data moet herophaal."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"skuif programhulpbronne"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Laat die program toe om hulpbronne van interne na eksterne media te skuif, en omgekeerd."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"lees sensitiewe logdata"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Laat die program toe om ekstra liggingverskaffer-bevele te gebruik. Die programme kan dit moontlik gebruik om met die werking van die GPS of ander liggingsbronne in te meng."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"toestemming om \'n liggingverskaffer te installeer"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Skep skynliggingsbronne vir toetsing of installeer \'n nuwe liggingsverskaffer. Die program kan dan die ligging en/of status wat deurgegee is deur ander liggingsbronne, soos GPS of liggingsverskaffers, oorheers."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"presiese (GPS) ligging"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Vekry toegang tot akkurate liggingsbronne soos die globale posisioneringstelsel op jou tablet. Wanneer liggingsdienste beskikbaar en aangeskakel is, laat hierdie toestemming die program toe om jou presiese ligging te bepaal."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Vekry toegang tot akkurate liggingsbronne soos die globale posisioneringstelsel op jou foon. Wanneer liggingsdienste beskikbaar en aangeskakel is, laat hierdie toestemming die program toe om jou presiese ligging te bepaal."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"benaderde (netwerkgebaseerde) ligging"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Verkry toegang tot \'n benaderde ligging vanaf die liggingsverskaffers wat netwerkbronne soos seltorings en Wi-Fi gebruik. Wanneer hierdie liggingsdienste beskikbaar en aangeskakel is, laat hierdie toestemming die program toe om jou benaderde ligging te bepaal."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"presiese ligging (GPS en netwerkgebaseer)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Laat die program toe om jou presiese ligging te kry met behulp van die globaleposisioneringstelsel (GPS) of netwerkliggingbronne soos seltorings en Wi-Fi. Hierdie liggingdienste moet aangeskakel en beskikbaar wees aan jou toestel vir die program om dit te gebruik. Programme kan dit gebruik om te bepaal waar jy is en kan batterylewe opgebruik."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"benaderde ligging (netwerkgebaseer)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Laat die program toe om jou benaderde ligging te kry. Hierdie ligging word verkry deur liggingdienste met gebruik van netwerkliggingbronne soos seltorings en Wi-Fi. Hierdie liggingdienste moet aangeskakel en beskikbaar wees aan jou toestel vir die program om dit te gebruik. Programme kan dit gebruik om te bepaal waar omtrent jy is."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"kry toegang tot SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Laat die program toe om SurfaceFlinger se laevlak-kenmerke te gebruik."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"lees raambuffer"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Laat die program toe om die inhoud van die raambuffer te lees."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"stel Wi-Fi-skerms op"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Laat die program toe om Wi-Fi-skerms op te stel en daaraan te koppel."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"beheer Wi-Fi-skerms"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Laat die program toe om laevlak-kenmerke van Wi-Fi-skerms te beheer."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"verander jou klankinstellings"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Laat die program toe om globale klankinstellings soos volume en watter luidspreker vir uitvoer gebruik word, te verander."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"neem klank op"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"gaan in by Bluetooth-instellings"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Laat die program toe om die plaaslike Bluetooth-tablet op te stel, en om met afstandbeheer toestelle saam te bind."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Laat die program toe om die plaaslike Bluetooth-foon op te stel en te ontdek en met afgeleë toestelle saam te bind."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Bekyk WiMAX-verbindings"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"koppel aan en ontkoppel van WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Laat die program toe om te bepaal of WiMAX geaktiveer is en of enige WiMAX-netwerke gekoppel is."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Verander WiMAX-status"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Laat die program toe om die tablet aan WiMAX-netwerke te koppel en daarvan te ontkoppel."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Laat die program toe om jou huidig gesinkroniseerde strome te verander. Kwaadwillige programme kan dalk jou gesinkroniseerde strome verander."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"lees terme wat jy by die woordeboek gevoeg het"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Laat ’n program toe om alle woorde, name en frases wat die gebruiker moontlik in die gebruikerwoordeboek gestoor het, te lees."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"skryf na gebruikergedefinieerde woordeboek"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"voeg woorde by gebruiker-gedefinieerde woordeboek"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Laat die program toe om nuwe woorde in die gebruikerwoordeboek te skryf."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"toets toegang tot beskermde berging"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"toets toegang tot beskermde berging"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Laat die program toe om \'n toestemming vir USB-storing wat op toekomstige toestelle beskikbaar sal wees, te toets."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Laat die program toe om \'n toestemming te toets vir USB-berging wat op toekomstige toestelle beskikbaar sal wees."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Laat die program toe om \'n toestemming vir die SD-kaart wat op toekomstige toestelle beskikbaar sal wees, te toets."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"verander of vee die inhoud van jou USB-berging uit"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"Verander of vee die inhoud van jou SD-kaart uit"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Laat die program toe om na die SD-kaart te skryf."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"verander/vee uit interne mediabergingsinhoud"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Laat die program toe om die inhoud van die interne mediaberging te verander."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"verkry toegang tot alle gebruikers se eksterne berging"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Laat die program toe om toegang tot eksterne berging vir alle gebruikers te verkry."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"lees die kaslêerstelsel"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Laat die program toe om die kaslêerstelsel te lees en skryf."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"maak/ontvang internetoproepe"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Vereis dat gestoorde programdata geënkripteer word."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Deaktiveer kameras"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Voorkom die gebruik van alle toestelkameras."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Deaktiveer kenmerke in \'keyguard\'"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Voorkom die gebruik van \'n paar kenmerke in \'keyguard\'."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Tuis"</item>
     <item msgid="869923650527136615">"Mobiel"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Probeer weer"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Maksimum gesigontsluit-pogings oorskry"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Laai, (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Gehef."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Gelaai"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Koppel jou herlaaier."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Geen SIM-kaart."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Geen SIM-kaart nie"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Geen SIM-kaart in tablet nie."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Geen SIM-kaart in foon nie."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Steek \'n SIM-kaart in."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Patroon uitgevee"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Sel bygevoeg"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Patroon klaar"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Voeg legstuk by."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Leeg"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Ontsluitruimte uitgevou."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Ontsluitruimte ingevou."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>-legstuk."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Gebruikerkieser"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Status"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Kamera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Media-kontroles"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Herordening van legstuk begin."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Herordening van legstuk beëindig."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Legstuk <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> uitgevee."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Vou ontsluitruimte uit."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Sleep-ontsluit."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Patroon ontsluit."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Gesigslot."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN ontsluit."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Wagwoord ontsluit."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Patroonarea."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Sleep-area."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopieer URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Kies teks"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Tekskeuse"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"voeg by woordeboek"</string>
-    <string name="deleteText" msgid="7070985395199629156">"vee uit"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Voeg by woordeboek"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Vee uit"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Invoermetode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksaksies"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Bergingspasie word min"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Oop Wi-Fi-netwerke beskikbaar"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Meld aan by Wi-Fi-netwerk"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Meld aan by netwerk"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kon nie aan Wi-Fikoppel nie"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" het \'n swak internetverbinding."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Aan:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Voer die vereiste PIN in:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Die foon sal tydelik van Wi-Fi ontkoppel terwyl dit aan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gekoppel is"</string>
     <string name="select_character" msgid="3365550120617701745">"Voeg karakter in"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Stuur SMS-boodskappe"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; stuur \'n groot aantal SMS-boodskappe. Wil jy hierdie program toelaat om voort te gaan om boodskappe te stuur?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Laat toe"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Weier"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; wil \'n boodskap na &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; stuur."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Hierdie "<font fgcolor="#ffffb060">"kan heffings veroorsaak"</font>" op jou selfoonrekening."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Dit sal heffings op jou selfoonrekening veroorsaak."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Stuur"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Kanselleer"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Onthou my keuse"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Jy kan dit later verander in Instellings &gt; Programme"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Laat altyd toe"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Moet nooit toelaat nie"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kaart verwyder"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Die mobielnetwerk sal nie beskikbaar wees nie totdat jy weer begin met \'n geldige SIM-kaart."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Klaar"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Stel datum"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Stel"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Klaar"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Verstek"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Geen toestemmings benodig nie"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Versteek"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Wys alle"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NUUT: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NUUT: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Verskaf deur <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Geen toestemmings benodig nie"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"dit kan jou dalk geld kos"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB-geheue"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB gekoppel"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Jy het via USB aan jou rekenaar gekoppel. Raak die knoppie hier onder as jy lêers tussen jou rekenaar en jou Android se USB-geheue wil kopieer."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is geaktiveer deur <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Raak om die netwerk te bestuur."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Gekoppel aan <xliff:g id="SESSION">%s</xliff:g>. Raak om die netwerk te bestuur."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Altydaan-VPN koppel tans..."</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Altydaan-VPN gekoppel"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Altydaan-VPN-fout"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Raak om verbinding terug te stel"</string>
     <string name="upload_file" msgid="2897957172366730416">"Kies lêer"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Geen lêer gekies nie"</string>
     <string name="reset" msgid="2448168080964209908">"Stel terug"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Deel"</string>
     <string name="find" msgid="4808270900322985960">"Vind"</string>
     <string name="websearch" msgid="4337157977400211589">"Websoektog"</string>
+    <string name="find_next" msgid="5742124618942193978">"Soek volgende"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Vind vorige"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Liggingsversoek van <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Liggingsversoek"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Versoek deur <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Foon"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Oorfone"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dokluidsprekers"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-klank"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Stelsel"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-oudio"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Klaar"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Media-uitvoer"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Skandeer tans..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Koppel tans..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Beskikbaar"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Nie beskikbaar nie"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Ingeboude skerm"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-skerm"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Oorlegger #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Draadlose skerm is gekoppel"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Hierdie skerm word op \'n ander toestel gewys"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Ontkoppel"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Noodoproep"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Het jy die patroon vergeet?"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Verkeerde patroon"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Verkeerde wagwoord"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Verkeerde PIN"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Probeer weer oor <xliff:g id="NUMBER">%d</xliff:g> sekondes."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Teken jou patroon"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Voer SIM-PIN in"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Voer PIN in"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Voer wagwoord in"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM is nou gedeaktiveer. Voer PUK-kode in om voort te gaan. Kontak diensverskaffer vir details."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Voer die gewenste PIN-kode in"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Bevestig gewenste PIN-kode"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Ontsluit tans SIM-kaart…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Verkeerde PIN-kode."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Tik \'n PIN in wat 4 tot 8 syfers lank is."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK-kode moet 8 of meer syfers wees."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Voer weer die korrekte PUK-kode in. Herhaalde pogings sal die SIM permanent deaktiveer."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN-kodes stem nie ooreen nie"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Te veel patroonpogings"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Om te ontsluit, meld met jou Google-rekening aan."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Gebruikernaam (e-pos)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Wagwoord"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Meld aan"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Ongeldige gebruikernaam of wagwoord."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Het jy jou gebruikernaam of wagwoord vergeet?"\n"Besoek "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Kontroleer tans rekening..."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Jy het jou PIN <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerd ingetik. "\n\n"Probeer weer oor <xliff:g id="NUMBER_1">%d</xliff:g> sekondes."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Jy het <xliff:g id="NUMBER_0">%d</xliff:g> keer jou wagwoord verkeerdelik getik. "\n\n"Probeer weer oor <xliff:g id="NUMBER_1">%d</xliff:g> sekondes."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerdelik geteken. "\n\n"Probeer weer oor <xliff:g id="NUMBER_1">%d</xliff:g> sekondes."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Jy het <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerdelik gepoog om die tablet te ontsluit. Na nog <xliff:g id="NUMBER_1">%d</xliff:g> onsuksesvolle pogings, sal die tablet na die fabrieksverstek teruggestel word en al die gebruikerdata sal verlore wees."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Jy het <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerdelik gepoog om die foon te ontsluit. Na nog <xliff:g id="NUMBER_1">%d</xliff:g> onsuksesvolle pogings, sal die foon na die fabrieksverstek teruggestel word en al die gebruikerdata sal verlore wees."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Jy het <xliff:g id="NUMBER">%d</xliff:g> keer verkeerdelik gepoog om die tablet te ontsluit. Die tablet sal nou na fabrieksverstek teruggestel word."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Jy het <xliff:g id="NUMBER">%d</xliff:g> keer verkeerdelik gepoog om die foon te ontsluit. Die foon sal nou na fabrieksverstek teruggestel word."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerdelik geteken. Na nog <xliff:g id="NUMBER_1">%d</xliff:g> onsuksesvolle pogings, sal jy gevra word om jou tablet te ontsluit deur middel van \'n e-posrekening."\n\n" Probeer weer oor <xliff:g id="NUMBER_2">%d</xliff:g> sekondes."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerdelik geteken. Na nog <xliff:g id="NUMBER_1">%d</xliff:g> onsuksesvolle pogings, sal jy gevra word om jou foon te ontsluit deur middel van \'n e-posrekening."\n\n" Probeer weer oor <xliff:g id="NUMBER_2">%d</xliff:g> sekondes."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Verwyder"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Moet volume bo veilige vlak verhoog word?"\n"Deur vir lang tydperke op hoë volume te luister, kan jou gehoor beskadig."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Hou aan met twee vingers inhou om toeganklikheid te aktiveer."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Toeganklikheid geaktiveer."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Toeganklikheid gekanselleer."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Huidige gebruiker <xliff:g id="NAME">%1$s</xliff:g> ."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Eienaar"</string>
 </resources>
diff --git a/core/res/res/values-am/donottranslate-cldr.xml b/core/res/res/values-am/donottranslate-cldr.xml
index 2319fbf..b3b76f9 100644
--- a/core/res/res/values-am/donottranslate-cldr.xml
+++ b/core/res/res/values-am/donottranslate-cldr.xml
@@ -1,93 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">ጃንዩወሪ</string>
-    <string name="month_long_standalone_february">ፌብሩወሪ</string>
-    <string name="month_long_standalone_march">ማርች</string>
-    <string name="month_long_standalone_april">ኤፕረል</string>
-    <string name="month_long_standalone_may">ሜይ</string>
-    <string name="month_long_standalone_june">ጁን</string>
-    <string name="month_long_standalone_july">ጁላይ</string>
-    <string name="month_long_standalone_august">ኦገስት</string>
-    <string name="month_long_standalone_september">ሴፕቴምበር</string>
-    <string name="month_long_standalone_october">ኦክተውበር</string>
-    <string name="month_long_standalone_november">ኖቬምበር</string>
-    <string name="month_long_standalone_december">ዲሴምበር</string>
-
-    <string name="month_long_january">ጃንዩወሪ</string>
-    <string name="month_long_february">ፌብሩወሪ</string>
-    <string name="month_long_march">ማርች</string>
-    <string name="month_long_april">ኤፕረል</string>
-    <string name="month_long_may">ሜይ</string>
-    <string name="month_long_june">ጁን</string>
-    <string name="month_long_july">ጁላይ</string>
-    <string name="month_long_august">ኦገስት</string>
-    <string name="month_long_september">ሴፕቴምበር</string>
-    <string name="month_long_october">ኦክተውበር</string>
-    <string name="month_long_november">ኖቬምበር</string>
-    <string name="month_long_december">ዲሴምበር</string>
-
-    <string name="month_medium_january">ጃንዩ</string>
-    <string name="month_medium_february">ፌብሩ</string>
-    <string name="month_medium_march">ማርች</string>
-    <string name="month_medium_april">ኤፕረ</string>
-    <string name="month_medium_may">ሜይ</string>
-    <string name="month_medium_june">ጁን</string>
-    <string name="month_medium_july">ጁላይ</string>
-    <string name="month_medium_august">ኦገስ</string>
-    <string name="month_medium_september">ሴፕቴ</string>
-    <string name="month_medium_october">ኦክተ</string>
-    <string name="month_medium_november">ኖቬም</string>
-    <string name="month_medium_december">ዲሴም</string>
-
-    <string name="month_shortest_january">ጃ</string>
-    <string name="month_shortest_february">ፌ</string>
-    <string name="month_shortest_march">ማ</string>
-    <string name="month_shortest_april">ኤ</string>
-    <string name="month_shortest_may">ሜ</string>
-    <string name="month_shortest_june">ጁ</string>
-    <string name="month_shortest_july">ጁ</string>
-    <string name="month_shortest_august">ኦ</string>
-    <string name="month_shortest_september">ሴ</string>
-    <string name="month_shortest_october">ኦ</string>
-    <string name="month_shortest_november">ኖ</string>
-    <string name="month_shortest_december">ዲ</string>
-
-    <string name="day_of_week_long_sunday">እሑድ</string>
-    <string name="day_of_week_long_monday">ሰኞ</string>
-    <string name="day_of_week_long_tuesday">ማክሰኞ</string>
-    <string name="day_of_week_long_wednesday">ረቡዕ</string>
-    <string name="day_of_week_long_thursday">ሐሙስ</string>
-    <string name="day_of_week_long_friday">ዓርብ</string>
-    <string name="day_of_week_long_saturday">ቅዳሜ</string>
-
-    <string name="day_of_week_medium_sunday">እሑድ</string>
-    <string name="day_of_week_medium_monday">ሰኞ</string>
-    <string name="day_of_week_medium_tuesday">ማክሰ</string>
-    <string name="day_of_week_medium_wednesday">ረቡዕ</string>
-    <string name="day_of_week_medium_thursday">ሐሙስ</string>
-    <string name="day_of_week_medium_friday">ዓርብ</string>
-    <string name="day_of_week_medium_saturday">ቅዳሜ</string>
-
-    <string name="day_of_week_short_sunday">እሑድ</string>
-    <string name="day_of_week_short_monday">ሰኞ</string>
-    <string name="day_of_week_short_tuesday">ማክሰ</string>
-    <string name="day_of_week_short_wednesday">ረቡዕ</string>
-    <string name="day_of_week_short_thursday">ሐሙስ</string>
-    <string name="day_of_week_short_friday">ዓርብ</string>
-    <string name="day_of_week_short_saturday">ቅዳሜ</string>
-
-    <string name="day_of_week_shortest_sunday">እ</string>
-    <string name="day_of_week_shortest_monday">ሰ</string>
-    <string name="day_of_week_shortest_tuesday">ማ</string>
-    <string name="day_of_week_shortest_wednesday">ረ</string>
-    <string name="day_of_week_shortest_thursday">ሐ</string>
-    <string name="day_of_week_shortest_friday">ዓ</string>
-    <string name="day_of_week_shortest_saturday">ቅ</string>
-
-    <string name="am">ጡዋት</string>
-    <string name="pm">ከሳዓት</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index f0e96ba..f846ffd 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"የስልክ አማራጮች"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"ማያ ቆልፍ"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"ኃይል አጥፋ"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"የሳንካ ሪፖርት"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"የሳንካ ሪፖርት ውሰድ"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"ይሄ እንደ የኢሜይል መልዕክት አድርጎ የሚልከውን ስለመሣሪያዎ የአሁኑ ሁኔታ መረጃ ይሰበስባል። የሳንካ ሪፖርቱን ከመጀመር ጀምሮ እስኪላክ ድረስ ትንሽ ጊዜ ይወስዳል፤ እባክዎ ይታገሱ።"</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"የፀጥታ ሁነታ"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"ድምፅ ጠፍቷል"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"ድምፅ በርቷል"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"መልዕክቶችዎ"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"ኤስ ኤም ኤስህን፣ ኢሜይልህን እና ሌላ መልዕክቶችህን አንብብና ፃፍ።"</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"የግል መረጃዎ"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"በጡባዊዎ ላይ የተከማቹ እውቂያዎች እና ቀን መቁጠሪያጋ ቀጥታ ይድረሱ።"</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"በስልኩ ላይ ወደ ተከማቸው ዕውቂያዎችዎ እና የቀን መቁጠሪያዎበቀጥታ  ይድረሱ"</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"በእውቂያ ካርድህ ላይ ወደተከማቸ የአንተ መረጃ ቀጥተኛ መዳረሻ።"</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"ማህበራዊ መረጃህ"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"ወደ የእውቂያዎችህና የማህበራዊ ግንኙነቶችህ መረጃ ቀጥተኛ መዳረሻ።"</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"ስፍራዎ"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"ያለህበትን አካባቢ ተቆጣጠር።"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"የአውታረ መረብ ግኑኙነት"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"የተለያዩ የአውታረ መረብ ባህሪያትን ድረስ።"</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"ብሉቱዝ"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"መሳሪያዎችን እና አውታረ መረቦችን በብሉቱዝ በኩል አግኝ።"</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"የድምጽ ቅንብሮች"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"የድምጽ ቅንብሮችን ቀይር።"</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"ባትሪ ላይ ተፅዕኖ ያሳርፋል"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"ባትሪ ቶሎ ሊጨርሱ የሚችሉ ባህርያትን ተጠቀም።"</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"ቀን መቁጠሪያ"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"ወደ ቀን መቁጠሪያና ክስተቶች ቀጥተኛ መዳረሻ።"</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"የተጠቃሚ መዝገበ ቃላት አንብብ"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"ቃላትን በተጠቃሚ መዝገበ ቃላት አንብብ።"</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"የተጠቃሚ መዝገበ ቃላት ጻፍ"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"ቃላትን የተጠቃሚ መዝገበ ቃላትህ ላይ አክል።"</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"ዕልባቶች እና ታሪክ"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"ወደ ዕልባቶችና የአሳሽ ታሪክ ቀጥተኛ መዳረሻ።"</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"ማንቂያ"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"የማንቂያ ሰዓቱን አዘጋጅ።"</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"የድምጽ መልዕክት"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"ወደ የድምጽ መልዕክት ቀጥተኛ መዳረሻ።"</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"ማይክሮፎን"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"ድምጽ ለመቅረጽ ወደ ማይክሮፎኑ ቀጥተኛ መዳረሻ።"</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"ካሜራ"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"ለካሜራ ምስል ወይም ቪዲዮ ለመቅረጽ ቀጥተኛ መዳረሻ።"</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"የመተግበሪያዎችህ መረጃ"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"በመሣሪያህ ላይ ያሉ የሌሎች መተግበሪያዎች ባህሪዎች ላይ ተፅዕኖ የማሳረፍ ችሎታ።"</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"ልጣፍ"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"የመሣሪያውን ልጣፍ ቅንብሮች ቀይር።"</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"ሰዓት"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"የመሣሪያውን ሰዓት ወይም የሰዓት ሰቁን ቀይር።"</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"የሁኔታ አሞሌ"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"የመሣሪያ ሁኔታ አሞሌ ቅንብሮቹን ቀይር።"</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"የማመሳሰል ቅንብሮች"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"ወደ የማመሳሰል ቅንብሮች መዳረሻ።"</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"መለያዎችዎ"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">" ለተገኙት መለያዎች ድረስ"</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"የሃርድዌር ቁጥጥሮች"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"የስርዓቱ ዝቅተኛ-ደረጃ ድረስ እና ጠብቅ"</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"የግንባታ  መሣሪያዎች"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"ባህሪያት ለመተግበሪያ ገንቢዎች ብቻ ያስፈልጋሉ።"</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"የሌላ መተግበሪያ ተጠቃሚ በይነገጽ"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"የሌሎች መተግበሪያዎች ተጠቃሚ በይነገጽ ተግብር።"</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>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"መተግበሪያው የWAP መልእክቶችን እንዲያነብ እና እንዲያካሂድ ይፈቅዳል። ይህ ፈቃድ የተላኩልህን መልእክቶች ላንተ ሳያሳይህ የመቆጣጠር ወይም የመሰረዝ ብቃትን ያጠቃልላል።"</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"አሂድ መተግበሪያዎችን ሰርስረህ አውጣ"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"መተግበሪያው በአሁኑ ጊዜና በቅርቡ እየተካሄዱ ስላሉ ተግባሮችን መረጃ ሰርስሮ እንዲያወጣ ይፈቅድለታል። ይህ መተግበሪያው በመሳሪያው ላይ የትኛዎቹ መተግበሪያዎች ጥቅም ላይ ስለመዋላቸው መረጃ እንዲያገኝ ሊፈቅድለት ይችላል።"</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"በተለያዩ ተጠቃሚዎች መካከል መስተጋብር መፍጠር"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"መተግበሪያው በመሣሪያው ላይ በተለያዩ ተጠቃሚዎች ላይ እርምጃዎችን እንዲፈጽም ይፈቅድለታል። ተንኮል-አዘል መተግበሪያዎች ይህንን ተጠቅመው በተጠቃሚዎች መካከል ያለውን ጥበቃ ሊጥሱ ይችላሉ።"</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"በተለያዩ ተጠቃሚዎች መካከል መስተጋብር ለመፍጠር ሙሉ ፍቃድ"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"በተለያዩ ተጠቃሚዎች ላይ ሊኖሩ የሚችሉ መስተጋብሮችን ሁሉ ይፈቅዳል።"</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"ተጠቃሚዎችን ያስተዳድሩ"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"መተግበሪያዎች በመሣሪያው ላይ ያሉ ተጠቃሚዎችን እንዲያቀናብር ያስችለዋል፣ መጠየቅን፣ መፍጠርንና መሰረዝን ጨምሮ።"</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"እየሄዱ ስላሉ የመተግበሪያዎች ዝርዝሮች አምጣ"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"መተግበሪያው በአሁኑ ጊዜ እየተካሄዱ ስላሉና በቅርብ ጊዜ ስለተካሄዱ ተግባሮች መረጃ ዝርዝር እንዲያወጣ ይፈቅድለታል። ተንኮል-አዘል መተግበሪያዎች ስለ ሌሎች መተግበሪያዎች የግል መረጃ ሊያገኙ ይችላሉ።"</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"አሂድ ትግበራዎችን ድጋሚ ደርድር"</string>
@@ -243,6 +287,14 @@
     <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="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ተደራሽነት በጊዜያዊነት ያነቃል"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"አንድ መተግበሪያ በጊዜያዊነት በመሣሪያው ላይ ተደራሽነትን እንዲያነቃ ያስችለዋል። ተንኮል-አዘል መተግበሪያዎች ያለተጠቃሚው ፍቃድ ተደራሽነትን ሊያነቁ ይችላሉ።"</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"የመስኮት መረጃን አምጣ"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"አንድ መተግበሪያ ከመስኮት አቀናባሪው ሆኖ ስለመስኮቱ መረጃ እንዲያመጣ ያስችለዋል። ተንኮል-አዘል መተግበሪያዎች ለውስጣዊ ስርዓት ጥቅም የታሰበ መረጃን ሊወስዱ ይችላሉ።"</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"ክስተቶችን አጣራ"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"አንድ መተግበሪያ የሁሉንም ተጠቃሚዎች ክስተቶች ከመላካቸው በፊት እነሱን የሚያጣራ የግቤት ማጣሪያ እንዲመዘግብ ያስችለዋል። ተንኮል-አዘል መተግበሪያዎች ተጠቃሚው ጣልቃ ሳይገባ የስርዓቱን በይነገጽ ሊቆጣጠሩት ይችላሉ።"</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"ማሳያን አጉላ"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"አንድ መተግበሪያ የአንድ ማሳያ ይዘት እንዲያጎላ ይፈቅድለታል። ተንኮል-አዘል መተግበሪያዎች መሣሪያውን ከጥቅም ውጪ በሚያደርገው ሁኔታ የማሳያ ይዘቱ ሊለውጡት ይችላሉ።"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"ከፊል ዝጋ"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"የእንቅስቃሴውን አደራጅ ወደ ዝጋ ሁነታ አስቀምጥ።ሙሉ ለሙሉ ዝጋ አያከናውንም።"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"የትግበራ መቀያየርን ተከላከል"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"የሚሄዱ ሂደቶችን የመጨረሻ ቁጥር ለመቆጣጠር ለመተግበሪያው ይፈቅዳሉ፡፡ ለመደበኛ መተግበሪያዎች መቼም አያስፈልግም፡፡"</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"የጀርባ መተግበሪያዎች እንዲዘጉ አስገድዳቸው"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"ወዲያውኑ ወደ ዳራው እንደሄዱ እንቅስቃሴዎች ሁልጊዜ እንደተጨረሱ ለመቆጣጠር ለመተግበሪያው ይፈቅዳሉ፡፡ ለመደበኛ መተግበሪያዎች መቼም አያስፈልጉም፡፡"</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"የባትሪ ስታስቲክስ ቀይር"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"የተሰበሰቡ የባትሪ  ስታስቲክሶችን ለመለወጥ ለመተግበሪያው ይፈቅዳሉ፡፡ለመደበኛ ትግበራዎች ጥቅም አይደለም፡፡"</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"የባትሪ ስታቲስቲክስን ያነባል"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"አንድ መተግበሪያ የአሁኑን የዝቅተኛ-ደረጃ ባትሪ አጠቃቀም ውሂብን እንዲያነብ ያስችላል። መተግበሪያው ስለሚጠቀሟቸው መተግበሪያዎች ዝርዝር መረጃ እንዲያገኝ ሊያስችለው ይችላል።"</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"የባትሪ ስታስቲክስን ይቀይራል"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"የተሰበሰቡ የባትሪ  ስታስቲክሶችን እንዲቀይር ለመተግበሪያው ያስችለዋል። ለመደበኛ መተግበሪያዎች ጥቅም አይደለም።"</string>
     <string name="permlab_backup" msgid="470013022865453920">"የስርዓት መጠባበቂያን ተቆጣጠር እናእነበረበት መልስ"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"የስርዓቱን ምትኬ  እና እንደነበር መልስ መንገዶችን ለመቆጣጠር ለመተግበሪያው ይፈቅዳሉ፡፡ በመደበኛ መተግበሪያዎች ለመጠቀም አይሆንም፡፡"</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"የሙሉ መጠበቂያ ወይም እነበረበት መልስ ከዋኝ አረጋግጥ"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"ያልተፈቀደ Windows አሳይ"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"በውስጣዊ የስርዓት የተጠቃሚ በይነገፅ ለመጠቀም የተዘጋጁ መስኮቶችን ለመፍጠር ለመተግበሪያው ይፈቅዳሉ። ለመደበኛ መተግበሪያዎች አገልግሎት አይደለም።"</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"በሌሎች መተግበሪያዎች ላይ ሳል"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"መተግበሪያው የስርዓት ማሳወቂያ መስኮቶች እንዲያሳይ ይፈቅድለታል። አንዳንድ ማሳወቂያ መስኮቶች መላ ማያ ገጹን ሊቆጣጠሩት ይችላሉ።"</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"መተግበሪያው በሌሎች መተግበሪያዎች ወይም አንዳንድ የበይነገጽ ክፍሎች ላይ እንዲስል ያስችለዋል። በማንኛውም የመተግበሪያ በይነገጽ ላይ በሚሰሩት ስራ ላይ ጣልቃ ሊገቡ ወይም በሌሎች መተግበሪያዎች ላይ ምን እንደሚያዩ የሚመስልዎት ነገር ሊቀይሩ ይችላሉ።"</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="permlab_freezeScreen" msgid="4708181184441880175">"ማያ ገጹን እሰር"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"መተግበሪያው ለሙሉ ማያ ገጽ ሽግግር ብሎ ማያ ገጹን በጊዜያዊነት እንዲያስር ይፈቅድለታል።"</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>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"በቀጥታ ትግበራዎች ጫን"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Android ፓኬጆችንለማዘመን ወይም አዲስ ለመጫን ለመተግበሪያው ይፈቅዳሉ፡፡ በዘፈቀደ ሀይለኛ ፍቃዶች ጋር ተንኮል አዘል መተግበሪያዎች አዲስ መተግበሪያዎችን ለማከል ሊጠቀሙበት ይችላሉ፡፡"</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="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"በሌሎች መተግበሪያዎች የመሸጎጫ ማውጫዎች ውስጥ ያሉትን ፋይሎች በመሰረዝ መተግበሪያው የጡባዊ ማከማቻ ቦታ ነጻ እንዲያስለቅቅ ያስችለዋል። ይሄ ሌሎች መተግበሪያዎች ውሂባቸውን ዳግም ማምጣት ስላለባቸው ይበልጥ ዘግየት ብለው እንዲጀምሩ ሊያደርጋቸው ይችላል።"</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"በሌሎች መተግበሪያዎች የመሸጎጫ ማውጫዎች ውስጥ ያሉትን ፋይሎች በመሰረዝ መተግበሪያው የስልክ ማከማቻ ቦታ ነጻ እንዲያስለቅቅ ያስችለዋል። ይሄ ሌሎች መተግበሪያዎች ውሂባቸውን ዳግም ማምጣት ስላለባቸው ይበልጥ ዘግየት ብለው እንዲጀምሩ ሊያደርጋቸው ይችላል።"</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"የመተግበሪያ ሃብቶችን አንቀሳቅስ"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"ከውስጣዊ ወደ  ውጫዊ ሚዲያ እና በተገላቢጦሽ የመተግበሪያ ሃብቶችን ለማንቀሳቀስ ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"ወሳኝ የማስታወሻ ውሂብ አንብብ"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"መተግበሪያው ተጨማሪ የአካባቢ አቅራቢ ትእዛዞችን እንዲደርስ ይፈቅድለታል። ይህ መተግበሪያው በGPS ወይም ሌላ የመነሻ ምንጮች ክወና ላይ ጣልቃ እንዲገባ ሊፈቅድለት ይችላል።"</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"የሥፍራ አቅራቢ ለመጫን ፍቀድ"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"ለሙከራ የማስመሰል የመነሻ ምንጮችን ፍጠር ወይም አዲስ የአካባቢ አቅራቢ ጫን። ይህ መተግበሪያው አካባቢውን እና/ወይም እንደ GPS ወይም የአካባቢ አቅራቢዎች ባሉ ሌላ የመነሻ ምንጮች የተመለሱ ሁኔታዎችን ችላ እንዲል ይፈቅድለታል።"</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"ትክክለኛ (GPS) አካባቢ"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"እንደ አለም አቀፍ የመሬት አቀማመጥ ስርዓት (GPS) ያሉ የትክክለኛ የመነሻ ምንጮችን በጡባዊ ቱኮው ላይ አግኝ። የአካባቢ አገልግሎቶች የሚገኙና የተነሱ ሲሆኑ ይህ ፈቃድ መተግበሪያው ትክክለኛ አካባቢህን እንዲያውቅ ይፈቅድለታል።"</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"እንደ አለም አቀፍ የመሬት አቀማመጥ ስርዓት (GPS) ያሉ የትክክለኛ የመነሻ ምንጮችን በስልኩ ላይ አግኝ። የአካባቢ አገልግሎቶች የሚገኙና የተነሱ ሲሆኑ ይህ ፈቃድ መተግበሪያው ትክክለኛ አካባቢህን እንዲያውቅ ይፈቅድለታል።"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"ግምታዊ (በአውታረ መረብ ላይ የተመሰረተ) አካባቢ"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"እንደ ህዋስ ማማ እና Wi-Fi ያሉ የአውታረ መረብ ምንጮችን በመጠቀም ግምታዊ አካባቢን ከአካባቢ አቅራቢዎች ድረስባቸው። እነዚህ የአካባቢ አገልግሎቶች የሚገኙና የተነሱ ሲሆኑ ይህ ፈቃድ መተግበሪያው ግምታዊ አካባቢህን እንዲያውቅ ይፈቅድለታል።"</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"ትክክለኛ አካባቢ (በጂ ፒ ኤስ እና አውታረ መረብ ላይ የተመሠረተ)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"መተግበሪያው የእርስዎን አለምአቀፍ የመሬት አቀማመጥ ስርዓትን (ጂ ፒ ኤስ) ወይም እንደ የተንቀሳቃሽ ስልክ ማማዎች እና Wi-Fi ያሉ የአውታረ መረብ አካባቢ ምንጮችን ተጠቅሞ ትክክለኛ አካባቢዎትን እንዲያውቅ ያስችለዋል። መተግበሪያው እነዚህ የአካባቢ አገልግሎቶችን እንዲጠቀምባቸው እነሱ ሊበሩ እና ለመሣሪያዎ የሚገኙ መሆን አለባቸው። መተግበሪያዎች እርስዎ የት እንዳሉ ለማወቅ ይህንን ሊጠቀሙበት ይችላሉ፣ እና ተጨማሪ ባትሪ ሊፈጁ ይችላሉ።"</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"ግምታዊ አካባቢ (በአውታረ መረብ ላይ የተመሰረተ)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"መተግበሪያው ግምታዊ አካባቢዎትን እንዲያገኝ ያሽችለዋል። ይህ አካባቢ እንደ የተንቀሳቃሽ ስልክ ማማዎች እና Wi-Fi ያሉ የአውታረ መረብ አካባቢ ምንጮችን በመጠቀም የሚገኝ ነው። መተግበሪያው እነዚህ የአካባቢ አገልግሎቶችን እንዲጠቀምባቸው እነሱ ሊበሩ እና ለመሣሪያዎ የሚገኙ መሆን አለባቸው። መተግበሪያዎች እርስዎ የት እንዳሉ ለማወቅ ይህንን ሊጠቀሙበት ይችላሉ።"</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"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="permlab_configureWifiDisplay" msgid="5595661694746742168">"የWifi ማሳያዎችን አዋቅር"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"መተግበሪያው የWifi ማሳያዎችን እንዲያዋቅርና ከእነሱ ጋር እንዲገናኝ ይፈቅድለታል።"</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"የWifi ማሳያዎችን ተቆጣጠር"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"መተግበሪያው በዝቅተኛ ደረጃ ላይ ያሉ የWifi ማሳያዎችን እንዲቆጣጠር ይፈቅድለታል።"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"የድምፅ ቅንብሮችን ለውጥ"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"መተግበሪያው አንደ የድምጽ መጠን እና ለውጽአት የትኛውን የድምጽ ማጉያ ጥቅም ላይ እንደዋለ የመሳሰሉ ሁለንተናዊ የድምጽ ቅንብሮችን እንዲያስተካክል ይፈቅድለታል።"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ኦዲዮ ቅዳ"</string>
@@ -437,7 +496,7 @@
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"የድረስባህሪያት ምልከታ"</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="permlab_readPhoneState" msgid="9178228524507610486">"የስልክ ሁኔታና ማንነት አንብብ"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"የብሉቱዝ ቅንብሮችን ድረስባቸው"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"የአካባቢውን ብሉቱዝ ጡባዊ ለማዋቀር እና አግኝቶ ከሩቅ መሣሪያዎች ጋር ለማጣመር ለመተግበሪያው ይፈቅዳሉ።"</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"የአካባቢውን ብሉቱዝ ጡባዊ ለማዋቀር እና አግኝቶ ከሩቅ መሣሪያዎች ጋር ለማጣመር ለመተግበሪያው ይፈቅዳሉ።"</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"የWiMAX ግኑኝነቶችን እይ"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"ከWiMAX ጋር ይገናኙ እና ያላቅቁ"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"መተግበሪያው WiMAX እንደነቃ እና ስለማናቸውም የተገናኙ የWiMAX አውታረ መረቦች መረጃ እንዲወስን ይፈቅድለታል።"</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"የWiMAX ሁኔታ ለውጥ"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"መተግበሪያው ጡባዊ ተኮውን ከWiMAX አውታረ መረብ ጋር እንዲያገናኝና እንዲያለያይ ይፈቅድለታል።"</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"በአሁኑ ጊዜ  የተመሳሰሉ ምግቦችን ለመቀየር ለመተግበሪያው ይፈቅዳሉ፡፡ የተመሳሰሉ ምግቦችህን ተንኮል አዘል መተግበሪያዎች ሊለውጡ ይችላሉ፡፡"</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"መዝገበ ቃላቱ ላይ ያከልካቸውን ቃላት አንብብ"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"መተግበሪያው ተጠቃሚው በተጠቃሚው መዝገበ-ቃላት አከማችቷቸው ሊሆኑ የሚችሉ ሁሉንም ቃላት፣ ስሞችና ሐረጋት እንዲያነባቸው ይፈቅድለታል።"</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"በተጠቃሚ በተወሰነ መዝገበ ቃላት ፃፍ"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"በተጠቃሚ በተገለጸ መዝገበ ቃላት ላይ ቃላትን ያክላል"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"በተጠቃሚ መዝገበ ቃላት ውስጥ አዲስ ቃል እንዲጽፍ ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"ጥበቃ ወደሚደረግለት ማከማቻ ያለ መዳረሻን ፈትሽ"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"ጥበቃ ወደሚደረግለት ማከማቻ ያለ መዳረሻን ፈትሽ"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"መተግበሪያው በወደፊት መሳሪዎች ላይ ለሚኖር የUSB ማህደረ ትውስታ ፈቃድ እንዲሞክር ይፈቅድለታል።"</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"መተግበሪያው በወደፊት መሳሪዎች ላይ ለሚኖር የUSB ማህደረ ትውስታ ፈቃድ እንዲሞክር ይፈቅድለታል።"</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"መተግበሪያው በወደፊት መሳሪዎች ላይ ለሚኖረው SD ካርድ ፈቃድ እንዲሞክር ይፈቅድለታል።"</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"የUSB ማከማቻህን ይዘቶች ቀይር ወይም ሰርዝ"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"የSD ካርድህን ይዘቶች ቀይር ወይም ሰርዝ"</string>
@@ -534,6 +593,8 @@
     <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="permlab_sdcardAccessAll" msgid="8150613823900460576">"የሁሉም ተጠቃሚዎች ውጫዊ ማከማቻውን ይደርስበታል"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"መተግበሪያውን የሁሉም ተጠቃሚዎች ውጫዊ ማከማቻውን እንዲደርስ ይፈቅድለታል።"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"የመሸጎጫ ስርዓተ ፋይል ድረስ"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"መሸጎጫ ስርዓተ ፋይል ለማንበብ እና ለመፃፍ ለመተግበሪያው ይፈቅዳሉ።"</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"የበይነ መረብ ጥሪዎች አድርግ/ተቀበል"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"የተከማቸ ትግበራ ውሂብ የተመሰጠረ እንዲሆን ጠይቅ።"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"ካሜራዎችን አቦዝን"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"የሁሉንም መሣሪያ ካሜራዎች መጠቀም ከልክል።"</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"በቁልፍ ጠባቂ ውስጥ ባህሪያትን ያሰናክሉ"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"በቁልፍ ጠባቂ ውስጥ የአንዳንድ ባህሪያትን መጠቀም ያግዱ።"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"መነሻ"</item>
     <item msgid="869923650527136615">"ተንቀሳቃሽ"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"እንደገና ሞክር"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"የመጨረሻውን  የገጽ ክፈት ሙከራዎችን አልፏል"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"ኃይል በመሙላት ላይ፣ <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"ኃይል ሞልቷል።"</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"ባትሪ ሞልቷል።"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"ኃይል መሙያዎን ያያይዙ"</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"ምንም SIM ካርድ የለም"</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"ምንም ሲም ካርድ የለም"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"በጡባዊ ውስጥ ምንም SIM ካርድ የለም።"</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"በስልክ ውስጥ ምንም SIM ካርድ የለም።"</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"ሲም ካርድ አስገባ፡፡"</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"ንድፍ ጸድቷል"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"ሕዋስ ታክሏል"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"ንድፍ ተጠናቋል"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"ንዑስ ፕሮግራም አክል"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"ባዶ"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"የመክፈቻ አካባቢ ተስፋፍቷል።"</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"የመክፈቻ አካባቢ ተሰብስቧል።"</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"የ<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> ንዑስ ፕሮግራም።"</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"ተጠቃሚ መራጭ"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"ሁኔታ"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"ካሜራ"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"የሚዲያ መቆጣጠሪያዎች"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"የንዑስ ፕሮግራም ዳግም መደርደር ተጀምሯል።"</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"የንዑስ ፕሮግራም ዳግም መደርደር አብቅቷል።"</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"ንዑስ ፕሮግራም <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> ተሰርዟል።"</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"የመክፈቻ አካባቢውን አስፋፋ።"</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"በማንሸራተት ክፈት።"</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"በስርዓተ-ጥለት መክፈት።"</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"በፊት መክፈት።"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"በፒን መክፈት።"</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"በይለፍ ቃል መክፈት።"</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"የስርዓተ-ጥለት አካባቢ።"</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"የማንሸራተቻ አካባቢ።"</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"የURL ቅጂ"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"ፅሁፍ ምረጥ"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"የፅሁፍ ምርጫ"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"ወደ መዝገበ ቃላት አክል"</string>
-    <string name="deleteText" msgid="7070985395199629156">"ሰርዝ"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"ወደ መዝገበ ቃላት አክል"</string>
+    <string name="deleteText" msgid="6979668428458199034">"ሰርዝ"</string>
     <string name="inputMethod" msgid="1653630062304567879">"ግቤት ሜተድ"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"የፅሁፍ እርምጃዎች"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"የማከማቻ ቦታ እያለቀ ነው"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"አውታረ መረቦች ሲኖሩ Wi-Fi ክፈት"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"ወደ Wi-Fi አውታረ መረብ በመለያ ግባ"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"ወደ አውታረ መረብ ይግቡ"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ወደ Wi-Fi ለማያያዝ አልተቻለም"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ደካማ የበይነመረብ ግንኙነት ኣለው።"</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"ለ፦"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"የሚፈለገውን ፒን ተይብ፦"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"ፒን፦"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"ስልኩ ከ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ጋር ተገናኝቶ ባለበት ጊዜ በጊዜያዊነት ከWi-Fi ጋር ያለው ግንኙነት ይቋረጣል"</string>
     <string name="select_character" msgid="3365550120617701745">"ቁምፊ አስገባ"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"የSMS መልዕክቶች መበላክ ላይ"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ቁጥራቸው ብዙ የሆኑ የኤስ.ኤም.ኤስ. መልዕክቶችን እየላከ ነው። ይሄ መተግበሪያ መልዕክቶችን መላኩን እንዲቀጥል መፍቀድ ትፈልጋለህ?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"ፍቀድ"</string>
     <string name="sms_control_no" msgid="625438561395534982">"ከልክል"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ለ&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; መልዕክት ለመላክ ይፈልጋል።"</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"ይሄ በተንቀሳቃሽ ስልክ መለያዎ ላይ "<font fgcolor="#ffffb060">"ክፍያዎችን ሊያስከትል ይችላል"</font>"።"</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"ይሄ በተንቀሳቃሽ ስልክ መለያዎ ላይ ክፍያዎችን ያስከትላል።"</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"ላክ"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"ሰርዝ"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"ምርጫዬን አስታውስ"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"ይሄንን በኋላ ላይ በቅንብሮች &gt; መተግበሪያዎች ውስጥ ሊቀይሩት ይችላሉ"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"ሁልጊዜ ፍቀድ"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"በጭራሽ አትፍቀድ"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM ካርድ ተወግዷል"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"በትክክል የገባ SIM ካርድ ድጋሚ እስኪያስጀምሩ የተንቀሳቃሽ ስልክ አውታረመረብ አይገኝም።"</string>
     <string name="sim_done_button" msgid="827949989369963775">"ተከናውኗል"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"ውሂብ አዘጋጅ"</string>
     <string name="date_time_set" msgid="5777075614321087758">"አዘጋጅ"</string>
     <string name="date_time_done" msgid="2507683751759308828">"ተጠናቋል"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"ነባሪ"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"ምንም ፍቃዶች አይጠየቁም"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"ደብቅ "</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"ሁሉንም አሳይ"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"አዲስ፦ "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"አዲስ፦ "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"በ<xliff:g id="APP_NAME">%1$s</xliff:g> የቀረበ።"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"ምንም ፍቃዶች አይጠየቁም"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"ይህ ገንዘብ ሊያስወጣዎብዎት ይችላል"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB ብዙ ማከማቻ"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB ተያይዟል"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"ከኮምፒዩተርህ ጋር በUSB በኩል አገናኝተሃል። በኮምፒዩተርህ እና በAndroid SD ማከማቻህ መካከል ፋይሎች ለመቅዳት ከፈለግህ ከዚህ በታች ያለውን አዝራር ንካ።"</string>
@@ -1139,7 +1231,7 @@
     <string name="permission_request_notification_title" msgid="6486759795926237907">"ፈቃድ ተጠይቋል"</string>
     <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">\n" ለ<xliff:g id="ACCOUNT">%s</xliff:g> መለያ ፈቃድ ተጠይቋል"</string>
     <string name="input_method_binding_label" msgid="1283557179944992649">"ግቤት ሜተድ"</string>
-    <string name="sync_binding_label" msgid="3687969138375092423">"አሳምር"</string>
+    <string name="sync_binding_label" msgid="3687969138375092423">"አስምር"</string>
     <string name="accessibility_binding_label" msgid="4148120742096474641">"ተደራሽነት"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ልጣፍ"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ልጣፍ ለውጥ"</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN በ<xliff:g id="APP">%s</xliff:g>ገብሯል"</string>
     <string name="vpn_text" msgid="3011306607126450322">"አውታረመረብ ለማደራጀት  ንካ።"</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"ለ<xliff:g id="SESSION">%s</xliff:g>የተገናኘ። አውታረመረቡን ለማደራጀት  ንካ።"</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ሁልጊዜ የበራ VPN በመገናኘት ላይ…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"ሁልጊዜ የበራ VPN ተገናኝቷል"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"ሁልጊዜ የበራ VPN ስህተት"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"ግንኙነት ዳግም ለማስጀመር ይንኩ"</string>
     <string name="upload_file" msgid="2897957172366730416">"ፋይል ምረጥ"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"ምንም ፋይል አልተመረጠም"</string>
     <string name="reset" msgid="2448168080964209908">"ዳግም አስጀምር"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"አጋራ"</string>
     <string name="find" msgid="4808270900322985960">"አግኝ"</string>
     <string name="websearch" msgid="4337157977400211589">"ድረ ፍለጋ"</string>
+    <string name="find_next" msgid="5742124618942193978">"ቀጣዩን አግኝ"</string>
+    <string name="find_previous" msgid="2196723669388360506">"ቀዳሚውን አግኝ"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"የስፍራ ጥየቃ ቅፅ<xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"የስፍራ ጥየቃ"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">" በ፡<xliff:g id="NAME">%1$s</xliff:g>(<xliff:g id="SERVICE">%2$s</xliff:g>) ተጠየቀ"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ስልክ"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"የጆሮ ማዳመጫዎች"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"የትከል ድምፅ ማጉያዎች"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI ድምጽ"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"ስርዓት"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"የብሉቱዝ ድምጽ"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"ተከናውኗል"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"የሚዲያ ውጽዓት"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"በመቃኘት ላይ..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"በማገናኘት ላይ..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"የሚገኙ"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"አይገኝም"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"ውስጥ የተሰራ ማያ ገጽ"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI ማያ ገጽ"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"ተደራቢ #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>፦ <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>፣ <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"ገመድ አልባ ማሳያ ተገናኝቷል"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"ይህ ማያ ገጽ በሌላ መሣሪያ ላይ እያሳየ ነው"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"ግንኙነት አቋርጥ"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"የአደጋ ጊዜ ጥሪ"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"ስርዓተ ጥለቱን እርሳ"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"የተሳሳተ ስርዓተ ጥለት"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"የተሳሳተ ይለፍ ቃል"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"የተሳሳተ ፒን"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"በ<xliff:g id="NUMBER">%d</xliff:g> ሰከንዶች ውስጥ እንደገና ይሞክሩ።"</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"ስርዓተ ጥለትዎን ይሳሉ"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"የሲም ፒን ያስገቡ"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"ፒን ያስገቡ"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"የይለፍ ቃል ያስገቡ"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"ሲም አሁን ተሰናክሏል። ለመቀጠል የPUK ኮድ ያስገቡ። ለዝርዝር ድምጸ ተያያዥ ሞደምን ያግኙ።"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"የተፈለገውን የፒን ኮድ ያስገቡ"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"የተፈለገውን የፒን ኮድ ያረጋግጡ"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"ሲም ካርዱን በመክፈት ላይ…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"ትክክል ያልሆነ ፒን ኮድ።"</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"ከ4 እስከ 8 ቁጥሮች የያዘ ፒን ይተይቡ።"</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"የPUK ኮድ 8 ወይም ከዚያ በላይ ቁጥሮች ሊኖረው ይገባል።"</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"ትክክለኛውን የPUK ኮድ እንደገና ያስገቡ። ተደጋጋሚ ሙከራዎች ሲም ካርዱን እስከመጨረሻው ያሰናክሉታል።"</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"ፒን ኮዶች አይገጣጠሙም"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"በጣም ብዙ የስርዓተ ጥለት ሙከራዎች"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"ለመክፈት በGoogle መለያዎ ይግቡ።"</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"የተጠቃሚ ስም (ኢሜይል)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"የይለፍ ቃል"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"ግባ"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"ልክ ያልሆነ የተጠቃሚ ስም ወይም የይለፍ ቃል።"</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"የተጠቃሚ ስምዎን ወይም የይለፍ ቃልዎን ረሱት?"\n<b>"google.com/accounts/recovery"</b>"ይጎብኙ።"</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"መለያውን በማረጋገጥ ላይ…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"ፒንዎን <xliff:g id="NUMBER_0">%d</xliff:g> ጊዜ በትክክል አልተየቡም። "\n\n"በ<xliff:g id="NUMBER_1">%d</xliff:g> ሰኮንዶች ውስጥ እንደገና ይሞክሩ።"</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"የይለፍ ቃልዎን <xliff:g id="NUMBER_0">%d</xliff:g> ጊዜ ትክክል ባልሆነ መንገድ ተይበዋል።"\n\n"በ<xliff:g id="NUMBER_1">%d</xliff:g> ሰኮንዶች ውስጥ እንደገና ይሞክሩ።"</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"የመክፈቻ ስርዓተ ጥለትዎን <xliff:g id="NUMBER_0">%d</xliff:g> ጊዜ በትክክል አልሳሉትም። "\n\n" ከ<xliff:g id="NUMBER_1">%d</xliff:g> ሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"ጡባዊ ቱኮውን <xliff:g id="NUMBER_0">%d</xliff:g> ጊዜ ትክክል ባልሆነ መንገድ ለመክፈት ሞክረዋል። ከ<xliff:g id="NUMBER_1">%d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ ጡባዊ ቱኮው በፋብሪካ ነባሪ ቅንብር ዳግም ይጀመርና ሁሉም የተጠቃሚ ውሂብ ይጠፋል።"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"ስልኩን <xliff:g id="NUMBER_0">%d</xliff:g> ጊዜ ትክክል ባልሆነ መንገድ ለመክፈት ሞክረዋል። ከ<xliff:g id="NUMBER_1">%d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ ስልኩ በፋብሪካ ነባሪ ቅንብር ዳግም ይጀመርና ሁሉም የተጠቃሚ ውሂብ ይጠፋል።"</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"ጡባዊ ቱኮዎን <xliff:g id="NUMBER">%d</xliff:g> ጊዜ ትክክል ባልሆነ መንገድ ለመክፈት ሞክረዋል። ጡባዊ ቱኮዎ አሁን በፋብሪካ ነባሪ ቅንብር ዳግም ይጀመራል።"</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"ስልኩን <xliff:g id="NUMBER">%d</xliff:g> ጊዜ ትክክል ባልሆነ መንገድ ለመክፈት ሞክረዋል። ስልኩ አሁን በፋብሪካ ነባሪ ቅንብር ዳግም ይጀመራል።"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%d</xliff:g> ጊዜ በትክክል አልሳሉትም። ከ<xliff:g id="NUMBER_1">%d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የኢሜይል መለያ ተጠቅመው ጡባዊ ቱኮዎን እንዲከፍቱ ይጠየቃሉ።"\n\n" ከ<xliff:g id="NUMBER_2">%d</xliff:g> ከሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%d</xliff:g> ጊዜ በትክክል አልሳሉትም። ከ<xliff:g id="NUMBER_1">%d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የኢሜይል መለያ ተጠቅመው ስልክዎን እንዲከፍቱ ይጠየቃሉ።"\n\n"እባክዎ ከ<xliff:g id="NUMBER_2">%d</xliff:g> ሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"አስወግድ"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"ድምጽ አደጋ ከሌለው መጠን በላይ ይጨመር??"\n"ለረጅም ጊዜ በከፍተኛ ድምጽ መስማት የመስማት ችሎታዎን ሊጎዳይ ይችላል።"</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"ተደራሽነትን ለማንቃት ሁለት ጣቶችዎን ባሉበት ያቆዩዋቸው።"</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"ተደራሽነት ነቅቷል።"</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"ተደራሽነት ተሰርዟል።"</string>
+    <string name="user_switched" msgid="3768006783166984410">"የአሁኑ ተጠቃሚ <xliff:g id="NAME">%1$s</xliff:g>።"</string>
+    <string name="owner_name" msgid="2716755460376028154">"ባለቤት"</string>
 </resources>
diff --git a/core/res/res/values-ar-rEG/donottranslate-cldr.xml b/core/res/res/values-ar-rEG/donottranslate-cldr.xml
index 57011d7..155480d 100644
--- a/core/res/res/values-ar-rEG/donottranslate-cldr.xml
+++ b/core/res/res/values-ar-rEG/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">يناير</string>
-    <string name="month_long_standalone_february">فبراير</string>
-    <string name="month_long_standalone_march">مارس</string>
-    <string name="month_long_standalone_april">أبريل</string>
-    <string name="month_long_standalone_may">مايو</string>
-    <string name="month_long_standalone_june">يونيو</string>
-    <string name="month_long_standalone_july">يوليو</string>
-    <string name="month_long_standalone_august">أغسطس</string>
-    <string name="month_long_standalone_september">سبتمبر</string>
-    <string name="month_long_standalone_october">أكتوبر</string>
-    <string name="month_long_standalone_november">نوفمبر</string>
-    <string name="month_long_standalone_december">ديسمبر</string>
-
-    <string name="month_long_january">يناير</string>
-    <string name="month_long_february">فبراير</string>
-    <string name="month_long_march">مارس</string>
-    <string name="month_long_april">أبريل</string>
-    <string name="month_long_may">مايو</string>
-    <string name="month_long_june">يونيو</string>
-    <string name="month_long_july">يوليو</string>
-    <string name="month_long_august">أغسطس</string>
-    <string name="month_long_september">سبتمبر</string>
-    <string name="month_long_october">أكتوبر</string>
-    <string name="month_long_november">نوفمبر</string>
-    <string name="month_long_december">ديسمبر</string>
-
-    <string name="month_medium_january">يناير</string>
-    <string name="month_medium_february">فبراير</string>
-    <string name="month_medium_march">مارس</string>
-    <string name="month_medium_april">أبريل</string>
-    <string name="month_medium_may">مايو</string>
-    <string name="month_medium_june">يونيو</string>
-    <string name="month_medium_july">يوليو</string>
-    <string name="month_medium_august">أغسطس</string>
-    <string name="month_medium_september">سبتمبر</string>
-    <string name="month_medium_october">أكتوبر</string>
-    <string name="month_medium_november">نوفمبر</string>
-    <string name="month_medium_december">ديسمبر</string>
-
-    <string name="month_shortest_january">ي</string>
-    <string name="month_shortest_february">ف</string>
-    <string name="month_shortest_march">م</string>
-    <string name="month_shortest_april">أ</string>
-    <string name="month_shortest_may">و</string>
-    <string name="month_shortest_june">ن</string>
-    <string name="month_shortest_july">ل</string>
-    <string name="month_shortest_august">غ</string>
-    <string name="month_shortest_september">س</string>
-    <string name="month_shortest_october">ك</string>
-    <string name="month_shortest_november">ب</string>
-    <string name="month_shortest_december">د</string>
-
-    <string name="day_of_week_long_sunday">الأحد</string>
-    <string name="day_of_week_long_monday">الإثنين</string>
-    <string name="day_of_week_long_tuesday">الثلاثاء</string>
-    <string name="day_of_week_long_wednesday">الأربعاء</string>
-    <string name="day_of_week_long_thursday">الخميس</string>
-    <string name="day_of_week_long_friday">الجمعة</string>
-    <string name="day_of_week_long_saturday">السبت</string>
-
-    <string name="day_of_week_medium_sunday">أحد</string>
-    <string name="day_of_week_medium_monday">إثنين</string>
-    <string name="day_of_week_medium_tuesday">ثلاثاء</string>
-    <string name="day_of_week_medium_wednesday">أربعاء</string>
-    <string name="day_of_week_medium_thursday">خميس</string>
-    <string name="day_of_week_medium_friday">جمعة</string>
-    <string name="day_of_week_medium_saturday">سبت</string>
-
-    <string name="day_of_week_short_sunday">أحد</string>
-    <string name="day_of_week_short_monday">إثنين</string>
-    <string name="day_of_week_short_tuesday">ثلاثاء</string>
-    <string name="day_of_week_short_wednesday">أربعاء</string>
-    <string name="day_of_week_short_thursday">خميس</string>
-    <string name="day_of_week_short_friday">جمعة</string>
-    <string name="day_of_week_short_saturday">سبت</string>
-
-    <string name="day_of_week_shortest_sunday">ح</string>
-    <string name="day_of_week_shortest_monday">ن</string>
-    <string name="day_of_week_shortest_tuesday">ث</string>
-    <string name="day_of_week_shortest_wednesday">ر</string>
-    <string name="day_of_week_shortest_thursday">خ</string>
-    <string name="day_of_week_shortest_friday">ج</string>
-    <string name="day_of_week_shortest_saturday">س</string>
-
-    <string name="am">ص</string>
-    <string name="pm">م</string>
-    <string name="yesterday">أمس</string>
-    <string name="today">اليوم</string>
-    <string name="tomorrow">غدًا</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
diff --git a/core/res/res/values-ar/donottranslate-cldr.xml b/core/res/res/values-ar/donottranslate-cldr.xml
index 0b9da23..135963b 100644
--- a/core/res/res/values-ar/donottranslate-cldr.xml
+++ b/core/res/res/values-ar/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">يناير</string>
-    <string name="month_long_standalone_february">فبراير</string>
-    <string name="month_long_standalone_march">مارس</string>
-    <string name="month_long_standalone_april">أبريل</string>
-    <string name="month_long_standalone_may">مايو</string>
-    <string name="month_long_standalone_june">يونيو</string>
-    <string name="month_long_standalone_july">يوليو</string>
-    <string name="month_long_standalone_august">أغسطس</string>
-    <string name="month_long_standalone_september">سبتمبر</string>
-    <string name="month_long_standalone_october">أكتوبر</string>
-    <string name="month_long_standalone_november">نوفمبر</string>
-    <string name="month_long_standalone_december">ديسمبر</string>
-
-    <string name="month_long_january">يناير</string>
-    <string name="month_long_february">فبراير</string>
-    <string name="month_long_march">مارس</string>
-    <string name="month_long_april">أبريل</string>
-    <string name="month_long_may">مايو</string>
-    <string name="month_long_june">يونيو</string>
-    <string name="month_long_july">يوليو</string>
-    <string name="month_long_august">أغسطس</string>
-    <string name="month_long_september">سبتمبر</string>
-    <string name="month_long_october">أكتوبر</string>
-    <string name="month_long_november">نوفمبر</string>
-    <string name="month_long_december">ديسمبر</string>
-
-    <string name="month_medium_january">يناير</string>
-    <string name="month_medium_february">فبراير</string>
-    <string name="month_medium_march">مارس</string>
-    <string name="month_medium_april">أبريل</string>
-    <string name="month_medium_may">مايو</string>
-    <string name="month_medium_june">يونيو</string>
-    <string name="month_medium_july">يوليو</string>
-    <string name="month_medium_august">أغسطس</string>
-    <string name="month_medium_september">سبتمبر</string>
-    <string name="month_medium_october">أكتوبر</string>
-    <string name="month_medium_november">نوفمبر</string>
-    <string name="month_medium_december">ديسمبر</string>
-
-    <string name="month_shortest_january">ي</string>
-    <string name="month_shortest_february">ف</string>
-    <string name="month_shortest_march">م</string>
-    <string name="month_shortest_april">أ</string>
-    <string name="month_shortest_may">و</string>
-    <string name="month_shortest_june">ن</string>
-    <string name="month_shortest_july">ل</string>
-    <string name="month_shortest_august">غ</string>
-    <string name="month_shortest_september">س</string>
-    <string name="month_shortest_october">ك</string>
-    <string name="month_shortest_november">ب</string>
-    <string name="month_shortest_december">د</string>
-
-    <string name="day_of_week_long_sunday">الأحد</string>
-    <string name="day_of_week_long_monday">الإثنين</string>
-    <string name="day_of_week_long_tuesday">الثلاثاء</string>
-    <string name="day_of_week_long_wednesday">الأربعاء</string>
-    <string name="day_of_week_long_thursday">الخميس</string>
-    <string name="day_of_week_long_friday">الجمعة</string>
-    <string name="day_of_week_long_saturday">السبت</string>
-
-    <string name="day_of_week_medium_sunday">أحد</string>
-    <string name="day_of_week_medium_monday">إثنين</string>
-    <string name="day_of_week_medium_tuesday">ثلاثاء</string>
-    <string name="day_of_week_medium_wednesday">أربعاء</string>
-    <string name="day_of_week_medium_thursday">خميس</string>
-    <string name="day_of_week_medium_friday">جمعة</string>
-    <string name="day_of_week_medium_saturday">سبت</string>
-
-    <string name="day_of_week_short_sunday">أحد</string>
-    <string name="day_of_week_short_monday">إثنين</string>
-    <string name="day_of_week_short_tuesday">ثلاثاء</string>
-    <string name="day_of_week_short_wednesday">أربعاء</string>
-    <string name="day_of_week_short_thursday">خميس</string>
-    <string name="day_of_week_short_friday">جمعة</string>
-    <string name="day_of_week_short_saturday">سبت</string>
-
-    <string name="day_of_week_shortest_sunday">ح</string>
-    <string name="day_of_week_shortest_monday">ن</string>
-    <string name="day_of_week_shortest_tuesday">ث</string>
-    <string name="day_of_week_shortest_wednesday">ر</string>
-    <string name="day_of_week_shortest_thursday">خ</string>
-    <string name="day_of_week_shortest_friday">ج</string>
-    <string name="day_of_week_shortest_saturday">س</string>
-
-    <string name="am">ص</string>
-    <string name="pm">م</string>
-    <string name="yesterday">أمس</string>
-    <string name="today">اليوم</string>
-    <string name="tomorrow">غدًا</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 7a9ad77..a7c0c50 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"غيغابايت"</string>
     <string name="terabyteShort" msgid="231613018159186962">"تيرابايت"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"بيتابايت"</string>
-    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;بلا عنوان&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"خيارات الهاتف"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"تأمين الشاشة"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"إيقاف التشغيل"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"تقرير الأخطاء"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"إعداد تقرير بالأخطاء"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"سيجمع هذا معلومات حول حالة جهازك الحالي لإرسالها كرسالة إلكترونية، ولكنه سيستغرق وقتًا قليلاً من بدء عرض تقرير بالأخطاء. وحتى يكون جاهزًا للإرسال، الرجاء الانتظار."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"وضع صامت"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"الصوت متوقف"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"الصوت قيد التشغيل"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"رسائلك"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"قراءة وكتابة الرسائل القصيرة SMS والرسائل الإلكترونية والرسائل الأخرى."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"معلوماتك الشخصية"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"الدخول المباشر إلى جهات اتصالك والتقويم المخزنين على الجهاز اللوحي."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"الدخول المباشر إلى التقويم وجهات الاتصال المخزّنة على الهاتف."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"الدخول المباشر إلى معلومات عنك، تم تخزينها في بطاقة الاتصال."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"المعلومات الاجتماعية"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"الدخول المباشر إلى معلومات عن جهات الاتصال والاتصالات الاجتماعية."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"موقعك"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"يمكنك مراقبة موقعك الفعلي."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"اتصال الشبكة"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"يمكنك الدخول إلى ميزات متعددة عبر الشبكة."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"بلوتوث"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"الدخول إلى الأجهزة والشبكات من خلال البلوتوث."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"إعدادات الصوت"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"تغيير إعدادات الصوت"</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"التأثير على البطارية"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"استخدم الميزات التي يمكن أن تؤدي إلى نفاد طاقة البطارية بسرعة."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"التقويم"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"الدخول المباشر إلى التقويم والأحداث."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"قراءة قاموس المستخدم"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"قراءة الكلمات في قاموس المستخدم."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"كتابة قاموس المستخدم"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"إضافة الكلمات إلى قاموس المستخدم."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"الإشارات المرجعية والسجل"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"الدخول المباشر إلى الإشارات المرجعية وسجل المتصفح."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"المنبه"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"تعيين المنبه."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"البريد الصوتي"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"الدخول المباشر إلى البريد الصوتي."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"الميكروفون"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"الدخول المباشر إلى الميكروفون لتسجيل الصوت."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"الكاميرا"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"الدخول المباشر إلى الكاميرا لالتقاط صورة أو تصوير مقطع فيديو."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"معلومات التطبيقات"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"القدرة على التأثير في سلوك التطبيقات الأخرى بجهازك."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"الخلفية"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"تغيير إعدادات خلفية الجهاز."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"الساعة"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"تغيير وقت الجهاز أو المنطقة الزمنية."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"شريط الحالة"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"تغيير إعدادات شريط حالة الجهاز."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"إعدادات المزامنة"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"الدخول إلى إعدادات المزامنة."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"حساباتك"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"الوصول إلى الحسابات المتاحة."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"عناصر التحكم بالأجهزة"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"دخول المستوى الأقل والتحكم بالنظام."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"أدوات التطوير"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"الميزات مطلوبة لمطوّري التطبيقات فقط."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"واجهة مستخدم تطبيقات أخرى"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"التأثير على واجهة المستخدم بالتطبيقات الأخرى."</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>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"للسماح للتطبيق بتلقي رسائل WAP ومعالجتها. ويتضمن هذا الإذن إمكانية مراقبة الرسائل التي يتم إرسالها إليك أو حذفها بدون عرضها لك."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"استرداد التطبيقات التي قيد التشغيل"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"للسماح للتطبيق باسترداد معلومات حول المهام التي يجري تشغيلها حاليًا والتي تم تشغيلها مؤخرًا. وقد يسمح هذا للتطبيق باكتشاف معلومات حول التطبيقات المستخدمة على الجهاز."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"التعامل بين المستخدمين"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"للسماح للتطبيق بتنفيذ إجراءات بين مستخدمين مختلفين على الجهاز. قد تستخدم التطبيقات الضارة ذلك لانتهاك الحماية بين المستخدمين."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"الترخيص بالكامل للتعامل بين المستخدمين"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"للسماح بجميع التعاملات المحتملة بين المستخدمين."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"إدارة المستخدمين"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"لتمكين التطبيقات من إدارة المستخدمين على الجهاز، بما في ذلك طلب البحث والإنشاء والحذف."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"استرداد تفاصيل التطبيقات قيد التشغيل"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"يسمح للتطبيق باسترداد معلومات تفصيلية حول المهام قيد التشغيل حاليًا ومؤخرًا. قد تكتشف التطبيقات الضارة معلومات خاصة حول التطبيقات الأخرى."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"إعادة ترتيب التطبيقات قيد التشغيل"</string>
@@ -243,6 +287,14 @@
     <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="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"تمكين إمكانية الدخول مؤقتًا"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"يتيح لتطبيق تمكين إمكانية الدخول مؤقتًا بالجهاز. قد تتيح التطبيقات الضارة تمكين إمكانية الدخول بدون موافقة المستخدم."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"استرداد معلومات النوافذ"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"للسماح لأحد التطبيقات باستعادة معلومات حول النوافذ من مدير النوافذ. يمكن أن تستعيد التطبيقات الضارة معلومات الغرض منها استخدام النظام الداخلي."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"تصفية الأحداث"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"للسماح لأحد التطبيقات بتسجيل فلتر إدخال يعمل على تصفية مجموعة البث من جميع أحداث المستخدمين قبل إرسالها. يمكن أن يتحكم برنامج ضار في واجهة المستخدم النظام دون تدخل المستخدم."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"تكبير الشاشة"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"للسماح للتطبيق بتكبير محتوى شاشة. قد تؤدي التطبيقات الضارة إلى نقل محتوى الشاشة بطريقة تعرض الجهاز في وضع غير قابل للاستخدام."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"إيقاف تشغيل جزئي"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"لوضع مدير الأنشطة في حالة إيقاف التشغيل. لا يتم تنفيذ إيقاف تشغيل كامل."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"منع التبديل بين التطبيقات"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"للسماح للتطبيق بالتحكم في الحد الأقصى لعدد العمليات التي سيتم تشغيلها. غير مطلوب على الإطلاق للتطبيقات العادية."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"فرض إغلاق تطبيقات الخلفية"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"للسماح للتطبيق بالتحكم في ما إذا كانت الأنشطة ستنتهي دائمًا عقب انتقالها إلى الخلفية. غير مطلوب على الإطلاق للتطبيقات العادية."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"تعديل إحصاءات البطارية"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"للسماح للتطبيق بتعديل إحصاءات البطارية المجمّعة. ليس للاستخدام بواسطة التطبيقات العادية."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"قراءة إحصاءات البطارية"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"للسماح لتطبيق بقراءة البيانات الحالية التي تستهلك مستوى منخفضًا من البطارية. قد يتيح التطبيق معرفة معلومات تفصيلية عن التطبيقات التي تستخدمها."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"تعديل إحصاءات البطارية"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"للسماح للتطبيق بتعديل إحصاءات البطارية المجمّعة. ليس للاستخدام بواسطة التطبيقات العادية."</string>
     <string name="permlab_backup" msgid="470013022865453920">"التحكم في النسخة الاحتياطية للنظام واستعادتها"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"للسماح للتطبيق بالتحكم في النسخة الاحتياطية للنظام وآلية الاستعادة. ليس للاستخدام بواسطة التطبيقات العادية."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"تأكيد إجراء عملية نسخ احتياطي أو استرداد كاملة"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"عرض النوافذ غير المصرح بها"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"للسماح للتطبيق بإنشاء نوافذ بقصد استخدامها بواسطة واجهة مستخدم النظام الداخلي. ليس للاستخدام بواسطة التطبيقات العادية."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"التغطية على تطبيقات أخرى"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"للسماح للتطبيق بعرض نوافذ تنبيه النظام. يمكن أن تستحوذ بعض نوافذ التنبيه على الشاشة بالكامل."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"للسماح بوضع التطبيق بالقرب أعلى التطبيقات الأخرى أو في أجزاء من واجهة المستخدم. وقد يتداخل مع استخدامك للواجهة في أي تطبيق أو قد يغير ما تعتقد أنك تراه في التطبيقات الأخرى."</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="permlab_freezeScreen" msgid="4708181184441880175">"تجميد الشاشة"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"للسماح للتطبيق بتجميد الشاشة مؤقتًا لإجراء انتقال بملء الشاشة."</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>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"تثبيت التطبيقات مباشرة"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"للسماح للتطبيق بتثبيت حزم Android الجديدة أو المحدّثة. يمكن أن تستخدم التطبيقات الضارة ذلك لإضافة تطبيقات جديدة ذات أذونات قوية على نحو عشوائي."</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="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"للسماح للتطبيق بتفريغ سعة تخزين الجهاز اللوحي من خلال حذف الملفات من أدلة ذاكرة التخزين المؤقت للتطبيقات الأخرى. قد يتسبب هذا في تشغيل التطبيقات الأخرى بشكل أكثر بطئًا حيث يلزمها إعادة استرداد بياناتها."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"للسماح للتطبيق بتفريغ مساحة تخزين الهاتف من خلال حذف الملفات من أدلة ذاكرة التخزين المؤقت للتطبيقات الأخرى. قد يتسبب هذا في تشغيل التطبيقات الأخرى بشكل أكثر بطئًا حيث يلزمها إعادة استرداد بياناتها."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"نقل موارد التطبيقات"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"للسماح للتطبيق بنقل موارد التطبيقات من الوسائط الداخلية إلى الوسائط الخارجية والعكس."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"قراءة بيانات السجل الحساسة"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"للسماح للتطبيق بالدخول إلى المزيد من أوامر موفر خدمة الموقع. وقد يتيح هذا للتطبيق التدخل في عمل GPS أو مصادر المواقع الأخرى."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"إذن لتثبيت موفر خدمة موقع"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"لإنشاء مصادر مواقع زائفة للاختبار أو تثبيت موفر مواقع جديد. يتيح هذا للتطبيق إلغاء الموقع و/أو الحالة التي تعرضها مصادر المواقع الأخرى مثل GPS أو موفري المواقع."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"موقع دقيق (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"للدخول إلى مصادر المواقع مثل نظام تحديد المواقع العالمي على الجهاز اللوحي. وعند توفر خدمات المواقع وتشغيلها، يتيح هذا الإذن للتطبيق تحديد الموقع تحديدًا دقيقًا."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"للدخول إلى مصادر المواقع الدقيقة مثل نظام تحديد المواقع العالمي على الهاتف. وعند توفر خدمات المواقع وتشغيلها، يتيح هذا الإذن للتطبيق تحديد الموقع تحديدًا دقيقًا."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"موقع تقريبي (يعتمد على الشبكة)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"للدخول إلى الموقع التقريبي من موفري المواقع باستخدام مصادر الشبكة مثل برج الهاتف الخلوي وWi-Fi. وعند توفر خدمات المواقع هذه وتشغيلها، يتيح هذا الإذن للتطبيق تحديد الموقع التقريبي."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"الموقع الدقيق (مستند إلى نظام تحديد المواقع العالمي والشبكة)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"للسماح للتطبيق بتحديد موقعك بدقة وهذا باستخدام نظام تحديد المواقع العالمي (GPS) أو مصادر المواقع التي تستخدم الشبكات مثل أبراج الجوال أو تقنية Wi-Fi. يتعين توفر خدمات المواقع هذه وتشغيلها على جهازك للتطبيق كي يستخدمها. وقد تستخدم التطبيقات هذا لتحديد موقعك وقد تستهلك مزيدًا من طاقة البطارية."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"الموقع التقريبي (مستند إلى الشبكة)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"للسماح للتطبيق بتحديد موقعك التقريبي الذي يستمد من خدمات الموقع باستخدام مصادر المواقع التي تستخدم الشبكات مثل أبراج الجوال وتقنية Wi-Fi. يتعين توفر خدمات المواقع هذه وتشغيلها على جهازك للتطبيق كي يستخدمها. وقد تستخدم التطبيقات هذا لتحديد موقعك التقريبي."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"الدخول إلى 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="permlab_configureWifiDisplay" msgid="5595661694746742168">"تهيئة شاشات Wifi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"للسماح للتطبيق بتهيئة شاشات Wifi والاتصال بها."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"التحكم في شاشات Wifi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"للسماح للتطبيق بالتحكم في الميزات ذات المستوى المنخفض في شاشات Wifi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"تغيير إعداداتك الصوتية"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"للسماح للتطبيق بتعديل إعدادات الصوت العامة مثل مستوى الصوت وأي السماعات يتم استخدامها للاستماع."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"تسجيل الصوت"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"الدخول إلى إعدادات بلوتوث"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"للسماح للتطبيق بتهيئة لوحة البلوتوث المحلي، واكتشاف أجهزة التحكم عن بعد والاقتران بها."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"للسماح للتطبيق بتهيئة هاتف البلوتوث المحلي، واكتشاف أجهزة التحكم عن بعد والاقتران بها."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"عرض اتصالات WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"الاتصال بـشبكة WiMAX وقطع الاتصال بها"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"للسماح للتطبيق بتحديد ما إذا تم تمكين WiMAX وتحديد معلومات حول أية شبكات WiMAX متصلة."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"تغيير حالة WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"للسماح للتطبيق بتوصيل الجهاز اللوحي بشبكات WiMAX وقطع اتصاله بها."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"للسماح للتطبيق بتعديل خلاصاتك المتزامنة في الوقت الحالي. قد تغيّر التطبيقات الضارة خلاصاتك المتزامنة."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"قراءة المصطلحات التي أضفتها إلى القاموس"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"للسماح للتطبيق بقراءة جميع الكلمات والأسماء والعبارات التي ربما يكون المستخدم قد خزنها في قاموس المستخدم."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"كتابة إلى القاموس المعرّف بواسطة المستخدم"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"إضافة كلمات إلى القاموس المعرّف بواسطة المستخدم"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"للسماح للتطبيق بكتابة كلمات جديدة في قاموس المستخدم."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"اختبار إمكانية الدخول إلى وحدة تخزين محمية"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"اختبار إمكانية الدخول إلى وحدة تخزين محمية"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"للسماح للتطبيق باختبار إذن لوحدة تخزين USB سيتم توفيرها على أجهزة مستقبلية."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"للسماح للتطبيق باختبار إذن لوحدة تخزين USB التي ستتوفر على أجهزة مستقبلية."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"للسماح للتطبيق باختبار إذن لبطاقة SD سيتم توفيرها على أجهزة مستقبلية."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"تعديل محتويات وحدة تخزين USB أو حذفها"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"تعديل محتويات بطاقة SD أو حذفها"</string>
@@ -534,6 +593,8 @@
     <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="permlab_sdcardAccessAll" msgid="8150613823900460576">"الوصول إلى سعة التخزين الخارجية لجميع المستخدمين"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"للسماح للتطبيق بالدخول إلى سعة التخزين الخارجية لجميع المستخدمين."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"الدخول إلى نظام ملفات ذاكرة التخزين المؤقت"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"للسماح للتطبيق بقراءة نظام ملفات ذاكرة التخزين المؤقت والكتابة به."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"إجراء/تلقي مكالمات عبر الإنترنت"</string>
@@ -564,8 +625,10 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"يمكنك طلب تشفير بيانات التطبيق المخزنة."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"تعطيل الكاميرات"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"يمكنك منح استخدام جميع كاميرات الجهاز."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"تعطيل الميزات في وضع حماية المفاتيح"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"يمكنك منع استخدام بعض الميزات في وضع حماية المفاتيح."</string>
   <string-array name="phoneTypes">
-    <item msgid="8901098336658710359">"الرئيسية"</item>
+    <item msgid="8901098336658710359">"المنزل"</item>
     <item msgid="869923650527136615">"الجوال"</item>
     <item msgid="7897544654242874543">"عمل"</item>
     <item msgid="1103601433382158155">"فاكس العمل"</item>
@@ -575,19 +638,19 @@
     <item msgid="9192514806975898961">"مخصص"</item>
   </string-array>
   <string-array name="emailAddressTypes">
-    <item msgid="8073994352956129127">"الرئيسية"</item>
+    <item msgid="8073994352956129127">"المنزل"</item>
     <item msgid="7084237356602625604">"عمل"</item>
     <item msgid="1112044410659011023">"آخر"</item>
     <item msgid="2374913952870110618">"مخصص"</item>
   </string-array>
   <string-array name="postalAddressTypes">
-    <item msgid="6880257626740047286">"الرئيسية"</item>
+    <item msgid="6880257626740047286">"المنزل"</item>
     <item msgid="5629153956045109251">"عمل"</item>
     <item msgid="4966604264500343469">"آخر"</item>
     <item msgid="4932682847595299369">"مخصص"</item>
   </string-array>
   <string-array name="imAddressTypes">
-    <item msgid="1738585194601476694">"الرئيسية"</item>
+    <item msgid="1738585194601476694">"المنزل"</item>
     <item msgid="1359644565647383708">"عمل"</item>
     <item msgid="7868549401053615677">"آخر"</item>
     <item msgid="3145118944639869809">"مخصص"</item>
@@ -608,7 +671,7 @@
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
     <string name="phoneTypeCustom" msgid="1644738059053355820">"مخصص"</string>
-    <string name="phoneTypeHome" msgid="2570923463033985887">"الرئيسية"</string>
+    <string name="phoneTypeHome" msgid="2570923463033985887">"المنزل"</string>
     <string name="phoneTypeMobile" msgid="6501463557754751037">"الجوال"</string>
     <string name="phoneTypeWork" msgid="8863939667059911633">"عمل"</string>
     <string name="phoneTypeFaxWork" msgid="3517792160008890912">"فاكس العمل"</string>
@@ -633,16 +696,16 @@
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"الذكرى السنوية"</string>
     <string name="eventTypeOther" msgid="7388178939010143077">"غير ذلك"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"مخصص"</string>
-    <string name="emailTypeHome" msgid="449227236140433919">"الرئيسية"</string>
+    <string name="emailTypeHome" msgid="449227236140433919">"المنزل"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"عمل"</string>
     <string name="emailTypeOther" msgid="2923008695272639549">"آخر"</string>
     <string name="emailTypeMobile" msgid="119919005321166205">"الجوال"</string>
     <string name="postalTypeCustom" msgid="8903206903060479902">"مخصص"</string>
-    <string name="postalTypeHome" msgid="8165756977184483097">"الرئيسية"</string>
+    <string name="postalTypeHome" msgid="8165756977184483097">"المنزل"</string>
     <string name="postalTypeWork" msgid="5268172772387694495">"عمل"</string>
     <string name="postalTypeOther" msgid="2726111966623584341">"آخر"</string>
     <string name="imTypeCustom" msgid="2074028755527826046">"مخصص"</string>
-    <string name="imTypeHome" msgid="6241181032954263892">"الرئيسية"</string>
+    <string name="imTypeHome" msgid="6241181032954263892">"المنزل"</string>
     <string name="imTypeWork" msgid="1371489290242433090">"عمل"</string>
     <string name="imTypeOther" msgid="5377007495735915478">"آخر"</string>
     <string name="imProtocolCustom" msgid="6919453836618749992">"مخصص"</string>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"أعد المحاولة"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"تم تجاوز الحد الأقصى لعدد محاولات تأمين الجهاز بالوجه"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"جارٍ الشحن، <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"تم الشحن."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"تم الشحن"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"توصيل جهاز الشحن."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"ليس هناك بطاقة SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"ليست هناك بطاقة SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ليس هناك بطاقة SIM في الجهاز اللوحي."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ليس هناك بطاقة SIM في الهاتف."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"أدخل بطاقة SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"تم محو النمط"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"تمت إضافة الخلية"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"اكتمل النمط"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"إضافة أداة."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"فارغة"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"تم توسيع منطقة إلغاء القفل."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"تم تصغير منطقة إلغاء القفل."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"أداة <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"محدد المستخدم"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"الحالة"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"الكاميرا"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"أدوات التحكم في الوسائط"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"بدأت إعادة ترتيب الأدوات."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"انتهت إعادة ترتيب الأدوات."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"تم حذف أداة <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"توسيع منطقة إلغاء القفل."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"إلغاء القفل باستخدام التمرير."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"إلغاء القفل باستخدام النقش."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"تأمين الجهاز بالوجه."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"إلغاء القفل باستخدام رقم التعريف الشخصي."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"إلغاء القفل باستخدام كلمة المرور."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"منطقة النقش."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"منطقة التمرير."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ب ت ث"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"نسخ عنوان URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"تحديد نص"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"تحديد النص"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"إضافة إلى القاموس"</string>
-    <string name="deleteText" msgid="7070985395199629156">"حذف"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"إضافة إلى القاموس"</string>
+    <string name="deleteText" msgid="6979668428458199034">"حذف"</string>
     <string name="inputMethod" msgid="1653630062304567879">"طريقة الإرسال"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"إجراءات النص"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"مساحة التخزين منخفضة"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"هناك شبكات Wi-Fi مفتوحة متاحة"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"تسجيل الدخول إلى شبكة Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"تسجيل الدخول إلى الشبكة"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"تعذر الاتصال بـ Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" لديها اتصال إنترنت رديء."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"إلى:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"اكتب رقم التعريف الشخصي المطلوب:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"رقم التعريف الشخصي:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"سيتم قطع اتصال الهاتف مؤقتًا بشبكة Wi-Fi في الوقت الذي يكون فيه متصلاً بـ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"إدراج حرف"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"إرسال رسائل قصيرة SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; يرسل عددًا كبيرًا من الرسائل القصيرة SMS. هل تريد السماح لهذا التطبيق بالاستمرار في إرسال الرسائل؟"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"السماح"</string>
     <string name="sms_control_no" msgid="625438561395534982">"رفض"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"هناك رغبة من &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; في إرسال رسالة إلى &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"هذا "<font fgcolor="#ffffb060">"قد يؤدي إلى فرض رسوم"</font>" على حسابك على الجوال."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"سيؤدي هذا إلى فرض رسوم على حسابك على الجوال."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"إرسال"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"إلغاء"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"تذكر اختياري"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"يمكنك تغيير ذلك لاحقًا من إعدادات &gt; تطبيقات"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"السماح دومًا"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"عدم السماح مطلقًا"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"تمت إزالة بطاقة SIM"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"لن تكون شبكة الجوال متاحة حتى تتم إعادة التشغيل وإدخال بطاقة SIM صالحة."</string>
     <string name="sim_done_button" msgid="827949989369963775">"تم"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"تعيين التاريخ"</string>
     <string name="date_time_set" msgid="5777075614321087758">"تعيين"</string>
     <string name="date_time_done" msgid="2507683751759308828">"تم"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"افتراضي"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"لا أذونات مطلوبة"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"إخفاء"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"عرض الكل"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"جديد: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"جديد: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"يقدمه <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"لا أذونات مطلوبة"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"قد يكلفك هذا مالاً."</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"تخزين USB كبير السعة"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB متصل"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"لقد اتصلت بجهاز الكمبيوتر من خلال USB. المس الزر أدناه إذا كنت تريد نسخ الملفات بين جهاز الكمبيوتر ووحدة تخزين USB في Android."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"تم تنشيط VPN بواسطة <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"المس لإدارة الشبكة."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"تم الاتصال بـ <xliff:g id="SESSION">%s</xliff:g>. المس لإدارة الشبكة."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"جارٍ الاتصال بشبكة ظاهرية خاصة (VPN) دائمة التشغيل..."</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"تم الاتصال بشبكة ظاهرية خاصة (VPN) دائمة التشغيل"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"خطأ بشبكة ظاهرية خاصة (VPN) دائمة التشغيل"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"المس لإعادة تعيين الاتصال"</string>
     <string name="upload_file" msgid="2897957172366730416">"اختيار ملف"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"لم يتم اختيار أي ملف"</string>
     <string name="reset" msgid="2448168080964209908">"إعادة تعيين"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"مشاركة"</string>
     <string name="find" msgid="4808270900322985960">"بحث"</string>
     <string name="websearch" msgid="4337157977400211589">"بحث الويب"</string>
+    <string name="find_next" msgid="5742124618942193978">"بحث عن التطابق التالي"</string>
+    <string name="find_previous" msgid="2196723669388360506">"بحث عن التطابق السابق"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"طلب الموقع من <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"طلب الموقع"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"مطلوب من <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"الهاتف"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"سماعات رأس"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"مكبرات صوت للإرساء"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"صوت HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"النظام"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"صوت بلوتوث"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"تم"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"المنفذ الإعلامي"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"جارٍ الفحص..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"جارٍ الاتصال..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"متاح"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"غير متاح"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"شاشة مدمجة"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"شاشة HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"المركب #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>، <xliff:g id="DPI">%4$d</xliff:g> نقطة لكل بوصة"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"تم التوصيل بشاشة لاسلكية"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"يتم عرض هذه الشاشة على جهاز آخر"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"قطع الاتصال"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"الاتصال بالطوارئ"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"نسيت النقش"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"نقش خاطئ"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"كلمة مرور خاطئة"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"رقم تعريف شخصي خاطئ"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"حاول مرة أخرى خلال <xliff:g id="NUMBER">%d</xliff:g> ثانية."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"ارسم نقشك"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"أدخل رقم التعريف الشخصي لبطاقة SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"أدخل رقم التعريف الشخصي"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"أدخل كلمة المرور"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"بطاقة SIM معطلة الآن. أدخل رمز PUK للمتابعة. اتصل بمشغل شبكة الجوال للاطلاع على التفاصيل."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"إدخال رمز رقم التعريف الشخصي المراد"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"تأكيد رمز رقم التعريف الشخصي المراد"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"جارٍ إلغاء تأمين بطاقة SIM…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"رقم التعريف الشخصي غير صحيح."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"اكتب رقم التعريف الشخصي المكون من 4 إلى 8 أرقام."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"يجب أن يتضمن رمز PUK‏ 8 أرقام أو أكثر."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"أعد إدخال رمز PUK الصحيح. وستؤدي المحاولات المتكررة إلى تعطيل بطاقة SIM نهائيًا."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"لا يتطابق رمزا رقم التعريف الشخصي"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"محاولات النقش كثيرة جدًا"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"لإلغاء التأمين، سجّل الدخول بحسابك في Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"اسم المستخدم (البريد إلكتروني)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"كلمة المرور"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"تسجيل الدخول"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"اسم مستخدم غير صحيح أو كلمة مرور غير صالحة."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"هل نسيت اسم المستخدم أو كلمة المرور؟"\n"انتقل إلى "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"جارٍ فحص الحساب…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"لقد كتبت رقم التعريف الشخصي بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. "\n\n"أعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"لقد كتبت كلمة المرور بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. "\n\n"أعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"لقد رسمت نقش إلغاء التأمين بطريقة غير صحيحة <xliff:g id="NUMBER_0">%d</xliff:g> مرة. "\n\n"أعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"لقد حاولت إلغاء تأمين الجهاز اللوحي بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات غير الناجحة الأخرى، ستتم إعادة تعيين الجهاز اللوحي على الإعدادات الافتراضية للمصنع وسيتم فقد جميع بيانات المستخدم."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"لقد حاولت إلغاء تأمين الهاتف بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات غير الناجحة الأخرى، ستتم إعادة تعيين الهاتف على الإعدادات الافتراضية للمصنع وسيتم فقد جميع بيانات المستخدم."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"لقد حاولت إلغاء تأمين الجهاز اللوحي بشكل غير صحيح <xliff:g id="NUMBER">%d</xliff:g> مرة. سيتم الآن إعادة تعيين الجهاز اللوحي على الإعدادات الافتراضية للمصنع."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"لقد حاولت إلغاء تأمين الهاتف بشكل غير صحيح <xliff:g id="NUMBER">%d</xliff:g> مرة. سيتم الآن إعادة تعيين الهاتف على الإعدادات الافتراضية للمصنع."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"لقد رسمت نقش إلغاء التأمين بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات غير الناجحة الأخرى، ستطالَب بإلغاء تأمين الجهاز اللوحي باستخدام معلومات حساب بريد إلكتروني."\n\n" أعد المحاولة خلال <xliff:g id="NUMBER_2">%d</xliff:g> ثانية."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"لقد رسمت نقش إلغاء التأمين بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات غير الناجحة الأخرى، ستُطالب بإلغاء تأمين الهاتف باستخدام حساب بريد إلكتروني لإلغاء تأمين الهاتف."\n\n" أعد المحاولة خلال <xliff:g id="NUMBER_2">%d</xliff:g> ثانية."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"إزالة"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"هل تريد رفع مستوى الصوت فوق المستوى الآمن؟"\n"قد يضر سماع صوت عالٍ لفترات طويلة بسمعك."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"اضغط بإصبعين لأسفل مع الاستمرار لتمكين تسهيل الدخول."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"تم تمكين إمكانية الدخول."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"تم إلغاء تسهيل الدخول."</string>
+    <string name="user_switched" msgid="3768006783166984410">"المستخدم الحالي <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"المالك"</string>
 </resources>
diff --git a/core/res/res/values-be/donottranslate-cldr.xml b/core/res/res/values-be/donottranslate-cldr.xml
index 365e60d..a346c83 100644
--- a/core/res/res/values-be/donottranslate-cldr.xml
+++ b/core/res/res/values-be/donottranslate-cldr.xml
@@ -1,85 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_may">травень</string>
-
-    <string name="month_long_january">студзень</string>
-    <string name="month_long_february">люты</string>
-    <string name="month_long_march">сакавік</string>
-    <string name="month_long_april">красавік</string>
-    <string name="month_long_may">май</string>
-    <string name="month_long_june">чэрвень</string>
-    <string name="month_long_july">ліпень</string>
-    <string name="month_long_august">жнівень</string>
-    <string name="month_long_september">верасень</string>
-    <string name="month_long_october">кастрычнік</string>
-    <string name="month_long_november">лістапад</string>
-    <string name="month_long_december">снежань</string>
-
-    <string name="month_medium_january">сту</string>
-    <string name="month_medium_february">лют</string>
-    <string name="month_medium_march">сак</string>
-    <string name="month_medium_april">кра</string>
-    <string name="month_medium_may">май</string>
-    <string name="month_medium_june">чэр</string>
-    <string name="month_medium_july">ліп</string>
-    <string name="month_medium_august">жні</string>
-    <string name="month_medium_september">вер</string>
-    <string name="month_medium_october">кас</string>
-    <string name="month_medium_november">ліс</string>
-    <string name="month_medium_december">сне</string>
-
-    <string name="month_shortest_january">с</string>
-    <string name="month_shortest_february">л</string>
-    <string name="month_shortest_march">с</string>
-    <string name="month_shortest_april">к</string>
-    <string name="month_shortest_may">м</string>
-    <string name="month_shortest_june">ч</string>
-    <string name="month_shortest_july">л</string>
-    <string name="month_shortest_august">ж</string>
-    <string name="month_shortest_september">в</string>
-    <string name="month_shortest_october">к</string>
-    <string name="month_shortest_november">л</string>
-    <string name="month_shortest_december">с</string>
-
-    <string name="day_of_week_long_sunday">нядзеля</string>
-    <string name="day_of_week_long_monday">панядзелак</string>
-    <string name="day_of_week_long_tuesday">аўторак</string>
-    <string name="day_of_week_long_wednesday">серада</string>
-    <string name="day_of_week_long_thursday">чацвер</string>
-    <string name="day_of_week_long_friday">пятніца</string>
-    <string name="day_of_week_long_saturday">субота</string>
-
-    <string name="day_of_week_medium_sunday">нд</string>
-    <string name="day_of_week_medium_monday">пн</string>
-    <string name="day_of_week_medium_tuesday">аў</string>
-    <string name="day_of_week_medium_wednesday">ср</string>
-    <string name="day_of_week_medium_thursday">чц</string>
-    <string name="day_of_week_medium_friday">пт</string>
-    <string name="day_of_week_medium_saturday">сб</string>
-
-    <string name="day_of_week_short_sunday">нд</string>
-    <string name="day_of_week_short_monday">пн</string>
-    <string name="day_of_week_short_tuesday">аў</string>
-    <string name="day_of_week_short_wednesday">ср</string>
-    <string name="day_of_week_short_thursday">чц</string>
-    <string name="day_of_week_short_friday">пт</string>
-    <string name="day_of_week_short_saturday">сб</string>
-
-    <string name="day_of_week_shortest_sunday">н</string>
-    <string name="day_of_week_shortest_monday">п</string>
-    <string name="day_of_week_shortest_tuesday">а</string>
-    <string name="day_of_week_shortest_wednesday">с</string>
-    <string name="day_of_week_shortest_thursday">ч</string>
-    <string name="day_of_week_shortest_friday">п</string>
-    <string name="day_of_week_shortest_saturday">с</string>
-
-    <string name="am">да палудня</string>
-    <string name="pm">пасля палудня</string>
-    <string name="yesterday">учора</string>
-    <string name="today">сёння</string>
-    <string name="tomorrow">заўтра</string>
-
     <string name="hour_minute_24">%-k.%M</string>
     <string name="hour_minute_ampm">%-l.%M %p</string>
     <string name="hour_minute_cap_ampm">%-l.%M %p</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 21f8896..6ae68f9 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Параметры тэлефона"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Блакіроўка экрана"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Выключыць"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Справаздача пра памылкі"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Справаздача пра памылку"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Будзе збiрацца iнфармацыя пра бягучы стан прылады, якая будзе адпраўляцца на электронную пошту. Стварэнне справаздачы пра памылкi зойме некаторы час."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Бязгучны рэжым"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Гук выкл."</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Гук уключаны"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Вашыя паведамленні"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Счытваць і запісваць вашы SMS-паведамленні, паведамленні электроннай пошты і іншыя паведамленні."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Вашая персанальная інфармацыя"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Прамы доступ да кантактаў і календара, якія захоўваюцца на планшэце."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Прамы доступ да кантактаў і календара, захаваных на тэлефоне."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Прамы доступ да інфармацыі пра вас, якая захоўваецца на вашай кантактнай карце."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Ваша сацыяльная інфармацыя"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Прамы доступ да інфармацыі аб вашых кантактах і сацыяльных сувязях."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Ваша месцазнаходжанне"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Кантраляваць сваё фізічнае месцазнаходжанне."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Сеткавая сувязь"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Доступ да розных функцый сеткі."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Доступ да прылад і сетак праз Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Налады гуку"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Змена налад гуку."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Уплывае на батарэю"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Выкарыстоўвайць магчымасці, якія могуць хутка разрадзіць батарэю."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Каляндар"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Прамы доступ да календара і мерапрыемстваў."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Чытаць карыстальніцкі слоўнік"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Чытаць словы ў карыстальніцкім слоўніку."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Запісаць карыстальніцкі слоўнік"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Дадаць словы ў карыстальніцкі слоўнік."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Закладкі і гісторыя"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Прамы доступ да закладак і гісторыі браўзера."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Будзільнік"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Усталяваць будзільнік."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Галасавая пошта"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Прамы доступ да галасавой пошты."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Мікрафон"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Прамы доступ да мікрафону для запісу гуку."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Камера"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Прамы доступ да камеры, каб зрабіць здымак ці зняць відэа."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Інфармацыя аб вашых прыкладаннях"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Магчымасць уплываць на паводзіны іншых прыкладанняў на вашай прыладзе."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Шпалеры"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Змяніць налады шпалер прылады."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Гадзіннік"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Змяніць час або часавы пояс прылады."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Радок стану"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Змяніць налады прылады ў радку стану."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Налады сінхранізацыі"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Доступ да налад сінхранізацыі."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Вашыя ўліковыя запісы"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Доступ да дзеючых уліковых запісаў."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Кіраванне апаратным забеспячэннем"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Ніжні ўзровень доступу і кіравання сістэмай."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Сродкі распрацоўкі"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Функцыi, патрэбныя толькі для распрацоўшчыкаў прыкладанняў."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Карыстальніцкі інтэрфейс іншага прыкладання"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Уплыў карыстальніцкіх інтэрфейсаў іншых прыкладанняў."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Сховішча"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Атрымаць доступ да USB-назапашвальнiка."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Доступ да SD-карты."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Дазваляе прыкладанням атрымліваць і апрацоўваць паведамленні WAP. Дзякуючы гэтаму дазволу можна кантраляваць або выдаляць паведамленні, пасланыя вам, не паказваючы іх."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"атрымаць запушчаныя прыкладанні"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Дазваляе прыкладанню атрымлiваць звесткi пра прыкладаннi, запушчаныя зараз i нядаўна. Прыкладанне можа знайсцi iнфармацыю пра тое, якiя прыкладаннi выкарыстоўваюцца на прыладзе."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"узаемадзеянне паміж карыстальнікамі"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Дазваляе прыкладанню выконваць дзеяннi сярод розных карыстальнiкаў прылады. Шкоднасныя прыкладаннi могуць выкарыстоўваць гэта, каб парушыць абарону памiж карыстальнiкамi."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"поўная ліцэнзія для ўзаемадзеяння паміж карыстальнiкамi"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Дазваляе ўсе магчымыя ўзаемадзеяннi паміж карыстальнікамі."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"кіраванне дадзенымi карыстальнікаў"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Дазваляе прыкладанням кіраваць звесткамi карыстальнікаў на прыладзе, у тым ліку запытамi, працэсамi стварэння і выдалення."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"атрымаць падрабязныя дадзеныя пра запушчаныя прыкладаннi"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Дазваляе прыкладанню атрымліваць падрабязную інфармацыю пра бягучыя і нядаўна запушчаныя задачы. Шкоднасныя прыкладанні могуць атрымліваць асабістую інфармацыю пра іншыя прыкладаннi."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"змяніць парадак запушчаных прыкладанняў"</string>
@@ -243,6 +287,14 @@
     <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="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"часова ўключыць даступнасць"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Дазваляе прыкладанню часова ўключаць даступнасць прылады. Шкоднасныя прыкладаннi могуць уключыць даступнасць без згоды карыстальніка."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"атрымаць звесткi пра акно"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Дазваляе прыкладанням вымаць iнфармацыю пра вокны з iнструмента кiравання вокнамi. Шкоднасныя прыкладаннi могуць вымаць iнфармацыю, якая прызначана для ўнутранага выкарыстання ў сiстэме."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"фільтр падзей"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Дазваляе прыкладанню рэгiстраваць фiльтр уводу, якi перадае паток усiх дзеянняў карыстальнiка, перш чым будуць адпраўленыя звесткi пра iх. Шкоднасныя прыкладаннi могуць кантраляваць iнтэрфейс без умяшальнiцтва."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"павялічыць адлюстраванне"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Прыкладанне зможа павялічыць ўтрыманне дысплея. Шкоднасныя праграмы могуць пераўтварыць змесціва дысплея такім чынам, што яно зробіць прыладу непрыдатнай для выкарыстання."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"частковае адключэнне"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Спыняе дзейнасць менеджэра. Не выконвае поўнае адключэнне."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"прадухіляць пераключэнне прыкладанняў"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Дазваляе прыкладанням кантраляваць максімальную колькасць запушчаных працэсаў. Не патрабуецца для звычайных прыкладанняў."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"прымусовае закрыццё фонавых прыкладанняў"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Дазваляе прыкладанням кантраляваць, ці будуць працэсы заўсёды завяршацца, як толькі яны пераходзяць у фонавы рэжым. Не патрабуецца для звычайных прыкладанняў."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"змяняць статыстыку батарэі"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Дазваляе прыкладанням змяняць сабраную статыстыку акумулятара. Не для выкарыстання звычайнымі прыкладаннямі."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"чытаць статыстыку батарэі"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Прыкладанне можа счытваць бягучыя звесткi пры нiзкi зарад акумулятара. Прыкладанне можа знайсцi падрабязную iнфармацы. пра прыкладаннi, якiя вы выкарыстоўваеце."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"змяняць статыстыку батарэі"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Дазваляе прыкладанням змяняць сабраную статыстыку батарэi. Не патрабуецца для звычайных прыкладанняў."</string>
     <string name="permlab_backup" msgid="470013022865453920">"кантраляваць рэзервовае капіяванне і аднаўленне сістэмы"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Дазваляе прыкладанням кантраляваць рэзервовае капіяванне сістэмы і механізм аднаўлення. Не патрабуецца для звычайных прыкладанняў."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"пацверджанне поўнага рэзервовага капіявання або аднаўлення"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"паказваць несанкцыянаваныя вокны"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Дазваляе прыкладанням ствараць вокны, прызначаныя для выкарыстання ўнутраным інтэрфейсам карыстальніка сістэмы. Не для выкарыстання звычайнымі прыкладаннямі."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"прыарытэт перад іншымі прыкладаннямі"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Дазваляе прыкладанню паказваць вокны з сістэмнымi апавяшчэннямi. Некаторыя вокны з апавяшчэннямi могуць займаць увесь экран."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Прыкладанне можа з\'яўляцца паверх iншых прыкладанняў. Яны могуць шкодзiць адно аднаму падчас працы iнтэрфейсаў або змяняць тое, што вы бачыце ў iншых прыкладаннях."</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="permlab_freezeScreen" msgid="4708181184441880175">"замарозіць экран"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Прыкладанне зможа часова замарозіць экран для пераходу ў поўнаэкранны рэжым."</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>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"усталяваць прыкладанні непасрэдна"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Дазваляе прыкладанням ксталёўваць новыя або абноўленыя пакеты Android. Шкоднасныя прыкладанні могуць выкарыстоўваць гэта, каб дадаваць новыя прыкладаннi з дазволамі адвольнай ступені."</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="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Прыкладанне дазваляе вызваляць сховiшча планшэта, выдаляючы файлы з дырэкторый кэша iншых прыкладанняў. Гэта можа прывесцi да таго, што iншыя прыкладаннi пачнуць працаваць павольней, таму што iм трэба будзе паўторна атрымлiваць свае дадзеныя."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Прыкладанне дазваляе вызваляць сховiшча тэлефона, выдаляючы файлы з дырэкторый кэша iншых прыкладанняў. Гэта можа прывесцi да таго, што iншыя прыкладаннi пачнуць працаваць павольней, таму што iм трэба будзе паўторна атрымлiваць свае дадзеныя."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"перамясціць рэсурсы прыкладання"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Дазваляе прыкладанням перамяшчаць рэсурсы прыкладання з унутраных на знешнія носьбіты і наадварот."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"чытаць канфідэнцыйныя дадзеныя дзённiка"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Дазваляе прыкладанням атрымліваць доступ да дадатковых каманд правайдара месцазнаходжання. Гэта можа дазволiць прыкладанню ўмешвацца ў працу GPS або іншых крыніц месцазнаходжання."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"дазвол на ўсталяванне пастаўшчыка месцазнаходжання"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Стварыць макет крыніц месцазнаходжання для тэставання і ўсталёўкі новага правайдара месцазнаходжання. Гэта дазваляе прыкладанню перавызначыць месцазнаходжанне і/або статус, вернуты іншымi крыніцамi, напрыклад геапазiцыйнай службай i правайдарамi месцазнаходжання."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"дакладнае месца (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Атрымлiвайце доступ да дакладных крынiц месцазнаходжання, такiх як Глабальная геапазiцыйная сiстэма, з планшэта. Калi службы вызначэння месцазнаходжання даступныя i ўключаныя, дзякуючы гэтаму дазволу прыкладанне зможа вызначаць ваша дакл месцазнаходжанне."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Атрымлiвайце доступ да дакладных крынiц месцазнаходжання, такiх як Глабальная геапазiцыйная сiстэма, з тэлефона. Калi службы вызначэння месцазнаходжання даступныя i ўключаныя, дзякуючы гэтаму дазволу прыкладанне зможа вызначаць ваша дакладн месцазнаходжанне."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"прыблізнае (заснаванае на дадзеных сеткі) месцазнаходжанне"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Атрымлiвайце доступ да прыблiзнага месцазнаходжання ад правайдараў месцазнаходжання з дапамогай крынiц сеткi, такiх як вышка мабiльнай сувязi i Wi-Fi. Калi гэтыя службы вызначэння месцазнаходжання будуць даступныя i ўключаныя, дзякуючы гэтаму дазволу прыкладанне зможа вызначаць ваша прыблiзнае месцазнаходжанне."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"дакладнае месцазнаходжанне (на аснове GPS і сеткі)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Дазваляе прыкладанню вызначаць дакладнае месцазнаходжанне з дапамогай GPS або сеткавых крынiц месцазнаходжання, напрыклад веж сотавай сувязi i Wi-Fi. Гэтыя службы вызначэння месцазнаходжання павiнны быць уключаны i даступныя для вашай прылады i прыкладання. Прыкладаннi могуць выкарыстоўваць гэта, каб вызначаць ваша прыблiзнае месцазнаходжанне, а таксама спажываць дадатковае сiлкаванне."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"прыблізнае месцазнаходжанне (па дадзеных сеткі)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Дазваляе прыкладанню вызначаць прыблiзнае месцазнаходжанне. Гэта месцазнаходжанне вызначаецца спецыяльнымi службамi з выкарыстаннем сеткавых крынiц месцазнаходжання, напрыклад веж сотавай сувязi i Wi-Fi. Службы вызначэння месцазнаходжання павiнны быць уключаны i даступныя для вашай прылады i прыкладання. Прыкладаннi могуць выкарыстоўваць гэта, каб вызначаць ваша прыблiзнае месцазнаходжанне."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"доступ да 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="permlab_configureWifiDisplay" msgid="5595661694746742168">"налада дысплеяў Wi-Fi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Дазволiць прыкладанню наладжвацца i падключацца да дысплеяў Wi-Fi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"кіраванне дысплеямi Wi-Fi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Прыкладанне зможа кіраваць нізкім узроўнем функцый дысплеяў Wi-Fi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"змяняць налады аудыё"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Дазваляе прыкладанням змяняць глабальныя налады гуку, такія як моц і тое, што дынамік выкарыстоўваецца для выхаду."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"запісваць аўдыё"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"атрыманне доступу да налад прылады Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Дазваляе прыкладанням наладжваць лакальны планшэт Bluetooth, выяўляць і падлучаць выдаленыя прылады."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Дазваляе прыкладанням наладжваць лакальны тэлефон Bluetooth, а таксама знаходзіць выдаленыя прылады i падлучацца да ix."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Прагляд злучэнняў WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"падключаць да WiMAX i адключаць ад яго"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Дазваляе прыкладанню вызначаць, ці ўключаны WiMAX, і інфармацыю пра любую сетку WiMAX, якая спалучана з iншымi."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Змяніць стан WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Дазваляе прыкладанням падключаць планшэт да сеткі WiMAX i адключаць яго ад яе."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Дазваляе прыкладанням змяняць бягучыя каналы сінхранізавання. Шкоднасныя прыкладанні могуць змяняць вашы каналы сінхранізацыi."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"чытанне тэрмінаў, дададзеных у слоўнік"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Дазваляе прыкладанням счытваць любыя словы, імёны і фразы, якія карыстальнік можа захоўваць у карыстальніцкім слоўніку."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"запісаць у карыстальніцкі слоўнік"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"Даданне слоў у карыстальнiцкі слоўнік"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Дазваляе прыкладанням запісваць новыя словы ў карыстальніцкі слоўнік."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"выпрабавальны доступ да абароненага сховiшча"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"выпрабавальны доступ да абароненага сховiшча"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Дазваляе прыкладанню правяраць дазвол на USB-назапашвальнiк, якi будзе даступны для прылад у будучынi."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Дазваляе прыкладанню правяраць дазвол на USB-назапашвальнiк, якi будзе даступны для прылад у будучынi."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Дазваляе прыкладанню правяраць дазвол на SD-карту, якая будзе даступна для прылад у будучынi."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"зм. або выд. змес. USB-назап."</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"змяніць або выдаліць змесціва SD-карты"</string>
@@ -534,6 +593,8 @@
     <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="permlab_sdcardAccessAll" msgid="8150613823900460576">"доступ да знешніх захоўвання для ўсіх карыстальнікаў"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Дазваляе ўсiм карыстальнiкам прыкладання атрымлiваць доступ да знешнега сховiшча"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"доступ да файлавай сістэмы кэша"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Дазваляе прыкладанню счытваць і выконваць запіс у файлавую сістэму кэш-памяці."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"рабіць/прымаць iнтэрнэт-выклікі"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Запыт на шыфраванне захаваных дадзеных прыкладанняў."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Адключыць камеры"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Забараніць выкарыстанне ўсіх камер прылады."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Адключэнне функцыі блакiроўкi клавiятуры"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Прадухіленне выкарыстання некаторых функцый падчас блакiроўкi."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Галоўная старонка"</item>
     <item msgid="869923650527136615">"Мабільны"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Паўтарыце спробу"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Перавышана максімальная колькасць спроб разблакоўкі праз Фэйскантроль"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Зарадка, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Зараджаны."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Зараджаны"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Падлучыце зарадную прыладу."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Няма SIM-карты."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Няма SIM-карты"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Няма SIM-карты ў планшэце."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"У тэлефоне няма SIM-карты."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Усталюйце SIM-карту."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Ключ выдалены"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Сотавы дададзены"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Ключ завершаны"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Дадаць віджэт"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Пусты"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Вобласць разблакіроўкі разгарнута."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Вобласць разблакіроўкі згарнута."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Віджэт <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Селектар карыстальнiка"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Стан"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Камера"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Налады мультымедыя"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Змяненне парадку віджэтаў пачалося."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Змяненне парадку віджэтаў скончылася."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Віджэт <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> выдалены."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Разгарнуць вобласць разблакіроўкі."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Разблакiроўка слайда."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Узор разблакiроўкі."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Фэйскантроль"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-код разблакiроўкі."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Пароль разблакiроўкі."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Вобласць узора."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Вобласць слайда."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"Alt"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Скапіяваць URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Выбраць тэкст"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Вылучэнне тэксту"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"дадаць у слоўнік"</string>
-    <string name="deleteText" msgid="7070985395199629156">"выдаліць"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Дадаць у слоўнік"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Выдалiць"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Метад уводу"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Дзеянні з тэкстам"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Месца для захавання на зыходзе"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Даступны адкрытыя сеткі Wi-Fi"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Увайдзіце ў сетку Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Увайдзіце ў сетку Wi-Fi"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Немагчыма падключыцца да Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" дрэннае падключэнне да Інтэрнэту."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Каму:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Увядзіце патрэбны PIN-код:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-код"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Тэлефон будзе часова адключаны ад Wi-Fi, пакуль ён падлучаны да прылады <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Уставіць сімвал"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Адпраўка SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"Прыкладанне &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; дасылае вялікую колькасць SMS-паведамленняў. Дазволіць гэтаму прыкладанню працягваць адпраўляць паведамленні?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Дазволіць"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Забараніць"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; хоча адправiць паведамленне на адрас &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Гэта "<font fgcolor="#ffffb060">"можа прывесцi да дадатковых выдаткаванняў"</font>" з вашага мабiльнага ўлiковага запiсу."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Гэта стане прычынай дадатковага спагнання сродкаў з вашага мабiльнага ўлiковага запiсу."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Адправiць"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Адмена"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Захаваць мой выбар"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Пазней гэта можна змянiць у раздзеле \"Налады &gt; Прыкладаннi\""</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Заўсёды дазваляць"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Ніколі не дазваляць"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-карта выдаленая"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Мабільная сетка будзе недаступная да перазагрузкі з дзеючай SIM-картай."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Гатова"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Усталяваць дату"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Задаць"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Гатова"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Па змаўчанні"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Дазволу не патрабуецца"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Не паказваць"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Паказаць усе"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"НОВАЕ: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"НОВАЕ: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Прадастаўленыя прыкладаннем <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Дазволу не патрабуецца"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"за гэта можа спаганяцца плата"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Унiверсальны USB-назапашвальнік"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB падлучаны"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Вы падлучаны да камп\'ютара праз USB. Націсніце на кнопку ніжэй, калі жадаеце капіраваць файлы з камп\'ютара на USB-назапашвальнік прылады Android і наадварот."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN актывуецца прыкладаннем <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Дакраніцеся, каб кіраваць сеткай."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Падлучаны да сеанса \"<xliff:g id="SESSION">%s</xliff:g>\". Дакраніцеся, каб кiраваць сеткай."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Падключэнне заўсёды ўключанага VPN..."</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Заўсёды ўключаны i падключаны VPN"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Памылка заўсёды ўключанага VPN"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Націсніце, каб скінуць падключэнне"</string>
     <string name="upload_file" msgid="2897957172366730416">"Выберыце файл"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Файл не выбраны"</string>
     <string name="reset" msgid="2448168080964209908">"Скінуць"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Адкрыць доступ"</string>
     <string name="find" msgid="4808270900322985960">"Пошук"</string>
     <string name="websearch" msgid="4337157977400211589">"Вэб-пошук"</string>
+    <string name="find_next" msgid="5742124618942193978">"Знайсці нiжэй"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Знайсці вышэй"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Запыт пра месцазнаходжанне ад карыстальніка <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Запыт месцазнаходжання"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Запыт ад карыстальнiка <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Тэлефон"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Навушнікі"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Дынамікі станцыi"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-аўдыёвыхад"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Сістэма"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-аўдыё"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Гатова"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Мультымедыйны выхад"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Сканiраванне..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Падключэнне..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Даступна"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Недаступны"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Убудаваны экран"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Экран HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Оверлей # <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> кр. на цалю"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Падключаны бесправадны дысплей"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Гэты экран паказваецца на іншай прыладзе"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Адключыць"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Экстранны выклік"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Забылі ключ"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Няправільна ключ"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Няправiльны пароль"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Няправільны PIN-код"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Паўтарыце спробу праз <xliff:g id="NUMBER">%d</xliff:g> с."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Намалюйце ключ"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Увядзіце PIN-код SIM-карты"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Увядзіце PIN-код"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Увядзіце пароль"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM-карта зараз адключана. Увядзіце PUK-код, каб працягнуць. Звяжыцеся са сваiм аператарам, каб атрымаць дадатковую iнфармацыю."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Увядзіце жаданы PIN-код"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Пацвердзіце жадан PIN-код"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Разблакiроўка SIM-карты..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Няправільны PIN-код."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Увядзіце PIN-код, які змяшчае ад 4 да 8 лічбаў."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK-код павінен утрымлiваць 8 лiчбаў і больш."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Паўторна увядзіце правільны PUK-код. Неаднаразовыя спробы назаўжды адключаць SIM-карту."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN-коды не супадаюць"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Занадта шмат спроб паўтарыць шаблон!"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Каб разблакiраваць, увайдзіце ў свой уліковы запіс Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Імя карыстальніка (электронная пошта)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Пароль"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Увайсцi"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Няправільнае імя карыстальніка ці пароль."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Забыліся на імя карыстальніка або пароль?"\n"Наведайце "<b>"google.com/accounts/recovery"</b></string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Праверка ўлiковага запiсу..."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Вы няправільна ўвялі PIN-код пэўную колькасць разоў: <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n"Паўтарыце спробу праз <xliff:g id="NUMBER_1">%d</xliff:g> с."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Вы няправільна ўвялі пароль пэўную колькасць разоў: <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n"Паўтарыце спробу праз <xliff:g id="NUMBER_1">%d</xliff:g> с."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Вы няправільна ўвялі графічны ключ разблакiроўкi пэўную колькасць разоў: <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n"Паўтарыце спробу праз <xliff:g id="NUMBER_1">%d</xliff:g> с."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Вы няправільна спрабавалі разблакiраваць планшэт некалькi разоў (<xliff:g id="NUMBER_0">%d</xliff:g>). Пасля яшчэ некалькiх спроб (<xliff:g id="NUMBER_1">%d</xliff:g>) ён будзе скінуты да заводскіх налад i карыстальнiцкiя дадзеныя будуць згубленыя."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Вы няправільна спрабавалі разблакiраваць планшэт некалькi разоў (<xliff:g id="NUMBER_0">%d</xliff:g>). Пасля яшчэ некалькiх спроб (<xliff:g id="NUMBER_1">%d</xliff:g>) ён будзе скінуты да завадскіх налад i карыстальнiцкiя дадзеныя будуць згубленыя."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Вы няправільна спрабавалі разблакiраваць планшэт некалькi разоў (<xliff:g id="NUMBER">%d</xliff:g>). Цяпер ён будзе скінуты да завадскіх налад."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Вы няправільна спрабавалі разблакiраваць тэлефон некалькi разоў (<xliff:g id="NUMBER">%d</xliff:g>). Цяпер ён будзе скінуты да завадскіх налад."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Вы няправільна ўвялі графічны ключ разблакiроўкi пэўную колькасць разоў: <xliff:g id="NUMBER_0">%d</xliff:g>. Пасля яшчэ некалькiх няўдалых спроб (<xliff:g id="NUMBER_1">%d</xliff:g>) вам будзе прапанавана разблакiраваць тэлефон, увайшоўшы ў Google."\n\n" Паўтарыце спробу праз <xliff:g id="NUMBER_2">%d</xliff:g> с."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Вы няправільна ўвялі графічны ключ разблакiроўкi пэўную колькасць разоў: <xliff:g id="NUMBER_0">%d</xliff:g>. Пасля яшчэ некалькiх няўдалых спроб (<xliff:g id="NUMBER_1">%d</xliff:g>) вам будзе прапанавана разблакiраваць тэлефон, увайшоўшы ў Google."\n\n" Паўтарыце спробу праз <xliff:g id="NUMBER_2">%d</xliff:g> с."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Выдаліць"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Павялiчыць гук больш за рэкамендаваны ўзровень?"\n"Доўгае слуханне музыкi на вялiкай гучнасцi можа пашкодзiць ваш слых."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Утрымлiвайце два пальцы, каб уключыць доступ."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Даступнасць уключана."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Даступнасць адменена."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Бягучы карыстальнік <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Уладальнік"</string>
 </resources>
diff --git a/core/res/res/values-bg/donottranslate-cldr.xml b/core/res/res/values-bg/donottranslate-cldr.xml
index 972d661..9c1ae2c 100644
--- a/core/res/res/values-bg/donottranslate-cldr.xml
+++ b/core/res/res/values-bg/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">януари</string>
-    <string name="month_long_standalone_february">февруари</string>
-    <string name="month_long_standalone_march">март</string>
-    <string name="month_long_standalone_april">април</string>
-    <string name="month_long_standalone_may">май</string>
-    <string name="month_long_standalone_june">юни</string>
-    <string name="month_long_standalone_july">юли</string>
-    <string name="month_long_standalone_august">август</string>
-    <string name="month_long_standalone_september">септември</string>
-    <string name="month_long_standalone_october">октомври</string>
-    <string name="month_long_standalone_november">ноември</string>
-    <string name="month_long_standalone_december">декември</string>
-
-    <string name="month_long_january">януари</string>
-    <string name="month_long_february">февруари</string>
-    <string name="month_long_march">март</string>
-    <string name="month_long_april">април</string>
-    <string name="month_long_may">май</string>
-    <string name="month_long_june">юни</string>
-    <string name="month_long_july">юли</string>
-    <string name="month_long_august">август</string>
-    <string name="month_long_september">септември</string>
-    <string name="month_long_october">октомври</string>
-    <string name="month_long_november">ноември</string>
-    <string name="month_long_december">декември</string>
-
-    <string name="month_medium_january">ян.</string>
-    <string name="month_medium_february">февр.</string>
-    <string name="month_medium_march">март</string>
-    <string name="month_medium_april">апр.</string>
-    <string name="month_medium_may">май</string>
-    <string name="month_medium_june">юни</string>
-    <string name="month_medium_july">юли</string>
-    <string name="month_medium_august">авг.</string>
-    <string name="month_medium_september">септ.</string>
-    <string name="month_medium_october">окт.</string>
-    <string name="month_medium_november">ноем.</string>
-    <string name="month_medium_december">дек.</string>
-
-    <string name="month_shortest_january">я</string>
-    <string name="month_shortest_february">ф</string>
-    <string name="month_shortest_march">м</string>
-    <string name="month_shortest_april">а</string>
-    <string name="month_shortest_may">м</string>
-    <string name="month_shortest_june">ю</string>
-    <string name="month_shortest_july">ю</string>
-    <string name="month_shortest_august">а</string>
-    <string name="month_shortest_september">с</string>
-    <string name="month_shortest_october">о</string>
-    <string name="month_shortest_november">н</string>
-    <string name="month_shortest_december">д</string>
-
-    <string name="day_of_week_long_sunday">неделя</string>
-    <string name="day_of_week_long_monday">понеделник</string>
-    <string name="day_of_week_long_tuesday">вторник</string>
-    <string name="day_of_week_long_wednesday">сряда</string>
-    <string name="day_of_week_long_thursday">четвъртък</string>
-    <string name="day_of_week_long_friday">петък</string>
-    <string name="day_of_week_long_saturday">събота</string>
-
-    <string name="day_of_week_medium_sunday">нд</string>
-    <string name="day_of_week_medium_monday">пн</string>
-    <string name="day_of_week_medium_tuesday">вт</string>
-    <string name="day_of_week_medium_wednesday">ср</string>
-    <string name="day_of_week_medium_thursday">чт</string>
-    <string name="day_of_week_medium_friday">пт</string>
-    <string name="day_of_week_medium_saturday">сб</string>
-
-    <string name="day_of_week_short_sunday">нд</string>
-    <string name="day_of_week_short_monday">пн</string>
-    <string name="day_of_week_short_tuesday">вт</string>
-    <string name="day_of_week_short_wednesday">ср</string>
-    <string name="day_of_week_short_thursday">чт</string>
-    <string name="day_of_week_short_friday">пт</string>
-    <string name="day_of_week_short_saturday">сб</string>
-
-    <string name="day_of_week_shortest_sunday">н</string>
-    <string name="day_of_week_shortest_monday">п</string>
-    <string name="day_of_week_shortest_tuesday">в</string>
-    <string name="day_of_week_shortest_wednesday">с</string>
-    <string name="day_of_week_shortest_thursday">ч</string>
-    <string name="day_of_week_shortest_friday">п</string>
-    <string name="day_of_week_shortest_saturday">с</string>
-
-    <string name="am">пр. об.</string>
-    <string name="pm">сл. об.</string>
-    <string name="yesterday">Вчера</string>
-    <string name="today">Днес</string>
-    <string name="tomorrow">Утре</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 8d45aa9..838f0cf 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Опции на телефона"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Заключване на екрана"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Изключване"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Сигнал за програмна грешка"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Получаване на сигнал за програмна грешка"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"По този начин ще се събере информация за текущото състояние на устройството ви, която да се изпрати като имейл съобщение. След стартирането на процеса ще мине известно време, докато сигналът за програмна грешка бъде готов за подаване. Моля, имайте търпение."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Тих режим"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Звукът е ИЗКЛЮЧЕН"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Звукът е ВКЛЮЧЕН"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Вашите съобщения"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Четене и запис на вашите SMS, имейли и други съобщения."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Вашите лични данни"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Пряк достъп до контактите и календара ви, съхранени в таблета."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Пряк достъп до контактите и календара ви, съхранени в телефона."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Осъществяване на директен достъп до информация за вас, съхранявана в картата ви с данни за контакт."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Социалната ви информация"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Осъществяване на директен достъп до информация за контактите и социалните ви връзки."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Местоположение"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Наблюдавайте физическото си местоположение."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Мрежова комуникация"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Осъществявайте достъп до различни мрежови функции."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Осъществяване на достъп до устройства и мрежи през Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Настройки за звука"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Промяна на настройките за звукa."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Оказване на влияние върху батерията"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Използване на функции, които могат бързо да изразходят батерията."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Календар"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Осъществяване на директен достъп до календара и събитията."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Четене на потребителския речник"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Четене на думи в потребителския речник."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Записване в потребителския речник"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Добавяне на думи в потребителския речник."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Отметки и история"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Осъществяване на директен достъп до отметките и историята на браузъра."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Будилник"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Навиване на будилника."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Гласова поща"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Осъществяване на директен достъп до гласовата поща."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Микрофон"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Осъществяване на директен достъп до микрофона с цел записване на звук."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Камера"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Осъществяване на директен достъп до камерата с цел заснемане на снимки или видеоклипове."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Информация за приложенията ви"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Възможност за оказване на влияние върху поведението на други приложения на устройството ви."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Тапет"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Промяна на настройките за тапет на устройството."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Часовник"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Промяна на часа или на часовата зона на устройството."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Лента на състоянието"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Промяна на настройките за лентата на състоянието на устройството."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Настройки за синхронизиране"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Осъществяване на достъп до настройките за синхронизиране."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Вашите профили"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Достъп до наличните профили."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Контрол върху хардуера"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Достъп и контрол на системата на ниско ниво."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Инструменти за програмиране"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Функции, необходими само за програмисти на приложения."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Други потребителски интерфейси на приложения"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Оказване на влияниe върху потребителския интерфейс на други приложения."</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>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Разрешава на приложението да получава и обработва WAP съобщения. Това разрешение включва възможността да наблюдава или изтрива изпратените до вас, без да ви ги покаже."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"извличане на изпълняваните приложения"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Разрешава на приложението да извлича информация за задачите, изпълнявани понастоящем и неотдавна. Това може да му позволи да открива данни за това, кои приложения се използват на устройството."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"взаимодействие с потребителите"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Разрешава на приложението да изпълнява действия за различни потребители на устройството. Злонамерените приложения може да използват това, за да нарушат защитата между потребителите."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"пълен лиценз за взаимодействие с потребителите"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Разрешава всички възможни взаимодействия с потребителите."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"управление на потребителите"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Разрешава на приложенията да управляват потребителите на устройството, включително изброяването, създаването и изтриването им."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"извличане на подробности за изпълняваните прилож."</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Разрешава на приложението да извлича подробна информация за задачите, изпълнявани понастоящем и неотдавна. Злонамерените приложения могат да открият поверителна информация за други приложения."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"пренареждане на изпълняваните приложения"</string>
@@ -243,6 +287,14 @@
     <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="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"временно активиране на достъпността"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Разрешава на приложението временно да активира достъпността на устройството. Злонамерените приложения може да я активират без съгласието на потребителя."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"извличане на информация за прозорците"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Разрешава на приложението да извлича информация за прозорците от съответния мениджър. Злонамерените приложения може да извличат данни, които са предназначени за вътрешно използване от системата."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"филтриране на събитията"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Разрешава на приложението да регистрира входящ филтър, който филтрира потока на всички потребителски събития преди изпращането им. Злонамерено приложение може да контролира системния потребителски интерфейс без намесата на потребителя."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"промяна на мащаба на дисплея"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Разрешава на приложението да променя мащаба на съдържанието на дисплей. Злонамерените приложения може да преобразят съдържанието на дисплея по начин, който изобразява устройството като неизползваемо."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"частично изключване"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Изключва диспечера на дейностите. Не извършва пълно изключване."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"предотвратяване на превключването между приложения"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Разрешава на приложението да контролира максималния брой изпълнявани процеси. Нормалните приложения никога не се нуждаят от това."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"принудително затваряне на приложенията на заден план"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Разрешава на приложението да контролира дали дейностите винаги се завършват веднага щом минат на заден план. Нормалните приложения никога не се нуждаят от това."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"промяна на статистическите данни за батерията"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Разрешава на приложението да променя събраните статистически данни за батерията. Не е предназначено за нормални приложения."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"четене на статистическите данни за батерията"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Разрешава на приложението да чете текущите данни за работа при ниско ниво на батерията. Може да му разреши да намери подробна информация за ползваните от вас приложения."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"промяна на статистическите данни за батерията"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Разрешава на приложението да променя събраните статистически данни за батерията. Не е предназначено за нормални приложения."</string>
     <string name="permlab_backup" msgid="470013022865453920">"контролиране на създаването и възстановяването на резервни копия на системата"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Разрешава на приложението да контролира системния механизъм за създаване и възстановяване на резервни копия. Не е предназначено за нормални приложения."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"потвърждаване на пълно резервно копие или възстановяване на операцията"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"показване на неупълномощени прозорци"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Разрешава на приложението да създава прозорци, предназначени за употреба от вътрешния системен потребителски интерфейс. Не е предназначено за нормални приложения."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"изобразяване над други приложения"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Разрешава на приложението да показва прозорци за системни сигнали. Някои от тях могат да завладеят целия екран."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Разрешава на приложението да се изобразява върху други приложения или части от потребителския интерфейс. Те може да смутят използването от ваша страна на интерфейса във всяко приложение или да променят това, което мислите, че виждате в другите приложения."</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="permlab_freezeScreen" msgid="4708181184441880175">"фиксиране на екрана"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Разрешава на приложението временно да фиксира екрана за преход към цял екран."</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>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"директно инсталиране на приложения"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Разрешава на приложението да инсталира нови или актуализирани пакети от Android. Злонамерените приложения могат да използват това, за да добавят нови приложения с произволно мощни разрешения."</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="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Разрешава на приложението да освобождава място в хранилището на таблета, като изтрива файлове в директориите за кеш на други приложения. Това може да доведе до по-бавното стартиране на другите приложения, защото те трябва да извличат отново данните си."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Разрешава на приложението да освобождава място в хранилището на телефона, като изтрива файлове в директориите за кеш на други приложения. Това може да доведе до по-бавното стартиране на другите приложения, защото те трябва да извличат отново данните си."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"преместване на ресурси на приложенията"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Разрешава на приложението да мести ресурси на приложения от вътрешни към външни носители и обратно."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"четене на поверителни данни от регистрационните файлове"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Разрешава на приложението достъп до допълнителни команди на доставчика на местоположение. Това може да му позволи да смущава работата на GPS или на другите източници на местоположение."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"разрешение за инсталиране на доставчик на местоположение"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Създаване на мними източници на местоположение за тестване или инсталиране на нов доставчик на местоположение. Това разрешава на приложението да заменя местоположението и/или състоянието, връщано от други източници, като GPS или доставчиците."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"точно местоположение (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Достъп до източници за точно местоположение, като системата GPS на таблета. Когато услугите за местоположения са налични и включени, това разрешение позволява на приложението да определя точното ви местоположение."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Достъп до източници за точно местоположение, като системата GPS на телефона. Когато услугите за местоположения са налични и включени, това разрешение позволява на приложението да определя точното ви местоположение."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"приблизително местоположение (основано на мрежата)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Достъп до приблизителното местоположение от съответните доставчици посредством източници на мрежи, като клетъчна кула и Wi-Fi. Когато тези услуги за местоположения са налични и включени, това разрешение позволява на приложението да определя приблизителното ви местоположение."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"точно местоположение (основано на GPS и мрежата)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Разрешава на приложението да получи точното ви местоположение посредством системата GPS или съответните мрежови източници, като клетъчни кули и Wi-Fi. Тези услуги за местоположение трябва да са включени и налице на устройството ви, за да могат да се използват от приложението. Приложенията може да ползват това, за да определят къде се намирате, и да изразходват повече енергия от батерията."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"приблизително местоположение (основано на мрежата)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Разрешава на приложението да получи приблизителното ви местоположение. То се извлича от услугите за местоположение посредством съответните мрежови източници, като клетъчни кули и Wi-Fi. Тези услуги трябва да са включени и налице на устройството ви, за да могат да се използват от приложението. Приложенията може да ползват това, за да определят къде приблизително се намирате."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"достъп до 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="permlab_configureWifiDisplay" msgid="5595661694746742168">"конфигуриране на дисплеите през WiFi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Разрешава на приложението да конфигурира и да се свързва с дисплеите през WiFi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"контролиране на дисплеите през WiFi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Разрешава на приложението да контролира функциите от ниско ниво на дисплеите през WiFi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"промяна на настройките ви за звука"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Разрешава на приложението да променя глобалните настройки за звука, като например силата и това, кой високоговорител се използва за изход."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"запис на звук"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"достъп до настройките за Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Разрешава на приложението да конфигурира локалния таблет с Bluetooth, както и да открива и да се сдвоява с отдалечени устройства."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Разрешава на приложението да конфигурира локалния телефон с Bluetooth, както и да открива и да се сдвоява с отдалечени устройства."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Преглед на връзките с WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"установяване и прекратяване на връзката с WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Разрешава на приложението да определя дали WiMAX мрежата е активирана, както и информация за всички такива мрежи, които са свързани."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Промяна на състоянието на WiMAX мрежата"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Разрешава на приложението да свързва таблета към WiMAX мрежа и да прекратява връзката му с нея."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Разрешава на приложението да променя текущо синхронизираните ви емисии. Злонамерените приложения могат да ги променят."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"четене на думите, които сте добавили в речника"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Разрешава на приложението да чете всички думи, имена и фрази, които потребителят може да е съхранил в потребителския речник."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"запис в дефинирания от потребителя речник"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"добавяне на думи в дефинирания от потребителя речник"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Разрешава на приложението да записва нови думи в потребителския речник."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"изпробване на достъп до защитено хранилище"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"изпробване на достъп до защитено хранилище"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Разрешава на приложението да изпробва разрешение за USB хран., което ще е налице на бъдещи у-ва."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Разрешава на приложението да изпробва разрешение за USB хран., което ще е налице на бъдещи у-ва."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Разрешава на приложението да изпробва разрешение за SD картата, което ще бъде налице на бъдещи устройства."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"промяна или изтрив. на съдърж. от USB хран. ви"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"промяна или изтриване на съдържанието от SD картата ви"</string>
@@ -534,6 +593,8 @@
     <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="permlab_sdcardAccessAll" msgid="8150613823900460576">"достъп до външ. хранилище за всички потребители"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Разрешава на приложението достъп до външното хранилище за всички потребители."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"достъп до файловата система на кеша"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Разрешава на приложението да чете и записва във файловата система на кеша."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"извършване/получаване на интернет обаждания"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Изисква съхраняваните данни за приложенията да бъдат шифровани."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Деактивиране на камерите"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Предотвратява употребата на камерите на всички устройства."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Функции при защита на клавишите: Деакт."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Предотвратява използването на някои функции при защита на клавишите."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Домашен"</item>
     <item msgid="869923650527136615">"Мобилен"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Опитайте отново"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Максималният брой опити за отключване с лице е надвишен"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Зарежда се, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Зареден."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Заредена"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Свържете зарядното си устройство."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Няма SIM карта."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Няма SIM карта"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"В таблета няма SIM карта."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"В телефона няма SIM карта."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Поставете SIM карта."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Фигурата е изчистена"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Клетката е добавена"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Фигурата е завършена"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Добавяне на приспособление."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Празно"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Областта за отключване е разгъната."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Областта за отключване е свита."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Приспособление за <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Инструмент за избор на потребители"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Състояние"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Камера"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Контроли за мултимедията"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Пренареждането на приспособленията започна."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Пренареждането на приспособленията завърши."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Приспособлението за <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> е изтрито."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Разгъване на областта за отключване."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Отключване с плъзгане."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Отключване с фигура."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Отключване с лице."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Отключване с ПИН код."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Отключване с парола."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Област на фигурата."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Област на плъзгане."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"АБВ"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Копиране на URL адреса"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Избор на текст"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Избиране на текст"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"добавяне към речника"</string>
-    <string name="deleteText" msgid="7070985395199629156">"изтриване"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Добавяне в речника"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Изтриване"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Метод на въвеждане"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Действия с текста"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Мястото в хранилището е на изчерпване"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Има достъпни отворени Wi-Fi мрежи"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Влизане в Wi-Fi мрежа"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Влезте в мрежата"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не можа да се свърже с Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" има лоша връзка с интернет."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"До:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Въведете задължителния ПИН:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"ПИН:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Телефонът временно ще прекрати връзката с Wi-Fi, докато е свързан с/ъс <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Вмъкване на знак"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Изпращане на SMS съобщения"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; изпраща голям брой SMS съобщения. Искате ли да разрешите на това приложение да продължи да го прави?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Разрешаване"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Отказване"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; иска да изпрати съобщение до &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Това "<font fgcolor="#ffffb060">"може да доведе до таксуване"</font>" на мобилната ви сметка."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Това ще доведе до таксуване на мобилната ви сметка."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Изпращане"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Отказ"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Изборът ми да се запомни"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Можете да промените това по-късно в „Настройки“ &gt; „Приложения“"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Винаги да се разрешава"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Никога да не се разрешава"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM картата е премахната"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Няма да имате достъп до мобилната мрежа, докато не рестартирате с поставена валидна SIM карта."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Задаване на дата"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Задаване"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Готово"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"По подразбиране"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Не се изискват разрешения"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Скриване"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Показване на всички"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"НОВО: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"НОВО: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Предоставено от <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Не се изискват разрешения"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"това може да ви струва пари"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Масово USB хранилище"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Връзка през USB"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Свързахте се с компютъра си през USB. Докоснете долния бутон, ако искате да копирате файлове между компютъра и USB хранилището си от Android."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN е активирана от <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Докоснете за управление на мрежата."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Свързана със: <xliff:g id="SESSION">%s</xliff:g>. Докоснете, за да управлявате мрежата."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Установява се връзка с винаги включената виртуална частна мрежа (VPN)…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Установена е връзка с винаги включената виртуална частна мрежа (VPN)"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Грешка във винаги включената виртуална частна мрежа (VPN)"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Докоснете, за да възстановите връзката"</string>
     <string name="upload_file" msgid="2897957172366730416">"Избор на файл"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Няма избран файл"</string>
     <string name="reset" msgid="2448168080964209908">"Повторно задаване"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Споделяне"</string>
     <string name="find" msgid="4808270900322985960">"Намиране"</string>
     <string name="websearch" msgid="4337157977400211589">"Уеб търсене"</string>
+    <string name="find_next" msgid="5742124618942193978">"Търсене на следващото"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Търсене на предишното"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Заявка за местоположение от <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Заявка за местоположение"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Заявено от <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Телефон"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Слушалки"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Докинг станц.: Високогов."</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI аудио"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Система"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Звук през Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Готово"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Изходяща мултимедия"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Сканира се..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Установява се връзка..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Налице"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Не е налице"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Вграден екран"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Екран „HDMI“"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Наслагване №<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"„<xliff:g id="NAME">%1$s</xliff:g>“: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Безжичният дисплей е свързан"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Този екран се показва на друго устройство"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Прекратяване на връзката"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Спешно обаждане"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Забравена фигура"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Грешна фигура"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Грешна парола"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Грешен ПИН код"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Опитайте отново след <xliff:g id="NUMBER">%d</xliff:g> секунди."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Начертайте фигурата си"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Въведете ПИН кода за SIM картата"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Въведете ПИН код"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Въведете паролата"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM картата вече е деактивирана. Въведете PUK кода, за да продължите. Свържете се с оператора за подробности."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Въведете желания ПИН код"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Потвърдете желания ПИН код"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM картата се отключва…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Неправилен ПИН код."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Въведете ПИН код с четири до осем цифри."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK кодът трябва да е с 8 или повече цифри."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Въведете отново правилния PUK код. Многократните опити ще деактивират за постоянно SIM картата."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"ПИН кодовете не съвпадат"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Опитите за фигурата са твърде много"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"За да отключите, влезте с профила си в Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Потребителско име (имейл)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Парола"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Вход"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Невалидно потребителско име или парола."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Забравили сте потребителското име или паролата си?"\n"Посетете "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Профилът се проверява…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Въведохте неправилно ПИН кода си <xliff:g id="NUMBER_0">%d</xliff:g> пъти. "\n\n"Опитайте отново след <xliff:g id="NUMBER_1">%d</xliff:g> секунди."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Въведохте неправилно паролата си <xliff:g id="NUMBER_0">%d</xliff:g> пъти. "\n\n"Опитайте отново след <xliff:g id="NUMBER_1">%d</xliff:g> секунди."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%d</xliff:g> пъти. "\n\n"Опитайте отново след <xliff:g id="NUMBER_1">%d</xliff:g> секунди."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Направихте опит да отключите неправилно таблета <xliff:g id="NUMBER_0">%d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%d</xliff:g> неуспешни опита ще бъдат възстановени стандартните му фабрични настройки и всички потребителски данни ще бъдат заличени."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Направихте опит да отключите неправилно телефона <xliff:g id="NUMBER_0">%d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%d</xliff:g> неуспешни опита ще бъдат възстановени стандартните му фабрични настройки и всички потребителски данни ще бъдат заличени."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Направихте опит да отключите неправилно таблета <xliff:g id="NUMBER">%d</xliff:g> пъти. Сега ще бъдат възстановени стандартните му фабрични настройки."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Направихте опит да отключите неправилно телефона <xliff:g id="NUMBER">%d</xliff:g> пъти. Сега ще бъдат възстановени стандартните му фабрични настройки."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%d</xliff:g> неуспешни опита ще бъдете помолени да отключите таблета посредством имейл адрес."\n\n" Опитайте отново след <xliff:g id="NUMBER_2">%d</xliff:g> секунди."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%d</xliff:g> неуспешни опита ще бъдете помолени да отключите телефона посредством имейл адрес."\n\n" Опитайте отново след <xliff:g id="NUMBER_2">%d</xliff:g> секунди."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Премахване"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Да се увеличи ли силата на звука над безопасното ниво?"\n"Продължителното слушане при висока сила на звука може да увреди слуха ви."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Продължете да натискате с два пръста, за да активирате функцията за достъпност."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Достъпността е активирана."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Функцията за достъпност е анулирана."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Текущ потребител <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Собственик"</string>
 </resources>
diff --git a/core/res/res/values-ca-rES/donottranslate-cldr.xml b/core/res/res/values-ca-rES/donottranslate-cldr.xml
deleted file mode 100644
index 113133d..0000000
--- a/core/res/res/values-ca-rES/donottranslate-cldr.xml
+++ /dev/null
@@ -1,150 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">gener</string>
-    <string name="month_long_standalone_february">febrer</string>
-    <string name="month_long_standalone_march">març</string>
-    <string name="month_long_standalone_april">abril</string>
-    <string name="month_long_standalone_may">maig</string>
-    <string name="month_long_standalone_june">juny</string>
-    <string name="month_long_standalone_july">juliol</string>
-    <string name="month_long_standalone_august">agost</string>
-    <string name="month_long_standalone_september">setembre</string>
-    <string name="month_long_standalone_october">octubre</string>
-    <string name="month_long_standalone_november">novembre</string>
-    <string name="month_long_standalone_december">desembre</string>
-
-    <string name="month_long_january">gener</string>
-    <string name="month_long_february">febrer</string>
-    <string name="month_long_march">març</string>
-    <string name="month_long_april">abril</string>
-    <string name="month_long_may">maig</string>
-    <string name="month_long_june">juny</string>
-    <string name="month_long_july">juliol</string>
-    <string name="month_long_august">agost</string>
-    <string name="month_long_september">setembre</string>
-    <string name="month_long_october">octubre</string>
-    <string name="month_long_november">novembre</string>
-    <string name="month_long_december">desembre</string>
-
-    <string name="month_medium_january">gen.</string>
-    <string name="month_medium_february">febr.</string>
-    <string name="month_medium_march">març</string>
-    <string name="month_medium_april">abr.</string>
-    <string name="month_medium_may">maig</string>
-    <string name="month_medium_june">juny</string>
-    <string name="month_medium_july">jul.</string>
-    <string name="month_medium_august">ag.</string>
-    <string name="month_medium_september">set.</string>
-    <string name="month_medium_october">oct.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">des.</string>
-
-    <string name="month_shortest_january">g</string>
-    <string name="month_shortest_february">f</string>
-    <string name="month_shortest_march">m</string>
-    <string name="month_shortest_april">a</string>
-    <string name="month_shortest_may">m</string>
-    <string name="month_shortest_june">j</string>
-    <string name="month_shortest_july">j</string>
-    <string name="month_shortest_august">a</string>
-    <string name="month_shortest_september">s</string>
-    <string name="month_shortest_october">o</string>
-    <string name="month_shortest_november">n</string>
-    <string name="month_shortest_december">d</string>
-
-    <string name="day_of_week_long_sunday">diumenge</string>
-    <string name="day_of_week_long_monday">dilluns</string>
-    <string name="day_of_week_long_tuesday">dimarts</string>
-    <string name="day_of_week_long_wednesday">dimecres</string>
-    <string name="day_of_week_long_thursday">dijous</string>
-    <string name="day_of_week_long_friday">divendres</string>
-    <string name="day_of_week_long_saturday">dissabte</string>
-
-    <string name="day_of_week_medium_sunday">dg.</string>
-    <string name="day_of_week_medium_monday">dl.</string>
-    <string name="day_of_week_medium_tuesday">dt.</string>
-    <string name="day_of_week_medium_wednesday">dc.</string>
-    <string name="day_of_week_medium_thursday">dj.</string>
-    <string name="day_of_week_medium_friday">dv.</string>
-    <string name="day_of_week_medium_saturday">ds.</string>
-
-    <string name="day_of_week_short_sunday">dg.</string>
-    <string name="day_of_week_short_monday">dl.</string>
-    <string name="day_of_week_short_tuesday">dt.</string>
-    <string name="day_of_week_short_wednesday">dc.</string>
-    <string name="day_of_week_short_thursday">dj.</string>
-    <string name="day_of_week_short_friday">dv.</string>
-    <string name="day_of_week_short_saturday">ds.</string>
-
-    <string name="day_of_week_shortest_sunday">g</string>
-    <string name="day_of_week_shortest_monday">l</string>
-    <string name="day_of_week_shortest_tuesday">t</string>
-    <string name="day_of_week_shortest_wednesday">c</string>
-    <string name="day_of_week_shortest_thursday">j</string>
-    <string name="day_of_week_shortest_friday">v</string>
-    <string name="day_of_week_shortest_saturday">s</string>
-
-    <string name="am">a.m.</string>
-    <string name="pm">p.m.</string>
-    <string name="yesterday">ahir</string>
-    <string name="today">avui</string>
-    <string name="tomorrow">demà</string>
-
-    <string name="hour_minute_24">%-k:%M</string>
-    <string name="hour_minute_ampm">%-l:%M %p</string>
-    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
-    <string name="twelve_hour_time_format">h:mm a</string>
-    <string name="twenty_four_hour_time_format">H:mm</string>
-    <string name="numeric_date">%d/%m/%Y</string>
-    <string name="numeric_date_format">dd/MM/yyyy</string>
-    <string name="numeric_date_template">"%s/%s/%s"</string>
-    <string name="month_day_year">%-e de %B de %Y</string>
-    <string name="time_of_day">%-k:%M:%S</string>
-    <string name="date_and_time">%-k:%M:%S %d/%m/%Y</string>
-    <string name="date_time">%2$s %1$s</string>
-    <string name="time_date">%1$s %3$s</string>
-    <string name="abbrev_month_day_year">%d/%m/%Y</string>
-    <string name="month_day">%-e de %B</string>
-    <string name="month">%-B</string>
-    <string name="month_year">%-B del %Y</string>
-    <string name="abbrev_month_day">%-e %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
-    <string name="time1_time2">%1$s - %2$s</string>
-    <string name="date1_date2">%2$s - %5$s</string>
-    <string name="numeric_md1_md2">%3$s/%2$s - %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s/%2$s/%4$s - %10$s %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s/%2$s - %10$s %6$s %8$s/%7$s</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s - %10$s %8$s/%7$s/%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
-    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
-    <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s de %2$s - %8$s de %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s de %2$s - %10$s %8$s de %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s de %2$s - %10$s %8$s de %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s de %2$s de %4$s - %10$s %8$s de %7$s de %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s de %2$s de %4$s - %10$s %8$s de %7$s de %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s - %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s - %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s - %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s-%8$s de %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s de %2$s - %8$s de %7$s de %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s-%8$s de %2$s de %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s de %2$s - %6$s %8$s de %7$s de %9$s</string>
-    <string name="short_format_month">%b</string>
-    <string name="full_wday_month_day_no_year">EEEE d MMMM</string>
-    <string name="abbrev_wday_month_day_no_year">EEE d MMMM</string>
-    <string name="abbrev_wday_month_day_year">EEE d MMM yyyy</string>
-</resources>
diff --git a/core/res/res/values-ca/donottranslate-cldr.xml b/core/res/res/values-ca/donottranslate-cldr.xml
index 03cf69d..84e7e79 100644
--- a/core/res/res/values-ca/donottranslate-cldr.xml
+++ b/core/res/res/values-ca/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">gener</string>
-    <string name="month_long_standalone_february">febrer</string>
-    <string name="month_long_standalone_march">març</string>
-    <string name="month_long_standalone_april">abril</string>
-    <string name="month_long_standalone_may">maig</string>
-    <string name="month_long_standalone_june">juny</string>
-    <string name="month_long_standalone_july">juliol</string>
-    <string name="month_long_standalone_august">agost</string>
-    <string name="month_long_standalone_september">setembre</string>
-    <string name="month_long_standalone_october">octubre</string>
-    <string name="month_long_standalone_november">novembre</string>
-    <string name="month_long_standalone_december">desembre</string>
-
-    <string name="month_long_january">gener</string>
-    <string name="month_long_february">febrer</string>
-    <string name="month_long_march">març</string>
-    <string name="month_long_april">abril</string>
-    <string name="month_long_may">maig</string>
-    <string name="month_long_june">juny</string>
-    <string name="month_long_july">juliol</string>
-    <string name="month_long_august">agost</string>
-    <string name="month_long_september">setembre</string>
-    <string name="month_long_october">octubre</string>
-    <string name="month_long_november">novembre</string>
-    <string name="month_long_december">desembre</string>
-
-    <string name="month_medium_january">gen.</string>
-    <string name="month_medium_february">febr.</string>
-    <string name="month_medium_march">març</string>
-    <string name="month_medium_april">abr.</string>
-    <string name="month_medium_may">maig</string>
-    <string name="month_medium_june">juny</string>
-    <string name="month_medium_july">jul.</string>
-    <string name="month_medium_august">ag.</string>
-    <string name="month_medium_september">set.</string>
-    <string name="month_medium_october">oct.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">des.</string>
-
-    <string name="month_shortest_january">g</string>
-    <string name="month_shortest_february">f</string>
-    <string name="month_shortest_march">m</string>
-    <string name="month_shortest_april">a</string>
-    <string name="month_shortest_may">m</string>
-    <string name="month_shortest_june">j</string>
-    <string name="month_shortest_july">j</string>
-    <string name="month_shortest_august">a</string>
-    <string name="month_shortest_september">s</string>
-    <string name="month_shortest_october">o</string>
-    <string name="month_shortest_november">n</string>
-    <string name="month_shortest_december">d</string>
-
-    <string name="day_of_week_long_sunday">diumenge</string>
-    <string name="day_of_week_long_monday">dilluns</string>
-    <string name="day_of_week_long_tuesday">dimarts</string>
-    <string name="day_of_week_long_wednesday">dimecres</string>
-    <string name="day_of_week_long_thursday">dijous</string>
-    <string name="day_of_week_long_friday">divendres</string>
-    <string name="day_of_week_long_saturday">dissabte</string>
-
-    <string name="day_of_week_medium_sunday">dg.</string>
-    <string name="day_of_week_medium_monday">dl.</string>
-    <string name="day_of_week_medium_tuesday">dt.</string>
-    <string name="day_of_week_medium_wednesday">dc.</string>
-    <string name="day_of_week_medium_thursday">dj.</string>
-    <string name="day_of_week_medium_friday">dv.</string>
-    <string name="day_of_week_medium_saturday">ds.</string>
-
-    <string name="day_of_week_short_sunday">dg.</string>
-    <string name="day_of_week_short_monday">dl.</string>
-    <string name="day_of_week_short_tuesday">dt.</string>
-    <string name="day_of_week_short_wednesday">dc.</string>
-    <string name="day_of_week_short_thursday">dj.</string>
-    <string name="day_of_week_short_friday">dv.</string>
-    <string name="day_of_week_short_saturday">ds.</string>
-
-    <string name="day_of_week_shortest_sunday">g</string>
-    <string name="day_of_week_shortest_monday">l</string>
-    <string name="day_of_week_shortest_tuesday">t</string>
-    <string name="day_of_week_shortest_wednesday">c</string>
-    <string name="day_of_week_shortest_thursday">j</string>
-    <string name="day_of_week_shortest_friday">v</string>
-    <string name="day_of_week_shortest_saturday">s</string>
-
-    <string name="am">a.m.</string>
-    <string name="pm">p.m.</string>
-    <string name="yesterday">ahir</string>
-    <string name="today">avui</string>
-    <string name="tomorrow">demà</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
@@ -99,13 +9,13 @@
     <string name="numeric_date">%d/%m/%Y</string>
     <string name="numeric_date_format">dd/MM/yyyy</string>
     <string name="numeric_date_template">"%s/%s/%s"</string>
-    <string name="month_day_year">%-e de %B de %Y</string>
+    <string name="month_day_year">%-e %B de %Y</string>
     <string name="time_of_day">%-k:%M:%S</string>
     <string name="date_and_time">%-k:%M:%S %d/%m/%Y</string>
     <string name="date_time">%2$s %1$s</string>
     <string name="time_date">%1$s %3$s</string>
     <string name="abbrev_month_day_year">%d/%m/%Y</string>
-    <string name="month_day">%-e de %B</string>
+    <string name="month_day">%-e %B</string>
     <string name="month">%-B</string>
     <string name="month_year">%-B del %Y</string>
     <string name="abbrev_month_day">%-e %b</string>
@@ -127,24 +37,24 @@
     <string name="time_wday_date">%1$s %2$s %3$s</string>
     <string name="wday_date">%2$s %3$s</string>
     <string name="time_wday">%1$s %2$s</string>
-    <string name="same_year_md1_md2">%3$s de %2$s - %8$s de %7$s</string>
+    <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
     <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s %3$s de %2$s - %10$s %8$s de %7$s</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s %3$s de %2$s - %10$s %8$s de %7$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
     <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
     <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s de %2$s de %4$s - %10$s %8$s de %7$s de %9$s</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s de %2$s de %4$s - %10$s %8$s de %7$s de %9$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s de %4$s - %10$s %8$s %7$s de %9$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s de %4$s - %10$s %8$s %7$s de %9$s</string>
     <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s - %10$s %6$s %8$s %7$s %9$s</string>
     <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s - %10$s %6$s %8$s %7$s %9$s</string>
     <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s - %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s-%8$s de %2$s</string>
+    <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
     <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
-    <string name="same_year_mdy1_mdy2">%3$s de %2$s - %8$s de %7$s de %9$s</string>
-    <string name="same_month_mdy1_mdy2">%3$s-%8$s de %2$s de %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s de %2$s - %6$s %8$s de %7$s de %9$s</string>
+    <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s de %9$s</string>
+    <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s de %9$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s de %9$s</string>
     <string name="short_format_month">%b</string>
-    <string name="full_wday_month_day_no_year">E d MMMM</string>
-    <string name="abbrev_wday_month_day_no_year">E d MMMM</string>
-    <string name="abbrev_wday_month_day_year">EEE d MMM y</string>
+    <string name="full_wday_month_day_no_year">EEEE d MMMM</string>
+    <string name="abbrev_wday_month_day_no_year">EEE d MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE d MMM yyyy</string>
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 711030c..fdc9506 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opcions del telèfon"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Bloqueig de pantalla"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Apaga"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Informe d\'error"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Crea informe d\'errors"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Es recopilarà informació sobre l\'estat actual del dispositiu, que s\'enviarà per correu electrònic. Passaran uns quants minuts des de l\'inici de l\'informe d\'errors fins al seu enviament, per la qual cosa et recomanem que tinguis paciència."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Mode silenciós"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"So desactivat"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"El so està activat"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Missatges"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Llegeix i escriu SMS, correus electrònics i altres missatges."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Informació personal"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Accés directe als contactes i al calendari emmagatzemat a la tauleta."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Accés directe als contactes i al calendari emmagatzemats al telèfon."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Accés directe a informació sobre tu, emmagatzemada a la targeta de contacte."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Informació social"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Accés directe a informació sobre els teus contactes i sobre les teves connexions socials."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"La teva ubicació"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Supervisa la teva ubicació física."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Comunicació de xarxa"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Accedeix a diverses funcions de xarxa."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Accés a dispositius i a xarxes mitjançant Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Configuració d\'àudio"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Canviar la configuració de l\'àudio."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Afectar la bateria"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Fer servir funcions que poden consumir bateria ràpidament."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Calendari"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Accés directe a calendaris i a esdeveniments."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Llegeix el diccionari de l\'usuari"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Llegeix paraules al diccionari de l\'usuari."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Escriu al diccionari de l\'usuari"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Afegeix paraules al diccionari de l\'usuari."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Marcadors i historial"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Accés directe a l\'historial de marcadors i de navegació."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarma"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Definir l\'alarma."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Bústia de veu"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Accés directe a la bústia de veu."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Micròfon"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Accés directe al micròfon per enregistrar àudio."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Càmera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Accés directe a la càmera per a la captura d\'imatges o de vídeos."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Informació de les aplicacions"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Capacitat d\'afectar el rendiment d\'altres aplicacions del dispositiu."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Fons de pantalla"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Canviar la configuració del fons de pantalla del dispositiu."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Rellotge"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Canviar l\'hora o la zona horària del dispositiu."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Barra d\'estat"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Canviar la configuració de la barra d\'estat del dispositiu."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Configuració de sincronització"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Accedir a la configuració de sincronització."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Comptes"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Accedeix als comptes disponibles."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Controls de maquinari"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Accés de nivell inferior i control del sistema."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Eines de desenvolupament"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funcions que només necessiten els desenvolupadors d\'aplicacions."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"IU d\'altres aplicacions"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Afectar la IU d\'altres aplicacions."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Emmagatzematge"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Accedeix a l\'emmag. USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Accedeix a la targeta SD."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permet que l\'aplicació rebi i processi missatges WAP. Aquest permís inclou la capacitat de controlar o de suprimir missatges que s\'han enviat al teu dispositiu sense mostrar-te\'ls."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"recupera les aplicacions en execució"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Permet que l\'aplicació recuperi informació sobre les tasques que s\'executen actualment i les que s\'han executat recentment. Aquesta acció pot permetre que l\'aplicació descobreixi informació sobre les aplicacions que s\'utilitzen al dispositiu."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interacciona entre usuaris"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permet que l\'aplicació dugui a terme accions en diferents usuaris del dispositiu. Les aplicacions malicioses poden fer servir aquest permís per infringir la protecció entre usuaris."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"llicència completa per interaccionar entre usuaris"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permet totes les interaccions possibles entre usuaris."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"gestió d\'usuaris"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permet que les aplicacions gestionin usuaris al dispositiu, incloses les consultes, la creació i la supressió."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recupera els detalls d\'aplicacions en execució"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permet que l\'aplicació recuperi informació detallada sobre les tasques que s\'estan executant actualment i que s\'han executat recentment. Les aplicacions malicioses poden descobrir informació privada sobre altres aplicacions."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"canvia l\'ordre de les aplicacions en execució"</string>
@@ -228,7 +272,7 @@
     <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"definició de la compatibilitat de pantalla"</string>
     <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Permet que l\'aplicació controli el mode de compatibilitat de pantalla d\'altres aplicacions. És possible que les aplicacions malicioses interrompin el comportament d\'altres aplicacions."</string>
     <string name="permlab_setDebugApp" msgid="3022107198686584052">"activa la depuració d\'aplicacions"</string>
-    <string name="permdesc_setDebugApp" msgid="4474512416299013256">"Permet que una aplicació activi la depuració per a una altra aplicació. Les aplicacions malicioses poden utilitzar aquesta funció per finalitzar altres aplicacions."</string>
+    <string name="permdesc_setDebugApp" msgid="4474512416299013256">"Permet que l\'aplicació activi la depuració d\'altra aplicació. Les aplicacions malicioses poden utilitzar aquest permís per interrompre l\'execució d\'altres aplicacions."</string>
     <string name="permlab_changeConfiguration" msgid="4162092185124234480">"canvi de la configuració de pantalla del sistema"</string>
     <string name="permdesc_changeConfiguration" msgid="4372223873154296076">"Permet que una aplicació canviï la configuració actual, com ara la configuració regional o la mida global del tipus de lletra."</string>
     <string name="permlab_enableCarMode" msgid="5684504058192921098">"activar el mode de cotxe"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Permet que l\'aplicació recuperi l\'estat intern del sistema. Les aplicacions malicioses poden recuperar una àmplia gamma d\'informació privada i de seguretat que normalment no haurien de necessitar mai."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"recuperació del contingut de la pantalla"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permet que l\'aplicació recuperi el contingut de la finestra activa. Les aplicacions malicioses poden recuperar el contingut de tota la finestra i examinar-ne tot el text, excepte les contrasenyes."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"activació temporal de l\'accessibilitat"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permet que una aplicació activi temporalment l\'accessibilitat al dispositiu. És possible que les aplicacions malicioses activin l\'accessibilitat sense el consentiment de l\'usuari."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"recupera informació de les finestres"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permet que una aplicació recuperi informació sobre les finestres del gestor de finestres. Aplicacions malicioses podrien recuperar informació dirigida a la utilització per part del sistema intern."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtra els esdeveniments"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Permet que una aplicació registri un filtre d\'entrada per a l\'emissió de tots els esdeveniments d\'usuari abans no s\'enviïn. Aplicacions malicioses podrien controlar la IU del sistema sense la intervenció de l\'usuari."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"augment de la pantalla"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Permet a una aplicació augmentar el contingut d\'una pantalla. Les aplicacions malicioses poden transformar el contingut de la pantalla de manera que el dispositiu no es pugui fer servir."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"apagar parcialment"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Posa el gestor d\'activitats en estat d\'apagada. No fa una apagada completa."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir els canvis d\'aplicació"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permet que l\'aplicació controli el nombre màxim de processos que s\'executaran. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"com fer que es tanquin les aplicacions en segon pla"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Permet que l\'aplicació controli si les activitats sempre finalitzen quan passen a segon pla. No es necessita mai per a les aplicacions normals."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"modificar les estadístiques de la bateria"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Permet que l\'aplicació modifiqui les estadístiques d\'ús dels components recopilades. No indicat per a les aplicacions normals."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"llegeix les estadístiques de la bateria"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permet que l\'aplicació llegeixi l\'ús de dades actual quan hi ha poca bateria. Pot permetre que l\'aplicació recopili informació detallada sobre les aplicacions que fas servir."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modifica les estadístiques de la bateria"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permet que l\'aplicació modifiqui les estadístiques d\'ús de la bateria recopilades. No ho poden fer servir les aplicacions normals."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controlar la còpia de seguretat i restauració del sistema"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Permet que l\'aplicació controli el mecanisme de còpia de seguretat i restauració del sistema. No indicat per a les aplicacions normals."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"confirmar una operació de còpia de seguretat completa o de restauració"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"visualitzar finestres no autoritzades"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Permet que l\'aplicació creï finestres que utilitzarà la interfície d\'usuari del sistema intern. No indicat per a les aplicacions normals."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"crida d\'altres aplicacions"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Permet que l\'aplicació mostri finestres d\'alerta del sistema. Algunes finestres d\'alerta poden ocupar tota la pantalla."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Permet que l\'aplicació dibuixi sobre les altres aplicacions o parts de la interfície d\'usuari. Pot interferir amb l\'ús de la interfície a qualsevol aplicació o canviar el que et sembla que estàs veient en altres aplicacions."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"modificar la velocitat d\'animacions global"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Permet que l\'aplicació canviï la velocitat d\'animació global (animacions més ràpides o lentes) en qualsevol moment."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"gestiona els testimonis d\'aplicacions"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Permet que les aplicacions creïn i gestionin els seus propis testimonis, evitant l\'ordre Z normal. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"bloqueig de la pantalla"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Permet a l\'aplicació bloquejar temporalment la pantalla per fer una transició de pantalla completa."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"prémer tecles i botons de control"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Permet que l\'aplicació lliuri els seus propis esdeveniments d\'entrada (tecles premudes, etc.) a d\'altres aplicacions. Les aplicacions malicioses poden utilitzar aquesta funció per controlar la tauleta."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Permet que l\'aplicació lliuri els seus propis esdeveniments d\'entrada (tecles premudes, etc.) a d\'altres aplicacions. Les aplicacions malicioses poden utilitzar aquesta funció per controlar el telèfon."</string>
@@ -286,7 +342,7 @@
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Permet al titular vincular amb la interfície de nivell superior d\'un servei de text (per exemple, SpellCheckerService). Les aplicacions normals mai no ho haurien de necessitar."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"vincula a un servei de VPN"</string>
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permet que el titular vinculi a la interfície de nivell superior d\'un servei de VPN. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
-    <string name="permlab_bindWallpaper" msgid="8716400279937856462">"vincular a un empaperat"</string>
+    <string name="permlab_bindWallpaper" msgid="8716400279937856462">"enllaça amb un fons de pantalla"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permet que el titular vinculi a la interfície de nivell superior d\'un fons de pantalla. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincula a un servei de widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permet que el titular vinculi a la interfície de nivell superior d\'un servei de widget. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"instal·la aplicacions directament"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Permet que l\'aplicació instal·li paquets d\'Android nous o actualitzats. Les aplicacions malicioses poden utilitzar aquesta funció per afegir aplicacions noves amb permisos eficaços de manera arbitrària."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"suprimeix totes les dades de memòria cau d\'aplicacions"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Permet que l\'aplicació alliberi emmagatzematge de la tauleta suprimint fitxers al directori de la memòria cau de l\'aplicació. Habitualment, l\'accés a processos del sistema és molt restringit."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Permet que l\'aplicació alliberi emmagatzematge del telèfon suprimint fitxers al directori de la memòria cau de l\'aplicació. Habitualment, l\'accés a processos del sistema és molt restringit."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Permet que l\'aplicació alliberi espai a la tauleta mitjançant la supressió de fitxers als directoris de la memòria cau d\'altres aplicacions. Això pot fer que altres aplicacions s\'iniciïn més a poc a poc, perquè han de tornar a recuperar les dades."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Permet que l\'aplicació alliberi espai al telèfon mitjançant la supressió de fitxers als directoris de la memòria cau d\'altres aplicacions. Això pot fer que altres aplicacions s\'iniciïn més a poc a poc, perquè han de tornar a recuperar les dades."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"mou els recursos de l\'aplicació"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Permet que l\'aplicació desplaci els recursos de l\'aplicació de suports interns a externs i viceversa."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"llegir dades de registre personals"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Permet que l\'aplicació accedeixi a ordres del proveïdor d\'ubicació addicionals. Aquesta acció pot permetre que l\'aplicació interfereixi amb el funcionament del GPS o d\'altres fonts d\'ubicació."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"permís per instal·lar un proveïdor d\'ubicacions"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Crea fonts d\'ubicació fictícies per provar o per instal·lar un proveïdor d\'ubicació nou. Aquesta acció permet que l\'aplicació substitueixi la ubicació o l\'estat que retornen altres fonts d\'ubicació, com ara el GPS o altres proveïdors d\'ubicació."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"ubicació precisa (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Accedeix a fonts d\'ubicació precises, com ara el Sistema de Posicionament Global (GPS) a la tauleta. Quan els serveis d\'ubicació estiguin disponibles i activats, aquest permís permet que l\'aplicació determini la teva ubicació precisa."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Accedeix a fonts d\'ubicació precises, com ara el Sistema de Posicionament Global (GPS) al telèfon. Quan els serveis d\'ubicació estiguin disponibles i activats, aquest permís permet que l\'aplicació determini la teva ubicació precisa."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"ubicació aproximada (basada en xarxa)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Accedeix a la ubicació aproximada des dels proveïdors d\'ubicació mitjançant fonts de xarxa, com ara torres de telefonia mòbil i Wi-Fi. Quan aquests serveis d\'ubicació estiguin disponibles i activats, aquest permís permet que l\'aplicació determini la teva ubicació aproximada."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"ubicació precisa (basada en GPS i xarxa)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Permet que l\'aplicació obtingui la teva ubicació precisa mitjançant un sistema de posicionament global (GPS) o fonts d\'ubicació de xarxa, com ara torres de telefonia mòbil i Wi-Fi. Aquests serveis d\'ubicació s\'han d\'activar i han d\'estar disponibles al dispositiu perquè l\'aplicació els pugui fer servir. Les aplicacions poden utilitzar aquestes dades per determinar aproximadament on et trobes i pot ser que consumeixin més bateria."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"ubicació aproximada (basada en xarxa)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Permet que l\'aplicació obtingui la teva ubicació aproximada. Aquesta ubicació prové dels serveis d\'ubicació que utilitzen fonts d\'ubicació de la xarxa, com ara torres de telefonia mòbil i Wi-Fi. Aquests serveis d\'ubicació s\'han d\'activar i han d\'estar disponibles al dispositiu perquè l\'aplicació els pugui fer servir. Les aplicacions poden utilitzar aquestes dades per determinar aproximadament on et trobes."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"accedir a SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Permet que l\'aplicació utilitzi funcions SurfaceFlinger de baix nivell."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"llegir la memòria intermèdia de marcs"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Permet que l\'aplicació llegeixi el contingut de la memòria intermèdia de marcs."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"configuració de les pantalles Wi-Fi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permet a l\'aplicació configurar-se i connectar-se a les pantalles Wi-Fi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"control de les pantalles Wi-Fi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permet a l\'aplicació controlar les funcions de baix nivell de les pantalles Wi-Fi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"canviar la configuració d\'àudio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permet que l\'aplicació modifiqui la configuració d\'àudio general, com ara el volum i l\'altaveu de sortida que es fa servir."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"enregistrar àudio"</string>
@@ -444,8 +503,8 @@
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permet que l\'aplicació accedeixi a les funcions de telèfon del dispositiu. Aquest permís permet que l\'aplicació determini el número de telèfon i els identificadors del dispositiu, si hi ha una trucada activa i el número remot connectat amb una trucada."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"evita que la tauleta entri en mode d\'inactivitat"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"impedir que el telèfon se suspengui"</string>
-    <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Permet que l\'aplicació impedeixi que la tauleta entri en mode d\'inactivitat."</string>
-    <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"Permet que l\'aplicació impedeixi que el telèfon entri en mode d\'inactivitat."</string>
+    <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Permet que l\'aplicació impedeixi que la tauleta entri en repòs."</string>
+    <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"Permet que l\'aplicació impedeixi que el telèfon entri en repòs."</string>
     <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"activa o desactiva la tauleta"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"engegar o apagar el telèfon"</string>
     <string name="permdesc_devicePower" product="tablet" msgid="6689862878984631831">"Permet que l\'aplicació encengui i apagui la tauleta."</string>
@@ -484,8 +543,8 @@
     <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"Permet que l\'aplicació pugui canviar la configuració de xarxa i interceptar i inspeccionar tot el trànsit de la xarxa, per exemple, canviar el servidor intermediari i el port de qualsevol APN. Les aplicacions malicioses poden controlar, redireccionar o modificar paquets de la xarxa sense el teu coneixement."</string>
     <string name="permlab_changeNetworkState" msgid="958884291454327309">"canviar la connectivitat de xarxa"</string>
     <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Permet que l\'aplicació pugui canviar l\'estat de connectivitat de la xarxa."</string>
-    <string name="permlab_changeTetherState" msgid="5952584964373017960">"Canvia la connectivitat de connexió compartida"</string>
-    <string name="permdesc_changeTetherState" msgid="1524441344412319780">"Permet a l\'aplicació canviar l\'estat de la connectivitat de les xarxes compartides."</string>
+    <string name="permlab_changeTetherState" msgid="5952584964373017960">"Canvia la connectivitat d\'ancoratge a xarxa"</string>
+    <string name="permdesc_changeTetherState" msgid="1524441344412319780">"Permet que l\'aplicació canviï l\'estat de la connectivitat de la xarxa d\'ancoratge."</string>
     <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"canviar la configuració d\'ús de dades de referència"</string>
     <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Permet que l\'aplicació canviï la configuració d\'ús de les dades de fons."</string>
     <string name="permlab_accessWifiState" msgid="5202012949247040011">"visualització de les connexions Wi-Fi"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"accés a la configuració de Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Permet que l\'aplicació configuri la tauleta Bluetooth local i que cerqui i sincronitzi dispositius remots."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permet que l\'aplicació configuri el telèfon Bluetooth local i que cerqui i sincronitzi dispositius remots."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Visualització de les connexions WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"connecta i desconnecta de WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permet que l\'aplicació determini si WiMAX està activat i que vegi la informació sobre totes les xarxes WiMAX que estan connectades."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Canvia l\'estat de WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permet que l\'aplicació connecti i desconnecti la tauleta de les xarxes WiMAX."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Permet que l\'aplicació modifiqui els feeds sincronitzats actualment. Les aplicacions malicioses poden canviar els teus feeds sincronitzats."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"lectura dels termes que afegeixes al diccionari"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Permet que l\'aplicació llegeixi les paraules, els noms i les frases que l\'usuari pot haver emmagatzemat al seu diccionari."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"escriu al diccionari definit per l\'usuari"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"afegeix paraules al diccionari definit per l\'usuari"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Permet que l\'aplicació escrigui paraules noves al diccionari de l\'usuari."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"accés de prova a emmagatzematge protegit"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"accés de prova a emmagatzematge protegit"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Permet que l\'aplicació provi un permís per a emmagatzematge USB que estarà disponible als dispositius en el futur."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Permet que l\'aplicació provi un permís per a emmagatzematge USB que estarà disponible a propers dispositius."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Permet que l\'aplicació provi un permís per a la targeta SD que estarà disponible als dispositius en el futur."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modificació o supressió del contingut de l\'emmagatzematge USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modifica o suprimeix el contingut de la targeta SD"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Permet a l\'aplicació escriure a la targeta SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"Canvia/esborra emmagatz. intern"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Permet que l\'aplicació modifiqui el contingut de l\'emmagatzematge multimèdia intern."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"accedeix a l\'emmagatzematge extern per a tots els usuaris"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Permet que l\'aplicació accedeixi a l\'emmagatzematge extern per a tots els usuaris."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"accedir al sistema de fitxers de la memòria cau"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permet que l\'aplicació llegeixi el sistema de fitxers de la memòria cau i que hi escrigui."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"fer/rebre trucades per Internet"</string>
@@ -546,24 +607,26 @@
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permet que l\'aplicació modifiqui la manera com es calcula l\'ús de la xarxa per part de les aplicacions. No indicat per a les aplicacions normals."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Defineix les normes de contrasenya"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controla la longitud i els caràcters permesos a les contrasenyes de desbloqueig de pantalla."</string>
-    <string name="policylab_watchLogin" msgid="914130646942199503">"Supervisa els intents de desbloqueig de la pantalla"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Control d\'intents de desbloqueig de pantalla"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja la tauleta o n\'esborra totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string>
     <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Supervisa el nombre de contrasenyes incorrectes introduïdes en desbloquejar la pantalla, i bloqueja el telèfon o esborra totes les dades del telèfon si s\'introdueixen massa contrasenyes incorrectes."</string>
     <string name="policylab_resetPassword" msgid="2620077191242688955">"Canvia la contrasenya de desbloqueig de pantalla"</string>
     <string name="policydesc_resetPassword" msgid="605963962301904458">"Canvia la contrasenya de desbloqueig de pantalla."</string>
-    <string name="policylab_forceLock" msgid="2274085384704248431">"Bloqueja la pantalla"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Bloqueig de pantalla"</string>
     <string name="policydesc_forceLock" msgid="1141797588403827138">"Controla com i quan es bloqueja la pantalla."</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Esborra totes les dades"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Esborra les dades de la tauleta sense advertiment mitjançant un restabliment de les dades de fàbrica."</string>
     <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Esborra les dades del telèfon sense advertiment mitjançant un restabliment de les dades de fàbrica."</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Defineix el servidor intermediari global del dispositiu"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Defineix el servidor intermediari global del dispositiu que cal utilitzar mentre la política estigui activada. Només el primer administrador del dispositiu pot definir el servidor intermediari global efectiu."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Defineix la caducitat de la contrasenya de bloqueig de pantalla"</string>
+    <string name="policylab_expirePassword" msgid="885279151847254056">"Defineix caducitat de bloqueig de pantalla"</string>
     <string name="policydesc_expirePassword" msgid="1729725226314691591">"Controla la freqüència amb què cal canviar la contrasenya de bloqueig de pantalla."</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Encriptació d’emmagatzematge"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Requereix que les dades de l\'aplicació emmagatzemades estiguin encriptades."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Desactiva les càmeres"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Impedeix l\'ús de totes les càmeres del dispositiu."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Des. funcions en bloq. tecles"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Impedeix l\'ús d\'algunes funcions en bloqueig de tecles."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Mòbil"</item>
@@ -674,7 +737,7 @@
     <string name="relationTypeSister" msgid="1735983554479076481">"Germana"</string>
     <string name="relationTypeSpouse" msgid="394136939428698117">"Cònjuge"</string>
     <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Personalitzada"</string>
-    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Particular"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Casa"</string>
     <string name="sipAddressTypeWork" msgid="6920725730797099047">"Feina"</string>
     <string name="sipAddressTypeOther" msgid="4408436162950119849">"Altres"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Introdueix el codi PIN"</string>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Torna-ho a provar"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"S\'ha superat el nombre màxim d\'intents de desbloqueig facial"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"S\'està carregant, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Carregada."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Carregada"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Connecteu el carregador."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"No hi ha cap targeta SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"No hi ha cap targeta SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No hi ha cap targeta SIM a la tauleta."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No hi ha cap targeta SIM al telèfon."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Insereix una targeta SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Patró esborrat"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"S\'ha afegit una cel·la"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Patró completat"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Afegeix un widget"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Buit"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"S\'ha ampliat l\'àrea de desbloqueig."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"L\'àrea de desbloqueig està replegada."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Widget de <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Selector d\'usuaris"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Estat"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Càmera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Controls multimèdia"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"S\'ha iniciat la reorganització del widget."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Ha finalitzat la reorganització del widget."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"S\'ha suprimit el widget de <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Amplia l\'àrea de desbloqueig."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Desbloqueig lliscant el dit"</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueig mitjançant patró"</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Desbloqueig facial"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueig mitjançant PIN"</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueig mitjançant contrasenya"</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Àrea de patró"</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Àrea per lliscar el dit"</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -821,9 +904,9 @@
     <string name="searchview_description_clear" msgid="1330281990951833033">"Neteja la consulta"</string>
     <string name="searchview_description_submit" msgid="2688450133297983542">"Envia la consulta"</string>
     <string name="searchview_description_voice" msgid="2453203695674994440">"Cerca per veu"</string>
-    <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"Vols activar l\'Exploració per tacte?"</string>
-    <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vol activar l\'Exploració per tacte. Quan l\'Exploració per tacte està activada, pots escoltar o veure les descripcions del que hi ha sota el dit o fer gestos per interactuar amb la tauleta."</string>
-    <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vol activar l\'Exploració per tacte. Quan l\'Exploració per tacte està activada, pots escoltar o veure les descripcions del que hi ha sota el dit o fer gestos per interactuar amb el telèfon."</string>
+    <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"Vols activar l\'exploració tàctil?"</string>
+    <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vol activar l\'exploració tàctil. Quan l\'exploració tàctil està activada, pots escoltar o veure les descripcions del contingut seleccionat o utilitzar gestos per interactuar amb la tauleta."</string>
+    <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vol activar l\'exploració tàctil. Quan l\'exploració per tàctil està activada, pots escoltar o veure les descripcions del contingut seleccionat o utilitzar gestos per interactuar amb el telèfon."</string>
     <string name="oneMonthDurationPast" msgid="7396384508953779925">"Fa 1 mes"</string>
     <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Fa menys d\'1 mes"</string>
   <plurals name="num_seconds_ago">
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copia l\'URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Selecciona el text"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selecció de text"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"afegeix al diccionari"</string>
-    <string name="deleteText" msgid="7070985395199629156">"suprimeix"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Afegeix al diccionari"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Suprimeix"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Mètode d\'entrada"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Accions de text"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"S\'està acabant l\'espai d\'emmagatzematge"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Xarxes Wi-fi obertes disponibles"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Inicia la sessió a la xarxa Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Inicia la sessió a la xarxa"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"No s\'ha pogut connectar a la Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" té una mala connexió a Internet."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Per a:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Introdueix el PIN sol·licitat:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"El telèfon es desconnectarà temporalment de la Wi-Fi mentre estigui connectat a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Insereix un caràcter"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"S\'estan enviant missatges SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; està enviant molts missatges SMS. Vols permetre que aquesta aplicació continuï enviant missatges?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Permet"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Denega"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vol enviar un missatge a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Aquesta acció "<font fgcolor="#ffffb060">"pot fer que s\'apliquin càrrecs"</font>" al compte del mòbil."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Aquesta acció farà que s\'apliquin càrrecs al compte del mòbil."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Envia"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Cancel·la"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Recorda la meva selecció"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Pots canviar aquesta opció més endavant a Configuració &gt; Aplicacions"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Permet sempre"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"No permetis mai"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Extracció de la targeta SIM"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"La xarxa de telefonia mòbil no estarà disponible fins que no reiniciïs amb una targeta SIM vàlida inserida."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Fet"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Establiment de data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Defineix"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Fet"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Predeterminat"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"No cal cap permís"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Amaga"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostra\'ls tots"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NOU: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NOU: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Proporcionat per <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"No cal cap permís"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"pot ser que comporti càrrecs"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Emmagatzematge massiu USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB connectat"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"T\'has connectat a l\'equip mitjançant USB. Toca el botó següent si vols copiar els fitxers entre l\'equip i l\'emmagatzematge USB d\'Android."</string>
@@ -1069,19 +1161,19 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="5100428757107469454">"Si actives l\'emmagatzematge USB, algunes de les aplicacions que utilitzes s\'aturaran i pot ser que no estiguin disponibles fins que no desactivis l\'emmagatzematge USB."</string>
     <string name="dlg_error_title" msgid="7323658469626514207">"S\'ha produït un error amb l\'operació de l\'USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"D\'acord"</string>
-    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connectat com a dispositiu multimèdia"</string>
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connectat com a disp. multimèdia"</string>
     <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Connectat com a càmera"</string>
     <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Connectat com a instal·lador"</string>
     <string name="usb_accessory_notification_title" msgid="7848236974087653666">"Connectat a un accessori USB"</string>
-    <string name="usb_notification_message" msgid="2290859399983720271">"Toca per obtenir altres opcions d\'USB."</string>
+    <string name="usb_notification_message" msgid="2290859399983720271">"Toca per accedir a altres opcions d\'USB."</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="9020092196061007262">"Formata l\'emmagatzematge USB"</string>
     <string name="extmedia_format_title" product="default" msgid="3648415921526526069">"Vols formatar la targeta SD?"</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="3934016853425761078">"S\'esborraran tots els fitxers emmagatzemats al dispositiu d\'emmagatzematge USB. Aquesta acció no es pot desfer."</string>
     <string name="extmedia_format_message" product="default" msgid="14131895027543830">"Es perdran totes les dades d\'aquesta targeta."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formata"</string>
-    <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuració d\'USB connectada"</string>
-    <string name="adb_active_notification_message" msgid="1016654627626476142">"Toca-ho per desactivar la depuració USB."</string>
-    <string name="select_input_method" msgid="4653387336791222978">"Selecció de mètodes d\'introducció"</string>
+    <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuració USB activada"</string>
+    <string name="adb_active_notification_message" msgid="1016654627626476142">"Toca per desactivar la depuració USB."</string>
+    <string name="select_input_method" msgid="4653387336791222978">"Selecciona un mètodes d\'entrada"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Configura els mètodes d\'entrada"</string>
     <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclat físic"</string>
     <string name="hardware" msgid="7517821086888990278">"Maquinari"</string>
@@ -1142,18 +1234,22 @@
     <string name="sync_binding_label" msgid="3687969138375092423">"Sincronització"</string>
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibilitat"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fons de pantalla"</string>
-    <string name="chooser_wallpaper" msgid="7873476199295190279">"Canvi de l\'empaperat"</string>
+    <string name="chooser_wallpaper" msgid="7873476199295190279">"Canvia el fons de pantalla"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ha activat VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca per gestionar la xarxa."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Connectat a <xliff:g id="SESSION">%s</xliff:g>. Toca per gestionar la xarxa."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"T\'estàs connectant a la VPN sempre activada…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Estàs connectat a la VPN sempre activada"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Error de la VPN sempre activada"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Toca per restablir la connexió"</string>
     <string name="upload_file" msgid="2897957172366730416">"Trieu un fitxer"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"No s\'ha escollit cap fitxer"</string>
     <string name="reset" msgid="2448168080964209908">"Reinicia"</string>
     <string name="submit" msgid="1602335572089911941">"Envia"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Mode de cotxe activat"</string>
     <string name="car_mode_disable_notification_message" msgid="8035230537563503262">"Toca per sortir del mode de cotxe."</string>
-    <string name="tethered_notification_title" msgid="3146694234398202601">"Ancoratge a la xarxa o punt de connexió actiu"</string>
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Ancoratge a la xarxa o zona Wi-Fi activat"</string>
     <string name="tethered_notification_message" msgid="6857031760103062982">"Toca per configurar."</string>
     <string name="back_button_label" msgid="2300470004503343439">"Enrere"</string>
     <string name="next_button_label" msgid="1080555104677992408">"Següent"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Comparteix"</string>
     <string name="find" msgid="4808270900322985960">"Cerca"</string>
     <string name="websearch" msgid="4337157977400211589">"Cerca al web"</string>
+    <string name="find_next" msgid="5742124618942193978">"Cerca el següent"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Cerca l\'anterior"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Sol·licitud d\'ubicació de <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Sol·licitud d\'ubicació"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Sol·licitat per <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1196,7 +1294,7 @@
     <string name="sync_undo_deletes" msgid="2941317360600338602">"Desfés les supressions"</string>
     <string name="sync_do_nothing" msgid="3743764740430821845">"No facis res per ara"</string>
     <string name="choose_account_label" msgid="5655203089746423927">"Tria un compte"</string>
-    <string name="add_account_label" msgid="2935267344849993553">"Addició d\'un compte"</string>
+    <string name="add_account_label" msgid="2935267344849993553">"Afegeix un compte"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Afegeix un compte"</string>
     <string name="number_picker_increment_button" msgid="2412072272832284313">"Incrementa"</string>
     <string name="number_picker_decrement_button" msgid="476050778386779067">"Redueix"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telèfon"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auriculars"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altaveus del connector"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Àudio HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Àudio per Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fet"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Sortida de contingut multimèdia"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"S\'està explorant..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"S\'està connectant..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Disponible"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"No disponible"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Pantalla integrada"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Pantalla HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Superposa #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"La pantalla sense fil està connectada"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Aquesta pantalla es mostra en un altre dispositiu"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Desconnecta"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Trucada d\'emergència"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Patró oblidat"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Patró incorrecte"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Contrasenya incorrecta"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN incorrecte"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Torna-ho a provar d\'aquí a <xliff:g id="NUMBER">%d</xliff:g> segons."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Dibuixa el patró"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Introdueix el PIN de la SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Introdueix el PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Introdueix la contrasenya"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"La SIM està desactivada. Introdueix el codi PUK per continuar. Contacta amb l\'operador de telefonia mòbil per obtenir detalls."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Introdueix el codi PIN"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Confirma el codi PIN"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"S\'està desbloquejant la targeta SIM..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Codi PIN incorrecte."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Escriu un PIN que tingui de 4 a 8 números."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"El codi PUK ha de tenir 8 números o més."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Torna a introduir el codi PUK correcte. Els intents repetits faran que es desactivi la SIM de manera permanent."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Els codis PIN no coincideixen"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Massa intents incorrectes"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Per desbloquejar el telèfon, inicia la sessió amb el compte de Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Nom d\'usuari (correu electrònic)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Contrasenya"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Inicia la sessió"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Nom d\'usuari o contrasenya no vàlids."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Has oblidat el teu nom d\'usuari o la contrasenya?"\n"Visita "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"S\'està comprovant el compte…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Has escrit malament el PIN <xliff:g id="NUMBER_0">%d</xliff:g> vegades. "\n\n"Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%d</xliff:g> segons."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Has escrit malament la contrasenya <xliff:g id="NUMBER_0">%d</xliff:g> vegades. "\n\n"Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%d</xliff:g> segons."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Has dibuixat el patró de desbloqueig de manera incorrecta <xliff:g id="NUMBER_0">%d</xliff:g> vegades. "\n\n"Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%d</xliff:g> segons."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER_0">%d</xliff:g> vegades de manera incorrecta. D\'aquí a <xliff:g id="NUMBER_1">%d</xliff:g> intents incorrectes més, la tauleta es restablirà a la configuració predeterminada de fàbrica i es perdran totes les dades dels usuaris."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER_0">%d</xliff:g> vegades de manera incorrecta. D\'aquí a <xliff:g id="NUMBER_1">%d</xliff:g> intents incorrectes més, el telèfon es restablirà a la configuració predeterminada de fàbrica i es perdran totes les dades dels usuaris."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. Ara la tauleta es restablirà a la configuració predeterminada de fàbrica."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. Ara el telèfon es restablirà a la configuració predeterminada de fàbrica."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%d</xliff:g> vegades de manera incorrecta. Després de <xliff:g id="NUMBER_1">%d</xliff:g> intents incorrectes més, se\'t demanarà que desbloquegis la tauleta amb un compte de correu electrònic."\n\n" Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%d</xliff:g> segons."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%d</xliff:g> vegades de manera incorrecta. Després de <xliff:g id="NUMBER_1">%d</xliff:g> intents incorrectes més, se\'t demanarà que desbloquegis el telèfon amb un compte de correu electrònic."\n\n" Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%d</xliff:g> segons."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Elimina"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Vols augmentar el volum per sobre del nivell de seguretat?"\n"Escoltar música a un volum alt durant períodes llargs pot perjudicar l\'oïda."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Mantén premuts els dos dits per activar l\'accessibilitat."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"S\'ha activat l\'accessibilitat."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Accessibilitat cancel·lada."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Usuari actual: <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Propietari"</string>
 </resources>
diff --git a/core/res/res/values-cs/donottranslate-cldr.xml b/core/res/res/values-cs/donottranslate-cldr.xml
index 59b82d3..ff7902d 100644
--- a/core/res/res/values-cs/donottranslate-cldr.xml
+++ b/core/res/res/values-cs/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">leden</string>
-    <string name="month_long_standalone_february">únor</string>
-    <string name="month_long_standalone_march">březen</string>
-    <string name="month_long_standalone_april">duben</string>
-    <string name="month_long_standalone_may">květen</string>
-    <string name="month_long_standalone_june">červen</string>
-    <string name="month_long_standalone_july">červenec</string>
-    <string name="month_long_standalone_august">srpen</string>
-    <string name="month_long_standalone_september">září</string>
-    <string name="month_long_standalone_october">říjen</string>
-    <string name="month_long_standalone_november">listopad</string>
-    <string name="month_long_standalone_december">prosinec</string>
-
-    <string name="month_long_january">ledna</string>
-    <string name="month_long_february">února</string>
-    <string name="month_long_march">března</string>
-    <string name="month_long_april">dubna</string>
-    <string name="month_long_may">května</string>
-    <string name="month_long_june">června</string>
-    <string name="month_long_july">července</string>
-    <string name="month_long_august">srpna</string>
-    <string name="month_long_september">září</string>
-    <string name="month_long_october">října</string>
-    <string name="month_long_november">listopadu</string>
-    <string name="month_long_december">prosince</string>
-
-    <string name="month_medium_january">1.</string>
-    <string name="month_medium_february">2.</string>
-    <string name="month_medium_march">3.</string>
-    <string name="month_medium_april">4.</string>
-    <string name="month_medium_may">5.</string>
-    <string name="month_medium_june">6.</string>
-    <string name="month_medium_july">7.</string>
-    <string name="month_medium_august">8.</string>
-    <string name="month_medium_september">9.</string>
-    <string name="month_medium_october">10.</string>
-    <string name="month_medium_november">11.</string>
-    <string name="month_medium_december">12.</string>
-
-    <string name="month_shortest_january">l</string>
-    <string name="month_shortest_february">ú</string>
-    <string name="month_shortest_march">b</string>
-    <string name="month_shortest_april">d</string>
-    <string name="month_shortest_may">k</string>
-    <string name="month_shortest_june">č</string>
-    <string name="month_shortest_july">č</string>
-    <string name="month_shortest_august">s</string>
-    <string name="month_shortest_september">z</string>
-    <string name="month_shortest_october">ř</string>
-    <string name="month_shortest_november">l</string>
-    <string name="month_shortest_december">p</string>
-
-    <string name="day_of_week_long_sunday">neděle</string>
-    <string name="day_of_week_long_monday">pondělí</string>
-    <string name="day_of_week_long_tuesday">úterý</string>
-    <string name="day_of_week_long_wednesday">středa</string>
-    <string name="day_of_week_long_thursday">čtvrtek</string>
-    <string name="day_of_week_long_friday">pátek</string>
-    <string name="day_of_week_long_saturday">sobota</string>
-
-    <string name="day_of_week_medium_sunday">ne</string>
-    <string name="day_of_week_medium_monday">po</string>
-    <string name="day_of_week_medium_tuesday">út</string>
-    <string name="day_of_week_medium_wednesday">st</string>
-    <string name="day_of_week_medium_thursday">čt</string>
-    <string name="day_of_week_medium_friday">pá</string>
-    <string name="day_of_week_medium_saturday">so</string>
-
-    <string name="day_of_week_short_sunday">ne</string>
-    <string name="day_of_week_short_monday">po</string>
-    <string name="day_of_week_short_tuesday">út</string>
-    <string name="day_of_week_short_wednesday">st</string>
-    <string name="day_of_week_short_thursday">čt</string>
-    <string name="day_of_week_short_friday">pá</string>
-    <string name="day_of_week_short_saturday">so</string>
-
-    <string name="day_of_week_shortest_sunday">N</string>
-    <string name="day_of_week_shortest_monday">P</string>
-    <string name="day_of_week_shortest_tuesday">Ú</string>
-    <string name="day_of_week_shortest_wednesday">S</string>
-    <string name="day_of_week_shortest_thursday">Č</string>
-    <string name="day_of_week_shortest_friday">P</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">dop.</string>
-    <string name="pm">odp.</string>
-    <string name="yesterday">Včera</string>
-    <string name="today">Dnes</string>
-    <string name="tomorrow">Zítra</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index c026ecd..374a6d5 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Možnosti telefonu"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Zámek obrazovky"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Vypnout"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Hlášení chyb"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Zaznamenat zprávu o chybě"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Shromažďuje informace o aktuálním stavu zařízení. Tyto informace je následně možné poslat v e-mailové zprávě, chvíli však potrvá, než bude hlášení o chybě připraveno k odeslání. Buďte prosím trpěliví."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Tichý režim"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Zvuk je VYPNUTÝ."</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Zvuk je zapnutý"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Vaše zprávy"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Čtení a zápis zpráv SMS, e-mailů a dalších zpráv."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Vaše osobní informace"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Přímý přístup k vašim kontaktům a kalendáři v tabletu."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Přímý přístup k vašim kontaktům a kalendáři v telefonu."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Přímý přístup k informacím o vás uložených na vaší vizitce"</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Informace o vašich kontaktech a sociálních sítích"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Přímý přístup k informacím o vašich kontaktech a sociálních propojeních"</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Vaše poloha"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Sledovat vaši fyzickou polohu."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Síťová komunikace"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Přístup k různým funkcím sítě."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Přístup do zařízení a k sítím prostřednictvím rozhraní Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Nastavení zvuku"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Změna nastavení zvuku"</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Vliv na baterii"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Používání funkcí, které mohou rychle vyčerpat baterii"</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalendář"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Přímý přístup ke kalendáři a událostem"</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Čtení uživatelského slovníku"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Čtení slov v uživatelském slovníku."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Zápis do uživatelského slovníku"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Přidávání slov do uživatelského slovníku."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Záložky a historie"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Přímý přístup k záložkám a historii prohlížení"</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Budík"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Nastavení budíku"</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Hlasová schránka"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Přímý přístup do hlasové schránky"</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Přímý přístup k mikrofonu a možnost nahrávání zvuku"</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Fotoaparát"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Přímý přístup k fotoaparátu a možnost pořizování fotografií a videí"</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Informace o vašich aplikacích"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Možnost ovlivnit chování dalších aplikací v zařízení"</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Tapeta"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Změna nastavení tapety zařízení"</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Hodiny"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Změna času nebo časového pásma zařízení"</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Stavový řádek"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Změna nastavení stavového řádku zařízení"</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Synchronizace"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Přístup k nastavení synchronizace"</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Vaše účty"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Přístup k dostupným účtům."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Řízení hardwaru"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Nízkoúrovňový přístup a kontrola nad systémem."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Nástroje pro vývojáře"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funkce pouze pro vývojáře aplikací."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Uživatelské rozhraní dalších aplikací"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Vliv na uživatelské rozhraní dalších aplikací"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Úložiště"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Přístup do úložiště USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Přístup ke kartě SD."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Umožňuje aplikaci přijmout a zpracovat zprávy WAP. Toto oprávnění umožňuje sledovat přijaté zprávy nebo je smazat, aniž by se vám zobrazily."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"načtení spuštěných aplikací"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Umožňuje aplikaci získat informace o aktuálně a naposledy spuštěných úlohách. Aplikace s tímto oprávněním může odhalit informace o aplikacích, které se v zařízení používají."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interakce napříč uživateli"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Umožňuje aplikaci provádět akce napříč různými uživateli zařízení. Škodlivé aplikace toto oprávnění mohou zneužít k obejití ochrany mezi uživateli."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"úplné oprávnění k interakcím napříč uživateli"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Povoluje všechny možné interakce napříč uživateli."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"správa uživatelů"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Umožňuje aplikacím spravovat uživatele v zařízení, včetně vytváření a mazání dotazů."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"získání podrobností o spuštěných aplikacích"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Umožňuje aplikaci získat podrobné informace o aktuálně a naposledy spuštěných úlohách. Škodlivé aplikace mohou odhalit soukromé informace o ostatních aplikacích."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"změna uspořádání spuštěných aplikací"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Umožňuje aplikaci získat informace o vnitřním stavu systému. Škodlivé aplikace mohou získat různé soukromé informace nebo informace o zabezpečení, které by běžně vůbec neměly potřebovat."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"načtení obsahu obrazovky"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Umožňuje aplikaci načíst obsah aktivního okna. Škodlivé aplikace mohou načíst obsah celého okna a prozkoumat všechen text kromě hesel."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"dočasná aktivace usnadnění přístupu"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Umožňuje aplikaci dočasně aktivovat usnadnění přístupu v zařízení. Škodlivé aplikace mohou usnadnění přístupu aktivovat bez souhlasu uživatele."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"načítání informací o oknech"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Umožňuje aplikaci načíst informace o oknech ze správce oken. Škodlivé aplikace mnohou načíst informace, které slouží k internímu systémovému využití."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrování událostí"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Umožní aplikaci registrovat vstupní filtr, který filtruje stream všech uživatelských přenosů před jejich odvysíláním. Škodlivé aplikace mohou používat uživatelské rozhraní systému bez zásahu uživatele."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"zvětšit zobrazení"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Povoluje aplikaci zvětšit obsah displeje. Škodlivé aplikace mohou změnit zobrazení obsahu způsobem, který učiní zařízení nepoužitelným."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"částečné vypnutí"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Uvede správce činností do vypnutého stavu. Nedojde však k úplnému vypnutí."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zabránění přepínání aplikací"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Umožňuje aplikaci řídit maximální počet spuštěných procesů. Běžné aplikace toto oprávnění nikdy nepotřebují."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"vynucení zavření aplikací na pozadí"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Umožňuje aplikaci ovládat, zda budou činnosti po přechodu na pozadí vždy ukončeny. Běžné aplikace toto oprávnění nikdy nepožadují."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"změna statistických údajů o baterii"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Umožňuje aplikaci upravit shromážděné statistiky o baterii. Toto oprávnění není určeno pro běžné aplikace."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"čtení statistických údajů o baterii"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Umožňuje aplikaci číst aktuální podrobné údaje o využití baterie. Aplikace to může využít k získání podrobných informací o tom, které aplikace používáte."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"změna statistických údajů o baterii"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Umožňuje aplikaci upravit shromážděné statistiky o baterii. Toto oprávnění není určeno pro běžné aplikace."</string>
     <string name="permlab_backup" msgid="470013022865453920">"ovládání zálohování a obnovy systému"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Umožňuje aplikaci řídit mechanismy zálohování a obnovení systému. Toto oprávnění není určeno pro běžné aplikace."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"potvrzení operace úplné zálohy nebo úplného obnovení"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"zobrazení nepovolených oken"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Umožňuje aplikaci vytvářet okna, která se budou používat v interním uživatelském rozhraní systému. Toto oprávnění není určeno pro běžné aplikace."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"kreslení přes další aplikace"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Umožňuje aplikaci zobrazit okna s výstrahami systému. Některá okna s výstrahami mohou převzít kontrolu nad celou obrazovkou."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Umožňuje aplikaci využívat jiné aplikace nebo části uživatelského rozhraní. Aplikace tak může zasahovat do používání rozhraní jakékoli aplikace a měnit rozhraní zobrazené v jiných aplikacích."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"změna globální rychlosti animace"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Umožňuje aplikaci kdykoliv globálně změnit rychlost animací (rychlejší či pomalejší animace)."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"správa klíčů aplikací"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Umožňuje aplikaci vytvořit a spravovat vlastní klíče a současně obejít pořadí vykreslování. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"zmrazit obrazovku"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Povoluje aplikaci dočasně zmrazit obrazovku pro přechod do režimu celé obrazovky."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"používání kláves a tlačítek"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Umožňuje aplikaci doručit vlastní vstupní události (stisknutí tlačítek atd.) dalším aplikacím. Škodlivé aplikace mohou pomocí tohoto oprávnění převzít kontrolu nad tabletem."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Umožňuje aplikaci doručit vlastní vstupní události (stisknutí tlačítek atd.) dalším aplikacím. Škodlivé aplikace mohou pomocí tohoto oprávnění převzít kontrolu nad telefonem."</string>
@@ -314,11 +370,11 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"přímá instalace aplikací"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Umožňuje aplikaci instalovat nové nebo aktualizované balíčky Android. Škodlivé aplikace mohou toto oprávnění použít k přidání nových aplikací s libovolně silnými oprávněními."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"smazání všech dat v mezipaměti aplikace"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Umožňuje aplikaci uvolnit úložiště tabletu smazáním souborů ze složky mezipaměti aplikace. Přístup je velmi omezen, obvykle jen na systémové procesy."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Umožňuje aplikaci uvolnit úložiště telefonu smazáním souborů ze složky mezipaměti aplikace. Přístup je velmi omezen, obvykle jen na systémové procesy."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Umožňuje aplikaci uvolnit úložiště v tabletu tím, že smaže soubory ve složkách mezipaměti jiných aplikací. To může způsobit, že se jiné aplikace budou spouštět pomaleji, protože budou potřebovat znovu načíst data."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Umožňuje aplikaci uvolnit úložiště v telefonu tím, že smaže soubory ve složkách mezipaměti jiných aplikací. To může způsobit, že se jiné aplikace budou spouštět pomaleji, protože budou potřebovat znovu načíst data."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"přesun zdrojů aplikace"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Umožňuje aplikaci přesunout zdroje aplikace z interního média do externího a naopak."</string>
-    <string name="permlab_readLogs" msgid="6615778543198967614">"číst citlivá data v protokolech"</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"čtení citlivých dat v protokolech"</string>
     <string name="permdesc_readLogs" product="tablet" msgid="82061313293455151">"Umožňuje aplikaci číst různé systémové soubory protokolů. Toto oprávnění aplikaci umožní získat obecné informace o činnostech s tabletem, které by mohly obsahovat osobní či soukromé informace."</string>
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Umožňuje aplikaci číst různé systémové soubory protokolů. Toto oprávnění aplikaci umožní získat obecné informace o činnostech s telefonem, které by mohly obsahovat osobní či soukromé informace."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"použít jakýkoliv dekodér pro přehrávání médií"</string>
@@ -364,10 +420,10 @@
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Umožňuje aplikaci získat přístup k sociálním aktualizacím od vašich přátel a synchronizaci těchto aktualizací. Při sdílení informací buďte opatrní – toto oprávnění umožňuje aplikaci číst komunikaci mezi vámi a vašimi přáteli v sociálních sítích bez ohledu na její důvěrnost. Poznámka: Toto oprávnění nemusí platit pro všechny sociální sítě."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"zapisovat do vašeho sociálního streamu"</string>
     <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Umožňuje aplikaci zobrazit sociální aktualizace od vašich přátel. Při sdílení informací buďte opatrní – aplikace s tímto oprávněním může vytvářet zprávy, které zdánlivě pochází od vašich přátel. Poznámka: Toto oprávnění nemusí platit pro všechny sociální sítě."</string>
-    <string name="permlab_readCalendar" msgid="5972727560257612398">"číst události kalendáře a důvěrné informace"</string>
+    <string name="permlab_readCalendar" msgid="5972727560257612398">"čtení událostí kalendáře a důvěrné informace"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Umožňuje aplikaci číst všechny události kalendáře uložené v tabletu, včetně událostí přátel nebo spolupracovníků. Aplikace s tímto oprávněním může sdílet nebo ukládat údaje v kalendáři bez ohledu na důvěrnost nebo citlivost těchto údajů."</string>
     <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Umožňuje aplikaci číst všechny události kalendáře uložené v telefonu, včetně událostí přátel nebo spolupracovníků. Aplikace s tímto oprávněním může sdílet nebo ukládat údaje v kalendáři bez ohledu na důvěrnost nebo citlivost těchto údajů."</string>
-    <string name="permlab_writeCalendar" msgid="8438874755193825647">"přidávat a upravovat události kalendáře a odesílat e-maily bez vědomí vlastníka"</string>
+    <string name="permlab_writeCalendar" msgid="8438874755193825647">"přidávání a upravování událostí kalendářů a odesílání e-mailů bez vědomí vlastníka"</string>
     <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"Umožňuje aplikaci přidat, odebrat nebo změnit události, které můžete v tabletu upravovat, a to včetně událostí přátel a spolupracovníků. Toto oprávnění umožňuje aplikaci odesílat zprávy, které budou zdánlivě přicházet od vlastníka kalendáře, nebo upravovat události bez vědomí vlastníka."</string>
     <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Umožňuje aplikaci přidat, odebrat nebo změnit události, které můžete v telefonu upravovat, a to včetně událostí přátel a spolupracovníků. Toto oprávnění umožňuje aplikaci odesílat zprávy, které budou zdánlivě přicházet od vlastníků kalendářů, nebo upravovat události bez vědomí vlastníků."</string>
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"simulace zdrojů polohy pro účely testování"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Umožňuje aplikaci získat přístup k dalším příkazům poskytovatele polohy. Aplikace s tímto oprávněním může narušit funkci GPS či jiných zdrojů polohy."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"oprávnění k instalaci poskytovatele polohy"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Vytváření simulace zdrojů polohy pro účely testování nebo instalace nového poskytovatele polohy. Toto oprávnění umožňuje aplikaci přepsat polohu nebo stav, který vracejí jiné zdroje polohy, například systém GPS nebo poskytovatelé polohy."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"přesná poloha (pomocí GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Přístup ke zdrojům přesné polohy v tabletu, jako je například systém GPS. Pokud jsou tyto služby určování polohy k dispozici a jsou zapnuté, umožňuje toto oprávnění aplikaci určit vaši přesnou polohu."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Přístup ke zdrojům přesné polohy v telefonu, jako je například systém GPS. Pokud jsou tyto služby určování polohy k dispozici a jsou zapnuté, umožňuje toto oprávnění aplikaci určit vaši přesnou polohu."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"přibližná poloha (pomocí sítě)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Přístup k přibližné poloze určené poskytovateli polohy prostřednictvím síťových zdrojů, jako jsou mobilní vysílače a sítě Wi-Fi. Pokud jsou tyto služby určování polohy k dispozici a jsou zapnuté, umožňuje toto oprávnění aplikaci určit vaši přibližnou polohu."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"přesná poloha (pomocí GPS a sítě)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Umožňuje aplikaci zjistit vaši přesnou polohu pomocí systému GPS nebo síťových lokalizačních zdrojů, jako jsou vysílače mobilní sítě a sítě Wi-Fi. Aby aplikace mohla služby určování polohy použít, musejí být zapnuté a musejí být v zařízení k dispozici. Aplikace pomocí těchto informací mohou určit vaši přesnou polohu a mohou spotřebovávat více energie z baterie."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"přibližná poloha (pomocí sítě)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Umožňuje aplikaci získat vaši přibližnou polohu. Polohu stanovují služby určování polohy pomocí síťových zdrojů, jako jsou vysílače mobilních sítí a sítě Wi-Fi. Aby aplikace mohla služby určování polohy použít, musejí být zapnuté a musejí být ve vašem zařízení k dispozici. Aplikace na základě těchto informací mohou zjistit vaši přibližnou polohu."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"přístup ke službě SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Umožňuje aplikaci používat nízkoúrovňové funkce SurfaceFlinger."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"čtení vyrovnávací paměti snímků"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Umožňuje aplikaci číst obsah vyrovnávací paměti snímků."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"konfigurovat displeje přes Wi-Fi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Povoluje aplikaci připojit a konfigurovat displeje přes Wi-Fi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"ovládat displeje přes Wi-Fi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Povoluje aplikaci ovládat základní funkce displejů přes Wi-Fi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"změna vašeho nastavení zvuku"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Umožňuje aplikaci změnit globální nastavení zvuku, například hlasitost či reproduktor pro výstup zvuku."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"nahrání zvuku"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"přístup do nastavení Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Umožňuje aplikaci konfigurovat místní tablet s rozhraním Bluetooth a vyhledávat a párovat vzdálená zařízení."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Umožňuje aplikaci konfigurovat místní telefon s rozhraním Bluetooth a vyhledávat a párovat vzdálená zařízení."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Zobrazit připojení WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"připojení a odpojení od sítě WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Umožňuje aplikaci zjistit, zda je povoleno připojení WiMAX, a také získat informace o všech připojených sítích WiMAX."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Změnit stav připojení WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Umožňuje aplikaci připojovat tablet k sítím WiMAX a odpojovat jej od nich."</string>
@@ -506,7 +565,7 @@
     <string name="permlab_bluetooth" msgid="6127769336339276828">"párování se zařízeními Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Umožňuje aplikaci zobrazit konfiguraci tabletu s rozhraním Bluetooth, vytvářet připojení ke spárovaným zařízením a přijímat tato připojení."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Umožňuje aplikaci zobrazit konfiguraci telefonu s rozhraním Bluetooth, vytvářet připojení ke spárovaným zařízením a přijímat tato připojení."</string>
-    <string name="permlab_nfc" msgid="4423351274757876953">"ovládat technologii NFC"</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"ovládání technologie NFC"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Umožňuje aplikaci komunikovat se štítky, kartami a čtečkami s podporou technologie NFC."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"vypnutí zámku obrazovky"</string>
     <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Umožňuje aplikaci vypnout zámek kláves a související zabezpečení heslem. Telefon například vypne zámek klávesnice při příchozím hovoru a po skončení hovoru jej zase zapne."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Umožňuje aplikaci upravit zdroje, které aktuálně synchronizujete. Škodlivé aplikace mohou synchronizované zdroje změnit."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"čtení výrazů přidaných do slovníku"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Umožňuje aplikaci číst slova, jména a fráze, která uživatel mohl uložit do svého slovníku."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"zápis do slovníku definovaného uživatelem"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"přidávání slov do slovníku definovaného uživatelem"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Umožňuje aplikaci zapisovat nová slova do uživatelského slovníku."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"testování přístupu do chráněného úložiště"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"testování přístupu do chráněného úložiště"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Umožňuje aplikaci testovat oprávnění pro úložiště USB, které bude dostupné v budoucích zařízeních."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Umožňuje aplikaci testovat oprávnění pro úložiště USB, které bude dostupné v budoucích zařízeních."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Umožňuje aplikaci testovat oprávnění pro kartu SD, která bude dostupná v budoucích zařízeních."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"úprava nebo smazání obsahu v úložišti USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"úprava nebo smazání obsahu na kartě SD"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Umožňuje aplikaci zapisovat na kartu SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"Upravit/smazat interní úlož."</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Umožňuje aplikaci upravovat obsah interního úložiště médií."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"přístup k externímu úložišti všech uživatelů"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Umožňuje aplikaci přistupovat k externímu úložišti pro všechny uživatele."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"přistupovat do souborového systému mezipaměti"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Umožňuje aplikaci číst a zapisovat do souborového systému mezipaměti."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"uskutečňovat a přijímat internetové hovory"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Požadovat šifrování uložených dat aplikací."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Vypnout fotoaparáty"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Zakázat používání všech fotoaparátů zařízení."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Zakázat funkce v zámku zařízení"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Zabránit používání některých funkcí v zámku zařízení."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domů"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -674,7 +737,7 @@
     <string name="relationTypeSister" msgid="1735983554479076481">"Sestra"</string>
     <string name="relationTypeSpouse" msgid="394136939428698117">"Manžel(ka)"</string>
     <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Vlastní"</string>
-    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Plocha"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Domů"</string>
     <string name="sipAddressTypeWork" msgid="6920725730797099047">"Práce"</string>
     <string name="sipAddressTypeOther" msgid="4408436162950119849">"Jiné"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Zadejte kód PIN"</string>
@@ -687,7 +750,7 @@
     <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Nesprávný kód PIN."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Chcete-li telefon odemknout, stiskněte Menu a poté 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Číslo tísňové linky"</string>
-    <string name="lockscreen_carrier_default" msgid="8963839242565653192">"Žádný signál."</string>
+    <string name="lockscreen_carrier_default" msgid="8963839242565653192">"Žádný signál"</string>
     <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Obrazovka uzamčena."</string>
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Chcete-li odemknout telefon nebo provést tísňové volání, stiskněte Menu."</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Telefon odemknete stisknutím tlačítka Menu."</string>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Zkusit znovu"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Překročili jste maximální povolený počet pokusů o odemknutí obličejem."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Nabíjení - <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"nabito"</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Nabito"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Připojte dobíjecí zařízení."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Není vložena SIM karta"</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Není vložena SIM karta"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"V tabletu není SIM karta."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"V telefonu není žádná SIM karta."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Vložte SIM kartu."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Bezpečnostní gesto vymazáno"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Buňka přidána"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Bezpečnostní gesto dokončeno"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Přidat widget"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Prázdné"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Oblast odemknutí byla rozšířena."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Oblast odemknutí byla sbalena."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>"</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Výběr uživatele"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Stav"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Fotoaparát"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Ovládání médií"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Přeuspořádání widgetů bylo zahájeno."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Přeuspořádání widgetů bylo dokončeno."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> byl smazán."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Rozšířit oblast odemknutí"</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Odemknutí přejetím prstem."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Odemknutí gestem."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Odemknutí obličejem."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Odemknutí kódem PIN."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Odemknutí heslem."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Oblast pro zadání bezpečnostního gesta."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Oblast pro přejetí prstem."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"Alt"</string>
@@ -831,7 +914,7 @@
     <item quantity="other" msgid="3903706804349556379">"před <xliff:g id="COUNT">%d</xliff:g> s"</item>
   </plurals>
   <plurals name="num_minutes_ago">
-    <item quantity="one" msgid="3306787433088810191">"před 1 minutou"</item>
+    <item quantity="one" msgid="3306787433088810191">"před 1 min"</item>
     <item quantity="other" msgid="2176942008915455116">"před <xliff:g id="COUNT">%d</xliff:g> min"</item>
   </plurals>
   <plurals name="num_hours_ago">
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopírovat adresu URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Vybrat text"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Výběr textu"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"přidat do slovníku"</string>
-    <string name="deleteText" msgid="7070985395199629156">"smazat"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Přidat do slovníku"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Smazat"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metoda zadávání dat"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Operace s textem"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"V úložišti je málo místa"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Jsou k dispozici veřejné sítě WiFi"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Přihlásit se k síti Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Přihlášení k síti"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Připojení k síti Wi-Fi se nezdařilo"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" má pomalé připojení k internetu."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Komu:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Zadejte požadovaný kód PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefon se při připojení k zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g> dočasně odpojí od sítě Wi-Fi"</string>
     <string name="select_character" msgid="3365550120617701745">"Vkládání znaků"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Odesílání zpráv SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"Aplikace &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;odesílá velký počet SMS zpráv. Chcete aplikaci povolit, aby zprávy odesílala i nadále?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Povolit"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Odmítnout"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chce odeslat zprávu na adresu &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457"><font fgcolor="#ffffb060">"Mohou být účtovány poplatky"</font>" na váš mobilní účet."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Budou účtovány poplatky na váš mobilní účet."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Odeslat"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Zrušit"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Zapamatovat moji volbu"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Svoji volbu můžete později změnit v nabídce Nastavení &gt; Aplikace."</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Povolit vždy"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nepovolit nikdy"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM karta odebrána"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilní síť bude dostupná až poté, co vložíte platnou SIM kartu a restartujete zařízení."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Hotovo"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Nastavení data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Nastavit"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Hotovo"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Výchozí"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Nejsou vyžadována žádná oprávnění"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Skrýt"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Zobrazit vše"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NOVÉ: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NOVÉ: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Poskytuje: <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Nejsou vyžadována žádná oprávnění"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"může vás to něco stát"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Velkokapacitní úložiště USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB připojeno"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Připojili jste se k počítači pomocí rozhraní USB. Chcete-li kopírovat soubory z počítače do úložiště USB v zařízení Android či obráceně, klepněte na tlačítko níže."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikace <xliff:g id="APP">%s</xliff:g> aktivovala síť VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotykem zobrazíte správu sítě."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Připojeno k relaci <xliff:g id="SESSION">%s</xliff:g>. Dotykem můžete síť spravovat."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Připojování k trvalé síti VPN…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Je připojena trvalá síť VPN"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Chyba trvalé sítě VPN"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Klepnutím resetujete připojení"</string>
     <string name="upload_file" msgid="2897957172366730416">"Zvolit soubor"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Není vybrán žádný soubor"</string>
     <string name="reset" msgid="2448168080964209908">"Resetovat"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Sdílet"</string>
     <string name="find" msgid="4808270900322985960">"Najít"</string>
     <string name="websearch" msgid="4337157977400211589">"Vyhledat na webu"</string>
+    <string name="find_next" msgid="5742124618942193978">"Najít další"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Najít předchozí"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Požadavek na informace o poloze od uživatele <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Požadavek na informace o poloze"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Požadavek od uživatele <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1206,8 +1304,8 @@
     <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Ubrat minutu"</string>
     <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Přidat hodinu"</string>
     <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Ubrat hodinu"</string>
-    <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Nastavit odp."</string>
-    <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Nastavit dop."</string>
+    <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Nastavit PM"</string>
+    <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Nastavit AM"</string>
     <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Přidat měsíc"</string>
     <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Ubrat měsíc"</string>
     <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Přidat den"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Sluchátka"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Reproduktory doku"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Zvuk HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Systém"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth Audio"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Hotovo"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Výstup médií"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Vyhledávání…"</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Připojování…"</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Dostupná"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Není k dispozici"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Integrovaná obrazovka"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Obrazovka HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Překryvná vrstva č. <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Bezdrátový displej je připojen"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Tato obrazovka se zobrazuje v jiném zařízení"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Odpojit"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Tísňové volání"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Zapomenuté gesto"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Nesprávné gesto"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Nesprávné heslo"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Nesprávný kód PIN"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Zkuste to znovu za <xliff:g id="NUMBER">%d</xliff:g> s."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Nakreslete gesto"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Zadejte kód PIN SIM karty"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Zadejte kód PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Zadejte heslo"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM karta byla deaktivována. Chcete-li pokračovat, je třeba zadat kód PUK. Podrobné informace získáte od operátora."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Zadejte požadovaný kód PIN."</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Potvrďte požadovaný kód PIN."</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Odblokování SIM karty..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Nesprávný kód PIN."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Zadejte kód PIN o délce 4–8 číslic."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Minimální délka kódu PUK je 8 číslic."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Znovu zadejte správný kód PUK. Opakovanými pokusy SIM kartu trvale deaktivujete."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Kódy PIN se neshodují."</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Příliš mnoho pokusů o nakreslení gesta"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Chcete-li telefon odemknout, přihlaste se pomocí svého účtu Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Uživatelské jméno (e-mail)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Heslo"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Přihlásit se"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Neplatné uživatelské jméno nebo heslo."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Zapomněli jste uživatelské jméno nebo heslo?"\n"Přejděte na stránku "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Kontrola účtu…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Již <xliff:g id="NUMBER_0">%d</xliff:g>krát jste zadali nesprávný kód PIN. "\n\n"Zkuste to znovu za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Již <xliff:g id="NUMBER_0">%d</xliff:g>krát jste nesprávně zadali heslo. "\n\n"Zkuste to znovu za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Již <xliff:g id="NUMBER_0">%d</xliff:g>krát jste zadali nesprávné bezpečnostní gesto. "\n\n"Zkuste to znovu za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Již jste se <xliff:g id="NUMBER_0">%d</xliff:g>krát pokusili odemknout tablet nesprávným způsobem. Po <xliff:g id="NUMBER_1">%d</xliff:g> dalších neúspěšných pokusech se v tabletu obnoví tovární nastavení a veškerá uživatelská data budou ztracena."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Již jste se <xliff:g id="NUMBER_0">%d</xliff:g>krát pokusili odemknout telefon nesprávným způsobem. Po <xliff:g id="NUMBER_1">%d</xliff:g> dalších neúspěšných pokusech se v telefonu obnoví tovární nastavení a veškerá uživatelská data budou ztracena."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Již jste se <xliff:g id="NUMBER">%d</xliff:g>krát pokusili odemknout tablet nesprávným způsobem. V tabletu se nyní obnoví výchozí tovární nastavení."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Již jste se <xliff:g id="NUMBER">%d</xliff:g>krát pokusili odemknout telefon nesprávným způsobem. V telefonu se nyní obnoví výchozí tovární nastavení."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Již <xliff:g id="NUMBER_0">%d</xliff:g>krát jste nesprávně nakreslili své heslo odemknutí. Po <xliff:g id="NUMBER_1">%d</xliff:g>dalších neúspěšných pokusech budete požádáni o odemčení tabletu pomocí e-mailového účtu."\n\n" Zkuste to znovu za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Již <xliff:g id="NUMBER_0">%d</xliff:g>krát jste nesprávně nakreslili své heslo odemknutí. Po <xliff:g id="NUMBER_1">%d</xliff:g> dalších neúspěšných pokusech budete požádáni o odemčení telefonu pomocí e-mailového účtu."\n\n" Zkuste to znovu za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Odebrat"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Chcete hlasitost zvýšit nad bezpečnou úroveň?"\n"Dlouhodobý poslech hlasitého zvuku může poškodit sluch."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Usnadnění zapnete dlouhým stisknutím dvěma prsty."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Usnadnění přístupu je aktivováno."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Usnadnění zrušeno."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Aktuální uživatel je <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Vlastník"</string>
 </resources>
diff --git a/core/res/res/values-da/donottranslate-cldr.xml b/core/res/res/values-da/donottranslate-cldr.xml
index 1dfc96c..d5b9878 100644
--- a/core/res/res/values-da/donottranslate-cldr.xml
+++ b/core/res/res/values-da/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">januar</string>
-    <string name="month_long_standalone_february">februar</string>
-    <string name="month_long_standalone_march">marts</string>
-    <string name="month_long_standalone_april">april</string>
-    <string name="month_long_standalone_may">maj</string>
-    <string name="month_long_standalone_june">juni</string>
-    <string name="month_long_standalone_july">juli</string>
-    <string name="month_long_standalone_august">august</string>
-    <string name="month_long_standalone_september">september</string>
-    <string name="month_long_standalone_october">oktober</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">december</string>
-
-    <string name="month_long_january">januar</string>
-    <string name="month_long_february">februar</string>
-    <string name="month_long_march">marts</string>
-    <string name="month_long_april">april</string>
-    <string name="month_long_may">maj</string>
-    <string name="month_long_june">juni</string>
-    <string name="month_long_july">juli</string>
-    <string name="month_long_august">august</string>
-    <string name="month_long_september">september</string>
-    <string name="month_long_october">oktober</string>
-    <string name="month_long_november">november</string>
-    <string name="month_long_december">december</string>
-
-    <string name="month_medium_january">jan.</string>
-    <string name="month_medium_february">feb.</string>
-    <string name="month_medium_march">mar.</string>
-    <string name="month_medium_april">apr.</string>
-    <string name="month_medium_may">maj</string>
-    <string name="month_medium_june">jun.</string>
-    <string name="month_medium_july">jul.</string>
-    <string name="month_medium_august">aug.</string>
-    <string name="month_medium_september">sep.</string>
-    <string name="month_medium_october">okt.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">dec.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">søndag</string>
-    <string name="day_of_week_long_monday">mandag</string>
-    <string name="day_of_week_long_tuesday">tirsdag</string>
-    <string name="day_of_week_long_wednesday">onsdag</string>
-    <string name="day_of_week_long_thursday">torsdag</string>
-    <string name="day_of_week_long_friday">fredag</string>
-    <string name="day_of_week_long_saturday">lørdag</string>
-
-    <string name="day_of_week_medium_sunday">søn.</string>
-    <string name="day_of_week_medium_monday">man.</string>
-    <string name="day_of_week_medium_tuesday">tir.</string>
-    <string name="day_of_week_medium_wednesday">ons.</string>
-    <string name="day_of_week_medium_thursday">tor.</string>
-    <string name="day_of_week_medium_friday">fre.</string>
-    <string name="day_of_week_medium_saturday">lør.</string>
-
-    <string name="day_of_week_short_sunday">søn.</string>
-    <string name="day_of_week_short_monday">man.</string>
-    <string name="day_of_week_short_tuesday">tir.</string>
-    <string name="day_of_week_short_wednesday">ons.</string>
-    <string name="day_of_week_short_thursday">tor.</string>
-    <string name="day_of_week_short_friday">fre.</string>
-    <string name="day_of_week_short_saturday">lør.</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">O</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">L</string>
-
-    <string name="am">f.m.</string>
-    <string name="pm">e.m.</string>
-    <string name="yesterday">i går</string>
-    <string name="today">i dag</string>
-    <string name="tomorrow">i morgen</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l.%M %p</string>
     <string name="hour_minute_cap_ampm">%-l.%M %^p</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 443f828..b0fcf8b 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Indstillinger for telefon"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Skærmlås"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Sluk"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Fejlrapport"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Lav fejlrapport"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Der indsamles oplysninger om din enheds aktuelle status, der efterfølgende sendes i en e-mail. Der går lidt tid, fra fejlrapporten påbegyndes, til den er klar til at blive sendt. Tak for tålmodigheden."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Lydløs"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Lyden er slået FRA"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Lyden er TIL"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Dine beskeder"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Læs og skriv sms-beskeder, e-mails og andre beskeder."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Dine personlige oplysninger"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Få direkte adgang til dine kontakter og din kalender, der er gemt på tabletcomputeren."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Få direkte adgang til dine kontakter og din kalender, der er gemt på telefonen."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Direkte adgang til oplysninger om dig, som er gemt på dit kontaktkort."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Dine sociale oplysninger"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Direkte adgang til oplysninger om dine kontaktpersoner og sociale forbindelser."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Din placering"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Overvåg din fysiske placering."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Netværkskommunikation"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Få adgang til forskellige netværksfunktioner."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Få adgang til enheder og netværk via Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Lydindstillinger"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Skifte lydindstillinger."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Påvirker batteriet"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Bruge funktioner, der hurtigt kan dræne batteriet."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalender"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Direkte adgang til kalender og begivenheder."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Læse brugerordbog"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Læse ord i brugerordbogen."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Skrive brugerordbog"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Føje ord til brugerordbogen."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Bogmærker og historik"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Direkte adgang til bogmærker og browserhistorik."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarm"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Indstille vækkeuret."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Telefonsvarer"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Direkte adgang til telefonsvarer."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Direkte adgang til mikrofonen, så der kan optages lyd."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Direkte adgang til kamera, så der kan tages billeder eller optages video."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Oplysninger om dine applikationer"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Evne til at påvirke andre applikationers adfærd på din enhed."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Baggrund"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Ændre enhedens baggrundsindstillinger."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Ur"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Ændre klokkeslæt eller tidszone på enheden."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Statusbjælke"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Ændre indstillinger for enhedens statusbjælke."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Synkronisering"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Adgang til synkroniseringsindstillingerne."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Dine konti"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Få adgang til de tilgængelige konti."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Hardwarekontroller"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Adgang og kontrol til systemet på lavere niveau."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Udviklingsværktøjer"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funktioner, der kun er nødvendige for udviklere af apps."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Andre applikationers brugergrænseflade"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Påvirke brugergrænsefladen for andre applikationer."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Lagring"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Få adgang til USB-lager."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Få adgang til SD-kortet."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Tillader, at appen kan modtage og behandle WAP-beskeder. Denne tilladelse omfatter muligheden for at overvåge eller slette de beskeder, der sendes til dig, uden at vise dem til dig."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"hente kørende apps"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Tillader, at appen kan hente oplysninger om nuværende og seneste opgaver. Med denne tilladelse kan appen finde oplysninger om, hvilke applikationer der bruges på enheden."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"kommuniker på tværs af brugere"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Tillader, at appen udfører handlinger på tværs af forskellige brugere på enheden. Ondsindede apps kan bruge dette til at krænke beskyttelsen mellem brugere."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"fuld licens til at kommunikere på tværs af brugere"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Tillader alle mulige former for kommunikation på tværs af brugere."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"administrer brugere"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Tillader, at apps administrerer brugere på enheden, herunder forespørgsler, oprettelser og sletninger."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"hente oplysninger om apps, der kører"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Tillader, at appen kan hente oplysninger om aktuelle og seneste opgaver. Ondsindede apps kan muligvis finde personlige oplysninger om andre apps."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"omorganisere kørende apps"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Tillader, at appen kan hente systemets interne tilstand. Ondsindede apps kan hente en lang række fortrolige og beskyttede oplysninger, som de normalt aldrig ville have brug for."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"hente skærmindhold"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Tillader, at appen kan hente indholdet i det aktive vindue. Ondsindede apps kan hente al indholdet i vinduet og undersøge al dens tekst med undtagelse af adgangskoder."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"aktivér tilgængelighed midlertidigt"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Tillader, at en applikation midlertidigt kan aktivere tilgængelighed på enheden. Skadelige apps kan muligvis aktivere tilgængelighed uden brugerens samtykke."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"hent oplysninger om vinduer"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Tillader, at en applikation henter oplysninger om vinduerne i vinduesadministratoren. Skadelige apps kan muligvis hente oplysninger, der er beregnet til intern systembrug."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrer begivenheder"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Tillader, at en applikation registrerer et inputfilter, som filtrerer alle brugeres strøm, før disse afsendes. Skadelige apps kan muligvis kontrollere systemets grænseflade uden brugerens deltagelse."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"forstør skærmen"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Tillader, at applikationer kan forstørre indholdet på en skærm. Skadelige apps kan omdanne skærmindholdet, så enheden bliver ubrugelig."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"delvis lukning"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Sætter aktivitetsadministratoren i lukningstilstand. Lukker ikke helt ned."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"undgå programskift"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Tillader, at appen kan kontrollere det maksimale antal kørende processer. Dette er aldrig nødvendigt til normale apps."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"tvinge baggrundsapps til at lukke"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Tillader, at appen kan kontrollere, om aktiviteter altid afsluttes, så snart de går i baggrunden. Det er aldrig nødvendigt til normale apps."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"rediger batteristatistikker"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Tillader, at appen kan ændre indsamlet batteristatistik. Anvendes ikke af normale apps."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"læs batteristatistikker"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Tillader, at en applikation læser de aktuelle data for batteriforbruget. Kan tillade, at applikationen henter detaljerede oplysninger om, hvilke apps du bruger."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"rediger batteristatistikker"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Tillader, at appen kan ændre indsamlede batteristatistikker. Anvendes ikke af normale apps."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontroller sikkerhedskopiering af system, og gendan"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Tillader, at appen kan kontrollere systemets sikkerhedskopi og gendannelsesmekanisme. Kan ikke anvendes af normale apps."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"bekræfte en komplet sikkerhedskopi, eller gendan drift"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"vis uautoriserede vinduer"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Tillader, at appen kan oprette vinduer, der er beregnet til brugergrænsefladen i det interne system. Anvendes ikke af normale apps."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"tegne over andre apps"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Tillader, at appen kan vise vinduer med systemunderretninger. Nogle underretningsvinduer kan overtage hele skærmen."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Tillader, at appen trækkes oven på andre applikationer eller dele af brugergrænsefladen. De kan forstyrre din brug af grænsefladen i en applikation eller ændre det, du tror, du ser i andre applikationer."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"rediger global animationshastighed"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Tillader, at appen til enhver tid kan ændre den globale animationshastighed (hurtigere eller langsommere animationer)."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"administrere apptokens"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Tillader, at appen kan oprette og administrere sine egen tokens, omgå deres normale Z-rækkefølge. Bør aldrig være nødvendigt for normale apps."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"frys skærmen"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Tillader, at applikationen midlertidigt fryser skærmen for overgange i fuld skærm."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"tryk på taster og kontrolknapper"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Tillader, at appen kan levere sine egne input (tastetryk osv.) i andre apps. Ondsindede apps kan bruge dette til at overtage din tablet."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Tillader, at appen kan levere sine egne input (tastetryk osv.) i andre apps. Ondsindede apps kan bruge dette til at overtage telefonen."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"installere apps direkte"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Tillader, at appen kan installere nye eller opdaterede Android-pakker. Ondsindede apps kan bruge dette til at tilføje nye apps med vilkårligt effektive tilladelser."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"slette alle appens cachedata"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Tillader, at en app kan frigøre plads på din tablet ved at slette filer i appens cachemappe. Adgangen er normalt begrænset til systemprocesser."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Tillader, at appen kan frigøre plads på din telefon ved at slette filer i appens cachemappe. Adgangen er normalt begrænset til systemprocesser."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Tillader, at appen frigør plads på tabletten ved at slette filer i andre applikationers cachemapper. Dette kan medføre, at andre applikationer starter langsommere op, da de skal hente de samme data igen."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Tillader, at appen frigør plads på telefonen ved at slette filer i andre applikationers cachemapper. Dette kan medføre, at andre applikationer starter langsommere op, da de skal hente de samme data igen."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"flytte appressourcer"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Tillader, at appen kan flytte appressourcer fra interne til eksterne medier og omvendt."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"læse følsomme logdata"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Tillader, at appen kan få adgang til yderligere kommandoer for placeringsudbydere. Dette bevirker muligvis, at appen kan forstyrre GPS-funktionen eller andre placeringskilder."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"tilladelse til at installere en placeringsudbyder"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Opret imiterede placeringskilder til test, eller installer en ny placeringsudbyder. Herved kan appen tilsidesætte den placering og/eller status, der returneres af andre placeringskilder, som f.eks. GPS eller placeringsudbydere."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"præcis (GPS) placering"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Få adgang til præcise placeringskilder, som f.eks. GPS (Global Positioning System) på tabletten. Når placeringstjenesterne er tilgængelige og aktiverede, kan appen med denne tilladelse bestemme din præcise placering."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Få adgang til præcise placeringskilder, som f.eks. GPS (Global Positioning System) på telefonen. Når placeringstjenesterne er tilgængelige og aktiverede, kan appen med denne tilladelse bestemme din præcise placering."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"omtrentlig (netværksbaseret) placering"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Få adgang til den omtrentlige placering fra placeringsudbydere ved hjælp af netværkskilder, som f.eks. mobilmaster og Wi-Fi. Når disse placeringstjenester er tilgængelige og aktiverede, kan appen med denne tilladelse bestemme din omtrentlige placering."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"præcis placering (GPS- og netværksbaseret)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Tillader, at appen henter din præcise placering ved hjælp af GPS (Global Positioning System) eller netværksplaceringskilder, såsom mobilmaster og Wi-Fi. Disse placeringstjenester skal være aktiverede og tilgængelige på din enhed, for at appen kan bruge dem. Apps kan bruge dette til at bestemme, hvor du er, og kan eventuelt bruge ekstra batterikapacitet."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"omtrentlig position (netværksbaseret)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Tillader, at appen henter din omtrentlige placering. Denne placering er udledt via placeringstjenester, der bruger netværksplaceringskilder, som f.eks. mobilmaster og Wi-Fi. Disse placeringstjenester skal være aktiverede og tilgængelige på din enhed, for at appen kan bruge dem. Apps kan bruge dette til at bestemme, hvor du omtrent er."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"få adgang til SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Tillader, at appen kan bruge SurfaceFlinger-funktioner på lavt niveau."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"læs rammebuffer"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Tillader, at appen kan læse indholdet fra rammebufferen."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"konfigurer Wi-Fi-skærme"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Tillader, at appen konfigurerer og opretter forbindelse til Wi-Fi-skærme."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"kontrollér Wi-Fi-skærme"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Tillader, at appen kontrollerer Wi-Fi-skærmfunktioner på lavt niveau."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"skift dine lydindstillinger"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Tillader, at appen kan ændre globale lydindstillinger, som f.eks. lydstyrke og hvilken højttaler der bruges til output."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"optage lyd"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"få adgang til Bluetooth-indstillinger"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Tillader, at appen kan konfigurere den lokale Bluetooth-tablet samt finde og parre med fjerne enheder."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Tillader, at appen kan konfigurere den lokale Bluetooth-telefon samt finde og parre med eksterne enheder."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"få vist WiMAX-forbindelser"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"tilslut og afbryd fra WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Tillader, at appen kan bestemme, hvorvidt WiMAX er aktiveret, og oplysninger om eventuelle WiMAX-netværk, der er forbundet."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Skift WiMAX-tilstand"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Tillader, at appen kan oprette forbindelse fra tabletten og afbryde forbindelsen til tabletten på WiMAX-netværk."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Tillader, at appen kan ændre dine synkroniserede feeds. Ondsindede apps kan ændre dine synkroniserede feeds."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"læse termer, som du har føjet til ordbogen"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Tillader, at appen kan læse alle ord, navne og sætninger, som brugeren har gemt i brugerordbogen."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"skrive til brugerordbogen"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"føj ord til den brugerdefinerede ordbog"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Tillader, at appen kan skrive nye ord i brugerordbogen."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"test adgangen til beskyttet lagring"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"test adgangen til beskyttet lagring"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Tillader, at appen tester en tilladelse til USB-lagring, der vil være tilgængelig på fremtidige enheder."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Tillader, at appen tester en tilladelse til USB-lagring, der vil være tilgængelig på fremtidige enheder."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Tillader, at appen kan teste en tilladelse for SD-kortet, der vil være tilgængelig på fremtidige enheder."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"ændre eller slette indhold på USB-lager"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"ændre eller slette indholdet på dit SD-kort"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Tillader, at appen kan skrive til SD-kortet."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"Rediger/slet internt medielagringsindhold"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Tillader, appen kan ændre indholdet af det interne medielager."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"få adgang til alle brugeres eksterne lagre"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Tillader, at appen får adgang til eksterne lagre for alle brugere."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"få adgang til cache-filsystemet"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Tillader, at appen kan læse og skrive i cachefilsystemet."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"foretage/modtage internetopkald"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Kræver, at gemte appdata krypteres."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Deaktiver kameraer"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Bloker brug af alle kameraer på enheden."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Deaktiver tastaturlåsfunktioner"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Forbyd brugen af ​​visse tastaturlåsfunktioner."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Hjem"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Prøv igen"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Det maksimale antal forsøg på at bruge Ansigtslås er overskredet"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Oplader, <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Opladt."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Opladet"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Tilslut din oplader."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Der er ikke noget SIM-kort."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Intet SIM-kort"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Der er ikke noget SIM-kort i tabletcomputeren."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Der er ikke noget SIM-kort i telefonen."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Indsæt et SIM-kort."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Mønster er ryddet"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Celle er tilføjet"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Mønster er afsluttet"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Tilføj widget."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Tom"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Oplåsningsområdet er udvidet."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Oplåsningsområdet er skjult."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Widget til <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Brugervælger"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Status"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Kamera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Mediekontrolelementer"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Omrokering af widgets er påbegyndt."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Omrokering af widgets er afsluttet."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widgetten <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> er slettet."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Udvid oplåsningsområdet."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Lås op ved at stryge."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Lås op med mønster."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Lås op med ansigt."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Lås op med pinkode."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Lås op med adgangskode."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mønsterområde."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Strygeområde."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopier webadresse"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Markér tekst"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Tekstmarkering"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"føj til ordbog"</string>
-    <string name="deleteText" msgid="7070985395199629156">"slet"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Føj til ordbog"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Slet"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Inputmetode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksthandlinger"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Der er snart ikke mere lagerplads"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Der er åbne Wi-Fi-netværk tilgængelige"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Log ind på Wi-Fi-netværket"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Log ind på netværk"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kunne ikke oprette forbindelse til Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" har en dårlig internetforbindelse."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Til:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Skriv den påkrævede pinkode:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Pinkode:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefonens Wi-Fi-forbindelse vil midlertidigt blive afbrudt, når den er tilsluttet <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Indsæt tegn"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Sender sms-beskeder"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sender et stort antal sms-beskeder. Vil du tillade, at denne app fortsat sender beskeder?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Tillad"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Afvis"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vil sende en besked til &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Dette "<font fgcolor="#ffffb060">"kan medføre gebyrer"</font>" på din mobilkonto."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Dette vil medføre gebyrer på din mobilkonto."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Send"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Annuller"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Husk mit valg"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Du kan ændre dette senere i Indstillinger &gt; Apps"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Tillad altid"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Tillad aldrig"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kort blev fjernet"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Det mobile netværk er utilgængeligt, indtil du genstarter med et gyldigt SIM-kort."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Afslut"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Angiv dato"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Angiv"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Udført"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Standard"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Der kræves ingen tilladelser"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Skjul"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Vis alle"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NYHED! "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NYHED! "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Leveret af <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Der kræves ingen tilladelser"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"dette kan koste dig penge"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB-masselager"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB er tilsluttet"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Du har fået forbindelse til din computer via USB. Tryk på knappen nedenfor, hvis du vil kopiere filer mellem din computer og din Androids USB-lager."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveres af <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tryk for at administrere netværket."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Forbundet til <xliff:g id="SESSION">%s</xliff:g>. Tryk for at administrere netværket."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Opretter forbindelse til Always-on VPN…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Always-on VPN er forbundet"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Fejl i Always-on VPN"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Tryk for at nulstille forbindelsen"</string>
     <string name="upload_file" msgid="2897957172366730416">"Vælg fil"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Ingen fil er valgt"</string>
     <string name="reset" msgid="2448168080964209908">"Nulstil"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Del"</string>
     <string name="find" msgid="4808270900322985960">"Find"</string>
     <string name="websearch" msgid="4337157977400211589">"Websøgning"</string>
+    <string name="find_next" msgid="5742124618942193978">"Find næste"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Find forrige"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Placeringsanmodning fra <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Placeringsanmodning"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Anmodet om af <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Hovedtelefoner"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dockstationens højttalere"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-lyd"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-lyd"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Udfør"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Medieudgang"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Søger..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Opretter forbindelse..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Tilgængelig"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Ikke tilgængelig"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Indbygget skærm"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-skærm"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlejring nr. <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Der er tilsluttet en trådløs skærm"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Denne skærm vises på en anden enhed"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Afbryd forbindelsen"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Nødopkald"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Glemt mønster"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Forkert mønster"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Forkert adgangskode"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Forkert pinkode"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Prøv igen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Tegn dit mønster"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Indtast pinkode til SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Indtast pinkode"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Angiv adgangskode"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM-kortet er nu deaktiveret. Indtast PUK-koden for at fortsætte. Kontakt mobiloperatøren for at få flere oplysninger."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Indtast den ønskede pinkode"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Bekræft den ønskede pinkode"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM-kortet låses op…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Forkert pinkode."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Indtast en pinkode på mellem 4 og 8 tal."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK-koden skal være på 8 tal eller mere."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Indtast den korrekte PUK-kode. Gentagne forsøg vil permanent deaktivere SIM-kortet."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Pinkoderne stemmer ikke overens"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"For mange forsøg på at tegne mønstret korrekt"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Lås op ved at logge ind med din Google-konto."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Brugernavn (e-mail)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Adgangskode"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Log ind"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Ugyldigt brugernavn eller ugyldig adgangskode."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Har du glemt dit brugernavn eller din adgangskode?"\n"Gå til "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Kontoen kontrolleres…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Du har indtastet en forkert pinkode <xliff:g id="NUMBER_0">%d</xliff:g> gange. "\n\n"Prøv igen om <xliff:g id="NUMBER_1">%d</xliff:g> sekunder."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Du har indtastet din adgangskode forkert <xliff:g id="NUMBER_0">%d</xliff:g> gange. "\n\n"Prøv igen om <xliff:g id="NUMBER_1">%d</xliff:g> sekunder."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%d</xliff:g> gange. "\n\n"Prøv igen om <xliff:g id="NUMBER_1">%d</xliff:g> sekunder."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Du har forsøgt at låse tabletten op forkert <xliff:g id="NUMBER_0">%d</xliff:g> gange. Efter <xliff:g id="NUMBER_1">%d</xliff:g> yderligere mislykkede forsøg nulstilles tabletten til fabriksindstillingerne, og alle brugerdata mistes."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Du har forsøgt at låse telefonen op forkert <xliff:g id="NUMBER_0">%d</xliff:g> gange. Efter <xliff:g id="NUMBER_1">%d</xliff:g> yderligere mislykkede forsøg, nulstilles telefonen til fabriksindstillingerne, og alle brugerdata mistes."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Du har forsøgt at låse tabletten op forkert <xliff:g id="NUMBER">%d</xliff:g> gange. Tabletten nulstilles til fabriksindstillingerne."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Du har forsøgt at låse telefonen op forkert <xliff:g id="NUMBER">%d</xliff:g> gange. Telefonen nulstilles til fabriksindstillingerne."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%d</xliff:g> gange. Efter <xliff:g id="NUMBER_1">%d</xliff:g> yderligere mislykkede forsøg vil du blive bedt om at låse din tablet op ved hjælp af en e-mailkonto"\n\n" Prøv igen om <xliff:g id="NUMBER_2">%d</xliff:g> sekunder."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%d</xliff:g> gange. Efter <xliff:g id="NUMBER_1">%d</xliff:g> yderligere mislykkede forsøg til vil du blive bedt om at låse din telefon op ved hjælp af en e-mailkonto."\n\n" Prøv igen om <xliff:g id="NUMBER_2">%d</xliff:g> sekunder."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Fjern"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Skal lydstyrken være over det sikre niveau?"\n"Du kan skade din hørelse ved at lytte ved høj lydstyrke i længere tid."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Hold fortsat to fingre nede for at aktivere tilgængelighed."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Tilgængelighed aktiveret."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Tilgængelighed er annulleret."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Nuværende bruger <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Ejer"</string>
 </resources>
diff --git a/core/res/res/values-de/donottranslate-cldr.xml b/core/res/res/values-de/donottranslate-cldr.xml
index 8b834db..9bdd8a3 100644
--- a/core/res/res/values-de/donottranslate-cldr.xml
+++ b/core/res/res/values-de/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Januar</string>
-    <string name="month_long_standalone_february">Februar</string>
-    <string name="month_long_standalone_march">März</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">Mai</string>
-    <string name="month_long_standalone_june">Juni</string>
-    <string name="month_long_standalone_july">Juli</string>
-    <string name="month_long_standalone_august">August</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">Oktober</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">Dezember</string>
-
-    <string name="month_long_january">Januar</string>
-    <string name="month_long_february">Februar</string>
-    <string name="month_long_march">März</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">Mai</string>
-    <string name="month_long_june">Juni</string>
-    <string name="month_long_july">Juli</string>
-    <string name="month_long_august">August</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">Oktober</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">Dezember</string>
-
-    <string name="month_medium_january">Jan.</string>
-    <string name="month_medium_february">Feb.</string>
-    <string name="month_medium_march">Mär.</string>
-    <string name="month_medium_april">Apr.</string>
-    <string name="month_medium_may">Mai</string>
-    <string name="month_medium_june">Jun.</string>
-    <string name="month_medium_july">Jul.</string>
-    <string name="month_medium_august">Aug.</string>
-    <string name="month_medium_september">Sep.</string>
-    <string name="month_medium_october">Okt.</string>
-    <string name="month_medium_november">Nov.</string>
-    <string name="month_medium_december">Dez.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">Sonntag</string>
-    <string name="day_of_week_long_monday">Montag</string>
-    <string name="day_of_week_long_tuesday">Dienstag</string>
-    <string name="day_of_week_long_wednesday">Mittwoch</string>
-    <string name="day_of_week_long_thursday">Donnerstag</string>
-    <string name="day_of_week_long_friday">Freitag</string>
-    <string name="day_of_week_long_saturday">Samstag</string>
-
-    <string name="day_of_week_medium_sunday">So.</string>
-    <string name="day_of_week_medium_monday">Mo.</string>
-    <string name="day_of_week_medium_tuesday">Di.</string>
-    <string name="day_of_week_medium_wednesday">Mi.</string>
-    <string name="day_of_week_medium_thursday">Do.</string>
-    <string name="day_of_week_medium_friday">Fr.</string>
-    <string name="day_of_week_medium_saturday">Sa.</string>
-
-    <string name="day_of_week_short_sunday">So.</string>
-    <string name="day_of_week_short_monday">Mo.</string>
-    <string name="day_of_week_short_tuesday">Di.</string>
-    <string name="day_of_week_short_wednesday">Mi.</string>
-    <string name="day_of_week_short_thursday">Do.</string>
-    <string name="day_of_week_short_friday">Fr.</string>
-    <string name="day_of_week_short_saturday">Sa.</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">D</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">D</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">vorm.</string>
-    <string name="pm">nachm.</string>
-    <string name="yesterday">Gestern</string>
-    <string name="today">Heute</string>
-    <string name="tomorrow">Morgen</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 8707f28..b4f87efb 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefonoptionen"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Display-Sperre"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Ausschalten"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Fehlerbericht"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Fehlerbericht abrufen"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Bei diesem Fehlerbericht werden Daten zum aktuellen Status Ihres Geräts erfasst und als E-Mail versandt. Vom Start des Berichts bis zu seinem Versand kann es eine Weile dauern. Bitte haben Sie etwas Geduld."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Lautlos-Modus"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Ton ist AUS."</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Ton ist AN."</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Ihre Nachrichten"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"SMS, E-Mails und andere Nachrichten lesen und schreiben"</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Ihre persönlichen Informationen"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Direkter Zugriff auf die Kontakte und den Kalender Ihres Tablets"</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Direkter Zugriff auf die Kontakte und den Kalender Ihres Telefons"</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Direkter Zugriff auf Informationen über Sie, die in Ihrer Kontaktkarte gespeichert sind"</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Ihre sozialen Informationen"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Direkter Zugriff auf Informationen über Ihre Kontakte und sozialen Verbindungen"</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Ihren Standort"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Ihren physischen Standort überwachen"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Netzkommunikation"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Zugriff auf verschiedene Netzwerkfunktionen"</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Auf Geräte und Netzwerke über Bluetooth zugreifen"</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Audioeinstellungen"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Audioeinstellungen ändern"</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Wirkt sich auf den Akku aus"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Funktionen nutzen, die den Akku schnell entladen"</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalender"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Direkter Zugriff auf Kalender und Termine"</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Ihr Wörterbuch lesen"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Wörter in Ihrem Wörterbuch lesen"</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"In Ihrem Wörterbuch schreiben"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Wörter zu Ihrem Wörterbuch hinzufügen"</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Lesezeichen und Verlauf"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Direkter Zugriff auf Lesezeichen und Browserverlauf"</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Wecker"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Wecker stellen"</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Mailbox"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Direkter Zugriff auf Mailbox"</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Direkter Zugriff auf das Mikrofon zur Audioaufnahme"</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Direkter Zugriff auf Kamera für Bild- oder Videoaufnahmen"</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Informationen zu Ihren Apps"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Einflussnahme auf das Verhalten anderer Apps auf Ihrem Gerät"</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Hintergrund"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Hintergrundeinstellungen des Geräts ändern"</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Uhr"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Uhrzeit oder Zeitzone des Geräts ändern"</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Statusleiste"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Einstellungen in der Statusleiste des Geräts ändern"</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Synchronisierungseinstellungen"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Zugriff auf Synchronisierungseinstellungen"</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Ihre Konten"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Zugriff auf verfügbare Konten"</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Hardware-Steuerelemente"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Zugriff und Steuerung des Systems auf niedrigerer Ebene."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Entwickler-Tools"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funktionen nur für App-Entwickler vorgesehen"</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Benutzeroberfläche anderer Apps"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Benutzeroberfläche anderer Apps beeinflussen"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Speicher"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Zugriff auf USB-Speicher"</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Zugriff auf SD-Karte"</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Ermöglicht der App, WAP-Nachrichten zu empfangen und zu verarbeiten. Mit der Berechtigung können Nachrichten, die an Sie gesendet wurden, überwacht und gelöscht werden, bevor sie Ihnen angezeigt werden."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"aktive Apps abrufen"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Ermöglicht der App, Informationen zu aktuellen und kürzlich ausgeführten Aufgaben abzurufen. Damit kann die App möglicherweise ermitteln, welche Apps auf Ihrem Gerät zum Einsatz kommen."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"Nutzerübergreifend interagieren"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Ermöglicht der App, auf dem Gerät nutzerübergreifend Aktionen durchzuführen. Schädliche Apps können so den zwischen den Nutzern bestehenden Schutz aufheben."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"Vollständige Lizenz zum nutzerübergreifenden Interagieren"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Ermöglicht alle möglichen nutzerübergreifenden Interaktionen"</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"Nutzer verwalten"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Ermöglicht Apps die Verwaltung der Nutzer auf dem Gerät, unter anderem das Abfragen, Erstellen und Löschen von Nutzern"</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"Details zu ausgeführten Apps abrufen"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Ermöglicht der App, detaillierte Informationen zu aktuellen und kürzlich ausgeführten Aufgaben abzurufen. Schädliche Apps können so geheime Informationen zu anderen Apps erhalten."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"Aktive Apps neu ordnen"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Ermöglicht der App, den internen Systemstatus abzurufen. Schädliche Apps können so eine Vielzahl an privaten und geschützten Daten abrufen, die sie in der Regel nicht benötigen."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"Bildschirminhalt abrufen"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Ermöglicht der App, den Inhalt des aktiven Fensters abzurufen. Schädliche Apps können so den gesamten Fensterinhalt abrufen und mit Ausnahme von Passwörtern den gesamten Text auswerten."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Bedienungshilfen vorübergehend aktivieren"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Ermöglicht einer App, die Bedienungshilfen auf dem Gerät vorübergehend zu aktivieren. Schädliche Apps können Bedienungshilfen ohne die Zustimmung des Nutzers aktivieren."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"Fensterinformationen abrufen"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Ermöglicht einer App, Informationen über die Fenster vom Fenster-Manager abzurufen. Schädliche Apps können Informationen abrufen, die für die systeminterne Nutzung gedacht sind."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"Ereignisse filtern"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Ermöglicht einer App, einen Eingabefilter zu registrieren, der den Stream aller Nutzerereignisse vor ihrem Versand filtert. Eine schädliche App kann die System-UI ohne Eingriff des Nutzers kontrollieren."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"Anzeige vergrößern"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Erlaubt der App, den Inhalt einer Anzeige zu vergrößern. Schädliche Apps verändern eventuell die Ansicht, sodass Inhalte nicht richtig angezeigt werden."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"partielles Herunterfahren"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Versetzt den Aktivitätsmanager in einen heruntergefahrenen Zustand. Führt kein vollständiges Herunterfahren aus."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"App-Wechsel verhindern"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Ermöglicht der App, die maximale Anzahl an aktiven Prozessen zu steuern. Wird nie für normale Apps benötigt."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"Apps im Hintergrund schließen"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Überlässt der App die Entscheidung, ob Aktivitäten immer beendet werden, sobald sie in den Hintergrund rücken. Wird nie für normale Apps benötigt."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"Akku-Daten ändern"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Ermöglicht der App, gesammelte Akkudaten zu ändern. Nicht für normale Apps vorgesehen."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"Akkudaten lesen"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Ermöglicht einer Anwendung, den momentan niedrigen Akkustand zu erkennen. Unter Umständen erhält die App detaillierte Informationen darüber, welche Apps Sie verwenden."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"Akkudaten ändern"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Ermöglicht der App, erfasste Akkudaten zu ändern. Nicht für normale Apps vorgesehen."</string>
     <string name="permlab_backup" msgid="470013022865453920">"Systemsicherung und -wiederherstellung kontrollieren"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Ermöglicht der App, den Sicherungs- und Wiederherstellungsmechanismus des Systems zu steuern. Nicht für normale Apps vorgesehen."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"Vollständige Sicherung oder Wiederherstellung bestätigen"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"nicht autorisierte Fenster anzeigen"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Ermöglicht der App die Erstellung von Fenstern, die von der Benutzeroberfläche des internen Systems verwendet werden. Nicht für normale Apps vorgesehen."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"Über andere Apps ziehen"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Ermöglicht der App, Fenster mit Systemwarnungen einzublenden. Manche dieser Systemwarnungen können den gesamten Bildschirm einnehmen."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Ermöglicht der App, über andere Apps oder Teile der Benutzeroberfläche zu zeichnen. Dies kann sich auf die Oberfläche in jeder App auswirken oder die erwartete Darstellung in anderen Apps verändern."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"Allgemeine Animationsgeschwindigkeit einstellen"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Ermöglicht der App, die allgemeine Animationsgeschwindigkeit (langsamere oder schnellere Animationen) jederzeit anzupassen."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"App-Token verwalten"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Ermöglicht der App, ihre eigenen Token zu erstellen und zu verwalten. Hierbei wird die normale Z-Reihenfolge umgangen. Sollte nie für normale Apps benötigt werden."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"Bildschirm fixieren"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Erlaubt der App, den Bildschirm zur Vollbildübertragung vorübergehend zu fixieren"</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"Tasten und Steuerungstasten drücken"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Ermöglicht der App, ihre eigenen Eingabeaktionen, zum Beispiel das Drücken von Tasten, an andere Apps weiterzugeben. Schädliche Apps können so die Kontrolle über Ihr Tablet übernehmen."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Ermöglicht der App, ihre eigenen Eingabeaktionen, zum Beispiel das Drücken von Tasten, an andere Apps weiterzugeben. Schädliche Apps können so die Kontrolle über Ihr Telefon übernehmen."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"Apps direkt installieren"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Ermöglicht der App, neue oder aktualisierte Android-Pakete zu installieren. Schädliche Apps können so neue Apps mit beliebig umfangreichen Berechtigungen hinzufügen."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"Alle Cache-Daten der App löschen"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Ermöglicht der App, Tablet-Speicher durch das Löschen von Dateien im Cache-Verzeichnis der App freizugeben. Der Zugriff beschränkt sich in der Regel auf Systemprozesse."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Ermöglicht der App, Telefonspeicher durch das Löschen von Dateien im Cache-Verzeichnis der App freizugeben. Der Zugriff beschränkt sich in der Regel auf Systemprozesse."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Ermöglicht der App, Speicherplatz auf dem Tablet durch Löschen von Dateien in den Cache-Verzeichnissen anderer Apps freizusetzen. Der Startvorgang anderer Apps kann sich hierdurch verlangsamen, weil die Daten neu abgerufen werden müssen."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Ermöglicht der App, Speicherplatz auf dem Telefon durch Löschen von Dateien in den Cache-Verzeichnissen anderer Apps freizusetzen. Der Startvorgang anderer Apps kann sich hierdurch verlangsamen, weil die Daten neu abgerufen werden müssen."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"App-Ressourcen verschieben"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Ermöglicht der App, App-Ressourcen von internen auf externe Medien zu verschieben und umgekehrt"</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"Vertrauliche Protokolldaten lesen"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Ermöglicht der App, auf zusätzliche Standortanbieterbefehle zuzugreifen. Damit könnte die App die Funktionsweise von GPS oder anderen Standortquellen beeinträchtigen."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"Berechtigung zur Installation eines Standortanbieters"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Erstellen von simulierten Standortquellen für Testzwecke oder Installation eines neuen Standortanbieters. Damit kann die App den von anderen Standortquellen wie GPS oder Standortanbietern zurückgegebenen Standort und/oder Status überschreiben."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"Genauer (GPS-)Standort"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Zugriff auf präzise Standortquellen wie GPS (Global Positioning System) auf dem Tablet. Wenn Standortdienste verfügbar und aktiviert sind, ermöglicht diese Berechtigung der App, Ihren genauen Standort zu bestimmen."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Zugriff auf präzise Standortquellen wie GPS (Global Positioning System) auf dem Telefon. Wenn Standortdienste verfügbar und aktiviert sind, ermöglicht diese Berechtigung der App, Ihren genauen Standort zu bestimmen."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"Ungefährer (netzwerkbasierter) Standort"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Zugriff auf den ungefähren Standort über Standortanbieter mithilfe von Netzwerkquellen wie Mobilfunkmasten und WLAN. Wenn diese Standortdienste verfügbar und aktiviert sind, ermöglicht die Berechtigung der App, Ihren ungefähren Standort zu bestimmen."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"genauer Standort (GPS- und netzwerkbasiert)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Ermöglicht der App, Ihre genaue Position anhand von GPS-Daten (Global Positioning System) oder über Netzwerkstandortquellen wie Sendemasten oder WLAN zu ermitteln. Diese Standortdienste müssen auf Ihrem Gerät verfügbar und aktiviert sein, damit die App sie verwenden kann. Apps können Ihren Standort anhand dieser Daten ermitteln und verbrauchen eventuell zusätzliche Akkuleistung."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"ungefährer Standort (netzwerkbasiert)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Ermöglicht der App, Ihren ungefähren Standort zu ermitteln. Diese Standortangabe stammt von Standortdiensten, die Netzwerkstandortquellen wie etwa Sendemasten oder WLAN verwenden. Diese Standortdienste müssen auf Ihrem Gerät verfügbar und aktiviert sein, damit die App sie verwenden kann. Apps können Ihren ungefähren Standort anhand dieser Daten ermitteln."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"Auf SurfaceFlinger zugreifen"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Ermöglicht der App, die systemnahen SurfaceFlinger-Funktionen zu verwenden"</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"Frame-Puffer lesen"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Ermöglicht der App, den Inhalt des Frame-Puffers zu lesen"</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"WLAN-Anzeigen konfigurieren"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Erlaubt der App, WLAN-Anzeigen zu konfigurieren und eine Verbindung zu diesen herzustellen"</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"WLAN-Anzeigen steuern"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Erlaubt der App, untergeordnete Funktionen von WLAN-Anzeigen zu steuern"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"Audio-Einstellungen ändern"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Ermöglicht der App, globale Audio-Einstellungen zu ändern, etwa die Lautstärke und den Lautsprecher für die Ausgabe."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"Audio aufnehmen"</string>
@@ -442,10 +501,10 @@
     <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"Ermöglicht der App, die Telefonfunktionen des Geräts zu steuern. Eine App mit dieser Berechtigung kann das Netzwerk wechseln oder das Radio des Telefons ein- und ausschalten, ohne Sie darüber zu informieren."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"Telefonstatus und Identität abrufen"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Ermöglicht der App, auf die Telefonfunktionen des Geräts zuzugreifen. Die Berechtigung erlaubt der App, die Telefonnummer und Geräte-IDs zu erfassen, festzustellen, ob gerade ein Gespräch geführt wird, und die Rufnummer verbundener Anrufer zu lesen."</string>
-    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"Standby-Modus des Tablets deaktivieren"</string>
-    <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"Standby-Modus deaktivieren"</string>
-    <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Ermöglicht der App, den Standby-Modus des Tablets zu deaktivieren"</string>
-    <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"Ermöglicht der App, den Standby-Modus des Telefons zu deaktivieren"</string>
+    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"Ruhezustand des Tablets deaktivieren"</string>
+    <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"Ruhezustand deaktivieren"</string>
+    <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Ermöglicht der App, den Ruhezustand des Tablets zu deaktivieren"</string>
+    <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"Ermöglicht der App, den Ruhezustand des Telefons zu deaktivieren"</string>
     <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"Tablet ein- oder ausschalten"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"Gerät ein- oder ausschalten"</string>
     <string name="permdesc_devicePower" product="tablet" msgid="6689862878984631831">"Ermöglicht der App, das Tablet ein- oder auszuschalten"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"Auf Bluetooth-Einstellungen zugreifen"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Ermöglicht der App, das lokale Bluetooth-Tablet zu konfigurieren, Remote-Geräte zu erkennen und eine Verbindung zu diesen herzustellen"</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Ermöglicht der App, das lokale Bluetooth-Telefon zu konfigurieren, Remote-Geräte zu erkennen und eine Verbindung zu diesen herzustellen"</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"WiMAX-Verbindungen anzeigen"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX-Verbindungen herstellen und trennen"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Ermöglicht der App festzustellen, ob WiMAX aktiviert ist. Zudem kann sie Informationen zu verbundenen WiMAX-Netzwerken abrufen."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX-Status ändern"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Ermöglicht der App, eine Verbindung zwischen dem Tablet und WiMAX-Netzwerken herzustellen und solche zu trennen."</string>
@@ -508,7 +567,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Ermöglicht der App, die Bluetooth-Konfiguration des Telefons einzusehen und Verbindungen mit gekoppelten Geräten herzustellen und zu akzeptieren."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"Nahfeldkommunikation steuern"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Ermöglicht der App die Kommunikation mit Tags für die Nahfeldkommunikation, Karten und Readern"</string>
-    <string name="permlab_disableKeyguard" msgid="3598496301486439258">"Bildschirmsperre deaktivieren"</string>
+    <string name="permlab_disableKeyguard" msgid="3598496301486439258">"Display-Sperre deaktivieren"</string>
     <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Ermöglicht der App, die Tastensperre sowie den damit verbundenen Passwortschutz zu deaktivieren. Das Telefon deaktiviert die Tastensperre beispielsweise, wenn ein Anruf eingeht, und aktiviert sie wieder, nachdem das Gespräch beendet wurde."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"Synchronisierungseinstellungen lesen"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Ermöglicht der App, die Synchronisierungseinstellungen eines Kontos zu lesen. Beispielsweise kann damit festgestellt werden, ob Kontakte mit einem Konto synchronisiert werden."</string>
@@ -522,18 +581,20 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Ermöglicht der App, Änderungen an kürzlich synchronisierten Feeds vorzunehmen. Schädliche Apps können so Ihre synchronisierten Feeds ändern."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"Begriffe lesen, die Sie zum Wörterbuch hinzugefügt haben"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Ermöglicht der App, alle Wörter, Namen und Ausdrücke zu lesen, die ein Nutzer in seinem Wörterbuch gespeichert hat."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"In benutzerdefiniertes Wörterbuch schreiben"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"Wörter zu meinem Wörterbuch hinzufügen"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Ermöglicht der App, dem Nutzerwörterbuch neue Einträge hinzuzufügen"</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"Zugriff auf geschützten Speicher testen"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"Zugriff auf geschützten Speicher testen"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Ermöglicht der App, eine Berechtigung für USB-Speicher zu testen, die künftig auf neuen Geräten verfügbar sein wird."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Ermöglicht der App, eine Berechtigung für USB-Speicher zu testen, die künftig auf neuen Geräten verfügbar sein wird"</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Ermöglicht der App, eine Berechtigung für SD-Karten zu testen, die künftig auf neuen Geräten verfügbar sein wird"</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"USB-Speicherinhalte ändern oder löschen"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"SD-Karteninhalte ändern oder löschen"</string>
     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"Ermöglicht der App, in den USB-Speicher zu schreiben"</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Ermöglicht der App, auf die SD-Karte zu schreiben"</string>
-    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"Intern. Mediensp. änd./löschen"</string>
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"Internen Medienspeicher ändern/löschen"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Ermöglicht der App, den Inhalt des internen Medienspeichers zu ändern"</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"Auf externen Speicher aller Nutzer zugreifen"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Ermöglicht der App, auf externen Speicher aller Nutzer zuzugreifen."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"Zugriff auf das Cache-Dateisystem"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Ermöglicht der App Lese- und Schreibzugriff auf das Cache-Dateisystem"</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"Internetanrufe tätigen/annehmen"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Anforderung, dass gespeicherte App-Daten verschlüsselt werden"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Kameras deaktivieren"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Nutzung sämtlicher Gerätekameras unterbinden"</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Funktionen in Keyguard deaktivieren"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Verhindert in Keyguard die Verwendung einiger Funktionen"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Privat"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Erneut versuchen"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Die maximal zulässige Anzahl an Face Unlock-Versuchen wurde überschritten."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Wird geladen... (<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Aufgeladen"</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Aufgeladen"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_low_battery" msgid="1482873981919249740">"Bitte Ladegerät anschließen"</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Keine SIM-Karte"</string>
+    <string name="lockscreen_low_battery" msgid="1482873981919249740">"Ladegerät anschließen"</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Keine SIM-Karte"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Keine SIM-Karte im Tablet"</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Keine SIM-Karte im Telefon"</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Legen Sie eine SIM-Karte ein."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Muster gelöscht"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Zelle hinzugefügt"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Muster abgeschlossen"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Widget hinzufügen"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Leer"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Entsperr-Bereich maximiert"</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Entsperr-Bereich mminimiert"</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>"</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Nutzerauswahl"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Status"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Kamera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Mediensteuerelemente"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Neuordnung der Widgets gestartet"</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Neuordnung der Widgets abgeschlossen"</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> gelöscht"</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Entsperr-Bereich maximieren"</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Entsperrung mit Fingerbewegung"</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Entsperrung mit Muster"</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Face Unlock"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Entsperrung mit PIN"</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Entsperrung mit Passwort"</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Bereich für Muster"</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Bereich für Fingerbewegung"</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -828,15 +911,15 @@
     <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Vor mehr als 1 Monat"</string>
   <plurals name="num_seconds_ago">
     <item quantity="one" msgid="4869870056547896011">"Vor 1 Sekunde"</item>
-    <item quantity="other" msgid="3903706804349556379">"Vor <xliff:g id="COUNT">%d</xliff:g> Sekunden"</item>
+    <item quantity="other" msgid="3903706804349556379">"vor <xliff:g id="COUNT">%d</xliff:g> Sekunden"</item>
   </plurals>
   <plurals name="num_minutes_ago">
     <item quantity="one" msgid="3306787433088810191">"Vor 1 Minute"</item>
-    <item quantity="other" msgid="2176942008915455116">"Vor <xliff:g id="COUNT">%d</xliff:g> Minuten"</item>
+    <item quantity="other" msgid="2176942008915455116">"vor <xliff:g id="COUNT">%d</xliff:g> Minuten"</item>
   </plurals>
   <plurals name="num_hours_ago">
     <item quantity="one" msgid="9150797944610821849">"Vor 1 Stunde"</item>
-    <item quantity="other" msgid="2467273239587587569">"Vor <xliff:g id="COUNT">%d</xliff:g> Stunden"</item>
+    <item quantity="other" msgid="2467273239587587569">"vor <xliff:g id="COUNT">%d</xliff:g> Stunden"</item>
   </plurals>
   <plurals name="last_num_days">
     <item quantity="other" msgid="3069992808164318268">"Letzte <xliff:g id="COUNT">%d</xliff:g> Tage"</item>
@@ -845,7 +928,7 @@
     <string name="older" msgid="5211975022815554840">"Älter"</string>
   <plurals name="num_days_ago">
     <item quantity="one" msgid="861358534398115820">"Gestern"</item>
-    <item quantity="other" msgid="2479586466153314633">"Vor <xliff:g id="COUNT">%d</xliff:g> Tagen"</item>
+    <item quantity="other" msgid="2479586466153314633">"vor <xliff:g id="COUNT">%d</xliff:g> Tagen"</item>
   </plurals>
   <plurals name="in_num_seconds">
     <item quantity="one" msgid="2729745560954905102">"in 1 Sekunde"</item>
@@ -865,7 +948,7 @@
   </plurals>
   <plurals name="abbrev_num_seconds_ago">
     <item quantity="one" msgid="1849036840200069118">"vor 1 Sekunde"</item>
-    <item quantity="other" msgid="3699169366650930415">"Vor <xliff:g id="COUNT">%d</xliff:g> Sekunden"</item>
+    <item quantity="other" msgid="3699169366650930415">"vor <xliff:g id="COUNT">%d</xliff:g> Sekunden"</item>
   </plurals>
   <plurals name="abbrev_num_minutes_ago">
     <item quantity="one" msgid="6361490147113871545">"vor 1 Minute"</item>
@@ -873,11 +956,11 @@
   </plurals>
   <plurals name="abbrev_num_hours_ago">
     <item quantity="one" msgid="4796212039724722116">"Vor 1 Stunde"</item>
-    <item quantity="other" msgid="6889970745748538901">"Vor <xliff:g id="COUNT">%d</xliff:g> Stunden"</item>
+    <item quantity="other" msgid="6889970745748538901">"vor <xliff:g id="COUNT">%d</xliff:g> Stunden"</item>
   </plurals>
   <plurals name="abbrev_num_days_ago">
     <item quantity="one" msgid="8463161711492680309">"Gestern"</item>
-    <item quantity="other" msgid="3453342639616481191">"Vor <xliff:g id="COUNT">%d</xliff:g> Tagen"</item>
+    <item quantity="other" msgid="3453342639616481191">"vor <xliff:g id="COUNT">%d</xliff:g> Tagen"</item>
   </plurals>
   <plurals name="abbrev_in_num_seconds">
     <item quantity="one" msgid="5842225370795066299">"in 1 Sekunde"</item>
@@ -930,14 +1013,14 @@
     <string name="copyUrl" msgid="2538211579596067402">"URL kopieren"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Text auswählen"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Textauswahl"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"Zum Wörterbuch hinzufügen"</string>
-    <string name="deleteText" msgid="7070985395199629156">"Löschen"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Zum Wörterbuch hinzufügen"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Löschen"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Eingabemethode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Textaktionen"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Der Speicherplatz wird knapp"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Einige Systemfunktionen funktionieren möglicherweise nicht."</string>
     <string name="ok" msgid="5970060430562524910">"OK"</string>
-    <string name="cancel" msgid="6442560571259935130">"Abbruch"</string>
+    <string name="cancel" msgid="6442560571259935130">"Abbrechen"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
     <string name="no" msgid="5141531044935541497">"Abbrechen"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Achtung"</string>
@@ -951,8 +1034,8 @@
     <string name="chooseUsbActivity" msgid="6894748416073583509">"App für USB-Gerät auswählen"</string>
     <string name="noApplications" msgid="2991814273936504689">"Diese Aktion kann von keiner App ausgeführt werden."</string>
     <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"\"<xliff:g id="APPLICATION">%1$s</xliff:g>\" wurde leider beendet."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Leider wurde der Prozess <xliff:g id="PROCESS">%1$s</xliff:g> beendet."</string>
+    <string name="aerr_application" msgid="932628488013092776">"\"<xliff:g id="APPLICATION">%1$s</xliff:g>\" wurde beendet."</string>
+    <string name="aerr_process" msgid="4507058997035697579">"Der Prozess <xliff:g id="PROCESS">%1$s</xliff:g> wurde beendet."</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
     <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> reagiert nicht."\n\n"Möchten Sie die App schließen?"</string>
     <string name="anr_activity_process" msgid="5776209883299089767">"Aktivität \"<xliff:g id="ACTIVITY">%1$s</xliff:g>\" reagiert nicht."\n\n"Möchten Sie sie beenden?"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Verfügbare WLAN-Netzwerke öffnen"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Im WLAN-Netzwerk anmelden"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Im Netzwerk anmelden"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Es konnte keine WLAN-Verbindung hergestellt werden."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" hat eine schlechte Internetverbindung."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"An:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Geben Sie die erforderliche PIN ein:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Das Telefon wird vorübergehend vom WLAN getrennt, während eine Verbindung mit <xliff:g id="DEVICE_NAME">%1$s</xliff:g> hergestellt wird."</string>
     <string name="select_character" msgid="3365550120617701745">"Zeichen einfügen"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Kurznachrichten werden gesendet"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sendet eine große Anzahl SMS. Möchten Sie zulassen, dass die App weiterhin Nachrichten sendet?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Zulassen"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Nicht zulassen"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; möchte eine Nachricht an &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; senden."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Hierfür könnten Ihrem Mobilfunkkonto "<font fgcolor="#ffffb060">"Gebühren berechnet werden"</font>"."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Hierfür werden Ihrem Mobilfunkkonto Gebühren berechnet."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Senden"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Abbrechen"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Auswahl merken"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Sie können dies unter \"Einstellungen &gt; Apps\" ändern."</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Immer zulassen"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nie zulassen"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-Karte entfernt"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Das Mobilfunknetz ist erst wieder verfügbar, wenn Sie einen Neustart mit einer gültigen SIM-Karte durchführen."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Fertig"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Datum festlegen"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Speichern"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Fertig"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Standard"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Keine Berechtigungen erforderlich"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Ausblenden"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Alle anzeigen"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"Neu: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"Neu: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Zur Verfügung gestellt von <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Keine Berechtigungen erforderlich"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"Hierfür können Gebühren anfallen."</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB-Massenspeicher"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB-Verbindung"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Sie haben eine USB-Verbindung mit Ihrem Computer hergestellt. Berühren Sie die Schaltfläche unten, wenn Sie Dateien von Ihrem Computer in den USB-Speicher Ihres Android-Geräts und umgekehrt kopieren möchten."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN wurde von <xliff:g id="APP">%s</xliff:g> aktiviert."</string>
     <string name="vpn_text" msgid="3011306607126450322">"Zum Verwalten des Netzwerks berühren"</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Verbunden mit <xliff:g id="SESSION">%s</xliff:g>. Zum Verwalten des Netzwerks berühren"</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Verbindung zu durchgehend aktivem VPN wird hergestellt…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Mit durchgehend aktivem VPN verbunden"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Durchgehend aktives VPN – Verbindungsfehler"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Zum Zurücksetzen der Verbindung tippen"</string>
     <string name="upload_file" msgid="2897957172366730416">"Datei auswählen"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Keine ausgewählt"</string>
     <string name="reset" msgid="2448168080964209908">"Zurücksetzen"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Teilen"</string>
     <string name="find" msgid="4808270900322985960">"Suchen"</string>
     <string name="websearch" msgid="4337157977400211589">"Websuche"</string>
+    <string name="find_next" msgid="5742124618942193978">"Weitersuchen"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Aufwärts weitersuchen"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Standortabfrage von <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Standortabfrage"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Angefordert von <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1248,7 +1346,7 @@
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Für Verbrauch/Einstell. berühren"</string>
     <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G-/3G-Daten deaktiviert"</string>
     <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G-Daten deaktiviert"</string>
-    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobile Daten deaktiviert"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobilfunk deaktiviert"</string>
     <string name="data_usage_wifi_limit_title" msgid="8992154736441284865">"WLAN-Daten deaktiviert"</string>
     <string name="data_usage_limit_body" msgid="3317964706973601386">"Zum Aktivieren berühren"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"2G-/3G-Datenlimit überschritten"</string>
@@ -1281,13 +1379,69 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Browser starten?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Anruf annehmen?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Immer"</string>
-    <string name="activity_resolver_use_once" msgid="2404644797149173758">"Nur einmal"</string>
+    <string name="activity_resolver_use_once" msgid="2404644797149173758">"Nur diesmal"</string>
     <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string>
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Kopfhörer"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock-Lautsprecher"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-Audio"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-Audio"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fertig"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Medienausgabe"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Wird gescannt..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Verbindung wird hergestellt..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Verfügbar"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Nicht verfügbar"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Integrierter Bildschirm"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-Bildschirm"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay-Nr. <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"WLAN-Anzeige ist aktiv."</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Dieser Bildschirm wird auf einem anderen Gerät angezeigt."</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Verbindung trennen"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Notruf"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Muster vergessen"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Falsches Muster"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Falsches Passwort"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Falsche PIN"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Versuchen Sie es in <xliff:g id="NUMBER">%d</xliff:g> Sekunden erneut."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Muster zeichnen"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"SIM-PIN eingeben"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"PIN eingeben"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Passwort eingeben"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"Die SIM-Karte ist jetzt deaktiviert. Geben Sie den PUK-Code ein, um fortzufahren. Weitere Informationen erhalten Sie von Ihrem Mobilfunkanbieter."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Gewünschten PIN-Code eingeben"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Gewünschten PIN-Code bestätigen"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM-Karte wird entsperrt…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Falscher PIN-Code"</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Geben Sie eine 4- bis 8-stellige PIN ein."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Der PUK-Code muss mindestens 8 Ziffern betragen."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Geben Sie den richtigen PUK-Code ein. Bei wiederholten Versuchen wird die SIM-Karte dauerhaft deaktiviert."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN-Codes stimmen nicht überein"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Zu viele Musterversuche"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Melden Sie sich zum Entsperren mit Ihrem Google-Konto an."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Nutzername (E-Mail)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Passwort"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Anmelden"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Ungültiger Nutzername oder ungültiges Passwort"</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Nutzernamen oder Passwort vergessen?"\n"Besuchen Sie "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Konto wird geprüft…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Sie haben Ihre PIN <xliff:g id="NUMBER_0">%d</xliff:g>-mal falsch eingegeben."\n\n"Versuchen Sie es in <xliff:g id="NUMBER_1">%d</xliff:g> Sekunden erneut."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Sie haben Ihr Passwort <xliff:g id="NUMBER_0">%d</xliff:g>-mal falsch eingegeben."\n\n"Versuchen Sie es in <xliff:g id="NUMBER_1">%d</xliff:g> Sekunden erneut."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Sie haben Ihr Entsperrungsmuster <xliff:g id="NUMBER_0">%d</xliff:g>-mal falsch gezeichnet. "\n\n"Versuchen Sie es in <xliff:g id="NUMBER_1">%d</xliff:g> Sekunden erneut."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Sie haben <xliff:g id="NUMBER_0">%d</xliff:g>-mal erfolglos versucht, das Tablet zu entsperren. Nach <xliff:g id="NUMBER_1">%d</xliff:g> weiteren erfolglosen Versuchen wird das Tablet auf die Werkseinstellungen zurückgesetzt und alle Nutzerdaten gehen verloren."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Sie haben <xliff:g id="NUMBER_0">%d</xliff:g>-mal erfolglos versucht, das Telefon zu entsperren. Nach <xliff:g id="NUMBER_1">%d</xliff:g> weiteren erfolglosen Versuchen wird das Telefon auf die Werkseinstellungen zurückgesetzt und alle Nutzerdaten gehen verloren."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Sie haben <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Tablet zu entsperren. Das Tablet wird nun auf die Werkseinstellungen zurückgesetzt."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Sie haben <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Telefon zu entsperren. Das Telefon wird nun auf die Werkseinstellungen zurückgesetzt."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Sie haben Ihr Entsperrungsmuster <xliff:g id="NUMBER_0">%d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%d</xliff:g> weiteren erfolglosen Versuchen werden Sie aufgefordert, Ihr Tablet mithilfe eines E-Mail-Kontos zu entsperren."\n\n" Versuchen Sie es in <xliff:g id="NUMBER_2">%d</xliff:g> Sekunden erneut."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Sie haben Ihr Entsperrungsmuster <xliff:g id="NUMBER_0">%d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%d</xliff:g> weiteren erfolglosen Versuchen werden Sie aufgefordert, Ihr Telefon mithilfe eines E-Mail-Kontos zu entsperren."\n\n" Versuchen Sie es in <xliff:g id="NUMBER_2">%d</xliff:g> Sekunden erneut."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Entfernen"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Lautstärke höher als Schwellenwert stellen?"\n"Wenn Sie über längere Zeiträume hinweg Musik in hoher Lautstärke hören, kann dies Ihr Gehör schädigen."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Drücken Sie mit zwei Fingern, um die Bedienungshilfen zu aktivieren."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Bedienungshilfen aktiviert"</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Bedienungshilfen abgebrochen"</string>
+    <string name="user_switched" msgid="3768006783166984410">"Aktueller Nutzer <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="owner_name" msgid="2716755460376028154">"Eigentümer"</string>
 </resources>
diff --git a/core/res/res/values-el/donottranslate-cldr.xml b/core/res/res/values-el/donottranslate-cldr.xml
index 1e7caa4..a0c69b5 100644
--- a/core/res/res/values-el/donottranslate-cldr.xml
+++ b/core/res/res/values-el/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Ιανουάριος</string>
-    <string name="month_long_standalone_february">Φεβρουάριος</string>
-    <string name="month_long_standalone_march">Μάρτιος</string>
-    <string name="month_long_standalone_april">Απρίλιος</string>
-    <string name="month_long_standalone_may">Μάιος</string>
-    <string name="month_long_standalone_june">Ιούνιος</string>
-    <string name="month_long_standalone_july">Ιούλιος</string>
-    <string name="month_long_standalone_august">Αύγουστος</string>
-    <string name="month_long_standalone_september">Σεπτέμβριος</string>
-    <string name="month_long_standalone_october">Οκτώβριος</string>
-    <string name="month_long_standalone_november">Νοέμβριος</string>
-    <string name="month_long_standalone_december">Δεκέμβριος</string>
-
-    <string name="month_long_january">Ιανουαρίου</string>
-    <string name="month_long_february">Φεβρουαρίου</string>
-    <string name="month_long_march">Μαρτίου</string>
-    <string name="month_long_april">Απριλίου</string>
-    <string name="month_long_may">Μαΐου</string>
-    <string name="month_long_june">Ιουνίου</string>
-    <string name="month_long_july">Ιουλίου</string>
-    <string name="month_long_august">Αυγούστου</string>
-    <string name="month_long_september">Σεπτεμβρίου</string>
-    <string name="month_long_october">Οκτωβρίου</string>
-    <string name="month_long_november">Νοεμβρίου</string>
-    <string name="month_long_december">Δεκεμβρίου</string>
-
-    <string name="month_medium_january">Ιαν</string>
-    <string name="month_medium_february">Φεβ</string>
-    <string name="month_medium_march">Μαρ</string>
-    <string name="month_medium_april">Απρ</string>
-    <string name="month_medium_may">Μαϊ</string>
-    <string name="month_medium_june">Ιουν</string>
-    <string name="month_medium_july">Ιουλ</string>
-    <string name="month_medium_august">Αυγ</string>
-    <string name="month_medium_september">Σεπ</string>
-    <string name="month_medium_october">Οκτ</string>
-    <string name="month_medium_november">Νοε</string>
-    <string name="month_medium_december">Δεκ</string>
-
-    <string name="month_shortest_january">Ι</string>
-    <string name="month_shortest_february">Φ</string>
-    <string name="month_shortest_march">Μ</string>
-    <string name="month_shortest_april">Α</string>
-    <string name="month_shortest_may">Μ</string>
-    <string name="month_shortest_june">Ι</string>
-    <string name="month_shortest_july">Ι</string>
-    <string name="month_shortest_august">Α</string>
-    <string name="month_shortest_september">Σ</string>
-    <string name="month_shortest_october">Ο</string>
-    <string name="month_shortest_november">Ν</string>
-    <string name="month_shortest_december">Δ</string>
-
-    <string name="day_of_week_long_sunday">Κυριακή</string>
-    <string name="day_of_week_long_monday">Δευτέρα</string>
-    <string name="day_of_week_long_tuesday">Τρίτη</string>
-    <string name="day_of_week_long_wednesday">Τετάρτη</string>
-    <string name="day_of_week_long_thursday">Πέμπτη</string>
-    <string name="day_of_week_long_friday">Παρασκευή</string>
-    <string name="day_of_week_long_saturday">Σάββατο</string>
-
-    <string name="day_of_week_medium_sunday">Κυρ</string>
-    <string name="day_of_week_medium_monday">Δευ</string>
-    <string name="day_of_week_medium_tuesday">Τρι</string>
-    <string name="day_of_week_medium_wednesday">Τετ</string>
-    <string name="day_of_week_medium_thursday">Πεμ</string>
-    <string name="day_of_week_medium_friday">Παρ</string>
-    <string name="day_of_week_medium_saturday">Σαβ</string>
-
-    <string name="day_of_week_short_sunday">Κυρ</string>
-    <string name="day_of_week_short_monday">Δευ</string>
-    <string name="day_of_week_short_tuesday">Τρι</string>
-    <string name="day_of_week_short_wednesday">Τετ</string>
-    <string name="day_of_week_short_thursday">Πεμ</string>
-    <string name="day_of_week_short_friday">Παρ</string>
-    <string name="day_of_week_short_saturday">Σαβ</string>
-
-    <string name="day_of_week_shortest_sunday">Κ</string>
-    <string name="day_of_week_shortest_monday">Δ</string>
-    <string name="day_of_week_shortest_tuesday">Τ</string>
-    <string name="day_of_week_shortest_wednesday">Τ</string>
-    <string name="day_of_week_shortest_thursday">Π</string>
-    <string name="day_of_week_shortest_friday">Π</string>
-    <string name="day_of_week_shortest_saturday">Σ</string>
-
-    <string name="am">π.μ.</string>
-    <string name="pm">μ.μ.</string>
-    <string name="yesterday">Χτες</string>
-    <string name="today">Σήμερα</string>
-    <string name="tomorrow">Αύριο</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 223e096..32d6d3d 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Επιλογές τηλεφώνου"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Κλείδωμα οθόνης"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Απενεργοποίηση"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Αναφορά σφαλμάτων"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Λήψη αναφοράς σφάλματος"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Θα συλλέξει πληροφορίες σχετικά με την τρέχουσα κατάσταση της συσκευής σας και θα τις στείλει μέσω μηνύματος ηλεκτρονικού ταχυδρομείου. Απαιτείται λίγος χρόνος για τη σύνταξη της αναφοράς σφάλματος και την αποστολή της. Κάντε λίγη υπομονή."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Λειτουργία σίγασης"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Ο ήχος είναι απενεργοποιημένος"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Ο ήχος είναι ενεργοποιημένος"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Τα μηνύματά σας"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Ανάγνωση και εγγραφή μηνυμάτων SMS, μηνυμάτων ηλεκτρονικού ταχυδρομείου και άλλων μηνυμάτων."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Οι προσωπικές σας πληροφορίες"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Άμεση πρόσβαση στις επαφές και στο ημερολόγιό σας που είναι αποθηκευμένα στο tablet."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Άμεση πρόσβαση στις επαφές και στο ημερολόγιό σας που είναι αποθηκευμένα στο τηλέφωνο."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Άμεση πρόσβαση σε πληροφορίες σχετικά με εσάς, οι οποίες είναι αποθηκευμένες στην κάρτα επαφών σας."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Οι κοινωνικές πληροφορίες σας"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Άμεση πρόσβαση σε πληροφορίες σχετικά με τις επαφές και τις κοινωνικές συνδέσεις σας."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Η τοποθεσία σας"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Παρακολούθηση της φυσικής τοποθεσίας σας."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Επικοινωνία δικτύου"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Πρόσβαση σε διάφορες λειτουργίες δικτύου."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Πρόσβαση σε συσκευές και δίκτυα μέσω Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Ρυθμίσεις ήχου"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Αλλαγή ρυθμίσεων ήχου."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Επηρεάζει την μπαταρία"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Χρήση λειτουργιών που μπορούν να εξαντλήσουν γρήγορα την μπαταρία."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Ημερολόγιο"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Άμεση πρόσβαση σε ημερολόγιο και συμβάντα."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Ανάγνωση λεξικού χρήστη"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Ανάγνωση λέξεων στο λεξικό χρήστη."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Εγγραφή στο λεξικό χρήστη"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Προσθήκη λέξεων στο λεξικό χρήστη."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Σελιδοδείκτες και ιστορικό"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Άμεση πρόσβαση σε σελιδοδείκτες και ιστορικού προγράμματος περιήγησης."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Ξυπνητήρι"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Ρύθμιση ξυπνητηριού."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Αυτόματος τηλεφωνητής"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Άμεση πρόσβαση στον αυτόματο τηλεφωνητή."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Μικρόφωνο"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Άμεση πρόσβαση στο μικρόφωνο για την εγγραφή ήχου."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Κάμερα"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Άμεση πρόσβαση σε κάμερα για λήψη εικόνας ή βίντεο."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Οι πληροφορίες των εφαρμογών σας"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Δυνατότητα επιρροής συμπεριφοράς άλλων εφαρμογών στη συσκευή σας."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Ταπετσαρία"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Αλλαγή των ρυθμίσεων ταπετσαρίας συσκευής."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Ρολόι"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Αλλαγή της ώρας ή της ζώνης ώρας συσκευής."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Γραμμή κατάστασης"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Αλλαγή των ρυθμίσεων γραμμής κατάστασης συσκευής."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Ρυθμίσεις συγχρονισμού"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Πρόσβαση στις ρυθμίσεις συγχρονισμού."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Οι λογαριασμοί σας"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Πρόσβαση στους διαθέσιμους λογαριασμούς."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Στοιχεία ελέγχου υλικού"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Χαμηλού επιπέδου πρόσβαση και έλεγχος του συστήματος."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Εργαλεία ανάπτυξης"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Δυνατότητες που είναι απαραίτητες μόνο σε προγραμματιστές εφαρμογών."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Άλλες διεπαφές εφαρμογών"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Επιρροή διεπαφής άλλων εφαρμογών."</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>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Επιτρέπει στην εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων WAP. Αυτό σημαίνει ότι η εφαρμογή θα μπορούσε να παρακολουθήσει ή να διαγράψει τα μηνύματα που αποστέλλονται στη συσκευή σας χωρίς αυτά να εμφανιστούν σε εσάς."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"ανάκτηση εκτελούμενων εφαρμογών"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Επιτρέπει στην εφαρμογή την ανάκτηση πληροφοριών σχετικά με τρέχουσες και πρόσφατα εκτελούμενες εργασίες. Αυτό μπορεί να δίνει τη δυνατότητα στην εφαρμογή να ανακαλύπτει πληροφορίες σχετικά με το ποιες εφαρμογές χρησιμοποιούνται στη συσκευή."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"αλληλεπίδραση στους χρήστες"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Δίνει στην εφαρμογή τη δυνατότητα να πραγματοποιεί ενέργειες σε όλους τους διαφορετικούς χρήστες στη συσκευή. Οι κακόβουλες εφαρμογές ενδέχεται να χρησιμοποιήσουν αυτή τη δυνατότητα για να παραβιάσουν την προστασία μεταξύ των χρηστών."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"πλήρης άδεια αλληλεπίδρασης στους χρήστες"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Επιτρέπει όλες τις πιθανές αλληλεπιδράσεις στους χρήστες."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"διαχείριση χρηστών"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Επιτρέπει στις εφαρμογές να διαχειρίζονται τους χρήστες της συσκευής, συμπεριλαμβανομένων των ερωτημάτων της δημιουργίας και της διαγραφής."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"ανάκτηση λεπτομερειών σχετικά με τις εκτελούμενες εφαρμογές"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Επιτρέπει στην εφαρμογή την ανάκτηση λεπτομερών πληροφοριών σχετικά με τις τρέχουσες εκτελούμενες εργασίες και τις εργασίες που έχουν εκτελεστεί πρόσφατα. Τυχόν κακόβουλες εφαρμογές ενδέχεται να ανακαλύψουν ιδιωτικές πληροφορίες σχετικά με άλλες εφαρμογές."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"αναδιάταξη εκτελούμενων εφαρμογών"</string>
@@ -243,6 +287,14 @@
     <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="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"προσωρινή ενεργοποίηση προσβασιμότητας"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Επιτρέπει σε μια εφαρμογή να ενεργοποιήσει την προσβασιμότητα στη συσκευή. Οι κακόβουλες εφαρμογές ενδέχεται να ενεργοποιήσουν την προσβασιμότητα χωρίς τη συγκατάθεση των χρηστών."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"ανάκτηση πληροφοριών παραθύρων"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Επιτρέπει σε μια εφαρμογή να ανακτήσει πληροφορίες σχετικά με τα παράθυρα από το διαχειριστή παραθύρων. Οι κακόβουλες εφαρμογές ενδέχεται να ανακτήσουν πληροφορίες που προορίζονται για την εσωτερική χρήση του συστήματος."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"φιλτράρισμα συμβάντων"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Επιτρέπει σε μια εφαρμογή να καταγράφει ένα φίλτρο εισαγωγής, το οποίο φιλτράρει τη ροή όλων των συμβάντων χρήστη πριν την αποστολή τους. Μια κακόβουλη εφαρμογή μπορεί να ελέγξει τη διεπαφή του συστήματος χωρίς την παρέμβαση του χρήστη."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"μεγέθυνση οθόνης"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Επιτρέπει στην εφαρμογή να μεγεθύνει το περιεχόμενο της οθόνης. Οι κακόβουλες εφαρμογές ενδέχεται να τροποποιούν το περιεχόμενο της οθόνης με τέτοιο τρόπο ώστε η εφαρμογή να μην μπορεί να χρησιμοποιηθεί."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"μερικός τερματισμός λειτουργίας"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Θέτει το πρόγραμμα διαχείρισης δραστηριοτήτων σε κατάσταση τερματισμού λειτουργιών. Δεν εκτελεί πλήρη τερματισμό λειτουργιών."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"αποτροπή εναλλαγών εφαρμογών"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Επιτρέπει στην εφαρμογή τον έλεγχο του μέγιστου αριθμού διαδικασιών που θα εκτελούνται. Δεν είναι απαραίτητο για συνήθεις εφαρμογές."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"αναγκαστικός τερματισμός εφαρμογών στο παρασκήνιο"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Επιτρέπει στην εφαρμογή να ελέγχει αν οι δραστηριότητες ολοκληρώνονται πάντοτε μόλις μεταβούν στο φόντο. Δεν απαιτείται για συνήθεις εφαρμογές."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"τροποποίηση στατιστικών μπαταρίας"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Επιτρέπει στην εφαρμογή την τροποποίηση στατιστικών μπαταρίας που έχουν συλλεχθεί. Δεν πρέπει να χρησιμοποιείται από συνήθεις εφαρμογές."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"ανάγνωση στατιστικών στοιχείων μπαταρίας"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Επιτρέπει σε μια εφαρμογή να διαβάζει τα δεδομένα τρέχουσας χαμηλού επιπέδου χρήσης μπαταρίας. Ενδέχεται να επιτρέπει στην εφαρμογή να εντοπίσει λεπτομερείς πληροφορίες σχετικά με τις εφαρμογές που χρησιμοποιείτε."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"τροποποίηση στατιστικών στοιχείων μπαταρίας"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Επιτρέπει στην εφαρμογή την τροποποίηση στατιστικών στοιχείων μπαταρίας που έχουν συλλεχθεί. Δεν πρέπει να χρησιμοποιείται από συνήθεις εφαρμογές."</string>
     <string name="permlab_backup" msgid="470013022865453920">"αντίγραφο ασφαλείας και επαναφορά συστήματος"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Επιτρέπει στην εφαρμογή τον έλεγχο του μηχανισμού δημιουργίας αντιγράφων ασφάλειας και ανάκτησης. Δεν προορίζεται για χρήση με συνήθεις εφαρμογές."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"επιβεβαίωση δημιουργίας πλήρους αντιγράφου ασφαλείας ή επαναφοράς λειτουργίας"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"προβολή μη εξουσιοδοτημένων παραθύρων"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Επιτρέπει στην εφαρμογή τη δημιουργία παραθύρων τα οποία προορίζονται για χρήση από τη διεπαφή χρήστη του εσωτερικού συστήματος. Δεν προορίζεται για χρήση με συνήθεις εφαρμογές."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"σχεδίαση πάνω σε άλλες εφαρμογές"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Επιτρέπει στην εφαρμογή την προβολή παραθύρων ειδοποίησης συστήματος. Ορισμένα παράθυρα ειδοποίησης μπορούν να εμφανιστούν σε ολόκληρη την οθόνη."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Επιτρέπει στην εφαρμογή το σχεδιασμό πάνω σε άλλες εφαρμογές ή τμήματα του περιβάλλοντος χρήστη. Ενδέχεται να παρεμβαίνουν στη χρήση του περιβάλλοντος σε άλλες εφαρμογές ή να αλλάζουν τα στοιχεία που βλέπετε σε άλλες εφαρμογές."</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="permlab_freezeScreen" msgid="4708181184441880175">"πάγωμα οθόνης"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Επιτρέπει στην εφαρμογή να παγώσει προσωρινά την οθόνη για μια μετάβαση πλήρους οθόνης."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"πάτημα πλήκτρων και κουμπιών ελέγχου"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Επιτρέπει στην εφαρμογή την εμφάνιση των δικών της συμβάντων εισόδου (πάτημα πλήκτρων, κλπ.) σε άλλες εφαρμογές. Τυχόν κακόβουλες εφαρμογές ενδέχεται να χρησιμοποιήσουν αυτήν τη δυνατότητα για να εμφανιστούν στο tablet."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Επιτρέπει στην εφαρμογή την εμφάνιση των δικών της συμβάντων εισόδου (πάτημα πλήκτρων, κλπ.) σε άλλες εφαρμογές. Τυχόν κακόβουλες εφαρμογές ενδέχεται να χρησιμοποιήσουν αυτήν τη δυνατότητα για να εμφανιστούν στο τηλέφωνο."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"απευθείας εγκατάσταση εφαρμογών"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Επιτρέπει στην εφαρμογή την εγκατάσταση νέων ή ενημερωμένων πακέτων Android. Τυχόν κακόβουλες εφαρμογές ενδέχεται να χρησιμοποιήσουν αυτήν τη δυνατότητα για να προσθέσουν νέες εφαρμογές με πολλές αυθαίρετες άδειες."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"διαγραφή όλων των δεδομένων προσωρινής μνήμης εφαρμογής"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Επιτρέπει στην εφαρμογή την απελευθέρωση αποθηκευτικού χώρου στο tablet μέσω της διαγραφής αρχείων στον κατάλογο προσωρινής αποθήκευσης. Η πρόσβαση περιορίζεται συνήθως αυστηρά στην επεξεργασία του συστήματος."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Επιτρέπει στην εφαρμογή την απελευθέρωση αποθηκευτικού χώρου στο τηλέφωνο μέσω της διαγραφής αρχείων στον κατάλογο προσωρινής αποθήκευσης. Η πρόσβαση περιορίζεται συνήθως αυστηρά στην επεξεργασία του συστήματος."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Επιτρέπει στην εφαρμογή να εξοικονομήσει χώρο αποθήκευσης στο tablet διαγράφοντας αρχεία στους καταλόγους προσωρινής μνήμης άλλων εφαρμογών. Για αυτόν το λόγο, η εκκίνηση άλλων εφαρμογών ενδέχεται να επιβραδυνθεί, καθώς θα πρέπει να ανακτήσουν εκ νέου τα δεδομένα τους."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Επιτρέπει στην εφαρμογή να εξοικονομήσει χώρο αποθήκευσης στο τηλέφωνο διαγράφοντας αρχεία στους καταλόγους προσωρινής μνήμης άλλων εφαρμογών. Για αυτόν το λόγο, η εκκίνηση άλλων εφαρμογών ενδέχεται να επιβραδυνθεί, καθώς θα πρέπει να ανακτήσουν εκ νέου τα δεδομένα τους."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"μετακίνηση πόρων εφαρμογής"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Επιτρέπει στην εφαρμογή την μετακίνηση πόρων εφαρμογών από εσωτερικά μέσα σε εξωτερικά και αντίστροφα."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"ανάγνωση ευαίσθητων δεδομένων αρχείου καταγραφής"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Επιτρέπει στην εφαρμογή την πρόσβαση σε επιπλέον εντολές παρόχου τοποθεσίας. Αυτό μπορεί να δώσει τη δυνατότητα στην εφαρμογή να παρέμβει στη λειτουργία του GPS ή άλλων πηγών τοποθεσίας."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"άδεια για εγκατάσταση ενός παρόχου τοποθεσίας"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Δημιουργεί ψευδείς πηγές τοποθεσίας για τη δοκιμή ή την εγκατάσταση νέου παρόχου τοποθεσίας. Αυτό δίνει τη δυνατότητα στην εφαρμογή να παρακάμπτει την τοποθεσία και/ή την κατάσταση που επιστρέφεται από άλλες πηγές τοποθεσίας, όπως το GPS ή οι πάροχοι τοποθεσίας."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"ακριβής (GPS) τοποθεσία"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Ακριβής πρόσβαση σε τοποθεσία με χρήση πηγών όπως το Παγκόσμιο Σύστημα Εντοπισμού (GPS) στο tablet. Όταν οι υπηρεσίες τοποθεσίας είναι διαθέσιμες και ενεργοποιημένες, αυτή η άδεια επιτρέπει στην εφαρμογή να προσδιορίσει την τοποθεσία σας με ακρίβεια."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Ακριβής πρόσβαση σε τοποθεσία με χρήση πηγών, όπως το Παγκόσμιο Σύστημα Εντοπισμού (GPS) στο τηλέφωνο. Όταν οι υπηρεσίες τοποθεσίας είναι διαθέσιμες και ενεργοποιημένες, αυτή η άδεια επιτρέπει στην εφαρμογή να προσδιορίσει την τοποθεσία σας με ακρίβεια."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"κατά προσέγγιση (βασισμένη στο δίκτυο) τοποθεσία"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Πρόσβαση σε τοποθεσία κατά προσέγγιση από παρόχους τοποθεσίας με χρήση πηγών δικτύου, όπως κεραίες κινητής τηλεφωνίας και Wi-Fi. Όταν αυτές οι υπηρεσίες τοποθεσίας είναι διαθέσιμες και ενεργοποιημένες, η συγκεκριμένη άδεια επιτρέπει στην εφαρμογή να προσδιορίσει την κατά προσέγγιση τοποθεσία σας."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"ακριβής θέση (GPS και βάσει δικτύου)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Επιτρέπει στην εφαρμογή να λαμβάνει την ακριβή θέση σας με τη χρήση του Παγκόσμιου Συστήματος Εντοπισμού (GPS) ή πηγών τοποθεσίας δικτύου, όπως κεραίες κινητής τηλεφωνίας και Wi-Fi. Αυτές οι υπηρεσίες τοποθεσίας πρέπει να είναι ενεργοποιημένες και διαθέσιμες στην συσκευή σας, ώστε να μπορούν να χρησιμοποιηθούν από την εφαρμογή. Οι εφαρμογές ενδέχεται να τις χρησιμοποιήσουν για να προσδιορίσουν τη θέση σας και ενδέχεται να καταναλώσουν επιπλέον ισχύ μπαταρίας."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"κατά προσέγγιση θέση (βάσει δικτύου)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Επιτρέπει στην εφαρμογή τη λήψη της κατά προσέγγιση τοποθεσίας σας. Αυτή η τοποθεσία προκύπτει από τις υπηρεσίες τοποθεσίας με τη χρήση πηγών τοποθεσίας δικτύου, όπως κεραίες κινητής τηλεφωνίας και Wi-Fi. Αυτές οι υπηρεσίες τοποθεσίας πρέπει να είναι ενεργοποιημένες και διαθέσιμες στην συσκευή σας, ώστε να μπορούν να χρησιμοποιηθούν από την εφαρμογή. Οι εφαρμογές ενδέχεται να τις χρησιμοποιήσουν για να προσδιορίσουν κατά προσέγγιση τη θέση σας."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"πρόσβαση στο 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="permlab_configureWifiDisplay" msgid="5595661694746742168">"διαμόρφωση οθονών Wifi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Επιτρέπει τη διαμόρφωση της εφαρμογής και τη σύνδεσης σε οθόνες Wifi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"έλεγχος οθονών Wifi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Επιτρέπει στην εφαρμογή τον έλεγχο των λειτουργιών χαμηλού επιπέδου των οθονών Wifi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"αλλαγή των ρυθμίσεων ήχου"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Επιτρέπει στην εφαρμογή την τροποποίηση καθολικών ρυθμίσεων ήχου, όπως η ένταση και ποιο ηχείο χρησιμοποιείται για έξοδο."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"εγγραφή ήχου"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"πρόσβαση στις ρυθμίσεις Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Επιτρέπει στην εφαρμογή τη διαμόρφωση του τοπικού tablet Bluetooth, τον εντοπισμό και τη σύζευξη με απομακρυσμένες συσκευές."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Επιτρέπει στην εφαρμογή τη διαμόρφωση του τοπικού tablet Bluetooth, τον εντοπισμό και τη σύζευξη με απομακρυσμένες συσκευές."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Προβολή συνδέσεων WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"σύνδεση και αποσύνδεση από το WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Επιτρέπει στην εφαρμογή να προσδιορίζει εάν το WiMAX είναι ενεργοποιημένο και πληροφορίες σχετικά με τυχόν δίκτυα WiMAX που είναι συνδεδεμένα."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Αλλαγή κατάστασης WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Επιτρέπει στην εφαρμογή τη σύνδεση στο tablet και την αποσύνδεση από αυτό, από δίκτυα WiMAX."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Επιτρέπει στην εφαρμογή να τροποποιήσει τις ροές δεδομένων, με τις οποίες είστε συγχρονισμένοι αυτήν τη στιγμή. Τυχόν κακόβουλες εφαρμογές ενδέχεται να αλλάξουν τις συγχρονισμένες ροές δεδομένων σας."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"ανάγνωση όρων που έχετε προσθέσει στο λεξικό"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Επιτρέπει στην εφαρμογή την ανάγνωση όλων των λέξεων, των ονομάτων και φράσεων, τα οποία ο χρήστης ενδέχεται να έχει αποθηκεύσει στο λεξικό χρήστη."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"εγγραφή σε λεξικό καθορισμένο από τον χρήστη"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"προσθήκη λέξεων στο καθορισμένο από το χρήστη λεξικό"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Επιτρέπει στην εφαρμογή την εγγραφή νέων λέξεων στο λεξικό χρήστη."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"δοκιμή πρόσβασης σε προστατευμένο χώρο αποθήκευσης"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"δοκιμή πρόσβασης σε προστατευμένο χώρο αποθήκευσης"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Επιτρέπει στην εφαρμογή τη δοκιμή μια άδειας για το χώρο αποθήκευσης USB που θα διατίθεται σε μελλοντικές συσκευές."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Επιτρέπει USB για άλλες συσκ."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Επιτρέπει στην εφαρμογή τη δοκιμή μια άδειας για την κάρτα SD που θα διατίθεται σε μελλοντικές συσκευές."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"τροπ. ή διαγρ. περιεχ. αποθ. χώρ. USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"τροποποίηση ή διαγραφή των περιεχομένων της κάρτας SD"</string>
@@ -534,6 +593,8 @@
     <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="permlab_sdcardAccessAll" msgid="8150613823900460576">"πρόσβ.εξωτ.χωρ. αποθ. όλων των χρηστ."</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Επιτρέπει στην εφαρμογή να αποκτήσει πρόσβαση σε εξωτερικό χώρο αποθήκευσης για όλους τους χρήστες."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"πρόσβαση στο σύστημα αρχείων προσωρινής μνήμης"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Επιτρέπει στην εφαρμογή την ανάγνωση και την εγγραφή του συστήματος αρχείων προσωρινής μνήμης."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"πραγματοποίηση/λήψη κλήσεων μέσω Διαδικτύου"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Να απαιτείται η κρυπτογράφηση των αποθηκευμένων δεδομένων εφαρμογής"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Απενεργοποίηση φωτογρ. μηχανών"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Να αποτρέπεται η χρήση των φωτογραφικών μηχανών της συσκευής."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Απενεργοποίηση λειτουργιών στο κλείδωμα πληκτρολογίου"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Αποφυγή της χρήσης ορισμένων λειτουργιών στο κλείδωμα πληκτρολογίου."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Οικία"</item>
     <item msgid="869923650527136615">"Κινητό"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Προσπαθήστε ξανά"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Έγινε υπέρβαση του μέγιστου αριθμού προσπαθειών Face Unlock"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Φόρτιση, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Φορτίστηκε."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Χρεώθηκε"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Συνδέστε τον φορτιστή."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Δεν υπάρχει κάρτα SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Δεν υπάρχει κάρτα SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Δεν υπάρχει κάρτα SIM στο tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Δεν υπάρχει κάρτα SIM στο τηλέφωνο."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Τοποθετήστε μια κάρτα SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Το μοτίβο απαλείφθηκε"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Προστέθηκε κελί"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Το μοτίβο ολοκληρώθηκε"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Προσθήκη γραφικού στοιχείου"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Κενή"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Ανάπτυξη της περιοχής ξεκλειδώματος."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Σύμπτυξη της περιοχής ξεκλειδώματος."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Γραφικό στοιχείο <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Επιλογέας χρήστη"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Κατάσταση"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Φωτογραφική μηχανή"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Στοιχεία ελέγχου μέσων"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Έχει ξεκινήσει η αναδιάταξη των γραφικών στοιχείων."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Έχει ολοκληρωθεί η αναδιάταξη των γραφικών στοιχείων."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Το γραφικό στοιχείο <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> έχει διαγραφεί."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Ανάπτυξη περιοχής ξεκλειδώματος."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Ξεκλείδωμα ολίσθησης."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Ξεκλείδωμα μοτίβου."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Face unlock."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Ξεκλείδωμα κωδικού ασφαλείας"</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Ξεκλείδωμα κωδικού πρόσβασης."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Περιοχή μοτίβου."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Περιοχή ολίσθησης"</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ΑΒΓ"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Αντιγραφή διεύθυνσης URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Επιλογή κειμένου"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Επιλογή κειμένου"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"προσθήκη στο λεξικό"</string>
-    <string name="deleteText" msgid="7070985395199629156">"διαγραφή"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Προσθήκη στο λεξικό"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Διαγραφή"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Μέθοδος εισόδου"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Ενέργειες κειμένου"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Ο χώρος αποθήκευσης εξαντλείται"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Υπάρχουν διαθέσιμα ανοικτά δίκτυα Wi-Fi"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Σύνδεση στο δίκτυο Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Σύνδεση σε δίκτυο"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Δεν είναι δυνατή η σύνδεση στο Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" έχει κακή σύνδεση στο Διαδίκτυο."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Προς:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Πληκτρολογήστε τον απαιτούμενο κωδικό PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Το τηλέφωνο θα αποσυνδεθεί προσωρινά από το δίκτυο Wi-Fi ενώ συνδέεται στη συσκευή <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Εισαγωγή χαρακτήρα"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Αποστολή μηνυμάτων SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"Η εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; στέλνει έναν μεγάλο αριθμό μηνυμάτων SMS. Θέλετε να επιτρέψετε σε αυτήν την εφαρμογή να συνεχίσει να στέλνει μηνύματα;"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Αποδοχή"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Άρνηση"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"Η εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; θέλει να αποστείλει ένα μήνυμα στη διεύθυνση &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Αυτή η ρύθμιση "<font fgcolor="#ffffb060">"ενδέχεται να επιφέρει χρεώσεις"</font>" στον λογαριασμό κινητού σας."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Αυτή η ρύθμιση θα επιφέρει χρεώσεις στον λογαριασμό κινητού σας."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Αποστολή"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Ακύρωση"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Απομνημόνευση της επιλογής μου"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Μπορ.να το αλλάξ.αργ.στις Ρυθ. &gt; Εφ."</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Να επιτρέπεται πάντα"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Να μην επιτρέπεται ποτέ"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Η κάρτα SIM αφαιρέθηκε"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Το δίκτυο κινητής τηλεφωνίας δεν θα είναι διαθέσιμο μέχρι να κάνετε επανεκκίνηση αφού τοποθετήσετε μια έγκυρη κάρτα SIM."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Τέλος"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Ορισμός ημερομηνίας"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ορισμός"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Τέλος"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Προεπιλεγμένο"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Δεν απαιτούνται άδειες"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Απόκρυψη"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Εμφάνιση όλων"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"ΝΕΟ: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"ΝΕΟ: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Παρέχεται από την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Δεν απαιτούνται άδειες"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"ενδέχεται να χρεωθείτε"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Μαζική αποθήκευση USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Το USB είναι συνδεδεμένο"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Συνδεθήκατε στον υπολογιστή σας μέσω USB. Αγγίξτε το παρακάτω κουμπί, αν θέλετε να κάνετε αντιγραφή αρχείων μεταξύ του υπολογιστή και του χώρου αποθήκευσης USB του Android."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"Το VPN ενεργοποιήθηκε από την εφαρμογή <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Αγγίξτε για τη διαχείριση του δικτύου."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Συνδέθηκε με <xliff:g id="SESSION">%s</xliff:g>. Αγγίξτε για τη διαχείριση του δικτύου."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Σύνδεση πάντα ενεργοποιημένου VPN…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Έχει συνδεθεί πάντα ενεργοποιημένο VPN"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Σφάλμα πάντα ενεργοποιημένου VPN"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Αγγίξτε για επαναφορά της σύνδεσης"</string>
     <string name="upload_file" msgid="2897957172366730416">"Επιλογή αρχείου"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Δεν έχει επιλεγεί αρχείο"</string>
     <string name="reset" msgid="2448168080964209908">"Επαναφορά"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Κοινή χρ."</string>
     <string name="find" msgid="4808270900322985960">"Εύρεση"</string>
     <string name="websearch" msgid="4337157977400211589">"Αναζήτηση ιστού"</string>
+    <string name="find_next" msgid="5742124618942193978">"Εύρεση επόμενου"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Εύρεση προηγούμενου"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Αίτημα τοποθεσίας από <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Αίτημα τοποθεσίας"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Ζητήθηκε από <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Τηλέφωνο"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Ακουστικά"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Ηχεία βάσης σύνδεσης"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Ήχος HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Σύστημα"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Ήχος Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Τέλος"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Έξοδος μέσων"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Σάρωση…"</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Σύνδεση…"</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Διαθέσιμη"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Μη διαθέσιμο"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Ενσωματωμένη οθόνη"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Οθόνη HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Επικάλυψη #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Έχει συνδεθεί ασύρματη οθόνη"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Αυτή η οθόνη εμφανίζεται σε μια άλλη συσκευή"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Αποσύνδεση"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Κλήσεις επείγουσας ανάγκης"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Ξεχάσατε το μοτίβο"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Εσφαλμένο μοτίβο"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Εσφαλμένος κωδικός πρόσβασης"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Εσφαλμένος κωδικός PIN"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Δοκιμάστε ξανά σε <xliff:g id="NUMBER">%d</xliff:g> δευτερόλεπτα."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Σχεδιάστε το μοτίβο σας"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Εισαγωγή PIN SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Πληκτρολογήστε το PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Εισαγάγετε κωδικό πρόσβασης"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"Η κάρτα SIM είναι απενεργοποιημένη αυτή τη στιγμή. Εισαγάγετε τον κωδικό PUK για να συνεχίσετε. Επικοινωνήστε με την εταιρεία κινητής τηλεφωνίας σας για λεπτομέρειες."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Εισαγάγετε τον απαιτούμενο κωδικό PIN"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Επιβεβαιώστε τον απαιτούμενο κωδικό PIN"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Ξεκλείδωμα κάρτας SIM..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Εσφαλμένος κωδικός PIN."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Πληκτρολογήστε έναν αριθμό PIN που να αποτελείται από 4 έως 8 αριθμούς."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Ο κωδικός PUK θα πρέπει να περιέχει τουλάχιστον 8 αριθμούς."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Εισαγάγετε ξανά τον κωδικό PUK. Οι επαναλαμβανόμενες προσπάθειες θα απενεργοποιήσουν οριστικά την κάρτα SIM."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Δεν υπάρχει αντιστοιχία των κωδικών PIN"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Πάρα πολλές προσπάθειες μοτίβου"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Για ξεκλείδωμα, συνδεθείτε με τον λογαριασμό σας Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Όνομα χρήστη (διεύθυνση ηλεκτρονικού ταχυδρομείου)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Κωδικός πρόσβασης"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Σύνδεση"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Μη έγκυρο όνομα χρήστη ή κωδικός πρόσβασης."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Ξεχάσατε το όνομα χρήστη ή τον κωδικό πρόσβασής σας;"\n"Επισκεφτείτε τη διεύθυνση "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Έλεγχος λογαριασμού…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Έχετε πληκτρολογήσει εσφαλμένα τον κωδικό σας PIN <xliff:g id="NUMBER_0">%d</xliff:g> φορές. "\n\n"Δοκιμάστε ξανά σε <xliff:g id="NUMBER_1">%d</xliff:g> δευτερόλεπτα."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Έχετε πληκτρολογήσει τον κωδικό πρόσβασης εσφαλμένα <xliff:g id="NUMBER_0">%d</xliff:g> φορές. "\n\n"Δοκιμάστε ξανά σε <xliff:g id="NUMBER_1">%d</xliff:g> δευτερόλεπτα."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Σχεδιάσατε εσφαλμένα το μοτίβο ξεκλειδώματος <xliff:g id="NUMBER_0">%d</xliff:g> φορές. "\n\n"Δοκιμάστε ξανά σε <xliff:g id="NUMBER_1">%d</xliff:g> δευτερόλετπα."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Προσπαθήσατε να ξεκλειδώσετε εσφαλμένα το tablet <xliff:g id="NUMBER_0">%d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%d</xliff:g> προσπάθειες, το tablet θα επαναφερθεί στις εργοστασιακές ρυθμίσεις και όλα τα δεδομένα χρήστη θα χαθούν."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Προσπαθήσατε να ξεκλειδώσετε εσφαλμένα το τηλέφωνο <xliff:g id="NUMBER_0">%d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%d</xliff:g> προσπάθειες, το τηλέφωνο θα επαναφερθεί στις εργοστασιακές ρυθμίσεις και όλα τα δεδομένα χρήστη θα χαθούν."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Προσπαθήσατε να ξεκλειδώσετε εσφαλμένα το tablet <xliff:g id="NUMBER">%d</xliff:g> φορές. Το tablet θα επαναφερθεί στις εργοστασιακές ρυθμίσεις."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Προσπαθήσατε να ξεκλειδώσετε εσφαλμένα το τηλέφωνο <xliff:g id="NUMBER">%d</xliff:g> φορές. Το τηλέφωνο θα επαναφερθεί στις εργοστασιακές ρυθμίσεις."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Σχεδιάσατε το μοτίβο ξεκλειδώματος εσφαλμένα <xliff:g id="NUMBER_0">%d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%d</xliff:g> ανεπιτυχείς προσπάθειες ακόμη, θα σας ζητηθεί να ξεκλειδώσετε το tablet σας με τη χρήση ενός λογαριασμού ηλεκτρονικού ταχυδρομείου."\n\n" Δοκιμάστε να συνδεθείτε ξανά σε <xliff:g id="NUMBER_2">%d</xliff:g> δευτερόλεπτα."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Σχεδιάσατε το μοτίβο ξεκλειδώματος εσφαλμένα <xliff:g id="NUMBER_0">%d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%d</xliff:g> ανεπιτυχείς προσπάθειες ακόμη, θα σας ζητηθεί να ξεκλειδώσετε το τηλέφωνό σας με τη χρήση ενός λογαριασμού ηλεκτρονικού ταχυδρομείου."\n\n" Δοκιμάστε ξανά σε <xliff:g id="NUMBER_2">%d</xliff:g> δευτερόλεπτα."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Κατάργηση"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Αύξηση έντασης ήχου πάνω από το επίπεδο ασφαλείας;"\n"Αν ακούτε μουσική σε υψηλή ένταση για μεγάλο χρονικό διάστημα ενδέχεται να προκληθεί βλάβη στην ακοή σας."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Αγγίξτε παρατεταμένα με δύο δάχτυλα για να ενεργοποιήσετε τη λειτουργία προσβασιμότητας."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Ενεργοποιήθηκε η προσβασιμότητα."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Η λειτουργία προσβασιμότητας ακυρώθηκε."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Τρέχων χρήστης <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Κάτοχος"</string>
 </resources>
diff --git a/core/res/res/values-en-rAU/donottranslate-cldr.xml b/core/res/res/values-en-rAU/donottranslate-cldr.xml
index 557833e..947fe92 100644
--- a/core/res/res/values-en-rAU/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rAU/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">January</string>
-    <string name="month_long_standalone_february">February</string>
-    <string name="month_long_standalone_march">March</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">May</string>
-    <string name="month_long_standalone_june">June</string>
-    <string name="month_long_standalone_july">July</string>
-    <string name="month_long_standalone_august">August</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">October</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">December</string>
-
-    <string name="month_long_january">January</string>
-    <string name="month_long_february">February</string>
-    <string name="month_long_march">March</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">May</string>
-    <string name="month_long_june">June</string>
-    <string name="month_long_july">July</string>
-    <string name="month_long_august">August</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">October</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">December</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mar</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">May</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aug</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Oct</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dec</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">Sunday</string>
-    <string name="day_of_week_long_monday">Monday</string>
-    <string name="day_of_week_long_tuesday">Tuesday</string>
-    <string name="day_of_week_long_wednesday">Wednesday</string>
-    <string name="day_of_week_long_thursday">Thursday</string>
-    <string name="day_of_week_long_friday">Friday</string>
-    <string name="day_of_week_long_saturday">Saturday</string>
-
-    <string name="day_of_week_medium_sunday">Sun</string>
-    <string name="day_of_week_medium_monday">Mon</string>
-    <string name="day_of_week_medium_tuesday">Tue</string>
-    <string name="day_of_week_medium_wednesday">Wed</string>
-    <string name="day_of_week_medium_thursday">Thu</string>
-    <string name="day_of_week_medium_friday">Fri</string>
-    <string name="day_of_week_medium_saturday">Sat</string>
-
-    <string name="day_of_week_short_sunday">Su</string>
-    <string name="day_of_week_short_monday">Mo</string>
-    <string name="day_of_week_short_tuesday">Tu</string>
-    <string name="day_of_week_short_wednesday">We</string>
-    <string name="day_of_week_short_thursday">Th</string>
-    <string name="day_of_week_short_friday">Fr</string>
-    <string name="day_of_week_short_saturday">Sa</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">W</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">am</string>
-    <string name="pm">pm</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M%p</string>
     <string name="hour_minute_cap_ampm">%-l:%M%^p</string>
diff --git a/core/res/res/values-en-rCA/donottranslate-cldr.xml b/core/res/res/values-en-rCA/donottranslate-cldr.xml
index 2aa7cbe..1845f28 100644
--- a/core/res/res/values-en-rCA/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rCA/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">January</string>
-    <string name="month_long_standalone_february">February</string>
-    <string name="month_long_standalone_march">March</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">May</string>
-    <string name="month_long_standalone_june">June</string>
-    <string name="month_long_standalone_july">July</string>
-    <string name="month_long_standalone_august">August</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">October</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">December</string>
-
-    <string name="month_long_january">January</string>
-    <string name="month_long_february">February</string>
-    <string name="month_long_march">March</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">May</string>
-    <string name="month_long_june">June</string>
-    <string name="month_long_july">July</string>
-    <string name="month_long_august">August</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">October</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">December</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mar</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">May</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aug</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Oct</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dec</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">Sunday</string>
-    <string name="day_of_week_long_monday">Monday</string>
-    <string name="day_of_week_long_tuesday">Tuesday</string>
-    <string name="day_of_week_long_wednesday">Wednesday</string>
-    <string name="day_of_week_long_thursday">Thursday</string>
-    <string name="day_of_week_long_friday">Friday</string>
-    <string name="day_of_week_long_saturday">Saturday</string>
-
-    <string name="day_of_week_medium_sunday">Sun</string>
-    <string name="day_of_week_medium_monday">Mon</string>
-    <string name="day_of_week_medium_tuesday">Tue</string>
-    <string name="day_of_week_medium_wednesday">Wed</string>
-    <string name="day_of_week_medium_thursday">Thu</string>
-    <string name="day_of_week_medium_friday">Fri</string>
-    <string name="day_of_week_medium_saturday">Sat</string>
-
-    <string name="day_of_week_short_sunday">Su</string>
-    <string name="day_of_week_short_monday">Mo</string>
-    <string name="day_of_week_short_tuesday">Tu</string>
-    <string name="day_of_week_short_wednesday">We</string>
-    <string name="day_of_week_short_thursday">Th</string>
-    <string name="day_of_week_short_friday">Fr</string>
-    <string name="day_of_week_short_saturday">Sa</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">W</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">am</string>
-    <string name="pm">pm</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M%p</string>
     <string name="hour_minute_cap_ampm">%-l:%M%^p</string>
diff --git a/core/res/res/values-en-rGB/donottranslate-cldr.xml b/core/res/res/values-en-rGB/donottranslate-cldr.xml
index cce895e..a10dfa50 100644
--- a/core/res/res/values-en-rGB/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rGB/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">January</string>
-    <string name="month_long_standalone_february">February</string>
-    <string name="month_long_standalone_march">March</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">May</string>
-    <string name="month_long_standalone_june">June</string>
-    <string name="month_long_standalone_july">July</string>
-    <string name="month_long_standalone_august">August</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">October</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">December</string>
-
-    <string name="month_long_january">January</string>
-    <string name="month_long_february">February</string>
-    <string name="month_long_march">March</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">May</string>
-    <string name="month_long_june">June</string>
-    <string name="month_long_july">July</string>
-    <string name="month_long_august">August</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">October</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">December</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mar</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">May</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aug</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Oct</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dec</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">Sunday</string>
-    <string name="day_of_week_long_monday">Monday</string>
-    <string name="day_of_week_long_tuesday">Tuesday</string>
-    <string name="day_of_week_long_wednesday">Wednesday</string>
-    <string name="day_of_week_long_thursday">Thursday</string>
-    <string name="day_of_week_long_friday">Friday</string>
-    <string name="day_of_week_long_saturday">Saturday</string>
-
-    <string name="day_of_week_medium_sunday">Sun</string>
-    <string name="day_of_week_medium_monday">Mon</string>
-    <string name="day_of_week_medium_tuesday">Tue</string>
-    <string name="day_of_week_medium_wednesday">Wed</string>
-    <string name="day_of_week_medium_thursday">Thu</string>
-    <string name="day_of_week_medium_friday">Fri</string>
-    <string name="day_of_week_medium_saturday">Sat</string>
-
-    <string name="day_of_week_short_sunday">Su</string>
-    <string name="day_of_week_short_monday">Mo</string>
-    <string name="day_of_week_short_tuesday">Tu</string>
-    <string name="day_of_week_short_wednesday">We</string>
-    <string name="day_of_week_short_thursday">Th</string>
-    <string name="day_of_week_short_friday">Fr</string>
-    <string name="day_of_week_short_saturday">Sa</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">W</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">am</string>
-    <string name="pm">pm</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M%p</string>
     <string name="hour_minute_cap_ampm">%-l:%M%^p</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index cdacbc4..888e42e 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Phone options"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Screen lock"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Power off"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Bug report"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Take bug report"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"This will collect information about your current device state, to send as an email message. It will take a little time from starting the bug report until it is ready to be sent. Please be patient."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Silent mode"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Sound is OFF"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Sound is ON"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Your messages"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Read and write your SMS, email and other messages."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Your personal information"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Direct access to your contacts and calendar stored on the tablet."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Direct access to your contacts and calendar stored on the phone."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Direct access to information about you, stored in on your contact card."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Your social information"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Direct access to information about your contacts and social connections."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Your location"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Monitor your physical location."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Network communication"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Access various network features."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Access devices and networks through Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Audio Settings"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Change audio settings."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Affects Battery"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Use features that can quickly drain battery."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Calendar"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Direct access to calendar and events."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Read User Dictionary"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Read words in user dictionary."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Write User Dictionary"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Add words to the user dictionary."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Bookmarks and History"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Direct access to bookmarks and browser history."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarm"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Set the alarm clock."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Voicemail"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Direct access to voicemail."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Microphone"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Direct access to the microphone to record audio."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Camera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Direct access to camera for image or video capture."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Your applications information"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Ability to affect behaviour of other applications on your device."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Wallpaper"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Change the device wallpaper settings."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Clock"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Change the device time or timezone."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Status Bar"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Change the device status bar settings."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Sync Settings"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Access to the sync settings."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Your accounts"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Access the available accounts."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Hardware controls"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Lower-level access and control of the system."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Development tools"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Features only needed for app developers."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Other Application UI"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Effect the UI of other applications."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Storage"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Access the USB storage."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Access the SD card."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Allows the app to receive and process WAP messages. This permission includes the ability to monitor or delete messages sent to you without showing them to you."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"retrieve running apps"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Allows the app to retrieve information about currently and recently running tasks. This may allow the app to discover information about which applications are used on the device."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interact across users"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Allows the app to perform actions across different users on the device. Malicious apps may use this to violate the protection between users."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"full license to interact across users"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Allows all possible interactions across users."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"manage users"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Allows apps to manage users on the device, including query, creation and deletion."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"retrieve details of running apps"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Allows the app to retrieve detailed information about currently and recently running tasks. Malicious apps may discover private information about other apps."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"re-order running apps"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Allows the app to retrieve the internal state of the system. Malicious apps may retrieve a wide variety of private and secure information that they should never normally need."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"retrieve screen content"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Allows the app to retrieve the content of the active window. Malicious apps may retrieve the entire window content and examine all its text except passwords."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"temporary enable accessibility"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Allows an application to temporarily enable accessibility on the device. Malicious apps may enable accessibility without user consent."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"retrieve window info"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Allows an application to retrieve information about the windows from the window manager. Malicious apps may retrieve information that is intended for internal system usage."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filter events"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Allows an application to register an input filter which filters the stream of all user events before they are dispatched. Malicious app may control the system UI without user intervention."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"magnify display"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Allows an application to magnify the content of a display. Malicious apps may transform the display content in a way that renders the device unusable."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"partial shutdown"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Puts the activity manager into a shut-down state. Does not perform a complete shut down."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"prevent app switches"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Allows the app to control the maximum number of processes that will run. Never needed for normal apps."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"force background apps to close"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Allows the app to control whether activities are always finished as soon as they go to the background. Never needed for normal apps."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"modify battery statistics"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Allows the app to modify collected battery statistics. Not for use by normal apps."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"read battery statistics"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Allows an application to read the current low-level battery use data. May allow the application to find out detailed information about which apps you use."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modify battery statistics"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Allows the app to modify collected battery statistics. Not for use by normal apps."</string>
     <string name="permlab_backup" msgid="470013022865453920">"control system back up and restore"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Allows the app to control the system\'s backup and restore mechanism. Not for use by normal apps."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"confirm a full backup or restore operation"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"display unauthorised windows"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Allows the app to create windows that are intended to be used by the internal system user interface. Not for use by normal apps."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"draw over other apps"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Allows the app to show system alert windows. Some alert windows may take over the entire screen."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Allows the app to draw on top of other applications or parts of the user interface. They may interfere with your use of the interface in any application, or change what you think you are seeing in other applications."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"modify global animation speed"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Allows the app to change the global animation speed (faster or slower animations) at any time."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"manage app tokens"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Allows the app to create and manage their own tokens, bypassing their normal Z-ordering. Should never be needed for normal apps."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"freeze screen"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Allows the application to temporarily freeze the screen for a full-screen transition."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"press keys and control buttons"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Allows the app to deliver its own input events (key presses, etc.) to other apps. Malicious apps may use this to take over the tablet."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Allows the app to deliver its own input events (key presses, etc.) to other apps. Malicious apps may use this to take over the phone."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"directly install apps"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Allows the app to install new or updated Android packages. Malicious apps may use this to add new apps with arbitrarily powerful permissions."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"delete all app cache data"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Allows the app to free up tablet storage by deleting files in app cache directory. Access is very restricted, usually to system process."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Allows the app to free phone storage by deleting files in app cache directory. Access is very restricted usually to system process."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Allows the app to free tablet storage by deleting files in the cache directories of other applications. This may cause other applications to start up more slowly as they need to re-retrieve their data."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Allows the app to free phone storage by deleting files in the cache directories of other applications. This may cause other applications to start up more slowly as they need to re-retrieve their data."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"move app resources"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Allows the app to move app resources from internal to external media and vice versa."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"read sensitive log data"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"permission to install a location provider"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Create mock location sources for testing or install a new location provider. This allows the app to override the location and/or status returned by other location sources such as GPS or location providers."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"precise (GPS) location"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Access precise location sources such as the Global Positioning System on the tablet. When location services are available and turned on, this permission allows the app to determine your precise location."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Access precise location sources such as the Global Positioning System on the phone. When location services are available and turned on, this permission allows the app to determine your precise location."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"approximate (network-based) location"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Access approximate location from location providers using network sources such as mobile tower and Wi-FI. When these location services are available and turned on, this permission allows the app to determine your approximate location."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"precise location (GPS and network-based)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Allows the app to get your precise location using the Global Positioning System (GPS) or network location sources such as mobile towers and Wi-Fi. These location services must be turned on and available to your device for the app to use them. Apps may use this to determine where you are, and may consume additional battery power."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"approximate location (network-based)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Allows the app to get your approximate location. This location is derived by location services using network location sources such as mobile towers and Wi-Fi. These location services must be turned on and available to your device for the app to use them. Apps may use this to determine approximately where you are."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"access SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Allows the app to use SurfaceFlinger low-level features."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"read frame buffer"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Allows the app to read the content of the frame buffer."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"configure Wi-Fi displays"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Allows the app to configure and connect to Wi-Fi displays."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"control Wi-Fi displays"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Allows the app to control low-level features of Wi-Fi displays."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"change your audio settings"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Allows the app to modify global audio settings such as volume and which speaker is used for output."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"record audio"</string>
@@ -488,9 +547,9 @@
     <string name="permdesc_changeTetherState" msgid="1524441344412319780">"Allows the app to change the state of tethered network connectivity."</string>
     <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"change background data usage setting"</string>
     <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Allows the app to change the background data usage setting."</string>
-    <string name="permlab_accessWifiState" msgid="5202012949247040011">"view WiFi connections"</string>
+    <string name="permlab_accessWifiState" msgid="5202012949247040011">"view Wi-Fi connections"</string>
     <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Allows the app to view information about Wi-FI networking, such as whether Wi-FI is enabled and name of connected Wi-FI devices."</string>
-    <string name="permlab_changeWifiState" msgid="6550641188749128035">"connect and disconnect from WiFi"</string>
+    <string name="permlab_changeWifiState" msgid="6550641188749128035">"connect and disconnect from Wi-Fi"</string>
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Allows the app to connect to and disconnect from Wi-FI access points and to make changes to device configuration for Wi-FI networks."</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"allow Wi-Fi Multicast reception"</string>
     <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Allows the app to receive packets sent to all devices on a Wi-FI network using multicast addresses, not just your tablet. It uses more power than the non-multicast mode."</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"access Bluetooth settings"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Allows the app to configure the local Bluetooth tablet and to discover and pair with remote devices."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Allows the app to configure the local Bluetooth phone and to discover and pair with remote devices."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"View WiMAX connections"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"connect and disconnect from WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Allows the app to determine whether WiMAX is enabled and information about any WiMAX networks that are connected."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"change WiMAX state"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Allows the app to connect the tablet to and disconnect the tablet from WiMAX networks."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Allows the app to modify your currently synced feeds. Malicious apps may change your synced feeds."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"read terms you added to the dictionary"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Allows the app to read all words, names and phrases that the user may have stored in the user dictionary."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"write to user-defined dictionary"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"add words to user-defined dictionary"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Allows the app to write new words into the user dictionary."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"test access to protected storage"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"test access to protected storage"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Allows the app to test a permission for USB storage that will be availabe on future devices."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Allows the app to test a permission for USB storage that will be available on future devices."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Allows the app to test a permission for the SD card that will be available on future devices."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modify or delete the contents of your USB storage"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modify or delete the contents of your SD card"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Allows the app to write to the SD card."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"modify/delete internal media storage contents"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Allows the app to modify the contents of the internal media storage."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"access external storage of all users"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Allows the app to access external storage for all users."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"access the cache file system"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Allows the app to read and write the cache file system."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"make/receive Internet calls"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Require that stored app data be encrypted."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Disable cameras"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Prevent use of all device cameras."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Disable features in keyguard"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Prevent use of some features in keyguard."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Home"</item>
     <item msgid="869923650527136615">"Mobile"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Try again"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Maximum Face Unlock attempts exceeded"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Charging, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Charged."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Charged"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Connect your charger."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"No SIM card."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"No SIM card"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No SIM card in tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No SIM card in phone."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Insert a SIM card."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Pattern cleared"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Cell added"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Pattern completed"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Add widget"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Empty"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Unlock area expanded."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Unlock area collapsed."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> widget."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"User selector"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Status"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Camera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Media controls"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Widget reordering started."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Widget reordering ended."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> deleted."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Expand unlock area."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Slide unlock."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Pattern unlock."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Face unlock."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin unlock."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Password unlock."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Pattern area."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Slide area."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copy URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Select text"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Text selection"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"add to dictionary"</string>
-    <string name="deleteText" msgid="7070985395199629156">"delete"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Add to dictionary"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Delete"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Input method"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Text actions"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Storage space running out"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Open Wi-Fi networks available"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Sign in to Wi-Fi network"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Sign in to network"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Couldn\'t connect to Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" has a poor Internet connection."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"To:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Type the required PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"The phone will temporarily disconnect from Wi-FI while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Insert character"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Sending SMS messages"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; is sending a large number of SMS messages. Do you want to allow this app to continue sending messages?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Allow"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Deny"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; would like to send a message to &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"This "<font fgcolor="#ffffb060">"may cause charges"</font>" on your mobile account."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"This will cause charges on your mobile account."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Send"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Cancel"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Remember my choice"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"You can change this later in Settings &gt; Apps"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Always Allow*"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Never Allow"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM card removed"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"The mobile network will be unavailable until you restart with a valid SIM card inserted."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Done"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Set date"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Set"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Done"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Default"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"No permission required"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Hide"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Show all"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NEW: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NEW: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Provided by <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"No permission required"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"this may cost you money"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB mass storage"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB connected"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"You\'ve connected to your computer via USB. Touch the button below if you want to copy files between your computer and your Android\'s USB storage."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is activated by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Touch to manage the network."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Connected to <xliff:g id="SESSION">%s</xliff:g>. Touch to manage the network."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Always-on VPN connecting…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Always-on VPN connected"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Always-on VPN error"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Touch to reset connection"</string>
     <string name="upload_file" msgid="2897957172366730416">"Choose file"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"No file chosen"</string>
     <string name="reset" msgid="2448168080964209908">"Reset"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Share"</string>
     <string name="find" msgid="4808270900322985960">"Find"</string>
     <string name="websearch" msgid="4337157977400211589">"Web Search"</string>
+    <string name="find_next" msgid="5742124618942193978">"Find next"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Find previous"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Location request from <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Location request"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Requested by <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1283,11 +1381,67 @@
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Always"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Just once"</string>
     <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string>
-    <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Phones"</string>
+    <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Phone"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Headphones"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock speakers"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI audio"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Done"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Media output"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Scanning..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Connecting..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Available"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Not available"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Built-in Screen"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI Screen"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Wireless display is connected"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"This screen is showing on another device"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Disconnect"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Emergency call"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Forgot Pattern"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Wrong Pattern"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Wrong Password"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Wrong PIN"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Draw your pattern"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Enter SIM PIN"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Enter PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Enter Password"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM is now disabled. Enter PUK code to continue. Contact carrier for details."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Enter desired PIN code"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Confirm desired PIN code"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Unlocking SIM card…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Incorrect PIN code."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Type a PIN that is 4 to 8 numbers."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK code should be 8 numbers or more."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Re-enter the correct PUK code. Repeated attempts will permanently disable the SIM."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN codes do not match"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Too many pattern attempts"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"To unlock, sign in with your Google account."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Username (email)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Password"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Sign in"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Invalid username or password."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Forgot your username or password?"\n"Visit "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Checking account…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"You have incorrectly typed your PIN <xliff:g id="NUMBER_0">%d</xliff:g> times. "\n\n"Try again in <xliff:g id="NUMBER_1">%d</xliff:g> seconds."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"You have incorrectly typed your password <xliff:g id="NUMBER_0">%d</xliff:g> times. "\n\n"Try again in <xliff:g id="NUMBER_1">%d</xliff:g> seconds."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%d</xliff:g> times. "\n\n"Try again in <xliff:g id="NUMBER_1">%d</xliff:g> seconds."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%d</xliff:g> times. After <xliff:g id="NUMBER_1">%d</xliff:g> more unsuccessful attempts, the tablet will be reset to factory default and all user data will be lost."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%d</xliff:g> times. After <xliff:g id="NUMBER_1">%d</xliff:g> more unsuccessful attempts, the phone will be reset to factory default and all user data will be lost."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. The tablet will now be reset to factory default."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The phone will now be reset to factory default."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%d</xliff:g> times. After <xliff:g id="NUMBER_1">%d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account."\n\n" Try again in <xliff:g id="NUMBER_2">%d</xliff:g> seconds."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%d</xliff:g> times. After <xliff:g id="NUMBER_1">%d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account."\n\n" Try again in <xliff:g id="NUMBER_2">%d</xliff:g> seconds."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Remove"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Raise volume above safe level?"\n"Listening at high volume for long periods may damage your hearing."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Keep holding down two fingers to enable accessibility."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Accessibility enabled."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Accessibility cancelled."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Current user <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Owner"</string>
 </resources>
diff --git a/core/res/res/values-en-rIE/donottranslate-cldr.xml b/core/res/res/values-en-rIE/donottranslate-cldr.xml
index 46b13ec..65cab99 100644
--- a/core/res/res/values-en-rIE/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rIE/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">January</string>
-    <string name="month_long_standalone_february">February</string>
-    <string name="month_long_standalone_march">March</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">May</string>
-    <string name="month_long_standalone_june">June</string>
-    <string name="month_long_standalone_july">July</string>
-    <string name="month_long_standalone_august">August</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">October</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">December</string>
-
-    <string name="month_long_january">January</string>
-    <string name="month_long_february">February</string>
-    <string name="month_long_march">March</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">May</string>
-    <string name="month_long_june">June</string>
-    <string name="month_long_july">July</string>
-    <string name="month_long_august">August</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">October</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">December</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mar</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">May</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aug</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Oct</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dec</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">Sunday</string>
-    <string name="day_of_week_long_monday">Monday</string>
-    <string name="day_of_week_long_tuesday">Tuesday</string>
-    <string name="day_of_week_long_wednesday">Wednesday</string>
-    <string name="day_of_week_long_thursday">Thursday</string>
-    <string name="day_of_week_long_friday">Friday</string>
-    <string name="day_of_week_long_saturday">Saturday</string>
-
-    <string name="day_of_week_medium_sunday">Sun</string>
-    <string name="day_of_week_medium_monday">Mon</string>
-    <string name="day_of_week_medium_tuesday">Tue</string>
-    <string name="day_of_week_medium_wednesday">Wed</string>
-    <string name="day_of_week_medium_thursday">Thu</string>
-    <string name="day_of_week_medium_friday">Fri</string>
-    <string name="day_of_week_medium_saturday">Sat</string>
-
-    <string name="day_of_week_short_sunday">Su</string>
-    <string name="day_of_week_short_monday">Mo</string>
-    <string name="day_of_week_short_tuesday">Tu</string>
-    <string name="day_of_week_short_wednesday">We</string>
-    <string name="day_of_week_short_thursday">Th</string>
-    <string name="day_of_week_short_friday">Fr</string>
-    <string name="day_of_week_short_saturday">Sa</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">W</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">a.m.</string>
-    <string name="pm">p.m.</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M%p</string>
     <string name="hour_minute_cap_ampm">%-l:%M%^p</string>
diff --git a/core/res/res/values-en-rIN/donottranslate-cldr.xml b/core/res/res/values-en-rIN/donottranslate-cldr.xml
index 177bd7e..48942fe 100644
--- a/core/res/res/values-en-rIN/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rIN/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">January</string>
-    <string name="month_long_standalone_february">February</string>
-    <string name="month_long_standalone_march">March</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">May</string>
-    <string name="month_long_standalone_june">June</string>
-    <string name="month_long_standalone_july">July</string>
-    <string name="month_long_standalone_august">August</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">October</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">December</string>
-
-    <string name="month_long_january">January</string>
-    <string name="month_long_february">February</string>
-    <string name="month_long_march">March</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">May</string>
-    <string name="month_long_june">June</string>
-    <string name="month_long_july">July</string>
-    <string name="month_long_august">August</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">October</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">December</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mar</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">May</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aug</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Oct</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dec</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">Sunday</string>
-    <string name="day_of_week_long_monday">Monday</string>
-    <string name="day_of_week_long_tuesday">Tuesday</string>
-    <string name="day_of_week_long_wednesday">Wednesday</string>
-    <string name="day_of_week_long_thursday">Thursday</string>
-    <string name="day_of_week_long_friday">Friday</string>
-    <string name="day_of_week_long_saturday">Saturday</string>
-
-    <string name="day_of_week_medium_sunday">Sun</string>
-    <string name="day_of_week_medium_monday">Mon</string>
-    <string name="day_of_week_medium_tuesday">Tue</string>
-    <string name="day_of_week_medium_wednesday">Wed</string>
-    <string name="day_of_week_medium_thursday">Thu</string>
-    <string name="day_of_week_medium_friday">Fri</string>
-    <string name="day_of_week_medium_saturday">Sat</string>
-
-    <string name="day_of_week_short_sunday">Su</string>
-    <string name="day_of_week_short_monday">Mo</string>
-    <string name="day_of_week_short_tuesday">Tu</string>
-    <string name="day_of_week_short_wednesday">We</string>
-    <string name="day_of_week_short_thursday">Th</string>
-    <string name="day_of_week_short_friday">Fr</string>
-    <string name="day_of_week_short_saturday">Sa</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">W</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">am</string>
-    <string name="pm">pm</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M%p</string>
     <string name="hour_minute_cap_ampm">%-l:%M%^p</string>
diff --git a/core/res/res/values-en-rNZ/donottranslate-cldr.xml b/core/res/res/values-en-rNZ/donottranslate-cldr.xml
index 41a00a5..117dda8 100644
--- a/core/res/res/values-en-rNZ/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rNZ/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">January</string>
-    <string name="month_long_standalone_february">February</string>
-    <string name="month_long_standalone_march">March</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">May</string>
-    <string name="month_long_standalone_june">June</string>
-    <string name="month_long_standalone_july">July</string>
-    <string name="month_long_standalone_august">August</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">October</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">December</string>
-
-    <string name="month_long_january">January</string>
-    <string name="month_long_february">February</string>
-    <string name="month_long_march">March</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">May</string>
-    <string name="month_long_june">June</string>
-    <string name="month_long_july">July</string>
-    <string name="month_long_august">August</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">October</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">December</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mar</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">May</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aug</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Oct</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dec</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">Sunday</string>
-    <string name="day_of_week_long_monday">Monday</string>
-    <string name="day_of_week_long_tuesday">Tuesday</string>
-    <string name="day_of_week_long_wednesday">Wednesday</string>
-    <string name="day_of_week_long_thursday">Thursday</string>
-    <string name="day_of_week_long_friday">Friday</string>
-    <string name="day_of_week_long_saturday">Saturday</string>
-
-    <string name="day_of_week_medium_sunday">Sun</string>
-    <string name="day_of_week_medium_monday">Mon</string>
-    <string name="day_of_week_medium_tuesday">Tue</string>
-    <string name="day_of_week_medium_wednesday">Wed</string>
-    <string name="day_of_week_medium_thursday">Thu</string>
-    <string name="day_of_week_medium_friday">Fri</string>
-    <string name="day_of_week_medium_saturday">Sat</string>
-
-    <string name="day_of_week_short_sunday">Su</string>
-    <string name="day_of_week_short_monday">Mo</string>
-    <string name="day_of_week_short_tuesday">Tu</string>
-    <string name="day_of_week_short_wednesday">We</string>
-    <string name="day_of_week_short_thursday">Th</string>
-    <string name="day_of_week_short_friday">Fr</string>
-    <string name="day_of_week_short_saturday">Sa</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">W</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">am</string>
-    <string name="pm">pm</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M%p</string>
     <string name="hour_minute_cap_ampm">%-l:%M%^p</string>
diff --git a/core/res/res/values-en-rUS/donottranslate-cldr.xml b/core/res/res/values-en-rUS/donottranslate-cldr.xml
index 15fcd8b..0587c165 100644
--- a/core/res/res/values-en-rUS/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rUS/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">January</string>
-    <string name="month_long_standalone_february">February</string>
-    <string name="month_long_standalone_march">March</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">May</string>
-    <string name="month_long_standalone_june">June</string>
-    <string name="month_long_standalone_july">July</string>
-    <string name="month_long_standalone_august">August</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">October</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">December</string>
-
-    <string name="month_long_january">January</string>
-    <string name="month_long_february">February</string>
-    <string name="month_long_march">March</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">May</string>
-    <string name="month_long_june">June</string>
-    <string name="month_long_july">July</string>
-    <string name="month_long_august">August</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">October</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">December</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mar</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">May</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aug</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Oct</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dec</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">Sunday</string>
-    <string name="day_of_week_long_monday">Monday</string>
-    <string name="day_of_week_long_tuesday">Tuesday</string>
-    <string name="day_of_week_long_wednesday">Wednesday</string>
-    <string name="day_of_week_long_thursday">Thursday</string>
-    <string name="day_of_week_long_friday">Friday</string>
-    <string name="day_of_week_long_saturday">Saturday</string>
-
-    <string name="day_of_week_medium_sunday">Sun</string>
-    <string name="day_of_week_medium_monday">Mon</string>
-    <string name="day_of_week_medium_tuesday">Tue</string>
-    <string name="day_of_week_medium_wednesday">Wed</string>
-    <string name="day_of_week_medium_thursday">Thu</string>
-    <string name="day_of_week_medium_friday">Fri</string>
-    <string name="day_of_week_medium_saturday">Sat</string>
-
-    <string name="day_of_week_short_sunday">Su</string>
-    <string name="day_of_week_short_monday">Mo</string>
-    <string name="day_of_week_short_tuesday">Tu</string>
-    <string name="day_of_week_short_wednesday">We</string>
-    <string name="day_of_week_short_thursday">Th</string>
-    <string name="day_of_week_short_friday">Fr</string>
-    <string name="day_of_week_short_saturday">Sa</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">W</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">am</string>
-    <string name="pm">pm</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M%p</string>
     <string name="hour_minute_cap_ampm">%-l:%M%^p</string>
diff --git a/core/res/res/values-en-rZA/donottranslate-cldr.xml b/core/res/res/values-en-rZA/donottranslate-cldr.xml
index 7a5bdbd..48ebc6e 100644
--- a/core/res/res/values-en-rZA/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rZA/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">January</string>
-    <string name="month_long_standalone_february">February</string>
-    <string name="month_long_standalone_march">March</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">May</string>
-    <string name="month_long_standalone_june">June</string>
-    <string name="month_long_standalone_july">July</string>
-    <string name="month_long_standalone_august">August</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">October</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">December</string>
-
-    <string name="month_long_january">January</string>
-    <string name="month_long_february">February</string>
-    <string name="month_long_march">March</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">May</string>
-    <string name="month_long_june">June</string>
-    <string name="month_long_july">July</string>
-    <string name="month_long_august">August</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">October</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">December</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mar</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">May</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aug</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Oct</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dec</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">Sunday</string>
-    <string name="day_of_week_long_monday">Monday</string>
-    <string name="day_of_week_long_tuesday">Tuesday</string>
-    <string name="day_of_week_long_wednesday">Wednesday</string>
-    <string name="day_of_week_long_thursday">Thursday</string>
-    <string name="day_of_week_long_friday">Friday</string>
-    <string name="day_of_week_long_saturday">Saturday</string>
-
-    <string name="day_of_week_medium_sunday">Sun</string>
-    <string name="day_of_week_medium_monday">Mon</string>
-    <string name="day_of_week_medium_tuesday">Tue</string>
-    <string name="day_of_week_medium_wednesday">Wed</string>
-    <string name="day_of_week_medium_thursday">Thu</string>
-    <string name="day_of_week_medium_friday">Fri</string>
-    <string name="day_of_week_medium_saturday">Sat</string>
-
-    <string name="day_of_week_short_sunday">Su</string>
-    <string name="day_of_week_short_monday">Mo</string>
-    <string name="day_of_week_short_tuesday">Tu</string>
-    <string name="day_of_week_short_wednesday">We</string>
-    <string name="day_of_week_short_thursday">Th</string>
-    <string name="day_of_week_short_friday">Fr</string>
-    <string name="day_of_week_short_saturday">Sa</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">W</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">am</string>
-    <string name="pm">pm</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M%p</string>
     <string name="hour_minute_cap_ampm">%-l:%M%^p</string>
diff --git a/core/res/res/values-es-rUS/donottranslate-cldr.xml b/core/res/res/values-es-rUS/donottranslate-cldr.xml
index e2c3254..9224786 100644
--- a/core/res/res/values-es-rUS/donottranslate-cldr.xml
+++ b/core/res/res/values-es-rUS/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">enero</string>
-    <string name="month_long_standalone_february">febrero</string>
-    <string name="month_long_standalone_march">marzo</string>
-    <string name="month_long_standalone_april">abril</string>
-    <string name="month_long_standalone_may">mayo</string>
-    <string name="month_long_standalone_june">junio</string>
-    <string name="month_long_standalone_july">julio</string>
-    <string name="month_long_standalone_august">agosto</string>
-    <string name="month_long_standalone_september">septiembre</string>
-    <string name="month_long_standalone_october">octubre</string>
-    <string name="month_long_standalone_november">noviembre</string>
-    <string name="month_long_standalone_december">diciembre</string>
-
-    <string name="month_long_january">enero</string>
-    <string name="month_long_february">febrero</string>
-    <string name="month_long_march">marzo</string>
-    <string name="month_long_april">abril</string>
-    <string name="month_long_may">mayo</string>
-    <string name="month_long_june">junio</string>
-    <string name="month_long_july">julio</string>
-    <string name="month_long_august">agosto</string>
-    <string name="month_long_september">septiembre</string>
-    <string name="month_long_october">octubre</string>
-    <string name="month_long_november">noviembre</string>
-    <string name="month_long_december">diciembre</string>
-
-    <string name="month_medium_january">ene.</string>
-    <string name="month_medium_february">feb.</string>
-    <string name="month_medium_march">mar.</string>
-    <string name="month_medium_april">abr.</string>
-    <string name="month_medium_may">may.</string>
-    <string name="month_medium_june">jun.</string>
-    <string name="month_medium_july">jul.</string>
-    <string name="month_medium_august">ago.</string>
-    <string name="month_medium_september">sep.</string>
-    <string name="month_medium_october">oct.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">dic.</string>
-
-    <string name="month_shortest_january">E</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">domingo</string>
-    <string name="day_of_week_long_monday">lunes</string>
-    <string name="day_of_week_long_tuesday">martes</string>
-    <string name="day_of_week_long_wednesday">miércoles</string>
-    <string name="day_of_week_long_thursday">jueves</string>
-    <string name="day_of_week_long_friday">viernes</string>
-    <string name="day_of_week_long_saturday">sábado</string>
-
-    <string name="day_of_week_medium_sunday">dom.</string>
-    <string name="day_of_week_medium_monday">lun.</string>
-    <string name="day_of_week_medium_tuesday">mar.</string>
-    <string name="day_of_week_medium_wednesday">mié.</string>
-    <string name="day_of_week_medium_thursday">jue.</string>
-    <string name="day_of_week_medium_friday">vie.</string>
-    <string name="day_of_week_medium_saturday">sáb.</string>
-
-    <string name="day_of_week_short_sunday">dom.</string>
-    <string name="day_of_week_short_monday">lun.</string>
-    <string name="day_of_week_short_tuesday">mar.</string>
-    <string name="day_of_week_short_wednesday">mié.</string>
-    <string name="day_of_week_short_thursday">jue.</string>
-    <string name="day_of_week_short_friday">vie.</string>
-    <string name="day_of_week_short_saturday">sáb.</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">L</string>
-    <string name="day_of_week_shortest_tuesday">M</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">J</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">a. m.</string>
-    <string name="pm">p. m.</string>
-    <string name="yesterday">ayer</string>
-    <string name="today">hoy</string>
-    <string name="tomorrow">mañana</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 3b39f2a..47d436d 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opciones de dispositivo"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Bloqueo de pantalla"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Apagar"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Informe de errores"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Iniciar informe de errores"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Se recopilará información sobre el estado actual de tu dispositivo, que se enviará por correo. Pasarán unos minutos desde que se inicie el informe de errores hasta que se envíe, por lo que te recomendamos que tengas paciencia."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Modo silencioso"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"El sonido está Desactivado"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"El sonido está Activado"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Tus mensajes"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Lee y escribe tus SMS, mensajes de correo y otros mensajes."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Tu información personal"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Acceso directo a los contactos y calendario guardados en tu dispositivo."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Acceso directo a tus contactos y calendario guardado en el dispositivo."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Acceso directo a tu información, almacenada en tu tarjeta de contacto"</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Tu información social"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Acceso directo a información sobre tus contactos y conexiones sociales"</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Tu ubicación"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Controlar tu ubicación física"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Comunicación de red"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Acceder a distintas funciones de red"</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Acceder a dispositivos y redes a través de Bluetooth"</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Configuración de audio"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Cambiar la configuración de audio"</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Afecta la batería."</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Uso de las características que se pueden agotar rápidamente la batería"</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Calendario"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Acceso directo a calendario y eventos"</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Leer el diccionario del usuario"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Leer palabras del diccionario del usuario"</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Escribir en el diccionario del usuario"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Agregar palabras al diccionario del usuario"</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Marcadores e historial"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Acceso directo a marcadores e historial del navegador"</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarma"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Ajusta el despertador."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Correo de voz"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Acceso directo al correo de voz"</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Micrófono"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Acceso directo a micrófono para grabar audio"</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Cámara"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Acceso directo a cámara para imagen o captura de video"</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Información de tus aplicaciones"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Capacidad para influir en el comportamiento de otras aplicaciones en el dispositivo"</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Fondo de pantalla"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Cambiar la configuración de fondo de pantalla del dispositivo"</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Reloj"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Cambiar la hora del dispositivo o la zona horaria"</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Barra de estado"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Cambiar la configuración de la barra de estado del dispositivo"</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Configuración de sincronización"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Acceso a los ajustes de sincronización"</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Tus cuentas"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Acceder a las cuentas disponibles."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Controles de hardware"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Acceso y control de nivel más bajo del sistema."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Herramientas de desarrollo"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funciones únicamente necesarias para los programadores de aplicaciones."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Interfaz de usuario de otra aplicación"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Influir la interfaz de usuario de otras aplicaciones"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Espacio de almacenamiento"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Acceder al almacenamiento USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Acceder a la tarjeta SD."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permite que la aplicación reciba y procese mensajes WAP, lo que significa que podría controlar o eliminar mensajes enviados al usuario sin mostrártelos."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"recuperar aplicaciones en ejecución"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Permite que la aplicación recupere información sobre las tareas que se estén ejecutando en ese momento o que se hayan ejecutado recientemente. La aplicación puede utilizar este permiso para descubrir cuáles son las aplicaciones que se utilizan en el dispositivo."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"Interactuar con los usuarios"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permite que la aplicación lleve a cabo acciones entre los diferentes usuarios del dispositivo. Las aplicaciones maliciosas pueden utilizar este permiso para infringir la protección entre usuarios."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"Licencia completa para interactuar con los usuarios"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permite todas las interacciones posibles con los usuarios."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"administrar usuarios"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permite a las aplicaciones administrar los usuarios del dispositivo, lo que incluye buscarlos, crearlos y eliminarlos."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recuperar información sobre las aplicaciones en ejecución"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite que la aplicación recupere información detallada sobre tareas en ejecución y recientemente ejecutadas. Las aplicaciones malintencionadas pueden hallar información privada sobre otras aplicaciones."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"reorganizar aplicaciones en ejecución"</string>
@@ -232,7 +276,7 @@
     <string name="permlab_changeConfiguration" msgid="4162092185124234480">"cambiar la configuración de visualización del sistema"</string>
     <string name="permdesc_changeConfiguration" msgid="4372223873154296076">"Permite que la aplicación cambie la configuración actual como, por ejemplo, la configuración regional o el tamaño de fuente general."</string>
     <string name="permlab_enableCarMode" msgid="5684504058192921098">"activar el modo de auto"</string>
-    <string name="permdesc_enableCarMode" msgid="4853187425751419467">"Permite que la aplicación habilite el modo coche."</string>
+    <string name="permdesc_enableCarMode" msgid="4853187425751419467">"Permite que la aplicación habilite el modo automóvil."</string>
     <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"cerrar otras aplicaciones"</string>
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Este permiso autoriza a la aplicación a interrumpir procesos en segundo plano de otras aplicaciones y puede hacer, por lo tanto, que esas aplicaciones dejen de ejecutarse."</string>
     <string name="permlab_forceStopPackages" msgid="2329627428832067700">"forzar la detención de otras aplicaciones"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Permite que la aplicación recupere el estado interno del sistema. Las aplicaciones maliciosas pueden recuperar una amplia variedad de información privada y segura que normalmente no necesitarían."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"recuperar contenido de la pantalla"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite que la aplicación recupere el contenido de la ventana activa. Las aplicaciones maliciosas pueden recuperar el contenido completo de la ventana y examinar todo el texto, excepto las contraseñas."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Activación temporal de la accesibilidad"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permite a una aplicación activar temporalmente la accesibilidad en el dispositivo. Las aplicaciones maliciosas pueden activar la accesibilidad sin el consentimiento del usuario."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"recuperar información de ventanas"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permite que una aplicación recupere la información del administrador de ventanas relacionada con estas. Las aplicaciones maliciosas pueden recuperar información destinada al uso interno del sistema."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrar eventos"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Permite que una aplicación registre un filtro de entrada que filtre la transmisión de todos los eventos del usuario antes de ser enviados. Las aplicaciones maliciosas pueden controlar la IU del sistema sin la intervención del usuario."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"ampliar la pantalla"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Permite que una aplicación amplíe el contenido de una pantalla. Las aplicaciones malintencionadas pueden transformar el contenido de la pantalla de manera que el dispositivo quede inutilizable."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"cierre parcial"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Pone al administrador de la actividad en estado de cierre. No realiza un cierre completo."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir conmutadores de aplicación"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permite que la aplicación controle la cantidad máxima de procesos que se ejecutarán. Las aplicaciones normales no deben utilizar este permiso."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forzar el cierre de aplicaciones de fondo"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Permite que la aplicación controle si las actividades se deben finalizar al pasar a segundo plano. Las aplicaciones normales no deben utilizar este permiso."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"modificar la estadística de la batería"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Permite que la aplicación modifique las estadísticas recopiladas sobre la batería. Las aplicaciones normales no deben utilizar este permiso."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"leer estadísticas de la batería"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permite a una aplicación leer los datos actuales de uso de batería de bajo nivel. Puede permitir a la aplicación buscar información detallada sobre las aplicaciones que usas."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modificar las estadísticas de la batería"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permite a la aplicación modificar las estadísticas recopiladas de la batería. Las aplicaciones normales no deben utilizarlo."</string>
     <string name="permlab_backup" msgid="470013022865453920">"copia de seguridad y restauración del sistema de control"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Permite que la aplicación controle el mecanismo de copia de seguridad y restauración del sistema. Las aplicaciones normales no deben utilizar este permiso."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"Confirmar una copia completa de seguridad o una operación de restauración"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"mostrar ventanas no autorizadas"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Permite que la aplicación cree ventanas para la interfaz de usuario interna del sistema. Las aplicaciones normales no deben usar este permiso."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"destacar sobre otras aplicaciones"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Permite que la aplicación muestre ventanas de alerta del sistema. Algunas ventanas de alerta pueden ocupar toda la pantalla."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Permite a la aplicación escribir por encima de otras aplicaciones o partes de la interfaz de usuario que pueden interferir en tu uso de la interfaz en cualquier aplicación o cambiar lo que crees que ves en otras aplicaciones."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"modificar la velocidad de la animación global"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Permite que la aplicación cambie la velocidad de animación global (animaciones más rápidas o más lentas) en cualquier momento."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"administrar tokens de aplicación"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Permite que la aplicación cree y administre sus propios tokens al ignorar su orden z normal. Las aplicaciones normales no deben utilizar este permiso."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"suspender la pantalla"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Permite que la aplicación suspenda temporalmente la pantalla para una transición a pantalla completa."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"presionar teclas y botones de control"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Permite que la aplicación ofrezca sus propios eventos de entrada (pulsaciones de teclas, etc.) a otras aplicaciones. Las aplicaciones maliciosas pueden utilizar este permiso para controlar la tableta."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Permite que la aplicación ofrezca sus propios eventos de entrada (pulsaciones de teclas, etc.) a otras aplicaciones. Las aplicaciones maliciosas pueden utilizar este permiso para controlar el dispositivo."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"instalar aplicaciones directamente"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Permite que la aplicación instale paquetes de Android nuevos o actualizados. Las aplicaciones maliciosas pueden utilizar este permiso para agregar nuevas aplicaciones con permisos arbitrarios potentes."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"eliminar todos los datos de caché de la aplicación"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Permite que la aplicación libere almacenamiento en la tableta al eliminar archivos en el directorio caché de la aplicación. El acceso al proceso del sistema suele ser muy restringido."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Permite que la aplicación libere espacio de almacenamiento en el dispositivo al eliminar archivos en el directorio caché de la aplicación. El acceso al proceso del sistema suele ser muy restringido."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Permite a la aplicación liberar almacenamiento de la tableta al eliminar archivos en los directorios de la memoria cache de otras aplicaciones. Esto puede ocasionar que otras aplicaciones arranquen más lentamente, ya que deben volver a recuperar sus datos."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Permite a la aplicación liberar almacenamiento del dispositivo al borrar los archivos en los directorios de la memoria cache de otras aplicaciones. Esto puede ocasionar que otras aplicaciones arranquen más lentamente, ya que deben volver a recuperar sus datos."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"mover recursos de la aplicación"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Permite que la aplicación traslade recursos de la aplicación de medios internos a medios externos y viceversa."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"lee los datos confidenciales del registro"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Permite que la aplicación acceda a comandos adicionales del proveedor de ubicación. Esto puede permitirle a la aplicación interferir con el funcionamiento del GPS o de otras fuentes de ubicación."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"autorización para instalar un proveedor de ubicación"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Permite crear fuentes de ubicación simuladas para hacer pruebas o instalar un nuevo proveedor de ubicación. Este permiso autoriza a la aplicación a sobrescribir la ubicación o el estado proporcionados por otras fuentes de ubicación, como los proveedores de ubicación o GPS."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"ubicación exacta (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Permite acceder a fuentes de determinación de la ubicación exacta, como el sistema de posicionamiento global (GPS) de la tableta. Cuando los servicios de ubicación están disponibles y activados, este permiso permite que la aplicación determine tu ubicación exacta."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Permite acceder a fuentes de determinación de la ubicación exacta, como el sistema de posicionamiento global (GPS) del dispositivo. Cuando los servicios de ubicación están disponibles y activados, este permiso permite que la aplicación determine tu ubicación exacta."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"ubicación aproximada (basada en red)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Permite acceder a la ubicación aproximada a través de proveedores de ubicación que utilizan fuentes de conexión como torres de telefonía móvil y redes Wi-Fi. Cuando estos servicios de ubicación están disponibles y activados, este permiso permite que la aplicación determine tu ubicación aproximada."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"ubicación precisa (según el GPS y la red)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Permite a la aplicación obtener tu ubicación precisa mediante el Sistema de Posicionamiento Global (GPS) o las fuentes de ubicación de red, como las torres de celulares y Wi-Fi. Estos servicios de ubicación deben estar encendidos y disponibles en tu dispositivo para que los use la aplicación. Las aplicaciones pueden usarlo para determinar tu ubicación, lo cual puede consumir más batería."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"ubicación aproximada (según la red)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Permite a la aplicación obtener tu ubicación aproximada. Esta ubicación deriva de los servicios de ubicación que usan fuentes de ubicación de red, como torres de celulares y Wi-Fi. Estos servicios de ubicación deben estar encendidos y disponibles en tu dispositivo para que los use la aplicación. Las aplicaciones pueden usarlo para determinar tu ubicación aproximada."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"acceder a SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Permite que la aplicación utilice funciones de SurfaceFlinger de bajo nivel."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"leer el búfer de tramas"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Permite que la aplicación lea el contenido del búfer de tramas."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"configurar pantallas Wi-Fi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permite que la aplicación configure y se conecte a pantallas Wi-Fi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controlar pantallas Wi-Fi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permite que la aplicación controle funciones de bajo nivel de las pantallas Wi-Fi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"cambiar tu configuración de audio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite que la aplicación modifique la configuración de audio global, por ejemplo, el volumen y el altavoz de salida."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"grabar audio"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"acceder a la configuración de Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Permite que la aplicación configure la tableta Bluetooth local y descubra y se sincronice con dispositivos remotos."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permite que la aplicación configure el dispositivo Bluetooth local y descubra y se sincronice con dispositivos remotos."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Ver conexiones WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"conectarse y desconectarse de WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permite que la aplicación determine si está activada la conexión WiMAX y que obtenga información sobre las redes WiMAX que están conectadas."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Cambiar el estado de WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite que la aplicación conecte la tableta a una red WiMAX y que la desconecte de ella."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Permite que la aplicación modifique los feeds actualmente sincronizados. Las aplicaciones maliciosas pueden cambiar tus feeds sincronizados."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"leer los términos que agregaste al diccionario"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Permite que la aplicación consulte cualquier palabra, nombre o frase que el usuario haya almacenado en su diccionario."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"agregar al diccionario definido por el usuario"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"agregar palabras en el diccionario definido por el usuario"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Permite que la aplicación ingrese palabras nuevas en el diccionario del usuario."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"probar acceso a almacenamiento protegido"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"probar acceso a almacenamiento protegido"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Permite que la aplicación pruebe un permiso de almacenamiento USB que estará disponible en futuros dispositivos."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Prueba permiso almac. USB."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Permite que la aplicación pruebe un permiso para la tarjeta SD que estará disponible en futuros dispositivos."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modificar/borrar contenido USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modificar o eliminar el contenido de la tarjeta SD"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Admite que la aplicación escriba en la tarjeta SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"modificar/eliminar los contenidos del almacenamientos de medios internos"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Permite que la aplicación modifique el contenido del almacenamiento de medios interno."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"acceder almacenamiento externo"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Permite que la aplicación acceda al almacenamiento externo de todos los usuarios."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"Acceder al sistema de archivos caché"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite que la aplicación lea y escriba el sistema de archivos almacenado en caché."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"realizar o recibir llamadas por Internet"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Exige que se encripten los datos de la aplicación almacenados."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Desactivar cámaras"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Evita el uso de todas las cámaras del dispositivo."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Desactiv. funciones en bloqueo"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Evita el uso de algunas funciones con el bloqueo del teclado."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Móvil"</item>
@@ -674,7 +737,7 @@
     <string name="relationTypeSister" msgid="1735983554479076481">"Hermana"</string>
     <string name="relationTypeSpouse" msgid="394136939428698117">"Cónyuge"</string>
     <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Personalizado"</string>
-    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Página principal"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Casa"</string>
     <string name="sipAddressTypeWork" msgid="6920725730797099047">"Trabajo"</string>
     <string name="sipAddressTypeOther" msgid="4408436162950119849">"Otro"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Ingresa el código PIN"</string>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Volver a intentarlo"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Se superó el máximo de intentos permitido para el desbloqueo facial del dispositivo."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Cargando <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Cargado."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Cargado"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecta tu cargador."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"No hay tarjeta SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"No hay tarjeta SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No hay tarjeta SIM en el tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No hay tarjeta SIM en el dispositivo."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Inserta una tarjeta SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Se eliminó el patrón"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Se agregó una celda."</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Se completó el patrón"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Agregar widget"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Vacío"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Área desbloqueada expandida."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"El área desbloqueada se contrajo."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> widget"</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Selector de usuarios"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Estado"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Cámara"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Controles de medios"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Se comenzaron a reordenar los widgets."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Se terminaron de reordenar los widgets."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> eliminado"</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Expandir el área desbloqueada"</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Desbloqueo por deslizamiento"</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueo por patrón"</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Desbloqueo facial"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueo por PIN"</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueo por contraseña"</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área de patrón"</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslizamiento"</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -824,19 +907,19 @@
     <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"¿Activar exploración táctil?"</string>
     <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> desea activar la exploración táctil. Cuando esta función esté activada, podrás escuchar o ver descripciones del contenido seleccionado o usar gestos para interactuar con la tableta."</string>
     <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> desea activar la exploración táctil. Cuando esta función esté activada, podrás escuchar o ver descripciones del contenido seleccionado o usar gestos para interactuar con el dispositivo."</string>
-    <string name="oneMonthDurationPast" msgid="7396384508953779925">"hace 1 mes"</string>
+    <string name="oneMonthDurationPast" msgid="7396384508953779925">"Hace 1 mes."</string>
     <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Anterior a 1 mes atrás"</string>
   <plurals name="num_seconds_ago">
     <item quantity="one" msgid="4869870056547896011">"hace 1 segundo"</item>
     <item quantity="other" msgid="3903706804349556379">"hace <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
   </plurals>
   <plurals name="num_minutes_ago">
-    <item quantity="one" msgid="3306787433088810191">"hace 1 minuto"</item>
+    <item quantity="one" msgid="3306787433088810191">"Hace 1 minuto."</item>
     <item quantity="other" msgid="2176942008915455116">"hace <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
   </plurals>
   <plurals name="num_hours_ago">
-    <item quantity="one" msgid="9150797944610821849">"hace 1 hora"</item>
-    <item quantity="other" msgid="2467273239587587569">"hace <xliff:g id="COUNT">%d</xliff:g> horas"</item>
+    <item quantity="one" msgid="9150797944610821849">"Hace 1 hora."</item>
+    <item quantity="other" msgid="2467273239587587569">"Hace <xliff:g id="COUNT">%d</xliff:g> horas."</item>
   </plurals>
   <plurals name="last_num_days">
     <item quantity="other" msgid="3069992808164318268">"Últimos <xliff:g id="COUNT">%d</xliff:g> días"</item>
@@ -845,7 +928,7 @@
     <string name="older" msgid="5211975022815554840">"Antiguos"</string>
   <plurals name="num_days_ago">
     <item quantity="one" msgid="861358534398115820">"ayer"</item>
-    <item quantity="other" msgid="2479586466153314633">"hace <xliff:g id="COUNT">%d</xliff:g> días"</item>
+    <item quantity="other" msgid="2479586466153314633">"Hace <xliff:g id="COUNT">%d</xliff:g> días."</item>
   </plurals>
   <plurals name="in_num_seconds">
     <item quantity="one" msgid="2729745560954905102">"en 1 segundo"</item>
@@ -869,15 +952,15 @@
   </plurals>
   <plurals name="abbrev_num_minutes_ago">
     <item quantity="one" msgid="6361490147113871545">"hace 1 min"</item>
-    <item quantity="other" msgid="851164968597150710">"hace <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
+    <item quantity="other" msgid="851164968597150710">"Hace <xliff:g id="COUNT">%d</xliff:g> minutos."</item>
   </plurals>
   <plurals name="abbrev_num_hours_ago">
-    <item quantity="one" msgid="4796212039724722116">"hace 1 hora"</item>
+    <item quantity="one" msgid="4796212039724722116">"Hace 1 hora."</item>
     <item quantity="other" msgid="6889970745748538901">"hace <xliff:g id="COUNT">%d</xliff:g> horas"</item>
   </plurals>
   <plurals name="abbrev_num_days_ago">
     <item quantity="one" msgid="8463161711492680309">"ayer"</item>
-    <item quantity="other" msgid="3453342639616481191">"hace <xliff:g id="COUNT">%d</xliff:g> días"</item>
+    <item quantity="other" msgid="3453342639616481191">"Hace <xliff:g id="COUNT">%d</xliff:g> días."</item>
   </plurals>
   <plurals name="abbrev_in_num_seconds">
     <item quantity="one" msgid="5842225370795066299">"en 1 segundo"</item>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copiar URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Seleccionar texto"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selección de texto"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"Agregar al diccionario"</string>
-    <string name="deleteText" msgid="7070985395199629156">"eliminar"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Agregar al diccionario"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Eliminar"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Método de entrada"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acciones de texto"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Queda poco espacio de almacenamiento"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Abrir redes disponibles de Wi-Fi"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Accede a una red Wi-Fi."</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Acceder a la red"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"No se pudo conectar a la red Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tiene una mala conexión a Internet."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Para:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Escribe el PIN solicitado:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"El dispositivo se desconectará temporalmente de la red Wi-Fi mientras esté conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="select_character" msgid="3365550120617701745">"Insertar caracteres"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Enviando mensajes SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; está enviando una gran cantidad de mensajes SMS. ¿Quieres permitir que está aplicación siga enviando mensajes?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Permitir"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Rechazar"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; desea enviar un mensaje a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Esto "<font fgcolor="#ffffb060">" puede causar que se apliquen cargos "</font>" en tu cuenta móvil."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Se aplicarán cargos en tu cuenta móvil."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Enviar"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Cancelar"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Recordar mi elección"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Puedes cambiar esta opción más tarde en Configuración &gt; Aplicaciones."</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Permitir siempre"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"No permitir nunca"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Tarjeta SIM eliminada"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"La red para celulares no estará disponible hasta que reinicies, luego de insertar una tarjeta SIM válida."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Finalizado"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Configurar fecha"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Establecer"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Listo"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Predeterminado"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"No se requieren permisos"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Ocultar"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostrar todos"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NUEVO: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NUEVO: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Proporcionado por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"No se requieren permisos"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"esto puede costarte dinero"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Almacenamiento USB masivo"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Conectado al USB"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Has conectado el dispositivo a la computadora por USB. Toca el siguiente botón si quieres copiar archivos entre tu computadora y el almacenamiento USB de tu Android."</string>
@@ -1126,7 +1218,7 @@
     <string name="ime_action_search" msgid="658110271822807811">"Buscar"</string>
     <string name="ime_action_send" msgid="2316166556349314424">"Enviar"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Siguiente"</string>
-    <string name="ime_action_done" msgid="8971516117910934605">"Hecho"</string>
+    <string name="ime_action_done" msgid="8971516117910934605">"Listo"</string>
     <string name="ime_action_previous" msgid="1443550039250105948">"Ant."</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Ejecutar"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Marcar el número"\n"con <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN está activado por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca para administrar la red."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Toca para administrar la red."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Estableciendo conexión con la VPN siempre activada..."</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Se estableció conexión con la VPN siempre activada."</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Se produjo un error al establecer conexión con la VPN siempre activada."</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Toca para restablecer la conexión."</string>
     <string name="upload_file" msgid="2897957172366730416">"Elegir archivo"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"No se seleccionó un archivo."</string>
     <string name="reset" msgid="2448168080964209908">"Restablecer"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Compartir"</string>
     <string name="find" msgid="4808270900322985960">"Buscar"</string>
     <string name="websearch" msgid="4337157977400211589">"Buscar en la Web"</string>
+    <string name="find_next" msgid="5742124618942193978">"Buscar siguiente"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Buscar anterior"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Solicitud de ubicación de <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Solicitud de ubicación"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Solicitado por <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Dispositivo"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auriculares"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altavoces del conector"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Audio HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Listo"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Salida multimedia"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Examinando..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Conectando..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Disponible"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"No disponible"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Pantalla integrada"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Pantalla HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Superposición #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> ppp"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Se conectó la pantalla inalámbrica"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Esta pantalla se muestra en otro dispositivo."</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Desconectar"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Llamada de emergencia"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"¿Olvidaste el patrón?"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Patrón incorrecto"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Contraseña incorrecta"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN incorrecto"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Vuelve a intentarlo en <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Dibuja tu patrón."</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Ingresa el PIN de la tarjeta SIM."</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Ingresa el PIN."</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Ingresa tu contraseña."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"La tarjeta SIM está inhabilitada. Para continuar, ingresa el código PUK. Si quieres obtener más información, ponte en contacto con el proveedor."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Ingresa el código PIN deseado"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Confirmar código PIN deseado"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Desbloqueando tarjeta SIM…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Código PIN incorrecto"</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Escribe un PIN que tenga de cuatro a ocho números."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"El código PUK debe tener ocho números como mínimo."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Vuelve a ingresar el código PUK correcto. Si ingresas un código incorrecto varias veces, se inhabilitará la tarjeta SIM."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Los códigos PIN no coinciden."</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Demasiados intentos incorrectos de ingresar el patrón"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Para desbloquear, accede con tu cuenta de Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Nombre de usuario (correo)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Contraseña"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Acceder"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Nombre de usuario o contraseña incorrectos"</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"¿Olvidaste tu nombre de usuario o contraseña?"\n"Accede a "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Comprobando la cuenta…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Escribiste incorrectamente tu PIN <xliff:g id="NUMBER_0">%d</xliff:g> veces. "\n\n"Vuelve a intentarlo en <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Escribiste incorrectamente tu contraseña <xliff:g id="NUMBER_0">%d</xliff:g> veces. "\n\n"Vuelve a intentarlo en <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Dibujaste incorrectamente tu patrón de desbloqueo <xliff:g id="NUMBER_0">%d</xliff:g> veces. "\n\n"Vuelve a intentarlo en <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Intentaste desbloquear la tableta <xliff:g id="NUMBER_0">%d</xliff:g> veces, pero no lo lograste. Puedes intentarlo <xliff:g id="NUMBER_1">%d</xliff:g> veces más antes de que se restablezcan los valores predeterminados de fábrica de la tableta y se pierdan todos los datos del usuario."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Intentaste desbloquear el dispositivo <xliff:g id="NUMBER_0">%d</xliff:g> veces, pero no lo lograste. Puedes intentarlo <xliff:g id="NUMBER_1">%d</xliff:g> veces más antes de que se restablezcan los valores predeterminados de fábrica del dispositivo y se pierdan todos los datos del usuario."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Intentaste desbloquear la tableta <xliff:g id="NUMBER">%d</xliff:g> veces, pero no lo lograste. Se restablecerán los valores predeterminados de fábrica de la tableta."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Intentaste desbloquear el dispositivo <xliff:g id="NUMBER">%d</xliff:g> veces, pero no lo lograste. Se restablecerán los valores predeterminados de fábrica del dispositivo."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Dibujaste incorrectamente tu patrón de desbloqueo <xliff:g id="NUMBER_0">%d</xliff:g> veces. Luego de <xliff:g id="NUMBER_1">%d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees tu tableta mediante el uso de una cuenta de correo."\n\n" Vuelve a intentarlo en <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Dibujaste incorrectamente tu patrón de desbloqueo <xliff:g id="NUMBER_0">%d</xliff:g> veces. Luego de <xliff:g id="NUMBER_1">%d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees tu dispositivo mediante el uso de una cuenta de correo."\n\n" Vuelve a intentarlo en <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Eliminar"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"¿Aumentar el volumen por encima del nivel seguro?"\n"Si escuchas con el volumen alto durante períodos prolongados, puedes dañar tu audición."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Mantén presionado con dos dedos para activar la accesibilidad."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Se activó la accesibilidad."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Se canceló la accesibilidad."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Usuario actual: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="owner_name" msgid="2716755460376028154">"Propietario"</string>
 </resources>
diff --git a/core/res/res/values-es/donottranslate-cldr.xml b/core/res/res/values-es/donottranslate-cldr.xml
index faf171a..0a680b6 100644
--- a/core/res/res/values-es/donottranslate-cldr.xml
+++ b/core/res/res/values-es/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">enero</string>
-    <string name="month_long_standalone_february">febrero</string>
-    <string name="month_long_standalone_march">marzo</string>
-    <string name="month_long_standalone_april">abril</string>
-    <string name="month_long_standalone_may">mayo</string>
-    <string name="month_long_standalone_june">junio</string>
-    <string name="month_long_standalone_july">julio</string>
-    <string name="month_long_standalone_august">agosto</string>
-    <string name="month_long_standalone_september">septiembre</string>
-    <string name="month_long_standalone_october">octubre</string>
-    <string name="month_long_standalone_november">noviembre</string>
-    <string name="month_long_standalone_december">diciembre</string>
-
-    <string name="month_long_january">enero</string>
-    <string name="month_long_february">febrero</string>
-    <string name="month_long_march">marzo</string>
-    <string name="month_long_april">abril</string>
-    <string name="month_long_may">mayo</string>
-    <string name="month_long_june">junio</string>
-    <string name="month_long_july">julio</string>
-    <string name="month_long_august">agosto</string>
-    <string name="month_long_september">septiembre</string>
-    <string name="month_long_october">octubre</string>
-    <string name="month_long_november">noviembre</string>
-    <string name="month_long_december">diciembre</string>
-
-    <string name="month_medium_january">ene.</string>
-    <string name="month_medium_february">feb.</string>
-    <string name="month_medium_march">mar.</string>
-    <string name="month_medium_april">abr.</string>
-    <string name="month_medium_may">may.</string>
-    <string name="month_medium_june">jun.</string>
-    <string name="month_medium_july">jul.</string>
-    <string name="month_medium_august">ago.</string>
-    <string name="month_medium_september">sep.</string>
-    <string name="month_medium_october">oct.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">dic.</string>
-
-    <string name="month_shortest_january">E</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">domingo</string>
-    <string name="day_of_week_long_monday">lunes</string>
-    <string name="day_of_week_long_tuesday">martes</string>
-    <string name="day_of_week_long_wednesday">miércoles</string>
-    <string name="day_of_week_long_thursday">jueves</string>
-    <string name="day_of_week_long_friday">viernes</string>
-    <string name="day_of_week_long_saturday">sábado</string>
-
-    <string name="day_of_week_medium_sunday">dom.</string>
-    <string name="day_of_week_medium_monday">lun.</string>
-    <string name="day_of_week_medium_tuesday">mar.</string>
-    <string name="day_of_week_medium_wednesday">mié.</string>
-    <string name="day_of_week_medium_thursday">jue.</string>
-    <string name="day_of_week_medium_friday">vie.</string>
-    <string name="day_of_week_medium_saturday">sáb.</string>
-
-    <string name="day_of_week_short_sunday">dom.</string>
-    <string name="day_of_week_short_monday">lun.</string>
-    <string name="day_of_week_short_tuesday">mar.</string>
-    <string name="day_of_week_short_wednesday">mié.</string>
-    <string name="day_of_week_short_thursday">jue.</string>
-    <string name="day_of_week_short_friday">vie.</string>
-    <string name="day_of_week_short_saturday">sáb.</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">L</string>
-    <string name="day_of_week_shortest_tuesday">M</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">J</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">a.m.</string>
-    <string name="pm">p.m.</string>
-    <string name="yesterday">ayer</string>
-    <string name="today">hoy</string>
-    <string name="tomorrow">mañana</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 0118067..c129483 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opciones del teléfono"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Bloqueo de pantalla"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Apagar"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Informe de error"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Crear informe de errores"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Se recopilará información sobre el estado actual de tu dispositivo, que se enviará por correo electrónico. Pasarán unos minutos desde que se inicie el informe de errores hasta que se envíe, por lo que te recomendamos que tengas paciencia."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Modo silencio"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"El sonido está desactivado. Activar"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"El sonido está activado. Desactivar"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Tus mensajes"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Leer y escribir SMS, correos electrónicos y otros mensajes"</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Tu información personal"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Accede directamente al calendario y a los contactos almacenados en el tablet."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Acceso directo al calendario y a los contactos almacenados en el teléfono"</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Acceder directamente a tu información personal almacenada en la tarjeta de contacto"</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Tu información social"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Acceder directamente a la información de tus contactos y tus conexiones sociales"</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Tu ubicación"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Controlar tu ubicación física"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Comunicación de red"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Acceder a distintas funciones de red"</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Acceder a dispositivos y redes a través de Bluetooth"</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Ajustes de audio"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Modificar ajustes de audio"</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Afectar a la batería"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Usar funciones que agotan la batería rápidamente"</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Calendario"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Acceder directamente al calendario y a los eventos"</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Leer el diccionario del usuario"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Leer palabras del diccionario del usuario"</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Escribir en el diccionario del usuario"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Añadir palabras al diccionario del usuario"</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Marcadores e historial"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Acceder directamente a los marcadores y al historial del navegador"</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarma"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Establecer alarmas"</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Buzón de voz"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Acceder directamente al buzón de voz"</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Micrófono"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Acceder directamente al micrófono para grabar audio"</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Cámara"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Acceder directamente a la cámara para hacer fotos o grabar vídeos"</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Información de tus aplicaciones"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Posibilidad de influir en el funcionamiento de otras aplicaciones del dispositivo"</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Fondo de pantalla"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Cambiar la configuración del fondo de pantalla del dispositivo"</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Reloj"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Cambiar la zona horaria o la hora del dispositivo"</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Barra de estado"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Cambiar la configuración de la barra de estado del dispositivo"</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Ajustes de sincronización"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Acceder a los ajustes de sincronización"</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Tus cuentas"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Acceder a las cuentas disponibles"</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Controles de hardware"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Acceso de nivel inferior y control del sistema"</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Herramientas de desarrollo"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funciones necesarias solo para desarrolladores de aplicaciones"</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Interfaz de usuario de otras aplicaciones"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Influir en la interfaz de usuario de otras aplicaciones"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Almacenamiento"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Acceso a almacenamiento USB"</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Acceder a la tarjeta SD"</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permite que la aplicación reciba y procese mensajes WAP, lo que significa que podría utilizar este permiso para controlar o eliminar mensajes enviados al usuario sin mostrárselos."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"recuperar aplicaciones en ejecución"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Permite que aplicación recupere información sobre tareas que se están ejecutando en ese momento o que se han ejecutado recientemente. La aplicación puede utilizar este permiso para descubrir cuáles son las aplicaciones que se utilizan en el dispositivo."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interactuar con los usuarios"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permite que la aplicación lleve a cabo acciones entre los diferentes usuarios del dispositivo. Las aplicaciones maliciosas pueden utilizar este permiso para infringir la protección entre usuarios."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"licencia completa para interactuar con los usuarios"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permite que la aplicación interactúe con los usuarios."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"administrar usuarios"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permite a las aplicaciones administrar los usuarios del dispositivo, p. ej., buscarlos, crearlos y eliminarlos."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recuperar información de aplicaciones en ejecución"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite que la aplicación recupere información sobre tareas que se están ejecutando en este momento o que se han ejecutado recientemente. Las aplicaciones malintencionadas pueden usar este servicio para acceder a información privada sobre otras aplicaciones."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"reorganizar aplicaciones en ejecución"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Permite que la aplicación recupere el estado interno del sistema. Las aplicaciones malintencionadas pueden usar este permiso para recuperar una gran variedad de información protegida y privada que normalmente no deberían necesitar."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"recuperar contenido de la pantalla"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite que la aplicación recupere el contenido de la ventana activa. Las aplicaciones malintencionadas pueden recuperar todo el contenido de la ventana y analizar todo el texto de la misma, excepto las contraseñas."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"habilitar la accesibilidad de forma temporal"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permite que una aplicación habilite la accesibilidad en el dispositivo de forma temporal. Las aplicaciones maliciosas pueden habilitar la accesibilidad sin el consentimiento del usuario."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"recuperar información de ventanas"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permite que una aplicación recupere información sobre las ventanas del administrador de ventanas. Las aplicaciones malintencionadas pueden recuperar información destinada al uso interno del sistema."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrar eventos"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Permite que una aplicación registre un filtro de entrada que filtre el flujo de los eventos del usuario antes de que se envíe. Las aplicaciones malintencionadas pueden controlar la interfaz del sistema sin la intervención del usuario."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"ampliar pantalla"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Permite que una aplicación amplíe el contenido de una pantalla. Las aplicaciones maliciosas pueden transformar el contenido de la pantalla para que el dispositivo no se pueda utilizar."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"cierre parcial"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Pone el administrador de actividades en estado de cierre. No realiza un cierre completo."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar cambios de aplicación"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permite que la aplicación controle el número máximo de procesos que se ejecutarán. No es necesario nunca para las aplicaciones normales."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forzar el cierre de aplicaciones en segundo plano"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Permite que la aplicación controle si las actividades finalizan siempre en cuanto pasan a segundo plano. Las aplicaciones normales nunca necesitan este permiso."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"modificar estadísticas de la batería"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Permite que la aplicación modifique las estadísticas recopiladas sobre la batería. Las aplicaciones normales no deben usar este permiso."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"leer estadísticas de la batería"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permite que una aplicación consulte los datos actuales de uso de batería de nivel inferior. Puede permitir que la aplicación obtenga información detallada sobre las aplicaciones que utilizas."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modificar estadísticas de la batería"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permite que la aplicación modifique las estadísticas recopiladas sobre la batería. Las aplicaciones normales no deben usar este permiso."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controlar las copias de seguridad y las restauraciones del sistema"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Permite que la aplicación controle el mecanismo de copia de seguridad y restauración del sistema. Las aplicaciones normales no deben usar este permiso."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"confirmar restauración o copia de seguridad completa"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"mostrar ventanas no autorizadas"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Permite que la aplicación cree ventanas para la interfaz de usuario interna del sistema. Las aplicaciones normales no deben usar este permiso."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"destacar sobre otras aplicaciones"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Permite que la aplicación muestre ventanas de alerta del sistema. Algunas ventanas de alerta pueden ocupar toda la pantalla."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Permite que la aplicación escriba sobre otras aplicaciones o en partes de interfaz de usuario. Pueden interferir con el uso de la interfaz en cualquier aplicación o modificar lo que crees que se muestra en otras aplicaciones."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"modificar velocidad de animación global"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Permite que la aplicación cambie la velocidad de animación global (animaciones más rápidas o más lentas) en cualquier momento."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"administrar tokens de aplicación"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Permite que la aplicación cree y administre sus propios tokens al ignorar su orden Z normal. Nunca debería ser necesario para las aplicaciones normales."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"bloquear pantalla"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Permite que la aplicación bloquee la pantalla temporalmente para activar el modo de pantalla completa."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"pulsar teclas y botones de control"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Permite que la aplicación proporcione sus propios eventos de entrada (pulsación de teclas, etc.) a otras aplicaciones. Las aplicaciones malintencionadas pueden usar este permiso para controlar el tablet."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Permite que la aplicación proporcione sus propios eventos de entrada (pulsación de teclas, etc.) a otras aplicaciones. Las aplicaciones malintencionadas pueden usar este permiso para controlar el teléfono."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"instalar aplicaciones directamente"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Permite que la aplicación instale paquetes de Android nuevos o actualizados. Las aplicaciones malintencionadas pueden usar este permiso para añadir aplicaciones nuevas con permisos arbitrarios potentes."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"eliminar todos los datos de caché de la aplicación"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Permite que la aplicación libere espacio de almacenamiento en el tablet al eliminar archivos en el directorio de caché de la aplicaciones. El acceso al proceso del sistema suele ser muy restringido."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Permite que la aplicación elimine archivos en el directorio de caché de la aplicación para liberar espacio de almacenamiento en el teléfono. El acceso al proceso del sistema suele ser muy restringido."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Permite que la aplicación elimine archivos de los directorios de la caché de otras aplicaciones para liberar espacio del tablet. Esto puede provocar que otras aplicaciones se inicien de forma más lenta, ya que deben volver a recuperar sus datos."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Permite que la aplicación elimine archivos de los directorios de la caché de otras aplicaciones para liberar espacio del teléfono. Esto puede provocar que otras aplicaciones se inicien de forma más lenta, ya que deben volver a recuperar sus datos."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"mover recursos de aplicaciones"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Permite que la aplicación mueva los recursos de aplicaciones de un medio interno a otro externo y viceversa."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"leer datos de registro personales"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Este permiso autoriza a la aplicación a acceder a comandos adicionales del proveedor de ubicación y puede permitirle interferir en el funcionamiento del GPS o de otras fuentes de ubicación."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"permiso para instalar un proveedor de ubicación"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Permite crear fuentes de ubicación simuladas para hacer pruebas o instalar un nuevo proveedor de ubicación. Este permiso autoriza a la aplicación a sobrescribir la ubicación o el estado proporcionados por otras fuentes de ubicación, como los proveedores de ubicación o GPS."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"ubicación exacta (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Permite acceder a fuentes de determinación de la ubicación exacta, como el sistema de posicionamiento global (GPS) del tablet. Cuando los servicios de ubicación están disponibles y activados, este permiso permite que la aplicación determine tu ubicación exacta."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Permite acceder a fuentes de determinación de la ubicación exacta, como el sistema de posicionamiento global (GPS) del teléfono. Cuando los servicios de ubicación están disponibles y activados, este permiso permite que la aplicación determine tu ubicación exacta."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"ubicación aproximada (basada en red)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Permite acceder a la ubicación aproximada a través de proveedores de ubicación que utilicen fuentes de conexión como torres de telefonía móvil y redes Wi-Fi. Cuando estos servicios de ubicación están disponibles y activados, este permiso permite que la aplicación determine tu ubicación aproximada."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"ubicación precisa (basada en red y GPS)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Permite que la aplicación obtenga tu ubicación precisa mediante el Sistema de posicionamiento global (GPS) o fuentes de ubicación de red, como torres de telefonía y redes Wi-Fi. Estos servicios de ubicación deben estar activados y disponibles para que la aplicación pueda utilizarlos. Las aplicaciones pueden utilizar este permiso para determinar tu ubicación y es posible que el dispositivo consuma más batería."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"ubicación aproximada (basada en red)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Permite que la aplicación obtenga tu ubicación aproximada. Esta ubicación se deriva de los servicios de ubicación que utilizan fuentes de ubicación de red, como torres de telefonía y redes Wi-Fi. Estos servicios de ubicación deben estar activados y disponibles para que la aplicación pueda utilizarlos. Las aplicaciones pueden utilizar este permiso para determinar tu ubicación de forma aproximada."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"acceder a SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Permite que la aplicación use funciones de SurfaceFlinger de nivel inferior."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"leer memoria de almacenamiento intermedio"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Permite que la aplicación lea el contenido de la memoria de almacenamiento intermedio."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"configurar pantallas Wi-Fi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permite que la aplicación configure pantallas Wi-Fi y se conecte a ellas."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controlar pantallas Wi-Fi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permite que la aplicación controle funciones de bajo nivel de pantallas Wi-Fi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"cambiar la configuración de audio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite que la aplicación modifique la configuración de audio global (por ejemplo, el volumen y el altavoz de salida)."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"grabar sonido"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"acceder a los ajustes de Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Permite que la aplicación configure el tablet Bluetooth local y que detecte dispositivos remotos y se sincronice con ellos."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permite que la aplicación configure el teléfono Bluetooth local y que detecte dispositivos remotos y se sincronice con ellos."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Ver conexiones WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"conectarse a WiMAX y desconectarse de esta red"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permite que la aplicación determine si está habilitada la conexión WiMAX y obtenga información sobre las redes WiMAX que están conectadas."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Cambiar estado de WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite que la aplicación conecte el tablet a redes WiMAX y lo desconecte de ellas."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Permite que la aplicación modifique los feeds sincronizados actualmente. Las aplicaciones malintencionadas pueden modificar los feeds sincronizados."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"consultar términos que hayas añadido al diccionario"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Permite que la aplicación lea cualquier palabra, nombre o frase que el usuario haya almacenado en su diccionario."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"añadir al diccionario definido por el usuario"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"añadir palabras al diccionario definido por el usuario"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Permite que la aplicación escriba palabras nuevas en el diccionario de usuario."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"probar acceso a almacenamiento protegido"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"probar acceso a almacenamiento protegido"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Probar permiso USB para futuros dispositivos"</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Probar permiso USB para futuros dispositivos"</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Permite que la aplicación pruebe un permiso para la tarjeta SD que estará disponible en futuros dispositivos."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"editar o borrar contenido de USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modificar o eliminar el contenido de la tarjeta SD"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Permite que la aplicación escriba en la tarjeta SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"modificar o eliminar el contenido del almacenamiento de medios interno"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Permite que la aplicación modifique el contenido del almacenamiento multimedia interno."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"acceder al almacenamiento externo de todos los usuarios"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Permite que la aplicación acceda al almacenamiento externo de todos los usuarios."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"acceder al sistema de archivos almacenado en caché"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite que la aplicación lea y escriba el sistema de archivos almacenado en caché."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"realizar/recibir llamadas por Internet"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Exige que se encripten los datos de la aplicación almacenados."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Inhabilitar cámaras"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Evitar el uso de las cámaras del dispositivo"</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Inhabilitar funciones en bloqueo"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Evita el uso de algunas funciones durante el bloqueo."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Móvil"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Vuelve a intentarlo"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Se ha superado el número máximo de intentos de desbloqueo facial."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Cargado"</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Cargado"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecta el cargador"</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Falta la tarjeta SIM"</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Falta la tarjeta SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No se ha insertado ninguna tarjeta SIM en el tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No se ha insertado ninguna tarjeta SIM en el teléfono."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Inserta una tarjeta SIM."</string>
@@ -736,7 +799,7 @@
     <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"Para desbloquear el teléfono, inicia sesión con tu cuenta de Google."</string>
     <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Nombre de usuario (correo electrónico)"</string>
     <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Contraseña"</string>
-    <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Acceder"</string>
+    <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Iniciar sesión"</string>
     <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Nombre de usuario o contraseña no válido"</string>
     <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"Si has olvidado tu nombre de usuario o tu contraseña,"\n"accede a la página "<b>"google.com/accounts/recovery"</b>"."</string>
     <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"Comprobando..."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Patrón borrado"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Se ha añadido una celda."</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Patrón completado"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Añadir widget"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Vacío"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Área de desbloqueo ampliada"</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Área de desbloqueo contraída"</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Widget de <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>"</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Selector de usuarios"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Estado"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Cámara"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Controles multimedia"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Se ha empezado a cambiar el orden de los widgets."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Se ha terminado de cambiar el orden de los widgets."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> eliminado"</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Ampliar área de desbloqueo"</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Desbloqueo deslizando el dedo"</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueo por patrón"</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Desbloqueo facial"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueo por PIN"</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueo por contraseña"</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área de patrón"</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área para deslizar"</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copiar URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Seleccionar texto"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selección de texto"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"añadir al diccionario"</string>
-    <string name="deleteText" msgid="7070985395199629156">"eliminar"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Añadir al diccionario"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Eliminar"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Método de entrada de texto"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acciones de texto"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Queda poco espacio"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Redes Wi-Fi abiertas disponibles"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Iniciar sesión en red Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Iniciar sesión en la red"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"No se ha podido establecer conexión con la red Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tiene una conexión inestable a Internet."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Para:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Escribe el PIN solicitado:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"El teléfono se desconectará temporalmente de la red Wi-Fi mientras está conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="select_character" msgid="3365550120617701745">"Insertar carácter"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Enviando mensajes SMS..."</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; está enviando un gran número de mensajes SMS. ¿Quieres permitir que está aplicación siga enviando mensajes?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Permitir"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Denegar"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; quiere enviar un mensaje a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457"><font fgcolor="#ffffb060">"Es posible que se apliquen cargos"</font>" en tu cuenta móvil."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Se aplicarán cargos en tu cuenta móvil."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Enviar"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Cancelar"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Recordar opción seleccionada"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Puedes cambiar esta opción más tarde en Ajustes &gt; Aplicaciones."</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Permitir siempre"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"No permitir nunca"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Tarjeta SIM eliminada"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"La red móvil no estará disponible hasta que reinicies el dispositivo con una tarjeta SIM válida."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Listo"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Establecer fecha"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Establecer"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Listo"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Predeterminado"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"No es necesario ningún permiso"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Ocultar"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostrar todos"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NUEVO:"</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NUEVO:"</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Proporcionado por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"No es necesario ningún permiso"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"es posible que se cobre por usar la aplicación."</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Almacenamiento USB masivo"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Conexión por USB"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Has conectado el dispositivo al ordenador por USB. Toca el siguiente botón si quieres transferir archivos entre el ordenador y el almacenamiento USB del dispositivo."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN activada por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca para administrar la red."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Toca para administrar la red."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Conectando VPN siempre activada…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN siempre activada conectada"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Error de VPN siempre activada"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Toca para restablecer la conexión."</string>
     <string name="upload_file" msgid="2897957172366730416">"Seleccionar archivo"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Archivo no seleccionado"</string>
     <string name="reset" msgid="2448168080964209908">"Restablecer"</string>
@@ -1154,7 +1250,7 @@
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Se ha habilitado el modo coche."</string>
     <string name="car_mode_disable_notification_message" msgid="8035230537563503262">"Toca para salir del modo coche."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"Anclaje a red/Zona Wi-Fi activo"</string>
-    <string name="tethered_notification_message" msgid="6857031760103062982">"Toca para configurar."</string>
+    <string name="tethered_notification_message" msgid="6857031760103062982">"Toca para configurar"</string>
     <string name="back_button_label" msgid="2300470004503343439">"Atrás"</string>
     <string name="next_button_label" msgid="1080555104677992408">"Siguiente"</string>
     <string name="skip_button_label" msgid="1275362299471631819">"Saltar"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Compartir"</string>
     <string name="find" msgid="4808270900322985960">"Buscar"</string>
     <string name="websearch" msgid="4337157977400211589">"Búsqueda web"</string>
+    <string name="find_next" msgid="5742124618942193978">"Buscar siguiente"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Buscar anterior"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Solicitud de ubicación de <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Solicitud de ubicación"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Solicitud enviada por <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1195,7 +1293,7 @@
     <string name="sync_really_delete" msgid="2572600103122596243">"Eliminar elementos"</string>
     <string name="sync_undo_deletes" msgid="2941317360600338602">"Deshacer las eliminaciones"</string>
     <string name="sync_do_nothing" msgid="3743764740430821845">"No hacer nada por ahora"</string>
-    <string name="choose_account_label" msgid="5655203089746423927">"Seleccionar una cuenta"</string>
+    <string name="choose_account_label" msgid="5655203089746423927">"Selecciona una cuenta"</string>
     <string name="add_account_label" msgid="2935267344849993553">"Añadir una cuenta"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Añadir cuenta"</string>
     <string name="number_picker_increment_button" msgid="2412072272832284313">"Aumentar"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Teléfono"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auriculares"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altavoces del conector"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Audio HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fin"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Salida multimedia"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Analizando..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Conectando..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Disponible"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"No disponible"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Pantalla integrada"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Pantalla HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Superposición #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Pantalla inalámbrica conectada"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Esta pantalla se muestra en otro dispositivo."</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Desconectar"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Llamada de emergencia"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"¿Has olvidado el patrón?"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"El patrón es incorrecto."</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Contraseña incorrecta"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN incorrecto"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Inténtalo de nuevo en <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Dibuja tu patrón de desbloqueo."</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Introduce el PIN de la tarjeta SIM."</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Introduce el PIN."</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Escribe tu contraseña."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"La tarjeta SIM está inhabilitada. Para continuar, introduce el código PUK. Si quieres obtener más información, ponte en contacto con el operador"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Introduce el código PIN deseado"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Confirma el código PIN"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Desbloqueando tarjeta SIM…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Código PIN incorrecto"</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Introduce un código PIN con una longitud comprendida entre cuatro y ocho dígitos."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"El código PUK debe tener ocho números como mínimo."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Vuelve a introducir el código PUK correcto. Si introduces un código incorrecto varias veces, se inhabilitará la tarjeta SIM."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Los códigos PIN no coinciden."</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Demasiados intentos incorrectos de crear el patrón"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Para desbloquear el teléfono, inicia sesión con tu cuenta de Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Nombre de usuario (correo electrónico)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Contraseña"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Iniciar sesión"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"El nombre de usuario o la contraseña no son válidos."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Si has olvidado tu nombre de usuario o tu contraseña,"\n"accede a la página "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Comprobando cuenta…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Has introducido un código PIN incorrecto <xliff:g id="NUMBER_0">%d</xliff:g> veces. "\n\n"Inténtalo de nuevo en <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Has introducido una contraseña incorrecta <xliff:g id="NUMBER_0">%d</xliff:g> veces. "\n\n"Inténtalo de nuevo en <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Has fallado <xliff:g id="NUMBER_0">%d</xliff:g> veces al dibujar tu patrón de desbloqueo. "\n\n"Inténtalo de nuevo en <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Has intentado desbloquear el tablet <xliff:g id="NUMBER_0">%d</xliff:g> veces, pero no lo has conseguido. Si fallas otras <xliff:g id="NUMBER_1">%d</xliff:g> veces, se restablecerán los datos de fábrica y se perderán todos los datos del usuario."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Has intentado desbloquear el teléfono <xliff:g id="NUMBER_0">%d</xliff:g> veces, pero no lo has conseguido. Si fallas otras <xliff:g id="NUMBER_1">%d</xliff:g> veces, se restablecerán los datos de fábrica y se perderán todos los datos del usuario."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Has intentado desbloquear el tablet <xliff:g id="NUMBER">%d</xliff:g> veces, pero no lo has conseguido. Se restablecerán los datos de fábrica del dispositivo."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Has intentado desbloquear el teléfono <xliff:g id="NUMBER">%d</xliff:g> veces, pero no lo has conseguido. Se restablecerán los datos de fábrica del dispositivo."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Has fallado <xliff:g id="NUMBER_0">%d</xliff:g> veces al dibujar el patrón de desbloqueo. Si fallas otras <xliff:g id="NUMBER_1">%d</xliff:g> veces, deberás usar una cuenta de correo electrónico para desbloquear el tablet."\n\n" Inténtalo de nuevo en <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Has fallado <xliff:g id="NUMBER_0">%d</xliff:g> veces al dibujar el patrón de desbloqueo. Si fallas otras <xliff:g id="NUMBER_1">%d</xliff:g> veces, deberás usar una cuenta de correo electrónico para desbloquear el teléfono."\n\n" Inténtalo de nuevo en <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Eliminar"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"¿Subir el volumen por encima del nivel de seguridad?"\n"Escuchar sonidos a alto volumen durante largos períodos de tiempo puede dañar tus oídos."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Mantén la pantalla pulsada con dos dedos para habilitar las funciones de accesibilidad."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Accesibilidad habilitada"</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Accesibilidad cancelada"</string>
+    <string name="user_switched" msgid="3768006783166984410">"Usuario actual: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="owner_name" msgid="2716755460376028154">"Propietario"</string>
 </resources>
diff --git a/core/res/res/values-et/donottranslate-cldr.xml b/core/res/res/values-et/donottranslate-cldr.xml
index d50d041..bf269dd 100644
--- a/core/res/res/values-et/donottranslate-cldr.xml
+++ b/core/res/res/values-et/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">jaanuar</string>
-    <string name="month_long_standalone_february">veebruar</string>
-    <string name="month_long_standalone_march">märts</string>
-    <string name="month_long_standalone_april">aprill</string>
-    <string name="month_long_standalone_may">mai</string>
-    <string name="month_long_standalone_june">juuni</string>
-    <string name="month_long_standalone_july">juuli</string>
-    <string name="month_long_standalone_august">august</string>
-    <string name="month_long_standalone_september">september</string>
-    <string name="month_long_standalone_october">oktoober</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">detsember</string>
-
-    <string name="month_long_january">jaanuar</string>
-    <string name="month_long_february">veebruar</string>
-    <string name="month_long_march">märts</string>
-    <string name="month_long_april">aprill</string>
-    <string name="month_long_may">mai</string>
-    <string name="month_long_june">juuni</string>
-    <string name="month_long_july">juuli</string>
-    <string name="month_long_august">august</string>
-    <string name="month_long_september">september</string>
-    <string name="month_long_october">oktoober</string>
-    <string name="month_long_november">november</string>
-    <string name="month_long_december">detsember</string>
-
-    <string name="month_medium_january">jaan</string>
-    <string name="month_medium_february">veebr</string>
-    <string name="month_medium_march">märts</string>
-    <string name="month_medium_april">apr</string>
-    <string name="month_medium_may">mai</string>
-    <string name="month_medium_june">juuni</string>
-    <string name="month_medium_july">juuli</string>
-    <string name="month_medium_august">aug</string>
-    <string name="month_medium_september">sept</string>
-    <string name="month_medium_october">okt</string>
-    <string name="month_medium_november">nov</string>
-    <string name="month_medium_december">dets</string>
-
-    <string name="month_shortest_january">1</string>
-    <string name="month_shortest_february">2</string>
-    <string name="month_shortest_march">3</string>
-    <string name="month_shortest_april">4</string>
-    <string name="month_shortest_may">5</string>
-    <string name="month_shortest_june">6</string>
-    <string name="month_shortest_july">7</string>
-    <string name="month_shortest_august">8</string>
-    <string name="month_shortest_september">9</string>
-    <string name="month_shortest_october">10</string>
-    <string name="month_shortest_november">11</string>
-    <string name="month_shortest_december">12</string>
-
-    <string name="day_of_week_long_sunday">pühapäev</string>
-    <string name="day_of_week_long_monday">esmaspäev</string>
-    <string name="day_of_week_long_tuesday">teisipäev</string>
-    <string name="day_of_week_long_wednesday">kolmapäev</string>
-    <string name="day_of_week_long_thursday">neljapäev</string>
-    <string name="day_of_week_long_friday">reede</string>
-    <string name="day_of_week_long_saturday">laupäev</string>
-
-    <string name="day_of_week_medium_sunday">P</string>
-    <string name="day_of_week_medium_monday">E</string>
-    <string name="day_of_week_medium_tuesday">T</string>
-    <string name="day_of_week_medium_wednesday">K</string>
-    <string name="day_of_week_medium_thursday">N</string>
-    <string name="day_of_week_medium_friday">R</string>
-    <string name="day_of_week_medium_saturday">L</string>
-
-    <string name="day_of_week_short_sunday">P</string>
-    <string name="day_of_week_short_monday">E</string>
-    <string name="day_of_week_short_tuesday">T</string>
-    <string name="day_of_week_short_wednesday">K</string>
-    <string name="day_of_week_short_thursday">N</string>
-    <string name="day_of_week_short_friday">R</string>
-    <string name="day_of_week_short_saturday">L</string>
-
-    <string name="day_of_week_shortest_sunday">1</string>
-    <string name="day_of_week_shortest_monday">2</string>
-    <string name="day_of_week_shortest_tuesday">3</string>
-    <string name="day_of_week_shortest_wednesday">4</string>
-    <string name="day_of_week_shortest_thursday">5</string>
-    <string name="day_of_week_shortest_friday">6</string>
-    <string name="day_of_week_shortest_saturday">7</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index c887a41..5fb21d4 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefonivalikud"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Ekraanilukk"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Lülita välja"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Veaaruanne"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Veaaruande võtmine"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Nii kogutakse teavet teie seadme praeguse oleku kohta, et saata see meilisõnumina. Enne kui saate veaaruande ära saata, võtab selle loomine natuke aega; varuge kannatust."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Hääletu režiim"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Heli on VÄLJAS"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Heli on SEES"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Teie sõnumid"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Teie SMS-, meili- ja muude sõnumite lugemine ja kirjutamine."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Teie isiklikud andmed"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Otsene juurdepääs tahvelarvutisse salvestatud kontaktidele ja kalendrile."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Otsene juurdepääs telefoni salvestatud kontaktidele ja kalendrile."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Otsene juurdepääs teie kohta käivale teabele, mis on salvestatud teie kontaktikaardile."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Teie sotsiaalne teave"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Otsene juurdepääs teie kontaktide teabele ja sotsiaalsetele sidemetele."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Teie asukoht"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Jälgige oma füüsilist asukohta."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Võrgusuhtlus"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Juurdepääs erinevatele võrgufunktsioonidele."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Juurdepääs seadmetele ja võrkudele Bluetoothi kaudu."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Heliseaded"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Heliseadete muutmine."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Aku mõjutamine"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Funktsioonide, mis võivad aku kiiresti tühjendada, kasutamine."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalender"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Otsene juurdepääs kalendrile ja sündmustele."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Kasutaja sõnaraamatu lugemine"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Kasutaja sõnaraamatu sõnade lugemine."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Kasutaja sõnaraamatusse kirjutamine"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Kasutaja sõnaraamatusse sõnade lisamine."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Järjehoidjad ja ajalugu"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Otsene juurdepääs järjehoidjatele ja brauseri ajaloole."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarm"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Äratuskella seadmine."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Kõnepost"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Otsene juurdepääs kõnepostile."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Otsene juurdepääs mikrofonile heli salvestamiseks."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Kaamera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Otsene juurdepääs kaamerale fotode või videote jäädvustamiseks."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Teie rakenduste teave"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Võime mõjutada teiste seadmes olevate rakenduste käitumist."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Taustapilt"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Seadme taustapildi seadete muutmine."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Kell"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Seadme aja või ajavööndi muutmine."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Olekuriba"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Seadme olekuriba seadete muutmine."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Sünkroonimisseaded"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Juurdepääs sünkroonimisseadetele."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Teie kontod"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Juurdepääs saadaolevatele kontodele."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Riistvara juhtelemendid"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Süsteemi madalama taseme juurdepääs ja juhtimine."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Arendustööriistad"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funktsioonid on vajalikud ainult rakenduste arendajatele."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Muu rakenduse kasutajaliides"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Teiste rakenduste kasutajaliidese mõjutamine."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Mäluruum"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Juurdepääs USB-mäluseadmele."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Juurdepääs SD-kaardile."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Võimaldab rakendusel vastu võtta ja töödelda WAP-sõnumeid. See luba hõlmab võimet jälgida või kustutada teile saadetud sõnumeid neid teile näitamata."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"Käitatud rakenduste toomine"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Võimaldab rakendusel tuua teavet praegu ja hiljuti käitatud ülesannete kohta. See võib lubada rakendusel avastada teavet selle kohta, milliseid rakendusi seadmes kasutatakse."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"toimingud erinevatel kasutajakontodel"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Lubab rakendusel teha toiminguid seadme erinevatel kasutajakontodel. Pahatahtlikud rakendused võivad kasutada seda kasutajatevahelise kaitse rikkumiseks."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"täielik litsents teha toiminguid erinevatel kasutajakontodel"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Lubab kõiki võimalikke toiminguid erinevatel kasutajakontodel."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"kasutajate haldamine"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Võimaldab rakendustel hallata seadme kasutajaid, sealhulgas päringuid, loomist ja kustutamist."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"töötavate rakenduste üksikasjade toomine"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Võimaldab rakendusel tuua üksikasjalikku teavet praegu töötavate ja hiljuti käitatud ülesannete kohta. Pahatahtlikud rakendused võivad tuvastada privaatset teavet muude rakenduste kohta."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"käitatud rakenduste ümberjärjestamine"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Võimaldab rakendusel teada saada süsteemi sisemist olekut. Pahatahtlikud rakendused võivad hankida mitmesugust privaatset ja turvateavet, mida neil tavaliselt kunagi vaja ei lähe."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"ekraanisisu taastamine"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Võimaldab rakendusel kätte saada aktiivse akna sisu. Pahatahtlikud rakendused võivad hankida kogu akna sisu ja uurida kogu selle teksti, välja arvatud paroole."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ajutine hõlbustuse lubamine"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Lubab rakendusel ajutiselt lubada seadmes hõlbustuse. Pahatahtlikud rakendused võivad lubada hõlbustuse kasutaja nõusolekuta."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"hangi akna teave"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Võimaldab rakendusel hankida teavet aknahalduri akende kohta. Pahatahtlikud rakendused võivad hankida teavet, mis on mõeldud süsteemisiseseks kasutamiseks."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtreeri sündmused"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Võimaldab rakendusel registreerida sisestusfiltri, mis filtreerib kõigi kasutaja sündmuste voo, enne kui need ära saadetakse. Pahatahtlik rakendus võib süsteemi kasutajaliidest juhtida ilma kasutaja sekkumiseta."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"kuva suurendamine"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Lubab rakendusel ekraani sisu suurendada. Pahatahtlikud rakendused võivad muundada kuva sisu nii, et seade muutub ebastabiilseks."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"osaline väljalülitamine"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Lülitab tegevushalduri väljalülitusolekusse. Ei lülita lõplikult välja."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"väldi rakenduste ümberlülitamist"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Võimaldab rakendusel juhtida töötavate protsesside maksimaalset arvu. Tavarakenduste puhul pole seda vaja."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"sundige taustarakendused sulguma"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Võimaldab rakendusel määrata, kas tegevused lõpetatakse kohe, kui need liiguvad taustale. Tavarakenduste puhul pole seda vaja."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"muuda akustatistikat"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Võimaldab rakendusel muuta kogutud akustatistikat. Mitte kasutada tavarakenduste puhul."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"aku statistika lugemine"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Lubab rakendusel lugeda madala akutaseme kasutusandmeid. Võib lubada rakendusel hankida üksikasjalikku teavet selle kohta, mis rakendusi te kasutate."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"aku statistika muutmine"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Võimaldab rakendusel muuta aku kohta kogutud statistikat. Mitte kasutada tavarakenduste puhul."</string>
     <string name="permlab_backup" msgid="470013022865453920">"juhi süsteemi varundust ja taastet"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Võimaldab rakendusel juhtida süsteemi varundus- ja taastemehhanismi. Mitte kasutada tavarakenduste puhul."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"täieliku varukoopia kinnitamine või toimingu taastamine"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"kuva volituseta aknad"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Võimaldab rakendusel luua aknaid, mis on mõeldud kasutamiseks süsteemisisesele kasutajaliidesele. Mitte kasutada tavarakenduste puhul."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"tõmmake üle teiste rakenduste"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Võimaldab rakendusel kuvada süsteemihoiatuste aknaid. Mõned hoiatusaknad võivad hõlmata kogu ekraani."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Lubab rakendusel joonistada teistele rakendustele või nende kasutajaliidestele. See võib segada ükskõik millise rakenduse liidese kasutamist või muuta seda, mida arvate nägevat."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"muuda üldist animatsioonikiirust"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Võimaldab rakendusel muuta animatsiooni üldist kiirust (animatsioone kiirendada või aeglustada) ükskõik millal."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"Rakenduse lubade haldamine"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Võimaldab rakendusel luua ja hallata tema enda lube, möödudes tavapärasest Z-järjekorrast. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"ekraanikuva peatamine"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Lubab rakendusel ajutiselt peatada ekraani kuva täisekraanile üleminekuks."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"vajuta klahve ja juhtnuppe"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Võimaldab rakendusel saata oma sisendtoiminguid (klahvivajutusi jms) teistele rakendustele. Pahatahtlikud rakendused võivad seda kasutada tahvelarvuti ülevõtmiseks."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Võimaldab rakendusel saata oma sisendtoiminguid (klahvivajutusi jms) teistele rakendustele. Pahatahtlikud rakendused võivad seda kasutada telefoni ülevõtmiseks."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"Rakenduste otse installimine"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Võimaldab rakendusel installida uusi või värskendatud Android-pakette. Pahatahtlikud rakendused võivad selle abil lisada uusi meelevaldse tegevuse lubadega rakendusi."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"Kõigi rakenduse vahemäluandmete kustutamine"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Võimaldab rakendusel vabastada tahvelarvuti mälu, kustutades faile otse rakenduse kataloogist. Süsteem on juurdepääsu sellele harilikult väga piiranud."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Võimaldab rakendusel vabastada telefoni mälu, kustutades faile otse rakenduse kataloogist. Süsteem on juurdepääsu sellele harilikult väga piiranud."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Lubab rakendusel vabastada tahvelarvuti mäluruumi, kustutades faile teiste rakenduste vahemälu kataloogides. Selle tagajärjel võivad teised rakendused käivituda aeglasemalt, sest need peavad oma andmed uuesti tooma."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Lubab rakendusel vabastada telefoni mäluruumi, kustutades faile teiste rakenduste vahemälu kataloogides. Selle tagajärjel võivad teised rakendused käivituda aeglasemalt, sest need peavad oma andmed uuesti tooma."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"Rakenduse ressursside teisaldamine"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Võimaldab rakendusel teisalda rakenduseressursid sisemiselt kandjalt välisele ja vastupidi."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"tundlike logiandmete lugemine"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Võimaldab rakendusel pääseda juurde asukohapakkuja erikäskudele. See võib lubada rakendusel segada GPS-i või muude asukohaallikate tööd."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"luba asukohapakkuja installimiseks"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Looge võltsasukoha allikaid, et katsetada või installida uut asukohapakkujat. See lubab rakendusel tühistada teiste asukohaallikate, näiteks GPS-i või asukohapakkujate tagastatud asukoha ja/või oleku."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"täpne (GPS-) asukoht"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Tahvelarvuti kaudu saate juurdepääsu täpsetele asukoha allikatele, näiteks ülemaailmsele kohamääramise süsteemile. Kui need asukohateenused on saadaval ja sisse lülitatud, saab rakendus loa teie ligilähedase asukoha määramiseks."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Telefoni kaudu saate juurdepääsu täpsetele asukoha allikatele, näiteks ülemaailmsele kohamääramise süsteemile. Kui need asukohateenused on saadaval ja sisse lülitatud, saab rakendus loa teie ligilähedase asukoha määramiseks."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"ligikaudne (võrgupõhine) asukoht"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Juurdepääs ligilähedasele asukohale asukohapakkujatelt, kes kasutavad selliseid võrguallikaid nagu mobiilside ja WiFi. Kui need asukohateenused on saadaval ja sisse lülitatud, saab rakendus loa teie ligilähedase asukoha määramiseks."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"täpne asukoht (GPS- ja võrgupõhine)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Lubab rakendusel hankida teie täpse asukoha globaalse positsioneerimissüsteemi (GPS) või võrgu asukohaallikate (nt mobiilimastide ja WiFi) järgi. Need asukohateenused peavad olema sisse lülitatud ja teie seadme jaoks saadaval, et rakendus saaks neid kasutada. Rakendused võivad kasutada seda teie asukoha tuvastamiseks ja tarbida akut."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"ligikaudne asukoht (võrgupõhine)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Lubab rakendusel hankida juurdepääsu ligikaudsele asukohale. Asukoht tuletatakse asukohateenuste järgi, kasutades võrgu asukohaallikaid, nt mobiilimastid ja WiFi. Need asukohateenused peavad olema sisse lülitatud ja teie seadme jaoks saadaval, et rakendus saaks neid kasutada. Rakendused võivad kasutada seda teie ligikaudse asukoha tuvastamiseks."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"juurdepääs SurfaceFlingerile"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Võimaldab rakendusel kasutada SurfaceFlingeri madalatasemelisi funktsioone."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"loe kaadripuhvrit"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Võimaldab rakendusel kaadripuhvri sisu lugeda."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"WiFi-ekraanide seadistamine"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Lubab rakendusel seadistada WiFi-ekraane ja nendega ühendus luua."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"WiFi-ekraanide juhtimine"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Lubab rakendusel juhtida WiFi-ekraanide madala taseme funktsioone."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"muuda heliseadeid"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Võimaldab rakendusel muuta üldiseid heliseadeid, näiteks helitugevust ja seda, millist kõlarit kasutatakse väljundiks."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"salvesta heli"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"juurdepääs Bluetoothi ​​seadetele"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Võimaldab rakendusel seadistada kohalikku Bluetooth-tahvelarvutit ning leida ja siduda seda kaugseadmetega."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Võimaldab rakendusel seadistada kohalikku Bluetooth-telefoni ning leida ja siduda seda kaugseadmetega."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Vaadake WiMAX-i ühendusi"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX-iga ühenduse loomine ja ühenduse katkestamine"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Võimaldab rakendusel määrata, kas WiMAX on lubatud, ja vaadata teavet kõikide ühendatud WiMAX-võrkude kohta."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX-i oleku muutmine"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Võimaldab rakendusel luua ja katkestada tahvelarvuti ühenduse WiMAX-i võrkudega."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Võimaldab rakendusel muuta teie praegu sünkroonitud vooge. Pahatahtlikud rakendused võivad muuta teie sünkroonitud vooge."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"lugege termineid, mis te sõnastikku lisasite"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Võimaldab rakendusel lugeda kõiki sõnu, nimesid ja fraase, mille kasutaja on kasutaja sõnaraamatusse salvestanud."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"Kasutaja määratud sõnastikku kirjutamine"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"sõnade lisamine kasutaja määratletud sõnastikku"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Võimaldab rakendusel kirjutada kasutajasõnastikku uusi sõnu."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"kaitstud salvestusruumi juurdepääsu katsetamine"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"kaitstud salvestusruumi juurdepääsu katsetamine"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Võimaldab rakendusel katsetada USB-salvestusruumi luba, mis on saadaval tulevastel seadmetel."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Võimaldab rakendusel testida luba USB-salvestuseks, mis on saadaval tulevastes seadmetes."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Võimaldab rakendusel katsetada SD-kaardi luba, mis on saadaval tulevastel seadmetel."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"muutke, kustut. USB-ruumi sisu"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"SD-kaardi sisu muutmine või kustutamine"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Võimaldab rakendusel kirjutada SD-kaardile."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"sisemälu sisu muutm./kustut."</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Võimaldab rakendusel muuta sisemise andmekandja sisu."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"juurdepääs välismäluseadmele (kõikidele kasutajatele)"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Võimaldab rakenduse kõikidel kasutajatel pöörduda välismäluseadme poole."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"juurdepääs vahemälu failisüsteemile"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Võimaldab rakendusel vahemälu failisüsteemi lugeda ja kirjutada."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"Interneti-kõnede tegemine/vastuvõtmine"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Nõua salvestatud rakenduse andmete krüpteerimist."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Keela kaamerad"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Vältige seadme kõigi kaamerate kasutamist."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Klahviluku funkts. keelamine"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Takistage klahviluku mõne funktsiooni kasutamist."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Kodu"</item>
     <item msgid="869923650527136615">"Mobiil"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Proovige uuesti"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Maksimaalne teenusega Face Unlock avamise katsete arv on ületatud"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Laadimine, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Laetud."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Laetud"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Ühendage laadija."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"SIM-kaarti pole."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM-kaarti pole"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tahvelarvutis pole SIM-kaarti."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefonis pole SIM-kaarti."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Sisestage SIM-kaart."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Muster on kustutatud"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Lahter on lisatud"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Muster on valmis"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Vidina lisamine."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Tühi"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Avamisala on laiendatud."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Avamisala on ahendatud."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Vidin <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Kasutaja valija"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Olek"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Kaamera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Meedia juhtnupud"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Vidina ümberkorraldamine algas."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Vidina ümberkorraldamine lõppes."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Vidin <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> on kustutatud."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Avamisala laiendamine."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Lohistamisega avamine."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Mustriga avamine."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Näoga avamine."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-koodiga avamine."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Parooliga avamine."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mustri ala."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Lohistamisala."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopeeri URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Valige tekst"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Teksti valimine"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"lisa sõnastikku"</string>
-    <string name="deleteText" msgid="7070985395199629156">"kustuta"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Lisa sõnastikku"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Kustuta"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Sisestusmeetod"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tekstitoimingud"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Talletusruum saab täis"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Avatud WiFi-võrgud on saadaval"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Logige sisse WiFi-võrku"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Logige võrku"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ei saanud WiFi-ga ühendust"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" on halb Interneti-ühendus."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Saaja:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Sisestage nõutav PIN-kood:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-kood:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefoni ühendus WiFi-ga katkestatakse ajutiselt, kui see on ühendatud seadmega <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Sisesta tähemärk"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS-sõnumite saatmine"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; saadab suurel hulgal SMS-sõnumeid. Kas tahate lubada sellel rakendusel ka edaspidi sõnumeid saata?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Luba"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Keela"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; soovib saata sõnumi aadressile &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"See "<font fgcolor="#ffffb060">"võib põhjustada kulusid"</font>" teie mobiilikontole."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"See lisab kulusid teie mobiilikontole."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Saada"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Tühista"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Jäta minu valik meelde"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Saate muuta jaotises Seaded &gt; Rakendused"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Luba alati"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Ära luba"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kaart eemaldatud"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobiilsidevõrk ei ole saadaval, kuni sisestate kehtiva SIM-kaardi ja taaskäivitate seadme."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Valmis"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Kuupäeva määramine"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Määra"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Valmis"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Vaikimisi"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Lube pole vaja"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Peida"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Näita kõiki"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"UUS: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"UUS: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Teenusepakkuja: <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Lube pole vaja"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"see võib olla tasuline"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB-massmälu"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB ühendatud"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Teil on arvutiga ühendus USB kaudu. Puudutage allolevat nuppu, kui soovite faile arvuti ja Androidi USB-salvestusruumi vahel kopeerida."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN-i aktiveeris <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Võrgu haldamiseks puudutage."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Ühendatud seansiga <xliff:g id="SESSION">%s</xliff:g>. Võrgu haldamiseks puudutage."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Ühendamine alati sees VPN-iga …"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Ühendatud alati sees VPN-iga"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Alati sees VPN-i viga"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Ühenduse lähtestamiseks puudutage"</string>
     <string name="upload_file" msgid="2897957172366730416">"Valige fail"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Ühtegi faili pole valitud"</string>
     <string name="reset" msgid="2448168080964209908">"Lähtesta"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Jaga"</string>
     <string name="find" msgid="4808270900322985960">"Otsi"</string>
     <string name="websearch" msgid="4337157977400211589">"Veebiotsing"</string>
+    <string name="find_next" msgid="5742124618942193978">"Leia järgmine"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Leia eelmine"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Asukohapäring kasutajalt <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Asukohapäring"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Taotleja: <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Kõrvaklapid"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Doki kõlarid"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI heli"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Süsteem"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-heli"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Valmis"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Meediaväljund"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Skaneering ..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Ühendan..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Saadaval"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Ei ole saadaval"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Sisseehitatud ekraan"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-ekraan"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Ülekate nr .<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Juhtmeta ekraaniühendus on loodud"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Ekraan on näha teises seadmes"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Katkesta ühendus"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Hädaabikõne"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Unustasin mustri"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Vale muster"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Vale parool"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Vale PIN-kood"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Proovige uuesti <xliff:g id="NUMBER">%d</xliff:g> sekundi pärast."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Joonistage oma muster"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Sisestage SIM-i PIN-kood"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Sisestage PIN-kood"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Sisestage parool"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM on nüüd keelatud. Jätkamiseks sisestage PUK-kood. Üksikasju küsige operaatorilt."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Sisestage soovitud PIN-kood"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Kinnitage soovitud PIN-kood"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM-kaardi avamine ..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Vale PIN-kood."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Sisestage 4–8-numbriline PIN-kood."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK-koodi pikkus peab olema vähemalt 8 numbrit."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Sisestage uuesti õige PUK-kood. Korduvkatsete korral keelatakse SIM jäädavalt."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN-koodid ei ole vastavuses"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Liiga palju mustrikatseid"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Avamiseks logige sisse oma Google\'i kontoga."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Kasutajanimi (e-post)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Parool"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Logi sisse"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Vale kasutajanimi või parool."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Kas unustasite kasutajanime või parooli?"\n"Külastage aadressi "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Konto kontrollimine ..."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Olete PIN-koodi <xliff:g id="NUMBER_0">%d</xliff:g> korda valesti sisestanud."\n\n"Proovige <xliff:g id="NUMBER_1">%d</xliff:g> sekundi pärast uuesti."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Olete parooli <xliff:g id="NUMBER_0">%d</xliff:g> korda valesti sisestanud. "\n\n"Proovige uuesti <xliff:g id="NUMBER_1">%d</xliff:g> sekundi pärast."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Joonistasite oma avamismustri <xliff:g id="NUMBER_0">%d</xliff:g> korda valesti."\n\n"Proovige <xliff:g id="NUMBER_1">%d</xliff:g> sekundi pärast uuesti."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Olete üritanud <xliff:g id="NUMBER_0">%d</xliff:g> korda tahvelarvutit valesti avada. Pärast veel <xliff:g id="NUMBER_1">%d</xliff:g> ebaõnnestunud katset lähtestatakse tahvelarvuti tehase vaikeseadetele ja kõik kasutajaandmed lähevad kaotsi."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Olete üritanud <xliff:g id="NUMBER_0">%d</xliff:g> korda telefoni valesti avada. Pärast veel <xliff:g id="NUMBER_1">%d</xliff:g> ebaõnnestunud katset lähtestatakse telefon tehase vaikeseadetele ja kõik kasutajaandmed lähevad kaotsi."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Olete püüdnud tahvelarvutit <xliff:g id="NUMBER">%d</xliff:g> korda valesti avada. Tahvelarvuti lähtestatakse nüüd tehase vaikeseadetele."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Olete püüdnud telefoni <xliff:g id="NUMBER">%d</xliff:g> korda valesti avada. Telefon lähtestatakse nüüd tehase vaikeseadetele."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Joonistasite oma avamismustri <xliff:g id="NUMBER_0">%d</xliff:g> korda valesti. Pärast veel <xliff:g id="NUMBER_1">%d</xliff:g> ebaõnnestunud katset palutakse teil tahvelarvuti avada meilikontoga."\n\n" Proovige uuesti <xliff:g id="NUMBER_2">%d</xliff:g> sekundi pärast."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Joonistasite oma avamismustri <xliff:g id="NUMBER_0">%d</xliff:g> korda valesti. Pärast veel <xliff:g id="NUMBER_1">%d</xliff:g> ebaõnnestunud katset palutakse teil telefon avada meilikontoga."\n\n" Proovige uuesti <xliff:g id="NUMBER_2">%d</xliff:g> sekundi pärast."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Eemalda"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Kas suurendada helitugevust üle ohutu piiri?"\n"Pikaajaline suure helitugevusega muusika kuulamine võib kahjustada kuulmist."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Hõlbustuse lubamiseks hoidke kaht sõrme all."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Hõlbustus on lubatud."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Hõlbustus on tühistatud."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Praegune kasutaja <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Omanik"</string>
 </resources>
diff --git a/core/res/res/values-fa/donottranslate-cldr.xml b/core/res/res/values-fa/donottranslate-cldr.xml
index 11473fe..402311a 100644
--- a/core/res/res/values-fa/donottranslate-cldr.xml
+++ b/core/res/res/values-fa/donottranslate-cldr.xml
@@ -1,82 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">ژانویه</string>
-    <string name="month_long_standalone_february">فوریه</string>
-    <string name="month_long_standalone_march">مارس</string>
-    <string name="month_long_standalone_april">آوریل</string>
-    <string name="month_long_standalone_may">مه</string>
-    <string name="month_long_standalone_june">ژوئن</string>
-    <string name="month_long_standalone_july">ژوئیه</string>
-    <string name="month_long_standalone_august">اوت</string>
-    <string name="month_long_standalone_september">سپتامبر</string>
-    <string name="month_long_standalone_october">اکتبر</string>
-    <string name="month_long_standalone_november">نوامبر</string>
-    <string name="month_long_standalone_december">دسامبر</string>
-
-    <string name="month_long_january">ژانویهٔ</string>
-    <string name="month_long_february">فوریهٔ</string>
-    <string name="month_long_march">مارس</string>
-    <string name="month_long_april">آوریل</string>
-    <string name="month_long_may">مهٔ</string>
-    <string name="month_long_june">ژوئن</string>
-    <string name="month_long_july">ژوئیهٔ</string>
-    <string name="month_long_august">اوت</string>
-    <string name="month_long_september">سپتامبر</string>
-    <string name="month_long_october">اکتبر</string>
-    <string name="month_long_november">نوامبر</string>
-    <string name="month_long_december">دسامبر</string>
-
-    <string name="month_medium_january">ژانویهٔ</string>
-    <string name="month_medium_february">فوریهٔ</string>
-    <string name="month_medium_march">مارس</string>
-    <string name="month_medium_april">آوریل</string>
-    <string name="month_medium_may">مهٔ</string>
-    <string name="month_medium_june">ژوئن</string>
-    <string name="month_medium_july">ژوئیهٔ</string>
-    <string name="month_medium_august">اوت</string>
-    <string name="month_medium_september">سپتامبر</string>
-    <string name="month_medium_october">اکتبر</string>
-    <string name="month_medium_november">نوامبر</string>
-    <string name="month_medium_december">دسامبر</string>
-
-    <string name="month_shortest_january">ژ</string>
-    <string name="month_shortest_february">ف</string>
-    <string name="month_shortest_march">م</string>
-    <string name="month_shortest_april">آ</string>
-    <string name="month_shortest_may">م</string>
-    <string name="month_shortest_june">ژ</string>
-    <string name="month_shortest_july">ژ</string>
-    <string name="month_shortest_august">ا</string>
-    <string name="month_shortest_september">س</string>
-    <string name="month_shortest_october">ا</string>
-    <string name="month_shortest_november">ن</string>
-    <string name="month_shortest_december">د</string>
-
-    <string name="day_of_week_long_sunday">یکشنبه</string>
-    <string name="day_of_week_long_monday">دوشنبه</string>
-    <string name="day_of_week_long_tuesday">سه‌شنبه</string>
-    <string name="day_of_week_long_wednesday">چهارشنبه</string>
-    <string name="day_of_week_long_thursday">پنجشنبه</string>
-    <string name="day_of_week_long_friday">جمعه</string>
-    <string name="day_of_week_long_saturday">شنبه</string>
-
-
-
-    <string name="day_of_week_shortest_sunday">ی</string>
-    <string name="day_of_week_shortest_monday">د</string>
-    <string name="day_of_week_shortest_tuesday">س</string>
-    <string name="day_of_week_shortest_wednesday">چ</string>
-    <string name="day_of_week_shortest_thursday">پ</string>
-    <string name="day_of_week_shortest_friday">ج</string>
-    <string name="day_of_week_shortest_saturday">ش</string>
-
-    <string name="am">قبل از ظهر</string>
-    <string name="pm">بعد از ظهر</string>
-    <string name="yesterday">دیروز</string>
-    <string name="today">امروز</string>
-    <string name="tomorrow">فردا</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
@@ -113,22 +37,22 @@
     <string name="time_wday_date">%1$s،‏ %2$s %3$s</string>
     <string name="wday_date">%2$s %3$s</string>
     <string name="time_wday">%1$s،‏ %2$s</string>
-    <string name="same_year_md1_md2">%3$s LLLL تا %8$s LLLL</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s LLLL تا %6$s %8$s LLLL</string>
-    <string name="same_year_md1_time1_md2_time2">%5$s،‏ %3$s LLLL تا %10$s،‏ %8$s LLLL</string>
-    <string name="same_month_md1_time1_md2_time2">%5$s،‏ %3$s LLLL تا %10$s،‏ %8$s LLLL</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s،‏ %1$s %3$s LLLL تا %10$s،‏ %6$s %8$s LLLL</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s،‏ %1$s %3$s LLLL تا %10$s،‏ %6$s %8$s LLLL</string>
+    <string name="same_year_md1_md2">%3$s %11$s تا %8$s %12$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %11$s تا %6$s %8$s %12$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s،‏ %3$s %11$s تا %10$s،‏ %8$s %12$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s،‏ %3$s %11$s تا %10$s،‏ %8$s %12$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s،‏ %1$s %3$s %11$s تا %10$s،‏ %6$s %8$s %12$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s،‏ %1$s %3$s %11$s تا %10$s،‏ %6$s %8$s %12$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%5$s،‏ %3$s %2$s %4$s تا %10$s،‏ %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%5$s،‏ %3$s %2$s %4$s تا %10$s،‏ %8$s %7$s %9$s</string>
     <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s،‏ %1$s %3$s %2$s %4$s تا %10$s،‏ %6$s %8$s %7$s %9$s</string>
     <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s،‏ %1$s %3$s %2$s %4$s تا %10$s،‏ %6$s %8$s %7$s %9$s</string>
     <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s تا %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_md1_md2">%3$s تا %8$s LLL</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s LLLL تا %6$s %8$s LLLL</string>
-    <string name="same_year_mdy1_mdy2">%3$s LLL تا %8$s %2$s %9$s</string>
+    <string name="same_month_md1_md2">%3$s تا %8$s %11$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %11$s تا %6$s %8$s %12$s</string>
+    <string name="same_year_mdy1_mdy2">%3$s %11$s تا %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s تا %8$s %2$s %9$s</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s LLL تا %6$s %8$s %2$s %9$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %11$s تا %6$s %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
     <string name="full_wday_month_day_no_year">E d LLLL</string>
     <string name="abbrev_wday_month_day_no_year">E d LLLL</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index f52ab95..50d62b9 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"گیگابایت"</string>
     <string name="terabyteShort" msgid="231613018159186962">"ترابایت"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"پتابایت"</string>
-    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;بدون عنوان&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -44,7 +44,7 @@
     <string name="passwordIncorrect" msgid="7612208839450128715">"رمز ورود اشتباه است."</string>
     <string name="mmiComplete" msgid="8232527495411698359">"MMI کامل شد."</string>
     <string name="badPin" msgid="9015277645546710014">"پین قدیمی که نوشته‎اید صحیح نیست."</string>
-    <string name="badPuk" msgid="5487257647081132201">"PUK که نوشته اید صحیح نیست."</string>
+    <string name="badPuk" msgid="5487257647081132201">"PUK که نوشته‌اید صحیح نیست."</string>
     <string name="mismatchPin" msgid="609379054496863419">"پین‎هایی که وارد کرده‎اید با یکدیگر مطابقت ندارند."</string>
     <string name="invalidPin" msgid="3850018445187475377">"یک پین بنویسید که 4 تا 8 رقم باشد."</string>
     <string name="invalidPuk" msgid="8761456210898036513">"یک PUK با 8 رقم یا بیشتر تایپ کنید."</string>
@@ -85,7 +85,7 @@
     <string name="serviceClassFAX" msgid="5566624998840486475">"نمابر"</string>
     <string name="serviceClassSMS" msgid="2015460373701527489">"پیامک"</string>
     <string name="serviceClassDataAsync" msgid="4523454783498551468">"غیر همگام"</string>
-    <string name="serviceClassDataSync" msgid="7530000519646054776">"همگام سازی"</string>
+    <string name="serviceClassDataSync" msgid="7530000519646054776">"همگام‌سازی"</string>
     <string name="serviceClassPacket" msgid="6991006557993423453">"بسته"</string>
     <string name="serviceClassPAD" msgid="3235259085648271037">"PAD"</string>
     <string name="roamingText0" msgid="7170335472198694945">"نشانگر رومینگ روشن"</string>
@@ -126,13 +126,13 @@
     <string name="httpErrorFileNotFound" msgid="6203856612042655084">"فایل درخواستی پیدا نشد."</string>
     <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"درخواست‌های زیادی در حال پردازش است. بعداً دوباره امتحان کنید."</string>
     <string name="notification_title" msgid="8967710025036163822">"خطای ورود به سیستم برای <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
-    <string name="contentServiceSync" msgid="8353523060269335667">"همگام سازی"</string>
-    <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"همگام سازی"</string>
+    <string name="contentServiceSync" msgid="8353523060269335667">"همگام‌سازی"</string>
+    <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"همگام‌سازی"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"تعداد موارد حذف شده <xliff:g id="CONTENT_TYPE">%s</xliff:g> بسیار زیاد است."</string>
-    <string name="low_memory" product="tablet" msgid="6494019234102154896">"حافظه رایانه لوحی پر است! برخی از فایل‎ها را حذف کنید تا فضا آزاد شود."</string>
+    <string name="low_memory" product="tablet" msgid="6494019234102154896">"حافظه رایانهٔ لوحی پر است! برخی از فایل‎ها را حذف کنید تا فضا آزاد شود."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"حافظه تلفن پر است. بعضی از فایل‌ها را حذف کنید تا فضا آزاد شود."</string>
     <string name="me" msgid="6545696007631404292">"من"</string>
-    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"گزینه‌های رایانه لوحی"</string>
+    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"گزینه‌های رایانهٔ لوحی"</string>
     <string name="power_dialog" product="default" msgid="1319919075463988638">"گزینه‌های تلفن"</string>
     <string name="silent_mode" msgid="7167703389802618663">"حالت ساکت"</string>
     <string name="turn_on_radio" msgid="3912793092339962371">"روشن کردن بی سیم"</string>
@@ -142,18 +142,21 @@
     <string name="silent_mode_silent" msgid="319298163018473078">"زنگ خاموش"</string>
     <string name="silent_mode_vibrate" msgid="7072043388581551395">"زنگ لرزشی"</string>
     <string name="silent_mode_ring" msgid="8592241816194074353">"زنگ روشن"</string>
-    <string name="shutdown_progress" msgid="2281079257329981203">"خاموش کردن..."</string>
-    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"رایانه لوحی شما خاموش می‌شود."</string>
+    <string name="shutdown_progress" msgid="2281079257329981203">"در حال خاموش شدن…"</string>
+    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"رایانهٔ لوحی شما خاموش می‌شود."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"گوشی شما خاموش می‌شود."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"آیا می‎خواهید تلفن خاموش شود؟"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"راه‌اندازی مجدد در حالت امن"</string>
-    <string name="reboot_safemode_confirm" msgid="55293944502784668">"آیا می‌خواهید با حالت امن راه‌اندازی مجدد کنید؟ با این کار کلیه برنامه‌های شخص ثالثی که نصب کرده‌اید غیرفعال می‌شوند. با راه‌اندازی دوباره سیستم این برنامه‌ها دوباره بازیابی می‌شوند."</string>
+    <string name="reboot_safemode_confirm" msgid="55293944502784668">"آیا می‌خواهید با حالت امن راه‌اندازی مجدد کنید؟ با این کار همهٔ برنامه‌های شخص ثالثی که نصب کرده‌اید غیرفعال می‌شوند. با راه‌اندازی دوباره سیستم این برنامه‌ها دوباره بازیابی می‌شوند."</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"اخیر"</string>
     <string name="no_recent_tasks" msgid="8794906658732193473">"برنامه‎های جدید موجود نیست."</string>
-    <string name="global_actions" product="tablet" msgid="408477140088053665">"گزینه‌های رایانه لوحی"</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>
     <string name="global_action_power_off" msgid="4471879440839879722">"خاموش کردن"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"گزارش اشکال"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"گرفتن گزارش اشکال"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"این گزارش اطلاعات مربوط به وضعیت دستگاه کنونی شما را جمع‌آوری می‌کند تا به صورت یک پیام ایمیل ارسال شود. از زمان شروع گزارش اشکال تا آماده شدن برای ارسال اندکی زمان می‌برد؛ لطفاً شکیبا باشید."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"حالت ساکت"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"صدا خاموش است"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"صدا روشن است"</string>
@@ -168,22 +171,57 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"پیام‌های شما"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"پیام کوتاه، ایمیل و دیگر پیام‌ها را بخوانید."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"اطلاعات شخصی شما"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"دسترسی مستقیم به مخاطبین و تقویم ذخیره شده در رایانه لوحی."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"دسترسی مستقیم به مخاطبین و تقویم ذخیره شده در گوشی."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"مستقیم به اطلاعات مربوط به خود، ذخیره شده در روی کارت تماس خود دسترسی داشته باشید."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"اطلاعات اجتماعی شما"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"مستقیم به اطلاعات مخاطبین و روابط اجتماعی دسترسی داشته باشید."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"موقعیت مکانی شما"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"بر موقعیت مکانی فیزیکی خود نظارت داشته باشید."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"ارتباط شبکه‌ای"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"به ویژگی‎های مختلف شبکه دسترسی داشته باشید."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"بلوتوث"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"از طریق بلوتوث به دستگاه‌ها و شبکه‌ها دسترسی داشته باشد."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"تنظیمات صدا"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"تنظیمات صوتی را تغییر دهید."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"روی باتری اثر دارد"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"از ویژگی‌هایی استفاده کنید که باتری را سریع خالی می‌کند."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"تقویم"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"مستقیم به رویدادها و تقویم دسترسی داشته باشید."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"خواندن فرهنگ لغت کاربر"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"کلمات را در فرهنگ لغت کاربر بخواند."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"نوشتن فرهنگ لغت کاربر"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"کلمات را به فرهنگ لغت کاربر اضافه کند."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"نشانک‌ها و سابقه"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"مستقیم به نشانک‌ها و سابقه مرور دسترسی داشته باشید."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"زنگ هشدار"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"ساعت زنگ دار را تنظیم کنید."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"پست صوتی"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"به پست صوتی مستقیم دسترسی داشته باشید."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"میکروفن"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"مستقیم به میکروفن برای ضبط صدا دسترسی داشته باشید."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"دوربین"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"مستقیم به دوربین برای عکس گرفتن یا ضبط فیلم دسترسی داشته باشید."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"اطلاعات برنامه‌های شما"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"می‌تواند بر عملکرد برنامه‌های دیگر روی دستگاه اثر بگذارد."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"تصویر زمینه"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"تنظیمات تصویر زمینه دستگاه را تغییر دهید."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"ساعت"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"زمان یا منطقهٔ زمانی دستگاه را تغییر دهید."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"نوار وضعیت"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"تنظیمات نوار وضعیت دستگاه را تغییر دهید."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"تنظیمات همگام‌سازی"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"به تنظیمات همگام‌سازی دسترسی داشته باشید."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"حساب‌های شما"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"به حساب‌های موجود دسترسی داشته باشید."</string>
-    <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"کنترل‌های سخت افزار"</string>
-    <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"دسترسی مستقیم به سخت افزار در گوشی."</string>
+    <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"کنترل‌های سخت‌افزار"</string>
+    <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"دسترسی مستقیم به سخت‌افزار در گوشی."</string>
     <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"تماس‌های تلفنی"</string>
     <string name="permgroupdesc_phoneCalls" msgid="7489701620446183770">"نظارت، ضبط و پردازش تماس‌های تلفنی."</string>
     <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="permgrouplab_display" msgid="4279909676036402636">"رابط برنامهٔ دیگر"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"روی رابط برنامه‌های دیگر اثر دارد."</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>
@@ -208,15 +246,21 @@
     <string name="permlab_sendSmsNoConfirmation" msgid="4781483105951730228">"ارسال پیامک بدون تأیید"</string>
     <string name="permdesc_sendSmsNoConfirmation" msgid="402569800862935907">"به برنامه اجازه می‌دهد پیامک‌ها را ارسال کند. این باعث ایجاد هزینه‌های پیش‌بینی نشده می‌شود. برنامه‌های مخرب ممکن است با ارسال پیام بدون تأیید شما هزینه‌هایی را برای شما ایجاد کنند."</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"خواندن پیام‌های نوشتاری شما (پیامک یا MMS)"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"به برنامه اجازه می‌دهد پیامک‌های ذخیره شده در رایانه لوحی یا سیم کارت شما را بخواند. این ویژگی به برنامه امکان می‌دهد همه پیامک‌ها را صرفنظر از محتوا یا محرمانه بودن آن‌ها بخواند."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"به برنامه اجازه می‌دهد پیامک‌های ذخیره شده در رایانهٔ لوحی یا سیم کارت شما را بخواند. این ویژگی به برنامه امکان می‌دهد همه پیامک‌ها را صرفنظر از محتوا یا محرمانه بودن آن‌ها بخواند."</string>
     <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"به برنامه اجازه می‌دهد پیامک‌های ذخیره شده در تلفن یا سیم کارت شما را بخواند. این ویژگی به برنامه امکان می‌دهد همه پیامک‌ها را صرفنظر از محتوا یا محرمانه بودن آن‌ها بخواند."</string>
     <string name="permlab_writeSms" msgid="3216950472636214774">"ویرایش پیام‌های نوشتاری شما (پیامک یا MMS)"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"به برنامه اجازه می‎دهد تا در پیام‌های کوتاه ذخیره شده در رایانه لوحی یا سیم کارت بنویسد. برنامه‎های مخرب پیام‌های شما را حذف می‎کنند."</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"به برنامه اجازه می‎دهد تا در پیام‌های کوتاه ذخیره شده در رایانهٔ لوحی یا سیم کارت بنویسد. برنامه‎های مخرب پیام‌های شما را حذف می‎کنند."</string>
     <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"به برنامه اجازه می‎دهد تا در پیام‌های کوتاه ذخیره شده در تلفن یا سیم کارت بنویسد. برنامه‎های مخرب می‎توانند پیام‌های شما را حذف کنند."</string>
     <string name="permlab_receiveWapPush" msgid="5991398711936590410">"دریافت پیام‌های نوشتاری (WAP)"</string>
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"به برنامه اجازه می‌دهد پیام‌های WAP را دریافت و پردازش کند. این مجوز می‌تواند پیام‌های ارسالی به شما را بدون نمایش آن‌ها به شما حذف یا کنترل کند."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"بازیابی برنامه‎های در حال اجرا"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"به برنامه امکان می‌دهد اطلاعات مربوط به کارهای در حال اجرای اخیر و کنونی را بازیابی کند. این ممکن است به برنامه امکان دهد به اطلاعات مربوط به برنامه‌هایی که در دستگاه استفاده می‌شوند دست یابد."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"ارتباط بین کاربران"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"به برنامه اجازه می‌دهد اقداماتی در بین کاربران مختلف در دستگاه انجام دهد. ممکن است برنامه‌های مخرب از این قابلیت برای نقض حفاظت موجود در بین کاربران استفاده کنند."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"مجوز کامل برای ارتباط بین کاربران"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"اجازه می‌دهد همه ارتباطات ممکن بین کاربران انجام شود."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"مدیریت کاربران"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"به برنامه‌ها اجازه می‌دهد مدیریت کاربران، از قبیل پرسش، ایجاد و حذف کاربران، را در دستگاه انجام دهند."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"بازیابی جزئیات برنامه‌های در حال اجرا"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"به برنامه اجازه می‎دهد تا اطلاعات مفصلی مربوط به کارهایی که در حال حاضر و اخیراً اجرا می‎شوند را بازیابی کند. برنامه‎های مخرب می‎توانند اطلاعات شخصی مربوط به برنامه‎های دیگر را پیدا کنند."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"تنظیم مجدد ترتیب برنامه‎های در حال اجرا"</string>
@@ -226,7 +270,7 @@
     <string name="permlab_startAnyActivity" msgid="2918768238045206456">"شروع هر نوع فعالیت"</string>
     <string name="permdesc_startAnyActivity" msgid="997823695343584001">"به برنامه اجازه می‎دهد هر فعالیتی را شروع کند بدون اینکه وضعیت صادرشده یا حفاظت با مجوز در نظر گرفته شود."</string>
     <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"تنظیم سازگاری با صفحهٔ نمایش"</string>
-    <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"به برنامه کاربردی اجازه کنترل حالت سازگاری صفحهٔ نمایش برای برنامه‌های دیگر را می‌دهد. برنامه‌های خرابکار ممکن است باعث کارکرد نادرست دیگر برنامه‌ها شوند."</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="4162092185124234480">"تغییر تنظیمات نمایشگر سیستم"</string>
@@ -243,38 +287,50 @@
     <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="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"قابلیت دسترسی به طور موقت فعال شود"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"به یک برنامه اجازه می‌دهد به صورت موقت قابلیت دسترسی را در دستگاه فعال کند. برنامه‌های مخرب می‌توانند قابلیت دسترسی را بدون رضایت کاربر فعال کنند."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"بازیابی اطلاعات پنجره"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"به یک برنامه کاربردی اجازه می‌دهد که اطلاعات مربوط به پنجره‌ها را از مدیریت پنجره بازیابی کند. برنامه‌های کاربردی مخرب ممکن است اطلاعاتی که برای استفاده سیستم داخلی درنظر گرفته شده‌اند را بازیابی کنند."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"فیلتر کردن رویدادها"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"به یک برنامه کاربردی اجازه می‌دهد یک فیلتر ورودی را که جریان تمام رویدادهای کاربران را قبل از ارسال شدن فیلتر می‌کند، ثبت نماید. برنامه‌ کاربردی مخرب ممکن است رابط کاربری سیستم را بدون مداخله کاربر، کنترل کند."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"بزرگ کردن صفحه نمایش"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"به یک برنامه کاربردی اجازه بزرگ کردن محتوای یک صفحه نمایش را می‌دهد. برنامه‌های کاربردی مضر می‌توانند محتوای صفحه نمایش را به طریقی منتقل کنند که باعث غیرقابل‌استفاده شدن دستگاه شود."</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_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="permlab_broadcastSmsReceived" msgid="5689095009030336593">"ارسال پخش دریافت شده توسط پیامک"</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 دریافت کرده است. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا دریافت پیام MMS را جعل کنند یا محتوای هر صفحه وب را با انواع مخرب جایگزین کنند."</string>
+    <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"به برنامه اجازه می‎دهد تا اعلانی را پخش کند که پیام WAP PUSH دریافت کرده است. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا دریافت پیام MMS را جعل کنند یا محتوای هر صفحهٔ وب را با انواع مخرب جایگزین کنند."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"محدود کردن تعداد فرآیندهای در حال اجرا"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"به برنامه اجازه می‎دهد تا حداکثر تعداد پردازشهایی را که اجرا خواهد شد کنترل کند. هرگز برای برنامه‎های عادی لازم نیست."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"بستن اجباری برنامه‌های پس‌زمینه"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"به برنامه اجازه می‎دهد تا به محض اینکه فعالیتها به پس‌زمینه رفتند تمام شوند. برای برنامه‎های عادی نیازی نیست."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"اصلاح کردن آمار مربوط به باتری"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"به برنامه اجازه می‎دهد تا آمار جمع آوری شده باتری را تغییر دهد. برای استفاده برنامه‎های عادی نیست."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"خواندن آمار باتری"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"به یک برنامه کاربردی اجازه می‌دهد که داده‌های استفاده کننده از میزان باتری کم کنونی را بخواند. این کار ممکن است به برنامه این امکان را بدهد که اطلاعات جزئی درباره برنامه‌هایی که استفاده می‌کنید، بدست آورد."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"اصلاح آمار باتری"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"به برنامه اجازه می‎دهد تا آمار جمع‌آوری شده باتری را تغییر دهد. برای استفاده برنامه‎های عادی نیست."</string>
     <string name="permlab_backup" msgid="470013022865453920">"کنترل نسخهٔ پشتیبان سیستم و بازیابی"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"به برنامه اجازه می‎دهد پشتیبان سیستم را کنترل کند و مکانیستم را بازیابی کند. برای استفاده برنامه‎های عادی نیست."</string>
-    <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"تهیه نسخهٔ پشتیبان کامل را تأیید کرده یا عملیات را بازیابی کنید"</string>
+    <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"تهیهٔ نسخهٔ پشتیبان کامل را تأیید کرده یا عملیات را بازیابی کنید"</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="permlab_systemAlertWindow" msgid="3543347980839518613">"ترسیم روی برنامه‌های دیگر"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"به برنامه اجازه می‎دهد تا پنجره‎های هشدار سیستم را نشان دهد. برخی از پنجره‌های هشدار ممکن است کل صفحه را کنترل کنند."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"به برنامه اجازه می‌دهد که در بالا یا بخش‌هایی از رابط کاربری دیگر برنامه‌های کاربردی متصل شود. این کار می‌تواند در استفاده شما از رابط هر برنامه کاربردی تداخل ایجاد کند یا آنچه را که به نظر خود در دیگر برنامه‌های کاربردی می‌بینید، تغییر دهد."</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="permlab_freezeScreen" msgid="4708181184441880175">"ثابت نگه داشتن صفحه"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"به برنامه کاربردی اجازه می‌دهد که موقتاً صفحه را برای یک انتقال تمام صفحه ثابت نگه دارد."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"کلیدها و دکمه‌های کنترل را فشار دهید"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"به برنامه اجازه می‎دهد تا رویدادهای ورودی خود (فشردن کلیدها و غیره) را تحویل دهد. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا کارکرد رایانه لوحی را کنترل کنند."</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>
@@ -296,42 +352,42 @@
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"به برنامه اجازه می‎دهد تا چرخش صفحه را هر وقت بخواهد تغییر دهد. برای برنامه‎های عادی نیاز نیست."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"تغییر سرعت اشاره‌گر"</string>
     <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"به برنامه اجازه می‎دهد تا سرعت ماوس و پد کنترل را هر وقت خواست تغییر دهد. برای برنامه‎های عادی نیاز نیست."</string>
-    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"تغییر چیدمان صفحه کلید"</string>
-    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"به برنامه اجازه می‌دهد تا چیدمان صفحه کلید را تغییر دهد. این کار هیچ‌گاه برای برنامه‌های عادی نیاز نیست."</string>
+    <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"تغییر چیدمان صفحه‌کلید"</string>
+    <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"به برنامه اجازه می‌دهد تا چیدمان صفحه‌کلید را تغییر دهد. این کار هیچ‌گاه برای برنامه‌های عادی نیاز نیست."</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" product="tablet" msgid="8525189272329086137">"به برنامه امکان می‌دهد قسمت‌هایی از خود را در حافظه دائمی کند. این کار حافظه موجود را برای سایر برنامه‌ها محدود کرده و باعث کندی رایانه لوحی می‌شود."</string>
+    <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"به برنامه امکان می‌دهد قسمت‌هایی از خود را در حافظه دائمی کند. این کار حافظه موجود را برای سایر برنامه‌ها محدود کرده و باعث کندی رایانهٔ لوحی می‌شود."</string>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"به برنامه امکان می‌دهد قسمت‌هایی از خود را در حافظه دائمی کند. این کار حافظه موجود را برای سایر برنامه‌ها محدود کرده و باعث کندی تلفن می‌شود."</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_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="permdesc_getPackageSize" msgid="3921068154420738296">"به برنامه اجازه می‎دهد تا کدها، داده‎ها و اندازه‎های حافظهٔ پنهان خود را بازیابی کند"</string>
     <string name="permlab_installPackages" msgid="2199128482820306924">"نصب مستقیم برنامه"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"به برنامه اجازه می‎دهد تا بسته‎های Android به روز شده یا جدید را نصب کند. برنامه‎های مخرب می‎توانند از این استفاده کنند تا برنامه‎های جدید را با مجوزهای قوی اختیاری اضافه کنند."</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_clearAppCache" msgid="7487279391723526815">"حذف تمام داده‎های حافظهٔ پنهان برنامه"</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"به برنامه اجازه می‌دهد که فضای رایانه لوحی را از طریق حذف کردن فایل‌ها در دایرکتوری حافظه پنهان دیگر برنامه‌های کاربردی، آزاد کند. این کار ممکن است باعث کندی دیگر برنامه‌های کاربردی در هنگام راه‌اندازی شود زیرا آنها باید دوباره داده‌های خود را بازیابی کنند."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"به برنامه اجازه می‌دهد که فضای تلفن را از طریق حذف کردن فایل‌ها در دایرکتوری حافظه پنهان دیگر برنامه‌های کاربردی، آزاد کند. این کار ممکن است باعث راه اندازی آهسته دیگر برنامه‌های کاربردی در نتیجه نیاز آنها به بازیابی داده‌های خود، شود."</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="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="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="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="permdesc_grantRevokePermissions" msgid="4088642654085850662">"به یک برنامهٔ کاربردی اجازه می‌دهد تا مجوزهای خاصی را برای خود یا دیگر برنامه‌ها ارائه کرده یا آن‌ها را لغو کند. برنامه‌های مضر از این حالت برای دسترسی به ویژگی‌هایی استفاده می‌کنند که شما اجازه آن را در اختیارشان قرار نداده‌اید."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"تنظیم برنامه‎های ترجیحی"</string>
-    <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"به برنامه اجازه می‎دهد تا برنامه‎های ترجیحی شما را تغییر دهد. برنامه‎های مخرب می‎توانند بدون اعلان برنامه‎هایی را که اجرا می‎شوند، تغییر دهند خود را به جای برنامه‎های کنونی قلمداد کنند تا داده‎های شخصی را از شما جمع آوری کنند."</string>
+    <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"به برنامه اجازه می‎دهد تا برنامه‎های ترجیحی شما را تغییر دهد. برنامه‎های مخرب می‎توانند بدون اعلان برنامه‎هایی را که اجرا می‎شوند، تغییر دهند خود را به جای برنامه‎های کنونی قلمداد کنند تا داده‎های شخصی را از شما جمع‌آوری کنند."</string>
     <string name="permlab_writeSettings" msgid="2226195290955224730">"اصلاح تنظیمات سیستم"</string>
     <string name="permdesc_writeSettings" msgid="7775723441558907181">"به برنامه اجازه می‎دهد تا داده‎های تنظیم سیستم را تغییر دهد. برنامه‎های مخرب می‎توانند پیکربندی سیستم شما را خراب کنند."</string>
     <string name="permlab_writeSecureSettings" msgid="204676251876718288">"اصلاح کردن تنظیمات سیستم ایمن"</string>
@@ -339,36 +395,36 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"اصلاح کردن نقشه سرویس‌های Google"</string>
     <string name="permdesc_writeGservices" msgid="1287309437638380229">"به برنامه اجازه می‎دهد تا نقشه سرویس‌های Google را تغییر دهد. برای استفاده برنامه‎های عادی نیست."</string>
     <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"اجرا شدن در هنگام راه‌اندازی"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"به برنامه اجازه می‎دهد تا به محض اتمام راه‎اندازی سیستم خودبخود شروع به کار کند. این کار ممکن است باعث شود مدت زمان بیشتری صرف شدوع به کار رایانه لوحی شود و به برنامه اجازه می‎دهد تا با اجرای همیشگی رایانه لوحی را کند کند."</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="7749760494399915651">"به برنامه اجازه می‎دهد تا پخش‌های ماندگار را که پس از اتمام پخش باقی می‎مانند ارسال کند. استفاده بیش از حد این ویژگی ممکن است باعث مصرف بیش از حد حافظه و در نتیجه کندی یا ناپایداری رایانه لوحی شود."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"به برنامه اجازه می‎دهد تا پخش‌های ماندگار را که پس از اتمام پخش باقی می‎مانند ارسال کند. استفاده بیش از حد این ویژگی ممکن است باعث مصرف بیش از حد حافظه و در نتیجه کندی یا ناپایداری رایانهٔ لوحی شود."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"به برنامه اجازه می‎دهد تا پخش‌های ماندگار را که پس از اتمام پخش باقی می‎مانند ارسال کند. استفاده بیش از حد این ویژگی ممکن است باعث مصرف بیش از حد حافظه و در نتیجه کندی یا ناپایداری تلفن شود."</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"خواندن مخاطبین شما"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در رایانه لوحی شما را بخواند از جمله، تعداد دفعات تماس‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا به روش‌های دیگری به افراد خاصی ارتباط برقرار کرده‌اید. این با برنامه‌ها امکان می‌دهد داده‌های مخاطب شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های مخاطب را بدون اطلاع شما به اشتراک بگذارند."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در رایانهٔ لوحی شما را بخواند از جمله، تعداد دفعات تماس‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا به روش‌های دیگری به افراد خاصی ارتباط برقرار کرده‌اید. این با برنامه‌ها امکان می‌دهد داده‌های مخاطب شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های مخاطب را بدون اطلاع شما به اشتراک بگذارند."</string>
     <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در تلفن شما را بخواند از جمله، تعداد دفعات تماس‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا به روش‌های دیگری با افراد خاصی ارتباط برقرار کرده‌اید. این به برنامه‌ها امکان می‌دهد داده‌های مخاطب شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های مخاطب را بدون اطلاع شما به اشتراک بگذارند."</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"اصلاح مخاطبین شما"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در رایانه لوحی شما را از جمله تعداد تماس‌‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا ارتباطاتی را که به هر شکل با مخاطبین خاصی برقرار کردید تغییر دهد. این مجوز به برنامه اجازه می‌دهد داده‌های مخاطب را حذف نماید."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در رایانهٔ لوحی شما را از جمله تعداد تماس‌‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا ارتباطاتی را که به هر شکل با مخاطبین خاصی برقرار کردید تغییر دهد. این مجوز به برنامه اجازه می‌دهد داده‌های مخاطب را حذف نماید."</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در تلفن شما را از جمله تعداد تماس‌‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا ارتباطاتی را که به هر شکل با مخاطبین خاصی برقرار کردید تغییر دهد. این مجوز به برنامه اجازه می‌دهد داده‌های مخاطب را حذف نماید."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"خواندن گزارش تماس"</string>
-    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"به برنامه اجازه می‌دهد گزارش تماس رایانه لوحی شما را بخواند از جمله داده‌های مربوط به تماس‌های ورودی و خروجی. این مجوز به برنامه‌ها اجازه می‌دهد داده‌های گزارش تماس شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های گزارش تماس شما را بدون اطلاع شما به اشتراک بگذارند."</string>
+    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"به برنامه اجازه می‌دهد گزارش تماس رایانهٔ لوحی شما را بخواند از جمله داده‌های مربوط به تماس‌های ورودی و خروجی. این مجوز به برنامه‌ها اجازه می‌دهد داده‌های گزارش تماس شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های گزارش تماس شما را بدون اطلاع شما به اشتراک بگذارند."</string>
     <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"به برنامه اجازه می‌دهد گزارش تماس تلفنی شما را بخواند از جمله داده‌های مربوط به تماس‌های ورودی و خروجی. این مجوز به برنامه‌ها اجازه می‌دهد داده‌های گزارش تماس شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های گزارش تماس شما را بدون اطلاع شما به اشتراک بگذارند."</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"نوشتن گزارش تماس"</string>
-    <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"به برنامه اجازه می‌دهد گزارشات تماس رایانه لوحی شما، از جمله داده‌هایی درمورد تماس‎های ورودی و خروجی را تغییر دهد. برنامه‌های مخرب ممکن است از این ویژگی برای پاک کردن یا تغییر گزارش تماس شما استفاده کنند."</string>
+    <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"به برنامه اجازه می‌دهد گزارشات تماس رایانهٔ لوحی شما، از جمله داده‌هایی درمورد تماس‎های ورودی و خروجی را تغییر دهد. برنامه‌های مخرب ممکن است از این ویژگی برای پاک کردن یا تغییر گزارش تماس شما استفاده کنند."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"به برنامه اجازه می‌دهد گزارشات تماس تلفنی شما، از جمله داده‌هایی درمورد تماس‎های ورودی و خروجی را تغییر دهد. برنامه‌های مخرب ممکن است از این ویژگی برای پاک کردن یا تغییر گزارش تماس شما استفاده کنند."</string>
     <string name="permlab_readProfile" msgid="4701889852612716678">"خواندن کارت تماس شما"</string>
-    <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"به برنامه اجازه می‎دهد اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را بخواند. یعنی برنامه می‎تواند شما را شناسایی کند و ممکن است اطلاعات نمایه شما را به دیگران ارسال کند."</string>
+    <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"به برنامه اجازه می‎دهد اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را بخواند. یعنی برنامه می‎تواند شما را شناسایی کند و ممکن است اطلاعات نمایهٔ شما را به دیگران ارسال کند."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"اصلاح کارت تماس شما"</string>
-    <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"به برنامه اجازه می‎دهد تا اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را تغییر دهد یا اضافه کند. یعنی برنامه‎ می‎تواند شما را شناسایی کند و ممکن است اطلاعات نمایه شما را برای دیگران ارسال کند."</string>
+    <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"به برنامه اجازه می‎دهد تا اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را تغییر دهد یا اضافه کند. یعنی برنامه‎ می‎تواند شما را شناسایی کند و ممکن است اطلاعات نمایهٔ شما را برای دیگران ارسال کند."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"خواندن جریان اجتماعی شما"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"به برنامه اجازه می‌دهد به به‌روزرسانی‌های اجتماعی از طرف شما و دوستان شما دسترسی پیدا کرده و آن‌ها را همگام‌سازی کند. دقت کنید که هنگام اشتراک‌گذاری -- این ویژگی به برنامه اجازه می‌دهد ارتباطات بین شما و دوستان شما را در شبکه‌های اجتماعی، صرفنظر از محرمانه بودن آن‌ها بخواند. توجه: این مجوز ممکن است در همه شبکه‌های اجتماعی اجرا نشود."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"نوشتن در جریان اجتماعی شما"</string>
     <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"به برنامه اجازه می‌دهد به‌روزرسانی‌های اجتماعی از طرف دوستان شما را نمایش دهد. دقت کنید هنگام اشتراک‌گذاری اطلاعات -- این ویژگی به برنامه اجازه می‌دهد پیام‌هایی را که به نظر می‌رسد از طرف یکی از دوستان شما باشد ایجاد کند. توجه: این مجوز در همه شبکه‌های اجتماعی قابل اجرا نیست."</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"خواندن رویدادهای تقویم به همراه اطلاعات محرمانه"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"به برنامه امکان می‌دهد همه رویدادهای تقویم ذخیره شده در رایانه لوحی شما را بخواند، از جمله رویدادهای دوستان یا همکاران. این ممکن است به برنامه امکان دهد داده‌های تقویم شما را صرفنظر از محرمانه یا حساس بودن آن‌ها به اشتراک گذاشته یا ذخیره کند."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"به برنامه امکان می‌دهد همه رویدادهای تقویم ذخیره شده در رایانهٔ لوحی شما را بخواند، از جمله رویدادهای دوستان یا همکاران. این ممکن است به برنامه امکان دهد داده‌های تقویم شما را صرفنظر از محرمانه یا حساس بودن آن‌ها به اشتراک گذاشته یا ذخیره کند."</string>
     <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"به برنامه امکان می‌دهد همه رویدادهای تقویم ذخیره شده در تلفن شما را بخواند، از جمله رویدادهای دوستان یا همکاران. این ممکن است به برنامه امکان دهد داده‌های تقویم شما را صرفنظر از محرمانه یا حساس بودن آن‌ها به اشتراک گذاشته یا ذخیره کند."</string>
     <string name="permlab_writeCalendar" msgid="8438874755193825647">"افزودن یا تغییر رویدادهای تقویم و ارسال ایمیل به مهمانان بدون دخالت مالک"</string>
-    <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"به برنامه اجازه می‌دهد رویدادهایی را که می‌توانید در رایانه لوحی خود اصلاح نمایید، از جمله رویدادهای دوستان یا همکاران خود را، اضافه یا حذف کرده یا تغییر دهد. این ویژگی ممکن است به برنامه اجازه دهد پیام‌هایی را که به نظر می‌رسد از مالکین تقویم رسیده است ارسال نموده یا رویدادها را بدون اطلاع مالک اصلاح کنند."</string>
+    <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"به برنامه اجازه می‌دهد رویدادهایی را که می‌توانید در رایانهٔ لوحی خود اصلاح نمایید، از جمله رویدادهای دوستان یا همکاران خود را، اضافه یا حذف کرده یا تغییر دهد. این ویژگی ممکن است به برنامه اجازه دهد پیام‌هایی را که به نظر می‌رسد از مالکین تقویم رسیده است ارسال نموده یا رویدادها را بدون اطلاع مالک اصلاح کنند."</string>
     <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"به برنامه اجازه می‌دهد رویدادهایی را که می‌توانید در تلفن خود اصلاح نمایید، از جمله رویدادهای دوستان یا همکاران خود را، اضافه یا حذف کرده یا تغییر دهد. این ویژگی ممکن است به برنامه اجازه دهد پیام‌هایی را که به نظر می‌رسد از مالکین تقویم رسیده است ارسال نموده یا رویدادها را بدون اطلاع مالک اصلاح کنند."</string>
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"منابع مکان کاذب برای تست"</string>
     <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"منابع موقعیت مکانی کاذب را برای تست کردن یا نصب یک ارائه‌دهنده موقعیت مکانی جدید ایجاد نمایید. این کار به برنامه امکان می‌دهد موقعیت مکانی و/یا وضعیت گزارش داده شده توسط سایر منابع موقعیت مکانی مانند GPS یا ارائه‌دهندگان موقعیت مکانی را نادیده بگیرد."</string>
@@ -376,29 +432,32 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"به برنامه اجازه می‎دهد تا به فرمان‌های ارائه‎دهنده موقعیت مکانی دیگری دسترسی داشته باشد. این ویژگی ممکن است باعث مختل شدن عملکرد GPS یا دیگر منابع موقعیت مکانی توسط این برنامه شود."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"مجوز برای نصب یک ارائه دهنده مکان"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"منابع موقعیت مکانی کاذب را برای تست کردن یا نصب یک ارائه‌دهنده موقعیت مکانی جدید ایجاد نمایید. این کار به برنامه امکان می‌دهد موقعیت مکانی و/یا وضعیت گزارش داده شده توسط سایر منابع موقعیت مکانی مانند GPS یا ارائه‌دهندگان موقعیت مکانی را نادیده بگیرد."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"موقعیت مکانی دقیق (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"به منابع موقعیت مکانی دقیق مانند سیستم موقعیت‌یابی جهانی در رایانه لوحی خود دسترسی پیدا کنید. وقتی سرویس‌های موقعیت مکانی موجود و فعال باشند، این مجوز به برنامه اجازه می‌دهد موقعیت مکانی دقیق شما را تعیین کند."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"به منابع موقعیت مکانی دقیق مانند سیستم موقعیت‌یابی جهانی در تلفن خود دسترسی پیدا کنید. وقتی سرویس‌های موقعیت مکانی موجود و فعال باشند، این مجوز به برنامه اجازه می‌دهد موقعیت مکانی دقیق شما را تعیین کند."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"موقعیت مکانی تقریبی (مبتنی بر شبکه)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"به موقعیت مکانی تقریبی ارا‌ئه‌دهندگان موقعیت مکانی با استفاده از منابع شبکه مانند برج مخابراتی و Wi-Fi دسترسی پیدا کنید. وقتی این سرویس‌های موقعیت مکانی موجود و فعال باشند، این مجوز به برنامه امکان می‌دهد موقعیت مکانی تقریبی شما را تعیین کند."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"موقعیت مکانی دقیق (مبتنی بر GPS و شبکه)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"به برنامه اجازه می‌دهد که موقعیت مکانی دقیق شما را با استفاده از سیستم موقعیت‌یاب جهانی (GPS) یا منابع موقعیت مکانی شبکه‌ای مانند برج‌های سلولی یا Wi-Fi دریافت کند. این سرویس‌های موقعیت مکانی باید در دستگاه شما برای برنامه‌ای که از آنها استفاده می‌کند، فعال و در دسترس باشد. برنامه‌ها ممکن است از آن برای تعیین جایی که هستید، استفاده کنند و ممکن است نیروی باتری بیشتری مصرف کنند."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"موقعیت مکانی تقریبی (مبتنی بر شبکه)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"به برنامه اجازه می‌دهد که موقعیت مکانی تقریبی شما را بدست آورد. این موقعیت مکانی از سرویس‌های موقعیت مکانی که از منابع موقعیت مکانی شبکه‌ای مانند برج‌های سلولی و Wi-Fi استفاده می‌کنند، بدست می‌آید. این سرویس‌های موقعیت مکانی باید در دستگاه شما برای برنامه‌ای که از آنها استفاده می‌کند، فعال و در دسترس باشد. برنامه‌ها ممکن است از آن برای تعیین تقریبی جایی که هستید، استفاده کنند."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"دسترسی به 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="permlab_configureWifiDisplay" msgid="5595661694746742168">"پیکربندی صفحه نمایش‌های Wifi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"به برنامه اجازه می‌دهد تا اتصال به صفحات نمایش Wifi را پیکربندی کند."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"کنترل صفحه نمایش‌های Wifi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"به برنامه اجازه می‌دهد که ویژگی‌های سطح پایین صفحه‌های نمایش Wifi را کنترل کند."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"تغییر تنظیمات صوتی"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"به برنامه امکان می‌دهد تنظیمات صوتی کلی مانند میزان صدا و بلندگوی مورد استفاده برای پخش صدا را اصلاح کند."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ضبط صدا"</string>
     <string name="permdesc_recordAudio" msgid="4906839301087980680">"به برنامه اجازه می‌دهد صدا را با میکروفن ضبط کند. این مجوز به برنامه اجازه می‌دهد صدا را در هر زمان که بخواهید بدون تأیید شما ضبط کند."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"عکسبرداری و فیلمبرداری"</string>
     <string name="permdesc_camera" msgid="8497216524735535009">"به برنامه اجازه می‌دهد با دوربین به عکسبرداری و فیلمبرداری بپردازد. این مجوز به برنامه اجازه می‌‌دهد از دوربین در هر زمانی بدون تأیید شما استفاده کند."</string>
-    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"غیر فعال کردن دائم رایانه لوحی"</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="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="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="permlab_mount_unmount_filesystems" product="nosdcard" msgid="2927361537942591841">"دسترسی به سیستم فایل حافظهٔ USB"</string>
     <string name="permlab_mount_unmount_filesystems" product="default" msgid="4402305049890953810">"دسترسی به سیستم فایل کارت SD"</string>
     <string name="permdesc_mount_unmount_filesystems" msgid="1829290701658992347">"به برنامه اجازه می‎دهد تا فایل‌های سیستمی در حافظه جداشدنی نصب شود یا نصب آن لغو شود."</string>
@@ -423,14 +482,14 @@
     <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="permlab_hardware_test" msgid="4148290860400659146">"تست سخت‌افزار"</string>
     <string name="permdesc_hardware_test" msgid="6597964191208016605">"به برنامه اجازه می‎دهد به منظور تست سخت‌افزار، قسمت‌های جانبی مختلف را کنترل کنند."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"تماس مستقیم با شماره تلفن‌ها"</string>
     <string name="permdesc_callPhone" msgid="3740797576113760827">"به برنامه اجازه می‌دهد بدون دخالت شما با شماره‌های تلفن تماس بگیرد. این ممکن است باعث ایجاد هزینه یا تماس‌های پیش‌بینی نشده شود. توجه داشته باشید که این به برنامه اجازه نمی‌دهد به برقراری تماس‌های اضطراری بپردازد. برنامه‌های مخرب ممکن است با برقراری تماس بدون تأیید شما هزینه‌هایی را برای شما ایجاد کنند."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"تماس مستقیم با هر شماره تلفنی"</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="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="permlab_locationUpdates" msgid="7785408253364335740">"کنترل اعلان‌های به‌روزرسانی مکان"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"به برنامه اجازه می‎دهد اعلانهای به‎روزرسانی موقعیت مکانی را از رادیو فعال/غیرفعال کند. برای استفاده برنامه‎های عادی نیست."</string>
@@ -442,17 +501,17 @@
     <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"به برنامه اجازه می‎دهد ویژگی‌های دستگاه را کنترل کند. برنامه‎ای که این مجوز را دارد می‎تواند بدون اطلاع شما تعویض شبکه داشته باشد، رادیوی تلفن را روشن یا خاموش کند و کارهایی از این قبیل را انجام دهد."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"خواندن وضعیت تلفن و شناسه"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"به برنامه اجازه می‌دهد به ویژگی‌های تلفن دستگاه شما دسترسی پیدا کند. این مجوز به برنامه اجازه می‌دهد شماره تلفن و شناسه‌های دستگاه، فعال بودن یک تماس و شماره راه دوری که با یک تماس متصل شده است را مشخص کند."</string>
-    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ممانعت از به خواب رفتن رایانه لوحی"</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="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="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="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="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="permlab_setWallpaperHints" msgid="3278608165977736538">"تنظیم اندازه تصویر زمینه"</string>
@@ -460,15 +519,15 @@
     <string name="permlab_masterClear" msgid="2315750423139697397">"بازنشانی سیستم به موارد پیش‌فرض کارخانه"</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="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="tablet" msgid="1676983712315827645">"به برنامه اجازه می‎دهد تا منطقهٔ زمانی رایانهٔ لوحی را تغییر دهد."</string>
     <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"به برنامه اجازه می‎دهد تا منطقهٔ زمانی تلفن را تغییر دهد."</string>
-    <string name="permlab_accountManagerService" msgid="4829262349691386986">"عملکرد به عنوان AccountManagerService"</string>
+    <string name="permlab_accountManagerService" msgid="4829262349691386986">"عملکرد به‌عنوان AccountManagerService"</string>
     <string name="permdesc_accountManagerService" msgid="1948455552333615954">"به برنامه اجازه می‎دهد با AccountAuthenticators تماس برقرار کند."</string>
     <string name="permlab_getAccounts" msgid="1086795467760122114">"یافتن حساب‌ها در دستگاه"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"به برنامه اجازه می‌دهد به لیست حساب‌های شناخته شده توسط رایانه لوحی دسترسی پیدا کند. این ممکن است حسا‌ب‌های ایجاد شده توسط برنامه‌هایی را که نصب کرده‌اید، شامل شود."</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"به برنامه اجازه می‌دهد به لیست حساب‌های شناخته شده توسط رایانهٔ لوحی دسترسی پیدا کند. این ممکن است حسا‌ب‌های ایجاد شده توسط برنامه‌هایی را که نصب کرده‌اید، شامل شود."</string>
     <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"به برنامه اجازه می‌دهد به لیست حساب‌های شناخته شده توسط تلفن دسترسی پیدا کند. این ممکن است حسا‌ب‌های ایجاد شده توسط برنامه‌هایی را که نصب کرده‌اید، شامل شود."</string>
     <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"ایجاد حساب‌ها و تنظیم گذرواژ‌ه‌ها"</string>
     <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"به برنامه اجازه می‎دهد از امکانات تأیید کننده اعتبار حساب AccountManager از جمله ایجاد حساب و دریافت و تنظیم گذرواژه‎ها استفاده کند."</string>
@@ -489,32 +548,32 @@
     <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"تغییر تنظیمات میزان استفاده داده در پس‌زمینه"</string>
     <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"به برنامه اجازه می‎دهد تا تنظیم کاربرد داده‎های پس‌زمینه را تغییر دهد."</string>
     <string name="permlab_accessWifiState" msgid="5202012949247040011">"مشاهدهٔ اتصالات Wi-Fi"</string>
-    <string name="permdesc_accessWifiState" msgid="5002798077387803726">"به برنامه امکان می‌دهد اطلاعات مربوط به شبکه Wi-Fi را مشاهده کند، به عنوان مثال فعال بودن Wi-Fi و نام دستگاه‌های Wi-Fi متصل."</string>
+    <string name="permdesc_accessWifiState" msgid="5002798077387803726">"به برنامه امکان می‌دهد اطلاعات مربوط به شبکه Wi-Fi را مشاهده کند، به‌عنوان مثال فعال بودن Wi-Fi و نام دستگاه‌های Wi-Fi متصل."</string>
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"اتصال به Wi-Fi و قطع اتصال از آن"</string>
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"به برنامه اجازه می‎دهد تا به نقاط دسترسی Wi-Fi وصل شود و ارتباط خود را با آن‌ها قطع کند و تغییراتی را در پیکربندی دستگاه برای شبکه‎های Wi-Fi ایجاد کند."</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"دریافت چندگانه Wi-Fi را مجاز می‌کند"</string>
-    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"به برنامه اجازه می‌دهد به دریافت بسته‌های ارسالی به همه دستگاه‌های موجود در شبکه Wi-Fi با استفاده از آدرس‌های پخش چندگانه و نه فقط به رایانه لوحی شما بپردازند. این از توان مصرف بیشتری نسبت به حالت پخش غیرچندگانه استفاده می‌کند."</string>
+    <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"به برنامه اجازه می‌دهد به دریافت بسته‌های ارسالی به همه دستگاه‌های موجود در شبکه Wi-Fi با استفاده از آدرس‌های پخش چندگانه و نه فقط به رایانهٔ لوحی شما بپردازند. این از توان مصرف بیشتری نسبت به حالت پخش غیرچندگانه استفاده می‌کند."</string>
     <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"به برنامه اجازه می‌دهد به دریافت بسته‌های ارسالی به همه دستگاه‌های موجود در شبکه Wi-Fi با استفاده از آدرس‌های پخش چندگانه و نه فقط به تلفن شما بپردازند. این از توان مصرف بیشتری نسبت به حالت پخش غیرچندگانه استفاده می‌کند."</string>
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"دسترسی به تنظیمات بلوتوث"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"به برنامه اجازه می‎دهد تا رایانه لوحی بلوتوث محلی را پیکربندی کرده، دستگاه‌های راه دور را شناسایی کرده و با آن‌ها جفت شود."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"به برنامه اجازه می‎دهد تا رایانهٔ لوحی بلوتوث محلی را پیکربندی کرده، دستگاه‌های راه دور را شناسایی کرده و با آن‌ها جفت شود."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"به برنامه اجازه می‎دهد تا تلفن بلوتوث محلی را پیکربندی کند و دستگاه‌های راه دور را پیدا کند و با آن‌ها جفت شود."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"مشاهدهٔ اتصالات وایمکس"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"اتصال و قطع اتصال از WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"به برنامه امکان می‌دهد فعال بودن وایمکس و اطلاعات مربوط به هر یک از شبکه‌های وایمکس متصل را مشخص کند."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"تغییر وضعیت WiMAX"</string>
-    <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"به برنامه امکان می‌دهد رایانه لوحی را به شبکه‌های وایمکس متصل کرده یا اتصال آن را از این شبکه‌ها قطع کند."</string>
+    <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"به برنامه امکان می‌دهد رایانهٔ لوحی را به شبکه‌های وایمکس متصل کرده یا اتصال آن را از این شبکه‌ها قطع کند."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"به برنامه امکان می‎دهد تا تلفن را به شبکه‌های وایمکس متصل کرده یا اتصال آنرا از این شبکه‌ها قطع کند."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"مرتبط‌ سازی با دستگاه‌های بلوتوث"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"به برنامه اجازه می‎دهد تا پیکربندی بلوتوث در رایانه لوحی را مشاهده کند و اتصال با دستگاه‌های مرتبط را برقرار کرده و بپذیرد."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"به برنامه اجازه می‎دهد تا پیکربندی بلوتوث در رایانهٔ لوحی را مشاهده کند و اتصال با دستگاه‌های مرتبط را برقرار کرده و بپذیرد."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"به برنامه اجازه می‎دهد تا پیکربندی بلوتوث در تلفن را مشاهده کند، و اتصالات دستگاه‌های مرتبط را برقرار کرده و بپذیرد."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"کنترل ارتباط راه نزدیک"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"به برنامه اجازه می‎دهد تا با تگهای ارتباط میدان نزدیک (NFC)، کارتها و فایل خوان ارتباط برقرار کند."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"غیرفعال کردن قفل صفحه شما"</string>
-    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"به برنامه امکان می‌دهد قفل کلید و هر گونه امنیت گذرواژه مرتبط را غیرفعال کند. به عنوان مثال تلفن هنگام دریافت یک تماس تلفنی ورودی قفل کلید را غیرفعال می‌کند و بعد از پایان تماس، قفل کلید را دوباره فعال می‌کند."</string>
-    <string name="permlab_readSyncSettings" msgid="6201810008230503052">"خواندن تنظیمات همگام سازی"</string>
-    <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"به برنامه اجازه می‌دهد تنظیمات را برای یک حساب بخواند. به عنوان مثال، این ویژگی می‌تواند تعیین کند آیا حساب «افراد» شما با یک حساب همگام‌سازی شده است."</string>
+    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"به برنامه امکان می‌دهد قفل کلید و هر گونه امنیت گذرواژه مرتبط را غیرفعال کند. به‌عنوان مثال تلفن هنگام دریافت یک تماس تلفنی ورودی قفل کلید را غیرفعال می‌کند و بعد از پایان تماس، قفل کلید را دوباره فعال می‌کند."</string>
+    <string name="permlab_readSyncSettings" msgid="6201810008230503052">"خواندن تنظیمات همگام‌سازی"</string>
+    <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"به برنامه اجازه می‌دهد تنظیمات را برای یک حساب بخواند. به‌عنوان مثال، این ویژگی می‌تواند تعیین کند آیا حساب «افراد» شما با یک حساب همگام‌سازی شده است."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"تغییر وضعیت همگام‌سازی بین فعال و غیرفعال"</string>
-    <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"به یک برنامه اجازه می‌دهد تنظیمات همگام‌سازی را برای یک حساب اصلاح کند. به عنوان مثال، از این ویژگی می‌توان برای فعال کردن همگام‌سازی برنامه «افراد» با یک حساب استفاده کرد."</string>
-    <string name="permlab_readSyncStats" msgid="7396577451360202448">"خواندن اطلاعات آماری همگام سازی"</string>
+    <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"به یک برنامه اجازه می‌دهد تنظیمات همگام‌سازی را برای یک حساب اصلاح کند. به‌عنوان مثال، از این ویژگی می‌توان برای فعال کردن همگام‌سازی برنامه «افراد» با یک حساب استفاده کرد."</string>
+    <string name="permlab_readSyncStats" msgid="7396577451360202448">"خواندن اطلاعات آماری همگام‌سازی"</string>
     <string name="permdesc_readSyncStats" msgid="1510143761757606156">"به یک برنامه اجازه می‌دهد وضعیت همگام‌سازی یک حساب را بخواند، از جمله سابقه رویدادهای همگام‌سازی و میزان داده‌های همگام‌سازی شده."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"خواندن فیدهای مشترک"</string>
     <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"به برنامه اجازه می‎دهد تا جزئیات مربوط به فیدهای همگام شده کنونی را دریافت کند."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"به برنامه اجازه می‎دهد تا فیدهای همگام شده کنونی را تغییر دهد. برنامه‎های مخرب می‎توانند فیدهای همگام شده را تغییر دهند."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"خواندن واژه‌هایی که به فرهنگ‌ لغت اضافه کردید"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"به برنامه اجازه می‎دهد همه کلمه، نام و عباراتی را که کاربر در فرهنگ لغت خود ذخیره کرده است بخواند."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"نوشتن در فرهنگ لغت تعریف شده از سوی کاربر"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"افزودن کلمات به فرهنگ لغت تعریف‌ شده توسط کاربر"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"به برنامه اجازه می‎دهد تا کلمات جدید را در فهرست کاربر بنویسد."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"تست کردن دسترسی به حافظهٔ محافظت‌شده"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"تست کردن دسترسی به حافظهٔ محافظت‌شده"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"به برنامه اجازه می‌دهد یک مجوز را برای حافظهٔ USB که در دستگاه‌های آتی موجود خواهد بود تست کند."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"به برنامه اجازه می‌دهد یک مجوز را برای حافظه USB که در دستگاه‌های آتی ارائه خواهد شد، تست کند."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"به برنامه اجازه می‌دهد یک مجوز را برای کارت SD که در دستگاه‌های آتی موجود خواهد بود تست کند."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"اصلاح یا حذف محتویات حافظهٔ USB شما"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"محتوای کارت SD شما را اصلاح کرده یا تغییر دهد"</string>
@@ -534,9 +593,11 @@
     <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="permlab_cache_filesystem" msgid="5656487264819669824">"دسترسی به سیستم فایل حافظه پنهان"</string>
-    <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"به برنامه اجازه می‎دهد تا سیستم فایل حافظه پنهان را بخواند و بنویسد."</string>
-    <string name="permlab_use_sip" msgid="5986952362795870502">"علامتگذاری/دریافت تماس‌های اینترنتی"</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"دسترسی به دستگاه ذخیره خارجی تمام کاربران"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"به برنامه اجازه می‌دهد به دستگاه ذخیره خارجی برای همه کاربران دسترسی داشته باشد."</string>
+    <string name="permlab_cache_filesystem" msgid="5656487264819669824">"دسترسی به سیستم فایل حافظهٔ پنهان"</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="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"خواندن سابقه استفاده از شبکه"</string>
     <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"به برنامه اجازه می‎دهد تا کاربرد شبکه را در طول زمان برای برنامه‎ها و شبکه‎های خاص بخواند."</string>
@@ -547,23 +608,25 @@
     <string name="policylab_limitPassword" msgid="4497420728857585791">"تنظیم قوانین رمز ورود"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"طول و نویسه‎های مجاز در گذرواژه‌های بازکردن قفل صفحه را کنترل کنید."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"نمایش تلاش‌های قفل گشایی صفحه"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"تعداد گذرواژه‎های اشتباه تایپ شده را هنگام بازکردن قفل صفحه کنترل می‌کند، و یا اگر دفعات زیادی گذرواژه اشتباه تایپ شود رایانه لوحی را قفل می‎کند و همه داده‎های رایانه لوحی را پاک می‎کند."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"تعداد گذرواژه‎های اشتباه تایپ شده را هنگام بازکردن قفل صفحه کنترل می‌کند، و یا اگر دفعات زیادی گذرواژه اشتباه تایپ شود رایانهٔ لوحی را قفل می‎کند و همه داده‎های رایانهٔ لوحی را پاک می‎کند."</string>
     <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"تعداد گذرواژه‎های نادرست تایپ شده را کنترل می‎کند. هنگام بازکردن قفل صفحه اگر دفعات زیادی گذرواژه نادرست تایپ کرده‎اید، تلفن را قفل کنید یا همه داده‎های تلفن را پاک کنید."</string>
     <string name="policylab_resetPassword" msgid="2620077191242688955">"تغییر رمز ورود قفل گشایی صفحه"</string>
     <string name="policydesc_resetPassword" msgid="605963962301904458">"گذرواژه بازگشایی قفل صفحه را تغییر دهید."</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"قفل کردن صفحه"</string>
     <string name="policydesc_forceLock" msgid="1141797588403827138">"نحوه و زمان قفل شدن صفحه را کنترل کنید."</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"پاک کردن تمام داده‌ها"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"با انجام بازنشانی به داده‌های کارخانه، داده‌های رایانه لوحی بدون هشدار پاک می‌شود."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"با انجام بازنشانی به داده‌های کارخانه، داده‌های رایانهٔ لوحی بدون هشدار پاک می‌شود."</string>
     <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"با انجام بازنشانی به داده‌های کارخانه، داده‌های تلفن بدون هشدار پاک می‌شود."</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"تنظیم پروکسی جهانی دستگاه"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"پروکسی جهانی دستگاه مورد نظر را جهت استفاده هنگام فعال بودن خط مشی تنظیم کنید. فقط اولین سرپرست دستگاه پروکسی جهانی مفید را تنظیم می‌کند."</string>
     <string name="policylab_expirePassword" msgid="885279151847254056">"تنظیم زمان انقضای رمز ورود قفل صفحه"</string>
-    <string name="policydesc_expirePassword" msgid="1729725226314691591">"کنترل کنید چند وقت یکبار باید گذرواژه صفحه قفل عوض شود."</string>
+    <string name="policydesc_expirePassword" msgid="1729725226314691591">"کنترل کنید چند وقت یک بار باید گذرواژه صفحه قفل عوض شود."</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"تنظیم رمزگذاری حافظه"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"باید اطلاعات ذخیره شده برنامه رمزگذاری شود."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"غیر فعال کردن دوربین ها"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"از استفاده از تمام دوربین‎های دستگاه جلوگیری کنید."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"غیرفعال کردن ویژگی‌‌ها در محافظ کلید"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"از استفاده از برخی ویژگی‌ها در محافظ کلید جلوگیری شود."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"خانه"</item>
     <item msgid="869923650527136615">"تلفن همراه"</item>
@@ -699,11 +762,11 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"دوباره امتحان کنید"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"دفعات تلاش برای Face Unlock از حداکثر مجاز بیشتر شد"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"در حال شارژ، <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"شارژ شد."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"شارژ شد"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"شارژر خود را متصل کنید."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"سیم کارت موجود نیست."</string>
-    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"سیم کارت درون رایانه لوحی نیست."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"سیم کارت موجود نیست"</string>
+    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"سیم کارت درون رایانهٔ لوحی نیست."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"سیم کارت درون تلفن نیست."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"سیم کارت را وارد کنید."</string>
     <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"سیم کارت موجود نیست یا قابل خواندن نیست. یک سیم کارت وارد کنید."</string>
@@ -721,13 +784,13 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"سیم کارت قفل شد."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"بازگشایی قفل سیم کارت..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده‎اید. "\n\n"لطفاً پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
-    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"گذرواژه خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه تایپ کرده‌اید. "\n\n"پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"گذرواژهٔ خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه تایپ کرده‌اید. "\n\n"پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"پین را<xliff:g id="NUMBER_0">%d</xliff:g>  بار اشتباه تایپ کرده‎اید. "\n\n"پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده‎اید. بعد از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که برای بازگشایی قفل رایانه لوحی خود به Google وارد شوید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده اید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر از شما خواسته می‎شود که برای بازگشایی قفل گوشی خود به برنامه Google وارد شوید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
-    <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"شما به اشتباه <xliff:g id="NUMBER_0">%d</xliff:g> بار اقدام به باز کردن قفل رایانه لوحی کرده‌اید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر، رایانه لوحی به پیش‌فرض کارخانه بازنشانی می‌شود و تمام داده‌های کاربر از دست خواهد رفت."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده‎اید. بعد از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که برای بازگشایی قفل رایانهٔ لوحی خود به Google وارد شوید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده‌اید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر از شما خواسته می‎شود که برای بازگشایی قفل گوشی خود به برنامهٔ Google وارد شوید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"شما به اشتباه <xliff:g id="NUMBER_0">%d</xliff:g> بار اقدام به باز کردن قفل رایانهٔ لوحی کرده‌اید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر، رایانهٔ لوحی به پیش‌فرض کارخانه بازنشانی می‌شود و تمام داده‌های کاربر از دست خواهد رفت."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"شما به اشتباه <xliff:g id="NUMBER_0">%d</xliff:g> بار اقدام به باز کردن قفل تلفن کرده‌اید. پس از<xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر، تلفن به پیش‌فرض کارخانه بازنشانی می‌شود و تمام داده‌های کاربر از دست خواهد رفت."</string>
-    <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"شما به اشتباه اقدام به باز کردن قفل <xliff:g id="NUMBER">%d</xliff:g> رایانه لوحی کرده‌اید. رایانه لوحی در حال حاضر به پیش‌فرض کارخانه بازنشانی می‌شود."</string>
+    <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"شما به اشتباه اقدام به باز کردن قفل <xliff:g id="NUMBER">%d</xliff:g> رایانهٔ لوحی کرده‌اید. رایانهٔ لوحی در حال حاضر به پیش‌فرض کارخانه بازنشانی می‌شود."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"شما به اشتباه <xliff:g id="NUMBER">%d</xliff:g> بار اقدام به باز کردن قفل تلفن کرده‌اید. این تلفن در حال حاضر به پیش‌فرض کارخانه بازنشانی می‌شود."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"در <xliff:g id="NUMBER">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"الگو را فراموش کرده‌اید؟"</string>
@@ -738,7 +801,7 @@
     <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"رمز ورود"</string>
     <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"ورود به سیستم"</string>
     <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"نام کاربر یا رمز ورود نامعتبر است."</string>
-    <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"نام کاربری یا گذرواژه خود را فراموش کردید؟"\n"از "<b>"google.com/accounts/recovery"</b>" بازدید کنید."</string>
+    <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"نام کاربری یا گذرواژهٔ خود را فراموش کردید؟"\n"از "<b>"google.com/accounts/recovery"</b>" بازدید کنید."</string>
     <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"در حال بررسی..."</string>
     <string name="lockscreen_unlock_label" msgid="737440483220667054">"بازگشایی قفل"</string>
     <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"صدا روشن"</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"الگو پاک شد"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"سلول اضافه شد"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"الگو تکمیل شد"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"ابزارک اضافه کنید."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"خالی"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"منطقه بازگشایی گسترده شد."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"منطقه بازگشایی کوچک شد."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"ابزارک <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"انتخابگر کاربر"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"وضعیت"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"دوربین"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"کنترل‌های رسانه"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"مرتب سازی مجدد ابزارک آغاز شد."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"مرتب‌سازی مجدد ابزارک به پایان رسید."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"ابزارک <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> حذف شد.‍"</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"گسترده کردن منطقه بازگشایی شده."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"باز کردن قفل با کشیدن انگشت روی صفحه."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"باز کردن قفل با الگو."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"باز کردن قفل با چهره."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"باز کردن قفل با پین."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"باز کردن قفل با گذرواژه."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ناحیه الگو."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ناحیه کشیدن انگشت روی صفحه."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -758,8 +841,8 @@
     <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"تست کارخانه انجام نشد"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"عملکرد FACTORY_TEST تنها برای بسته‌های نصب شده در /system/app پشتیبانی می‌شود."</string>
-    <string name="factorytest_no_action" msgid="872991874799998561">"بسته ای یافت نشد که عملکرد FACTORY_TEST را ارائه کند."</string>
-    <string name="factorytest_reboot" msgid="6320168203050791643">"راه اندازی مجدد"</string>
+    <string name="factorytest_no_action" msgid="872991874799998561">"بسته‌ای یافت نشد که عملکرد FACTORY_TEST را ارائه کند."</string>
+    <string name="factorytest_reboot" msgid="6320168203050791643">"راه‌اندازی مجدد"</string>
     <string name="js_dialog_title" msgid="1987483977834603872">"صفحه در \"<xliff:g id="TITLE">%s</xliff:g>\" می‎گوید:"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"جاوا اسکریپت"</string>
     <string name="js_dialog_before_unload" msgid="730366588032430474">"از این صفحه خارج می‎شوید؟"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"برای ادامه روی تأیید و برای ماندن در همین صفحه روی لغو کلیک کنید."</string>
@@ -786,7 +869,7 @@
     <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"خواندن سابقه و نشانک‌های وب شما"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"به برنامه اجازه می‌دهد سابقه نشانی‌های اینترنتی را که مرورگر بازدید کرده است و همه نشانک‌های مرورگر را بخواند. توجه: این مجوز توسط مرورگرهای شخص ثالث یا سایر برنامه‌های دارای قابلیت مرور وب قابل اجرا نیست."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"نوشتن نشانک‌های وب و سابقه"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"به برنامه اجازه می‌دهد سابقه مرورگر یا نشانک‌های ذخیره شده در رایانه لوحی شما را اصلاح کند. این ویژگی ممکن است به برنامه اجازه دهد داده‌های مرورگر را حذف یا اصلاح کند. توجه: این مجوز ممکن است توسط مرورگرهای شخص ثالث یا سایر برنامه‌های دارای قابلیت مرور وب قابل اجرا نباشد."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"به برنامه اجازه می‌دهد سابقه مرورگر یا نشانک‌های ذخیره شده در رایانهٔ لوحی شما را اصلاح کند. این ویژگی ممکن است به برنامه اجازه دهد داده‌های مرورگر را حذف یا اصلاح کند. توجه: این مجوز ممکن است توسط مرورگرهای شخص ثالث یا سایر برنامه‌های دارای قابلیت مرور وب قابل اجرا نباشد."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"به برنامه اجازه می‌دهد سابقه مرورگر یا نشانک‌های ذخیره شده در تلفن شما را اصلاح کند. این ویژگی ممکن است به برنامه اجازه دهد داده‌های مرورگر را حذف یا اصلاح کند. توجه: این مجوز ممکن است توسط مرورگرهای شخص ثالث یا سایر برنامه‌های دارای قابلیت مرور وب قابل اجرا نباشد."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"تنظیم یک هشدار"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"به برنامه اجازه می‎دهد تا هشداری را در برنامه ساعت زنگدار نصب شده تنظیم کند. برخی از برنامه‎های ساعت زنگدار نمی‎توانند این ویژگی را اعمال کنند."</string>
@@ -822,7 +905,7 @@
     <string name="searchview_description_submit" msgid="2688450133297983542">"ارسال عبارت جستجو"</string>
     <string name="searchview_description_voice" msgid="2453203695674994440">"جستجوی صوتی"</string>
     <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"فعال کردن «کاوش با لمس»؟"</string>
-    <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> می‌خواهد «کاوش با لمس» را فعال کند. وقتی «کاوش با لمس» فعال است، می‌توانید توضیحاتی را برای آنچه که زیر انگشت شما است مشاهده کرده یا بشنوید یا برای استفاده از رایانه لوحی از حرکات اشاره استفاده کنید."</string>
+    <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> می‌خواهد «کاوش با لمس» را فعال کند. وقتی «کاوش با لمس» فعال است، می‌توانید توضیحاتی را برای آنچه که زیر انگشت شما است مشاهده کرده یا بشنوید یا برای استفاده از رایانهٔ لوحی از حرکات اشاره استفاده کنید."</string>
     <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> می‌خواهد «کاوش با لمس» را فعال کند. وقتی «کاوش با لمس» فعال است، می‌توانید توضیحاتی را برای آنچه که زیر انگشت شما است مشاهده کرده یا بشنوید یا برای استفاده از تلفن خود از حرکات اشاره استفاده کنید."</string>
     <string name="oneMonthDurationPast" msgid="7396384508953779925">"۱ ماه قبل"</string>
     <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"قبل از ۱ ماه گذشته"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"کپی URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"انتخاب متن"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"انتخاب متن"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"افزودن به فرهنگ لغت"</string>
-    <string name="deleteText" msgid="7070985395199629156">"حذف"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"افزودن به فرهنگ‌لغت"</string>
+    <string name="deleteText" msgid="6979668428458199034">"حذف"</string>
     <string name="inputMethod" msgid="1653630062304567879">"روش ورودی"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"عملکردهای متنی"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"فضای ذخیره‌سازی رو به اتمام است"</string>
@@ -964,15 +1047,15 @@
     <string name="webpage_unresponsive" msgid="3272758351138122503">"این صفحه پاسخ نمی‌دهد."\n\n"آیا می‌خواهید آن را ببندید؟"</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="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="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_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_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>
@@ -986,7 +1069,7 @@
     <string name="volume_ringtone" msgid="6885421406845734650">"میزان صدای زنگ"</string>
     <string name="volume_music" msgid="5421651157138628171">"میزان صدای رسانه"</string>
     <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"پخش از طریق بلوتوث"</string>
-    <string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"آهنگ زنگ روی بیصدا تنظیم شد"</string>
+    <string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"آهنگ زنگ روی بی‌صدا تنظیم شد"</string>
     <string name="volume_call" msgid="3941680041282788711">"میزان صدای هنگام تماس"</string>
     <string name="volume_bluetooth_call" msgid="2002891926351151534">"میزان صدای تماس بلوتوث"</string>
     <string name="volume_alarm" msgid="1985191616042689100">"میزان صدای هشدار"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"شبکه‌های Wi-Fi موجود را باز کنید"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"ورود به شبکه Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"ورود به شبکه"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"اتصال به Wi-Fi ممکن نیست"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" اتصال اینترنتی ضعیفی دارد."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"به:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"پین لازم را تایپ کنید:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"پین:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"این گوشی به‌طور موقت از Wi-Fi قطع خواهد شد، در حالی که به <xliff:g id="DEVICE_NAME">%1$s</xliff:g> وصل است"</string>
     <string name="select_character" msgid="3365550120617701745">"درج نویسه"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"ارسال پیامک ها"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; در حال ارسال تعداد زیادی پیامک است. آیا اجازه می‌دهید این برنامه همچنان پیامک ارسال کند؟"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"اجازه دادن"</string>
     <string name="sms_control_no" msgid="625438561395534982">"ردکردن"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; مایل است پیامی به &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; ارسال کند."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"این کار "<font fgcolor="#ffffb060">"می‌تواند منجر به شارژ"</font>" حساب تلفن همراه شما شود."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"این کار حساب تلفن همراه شما را شارژ خواهد کرد."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"ارسال"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"لغو"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"این انتخاب را به خاطر بسپار"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"می‌توانید بعداً آن را در تنظیمات &gt; برنامه‌ها تغییر دهید"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"همیشه مجاز"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"همیشه غیرمجاز"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"سیم کارت برداشته شد"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"تا وقتی که با یک سیم‌کارت معتبر راه‌اندازی مجدد نکنید شبکه تلفن همراه غیر قابل‌ دسترس خواهد بود."</string>
     <string name="sim_done_button" msgid="827949989369963775">"انجام شد"</string>
@@ -1043,25 +1137,23 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"تاریخ تنظیم"</string>
     <string name="date_time_set" msgid="5777075614321087758">"تنظیم"</string>
     <string name="date_time_done" msgid="2507683751759308828">"انجام شد"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"پیش‌فرض"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"مجوزی لازم نیست"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"پنهان کردن"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"نمایش همه"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"جدید: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"جدید: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"ارائه شده توسط <xliff:g id="APP_NAME">%1$s</xliff:g> ."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"مجوزی لازم نیست"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"ممکن است برای شما هزینه داشته باشد"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"حافظه انبوه USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB متصل شد"</string>
-    <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"شما از طریق USB به رایانه خود متصل شده‎اید. اگر می‎خواهید فایل‎ها را بین رایانه خود و حافظهٔ USB در Android کپی کنید، دکمه زیر را لمس کنید."</string>
-    <string name="usb_storage_message" product="default" msgid="805351000446037811">"شما از طریق USB به رایانه خود متصل شده‎اید. اگر می‎خواهید فایل‎ها را بین رایانه خود و کارت SD در Android کپی کنید، دکمه زیر را لمس کنید."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"شما از طریق USB به رایانهٔ خود متصل شده‎اید. اگر می‎خواهید فایل‎ها را بین رایانهٔ خود و حافظهٔ USB در Android کپی کنید، دکمه زیر را لمس کنید."</string>
+    <string name="usb_storage_message" product="default" msgid="805351000446037811">"شما از طریق USB به رایانهٔ خود متصل شده‎اید. اگر می‎خواهید فایل‎ها را بین رایانهٔ خود و کارت SD در Android کپی کنید، دکمه زیر را لمس کنید."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"روشن کردن دستگاه ذخیره‌سازی USB"</string>
     <string name="usb_storage_error_message" product="nosdcard" msgid="3017045217365540658">"هنگام استفاده از حافظهٔ USB برای حافظه انبوه USB مشکلی بوجود آمد."</string>
     <string name="usb_storage_error_message" product="default" msgid="2876018512716970313">"هنگام استفاده از کارت SD برای حافظه ذخیره انبوه USB مشکلی بوجود آمد."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB متصل شد"</string>
-    <string name="usb_storage_notification_message" msgid="939822783828183763">"برای کپی کردن فایل‌ها از/به رایانه خود لمس کنید."</string>
+    <string name="usb_storage_notification_message" msgid="939822783828183763">"برای کپی کردن فایل‌ها از/به رایانهٔ خود لمس کنید."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"خاموش کردن دستگاه ذخیره‌سازی USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="1656852098555623822">"برای غیرفعال کردن حافظهٔ USB، لمس کنید."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"دستگاه ذخیره‌سازی USB در حال استفاده است"</string>
-    <string name="usb_storage_stop_message" product="nosdcard" msgid="4264025280777219521">"قبل از غیرفعال کردن حافظهٔ USB، حافظهٔ USB مربوط به Android را در رایانه خود لغو نصب کنید (\"خارج کنید\")."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="4264025280777219521">"قبل از غیرفعال کردن حافظهٔ USB، حافظهٔ USB مربوط به Android را در رایانهٔ خود لغو نصب کنید (\"خارج کنید\")."</string>
     <string name="usb_storage_stop_message" product="default" msgid="8043969782460613114">"قبل از غیرفعال کردن حافظهٔ USB، کارت SD مربوط به Android را در رایانه لغو نصب کنید (\"خارج کنید\")."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"خاموش کردن دستگاه ذخیره‌سازی USB"</string>
     <string name="usb_storage_stop_error_message" msgid="1970374898263063836">"هنگام غیرفعال کردن حافظهٔ USB مشکلی بوجود آمد. بررسی کنید میزبان USB را لغو نصب کرده باشید، سپس دوباره امتحان کنید."</string>
@@ -1069,9 +1161,9 @@
     <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>
-    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"متصل شده به عنوان دوربین"</string>
-    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"متصل شده به عنوان نصب کننده"</string>
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"متصل شده به‌عنوان دستگاه رسانه‌ای"</string>
+    <string name="usb_ptp_notification_title" msgid="1960817192216064833">"متصل شده به‌عنوان دوربین"</string>
+    <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"متصل شده به‌عنوان نصب کننده"</string>
     <string name="usb_accessory_notification_title" msgid="7848236974087653666">"به یک وسیله جانبی USB وصل شده است"</string>
     <string name="usb_notification_message" msgid="2290859399983720271">"برای سایر گزینه‌های USB لمس کنید."</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="9020092196061007262">"حافظهٔ USB فرمت شود؟"</string>
@@ -1083,10 +1175,10 @@
     <string name="adb_active_notification_message" msgid="1016654627626476142">"برای غیرفعال کردن اشکال زدایی USB لمس کنید."</string>
     <string name="select_input_method" msgid="4653387336791222978">"انتخاب روش ورودی"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"تنظیم روش‌های ورودی"</string>
-    <string name="use_physical_keyboard" msgid="6203112478095117625">"صفحه کلید فیزیکی"</string>
+    <string name="use_physical_keyboard" msgid="6203112478095117625">"صفحه‌کلید فیزیکی"</string>
     <string name="hardware" msgid="7517821086888990278">"سخت‌افزار"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"انتخاب طرح‌بندی صفحه کلید"</string>
-    <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"برای انتخاب یک طرح‌بندی صفحه کلید لمس کنید…"</string>
+    <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"انتخاب طرح‌بندی صفحه‌کلید"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"برای انتخاب یک طرح‌بندی صفحه‌کلید لمس کنید…"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"داوطلبین"</u></string>
@@ -1101,8 +1193,8 @@
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"کارت SD آسیب دیده"</string>
     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="1795917578395333280">"حافظهٔ USB خراب است. سعی کنید آنرا دوباره فرمت کنید."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="1753898567525568253">"کارت SD خراب است. سعی کنید آنرا دوباره فرمت کنید."</string>
-    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"حافظهٔ USB به صورت غیر منتظره جدا شد"</string>
-    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"کارت SD به صورت غیر منتظره ای جدا شد"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"حافظهٔ USB به صورت غیرمنتظره جدا شد"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"کارت SD به صورت غیرمنتظره‌ای جدا شد"</string>
     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"اتصال حافظهٔ USB را قبل از بیرون آوردن قطع کنید تا سبب از بین رفتن داده‌ها نشود."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"کارت SD را قبل از بیرون آوردن جدا کنید تا سبب از بین رفتن داده‌ها نشود."</string>
     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"حافظهٔ USB را می‌توانید با ایمنی جدا کنید"</string>
@@ -1139,7 +1231,7 @@
     <string name="permission_request_notification_title" msgid="6486759795926237907">"مجوز درخواست شد"</string>
     <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"مجوز"\n"برای حساب <xliff:g id="ACCOUNT">%s</xliff:g> درخواست شد."</string>
     <string name="input_method_binding_label" msgid="1283557179944992649">"روش ورودی"</string>
-    <string name="sync_binding_label" msgid="3687969138375092423">"همگام سازی"</string>
+    <string name="sync_binding_label" msgid="3687969138375092423">"همگام‌سازی"</string>
     <string name="accessibility_binding_label" msgid="4148120742096474641">"قابلیت دسترسی"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"تصویر زمینه"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"تغییر تصویر زمینه"</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN توسط <xliff:g id="APP">%s</xliff:g> فعال شده است"</string>
     <string name="vpn_text" msgid="3011306607126450322">"برای مدیریت شبکه لمس کنید."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"به <xliff:g id="SESSION">%s</xliff:g> وصل شد. برای مدیریت شبکه لمس کنید."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"در حال اتصال VPN همیشه فعال…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN همیشه فعال متصل شد"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"خطای VPN همیشه فعال"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"برای بازنشانی اتصال لمس کنید"</string>
     <string name="upload_file" msgid="2897957172366730416">"انتخاب فایل"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"هیچ فایلی انتخاب نشد"</string>
     <string name="reset" msgid="2448168080964209908">"بازنشانی"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"اشتراک‌گذاری"</string>
     <string name="find" msgid="4808270900322985960">"یافتن"</string>
     <string name="websearch" msgid="4337157977400211589">"جستجوی وب"</string>
+    <string name="find_next" msgid="5742124618942193978">"یافتن بعدی"</string>
+    <string name="find_previous" msgid="2196723669388360506">"یافتن قبلی"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"درخواست موقعیت مکانی از <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"درخواست موقعیت مکانی"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"درخواست شده توسط <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1272,7 +1370,7 @@
     <string name="fingerprints" msgid="4516019619850763049">"اثر انگشت:"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"اثر انگشت SHA-256:"</string>
     <string name="sha1_fingerprint" msgid="7930330235269404581">"اثر انگشت SHA-1"</string>
-    <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"مشاهده همه"</string>
+    <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"مشاهدهٔ همه"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"انتخاب فعالیت"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"اشتراک‌گذاری با"</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"دستگاه قفل است."</string>
@@ -1282,12 +1380,68 @@
     <string name="SetupCallDefault" msgid="5834948469253758575">"تماس را می‌پذیرید؟"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"همیشه"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"فقط این بار"</string>
-    <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"رایانه لوحی"</string>
+    <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"رایانهٔ لوحی"</string>
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"تلفن"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"هدفون‌ها"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"بلندگوهای جایگاه اتصال"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"صدای HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"سیستم"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"بلوتوث‌های صوتی"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"انجام شد"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"خروجی رسانه"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"در حال اسکن کردن…"</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"درحال اتصال…"</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"در دسترس"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"در دسترس نیست"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"صفحه نمایش از خود"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"صفحه HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"همپوشانی #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"نمایشگر بی‌سیم متصل است"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"این صفحه در حال نمایش در دستگاه دیگری است"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"قطع اتصال"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"تماس اضطراری"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"الگو را فراموش کرده‌اید"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"الگوی اشتباه"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"گذرواژه اشتباه"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"پین اشتباه"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"پس از <xliff:g id="NUMBER">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"الگوی خود را رسم کنید"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"پین سیم کارت را وارد کنید"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"پین را وارد کنید"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"گذرواژه را وارد کنید"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"اکنون سیم کارت غیرفعال است. پین کد را برای ادامه وارد کنید. برای جزئیات با شرکت مخابراتی خود تماس بگیرید."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"پین کد دلخواه را وارد کنید"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"تأیید پین کد دلخواه"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"بازگشایی قفل سیم کارت..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"پین کد اشتباه است."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"یک پین ۴ تا ۸ رقمی را تایپ کنید."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"پین کد باید ۸ عدد یا بیشتر باشد."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"پین کد صحیح را دوباره وارد کنید. تلاش‌های مکرر به‌طور دائم سیم کارت را غیرفعال خواهد کرد."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"پین کدها منطبق نیستند"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"تلاش‎های زیادی برای کشیدن الگو صورت گرفته است"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"برای بازگشایی قفل، با حساب Google خود وارد سیستم شوید."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"نام کاربری (ایمیل)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"گذرواژه"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"ورود به سیستم"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"نام کاربری یا گذرواژه نامعتبر."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"نام کاربری یا گذرواژه خود را فراموش کردید؟"\n"از "<b>"google.com/accounts/recovery"</b>" بازدید کنید."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"درحال بررسی حساب..."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"پین خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه تایپ کردید. "\n\n"پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"گذرواژه خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه تایپ کردید. "\n\n"پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیدید. "\n\n"لطفاً پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"شما به اشتباه <xliff:g id="NUMBER_0">%d</xliff:g> بار اقدام به باز کردن قفل رایانه لوحی کرده‌اید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر، رایانهٔ لوحی به پیش‌فرض کارخانه بازنشانی می‌شود و تمام داده‌های کاربر از دست خواهد رفت."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"شما به اشتباه <xliff:g id="NUMBER_0">%d</xliff:g> بار اقدام به باز کردن قفل تلفن کرده‌اید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر، تلفن به پیش‌فرض کارخانه بازنشانی می‌شود و تمام داده‌های کاربر از دست خواهد رفت."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"شما به اشتباه <xliff:g id="NUMBER">%d</xliff:g> بار اقدام به باز کردن قفل رایانه لوحی کرده‌اید. رایانه لوحی اکنون به پیش‌فرض کارخانه بازنشانی می‌شود."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"شما به اشتباه <xliff:g id="NUMBER">%d</xliff:g> بار اقدام به باز کردن قفل تلفن کرده‌اید. این تلفن اکنون به پیش‌فرض کارخانه بازنشانی می‌شود."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده‎اید. بعد از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که با استفاده از یک حساب ایمیل قفل رایانه لوحی خود را باز کنید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده‌اید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که با استفاده از یک حساب ایمیل قفل تلفن خود را باز کنید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"برداشتن"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"صدا به بالاتر از سطح ایمن افزایش یابد؟"\n"گوش دادن به صدای بلند برای زمان‌های طولانی می‌تواند به شنوایی شما آسیب برساند."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"برای فعال کردن قابلیت دسترسی، با دو انگشت خود همچنان به طرف پایین فشار دهید."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"قابلیت دسترسی فعال شد."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"قابلیت دسترسی لغو شد."</string>
+    <string name="user_switched" msgid="3768006783166984410">"کاربر کنونی <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"دارنده"</string>
 </resources>
diff --git a/core/res/res/values-fi-rFI/donottranslate-cldr.xml b/core/res/res/values-fi-rFI/donottranslate-cldr.xml
index e9e1a25..04f0a77 100644
--- a/core/res/res/values-fi-rFI/donottranslate-cldr.xml
+++ b/core/res/res/values-fi-rFI/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">tammikuu</string>
-    <string name="month_long_standalone_february">helmikuu</string>
-    <string name="month_long_standalone_march">maaliskuu</string>
-    <string name="month_long_standalone_april">huhtikuu</string>
-    <string name="month_long_standalone_may">toukokuu</string>
-    <string name="month_long_standalone_june">kesäkuu</string>
-    <string name="month_long_standalone_july">heinäkuu</string>
-    <string name="month_long_standalone_august">elokuu</string>
-    <string name="month_long_standalone_september">syyskuu</string>
-    <string name="month_long_standalone_october">lokakuu</string>
-    <string name="month_long_standalone_november">marraskuu</string>
-    <string name="month_long_standalone_december">joulukuu</string>
-
-    <string name="month_long_january">tammikuuta</string>
-    <string name="month_long_february">helmikuuta</string>
-    <string name="month_long_march">maaliskuuta</string>
-    <string name="month_long_april">huhtikuuta</string>
-    <string name="month_long_may">toukokuuta</string>
-    <string name="month_long_june">kesäkuuta</string>
-    <string name="month_long_july">heinäkuuta</string>
-    <string name="month_long_august">elokuuta</string>
-    <string name="month_long_september">syyskuuta</string>
-    <string name="month_long_october">lokakuuta</string>
-    <string name="month_long_november">marraskuuta</string>
-    <string name="month_long_december">joulukuuta</string>
-
-    <string name="month_medium_january">tammikuuta</string>
-    <string name="month_medium_february">helmikuuta</string>
-    <string name="month_medium_march">maaliskuuta</string>
-    <string name="month_medium_april">huhtikuuta</string>
-    <string name="month_medium_may">toukokuuta</string>
-    <string name="month_medium_june">kesäkuuta</string>
-    <string name="month_medium_july">heinäkuuta</string>
-    <string name="month_medium_august">elokuuta</string>
-    <string name="month_medium_september">syyskuuta</string>
-    <string name="month_medium_october">lokakuuta</string>
-    <string name="month_medium_november">marraskuuta</string>
-    <string name="month_medium_december">joulukuuta</string>
-
-    <string name="month_shortest_january">T</string>
-    <string name="month_shortest_february">H</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">H</string>
-    <string name="month_shortest_may">T</string>
-    <string name="month_shortest_june">K</string>
-    <string name="month_shortest_july">H</string>
-    <string name="month_shortest_august">E</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">L</string>
-    <string name="month_shortest_november">M</string>
-    <string name="month_shortest_december">J</string>
-
-    <string name="day_of_week_long_sunday">sunnuntai</string>
-    <string name="day_of_week_long_monday">maanantai</string>
-    <string name="day_of_week_long_tuesday">tiistai</string>
-    <string name="day_of_week_long_wednesday">keskiviikko</string>
-    <string name="day_of_week_long_thursday">torstai</string>
-    <string name="day_of_week_long_friday">perjantai</string>
-    <string name="day_of_week_long_saturday">lauantai</string>
-
-    <string name="day_of_week_medium_sunday">su</string>
-    <string name="day_of_week_medium_monday">ma</string>
-    <string name="day_of_week_medium_tuesday">ti</string>
-    <string name="day_of_week_medium_wednesday">ke</string>
-    <string name="day_of_week_medium_thursday">to</string>
-    <string name="day_of_week_medium_friday">pe</string>
-    <string name="day_of_week_medium_saturday">la</string>
-
-    <string name="day_of_week_short_sunday">su</string>
-    <string name="day_of_week_short_monday">ma</string>
-    <string name="day_of_week_short_tuesday">ti</string>
-    <string name="day_of_week_short_wednesday">ke</string>
-    <string name="day_of_week_short_thursday">to</string>
-    <string name="day_of_week_short_friday">pe</string>
-    <string name="day_of_week_short_saturday">la</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">K</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">P</string>
-    <string name="day_of_week_shortest_saturday">L</string>
-
-    <string name="am">ap.</string>
-    <string name="pm">ip.</string>
-    <string name="yesterday">eilen</string>
-    <string name="today">tänään</string>
-    <string name="tomorrow">huomenna</string>
-
     <string name="hour_minute_24">%-k.%M</string>
     <string name="hour_minute_ampm">%-l.%M %p</string>
     <string name="hour_minute_cap_ampm">%-l.%M %^p</string>
diff --git a/core/res/res/values-fi/donottranslate-cldr.xml b/core/res/res/values-fi/donottranslate-cldr.xml
index 71cccf3..543595f 100644
--- a/core/res/res/values-fi/donottranslate-cldr.xml
+++ b/core/res/res/values-fi/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">tammikuu</string>
-    <string name="month_long_standalone_february">helmikuu</string>
-    <string name="month_long_standalone_march">maaliskuu</string>
-    <string name="month_long_standalone_april">huhtikuu</string>
-    <string name="month_long_standalone_may">toukokuu</string>
-    <string name="month_long_standalone_june">kesäkuu</string>
-    <string name="month_long_standalone_july">heinäkuu</string>
-    <string name="month_long_standalone_august">elokuu</string>
-    <string name="month_long_standalone_september">syyskuu</string>
-    <string name="month_long_standalone_october">lokakuu</string>
-    <string name="month_long_standalone_november">marraskuu</string>
-    <string name="month_long_standalone_december">joulukuu</string>
-
-    <string name="month_long_january">tammikuuta</string>
-    <string name="month_long_february">helmikuuta</string>
-    <string name="month_long_march">maaliskuuta</string>
-    <string name="month_long_april">huhtikuuta</string>
-    <string name="month_long_may">toukokuuta</string>
-    <string name="month_long_june">kesäkuuta</string>
-    <string name="month_long_july">heinäkuuta</string>
-    <string name="month_long_august">elokuuta</string>
-    <string name="month_long_september">syyskuuta</string>
-    <string name="month_long_october">lokakuuta</string>
-    <string name="month_long_november">marraskuuta</string>
-    <string name="month_long_december">joulukuuta</string>
-
-    <string name="month_medium_january">tammikuuta</string>
-    <string name="month_medium_february">helmikuuta</string>
-    <string name="month_medium_march">maaliskuuta</string>
-    <string name="month_medium_april">huhtikuuta</string>
-    <string name="month_medium_may">toukokuuta</string>
-    <string name="month_medium_june">kesäkuuta</string>
-    <string name="month_medium_july">heinäkuuta</string>
-    <string name="month_medium_august">elokuuta</string>
-    <string name="month_medium_september">syyskuuta</string>
-    <string name="month_medium_october">lokakuuta</string>
-    <string name="month_medium_november">marraskuuta</string>
-    <string name="month_medium_december">joulukuuta</string>
-
-    <string name="month_shortest_january">T</string>
-    <string name="month_shortest_february">H</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">H</string>
-    <string name="month_shortest_may">T</string>
-    <string name="month_shortest_june">K</string>
-    <string name="month_shortest_july">H</string>
-    <string name="month_shortest_august">E</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">L</string>
-    <string name="month_shortest_november">M</string>
-    <string name="month_shortest_december">J</string>
-
-    <string name="day_of_week_long_sunday">sunnuntaina</string>
-    <string name="day_of_week_long_monday">maanantaina</string>
-    <string name="day_of_week_long_tuesday">tiistaina</string>
-    <string name="day_of_week_long_wednesday">keskiviikkona</string>
-    <string name="day_of_week_long_thursday">torstaina</string>
-    <string name="day_of_week_long_friday">perjantaina</string>
-    <string name="day_of_week_long_saturday">lauantaina</string>
-
-    <string name="day_of_week_medium_sunday">su</string>
-    <string name="day_of_week_medium_monday">ma</string>
-    <string name="day_of_week_medium_tuesday">ti</string>
-    <string name="day_of_week_medium_wednesday">ke</string>
-    <string name="day_of_week_medium_thursday">to</string>
-    <string name="day_of_week_medium_friday">pe</string>
-    <string name="day_of_week_medium_saturday">la</string>
-
-    <string name="day_of_week_short_sunday">su</string>
-    <string name="day_of_week_short_monday">ma</string>
-    <string name="day_of_week_short_tuesday">ti</string>
-    <string name="day_of_week_short_wednesday">ke</string>
-    <string name="day_of_week_short_thursday">to</string>
-    <string name="day_of_week_short_friday">pe</string>
-    <string name="day_of_week_short_saturday">la</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">K</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">P</string>
-    <string name="day_of_week_shortest_saturday">L</string>
-
-    <string name="am">ap.</string>
-    <string name="pm">ip.</string>
-    <string name="yesterday">eilen</string>
-    <string name="today">tänään</string>
-    <string name="tomorrow">huomenna</string>
-
     <string name="hour_minute_24">%-k.%M</string>
     <string name="hour_minute_ampm">%-l.%M %p</string>
     <string name="hour_minute_cap_ampm">%-l.%M %^p</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index bd28a20..2b08bea 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Puhelimen asetukset"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Näytön lukitus"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Katkaise virta"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Virheraportti"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Luo virheraportti"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Toiminto kerää tietoja nykyisestä laitteen tilasta ja lähettää ne sähköpostitse. Kestää hetken aikaa, ennen kuin virheraportti on valmis lähetettäväksi, ole kärsivällinen."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Äänetön tila"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Äänet ovat POISSA KÄYTÖSTÄ"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Äänet ovat KÄYTÖSSÄ"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Omat viestit"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Tekstiviestien, sähköpostin ja muiden viestien lukeminen ja kirjoittaminen."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Henkilötietosi"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Käyttöoikeudet tablet-laitteelle tallennettuihin yhteystietoihin ja kalenteriin."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Saa suora käyttöyhteys puhelimelle tallennettuihin yhteystietoihin ja kalenteriin."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Yhteystietokorttiisi tallennettujen tietojesi käyttöoikeus."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Sosiaaliset tietosi"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Kontaktiesi ja internet-kontaktiesi tietojen käyttöoikeus."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Oma sijainti"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Tarkkaile fyysistä sijaintiasi."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Verkkoviestintä"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Käyttää useita ​​verkon ominaisuuksia."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Käytä laitteita ja verkkoja Bluetooth-yhteyden kautta."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Ääniasetukset"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Muuta ääniasetuksia."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Vaikuttaa akun kestoon"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Käytä ominaisuuksia, jotka voivat tyhjentää akun nopeasti."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalenteri"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Kalenterin ja tapahtumien käyttöoikeus."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Lue käyttäjän sanakirjaa"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Lue sanoja käyttäjän sanakirjasta."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Kirjoita käyttäjän sanakirjaan"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Lisää sanoja käyttäjän sanakirjaan."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Kirjanmerkit ja historia"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Kirjanmerkkien ja selaimen historian käyttöoikeus."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Herätys"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Aseta herätysaika."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Vastaaja"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Vastaajan käyttöoikeus."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofoni"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Äänen tallentamiseen käytettävän mikrofonin käyttöoikeus."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Kuvien tai videon tallentamiseen käytettävän kameran käyttöoikeus."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Sovelluksiesi tiedot"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Mahdollisuus vaikuttaa muiden laitteen sovelluksien käytökseen."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Taustakuva"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Muuta laitteen taustakuvan asetuksia."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Kello"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Muuta laitteen aikaa tai aikavyöhykettä."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Tilapalkki"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Muuta laitteen tilarivin asetuksia."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Synkronointiasetukset"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Synkronointiasetuksien käyttöoikeus."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Omat tilit"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Käytä saatavilla olevia tilejä."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Laitteiston hallinta"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Alemman tason käyttöoikeus ja järjestelmän hallintaoikeus."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Kehittäjätyökalut"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Vain sovelluskehittäjien tarvitsemat ominaisuudet."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Muiden sovelluksien käyttöliittymät"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Vaikuta muiden sovelluksien käyttöliittymään."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Tallennustila"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Käytä USB-tallennustilaa."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Käytä SD-korttia."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Antaa sovelluksen vastaanottaa ja käsitellä WAP-viestejä. Sovellus voi valvoa tai poistaa laitteeseesi lähetettyjä viestejä näyttämättä niitä sinulle."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"käynnissä olevien sovellusten noutaminen"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Antaa sovelluksen noutaa tietoja käynnissä olevista ja äskettäin suoritetuista tehtävistä. Sovellus voi saada tietoja laitteella käytetyistä sovelluksista."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"suorita käyttäjien välisiä toimintoja"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Antaa sovelluksen suorittaa käyttäjien välisiä toimintoja laitteessa. Haitalliset sovellukset voivat vahingoittaa käyttäjien välistä suojausta."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"lupa suorittaa käyttäjien välisiä toimintoja"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Sallii kaikki käyttäjien väliset toiminnot."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"hallinnoi käyttäjiä"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Antaa sovelluksien hallinnoida laitteen käyttäjiä esim. hakemalla, luomalla tai poistamalla käyttäjiä."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"hae tiedot suoritettavista sovelluksista"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Antaa sovellukselle oikeuden noutaa käynnissä oleviin ja käynnissä olleisiin tehtäviin liittyviä tietoja. Haitalliset sovellukset saattavat saada näin muihin sovelluksiin liittyviä yksityisiä tietoja."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"käynnissä olevien sovellusten järjesteleminen"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Antaa sovelluksen noutaa järjestelmän sisäisen tilan. Haitalliset sovellukset voivat noutaa paljon yksityisiä ja suojattuja tietoja, joita niiden ei pitäisi tarvita normaalisti."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"nouda näytön sisältö"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Antaa sovelluksen noutaa aktiivisen ikkunan sisällön. Haitalliset sovellukset voivat noutaa koko ikkunan sisällön ja tarkastella sen kaikkea tekstiä lukuun ottamatta salasanoja."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ota esteettömyystila käyttöön väliaikaisesti"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Antaa sovelluksen ottaa esteettömyystilan käyttöön laitteessa väliaikaisesti. Haitalliset sovellukset voivat ottaa esteettömyystilan käyttöön ilman käyttäjän lupaa."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"nouda ikkunoiden tietoja"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Antaa sovelluksen noutaa ikkunoiden tietoja ikkunanhallinnasta. Haitalliset sovellukset voivat noutaa tietoja, jotka on tarkoitettu järjestelmän sisäiseen käyttöön."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"suodata tapahtumat"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Antaa sovelluksen rekisteröidä syöttösuodattimen, joka suodattaa kaikkien käyttäjätapahtumien streamin ennen tapahtumien näyttämistä. Haitalliset sovellukset voivat hallita järjestelmän käyttöliittymää ilman käyttäjän lupaa."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"suurenna ruutu"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Antaa sovelluksen suurentaa ruudun sisällön. Haitalliset sovellukset voivat muuttaa näytettävää sisältöä siten, ettei laitetta enää voi käyttää."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"sulje puhelin osittain"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Asettaa toimintojen hallinnan sulkeutumistilaan. Ei sulje puhelinta kokonaan."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"estä sovellusten vaihto"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Antaa sovelluksen hallita suoritettavien sovellusten enimmäismäärää. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"pakota taustasovelluksia sulkeutumaan"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Antaa sovelluksen hallita, suoritetaanko toiminnot aina loppuun heti, kun ne siirtyvät taustalle. Ei tavallisten sovellusten käyttöön."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"muokkaa akun tilastoja"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Antaa sovelluksen muokata kerättyjä akkutilastoja. Ei tavallisten sovellusten käyttöön."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"lue akkutilastoja"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Antaa sovelluksen lukea nykyisiä alhaisen tason akunkäyttötietoja. Sovellus saattaa saada tietoonsa, mitä sovelluksia käytät."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"muokkaa akkutilastoja"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Antaa sovelluksen muokata kerättyjä akkutilastoja. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_backup" msgid="470013022865453920">"hallitse järjestelmän varmuuskopiointia ja palauttamista"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Antaa sovelluksen hallita järjestelmän varmuuskopiointi- ja palautusmekanismia. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"vahvista täysi varmuuskopiointi tai palauta toiminto"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"näytä luvattomia ikkunoita"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Antaa sovelluksen luoda ikkunoita, jotka on tarkoitettu sisäisen järjestelmäkäyttöliittymän käytettäviksi. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"piirrä muihin sovelluksiin"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Antaa sovelluksen näyttää järjestelmäilmoitusikkunoita. Jotkut ilmoitusikkunat voivat olla koko ruudun kokoisia."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Antaa sovelluksen piirtää muiden sovelluksien tai niiden käyttöliittymän osien päälle. Luvan saaneet sovellukset voivat häiritä muiden sovelluksien käyttöliittymien käyttöä tai muuttaa muiden sovelluksien osiksi luulemiasi näkymiä."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"muokkaa yleistä animaationopeutta"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Antaa sovelluksen muuttaa yleistä animaationopeutta (nopeuttaa tai hidastaa animaatioita) milloin tahansa."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"sovellustunnusten hallinta"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Antaa sovelluksen luoda ja hallinnoida omia tunnuksia ohittaen tavallisen Z-järjestyksen. Ei tavallisten sovellusten käyttöön."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"pysäytä ruutu"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Antaa sovelluksen pysäyttää ruudun väliaikaisesti siirtyäkseen koko ruudun tilaan."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"painaa näppäimiä ja hallintapainikkeita"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Antaa sovelluksen käyttää omia syötteitään (kuten näppäinpainalluksia) muissa sovelluksissa. Haitalliset sovellukset voivat ottaa tällä tablet-laitteen haltuun."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Antaa sovelluksen käyttää omia syötteitään (kuten näppäinpainalluksia) muissa sovelluksissa. Haitalliset sovellukset voivat ottaa tällä puhelimen haltuun."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"sovellusten asentaminen suoraan"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Antaa sovelluksen asentaa uusia tai päivitettyjä Android-paketteja. Haitalliset sovellukset voivat käyttää tätä uusien sovellusten asentamiseen mielivaltaisen voimakkailla käyttöluvilla."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"sovellusvälimuistin kaikkien tietojen poistaminen"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Antaa sovelluksen vapauttaa tablet-laitteen tallennustilaa poistamalla tiedostoja sovellusvälimuistihakemistosta. Käyttö on yleensä tarkasti rajattu järjestelmäprosesseihin."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Antaa sovelluksen vapauttaa puhelimen tallennustilaa poistamalla tiedostoja sovellusvälimuistihakemistosta. Käyttö on yleensä tarkasti rajattu järjestelmäprosesseihin."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Antaa sovelluksen vapauttaa tablet-laitteen tallennustilaa poistamalla tiedostoja muiden sovellusten välimuistihakemistosta. Muut sovellukset voivat käynnistyä hitaammin, koska niiden täytyy noutaa tietonsa uudelleen."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Antaa sovelluksen vapauttaa puhelimen tallennustilaa poistamalla tiedostoja muiden sovellusten välimuistihakemistosta. Muut sovellukset voivat käynnistyä hitaammin, koska niiden täytyy noutaa tietonsa uudelleen."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"sovellusresurssien siirtäminen"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Antaa sovelluksen siirtää sovellusresursseja sisäisiltä tietovälineiltä ulkoisille ja päinvastoin."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"lukea arkaluonteisia lokitietoja"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Antaa sovelluksen käyttää ylimääräisiä sijaintipalvelukomentoja. Sovellus voi käyttää tätä GPS:n tai muun sijaintilähteen toiminnan häiritsemiseen."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"asenna sijainnintarjoaja"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Luo imitoituja sijaintilähteitä testaustarkoituksessa tai asenna uusi sijaintipalvelu. Sovellus voi ohittaa muiden sijaintilähteiden kuten GPS:n ja sijaintipalveluiden palauttaman sijainnin ja/tai tilan."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"tarkka sijainti (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Käytä tarkkoja sijaintilähteitä, kuten tablet-laitteen GPS-järjestelmää. Kun sijaintipalvelut ovat saatavilla ja käytössä, sovellus voi määrittää tarkan sijaintisi."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Käytä tarkkoja sijaintilähteitä, kuten puhelimen GPS-järjestelmää. Kun sijaintipalvelut ovat saatavilla ja käytössä, sovellus voi määrittää tarkan sijaintisi."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"likimääräinen sijainti (verkkopohjainen)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Käytä likimääräistä sijaintia sijaintipalveluilta verkkolähteiden kuten radiomastojen ja wifin kautta. Kun nämä sijaintipalvelut ovat saatavilla ja käytössä, sovellus voi määrittää likimääräisen sijaintisi."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"tarkka sijainti (GPS- ja verkkopohjainen)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Antaa sovelluksen käyttää tarkkaa sijaintiasi, joka määritetään GPS:n tai verkon sijaintilähteiden kuten radiomastojen ja wifi-verkkojen avulla. Sijaintipalveluiden täytyy olla käytössä ja laitteesi saatavilla, jotta sovellus voi käyttää niitä. Sovellus voi määrittää tämän luvan avulla sijaintisi ja lisätä akun käyttöä."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"likimääräinen sijainti (verkkopohjainen)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Antaa sovelluksen käyttää likimääräistä sijaintiasi. Sijainnin määrittävät sijaintipalvelut verkon sijaintilähteiden kuten radiomastojen ja wifi-verkkojen avulla. Sijaintipalveluiden täytyy olla käytössä ja laitteesi saatavilla, jotta sovellus voi käyttää niitä. Sovellus voi määrittää tämän luvan avulla likimääräisen sijaintisi."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"käytä SurfaceFlinger-sovellusta"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Antaa sovelluksen käyttää SurfaceFlingerin matalan tason ominaisuuksia."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"lue kehyspuskuria"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Antaa sovelluksen lukea kehyspuskurin sisältöä."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"määritä wifi-näyttöjen asetukset"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Antaa sovelluksen määrittää wifi-näyttöjä ja muodostaa yhteyden niihin."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"hallitse wifi-näyttöjä"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Antaa sovelluksen hallita wifi-näyttöjen matalan tason ominaisuuksia."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"muuta ääniasetuksia"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Antaa sovelluksen muokata yleisiä ääniasetuksia, kuten äänenvoimakkuutta ja käytettävää kaiutinta."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"tallentaa ääntä"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"käytä Bluetooth-asetuksia"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Antaa sovelluksen määrittää paikallisen Bluetooth-tabletin asetukset sekä tunnistaa muita laitteita ja muodostaa niiden kanssa laitepareja."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Antaa sovelluksen määrittää paikallisen Bluetooth-puhelimen asetukset sekä tunnistaa muita laitteita ja muodostaa niiden kanssa laitepareja."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Näytä WiMAX-yhteydet"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"muodosta yhteys WiMAXiin ja katkaise yhteys"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Antaa sovelluksen määrittää, onko WiMAX käytössä, sekä saada selville tietoja WiMAX-verkoista, joihin on muodostettu yhteys."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Vaihda WiMAX-verkon tilaa"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Antaa sovelluksen muodostaa tablet-laitteella yhteyden WiMAX-verkkoon ja katkaista yhteyden."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Antaa sovelluksen muokata synkronoitavia syötteitä. Haitalliset sovellukset voivat muuttaa synkronoitavia syötteitä."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"lue sanakirjaan lisättyjä termejä"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Antaa sovelluksen lukea sanoja, nimiä tai ilmauksia, joita käyttäjä on voinut tallentaa käyttäjän sanakirjaan."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"käyttäjän määrittelemään sanakirjaan kirjoittaminen"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"lisää sanoja käyttäjän sanakirjaan"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Antaa sovelluksen kirjoittaa uusia sanoja käyttäjän sanakirjaan."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"suojatun tallennustilan käyttöoikeuden testaus"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"suojatun tallennustilan käyttöoikeuden testaus"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Antaa sovelluksen testata muiden laitteiden käyttämän USB-tallennustilan käyttölupaa."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Antaa sovelluksen testata tulevien laitteiden USB-tallennustilan käyttölupaa."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Antaa sovelluksen testata muiden laitteiden käyttämän SD-kortin käyttölupaa."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"muokkaa tai poista USB:n sis."</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"muokkaa tai poista SD-kortin sisältöä"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Antaa sovelluksen kirjoittaa SD-kortille."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"muokkaa/poista sisäisen säilytystilan sisältöä"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Antaa sovelluksen muokata sisäisen tallennustilan sisältöä."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"käyttää kaikkien käyttäjien ulk. tallennustilaa"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Sallii sovelluksen käyttää ulkoista tallennustilaa kaikille käyttäjille."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"käytä välimuistin tiedostojärjestelmää"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Antaa sovelluksen lukea välimuistin tiedostojärjestelmää ja kirjoittaa siihen."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"soita/vastaanota internetpuheluita"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Pakota tallennettujen sovellustietojen salaus."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Poista kamerat käytöstä"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Estä laitteen kaikkien kameroiden käyttö."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Poista omin. käyt. näppäinluk."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Estä joidenkin ominaisuuksien käyttö näppäinlukolla."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Puhelinnumero (koti)"</item>
     <item msgid="869923650527136615">"Mobiili"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Yritä uudelleen"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Face Unlock -yrityksiä tehty suurin sallittu määrä."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Ladataan (<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Ladattu."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Täynnä"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Kytke laturi."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Ei SIM-korttia."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Ei SIM-korttia"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tablet-laitteessa ei ole SIM-korttia."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Puhelimessa ei ole SIM-korttia."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Aseta SIM-kortti."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Kuvio tyhjennetty"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Solu lisätty"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Kuvio valmis"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Lisää widget."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Tyhjä"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Lukituksen poiston alue laajennettu."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Lukituksen poiston alue tiivistetty."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>-widget."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Käyttäjävalitsin"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Tila"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Kamera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Mediaohjaimet"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Widgetien järjestely aloitettu."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Widgetien järjestely päättyi."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> poistettu."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Laajenna lukituksen poiston aluetta."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Lukituksen poisto liu\'uttamalla."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Lukituksen poisto salasanalla."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Face Unlock"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Lukituksen poisto PIN-koodilla."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Lukituksen poisto salasanalla."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Kuvioalue."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Liu\'utusalue."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopioi URL-osoite"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Valitse tekstiä"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Tekstin valinta"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"lisää sanakirjaan"</string>
-    <string name="deleteText" msgid="7070985395199629156">"poista"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Lisää sanakirjaan"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Poista"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Syöttötapa"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tekstitoiminnot"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Tallennustila loppumassa"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Avoimia wifi-verkkoja käytettävissä"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Kirjaudu wifi-verkkoon"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Kirjaudu verkkoon"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wifi-yhteyden muodostaminen epäonnistui"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" : huono internetyhteys."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Kohde:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Kirjoita pyydetty PIN-koodi:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-koodi:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Puhelimen yhteys wifi-verkkoon katkaistaan väliaikaisesti puhelimen ollessa yhdistettynä laitteeseen <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Lisää merkki"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Tekstiviestien lähettäminen"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; lähettää suuria määriä tekstiviestejä. Annetaanko tämän sovelluksen jatkaa tekstiviestien lähettämistä?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Salli"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Kiellä"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; haluaa lähettää viestin osoitteeseen &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Tämä "<font fgcolor="#ffffb060">"voi aiheuttaa kuluja"</font>" matkapuhelinliittymälaskuusi."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Tämä aiheuttaa kuluja matkapuhelinliittymälaskuusi."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Lähetä"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Peruuta"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Muista valintani"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Muuta kohd. Asetukset &gt; Sovellukset"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Salli aina"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Älä koskaan salli"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kortti poistettu"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobiiliverkko ei ole käytettävissä, ennen kuin käynnistät uudelleen kelvollisella laitteeseen kytketyllä SIM-kortilla."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Valmis"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Aseta päivämäärä"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Aseta"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Valmis"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Oletus"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Lupia ei tarvita"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Piilota"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Näytä kaikki"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"UUTTA: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"UUTTA: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Palvelun tarjoaa <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Lupia ei tarvita"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"tämä voi maksaa"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB-massamuisti"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB yhdistetty"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Olet yhdistänyt laitteesi tietokoneeseen USB-kaapelin kautta. Kosketa alla olevaa painiketta, jos haluat kopioida tiedostoja tietokoneesi ja Androidin USB-tallennustilan välillä."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> on aktivoinut VPN-yhteyden"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Voit hallinnoida verkkoa koskettamalla."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Yhdistetty: <xliff:g id="SESSION">%s</xliff:g>. Hallinnoi verkkoa koskettamalla."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Yhdistetään aina käytössä olevaan VPN-verkkoon..."</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Yhdistetty aina käytössä olevaan VPN-verkkoon"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Aina käytössä oleva VPN: virhe"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Nollaa yhteys koskettamalla"</string>
     <string name="upload_file" msgid="2897957172366730416">"Valitse tiedosto"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Ei valittua tiedostoa"</string>
     <string name="reset" msgid="2448168080964209908">"Palauta"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Jaa"</string>
     <string name="find" msgid="4808270900322985960">"Etsi"</string>
     <string name="websearch" msgid="4337157977400211589">"Verkkohaku"</string>
+    <string name="find_next" msgid="5742124618942193978">"Hae seuraava"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Hae edellinen"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Sijaintipyyntö käyttäjältä <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Sijaintipyyntö"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Pyytänyt <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Puhelin"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Kuulokkeet"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Telineen kaiuttimet"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-ääni"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Järjestelmä"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-ääni"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Valmis"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Median äänentoisto"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Etsitään..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Yhdistetään..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Käytettävissä"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Ei käytettävissä"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Yhdysrakenteinen näyttö"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-ruutu"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Peittokuva # <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Langaton näyttö on yhdistetty"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Tämä ruutu näkyy toisella laitteella"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Katkaise yhteys"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Hätäpuhelu"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Unohtunut kuvio"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Väärä kuvio"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Väärä salasana"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Väärä PIN-koodi"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Yritä uudelleen <xliff:g id="NUMBER">%d</xliff:g> sekunnin kuluttua."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Piirrä kuvio"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Anna SIM-kortin PIN-koodi"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Anna PIN-koodi"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Anna salasana"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM-kortti on nyt poistettu käytöstä. Jatka antamalla PUK-koodi. Saat lisätietoja ottamalla yhteyttä operaattoriin."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Anna haluamasi PIN-koodi"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Vahvista haluamasi PIN-koodi"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM-kortin lukitusta poistetaan…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Virheellinen PIN-koodi."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Anna 4–8-numeroinen PIN-koodi."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK-koodissa tulee olla vähintään 8 numeroa."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Anna uudelleen oikea PUK-koodi. Jos teet liian monta yritystä, SIM-kortti poistetaan käytöstä pysyvästi."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN-koodit eivät täsmää"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Liikaa kuvionpiirtoyrityksiä"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Poista lukitus kirjautumalla sisään Google-tililläsi."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Käyttäjänimi (sähköposti)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Salasana"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Kirjaudu sisään"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Virheellinen käyttäjänimi tai salasana."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Unohditko käyttäjänimesi tai salasanasi?"\n"Käy osoitteessa "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Tarkistetaan tiliä..."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Olet kirjoittanut PIN-koodin väärin <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. "\n\n"Yritä uudelleen <xliff:g id="NUMBER_1">%d</xliff:g> sekunnin kuluttua."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Olet kirjoittanut salasanan väärin <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. "\n\n"Yritä uudelleen <xliff:g id="NUMBER_1">%d</xliff:g> sekunnin kuluttua."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Olet piirtänyt lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. "\n\n"Yritä uudelleen <xliff:g id="NUMBER_1">%d</xliff:g> sekunnin kuluttua."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Tablet-laitteen lukituksen poisto epäonnistui <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. Jos teet vielä <xliff:g id="NUMBER_1">%d</xliff:g> epäonnistunutta yritystä, tablet-laitteeseen palautetaan tehdasasetukset ja kaikki käyttäjätiedot häviävät."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Puhelimen lukituksen poisto epäonnistui <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. Jos teet vielä <xliff:g id="NUMBER_1">%d</xliff:g> epäonnistunutta yritystä, puhelimeen palautetaan tehdasasetukset ja kaikki käyttäjätiedot häviävät."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Tablet-laitteen lukituksen poisto epäonnistui <xliff:g id="NUMBER">%d</xliff:g> kertaa. Laitteeseen palautetaan nyt tehdasasetukset."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Puhelimen lukituksen poisto epäonnistui <xliff:g id="NUMBER">%d</xliff:g> kertaa. Puhelimeen palautetaan nyt tehdasasetukset."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%d</xliff:g> kertaa, sinua pyydetään poistamaan tablet-laitteesi lukitus sähköpostitilin avulla."\n\n" Yritä uudelleen <xliff:g id="NUMBER_2">%d</xliff:g> sekunnin kuluttua."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%d</xliff:g> kertaa, sinua pyydetään poistamaan puhelimesi lukitus sähköpostitilin avulla."\n\n" Yritä uudelleen <xliff:g id="NUMBER_2">%d</xliff:g> sekunnin kuluttua."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Poista"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Nostetaanko äänenvoimakkuus turvallista tasoa voimakkaammaksi?"\n"Jos kuuntelet suurella äänenvoimakkuudella pitkiä aikoja, kuulosi voi vahingoittua."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Ota esteettömyystila käyttöön koskettamalla pitkään kahdella sormella."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Esteettömyystila käytössä."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Esteettömyystila peruutettu."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Nykyinen käyttäjä: <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Omistaja"</string>
 </resources>
diff --git a/core/res/res/values-fr/donottranslate-cldr.xml b/core/res/res/values-fr/donottranslate-cldr.xml
index 840f728..ff10aec 100644
--- a/core/res/res/values-fr/donottranslate-cldr.xml
+++ b/core/res/res/values-fr/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">janvier</string>
-    <string name="month_long_standalone_february">février</string>
-    <string name="month_long_standalone_march">mars</string>
-    <string name="month_long_standalone_april">avril</string>
-    <string name="month_long_standalone_may">mai</string>
-    <string name="month_long_standalone_june">juin</string>
-    <string name="month_long_standalone_july">juillet</string>
-    <string name="month_long_standalone_august">août</string>
-    <string name="month_long_standalone_september">septembre</string>
-    <string name="month_long_standalone_october">octobre</string>
-    <string name="month_long_standalone_november">novembre</string>
-    <string name="month_long_standalone_december">décembre</string>
-
-    <string name="month_long_january">janvier</string>
-    <string name="month_long_february">février</string>
-    <string name="month_long_march">mars</string>
-    <string name="month_long_april">avril</string>
-    <string name="month_long_may">mai</string>
-    <string name="month_long_june">juin</string>
-    <string name="month_long_july">juillet</string>
-    <string name="month_long_august">août</string>
-    <string name="month_long_september">septembre</string>
-    <string name="month_long_october">octobre</string>
-    <string name="month_long_november">novembre</string>
-    <string name="month_long_december">décembre</string>
-
-    <string name="month_medium_january">janv.</string>
-    <string name="month_medium_february">févr.</string>
-    <string name="month_medium_march">mars</string>
-    <string name="month_medium_april">avr.</string>
-    <string name="month_medium_may">mai</string>
-    <string name="month_medium_june">juin</string>
-    <string name="month_medium_july">juil.</string>
-    <string name="month_medium_august">août</string>
-    <string name="month_medium_september">sept.</string>
-    <string name="month_medium_october">oct.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">déc.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">dimanche</string>
-    <string name="day_of_week_long_monday">lundi</string>
-    <string name="day_of_week_long_tuesday">mardi</string>
-    <string name="day_of_week_long_wednesday">mercredi</string>
-    <string name="day_of_week_long_thursday">jeudi</string>
-    <string name="day_of_week_long_friday">vendredi</string>
-    <string name="day_of_week_long_saturday">samedi</string>
-
-    <string name="day_of_week_medium_sunday">dim.</string>
-    <string name="day_of_week_medium_monday">lun.</string>
-    <string name="day_of_week_medium_tuesday">mar.</string>
-    <string name="day_of_week_medium_wednesday">mer.</string>
-    <string name="day_of_week_medium_thursday">jeu.</string>
-    <string name="day_of_week_medium_friday">ven.</string>
-    <string name="day_of_week_medium_saturday">sam.</string>
-
-    <string name="day_of_week_short_sunday">dim.</string>
-    <string name="day_of_week_short_monday">lun.</string>
-    <string name="day_of_week_short_tuesday">mar.</string>
-    <string name="day_of_week_short_wednesday">mer.</string>
-    <string name="day_of_week_short_thursday">jeu.</string>
-    <string name="day_of_week_short_friday">ven.</string>
-    <string name="day_of_week_short_saturday">sam.</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">L</string>
-    <string name="day_of_week_shortest_tuesday">M</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">J</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">matin</string>
-    <string name="pm">soir</string>
-    <string name="yesterday">hier</string>
-    <string name="today">aujourd’hui</string>
-    <string name="tomorrow">demain</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index e000f93..479fe18 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Options du téléphone"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Verrouillage de l\'écran"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Éteindre"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Rapport de bug"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Créer un rapport de bug"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Cela permet de recueillir des informations concernant l\'état actuel de votre appareil. Ces informations sont ensuite envoyées sous forme d\'e-mail. Merci de patienter pendant la préparation du rapport de bug. Cette opération peut prendre quelques instants."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Mode silencieux"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Le son est désactivé."</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Le son est activé."</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Vos messages"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Permet de lire et de rédiger vos SMS, e-mails et autres messages."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Vos informations personnelles"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Accéder directement aux contacts et à l\'agenda enregistrés sur la tablette"</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Accéder directement aux contacts et à l\'agenda enregistrés sur votre téléphone"</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Accès direct aux informations vous concernant enregistrées dans la fiche de contact"</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Vos informations sur les réseaux sociaux"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Accès direct aux informations sur vos contacts et vos amis sur les réseaux sociaux"</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Votre position"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Déterminer votre position géographique"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Communications réseau"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Accéder à différentes fonctionnalités du réseau"</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Accéder aux appareils et aux réseaux via le Bluetooth"</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Paramètres audio"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Modification des paramètres audio"</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Affecte la batterie"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Utilisation de fonctionnalités qui peuvent épuiser rapidement la batterie"</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Agenda"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Accès direct à l\'agenda et aux événements"</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Consulter le dictionnaire personnel"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Consulter les mots ajoutés au dictionnaire personnel"</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Modifier le dictionnaire personnel"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Ajouter des mots au dictionnaire personnel"</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Favoris et historique"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Accès direct aux favoris et à l\'historique du navigateur"</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarme"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Réglage du réveil"</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Messagerie vocale"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Accès direct à la messagerie vocale"</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Microphone"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Accès direct au microphone pour enregistrer du contenu audio"</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Appareil photo"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Accès direct à la caméra pour la capture d\'images ou de vidéos"</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Informations relatives à vos applications"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Possibilité de modifier le comportement des autres applications sur votre appareil"</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Fond d\'écran"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Modification des paramètres du fond d\'écran de l\'appareil"</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Horloge"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Modification de l\'heure ou du fuseau horaire de l\'appareil"</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Barre d\'état"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Modification des paramètres de la barre d\'état de l\'appareil"</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Paramètres de synchronisation"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Accès aux paramètres de synchronisation"</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Vos comptes"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Accéder aux comptes disponibles"</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Commandes du matériel"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Accès et contrôle de faible niveau du système."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Outils de développement"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Ces fonctionnalités sont destinées uniquement aux développeurs d\'applications."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Interface utilisateur d\'une autre application"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Effet sur l\'interface utilisateur d\'autres applications"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Stockage"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Accéder à la  mémoire de stockage USB"</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Accéder à la carte SD"</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permet à l\'application de recevoir et de traiter les messages WAP. Cette autorisation lui donne la possibilité de surveiller ou supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"récupérer les applications en cours d\'exécution"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Permet à l\'application de récupérer des informations sur des tâches en cours d\'exécution et récemment exécutées. L\'application est ainsi susceptible de d\'obtenir des informations sur les applications utilisées sur l\'appareil."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interagir entre les utilisateurs"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permet à l\'application d\'effectuer des actions entre les différents utilisateurs de l\'appareil. Les applications malveillantes peuvent utiliser cette autorisation pour passer outre la protection entre les utilisateurs."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"autorisation totale d\'interagir entre les utilisateurs"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permet toutes les interactions possibles entre les utilisateurs."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"Gérer les utilisateurs"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permet aux applications de gérer les utilisateurs de l\'appareil, y compris la recherche, la création et la suppression d\'utilisateurs."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"récupérer les détails des applications en cours d\'exécution"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permet à l\'application de récupérer des informations détaillées sur les tâches en cours d\'exécution ou récemment exécutées. Des applications malveillantes peuvent utiliser cette fonctionnalité pour obtenir des informations confidentielles relatives à d\'autres applications."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"réorganiser les applications en cours d\'exécution"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Permet à l\'application de récupérer l\'état interne du système. Des applications malveillantes peuvent récupérer de nombreuses informations confidentielles et sécurisées dont elles ne devraient pas avoir besoin normalement."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"récupérer le contenu de l\'écran"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permet à l\'application de récupérer le contenu de la fenêtre active. Des applications malveillantes peuvent exploiter cette fonctionnalité pour récupérer et lire la totalité du contenu de la fenêtre, à l\'exception des mots de passe."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"activer temporairement l\'accessibilité"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permet à une application d\'activer temporairement l\'accessibilité sur l\'appareil. Des applications malveillantes peuvent activer l\'accessibilité sans le consentement de l\'utilisateur."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"récupérer les informations sur les fenêtres"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permet à une application de récupérer les informations sur les fenêtres depuis le gestionnaire de fenêtres. Des applications malveillantes peuvent récupérer des informations destinées à un usage interne du système."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrer les événements"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Permet à une application d\'enregistrer un filtre d\'entrée pour filtrer le flux de tous les événements des utilisateurs avant qu\'ils ne soient traités. Des applications malveillantes peuvent contrôler l\'interface utilisateur du système sans l\'intervention de l\'utilisateur."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"agrandir l\'écran"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Permet à une application d\'agrandir le contenu à l\'écran. Les applications malveillantes peuvent transformer ce contenu et rendre l\'appareil inutilisable."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"arrêt partiel"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Place le gestionnaire d\'activités en état d\'arrêt. N\'effectue pas un arrêt complet."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"empêcher les changements d\'applications"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permet à l\'application de contrôler le nombre maximal de processus devant s\'exécuter. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forcer la fermeture des applications en arrière-plan"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Permet à l\'application de contrôler si les activités sont toujours terminées ou non lorsqu\'elles passent en arrière-plan. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"Modification des statistiques de la batterie"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Permet à l\'application de modifier les statistiques collectées concernant la batterie. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"lire les statistiques de la batterie"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permet à une application de lire les données de consommation actuelles indiquant le faible niveau de la batterie. Permet éventuellement à l\'application d\'obtenir des informations détaillées sur les applications que vous utilisez."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modifier les statistiques de la batterie"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permet à l\'application de modifier les statistiques collectées concernant la batterie. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
     <string name="permlab_backup" msgid="470013022865453920">"contrôler la sauvegarde et la restauration du système"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Permet à l\'application de contrôler le mécanisme de sauvegarde et de restauration du système. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"confirmer une sauvegarde complète ou une restauration"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"Affichage de fenêtres non autorisées"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Permet à l\'application de créer des fenêtres destinées à être utilisées par l\'interface utilisateur du système interne. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"ignorer les autres applications"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Permet à l\'application d\'afficher les fenêtres d\'alertes système. Certaines fenêtres d\'alerte peuvent occuper la totalité de l\'écran."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Permet à l\'application d\'ignorer d\'autres applications ou certaines parties de l\'interface utilisateur. Cela peut altérer votre utilisation de l\'interface de n\'importe quelle application, ou modifier ce que vous pensez voir dans d\'autres applications."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"Réglage de la vitesse des animations"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Permet à l\'application de modifier à tout moment la vitesse générale des animations pour les ralentir ou les accélérer."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"gérer les jetons d\'application"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Permet à l\'application de créer et de gérer ses propres jetons en ignorant leur ordre de plan normal. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"bloquer l\'écran"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Permet à l\'application de bloquer temporairement l\'écran pour passer en mode plein écran."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"Utilisation des touches ou contrôle des commandes"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Permet à l\'application de fournir ses propres événements d\'entrée (pression de touche, etc.) à d\'autres applications. Des applications malveillantes peuvent exploiter cette fonctionnalité pour prendre le contrôle de la tablette."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Permet à l\'application de fournir ses propres événements d\'entrée (pression de touche, etc.) à d\'autres applications. Des applications malveillantes peuvent exploiter cette fonctionnalité pour prendre le contrôle du téléphone."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"installer directement les applications"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Permet à l\'application d\'installer des packages Android nouveaux ou mis à jour. Des applications malveillantes peuvent exploiter cette fonctionnalité pour ajouter de nouvelles applications à l\'aide d\'autorisations anormalement élevées."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"supprimer toutes les données du cache de l\'application"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Permet à l\'application de libérer de l\'espace de stockage sur la tablette en supprimant les fichiers situés dans le répertoire du cache de l\'application. Cet accès est en général limité aux processus système."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Permet à l\'application de libérer de l\'espace de stockage sur le téléphone en supprimant les fichiers stockés dans le répertoire du cache de l\'application. Cet accès est en général limité aux processus système."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Permet à l\'application de libérer de la mémoire de stockage sur la tablette en supprimant des fichiers dans les répertoires en cache d\'autres applications. Cette autorisation peut occasionner un démarrage plus lent de ces applications, dans la mesure où une nouvelle récupération de leurs données est requise."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Permet à l\'application de libérer de la mémoire de stockage sur le téléphone en supprimant des fichiers dans les répertoires en cache d\'autres applications. Cette autorisation peut occasionner un démarrage plus lent de ces applications, dans la mesure où une nouvelle récupération de leurs données est requise."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"déplacer les ressources d\'une application"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Permet à l\'application de déplacer les ressources d\'une application depuis un support interne vers un support externe, et inversement."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"lire les données des journaux à caractère confidentiel"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Permet à l\'application d\'accéder à des commandes de fournisseur de position supplémentaires. Elle est ainsi susceptible d\'interférer avec le bon fonctionnement du GPS ou de toute autre source de localisation."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"autoriser l\'installation d\'un fournisseur de services de localisation"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Permet de créer des sources de localisation fictives à des fins de tests ou pour installer un nouveau fournisseur de position. L\'application peut ainsi modifier la position et/ou l\'état renvoyé par d\'autres sources de localisation telles que le GPS ou les fournisseurs de position."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"position (GPS) exacte"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Permet d\'accéder à des sources de localisation précises telles que le système GPS de la tablette. Lorsque les services de localisation sont disponibles et activés, cette autorisation permet à l\'application de déterminer votre position exacte."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Permet d\'accéder à des sources de localisation précises telles que le système GPS du téléphone. Lorsque les services de localisation sont disponibles et activés, cette autorisation permet à l\'application de déterminer votre position exacte."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"position (réseau) approximative"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Permet d\'accéder à la position approximative par l\'intermédiaire de fournisseurs de position utilisant des sources réseau telles que les antennes-relais et le Wi-Fi. Lorsque ces services de localisation sont disponibles et activés, cette autorisation permet à l\'application de déterminer votre position approximative."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"position précise (GPS et réseau)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Permet à l\'application d\'obtenir votre position exacte à l\'aide du récepteur satellite GPS ou des sources de localisation de réseau tels que les points d\'accès Wi-Fi et les antennes-relais. Ces services de localisation doivent être activés et disponibles sur votre appareil pour que l\'application puissent déterminer où vous vous trouvez, le cas échéant. Cette autorisation peut entraîner une utilisation accrue de la batterie."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"position approximative (réseau)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Permet à l\'application d\'obtenir votre position approximative. Celle-ci est fournie par des services de localisation sur la base des sources de localisation de réseau tels que les points d\'accès Wi-Fi et les antennes-relais. Ces services de localisation doivent être activés et disponibles sur votre appareil pour que l\'application puisse déterminer où vous vous trouvez de façon approximative, le cas échéant."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"Accès à SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Permet à l\'application d\'utiliser les fonctionnalités de bas niveau de SurfaceFlinger."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"Lecture de la mémoire tampon graphique"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Permet à l\'application de lire le contenu de la mémoire tampon graphique."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"configurer les écrans Wi-Fi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permet à l\'application de configurer des écrans Wi-Fi et de s\'y connecter."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"contrôler les écrans Wi-Fi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permet à l\'application de contrôler les fonctionnalités de base des écrans Wi-Fi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modifier vos paramètres audio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permet à l\'application de modifier les paramètres audio généraux, tels que le volume et la sortie audio utilisée."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"Enregistrement de fichier audio"</string>
@@ -478,7 +537,7 @@
     <string name="permdesc_useCredentials" msgid="7984227147403346422">"Permet à l\'application de demander des jetons d\'authentification."</string>
     <string name="permlab_accessNetworkState" msgid="4951027964348974773">"afficher les connexions réseau"</string>
     <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Permet à l\'application d\'accéder à des informations sur les connexions réseau, comme les réseaux existants et connectés."</string>
-    <string name="permlab_createNetworkSockets" msgid="8018758136404323658">"accès complet au réseau"</string>
+    <string name="permlab_createNetworkSockets" msgid="8018758136404323658">"bénéficier d\'un accès complet au réseau"</string>
     <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Permet à l\'application de créer des sockets réseau et d\'utiliser des protocoles réseau personnalisés. Le navigateur et d\'autres applications permettent d\'envoyer des données sur Internet. Cette autorisation n\'est donc pas nécessaire pour envoyer des données sur Internet."</string>
     <string name="permlab_writeApnSettings" msgid="505660159675751896">"changer/intercepter les paramètres et le trafic du réseau"</string>
     <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"Permet à l\'application de modifier les paramètres réseau, ainsi que d\'intercepter et de surveiller tout le trafic réseau ayant pour but de modifier le proxy et le port d\'un APN, par exemple. Des applications malveillantes peuvent exploiter cette fonctionnalité pour surveiller, rediriger ou modifier les paquets réseau à votre insu."</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"accéder aux paramètres Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Permet à l\'application de configurer la tablette Bluetooth locale, d\'identifier des appareils distants et de les associer à la tablette."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permet à l\'application de configurer le téléphone Bluetooth local, d\'identifier des appareils distants et de les associer au téléphone."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"afficher les connexions WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"se connecter au réseau WiMAX et s\'en déconnecter"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permet à l\'application de déterminer si le WiMAX est activé et d\'obtenir des informations sur tous les réseaux WiMAX connectés."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Modifier l\'état du WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permet à l\'application de connecter la tablette aux réseaux WiMAX et de l\'en déconnecter."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Permet à l\'application de modifier les flux en cours de synchronisation. Des applications malveillantes peuvent exploiter cette fonctionnalité pour modifier vos flux synchronisés."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"voir les termes ajoutés au dictionnaire"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Permet à l\'application d\'accéder aux mots, noms et expressions que l\'utilisateur a pu enregistrer dans son dictionnaire personnel."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"enregistrer dans le dictionnaire défini par l\'utilisateur"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"ajouter des mots au dictionnaire personnel"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Permet à l\'application d\'enregistrer de nouveaux mots dans le dictionnaire personnel de l\'utilisateur."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"tester l\'accès à la mémoire de stockage protégée"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"tester l\'accès à la mémoire de stockage protégée"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Permet à l\'application de tester une autorisation pour la mémoire de stockage USB qui sera ensuite proposée sur les futurs appareils."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Permet à l\'application de tester une autorisation pour la mémoire de stockage USB qui sera ensuite proposée sur les futurs appareils."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Permet à l\'application de tester une autorisation pour la carte SD qui sera ensuite proposée sur les futurs appareils."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modifier ou supprimer le contenu de la mémoire USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modifier ou supprimer le contenu de la carte SD"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Permet à l\'application de modifier le contenu de la carte SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"Modifier/Supprimer contenu mémoire interne"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Permet à l\'application de modifier le contenu de la mémoire de stockage multimédia interne."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"Accès stock. ext. tous utilis."</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Permet à l\'application d\'accéder à la mémoire de stockage externe pour tous les utilisateurs."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"accéder au système de fichiers en cache"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permet à l\'application d\'obtenir des droits en lecture/écriture concernant le système de fichiers du cache."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"effectuer/recevoir des appels Internet"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Exiger le chiffrement des données d\'application stockées"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Désactiver les appareils photo"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Empêcher l\'utilisation de tous les appareils photos"</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Désact. fonct. si protec. clav."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Empêcher l\'utilisation de certaines fonctionnalités lorsque la protection du clavier est activée"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domicile"</item>
     <item msgid="869923650527136615">"Mobile"</item>
@@ -674,7 +737,7 @@
     <string name="relationTypeSister" msgid="1735983554479076481">"Sœur"</string>
     <string name="relationTypeSpouse" msgid="394136939428698117">"Conjoint"</string>
     <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Personnalisée"</string>
-    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Accueil"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Domicile"</string>
     <string name="sipAddressTypeWork" msgid="6920725730797099047">"Professionnelle"</string>
     <string name="sipAddressTypeOther" msgid="4408436162950119849">"Autre"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Saisissez le code PIN."</string>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Veuillez réessayer."</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Nombre maximal autorisé de tentatives Face Unlock atteint."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"En charge (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Chargé"</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Chargé"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Branchez votre chargeur."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Aucune carte SIM n\'a été trouvée."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Aucune carte SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Aucune carte SIM n\'est insérée dans la tablette."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Aucune carte SIM n\'est insérée dans le téléphone."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Insérez une carte SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Schéma effacé."</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Cellule ajoutée."</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Schéma terminé."</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Ajouter un widget"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Vide"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Zone de déverrouillage développée."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Zone de déverrouillage réduite."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>"</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Sélecteur d\'utilisateur"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"État"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Caméra"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Commandes multimédias"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Début de la réorganisation des widgets"</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Réorganisation des widgets terminée."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Le widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> a été supprimé."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Développer la zone de déverrouillage"</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Déverrouillage en faisant glisser votre doigt sur l\'écran"</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Déverrouillage par schéma"</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Déverrouillage par reconnaissance faciale"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Déverrouillage par code PIN"</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Déverrouillage par mot de passe"</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zone du schéma"</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zone où faire glisser votre doigt sur l\'écran"</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copier l\'URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Sélectionner texte"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Sélection de texte"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"ajouter au dictionnaire"</string>
-    <string name="deleteText" msgid="7070985395199629156">"supprimer"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Ajouter au dictionnaire"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Supprimer"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Mode de saisie"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Actions sur le texte"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Espace de stockage bientôt saturé"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Réseaux Wi-Fi ouverts disponibles"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Connectez-vous au réseau Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Se connecter au réseau"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Impossible de se connecter au Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" dispose d\'une mauvaise connexion Internet."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"À :"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Saisissez le code PIN requis :"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Code PIN :"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Le téléphone sera déconnecté du réseau Wi-Fi tant qu\'il sera connecté à l\'appareil <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="select_character" msgid="3365550120617701745">"Insérer un caractère"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Envoi de messages SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; envoie un grand nombre de SMS. Autorisez-vous cette application à poursuivre l\'envoi des messages ?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Autoriser"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Refuser"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; souhaite envoyer un message à &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Ceci "<font fgcolor="#ffffb060">"peut entraîner des frais"</font>" sur votre compte mobile."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Ceci entraînera des frais sur votre compte mobile."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Envoyer"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Annuler"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Mémoriser mon choix"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Pour modifier : Paramètres &gt; Applications"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Toujours autoriser"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Ne jamais autoriser"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Carte SIM retirée"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Le réseau mobile ne sera pas disponible avant le redémarrage avec une carte SIM valide insérée."</string>
     <string name="sim_done_button" msgid="827949989369963775">"OK"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Définir la date"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Définir"</string>
     <string name="date_time_done" msgid="2507683751759308828">"OK"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Par défaut"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Aucune autorisation requise"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Masquer"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Tout afficher"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NOUVEAU"</font>" :"</string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NOUVEAU"</font>" :"</string>
     <string name="perms_description_app" msgid="5139836143293299417">"Fourni par <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Aucune autorisation requise"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"cela peut engendrer des frais"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Mémoire de stockage de masse USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Connecté par USB"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Vous êtes connecté à votre ordinateur via un câble USB. Appuyez sur le bouton ci-dessous pour copier des fichiers de votre ordinateur vers la mémoire de stockage USB de votre appareil Android, ou inversement."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN activé par <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Appuyez ici pour gérer le réseau."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Connecté à <xliff:g id="SESSION">%s</xliff:g>. Appuyez ici pour gérer le réseau."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN permanent en cours de connexion…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN permanent connecté"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Erreur du VPN permanent"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Appuyez sur l\'écran pour réinitialiser la connexion."</string>
     <string name="upload_file" msgid="2897957172366730416">"Sélectionner un fichier"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Aucun fichier sélectionné"</string>
     <string name="reset" msgid="2448168080964209908">"Réinitialiser"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Partager"</string>
     <string name="find" msgid="4808270900322985960">"Rechercher"</string>
     <string name="websearch" msgid="4337157977400211589">"Recherche Web"</string>
+    <string name="find_next" msgid="5742124618942193978">"Rechercher suivant"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Rechercher précédent"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Demande de position de la part de <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Demande de position"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Demande de <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Téléphone"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Écouteurs"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Haut-parleurs de la station d\'accueil"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Audio HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Système"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"OK"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Sortie multimédia"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Analyse en cours..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Connexion en cours..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Disponible"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Indisponible"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Écran intégré"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Écran HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Superposition n° <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g> : <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"L\'affichage sans fil est connecté."</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Cet écran s\'affiche sur un autre appareil."</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Déconnecter"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Appel d\'urgence"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"J\'ai oublié le schéma"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Schéma incorrect."</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Mot de passe incorrect."</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Code PIN incorrect."</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Réessayez dans <xliff:g id="NUMBER">%d</xliff:g> secondes."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Dessinez votre schéma."</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Saisissez le code PIN de la carte SIM."</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Saisissez le code PIN."</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Saisissez votre mot de passe."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"La carte SIM est maintenant désactivée. Saisissez le code PUK pour continuer. Contactez votre opérateur pour en savoir plus."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Saisir le code PIN souhaité"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Confirmer le code PIN souhaité"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Déblocage de la carte SIM en cours…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Le code PIN est erroné."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Veuillez saisir un code PIN comprenant entre quatre et huit chiffres."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Le code PUK doit contenir au moins 8 chiffres."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Veuillez saisir de nouveau le code PUK correct. Des tentatives répétées désactivent définitivement la carte SIM."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Les codes PIN ne correspondent pas."</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Trop de tentatives."</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Pour déverrouiller le téléphone, veuillez vous connecter avec votre compte Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Nom d\'utilisateur (e-mail)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Mot de passe"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Connexion"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Nom d\'utilisateur ou mot de passe non valide."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Vous avez oublié votre nom d\'utilisateur ou votre mot de passe ?"\n"Rendez-vous sur la page "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Vérification du compte en cours…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Vous avez saisi un code PIN incorrect à <xliff:g id="NUMBER_0">%d</xliff:g> reprises. "\n\n"Veuillez réessayer dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Vous avez saisi un mot de passe incorrect à <xliff:g id="NUMBER_0">%d</xliff:g> reprises. "\n\n"Veuillez réessayer dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%d</xliff:g> reprises."\n\n"Veuillez réessayer dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Vous avez tenté de déverrouiller la tablette de façon incorrecte à <xliff:g id="NUMBER_0">%d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%d</xliff:g> fois, sa configuration d\'usine sera rétablie, et toutes les données utilisateur seront perdues."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Vous avez tenté de déverrouiller le téléphone de façon incorrecte à <xliff:g id="NUMBER_0">%d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%d</xliff:g> fois, sa configuration d\'usine sera rétablie, et toutes les données utilisateur seront perdues."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Vous avez tenté de déverrouiller la tablette de façon incorrecte à <xliff:g id="NUMBER">%d</xliff:g> reprises. Sa configuration d\'usine va être rétablie."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Vous avez tenté de déverrouiller le téléphone de façon incorrecte à <xliff:g id="NUMBER">%d</xliff:g> reprises. Sa configuration d\'usine va être rétablie."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%d</xliff:g> fois, vous devrez déverrouiller votre tablette à l\'aide d\'un compte de messagerie électronique."\n\n" Veuillez réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de messagerie électronique."\n\n" Veuillez réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Supprimer"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Augmenter le volume au-dessus du niveau de sécurité ?"\n"L\'écoute à un volume élevé pendant des périodes prolongées peut endommager votre audition."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Pour activer l\'accessibilité, appuyez de manière prolongée avec deux doigts."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"L\'accessibilité a bien été activée."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Accessibilité annulée."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Utilisateur actuel : <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="owner_name" msgid="2716755460376028154">"Propriétaire"</string>
 </resources>
diff --git a/core/res/res/values-hi-rIN/donottranslate-cldr.xml b/core/res/res/values-hi-rIN/donottranslate-cldr.xml
index 6bfd3de..5371e15 100644
--- a/core/res/res/values-hi-rIN/donottranslate-cldr.xml
+++ b/core/res/res/values-hi-rIN/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">जनवरी</string>
-    <string name="month_long_standalone_february">फरवरी</string>
-    <string name="month_long_standalone_march">मार्च</string>
-    <string name="month_long_standalone_april">अप्रैल</string>
-    <string name="month_long_standalone_may">मई</string>
-    <string name="month_long_standalone_june">जून</string>
-    <string name="month_long_standalone_july">जुलाई</string>
-    <string name="month_long_standalone_august">अगस्त</string>
-    <string name="month_long_standalone_september">सितम्बर</string>
-    <string name="month_long_standalone_october">अक्तूबर</string>
-    <string name="month_long_standalone_november">नवम्बर</string>
-    <string name="month_long_standalone_december">दिसम्बर</string>
-
-    <string name="month_long_january">जनवरी</string>
-    <string name="month_long_february">फरवरी</string>
-    <string name="month_long_march">मार्च</string>
-    <string name="month_long_april">अप्रैल</string>
-    <string name="month_long_may">मई</string>
-    <string name="month_long_june">जून</string>
-    <string name="month_long_july">जुलाई</string>
-    <string name="month_long_august">अगस्त</string>
-    <string name="month_long_september">सितम्बर</string>
-    <string name="month_long_october">अक्तूबर</string>
-    <string name="month_long_november">नवम्बर</string>
-    <string name="month_long_december">दिसम्बर</string>
-
-    <string name="month_medium_january">जनवरी</string>
-    <string name="month_medium_february">फरवरी</string>
-    <string name="month_medium_march">मार्च</string>
-    <string name="month_medium_april">अप्रैल</string>
-    <string name="month_medium_may">मई</string>
-    <string name="month_medium_june">जून</string>
-    <string name="month_medium_july">जुलाई</string>
-    <string name="month_medium_august">अगस्त</string>
-    <string name="month_medium_september">सितम्बर</string>
-    <string name="month_medium_october">अक्तूबर</string>
-    <string name="month_medium_november">नवम्बर</string>
-    <string name="month_medium_december">दिसम्बर</string>
-
-    <string name="month_shortest_january">ज</string>
-    <string name="month_shortest_february">फ़</string>
-    <string name="month_shortest_march">मा</string>
-    <string name="month_shortest_april">अ</string>
-    <string name="month_shortest_may">म</string>
-    <string name="month_shortest_june">जू</string>
-    <string name="month_shortest_july">जु</string>
-    <string name="month_shortest_august">अ</string>
-    <string name="month_shortest_september">सि</string>
-    <string name="month_shortest_october">अ</string>
-    <string name="month_shortest_november">न</string>
-    <string name="month_shortest_december">दि</string>
-
-    <string name="day_of_week_long_sunday">रविवार</string>
-    <string name="day_of_week_long_monday">सोमवार</string>
-    <string name="day_of_week_long_tuesday">मंगलवार</string>
-    <string name="day_of_week_long_wednesday">बुधवार</string>
-    <string name="day_of_week_long_thursday">गुरुवार</string>
-    <string name="day_of_week_long_friday">शुक्रवार</string>
-    <string name="day_of_week_long_saturday">शनिवार</string>
-
-    <string name="day_of_week_medium_sunday">रवि</string>
-    <string name="day_of_week_medium_monday">सोम</string>
-    <string name="day_of_week_medium_tuesday">मंगल</string>
-    <string name="day_of_week_medium_wednesday">बुध</string>
-    <string name="day_of_week_medium_thursday">गुरु</string>
-    <string name="day_of_week_medium_friday">शुक्र</string>
-    <string name="day_of_week_medium_saturday">शनि</string>
-
-    <string name="day_of_week_short_sunday">रवि</string>
-    <string name="day_of_week_short_monday">सोम</string>
-    <string name="day_of_week_short_tuesday">मंगल</string>
-    <string name="day_of_week_short_wednesday">बुध</string>
-    <string name="day_of_week_short_thursday">गुरु</string>
-    <string name="day_of_week_short_friday">शुक्र</string>
-    <string name="day_of_week_short_saturday">शनि</string>
-
-    <string name="day_of_week_shortest_sunday">र</string>
-    <string name="day_of_week_shortest_monday">सो</string>
-    <string name="day_of_week_shortest_tuesday">मं</string>
-    <string name="day_of_week_shortest_wednesday">बु</string>
-    <string name="day_of_week_shortest_thursday">गु</string>
-    <string name="day_of_week_shortest_friday">शु</string>
-    <string name="day_of_week_shortest_saturday">श</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-hi/donottranslate-cldr.xml b/core/res/res/values-hi/donottranslate-cldr.xml
index d9405d8..8043169 100644
--- a/core/res/res/values-hi/donottranslate-cldr.xml
+++ b/core/res/res/values-hi/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">जनवरी</string>
-    <string name="month_long_standalone_february">फरवरी</string>
-    <string name="month_long_standalone_march">मार्च</string>
-    <string name="month_long_standalone_april">अप्रैल</string>
-    <string name="month_long_standalone_may">मई</string>
-    <string name="month_long_standalone_june">जून</string>
-    <string name="month_long_standalone_july">जुलाई</string>
-    <string name="month_long_standalone_august">अगस्त</string>
-    <string name="month_long_standalone_september">सितम्बर</string>
-    <string name="month_long_standalone_october">अक्तूबर</string>
-    <string name="month_long_standalone_november">नवम्बर</string>
-    <string name="month_long_standalone_december">दिसम्बर</string>
-
-    <string name="month_long_january">जनवरी</string>
-    <string name="month_long_february">फरवरी</string>
-    <string name="month_long_march">मार्च</string>
-    <string name="month_long_april">अप्रैल</string>
-    <string name="month_long_may">मई</string>
-    <string name="month_long_june">जून</string>
-    <string name="month_long_july">जुलाई</string>
-    <string name="month_long_august">अगस्त</string>
-    <string name="month_long_september">सितम्बर</string>
-    <string name="month_long_october">अक्तूबर</string>
-    <string name="month_long_november">नवम्बर</string>
-    <string name="month_long_december">दिसम्बर</string>
-
-    <string name="month_medium_january">जनवरी</string>
-    <string name="month_medium_february">फरवरी</string>
-    <string name="month_medium_march">मार्च</string>
-    <string name="month_medium_april">अप्रैल</string>
-    <string name="month_medium_may">मई</string>
-    <string name="month_medium_june">जून</string>
-    <string name="month_medium_july">जुलाई</string>
-    <string name="month_medium_august">अगस्त</string>
-    <string name="month_medium_september">सितम्बर</string>
-    <string name="month_medium_october">अक्तूबर</string>
-    <string name="month_medium_november">नवम्बर</string>
-    <string name="month_medium_december">दिसम्बर</string>
-
-    <string name="month_shortest_january">ज</string>
-    <string name="month_shortest_february">फ़</string>
-    <string name="month_shortest_march">मा</string>
-    <string name="month_shortest_april">अ</string>
-    <string name="month_shortest_may">म</string>
-    <string name="month_shortest_june">जू</string>
-    <string name="month_shortest_july">जु</string>
-    <string name="month_shortest_august">अ</string>
-    <string name="month_shortest_september">सि</string>
-    <string name="month_shortest_october">अ</string>
-    <string name="month_shortest_november">न</string>
-    <string name="month_shortest_december">दि</string>
-
-    <string name="day_of_week_long_sunday">रविवार</string>
-    <string name="day_of_week_long_monday">सोमवार</string>
-    <string name="day_of_week_long_tuesday">मंगलवार</string>
-    <string name="day_of_week_long_wednesday">बुधवार</string>
-    <string name="day_of_week_long_thursday">गुरुवार</string>
-    <string name="day_of_week_long_friday">शुक्रवार</string>
-    <string name="day_of_week_long_saturday">शनिवार</string>
-
-    <string name="day_of_week_medium_sunday">रवि</string>
-    <string name="day_of_week_medium_monday">सोम</string>
-    <string name="day_of_week_medium_tuesday">मंगल</string>
-    <string name="day_of_week_medium_wednesday">बुध</string>
-    <string name="day_of_week_medium_thursday">गुरु</string>
-    <string name="day_of_week_medium_friday">शुक्र</string>
-    <string name="day_of_week_medium_saturday">शनि</string>
-
-    <string name="day_of_week_short_sunday">रवि</string>
-    <string name="day_of_week_short_monday">सोम</string>
-    <string name="day_of_week_short_tuesday">मंगल</string>
-    <string name="day_of_week_short_wednesday">बुध</string>
-    <string name="day_of_week_short_thursday">गुरु</string>
-    <string name="day_of_week_short_friday">शुक्र</string>
-    <string name="day_of_week_short_saturday">शनि</string>
-
-    <string name="day_of_week_shortest_sunday">र</string>
-    <string name="day_of_week_shortest_monday">सो</string>
-    <string name="day_of_week_shortest_tuesday">मं</string>
-    <string name="day_of_week_shortest_wednesday">बु</string>
-    <string name="day_of_week_shortest_thursday">गु</string>
-    <string name="day_of_week_shortest_friday">शु</string>
-    <string name="day_of_week_shortest_saturday">श</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 6a43298..65aa563 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"फ़ोन विकल्‍प"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"स्‍क्रीन लॉक"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"पावर बंद"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"बग रिपोर्ट"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"बग रिपोर्ट प्राप्त करें"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"ईमेल संदेश के रूप में भेजने के लिए, इसके द्वारा आपके उपकरण की वर्तमान स्थिति के बारे में जानकारी एकत्र की जाएगी. बग रिपोर्ट प्रारंभ करने से लेकर भेजने के लिए तैयार होने तक कुछ समय लगेगा; कृपया धैर्य रखें."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"मौन मोड"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"ध्‍वनि बंद है"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"ध्‍वनि चालू है"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"आपके संदेश"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"अपने SMS, ईमेल, और अन्य संदेशों को पढ़ें और लिखें."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"आपकी निजी जानकारी"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"टेबलेट पर संग्रहीत आपके संपर्कों और कैलेंडर में सीधे पहुंचें."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"फ़ोन पर संग्रहीत आपके संपर्कों और कैलेंडर में सीधे पहुंचें."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"अपने संपर्क कार्ड में संग्रहीत, अपनी जानकारी पर सीधी पहुंच."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"आपकी सामाजिक जानकारी"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"अपने संपर्कों और सामाजिक कनेक्‍शन के बारे में जानकारी पर सीधी पहुंच."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"आपका स्‍थान"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"अपने भौतिक स्‍थान पर नज़र रखें."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"नेटवर्क संचार"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"विभिन्‍न नेटवर्क सुविधाओं पर पहुंचें."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Bluetooth के माध्‍यम से उपकरणों और नेटवर्क पर पहुंचें."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"ऑडियो सेटिंग"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"ऑडियो सेटिंग बदलें."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"बैटरी प्रभावित होती है"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"उन सुविधाओं का उपयोग करें जो बैटरी की खपत तेज़ी से कर सकती हैं."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"कैलेंडर"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"कैलेंडर और ईवेंट पर सीधी पहुंच."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"उपयोगकर्ता डिक्‍शनरी पढ़ें"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"उपयोगकर्ता डिक्‍शनरी में शब्‍द पढ़ें."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"उपयोगकर्ता डिक्‍शनरी में लिखें"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"उपयोगकर्ता डिक्‍शनरी में शब्‍द जोड़ें."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"बुकमार्क और इतिहास"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"बुकमार्क और ब्राउज़र इतिहास पर सीधी पहुंच."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"अलार्म"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"अलार्म घड़ी सेट करें."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"ध्वनिमेल"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"ध्‍वनिमेल पर सीधी पहुंच."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"माइक्रोफ़ोन"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"ऑडियो रिकॉर्ड करने के लिए माइक्रोफ़ोन पर सीधी पहुंच."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"कैमरा"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"चित्र या वीडियो कैप्‍चर के लिए कैमरे पर सीधी पहुंच."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"आपके एप्‍लिकेशन की जानकारी"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"अपने उपकरण पर अन्‍य एप्‍लिकेशन के व्‍यवहार को प्रभावित करने की क्षमता."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"वॉलपेपर"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"उपकरण की वॉलपेपर सेटिंग बदलें."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"घड़ी"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"उपकरण का समय या समय क्षेत्र बदलें."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"स्थिति बार"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"उपकरण के स्‍थिति बार की सेटिंग बदलें."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"समन्वयन सेटिंग"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"समन्‍वयन सेटिंग पर पहुंचें."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"आपके खाते"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"उपलब्‍ध खातों में पहुंचें."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"हार्डवेयर नियंत्रण"</string>
@@ -184,10 +220,12 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"सिस्‍टम का निम्‍न-स्‍तर पहुंच और नियंत्रण."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"डेवलपमेंट टूल"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"सुविधाएं जो केवल एप्लिकेशन डेवलपर के लिए आवश्यक हैं."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"अन्‍य एप्‍लिकेशन UI"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"अन्‍य एप्‍लिकेशन के UI को प्रभावित करें."</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="permlab_statusBar" msgid="7417192629601890791">"स्‍थिति बार अक्षम या बदलें"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"एप्लिकेशन को स्थिति बार अक्षम करने या सिस्‍टम आइकन को जोड़ने या निकालने देता है."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"स्‍थिति बार"</string>
     <string name="permdesc_statusBarService" msgid="716113660795976060">"एप्‍लिकेशन को स्‍थिति बार होने देता है."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"एप्लिकेशन को WAP संदेशों को प्राप्‍त और संसाधित करने देता है. इस अनुमति में आपको भेजे गए संदेशों की निगरानी आपको दिखाए बिना करने और हटाने की क्षमता शामिल है."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"चल रहे एप्‍लिकेशन पुनर्प्राप्त करें"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"एप्लिकेशन को वर्तमान में और हाल ही में चल रहे कार्यों के बारे में जानकारी को पुन: प्राप्‍त करने देता है. इससे एप्लिकेशन उपकरण पर उपयोग किए गए एप्लिकेशन के बारे में जानकारी खोज सकता है."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"उपयोगकर्ताओं के बीच सहभागिता करें"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"एप्लिकेशन को उपकरण पर भिन्न उपयोगकर्ताओं के बीच कार्य निष्पादित करने देता है. दुर्भावनापूर्ण एप्लिकेशन उपयोगकर्ताओं के बीच सुरक्षा का उल्लंघन करने के लिए इसका उपयोग कर सकते हैं."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"उपयोगकर्ताओं के बीच सहभागिता करने के लिए पूर्ण लाइसेंस"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"उपयोगकर्ताओं के बीच सभी संभव सहभागिता करने देता है."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"उपयोगकर्ता प्रबंधित करें"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"एप्लिकेशन को उपकरण पर क्वेरी, निर्माण और हटाने सहित उपयोगकर्ताओं को प्रबंधित करने की सुविधा देता है."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"चल रहे एप्‍लिकेशन के विवरण प्राप्त करें"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"एप्लिकेशन को वर्तमान में और हाल ही में चल रहे कार्यों की जानकारी प्राप्त करने देता है. दुर्भावनापूर्ण एप्लिकेशन अन्य एप्लिकेशन के बारे में निजी जानकारी खोज सकते हैं."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"चल रहे एप्‍लिकेशन पुन: क्रमित करें"</string>
@@ -230,7 +274,7 @@
     <string name="permlab_setDebugApp" msgid="3022107198686584052">"एप्‍लिकेशन डीबग करना सक्षम करें"</string>
     <string name="permdesc_setDebugApp" msgid="4474512416299013256">"एप्लिकेशन को अन्य एप्लिकेशन के लिए डीबग किया जाना चालू करने देता है. दुर्भावनापूर्ण एप्लिकेशन इसका उपयोग अन्य एप्लिकेशन को समाप्त करने के लिए कर सकते हैं."</string>
     <string name="permlab_changeConfiguration" msgid="4162092185124234480">"सिस्‍टम प्रदर्शन सेटिंग बदलें"</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="permlab_killBackgroundProcesses" msgid="3914026687420177202">"अन्‍य एप्‍लिकेशन बंद करें"</string>
@@ -243,6 +287,14 @@
     <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="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"पहुंच-योग्यता को अस्थायी रूप से सक्षम करें"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"एप्लिकेशन को उपकरण पर पहुंच-योग्यता को अस्थायी रूप से सक्षम करने देता है. दुर्भावनापूर्ण एप्लिकेशन उपयोगकर्ता की सहमति के बिना पहुंच-योग्यता को सक्षम कर सकते हैं."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"विंडो जानकारी प्राप्त करें"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"एप्‍लिकेशन को विंडो प्रबंधक से windows के बारे में जानकारी प्राप्त करने देता है. दुर्भावनापूर्ण एप्‍लिकेशन आंतरिक सिस्टम उपयोग के लिए अभिप्रेत जानकारी को प्राप्त कर सकते हैं."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"ईवेंट फ़िल्टर करें"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"एप्‍लिकेशन को इनपुट फ़िल्‍टर पंजीकृत करने देता है, जो सभी उपयोगकर्ता ईवेंट के स्‍ट्रीम को भेजे जाने से पहले फ़िल्‍टर करता है. दुर्भावनापूर्ण एप्‍लिकेशन उपयोगकर्ता के हस्‍तक्षेप के बिना सिस्‍टम UI को नियंत्रित कर सकता है."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"डिस्प्ले को आवर्धित करें"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"एप्लिकेशन को डिस्प्ले की सामग्री आवर्धित करने देता है. दुर्भावनापूर्ण एप्लिकेशन डिस्प्ले सामग्री को इस तरह से बदल सकते हैं कि उपकरण अनुपयोगी रेंडर होता है."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"आंशिक शटडाउन"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"गतिविधि प्रबंधक को शटडाउन स्‍थिति में रखता है. पूर्ण शटडाउन निष्‍पादित नहीं करता है."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"एप्‍लिकेशन स्‍विच करने से रोकता है"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"एप्लिकेशन को चलाई जाने वाली अधिकतम प्रक्रियाओं को नियंत्रित करने देता है. सामान्य एप्लिकेशन के लिए कभी आवश्यक नहीं होती."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"पृष्ठभूमि एप्‍लिकेशन को बलपूर्वक बंद करें"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"एप्लिकेशन को यह नियंत्रित करने देता है कि पृष्ठभूमि में जाते ही गतिविधियां पूर्ण हो जाती है या नही. सामान्य एप्लिकेशन के लिए कभी आवश्यकता नहीं होती."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"बैटरी आंकड़े संशोधित करें"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"एप्‍लिकेशन को बैटरी के संकलित आंकड़ों को संशोधित करने देता है. सामान्‍य एप्‍लिकेशन द्वारा उपयोग करने के लिए नहीं."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"बैटरी के आंकड़े पढ़ें"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"एप्लिकेशन को वर्तमान निम्न-स्तरीय बैटरी उपयोग डेटा पढ़ने देती है. एप्लिकेशन को आपके द्वारा उपयोग किए जाने वाले एप्लिकेशन के बारे में विस्तृत जानकारी ढूंढने दे सकती है."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"बैटरी के आंकड़े संशोधित करें"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"एप्‍लिकेशन को बैटरी के संकलित आंकड़ों को संशोधित करने देती है. सामान्‍य एप्‍लिकेशन के द्वारा उपयोग करने के लिए नहीं."</string>
     <string name="permlab_backup" msgid="470013022865453920">"सिस्‍टम बैकअप नियंत्रित और पुनर्स्‍थापित करें"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"एप्लिकेशन को सिस्टम के बैकअप को नियंत्रित और क्रियाविधि को पुर्नस्थापित करने देता है. सामान्‍य एप्‍लिकेशन द्वारा उपयोग करने के लिए नहीं."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"पूर्ण बैकअप या पुनर्स्‍थापना कार्यवाही की पुष्टि करें"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"अनधिकृत विंडो दिखाएं"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"किसी एप्‍लिकेशन को ऐसी विंडो बनाने देता है जिनका उपयोग आंतरिक सिस्‍टम उपयोगकर्ता इंटरफ़ेस द्वारा किया जाना है. सामान्‍य एप्‍लिकेशन द्वारा उपयोग करने के लिए नहीं."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"अन्‍य एप्‍लिकेशन पर खींचें"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"एप्लिकेशन को सिस्टम अलर्ट विंडो प्रदर्शित करने देता है. कुछ अलर्ट विंडो संपूर्ण स्क्रीन को घेर सकते हैं."</string>
-    <string name="permlab_setAnimationScale" msgid="2805103241153907174">"वैश्विक एनिमेशन गति संशोधित करें"</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"एप्लिकेशन को अन्य एप्लिकेशन के शीर्ष पर या उपयोगकर्ता इंटरफ़ेस के हिस्सों पर आने देती है. वे किसी भी एप्लिकेशन में इंटरफ़ेस के आपके उपयोग में हस्तक्षेप कर सकते हैं, या उस चीज को बदल सकती है जिसके बारे में आपको लगता है कि आप उसे अन्य एप्लिकेशन में देख रहे हैं."</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="permlab_freezeScreen" msgid="4708181184441880175">"स्क्रीन को स्थिर करें"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"पूर्ण-स्क्रीन संक्रमण के लिए एप्लिकेशन को अस्थायी रूप से स्क्रीन को स्थिर करने देता है."</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>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"सीधे एप्‍लिकेशन इंस्‍टॉल करें"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"एप्लिकेशन को नए या अपडेट किए गए Android पैकेज इंस्टॉल करने देता है. दुर्भावनापूर्ण एप्लिकेशन इसका उपयोग अनियंत्रित रूप से सशक्त अनुमतियों वाले नए एप्लिकेशन जोड़ने में कर सकते हैं."</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="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"एप्लिकेशन को अन्य एप्लिकेशन की संचय निर्देशिकाओं में से फ़ाइलें हटाकर टेबलेट संग्रहण को खाली करने देती है. इससे अन्य एप्लिकेशन अधिक धीमे प्रारंभ हो सकते हैं क्योंकि उन्हें अपना डेटा पुनर्प्राप्त करने की आवश्यकता होती है."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"एप्लिकेशन को अन्य एप्लिकेशन की संचय निर्देशिकाओं में से फ़ाइलें हटाकर फ़ोन संग्रहण को खाली करने देती है. इससे अन्य एप्लिकेशन अधिक धीमे प्रारंभ हो सकते हैं क्योंकि उन्हें अपना डेटा पुनर्प्राप्त करने की आवश्यकता होती है."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"एप्‍लिकेशन संसाधनों को ले जाएं"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"एप्‍लिकेशन को एप्‍लिकेशन संसाधनों को आंतरिक से बाहरी मीडिया में और इसके विपरीत ले जाने देता है."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"संवेदनशील लॉग डेटा पढ़ें"</string>
@@ -332,11 +388,11 @@
     <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"एप्लिकेशन को उसके या अन्य एप्लिकेशन के लिए विशेष अनुमतियां देने या रद्द करने देता है. दुर्भावनापूर्ण एप्लिकेशन इसका उपयोग उन सुविधाओं तक पहुंचने के लिए कर सकते हैं जो आपने उन्हें नहीं दी हैं."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"पसंदीदा एप्‍लिकेशन सेट करें"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"एप्लिकेशन को आपके पसंदीदा एप्लिकेशन को संशोधित करने देता है. दुर्भावनापूर्ण एप्लिकेशन आपसे निजी डेटा एकत्रित करने के लिए आपके मौजूदा एप्लिकेशन को स्पूफ़ करके, चलाए जाने वाले एप्लिकेशन को चुपचाप बदल सकते हैं."</string>
-    <string name="permlab_writeSettings" msgid="2226195290955224730">"सिस्‍टम सेटिंग संशोधित करें"</string>
+    <string name="permlab_writeSettings" msgid="2226195290955224730">"सिस्‍टम सेटिंग बदलें"</string>
     <string name="permdesc_writeSettings" msgid="7775723441558907181">"एप्लिकेशन को सिस्टम सेटिंग डेटा संशोधित करने देता है. दुर्भावनापूर्ण एप्लिकेशन आपके सिस्टम के कॉन्फ़िगरेशन को दूषित कर सकते हैं."</string>
-    <string name="permlab_writeSecureSettings" msgid="204676251876718288">"सुरक्षित सिस्‍टम सेटिंग संशोधित करें"</string>
+    <string name="permlab_writeSecureSettings" msgid="204676251876718288">"सुरक्षित सिस्‍टम सेटिंग बदलें"</string>
     <string name="permdesc_writeSecureSettings" msgid="8159535613020137391">"एप्लिकेशन को सिस्टम के सुरक्षित सेटिंग डेटा को संशोधित करने देता है. सामान्‍य एप्‍लिकेशन द्वारा उपयोग करने के लिए नहीं."</string>
-    <string name="permlab_writeGservices" msgid="2149426664226152185">"Google सेवाएं मैप संशोधित करें"</string>
+    <string name="permlab_writeGservices" msgid="2149426664226152185">"Google सेवाएं मैप बदलें"</string>
     <string name="permdesc_writeGservices" msgid="1287309437638380229">"एप्‍लिकेशन को Google सेवाओं का मानचित्र संशोधित करने देता है. सामान्‍य एप्‍लिकेशन द्वारा उपयोग करने के लिए नहीं."</string>
     <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"प्रारंभ होने पर चलाएं"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"एप्लिकेशन को सिस्टम द्वारा बूटिंग पूर्ण करते ही स्वतः आरंभ करने देता है. इससे टेबलेट को आरंभ होने में अधिक समय लग सकता है और एप्लिकेशन को निरंतर चलाकर संपूर्ण टेबलेट को धीमा करने देता है."</string>
@@ -347,7 +403,7 @@
     <string name="permlab_readContacts" msgid="8348481131899886131">"अपने संपर्क पढ़ें"</string>
     <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"एप्लिकेशन को आपके टेबलेट में संग्रहीत संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्‍य तरीके से संवाद करने की आवृत्ति को पढ़ने देता है. यह अनुमति एप्लिकेशन को आपके संपर्क डेटा को सहेजने देती है, और दुर्भावनापूर्ण एप्लिकेशन आपकी जानकारी के बिना संपर्क डेटा को साझा कर सकते हैं."</string>
     <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"एप्लिकेशन को आपके फ़ोन में संग्रहीत संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्‍य तरीके से संवाद करने की आवृत्ति को पढ़ने देता है. यह अनुमति एप्लिकेशन को आपके संपर्क डेटा को सहेजने देती है, और दुर्भावनापूर्ण एप्लिकेशन आपकी जानकारी के बिना संपर्क डेटा को साझा कर सकते हैं."</string>
-    <string name="permlab_writeContacts" msgid="5107492086416793544">"अपने संपर्क संशोधित करें"</string>
+    <string name="permlab_writeContacts" msgid="5107492086416793544">"अपने संपर्क बदलें"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"एप्लिकेशन को आपके टेबलेट में संग्रहीत संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्‍य तरीके से संवाद करने की आवृत्ति को संशोधित करने देता है. यह अनुमति एप्लिकेशन को आपके संपर्क डेटा को हटाने देती है."</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"एप्लिकेशन को आपके फ़ोन में संग्रहीत संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्‍य तरीके से संवाद करने की आवृत्ति को संशोधित करने देता है. यह अनुमति एप्लिकेशन को आपके संपर्क डेटा को हटाने देती है."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"कॉल लॉग पढ़ें"</string>
@@ -358,7 +414,7 @@
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"एप्‍लिकेशन को इनकमिंग और आउटगोइंग कॉल के डेटा सहित, आपके फ़ोन का कॉल लॉग संशोधित करने देता है. दुर्भावनापूर्ण एप्‍लिकेशन आपके कॉल लॉग को मिटाने या संशोधित करने के लिए इसका उपयोग कर सकते हैं."</string>
     <string name="permlab_readProfile" msgid="4701889852612716678">"स्‍वयं का संपर्क कार्ड पढ़ें"</string>
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"एप्लिकेशन को आपके उपकरण में संग्रहीत व्यक्तिगत प्रोफ़ाइल जानकारी, जैसे आपका नाम और संपर्क जानकारी, पढ़ने देता है. इसका अर्थ है कि एप्लिकेशन आपको पहचान सकता है और आपकी प्रोफ़ाइल जानकारी अन्य लोगों को भेज सकता है."</string>
-    <string name="permlab_writeProfile" msgid="907793628777397643">"स्‍वयं का संपर्क कार्ड संशोधित करें"</string>
+    <string name="permlab_writeProfile" msgid="907793628777397643">"स्‍वयं का संपर्क कार्ड बदलें"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"एप्लिकेशन को आपके उपकरण में संग्रहीत निजी प्रोफ़ाइल जानकारी, जैसे आपका नाम और संपर्क जानकारी को बदलने या उसमें कुछ जोड़ने देता है. इसका अर्थ है कि एप्लिकेशन आपको पहचान सकता है और आपकी प्रोफ़ाइल जानकारी अन्य लोगों को भेज सकता है."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"अपनी सामाजिक स्‍ट्रीम पढ़ें"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"एप्लिकेशन को आपके और आपके मित्रों के सामाजिक अपडेट तक पहुंचने और उन्हें समन्‍वयित करने देता है. जानकारी साझा करते समय सावधान रहें - इससे गोपनीयता पर ध्यान दिए बिना, एप्लिकेशन सामाजिक नेटवर्क पर आपके और आपके मित्रों के बीच संचारों को पढ़ सकता है. ध्‍यान दें: यह अनुमति सभी सामाजिक नेटवर्क पर लागू नहीं की जा सकती."</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"एप्लिकेशन को अतिरिक्त स्थान प्रदाता आदेशों पर पहुंचने देता है. यह एप्लिकेशन को GPS या अन्य स्थान स्रोतों के संचालन में बाधा पहुंचाने दे सकता है."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"किसी स्‍थान प्रदाता को इंस्‍टॉल करने की अनुमति"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"परीक्षण के लिए कृत्रिम स्थान स्रोत बनाएं या एक नए स्थान प्रदाता को इंस्‍टॉल करें. यह एप्लिकेशन को स्‍थान और/या अन्‍य स्थान स्रोतों जैसे GPS या स्‍थान प्रदाताओं द्वारा लौटाई गई स्थिति को ओवरराइड करने देता है."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"सटीक (GPS) स्‍थान"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"टेबलेट पर सटीक स्थान स्रोतों जैसे ग्लोबल पोजिशनिंग सिस्टम तक पहुंचें. जब स्थान सेवाएं उपलब्ध और चालू हैं, तो यह यह अनुमति एप्लिकेशन को आपका सटीक स्थान निर्धारित करने देती है."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"फ़ोन पर सटीक स्थान स्रोतों जैसे ग्लोबल पोजिशनिंग सिस्टम तक पहुंचें. जब स्थान सेवाएं उपलब्ध और चालू हों, तो यह अनुमति एप्लिकेशन को आपका सटीक स्थान निर्धारित करने देती है."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"अनुमानित (नेटवर्क-आधारित) स्‍थान"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"उपलब्‍ध नेटवर्क स्रोतों जैसे सेल टॉवर और WI- Fi का उपयोग करते हुए स्‍थान प्रदाताओं से अनुमानित स्थान तक पहुचें. जब ये स्थान सेवाएं उपलब्ध और चालू हों, तो यह अनुमति एप्लिकेशन को आपका अनुमानित स्थान निर्धारित करते देती है."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"सटीक स्थान (GPS और नेटवर्क-आधारित)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"एप्लिकेशन को ग्लोबल पोज़िशनिंग सिस्टम (GPS) या सेल टॉवर और Wi-Fi जैसे नेटवर्क स्थान स्रोतों का उपयोग करके आपका सटीक स्थान प्राप्त करने देती है. एप्लिकेशन द्वारा इन स्थान सेवाओं का उपयोग किए जाने के लिए इन्हें चालू होना चाहिए और आपके उपकरण पर उपलब्ध होना चाहिए. एप्लिकेशन इसका उपयोग यह पता करने में कर सकते हैं कि आप कहां पर हैं, और अतिरिक्त बैटरी की खपत कर सकते हैं."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"अनुमानित स्थान (नेटवर्क-आधारित)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"एप्लिकेशन को आपका अनुमानित स्थान प्राप्त करने देती है. इस स्थान को सेल टॉवर और Wi-Fi जैसे नेटवर्क स्थान स्रोतों का उपयोग करके स्थान सेवाओं द्वारा प्राप्त किया गया है. एप्लिकेशन द्वारा इन स्थान सेवाओं का उपयोग करने के लिए इन्हें चालू होना चाहिए और आपके उपकरण में उपलब्ध होना चाहिए. एप्लिकेशन इसका उपयोग यह पता लगाने में कर सकते हैं कि आप लगभग कहां पर हैं."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"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="permlab_configureWifiDisplay" msgid="5595661694746742168">"Wifi डिस्प्ले को कॉन्फ़िगर करें"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"एप्लिकेशन को कॉन्फ़िगर करने देता है और Wifi डिस्प्ले से कनेक्ट करता है."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wifi डिस्प्ले को नियंत्रित करें"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"एप्लिकेशन को Wifi डिस्प्ले की निम्न-स्तर की सुविधाएं नियंत्रित करने देता है."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"अपनी ऑडियो सेटिंग बदलें"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"एप्लिकेशन को वैश्विक ऑडियो सेटिंग, जैसे वॉल्‍यूम और कौन-सा स्पीकर आउटपुट के लिए उपयोग किया गया, संशोधित करने देता है."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ऑडियो रिकॉर्ड करें"</string>
@@ -438,7 +497,7 @@
     <string name="permdesc_checkinProperties" msgid="4024526968630194128">"एप्लिकेशन को चेकइन सेवा द्वारा अपलोड किए गए गुणों पर पढ़ें/लिखें पहुंच देता है. सामान्‍य एप्‍लिकेशन द्वारा उपयोग करने के लिए नहीं."</string>
     <string name="permlab_bindGadget" msgid="776905339015863471">"विजेट चुनें"</string>
     <string name="permdesc_bindGadget" msgid="8261326938599049290">"एप्लिकेशन को सिस्टम को यह बताने देता है कि किस एप्लिकेशन द्वारा कौन से विजेट का उपयोग किया जा सकता है. कोई एप्लिकेशन, इस अनुमति के साथ अन्य एप्लिकेशन के निजी डेटा पर पहुंच सकते हैं. सामान्‍य एप्‍लिकेशन द्वारा उपयोग करने के लिए नहीं."</string>
-    <string name="permlab_modifyPhoneState" msgid="8423923777659292228">"फ़ोन स्‍थिति संशोधित करें"</string>
+    <string name="permlab_modifyPhoneState" msgid="8423923777659292228">"फ़ोन स्‍थिति बदलें"</string>
     <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"एप्‍लिकेशन को उपकरण की फ़ोन सुविधाएं नियंत्रित करने देता है. इस अनुमति वाला कोई एप्‍लिकेशन आपको सूचित किए बिना नेटवर्क स्‍विच कर सकता है, फ़ोन का रेडियो चालू और बंद कर सकता है और ऐसे ही अन्य कार्य कर सकता है."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"फ़ोन की स्‍थिति और पहचान पढ़ें"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"एप्लिकेशन को उपकरण की फ़ोन सुविधाओं तक पहुंचने देता है. यह अनुमति एप्लिकेशन को फ़ोन नंबर और उपकरण आईडी, कॉल सक्रिय है या नहीं, और कॉल द्वारा कनेक्ट किया गया दूरस्‍थ नंबर निर्धारित करने देती है."</string>
@@ -455,7 +514,7 @@
     <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="permlab_setWallpaperHints" msgid="3278608165977736538">"अपने वॉलपेपर का आकार समायोजित करें"</string>
+    <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"अपने वॉलपेपर का आकार एडजस्ट करें"</string>
     <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"एप्‍लिकेशन को सिस्‍टम वॉलपेपर आकार संकेत सेट करने देता है."</string>
     <string name="permlab_masterClear" msgid="2315750423139697397">"फ़ैक्‍ट्री डिफ़ॉल्‍ट पर सिस्‍टम रीसेट करें"</string>
     <string name="permdesc_masterClear" msgid="3665380492633910226">"एप्लिकेशन को सभी डेटा, कॉन्फ़िगरेशन, और इंस्टॉल एप्लिकेशन मिटाकर, सिस्टम को पूरी तरह उसकी फ़ैक्टरी सेटिंग पर रीसेट करने देता है."</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"Bluetooth सेटिंग पर पहुंचें"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"किसी एप्‍लिकेशन को स्‍थानीय Bluetooth टेबलेट कॉन्‍फ़िगर करने की और रिमोट उपकरणों के साथ खोजने और युग्‍मित करने देता है."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"एप्‍लिकेशन को स्‍थानीय Bluetooth फ़ोन कॉन्‍फ़िगर करने देता है, और रिमोट उपकरणों के साथ खोजने और युग्‍मित करने देता है."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"WiMAX कनेक्‍शन देखें"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX से कनेक्ट और डिस्कनेक्ट करें"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"एप्लिकेशन को WiMAX सक्षम है या नहीं और कनेक्‍ट किए गए किसी WiMAX नेटवर्क के बारे में जानकारी निर्धारित करने देता है."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX स्‍थिति बदलें"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"एप्‍लिकेशन को WiMAX नेटवर्क से टेबलेट को कनेक्‍ट और डिस्‍कनेक्‍ट करने देता है."</string>
@@ -522,18 +581,20 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"एप्लिकेशन को आपके वर्तमान समन्वयित फ़ीड को संशोधित करने देता है. दुर्भावनापूर्ण एप्लिकेशन आपके समन्वयित फ़ीड को बदल सकते है."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"डिक्शनरी में आपके द्वारा जोड़े गए शब्‍दों को पढ़ें"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"एप्‍लिकेशन को ऐसे सभी शब्‍दों, नामों और वाक्यांशों को पढ़ने देता है जो संभवत: उपयोगकर्ता द्वारा उपयोगकर्ता ‍डिक्शनरी में संग्रहीत किए गए हों."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"उपयोगकर्ता-निर्धारित डिक्शनरी में लिखें"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"उपयोगकर्ता द्वारा परिभाषित डिक्शनरी में शब्द जोड़ें"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"एप्लिकेशन को उपयोगकर्ता डिक्शनरी में नए शब्द लिखने देता है."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"संरक्ष‍ित संग्रहण पर पहुंच का परीक्षण करें"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"संरक्ष‍ित संग्रहण पर पहुंच का परीक्षण करें"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"एप्लि. को USB संग्रहण अनुमति जांचने देता है जो भावी उपकरणों में उपलब्‍ध होगा."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"एप्लि. को USB संग्रहण अनुमति का परीक्षण करने देता है जो भविष्‍य के उपकरणों में उपलब्‍ध होगा."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"एप्लिकेशन को SD कार्ड के लिए किसी अनुमति का परीक्षण करने देता है जो भविष्‍य के उपकरणों में उपलब्‍ध होगा."</string>
-    <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"अपने USB संग्रहण की सामग्री संशोधित करें या हटाएं"</string>
-    <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"अपने SD कार्ड की सामग्री संशोधित करें या हटाएं"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"अपने USB संग्रहण की सामग्री बदलें या हटाएं"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"अपने 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="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"आंतरिक मीडिया संग्रहण सामग्रियों को बदलें/हटाएं"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"एप्लिकेशन को आंतरिक मीडिया संग्रहण की सामग्री को संशोधित करने देता है."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"सभी उपयोगकर्ताओं के बाहरी संग्रहण तक पहुंचें"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"एप्लिकेशन को सभी उपयोगकर्ताओं के बाहरी संग्रहण तक पहुंचने दें."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"कैश फ़ाइल सिस्‍टम में पहंचे"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"एप्‍लिकेशन को संचय फ़ाइल सिस्‍टम पढ़ने और लिखने देता है."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"इंटरनेट कॉल करें/प्राप्त करें"</string>
@@ -542,7 +603,7 @@
     <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"किसी एप्लिकेशन को विशिष्ट नेटवर्क और एप्‍लिकेशन के लिए ऐतिहासिक नेटवर्क उपयोग को पढ़ने देता है."</string>
     <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"नेटवर्क नीति प्रबंधित करें"</string>
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"एप्‍लिकेशन को नेटवर्क नीतियां प्रबंधित करने और एप्‍लिकेशन-विशिष्‍ट नियमों को परिभाषित करने देता है."</string>
-    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"नेटवर्क उपयोग हिसाब संशोधित करें"</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"नेटवर्क उपयोग हिसाब बदलें"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"एप्लिकेशन को यह संशोधित करने देता है कि एप्‍लिकेशन की तुलना में नेटवर्क उपयोग का मूल्यांकन कैसे किया जाता है. सामान्‍य एप्‍लिकेशन द्वारा उपयोग करने के लिए नहीं."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियम सेट करें"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"स्‍क्रीन-अनलॉक पासवर्ड में अनुमति प्राप्त लंबाई और वर्णों को नियंत्रित करें."</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"संग्रहीत एप्‍लिकेशन डेटा को एन्क्रिप्ट किया जाना आवश्‍यक है."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"कैमरों को अक्षम करें"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"सभी उपकरण कैमरों का उपयोग रोकें."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"कीगार्ड में सुविधाएं अक्षम करें"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"कीगार्ड में कुछ सुविधाओं का उपयोग रोकें."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"घर"</item>
     <item msgid="869923650527136615">"मोबाइल"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"पुनः प्रयास करें"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"फेस अनलॉक के अधिकतम प्रयासों की सीमा पार हो गई"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"चार्ज हो रही है, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"चार्ज हो चुकी है."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"चार्ज हो गया"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"अपना चार्जर कनेक्‍ट करें."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"कोई सिम कार्ड नहीं है."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"कोई सिम कार्ड नहीं है"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"टेबलेट में कोई सिम कार्ड नहीं है."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"फ़ोन में कोई सिम कार्ड नहीं है."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"कोई सिमकार्ड डालें."</string>
@@ -711,7 +774,7 @@
     <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"आपका सिम कार्ड स्‍थायी रूप से अक्षम कर दिया गया है."\n" दूसरे SIM कार्ड के लिए अपने वायरलेस सेवा प्रदाता से संपर्क करें."</string>
     <string name="lockscreen_transport_prev_description" msgid="201594905152746886">"पिछला ट्रैक बटन"</string>
     <string name="lockscreen_transport_next_description" msgid="6089297650481292363">"अगला ट्रैक बटन"</string>
-    <string name="lockscreen_transport_pause_description" msgid="7659088786780128001">"रोकें बटन"</string>
+    <string name="lockscreen_transport_pause_description" msgid="7659088786780128001">"पॉज़ करें बटन"</string>
     <string name="lockscreen_transport_play_description" msgid="5888422938351019426">"चलाएं बटन"</string>
     <string name="lockscreen_transport_stop_description" msgid="4562318378766987601">"रोकें बटन"</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"केवल आपातकालीन कॉल"</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"प्रतिमान साफ़ किया गया"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"कक्ष जोड़ा गया"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"प्रतिमान पूरा किया गया"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"विजेट जोड़ें"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"रिक्त"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"अनलॉक क्षेत्र को विस्तृत कर दिया गया."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"अनलॉक क्षेत्र को संक्षिप्त कर दिया गया."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> विजेट."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"उपयोगकर्ता चयनकर्ता"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"स्थिति"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"कैमरा"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"मीडिया नियंत्रण"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"विजेट पुनः क्रमित करना प्रारंभ."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"विजेट पुनः क्रमित करना समाप्त."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"विजेट <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> को हटा दिया गया."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"अनलॉक क्षेत्र विस्तृत करें."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"स्लाइड अनलॉक."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"प्रतिमान अनलॉक."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"फेस अनलॉक."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"पिन अनलॉक."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"पासवर्ड अनलॉक."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"प्रतिमान क्षेत्र."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"स्लाइड क्षेत्र."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -762,7 +845,7 @@
     <string name="factorytest_reboot" msgid="6320168203050791643">"रीबूट करें"</string>
     <string name="js_dialog_title" msgid="1987483977834603872">"\'<xliff:g id="TITLE">%s</xliff:g>\' पर यह पृष्ठ दर्शाता है:"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
-    <string name="js_dialog_before_unload" msgid="730366588032430474">"इस पृष्ठ से दूर नेविगेट करें?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"जारी रखने के लिए ठीक का चयन करें, या वर्तमान पृष्ठ पर रहने के लिए रद्द करें का चयन करें."</string>
+    <string name="js_dialog_before_unload" msgid="730366588032430474">"इस पृष्ठ से दूर नेविगेट करें?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"जारी रखने के लिए ठीक को चुनें, या वर्तमान पृष्ठ पर रहने के लिए रद्द करें को चुनें."</string>
     <string name="save_password_label" msgid="6860261758665825069">"पुष्टि करें"</string>
     <string name="double_tap_toast" msgid="4595046515400268881">"युक्ति: ज़ूम इन और आउट करने के लिए डबल-टैप करें."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"स्‍वत: भरण"</string>
@@ -792,7 +875,7 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"एप्‍लिकेशन को इंस्‍टॉल किए गए अलार्म घड़ी एप्‍लिकेशन में अलार्म सेट करने देता है. हो सकता है कुछ अलार्म घड़ी एप्‍लिकेशन में यह सुविधा न हो."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"ध्‍वनिमेल जोड़ें"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"एप्लिकेशन को आपके ध्‍वनिमेल इनबॉक्‍स में संदेश जोड़ने देता है."</string>
-    <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ब्राउज़र भौगोलिक-स्थान अनुमतियों को संशोधित करें"</string>
+    <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ब्राउज़र भौगोलिक-स्थान अनुमतियों को बदलें"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"एप्‍लिकेशन को ब्राउज़र के भौगोलिक-स्‍थान की अनुमतियां संशोधित करने देता है. दुर्भावनापूर्ण एप्‍लिकेशन इसका उपयोग एकपक्षीय वेबसाइट को स्‍थान जानकारी भेजने में कर सकते हैं."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"पैकेज सत्‍यापि‍त करें"</string>
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"एप्‍लि‍केशन को इंस्‍टॉल करने योग्‍य पैकेज सत्‍यापि‍त करने देता है."</string>
@@ -921,17 +1004,17 @@
     <string name="Midnight" msgid="5630806906897892201">"मध्‍यरात्रि"</string>
     <string name="elapsed_time_short_format_mm_ss" msgid="4431555943828711473">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
     <string name="elapsed_time_short_format_h_mm_ss" msgid="1846071997616654124">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
-    <string name="selectAll" msgid="6876518925844129331">"सभी का चयन करें"</string>
+    <string name="selectAll" msgid="6876518925844129331">"सभी को चुनें"</string>
     <string name="cut" msgid="3092569408438626261">"काटें"</string>
     <string name="copy" msgid="2681946229533511987">"प्रतिलिपि बनाएं"</string>
     <string name="paste" msgid="5629880836805036433">"चिपकाएं"</string>
     <string name="replace" msgid="5781686059063148930">"बदलें•"</string>
     <string name="delete" msgid="6098684844021697789">"हटाएं"</string>
     <string name="copyUrl" msgid="2538211579596067402">"URL की प्रतिलिपि बनाएं"</string>
-    <string name="selectTextMode" msgid="1018691815143165326">"पाठ का चयन करें"</string>
+    <string name="selectTextMode" msgid="1018691815143165326">"पाठ को चुनें"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"पाठ चयन"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"डिक्‍शनरी में जोड़ें"</string>
-    <string name="deleteText" msgid="7070985395199629156">"हटाएं"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"शब्दकोश में जोड़ें"</string>
+    <string name="deleteText" msgid="6979668428458199034">"हटाएं"</string>
     <string name="inputMethod" msgid="1653630062304567879">"इनपुट विधि"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"पाठ क्रियाएं"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"संग्रहण स्‍थान समाप्‍त हो रहा है"</string>
@@ -982,7 +1065,7 @@
     <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="sendText" msgid="5209874571959469142">"पाठ के लिए किसी क्रिया का चयन करें"</string>
+    <string name="sendText" msgid="5209874571959469142">"पाठ के लिए किसी क्रिया को चुनें"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"रिंगर वॉल्‍यूम"</string>
     <string name="volume_music" msgid="5421651157138628171">"मीडिया वॉल्‍यूम"</string>
     <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"Bluetooth द्वारा चलाया जा रहा है"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"खुले Wi-Fi नेटवर्क उपलब्‍ध है"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Wi-Fi नेटवर्क में साइन इन करें"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"नेटवर्क में साइन इन करें"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi से कनेक्‍ट नहीं हो सका"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" के पास एक कमज़ोर इंटरनेट कनेक्‍शन है."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"प्रति:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"आवश्‍यक पिन लिखें:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"पिन:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"फ़ोन <xliff:g id="DEVICE_NAME">%1$s</xliff:g> से कनेक्ट रहते समय Wi-Fi से अस्थायी रूप से डिस्कनेक्ट हो जाएगा"</string>
     <string name="select_character" msgid="3365550120617701745">"वर्ण सम्‍मिलित करें"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS संदेश भेज रहा है"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; बड़ी संख्या में SMS संदेश भेज रहा है. क्या आप इस एप्लिकेशन को संदेश भेजना जारी रखने देना चाहते हैं?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"अनुमति दें"</string>
     <string name="sms_control_no" msgid="625438561395534982">"अस्वीकार करें"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;, &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; पर संदेश भेजना चाहता है."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"इससे आपके मोबाइल खाते पर "<font fgcolor="#ffffb060">"शुल्क लग सकते हैं"</font>"."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"इससे आपके मोबाइल खाते पर शुल्क लगेंगे."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"भेजें"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"रद्द करें"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"मेरी पसंद को याद रखें"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"आप इसे बाद में सेटिंग &gt; एप्लिकेशन में बदल सकते हैं"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"हमेशा अनुमति दें"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"कभी भी अनुमति न दें"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"सिमकार्ड निकाला गया"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"मान्‍य सि‍म कार्ड डालकर पुन: प्रारंभ करने तक मोबाइल नेटवर्क अनुपलब्‍ध रहेगा."</string>
     <string name="sim_done_button" msgid="827949989369963775">"पूर्ण"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"दिनांक सेट करें"</string>
     <string name="date_time_set" msgid="5777075614321087758">"सेट करें"</string>
     <string name="date_time_done" msgid="2507683751759308828">"पूर्ण"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"डिफ़ॉल्ट"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"किसी अनुमति की आवश्‍यकता नहीं है"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"छुपाएं"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"सभी दिखाएं"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"नया: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"नया: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"<xliff:g id="APP_NAME">%1$s</xliff:g> द्वारा प्रदत्त."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"किसी अनुमति की आवश्‍यकता नहीं है"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"इससे आपको धन देना पड़ सकता है"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB विशाल संग्रहण"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB कनेक्ट किया गया"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"आप USB द्वारा अपने कंप्‍यूटर से कनेक्‍ट हो चुके हैं. यदि आप अपने कंप्‍यूटर और Android के USB संग्रहण के बीच फ़ाइलों की प्रतिलिपि बनाना चाहते हैं तो नीचे दिया गया बटन स्‍पर्श करें."</string>
@@ -1057,7 +1149,7 @@
     <string name="usb_storage_error_message" product="nosdcard" msgid="3017045217365540658">"USB विशाल संग्रहण के लिए आपके USB संग्रहण का उपयोग करने में समस्‍या है."</string>
     <string name="usb_storage_error_message" product="default" msgid="2876018512716970313">"USB विशाल संग्रहण के लिए आपके SD कार्ड का उपयोग करने में समस्‍या है."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB कनेक्ट किया गया"</string>
-    <string name="usb_storage_notification_message" msgid="939822783828183763">"आपके कंप्‍यूटर में/से फ़ाइल की प्रतिलिपि बनाने के लिए चयन करें."</string>
+    <string name="usb_storage_notification_message" msgid="939822783828183763">"आपके कंप्‍यूटर में/से फ़ाइल की प्रतिलिपि बनाने के लिए चुनें."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"USB संग्रहण बंद करें"</string>
     <string name="usb_storage_stop_notification_message" msgid="1656852098555623822">"USB संग्रहण बंद करने के लिए स्‍पर्श करें."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB संग्रहण उपयोग में है"</string>
@@ -1085,7 +1177,7 @@
     <string name="configure_input_methods" msgid="9091652157722495116">"इनपुट पद्धतियां सेट करें"</string>
     <string name="use_physical_keyboard" msgid="6203112478095117625">"भौतिक कीबोर्ड"</string>
     <string name="hardware" msgid="7517821086888990278">"हार्डवेयर"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"कीबोर्ड लेआउट का चयन करें"</string>
+    <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"कीबोर्ड लेआउट को चुनें"</string>
     <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"कीबोर्ड लेआउट का चयन करने के लिए स्‍पर्श करें."</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN को <xliff:g id="APP">%s</xliff:g> द्वारा सक्रिय किया गया है"</string>
     <string name="vpn_text" msgid="3011306607126450322">"नेटवर्क प्रबंधित करने के लिए स्‍पर्श करें."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"<xliff:g id="SESSION">%s</xliff:g> से कनेक्‍ट किया गया. नेटवर्क प्रबंधित करने के लिए स्‍पर्श करें."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"हमेशा-चालू VPN कनेक्ट हो रहा है…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"हमेशा-चालू VPN कनेक्ट है"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"हमेशा-चालू VPN त्रुटि"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"कनेक्शन रीसेट करने के लिए स्पर्श करें"</string>
     <string name="upload_file" msgid="2897957172366730416">"फ़ाइल चुनें"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"कोई फ़ाइल चुनी नहीं गई"</string>
     <string name="reset" msgid="2448168080964209908">"रीसेट करें"</string>
@@ -1182,9 +1278,11 @@
     <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"USB संग्रहण का उपयोग वर्तमान में एक कंप्‍यूटर द्वारा किया जा रहा है."</string>
     <string name="media_shared" product="default" msgid="5706130568133540435">"SD कार्ड का उपयोग वर्तमान में एक कंप्‍यूटर द्वारा किया जा रहा है."</string>
     <string name="media_unknown_state" msgid="729192782197290385">"बाह्य मीडिया अज्ञात स्‍थिति में है."</string>
-    <string name="share" msgid="1778686618230011964">"शेयर करें"</string>
+    <string name="share" msgid="1778686618230011964">"साझा करें"</string>
     <string name="find" msgid="4808270900322985960">"ढूंढें"</string>
     <string name="websearch" msgid="4337157977400211589">"वेब खोज"</string>
+    <string name="find_next" msgid="5742124618942193978">"अगला ढूंढें"</string>
+    <string name="find_previous" msgid="2196723669388360506">"पिछला ढूंढें"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g> की ओर से स्‍थान अनुरोध"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"स्‍थान अनुरोध"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>) द्वारा अनुरोधित"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"फ़ोन"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"हेडफ़ोन"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"डॉक स्‍पीकर"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI ऑडियो"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"सिस्‍टम"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth ऑडियो"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"पूर्ण"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"मीडिया आउटपुट"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"स्‍कैन कर रहा है..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"कनेक्ट हो रहा है..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"उपलब्ध"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"उपलब्‍ध नहीं"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"अंतर्निहित स्क्रीन"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI स्क्रीन"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"ओवरले #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"वायरलेस डिस्प्ले कनेक्ट है"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"यह स्क्रीन अन्य उपकरण पर दिखाई दे रही है"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"डिस्कनेक्ट करें"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"आपातकालीन कॉल"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"प्रतिमान भूल गए"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"गलत प्रतिमान"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"गलत पासवर्ड"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"गलत PIN"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"अपना प्रतिमान आरेखित करें"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"सिम PIN डालें"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"PIN डालें"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"पासवर्ड डालें"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"सिम अब अक्षम हो गई है. जारी रखने के लिए PUK कोड डालें. विवरण के लिए वाहक से संपर्क करें."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"इच्छित पिन कोड डालें"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"इच्छित पिन कोड की पुष्टि करें"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM कार्ड अनलॉक कर रहा है…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"गलत PIN कोड."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"ऐसा PIN लिखें, जो 4 से 8 अंकों का हो."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK कोड 8 या अधिक संख्या वाला होना चाहिए."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"सही PUK कोड पुन: डालें. बार-बार प्रयास करने से सिम स्थायी रूप से अक्षम हो जाएगी."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"पिन कोड का मिलान नहीं होता"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"बहुत अधिक प्रतिमान प्रयास"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"अनलॉक करने के लिए, अपने Google खाते से साइन इन करें."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"उपयोगकर्ता नाम (ईमेल)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"पासवर्ड"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"साइन इन करें"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"अमान्य उपयोगकर्ता नाम या पासवर्ड."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"अपना उपयोगकर्ता नाम या पासवर्ड भूल गए?"\n" "<b>"google.com/accounts/recovery"</b>" पर जाएं."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"खाते की जांच की जा रही है…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"आप अपना PIN <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से लिख चुके हैं. "\n\n" <xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"आप अपना पासवर्ड <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से लिख चुके हैं. "\n\n" <xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"आपने अपना अनलॉक प्रतिमान <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से आरेखित किया है. "\n\n" <xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"आप टेबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से प्रयास कर चुके हैं. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, टेबलेट फ़ैक्टरी डिफ़ॉल्ट पर रीसेट हो जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"आप फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से प्रयास कर चुके हैं. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, फ़ोन फ़ैक्टरी डिफ़ॉल्ट पर रीसेट हो जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"आप टेबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से प्रयास कर चुके हैं. टेबलेट अब फ़ैक्‍टरी डिफ़ॉल्‍ट पर रीसेट हो जाएगा."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"आप फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से प्रयास कर चुके हैं. फ़ोन अब फ़ैक्टरी डिफ़ॉल्ट पर रीसेट हो जाएगा."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"आपने अपने अनलॉक प्रतिमान को <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से आरेखित किया है. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने टेबलेट को किसी ईमेल खाते के उपयोग से अनलॉक करने के लिए कहा जाएगा."\n\n" <xliff:g id="NUMBER_2">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"आपने अपने अनलॉक प्रतिमान को <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से आरेखित किया है. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने फ़ोन को किसी ईमेल खाते का उपयोग करके अनलॉक करने के लिए कहा जाएगा."\n\n" <xliff:g id="NUMBER_2">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"निकालें"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"वॉल्यूम को सुरक्षित स्तर से अधिक करें?"\n"अधिक देर तक उच्च वॉल्यूम पर सुनने से आपकी सुनने की क्षमता को नुकसान हो सकता है."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"पहुंच-योग्यता को सक्षम करने के लिए दो अंगुलियों से नीचे दबाए रखें."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"पहुंच-योग्यता सक्षम कर दी है."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"पहुंच-योग्यता रद्द की गई."</string>
+    <string name="user_switched" msgid="3768006783166984410">"वर्तमान उपयोगकर्ता <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"स्वामी"</string>
 </resources>
diff --git a/core/res/res/values-hr-rHR/donottranslate-cldr.xml b/core/res/res/values-hr-rHR/donottranslate-cldr.xml
index a601d93..57e0572 100644
--- a/core/res/res/values-hr-rHR/donottranslate-cldr.xml
+++ b/core/res/res/values-hr-rHR/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">siječanj</string>
-    <string name="month_long_standalone_february">veljača</string>
-    <string name="month_long_standalone_march">ožujak</string>
-    <string name="month_long_standalone_april">travanj</string>
-    <string name="month_long_standalone_may">svibanj</string>
-    <string name="month_long_standalone_june">lipanj</string>
-    <string name="month_long_standalone_july">srpanj</string>
-    <string name="month_long_standalone_august">kolovoz</string>
-    <string name="month_long_standalone_september">rujan</string>
-    <string name="month_long_standalone_october">listopad</string>
-    <string name="month_long_standalone_november">studeni</string>
-    <string name="month_long_standalone_december">prosinac</string>
-
-    <string name="month_long_january">siječnja</string>
-    <string name="month_long_february">veljače</string>
-    <string name="month_long_march">ožujka</string>
-    <string name="month_long_april">travnja</string>
-    <string name="month_long_may">svibnja</string>
-    <string name="month_long_june">lipnja</string>
-    <string name="month_long_july">srpnja</string>
-    <string name="month_long_august">kolovoza</string>
-    <string name="month_long_september">rujna</string>
-    <string name="month_long_october">listopada</string>
-    <string name="month_long_november">studenoga</string>
-    <string name="month_long_december">prosinca</string>
-
-    <string name="month_medium_january">01.</string>
-    <string name="month_medium_february">02.</string>
-    <string name="month_medium_march">03.</string>
-    <string name="month_medium_april">04.</string>
-    <string name="month_medium_may">05.</string>
-    <string name="month_medium_june">06.</string>
-    <string name="month_medium_july">07.</string>
-    <string name="month_medium_august">08.</string>
-    <string name="month_medium_september">09.</string>
-    <string name="month_medium_october">10.</string>
-    <string name="month_medium_november">11.</string>
-    <string name="month_medium_december">12.</string>
-
-    <string name="month_shortest_january">1.</string>
-    <string name="month_shortest_february">2.</string>
-    <string name="month_shortest_march">3.</string>
-    <string name="month_shortest_april">4.</string>
-    <string name="month_shortest_may">5.</string>
-    <string name="month_shortest_june">6.</string>
-    <string name="month_shortest_july">7.</string>
-    <string name="month_shortest_august">8.</string>
-    <string name="month_shortest_september">9.</string>
-    <string name="month_shortest_october">10.</string>
-    <string name="month_shortest_november">11.</string>
-    <string name="month_shortest_december">12.</string>
-
-    <string name="day_of_week_long_sunday">nedjelja</string>
-    <string name="day_of_week_long_monday">ponedjeljak</string>
-    <string name="day_of_week_long_tuesday">utorak</string>
-    <string name="day_of_week_long_wednesday">srijeda</string>
-    <string name="day_of_week_long_thursday">četvrtak</string>
-    <string name="day_of_week_long_friday">petak</string>
-    <string name="day_of_week_long_saturday">subota</string>
-
-    <string name="day_of_week_medium_sunday">ned</string>
-    <string name="day_of_week_medium_monday">pon</string>
-    <string name="day_of_week_medium_tuesday">uto</string>
-    <string name="day_of_week_medium_wednesday">sri</string>
-    <string name="day_of_week_medium_thursday">čet</string>
-    <string name="day_of_week_medium_friday">pet</string>
-    <string name="day_of_week_medium_saturday">sub</string>
-
-    <string name="day_of_week_short_sunday">ned</string>
-    <string name="day_of_week_short_monday">pon</string>
-    <string name="day_of_week_short_tuesday">uto</string>
-    <string name="day_of_week_short_wednesday">sri</string>
-    <string name="day_of_week_short_thursday">čet</string>
-    <string name="day_of_week_short_friday">pet</string>
-    <string name="day_of_week_short_saturday">sub</string>
-
-    <string name="day_of_week_shortest_sunday">n</string>
-    <string name="day_of_week_shortest_monday">p</string>
-    <string name="day_of_week_shortest_tuesday">u</string>
-    <string name="day_of_week_shortest_wednesday">s</string>
-    <string name="day_of_week_shortest_thursday">č</string>
-    <string name="day_of_week_shortest_friday">p</string>
-    <string name="day_of_week_shortest_saturday">s</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">jučer</string>
-    <string name="today">danas</string>
-    <string name="tomorrow">sutra</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-hr/donottranslate-cldr.xml b/core/res/res/values-hr/donottranslate-cldr.xml
index 9b51862..9e4b225 100644
--- a/core/res/res/values-hr/donottranslate-cldr.xml
+++ b/core/res/res/values-hr/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">siječanj</string>
-    <string name="month_long_standalone_february">veljača</string>
-    <string name="month_long_standalone_march">ožujak</string>
-    <string name="month_long_standalone_april">travanj</string>
-    <string name="month_long_standalone_may">svibanj</string>
-    <string name="month_long_standalone_june">lipanj</string>
-    <string name="month_long_standalone_july">srpanj</string>
-    <string name="month_long_standalone_august">kolovoz</string>
-    <string name="month_long_standalone_september">rujan</string>
-    <string name="month_long_standalone_october">listopad</string>
-    <string name="month_long_standalone_november">studeni</string>
-    <string name="month_long_standalone_december">prosinac</string>
-
-    <string name="month_long_january">siječnja</string>
-    <string name="month_long_february">veljače</string>
-    <string name="month_long_march">ožujka</string>
-    <string name="month_long_april">travnja</string>
-    <string name="month_long_may">svibnja</string>
-    <string name="month_long_june">lipnja</string>
-    <string name="month_long_july">srpnja</string>
-    <string name="month_long_august">kolovoza</string>
-    <string name="month_long_september">rujna</string>
-    <string name="month_long_october">listopada</string>
-    <string name="month_long_november">studenoga</string>
-    <string name="month_long_december">prosinca</string>
-
-    <string name="month_medium_january">01.</string>
-    <string name="month_medium_february">02.</string>
-    <string name="month_medium_march">03.</string>
-    <string name="month_medium_april">04.</string>
-    <string name="month_medium_may">05.</string>
-    <string name="month_medium_june">06.</string>
-    <string name="month_medium_july">07.</string>
-    <string name="month_medium_august">08.</string>
-    <string name="month_medium_september">09.</string>
-    <string name="month_medium_october">10.</string>
-    <string name="month_medium_november">11.</string>
-    <string name="month_medium_december">12.</string>
-
-    <string name="month_shortest_january">1.</string>
-    <string name="month_shortest_february">2.</string>
-    <string name="month_shortest_march">3.</string>
-    <string name="month_shortest_april">4.</string>
-    <string name="month_shortest_may">5.</string>
-    <string name="month_shortest_june">6.</string>
-    <string name="month_shortest_july">7.</string>
-    <string name="month_shortest_august">8.</string>
-    <string name="month_shortest_september">9.</string>
-    <string name="month_shortest_october">10.</string>
-    <string name="month_shortest_november">11.</string>
-    <string name="month_shortest_december">12.</string>
-
-    <string name="day_of_week_long_sunday">nedjelja</string>
-    <string name="day_of_week_long_monday">ponedjeljak</string>
-    <string name="day_of_week_long_tuesday">utorak</string>
-    <string name="day_of_week_long_wednesday">srijeda</string>
-    <string name="day_of_week_long_thursday">četvrtak</string>
-    <string name="day_of_week_long_friday">petak</string>
-    <string name="day_of_week_long_saturday">subota</string>
-
-    <string name="day_of_week_medium_sunday">ned</string>
-    <string name="day_of_week_medium_monday">pon</string>
-    <string name="day_of_week_medium_tuesday">uto</string>
-    <string name="day_of_week_medium_wednesday">sri</string>
-    <string name="day_of_week_medium_thursday">čet</string>
-    <string name="day_of_week_medium_friday">pet</string>
-    <string name="day_of_week_medium_saturday">sub</string>
-
-    <string name="day_of_week_short_sunday">ned</string>
-    <string name="day_of_week_short_monday">pon</string>
-    <string name="day_of_week_short_tuesday">uto</string>
-    <string name="day_of_week_short_wednesday">sri</string>
-    <string name="day_of_week_short_thursday">čet</string>
-    <string name="day_of_week_short_friday">pet</string>
-    <string name="day_of_week_short_saturday">sub</string>
-
-    <string name="day_of_week_shortest_sunday">n</string>
-    <string name="day_of_week_shortest_monday">p</string>
-    <string name="day_of_week_shortest_tuesday">u</string>
-    <string name="day_of_week_shortest_wednesday">s</string>
-    <string name="day_of_week_shortest_thursday">č</string>
-    <string name="day_of_week_shortest_friday">p</string>
-    <string name="day_of_week_shortest_saturday">s</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">jučer</string>
-    <string name="today">danas</string>
-    <string name="tomorrow">sutra</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index a33e03e..e279216 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opcije telefona"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Zaključavanje zaslona"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Isključi"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Izvješće o bugovima"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Izradi izvješće o bugu"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Time će se prikupiti podaci o trenutačnom stanju vašeg uređaja koje ćete nam poslati u e-poruci. Za pripremu izvješća o bugu potrebno je nešto vremena pa vas molimo za strpljenje."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Bešumni način"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Zvuk je isključen"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Zvuk je uključen"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Vaše poruke"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Čitajte i pišite SMS-ove, poruke e-pošte i ostale poruke."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Vaši osobni podaci"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Izravan pristup kontaktima i kalendaru pohranjenima na tabletnom uređaju."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Izravan pristup kontaktima i kalendaru pohranjenom na telefonu."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Izravan pristup informacijama o vama koje su pohranjene na vašoj posjetnici."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Informacije o vašoj društvenoj aktivnosti"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Izravan pristup informacijama o kontaktima i društvenim vezama."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Vaša lokacija"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Pratite svoju fizičku lokaciju."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Mrežna komunikacija"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Pristupajte raznim značajkama mreže."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Pristupajte uređajima i mrežama putem Bluetootha."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Postavke zvuka"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Promjena postavki zvuka."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Utječe na bateriju"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Upotreba značajki koje brzo prazne bateriju."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalendar"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Izravan pristup kalendaru i događajima."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Čitaj korisnički rječnik"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Pročitajte riječi u korisničkom rječniku."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Piši u korisnički rječnik"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Dodavanje riječi u korisnički rječnik."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Oznake i povijest"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Izravan pristup oznakama i povijest preglednika."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarm"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Postavljanje alarma na budilici."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Govorna pošta"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Izravan pristup govornoj pošti."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Izravan pristup mikrofonu za snimanje zvuka."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Fotoaparat"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Izravan pristup fotoaparatu za slikanje ili snimanje videozapisa."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Informacije o vašoj aplikaciji"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Sposobnost da utječu na postupanje drugih aplikacija na vašem uređaju."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Pozadinska slika"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Promjena postavki pozadinske slike na uređaju."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Sat"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Promjena vremena ili vremenske zone uređaja."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Traka statusa"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Promijenite postavke statusne trake uređaja."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Postavke sinkronizacije"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Pristup postavkama sinkronizacije."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Vaši računi"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Pristup dostupnim računima."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Hardverske kontrole"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Niskorazinski pristup i nadzor nad sustavom."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Razvojni alati"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Značajke potrebne samo za razvojne programere aplikacija."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Korisničko sučelje druge aplikacije"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Utjecaj na korisničko sučelje drugih aplikacija."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Prostor za pohranu"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Pristupi memoriji USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Pristup SD kartici."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Aplikaciji omogućuje primanje i obradu WAP poruka. Ta dozvola uključuje mogućnost nadziranja ili brisanja vama poslanih poruka, a da vam ih ne prikaže."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"dohvaćanje pokrenutih aplikacija"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Aplikaciji omogućuje dohvaćanje informacija o trenutačnim i nedavnim tekućim zadacima. To aplikaciji može omogućiti otkrivanje informacija o tome koje se aplikacije upotrebljavaju na uređaju."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interakcija među korisnicima"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Omogućuje aplikaciji izvršavanje radnji među korisnicima na uređaju. Zlonamjerne aplikacije mogu to iskoristiti za narušavanje zaštite među korisnicima."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"dozvola za potpunu interakciju među korisnicima"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Omogućuje sve moguće interakcije među korisnicima."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"upravljanje korisnicima"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Omogućuje aplikacijama upravljanje korisnicima na uređaju, uključujući upit, izradu i brisanje."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"dohvaćanje pojedinosti o pokrenutim aplikacijama"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Aplikaciji omogućuje dohvaćanje detaljnih informacija o trenutačno i nedavno pokrenutim zadacima. Zlonamjerne aplikacije mogu otkriti privatne informacije o drugim aplikacijama."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"promjena redoslijeda pokrenutih aplikacija"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Omogućuje aplikaciji dohvaćanje unutarnjeg stanja sustava. Zlonamjerne aplikacije mogu dohvatiti razne privatne i sigurnosne podatke koje im inače nikada ne bi trebale biti potrebne."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"dohvaćanje sadržaja zaslona"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Omogućuje aplikaciji dohvaćanje sadržaja aktivnog prozora. Zlonamjerne aplikacije mogu dohvatiti sav sadržaj prozora i pregledati sav njegov tekst osim zaporki."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"privremeno omogući dostupnost"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Aplikacija može privremeno omogućiti dostupnost na uređaju. Zlonamjerne aplikacije mogu omogućiti dostupnost bez korisnikova odobrenja."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"dohvaćanje informacija o prozoru"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Aplikaciji omogućuje dohvaćanje informacija o prozorima iz upravitelja prozora. Zlonamjerne aplikacije mogu dohvaćati informacije koje su namijenjene za internu uporabu sustava."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtriranje događaja"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Aplikaciji omogućuje registraciju ulaznog filtra koji filtrira strujanje svih korisničkih događaja prije otpreme. Zlonamjerne aplikacije mogu kontrolirati korisničko sučelje sustava bez znanja korisnika."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"uvećaj prikaz"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Omogućuje aplikaciji uvećavanje sadržaja zaslona. Zlonamjerne aplikacije mogu izmijeniti sadržaj zaslona tako da uređaj postane neupotrebljiv."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"djelomično isključivanje"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Postavlja upravitelja za aktivnost u stanje mirovanja. Ne isključuje ga u potpunosti."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"sprečavanje promjene aplikacije"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Omogućuje aplikaciji upravljanje maksimalnim brojem postupaka koji će biti pokrenuti. Nikada nije potrebno za uobičajene aplikacije."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"prisilno zatvaranje pozadinskih aplikacija"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Omogućuje aplikaciji da upravlja time hoće li radnje uvijek prekinuti s radom čim odu u pozadinu. Nikada nije potrebno za normalne aplikacije."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"izmjena statistike o bateriji"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Omogućuje aplikaciji promjenu prikupljene statistike o potrošnji baterije. Nije namijenjena uobičajenim aplikacijama."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"očitavanje statistike o bateriji"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Aplikacija može očitavati podatke o trenutačnoj potrošnji baterije na niskoj razini. Tako može doznati detaljne informacije o aplikacijama koje upotrebljavate."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"izmjena statistike o bateriji"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Omogućuje aplikaciji promjenu prikupljene statistike o potrošnji baterije. Nije namijenjena uobičajenim aplikacijama."</string>
     <string name="permlab_backup" msgid="470013022865453920">"sigurnosna kopija i oporavak nadzornog sustava"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Omogućuje aplikaciji upravljanje mehanizmom stvaranja sigurnosnih kopija i obnove sustava. Nije namijenjena uobičajenim aplikacijama."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"potvrditi postupak izrade sigurnosne kopije ili obnove"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"prikaz neovlaštenih prozora"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Omogućuje aplikaciji stvaranje prozora koje bi trebalo upotrebljavati korisničko sučelje internog sustava. Nije namijenjeno uobičajenim aplikacijama."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"crtanje preko drugih aplikacija"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Aplikaciji omogućuje prikaz prozora upozorenja sustava. Neki prozori upozorenja mogu zauzeti cijeli zaslon."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Aplikacija može crtati preko drugih aplikacija ili dijelova korisničkog sučelja. Može ometati upotrebu sučelja na bilo kojoj aplikaciji ili promijeniti izgled drugih aplikacija."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"izmjena globalne brzine animacije"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"U bilo kojem trenutku aplikaciji omogućuje promjenu globalne brzine animacija (brža ili sporija animacija)."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"upravljanje oznakama aplikacije"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Omogućuje aplikaciji stvaranje vlastitih oznaka i upravljanje njima, zaobilazeći njihov uobičajeni Z-redoslijed. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"zamrzni ekran"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Omogućuje aplikaciji privremeno zamrzavanje zaslona za prijelaz na cijeli zaslon."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"pritisnite tipke i gumbe za nadzor"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Omogućuje aplikaciji slanje vlastitih ulaznih događaja (pritiskanje tipki itd.) drugim aplikacijama. Zlonamjerne aplikacije na taj način mogu preuzeti tabletno računalo."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Omogućuje aplikaciji slanje vlastitih ulaznih događaja (pritiskanje tipki itd.) drugim aplikacijama. Zlonamjerne aplikacije na taj način mogu preuzeti telefon."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"izravno instaliranje aplikacija"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Omogućuje aplikaciji instaliranje novih ili ažuriranih Androidovih paketa. Zlonamjerne aplikacije mogu na taj način dodati nove aplikacije s proizvoljno moćnim dozvolama."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"brisanje svih podataka predmemorije aplikacije"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Omogućuje aplikaciji oslobađanje prostora u pohrani tabletnog računala brisanjem datoteka u direktoriju predmemorije aplikacije. Pristup je vrlo ograničen, obično na procese sustava."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Omogućuje aplikaciji oslobađanje prostora u pohrani telefona brisanjem datoteka u direktoriju predmemorije aplikacije. Pristup je vrlo ograničen, obično na procese sustava."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Aplikacija može osloboditi prostor za pohranu na tabletnom računalu brisanjem datoteka u direktorijima predmemorije drugih aplikacija. Time može uzrokovati sporije pokretanje drugih aplikacija jer one moraju ponovo dohvaćati svoje podatke."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Aplikacija može osloboditi prostor za pohranu na telefonu brisanjem datoteka u direktorijima predmemorije drugih aplikacija. Time može uzrokovati sporije pokretanje drugih aplikacija jer one moraju ponovo dohvaćati svoje podatke."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"premještanje resursa aplikacije"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Omogućuje aplikaciji premještanje izvora aplikacije s unutarnjih na vanjske medije i obrnuto."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"čitaj osjetljive podatke dnevnika"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Aplikaciji omogućuje pristup dodatnim naredbama za pružatelja usluga lokacije. To aplikaciji može omogućiti ometanje rada GPS-a ili drugih izvora lokacije."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"dopuštenje za instaliranje davatelja usluge lociranja"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Stvaranje lažnih izvora lokacije radi testiranja ili za instaliranje novog pružatelja usluga lokacije. To aplikaciji omogućuje zaobilaženje lokacije i/ili statusa koji vraćaju drugi izvori lokacije, primjerice GPS ili pružatelji usluga lokacije."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"precizna lokacija (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Pristup preciznim izvorima lokacije, primjerice globalnom sustavu pozicioniranja na vašem tabletnom računalu. Kad su usluge lokacije dostupne i uključene, ta dozvola aplikaciji omogućuje utvrđivanje vaše precizne lokacije."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Pristup preciznim izvorima lokacije, primjerice globalnom sustavu pozicioniranja na vašem telefonu. Kad su usluge lokacije dostupne i uključene, ta dozvola aplikaciji omogućuje utvrđivanje vaše precizne lokacije."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"približna lokacija (mreža)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Pristup približnoj lokaciji od pružatelja usluge lokacije koji upotrebljavaju mrežne izvore, primjerice bazne stanice i Wi-Fi. Kad su te usluge lokacije dostupne i uključene, ta dozvola aplikaciji omogućuje utvrđivanje vaše približne lokacije."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"precizna lokacija (GPS i mreža)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Aplikacija može dobiti vašu preciznu lokaciju pomoću globalnog pozicijskog sustava (GPS-a) ili mrežnih izvora lokacije kao što su bazne stanice i Wi-Fi. Te lokacijske usluge moraju biti uključene i dostupne vašem uređaju da bi ih aplikacija mogla upotrebljavati. Aplikacije mogu upotrebljavati tu mogućnost kako bi utvrdile vašu lokaciju i mogu dodatno trošiti bateriju."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"približna lokacija (mreža)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Aplikacija može dobiti vašu približnu lokaciju. Tu lokaciju izvode lokacijske usluge pomoću mrežnih izvora lokacije kao što su bazne stanice i Wi-Fi. Te lokacijske usluge moraju biti uključene i dostupne vašem uređaju da bi ih aplikacija mogla upotrebljavati. Aplikacije mogu upotrebljavati tu mogućnost kako bi utvrdile vašu približnu lokaciju."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"pristup značajci SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Aplikaciji omogućuje upotrebu značajki niske razine SurfaceFlinger."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"čitanje međuspremnika okvira"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Aplikaciji omogućuje čitanje sadržaja međuspremnika okvira."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"konfiguriraj Wifi zaslone"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Omogućuje aplikaciji konfiguriranje i povezivanje s WiFi zaslonima."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"upravljaj Wifi zaslonima"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Omogućuje aplikaciji upravljanje značajkama WiFi zaslona niske razine."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"promjena postavki zvuka"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Aplikaciji omogućuje izmjenu globalnih postavki zvuka, primjerice glasnoće i zvučnika koji se upotrebljava za izlaz."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"snimanje zvuka"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"pristupanje postavkama Bluetootha"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Aplikaciji omogućuje konfiguraciju lokalnog tabletnog računala s Bluetoothom te otkrivanje i uparivanje s udaljenim  uređajima."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Aplikaciji omogućuje konfiguraciju lokalnog Bluetooth telefona i otkrivanje i uparivanje s udaljenim uređajima."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Prikaz WiMAX veza"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"uspostavljanje i prekidanje veze s WiMAX-om"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Aplikaciji omogućuje utvrđivanje omogućenosti WiMAX mreže te daje informaciju o tome je li spojena neka WiMAX mreža."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Promjena stanja WiMAX mreže"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Aplikaciji omogućuje povezivanje tabletnog računala s WiMAX mrežama i prekidanje veze tabletnog računala s njima."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Omogućuje aplikaciji promjenu vaših trenutačno sinkroniziranih feedova. Zlonamjerne aplikacije mogu promijeniti vaše sinkronizirane feedove."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"čitanje pojmova koje ste dodali u rječnik"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Aplikaciji omogućuje čitanje svih riječi, imena i fraza koje je korisnik pohranio u korisničkom rječniku."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"pisanje u korisnički definiran rječnik"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"dodavanje riječi u rječnik koji je izradio korisnik"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Aplikaciji omogućuje pisanje novih riječi u korisnički rječnik."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"testiranje pristupa zaštićenoj pohrani"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"testiranje pristupa zaštićenoj pohrani"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Aplikaciji omogućuje testiranje dozvole za USB pohranu koja će biti dostupna na budućim uređajima."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Aplikaciji omogućuje testiranje dozvole za USB pohranu koja će biti dostupna na budućim uređajima."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Aplikaciji omogućuje testiranje dozvole za SD karticu koja će biti dostupna na budućim uređajima."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"izmjena/brisanje sadrž. USB-a"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"izmjena ili brisanje sadržaja SD kartice"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Aplikaciji omogućuje pisanje na SD karticu."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"izmijeni/izbriši sadržaj pohranjen na internim medijima"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Aplikaciji omogućuje izmjenu sadržaja pohranjenog na internim medijima."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"pristup vanjskoj pohrani svima"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Omogućuje aplikaciji pristup vanjskoj pohrani za sve korisnike."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"pristup sustavu datoteka predmemorije"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Aplikaciji omogućuje čitanje i pisanje u datotečnom sustavu privremene memorije."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"zovi/primaj internetske pozive"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Zahtijevajte da pohranjeni podaci aplikacije budu šifrirani."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Onemogući fotoaparate"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Spriječite upotrebu svih kamera uređaja."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Onemogući zaštitu tipkovnice"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Sprječava se upotreba nekih značajki u zaštitnom zaključavanju tipkovnice."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Početna"</item>
     <item msgid="869923650527136615">"Mobilni"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Pokušajte ponovo"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Premašen je maksimalni broj Otključavanja licem"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Punjenje, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Napunjeno."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Napunjeno"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Priključite punjač."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nema SIM kartice."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Nema SIM kartice"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"U tabletnom uređaju nema SIM kartice."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"U telefonu nema SIM kartice."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Umetnite SIM karticu."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Uzorak je obrisan"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Dodan je mobitel"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Uzorak je dovršen"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Dodavanje widgeta."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Prazno"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Područje za otključavanje prošireno je."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Područje za otključavanje sažeto je."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> widget."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Birač korisnika"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Status"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Fotoaparat"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Nadzor medija"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Pokrenuta je promjena redoslijeda widgeta."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Završena je promjena redoslijeda widgeta."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> izbrisan je."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Proširivanje područja za otključavanje."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Otključavanje klizanjem."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Uzorak za otključavanje."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Otključavanje licem."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Otključavanje PIN-om."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Otključavanje zaporkom."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Područje uzorka."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Područje klizanja."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopiraj URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Odabir teksta"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Odabir teksta"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"dodaj u rječnik"</string>
-    <string name="deleteText" msgid="7070985395199629156">"izbriši"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Dodaj u rječnik"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Izbriši"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Način unosa"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Radnje s tekstom"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Ponestaje prostora za pohranu"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Omogućavanje otvaranja Wi-Fi mreža"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Prijavite se na Wi-Fi mrežu"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Prijavite se na mrežu"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ne može se spojiti na Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ima lošu internetsku vezu."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Prima:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Upišite potreban PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefon će se privremeno isključiti s Wi-Fija dok je povezan s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Umetni znak"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Slanje SMS poruka"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"Aplikacija &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; šalje veliki broj SMS poruka. Želite li dopustiti ovoj aplikaciji da nastavi slati poruke?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Dopusti"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Odbij"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; želi poslati poruku na &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Ovo "<font fgcolor="#ffffb060">"će se možda naplaćivati"</font>" putem vašeg mobilnog računa."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Ovo se naplaćuje putem vašeg mobilnog računa."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Pošalji"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Odustani"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Zapamti odabir"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Kasnije to možete promijeniti u odjeljku Postavke &gt; Aplikacije"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Dopusti uvijek"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Ne dopuštaj nikada"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM kartica uklonjena"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilna mreža bit će nedostupna do ponovnog pokretanja s umetnutom važećom SIM karticom."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Gotovo"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Postavi datum"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Postavi"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Gotovo"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Zadano"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Nije potrebno dopuštenje"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Sakrij"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Pokaži sve"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NOVO: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NOVO: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Omogućuje aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Nije potrebno dopuštenje"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"možda ćete morati platiti"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB masovna pohrana"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB povezan"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Povezali ste se s računalom putem USB-a. Dodirnite gumb u nastavku ako želite kopirati datoteke između računala i USB pohrane uređaja Android."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikacija <xliff:g id="APP">%s</xliff:g> aktivirala je VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dodirnite za upravljanje mrežom."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Povezan sa sesijom <xliff:g id="SESSION">%s</xliff:g>. Dodirnite za upravljanje mrežom."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Povezivanje s uvijek uključenom VPN mrežom…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Povezan s uvijek uključenom VPN mrežom"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Pogreška uvijek uključene VPN mreže"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Dodirnite za poništavanje veze"</string>
     <string name="upload_file" msgid="2897957172366730416">"Odaberite datoteku"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nema odabranih datoteka"</string>
     <string name="reset" msgid="2448168080964209908">"Ponovo postavi"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Dijeli"</string>
     <string name="find" msgid="4808270900322985960">"Pronađi"</string>
     <string name="websearch" msgid="4337157977400211589">"Pretraž. weba"</string>
+    <string name="find_next" msgid="5742124618942193978">"Nađi sljedeće"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Nađi prethodno"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Zahtjev za lokaciju koji upućuje <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Zahtjev za lokaciju"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Zatražio <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Slušalice"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Zvučnici postolja"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI audio"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sustav"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth zvuk"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Gotovo"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Medijski izlaz"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Skeniranje..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Povezivanje..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Dostupno"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Nije dostupno"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Ugrađeni zaslon"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI zaslon"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Preklapanje br. <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Bežični je prikaz povezan"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Ovaj se zaslon prikazuje na nekom drugom uređaju"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Isključi"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Hitan poziv"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Zaboravili ste obrazac"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Pogrešan obrazac"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Pogrešna zaporka"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Pogrešan PIN"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Pokušajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> s."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Iscrtajte svoj obrazac"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Unesite PIN za SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Unesite PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Unesite zaporku"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM je sad onemogućen. Unesite PUK kôd da biste nastavili. Kontaktirajte operatera za pojedinosti."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Upišite željeni PIN kôd"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Potvrdite željeni PIN kôd"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Otključavanje SIM kartice…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Netočan PIN kôd."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Unesite PIN koji ima od 4 do 8 brojeva."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK kôd treba imati 8 brojeva ili više."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Ponovo unesite ispravan PUK kôd. Ponovljeni pokušaji trajno će onemogućiti SIM."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN kodovi nisu jednaki"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Previše pokušaja iscrtavanja obrasca"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Za otključavanje prijavite se Google računom."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Korisničko ime (e-pošta)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Zaporka"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Prijava"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Nevažeće korisničko ime ili zaporka."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Zaboravili ste korisničko ime ili zaporku?"\n"Posjetite "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Provjera računa..."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Netočno ste napisali PIN <xliff:g id="NUMBER_0">%d</xliff:g> puta. "\n\n"Pokušajte ponovo za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Netočno ste napisali zaporku <xliff:g id="NUMBER_0">%d</xliff:g> puta. "\n\n"Pokušajte ponovo za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Netočno ste iscrtali obrazac za otključavanje <xliff:g id="NUMBER_0">%d</xliff:g> puta. "\n\n"Pokušajte ponovo za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Netočno ste pokušali otključati tabletno računalo <xliff:g id="NUMBER_0">%d</xliff:g> puta. Ono će se vratiti na tvorničke postavke i svi korisnički podaci bit će izgubljeni nakon još ovoliko neuspjelih pokušaja: <xliff:g id="NUMBER_1">%d</xliff:g>."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Netočno ste pokušali otključati telefon <xliff:g id="NUMBER_0">%d</xliff:g> puta. On će se vratiti na tvorničke postavke i svi korisnički podaci bit će izgubljeni nakon još ovoliko neuspjelih pokušaja: <xliff:g id="NUMBER_1">%d</xliff:g>."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Netočno ste pokušali otključati tabletno računalo <xliff:g id="NUMBER">%d</xliff:g> puta. Sada će se vratiti na tvorničke postavke."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Netočno ste pokušali otključati telefon <xliff:g id="NUMBER">%d</xliff:g> puta. Sada će se vratiti na tvorničke postavke."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Netočno ste iscrtali obrazac za otključavanje <xliff:g id="NUMBER_0">%d</xliff:g> puta. Nakon još ovoliko neuspješnih pokušaja: <xliff:g id="NUMBER_1">%d</xliff:g> morat ćete otključati tabletno računalo pomoću računa e-pošte."\n\n" Pokušajte ponovo za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Netočno ste iscrtali obrazac za otključavanje <xliff:g id="NUMBER_0">%d</xliff:g> puta. Nakon još ovoliko neuspješnih pokušaja: <xliff:g id="NUMBER_1">%d</xliff:g> morat ćete otključati telefon pomoću računa e-pošte."\n\n" Pokušajte ponovo za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Ukloni"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Pojačati iznad sigurne razine?"\n"Dulje slušanje preglasne glazbe može vam oštetiti sluh."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Nastavite držati s dva prsta kako biste omogućili pristupačnost."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Dostupnost je omogućena."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Pristupačnost otkazana."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Trenutačni korisnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Vlasnik"</string>
 </resources>
diff --git a/core/res/res/values-hu-rHU/donottranslate-cldr.xml b/core/res/res/values-hu-rHU/donottranslate-cldr.xml
index afb7676..5f4b8aa 100644
--- a/core/res/res/values-hu-rHU/donottranslate-cldr.xml
+++ b/core/res/res/values-hu-rHU/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">január</string>
-    <string name="month_long_standalone_february">február</string>
-    <string name="month_long_standalone_march">március</string>
-    <string name="month_long_standalone_april">április</string>
-    <string name="month_long_standalone_may">május</string>
-    <string name="month_long_standalone_june">június</string>
-    <string name="month_long_standalone_july">július</string>
-    <string name="month_long_standalone_august">augusztus</string>
-    <string name="month_long_standalone_september">szeptember</string>
-    <string name="month_long_standalone_october">október</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">december</string>
-
-    <string name="month_long_january">január</string>
-    <string name="month_long_february">február</string>
-    <string name="month_long_march">március</string>
-    <string name="month_long_april">április</string>
-    <string name="month_long_may">május</string>
-    <string name="month_long_june">június</string>
-    <string name="month_long_july">július</string>
-    <string name="month_long_august">augusztus</string>
-    <string name="month_long_september">szeptember</string>
-    <string name="month_long_october">október</string>
-    <string name="month_long_november">november</string>
-    <string name="month_long_december">december</string>
-
-    <string name="month_medium_january">jan.</string>
-    <string name="month_medium_february">febr.</string>
-    <string name="month_medium_march">márc.</string>
-    <string name="month_medium_april">ápr.</string>
-    <string name="month_medium_may">máj.</string>
-    <string name="month_medium_june">jún.</string>
-    <string name="month_medium_july">júl.</string>
-    <string name="month_medium_august">aug.</string>
-    <string name="month_medium_september">szept.</string>
-    <string name="month_medium_october">okt.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">dec.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">Á</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">vasárnap</string>
-    <string name="day_of_week_long_monday">hétfő</string>
-    <string name="day_of_week_long_tuesday">kedd</string>
-    <string name="day_of_week_long_wednesday">szerda</string>
-    <string name="day_of_week_long_thursday">csütörtök</string>
-    <string name="day_of_week_long_friday">péntek</string>
-    <string name="day_of_week_long_saturday">szombat</string>
-
-    <string name="day_of_week_medium_sunday">V</string>
-    <string name="day_of_week_medium_monday">H</string>
-    <string name="day_of_week_medium_tuesday">K</string>
-    <string name="day_of_week_medium_wednesday">Sze</string>
-    <string name="day_of_week_medium_thursday">Cs</string>
-    <string name="day_of_week_medium_friday">P</string>
-    <string name="day_of_week_medium_saturday">Szo</string>
-
-    <string name="day_of_week_short_sunday">V</string>
-    <string name="day_of_week_short_monday">H</string>
-    <string name="day_of_week_short_tuesday">K</string>
-    <string name="day_of_week_short_wednesday">Sze</string>
-    <string name="day_of_week_short_thursday">Cs</string>
-    <string name="day_of_week_short_friday">P</string>
-    <string name="day_of_week_short_saturday">Szo</string>
-
-    <string name="day_of_week_shortest_sunday">V</string>
-    <string name="day_of_week_shortest_monday">H</string>
-    <string name="day_of_week_shortest_tuesday">K</string>
-    <string name="day_of_week_shortest_wednesday">S</string>
-    <string name="day_of_week_shortest_thursday">C</string>
-    <string name="day_of_week_shortest_friday">P</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">de.</string>
-    <string name="pm">du.</string>
-    <string name="yesterday">tegnap</string>
-    <string name="today">ma</string>
-    <string name="tomorrow">holnap</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%p %-l:%M</string>
     <string name="hour_minute_cap_ampm">%^p %-l:%M</string>
diff --git a/core/res/res/values-hu/donottranslate-cldr.xml b/core/res/res/values-hu/donottranslate-cldr.xml
index 28b65bc..c925b82 100644
--- a/core/res/res/values-hu/donottranslate-cldr.xml
+++ b/core/res/res/values-hu/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">január</string>
-    <string name="month_long_standalone_february">február</string>
-    <string name="month_long_standalone_march">március</string>
-    <string name="month_long_standalone_april">április</string>
-    <string name="month_long_standalone_may">május</string>
-    <string name="month_long_standalone_june">június</string>
-    <string name="month_long_standalone_july">július</string>
-    <string name="month_long_standalone_august">augusztus</string>
-    <string name="month_long_standalone_september">szeptember</string>
-    <string name="month_long_standalone_october">október</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">december</string>
-
-    <string name="month_long_january">január</string>
-    <string name="month_long_february">február</string>
-    <string name="month_long_march">március</string>
-    <string name="month_long_april">április</string>
-    <string name="month_long_may">május</string>
-    <string name="month_long_june">június</string>
-    <string name="month_long_july">július</string>
-    <string name="month_long_august">augusztus</string>
-    <string name="month_long_september">szeptember</string>
-    <string name="month_long_october">október</string>
-    <string name="month_long_november">november</string>
-    <string name="month_long_december">december</string>
-
-    <string name="month_medium_january">jan.</string>
-    <string name="month_medium_february">febr.</string>
-    <string name="month_medium_march">márc.</string>
-    <string name="month_medium_april">ápr.</string>
-    <string name="month_medium_may">máj.</string>
-    <string name="month_medium_june">jún.</string>
-    <string name="month_medium_july">júl.</string>
-    <string name="month_medium_august">aug.</string>
-    <string name="month_medium_september">szept.</string>
-    <string name="month_medium_october">okt.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">dec.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">Á</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">vasárnap</string>
-    <string name="day_of_week_long_monday">hétfő</string>
-    <string name="day_of_week_long_tuesday">kedd</string>
-    <string name="day_of_week_long_wednesday">szerda</string>
-    <string name="day_of_week_long_thursday">csütörtök</string>
-    <string name="day_of_week_long_friday">péntek</string>
-    <string name="day_of_week_long_saturday">szombat</string>
-
-    <string name="day_of_week_medium_sunday">V</string>
-    <string name="day_of_week_medium_monday">H</string>
-    <string name="day_of_week_medium_tuesday">K</string>
-    <string name="day_of_week_medium_wednesday">Sze</string>
-    <string name="day_of_week_medium_thursday">Cs</string>
-    <string name="day_of_week_medium_friday">P</string>
-    <string name="day_of_week_medium_saturday">Szo</string>
-
-    <string name="day_of_week_short_sunday">V</string>
-    <string name="day_of_week_short_monday">H</string>
-    <string name="day_of_week_short_tuesday">K</string>
-    <string name="day_of_week_short_wednesday">Sze</string>
-    <string name="day_of_week_short_thursday">Cs</string>
-    <string name="day_of_week_short_friday">P</string>
-    <string name="day_of_week_short_saturday">Szo</string>
-
-    <string name="day_of_week_shortest_sunday">V</string>
-    <string name="day_of_week_shortest_monday">H</string>
-    <string name="day_of_week_shortest_tuesday">K</string>
-    <string name="day_of_week_shortest_wednesday">S</string>
-    <string name="day_of_week_shortest_thursday">C</string>
-    <string name="day_of_week_shortest_friday">P</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">de.</string>
-    <string name="pm">du.</string>
-    <string name="yesterday">tegnap</string>
-    <string name="today">ma</string>
-    <string name="tomorrow">holnap</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 9b878c2..88f4046 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefonbeállítások"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Képernyő lezárása"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Kikapcsolás"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Programhiba bejelentése"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Hibajelentés készítése"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Ezzel információt fog gyűjteni az eszköz jelenlegi állapotáról, amelyet a rendszer e-mailben fog elküldeni. Kérjük, legyen türelemmel, amíg a hibajelentés elkészül, és küldhető állapotba kerül."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Néma üzemmód"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Hang kikapcsolva"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Hang bekapcsolva"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Saját üzenetek"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"SMS-ek, e-mailek és egyéb üzenetek olvasása és írása."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Az Ön személyes adatai"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Közvetlen hozzáférés a táblagépen tárolt névjegyekhez és naptárhoz."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Közvetlen hozzáférés a telefonon tárolt névjegyekhez és naptárhoz."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Közvetlen hozzáférés a névjegykártyán tárolt információkhoz"</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Az Ön közösségi adatai"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Közvetlen hozzáférés a névjegyekre és közösségi kapcsolatokra vonatkozó információkhoz"</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Tartózkodási hely"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Tartózkodási hely figyelése."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Hálózati kommunikáció"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Hozzáférés különböző hálózati funkciókhoz."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Eszközök és hálózatok elérése Bluetoothon keresztül."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Hangbeállítások"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Hangbeállítások módosítása"</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Hozzáférés az akkumulátor teljesítményéhez"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Olyan funkciók használata, amelyek gyorsan lemerítik az akkumulátort."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Naptár"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Közvetlen hozzáférés a naptárhoz és az eseményekhez"</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Felhasználói szótár olvasása"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Szavak olvasása a felhasználói szótárban."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Írás a felhasználói szótárba"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Szavak hozzáadása a felhasználói szótárhoz."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Könyvjelzők és előzmények"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Közvetlen hozzáférés a könyvjelzőkhöz és a böngészési előzményekhez"</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Ébresztő"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Ébresztőóra beállítása"</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Hangposta"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Közvetlen hozzáférés a hangpostához"</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Közvetlen hozzáférés a mikrofonhoz hangrögzítés céljából"</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Fényképezőgép"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Közvetlen hozzáférés a fényképezőgéphez kép vagy videó rögzítése céljából"</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Az Ön alkalmazásainak információi"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Képes az eszközön a többi alkalmazás viselkedését befolyásolni."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Háttérkép"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Az eszköz háttérkép-beállításainak módosítása"</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Óra"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Az eszközön jelzett idő vagy időzóna módosítása"</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Állapotsor"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Az eszköz állapotsor-beállításainak módosítása"</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Szinkronizálási beállítások"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Hozzáférés a szinkronizálási beállításokhoz"</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Az Ön fiókjai"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Hozzáférés az elérhető fiókokhoz."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Hardver vezérlése"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Alacsony szintű hozzáférés és a rendszer vezérlése."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Fejlesztői eszközök"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Csak az alkalmazásfejlesztők számára fontos funkciók."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Egyéb alkalmazások kezelőfelülete"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Hozzáférés más alkalmazások kezelőfelületéhez"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Tárhely"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Az USB-tár elérése."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Az SD-kártya elérése."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Lehetővé teszi az alkalmazás számára, hogy WAP-üzeneteket fogadjon és dolgozzon fel. Ez azt is jelenti, hogy az alkalmazás megfigyelheti vagy törölheti a beérkező üzeneteket anélkül, hogy Ön látná azokat."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"futó alkalmazások lekérése"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Lehetővé teszi az alkalmazás számára a jelenleg futó és nemrég befejezett feladatokkal kapcsolatos információk lekérését. Ezáltal az alkalmazás engedélyt kap az eszközön használt alkalmazásokkal kapcsolatos információk felderítésére."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"felhasználók közötti interakció"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Lehetővé teszi az alkalmazás számára, hogy több felhasználó között végezzen különféle műveleteket az eszközön. A rosszindulatú alkalmazások arra használhatják ezt, hogy megsértsék a felhasználók biztonságát."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"teljes licenc a felhasználók közötti interakcióhoz"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Lehetővé teszi az összes lehetséges interakciót a felhasználók között."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"Felhasználók kezelése"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Lehetővé teszi az alkalmazások számára a készüléken beállított felhasználók kezelését, beleértve a lekérdezéseket, a létrehozásokat és törléseket."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"futó alkalmazások részleteinek lekérése"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Lehetővé teszi az alkalmazás számára a jelenleg és a nemrég futó feladatok részletes adatainak lekérését. A rosszindulatú alkalmazások más alkalmazásokkal kapcsolatos privát adatokhoz férhetnek hozzá."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"futó alkalmazások átrendezése"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Lehetővé teszi az alkalmazás számára, hogy lekérje a rendszer belső állapotát. A rosszindulatú programok lekérhetnek számos olyan privát és biztonságos adatot, amelyekre normál esetben soha nincs szükségük."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"a képernyő tartalmának lekérése"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Lehetővé teszi az alkalmazás számára az aktív ablak tartalmának letöltését. A rosszindulatú alkalmazások letölthetik az ablak teljes tartalmát, és a jelszavak kivételével az összes szöveget megvizsgálhatják."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Ideiglenes hozzáférés engedélyezése"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Engedélyezi egy alkalmazás számára, hogy ideiglenesen hozzáférést biztosítson az eszközhöz. A kártékony alkalmazások a felhasználó beleegyezése nélkül engedélyezhetik a hozzáférést."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"ablakkal kapcsolatos információk lekérése"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Lehetővé teszi, hogy az alkalmazás információkat kérjen le az ablakkezelőben lévő ablakokkal kapcsolatban. A rosszindulatú alkalmazások belső rendszerhasználathoz szükséges információkat kérhetnek le."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"események szűrése"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Lehetővé teszi az alkalmazás számára, hogy egy bemeneti szűrőt használjon, amely megszűri a falon megjelenő felhasználói eseményeket, még mielőtt megjelennének. A rosszindulatú alkalmazások felhasználói beavatkozás nélkül irányíthatják a rendszer kezelőfelületét."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"kijelző nagyítása"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Lehetővé teszi egy alkalmazás számára, hogy kinagyítsa a kijelzőn megjelenő tartalmat. Előfordulhat, hogy a rosszindulatú alkalmazások úgy alakítják át a kijelző tartalmát, hogy használhatatlanná válik az eszköz."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"részleges rendszerleállítás"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Leállítás állapotba helyezi a tevékenységkezelőt. Nem hajtja végre a teljes leállítást."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"alkalmazásváltás megakadályozása"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Lehetővé teszi az alkalmazás számára a futtatható folyamatok maximális számának vezérlését. Soha nem lehet rá szüksége a normál alkalmazásoknak."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"háttéralkalmazások leállításának kényszerítése"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Lehetővé teszi az alkalmazás számára annak vezérlését, hogy a tevékenységek mindig befejeződjenek-e, amint a háttérbe kerülnek. A normál alkalmazások soha nem használják ezt."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"akkumulátorstatisztikák módosítása"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Lehetővé teszi az alkalmazás számára az összegyűjtött akkumulátorhasználati statisztikák módosítását. Normál alkalmazások nem használhatják."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"akkumulátorstatisztikák beolvasása"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Lehetővé teszi egy alkalmazás számára, hogy leolvassa az aktuális alacsony szintű akkumulátorhasználatra vonatkozó adatokat. Ezáltal az alkalmazás részletes adatokhoz jut az Ön által használt alkalmazásokról."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"akkumulátorstatisztikák módosítása"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Lehetővé teszi az alkalmazás számára az összegyűjtött akkumulátorhasználati statisztikák módosítását. Normál alkalmazások nem használhatják."</string>
     <string name="permlab_backup" msgid="470013022865453920">"rendszer biztonsági mentésének és helyreállításának vezérlése"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Lehetővé teszi az alkalmazás számára a rendszer biztonsági mentési és visszaállítási mechanizmusának vezérlését. Normál alkalmazások nem használhatják."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"teljes biztonsági mentés vagy helyreállítási művelet megerősítése"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"azonosítatlan ablakok megjelenítése"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Lehetővé teszi az alkalmazás számára olyan ablakok létrehozását, amelyek a belső rendszer felhasználói felületét kívánják használni. Normál alkalmazások nem használhatják."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"ráhúzás más alkalmazásokra"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Lehetővé teszi az alkalmazás számára a rendszerriasztás-ablakok megjelenítését. Egyes ablakok elfoglalhatják a teljes képernyőt is."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Lehetővé teszi az alkalmazás számára, hogy felhasználjon más alkalmazásokat, vagy igénybe vegye a felhasználói felület egyéb részeit. Befolyásolhatja a felület használatát mindegyik alkalmazásnál, és módosíthatja az Ön által látott elemeket a többi alkalmazásban."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"animáció általános sebességének módosítása"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Lehetővé teszi az alkalmazás számára, hogy bármikor globálisan módosítsa az animációk sebességét (gyorsabb vagy lassabb animációk)."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"alkalmazástokenek kezelése"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Lehetővé teszi az alkalmazás számára saját tokenek létrehozását és kezelését, kihagyva a szokásos Z-sorrendet. A normál alkalmazásoknak erre soha nincs szüksége."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"képernyő rögzítése"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Lehetővé teszi az alkalmazás számára, hogy ideiglenesen rögzítse a képernyőt a teljes képernyős váltáshoz."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"billentyűk és gombok megnyomása"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Lehetővé teszi az alkalmazás számára saját beviteli eseményeinek (billentyűlenyomások stb.) elküldését más alkalmazásoknak. A rosszindulatú alkalmazások ennek segítségével átvehetik a táblagép irányítását."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Lehetővé teszi az alkalmazás számára saját beviteli eseményeinek (billentyűlenyomások stb.) elküldését más alkalmazásoknak. A rosszindulatú alkalmazások ennek segítségével átvehetik a telefon irányítását."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"alkalmazások közvetlen telepítése"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Lehetővé teszi az alkalmazás számára új vagy frissített Android-csomagok telepítését. A rosszindulatú alkalmazások ezáltal önkényesen hozzáadhatnak hatékony engedélyekkel rendelkező alkalmazásokat."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"alkalmazás-gyorsítótár összes adatának törlése"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Lehetővé teszi az alkalmazás számára, hogy helyet szabadítson fel a táblagépen az alkalmazás-gyorsítótár könyvtárban lévő fájlok törlésével. A hozzáférés erősen korlátozott, általában a rendszerfolyamatokra korlátozódik."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Lehetővé teszi az alkalmazás számára, hogy helyet szabadítson fel a telefonon az alkalmazás-gyorsítótár könyvtárban lévő fájlok törlésével. A hozzáférés erősen korlátozott, általában a rendszerfolyamatokra korlátozódik."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Lehetővé teszi az alkalmazás számára, hogy tárhelyet szabadítson fel a táblagépen azáltal, hogy fájlokat töröl más alkalmazások gyorsítótármappáiból. Ez a többi alkalmazás lassabb elindulását okozhatja, mert azoknak újra le kell kérniük az adataikat."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Lehetővé teszi az alkalmazás számára, hogy tárhelyet szabadítson fel a telefonon azáltal, hogy fájlokat töröl más alkalmazások gyorsítótármappáiból. Ez a többi alkalmazás lassabb elindulását okozhatja, mert azoknak újra le kell kérniük az adataikat."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"alkalmazás-erőforrások áthelyezése"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Lehetővé teszi az alkalmazás számára alkalmazás-erőforrások áthelyezését a belső tárolóról egy külső tárolóra, és fordítva."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"érzékeny naplóadatok olvasása"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Lehetővé teszi az alkalmazás számára további helyszolgáltatói parancsok elérését. Ezáltal az alkalmazás beavatkozhat a GPS vagy más helyforrások működésébe."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"engedély helyszolgáltató telepítésére"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Helyforrásutánzatok létrehozása tesztelés céljából, vagy új helyszolgáltató telepítése. Ez lehetővé teszi az alkalmazás számára, hogy felülírja az olyan helyforrások által biztosított hely- és/vagy állapotadatokat, mint a GPS vagy helyszolgáltatók."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"pontos (GPS-alapú) tartózkodási hely"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"A pontos tartózkodásihely-adatokhoz való hozzáférés GPS használatával táblagépen. Amikor a helyszolgáltatások elérhetők és engedélyezve vannak, akkor az alkalmazás meghatározhatja az Ön pontos tartózkodási helyét."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"A pontos tartózkodásihely-adatokhoz való hozzáférés GPS használatával telefonon. Amikor a helyszolgáltatások elérhetők és engedélyezve vannak, akkor az alkalmazás meghatározhatja az Ön pontos tartózkodási helyét."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"hozzávetőleges (hálózatalapú) tartózkodási hely"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"A hozzávetőleges tartózkodásihely-adatokhoz való hozzáférés cellatornyok és Wi-Fi hálózatok használatával. Amikor ezek a helyszolgáltatások elérhetők és engedélyezve vannak, akkor az alkalmazás meghatározhatja az Ön hozzávetőleges tartózkodási helyét."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"pontos (GPS- és hálózatalapú) tartózkodási hely"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Lehetővé teszi az alkalmazás számára a pontos tartózkodási helyének lekérését a GPS és a hálózati helyforrások, így például az adótornyok és a Wi-Fi hálózatok adatainak felhasználásával. A helyszolgáltatásokat be kell kapcsolni, és az adatoknak elérhetőknek kell lenniük az eszközén ahhoz, hogy az alkalmazás használhassa őket. Használatukkal az alkalmazások meghatározhatják az Ön tartózkodási helyét, és az akkumulátort is fokozottan fogyaszthatják."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"hozzávetőleges (hálózatalapú) tartózkodási hely"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Lehetővé teszi az alkalmazás számára a körülbelüli tartózkodási helyének lekérését. A helymeghatározás a hálózati helyforrások, így például az adótornyok és a Wi-Fi hálózatok adatainak felhasználásával történik. A helyszolgáltatásokat be kell kapcsolni, és az adatoknak elérhetőknek kell lenniük az eszközén ahhoz, hogy az alkalmazás használhassa őket. Használatukkal az alkalmazások meghatározhatják az Ön hozzávetőleges tartózkodási helyét."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"hozzáférés a SurfaceFlingerhez"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Lehetővé teszi az alkalmazás számára a SurfaceFlinger alacsony szintű funkciók használatát."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"keretpuffer olvasása"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Lehetővé teszi az alkalmazás számára a keretpuffer tartalmának olvasását."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"Wi-Fi kijelzők konfigurálása"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Lehetővé teszi, hogy az alkalmazás Wi-Fi kijelzőket konfiguráljon, és csatlakozzon hozzájuk."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wi-Fi kijelzők irányítása"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Lehetővé teszi, hogy az alkalmazás irányítsa a Wi-Fi kijelzők alacsonyabb szintű funkcióit."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"hangbeállítások módosítása"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Lehetővé teszi az alkalmazás számára az általános hangbeállítások, például a hangerő és a használni kívánt kimeneti hangszóró módosítását."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"hanganyag rögzítése"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"Bluetooth-beállítások elérése"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Lehetővé teszi az alkalmazás számára, hogy konfigurálja a helyi Bluetooth-t, valamint hogy távoli eszközöket fedezzen fel és párosítson."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Lehetővé teszi az alkalmazás számára, hogy konfigurálja a helyi Bluetooth telefont, valamint hogy távoli eszközöket fedezzen fel és párosítson."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"WiMAX kapcsolatok megtekintése"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX-kapcsolódás és a kapcsolat bontása"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Lehetővé teszi az alkalmazás számára, hogy ellenőrizze, a WiMax engedélyezve van-e, valamint hogy információt gyűjtsön a csatlakoztatott WiMax-hálózatokról."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX-állapot módosítása"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Lehetővé teszi az alkalmazás számára, hogy a táblagépet csatlakoztassa WiMAX-hálózathoz vagy leválassza azt róla."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Lehetővé teszi az alkalmazás számára, hogy módosítsa a jelenleg szinkronizált hírcsatornákat. A rosszindulatú alkalmazások módosíthatják a szinkronizált hírcsatornákat."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"szótárhoz adott kifejezések olvasása"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Lehetővé teszi az alkalmazás számára, hogy beolvassa a felhasználói szótárban tárolt összes szót, nevet és kifejezést."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"a felhasználó által definiált szótár írása"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"szavak hozzáadása a felhasználó által definiált szótárhoz"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Lehetővé teszi az alkalmazás számára, hogy új szavakat írjon a felhasználói szótárba."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"védett tárhelyhez való hozzáférés tesztelése"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"védett tárhelyhez való hozzáférés tesztelése"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Lehetővé teszi az alkalmazás számára egy olyan USB-háttértár engedélyének tesztelését, amely későbbi eszközökön lesz elérhető."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Lehetővé teszi az alkalmazás számára egy olyan USB-háttértár engedélyének tesztelését, amely későbbi eszközökön lesz elérhető."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Lehetővé teszi az alkalmazás számára egy olyan SD-kártya engedélyének tesztelését, amely későbbi eszközökön lesz elérhető."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"USB-tár törlése/módosítása"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"SD-kártya tartalmának módosítása vagy törlése"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Lehetővé teszi az alkalmazás számára, hogy írjon az SD-kártyára."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"belső tár tartalmának módosítása/törlése"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Lehetővé teszi az alkalmazás számára, hogy módosítsa a belső háttértár tartalmát."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"hozzáf. minden felh. külső tár"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Minden felhasználó számára lehetővé teszi, hogy az alkalmazás hozzáférjen külső tárolókhoz."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"hozzáférés a gyorsítótár fájlrendszeréhez"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Lehetővé teszi az alkalmazás számára a gyorsítótár-fájlrendszer olvasását és írását."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"internetes hívások kezdeményezése és fogadása"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Megköveteli a tárolt alkalmazásadatok titkosítását."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Kamerák letiltása"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Az összes eszközkamera használatának megakadályozása."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Funkciók letiltása billentyűzár esetén."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Bizonyos funkciók használatának megakadályozása billentyűzár esetén."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Otthoni"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Újra"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Elérte az arcalapú feloldási kísérletek maximális számát"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Töltés (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Feltöltve."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Feltöltve"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Csatlakoztassa a töltőt."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nincs SIM-kártya."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Nincs SIM kártya."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nincs SIM-kártya a táblagépben."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Nincs SIM-kártya a telefonban."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Helyezzen be egy SIM kártyát."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Minta törölve"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Cella hozzáadva"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Minta befejezve"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Modul hozzáadása."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Üres"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Feloldási terület kiterjesztve."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Feloldási terület összecsukva."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> modul."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Felhasználóválasztó"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Állapot"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Kamera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Médiaelemek vezérlője"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"A modulátrendezés elkezdődött."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"A modulátrendezés véget ért."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> modul törölve."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"A feloldási terület kiterjesztése."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Feloldás csúsztatással"</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Feloldás mintával"</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Arcalapú feloldás"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Feloldás PIN kóddal"</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Feloldás jelszóval"</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mintaterület"</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Csúsztatási terület"</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"URL másolása"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Szöveg kijelölése"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Szöveg kijelölése"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"hozzáadás a szótárhoz"</string>
-    <string name="deleteText" msgid="7070985395199629156">"törlés"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Hozzáadás a szótárhoz"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Törlés"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Beviteli mód"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Műveletek szöveggel"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Kevés a szabad terület"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Nyílt Wi-Fi hálózatok elérhetők"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Bejelentkezés Wi-Fi hálózatba"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Bejelentkezés a hálózatba"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nem sikerült csatlakozni a Wi-Fi hálózathoz"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" rossz internetkapcsolattal rendelkezik."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Címzett:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Adja meg a szükséges PIN kódot:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN kód:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"A telefon ideiglenesen kilép a Wi-Fi hálózatról, míg a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközhöz csatlakozik."</string>
     <string name="select_character" msgid="3365550120617701745">"Karakter beszúrása"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS-ek küldése"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/ b&gt; nagyszámú SMS üzenetet küld. Engedélyezi, hogy ez az alkalmazás továbbra is üzeneteket küldjön?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Engedélyezés"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Elutasítás"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; üzenetet szeretne küldeni &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; számra."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Ezzel "<font fgcolor="#ffffb060">"díjtételek keletkezhetnek"</font>" mobilszámláján."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Ezzel díjtételek keletkeznek mobilszámláján."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Küldés"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Mégse"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"A választás mentése"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Módosítás: Beállítások &gt; Alkalmazások"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Engedélyezés mindig"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Soha nem engedélyezem"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kártya eltávolítva"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"A mobilhálózat nem lesz elérhető, amíg újra nem indítja egy érvényes SIM kártya behelyezése után."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Kész"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Dátum beállítása"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Beállítás"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Kész"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Alapértelmezett"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Nincs szükség engedélyre"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Elrejtés"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Az összes megjelenítése"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"ÚJ: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"ÚJ: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Szolgáltató: <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Nincs szükség engedélyre"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"ez pénzbe kerülhet Önnek"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB-háttértár"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB-eszköz csatlakoztatva"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"USB-kapcsolaton keresztül csatlakozott a számítógéphez. Érintse meg a lenti gombot, ha fájlokat szeretne másolni a számítógép és az Android USB-tára között."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"A(z) <xliff:g id="APP">%s</xliff:g> aktiválta a VPN-t"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Érintse meg a hálózat kezeléséhez."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Csatlakozva ide: <xliff:g id="SESSION">%s</xliff:g>. Érintse meg a hálózat kezeléséhez."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Csatlakozás a mindig bekapcsolt VPN-hez..."</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Csatlakozva a mindig bekapcsolt VPN-hez"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Hiba a mindig bekapcsolt VPN-nel"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Érintse meg a kapcsolat alaphelyzetbe állításához."</string>
     <string name="upload_file" msgid="2897957172366730416">"Fájl kiválasztása"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nincs fájl kiválasztva"</string>
     <string name="reset" msgid="2448168080964209908">"Alaphelyzet"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Megosztás"</string>
     <string name="find" msgid="4808270900322985960">"Keresés"</string>
     <string name="websearch" msgid="4337157977400211589">"Webes keresés"</string>
+    <string name="find_next" msgid="5742124618942193978">"Következő keresése"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Előző keresése"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Helykérelem a következőtől: <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Helykérelem"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Igénylő <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Fejhallgató"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dokkolóegység hangszórója"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI audió"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Rendszer"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth hang"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Kész"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Médiakimenet"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Keresés..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Kapcsolódás..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Elérhető"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Nem érhető el"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Beépített képernyő"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-képernyő"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"<xliff:g id="ID">%1$d</xliff:g>. fedvény"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> képpont"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Vezeték nélküli kijelző csatlakoztatva"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Ez a kijelző megjelenítést végez egy másik eszközön"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Szétkapcsol"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Segélyhívás"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Elfelejtett minta"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Helytelen minta"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Helytelen jelszó"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Helytelen PIN kód"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Próbálkozzon újra <xliff:g id="NUMBER">%d</xliff:g> másodperc múlva."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Rajzolja le a mintát"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Adja meg a SIM kártya PIN kódját"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Adja meg a PIN kódot"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Írja be a jelszót"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"A SIM kártya le van tiltva. A folytatáshoz adja meg a PUK kódot. A részletekért vegye fel a kapcsolatot szolgáltatójával."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Kívánt PIN kód megadása"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Kívánt PIN kód megerősítése"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM kártya feloldása..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Helytelen PIN kód."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"4–8 számjegyű PIN kódot írjon be."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"A PUK kód legalább  8 számjegyből kell, hogy álljon."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Adja meg újra a helyes PUK kódot. Az ismételt próbálkozással véglegesen letiltja a SIM kártyát."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"A PIN kódok nem egyeznek."</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Túl sok mintarajzolási próbálkozás"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"A feloldáshoz jelentkezzen be Google Fiókjával."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Felhasználónév (e-mail cím)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Jelszó"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Bejelentkezés"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Érvénytelen felhasználónév vagy jelszó."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Elfelejtette a felhasználónevét vagy jelszavát?"\n"Keresse fel a "<b>"google.com/accounts/recovery"</b>" webhelyet."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Fiók ellenőrzése..."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"<xliff:g id="NUMBER_0">%d</xliff:g> alkalommal helytelenül adta meg PIN kódját. "\n\n"Próbálja újra <xliff:g id="NUMBER_1">%d</xliff:g> másodperc múlva."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"<xliff:g id="NUMBER_0">%d</xliff:g> alkalommal helytelenül adta meg a jelszót. "\n\n" Próbálja újra <xliff:g id="NUMBER_1">%d</xliff:g> másodperc múlva."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"<xliff:g id="NUMBER_0">%d</xliff:g> alkalommal rosszul rajzolta le feloldási mintát. "\n\n"Próbálja újra <xliff:g id="NUMBER_1">%d</xliff:g> másodperc múlva."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"A táblagépet <xliff:g id="NUMBER_0">%d</xliff:g> alkalommal próbálta meg sikertelenül feloldani. <xliff:g id="NUMBER_1">%d</xliff:g> további sikertelen próbálkozás után a rendszer visszaállítja a táblagép gyári alapértelmezett beállításait, és minden felhasználói adat elvész."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"A telefont <xliff:g id="NUMBER_0">%d</xliff:g> alkalommal próbálta meg sikertelenül feloldani. <xliff:g id="NUMBER_1">%d</xliff:g> további sikertelen próbálkozás után a rendszer visszaállítja a telefon gyári alapértelmezett beállításait, és minden felhasználói adat elvész."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"A táblagépet <xliff:g id="NUMBER">%d</xliff:g> alkalommal próbálta meg sikertelenül feloldani. A rendszer visszaállítja a táblagép gyári alapértelmezett beállításait."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"A telefont <xliff:g id="NUMBER">%d</xliff:g> alkalommal próbálta meg sikertelenül feloldani. A rendszer visszaállítja a telefon gyári alapértelmezett beállításait."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"<xliff:g id="NUMBER_0">%d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%d</xliff:g> sikertelen kísérlet után egy e-mail fiók használatával kell feloldania a táblagépét."\n\n" Kérjük, próbálja újra <xliff:g id="NUMBER_2">%d</xliff:g> másodperc múlva."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"<xliff:g id="NUMBER_0">%d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%d</xliff:g> sikertelen kísérlet után egy e-mail fiók használatával kell feloldania a telefonját."\n\n" Kérjük, próbálja újra <xliff:g id="NUMBER_2">%d</xliff:g> másodperc múlva."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Eltávolítás"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"A biztonságos szint fölé emeli a hangerőt?"\n"Ha hosszú ideig hangosan hallgatja a zenét, az károsíthatja a hallását."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Továbbra is tartsa lenyomva két ujját a hozzáférés engedélyezéséhez."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Hozzáférés engedélyezve"</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Hozzáférés megszakítva."</string>
+    <string name="user_switched" msgid="3768006783166984410">"<xliff:g id="NAME">%1$s</xliff:g> az aktuális felhasználó."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Tulajdonos"</string>
 </resources>
diff --git a/core/res/res/values-in-rID/donottranslate-cldr.xml b/core/res/res/values-in-rID/donottranslate-cldr.xml
index b79fe00..8b13bcf 100644
--- a/core/res/res/values-in-rID/donottranslate-cldr.xml
+++ b/core/res/res/values-in-rID/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Januari</string>
-    <string name="month_long_standalone_february">Februari</string>
-    <string name="month_long_standalone_march">Maret</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">Mei</string>
-    <string name="month_long_standalone_june">Juni</string>
-    <string name="month_long_standalone_july">Juli</string>
-    <string name="month_long_standalone_august">Agustus</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">Oktober</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">Desember</string>
-
-    <string name="month_long_january">Januari</string>
-    <string name="month_long_february">Februari</string>
-    <string name="month_long_march">Maret</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">Mei</string>
-    <string name="month_long_june">Juni</string>
-    <string name="month_long_july">Juli</string>
-    <string name="month_long_august">Agustus</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">Oktober</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">Desember</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mar</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">Mei</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Agu</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Okt</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Des</string>
-
-    <string name="month_shortest_january">1</string>
-    <string name="month_shortest_february">2</string>
-    <string name="month_shortest_march">3</string>
-    <string name="month_shortest_april">4</string>
-    <string name="month_shortest_may">5</string>
-    <string name="month_shortest_june">6</string>
-    <string name="month_shortest_july">7</string>
-    <string name="month_shortest_august">8</string>
-    <string name="month_shortest_september">9</string>
-    <string name="month_shortest_october">10</string>
-    <string name="month_shortest_november">11</string>
-    <string name="month_shortest_december">12</string>
-
-    <string name="day_of_week_long_sunday">Minggu</string>
-    <string name="day_of_week_long_monday">Senin</string>
-    <string name="day_of_week_long_tuesday">Selasa</string>
-    <string name="day_of_week_long_wednesday">Rabu</string>
-    <string name="day_of_week_long_thursday">Kamis</string>
-    <string name="day_of_week_long_friday">Jumat</string>
-    <string name="day_of_week_long_saturday">Sabtu</string>
-
-    <string name="day_of_week_medium_sunday">Min</string>
-    <string name="day_of_week_medium_monday">Sen</string>
-    <string name="day_of_week_medium_tuesday">Sel</string>
-    <string name="day_of_week_medium_wednesday">Rab</string>
-    <string name="day_of_week_medium_thursday">Kam</string>
-    <string name="day_of_week_medium_friday">Jum</string>
-    <string name="day_of_week_medium_saturday">Sab</string>
-
-    <string name="day_of_week_short_sunday">Min</string>
-    <string name="day_of_week_short_monday">Sen</string>
-    <string name="day_of_week_short_tuesday">Sel</string>
-    <string name="day_of_week_short_wednesday">Rab</string>
-    <string name="day_of_week_short_thursday">Kam</string>
-    <string name="day_of_week_short_friday">Jum</string>
-    <string name="day_of_week_short_saturday">Sab</string>
-
-    <string name="day_of_week_shortest_sunday">1</string>
-    <string name="day_of_week_shortest_monday">2</string>
-    <string name="day_of_week_shortest_tuesday">3</string>
-    <string name="day_of_week_shortest_wednesday">4</string>
-    <string name="day_of_week_shortest_thursday">5</string>
-    <string name="day_of_week_shortest_friday">6</string>
-    <string name="day_of_week_shortest_saturday">7</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-in/donottranslate-cldr.xml b/core/res/res/values-in/donottranslate-cldr.xml
index 9a634cc..6e9bba4 100644
--- a/core/res/res/values-in/donottranslate-cldr.xml
+++ b/core/res/res/values-in/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Januari</string>
-    <string name="month_long_standalone_february">Februari</string>
-    <string name="month_long_standalone_march">Maret</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">Mei</string>
-    <string name="month_long_standalone_june">Juni</string>
-    <string name="month_long_standalone_july">Juli</string>
-    <string name="month_long_standalone_august">Agustus</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">Oktober</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">Desember</string>
-
-    <string name="month_long_january">Januari</string>
-    <string name="month_long_february">Februari</string>
-    <string name="month_long_march">Maret</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">Mei</string>
-    <string name="month_long_june">Juni</string>
-    <string name="month_long_july">Juli</string>
-    <string name="month_long_august">Agustus</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">Oktober</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">Desember</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mar</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">Mei</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Agu</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Okt</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Des</string>
-
-    <string name="month_shortest_january">1</string>
-    <string name="month_shortest_february">2</string>
-    <string name="month_shortest_march">3</string>
-    <string name="month_shortest_april">4</string>
-    <string name="month_shortest_may">5</string>
-    <string name="month_shortest_june">6</string>
-    <string name="month_shortest_july">7</string>
-    <string name="month_shortest_august">8</string>
-    <string name="month_shortest_september">9</string>
-    <string name="month_shortest_october">10</string>
-    <string name="month_shortest_november">11</string>
-    <string name="month_shortest_december">12</string>
-
-    <string name="day_of_week_long_sunday">Minggu</string>
-    <string name="day_of_week_long_monday">Senin</string>
-    <string name="day_of_week_long_tuesday">Selasa</string>
-    <string name="day_of_week_long_wednesday">Rabu</string>
-    <string name="day_of_week_long_thursday">Kamis</string>
-    <string name="day_of_week_long_friday">Jumat</string>
-    <string name="day_of_week_long_saturday">Sabtu</string>
-
-    <string name="day_of_week_medium_sunday">Min</string>
-    <string name="day_of_week_medium_monday">Sen</string>
-    <string name="day_of_week_medium_tuesday">Sel</string>
-    <string name="day_of_week_medium_wednesday">Rab</string>
-    <string name="day_of_week_medium_thursday">Kam</string>
-    <string name="day_of_week_medium_friday">Jum</string>
-    <string name="day_of_week_medium_saturday">Sab</string>
-
-    <string name="day_of_week_short_sunday">Min</string>
-    <string name="day_of_week_short_monday">Sen</string>
-    <string name="day_of_week_short_tuesday">Sel</string>
-    <string name="day_of_week_short_wednesday">Rab</string>
-    <string name="day_of_week_short_thursday">Kam</string>
-    <string name="day_of_week_short_friday">Jum</string>
-    <string name="day_of_week_short_saturday">Sab</string>
-
-    <string name="day_of_week_shortest_sunday">1</string>
-    <string name="day_of_week_shortest_monday">2</string>
-    <string name="day_of_week_shortest_tuesday">3</string>
-    <string name="day_of_week_shortest_wednesday">4</string>
-    <string name="day_of_week_shortest_thursday">5</string>
-    <string name="day_of_week_shortest_friday">6</string>
-    <string name="day_of_week_shortest_saturday">7</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index a760e41..b5dfcd5 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -134,7 +134,7 @@
     <string name="me" msgid="6545696007631404292">"Saya"</string>
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opsi tablet"</string>
     <string name="power_dialog" product="default" msgid="1319919075463988638">"Opsi telepon"</string>
-    <string name="silent_mode" msgid="7167703389802618663">"Modus senyap"</string>
+    <string name="silent_mode" msgid="7167703389802618663">"Mode senyap"</string>
     <string name="turn_on_radio" msgid="3912793092339962371">"Hidupkan nirkabel"</string>
     <string name="turn_off_radio" msgid="8198784949987062346">"Matikan nirkabel"</string>
     <string name="screen_lock" msgid="799094655496098153">"Kunci layar"</string>
@@ -154,11 +154,14 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opsi telepon"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Kunci layar"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Matikan daya"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Laporan bug"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Ambil laporan bug"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Ini akan mengumpulkan informasi tentang status perangkat Anda saat ini, untuk dikirimkan sebagai pesan email. Akan memakan sedikit waktu dari memulai laporan bug hingga siap untuk dikirim; bersabarlah."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Mode senyap"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Suara MATI"</string>
-    <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Suara HIDUP"</string>
+    <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Suara AKTIF"</string>
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode pesawat"</string>
-    <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Mode pesawat HIDUP"</string>
+    <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Mode pesawat AKTIF"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Mode pesawat MATI"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode aman"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Pesan Anda"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Membaca dan menulis SMS, email, dan pesan Anda lainnya."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Informasi pribadi Anda"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Akses langsung ke kontak dan kalender yang disimpan di tablet."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"akses langsung pada kontak dan kalender yang tersimpan pada ponsel."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Akses langsung ke informasi tentang Anda, yang tersimpan dalam kartu kontak Anda."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Informasi sosial Anda"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Akses langsung ke informasi tentang kontak dan hubungan sosial Anda."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Lokasi Anda"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Memonitor lokasi fisik Anda."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Komunikasi jaringan"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Mengakses berbagai fitur jaringan."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Mengakses perangkat dan jaringan melalui Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Setelan Audio"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Mengubah setelan audio."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Memengaruhi Baterai"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Menggunakan fitur yang dapat menguras baterai dengan cepat."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalender"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Akses langsung ke kalender dan acara."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Membaca Kamus Pengguna"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Membaca kata dalam kamus pengguna."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Menulis Kamus Pengguna"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Menambahkan kata ke kamus pengguna."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Bookmark dan Riwayat"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Akses langsung ke bookmark dan riwayat browser."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarm"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Menyetel jam alarm."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Pesan Suara"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Akses langsung ke pesan suara."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Akses langsung ke mikrofon untuk merekam audio."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Akses langsung ke kamera untuk gambar atau tangkapan video."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Informasi aplikasi Anda"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Kemampuan untuk memengaruhi perilaku aplikasi lain pada perangkat Anda."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Wallpaper"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Mengubah setelan wallpaper perangkat."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Jam"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Mengubah zona waktu atau waktu perangkat."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Bilah Status"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Mengubah setelan bilah status perangkat."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Setelan Sinkronisasi"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Akses ke setelan sinkronisasi."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Akun-akun Anda"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Akses akun yang tersedia."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Kontrol perangkat keras"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Akses tingkat rendah dan kontrol sistem."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Peralatan pengembangan"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Fitur hanya diperlukan oleh pengembang apl."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"UI Aplikasi Lainnya"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Memengaruhi UI aplikasi lain."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Penyimpanan"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Akses penyimpanan USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Akses kartu SD."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Memungkinkan aplikasi menerima dan memproses pesan WAP. Izin ini mencakup kemampuan untuk memantau atau menghapus pesan yang dikirim kepada Anda tanpa menunjukkannya kepada Anda."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"mengambil apl yang berjalan"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Memungkinkan aplikasi mengambil informasi tentang tugas yang dijalankan saat ini dan baru-baru ini. Izin ini memungkinkan aplikasi menemukan informasi tentang aplikasi mana yang digunakan pada perangkat."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"berinteraksi antar-pengguna"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Mengizinkan aplikasi melakukan tindakan antar-pengguna yang berbeda pada perangkat. Aplikasi berbahaya dapat menggunakan ini untuk mengganggu perlindungan antar-pengguna."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"lisensi penuh untuk berinteraksi antar-pengguna"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Mengizinkan semua interaksi yang mungkin antar-pengguna."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"kelola pengguna"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Memungkinkan aplikasi mengelola pengguna pada perangkat, termasuk kueri, pembuatan, dan penghapusan."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"mengambil detail aplikasi yang sedang berjalan"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Izinkan aplikasi mengambil informasi mendetail tentang tugas yang saat ini dan baru-baru ini dijalankan. Aplikasi berbahaya dapat menemukan informasi pribadi tentang aplikasi lain."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"menyusun ulang apl yang berjalan"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Mengizinkan apl mengambil keadaan internal sistem. Apl berbahaya dapat mengambil berbagai informasi pribadi dan aman yang seharusnya tidak diperlukan."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"ambil konten layar"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Mengizinkan apl mengambil konten jendela aktif. Apl berbahaya dapat mengambil seluruh konten jendela dan memeriksa semua teksnya kecuali sandi."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"aktifkan aksesibilitas untuk sementara"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Memungkinkan aplikasi mengaktifkan aksesibilitas pada perangkat untuk sementara. Aplikasi berbahaya dapat mengaktifkan aksesibilitas tanpa izin pengguna."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"mengambil info jendela"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Mengizinkan aplikasi mengambil informasi tentang jendela dari pengelola jendela. Aplikasi berbahaya dapat mengambil informasi yang ditujukan untuk penggunaan sistem internal."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"memfilter acara"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Mengizinkan aplikasi mendaftarkan filter masukan yang memfilter streaming semua acara pengguna sebelum acara dikirimkan. Aplikasi berbahaya dapat mengontrol UI sistem tanpa campur tangan pengguna."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"memperbesar tampilan"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Izinkan aplikasi memperbesar konten tampilan. Aplikasi berbahaya dapat mengubah konten tampilan dengan merender perangkat menjadi tidak dapat digunakan."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"penghentian sebagian"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Letakkan pengelola aktivitas dalam kondisi mati. Tidak melakukan penonaktifan penuh."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"cegah pergantian aplikasi"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Mengizinkan apl mengontrol jumlah maksimum proses yang akan berjalan. Tidak pernah diperlukan oleh apl normal."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"paksa aplikasi latar belakang agar menutup"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Mengizinkan apl mengontrol apakah aktivitas selalu selesai setelah berpindah ke latar belakang. Tidak pernah digunakan untuk apl normal."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"ubah statistika baterai"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Mengizinkan apl memodifikasi statistik baterai yang dikumpulkan. Tidak untuk digunakan oleh apl normal."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"baca statistik baterai"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Mengizinkan aplikasi membaca data penggunaan baterai tingkat rendah. Dapat mengizinkan aplikasi mencari informasi mendetail tentang aplikasi mana yang Anda gunakan."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"ubah statistik baterai"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Mengizinkan aplikasi mengubah statistik baterai yang dikumpulkan. Tidak untuk digunakan oleh aplikasi normal."</string>
     <string name="permlab_backup" msgid="470013022865453920">"mengontrol cadangan dan pemulihan sistem"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Mengizinkan apl mengontrol mekanisme pencadangan dan pemulihan sistem. Tidak untuk digunakan oleh apl normal."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"konfirmasi pencadangan penuh atau pulihkan operasi"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"tampilkan jendela yang tidak diizinkan"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Mengizinkan apl membuat jendela agar dapat digunakan oleh antarmuka pengguna sistem internal. Tidak untuk digunakan oleh apl normal."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"tutup aplikasi lain"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Memungkinkan aplikasi menampilkan jendela lansiran sistem. Beberapa jendela lansiran dapat mengambil alih seluruh layar."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Mengizinkan aplikasi untuk berada di atas aplikasi lainnya atau bagian antarmuka pengguna. Aplikasi tersebut mungkin menganggu penggunaan Anda atas antarmuka pada aplikasi mana pun, atau ubah apa yang Anda lihat di aplikasi lainnya."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"ubah kecepatan animasi global"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Mengizinkan apl mengubah kecepatan animasi global (animasi lebih cepat atau lebih lambat) kapan saja."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"mengelola token apl"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Mengizinkan apl membuat dan mengelola tokennya sendiri, memintas pengurutan Z normalnya. Tidak pernah diperlukan oleh apl normal."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"membekukan layar"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Izinkan aplikasi membekukan layar untuk transisi layar penuh untuk sementara."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"tekan kunci dan tombol kontrol"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Mengizinkan apl menyampaikan aktivitas masukannya sendiri (penekanan tombol, dll) ke apl lain. Apl berbahaya dapat menggunakan ini untuk mengambil alih tablet."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Mengizinkan apl menyampaikan aktivitas masukannya sendiri (penekanan tombol, dll) ke apl lain. Apl berbahaya dapat menggunakan ini untuk mengambil alih ponsel."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"langsung memasang apl"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Mengizinkan apl memasang paket Android yang baru atau diperbarui. Apl berbahaya dapat menggunakan ini untuk menambahkan apl baru dengan sembarang izin yang kuat."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"menghapus semua data cache apl"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Mengizinkan apl mengosongkan penyimpanan tablet dengan menghapus file dalam direktori cache apl. Akses biasanya sangat terbatas dan hanya diberikan bagi proses sistem."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Mengizinkan apl mengosongkan penyimpanan ponsel dengan menghapus file dalam direktori cache apl. Akses biasanya sangat terbatas dan hanya diberikan bagi proses sistem."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Mengizinkan aplikasi mengosongkan penyimpanan tablet menghapus file dalam direktori cache aplikasi lainnya. Ini dapat menyebabkan aplikasi lain memulai lebih lambat karena perlu mengambil ulang data mereka."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Mengizinkan aplikasi mengosongkan penyimpanan ponsel menghapus file dalam direktori cache aplikasi lainnya. Ini dapat menyebabkan aplikasi lain memulai lebih lambat karena perlu mengambil ulang data mereka."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"memindahkan sumber daya apl"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Mengizinkan apl memindahkan sumber daya apl dari media internal ke eksternal dan sebaliknya."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"baca data log sensitif"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Memungkinkan aplikasi mengakses perintah penyedia lokasi ekstra. Izin ini dapat memungkinkan aplikasi mengganggu pengoperasian GPS atau sumber lokasi lain."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"izin untuk memasang suatu penyedia lokasi"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Membuat sumber lokasi palsu untuk uji coba atau memasang penyedia lokasi baru. Izin ini memungkinkan aplikasi mengganti lokasi dan/atau status yang dimunculkan sumber lokasi lain, misalnya GPS atau penyedia lokasi."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"lokasi (GPS) yang tepat"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Mengakses sumber lokasi yang tepat, misalnya Sistem Pemosisian Global (GPS) di tablet. Ketika layanan lokasi tersedia dan diaktifkan, izin ini memungkinkan aplikasi menentukan lokasi Anda yang tepat."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Mengakses sumber lokasi yang tepat, misalnya Sistem Pemosisian Global (GPS) di ponsel. Ketika layanan lokasi tersedia dan diaktifkan, izin ini memungkinkan aplikasi menentukan lokasi Anda yang tepat."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"perkiraan lokasi (berbasis jaringan)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Mengakses perkiraan lokasi dari penyedia lokasi menggunakan sumber jaringan, misalnya menara seluler dan Wi-Fi. Ketika layanan lokasi ini tersedia dan diaktifkan, izin ini memungkinkan aplikasi menentukan perkiraan lokasi Anda."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"lokasi akurat (berbasis jaringan dan GPS)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Mengizinkan aplikasi memperoleh lokasi Anda yang akurat menggunakan Sistem Pemosisian Global (GPS) atau sumber lokasi jaringan, misalnya menara seluler dan Wi-Fi. Layanan lokasi ini harus diaktifkan dan tersedia untuk perangkat Anda agar aplikasi dapat menggunakannya. Aplikasi dapat menggunakan ini untuk menentukan perkiraan tempat Anda berada dan dapat menghabiskan daya baterai tambahan."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"perkiraan lokasi (berbasis jaringan)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Mengizinkan aplikasi untuk mendapatkan perkiraan lokasi Anda. Lokasi ini diperoleh dengan layanan lokasi yang menggunakan sumber lokasi jaringan, misalnya menara seluler dan Wi-Fi. Layanan lokasi ini harus diaktifkan dan tersedia untuk perangkat Anda agar aplikasi dapat menggunakannya. Aplikasi dapat menggunakan ini untuk menentukan perkiraan tempat Anda berada."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"akses SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Mengizinkan apl menggunakan fitur tingkat rendah SurfaceFlinger."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"baca buffer frame"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Mengizinkan apl membaca konten penyangga frame."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"mengonfigurasi tampilan Wifi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Izinkan aplikasi mengonfigurasi dan terhubung ke tampilan Wifi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"mengontrol tampilan Wifi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Izinkan aplikasi mengontrol fitur tingkat rendah dari tampilan Wifi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ubah setelan audio Anda"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Memungkinkan aplikasi mengubah setelan audio global, misalnya volume dan pengeras suara mana yang digunakan untuk keluaran."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"rekam audio"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"akses setelan Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Mengizinkan apl mengonfigurasi tablet Bluetooth lokal, dan menemukan serta menyandingkan dengan perangkat jarak jauh."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Mengizinkan apl mengonfigurasi ponsel Bluetooth lokal, dan menemukan serta menyandingkan dengan perangkat jarak jauh."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Lihat sambungan WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"sambungkan dan putuskan dari WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Memungkinkan aplikasi menentukan apakah WiMAX diaktifkan dan informasi tentang jaringan WiMAX apa saja yang tersambung."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Ubah status WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Memungkinkan aplikasi menyambungkan tablet ke dan memutus tablet dari jaringan WiMAX."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Mengizinkan apl memodifikasi umpan Anda yang disinkronkan saat ini. Apl berbahaya dapat mengubah umpan Anda yang disinkronkan."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"baca istilah yang Anda tambahkan ke kamus"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Memungkinkan aplikasi membaca semua kata, nama, dan frasa yang mungkin disimpan oleh pengguna di kamus pengguna."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"menulis ke kamus yang dibuat pengguna"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"Menambahkan kata ke kamus yang ditentukan pengguna"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Mengizinkan apl menulis kata-kata baru ke dalam kamus pengguna."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"akses uji coba ke penyimpanan yang dilindungi"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"akses uji coba ke penyimpanan yang dilindungi"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Memungkinkan aplikasi menguji izin untuk penyimpanan USB yang akan tersedia pada perangkat yang akan datang."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Memungkinkan aplikasi menguji izin penyimpanan USB yang akan tersedia di perangkat mendatang."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Memungkinkan aplikasi menguji izin untuk kartu SD yang akan tersedia pada perangkat yang akan datang."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"ubah/hapus konten pympanan USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"mengubah atau menghapus konten kartu SD Anda"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Memungkinkan apl menulis ke kartu SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"ubah/hapus konten penyimpanan media internal"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Mengizinkan apl memodifikasi konten penyimpanan media internal."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"akses penyimpanan eksternal"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Izinkan aplikasi mengakses penyimpanan eksternal untuk semua pengguna."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"akses sistem file cache."</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Mengizinkan apl membaca dan menulis pada sistem file cache."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"lakukan//terima panggilan internet"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Mengharuskan data apl yang disimpan untuk dienkripsi."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Nonaktifkan kamera"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Mencegah penggunaan semua kamera perangkat."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Nonaktifkan fitur di pengaman"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Mencegah penggunaan beberapa fitur dalam pengaman."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Rumah"</item>
     <item msgid="869923650527136615">"Seluler"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Coba lagi"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Percobaan Face Unlock melebihi batas maksimum"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Mengisi daya, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Terisi."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Terisi"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Hubungkan pengisi daya."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Tidak ada kartu SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Tidak ada kartu SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tidak ada kartu SIM dalam tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Tidak ada Kartu SIM di dalam ponsel."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Masukkan kartu SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Pola dihapus"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Sel ditambahkan"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Pola selesai"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Tambahkan widget."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Kosong"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Area buka kunci diluaskan."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Area buka kunci diciutkan."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Pemilih pengguna"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Status"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Kamera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Kontrol media"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Pengurutan ulang widget dimulai."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Pengurutan ulang widget berakhir."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> dihapus."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Luaskan area buka kunci."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Buka kunci dengan menggeser."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Buka kunci dengan pola."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Buka kunci dengan face unlock."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Buka kunci dengan PIN."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Buka kunci dengan sandi."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Area pola."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Area geser."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Salin URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Pilih teks"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Pemilihan teks"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"tambahkan ke kamus"</string>
-    <string name="deleteText" msgid="7070985395199629156">"hapus"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Tambahkan ke kamus"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Hapus"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metode masukan"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tindakan teks"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Ruang penyimpanan hampir habis"</string>
@@ -942,7 +1025,7 @@
     <string name="no" msgid="5141531044935541497">"Batal"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Perhatian"</string>
     <string name="loading" msgid="7933681260296021180">"Memuat..."</string>
-    <string name="capital_on" msgid="1544682755514494298">"HIDUP"</string>
+    <string name="capital_on" msgid="1544682755514494298">"AKTIF"</string>
     <string name="capital_off" msgid="6815870386972805832">"MATI"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Tindakan lengkap menggunakan"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"Gunakan secara default untuk tindakan ini."</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Jaringan Wi-Fi terbuka tersedia"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Masuk ke jaringan Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Masuk ke jaringan"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Tidak dapat tersambung ke Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" memiliki sambungan internet yang buruk."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Kepada:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Ketik PIN yang diminta:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Ponsel akan terputus sementara dari Wi-Fi saat tersambung ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Sisipkan huruf"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Mengirim pesan SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sedang mengirim pesan SMS dalam jumlah besar. Izinkan aplikasi ini untuk melanjutkan pengiriman pesan?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Izinkan"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Tolak"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ingin mengirim pesan kepada &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Hal ini "<font fgcolor="#ffffb060">"dapat menyebabkan akun ponsel Anda"</font>" mendapat tagihan."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Hal ini akan menyebabkan tagihan diberlakukan pada akun seluler Anda."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Kirim"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Batal"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Ingat pilihan saya"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Anda dapat mengubah ini nanti di Setelan &gt; Aplikasi"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Selalu Izinkan"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Jangan Pernah Izinkan"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Kartu SIM dihapus"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Jaringan seluler tidak akan tersedia sampai Anda memulai lagi dengan memasukkan kartu SIM yang valid."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Selesai"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setel tanggal"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Setel"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Selesai"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Default"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Tidak perlu izin"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Sembunyikan"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Tampilkan semua"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"BARU: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"BARU: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Disediakan oleh <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Tidak perlu izin"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"ini mungkin tidak gratis"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Penyimpanan massal USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB terhubung"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Anda telah tersambung ke komputer melalui USB. Sentuh tombol di bawah jika Anda ingin menyalin file antara komputer dan penyimpanan USB Android Anda."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Sentuh untuk mengelola jaringan."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Tersambung ke <xliff:g id="SESSION">%s</xliff:g>. Sentuh untuk mengelola jaringan."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Menyambungkan VPN selalu aktif..."</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN selalu aktif tersambung"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Kesalahan VPN selalu aktif"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Sentuh untuk menyetel ulang sambungan"</string>
     <string name="upload_file" msgid="2897957172366730416">"Pilih file"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Tidak ada file yang dipilih"</string>
     <string name="reset" msgid="2448168080964209908">"Setel ulang"</string>
@@ -1178,13 +1274,15 @@
     <string name="media_bad_removal" msgid="7960864061016603281">"Kartu SD dihapus sebelum dilepas."</string>
     <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Saat ini penyimpanan USB sedang diperiksa."</string>
     <string name="media_checking" product="default" msgid="7334762503904827481">"Kartu SD sedang diperiksa."</string>
-    <string name="media_removed" msgid="7001526905057952097">"Kartu SD telah dihapus."</string>
+    <string name="media_removed" msgid="7001526905057952097">"Kartu SD telah dikeluarkan."</string>
     <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Saat ini penyimpanan USB sedang digunakan oleh komputer."</string>
     <string name="media_shared" product="default" msgid="5706130568133540435">"Kartu SD sedang digunakan oleh komputer."</string>
     <string name="media_unknown_state" msgid="729192782197290385">"Media eksternal dalam status tidak diketahui."</string>
     <string name="share" msgid="1778686618230011964">"Bagikan"</string>
     <string name="find" msgid="4808270900322985960">"Temukan"</string>
     <string name="websearch" msgid="4337157977400211589">"Penelusuran Web"</string>
+    <string name="find_next" msgid="5742124618942193978">"Cari berikutnya"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Cari sebelumnya"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Permintaan lokasi dari <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Permintaan lokasi"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Diminta oleh <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Ponsel"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Headphone"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Pengeras suara dok"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Audio HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Selesai"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Keluaran media"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Memindai..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Menyambung..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Tersedia"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Tidak tersedia"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Layar Bawaan"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Layar HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Hamparan #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Layar nirkabel tersambung"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Layar ini ditampilkan di perangkat lain"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Putuskan sambungan"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Panggilan darurat"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Lupa Pola?"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Pola Salah"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Sandi Salah"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN Salah"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Coba lagi dalam <xliff:g id="NUMBER">%d</xliff:g> detik."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Gambar pola Anda"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Masukkan PIN SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Masukkan PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Masukkan Sandi"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM telah dinonaktifkan. Masukkan kode PUK untuk melanjutkan. Hubungi operator untuk keterangan selengkapnya."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Masukkan kode PIN yang diinginkan"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Konfirmasi kode PIN yang diinginkan"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Membuka kunci kartu SIM…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Kode PIN salah."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Ketik PIN yang terdiri dari 4 sampai 8 angka."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Kode PUK harus terdiri dari 8 angka atau lebih."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Masukkan kembali kode PUK yang benar. Jika berulang kali gagal, SIM akan dinonaktifkan secara permanen."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Kode PIN tidak cocok"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Terlalu banyak upaya pola"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Untuk membuka kunci, masuk dengan akun Google Anda."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Nama pengguna (email)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Sandi"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Masuk"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Nama pengguna atau sandi tidak valid."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Lupa nama pengguna atau sandi Anda?"\n"Kunjungi "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Memeriksa akun…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Anda telah <xliff:g id="NUMBER_0">%d</xliff:g> kali salah mengetik PIN. "\n\n"Coba lagi dalam <xliff:g id="NUMBER_1">%d</xliff:g> detik."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Anda telah <xliff:g id="NUMBER_0">%d</xliff:g> kali salah mengetik sandi. "\n\n"Coba lagi dalam <xliff:g id="NUMBER_1">%d</xliff:g> detik."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Anda telah <xliff:g id="NUMBER_0">%d</xliff:g> kali salah menggambar pola pembuka kunci. "\n\n"Coba lagi dalam <xliff:g id="NUMBER_1">%d</xliff:g> detik."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Anda telah <xliff:g id="NUMBER_0">%d</xliff:g> kali gagal saat berusaha membuka kunci tablet. Setelah <xliff:g id="NUMBER_1">%d</xliff:g> lagi upaya gagal, tablet akan disetel ulang ke setelan default pabrik dan semua data pengguna akan hilang."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Anda telah <xliff:g id="NUMBER_0">%d</xliff:g> kali gagal saat berusaha membuka kunci ponsel. Setelah <xliff:g id="NUMBER_1">%d</xliff:g> lagi upaya gagal, ponsel akan disetel ulang ke setelan default pabrik dan semua data pengguna akan hilang."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Anda telah <xliff:g id="NUMBER">%d</xliff:g> kali gagal saat berusaha membuka kunci tablet. Kini tablet akan disetel ulang ke setelan default pabrik."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Anda telah <xliff:g id="NUMBER">%d</xliff:g> kali gagal saat berusaha untuk membuka kunci ponsel. Kini ponsel akan disetel ulang ke setelan default pabrik."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Anda telah <xliff:g id="NUMBER_0">%d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%d</xliff:g> lagi upaya gagal, Anda akan diminta membuka kunci tablet menggunakan akun email."\n\n"Coba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> detik."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Anda telah <xliff:g id="NUMBER_0">%d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%d</xliff:g> lagi upaya gagal, Anda akan diminta membuka kunci ponsel menggunakan akun email."\n\n"Coba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> detik."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Hapus"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Naikkan volume di atas tingkat aman?"\n"Mendengarkan volume tinggi dalam jangka waktu yang lama dapat merusak pendengaran Anda."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Tahan terus dua jari untuk mengaktifkan aksesibilitas."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Aksesibilitas diaktifkan."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Aksesibilitas dibatalkan."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Pengguna saat ini <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Pemilik"</string>
 </resources>
diff --git a/core/res/res/values-it/donottranslate-cldr.xml b/core/res/res/values-it/donottranslate-cldr.xml
index 8cee828..9ff27e8 100644
--- a/core/res/res/values-it/donottranslate-cldr.xml
+++ b/core/res/res/values-it/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">gennaio</string>
-    <string name="month_long_standalone_february">febbraio</string>
-    <string name="month_long_standalone_march">marzo</string>
-    <string name="month_long_standalone_april">aprile</string>
-    <string name="month_long_standalone_may">maggio</string>
-    <string name="month_long_standalone_june">giugno</string>
-    <string name="month_long_standalone_july">luglio</string>
-    <string name="month_long_standalone_august">agosto</string>
-    <string name="month_long_standalone_september">settembre</string>
-    <string name="month_long_standalone_october">ottobre</string>
-    <string name="month_long_standalone_november">novembre</string>
-    <string name="month_long_standalone_december">dicembre</string>
-
-    <string name="month_long_january">gennaio</string>
-    <string name="month_long_february">febbraio</string>
-    <string name="month_long_march">marzo</string>
-    <string name="month_long_april">aprile</string>
-    <string name="month_long_may">maggio</string>
-    <string name="month_long_june">giugno</string>
-    <string name="month_long_july">luglio</string>
-    <string name="month_long_august">agosto</string>
-    <string name="month_long_september">settembre</string>
-    <string name="month_long_october">ottobre</string>
-    <string name="month_long_november">novembre</string>
-    <string name="month_long_december">dicembre</string>
-
-    <string name="month_medium_january">gen</string>
-    <string name="month_medium_february">feb</string>
-    <string name="month_medium_march">mar</string>
-    <string name="month_medium_april">apr</string>
-    <string name="month_medium_may">mag</string>
-    <string name="month_medium_june">giu</string>
-    <string name="month_medium_july">lug</string>
-    <string name="month_medium_august">ago</string>
-    <string name="month_medium_september">set</string>
-    <string name="month_medium_october">ott</string>
-    <string name="month_medium_november">nov</string>
-    <string name="month_medium_december">dic</string>
-
-    <string name="month_shortest_january">G</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">G</string>
-    <string name="month_shortest_july">L</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">domenica</string>
-    <string name="day_of_week_long_monday">lunedì</string>
-    <string name="day_of_week_long_tuesday">martedì</string>
-    <string name="day_of_week_long_wednesday">mercoledì</string>
-    <string name="day_of_week_long_thursday">giovedì</string>
-    <string name="day_of_week_long_friday">venerdì</string>
-    <string name="day_of_week_long_saturday">sabato</string>
-
-    <string name="day_of_week_medium_sunday">dom</string>
-    <string name="day_of_week_medium_monday">lun</string>
-    <string name="day_of_week_medium_tuesday">mar</string>
-    <string name="day_of_week_medium_wednesday">mer</string>
-    <string name="day_of_week_medium_thursday">gio</string>
-    <string name="day_of_week_medium_friday">ven</string>
-    <string name="day_of_week_medium_saturday">sab</string>
-
-    <string name="day_of_week_short_sunday">dom</string>
-    <string name="day_of_week_short_monday">lun</string>
-    <string name="day_of_week_short_tuesday">mar</string>
-    <string name="day_of_week_short_wednesday">mer</string>
-    <string name="day_of_week_short_thursday">gio</string>
-    <string name="day_of_week_short_friday">ven</string>
-    <string name="day_of_week_short_saturday">sab</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">L</string>
-    <string name="day_of_week_shortest_tuesday">M</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">G</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">m.</string>
-    <string name="pm">p.</string>
-    <string name="yesterday">ieri</string>
-    <string name="today">oggi</string>
-    <string name="tomorrow">domani</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index d912688..0edb0c1 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opzioni telefono"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Blocco schermo"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Spegni"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Segnalazione di bug"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Apri segnalazione bug"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Raccoglierà informazioni sullo stato corrente del dispositivo che verranno inviate sotto forma di messaggio email. Passerà un po\' di tempo prima che la segnalazione di bug aperta sia pronta per essere inviata; ti preghiamo di avere pazienza."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Modalità silenziosa"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Audio non attivo"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Audio attivo"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"I tuoi messaggi"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Consentono di leggere e scrivere SMS, email e altri messaggi."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Informazioni personali"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Accedere direttamente ai contatti e al calendario memorizzati sul tablet."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Accedere direttamente ai contatti e al calendario memorizzati sul telefono."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Accesso diretto alle informazioni su di te memorizzate nella tua scheda di contatto."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Tue informazioni sociali"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Accesso diretto alle informazioni sui tuoi contatti e sulle tue connessioni sociali."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"La tua posizione"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Monitoraggio della posizione fisica dell\'utente."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Comunicazione di rete"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Accesso a varie funzioni di rete."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"È possibile accedere a dispositivi e reti tramite Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Impostazioni audio"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Modifica delle impostazioni audio."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Influenza sulla batteria"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Uso di funzioni che possono consumare rapidamente la batteria."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Calendario"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Accesso diretto al calendario e agli eventi."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Lettura del dizionario utente"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"È possibile leggere le parole nel dizionario utente."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Scrittura nel dizionario utente"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"È possibile aggiungere parole al dizionario utente."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Segnalibri e cronologia"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Accesso diretto ai segnalibri e alla cronologia del browser."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Sveglia"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Impostazione della sveglia."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Segreteria"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Accesso diretto alla segreteria."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Microfono"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Accesso diretto al microfono per registrare audio."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Fotocamera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Accesso diretto alla fotocamera per acquisizione di immagini o video."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Informazioni sulle tue applicazioni"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Possibilità di influenzare il comportamento di altre applicazioni sul dispositivo."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Sfondo"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Modifica delle impostazioni dello sfondo del dispositivo."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Orologio"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Modifica della data e dell\'ora o del fuso orario del dispositivo."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Barra di stato"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Modifica delle impostazioni della barra di stato del dispositivo."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Impostazioni di sincronizzazione"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Accesso alle impostazioni di sincronizzazione."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"I tuoi account"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Accedere agli account disponibili."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Controlli hardware"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Accesso al sistema e controllo di livello inferiore."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Strumenti di sviluppo"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funzionalità necessarie soltanto agli sviluppatori di applicazioni."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Interfaccia utente di altre applicazioni"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Influenza sull\'interfaccia utente di altre applicazioni."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Archiviazione"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Accesso all\'archivio USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Accesso alla scheda SD."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Consente all\'applicazione di ricevere ed elaborare messaggi WAP. Questa autorizzazione include la facoltà di monitorare o eliminare i messaggi che ti vengono inviati senza mostrarteli."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"recupero applicazioni in esecuzione"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Consente all\'applicazione di recuperare informazioni sulle attività attualmente e recentemente in esecuzione. Ciò potrebbe consentire all\'applicazione di scoprire informazioni sulle applicazioni in uso sul dispositivo."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interazione tra gli utenti"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Consente all\'applicazione di compiere azioni per diversi utenti sul dispositivo. Le applicazioni dannose potrebbero farne uso per violare la protezione tra utenti."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"licenza completa per l\'interazione tra utenti"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Consente tutte le interazioni possibili tra gli utenti."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"Gestione utenti"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Consente alle applicazioni di gestire gli utenti sul dispositivo, nonché query, creazione ed eliminazione."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recupero dettagli applicazioni in esecuzione"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Consente all\'applicazione di recuperare informazioni dettagliate sulle attività attualmente e recentemente in esecuzione. Le applicazioni dannose potrebbero scoprire informazioni riservate su altre applicazioni."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"riordinamento applicazioni in esecuzione"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Consente all\'applicazione di recuperare lo stato interno del sistema. Le applicazioni dannose potrebbero recuperare una vasta gamma di informazioni private e protette di cui normalmente non dovrebbero mai avere bisogno."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"recupero dei contenuti della schermata"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Consente all\'applicazione di recuperare i contenuti della finestra attiva. Le applicazioni dannose potrebbero recuperare l\'intero contenuto della finestra ed esaminare tutto il testo, tranne le password."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"attivazione temporanea dell\'accessibilità"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Consente a un\'applicazione di attivare temporaneamente l\'accessibilità sul dispositivo. Le applicazioni dannose potrebbero attivare l\'accessibilità senza il consenso dell\'utente."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"recupero di informazioni sulle finestre"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Consente a un\'applicazione di recuperare informazioni sulle finestre dalla gestione finestre. Le applicazioni dannose potrebbero recuperare informazioni destinate all\'utilizzo da parte del sistema interno."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtro eventi"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Consente a un\'applicazione di registrare un filtro di ingresso che filtra lo stream di tutti gli eventi degli utenti prima che vengano inviati. Un\'applicazione dannosa potrebbe controllare l\'interfaccia utente del sistema senza l\'intervento dell\'utente."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"ingrandimento dello schermo"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Consente a un\'applicazione di ingrandire i contenuti di uno schermo. Le applicazioni dannose potrebbero trasformare i contenuti dello schermo in modo da rendere inutilizzabile il dispositivo."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"chiusura parziale"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Mette il gestore delle attività in uno stato di chiusura. Non esegue una chiusura completa."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedire commutazione applicazione"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Consente all\'applicazione di controllare il numero massimo di processi che verranno eseguiti. Mai necessaria per le applicazioni normali."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"chiusura forzata applicazioni di background"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Consente all\'applicazione di controllare se le attività sono sempre terminate non appena passano in background. Mai necessaria per le applicazioni normali."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"modifica statistiche batteria"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Consente all\'applicazione di modificare le statistiche raccolte sulla batteria. Da non usare per normali applicazioni."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"lettura statistiche batteria"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Consente a un\'applicazione di leggere i dati di utilizzo della batteria di basso livello correnti. Potrebbe consentire all\'applicazione di trovare informazioni dettagliate sulle applicazioni che utilizzi."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modifica statistiche batteria"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Consente all\'applicazione di modificare le statistiche raccolte sulla batteria. Da non usare per normali applicazioni."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controllo del backup di sistema e ripristino"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Consente all\'applicazione di controllare il meccanismo di backup e di ripristino del sistema. Da non usare per normali applicazioni."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"conferma di un\'operazione completa di backup o di ripristino"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"visualizzazione finestre non autorizzate"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Consente all\'applicazione di creare finestre destinate all\'uso da parte dell\'interfaccia utente del sistema interno. Da non usare per normali applicazioni."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"disegno su altre applicazioni"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Consente all\'applicazione di mostrare finestre di avviso di sistema. Alcune finestre di avviso potrebbero occupare l\'intero schermo."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Consente all\'applicazione di spostarsi sopra ad altre applicazioni o parti dell\'interfaccia utente. Potrebbe interferire con il tuo utilizzo dell\'interfaccia in qualsiasi applicazione o cambiare ciò che credi di vedere in altre applicazioni."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"modifica velocità di animazione globale"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Consente all\'applicazione di modificare la velocità di animazione globale (animazioni più veloci o più lente) in qualsiasi momento."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"gestione token applicazioni"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Consente all\'applicazione di creare e gestire i propri token, bypassando il loro normale Z-order. Non dovrebbe mai essere necessaria per le applicazioni normali."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"blocco dello schermo"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Consente all\'applicazione di bloccare temporaneamente lo schermo per una transizione a schermo intero."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"uso tasti e pulsanti di controllo"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Consente all\'applicazione di offrire i suoi eventi di input (pressioni di tasti ecc.) ad altre applicazioni. Le applicazioni dannose potrebbero farne uso per assumere il controllo del tablet."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Consente all\'applicazione di offrire i suoi eventi di input (pressioni di tasti ecc.) ad altre applicazioni. Le applicazioni dannose potrebbero farne uso per assumere il controllo del telefono."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"installazione diretta di applicazioni"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Consente all\'applicazione da installare pacchetti Android nuovi o aggiornati. Le applicazioni dannose potrebbero farne uso per aggiungere nuove applicazioni con autorizzazioni arbitrariamente importanti."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"eliminazione di tutti i dati della cache applicazioni"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Consente all\'applicazione di liberare spazio sul tablet eliminando file nella directory della cache dell\'applicazione. L\'accesso è generalmente limitato a processi di sistema."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Consente all\'applicazione di liberare spazio sul telefono eliminando file nella directory della cache dell\'applicazione. L\'accesso è generalmente limitato a processi di sistema."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Consente all\'applicazione di liberare memoria sul tablet eliminando file nelle directory della cache di altre applicazioni. Altre applicazioni potrebbero avviarsi più lentamente perché devono recuperare di nuovo i loro dati."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Consente all\'applicazione di liberare memoria sul telefono eliminando file nelle directory della cache di altre applicazioni. Altre applicazioni potrebbero avviarsi più lentamente perché devono recuperare di nuovo i loro dati."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"spostamento delle risorse dell\'applicazione"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Consente all\'applicazione di spostare le risorse delle applicazioni da supporti interni a supporti esterni e viceversa."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"Lettura dati di registro sensibili"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Consente all\'applicazione di accedere a ulteriori comandi del fornitore di posizione. Ciò potrebbe consentire all\'applicazione di interferire con il funzionamento del GPS o di altre fonti di localizzazione."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"autorizzazione a installare un provider di localizzazione"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Crea fonti di localizzazione fittizie per i test o installa un nuovo fornitore di posizione. Ciò consente all\'applicazione di ignorare la posizione e/o lo stato restituito da altre fonti di localizzazione, come il GPS o fornitori di posizione."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"posizione precisa (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Accedi a fonti di localizzazione precise, come il Global Positioning System sul tablet. Quando i servizi di localizzazione sono disponibili e attivi, questa autorizzazione consente all\'applicazione di determinare la tua posizione precisa."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Accedi a fonti di localizzazione precise, come il Global Positioning System sul telefono. Quando i servizi di localizzazione sono disponibili e attivi, questa autorizzazione consente all\'applicazione di determinare la tua posizione precisa."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"posizione approssimativa (basata sulla rete)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Accedi alla posizione approssimativa offerta da fornitori di posizione che utilizzano fonti di rete come antenne di telefonia mobile e Wi-Fi. Quando questi servizi di localizzazione sono disponibili e attivi, questa autorizzazione consente all\'applicazione di determinare la tua posizione approssimativa."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"posizione precisa (GPS e basata sulla rete)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Consente all\'applicazione di ottenere la tua posizione esatta utilizzando il sistema GPS (Global Positioning System) o fonti di localizzazione delle reti come ripetitori di telefonia mobile e Wi-Fi. Questi servizi di localizzazione devono essere attivi e disponibili sul dispositivo per poter essere utilizzati dall\'applicazione. Le applicazioni potrebbero utilizzare questa autorizzazione per stabilire la tua posizione e potrebbero consumare ulteriore batteria."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"posizione approssimativa (basata sulla rete)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Consente all\'applicazione di ottenere la tua posizione approssimativa. Questa posizione viene ottenuta da servizi di localizzazione utilizzando fonti di localizzazione delle reti come ripetitori di telefonia mobile e Wi-Fi. Questi servizi di localizzazione devono essere attivi e disponibili sul dispositivo per poter essere utilizzati dall\'applicazione. Le applicazioni potrebbero utilizzare questa autorizzazione per stabilire la tua posizione approssimativa."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"accesso a SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Consente all\'applicazione l\'utilizzo di funzioni di basso livello SurfaceFlinger."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"lettura buffer di frame"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Consente all\'applicazione di leggere i contenuti del buffer di frame."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"configurazione di schermi Wi-Fi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Consente all\'applicazione di configurare schermi Wi-Fi e di collegarsi a essi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controllo di schermi Wi-Fi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Consente all\'applicazione di controllare le funzioni di basso livello di schermi Wi-Fi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modifica impostazioni audio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Consente all\'applicazione di modificare le impostazioni audio globali, come il volume e quale altoparlante viene utilizzato per l\'uscita."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"registrazione audio"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"accesso alle impostazioni Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Consente all\'applicazione di configurare il tablet Bluetooth locale e di rilevare ed effettuare l\'accoppiamento con dispositivi remoti."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Consente all\'applicazione di configurare il telefono Bluetooth locale e di rilevare ed effettuare l\'accoppiamento con dispositivi remoti."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Visualizzazione connessioni WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"connessione e disconnessione da WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Consente all\'applicazione di determinare se WiMAX è abilitato e informazioni su eventuali reti WiMAX che sono connesse."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Modifica stato WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Consente all\'applicazione di connettere/disconnettere il tablet dalle reti WiMAX."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Consente all\'applicazione di modificare i feed attualmente sincronizzati. Le applicazioni dannose potrebbero modificare i tuoi feed sincronizzati."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"lettura termini aggiunti al dizionario"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Consente all\'applicazione di leggere tutte le parole, le frasi e i nomi che l\'utente potrebbe aver memorizzato nel dizionario utente."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"scrittura nel dizionario definito dall\'utente"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"aggiunta di parole al dizionario definito dall\'utente"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Consente all\'applicazione di scrivere nuove parole nel dizionario utente."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"test dell\'accesso all\'archivio protetto"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"test dell\'accesso all\'archivio protetto"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Consente all\'applicazione di testare un\'autorizzazione relativa all\'archivio USB che sarà disponibile su dispositivi futuri."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Consente all\'applicazione di testare un\'autorizzazione relativa all\'archivio USB che sarà disponibile su dispositivi futuri."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Consente all\'applicazione di testare un\'autorizzazione relativa alla scheda SD che sarà disponibile su dispositivi futuri."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"mod./elimin. cont. archivio USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modifica o eliminazione dei contenuti della scheda SD"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Consente all\'applicazione di scrivere sulla scheda SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"modifica/eliminaz. contenuti archivio media int."</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Consente all\'applicazione di modificare i contenuti dell\'archivio media interno."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"accesso memoria esterna utenti"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Consente all\'applicazione di accedere alla memoria esterna di tutti gli utenti."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"accesso al filesystem nella cache"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Consente all\'applicazione di leggere e scrivere il filesystem nella cache."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"effettuazione/ricezione chiamate Internet"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Richiede la crittografia dei dati applicazione memorizzati."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Disattiva fotocamere"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Impedisci l\'utilizzo di tutte le fotocamere del dispositivo."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Disattiva le funzioni con il blocco tastiera"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Impedisce l\'utilizzo di alcune funzioni con il blocco tastiera."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Cellulare"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Riprova"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Numero massimo di tentativi di Sblocco col sorriso superato"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"In carica (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Carico."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Carica"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Collegare il caricabatterie."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nessuna SIM presente."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Nessuna scheda SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nessuna scheda SIM presente nel tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Nessuna SIM presente nel telefono."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Inserisci una scheda SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Sequenza cancellata"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Cella aggiunta"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Sequenza completata"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Aggiungi widget."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Vuoto"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Area di sblocco estesa."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Area di sblocco compressa."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> widget."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Selettore utente"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Stato"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Fotocamera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Controlli media"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Riordino dei widget iniziato."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Riordino dei widget terminato."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> eliminato."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Espandi area di sblocco."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Sblocco con scorrimento."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Sblocco con sequenza."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Sblocco col sorriso."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Sblocco con PIN."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Sblocco con password."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Area sequenza."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Area di scorrimento."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copia URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Seleziona testo"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selezione testo"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"aggiungi al dizionario"</string>
-    <string name="deleteText" msgid="7070985395199629156">"elimina"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Aggiungi al dizionario"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Elimina"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metodo inserimento"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Azioni testo"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Spazio di archiviazione in esaurimento"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Reti Wi-Fi aperte disponibili"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Accedi a rete Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Accedi alla rete"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Impossibile connettersi alla rete Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ha una connessione Internet debole."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"A:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Inserisci il PIN richiesto:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Il telefono verrà momentaneamente scollegato dalla rete Wi-Fi durante il collegamento a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="select_character" msgid="3365550120617701745">"Inserisci carattere"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Invio SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sta inviando molti SMS. Vuoi consentire all\'applicazione di continuare a inviare messaggi?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Consenti"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Nega"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vorrebbe inviare un messaggio a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457"><font fgcolor="#ffffb060">"Potrebbero essere effettuati addebiti"</font>" sul tuo account per cellulari."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Verranno effettuati addebiti sul tuo account per cellulari."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Invia"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Annulla"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Memorizza la mia scelta"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Modifica: Impostazioni &gt; Applicazioni"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Consenti sempre"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Non consentire mai"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Scheda SIM rimossa"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"La rete mobile non sarà disponibile finché non eseguirai il riavvio con una scheda SIM valida inserita."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Fine"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Imposta data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Imposta"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Fine"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Predefinito"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Nessuna autorizzazione richiesta"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Nascondi"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostra tutto"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NUOVA: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NUOVA: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Fornito da <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Nessuna autorizzazione richiesta"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"potrebbe comportare dei costi"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Archivio di massa USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB collegata"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Ti sei collegato al computer tramite USB. Tocca il pulsante in basso se desideri copiare file tra il computer e l\'archivio USB di Android."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN attivata da <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tocca per gestire la rete."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Collegata a <xliff:g id="SESSION">%s</xliff:g>. Tocca per gestire la rete."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Connessione a VPN sempre attiva…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sempre attiva connessa"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Errore VPN sempre attiva"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Tocca per ripristinare la connessione"</string>
     <string name="upload_file" msgid="2897957172366730416">"Scegli file"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nessun file è stato scelto"</string>
     <string name="reset" msgid="2448168080964209908">"Reimposta"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Condividi"</string>
     <string name="find" msgid="4808270900322985960">"Trova"</string>
     <string name="websearch" msgid="4337157977400211589">"Ricerca Web"</string>
+    <string name="find_next" msgid="5742124618942193978">"Trova successivo"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Trova precedente"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Richiesta posizione da <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Richiesta posizione"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Richiesto da <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefono"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Cuffie audio"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altoparlanti dock"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Audio HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fine"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Uscita media"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Ricerca in corso..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Connessione..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Disponibile"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Non disponibili"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Schermo incorporato"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Schermo HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay n. <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Il display wireless è connesso"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Questa schermata è mostrata su un altro dispositivo"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Disconnetti"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Chiamata di emergenza"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Sequenza dimenticata"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Sequenza sbagliata"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Password sbagliata"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN errato"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Riprova fra <xliff:g id="NUMBER">%d</xliff:g> secondi."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Inserisci la sequenza"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Inserisci il PIN della SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Inserisci PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Inserisci la password"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"La scheda SIM è disattivata. Inserisci il codice PUK per continuare. Contatta l\'operatore per avere informazioni dettagliate."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Inserisci il codice PIN desiderato"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Conferma il codice PIN desiderato"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Sblocco scheda SIM..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Codice PIN errato."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Il PIN deve essere di 4-8 numeri."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Il codice PUK dovrebbe avere almeno otto numeri."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Inserisci di nuovo il codice PUK corretto. Ripetuti tentativi comportano la disattivazione definitiva della scheda SIM."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"I codici PIN non corrispondono"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Troppi tentativi di inserimento della sequenza"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Per sbloccare, accedi con il tuo account Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Nome utente (email)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Password"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Accedi"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Nome utente o password non validi."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Hai dimenticato il nome utente o la password?"\n"Visita "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Controllo account…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Hai digitato il tuo PIN <xliff:g id="NUMBER_0">%d</xliff:g> volte in modo errato. "\n\n"Riprova tra <xliff:g id="NUMBER_1">%d</xliff:g> secondi."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Hai digitato la tua password <xliff:g id="NUMBER_0">%d</xliff:g> volte in modo errato. "\n\n"Riprova tra <xliff:g id="NUMBER_1">%d</xliff:g> secondi."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"<xliff:g id="NUMBER_0">%d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. "\n\n"Riprova tra <xliff:g id="NUMBER_1">%d</xliff:g> secondi."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"<xliff:g id="NUMBER_0">%d</xliff:g> tentativi errati di sblocco del tablet. Dopo altri <xliff:g id="NUMBER_1">%d</xliff:g> tentativi falliti, il tablet verrà sottoposto a un ripristino dei dati di fabbrica e tutti i dati utente andranno persi."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"<xliff:g id="NUMBER_0">%d</xliff:g> tentativi errati di sblocco del telefono. Dopo altri <xliff:g id="NUMBER_1">%d</xliff:g> tentativi falliti, il telefono verrà sottoposto a un ripristino dei dati di fabbrica e tutti i dati utente andranno persi."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"<xliff:g id="NUMBER">%d</xliff:g> tentativi errati di sblocco del tablet. Il tablet verrà sottoposto a un ripristino dei dati di fabbrica."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"<xliff:g id="NUMBER">%d</xliff:g> tentativi errati di sblocco del telefono. Il telefono verrà sottoposto a un ripristino dei dati di fabbrica."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"<xliff:g id="NUMBER_0">%d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. Dopo altri <xliff:g id="NUMBER_1">%d</xliff:g> tentativi falliti, ti verrà chiesto di sbloccare il tablet con un account email."\n\n" Riprova tra <xliff:g id="NUMBER_2">%d</xliff:g> secondi."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"<xliff:g id="NUMBER_0">%d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. Dopo altri <xliff:g id="NUMBER_1">%d</xliff:g> tentativi falliti, ti verrà chiesto di sbloccare il telefono con un account email."\n\n" Riprova tra <xliff:g id="NUMBER_2">%d</xliff:g> secondi."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Rimuovi"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Aumentare il volume oltre il livello di sicurezza?"\n"Ascoltare musica ad alto volume per lunghi periodi potrebbe danneggiare l\'udito."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Continua a tenere premuto con due dita per attivare l\'accessibilità."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Accessibilità attivata."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Accessibilità annullata."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Utente corrente <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Proprietario"</string>
 </resources>
diff --git a/core/res/res/values-iw/donottranslate-cldr.xml b/core/res/res/values-iw/donottranslate-cldr.xml
index 02d1e9c..631c059 100644
--- a/core/res/res/values-iw/donottranslate-cldr.xml
+++ b/core/res/res/values-iw/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">ינואר</string>
-    <string name="month_long_standalone_february">פברואר</string>
-    <string name="month_long_standalone_march">מרס</string>
-    <string name="month_long_standalone_april">אפריל</string>
-    <string name="month_long_standalone_may">מאי</string>
-    <string name="month_long_standalone_june">יוני</string>
-    <string name="month_long_standalone_july">יולי</string>
-    <string name="month_long_standalone_august">אוגוסט</string>
-    <string name="month_long_standalone_september">ספטמבר</string>
-    <string name="month_long_standalone_october">אוקטובר</string>
-    <string name="month_long_standalone_november">נובמבר</string>
-    <string name="month_long_standalone_december">דצמבר</string>
-
-    <string name="month_long_january">ינואר</string>
-    <string name="month_long_february">פברואר</string>
-    <string name="month_long_march">מרס</string>
-    <string name="month_long_april">אפריל</string>
-    <string name="month_long_may">מאי</string>
-    <string name="month_long_june">יוני</string>
-    <string name="month_long_july">יולי</string>
-    <string name="month_long_august">אוגוסט</string>
-    <string name="month_long_september">ספטמבר</string>
-    <string name="month_long_october">אוקטובר</string>
-    <string name="month_long_november">נובמבר</string>
-    <string name="month_long_december">דצמבר</string>
-
-    <string name="month_medium_january">ינו</string>
-    <string name="month_medium_february">פבר</string>
-    <string name="month_medium_march">מרס</string>
-    <string name="month_medium_april">אפר</string>
-    <string name="month_medium_may">מאי</string>
-    <string name="month_medium_june">יונ</string>
-    <string name="month_medium_july">יול</string>
-    <string name="month_medium_august">אוג</string>
-    <string name="month_medium_september">ספט</string>
-    <string name="month_medium_october">אוק</string>
-    <string name="month_medium_november">נוב</string>
-    <string name="month_medium_december">דצמ</string>
-
-    <string name="month_shortest_january">1</string>
-    <string name="month_shortest_february">2</string>
-    <string name="month_shortest_march">3</string>
-    <string name="month_shortest_april">4</string>
-    <string name="month_shortest_may">5</string>
-    <string name="month_shortest_june">6</string>
-    <string name="month_shortest_july">7</string>
-    <string name="month_shortest_august">8</string>
-    <string name="month_shortest_september">9</string>
-    <string name="month_shortest_october">10</string>
-    <string name="month_shortest_november">11</string>
-    <string name="month_shortest_december">12</string>
-
-    <string name="day_of_week_long_sunday">יום ראשון</string>
-    <string name="day_of_week_long_monday">יום שני</string>
-    <string name="day_of_week_long_tuesday">יום שלישי</string>
-    <string name="day_of_week_long_wednesday">יום רביעי</string>
-    <string name="day_of_week_long_thursday">יום חמישי</string>
-    <string name="day_of_week_long_friday">יום שישי</string>
-    <string name="day_of_week_long_saturday">יום שבת</string>
-
-    <string name="day_of_week_medium_sunday">יום א\'</string>
-    <string name="day_of_week_medium_monday">יום ב\'</string>
-    <string name="day_of_week_medium_tuesday">יום ג\'</string>
-    <string name="day_of_week_medium_wednesday">יום ד\'</string>
-    <string name="day_of_week_medium_thursday">יום ה\'</string>
-    <string name="day_of_week_medium_friday">יום ו\'</string>
-    <string name="day_of_week_medium_saturday">שבת</string>
-
-    <string name="day_of_week_short_sunday">יום א\'</string>
-    <string name="day_of_week_short_monday">יום ב\'</string>
-    <string name="day_of_week_short_tuesday">יום ג\'</string>
-    <string name="day_of_week_short_wednesday">יום ד\'</string>
-    <string name="day_of_week_short_thursday">יום ה\'</string>
-    <string name="day_of_week_short_friday">יום ו\'</string>
-    <string name="day_of_week_short_saturday">שבת</string>
-
-    <string name="day_of_week_shortest_sunday">א</string>
-    <string name="day_of_week_shortest_monday">ב</string>
-    <string name="day_of_week_shortest_tuesday">ג</string>
-    <string name="day_of_week_shortest_wednesday">ד</string>
-    <string name="day_of_week_shortest_thursday">ה</string>
-    <string name="day_of_week_shortest_friday">ו</string>
-    <string name="day_of_week_shortest_saturday">ש</string>
-
-    <string name="am">לפנה"צ</string>
-    <string name="pm">אחה"צ</string>
-    <string name="yesterday">אתמול</string>
-    <string name="today">היום</string>
-    <string name="tomorrow">מחר</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 416aa4e..bb6a3ac 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"אפשרויות טלפון"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"נעילת מסך"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"כיבוי"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"דיווח על באג"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"מלא דיווח על באג"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"פעולה זו תאסוף מידע על מצב המכשיר הנוכחי שלך על מנת לשלוח אותו כהודעת דוא\"ל. היא תימשך זמן קצר מרגע פתיחת דיווח הבאג ועד שיהיה ניתן לבצע שליחה. התאזר בסבלנות."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"מצב שקט"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"הקול כבוי"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"קול מופעל"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"ההודעות שלך"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"קריאה וכתיבה בהודעות ה-SMS, הדוא\"ל והודעות אחרות שלך."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"המידע האישי שלך"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"גישה ישירה לאנשי הקשר וללוח השנה המאוחסנים בטבלט."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"גישה ישירה לאנשי הקשר וללוח השנה המאוחסנים בטלפון."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"גישה ישירה למידע עליך, המאוחסן בכרטיס איש הקשר שלך."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"מידע על הקשרים החברתיים שלך"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"גישה ישירה למידע על אנשי קשר וקשרים חברתיים שלך."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"המיקום שלך"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"עקוב אחר המיקום הפיזי שלך."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"תקשורת רשת"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"הרשאת גישה לתכונות רשת שונות."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"גישה למכשירים ולרשתות באמצעות Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"הגדרות אודיו"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"שינוי הגדרות האודיו."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"השפעה על הסוללה"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"שימוש בתכונות שיכולות לרוקן את הסוללה במהירות."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"לוח שנה"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"גישה ישירה ללוח השנה ולאירועים."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"קריאת מילון משתמש"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"קריאת מילים במילון משתמש."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"כתיבת מילון משתמש"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"הוספת מילים למילון משתמש."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"סימניות והיסטוריה"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"גישה ישירה אל סימניות והיסטוריית דפדפן."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"שעון מעורר"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"הגדרת השעון המעורר."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"דואר קולי"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"גישה ישירה לדואר הקולי."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"מיקרופון"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"גישה ישירה אל המיקרופון להקלטת אודיו."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"מצלמה"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"גישה ישירה למצלמה לצילום תמונות או וידאו."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"מידע על היישומים שלך"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"יכולת להשפיע על התנהגותם של יישומים אחרים במכשיר."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"טפט"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"שינוי הגדרות הטפט של המכשיר."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"שעון"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"שינוי השעה או אזור הזמן של המכשיר."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"שורת המצב"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"שינוי הגדרות שורת המצב של המכשיר."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"הגדרות סנכרון"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"גישה להגדרות הסנכרון."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"החשבונות שלך"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"גישה לכל החשבונות הזמינים."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"בקרת חומרה"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"גישה ושליטה במערכת ברמה נמוכה."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"כלי פיתוח"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"תכונות הדרושות למפתחי יישומים בלבד."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"ממשק המשתמש של יישום אחר"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"השפעה על ממשק המשתמש של יישומים אחרים."</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>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"מאפשר ליישום לקבל ולעבד הודעות WAP. אישור זה כולל את היכולת לעקוב אחר הודעות שנשלחו אליך ולמחוק אותן מבלי להציג לך אותן."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"אחזור יישומים פעילים"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"מאפשר ליישום לאחזר מידע לגבי משימות הפועלות כרגע ושפעלו לאחרונה. ייתכן שהדבר יתיר ליישום לגלות מידע לגבי היישומים שבהם נעשה שימוש במכשיר."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"אינטראקציה בין משתמשים"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"מאפשר ליישום לבצע פעולות בין משתמשים שונים במכשיר. יישומים זדוניים עשויים להשתמש ביכולת זו כדי לפרוץ את ההגנה בין משתמשים."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"רישיון מלא לבצע אינטראקציה בין משתמשים"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"מאפשר את כל האינטראקציות האפשריות בין משתמשים."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"נהל משתמשים"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"מאפשר ליישומים לנהל משתמשים במכשיר, כולל שאילתה, יצירה ומחיקה."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"אחזור פרטי יישומים פועלים"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"מאפשר ליישום לאחזר מידע מפורט על המשימות הנוכחיות הפועלות ועל משימות שפעלו לאחרונה. יישומים זדוניים עלולים לגלות מידע אישי על יישומים אחרים."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"סידור מחדש של יישומים פעילים"</string>
@@ -243,6 +287,14 @@
     <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="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"הפעלת נגישות זמנית"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"מאפשר ליישום להפעיל באופן זמני נגישות במכשיר. יישומים זדוניים עלולים לאפשר נגישות ללא הסכמת משתמש."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"אחזר מידע חלון"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"מאפשר ליישום לאחזר מידע לגבי החלונות ממנהל החלונות. יישומים זדוניים עשויים לאחזר מידע המיועד לשימוש מערכת פנימי."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"סנן אירועים"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"מאפשר ליישום לרשום מסנן קלט שמסנן את הזרם של כל אירועי המשתמש לפני שהם נשלחים. יישום זדוני עשוי לשלוט ב-UI של המערכת ללא התערבות משתמש."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"הגדלת תצוגה"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"מאפשר ליישום להגדיל את התוכן של תצוגה. יישומים זדוניים עלולים לשנות את תוכן התצוגה כך שהמכשיר יהפוך לבלתי שמיש."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"כיבוי חלקי"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"מעביר את מנהל הפעילויות למצב כיבוי. לא מבצע כיבוי מלא."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"מנע החלפת יישומים"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"מאפשר ליישום לשלוט על המספר המרבי של תהליכים שיפעלו. הרשאה זו לעולם אינה נחוצה ליישומים רגילים."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"אילוץ סגירה של יישומים ברקע"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"מאפשר ליישום לקבוע אם פעילויות תמיד מסתיימות עם העברתן לרקע. הרשאה זו לעולם אינה נחוצה ליישומים רגילים."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"שנה את הנתונים הסטטיסטיים של הסוללה"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"מאפשר ליישום לשנות נתונים סטטיסטיים שנאספו לגבי הסוללה. לא מיועד לשימוש על ידי יישומים רגילים."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"קריאת הנתונים הסטטיסטיים של הסוללה"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"מאפשר ליישום לקרוא את נתוני השימוש הנוכחיים של הסוללה ברמה נמוכה. עשוי לאפשר ליישום לגלות מידע מפורט לגבי היישומים שבהם אתה משתמש."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"שינוי הנתונים הסטטיסטיים של הסוללה"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"מאפשר ליישום לשנות נתונים סטטיסטיים שנאספו לגבי הסוללה. לא מיועד לשימוש על ידי יישומים רגילים."</string>
     <string name="permlab_backup" msgid="470013022865453920">"שלוט בגיבוי ובשחזור של המערכת"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"מאפשר ליישום לשלוט במנגנון הגיבוי והשחזור של המערכת. לא מיועד לשימוש על ידי יישומים רגילים."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"אשר פעולה של גיבוי או שחזור מלא"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"הצג חלונות ללא הרשאה"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"הרשאה זו מאפשרת ליישום ליצור חלונות המיועדים לשימוש על ידי ממשק המשתמש של המערכת הפנימית. לא מיועד לשימוש ביישומים רגילים."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"ציור על יישומים אחרים"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"מאפשר ליישום להציג חלונות התראה של המערכת. חלונות התראה מסוימים עשויים להשתלט על המסך כולו."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"מאפשר ליישום לצייר על יישומים אחרים או על חלקים מממשק המשתמש. הדבר עשוי להפריע לך להשתמש בממשק של יישומים, או לשנות את מה שאתה חושב שאתה רואה ביישומים אחרים."</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="permlab_freezeScreen" msgid="4708181184441880175">"הקפאת מסך"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"מאפשר ליישום להקפיא באופן זמני את המסך למעבר למסך מלא."</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>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"התקנה ישירה של יישומים"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"מאפשר ליישום להתקין חבילות Android חדשות או מעודכנות. יישומים זדוניים עלולים להשתמש בכך כדי להוסיף יישומים חדשים בעלי הרשאות זה כדי להוסיף יישומים חדשים עם הרשאות רבות-עוצמה אקראיות."</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="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"מאפשר ליישום לשחרר שטח אחסון בטאבלט על ידי מחיקת קבצים בספריות הקבצים השמורים של יישומים אחרים. הדבר עשוי לגרום להפעלה של יישומים אחרים להיות איטית יותר מכיוון שעליהם לאחזר מחדש את הנתונים."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"מאפשר ליישום לפנות שטח אחסון בטלפון על ידי מחיקת קבצים בספריות הקבצים השמורים של יישומים אחרים. הדבר עשוי לגרום להפעלה של יישומים אחרים להיות איטית יותר מכיוון שעליהם לאחזר מחדש את הנתונים."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"העברה של משאבי יישומים"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"מאפשר ליישום להעביר משאבי יישומים ממדיה פנימית לחיצונית, ולהפך."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"קרא נתונים רגישים של יומן רישום"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"מאפשר ליישום לגשת לפקודות נוספות של ספק שירות המיקום. אישור זה עשוי לאפשר ליישום לשבש את פעולת ה-GPS או מקורות מיקום אחרים."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"הרשאה להתקין ספק מיקום"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"צור מקורות מיקום מדומים לבדיקה, או התקן ספק מיקום חדש. פעולה זו מאפשרת ליישום לעקוף את המיקום ו/או הסטטוס המוחזרים על ידי מקורות מיקום אחרים כמו GPS או ספקי מיקום."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"מיקום מדויק (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"גש למקורות מיקום מדויק כמו GPS בטאבלט. כאשר שירותי מיקום זמינים ומופעלים, אישור זה מאפשר ליישום לקבוע את המיקום המדויק שלך."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"גש למקורות מיקום מדויק כמו GPS בטלפון. כאשר שירותי מיקום זמינים ומופעלים, אישור זה מאפשר ליישום לקבוע את המיקום המדויק שלך."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"מיקום משוער (מבוסס רשת)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"גש למיקום המשוער מספקי מיקום באמצעות מקורות רשת כמו אנטנות סלולריות ו-Wi-Fi. כאשר שירותי מיקום אלה זמינים ומופעלים, אישור זה מאפשר ליישום לקבוע את המיקום המשוער שלך."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"מיקום מדויק (מבוסס GPS ורשת)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"מאפשר ליישום לקבל את המיקום המדויק שלך באמצעות מערכת המיקום הגלובלית (GPS) או מקורות מיקום ברשת כגון אנטנות סלולריות ו-Wi-Fi. שירותי מיקום אלה חייבים להיות מופעלים ונגישים למכשיר שלך כדי שהיישום ישתמש בהם. ייתכן שיישומים יעשו בכך שימוש כדי לקבוע היכן אתה נמצא ולגרום לצריכת סוללה מוגברת."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"מיקום משוער (מבוסס רשת)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"מאפשר ליישום לקבל את מיקומך המשוער. מיקום זה נגזר על-פי שירותי מיקום העושים שימוש במקורות מיקום ברשת, כגון אנטנות סלולריות ו-Wi-Fi. שירותי מיקום אלה חייבים להיות מופעלים ונגישים למכשיר שלך כדי שהיישום ישתמש בהם. ייתכן שיישומים יעשו בכך שימוש כדי לקבוע את מיקומך המשוער."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"גישה ל-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="permlab_configureWifiDisplay" msgid="5595661694746742168">"הגדר תצוגות Wifi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"מאפשר ליישום להגדיר ולהתחבר לתצוגות Wifi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"שלוט בתצוגות Wifi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"מאפשר ליישום לשלוט בתכונות ברמה נמוכה של תצוגות Wifi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"שנה את הגדרות האודיו שלך"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"מאפשר ליישום לשנות הגדרות אודיו גלובליות כמו עוצמת קול ובחירת הרמקול המשמש לפלט."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"הקלט אודיו"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"גישה להגדרות Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"מאפשר ליישום להגדיר את תצורתו של הטבלט המקומי מסוג Bluetooth וכן לגלות מכשירים מרוחקים ולבצע התאמה איתם."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"מאפשר ליישום להגדיר את תצורתו של הטלפון המקומי מסוג Bluetooth וכן לגלות מכשירים מרוחקים ולבצע התאמה איתם."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"הצג חיבורי WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"התחברות והתנתקות מ-WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"מאפשר ליישום לדעת האם WiNMAX מופעל, כמו גם לקבל מידע האם רשתות WiNMAX כלשהן מחוברות."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"שנה את מצב WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"מאפשר ליישום לחבר את הטאבלט לרשתות WiMAX ולהתנתק מהן."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"מאפשר ליישום לשנות את ההזנות הנוכחיות שלך שמסונכרנות. יישומים זדוניים עלולים לשמות את ההזנות המסונכרנות שלך."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"קריאת מונחים שהוספת למילון"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"מאפשר ליישום לקרוא את כל המילים, השמות והביטויים שהמשתמש אחסן במילון המשתמש."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"כתיבה למילון בהגדרת המשתמש"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"הוספת מילים למילון מוגדר-משתמש"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"מאפשר ליישום לכתוב מילים חדשות במילון המשתמש."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"בדיקת גישה לאחסון מוגן"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"בדיקת גישה לאחסון מוגן"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"מאפשר ליישום לבדוק אישור לאחסון USB שיהיה זמין במכשירים עתידיים."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"מאפשר ליישום לבדוק אישור לאחסון USB שיהיה זמין במכשירים עתידיים."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"מאפשר ליישום לבדוק אישור לכרטיס SD שיהיה זמין במכשירים עתידיים."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"שינוי או מחיקה של תוכן אחסון ה-USB שלך"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"שינוי או מחיקה של תוכן כרטיס ה-SD שלך"</string>
@@ -534,6 +593,8 @@
     <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="permlab_sdcardAccessAll" msgid="8150613823900460576">"גישה לאחסון חיצוני, כל המשתמשים"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"מאפשר ליישום לגשת לאחסון חיצוני עבור כל המשתמשים."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"גישה למערכת הקבצים בקובץ השמור"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"מאפשר ליישום לקרוא ולכתוב במערכת הקבצים של הקבצים השמורים."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"בצע/קבל שיחות אינטרנט"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"דרוש שנתוני יישומים מאוחסנים יהיו מוצפנים."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"השבת מצלמות"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"מנע שימוש בכל המצלמות שבמכשיר."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"השבת תכונות ב-Keyguard"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"מנע שימוש בתכונות מסוימות ב-Keyguard."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"בית"</item>
     <item msgid="869923650527136615">"נייד"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"נסה שוב"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"חרגת ממספר הניסיונות המרבי של זיהוי פרצוף"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"טוען (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"נטען."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"טעון"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"חבר את המטען."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"אין כרטיס SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"אין כרטיס SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"אין כרטיס SIM בטבלט."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"אין כרטיס SIM בטלפון."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"הכנס כרטיס SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"התבנית נמחקה"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"התא נוסף"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"התבנית הושלמה"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"הוסף Widget."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"ריק"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"אזור ביטול הנעילה הורחב."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"אזור ביטול הנעילה כווץ."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Widget ‏<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"בוחר משתמשים"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"סטטוס"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"מצלמה"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"פקדי מדיה"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"סידור מחדש של Widgets התחיל."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"סידור מחדש של Widgets הסתיים."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widget ‏<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> נמחק."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"הרחב את אזור ביטול הנעילה."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"ביטול נעילה באמצעות הסטה."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ביטול נעילה באמצעות ציור קו."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"ביטול נעילה באמצעות זיהוי פרצוף."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"ביטול נעילה באמצעות מספר PIN."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ביטול נעילה באמצעות סיסמה."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"אזור ציור קו."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"אזור הסטה."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"אבג"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"העתק כתובת אתר"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"בחר טקסט"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"בחירת טקסט"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"הוסף למילון"</string>
-    <string name="deleteText" msgid="7070985395199629156">"מחק"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"הוסף למילון"</string>
+    <string name="deleteText" msgid="6979668428458199034">"מחק"</string>
     <string name="inputMethod" msgid="1653630062304567879">"שיטת קלט"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"פעולות טקסט"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"שטח האחסון אוזל"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"רשתות Wi-Fi פתוחות זמינות"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"כניסה לרשת Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"היכנס לרשת"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"אין אפשרות להתחבר ל-Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" אינו מחובר היטב לאינטרנט."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"אל:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"הקלד את קוד ה-PIN הנדרש."</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"הטלפון יתנתק מרשת ה-Wi-Fi באופן זמני בשעה שהוא מחובר אל <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"הוסף תו"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"שולח הודעות SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt; <xliff:g id="APP_NAME">%1$s</xliff:g> &lt;/ b&gt; שולח מספר רב של הודעות SMS. האם ברצונך לאפשר ליישום זה להמשיך לשלוח הודעות?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"אפשר"</string>
     <string name="sms_control_no" msgid="625438561395534982">"דחה"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; רוצה לשלוח הודעה אל &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"הפעולה "<font fgcolor="#ffffb060">"עשויה לגרום לחיובים"</font>" בחשבון המכשיר הנייד שלך."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"הפעולה תגרום לחיובים בחשבון המכשיר הנייד שלך."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"שלח"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"בטל"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"זכור את הבחירה שלי"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"ניתן לשנות זאת מאוחר יותר ב\'הגדרות\' &gt; \'יישומים\'"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"אפשר תמיד"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"לעולם אל תאפשר"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"כרטיס ה-SIM הוסר"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"הרשת הסלולרית לא תהיה זמינה עד שתפעיל מחדש לאחר הכנסת כרטיס SIM חוקי."</string>
     <string name="sim_done_button" msgid="827949989369963775">"סיום"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"הגדר תאריך"</string>
     <string name="date_time_set" msgid="5777075614321087758">"הגדר"</string>
     <string name="date_time_done" msgid="2507683751759308828">"בוצע"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"ברירת מחדל"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"לא דרושים אישורים"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"הסתר"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"הצג הכל"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"חדש: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"חדש: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"מטעם <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"לא דרושים אישורים"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"פעולה זו עשויה לחייב אותך בכסף:"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"אמצעי מסוג USB לאחסון בנפח גדול"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB מחובר"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"התחברת למחשב באמצעות USB. גע בלחצן שבהמשך אם ברצונך להעתיק קבצים בין המחשב לאחסון ה-USB של מכשיר ה-Android שלך."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN מופעל על ידי <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"גע כדי לנהל את הרשת."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"מחובר אל <xliff:g id="SESSION">%s</xliff:g>. גע כדי לנהל את הרשת."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ה-VPN שמופעל תמיד, מתחבר..."</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"ה-VPN שפועל תמיד, מחובר"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"שגיאת VPN שמופעל תמיד"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"גע כדי לאפס את החיבור"</string>
     <string name="upload_file" msgid="2897957172366730416">"בחר קובץ"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"לא נבחר קובץ"</string>
     <string name="reset" msgid="2448168080964209908">"איפוס"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"שתף"</string>
     <string name="find" msgid="4808270900322985960">"מצא"</string>
     <string name="websearch" msgid="4337157977400211589">"חיפוש באינטרנט"</string>
+    <string name="find_next" msgid="5742124618942193978">"חפש את הבא"</string>
+    <string name="find_previous" msgid="2196723669388360506">"חפש את הקודם"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"בקשת מיקום מאת <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"בקשת מיקום"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"מבוקש על ידי <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"טלפון"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"אוזניות"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"רמקולים של מעגן"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"אודיו HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"מערכת"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"אודיו Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"סיום"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"פלט מדיה"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"סורק..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"מתחבר..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"זמין"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"לא זמין"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"מסך מובנה"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"מסך HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"שכבת על #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: ‎<xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>‎, ‏<xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"מסך אלחוטי מחובר"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"מסך זה מוצג במכשיר אחר"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"נתק"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"שיחת חירום"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"שכחת את הקו"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"קו ביטול נעילה שגוי"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"סיסמה שגויה"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"מספר PIN שגוי"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"נסה שוב בעוד <xliff:g id="NUMBER">%d</xliff:g> שניות."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"שרטט את קו ביטול הנעילה"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"הזן מספר PIN ל-SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"הזן מספר PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"הזן את הסיסמה"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"כרטיס ה-SIM מושבת כעת. הזן קוד PUK כדי להמשיך. פנה אל הספק לפרטים."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"הזן את קוד ה-PIN הרצוי"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"אשר את קוד ה-PIN הרצוי"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"מבטל נעילה של כרטיס SIM…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"קוד PIN שגוי."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"הקלד מספר PIN שאורכו 4 עד 8 ספרות."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"קוד PUK צריך להיות בן 8 ספרות או יותר."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"הזן מחדש את קוד PUK הנכון. ניסיונות חוזרים ישביתו לצמיתות את כרטיס ה-SIM."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"קודי ה-PIN אינם תואמים"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"ניסיונות רבים מדי לשרטוט קו ביטול נעילה."</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"כדי לבטל את הנעילה, היכנס באמצעות חשבון Google שלך."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"שם משתמש (דוא\"ל)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"סיסמה"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"היכנס"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"שם משתמש או סיסמה לא חוקיים."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"שכחת את שם המשתמש או הסיסמה?"\n"בקר בכתובת "<b>"google.com/accounts/recovery"</b></string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"בודק חשבון…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"הקלדת מספר PIN שגוי <xliff:g id="NUMBER_0">%d</xliff:g> פעמים. "\n\n"נסה שוב בעוד <xliff:g id="NUMBER_1">%d</xliff:g> שניות."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"הקלדת סיסמה שגויה <xliff:g id="NUMBER_0">%d</xliff:g> פעמים."\n\n"נסה שוב בעוד <xliff:g id="NUMBER_1">%d</xliff:g> שניות."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%d</xliff:g> פעמים. "\n\n"נסה שוב בעוד <xliff:g id="NUMBER_1">%d</xliff:g> שניות."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"ביצעת <xliff:g id="NUMBER_0">%d</xliff:g> ניסיונות שגויים לביטול נעילת הטלפון. לאחר <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות כושלים נוספים, הטאבלט יעבור איפוס לברירת המחדל של היצרן וכל נתוני המשתמש יאבדו."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"ביצעת <xliff:g id="NUMBER_0">%d</xliff:g> ניסיונות שגויים לביטול נעילת הטלפון. לאחר <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות כושלים נוספים, הטלפון יעבור איפוס לברירת המחדל של היצרן וכל נתוני המשתמש יאבדו."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"ביצעת <xliff:g id="NUMBER">%d</xliff:g> ניסיונות שגויים לביטול נעילת הטאבלט. הטאבלט יעבור כעת איפוס לברירת המחדל של היצרן."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"ביצעת <xliff:g id="NUMBER">%d</xliff:g> ניסיונות שגויים לביטול נעילת הטלפון. הטלפון יעבור כעת איפוס לברירת המחדל של היצרן."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטאבלט באמצעות חשבון דוא\"ל‏."\n\n"נסה שוב בעוד <xliff:g id="NUMBER_2">%d</xliff:g> שניות."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטלפון באמצעות חשבון דוא\"ל‏."\n\n"נסה שוב בעוד <xliff:g id="NUMBER_2">%d</xliff:g> שניות."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"הסר"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"האם להעלות את עוצמת הקול מעל לרמה הבטוחה?"\n"האזנה בעוצמת קול גבוהה למשך זמן ארוך עלולה לפגוע בשמיעה."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"המשך לגעת בשתי אצבעות כדי להפעיל נגישות."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"נגישות הופעלה."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"נגישות בוטלה."</string>
+    <string name="user_switched" msgid="3768006783166984410">"המשתמש הנוכחי <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"בעלים"</string>
 </resources>
diff --git a/core/res/res/values-ja/donottranslate-cldr.xml b/core/res/res/values-ja/donottranslate-cldr.xml
index 450adc3..1c1d55f 100644
--- a/core/res/res/values-ja/donottranslate-cldr.xml
+++ b/core/res/res/values-ja/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">1月</string>
-    <string name="month_long_standalone_february">2月</string>
-    <string name="month_long_standalone_march">3月</string>
-    <string name="month_long_standalone_april">4月</string>
-    <string name="month_long_standalone_may">5月</string>
-    <string name="month_long_standalone_june">6月</string>
-    <string name="month_long_standalone_july">7月</string>
-    <string name="month_long_standalone_august">8月</string>
-    <string name="month_long_standalone_september">9月</string>
-    <string name="month_long_standalone_october">10月</string>
-    <string name="month_long_standalone_november">11月</string>
-    <string name="month_long_standalone_december">12月</string>
-
-    <string name="month_long_january">1月</string>
-    <string name="month_long_february">2月</string>
-    <string name="month_long_march">3月</string>
-    <string name="month_long_april">4月</string>
-    <string name="month_long_may">5月</string>
-    <string name="month_long_june">6月</string>
-    <string name="month_long_july">7月</string>
-    <string name="month_long_august">8月</string>
-    <string name="month_long_september">9月</string>
-    <string name="month_long_october">10月</string>
-    <string name="month_long_november">11月</string>
-    <string name="month_long_december">12月</string>
-
-    <string name="month_medium_january">1月</string>
-    <string name="month_medium_february">2月</string>
-    <string name="month_medium_march">3月</string>
-    <string name="month_medium_april">4月</string>
-    <string name="month_medium_may">5月</string>
-    <string name="month_medium_june">6月</string>
-    <string name="month_medium_july">7月</string>
-    <string name="month_medium_august">8月</string>
-    <string name="month_medium_september">9月</string>
-    <string name="month_medium_october">10月</string>
-    <string name="month_medium_november">11月</string>
-    <string name="month_medium_december">12月</string>
-
-    <string name="month_shortest_january">1</string>
-    <string name="month_shortest_february">2</string>
-    <string name="month_shortest_march">3</string>
-    <string name="month_shortest_april">4</string>
-    <string name="month_shortest_may">5</string>
-    <string name="month_shortest_june">6</string>
-    <string name="month_shortest_july">7</string>
-    <string name="month_shortest_august">8</string>
-    <string name="month_shortest_september">9</string>
-    <string name="month_shortest_october">10</string>
-    <string name="month_shortest_november">11</string>
-    <string name="month_shortest_december">12</string>
-
-    <string name="day_of_week_long_sunday">日</string>
-    <string name="day_of_week_long_monday">月</string>
-    <string name="day_of_week_long_tuesday">火</string>
-    <string name="day_of_week_long_wednesday">水</string>
-    <string name="day_of_week_long_thursday">木</string>
-    <string name="day_of_week_long_friday">金</string>
-    <string name="day_of_week_long_saturday">土</string>
-
-    <string name="day_of_week_medium_sunday">日</string>
-    <string name="day_of_week_medium_monday">月</string>
-    <string name="day_of_week_medium_tuesday">火</string>
-    <string name="day_of_week_medium_wednesday">水</string>
-    <string name="day_of_week_medium_thursday">木</string>
-    <string name="day_of_week_medium_friday">金</string>
-    <string name="day_of_week_medium_saturday">土</string>
-
-    <string name="day_of_week_short_sunday">日</string>
-    <string name="day_of_week_short_monday">月</string>
-    <string name="day_of_week_short_tuesday">火</string>
-    <string name="day_of_week_short_wednesday">水</string>
-    <string name="day_of_week_short_thursday">木</string>
-    <string name="day_of_week_short_friday">金</string>
-    <string name="day_of_week_short_saturday">土</string>
-
-    <string name="day_of_week_shortest_sunday">日</string>
-    <string name="day_of_week_shortest_monday">月</string>
-    <string name="day_of_week_shortest_tuesday">火</string>
-    <string name="day_of_week_shortest_wednesday">水</string>
-    <string name="day_of_week_shortest_thursday">木</string>
-    <string name="day_of_week_shortest_friday">金</string>
-    <string name="day_of_week_shortest_saturday">土</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">昨日</string>
-    <string name="today">今日</string>
-    <string name="tomorrow">明日</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M%p</string>
     <string name="hour_minute_cap_ampm">%-l:%M%^p</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index af28156..8af0fed 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"携帯電話オプション"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"画面ロック"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"電源を切る"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"バグレポート"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"バグレポートを取得"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"現在の端末の状態に関する情報が収集され、その内容がメールで送信されます。バグレポートが開始してから送信可能な状態となるまでには多少の時間がかかりますのでご了承ください。"</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"マナーモード"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"サウンドOFF"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"サウンドON"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"送受信したメッセージ"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"SMS、メールなどのメッセージを読み書きします。"</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"個人情報"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"タブレットの連絡先とカレンダーに直接アクセス"</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"端末の連絡先とカレンダーに直接アクセス"</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"連絡先カードに保存されている個人情報に直接アクセスします。"</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"ソーシャル情報"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"連絡先とソーシャルコネクションに関する情報に直接アクセスします。"</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"現在地"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"現在地を追跡します。"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"ネットワーク通信"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"さまざまなネットワーク機能にアクセスします。"</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Bluetooth経由でデバイスやネットワークにアクセスします。"</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"音声設定"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"音声設定を変更します。"</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"電池への影響"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"短時間で電池を消費する機能を使用します。"</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"カレンダー"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"カレンダーと予定に直接アクセスします。"</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"単語リストの読み取り"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"単語リストから語句を読み取ります。"</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"単語リストへの書き込み"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"単語リストに語句を追加します。"</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"ブックマークと履歴"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"ブックマークとブラウザの履歴に直接アクセスします。"</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"アラーム"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"アラームを設定します。"</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"ボイスメール"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"ボイスメールに直接アクセスします。"</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"マイク"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"マイクに直接アクセスして音声を記録します。"</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"カメラ"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"カメラに直接アクセスして画像または動画を撮影します。"</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"アプリ情報"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"端末上の他のアプリの動作に影響を及ぼします。"</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"壁紙"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"端末の壁紙設定を変更します。"</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"時刻"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"端末の時刻またはタイムゾーンを変更します。"</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"ステータスバー"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"端末のステータスバー設定を変更します。"</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"同期設定"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"同期設定にアクセスします。"</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"アカウント"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"利用可能なアカウントにアクセスします。"</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"ハードウェアの制御"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"システムの低レベルのアクセスと制御"</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"開発ツール"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"アプリのデベロッパーにのみ必要な機能です。"</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"他のアプリのUI"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"他のアプリのUIに影響を及ぼします。"</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>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"WAPメッセージの受信と処理をアプリに許可します。これにより、アプリが端末に届いたメッセージを表示することなく監視または削除できるようになります。"</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"実行中のアプリの取得"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"現在実行中または最近実行したタスクに関する情報の取得をアプリに許可します。これにより、その端末でどのアプリを使用しているかをアプリから識別できるようになる可能性があります。"</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"ユーザー間の交流"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"端末上の各ユーザーに対して操作を実行することをアプリに許可します。この許可を悪意のあるアプリに利用されると、ユーザー間の保護が侵害される恐れがあります。"</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"ユーザー間で交流するための完全ライセンス"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"ユーザー間の交流をすべて許可します。"</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"ユーザーの管理"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"ユーザーの問い合わせ、作成、削除を含め、端末上のユーザーを管理することをアプリに許可します。"</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"実行中のアプリの詳細の取得"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"現在実行中のタスクまたは最近実行したタスクに関する情報の取得をアプリに許可します。この許可を悪意のあるアプリに利用されると、他のアプリに関する非公開情報が読み取られる恐れがあります。"</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"実行中のアプリの順序変更"</string>
@@ -243,6 +287,14 @@
     <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="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ユーザー補助を一時的に有効にする"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"この端末のユーザー補助を一時的に有効にすることをアプリに許可します。悪意のあるアプリはユーザーの同意を得ずにユーザー補助を有効にする場合があります。"</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"ウィンドウ情報の取得"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"ウィンドウマネージャからウィンドウに関する情報を取得することをアプリに許可します。悪意のあるアプリが内部システムの利用を目的に情報を取得する恐れがあります。"</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"イベントのフィルタリング"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"すべてのユーザーイベントが送られる前にストリームをフィルタリングする入力フィルタを登録することをアプリに許可します。悪意のあるアプリがユーザーの操作なしでシステムUIを制御する恐れがあります。"</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"表示の拡大"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"表示内容を拡大することをアプリに許可します。悪意のあるアプリが、端末を使用できなくなるように表示内容を変換する恐れがあります。"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"部分的にシャットダウンする"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"アクティビティマネージャをシャットダウン状態にします。完全なシャットダウンは実行しません。"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"アプリケーションの切り替えを禁止する"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"実行するプロセスの上限数を制御することをアプリに許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"バックグラウンドのアプリの強制終了"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"バックグラウンドになりしだい操作を常に終了するかどうかの制御をアプリに許可します。通常のアプリでは不要です。"</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"電池統計情報の変更"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"電池に関して収集した統計情報の変更をアプリに許可します。通常のアプリでは使用しません。"</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"電池統計情報の読み取り"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"現在の電池消費量の低レベルデータを読み取ることをアプリに許可します。このアプリが、使用しているアプリの詳細情報を確認できるようになります。"</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"電池統計情報の変更"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"電池に関して収集した統計情報の変更をアプリに許可します。通常のアプリでは使用しません。"</string>
     <string name="permlab_backup" msgid="470013022865453920">"システムのバックアップと復元を制御する"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"システムのバックアップと復元メカニズムの制御をアプリに許可します。通常のアプリでは使用しません。"</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"フルバックアップや復元の操作の確認"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"未許可のウィンドウの表示"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"内部システムのユーザーインターフェースで使用するためのウィンドウを作成することをアプリに許可します。通常のアプリでは使用しません。"</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"他のアプリの上に重ねて表示"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"システムの警告ウィンドウの表示をアプリに許可します。警告ウィンドウによっては、画面全体が乗っ取られる恐れがあります。"</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"他のアプリやユーザーインターフェースの一部の上に重ねて描画することをアプリに許可します。これにより、他のアプリのインターフェースを使用する際に邪魔になったり、他のアプリに表示されていると思われるものが変更されたりする場合があります。"</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-orderingを回避して独自のトークンを作成、管理することをアプリに許可します。通常のアプリでは不要です。"</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"画面のフリーズ"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"全画面遷移のために画面を一時的にフリーズすることをアプリに許可します。"</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>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"アプリの直接インストール"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"新規またはアップデート用Androidパッケージのインストールをアプリに許可します。この許可を悪意のあるアプリに利用されると、強力な権限を持つ新しいアプリが勝手に追加される恐れがあります。"</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="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"他のアプリのキャッシュディレクトリからファイルを削除してタブレットのストレージ領域を解放することをアプリに許可します。他のアプリはデータを再取得する必要があるため、これにより他のアプリの起動が遅れる場合があります。"</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"他のアプリのキャッシュディレクトリからファイルを削除して端末のストレージ領域を解放することをアプリに許可します。他のアプリはデータを再取得する必要があるため、これにより他のアプリの起動が遅れる場合があります。"</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"アプリのリソースの移動"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"内部メディアと外部メディアの間でアプリのリソースを移動することをアプリに許可します。"</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"機密ログデータの読み取り"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"位置情報提供元の追加のコマンドにアクセスすることをアプリに許可します。許可すると、アプリがGPSなどの位置情報源の動作を妨害する恐れがあります。"</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"位置情報提供元のインストールを許可する"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"テスト用に仮の位置情報源を作成するか、新しい位置情報提供元をインストールします。これにより、他の位置情報源(GPS、位置情報提供元など)から返された位置情報やステータスをアプリが上書きできるようになる可能性があります。"</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"正確な位置情報(GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"正確な位置情報源(タブレットのGPSなど)にアクセスします。これにより、位置情報サービスが利用でき、ONになっているときは、アプリが正確な現在地を特定できるようになります。"</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"正確な位置情報源(携帯端末のGPSなど)にアクセスします。これにより、位置情報サービスが利用でき、ONになっているときは、アプリが正確な現在地を特定できるようになります。"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"おおよその位置情報(ネットワーク基地局)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"基地局やWi-Fiなどのネットワーク情報源を使用して、位置情報提供元からのおおよその位置情報にアクセスします。これにより、これらの位置情報サービスが利用でき、ONになっているときは、アプリがおおよその現在地を特定できるようになります。"</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"正確な位置情報(GPSとネットワーク基地局)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"グローバルポジショニングシステム(GPS)またはネットワーク位置情報源(携帯基地局やWi-Fiなど)を利用して正確な位置情報を取得することをアプリに許可します。これらの位置情報サービスはONの状態にして、端末でアプリがサービスを利用できるようにする必要があります。アプリはこの位置情報を利用してユーザーの現在地を特定できます。また、これにより電池の消費量が増える可能性があります。"</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"おおよその位置情報(ネットワーク基地局)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"ユーザーのおおよその位置情報を取得することをアプリに許可します。この位置情報はネットワーク位置情報源(携帯基地局やWi-Fiなど)を利用した位置情報サービスから取得されます。これらの位置情報サービスはONの状態にして、端末でアプリがサービスを利用できるようにする必要があります。アプリはこの位置情報を利用してユーザーのおおよその現在地を特定できます。"</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"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="permlab_configureWifiDisplay" msgid="5595661694746742168">"Wi-Fiディスプレイの設定"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Wi-Fiディスプレイを設定して接続することをアプリに許可します。"</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wi-Fiディスプレイの制御"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Wi-Fiディスプレイの低レベル機能を制御することをアプリに許可します。"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"音声設定の変更"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"音声全般の設定(音量、出力に使用するスピーカーなど)の変更をアプリに許可します。"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"録音"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"Bluetoothの設定へのアクセス"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"ローカルのBluetoothタブレットを設定することと、リモート端末を検出してペアに設定することをアプリに許可します。"</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"ローカルのBluetooth携帯端末を設定することと、リモート端末を検出してペアに設定することをアプリに許可します。"</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"WiMAX接続の表示"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAXへの接続と切断"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"WiMAXがONになっているかどうかを識別し、接続されているWiMAXネットワークの情報を表示することをアプリに許可します。"</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX状態の変更"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"タブレットのWiMAXネットワークへの接続と切断をアプリに許可します。"</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"現在同期されているフィードの変更をアプリに許可します。この許可を悪意のあるアプリに利用されると、同期されたフィードが変更される恐れがあります。"</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"辞書に追加された語句の読み取り"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"ユーザー辞書に登録されているすべての語句や名前を読み取ることをアプリに許可します。"</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"単語リストへの書き込み"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"単語リストへの語句の追加"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"単語リストに新しい語句を書き込むことをアプリに許可します。"</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"保護されたストレージへのテストアクセス"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"保護されたストレージへのテストアクセス"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"今後追加するデバイスで使用できるUSBストレージの権限のテストをアプリに許可します。"</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"今後追加する端末で使用できるUSBストレージの権限のテストをアプリに許可します。"</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"今後追加するデバイスで使用できるSDカードの権限のテストをアプリに許可します。"</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"USBストレージのコンテンツの変更または削除"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"SDカードのコンテンツの変更または削除"</string>
@@ -534,6 +593,8 @@
     <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="permlab_sdcardAccessAll" msgid="8150613823900460576">"全ユーザー外部ストレージへのアクセス"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"すべてのユーザーの外部ストレージへのアクセスをアプリに許可します。"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"キャッシュファイルシステムにアクセス"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"キャッシュファイルシステムの読み書きをアプリに許可します。"</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"インターネット通話の発着信"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"保存したアプリデータが暗号化されるようにします。"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"カメラを無効にする"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"すべての端末カメラを使用できないようにします。"</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"キーガードの機能を無効にする"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"キーガードの一部の機能の使用を禁止します。"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"自宅"</item>
     <item msgid="869923650527136615">"携帯"</item>
@@ -687,7 +750,7 @@
     <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"PINコードが正しくありません。"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"MENU、0キーでロック解除"</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"緊急通報番号"</string>
-    <string name="lockscreen_carrier_default" msgid="8963839242565653192">"通信サービスはありません。"</string>
+    <string name="lockscreen_carrier_default" msgid="8963839242565653192">"通信サービスはありません"</string>
     <string name="lockscreen_screen_locked" msgid="7288443074806832904">"画面ロック中"</string>
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"MENUキーでロック解除(または緊急通報)"</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"MENUキーでロック解除"</string>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"もう一度お試しください"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"フェイスアンロックの最大試行回数を超えました"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"充電しています: <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"充電完了"</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"充電完了"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"充電してください"</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"SIMカードが挿入されていません"</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIMカードが挿入されていません"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"タブレット内にSIMカードがありません。"</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"SIMカードが挿入されていません"</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"SIMカードを挿入してください。"</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"パターンを消去しました"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"セルを追加しました"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"パターンの描画が完了しました"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"ウィジェットを追加します。"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"なし"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"ロック解除エリアを拡大しました。"</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"ロック解除エリアを縮小しました。"</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>ウィジェットです。"</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"ユーザー切り替え"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"ステータス"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"カメラ"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"メディアコントロール"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"ウィジェットの並べ替えを開始しました。"</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"ウィジェットの並べ替えを終了しました。"</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>ウィジェットを削除しました。"</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"ロック解除エリアを拡大します。"</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"スライドロックを解除します。"</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"パターンロックを解除します。"</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"フェイスアンロックを行います。"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PINロックを解除します。"</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"パスワードロックを解除します。"</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"パターンエリアです。"</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"スライドエリアです。"</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -760,7 +843,7 @@
     <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST操作は、/system/appにインストールされたパッケージのみが対象です。"</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"FACTORY_TEST操作を行うパッケージは見つかりませんでした。"</string>
     <string name="factorytest_reboot" msgid="6320168203050791643">"再起動"</string>
-    <string name="js_dialog_title" msgid="1987483977834603872">"ページ「<xliff:g id="TITLE">%s</xliff:g>」の記述:"</string>
+    <string name="js_dialog_title" msgid="1987483977834603872">"<xliff:g id="TITLE">%s</xliff:g> のページ:"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="730366588032430474">"このページから移動しますか?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"移動する場合は[OK]、現在のページに留まる場合は[キャンセル]をタップしてください。"</string>
     <string name="save_password_label" msgid="6860261758665825069">"確認"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"URLをコピー"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"テキストを選択"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"テキスト選択"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"辞書に追加"</string>
-    <string name="deleteText" msgid="7070985395199629156">"削除"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"辞書に追加"</string>
+    <string name="deleteText" msgid="6979668428458199034">"削除"</string>
     <string name="inputMethod" msgid="1653630062304567879">"入力方法"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"テキスト操作"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"空き容量わずか"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Wi-Fiオープンネットワークが利用できます"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Wi-Fiネットワークにログイン"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"ネットワークにログイン"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fiに接続できませんでした"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" はインターネット接続に問題があります。"</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"To:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"必要なPINを入力してください:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"携帯端末が<xliff:g id="DEVICE_NAME">%1$s</xliff:g>に接続されている間は一時的にWi-Fi接続が解除されます。"</string>
     <string name="select_character" msgid="3365550120617701745">"文字を挿入"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMSメッセージの送信中"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;が大量のSMSメッセージを送信しています。このアプリにこのままメッセージの送信を許可しますか?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"許可する"</string>
     <string name="sms_control_no" msgid="625438561395534982">"許可しない"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;が、&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;にメッセージを送信しようとしています。"</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"モバイルアカウントへの"<font fgcolor="#ffffb060">"請求が発生する可能性"</font>"があります。"</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"モバイルアカウントへの請求が発生します。"</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"送信"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"キャンセル"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"この選択を保存"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"これは後から[設定] &gt; [アプリ]で変更できます。"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"常に許可する"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"許可しない"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIMカードが取り外されました"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"有効なSIMカードを挿入して再起動するまでは、モバイルネットワークは利用できません。"</string>
     <string name="sim_done_button" msgid="827949989369963775">"完了"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"日付設定"</string>
     <string name="date_time_set" msgid="5777075614321087758">"設定"</string>
     <string name="date_time_done" msgid="2507683751759308828">"完了"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"端末既定"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"権限の許可は必要ありません"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"隠す"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"すべて表示"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NEW: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NEW: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"<xliff:g id="APP_NAME">%1$s</xliff:g>で提供されます。"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"権限の許可は必要ありません"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"料金が発生する場合があります"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USBマスストレージ"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB接続"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"USBでパソコンに接続しています。パソコンとAndroidのUSBストレージ間でファイルをコピーするには下のボタンをタップします。"</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPNが<xliff:g id="APP">%s</xliff:g>により有効化されました"</string>
     <string name="vpn_text" msgid="3011306607126450322">"タップしてネットワークを管理します。"</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"<xliff:g id="SESSION">%s</xliff:g>に接続しました。ネットワークを管理するにはタップしてください。"</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPNに常時接続しています…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPNに常時接続しました"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"常時接続VPNのエラー"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"接続をリセットするにはタップします"</string>
     <string name="upload_file" msgid="2897957172366730416">"ファイルを選択"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"ファイルが選択されていません"</string>
     <string name="reset" msgid="2448168080964209908">"リセット"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"共有"</string>
     <string name="find" msgid="4808270900322985960">"検索"</string>
     <string name="websearch" msgid="4337157977400211589">"ウェブ検索"</string>
+    <string name="find_next" msgid="5742124618942193978">"次を検索"</string>
+    <string name="find_previous" msgid="2196723669388360506">"前を検索"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g>さんからの現在地情報リクエスト"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"現在地情報へのアクセス許可"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g>さん(<xliff:g id="SERVICE">%2$s</xliff:g>)からのリクエスト"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"携帯端末"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ヘッドホン"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ホルダーのスピーカー"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMIオーディオ"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"システム"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth音声"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"完了"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"メディア出力"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"スキャン中..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"接続中..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"利用できます"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"利用できません"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"内蔵スクリーン"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI画面"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"オーバーレイ第<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>、<xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"ワイヤレスディスプレイが接続されています"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"この画面は別の端末で表示されています"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"切断"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"緊急通報"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"パターンを忘れた場合"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"パターンが正しくありません"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"パスワードが正しくありません"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"PINが正しくありません"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%d</xliff:g>秒以内にもう一度お試しください。"</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"パターンを入力"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"SIM PINを入力"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"PINを入力"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"パスワードを入力"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIMが無効になりました。続行するにはPUKコードを入力してください。詳しくは携帯通信会社にお問い合わせください。"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"希望のPINコードを入力してください"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"希望のPINコードを確認してください"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIMカードのロック解除中…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"PINコードが正しくありません。"</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"PINは4~8桁の数字で入力してください。"</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUKコードは8桁以上の番号です。"</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"正しいPUKコードを再入力してください。誤入力を繰り返すと、SIMが永久に無効になるおそれがあります。"</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PINコードが一致しません"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"パターンの入力を所定の回数以上間違えました。"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"ロックを解除するにはGoogleアカウントでログインしてください。"</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"ユーザー名(メール)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"パスワード"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"ログイン"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"ユーザー名またはパスワードが無効です。"</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"ユーザー名またはパスワードを忘れた場合は"\n" "<b>"google.com/accounts/recovery"</b>" にアクセスしてください。"</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"アカウントをチェックしています…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"PINの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒以内にもう一度お試しください。"</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"パスワードの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒以内にもう一度お試しください。"</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒以内にもう一度お試しください。"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"タブレットのロック解除に<xliff:g id="NUMBER_0">%d</xliff:g>回失敗しました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回失敗すると、タブレットは出荷時設定にリセットされ、ユーザーのデータはすべて失われます。"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"携帯端末のロック解除に<xliff:g id="NUMBER_0">%d</xliff:g>回失敗しました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回失敗すると、端末は出荷時設定にリセットされ、ユーザーのデータはすべて失われます。"</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"タブレットのロック解除を<xliff:g id="NUMBER">%d</xliff:g>回失敗しました。タブレットは出荷時設定にリセットされます。"</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"携帯端末のロック解除を<xliff:g id="NUMBER">%d</xliff:g>回失敗しました。端末は出荷時設定にリセットされます。"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、タブレットのロック解除にメールアカウントが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒以内にもう一度お試しください。"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、携帯端末のロック解除にメールアカウントが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒以内にもう一度お試しください。"</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" - "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"削除"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"安全レベルを超えるまで音量を上げますか?"\n"大音量で長時間聞き続けると、聴力を損なう恐れがあります。"</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"ユーザー補助機能を有効にするには2本の指で押し続けてください。"</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"ユーザー補助が有効になりました。"</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"ユーザー補助をキャンセルしました。"</string>
+    <string name="user_switched" msgid="3768006783166984410">"現在のユーザーは<xliff:g id="NAME">%1$s</xliff:g>です。"</string>
+    <string name="owner_name" msgid="2716755460376028154">"所有者"</string>
 </resources>
diff --git a/core/res/res/values-ko/donottranslate-cldr.xml b/core/res/res/values-ko/donottranslate-cldr.xml
index 5382871..59b975f 100644
--- a/core/res/res/values-ko/donottranslate-cldr.xml
+++ b/core/res/res/values-ko/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">1월</string>
-    <string name="month_long_standalone_february">2월</string>
-    <string name="month_long_standalone_march">3월</string>
-    <string name="month_long_standalone_april">4월</string>
-    <string name="month_long_standalone_may">5월</string>
-    <string name="month_long_standalone_june">6월</string>
-    <string name="month_long_standalone_july">7월</string>
-    <string name="month_long_standalone_august">8월</string>
-    <string name="month_long_standalone_september">9월</string>
-    <string name="month_long_standalone_october">10월</string>
-    <string name="month_long_standalone_november">11월</string>
-    <string name="month_long_standalone_december">12월</string>
-
-    <string name="month_long_january">1월</string>
-    <string name="month_long_february">2월</string>
-    <string name="month_long_march">3월</string>
-    <string name="month_long_april">4월</string>
-    <string name="month_long_may">5월</string>
-    <string name="month_long_june">6월</string>
-    <string name="month_long_july">7월</string>
-    <string name="month_long_august">8월</string>
-    <string name="month_long_september">9월</string>
-    <string name="month_long_october">10월</string>
-    <string name="month_long_november">11월</string>
-    <string name="month_long_december">12월</string>
-
-    <string name="month_medium_january">1월</string>
-    <string name="month_medium_february">2월</string>
-    <string name="month_medium_march">3월</string>
-    <string name="month_medium_april">4월</string>
-    <string name="month_medium_may">5월</string>
-    <string name="month_medium_june">6월</string>
-    <string name="month_medium_july">7월</string>
-    <string name="month_medium_august">8월</string>
-    <string name="month_medium_september">9월</string>
-    <string name="month_medium_october">10월</string>
-    <string name="month_medium_november">11월</string>
-    <string name="month_medium_december">12월</string>
-
-    <string name="month_shortest_january">1월</string>
-    <string name="month_shortest_february">2월</string>
-    <string name="month_shortest_march">3월</string>
-    <string name="month_shortest_april">4월</string>
-    <string name="month_shortest_may">5월</string>
-    <string name="month_shortest_june">6월</string>
-    <string name="month_shortest_july">7월</string>
-    <string name="month_shortest_august">8월</string>
-    <string name="month_shortest_september">9월</string>
-    <string name="month_shortest_october">10월</string>
-    <string name="month_shortest_november">11월</string>
-    <string name="month_shortest_december">12월</string>
-
-    <string name="day_of_week_long_sunday">일요일</string>
-    <string name="day_of_week_long_monday">월요일</string>
-    <string name="day_of_week_long_tuesday">화요일</string>
-    <string name="day_of_week_long_wednesday">수요일</string>
-    <string name="day_of_week_long_thursday">목요일</string>
-    <string name="day_of_week_long_friday">금요일</string>
-    <string name="day_of_week_long_saturday">토요일</string>
-
-    <string name="day_of_week_medium_sunday">일</string>
-    <string name="day_of_week_medium_monday">월</string>
-    <string name="day_of_week_medium_tuesday">화</string>
-    <string name="day_of_week_medium_wednesday">수</string>
-    <string name="day_of_week_medium_thursday">목</string>
-    <string name="day_of_week_medium_friday">금</string>
-    <string name="day_of_week_medium_saturday">토</string>
-
-    <string name="day_of_week_short_sunday">일</string>
-    <string name="day_of_week_short_monday">월</string>
-    <string name="day_of_week_short_tuesday">화</string>
-    <string name="day_of_week_short_wednesday">수</string>
-    <string name="day_of_week_short_thursday">목</string>
-    <string name="day_of_week_short_friday">금</string>
-    <string name="day_of_week_short_saturday">토</string>
-
-    <string name="day_of_week_shortest_sunday">일</string>
-    <string name="day_of_week_shortest_monday">월</string>
-    <string name="day_of_week_shortest_tuesday">화</string>
-    <string name="day_of_week_shortest_wednesday">수</string>
-    <string name="day_of_week_shortest_thursday">목</string>
-    <string name="day_of_week_shortest_friday">금</string>
-    <string name="day_of_week_shortest_saturday">토</string>
-
-    <string name="am">오전</string>
-    <string name="pm">오후</string>
-    <string name="yesterday">어제</string>
-    <string name="today">오늘</string>
-    <string name="tomorrow">내일</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%p %-l:%M</string>
     <string name="hour_minute_cap_ampm">%p %-l:%M</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 1f2a17f..37c6b01 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"휴대전화 옵션"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"화면 잠금"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"종료"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"버그 신고"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"버그 신고 받기"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"이렇게 하면 현재 기기 상태에 대한 정보를 수집하여 이메일 메시지로 전송합니다. 버그 신고를 시작하여 전송할 준비가 되려면 약간 시간이 걸립니다."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"무음 모드"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"소리 꺼짐"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"소리 켜짐"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"메시지"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"SMS, 이메일 및 기타 메시지를 읽고 씁니다."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"개인정보"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"태블릿에 저장된 주소록 및 캘린더에 직접 액세스합니다."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"휴대전화에 저장된 주소록 및 캘린더에 직접 액세스합니다."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"연락처 카드에 저장된 내 개인 정보에 직접 액세스합니다."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"소셜 정보"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"내 연락처 및 소셜 친구의 개인 정보에 직접 액세스합니다."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"위치"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"실제 위치 모니터링"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"네트워크 통신"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"다양한 네트워크 기능에 액세스할 수 있도록 합니다."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"블루투스"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"블루투스를 통해 기기 및 네트워크에 액세스"</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"오디오 설정"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"오디오 설정을 변경합니다."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"배터리 소모"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"배터리를 빨리 소모시킬 수 있는 기능을 사용합니다."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"캘린더"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"캘린더 및 일정에 직접 액세스합니다."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"사용자 사전 읽기"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"사용자 사전의 단어 읽기"</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"사용자 사전 쓰기"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"사용자 사전에 단어 추가"</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"북마크 및 기록"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"북마크 및 브라우저 기록에 직접 액세스합니다."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"알람"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"알람 시계를 설정합니다."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"음성사서함"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"음성사서함에 직접 액세스합니다."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"마이크"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"오디오를 녹음하기 위해 마이크에 직접 액세스합니다."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"카메라"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"이미지 및 동영상을 캡처하기 위해 카메라에 직접 액세스합니다."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"애플리케이션 정보"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"기기의 다른 애플리케이션의 작동에 영향을 줍니다."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"배경화면"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"기기 배경화면 설정을 변경합니다."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"시계"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"기기 시간 및 시간대를 변경합니다."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"상태 표시줄"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"기기 상태 표시줄 설정을 변경합니다."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"동기화 설정"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"동기화 설정에 액세스합니다."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"계정"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"사용 가능한 계정에 액세스합니다."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"하드웨어 제어"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"시스템을 하위 수준에서 액세스하고 제어합니다."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"개발 도구"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"앱 개발자에게만 필요한 기능입니다."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"다른 애플리케이션 UI"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"다른 애플리케이션의 UI에 영향을 줍니다."</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>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"앱이 WAP 메시지를 수신하고 처리할 수 있도록 허용합니다. 이는 앱이 사용자에게 표시하지 않고 기기로 전송된 메시지를 모니터링 또는 삭제할 수도 있다는 것을 의미합니다."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"실행 중인 앱 검색"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"앱이 현재 실행 중이거나 최근에 실행된 작업에 대한 정보를 검색할 수 있도록 허용합니다. 이 경우 앱이 기기에서 사용되는 다른 앱에 대한 정보를 검색할 수 있습니다."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"여러 사용자와의 상호작용"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"앱이 기기에서 다양한 사용자에 대한 작업을 수행할 수 있도록 허용합니다. 이 경우 악성 앱이 사용자 간의 보호를 위반할 수 있습니다."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"여러 사용자와의 상호작용을 위한 정식 라이센스"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"여러 사용자와의 가능한 모든 상호작용을 허용합니다."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"사용자 관리"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"앱이 기기에서 검색, 생성 및 삭제를 포함한 사용자 관리를 할 수 있도록 허용합니다."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"실행 중인 앱 세부정보 검색"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"앱이 현재 실행 중이거나 최근에 실행된 작업에 대한 상세한 정보를 검색할 수 있도록 허용합니다. 이 경우 악성 앱이 다른 앱에 대한 개인 정보를 검색할 수 있습니다."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"실행 중인 앱 순서 재지정"</string>
@@ -243,6 +287,14 @@
     <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="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"일시적인 접근성 사용"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"애플리케이션이 기기에서 일시적으로 접근성을 사용하도록 허용합니다. 이 경우 악성 앱이 사용자의 동의 없이 접근성을 사용할 수 있습니다."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"창 관련 정보 가져오기"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"애플리케이션이 Window Manager에서 창 관련 정보를 가져오도록 허용합니다. 이 경우 악성 앱이 내부 시스템에서만 사용하도록 되어 있는 정보를 가져올 수 있습니다."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"일정 필터링"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"애플리케이션에 입력 필터를 등록할 수 있도록 하여 모든 사용자 일정 스트림을 전달하기 전에 필터링합니다. 이 경우 사용자의 개입 없이 악성 앱이 시스템 UI를 제어할 수 있습니다."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"디스플레이 확대"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"앱이 표시된 콘텐츠를 확대하도록 허용합니다. 악성 앱은 표시된 콘텐츠를 변형시켜 기기를 사용할 수 없게 만들 수 있습니다."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"부분 종료"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"작업 관리자를 종료 상태로 설정합니다. 전체 종료를 수행하지는 않습니다."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"애플리케이션 전환 방지"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"앱이 실행할 최대 프로세스 수를 제어할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"백그라운드 앱 강제 종료"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"앱이 백그라운드로 이동한 활동을 항상 바로 종료할지 여부를 제어할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"배터리 통계 수정"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"앱이 수집된 배터리 통계를 수정할 수 있도록 허용합니다. 일반 앱에서는 사용하지 않습니다."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"배터리 통계 확인"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"애플리케이션이 현재의 낮은 수준 배터리 사용 데이터를 읽을 수 있도록 합니다. 이 경우 애플리케이션이 내가 사용하는 앱에 대한 세부정보를 파악할 수도 있습니다."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"배터리 통계 수정"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"앱이 수집된 배터리 통계를 수정할 수 있도록 허용합니다. 일반 앱에서는 사용하지 않습니다."</string>
     <string name="permlab_backup" msgid="470013022865453920">"시스템 백업 및 복원 관리"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"앱이 시스템의 백업 및 복원 메커니즘을 제어할 수 있도록 허용합니다. 일반 앱에서는 사용하지 않습니다."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"전체 백업 또는 복원 작업 확인"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"인증되지 않은 창 표시"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"애플리케이션이 내부 시스템 사용자 인터페이스에서 사용하는 창을 만들 수 있도록 허용합니다. 일반 애플리케이션에서는 사용하지 않습니다."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"다른 앱 위에 그리기"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"앱이 시스템 경고 창을 표시할 수 있도록 허용합니다. 이 경우 앱이 화면 전체를 차지할 수도 있습니다."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"앱이 다른 애플리케이션이나 사용자 인터페이스 부분 위에 그림을 그릴 수 있도록 합니다. 이 경우 애플리케이션에서 인터페이스 사용에 방해가 되거나 다른 애플리케이션에서 표시되는 콘텐츠가 변경될 수 있습니다."</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="permlab_freezeScreen" msgid="4708181184441880175">"화면 고정"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"앱이 전체 화면 전환을 위해 일시적으로 화면을 고정하도록 허용합니다."</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>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"앱 직접 설치"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"앱이 새로운 또는 업데이트된 Android 패키지를 설치할 수 있도록 허용합니다. 이 경우 악성 앱이 임의의 강력한 권한을 가진 새 앱을 추가할 수 있습니다."</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="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"앱이 다른 애플리케이션의 캐시 디렉토리에서 파일을 삭제하여 태블릿의 저장 공간을 늘릴 수 있도록 합니다. 이 경우 다른 애플리케이션이 해당 데이터를 다시 검색해야 하기 때문에 시작 속도가 느려질 수 있습니다."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"앱이 다른 애플리케이션의 캐시 디렉토리에서 파일을 삭제하여 휴대전화의 저장 공간을 늘릴 수 있도록 합니다. 이 경우 다른 애플리케이션이 해당 데이터를 다시 검색해야 하기 때문에 시작 속도가 느려질 수 있습니다."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"앱 리소스 이동"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"앱이 앱 리소스를 내부에서 외부 미디어로 또는 그 반대로 이동할 수 있도록 허용합니다."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"중요한 로그 데이터 읽기"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"앱이 추가 위치 정보 제공업체 명령에 액세스하도록 허용합니다. 이 경우 앱이 GPS 또는 기타 위치 소스의 작동을 방해하게 될 수 있습니다."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"위치 정보 공급자 설치 권한"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"테스트용 가상 위치 소스를 만들거나 새로운 위치 정보 제공업체를 설치합니다. 이 경우 앱이 GPS 또는 위치 정보 제공업체 등 기타 위치 소스가 반환한 위치 또는 상태를 덮어쓸 수 있습니다."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"정확한(GPS) 위치"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"태블릿 GPS 등의 정확한 위치 소스에 액세스하세요. 위치 정보 서비스를 사용할 수 있고 사용하도록 설정한 경우, 이 권한을 통해 앱이 정확한 위치를 결정할 수 있습니다."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"휴대전화 GPS 등의 정확한 위치 소스에 액세스하세요. 위치 정보 서비스를 사용할 수 있고 사용하도록 설정한 경우, 이 권한을 통해 앱이 정확한 위치를 결정할 수 있습니다."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"대략적인(네트워크 기반) 위치"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"기지국이나 Wi-Fi 등의 네트워크 소스를 사용하여 위치 정보 제공업체로부터 대략적인 위치에 액세스하세요. 위치 정보 서비스를 사용할 수 있고 사용하도록 설정한 경우, 이 권한을 통해 앱이 대략적인 위치를 결정할 수 있습니다."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"정확한 위치(GPS 및 네트워크 기반)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"앱에서 GPS 또는 기지국 및 Wi-Fi와 같은 네트워크 위치 제공자를 사용하는 위치 서비스를 통해 내 정확한 위치를 알 수 있도록 합니다. 앱에서 이를 사용하도록 하려면 기기에서 이러한 위치 서비스는 사용하도록 설정해야 합니다. 앱에서 위치 서비스를 사용하여 내 위치를 파악할 수 있으며 배터리 소모량이 증가할 수 있습니다."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"대략적인 위치(네트워크 기반)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"앱에서 나의 대략적인 위치를 알 수 있게 합니다. 이 위치는 기지국 및 Wi-Fi와 같은 네트워크 위치 제공자를 사용하는 위치 서비스를 통해 알 수 있습니다. 앱에서 이를 사용하도록 하려면 기기에서 이러한 위치 서비스를 사용하도록 설정해야 합니다. 앱에서 이를 사용하여 나의 대략적인 위치를 파악할 수 있습니다."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"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="permlab_configureWifiDisplay" msgid="5595661694746742168">"Wi-Fi 디스플레이 설정"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"앱이 Wi-Fi 디스플레이를 설정하고 연결하도록 허용합니다."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wi-Fi 디스플레이 제어"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"앱이 Wi-Fi 디스플레이의 하위 수준 기능을 제어하도록 허용합니다."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"오디오 설정 변경"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"앱이 음량이나 출력을 위해 사용하는 스피커 등 전체 오디오 설정을 변경할 수 있도록 허용합니다."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"오디오 녹음"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"블루투스 설정에 액세스"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"앱이 로컬 블루투스 태블릿을 설정한 다음 원격 기기를 검색하여 페어링할 수 있도록 허용합니다."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"앱이 로컬 블루투스 휴대전화를 설정한 다음 원격 기기를 검색하여 페어링할 수 있도록 허용합니다."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"WiMAX 연결 보기"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX 연결 및 연결 해제"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"앱이 WiMAX를 사용하도록 설정했는지 여부와 연결된 WiMAX 네트워크에 대한 정보를 결정할 수 있도록 허용합니다."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX 상태 변경"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"앱이 태블릿을 WiMAX 네트워크에 연결하거나 연결을 끊을 수 있도록 허용합니다."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"앱이 현재 동기화된 피드를 수정할 수 있도록 허용합니다. 이 경우 악성 앱이 동기화된 피드를 변경할 수 있습니다."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"사전에 추가한 단어 읽기"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"앱이 사용자 사전에 저장하고 있는 모든 단어, 이름, 문구 등을 읽을 수 있도록 허용합니다."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"사용자 정의 사전에 작성"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"사용자 정의 사전에 단어 추가"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"앱이 사용자 사전에 새 단어를 입력할 수 있도록 허용합니다."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"보호된 저장소에 액세스 테스트"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"보호된 저장소에 액세스 테스트"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"앱이 미래의 기기에서 사용할 수 있는 USB 저장소의 권한을 테스트하도록 허용합니다."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"앱이 향후 기기에서 사용할 수 있는 USB 저장소의 권한을 테스트하도록 허용합니다."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"앱이 미래의 기기에서 사용할 수 있는 SD 카드의 권한을 테스트하도록 허용합니다."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"USB 저장소의 콘텐츠 수정 또는 삭제"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"SD 카드의 콘텐츠 수정 또는 삭제"</string>
@@ -534,6 +593,8 @@
     <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="permlab_sdcardAccessAll" msgid="8150613823900460576">"모든 사용자의 외부 저장소에 액세스"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"앱이 모든 사용자의 외부 저장소에 액세스하도록 허용합니다."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"캐시 파일시스템 액세스"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"앱이 캐시 파일 시스템을 읽고 쓸 수 있도록 허용합니다."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"인터넷 전화 걸기/받기"</string>
@@ -549,7 +610,7 @@
     <string name="policylab_watchLogin" msgid="914130646942199503">"화면 잠금해제 시도 모니터링"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"화면 잠금해제 시 비밀번호를 잘못 입력한 횟수를 모니터링하고, 잘못된 비밀번호 입력 횟수가 너무 많은 경우 태블릿을 잠그거나 태블릿에 있는 데이터를 모두 지웁니다."</string>
     <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"화면 잠금해제 시 비밀번호를 잘못 입력한 횟수를 모니터링하고, 잘못된 비밀번호 입력 횟수가 너무 많은 경우 휴대전화를 잠그거나 휴대전화에 있는 데이터를 모두 지웁니다."</string>
-    <string name="policylab_resetPassword" msgid="2620077191242688955">"화면 잠금해제 비밀번호를 변경합니다."</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"화면 잠금해제 비밀번호 변경"</string>
     <string name="policydesc_resetPassword" msgid="605963962301904458">"화면 잠금해제 비밀번호를 변경합니다."</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"화면 잠금"</string>
     <string name="policydesc_forceLock" msgid="1141797588403827138">"화면을 잠그는 방법과 시기를 제어합니다."</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"저장한 애플리케이션 데이터를 암호화해야 합니다."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"카메라 사용 안함"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"모든 기기 카메라의 사용 차단"</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"키가드에서 기능 사용중지"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"키가드에서 일부 기능의 사용을 차단합니다."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"집"</item>
     <item msgid="869923650527136615">"모바일"</item>
@@ -674,7 +737,7 @@
     <string name="relationTypeSister" msgid="1735983554479076481">"여자 형제"</string>
     <string name="relationTypeSpouse" msgid="394136939428698117">"배우자"</string>
     <string name="sipAddressTypeCustom" msgid="2473580593111590945">"맞춤설정"</string>
-    <string name="sipAddressTypeHome" msgid="6093598181069359295">"홈"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"집"</string>
     <string name="sipAddressTypeWork" msgid="6920725730797099047">"직장"</string>
     <string name="sipAddressTypeOther" msgid="4408436162950119849">"기타"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PIN 코드 입력"</string>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"다시 시도"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"얼굴 인식 잠금해제 최대 시도 횟수를 초과했습니다."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"충전 중(<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"충전되었습니다."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"충전됨"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"충전기를 연결하세요."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"SIM 카드가 없습니다."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM 카드가 없습니다."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"태블릿에 SIM 카드가 없습니다."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"휴대전화에 SIM 카드가 없습니다."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"SIM 카드를 삽입하세요."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"패턴 삭제"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"셀 추가됨"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"패턴 완료"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"위젯 추가"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"비어 있음"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"잠금 해제 영역 확장됨"</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"잠금 해제 영역 축소됨"</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> 위젯"</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"사용자 선택기"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"상태"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"카메라"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"미디어 조정"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"위젯 재정렬 시작됨"</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"위젯 재정렬 완료됨"</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> 위젯이 삭제됨"</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"잠금 해제 영역 확장"</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"슬라이드하여 잠금해제합니다."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"패턴을 사용하여 잠금해제합니다."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"얼굴 인식을 사용하여 잠금해제합니다."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"핀을 사용하여 잠금해제합니다."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"비밀번호를 사용하여 잠금해제합니다."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"패턴을 그리는 부분입니다."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"슬라이드하는 부분입니다."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -781,7 +864,7 @@
     <string name="autofill_department" msgid="5343279462564453309">"지역"</string>
     <string name="autofill_prefecture" msgid="2028499485065800419">"현"</string>
     <string name="autofill_parish" msgid="8202206105468820057">"군"</string>
-    <string name="autofill_area" msgid="3547409050889952423">"구역"</string>
+    <string name="autofill_area" msgid="3547409050889952423">"주소"</string>
     <string name="autofill_emirate" msgid="2893880978835698818">"에미리트"</string>
     <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"웹 북마크 및 기록 읽기"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"앱이 브라우저가 방문한 모든 URL의 기록과 모든 브라우저 북마크를 읽을 수 있도록 허용합니다. 참고: 이 권한은 타사 브라우저 또는 브라우저 기능을 가진 기타 애플리케이션에 적용되지 않습니다."</string>
@@ -912,7 +995,7 @@
     <string name="years" msgid="6881577717993213522">"년"</string>
     <string name="VideoView_error_title" msgid="3534509135438353077">"영상 문제"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"이 기기로 스트리밍하기에 적합하지 않은 동영상입니다."</string>
-    <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"동영상이 재생되지 않습니까?"</string>
+    <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"동영상을 재생할 수 없습니다."</string>
     <string name="VideoView_error_button" msgid="2822238215100679592">"확인"</string>
     <string name="relative_time" msgid="1818557177829411417">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="noon" msgid="7245353528818587908">"정오"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"URL 복사"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"텍스트 선택"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"텍스트 선택"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"사전에 추가"</string>
-    <string name="deleteText" msgid="7070985395199629156">"삭제"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"사전에 추가"</string>
+    <string name="deleteText" msgid="6979668428458199034">"삭제"</string>
     <string name="inputMethod" msgid="1653630062304567879">"입력 방법"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"텍스트 작업"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"저장 공간이 부족함"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"개방형 Wi-Fi 네트워크 사용 가능"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Wi-Fi 네트워크에 로그인"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"네트워크에 로그인"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi에 연결할 수 없습니다"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" 인터넷 연결 상태가 좋지 않습니다."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"받는사람:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"필수 PIN 입력:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>에 연결되어 있는 동안 일시적으로 휴대전화의 Wi-Fi 연결이 해제됩니다."</string>
     <string name="select_character" msgid="3365550120617701745">"문자 삽입"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS 메시지를 보내는 중"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;이(가) SMS 메시지를 대량으로 보내고 있습니다. 해당 앱이 메시지를 계속 보내도록 하시겠습니까?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"허용"</string>
     <string name="sms_control_no" msgid="625438561395534982">"거부"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;(으)로 메시지를 보내시겠습니까?"</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"모바일 계정에 "<font fgcolor="#ffffb060">"요금이 부과될 수 있습니다"</font>"."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"모바일 계정에 요금이 부과됩니다."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"전송"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"취소"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"내 선택사항 기억"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"나중에 설정 &gt; 애플리케이션에서 변경할 수 있습니다."</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"항상 허용"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"허용 안함"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM 카드 제거됨"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"유효한 SIM 카드를 삽입하여 다시 시작할 때까지 모바일 네트워크를 사용할 수 없습니다."</string>
     <string name="sim_done_button" msgid="827949989369963775">"완료"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"날짜 설정"</string>
     <string name="date_time_set" msgid="5777075614321087758">"설정"</string>
     <string name="date_time_done" msgid="2507683751759308828">"완료"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"기본값"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"권한 필요 없음"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"숨기기"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"모두 표시"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"신규: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"신규: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"<xliff:g id="APP_NAME">%1$s</xliff:g> 제공"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"권한 필요 없음"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"비용이 부과될 수 있습니다."</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB 대용량 저장소"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB 연결됨"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"USB를 통해 컴퓨터에 연결했습니다. 컴퓨터와 Android의 USB 저장소 간에 파일을 복사하려면 아래의 버튼을 터치하세요."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN이 <xliff:g id="APP">%s</xliff:g>에 의해 활성화됨"</string>
     <string name="vpn_text" msgid="3011306607126450322">"네트워크를 관리하려면 터치하세요."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"<xliff:g id="SESSION">%s</xliff:g>에 연결되어 있습니다. 네트워크를 관리하려면 터치하세요."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"연결 유지 VPN에 연결하는 중…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"연결 유지 VPN에 연결됨"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"연결 유지 VPN 오류"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"터치하여 연결 재설정"</string>
     <string name="upload_file" msgid="2897957172366730416">"파일 선택"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"파일을 선택하지 않았습니다."</string>
     <string name="reset" msgid="2448168080964209908">"초기화"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"공유"</string>
     <string name="find" msgid="4808270900322985960">"찾기"</string>
     <string name="websearch" msgid="4337157977400211589">"웹 검색"</string>
+    <string name="find_next" msgid="5742124618942193978">"다음 항목 찾기"</string>
+    <string name="find_previous" msgid="2196723669388360506">"이전 항목 찾기"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g>의 위치 요청"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"위치 요청"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"요청한 사람: <xliff:g id="NAME">%1$s</xliff:g>(<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"휴대전화"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"헤드폰"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"도크 스피커"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI 오디오"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"시스템"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"블루투스 오디오"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"완료"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"미디어 출력"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"검색 중..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"연결 중..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"사용 가능"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"사용할 수 없음"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"기본으로 제공되는 화면"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI 화면"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"<xliff:g id="ID">%1$d</xliff:g>번째 오버레이"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"무선 디스플레이가 연결되었습니다."</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"이 화면은 다른 기기에서 표시되고 있습니다."</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"연결 해제"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"긴급 통화"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"패턴을 잊음"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"잘못된 패턴"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"잘못된 비밀번호"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"잘못된 PIN"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%d</xliff:g>초 후에 다시 시도해 주세요."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"패턴 그리기"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"SIM PIN 입력"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"PIN 입력"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"비밀번호 입력"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"이제 SIM을 사용할 수 없습니다. 계속하려면 PUK 코드를 입력합니다. 자세한 내용은 이동통신사에 문의하세요."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"원하는 PIN 코드 입력"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"원하는 PIN 코드 확인"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM 카드 잠금해제 중..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"PIN 코드가 잘못되었습니다."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"4~8자리 숫자로 된 PIN을 입력하세요."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK 코드는 8자리 이상의 숫자여야 합니다."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"올바른 PUK 코드를 다시 입력하세요. 입력을 반복해서 시도하면 SIM을 영구적으로 사용할 수 없게 됩니다."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN 코드가 일치하지 않음"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"패턴 시도 횟수가 너무 많음"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"잠금해제하려면 Google 계정으로 로그인하세요."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"사용자 이름(이메일)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"비밀번호"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"로그인"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"사용자 이름 또는 비밀번호가 잘못되었습니다."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"사용자 이름이나 비밀번호를 잊어버렸습니까?"\n<b>"google.com/accounts/recovery"</b>" 페이지를 방문하세요."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"계정 확인 중…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"PIN을 <xliff:g id="NUMBER_0">%d</xliff:g>회 잘못 입력했습니다. "\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>초 후에 다시 시도해 주세요."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"비밀번호를 <xliff:g id="NUMBER_0">%d</xliff:g>회 잘못 입력했습니다. "\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>초 후에 다시 시도해 주세요."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"잠금해제 패턴을 <xliff:g id="NUMBER_0">%d</xliff:g>회 잘못 그렸습니다. "\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>초 후에 다시 시도해 주세요."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"태블릿을 잠금해제하려는 시도가 <xliff:g id="NUMBER_0">%d</xliff:g>회 잘못되었습니다. <xliff:g id="NUMBER_1">%d</xliff:g>회 더 실패하면 태블릿이 초기화되고 사용자 데이터가 모두 사라집니다."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"휴대전화를 잠금해제하려는 시도가 <xliff:g id="NUMBER_0">%d</xliff:g>회 잘못되었습니다. <xliff:g id="NUMBER_1">%d</xliff:g>회 더 실패하면 휴대전화가 초기화되고 사용자 데이터가 모두 사라집니다."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"태블릿을 잠금해제하려는 시도가 <xliff:g id="NUMBER">%d</xliff:g>회 잘못되었습니다. 태블릿이 초기화됩니다."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"휴대전화를 잠금해제하려는 시도가 <xliff:g id="NUMBER">%d</xliff:g>회 잘못되었습니다. 휴대전화가 초기화됩니다."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"잠금해제 패턴을 <xliff:g id="NUMBER_0">%d</xliff:g>회 잘못 그렸습니다. <xliff:g id="NUMBER_1">%d</xliff:g>회 더 실패하면 이메일 계정을 사용하여 태블릿을 잠금해제해야 합니다."\n\n" <xliff:g id="NUMBER_2">%d</xliff:g>초 후에 다시 시도해 주세요."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"잠금해제 패턴을 <xliff:g id="NUMBER_0">%d</xliff:g>회 잘못 그렸습니다. <xliff:g id="NUMBER_1">%d</xliff:g>회 더 실패하면 이메일 계정을 사용하여 휴대전화를 잠금해제해야 합니다."\n\n" <xliff:g id="NUMBER_2">%d</xliff:g>초 후에 다시 시도해 주세요."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"삭제"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"안전한 수준 이상으로 볼륨을 높이시겠습니까?"\n"높은 볼륨으로 장시간 청취하면 청력에 손상이 올 수 있습니다."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"두 손가락으로 길게 누르면 접근성을 사용하도록 설정됩니다."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"접근성을 사용 설정했습니다."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"접근성이 취소되었습니다."</string>
+    <string name="user_switched" msgid="3768006783166984410">"현재 사용자는 <xliff:g id="NAME">%1$s</xliff:g>님입니다."</string>
+    <string name="owner_name" msgid="2716755460376028154">"소유자"</string>
 </resources>
diff --git a/core/res/res/values-land/alias.xml b/core/res/res/values-land/alias.xml
new file mode 100644
index 0000000..eac5ece
--- /dev/null
+++ b/core/res/res/values-land/alias.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <!-- Alias used to reference one of two possible layouts in keyguard.  -->
+    <item type="layout" name="keyguard_eca">@android:layout/keyguard_emergency_carrier_area_empty</item>
+</resources>
diff --git a/core/res/res/values-land/arrays.xml b/core/res/res/values-land/arrays.xml
index 6db3a508..240b9e4 100644
--- a/core/res/res/values-land/arrays.xml
+++ b/core/res/res/values-land/arrays.xml
@@ -22,16 +22,16 @@
     <!-- Resources for GlowPadView in LockScreen -->
     <array name="lockscreen_targets_when_silent">
         <item>@null</item>"
-        <item>@drawable/ic_lockscreen_unlock</item>
         <item>@drawable/ic_action_assist_generic</item>
         <item>@drawable/ic_lockscreen_soundon</item>
+        <item>@drawable/ic_lockscreen_unlock</item>
     </array>
 
     <array name="lockscreen_target_descriptions_when_silent">
         <item>@null</item>
-        <item>@string/description_target_unlock</item>
         <item>@string/description_target_search</item>
         <item>@string/description_target_soundon</item>
+        <item>@string/description_target_unlock</item>
     </array>
 
     <array name="lockscreen_direction_descriptions">
@@ -43,37 +43,30 @@
 
     <array name="lockscreen_targets_when_soundon">
         <item>@null</item>
-        <item>@drawable/ic_lockscreen_unlock</item>
         <item>@drawable/ic_action_assist_generic</item>
         <item>@drawable/ic_lockscreen_silent</item>
+        <item>@drawable/ic_lockscreen_unlock</item>
     </array>
 
     <array name="lockscreen_target_descriptions_when_soundon">
         <item>@null</item>
-        <item>@string/description_target_unlock</item>
         <item>@string/description_target_search</item>
         <item>@string/description_target_silent</item>
+        <item>@string/description_target_unlock</item>
     </array>
 
     <array name="lockscreen_targets_with_camera">
         <item>@null</item>
-        <item>@drawable/ic_lockscreen_unlock</item>
         <item>@drawable/ic_action_assist_generic</item>
         <item>@drawable/ic_lockscreen_camera</item>
+        <item>@drawable/ic_lockscreen_unlock</item>
     </array>
 
     <array name="lockscreen_target_descriptions_with_camera">
         <item>@null</item>
-        <item>@string/description_target_unlock</item>
         <item>@string/description_target_search</item>
         <item>@string/description_target_camera</item>
-    </array>
-
-    <array name="lockscreen_chevron_drawables">
-        <item>@null</item>
-        <item>@drawable/ic_lockscreen_chevron_up</item>
-        <item>@null</item>
-        <item>@null</item>
+        <item>@string/description_target_unlock</item>
     </array>
 
 </resources>
diff --git a/core/res/res/values-land/bools.xml b/core/res/res/values-land/bools.xml
new file mode 100644
index 0000000..a1dd2e4
--- /dev/null
+++ b/core/res/res/values-land/bools.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+    <bool name="kg_enable_camera_default_widget">false</bool>
+    <bool name="kg_top_align_page_shrink_on_bouncer_visible">true</bool>
+    <bool name="kg_share_status_area">false</bool>
+    <bool name="kg_sim_puk_account_full_screen">false</bool>
+</resources>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index 6f96852..8f1bd9a 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -43,4 +43,22 @@
     <!-- Size of clock font in LockScreen on Unsecure unlock screen. -->
     <dimen name="keyguard_lockscreen_clock_font_size">70sp</dimen>
 
+    <!-- Shift emergency button from the left edge by this amount.  Used by landscape layout on
+         phones -->
+    <dimen name="kg_emergency_button_shift">30dp</dimen>
+
+    <!-- Space reserved at the bottom of secure views (pin/pattern/password/SIM pin/SIM puk) -->
+    <dimen name="kg_secure_padding_height">0dp</dimen>
+
+    <!-- Top padding for the widget pager -->
+    <dimen name="kg_widget_pager_top_padding">0dp</dimen>
+
+    <!-- Bottom padding for the widget pager -->
+    <dimen name="kg_widget_pager_bottom_padding">0dp</dimen>
+
+    <!-- If the height if keyguard drops below this threshold (most likely
+    due to the appearance of the IME), then drop the multiuser selector.
+    Landscape's layout allows this to be smaller than for portrait. -->
+    <dimen name="kg_squashed_layout_threshold">400dp</dimen>
+
 </resources>
diff --git a/core/res/res/values-land/integers.xml b/core/res/res/values-land/integers.xml
new file mode 100644
index 0000000..020fd23
--- /dev/null
+++ b/core/res/res/values-land/integers.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <!-- Gravity to make KeyguardSelectorView work in multiple orientations
+        0x13 == "left|center_vertical" -->
+    <integer name="kg_selector_gravity">0x13</integer>
+    <integer name="kg_widget_region_weight">45</integer>
+    <integer name="kg_security_flipper_weight">55</integer>
+    <integer name="kg_glowpad_rotation_offset">-90</integer>
+</resources>
diff --git a/core/res/res/values-lt-rLT/donottranslate-cldr.xml b/core/res/res/values-lt-rLT/donottranslate-cldr.xml
index 0c1d0aa..6cf6098 100644
--- a/core/res/res/values-lt-rLT/donottranslate-cldr.xml
+++ b/core/res/res/values-lt-rLT/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Sausis</string>
-    <string name="month_long_standalone_february">Vasaris</string>
-    <string name="month_long_standalone_march">Kovas</string>
-    <string name="month_long_standalone_april">Balandis</string>
-    <string name="month_long_standalone_may">Gegužė</string>
-    <string name="month_long_standalone_june">Birželis</string>
-    <string name="month_long_standalone_july">Liepa</string>
-    <string name="month_long_standalone_august">Rugpjūtis</string>
-    <string name="month_long_standalone_september">Rugsėjis</string>
-    <string name="month_long_standalone_october">Spalis</string>
-    <string name="month_long_standalone_november">Lapkritis</string>
-    <string name="month_long_standalone_december">Gruodis</string>
-
-    <string name="month_long_january">sausio</string>
-    <string name="month_long_february">vasario</string>
-    <string name="month_long_march">kovo</string>
-    <string name="month_long_april">balandžio</string>
-    <string name="month_long_may">gegužės</string>
-    <string name="month_long_june">birželio</string>
-    <string name="month_long_july">liepos</string>
-    <string name="month_long_august">rugpjūčio</string>
-    <string name="month_long_september">rugsėjo</string>
-    <string name="month_long_october">spalio</string>
-    <string name="month_long_november">lapkričio</string>
-    <string name="month_long_december">gruodžio</string>
-
-    <string name="month_medium_january">sau.</string>
-    <string name="month_medium_february">vas.</string>
-    <string name="month_medium_march">kov.</string>
-    <string name="month_medium_april">bal.</string>
-    <string name="month_medium_may">geg.</string>
-    <string name="month_medium_june">bir.</string>
-    <string name="month_medium_july">lie.</string>
-    <string name="month_medium_august">rgp.</string>
-    <string name="month_medium_september">rgs.</string>
-    <string name="month_medium_october">spl.</string>
-    <string name="month_medium_november">lap.</string>
-    <string name="month_medium_december">grd.</string>
-
-    <string name="month_shortest_january">S</string>
-    <string name="month_shortest_february">V</string>
-    <string name="month_shortest_march">K</string>
-    <string name="month_shortest_april">B</string>
-    <string name="month_shortest_may">G</string>
-    <string name="month_shortest_june">B</string>
-    <string name="month_shortest_july">L</string>
-    <string name="month_shortest_august">R</string>
-    <string name="month_shortest_september">R</string>
-    <string name="month_shortest_october">S</string>
-    <string name="month_shortest_november">L</string>
-    <string name="month_shortest_december">G</string>
-
-    <string name="day_of_week_long_sunday">sekmadienis</string>
-    <string name="day_of_week_long_monday">pirmadienis</string>
-    <string name="day_of_week_long_tuesday">antradienis</string>
-    <string name="day_of_week_long_wednesday">trečiadienis</string>
-    <string name="day_of_week_long_thursday">ketvirtadienis</string>
-    <string name="day_of_week_long_friday">penktadienis</string>
-    <string name="day_of_week_long_saturday">šeštadienis</string>
-
-    <string name="day_of_week_medium_sunday">Sk</string>
-    <string name="day_of_week_medium_monday">Pr</string>
-    <string name="day_of_week_medium_tuesday">An</string>
-    <string name="day_of_week_medium_wednesday">Tr</string>
-    <string name="day_of_week_medium_thursday">Kt</string>
-    <string name="day_of_week_medium_friday">Pn</string>
-    <string name="day_of_week_medium_saturday">Št</string>
-
-    <string name="day_of_week_short_sunday">Sk</string>
-    <string name="day_of_week_short_monday">Pr</string>
-    <string name="day_of_week_short_tuesday">An</string>
-    <string name="day_of_week_short_wednesday">Tr</string>
-    <string name="day_of_week_short_thursday">Kt</string>
-    <string name="day_of_week_short_friday">Pn</string>
-    <string name="day_of_week_short_saturday">Št</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">P</string>
-    <string name="day_of_week_shortest_tuesday">A</string>
-    <string name="day_of_week_shortest_wednesday">T</string>
-    <string name="day_of_week_shortest_thursday">K</string>
-    <string name="day_of_week_shortest_friday">P</string>
-    <string name="day_of_week_shortest_saturday">Š</string>
-
-    <string name="am">priešpiet</string>
-    <string name="pm">popiet</string>
-    <string name="yesterday">vakar</string>
-    <string name="today">šiandien</string>
-    <string name="tomorrow">rytoj</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
diff --git a/core/res/res/values-lt/donottranslate-cldr.xml b/core/res/res/values-lt/donottranslate-cldr.xml
index 8a2c0f4..b1a94f3 100644
--- a/core/res/res/values-lt/donottranslate-cldr.xml
+++ b/core/res/res/values-lt/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Sausis</string>
-    <string name="month_long_standalone_february">Vasaris</string>
-    <string name="month_long_standalone_march">Kovas</string>
-    <string name="month_long_standalone_april">Balandis</string>
-    <string name="month_long_standalone_may">Gegužė</string>
-    <string name="month_long_standalone_june">Birželis</string>
-    <string name="month_long_standalone_july">Liepa</string>
-    <string name="month_long_standalone_august">Rugpjūtis</string>
-    <string name="month_long_standalone_september">Rugsėjis</string>
-    <string name="month_long_standalone_october">Spalis</string>
-    <string name="month_long_standalone_november">Lapkritis</string>
-    <string name="month_long_standalone_december">Gruodis</string>
-
-    <string name="month_long_january">sausio</string>
-    <string name="month_long_february">vasario</string>
-    <string name="month_long_march">kovo</string>
-    <string name="month_long_april">balandžio</string>
-    <string name="month_long_may">gegužės</string>
-    <string name="month_long_june">birželio</string>
-    <string name="month_long_july">liepos</string>
-    <string name="month_long_august">rugpjūčio</string>
-    <string name="month_long_september">rugsėjo</string>
-    <string name="month_long_october">spalio</string>
-    <string name="month_long_november">lapkričio</string>
-    <string name="month_long_december">gruodžio</string>
-
-    <string name="month_medium_january">Sau</string>
-    <string name="month_medium_february">Vas</string>
-    <string name="month_medium_march">Kov</string>
-    <string name="month_medium_april">Bal</string>
-    <string name="month_medium_may">Geg</string>
-    <string name="month_medium_june">Bir</string>
-    <string name="month_medium_july">Lie</string>
-    <string name="month_medium_august">Rgp</string>
-    <string name="month_medium_september">Rgs</string>
-    <string name="month_medium_october">Spl</string>
-    <string name="month_medium_november">Lap</string>
-    <string name="month_medium_december">Grd</string>
-
-    <string name="month_shortest_january">S</string>
-    <string name="month_shortest_february">V</string>
-    <string name="month_shortest_march">K</string>
-    <string name="month_shortest_april">B</string>
-    <string name="month_shortest_may">G</string>
-    <string name="month_shortest_june">B</string>
-    <string name="month_shortest_july">L</string>
-    <string name="month_shortest_august">R</string>
-    <string name="month_shortest_september">R</string>
-    <string name="month_shortest_october">S</string>
-    <string name="month_shortest_november">L</string>
-    <string name="month_shortest_december">G</string>
-
-    <string name="day_of_week_long_sunday">sekmadienis</string>
-    <string name="day_of_week_long_monday">pirmadienis</string>
-    <string name="day_of_week_long_tuesday">antradienis</string>
-    <string name="day_of_week_long_wednesday">trečiadienis</string>
-    <string name="day_of_week_long_thursday">ketvirtadienis</string>
-    <string name="day_of_week_long_friday">penktadienis</string>
-    <string name="day_of_week_long_saturday">šeštadienis</string>
-
-    <string name="day_of_week_medium_sunday">Sk</string>
-    <string name="day_of_week_medium_monday">Pr</string>
-    <string name="day_of_week_medium_tuesday">An</string>
-    <string name="day_of_week_medium_wednesday">Tr</string>
-    <string name="day_of_week_medium_thursday">Kt</string>
-    <string name="day_of_week_medium_friday">Pn</string>
-    <string name="day_of_week_medium_saturday">Št</string>
-
-    <string name="day_of_week_short_sunday">Sk</string>
-    <string name="day_of_week_short_monday">Pr</string>
-    <string name="day_of_week_short_tuesday">An</string>
-    <string name="day_of_week_short_wednesday">Tr</string>
-    <string name="day_of_week_short_thursday">Kt</string>
-    <string name="day_of_week_short_friday">Pn</string>
-    <string name="day_of_week_short_saturday">Št</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">P</string>
-    <string name="day_of_week_shortest_tuesday">A</string>
-    <string name="day_of_week_shortest_wednesday">T</string>
-    <string name="day_of_week_shortest_thursday">K</string>
-    <string name="day_of_week_shortest_friday">P</string>
-    <string name="day_of_week_shortest_saturday">Š</string>
-
-    <string name="am">priešpiet</string>
-    <string name="pm">popiet</string>
-    <string name="yesterday">vakar</string>
-    <string name="today">šiandien</string>
-    <string name="tomorrow">rytoj</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 54badb6..f2ad504 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefono parinktys"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Ekrano užraktas"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Išjungti maitinimą"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Pranešimas apie triktį"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Pranešti apie triktį"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Bus surinkta informacija apie dabartinę įrenginio būseną ir išsiųsta el. pašto pranešimu. Šiek tiek užtruks, kol pranešimas apie triktį bus paruoštas siųsti; būkite kantrūs."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Tylus režimas"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Garsas IŠJUNGTAS"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Garsas ĮJUNGTAS"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Jūsų pranešimai"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Skaitykite ir rašykite SMS, el. laiškus ir kitus pranešimus."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Asmeninė informacija"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Tiesioginė prieiga prie kontaktų ir kalendoriaus, išsaugotų planšetiniame kompiuteryje."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Tiesioginė prieiga prie adresatų ir kalendoriaus, saugomų telefone."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Tiesioginė prieiga prie informacijos, saugomos kontaktinėje kortelėje."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Socialinė informacija"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Tiesioginė prieiga prie kontaktų ir socialinių ryšių informacijos."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Jūsų vieta"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Stebėti fizinę vietą."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Tinklo ryšys"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Pasiekti įvairias tinklo funkcijas."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Pasiekti įrenginius ir tinklus naudojant „Bluetooth“."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Garso nustatymai"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Keisti garso nustatymus."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Paveikia akumuliatorių"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Naudoti funkcijas, galinčias greitai iškrauti akumuliatorių."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalendorius"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Tiesioginė prieiga prie kalendoriaus ir įvykių."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Skaityti naudotojo žodyną"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Skaityti žodžius naudotojo žodyne."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Rašyti į naudotojo žodyną"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Pridėti žodžius į naudotojo žodyną."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Žymės ir istorija"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Tiesioginė prieiga prie žymių ir naršyklės istorijos."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Signalas"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Nustatyti žadintuvo signalą."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Balso paštas"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Tiesioginė prieiga prie balso pašto."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofonas"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Tiesioginė prieiga prie mikrofono, kad būtų galima įrašyti garsą."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Fotoaparatas"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Tiesioginė prieiga prie fotoaparato, kad būtų galima fotografuoti vaizdus arba įrašyti vaizdo įrašus."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Programų informacija"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Galimybė paveikti kitų įrenginio programų veikimą."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Ekrano fonas"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Keisti įrenginio ekrano fono nustatymus."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Laikrodis"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Keisti įrenginio laiką arba laiko juostą."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Būsenos juosta"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Keisti įrenginio būsenos juostos nustatymus."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Sinchronizavimo nustatymai"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Prieiga prie sinchronizavimo nustatymų."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Jūsų paskyros"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Pasiekite galimas paskyras."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Aparatinės įrangos valdikliai"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Žemesnio lygio prieiga prie sistemos ir jos valdymas."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Kūrėjo įrankiai"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funkcijos reikalingos tik programos kūrėjams."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Kitų programų naudotojo sąsaja"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Paveikti kitų programų naudotojo sąsają."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Saugykla"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Pasiekti USB atmintinę."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Pasiekite SD kortelę."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Leidžiama programai gauti ir apdoroti WAP pranešimus. Šis leidimas apima galimybę stebėti ar ištrinti jums siunčiamus pranešimus jums jų neparodžius."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"nuskaityti vykdomas programas"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Leidžiama programai nuskaityti informaciją apie šiuo ir pastaruoju metu vykdomas užduotis. Taip programa gali atrasti informacijos, kokios programos naudojamos įrenginyje."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"sąveikauti su naudotojais"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Leidžiama programai atlikti veiksmus skirtingų įrenginio naudotojų profiliuose. Kenkėjiškos programos gali pasinaudoti šiuo leidimu, kad pažeistų naudotojų saugumą."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"visa licencija, leidžianti sąveikauti su naudotojais"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Leidžiama bet kokia sąveika tarp naudotojų."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"tvarkyti naudotojus"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Leidžia programoms tvarkyti įrenginio naudotojų duomenis, įskaitant užklausų teikimą, duomenų kūrimą ir ištrynimą."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"nuskaityti veikiančių programų išsamią informaciją"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Leidžiama programai nuskaityti išsamią informaciją apie šiuo ir pastaruoju metu vykdomas užduotis. Kenkėjiškos programos gali surasti privačios informacijos apie kitas programas."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"pertvarkyti vykdomas programas"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Leidžiama programai nuskaityti vidinę sistemos būseną. Kenkėjiškos programos gali nuskaityti daug įvairios privačios ir saugios informacijos, kurios paprastai joms niekada neturėtų reikėti."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"nuskaityti ekrano turinį"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Leidžiama programai nuskaityti aktyvaus lango turinį. Kenkėjiškos programos gali bandyti išgauti viso lango turinį ir tirti visą jo tekstą, išskyrus slaptažodžius."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"laikinai įgalinti pritaikymą neįgaliesiems"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Leidžiama programai laikinai įgalinti pritaikymą neįgaliesiems įrenginyje. Kenkėjiškos programos pritaikymą neįgaliesiems gali įgalinti be naudotojo sutikimo."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"gauti lango informaciją"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Leidžiama programai iš langų tvarkytuvės gauti informaciją apie langus. Kenkėjiškos programos gali gauti informaciją, kuri skirta naudoti sistemos viduje."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrų įvykiai"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Leidžiama programai registruoti įvesties filtrą, kuriuo filtruojamas visų naudotojo įvykių srautas prieš juos išsiunčiant. Kenkėjiška programa gali kontroliuoti sistemos naudotojo sąsają be naudotojo įsikišimo."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"didinti pateiktį"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Leidžiama programai didinti pateikties turinį. Kenkėjiškos programos gali pakeisti pateikties turinį taip, kad nebūtų galima naudoti įrenginio."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"dalinis išjungimas"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Veiklos tvarkyklę perjungia į išsijungimo būseną. Neišjungia visiškai."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"neleisti perjungti programų"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Leidžiama programai valdyti didžiausią vykdomų procesų skaičių. Nereikalinga įprastoms programoms."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"priverstinai uždaryti fonines programas"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Leidžiama programai valdyti, ar veiksmai visada užbaigiami, kai jie perkeliami į foną. Nereikalinga įprastoms programoms."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"keisti akumuliatoriaus statistiką"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Leidžiama programai keisti surinktą akumuliatoriaus statistiką. Neskirta naudoti įprastoms programoms."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"skaityti akumuliatoriaus statistiką"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Leidžiama programai skaityti dabartinius išsikraunančio akumuliatoriaus naudojimo duomenis. Gali būti leidžiama programai sužinoti išsamią informaciją apie jūsų naudojamas programas."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"keisti akumuliatoriaus statistiką"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Leidžiama programai keisti surinktą akumuliatoriaus statistiką. Neskirta naudoti įprastoms programoms."</string>
     <string name="permlab_backup" msgid="470013022865453920">"valdyti sistemos atsarginę kopiją ir atkūrimą"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Leidžiama programai valdyti sistemos atsarginės kopijos ir atkūrimo mechanizmą. Neskirta naudoti įprastose programose."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"patvirtinkite visos atsarginės kopijos kūrimą arba atkurkite operaciją"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"pateikti neteisėtus langus"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Leidžiama programai kurti langus, kuriuos turėtų naudoti vidinės sistemos naudotojo sąsaja. Neskirta naudoti įprastoms programoms."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"perrašyti kitas programas"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Leidžiama programai rodyti sistemos įspėjimų langus. Kai kurie įspėjimų langai gali apimti visą ekraną."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Leidžiama programai pasinaudoti kitomis programomis ar naudotojo sąsajos dalimis. Jos gali trukdyti jums naudoti sąsają bet kokioje programoje arba pakeisti tai, ką, jūsų manymu, matote kitose programose."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"keisti visos animacijos greitį"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Leidžiama programai bet kuriuo metu keisti visą animacijos greitį (greitesnių ar lėtesnių animacijų)."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"valdyti programos prieigos raktus"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Leidžiama programai kurti ir valdyti prieigos raktus, apeinant įprastą Z tvarką. Įprastoms programoms to neturėtų prireikti."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"užfiksuoti ekraną"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Leidžiama programai laikinai užfiksuoti ekraną, kad būtų galima perkelti visą ekraną."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"paspauskite klavišus ir valdymo mygtukus"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Leidžiama programai kitoms programoms pateikti savo įvesties įvykius (klavišų paspaudimus ir kt.). Kenkėjiškos programos gali tai naudoti, kad užvaldytų planšetinį kompiuterį."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Leidžiama programai kitoms programoms pateikti savo įvesties įvykius (klavišų paspaudimus ir kt.). Kenkėjiškos programos gali tai naudoti, kad užvaldytų telefoną."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"tiesiogiai įdiegti programas"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Leidžiama programai įdiegti naujus ar atnaujintus „Android“ paketus. Kenkėjiškos programos gali tai naudoti, kad pridėtų naujų programų su nepagrįstai galingais leidimais."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"ištrinti visus programos talpyklos duomenis"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Leidžiama programai atlaisvinti planšetinio kompiuterio atmintį ištrinant programos talpyklos kataloge esančius failus. Prieiga labai ribota, dažniausiai ji suteikiama tik sistemos procesams."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Leidžiama programai atlaisvinti telefono atmintį ištrinant programos talpyklos kataloge esančius failus. Prieiga labai ribota, dažniausiai ji suteikiama tik sistemos procesams."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Leidžiama programai atlaisvinti planšetinio kompiuterio atmintinę ištrinant failus kitų programų talpykloje esančiuose kataloguose. Dėl ko kitos programos gali būti lėčiau paleidžiamos, nes joms reikia iš naujo gauti duomenis."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Leidžiama programai atlaisvinti telefono atmintinę ištrinant failus kitų programų talpykloje esančiuose kataloguose. Dėl to kitos programos gali būti lėčiau paleidžiamos, nes joms reikia iš naujo gauti duomenis."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"perkelti programos išteklius"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Leidžiama programai perkelti programos išteklius iš vidinės medijos į išorinę ir atvirkščiai."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"skaityti slaptus žurnalo duomenis"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Leidžiama programai pasiekti papildomas vietos nustatymo paslaugų teikėjų komandas. Dėl to programa gali trukdyti veikti GPS ar kitiems vietos nustatymo šaltiniams."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"leidimas įdiegti vietos teikimo įrankį"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Kurti bandomuosius imituojančius vietos nustatymo šaltinius arba įdiegti naują vietos nustatymo paslaugų teikėją. Programai leidžiama nepaisyti vietos ir (arba) būsenos, kurią pateikia kiti vietos nustatymo šaltiniai, pvz., GPS arba vietos nustatymo paslaugų teikėjai."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"tiksli (GPS) vieta"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Pasiekite tikslius vietos nustatymo šaltinius, pvz., pasaulinę padėties nustatymo sistemą, planšetiniame kompiuteryje. Kai vietos nustatymo paslaugos pasiekiamos ir įjungtos, šis leidimas suteikia teisę programai nustatyti tikslią vietą."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Pasiekite tikslius vietos nustatymo šaltinius, pvz., pasaulinę padėties nustatymo sistemą telefone. Kai vietos nustatymo paslaugos pasiekiamos ir įjungtos, šis leidimas suteikia teisę programai nustatyti tikslią vietą."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"apytikslė (pagrįsta pagal tinklą) vieta"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Pasiekite apytikslę vietą iš vietos nustatymo paslaugų teikėjų naudodami tinklo šaltinius, pvz., mobiliojo ryšio bokštą ir „Wi-Fi“. Kai šios vietos nustatymo paslaugos pasiekiamos ir įjungtos, šis leidimas suteikia teisę programai nustatyti apytikslę jūsų vietą."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"tiksli vieta (pagrįsta pagal GPS ir tinklą)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Leidžiama programai gauti jūsų tikslią vietą naudojant visuotinę vietos nustatymo sistemą (angl. „Global Positioning System“, GPS) arba tinklo vietos šaltinius, pvz., mobiliojo ryšio bokštus ir „Wi-Fi“. Šios vietos paslaugos turi būti įjungtos ir pasiekiamos įrenginyje, kad programa galėtų jas naudoti. Programos gali tai naudoti jūsų vietai nustatyti bei eikvoti papildomą akumuliatoriaus energiją."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"apytikslė vieta (pagrįsta pagal tinklą)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Leidžiama programai gauti jūsų apytikslę vietą. Ši vieta gaunama vietos paslaugų naudojant tinklo vietos šaltinius, pvz., mobiliojo ryšio bokštus ir „Wi-Fi“. Šios vietos paslaugos turi būti įjungtos ir pasiekiamos įrenginyje, kad programa galėtų jas naudoti. Programos gali tai naudoti jūsų apytikslei vietai nustatyti."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"pasiekti „SurfaceFlinger“"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Leidžiama programai naudoti „SurfaceFlinger“ žemo lygio funkcijas."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"skaityti kadrų buferį"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Leidžiama programai skaityti rėmelio buferio turinį."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"konfigūruoti „Wi-Fi“ pateiktis"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Leidžiama programai konfigūruoti ir prisijungti prie „Wi-Fi“ pateikčių."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"valdyti „Wi-Fi“ pateiktis"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Leidžiama programai valdyti „Wi-Fi“ pateikčių žemo lygio funkcijas."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"keisti garso nustatymus"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Leidžiama programai keisti visuotinius garso nustatymus, pvz., garsumą ir tai, kuris garsiakalbis naudojamas išvesčiai."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"įrašyti garsą"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"pasiekti „Bluetooth“ nustatymus"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Leidžiama programai konfigūruoti vietinį „Bluetooth“ planšetinį kompiuterį ir atrasti nuotolinius įrenginius bei su jais susieti."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Leidžiama programai konfigūruoti vietinį „Bluetooth“ telefoną ir atrasti bei susieti su nuotoliniais įrenginiais."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Žiūrėti „WiMAX“ ryšius"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"prisijungti prie WiMAX ir atsijungti nuo jo"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Leidžiama programai nustatyti, ar įgalintas „WiMAX“, ir informaciją apie visus prijungtus tinklus."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Keisti „WiMAX“ būseną"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Leidžia programai prijungti planšetinį kompiuterį prie „WiMAX“ ryšio tinklų ir nuo jų atjungti."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Leidžiama programai keisti šiuo metu sinchronizuojamus sklaidos kanalus. Kenkėjiškos programos gali pakeisti sinchronizuojamus sklaidos kanalus."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"skaityti terminus, kuriuos pridėjote į žodyną"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Leidžiama programai skaityti visus žodžius, vardus ir frazes, kuriuos naudotojas išsaugojo naudotojo žodyne."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"rašyti naudotojo nustatytame žodyne"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"pridėti žodžių prie naudotojo apibrėžto žodyno"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Leidžiama programai rašyti naujus žodžius į naudotojo žodyną."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"prieigos prie apsaugotos saugyklos tikrinimas"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"prieigos prie apsaugotos saugyklos tikrinimas"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Leidž. progr. tikr. USB atm., kuri bus pasiek. ateityje naud. kt. įreng., leidimą."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Leidžia progr. tikr. leidimą USB atm., kuri bus vėlesn. įreng."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Leidžiama programai tikrinti SD kortelės, kuri bus pasiekiama ateityje naudojant kitus įrenginius, leidimą."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"keisti / trinti USB atm. turinį"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"keisti arba trinti SD kortelės turinį"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Leidžiama programai rašyti į SD kortelę."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"keisti / ištr. vid. med. atm. tur."</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Leidžiama programai keisti vidinės medijos saugyklos turinį."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"pasiekti visų naud. išor. atm."</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Leidžiama programai pasiekti visų naudotojų išorinę atmintinę."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"pasiekti talpyklos failų sistemą"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Leidžiama programai skaityti talpyklos failų sistemą ir į ją rašyti."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"skambinti / priimti skambučius internetu"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Reikalauti, kad saugomos programos duomenys būtų šifruoti."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Neleisti fotoaparatų"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Neleisti naudoti visų įrenginio fotoaparatų."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Funkcijų išjung. klaviat. aps."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Naudojant klaviatūros apsaugos funkciją, neleisti naudoti kai kurių funkcijų."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Pagrindinis"</item>
     <item msgid="869923650527136615">"Mobilusis"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Bandykite dar kartą"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Viršijote maksimalų atrakinimo pagal veidą bandymų skaičių"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Įkraunama, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Įkrauta."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Įkrauta"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Prijunkite kroviklį."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nėra SIM kortelės."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Nėra SIM kortelės"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Planšetiniame kompiuteryje nėra SIM kortelės."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefone nėra SIM kortelės."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Įdėkite SIM kortelę."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Šablonas išvalytas"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Pridėtas langelis"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Šablonas užbaigtas"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Pridėti valdiklį."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Tuščia"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Atrakinimo sritis išplėsta."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Atrakinimo sritis sutraukta."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Valdiklis <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Naudotojo pasirinkimo valdiklis"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Būsena"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Fotoaparatas"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Medijos valdikliai"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Valdiklių pertvarkymas pradėtas."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Valdiklių pertvarkymas baigtas."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Valdiklis <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> ištrintas."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Išplėsti atrakinimo sritį."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Atrakinimas slystant."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Atrakinimas pagal piešinį."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Atrakinimas pagal veidą."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Atrakinimas įvedus PIN kodą."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Atrakinimas įvedus slaptažodį."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Atrakinimo pagal piešinį sritis."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Slydimo sritis."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopijuoti URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Pasirinkti tekstą"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Teksto pasirinkimas"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"pridėti prie žodyno"</string>
-    <string name="deleteText" msgid="7070985395199629156">"ištrinti"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Pridėti prie žodyno"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Ištrinti"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Įvesties būdas"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksto veiksmai"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Mažėja laisvos saugyklos vietos"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Atidaryti galimus „Wi-Fi“ tinklus"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Prisijungti prie „Wi-Fi“ ryšio tinklo"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Prisijungti prie tinklo"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nepavyko prisijungti prie „Wi-Fi“"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" turi prastą interneto ryšį."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Skirta:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Įveskite reikiamą PIN kodą:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN kodas:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefonas bus laikinai atjungtas nuo „Wi-Fi“, kol bus prijungtas prie „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“"</string>
     <string name="select_character" msgid="3365550120617701745">"Įterpti simbolį"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS pranešimų siuntimas"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"Naudojant &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; siunčiama daug SMS pranešimų. Ar norite leisti šiai programai toliau siųsti pranešimus?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Leisti"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Uždrausti"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; norėtų išsiųsti pranešimą šiuo adresu: &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457"><font fgcolor="#ffffb060">"Gali būti taikomi mokesčiai"</font>" paskyroje mobiliesiems."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Bus taikomi mokesčiai paskyroje mobiliesiems."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Siųsti"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Atšaukti"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Atsiminti mano pasirinkimą"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Tai vėliau galėsite pakeisti skiltyje „Nustatymai“ &gt; „Programos“"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Visada leisti"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Niekada neleisti"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM kortelė pašalinta"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilusis tinklas bus nepasiekiamas, kol nepaleisite iš naujo įdėję tinkamą SIM kortelę."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Atlikta"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Nustatyti datą"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Nustatyti"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Baigta"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Numatytasis"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Nereikia leidimų"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Slėpti"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Rodyti viską"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NAUJAS: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NAUJAS: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Pateikė „<xliff:g id="APP_NAME">%1$s</xliff:g>“."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Nereikia leidimų"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"tai gali kainuoti"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB didelės talpos atmintis"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB prijungtas"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Prisijungėte prie kompiuterio per USB. Jei norite kopijuoti failus iš kompiuterio į „Android“ USB atmintį ir atvirkščiai, palieskite toliau pateiktą mygtuką."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN suaktyvino „<xliff:g id="APP">%s</xliff:g>“"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Palieskite, kad valdytumėte tinklą."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Prisijungta prie <xliff:g id="SESSION">%s</xliff:g>. Jei norite valdyti tinklą, palieskite."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Prisijungiama prie visada įjungto VPN…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Prisijungta prie visada įjungto VPN"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Visada įjungto VPN klaida"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Palieskite, kad iš naujo nustatytumėte ryšį"</string>
     <string name="upload_file" msgid="2897957172366730416">"Pasirinkti failą"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nepasirinktas joks failas"</string>
     <string name="reset" msgid="2448168080964209908">"Atstatyti"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Bendrinti"</string>
     <string name="find" msgid="4808270900322985960">"Ieškoti"</string>
     <string name="websearch" msgid="4337157977400211589">"Žiniat. paieška"</string>
+    <string name="find_next" msgid="5742124618942193978">"Rasti kitą"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Rasti ankstesnį"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Vietos užklausa iš <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Vietos užklausa"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Užklausą pateikė <xliff:g id="NAME">%1$s</xliff:g> („<xliff:g id="SERVICE">%2$s</xliff:g>“)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefonas"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Ausinės"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Doko garsiakalbiai"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI garsas"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"„Bluetooth“ garsas"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Atlikta"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Medijos išvestis"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Nuskaitoma..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Jungiama..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Pasiekiama"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Nepasiekiama"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Integruotas ekranas"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI ekranas"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Perdanga nr. <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"„<xliff:g id="NAME">%1$s</xliff:g>“: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> tašk. colyje"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Prijungtas belaidis monitorius"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Šis ekranas rodomas kitame įrenginyje"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Atjungti"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Skambutis pagalbos numeriu"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Pamiršau atrakinimo piešinį"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Netinkamas atrakinimo piešinys"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Netinkamas slaptažodis"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Netinkamas PIN kodas"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Bandyti dar kartą po <xliff:g id="NUMBER">%d</xliff:g> sek."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Nupieškite atrakinimo piešinį"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Įveskite SIM PIN kodą"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Įveskite PIN kodą"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Įveskite slaptažodį"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"Dabar SIM neleidžiama. Jei norite tęsti, įveskite PUK kodą. Jei reikia išsamios informacijos, susisiekite su operatoriumi."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Įveskite pageidaujamą PIN kodą"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Patvirtinkite pageidaujamą PIN kodą"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Atrakinama SIM kortelė…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Netinkamas PIN kodas."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Įveskite PIN kodą, sudarytą iš 4–8 skaičių."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK kodas turėtų būti mažiausiai 8 skaitmenų."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Pakartotinai įveskite tinkamą PUK kodą. Pakartotinai bandant SIM bus neleidžiama visam laikui."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN kodai neatitinka"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Per daug atrakinimo piešinių bandymų"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Jei norite atrakinti, prisijunkite naudodami „Google“ paskyrą."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Naudotojo vardas (el. paštas)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Slaptažodis"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Prisijungti"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Netinkamas naudotojo vardas ar slaptažodis."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Pamiršote naudotojo vardą ar slaptažodį?"\n"Apsilankykite šiuo adresu: "<b>"google.com/accounts/recovery"</b></string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Tikrinama paskyra…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"PIN kodą netinkamai įvedėte <xliff:g id="NUMBER_0">%d</xliff:g> k. "\n\n"Bandykite dar kartą po <xliff:g id="NUMBER_1">%d</xliff:g> sek."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Neteisingai įvedėte slaptažodį <xliff:g id="NUMBER_0">%d</xliff:g> k. "\n\n"Bandykite dar kartą po <xliff:g id="NUMBER_1">%d</xliff:g> sek."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Netinkamai nupiešėte atrakinimo piešinį <xliff:g id="NUMBER_0">%d</xliff:g> k. "\n\n"Bandykite dar kartą po <xliff:g id="NUMBER_1">%d</xliff:g> sek."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"<xliff:g id="NUMBER_0">%d</xliff:g> k. bandėte netinkamai atrakinti planšetinį kompiuterį. Po dar <xliff:g id="NUMBER_1">%d</xliff:g> nesėkm. band. planšetiniame kompiuteryje bus iš naujo nustatyti numatytieji gamyklos nustatymai ir bus prarasti visi naudotojo duomenys."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"<xliff:g id="NUMBER_0">%d</xliff:g> k. bandėte netinkamai atrakinti telefoną. Po dar <xliff:g id="NUMBER_1">%d</xliff:g> nesėkm. band. telefone bus iš naujo nustatyti numatytieji gamyklos nustatymai ir bus prarasti visi naudotojo duomenys."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"<xliff:g id="NUMBER">%d</xliff:g> k. bandėte netinkamai atrakinti planšetinį kompiuterį. Planšetiniame kompiuteryje bus iš naujo nustatyti numatytieji gamyklos nustatymai."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"<xliff:g id="NUMBER">%d</xliff:g> k. bandėte netinkamai atrakinti telefoną. Telefone bus iš naujo nustatyti numatytieji gamyklos nustatymai."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Netinkamai nupiešėte atrakinimo piešinį <xliff:g id="NUMBER_0">%d</xliff:g> k. Po dar <xliff:g id="NUMBER_1">%d</xliff:g> nesėkm. band. būsite paprašyti atrakinti planšetinį kompiuterį naudodami „Google“ prisijungimo duomenis."\n\n" Bandykite dar kartą po <xliff:g id="NUMBER_2">%d</xliff:g> sek."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Netinkamai nupiešėte atrakinimo piešinį <xliff:g id="NUMBER_0">%d</xliff:g> k. Po dar <xliff:g id="NUMBER_1">%d</xliff:g> nesėkm. band. būsite paprašyti atrakinti telefoną naudodami „Google“ prisijungimo duomenis."\n\n" Bandykite dar kartą po <xliff:g id="NUMBER_2">%d</xliff:g> sek."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Pašalinti"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Padidinti garsumą viršijant saugų lygį?"\n"Ilgai klausantis dideliu garsumu gali sutrikti klausa."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Laikykite palietę dviem pirštais, kad įgalintumėte pritaikymo neįgaliesiems režimą."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Pritaikymas neįgaliesiems įgalintas."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Pritaikymo neįgaliesiems režimas atšauktas."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Dabartinis naudotojas: <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Savininkas"</string>
 </resources>
diff --git a/core/res/res/values-lv-rLV/donottranslate-cldr.xml b/core/res/res/values-lv-rLV/donottranslate-cldr.xml
index 9dbc5e05..3922f6b 100644
--- a/core/res/res/values-lv-rLV/donottranslate-cldr.xml
+++ b/core/res/res/values-lv-rLV/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">janvāris</string>
-    <string name="month_long_standalone_february">februāris</string>
-    <string name="month_long_standalone_march">marts</string>
-    <string name="month_long_standalone_april">aprīlis</string>
-    <string name="month_long_standalone_may">maijs</string>
-    <string name="month_long_standalone_june">jūnijs</string>
-    <string name="month_long_standalone_july">jūlijs</string>
-    <string name="month_long_standalone_august">augusts</string>
-    <string name="month_long_standalone_september">septembris</string>
-    <string name="month_long_standalone_october">oktobris</string>
-    <string name="month_long_standalone_november">novembris</string>
-    <string name="month_long_standalone_december">decembris</string>
-
-    <string name="month_long_january">janvāris</string>
-    <string name="month_long_february">februāris</string>
-    <string name="month_long_march">marts</string>
-    <string name="month_long_april">aprīlis</string>
-    <string name="month_long_may">maijs</string>
-    <string name="month_long_june">jūnijs</string>
-    <string name="month_long_july">jūlijs</string>
-    <string name="month_long_august">augusts</string>
-    <string name="month_long_september">septembris</string>
-    <string name="month_long_october">oktobris</string>
-    <string name="month_long_november">novembris</string>
-    <string name="month_long_december">decembris</string>
-
-    <string name="month_medium_january">janv.</string>
-    <string name="month_medium_february">febr.</string>
-    <string name="month_medium_march">marts</string>
-    <string name="month_medium_april">apr.</string>
-    <string name="month_medium_may">maijs</string>
-    <string name="month_medium_june">jūn.</string>
-    <string name="month_medium_july">jūl.</string>
-    <string name="month_medium_august">aug.</string>
-    <string name="month_medium_september">sept.</string>
-    <string name="month_medium_october">okt.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">dec.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">svētdiena</string>
-    <string name="day_of_week_long_monday">pirmdiena</string>
-    <string name="day_of_week_long_tuesday">otrdiena</string>
-    <string name="day_of_week_long_wednesday">trešdiena</string>
-    <string name="day_of_week_long_thursday">ceturtdiena</string>
-    <string name="day_of_week_long_friday">piektdiena</string>
-    <string name="day_of_week_long_saturday">sestdiena</string>
-
-    <string name="day_of_week_medium_sunday">Sv</string>
-    <string name="day_of_week_medium_monday">Pr</string>
-    <string name="day_of_week_medium_tuesday">Ot</string>
-    <string name="day_of_week_medium_wednesday">Tr</string>
-    <string name="day_of_week_medium_thursday">Ce</string>
-    <string name="day_of_week_medium_friday">Pk</string>
-    <string name="day_of_week_medium_saturday">Se</string>
-
-    <string name="day_of_week_short_sunday">Sv</string>
-    <string name="day_of_week_short_monday">Pr</string>
-    <string name="day_of_week_short_tuesday">Ot</string>
-    <string name="day_of_week_short_wednesday">Tr</string>
-    <string name="day_of_week_short_thursday">Ce</string>
-    <string name="day_of_week_short_friday">Pk</string>
-    <string name="day_of_week_short_saturday">Se</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">P</string>
-    <string name="day_of_week_shortest_tuesday">O</string>
-    <string name="day_of_week_shortest_wednesday">T</string>
-    <string name="day_of_week_shortest_thursday">C</string>
-    <string name="day_of_week_shortest_friday">P</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">vakar</string>
-    <string name="today">šodien</string>
-    <string name="tomorrow">rīt</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-lv/donottranslate-cldr.xml b/core/res/res/values-lv/donottranslate-cldr.xml
index 10dcd35..ec768bc 100644
--- a/core/res/res/values-lv/donottranslate-cldr.xml
+++ b/core/res/res/values-lv/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">janvāris</string>
-    <string name="month_long_standalone_february">februāris</string>
-    <string name="month_long_standalone_march">marts</string>
-    <string name="month_long_standalone_april">aprīlis</string>
-    <string name="month_long_standalone_may">maijs</string>
-    <string name="month_long_standalone_june">jūnijs</string>
-    <string name="month_long_standalone_july">jūlijs</string>
-    <string name="month_long_standalone_august">augusts</string>
-    <string name="month_long_standalone_september">septembris</string>
-    <string name="month_long_standalone_october">oktobris</string>
-    <string name="month_long_standalone_november">novembris</string>
-    <string name="month_long_standalone_december">decembris</string>
-
-    <string name="month_long_january">janvāris</string>
-    <string name="month_long_february">februāris</string>
-    <string name="month_long_march">marts</string>
-    <string name="month_long_april">aprīlis</string>
-    <string name="month_long_may">maijs</string>
-    <string name="month_long_june">jūnijs</string>
-    <string name="month_long_july">jūlijs</string>
-    <string name="month_long_august">augusts</string>
-    <string name="month_long_september">septembris</string>
-    <string name="month_long_october">oktobris</string>
-    <string name="month_long_november">novembris</string>
-    <string name="month_long_december">decembris</string>
-
-    <string name="month_medium_january">janv.</string>
-    <string name="month_medium_february">febr.</string>
-    <string name="month_medium_march">marts</string>
-    <string name="month_medium_april">apr.</string>
-    <string name="month_medium_may">maijs</string>
-    <string name="month_medium_june">jūn.</string>
-    <string name="month_medium_july">jūl.</string>
-    <string name="month_medium_august">aug.</string>
-    <string name="month_medium_september">sept.</string>
-    <string name="month_medium_october">okt.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">dec.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">svētdiena</string>
-    <string name="day_of_week_long_monday">pirmdiena</string>
-    <string name="day_of_week_long_tuesday">otrdiena</string>
-    <string name="day_of_week_long_wednesday">trešdiena</string>
-    <string name="day_of_week_long_thursday">ceturtdiena</string>
-    <string name="day_of_week_long_friday">piektdiena</string>
-    <string name="day_of_week_long_saturday">sestdiena</string>
-
-    <string name="day_of_week_medium_sunday">Sv</string>
-    <string name="day_of_week_medium_monday">Pr</string>
-    <string name="day_of_week_medium_tuesday">Ot</string>
-    <string name="day_of_week_medium_wednesday">Tr</string>
-    <string name="day_of_week_medium_thursday">Ce</string>
-    <string name="day_of_week_medium_friday">Pk</string>
-    <string name="day_of_week_medium_saturday">Se</string>
-
-    <string name="day_of_week_short_sunday">Sv</string>
-    <string name="day_of_week_short_monday">Pr</string>
-    <string name="day_of_week_short_tuesday">Ot</string>
-    <string name="day_of_week_short_wednesday">Tr</string>
-    <string name="day_of_week_short_thursday">Ce</string>
-    <string name="day_of_week_short_friday">Pk</string>
-    <string name="day_of_week_short_saturday">Se</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">P</string>
-    <string name="day_of_week_shortest_tuesday">O</string>
-    <string name="day_of_week_shortest_wednesday">T</string>
-    <string name="day_of_week_shortest_thursday">C</string>
-    <string name="day_of_week_shortest_friday">P</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">vakar</string>
-    <string name="today">šodien</string>
-    <string name="tomorrow">rīt</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 91d9415..ee0b023 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Tālruņa opcijas"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Ekrāna bloķētājs"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Strāvas padeve ir izslēgta."</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Kļūdu ziņojums"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Kļūdu ziņojuma sagatavošana"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Veicot šo darbību, tiks apkopota informācija par jūsu ierīces pašreizējo stāvokli un nosūtīta e-pasta ziņojuma veidā. Kļūdu ziņojuma pabeigšanai un nosūtīšanai var būt nepieciešams laiks. Lūdzu, esiet pacietīgs."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Klusuma režīms"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Skaņa ir IZSLĒGTA."</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Skaņa ir IESLĒGTA."</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Jūsu ziņojumi"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Lasiet un rakstiet īsziņas, e-pasta un citus ziņojumus."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Personas informācija"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Tieša piekļuve planšetdatorā saglabātajām kontaktpersonām un kalendāram."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Tiešā piekļuve tālrunī saglabātajām kontaktpersonām un kalendāram."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Tieša piekļuve jūsu vizītkartē saglabātajai informācijai par jums."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Jūsu sociālo tīklu informācija"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Tieša piekļuve informācijai par jūsu kontaktpersonām un sociālajiem savienojumiem."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Jūsu atrašanās vieta"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Pārrauga jūsu fizisko atrašanās vietu."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Tīkla sakari"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Piekļūst dažādām tīkla funkcijām."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Piekļūt ierīcēm vai tīkliem, izmantojot tehnoloģiju Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Audio iestatījumi"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Audio iestatījumu maiņa."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Ietekme uz akumulatora darbību"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Tādu funkciju izmantošana, kas patērē daudz akumulatora enerģijas."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalendārs"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Tieša piekļuve kalendāram un pasākumiem."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Lietotāja vārdnīcas lasīšana"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Lasīt vārdus lietotāja vārdnīcā."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Rakstīšana lietotāja vārdnīcā"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Pievienot vārdus lietotāja vārdnīcai."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Grāmatzīmes un vēsture"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Tieša piekļuve grāmatzīmēm un pārlūkprogrammas vēsturei."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Signāls"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Modinātājpulksteņa iestatīšana."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Balss pasts"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Tieša piekļuve balss pastam."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofons"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Tieša piekļuve mikrofonam, lai ierakstītu audio."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Tieša piekļuve kamerai, lai uzņemtu attēlus vai videoklipus."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Informācija par jūsu lietojumprogrammām"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Spēja ietekmēt citu ierīcē esošo lietojumprogrammu darbību."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Fona tapete"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Ierīces fona tapetes iestatījumu maiņa."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Pulkstenis"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Ierīces laika vai laika joslas maiņa."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Statusa josla"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Ierīces statusa joslas iestatījumu maiņa."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Sinhronizācijas iestatījumi"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Pieeja sinhronizācijas iestatījumiem."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Jūsu konti"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Piekļūstiet pieejamajiem kontiem."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Aparatūras vadīklas"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Sistēmas apakšējā līmeņa piekļuve un vadība."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Izstrādes rīki"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Tikai lietotņu izstrādātājiem nepieciešamās funkcijas."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Citu lietojumprogrammu lietotāja saskarnes"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Ietekme uz citu lietojumprogrammu lietotāja saskarni."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Krātuve"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Piekļūst USB krātuvei."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Piekļūstiet SD kartei."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Ļauj lietotnei saņemt un apstrādāt WAP ziņojumus. Šī atļauja ietver iespēju pārraudzīt vai dzēst jums nosūtītos ziņojumus, neparādot tos jums."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"izgūt izmantotās lietotnes"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Ļauj lietotnei izgūt informāciju par pašreiz un nesen darbinātajiem uzdevumiem. Tādējādi lietotne var atklāt informāciju par ierīcē izmantotajām lietojumprogrammām."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"darboties visos lietotāju kontos"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Ļauj lietotnei veikt darbības vairāku ierīces lietotāju kontos. Ļaunprātīgas lietotnes var izmantot šo atļauju, lai apdraudētu lietotāju kontu drošību."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"pilna licence ar atļauju darboties visos lietotāju kontos"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Ļauj veikt jebkādas darbības visos lietotāju kontos."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"Lietotāju pārvaldība"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Ļauj lietotnēm pārvaldīt ierīces lietotājus, tostarp izveidot un dzēst lietotājus un veidot vaicājumus."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"Informācijas izguve par izmantotajām lietotnēm"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Ļauj lietotnei izgūt informāciju par šobrīd un nesen veiktajiem uzdevumiem. Ļaunprātīgas lietotnes var atklāt privātu informāciju par citām lietotnēm."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"pārkārtot izmantotās lietotnes"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Ļauj lietotnei izgūt sistēmas iekšējo statusu. Ļaunprātīgas lietotnes var izgūt dažādu privātu un drošu informāciju, kas parasti tām nav nepieciešama."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"Ekrāna satura iegūšana"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Ļauj lietotnei izgūt aktīva loga saturu. Ļaunprātīgas lietotnes var izgūt visu loga saturu un pārbaudīt visu tā tekstu, izņemot paroles."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Īslaicīga pieejamības režīma iespējošana"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Ļauj lietojumprogrammai īslaicīgi ierīcē iespējot pieejamības režīmu. Ļaunprātīgas lietotnes var iespējot pieejamības režīmu bez lietotāja atļaujas."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"Izgūt informāciju par logiem"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Ļauj lietojumprogrammai no logu pārvaldnieka izgūt informāciju par logiem. Ļaunprātīgas lietotnes var izgūt informāciju, kas ir paredzēta iekšējai izmantošanai sistēmā."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"Filtrēt notikumus"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Ļauj lietojumprogrammai reģistrēt ieejas filtru, kas filtrē visu lietotāja notikumu straumi, pirms notikumi tiek nosūtīti. Ļaunprātīga lietotne var kontrolēt sistēmas lietotāja saskarni, nejautājot lietotājam."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"displeja palielināšana"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Ļauj lietojumprogrammai palielināt displeja saturu. Ļaunprātīgas lietotnes var pārveidot displeja saturu tā, ka ierīce kļūst nelietojama."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"daļēja izslēgšana"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Liek darbību pārvaldniekam pāriet izslēgšanas stāvoklī. Neveic pilnīgu izslēgšanu."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"novērst lietojumprogrammu pārslēgšanu"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Ļauj lietotnei kontrolēt izpildāmo procesu maksimālo skaitu. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"veikt fonā darbojošos lietotņu piespiedu aizvēršanu"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Ļauj lietotnei kontrolēt, vai darbības vienmēr tiek pabeigtas, tiklīdz tās nonāk fonā. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"pārveidot akumulatora statistiku"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Ļauj lietotnei modificēt apkopoto statistiku par akumulatoru. Atļauja neattiecas uz parastām lietotnēm."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"akumulatora statistikas lasīšana"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Ļauj lietojumprogrammai lasīt pašreizējos zema akumulatora enerģijas patēriņa datus. Var atļaut lietojumprogrammai iegūt detalizētu informāciju par to, kuras lietotnes izmantojat."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"akumulatora statistikas pārveidošana"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Ļauj lietotnei pārveidot apkopoto statistiku par akumulatoru. Atļauja neattiecas uz parastām lietotnēm."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontrolēt sistēmas dublējumu un atjaunošanu"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Ļauj lietotnei kontrolēt sistēmas dublēšanas un atjaunošanas mehānismu. Atļauja neattiecas uz parastām lietotnēm."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"Apstiprināt pilnu dublējumu vai atjaunot darbību"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"attēlot neautorizētus logus"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Ļauj lietotnei izveidot logus, kas paredzēti izmantošanai iekšējās sistēmas lietotāja saskarnē. Atļauja neattiecas uz parastām lietotnēm."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"zīmēt pāri citām lietotnēm"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Ļauj lietotnei rādīt sistēmas brīdinājuma logus. Atsevišķi brīdinājuma logi var tikt rādīti pa visu ekrānu."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Ļauj lietotni rādīt virs citām lietojumprogrammām vai lietotāja saskarnes daļām. Var traucēt saskarnes lietošanu jebkurā lietojumprogrammā vai mainīt citu lietojumprogrammu izskatu."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"pārveidot globālo animācijas ātrumu"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Ļauj lietotnei jebkurā laikā mainīt vispārējo animācijas ātrumu (lēnākām vai ātrākām animācijām)."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"pārvaldīt lietotnes pilnvaras"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Ļauj lietotnei veidot un pārvaldīt savas pilnvaras, apejot to parasto “Z kārtošanu”. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"attēla “iesaldēšana”"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Ļauj lietojumprogrammai īslaicīgi “iesaldēt” attēlu, lai pārietu uz pilnekrāna režīmu."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"nospiest taustiņus un vadības pogas"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Ļauj lietotnei rādīt savas ievades notikumus (nospiestos taustiņus u.c.) citās lietotnēs. Ļaunprātīgas lietotnes to var izmantot, lai pārņemtu planšetdatora vadību."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Ļauj lietotnei rādīt savas ievades notikumus (nospiestos taustiņus u.c.) citās lietotnēs. Ļaunprātīgas lietotnes to var izmantot, lai pārņemtu tālruņa vadību."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"tieši instalēt lietotnes"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Ļauj lietotnei instalēt jaunas vai atjauninātas Android pakotnes. Ļaunprātīgas lietotnes to var izmantot, lai pievienotu jaunas lietotnes ar patvaļīgi derīgām atļaujām."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"dzēst visus lietotnes kešatmiņas datus"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Ļauj lietotnei atbrīvot vietu planšetdatora atmiņā, dzēšot failus lietotnes kešatmiņas direktorijā. Piekļuve parasti ir atļauta tikai sistēmas procesam."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Ļauj lietotnei atbrīvot vietu tālruņa atmiņā, dzēšot failus lietotnes kešatmiņas direktorijā. Piekļuve parasti ir atļauta tikai sistēmas procesam."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Ļauj lietotnei atbrīvot vietu planšetdatorā, dzēšot failus citu lietojumprogrammu kešatmiņas direktorijos. Citu lietojumprogrammu palaišana var būt lēnāka, jo tajās ir atkārtoti jāizgūst dati."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Ļauj lietotnei atbrīvot vietu tālrunī, dzēšot failus citu lietojumprogrammu kešatmiņas direktorijos. Citu lietojumprogrammu palaišana var būt lēnāka, jo tajās ir atkārtoti jāizgūst dati."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"pārvietot lietotnes resursus"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Ļauj lietotnei pārvietot lietotnes resursus no iekšēja datu nesēja uz ārēju datu nesēju un otrādi."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"lasīt sensitīvus žurnāla datus"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Ļauj lietotnei piekļūt papildu atrašanās vietas noteikšanas nodrošinātāju komandām. Tas var ļaut lietotnei traucēt GPS vai citu atrašanās vietas noteikšanas avotu darbību."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"atļauja instalēt atrašanās vietas sniedzēju"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Izveido neīstus atrašanās vietas noteikšanas avotus testēšanas nolūkiem vai instalē jaunu atrašanās vietas noteikšanas nodrošinātāju. Tas ļauj lietotnei ignorēt atrašanās vietu un/vai statusu, ko norādīja citi atrašanās vietas noteikšanas avoti, piemēram, GPS vai atrašanās vietas noteikšanas nodrošinātāji."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"precīza atrašanās vieta (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Piekļūst precīzas atrašanās vietas noteikšanas avotiem, piemēram, planšetdatora globālās pozicionēšanas sistēmai. Kad atrašanās vietas noteikšanas pakalpojumi ir pieejami un ieslēgti, ar šo atļauja lietotne var noteikt jūsu precīzu atrašanās vietu."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Piekļūst precīzas atrašanās vietas noteikšanas avotiem, piemēram, tālruņa globālās pozicionēšanas sistēmai. Kad atrašanās vietas noteikšanas pakalpojumi ir pieejami un ieslēgti, ar šo atļauju lietotne var noteikt jūsu precīzu atrašanās vietu."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"aptuvena atrašanās vieta (tīklā)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Piekļūst informācijai par aptuveno atrašanās vietu no atrašanās vietas noteikšanas nodrošinātājiem, izmantojot tādus tīkla avotus kā mobilo sakaru tornis un Wi-Fi. Kad šie atrašanās vietas noteikšanas pakalpojumi ir pieejami un ir ieslēgti, ar šo atļauju lietotne var noteikt jūsu aptuveno atrašanās vietu."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"precīza atrašanās vieta (GPS un tīklā)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Ļauj lietotnei iegūt precīzu informāciju par jūsu atrašanās vietu, izmantojot globālo pozicionēšanas sistēmu (GPS) vai tīkla atrašanās vietas pakalpojumus, piemēram, mobilo sakaru torņus un Wi-Fi. Lai lietotne varētu izmantot šos atrašanās vietas pakalpojumus, ierīcē tiem ir jābūt ieslēgtiem un pieejamiem. Lietotnes var izmantot šo atļauju, lai noteiktu jūsu atrašanās vietu, un var patērēt papildu akumulatora enerģiju."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"aptuvena atrašanās vieta (tīklā)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Ļauj lietotnei iegūt informāciju par aptuvenu jūsu atrašanās vietu. Tā tiek noteikta atrašanās vietas pakalpojumos, izmantojot tīkla atrašanās vietas avotus, kā arī mobilo sakaru torņus un Wi-Fi. Lai lietotne varētu izmantot šos atrašanās vietas pakalpojumus, ierīcē tiem ir jābūt ieslēgtiem un pieejamiem. Lietotnes var izmantot šo atļauju, lai noteiktu aptuvenu jūsu atrašanās vietu."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"piekļūt SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Ļauj lietotnei lietot SurfaceFlinger zema līmeņa funkcijas."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"lasīt kadru buferi"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Ļauj lietotnei lasīt kadru bufera saturu."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"Wi-Fi displeju konfigurēšana"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Ļauj lietotnei konfigurēt Wi-Fi displejus un veidot savienojumu ar tiem."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wi-Fi displeju vadība"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Ļauj lietotnei kontrolēt zema līmeņa funkcijas Wi-Fi displejos."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"mainīt audio iestatījumus"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Ļauj lietotnei mainīt globālos audio iestatījumus, piemēram, skaļumu un izejai izmantoto skaļruni."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ierakstīt audio"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"piekļūt Bluetooth iestatījumiem"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Ļauj lietotnei konfigurēt vietējo Bluetooth planšetdatoru, kā arī atklāt attālas ierīces un savienot tās pārī."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Ļauj lietotnei konfigurēt vietējo Bluetooth tālruni, kā arī atklāt attālas ierīces un savienot tās pārī."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Skatīt WiMAX savienojumus"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX savienojuma izveide un pārtraukšana"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Ļauj lietotnei noteikt, vai WiMAX ir iespējots, un sniedz informāciju par visiem WiMAX tīkliem, ar kuriem ir izveidots savienojums."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX statusa mainīšana"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Ļauj lietotnei izveidot un pārtraukt planšetdatora savienojumu ar WiMAX tīkliem."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Ļauj lietotnei modificēt pašreizējās sinhronizētās plūsmas. Ļaunprātīgas lietotnes var mainīt jūsu sinhronizētās plūsmas."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"lasīt vārdnīcai pievienotos vārdus"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Ļauj lietotnei lasīt visus vārdus, nosaukumus un frāzes, ko lietotājs ir saglabājis lietotāja vārdnīcā."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"rakstīt lietotāja noteiktā vārdnīcā"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"vārdu pievienošana lietotāja noteiktai vārdnīcai"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Ļauj lietotnei rakstīt jaunus vārdus lietotāja vārdnīcā."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"aizsargātai krātuvei pieejamas piekļuves pārbaude"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"aizsargātai krātuvei pieejamas piekļuves pārbaude"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Ļauj lietotnei pārbaudīt atļauju USB krātuvei, kas būs pieejama turpmākajās ierīcēs."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Ļauj lietotnei pārbaudīt USB krātuves atļauju; krātuve būs pieejama turpmākajās ierīcēs."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Ļauj lietotnei pārbaudīt atļauju SD kartei, kas būs pieejama turpmākajās ierīcēs."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"mainīt vai dzēst USB atm. sat."</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"SD kartes satura pārveidošana vai dzēšana"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Ļauj lietotnei rakstīt SD kartē."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"pārv./dz.datu n.iekš.atm.sat."</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Ļauj lietotnei modificēt datu nesēja iekšējās atmiņas saturu."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"piekļ. visu liet. ārējai krāt."</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Ļauj lietotnei piekļūt visu lietotāju ārējai krātuvei."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"piekļūt kešatmiņas failu sistēmai"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Ļauj lietotnei lasīt un rakstīt kešatmiņas failu sistēmā."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"veikt/saņemt interneta zvanus"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Pieprasa, lai saglabātie lietotnes dati tiktu šifrēti."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Atspējot kameras"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Neļauj izmantot nevienu ierīces kameru."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Bloķēšanas f-jas atspējošana"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Atspējot noteiktas funkcijas taustiņslēgā."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Mājas"</item>
     <item msgid="869923650527136615">"Mobilais"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Mēģināt vēlreiz"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Ir pārsniegts maksimālais Autorizācijas pēc sejas mēģinājumu skaits."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Notiek uzlāde (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Uzlādēts."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Uzlādēts"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Pievienojiet uzlādes ierīci."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nav SIM kartes."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Nav SIM kartes"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Planšetdatorā nav SIM kartes."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Tālrunī nav SIM kartes."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Ievietojiet SIM karti."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Kombinācija notīrīta"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Šūna pievienota"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Kombinācija pabeigta"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Pievienot logrīku."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Tukšs"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Atbloķēšanas apgabals ir izvērsts."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Atbloķēšanas apgabals ir sakļauts."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Logrīks <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Lietotāju atlasītājs"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Statuss"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Kamera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Multivides vadīklas"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Logrīku pārkārtošana ir sākta."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Logrīku pārkārtošana ir pabeigta."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Logrīks <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> ir izdzēsts."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Izvērst atbloķēšanas apgabalu."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Autorizācija, velkot ar pirkstu."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Autorizācija ar kombināciju."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Autorizācija pēc sejas."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Autorizācija ar PIN kodu."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Autorizācija ar paroli."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Kombinācijas ievades apgabals."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Apgabals, kur vilkt ar pirkstu."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopēt URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Atlasīt tekstu"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Teksta atlase"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"pievienot vārdnīcai"</string>
-    <string name="deleteText" msgid="7070985395199629156">"dzēst"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Pievienot vārdnīcai"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Dzēst"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Ievades metode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksta darbības"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Paliek maz brīvas vietas"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Ir pieejami atvērti Wi-Fi tīkli."</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Pierakstieties Wi-Fi tīklā."</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Pierakstīšanās tīklā"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nevarēja izveidot savienojumu ar Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ir slikts interneta savienojums."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Kam:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Ierakstiet pieprasīto PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Tālrunis tiks īslaicīgi atvienots no Wi-Fi tīkla, kamēr būs izveidots savienojums ar ierīci <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="select_character" msgid="3365550120617701745">"Ievietojiet rakstzīmi"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Īsziņu sūtīšana"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"Lietotne &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sūta daudz īsziņu. Vai vēlaties, lai šī lietotne turpinātu sūtīt ziņojumus?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Atļaut"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Aizliegt"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vēlas sūtīt īsziņu adresātam &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"No jūsu mobilās ierīces konta "<font fgcolor="#ffffb060">"var tikt iekasēta maksa"</font>"."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"No jūsu mobilās ierīces konta tiks iekasēta maksa."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Sūtīt"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Atcelt"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Atcerēties manu izvēli"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Lai mainītu: Iestatījumi &gt; Lietotnes"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Vienmēr atļaut"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Neatļaut nekad"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM karte ir izņemta."</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilais tīkls nebūs pieejams līdz brīdim, kad restartēsiet ierīci ar ievietotu derīgu SIM karti."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Gatavs"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Datuma iestatīšana"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Iestatīt"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Gatavs"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Noklusējums"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Atļaujas nav nepieciešamas."</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Slēpt"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Rādīt visu"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"JAUNA: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"JAUNA: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Nodrošina <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Atļaujas nav nepieciešamas."</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"par to no jums var tikt iekasēta maksa"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB lielapjoma atmiņa"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB ir pievienots."</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Ir izveidots savienojums ar datoru, izmantojot USB. Pieskarieties tālāk esošajai pogai, ja vēlaties kopēt failus no datora Android USB atmiņā vai otrādi."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"Lietojumprogramma <xliff:g id="APP">%s</xliff:g> aktivizēja VPN."</string>
     <string name="vpn_text" msgid="3011306607126450322">"Pieskarieties, lai pārvaldītu tīklu."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Ir izveidots savienojums ar <xliff:g id="SESSION">%s</xliff:g>. Pieskarieties, lai pārvaldītu tīklu."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Notiek savienojuma izveide ar vienmēr ieslēgtu VPN…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Izveidots savienojums ar vienmēr ieslēgtu VPN."</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Kļūda saistībā ar vienmēr ieslēgtu VPN"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Pieskarieties, lai atiestatītu savienojumu."</string>
     <string name="upload_file" msgid="2897957172366730416">"Izvēlēties failu"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Neviens fails nav izvēlēts"</string>
     <string name="reset" msgid="2448168080964209908">"Atiestatīt"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Kopīgot"</string>
     <string name="find" msgid="4808270900322985960">"Atrast"</string>
     <string name="websearch" msgid="4337157977400211589">"Meklēt tīmeklī"</string>
+    <string name="find_next" msgid="5742124618942193978">"Atrast nākamo"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Atrast iepriekšējo"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Atrašanās vietas pieprasījums no: <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Atrašanās vietas pieprasījums"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Pieprasīja: <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Tālrunis"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Austiņas"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Doka skaļruņi"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI audio"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistēma"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Gatavs"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Multivides izeja"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Notiek meklēšana..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Notiek savienojuma izveide..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Pieejams"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Nav pieejams"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Iebūvēts ekrāns"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI ekrāns"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Pārklājums Nr. <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Bezvadu attēlošanas savienojums ir izveidots."</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Šis ekrāns tiek rādīts citā ierīcē."</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Pārtraukt savienojumu"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Ārkārtas izsaukums"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Aizmirsu kombināciju"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Nepareiza kombinācija"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Nepareiza parole"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Nepareizs PIN"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Mēģiniet vēlreiz pēc <xliff:g id="NUMBER">%d</xliff:g> sekundēm."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Norādiet savu kombināciju"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Ievadiet SIM kartes PIN"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Ievadiet PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Ievadiet paroli"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM karte ir atspējota. Lai turpinātu, ievadiet PUK kodu. Lai iegūtu detalizētu informāciju, sazinieties ar mobilo sakaru operatoru."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Ievadiet vēlamo PIN kodu."</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Apstipriniet vēlamo PIN."</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Notiek SIM kartes atbloķēšana..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"PIN kods nav pareizs."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Ievadiet PIN, kas sastāv no 4 līdz 8 cipariem."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK kodam ir jābūt vismaz 8 ciparus garam."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Atkārtoti ievadiet pareizo PUK kodu. Ja vairākas reizes ievadīsiet to nepareizi, SIM karte tiks neatgriezeniski atspējota."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN kodi neatbilst."</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Pārāk daudz kombinācijas mēģinājumu"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Lai atbloķētu, pierakstieties, izmantojot savu Google kontu."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Lietotājvārds (e-pasts)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Parole"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Pierakstīties"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Nederīgs lietotājvārds vai parole."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Vai aizmirsāt lietotājvārdu vai paroli?"\n"Apmeklējiet vietni "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Notiek konta pārbaude…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Jūs nepareizi ievadījāt PIN <xliff:g id="NUMBER_0">%d</xliff:g> reizes."\n\n"Mēģiniet vēlreiz pēc <xliff:g id="NUMBER_1">%d</xliff:g> sekundēm."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Jūs nepareizi ievadījāt paroli <xliff:g id="NUMBER_0">%d</xliff:g> reizes."\n\n"Mēģiniet vēlreiz pēc <xliff:g id="NUMBER_1">%d</xliff:g> sekundēm."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Jūs nepareizi norādījāt atbloķēšanas kombināciju <xliff:g id="NUMBER_0">%d</xliff:g> reizes."\n\n"Mēģiniet vēlreiz pēc <xliff:g id="NUMBER_1">%d</xliff:g> sekundēm."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Jūs nepareizi veicāt planšetdatora atbloķēšanu <xliff:g id="NUMBER_0">%d</xliff:g> reizes. Pēc vēl <xliff:g id="NUMBER_1">%d</xliff:g> neveiksmīgiem mēģinājumiem planšetdatorā tiks atiestatīti rūpnīcas noklusējuma iestatījumi un lietotāja dati tiks zaudēti."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Jūs nepareizi veicāt tālruņa atbloķēšanu <xliff:g id="NUMBER_0">%d</xliff:g> reizes. Pēc vēl <xliff:g id="NUMBER_1">%d</xliff:g> neveiksmīgiem mēģinājumiem tālrunī tiks atiestatīti rūpnīcas noklusējuma iestatījumi un lietotāja dati tiks zaudēti."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Jūs nepareizi veicāt planšetdatora atbloķēšanu <xliff:g id="NUMBER">%d</xliff:g> reizes. Planšetdatorā tiks atiestatīti rūpnīcas noklusējuma iestatījumi."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Jūs nepareizi veicāt tālruņa atbloķēšanu <xliff:g id="NUMBER">%d</xliff:g> reizes. Tālrunī tiks atiestatīti rūpnīcas noklusējuma iestatījumi."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Jūs nepareizi norādījāt atbloķēšanas kombināciju <xliff:g id="NUMBER_0">%d</xliff:g> reizes. Pēc vēl <xliff:g id="NUMBER_1">%d</xliff:g> neveiksmīgiem mēģinājumiem planšetdators būs jāatbloķē, izmantojot e-pasta kontu."\n\n"Mēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%d</xliff:g> sekundēm."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Jūs nepareizi norādījāt atbloķēšanas kombināciju <xliff:g id="NUMBER_0">%d</xliff:g> reizes. Pēc vēl <xliff:g id="NUMBER_1">%d</xliff:g> neveiksmīgiem mēģinājumiem tālrunis būs jāatbloķē, izmantojot e-pasta kontu."\n\n"Mēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%d</xliff:g> sekundēm."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">"  — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Noņemt"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Vai palielināt skaļumu virs drošības līmeņa?"\n"Ilgstoši klausoties skaņu lielā skaļumā, var tikt bojāta dzirde."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Lai iespējotu pieejamību, turiet nospiestus divus pirkstus."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Pieejamības režīms ir iespējots."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Pieejamība ir atcelta."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Pašreizējais lietotājs: <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Īpašnieks"</string>
 </resources>
diff --git a/core/res/res/values-mcc310/config.xml b/core/res/res/values-mcc310/config.xml
new file mode 100644
index 0000000..df398f9
--- /dev/null
+++ b/core/res/res/values-mcc310/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Whether safe headphone volume is enabled or not (country specific). -->
+    <bool name="config_safe_media_volume_enabled">false</bool>
+
+</resources>
diff --git a/core/res/res/values-mcc311/config.xml b/core/res/res/values-mcc311/config.xml
new file mode 100644
index 0000000..df398f9
--- /dev/null
+++ b/core/res/res/values-mcc311/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Whether safe headphone volume is enabled or not (country specific). -->
+    <bool name="config_safe_media_volume_enabled">false</bool>
+
+</resources>
diff --git a/core/res/res/values-mcc312/config.xml b/core/res/res/values-mcc312/config.xml
new file mode 100644
index 0000000..df398f9
--- /dev/null
+++ b/core/res/res/values-mcc312/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Whether safe headphone volume is enabled or not (country specific). -->
+    <bool name="config_safe_media_volume_enabled">false</bool>
+
+</resources>
diff --git a/core/res/res/values-mcc313/config.xml b/core/res/res/values-mcc313/config.xml
new file mode 100644
index 0000000..df398f9
--- /dev/null
+++ b/core/res/res/values-mcc313/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Whether safe headphone volume is enabled or not (country specific). -->
+    <bool name="config_safe_media_volume_enabled">false</bool>
+
+</resources>
diff --git a/core/res/res/values-mcc314/config.xml b/core/res/res/values-mcc314/config.xml
new file mode 100644
index 0000000..df398f9
--- /dev/null
+++ b/core/res/res/values-mcc314/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Whether safe headphone volume is enabled or not (country specific). -->
+    <bool name="config_safe_media_volume_enabled">false</bool>
+
+</resources>
diff --git a/core/res/res/values-mcc315/config.xml b/core/res/res/values-mcc315/config.xml
new file mode 100644
index 0000000..df398f9
--- /dev/null
+++ b/core/res/res/values-mcc315/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Whether safe headphone volume is enabled or not (country specific). -->
+    <bool name="config_safe_media_volume_enabled">false</bool>
+
+</resources>
diff --git a/core/res/res/values-mcc316/config.xml b/core/res/res/values-mcc316/config.xml
new file mode 100644
index 0000000..df398f9
--- /dev/null
+++ b/core/res/res/values-mcc316/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Whether safe headphone volume is enabled or not (country specific). -->
+    <bool name="config_safe_media_volume_enabled">false</bool>
+
+</resources>
diff --git a/core/res/res/values-mcc440/config.xml b/core/res/res/values-mcc440/config.xml
new file mode 100644
index 0000000..4ca1677
--- /dev/null
+++ b/core/res/res/values-mcc440/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Whether camera shutter sound is forced or not  (country specific). -->
+    <bool name="config_camera_sound_forced">true</bool>
+
+</resources>
diff --git a/core/res/res/values-ms/donottranslate-cldr.xml b/core/res/res/values-ms/donottranslate-cldr.xml
index 09d461c..a5843ff 100644
--- a/core/res/res/values-ms/donottranslate-cldr.xml
+++ b/core/res/res/values-ms/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Januari</string>
-    <string name="month_long_standalone_february">Februari</string>
-    <string name="month_long_standalone_march">Mac</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">Mei</string>
-    <string name="month_long_standalone_june">Jun</string>
-    <string name="month_long_standalone_july">Julai</string>
-    <string name="month_long_standalone_august">Ogos</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">Oktober</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">Disember</string>
-
-    <string name="month_long_january">Januari</string>
-    <string name="month_long_february">Februari</string>
-    <string name="month_long_march">Mac</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">Mei</string>
-    <string name="month_long_june">Jun</string>
-    <string name="month_long_july">Julai</string>
-    <string name="month_long_august">Ogos</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">Oktober</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">Disember</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mac</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">Mei</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Ogos</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Okt</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dis</string>
-
-    <string name="month_shortest_january">1</string>
-    <string name="month_shortest_february">2</string>
-    <string name="month_shortest_march">3</string>
-    <string name="month_shortest_april">4</string>
-    <string name="month_shortest_may">5</string>
-    <string name="month_shortest_june">6</string>
-    <string name="month_shortest_july">7</string>
-    <string name="month_shortest_august">8</string>
-    <string name="month_shortest_september">9</string>
-    <string name="month_shortest_october">10</string>
-    <string name="month_shortest_november">11</string>
-    <string name="month_shortest_december">12</string>
-
-    <string name="day_of_week_long_sunday">Ahad</string>
-    <string name="day_of_week_long_monday">Isnin</string>
-    <string name="day_of_week_long_tuesday">Selasa</string>
-    <string name="day_of_week_long_wednesday">Rabu</string>
-    <string name="day_of_week_long_thursday">Khamis</string>
-    <string name="day_of_week_long_friday">Jumaat</string>
-    <string name="day_of_week_long_saturday">Sabtu</string>
-
-    <string name="day_of_week_medium_sunday">Ahd</string>
-    <string name="day_of_week_medium_monday">Isn</string>
-    <string name="day_of_week_medium_tuesday">Sel</string>
-    <string name="day_of_week_medium_wednesday">Rab</string>
-    <string name="day_of_week_medium_thursday">Kha</string>
-    <string name="day_of_week_medium_friday">Jum</string>
-    <string name="day_of_week_medium_saturday">Sab</string>
-
-    <string name="day_of_week_short_sunday">Ahd</string>
-    <string name="day_of_week_short_monday">Isn</string>
-    <string name="day_of_week_short_tuesday">Sel</string>
-    <string name="day_of_week_short_wednesday">Rab</string>
-    <string name="day_of_week_short_thursday">Kha</string>
-    <string name="day_of_week_short_friday">Jum</string>
-    <string name="day_of_week_short_saturday">Sab</string>
-
-    <string name="day_of_week_shortest_sunday">1</string>
-    <string name="day_of_week_shortest_monday">2</string>
-    <string name="day_of_week_shortest_tuesday">3</string>
-    <string name="day_of_week_shortest_wednesday">4</string>
-    <string name="day_of_week_shortest_thursday">5</string>
-    <string name="day_of_week_shortest_friday">6</string>
-    <string name="day_of_week_shortest_saturday">7</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 5a49127..e89f70f 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Pilihan telefon"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Kunci skrin"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Matikan kuasa"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Laporan pepijat"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Ambil laporan pepijat"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Ini akan mengumpul maklumat tentang keadaan peranti semasa anda untuk dihantarkan sebagai mesej e-mel. Proses ini akan mengambil sedikit masa bermula dari laporan pepijat sehingga siap untuk dihantar; jadi diharap bersabar."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Mod senyap"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Bunyi DIMATIKAN"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Bunyi DIHIDUPKAN"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Mesej anda"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Membaca dan menulis SMS, e-mel, dan mesej lain."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Maklumat peribadi anda"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Akses langsung kepada kenalan dan kalendar anda yang disimpan dalam tablet."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Akses langsung kepada kenalan dan kalendar yang disimpan pada telefon."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Akses langsung ke maklumat tentang anda, yang disimpan pada kad kenalan anda."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Maklumat sosial anda"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Akses langsung ke maklumat tentang kenalan anda dan sambungan sosial."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Lokasi anda"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Pantau lokasi fizikal anda."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Komunikasi rangkaian"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Akses pelbagai ciri rangkaian."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Akses peranti dan rangkaian melalui Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Tetapan Audio"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Tukar tetapan audio."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Menjejaskan Bateri"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Gunakan ciri yang boleh menghabiskan bateri dengan cepat."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalendar"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Akses langsung ke kalendar dan acara."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Baca Kamus Pengguna"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Baca perkataan di dalam kamus pengguna."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Tulis Kamus Pengguna"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Tambah perkataan ke kamus pengguna."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Penanda halaman dan Sejarah"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Akses langsung ke penanda halaman dan sejarah penyemak imbas."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Penggera"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Tetapkan jam penggera."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Mel suara"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Akses langsung ke mel suara."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Akses langsung ke mikrofon untuk merakam audio."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Akses langsung ke kamera untuk merakam imej atau video."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Maklumat aplikasi anda"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Keupayaan untuk mempengaruhi tingkah laku aplikasi lain pada peranti anda."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Kertas dinding"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Tukar tetapan kertas dinding peranti."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Jam"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Tukar masa peranti atau zon masa."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Bar Status"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Tukar tetapan bar status peranti."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Tetapan Penyegerakan"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Akses ke tetapan segerakan."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Akaun anda"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Akses akaun yang tersedia."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Kawalan perkakasan"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Akses dan kawalan peringkat lebih rendah bagi sistem."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Alatan pembangunan"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Ciri hanya diperlukan untuk pembangun apl."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Aplikasi UI Lain"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Mempengaruhi UI aplikasi lain."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Storan"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Akses storan USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Akses kad SD."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Membenarkan apl menerima dan memproses mesej WAP. Kebenaran ini termasuk keupayaan untuk memantau atau memadam mesej yang dihantar kepada anda tanpa menunjukkannya kepada anda."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"dapatkan semula apl yang sedang dijalankan"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Membenarkan apl mengambil maklumat tentang tugasan yang sedang dan baru berjalan. Ini boleh membenarkan apl untuk menemui maklumat tentang apl mana yang digunakan pada peranti."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"berinteraksi sesama pengguna"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Membenarkan apl melakukan tindakan merentasi pengguna berbeza pada peranti. Apl hasad boleh menggunakan ini untuk melanggar perlindungan antara pengguna."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"lesen penuh untuk berinteraksi sesama pengguna"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Membenarkan semua interaksi yang mungkin sesama pengguna."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"urus pengguna"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Membenarkan apl mengurus pengguna pada peranti ini, termasuk pertanyaan, pembuatan dan pemadaman."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"dapatkan butiran apl yang berjalan"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Membenarkan apl untuk mendapatkan maklumat terperinci tentang tugasan yang sedang dan baru berjalan. Apl hasad boleh mendapat maklumat peribadi tentang apl lain."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"susun semula tertib apl yang dijalankan"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Membenarkan apl untuk mendapatkan semula keadaan dalaman sistem. Apl hasad boleh mendapatkan pelbagai maklumat peribadi dan selamat yang biasanya tidak ia perlukan."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"dapatkan semula kandungan skrin"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Membenarkan apl untuk mendapatkan kandungan tetingkap aktif. Apl hasad boleh mengambil keseluruhan kandungan tetingkap dan memeriksa semua teks kecuali kata laluan."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"dayakan kebolehcapaian untuk sementara"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Membenarkan aplikasi untuk mendayakan kebolehcapaian untuk sementara pada peranti. Apl hasad mungkin mendayakan kebolehcapaian tanpa izin pengguna."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"dapatkan maklumat tetingkap"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Membolehkan aplikasi mendapatkan maklumat tentang tetingkap dari pengurus tetingkap. Apl hasad boleh mendapatkan maklumat yang bertujuan untuk penggunaan sistem dalaman."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"tapis acara"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Membenarkan aplikasi mendaftarkan penapis input yang menapis strim semua acara pengguna sebelum dihantar. Apl hasad mungkin mengawal UI sistem tanpa campur tangan pengguna."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"besarkan paparan"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Membenarkan aplikasi membesarkan kandungan paparan. Apl hasad mungkin mengubah kandungan paparan yang akan membuatkan peranti tidak boleh digunakan."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"penutupan separa"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Meletakkan pengurus aktiviti dalam keadaan tutup. Tidak melaksanakan penutupan lengkap."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"halang pertukaran apl"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Membenarkan apl untuk mengawal bilangan maksimum proses yang akan berlangsung. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"memaksa apl latar belakang untuk menutup"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Membenarkan apl untuk mengawal sama ada aktiviti sentiasa selesai sebaik sahaja ia pergi ke latar belakang. Tidak sekali-kali diperlukan untuk apl biasa."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"ubah suai statistik bateri"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Membenarkan apl untuk mengubah suai statistik bateri yang dikumpul. Bukan untuk kegunaan apl biasa."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"baca statistik bateri"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Membenarkan aplikasi membaca data penggunaan bateri tahap rendah semasa. Boleh membenarkan aplikasi untuk mencari maklumat terperinci tentang apl yang anda gunakan."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"ubah suai statistik bateri"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Membenarkan apl mengubah suai statistik bateri yang dikumpul. Bukan untuk penggunaan apl normal."</string>
     <string name="permlab_backup" msgid="470013022865453920">"sandaran dan pemulihan sistem kawalan"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Membenarkan apl untuk mengawal sandaran sistem dan memulihkan mekanisme. Bukan untuk digunakan oleh apl biasa."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"sahkan penyandaran penuh atau pemulihan operasi"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"memapaparkan tetingkap yang tiada kebenaran"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Membenarkan apl untuk membuat tetingkap yang dimaksudkan untuk digunakan oleh antara muka pengguna sistem dalaman. Bukan untuk digunakan oleh apl biasa."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"lukis atas apl lain"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Membenarkan apl menunjukkan tetingkap amaran sistem.Sesetengah tetingkap amaran boleh mengambil alih keseluruhan skrin."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Membenarkan aplikasi bertindih di atas aplikasi lain atau sebahagian daripada antara muka pengguna. Ini mungkin mengganggu penggunaan antara muka anda dalam sebarang aplikasi atau menukar apa yang anda rasa anda lihat dalam aplikasi lain."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"mengubah suai kelajuan animasi global"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Membenarkan apl menukar kelajuan animasi global (animasi yang lebih laju atau lebih perlahan) pada bila-bila masa sahaja."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"urus token apl"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Membenarkan apl untuk membuat dan menguruskan token mereka sendiri, dengan memintas susunan-Z biasanya. Tidak sekali-kali diperlukan untuk apl biasa."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"bekukan skrin"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Membenarkan aplikasi membekukan sementara skrin untuk peralihan skrin penuh."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"menekan kekunci dan butang kawalan"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Membenarkan apl untuk menyampaikan peristiwa input sendiri (tekanan kekunci, dan sebagainya) kepada apl lain. Apl hasad boleh menggunakannya untuk mengambil alih tablet."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Membenarkan apl untuk menyampaikan peristiwa input sendiri (tekanan kekunci, dan sebagainya) kepada apl lain. Apl hasad boleh menggunakannya untuk mengambil alih telefon."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"pasang terus apl"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Membenarkan apl untuk memasang pakej Android yang baharu atau yang dikemas kini. Apl hasad boleh menggunakannya untuk menambah apl baharu dengan keizinan berkuasa secara sewenang-wenangnya."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"padamkan semua data cache apl"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Membenarkan apl untuk mengosongkan storan tablet dengan memadam fail dalam direktori cache apl. Kebiasaannya, akses adalah terhad kepada proses sistem."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Membenarkan apl untuk mengosongkan storan telefon dengan memadam fail dalam direktori cache apl. Kebiasaannya, akses adalah terhad kepada proses sistem."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Membenarkan apl mengosongkan storan tablet dengan memadam fail dalam direktori cache aplikasi lain. Ini boleh menyebabkan aplikasi lain bermula lebih perlahan kerana perlu mendapatkan semula datanya."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Membenarkan apl mengosongkan storan telefon dengan memadam fail dalam direktori cache aplikasi lain. Ini boleh menyebabkan aplikasi lain bermula lebih perlahan kerana perlu mendapatkan semula datanya."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"Alih sumber apl"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Membenarkan apl untuk memindahkan sumber apl dari media dalaman ke luaran dan sebaliknya."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"baca data log sensitif"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Membenarkan apl untuk mengakses arahan pembekal lokasi tambahan. Ini boleh membenarkan apl untuk campur tangan dengan operasi GPS atau sumber lokasi lain."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"kebenaran untuk memasang pembekal lokasi"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Buat sumber lokasi palsu untuk menguji atau memasang pembekal lokasi baharu. Ini membenarkan apl untuk membatalkan lokasi dan/atau status yang dikembalikan oleh sumber lokasi lain seperti GPS atau pembekal lokasi."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"lokasi (GPS) tepat"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Akses sumber lokasi yang tepat seperti Sistem Kedudukan Global pada tablet. Apabila perkhidmatan lokasi tersedia dan dihidupkan, kebenaran ini membenarkan apl menentukan lokasi tepat anda."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Akses sumber lokasi yang tepat seperti Sistem Kedudukan Global pada telefon. Apabila perkhidmatan lokasi tersedia dan dihidupkan, kebenaran ini membenarkan apl menentukan lokasi tepat anda."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"lokasi (berasaskan rangkaian) anggaran"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Akses lokasi anggaran dari pembekal lokasi menggunakan sumber rangkaian seperti menara sel dan Wi-Fi. Apabila perkhidmatan lokasi ini tersedia dan dihidupkan, kebenaran ini membenarkan apl menentukan lokasi anggaran anda."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"lokasi tepat (GPS dan berasaskan rangkaian)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Membenarkan apl mendapatkan lokasi tepat anda menggunakan Sistem Kedudukan Global (GPS) atau sumber lokasi rangkaian seperti menara sel dan Wi-Fi. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada peranti anda untuk kegunaan apl. Apl boleh menggunakan ini untuk menentukan tempat anda berada dan mungkin menggunakan kuasa bateri tambahan."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"lokasi anggaran (berasaskan rangkaian)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Membenarkan apl mendapatkan lokasi anggaran anda. Lokasi ini diperolehi oleh perkhidmatan lokasi menggunakan sumber lokasi rangkaian seperti menara sel dan Wi-Fi. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada peranti anda untuk kegunaan apl. Apl boleh menggunakan ini untuk menentukan secara anggaran tempat anda berada."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"akses SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Membenarkan apl menggunakan ciri peringkat rendah SurfaceFlinger."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"baca penimbal bingkai"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Membenarkan apl membaca kandungan penimbal bingkai."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"konfigurasikan paparan Wifi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Membenarkan apl mengkonfigurasi dan menyambung ke paparan Wifi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"kawal paparan Wifi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Membenarkan apl mengawal ciri tahap rendah paparan Wifi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"tukar tetapan audio anda"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Membenarkan apl untuk mengubah suai tetapan audio global seperti kelantangan dan pembesar suara mana digunakan untuk output."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"rakam audio"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"akses tetapan Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Membenarkan apl mengkonfigurasikan tablet Bluetooth setempat dan menemui serta berpasangan dengan peranti jauh."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Membenarkan apl mengkonfigurasikan telefon Bluetooth setempat dan menemui serta berpasangan dengan peranti jauh."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Lihat sambungan WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"sambung dan putuskan sambungan WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Membenarkan apl menentukan sama ada WiMaX didayakan dan maklumat tentang sebarang rangkaian WiMaX yang disambungkan."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Tukar keadaan WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Membenarkan apl untuk menyambungkan tablet ke dan menyahsambungkan tablet dari rangkaian WiMaX."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Membenarkan apl untuk mengubah suai suapan segerakan semasa anda. Apl hasad boleh menukar suapan anda yang disegerakkan."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"baca istilah yang anda tambahkan kepada kamus"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Membenarkan apl membaca semua perkataan, nama dan frasa yang mungkin telah disimpan oleh pengguna dalam kamus pengguna."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"tulis ke kamus yang ditakrifkan pengguna"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"tambah perkataan ke kamus ditakrifkan pengguna"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Membenarkan apl menulis perkataan baharu ke dalam kamus pengguna."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"uji akses ke storan dilindungi"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"uji akses ke storan dilindungi"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Membenarkan apl menguji kebenaran untuk storan USB yang akan tersedia pada peranti akan datang."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Apl boleh uji kebenaran USB."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Membenarkan apl menguji kebenaran untuk kad SD yang akan tersedia pada peranti akan datang."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"ubah suai atau padam kandungan storan USB anda"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"ubah suai atau padam kandungan kad SD anda"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Membenarkan apl menulis ke kad SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"ubh suai/pdm kdg strn mdia dlm"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Membenarkan apl mengubah suai kandungan storan media dalaman."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"mengakses storan luaran untuk semua pengguna"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Membenarkan apl untuk mengakses storan luaran untuk semua pengguna."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"akses sistem fail cache"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Membenarkan apl membaca dan menulis cache sistem fail."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"membuat/menerima panggilan Internet"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Memerlukan data apl yang disimpan itu disulitkan."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Lumpuhkan kamera"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Menghalang penggunaan semua kamera peranti."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Lumpuh ciri pelindung kekunci"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Cegah penggunaan beberapa ciri dalam pelindung kekunci."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Laman Utama"</item>
     <item msgid="869923650527136615">"Mudah alih"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Cuba lagi"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Telah melepasi had cubaan Buka Kunci Wajah"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Mengecas, (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Sudah dicas."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Sudah dicas"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Sambungkan pengecas anda."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Tiada kad SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Tiada kad SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tiada kad SIM dalam tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Kad SIM tiada dalam telefon."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Masukkan kad SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Corak dipadamkan"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Sel ditambahkan"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Corak siap"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Tambah widget."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Kosong"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Bahagian buka kunci dikembangkan."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Bahagian buka kunci diruntuhkan."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Pemilih pengguna"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Status"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Kamera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Kawalan media"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Penyusunan semula widget dimulakan."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Penyusunan semula widget tamat."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> dipadamkan."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Kembangkan bahagian buka kunci."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Buka kunci luncur."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Buka kunci corak."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Wajah Buka Kunci"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Buka kunci pin."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Buka kunci kata laluan."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Kawasan corak."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Kawasan luncur."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Salin URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Pilih teks"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Pemilihan teks"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"tambahkan pada kamus"</string>
-    <string name="deleteText" msgid="7070985395199629156">"padam"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Tambah ke kamus"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Padam"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Kaedah input"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tindakan teks"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Ruang storan semakin berkurangan"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Rangkaian Wi-Fi terbuka tersedia"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Log masuk ke rangkaian Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Log masuk ke rangkaian"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Tidak boleh menyambung kepada Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" mempunyai sambungan internet yang kurang baik."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Kepada:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Taipkan PIN yang diperlukan:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Sambungan telefon ke Wi-Fi akan diputuskan buat sementara waktu semasa telefon bersambung ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Masukkan aksara"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Menghantar mesej SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sedang menghantar banyak mesej SMS. Adakah anda mahu membenarkan apl ini terus menghantar mesej?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Benarkan"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Nafikan"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ingin menghantar mesej kepada &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Ini akan menyebabkan akaun mudah alih anda "<font fgcolor="#ffffb060">"dikenakan caj"</font>"."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Ini akan menyebabkan akaun mudah alih anda dikenakan caj."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Hantar"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Batal"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Ingat pilihan saya"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Anda boleh menukar ini nanti dalam Tetapan &gt; Apl"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Sentiasa Benarkan"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Jangan Benarkan"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Kad SIM dikeluarkan"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Rangkaian mudah alih tidak akan tersedia sehingga anda mula semula dengan kad SIM yang sah dimasukkan."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Selesai"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Tetapkan tarikh"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Tetapkan"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Selesai"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Lalai"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Tiada kebenaran diperlukan"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Sembunyikan"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Tunjukkan semua"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"BAHARU: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"BAHARU: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Disediakan oleh <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Tiada kebenaran diperlukan"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"anda mungkin dikenakan bayaran"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Storan massa USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"sambungan USB"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Anda bersambung ke komputer melalui USB. Sentuh butang di bawah jika anda mahu menyalin fail antara komputer dan storan USB Android anda."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Sentuh untuk mengurus rangkaian."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Bersambung ke <xliff:g id="SESSION">%s</xliff:g>. Sentuh untuk mengurus rangkaian."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN sentiasa hidup sedang disambungkan..."</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sentiasa hidup telah disambungkan"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Ralat VPN sentiasa hidup"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Sentuh untuk menetapkan semula sambungan"</string>
     <string name="upload_file" msgid="2897957172366730416">"Pilih fail"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Tiada fail dipilih"</string>
     <string name="reset" msgid="2448168080964209908">"Tetapkan semula"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Kongsi"</string>
     <string name="find" msgid="4808270900322985960">"Dapatkan"</string>
     <string name="websearch" msgid="4337157977400211589">"Carian Web"</string>
+    <string name="find_next" msgid="5742124618942193978">"Cari seterusnya"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Cari sebelumnya"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Permintaan lokasi daripada <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Permintaan lokasi"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Diminta oleh <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Fon kepala"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Pembesar suara dok"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Audio HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Selesai"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Output media"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Mengimbas…"</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Menyambung..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Tersedia"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Tidak tersedia"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Skrin Terbina Dalam"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Skrin HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Tindih #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Paparan wayarles disambungkan"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Skrin ini ditunjukkan pada peranti lain"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Putus sambungan"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Panggilan kecemasan"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Lupa Corak"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Corak Salah"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Kata Laluan Salah"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN salah"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Cuba lagi dalam <xliff:g id="NUMBER">%d</xliff:g> saat."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Lukiskan corak anda"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Masukkan PIN SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Masukkan PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Masukkan Kata Laluan"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"Kini SIM dilumpuhkan. Masukkan kod PUK untuk meneruskan. Hubungi pembawa untuk butiran."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Masukkan kod PIN yang diingini"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Sahkan kod PIN yang diingini"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Membuka kunci kad SIM..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Kod PIN salah."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Taipkan PIN yang mengandungi 4 hingga 8 nombor."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Kod PUK mestilah 8 nombor atau lebih."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Masukkan semula kod PIN yang betul. Percubaan berulang akan melumpuhkan SIM secara kekal."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Kod PIN tidak sepadan"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Terlalu banyak percubaan melukis corak"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Untuk membuka kunci, log masuk dengan akaun Google anda."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Nama Pengguna (E-mel)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Kata laluan"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Log masuk"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Nama pengguna atau kata laluan tidak sah."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Lupa nama pengguna atau kata laluan anda?"\n"Lawati"<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Menyemak akaun…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Anda telah menaip PIN anda secara salah sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. "\n\n"Cuba lagi dalam <xliff:g id="NUMBER_1">%d</xliff:g> saat."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Anda telah menaip kata laluan anda secara salah sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. "\n\n"Cuba lagi dalam <xliff:g id="NUMBER_1">%d</xliff:g> saat."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Anda telah tersilap melukis corak buka kunci anda sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. "\n\n"Cuba lagi dalam <xliff:g id="NUMBER_1">%d</xliff:g> saat."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Anda telah mencuba untuk membuka kunci tablet dengan salah sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%d</xliff:g> lagi percubaan yang tidak berjaya, tablet akan ditetapkan semula kepada tetapan lalai kilang dan semua data pengguna akan hilang."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Anda telah mencuba untuk membuka kunci telefon dengan salah sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%d</xliff:g> lagi percubaan yang tidak berjaya, telefon akan ditetapkan semula kepada tetapan lalai kilang dan semua data pengguna akan hilang."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Anda telah mencuba untuk membuka kunci tablet secara salah sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Tablet kini akan ditetapkan semula ke tetapan lalai kilang."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Anda telah mencuba untuk membuka kunci telefon secara salah sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Telefon kini akan ditetapkan semula ke tetapan lalai kilang."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Anda telah tersilap melukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%d</xliff:g> lagi percubaan yang tidak berjaya, anda akan diminta membuka kunci tablet anda menggunakan log masuk Google anda."\n\n" Cuba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> saat."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Anda telah tersilap lukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%d</xliff:g> lagi percubaan yang tidak berjaya, anda akan diminta membuka kunci telefon anda menggunakan log masuk Google anda."\n\n" Cuba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> saat."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Alih keluar"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Tingkatkan kelantangan di atas tahap selamat?"\n"Mendengar pada kelantangan tinggi untuk tempoh yang panjang boleh merosakkan pendengaran anda."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Teruskan menahan dengan dua jari untuk mendayakan kebolehcapaian."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Kebolehcapaian didayakan."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Kebolehcapaian dibatalkan."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Pengguna semasa <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Pemilik"</string>
 </resources>
diff --git a/core/res/res/values-nb/donottranslate-cldr.xml b/core/res/res/values-nb/donottranslate-cldr.xml
index 637dd5e..8eb1ff6 100644
--- a/core/res/res/values-nb/donottranslate-cldr.xml
+++ b/core/res/res/values-nb/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">januar</string>
-    <string name="month_long_standalone_february">februar</string>
-    <string name="month_long_standalone_march">mars</string>
-    <string name="month_long_standalone_april">april</string>
-    <string name="month_long_standalone_may">mai</string>
-    <string name="month_long_standalone_june">juni</string>
-    <string name="month_long_standalone_july">juli</string>
-    <string name="month_long_standalone_august">august</string>
-    <string name="month_long_standalone_september">september</string>
-    <string name="month_long_standalone_october">oktober</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">desember</string>
-
-    <string name="month_long_january">januar</string>
-    <string name="month_long_february">februar</string>
-    <string name="month_long_march">mars</string>
-    <string name="month_long_april">april</string>
-    <string name="month_long_may">mai</string>
-    <string name="month_long_june">juni</string>
-    <string name="month_long_july">juli</string>
-    <string name="month_long_august">august</string>
-    <string name="month_long_september">september</string>
-    <string name="month_long_october">oktober</string>
-    <string name="month_long_november">november</string>
-    <string name="month_long_december">desember</string>
-
-    <string name="month_medium_january">jan.</string>
-    <string name="month_medium_february">feb.</string>
-    <string name="month_medium_march">mars</string>
-    <string name="month_medium_april">apr.</string>
-    <string name="month_medium_may">mai</string>
-    <string name="month_medium_june">juni</string>
-    <string name="month_medium_july">juli</string>
-    <string name="month_medium_august">aug.</string>
-    <string name="month_medium_september">sep.</string>
-    <string name="month_medium_october">okt.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">des.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">søndag</string>
-    <string name="day_of_week_long_monday">mandag</string>
-    <string name="day_of_week_long_tuesday">tirsdag</string>
-    <string name="day_of_week_long_wednesday">onsdag</string>
-    <string name="day_of_week_long_thursday">torsdag</string>
-    <string name="day_of_week_long_friday">fredag</string>
-    <string name="day_of_week_long_saturday">lørdag</string>
-
-    <string name="day_of_week_medium_sunday">søn.</string>
-    <string name="day_of_week_medium_monday">man.</string>
-    <string name="day_of_week_medium_tuesday">tir.</string>
-    <string name="day_of_week_medium_wednesday">ons.</string>
-    <string name="day_of_week_medium_thursday">tor.</string>
-    <string name="day_of_week_medium_friday">fre.</string>
-    <string name="day_of_week_medium_saturday">lør.</string>
-
-    <string name="day_of_week_short_sunday">søn.</string>
-    <string name="day_of_week_short_monday">man.</string>
-    <string name="day_of_week_short_tuesday">tir.</string>
-    <string name="day_of_week_short_wednesday">ons.</string>
-    <string name="day_of_week_short_thursday">tor.</string>
-    <string name="day_of_week_short_friday">fre.</string>
-    <string name="day_of_week_short_saturday">lør.</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">O</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">L</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">i går</string>
-    <string name="today">i dag</string>
-    <string name="tomorrow">i morgen</string>
-
     <string name="hour_minute_24">%H.%M</string>
     <string name="hour_minute_ampm">%-l.%M %p</string>
     <string name="hour_minute_cap_ampm">%-l.%M %^p</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index b94f399..65014d3 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefoninnstillinger"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Lås skjermen"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Slå av"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Feilrapport"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Utfør feilrapport"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Informasjon om den nåværende tilstanden til enheten din samles inn og sendes som en e-post. Det tar litt tid fra du starter feilrapporten til e-posten er klar, så vær tålmodig."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Stillemodus"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Lyden er av"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Lyden er på"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Meldinger"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Tillatelse til å lese og skrive SMS-ene dine, e-post og andre meldinger."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Personlig informasjon"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Direkte tilgang til dine kontakter og kalender lagret på nettbrettet."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Direkte tilgang til kontakter og kalendre lagret på telefonen."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Direkte tilgang til informasjonen om deg, som er lagret på kontaktkortet ditt."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Den sosiale informasjonen din"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Direkte tilgang til informasjon om kontaktene og de sosiale forbindelsene dine."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Din posisjon"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Overvåking av telefonens fysiske posisjon."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Nettverkstilgang"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Tilgang til ulike nettverksfunksjoner."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Bruke enheter og nettverk gjennom Bluetooth"</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Lydinnstillingene"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Endre lydinnstillingene."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Påvirker batteriet"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Bruke funksjoner som kan tappe batteriet fortere."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalenderen"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Direkte tilgang til kalenderen og aktiviteter."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Lese brukerordlisten"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Lese ord i brukerordlisten."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Skrive i brukerordlisten"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Legge til ord i brukerordlisten."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Bokmerkene og loggen"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Direkte tilgang til bokmerker og nettleserloggen."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarmen"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Stille vekkerklokken."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Talepostkassen"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Direkte tilgang til talepostkassen."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofonen"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Direkte tilgang til mikrofonen for å ta opp lyd."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Kameraet"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Direkte tilgang til kamera for bilde- eller videoopptak."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Appinformasjonen din"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Ha muligheten til å påvirke andre apper på enheten din."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Bakgrunnen"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Endre enhetens bakgrunnsinnstillinger."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Klokken"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Endre klokken eller tidssonen på enheten."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Statusfelt"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Endre innstillingene for enhetens statusfelt."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Synkroniseringsinnsttillingene"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Tilgang til synkroniseringsinnstillingene."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Google-kontoer"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Tilgang til tilgjengelige Google-kontoer."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Maskinvarekontroll"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Lavnivå tilgang og kontroll over systemet."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Utviklingsverktøy"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funksjoner som bare apputviklere trenger."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Brukergrensesnittet til andre apper"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Påvirke brukergrensesnittet i andre apper."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Lagring"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Tilgang til USB-lagring."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Tilgang til minnekortet."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Lar appen motta og behandle WAP-meldinger. Dette betyr at appen kan overvåke eller slette meldinger som er sendt til deg uten at du har sett dem."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"hente apper som kjører"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Lar appen hente informasjon om oppgaver som kjører og som nylig har kjørt. Dette kan tillate appen å oppdage informasjon om hvilke apper som brukes på enheten."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"samhandling på tvers av brukere"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Tillater at appen utfører handlinger på tvers av ulike brukere på enheten. Skadelige apper kan utnytte dette til å bryte beskyttelsen mellom brukere."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"full lisens til å samhandle på tvers av brukere"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Tillater alle mulige samhandlinger på tvers av brukere."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"Administrere brukere"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Lar apper administrere brukere på enheten, herunder forespørsler, oppretting og sletting."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"hente informasjon om apper som kjører"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Tillater at appen henter ut informasjon om oppgaver som kjører eller nylig har kjørt. Skadelige apper kan bruke dette til å oppdage privat informasjon om andre apper."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"Endre rekkefølge på apper som kjører"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Lar appen hente ut informasjon om systemets indre tilstand. Ondsinnede apper kan hente et bredt spekter av privat og sikker informasjon som de vanligvis aldri burde ha behov for."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"hent av skjerminnhold"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Lar appen hente ut innholdet i det aktive vinduet. Ondsinnede apper kan hente ut hele vindusinnholdet og undersøke all teksten, med unntak av passord."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Aktiver tilgjengelighet midlertidig"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Lar en app midlertidig aktivere tilgjengelighet på enheten. Skadelige apper kan aktivere tilgjengelighet uten bekreftelse fra brukeren."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"hente vindusinformasjon"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Lar appen hente informasjon om vinduene fra vindusbehandleren. Skadelige apper kan hente informasjon som ikke er ment for intern systembruk."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrere hendelser"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Lar appen registrere et inndatafilter som filtrerer strømmen for alle brukerhendelser før de sendes ut. Skadelige apper kan kontrollere brukergrensesnittet for systemet uten at brukeren gjør noe."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"forstørre visningen"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Lar apper forstørre innholdet  på en skjerm. Skadelige apper kan endre skjerminnhold på en måte som gjør at enheten blir ubrukelig."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"delvis avslutning"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Lar applikasjonen sette aktivitetshåndtereren i avslutningstilstand. Slår ikke systemet helt av."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"forhindre applikasjonsbytte"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Lar appen kontrollere det maksimale antallet prosesser som kjører. Aldri nødvendig for vanlige apper."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"tvinger bakgrunnsapper til å lukkes"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Lar appen kontrollere hvorvidt aktiviteter alltid er fullført så snart de flyttes til bakgrunnen. Aldri nødvendig for vanlige apper."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"endre batteristatistikk"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Lar appen endre innsamlet batteristatistikk. Ikke beregnet på vanlige apper."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"lese batteristatistikk"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Lar apper lese gjeldende data på lavt nivå om batteribruk. Kan også la appen finne ut detaljert informasjon om hvilke apper du bruker."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"endre batteristatistikk"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Lar appen endre innsamlet batteristatistikk. Ikke beregnet på vanlige apper."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontrollere sikkerhetskopiering og gjenoppretting"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Lar appen kontrollere systemets mekanisme for sikkerhetskopiering og gjenoppretting. Ikke beregnet på vanlige apper."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"bekrefte en fullstendig sikkerhetskopi, eller gjenopprette driften"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"vis uautoriserte vinduer"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Lar appen opprette vinduer som er ment for å brukes av brukergrensesnittet til det interne systemet. Ikke beregnet på vanlige apper."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"tegner over andre apper"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Lar appen vise systemvarselvinduer. Noen varselvinduer kan ta over hele skjermen."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Lar appen være aktiv over andre apper eller deler av brukergrensesnittet. Dette kan virke inn på bruken din av grensesnittet i andre apper, eller endre det du tror du ser i andre apper."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"endre global animasjonshastighet"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Lar appen når som helst endre den globale animasjonshastigheten (raskere eller langsommere animasjoner)."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"administrere apptokener"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Lar appen opprette og administrere egne tokener, ved å forbigå normal Z-rekkefølge. Skal aldri være nødvendig for normale apper."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"fryse skjermbildet"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Tillater appen å midlertidig fryse skjermen for overgang til fullskjerm."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"trykke taster og kontrolknapper"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Lar appen levere sine egne inndatahendelser (tastetrykk osv.) til andre apper. Ondsinnede apper kan bruke dette til å ta over nettbrettet."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Lar appen levere sine egne inndatahendelser (tastetrykk osv.) til andre apper. Ondsinnede apper kan bruke dette til å ta over telefonen."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"installere apper direkte"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Lar appen installere nye eller oppdaterte Android-pakker. Ondsinnede apper kan bruke dette til å legge til nye apper med vilkårlig omfattende tillatelser."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"slette alle bufferdata for apper"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Lar appen frigjøre lagringsplass på nettbrettet ved å slette filer i katalogen for appbuffere. Tilgangen er veldig begrenset, vanligvis til systemprosesser."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Lar appen frigjøre lagringsplass på telefonen ved å slette filer i katalogen for appbuffere. Tilgangen er veldig begrenset, vanligvis til systemprosesser."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Lar appen frigjøre lagringsplass på nettbrettet ved å slette filer i bufferkataloger eller andre apper. Dette kan medføre tregere oppstart av andre apper, siden de må hente inn dataene sine på nytt."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Lar appen frigjøre lagringsplass på telefonen ved å slette filer i bufferkataloger eller andre apper. Dette kan medføre tregere oppstart av andre apper, siden de må hente inn dataene sine på nytt."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"flytte appressurser"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Lar appen flytte appressurser fra interne til eksterne medier, og omvendt."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"lese sensitive loggdata"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Lar appen få tilgang til flere kommandoer fra posisjonsangivere. Dette kan gjøre at appen forstyrrer GPS-funksjonen eller andre posisjonskilder."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"installere posisjonskilder"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Opprette fiktive posisjonskilder for testing eller installere en ny posisjonsangiver. Dette gjør at appen kan overstyre posisjonen eller statusen som rapporteres av ekte posisjonskilder, som for eksempel GPS eller posisjonsangivere."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"nøyaktig (GPS) posisjon"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Bruke kilder for nøyaktig posisjon på nettbrettet ditt, slik som Global Positioning System (GPS). Når posisjonstjenester er tilgjengelige og aktiverte, gjør denne tillatelsen at appen kan finne den nøyaktige posisjonen din."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Bruke kilder for nøyaktig posisjon på telefonen din, slik som Global Positioning System (GPS). Når posisjonstjenester er tilgjengelige og aktiverte, gjør denne tillatelsen at appen kan finne den nøyaktige posisjonen din."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"omtrentlig (nettverksbasert) posisjon"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Få omtrentlig posisjon fra posisjonsangivere ved bruk av nettverkskilder, slik som telefonmaster og Wi-Fi. Når disse posisjonstjenestene er tilgjengelige og aktiverte, gjør denne tillatelsen at appen kan finne den omtrentlige posisjonen din."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"presis posisjon (GPS- og nettverksbasert)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Lar appen se den nøyaktige posisjonen din ved hjelp av GPS (Global Positioning System) eller posisjonstjenester for nettverk, som for eksempel basestasjoner og Wi-Fi. Disse posisjonstjenestene må være slått på og tilgjengelig for enheten din, for at appen skal kunne bruke dem. Apper kan bruke dette til å fastslå hvor du er, og funksjonen kan medføre økt batteribruk."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"omtrentlig posisjon (nettverksbasert)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Lar appen se den omtrentlige posisjonen din. Denne posisjonen hentes fra posisjonstjenester som benytter posisjonskilder som for eksempel basestasjoner og Wi-Fi. Disse posisjonstjenestene må være slått på og tilgjengelig for enheten din, for at appen skal kunne bruke dem. Apper kan bruke dette til å finne ut omtrent hvor du er."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"få tilgang til SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Lar appen bruke grunnleggende SurfaceFlinger-funksjoner."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"lese skjermbufferet"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Lar appen lese innholdet i rammebufferen."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"konfigurere Wi-Fi-skjermer"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Tillater appen å konfigurere og koble til Wi-Fi-skjermer."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"kontrollere Wi-Fi-skjermer"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Tillater appen å kontrollere lavnivåfunksjoner i Wi-Fi-skjermer."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"endre lydinnstillinger"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Lar appen endre globale lydinnstillinger slik som volum og hvilken høyttaler som brukes for lydavspilling."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ta opp lyd"</string>
@@ -467,16 +526,16 @@
     <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"Lar appen endre telefonens tidssone."</string>
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"fungere som kontoadministrasjonstjenesten"</string>
     <string name="permdesc_accountManagerService" msgid="1948455552333615954">"Lar appen foreta anrop til kontoautentiseringstjenester."</string>
-    <string name="permlab_getAccounts" msgid="1086795467760122114">"finner kontoer på enheten"</string>
+    <string name="permlab_getAccounts" msgid="1086795467760122114">"finne kontoer på enheten"</string>
     <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Lar appen hente listen over kontoene nettbrettet kjenner. Dette kan inkludere kontoer som er opprettet av apper du har installert."</string>
     <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Lar appen hente listen over kontoene telefonen kjenner. Dette kan inkludere kontoer som er opprettet av apper du har installert."</string>
-    <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"oppretter kontoer og angir passord"</string>
+    <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"opprette kontoer og angi passord"</string>
     <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"Lar appen bruke kontoadministratoren sine rettigheter til kontoautentisering, herunder oppretting av kontoer samt innhenting og angivelse av passord."</string>
-    <string name="permlab_manageAccounts" msgid="4983126304757177305">"legger til eller fjerner kontoer"</string>
+    <string name="permlab_manageAccounts" msgid="4983126304757177305">"legge til eller fjerne kontoer"</string>
     <string name="permdesc_manageAccounts" msgid="8698295625488292506">"Lar appen utføre handlinger som å legge til og fjerne kontoer samt slette passord."</string>
     <string name="permlab_useCredentials" msgid="235481396163877642">"bruke kontoer på enheten"</string>
     <string name="permdesc_useCredentials" msgid="7984227147403346422">"Lar appen be om autentiseringstokener."</string>
-    <string name="permlab_accessNetworkState" msgid="4951027964348974773">"ser nettverkstilkoblinger"</string>
+    <string name="permlab_accessNetworkState" msgid="4951027964348974773">"se nettverkstilkoblinger"</string>
     <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Lar appen se informasjon om nettverkstilkoblinger, slik som hvilke nettverk som finnes og er tilkoblet."</string>
     <string name="permlab_createNetworkSockets" msgid="8018758136404323658">"full nettverkstilgang"</string>
     <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Lar appen opprette nettverkskontakter og bruke tilpassede nettverksprotokoller. Nettleseren og andre apper gjør det mulig å sende data til Internett, så denne tillatelsen er ikke nødvendig for å kunne sende data til Internett."</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"endrer Bluetooth-innstillinger"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Lar appen konfigurere det lokale Bluetooth-nettbrettet, samt oppdage og koble sammen med eksterne enheter."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Lar appen konfigurere den lokale Bluetooth-telefonen, samt oppdage og koble sammen med eksterne enheter."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"ser WiMAX-tilkoblinger"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"koble til eller fra WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Lar appen avgjøre hvorvidt WiMAX er aktivert og finne informasjon om eventuelle tilkoblede WiMAX-nettverk."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Endre WiMAX-status"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Lar appen koble nettbrettet til og fra WiMAX-nettverk."</string>
@@ -522,18 +581,20 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Lar appen endre strømmer som er synkronisert for øyeblikket. Ondsinnede apper kan endre de synkroniserte strømmene dine."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"leser uttrykkene du har lagt til i ordboken"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Lar appen lese alle ord, navn og uttrykk som brukeren har lagret i brukerordlisten."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"skrive i brukerdefinert ordliste"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"legge til ord i brukerdefinert ordliste"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Lar appen skrive nye ord i brukerordlisten."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"testadgang til beskyttet lagring"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"testadgang til beskyttet lagring"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Lar appen teste en tillatelse for USB-lagring som kommer til å bli tilgjengelig på fremtidige enheter."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Lar appen teste en tillatelse for USB-lagring som kommer til å bli tilgjengelig på fremtidige enheter."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Lar appen teste en tillatelse for SD-kortet som kommer til å bli tilgjengelig på fremtidige enheter."</string>
-    <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"endrer eller sletter innholdet i USB-lagringen"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"endre eller slette innholdet i USB-lagringen"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"endre eller slette innhold i SD-kortet"</string>
     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"Gir appen tillatelse til å skrive til USB-lagringen."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Lar appen skrive til SD-kortet."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"endre eller slette innhold på interne medier"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Lar appen endre innholdet i det interne lagringsmediet."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"åpne eksternlagring for alle brukere"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Tillater appen å åpne eksternlagring for alle brukere."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"tilgang til bufrede filer"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Lar appen lese og skrive til det bufrede filsystemet."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"foreta/motta Internett-anrop"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Krev at lagrede appdata krypteres."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Deaktiver kameraer"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Hindre bruk av alle kameraer på enheten."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Deaktiv. funksj. i tastelås"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Forhindre bruk av enkelte funksjoner når tastelåsen er på."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Hjemmenummer"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -674,7 +737,7 @@
     <string name="relationTypeSister" msgid="1735983554479076481">"Søster"</string>
     <string name="relationTypeSpouse" msgid="394136939428698117">"Ektefelle"</string>
     <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Egendefinert"</string>
-    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Startside"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Hjem"</string>
     <string name="sipAddressTypeWork" msgid="6920725730797099047">"Arbeid"</string>
     <string name="sipAddressTypeOther" msgid="4408436162950119849">"Annen"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Skriv inn PIN-kode"</string>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Prøv på nytt"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Du har overskredet grensen for opplåsingsforsøk med Ansiktslås"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Lader, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Fullt ladet"</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Oppladet"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Koble til en batterilader."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Mangler SIM-kort."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM-kortet mangler"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nettbrettet mangler SIM-kort."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Ikke noe SIM-kort i telefonen."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Sett inn et SIM-kort."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Mønsteret er slettet"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Celle er lagt til"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Mønsteret er fullført"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Legg til modul."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Tom"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Opplåsingsfeltet vises."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Opplåsingsfeltet skjules."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>-modul."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Brukervelgeren"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Status"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Kamera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Mediekontroll"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Endring av modulplasseringen har startet."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Endringen av modulplasseringen er ferdig."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Modulen <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> ble slettet."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Vis opplåsingsfeltet."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Opplåsning ved å dra med fingeren."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Mønsteropplåsning."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Ansiktsopplåsning."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-opplåsning."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Passordopplåsning."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mønsterområde."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Dra-felt."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopier URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Marker tekst"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Merket tekst"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"legg til i ordliste"</string>
-    <string name="deleteText" msgid="7070985395199629156">"slett"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Legg til i ordlisten"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Slett"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Inndatametode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksthandlinger"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Lite ledig lagringsplass"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Åpne trådløsnett i nærheten"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Pålogging til Wi-Fi-nettverk"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Logg deg på nettverket"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kan ikke koble til Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" har en dårlig Internett-tilkobling."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Til:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Skriv inn påkrevd PIN-kode:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefonen frakobles Wi-Fi midlertidig mens den er tilkoblet <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Sett inn tegn"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Sender SMS-meldinger"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sender et stort antall SMS. Vil du la appen fortsette å sende ut meldinger?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Tillat"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Sperr"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ønsker å sende en melding til &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Dette "<font fgcolor="#ffffb060">"kan føre til belastninger"</font>" på mobilkontoen din."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Dette kommer til å føre til belastninger på mobilkontoen din."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Send"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Avbryt"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Husk valget mitt"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Du kan endre dette senere i Innstillinger &gt; Apper"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Alltid tillat"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Aldri tillat"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kort er fjernet"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Det mobile nettverket forblir utilgjengelig inntil du starter på nytt med et gyldig SIM-kort."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Fullført"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Angi dato"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Lagre"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Ferdig"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Standard"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Trenger ingen rettigheter"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Skjul"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Vis alle"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NYTT: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NYTT: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Levert av <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Trenger ingen rettigheter"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"dette kan koste deg penger"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB-masselagring"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB koblet til"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Du har koblet deg til datamaskinen via USB. Trykk på knappen nedenfor hvis du vil kopiere filer mellom datamaskinen og Android-telefonens USB-lagring."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN er aktivert av <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Trykk for å administrere nettverket."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Koblet til <xliff:g id="SESSION">%s</xliff:g>. Trykk for å administrere nettverket."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Alltid-på VPN kobler til ..."</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Alltid-på VPN er tilkoblet"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Alltid-på VPN-feil"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Trykk for å tilbakestille tilkoblingen"</string>
     <string name="upload_file" msgid="2897957172366730416">"Velg fil"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Ingen fil er valgt"</string>
     <string name="reset" msgid="2448168080964209908">"Tilbakestill"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Del"</string>
     <string name="find" msgid="4808270900322985960">"Finn"</string>
     <string name="websearch" msgid="4337157977400211589">"Nettsøk"</string>
+    <string name="find_next" msgid="5742124618942193978">"Finn neste"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Finn forrige"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Posisjonsforespørsel fra <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Posisjonsforespørsel"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Forespurt av <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Hodetelefoner"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dokkhøyttalere"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-lyd"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-lyd"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fullført"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Medieutgang"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Skanner ..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Kobler til ..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Tilgjengelig"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Ikke tilgjengelig"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Innebygd skjerm"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-skjerm"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlegg #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Trådløs skjermdeling er tilkoblet"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Denne skjermen vises på en annen enhet"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Koble fra"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Nødnummer"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Har du glemt mønsteret?"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Feil mønster"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Feil passord"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Feil PIN-kode"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Prøv på nytt om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Tegn mønsteret ditt"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Skriv inn PIN-koden for SIM-kortet"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Skriv inn PIN-koden"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Skriv inn passordet"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM-kortet er nå deaktivert. Skriv inn PUK-koden for å fortsette. Ta kontakt med operatøren for mer informasjon."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Tast inn ønsket PIN-kode"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Bekreft ønsket PIN-kode"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Låser opp SIM-kortet ..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Feil PIN-kode."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Skriv inn en PIN-kode på fire til åtte sifre."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK-koden skal være på åtte eller flere siffer."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Skriv inn den korrekte PUK-koden på nytt. Gjentatte forsøk kommer til å deaktivere SIM-kortet."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN-kodene stemmer ikke overens"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"For mange forsøk på tegning av mønster"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Logg deg på med Google-kontoen din for å låse opp."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Brukernavn (e-postadresse)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Passord"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Logg på"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Ugyldig brukernavn eller passord."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Har du glemt brukernavnet eller passordet?"\n"Gå til "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Sjekker kontoen ..."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Du har oppgitt feil PIN-kode <xliff:g id="NUMBER_0">%d</xliff:g> ganger. "\n\n"Prøv på nytt om <xliff:g id="NUMBER_1">%d</xliff:g> sekunder."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Du har tastet inn passordet ditt feil <xliff:g id="NUMBER_0">%d</xliff:g> ganger. "\n\n"Prøv på nytt om <xliff:g id="NUMBER_1">%d</xliff:g> sekunder."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Du har tegnet opplåsningsmønsteret ditt feil <xliff:g id="NUMBER_0">%d</xliff:g> ganger. "\n\n"Prøv på nytt om <xliff:g id="NUMBER_1">%d</xliff:g> sekunder."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Du har oppgitt feil opplåsningspassord for nettbrettet <xliff:g id="NUMBER_0">%d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%d</xliff:g> gale forsøk, tilbakestilles nettbrettet til fabrikkstandard og all data går tapt."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Du har oppgitt feil opplåsningspassord for telefonen <xliff:g id="NUMBER_0">%d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%d</xliff:g> gale forsøk, tilbakestilles telefonen til fabrikkstandard og all data går tapt."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Du har oppgitt feil opplåsningspassord for nettbrettet <xliff:g id="NUMBER">%d</xliff:g> ganger. Telefonen tilbakestilles nå til fabrikkstandard."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Du har oppgitt feil opplåsningspassord for telefonen <xliff:g id="NUMBER">%d</xliff:g> ganger. Telefonen tilbakestilles nå til fabrikkstandard."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Du har tegnet opplåsningsmønsteret feil <xliff:g id="NUMBER_0">%d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%d</xliff:g> gale forsøk, blir du bedt om å låse opp nettbrettet via en e-postkonto."\n\n" Prøv på nytt om <xliff:g id="NUMBER_2">%d</xliff:g> sekunder."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Du har tegnet opplåsningsmønsteret feil <xliff:g id="NUMBER_0">%d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%d</xliff:g> gale forsøk, blir du bedt om å låse opp telefonen via en e-postkonto."\n\n" Prøv på nytt om <xliff:g id="NUMBER_2">%d</xliff:g> sekunder."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Fjern"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Vil du øke lydnivået over trygt nivå?"\n"Lytting på høyt lydnivå i lange perioder kan skade hørselen din."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Fortsett å holde nede to fingre for å aktivere tilgjengelighet."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Tilgjengelighet er aktivert."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Tilgjengelighetstjenesten ble avbrutt."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Gjeldende bruker: <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Eier"</string>
 </resources>
diff --git a/core/res/res/values-nl/donottranslate-cldr.xml b/core/res/res/values-nl/donottranslate-cldr.xml
index ca3813f..1495a48 100644
--- a/core/res/res/values-nl/donottranslate-cldr.xml
+++ b/core/res/res/values-nl/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">januari</string>
-    <string name="month_long_standalone_february">februari</string>
-    <string name="month_long_standalone_march">maart</string>
-    <string name="month_long_standalone_april">april</string>
-    <string name="month_long_standalone_may">mei</string>
-    <string name="month_long_standalone_june">juni</string>
-    <string name="month_long_standalone_july">juli</string>
-    <string name="month_long_standalone_august">augustus</string>
-    <string name="month_long_standalone_september">september</string>
-    <string name="month_long_standalone_october">oktober</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">december</string>
-
-    <string name="month_long_january">januari</string>
-    <string name="month_long_february">februari</string>
-    <string name="month_long_march">maart</string>
-    <string name="month_long_april">april</string>
-    <string name="month_long_may">mei</string>
-    <string name="month_long_june">juni</string>
-    <string name="month_long_july">juli</string>
-    <string name="month_long_august">augustus</string>
-    <string name="month_long_september">september</string>
-    <string name="month_long_october">oktober</string>
-    <string name="month_long_november">november</string>
-    <string name="month_long_december">december</string>
-
-    <string name="month_medium_january">jan.</string>
-    <string name="month_medium_february">feb.</string>
-    <string name="month_medium_march">mrt.</string>
-    <string name="month_medium_april">apr.</string>
-    <string name="month_medium_may">mei</string>
-    <string name="month_medium_june">jun.</string>
-    <string name="month_medium_july">jul.</string>
-    <string name="month_medium_august">aug.</string>
-    <string name="month_medium_september">sep.</string>
-    <string name="month_medium_october">okt.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">dec.</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">zondag</string>
-    <string name="day_of_week_long_monday">maandag</string>
-    <string name="day_of_week_long_tuesday">dinsdag</string>
-    <string name="day_of_week_long_wednesday">woensdag</string>
-    <string name="day_of_week_long_thursday">donderdag</string>
-    <string name="day_of_week_long_friday">vrijdag</string>
-    <string name="day_of_week_long_saturday">zaterdag</string>
-
-    <string name="day_of_week_medium_sunday">zo</string>
-    <string name="day_of_week_medium_monday">ma</string>
-    <string name="day_of_week_medium_tuesday">di</string>
-    <string name="day_of_week_medium_wednesday">wo</string>
-    <string name="day_of_week_medium_thursday">do</string>
-    <string name="day_of_week_medium_friday">vr</string>
-    <string name="day_of_week_medium_saturday">za</string>
-
-    <string name="day_of_week_short_sunday">zo</string>
-    <string name="day_of_week_short_monday">ma</string>
-    <string name="day_of_week_short_tuesday">di</string>
-    <string name="day_of_week_short_wednesday">wo</string>
-    <string name="day_of_week_short_thursday">do</string>
-    <string name="day_of_week_short_friday">vr</string>
-    <string name="day_of_week_short_saturday">za</string>
-
-    <string name="day_of_week_shortest_sunday">Z</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">D</string>
-    <string name="day_of_week_shortest_wednesday">W</string>
-    <string name="day_of_week_shortest_thursday">D</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">Z</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Gisteren</string>
-    <string name="today">Vandaag</string>
-    <string name="tomorrow">Morgen</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 0af5649..21fe1cc 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefoonopties"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Schermvergrendeling"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Uitschakelen"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Foutenrapport"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Foutenrapport genereren"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Hiermee worden gegevens over de huidige status van uw apparaat verzameld en als e-mail verzonden. Wanneer u een foutenrapport start, duurt het even voordat het kan worden verzonden. Even geduld alstublieft."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Stille modus"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Geluid is UIT"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Geluid is AAN"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Uw berichten"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Sms, e-mail en andere berichten lezen en schrijven."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Uw persoonlijke informatie"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Rechtstreekse toegang tot de op uw tablet opgeslagen contacten en agenda."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Rechtstreekse toegang tot de op uw telefoon opgeslagen contacten en agenda."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Rechtstreeks toegang krijgen tot informatie over u die is opgeslagen op uw contactkaart."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Uw sociale informatie"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Rechtstreeks toegang krijgen tot informatie over uw contacten en sociale connecties."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Uw locatie"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Uw fysieke locatie bijhouden."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Netwerkcommunicatie"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Toegang tot verschillende netwerkfuncties."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Toegang tot apparaten en netwerken via Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Audio-instellingen"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Audio-instellingen wijzigen."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"De accu beïnvloeden"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Functies gebruiken waardoor de accu snel leeg kan raken."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Agenda"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Rechtstreeks toegang krijgen tot agenda en afspraken."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Gebruikerswoordenboek lezen"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Woorden lezen in het gebruikerswoordenboek."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Gebruikerswoordenboek schrijven"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Woorden toevoegen aan het gebruikerswoordenboek."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Bladwijzers en geschiedenis"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Rechtstreeks toegang krijgen tot bladwijzers en browsergeschiedenis."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarm"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"De wekker instellen."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Voicemail"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Rechtstreeks toegang krijgen tot voicemail."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Microfoon"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Rechtstreeks toegang krijgen tot de microfoon om geluid op te nemen."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Camera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Rechtstreeks toegang krijgen tot de camera om afbeeldingen of video\'s vast te leggen."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Informatie over uw applicaties"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Mogelijkheid om het gedrag van andere applicaties op uw apparaat te beïnvloeden."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Achtergrond"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"De achtergrondinstellingen van het apparaat wijzigen."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Klok"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"De tijd of tijdzone van het apparaat wijzigen."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Statusbalk"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"De instellingen van de apparaatstatusbalk wijzigen."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Synchronisatie-instellingen"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Toegang krijgen tot de synchronisatie-instellingen."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Uw accounts"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Toegang tot de beschikbare accounts."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Bedieningselementen hardware"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Toegang tot en beheer van het systeem op lager niveau."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Ontwikkelingshulpprogramma\'s"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Functies die alleen nodig zijn voor app-ontwikkelaars."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Gebruikersinterface van andere applicaties"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"De gebruikersinterface van andere applicaties beïnvloeden."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Opslagruimte"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Toegang krijgen tot USB-opslag."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Toegang tot de SD-kaart."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Hiermee kan de app WAP-berichten ontvangen en verwerken. Dit betekent dat de app berichten die naar uw apparaat zijn verzonden, kan bijhouden of verwijderen zonder deze aan u weer te geven."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"actieve apps ophalen"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Hiermee kan de app informatie ophalen over actieve en recent uitgevoerde taken. Zo kan de app informatie vinden over welke apps op het apparaat worden gebruikt."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interactie tussen gebruikers"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Hiermee kan de app acties uitvoeren voor verschillende gebruikers van het apparaat. Schadelijke apps kunnen dit gebruiken om de beveiliging tussen gebruikers te schenden."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"volledige toestemming voor interactie tussen gebruikers"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Hiermee is alle mogelijke interactie tussen gebruikers toegestaan."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"gebruikers beheren"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Toestaan dat apps gebruikers op het apparaat beheren, inclusief het opvragen van gegevens en het maken en verwijderen van gebruikers."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"details van actieve apps ophalen"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Hiermee kan de app gedetailleerde informatie over huidige en recent uitgevoerde taken ophalen. Schadelijke apps kunnen op deze manier mogelijk privé-informatie over andere apps achterhalen."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"actieve apps opnieuw rangschikken"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Hiermee kan de app de interne systeemstatus ophalen. Schadelijke apps kunnen een grote hoeveelheid persoonlijke en beveiligde informatie ophalen die ze normaal gesproken nooit nodig hebben."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"scherminhoud ophalen"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Hiermee kan de app de inhoud van het actieve venster ophalen. Schadelijke apps kunnen de volledige inhoud van het venster ophalen en alle tekst bekijken, behalve wachtwoorden."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"toegankelijkheid tijdelijk inschakelen"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Een app toestaan toegankelijkheid tijdelijk in te schakelen op het apparaat. Schadelijke apps kunnen toegankelijkheid inschakelen zonder toestemming van de gebruiker."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"venstergegevens ophalen"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Toestaan dat een app gegevens over vensters kan ophalen uit vensterbeheer. Schadelijke apps kunnen gegevens ophalen die zijn bedoeld voor interne systeemfunctionaliteit."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"evenementen filteren"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Toestaan dat een app een invoerfilter registreert waarmee de streams van alle gebruikersgebeurtenissen worden gefilterd voordat deze worden verzonden. Schadelijke apps kunnen de gebruikersinterface van het systeem beheren zonder tussenkomst van de gebruiker."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"display vergroten"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Een app toestaan de inhoud van een display te vergroten. Schadelijke apps kunnen de display-inhoud transformeren op een manier waardoor het apparaat onbruikbaar wordt."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"gedeeltelijke uitschakeling"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Hiermee wordt activiteitenbeheer uitgeschakeld. Er wordt geen volledige uitschakeling uitgevoerd."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"schakelen tussen apps voorkomen"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Hiermee kan de app het maximale aantal processen beheren dat kan worden uitgevoerd. Nooit nodig voor normale apps."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"achtergrondapps gedwongen stoppen"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Hiermee kan de app bepalen of activiteiten worden afgerond zodra ze naar de achtergrond worden verplaatst. Dit is nooit nodig voor normale apps."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"accustatistieken aanpassen"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Hiermee kan de app verzamelde accustatistieken wijzigen. Niet voor gebruik door normale apps."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"accustatistieken lezen"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Hiermee kan de app het huidige accugebruik voor gegevens op laag niveau lezen. Een app kan hierdoor mogelijk gedetailleerde informatie achterhalen over de door u gebruikte apps."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"accustatistieken aanpassen"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Hiermee kan de app verzamelde accustatistieken wijzigen. Niet voor gebruik door normale apps."</string>
     <string name="permlab_backup" msgid="470013022865453920">"systeemback-up en -herstel beheren"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Hiermee kan de app het beheer van het mechanisme voor systeemback-up en -herstel beheren. Niet voor gebruik door normale apps."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"een volledige back-up- of herstelbewerking bevestigen"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"niet-geautoriseerde vensters weergeven"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Hiermee kan de app vensters maken die door de interne systeemgebruikersinterface worden gebruikt. Niet voor gebruik door normale apps."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"weergeven over andere apps"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Hiermee kan de app vensters met systeemwaarschuwingen weergeven. Sommige waarschuwingsvensters kunnen het volledige scherm overnemen."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Hiermee kan de app tekenen op andere apps of de gebruikersinterface. De app kan uw gebruik van de interface in alle apps verstoren, of wijzigen wat u in andere apps denkt te zien."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"algemene animatiesnelheid wijzigen"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Hiermee kan de app op elk gewenst moment de algemene animatiesnelheid wijzigen (snellere of tragere animaties)."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"app-tokens beheren"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Hiermee kan de app zelf tokens maken en beheren buiten de normale Z-rangschikking om. Dit is in principe nooit nodig voor normale apps."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"scherm bevriezen"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"De app toestaan het scherm tijdelijk te bevriezen voor een volledige schermovergang."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"drukken op toetsen en bedieningselementen"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Hiermee kan de app de eigen invoergebeurtenissen (zoals toetsaanslagen) aan andere apps doorgeven. Schadelijke apps kunnen dit gebruiken om de tablet over te nemen."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Hiermee kan de app de eigen invoergebeurtenissen (toetsaanslagen, enzovoort) aan andere apps doorgeven. Schadelijke apps kunnen dit gebruiken om de telefoon over te nemen."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"apps rechtstreeks installeren"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Hiermee kan de app nieuwe of bijgewerkte Android-pakketten installeren. Schadelijke apps kunnen hiermee nieuwe apps toevoegen met willekeurig belangrijke rechten."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"alle cachegegevens van app verwijderen"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Hiermee kan de app opslagruimte op de tablet vrij maken door bestanden te verwijderen uit de cachemap van de app. De toegang is doorgaans beperkt tot het systeemproces."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Hiermee kan de app opslagruimte op de telefoon vrij maken door bestanden te verwijderen uit de cachemap van de app. De toegang is doorgaans beperkt tot het systeemproces."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Hiermee kan de app opslagruimte op de tablet vrij maken door bestanden te verwijderen uit de cachemappen van andere apps. Hierdoor worden andere apps mogelijk langzamer gestart, omdat ze gegevens opnieuw moeten ophalen."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Hiermee kan de app opslagruimte op de telefoon vrij maken door bestanden te verwijderen uit de cachemappen van andere apps. Hierdoor worden andere apps mogelijk langzamer gestart, omdat ze gegevens opnieuw moeten ophalen."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"appbronnen verplaatsen"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Hiermee kan de app andere appbronnen verplaatsen van interne naar externe media en andersom."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"gevoelige logbestandsgegevens lezen"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Hiermee krijgt de app toegang tot extra opdrachten voor de locatieprovider. De app kan hiermee de werking van GPS of andere locatiebronnen te verstoren."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"toestemming om een locatieprovider te installeren"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Voorbeeld-locatiebronnen maken voor tests of een nieuwe locatieprovider instellen. Hiermee kan de app de locatie en/of status overschrijven van andere locatiebronnen zoals GPS of locatieproviders."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"nauwkeurige locatie (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Toegang tot nauwkeurige locatiebronnen zoals het GPS-systeem op de tablet. Wanneer locatieservices beschikbaar en ingeschakeld zijn, kan de app met deze toestemming uw nauwkeurige locatie bepalen."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Toegang tot nauwkeurige locatiebronnen zoals het GPS-systeem op de telefoon. Wanneer locatieservices beschikbaar en ingeschakeld zijn, kan de app met deze toestemming uw nauwkeurige locatie bepalen."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"geschatte locatie (netwerkgebaseerd)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Toegang tot geschatte locatie via locatieproviders op basis van netwerkbronnen zoals telefoonmasten en wifi. Wanneer deze locatieservices beschikbaar en ingeschakeld zijn, kan de app met deze toestemming uw geschatte locatie bepalen."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"precieze locatie (GPS- en netwerkgebaseerd)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Hiermee kan de app uw precieze locatie bepalen via GPS (Global Positioning System) of netwerklocatiebronnen zoals zendmasten en wifi. Deze locatieservices moeten zijn ingeschakeld en beschikbaar zijn op uw apparaat voordat de app ze kan gebruiken. Apps kunnen dit gebruiken om te bepalen waar u bent en verbruiken mogelijk extra acculading."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"geschatte locatie (netwerkgebaseerd)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Hiermee kan de app beschikken over uw geschatte locatie. Deze locatie wordt afgeleid van locatieservices die netwerklocatiebronnen zoals zendmasten en wifi gebruiken. Deze locatieservices moeten zijn ingeschakeld en beschikbaar zijn op uw apparaat voordat de app ze kan gebruiken. Apps kunnen dit gebruiken om ongeveer te bepalen waar u zich bevindt."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"toegang tot SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Hiermee kan de app SurfaceFlinger-functies op laag niveau gebruiken."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"framebuffer lezen"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Hiermee kan de app de inhoud van de framebuffer lezen."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"wifi-displays configureren"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"De app toestaan wifi-displays te configureren en hiermee verbinding te maken."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"wifi-displays beheren"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"De app toestaan minder belangrijke functies van wifi-displays te beheren."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"uw audio-instellingen wijzigen"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Hiermee kan de app algemene audio-instellingen wijzigen zoals het volume en welke luidspreker wordt gebruikt voor de uitvoer."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"audio opnemen"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"Bluetooth-instellingen openen"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Hiermee kan de app de lokale Bluetooth-tablet configureren en externe apparaten zoeken en koppelen."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Hiermee kan de app de lokale Bluetooth-telefoon configureren en externe apparaten zoeken en koppelen."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"WiMAX-verbindingen weergeven"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX-verbinding maken en verbreken"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Hiermee kan de app bepalen of WiMAX is ingeschakeld en informatie bekijken over alle WiMAX-netwerken waarmee verbinding is gemaakt."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX-status wijzigen"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Hiermee kan de app de tablet verbinden met WiMAX-netwerken en de verbinding daarmee verbreken."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Hiermee kan de app uw momenteel gesynchroniseerde feeds aanpassen. Schadelijke apps kunnen uw gesynchroniseerde feeds wijzigen."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"termen lezen die u heeft toegevoegd aan het woordenboek"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Hiermee kan de app alle woorden, namen en woordcombinaties lezen die de gebruiker heeft opgeslagen in het gebruikerswoordenboek."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"schrijven naar door gebruiker gedefinieerd woordenboek"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"woorden toevoegen aan het gebruikerswoordenboek"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Hiermee kan de app nieuwe woorden schrijven naar het gebruikerswoordenboek."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"testtoegang tot beveiligde opslag"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"testtoegang tot beveiligde opslag"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Hiermee kan de app toestemming testen voor USB-opslag die beschikbaar komt op toekomstige apparaten."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Hiermee kan de app toestemming testen voor USB-opslag op toekomstige apparaten."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Hiermee kan de app toestemming testen voor de SD-kaart die beschikbaar komt op toekomstige apparaten."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"de inhoud van uw USB-opslag aanpassen of verwijderen"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"de inhoud van uw SD-kaart aanpassen of verwijderen"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Hiermee kan de app schrijven naar de SD-kaart."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"inh. mediaopsl. wijz./verw."</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Hiermee kan de app de inhoud van de interne mediaopslag aanpassen."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"toegang tot externe opslag van alle gebruikers"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Hiermee krijgt de app toegang tot externe opslag van alle gebruikers."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"het cachebestandssysteem openen"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Hiermee kan de app het cachebestandssysteem lezen en schrijven."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"internetoproepen starten/ontvangen"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Vereisen dat opgeslagen appgegevens kunnen worden gecodeerd."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Camera\'s uitschakelen"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Het gebruik van alle apparaatcamera\'s voorkomen."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Functies uit in toetsblokk."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Gebruik van bepaalde functies voorkomen in toetsblokkering."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Thuis"</item>
     <item msgid="869923650527136615">"Mobiel"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Nogmaals proberen"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Maximaal aantal pogingen voor Face Unlock overschreden"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Opladen, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Opgeladen."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Opgeladen"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Sluit de oplader aan."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Geen SIM-kaart."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Geen simkaart"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Geen SIM-kaart in tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Geen SIM-kaart in telefoon."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Plaats een simkaart."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Patroon gewist"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Cel toegevoegd"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Patroon voltooid"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Widget toevoegen."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Leeg"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Ontgrendelingsgebied uitgevouwen."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Ontgrendelingsgebied samengevouwen."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Gebruikersselectie"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Status"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Camera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Mediabediening"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Opnieuw indelen van widget gestart."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Opnieuw indelen van widget beëindigd."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> verwijderd."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Ontgrendelingsgebied uitvouwen."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Ontgrendeling via schuiven."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Ontgrendeling via patroon."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Ontgrendeling via gezichtsherkenning."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Ontgrendeling via pincode."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Ontgrendeling via wachtwoord."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Tekengebied voor patroon."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Schuifgebied."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"Alt"</string>
@@ -820,7 +903,7 @@
     <string name="searchview_description_query" msgid="5911778593125355124">"Zoekopdracht"</string>
     <string name="searchview_description_clear" msgid="1330281990951833033">"Zoekopdracht wissen"</string>
     <string name="searchview_description_submit" msgid="2688450133297983542">"Zoekopdracht verzenden"</string>
-    <string name="searchview_description_voice" msgid="2453203695674994440">"Spraakgestuurd zoeken"</string>
+    <string name="searchview_description_voice" msgid="2453203695674994440">"Gesproken zoekopdrachten"</string>
     <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"\'Verkennen via aanraking\' aan?"</string>
     <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> wil \'Verkennen via aanraking\' inschakelen. Wanneer \'Verkennen via aanraking\' is ingeschakeld, kunt u beschrijvingen beluisteren of bekijken van wat er onder uw vinger staat of aanraakbewerkingen uitvoeren op de tablet."</string>
     <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> wil \'Verkennen via aanraking\' inschakelen. Wanneer \'Verkennen via aanraking\' is ingeschakeld, kunt u beschrijvingen beluisteren of bekijken van wat er onder uw vinger staat of aanraakbewerkingen uitvoeren op de telefoon."</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"URL kopiëren"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Tekst selecteren"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Tekstselectie"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"toevoegen aan woordenboek"</string>
-    <string name="deleteText" msgid="7070985395199629156">"verwijderen"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Toevoegen aan woordenboek"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Verwijderen"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Invoermethode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tekstacties"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Opslagruimte is bijna vol"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Open Wi-Fi-netwerken beschikbaar"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Aanmelden bij wifi-netwerk"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Aanmelden bij netwerk"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kan geen verbinding maken met Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" heeft een slechte internetverbinding."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Naar:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Voer de gewenste pincode in:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Pincode"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"De verbinding met het wifi-netwerk wordt tijdelijk uitgeschakeld terwijl de telefoon verbonden is met <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Teken invoegen"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS-berichten verzenden"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; verzendt moment een groot aantal sms-berichten. Wilt u toestaan ​​dat deze app berichten blijft verzenden?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Toestaan"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Weigeren"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; wil graag een bericht verzenden naar &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Dit "<font fgcolor="#ffffb060">"kan leiden tot kosten"</font>" in uw mobiele account."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Dit leidt tot kosten in uw mobiele account."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Verzenden"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Annuleren"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Mijn keuze onthouden"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"U kunt dit later wijzigen in \'Instellingen\' &gt; \'Apps\'"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Altijd toestaan"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nooit toestaan"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Simkaart verwijderd"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Het mobiele netwerk is niet beschikbaar totdat u het apparaat opnieuw start met een geldige simkaart."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Gereed"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Datum instellen"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Instellen"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Gereed"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Standaard"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Geen machtigingen vereist"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Verbergen"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Alles weergeven"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NIEUW: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NIEUW: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Geleverd door <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Geen machtigingen vereist"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"hieraan kunnen kosten zijn verbonden"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB-massaopslag"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB-verbinding"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"U heeft uw telefoon via USB op uw computer aangesloten. Raak de knop hieronder aan als u bestanden tussen uw computer en de USB-opslag van uw Android wilt kopiëren."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN wordt geactiveerd door <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Raak aan om het netwerk te beheren."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Verbonden met <xliff:g id="SESSION">%s</xliff:g>. Tik om het netwerk te beheren."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Always-on VPN-verbinding maken…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Always-on VPN-verbinding"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Fout met Always-on VPN"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Raak dit aan om de verbinding opnieuw in te stellen"</string>
     <string name="upload_file" msgid="2897957172366730416">"Bestand kiezen"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Geen bestand geselecteerd"</string>
     <string name="reset" msgid="2448168080964209908">"Opnieuw instellen"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Delen"</string>
     <string name="find" msgid="4808270900322985960">"Vinden"</string>
     <string name="websearch" msgid="4337157977400211589">"Online zoeken"</string>
+    <string name="find_next" msgid="5742124618942193978">"Volgende zoeken"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Vorige zoeken"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Locatieverzoek van <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Locatieverzoek"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Aangevraagd door <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefoon"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Hoofdtelefoon"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dockluidsprekers"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-audio"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Systeem"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-audio"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Gereed"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Media-uitvoer"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Scannen..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Verbinden..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Beschikbaar"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Niet beschikbaar"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Ingebouwd scherm"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-scherm"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Draadloze display is aangesloten"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Dit scherm wordt op een ander apparaat weergegeven"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Verbinding verbreken"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Noodoproep"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Patroon vergeten"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Onjuist patroon"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Onjuist wachtwoord"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Onjuiste pincode"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Probeer het over <xliff:g id="NUMBER">%d</xliff:g> seconden opnieuw."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Teken uw patroon"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Geef de pincode van de simkaart op"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Pincode opgeven"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Wachtwoord invoeren"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"De simkaart is nu uitgeschakeld. Geef de PUK-code op om door te gaan. Neem contact op met de provider voor informatie."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Gewenste pincode opgeven"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Gewenste pincode bevestigen"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Simkaart ontgrendelen..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Onjuiste pincode."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Voer een pincode van 4 tot 8 cijfers in."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"De PUK-code is minimaal acht nummers lang."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Geef de juiste PUK-code opnieuw op. Bij herhaalde pogingen wordt de simkaart permanent uitgeschakeld."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Pincodes komen niet overeen"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Te veel patroonpogingen"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Als u wilt ontgrendelen, moet u zich aanmelden bij uw Google-account."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Gebruikersnaam (e-mail)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Wachtwoord"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Aanmelden"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Ongeldige gebruikersnaam of wachtwoord."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Bent u uw gebruikersnaam of wachtwoord vergeten?"\n"Ga naar "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Account controleren…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"U heeft uw pincode <xliff:g id="NUMBER_0">%d</xliff:g> keer onjuist getypt. "\n\n"Probeer het over <xliff:g id="NUMBER_1">%d</xliff:g> seconden opnieuw."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"U heeft uw wachtwoord <xliff:g id="NUMBER_0">%d</xliff:g> keer onjuist getypt. "\n\n"Probeer het over <xliff:g id="NUMBER_1">%d</xliff:g> seconden opnieuw."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"U heeft uw ontgrendelingspatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer onjuist getekend. "\n\n"Probeer het over <xliff:g id="NUMBER_1">%d</xliff:g> seconden opnieuw."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"U heeft <xliff:g id="NUMBER_0">%d</xliff:g> keer geprobeerd de tablet op een onjuiste manier te ontgrendelen. Na nog eens <xliff:g id="NUMBER_1">%d</xliff:g> mislukte pogingen worden de fabrieksinstellingen hersteld op de tablet en gaan alle gebruikersgegevens verloren."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"U heeft nu <xliff:g id="NUMBER_0">%d</xliff:g> keer geprobeerd de telefoon op een onjuiste manier te ontgrendelen. Na nog eens <xliff:g id="NUMBER_1">%d</xliff:g> mislukte pogingen worden de fabrieksinstellingen hersteld op de telefoon en gaan alle gebruikersgegevens verloren."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"U heeft <xliff:g id="NUMBER">%d</xliff:g> keer geprobeerd de tablet op een onjuiste manier te ontgrendelen. De fabrieksinstellingen worden nu hersteld op de tablet."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"U heeft <xliff:g id="NUMBER">%d</xliff:g> keer geprobeerd de telefoon op een onjuiste manier te ontgrendelen. De fabrieksinstellingen worden nu hersteld op de telefoon."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"U heeft uw ontgrendelingspatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer onjuist getekend. Na nog eens <xliff:g id="NUMBER_1">%d</xliff:g> mislukte pogingen wordt u gevraagd uw tablet te ontgrendelen via een e-mailaccount."\n\n" Probeer het over <xliff:g id="NUMBER_2">%d</xliff:g> seconden opnieuw."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"U heeft uw ontgrendelingspatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer onjuist getekend. Na nog eens <xliff:g id="NUMBER_1">%d</xliff:g> mislukte pogingen wordt u gevraagd uw telefoon te ontgrendelen via een e-mailaccount."\n\n" Probeer het over <xliff:g id="NUMBER_2">%d</xliff:g> seconden opnieuw."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Verwijderen"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Wilt u het volume verhogen tot boven het aanbevolen geluidsniveau?"\n"Te lang luisteren op een te hoog volume kan leiden tot gehoorbeschadiging."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Blijf het scherm met twee vingers aanraken om toegankelijkheid in te schakelen."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Toegankelijkheid ingeschakeld."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Toegankelijkheid geannuleerd."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Huidige gebruiker <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Eigenaar"</string>
 </resources>
diff --git a/core/res/res/values-pl/donottranslate-cldr.xml b/core/res/res/values-pl/donottranslate-cldr.xml
index 2950e60..53f0c36 100644
--- a/core/res/res/values-pl/donottranslate-cldr.xml
+++ b/core/res/res/values-pl/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">styczeń</string>
-    <string name="month_long_standalone_february">luty</string>
-    <string name="month_long_standalone_march">marzec</string>
-    <string name="month_long_standalone_april">kwiecień</string>
-    <string name="month_long_standalone_may">maj</string>
-    <string name="month_long_standalone_june">czerwiec</string>
-    <string name="month_long_standalone_july">lipiec</string>
-    <string name="month_long_standalone_august">sierpień</string>
-    <string name="month_long_standalone_september">wrzesień</string>
-    <string name="month_long_standalone_october">październik</string>
-    <string name="month_long_standalone_november">listopad</string>
-    <string name="month_long_standalone_december">grudzień</string>
-
-    <string name="month_long_january">stycznia</string>
-    <string name="month_long_february">lutego</string>
-    <string name="month_long_march">marca</string>
-    <string name="month_long_april">kwietnia</string>
-    <string name="month_long_may">maja</string>
-    <string name="month_long_june">czerwca</string>
-    <string name="month_long_july">lipca</string>
-    <string name="month_long_august">sierpnia</string>
-    <string name="month_long_september">września</string>
-    <string name="month_long_october">października</string>
-    <string name="month_long_november">listopada</string>
-    <string name="month_long_december">grudnia</string>
-
-    <string name="month_medium_january">sty</string>
-    <string name="month_medium_february">lut</string>
-    <string name="month_medium_march">mar</string>
-    <string name="month_medium_april">kwi</string>
-    <string name="month_medium_may">maj</string>
-    <string name="month_medium_june">cze</string>
-    <string name="month_medium_july">lip</string>
-    <string name="month_medium_august">sie</string>
-    <string name="month_medium_september">wrz</string>
-    <string name="month_medium_october">paź</string>
-    <string name="month_medium_november">lis</string>
-    <string name="month_medium_december">gru</string>
-
-    <string name="month_shortest_january">s</string>
-    <string name="month_shortest_february">l</string>
-    <string name="month_shortest_march">m</string>
-    <string name="month_shortest_april">k</string>
-    <string name="month_shortest_may">m</string>
-    <string name="month_shortest_june">c</string>
-    <string name="month_shortest_july">l</string>
-    <string name="month_shortest_august">s</string>
-    <string name="month_shortest_september">w</string>
-    <string name="month_shortest_october">p</string>
-    <string name="month_shortest_november">l</string>
-    <string name="month_shortest_december">g</string>
-
-    <string name="day_of_week_long_sunday">niedziela</string>
-    <string name="day_of_week_long_monday">poniedziałek</string>
-    <string name="day_of_week_long_tuesday">wtorek</string>
-    <string name="day_of_week_long_wednesday">środa</string>
-    <string name="day_of_week_long_thursday">czwartek</string>
-    <string name="day_of_week_long_friday">piątek</string>
-    <string name="day_of_week_long_saturday">sobota</string>
-
-    <string name="day_of_week_medium_sunday">niedz.</string>
-    <string name="day_of_week_medium_monday">pon.</string>
-    <string name="day_of_week_medium_tuesday">wt.</string>
-    <string name="day_of_week_medium_wednesday">śr.</string>
-    <string name="day_of_week_medium_thursday">czw.</string>
-    <string name="day_of_week_medium_friday">pt.</string>
-    <string name="day_of_week_medium_saturday">sob.</string>
-
-    <string name="day_of_week_short_sunday">niedz.</string>
-    <string name="day_of_week_short_monday">pon.</string>
-    <string name="day_of_week_short_tuesday">wt.</string>
-    <string name="day_of_week_short_wednesday">śr.</string>
-    <string name="day_of_week_short_thursday">czw.</string>
-    <string name="day_of_week_short_friday">pt.</string>
-    <string name="day_of_week_short_saturday">sob.</string>
-
-    <string name="day_of_week_shortest_sunday">N</string>
-    <string name="day_of_week_shortest_monday">P</string>
-    <string name="day_of_week_shortest_tuesday">W</string>
-    <string name="day_of_week_shortest_wednesday">Ś</string>
-    <string name="day_of_week_shortest_thursday">C</string>
-    <string name="day_of_week_shortest_friday">P</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Wczoraj</string>
-    <string name="today">Dzisiaj</string>
-    <string name="tomorrow">Jutro</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 229012b..6f7c072 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opcje telefonu"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Blokada ekranu"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Wyłącz"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Zgłoszenie błędu"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Zgłoś błąd"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Informacje o bieżącym stanie urządzenia zostaną zebrane i wysłane e-mailem. Przygotowanie zgłoszenia błędu do wysłania chwilę potrwa, więc zachowaj cierpliwość."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Tryb cichy"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Dźwięk jest wyłączony"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Dźwięk jest włączony"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Twoje wiadomości"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Czytanie i zapisywanie wiadomości SMS, e-mail i innych"</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Informacje osobiste"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Bezpośredni dostęp do kalendarza i kontaktów zapisanych w tablecie."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Bezpośredni dostęp do kontaktów i kalendarza zapisanych w telefonie."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Bezpośredni dostęp do informacji o Tobie zapisanych na wizytówce."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Twoje informacje społecznościowe"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Bezpośredni dostęp do informacji o Twoich kontaktach i powiązaniach społecznościowych."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Twoja lokalizacja"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Monitorowanie fizycznej lokalizacji"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Połączenia sieciowe"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Uzyskiwanie dostępu do różnych funkcji sieciowych"</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Urządzenia dostępowe i sieci przez Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Ustawienia dźwięku"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Zmiana ustawień dźwięku."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Użycie baterii"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Korzystanie z funkcji, które mogą szybko rozładować baterię."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalendarz"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Bezpośredni dostęp do kalendarza i wydarzeń."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Czytanie słownika użytkownika"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Czytanie wyrazów ze słownika użytkownika."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Zapisywanie w słowniku użytkownika"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Dodawanie wyrazów do słownika użytkownika."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Zakładki i historia"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Bezpośredni dostęp do zakładek i historii przeglądarki."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarm"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Ustawianie budzika."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Poczta głosowa"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Bezpośredni dostęp do poczty głosowej."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Bezpośredni dostęp do mikrofonu i nagrywanie dźwięku."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Aparat"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Bezpośredni dostęp do aparatu – robienie zdjęć i nagrywanie filmów."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Informacje o aplikacjach"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Możliwość zmiany działania innych aplikacji na urządzeniu."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Tapeta"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Zmiana ustawień tapety urządzenia."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Zegar"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Zmiana czasu i strefy czasowej na urządzeniu."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Pasek stanu"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Zmiana ustawień paska stanu urządzenia."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Ustawienia synchronizacji"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Dostęp do ustawień synchronizacji."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Twoje konta"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Dostęp do udostępnionych kont."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Sterowanie sprzętowe"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Dostęp i kontrola systemu niższego poziomu."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Narzędzia programistyczne"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funkcje potrzebne jedynie programistom."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Interfejsy innych aplikacji"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Możliwość wpływania na interfejsy innych aplikacji."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Pamięć"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Dostęp do nośnika USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Dostęp do karty SD."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Pozwala aplikacji na odbieranie i przetwarzanie wiadomości WAP. To oznacza, że aplikacja będzie mogła bez Twojej wiedzy monitorować i usuwać wiadomości wysyłane do Twojego urządzenia."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"pobieranie uruchomionych aplikacji"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Pozwala aplikacji na pobieranie informacji o aktualnie i niedawno działających zadaniach. Dzięki temu aplikacja może uzyskać informacje o tym, które aplikacje są używane na urządzeniu."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interakcje między użytkownikami"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Umożliwia aplikacji wykonywanie działań dotyczących różnych użytkowników urządzenia. Złośliwe aplikacje mogą to wykorzystać do złamania zabezpieczeń na kontach użytkowników."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"pełna licencja na interakcje między użytkownikami"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Zezwala na wszystkie możliwe interakcje między użytkownikami."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"zarządzanie użytkownikami"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Pozwala aplikacjom na zarządzanie użytkownikami na urządzeniu, w tym na ich sprawdzanie, tworzenie i usuwanie."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"Pobieraj informacje o uruchomionych aplikacjach"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Zezwala aplikacji na pobieranie informacji o obecnie i ostatnio uruchomionych zadaniach. Złośliwe aplikacje mogą uzyskać dostęp do prywatnych informacji na temat innych aplikacji."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"zmienianie kolejności uruchomionych aplikacji"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Pozwala aplikacji na pobieranie wewnętrznego stanu systemu. Złośliwe aplikacje mogą pobrać szereg prywatnych i zabezpieczonych informacji, które normalnie nie są im potrzebne."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"pobieranie zawartości ekranu"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Pozwala aplikacji na pobieranie zawartości aktywnego okna. Złośliwe aplikacje mogą pobrać całą zawartość okna i przeanalizować znajdujący się w nim tekst z wyjątkiem haseł."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"tymczasowo włącz ułatwienia dostępu"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Umożliwia aplikacji tymczasowe włączanie ułatwień dostępu na urządzeniu. Złośliwe aplikacje mogą je włączać bez zgody użytkownika."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"pobieranie informacji o oknach"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Zezwala aplikacji na pobieranie informacji o oknach z menedżera okien. Złośliwe aplikacje mogą pobierać informacje przeznaczone do użytku wewnętrznego w systemie."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrowanie zdarzeń"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Zezwala aplikacji na zarejestrowanie filtra wejściowego, który filtruje strumień wszystkich zdarzeń z udziałem użytkownika przed ich rozesłaniem. Złośliwe aplikacje mogą kontrolować interfejs systemu niezależnie od działań użytkownika."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"powiększanie ekranu"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Zezwala aplikacji na powiększenie zawartości ekranu. Szkodliwe aplikacje mogą przekształcić zawartość ekranu tak, by urządzenie stało się bezużyteczne."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"częściowe wyłączenie"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Przełącza menedżera aktywności w stan wyłączenia. Nie wykonuje pełnego wyłączenia."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zapobieganie przełączaniu aplikacji"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Pozwala aplikacji na kontrolowanie maksymalnej liczby uruchamianych procesów. Nigdy niewykorzystywane przez normalne aplikacje."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"wymuszanie zamknięcia aplikacji w tle"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Pozwala aplikacji na kontrolowanie, czy czynności są zawsze kończone, kiedy zaczynają działać w tle. Nigdy nie jest potrzebne normalnym aplikacjom."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"zmienianie statystyk dotyczących baterii"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Pozwala aplikacji na modyfikowanie zebranych statystyk dotyczących baterii. Nieprzeznaczone dla zwykłych aplikacji."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"odczytywanie statystyk dotyczących baterii"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Zezwala aplikacji na odczytywanie bieżących danych niskiego poziomu o wykorzystaniu baterii. Możliwe jest wtedy zbieranie przez aplikację szczegółowych danych o używanych aplikacjach."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"zmienianie statystyk dotyczących baterii"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Zezwala aplikacji na modyfikowanie zebranych statystyk dotyczących baterii. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontrolowanie tworzenia i przywracania kopii zapasowych systemu"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Pozwala aplikacji na sterowanie mechanizmem tworzenia kopii zapasowych systemu i ich przywracania. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"Potwierdzenie operacji utworzenia pełnej kopii zapasowej lub przywracania"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"wyświetlanie nieuwierzytelnionych okien"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Pozwala aplikacji na tworzenie okien przeznaczonych do wykorzystania przez wewnętrzny interfejs użytkownika systemu. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"rysowanie na innych aplikacjach"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Pozwala aplikacji na pokazywanie okien z alertami systemu. Niektóre okna z alertami mogą zająć cały ekran."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Zezwala aplikacji na wyświetlanie elementów interfejsu nad innymi aplikacjami lub elementami ich interfejsu. Może to powodować zakłócenia w korzystaniu z interfejsu innej aplikacji lub inne działanie aplikacji, niż wynikałoby to z widocznego interfejsu danej aplikacji."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"zmienianie ogólnej prędkości animacji"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Pozwala aplikacji na zmianę ogólnej prędkości animacji (szybsze lub wolniejsze animacje) w dowolnym momencie."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"zarządzanie tokenami aplikacji"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Pozwala aplikacji na tworzenie własnych tokenów i zarządzanie nimi z pominięciem zwykłego porządku warstw (Z-order). Nieprzeznaczone dla zwykłych aplikacji."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"wstrzymywanie ekranu"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Zezwala aplikacji na tymczasowe wstrzymanie ekranu przy przejściach pełnoekranowych."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"naciskanie klawiszy oraz przycisków sterujących"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Pozwala aplikacji na przesyłanie własnych zdarzeń wprowadzania danych (naciśnięć klawiszy itp.) do innych aplikacji. Złośliwe aplikacje mogą to wykorzystać do przejęcia kontroli nad tabletem."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Pozwala aplikacji na przesyłanie własnych zdarzeń wprowadzania danych (naciśnięć klawiszy itp.) do innych aplikacji. Złośliwe aplikacje mogą to wykorzystać do przejęcia kontroli nad telefonem."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"bezpośrednie instalowanie aplikacji"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Pozwala aplikacji na instalowanie nowych lub zaktualizowanych pakietów Androida. Złośliwe aplikacje mogą to wykorzystać w celu dodania nowych aplikacji o dowolnie wysokich uprawnieniach."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"usuwanie wszystkich danych aplikacji z pamięci podręcznej"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Pozwala aplikacji na zwalnianie pamięci tabletu przez usuwanie plików z katalogu pamięci podręcznej aplikacji. Dostęp jest bardzo ograniczony, z reguły do procesów systemu."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Pozwala aplikacji na zwalnianie pamięci telefonu przez usuwanie plików z katalogu pamięci podręcznej aplikacji. Dostęp jest bardzo ograniczony, z reguły do procesów systemu."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Zezwala aplikacji na zwolnienie pamięci tabletu przez usunięcie plików w katalogach pamięci podręcznej innych aplikacji. Może to spowodować wolniejsze uruchamianie się innych aplikacji, ponieważ muszą one ponownie pobrać dane."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Zezwala aplikacji na zwolnienie pamięci telefonu przez usunięcie plików w katalogach pamięci podręcznej innych aplikacji. Może to spowodować wolniejsze uruchamianie się innych aplikacji, ponieważ muszą one ponownie pobrać dane."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"przenoszenie zasobów aplikacji"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Pozwala aplikacji na przenoszenie zasobów aplikacji z nośnika wewnętrznego na zewnętrzny i odwrotnie."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"odczyt wrażliwych danych dziennika"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Pozwala aplikacji na dostęp do dodatkowych poleceń dostawcy informacji o lokalizacji. Aplikacje z tym uprawnieniem mogą wpływać na działanie urządzenia GPS lub innych źródeł lokalizacji."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"uprawnienia do instalowania dostawcy danych o lokalizacji"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Tworzenie pozorowanych źródeł lokalizacji dla potrzeb testów lub instalacji nowego dostawcy informacji o lokalizacji. Aplikacje z tym uprawnieniem mogą zastąpić lokalizację i/lub stan zwracany przez inne źródła lokalizacji, takie jak GPS lub dostawcy danych o lokalizacji."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"dokładna lokalizacja (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Dostęp do dokładnych źródeł lokalizacji, takich jak układ GPS w tablecie. Jeśli usługi lokalizacji są dostępne i włączone, aplikacja z tym uprawnieniem może dokładnie ustalać Twoją lokalizację."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Dostęp do dokładnych źródeł lokalizacji, takich jak układ GPS w telefonie. Jeśli usługi lokalizacji są dostępne i włączone, aplikacja z tym uprawnieniem może dokładnie ustalać Twoją lokalizację."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"przybliżona lokalizacja (na podstawie sieci)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Dostęp do przybliżonej lokalizacji ustalanej przez dostawców lokalizacji używających źródeł sieciowych, takich jak nadajniki telefonii komórkowej i Wi-Fi. Jeśli te usługi lokalizacji są dostępne i włączone, aplikacja z tym uprawnieniem może określać Twoją przybliżoną lokalizację."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"dokładna lokalizacja (na podstawie sygnału GPS i sieci)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Zezwala aplikacji na określanie dokładnej lokalizacji dzięki sygnałowi GPS lub źródłom lokalizacji sieciowej, takim jak wieże sieci komórkowych i sieci Wi-Fi. Te usługi lokalizacyjne muszą być włączone i dostępne dla urządzenia, by aplikacja mogła z nich korzystać. Gdy to uprawnienie jest aktywne, aplikacje mogą określać Twoje położenie. Pamiętaj jednak, że telefon zużywa wtedy więcej energii."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"przybliżona lokalizacja (na podstawie sieci)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Zezwala aplikacji na określanie przybliżonej lokalizacji. Jest ona odczytywana z usług lokalizacyjnych wykorzystujących źródła lokalizacji sieciowej, takie jak wieże sieci komórkowych i sieci Wi-Fi. Te usługi lokalizacyjne muszą być włączone i dostępne dla urządzenia, by aplikacja mogła z nich korzystać. Gdy to uprawnienie jest aktywne, aplikacje mogą określać Twoje przybliżone położenie."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"dostęp do usługi SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Pozwala aplikacji na wykorzystanie funkcji niskiego poziomu usługi SurfaceFlinger."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"czytanie bufora ramki"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Pozwala aplikacji na odczyt zawartości bufora ramki."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"konfigurowanie wyświetlaczy Wi-Fi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Zezwala aplikacji na konfigurację wyświetlaczy Wi-Fi i łączenie z nimi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"zarządzanie wyświetlaczami Wi-Fi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Zezwala aplikacji na zarządzanie niskopoziomowymi funkcjami wyświetlaczy Wi-Fi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"zmienianie ustawień audio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Pozwala aplikacji na modyfikowanie globalnych ustawień dźwięku, takich jak głośność oraz urządzenie wyjściowe."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"nagrywanie dźwięku"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"uzyskiwanie dostępu do ustawień Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Pozwala aplikacji na konfigurowanie lokalnego tabletu z funkcją Bluetooth oraz na wykrywanie urządzeń zdalnych i parowanie z nimi."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Pozwala aplikacji na konfigurowanie lokalnego telefonu z funkcją Bluetooth oraz na wykrywanie urządzeń zdalnych i parowanie z nimi."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Wyświetl połączenia WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"łączenie się i rozłączanie z siecią WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Pozawala aplikacji określić, czy obsługa WiMAX jest włączona, oraz uzyskać informacje o wszystkich podłączonych sieciach WiMAX."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Zmień stan WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Pozwala aplikacji na nawiązywanie i kończenie połączeń z sieciami WiMAX w tablecie."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Pozwala aplikacji na zmianę obecnie zsynchronizowanych kanałów. Złośliwe aplikacje mogą zmienić zsynchronizowane kanały."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"odczytywanie terminów dodanych do słownika"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Pozwala aplikacji na odczytywanie wszelkich słów, nazw i wyrażeń zapisanych w słowniku użytkownika."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"zapisywanie w słowniku zdefiniowanym przez użytkownika"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"dodawanie wyrazów do słownika zdefiniowanego przez użytkownika"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Pozwala aplikacji na zapisywanie nowych słów do słownika użytkownika."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"testowanie dostępu do chronionej pamięci"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"testowanie dostępu do chronionej pamięci"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Pozwala aplikacji na testowanie uprawnienia do pamięci USB, które będzie dostępne w przyszłych urządzeniach."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Aplikacja może testować uprawnienie do pamięci USB, dostępne w przyszłych urządzeniach."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Pozwala aplikacji na testowanie uprawnienia do karty SD, które będzie dostępne w przyszłych urządzeniach."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modyfikowanie i usuwanie zawartości pamięci USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modyfikowanie i usuwanie zawartości karty SD"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Pozwala aplikacji na zapis na karcie SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"modyfikowanie/usuwanie zawartości pamięci wew."</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Pozwala aplikacji na modyfikowanie zawartości pamięci wewnętrznej."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"dostęp do zewnętrznej pamięci wszystkich"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Pozwala aplikacji na dostęp do zewnętrznej pamięci masowej dla wszystkich użytkowników."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"dostęp do systemu plików pamięci podręcznej"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Pozwala aplikacji na odczyt i zapis w systemie plików pamięci podręcznej."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"nawiązywanie/odbieranie połączeń przez internet"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Wymaganie szyfrowania przechowywanych danych aplikacji"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Wyłącz aparaty"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Zapobieganie używaniu wszystkich aparatów w urządzeniu"</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Wyłącz funkcje w blokadzie"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Zablokuj używanie niektórych funkcji w blokadzie."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Dom"</item>
     <item msgid="869923650527136615">"Komórka"</item>
@@ -697,12 +760,12 @@
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Poprawnie!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Spróbuj ponownie."</string>
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Spróbuj ponownie."</string>
-    <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Przekroczono maksymalną liczbę prób odblokowania Face Unlock."</string>
+    <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Przekroczono maksymalną liczbę prób rozpoznania twarzy."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Ładowanie (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Naładowany."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Naładowana"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Podłącz ładowarkę."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Brak karty SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Brak karty SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Brak karty SIM w tablecie."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Brak karty SIM w telefonie."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Włóż kartę SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Wzór wyczyszczony"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Dodano komórkę."</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Wzór ukończony"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Dodaj widżet."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Puste"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Rozwinięto obszar odblokowania."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Zwinięto obszar odblokowania."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Widżet <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Wybór użytkownika"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Stan"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Aparat"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Elementy sterujące multimediów"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Rozpoczęto zmienianie kolejności widżetów."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Zakończono zmienianie kolejności widżetów."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Usunięto widżet <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Rozwiń obszar odblokowania."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Odblokowanie przesunięciem."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Odblokowanie wzorem."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Rozpoznanie twarzy"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Odblokowanie kodem PIN."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Odblokowanie hasłem."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Obszar wzoru."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Obszar przesuwania."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopiuj adres URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Zaznacz tekst"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Zaznaczanie tekstu"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"dodaj do słownika"</string>
-    <string name="deleteText" msgid="7070985395199629156">"usuń"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Dodaj do słownika"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Usuń"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Sposób wprowadzania tekstu"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Działania na tekście"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Kończy się miejsce"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Otwórz dostępne sieci Wi-Fi"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Zaloguj się do sieci Wi-Fi."</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Zaloguj się do sieci"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nie można połączyć się z siecią Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ma powolne połączenie internetowe."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Do:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Wpisz wymagany kod PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Kod PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Na czas połączenia z <xliff:g id="DEVICE_NAME">%1$s</xliff:g> telefon zostanie tymczasowo odłączony od Wi-Fi"</string>
     <string name="select_character" msgid="3365550120617701745">"Wstaw znak"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Wysyłanie wiadomości SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; wysyła wiele SMS-ów. Chcesz pozwolić tej aplikacji dalej wysyłać SMS-y?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Pozwól"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Odmów"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chce wysłać wiadomość do &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"To "<font fgcolor="#ffffb060">"może spowodować obciążenie"</font>" Twojego konta komórkowego."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"To spowoduje obciążenie Twojego konta komórkowego."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Wyślij"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Anuluj"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Zapamiętaj mój wybór"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Możesz to zmienić: Ustawienia &gt; Aplikacje"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Zawsze zezwalaj"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nigdy nie zezwalaj"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Karta SIM wyjęta"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Sieć komórkowa będzie niedostępna do chwili ponownego uruchomienia urządzenia z użyciem ważnej karty SIM."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Gotowe"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Ustaw datę"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ustaw"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Gotowe"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Domyślne"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Nie są wymagane żadne uprawnienia"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Ukryj"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Pokaż wszystko"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NOWE: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NOWE: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Dostarczane przez <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Nie są wymagane żadne uprawnienia"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"to może generować dodatkowe koszty"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Pamięć masowa USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Połączenie przez USB"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Nawiązano połączenie z komputerem przez USB. Jeśli chcesz skopiować pliki między komputerem a nośnikiem USB systemu Android, dotknij poniższego przycisku."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"Obsługa sieci VPN została włączona przez aplikację <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotknij, aby zarządzać siecią."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Nawiązano połączenie z: <xliff:g id="SESSION">%s</xliff:g>. Dotknij, aby zarządzać siecią."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Łączę z zawsze włączoną siecią VPN…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Połączono z zawsze włączoną siecią VPN"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Błąd zawsze włączonej sieci VPN"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Kliknij, aby zresetować połączenie"</string>
     <string name="upload_file" msgid="2897957172366730416">"Wybierz plik"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nie wybrano pliku"</string>
     <string name="reset" msgid="2448168080964209908">"Resetuj"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Udostępnij"</string>
     <string name="find" msgid="4808270900322985960">"Znajdź"</string>
     <string name="websearch" msgid="4337157977400211589">"Wyszukiwarka"</string>
+    <string name="find_next" msgid="5742124618942193978">"Znajdź następne"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Znajdź poprzednie"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Prośba o lokalizację od użytkownika <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Prośba o lokalizację"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Żądane przez <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Słuchawki"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Głośniki stacji dokującej"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Dźwięk przez HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Dźwięk Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Gotowe"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Wyjście multimediów"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Skanuję..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Łączę..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Dostępne"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Niedostępne"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Wbudowany ekran"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Ekran HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Nakładka nr <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Podłączony jest wyświetlacz bezprzewodowy"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Ten ekran jest wyświetlany na innym urządzeniu"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Rozłącz"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Połączenie alarmowe"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Nie pamiętam wzoru"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Nieprawidłowy wzór"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Nieprawidłowe hasło"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Nieprawidłowy PIN"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Spróbuj ponownie za <xliff:g id="NUMBER">%d</xliff:g> s."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Narysuj wzór"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Podaj PIN karty SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Podaj PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Wpisz hasło"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"Karta SIM została wyłączona. Podaj kod PUK, by przejść dalej. Szczegóły uzyskasz od operatora."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Podaj wybrany kod PIN"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Potwierdź wybrany kod PIN"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Odblokowuję kartę SIM…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Nieprawidłowy PIN."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Wpisz PIN o długości od 4 do 8 cyfr."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Kod PUK musi mieć co najmniej 8 cyfr."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Ponownie podaj poprawny kod PUK. Nieudane próby spowodują trwałe wyłączenie karty SIM."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Kody PIN nie pasują"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Zbyt wiele prób narysowania wzoru"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Aby odblokować, zaloguj się na konto Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Nazwa użytkownika (e-mail)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Hasło"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Zaloguj się"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Nieprawidłowa nazwa użytkownika lub hasło."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Nie pamiętasz nazwy użytkownika lub hasła?"\n"Wejdź na "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Sprawdzam konto"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Po raz <xliff:g id="NUMBER_0">%d</xliff:g> wpisałeś nieprawidłowy PIN. "\n\n"Spróbuj ponownie za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Po raz <xliff:g id="NUMBER_0">%d</xliff:g> wpisałeś nieprawidłowe hasło. "\n\n"Spróbuj ponownie za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Po raz <xliff:g id="NUMBER_0">%d</xliff:g> narysowałeś nieprawidłowy wzór odblokowania. "\n\n"Spróbuj ponownie za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Po raz <xliff:g id="NUMBER_0">%d</xliff:g> próbowałeś nieprawidłowo odblokować tablet. Po kolejnych <xliff:g id="NUMBER_1">%d</xliff:g> nieudanych próbach tablet zostanie zresetowany do ustawień fabrycznych, a wszystkie dane użytkownika zostaną utracone."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Po raz <xliff:g id="NUMBER_0">%d</xliff:g> próbowałeś nieprawidłowo odblokować telefon. Po kolejnych <xliff:g id="NUMBER_1">%d</xliff:g> nieudanych próbach telefon zostanie zresetowany do ustawień fabrycznych, a wszystkie dane użytkownika zostaną utracone."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowałeś nieprawidłowo odblokować tablet. Tablet zostanie teraz zresetowany do ustawień fabrycznych."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowałeś nieprawidłowo odblokować telefon. Telefon zostanie teraz zresetowany do ustawień fabrycznych."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Po raz <xliff:g id="NUMBER_0">%d</xliff:g> nieprawidłowo narysowałeś wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%d</xliff:g> nieudanych próbach konieczne będzie odblokowanie tabletu przy użyciu danych logowania na konto Google."\n\n" Spróbuj ponownie za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Po raz <xliff:g id="NUMBER_0">%d</xliff:g> nieprawidłowo narysowałeś wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%d</xliff:g> nieudanych próbach konieczne będzie odblokowanie telefonu przy użyciu danych logowania na konto Google."\n\n" Spróbuj ponownie za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Usuń"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Chcesz ustawić głośność powyżej bezpiecznego poziomu?"\n"Słuchanie przy dużym poziomie głośności przez dłuższy czas może doprowadzić do uszkodzenia słuchu."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Aby włączyć ułatwienia dostępu, przytrzymaj dwa palce."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Włączono ułatwienia dostępu."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Ułatwienia dostępu zostały anulowane."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Bieżący użytkownik: <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Właściciel"</string>
 </resources>
diff --git a/core/res/res/values-port/alias.xml b/core/res/res/values-port/alias.xml
new file mode 100644
index 0000000..bf3eecb
--- /dev/null
+++ b/core/res/res/values-port/alias.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <!-- Alias used to reference one of two possible layouts in keyguard.  -->
+    <item type="layout" name="keyguard_eca">@android:layout/keyguard_emergency_carrier_area</item>
+</resources>
diff --git a/core/res/res/values-port/bools.xml b/core/res/res/values-port/bools.xml
index fc62b69b..1e2a4f2 100644
--- a/core/res/res/values-port/bools.xml
+++ b/core/res/res/values-port/bools.xml
@@ -16,4 +16,6 @@
 
 <resources>
     <bool name="action_bar_embed_tabs">false</bool>
+    <bool name="kg_share_status_area">true</bool>
+    <bool name="kg_sim_puk_account_full_screen">true</bool>
 </resources>
diff --git a/core/res/res/values-port/integers.xml b/core/res/res/values-port/integers.xml
new file mode 100644
index 0000000..ef7e4da
--- /dev/null
+++ b/core/res/res/values-port/integers.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <!-- Gravity to make KeyguardSelectorView work in multiple orientations
+        0x31 == "top|center_horizontal" -->
+    <integer name="kg_selector_gravity">0x31</integer>
+</resources>
\ No newline at end of file
diff --git a/core/res/res/values-pt-rPT/donottranslate-cldr.xml b/core/res/res/values-pt-rPT/donottranslate-cldr.xml
index 54417a4..26d8371 100644
--- a/core/res/res/values-pt-rPT/donottranslate-cldr.xml
+++ b/core/res/res/values-pt-rPT/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Janeiro</string>
-    <string name="month_long_standalone_february">Fevereiro</string>
-    <string name="month_long_standalone_march">Março</string>
-    <string name="month_long_standalone_april">Abril</string>
-    <string name="month_long_standalone_may">Maio</string>
-    <string name="month_long_standalone_june">Junho</string>
-    <string name="month_long_standalone_july">Julho</string>
-    <string name="month_long_standalone_august">Agosto</string>
-    <string name="month_long_standalone_september">Setembro</string>
-    <string name="month_long_standalone_october">Outubro</string>
-    <string name="month_long_standalone_november">Novembro</string>
-    <string name="month_long_standalone_december">Dezembro</string>
-
-    <string name="month_long_january">Janeiro</string>
-    <string name="month_long_february">Fevereiro</string>
-    <string name="month_long_march">Março</string>
-    <string name="month_long_april">Abril</string>
-    <string name="month_long_may">Maio</string>
-    <string name="month_long_june">Junho</string>
-    <string name="month_long_july">Julho</string>
-    <string name="month_long_august">Agosto</string>
-    <string name="month_long_september">Setembro</string>
-    <string name="month_long_october">Outubro</string>
-    <string name="month_long_november">Novembro</string>
-    <string name="month_long_december">Dezembro</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Fev</string>
-    <string name="month_medium_march">Mar</string>
-    <string name="month_medium_april">Abr</string>
-    <string name="month_medium_may">Mai</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Ago</string>
-    <string name="month_medium_september">Set</string>
-    <string name="month_medium_october">Out</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dez</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">domingo</string>
-    <string name="day_of_week_long_monday">segunda-feira</string>
-    <string name="day_of_week_long_tuesday">terça-feira</string>
-    <string name="day_of_week_long_wednesday">quarta-feira</string>
-    <string name="day_of_week_long_thursday">quinta-feira</string>
-    <string name="day_of_week_long_friday">sexta-feira</string>
-    <string name="day_of_week_long_saturday">sábado</string>
-
-    <string name="day_of_week_medium_sunday">dom</string>
-    <string name="day_of_week_medium_monday">seg</string>
-    <string name="day_of_week_medium_tuesday">ter</string>
-    <string name="day_of_week_medium_wednesday">qua</string>
-    <string name="day_of_week_medium_thursday">qui</string>
-    <string name="day_of_week_medium_friday">sex</string>
-    <string name="day_of_week_medium_saturday">sáb</string>
-
-    <string name="day_of_week_short_sunday">dom</string>
-    <string name="day_of_week_short_monday">seg</string>
-    <string name="day_of_week_short_tuesday">ter</string>
-    <string name="day_of_week_short_wednesday">qua</string>
-    <string name="day_of_week_short_thursday">qui</string>
-    <string name="day_of_week_short_friday">sex</string>
-    <string name="day_of_week_short_saturday">sáb</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">S</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">Q</string>
-    <string name="day_of_week_shortest_thursday">Q</string>
-    <string name="day_of_week_shortest_friday">S</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">Antes do meio-dia</string>
-    <string name="pm">Depois do meio-dia</string>
-    <string name="yesterday">Ontem</string>
-    <string name="today">Hoje</string>
-    <string name="tomorrow">Amanhã</string>
-
     <string name="hour_minute_24">%-kh%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 6f8616a..fd7211e 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opções do telefone"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Bloqueio de ecrã"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Desligar"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Relatório de erros"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Criar Rel. Erro"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Será recolhida informação sobre o estado atual do seu dispositivo a enviar através de uma mensagem de email. Demorará algum tempo até que o relatório de erro esteja pronto para ser enviado. Aguarde um pouco."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Modo silencioso"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Som desactivado"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"O som está activado"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"As suas mensagens"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Ler e escrever SMS, e-mail e outras mensagens."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Os seus dados pessoais"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Acesso directo aos seus contactos e calendário armazenados no tablet."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Acesso directo aos seus contactos e calendário armazenados no telefone."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Acesso direto às suas informações, armazenadas no seu cartão de contacto."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"As suas informações sociais"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Acesso direto às informações sobre os seus contactos e ligações sociais."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"A sua localização"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Monitorizar a sua localização física."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Comunicação de rede"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Aceder a várias funcionalidades de rede."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Aceder a dispositivos e redes através de Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Definições de Áudio"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Alterar as definições de áudio."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Afetar a Bateria"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Utilizar funcionalidades que podem descarregar rapidamente a bateria."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Calendário"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Acesso direto ao calendário e eventos."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Ler Dicionário do Utilizador"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Ler palavras no dicionário do utilizador."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Escrever no Dicionário do Utilizador"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Adicionar palavras ao dicionário do utilizador."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Marcadores e Histórico"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Acesso direto aos marcadores e histórico do navegador."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarme"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Definir o despertador."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Correio de voz"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Acesso direto ao correio de voz."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Microfone"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Acesso direto ao microfone para gravar áudio."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Câmara"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Acesso direto à câmara para captura de imagens ou vídeos."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"As informações das suas aplicações"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Capacidade de afetar o comportamento de outras aplicações no seu dispositivo."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Imagem de fundo"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Alterar as definições de imagem de fundo do dispositivo."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Relógio"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Alterar a hora ou o fuso horário do dispositivo."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Barra de Estado"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Alterar as definições da barra de estado do dispositivo."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Definições de Sincronização"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Acesso às definições de sincronização."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"As suas contas"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Aceda às contas disponíveis."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Controlos de hardware"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Acesso e controlo de nível inferior do sistema."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Ferramentas de desenvolvimento"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funcionalidades apenas necessárias para programadores de aplicações."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"IU de Outras Aplicações"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Afetar a IU de outras aplicações."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Armazenamento"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Aceder ao armazenamento USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Aceder ao cartão SD."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permite que a aplicação receba e processe mensagens WAP. Esta autorização inclui a capacidade de monitorizar ou eliminar mensagens enviadas para si sem as apresentar."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"obter aplicações em execução"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Permite que a aplicação recupere informações acerca de tarefas executadas atual e recentemente. Isto pode permitir que a aplicação descubra informações acerca de quais as aplicações utilizadas no dispositivo."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interagir entre utilizadores"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permite que a aplicação execute ações com diferentes utilizadores no dispositivo. Aplicações maliciosas poderão utilizar esta opção para violar a proteção entre utilizadores."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"licença completa para interagir entre utilizadores"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permite todas as interações possíveis entre utilizadores."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"gerir utilizadores"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permite às aplicações a gestão de utilizadores no dispositivo, incluindo a criação e eliminação de consultas."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"obter detalhes das aplicações em execução"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite à aplicação obter informações detalhadas sobre tarefas atualmente em execução e recentemente executadas. As aplicações maliciosas poderão descobrir informações privadas de outras aplicações."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"reordenar as aplicações em execução"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Permite que a aplicação obtenha o estado interno do sistema. As aplicações maliciosas podem obter uma ampla variedade de dados privados e seguros de que, normalmente, nunca devem necessitar."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"obter o conteúdo do ecrã"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite que a aplicação obtenha o conteúdo da janela ativa. As aplicações maliciosas podem obter todo o conteúdo da janela e examinar todo o texto, exceto as palavras-passe."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"acessibilidade ativada temporariamente"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permite que uma aplicação ative temporariamente a acessibilidade no dispositivo. As aplicações maliciosas podem ativar a acessibilidade sem o consentimento do utilizador."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"obter informações da janela"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permite que uma aplicação obtenha informações sobre as janelas a partir do gestor de janelas. Aplicações maliciosas podem obter informações que se destinam à utilização interna do sistema."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrar eventos"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Permite que uma aplicação registe um filtro de entrada que filtra a transmissão em fluxo contínuo para todos os eventos de utilizador antes de serem entregues. Uma aplicação maliciosa pode controlar a IU do sistema sem intervenção do utilizador."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"ampliar o visor"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Permite que uma aplicação amplie o conteúdo de um visor. As aplicações maliciosas poderão transformar o conteúdo do visor de um modo que torne o dispositivo inutilizável."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"encerramento parcial"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Coloca o gestor de actividade num estado de encerramento. Não executa um encerramento completo."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir trocas de aplicações"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permite a uma aplicação controlar o número máximo de processos que será executado. Nunca é necessário para aplicações normais."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forçar as aplicações em segundo plano a fechar"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Permite que uma aplicação controle se as atividades são sempre terminadas assim que passam para segundo plano. Nunca é necessário para aplicações normais."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"modificar estatísticas da bateria"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Permite a modificação das estatísticas recolhidas sobre a bateria. Não se destina a utilização por aplicações normais."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"ler estatísticas da bateria"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permite que uma aplicação leia os atuais dados de utilização da bateria de baixo nível. Poderá permitir que a aplicação encontre informações detalhadas sobre as aplicações que utiliza."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modificar estatísticas da bateria"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permite que a aplicação modifique as estatísticas recolhidas sobre a bateria. Não se destina a utilização por aplicações normais."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controlar a cópia de segurança e restauro do sistema"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Permite que a aplicação controle o mecanismo de cópia de segurança e de restauro do sistema. Não se destina a utilização por aplicações normais."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"confirmar uma operação de restauro ou de cópia de segurança completa"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"apresentar janelas não autorizadas"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Permite que a aplicação crie janelas que se destinam a ser utilizadas ​​pela interface de utilizador do sistema interno. Nunca é necessário para aplicações normais."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"desenhar sobre outras aplicações"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Permite que a aplicação mostre janelas de alerta do sistema. Algumas janelas de alerta podem ocupar todo o ecrã."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Permite que a aplicação se sobreponha a outras aplicações ou partes da interface de utilizador. Poderá interferir na utilização da interface de qualquer aplicação ou alterar o que pensa estar a ver noutras aplicações."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"modificar velocidade global da animação"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Permite que a aplicação altere a velocidade global da animação (animações mais rápidas ou mais lentas) em qualquer altura."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"gerir tokens da aplicação"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Permite que a aplicação crie e faça a gestão dos seus próprios tokens, ignorando a ordenação normal dos mesmos pelo eixo dos Z. Nunca deve ser necessário para aplicações normais."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"fixar o ecrã"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Permite que a aplicação fixe temporariamente o ecrã para uma transição para ecrã completo."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"premir teclas e botões de controlo"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Permite que a aplicação forneça os seus próprios eventos de entrada (toques em teclas, etc.) a outras aplicações. As aplicações maliciosas podem utilizar este item para controlar o tablet."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Permite que a aplicação forneça os seus próprios eventos de entrada (toques em teclas, etc.) a outras aplicações. As aplicações maliciosas podem utilizar isto para controlar o telemóvel."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"instalar aplicações diretamente"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Permite que a aplicação instale pacotes novos ou atualizados do Android. As aplicações maliciosas podem utilizar isto para adicionar novas aplicações com autorizações arbitrariamente fortes."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"eliminar todos os dados de cache da aplicação"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Permite que a aplicação liberte espaço de armazenamento no tablet ao eliminar ficheiros no diretório da cache da aplicação. Geralmente, o acesso é muito limitado para processamento do sistema."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Permite que a aplicação liberte espaço de armazenamento no telemóvel ao eliminar ficheiros no diretório da cache da aplicação. Geralmente, o acesso é muito limitado para processamento do sistema."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Permite que a aplicação liberte espaço de armazenamento no tablet eliminando ficheiros nos diretórios da cache de outras aplicações. Isto poderá tornar o arranque de outras aplicações mais lento, pois necessitam de recuperar novamente os respetivos dados."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Permite que a aplicação liberte espaço de armazenamento no telemóvel eliminando ficheiros nos diretórios da cache de outras aplicações. Isto poderá tornar o arranque de outras aplicações mais lento, pois necessitam de recuperar novamente os respetivos dados."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"mover recursos de aplicações"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Permite que a aplicação mova recursos de aplicações de meios internos para meios externos e vice-versa."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"ler dados sensíveis de registo"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Permite que a aplicação aceda a comandos adicionais do fornecedor de localização. Isto pode permitir que a aplicação interfira com o funcionamento do GPS ou de outras fontes de localização."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"autorização para instalar um fornecedor de localização"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Criar fontes de localização fictícias para fins de teste ou instalar um fornecedor de localização novo. Isto permite que a aplicação substitua a localização e/ou o estado devolvido por outras fontes de localização como, por exemplo, GPS ou fornecedores de localização."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"localização exata (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Aceder a fontes de localização precisas, tais como o Sistema de Posicionamento Global do tablet. Quando os serviços de localização estão disponíveis e ativados, esta autorização permite que a aplicação determine a localização exata do utilizador."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Aceder a fontes de localização precisas, tais como o Sistema de Posicionamento Global do telemóvel. Quando os serviços de localização estão disponíveis e ativados, esta autorização permite que a aplicação determine a localização exata do utilizador."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"localização aproximada (baseada na rede)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Aceder à localização aproximada a partir de fornecedores de localização utilizando fontes de rede, tais como antenas de telemóvel e Wi-Fi. Quando estes serviços de localização estão disponíveis e ativados, esta autorização permite que a aplicação determine a localização aproximada do utilizador."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"localização exata (baseada no GPS e na rede)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Permite que a aplicação obtenha a sua localização exata através do Sistema de Posicionamento Global (GPS) ou das fontes de localização da rede, tais como torres de telemóvel e Wi-Fi. Estes serviços de localização têm de estar ativados e disponíveis no dispositivo para que a aplicação os utilize. As aplicações poderão utilizá-los para determinar a sua localização e poderão consumir mais energia da bateria."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"localização aproximada (baseada na rede)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Permite que a aplicação obtenha a sua localização aproximada. Esta localização é gerada pelos serviços de localização, que utilizam fontes de localização da rede, tais como torres de telemóvel e Wi-Fi. Estes serviços de localização têm de estar ativados e disponíveis no dispositivo para que a aplicação os utilize. As aplicações poderão utilizá-los para determinar a sua localização aproximada."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"aceder a SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Permite à aplicação utilizar funcionalidades de SurfaceFlinger de nível inferior."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"ler memória intermédia de fotogramas"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Permite à aplicação ler o conteúdo da memória intermédia de fotogramas."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"configurar visores Wi-Fi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permite que a aplicação se configure e se ligue a visores Wi-Fi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controlar visores Wi-Fi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permite que a aplicação controle funcionalidades de baixo nível em visores Wi-Fi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"alterar as suas definições de áudio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite que a aplicação modifique definições de áudio globais, tais como o volume e qual o altifalante utilizado para a saída de som."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"gravar áudio"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"aceder às definições de Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Permite à aplicação configurar o tablet Bluetooth local, bem como descobrir e emparelhar com dispositivos remotos."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permite que a aplicação configure o telemóvel Bluetooth local, bem como descobrir e emparelhar com dispositivos remotos."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Ver ligações WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"ligar e desligar do WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permite que a aplicação determine se o WiMAX está ativado e aceda a informações acerca de qualquer rede WiMAX que esteja ligada."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Alterar estado do WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite que a aplicação ligue e desligue o tablet de redes WiMAX."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Permite à aplicação modificar os feeds atualmente sincronizados. Isto pode permitir a uma aplicação maliciosa alterar os seus feeds sincronizados."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"ler os termos adicionados ao dicionário"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Permite que a aplicação leia todas as palavras, nomes e expressões que o utilizador possa ter guardado no dicionário do utilizador."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"escrever no dicionário definido pelo utilizador"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"adicionar palavras ao dicionário definido pelo utilizador"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Permite à aplicação escrever novas palavras no dicionário do utilizador."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"testar o acesso a armazenamento protegido"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"testar o acesso a armazenamento protegido"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Permite que a aplicação teste uma autorização para a memória USB que irá estar disponível em dispositivos futuros."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Permite que a aplicação teste uma autorização para a memória USB que irá estar disponível em dispositivos futuros."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Permite que a aplicação teste uma autorização para o cartão SD que irá estar disponível em dispositivos futuros."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modificar ou eliminar os conteúdos da memória USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modificar ou eliminar os conteúdos do cartão SD"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Permite que a aplicação escreva no cartão SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"modif./elim. armaz. interno"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Permite que a aplicação modifique o conteúdo de armazenamento de suportes internos."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"aceder ao armazenamento externo de todos os utilizadores"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Permite que a aplicação aceda ao armazenamento externo para todos os utilizadores."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"aceder ao sistema de ficheiros da cache"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite à aplicação ler e escrever no sistema de ficheiros da cache."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"fazer/receber chamadas pela internet"</string>
@@ -557,13 +618,15 @@
     <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Apagar os dados do tablet sem avisar através de uma reposição de dados de fábrica."</string>
     <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Apagar os dados do telemóvel sem avisar através de uma reposição de dados de fábrica."</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Definir o proxy global do aparelho"</string>
-    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Definir o proxy global do aparelho a ser utilizado quando a política estiver activada. Só o primeiro administrador do aparelho define o proxy global efectivo."</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Definir o proxy global do dispositivo a ser utilizado quando a política estiver ativada. Só o primeiro administrador do dispositivo pode definir o proxy global efetivo."</string>
     <string name="policylab_expirePassword" msgid="885279151847254056">"Def. valid. palavra-passe bloq. ecrã"</string>
     <string name="policydesc_expirePassword" msgid="1729725226314691591">"Controlar a frequência com que a palavra-passe do bloqueio de ecrã deve ser alterada."</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Def. encriptação armazenamento"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Solicitar encriptação dos dados da aplicação armazenados."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Desativar câmaras"</string>
-    <string name="policydesc_disableCamera" msgid="2306349042834754597">"Evitar a utilização de todas as câmaras do aparelho."</string>
+    <string name="policydesc_disableCamera" msgid="2306349042834754597">"Evitar a utilização de todas as câmaras do dispositivo."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Desat. func. com teclado bloq."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Evitar a utilização de algumas funcionalidades com o teclado bloqueado."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Residência"</item>
     <item msgid="869923650527136615">"Móvel"</item>
@@ -674,7 +737,7 @@
     <string name="relationTypeSister" msgid="1735983554479076481">"Irmã"</string>
     <string name="relationTypeSpouse" msgid="394136939428698117">"Cônjuge"</string>
     <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Personalizado"</string>
-    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Residência"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Casa"</string>
     <string name="sipAddressTypeWork" msgid="6920725730797099047">"Emprego"</string>
     <string name="sipAddressTypeOther" msgid="4408436162950119849">"Outro"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Escreva o código PIN"</string>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Tentar novamente"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Excedido o n.º máximo de tentativas de Desbloqueio Através do Rosto"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"A carregar, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Carregado."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Cobrado"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Ligue o carregador."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nenhum cartão SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Nenhum cartão SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nenhum cartão SIM no tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Nenhum cartão SIM no telefone."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Insira um cartão SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Sequência apagada"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Célula adicionada"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Sequência concluída"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Adicionar widget."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Vazio"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Área de desbloqueio expandida."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Área de desbloqueio minimizada."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> widget."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Seletor de utilizadores"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Estado"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Câmara"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Controlos de multimédia"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Reordenação de widgets iniciada."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Reordenação de widgets concluída."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> eliminado."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Expandir área de desbloqueio."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Desbloqueio através de deslize."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueio através de sequência."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Desbloqueio através do rosto."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueio através de PIN."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueio através de palavra-passe."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área da sequência."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslize."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copiar URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Selecionar texto"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selecção de texto"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"adicionar ao dicionário"</string>
-    <string name="deleteText" msgid="7070985395199629156">"eliminar"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Adicionar ao dicionário"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Eliminar"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Método de entrada"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acções de texto"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Está quase sem espaço de armazenamento"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Abrir redes Wi-Fi disponíveis"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Iniciar sessão na rede Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Inicie sessão na rede"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Não foi possível ligar a Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tem uma ligação à internet fraca."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Para:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Introduza o PIN solicitado:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"O telemóvel irá desligar-se temporariamente da rede Wi-Fi enquanto está ligado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Introduzir carácter"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"A enviar mensagens SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; está a enviar um grande número de mensagens SMS. Pretende autorizar que a aplicação continue a enviar mensagens?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Permitir"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Recusar"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; gostaria de enviar uma mensagem para &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Isto "<font fgcolor="#ffffb060">"poderá resultar em custos"</font>" para a sua conta de telemóvel."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Isto resultará em custos para a sua conta de telemóvel."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Enviar"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Cancelar"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Memorizar a minha escolha"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Pode depois alterar isto em Definições &gt; Aplicações"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Permitir Sempre"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nunca Permitir"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Cartão SIM removido"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"A rede de telemóvel estará indisponível até que reinicie o aparelho com um cartão SIM válido inserido."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Concluído"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Definir data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Definir"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Concluído"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Predefinido"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Não são necessárias permissões"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Ocultar"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostrar tudo"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NOVA: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NOVA: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Fornecido por <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Não são necessárias permissões"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"isto poderá estar sujeito a custos"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Armazenamento em massa USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Ligado através de USB"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Ligou ao computador através de USB. Toque no botão abaixo se pretender copiar ficheiros entre o computador e a memória de armazenamento USB do Android."</string>
@@ -1069,7 +1161,7 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="5100428757107469454">"Se ativar a memória de armazenamento USB, algumas aplicações que estiver a utilizar serão paradas e poderão ficar indisponíveis até desativar a memória de armazenamento USB."</string>
     <string name="dlg_error_title" msgid="7323658469626514207">"Operação USB sem êxito"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Ligado como um aparelho multimédia"</string>
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Ligado como um dispositivo multimédia"</string>
     <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Ligado como uma câmara"</string>
     <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Ligado como um instalador"</string>
     <string name="usb_accessory_notification_title" msgid="7848236974087653666">"Ligado a um acessório USB"</string>
@@ -1114,7 +1206,7 @@
     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"O armazenamento USB foi removido. Insira um novo suporte de dados."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Cartão SD removido. Insira um novo cartão."</string>
     <string name="activity_list_empty" msgid="1675388330786841066">"Não foi encontrada nenhuma atividade correspondente."</string>
-    <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"actualizar estatísticas de utilização de componentes"</string>
+    <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"atualizar estatísticas de utilização de componentes"</string>
     <string name="permdesc_pkgUsageStats" msgid="1106612424254277630">"Permite que a aplicação modifique as estatísticas de utilização de componentes recolhidas. Não se destina a utilização por aplicações normais."</string>
     <string name="permlab_copyProtectedData" msgid="4341036311211406692">"copiar conteúdo"</string>
     <string name="permdesc_copyProtectedData" msgid="4390697124288317831">"Permite à aplicação invocar o serviço de contentor predefinido para copiar conteúdo. Não se destina a ser utilizado por aplicações normais."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"A VPN foi ativada pelo <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toque para gerir a rede."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Ligado a <xliff:g id="SESSION">%s</xliff:g>. Toque para gerir a rede."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"A ligar VPN sempre ativa..."</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sempre ativa ligada"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Erro da VPN sempre ativa"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Toque para repor a ligação"</string>
     <string name="upload_file" msgid="2897957172366730416">"Escolher ficheiro"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Não foi selecionado nenhum ficheiro"</string>
     <string name="reset" msgid="2448168080964209908">"Repor"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Partilhar"</string>
     <string name="find" msgid="4808270900322985960">"Localizar"</string>
     <string name="websearch" msgid="4337157977400211589">"Pesquisar na Web"</string>
+    <string name="find_next" msgid="5742124618942193978">"Localizar seguinte"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Localizar anterior"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Pedido de localização de <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Pedido de localização"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Pedido por <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telemóvel"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auscultadores"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altif. estação ancoragem"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Áudio HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Áudio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Concluído"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Saída de som multimédia"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"A procurar..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"A ligar..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Disponível"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Não disponível"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Ecrã Integrado"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Ecrã HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Sobreposição #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> ppp"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"O Display sem fios está ligado"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Este ecrã está a ser apresentado noutro dispositivo"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Desligar"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Chamada de emergência"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Esqueceu-se da Sequência"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Sequência Incorreta"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Palavra-passe Incorreta"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN Incorreto"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Tente novamente dentro de <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Desenhe a sua sequência"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Introduzir PIN do cartão SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Introduzir PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Introduzir Palavra-passe"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"O SIM está agora desativado. Introduza o código PUK para continuar. Contacte o operador para obter detalhes."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Introduza o código PIN pretendido"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Confirme o código PIN pretendido"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"A desbloquear cartão SIM..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Código PIN incorreto."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Introduza um PIN entre 4 e 8 números."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"O código PUK deve ter 8 ou mais números."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Volte a introduzir o código PUK correto. Demasiadas tentativas consecutivas irão desativar permanentemente o SIM."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Os códigos PIN não correspondem"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Demasiadas tentativas para desenhar sequência"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Para desbloquear, inicie sessão com a sua Conta do Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Nome de utilizador (email)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Palavra-passe"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Iniciar sessão"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Nome de utilizador ou palavra-passe inválidos."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Esqueceu-se do nome de utilizador ou da palavra-passe?"\n"Aceda a "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"A verificar a conta…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Escreveu o PIN incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. "\n\n"Tente novamente dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Escreveu a palavra-passe incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. "\n\n"Tente novamente dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Desenhou a sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. "\n\n"Tente novamente dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Tentou desbloquear o tablet <xliff:g id="NUMBER_0">%d</xliff:g> vezes de forma incorreta. Depois de mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas sem êxito, as definições de origem do telemóvel serão repostas e todos os dados do utilizador serão perdidos."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Tentou desbloquear o telemóvel <xliff:g id="NUMBER_0">%d</xliff:g> vezes de forma incorreta. Depois de mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas sem êxito, as definições de origem do telemóvel serão repostas e todos os dados do utilizador serão perdidos."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Tentou desbloquear o tablet <xliff:g id="NUMBER">%d</xliff:g> vezes de forma incorreta, pelo que será reposta a predefinição de fábrica."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Tentou desbloquear o telemóvel <xliff:g id="NUMBER">%d</xliff:g> vezes de forma incorreta, pelo que será reposta a predefinição de fábrica."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Desenhou a sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. Depois de mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas sem sucesso, ser-lhe-á pedido para desbloquear o tablet através de uma conta de email."\n\n" Tente novamente dentro de <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Desenhou a sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. Depois de mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas sem sucesso, ser-lhe-á pedido para desbloquear o telemóvel através de uma conta de email."\n\n" Tente novamente dentro de <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" - "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Remover"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Aumentar o volume acima do nível de segurança?"\n"Ouvir em volume alto durante longos períodos de tempo poderá prejudicar a sua audição."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Mantenha os dois dedos para ativar a acessibilidade."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Acessibilidade ativada."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Acessibilidade cancelada."</string>
+    <string name="user_switched" msgid="3768006783166984410">"<xliff:g id="NAME">%1$s</xliff:g> do utilizador atual."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Proprietário"</string>
 </resources>
diff --git a/core/res/res/values-pt/donottranslate-cldr.xml b/core/res/res/values-pt/donottranslate-cldr.xml
index d999c06..c3e6c29 100644
--- a/core/res/res/values-pt/donottranslate-cldr.xml
+++ b/core/res/res/values-pt/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">janeiro</string>
-    <string name="month_long_standalone_february">fevereiro</string>
-    <string name="month_long_standalone_march">março</string>
-    <string name="month_long_standalone_april">abril</string>
-    <string name="month_long_standalone_may">maio</string>
-    <string name="month_long_standalone_june">junho</string>
-    <string name="month_long_standalone_july">julho</string>
-    <string name="month_long_standalone_august">agosto</string>
-    <string name="month_long_standalone_september">setembro</string>
-    <string name="month_long_standalone_october">outubro</string>
-    <string name="month_long_standalone_november">novembro</string>
-    <string name="month_long_standalone_december">dezembro</string>
-
-    <string name="month_long_january">janeiro</string>
-    <string name="month_long_february">fevereiro</string>
-    <string name="month_long_march">março</string>
-    <string name="month_long_april">abril</string>
-    <string name="month_long_may">maio</string>
-    <string name="month_long_june">junho</string>
-    <string name="month_long_july">julho</string>
-    <string name="month_long_august">agosto</string>
-    <string name="month_long_september">setembro</string>
-    <string name="month_long_october">outubro</string>
-    <string name="month_long_november">novembro</string>
-    <string name="month_long_december">dezembro</string>
-
-    <string name="month_medium_january">jan</string>
-    <string name="month_medium_february">fev</string>
-    <string name="month_medium_march">mar</string>
-    <string name="month_medium_april">abr</string>
-    <string name="month_medium_may">mai</string>
-    <string name="month_medium_june">jun</string>
-    <string name="month_medium_july">jul</string>
-    <string name="month_medium_august">ago</string>
-    <string name="month_medium_september">set</string>
-    <string name="month_medium_october">out</string>
-    <string name="month_medium_november">nov</string>
-    <string name="month_medium_december">dez</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">domingo</string>
-    <string name="day_of_week_long_monday">segunda-feira</string>
-    <string name="day_of_week_long_tuesday">terça-feira</string>
-    <string name="day_of_week_long_wednesday">quarta-feira</string>
-    <string name="day_of_week_long_thursday">quinta-feira</string>
-    <string name="day_of_week_long_friday">sexta-feira</string>
-    <string name="day_of_week_long_saturday">sábado</string>
-
-    <string name="day_of_week_medium_sunday">dom</string>
-    <string name="day_of_week_medium_monday">seg</string>
-    <string name="day_of_week_medium_tuesday">ter</string>
-    <string name="day_of_week_medium_wednesday">qua</string>
-    <string name="day_of_week_medium_thursday">qui</string>
-    <string name="day_of_week_medium_friday">sex</string>
-    <string name="day_of_week_medium_saturday">sáb</string>
-
-    <string name="day_of_week_short_sunday">dom</string>
-    <string name="day_of_week_short_monday">seg</string>
-    <string name="day_of_week_short_tuesday">ter</string>
-    <string name="day_of_week_short_wednesday">qua</string>
-    <string name="day_of_week_short_thursday">qui</string>
-    <string name="day_of_week_short_friday">sex</string>
-    <string name="day_of_week_short_saturday">sáb</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">S</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">Q</string>
-    <string name="day_of_week_shortest_thursday">Q</string>
-    <string name="day_of_week_shortest_friday">S</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Ontem</string>
-    <string name="today">Hoje</string>
-    <string name="tomorrow">Amanhã</string>
-
     <string name="hour_minute_24">%-kh%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 4bd669c..ed656fe 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opções do telefone"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Bloquear tela"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Desligar"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Relatório de bugs"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Obter relatório de bugs"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Isto coletará informações sobre o estado atual do dispositivo para enviá-las em uma mensagem de e-mail. Após iniciar o relatório de bugs, será necessário aguardar algum tempo até que esteja pronto para ser enviado."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Modo silencioso"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Som DESATIVADO"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"O som está ATIVADO"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Suas mensagens"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Ler e gravar mensagens SMS, e-mails e outras mensagens."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Suas informações pessoais"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Acessa diretamente seus contatos e agenda armazenados no tablet."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Acessa diretamente os seus contatos e agenda armazenados no telefone."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Acesso direto a informações sobre você, armazenadas em seu cartão de contato."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Suas informações sociais"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Acesso direto às informações de seus contatos e conexões sociais."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Seu local"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Monitore seu local físico."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Comunicação da rede"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Acesse diversos recursos de rede."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Acessar dispositivos e redes por meio do Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Configurações de áudio"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Alterar as configurações de áudio."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Afeta a bateria"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Usar recursos que podem descarregar a bateria rapidamente."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Agenda"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Acesso direto ao calendário e eventos."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Ler o dicionário do usuário"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Ler as palavras do dicionário do usuário."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Escrever no dicionário do usuário"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Adicionar palavras ao dicionário do usuário."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Favoritos e histórico"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Acesso direto aos favoritos e histórico do navegador."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarme"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Configurar o despertador."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Correio de voz"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Acesso direto ao correio de voz."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Microfone"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Acesso direto ao microfone para gravação de áudio."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Câmera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Acesso direto à câmera para captura de imagens ou vídeo."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Informações sobre seus aplicativos"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Capacidade de afetar o comportamento de outros aplicativos no dispositivo."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Plano de fundo"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Alterar as configurações de papel de parede do dispositivo."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Relógio"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Alterar a hora ou fuso horário no dispositivo."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Barra de status"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Alterar as configurações da barra de status do dispositivo."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Configurações de sincronização"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Acesso às configurações de sincronização."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Suas contas"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Acessar as contas disponíveis."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Controles de hardware"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Acesso de nível inferior e controle do sistema."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Ferramentas de desenvolvimento"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Recursos necessários apenas para desenvolvedores de aplicativos."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Interface de outro aplicativo"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Afetar a interface do usuário de outros aplicativos."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Armazenamento"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Acessa o armazenamento USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Acessar o cartão SD."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permite que o aplicativo receba e processe mensagens WAP. Esta permissão inclui a capacidade de monitorar ou excluir mensagens enviadas para você sem mostrá-las para você."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"recuperar aplicativos em execução"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Permite que o aplicativo obtenha informações sobre tarefas em execução atuais e recentes. Pode permitir que o aplicativo descubra informações sobre os aplicativos usados ​​no dispositivo."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interagir entre os usuários"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permite que o aplicativo execute ações entre os diversos usuários do aparelho. Aplicativos mal-intencionados podem usar isto para violar a proteção entre os usuários."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"permissão total para interagir entre os usuários"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permite todas as interações possíveis entre os usuários."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"gerenciar usuários"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permite que os aplicativos gerenciem os usuários do dispositivo, incluindo a consulta, a criação e a exclusão de usuários."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recuperar detalhes dos aplicativos em execução"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite que o aplicativo recupere informações detalhadas sobre tarefas executadas atual e recentemente. Aplicativos maliciosos podem descobrir informações privadas sobre outros aplicativos."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"reordenar os aplicativos em execução"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Permite que o aplicativo recupere o estado interno do sistema. Aplicativos maliciosos podem obter uma grande variedade de informações privadas e seguras que eles normalmente não precisariam."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"recuperar conteúdo da tela"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite que o aplicativo recupere o conteúdo da janela ativa. Aplicativos maliciosos podem recuperar o conteúdo da janela inteira e examinar todo o texto, exceto as senhas."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ativar temporariamente a acessibilidade"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permite que um aplicativo ative temporariamente a acessibilidade no dispositivo. Aplicativos maliciosos podem ativar a acessibilidade sem o consentimento do usuário."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"recuperar informações de janelas"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permite que o aplicativo recupere informações sobre as janelas do gerenciador de janelas. Aplicativos mal-intencionados podem recuperar informações destinadas ao uso interno do sistema."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrar eventos"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Permite que o aplicativo registre um filtro de entrada que filtra o fluxo de todos os eventos do usuário antes que sejam enviados. Aplicativos mal-intencionados podem controlar a interface do sistema sem a intervenção do usuário."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"ampliar monitor"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Permite que o aplicativo amplie o conteúdo de um monitor. Aplicativos maliciosos podem manipular o conteúdo do monitor de modo a tornar o dispositivo inutilizável."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"desligamento parcial"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Coloca o gerenciador de atividades em um estado de desligamento. Não executa o desligamento completo."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar trocas de aplicativo"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permite que o aplicativo controle o máximo de processos que serão executados. Nunca é necessário para aplicativos normais."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forçar encerramento de aplicativos em segundo plano"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Permite que o aplicativo controle se as atividades são sempre encerrados ao serem enviados para o plano de fundo. Nunca é necessário para aplicativos normais."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"modificar estatísticas da bateria"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Permite que o aplicativo modifique as estatísticas coletadas da bateria. Não deve ser usado em aplicativos normais."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"acessar estatísticas da bateria"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permite que o aplicativo leia os dados de uso da bateria de baixo nível atuais. Pode fornecer ao aplicativo informações detalhadas sobre os aplicativos usados por você."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modificar estatísticas da bateria"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permite que o aplicativo modifique as estatísticas coletadas da bateria. Não deve ser usado em aplicativos normais."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controlar backup e restauração do sistema"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Permite que o aplicativo controle o backup do sistema e restaure mecanismos. Não deve ser usado em aplicativos normais."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"confirmar um backup completo ou uma operação de restauração"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"exibir janelas não autorizadas"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Permite que o aplicativo crie janelas destinadas ao uso ​​pela interface interna do sistema. Não deve ser usado em aplicativos normais."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"induzir outros aplicativos"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Permite que o aplicativo mostre janelas de alerta do sistema. Algumas janelas de alerta podem ocupar toda a tela."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Permite que o aplicativo se sobreponha visualmente a outros aplicativos ou a partes da interface do usuário. Podem interferir com o uso da interface de qualquer aplicativo ou alterar o que você acha que está vendo em outros aplicativos."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"modificar velocidade de animação global"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Permite que o aplicativo altere a velocidade de animação global (animação mais rápida ou mais lenta) a qualquer momento."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"gerenciar tokens do aplicativo"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Permite que o aplicativo crie e gerencie seus próprios tokens, ignorando seus pedidos Z normais. Nunca deve ser necessário para aplicativos normais."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"congelar tela"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Permite que o aplicativo congele temporariamente a tela para uma transição de tela inteira."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"pressionar as teclas e os botões de controle"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Permite que o aplicativo exiba seus próprios eventos de entrada (teclas pressionadas, etc.) para outros aplicativos. Aplicativos maliciosos podem usar isso para tomar conta do tablet."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Permite que o aplicativo entregue seus próprios eventos de entrada (teclas pressionadas, etc,) para outros aplicativos. Aplicativos maliciosos podem usar esse recurso para assumir o controle do telefone."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"instalar aplicativos diretamente"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Permite que o aplicativo instale pacotes novos ou atualizados do Android. Aplicativos maliciosos podem usar esse recurso para adicionar novos aplicativos com permissões arbitrariamente poderosas."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"excluir todos os dados do cache do aplicativo"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Permite que o aplicativo aumente o espaço de armazenamento no tablet por meio da exclusão de arquivos no diretório de cache do aplicativo. Em geral, o acesso é muito restrito para processos do sistema."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Permite que o aplicativo aumente o espaço de armazenamento gratuito do telefone por meio da exclusão de arquivos do diretório de cache do aplicativo. Em geral, o acesso é muito restrito paras processo do sistema."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Permite que o aplicativo libere o armazenamento do tablet excluindo arquivos nos diretórios de cache de outros aplicativos. Isso pode fazer com que outros aplicativos iniciem mais lentamente, pois precisam recuperar seus dados."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Permite que o aplicativo libere o armazenamento do telefone excluindo arquivos nos diretórios de cache de outros aplicativos. Isso pode fazer com que outros aplicativos iniciem mais lentamente, pois precisam recuperar seus dados."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"mover recursos de aplicativos"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Permite que o aplicativo mova recursos de aplicativos da mídia interna para mídia externa e vice-versa."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"ler dados de registro de informações confidenciais"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Permite que o aplicativo acesse comandos do provedor não relacionados à localização. Isso pode permitir que o aplicativo interfira no funcionamento do GPS ou de outras fontes de localização."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"autorização para instalar um provedor de localização"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Criar fontes de localização simuladas para testar ou instalar um novo provedor de localização. Isso permite que o aplicativo substitua a localização e/ou o status retornado por outras fontes de localização, como o GPS ou provedores de localização."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"loalização precisa (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Acessar fontes de localização precisa, como o GPS do tablet. Quando esses serviços de localização estão disponíveis e ligados, esta permissão possibilita que o aplicativo determine sua localização precisa."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Acessar fontes de localização precisa, como o GPS do telefone. Quando esses serviços de localização estão disponíveis e ligados, esta permissão possibilita que o aplicativo determine sua localização precisa."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"localização aproximada (com base na rede)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Acessar a localização aproximada a partir de fornecedores de localização que utilizam fontes de rede como torres de celular e Wi-Fi. Quando esses serviços de localização estão disponíveis e ligados, esta permissão possibilita que o aplicativo determine sua localização aproximada."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"localização precisa (GPS e com base na rede)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Permite que o aplicativo acesse sua localização exata por meio do sistema de posicionamento global (GPS) ou de fontes de localização da rede, como torres de celulares e redes Wi-Fi. Esses serviços de localização devem estar ativados e disponíveis para que sejam usados pelo aplicativo. O aplicativo pode usar esta permissão para determinar onde você está, além de consumir mais bateria."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"localização aproximada (com base na rede)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Permite que o aplicativo acesse sua localização aproximada por meio do sistema de posicionamento global (GPS) ou de fontes de localização da rede, como torres de celulares e redes Wi-Fi. Esses serviços de localização devem estar ativados e disponíveis para que sejam usados pelo aplicativo. O aplicativo pode usar esta permissão para determinar aproximadamente onde você está."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"acessar SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Permite que o aplicativo use recursos com baixos níveis de SurfaceFlinger."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"ler o buffer do frame"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Permite que o aplicativo leia o conteúdo do buffer de frame."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"configurar monitores Wi-Fi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permite que o aplicativo configure e conecte a monitores Wi-Fi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controlar monitores Wi-Fi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permite que o aplicativo controle recursos de baixo nível de monitores Wi-Fi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"alterar as suas configurações de áudio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite que o aplicativo modifique configurações de áudio globais como volume e alto-falantes de saída."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"gravar áudio"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"acessar configurações de Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Permite que um aplicativo configure o tablet Bluetooth local, descubra dispositivos remotos e emparelhe com eles."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permite que um aplicativo configure o telefone Bluetooth local, descubra e emparelhe com dispositivos remotos."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Ver conexões WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"conectar e desconectar do WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permite que o aplicativo determine se o WiMAX está ativado e acesse informações sobre as redes WiMAX conectadas."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Alterar estado do WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite que o aplicativo conecte e desconecte o tablet de redes WiMAX."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Permite que o aplicativo modifique seus feeds sincronizados no momento. Aplicativos maliciosos podem alterar seus feeds sincronizados."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"ler termos adicionados ao dicionário"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Permite que o aplicativo leia palavras, nomes e frases armazenados pelo usuário no dicionário do usuário."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"gravar no dicionário definido pelo usuário"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"adicionar palavras ao dicionário do usuário"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Permite que o aplicativo grave novas palavras no dicionário do usuário."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"testar o acesso ao armazenamento protegido"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"testar o acesso ao armazenamento protegido"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Permite que o aplicativo teste uma permissão para o armazenamento USB que estará disponível em dispositivos futuros."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Permite que o aplicativo teste uma permissão para o armazenamento USB que estará disponível em dispositivos futuros."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Permite que o aplicativo teste uma permissão para o cartão SD que estará disponível em dispositivos futuros."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modif ou excl cont. armaz USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modificar ou excluir o conteúdo do cartão SD"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Permite que o aplicativo grave em seu cartão SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"modificar/excluir conteúdos de armazenamento de mídia internos"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Permite que o aplicativo modifique o conteúdo da mídia de armazenamento interno."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"acessar arm. ext. dos usuários"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Permite que o aplicativo acesse o armazenamento externo para todos os usuários."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"acessar o sistema de arquivos de cache"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite que o aplicativo leia e grave o sistema de arquivos cache."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"fazer/receber chamadas pela internet"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Exija que os dados armazenados do aplicativo sejam criptografados."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Desativar câmeras"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Impeça o uso de todas as câmeras do dispositivo."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Desat. recursos ao bloq. tecl."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Impede o uso de determinados recursos quando o teclado está bloqueado."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Residencial"</item>
     <item msgid="869923650527136615">"Celular"</item>
@@ -695,14 +758,14 @@
     <string name="lockscreen_emergency_call" msgid="5347633784401285225">"Chamada de emergência"</string>
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Retornar à chamada"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Correto!"</string>
-    <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Tentar novamente"</string>
-    <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Tentar novamente"</string>
+    <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Tente novamente"</string>
+    <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Tente novamente"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"O número máximo de tentativas de Desbloqueio por reconhecimento facial foi excedido"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Carregando, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Carregado."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Carregado"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecte o seu carregador."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Sem cartão SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Sem cartão SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Não há um cartão SIM no tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Não há um cartão SIM no telefone."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Insera um cartão SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Padrão apagado"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Célula adicionada"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Padrão concluído"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Adicionar widget"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Vazio"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Área de desbloqueio expandida."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Área de desbloqueio recolhida."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Widget de <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Seletor de usuários"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Status"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Câmera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Controles de mídia"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Reordenação de widgets iniciada."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Reordenação de widgets concluída."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> excluído."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Expandir a área de desbloqueio."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Desbloqueio com deslize."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueio com padrão."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Desbloqueio facial."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueio com PIN."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueio com senha."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área do padrão."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslize."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copiar URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Selecionar texto"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Seleção de texto"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"adicionar ao dicionário"</string>
-    <string name="deleteText" msgid="7070985395199629156">"excluir"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Adicionar ao dicionário"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Excluir"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Método de entrada"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Ações de texto"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Pouco espaço de armazenamento"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Redes Wi-Fi abertas disponíveis"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Fazer login na rede Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Acessar a rede"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Não foi possível se conectar a redes Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tem uma conexão de baixa qualidade com a Internet."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Para:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Digite o PIN obrigatório:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"O telefone desconectará temporariamente da rede Wi-Fi enquanto estiver conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Inserir caractere"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Enviando mensagens SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; envia uma grande quantidade de mensagens SMS. Deseja permitir que este aplicativo continue enviando mensagens?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Permitir"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Negar"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; deseja enviar uma mensagem para &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Isto "<font fgcolor="#ffffb060">"poderá gerar cobranças"</font>" em sua conta de celular."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Isto irá gerar cobranças em sua conta de celular."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Enviar"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Cancelar"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Lembrar minha escolha"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"P/ alterar: Configurações &gt; Aplicativos"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Sempre permitir"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nunca permitir"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Cartão SIM removido"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"A rede móvel ficará indisponível até que você reinicie com um cartão SIM válido inserido."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Concluído"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Definir data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Definir"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Concluído"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Padrão"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Nenhuma permissão necessária"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Ocultar"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostrar todas"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NOVO: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NOVO: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Fornecido por <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Nenhuma permissão necessária"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"isso pode lhe custar dinheiro"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Armazenamento USB em massa"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Conectado por USB"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Você se conectou ao computador via USB. Toque no botão abaixo se quiser copiar arquivos entre o computador e o armazenamento USB de seu Android."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"A VPN está ativada por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toque para gerenciar a rede."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Toque para gerenciar a rede."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN sempre ativa conectando..."</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sempre ativa conectada"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Erro na VPN sempre ativa"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Toque para redefinir a conexão"</string>
     <string name="upload_file" msgid="2897957172366730416">"Escolher arquivo"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nenhum arquivo escolhido"</string>
     <string name="reset" msgid="2448168080964209908">"Redefinir"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Compartilhar"</string>
     <string name="find" msgid="4808270900322985960">"Localizar"</string>
     <string name="websearch" msgid="4337157977400211589">"Pesquisa na web do Google"</string>
+    <string name="find_next" msgid="5742124618942193978">"Localizar próximo"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Localizar anterior"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Solicitação de local de <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Solicitação de local"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Solicitado por <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefone"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Fones de ouvido"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Alto-falantes do dock"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Áudio HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Áudio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Concluído"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Saída de mídia"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Verificando..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Conectando..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Disponível"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Não disponível"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Tela integrada"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Tela HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Sobreposição nº <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"O Display sem fio está conectado"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Tela exibida em outro dispositivo."</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Desconectar"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Chamada de emergência"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Esqueci o padrão"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Padrão incorreto"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Senha incorreta"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN incorreto"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Tente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Desenhe seu padrão"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Digite o PIN do cartão SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Digite o PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Digite a senha"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"O SIM foi desativado. Insira o código PUK para continuar. Entre em contato com a operadora para obter mais detalhes."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Digite o código PIN desejado"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Confirme o código PIN desejado"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Desbloqueando o cartão SIM…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Código PIN incorreto."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Digite um PIN com quatro a oito números."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"O código PUK deve ter 8 números ou mais."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Introduza novamente o código PUK correto. Muitas tentativas malsucedidas desativarão permanentemente o SIM."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Os códigos PIN não coincidem"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Muitas tentativas de padrão"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Para desbloquear, faça login usando sua Conta do Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Nome de usuário (e-mail)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Senha"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Fazer login"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Nome de usuário ou senha inválidos."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Esqueceu seu nome de usuário ou senha?"\n"Acesse "<b>"google.com.br/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Verificando a conta..."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Você digitou seu PIN incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. "\n\n"Tente novamente em <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Você digitou sua senha incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. "\n\n"Tente novamente em <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. "\n\n"Tente novamente em <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Você tentou desbloquear incorretamente o tablet <xliff:g id="NUMBER_0">%d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas malsucedidas, o tablet será redefinido para o padrão de fábrica e todos os dados do usuário serão perdidos."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Você tentou desbloquear incorretamente o telefone <xliff:g id="NUMBER_0">%d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas malsucedidas, o telefone será redefinido para o padrão de fábrica e todos os dados do usuário serão perdidos."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Você tentou desbloquear incorretamente o tablet <xliff:g id="NUMBER">%d</xliff:g> vezes. O tablet será redefinido para o padrão de fábrica."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Você tentou desbloquear incorretamente o telefone <xliff:g id="NUMBER">%d</xliff:g> vezes. O telefone será redefinido para o padrão de fábrica."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear seu tablet."\n\n" Tente novamente em <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear."\n\n" Tente novamente em <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Remover"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Aumentar o volume acima do nível seguro?"\n"A audição em volume elevado por períodos longos pode prejudicar sua audição."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Mantenha pressionado com dois dedos para ativar a acessibilidade."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Acessibilidade ativada."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Acessibilidade cancelada."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Usuário atual <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Proprietário"</string>
 </resources>
diff --git a/core/res/res/values-rm/donottranslate-cldr.xml b/core/res/res/values-rm/donottranslate-cldr.xml
index ccdb17c..e6f0df2 100644
--- a/core/res/res/values-rm/donottranslate-cldr.xml
+++ b/core/res/res/values-rm/donottranslate-cldr.xml
@@ -1,94 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">schaner</string>
-    <string name="month_long_standalone_february">favrer</string>
-    <string name="month_long_standalone_march">mars</string>
-    <string name="month_long_standalone_april">avrigl</string>
-    <string name="month_long_standalone_may">matg</string>
-    <string name="month_long_standalone_june">zercladur</string>
-    <string name="month_long_standalone_july">fanadur</string>
-    <string name="month_long_standalone_august">avust</string>
-    <string name="month_long_standalone_september">settember</string>
-    <string name="month_long_standalone_october">october</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">december</string>
-
-    <string name="month_long_january">schaner</string>
-    <string name="month_long_february">favrer</string>
-    <string name="month_long_march">mars</string>
-    <string name="month_long_april">avrigl</string>
-    <string name="month_long_may">matg</string>
-    <string name="month_long_june">zercladur</string>
-    <string name="month_long_july">fanadur</string>
-    <string name="month_long_august">avust</string>
-    <string name="month_long_september">settember</string>
-    <string name="month_long_october">october</string>
-    <string name="month_long_november">november</string>
-    <string name="month_long_december">december</string>
-
-    <string name="month_medium_january">schan.</string>
-    <string name="month_medium_february">favr.</string>
-    <string name="month_medium_march">mars</string>
-    <string name="month_medium_april">avr.</string>
-    <string name="month_medium_may">matg</string>
-    <string name="month_medium_june">zercl.</string>
-    <string name="month_medium_july">fan.</string>
-    <string name="month_medium_august">avust</string>
-    <string name="month_medium_september">sett.</string>
-    <string name="month_medium_october">oct.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">dec.</string>
-
-    <string name="month_shortest_january">S</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">Z</string>
-    <string name="month_shortest_july">F</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">dumengia</string>
-    <string name="day_of_week_long_monday">glindesdi</string>
-    <string name="day_of_week_long_tuesday">mardi</string>
-    <string name="day_of_week_long_wednesday">mesemna</string>
-    <string name="day_of_week_long_thursday">gievgia</string>
-    <string name="day_of_week_long_friday">venderdi</string>
-    <string name="day_of_week_long_saturday">sonda</string>
-
-    <string name="day_of_week_medium_sunday">du</string>
-    <string name="day_of_week_medium_monday">gli</string>
-    <string name="day_of_week_medium_tuesday">ma</string>
-    <string name="day_of_week_medium_wednesday">me</string>
-    <string name="day_of_week_medium_thursday">gie</string>
-    <string name="day_of_week_medium_friday">ve</string>
-    <string name="day_of_week_medium_saturday">so</string>
-
-    <string name="day_of_week_short_sunday">du</string>
-    <string name="day_of_week_short_monday">gli</string>
-    <string name="day_of_week_short_tuesday">ma</string>
-    <string name="day_of_week_short_wednesday">me</string>
-    <string name="day_of_week_short_thursday">gie</string>
-    <string name="day_of_week_short_friday">ve</string>
-    <string name="day_of_week_short_saturday">so</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">G</string>
-    <string name="day_of_week_shortest_tuesday">M</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">G</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="yesterday">ier</string>
-    <string name="today">oz</string>
-    <string name="tomorrow">damaun</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index a00934d..0e7aaec 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -192,6 +192,12 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opziuns dal telefon"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Bloccaziun dal visur"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Metter ord funcziun"</string>
+    <!-- no translation found for global_action_bug_report (7934010578922304799) -->
+    <skip />
+    <!-- no translation found for bugreport_title (2667494803742548533) -->
+    <skip />
+    <!-- no translation found for bugreport_message (398447048750350456) -->
+    <skip />
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Modus silenzius"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Il tun è deactivà."</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Il tun è activà."</string>
@@ -209,15 +215,82 @@
     <!-- no translation found for permgroupdesc_messages (7821999071003699236) -->
     <skip />
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Vossas infurmaziuns persunalas"</string>
-    <!-- no translation found for permgroupdesc_personalInfo (6975389054186265786) -->
+    <!-- no translation found for permgroupdesc_personalInfo (8426453129788861338) -->
     <skip />
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Acceder directamain als contacts ed al chalender memorisà sin il telefonin."</string>
+    <!-- no translation found for permgrouplab_socialInfo (5799096623412043791) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_socialInfo (7129842457611643493) -->
+    <skip />
     <string name="permgrouplab_location" msgid="635149742436692049">"Vossa posiziun"</string>
     <!-- no translation found for permgroupdesc_location (5704679763124170100) -->
     <skip />
     <string name="permgrouplab_network" msgid="5808983377727109831">"Communicaziun rait"</string>
     <!-- no translation found for permgroupdesc_network (4478299413241861987) -->
     <skip />
+    <!-- no translation found for permgrouplab_bluetoothNetwork (1585403544162128109) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_bluetoothNetwork (5625288577164282391) -->
+    <skip />
+    <!-- no translation found for permgrouplab_audioSettings (8329261670151871235) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_audioSettings (2641515403347568130) -->
+    <skip />
+    <!-- no translation found for permgrouplab_affectsBattery (6209246653424798033) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_affectsBattery (6441275320638916947) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendar (5863508437783683902) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_calendar (5777534316982184416) -->
+    <skip />
+    <!-- no translation found for permgrouplab_dictionary (4148597128843641379) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_dictionary (7921166355964764490) -->
+    <skip />
+    <!-- no translation found for permgrouplab_writeDictionary (8090237702432576788) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_writeDictionary (2711561994497361646) -->
+    <skip />
+    <!-- no translation found for permgrouplab_bookmarks (1949519673103968229) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_bookmarks (4169771606257963028) -->
+    <skip />
+    <!-- no translation found for permgrouplab_deviceAlarms (6117704629728824101) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_deviceAlarms (4769356362251641175) -->
+    <skip />
+    <!-- no translation found for permgrouplab_voicemail (4162237145027592133) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_voicemail (2498403969862951393) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphone (171539900250043464) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_microphone (7106618286905738408) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camera (4820372495894586615) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_camera (2933667372289567714) -->
+    <skip />
+    <!-- no translation found for permgrouplab_appInfo (8028789762634147725) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_appInfo (3950378538049625907) -->
+    <skip />
+    <!-- no translation found for permgrouplab_wallpaper (3850280158041175998) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_wallpaper (5630417854750540154) -->
+    <skip />
+    <!-- no translation found for permgrouplab_systemClock (406535759236612992) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_systemClock (3944359833624094992) -->
+    <skip />
+    <!-- no translation found for permgrouplab_statusBar (2095862568113945398) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_statusBar (6242593432226807171) -->
+    <skip />
+    <!-- no translation found for permgrouplab_syncSettings (3341990986147826541) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_syncSettings (7603195265129031797) -->
+    <skip />
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Voss contos"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Access als contos disponibels"</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Cumonds da la hardware"</string>
@@ -229,6 +302,10 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Utensils per sviluppaders"</string>
     <!-- no translation found for permgroupdesc_developmentTools (7058828032358142018) -->
     <skip />
+    <!-- no translation found for permgrouplab_display (4279909676036402636) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_display (6051002031933013714) -->
+    <skip />
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Memoria"</string>
     <!-- no translation found for permgroupdesc_storage (7442318502446874999) -->
     <skip />
@@ -289,6 +366,18 @@
     <skip />
     <!-- no translation found for permdesc_getTasks (7454215995847658102) -->
     <skip />
+    <!-- no translation found for permlab_interactAcrossUsers (7114255281944211682) -->
+    <skip />
+    <!-- no translation found for permdesc_interactAcrossUsers (364670963623385786) -->
+    <skip />
+    <!-- no translation found for permlab_interactAcrossUsersFull (2567734285545074105) -->
+    <skip />
+    <!-- no translation found for permdesc_interactAcrossUsersFull (376841368395502366) -->
+    <skip />
+    <!-- no translation found for permlab_manageUsers (1676150911672282428) -->
+    <skip />
+    <!-- no translation found for permdesc_manageUsers (8409306667645355638) -->
+    <skip />
     <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
     <skip />
     <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
@@ -339,6 +428,22 @@
     <skip />
     <!-- no translation found for permdesc_retrieve_window_content (3193269069469700265) -->
     <skip />
+    <!-- no translation found for permlab_temporary_enable_accessibility (2312612135127310254) -->
+    <skip />
+    <!-- no translation found for permdesc_temporary_enable_accessibility (8079456293182975464) -->
+    <skip />
+    <!-- no translation found for permlab_retrieve_window_info (8532295199112519378) -->
+    <skip />
+    <!-- no translation found for permdesc_retrieve_window_info (4998836370424186849) -->
+    <skip />
+    <!-- no translation found for permlab_filter_events (8675535648807427389) -->
+    <skip />
+    <!-- no translation found for permdesc_filter_events (8006236315888347680) -->
+    <skip />
+    <!-- no translation found for permlab_magnify_display (5973626738170618775) -->
+    <skip />
+    <!-- no translation found for permdesc_magnify_display (7121235684515003792) -->
+    <skip />
     <string name="permlab_shutdown" msgid="7185747824038909016">"serrar parzialmain"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Metta l\'administratur dad activitads en in stadi da pausa. El na vegn betg serrà dal tut."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar il midar tranter applicaziuns"</string>
@@ -364,8 +469,13 @@
     <skip />
     <!-- no translation found for permdesc_setAlwaysFinish (7471310652868841499) -->
     <skip />
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"modifitgar las datas da l\'accu"</string>
-    <!-- no translation found for permdesc_batteryStats (6835186932305744068) -->
+    <!-- no translation found for permlab_batteryStats (2789610673514103364) -->
+    <skip />
+    <!-- no translation found for permdesc_batteryStats (5897346582882915114) -->
+    <skip />
+    <!-- no translation found for permlab_updateBatteryStats (3719689764536379557) -->
+    <skip />
+    <!-- no translation found for permdesc_updateBatteryStats (6862817857178025002) -->
     <skip />
     <string name="permlab_backup" msgid="470013022865453920">"controllar las copias da segirezza e la restauraziun dal sistem"</string>
     <!-- no translation found for permdesc_backup (6912230525140589891) -->
@@ -379,7 +489,7 @@
     <skip />
     <!-- no translation found for permlab_systemAlertWindow (3543347980839518613) -->
     <skip />
-    <!-- no translation found for permdesc_systemAlertWindow (4460454022797261814) -->
+    <!-- no translation found for permdesc_systemAlertWindow (8584678381972820118) -->
     <skip />
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"modifitgar la sveltezza globala da las animaziuns"</string>
     <!-- no translation found for permdesc_setAnimationScale (7690063428924343571) -->
@@ -388,6 +498,10 @@
     <skip />
     <!-- no translation found for permdesc_manageAppTokens (8043431713014395671) -->
     <skip />
+    <!-- no translation found for permlab_freezeScreen (4708181184441880175) -->
+    <skip />
+    <!-- no translation found for permdesc_freezeScreen (8558923789222670064) -->
+    <skip />
     <string name="permlab_injectEvents" msgid="1378746584023586600">"smatgar tastas e tastas da controlla"</string>
     <!-- no translation found for permdesc_injectEvents (206352565599968632) -->
     <skip />
@@ -464,9 +578,9 @@
     <skip />
     <!-- no translation found for permlab_clearAppCache (7487279391723526815) -->
     <skip />
-    <!-- no translation found for permdesc_clearAppCache (3523396284474042284) -->
+    <!-- no translation found for permdesc_clearAppCache (8974640871945434565) -->
     <skip />
-    <!-- no translation found for permdesc_clearAppCache (5067988373366292186) -->
+    <!-- no translation found for permdesc_clearAppCache (2459441021956436779) -->
     <skip />
     <!-- no translation found for permlab_movePackage (3289890271645921411) -->
     <skip />
@@ -581,15 +695,13 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"permetter l\'installaziun d\'in purschider da servetschs da localisaziun"</string>
     <!-- no translation found for permdesc_installLocationProvider (9066146120470591509) -->
     <skip />
-    <!-- no translation found for permlab_accessFineLocation (5885550969882561436) -->
+    <!-- no translation found for permlab_accessFineLocation (1191898061965273372) -->
     <skip />
-    <!-- no translation found for permdesc_accessFineLocation (8960597421469894181) -->
+    <!-- no translation found for permdesc_accessFineLocation (5295047563564981250) -->
     <skip />
-    <!-- no translation found for permdesc_accessFineLocation (239268765496141815) -->
+    <!-- no translation found for permlab_accessCoarseLocation (4887895362354239628) -->
     <skip />
-    <!-- no translation found for permlab_accessCoarseLocation (7422827215441638984) -->
-    <skip />
-    <!-- no translation found for permdesc_accessCoarseLocation (5383798877137640762) -->
+    <!-- no translation found for permdesc_accessCoarseLocation (2538200184373302295) -->
     <skip />
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"access a SurfaceFlinger"</string>
     <!-- no translation found for permdesc_accessSurfaceFlinger (1041619516733293551) -->
@@ -597,6 +709,14 @@
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"leger il paraculp da frame"</string>
     <!-- no translation found for permdesc_readFrameBuffer (4937405521809454680) -->
     <skip />
+    <!-- no translation found for permlab_configureWifiDisplay (5595661694746742168) -->
+    <skip />
+    <!-- no translation found for permdesc_configureWifiDisplay (7916815158690218065) -->
+    <skip />
+    <!-- no translation found for permlab_controlWifiDisplay (393641276723695496) -->
+    <skip />
+    <!-- no translation found for permdesc_controlWifiDisplay (4543912292681826986) -->
+    <skip />
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modifitgar Voss parameters audio"</string>
     <!-- no translation found for permdesc_modifyAudioSettings (3522565366806248517) -->
     <skip />
@@ -797,7 +917,7 @@
     <skip />
     <!-- no translation found for permdesc_bluetoothAdmin (8931682159331542137) -->
     <skip />
-    <!-- no translation found for permlab_accessWimaxState (7436749103151096452) -->
+    <!-- no translation found for permlab_accessWimaxState (4195907010610205703) -->
     <skip />
     <!-- no translation found for permdesc_accessWimaxState (6360102877261978887) -->
     <skip />
@@ -841,7 +961,7 @@
     <skip />
     <!-- no translation found for permdesc_readDictionary (659614600338904243) -->
     <skip />
-    <!-- no translation found for permlab_writeDictionary (2296383164914812772) -->
+    <!-- no translation found for permlab_writeDictionary (2183110402314441106) -->
     <skip />
     <!-- no translation found for permdesc_writeDictionary (8185385716255065291) -->
     <skip />
@@ -849,7 +969,7 @@
     <skip />
     <!-- no translation found for permlab_sdcardRead (8235341515605559677) -->
     <skip />
-    <!-- no translation found for permdesc_sdcardRead (5791957130190763289) -->
+    <!-- no translation found for permdesc_sdcardRead (3642473292348132072) -->
     <skip />
     <!-- no translation found for permdesc_sdcardRead (5914402684685848828) -->
     <skip />
@@ -865,6 +985,10 @@
     <skip />
     <!-- no translation found for permdesc_mediaStorageWrite (8189160597698529185) -->
     <skip />
+    <!-- no translation found for permlab_sdcardAccessAll (8150613823900460576) -->
+    <skip />
+    <!-- no translation found for permdesc_sdcardAccessAll (3215208357415891320) -->
+    <skip />
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"access al sistem da datotecas da cache"</string>
     <!-- no translation found for permdesc_cache_filesystem (5578967642265550955) -->
     <skip />
@@ -921,6 +1045,10 @@
     <skip />
     <!-- no translation found for policydesc_disableCamera (2306349042834754597) -->
     <skip />
+    <!-- no translation found for policylab_disableKeyguardFeatures (266329104542638802) -->
+    <skip />
+    <!-- no translation found for policydesc_disableKeyguardFeatures (3467082272186534614) -->
+    <skip />
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Privat"</item>
     <item msgid="869923650527136615">"Telefonin"</item>
@@ -1090,11 +1218,13 @@
     <skip />
     <!-- no translation found for lockscreen_plugged_in (8057762828355572315) -->
     <skip />
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Chargià"</string>
+    <!-- no translation found for lockscreen_charged (321635745684060624) -->
+    <skip />
     <!-- no translation found for lockscreen_battery_short (4477264849386850266) -->
     <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Connectai Voss chargiader."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nagina carta SIM."</string>
+    <!-- no translation found for lockscreen_missing_sim_message_short (5099439277819215399) -->
+    <skip />
     <!-- no translation found for lockscreen_missing_sim_message (151659196095791474) -->
     <skip />
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"En il telefon na sa chatta nagina carta SIM."</string>
@@ -1168,6 +1298,46 @@
     <skip />
     <!-- no translation found for lockscreen_access_pattern_detected (4988730895554057058) -->
     <skip />
+    <!-- no translation found for keyguard_accessibility_add_widget (8273277058724924654) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_widget_empty_slot (1281505703307930757) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_unlock_area_expanded (2278106022311170299) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_unlock_area_collapsed (6366992066936076396) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_widget (6527131039741808240) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_user_selector (1226798370913698896) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_status (8008264603935930611) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_camera (8904231194181114603) -->
+    <skip />
+    <!-- no translation found for keygaurd_accessibility_media_controls (262209654292161806) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_widget_reorder_start (8736853615588828197) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_widget_reorder_end (7170190950870468320) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_widget_deleted (4426204263929224434) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_expand_lock_area (519859720934178024) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_slide_unlock (2959928478764697254) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_pattern_unlock (1490840706075246612) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_face_unlock (4817282543351718535) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_pin_unlock (2469687111784035046) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_password_unlock (7675777623912155089) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_pattern_area (7679891324509597904) -->
+    <skip />
+    <!-- no translation found for keyguard_accessibility_slide_area (6736064494019979544) -->
+    <skip />
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -1414,9 +1584,9 @@
     <!-- no translation found for selectTextMode (1018691815143165326) -->
     <skip />
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selecziun da text"</string>
-    <!-- no translation found for addToDictionary (9090375111134433012) -->
+    <!-- no translation found for addToDictionary (4352161534510057874) -->
     <skip />
-    <!-- no translation found for deleteText (7070985395199629156) -->
+    <!-- no translation found for deleteText (6979668428458199034) -->
     <skip />
     <string name="inputMethod" msgid="1653630062304567879">"Metoda d\'endataziun"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acziuns da text"</string>
@@ -1536,7 +1706,9 @@
   </plurals>
     <!-- no translation found for wifi_available_sign_in (4029489716605255386) -->
     <skip />
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <!-- no translation found for network_available_sign_in (8495155593358054676) -->
+    <skip />
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <!-- no translation found for wifi_watchdog_network_disabled (7904214231651546347) -->
     <skip />
@@ -1568,6 +1740,8 @@
     <skip />
     <!-- no translation found for wifi_p2p_show_pin_message (8530563323880921094) -->
     <skip />
+    <!-- no translation found for wifi_p2p_frequency_conflict_message (7363907213787469151) -->
+    <skip />
     <string name="select_character" msgid="3365550120617701745">"Inserir in caracter"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Trametter messadis SMS"</string>
     <!-- no translation found for sms_control_message (3867899169651496433) -->
@@ -1576,6 +1750,24 @@
     <skip />
     <!-- no translation found for sms_control_no (625438561395534982) -->
     <skip />
+    <!-- no translation found for sms_short_code_confirm_message (1645436466285310855) -->
+    <skip />
+    <!-- no translation found for sms_short_code_details (3492025719868078457) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_details (5523826349105123687) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (4458878637111023413) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (2927389840209170706) -->
+    <skip />
+    <!-- no translation found for sms_short_code_remember_choice (5289538592272218136) -->
+    <skip />
+    <!-- no translation found for sms_short_code_remember_undo_instruction (4960944133052287484) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_always_allow (3241181154869493368) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_never_allow (446992765774269673) -->
+    <skip />
     <!-- no translation found for sim_removed_title (6227712319223226185) -->
     <skip />
     <!-- no translation found for sim_removed_message (2333164559970958645) -->
@@ -1595,14 +1787,13 @@
     <string name="date_time_set" msgid="5777075614321087758">"Definir"</string>
     <!-- no translation found for date_time_done (2507683751759308828) -->
     <skip />
-    <string name="default_permission_group" msgid="2690160991405646128">"Standard"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Naginas permissiuns obligatoricas"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Zuppentar"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Mussar tut"</b></string>
     <!-- no translation found for perms_new_perm_prefix (8257740710754301407) -->
     <skip />
     <!-- no translation found for perms_description_app (5139836143293299417) -->
     <skip />
+    <string name="no_permissions" msgid="7283357728219338112">"Naginas permissiuns obligatoricas"</string>
+    <!-- no translation found for perm_costs_money (4902470324142151116) -->
+    <skip />
     <!-- no translation found for usb_storage_activity_title (4465055157209648641) -->
     <skip />
     <string name="usb_storage_title" msgid="5901459041398751495">"Connectà cun agid d\'in cabel USB"</string>
@@ -1759,6 +1950,14 @@
     <skip />
     <!-- no translation found for vpn_text_long (6407351006249174473) -->
     <skip />
+    <!-- no translation found for vpn_lockdown_connecting (6443438964440960745) -->
+    <skip />
+    <!-- no translation found for vpn_lockdown_connected (8202679674819213931) -->
+    <skip />
+    <!-- no translation found for vpn_lockdown_error (6009249814034708175) -->
+    <skip />
+    <!-- no translation found for vpn_lockdown_reset (5365010427963548932) -->
+    <skip />
     <string name="upload_file" msgid="2897957172366730416">"Tscherner ina datoteca"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nagina datoteca tschernida"</string>
     <string name="reset" msgid="2448168080964209908">"Reinizialisar"</string>
@@ -1818,6 +2017,10 @@
     <skip />
     <!-- no translation found for websearch (4337157977400211589) -->
     <skip />
+    <!-- no translation found for find_next (5742124618942193978) -->
+    <skip />
+    <!-- no translation found for find_previous (2196723669388360506) -->
+    <skip />
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -2020,7 +2223,7 @@
     <skip />
     <!-- no translation found for default_audio_route_name_dock_speakers (6240602982276591864) -->
     <skip />
-    <!-- no translation found for default_audio_route_name_hdmi (7986404173839007682) -->
+    <!-- no translation found for default_media_route_name_hdmi (2450970399023478055) -->
     <skip />
     <!-- no translation found for default_audio_route_category_name (3722811174003886946) -->
     <skip />
@@ -2028,4 +2231,117 @@
     <skip />
     <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) -->
     <skip />
+    <!-- no translation found for media_route_button_content_description (5758553567065145276) -->
+    <skip />
+    <!-- no translation found for media_route_status_scanning (7279908761758293783) -->
+    <skip />
+    <!-- no translation found for media_route_status_connecting (6422571716007825440) -->
+    <skip />
+    <!-- no translation found for media_route_status_available (6983258067194649391) -->
+    <skip />
+    <!-- no translation found for media_route_status_not_available (6739899962681886401) -->
+    <skip />
+    <!-- no translation found for display_manager_built_in_display_name (2583134294292563941) -->
+    <skip />
+    <!-- no translation found for display_manager_hdmi_display_name (1555264559227470109) -->
+    <skip />
+    <!-- no translation found for display_manager_overlay_display_name (5142365982271620716) -->
+    <skip />
+    <!-- no translation found for display_manager_overlay_display_title (652124517672257172) -->
+    <skip />
+    <!-- no translation found for wifi_display_notification_title (2223050649240326557) -->
+    <skip />
+    <!-- no translation found for wifi_display_notification_message (4498802012464170685) -->
+    <skip />
+    <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) -->
+    <skip />
+    <!-- no translation found for kg_emergency_call_label (684946192523830531) -->
+    <skip />
+    <!-- no translation found for kg_forgot_pattern_button_text (8852021467868220608) -->
+    <skip />
+    <!-- no translation found for kg_wrong_pattern (1850806070801358830) -->
+    <skip />
+    <!-- no translation found for kg_wrong_password (2333281762128113157) -->
+    <skip />
+    <!-- no translation found for kg_wrong_pin (1131306510833563801) -->
+    <skip />
+    <!-- no translation found for kg_too_many_failed_attempts_countdown (6358110221603297548) -->
+    <skip />
+    <!-- no translation found for kg_pattern_instructions (398978611683075868) -->
+    <skip />
+    <!-- no translation found for kg_sim_pin_instructions (2319508550934557331) -->
+    <skip />
+    <!-- no translation found for kg_pin_instructions (2377242233495111557) -->
+    <skip />
+    <!-- no translation found for kg_password_instructions (5753646556186936819) -->
+    <skip />
+    <!-- no translation found for kg_puk_enter_puk_hint (453227143861735537) -->
+    <skip />
+    <!-- no translation found for kg_puk_enter_pin_hint (7871604527429602024) -->
+    <skip />
+    <!-- no translation found for kg_enter_confirm_pin_hint (325676184762529976) -->
+    <skip />
+    <!-- no translation found for kg_sim_unlock_progress_dialog_message (8950398016976865762) -->
+    <skip />
+    <!-- no translation found for kg_password_wrong_pin_code (1139324887413846912) -->
+    <skip />
+    <!-- no translation found for kg_invalid_sim_pin_hint (8795159358110620001) -->
+    <skip />
+    <!-- no translation found for kg_invalid_sim_puk_hint (7553388325654369575) -->
+    <skip />
+    <!-- no translation found for kg_invalid_puk (3638289409676051243) -->
+    <skip />
+    <!-- no translation found for kg_invalid_confirm_pin_hint (7003469261464593516) -->
+    <skip />
+    <!-- no translation found for kg_login_too_many_attempts (6486842094005698475) -->
+    <skip />
+    <!-- no translation found for kg_login_instructions (1100551261265506448) -->
+    <skip />
+    <!-- no translation found for kg_login_username_hint (5718534272070920364) -->
+    <skip />
+    <!-- no translation found for kg_login_password_hint (9057289103827298549) -->
+    <skip />
+    <!-- no translation found for kg_login_submit_button (5355904582674054702) -->
+    <skip />
+    <!-- no translation found for kg_login_invalid_input (5754664119319872197) -->
+    <skip />
+    <!-- no translation found for kg_login_account_recovery_hint (5690709132841752974) -->
+    <skip />
+    <!-- no translation found for kg_login_checking_password (1052685197710252395) -->
+    <skip />
+    <!-- no translation found for kg_too_many_failed_pin_attempts_dialog_message (8276745642049502550) -->
+    <skip />
+    <!-- no translation found for kg_too_many_failed_password_attempts_dialog_message (7813713389422226531) -->
+    <skip />
+    <!-- no translation found for kg_too_many_failed_pattern_attempts_dialog_message (74089475965050805) -->
+    <skip />
+    <!-- no translation found for kg_failed_attempts_almost_at_wipe (1575557200627128949) -->
+    <skip />
+    <!-- no translation found for kg_failed_attempts_almost_at_wipe (4051015943038199910) -->
+    <skip />
+    <!-- no translation found for kg_failed_attempts_now_wiping (2072996269148483637) -->
+    <skip />
+    <!-- no translation found for kg_failed_attempts_now_wiping (4817627474419471518) -->
+    <skip />
+    <!-- no translation found for kg_failed_attempts_almost_at_login (3253575572118914370) -->
+    <skip />
+    <!-- no translation found for kg_failed_attempts_almost_at_login (1437638152015574839) -->
+    <skip />
+    <!-- no translation found for kg_text_message_separator (4160700433287233771) -->
+    <skip />
+    <!-- no translation found for kg_reordering_delete_drop_target_text (7899202978204438708) -->
+    <skip />
+    <!-- no translation found for safe_media_volume_warning (7382971871993371648) -->
+    <skip />
+    <!-- no translation found for continue_to_enable_accessibility (1626427372316070258) -->
+    <skip />
+    <!-- no translation found for accessibility_enabled (1381972048564547685) -->
+    <skip />
+    <!-- no translation found for enable_accessibility_canceled (3833923257966635673) -->
+    <skip />
+    <!-- no translation found for user_switched (3768006783166984410) -->
+    <skip />
+    <!-- no translation found for owner_name (2716755460376028154) -->
+    <!-- no translation found for owner_name (3879126011135546571) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro-rRO/donottranslate-cldr.xml b/core/res/res/values-ro-rRO/donottranslate-cldr.xml
index 732ae24..7056803 100644
--- a/core/res/res/values-ro-rRO/donottranslate-cldr.xml
+++ b/core/res/res/values-ro-rRO/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">ianuarie</string>
-    <string name="month_long_standalone_february">februarie</string>
-    <string name="month_long_standalone_march">martie</string>
-    <string name="month_long_standalone_april">aprilie</string>
-    <string name="month_long_standalone_may">mai</string>
-    <string name="month_long_standalone_june">iunie</string>
-    <string name="month_long_standalone_july">iulie</string>
-    <string name="month_long_standalone_august">august</string>
-    <string name="month_long_standalone_september">septembrie</string>
-    <string name="month_long_standalone_october">octombrie</string>
-    <string name="month_long_standalone_november">noiembrie</string>
-    <string name="month_long_standalone_december">decembrie</string>
-
-    <string name="month_long_january">ianuarie</string>
-    <string name="month_long_february">februarie</string>
-    <string name="month_long_march">martie</string>
-    <string name="month_long_april">aprilie</string>
-    <string name="month_long_may">mai</string>
-    <string name="month_long_june">iunie</string>
-    <string name="month_long_july">iulie</string>
-    <string name="month_long_august">august</string>
-    <string name="month_long_september">septembrie</string>
-    <string name="month_long_october">octombrie</string>
-    <string name="month_long_november">noiembrie</string>
-    <string name="month_long_december">decembrie</string>
-
-    <string name="month_medium_january">ian.</string>
-    <string name="month_medium_february">feb.</string>
-    <string name="month_medium_march">mar.</string>
-    <string name="month_medium_april">apr.</string>
-    <string name="month_medium_may">mai</string>
-    <string name="month_medium_june">iun.</string>
-    <string name="month_medium_july">iul.</string>
-    <string name="month_medium_august">aug.</string>
-    <string name="month_medium_september">sept.</string>
-    <string name="month_medium_october">oct.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">dec.</string>
-
-    <string name="month_shortest_january">I</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">I</string>
-    <string name="month_shortest_july">I</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">duminică</string>
-    <string name="day_of_week_long_monday">luni</string>
-    <string name="day_of_week_long_tuesday">marți</string>
-    <string name="day_of_week_long_wednesday">miercuri</string>
-    <string name="day_of_week_long_thursday">joi</string>
-    <string name="day_of_week_long_friday">vineri</string>
-    <string name="day_of_week_long_saturday">sâmbătă</string>
-
-    <string name="day_of_week_medium_sunday">Du</string>
-    <string name="day_of_week_medium_monday">Lu</string>
-    <string name="day_of_week_medium_tuesday">Ma</string>
-    <string name="day_of_week_medium_wednesday">Mi</string>
-    <string name="day_of_week_medium_thursday">Jo</string>
-    <string name="day_of_week_medium_friday">Vi</string>
-    <string name="day_of_week_medium_saturday">Sâ</string>
-
-    <string name="day_of_week_short_sunday">Du</string>
-    <string name="day_of_week_short_monday">Lu</string>
-    <string name="day_of_week_short_tuesday">Ma</string>
-    <string name="day_of_week_short_wednesday">Mi</string>
-    <string name="day_of_week_short_thursday">Jo</string>
-    <string name="day_of_week_short_friday">Vi</string>
-    <string name="day_of_week_short_saturday">Sâ</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">L</string>
-    <string name="day_of_week_shortest_tuesday">M</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">J</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">ieri</string>
-    <string name="today">azi</string>
-    <string name="tomorrow">mâine</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-ro/donottranslate-cldr.xml b/core/res/res/values-ro/donottranslate-cldr.xml
index e9a70dc..935c6af 100644
--- a/core/res/res/values-ro/donottranslate-cldr.xml
+++ b/core/res/res/values-ro/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">ianuarie</string>
-    <string name="month_long_standalone_february">februarie</string>
-    <string name="month_long_standalone_march">martie</string>
-    <string name="month_long_standalone_april">aprilie</string>
-    <string name="month_long_standalone_may">mai</string>
-    <string name="month_long_standalone_june">iunie</string>
-    <string name="month_long_standalone_july">iulie</string>
-    <string name="month_long_standalone_august">august</string>
-    <string name="month_long_standalone_september">septembrie</string>
-    <string name="month_long_standalone_october">octombrie</string>
-    <string name="month_long_standalone_november">noiembrie</string>
-    <string name="month_long_standalone_december">decembrie</string>
-
-    <string name="month_long_january">ianuarie</string>
-    <string name="month_long_february">februarie</string>
-    <string name="month_long_march">martie</string>
-    <string name="month_long_april">aprilie</string>
-    <string name="month_long_may">mai</string>
-    <string name="month_long_june">iunie</string>
-    <string name="month_long_july">iulie</string>
-    <string name="month_long_august">august</string>
-    <string name="month_long_september">septembrie</string>
-    <string name="month_long_october">octombrie</string>
-    <string name="month_long_november">noiembrie</string>
-    <string name="month_long_december">decembrie</string>
-
-    <string name="month_medium_january">ian.</string>
-    <string name="month_medium_february">feb.</string>
-    <string name="month_medium_march">mar.</string>
-    <string name="month_medium_april">apr.</string>
-    <string name="month_medium_may">mai</string>
-    <string name="month_medium_june">iun.</string>
-    <string name="month_medium_july">iul.</string>
-    <string name="month_medium_august">aug.</string>
-    <string name="month_medium_september">sept.</string>
-    <string name="month_medium_october">oct.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">dec.</string>
-
-    <string name="month_shortest_january">I</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">I</string>
-    <string name="month_shortest_july">I</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">duminică</string>
-    <string name="day_of_week_long_monday">luni</string>
-    <string name="day_of_week_long_tuesday">marți</string>
-    <string name="day_of_week_long_wednesday">miercuri</string>
-    <string name="day_of_week_long_thursday">joi</string>
-    <string name="day_of_week_long_friday">vineri</string>
-    <string name="day_of_week_long_saturday">sâmbătă</string>
-
-    <string name="day_of_week_medium_sunday">Du</string>
-    <string name="day_of_week_medium_monday">Lu</string>
-    <string name="day_of_week_medium_tuesday">Ma</string>
-    <string name="day_of_week_medium_wednesday">Mi</string>
-    <string name="day_of_week_medium_thursday">Jo</string>
-    <string name="day_of_week_medium_friday">Vi</string>
-    <string name="day_of_week_medium_saturday">Sâ</string>
-
-    <string name="day_of_week_short_sunday">Du</string>
-    <string name="day_of_week_short_monday">Lu</string>
-    <string name="day_of_week_short_tuesday">Ma</string>
-    <string name="day_of_week_short_wednesday">Mi</string>
-    <string name="day_of_week_short_thursday">Jo</string>
-    <string name="day_of_week_short_friday">Vi</string>
-    <string name="day_of_week_short_saturday">Sâ</string>
-
-    <string name="day_of_week_shortest_sunday">D</string>
-    <string name="day_of_week_shortest_monday">L</string>
-    <string name="day_of_week_shortest_tuesday">M</string>
-    <string name="day_of_week_shortest_wednesday">M</string>
-    <string name="day_of_week_shortest_thursday">J</string>
-    <string name="day_of_week_shortest_friday">V</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">ieri</string>
-    <string name="today">azi</string>
-    <string name="tomorrow">mâine</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 59acfe1..f274acd 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opţiuni telefon"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Blocaţi ecranul"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Opriţi alimentarea"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Raport despre erori"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Executaţi un raport despre erori"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Acest raport va colecta informaţii despre starea actuală a dispozitivului, pentru a le trimite într-un e-mail. Aveți răbdare după pornirea raportului despre erori până când va fi gata de trimis."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Mod Silenţios"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Sunetul este DEZACTIVAT"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Sunetul este ACTIVAT"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Mesajele dvs."</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Citire şi scriere mesaje SMS, e-mailuri şi alte mesaje."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Informaţiile dvs. personale"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Acces direct la agenda şi la calendarul stocate pe computerul dvs. tablet PC."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Acces direct la agenda şi la calendarul stocate pe telefonul dvs."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Acces direct la informaţii despre dvs., stocate pe cartea de vizită."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Informaţiile dvs. sociale"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Acces direct la informaţii despre persoanele de contact şi conexiunile dvs. sociale."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Locaţia dvs."</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Monitorizează locaţia dvs. fizică."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Comunicare în reţea"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Accesează diferite funcţii ale reţelei."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Accesează dispozitive şi reţele prin intermediul Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Setările audio"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Modifică setările audio."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Capacitatea de a afecta bateria"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Utilizează funcţii care pot consuma rapid bateria."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Calendarul"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Acces direct la calendar şi la evenimente."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Citeşte dicţionarul utilizatorului"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Citeşte cuvinte din dicţionarul utilizatorului."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Scrie în dicţionarul utilizatorului"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Adaugă cuvinte în dicţionarul utilizatorului."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Marcajele şi Istoricul"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Acces direct la marcaje şi la istoricul navigării."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarma"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Setează ceasul cu alarmă."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Mesageria vocală"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Acces direct la mesageria vocală."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Microfonul"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Acces direct la microfon pentru înregistrări audio."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Camera foto"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Acces direct la camera foto pentru a realiza fotografii şi videoclipuri."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Informaţiile despre aplicaţiile dvs."</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Capacitatea de a influenţa comportamentul altor aplicaţii de pe dispozitiv."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Imaginea de fundal"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Modifică setările pentru imaginea de fundal a dispozitivului."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Ceasul"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Modifică ora sau fusul orar ale dispozitivului."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Bara de stare"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Modifică setările pentru bara de stare a dispozitivului."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Setările de sincronizare"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Acces la setările de sincronizare."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Conturile dvs."</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Accesează conturile disponibile."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Controale hardware"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Acces şi control de nivel redus ale sistemului."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Instrumente de dezvoltare"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funcţii necesare doar pentru dezvoltatorii de aplicaţii."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Interfaţa de utilizare a altor aplicaţii"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Influenţează interfaţa de utilizare a altor aplicaţii."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Stocare"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Accesează stocarea USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Accesează cardul SD."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permite aplicaţiei să primească şi să proceseze mesaje WAP. Această permisiune include capacitatea de a monitoriza sau şterge mesajele care v-au fost trimise fără a vi le arăta."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"preluare aplicaţii care rulează"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Permite aplicaţiei să preia informaţiile despre activităţile care rulează în prezent şi care au rulat recent. În acest fel, aplicaţia poate descoperi informaţii despre aplicaţiile care sunt utilizate pe dispozitiv."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interacţiune între utilizatori"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permite aplicaţiei să efectueze acţiuni pentru diferiţi utilizatori pe dispozitiv. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a încălca protecţia între utilizatori."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"licenţă completă pentru interacţiune între utilizatori"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permite toate interacţiunile posibile între utilizatori."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"gestionează utilizatorii"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permite aplicaţiilor să gestioneze utilizatorii de pe dispozitiv, inclusiv interogarea, crearea şi ştergerea acestora."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"preia detalii despre aplicaţiile care rulează"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite aplicaţiei să preia informaţii detaliate despre activităţile rulate curent şi recent. Aplicaţiile rău intenţionate pot să descopere informaţii private despre alte aplicaţii."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"reordonare aplicaţii care rulează"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Permite aplicaţiei să preia starea internă a sistemului. Aplicaţiile rău intenţionate pot să preia o gamă variată de informaţii private şi securizate, de care în mod normal nu ar avea nevoie niciodată."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"preia conţinutul de pe ecran"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite aplicaţiei să preia conţinutul ferestrei active. Aplicaţiile rău intenţionate pot să preia întregul conţinut al ferestrei şi să examineze integral textul acesteia, cu excepţia parolelor."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"activare temporară a accesibilității"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permite unei aplicaţii să activeze temporar accesibilitatea pe gadget. Aplicaţiile rău intenţionate o pot activa fără consimţământul utilizatorului."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"preluare informaţii despre ferestre"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permite unei aplicaţii să preia informaţii despre ferestrele din managerul de ferestre. Aplicaţiile rău intenţionate pot prelua informaţii care sunt destinate utilizării sistemului intern."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrare evenimente"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Permite unei aplicaţii să înregistreze un filtru de intrare, care filtrează transmiterea în flux a tuturor evenimentelor utilizatorilor înainte ca acestea să fie expediate. Aplicaţiile rău intenţionate pot controla interfaţa de utilizare a sistemului fără intervenţia utilizatorului."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"măreşte afişajul"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Permite unei aplicaţii să mărească conţinutul unui afişaj. Aplicaţiile rău intenţionate pot transforma conţinutul afişajului într-un mod care ar face inutilizabil dispozitivul."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"închidere parţială"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Plasează Managerul de activităţi într-o stare de închidere. Nu efectuează o închidere completă."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"împiedicare comutare între aplicaţii"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permite aplicaţiei să controleze numărul maxim de procese care vor rula. Nu este niciodată necesară pentru aplicaţiile obişnuite."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forţează închiderea aplicaţiilor de fundal"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Permite aplicaţiei să controleze dacă activităţile sunt întotdeauna închise imediat ce ajung în fundal. Nu este niciodată necesară pentru aplicaţiile obişnuite."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"modificare statistici referitoare la baterie"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Permite aplicaţiei să modifice statisticile colectate despre baterie. Nu se utilizează de aplicaţiile obişnuite."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"citeşte statistici referitoare la baterie"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permite unei aplicaţii să citească datele actuale privind utilizarea la nivel redus a bateriei. Cu această permisiune, aplicaţia poate afla informaţii detaliate despre aplicaţiile pe care le utilizaţi."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modifică statistici referitoare la baterie"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permite aplicaţiei să modifice statisticile colectate despre baterie. Nu se utilizează de aplicaţiile obişnuite."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controlare copiere de rezervă şi restabilire a sistemului"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Permite aplicaţiei să controleze mecanismul de copiere de rezervă şi de restabilire al sistemului. Nu se utilizează de aplicaţiile obişnuite."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"confirmă o operaţie completă de copiere de rezervă sau de restabilire"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"afişare ferestre neautorizate"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Permite aplicaţiei să creeze ferestre destinate a fi folosite de către interfaţa de utilizare a sistemului intern. Nu se utilizează de aplicaţiile obişnuite."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"suprapune elemente vizuale peste alte aplicaţii"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Permite aplicaţiei să afişeze ferestre de alertă de sistem. Unele ferestre de alertă pot prelua controlul asupra întregului ecran."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Permite aplicaţiei să suprapună elemente vizuale peste alte aplicaţii sau părţi ale interfeţei cu utilizatorul. Acestea pot interfera cu utilizarea de către dvs. a interfeţei în orice aplicaţie sau pot schimba ceea ce credeţi că vedeţi în alte aplicaţii."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"modificare viteză de animaţie globală"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Permite aplicaţiei să modifice oricând viteza globală de animaţie (animaţii mai rapide sau mai lente)."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"gestionare indicative aplicaţii"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Permite aplicaţiei să creeze şi să gestioneze propriile indicative, evitând ordinea lor Z normală. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"îngheaţă ecranul"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Permite aplicaţiei să îngheţe temporar ecranul pentru o tranziţie la ecran complet."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"apăsare taste şi control butoane"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Permite aplicaţiei să furnizeze propriile evenimente de intrare (apăsări de taste etc.) către alte aplicaţii. Aplicaţiile rău intenţionate pot să utilizeze această permisiune pentru a prelua controlul asupra tabletei."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Permite aplicaţiei să furnizeze propriile evenimente de intrare (apăsări de taste etc.) către alte aplicaţii. Aplicaţiile rău intenţionate pot să utilizeze această permisiune pentru a prelua controlul asupra telefonului."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"instalare directă a aplicaţiilor"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Permite aplicaţiei să instaleze pachete Android noi sau actualizate. Aplicaţiile rău intenţionate pot să utilizeze această permisiune pentru a adăuga aplicaţii noi cu permisiuni puternice alese la întâmplare."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"ştergere integrală date din cache ale aplicaţiei"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Permite aplicaţiei să elibereze spaţiu de stocare pe tabletă, prin ştergerea fişierelor din directorul cache al aplicaţiei. De regulă, accesul este strict restricţionat la procesul de sistem."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Permite aplicaţiei să elibereze spaţiu de stocare pe telefon, prin ştergerea fişierelor din directorul cache al aplicaţiei. De regulă, accesul este strict restricţionat la procesul de sistem."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Permite aplicaţiei să elibereze spaţiul de stocare al tabletei, ştergând fişierele din directoarele cache ale altor aplicaţii. Acest lucru poate determina pornirea mai lentă a altor aplicaţii, deoarece acestea trebuie să îşi recupereze datele."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Permite aplicaţiei să elibereze spaţiul de stocare al telefonului, ştergând fişierele din directoarele cache ale altor aplicaţii. Acest lucru poate determina pornirea mai lentă a altor aplicaţii, deoarece acestea trebuie să îşi recupereze datele."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"mutare resurse aplicaţii"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Permite aplicaţiei să mute resursele aplicaţiei de pe suporturile fizice interne pe cele externe şi invers."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"citire date de jurnal problematice"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Permite aplicaţiei să acceseze comenzi suplimentare pentru furnizorul locaţiei. Aplicaţia ar putea să utilizeze această permisiune pentru a influenţa operaţiile GPS sau ale altor surse de locaţii."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"permisiune pentru instalarea unui furnizor de locaţii"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Creează surse de locaţii pentru testare sau instalează un furnizor de locaţie nou. Acest lucru permite aplicaţiei să înlocuiască locaţia şi/sau starea returnate de alte surse de locaţii, cum ar fi GPS sau furnizorii de locaţii."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"locaţie exactă (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Accesează de pe tabletă surse de locaţii exacte, cum ar fi cele ale sistemului Global Positioning System. Atunci când serviciile de localizare sunt disponibile şi activate, cu această permisiune aplicaţia poate determina locaţia dvs. exactă."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Accesează de pe telefon surse de locaţii exacte, cum ar fi cele ale sistemului Global Positioning System. Atunci când serviciile de localizare sunt disponibile şi activate, cu această permisiune aplicaţia poate determina locaţia dvs. exactă."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"locaţie aproximativă (bazată pe reţea)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Accesează locaţia aproximativă de la furnizorii de locaţie utilizând surse de reţea cum ar fi cele prin turn de celule şi Wi-Fi. Atunci când aceste servicii de localizare sunt disponibile şi activate, cu această permisiune aplicaţia poate determina locaţia dvs. aproximativă."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"locaţia exactă (bazată pe reţea şi GPS)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Permite aplicaţiei să obţină locaţia dvs. exactă utilizând sistemul GPS (Global Positioning System) sau surse de localizare prin reţele, cum ar fi cele prin turn de celule şi Wi-Fi. Pentru a fi utilizate de aplicaţie, aceste servicii de localizare trebuie să fie activate şi disponibile pe dispozitivul dvs. Aplicaţiile pot utiliza această permisiune pentru a determina locaţia dvs. şi pot să consume mai multă energie a bateriei."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"locaţia aproximativă (bazată pe reţea)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Permite aplicaţiei să obţină locaţia dvs. aproximativă. Această locaţie este dedusă de serviciile de localizare utilizând surse de localizare prin reţele, cum ar fi cele prin turn de celule şi Wi-Fi. Pentru a fi utilizate de aplicaţie, aceste servicii de localizare trebuie să fie activate şi disponibile pe dispozitivul dvs. Aplicaţiile pot utiliza această permisiune pentru a determina locaţia dvs. aproximativă."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"accesare SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Permite aplicaţiei să utilizeze funcţiile de nivel redus SurfaceFlinger."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"citire zonă tampon de cadre"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Permite aplicaţiei să citească conţinutul zonei-tampon a cadrului."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"configurează afişaje Wi-Fi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permite aplicaţiei să configureze şi să se conecteze la afişaje Wi-Fi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controlează afişaje Wi-Fi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permite aplicaţiei să controleze funcţiile de nivel redus ale afişajelor Wi-Fi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modificare setări audio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite aplicaţiei să modifice setările audio globale, cum ar fi volumul şi difuzorul care este utilizat pentru ieşire."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"înregistrare audio"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"accesează setările Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Permite aplicaţiei să configureze tableta Bluetooth locală, să descopere şi să se împerecheze cu dispozitive la distanţă."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permite aplicaţiei să configureze telefonul Bluetooth local, să descopere şi să se împerecheze cu dispozitive la distanţă."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Afişaţi conexiunile WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"se conectează şi se deconectează de la WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permite aplicaţiei să stabilească dacă o reţea WiMAX este activată şi să vadă informaţiile cu privire la toate reţelele WiMAX conectate."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Schimbaţi starea WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite aplicaţiei să conecteze şi să deconecteze tableta la şi de la reţelele WiMAX."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Permite aplicaţiei să modifice fluxurile sincronizate curent. Aplicaţiile rău intenţionate pot să modifice fluxurile sincronizate."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"citeşte termenii adăugaţi în dicţionar"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Permite aplicaţiei să citească toate cuvintele, numele şi expresiile stocate în dicţionarul utilizatorului."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"scriere în dicţionarul definit de utilizator"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"adaugă cuvinte în dicţionarul definit de utilizator"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Permite aplicaţiei să scrie cuvinte noi în dicţionarul utilizatorului."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"testează accesul la stocarea protejată"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"testează accesul la stocarea protejată"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Permite aplic. să testeze o permis. pt. stoc. USB care va fi dispon. pe dispozit. viitoare."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Permite aplicaţiei testarea permisiunii pt. stocarea USB, disponibilă pe gadgeturi viitoare."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Permite aplicaţiei să testeze o permisiune pentru cardul SD care va fi disponibil pe dispozitivele viitoare."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modifică sau şterge conţinutul stocării USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modifică sau şterge conţinutul cardului SD"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Permite aplicaţiei să scrie pe cardul SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"modif./şterg. conţinutul media stocat intern"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Permite aplicaţiei să modifice conţinutul stocării media interne."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"acces. stoc. ext. pt. toţi utilizat."</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Permite aplicaţiei să acceseze stocarea externă pentru toţi utilizatorii."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"accesare sistem de fişiere cache"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite aplicaţiei să scrie şi să citească sistemul de fişiere cache."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"efectuare/primire apeluri prin internet"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Necesită ca datele aplicaţiei stocate să fie criptate."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Dezactivaţi camerele foto"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Împiedicaţi utilizarea camerelor foto de pe dispozitiv."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Dezactiv. funcții după blocare"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Previne utilizarea unora dintre funcții când tastatura este blocată."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domiciliu"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Încercaţi din nou"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"S-a depăşit numărul maxim de încercări pentru Deblocare facială"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Se încarcă, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Încărcată."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Încărcată"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conectaţi încărcătorul."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Niciun card SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Niciun card SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nu există card SIM în computerul tablet PC."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefonul nu are card SIM."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Introduceţi un card SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Modelul a fost şters"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Celulă adăugată"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Modelul a fost desenat"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Adăugaţi un widget."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Gol"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Zona de deblocare a fost extinsă."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Zona de deblocare a fost restrânsă."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Selector utilizator"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Stare"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Cameră foto"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Comenzi media"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"A început reordonarea widgeturilor."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Reordonarea widgeturilor s-a încheiat."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widgetul <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> a fost eliminat."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Extindeţi zona de deblocare."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Deblocare prin glisare."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Deblocare cu model."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Deblocare facială."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Deblocare cu PIN."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Deblocare cu parolă."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zonă model."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zonă glisare."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Copiaţi adresa URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Selectaţi text"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selectare text"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"adăugaţi în dicţionar"</string>
-    <string name="deleteText" msgid="7070985395199629156">"ştergeţi"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Adăugaţi în dicţionar"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Ştergeţi"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metodă de intrare"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acţiuni pentru text"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Spaţiul de stocare aproape ocupat"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Reţele Wi-Fi deschise disponibile"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Conectaţi-vă în reţeaua Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Conectaţi-vă la reţea"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nu se poate conecta la Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" are o conexiune la internet slabă."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Către:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Introduceţi codul PIN necesar:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Cod PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefonul se va deconecta temporar de la reţeaua Wi-Fi cât timp este conectat la <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Introduceţi caracterul"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Se trimit mesaje SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; trimite un număr mare de mesaje SMS. Permiteţi acestei aplicaţii să trimită în continuare mesaje?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Permiteţi"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Refuzaţi"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; intenţionează să trimită un mesaj la &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Aceasta "<font fgcolor="#ffffb060">"poate genera costuri"</font>" în contul dvs. mobil."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Aceasta va genera costuri în contul dvs. mobil."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Trimiteţi"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Anulaţi"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Doresc să se reţină opţiunea"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Puteţi modifica ulterior în Setări &gt; Aplicaţii"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Permiteţi întotdeauna"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nu permiteţi niciodată"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Card SIM eliminat"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Reţeaua mobilă va fi indisponibilă până când reporniţi cu o cartelă SIM validă introdusă."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Terminat"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setaţi data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Setaţi"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Terminat"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Prestabilit"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Nu se solicită nicio permisiune"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Ascundeţi"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Afişaţi-le pe toate"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NOU: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NOU: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Furnizată de <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Nu se solicită nicio permisiune"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"aceasta poate să genereze costuri"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Stocare masivă USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB conectat"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"V-aţi conectat la computer prin USB. Atingeţi butonul de mai jos dacă doriţi să copiaţi fişiere de pe computer pe stocarea USB Android sau invers."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN este activată de <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Atingeţi pentru a gestiona reţeaua."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Conectat la <xliff:g id="SESSION">%s</xliff:g>. Atingeţi pentru a gestiona reţeaua."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Se efectuează conectarea la reţeaua VPN activată permanent…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Conectat(ă) la reţeaua VPN activată permanent"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Eroare de reţea VPN activată permanent"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Atingeţi pentru a reseta conexiunea"</string>
     <string name="upload_file" msgid="2897957172366730416">"Alegeţi un fişier"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nu au fost găsite fişiere"</string>
     <string name="reset" msgid="2448168080964209908">"Resetaţi"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Distribuiţi"</string>
     <string name="find" msgid="4808270900322985960">"Găsiţi"</string>
     <string name="websearch" msgid="4337157977400211589">"Căutare pe web"</string>
+    <string name="find_next" msgid="5742124618942193978">"Următorul rezultat"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Rezultatul anterior"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Solicitare de locaţie de la <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Solicitare de locaţie"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Solicitat de <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Căşti"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Difuz. dispozit. andocare"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Ieşire audio HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Terminat"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Rezultate media"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Se scanează..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Se conectează..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Disponibilă"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Indisponibilă"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Ecran încorporat"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Ecran HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Suprapunerea <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Ecranul wireless este conectat"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Acest ecran este afişat pe alt gadget"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Deconectaţi-vă"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Apel de urgenţă"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Model uitat"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Model greşit"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Parolă greşită"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Cod PIN greşit"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Încercaţi din nou peste <xliff:g id="NUMBER">%d</xliff:g> (de) secunde."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Desenaţi modelul"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Introduceţi codul PIN al cardului SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Introduceţi codul PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Introduceţi parola"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"Cardul SIM este acum dezactivat. Introduceţi codul PUK pentru a continua. Contactaţi operatorul pentru mai multe detalii."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Introduceţi codul PIN dorit"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Confirmaţi codul PIN dorit"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Se deblochează cardul SIM..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Cod PIN incorect."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Introduceţi un cod PIN format din 4 până la 8 cifre."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Codul PUK trebuie să aibă minimum 8 cifre."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Reintroduceţi codul PUK corect. Încercările repetate vor dezactiva definitiv cardul SIM."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Codurile PIN nu coincid"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Prea multe încercări de desenare a modelului"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Pentru a debloca, conectaţi-vă cu Contul dvs. Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Nume de utilizator (e-mail)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Parolă"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Conectaţi-vă"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Nume de utilizator sau parolă nevalide."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Aţi uitat numele de utilizator sau parola?"\n"Accesaţi "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Se verifică contul…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Aţi introdus incorect codul PIN de <xliff:g id="NUMBER_0">%d</xliff:g> ori."\n\n"Încercaţi din nou peste <xliff:g id="NUMBER_1">%d</xliff:g> (de) secunde."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Aţi introdus incorect parola de <xliff:g id="NUMBER_0">%d</xliff:g> ori. "\n\n"Încercaţi din nou peste <xliff:g id="NUMBER_1">%d</xliff:g> (de) secunde."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%d</xliff:g> ori. "\n\n"Încercaţi din nou peste <xliff:g id="NUMBER_1">%d</xliff:g> (de) secunde."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Aţi efectuat <xliff:g id="NUMBER_0">%d</xliff:g> încercări incorecte de deblocare a tabletei. După încă <xliff:g id="NUMBER_1">%d</xliff:g> încercări nereuşite, aceasta va fi resetată la setările prestabilite din fabrică, iar toate datele de utilizator se vor pierde."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Aţi efectuat <xliff:g id="NUMBER_0">%d</xliff:g> încercări incorecte de deblocare a telefonului. După încă <xliff:g id="NUMBER_1">%d</xliff:g> încercări nereuşite, acesta va fi resetat la setările prestabilite din fabrică, iar toate datele de utilizator se vor pierde."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Aţi efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a tabletei. Tableta va fi acum resetată la setările prestabilite din fabrică."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Aţi efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a telefonului. Telefonul va fi acum resetat la setările prestabilite din fabrică."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%d</xliff:g> încercări nereuşite, vi se va solicita să deblocaţi tableta cu ajutorul unui cont de e-mail."\n\n" Încercaţi din nou peste <xliff:g id="NUMBER_2">%d</xliff:g> (de) secunde."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%d</xliff:g> încercări nereuşite, vi se va solicita să deblocaţi telefonul cu ajutorul unui cont de e-mail."\n\n" Încercaţi din nou peste <xliff:g id="NUMBER_2">%d</xliff:g> (de) secunde."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Eliminaţi"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Ridicaţi volumul mai sus de nivelul sigur?"\n"Ascultarea la volum ridicat pe perioade lungi de timp vă poate afecta auzul."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Menţineţi două degete pe ecran pentru a activa accesibilitatea."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"S-a activat accesibilitatea."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Accesibilitatea a fost anulată"</string>
+    <string name="user_switched" msgid="3768006783166984410">"Utilizator curent: <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Proprietar"</string>
 </resources>
diff --git a/core/res/res/values-ru/donottranslate-cldr.xml b/core/res/res/values-ru/donottranslate-cldr.xml
index 2fbcd43..03c64ab 100644
--- a/core/res/res/values-ru/donottranslate-cldr.xml
+++ b/core/res/res/values-ru/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">январь</string>
-    <string name="month_long_standalone_february">февраль</string>
-    <string name="month_long_standalone_march">март</string>
-    <string name="month_long_standalone_april">апрель</string>
-    <string name="month_long_standalone_may">май</string>
-    <string name="month_long_standalone_june">июнь</string>
-    <string name="month_long_standalone_july">июль</string>
-    <string name="month_long_standalone_august">август</string>
-    <string name="month_long_standalone_september">сентябрь</string>
-    <string name="month_long_standalone_october">октябрь</string>
-    <string name="month_long_standalone_november">ноябрь</string>
-    <string name="month_long_standalone_december">декабрь</string>
-
-    <string name="month_long_january">января</string>
-    <string name="month_long_february">февраля</string>
-    <string name="month_long_march">марта</string>
-    <string name="month_long_april">апреля</string>
-    <string name="month_long_may">мая</string>
-    <string name="month_long_june">июня</string>
-    <string name="month_long_july">июля</string>
-    <string name="month_long_august">августа</string>
-    <string name="month_long_september">сентября</string>
-    <string name="month_long_october">октября</string>
-    <string name="month_long_november">ноября</string>
-    <string name="month_long_december">декабря</string>
-
-    <string name="month_medium_january">янв</string>
-    <string name="month_medium_february">фев</string>
-    <string name="month_medium_march">мар</string>
-    <string name="month_medium_april">апр</string>
-    <string name="month_medium_may">май</string>
-    <string name="month_medium_june">июн</string>
-    <string name="month_medium_july">июл</string>
-    <string name="month_medium_august">авг</string>
-    <string name="month_medium_september">сен</string>
-    <string name="month_medium_october">окт</string>
-    <string name="month_medium_november">ноя</string>
-    <string name="month_medium_december">дек</string>
-
-    <string name="month_shortest_january">Я</string>
-    <string name="month_shortest_february">Ф</string>
-    <string name="month_shortest_march">М</string>
-    <string name="month_shortest_april">А</string>
-    <string name="month_shortest_may">М</string>
-    <string name="month_shortest_june">И</string>
-    <string name="month_shortest_july">И</string>
-    <string name="month_shortest_august">А</string>
-    <string name="month_shortest_september">С</string>
-    <string name="month_shortest_october">О</string>
-    <string name="month_shortest_november">Н</string>
-    <string name="month_shortest_december">Д</string>
-
-    <string name="day_of_week_long_sunday">воскресенье</string>
-    <string name="day_of_week_long_monday">понедельник</string>
-    <string name="day_of_week_long_tuesday">вторник</string>
-    <string name="day_of_week_long_wednesday">среда</string>
-    <string name="day_of_week_long_thursday">четверг</string>
-    <string name="day_of_week_long_friday">пятница</string>
-    <string name="day_of_week_long_saturday">суббота</string>
-
-    <string name="day_of_week_medium_sunday">вс</string>
-    <string name="day_of_week_medium_monday">пн</string>
-    <string name="day_of_week_medium_tuesday">вт</string>
-    <string name="day_of_week_medium_wednesday">ср</string>
-    <string name="day_of_week_medium_thursday">чт</string>
-    <string name="day_of_week_medium_friday">пт</string>
-    <string name="day_of_week_medium_saturday">сб</string>
-
-    <string name="day_of_week_short_sunday">вс</string>
-    <string name="day_of_week_short_monday">пн</string>
-    <string name="day_of_week_short_tuesday">вт</string>
-    <string name="day_of_week_short_wednesday">ср</string>
-    <string name="day_of_week_short_thursday">чт</string>
-    <string name="day_of_week_short_friday">пт</string>
-    <string name="day_of_week_short_saturday">сб</string>
-
-    <string name="day_of_week_shortest_sunday">В</string>
-    <string name="day_of_week_shortest_monday">П</string>
-    <string name="day_of_week_shortest_tuesday">В</string>
-    <string name="day_of_week_shortest_wednesday">С</string>
-    <string name="day_of_week_shortest_thursday">Ч</string>
-    <string name="day_of_week_shortest_friday">П</string>
-    <string name="day_of_week_shortest_saturday">С</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Вчера</string>
-    <string name="today">Сегодня</string>
-    <string name="tomorrow">Завтра</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index ea69d45..42e5f86 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -149,11 +149,14 @@
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Переход в безопасный режим"</string>
     <string name="reboot_safemode_confirm" msgid="55293944502784668">"Перейти в безопасный режим? Все приложения сторонних поставщиков отключатся. Они будут включены по возвращении в обычный режим."</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>
     <string name="global_action_power_off" msgid="4471879440839879722">"Отключить питание"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Отчет об ошибке"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Создание отчета об ошибке"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Информация о текущем состоянии вашего устройства будет собрана и отправлена по электронной почте. Подготовка отчета займет некоторое время."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Режим без звука"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Выключить"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Включить"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Сообщения"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Чтение и запись SMS, электронных писем и других сообщений."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Личная информация"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Прямой доступ к контактам и событиям календаря, сохраненным в памяти планшетного ПК."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Прямой доступ к контактам и событиям календаря, сохраненным в памяти телефона."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Прямой доступ к моим контактным данным."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Информация о моих социальных контактах"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Прямой доступ к информации о моих контактах и социальных связях."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Ваше местоположение"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Приложение сможет отслеживать ваше местоположение."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Сетевой обмен данными"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Приложение сможет получать доступ к различным сетевым функциям."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Доступ к устройствам и сетям через Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Настройки звука"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Изменение настроек звука."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Воздействие на батарею"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Использование функций, приводящих к быстрой разрядке батареи."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Календарь"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Прямой доступ к календарю и мероприятиям."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Чтение данных из пользовательского словаря"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Чтение слов в пользовательском словаре."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Запись данных в пользовательский словарь"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Добавление слов в пользовательский словарь."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Закладки и история"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Прямой доступ к закладкам и истории браузера."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Будильник"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Настройка будильника."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Голосовая почта"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Прямой доступ к голосовой почте."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Микрофон"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Прямой доступ к микрофону для записи звука."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Камера"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Прямой доступ к камере для фото- и видеосъемки."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Информация о приложениях"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Возможность влиять на поведение других приложений на устройстве."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Обои"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Изменение настроек обоев на устройстве."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Часы"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Изменение времени или часового пояса на устройстве."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Строка состояния"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Изменение настроек строки состояния для устройства."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Настройки синхронизации"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Доступ к настройкам синхронизации."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Ваши аккаунты"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Доступ к имеющимся аккаунтам."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Управление оборудованием"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Доступ нижнего уровня и управление системой."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Инструменты разработки"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Функции, предназначенные для разработчиков приложений."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Интерфейс других приложений"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Воздействие на интерфейс других приложений."</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>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Приложение сможет получать и обрабатывать WAP-сообщения. Это значит, что оно сможет отслеживать и удалять отправленные на ваше устройство сообщения, не показывая их."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"Получение данных о запущенных приложениях"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Приложение сможет получать информацию о недавно запущенных и выполняемых задачах, а следовательно, и о приложениях, используемых на устройстве."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"разрешить взаимодействие со всеми аккаунтами"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Приложение сможет выполнять действия во всех аккаунтах на этом устройстве. При этом защита от вредоносных приложений может быть недостаточной."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"разрешить полное взаимодействие со всеми аккаунтами"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Приложение сможет выполнять любые действия во всех аккаунтах на этом устройстве."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"Управлять аккаунтами"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Приложения смогут управлять аккаунтами на этом устройстве (выполнять поиск, создавать и удалять их)"</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"получение сведений о работающих приложениях"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Приложение сможет получать подробные сведения о недавно запущенных и выполняемых задачах. При этом конфиденциальная информация о других приложениях не будет защищена от вредоносных программ."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"Упорядочивание запущенных приложений"</string>
@@ -243,6 +287,14 @@
     <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="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Включение специальных возможностей"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Приложение сможет временно включать на устройстве специальные возможности. Вредоносные приложения смогут включать их без вашего ведома."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"доступ к информации в окне"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Открывает приложению доступ к информации из диспетчера окон. Обратите внимание, что вредоносное ПО может получить доступ к некоторой системной информации устройства."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"Фильтрация событий"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Разрешает приложению зарегистрировать входной фильтр, который анализирует весь поток пользовательских событий. Обратите внимание, что вредоносное ПО может получить доступ к управлению интерфейсом без ведома пользователя."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"увеличивать изображение"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Приложение сможет увеличивать содержимое экрана. Вредоносные программы смогут изменять изображение таким образом, что устройством нельзя будет пользоваться."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"частичное завершение работы"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Завершает работу диспетчера активности. Не выполняет полное завершение работы."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"запретить переключение приложений"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Приложение сможет управлять максимальным количеством процессов, которые могут быть запущены. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"Закрытие фоновых приложений"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Приложение сможет управлять завершением процессов после их перехода в фоновый режим. Это разрешение не используется обычными приложениями."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"Изменение данных об использовании батареи"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Приложение сможет изменять собранную статистику использования заряда батареи. Это разрешение не используется обычными приложениями."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"считывать статистики батареи"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Разрешает приложению получать данные об использовании батареи на низшем уровне. В результате оно может иметь доступ к информации об используемых вами программах."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"изменять статистику батареи"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Приложение сможет изменять собранную статистику использования заряда батареи. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_backup" msgid="470013022865453920">"управление резервным копированием и восстановлением системы"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Приложение сможет управлять механизмами резервного копирования и восстановления системы. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"подтверждать полное резервное копирование или восстановление"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"показывать неавторизованные окна"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Приложение сможет создавать окна для интерфейса внутренней системы. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"Показ сообщений поверх других окон"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Приложение сможет показывать системные предупреждения. Некоторые из них могут перехватить управление всем экраном."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Разрешает приложению отображать элементы своего интерфейса поверх окон других программ. Это может мешать вашему взаимодействию с другими приложениями и вести к недоразумениям."</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="permlab_freezeScreen" msgid="4708181184441880175">"замораживать изображение"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Приложение сможет приостанавливать изображение на время перехода в полноэкранный режим."</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>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"непосредственная установка приложений"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Приложение сможет устанавливать новые или обновленные пакеты Android. Вредоносные программы смогут таким образом добавлять новые программы с любыми разрешениями."</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="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Разрешает приложению освобождать место на планшетном ПК, удаляя кэшированные файлы других программ. В результате другие приложения могут запускаться медленнее, так как им потребуется повторно извлекать необходимые данные."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Разрешает приложению освобождать место на телефоне, удаляя кэшированные файлы других программ. В результате другие приложения могут запускаться медленнее, так как им потребуется повторно извлекать необходимые данные."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"перемещение ресурсов приложения"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Приложение сможет перемещать ресурсы из внутреннего накопителя на внешний и наоборот."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"Просмотр конфиденциальных данных в журнале"</string>
@@ -370,21 +426,24 @@
     <string name="permlab_writeCalendar" msgid="8438874755193825647">"Добавление/изменение мероприятий и отправление гостям эл. сообщений без предупреждения владельца календаря"</string>
     <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"Приложение сможет добавлять, удалять и изменять мероприятия, доступные для редактирования на вашем планшетном ПК, включая мероприятия, добавленные другими людьми. Так приложение сможет рассылать сообщения от имени владельца календаря и изменять мероприятия без его ведома."</string>
     <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Приложение сможет добавлять, удалять и изменять мероприятия, доступные для редактирования на вашем телефоне, включая мероприятия, добавленные другими людьми. Так приложение сможет рассылать сообщения от имени владельца календаря и изменять мероприятия без его ведома."</string>
-    <string name="permlab_accessMockLocation" msgid="8688334974036823330">"копировать источники мест для проверки"</string>
+    <string name="permlab_accessMockLocation" msgid="8688334974036823330">"Установка фиктивного местоположения для отладки"</string>
     <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Приложение сможет создавать фиктивные местоположения для тестирования или установки нового источника геоданных и переопределять местоположение и/или статус, возвращаемые другими источниками, такими как система GPS."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"получать доступ к дополнительным командам источника данных о местоположении"</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Приложение получит доступ к дополнительным командам управления источниками геоданных и сможет вмешиваться в работу системы GPS или других источников геоданных."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"разрешение на установку поставщика местоположения"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Приложение сможет создавать фиктивные местоположения для тестирования или установки нового источника геоданных и переопределять местоположение и/или статус, возвращаемые другими источниками, такими как система GPS или службы геопозиционирования."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"Определение точного местоположения (по спутникам GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Приложение сможет определять ваше точное местоположение, используя данные со спутников GPS. Для этого в настройках устройства должна быть включена соответствующая функция."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Приложение сможет определять ваше точное местоположение, используя данные со спутников GPS. Для этого в настройках устройства должна быть включена соответствующая функция."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"Определение примерного местоположения (по координатам сети)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Приложение сможет определять ваше примерное местоположение, используя различные источники геоданных (например, по координатам мобильной сети и точек доступа Wi-Fi). Для этого в настройках устройства должна быть включена соответствующая функция."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"точное местоположение (на основе сети и сигналов GPS)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Разрешает приложению получать данные о вашем точном местоположении с помощью глобального позиционирования (GPS), вышек сотовой связи и точек доступа Wi-Fi. Эти службы должны быть включены на устройстве, а приложению должно быть разрешено их использовать. Это может вести к дополнительному расходу заряда батареи."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"примерное местоположение (на основе сети)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Разрешает приложению получать данные о вашем примерном местоположении с помощью служб определения местоположения, вышек сотовой связи и точек доступа Wi-Fi. Эти службы должны быть включены на устройстве, а приложению должно быть разрешено их использовать."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"получать доступ к 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="permlab_configureWifiDisplay" msgid="5595661694746742168">"настраивать экраны, подключенные через Wi-Fi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Приложение сможет подключаться к экранам с помощью Wi-Fi и настраивать их."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"управлять экранами, подключенными через Wi-Fi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Приложение сможет управлять низкоуровневыми функциями экранов, подключенных через Wi-Fi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"Изменение настроек аудио"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Приложение сможет изменять системные настройки звука, например уровень громкости и активный динамик."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"Запись аудио"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"Доступ к настройкам Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Приложение сможет настраивать параметры локального планшетного ПК с поддержкой Bluetooth, а также обнаруживать удаленные устройства и выполнять сопряжение с ними."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Приложение сможет настраивать параметры локального телефона с поддержкой Bluetooth, а также обнаруживать удаленные устройства и выполнять сопряжение с ними."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Просмотр подключений WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"подключать/отключать сеть WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Приложение сможет определять, активирован ли WiMAX, а также получать информацию о подключенных сетях WiMAX."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Изменение статуса WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Приложение сможет подключать устройство к сетям WiMAX и отключать его от них."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Приложение сможет изменять фиды, синхронизируемые в настоящее время. Вредоносные программы смогут изменять синхронизированные фиды."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"Просмотр добавленных в словарь слов"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Приложение получит доступ ко всем словам и фразам, которые хранятся в пользовательском словаре."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"Добавление данных в словарь пользователя"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"добавлять слова в пользовательский словарь"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Приложение сможет добавлять слова в пользовательский словарь."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"Проверка доступа к защищенному хранилищу"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"Проверка доступа к защищенному хранилищу"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Приложение сможет проверять разрешение для USB-накопителя, которое в дальнейшем будет предоставляться на других устройствах."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Приложение сможет проверять разрешение для USB-накопителя, которое в дальнейшем будет предоставляться на других устройствах."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Приложение сможет проверять разрешение для SD-карты, которое в дальнейшем будет предоставляться на других устройствах."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"Изменение/удаление данных на USB-накопителе"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"Изменение или удаление содержимого SD-карты"</string>
@@ -534,6 +593,8 @@
     <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="permlab_sdcardAccessAll" msgid="8150613823900460576">"разрешить доступ к внешним накопителям из всех аккаунтов"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Приложение сможет обращаться к внешним накопителям из всех аккаунтов."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"получать доступ к кэшу файловой системы"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Приложение сможет выполнять чтение и запись в файловую систему кэша."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"Осуществление/прием интернет-вызовов"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Шифровать данные приложений в хранилище."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Отключить камеры"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Запретить использование камер на устройстве."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Отключить функции блокировки"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Запретить использование некоторых функций блокировки клавиатуры."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Домашний"</item>
     <item msgid="869923650527136615">"Мобильный"</item>
@@ -687,7 +750,7 @@
     <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Неверный PIN-код."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Для разблокировки нажмите \"Меню\", а затем 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Экстренная служба"</string>
-    <string name="lockscreen_carrier_default" msgid="8963839242565653192">"Сеть не найдена."</string>
+    <string name="lockscreen_carrier_default" msgid="8963839242565653192">"Сеть не найдена"</string>
     <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Экран заблокирован."</string>
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Нажмите \"Меню\", чтобы разблокировать экран или вызвать службу экстренной помощи."</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Для разблокировки нажмите \"Меню\"."</string>
@@ -695,14 +758,14 @@
     <string name="lockscreen_emergency_call" msgid="5347633784401285225">"Экстренный вызов"</string>
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Вернуться к вызову"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Правильно!"</string>
-    <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Повторить попытку"</string>
+    <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Повторите попытку"</string>
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Повторить попытку"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Все попытки войти с помощью Фейсконтроля использованы"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Идет зарядка (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Батарея заряжена"</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Заряжено"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Подключите зарядное устройство"</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Нет SIM-карты"</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Нет SIM-карты"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"SIM-карта не установлена."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"SIM-карта не установлена."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Вставьте SIM-карту."</string>
@@ -725,10 +788,10 @@
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"Вы <xliff:g id="NUMBER_0">%d</xliff:g> раз неверно указали PIN-код. "\n\n"Повтор через <xliff:g id="NUMBER_1">%d</xliff:g> сек."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Вы <xliff:g id="NUMBER_0">%d</xliff:g> раз неверно указали графический ключ. После <xliff:g id="NUMBER_1">%d</xliff:g> неверных попыток для разблокировки планшетного ПК потребуется войти в аккаунт Google. "\n\n" Повтор через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"Вы <xliff:g id="NUMBER_0">%d</xliff:g> раз неверно указали графический ключ. После <xliff:g id="NUMBER_1">%d</xliff:g> неверных попыток для разблокировки телефона потребуется войти в аккаунт Google. "\n\n" Повтор через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
-    <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Не удалось разблокировать планшетный ПК (число попыток: <xliff:g id="NUMBER_0">%d</xliff:g>). Осталось попыток: <xliff:g id="NUMBER_1">%d</xliff:g>. После этого будут установлены настройки по умолчанию, что приведет к удалению всех пользовательских данных."</string>
-    <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Не удалось разблокировать телефон (число попыток: <xliff:g id="NUMBER_0">%d</xliff:g>). Осталось попыток: <xliff:g id="NUMBER_1">%d</xliff:g>. После этого будут установлены настройки по умолчанию, что приведет к удалению всех пользовательских данных."</string>
-    <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Не удалось разблокировать планшетный ПК (число попыток: <xliff:g id="NUMBER">%d</xliff:g>). Будут установлены настройки по умолчанию."</string>
-    <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Не удалось разблокировать телефон (число попыток: <xliff:g id="NUMBER">%d</xliff:g>). Будут установлены настройки по умолчанию."</string>
+    <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Вы <xliff:g id="NUMBER_0">%d</xliff:g> раз не смогли разблокировать планшетный ПК. После <xliff:g id="NUMBER_1">%d</xliff:g> неверных попыток будут восстановлены заводские настройки, что приведет к удалению всех пользовательских данных."</string>
+    <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Вы <xliff:g id="NUMBER_0">%d</xliff:g> раз не смогли разблокировать телефон. После <xliff:g id="NUMBER_1">%d</xliff:g> неверных попыток будут восстановлены заводские настройки, что приведет к удалению всех пользовательских данных."</string>
+    <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Вы <xliff:g id="NUMBER">%d</xliff:g> раз не смогли разблокировать планшетный ПК. Будут восстановлены заводские настройки."</string>
+    <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Вы <xliff:g id="NUMBER">%d</xliff:g> раз не смогли разблокировать телефон. Будут восстановлены заводские настройки."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Повторите попытку через <xliff:g id="NUMBER">%d</xliff:g> с."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Забыли графический ключ?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Снятие блокировки аккаунта"</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Графический ключ сброшен"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Ячейка добавлена"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Графический ключ введен"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Добавить виджет"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Пусто"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Область разблокировки развернута"</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Область разблокировки свернута"</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Виджет \"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>\""</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Выбор аккаунта"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Статус"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Камера"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Управление блокировкой"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Начато переопределение порядка виджетов"</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Порядок виджетов определен"</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Виджет <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> удален"</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Развернуть области разблокировки"</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Прокрутка"</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Графический ключ"</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Фейсконтроль"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-код"</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Пароль"</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Область ввода графического ключа"</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Область прокрутки"</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"АБВ"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Копировать URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Выбрать текст"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Выбор текста"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"добавить в словарь"</string>
-    <string name="deleteText" msgid="7070985395199629156">"удалить"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Добавить в словарь"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Удалить"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Способ ввода"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Операции с текстом"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Заканчивается свободное место"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Найдены доступные сети Wi-Fi"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Подключение к Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Войдите в сеть"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не удалось подключиться к сети Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" – плохое интернет-соединение."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Кому:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Введите PIN-код:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-код:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"При подключении к устройству <xliff:g id="DEVICE_NAME">%1$s</xliff:g> телефон будет временно отключаться от сети Wi-Fi"</string>
     <string name="select_character" msgid="3365550120617701745">"Введите символ"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Отправка SMS-сообщений"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; отправляет большое количество SMS. Разрешить приложению и дальше отправлять сообщения?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Разрешить"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Запретить"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"Приложение &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; собирается отправить сообщение на адрес &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"С вашего мобильного счета "<font fgcolor="#ffffb060">"могут быть списаны средства"</font>"."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"С вашего мобильного счета будут списаны средства."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Отправить"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Отмена"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Запомнить выбранный телефон"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Это можно изменить позже в разделе настроек \"Приложения\"."</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Всегда разрешать"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Не разрешать"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-карта удалена"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Пока вы не вставите действующую SIM-карту, мобильная сеть будет недоступна."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Настройка даты"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Установить"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Готово"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"По умолчанию"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Не требуется разрешений"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Скрыть"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Показать все"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"НОВОЕ: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"НОВОЕ: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Источник: <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Не требуется разрешений"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"за это может взиматься плата"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Запоминающее устройство USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB-подключение установлено"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Устройство подключено к компьютеру через USB-порт. Нажмите кнопку ниже, чтобы скопировать файлы с компьютера на USB-накопитель Android-устройства."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"Сеть VPN активирована приложением <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Нажмите, чтобы открыть настройки."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Сеть VPN подключена: <xliff:g id="SESSION">%s</xliff:g>. Нажмите, чтобы открыть настройки."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Подключение…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Подключено"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Ошибка"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Нажмите, чтобы сбросить соединение"</string>
     <string name="upload_file" msgid="2897957172366730416">"Выбрать файл"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Не выбран файл"</string>
     <string name="reset" msgid="2448168080964209908">"Сбросить"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Отправить"</string>
     <string name="find" msgid="4808270900322985960">"Найти"</string>
     <string name="websearch" msgid="4337157977400211589">"Веб-поиск"</string>
+    <string name="find_next" msgid="5742124618942193978">"Cлед."</string>
+    <string name="find_previous" msgid="2196723669388360506">"Пред."</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Пользователь <xliff:g id="NAME">%s</xliff:g> запрашивает ваше местоположение"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Запрос местоположения"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Запрашивает <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Телефон"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Наушники"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Динамики док-станции"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-аудио"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Система"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Воспроизведение звука через Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Готово"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Перенаправлять поток мультимедиа"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Сканирование..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Подключение..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Доступен"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Недоступные"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Встроенный экран"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Экран HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Наложение № <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> х <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> тчк/дюйм"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Беспроводной проектор подключен"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Изображение передается на другое устройство"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Отключить"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Экстренный вызов"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Забыли графический ключ?"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Неправильный графический ключ"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Неправильный пароль"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Неправильный PIN-код"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Повторите попытку через <xliff:g id="NUMBER">%d</xliff:g> сек."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Введите графический ключ"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Введите PIN-код SIM-карты"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Введите PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Введите пароль"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM-карта заблокирована. Чтобы продолжить, введите PUK-код. За подробной информацией обратитесь к своему оператору связи."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Введите желаемый PIN-код"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Введите PIN-код ещё раз"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Разблокировка SIM-карты…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Неверный PIN-код."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Введите PIN-код (от 4 до 8 цифр)."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK-код должен содержать не менее 8 символов."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Введите правильный PUK-код. После нескольких неудачных попыток SIM-карта будет заблокирована."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN-коды не совпадают"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Слишком много попыток ввода графического ключа"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Чтобы разблокировать устройство, войдите в свой аккаунт Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Имя пользователя (эл. почта)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Пароль"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Войти"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Неверное имя пользователя или пароль."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Забыли имя пользователя или пароль?"\n"Перейдите на страницу "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Проверка данных…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Вы <xliff:g id="NUMBER_0">%d</xliff:g> раз неверно указали PIN-код. "\n\n"Повтор через <xliff:g id="NUMBER_1">%d</xliff:g> сек."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Вы <xliff:g id="NUMBER_0">%d</xliff:g> раз неверно указали пароль."\n\n"Повтор через <xliff:g id="NUMBER_1">%d</xliff:g> сек."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Вы <xliff:g id="NUMBER_0">%d</xliff:g> раз неверно указали графический ключ."\n\n"Повтор через <xliff:g id="NUMBER_1">%d</xliff:g> сек."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Вы <xliff:g id="NUMBER_0">%d</xliff:g> раз не смогли разблокировать планшетный ПК. После <xliff:g id="NUMBER_1">%d</xliff:g> неверных попыток будут восстановлены заводские настройки, что приведет к удалению всех пользовательских данных."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Вы <xliff:g id="NUMBER_0">%d</xliff:g> раз не смогли разблокировать телефон. После <xliff:g id="NUMBER_1">%d</xliff:g> неверных попыток будут восстановлены заводские настройки, что приведет к удалению всех пользовательских данных."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Вы <xliff:g id="NUMBER">%d</xliff:g> раз не смогли разблокировать планшетный ПК. Будут восстановлены заводские настройки."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Вы <xliff:g id="NUMBER">%d</xliff:g> раз не смогли разблокировать телефон. Будут восстановлены заводские настройки."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Вы <xliff:g id="NUMBER_0">%d</xliff:g> раз неверно указали графический ключ. После <xliff:g id="NUMBER_1">%d</xliff:g> неверных попыток для разблокировки планшетного ПК потребуется войти в аккаунт Google."\n\n"Повтор через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Вы <xliff:g id="NUMBER_0">%d</xliff:g> раз неверно указали графический ключ. После <xliff:g id="NUMBER_1">%d</xliff:g> неверных попыток для разблокировки телефона потребуется войти в аккаунт Google."\n\n"Повтор через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Удалить"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Увеличить громкость до небезопасного уровня?"\n"Долговременное прослушивание на такой громкости может повредить слух."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Чтобы включить специальные возможности, удерживайте пальцы на экране."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Специальные возможности включены."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Специальные возможности не будут включены."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Выбран аккаунт пользователя <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Владелец"</string>
 </resources>
diff --git a/core/res/res/values-sk-rSK/donottranslate-cldr.xml b/core/res/res/values-sk-rSK/donottranslate-cldr.xml
index 2843ae3..651c58c 100644
--- a/core/res/res/values-sk-rSK/donottranslate-cldr.xml
+++ b/core/res/res/values-sk-rSK/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">január</string>
-    <string name="month_long_standalone_february">február</string>
-    <string name="month_long_standalone_march">marec</string>
-    <string name="month_long_standalone_april">apríl</string>
-    <string name="month_long_standalone_may">máj</string>
-    <string name="month_long_standalone_june">jún</string>
-    <string name="month_long_standalone_july">júl</string>
-    <string name="month_long_standalone_august">august</string>
-    <string name="month_long_standalone_september">september</string>
-    <string name="month_long_standalone_october">október</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">december</string>
-
-    <string name="month_long_january">januára</string>
-    <string name="month_long_february">februára</string>
-    <string name="month_long_march">marca</string>
-    <string name="month_long_april">apríla</string>
-    <string name="month_long_may">mája</string>
-    <string name="month_long_june">júna</string>
-    <string name="month_long_july">júla</string>
-    <string name="month_long_august">augusta</string>
-    <string name="month_long_september">septembra</string>
-    <string name="month_long_october">októbra</string>
-    <string name="month_long_november">novembra</string>
-    <string name="month_long_december">decembra</string>
-
-    <string name="month_medium_january">jan</string>
-    <string name="month_medium_february">feb</string>
-    <string name="month_medium_march">mar</string>
-    <string name="month_medium_april">apr</string>
-    <string name="month_medium_may">máj</string>
-    <string name="month_medium_june">jún</string>
-    <string name="month_medium_july">júl</string>
-    <string name="month_medium_august">aug</string>
-    <string name="month_medium_september">sep</string>
-    <string name="month_medium_october">okt</string>
-    <string name="month_medium_november">nov</string>
-    <string name="month_medium_december">dec</string>
-
-    <string name="month_shortest_january">j</string>
-    <string name="month_shortest_february">f</string>
-    <string name="month_shortest_march">m</string>
-    <string name="month_shortest_april">a</string>
-    <string name="month_shortest_may">m</string>
-    <string name="month_shortest_june">j</string>
-    <string name="month_shortest_july">j</string>
-    <string name="month_shortest_august">a</string>
-    <string name="month_shortest_september">s</string>
-    <string name="month_shortest_october">o</string>
-    <string name="month_shortest_november">n</string>
-    <string name="month_shortest_december">d</string>
-
-    <string name="day_of_week_long_sunday">nedeľa</string>
-    <string name="day_of_week_long_monday">pondelok</string>
-    <string name="day_of_week_long_tuesday">utorok</string>
-    <string name="day_of_week_long_wednesday">streda</string>
-    <string name="day_of_week_long_thursday">štvrtok</string>
-    <string name="day_of_week_long_friday">piatok</string>
-    <string name="day_of_week_long_saturday">sobota</string>
-
-    <string name="day_of_week_medium_sunday">ne</string>
-    <string name="day_of_week_medium_monday">po</string>
-    <string name="day_of_week_medium_tuesday">ut</string>
-    <string name="day_of_week_medium_wednesday">st</string>
-    <string name="day_of_week_medium_thursday">št</string>
-    <string name="day_of_week_medium_friday">pi</string>
-    <string name="day_of_week_medium_saturday">so</string>
-
-    <string name="day_of_week_short_sunday">ne</string>
-    <string name="day_of_week_short_monday">po</string>
-    <string name="day_of_week_short_tuesday">ut</string>
-    <string name="day_of_week_short_wednesday">st</string>
-    <string name="day_of_week_short_thursday">št</string>
-    <string name="day_of_week_short_friday">pi</string>
-    <string name="day_of_week_short_saturday">so</string>
-
-    <string name="day_of_week_shortest_sunday">N</string>
-    <string name="day_of_week_shortest_monday">P</string>
-    <string name="day_of_week_shortest_tuesday">U</string>
-    <string name="day_of_week_shortest_wednesday">S</string>
-    <string name="day_of_week_shortest_thursday">Š</string>
-    <string name="day_of_week_shortest_friday">P</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">dopoludnia</string>
-    <string name="pm">popoludní</string>
-    <string name="yesterday">Včera</string>
-    <string name="today">Dnes</string>
-    <string name="tomorrow">Zajtra</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
diff --git a/core/res/res/values-sk/donottranslate-cldr.xml b/core/res/res/values-sk/donottranslate-cldr.xml
index dcdaad1..48c644a 100644
--- a/core/res/res/values-sk/donottranslate-cldr.xml
+++ b/core/res/res/values-sk/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">január</string>
-    <string name="month_long_standalone_february">február</string>
-    <string name="month_long_standalone_march">marec</string>
-    <string name="month_long_standalone_april">apríl</string>
-    <string name="month_long_standalone_may">máj</string>
-    <string name="month_long_standalone_june">jún</string>
-    <string name="month_long_standalone_july">júl</string>
-    <string name="month_long_standalone_august">august</string>
-    <string name="month_long_standalone_september">september</string>
-    <string name="month_long_standalone_october">október</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">december</string>
-
-    <string name="month_long_january">januára</string>
-    <string name="month_long_february">februára</string>
-    <string name="month_long_march">marca</string>
-    <string name="month_long_april">apríla</string>
-    <string name="month_long_may">mája</string>
-    <string name="month_long_june">júna</string>
-    <string name="month_long_july">júla</string>
-    <string name="month_long_august">augusta</string>
-    <string name="month_long_september">septembra</string>
-    <string name="month_long_october">októbra</string>
-    <string name="month_long_november">novembra</string>
-    <string name="month_long_december">decembra</string>
-
-    <string name="month_medium_january">jan</string>
-    <string name="month_medium_february">feb</string>
-    <string name="month_medium_march">mar</string>
-    <string name="month_medium_april">apr</string>
-    <string name="month_medium_may">máj</string>
-    <string name="month_medium_june">jún</string>
-    <string name="month_medium_july">júl</string>
-    <string name="month_medium_august">aug</string>
-    <string name="month_medium_september">sep</string>
-    <string name="month_medium_october">okt</string>
-    <string name="month_medium_november">nov</string>
-    <string name="month_medium_december">dec</string>
-
-    <string name="month_shortest_january">j</string>
-    <string name="month_shortest_february">f</string>
-    <string name="month_shortest_march">m</string>
-    <string name="month_shortest_april">a</string>
-    <string name="month_shortest_may">m</string>
-    <string name="month_shortest_june">j</string>
-    <string name="month_shortest_july">j</string>
-    <string name="month_shortest_august">a</string>
-    <string name="month_shortest_september">s</string>
-    <string name="month_shortest_october">o</string>
-    <string name="month_shortest_november">n</string>
-    <string name="month_shortest_december">d</string>
-
-    <string name="day_of_week_long_sunday">nedeľa</string>
-    <string name="day_of_week_long_monday">pondelok</string>
-    <string name="day_of_week_long_tuesday">utorok</string>
-    <string name="day_of_week_long_wednesday">streda</string>
-    <string name="day_of_week_long_thursday">štvrtok</string>
-    <string name="day_of_week_long_friday">piatok</string>
-    <string name="day_of_week_long_saturday">sobota</string>
-
-    <string name="day_of_week_medium_sunday">ne</string>
-    <string name="day_of_week_medium_monday">po</string>
-    <string name="day_of_week_medium_tuesday">ut</string>
-    <string name="day_of_week_medium_wednesday">st</string>
-    <string name="day_of_week_medium_thursday">št</string>
-    <string name="day_of_week_medium_friday">pi</string>
-    <string name="day_of_week_medium_saturday">so</string>
-
-    <string name="day_of_week_short_sunday">ne</string>
-    <string name="day_of_week_short_monday">po</string>
-    <string name="day_of_week_short_tuesday">ut</string>
-    <string name="day_of_week_short_wednesday">st</string>
-    <string name="day_of_week_short_thursday">št</string>
-    <string name="day_of_week_short_friday">pi</string>
-    <string name="day_of_week_short_saturday">so</string>
-
-    <string name="day_of_week_shortest_sunday">N</string>
-    <string name="day_of_week_shortest_monday">P</string>
-    <string name="day_of_week_shortest_tuesday">U</string>
-    <string name="day_of_week_shortest_wednesday">S</string>
-    <string name="day_of_week_shortest_thursday">Š</string>
-    <string name="day_of_week_shortest_friday">P</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">dopoludnia</string>
-    <string name="pm">popoludní</string>
-    <string name="yesterday">Včera</string>
-    <string name="today">Dnes</string>
-    <string name="tomorrow">Zajtra</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 165f1ed..c364380 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Možnosti telefónu"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Uzamknutie obrazovky"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Vypnúť"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Správa o chybe"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Zaznamenať správu o chybe"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Zhromažďuje informácie o aktuálnom stave zariadenia a tieto informácie je následne možné odoslať prostredníctvom e-mailovej správy. Od spustenia vytvárania správy o chybe až do chvíle, kedy je tento nástroj pripravený odoslať prvú správu, môže uplynúť nejaký čas. Prosíme vás preto o trpezlivosť."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Tichý režim"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Zvuk je VYPNUTÝ."</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Zvuk je zapnutý"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Vaše správy"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Čítanie a písanie správ SMS, e-mailov a ďalších správ."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Vaše osobné informácie"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Priamy prístup k vašim kontaktom a kalendáru uloženým v tablete."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Priamy prístup k vašim kontaktom a kalendáru uloženým v telefóne."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Priamy prístup k informáciám o vás uložených na vašej karte kontaktu."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Vaše sociálne informácie"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Priamy prístup k informáciám o vašich kontaktoch a sociálnych prepojeniach."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Vaša poloha"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Sledovanie vašej fyzickej polohy."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Sieťová komunikácia"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Prístup k rôznym funkciám siete."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Prístup k zariadeniam a sieťam prostredníctvom rozhrania Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Nastavenia zvuku"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Zmena nastavení zvuku."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Má vplyv na batériu"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Používanie funkcií, ktoré môžu rýchlo vyčerpať batériu."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalendár"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Priamy prístup ku kalendáru a udalostiam."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Čítanie požívateľského slovníka"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Čítanie slov v používateľskom slovníku."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Zápis do používateľského slovníka"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Pridávanie slov do používateľského slovníka."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Záložky a história"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Priamy prístup k záložkám a histórii prehliadača."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Budík"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Nastavenie budíka."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Hlasová schránka"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Priamy prístup do hlasovej schránky."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofón"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Priamy prístup k mikrofónu na záznam zvuku."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Fotoaparát"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Priamy prístup k fotoaparátu na nasnímanie fotografií alebo natočenie videí."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Informácie o vašich aplikáciách"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Schopnosť ovplyvniť správanie ďalších aplikácií na vašom zariadení."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Tapeta"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Zmena nastavení tapety zariadenia."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Hodiny"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Zmena času a časového pásma zariadenia."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Stavový riadok"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Zmena nastavení stavového riadka zariadenia."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Nastavenia synchronizácie"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Prístup do nastavení synchronizácie."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Vaše účty"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Prístup k dostupným účtom."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Ovládanie hardvéru"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Nízkoúrovňový prístup a ovládanie systému."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Nástroje pre vývoj"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funkcie len pre vývojárov aplikácií."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Používateľské rozhranie iných aplikácií"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Vplyv na používateľské rozhranie ďalších aplikácií."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Ukladací priestor"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Prístup do ukl. priestoru USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Prístup na kartu SD."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Umožňuje aplikácii prijímať a spracovávať správy WAP. Toto povolenie zahŕňa možnosť sledovať vaše správy alebo ich odstrániť bez toho, aby sa vám zobrazili."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"načítať spustené aplikácie"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Umožňuje aplikácii načítať informácie o aktuálne či nedávno spustených úlohách. Toto povolenie môže aplikácii umožniť objaviť informácie o tom, ktoré aplikácie sa na zariadení používajú."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interakcie naprieč používateľmi"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Umožňuje aplikácii vykonávať akcie naprieč rôznymi používateľmi zariadenia. Škodlivé aplikácie môžu toto povolenie zneužiť na obídenie ochrany medzi používateľmi."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"plná licencia na interakcie naprieč používateľmi"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Umožňuje všetky možné interakcie naprieč používateľmi."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"správa používateľov"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Umožňuje aplikáciám spravovať používateľov v zariadení, vrátane vyhľadávania dopytov, vytvorenia a odstránenia."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"načítať podrobnosti o spustených aplikáciách"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Umožňuje aplikácii načítať podrobné informácie o aktuálnych a nedávno spustených úlohách. Škodlivé aplikácie môžu odhaliť súkromné informácie o iných aplikáciách."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"zmeniť poradie spustených aplikácií"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Umožňuje aplikácii načítať interný stav systému. Škodlivé aplikácie môžu načítať široký rozsah súkromných a zabezpečených informácií, ktoré by obvykle nemali nikdy potrebovať."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"načítanie obsahu obrazovky"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Umožňuje aplikácii načítať obsah aktívneho okna. Škodlivé aplikácie môžu získať celý obsah okna a preskúmať celý jeho text okrem hesiel."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"dočasné povolenie zjednodušenia ovládania"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Umožňuje aplikácii dočasne povoliť zjednodušenie ovládania v zariadení. Škodlivé aplikáciu môžu zjednodušenie ovládania povoliť bez súhlasu používateľa."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"načítanie informácií o oknách"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Umožňuje aplikácii načítať informácie o oknách zo správcu okien. Škodlivé aplikácie môžu načítať informácie, ktoré sú určené pre interné využitie systému."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrovanie udalostí"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Umožňuje aplikácii zaregistrovať vstupný filter, ktorý filtruje stream všetkých prenosov používateľa pred ich odvysielaním. Škodlivá aplikácia môže bez zásahu používateľa ovládať používateľské rozhranie systému."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"priblížiť zobrazenie"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Umožňuje aplikácii priblížiť obsah displeja. Škodlivé aplikácie môžu zmeniť zobrazenie obsahu tak, že sa zariadenie stane nepoužiteľným."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"Čiastočné vypnutie"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Uvedie správcu činností do vypnutého stavu. Úplné vypnutie však nenastane."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zabrániť prepínaniu aplikácií"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Umožňuje aplikácii kontrolovať maximálny počet spustených procesov. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"vynútiť zavretie aplikácií na pozadí"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Umožňuje aplikácii ovládať, či sa aktivity po presune na pozadie vždy ukončia. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"zmena štatistických údajov o batérii"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Umožňuje aplikácii zmeniť zhromaždené štatistické údaje o batérii. Bežné aplikácie toto nastavenie nepoužívajú."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"čítať štatistické údaje o batérii"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Umožňuje aplikácii čítať aktuálne údaje nízkej úrovne o používaní batérie. Pomocou tejto funkcie môže aplikácia zistiť podrobnosti o tom, ktoré aplikácie používate."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"zmena štatistických údajov o batérii"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Umožňuje aplikácii zmeniť zhromaždené štatistické údaje o batérii. Bežné aplikácie toto nastavenie nepoužívajú."</string>
     <string name="permlab_backup" msgid="470013022865453920">"Ovládať zálohovanie a obnovu systému"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Umožňuje aplikácii ovládať mechanizmus na zálohovanie a obnovu údajov systému. Bežné aplikácie toto nastavenie nepoužívajú."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"potvrdenie operácie úplnej zálohy alebo úplného obnovenia"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"zobrazenie neoprávnených okien"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Umožňuje aplikácii vytvárať okná, ktoré majú byť použité interným systémom používateľského rozhrania. Bežné aplikácie toto nastavenie nepoužívajú."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"vykresliť cez ďalšie aplikácie"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Umožňuje aplikácii zobraziť okná s výstrahami systému. Niektoré okná s výstrahami môžu prevziať kontrolu nad celou obrazovkou."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Umožňuje aplikáciu vykresľovanie nad inými aplikáciami alebo súčasťami používateľského rozhrania. Táto funkcia môže zasahovať do vášho používania rozhrania inej aplikácie alebo meniť zobrazovaný obsah v iných aplikáciách."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"globálne zmeny rýchlosti animácie"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Umožňuje aplikácii kedykoľvek globálne zmeniť rýchlosť animácie (rýchlejšia alebo pomalšia animácia)."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"spravovať tokeny aplikácií"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Umožňuje aplikácii vytvárať a spravovať svoje vlastné tokeny a obísť ich obvyklé Z-usporiadanie. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"zmraziť obrazovku"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Umožňuje aplikácii dočasne zmraziť obrazovku na prechod v režime celej obrazovky."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"používanie kláves a tlačidiel"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Umožňuje aplikácii doručiť vlastné udalosti vstupu (stlačenie tlačidiel atď.) ďalším aplikáciám. Škodlivé aplikácie môžu pomocou toho prevziať kontrolu nad tabletom."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Umožňuje aplikácii doručiť vlastné udalosti vstupu (stlačenie tlačidiel atď.) ďalším aplikáciám. Škodlivé aplikácie môžu pomocou tohto nastavenia prevziať kontrolu nad telefónom."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"priamo inštalovať aplikácie"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Umožňuje aplikácii nainštalovať nové alebo aktualizované balíky systému Android. Škodlivé aplikácie môžu použiť toto nastavenie na pridanie nových aplikácií s ľubovoľnými povoleniami."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"odstrániť všetky údaje vyrovnávacej pamäte aplikácie"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Umožňuje aplikácii uvoľniť ukladací priestor v tablete odstránením súborov v adresári vyrovnávacej pamäte aplikácie. Prístup je veľmi obmedzený, väčšinou len pre systémový proces."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Umožňuje aplikácii uvoľniť ukladací priestor telefónu odstránením súborov v adresári vyrovnávacej pamäte aplikácie. Prístup je veľmi obmedzený, väčšinou len pre systémový proces."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Umožňuje aplikácii uvoľniť ukladací priestor v tablete odstránením súborov v adresároch iných aplikácií vo vyrovnávacej pamäti. To môže viesť k pomalšiemu spúšťaniu iných aplikácií, pretože musia znovu načítať svoje údaje."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Umožňuje aplikácii uvoľniť ukladací priestor v telefóne odstránením súborov v adresároch iných aplikácií vo vyrovnávacej pamäti. To môže viesť k pomalšiemu spúšťaniu iných aplikácií, pretože musia znovu načítať svoje údaje."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"presúvať prostriedky aplikácií"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Umožňuje aplikácii presúvať prostriedky aplikácií medzi internými a externými médiami."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"čítať citlivé údaje denníkov"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Umožňuje aplikácii pristupovať k ďalším príkazom poskytovateľa informácií o polohe. Aplikácii to môže umožniť zasahovať do činnosti systému GPS alebo iných zdrojov informácií o polohe."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"Oprávnenie na inštaláciu poskytovateľa polohy"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Vytváranie simulovaných zdrojov polohy na testovanie alebo inštalácia nového poskytovateľa informácií o polohe. Aplikácii to umožní nahradiť polohu a stav, ktoré vracajú iné zdroje informácií o polohe, ako sú napríklad systém GPS alebo poskytovatelia informácií o polohe."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"presná poloha (pomocou GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Prístup ku presným zdrojom informácií o polohe, ako je napríklad systém GPS, na tablete. Keď sú služby určovania polohy k dispozícii a sú zapnuté, toto povolenie umožňuje aplikácii určiť vašu približnú polohu."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Prístup ku presným zdrojom informácií o polohe, ako je napríklad systém GPS, na telefóne. Keď sú služby určovania polohy k dispozícii a sú zapnuté, toto povolenie umožňuje aplikácii určiť vašu približnú polohu."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"približná poloha (pomocou siete)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Prístup ku približnej polohe určenej poskytovateľmi informácií o polohe prostredníctvom sieťových zdrojov, ako sú stanice BTS a siete Wi-Fi. Keď sú tieto služby určovania polohy k dispozícii a sú zapnuté, toto povolenie umožňuje aplikácii určiť vašu približnú polohu."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"presná poloha (pomocou GPS a siete)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Umožňuje aplikácii získať vašu presnú polohu pomocou systému GPS (Global Positioning System) alebo zdrojov určenia polohy siete, napríklad mobilných veží a sietí Wi-Fi. Tieto služby využívajúce polohu musia byť na vašom zariadení zapnuté a dostupné, inak ich aplikácia nebude môcť využívať. Aplikácie môžu tieto služby využívať na určenie vašej polohy. Tieto služby môžu zvýšiť spotrebu batérie."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"približná poloha (pomocou siete)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Umožňuje aplikácii získať vašu približnú polohu. Táto poloha je odvodená zo služieb využívajúcich polohu pomocou zdrojov určenia polohy siete, napríklad mobilných veží a sietí Wi-Fi. Tieto služby využívajúce polohu musia byť na vašom zariadení zapnuté a dostupné, inak ich aplikácia nebude môcť využívať. Aplikácie môžu tieto služby využívať na určenie vašej približnej polohy."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"prístup k službe SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Umožňuje aplikácii používať funkcie nízkej úrovne aplikácie SurfaceFlinger."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"čítanie vyrovnávacej pamäte snímok"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Umožňuje aplikácii čítať obsah vyrovnávacej pamäte snímok."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"konfigurovať displeje cez sieť Wi-Fi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Umožňuje aplikácii konfigurovať displeje a pripojiť sa k nim cez siete Wi-Fi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"ovládať displeje cez sieť Wi-Fi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Umožňuje aplikácii ovládať základné funkcie displejov cez siete Wi-Fi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"zmeny vašich nastavení zvuku"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Umožňuje aplikácii upraviť globálne nastavenia zvuku, ako je hlasitosť, alebo určiť, z ktorého reproduktora bude zvuk vychádzať."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"záznam zvuku"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"pristupovať k nastaveniam Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Umožňuje aplikácii konfigurovať miestny tablet s rozhraním Bluetooth a vyhľadávať a spárovať vzdialené zariadenia."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Umožňuje aplikácii konfigurovať miestny telefón s rozhraním Bluetooth, vyhľadávať a spárovať vzdialené zariadenia."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Zobraziť pripojenia siete WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"pripojiť a odpojiť od WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Umožňuje aplikácii určiť, či je povolený štandard WiMAX, a tiež informácie o všetkých pripojených sieťach WiMAX."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Zmeniť stav siete WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Umožňuje aplikácii pripojiť tablet k sieťam WiMAX a odpojiť ho od nich."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Umožňuje aplikácii upraviť vaše aktuálne synchronizované informačné kanály. Škodlivé aplikácie môžu synchronizované informačné kanály zmeniť."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"čítať výrazy pridané do slovníka"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Umožňuje aplikácii čítať všetky slová, názvy a frázy, ktoré mohol používateľ uložiť do svojho slovníka."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"zapisovať do slovníka definovaného používateľom"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"pridať slová do slovníka definovaného používateľom"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Umožňuje aplikácii zapisovať nové slová do používateľského slovníka."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"testovanie prístupu do chráneného ukladacieho priestoru"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"testovanie prístupu do chráneného ukladacieho priestoru"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Umožňuje aplikácii testovať povolenie pre ukladací priestor USB, ktorý bude k dispozícii v budúcich zariadeniach."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Umožňuje aplikácii testovať povolenie pre úložisko USB, ktoré bude k dispozícii na zariadeniach."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Umožňuje aplikácii testovať povolenie pre kartu SD, ktorá bude k dispozícii v budúcich zariadeniach."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"upraviť alebo odstrániť obsah úložiska USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"úprava alebo odstránenie obsahu na karte SD"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Umožňuje aplikácii zápis na kartu SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"úprava alebo odstránenie obsahu interného ukladacieho priestoru média"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Umožňuje aplikácii zmeniť obsah interného ukladacieho priestoru média."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"pristupovať k externému ukladaciemu priestoru pre všetkých používateľov"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Umožňuje aplikácii pristupovať k externému ukladaciemu priestoru pre všetkých používateľov."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"pristupovať do súborového systému vyrovnávacej pamäte"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Umožňuje aplikácii čítať a zapisovať do súborového systému vyrovnávacej pamäte."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"uskutočňovať a prijímať internetové hovory"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Vyžadovať šifrovanie uložených údajov aplikácií."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Zakázať fotoaparáty"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Zakázať používanie všetkých fotoaparátov zariadenia."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Zákaz funkcie v zámke kláves."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Zabrániť používaniu niektorých funkcií v zámke klávesov."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domovská stránka"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Skúsiť znova"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Prekročili ste maximálny povolený počet pokusov o odomknutie tvárou"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Prebieha nabíjanie, <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Nabité."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Nabitá batéria"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Pripojte nabíjačku."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nie je vložená karta SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Nie je vložená karta SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"V tablete nie je žiadna karta SIM."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"V telefóne nie je žiadna karta SIM."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Vložte kartu SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Bezpečnostný vzor bol vymazaný"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Bunka bola pridaná"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Bezpečnostný vzor bol dokončený"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Pridať miniaplikáciu."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Prázdne"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Oblasť na odomknutie bola rozšírená."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Oblasť na odomknutie bola zúžená."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Miniaplikácia <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Výber používateľa"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Stav"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Fotoaparát"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Ovládacie prvky médií"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Zmena usporiadania miniaplikácií sa začala."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Zmena usporiadania miniaplikácií sa skončila."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Miniaplikácia <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> bola odstránená."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Rozšíriť oblasť na odomknutie."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Odomknutie prejdením prstom."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Odomknutie vzorom."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Odomknutie tvárou."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Odomknutie kódom PIN."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Odomknutie heslom."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Oblasť na zadanie bezpečnostného vzoru."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Oblasť na prejdenie prstom."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Skopírovať adresu URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Vybrať text"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Výber textu"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"pridať do slovníka"</string>
-    <string name="deleteText" msgid="7070985395199629156">"odstrániť"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Pridať do slovníka"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Odstrániť"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metóda vstupu"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Operácie s textom"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Nedostatok ukladacieho priestoru"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"K dispozícii sú verejné siete Wi-Fi"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Prihlásenie sa do siete Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Prihláste sa do siete"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nepodarilo sa pripojiť k sieti Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" má nekvalitné internetové pripojenie."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Komu:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Zadajte požadovaný kód PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefón bude počas pripojenia k zariadeniu <xliff:g id="DEVICE_NAME">%1$s</xliff:g> od siete Wi-Fi dočasne odpojený."</string>
     <string name="select_character" msgid="3365550120617701745">"Vkladanie znakov"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Odosielanie správ SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"Aplikácia &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; posiela veľký počet správ SMS. Chcete tejto aplikácií povoliť, aby aj naďalej posielala správy?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Povoliť"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Odmietnuť"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chce odoslať správu na adresu &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457"><font fgcolor="#ffffb060">"Môžu sa účtovať poplatky"</font>" na váš mobilný účet."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Budú sa účtovať poplatky na váš mobilný účet."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Odoslať"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Zrušiť"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Zapamätať si voľbu"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Zmena v časti Nastavenia &gt; Aplikácie"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Vždy povoliť"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nikdy nepovoliť"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Karta SIM bola odobraná"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilná sieť nebude k dispozícii, kým nevložíte platnú kartu SIM a zariadenie nereštartujete."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Hotovo"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Nastaviť dátum"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Nastaviť"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Hotovo"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Predvolené"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Nevyžadujú sa žiadne oprávnenia."</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Skryť"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Zobraziť všetky"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NOVINKA: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NOVINKA: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Poskytuje aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Nevyžadujú sa žiadne oprávnenia."</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"môžu sa vám účtovať poplatky"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Veľkokapacitné úložisko USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Zariadenie USB pripojené"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Zariadenie ste pripojili k počítaču pomocou portu USB. Ak chcete kopírovať súbory z počítača do ukladacieho priestoru USB v zariadení so systémom Android alebo naopak, dotknite sa tlačidla nižšie."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikáciu <xliff:g id="APP">%s</xliff:g> aktivovala sieť VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotykom môžete spravovať sieť."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Pripojené k relácii <xliff:g id="SESSION">%s</xliff:g>. Po dotyku môžete sieť spravovať."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Prebieha pripájanie k vždy zapnutej sieti VPN..."</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Pripojenie k vždy zapnutej sieti VPN"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Chyba vždy zapnutej siete VPN"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Dotykom obnovíte pripojenie"</string>
     <string name="upload_file" msgid="2897957172366730416">"Zvoliť súbor"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nie je vybratý žiadny súbor"</string>
     <string name="reset" msgid="2448168080964209908">"Obnoviť"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Zdieľať"</string>
     <string name="find" msgid="4808270900322985960">"Nájsť"</string>
     <string name="websearch" msgid="4337157977400211589">"Hľadať na webe"</string>
+    <string name="find_next" msgid="5742124618942193978">"Nájsť ďalšiu"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Nájsť predchádzajúcu"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Žiadosť o informácie o polohe od používateľa <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Žiadosť o informácie o polohe"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Žiadosť od používateľa <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefón"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Slúchadlá"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Reproduktory doku"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Zvuk HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Systém"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Hotovo"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Výstup médií"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Prebieha vyhľadávanie..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Prebieha pripájanie…"</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"K dispozícii"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Nie je k dispozícii"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Vstavaná obrazovka"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Obrazovka HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Prekrytie č. <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Bezdrôtový displej je pripojený"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Táto obrazovka sa zobrazuje na inom zariadení"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Odpojiť"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Tiesňové volanie"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Nepamätám si vzor"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Nesprávny vzor"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Nesprávne heslo"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Nesprávny kód PIN"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Skúste to znova o <xliff:g id="NUMBER">%d</xliff:g> s."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Nakreslite svoj vzor"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Zadajte kód PIN karty SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Zadajte kód PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Zadajte heslo"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"Karta SIM je teraz zakázaná. Ak chcete pokračovať, zadajte kód PUK. Podrobné informácie získate od operátora."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Zadajte požadovaný kód PIN"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Potvrďte požadovaný kód PIN"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Prebieha odomykanie karty SIM..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Nesprávny kód PIN."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Zadajte kód PIN s dĺžkou 4 až 8 číslic."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Kód PUK musí obsahovať 8 alebo viac číslic."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Znova zadajte správny kód PUK. Opakované pokusy zakážu kartu SIM natrvalo."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Kódy PIN sa nezhodujú"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Príliš veľa pokusov o nakreslenie vzoru"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Ak chcete telefón odomknúť, prihláste sa pomocou svojho účtu Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Používateľské meno (e-mail)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Heslo"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Prihlásiť sa"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Neplatné používateľské meno alebo heslo."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Zabudli ste svoje používateľské meno alebo heslo?"\n" Navštívte stránky "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Prebieha kontrola účtu..."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"<xliff:g id="NUMBER_0">%d</xliff:g>-krát ste zadali nesprávny kód PIN. "\n\n"Skúste to znova o <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"<xliff:g id="NUMBER_0">%d</xliff:g>-krát ste zadali nesprávne heslo. "\n\n"Skúste to znova o <xliff:g id="NUMBER_1">%d</xliff:g>."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"<xliff:g id="NUMBER_0">%d</xliff:g>-krát ste použili nesprávny bezpečnostný vzor. "\n\n"Skúste to znova o <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Tablet ste sa pokúsili odomknúť nesprávnym spôsobom <xliff:g id="NUMBER_0">%d</xliff:g>-krát. Po <xliff:g id="NUMBER_1">%d</xliff:g> ďalších neúspešných pokusoch sa v tablete obnovia predvolené továrenské nastavenia a všetky používateľské údaje budú stratené."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Telefón ste sa pokúsili odomknúť nesprávnym spôsobom <xliff:g id="NUMBER_0">%d</xliff:g>-krát. Po <xliff:g id="NUMBER_1">%d</xliff:g> ďalších neúspešných pokusoch sa v telefóne obnovia predvolené továrenské nastavenia a všetky používateľské údaje budú stratené."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Tablet ste sa pokúsili odomknúť nesprávnym spôsobom <xliff:g id="NUMBER">%d</xliff:g>-krát. V tablete sa teraz obnovia predvolené továrenské nastavenia."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Telefón ste sa pokúsili odomknúť nesprávnym spôsobom <xliff:g id="NUMBER">%d</xliff:g>-krát. V telefóne sa teraz obnovia predvolené továrenské nastavenia."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"<xliff:g id="NUMBER_0">%d</xliff:g>-krát ste nesprávne nakreslili svoj bezpečnostný vzor. Po ďalších <xliff:g id="NUMBER_1">%d</xliff:g> neúspešných pokusoch sa zobrazí výzva na odomknutie tabletu pomocou e-mailového účtu."\n\n" Skúste to znova o <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"<xliff:g id="NUMBER_0">%d</xliff:g>-krát ste nesprávne nakreslili svoj bezpečnostný vzor. Po <xliff:g id="NUMBER_1">%d</xliff:g> ďalších neúspešných pokusoch sa zobrazí výzva na odomknutie telefónu pomocou e-mailového účtu."\n\n" Skúste to znova o <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Odstrániť"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Chcete zvýšiť hlasitosť nad bezpečnú úroveň?"\n"Dlhodobé počúvanie pri vysokej hlasitosti môže viesť k poškodeniu vášho sluchu."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Zjednodušenie ovládania povolíte dlhým stlačením dvoma prstami."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Zjednodušenie ovládania je povolené."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Zjednodušenie ovládania bolo zrušené."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Aktuálny používateľ je <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Vlastník"</string>
 </resources>
diff --git a/core/res/res/values-sl-rSI/donottranslate-cldr.xml b/core/res/res/values-sl-rSI/donottranslate-cldr.xml
index cbabccd..84fffbd 100644
--- a/core/res/res/values-sl-rSI/donottranslate-cldr.xml
+++ b/core/res/res/values-sl-rSI/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">januar</string>
-    <string name="month_long_standalone_february">februar</string>
-    <string name="month_long_standalone_march">marec</string>
-    <string name="month_long_standalone_april">april</string>
-    <string name="month_long_standalone_may">maj</string>
-    <string name="month_long_standalone_june">junij</string>
-    <string name="month_long_standalone_july">julij</string>
-    <string name="month_long_standalone_august">avgust</string>
-    <string name="month_long_standalone_september">september</string>
-    <string name="month_long_standalone_october">oktober</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">december</string>
-
-    <string name="month_long_january">januar</string>
-    <string name="month_long_february">februar</string>
-    <string name="month_long_march">marec</string>
-    <string name="month_long_april">april</string>
-    <string name="month_long_may">maj</string>
-    <string name="month_long_june">junij</string>
-    <string name="month_long_july">julij</string>
-    <string name="month_long_august">avgust</string>
-    <string name="month_long_september">september</string>
-    <string name="month_long_october">oktober</string>
-    <string name="month_long_november">november</string>
-    <string name="month_long_december">december</string>
-
-    <string name="month_medium_january">jan.</string>
-    <string name="month_medium_february">feb.</string>
-    <string name="month_medium_march">mar.</string>
-    <string name="month_medium_april">apr.</string>
-    <string name="month_medium_may">maj.</string>
-    <string name="month_medium_june">jun.</string>
-    <string name="month_medium_july">jul.</string>
-    <string name="month_medium_august">avg.</string>
-    <string name="month_medium_september">sep.</string>
-    <string name="month_medium_october">okt.</string>
-    <string name="month_medium_november">nov.</string>
-    <string name="month_medium_december">dec.</string>
-
-    <string name="month_shortest_january">j</string>
-    <string name="month_shortest_february">f</string>
-    <string name="month_shortest_march">m</string>
-    <string name="month_shortest_april">a</string>
-    <string name="month_shortest_may">m</string>
-    <string name="month_shortest_june">j</string>
-    <string name="month_shortest_july">j</string>
-    <string name="month_shortest_august">a</string>
-    <string name="month_shortest_september">s</string>
-    <string name="month_shortest_october">o</string>
-    <string name="month_shortest_november">n</string>
-    <string name="month_shortest_december">d</string>
-
-    <string name="day_of_week_long_sunday">nedelja</string>
-    <string name="day_of_week_long_monday">ponedeljek</string>
-    <string name="day_of_week_long_tuesday">torek</string>
-    <string name="day_of_week_long_wednesday">sreda</string>
-    <string name="day_of_week_long_thursday">četrtek</string>
-    <string name="day_of_week_long_friday">petek</string>
-    <string name="day_of_week_long_saturday">sobota</string>
-
-    <string name="day_of_week_medium_sunday">ned.</string>
-    <string name="day_of_week_medium_monday">pon.</string>
-    <string name="day_of_week_medium_tuesday">tor.</string>
-    <string name="day_of_week_medium_wednesday">sre.</string>
-    <string name="day_of_week_medium_thursday">čet.</string>
-    <string name="day_of_week_medium_friday">pet.</string>
-    <string name="day_of_week_medium_saturday">sob.</string>
-
-    <string name="day_of_week_short_sunday">ned.</string>
-    <string name="day_of_week_short_monday">pon.</string>
-    <string name="day_of_week_short_tuesday">tor.</string>
-    <string name="day_of_week_short_wednesday">sre.</string>
-    <string name="day_of_week_short_thursday">čet.</string>
-    <string name="day_of_week_short_friday">pet.</string>
-    <string name="day_of_week_short_saturday">sob.</string>
-
-    <string name="day_of_week_shortest_sunday">n</string>
-    <string name="day_of_week_shortest_monday">p</string>
-    <string name="day_of_week_shortest_tuesday">t</string>
-    <string name="day_of_week_shortest_wednesday">s</string>
-    <string name="day_of_week_shortest_thursday">č</string>
-    <string name="day_of_week_shortest_friday">p</string>
-    <string name="day_of_week_shortest_saturday">s</string>
-
-    <string name="am">dop.</string>
-    <string name="pm">pop.</string>
-    <string name="yesterday">Včeraj</string>
-    <string name="today">Danes</string>
-    <string name="tomorrow">Jutri</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-sl/donottranslate-cldr.xml b/core/res/res/values-sl/donottranslate-cldr.xml
index b804b3f..137ed3f 100644
--- a/core/res/res/values-sl/donottranslate-cldr.xml
+++ b/core/res/res/values-sl/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">januar</string>
-    <string name="month_long_standalone_february">februar</string>
-    <string name="month_long_standalone_march">marec</string>
-    <string name="month_long_standalone_april">april</string>
-    <string name="month_long_standalone_may">maj</string>
-    <string name="month_long_standalone_june">junij</string>
-    <string name="month_long_standalone_july">julij</string>
-    <string name="month_long_standalone_august">avgust</string>
-    <string name="month_long_standalone_september">september</string>
-    <string name="month_long_standalone_october">oktober</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">december</string>
-
-    <string name="month_long_january">januar</string>
-    <string name="month_long_february">februar</string>
-    <string name="month_long_march">marec</string>
-    <string name="month_long_april">april</string>
-    <string name="month_long_may">maj</string>
-    <string name="month_long_june">junij</string>
-    <string name="month_long_july">julij</string>
-    <string name="month_long_august">avgust</string>
-    <string name="month_long_september">september</string>
-    <string name="month_long_october">oktober</string>
-    <string name="month_long_november">november</string>
-    <string name="month_long_december">december</string>
-
-    <string name="month_medium_january">jan</string>
-    <string name="month_medium_february">feb</string>
-    <string name="month_medium_march">mar</string>
-    <string name="month_medium_april">apr</string>
-    <string name="month_medium_may">maj</string>
-    <string name="month_medium_june">jun</string>
-    <string name="month_medium_july">jul</string>
-    <string name="month_medium_august">avg</string>
-    <string name="month_medium_september">sep</string>
-    <string name="month_medium_october">okt</string>
-    <string name="month_medium_november">nov</string>
-    <string name="month_medium_december">dec</string>
-
-    <string name="month_shortest_january">j</string>
-    <string name="month_shortest_february">f</string>
-    <string name="month_shortest_march">m</string>
-    <string name="month_shortest_april">a</string>
-    <string name="month_shortest_may">m</string>
-    <string name="month_shortest_june">j</string>
-    <string name="month_shortest_july">j</string>
-    <string name="month_shortest_august">a</string>
-    <string name="month_shortest_september">s</string>
-    <string name="month_shortest_october">o</string>
-    <string name="month_shortest_november">n</string>
-    <string name="month_shortest_december">d</string>
-
-    <string name="day_of_week_long_sunday">nedelja</string>
-    <string name="day_of_week_long_monday">ponedeljek</string>
-    <string name="day_of_week_long_tuesday">torek</string>
-    <string name="day_of_week_long_wednesday">sreda</string>
-    <string name="day_of_week_long_thursday">četrtek</string>
-    <string name="day_of_week_long_friday">petek</string>
-    <string name="day_of_week_long_saturday">sobota</string>
-
-    <string name="day_of_week_medium_sunday">ned</string>
-    <string name="day_of_week_medium_monday">pon</string>
-    <string name="day_of_week_medium_tuesday">tor</string>
-    <string name="day_of_week_medium_wednesday">sre</string>
-    <string name="day_of_week_medium_thursday">čet</string>
-    <string name="day_of_week_medium_friday">pet</string>
-    <string name="day_of_week_medium_saturday">sob</string>
-
-    <string name="day_of_week_short_sunday">ned</string>
-    <string name="day_of_week_short_monday">pon</string>
-    <string name="day_of_week_short_tuesday">tor</string>
-    <string name="day_of_week_short_wednesday">sre</string>
-    <string name="day_of_week_short_thursday">čet</string>
-    <string name="day_of_week_short_friday">pet</string>
-    <string name="day_of_week_short_saturday">sob</string>
-
-    <string name="day_of_week_shortest_sunday">n</string>
-    <string name="day_of_week_shortest_monday">p</string>
-    <string name="day_of_week_shortest_tuesday">t</string>
-    <string name="day_of_week_shortest_wednesday">s</string>
-    <string name="day_of_week_shortest_thursday">č</string>
-    <string name="day_of_week_shortest_friday">p</string>
-    <string name="day_of_week_shortest_saturday">s</string>
-
-    <string name="am">dop.</string>
-    <string name="pm">pop.</string>
-    <string name="yesterday">Včeraj</string>
-    <string name="today">Danes</string>
-    <string name="tomorrow">Jutri</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 46cbcdb..7f94c204 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Možnosti telefona"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Zaklep zaslona"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Izklopi"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Poročilo o napakah"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Ustvari poročilo o napakah"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"S tem bodo zbrani podatki o trenutnem stanju naprave, ki bodo poslani v e-poštnem sporočilu. Izvedba poročila o napakah in priprava trajata nekaj časa, zato bodite potrpežljivi."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Tihi način"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Zvok je IZKLOPLJEN"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Zvok je VKLOPLJEN"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Vaša sporočila"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Pisanje in branje SMS-ov, e-pošte in drugih sporočil."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Osebni podatki"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Neposreden dostop do stikov in koledarskih vnosov, shranjenih v tabličnem računalniku."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Neposreden dostop do stikov in koledarja, shranjenega v telefonu."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Neposreden dostop do podatkov o vas, shranjenih v vizitki."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Podatki v družabnih omrežjih"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Neposreden dostop do podatkov o stikih in družabnih povezav."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Vaša lokacija"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Spremljanje fizične lokacije."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Omrežna komunikacija"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Dostop do različnih funkcij omrežja."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Dostopanje do naprav in omrežij prek povezave Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Nastavitve zvoka"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Spreminjanje nastavitev zvoka."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Vpliv na baterijo"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Uporaba funkcij, ki lahko hitro izpraznijo baterijo."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Google Koledar"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Neposreden dostop do koledarja in dogodkov."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Branje uporabniškega slovarja"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Branje besed v uporabniškem slovarju."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Pisanje v uporabniški slovar"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Dodajanje besed v uporabniški slovar."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Zaznamki in zgodovina"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Neposreden dostop do zaznamkov in zgodovine brskalnika."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarm"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Nastavitev budilke."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Odzivnik"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Neposreden dostop do odzivnika."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Neposreden dostop do mikrofona za snemanje zvoka."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Fotoaparat"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Neposreden dostop do fotoaparata za fotografiranje ali snemanje videoposnetkov."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Podatki o vaših aplikacijah"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Zmožnost vpliva na delovanje drugih aplikacij v napravi."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Slika za ozadje"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Spreminjanje nastavitev slike za ozadje."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Ura"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Sprememba časa ali časovnega pasu naprave."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Vrstica stanja"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Spreminjanje nastavitev vrstice stanja naprave."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Nastavitve sinhronizacije"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Dostop do sinhronizacijskih nastavitev."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Vaši računi"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Dostop do razpoložljivih računov."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Kontrolniki strojne opreme"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Dostop nižje ravni in nadzor sistema."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Razvojna orodja"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funkcije, ki jih potrebujejo le razvijalci programa."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Uporabniški vmesnik druge aplikacije"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Vpliv na uporabniški vmesnik drugih aplikacij."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Prostor za shranjevanje"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Dostop do pomnilnika USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Dostop do kartice SD."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Aplikaciji omogoča prejemanje in obdelavo sporočil WAP. S tem lahko aplikacija nadzoruje ali izbriše sporočila, poslana v napravo, ne da bi vam jih pokazala."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"dobivanje programov, ki se izvajajo"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Aplikaciji omogoča prejemanje podatkov o trenutnih in nedavno izvajajočih se opravilih. S tem lahko aplikacija odkrije podatke o aplikacijah, ki se uporabljajo v napravi."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interakcija z uporabniki"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Aplikaciji omogoča izvajanje dejanj za različne uporabnike v napravi. Zlonamerne aplikacije lahko to uporabijo za kršitev zaščite med uporabniki."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"polna licenca za interakcijo z uporabniki"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Dovoli vso mogočo interakcijo z uporabniki"</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"upravljanje uporabnikov"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Aplikacijam omogoča upravljanje uporabnikov v napravi, vključno z iskanjem, ustvarjanjem in brisanjem."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"prejemanje podrobnosti o aplikacijah, ki se izvajajo"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Aplikaciji omogoča, da dobi podatke o trenutnih in nedavno izvajajočih se opravilih. Zlonamerne aplikacije lahko odkrijejo zasebne podatke o drugih aplikacijah."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"preurejanje programov, ki se izvajajo"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Programu omogoča prejemanje notranjega stanja sistema. Zlonamerni programi lahko na ta način dobijo različne zasebne in varnostne podatke, ki jih običajno ne potrebujejo."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"prenos vsebine zaslona"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Programu omogoča dostop do vsebine aktivnega okna. Zlonamerni programi lahko dobijo vso vsebino okna in pregledajo njeno besedilo razen gesel."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"začasno omogoči pripomočke za ljudi s posebnimi potrebami"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Aplikaciji omogoča, da v napravi začasno omogoči pripomočke za ljudi s posebnimi potrebami. Zlonamerne aplikacije jih lahko omogočijo brez soglasja uporabnika."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"prenos podatkov o oknih"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Omogoča, da aplikacija iz upravitelja oken pridobiva podatke o oknih. Zlonamerne aplikacije lahko pridobivajo podatke, namenjene za notranjo uporabo v sistemu."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtriranje dogodkov"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Omogoča, da aplikacija registrira vhodni filter, ki pred razpošiljanjem filtrira tok vseh uporabniških dogodkov. Zlonamerne aplikacije lahko nadzirajo uporabniški vmesnik sistema brez posega uporabnika."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"povečevanje zaslona"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Omogoča aplikaciji povečevanje vsebine zaslona. Zlonamerne aplikacije lahko preoblikujejo vsebino zaslona tako, da je naprava neuporabna."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"delna zaustavitev"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Upravitelja dejavnosti preklopi v stanje za zaustavitev. Ne izvede celotne zaustavitve."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"preprečevanje preklopa programov"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Programu omogoča nadzor največjega števila postopkov, ki se bodo izvajali. Tega nikoli ni treba uporabiti za navadne programe."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"vsiljeno zapiranje aplikacij v ozadju"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Programu omogoča, da nadzoruje, ali so dejavnosti zaključene takoj, ko so premaknjene v ozadje. Tega ni treba nikoli uporabiti za navadne programe."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"spreminjanje statističnih podatkov o bateriji"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Programu omogoča spreminjanje zbranih statističnih podatkov o bateriji. Ni za uporabo z navadnimi programi."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"branje statističnih podatkov o akumulatorju"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Aplikaciji omogoča branje podatkov o trenutni nizki napolnjenosti akumulatorja. Aplikaciji lahko tudi dovoli dostop do podrobnosti o tem, katere aplikacije uporabljate."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"spreminjanje statističnih podatkov o akumulatorju"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Aplikaciji omogoča spreminjanje zbranih statističnih podatkov o akumulatorju. Ni primerno za uporabo z običajnimi aplikacijami."</string>
     <string name="permlab_backup" msgid="470013022865453920">"nadzor varnostnega kopiranja sistema in obnovitev"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Programu omogoča nadzor mehanizma za varnostno kopiranje in obnovitev sistema. Ni za uporabo z navadnimi programi."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"potrditev popolnega varnostnega kopiranja ali obnovitve"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"prikazovanje nepooblaščenih oken"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Programu omogoča ustvarjanje oken, ki jih bo uporabljal uporabniški vmesnik notranjega sistema. Ni za uporabo z navadnimi programi."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"prekrivanje drugih aplikacij"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Aplikaciji omogoča, da prikaže okna s sistemskimi opozorili. Nekatera okna z opozorili lahko zavzamejo celoten zaslon."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Aplikaciji omogoča risanje na vrhu drugih aplikacij ali delov uporabniškega vmesnika. To lahko vpliva na vašo uporabo vmesnika v kateri koli aplikaciji ali vas zavede pri prikazu v drugih aplikacijah."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"spreminjanje splošne hitrosti animacij"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Programu omogoča, da kadar koli spremeni splošno hitrost animacije (hitrejše ali počasnejše animacije)."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"upravljanje žetonov programa"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Programu omogoča, da ustvari in upravlja svoje žetone ter obide navadno razvrščanje Z. Tega ni treba nikoli uporabiti za navadne programe."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"zamrzovanje zaslona"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Omogoča aplikaciji začasno zamrznitev zaslona za prehod na celozaslonski način."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"pritiskanje tipk in gumbov za nadzor"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Programu omogoča, da svoje dogodke vnosa (pritiske tipk ipd.) dostavi drugim programom. Zlonamerni programi lahko s tem prevzamejo nadzor nad tabličnim računalnikom."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Programu omogoča, da svoje dogodke vnosa (pritiske tipk ipd.) dostavi drugim programom. Zlonamerni programi lahko s tem prevzamejo nadzor nad telefonom."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"neposredno nameščanje programov"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Programu omogoča namestitev novih ali posodobljenih paketov sistema Android. Zlonamerni programi lahko to uporabijo za dodajanje novih programov s poljubnimi zmogljivimi dovoljenji."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"brisanje vseh podatkov predpomnilnika programa"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Programu omogoča sproščanje pomnilnika tabličnega računalnika z brisanjem datotek v imeniku predpomnilnika telefona. Dostop je zelo omejen, navadno le na sistemske procese."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Programu omogoča sproščanje pomnilnika telefona z brisanjem datotek v imeniku predpomnilnika telefona. Dostop je zelo omejen, navadno le na sistemske procese."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Aplikaciji omogoča sproščanje pomnilnika v tabličnem računalniku, tako da izbriše imenike predpomnilnika drugih aplikacij. To lahko povzroči počasnejši zagon drugih aplikacij, saj morajo znova prenesti svoje podatke."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Aplikaciji omogoča sproščanje pomnilnika telefona, tako da izbriše datoteke v imenikih predpomnilnika drugih aplikacij. To lahko povzroči počasnejši zagon drugih aplikacij, saj morajo znova prenesti svoje podatke."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"premikanje sredstev programa"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Programu omogoča premikanje sredstev programa iz notranjih medijev v zunanje in obratno."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"branje občutljivih dnevniških podatkov"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Aplikaciji omogoča, da dostopa do dodatnih ukazov ponudnika lokacij. S tem lahko moti delovanje sistema GPS ali drugih virov lokacije."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"dovoljenje za namestitev ponudnika lokacije"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Ustvarjanje simuliranih virov lokacije za preverjanje ali namestitev novega ponudnika lokacije. S tem lahko aplikacija preglasi lokacijo in/ali stanje, ki ga vrnejo drugi viri lokacije, kot so GPS in ponudniki lokacij."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"natančna lokacija (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Dostop do virov za določitev natančne lokacije, kot je GPS v tabličnem računalniku. Ko so lokacijske storitve na voljo in vklopljene, lahko aplikacija s tem dovoljenjem natančno določi vašo lokacijo."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Dostop do virov za določitev natančne lokacije, kot je GPS v telefonu. Ko so lokacijske storitve na voljo in vklopljene, lahko aplikacija s tem dovoljenjem natančno določi vašo lokacijo."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"približna lokacija, ki temelji na omrežju"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Dostop do približne lokacije s pomočjo ponudnikov lokacij, ki uporabljajo omrežne vire, kot so bazne postaje in Wi-Fi. Ko so te lokacijske storitve na voljo in vklopljene, lahko aplikacija s tem dovoljenjem določi vašo približno lokacijo."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"natančna lokacija (na podlagi podatkov GPS in omrežja)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Aplikaciji omogoča, da določi vašo natančno lokacijo na podlagi sistema GPS ali omrežnih lokacijskih virov, kot so bazne postaje mobilne telefonije ali Wi-Fi. Te lokacijske storitve morajo biti vklopljene in na voljo v napravi, če želite, da jih aplikacija uporablja. Aplikacije lahko na podlagi tega določijo vašo lokacijo in še dodatno izpraznijo akumulator."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"približna lokacija (na podlagi omrežja)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Aplikaciji omogoča, da določi vašo približno lokacijo na podlagi lokacijskih storitev z omrežnimi lokacijskimi viri, kot so bazne postaje mobilne telefonije in Wi-Fi. Te lokacijske storitve morajo biti vklopljene in na voljo v napravi, če želite, da jih aplikacija uporablja. Aplikacije lahko na podlagi tega določijo vašo približno lokacijo."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"dostop do storitve SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Programu omogoča uporabo funkcij nizke ravni SurfaceFlinger."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"branje grafičnega/slikovnega medpomnilnika"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Programu omogoča branje vsebine grafičnega/slikovnega medpomnilnika."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"konfiguriranje zaslonov Wi-Fi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Omogoča aplikaciji konfiguriranje zaslonov Wi-Fi in povezovanje z njimi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"nadzor zaslonov Wi-Fi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Omogoča aplikaciji nadzor osnovnih funkcij zaslonov Wi-Fi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"spreminjanje nastavitev zvoka"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Aplikaciji omogoča spreminjanje splošnih zvočnih nastavitev, na primer glasnost in kateri zvočnik se uporablja."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"snemanje zvoka"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"dostop do nastavitev Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Programu omogoča konfiguriranje lokalnega tabličnega računalnika Bluetooth ter zaznavanje oddaljenih naprav in združevanje z njimi."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Programu omogoča konfiguriranje lokalnega telefona s tehnologijo Bluetooth ter odkrivanje oddaljenih naprav in povezovanje z njimi."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Prikaz povezav WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"vzpostavitev povezave z omrežjem WiMax in prekinitev povezave z njim"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Aplikaciji omogoča, da ugotovi, ali je WiMAX omogočen, in ogled podatkov o povezanih omrežjih WiMAX."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Sprememba stanja omrežja WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Aplikaciji omogoča, da vzpostavi povezavo med tabličnim računalnikom in omrežjem WiMAX ter jo prekine."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Programu omogoča spreminjanje trenutno sinhroniziranih virov. Zlonamerni programi lahko s tem spremenijo sinhronizirane vire."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"branje izrazov, ki ste jih dodali v slovar"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Aplikaciji omogoča, da prebere vse besede, imena in besedne zveze, ki jih je uporabnik morda shranil v uporabniški slovar."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"pisanje v uporabniško določen slovar"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"dodajanje besed v uporabniški slovar"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Programu omogoča pisanje nove besede v uporabniški slovar."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"preskus dostopa do zaščitene shrambe"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"preskus dostopa do zaščitene shrambe"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Aplikaciji omogoča preskušanje dovoljenja za pomnilnik USB, ki bo na voljo v prihodnjih napravah."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Aplikaciji omogoča preskušanje dovoljenja za shrambo USB, ki bo na voljo v prihodnjih napravah."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Aplikaciji omogoča preskušanje dovoljenja za kartico SD, ki bo na voljo v prihodnjih napravah."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"spr. ali bris. vseb. pomn. USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"spreminjanje ali brisanje vsebine kartice SD"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Programu omogoča pisanje na kartico SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"spreminjanje/brisanje vsebine notranje shrambe nosilca podatkov"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Programu omogoča spreminjanje vsebine notranje shrambe nosilca podatkov."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"dostop do zunanje naprave za shranjevanje za vse uporabnike"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Aplikaciji omogoča dostop do zunanje naprave za shranjevanje za vse uporabnike."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"dostop do datotečnega sistema predpomnilnika"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Programu omogoča branje in pisanje v datotečni sistem predpomnilnika."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"opravljanje/sprejemanje internetnih klicev"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Shranjeni podatki programa morajo biti šifrirani."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Onemogoči fotoaparate"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Prepreči uporabo vseh fotoaparatov v napravi."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Onemogočanje funkcij tipkov."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Preprečitev uporabe nekaterih funkcij tipkovnice."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Začetna stran"</item>
     <item msgid="869923650527136615">"Mobilni"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Poskusite znova"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Presegli ste dovoljeno število poskusov odklepanja z obrazom"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Polnjenje (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Napolnjeno."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Napolnjeno"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Priključite napajalnik."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Ni kartice SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Ni kartice SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"V tabličnem računalniku ni kartice SIM."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"V telefonu ni kartice SIM."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Vstavite kartico SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Vzorec je izbrisan"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Celica je dodana"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Vzorec je končan"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Dodajanje pripomočka."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Prazno"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Območje odklepanja razširjeno."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Območje odklepanja strnjeno."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Pripomoček <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Izbirnik uporabnika"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Stanje"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Fotoaparat"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Kontrolniki predstavnosti"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Prerazporejanje pripomočkov začeto."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Prerazporejanje pripomočkov končano."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Pripomoček <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> izbrisan."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Razširitev območja odklepanja."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Odklepanje s podrsanjem."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Odklepanje z vzorcem."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Odklepanje z obrazom."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Odklepanje s kodo PIN."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Odklepanje z geslom."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Območje vzorca."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Območje podrsanja."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopiraj URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Izbira besedila"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Izbrano besedilo"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"dodaj v slovar"</string>
-    <string name="deleteText" msgid="7070985395199629156">"izbriši"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Dodaj v slovar"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Izbriši"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Način vnosa"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Besedilna dejanja"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Prostor za shranjevanje bo pošel"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Odpiranje razpoložljivih brezžičnih omrežij"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Prijava v omrežje Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Prijava v omrežje"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Z omrežjem Wi-Fi se ni mogoče povezati"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ima slabo internetno povezavo."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Za:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Vnesite zahtevano kodo PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefon bo začasno prekinil povezavo z Wi-Fi-jem, ko je povezan z napravo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Vstavljanje znaka"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Pošiljanje sporočil SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pošilja veliko SMS-ov. Ali želite dovoliti, da jih še naprej pošilja?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Dovoli"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Zavrni"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; želi poslati sporočilo na &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"S tem bo "<font fgcolor="#ffffb060">"morda bremenjen"</font>" vaš račun za mobilno napravo."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"S tem bo bremenjen vaš račun za mobilno napravo."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Pošlji"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Prekliči"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Zapomni si mojo izbiro"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"To lahko pozneje spremenite v Nastavitve &gt; Aplikacije"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Vedno dovoli"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nikoli ne dovoli"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Kartica SIM odstranjena"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mobilno omrežje ne bo na voljo, dokler naprave vnovič ne zaženete z veljavno kartico SIM."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Dokončano"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Nastavi datum"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Nastavi"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Končano"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Privzeto"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Ni zahtevanih dovoljenj"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Skrij"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Pokaži vse"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NOVO: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NOVO: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Zagotavlja aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Ni zahtevanih dovoljenj"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"to je lahko plačljivo"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Masovni pomnilnik USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Povezava USB je vzpostavljena"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Z računalnikom ste vzpostavili povezavo z USB-jem. Dotaknite se spodnjega gumba, če želite kopirati datoteke med računalnikom in pomnilnikom USB v Androidu."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN je aktiviral program <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotaknite se, če želite upravljati omrežje."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Vzpostavljena povezava s sejo <xliff:g id="SESSION">%s</xliff:g>. Dotaknite se, če želite upravljati omrežje."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Povezovanje v stalno vklopljeno navidezno zasebno omrežje ..."</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Vzpostavljena povezava v stalno vklopljeno navidezno zasebno omrežje"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Napaka stalno vklopljenega navideznega zasebnega omrežja"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Dotaknite se, da ponastavite povezavo"</string>
     <string name="upload_file" msgid="2897957172366730416">"Izberi datoteko"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nobena datoteka ni izbrana"</string>
     <string name="reset" msgid="2448168080964209908">"Ponastavi"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Deli z dr."</string>
     <string name="find" msgid="4808270900322985960">"Najdi"</string>
     <string name="websearch" msgid="4337157977400211589">"Spletno iskanje"</string>
+    <string name="find_next" msgid="5742124618942193978">"Najdi naslednje"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Najdi prejšnje"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Zahteva za lokacijo uporabnika <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Zahteva za lokacijo"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Zahtevala oseba <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Slušalke"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Zvočniki stojala"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Zvok HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Zvok prek Bluetootha"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Končano"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Izhod predstavnosti"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Pregledovanje ..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Vzpostavljanje povezave ..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Na voljo"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Ni na voljo"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Vgrajen zaslon"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Zaslon HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Prekrivanje #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> pik na palec"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Brezžični zaslon je povezan"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Ta zaslon je prikazan v drugi napravi"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Prekini povezavo"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Klic v sili"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Pozabljen vzorec"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Napačen vzorec"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Napačno geslo"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Napačen PIN"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Čez <xliff:g id="NUMBER">%d</xliff:g> sekund poskusite znova."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Narišite vzorec"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Vnesite PIN za kartico SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Vnesite PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Vnesite geslo"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"Kartica SIM je onemogočena. Če želite nadaljevati, vnesite kodo PUK. Za dodatne informacije se obrnite na operaterja."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Vnesite želeno kodo PIN"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Potrdite želeno kodo PIN"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Odklepanje kartice SIM ..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Napačna koda PIN."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Vnesite PIN, ki vsebuje od štiri do osem številk."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Koda PUK mora vsebovati 8 ali več števk."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Vnovič vnesite pravilno kodo PUK. Večkratni poskusi bodo trajno onemogočili kartico SIM."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Kodi PIN se ne ujemata"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Preveč poskusov vzorca"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Če želite odkleniti napravo, se prijavite z Google Računom."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Uporabniško ime (e-pošta)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Geslo"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Prijava"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Neveljavno uporabniško ime ali geslo."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Ali ste pozabili uporabniško ime ali geslo?"\n"Obiščite "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Preverjanje računa ..."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"PIN ste <xliff:g id="NUMBER_0">%d</xliff:g>-krat vnesli napačno. "\n\n"Znova poskusite čez <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Geslo ste <xliff:g id="NUMBER_0">%d</xliff:g>-krat vnesli napačno. "\n\n"Znova poskusite čez <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Vzorec za odklepanje ste nepravilno narisali <xliff:g id="NUMBER_0">%d</xliff:g>-krat. "\n\n"Poskusite znova čez <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Tablični računalnik ste poskusili <xliff:g id="NUMBER_0">%d</xliff:g>-krat napačno odkleniti. Če poskusite še <xliff:g id="NUMBER_1">%d</xliff:g>-krat in ne uspete, bo ponastavljen na privzete tovarniške nastavitve in vsi uporabniški podatki bodo izgubljeni."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Telefon ste poskusili <xliff:g id="NUMBER_0">%d</xliff:g>-krat napačno odkleniti. Če poskusite še <xliff:g id="NUMBER_1">%d</xliff:g>-krat in ne uspete, bo ponastavljen na privzete tovarniške nastavitve in vsi uporabniški podatki bodo izgubljeni."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Tablični računalnik ste poskusili <xliff:g id="NUMBER">%d</xliff:g>-krat napačno odkleniti, zato bo ponastavljen na privzete tovarniške nastavitve."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Telefon ste poskusili <xliff:g id="NUMBER">%d</xliff:g>-krat napačno odkleniti, zato bo ponastavljen na privzete tovarniške nastavitve."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%d</xliff:g>-krat napačno vnesli. Po nadaljnjih <xliff:g id="NUMBER_1">%d</xliff:g> neuspešnih poskusih boste pozvani, da tablični računalnik odklenete z e-poštnim računom."\n\n"Poskusite znova čez <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%d</xliff:g>-krat napačno vnesli. Po nadaljnjih <xliff:g id="NUMBER_1">%d</xliff:g> neuspešnih poskusih boste pozvani, da odklenete telefon z Googlovimi podatki za prijavo."\n\n"Poskusite znova čez <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Odstrani"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Želite povečati glasnost nad varno raven?"\n"Dolgotrajna izpostavljenost glasnim tonom lahko poškoduje sluh."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Če želite omogočiti pripomočke za ljudi s posebnimi potrebami, na zaslonu pridržite z dvema prstoma."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Pripomočki za ljudi s posebnimi potrebami so omogočeni."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Omogočanje pripomočkov za ljudi s posebnimi potrebami preklicano."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Trenutni uporabnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Lastnik"</string>
 </resources>
diff --git a/core/res/res/values-sr-rRS/donottranslate-cldr.xml b/core/res/res/values-sr-rRS/donottranslate-cldr.xml
index 7168bcc..996c75e 100644
--- a/core/res/res/values-sr-rRS/donottranslate-cldr.xml
+++ b/core/res/res/values-sr-rRS/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">јануар</string>
-    <string name="month_long_standalone_february">фебруар</string>
-    <string name="month_long_standalone_march">март</string>
-    <string name="month_long_standalone_april">април</string>
-    <string name="month_long_standalone_may">мај</string>
-    <string name="month_long_standalone_june">јун</string>
-    <string name="month_long_standalone_july">јул</string>
-    <string name="month_long_standalone_august">август</string>
-    <string name="month_long_standalone_september">септембар</string>
-    <string name="month_long_standalone_october">октобар</string>
-    <string name="month_long_standalone_november">новембар</string>
-    <string name="month_long_standalone_december">децембар</string>
-
-    <string name="month_long_january">јануар</string>
-    <string name="month_long_february">фебруар</string>
-    <string name="month_long_march">март</string>
-    <string name="month_long_april">април</string>
-    <string name="month_long_may">мај</string>
-    <string name="month_long_june">јун</string>
-    <string name="month_long_july">јул</string>
-    <string name="month_long_august">август</string>
-    <string name="month_long_september">септембар</string>
-    <string name="month_long_october">октобар</string>
-    <string name="month_long_november">новембар</string>
-    <string name="month_long_december">децембар</string>
-
-    <string name="month_medium_january">јан</string>
-    <string name="month_medium_february">феб</string>
-    <string name="month_medium_march">мар</string>
-    <string name="month_medium_april">апр</string>
-    <string name="month_medium_may">мај</string>
-    <string name="month_medium_june">јун</string>
-    <string name="month_medium_july">јул</string>
-    <string name="month_medium_august">авг</string>
-    <string name="month_medium_september">сеп</string>
-    <string name="month_medium_october">окт</string>
-    <string name="month_medium_november">нов</string>
-    <string name="month_medium_december">дец</string>
-
-    <string name="month_shortest_january">ј</string>
-    <string name="month_shortest_february">ф</string>
-    <string name="month_shortest_march">м</string>
-    <string name="month_shortest_april">а</string>
-    <string name="month_shortest_may">м</string>
-    <string name="month_shortest_june">ј</string>
-    <string name="month_shortest_july">ј</string>
-    <string name="month_shortest_august">а</string>
-    <string name="month_shortest_september">с</string>
-    <string name="month_shortest_october">о</string>
-    <string name="month_shortest_november">н</string>
-    <string name="month_shortest_december">д</string>
-
-    <string name="day_of_week_long_sunday">недеља</string>
-    <string name="day_of_week_long_monday">понедељак</string>
-    <string name="day_of_week_long_tuesday">уторак</string>
-    <string name="day_of_week_long_wednesday">среда</string>
-    <string name="day_of_week_long_thursday">четвртак</string>
-    <string name="day_of_week_long_friday">петак</string>
-    <string name="day_of_week_long_saturday">субота</string>
-
-    <string name="day_of_week_medium_sunday">нед</string>
-    <string name="day_of_week_medium_monday">пон</string>
-    <string name="day_of_week_medium_tuesday">уто</string>
-    <string name="day_of_week_medium_wednesday">сре</string>
-    <string name="day_of_week_medium_thursday">чет</string>
-    <string name="day_of_week_medium_friday">пет</string>
-    <string name="day_of_week_medium_saturday">суб</string>
-
-    <string name="day_of_week_short_sunday">нед</string>
-    <string name="day_of_week_short_monday">пон</string>
-    <string name="day_of_week_short_tuesday">уто</string>
-    <string name="day_of_week_short_wednesday">сре</string>
-    <string name="day_of_week_short_thursday">чет</string>
-    <string name="day_of_week_short_friday">пет</string>
-    <string name="day_of_week_short_saturday">суб</string>
-
-    <string name="day_of_week_shortest_sunday">н</string>
-    <string name="day_of_week_shortest_monday">п</string>
-    <string name="day_of_week_shortest_tuesday">у</string>
-    <string name="day_of_week_shortest_wednesday">с</string>
-    <string name="day_of_week_shortest_thursday">ч</string>
-    <string name="day_of_week_shortest_friday">п</string>
-    <string name="day_of_week_shortest_saturday">с</string>
-
-    <string name="am">пре подне</string>
-    <string name="pm">поподне</string>
-    <string name="yesterday">јуче</string>
-    <string name="today">данас</string>
-    <string name="tomorrow">сутра</string>
-
     <string name="hour_minute_24">%H.%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
diff --git a/core/res/res/values-sr/donottranslate-cldr.xml b/core/res/res/values-sr/donottranslate-cldr.xml
index 7426bdc..7fca1a2 100644
--- a/core/res/res/values-sr/donottranslate-cldr.xml
+++ b/core/res/res/values-sr/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">јануар</string>
-    <string name="month_long_standalone_february">фебруар</string>
-    <string name="month_long_standalone_march">март</string>
-    <string name="month_long_standalone_april">април</string>
-    <string name="month_long_standalone_may">мај</string>
-    <string name="month_long_standalone_june">јун</string>
-    <string name="month_long_standalone_july">јул</string>
-    <string name="month_long_standalone_august">август</string>
-    <string name="month_long_standalone_september">септембар</string>
-    <string name="month_long_standalone_october">октобар</string>
-    <string name="month_long_standalone_november">новембар</string>
-    <string name="month_long_standalone_december">децембар</string>
-
-    <string name="month_long_january">јануар</string>
-    <string name="month_long_february">фебруар</string>
-    <string name="month_long_march">март</string>
-    <string name="month_long_april">април</string>
-    <string name="month_long_may">мај</string>
-    <string name="month_long_june">јун</string>
-    <string name="month_long_july">јул</string>
-    <string name="month_long_august">август</string>
-    <string name="month_long_september">септембар</string>
-    <string name="month_long_october">октобар</string>
-    <string name="month_long_november">новембар</string>
-    <string name="month_long_december">децембар</string>
-
-    <string name="month_medium_january">јан</string>
-    <string name="month_medium_february">феб</string>
-    <string name="month_medium_march">мар</string>
-    <string name="month_medium_april">апр</string>
-    <string name="month_medium_may">мај</string>
-    <string name="month_medium_june">јун</string>
-    <string name="month_medium_july">јул</string>
-    <string name="month_medium_august">авг</string>
-    <string name="month_medium_september">сеп</string>
-    <string name="month_medium_october">окт</string>
-    <string name="month_medium_november">нов</string>
-    <string name="month_medium_december">дец</string>
-
-    <string name="month_shortest_january">ј</string>
-    <string name="month_shortest_february">ф</string>
-    <string name="month_shortest_march">м</string>
-    <string name="month_shortest_april">а</string>
-    <string name="month_shortest_may">м</string>
-    <string name="month_shortest_june">ј</string>
-    <string name="month_shortest_july">ј</string>
-    <string name="month_shortest_august">а</string>
-    <string name="month_shortest_september">с</string>
-    <string name="month_shortest_october">о</string>
-    <string name="month_shortest_november">н</string>
-    <string name="month_shortest_december">д</string>
-
-    <string name="day_of_week_long_sunday">недеља</string>
-    <string name="day_of_week_long_monday">понедељак</string>
-    <string name="day_of_week_long_tuesday">уторак</string>
-    <string name="day_of_week_long_wednesday">среда</string>
-    <string name="day_of_week_long_thursday">четвртак</string>
-    <string name="day_of_week_long_friday">петак</string>
-    <string name="day_of_week_long_saturday">субота</string>
-
-    <string name="day_of_week_medium_sunday">нед</string>
-    <string name="day_of_week_medium_monday">пон</string>
-    <string name="day_of_week_medium_tuesday">уто</string>
-    <string name="day_of_week_medium_wednesday">сре</string>
-    <string name="day_of_week_medium_thursday">чет</string>
-    <string name="day_of_week_medium_friday">пет</string>
-    <string name="day_of_week_medium_saturday">суб</string>
-
-    <string name="day_of_week_short_sunday">нед</string>
-    <string name="day_of_week_short_monday">пон</string>
-    <string name="day_of_week_short_tuesday">уто</string>
-    <string name="day_of_week_short_wednesday">сре</string>
-    <string name="day_of_week_short_thursday">чет</string>
-    <string name="day_of_week_short_friday">пет</string>
-    <string name="day_of_week_short_saturday">суб</string>
-
-    <string name="day_of_week_shortest_sunday">н</string>
-    <string name="day_of_week_shortest_monday">п</string>
-    <string name="day_of_week_shortest_tuesday">у</string>
-    <string name="day_of_week_shortest_wednesday">с</string>
-    <string name="day_of_week_shortest_thursday">ч</string>
-    <string name="day_of_week_shortest_friday">п</string>
-    <string name="day_of_week_shortest_saturday">с</string>
-
-    <string name="am">пре подне</string>
-    <string name="pm">поподне</string>
-    <string name="yesterday">јуче</string>
-    <string name="today">данас</string>
-    <string name="tomorrow">сутра</string>
-
     <string name="hour_minute_24">%H.%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index fd337a3..5a94aad 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Опције телефона"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Закључај екран"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Искључи"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Извештај о грешци"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Направи извештај о грешци"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Овим ће се прикупити информације о тренутном стању уређаја како би биле послате у поруци е-поште. Од започињања извештаја о грешци до тренутка за његово слање проћи ће неко време; будите стрпљиви."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Нечујни режим"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Звук је ИСКЉУЧЕН"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Звук је УКЉУЧЕН"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Поруке"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Читање и писање SMS порука, порука е-поште и осталих порука."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Личне информације"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Директни приступ контактима и календарима сачуваним на таблету."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Директни приступ контактима и календару сачуваним на телефону."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Директан приступ информацијама о вама, ускладиштеним на контакт картици."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Информације са друштвених мрежа"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Директан приступ информацијама о контактима и друштвеним везама."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Локација"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Надгледајте своју физичку локацију."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Комуникација преко мреже"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Приступајте разним функцијама мреже."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Приступање уређајима и мрежама преко Bluetooth-а."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Аудио подешавања"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Промена аудио подешавања."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Утицај на батерију"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Коришћење функција које могу брзо да истроше батерију."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Календар"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Директан приступ календару и догађајима."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Читање речника корисника"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Читање речи у речнику корисника."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Уписивање у речник корисника"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Додавање речи у речник корисника."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Обележивачи и историја"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Директан приступ обележивачима и историји прегледача."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Аларм"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Подешавање будилника."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Говорна пошта"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Директан приступ говорној пошти."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Микрофон"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Директан приступ микрофону за снимање звука."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Камера"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Директан приступ камери за снимање слика или видео снимака."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Информације о апликацијама"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Способност да се утиче на понашање других апликација на уређају."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Позадина"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Промена подешавања позадине уређаја."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Сат"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Промена времена или временске зоне уређаја."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Статусна трака"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Промена подешавања статусне траке уређаја."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Подешавања синхронизације"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Приступ подешавањима синхронизације."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Налози"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Приступ доступним налозима."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Контроле хардвера"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Нижи нивои приступа и контроле система."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Алатке за програмирање"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Функције потребне само програмерима апликација."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Кориснички интерфејс других апликација"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Утицај на кориснички интерфејс других апликација."</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>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Дозвољава апликацији да прима и обрађује WAP поруке. Ова дозвола укључује могућност праћења или брисања порука које вам се шаљу, а које вам се не приказују."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"преузимање покренутих апликација"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Дозвољава апликацији да преузима информације о актуелним и недавно покренутим задацима. Ово може да омогући апликацији да открије информације о томе које се апликације користе на уређају."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"интеракција између корисника"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Дозвољава апликацији да обавља радње између различитих корисника на уређају. Злонамерне апликације могу да користе ово да би угрозиле заштиту између корисника."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"пуна лиценца за интеракцију између корисника"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Дозвољава све могуће интеракције између корисника."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"управљање корисницима"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Дозвољава апликацијама да управљају корисницима на уређају, укључујући постављање упита, прављење и брисање."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"преузимање детаља о покренутим апликацијама"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Дозвољава апликацији да преузима детаљне информације о актуелним и недавно покренутим задацима. Злонамерне апликације могу да открију приватне информације о другим апликацијама."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"промена редоследа покренутих апликација"</string>
@@ -243,6 +287,14 @@
     <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="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"привремено омогућавање приступачности"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Дозвољава апликацији да привремено омогући приступачност на уређају. Злонамерне апликације могу да омогуће приступачност без дозволе корисника."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"преузимање информација о прозорима"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Омогућава апликацији да преузме информације о прозорима од менаџера прозора. Злонамерне апликације могу да преузму информације које су намењене за интерну употребу система."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"филтрирање догађаја"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Омогућава апликацији да региструје филтер улазног садржаја који филтрира стрим свих догађаја корисника пре њиховог слања. Злонамерна апликација може да контролише кориснички интерфејс система без интервенције корисника."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"увеличавање екрана"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Дозвољава апликацији да увеличава садржај екрана. Злонамерне апликације могу да промене садржај екрана до те мере да уређај постаје неупотребљив."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"делимично искључивање"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Ставља менаџера активности у стање искључивања. Не искључује га у потпуности."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"спречавање пребацивања са једне апликације на другу"</string>
@@ -254,13 +306,15 @@
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"слање емитовања примљених путем SMS порука"</string>
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Дозвољава апликацији да емитује обавештење да је SMS порука примљена. Злонамерне апликације на тај начин могу да фалсификују долазне SMS поруке."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"слање примљених PUSH емитовања преко WAP-а"</string>
-    <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Дозвољава апликацији да емитује обавештење да је примљена PUSH порука преко WAP-а. Злонамерне апликације то могу да искористе да фалсификују пријем MMS порука или да кришом замене садржај било које веб странице уносом злонамерног садржаја."</string>
+    <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Дозвољава апликацији да емитује обавештење да је примљена PUSH порука преко WAP-а. Злонамерне апликације то могу да искористе да фалсификују пријем MMS порука или да кришом замене садржај било које веб-странице уносом злонамерног садржаја."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"ограничење броја покренутих процеса"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Дозвољава апликацији да управља максималним бројем процеса који ће моћи да се покрену. Никада није потребна уобичајеним апликацијама."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"принудно затварање позадинских апликација"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Дозвољава апликацији да управља тиме да ли ће се активности увек окончати чим пређу у позадину. Уобичајене апликације је никада не користе."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"измена статистике о батерији"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Дозвољава апликацији да измени прикупљену статистику о батерији. Не користе је уобичајене апликације."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"читање статистике о батерији"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Дозвољава апликацији да чита опште податке о тренутној употреби батерије на измаку. Можда ће апликацији дозволити да сазна детаљне информације о томе које апликације користите."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"измена статистике о батерији"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Дозвољава апликацији да мења прикупљену статистику о батерији. Не користе је обичне апликације."</string>
     <string name="permlab_backup" msgid="470013022865453920">"контрола резервне копије система и враћање почетних вредности"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Дозвољава апликацији да управља системским механизмом за прављење резервне копије и враћање. Не користе је уобичајене апликације."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"потврда прављења пуне резервне копије или операције враћања"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"приказ неовлашћених прозора"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Дозвољава апликацији да прави прозоре које ће користити кориснички интерфејс интерног система. Не користе је уобичајене апликације."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"превлачење преко других апликација"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Дозвољава апликацији да приказује прозоре са системским упозорењима. Неки прозори са упозорењима могу да преузму цео екран."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Дозвољава апликацији да се приказује преко других апликација или делова корисничког интерфејса. То може да омета употребу интерфејса при раду са другим апликацијама, а може и да измени ставке које видите на екрану у другим апликацијама."</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="permlab_freezeScreen" msgid="4708181184441880175">"замрзавање екрана"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Дозвољава апликацији да привремено замрзне екран ради преласка на цео екран."</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>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"директно инсталирање апликација"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Дозвољава апликацији да инсталира нове или ажуриране Android пакете. Злонамерне апликације на тај начин могу да додају нове апликације са произвољно снажним дозволама."</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="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Дозвољава апликацији да ослободи меморију таблета брисањем датотека из директоријума кеша других апликација. То може да доведе до споријег покретања других апликација јер ће поново морати да преузимају податке."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Дозвољава апликацији да ослободи меморију телефона брисањем датотека из директоријума кеша других апликација. То може да доведе до споријег покретања других апликација јер ће поново морати да преузимају податке."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"премештање ресурса апликације"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Дозвољава апликацији да премешта ресурсе апликације са интерног на екстерни медијум и обратно."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"читање поверљивих података из евиденције"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Дозвољава апликацији да приступа додатним командама добављача локације. Ово може да омогући апликацији да омета рад GPS уређаја или других извора локације."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"дозвола за инсталирање добављача локације"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Прављење лажних извора локација у сврху тестирања или инсталирање новог добављача локације. Ово омогућава апликацији да замени локацију и/или статус који пријављују други извори локација, као што су GPS или добављачи локације."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"прецизна (GPS) локација"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Приступ изворима прецизне локације као што је систем глобалног позиционирања на таблету. Када су услуге локације доступне и укључене, ова дозвола омогућава апликацији да утврди вашу прецизну локацију."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Приступ изворима прецизне локације као што је систем глобалног позиционирања на телефону. Када су услуге локације доступне и укључене, ова дозвола омогућава апликацији да утврди вашу прецизну локацију."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"приближна локација (заснована на мрежи)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Приступ приближној локацији преко добављача локације помоћу извора мреже као што су мобилни предајник и Wi-Fi. Када су ове услуге локације доступне и укључене, ова дозвола омогућава апликацији да утврди вашу приближну локацију."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"прецизна локација (заснована на GPS-у и мрежи)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Дозвољава апликацији да преузме прецизне податке о вашој локацији помоћу глобалног система позиционирања (GPS) или мрежних извора локација као што су мобилни предајници и Wi-Fi мреже. Ове услуге лоцирања морају да буду укључене и доступне уређају да би апликација могла да их користи. Апликације на основу овога могу да одреде где се приближно налазите и могу додатно да троше батерију."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"приближна локација (заснована на мрежи)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Дозвољава апликацији да преузме податке о вашој приближној локацији. Податке о овој локацији обезбеђују услуге лоцирања помоћу мрежних извора локација као што су мобилни предајници и Wi-Fi мреже. Ове услуге лоцирања морају да буду укључене и доступне уређају да би апликација могла да их користи. Апликације на основу овога могу да одреде где се приближно налазите."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"приступ функцији 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="permlab_configureWifiDisplay" msgid="5595661694746742168">"конфигурисање Wi-Fi екрана"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Дозвољава апликацији да конфигурише Wi-Fi екране и повезује се са њима."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"контрола Wi-Fi екрана"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Дозвољава апликацији да контролише функције Wi-Fi екрана ниског нивоа."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"промена аудио подешавања"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Дозвољава апликацији да мења глобална аудио подешавања као што су јачина звука и избор звучника који се користи као излаз."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"снимање аудио записа"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"приступ Bluetooth подешавањима"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Дозвољава апликацији да конфигурише локални Bluetooth таблет, као и да открије даљинске уређаје и упари се са њима."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Дозвољава апликацији да конфигурише локални Bluetooth телефон, као и да открије даљинске уређаје и упари се са њима."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Преглед WiMAX веза"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"повезивање и прекид везе са WiMAX-ом"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Дозвољава апликацији да утврди да ли је WiMAX омогућен, као и информације о било којим повезаним WiMAX мрежама."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Промени WiMAX статус"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Дозвољава апликацији да повезује таблет са WiMAX мрежама и прекида везе са њима."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Дозвољава апликацији да измени тренутно синхронизоване фидове. Злонамерне апликације могу да промене синхронизоване фидове."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"читање термина које сте додали у речник"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Дозвољава апликацији да чита све речи, називе и фразе које је корисник можда сачувао у корисничком речнику."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"уписивање у речник који је дефинисао корисник"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"додавање речи у речник корисника"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Дозвољава апликацији да уписује нове речи у кориснички речник."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"тестирање приступа заштићеној меморији"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"тестирање приступа заштићеној меморији"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Дозвољава апликацији да тестира дозволу за USB меморију која ће бити доступна на будућим уређајима."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Дозвољава апликацији да тестира дозволу за USB меморију која ће бити доступна на будућим уређајима."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Дозвољава апликацији да тестира дозволу за SD картицу која ће бити доступна на будућим уређајима."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"измена или брисање садржаја USB меморије"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"мењање или брисање садржаја SD картице"</string>
@@ -534,6 +593,8 @@
     <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="permlab_sdcardAccessAll" msgid="8150613823900460576">"приступ спољној меморији свих корисника"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Дозвољава апликацији да приступа спољној меморији за све кориснике."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"приступ систему датотека кеша"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Дозвољава апликацији да чита систем датотека кеша и уписује податке у њега."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"упућивање/пријем Интернет позива"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Захтева да сачувани подаци апликације буду шифровани."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Онемогућавање камера"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Спречите коришћење свих камера уређаја."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Онемогућавање функција закључавања тастатуре."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Спречавање неких функција закључавања тастатуре."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Кућа"</item>
     <item msgid="869923650527136615">"Мобилни"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Покушајте поново"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Премашен је највећи дозвољени број покушаја Откључавања лицем"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Пуњење, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Батерија је напуњена."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Напуњено"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Повежите пуњач."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Нема SIM картице."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Нема SIM картице"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"У таблету нема SIM картице."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"У телефон није уметнута SIM картица."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Уметните SIM картицу."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Образац је обрисан"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Ћелија је додата"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Образац је довршен"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Додај виџет."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Празно"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Област откључавања је проширена."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Област откључавања је скупљена."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Виџет <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Избор корисника"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Статус"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Камера"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Контроле за медије"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Започела је промена редоследа виџета."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Промена редоследа виџета је завршена."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Виџет <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> је избрисан."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Прошири област откључавања."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Откључавање превлачењем."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Откључавање шаблоном."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Откључавање лицем."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Откључавање PIN-ом."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Откључавање лозинком."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Област шаблона."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Област превлачења."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Копирај URL адресу"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Изабери текст"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Избор текста"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"додај у речник"</string>
-    <string name="deleteText" msgid="7070985395199629156">"избриши"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Додај у речник"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Избриши"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Метод уноса"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Радње у вези са текстом"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Простор за складиштење је на измаку"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Доступне су отворене Wi-Fi мреже"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Пријавите се на Wi-Fi мрежу"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Пријављивање на мрежу"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Није било могуће повезати са Wi-Fi мрежом"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" има лошу интернет везу."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Коме:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Унесите потребни PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Телефон ће привремено прекинути везу са Wi-Fi-јем док је повезан са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Уметање знака"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Слање SMS порука"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; шаље велики број SMS порука. Желите ли да дозволите овој апликацији да настави са слањем порука?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Дозволи"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Одбиј"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; жели да пошаље поруку на адресу &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Ово "<font fgcolor="#ffffb060">"може да изазове трошкове"</font>" на налогу за мобилни уређај."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Ово ће изазвати трошкове на налогу за мобилни уређај."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Пошаљи"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Откажи"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Запамти мој избор"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Ово можете да промените касније у Подешавања &gt; Апликације"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Увек дозволи"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Никада не дозволи"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM картица је уклоњена"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Мобилна мрежа неће бити доступна док не покренете систем поново уз уметање важеће SIM картице."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Подешавање датума"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Подеси"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Готово"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Подразумевано"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Није потребна ниједна дозвола"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Сакриј"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Прикажи све"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"НОВО: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"НОВО: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Омогућава <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Није потребна ниједна дозвола"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"ово ће вам можда бити наплаћено"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB великог капацитета"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB је повезан"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Повезали сте рачунар преко USB-а. Додирните дугме испод ако желите да копирате датотеке са рачунара у Android USB меморију и обрнуто."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"Апликација <xliff:g id="APP">%s</xliff:g> је активирала VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Додирните да бисте управљали мрежом."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Повезано са сесијом <xliff:g id="SESSION">%s</xliff:g>. Додирните да бисте управљали мрежом."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Повезивање стално укљученог VPN-а..."</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Стално укључени VPN је повезан"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Грешка стално укљученог VPN-а"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Додирните да бисте ресетовали везу"</string>
     <string name="upload_file" msgid="2897957172366730416">"Одабери датотеку"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Није изабрана ниједна датотека"</string>
     <string name="reset" msgid="2448168080964209908">"Поново постави"</string>
@@ -1184,7 +1280,9 @@
     <string name="media_unknown_state" msgid="729192782197290385">"Екстерни медиј непознатог статуса."</string>
     <string name="share" msgid="1778686618230011964">"Дели"</string>
     <string name="find" msgid="4808270900322985960">"Пронађи"</string>
-    <string name="websearch" msgid="4337157977400211589">"Веб претрага"</string>
+    <string name="websearch" msgid="4337157977400211589">"Веб-претрага"</string>
+    <string name="find_next" msgid="5742124618942193978">"Пронађи следеће"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Пронађи претходно"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Захтев за локацију од корисника <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Захтев за локацију"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Захтева <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Телефон"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Слушалице"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Звучници базне станице"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI аудио"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Систем"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth аудио"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Готово"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Излаз медија"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Скенирање..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Повезивање..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Доступна"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Нису доступне"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Уграђени екран"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI екран"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Постављени елемент бр. <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>×<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Бежични екран је повезан"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Овај екран се приказује на другом уређају"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Прекини везу"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Хитни позив"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Заборављени шаблон"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Погрешан шаблон"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Погрешна лозинка"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Погрешан PIN"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Покушајте поново за <xliff:g id="NUMBER">%d</xliff:g> секунде(и)."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Нацртајте шаблон"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Унесите PIN SIM картице"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Унесите PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Унесите лозинку"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM картица је сада онемогућена. Унесите PUK кôд да бисте наставили. За детаље контактирајте оператера."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Унесите жељени PIN кôд"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Потврдите жељени PIN кôд"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Откључавање SIM картице…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"PIN кôд је нетачан."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Унесите PIN који има од 4 до 8 бројева."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK кôд треба да има 8 или више бројева."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Поново унесите исправни PUK кôд. Поновљени покушаји ће трајно онемогућити SIM."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN кодови се не подударају"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Превише покушаја уноса шаблона"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Да бисте откључали, пријавите се помоћу Google налога."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Корисничко име (адреса е-поште)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Лозинка"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Пријави ме"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Неважеће корисничко име или лозинка."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Заборавили сте корисничко име или лозинку?"\n"Посетите адресу "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Провера налога…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Унели сте PIN неисправно <xliff:g id="NUMBER_0">%d</xliff:g> пута. "\n\n"Покушајте поново за <xliff:g id="NUMBER_1">%d</xliff:g> секунде(и)."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Унели сте лозинку неисправно <xliff:g id="NUMBER_0">%d</xliff:g> пута. "\n\n"Покушајте поново за <xliff:g id="NUMBER_1">%d</xliff:g> секунде(и)."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Нацртали сте шаблон за откључавање неисправно <xliff:g id="NUMBER_0">%d</xliff:g> пута. "\n\n"Покушајте поново за <xliff:g id="NUMBER_1">%d</xliff:g> секунде(и)."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Покушали сте да откључате таблет неисправно <xliff:g id="NUMBER_0">%d</xliff:g> пута. Након још <xliff:g id="NUMBER_1">%d</xliff:g> неуспешна(их) покушаја таблет ће бити враћен на подразумевана фабричка подешавања и сви кориснички подаци ће бити изгубљени."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Покушали сте да откључате телефон неисправно <xliff:g id="NUMBER_0">%d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%d</xliff:g> неуспешна(их) покушаја телефон ће бити враћен на подразумевана фабричка подешавања и сви кориснички подаци ће бити изгубљени."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Покушали сте да откључате таблет неисправно <xliff:g id="NUMBER">%d</xliff:g> пута. Таблет ће сада бити враћен на подразумевана фабричка подешавања."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Покушали сте да откључате телефон неисправно <xliff:g id="NUMBER">%d</xliff:g> пута. Телефон ће сада бити враћен на подразумевана фабричка подешавања."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Нацртали сте шаблон за откључавање неисправно <xliff:g id="NUMBER_0">%d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате таблет помоћу налога е-поште."\n\n"Покушајте поново за <xliff:g id="NUMBER_2">%d</xliff:g> секунде(и)."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Нацртали сте шаблон за откључавање неисправно <xliff:g id="NUMBER_0">%d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу налога е-поште."\n\n"Покушајте поново за <xliff:g id="NUMBER_2">%d</xliff:g> секунде(и)."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Уклони"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Желите да појачате звук изнад безбедног нивоа?"\n"Ако дуже време слушате гласну музику, може доћи до оштећења слуха."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Држите са два прста да бисте омогућили приступачност."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Приступачност је омогућена."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Приступачност је отказана."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Актуелни корисник <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Власник"</string>
 </resources>
diff --git a/core/res/res/values-sv/donottranslate-cldr.xml b/core/res/res/values-sv/donottranslate-cldr.xml
index 8b7833f..64c83f2 100644
--- a/core/res/res/values-sv/donottranslate-cldr.xml
+++ b/core/res/res/values-sv/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">januari</string>
-    <string name="month_long_standalone_february">februari</string>
-    <string name="month_long_standalone_march">mars</string>
-    <string name="month_long_standalone_april">april</string>
-    <string name="month_long_standalone_may">maj</string>
-    <string name="month_long_standalone_june">juni</string>
-    <string name="month_long_standalone_july">juli</string>
-    <string name="month_long_standalone_august">augusti</string>
-    <string name="month_long_standalone_september">september</string>
-    <string name="month_long_standalone_october">oktober</string>
-    <string name="month_long_standalone_november">november</string>
-    <string name="month_long_standalone_december">december</string>
-
-    <string name="month_long_january">januari</string>
-    <string name="month_long_february">februari</string>
-    <string name="month_long_march">mars</string>
-    <string name="month_long_april">april</string>
-    <string name="month_long_may">maj</string>
-    <string name="month_long_june">juni</string>
-    <string name="month_long_july">juli</string>
-    <string name="month_long_august">augusti</string>
-    <string name="month_long_september">september</string>
-    <string name="month_long_october">oktober</string>
-    <string name="month_long_november">november</string>
-    <string name="month_long_december">december</string>
-
-    <string name="month_medium_january">jan</string>
-    <string name="month_medium_february">feb</string>
-    <string name="month_medium_march">mar</string>
-    <string name="month_medium_april">apr</string>
-    <string name="month_medium_may">maj</string>
-    <string name="month_medium_june">jun</string>
-    <string name="month_medium_july">jul</string>
-    <string name="month_medium_august">aug</string>
-    <string name="month_medium_september">sep</string>
-    <string name="month_medium_october">okt</string>
-    <string name="month_medium_november">nov</string>
-    <string name="month_medium_december">dec</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">söndag</string>
-    <string name="day_of_week_long_monday">måndag</string>
-    <string name="day_of_week_long_tuesday">tisdag</string>
-    <string name="day_of_week_long_wednesday">onsdag</string>
-    <string name="day_of_week_long_thursday">torsdag</string>
-    <string name="day_of_week_long_friday">fredag</string>
-    <string name="day_of_week_long_saturday">lördag</string>
-
-    <string name="day_of_week_medium_sunday">sön</string>
-    <string name="day_of_week_medium_monday">mån</string>
-    <string name="day_of_week_medium_tuesday">tis</string>
-    <string name="day_of_week_medium_wednesday">ons</string>
-    <string name="day_of_week_medium_thursday">tors</string>
-    <string name="day_of_week_medium_friday">fre</string>
-    <string name="day_of_week_medium_saturday">lör</string>
-
-    <string name="day_of_week_short_sunday">sön</string>
-    <string name="day_of_week_short_monday">mån</string>
-    <string name="day_of_week_short_tuesday">tis</string>
-    <string name="day_of_week_short_wednesday">ons</string>
-    <string name="day_of_week_short_thursday">tors</string>
-    <string name="day_of_week_short_friday">fre</string>
-    <string name="day_of_week_short_saturday">lör</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">O</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">L</string>
-
-    <string name="am">f.m.</string>
-    <string name="pm">e.m.</string>
-    <string name="yesterday">igår</string>
-    <string name="today">idag</string>
-    <string name="tomorrow">imorgon</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index ebe61a2..2737d62 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -143,7 +143,7 @@
     <string name="silent_mode_vibrate" msgid="7072043388581551395">"Vibrerande ringsignal"</string>
     <string name="silent_mode_ring" msgid="8592241816194074353">"Ringsignal på"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Avslutar…"</string>
-    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Din pekdator stängs av."</string>
+    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Din surfplatta stängs av."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Din telefon stängs av."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Vill du stänga av?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Starta om i felsäkert läge"</string>
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefonalternativ"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Skärmlås"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Stäng av"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Felrapport"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Skapa felrapport"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Nu hämtas information om aktuell status för enheten, som sedan skickas i ett e-postmeddelade. Det tar en liten stund innan felrapporten är färdig och kan skickas, så vi ber dig ha tålamod."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Tyst läge"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Ljudet är AV"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Ljudet är PÅ"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Dina meddelanden"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Läsa och skriva SMS, e-post och andra meddelanden."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Dina personliga uppgifter"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Direktåtkomst till dina kontakter och kalendern som har lagrats på pekdatorn."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Direktåtkomst till dina kontakter och kalendern som har lagrats på telefonen."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Direktåtkomst till information om dig som lagras på ditt kontaktkort."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Dina sociala uppgifter"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Direktåtkomst till information om dina kontakter och sociala kontakter."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Din plats"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Övervaka din fysiska plats."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Nätverkskommunikation"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Åtkomst till olika nätverksfunktioner."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Få åtkomst till enheter och nätverk via Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Ljudinställningar"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Ändra ljudinställningar."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Påverkar batteriet"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Använda funktioner som gör att batteriet tar slut snabbt."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalender"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Direktåtkomst till kalender och händelser."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Läsa den egna ordlistan"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Läsa ord i den egna ordlistan."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Skriva i den egna ordlistan"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Lägga till ord i den egna ordlistan."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Bokmärken och historik"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Direktåtkomst till bokmärken och webbläsarhistorik."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Larm"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Ställa alarmet."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Röstmeddelanden"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Direktåtkomst till röstbrevlådan."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Direktåtkomst till mikrofonen för att spela in ljud."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Direktåtkomst till kamera för att ta bilder eller spela in video."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Information i dina appar"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Kan påverka beteendet hos andra appar på enheten."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Bakgrund"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Ändra inställningarna för enhetens bakgrund."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Klocka"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Ändra tid eller tidszon i enheten."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Statusfält"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Ändra inställningarna för enhetens statusfält."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Synkroniseringsinställningar"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Åtkomst till synkroniseringsinställningarna."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Dina konton"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Få åtkomst till tillgängliga konton."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Kontroller för maskinvara"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Åtkomst och kontroll av systemet på lägre nivå."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Utvecklingsverktyg"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funktioner som endast behövs för apputvecklare."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Gränssnitt i annan app"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Påverka gränssnittet i andra appar."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Lagring"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Få åtkomst till USB-enheten."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Få åtkomst till SD-kortet."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Tillåter att appen tar emot och hanterar WAP-meddelanden. Med den här behörigheten kan appen övervaka eller ta bort meddelanden som skickats till dig utan att visa dem för dig."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"hämta appar som körs"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Tillåter att appen hämtar information om nyligen körda och pågående aktiviteter. Detta kan innebära att appen tillåts ta reda på vilka appar som används på enheten."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interagera mellan användare"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Tillåter att appen utför åtgärder mellan användare på enheten. Skadliga appar kan använda detta som ett sätt att kringgå skyddet mellan användare."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"fullständig behörighet att interagera mellan användare"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Tillåter all slags interaktion mellan användare."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"hantera användare"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Tillåter att appen hanterar användare på enheten, inklusive att söka efter, skapa och radera användarinformation."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"hämta information om aktiva appar"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Tillåter att appen hämtar detaljerad information om uppgifter som körs och har körts. Skadliga appar kan upptäcka personliga uppgifter om andra appar."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"byt ordning på appar som körs"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Tillåter att appen hämtar systemets interna status. Skadliga appar kan hämta privat och skyddad information som normalt aldrig ska behövas."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"hämta skärminnehåll"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Tillåter att appen hämtar innehållet i det aktiva fönstret. Skadliga appar kan hämta allt innehåll i fönstret och läsa all text utom lösenord."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"aktivera tillgänglighetsläget tillfälligt"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Tillåt att en app tillfälligt aktiverar tillgänglighetsläget på enheten. Skadliga appar kan aktivera tillgänglighetsläget utan användarens medgivande."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"hämta information om fönster"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Tillåter att appen hämtar information om fönstren från fönsterhanteraren. Skadliga appar kan hämta information som är avsedd för användning i det interna systemet."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"filtrera händelser"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Tillåter att appen registrerar indatafilter som filtrerar flödet med användarhändelser innan de skickas. Skadliga appar kan styra systemets användargränssnitt utan att användaren gör något."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"förstora skärmen"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Tillåter att en app förstorar innehållet på en skärm. Skadliga appar kan förvandla skärminnehållet på ett sätt som gör att enheten blir oanvändbar."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"avsluta delvis"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Sätter aktivitetshanteraren i avstängningsläge. Utför inte en fullständig avstängning."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"förhindrar programbyten"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Tillåter att appen styr högsta antalet processer som körs. Behövs inte för vanliga appar."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"tvinga bakgrundsappar att avslutas"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Tillåter att appen bestämmer om aktiviteter alltid är slutförda när de hamnar i bakgrunden. Ska inte behövas för vanliga appar."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"ändra batteristatistik"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Tillåter att appen ändrar samlad batteristatistik. Används inte av vanliga appar."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"läs batteristatistik"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Tillåter att en app läser de aktuella uppgifterna om låg batterianvändningsnivå. Appen kan tillåtas få reda på detaljerade uppgifter om vilka appar du använder."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"ändra batteristatistik"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Tillåter att appen ändrar samlad batteristatistik. Används inte av vanliga appar."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontrollera säkerhetskopiering och återställning av systemet"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Tillåter att appen styr över systemets mekanism för säkerhetskopiering och återställning. Används inte av vanliga appar."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"Bekräfta fullständig säkerhetskopia eller återställning"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"visa otillåtna fönster"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Tillåter att appen skapar fönster som ska användas av det interna systemgränssnittet. Används inte av vanliga appar."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"skriva över andra appar"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Tillåter att appen visar fönster med systemvarningar. Vissa varningsfönster kan överta hela skärmen."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Tillåter att appen att dras ovanpå andra appar eller delar av användargränssnittet. De kan störa din användning av gränssnittet i olika appar eller ändra vad du tror visas i andra appar."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"ändra global animeringshastighet"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Tillåter att appen när som helst ändrar den globala animeringshastigheten (snabbare eller långsammare)."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"hantera token i appar"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Tillåter att appen skapar och hanterar egna token och förbigår normala Z-beställningar. Behövs inte för vanliga appar."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"frysa skärmen"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Tillåter att appen tillfälligt fryser skärmen för övergång till helskärm."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"trycka på knappar och styrknappar"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Tillåter att appen levererar egna inmatningshändelser (knapptryckningar osv.) till andra appar. Skadliga appar kan använda detta för att kapa pekdatorn."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Tillåter att appen levererar egna inmatningshändelser (knapptryckningar osv.) till andra appar. Skadliga appar kan använda detta för att kapa mobilen."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"installera appar direkt"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Tillåter att appen installerar nya eller uppdaterade Android-paket. Skadliga appar kan använda detta för att lägga till nya appar med godtyckliga och starka behörigheter."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"ta bort cacheinformation för alla appar"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Tillåter att appen frigör lagringsutrymme på pekdatorn genom att ta bort filer i programmets katalog för cachelagring. Mycket begränsad åtkomst, vanligtvis till systemprocesser."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Tillåter att appen frigör lagringsutrymme på mobilen genom att ta bort filer i programmets katalog för cachelagring. Mycket begränsad åtkomst, vanligtvis till systemprocesser."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Tillåter att appen frigör utrymme på surfplattan genom att ta bort filer i andra appars cachekataloger. Detta kan medföra att andra appar startar långsammare eftersom samma data måste hämtas på nytt."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Tillåter att appen frigör utrymme på mobilen genom att ta bort filer i andra appars cachekataloger. Detta kan medföra att andra appar startar långsammare eftersom samma data måste hämtas på nytt."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"flytta appresurser"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Tillåter att appen flyttar appresurser från interna till externa medier och tvärtom."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"läsa känsliga loggdata"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Tillåter att appen får åtkomst till extra kommandon för platsleverantör. Detta kan innebära att appen tillåts störa funktionen för GPS eller andra platskällor."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"behörighet att installera en platsleverantör"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Skapa skenplatser för tester eller installera en ny platsleverantör. Detta innebär att appen tillåts åsidosätta den plats och/eller status som returneras av andra platskällor, som GPS eller platsleverantörer."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"exakt (GPS-definierad) plats"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Få åtkomst till exakta platskällor, till exempel GPS på pekdatorn. När platstjänsterna är tillgängliga och aktiverade tillåts appen att fastställa exakt var du befinner dig med den här behörigheten."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Få åtkomst till exakta platskällor, till exempel GPS på mobilen. När platstjänsterna är tillgängliga och aktiverade tillåts appen att fastställa exakt var du befinner dig med den här behörigheten."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"ungefärlig (nätverksbaserad) plats"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Få åtkomst till ungefärlig plats från platsleverantörer med hjälp av källor i nätverket som mobilmast och Wi-Fi. När platstjänsterna är tillgängliga och aktiverade tillåts appen att fastställa ungefär var du befinner dig med den här behörigheten."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"exakt plats (GPS- och nätverksbaserad)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Tillåter att appen känner av din ungefärliga position med hjälp av GPS eller platstjänster som mobilmaster och Wi-Fi. Platstjänsterna måste vara aktiverade och tillgängliga på enheten för att appen ska kunna använda dem. Appar kan använda detta för att avgöra ungefär var du befinner dig."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"ungefärlig position (nätverksbaserad)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Tillåter att appen känner av din ungefärliga position. Platsen avgörs genom platstjänster med hjälp av nätverksplatskällor som mobilmaster och Wi-Fi. Platstjänsterna måste vara aktiverade och tillgängliga på enheten för att appen ska kunna använda dem. Appar kan använda detta för att avgöra ungefär var du befinner dig."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"få åtkomst till SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Tillåter att appen använder lågnivåfunktioner i SurfaceFlinger."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"läsa rambuffert"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Tillåter att appen läser innehållet i rambufferten."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"konfigurerar Wi-Fi-skärmar"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Tillåter att appen konfigurerar och ansluter till Wi-Fi-skärmar."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"kontrollerar Wi-Fi-skärmar"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Tillåter att appen kontrollerar grundläggande funktioner för Wi-Fi-skärmar."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ändra dina ljudinställningar"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Tillåter att appen ändrar globala ljudinställningar som volym och vilken högtalarutgång som används."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"spela in ljud"</string>
@@ -395,7 +454,7 @@
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"inaktivera telefonen permanent"</string>
     <string name="permdesc_brick" product="tablet" msgid="4334818808001699530">"Tillåter att appen inaktiverar hela pekdatorn permanent. Detta är mycket farligt."</string>
     <string name="permdesc_brick" product="default" msgid="5788903297627283099">"Tillåter att appen inaktiverar hela mobilen permanent. Detta är mycket farligt."</string>
-    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"tvinga omstart av pekdator"</string>
+    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"tvinga omstart av surfplatta"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"tvinga omstart av telefon"</string>
     <string name="permdesc_reboot" product="tablet" msgid="8172056180063700741">"Tillåter att appen tvingar pekdatorn att starta om."</string>
     <string name="permdesc_reboot" product="default" msgid="5326008124289989969">"Tillåter att appen tvingar mobilen att starta om."</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"få åtkomst till Bluetooth-inställningar"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Tillåter att appen konfigurerar den lokala Bluetooth-pekdatorn samt upptäcker och parkopplar den med fjärranslutna enheter."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Tillåter att appen konfigurerar den lokala Bluetooth-mobilen samt upptäcker och parkopplar den med fjärranslutna enheter."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Visa WiMAX-anslutningar"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"ansluta till och koppla från WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Tillåter att appen avgör om WiMAX är aktiverat och kommer åt information om eventuella anslutna WiMAX-nätverk."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"ändra WiMAX-status"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Tillåter att appen ansluter pekdatorn till eller kopplar från WiMAX-nätverk."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Tillåter att appen ändrar dina aktuella synkroniserade flöden. Skadliga appar kan ändra dina synkroniserade flöden."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"läsa termer som du har lagt till i ordlistan"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Tillåter att appen läser alla ord, namn och fraser som användaren har sparat i ordlistan."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"lägga till i användardefinierad ordlista"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"lägga till ord i den användardefinierade ordlistan"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Tillåter att appen anger nya ord i användarordlistan."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"testa åtkomst till skyddad lagringsenhet"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"testa åtkomst till skyddad lagringsenhet"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Tillåter appen att testa behörighet till USB-enheter för användning på framtida enheter."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Tillåter att appen testar behörighet till USB-enheter för användning på framtida enheter."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Tillåter appen att testa behörighet till SD-kortet för användning på framtida enheter."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"ändra eller ta bort innehållet"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"ändra eller ta bort innehåll på SD-kortet"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Tillåter att appen skriver till SD-kortet."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"ändra/ta bort innehåll"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Tillåter att appen ändrar innehållet på den interna lagringsenheten."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"åtkomst till lagringsutrymme"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Tillåter att appen får åtkomst till en extern lagringsenhet för alla användare."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"åtkomst till cachefilsystemet"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Tillåter att appen läser och skriver till cachefilsystemet."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"ringa/ta emot Internetsamtal"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Kräv att sparade appdata krypteras."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Inaktivera kameror"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Förhindra att enhetens kameror används."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Inaktivera vid knapplås"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Förhindra användning av vissa funktioner vid knapplås."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Hem"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Försök igen"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Du har försökt låsa upp med Ansiktslås för många gånger"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Laddar (<xliff:g id="PERCENT">%%</xliff:g> <xliff:g id="NUMBER">%d</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Laddad."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Batteriet har laddats"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Anslut din laddare."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Inget SIM-kort."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Inget SIM-kort"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Inget SIM-kort i pekdatorn."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Inget SIM-kort i telefonen."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Sätt i ett SIM-kort."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Grafiskt lösenord har tagits bort"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"En cell har lagts till"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Grafiskt lösenord har slutförts"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Lägg till en widget."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Tom"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Expanderad upplåsningsyta."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Komprimerad upplåsningsyta."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Widget för <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Användarväljare"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Status"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Kamera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Mediereglage"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Ändring av widgetarnas ordning har påbörjats."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Ändring av widgetarnas ordning har avslutats."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widgeten <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> har tagits bort."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Expandera upplåsningsytan."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Lås upp genom att dra."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Lås upp med grafiskt lösenord."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Lås upp med Ansiktslås."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Lås upp med PIN-kod."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Lås upp med lösenord."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Fält för grafiskt lösenord."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Fält med dragreglage."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopiera webbadress"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Markera text"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Textmarkering"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"lägg till i ordlista"</string>
-    <string name="deleteText" msgid="7070985395199629156">"ta bort"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Lägg till i ordlista"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Ta bort"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Indatametod"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Textåtgärder"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Lagringsutrymmet börjar ta slut"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Öppna Wi-Fi-nätverk är tillgängliga"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Logga in på Wi-Fi-nätverk"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Logga in på nätverket"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Det gick inte att ansluta till Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" har en dålig Internetanslutning."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Till:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Ange den obligatoriska PIN-koden:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-kod:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Mobilen kommer tillfälligt att kopplas från Wi-Fi när den är ansluten till <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Infoga tecken"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Skickar SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; skickar ett stort antal SMS. Vill du tillåta att appen fortsätter att skicka meddelanden?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Tillåt"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Neka"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vill skicka ett meddelande till &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Detta "<font fgcolor="#ffffb060">"kan medföra debiteringar"</font>" på ditt mobilkonto."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Ditt mobilkonto kommer att debiteras."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Skickat"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Avbryt"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Kom ihåg mitt val"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Du kan ändra detta senare i Inställningar &gt; Appar"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Tillåt alltid"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Tillåt aldrig"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kortet togs bort"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Det mobila nätverket kommer inte att vara tillgängligt förrän du startar om med ett giltigt SIM-kort."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Klar"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Ange datum"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ställ in"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Klar"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Standardinställning"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Inga behörigheter krävs"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Dölj"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Visa alla"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"NY: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NY: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Tillhandahålls av <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Inga behörigheter krävs"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"detta kan kosta pengar"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB-masslagring"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB-ansluten"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Du har anslutit enheten till datorn via USB. Tryck på knappen nedan om du vill kopiera filer mellan datorn och Android-enhetens USB-lagringsenhet."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveras av <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tryck om du vill hantera nätverket."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Ansluten till <xliff:g id="SESSION">%s</xliff:g>. Knacka lätt om du vill hantera nätverket."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Ansluter till Always-on VPN ..."</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Ansluten till Always-on VPN"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Fel på Always-on VPN"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Tryck för att återställa anslutningen"</string>
     <string name="upload_file" msgid="2897957172366730416">"Välj fil"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Ingen fil har valts"</string>
     <string name="reset" msgid="2448168080964209908">"Återställ"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Dela"</string>
     <string name="find" msgid="4808270900322985960">"Sök efter"</string>
     <string name="websearch" msgid="4337157977400211589">"Webbsökning"</string>
+    <string name="find_next" msgid="5742124618942193978">"Sök nästa"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Sök föregående"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Positionsförfrågan från <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Positionsförfrågan"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Begärt av <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1282,12 +1380,68 @@
     <string name="SetupCallDefault" msgid="5834948469253758575">"Vill du ta emot samtal?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Alltid"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Bara en gång"</string>
-    <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Pekdator"</string>
+    <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Surfplatta"</string>
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Mobil"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Hörlurar"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dockningsstationens högtalare"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI-ljud"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-ljud"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Klar"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Medieuppspelning"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Skannar…"</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Ansluter ..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Tillgängliga"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Ej tillgängligt"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Inbyggd skärm"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI-skärm"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Överlagring #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Trådlös anslutning till skärm"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Den här skärmen visas på en annan enhet"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Koppla från"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Nödsamtal"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Har du glömt ditt grafiska lösenord?"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Fel grafiskt lösenord"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Fel lösenord"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Fel PIN-kod"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Försök igen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Rita ditt grafiska lösenord"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Ange PIN-kod för SIM-kortet"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Ange PIN-kod"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Ange lösenord"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM-kortet är nu inaktiverat. Ange PUK-koden om du vill fortsätta. Kontakta operatören om du vill få mer information."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Ange önskad PIN-kod"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Bekräfta önskad PIN-kod"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Låser upp SIM-kort …"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Fel PIN-kod."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Ange en PIN-kod med 4 till 8 siffror."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK-koden ska vara minst åtta siffror."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Ange rätt PUK-kod igen. Om försöken upprepas inaktiveras SIM-kortet permanent."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN-koderna stämmer inte överens"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"För många försök med grafiskt lösenord"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Logga in med ditt Google-konto om du vill låsa upp."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Användarnamn (e-post)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Lösenord"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Logga in"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Ogiltigt användarnamn eller lösenord."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Har du glömt ditt användarnamn eller lösenord?"\n"Besök "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Kontot kontrolleras …"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Du har angett fel lösenord <xliff:g id="NUMBER_0">%d</xliff:g> gånger. "\n\n"Försök igen om <xliff:g id="NUMBER_1">%d</xliff:g> sekunder."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Du har angett fel lösenord <xliff:g id="NUMBER_0">%d</xliff:g> gånger. "\n\n"Försök igen om <xliff:g id="NUMBER_1">%d</xliff:g> sekunder."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%d</xliff:g> gånger. "\n\n"Försök igen om <xliff:g id="NUMBER_1">%d</xliff:g> sekunder."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Du har försökt låsa upp mobilen på fel sätt <xliff:g id="NUMBER_0">%d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%d</xliff:g> misslyckade försök återställs surfplattan till fabriksinställningarna. Du förlorar då alla användardata."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Du har försökt låsa upp mobilen på fel sätt <xliff:g id="NUMBER_0">%d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%d</xliff:g> misslyckade försök återställs mobilen till fabriksinställningarna. Du förlorar då alla användardata."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Du har försökt låsa upp surfplattan på fel sätt <xliff:g id="NUMBER">%d</xliff:g> gånger. Surfplattan återställs nu till fabriksinställningarna."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Du har försökt låsa upp mobilen på fel sätt <xliff:g id="NUMBER">%d</xliff:g> gånger. Mobilen återställs nu till fabriksinställningarna."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%d</xliff:g> försök ombeds du låsa upp surfplattan med ett e-postkonto."\n\n" Försök igen om <xliff:g id="NUMBER_2">%d</xliff:g> sekunder."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%d</xliff:g> försök ombeds du låsa upp mobilen med hjälp av ett e-postkonto."\n\n" Försök igen om <xliff:g id="NUMBER_2">%d</xliff:g> sekunder."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Ta bort"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Vill du höja volymen över den säkra nivån?"\n"Om du lyssnar på hög volym under långa perioder kan din hörsel skadas."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Fortsätt trycka med två fingrar om du vill aktivera tillgänglighetsläget."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Tillgänglighetsläget har aktiverats."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Byte till tillgänglighetsläge avbrutet."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Nuvarande användare: <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Ägare"</string>
 </resources>
diff --git a/core/res/res/values-sw/donottranslate-cldr.xml b/core/res/res/values-sw/donottranslate-cldr.xml
index 2bc07c1..a7a5150 100644
--- a/core/res/res/values-sw/donottranslate-cldr.xml
+++ b/core/res/res/values-sw/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Januari</string>
-    <string name="month_long_standalone_february">Februari</string>
-    <string name="month_long_standalone_march">Machi</string>
-    <string name="month_long_standalone_april">Aprili</string>
-    <string name="month_long_standalone_may">Mei</string>
-    <string name="month_long_standalone_june">Juni</string>
-    <string name="month_long_standalone_july">Julai</string>
-    <string name="month_long_standalone_august">Agosti</string>
-    <string name="month_long_standalone_september">Septemba</string>
-    <string name="month_long_standalone_october">Oktoba</string>
-    <string name="month_long_standalone_november">Novemba</string>
-    <string name="month_long_standalone_december">Desemba</string>
-
-    <string name="month_long_january">Januari</string>
-    <string name="month_long_february">Februari</string>
-    <string name="month_long_march">Machi</string>
-    <string name="month_long_april">Aprili</string>
-    <string name="month_long_may">Mei</string>
-    <string name="month_long_june">Juni</string>
-    <string name="month_long_july">Julai</string>
-    <string name="month_long_august">Agosti</string>
-    <string name="month_long_september">Septemba</string>
-    <string name="month_long_october">Oktoba</string>
-    <string name="month_long_november">Novemba</string>
-    <string name="month_long_december">Desemba</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mac</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">Mei</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Ago</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Okt</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Des</string>
-
-    <string name="month_shortest_january">1</string>
-    <string name="month_shortest_february">2</string>
-    <string name="month_shortest_march">3</string>
-    <string name="month_shortest_april">4</string>
-    <string name="month_shortest_may">5</string>
-    <string name="month_shortest_june">6</string>
-    <string name="month_shortest_july">7</string>
-    <string name="month_shortest_august">8</string>
-    <string name="month_shortest_september">9</string>
-    <string name="month_shortest_october">10</string>
-    <string name="month_shortest_november">11</string>
-    <string name="month_shortest_december">12</string>
-
-    <string name="day_of_week_long_sunday">Jumapili</string>
-    <string name="day_of_week_long_monday">Jumatatu</string>
-    <string name="day_of_week_long_tuesday">Jumanne</string>
-    <string name="day_of_week_long_wednesday">Jumatano</string>
-    <string name="day_of_week_long_thursday">Alhamisi</string>
-    <string name="day_of_week_long_friday">Ijumaa</string>
-    <string name="day_of_week_long_saturday">Jumamosi</string>
-
-    <string name="day_of_week_medium_sunday">Jpi</string>
-    <string name="day_of_week_medium_monday">Jtt</string>
-    <string name="day_of_week_medium_tuesday">Jnn</string>
-    <string name="day_of_week_medium_wednesday">Jtn</string>
-    <string name="day_of_week_medium_thursday">Alh</string>
-    <string name="day_of_week_medium_friday">Iju</string>
-    <string name="day_of_week_medium_saturday">Jmo</string>
-
-    <string name="day_of_week_short_sunday">Jpi</string>
-    <string name="day_of_week_short_monday">Jtt</string>
-    <string name="day_of_week_short_tuesday">Jnn</string>
-    <string name="day_of_week_short_wednesday">Jtn</string>
-    <string name="day_of_week_short_thursday">Alh</string>
-    <string name="day_of_week_short_friday">Iju</string>
-    <string name="day_of_week_short_saturday">Jmo</string>
-
-    <string name="day_of_week_shortest_sunday">1</string>
-    <string name="day_of_week_shortest_monday">2</string>
-    <string name="day_of_week_shortest_tuesday">3</string>
-    <string name="day_of_week_shortest_wednesday">4</string>
-    <string name="day_of_week_shortest_thursday">5</string>
-    <string name="day_of_week_shortest_friday">6</string>
-    <string name="day_of_week_shortest_saturday">7</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index c2bd3ee..afdb39e 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Chaguo za simu"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Funga skrini"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Nishati imezimwa"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Ripoti ya hitilafu"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Chukua ripoti ya hitilafu"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Hii itakusanya maelezo kuhusu hali yako ya sasa ya kifaa, ili kutuma ujumbe wa barua pepe. Itachukua muda mfupi kuanza ripoti ya hitilafu mpaka itakapokuwa tayari kutumwa; tafadhali vumilia."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Mtindo wa kimya"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Sauti Imezimwa"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Sauti imewashwa"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Ujumbe wako"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Soma na kuandika SMS, barua pepe, na jumbe zako zingine."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Maelezo yako ya kibinafsi"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Ufikiaji wa moja kwa moja wa anwani zako na kalenda iliyohifadhiwa kwenye kompyuta ndogo."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Ufikiaji wa moja kwa moja wa anwani zako na kalenda zilizohifadhiwa kwenye simu."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Kufikia moja kwa moja taarifa kukuhusu, iliyoakibishwa kwenye kadi yako ya anwani."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Taarifa yako ya kijamii"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Kufikia moja kwa moja taarifa kuhusu anwani zako na miunganisho ya kijamii."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Mahali pako"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Fuatilia eneo lako halisi."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Mawasiliano ya mtandao"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Fikia vipengele mbalimbali vya mtandao."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Fikia vifaa na mitandao kupitia Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Mipangilio ya Sauti"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Badilisha mipangilio ya sauti."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Huathiri Betri"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Tumia vipengele vinaweza kumaliza betri haraka."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalenda"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Kufikia moja kwa moja kalenda na matukio."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Soma Kamuzi ya Mtumiaji"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Soma maneno katika kamusi ya mtumiaji."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Andika Kamusi ya Mtumiaji"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Ongeza maneno katika kamusi mtumiaji."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Vialamisho na Historia"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Kufikia moja kwa moja vialamisho na historia ya kivinjari"</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Kengele"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Weka saa ya kengele."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Barua ya sauti"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Fikia barua ya sauti moja kwa moja."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Kipokea sauti"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Kufikia moja kwa moja kipokea sauti ili kurekodi sauti."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Kufikia moja kwa moja kamera ya kunasa taswira au video."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Taarifa ya programu zako"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Uwezo wa kuathiri tabia ya programu nyingine kwenye kifaa chako."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Taswira"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Badilisha mipangilio taswira ya kifaa."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Saa"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Badilisha muda wa kifaa au ukanda wa saa."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Hali Upau"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Badilisha mipangilio ya upau wa hali ya kifaa."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Mipangilio ya Upatanishi"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Kufikia mipangilio ya upatanishi."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Akaunti zako"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Fikia akaunti zinazopatikana."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Vidhibiti vya maunzi"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Ufikiaji wa kiwango cha chini na udhibiti wa mfumo."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Zana za utengenezaji"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Vipengee vinahitajika tu na wasinidi wa programu."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Programu Nyingine ya UI"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Ruhusu UI ya programu nyungine."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Hifadhi"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Fikia hifadhi ya USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Fikia kadi ya SD."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Inaruhusu programu kupokea na kuchakata ujumbe wa WAP. Idhini hii inajumuisha uwezo wa kuchunguza na kufuta ujumbe uliotumwa kwako bila ya kukuonyesha."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"rudisha programu zinazoendeshwa"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Inaruhusu programu kurudisha taarifa kuhusu kazi zinazoendeshwa sasa na hivi karibuni. Hii inaweza kuruhusu programu kugundua taarifa kuhusu ni programu zipi zinazotumika kwenye kifaa."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"Tagusana na watumiaji"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Inaruhusu programu kutenda vitendo kwa watumiaji tofauti kwenye kifaa. Programu hasidi huenda zikatumia hii ili kukiuka ulinzi kati ya watumiaji."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"leseni kamili ili kutagusana na watumiaji"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Inaruhusu miingialiano yote inayowezekana kwa watumiaji."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"dhibiti watumiaji"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Inaruhusu programu kudhibiti watumiaji kwenye kifaa, pamoja na hoji, uundaji na ufutaji."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"epua maelezo ya programu zinazoendeshwa"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Huruhusu programu kuepua maelezo tondoti kuhusu kazi za sasa na zinazoendelea hivi karibuni. Programu hasidi huenda zikagundua maelezo ya kibinafsi kuhusu programu zingine."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"Agiza tena programu za kuendeshwa"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Inaruhusu programu kutoa hali ya ndani ya mfumo. Programu hasidi zinaweza kutoa aina nyingi za taarifa za faragha na salama ambazo kwa kawaida hazihitaji."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"epua maudhui ya skrini"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Inaruhusu programu kutoa maudhui ya dirisha amilifu. Programu hasidi zinaweza kutoa maudhui yote ya dirisha na kuchunguza maandishi yake yote isipokuwa nenosiri."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"wezesha ufikivu kwa muda"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Inaruhusu programu kuwezesha kwa muda ufikivu kwenye kifaa. Huenda programu hasidi zikawezesha ufikivu bila kibali cha mtumiaji."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"okoa maelezo ya dirisha"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Huruhusu programu kuokoa maelezo kuhusu madirisha kutoka kwenye kidhibiti dirisha. Huenda programu hasidi ikakusanya maelezo ambayo yamekusudiwa kwa matumizi ya mfumo wa ndani."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"chuja matukio"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Huruhusu programu kusajili kichujio ingizo kinachochuja mkondo wa matukio ya mtumiaji kabla ya kutumwa. Huenda programu hasidi ikadhibiti mfumo wa UI bila mtumiaji kuingilia kati."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"kuza oneysho"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Inaruhusu programu kukuza maudhui ya onyesho. Programu hasidi zinaweza kubadili maudhui kwa njia ambayo inaweza kukifanya kifaa kutotumika."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"Zima nusu"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Huweka kisimamia shughuli katika hali ya kuzima. Haiadhiri uzimaji kamili"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zuia swichi za app"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Inaruhusu programu kudhibiti upeo wa idadi ya michakato ambayo itaendeshwa. Kamwe hazihitajiki kwa programu za kwaida."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"lazimisha programu za usuli kufunga"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Inaruhusu programu kudhibiti kama daima shughuli zinamalizwa wakati ziendapo kwa mandhari-nyuma. Kamwe hazihitajiki kwa programu za kawaida."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"rekebisha takwimu za betri"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Inaruhusu programu kurekebisha takwimu za betri zilizokusanywa. Si kwa matumizi ya programu za kawaida."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"soma takwimu za betri"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Inaruhusu programu kusoma data ya sasa ya matumizi ya kiwango cha chini cha betri. Huenda ikaruhusu kupata maelezo ya kina kuhusu programu unazozitumia."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"rekebisha takwimu za betri"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Inaruhusu programu kurekebisha takwimu za betri zilizokusanywa. Si ya kutumiwa na programu za kawaida."</string>
     <string name="permlab_backup" msgid="470013022865453920">"Dhibiti chelezo la mfumo na rejesha"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Inaruhusu programu kudhibiti utaratibu wa kucheleza na kurejesha wa mfumo. Si kwa matumizi na programu za kawaida."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"thibitisha chelezo kamilifu au rejesha upya uendeshaji"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"onyesha madirisha yasiyoidhinishwa"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Huruhusu programu kuunda madirisha ambayo yananuiwa kutumiwa na kusano ya mtumiaji ya mfumo wa ndani. Sio ya matumizi na programu za kawaida."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"chora juu ya programu zingine"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Inaruhusu programu kuonyesha madirisha ya tahadhari za mfumo. Baadhi ya madirisha ya tahadhari ya mfumo yanaweza kujaa kwenye skrini nzima."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Inaruhusu programu kuchora juu ya programu nyingine au sehemu za kiolesura cha mtumiaji. Huenda zikahitilafiana na utumiaji wako wa kiolesura katika programu yoyote, au kubadilisha unachofikiri unakiona katika programu nyingine."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"rekebisha kasi ya jumla ya uhuisho"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Huruhusu programu kubadilisha kasi ya uhuishaji kijumla (uhuisho wa haraka zaidi au wa polepole zaidi) wakati wowote."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"Dhibiti shuhuda za programu"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Inaruhusu programu kuunda na kudhibiti shuhuda zake, kukwepa mipangilio yao ya kawaida. Haitahitajika kamwe na programu za kawaida."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"lemaza skrini"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Inaruhusu programu kulemaza kwa muda skrini kwa ajili ya mpito kamili wa skrinimaombi kwa muda kufungia screen kwa ajili ya mpito full-screen."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"bonyeza vitufe na vitufe vya kudhibiti"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Huruhusu programu kuwasilisha matukio yake ya ingizo (mibonyezo ya vitufe, nk.) kwa programu zingine. programu hasidi zinaweza kutumia hii ili kutawala kompyuta kibao."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Inaruhusu programu kuwasilisha matukio yake ya ingizo (mibonyezo ya kitufe, nk.)kwa programu zingine.Programu hasidi zinaweza kutumia hii kutawala simu."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"sakinisha programu moja kwa moja"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Inaruhusu programu kusakanisha au kusasisha furushi mpya za Android. Programu hasidi zinaweza kutumia hii kuongeza programu mpya ambazo zina ruhusa zenye nguvu."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"Futa data yote kwenye kache ya programu"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Inaruhusu programu kuongeza hifadhi ya kompyuta kibao kwa kufuta faili katika saraka ya kache ya programu. Upatikanaji umezuiwa kwa mfumo wa uendeshaji tu."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Inaruhusu programu  kuongeza hifadhi  ya simu kwa kufuta faili katika programu ya saraka ya kache. Upatikanaji umefungiwa kwa mfumo wa uendeshaji tu."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Inaruhusu programu kutoa nafasi ya hifadhi ya kompyuta ndogo kwa kufuta faili katika saraka za kache za programu nyingine. Huenda hii ikasababisha programu nyingine kuanza polepole zaidi kwa sababu zinahitaji kuepua data zazo."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Inaruhusu programu kutoa nafasi ya hifadhi ya simu kwa kufuta faili katika saraka za kache za programu nyingine. Huenda hii ikasababisha programu nyingine kuanza polepole zaidi kwa sababu zinahitaji kuepua data zazo."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"songesha rasilimali ya programu"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Huruhusu programu kuhamisha nyenzo za programu kutoka midia ya ndani hadi ya nje na kinyume chake."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"soma kumbukumbu ya data muhimu"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Huruhusu programu kufikia amri za ziada za mtoaji huduma wa eneo. Hii inaweza kuruhusu programu kuhitilafiana na uendeshaji wa GPS au vyanzo vingine vya eneo."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"kibali ili kusakinisha mtoa huduma ya mahali"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Unda vyanzo vya eneo la majaribio vya kujaribu au kusakinisha mtoaji huduma mpya wa eneo. Hii inaruhusu programu kufuta eneo na/au hali zilizorudishwa na vyanzo vingine vya eneo kama vile GPS au watoaji huduma wa eneo."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"eneo halisi la (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Fikia vyanzo vya eneo sahihi kama vile Mfumo wa Global Positioning kwenye kompyuta ndogo. Wakati huduma za eneo zinapatikana na kuwashwa, kibali hiki kinaruhusu programu kuthibitisha eneo lako kamili."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Fikia vyanzo vya eneo sahihi kama vile Mfumo wa Global Positioning kwenye simu. Wakati huduma za eneo zinapatikana na zimewashwa, kibali hiki kinaruhusu programu kuthibitisha eneo lako kamili."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"eneo karibu  (linalotegemea mtandao)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Fikia kadirio la eneo lako kutoka kwa watoaji huduma wa eneo kwa kutumia vyanzo vya mtandao kama vile mnara wa seli na Wi-Fi. Wakati huduma hizi za eneo zinapatikana na kuwashwa, kibali hiki kinaruhusu programu kuthibitisha kadirio la eneo lako."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"eneo sahihi (GPS na mtandao)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Inaruhusu programu kupata eneo lako sahihi kwa kutumia Mfumo wa Mkao Ulimwenguni (GPS) au vyanzo vya mtandao vya eneo kama vile minara na Wi-Fi. Lazima huduma hizi za eneo ziwashwe na kupatikana kwenye kifaa chako ili programu izitumie. Huenda programu zikatumia hii kutambua ulipo, na zinaweza kutumia kawi ya ziada ya betri."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"eneo la kukadiriwa (ya mtandao)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Inaruhusu programu kupata eneo lako la kukadiria. Eneo hili linatokana na huduma za maeneo kwa kutumia vyanzo vya mtandao vya eneo kama vile minara na Wi-Fi. Lazima huduma hizi za eneo ziwashwe na kupatikana kwenye kifaa chako ili programu izitumie. Huenda programu zikatumia hii kutambua ulipo kwa kukadiria."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"fikia SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Inaruhusu programu kutumia vipengee vya kiwango cha chini vya SurfaceFlinger."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"soma bafa ya fremu"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Inaruhusu programu kusoma maudhui ya fremu ya bafa."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"sanidi maonyesho ya Wifi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Inaruhusu programu kusanidi na kuunganika kwenye maonyesho ya Wifi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"dhibiti maonyesho ya Wifi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Inaruhusu programu kudhibiti vipengele vya kiwango cha chini vya maonyesho ya Wifi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"badilisha mipangilio yako ya sauti"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Inaruhusu programu kurekebisha mipangilio ya sauti kila mahali kama vile sauti na ni kipaza sauti kipi ambacho kinatumika kwa kutoa."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"rekodi sauti"</string>
@@ -470,8 +529,8 @@
     <string name="permlab_getAccounts" msgid="1086795467760122114">"pata akaunti kwenye kifaa"</string>
     <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Inaruhusu programu kupata orodha ya akaunti zinazojulikana kwa kompyuta kibao. Hii inaweza kujumuisha akaunti zozote zilizoundwa na programu ambazo umesakinisha."</string>
     <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Inaruhusu programu kupata orodha ya akaunti zinazojulikana kwa simu. Hii inaweza kujumuisha akaunti zozote zilizoundwa na programu ambazo umesakinisha."</string>
-    <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"unda akaunti na weka manenosiri"</string>
-    <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"Inaruhusu programu kutumia uwezo wa uthibitishaji akaunti wa KidhibitiAkaunti, pamoja na kuunda akaunti na kupata na kuweka nywila zao."</string>
+    <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"fungua akaunti na weka manenosiri"</string>
+    <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"Inaruhusu programu kutumia uwezo wa uthibitishaji akaunti wa KidhibitiAkaunti, ikiwa ni pamoja na kufungua akaunti na kupata na kuweka manenosiri ya akaunti hizo."</string>
     <string name="permlab_manageAccounts" msgid="4983126304757177305">"ongeza au uondoe akaunti"</string>
     <string name="permdesc_manageAccounts" msgid="8698295625488292506">"Inaruhusu programu kutekeleza shughuli kama vile kuongeza na kutoa akaunti, na kufuta manenosiri yazo."</string>
     <string name="permlab_useCredentials" msgid="235481396163877642">"tumia akaunti kwenye kifaa"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"fikia mipangilio ya Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Inaruhusu programu kusanidi kompyuta kibao ya karibu ya Bluetooth na kutambua na kuoanisha na vifaa vya kudhibiti."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Inaruhusu programu kusanidi simu ya karibu ya Bluetooth, na kutambua na kuoanisha na vifaa vya mbali."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Ona miunganisho ya WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"unganisha na uukate muunaganisho kutoka kwenye  WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Inaruhusu programu kuthibitisha ikiwa WiMAX imewezeshwa na taarifa kuhusu mitandao yoyote ya WiMAX ambayo imeunganishwa."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Badilisha hali ya WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Inaruhusu programu kuunganisha kompyuta kibao,  na kukata kompyuta kibao kutoka mitandao ya WiMAX."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Inaruhusu programu kurekebisha milisho yako iliyolandanishwa kwa sasa. Programu hasidi zinaweza kubadilisha milisho yako iliyolandanishwa."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"soma maneno uliyoongeza kwenye kamusi"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Inaruhusu programu kusoma maneno, majina na misemo yote ambayo mtumiaji alihifadhi katika kamusi ya mtumiaji."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"andika kwa kamusi iliyobainishwa na mtumiaji"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"ongeza maneno katika kamusi ya mtumiaji iliyofafanuliwa"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Inaruhusu programu kuandika maneno mapya katika kamusi ya mtumiaji."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"jaribu mfikio kwa hifadhi iliyolindwa"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"jaribu mfikio kwa hifadhi iliyolindwa"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Inaruhusu programu kujaribu idhini ya hifadhi ya USB itakayokuwa kwenye vifaa vya baadaye."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Inaruhusu programu kujaribu idhini ya hifadhi ya USB itakayopatikana kwenye vifaa vya baadaye."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Inaruhusu programu kujaribu idhini ya kadi ya SD itakayokuwa kwenye vifaa vya baadaye."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"rekebisha au ufute maudhui ya hifadhi yako ya USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"rekebisha au ufute maudhui ya kadi yako ya SD"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Inaruhusu programu kuandikia kadi ya SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"badilisha/futa maudhui ya hifadhi ya media ya ndani."</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Inaruhusu programu kurekebisha maudhui ya hifadhi ya ndani vyombo vya habari."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"Fikia hifadhi ya nje ya watumiaji wote"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Inaruhusu programu kufikia hifadhi ya nje kwa watumiaji wote."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"fikia faili za mfumo za kache"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Inaruhusu programu kusoma na kuandika mfumo wa faili wa kache."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"piga/pokea simu za mtandao"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Inahitaji kwamba data ya programu iliyohifadhiwa iwe na msimbo fiche."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Lemaza kamera"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Zuia matumizi yote ya kamera za kifaa."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Lemaza vipengele kwenye kilinzi cha kitufe."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Inazuia matumizi ya baadhi ya vipengele kwenye kilinzi cha kitufe."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Nyumbani"</item>
     <item msgid="869923650527136615">"Simu ya mkononi"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Jaribu tena"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Majaribio ya Juu ya Kufungua Uso yamezidishwa"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Inachaji <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Imechajiwa."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Imechajiwa"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Unganisha chaja yako"</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Hakuna SIM kadi."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Hakuna SIM kadi"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Hakuna SIM kadi katika kompyuta ndogo."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Hakuna SIM kadi kwenye simu."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Ingiza SIM kadi."</string>
@@ -737,7 +800,7 @@
     <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Jina la mtumiaji (barua pepe)"</string>
     <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Nenosiri"</string>
     <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Ingia"</string>
-    <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Jina batili la mtumiaji au nywila"</string>
+    <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Jina la mtumiaji au nenosiri batili."</string>
     <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"Umesahau jina lako la mtumiaji au nenosiri?"\n"Tembela "<b>"google.com/accounts/recovery"</b>"."</string>
     <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"Inakagua..."</string>
     <string name="lockscreen_unlock_label" msgid="737440483220667054">"Fungua"</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Ruwaza imefutwa"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Kiini kimeongezwa"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Ruwaza imekamilika"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Ongeza wiji"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Tupu"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Eneo la kufungua limepanuliwa."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Eneo la kufungua limekunjwa."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> ya wiji."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Kiteuzi cha mtumiaji"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Hali"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Kamera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Vidhibiti vya media"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Upangaji upya wa wiji umeanza."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Upangaji upya wa wiji umekamilika."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Wiji <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> imefutwa."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Panua eneo la kufungua."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Kufungua slaidi."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Kufungua kwa ruwaza."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Kufungua kwa uso."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Kufungua kwa PIN."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Kufungua kwa nenosiri."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Eneo la ruwaza."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Eneo la slaidi."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -901,7 +984,7 @@
     <string name="day" msgid="8144195776058119424">"siku"</string>
     <string name="days" msgid="4774547661021344602">"siku"</string>
     <string name="hour" msgid="2126771916426189481">"saa"</string>
-    <string name="hours" msgid="894424005266852993">"masaa"</string>
+    <string name="hours" msgid="894424005266852993">"saa"</string>
     <string name="minute" msgid="9148878657703769868">"dakika"</string>
     <string name="minutes" msgid="5646001005827034509">"Dakika"</string>
     <string name="second" msgid="3184235808021478">"sekunde"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Nakili URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Chagua maandishi"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Uchaguzi wa maandishi?"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"ongeza kwa kamusi"</string>
-    <string name="deleteText" msgid="7070985395199629156">"futa"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Ongeza kwenye kamusi"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Futa"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Mbinu ya uingizaji"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Vitendo vya maandishi"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Nafasi ya kuhafadhi inakwisha"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Fungua mitandao ya Wi-Fi inayopatikana"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Ingia kwenye mtandao wa Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Ingia kwenye mtandao"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Haikuweza kuunganisha kwa Mtandao-Hewa"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ina muunganisho duni wa Mtandao."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Kwa:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Charaza PIN inayohitajika:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Simu itaukata muunganisho kwa muda kutoka kwenye Wi-Fi inapokuwa imeunganishwa kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Ingiza kibambo"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Inatuma ujumbe wa SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; inatuma idadi kubwa ya jumbe za SMS. Je, unataka kuruhusu programu hii kuendelea kutuma jumbe?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Ruhusu"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Kataza"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ingependa kutuma ujumbe kwa &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Hii "<font fgcolor="#ffffb060">"huenda ikasababisha gharama"</font>" kwenye akaunti yako ya simu."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Hii itasababisha gharama kwenye akaunti yako ya simu."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Tuma"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Ghairi"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Kumbuka chaguo yangu"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Unaweza kubadilisha hii baadaye kwenye Mipangilio &gt; Programu"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Ruhusu Kila mara"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Usiruhusu Kamwe"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Kadi ya SIM imeondolewa"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"mtandao wa simu hutapatika hadi uanzishe upya na SIM kadi halali iliyoingizwa."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Kwisha"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Weka tarehe"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Weka"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Imekamilika"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Chaguo-msingi"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Hakuna vibali vinavyohitajika"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Ficha"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Onyesha zote"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">" MPYA: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">" MPYA: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Imetolewa na <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Hakuna vibali vinavyohitajika"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"huenda hii ikakugharimu pesa"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Hifadhi kubwa ya USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB imeunganishwa"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Umeunganisha kwenye kompyuta yako kupitia USB. Gusa kitufe hapa chini kama unataka kunakili faili kati ya kompyuta yako na hifadhi yako ya USB ya Android."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN imeamilishwa na <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Gusa ili kudhibiti mtandao."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Imeunganishwa kwa <xliff:g id="SESSION">%s</xliff:g>. Gusa ili kudhibiti mtandao."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Kila mara VPN iliyowashwa inaunganishwa…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Kila mara VPN iliyowashwa imeunganishwa"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Kila mara kuna hitilafu ya VPN iliyowashwa"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Gusa ili kuweka upya muunganisho"</string>
     <string name="upload_file" msgid="2897957172366730416">"Chagua faili"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Hakuna faili iliyochaguliwa"</string>
     <string name="reset" msgid="2448168080964209908">"Weka upya"</string>
@@ -1159,9 +1255,9 @@
     <string name="next_button_label" msgid="1080555104677992408">"Ifuatayo"</string>
     <string name="skip_button_label" msgid="1275362299471631819">"Ruka"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Utumizi wa juu wa data ya simu"</string>
-    <string name="throttle_warning_notification_message" msgid="3340822228599337743">"Gusa ili kujifunza zaidi kuhusu matumizi ya data ya simu ya mkononi."</string>
+    <string name="throttle_warning_notification_message" msgid="3340822228599337743">"Gusa ili kupata maelezo zaidi kuhusu matumizi ya data ya simu ya mkononi."</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Kiwango cha kupunguza data ya simu kimezidishwa."</string>
-    <string name="throttled_notification_message" msgid="5443457321354907181">"Gusa ili kujifunza zaidi kuhusu matumizi ya data ya simu ya mkononi."</string>
+    <string name="throttled_notification_message" msgid="5443457321354907181">"Gusa ili kupata maelezo zaidi kuhusu matumizi ya data ya simu ya mkononi."</string>
     <string name="no_matches" msgid="8129421908915840737">"Hakuna vinavyolingana"</string>
     <string name="find_on_page" msgid="1946799233822820384">"Pata kwenye ukurasa"</string>
   <plurals name="matches_found">
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Shiriki"</string>
     <string name="find" msgid="4808270900322985960">"Tafuta"</string>
     <string name="websearch" msgid="4337157977400211589">"Utafutaji Wavuti"</string>
+    <string name="find_next" msgid="5742124618942193978">"Pata ifuatayo"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Pata iliyotangulia"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Ombi la mahali kutoka <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Ombi la mahali"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Imeombwa na <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1193,7 +1291,7 @@
     <string name="sync_too_many_deletes" msgid="5296321850662746890">"Upeo wa ufutaji umezidishwa"</string>
     <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"Kuna vipengee <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> vilivyofutwa vya <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, akaunti <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. Je, unataka kufanya nini?"</string>
     <string name="sync_really_delete" msgid="2572600103122596243">"Futa vipengee"</string>
-    <string name="sync_undo_deletes" msgid="2941317360600338602">"Tengua ufutaji"</string>
+    <string name="sync_undo_deletes" msgid="2941317360600338602">"Tendua ufutaji"</string>
     <string name="sync_do_nothing" msgid="3743764740430821845">"Usifanye chochote kwa sasa"</string>
     <string name="choose_account_label" msgid="5655203089746423927">"Chagua akaunti"</string>
     <string name="add_account_label" msgid="2935267344849993553">"Ongeza akaunti"</string>
@@ -1222,8 +1320,8 @@
     <string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Songa"</string>
     <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Ingiza"</string>
     <string name="activitychooserview_choose_application" msgid="2125168057199941199">"Chagua programu"</string>
-    <string name="shareactionprovider_share_with" msgid="806688056141131819">"Gawa na"</string>
-    <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Gawa na <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+    <string name="shareactionprovider_share_with" msgid="806688056141131819">"Shiriki na"</string>
+    <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Shiriki na <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Utambo unaosonga. Gusa &amp; shika"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Sogeza juu kwa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
     <string name="description_direction_down" msgid="5087739728639014595">"Sogeza chini kwa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Simu"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Vipokeasauti"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Vipasa sauti vya kituo"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Sauti ya HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Mfumo"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Sauti ya Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Kwisha"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Towe la midia"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Inatambaza..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Inaunganisha..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Inapatikana"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Haipatikani"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Skrini Iliyojengwa ndani"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Skrini ya HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Uwekeleaji #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Onyesho pasiwaya limeunganishwa"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Skrini hii inaonyesha kwenye kifaa kingine"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Tenganisha"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Simu ya dharura"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Umesahau Ruwaza"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Ruwaza Isiyo sahihi"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Nenosiri Lisilo sahihi"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN isiyo sahihi"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Jaribu tena baada ya sekunde <xliff:g id="NUMBER">%d</xliff:g>."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Chora ruwaza yako"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Ingiza PIN ya SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Ingiza PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Ingiza Nenosiri"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM sasa imelemazwa. Ingiza msimbo wa PUK ili kuendelea. Wasiliana na mtoa huduma kwa maelezo."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Ingiza msimbo wa PIN unaopendelewa"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Thibitisha msimbo wa PIN unaopendelewa"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Inafungua kadi ya SIM..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Msimbo wa PIN usio sahihi."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Charaza PIN iliyo na tarakimu kati ya 4 na 8."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Msimbo wa PUK unafaa kuwa na nambari 8 au zaidi."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Ingiza upya msimbo sahihi wa PUK. Majaribio yanayorudiwa yatalemaza SIM kabisa."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Misimbo ya PIN haifanani"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Majaribio mengi mno ya mchoro"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Ili kufungua, ingia kwa Akaunti yako ya Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Jina la mtumiaji (barua pepe)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Nenosiri"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Ingia"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Jina la mtumiaji au nenosiri batili."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Je, umesahau jina lako la mtumiaji au nenosiri?"\n"Tembela "<b>"Bgoogle.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Inakagua akaunti…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Umeingiza nenosiri lako kwa makosa mara <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n" Jaribu tena baada ya sekunde <xliff:g id="NUMBER_1">%d</xliff:g>."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Umeingiza nenosiri lako kwa makosa mara <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n" Jaribu tena baada ya sekunde <xliff:g id="NUMBER_1">%d</xliff:g>."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Umechora ruwaza yako ya kufunga kwa makosa mara <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n" Jaribu tena baada ya sekunde <xliff:g id="NUMBER_1">%d</xliff:g>."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Umejaribu kufungua kompyuta ndogo kwa njia isiyo sahihi mara <xliff:g id="NUMBER_0">%d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%d</xliff:g> zaidi yasiyofaulu, kompyuta ndogo itarejeshwa katika mfumo chaguo-msingi ilivyotoka kiwandani data yote ya mtumiaji itapotea."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Umejaribu kufungua simu kwa njia isiyo sahihi mara <xliff:g id="NUMBER_0">%d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%d</xliff:g> zaidi yasiyofaulu, simu itarejeshwa katika mfumo chaguo-msingi ilivyotoka kiwandani na data yote ya mtumiaji itapotea."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Umejaribu kufungua kompyuta ndogo kwa njia isiyo sahihi mara <xliff:g id="NUMBER">%d</xliff:g>. Sasa kompyuta ndogo itarejeshwa katika mfumo chaguo-msingi ilivyotoka kiwandani."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Umejaribu kufungua simu kwa njia isiyo sahihi mara <xliff:g id="NUMBER">%d</xliff:g>. Sasa simu  itarejeshwa katika mfumo chaguo-msingi ilivyotoka kiwandani."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Umekosea katika kuweka mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%d</xliff:g> bila kufaulu, utaombwa kufungua kompyuta yako ndogo kwa kutumia akaunti yako ya barua pepe."\n\n" Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%d</xliff:g>."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Umekosea kuchora mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%d</xliff:g> yasiyofaulu, utaombwa kufungua simu yako kwa kutumia akaunti ya barua pepe."\n\n" Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%d</xliff:g>."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Ondoa"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Ongeza sauti zaidi ya kiwango salama? "\n"Kusikiliza kwa sauti ya juu kwa muda mrefu kunaweza kuharibu uwezo wako wa kusikia."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Endelea kushikilia chini kwa vidole vyako viwili ili kuwezesha ufikivu."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Ufikivu umewezeshwa."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Ufikivu umeghairiwa."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Mtumiaji wa sasa <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Mmiliki"</string>
 </resources>
diff --git a/core/res/res/values-sw380dp-land/dimens.xml b/core/res/res/values-sw380dp-land/dimens.xml
new file mode 100644
index 0000000..20eb1be
--- /dev/null
+++ b/core/res/res/values-sw380dp-land/dimens.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/dimens.xml
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <!-- Top margin for the clock view --> 
+    <dimen name="kg_clock_top_margin">48dp</dimen>
+</resources>
diff --git a/core/res/res/values-sw380dp/dimens.xml b/core/res/res/values-sw380dp/dimens.xml
new file mode 100644
index 0000000..fc0e85d
--- /dev/null
+++ b/core/res/res/values-sw380dp/dimens.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <!-- Width of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) -->
+    <dimen name="keyguard_security_width">340dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/core/res/res/values-sw600dp-land/dimens.xml b/core/res/res/values-sw600dp-land/dimens.xml
new file mode 100644
index 0000000..5507e5f
--- /dev/null
+++ b/core/res/res/values-sw600dp-land/dimens.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/dimens.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <!-- Top margin for the clock view --> 
+    <dimen name="kg_clock_top_margin">85dp</dimen>
+
+    <!-- Size of margin on the right of keyguard's status view -->
+    <dimen name="kg_status_line_font_right_margin">16dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/core/res/res/values-sw600dp-land/integers.xml b/core/res/res/values-sw600dp-land/integers.xml
new file mode 100644
index 0000000..b724c90
--- /dev/null
+++ b/core/res/res/values-sw600dp-land/integers.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <integer name="kg_widget_region_weight">50</integer>
+    <integer name="kg_security_flipper_weight">50</integer>
+    <integer name="kg_glowpad_rotation_offset">0</integer>
+</resources>
diff --git a/core/res/res/values-sw600dp-port/integers.xml b/core/res/res/values-sw600dp-port/integers.xml
new file mode 100644
index 0000000..65b854a
--- /dev/null
+++ b/core/res/res/values-sw600dp-port/integers.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <integer name="kg_widget_region_weight">46</integer>
+    <integer name="kg_security_flipper_weight">54</integer>
+</resources>
\ No newline at end of file
diff --git a/core/res/res/values-sw600dp/alias.xml b/core/res/res/values-sw600dp/alias.xml
new file mode 100644
index 0000000..bf3eecb
--- /dev/null
+++ b/core/res/res/values-sw600dp/alias.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <!-- Alias used to reference one of two possible layouts in keyguard.  -->
+    <item type="layout" name="keyguard_eca">@android:layout/keyguard_emergency_carrier_area</item>
+</resources>
diff --git a/core/res/res/values-sw600dp/bools.xml b/core/res/res/values-sw600dp/bools.xml
index b8db31f..ddc48c5 100644
--- a/core/res/res/values-sw600dp/bools.xml
+++ b/core/res/res/values-sw600dp/bools.xml
@@ -16,4 +16,12 @@
 
 <resources>
     <bool name="target_honeycomb_needs_options_menu">false</bool>
+    <bool name="show_ongoing_ime_switcher">true</bool>
+    <bool name="kg_share_status_area">false</bool>
+    <bool name="kg_sim_puk_account_full_screen">false</bool>
+    <bool name="kg_show_ime_at_screen_on">false</bool>
+    <!-- No camera for you, tablet user -->
+    <bool name="kg_enable_camera_default_widget">false</bool>
+    <bool name="kg_center_small_widgets_vertically">true</bool>
+    <bool name="kg_top_align_page_shrink_on_bouncer_visible">false</bool>
 </resources>
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index 1486d9c..5a007ce 100644
--- a/core/res/res/values-sw600dp/config.xml
+++ b/core/res/res/values-sw600dp/config.xml
@@ -37,5 +37,8 @@
          used for picking activities to handle an intent. -->
     <integer name="config_maxResolverActivityColumns">3</integer>
 
+    <!-- Use a larger scaling span for larger screen devices. -->
+    <dimen name="config_minScalingSpan">32mm</dimen>
+
 </resources>
 
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 8937c2a..52c230b 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -45,6 +45,9 @@
     <!-- Size of lockscreen outerring on unsecure unlock LockScreen -->
     <dimen name="keyguard_lockscreen_outerring_diameter">364dp</dimen>
 
+    <!-- Height of FaceUnlock view in keyguard -->
+    <dimen name="face_unlock_height">430dip</dimen>
+
     <!-- target placement radius for GlowPadView. Should be 1/2 of outerring diameter. -->
     <dimen name="glowpadview_target_placement_radius">182dip</dimen>
 
@@ -74,5 +77,40 @@
     <!-- Preference fragment padding, sides -->
     <dimen name="preference_fragment_padding_side">24dp</dimen>
     <dimen name="preference_screen_header_padding_side">24dip</dimen>
-</resources>
 
+    <!-- Keyguard dimensions -->
+    <!-- Size of the clock font in keyguard's status view -->
+    <dimen name="kg_status_clock_font_size">141dp</dimen>
+
+    <!-- Size of the date font in keyguard's status view  -->
+    <dimen name="kg_status_date_font_size">25.5dp</dimen>
+
+    <!-- Size of the generic status lines keyguard's status view  -->
+    <dimen name="kg_status_line_font_size">16sp</dimen>
+
+    <!-- Top margin for the clock view --> 
+    <dimen name="kg_clock_top_margin">0dp</dimen>
+
+    <!-- Size of margin on the right of keyguard's status view -->
+    <dimen name="kg_status_line_font_right_margin">50dp</dimen>
+
+    <!-- Horizontal padding for the widget pager -->
+    <dimen name="kg_widget_pager_horizontal_padding">24dp</dimen>
+
+    <!-- Top padding for the widget pager -->
+    <dimen name="kg_widget_pager_top_padding">0dp</dimen>
+
+    <!-- Bottom padding for the widget pager -->
+    <dimen name="kg_widget_pager_bottom_padding">0dp</dimen>
+
+    <!-- Top margin for the runway lights. We add a negative margin in large
+        devices to account for the widget pager padding -->
+    <dimen name="kg_runway_lights_top_margin">-10dp</dimen>
+
+    <!-- Margin around the various security views -->
+    <dimen name="keyguard_security_view_margin">12dp</dimen>
+
+    <!-- Margin around the various security views -->
+    <dimen name="keyguard_muliuser_selector_margin">12dp</dimen>
+
+</resources>
diff --git a/core/res/res/values-sw600dp/integers.xml b/core/res/res/values-sw600dp/integers.xml
new file mode 100644
index 0000000..de9829c
--- /dev/null
+++ b/core/res/res/values-sw600dp/integers.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <integer name="kg_carousel_angle">60</integer>
+</resources>
diff --git a/core/res/res/values-sw720dp-land/arrays.xml b/core/res/res/values-sw720dp-land/arrays.xml
deleted file mode 100644
index d845875..0000000
--- a/core/res/res/values-sw720dp-land/arrays.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/res/any/colors.xml
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <array name="lockscreen_chevron_drawables">
-        <item>@drawable/ic_lockscreen_chevron_right</item>
-        <item>@null</item>
-        <item>@null</item>
-        <item>@null</item>
-    </array>
-
-</resources>
diff --git a/core/res/res/values-sw720dp-land/dimens.xml b/core/res/res/values-sw720dp-land/dimens.xml
new file mode 100644
index 0000000..14726ab
--- /dev/null
+++ b/core/res/res/values-sw720dp-land/dimens.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/dimens.xml
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <!-- Top margin for the clock view --> 
+    <dimen name="kg_clock_top_margin">174dp</dimen>
+
+    <!-- Size of margin on the right of keyguard's status view -->
+    <dimen name="kg_status_line_font_right_margin">16dp</dimen>
+
+    <!-- Horizontal padding for the widget pager -->
+    <dimen name="kg_widget_pager_horizontal_padding">32dp</dimen>
+</resources>
diff --git a/core/res/res/values-sw720dp-port/arrays.xml b/core/res/res/values-sw720dp-port/arrays.xml
deleted file mode 100644
index d845875..0000000
--- a/core/res/res/values-sw720dp-port/arrays.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/res/any/colors.xml
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <array name="lockscreen_chevron_drawables">
-        <item>@drawable/ic_lockscreen_chevron_right</item>
-        <item>@null</item>
-        <item>@null</item>
-        <item>@null</item>
-    </array>
-
-</resources>
diff --git a/core/res/res/values-sw720dp-port/integers.xml b/core/res/res/values-sw720dp-port/integers.xml
new file mode 100644
index 0000000..5f85f71
--- /dev/null
+++ b/core/res/res/values-sw720dp-port/integers.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <integer name="kg_widget_region_weight">48</integer>
+    <integer name="kg_security_flipper_weight">52</integer>
+</resources>
\ No newline at end of file
diff --git a/core/res/res/values-sw720dp/dimens.xml b/core/res/res/values-sw720dp/dimens.xml
index fc336ae..ccdb4be 100644
--- a/core/res/res/values-sw720dp/dimens.xml
+++ b/core/res/res/values-sw720dp/dimens.xml
@@ -70,6 +70,51 @@
         This helps in aligning titles when some items have icons and some don't. When space is
         at a premium, we don't pre-allocate any space. -->
     <dimen name="preference_icon_minWidth">56dp</dimen>
+
+    <!-- Keyguard dimensions -->
+    <!-- Size of the clock font in keyguard's status view -->
+    <dimen name="kg_status_clock_font_size">188dp</dimen>
+
+    <!-- Size of the date font in keyguard's status view  -->
+    <dimen name="kg_status_date_font_size">34dp</dimen>
+
+    <!-- Size of the generic status lines keyguard's status view  -->
+    <dimen name="kg_status_line_font_size">19sp</dimen>
+
+    <!-- Top margin for the clock view --> 
+    <dimen name="kg_clock_top_margin">0dp</dimen>
+
+    <!-- Size of margin on the right of keyguard's status view -->
+    <dimen name="kg_status_line_font_right_margin">32dp</dimen>
+
+    <!-- Horizontal padding for the widget pager -->
+    <dimen name="kg_widget_pager_horizontal_padding">80dp</dimen>
+
+    <!-- Top padding for the widget pager -->
+    <dimen name="kg_widget_pager_top_padding">0dp</dimen>
+
+    <!-- Bottom padding for the widget pager -->
+    <dimen name="kg_widget_pager_bottom_padding">0dp</dimen>
+
+    <!-- Top margin for the runway lights. We add a negative margin in large
+        devices to account for the widget pager padding -->
+    <dimen name="kg_runway_lights_top_margin">-30dp</dimen>
+
+    <!-- Margin around the various security views -->
+    <dimen name="keyguard_muliuser_selector_margin">24dp</dimen>
+
+    <!-- Stroke width of the frame for the circular avatars. -->
+    <dimen name="keyguard_avatar_frame_stroke_width">3dp</dimen>
+
+    <!-- Size of the avator on the multiuser lockscreen. -->
+    <dimen name="keyguard_avatar_size">88dp</dimen>
+
+    <!-- Size of the text under the avator on the multiuser lockscreen. -->
+    <dimen name="keyguard_avatar_name_size">12sp</dimen>
+
+    <!-- Width of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) -->
+    <dimen name="keyguard_security_width">420dp</dimen>
+
+    <!-- Height of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) -->
+    <dimen name="keyguard_security_height">420dp</dimen>
 </resources>
-
-
diff --git a/core/res/res/values-sw720dp/styles.xml b/core/res/res/values-sw720dp/styles.xml
index 640e898..fee1c24f 100644
--- a/core/res/res/values-sw720dp/styles.xml
+++ b/core/res/res/values-sw720dp/styles.xml
@@ -16,8 +16,8 @@
 
 <resources>
     <style name="PreferencePanel">
-        <item name="android:layout_marginLeft">@dimen/preference_screen_side_margin</item>
-        <item name="android:layout_marginRight">@dimen/preference_screen_side_margin</item>
+        <item name="android:layout_marginStart">@dimen/preference_screen_side_margin</item>
+        <item name="android:layout_marginEnd">@dimen/preference_screen_side_margin</item>
         <item name="android:layout_marginTop">@dimen/preference_screen_top_margin</item>
         <item name="android:layout_marginBottom">@dimen/preference_screen_bottom_margin</item>
         <item name="android:background">?attr/detailsElementBackground</item>
diff --git a/core/res/res/values-th-rTH/donottranslate-cldr.xml b/core/res/res/values-th-rTH/donottranslate-cldr.xml
index 7049c529..2517143 100644
--- a/core/res/res/values-th-rTH/donottranslate-cldr.xml
+++ b/core/res/res/values-th-rTH/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">มกราคม</string>
-    <string name="month_long_standalone_february">กุมภาพันธ์</string>
-    <string name="month_long_standalone_march">มีนาคม</string>
-    <string name="month_long_standalone_april">เมษายน</string>
-    <string name="month_long_standalone_may">พฤษภาคม</string>
-    <string name="month_long_standalone_june">มิถุนายน</string>
-    <string name="month_long_standalone_july">กรกฎาคม</string>
-    <string name="month_long_standalone_august">สิงหาคม</string>
-    <string name="month_long_standalone_september">กันยายน</string>
-    <string name="month_long_standalone_october">ตุลาคม</string>
-    <string name="month_long_standalone_november">พฤศจิกายน</string>
-    <string name="month_long_standalone_december">ธันวาคม</string>
-
-    <string name="month_long_january">มกราคม</string>
-    <string name="month_long_february">กุมภาพันธ์</string>
-    <string name="month_long_march">มีนาคม</string>
-    <string name="month_long_april">เมษายน</string>
-    <string name="month_long_may">พฤษภาคม</string>
-    <string name="month_long_june">มิถุนายน</string>
-    <string name="month_long_july">กรกฎาคม</string>
-    <string name="month_long_august">สิงหาคม</string>
-    <string name="month_long_september">กันยายน</string>
-    <string name="month_long_october">ตุลาคม</string>
-    <string name="month_long_november">พฤศจิกายน</string>
-    <string name="month_long_december">ธันวาคม</string>
-
-    <string name="month_medium_january">ม.ค.</string>
-    <string name="month_medium_february">ก.พ.</string>
-    <string name="month_medium_march">มี.ค.</string>
-    <string name="month_medium_april">เม.ย.</string>
-    <string name="month_medium_may">พ.ค.</string>
-    <string name="month_medium_june">มิ.ย.</string>
-    <string name="month_medium_july">ก.ค.</string>
-    <string name="month_medium_august">ส.ค.</string>
-    <string name="month_medium_september">ก.ย.</string>
-    <string name="month_medium_october">ต.ค.</string>
-    <string name="month_medium_november">พ.ย.</string>
-    <string name="month_medium_december">ธ.ค.</string>
-
-    <string name="month_shortest_january">ม.ค.</string>
-    <string name="month_shortest_february">ก.พ.</string>
-    <string name="month_shortest_march">มี.ค.</string>
-    <string name="month_shortest_april">เม.ย.</string>
-    <string name="month_shortest_may">พ.ค.</string>
-    <string name="month_shortest_june">มิ.ย.</string>
-    <string name="month_shortest_july">ก.ค.</string>
-    <string name="month_shortest_august">ส.ค.</string>
-    <string name="month_shortest_september">ก.ย.</string>
-    <string name="month_shortest_october">ต.ค.</string>
-    <string name="month_shortest_november">พ.ย.</string>
-    <string name="month_shortest_december">ธ.ค.</string>
-
-    <string name="day_of_week_long_sunday">วันอาทิตย์</string>
-    <string name="day_of_week_long_monday">วันจันทร์</string>
-    <string name="day_of_week_long_tuesday">วันอังคาร</string>
-    <string name="day_of_week_long_wednesday">วันพุธ</string>
-    <string name="day_of_week_long_thursday">วันพฤหัสบดี</string>
-    <string name="day_of_week_long_friday">วันศุกร์</string>
-    <string name="day_of_week_long_saturday">วันเสาร์</string>
-
-    <string name="day_of_week_medium_sunday">อา.</string>
-    <string name="day_of_week_medium_monday">จ.</string>
-    <string name="day_of_week_medium_tuesday">อ.</string>
-    <string name="day_of_week_medium_wednesday">พ.</string>
-    <string name="day_of_week_medium_thursday">พฤ.</string>
-    <string name="day_of_week_medium_friday">ศ.</string>
-    <string name="day_of_week_medium_saturday">ส.</string>
-
-    <string name="day_of_week_short_sunday">อา.</string>
-    <string name="day_of_week_short_monday">จ.</string>
-    <string name="day_of_week_short_tuesday">อ.</string>
-    <string name="day_of_week_short_wednesday">พ.</string>
-    <string name="day_of_week_short_thursday">พฤ.</string>
-    <string name="day_of_week_short_friday">ศ.</string>
-    <string name="day_of_week_short_saturday">ส.</string>
-
-    <string name="day_of_week_shortest_sunday">อ</string>
-    <string name="day_of_week_shortest_monday">จ</string>
-    <string name="day_of_week_shortest_tuesday">อ</string>
-    <string name="day_of_week_shortest_wednesday">พ</string>
-    <string name="day_of_week_shortest_thursday">พ</string>
-    <string name="day_of_week_shortest_friday">ศ</string>
-    <string name="day_of_week_shortest_saturday">ส</string>
-
-    <string name="am">ก่อนเที่ยง</string>
-    <string name="pm">หลังเที่ยง</string>
-    <string name="yesterday">เมื่อวาน</string>
-    <string name="today">วันนี้</string>
-    <string name="tomorrow">พรุ่งนี้</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
diff --git a/core/res/res/values-th/donottranslate-cldr.xml b/core/res/res/values-th/donottranslate-cldr.xml
index f3196d1..7ab4191 100644
--- a/core/res/res/values-th/donottranslate-cldr.xml
+++ b/core/res/res/values-th/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">มกราคม</string>
-    <string name="month_long_standalone_february">กุมภาพันธ์</string>
-    <string name="month_long_standalone_march">มีนาคม</string>
-    <string name="month_long_standalone_april">เมษายน</string>
-    <string name="month_long_standalone_may">พฤษภาคม</string>
-    <string name="month_long_standalone_june">มิถุนายน</string>
-    <string name="month_long_standalone_july">กรกฎาคม</string>
-    <string name="month_long_standalone_august">สิงหาคม</string>
-    <string name="month_long_standalone_september">กันยายน</string>
-    <string name="month_long_standalone_october">ตุลาคม</string>
-    <string name="month_long_standalone_november">พฤศจิกายน</string>
-    <string name="month_long_standalone_december">ธันวาคม</string>
-
-    <string name="month_long_january">มกราคม</string>
-    <string name="month_long_february">กุมภาพันธ์</string>
-    <string name="month_long_march">มีนาคม</string>
-    <string name="month_long_april">เมษายน</string>
-    <string name="month_long_may">พฤษภาคม</string>
-    <string name="month_long_june">มิถุนายน</string>
-    <string name="month_long_july">กรกฎาคม</string>
-    <string name="month_long_august">สิงหาคม</string>
-    <string name="month_long_september">กันยายน</string>
-    <string name="month_long_october">ตุลาคม</string>
-    <string name="month_long_november">พฤศจิกายน</string>
-    <string name="month_long_december">ธันวาคม</string>
-
-    <string name="month_medium_january">ม.ค.</string>
-    <string name="month_medium_february">ก.พ.</string>
-    <string name="month_medium_march">มี.ค.</string>
-    <string name="month_medium_april">เม.ย.</string>
-    <string name="month_medium_may">พ.ค.</string>
-    <string name="month_medium_june">มิ.ย.</string>
-    <string name="month_medium_july">ก.ค.</string>
-    <string name="month_medium_august">ส.ค.</string>
-    <string name="month_medium_september">ก.ย.</string>
-    <string name="month_medium_october">ต.ค.</string>
-    <string name="month_medium_november">พ.ย.</string>
-    <string name="month_medium_december">ธ.ค.</string>
-
-    <string name="month_shortest_january">ม.ค.</string>
-    <string name="month_shortest_february">ก.พ.</string>
-    <string name="month_shortest_march">มี.ค.</string>
-    <string name="month_shortest_april">เม.ย.</string>
-    <string name="month_shortest_may">พ.ค.</string>
-    <string name="month_shortest_june">มิ.ย.</string>
-    <string name="month_shortest_july">ก.ค.</string>
-    <string name="month_shortest_august">ส.ค.</string>
-    <string name="month_shortest_september">ก.ย.</string>
-    <string name="month_shortest_october">ต.ค.</string>
-    <string name="month_shortest_november">พ.ย.</string>
-    <string name="month_shortest_december">ธ.ค.</string>
-
-    <string name="day_of_week_long_sunday">วันอาทิตย์</string>
-    <string name="day_of_week_long_monday">วันจันทร์</string>
-    <string name="day_of_week_long_tuesday">วันอังคาร</string>
-    <string name="day_of_week_long_wednesday">วันพุธ</string>
-    <string name="day_of_week_long_thursday">วันพฤหัสบดี</string>
-    <string name="day_of_week_long_friday">วันศุกร์</string>
-    <string name="day_of_week_long_saturday">วันเสาร์</string>
-
-    <string name="day_of_week_medium_sunday">อา.</string>
-    <string name="day_of_week_medium_monday">จ.</string>
-    <string name="day_of_week_medium_tuesday">อ.</string>
-    <string name="day_of_week_medium_wednesday">พ.</string>
-    <string name="day_of_week_medium_thursday">พฤ.</string>
-    <string name="day_of_week_medium_friday">ศ.</string>
-    <string name="day_of_week_medium_saturday">ส.</string>
-
-    <string name="day_of_week_short_sunday">อา.</string>
-    <string name="day_of_week_short_monday">จ.</string>
-    <string name="day_of_week_short_tuesday">อ.</string>
-    <string name="day_of_week_short_wednesday">พ.</string>
-    <string name="day_of_week_short_thursday">พฤ.</string>
-    <string name="day_of_week_short_friday">ศ.</string>
-    <string name="day_of_week_short_saturday">ส.</string>
-
-    <string name="day_of_week_shortest_sunday">อ</string>
-    <string name="day_of_week_shortest_monday">จ</string>
-    <string name="day_of_week_shortest_tuesday">อ</string>
-    <string name="day_of_week_shortest_wednesday">พ</string>
-    <string name="day_of_week_shortest_thursday">พ</string>
-    <string name="day_of_week_shortest_friday">ศ</string>
-    <string name="day_of_week_shortest_saturday">ส</string>
-
-    <string name="am">ก่อนเที่ยง</string>
-    <string name="pm">หลังเที่ยง</string>
-    <string name="yesterday">เมื่อวาน</string>
-    <string name="today">วันนี้</string>
-    <string name="tomorrow">พรุ่งนี้</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 976ff8a..0a86a86 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"ตัวเลือกโทรศัพท์"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"ล็อกหน้าจอ"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"ปิดเครื่อง"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"รายงานข้อบกพร่อง"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"ใช้รายงานข้อบกพร่อง"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"การดำเนินการนี้จะรวบรวมข้อมูลเกี่ยวกับสถานะปัจจุบันของอุปกรณ์ของคุณ โดยจะส่งไปในรูปแบบข้อความอีเมล อาจใช้เวลาสักครู่ตั้งแต่เริ่มการสร้างรายงานข้อบกพร่องจนกระทั่งเสร็จสมบูรณ์ โปรดอดทนรอ"</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"โหมดปิดเสียง"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"ปิดเสียงไว้"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"เปิดเสียงแล้ว"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"ข้อความของคุณ"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"อ่านและเขียน SMS อีเมล และข้อความอื่นๆ ของคุณ"</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"ข้อมูลส่วนบุคคลของคุณ"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"การเข้าถึงสมุดโทรศัพท์และปฏิทินที่จัดเก็บอยู่บนแท็บเล็ตโดยตรง"</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"เข้าถึงที่อยู่ติดต่อและปฏิทินของที่จัดเก็บบนโทรศัพท์โดยตรง"</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"เข้าถึงข้อมูลเกี่ยวกับคุณซึ่งจัดเก็บไว้ในบัตรผู้ติดต่อของคุณได้โดยตรง"</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"ข้อมูลทางสังคมของคุณ"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"เข้าถึงข้อมูลเกี่ยวกับผู้ติดต่อและเครือข่ายสังคมของคุณโดยตรง"</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"ตำแหน่งของคุณ"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"ตรวจดูตำแหน่งทางกายภาพของคุณ"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"การสื่อสารของเครือข่าย"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"เข้าถึงคุณลักษณะเครือข่ายต่างๆ"</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"บลูทูธ"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"เข้าถึงอุปกรณ์และเครือข่ายผ่านบลูทูธ"</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"การตั้งค่าเสียง"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"เปลี่ยนการตั้งค่าเสียง"</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"มีผลต่อแบตเตอรี่"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"ใช้คุณลักษณะที่ทำให้พลังงานแบตเตอรี่ลดลงอย่างรวดเร็ว"</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"ปฏิทิน"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"เข้าถึงปฏิทินและกิจกรรมโดยตรง"</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"อ่านพจนานุกรมผู้ใช้"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"อ่านคำในพจนานุกรมผู้ใช้"</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"เขียนพจนานุกรมผู้ใช้"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"เพิ่มคำลงในพจนานุกรมผู้ใช้"</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"บุ๊กมาร์กและประวัติ"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"เข้าถึงบุ๊กมาร์กและประวัติของเบราว์เซอร์โดยตรง"</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"เตือน"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"ตั้งนาฬิกาปลุก"</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"ข้อความเสียง"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"เข้าถึงข้อความเสียงโดยตรง"</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"ไมโครโฟน"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"เข้าถึงไมโครโฟนเพื่อบันทึกเสียงโดยตรง"</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"กล้องถ่ายรูป"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"เข้าถึงกล้องถ่ายรูปเพื่อดูภาพและวิดีโอที่ถ่ายไว้โดยตรง"</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"ข้อมูลแอปพลิเคชันของคุณ"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"สามารถส่งผลต่อการทำงานของแอปพลิเคชันอื่นในอุปกรณ์ของคุณ"</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"วอลเปเปอร์"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"เปลี่ยนการตั้งค่าวอลเปเปอร์ของอุปกรณ์"</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"นาฬิกา"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"เปลี่ยนเวลาหรือเขตเวลาของอุปกรณ์"</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"แถบสถานะ"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"เปลี่ยนการตั้งค่าแถบสถานะของอุปกรณ์"</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"การตั้งค่าการซิงค์"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"เข้าถึงการตั้งค่าการซิงค์"</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"บัญชีของคุณ"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"เข้าถึงบัญชีที่ใช้งานได้"</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"การควบคุมฮาร์ดแวร์"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"การเข้าถึงและควบคุมของระบบในระดับต่ำ"</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"เครื่องมือในการพัฒนา"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"คุณลักษณะที่จำเป็นสำหรับนักพัฒนาแอปพลิเคชันเท่านั้น"</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"UI แอปพลิเคชันอื่นๆ"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"ส่งผลต่อ UI ของแอปพลิเคชันอื่น"</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>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ WAP การอนุญาตนี้รวมถึงความสามารถในการตรวจสอบหรือลบข้อความที่ส่งมาให้คุณโดยไม่ต้องแสดงให้คุณเห็น"</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"เรียกแอปพลิเคชันที่ทำงานอยู่"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"อนุญาตให้แอปพลิเคชันเรียกดูข้อมูลเกี่ยวกับงานที่ดำเนินการอยู่ในขณะนี้และเมื่อเร็วๆ นี้ ซึ่งอาจทำให้แอปพลิเคชันสามารถค้นข้อมูลได้ว่าอุปกรณ์นี้ใช้แอปพลิเคชันใดบ้าง"</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"โต้ตอบระหว่างผู้ใช้"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"อนุญาตให้แอปพลิเคชันทำงานได้กับผู้ใช้หลายรายบนอุปกรณ์นี้ แอปพลิเคชันที่เป็นอันตรายอาจใช้การทำงานนี้ในการบุกรุกการป้องกันระหว่างผู้ใช้"</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"ใบอนุญาตฉบับเต็มสำหรับการโต้ตอบระหว่างผู้ใช้"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"อนุญาตให้ทำการโต้ตอบทุกชนิดที่เป็นไปได้กับผู้ใช้ต่างๆ"</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"จัดการผู้ใช้"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"อนุญาตให้แอปพลิเคชันจัดการผู้ใช้บนอุปกรณ์ รวมทั้งการถามคำถาม การสร้าง และการลบ"</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"ดึงรายละเอียดของแอปที่ทำงานอยู่"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"อนุญาตให้แอปพลิเคชันดึงข้อมูลเกี่ยวกับงานที่กำลังเรียกใช้อยู่ในปัจจุบันและงานล่าสุด แอปพลิเคชันที่เป็นอันตรายอาจค้นพบข้อมูลเฉพาะตัวเกี่ยวกับแอปพลิเคชันอื่นๆ"</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"จัดลำดับแอปพลิเคชันที่ทำงานอยู่ใหม่"</string>
@@ -243,6 +287,14 @@
     <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="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"เปิดใช้งานการเข้าถึงชั่วคราว"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"ช่วยให้แอปพลิเคชันสามารถเปิดใช้งานการเข้าถึงบนอุปกรณ์เป็นการชั่วคราว แอปพลิเคชันที่เป็นอันตรายอาจเปิดใช้งานการเข้าถึงโดยไม่ได้รับความยินยอมจากผู้ใช้"</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"เรียกข้อมูลหน้าต่าง"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"อนุญาตให้แอปพลิเคชันดึงข้อมูลเกี่ยวกับหน้าต่างจากเครื่องมือจัดการหน้าต่าง แอปพลิเคชันที่เป็นอันตรายอาจดึงข้อมูลที่มีไว้เพื่อการใช้ของระบบภายใน"</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"กรองกิจกรรม"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"อนุญาตให้แอปพลิเคชันลงทะเบียนตัวกรองข้อมูลซึ่งจะกรองสตรีมกิจกรรมทั้งหมดของผู้ใช้ก่อนที่จะทำการเผยแพร่ออกไป แอปพลิเคชันที่เป็นอันตรายอาจควบคุม UI ของระบบโดยไม่ต้องให้ผู้ใช้จัดการ"</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"ขยายการแสดงผล"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"อนุญาตให้แอปพลิเคชันขยายเนื้อหาที่แสดงผล แอปพลิเคชันที่เป็นอันตรายอาจแปลงเนื้อหาที่แสดงในลักษณะที่ทำให้ไม่สามารถใช้อุปกรณ์ได้"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"ปิดการทำงานบางส่วน"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"กำหนดให้ตัวจัดการกิจกรรมอยู่ในสถานะปิดระบบ โดยไม่ได้ปิดระบบอย่างสมบูรณ์"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ป้องกันการเปลี่ยนแอปพลิเคชัน"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"อนุญาตให้แอปพลิเคชันควบคุมจำนวนสูงสุดของกระบวนการที่จะเรียกใช้ ไม่จำเป็นต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"บังคับปิดแอปพลิเคชันในพื้นหลัง"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"อนุญาตให้แอปพลิเคชันควบคุมว่ากิจกรรมจะสิ้นสุดทันทีที่เข้าสู่พื้นหลังเสมอหรือไม่ ไม่จำเป็นต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"แก้ไขสถิติแบตเตอรี่"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"อนุญาตให้แอปพลิเคชันแก้ไขสถิติของแบตเตอรี่ที่เก็บรวบรวมไว้ ไม่ใช้สำหรับแอปพลิเคชันทั่วไป"</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"อ่านสถิติของแบตเตอรี่่"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลการใช้แบตเตอรี่ที่มีพลังงานเหลือน้อยในปัจจุบัน โดยอาจอนุญาตให้แอปพลิเคชันค้นหาข้อมูลรายละเอียดว่าคุณใช้งานแอปพลิเคชันใดบ้าง"</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"แก้ไขสถิติของแบตเตอรี่"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"อนุญาตให้แอปพลิเคชันแก้ไขสถิติของแบตเตอรี่่ที่เก็บรวบรวมไว้ ไม่ใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_backup" msgid="470013022865453920">"ควบคุมการสำรองและคืนค่า"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"อนุญาตให้แอปพลิเคชันควบคุมการสำรองข้อมูลของระบบและกลไกการเรียกคืน ไม่ใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"ยืนยันการสำรองข้อมูลหรือการคืนค่าทั้งหมด"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"แสดงหน้าต่างที่ไม่ได้รับอนุญาต"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"อนุญาตให้แอปพลิเคชันสร้างหน้าต่างสำหรับให้ใช้โดยส่วนติดต่อผู้ใช้ของระบบภายใน ไม่ใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"ปิดคลุมแอปอื่นๆ"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"อนุญาตให้แอปพลิเคชันแสดงหน้าต่างการแจ้งเตือนของระบบ ซึ่งบางหน้าต่างอาจเข้าควบคุมทั้งหน้าจอ"</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"อนุญาตให้แอปพลิเคชันทำงานบนแอปพลิเคชันหรือส่วนอื่นๆ ของส่วนติดต่อผู้ใช้ ซึ่งอาจรบกวนการใช้งานส่วนติดต่อของคุณในแอปพลิเคชันต่างๆ หรือเปลี่ยนสิ่งที่คุณคิดว่าคุณเห็นในแอปพลิเคชันอื่นๆ"</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="permlab_freezeScreen" msgid="4708181184441880175">"ตรึงหน้าจอ"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"อนุญาตให้แอปพลิเคชันตรึงหน้าจอไว้ชั่วคราวสำหรับการเปลี่ยนเป็นแบบเต็มหน้าจอ"</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"กดปุ่มต่างๆ และปุ่ม Ctrl"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"อนุญาตให้แอปพลิเคชันส่งกิจกรรมการนำเข้าข้อมูลของตนเอง (เช่น การกดปุ่ม) ไปยังแอปพลิเคชันอื่นๆ แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้เข้าควบคุมแท็บเล็ต"</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"อนุญาตให้แอปพลิเคชันส่งกิจกรรมการนำเข้าข้อมูลของตนเอง (เช่น การกดปุ่ม) ไปยังแอปพลิเคชันอื่นๆ แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้เข้าควบคุมโทรศัพท์"</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"ติดตั้งแอปพลิเคชันโดยตรง"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"อนุญาตให้แอปพลิเคชันติดตั้งแพคเกจ Android ใหม่หรือที่อัปเดต แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ในการเพิ่มแอปพลิเคชันใหม่ๆ ด้วยสิทธิ์ที่สูงนี้ได้ตามต้องการ"</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="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"อนุญาตให้แอปพลิเคชันสร้างพื้นที่ว่างในที่จัดเก็บข้อมูลของแท็บเล็ต โดยลบไฟล์ในไดเรกทอรีแคชของแอปพลิเคชันอื่นๆ ซึ่งอาจทำให้แอปพลิเคชันอื่นเริ่มทำงานช้ากว่าเดิมเนื่องจากต้องดึงข้อมูลของตนซ้ำ"</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"อนุญาตให้แอปพลิเคชันสร้างพื้นที่ว่างในที่จัดเก็บข้อมูลของโทรศัพท์ โดยลบไฟล์ในไดเรกทอรีแคชของแอปพลิเคชันอื่นๆ ซึ่งอาจทำให้แอปพลิเคชันอื่นเริ่มทำงานช้ากว่าเดิมเนื่องจากต้องดึงข้อมูลของตนซ้ำ"</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"ย้ายแหล่งข้อมูลแอปพลิเคชัน"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"อนุญาตให้แอปพลิเคชันย้ายแหล่งข้อมูลแอปพลิเคชันจากภายในไปยังสื่อภายนอกและกลับกัน"</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"อ่านข้อมูลบันทึกที่สำคัญ"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"อนุญาตให้แอปเข้าถึงคำสั่งของผู้ให้บริการตำแหน่งเพิ่มเติม ซึ่งอาจทำให้แอปสามารถแทรกแซงการทำงานของ GPS หรือต้นทางของตำแหน่งอื่นๆ ได้"</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"การอนุญาตให้ติดตั้งโปรแกรมแจ้งตำแหน่ง"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"สร้างต้นทางของตำแหน่งจำลองสำหรับการทดสอบหรือติดตั้งผู้ให้บริการตำแหน่งรายใหม่ ซึ่งจะทำให้แอปพลิเคชันสามารถแทนที่ตำแหน่งและ/หรือสถานะที่ส่งกลับมาจากต้นทางของตำแหน่งอื่นๆ เช่น GPS หรือผู้ให้บริการตำแหน่งได้"</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"ตำแหน่งที่แม่นยำ (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"เข้าถึงต้นทางของตำแหน่งที่แม่นยำ เช่น ระบบกำหนดตำแหน่งบนพื้นโลก (GPS) ในแท็บเล็ต หากบริการตำแหน่งใช้งานได้และเปิดอยู่ การอนุญาตนี้จะทำให้แอปพลิเคชันสามารถระบุตำแหน่งที่ของคุณได้อย่างแม่นยำ"</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"เข้าถึงต้นทางของตำแหน่งที่แม่นยำ เช่น ระบบกำหนดตำแหน่งบนพื้นโลก (GPS) ในโทรศัพท์ หากบริการตำแหน่งใช้งานได้และเปิดอยู่ การอนุญาตนี้จะทำให้แอปพลิเคชันสามารถระบุตำแหน่งที่ของคุณได้อย่างแม่นยำ"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"ตำแหน่งโดยประมาณ (อิงตามเครือข่าย)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"เข้าถึงตำแหน่งโดยประมาณจากผู้ให้บริการตำแหน่งโดยใช้แหล่งข้อมูลเครือข่าย เช่น เสาสัญญาณและ WiFi หากบริการตำแหน่งเหล่านี้ใช้งานได้และเปิดอยู่ การอนุญาตนี้จะทำให้แอปพลิเคชันสามารถระบุตำแหน่งโดยประมาณของคุณได้"</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"ตำแหน่งที่แม่นยำ (อิงตาม GPS และเครือข่าย)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"อนุญาตให้แอปพลิเคชันรับตำแหน่งที่แม่นยำของคุณโดยใช้ Global Positioning System (GPS) หรือต้นทางของตำแหน่งในเครือข่ายอย่างเช่น เสาสัญญาณมือถือ และ WiFi บริการตำแหน่งเหล่านี้จะต้องถูกเปิดใช้งานอยู่สำหรับอุปกรณ์ของคุณเพื่อให้แอปพลิเคชันสามารถใช้งานได้ แอปพลิเคชันสามารถใช้บริการตำแหน่งนี้เพื่อตัดสินว่าคุณอยู่ ณ จุดใด และอาจใช้พลังงานแบตเตอรี่มากกว่าปกติ"</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"ตำแหน่งโดยประมาณ (อิงตามเครือข่าย)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"อนุญาตให้แอปพลิเคชันรับตำแหน่งโดยประมาณของคุณ บริการตำแหน่งจะดึงตำแหน่งขึ้นมาโดยใช้ต้นทางของตำแหน่งอย่างเช่น เสาสัญญาณมือถือ และ WiFi บริการตำแหน่งเหล่านี้จะต้องถูกเปิดใช้งานอยู่สำหรับอุปกรณ์ของคุณเพื่อให้แอปพลิเคชันสามารถใช้งานได้ แอปพลิเคชันสามารถใช้บริการตำแหน่งนี้เพื่อตัดสินอย่างคร่าวๆ ว่าคุณอยู่ ณ จุดใด"</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"เข้าถึง 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="permlab_configureWifiDisplay" msgid="5595661694746742168">"กำหนดค่าการแสดงผลด้วย WiFi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"อนุญาตให้แอปกำหนดค่าและเชื่อมต่อกับจอแสดงผล WiFi ได้"</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"ควบคุมการแสดงผลด้วย WiFi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"อนุญาตให้แอปควบคุมคุณลักษณะต่างๆ ในระดับล่างของการแสดงผลด้วย WiFi"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"เปลี่ยนการตั้งค่าเสียงของคุณ"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"อนุญาตให้แอปพลิเคชันปรับเปลี่ยนการตั้งค่าเสียงทั้งหมดได้ เช่น ระดับเสียงและลำโพงที่จะใช้งาน"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"บันทึกเสียง"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"เข้าถึงการตั้งค่าบลูทูธ"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"อนุญาตให้แอปพลิเคชันกำหนดค่าแท็บเล็ตบลูทูธในตัวเครื่อง รวมทั้งค้นหาและจับคู่กับอุปกรณ์ที่อยู่ระยะไกล"</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"อนุญาตให้แอปพลิเคชันกำหนดค่าโทรศัพท์บลูทูธในตัวเครื่อง ตลอดจนค้นหาและจับคู่กับอุปกรณ์ที่อยู่ระยะไกล"</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"ดูการเชื่อมต่อ WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"เชื่อมต่อและเลิกเชื่อมต่อจาก WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"อนุญาตให้แอปพลิเคชันตรวจสอบว่า WiMAX เปิดใช้งานอยู่หรือไม่และข้อมูลเกี่ยวกับเครือข่าย WiMAX ใดๆ ที่เชื่อมต่ออยู่"</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"เปลี่ยนสถานะของ WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"อนุญาตให้แอปพลิเคชันเชื่อมต่อและยกเลิกการเชื่อมต่อแท็บเล็ตกับเครือข่าย WiMAX"</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"อนุญาตให้แอปพลิเคชันแก้ไขฟีดที่ซิงค์ในปัจจุบันของคุณ แอปพลิเคชันที่เป็นอันตรายอาจเปลี่ยนแปลงฟีดที่ซิงค์ของคุณ"</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"อ่านคำที่คุณเพิ่มลงในพจนานุกรม"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"อนุญาตให้แอปพลิเคชันอ่านคำ ชื่อ และวลีทั้งหมดที่ผู้ใช้ได้จัดเก็บไว้ในพจนานุกรมผู้ใช้"</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"เขียนลงในพจนานุกรมที่ผู้ใช้กำหนด"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"เพิ่มคำลงในพจนานุกรมที่ผู้ใช้กำหนด"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"อนุญาตให้แอปพลิเคชันเขียนคำใหม่ลงในพจนานุกรมผู้ใช้"</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"ทดสอบการเข้าถึงที่จัดเก็บข้อมูลที่มีการป้องกัน"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"ทดสอบการเข้าถึงที่จัดเก็บข้อมูลที่มีการป้องกัน"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"อนุญาตให้แอปพลิเคชันทดสอบการอนุญาตสำหรับที่จัดเก็บข้อมููล USB ที่จะสามารถใช้งานได้ในอุปกรณ์ในอนาคต"</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"อนุญาตให้แอปพลิเคชันทดสอบการอนุญาตสำหรับที่จัดเก็บข้อมููล USB ที่จะสามารถใช้งานได้ในอุปกรณ์ในอนาคต"</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"อนุญาตให้แอปพลิเคชันทดสอบการอนุญาตสำหรับการ์ด SD ที่จะสามารถใช้งานได้ในอุปกรณ์ในอนาคต"</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"แก้ไขหรือลบเนื้อหาใน USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"แก้ไขหรือลบเนื้อหาในการ์ด SD ของคุณ"</string>
@@ -534,6 +593,8 @@
     <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="permlab_sdcardAccessAll" msgid="8150613823900460576">"เข้าถึงที่จัดเก็บภายนอกของทุกคน"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"อนุญาตให้แอปพลิเคชันเข้าถึงที่จัดเก็บข้อมูลภายนอกสำหรับผู้ใช้ทั้งหมด"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"เข้าถึงระบบไฟล์แคช"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"อนุญาตให้แอปพลิเคชันอ่านและเขียนระบบไฟล์แคช"</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"โทรออก/รับสายอินเทอร์เน็ต"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"ข้อมูลของแอปพลิเคชันที่จัดเก็บต้องมีการเข้ารหัส"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"ปิดใช้งานกล้องถ่ายรูป"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"ป้องกันการใช้กล้องถ่ายรูปของอุปกรณ์ทั้งหมด"</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"ปิดใช้งานคุณลักษณะการล็อกปุ่ม"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"ป้องกันการใช้คุณลักษณะบางส่วนในการล็อกปุ่ม"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"บ้าน"</item>
     <item msgid="869923650527136615">"มือถือ"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"ลองอีกครั้ง"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"มีความพยายามที่จะใช้ Face Unlock เกินขีดจำกัด"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"กำลังชาร์จ, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"ชาร์จแล้ว"</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"ชาร์จแล้ว"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"เสียบที่ชาร์จของคุณ"</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"ไม่มีซิมการ์ด"</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"ไม่มีซิมการ์ด"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ไม่มีซิมการ์ดในแท็บเล็ต"</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ไม่มีซิมการ์ดในโทรศัพท์"</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"ใส่ซิมการ์ด"</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"ล้างรูปแบบแล้ว"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"เพิ่มเซลแล้ว"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"วาดรูปแบบเสร็จสิ้น"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"เพิ่มวิดเจ็ต"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"ว่าง"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"ขยายพื้นที่ปลดล็อกแล้ว"</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"ยุบพื้นที่ปลดล็อกแล้ว"</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"วิดเจ็ต <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>"</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"ตัวเลือกผู้ใช้"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"สถานะ"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"กล้องถ่ายรูป"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"การควบคุมสื่อ"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"เริ่มเรียงลำดับวิดเจ็ตใหม่"</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"เรียงลำดับวิดเจ็ตใหม่เสร็จแล้ว"</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"ลบวิดเจ็ต <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> แล้ว"</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"ขยายพื้นที่ปลดล็อก"</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"การปลดล็อกด้วยการเลื่อน"</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"การปลดล็อกด้วยรูปแบบ"</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"การปลดล็อกด้วยใบหน้า"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"การปลดล็อกด้วย PIN"</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"การปลดล็อกด้วยรหัสผ่าน"</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"พื้นที่สำหรับรูปแบบ"</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"พื้นที่สำหรับการเลื่อน"</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"คัดลอก URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"เลือกข้อความ"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"การเลือกข้อความ"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"เพิ่มลงในพจนานุกรม"</string>
-    <string name="deleteText" msgid="7070985395199629156">"ลบ"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"เพิ่มในพจนานุกรม"</string>
+    <string name="deleteText" msgid="6979668428458199034">"ลบ"</string>
     <string name="inputMethod" msgid="1653630062304567879">"วิธีป้อนข้อมูล"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"การทำงานของข้อความ"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"พื้นที่จัดเก็บเหลือน้อย"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"เปิดเครือข่าย Wi-Fi ที่ใช้งานได้"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"ลงชื่อเข้าใช้เครือข่าย WiFi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"ลงชื่อเข้าใช้เครือข่าย"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ไม่สามารถเชื่อมต่อ Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" มีสัญญาณอินเทอร์เน็ตไม่ดี"</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"ถึง:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"พิมพ์ PIN ที่ต้องการ:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"โทรศัพท์จะยกเลิกการเชื่อมต่อกับ Wi-Fi ชั่วคราวในขณะที่เชื่อมต่อกับ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"ใส่อักขระ"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"กำลังส่งข้อความ SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; กำลังส่งข้อความ SMS จำนวนมาก คุณต้องการอนุญาตให้แอปพลิเคชันนี้ส่งข้อความต่อหรือไม่"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"อนุญาต"</string>
     <string name="sms_control_no" msgid="625438561395534982">"ปฏิเสธ"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ต้องการส่งข้อความไปยัง &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"การดำเนินการนี้"<font fgcolor="#ffffb060">"อาจมีค่าใช้จ่ายเพิ่มเติม"</font>"สำหรับบัญชีมือถือของคุณ"</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"การดำเนินการนี้อาจมีค่าใช้จ่ายเพิ่มเติมสำหรับบัญชีมือถือของคุณ"</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"ส่ง"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"ยกเลิก"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"จดจำตัวเลือกของฉัน"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"คุณสามารถเปลี่ยนค่านี้ภายหลังในการตั้งค่า &gt; แอปพลิเคชัน"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"อนุญาตทุกครั้ง"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"ไม่อนุญาตเลย"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"นำซิมการ์ดออกแล้ว"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"เครือข่ายมือถือจะไม่สามารถใช้งานได้จนกว่าคุณจะรีสตาร์ทโดยใส่ซิมการ์ดที่ถูกต้องแล้ว"</string>
     <string name="sim_done_button" msgid="827949989369963775">"เสร็จสิ้น"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"ตั้งวันที่"</string>
     <string name="date_time_set" msgid="5777075614321087758">"ตั้งค่า"</string>
     <string name="date_time_done" msgid="2507683751759308828">"เสร็จสิ้น"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"เริ่มต้น"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"ไม่ต้องการการอนุญาต"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"ซ่อน"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"แสดงทั้งหมด"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"ใหม่: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"ใหม่: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"โดย <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"ไม่ต้องการการอนุญาต"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"รายการนี้อาจมีการเรียกเก็บเงิน"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"ที่จัดเก็บข้อมูลจำนวนมากแบบ USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"เชื่อมต่อ USB แล้ว"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"คุณได้เชื่อมต่อกับคอมพิวเตอร์ผ่าน USB แล้ว แตะปุ่มด้านล่างหากคุณต้องการคัดลอกไฟล์ระหว่างคอมพิวเตอร์กับที่จัดเก็บข้อมูล USB ของแอนดรอยด์"</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"เปิดใช้งาน VPN โดย <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"แตะเพื่อจัดการเครือข่าย"</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"เชื่อมต่อกับ <xliff:g id="SESSION">%s</xliff:g> แตะเพื่อจัดการเครือข่าย"</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"กำลังเชื่อมต่อ VPN แบบเปิดตลอดเวลา…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"เชื่อมต่อ VPN แบบเปิดตลอดเวลาแล้ว"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"ข้อผิดพลาดของ VPN แบบเปิดตลอดเวลา"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"แตะเพื่อรีเซ็ตการเชื่อมต่อ"</string>
     <string name="upload_file" msgid="2897957172366730416">"เลือกไฟล์"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"ไม่ได้เลือกไฟล์ไว้"</string>
     <string name="reset" msgid="2448168080964209908">"รีเซ็ต"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"แบ่งปัน"</string>
     <string name="find" msgid="4808270900322985960">"ค้นหา"</string>
     <string name="websearch" msgid="4337157977400211589">"ค้นเว็บ"</string>
+    <string name="find_next" msgid="5742124618942193978">"ค้นหาถัดไป"</string>
+    <string name="find_previous" msgid="2196723669388360506">"ค้นหาก่อนหน้านี้"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"คำขอสถานที่จาก <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"คำขอสถานที่"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"ร้องขอโดย <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"โทรศัพท์"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"หูฟัง"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ลำโพงแท่นชาร์จ"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"เสียง HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"ระบบ"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"เสียงบลูทูธ"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"เสร็จสิ้น"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"เอาต์พุตสื่อ"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"กำลังสแกน..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"กำลังเชื่อมต่อ..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"พร้อมใช้งาน"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"ไม่พร้อมใช้งาน"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"หน้าจอในตัว"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"หน้าจอ HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"การวางซ้อน #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"เชื่อมต่อการแสดงผลแบบไร้สายอยู่"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"หน้าจอนี้กำลังแสดงบนอุปกรณ์อื่น"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"หยุดเชื่อมต่อ"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"หมายเลขฉุกเฉิน"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"ลืมรูปแบบใช่หรือไม่"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"รูปแบบไม่ถูกต้อง"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"รหัสผ่านไม่ถูกต้อง"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN ไม่ถูกต้อง"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"ลองอีกครั้งในอีก <xliff:g id="NUMBER">%d</xliff:g> วินาที"</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"วาดรูปแบบของคุณ"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"ป้อน PIN ของซิม"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"ป้อน PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"ป้อนรหัสผ่าน"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"ซิมการ์ดถูกปิดใช้งานแล้วในตอนนี้ ป้อนรหัส PUK เพื่อดำเนินการต่อ โปรดติดต่อผู้ให้บริการสำหรับรายละเอียด"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"ป้อนรหัส PIN ที่ต้องการ"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"ยืนยันรหัส PIN ที่ต้องการ"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"กำลังปลดล็อกซิมการ์ด…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"รหัส PIN ไม่ถูกต้อง"</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"พิมพ์ PIN ซึ่งเป็นเลข 4 ถึง 8 หลัก"</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"รหัส PUK ต้องเป็นตัวเลขอย่างน้อย 8 หลัก"</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"ใส่รหัส PUK ที่ถูกต้องอีกครั้ง การพยายามซ้ำหลายครั้งจะทำให้ซิมการ์ดถูกปิดใช้งานอย่างถาวร"</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"รหัส PIN ไม่ตรง"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"ลองหลายรูปแบบมากเกินไป"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"หากต้องการปลดล็อก ให้ลงชื่อเข้าใช้ด้วยบัญชี Google ของคุณ"</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"ชื่อผู้ใช้ (อีเมล)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"รหัสผ่าน"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"ลงชื่อเข้าใช้"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง"</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"หากลืมชื่อผู้ใช้หรือรหัสผ่าน"\n"โปรดไปที่ "<b>"google.com/accounts/recovery"</b></string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"กำลังตรวจสอบบัญชี…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"คุณพิมพ์ PIN ไม่ถูกต้องไป <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว "\n\n"โปรดลองอีกครั้งใน <xliff:g id="NUMBER_1">%d</xliff:g> วินาที"</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"คุณพิมพ์รหัสผ่านไม่ถูกต้องไป <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว "\n\n"โปรดลองอีกครั้งใน <xliff:g id="NUMBER_1">%d</xliff:g> วินาที"</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้องไป <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว "\n\n"โปรดลองอีกครั้งใน <xliff:g id="NUMBER_1">%d</xliff:g> วินาที"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"คุณพยายามปลดล็อกแท็บเล็ตอย่างไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว หากพยายามแล้วไม่สำเร็จอีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง แท็บเล็ตจะถูกรีเซ็ตเป็นค่าเริ่มต้นจากโรงงานและข้อมูลผู้ใช้ทั้งหมดจะหายไป"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"คุณพยายามปลดล็อกโทรศัพท์อย่างไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว หากพยายามแล้วไม่สำเร็จอีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง โทรศัพท์จะถูกรีเซ็ตเป็นค่าเริ่มต้นจากโรงงานและข้อมูลผู้ใช้ทั้งหมดจะหายไป"</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"คุณพยายามปลดล็อกแท็บเล็ตอย่างไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้งแล้ว ขณะนี้แท็บเล็ตจะถูกรีเซ็ตเป็นค่าเริ่มต้นจากโรงงาน"</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"คุณพยายามปลดล็อกโทรศัพท์อย่างไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้งแล้ว ขณะนี้โทรศัพท์จะถูกรีเซ็ตเป็นค่าเริ่มต้นจากโรงงาน"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกแท็บเล็ตโดยใช้บัญชีอีเมล"\n\n" โปรดลองอีกครั้งใน <xliff:g id="NUMBER_2">%d</xliff:g> วินาที"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกโทรศัพท์โดยใช้ับัญชีอีเมล"\n\n" โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%d</xliff:g> วินาที"</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"นำออก"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"เพิ่มระดับเสียงจนเกินระดับที่ปลอดภัยหรือไม่"\n"การฟังเสียงดังเป็นเวลานานอาจทำให้การได้ยินของคุณบกพร่องได้"</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"ใช้สองนิ้วแตะค้างไว้เพื่อเปิดใช้งานการเข้าถึง"</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"เปิดใช้งานการเข้าถึงแล้ว"</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"ยกเลิกการเข้าถึงแล้ว"</string>
+    <string name="user_switched" msgid="3768006783166984410">"ผู้ใช้ปัจจุบัน <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="owner_name" msgid="2716755460376028154">"เจ้าของ"</string>
 </resources>
diff --git a/core/res/res/values-tl/donottranslate-cldr.xml b/core/res/res/values-tl/donottranslate-cldr.xml
index 6ff92e3..4545fb5 100644
--- a/core/res/res/values-tl/donottranslate-cldr.xml
+++ b/core/res/res/values-tl/donottranslate-cldr.xml
@@ -1,70 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">1</string>
-    <string name="month_long_standalone_february">2</string>
-    <string name="month_long_standalone_march">3</string>
-    <string name="month_long_standalone_april">4</string>
-    <string name="month_long_standalone_may">5</string>
-    <string name="month_long_standalone_june">6</string>
-    <string name="month_long_standalone_july">7</string>
-    <string name="month_long_standalone_august">8</string>
-    <string name="month_long_standalone_september">9</string>
-    <string name="month_long_standalone_october">10</string>
-    <string name="month_long_standalone_november">11</string>
-    <string name="month_long_standalone_december">12</string>
-
-    <string name="month_long_january">1</string>
-    <string name="month_long_february">2</string>
-    <string name="month_long_march">3</string>
-    <string name="month_long_april">4</string>
-    <string name="month_long_may">5</string>
-    <string name="month_long_june">6</string>
-    <string name="month_long_july">7</string>
-    <string name="month_long_august">8</string>
-    <string name="month_long_september">9</string>
-    <string name="month_long_october">10</string>
-    <string name="month_long_november">11</string>
-    <string name="month_long_december">12</string>
-
-
-    <string name="month_shortest_january">1</string>
-    <string name="month_shortest_february">2</string>
-    <string name="month_shortest_march">3</string>
-    <string name="month_shortest_april">4</string>
-    <string name="month_shortest_may">5</string>
-    <string name="month_shortest_june">6</string>
-    <string name="month_shortest_july">7</string>
-    <string name="month_shortest_august">8</string>
-    <string name="month_shortest_september">9</string>
-    <string name="month_shortest_october">10</string>
-    <string name="month_shortest_november">11</string>
-    <string name="month_shortest_december">12</string>
-
-    <string name="day_of_week_long_sunday">1</string>
-    <string name="day_of_week_long_monday">2</string>
-    <string name="day_of_week_long_tuesday">3</string>
-    <string name="day_of_week_long_wednesday">4</string>
-    <string name="day_of_week_long_thursday">5</string>
-    <string name="day_of_week_long_friday">6</string>
-    <string name="day_of_week_long_saturday">7</string>
-
-
-
-    <string name="day_of_week_shortest_sunday">1</string>
-    <string name="day_of_week_shortest_monday">2</string>
-    <string name="day_of_week_shortest_tuesday">3</string>
-    <string name="day_of_week_shortest_wednesday">4</string>
-    <string name="day_of_week_shortest_thursday">5</string>
-    <string name="day_of_week_shortest_friday">6</string>
-    <string name="day_of_week_shortest_saturday">7</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index e9ea129..072f6df 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Pagpipilian sa telepono"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Pag-lock sa screen"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"I-off"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Ulat sa bug"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Kunin ang ulat sa bug"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Mangongolekta ito ng impormasyon tungkol sa kasalukuyang katayuan ng iyong device, na ipapadala bilang mensaheng e-mail. Gugugol ito ng kaunting oras mula sa pagsisimula sa ulat sa bug hanggang sa handa na itong maipadala; mangyaring maging mapagpasensya."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Silent mode"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Naka-OFF ang tunog"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Naka-ON ang sound"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Iyong mga mensahe"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Basahin at isulat ang iyong SMS, e-mail, at iba pang mga mensahe."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Iyong personal na impormasyon"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Direktang access sa iyong mga contact at kalendaryong nakaimbak sa tablet."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Direktang access sa iyong mga contact at kalendaryong nakaimbak sa telepono."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Direktang access sa impormasyon tungkol sa iyo, na naka-imbak sa iyong contact card."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Ang iyong social na impormasyon"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Direktang access sa impormasyon tungkol sa iyong mga contact at social na koneksyon."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Iyong lokasyon"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Subaybayan ang iyong pisikal na lokasyon."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Pakikipag-ugnay sa network"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Mag-access ng iba\'t ibang mga tampok ng network."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"I-access ang mga device at network sa pamamagitan ng Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Mga Setting ng Audio"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Baguhin ang mga setting ng audio."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Naaapektuhan ang Baterya"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Gumamit ng mga tampok na mabilisang uubos ng baterya."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalendaryo"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Direktang access sa kalendaryo at mga kaganapan."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Basahin ang Disyunaryo ng User"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Magbasa ng mga salita sa diksyunaryo ng user."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Magsulat sa Diksyunaryo ng User"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Magdagdag ng mga salita sa diksyunaryo ng user."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Mga Bookmark at Kasaysayan"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Direktang access sa mga bookmark at kasaysayan ng browser."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarm"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Itakda ang alarm clock."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Voicemail"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Direktang access sa voicemail."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikropono"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Direktang access sa mikropono upang mag-record ng audio."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Camera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Direktang access sa camera para sa pagkuha ng larawan o video."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Ang impormasyon ng iyong mga application"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Kakayahang maapektuhan ang pag-uugali ng iba pang mga application sa iyong device."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Wallpaper"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Baguhin ang mga setting ng wallpaper ng device."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Orasan"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Baguhin ang oras o timezone ng device."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Status Bar"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Baguhin ang mga setting ng status bar ng device"</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Mga Setting ng Pag-sync"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Access sa mga setting ng pag-sync."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Iyong mga account"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"I-access ang mga available na account."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Mga kontrol ng hardware"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Mas mababang antas na access at kontrol ng system."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Mga tool na pang-develop"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Kinakailangan lamang ang mga tampok para sa mga developer ng app."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Iba pang UI ng Application"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Apektuhan ang UI ng iba pang mga application."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Imbakan"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"I-access ang imbakan na USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"I-access ang SD card."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Pinapayagan ang app na tumanggap at magproseso ng mga mensaheng WAP. Kabilang sa pahintulot na ito ang kakayahang sumubaybay o magtanggal ang app ng mga mensaheng ipinapadala sa iyo nang hindi ipinapakita ang mga ito sa iyo."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"bawiin ang tumatakbong apps"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Pinapayagan ang app na kumuha ng impormasyon tungkol sa mga kasalukuyan at kamakailang gumaganang gawain. Maaari nitong payagan ang app na tumuklas ng impormasyon tungkol sa kung aling mga application ang ginagamit sa device."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"makipag-ugnayan sa kabuuan ng mga user"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Binibigyang-daan ang app upang magsagawa ng mga pagkilos sa kabuuan ng iba\'t ibang mga user sa device. Maaari itong gamitin ng nakakahamak na apps upang lumabag sa proteksyon sa pagitan ng mga user."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"ganap na lisensya upang makipag-ugnayan sa kabuuan ng mga user"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Pinapayagan ang lahat ng posibleng pakikipag-ugnayan sa kabuuan ng mga user."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"pamahalaan ang mga user"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Binibigyang-daan ang apps na mamahala ng mga user sa device, kabilang ang query, paglikha at pagtanggal."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"bawiin ang mga detalye ng gumaganang apps"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Binibigyang-daan ang app na bawiin ang detalyadong impormasyon tungkol sa mga kasalukuyan at kamakailang gumaganang gawain. Maaaring makatuklas ang nakakahamak na apps ng pribadong impormasyon tungkol sa iba pang apps."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"muling isaayos ang tumatakbong apps"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Pinapayagan ang app na mabawi ang panloob na katayuan ng system. Maaaring bawiin ng nakakahamak na apps ang iba\'t ibang pribado at secure na impormasyon na hindi kailanman normal na kinakailangan ng mga ito."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"kunin ang nilalaman ng screen"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Pinapayagan ang app na bawiin ang nilalaman ng aktibong window. Maaaring bawiin ng nakakahamak na apps ang kabuuang nilalaman ng window at suriin ang lahat ng teksto nito maliban sa mga password."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"pansamantalang paganahin ang accessibility"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Nagbibigay-daan sa isang application na pansamantalang paganahin ang accessibility sa device. Maaaring paganahin ng nakakahamak na apps ang accessibility nang walang pahintulot ng user."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"kunin ang impormasyon ng window"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Pinapayagan ang application na kumuha ng impormasyon tungkol sa mga window mula sa tagapamahala ng window. Maaaring kumuha ang mga nakakahamak na app ng impormasyong nilayon para sa panloob na paggamit ng system."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"i-filter ang mga kaganapan"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Pinapayagan ang isang application na magrehistro ng filter ng input na nagpi-filter sa stream ng lahat ng kaganapan ng user bago maipadala ang mga iyon. Maaaring kontrolin ng nakakahamak na app ang system UI nang hindi nakikialam ang user."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"i-magnify ang display"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Pinapayagan ang isang application na i-magnify ang nilalaman ng isang display. Maaaring ibahin ng nakakahamak na apps ang nilalaman ng display sa paraang nagre-render sa device na hindi kapaki-pakinabang."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"bahagyang pag-shutdown"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Inilalagay ang tagapamahala ng aktibidad sa katayuan ng pag-shutdown. Hindi nagsasagawa ng kumpletong pag-shutdown."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"pigilan ang mga paglipat ng app"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Pinapayagan ang app na kontrolin ang maximum na bilang ng mga proseso na tatakbo. Hindi kailanman kinakailangan para sa normal na apps."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"pwersahin ang mga app sa background na magsara"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Pinapayagan ang apps na kontrolin kung palaging natatapos ang mga aktibidad sa sandaling pumunta ang mga ito sa background. Hindi kailanman kinakailangan para sa normal na apps."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"baguhin ang mga istatistika ng baterya"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Pinapayagan ang app na baguhin ang nakolektang mga istatistika ng baterya. Hindi para sa paggamit ng normal na apps."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"basahin ang mga istatistika ng baterya"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Binibigyang-daan ang application na basahin ang kasalukuyang data sa paggamit ng mababang antas ng baterya. Maaaring bigyang-daan ang application na malaman ang detalyadong impormasyon tungkol sa kung aling apps ang ginagamit mo."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"baguhin ang mga istatistika ng baterya"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Binibigyang-daan ang app na baguhin ang mga nakolektang istatistika ng baterya. Hindi para sa paggamit ng normal na apps."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontrolin ang system backup at pagbawi"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Pinapayagan ang app na kontrolin ang backup ng system at ipanumbalik ang mekanismo. Hindi para sa paggamit ng normal na apps."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"Kumpirmahin ang isang buong pagpapatakbo ng pag-backup o pagpapanumbalik"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"ipakita ang mga hindi pinahintulutang window"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Pinapayagan ang app na lumikha ng mga window na nakalaan upang gamitin ng user interface ng panloob na system. Hindi para sa paggamit ng normal na apps."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"gumuhit sa ibabaw ng ibang mga app"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Pinapayagan ang app na magpakita ng mga window ng alerto sa system. Maaaring sakupin ng ilang window ng alerto ang buong screen."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Binibigyang-daan ang app na gumuhit sa ibabaw ng iba pang mga application o mga bahagi ng interface ng user. Maaaring manghimasok ang mga ito sa iyong paggamit sa interface sa anumang application, o baguhin ang sa palagay mo ay nakikita mo sa iba pang mga application."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"baguhin ang bilis ng global animation"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Pinapayagan ang app na baguhin ang bilis ng global animation (mas mabilis o mas mabagal na mga animation) anumang oras."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"pamahalaan ang mga token ng app"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Pinapayagan ang app na lumikha ng at pamahalaan ang sariling mga token ng mga ito, na bina-bypass ang normal na Z-ordering ng mga ito. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"i-freeze ang screen"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Pinapayagan ang application na pansamantalang i-freeze ang screen para sa isang full-screen na transition."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"pindutin ang mga key at kontrolin ang mga pindutan"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Pinapayagan ang app na ihatid ang sariling mga kaganapan ng input nito (mga pagpindot sa key, atbp.) sa iba pang apps. Maaari itong gamitin ng nakakahamak na apps upang pangasiwaan ang tablet."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Pinapayagan ang app na ihatid ang sariling mga kaganapan ng input nito (mga pagpindot sa key, atbp.) sa iba pang apps. Maaari itong gamitin ng nakakahamak na apps upang pangasiwaan ang telepono."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"direktang mag-install ng apps"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Pinapayagan ang app na mag-install ng bago o na-update na mga package ng Android. Maaari itong gamitin ng nakakahamak na apps upang magdagdag ng bagong apps na may hindi tukoy na malakas na mga pahintulot."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"tanggalin ang lahat ng data sa cache ng app"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Pinapayagan ang app na magbakante ng storage ng tablet sa pamamagitan ng pagtanggal ng mga file sa direktoryo ng cache ng app. Karaniwang talagang pinaghihigpitan ang access sa proseso ng system."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Pinapayagan ang app na magbakante ng storage ng telepono sa pamamagitan ng pagtanggal ng mga file sa direktoryo ng cache ng app. Karaniwang talagang pinaghihigpitan ang access sa proseso ng system."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Binibigyang-daan ang app na bawasan ang laman ng storage ng tablet sa pamamagitan ng pagtatanggal ng mga file sa mga direktoryo ng cache ng iba pang mga application. Maaaring pabagalin nito ang pagsisimula ng iba pang mga application dahil kailangang muling kunin ng mga ito ang kanilang data."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Binibigyang-daan ang app na bawasan ang laman ng storage ng telepono sa pamamagitan ng pagtatanggal ng mga file sa mga direktoryo ng cache ng iba pang mga application. Maaaring pabagalin nito ang pagsisimula ng iba pang mga application dahil kailangang muling kunin ng mga ito ang kanilang data."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"ilipat ang mga mapagkukunan ng app"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Pinapayagan ang app na ilipat ang mga mapagkukunan ng app mula sa panloob patungo sa panlabas na media at kabaliktaran."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"magbasa ng sensitibong data ng tala"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Pinapayagan ang app na mag-access ng mga dagdag na command ng provider ng lokasyon. Maaari nitong payagan ang app na gambalain ang pagpapatakbo ng GPS o ng iba pang mga pinagmulan ng lokasyon."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"pahintulot na mag-install ng provider ng lokasyon"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Lumikha ng mga mock na pinagmulan ng lokasyon o mag-install ng bagong provider ng lokasyon. Pinapayagan nito ang app na i-override ang lokasyon at/o katayuan na ibinabalik ng iba pang mga pinagmulan ng lokasyon gaya ng GPS o mga provider ng lokasyon."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"tumpak (GPS) na lokasyon"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Mag-access ng mga tumpak na pinagmulan ng lokasyon gaya ng Global Positioning System sa tablet. Kapag available at naka-on ang mga serbisyo ng lokasyon, pinapayagan ng pahintulot na ito ang app na tukuyin ang iyong tumpak na lokasyon."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Mag-access ng mga tumpak na pinagmulan ng lokasyon gaya ng Global Positioning System sa telepono. Kapag available at naka-on ang mga serbisyo ng lokasyon, pinapayagan ng pahintulot na ito ang app na tukuyin ang iyong tumpak na lokasyon."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"tinatantya (network-based) na lokasyon"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Mag-access ng tinatantyang lokasyon mula sa mga provider ng lokasyon gamit ang mga pinagmumulan ng network gaya ng cell tower at Wi-Fi. Kapag available at naka-on ang mga serbisyo ng lokasyon na ito, pinapayagan ng pahintulot na ito ang app na tukuyin ang iyong tinatantyang lokasyon."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"tumpak na lokasyon (batay  sa GPS at network)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Binibigyang-daan ang app na makuha ang iyong tumpak na lokasyon gamit ang Global Positioning System (GPS) o network ng mga pinagmulan ng lokasyon gaya ng mga cell tower at Wi-Fi. Dapat ay naka-on ang mga serbisyo ng lokasyon na ito at available sa iyong device upang magamit ng app ang mga ito. Maaaring gamitin ito ng apps upang matukoy kung nasaan ka, at maaaring gumamit ng karagdagang power ng baterya."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"tinatayang lokasyon (batay sa network)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Binibigyang-daan ang app na makuha ang iyong tinatayang lokasyon. Ang lokasyong ito ay nagmula ng mga serbisyo ng lokasyon na gumagamit ng network ng mga pinagmulan ng lokasyon gaya ng mga cell tower at Wi-Fi. Dapat ay naka-on ang mga serbisyo ng lokasyon na ito at available sa iyong device upang magamit ng app ang mga ito. Maaaring gamitin ito ng apps upang matukoy ang tinatayang lokasyon na kinaroroonan mo."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"i-access ang SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Pinapayagan ang app na gamitin ang mababang antas na mga tampok ng SurfaceFlinger."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"basahin ang buffer ng frame"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Pinapayagan ang app na basahin ang nilalaman ng buffer ng frame."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"mag-configure ng mga Wifi display"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Pinapayagan ang app na mag-configure at kumonekta sa mga Wifi display."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"magkontrol ng mga Wifi display"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Pinapayagan ang app na magkontrol ng mga tampok sa mababang antas ng mga dispay ng Wifi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"baguhin ang mga setting ng iyong audio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Pinapayagan ang app na baguhin ang mga pandaigdigang setting ng audio gaya ng volume at kung aling speaker ang ginagamit para sa output."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"mag-record ng audio"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"I-access ang mga setting ng Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Pinapayagan ang app na i-configure ang lokal na Bluetooth tablet, at tumuklas ng at ipares sa mga malayuang device."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Pinapayagan ang app na i-configure ang lokal na Bluetooth na telepono, at tumuklas ng at ipares sa mga malayuang device."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Tingnan ang mga WiMAX na koneksyon"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"kumonekta at magdiskonekta mula sa WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Pinapayagan ang app na tukuyin kung pinapagana ang WiMAX at impormasyon tungkol sa anumang mga WiMAX network na nakakonekta."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Baguhin ang katayuan ng WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Pinapayagan ang app na ikonekta ang tablet at idiskonekta ang tablet mula sa mga WiMAX network."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Pinapayagan ang app na baguhin ang iyong kasalukuyang na-sync na mga feed. Maaaring baguhin ng nakakahamak na apps ang iyong na-sync na mga feed."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"basahin ang mga terminong idinagdag mo sa diksyunaryo"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Pinapayagan ang app na basahin ang lahat ng salita, pangalan at parirala na maaaring inimbak ng user sa diksyunaryo ng user."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"magsulat sa diksyunaryong tinukoy ng user"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"magdagdag ng mga salita sa diksyunaryong tinukoy ng user"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Pinapayagan ang app na magsulat ng mga bagong salita sa diksyunaryo ng user."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"subukan ang access sa pinoprotektahang storage"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"subukan ang access sa pinoprotektahang storage"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Pinapayagan ang app na subukan ang isang pahintulot para sa USB storage na magiging availabe sa mga device sa hinaharap."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Binibigyang-daan ang app na subukan ang isang pagpapahintulot para sa USB storage na magiging availabe sa mga device sa hinaharap."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Pinapayagan ang app na subukan ang isang pahintulot para sa SD card na magiging available sa mga device sa hinaharap."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"bago tanggal laman USB storage"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"baguhin o tanggalin ang mga nilalaman ng iyong SD card"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Pinapayagan ang app na magsulat sa SD card."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"baguhin/tanggalin ang mga nilalaman ng panloob na imbakan ng media"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Pinapayagan ang app na baguhin ang mga nilalaman ng panloob na media storage."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"i-access panlabas na storage ng user"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Pinapayagan ang app na mag-access ng panlabas na storage para sa lahat ng user."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"i-access ang cache filesystem"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Pinapayagan ang app na basahin at isulat ang cache filesystem."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"gumawa/tumanggap ng mga tawag sa Internet"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Hilinging naka-encrypt ang nakaimbak na data ng app."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Huwag paganahin mga camera"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Pigilan ang paggamit sa lahat ng camera ng device."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Wag paganahin tampok keyguard"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Pigilan ang paggamit ng ilang tampok sa keyguard."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Home"</item>
     <item msgid="869923650527136615">"Mobile"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Subukang muli"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Nalagpasan na ang maximum na mga pagtatangka sa Face Unlock"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Nagcha-charge, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Naka-charge."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Siningil"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Ikonekta ang iyong charger."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Walang SIM card."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Walang SIM card"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Walang SIM card sa tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Walang SIM card sa telepono."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Maglagay ng isang SIM card."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Na-clear ang pattern"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Idinagdag ang cell"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Nakumpleto ang pattern"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Magdagdag ng widget."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Walang laman"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Pinalaki ang bahagi ng pag-unlock."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Pinaliit ang bahagi ng pag-unlock."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> widget."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Tagapili ng user"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Katayuan"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Camera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Mga kontrol ng media"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Nagsimula na ang pagbabago ng ayos ng widget."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Natapos na ang pagbabago ng ayos ng widget."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Tinanggal ang widget na <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Palakihin ang bahagi ng pag-unlock."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Pag-unlock ng slide."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Pag-unlock ng pattern."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Face unlock."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pag-unlock ng pin."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Pag-unlock ng password."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Bahagi ng pattern."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Bahagi ng slide."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopyahin ang URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Pumili ng teksto"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Pagpili ng teksto"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"idagdag sa diksyunaryo"</string>
-    <string name="deleteText" msgid="7070985395199629156">"tanggalin"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Idagdag sa diksyunaryo"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Tanggalin"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Pamamaraan ng pag-input"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Pagkilos ng teksto"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Nauubusan na ang puwang ng storage"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Buksan ang mga available na Wi-Fi network"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Mag-sign in sa network ng Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Mag-sign in sa network"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Hindi makakonekta sa Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ay mayroong mahinang koneksyon sa Internet."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Kay:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"I-type ang kinakailangang PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Pansamantalang madidiskoneta ang telepono sa Wi-Fi habang nakakonekta ito sa <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Magpasok ng character"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Nagpapadala ng mga SMS na mensahe"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"Ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ay nagpapadala ng maraming mensaheng SMS. Gusto mo bang payagan ang app na ito na magpatuloy sa pagpapadala ng mga mensahe?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Payagan"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Tanggihan"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"Gustong magpadala ng mensahe ng &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sa &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Magsasanhi ito "<font fgcolor="#ffffb060">"ng mga pagsingil"</font>" sa iyong mobile account."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Magsasanhi ito ng mga pagsingil sa iyong mobile account."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Ipadala"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Kanselahin"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Tandaan ang aking pinili"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Mapapalitan mo ito sa ibang pagkakataon sa Mga Setting &gt; Apps"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Palaging Payagan"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Huwag kailanman Payagan"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Naalis ang SIM card"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Hindi magiging available ang mobile network hanggang mag-restart ka gamit ang isang may-bisang SIM card"</string>
     <string name="sim_done_button" msgid="827949989369963775">"Tapos na"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Itakda ang petsa"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Itakda"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Tapos na"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Default"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Walang mga kinakailangang pahintulot"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Itago"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Ipakita lahat"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"BAGO: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"BAGO: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Ibinigay ng <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Walang mga kinakailangang pahintulot"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"maaari itong magdulot ng gastos sa iyo"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB mass storage"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Nakakonekta ang USB"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Kumonekta ka sa iyong computer sa pamamagitan ng USB. Pindutin ang button sa ibaba kung gusto mong kumopya ng mga file sa pagitan ng iyong computer at USB storage ng iyong Android."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"Isinaaktibo ang VPN ng <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Pindutin upang pamahalaan ang network."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Nakakonekta sa <xliff:g id="SESSION">%s</xliff:g>. Pindutin upang pamahalaan ang network."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Kumukonekta ang Always-on VPN…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Nakakonekta ang Always-on VPN"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Error sa Always-on VPN"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Pindutin upang i-reset ang koneksyon"</string>
     <string name="upload_file" msgid="2897957172366730416">"Pumili ng file"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Walang napiling file"</string>
     <string name="reset" msgid="2448168080964209908">"I-reset"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Ibahagi"</string>
     <string name="find" msgid="4808270900322985960">"Hanapin"</string>
     <string name="websearch" msgid="4337157977400211589">"Paghahanap sa Web"</string>
+    <string name="find_next" msgid="5742124618942193978">"Hanapin ang susunod"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Hanapin ang nakaraan"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Kahilingan sa lokasyon mula kay <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Kahilingan sa Lokasyon"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Hiniling ni <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telepono"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Mga Headphone"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Mga speaker ng dock"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI audio"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio sa Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Tapos na"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Output ng media"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Nagsa-scan..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Kumukonekta..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Available"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Hindi available"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Built-in na Screen"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI Screen"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Nakakonekta ang wireless na display"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Lumalabas ang screen na ito sa isa pang device"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Alisin sa pagkakakonekta"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Emergency na tawag"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Nakalimutan ang Pattern"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Maling Pattern"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Maling Password"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Maling PIN"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Subukang muli sa loob ng <xliff:g id="NUMBER">%d</xliff:g> (na) segundo."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Iguhit ang iyong pattern"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Ilagay ang SIM PIN"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Ilagay ang PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Ilagay ang Password"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"Hindi na pinagana ang SIM ngayon. Maglagay ng PUK code upang magpatuloy. Makipag-ugnay sa carrier para sa mga detalye."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Ilagay ang ninanais na PIN code"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Kumpirmahin ang ninanais na PIN code"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Ina-unlock ang SIM card…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Hindi tamang PIN code."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Mag-type ng PIN na 4 hanggang 8 numero."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Dapat ay 8 numero o higit pa ang PUK code."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Muling ilagay ang tamang PUK code. Permanenteng hindi pagaganahin ang SIM ng mga paulit-ulit na pagtatangka."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Hindi tumutugma ang mga PIN code"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Masyadong maraming pagtatangka sa pattern"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Upang i-unlock, mag-sign in gamit ang iyong Google account."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Username (email)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Password"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Mag-sign in"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Di-wastong username o password."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Nakalimutan ang iyong username o password?"\n"Bisitahin ang "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Tinitingnan ang account…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Na-type mo nang hindi tama ang iyong PIN nang <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. "\n\n"Subukang muli sa loob ng <xliff:g id="NUMBER_1">%d</xliff:g> (na) segundo."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Na-type mo nang hindi tama ang iyong password nang <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. "\n\n"Subukang muli sa loob ng <xliff:g id="NUMBER_1">%d</xliff:g> (na) segundo."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Naguhit mo nang hindi tama ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. "\n\n"Subukang muli sa loob ng <xliff:g id="NUMBER_1">%d</xliff:g> (na) segundo."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Tinangka mo sa hindi tamang paraan na i-unlock ang tabelt nang <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. Pagkatapos ng <xliff:g id="NUMBER_1">%d</xliff:g> pang hindi matagumpay na pagtatangka, ire-reset ang tablet sa factory default at mawawala ang lahat ng data ng user."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Tinangka mo sa hindi tamang paraan na i-unlock ang telepono nang <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. Pagkatapos ng <xliff:g id="NUMBER_1">%d</xliff:g> pang hindi matagumpay na pagtatangka, ire-reset ang telepono sa factory default at mawawala ang lahat ng data ng user."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Tinangka mo sa hindi tamang paraan na i-unlock ang tablet nang <xliff:g id="NUMBER">%d</xliff:g> (na) beses. Ire-reset na ngayon ang tablet sa factory default."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Tinangka mo sa hindi tamang paraan na i-unlock ang telepono nang <xliff:g id="NUMBER">%d</xliff:g> (na) beses. Ire-reset na ngayon ang telepono sa factory default."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Naguhit mo nang hindi tama ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. Pagkatapos ng <xliff:g id="NUMBER_1">%d</xliff:g> pang hindi matagumpay na pagtatangka, hihilingin sa iyong i-unlock ang tablet mo gamit ang isang email account."\n\n" Subukang muli sa loob ng <xliff:g id="NUMBER_2">%d</xliff:g> (na) segundo."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Naguhit mo nang hindi tama ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. Pagkatapos ng <xliff:g id="NUMBER_1">%d</xliff:g> pang hindi matagumpay na pagtatangka, hihilingin sa iyong i-unlock ang telepono mo gamit ang isang email account."\n\n" Subukang muli sa loob ng <xliff:g id="NUMBER_2">%d</xliff:g> (na) segundo."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Alisin"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Lakasan ang volume nang lagpas sa ligtas na antas?"\n"Maaaring mapinsala ng pakikinig sa malakas na volume sa loob ng mahahabang panahon ang iyong pandinig."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Panatilihing nakapindot nang matagal ang iyong dalawang daliri upang paganahin ang pagiging naa-access."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Pinagana ang accessibility."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Nakansela ang pagiging naa-access."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Kasalukuyang user <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"May-ari"</string>
 </resources>
diff --git a/core/res/res/values-tr/donottranslate-cldr.xml b/core/res/res/values-tr/donottranslate-cldr.xml
index 92b0c72..1ab4ff7 100644
--- a/core/res/res/values-tr/donottranslate-cldr.xml
+++ b/core/res/res/values-tr/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Ocak</string>
-    <string name="month_long_standalone_february">Şubat</string>
-    <string name="month_long_standalone_march">Mart</string>
-    <string name="month_long_standalone_april">Nisan</string>
-    <string name="month_long_standalone_may">Mayıs</string>
-    <string name="month_long_standalone_june">Haziran</string>
-    <string name="month_long_standalone_july">Temmuz</string>
-    <string name="month_long_standalone_august">Ağustos</string>
-    <string name="month_long_standalone_september">Eylül</string>
-    <string name="month_long_standalone_october">Ekim</string>
-    <string name="month_long_standalone_november">Kasım</string>
-    <string name="month_long_standalone_december">Aralık</string>
-
-    <string name="month_long_january">Ocak</string>
-    <string name="month_long_february">Şubat</string>
-    <string name="month_long_march">Mart</string>
-    <string name="month_long_april">Nisan</string>
-    <string name="month_long_may">Mayıs</string>
-    <string name="month_long_june">Haziran</string>
-    <string name="month_long_july">Temmuz</string>
-    <string name="month_long_august">Ağustos</string>
-    <string name="month_long_september">Eylül</string>
-    <string name="month_long_october">Ekim</string>
-    <string name="month_long_november">Kasım</string>
-    <string name="month_long_december">Aralık</string>
-
-    <string name="month_medium_january">Oca</string>
-    <string name="month_medium_february">Şub</string>
-    <string name="month_medium_march">Mar</string>
-    <string name="month_medium_april">Nis</string>
-    <string name="month_medium_may">May</string>
-    <string name="month_medium_june">Haz</string>
-    <string name="month_medium_july">Tem</string>
-    <string name="month_medium_august">Ağu</string>
-    <string name="month_medium_september">Eyl</string>
-    <string name="month_medium_october">Eki</string>
-    <string name="month_medium_november">Kas</string>
-    <string name="month_medium_december">Ara</string>
-
-    <string name="month_shortest_january">O</string>
-    <string name="month_shortest_february">Ş</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">N</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">H</string>
-    <string name="month_shortest_july">T</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">E</string>
-    <string name="month_shortest_october">E</string>
-    <string name="month_shortest_november">K</string>
-    <string name="month_shortest_december">A</string>
-
-    <string name="day_of_week_long_sunday">Pazar</string>
-    <string name="day_of_week_long_monday">Pazartesi</string>
-    <string name="day_of_week_long_tuesday">Salı</string>
-    <string name="day_of_week_long_wednesday">Çarşamba</string>
-    <string name="day_of_week_long_thursday">Perşembe</string>
-    <string name="day_of_week_long_friday">Cuma</string>
-    <string name="day_of_week_long_saturday">Cumartesi</string>
-
-    <string name="day_of_week_medium_sunday">Paz</string>
-    <string name="day_of_week_medium_monday">Pzt</string>
-    <string name="day_of_week_medium_tuesday">Sal</string>
-    <string name="day_of_week_medium_wednesday">Çar</string>
-    <string name="day_of_week_medium_thursday">Per</string>
-    <string name="day_of_week_medium_friday">Cum</string>
-    <string name="day_of_week_medium_saturday">Cmt</string>
-
-    <string name="day_of_week_short_sunday">Paz</string>
-    <string name="day_of_week_short_monday">Pzt</string>
-    <string name="day_of_week_short_tuesday">Sal</string>
-    <string name="day_of_week_short_wednesday">Çar</string>
-    <string name="day_of_week_short_thursday">Per</string>
-    <string name="day_of_week_short_friday">Cum</string>
-    <string name="day_of_week_short_saturday">Cmt</string>
-
-    <string name="day_of_week_shortest_sunday">P</string>
-    <string name="day_of_week_shortest_monday">P</string>
-    <string name="day_of_week_shortest_tuesday">S</string>
-    <string name="day_of_week_shortest_wednesday">Ç</string>
-    <string name="day_of_week_shortest_thursday">P</string>
-    <string name="day_of_week_shortest_friday">C</string>
-    <string name="day_of_week_shortest_saturday">C</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Dün</string>
-    <string name="today">Bugün</string>
-    <string name="tomorrow">Yarın</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 1259bd5..dbb7b0d 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefon seçenekleri"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Ekran kilidi"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Kapat"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Hata raporu"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Hata raporu al"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Bu rapor, e-posta iletisi olarak göndermek üzere mevcut cihazınızın durumuyla ilgili bilgi toplar. Hata raporu başlatıldıktan sonra hazır olması biraz zaman alabilir, lütfen sabırlı olun."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Sessiz mod"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Ses KAPALI"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Ses AÇIK"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Mesajlarınız"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"SMS mesajlarınızı, e-posta iletilerinizi ve diğer mesajlarınızı okuyup yazma."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Kişisel bilgileriniz"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Tabletinizde depolanan kişilere ve takvime doğrudan erişim."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Telefonunuzda depolanan kişilere ve takvime doğrudan erişim."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Sizinle ilgili, kişi kartınızda kayıtlı bilgilere doğrudan erişim."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Sosyal bilgileriniz"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Kişileriniz ve sosyal bağlantılarınızla ilgili bilgilere doğrudan erişim."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Konumunuz"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Fiziksel konumunuzu izleme."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Ağ iletişimi"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Çeşitli ağ özelliklerine erişme."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Cihazlara ve ağlara Bluetooth ile eriş."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Ses Ayarları"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Ses ayarlarını değiştirme."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Pili Etkileyenler"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Pili çok çabuk tüketebilen özellikleri kullanma."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Takvim"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Takvime ve etkinliklere doğrudan erişim."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Kullanıcı Sözlüğünü Oku"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Kelimeleri kullanıcı sözlüğünde oku."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Kullanıcı Sözlüğüne Yaz"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Kelimeleri kullanıcı sözlüğüne ekle."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Yer İşaretleri ve Geçmiş"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Yer işaretlerine ve tarayıcı geçmişine doğrudan erişim."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Alarm"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Alarm saatini ayarlama."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Sesli mesaj"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Sesli mesaja doğrudan erişim."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Ses kaydetmek için mikrofona doğrudan erişim."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Resim ve video kaydı için kameraya doğrudan erişim."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Uygulama bilgileriniz"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Cihazınızdaki diğer uygulamaların davranışlarını etkileyebilme."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Duvar Kağıdı"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Cihazın duvar kâğıdı ayarlarını değiştirme."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Saat"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Cihazın saatini ve saat dilimini değiştirme."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Durum Çubuğu"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Cihaz durumunun çubuk ayarlarını değiştirme."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Senkronizasyon Ayarları"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Senkronizasyon ayarlarına erişme."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Hesaplarınız"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Kullanılabilir hesaplara erişin."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Donanım denetimleri"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Sisteme alt düzey erişim ve denetimi."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Geliştirme araçları"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Yalnızca uygulama geliştiriciler için gerekli özellikler."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Diğer Uygulamaların Kullanıcı Arayüzü"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Diğer uygulamaların kullanıcı arayüzünü etkileme."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Depolama"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"USB belleğe erişin."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"SD karta erişin."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Uygulamaya WAP mesajlarını alma ve işleme izni verir. Buna, size gönderilen mesajları takip edip size göstermeden silebilme izni de dahildir."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"çalışan uygulamaları al"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Uygulamaya o anda ve son çalışan görevler hakkında bilgi alma izni verir. Bu izin, uygulamanın cihaz tarafından kullanılan uygulamalar hakkında bilgi elde etmesine olanak sağlayabilir."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"kullanıcılar arasında etkileşim kur"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Uygulamaya cihazdaki farklı kullanıcılar arasında işlem gerçekleştirme izni verir. Kötü amaçlı uygulamalar bu izinle kullanıcılar arasındaki korumayı ihlal edebilir."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"kullanıcılar arasında etkileşim kurmak için tam izin"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Kullanıcılar arasında tüm etkileşime izin verir."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"kullanıcıları yönet"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Uygulamalara, sorgulama, oluşturma ve silme işlemleri de dahil olmak üzere cihazdaki kullanıcıları yönetme izni verir."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"çalışan uygulamaların ayrıntılarını al"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Uygulamaya, şu anda çalışmakta olan ve son çalışan işlemler hakkında ayrıntılı bilgi alma izni verir. Kötü amaçlı uygulamalar diğer uygulamalar hakkında gizli bilgileri ele geçirebilir."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"çalışan uygulamaları yeniden sırala"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Uygulamaya, sistemin iç durumunu alma izni verir. Kötü amaçlı uygulamalar normalde gerek duymadıkları çok çeşitli özel ve güvenli bilgilerini alabilir."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"ekran içeriğini al"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Uygulamaya, etkin pencerenin içeriğini alma izni verir. Kötü amaçlı uygulamalar tüm pencere içeriğini alabilir ve şifreleri hariç tüm metni inceleyebilir."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"erişilebilirliği geçici olarak etkinleştir"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Uygulamaya, cihazda erişilebilirliği geçici olarak etkinleştirme izni verir. Kötü amaçlı uygulamalar, kullanıcının izni olmadan erişilebilirliği etkinleştirebilirler."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"pencere bilgilerini al"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Uygulamaya, pencere yöneticisinden pencerelerle ilgili bilgi alma izni verir. Zararlı uygulamalar dahili sistem kullanımına yönelik bilgileri alabilir."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"etkinlikleri filtrele"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Uygulamaya, tüm kullanıcı etkinlikleri dağıtılmadan önce ilgili akışa filtre uygulayan bir giriş filtresi kaydetme izni verir. Zararlı uygulamalar kullanıcı müdahalesi olmadan sistem arayüzünü denetleyebilir."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"ekranı büyüt"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Uygulamaya bir ekranın içeriğini büyütme izni verir. Kötü amaçlı uygulamalar ekranın içeriğini etkileyerek cihazı kullanılmaz hale getirebilir."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"kısmi kapatma"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Eylem yöneticisini kapalı duruma getirir. Tam kapatma işlemi gerçekleştirmez."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"uygulama değişimlerini engelle"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Uygulamaya, çalışacak süreçlerin azami sayısını denetleme izni verir. Normal uygulamalar için gerekli değildir."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"arka plan uygulamaları kapanmaya zorla"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Uygulamaya, etkinliklerin arka plana geçer geçmez her zaman tamamlanıp tamamlanmadıklarını denetleme izni verir. Normal uygulamalar için gerekli değildir."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"pil istatistiklerini değiştir"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Uygulamaya, toplanan pil kullanım istatistiklerini değiştirme izni verir. Normal uygulamaların kullanımına yönelik değildir."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"pil istatistiklerini oku"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Uygulamaya, mevcut pil kullanım verilerini alt düzeyde okuma izni verir. Uygulamanın hangi uygulamaları kullandığınızla ilgili ayrıntılı bilgi edinmesine olanak sağlayabilir."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"pil istatistiklerini değiştir"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Uygulamaya, toplanan pil kullanım istatistiklerini değiştirme izni verir. Normal uygulamaların kullanımına yönelik değildir."</string>
     <string name="permlab_backup" msgid="470013022865453920">"sistem yedeğini kontrol et ve geri yükle"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Uygulamaya, sistem yedekleme ve geri yükleme mekanizmasını denetleme izni verir. Normal uygulamaların kullanımına yönelik değildir."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"tam yedekleme veya geri yükleme işlemini onaylayın"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"yetkisiz pencereleri görüntüle"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Uygulamaya, dahili sistem kullanıcı arayüzü tarafından kullanılacak pencereler oluşturma izni verir. Normal uygulamaların kullanımına yönelik değildir."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"diğer uygulamaları sürükle"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Uygulamaya sistem uyarı pencerelerini gösterme izni verir. Bazı uyarı pencereleri tüm ekranı kaplayabilir."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Uygulamaya, diğer uygulamaların veya kullanıcı arayüzüne ait bölümlerin üstüne çizim yapma izni verir. Bu izne sahip uygulamalar herhangi bir uygulamada kullanıcı arayüzünü kullanımınızı etkileyebilir veya diğer uygulamalarda gördüğünüzü düşündüğünüz arayüz öğelerini değiştirmiş olabilir."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"genel animasyon hızını değiştir"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Uygulamaya, istediği zaman genel animasyon hızını değiştirme (animasyonları hızlandırma veya yavaşlatma) izni verir."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"uygulama jetonlarını yönet"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Uygulamaya, kendi normal Z sıralamalarını atlayarak kendi jetonlarını oluşturma ve yönetme izni verir. Normal uygulamalar için gerekli değildir."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"ekranı dondur"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Uygulamaya tam ekran geçişi için ekranı geçici olarak dondurma izni verir."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"tuşlara bas ve düğmeleri denetle"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Uygulamaya, diğer uygulamalar için kendi giriş işlemlerini (tuşa basma vb.) gönderme izni verir. Kötü amaçlı uygulamalar tableti ele geçirmek için bunu kullanabilir."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Uygulamaya, kendi giriş etkinliklerini (tuşa basma vb.) diğer uygulamalara gönderme izni verir. Kötü amaçlı uygulamalar telefonu ele geçirmek için bunu kullanabilir."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"uygulamaları doğrudan yükle"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Uygulamaya, yeni veya güncellenmiş Android paketleri yükleme izni verir. Kötü amaçlı uygulamalar, istedikleri şekilde güçlü izinlere sahip yeni uygulamalar eklemek için bunu kullanabilir."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"tüm uygulama önbelleği verilerini sil"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Uygulamaya, önbellek dizinindeki dosyaları silerek tabletin depolama bölümünü boşaltma izni verir. Erişim genellikle sadece sistem işlemlerine verilecek şekilde oldukça kısıtlıdır."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Uygulamaya, önbellek dizinindeki dosyaları silerek telefonunuzun depolama bölümünü boşaltma izni verir. Erişim genellikle sadece sistem işlemlerine verilecek şekilde oldukça kısıtlıdır."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Uygulamaya, diğer uygulamaların önbellek dizinlerindeki dosyaları silerek tablette depolama alanı açma izni verir. Bu durum, diğer uygulamaların, verilerini tekrar almalarını gerektireceğinden daha yavaş başlamalarına neden olabilir."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Uygulamaya, diğer uygulamaların önbellek dizinlerindeki dosyaları silerek telefonda depolama alanı açma izni verir. Bu durum, diğer uygulamaların, verilerini tekrar almalarını gerektireceğinden daha yavaş başlamalarına neden olabilir."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"uygulama kaynaklarını taşı"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Uygulamaya, iç medyadan dış medyaya (ve tam tersi yönde) uygulama kaynaklarını taşıma izni verir."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"hassas günlük verilerini okuma"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Uygulamaya ekstra konum sağlayıcı komutlarına erişim izni verir. Bu izin, uygulamanın GPS veya diğer konum kaynaklarının çalışmasına müdahale etmesine olanak sağlayabilir."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"konum sağlayıcı yükleme izni"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Test amacıyla veya yeni bir konum sağlayıcı yüklemek için sahte konum kaynakları oluşturma. Bu izin, uygulamanın GPS veya konum sağlayıcıları gibi diğer konum kaynakları tarafından döndürülen konum ve/veya durum bilgisini geçersiz kılmasına olanak sağlar."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"kesin (GPS) konum"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Tabletteki Küresel Konumlandırma Sistemi gibi kesin konum kaynaklarına erişim. Konum hizmetleri kullanılabilir ve açık olduğunda, bu izin, uygulamanın kesin konumunuzu belirlemesine olanak sağlar."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Telefondaki Küresel Konumlandırma Sistemi gibi kesin konum kaynaklarına erişim. Konum hizmetleri kullanılabilir ve açık olduğunda, bu izin, uygulamanın kesin konumunuzu belirlemesine olanak sağlar."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"yaklaşık (ağ tabanlı) konum"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Baz istasyonu veya Kablosuz gibi ağ kaynaklarını kullanarak konum sağlayıcılardan alınan yaklaşık konum bilgisine erişim. Bu konum hizmetleri kullanılabilir ve açık olduğunda, bu izin, uygulamanın yaklaşık konumunuzu belirlemesine olanak sağlar."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"hassas konum (GPS ve ağ tabanlı)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Uygulamaya, Küresel Konumlandırma Sistemi (GPS) veya baz istasyonları ve Kablosuz bağlantı gibi ağ konum kaynaklarını kullanarak konumunuzu hassas bir şekilde belirleme izni verir. Uygulamaların bu konum hizmetlerini kullanabilmesi için bunların cihazınızda açık ve kullanılabilir olması gerekir. Uygulamalar bulunduğunuz yeri belirlemek için bu izni kullanabilirler ve bu kullanım fazladan pil tüketimine neden olabilir."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"yaklaşık konum (ağ tabanlı)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Uygulamaya, yaklaşık konumunuzu belirleme izni verir. Bu konum bilgisi, baz istasyonları ve Kablosuz bağlantı gibi ağ konum kaynaklarını kullanan konum hizmetlerinden elde edilir. Uygulamaların bu konum hizmetlerini kullanabilmesi için bunların cihazınızda açık ve kullanılabilir olması gerekir. Uygulamalar bulunduğunuz yeri yaklaşık olarak belirlemek için bu izni kullanabilirler."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"SurfaceFlinger\'a eriş"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Uygulamaya, SurfaceFlinger\'a ait düşük düzey özellikleri kullanma izni verir."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"çerçeve arabelleğini oku"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Uygulamaya, çerçeve arabelleğinin içeriğini okuma izni verir."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"Kablosuz ekranları yapılandır"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Uygulamaya kablosuz ekranları yapılandırma ve bunlara bağlanma izni verir."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Kablosuz ekranları denetle"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Uygulamaya kablosuz ekranların alt düzey özelliklerini kontrol etme izni verir."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ses ayarlarınızı değiştirin"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Uygulamaya ses düzeyi ve ses çıkışı için kullanılan hoparlör gibi genel ses ayarlarını değiştirme izni verir."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ses kaydet"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"Bluetooth ayarlara eriş"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Uygulamaya, yerel Bluetooth tabletini yapılandırma ve uzak cihazları keşfedip bunlarla eşleşme izni verir."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Uygulamaya, yerel Bluetooth telefonunu yapılandırma ve uzak cihazları keşfedip bunlarla eşleşme izni verir."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"WiMAX bağlantılarını görüntüle"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX\'e bağlan veya WiMAX bağlantısını kes"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Uygulamaya, WiMAX\'in etkin olup olmadığını belirleme ve bağlı tüm WiMAX ağlarıyla ilgili bilgilere erişme izni verir."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX durumunu değiştir"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Uygulamaya, tableti WiMAX ağlarına bağlanma veya bağlantıyı kesme izni verir."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Uygulamaya, o anda senkronize edilmiş özet akışlarını değiştirme izni verir. Kötü amaçlı uygulamalar senkronize edilmiş özet akışlarını değiştirebilir."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"sözlüğe eklediğim terimleri oku"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Uygulamaya, kullanıcının kullanıcı sözlüğünde depolamış olabileceği kelimeleri, adları ve kelime öbeklerini okuma izni verir."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"kullanıcı tanımlı sözlüğe yaz"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"kullanıcı tanımlı sözlüğe kelime ekle"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Uygulamaya, kullanıcı sözlüğüne yeni kelimeler yazma izni verir."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"korumalı depolama birimine erişimi test et"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"korumalı depolama birimine erişimi test et"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Uygulamaya gelecekteki cihazlarda kullanılabilecek USB belleğe ilişkin bir izni test etme izni verir."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Uygulamaya, gelecekteki cihazlarda kullanılabilecek USB depolama birimi için bir izni test etme olanağı verir."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Uygulamaya gelecekteki cihazlarda kullanılabilecek SD karta ilişkin bir izni test etme olanağı verir."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"USB belleğimin içeriğini değiştir veya sil"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"SD kartın içeriğini değiştir veya sil"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Uygulamaya, SD karta yazma izni verir."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"dahili medya depolama birimi içeriğini değiştir/sil"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Uygulamaya, dahili medya depolama içeriğini değiştirme izni verir."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"tüm kullanıcılar için harici depolama eriş"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Uygulamaya tüm kullanıcılar için harici depolamaya erişim izni verir."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"önbellek dosya sistemine eriş"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Uygulamaya, önbellek dosya sisteminde okuma ve yazma yapma izni verir."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"İnternet çağrılar yap/alma"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Depolanan uygulama verilerinin şifrelenmiş olmasını zorunlu kılma."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Kameraları devre dışı bırak"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Tüm cihaz kameralarının kullanımını engelleme."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Keyguard\'daki özellikleri devre dışı bırak"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Keyguard\'daki bazı özelliklerin kullanılmasını önle."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Ev"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Tekrar deneyin"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Yüz Tanıma Kilidi için maksimum deneme sayısı aşıldı"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Şarj oluyor (<xliff:g id="PERCENT">%%</xliff:g><xliff:g id="NUMBER">%d</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Şarj oldu."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Şarj oldu"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="PERCENT">%%</xliff:g><xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Şarj cihazınızı bağlayın."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"SIM kart yok."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM kart yok"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tablette SIM kart yok."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefonda SIM kart yok."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"SIM kartı takın."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Desen temizlendi"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Hücre eklendi"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Desen tamamlandı"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Widget ekleyin."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Boş"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Kilit açma alanı genişletildi."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Kilit açma alanı daraltıldı."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> widget\'ı."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Kullanıcı seçici"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Durum"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Kamera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Medya denetimleri"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Widget\'ları yeniden sıralama işlemi başladı."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Widget\'ları yeniden sıralama işlemi bitti."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> widget\'ı silindi."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Kilit açma alanını genişletin."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Kaydırarak kilit açma."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desenle kilit açma."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Yüzle kilit açma."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin koduyla kilit açma."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Şifreyle kilit açma."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Desen alanı."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Kaydırma alanı."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"URL\'yi kopyala"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Metin seç"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Metin seçimi"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"sözlüğe ekle"</string>
-    <string name="deleteText" msgid="7070985395199629156">"sil"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Sözlüğe ekle"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Sil"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Giriş yöntemi"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Metin eylemleri"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Depolama alanı bitiyor"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Kullanılabilir kablosuz ağları aç"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Kablosuz ağda oturum açın"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Ağda oturum açın"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kablosuz bağlantısı kurulamadı"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" İnternet bağlantısı zayıf."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Alıcı:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Gerekli PIN\'i yazın:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefon <xliff:g id="DEVICE_NAME">%1$s</xliff:g> adlı cihaza bağlıyken Kablosuz ağ bağlantısı geçici olarak kesilecektir"</string>
     <string name="select_character" msgid="3365550120617701745">"Karakter ekle"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS mesajları gönderiliyor"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; çok sayıda SMS mesajı gönderiyor. Bu uygulamanın mesaj göndermeye devam etmesine izin veriyor musunuz?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"İzin ver"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Reddet"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;, &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; adresine bir mesaj göndermek istiyor."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Bu işlem, mobil hesabınızdan "<font fgcolor="#ffffb060">"ücret alınmasına neden olabilir"</font>"."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Bu işlem, mobil hesabınızdan ücret alınmasına neden olacaktır."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Gönder"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"İptal"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Seçimimi hatırla"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Bu ayarı daha sonra Ayarlar &gt; Uygulamalar\'dan değiştirebilirsiniz."</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Her Zaman İzin Ver"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Asla İzin Verme"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM kart çıkarıldı"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Geçerli bir SIM kart yerleştirilmiş olarak yeniden başlatana kadar mobil ağ kullanılamayacak."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Tamamlandı"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Tarihi ayarlayın"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ayarla"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Tamamlandı"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Varsayılan"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"İzin gerektirmez"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Gizle"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Tümünü göster"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"YENİ: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"YENİ: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Sağlayan: <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"İzin gerektirmez"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"bunun için sizden ücret alınabilir"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB yığın belleği"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB bağlandı"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Cihazınızı USB ile bilgisayarınıza bağladınız. Bilgisayarınız ile Android\'inizin USB belleği arasında dosya kopyalamak istiyorsanız aşağıdaki düğmeye dokunun."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN, <xliff:g id="APP">%s</xliff:g> tarafından etkinleştirildi"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Ağı yönetmek için dokunun."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"<xliff:g id="SESSION">%s</xliff:g> oturumuna bağlandı. Ağı yönetmek için dokunun."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Her zaman açık VPN\'ye bağlanılıyor…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Her zaman açık VPN\'ye bağlanıldı"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Her zaman açık VPN hatası"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Bağlantıyı sıfırlamak için dokunun"</string>
     <string name="upload_file" msgid="2897957172366730416">"Dosya seç"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Seçili dosya yok"</string>
     <string name="reset" msgid="2448168080964209908">"Sıfırla"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Paylaş"</string>
     <string name="find" msgid="4808270900322985960">"Bul"</string>
     <string name="websearch" msgid="4337157977400211589">"Google Web Arama"</string>
+    <string name="find_next" msgid="5742124618942193978">"Sonrakini bul"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Öncekini bul"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g> kullanıcısından gelen konum isteği"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Konum isteği"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g> tarafından istendi (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Kulaklıklar"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Yuva hoparlörleri"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI ses"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth ses"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Tamamlandı"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Medya çıkışı"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Taranıyor..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Bağlanılıyor..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Kullanılabilir"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Yok"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Yerleşik Ekran"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI Ekran"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Yer Paylaşımı No. <xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Kablosuz ekrana bağlandı"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Bu ekran başka bir cihazda gösteriliyor"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Bağlantıyı kes"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Acil durum çağrısı"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Deseni Unuttunuz mu?"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Yanlış Desen"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Yanlış Şifre"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Yanlış PIN"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%d</xliff:g> saniye içinde yeniden deneyin."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Deseninizi çizin"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"SIM PIN kodunu girin"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"PIN\'i girin"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Şifreyi Girin"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM kart artık devre dışı bırakıldı. Devam etmek için PUK kodunu girin. Ayrıntılı bilgi için operatörle bağlantı kurun."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"İstenen PIN kodunu girin"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"İstenen PIN kodunu onaylayın"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM kart kilidi açılıyor…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Yanlış PIN kodu."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"4-8 rakamdan oluşan bir PIN girin."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK kodu 8 veya daha çok basamaklı bir sayı olmalıdır."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Doğru PUK kodunu tekrar girin. Çok sayıda deneme yapılırsa SIM kart kalıcı olarak devre dışı bırakılır."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN kodları eşleşmiyor"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Çok fazla sayıda desen denemesi yapıldı"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Kilidi açmak için Google hesabınızla oturum açın."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Kullanıcı adı (e-posta)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Şifre"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Oturum aç"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Geçersiz kullanıcı adı veya şifre."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Kullanıcı adınızı veya şifrenizi mi unuttunuz?"\n<b>"google.com/accounts/recovery"</b>" adresini ziyaret edin."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Hesap denetleniyor…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"PIN kodunuzu <xliff:g id="NUMBER_0">%d</xliff:g> kez yanlış girdiniz. "\n\n"<xliff:g id="NUMBER_1">%d</xliff:g> saniye içinde tekrar deneyin."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Şifrenizi <xliff:g id="NUMBER_0">%d</xliff:g> kez yanlış yazdınız. "\n\n"<xliff:g id="NUMBER_1">%d</xliff:g> saniye içinde tekrar deneyin."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%d</xliff:g> kez yanlış çizdiniz. "\n\n"<xliff:g id="NUMBER_1">%d</xliff:g> saniye içinde tekrar deneyin."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Tablet kilidini <xliff:g id="NUMBER_0">%d</xliff:g> defa yanlış bir şekilde açmaya çalıştınız. <xliff:g id="NUMBER_1">%d</xliff:g> defa daha başarısız deneme yapılırsa, tablet fabrika varsayılan değerine sıfırlanır ve tüm kullanıcı verileri kaybedilir."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Telefonun kilidini <xliff:g id="NUMBER_0">%d</xliff:g> defa yanlış bir şekilde açmaya çalıştınız. <xliff:g id="NUMBER_1">%d</xliff:g> defa daha başarısız deneme yapılırsa, telefon fabrika varsayılan değerine sıfırlanır ve tüm kullanıcı verileri kaybedilir."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Tablet kilidini <xliff:g id="NUMBER">%d</xliff:g> defa yanlış bir şekilde açmaya çalıştınız. Tablet şimdi fabrika varsayılanına sıfırlanacak."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Telefon kilidini <xliff:g id="NUMBER">%d</xliff:g> defa yanlış bir şekilde açmaya çalıştınız. Telefon şimdi fabrika varsayılanına sıfırlanacak."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%d</xliff:g> kez yanlış çizdiniz. <xliff:g id="NUMBER_1">%d</xliff:g> başarısız denemeden sonra, tabletinizi bir e-posta hesabı kullanarak açmanız istenir."\n\n" <xliff:g id="NUMBER_2">%d</xliff:g> saniye içinde tekrar deneyin."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%d</xliff:g> kez yanlış çizdiniz. <xliff:g id="NUMBER_1">%d</xliff:g> başarısız denemeden sonra telefonunuzu bir e-posta hesabı kullanarak açmanız istenir."\n\n" <xliff:g id="NUMBER_2">%d</xliff:g> saniye içinde tekrar deneyin."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Kaldır"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Ses düzeyi güvenli seviyenin üzerine çıkarılsın mı?"\n"Yüksek sesle uzun süre dinlemek işitme yetinize zarar verebilir."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Erişilebilirliği etkinleştirmek için iki parmağınızı basılı tutmaya devam edin."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Erişilebilirlik etkinleştirildi."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Erişilebilirlik iptal edildi."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Geçerli kullanıcı: <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Sahibi"</string>
 </resources>
diff --git a/core/res/res/values-uk-rUA/donottranslate-cldr.xml b/core/res/res/values-uk-rUA/donottranslate-cldr.xml
index caf46a3..f7ca458 100644
--- a/core/res/res/values-uk-rUA/donottranslate-cldr.xml
+++ b/core/res/res/values-uk-rUA/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">січень</string>
-    <string name="month_long_standalone_february">лютий</string>
-    <string name="month_long_standalone_march">березень</string>
-    <string name="month_long_standalone_april">квітень</string>
-    <string name="month_long_standalone_may">травень</string>
-    <string name="month_long_standalone_june">червень</string>
-    <string name="month_long_standalone_july">липень</string>
-    <string name="month_long_standalone_august">серпень</string>
-    <string name="month_long_standalone_september">вересень</string>
-    <string name="month_long_standalone_october">жовтень</string>
-    <string name="month_long_standalone_november">листопад</string>
-    <string name="month_long_standalone_december">грудень</string>
-
-    <string name="month_long_january">січня</string>
-    <string name="month_long_february">лютого</string>
-    <string name="month_long_march">березня</string>
-    <string name="month_long_april">квітня</string>
-    <string name="month_long_may">травня</string>
-    <string name="month_long_june">червня</string>
-    <string name="month_long_july">липня</string>
-    <string name="month_long_august">серпня</string>
-    <string name="month_long_september">вересня</string>
-    <string name="month_long_october">жовтня</string>
-    <string name="month_long_november">листопада</string>
-    <string name="month_long_december">грудня</string>
-
-    <string name="month_medium_january">січ.</string>
-    <string name="month_medium_february">лют.</string>
-    <string name="month_medium_march">бер.</string>
-    <string name="month_medium_april">квіт.</string>
-    <string name="month_medium_may">трав.</string>
-    <string name="month_medium_june">черв.</string>
-    <string name="month_medium_july">лип.</string>
-    <string name="month_medium_august">серп.</string>
-    <string name="month_medium_september">вер.</string>
-    <string name="month_medium_october">жовт.</string>
-    <string name="month_medium_november">лист.</string>
-    <string name="month_medium_december">груд.</string>
-
-    <string name="month_shortest_january">С</string>
-    <string name="month_shortest_february">Л</string>
-    <string name="month_shortest_march">Б</string>
-    <string name="month_shortest_april">К</string>
-    <string name="month_shortest_may">Т</string>
-    <string name="month_shortest_june">Ч</string>
-    <string name="month_shortest_july">Л</string>
-    <string name="month_shortest_august">С</string>
-    <string name="month_shortest_september">В</string>
-    <string name="month_shortest_october">Ж</string>
-    <string name="month_shortest_november">Л</string>
-    <string name="month_shortest_december">Г</string>
-
-    <string name="day_of_week_long_sunday">неділя</string>
-    <string name="day_of_week_long_monday">понеділок</string>
-    <string name="day_of_week_long_tuesday">вівторок</string>
-    <string name="day_of_week_long_wednesday">середа</string>
-    <string name="day_of_week_long_thursday">четвер</string>
-    <string name="day_of_week_long_friday">пʼятниця</string>
-    <string name="day_of_week_long_saturday">субота</string>
-
-    <string name="day_of_week_medium_sunday">нд.</string>
-    <string name="day_of_week_medium_monday">пн.</string>
-    <string name="day_of_week_medium_tuesday">вт.</string>
-    <string name="day_of_week_medium_wednesday">ср.</string>
-    <string name="day_of_week_medium_thursday">чт.</string>
-    <string name="day_of_week_medium_friday">пт.</string>
-    <string name="day_of_week_medium_saturday">сб.</string>
-
-    <string name="day_of_week_short_sunday">нд.</string>
-    <string name="day_of_week_short_monday">пн.</string>
-    <string name="day_of_week_short_tuesday">вт.</string>
-    <string name="day_of_week_short_wednesday">ср.</string>
-    <string name="day_of_week_short_thursday">чт.</string>
-    <string name="day_of_week_short_friday">пт.</string>
-    <string name="day_of_week_short_saturday">сб.</string>
-
-    <string name="day_of_week_shortest_sunday">Н</string>
-    <string name="day_of_week_shortest_monday">П</string>
-    <string name="day_of_week_shortest_tuesday">В</string>
-    <string name="day_of_week_shortest_wednesday">С</string>
-    <string name="day_of_week_shortest_thursday">Ч</string>
-    <string name="day_of_week_shortest_friday">П</string>
-    <string name="day_of_week_shortest_saturday">С</string>
-
-    <string name="am">дп</string>
-    <string name="pm">пп</string>
-    <string name="yesterday">Вчора</string>
-    <string name="today">Сьогодні</string>
-    <string name="tomorrow">Завтра</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
diff --git a/core/res/res/values-uk/donottranslate-cldr.xml b/core/res/res/values-uk/donottranslate-cldr.xml
index 46211ac..51c2cb5 100644
--- a/core/res/res/values-uk/donottranslate-cldr.xml
+++ b/core/res/res/values-uk/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">Січень</string>
-    <string name="month_long_standalone_february">Лютий</string>
-    <string name="month_long_standalone_march">Березень</string>
-    <string name="month_long_standalone_april">Квітень</string>
-    <string name="month_long_standalone_may">Травень</string>
-    <string name="month_long_standalone_june">Червень</string>
-    <string name="month_long_standalone_july">Липень</string>
-    <string name="month_long_standalone_august">Серпень</string>
-    <string name="month_long_standalone_september">Вересень</string>
-    <string name="month_long_standalone_october">Жовтень</string>
-    <string name="month_long_standalone_november">Листопад</string>
-    <string name="month_long_standalone_december">Грудень</string>
-
-    <string name="month_long_january">січня</string>
-    <string name="month_long_february">лютого</string>
-    <string name="month_long_march">березня</string>
-    <string name="month_long_april">квітня</string>
-    <string name="month_long_may">травня</string>
-    <string name="month_long_june">червня</string>
-    <string name="month_long_july">липня</string>
-    <string name="month_long_august">серпня</string>
-    <string name="month_long_september">вересня</string>
-    <string name="month_long_october">жовтня</string>
-    <string name="month_long_november">листопада</string>
-    <string name="month_long_december">грудня</string>
-
-    <string name="month_medium_january">січ.</string>
-    <string name="month_medium_february">лют.</string>
-    <string name="month_medium_march">бер.</string>
-    <string name="month_medium_april">квіт.</string>
-    <string name="month_medium_may">трав.</string>
-    <string name="month_medium_june">черв.</string>
-    <string name="month_medium_july">лип.</string>
-    <string name="month_medium_august">серп.</string>
-    <string name="month_medium_september">вер.</string>
-    <string name="month_medium_october">жовт.</string>
-    <string name="month_medium_november">лист.</string>
-    <string name="month_medium_december">груд.</string>
-
-    <string name="month_shortest_january">С</string>
-    <string name="month_shortest_february">Л</string>
-    <string name="month_shortest_march">Б</string>
-    <string name="month_shortest_april">К</string>
-    <string name="month_shortest_may">Т</string>
-    <string name="month_shortest_june">Ч</string>
-    <string name="month_shortest_july">Л</string>
-    <string name="month_shortest_august">С</string>
-    <string name="month_shortest_september">В</string>
-    <string name="month_shortest_october">Ж</string>
-    <string name="month_shortest_november">Л</string>
-    <string name="month_shortest_december">Г</string>
-
-    <string name="day_of_week_long_sunday">Неділя</string>
-    <string name="day_of_week_long_monday">Понеділок</string>
-    <string name="day_of_week_long_tuesday">Вівторок</string>
-    <string name="day_of_week_long_wednesday">Середа</string>
-    <string name="day_of_week_long_thursday">Четвер</string>
-    <string name="day_of_week_long_friday">Пʼятниця</string>
-    <string name="day_of_week_long_saturday">Субота</string>
-
-    <string name="day_of_week_medium_sunday">Нд</string>
-    <string name="day_of_week_medium_monday">Пн</string>
-    <string name="day_of_week_medium_tuesday">Вт</string>
-    <string name="day_of_week_medium_wednesday">Ср</string>
-    <string name="day_of_week_medium_thursday">Чт</string>
-    <string name="day_of_week_medium_friday">Пт</string>
-    <string name="day_of_week_medium_saturday">Сб</string>
-
-    <string name="day_of_week_short_sunday">Нд</string>
-    <string name="day_of_week_short_monday">Пн</string>
-    <string name="day_of_week_short_tuesday">Вт</string>
-    <string name="day_of_week_short_wednesday">Ср</string>
-    <string name="day_of_week_short_thursday">Чт</string>
-    <string name="day_of_week_short_friday">Пт</string>
-    <string name="day_of_week_short_saturday">Сб</string>
-
-    <string name="day_of_week_shortest_sunday">Н</string>
-    <string name="day_of_week_shortest_monday">П</string>
-    <string name="day_of_week_shortest_tuesday">В</string>
-    <string name="day_of_week_shortest_wednesday">С</string>
-    <string name="day_of_week_shortest_thursday">Ч</string>
-    <string name="day_of_week_shortest_friday">П</string>
-    <string name="day_of_week_shortest_saturday">С</string>
-
-    <string name="am">дп</string>
-    <string name="pm">пп</string>
-    <string name="yesterday">Вчора</string>
-    <string name="today">Сьогодні</string>
-    <string name="tomorrow">Завтра</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %p</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 8131fd7..6512007 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Параметри телеф."</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Заблок. екран"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Вимкнути"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Звіт про помилки"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Зробити звіт про помилки"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Збиратиметься інформація про поточний стан вашого пристрою для подальшого надсилання електронною поштою. Від початку створення звіту про помилки до його повної готовності для надсилання потрібен певний час, тож будьте терплячими."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Беззвуч. режим"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Звук ВИМК."</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Звук УВІМК."</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Ваші повідомл."</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Читати та писати в SMS, електронні листи й інші повідомлення."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Ваша особиста інформація"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Прямий доступ до контактів і календаря, збережених у пристрої."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Прямий доступ до ваших контактів і календаря, збереж. у телефоні."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Безпосередній доступ до інформації про вас, збереженої на вашій картці контакта."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Соціальна інформація"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Безпосередній доступ до інформації про ваші контакти та соціальні зв’язки."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Ваше місцезнаходження"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Відстежувати ваше фізичне місцезнаходження."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Підключення до мережі"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Отримувати доступ до різних функцій мережі."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Отримувати доступ до пристроїв і мереж через Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Налаштування звуку"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Зміна налаштувань звуку."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Заряд акумулятора"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Використання функцій, які швидко зменшують заряд акумулятора."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Календар"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Безпосередній доступ до календаря та подій."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Читати словник користувача"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Читати слова в словнику користувача."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Писати в словник користувача"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Додавати слова в словник користувача."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Закладки й історія"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Безпосередній доступ до закладок та історії веб-переглядача."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Сигнал"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Налаштування сигналу будильника."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Голосова пошта"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Безпосередній доступ до голосової пошти."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Мікрофон"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Безпосередній доступ до мікрофона для запису звуку."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Камера"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Безпосередній доступ до камери для здійснення фото- чи відеозйомки."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Інформація про програми"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Здатність впливати на роботу інших програм на пристрої."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Фоновий малюнок"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Зміна налаштувань фонового малюнка пристрою."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Годинник"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Зміна часу чи часового поясу пристрою."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Рядок стану"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Зміна налаштувань рядка стану пристрою."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Налаштування синхронізації"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Доступ до налаштувань синхронізації."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Ваші облікові записи"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Доступ до доступних обл. записів."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Керув. апар. забезп."</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Контроль і доступ до системи на нижчому рівні."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Інструм. розробника"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Функції, потрібні лише для розробників програм."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Інтерфейс іншої програми"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Вплив на інтерфейс інших програм."</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>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Дозволяє програмі отримувати й обробляти WAP-повідомлення. Це означає, що програма може відстежувати чи видаляти повідомлення, надіслані на ваш пристрій, навіть не показуючи їх вам."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"отримувати запущені програми"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Дозволяє програмі отримувати інформацію про поточні й останні запущені завдання. Це може дозволити програмі виявляти інформацію про програми, які використовуються на пристрої."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"взаємодіяти між користувачами"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Дозволяє програмі виконувати дії щодо різних користувачів на пристрої. Шкідливі програми можуть використовувати це для порушення захисту окремих користувачів."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"повна ліцензія на взаємодію між користувачами"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Дозволяє всі можливі взаємодії щодо користувачів."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"керувати користувачами"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Дозволяє програмам керувати користувачами на пристрої, зокрема надсилати запити про користувачів, створювати й видаляти їх."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"отримувати дані про запущені програми"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Дозволяє програмі отримувати інформацію про поточні й останні запущені завдання. Шкідливі програми можуть виявляти особисту інформацію про інші програми."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"змінювати порядок запущених програм"</string>
@@ -243,6 +287,14 @@
     <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="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"тимчасово вмикати доступність"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Дозволяє програмі тимчасового вмикати доступність на пристрої. Шкідливі програми можуть вмикати доступність без згоди користувача."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"отримувати інформацію про вікна"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Дозволяє програмі отримувати інформацію про вікна від диспетчера вікон. Шкідливі програми можуть отримувати інформацію, яка призначена для внутрішнього користування системи."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"фільтрувати події"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Дозволяє програмі реєструвати вхідний фільтр, який фільтрує потік усіх подій користувача перед їх надсиланням. Шкідливі програми можуть контролювати інтерфейс системи без втручання користувача."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"збільшити екран"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Дозволяє програмі збільшувати вміст екрана. Зловмисні програми можуть змінювати вміст екрана так, що пристроєм стає неможливо користуватися."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"частк. заверш. роб."</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Переводить диспетчер дій у стан завершення роботи. Не виконує повне завершення роботи."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"запобіг. зміні програм"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Дозволяє програмі контролювати максимальну кількість процесів, які буде запущено. Ніколи не вимагається для звичайних програм."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"примусово закривати фонові програми"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Дозволяє програмі контролювати обов’язкове завершення всіх дій, які переходять у фоновий режим. Ніколи не вимагається для звичайних програм."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"змінювати статистику батареї"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Дозволяє програмі змінювати зібрану статистику акумулятора. Не для використання звичайними програмами."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"читати статистику акумулятора"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Дозволяє програмі зчитувати дані про поточний низький рівень споживання заряду акумулятора. Програма може отримувати докладну інформацію про те, якими програмами ви користуєтеся."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"змінювати статистику акумулятора"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Дозволяє програмі змінювати зібрану статистику акумулятора. Не для використання звичайними програмами."</string>
     <string name="permlab_backup" msgid="470013022865453920">"контр. резерв. копіюв. і відн. сист."</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Дозволяє програмі контролювати механізми резервного копіювання та відновлення системи. Не для використання звичайними програмами."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"підтверджувати повну операцію резервного копіювання або відновлення"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"відображати несанкціон. вікна"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Дозволяє програмі створювати вікна, які мають використовуватися інтерфейсом користувача внутрішньої системи. Не для використання звичайними програмами."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"відображатися над іншими програмами"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Дозволяє програмі відображати вікна сповіщень системи. Деякі вікна сповіщень можуть контролювати весь екран."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Дозволяє програмі відображатися поверх інших програм або частин інтерфейсу користувача. Це може заважати користуватися інтерфейсом інших програм або змінювати те, що ви бачите в інших програмах."</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="permlab_freezeScreen" msgid="4708181184441880175">"зафіксувати екран"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Дозволяє програмі тимчасово фіксувати екран для переходу в повноекранний режим."</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>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"безпосередньо встановлювати програми"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Дозволяє програмі встановлювати нові чи оновлені пакети Android. Шкідливі програми можуть використовувати це для додавання нових програм із сумнівно переконливими дозволами."</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="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Дозволяє програмі звільняти пам’ять планшетного ПК, видаляючи файли в каталогах кешу інших програм. Через це інші програми можуть запускатися повільніше, оскільки їм потрібно повторно отримати свої дані."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Дозволяє програмі звільняти пам’ять телефону, видаляючи файли в каталогах кешу інших програм. Через це інші програми можуть запускатися повільніше, оскільки вони мають повторно отримати свої дані."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"переміщувати ресурси програми"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Дозволяє програмі переміщувати ресурси програми з внутрішніх на зовнішні носії та навпаки."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"зчит. закриті дані журн."</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Дозволяє програмі отримувати доступ до додаткових команд постачальника даних місцезнаходження. Це може дати програмі змогу втручатися в роботу GPS чи інших джерел даних про місцезнаходження."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"дозвіл на встановлення провайдера місцезнах."</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Створювати фіктивні джерела місцезнаходження для тестування або встановлювати нового постачальника даних місцезнаходження. Це може дозволити програмі замінювати місцезнаходження та/чи статус, отриманий від інших джерел даних про місцезнаходження, як-от постачальників послуг GPS або постачальників даних місцезнаходження."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"точне (GPS) місцезнаходження"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Отримувати доступ до джерел даних про точне місцезнаходження, як-от системи глобального позиціонування на планшетному ПК. Якщо ці служби локації доступні й увімкнені, такий дозвіл дає програмі змогу визначати ваше точне місцезнаходження."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Отримувати доступ до джерел даних про точне місцезнаходження, як-от системи глобального позиціонування на телефоні. Якщо служби локації доступні й увімкнені, такий дозвіл дає програмі змогу визначати ваше точне місцезнаходження."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"приблизне (мережеве) місцезнаходження"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Отримувати доступ до приблизного місцезнаходження від постачальників даних місцезнаходження за допомогою мережевих джерел, як-от веж мобільного зв’язку й точок доступу Wi-Fi. Якщо ці служби локації доступні й увімкнені, такий дозвіл дає програмі змогу визначати ваше приблизне місцезнаходження."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"точне місцезнаходження (на основі GPS і мережі)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Дозволяє програмі дізнатися ваше точне місцезнаходження за допомогою системи глобального позиціонування (GPS) або мережевих джерел даних про місцезнаходження, як-от антен мобільного зв’язку та Wi-Fi. Щоб програма могла використовувати служби локації, вони мають бути ввімкнені та доступні для вашого пристрою. Програми можуть використовувати це, щоб визначити ваше приблизне місцезнаходження, і додатково споживати заряд акумулятора."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"приблизне місцезнаходження (на основі мережі)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Дозволяє програмі дізнатися ваше приблизне місцезнаходження. Місцезнаходження визначається службами локації за допомогою мережевих джерел даних про місцезнаходження, як-от антен мобільного зв’язку та Wi-Fi. Щоб програма могла використовувати служби локації, вони мають бути ввімкнені та доступні для вашого пристрою. Програми можуть використовувати це, щоб визначити ваше приблизне місцезнаходження."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"дост. до 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="permlab_configureWifiDisplay" msgid="5595661694746742168">"налаштувати екрани Wi-Fi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Дозволяє програмі налаштовувати екрани Wi-Fi і під’єднуватися до них."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"керувати екранами Wi-Fi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Дозволяє програмі керувати низькорівневими функціями екранів Wi-Fi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"змінювати налаштув-ня звуку"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Дозволяє програмі змінювати загальні налаштування звуку, як-от гучність і динамік, який використовується для виводу сигналу."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"запис-ти аудіо"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"отримувати доступ до налаштувань Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Дозволяє програмі налаштовувати планшетний ПК із локальним Bluetooth, а також знаходити віддалені пристрої та створювати з ними пару."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Дозволяє програмі налаштовувати телефон із локальним Bluetooth, а також знаходити віддалені пристрої та створювати з ними пару."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Переглядати з’єднання WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"під’єднуватися та від’єднуватися від WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Дозволяє програмі визначати, чи ввімкнено WiMAX, а також переглядати інформацію про будь-які під’єднані мережі WiMAX."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Змінити стан WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Дозволяє програмі під’єднувати планшетний ПК до мереж WiMAX і від’єднувати його від них."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Дозволяє програмі змінювати поточно синхронізовані канали. Шкідливі програми можуть змінювати ваші синхронізовані канали."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"читати додані в словник терміни"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Дозволяє програмі читати всі слова, назви та фрази, які користувач міг зберегти у своєму словнику."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"писати у вказаний користувачем словник"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"додавати слова у вказаний користувачем словник"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Дозволяє програмі писати нові слова в словник користувача."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"тестувати доступ до захищеної пам’яті"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"тестувати доступ до захищеної пам’яті"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Дозволяє програмі тестувати дозвіл для носія USB, який буде доступний на майбутніх пристроях."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Дозволяє програмі тестувати дозвіл для носія USB, який буде доступний на майбутніх пристроях."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Дозволяє програмі тестувати дозвіл для карти SD, яка буде доступна на майбутніх пристроях."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"змінювати чи видаляти вміст USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"змінювати чи видаляти вміст на карті SD"</string>
@@ -534,6 +593,8 @@
     <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="permlab_sdcardAccessAll" msgid="8150613823900460576">"доступ до зовн. пам’яті всіх корист."</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Дозволяє програмі отримувати доступ до зовнішньої пам’яті всіх користувачів."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"отр. дост. до файл. сист. кешу"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Дозволяє програмі читати з файлової системи кеш-пам’яті та писати в неї."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"здійсн./отрим. Інтернет-дзвін."</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Вимагати шифрування даних збереженої програми."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Вимкнути камери"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Запобігати використанню всіх камер пристрою."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Вимикати функції на клавіатурі"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Запобігає використанню деяких функцій на клавіатурі."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Дом."</item>
     <item msgid="869923650527136615">"Мобільний"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Повторіть спробу"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Перевищено максимальну кількість спроб розблокування за допомогою функції \"Фейсконтроль\""</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Заряджається, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Заряджено."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Заряджено"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Підкл. заряд. пристрій."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Нема SIM-карти."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Відсутня SIM-карта"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"У пристр. нема SIM-карти."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"У тел. немає SIM-карти."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Вставте SIM-карту."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Ключ очищено"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Телефон додано"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Малювання ключа закінчено"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Додати віджет."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Порожня область"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Область розблокування розгорнуто."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Область розблокування згорнуто."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"Віджет <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Вибір користувача"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Статус"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Камера"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Елементи керування носієм"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Змінення порядку віджетів розпочато."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Змінення порядку віджетів закінчено."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Віджет <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> видалено."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Розгорнути область розблокування."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Розблокування повзунком."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Розблокування ключем."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Фейсконтроль"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Розблокування PIN-кодом."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Розблокування паролем."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Область ключа."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Область повзунка."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Копіюв. URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Вибрати текст"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Вибір тексту"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"додати в словник"</string>
-    <string name="deleteText" msgid="7070985395199629156">"видалити"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Додати в словник"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Видалити"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Метод введення"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Дії з текстом"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Закінчується пам’ять"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Відкриті Wi-Fi мережі доступні"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Вхід у мережу Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Вхід у мережу"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не вдалося під’єднатися до мережі Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" має погане з’єднання з Інтернетом."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Кому:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Введіть потрібний PIN-код:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-код:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Під час з’єднання з пристроєм <xliff:g id="DEVICE_NAME">%1$s</xliff:g> телефон тимчасово від’єднається від мережі Wi-Fi"</string>
     <string name="select_character" msgid="3365550120617701745">"Вставл-ня символу"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Надсил. SMS повідомлень"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"Програма &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; надсилає велику кількість SMS-повідомлень. Дозволити цій програмі й надалі надсилати повідомлення?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Дозволити"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Відмовити"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; хоче надіслати повідомлення на таку адресу: &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Це "<font fgcolor="#ffffb060">"може призвести до стягнення плати"</font>" з вашого рахунку в оператора мобільного зв’язку."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Це призведе до стягнення плати з вашого рахунку в оператора мобільного зв’язку."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Надіслати"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Скасувати"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Запам’ятати мій вибір"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Можна змінити згодом у Налаштування &gt; Програми"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Завжди дозволяти"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Ніколи не дозволяти"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-карту вилучено"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Мобільна мережа буде недоступна, поки ви не здійсните перезапуск, вставивши дійсну SIM-карту."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Установити дату"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Застосувати"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Готово"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"За умовч."</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Дозвіл не потрібний"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Сховати"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Показ. всі"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"НОВИЙ: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"НОВИЙ: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Надано <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Дозвіл не потрібний"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"це платна послуга"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB великої ємності"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Підкл. через USB"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Ви під’єдналися до комп’ютера за допомогою USB. Торкніться кнопки нижче, якщо потрібно скопіювати файли з комп’ютера на носій USB вашого пристрою Android або навпаки."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"Мережу VPN активовано програмою <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Торкніться, щоб керувати мережею."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Під’єднано до сеансу <xliff:g id="SESSION">%s</xliff:g>. Торкніться, щоб керувати мережею."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Під’єднання до постійної мережі VPN…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Під’єднано до постійної мережі VPN"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Помилка постійної мережі VPN"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Торкніться, щоб скинути з’єднання"</string>
     <string name="upload_file" msgid="2897957172366730416">"Виберіть файл"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Не вибрано файл"</string>
     <string name="reset" msgid="2448168080964209908">"Віднов."</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Надіслати"</string>
     <string name="find" msgid="4808270900322985960">"Знайти"</string>
     <string name="websearch" msgid="4337157977400211589">"Веб-пошук"</string>
+    <string name="find_next" msgid="5742124618942193978">"Знайти наступне"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Знайти попереднє"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Запит про місцезнаходження від користувача <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Запит про місцезнаходження"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Запит зроблено користувачем <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Телефон"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Навушники"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Динаміки док-станції"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Аудіовихід HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Система"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Аудіо Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Готово"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Вивід медіа-даних"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Сканування..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"З’єднання..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Доступно"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Недоступно"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Вбудований екран"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Екран HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Накладання №<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>х<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Бездротовий екран під’єднано"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Цей екран відображається на іншому пристрої"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Від’єднати"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Екстрений виклик"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Не пам’ятаю ключ"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Неправильний ключ"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Неправильний пароль"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Неправильний PIN-код"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Повторіть спробу через <xliff:g id="NUMBER">%d</xliff:g> с."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Намалюйте ключ"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Введіть PIN-код SIM-карти"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Введіть PIN-код"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Введіть пароль"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"Зараз SIM-карту вимкнено. Введіть PUK-код, щоб продовжити. Зв’яжіться з оператором, щоб дізнатися більше."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Введіть потрібний PIN-код"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Підтвердьте потрібний PIN-код"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Розблокування SIM-карти…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Неправильний PIN-код."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Введіть PIN-код із 4–8 цифр."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK-код має складатися зі щонайменше 8 цифр."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Повторно введіть правильний PUK-код. Численні спроби назавжди вимкнуть SIM-карту."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN-коди не збігаються"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Забагато спроб намалювати ключ"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Щоб розблокувати, увійдіть, використовуючи дані облікового запису Google."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Ім’я користувача (електронна адреса)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Пароль"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Увійти"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Недійсне ім’я користувача чи пароль."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Не пам’ятаєте ім’я користувача чи пароль?"\n"Відвідайте сторінку "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Перевірка облікового запису…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"PIN-код неправильно введено стільки разів: <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n"Повторіть спробу через <xliff:g id="NUMBER_1">%d</xliff:g> с."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Пароль неправильно введено стільки разів: <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n"Повторіть спробу через <xliff:g id="NUMBER_1">%d</xliff:g> с."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n"Повторіть спробу через <xliff:g id="NUMBER_1">%d</xliff:g> с."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Кількість невдалих спроб розблокувати планшетний ПК: <xliff:g id="NUMBER_0">%d</xliff:g>. У вас є ще стільки спроб: <xliff:g id="NUMBER_1">%d</xliff:g>. У разі невдачі налаштування планшетного ПК буде змінено на заводські за умовчанням, а всі дані користувача – втрачено."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Кількість невдалих спроб розблокувати телефон: <xliff:g id="NUMBER_0">%d</xliff:g>. У вас є ще стільки спроб: <xliff:g id="NUMBER_1">%d</xliff:g>. У разі невдачі налаштування телефону буде змінено на заводські за умовчанням, а всі дані користувача – втрачено."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Кількість невдалих спроб розблокувати планшетний ПК: <xliff:g id="NUMBER">%d</xliff:g>. Налаштування планшетного ПК буде змінено на заводські за умовчанням."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Кількість невдалих спроб розблокувати телефон: <xliff:g id="NUMBER">%d</xliff:g>. Налаштування телефону буде змінено на заводські за умовчанням."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%d</xliff:g>. У вас є ще стільки спроб: <xliff:g id="NUMBER_1">%d</xliff:g>. У разі невдачі з’явиться запит розблокувати планшетний ПК за допомогою облікового запису електронної пошти."\n\n" Повторіть спробу через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%d</xliff:g>. У вас є ще стільки спроб: <xliff:g id="NUMBER_1">%d</xliff:g>. У разі невдачі з’явиться запит розблокувати телефон за допомогою облікового запису електронної пошти."\n\n" Повторіть спробу через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Вилучити"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Збільшити гучність понад безпечний рівень?"\n"Надто гучне прослуховування впродовж тривалого періоду може пошкодити слух."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Утримуйте двома пальцями, щоб увімкнути доступність."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Доступність увімкнено."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Доступність скасовано."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Поточний користувач: <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Власник"</string>
 </resources>
diff --git a/core/res/res/values-vi-rVN/donottranslate-cldr.xml b/core/res/res/values-vi-rVN/donottranslate-cldr.xml
index 5d049a1..a385015 100644
--- a/core/res/res/values-vi-rVN/donottranslate-cldr.xml
+++ b/core/res/res/values-vi-rVN/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">tháng một</string>
-    <string name="month_long_standalone_february">tháng hai</string>
-    <string name="month_long_standalone_march">tháng ba</string>
-    <string name="month_long_standalone_april">tháng tư</string>
-    <string name="month_long_standalone_may">tháng năm</string>
-    <string name="month_long_standalone_june">tháng sáu</string>
-    <string name="month_long_standalone_july">tháng bảy</string>
-    <string name="month_long_standalone_august">tháng tám</string>
-    <string name="month_long_standalone_september">tháng chín</string>
-    <string name="month_long_standalone_october">tháng mười</string>
-    <string name="month_long_standalone_november">tháng mười một</string>
-    <string name="month_long_standalone_december">tháng mười hai</string>
-
-    <string name="month_long_january">tháng một</string>
-    <string name="month_long_february">tháng hai</string>
-    <string name="month_long_march">tháng ba</string>
-    <string name="month_long_april">tháng tư</string>
-    <string name="month_long_may">tháng năm</string>
-    <string name="month_long_june">tháng sáu</string>
-    <string name="month_long_july">tháng bảy</string>
-    <string name="month_long_august">tháng tám</string>
-    <string name="month_long_september">tháng chín</string>
-    <string name="month_long_october">tháng mười</string>
-    <string name="month_long_november">tháng mười một</string>
-    <string name="month_long_december">tháng mười hai</string>
-
-    <string name="month_medium_january">thg 1</string>
-    <string name="month_medium_february">thg 2</string>
-    <string name="month_medium_march">thg 3</string>
-    <string name="month_medium_april">thg 4</string>
-    <string name="month_medium_may">thg 5</string>
-    <string name="month_medium_june">thg 6</string>
-    <string name="month_medium_july">thg 7</string>
-    <string name="month_medium_august">thg 8</string>
-    <string name="month_medium_september">thg 9</string>
-    <string name="month_medium_october">thg 10</string>
-    <string name="month_medium_november">thg 11</string>
-    <string name="month_medium_december">thg 12</string>
-
-    <string name="month_shortest_january">1</string>
-    <string name="month_shortest_february">2</string>
-    <string name="month_shortest_march">3</string>
-    <string name="month_shortest_april">4</string>
-    <string name="month_shortest_may">5</string>
-    <string name="month_shortest_june">6</string>
-    <string name="month_shortest_july">7</string>
-    <string name="month_shortest_august">8</string>
-    <string name="month_shortest_september">9</string>
-    <string name="month_shortest_october">10</string>
-    <string name="month_shortest_november">11</string>
-    <string name="month_shortest_december">12</string>
-
-    <string name="day_of_week_long_sunday">Chủ nhật</string>
-    <string name="day_of_week_long_monday">Thứ hai</string>
-    <string name="day_of_week_long_tuesday">Thứ ba</string>
-    <string name="day_of_week_long_wednesday">Thứ tư</string>
-    <string name="day_of_week_long_thursday">Thứ năm</string>
-    <string name="day_of_week_long_friday">Thứ sáu</string>
-    <string name="day_of_week_long_saturday">Thứ bảy</string>
-
-    <string name="day_of_week_medium_sunday">CN</string>
-    <string name="day_of_week_medium_monday">Th 2</string>
-    <string name="day_of_week_medium_tuesday">Th 3</string>
-    <string name="day_of_week_medium_wednesday">Th 4</string>
-    <string name="day_of_week_medium_thursday">Th 5</string>
-    <string name="day_of_week_medium_friday">Th 6</string>
-    <string name="day_of_week_medium_saturday">Th 7</string>
-
-    <string name="day_of_week_short_sunday">CN</string>
-    <string name="day_of_week_short_monday">Th 2</string>
-    <string name="day_of_week_short_tuesday">Th 3</string>
-    <string name="day_of_week_short_wednesday">Th 4</string>
-    <string name="day_of_week_short_thursday">Th 5</string>
-    <string name="day_of_week_short_friday">Th 6</string>
-    <string name="day_of_week_short_saturday">Th 7</string>
-
-    <string name="day_of_week_shortest_sunday">1</string>
-    <string name="day_of_week_shortest_monday">2</string>
-    <string name="day_of_week_shortest_tuesday">3</string>
-    <string name="day_of_week_shortest_wednesday">4</string>
-    <string name="day_of_week_shortest_thursday">5</string>
-    <string name="day_of_week_shortest_friday">6</string>
-    <string name="day_of_week_shortest_saturday">7</string>
-
-    <string name="am">SA</string>
-    <string name="pm">CH</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-vi/donottranslate-cldr.xml b/core/res/res/values-vi/donottranslate-cldr.xml
index 9a757cd..977e021 100644
--- a/core/res/res/values-vi/donottranslate-cldr.xml
+++ b/core/res/res/values-vi/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">tháng một</string>
-    <string name="month_long_standalone_february">tháng hai</string>
-    <string name="month_long_standalone_march">tháng ba</string>
-    <string name="month_long_standalone_april">tháng tư</string>
-    <string name="month_long_standalone_may">tháng năm</string>
-    <string name="month_long_standalone_june">tháng sáu</string>
-    <string name="month_long_standalone_july">tháng bảy</string>
-    <string name="month_long_standalone_august">tháng tám</string>
-    <string name="month_long_standalone_september">tháng chín</string>
-    <string name="month_long_standalone_october">tháng mười</string>
-    <string name="month_long_standalone_november">tháng mười một</string>
-    <string name="month_long_standalone_december">tháng mười hai</string>
-
-    <string name="month_long_january">tháng một</string>
-    <string name="month_long_february">tháng hai</string>
-    <string name="month_long_march">tháng ba</string>
-    <string name="month_long_april">tháng tư</string>
-    <string name="month_long_may">tháng năm</string>
-    <string name="month_long_june">tháng sáu</string>
-    <string name="month_long_july">tháng bảy</string>
-    <string name="month_long_august">tháng tám</string>
-    <string name="month_long_september">tháng chín</string>
-    <string name="month_long_october">tháng mười</string>
-    <string name="month_long_november">tháng mười một</string>
-    <string name="month_long_december">tháng mười hai</string>
-
-    <string name="month_medium_january">thg 1</string>
-    <string name="month_medium_february">thg 2</string>
-    <string name="month_medium_march">thg 3</string>
-    <string name="month_medium_april">thg 4</string>
-    <string name="month_medium_may">thg 5</string>
-    <string name="month_medium_june">thg 6</string>
-    <string name="month_medium_july">thg 7</string>
-    <string name="month_medium_august">thg 8</string>
-    <string name="month_medium_september">thg 9</string>
-    <string name="month_medium_october">thg 10</string>
-    <string name="month_medium_november">thg 11</string>
-    <string name="month_medium_december">thg 12</string>
-
-    <string name="month_shortest_january">1</string>
-    <string name="month_shortest_february">2</string>
-    <string name="month_shortest_march">3</string>
-    <string name="month_shortest_april">4</string>
-    <string name="month_shortest_may">5</string>
-    <string name="month_shortest_june">6</string>
-    <string name="month_shortest_july">7</string>
-    <string name="month_shortest_august">8</string>
-    <string name="month_shortest_september">9</string>
-    <string name="month_shortest_october">10</string>
-    <string name="month_shortest_november">11</string>
-    <string name="month_shortest_december">12</string>
-
-    <string name="day_of_week_long_sunday">Chủ nhật</string>
-    <string name="day_of_week_long_monday">Thứ hai</string>
-    <string name="day_of_week_long_tuesday">Thứ ba</string>
-    <string name="day_of_week_long_wednesday">Thứ tư</string>
-    <string name="day_of_week_long_thursday">Thứ năm</string>
-    <string name="day_of_week_long_friday">Thứ sáu</string>
-    <string name="day_of_week_long_saturday">Thứ bảy</string>
-
-    <string name="day_of_week_medium_sunday">CN</string>
-    <string name="day_of_week_medium_monday">Th 2</string>
-    <string name="day_of_week_medium_tuesday">Th 3</string>
-    <string name="day_of_week_medium_wednesday">Th 4</string>
-    <string name="day_of_week_medium_thursday">Th 5</string>
-    <string name="day_of_week_medium_friday">Th 6</string>
-    <string name="day_of_week_medium_saturday">Th 7</string>
-
-    <string name="day_of_week_short_sunday">CN</string>
-    <string name="day_of_week_short_monday">Th 2</string>
-    <string name="day_of_week_short_tuesday">Th 3</string>
-    <string name="day_of_week_short_wednesday">Th 4</string>
-    <string name="day_of_week_short_thursday">Th 5</string>
-    <string name="day_of_week_short_friday">Th 6</string>
-    <string name="day_of_week_short_saturday">Th 7</string>
-
-    <string name="day_of_week_shortest_sunday">1</string>
-    <string name="day_of_week_shortest_monday">2</string>
-    <string name="day_of_week_shortest_tuesday">3</string>
-    <string name="day_of_week_shortest_wednesday">4</string>
-    <string name="day_of_week_shortest_thursday">5</string>
-    <string name="day_of_week_shortest_friday">6</string>
-    <string name="day_of_week_shortest_saturday">7</string>
-
-    <string name="am">SA</string>
-    <string name="pm">CH</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index d9de025..7fb3412 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Tùy chọn điện thoại"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Khoá màn hình"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Tắt nguồn"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Báo cáo lỗi"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Nhận báo cáo lỗi"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Báo cáo này sẽ thu thập thông tin về tình trạng thiết bị hiện tại của bạn, để gửi dưới dạng thông báo qua email. Sẽ mất một chút thời gian kể từ khi bắt đầu báo cáo lỗi cho tới khi báo cáo sẵn sàng để gửi; xin vui lòng kiên nhẫn."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Chế độ im lặng"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Âm thanh TẮT"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Âm thanh BẬT"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Tin nhắn của bạn"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Đọc và soạn SMS, email và các tin nhắn khác của bạn."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Thông tin cá nhân của bạn"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Quyền truy cập trực tiếp vào danh bạ và lịch của bạn được lưu trữ trên máy tính bảng."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Quyền truy cập trực tiếp vào danh bạ và lịch của bạn được lưu trữ trên điện thoại."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Truy cập trực tiếp vào thông tin về bạn, được lưu trữ trên thẻ liên hệ của bạn."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Thông tin xã hội của bạn"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Truy cập trực tiếp vào thông tin về các địa chỉ liên hệ và các kết nối xã hội của bạn."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Vị trí của bạn"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Giám sát vị trí thực của bạn."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Kết nối mạng"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Truy cập các tính năng mạng khác nhau."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Truy cập vào các thiết bị và mạng thông qua Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Cài đặt âm thanh"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Thay đổi cài đặt âm thanh."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Ảnh hưởng tới pin"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Sử dụng các tính năng có thể làm nhanh hết pin."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Lịch"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Truy cập trực tiếp vào lịch và sự kiện."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Đọc từ điển người dùng"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Đọc các từ trong từ điển người dùng."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Ghi từ điển người dùng"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Thêm từ vào từ điển người dùng."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Dấu trang và lịch sử"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Truy cập trực tiếp vào dấu trang và lịch sử trình duyệt."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Báo thức"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Đặt đồng hồ báo thức."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Thư thoại"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Truy cập trực tiếp vào thư thoại."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"Micrô"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Truy cập trực tiếp vào micrô để ghi âm."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Máy ảnh"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Truy cập trực tiếp vào máy ảnh để chụp ảnh hoặc quay video."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Thông tin về các ứng dụng của bạn"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Khả năng ảnh hưởng tới hoạt động của các ứng dụng khác trên thiết bị của bạn."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Hình nền"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Thay đổi cài đặt hình nền của thiết bị."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Đồng hồ"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Thay đổi giờ hoặc múi giờ của thiết bị."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Thanh trạng thái"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Thay đổi cài đặt thanh trạng thái của thiết bị."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Cài đặt đồng bộ hóa"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Truy cập vào cài đặt đồng bộ hóa."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Tài khoản của bạn"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Truy cập các tài khoản khả dụng."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Kiểm soát phần cứng"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Quyền truy cập và quyền kiểm soát hệ thống cấp thấp hơn."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Công cụ phát triển"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Các tính năng chỉ cần cho nhà phát triển ứng dụng."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Giao diện người dùng của ứng dụng khác"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Ảnh hưởng tới giao diện người dùng của các ứng dụng khác."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Dung lượng"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Truy cập bộ nhớ USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Truy cập thẻ SD."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Cho phép ứng dụng nhận và xử lý tin nhắn WAP. Quyền này bao gồm khả năng giám sát hoặc xóa tin nhắn được gửi cho bạn mà không hiển thị chúng cho bạn."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"truy xuất các ứng dụng đang chạy"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Cho phép ứng dụng truy xuất thông tin về các công việc đã và đang chạy gần đây. Việc này có thể cho phép ứng dụng phát hiện thông tin về những ứng dụng nào đã được sử dụng trên thiết bị."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"tương tác giữa người dùng"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Cho phép ứng dụng thực hiện hành động giữa những người dùng khác trên thiết bị. Ứng dụng độc hại có thể sử dụng quyền này để vi phạm khả năng bảo vệ giữa người dùng."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"cấp phép đầy đủ để tương tác giữa người dùng"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Cho phép tất cả các tương tác giữa người dùng."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"quản lý người dùng"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Cho phép ứng dụng quản lý người dùng trên thiết bị, bao gồm truy vấn, tạo và xóa."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"truy xuất chi tiết về các ứng dụng đang chạy"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Cho phép ứng dụng truy xuất thông tin chi tiết về các tác vụ đã và đang chạy gần đây. Ứng dụng độc hại có thể phát hiện thông tin riêng tư về các ứng dụng khác."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"sắp xếp lại những ứng dụng đang chạy"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Cho phép ứng dụng truy xuất trạng thái nội bộ của hệ thống. Ứng dụng độc hại có thể truy xuất nhiều loại thông tin riêng tư và bảo mật khác nhau mà thông thường chúng không bao giờ cần."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"truy xuất nội dung màn hình"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Cho phép ứng dụng truy xuất nội dung của cửa sổ hiện hành. Ứng dụng độc hại có thể truy xuất toàn bộ nội dung của cửa sổ cũng như xem xét toàn bộ văn bản của cửa sổ ngoại trừ mật khẩu."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"tạm thời bật trợ năng"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Cho phép ứng dụng tạm thời bật trợ năng trên thiết bị. Các ứng dụng độc hại có thể bật trợ năng mà không có sự đồng ý của người dùng."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"truy xuất thông tin cửa sổ"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Cho phép ứng dụng truy xuất thông tin về các cửa sổ từ trình quản lý cửa sổ. Các ứng dụng độc hại có thể truy xuất thông tin được dành để sử dụng trong hệ thống nội bộ."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"lọc sự kiện"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Cho phép ứng dụng đăng ký bộ lọc dữ liệu nhập để lọc luồng tất cả các sự kiện người dùng trước khi chúng được gửi đi. Ứng dụng độc hại có thể kiểm soát Giao diện người dùng hệ thống mà không cần sự can thiệp của người dùng."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"thu phóng màn hình"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Cho phép ứng dụng thu phóng nội dung trên màn hình. Ứng dụng độc hại có thể biến đổi nội dung trên màn hình theo cách kết xuất thiết bị không thể sử dụng được."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"tắt từng phần"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Đặt trình quản lý hoạt động sang trạng thái tắt. Không thực hiện tắt hoàn toàn."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ngăn chuyển đổi ứng dụng"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Cho phép ứng dụng kiểm soát số quy trình tối đa sẽ chạy. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"buộc ứng dụng nền đóng"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Cho phép ứng dụng kiểm soát xem các hoạt động có luôn hoàn tất ngay khi chúng chuyển sang nền sau hay không. Không cần thiết cho các ứng dụng thông thường."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"sửa đổi thống kê về pin"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Cho phép ứng dụng sửa đổi các số liệu thống kê về pin đã được thu thập. Không dành cho các ứng dụng thông thường."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"đọc số liệu thống kê về pin"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Cho phép ứng dụng đọc dữ liệu sử dụng pin mức thấp hiện tại. Có thể cho phép ứng dụng biết thông tin chi tiết về ứng dụng bạn sử dụng."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"sửa đổi số liệu thống kê về pin"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Cho phép ứng dụng sửa đổi các số liệu thống kê về pin đã được thu thập. Không dành cho các ứng dụng thông thường."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kiểm soát sao lưu và khôi phục hệ thống"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Cho phép ứng dụng kiểm soát cơ chế sao lưu và khôi phục của hệ thống. Không dành cho các ứng dụng thông thường."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"xác nhận bản sao lưu đầy đủ hoặc khôi phục hoạt động"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"hiển thị các cửa sổ trái phép"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Cho phép ứng dụng tạo các cửa sổ dùng cho giao diện người dùng hệ thống nội bộ. Không dành cho các ứng dụng thông thường."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"vẽ trên ứng dụng khác"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Cho phép ứng dụng hiển thị các cửa sổ cảnh báo hệ thống. Một số cửa sổ cảnh báo có thể kiểm soát toàn bộ màn hình."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Cho phép ứng dụng vẽ trên đầu các ứng dụng khác hoặc các phần của giao diện người dùng. Chúng có thể ảnh hưởng đến việc bạn sử dụng giao diện trong bất kỳ ứng dụng nào hoặc thay đổi suy nghĩ của bạn về những gì bạn đang thấy trong các ứng dụng khác."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"sửa đổi tốc độ hoạt ảnh chung"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Cho phép ứng dụng thay đổi tốc độ hoạt ảnh nói chung (hoạt ảnh nhanh hơn hoặc chậm hơn) bất cứ lúc nào."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"quản lý mã thông báo của ứng dụng"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Cho phép ứng dụng tạo và quản lý các mã thông báo riêng của mình, chuyển đổi thứ tự Z thông thường. Không cần thiết cho các ứng dụng thông thường."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"đóng băng màn hình"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Cho phép ứng dụng tạm thời đóng băng màn hình để chuyển sang chế độ toàn màn hình."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"nhấn phím và kiểm soát các nút"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Cho phép ứng dụng gửi các sự kiện nhập của riêng ứng dụng (số lần nhấn phím, v.v..) đến các ứng dụng khác. Ứng dụng độc hại có thể sử dụng quyền này để kiểm soát máy tính bảng."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Cho phép ứng dụng gửi các sự kiện nhập của riêng ứng dụng (số lần nhấn phím, v.v..) đến các ứng dụng khác. Ứng dụng độc hại có thể sử dụng quyền này để kiểm soát điện thoại."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"trực tiếp cài đặt ứng dụng"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Cho phép ứng dụng cài đặt các gói Android mới hoặc đã được cập nhật. Ứng dụng độc hại có thể sử dụng quyền này để thêm ứng dụng mới có các quyền tùy ý."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"xóa tất cả dữ liệu bộ nhớ cache của ứng dụng"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Cho phép ứng dụng giải phóng dung lượng của máy tính bảng bằng cách xóa các tệp trong thư mục bộ nhớ cache của ứng dụng. Quyền truy cập thường rất hạn chế đối với quy trình hệ thống."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Cho phép ứng dụng giải phóng dung lượng của điện thoại bằng cách xóa các tệp trong thư mục bộ nhớ cache của ứng dụng. Quyền truy cập thường rất hạn chế đối với quy trình hệ thống."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Cho phép ứng dụng giải phóng bộ nhớ máy tính bảng bằng cách xóa các tệp trong thư mục bộ nhớ cache của các ứng dụng khác. Điều này có thể khiến các ứng dụng khác khởi động chậm hơn vì chúng cần truy xuất lại dữ liệu."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Cho phép ứng dụng giải phóng bộ nhớ điện thoại bằng cách xóa các tệp trong thư mục bộ nhớ cache của các ứng dụng khác. Điều này có thể khiến các ứng dụng khác khởi động chậm hơn vì chúng cần truy xuất lại dữ liệu."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"xóa tài nguyên ứng dụng"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Cho phép ứng dụng di chuyển các tài nguyên ứng dụng từ phương tiện nội bộ sang phương tiện bên ngoài và ngược lại."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"đọc dữ liệu nhật ký nhạy cảm"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Cho phép ứng dụng truy cập vào các lệnh của nhà cung cấp vị trí bổ sung. Việc này có thể cho phép ứng dụng can thiệp vào quá trình vận hành của GPS hoặc các nguồn vị trí khác."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"quyền cài đặt nhà cung cấp vị trí"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Tạo nguồn vị trí mô phỏng cho thử nghiệm hoặc cài đặt nhà cung cấp vị trí mới. Việc này cho phép ứng dụng ghi đè vị trí và/hoặc trạng thái được trả về bởi các nguồn vị trí khác như GPS hoặc nhà cung cấp vị trí."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"vị trí (GPS) chính xác"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Truy cập nguồn vị trí chính xác như Hệ thống định vị toàn cầu trên máy tính bảng. Khi các dịch vụ định vị sẵn có và được bật, quyền này cho phép ứng dụng xác định vị trí chính xác của bạn."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Truy cập nguồn vị trí chính xác như Hệ thống định vị toàn cầu trên điện thoại. Khi các dịch vụ định vị sẵn có và được bật, quyền này cho phép ứng dụng xác định vị trí chính xác của bạn."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"vị trí (dựa trên mạng) gần đúng"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Truy cập vị trí gần đúng từ nhà cung cấp vị trí bằng cách sử dụng các tài nguyên mạng như tháp phát sóng và Wi-Fi. Khi các dịch vụ định vị này sẵn có và được bật, quyền này cho phép ứng dụng xác định vị trí gần đúng của bạn."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"vị trí chính xác (dựa vào mạng và GPS)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Cho phép ứng dụng nhận vị trí chính xác của bạn bằng cách sử dụng Hệ thống định vị toàn cầu (GPS) hoặc các nguồn vị trí mạng chẳng hạn như tháp điện thoại di động và Wi-Fi. Các dịch vụ vị trí này phải được bật và có sẵn cho thiết bị của bạn để ứng dụng sử dụng chúng. Ứng dụng có thể sử dụng dịch vụ vị trí này để xác định vị trí của bạn và có thể tiêu hao thêm nguồn pin."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"vị trí gần đúng (dựa vào mạng)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Cho phép ứng dụng nhận vị trí gần đúng của bạn. Vị trí này có được là do dịch vụ vị trí sử dụng các nguồn vị trí mạng chẳng hạn như tháp điện thoại di động và Wi-Fi. Các dịch vụ vị trí này phải được bật và có sẵn cho thiết bị của bạn để ứng dụng sử dụng chúng. Ứng dụng có thể sử dụng dịch vụ vị trí này để xác định vị trí gần đúng của bạn."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"truy cập SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Cho phép ứng dụng sử dụng các tính năng SurfaceFlinger cấp độ thấp."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"đọc bộ đệm khung"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Cho phép ứng dụng đọc nội dung của bộ đệm khung."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"định cấu hình màn hình Wifi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Cho phép ứng dụng định cấu hình và kết nối với màn hình Wifi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"kiểm soát màn hình Wifi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Cho phép ứng dụng kiểm soát các tính năng cấp thấp của màn hình Wifi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"thay đổi cài đặt âm thanh của bạn"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Cho phép ứng dụng sửa đổi cài đặt âm thanh chung chẳng hạn như âm lượng và loa nào được sử dụng cho thiết bị ra."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ghi âm"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"truy cập cài đặt Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Cho phép ứng dụng định cấu hình máy tính bảng Bluetooth cục bộ cũng như phát hiện và ghép nối với các thiết bị từ xa."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Cho phép ứng dụng định cấu hình điện thoại Bluetooth cục bộ cũng như phát hiện và ghép nối với các thiết bị từ xa."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Xem kết nối WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"kết nối và ngắt kết nối khỏi WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Cho phép ứng dụng xác định liệu WiMAX đã được bật chưa và thông tin về bất kỳ mạng WiMAX nào được kết nối."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Thay đổi trạng thái WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Cho phép ứng dụng kết nối máy tính bảng và ngắt kết nối máy tính bảng khỏi mạng WiMAX."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Cho phép ứng dụng sửa đổi nguồn cấp dữ liệu hiện đã được đồng bộ hóa của bạn. Ứng dụng độc hại có thể thay đổi nguồn cấp dữ liệu đã đồng bộ hóa của bạn."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"đọc cụm từ bạn đã thêm vào từ điển"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Cho phép ứng dụng đọc tất cả các từ, tên và cụm từ mà người dùng có thể đã lưu trữ trong từ điển của người dùng."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"ghi vào từ điển do người dùng xác định"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"thêm từ vào từ điển do người dùng xác định"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Cho phép ứng dụng ghi từ mới vào từ điển của người dùng."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"kiểm tra quyền truy cập vào bộ nhớ được bảo vệ"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"kiểm tra quyền truy cập vào bộ nhớ được bảo vệ"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Cho phép ứng dụng kiểm tra quyền cho bộ lưu trữ USB trên các thiết bị trong tương lai."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Cho phép ứng dụng kiểm tra quyền của bộ lưu trữ USB trên các thiết bị trong tương lai."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Cho phép ứng dụng kiểm tra quyền cho thẻ SD sẽ các thiết bị trong tương lai."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"sửa đổi hoặc xóa nội dung của bộ lưu trữ USB của bạn"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"sửa đổi hoặc xóa nội dung của thẻ SD của bạn"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Cho phép ứng dụng ghi vào thẻ SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"sửa đổi/xóa nội dung trên bộ nhớ phương tiện cục bộ"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Cho phép ứng dụng sửa đổi nội dung của bộ lưu trữ phương tiện nội bộ."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"truy cập bộ nhớ ngoài của tất cả người dùng"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Cho phép ứng dụng truy cập bộ nhớ ngoài của tất cả người dùng."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"truy cập hệ thống tệp bộ nhớ cache"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Cho phép ứng dụng đọc và ghi hệ thống tệp bộ nhớ cache."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"thực hiện/nhận cuộc gọi qua Internet"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Yêu cầu dữ liệu ứng dụng được lưu trữ phải được mã hóa."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Vô hiệu hóa máy ảnh"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Ngăn sử dụng tất cả máy ảnh của thiết bị."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Tắt tính năng trong chế độ bảo vệ phím"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Ngăn sử dụng một số tính năng trong chế độ bảo vệ phím."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Nhà riêng"</item>
     <item msgid="869923650527136615">"ĐT di động"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Thử lại"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Đã vượt quá số lần Mở khóa bằng khuôn mặt tối đa"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Đang sạc, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Đã sạc."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Bị tính phí"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Kết nối bộ sạc của bạn."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Không có thẻ SIM nào."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Không có thẻ SIM nào"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Không có thẻ SIM nào trong máy tính bảng."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Không có thẻ SIM nào trong điện thoại."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Hãy lắp thẻ SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Đã xóa hình"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Đã thêm ô"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Đã vẽ xong hình"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Thêm tiện ích."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Trống"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Đã mở rộng vùng khóa."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Đã thu gọn vùng khóa."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> tiện ích."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Bộ chọn người dùng"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Trạng thái"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Máy ảnh"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Điều khiển phương tiện"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Đã bắt đầu xắp xếp lại tiện ích."</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Đã kết thúc sắp xếp lại tiện ích."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Đã xóa tiện ích <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Mở rộng vùng khóa."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Mở khóa bằng cách trượt."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Mở khóa bằng hình."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Mở khóa bằng khuôn mặt."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Mở khóa bằng mã pin."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Mở khóa bằng mật khẩu."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Khu vực hình."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Khu vực trượt."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Sao chép URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Chọn văn bản"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Lựa chọn văn bản"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"thêm vào từ điển"</string>
-    <string name="deleteText" msgid="7070985395199629156">"xóa"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Thêm vào từ điển"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Xóa"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Phương thức nhập"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tác vụ văn bản"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Sắp hết dung lượng lưu trữ"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Mở mạng Wi-Fi khả dụng"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Đăng nhập vào mạng Wi-Fi"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Đăng nhập vào mạng"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Không thể kết nối với Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" có kết nối Internet không tốt."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Người nhận:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Nhập PIN bắt buộc:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Mã PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Điện thoại sẽ tạm thời ngắt kết nối khỏi Wi-Fi trong khi điện thoại được kết nối với <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Chèn ký tự"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Đang gửi tin nhắn SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; đang gửi rất nhiều tin nhắn SMS. Bạn có muốn cho phép ứng dụng này tiếp tục gửi tin nhắn không?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Cho phép"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Từ chối"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; muốn gửi thư đến &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Điều này "<font fgcolor="#ffffb060">"có thể gây ra các khoản phí"</font>" đối với tài khoản di động của bạn."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Điều này sẽ gây ra các khoản phí đối với tài khoản di động của bạn."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Gửi"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Hủy"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Nhớ lựa chọn của tôi"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Bạn có thể thay đổi cài đặt này sau trong Cài đặt &gt; Ứng dụng"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Luôn cho phép"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Không bao giờ cho phép"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Đã xóa thẻ SIM"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Mạng di động sẽ không khả dụng cho đến khi bạn khởi động lại với thẻ SIM hợp lệ được lắp."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Xong"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Đặt ngày"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Đặt"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Xong"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Mặc định"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Không yêu cầu quyền"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Ẩn"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Hiển thị tất cả"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"MỚI: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"MỚI: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Được cung cấp bởi <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Không yêu cầu quyền"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"bạn có thể mất tiền vì điều này"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Bộ nhớ dung lượng lớn USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB đã kết nối"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Bạn đã kết nối với máy tính của mình qua USB. Hãy chạm vào nút bên dưới nếu bạn muốn sao chép các tệp giữa máy tính và bộ lưu trữ USB của Android của bạn."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN được <xliff:g id="APP">%s</xliff:g> kích hoạt"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Chạm để quản lý mạng."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Đã kết nối với <xliff:g id="SESSION">%s</xliff:g>. Chạm để quản lý mạng."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Đang kết nối VPN luôn bật…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Đã kết nối VPN luôn bật"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Lỗi VPN luôn bật"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Chạm để đặt lại kết nối"</string>
     <string name="upload_file" msgid="2897957172366730416">"Chọn tệp"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Không có tệp nào được chọn"</string>
     <string name="reset" msgid="2448168080964209908">"Đặt lại"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Chia sẻ"</string>
     <string name="find" msgid="4808270900322985960">"Tìm"</string>
     <string name="websearch" msgid="4337157977400211589">"Tìm kiếm trên web"</string>
+    <string name="find_next" msgid="5742124618942193978">"Tìm kết quả phù hợp tiếp theo"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Tìm kết quả phù hợp trước"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Yêu cầu vị trí từ <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Yêu cầu vị trí"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Được yêu cầu bởi <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Điện thoại"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Tai nghe"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Loa đế"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Âm thanh HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Hệ thống"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Âm thanh Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Xong"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Đầu ra phương tiện"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Đang quét..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Đang kết nối..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Khả dụng"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Không khả dụng"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Màn hình tích hợp"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Màn hình HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Lớp phủ #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Hiển thị không dây đã được kết nối"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Màn hình này đang hiển thị trên thiết bị khác"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Ngắt kết nối"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Cuộc gọi khẩn cấp"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Đã quên hình"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Hình sai"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Mật khẩu sai"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN sai"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Hãy thử lại sau <xliff:g id="NUMBER">%d</xliff:g> giây."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Vẽ hình của bạn"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Nhập PIN của SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Nhập PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Nhập mật khẩu"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM hiện bị vô hiệu hóa. Nhập mã PUK để tiếp tục. Liên hệ với nhà cung cấp dịch vụ để biết chi tiết."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Nhập mã PIN mong muốn"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Xác nhận mã PIN mong muốn"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Đang mở khóa thẻ SIM…"</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Mã PIN không chính xác."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Nhập mã PIN có từ 4 đến 8 số."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Mã PUK phải có từ 8 số trở lên."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Hãy nhập lại mã PUK chính xác. Nhiều lần lặp lại sẽ vô hiệu hóa vĩnh viễn thẻ SIM."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Mã PIN không khớp"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Quá nhiều lần nhập hình"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Để mở khóa, hãy đăng nhập bằng tài khoản Google của bạn."</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Tên người dùng (email)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Mật khẩu"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Đăng nhập"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Tên người dùng hoặc mật khẩu không hợp lệ."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Bạn quên tên người dùng hoặc mật khẩu?"\n"Hãy truy cập "<b>"google.com/accounts/recovery"</b>"."</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Đang kiểm tra tài khoản…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Bạn đã <xliff:g id="NUMBER_0">%d</xliff:g> lần nhập sai mã PIN của mình. Hãy "\n\n"thử lại sau <xliff:g id="NUMBER_1">%d</xliff:g> giây."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Bạn đã <xliff:g id="NUMBER_0">%d</xliff:g> lần nhập sai mật khẩu của mình. Hãy "\n\n"thử lại sau <xliff:g id="NUMBER_1">%d</xliff:g> giây."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Bạn đã <xliff:g id="NUMBER_0">%d</xliff:g> lần vẽ không chính xác hình mở khóa của mình. Hãy "\n\n"thử lại sau <xliff:g id="NUMBER_1">%d</xliff:g> giây."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Bạn đã <xliff:g id="NUMBER_0">%d</xliff:g> lần mở khóa máy tính bảng không đúng cách. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần mở khóa không thành công nữa, máy tính bảng sẽ được đặt lại về mặc định ban đầu và tất cả dữ liệu người dùng sẽ bị mất."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Bạn đã <xliff:g id="NUMBER_0">%d</xliff:g> lần mở khóa điện thoại không đúng cách. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần mở khóa không thành công nữa, điện thoại sẽ được đặt lại về mặc định ban đầu và tất cả dữ liệu người dùng sẽ bị mất."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Bạn đã <xliff:g id="NUMBER">%d</xliff:g> lần mở khóa máy tính bảng không đúng cách. Bây giờ, máy tính bảng sẽ được đặt lại về mặc định ban đầu."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Bạn đã <xliff:g id="NUMBER">%d</xliff:g> lần mở khóa điện thoại không đúng cách. Bây giờ, điện thoại sẽ được đặt lại về mặc định ban đầu."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Bạn đã <xliff:g id="NUMBER_0">%d</xliff:g> lần vẽ không chính xác hình mở khóa của mình. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa máy tính bảng bằng tài khoản email."\n\n" Vui lòng thử lại sau <xliff:g id="NUMBER_2">%d</xliff:g> giây."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Bạn đã <xliff:g id="NUMBER_0">%d</xliff:g> lần vẽ không chính xác hình mở khóa của mình. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa điện thoại bằng tài khoản email."\n\n" Vui lòng thử lại sau <xliff:g id="NUMBER_2">%d</xliff:g> giây."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Xóa"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Tăng âm lượng trên mức an toàn?"\n"Nghe ở âm lượng cao trong thời gian dài có thể gây hại cho thính giác của bạn."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Tiếp tục giữ hai ngón tay để bật trợ năng."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Trợ năng đã được bật."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Đã hủy trợ năng."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Người dùng hiện tại <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Chủ sở hữu"</string>
 </resources>
diff --git a/core/res/res/values-w720dp/bools.xml b/core/res/res/values-w720dp/bools.xml
index c87f689..352c319 100644
--- a/core/res/res/values-w720dp/bools.xml
+++ b/core/res/res/values-w720dp/bools.xml
@@ -16,5 +16,4 @@
 
 <resources>
     <bool name="action_bar_expanded_action_views_exclusive">false</bool>
-    <bool name="show_ongoing_ime_switcher">false</bool>
 </resources>
diff --git a/core/res/res/values-zh-rCN/donottranslate-cldr.xml b/core/res/res/values-zh-rCN/donottranslate-cldr.xml
index 9e6ef1c..b34b8b3 100644
--- a/core/res/res/values-zh-rCN/donottranslate-cldr.xml
+++ b/core/res/res/values-zh-rCN/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">1 月</string>
-    <string name="month_long_standalone_february">2 月</string>
-    <string name="month_long_standalone_march">3 月</string>
-    <string name="month_long_standalone_april">4 月</string>
-    <string name="month_long_standalone_may">5 月</string>
-    <string name="month_long_standalone_june">6 月</string>
-    <string name="month_long_standalone_july">7 月</string>
-    <string name="month_long_standalone_august">8 月</string>
-    <string name="month_long_standalone_september">9 月</string>
-    <string name="month_long_standalone_october">10 月</string>
-    <string name="month_long_standalone_november">11 月</string>
-    <string name="month_long_standalone_december">12 月</string>
-
-    <string name="month_long_january">1 月</string>
-    <string name="month_long_february">2 月</string>
-    <string name="month_long_march">3 月</string>
-    <string name="month_long_april">4 月</string>
-    <string name="month_long_may">5 月</string>
-    <string name="month_long_june">6 月</string>
-    <string name="month_long_july">7 月</string>
-    <string name="month_long_august">8 月</string>
-    <string name="month_long_september">9 月</string>
-    <string name="month_long_october">10 月</string>
-    <string name="month_long_november">11 月</string>
-    <string name="month_long_december">12 月</string>
-
-    <string name="month_medium_january">1 月</string>
-    <string name="month_medium_february">2 月</string>
-    <string name="month_medium_march">3 月</string>
-    <string name="month_medium_april">4 月</string>
-    <string name="month_medium_may">5 月</string>
-    <string name="month_medium_june">6 月</string>
-    <string name="month_medium_july">7 月</string>
-    <string name="month_medium_august">8 月</string>
-    <string name="month_medium_september">9 月</string>
-    <string name="month_medium_october">10 月</string>
-    <string name="month_medium_november">11 月</string>
-    <string name="month_medium_december">12 月</string>
-
-    <string name="month_shortest_january">1 月</string>
-    <string name="month_shortest_february">2 月</string>
-    <string name="month_shortest_march">3 月</string>
-    <string name="month_shortest_april">4 月</string>
-    <string name="month_shortest_may">5 月</string>
-    <string name="month_shortest_june">6 月</string>
-    <string name="month_shortest_july">7 月</string>
-    <string name="month_shortest_august">8 月</string>
-    <string name="month_shortest_september">9 月</string>
-    <string name="month_shortest_october">10 月</string>
-    <string name="month_shortest_november">11 月</string>
-    <string name="month_shortest_december">12 月</string>
-
-    <string name="day_of_week_long_sunday">星期日</string>
-    <string name="day_of_week_long_monday">星期一</string>
-    <string name="day_of_week_long_tuesday">星期二</string>
-    <string name="day_of_week_long_wednesday">星期三</string>
-    <string name="day_of_week_long_thursday">星期四</string>
-    <string name="day_of_week_long_friday">星期五</string>
-    <string name="day_of_week_long_saturday">星期六</string>
-
-    <string name="day_of_week_medium_sunday">周日</string>
-    <string name="day_of_week_medium_monday">周一</string>
-    <string name="day_of_week_medium_tuesday">周二</string>
-    <string name="day_of_week_medium_wednesday">周三</string>
-    <string name="day_of_week_medium_thursday">周四</string>
-    <string name="day_of_week_medium_friday">周五</string>
-    <string name="day_of_week_medium_saturday">周六</string>
-
-    <string name="day_of_week_short_sunday">周日</string>
-    <string name="day_of_week_short_monday">周一</string>
-    <string name="day_of_week_short_tuesday">周二</string>
-    <string name="day_of_week_short_wednesday">周三</string>
-    <string name="day_of_week_short_thursday">周四</string>
-    <string name="day_of_week_short_friday">周五</string>
-    <string name="day_of_week_short_saturday">周六</string>
-
-    <string name="day_of_week_shortest_sunday">日</string>
-    <string name="day_of_week_shortest_monday">一</string>
-    <string name="day_of_week_shortest_tuesday">二</string>
-    <string name="day_of_week_shortest_wednesday">三</string>
-    <string name="day_of_week_shortest_thursday">四</string>
-    <string name="day_of_week_shortest_friday">五</string>
-    <string name="day_of_week_shortest_saturday">六</string>
-
-    <string name="am">上午</string>
-    <string name="pm">下午</string>
-    <string name="yesterday">昨天</string>
-    <string name="today">今天</string>
-    <string name="tomorrow">明天</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%p %-l:%M</string>
     <string name="hour_minute_cap_ampm">%p %-l:%M</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index f2f9fde..251389b 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -144,7 +144,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"振铃器开启"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"正在关机..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"您的平板电脑会关闭。"</string>
-    <string name="shutdown_confirm" product="default" msgid="649792175242821353">"您的手机会关机。"</string>
+    <string name="shutdown_confirm" product="default" msgid="649792175242821353">"您的手机将会关机。"</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"您要关机吗?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"重新启动并进入安全模式"</string>
     <string name="reboot_safemode_confirm" msgid="55293944502784668">"您要重新启动并进入安全模式吗?这样会停用您已安装的所有第三方应用。再次重新启动将恢复这些应用。"</string>
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"手机选项"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"屏幕锁定"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"关机"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"错误报告"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"提交错误报告"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"这会收集有关当前设备状态的信息,并以电子邮件的形式进行发送。从开始生成错误报告到准备好发送需要一点时间,请耐心等待。"</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"静音模式"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"声音已关闭"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"声音已开启"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"您的信息"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"读写短信、电子邮件和其他消息。"</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"您的个人信息"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"直接访问平板电脑上存储的联系人和日历。"</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"直接访问手机上存储的联系人和日历。"</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"直接访问您存储在名片上的信息。"</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"您的社交信息"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"直接访问与您的联系人和社交人脉相关的信息。"</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"您的位置"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"监视您的实际位置。"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"网络通信"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"使用各种网络功能。"</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"蓝牙"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"通过蓝牙访问设备和网络。"</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"音频设置"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"更改音频设置。"</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"影响电池的使用"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"使用耗电量较大的功能。"</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"日历"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"直接访问日历和活动。"</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"读取用户词典"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"读取用户词典中的字词。"</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"写入用户词典"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"将字词添加到用户词典。"</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"书签和历史记录"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"直接访问书签和浏览器历史记录。"</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"闹钟"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"设置闹钟。"</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"语音信箱"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"直接访问语音信箱。"</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"麦克风"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"直接使用麦克风以录制音频。"</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"相机"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"直接使用相机以拍摄图片或视频。"</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"您的应用信息"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"能够影响设备上其他应用的行为。"</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"壁纸"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"更改设备的壁纸设置。"</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"时钟"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"更改设备的时间或时区。"</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"状态栏"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"更改设备的状态栏设置。"</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"同步设置"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"访问同步设置。"</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"您的帐户"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"访问可用的帐户。"</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"硬件控制"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"对系统进行低级访问和控制。"</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"开发工具"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"只有应用开发者才需要的功能。"</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"其他应用的用户界面"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"影响其他应用的用户界面。"</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>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"允许该应用接收和处理 WAP 消息。此权限包括监视发送给您的消息或删除发送给您的消息而不向您显示的功能。"</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"检索正在运行的应用"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"允许该应用检索近期运行的和当前正在运行的任务的相关信息。此权限可让该应用了解设备上使用了哪些应用。"</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"用户间互动"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"允许该应用在设备上跨多个用户执行操作。恶意应用可能会借此破坏用户之间的保护措施。"</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"完全允许在用户之间进行互动"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"允许在用户之间进行所有可能的互动。"</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"管理用户"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"允许应用管理设备上的用户(包括查询、创建和删除用户)。"</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"检索正在运行的应用的详细信息"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"允许该应用检索当前正在运行和近期运行的任务的详细信息。恶意应用可能会发现有关其他应用的私密信息。"</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"对正在运行的应用重新排序"</string>
@@ -243,6 +287,14 @@
     <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="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"暂时启用辅助功能"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"允许应用在设备上暂时启用辅助功能。恶意应用可能会在未经用户同意的情况下擅自启用辅助功能。"</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"检索窗口信息"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"允许应用通过窗口管理器检索窗口信息。恶意应用可能会检索供内部系统使用的信息。"</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"过滤事件"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"允许应用注册输入过滤器,这类过滤器会在所有用户事件分派之前对用户事件流进行过滤。恶意应用可能会在没有用户干预的情况下控制系统用户界面。"</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"放大显示内容"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"允许应用放大显示内容。恶意应用可能会以特定方式改变显示内容,使得设备无法使用。"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"部分关机"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"使活动管理器进入关闭状态。不执行彻底关机。"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"禁止切换应用"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"允许应用控制将运行的进程数上限。普通应用绝不需要此权限。"</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"强制关闭后台应用"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"允许应用控制活动在转入后台后是否立即结束。普通应用绝不需要此权限。"</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"修改电池统计信息"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"允许应用修改收集到的电池统计信息。普通应用不能使用此权限。"</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"读取电池使用统计信息"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"允许应用读取当前电量使用情况的基础数据,此权限可让应用了解关于您使用了哪些应用的详细信息。"</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"修改电池使用统计信息"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"允许该应用修改收集到的电池统计信息。普通应用不应使用此权限。"</string>
     <string name="permlab_backup" msgid="470013022865453920">"控制系统备份和还原"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"允许应用控制系统的备份和还原机制。普通应用不能使用此权限。"</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"确认完整备份或恢复操作"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"显示未授权的窗口"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"允许该应用创建供内部系统用户界面使用的窗口。普通应用不应使用此权限。"</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"在其他应用之上显示内容"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"允许该应用显示系统提醒窗口。某些提醒窗口可能会占据整个屏幕。"</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"允许该应用在其他应用之上或用户界面的特定部分绘图。这可能会干扰您对所有应用界面的使用,或使您在其他应用中看到的内容发生变化。"</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="permlab_freezeScreen" msgid="4708181184441880175">"冻结屏幕"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"允许应用暂时冻结屏幕进行全屏转换。"</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>
@@ -288,8 +344,8 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"允许用户绑定到 VPN 服务的顶级接口。普通应用绝不需要此权限。"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"绑定到壁纸"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"允许用户绑定到壁纸的顶级接口。普通应用绝不需要此权限。"</string>
-    <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"绑定到窗口小部件服务"</string>
-    <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允许用户绑定到窗口小部件服务的顶级接口。普通应用绝不需要此权限。"</string>
+    <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"绑定到小部件服务"</string>
+    <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允许应用绑定到小部件服务的顶级接口。普通应用绝不需要此权限。"</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"与设备管理器交互"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"允许用户将意向发送给设备管理员。普通应用绝不需要此权限。"</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"更改屏幕显示方向"</string>
@@ -314,8 +370,8 @@
     <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="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"允许该应用删除其他应用的缓存目录中的文件,从而释放平板电脑存储空间。此权限可能会导致其他应用的启动速度变慢,因为应用必须重新检索数据。"</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"允许该应用删除其他应用的缓存目录中的文件,从而释放手机存储空间。此权限可能会导致其他应用的启动速度变慢,因为应用必须重新检索数据。"</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"移动应用资源"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"允许应用在内部与外部媒体之间移动应用资源。"</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"查阅敏感日志数据"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"允许该应用访问额外的位置提供程序命令。此权限可让该应用干扰 GPS 或其他位置源的运行。"</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"允许安装位置信息提供程序"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"创建用于测试的模拟位置源或安装新的位置提供程序。此权限可让该应用覆盖由其他位置源(如 GPS)或位置提供程序返回的位置和/或状态信息。"</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"确切 (GPS) 位置"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"访问平板电脑上的 GPS 等确切位置源。当位置服务可用且处于启用状态时,此权限可让该应用确定您的确切位置。"</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"访问手机上的 GPS 等确切位置源。当位置服务可用且处于启用状态时,此权限可让该应用确定您的确切位置。"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"(基于网络的)大概位置"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"访问位置提供程序根据基站和 Wi-Fi 等网络源确定的大概位置。当这些位置服务可用且处于启用状态时,此权限可让该应用确定您的大概位置。"</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"精确位置(基于 GPS 和网络)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"允许该应用通过全球定位系统 (GPS) 或网络位置信息源(例如基站和 Wi-Fi)获取您的精确位置信息。您必须在设备上开启这些位置服务,应用才能获得位置信息。应用会使用此类服务确定您的位置,这可能会消耗更多电量。"</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"大致位置(基于网络)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"允许该应用获取您的大致位置信息。这类位置信息来自于使用网络位置信息源(例如基站和 Wi-Fi)的位置服务。您必须在设备上开启这些位置服务,应用才能获得位置信息。应用会使用此类服务确定您的大概位置。"</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"访问 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="permlab_configureWifiDisplay" msgid="5595661694746742168">"配置 Wi-Fi 显示设备"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"允许应用配置并连接到 Wi-Fi 显示设备。"</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"控制 Wi-Fi 显示设备"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"允许应用控制 Wi-Fi 显示设备的基础功能。"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"更改您的音频设置"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"允许该应用修改全局音频设置,例如音量和用于输出的扬声器。"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"录音"</string>
@@ -436,8 +495,8 @@
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"允许应用启用/停用来自无线装置的位置更新通知。普通应用不能使用此权限。"</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"访问检入属性"</string>
     <string name="permdesc_checkinProperties" msgid="4024526968630194128">"允许应用对登记服务上传的属性拥有读取/写入权限。普通应用不能使用此权限。"</string>
-    <string name="permlab_bindGadget" msgid="776905339015863471">"选择窗口小部件"</string>
-    <string name="permdesc_bindGadget" msgid="8261326938599049290">"允许应用告知系统哪些窗口小部件可供哪个应用使用。拥有此权限的应用可向其他应用授予对个人资料的访问权限。普通应用不能使用此权限。"</string>
+    <string name="permlab_bindGadget" msgid="776905339015863471">"选择小部件"</string>
+    <string name="permdesc_bindGadget" msgid="8261326938599049290">"允许应用告知系统哪些小部件可供哪个应用使用。拥有此权限的应用可向其他应用授予对个人资料的访问权限。普通应用不应使用此权限。"</string>
     <string name="permlab_modifyPhoneState" msgid="8423923777659292228">"修改手机状态"</string>
     <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"允许应用控制设备的电话功能。拥有此权限的应用可在不通知您的情况下执行切换网络、开关手机无线装置等此类操作。"</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"读取手机状态和身份"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"访问蓝牙设置"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"允许应用配置本地蓝牙平板电脑,以及发现远程设备并进行配对。"</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"允许应用配置本地蓝牙手机,以及发现远程设备并进行配对。"</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"查看 WiMAX 连接"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"建立或中断 WiMAX 网络连接"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"允许该应用确定是否启用了 WiMAX 以及连接的任何 WiMAX 网络的相关信息。"</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"更改 WiMAX 状态"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"允许该应用建立和断开平板电脑与 WiMAX 网络之间的连接。"</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"允许应用修改您当前同步的 Feed。恶意应用可能会更改您的同步 Feed。"</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"读取您添加到词典的字词"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"允许该应用读取用户可能已在用户词典中存储的所有字词、名称和词组。"</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"写入用户定义的词典"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"向用户定义的词典添加字词"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"允许应用向用户词典中写入新词。"</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"测试对受保护存储空间的访问权限"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"测试对受保护存储空间的访问权限"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"允许该应用测试将对以后的设备开放的 USB 存储设备权限。"</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"允许应用测试以后的设备将支持的 USB 存储设备权限。"</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"允许该应用测试将对以后的设备开放的 SD 卡权限。"</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"修改或删除您的 USB 存储设备中的内容"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"修改或删除您的 SD 卡中的内容"</string>
@@ -534,6 +593,8 @@
     <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="permlab_sdcardAccessAll" msgid="8150613823900460576">"访问所有用户的外部存储设备"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"允许应用访问所有用户的外部存储设备。"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"访问缓存文件系统"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"允许应用读取和写入缓存文件系统。"</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"拨打/接听互联网通话"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"要求对存储的应用数据进行加密。"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"停用相机"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"禁止使用所有设备摄像头。"</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"锁屏时禁用某些功能"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"锁屏时禁止使用某些功能。"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"住宅"</item>
     <item msgid="869923650527136615">"手机"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"重试"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"已超过“人脸解锁”尝试次数上限"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"正在充电,<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"已充满。"</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"充电完成"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"连接您的充电器。"</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"没有 SIM 卡"</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"没有 SIM 卡"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"平板电脑中没有 SIM 卡。"</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"手机中无 SIM 卡"</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"请插入 SIM 卡"</string>
@@ -714,7 +777,7 @@
     <string name="lockscreen_transport_pause_description" msgid="7659088786780128001">"“暂停”按钮"</string>
     <string name="lockscreen_transport_play_description" msgid="5888422938351019426">"“播放”按钮"</string>
     <string name="lockscreen_transport_stop_description" msgid="4562318378766987601">"“停止”按钮"</string>
-    <string name="emergency_calls_only" msgid="6733978304386365407">"只能使用紧急呼救"</string>
+    <string name="emergency_calls_only" msgid="6733978304386365407">"只能拨打紧急呼救电话"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"网络已锁定"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM 卡已用 PUK 码锁定"</string>
     <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"请参阅《用户指南》或与客服人员联系。"</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"图案已清除"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"已添加单元格"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"图案绘制完成"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"添加小部件。"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"空白"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"已展开解锁区域。"</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"已折叠解锁区域。"</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>小部件。"</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"用户选择器"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"状态"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"相机"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"媒体控制"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"已开始将小部件重新排序。"</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"已完成小部件重新排序。"</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"已删除小部件<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>。"</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"展开解锁区域。"</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"滑动解锁。"</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"图案解锁。"</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"人脸解锁。"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN 解锁。"</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"密码解锁。"</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"图案区域。"</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"滑动区域。"</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"复制网址"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"选择文字"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"文字选择"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"添加到词典"</string>
-    <string name="deleteText" msgid="7070985395199629156">"删除"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"添加到词典"</string>
+    <string name="deleteText" msgid="6979668428458199034">"删除"</string>
     <string name="inputMethod" msgid="1653630062304567879">"输入法"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"文字操作"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"存储空间不足"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"打开可用的 Wi-Fi 网络"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"登录到 Wi-Fi 网络"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"登录网络"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"无法连接到 Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" 互联网连接状况不佳。"</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"收件人:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"键入所需的 PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"手机连接到<xliff:g id="DEVICE_NAME">%1$s</xliff:g>时会暂时断开与 Wi-Fi 的连接。"</string>
     <string name="select_character" msgid="3365550120617701745">"插入字符"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"正在发送短信"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;在发送大量短信。是否允许该应用继续发送短信?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"允许"</string>
     <string name="sms_control_no" msgid="625438561395534982">"拒绝"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;想要向 &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; 发送一条短信。"</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457"><font fgcolor="#ffffb060">"这可能会导致您的手机号产生费用。"</font></string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"这会导致您的手机号产生费用。"</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"发送"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"取消"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"记住我的选择"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"之后,您可以在“设置”&gt;“应用”中更改此设置"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"始终允许"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"永不允许"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"已移除 SIM 卡"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"移动网络不可用。请插入有效的 SIM 卡并重新启动。"</string>
     <string name="sim_done_button" msgid="827949989369963775">"完成"</string>
@@ -1043,20 +1137,18 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"设置日期"</string>
     <string name="date_time_set" msgid="5777075614321087758">"设置"</string>
     <string name="date_time_done" msgid="2507683751759308828">"完成"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"默认"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"不需要任何权限"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"隐藏"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"全部显示"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"新增:"</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"新增:"</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"由“<xliff:g id="APP_NAME">%1$s</xliff:g>”提供。"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"不需要任何权限"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"这可能会产生费用"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB 大容量存储设备"</string>
-    <string name="usb_storage_title" msgid="5901459041398751495">"USB 已连接"</string>
+    <string name="usb_storage_title" msgid="5901459041398751495">"已连接 USB"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"您已通过 USB 连接至计算机。如果您要在计算机与 Android 设备的 USB 存储设备之间复制文件,请触摸下面的按钮。"</string>
     <string name="usb_storage_message" product="default" msgid="805351000446037811">"您已通过 USB 连接至计算机。如果您要在计算机和 Android 设备的 SD 卡之间复制文件,请触摸下面的按钮。"</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"打开 USB 存储设备"</string>
     <string name="usb_storage_error_message" product="nosdcard" msgid="3017045217365540658">"使用 USB 存储设备作为 USB 大容量存储设备时出现问题。"</string>
     <string name="usb_storage_error_message" product="default" msgid="2876018512716970313">"使用 SD 卡作为 USB 大容量存储设备时出现问题。"</string>
-    <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB 已连接"</string>
+    <string name="usb_storage_notification_title" msgid="8175892554757216525">"已连接 USB"</string>
     <string name="usb_storage_notification_message" msgid="939822783828183763">"触摸可将文件复制到计算机或从计算机复制到存储设备。"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"关闭 USB 存储设备"</string>
     <string name="usb_storage_stop_notification_message" msgid="1656852098555623822">"触摸可关闭 USB 存储设备。"</string>
@@ -1121,7 +1213,7 @@
     <string name="permlab_route_media_output" msgid="1642024455750414694">"更改媒体输出线路"</string>
     <string name="permdesc_route_media_output" msgid="4932818749547244346">"允许该应用将媒体输出线路更改到其他外部设备。"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"触摸两次可进行缩放控制"</string>
-    <string name="gadget_host_error_inflating" msgid="4882004314906466162">"无法添加窗口小部件。"</string>
+    <string name="gadget_host_error_inflating" msgid="4882004314906466162">"无法添加小部件。"</string>
     <string name="ime_action_go" msgid="8320845651737369027">"开始"</string>
     <string name="ime_action_search" msgid="658110271822807811">"搜索"</string>
     <string name="ime_action_send" msgid="2316166556349314424">"发送"</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"“<xliff:g id="APP">%s</xliff:g>”已激活 VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"触摸可管理网络。"</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"已连接到“<xliff:g id="SESSION">%s</xliff:g>”。触摸可管理网络。"</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"正在连接到始终开启的 VPN…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"已连接到始终开启的 VPN"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"始终开启的 VPN 出现错误"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"触摸即可重置连接"</string>
     <string name="upload_file" msgid="2897957172366730416">"选择文件"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"未选定任何文件"</string>
     <string name="reset" msgid="2448168080964209908">"重置"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"分享"</string>
     <string name="find" msgid="4808270900322985960">"查找"</string>
     <string name="websearch" msgid="4337157977400211589">"网页搜索"</string>
+    <string name="find_next" msgid="5742124618942193978">"查找下一个"</string>
+    <string name="find_previous" msgid="2196723669388360506">"查找上一个"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"来自<xliff:g id="NAME">%s</xliff:g>的定位请求"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"定位请求"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"请求人:<xliff:g id="NAME">%1$s</xliff:g>(<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"手机"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"耳机"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"基座扬声器"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI 音频"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"系统"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"蓝牙音频"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"完成"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"媒体输出线路"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"正在扫描..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"正在连接..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"可连接"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"无法连接"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"内置屏幕"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI 屏幕"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"叠加视图 #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>:<xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>,<xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"已连接到无线显示设备"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"此屏幕的内容正显示在另一台设备上"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"断开连接"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"紧急呼救"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"忘记了图案"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"图案错误"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"密码错误"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN 有误"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"请在 <xliff:g id="NUMBER">%d</xliff:g> 秒后重试。"</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"绘制您的图案"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"输入 SIM PIN"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"输入 PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"输入密码"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM 卡已被停用,需要输入 PUK 码才能继续使用。有关详情,请联系您的运营商。"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"请输入所需 PIN 码"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"请确认所需 PIN 码"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"正在解锁 SIM 卡..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"PIN 码有误。"</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"请输入 4 至 8 位数的 PIN。"</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK 码应至少包含 8 位数字。"</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"请重新输入正确的 PUK 码。如果尝试错误次数过多,SIM 卡将永久停用。"</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN 码不匹配"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"图案尝试次数过多"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"要解锁,请登录您的 Google 帐户。"</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"用户名(电子邮件地址)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"密码"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"登录"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"用户名或密码无效。"</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"忘记了用户名或密码?"\n"请访问 "<b>"google.com/accounts/recovery"</b>"。"</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"正在检查帐户…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地输入了 PIN。"\n\n"请在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒后重试。"</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地输入了密码。"\n\n"请在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒后重试。"</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地绘制了解锁图案。"\n\n"请在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒后重试。"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地尝试解锁平板电脑。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,平板电脑就会重置为出厂默认设置,而且所有用户数据都会丢失。"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地尝试解锁手机。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,手机就会重置为出厂默认设置,而且所有用户数据都会丢失。"</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"您已经 <xliff:g id="NUMBER">%d</xliff:g> 次错误地尝试解锁平板电脑。平板电脑现在将重置为出厂默认设置。"</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"您已经 <xliff:g id="NUMBER">%d</xliff:g> 次错误地尝试解锁手机。手机现在将重置为出厂默认设置。"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地绘制了解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐户解锁平板电脑。"\n\n"请在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒后重试。"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地绘制了解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐户解锁手机。"\n\n"请在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒后重试。"</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"删除"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"将音量调高到安全级别以上?"\n"长时间聆听高音量可能会损伤听力。"</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"持续按住双指即可启用辅助功能。"</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"辅助功能已启用。"</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"已取消辅助功能。"</string>
+    <string name="user_switched" msgid="3768006783166984410">"当前用户是<xliff:g id="NAME">%1$s</xliff:g>。"</string>
+    <string name="owner_name" msgid="2716755460376028154">"机主"</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/donottranslate-cldr.xml b/core/res/res/values-zh-rTW/donottranslate-cldr.xml
index 907d82e..869705e 100644
--- a/core/res/res/values-zh-rTW/donottranslate-cldr.xml
+++ b/core/res/res/values-zh-rTW/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">1 月</string>
-    <string name="month_long_standalone_february">2 月</string>
-    <string name="month_long_standalone_march">3 月</string>
-    <string name="month_long_standalone_april">4 月</string>
-    <string name="month_long_standalone_may">5 月</string>
-    <string name="month_long_standalone_june">6 月</string>
-    <string name="month_long_standalone_july">7 月</string>
-    <string name="month_long_standalone_august">8 月</string>
-    <string name="month_long_standalone_september">9 月</string>
-    <string name="month_long_standalone_october">10 月</string>
-    <string name="month_long_standalone_november">11 月</string>
-    <string name="month_long_standalone_december">12 月</string>
-
-    <string name="month_long_january">1 月</string>
-    <string name="month_long_february">2 月</string>
-    <string name="month_long_march">3 月</string>
-    <string name="month_long_april">4 月</string>
-    <string name="month_long_may">5 月</string>
-    <string name="month_long_june">6 月</string>
-    <string name="month_long_july">7 月</string>
-    <string name="month_long_august">8 月</string>
-    <string name="month_long_september">9 月</string>
-    <string name="month_long_october">10 月</string>
-    <string name="month_long_november">11 月</string>
-    <string name="month_long_december">12 月</string>
-
-    <string name="month_medium_january">1 月</string>
-    <string name="month_medium_february">2 月</string>
-    <string name="month_medium_march">3 月</string>
-    <string name="month_medium_april">4 月</string>
-    <string name="month_medium_may">5 月</string>
-    <string name="month_medium_june">6 月</string>
-    <string name="month_medium_july">7 月</string>
-    <string name="month_medium_august">8 月</string>
-    <string name="month_medium_september">9 月</string>
-    <string name="month_medium_october">10 月</string>
-    <string name="month_medium_november">11 月</string>
-    <string name="month_medium_december">12 月</string>
-
-    <string name="month_shortest_january">1 月</string>
-    <string name="month_shortest_february">2 月</string>
-    <string name="month_shortest_march">3 月</string>
-    <string name="month_shortest_april">4 月</string>
-    <string name="month_shortest_may">5 月</string>
-    <string name="month_shortest_june">6 月</string>
-    <string name="month_shortest_july">7 月</string>
-    <string name="month_shortest_august">8 月</string>
-    <string name="month_shortest_september">9 月</string>
-    <string name="month_shortest_october">10 月</string>
-    <string name="month_shortest_november">11 月</string>
-    <string name="month_shortest_december">12 月</string>
-
-    <string name="day_of_week_long_sunday">星期日</string>
-    <string name="day_of_week_long_monday">星期一</string>
-    <string name="day_of_week_long_tuesday">星期二</string>
-    <string name="day_of_week_long_wednesday">星期三</string>
-    <string name="day_of_week_long_thursday">星期四</string>
-    <string name="day_of_week_long_friday">星期五</string>
-    <string name="day_of_week_long_saturday">星期六</string>
-
-    <string name="day_of_week_medium_sunday">週日</string>
-    <string name="day_of_week_medium_monday">週一</string>
-    <string name="day_of_week_medium_tuesday">週二</string>
-    <string name="day_of_week_medium_wednesday">週三</string>
-    <string name="day_of_week_medium_thursday">週四</string>
-    <string name="day_of_week_medium_friday">週五</string>
-    <string name="day_of_week_medium_saturday">週六</string>
-
-    <string name="day_of_week_short_sunday">週日</string>
-    <string name="day_of_week_short_monday">週一</string>
-    <string name="day_of_week_short_tuesday">週二</string>
-    <string name="day_of_week_short_wednesday">週三</string>
-    <string name="day_of_week_short_thursday">週四</string>
-    <string name="day_of_week_short_friday">週五</string>
-    <string name="day_of_week_short_saturday">週六</string>
-
-    <string name="day_of_week_shortest_sunday">日</string>
-    <string name="day_of_week_shortest_monday">一</string>
-    <string name="day_of_week_shortest_tuesday">二</string>
-    <string name="day_of_week_shortest_wednesday">三</string>
-    <string name="day_of_week_shortest_thursday">四</string>
-    <string name="day_of_week_shortest_friday">五</string>
-    <string name="day_of_week_shortest_saturday">六</string>
-
-    <string name="am">上午</string>
-    <string name="pm">下午</string>
-    <string name="yesterday">昨天</string>
-    <string name="today">今天</string>
-    <string name="tomorrow">明天</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%p %-l:%M</string>
     <string name="hour_minute_cap_ampm">%p %-l:%M</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 8975871..473b9d0 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -28,7 +28,7 @@
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;未命名&gt;"</string>
-    <string name="ellipsis" msgid="7899829516048813237">"..."</string>
+    <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
     <string name="emptyPhoneNumber" msgid="7694063042079676517">"(沒有電話號碼)"</string>
     <string name="unknownName" msgid="2277556546742746522">"(不明)"</string>
@@ -142,7 +142,7 @@
     <string name="silent_mode_silent" msgid="319298163018473078">"鈴聲關閉"</string>
     <string name="silent_mode_vibrate" msgid="7072043388581551395">"鈴聲震動"</string>
     <string name="silent_mode_ring" msgid="8592241816194074353">"鈴聲開啟"</string>
-    <string name="shutdown_progress" msgid="2281079257329981203">"關機中..."</string>
+    <string name="shutdown_progress" msgid="2281079257329981203">"關機中…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"您的平板電腦將會關機。"</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"手機即將關機。"</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"您要關機嗎?"</string>
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"電話選項"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"螢幕鎖定"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"關機"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"錯誤報告"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"取得錯誤報告"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"這會收集您目前裝置狀態的相關資訊,以便透過電子郵件傳送。從錯誤報告開始建立到準備傳送的這段過程可能需要一點時間,敬請耐心等候。"</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"靜音模式"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"音效已關閉"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"音效已開啟"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"您的簡訊"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"讀取及寫入您的簡訊、電子郵件和其他訊息。"</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"您的個人資訊"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"直接存取平板電腦上儲存的聯絡人和日曆。"</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"直接存取手機上的聯絡人與日曆。"</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"直接存取您儲存在聯絡人卡片中的個人資訊。"</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"您的社交資訊"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"直接存取您的聯絡人資訊與社交網站資訊。"</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"您的位置"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"監控您的實際位置。"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"網路通訊"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"存取各種網路功能。"</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"藍牙"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"透過藍牙存取裝置和網路。"</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"音效設定"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"變更音訊設定。"</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"影響電力"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"使用可能大量耗電的功能。"</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"日曆"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"直接存取日曆和活動。"</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"讀取使用者字典"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"讀取使用者字典中的字詞。"</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"寫入使用者字典"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"將字詞加入使用者字典。"</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"書籤與紀錄"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"直接存取書籤和瀏覽器紀錄。"</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"鬧鐘"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"設定鬧鐘。"</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"語音信箱"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"直接存取語音信箱。"</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"麥克風"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"直接使用麥克風錄音。"</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"相機"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"直接使用相機拍照或錄影。"</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"您的應用程式資訊"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"影響裝置上其他應用程式的行為。"</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"桌布"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"變更裝置桌布設定。"</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"時鐘"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"變更裝置時間或時區。"</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"狀態列"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"變更裝置狀態列設定。"</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"同步處理設定"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"存取同步處理設定。"</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"您的帳戶"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"存取可用帳戶。"</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"硬體控制"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"系統低階存取與控制。"</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"開發工具"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"只有應用程式開發人員需要使用的功能。"</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"其他應用程式使用者介面"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"影響其他應用程式的使用者介面。"</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>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"允許應用程式接收和處理 WAP 訊息。這項權限也能讓應用程式監控訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"擷取執行中的應用程式"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"允許應用程式擷取最近執行工作的資訊。這項設定可讓應用程式找出裝置所用程式的相關資訊。"</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"對所有使用者執行各種動作"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"允許應用程式對裝置上的所有使用者執行各種動作。請注意,惡意應用程式可能利用此功能侵害使用者之間的保護機制。"</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"完整授權對所有使用者執行各種動作"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"允許對所有使用者執行各種可能的動作。"</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"管理使用者"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"允許應用程式管理裝置上的使用者,包括查詢、建立及刪除使用者。"</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"擷取執行中應用程式的詳細資訊"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"允許應用程式擷取目前及最近所執行任務的詳細資訊。請注意,惡意應用程式可能會找出其他應用程式的不公開資訊。"</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"重新排序正在執行的應用程式"</string>
@@ -243,6 +287,14 @@
     <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="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"暫時啟用協助工具"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"允許應用程式在裝置上暫時啟用協助工具。惡意應用程式可能藉此在未經使用者同意的情況下擅自啟用協助工具。"</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"擷取視窗資訊"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"允許應用程式透過視窗管理程式擷取視窗的相關資訊。請注意,惡意應用程式可能藉此擷取僅限內部系統使用的資訊。"</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"篩選活動"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"允許應用程式註冊輸入篩選器,在分派所有使用者活動的串流前先行篩選。請注意,惡意應用程式可能藉此擅自控制系統使用者介面。"</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"放大畫面"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"允許應用程式放大畫面內容。請注意,惡意應用程式可能會藉此利用不正常的方式改變顯示內容,導致裝置失靈。"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"部分關機"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"讓活動管理員進入關機狀態,而不執行完整的關機程序。"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"防止切換應用程式"</string>
@@ -259,8 +311,10 @@
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"允許應用程式控制可執行程序的數量上限 (一般應用程式不需使用)。"</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"強制關閉背景應用程式"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"允許應用程式控制活動是否隨時可於完成後立刻進入背景 (一般應用程式不需使用)。"</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"編輯電池狀態"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"允許應用程式修改收集到的電池使用統計資料 (不建議一般應用程式使用)。"</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"讀取電池使用統計資料"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"允許應用程式讀取目前的低電量使用資料。應用程式可能藉此找到一些詳細資訊,例如您所使用的應用程式為何。"</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"修改電池使用統計資料"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"允許應用程式修改收集到的電池使用統計資料 (不建議一般應用程式使用)。"</string>
     <string name="permlab_backup" msgid="470013022865453920">"控制系統備份與還原"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"允許應用程式控制系統備份與還原機制 (不建議一般應用程式使用)。"</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"確認完整備份或還原作業"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"顯示未授權視窗"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"允許應用程式為內部系統使用者介面建立視窗 (不建議一般應用程式使用)。"</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"描繪其他應用程式"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"允許應用程式顯示系統警告視窗。部分警告視窗可能會佔據整個螢幕。"</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"允許應用程式在其他應用程式頂層或使用者介面的特定部分繪圖。這可能會干擾您在所有應用程式中的介面使用行為,或是使您在其他應用程式中預期看到的內容發生變化。"</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">"允許應用程序略過一般程序,直接建立及管理本身的憑證 (一般應用程式不需使用)。"</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"凍結螢幕"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"允許應用程式暫時凍結螢幕畫面,顯示全螢幕轉場效果。"</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>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"直接安裝應用程式"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"允許應用程式安裝新的 Android 套件或進行更新。請注意,惡意應用程式可能利用此功能新增應用程式,並給予其最高權限。"</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="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"允許應用程式刪除其他應用程式快取目錄中的檔案,藉此釋放平板電腦儲存空間。這可能會使其他應用程式的啟動速度變慢,因為應用程式必須重新擷取資料。"</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"允許應用程式刪除其他應用程式快取目錄中的檔案,藉此釋放手機儲存空間。這可能會使其他應用程式的啟動速度變慢,因為應用程式必須重新擷取資料。"</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"移動應用程式資源"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"允許應用程式將應用程式資源從內部媒體移到外部媒體,反之亦可。"</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"讀取機密記錄資料"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"允許應用程式存取額外位置資訊提供者指令。這項設定可能會造成應用程式干擾 GPS 或其他位置資訊來源的運作。"</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"准許安裝位置提供者"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"建立虛構的位置資訊來源以供測試,或安裝新的位置資訊提供者。這項設定可讓應用程式覆寫 GPS 或位置資訊提供者等其他位置資訊來源所傳回的位置資訊和/或狀態。"</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"精確位置 (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"存取平板電腦 GPS 等精確位置資訊來源。當位置資訊服務可以使用且已開啟時,這項權限即可讓應用程式判斷您的精確位置。"</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"存取手機 GPS 等精確位置資訊來源。當位置資訊服務可以使用且已開啟時,這項權限即可讓應用程式判斷您的精確位置。"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"概略位置 (以網路為基準)"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"存取無線通信基地台、Wi-Fi 等網路來源提供的概略位置資訊。當上述位置資訊服務可以使用且已開啟時,這項權限即可讓應用程式判斷您的概略位置。"</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"精確位置 (以 GPS 和網路為基準)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"允許應用程式使用全球衛星定位系統 (GPS) 或網路位置來源 (例如無線通信基地台和 WiFi) 取得您的精確位置。您必須在裝置上開啟這些定位服務,才能供應用程式使用。應用程式可能藉此判別您的位置,也可能增加額外耗電。"</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"概略位置 (以網路為基準)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"允許應用程式取得您的概略位置。這類位置資訊取自使用網路位置來源 (例如無線通信基地台和 WiFi) 的定位服務。您必須在裝置上開啟這些定位服務,才能供應用程式使用。應用程式可能藉此判別您的概略位置。"</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"存取 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="permlab_configureWifiDisplay" msgid="5595661694746742168">"設定 WiFi 顯示裝置"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"允許應用程式設定及連接 WiFi 顯示裝置。"</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"控制 WiFi 顯示裝置"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"允許應用程式控制 WiFi 顯示裝置的低階功能。"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"變更音訊設定"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"允許應用程式修改全域音訊設定,例如音量和用來輸出的喇叭。"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"錄製音訊"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"存取藍牙設定"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"允許應用程式設定本機藍牙平板電腦,以及搜尋遠端裝置並配對連線。"</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"允許應用程式設定本機藍牙手機,以及搜尋遠端裝置並配對連線。"</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"查看 WiMAX 連線"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"建立或中斷與 WiMAX 網路的連線"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"允許應用程式判斷是否已啟用 WiMAX,以及判讀任何已連上 WiMAX 網路的相關資訊。"</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"變更 WiMAX 狀態"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"允許應用程式建立或中斷平板電腦與 WiMAX 網路的連線。"</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"允許應用程式修改目前已同步處理的資訊提供。請注意,惡意應用程式可能利用此功能變更已同步處理的資訊提供。"</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"讀取您加入字典的字詞"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"允許應用程式讀取使用者儲存在使用者字典內的所有字詞、名稱和詞組。"</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"寫入使用者定義的字典"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"將字詞加入使用者定義的字典"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"允許應用程式將新字詞寫入使用者的字典。"</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"測試能否存取受保護的儲存裝置"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"測試能否存取受保護的儲存裝置"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"允許應用程式測試未來裝置將支援的 USB 儲存裝置權限。"</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"允許應用程式測試未來裝置將支援的 USB 儲存權限。"</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"允許應用程式測試未來裝置將支援的 SD 卡權限。"</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"修改或刪除 USB 儲存裝置的內容"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"修改或刪除 SD 卡的內容"</string>
@@ -534,6 +593,8 @@
     <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="permlab_sdcardAccessAll" msgid="8150613823900460576">"存取外部儲存空間 (所有使用者)"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"允許應用程式存取外部儲存空間 (所有使用者)。"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"存取快取檔案系統"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"允許應用程式讀取及寫入快取檔案系統。"</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"撥打/接聽網路電話"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"必須為儲存的應用程式資料加密。"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"停用相機"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"禁止使用所有裝置相機。"</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"停用鍵盤保護框上的功能"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"禁止使用鍵盤保護框上的部分功能。"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"住家電話"</item>
     <item msgid="869923650527136615">"行動電話"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"再試一次"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"已超過人臉解鎖嘗試次數上限"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"充電中 (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"充電完成。"</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"充電完成"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"請連接充電器。"</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"沒有 SIM  卡。"</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"找不到 SIM 卡"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"平板電腦中沒有 SIM 卡。"</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"手機未插入 SIM 卡。"</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"插入 SIM 卡。"</string>
@@ -719,7 +782,7 @@
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM 的 PUK 已鎖定。"</string>
     <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"參閱《使用者指南》或與客戶服務中心聯絡。"</string>
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM 卡已鎖定。"</string>
-    <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"解鎖 SIM 卡中..."</string>
+    <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"解鎖 SIM 卡中…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"您的解鎖圖形已畫錯 <xliff:g id="NUMBER_0">%d</xliff:g> 次。"\n\n"請在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒後再試一次。"</string>
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"您的密碼已輸錯 <xliff:g id="NUMBER_0">%d</xliff:g> 次。"\n\n"請在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒後再試一次。"</string>
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"您的 PIN 已輸錯 <xliff:g id="NUMBER_0">%d</xliff:g> 次。"\n\n"請在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒後再試一次。"</string>
@@ -739,7 +802,7 @@
     <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"登入"</string>
     <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"使用者名稱或密碼錯誤。"</string>
     <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"忘了使用者名稱或密碼?"\n"請造訪 "<b>"google.com/accounts/recovery"</b>"。"</string>
-    <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"檢查中..."</string>
+    <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"檢查中…"</string>
     <string name="lockscreen_unlock_label" msgid="737440483220667054">"解除封鎖"</string>
     <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"開啟音效"</string>
     <string name="lockscreen_sound_off_label" msgid="996822825154319026">"關閉音效"</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"已清除解鎖圖形"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"已加入 1 格"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"已畫出解鎖圖形"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"新增小工具。"</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"空白"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"解鎖區域已展開。"</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"解鎖區域已收合。"</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>小工具。"</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"使用者選取工具"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"狀態"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"相機"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"媒體控制項"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"已開始將小工具重新排序。"</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"小工具重新排序已完成。"</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>小工具已刪除。"</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"展開解鎖區域。"</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"滑動解鎖。"</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"圖形解鎖。"</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"人臉解鎖。"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN 解鎖。"</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"密碼解鎖。"</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"圖形區域。"</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"滑動區域。"</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"複製網址"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"選取文字"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"選取文字"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"新增至字典"</string>
-    <string name="deleteText" msgid="7070985395199629156">"刪除"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"加入字典"</string>
+    <string name="deleteText" msgid="6979668428458199034">"刪除"</string>
     <string name="inputMethod" msgid="1653630062304567879">"輸入法"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"文字動作"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"儲存空間即將用盡"</string>
@@ -941,7 +1024,7 @@
     <string name="yes" msgid="5362982303337969312">"確定"</string>
     <string name="no" msgid="5141531044935541497">"取消"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"注意"</string>
-    <string name="loading" msgid="7933681260296021180">"載入中..."</string>
+    <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>
@@ -970,7 +1053,7 @@
     <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_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_complete" msgid="1405954754112999229">"啟動完成。"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"開啟可用 Wi-Fi 網路"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"登入 WiFi 網路"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"登入網路"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"無法連線至 Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" 的網際網路連線狀況不佳。"</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"收件者:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"請輸入必要的 PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"手機與 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 連線期間將暫時中斷 WiFi 連線"</string>
     <string name="select_character" msgid="3365550120617701745">"插入字元"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"傳送 SMS 簡訊"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;&lt;/b&gt;「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在傳送大量簡訊。您要允許這個應用程式繼續傳送簡訊嗎?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"允許"</string>
     <string name="sms_control_no" msgid="625438561395534982">"拒絕"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; 要求將訊息傳送至 &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;。"</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"這"<font fgcolor="#ffffb060">"可能會透過您的行動帳戶計費"</font>"。"</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"這會透過您的行動帳戶計費。"</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"傳送"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"取消"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"記住我的選擇"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"您日後可在 [設定] &gt; [應用程式] 中進行變更。"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"一律允許"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"一律不允許"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM 卡已移除"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"您必須先插入有效的 SIM 卡再重新啟動手機,才能使用行動網路。"</string>
     <string name="sim_done_button" msgid="827949989369963775">"完成"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"日期設定"</string>
     <string name="date_time_set" msgid="5777075614321087758">"設定"</string>
     <string name="date_time_done" msgid="2507683751759308828">"完成"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"預設值"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"無須許可"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>" 隱藏"</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"顯示全部"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"新增:"</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"新增:"</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"由「<xliff:g id="APP_NAME">%1$s</xliff:g>」提供。"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"無須許可"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"這可能需要付費"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB 大量儲存裝置"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB 已連接"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"您已透過 USB 與電腦建立連線。如要在電腦和 Android 的 USB 儲存裝置之間複製檔案,請輕觸下方按鈕。"</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> 已啟用 VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"輕觸即可管理網路。"</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"已連線至 <xliff:g id="SESSION">%s</xliff:g>,輕觸即可管理網路。"</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"正在連線至永久連線的 VPN…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"已連線至永久連線的 VPN"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"永久連線的 VPN 發生錯誤"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"輕觸即可重設連線"</string>
     <string name="upload_file" msgid="2897957172366730416">"選擇檔案"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"未選擇任何檔案"</string>
     <string name="reset" msgid="2448168080964209908">"重設"</string>
@@ -1169,10 +1265,10 @@
     <item quantity="other" msgid="4641872797067609177">"第 <xliff:g id="INDEX">%d</xliff:g> 個相符項目 (共 <xliff:g id="TOTAL">%d</xliff:g> 個相符項目)"</item>
   </plurals>
     <string name="action_mode_done" msgid="7217581640461922289">"完成"</string>
-    <string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"正在卸載 USB 儲存裝置..."</string>
-    <string name="progress_unmounting" product="default" msgid="1327894998409537190">"正在卸載 SD 卡..."</string>
-    <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"正在清除 USB 儲存裝置..."</string>
-    <string name="progress_erasing" product="default" msgid="6596988875507043042">"正在清除 SD 卡..."</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"正在卸載 USB 儲存裝置…"</string>
+    <string name="progress_unmounting" product="default" msgid="1327894998409537190">"正在卸載 SD 卡…"</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"正在清除 USB 儲存裝置的資料…"</string>
+    <string name="progress_erasing" product="default" msgid="6596988875507043042">"正在清除 SD 卡的資料…"</string>
     <string name="format_error" product="nosdcard" msgid="6299769563624776948">"無法清除 USB 儲存裝置。"</string>
     <string name="format_error" product="default" msgid="7315248696644510935">"無法清除 SD 卡。"</string>
     <string name="media_bad_removal" msgid="7960864061016603281">"SD 卡尚未卸載就已移除。"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"分享"</string>
     <string name="find" msgid="4808270900322985960">"尋找"</string>
     <string name="websearch" msgid="4337157977400211589">"網頁搜尋"</string>
+    <string name="find_next" msgid="5742124618942193978">"尋找下一個項目"</string>
+    <string name="find_previous" msgid="2196723669388360506">"尋找上一個項目"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g> 的地點要求"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"位置要求"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"要求者:<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
@@ -1277,7 +1375,7 @@
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"分享活動"</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"裝置已鎖定。"</string>
     <string name="list_delimeter" msgid="3975117572185494152">"、 "</string>
-    <string name="sending" msgid="3245653681008218030">"傳送中..."</string>
+    <string name="sending" msgid="3245653681008218030">"傳送中…"</string>
     <string name="launchBrowserDefault" msgid="2057951947297614725">"啟動「瀏覽器」嗎?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"接聽電話嗎?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"一律採用"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"手機"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"耳機"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"座架喇叭"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI 音訊"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"系統"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"藍牙音訊"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"完成"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"媒體輸出"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"掃描中..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"連線中…"</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"可以使用"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"無法使用"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"內建畫面"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI 螢幕"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"第 <xliff:g id="ID">%1$d</xliff:g> 個重疊效果"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>:<xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>,<xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"已連接無線顯示器"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"其他裝置正在顯示這個畫面"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"中斷連線"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"緊急電話"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"忘記圖形"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"圖形錯誤"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"密碼錯誤"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN 錯誤"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"請在 <xliff:g id="NUMBER">%d</xliff:g> 秒後再試一次。"</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"畫出圖形"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"輸入 SIM PIN"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"輸入 PIN"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"輸入密碼"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM 卡已遭停用,必須輸入 PUK 碼才能繼續使用。詳情請洽您的行動通訊業者。"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"輸入所需的 PIN 碼"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"確認所需的 PIN 碼"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"正在解除 SIM 卡鎖定..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"PIN 碼不正確。"</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"請輸入 4 到 8 碼的 PIN。"</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK 碼至少必須為 8 碼。"</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"重新輸入正確的 PUK 碼。如果錯誤次數過多,SIM 卡將會永久停用。"</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN 碼不符"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"圖形嘗試次數過多"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"如要解除鎖定,請使用 Google 帳戶登入。"</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"使用者名稱 (電子郵件)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"密碼"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"登入"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"使用者名稱或密碼無效。"</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"忘了使用者名稱或密碼?"\n"請前往 "<b>"google.com/accounts/recovery"</b>"。"</string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"正在檢查帳戶…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"您的 PIN 已輸錯 <xliff:g id="NUMBER_0">%d</xliff:g> 次。"\n\n"請在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒後再試一次。"</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"您的密碼已輸錯 <xliff:g id="NUMBER_0">%d</xliff:g> 次。"\n\n"請在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒後再試一次。"</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"您的解鎖圖形已畫錯 <xliff:g id="NUMBER_0">%d</xliff:g> 次。"\n\n"請在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒後再試一次。"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"您嘗試解除這個平板電腦的鎖定已失敗 <xliff:g id="NUMBER_0">%d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%d</xliff:g> 次機會。如果失敗次數超過限制,平板電腦將恢復原廠設定,所有使用者資料都會遺失。"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"您嘗試解除這支手機的鎖定已失敗 <xliff:g id="NUMBER_0">%d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%d</xliff:g> 次機會。如果失敗次數超過限制,手機將恢復原廠設定,所有使用者資料都會遺失。"</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"您嘗試解除這個平板電腦的鎖定已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次,平板電腦現在將恢復原廠設定。"</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"您嘗試解除這支手機的鎖定已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次,手機現在將恢復原廠設定。"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"您的解鎖圖形已畫錯 <xliff:g id="NUMBER_0">%d</xliff:g> 次,如果再嘗試 <xliff:g id="NUMBER_1">%d</xliff:g> 次仍未成功,系統就會要求您透過電子郵件帳戶解除平板電腦的鎖定狀態。"\n\n"請在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒後再試一次。"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"您的解鎖圖形已畫錯 <xliff:g id="NUMBER_0">%d</xliff:g> 次,如果再嘗試 <xliff:g id="NUMBER_1">%d</xliff:g> 次仍未成功,系統就會要求您透過電子郵件帳戶解除手機的鎖定狀態。"\n\n"請在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒後再試一次。"</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"移除"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"要將音量調高到安全等級以上嗎?"\n"長時間聆聽偏高音量可能會損害您的聽力。"</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"持續用兩指按住即可啟用協助工具。"</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"協助工具已啟用。"</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"協助工具已取消。"</string>
+    <string name="user_switched" msgid="3768006783166984410">"目前的使用者是 <xliff:g id="NAME">%1$s</xliff:g>。"</string>
+    <string name="owner_name" msgid="2716755460376028154">"擁有者"</string>
 </resources>
diff --git a/core/res/res/values-zu/donottranslate-cldr.xml b/core/res/res/values-zu/donottranslate-cldr.xml
index df578ed..97b179b1 100644
--- a/core/res/res/values-zu/donottranslate-cldr.xml
+++ b/core/res/res/values-zu/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">uJanuwari</string>
-    <string name="month_long_standalone_february">uFebruwari</string>
-    <string name="month_long_standalone_march">uMashi</string>
-    <string name="month_long_standalone_april">u-Apreli</string>
-    <string name="month_long_standalone_may">uMeyi</string>
-    <string name="month_long_standalone_june">uJuni</string>
-    <string name="month_long_standalone_july">uJulayi</string>
-    <string name="month_long_standalone_august">uAgasti</string>
-    <string name="month_long_standalone_september">uSepthemba</string>
-    <string name="month_long_standalone_october">u-Okthoba</string>
-    <string name="month_long_standalone_november">uNovemba</string>
-    <string name="month_long_standalone_december">uDisemba</string>
-
-    <string name="month_long_january">Januwari</string>
-    <string name="month_long_february">Februwari</string>
-    <string name="month_long_march">Mashi</string>
-    <string name="month_long_april">Apreli</string>
-    <string name="month_long_may">Meyi</string>
-    <string name="month_long_june">Juni</string>
-    <string name="month_long_july">Julayi</string>
-    <string name="month_long_august">Agasti</string>
-    <string name="month_long_september">Septhemba</string>
-    <string name="month_long_october">Okthoba</string>
-    <string name="month_long_november">Novemba</string>
-    <string name="month_long_december">Disemba</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mas</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">Mey</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aga</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Okt</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dis</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">Sonto</string>
-    <string name="day_of_week_long_monday">Msombuluko</string>
-    <string name="day_of_week_long_tuesday">Lwesibili</string>
-    <string name="day_of_week_long_wednesday">Lwesithathu</string>
-    <string name="day_of_week_long_thursday">uLwesine</string>
-    <string name="day_of_week_long_friday">Lwesihlanu</string>
-    <string name="day_of_week_long_saturday">Mgqibelo</string>
-
-    <string name="day_of_week_medium_sunday">Son</string>
-    <string name="day_of_week_medium_monday">Mso</string>
-    <string name="day_of_week_medium_tuesday">Bil</string>
-    <string name="day_of_week_medium_wednesday">Tha</string>
-    <string name="day_of_week_medium_thursday">Sin</string>
-    <string name="day_of_week_medium_friday">Hla</string>
-    <string name="day_of_week_medium_saturday">Mgq</string>
-
-    <string name="day_of_week_short_sunday">Son</string>
-    <string name="day_of_week_short_monday">Mso</string>
-    <string name="day_of_week_short_tuesday">Bil</string>
-    <string name="day_of_week_short_wednesday">Tha</string>
-    <string name="day_of_week_short_thursday">Sin</string>
-    <string name="day_of_week_short_friday">Hla</string>
-    <string name="day_of_week_short_saturday">Mgq</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">B</string>
-    <string name="day_of_week_shortest_wednesday">T</string>
-    <string name="day_of_week_shortest_thursday">S</string>
-    <string name="day_of_week_shortest_friday">H</string>
-    <string name="day_of_week_shortest_saturday">M</string>
-
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%-k:%M</string>
     <string name="hour_minute_ampm">%-l:%M %p</string>
     <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index a2bc951..eb1cbfb 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -154,6 +154,9 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Okukhethwa kukho kwefoni"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Ukuvala isikrini"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Vala amandla"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Umbiko wephutha"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"Thatha umbiko wesiphazamiso"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Lokhu kuzoqoqa ulwazi mayelana nesimo samanje sedivayisi yakho, ukuthumela imilayezo ye-imeyili. Kuzothatha isikhathi esincane kusuka ekuqaleni umbiko wesiphazamiso uze ulungele ukuthunyelwa; sicela ubekezele."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Imodi ethulile"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Umsindo UVALIWE"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Umsindo UVULIWE"</string>
@@ -168,12 +171,45 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Imiyalezo yakho"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"Funda futhi ubhale i-SMS yakho, i-imeyili, kanye neminye imiyalezo."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Ukwaziswa kwakho komuntu siqu"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Ukufinyelela okuqondile othintana nabo nekhalenda egcinwe kwithebhulethi yakho."</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Ukufinyelela okuqondile othintana nabo nekhalenda egcinwe efonini yakho."</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Ukufinyelela okuqondile kulwazi mayelana nawe, kulondolozwe ekhadini loxhumana naye."</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Ulwazi lakho lomphakathi"</string>
+    <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"Ukufinyelela okuqondile kulwazi mayelana noxhumana nabo bomphakathi."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Indawo yakho"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"Gada indawo yakho yokuhlala"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Uxhumano lwenethiwekhi"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"Finyelela kokuqukethwe inethiwekhi okuhlukahlukee."</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"I-Bluetooth"</string>
+    <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Finyelela amadivayisi namanethiwekhi nge-Bluetooth."</string>
+    <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Izilungiselelo zomsindo"</string>
+    <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Shintsha izilungiselelo zomsindo."</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Ithinta ibhethri"</string>
+    <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Sebenzisa izici ezingakhipha ngokushesha ibhethri."</string>
+    <string name="permgrouplab_calendar" msgid="5863508437783683902">"Ikhalenda"</string>
+    <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Ukufinyelela okuqondile kukhalenda nezehlakalo."</string>
+    <string name="permgrouplab_dictionary" msgid="4148597128843641379">"Funda isichazamazwi somsebenzisi"</string>
+    <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"Funda amagama kusichazamazwi somsebenzisi."</string>
+    <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Bhala isichazamazwi somsebenzisi"</string>
+    <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Engeza amagama kusichazamazwi somsebenzisi."</string>
+    <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Amabhukhimakhi nomlando"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Ukufinyelela okuqondile kumlando wamabhukimakhi nesiphequluli."</string>
+    <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"I-alamu"</string>
+    <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Setha i-alamu."</string>
+    <string name="permgrouplab_voicemail" msgid="4162237145027592133">"I-voicemail"</string>
+    <string name="permgroupdesc_voicemail" msgid="2498403969862951393">"Ukufinyelela okuqondile ku-voicemail."</string>
+    <string name="permgrouplab_microphone" msgid="171539900250043464">"I-Microphone"</string>
+    <string name="permgroupdesc_microphone" msgid="7106618286905738408">"Ukufinyelela okuqondile ku-microphone ukuze uqophe umsindo."</string>
+    <string name="permgrouplab_camera" msgid="4820372495894586615">"Ikhamela"</string>
+    <string name="permgroupdesc_camera" msgid="2933667372289567714">"Ukufinyelela okuqondile kukhamera ekuthwebuleni isithombe noma ividiyo."</string>
+    <string name="permgrouplab_appInfo" msgid="8028789762634147725">"Ulwazi lezinhlelo zakho zokusebenza"</string>
+    <string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Amandla okuthinta ukuziphatha kwezinhlelo zokusebenza kudivayisi yakho."</string>
+    <string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Isithombe sangemuva"</string>
+    <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Shintsha izilungiselelo ze-wallpaper yedivayisi."</string>
+    <string name="permgrouplab_systemClock" msgid="406535759236612992">"Iwashi"</string>
+    <string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Shintsha isikhathi sedivayisi noma izoni yesikhathi."</string>
+    <string name="permgrouplab_statusBar" msgid="2095862568113945398">"Ibha yesimo"</string>
+    <string name="permgroupdesc_statusBar" msgid="6242593432226807171">"Shintsha izilungiselelo zebha yesimo yedivayisi."</string>
+    <string name="permgrouplab_syncSettings" msgid="3341990986147826541">"Vumelanisa izilungiselelo"</string>
+    <string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"Ukufinyela kuzilungiselelo zokuvumelanisa."</string>
     <string name="permgrouplab_accounts" msgid="3359646291125325519">"Ama-akhawunti akho"</string>
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Finyelela kuma-akhawunti atholakalayo"</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Izilawuli zezingxenyekazi zekhompyutha"</string>
@@ -184,6 +220,8 @@
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Ukufinyelela kwezinga eliphansi nokulawula uhlelo."</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Amathuluzi okuthuthukisa"</string>
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Okuqukethwe okudingakela abasunguli bensiza kuphela."</string>
+    <string name="permgrouplab_display" msgid="4279909676036402636">"Enye i-UI yohlelo lokusebenza"</string>
+    <string name="permgroupdesc_display" msgid="6051002031933013714">"Kuthinta i-UI yezinye izinhlelo zokusebenza."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Isitoreji"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Finyelela kwisitoreji se-USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Finyelela ikhadi le-SD."</string>
@@ -217,6 +255,12 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Ivumela uhlelo lokusebenza ukuthola nokucubungula imilayezo ye-WAP. Le mvume ifaka phakathi amandla okungamela noma okwesusa imilayezo ethunyelwe kuwe ngaphandle kokukubonisa."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"thola izinsiza ezisebenzayo"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Ivumela uhlelo lokusebenza ukubuyisa ulwazi mayelana nemisebenzi yamanje neyakamuva. Lokhu kungavumela uhlelo lokusebenza ukuthola ulwazi mayelana nokuthi iziphi izinhlelo zokusebenza ezisetshenziswa kudivayisi."</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"ihlanganyela phakathi kwabasebenzisi"</string>
+    <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Ivumela uhlelo lokusebenza ukwenza izenzo kubasebenzisi bonke kudivayisi. Izinhlelo zokusebenza ezingalungile zingasebenzisa lokhu ukwephula ukuvikela phakathi kwabasebenzisi."</string>
+    <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"ilayisensi egcwele yokuhlanganyela kubasebenzisi"</string>
+    <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Ivumela konke ukuhlanganyela phakathi kwabasebenzisi."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"phatha abasebenzisi"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Ivumela izinhlelo zokusebenza ukuphatha abasebenzisi kudivayisi, kufaka phakathi umbuzo, ukudala nokususa."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"thola kabusha imininingwane yezinhlelo zokusebenza ezisebenzayo"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Ivumela uhlelo lokusebenza ukuthola kabusha ulwazi mayelana nezinto ezenzeka manje nezisanda kwenzeka. Izinhlelo zokusebenza ezingalungile zingathola imininingwane eyimfihlo mayelana nezinye izinhlelo zokusebenza."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"misa kabusha izinsiza ezisebenzayo"</string>
@@ -243,6 +287,14 @@
     <string name="permdesc_dump" msgid="1778299088692290329">"Ivumela insiza ukuthi ithole kabusha ingaphakathi lesistimu. izinsiza ezinobungozi zingathola kabusha inqwaba yolwazi oluyimfihlo noluvikelekile ezingajwayele ukuthi ziludinge."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"letha okuqukethwe kwesikrini"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Ivumela insiza ukuthi ithole okuqukethe kwi-Window. Izinsiza ezinobungozi zingathola kabush iwindi eliphelele bese ibheka konke okuqukethwe ngaphandle kwaaaphasiwedi."</string>
+    <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"nika amandla okwesikhashana ukufinyelela"</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Ivumela uhlelo lokusebenza ukunika amandla ukufinyelela kwesikhashana kuvidayisi. Izinhlelo zokusebenza ezingalungile zinganika amandla ukufinyelela ngaphandle kwemvume yomsebenzisi."</string>
+    <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"buyisa ulwazi lewindi"</string>
+    <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Ivumela uhlelo lokusebenza ukubuyisa ulwazi mayelana namawindi avela kumphathi wewindi. Izinhlelo zokusebenza zingabuyisa ulwazi olubhekiswe ukusetshenziselwa kohlelo lwangaphakathi."</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"hlunga imicimbi"</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Ivumela uhlelo lokusebenza ukubhalisa isihlungi sokufaka ukusakaza kwazo zonke izehlakalo zomsebenzisi ngaphambi kokuthunyelwa. Izinhlelo zokusebenza zingalawula i-UI yohlelo ngaphandle kokungena komsebenzisi."</string>
+    <string name="permlab_magnify_display" msgid="5973626738170618775">"lungisa ukubuka"</string>
+    <string name="permdesc_magnify_display" msgid="7121235684515003792">"Ivumela uhlelo lokusebenza ukusondeza okuqukethwe kokubukwa. Izinhlelo zokusebenza ezingalungile zidlulisela okuqukethwe kokubuka ngendlela eyenza idivayisi ingasebenziseki."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"ukuvala shaqa kwengxenye"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Ibeka imeneja yomsebenzi kwisimo sokuvala shaqa. Ayenzi ukuvala shaqa okuphelele."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"gwema ukushintsha kohlelo lokusebenza"</string>
@@ -254,13 +306,15 @@
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"thumela umsakazo otholwe nge-SMS"</string>
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Ivumela insiza ukuthi isakaze isaziso sokuthi umyalezo we-SMS utholakele. Izinsiza ezinobungozi zingasebenzisa lokhu ukufoja imiyalezo ye-SMS engenayo."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"thumela umsakazo otholwe nge-WAP-PUSH"</string>
-    <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Ivumela insiza ukuthi isakaze isaziso sokuthi umyalezo we-WAP PUSH utholakele. Izinsiza ezinobungozi zingasebenzisa lokhu ukufoja ukutholakala kwemiyalezo ye-S noa zisuse okuqukethwe kwanoma iliphi ikhasi lewebhu eliqukethe okunobungozi."</string>
+    <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Ivumela insiza ukuthi isakaze isaziso sokuthi umyalezo we-WAP PUSH utholakele. Izinsiza ezinobungozi zingasebenzisa lokhu ukufoja ukutholakala kwemiyalezo ye-S noma zisuse okuqukethwe kwanoma iliphi ikhasi lewebhu eliqukethe okunobungozi."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"khawula inani lezinqubo ezisebenzayo"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Ivumela insiza ukuthi ilawule isibalo esikhulu sezinto eziqhubekayo eziyosebenza. Ayidingakeli izinsiza ezijwayelekile."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"phoqa izinhlelo zokusebenza ezingemuva ukuthi zivaleke"</string>
     <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Ivumela izinsiza ukuthi zilawule ukuthi izehlakalo ziyaphela yini emumva kokuba ziye ngemumva. Akudingakeli izinsiza ezijwayelekile."</string>
-    <string name="permlab_batteryStats" msgid="7863923071360031652">"guqula izibalo zebhetri"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"Ivumela insiza ukuthi iguqule imininingwane yebhethri eqoqiwe. Akwenzelwe ukuthi kusetshenziswe izinsiza ezijwayelekile."</string>
+    <string name="permlab_batteryStats" msgid="2789610673514103364">"funda izibalo zebhethri"</string>
+    <string name="permdesc_batteryStats" msgid="5897346582882915114">"Ivumela uhlelo lokusebenza ukufunda idatha yokusebenza yebhethri leleveli ephansi yamanje. Ingavumela uhlelo lokusebenza ukuthola ulwazi lemininingwane mayelana nokuthi iziphi izinhlelo zokusebenza ozisebenzisayo."</string>
+    <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"guqula izibalo zebhetri"</string>
+    <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Ivumela uhlelo lokusebenza ukuthi luguqule izibalo zebhethri eziqoqiwe. Akwenzelwe ukuthi kusetshenziswe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_backup" msgid="470013022865453920">"lawula ukusekela ngokulondoloza uhlelo bese ubuyisela esimweni"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Ivumela insiza ukuthi ilawule isipele sesistimu kanye nohlelo lokubuyiselwa kabusha. Ayenzelwe ukusetshenziswa izinsiza ezijwayelekile."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"qinisekisa isipele sonke noma buyisela futhi ukusebenza"</string>
@@ -268,11 +322,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"bonisa amawindi angavunyelwe"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Ivumela insiza ukuthi yakhe amawindi enzelwe ukuthi asetshenziswe inkundla yokusetshenziswa kwangaphakathi kwesistimu. Ayisethsnziswa izinsiza ezijwayelekile."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"dweba phezulu kwezinye izinhlelo zokusebenza"</string>
-    <string name="permdesc_systemAlertWindow" msgid="4460454022797261814">"Ivumela uhlelo lokusebenza ukubonisa amawindi esexwayiso esistimu. Amanye amawindi esexwayiso angathatha isikrini sonke."</string>
+    <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Ivumela uhlelo lokusebenza ukudweba phezu kwezinye izinhlelo zokusebenza noma izingxene zokusetshenziswa ukubonwa. Zingaphazamisa ukusebenzisa kwakho kokusetshenziswa kubonwa kunoma uluphi uhlelo lokusebenza, noma ukushintsha ocabanga ukuthi uyakubona kwezinye izinhlelo zokusebenza."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"guqula isivinini sokugqwayiza jikelele"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Ivumela uhlelo lokusebenza ukushintsha isivinini sokugqwayiza jikelele (ukugqwayiza okusheshayo noma okulengayo) nganoma isiphi isikhathi."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"lawula amathokheni ezinsiza"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Ivumela insiza ukuthi idale iphinde futhi ilawule amathokheni ayo, ngokweqa uku-oda kuka-Z okwejwayelekile. Akufanele kudingakele izinsiza ezijwayelekile."</string>
+    <string name="permlab_freezeScreen" msgid="4708181184441880175">"misa kancane isikrini"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Ivumela uhlelo lokusebenza ukumisa okwesikhashana isikrini ngokushintshwa kwesikrini esigcwele."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"chofoza okhiye nezinkinobho zokulawula"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Ivumela uhlelo lokusebenza ukuthi lizenzele izehlakalo zalo zokufaka (ukucindezela kokhiye, njll)  kwezinye izinhlelo zokusebenza. Izinhlelo zokusebenza ezinobungozi zingasebenzisa lokhu ukuthi zilawule ithebhulethi."</string>
     <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Ivumela insiza ukuthi ithumele imicimbi yayo (ukucindezelwa kwezinkinobho, njll) kwezinye izinsiza. Izinsiza ezinobungozi zingasebenzisa lokhu ukuthi zilawule ucingo."</string>
@@ -314,8 +370,8 @@
     <string name="permlab_installPackages" msgid="2199128482820306924">"faka ngqo izinsiza"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Ivumela insiza ukuthi ifake amaphakheji e-Android amasha noma abuyekeziwe. Izinsiza ezinobungozi zngasebenzisa lokhu ukwengeza izinsiza ezintsha ezinemvume emndla."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"Susa yonke i-data egcinwe okwesikhashana yensiza"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Ivumel insiza ukuthi ikhulule isikhala sokulondoloza sekhompyutha yepeni ngokuthi isuse amafayela afihlwe emtapweni wensiza. Ukufinyelela kunqandwe kakhulu ngokusebenza kwesistimu."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Ivumela insiza ukuthi ikhulule isikhala sokulondoloza socingo ngokuthi isuse amafayela agcinwe okwesikhashana emtapweni wensiza. Ukufinyelela kunqandwe kakhulu ngokusebenza kwesistimu."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Ivumela uhlelo lokusebenza ukukhulula isitoreji se-tablet ngokususa amafayela enqolobaneni yezinye izinhlelo zokusebenza. Lokhu kungabangela ezinye izinhlelo zokusebenza ukuqala kancane njengoba zidinga ukubuyisa idatha yazo."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Ivumela uhlelo lokusebenza ukukhulula isitoreji sefoni ngokususa amafayela enqolobaneni yezinye izinhlelo zokusebenza. Lokhu kungabangela ezinye izinhlelo zokusebenza ukuqala kancane njengoba zidinga ukubuyisa idatha yazo."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"hambis izinto zensiz"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Ivumela insiza ukuthi ihambise izinto eziqukethwe insiz izisusa emidiyeni yangaphakathi kuya kweyangaphandle njalonjalo."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"funda idatha yefayela lokungena ebucayi"</string>
@@ -376,15 +432,18 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Ivumela uhlelo lokusebenza ukufinyelela imiyalo yabanikeli bendawo engaphezulu. Lokhu kungavumela uhlelo lokusebenza ukuthi liphazamisane nomsebenzi we-GPS noma eminye imithombo yendawo."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"imvume yokufaka umhlinzeki wendawo"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Dala imithombo yendawo ye-mock ngokuhlola noma ukufaka umnikeli wendawo omusha. Lokhu kuvumela uhlelo lokusebenza ukubhala ngaphezulu indawo kanye/noma isimo esibuyiswe eminye imithombo yendawo njenge-GPS noma abanikeli bendawo."</string>
-    <string name="permlab_accessFineLocation" msgid="5885550969882561436">"indawo (GPS) eqondile"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"Finyelela imithombo yendawo eqondile njenge-Global Positioning System kuthebhulethi. Uma amasevisi endawo atholakala futhi akhanyisiwe, le mvume ivumela uhlelo lokusebenza ukucacisa indawo yakho eqondile."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"Finyelela imithombo yendawo eqondile njenge-Global Positioning System efonini. Uma amasevisi endawo atholakala futhi akhanyisiwe, le mvume ivumela uhlelo lokusebenza ukucacisa indawo yakho eqondile."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"indawo (esuselwe kunethiwekhi) eseduzane"</string>
-    <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"Finyelela cishe indawo kusuka kubanikeli bendawo usebenzisa imithombo yenethiwekhi efana ne-cell tower ne-Wi-Fi. Uma lawo masevisi endawo atholakala futhi akhanyisiwe, le mvume ivumela uhlelo lokusebenza ukucacisa cishe indawo yakho."</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"indawo eqondile (kususelwe ku-GPS nakunethiwekhi)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Ivumela uhlelo lokusebenza ukuthola indawo yakho uqobo isebenzisa i-Global Positioning System (GPS) noma imithombo yendawo yenethiwekhi njengama-cell tower ne-Wi-Fi. Lawa masevisi endawo kufanele akhanyiswe futhi atholakale kudivayisi yakho ukuze asetshenziswe uhlelo lokusebenza. Izinhlelo zokusebenza zingasebenzias lokhu ukucacisa lapho ukhona, futhi angasebenzisa ibhethri elingeziwe."</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"indawo eseduze (kususelwe kunethiwekhi)"</string>
+    <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Ivumela uhlelo lokusebenza ukuthola cishe indawo yakho. Le ndawo isuselwe kumasevisi endawo kusetshenziswa imithombo yendawo yenethiwekhi njengama-cell tower ne-Wi-Fi. Lawo masevisi endawo kufanele akhanyiswe futhi atholakale kudivayisi yakho ukuze asetshenziswe uhlelo lakho lokusebenza. Izinhlelo zokusebenza zingasebenzisa lokhu ukucacisa cishe lapho ukhona."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"finyelela i-SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Ivumela insiza ukuthi isebenzise okuqukethwe i-SurfaceFlinger okusezingeni eliphansi."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"funda isikhumbuli sesikhashana sendikimba"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Ivumela insiza ukuthi ifunde okuqukethwe ifreyimu yebhafa."</string>
+    <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"lungisa ukubukwa kwe-Wifi"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Ivumela uhlelo lokusebenza ukulungisa nokuxhuma ekubukisweni kwe-Wifi."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"lawula ukubukwa kwe-Wifi"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Uvumela uhlelo lokusebenza ukulawula izici zeleveli ephansi zokuboniswa kwe-Wifi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"shintsha izilungiselelo zakho zomsindo"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Ivumela uhlelo lokusebenza ukushintsha izilungiselelo zomsindo we-global njengevolomu nokuthi isiphi isipika esisetshenziselwa okukhiphayo."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"qopha umsindo"</string>
@@ -428,7 +487,7 @@
     <string name="permlab_callPhone" msgid="3925836347681847954">"ngokuqondile shayela izinombolo zocingo"</string>
     <string name="permdesc_callPhone" msgid="3740797576113760827">"Ivumela uhlelo lokusebenza ukushayela izinombolo zefoni ngaphandle kokuhlanganyela kwakho. Lokhu kungaholela emashajini noma amakholi angalindelekile. Qaphela ukuthi lokhu akuvumeli uhlelo lokusebenza ukushayela izinombolo zesimo esiphuthumayo. Izinhlelo zokusebenza ezingalungile zingabiza imali ngokwenze amakholi ngaphandle kokuqinisekisa kwakho."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"ngokuqondile shayela noma iziphi izinombolo zocingo."</string>
-    <string name="permdesc_callPrivileged" msgid="1689024901509996810">"Ivumela insiza ukuth ishayele noa iyiphi inombolo okubandakanya nezinombolo eziphuthumayo ngaphandle kokugammbukela. zinsiza ezinobungozi zingafaka izingcingo ezingenasiidngo nezingekho emthethweni esevisini ephuthumayo."</string>
+    <string name="permdesc_callPrivileged" msgid="1689024901509996810">"Ivumela insiza ukuth ishayele noma iyiphi inombolo okubandakanya nezinombolo eziphuthumayo ngaphandle kokugammbukela. zinsiza ezinobungozi zingafaka izingcingo ezingenasiidngo nezingekho emthethweni esevisini ephuthumayo."</string>
     <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"ngokuqondile qalisa ukumisa ithebhulethi nge-CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"ngokuqondile qalisa ukumisa ifoni nge-CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Ivumela insiza ukuqalisa amalungiselelo e-CDMA. Izinsiza ezinobungozi ingaqalisa amalungiselelo e-CDMA ngokungenasidingo."</string>
@@ -481,7 +540,7 @@
     <string name="permlab_createNetworkSockets" msgid="8018758136404323658">"ukufinyelela kwenethiwekhi okugcwele"</string>
     <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Ivumela uhlelo lokusebenza ukudala amasokethi enethiwekhi nokusebenzisa iziphakamiso eziyisisekelo zenethiwekhi yezifiso. Iziphequluli nezinye izinhlelo zokusebenza zinikela ngezindlela zokuthumela idatha ku-intanethi, ngakho-le le mvume ayidingekile ukuthumela idatha ku-intanethi."</string>
     <string name="permlab_writeApnSettings" msgid="505660159675751896">"shintsha/ngenelela izilungiselelo kanye nokuhamba kuhleloxhumano"</string>
-    <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"Ivumela insiza ukuthi iguqule izilungiselelo zenethiwekhi kanye nokunciphisa kanye nokuhlola konke ukuphithizela kwenethiwekhi, isibonelo ukushintsha i-proy kanye ne-port yanom iyiphi i-APN. Izinhlelo zokusebenza ezinobungozi zingabheka, zithumele kabusha noa ziguqule okuqukethwe enethiwekhini ngaphandle kokwazi kwakho."</string>
+    <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"Ivumela insiza ukuthi iguqule izilungiselelo zenethiwekhi kanye nokunciphisa kanye nokuhlola konke ukuphithizela kwenethiwekhi, isibonelo ukushintsha i-proy kanye ne-port yanom iyiphi i-APN. Izinhlelo zokusebenza ezinobungozi zingabheka, zithumele kabusha noma ziguqule okuqukethwe enethiwekhini ngaphandle kokwazi kwakho."</string>
     <string name="permlab_changeNetworkState" msgid="958884291454327309">"shintsha uxhumano lwenethiwekhi"</string>
     <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Ivumela insiza ukuthi iguqule isimo sokuxhuaniseka kwenethiwekhi."</string>
     <string name="permlab_changeTetherState" msgid="5952584964373017960">"Shintsha uxhumano lokusebenzisa njengemodemu"</string>
@@ -498,7 +557,7 @@
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"finyelela ezilungiselelweni ze-Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Ivumela uhlelo lokusebenza ukumisa ithebhulethi ye-Bluetooth yasendawni, nokuthola nokubhanqanisa namadivaysi okulawula okukude."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Ivumela uhlelo lokusebenza ukumisa ifoni ye-Bluetooth yasendawni, nokuthola nokubhanqanisa namadivaysi okulawula okukude."</string>
-    <string name="permlab_accessWimaxState" msgid="7436749103151096452">"Buka ukuxhumeka kwi-WiMAX"</string>
+    <string name="permlab_accessWimaxState" msgid="4195907010610205703">"xhuma futhi unqamule kusuka ku-WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Ivumela uhlelo lokusebenza ukucacisa ukuthi ingabe i-WiMAX inikwe amandla futhi ulwazi mayelana namanethiwekhi e-WiMAX axhunyiwe."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Shintsha isimo se-WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Ivumela uhlelo lokusebenza ukuxhuma ithebhulethi nokunqamula ithebhulethi kumanethiwekhi e-WiMAX."</string>
@@ -522,11 +581,11 @@
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Ivumela insiza ukuthi iguqule amafidi akho avumelanisiwe njengamanje. Izinsiza ezinobungozi zingaguqula amafidi akho avumelanisiwe."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"funda imibandela oyengezile esichazimazwini"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Ivumela uhlelo lokusebenza ukufunda onke amabizo, amagama, namatemu umsebenzisi awalondolozile kusichazamazwi somsebenzisi."</string>
-    <string name="permlab_writeDictionary" msgid="2296383164914812772">"bhala kwisichazamazwi esicacisiwe somsebenzisi"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"engeza amagama kusichazamazwi ezichazwe umsebenzisi"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Ivumela insiza ukuthi ibhale amagama amasha esichazinimazwi."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"ukufinyelela kokuhlola esilondolozini esivikelekile"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"ukufinyelela kokuhlola esilondolozini esivikelekile"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"Ivumela uhlelo lokusebenza ukuhlola imvume yokugciniwe okufinyeleleka nge-USB okuzotholakala kumadivayisi alandelayo."</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Ivumela uhlelo lokusebenza ukuhlola imvume yesitoreji se-USB okuzotholakala kumadivayisi alandelayo."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Ivumela uhlelo lokusebenza ukuhlola imvume yekhadi le-SD okuzotholakala kumadivayisi alandelayo."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"guqula noma ususe okuqukethwe kwakho okugciniwe okufinyeleleka nge-USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"shintsha noma ususe okuqukethwe ekhadini lakho le-SD"</string>
@@ -534,6 +593,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Ivumela insiza ukuthi ibhalele ekhadini le-SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"guqula/susa okuqukethwe kwisitoreji semidiya yangaphakathi"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Ivumela insiza ukuthi iguqule okuqukethwe kokulondoloza imidiya yangaphakathi."</string>
+    <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"ukufinyelela isilondolozi sangaphandle sabo bonke abasebenzisi"</string>
+    <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Vumela uhlelo lokusebenza ukufinyelela isilondolozi sangaphandle kubo bonke abasebenzisi."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"finyelela kunqolobane yesistimu yefayela"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Ivumela insiza ukuthi ifunde futhi ibhale isistimu yokufayila amafayela esikhashana."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"yena/thola amakholi e-Inthanethi"</string>
@@ -564,6 +625,8 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Idinga ukuthi idatha yohlelo lokusebenza olugciniwe ibethelwe"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Khubaza amakhamera"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Vimbela ukusetshenziswa kwamadivaysi wonke wamakhamera"</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Khubaza izici kokhiye abagadile"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Vikela ukusebenza kwezinye izici kokhiye abagadile."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Ekhaya"</item>
     <item msgid="869923650527136615">"Iselula"</item>
@@ -699,10 +762,10 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Zama futhi"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Ukuzama Kokuvula Ubuso Okuningi kudluliwe"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Iyashaja (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
-    <string name="lockscreen_charged" msgid="4938930459620989972">"Kushajiwe."</string>
+    <string name="lockscreen_charged" msgid="321635745684060624">"Kushajiwe"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Xhuma ishaja yakho."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Alikho ikhadi le-SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Alikho ikhadi le-SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Alikho ikhadi le-SIM efonini."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Alikho ikhadi le-SIM efonini."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Faka ikhadi le-SIM."</string>
@@ -747,6 +810,26 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Iphethini isusiwe"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Kwengezwe"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Iphethini isiphelile"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Engeza iwijethi."</string>
+    <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Akunalutho"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Indawo yokuvula inwetshisiwe."</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"Indawo yokuvula inciphisiwe."</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> iwijethi."</string>
+    <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Isikhethi somsebenzisi"</string>
+    <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Isimo"</string>
+    <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Ikhamera"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Izilawuli zemidiya"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Ukuhlelwa kabusha kwewijethi kuqalile"</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Ukuhlelwa kabusha kwewijethi kuphelile."</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Iwijethi <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> isusiwe."</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Nwebisa indawo yokuvula."</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Ukuvula ngokuslayida."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Ukuvula ngephethini."</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Vula ngobuso"</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Ukuvula ngephinikhodi."</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Ukuvula ngephasiwedi."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Indawo yephethini."</string>
+    <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Indawo yokushelelisa."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -930,8 +1013,8 @@
     <string name="copyUrl" msgid="2538211579596067402">"Kopisha i-URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"Khetha umbhalo"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Inketho yombhalo"</string>
-    <string name="addToDictionary" msgid="9090375111134433012">"Faka esichazinimazwi"</string>
-    <string name="deleteText" msgid="7070985395199629156">"susa"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"Engeza kwisichazamazwi"</string>
+    <string name="deleteText" msgid="6979668428458199034">"Susa"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Indlela yokufakwayo"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Izenzo zombhalo"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Isikhala sokulondoloza siyaphela"</string>
@@ -1011,7 +1094,8 @@
     <item quantity="other" msgid="7915895323644292768">"Vula amanethiwekhi we-Wi-Fi atholakalayo"</item>
   </plurals>
     <string name="wifi_available_sign_in" msgid="4029489716605255386">"Ngena enethiwekhini ye-Wi-Fi network"</string>
-    <!-- no translation found for wifi_available_sign_in_detailed (6797764740339907572) -->
+    <string name="network_available_sign_in" msgid="8495155593358054676">"Ngena ngemvume kunethiwekhi"</string>
+    <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ayikwazanga ukuxhuma kwi-Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" inoxhumano oluphansi lwe-inthanethi."</string>
@@ -1028,11 +1112,21 @@
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"Ku:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Faka i-PIN edingekayo:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Ifoni izonqamuka okwesikhashana ku-Wi-Fi ngenkathi ixhumeke ku-<xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Faka uhlamvu"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Ithumela imiyalezo ye-SMS"</string>
     <string name="sms_control_message" msgid="3867899169651496433">"I-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ithumela inombolo enkulu yemilayezo ye-SMS. Ufuna ukuvumela lolu hlelo lokusebenza ukuqhubeka ukuthumela imilayezo?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Vumela"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Nqaba"</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"I-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ingathanda ukuthumela umlayezo ku-&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
+    <string name="sms_short_code_details" msgid="3492025719868078457">"Lokhu "<font fgcolor="#ffffb060">"kungabangela amashaji"</font>" ku-akhawunti yakho yeselula."</string>
+    <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"Lokhu kuzobangela amashaji ku-akhawunti yakho yeselula."</font></string>
+    <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Thumela"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Khansela"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Khumbula inketho yami"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Ungashintsha lokhu kamuva kuzilungiselelo &gt; izinhlelo zokusebenza"</string>
+    <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Vumela njalo?"</string>
+    <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Ungavumeli"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Ikhadi le-SIM likhishiwe"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"Inethiwekhi yeselula ngeke itholakale kuwena kuze kube uqala kabusha ufake ikhadi le-SIM elifanele."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Kwenziwe"</string>
@@ -1043,12 +1137,10 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setha idethi"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Hlela"</string>
     <string name="date_time_done" msgid="2507683751759308828">"Kwenziwe"</string>
-    <string name="default_permission_group" msgid="2690160991405646128">"Okuzenzakalelayo"</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Ayikho imvume edingekayo"</string>
-    <string name="perms_hide" msgid="7283915391320676226"><b>"Fihla "</b></string>
-    <string name="perms_show_all" msgid="2671791163933091180"><b>"Bonisa konke"</b></string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"OKUSHA: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"OKUSHA: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Inikelwe yi-<xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Ayikho imvume edingekayo"</string>
+    <string name="perm_costs_money" msgid="4902470324142151116">"lokhu kungakudlela imali"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Isitoreji Esikhulu se-USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"I-USB ixhunyiwe"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Uxhumeke kwikhompyutha yakho nge-USB. Thinta inkinobho engenzansi uma ufuna ukukopisha amafayela phakathi kwekhompyutha yakho nokugcina nge-Android USB yakho."</string>
@@ -1147,6 +1239,10 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"i-VPN ivuswe ngu <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Thinta ukuze wengamele inethiwekhi."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Ixhumeke ku-.<xliff:g id="SESSION">%s</xliff:g> Thinta ukuze ulawule inethiwekhi."</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"I-VPN ehlala ikhanya iyaxhuma…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"I-VPN ehlala ikhanya ixhunyiwe"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Iphutha le-VPN ehlala ikhanya"</string>
+    <string name="vpn_lockdown_reset" msgid="5365010427963548932">"Thinta ukuze usethe kabusha ukuxhuma"</string>
     <string name="upload_file" msgid="2897957172366730416">"Khetha ifayela"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Ayikho ifayela ekhethiwe"</string>
     <string name="reset" msgid="2448168080964209908">"Setha kabusha"</string>
@@ -1185,6 +1281,8 @@
     <string name="share" msgid="1778686618230011964">"Yabelana"</string>
     <string name="find" msgid="4808270900322985960">"Thola"</string>
     <string name="websearch" msgid="4337157977400211589">"USesho lweWebhu"</string>
+    <string name="find_next" msgid="5742124618942193978">"Thola okulandelayo"</string>
+    <string name="find_previous" msgid="2196723669388360506">"Thola kwangaphambilini"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Isicelo sendawo esiphuma ku-<xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Isicelo sendawo"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"Icelwe ngu-:<xliff:g id="NAME">%1$s</xliff:g><xliff:g id="SERVICE">%2$s</xliff:g>"</string>
@@ -1286,8 +1384,64 @@
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Ifoni"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Ama-headphone"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Izipikha ze-Dock"</string>
-    <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"Umsindo we-HDMI"</string>
+    <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Isistimu"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Umsindo we-Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Qedile"</string>
+    <string name="media_route_button_content_description" msgid="5758553567065145276">"Okukhiphayo kwemidiya"</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"Iyaskena..."</string>
+    <string name="media_route_status_connecting" msgid="6422571716007825440">"Iyaxhuma..."</string>
+    <string name="media_route_status_available" msgid="6983258067194649391">"Kuyatholakala"</string>
+    <string name="media_route_status_not_available" msgid="6739899962681886401">"Ayitholakali"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Okwakhelwe ngaphakathi kwesikrini"</string>
+    <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Isikrini se-HDMI"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Isendlalelo #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
+    <string name="wifi_display_notification_title" msgid="2223050649240326557">"Ukubukeka okungenantambo kuxhunyiwe"</string>
+    <string name="wifi_display_notification_message" msgid="4498802012464170685">"Lesi sikrini siyabonakala kwenye idivayisi"</string>
+    <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Nqamula"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Ucingo lwezimo eziphuthumayo"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Ukhohlwe iphethini?"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Iphatheni engalungile"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Iphasiwedi engalungile"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"Iphinikhodi engalungile"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Zama futhi emasekhondini angu-<xliff:g id="NUMBER">%d</xliff:g>."</string>
+    <string name="kg_pattern_instructions" msgid="398978611683075868">"Dweba iphethini"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Faka iphinikhodi ye-SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Faka iphinikhodi"</string>
+    <string name="kg_password_instructions" msgid="5753646556186936819">"Faka iphasiwedi"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"I-SIM manje ikhutshaziwe. Faka ikhodi ye-PUK ukuze uqhubeke. Xhumana nenkampani yenethiwekhi ngemininingwane."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Faka iphinikhodi oyithandayo"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Qiniseka iphinikhodi oyithandayo"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Ivula ikhadi le-SIM..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Iphinikhodi engalungile."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Thayipha iphinikhodi enezinombolo ezingu-4 kuya kwezingu-8."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Ikhodi ye-PUK kufanele ibe yizinombolo ezingu-8 noma eziningi."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Faka kabusha ikhodi ye-PUK elungile. Imizamo ephindiwe izokhubaza unaphakade i-SIM."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Iphinikhodi ayifani"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Kunemizamo eminingi kakhulu yephathini"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Ukuvula, ngena ngemvume kwi-akhawunti ye-Google"</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Igama lomsebenzisi (i-imeyli)"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"Iphasiwedi"</string>
+    <string name="kg_login_submit_button" msgid="5355904582674054702">"Ngena ngemvume"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"Igama lomsebezisi elingalungile noma iphasiwedi."</string>
+    <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Ukhohlwe igama lomsebenzisi noma iphasiwedi?"\n"Vakashela"<b>"google.com/accounts/recovery"</b></string>
+    <string name="kg_login_checking_password" msgid="1052685197710252395">"Ukuhlola i-akhawunti…"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Ubhale iphinikhodi ykho ngendlela engafanele izikhathi ezingu-<xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n"Zama futhi emasekhondini angu-<xliff:g id="NUMBER_1">%d</xliff:g>."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Ubhale iphasiwedi yakho ngendlela engafanele <xliff:g id="NUMBER_0">%d</xliff:g> izikhathi. "\n\n"Zama futhi emasekhondini angu-<xliff:g id="NUMBER_1">%d</xliff:g>."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Udwebe iphathini yakho yokuvula ngendlela engafanele-<xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n" Zama futhi emasekhondini angu-<xliff:g id="NUMBER_1">%d</xliff:g>"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Uzame ngokusebenzisa indlela engafanele ukuvula ithebhulethi izikhathi ezingu-<xliff:g id="NUMBER_0">%d</xliff:g>. Ngemuva kokuzama ngaphandle kwempumelelo okungu-<xliff:g id="NUMBER_1">%d</xliff:g>, ithebhulethi izobuyiselwa kwizimiso zasembonini futhi yonke imininingwane yomsebenzisi izolahleka."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Uzame ngokusebenzisa indlela engafanele ukuvula ifoni izikhathi ezingu-<xliff:g id="NUMBER_0">%d</xliff:g>. Ngemuva kokuzama ngaphandle kwempumelelo okungu-<xliff:g id="NUMBER_1">%d</xliff:g>, ifoni izobuyiselwa kwizimiso zasembonini futhi yonke imininingwane yomsebenzisi izolahleka."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Uzame ukuvula ngendlela engafanele ifoni izikhathi ezingu-<xliff:g id="NUMBER">%d</xliff:g>. Ithebhulethi manje isizosethwa kabusha ibe yizimiso ezizenzakalelayo."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Uzame ukuvula ngendlela engafanele ifoni izikhathi ezingu-<xliff:g id="NUMBER">%d</xliff:g>. Ifoni manje isizosethwa kabusha ibe yizimiso ezizenzakalelayo."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Udwebe ngokungalungile iphathini yakho yokuvula izikhathi ezingu-<xliff:g id="NUMBER_0">%d</xliff:g>. Emva <xliff:g id="NUMBER_1">%d</xliff:g> kweminye imizamo engaphumelelanga, uzocelwa ukuvula ithebhulethi yakho usebenzisa ukungena ngemvume kwi-Google."\n\n" Sicela uzame futhi kwengu-<xliff:g id="NUMBER_2">%d</xliff:g> imizuzwana."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Ukulayisha ungenisa iphathini yakho yokuvula ngendlela engalungile izikhathi ezi-<xliff:g id="NUMBER_0">%d</xliff:g> Emva kweminye imizamo engu-<xliff:g id="NUMBER_1">%d</xliff:g>, uzocelwa ukuvula ifoni yakho usebenzisa ukungena ngemvume ku-Google"\n\n" Zame futhi emumva kwengu- <xliff:g id="NUMBER_2">%d</xliff:g> imizuzwana."</string>
+    <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
+    <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Susa"</string>
+    <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Khulisa ivolomu ngaphezu kweleveli yokuphepha?"\n"Ukulalela ngevolomu ephezulu izikhathi ezide kungalimaza ukuzwa kwakho."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Gcina ucindezele iminwe yakho emibili ukuze unike amandla ukufinyelela."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Ukufinyelela kunikwe amandla."</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Ukufinyelela kukhanseliwe."</string>
+    <string name="user_switched" msgid="3768006783166984410">"Umsebenzisi wamanje <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="owner_name" msgid="2716755460376028154">"Umnikazi"</string>
 </resources>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index b425ad7..1e966f7 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -242,8 +242,6 @@
        <item>@drawable/list_divider_holo_dark</item>
        <item>@drawable/list_divider_holo_light</item>
        <item>@drawable/list_divider_holo_light</item>
-       <item>@drawable/ic_lockscreen_chevron_left</item>
-       <item>@drawable/ic_lockscreen_chevron_right</item>
        <item>@drawable/ab_transparent_dark_holo</item>
        <item>@drawable/ab_stacked_transparent_dark_holo</item>
        <item>@drawable/ab_bottom_transparent_dark_holo</item>
@@ -400,11 +398,25 @@
         <item>@null</item>
     </array>
 
-    <array name="lockscreen_chevron_drawables">
-        <item>@drawable/ic_lockscreen_chevron_right</item>
-        <item>@null</item>
-        <item>@null</item>
-        <item>@null</item>
+    <array name="lockscreen_targets_unlock_only">
+        <item>@*android:drawable/ic_lockscreen_unlock</item>
     </array>
 
+    <array name="lockscreen_target_descriptions_unlock_only">
+        <item>@*android:string/description_target_unlock</item>
+    </array>
+
+    <!-- list of 3- or 4-letter mnemonics for a 10-key numeric keypad -->
+    <string-array translatable="false" name="lockscreen_num_pad_klondike">
+        <item></item><!-- 0 -->
+        <item></item><!-- 1 -->
+        <item>ABC</item><!-- 2 -->
+        <item>DEF</item><!-- 3 -->
+        <item>GHI</item><!-- 4 -->
+        <item>JKL</item><!-- 5 -->
+        <item>MNO</item><!-- 6 -->
+        <item>PQRS</item><!-- 7 -->
+        <item>TUV</item><!-- 8 -->
+        <item>WXYZ</item><!-- 9 -->
+    </string-array>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index aa8b643..447daab 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -275,6 +275,11 @@
         <!-- The preferred item height for dropdown lists. -->
         <attr name="dropdownListPreferredItemHeight" format="dimension" />
 
+        <!-- The preferred padding along the start edge of list items. -->
+        <attr name="listPreferredItemPaddingStart" format="dimension" />
+        <!-- The preferred padding along the end edge of list items. -->
+        <attr name="listPreferredItemPaddingEnd" format="dimension" />
+
         <!-- ============= -->
         <!-- Window styles -->
         <!-- ============= -->
@@ -478,6 +483,8 @@
         <attr name="autoCompleteTextViewStyle" format="reference" />
         <!-- Default Checkbox style. -->
         <attr name="checkboxStyle" format="reference" />
+        <!-- Default CheckedTextView style. -->
+        <attr name="checkedTextViewStyle" format="reference" />
         <!-- Default ListView style for drop downs. -->
         <attr name="dropDownListViewStyle" format="reference" />
         <!-- Default EditText style. -->
@@ -763,11 +770,15 @@
         <attr name="dialogCustomTitleDecorLayout" format="reference" />
         <!-- Window decor layout to use in dialog mode with title only -->
         <attr name="dialogTitleDecorLayout" format="reference" />
+
         <!-- Theme to use for alert dialogs spawned from this theme. -->
         <attr name="alertDialogTheme" format="reference" />
         <!-- Icon drawable to use for alerts -->
         <attr name="alertDialogIcon" format="reference" />
 
+        <!-- Theme to use for presentations spawned from this theme. -->
+        <attr name="presentationTheme" format="reference" />
+
         <!-- Drawable to use for generic vertical dividers. -->
         <attr name="dividerVertical" format="reference" />
 
@@ -1186,8 +1197,8 @@
     <!-- A coordinate in the Y dimension. -->
     <attr name="y" format="dimension" />
 
-    <!-- Specifies how to place the content of an object, both
-         on the x- and y-axis, within the object itself. -->
+    <!-- Specifies how an object should position its content, on both the X and Y axes,
+         within its own bounds.  -->
     <attr name="gravity">
         <!-- Push object to the top of its container, not changing its size. -->
         <flag name="top" value="0x30" />
@@ -1246,8 +1257,8 @@
     <!-- Reference to an array resource that will populate a list/adapter. -->
     <attr name="entries" format="reference" />
 
-    <!-- Standard gravity constant that a child can supply to its parent.
-         Defines how to place the view, both its x- and y-axis, within its parent view group. -->
+    <!-- Standard gravity constant that a child supplies to its parent.
+         Defines how the child view should be positioned, on both the X and Y axes, within its enclosing layout. -->
     <attr name="layout_gravity">
         <!-- Push object to the top of its container, not changing its size. -->
         <flag name="top" value="0x30" />
@@ -2154,39 +2165,11 @@
             <enum name="no" value="2" />
         </attr>
 
-        <!-- @hide Controls whether this view can take accessibility focus. -->
-        <attr name="accessibilityFocusable" format="integer">
-            <!-- The system determines whether the view can take accessibility focus - default
-                 (recommended).
-                 <p>
-                 Such a view is consideted by the focus search if it is:
-                 <ul>
-                 <li>
-                 Important for accessibility and actionable (clickable, long clickable, focusable)
-                 </li>
-                 <li>
-                 Important for accessibility, not actionable (clickable, long clickable, focusable),
-                 and does not have an actionable predecessor.
-                 </li>
-                 </ul>
-                 An accessibility srvice can request putting accessibility focus on such a view.
-                 </p> -->
-            <enum name="auto" value="0" />
-            <!-- The view can take accessibility focus.
-                 <p>
-                 A view that can take accessibility focus is always considered during focus
-                 search and an accessibility service can request putting accessibility focus
-                 on it.
-                 </p> -->
-            <enum name="yes" value="1" />
-            <!-- The view can not take accessibility focus.
-                 <p>
-                 A view that can not take accessibility focus is never considered during focus
-                 search and an accessibility service can not request putting accessibility focus
-                 on it.
-                 </p> -->
-            <enum name="no" value="2" />
-        </attr>
+        <!-- Specifies the id of a view for which this view serves as a label for
+             accessibility purposes. For example, a TextView before an EditText in
+             the UI usually specifies what infomation is contained in the EditText.
+             Hence, the TextView is a label for the EditText. -->
+        <attr name="labelFor" format="integer" />
 
     </declare-styleable>
 
@@ -2399,6 +2382,12 @@
         <!-- The extra value of the subtype. This string can be any string and will be passed to
              the IME when the framework calls the IME with the subtype.  -->
         <attr name="imeSubtypeExtraValue" format="string" />
+        <!-- The unique id for the subtype. The input method framework keeps track of enabled
+             subtypes by ID. When the IME package gets upgraded, enabled IDs will stay enabled even
+             if other attributes are different. If the ID is unspecified (by calling the other
+             constructor or 0. Arrays.hashCode(new Object[] {locale, mode, extraValue,
+             isAuxiliary, overridesImplicitlyEnabledSubtype}) will be used instead. -->
+        <attr name="subtypeId" format="integer"/>
     </declare-styleable>
 
     <!-- Use <code>spell-checker</code> as the root tag of the XML resource that
@@ -3057,6 +3046,24 @@
         <!-- Present the text in ALL CAPS. This may use a small-caps form when available. -->
         <attr name="textAllCaps" format="boolean" />
     </declare-styleable>
+    <declare-styleable name="TextClock">
+        <!-- Specifies the formatting pattern used to show the time and/or date
+             in 12-hour mode. Please refer to {@link android.text.format.DateFormat}
+             for a complete description of accepted formatting patterns.
+             The default pattern is "h:mm aa". -->
+        <attr name="format12Hour" format="string"/>
+        <!-- Specifies the formatting pattern used to show the time and/or date
+             in 24-hour mode. Please refer to {@link android.text.format.DateFormat}
+             for a complete description of accepted formatting patterns.
+             The default pattern is "k:mm". -->
+        <attr name="format24Hour" format="string"/>
+        <!-- Specifies the time zone to use. When this attribute is specified, the
+             TextClock will ignore the time zone of the system. To use the user's
+             time zone, do not specify this attribute. The default value is the
+             user's time zone. Please refer to {@link java.util.TimeZone} for more
+             information about time zone ids. -->
+        <attr name="timeZone" format="string"/>
+    </declare-styleable>
     <declare-styleable name="TextSwitcher">
     </declare-styleable>
     <declare-styleable name="TextView">
@@ -3668,6 +3675,24 @@
         <!-- If set to true, the parent will be used as the anchor when the anchor cannot be
              be found for layout_toLeftOf, layout_toRightOf, etc. -->
         <attr name="layout_alignWithParentIfMissing" format="boolean" />
+        <!-- Positions the end edge of this view to the start of the given anchor view ID.
+             Accommodates end margin of this view and start margin of anchor view. -->
+        <attr name="layout_toStartOf" format="reference" />
+        <!-- Positions the start edge of this view to the end of the given anchor view ID.
+             Accommodates start margin of this view and end margin of anchor view. -->
+        <attr name="layout_toEndOf" format="reference" />
+        <!-- Makes the start edge of this view match the start edge of the given anchor view ID.
+            Accommodates start margin. -->
+        <attr name="layout_alignStart" format="reference" />
+        <!-- Makes the end edge of this view match the end edge of the given anchor view ID.
+            Accommodates end margin. -->
+        <attr name="layout_alignEnd" format="reference" />
+        <!-- If true, makes the start edge of this view match the start edge of the parent.
+            Accommodates start margin. -->
+        <attr name="layout_alignParentStart" format="boolean" />
+        <!-- If true, makes the end edge of this view match the end edge of the parent.
+            Accommodates end margin. -->
+        <attr name="layout_alignParentEnd" format="boolean" />
     </declare-styleable>
     <declare-styleable name="VerticalSlider_Layout">
         <attr name="layout_scale" format="float" />
@@ -4080,6 +4105,10 @@
                  The clip will be based on the horizontal gravity: a left gravity will clip the right
                  edge, a right gravity will clip the left edge, and neither will clip both edges. -->
             <flag name="clip_horizontal" value="0x08" />
+            <!-- Push object to the beginning of its container, not changing its size. -->
+            <flag name="start" value="0x00800003" />
+            <!-- Push object to the end of its container, not changing its size. -->
+            <flag name="end" value="0x00800005" />
         </attr>
         <!-- Reference to a drawable resource to draw with the specified scale. -->
         <attr name="drawable" />
@@ -5177,6 +5206,8 @@
         <attr name="updatePeriodMillis" format="integer" />
         <!-- A resource id of a layout. -->
         <attr name="initialLayout" format="reference" />
+        <!-- A resource id of a layout. -->
+        <attr name="initialKeyguardLayout" format="reference" />
         <!-- A class name in the AppWidget's package to be launched to configure.
              If not supplied, then no activity will be launched. -->
         <attr name="configure" format="string" />
@@ -5187,12 +5218,19 @@
              by the widget's host. -->
         <attr name="autoAdvanceViewId" format="reference" />
         <!-- Optional parameter which indicates if and how this widget can be
-             resized. -->
+             resized. Supports combined values using | operator. -->
         <attr name="resizeMode" format="integer">
             <flag name="none" value="0x0" />
             <flag name="horizontal" value="0x1" />
             <flag name="vertical" value="0x2" />
         </attr>
+        <!-- Optional parameter which indicates where this widget can be shown,
+             ie. home screen, keyguard or both.
+             resized. Supports combined values using | operator. -->
+        <attr name="widgetCategory" format="integer">
+            <flag name="home_screen" value="0x1" />
+            <flag name="keyguard" value="0x2" />
+        </attr>
     </declare-styleable>
 
     <!-- =============================== -->
@@ -5280,6 +5318,19 @@
         <attr name="description" />
     </declare-styleable>
 
+    <!-- Use <code>dream</code> as the root tag of the XML resource that
+         describes an
+         {@link android.service.dreams.DreamService}, which is
+         referenced from its
+         {@link android.service.dreams.DreamService#DREAM_META_DATA}
+         meta-data entry.  Described here are the attributes that can be
+         included in that tag. -->
+    <declare-styleable name="Dream">
+        <!-- Component name of an activity that allows the user to modify
+             the settings for this dream. -->
+        <attr name="settingsActivity" />
+    </declare-styleable>
+
     <!-- =============================== -->
     <!-- Accounts package class attributes -->
     <!-- =============================== -->
@@ -5425,6 +5476,19 @@
 
         <!-- Used when the handle shouldn't wait to be hit before following the finger -->
         <attr name="alwaysTrackFinger"/>
+
+        <!-- Location along the circle of the first item, in degrees.-->
+        <attr name="firstItemOffset" format="float" />
+
+        <!-- Causes targets to snap to the finger location on activation. -->
+        <attr name="magneticTargets" format="boolean" />
+
+        <attr name="gravity" />
+
+        <!-- Determine whether the glow pad is allowed to scale to fit the bounds indicated
+            by its parent. If this is set to false, no scaling will occur. If this is set to true
+            scaling will occur to fit for any axis in which gravity is set to center. -->
+        <attr name="allowScaling" format="boolean" />
     </declare-styleable>
 
     <!-- =============================== -->
@@ -5513,6 +5577,7 @@
         </attr>
         <!-- Options affecting how the action bar is displayed. -->
         <attr name="displayOptions">
+            <flag name="none" value="0" />
             <flag name="useLogo" value="0x1" />
             <flag name="showHome" value="0x2" />
             <flag name="homeAsUp" value="0x4" />
@@ -5716,4 +5781,83 @@
         <attr name="minHeight" />
     </declare-styleable>
 
+    <!-- PagedView specific attributes. These attributes are used to customize
+         a PagedView view in XML files. -->
+    <declare-styleable name="PagedView">
+        <!-- The space between adjacent pages of the PagedView. -->
+        <attr name="pageSpacing" format="dimension" />
+        <!-- The padding for the scroll indicator area -->
+        <attr name="scrollIndicatorPaddingLeft" format="dimension" />
+        <attr name="scrollIndicatorPaddingRight" format="dimension" />
+    </declare-styleable>
+
+    <declare-styleable name="KeyguardGlowStripView">
+        <attr name="dotSize" format="dimension" />
+        <attr name="numDots" format="integer" />
+        <attr name="glowDot" format="reference" />
+        <attr name="leftToRight" format="boolean" />
+    </declare-styleable>
+
+    <!-- Some child types have special behavior. -->
+    <attr name="layout_childType">
+        <!-- No special behavior. Layout will proceed as normal. -->
+        <enum name="none" value="0" />
+        <!-- Widget container.
+             This will be resized in response to certain events. -->
+        <enum name="widget" value="1" />
+        <!-- Security challenge container.
+             This will be dismissed/shown in response to certain events,
+             possibly obscuring widget elements. -->
+        <enum name="challenge" value="2" />
+        <!-- User switcher.
+             This will consume space from the total layout area. -->
+        <enum name="userSwitcher" value="3" />
+        <!-- Scrim. This will block access to child views that
+             come before it in the child list in bouncer mode. -->
+        <enum name="scrim" value="4" />
+        <!-- The home for widgets. All widgets will be descendents of this. -->
+        <enum name="widgets" value="5" />
+        <!-- This is a handle that is used for expanding the
+             security challenge container when it is collapsed. -->
+        <enum name="expandChallengeHandle" value="6" />
+        <!-- Delete drop target.  This will be the drop target to delete pages. -->
+        <enum name="pageDeleteDropTarget" value="7" />
+    </attr>
+
+    <declare-styleable name="SlidingChallengeLayout_Layout">
+        <attr name="layout_childType" />
+        <attr name="layout_maxHeight" />
+    </declare-styleable>
+
+    <!-- Attributes that can be used with <code>&lt;FragmentBreadCrumbs&gt;</code>
+    tags. -->
+    <declare-styleable name="FragmentBreadCrumbs">
+        <attr name="gravity" />
+    </declare-styleable>
+
+    <declare-styleable name="MultiPaneChallengeLayout">
+        <!-- Influences how layout_centerWithinArea behaves -->
+        <attr name="orientation" />
+    </declare-styleable>
+
+    <declare-styleable name="MultiPaneChallengeLayout_Layout">
+        <!-- Percentage of the screen this child should consume or center within.
+             If 0/default, the view will be measured by standard rules
+             as if this were a FrameLayout. -->
+        <attr name="layout_centerWithinArea" format="float" />
+        <attr name="layout_childType" />
+        <attr name="layout_gravity" />
+        <attr name="layout_maxWidth" format="dimension" />
+        <attr name="layout_maxHeight" />
+    </declare-styleable>
+
+    <declare-styleable name="KeyguardSecurityViewFlipper_Layout">
+        <attr name="layout_maxWidth" />
+        <attr name="layout_maxHeight" />
+    </declare-styleable>
+
+    <declare-styleable name="NumPadKey">
+        <attr name="digit" format="integer" />
+        <attr name="textView" format="reference" />
+    </declare-styleable>
 </resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index f971d39..d899e9d 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -199,7 +199,7 @@
         <flag name="development" value="0x20" />
     </attr>
 
-    <!-- Flags indicating more context for a permission group. @hide -->
+    <!-- Flags indicating more context for a permission group. -->
     <attr name="permissionGroupFlags">
         <!-- Set to indicate that this permission group contains permissions
              protecting access to some information that is considered
@@ -207,6 +207,14 @@
         <flag name="personalInfo" value="0x0001" />
     </attr>
 
+    <!-- Flags indicating more context for a permission. -->
+    <attr name="permissionFlags">
+        <!-- Set to indicate that this permission allows an operation that
+             may cost the user money.  Such permissions may be highlighted
+             when shown to the user with this additional information.  -->
+        <flag name="costsMoney" value="0x0001" />
+    </attr>
+
     <!-- Specified the name of a group that this permission is associated
          with.  The group must have been defined with the
          {@link android.R.styleable#AndroidManifestPermissionGroup permission-group} tag. -->
@@ -284,7 +292,20 @@
          who do not know their particular component name) and for all
          content providers. -->
     <attr name="exported" format="boolean" />
-    
+
+    <!-- If set to true, a single instance of this component will run for
+         all users.  That instance will run as user 0, the default/primary
+         user.  When the app running is in processes for other users and interacts
+         with this component (by binding to a service for example) those processes will
+         always interact with the instance running for user 0.  Enabling
+         single user mode forces "exported" of the component to be false, to
+         help avoid introducing multi-user security bugs.  This feature is only
+         available to applications built in to the system image; you must hold the
+         permission INTERACT_ACROSS_USERS in order
+         to use this feature.  This flag can only be used with services,
+         receivers, and providers; it can not be used with activities. -->
+    <attr name="singleUser" format="boolean" />
+
     <!-- Specify a specific process that the associated code is to run in.
          Use with the application tag (to supply a default process for all
          application components), or with the activity, receiver, service,
@@ -423,6 +444,10 @@
          recently launched activities. -->
     <attr name="excludeFromRecents" format="boolean" />
 
+    <!-- Specify that an Activity should be shown over the lock screen and,
+         in a multiuser environment, across all users' windows -->
+    <attr name="showOnLockScreen" format="boolean" />
+
     <!-- Specify the authorities under which this content provider can be
          found.  Multiple authorities may be supplied by separating them
          with a semicolon.  Authority names should use a Java-style naming
@@ -627,6 +652,8 @@
              physical screen size has changed such as switching to an external
              display. -->
         <flag name="smallestScreenSize" value="0x0800" />
+        <!-- The layout direction has changed. For example going from LTR to RTL. -->
+        <flag name="layoutDirection" value="0x2000" />
         <!-- The font scaling factor has changed, that is the user has
              selected a new global font size. -->
         <flag name="fontScale" value="0x40000000" />
@@ -685,11 +712,11 @@
          backup and restore of the application's data on external storage. -->
     <attr name="backupAgent" format="string" />
 
-    <!-- Whether to allow the application to participate in backup
-         infrastructure.  If this attribute is set to <code>false</code>, no backup
-         of the application will ever be performed, even by a full-system backup that
-         would otherwise cause all application data to be saved via adb.  The
-         default value of this attribute is <code>true</code>. -->
+    <!-- Whether to allow the application to participate in the backup
+         and restore infrastructure.  If this attribute is set to <code>false</code>,
+         no backup or restore of the application will ever be performed, even by a
+         full-system backup that would otherwise cause all application data to be saved
+         via adb.  The default value of this attribute is <code>true</code>. -->
     <attr name="allowBackup" format="boolean" />
 
     <!-- Whether the application in question should be terminated after its
@@ -880,6 +907,7 @@
         <attr name="permissionGroup" />
         <attr name="description" />
         <attr name="protectionLevel" />
+        <attr name="permissionFlags" />
     </declare-styleable>
     
     <!-- The <code>permission-group</code> tag declares a logical grouping of
@@ -903,6 +931,7 @@
         <attr name="icon" />
         <attr name="logo" />
         <attr name="description" />
+        <attr name="permissionGroupFlags" />
         <attr name="priority" />
     </declare-styleable>
     
@@ -1194,6 +1223,7 @@
              component specific values). -->
         <attr name="enabled" />
         <attr name="exported" />
+        <attr name="singleUser" />
     </declare-styleable>
     
     <!-- Attributes that can be supplied in an AndroidManifest.xml
@@ -1275,6 +1305,7 @@
              that is isolated from the rest of the system.  The only communication
              with it is through the Service API (binding and starting). -->
         <attr name="isolatedProcess" format="boolean" />
+        <attr name="singleUser" />
     </declare-styleable>
     
     <!-- The <code>receiver</code> tag declares an
@@ -1308,8 +1339,9 @@
              component specific values). -->
         <attr name="enabled" />
         <attr name="exported" />
+        <attr name="singleUser" />
     </declare-styleable>
-    
+
     <!-- The <code>activity</code> tag declares an
          {@link android.app.Activity} class that is available
          as part of the package's application components, implementing
@@ -1348,6 +1380,7 @@
         <attr name="alwaysRetainTaskState" />
         <attr name="stateNotNeeded" />
         <attr name="excludeFromRecents" />
+        <attr name="showOnLockScreen" />
         <!-- Specify whether the activity is enabled or not (that is, can be instantiated by the system).
              It can also be specified for an application as a whole, in which case a value of "false"
              will override any component specific values (a value of "true" will not override the
@@ -1362,6 +1395,10 @@
         <attr name="hardwareAccelerated" />
         <attr name="uiOptions" />
         <attr name="parentActivityName" />
+        <attr name="singleUser" />
+        <!-- @hide This broacast receiver will only receive broadcasts for the
+             primary user.  Can only be used with receivers. -->
+        <attr name="primaryUserOnly" format="boolean" />
     </declare-styleable>
     
     <!-- The <code>activity-alias</code> tag declares a new
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index f9762b1..18e4f2f 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -15,6 +15,10 @@
 -->
 
 <resources>
+    <bool name="kg_enable_camera_default_widget">true</bool>
+    <bool name="kg_center_small_widgets_vertically">false</bool>
+    <bool name="kg_top_align_page_shrink_on_bouncer_visible">true</bool>
+    <bool name="kg_show_ime_at_screen_on">true</bool>
     <bool name="action_bar_embed_tabs">true</bool>
     <bool name="action_bar_embed_tabs_pre_jb">false</bool>
     <bool name="split_action_bar_is_narrow">true</bool>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 41f902f..604bf4b 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -18,8 +18,8 @@
 */
 -->
 <resources>
-      <drawable name="screen_background_light">#ffffffff</drawable>
-      <drawable name="screen_background_dark">#ff000000</drawable>
+    <drawable name="screen_background_light">#ffffffff</drawable>
+    <drawable name="screen_background_dark">#ff000000</drawable>
     <drawable name="status_bar_closed_default_background">#ff000000</drawable>
     <drawable name="status_bar_opened_default_background">#ff000000</drawable>
     <drawable name="notification_item_background_color">#ff111111</drawable>
@@ -90,7 +90,8 @@
     <color name="perms_dangerous_grp_color">#33b5e5</color>
     <color name="perms_dangerous_perm_color">#33b5e5</color>
     <color name="shadow">#cc222222</color>
-
+    <color name="perms_costs_money">#ffffbb33</color>
+    
     <!-- For search-related UIs -->
     <color name="search_url_text_normal">#7fa87f</color>
     <color name="search_url_text_selected">@android:color/black</color>
@@ -114,6 +115,11 @@
     <color name="lockscreen_clock_am_pm">#ffffffff</color>
     <color name="lockscreen_owner_info">#ff9a9a9a</color>
 
+    <!-- keyguard overscroll widget pager -->
+    <color name="kg_multi_user_text_active">#ffffffff</color>
+    <color name="kg_multi_user_text_inactive">#ff808080</color>
+    <color name="kg_widget_pager_gradient">#ffffffff</color>
+
     <!-- FaceLock -->
     <color name="facelock_spotlight_mask">#CC000000</color>
 
@@ -184,5 +190,10 @@
     <drawable name="notification_template_icon_bg">#3333B5E5</drawable>
     <drawable name="notification_template_icon_low_bg">#0cffffff</drawable>
 
+    <!-- Keyguard colors -->
+    <color name="keyguard_avatar_frame_color">#ffffffff</color>
+    <color name="keyguard_avatar_frame_shadow_color">#80000000</color>
+    <color name="keyguard_avatar_nick_color">#ffffffff</color>
+    <color name="keyguard_avatar_frame_pressed_color">#ff35b5e5</color>
 </resources>
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4d54fd2..3b7d73a 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -65,6 +65,11 @@
          master volume stream and nothing else . -->
     <bool name="config_useMasterVolume">false</bool>
 
+    <!-- Flag indicating that the media framework should support playing of sounds on volume
+         key usage.  This adds noticeable additional overhead to volume key processing, so
+         is disableable for products for which it is irrelevant. -->
+    <bool name="config_useVolumeKeySounds">true</bool>
+
     <!-- Array of integer pairs controlling the rate at which the master volume changes
          in response to volume up and down key events.
          The first integer of each pair is compared against the current master volume
@@ -287,6 +292,9 @@
     <!-- Integer indicating wpa_supplicant scan interval in milliseconds -->
     <integer translatable="false" name="config_wifi_supplicant_scan_interval">15000</integer>
 
+    <!-- Integer indicating wpa_supplicant scan interval when p2p is connected in milliseconds -->
+    <integer translatable="false" name="config_wifi_scan_interval_p2p_connected">60000</integer>
+
     <!-- Integer indicating the framework scan interval in milliseconds. This is used in the scenario
          where the chipset does not support background scanning (config_wifi_background_scan_suport
          is false) to set up a periodic wake up scan so that the device can connect to a new access
@@ -396,6 +404,12 @@
     -->
     <integer name="config_longPressOnPowerBehavior">1</integer>
 
+    <!-- Package name for default keyguard appwidget [DO NOT TRANSLATE] -->
+    <string name="widget_default_package_name"></string>
+
+    <!-- Class name for default keyguard appwidget [DO NOT TRANSLATE] -->
+    <string name="widget_default_class_name"></string>
+
     <!-- Indicate whether the SD card is accessible without removing the battery. -->
     <bool name="config_batterySdCardAccessibility">false</bool>
 
@@ -466,6 +480,9 @@
          Also, the battery stats are flushed to disk when we hit this level.  -->
     <integer name="config_criticalBatteryWarningLevel">4</integer>
 
+    <!-- Shutdown if the battery temperature exceeds (this value * 0.1) Celsius. -->
+    <integer name="config_shutdownBatteryTemperature">680</integer>
+
     <!-- Display low battery warning when battery level dips to this value -->
     <!-- Display low battery warning when battery level dips to this value -->
     <integer name="config_lowBatteryWarningLevel">15</integer>
@@ -474,7 +491,7 @@
     <integer name="config_lowBatteryCloseWarningLevel">20</integer>
 
     <!-- Default color for notification LED. -->
-    <color name="config_defaultNotificationColor">#ff00ff00</color>
+    <color name="config_defaultNotificationColor">#ffffffff</color>
 
     <!-- Default LED on time for notification LED in milliseconds. -->
     <integer name="config_defaultNotificationLedOn">500</integer>
@@ -528,25 +545,49 @@
     <integer name="config_longPressOnHomeBehavior">2</integer>
 
     <!-- Array of light sensor LUX values to define our levels for auto backlight brightness support.
-         The N entries of this array define N + 1 zones as follows:
+         The N entries of this array define N + 1 control points as follows:
+         (1-based arrays)
 
-         Zone 0:        0 <= LUX < array[0]
-         Zone 1:        array[0] <= LUX < array[1]
+         Point 1:            (0, value[1]):             lux <= 0
+         Point 2:     (level[1], value[2]):  0        < lux <= level[1]
+         Point 3:     (level[2], value[3]):  level[2] < lux <= level[3]
          ...
-         Zone N:        array[N - 1] <= LUX < array[N]
-         Zone N + 1:    array[N] <= LUX < infinity
+         Point N+1: (level[N], value[N+1]):  level[N] < lux
+
+         The control points must be strictly increasing.  Each control point
+         corresponds to an entry in the brightness backlight values arrays.
+         For example, if LUX == level[1] (first element of the levels array)
+         then the brightness will be determined by value[2] (second element
+         of the brightness values array).
+
+         Spline interpolation is used to determine the auto-brightness
+         backlight values for LUX levels between these control points.
 
          Must be overridden in platform specific overlays -->
     <integer-array name="config_autoBrightnessLevels">
     </integer-array>
 
+    <!-- Minimum screen brightness setting allowed by the power manager.
+         The user is forbidden from setting the brightness below this level. -->
+    <integer name="config_screenBrightnessSettingMinimum">10</integer>
 
-    <!-- Minimum screen brightness allowed by the power manager. -->
-    <integer name="config_screenBrightnessDim">20</integer>
+    <!-- Maximum screen brightness allowed by the power manager.
+         The user is forbidden from setting the brightness above this level. -->
+    <integer name="config_screenBrightnessSettingMaximum">255</integer>
+
+    <!-- Default screen brightness setting.
+         Must be in the range specified by minimum and maximum. -->
+    <integer name="config_screenBrightnessSettingDefault">102</integer>
+
+    <!-- Screen brightness used to dim the screen when the user activity
+         timeout expires.  May be less than the minimum allowed brightness setting
+         that can be set by the user. -->
+    <integer name="config_screenBrightnessDim">10</integer>
 
     <!-- Array of output values for LCD backlight corresponding to the LUX values
          in the config_autoBrightnessLevels array.  This array should have size one greater
          than the size of the config_autoBrightnessLevels array.
+         The brightness values must be between 0 and 255 and be non-decreasing.
          This must be overridden in platform specific overlays -->
     <integer-array name="config_autoBrightnessLcdBacklightValues">
     </integer-array>
@@ -554,6 +595,7 @@
     <!-- Array of output values for button backlight corresponding to the LUX values
          in the config_autoBrightnessLevels array.  This array should have size one greater
          than the size of the config_autoBrightnessLevels array.
+         The brightness values must be between 0 and 255 and be non-decreasing.
          This must be overridden in platform specific overlays -->
     <integer-array name="config_autoBrightnessButtonBacklightValues">
     </integer-array>
@@ -561,6 +603,7 @@
     <!-- Array of output values for keyboard backlight corresponding to the LUX values
          in the config_autoBrightnessLevels array.  This array should have size one greater
          than the size of the config_autoBrightnessLevels array.
+         The brightness values must be between 0 and 255 and be non-decreasing.
          This must be overridden in platform specific overlays -->
     <integer-array name="config_autoBrightnessKeyboardBacklightValues">
     </integer-array>
@@ -587,11 +630,23 @@
     <!-- True if WallpaperService is enabled -->
     <bool name="config_enableWallpaperService">true</bool>
 
-    <!-- Package name providing network location support. -->
-    <string name="config_networkLocationProviderPackageName" translatable="false">@null</string>
-
-    <!-- Package name providing geocoder API support. -->
-    <string name="config_geocodeProviderPackageName" translatable="false">@null</string>
+    <!-- Package name(s) containing location provider support.
+         These packages can contain services implementing location providers,
+         such as the Geocode Provider, Network Location Provider, and
+         Fused Location Provider. They will each be searched for
+         service components implementing these providers.
+         It is strongly recommended that the packages explicitly named
+         below are on the system image, so that they will not map to
+         a 3rd party application.
+         The location framework also has support for installation
+         of new location providers at run-time. The new package does not
+         have to be explicitly listed here, however it must have a signature
+         that matches the signature of at least one package on this list.
+         -->
+    <string-array name="config_locationProviderPackageNames" translatable="false">
+        <!-- The standard AOSP fused location provider -->
+        <item>com.android.location.fused</item>
+    </string-array>
 
     <!-- Boolean indicating if current platform supports bluetooth SCO for off call
     use cases -->
@@ -601,9 +656,9 @@
          speech -->
     <bool name="config_bluetooth_wide_band_speech">true</bool>
 
-    <!-- Boolean indicating if current platform supports quick switch-on/off of
-         Bluetooth Module -->
-    <bool name="config_bluetooth_adapter_quick_switch">true</bool>
+    <!-- Boolean indicating if current platform need do one-time bluetooth address
+         re-validation -->
+    <bool name="config_bluetooth_address_validation">false</bool>
 
     <!-- The default data-use polling period. -->
     <integer name="config_datause_polling_period_sec">600</integer>
@@ -846,10 +901,16 @@
     <!-- Name of the wimax state tracker clas -->
     <string name="config_wimaxStateTrackerClassname" translatable="false"></string>
 
-    <!-- enable screen saver feature -->
-    <bool name="config_enableDreams">false</bool>
-    <!-- Name of screensaver components to look for if none has been chosen by the user -->
-    <string name="config_defaultDreamComponent" translatable="false">com.google.android.deskclock/com.android.deskclock.Screensaver</string>
+    <!-- Is the dreams feature supported? -->
+    <bool name="config_dreamsSupported">true</bool>
+    <!-- If supported, are dreams enabled? (by default) -->
+    <bool name="config_dreamsEnabledByDefault">true</bool>
+    <!-- If supported and enabled, are dreams activated when docked? (by default) -->
+    <bool name="config_dreamsActivatedOnDockByDefault">true</bool>
+    <!-- If supported and enabled, are dreams activated when asleep and charging? (by default) -->
+    <bool name="config_dreamsActivatedOnSleepByDefault">false</bool>
+    <!-- ComponentName of the default dream (Settings.Secure.SCREENSAVER_COMPONENT) -->
+    <string name="config_dreamsDefaultComponent">com.google.android.deskclock/com.android.deskclock.Screensaver</string>
 
     <!-- Base "touch slop" value used by ViewConfiguration as a
          movement threshold where scrolling should begin. -->
@@ -871,4 +932,72 @@
 
     <!-- The default value if the SyncStorageEngine should sync automatically or not -->
     <bool name="config_syncstorageengine_masterSyncAutomatically">true</bool>
+
+    <!--  Maximum number of supported users -->
+    <integer name="config_multiuserMaximumUsers">1</integer>
+
+    <!-- Minimum span needed to begin a touch scaling gesture.
+         If the span is equal to or greater than this size, a scaling gesture
+         will begin, where supported. (See android.view.ScaleGestureDetector)
+
+         This also takes into account the size of any active touch points.
+         Devices with screens that deviate too far from their assigned density
+         bucket should consider tuning this value in a device-specific overlay.
+         For best results, care should be taken such that this value remains
+         larger than the minimum reported touchMajor/touchMinor values
+         reported by the hardware. -->
+    <dimen name="config_minScalingSpan">27mm</dimen>
+
+    <!-- Minimum accepted value for touchMajor while scaling. This may be tuned
+         per-device in overlays. -->
+    <dimen name="config_minScalingTouchMajor">48dp</dimen>
+
+    <!-- Safe headphone volume index. When music stream volume is below this index
+    the SPL on headphone output is compliant to EN 60950 requirements for portable music
+    players. -->
+    <integer name="config_safe_media_volume_index">10</integer>
+
+    <!-- Whether WiFi display is supported by this device.
+         There are many prerequisites for this feature to work correctly.
+         Here are a few of them:
+         * The WiFi radio must support WiFi P2P.
+         * The WiFi radio must support concurrent connections to the WiFi display and
+           to an access point.
+         * The Audio Flinger audio_policy.conf file must specify a rule for the "r_submix"
+           remote submix module.  This module is used to record and stream system
+           audio output to the WiFi display encoder in the media server.
+         * The remote submix module "audio.r_submix.default" must be installed on the device.
+         * The device must be provisioned with HDCP keys (for protected content).
+    -->
+    <bool name="config_enableWifiDisplay">false</bool>
+
+    <!-- When true use the linux /dev/input/event subsystem to detect the switch changes
+         on the headphone/microphone jack. When false use the older uevent framework. -->
+    <bool name="config_useDevInputEventForAudioJack">false</bool>
+
+    <!-- Whether safe headphone volume is enabled or not (country specific). -->
+    <bool name="config_safe_media_volume_enabled">true</bool>
+
+    <!-- Set to true if the wifi display supports compositing content stored
+         in gralloc protected buffers.  For this to be true, there must exist
+         a protected hardware path for surface flinger to composite and send
+         protected buffers to the wifi display video encoder.
+
+         If this flag is false, we advise applications not to use protected
+         buffers (if possible) when presenting content to a wifi display because
+         the content may be blanked.
+
+         This flag controls whether the {@link Display#FLAG_SUPPORTS_PROTECTED_BUFFERS}
+         flag is set for wifi displays.
+    -->
+    <bool name="config_wifiDisplaySupportsProtectedBuffers">false</bool>
+
+    <!-- Whether camera shutter sound is forced or not  (country specific). -->
+    <bool name="config_camera_sound_forced">false</bool>
+
+    <!-- Set to true if we need to not prefer an APN.
+         This is being added to enable a simple scenario of pre-paid
+         provisioning on some carriers, working around a bug (7305641)
+         where if the preferred is used we don't try the others. -->
+    <bool name="config_dontPreferApn">false</bool>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index f30943a..637128a5 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -193,6 +193,9 @@
     <!-- Padding on left margin of PIN text entry field to center it when del button is showing -->
     <dimen name="keyguard_lockscreen_pin_margin_left">40dip</dimen>
 
+    <!-- Height of FaceUnlock view in keyguard -->
+    <dimen name="face_unlock_height">330dip</dimen>
+
     <!-- Minimum popup width for selecting an activity in ActivityChooserDialog/ActivityChooserView. -->
     <dimen name="activity_chooser_popup_min_width">200dip</dimen>
 
@@ -237,4 +240,104 @@
     <dimen name="notification_title_text_size">18dp</dimen>
     <!-- Size of smaller notification text (see TextAppearance.StatusBar.EventContent.Line2, Info, Time) -->
     <dimen name="notification_subtext_size">12dp</dimen>
+
+    <!-- Keyguard dimensions -->
+    <!-- TEMP -->
+    <dimen name="kg_security_panel_height">600dp</dimen>
+
+    <!-- Height of security view in keyguard. -->
+    <dimen name="kg_security_view_height">480dp</dimen>
+
+    <!-- Width of widget view in keyguard. -->
+    <dimen name="kg_widget_view_width">0dp</dimen>
+
+    <!-- Height of widget view in keyguard. -->
+    <dimen name="kg_widget_view_height">0dp</dimen>
+
+    <!-- Size of the clock font in keyguard's status view -->
+    <dimen name="kg_status_clock_font_size">75dp</dimen>
+
+    <!-- Size of the date font in keyguard's status view  -->
+    <dimen name="kg_status_date_font_size">15dp</dimen>
+
+    <!-- Size of the generic status lines keyguard's status view  -->
+    <dimen name="kg_status_line_font_size">13dp</dimen>
+
+    <!-- Size of margin on the right of keyguard's status view -->
+    <dimen name="kg_status_line_font_right_margin">16dp</dimen>
+
+    <!-- Top margin for the clock view -->
+    <dimen name="kg_clock_top_margin">-16dp</dimen>
+
+    <!-- Horizontal gap between keys in PIN and SIM PIN numeric keyboards in keyguard -->
+    <dimen name="kg_key_horizontal_gap">0dp</dimen>
+
+    <!-- Horizontal gap between keys in PIN and SIM PIN numeric keyboards in keyguard -->
+    <dimen name="kg_key_vertical_gap">0dp</dimen>
+
+    <!-- Horizontal gap between keys in PIN and SIM PIN numeric keyboards in keyguard -->
+    <dimen name="kg_pin_key_height">60dp</dimen>
+
+    <!-- Space reserved at the bottom of secure views (pin/pattern/password/SIM pin/SIM puk) -->
+    <dimen name="kg_secure_padding_height">46dp</dimen>
+
+    <!-- The height of the runway lights strip -->
+    <dimen name="kg_runway_lights_height">7dp</dimen>
+
+    <!-- The height of the runway lights strip -->
+    <dimen name="kg_runway_lights_vertical_padding">2dp</dimen>
+
+    <!-- Horizontal padding for the widget pager -->
+    <dimen name="kg_widget_pager_horizontal_padding">16dp</dimen>
+
+    <!-- Top padding for the widget pager -->
+    <dimen name="kg_widget_pager_top_padding">0dp</dimen>
+
+    <!-- Bottom padding for the widget pager -->
+    <dimen name="kg_widget_pager_bottom_padding">64dp</dimen>
+
+    <!-- Top margin for the runway lights. We add a negative margin in large
+        devices to account for the widget pager padding -->
+    <dimen name="kg_runway_lights_top_margin">0dp</dimen>
+
+    <!-- Touch slop for the global toggle accessibility gesture -->
+    <dimen name="accessibility_touch_slop">80dip</dimen>
+
+    <!-- Width of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) -->
+    <dimen name="keyguard_security_width">320dp</dimen>
+
+    <!-- Height of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) -->
+    <dimen name="keyguard_security_height">400dp</dimen>
+
+    <!-- Margin around the various security views -->
+    <dimen name="keyguard_security_view_margin">8dp</dimen>
+
+    <!-- Margin around the various security views -->
+    <dimen name="keyguard_muliuser_selector_margin">8dp</dimen>
+
+    <!-- Stroke width of the frame for the circular avatars. -->
+    <dimen name="keyguard_avatar_frame_stroke_width">2dp</dimen>
+
+    <!-- Shadow radius under the frame for the circular avatars. -->
+    <dimen name="keyguard_avatar_frame_shadow_radius">1dp</dimen>
+
+    <!-- Size of the avator on hte multiuser lockscreen. -->
+    <dimen name="keyguard_avatar_size">66dp</dimen>
+
+    <!-- Size of the text under the avator on the multiuser lockscreen. -->
+    <dimen name="keyguard_avatar_name_size">10sp</dimen>
+
+    <!-- Size of the region along the edge of the screen that will accept
+         swipes to scroll the widget area. -->
+    <dimen name="kg_edge_swipe_region_size">24dp</dimen>
+
+    <!-- If the height if keyguard drops below this threshold (most likely
+    due to the appearance of the IME), then drop the multiuser selector. -->
+    <dimen name="kg_squashed_layout_threshold">600dp</dimen>
+
+    <!-- The height of widgets which do not support vertical resizing. This is only
+    used on tablets; on phones, this size is determined by the space left by the
+    security mode. -->
+    <dimen name="kg_small_widget_height">160dp</dimen>
+
 </resources>
diff --git a/core/res/res/values/donottranslate-cldr.xml b/core/res/res/values/donottranslate-cldr.xml
index 15fcd8b..0587c165 100644
--- a/core/res/res/values/donottranslate-cldr.xml
+++ b/core/res/res/values/donottranslate-cldr.xml
@@ -1,96 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="month_long_standalone_january">January</string>
-    <string name="month_long_standalone_february">February</string>
-    <string name="month_long_standalone_march">March</string>
-    <string name="month_long_standalone_april">April</string>
-    <string name="month_long_standalone_may">May</string>
-    <string name="month_long_standalone_june">June</string>
-    <string name="month_long_standalone_july">July</string>
-    <string name="month_long_standalone_august">August</string>
-    <string name="month_long_standalone_september">September</string>
-    <string name="month_long_standalone_october">October</string>
-    <string name="month_long_standalone_november">November</string>
-    <string name="month_long_standalone_december">December</string>
-
-    <string name="month_long_january">January</string>
-    <string name="month_long_february">February</string>
-    <string name="month_long_march">March</string>
-    <string name="month_long_april">April</string>
-    <string name="month_long_may">May</string>
-    <string name="month_long_june">June</string>
-    <string name="month_long_july">July</string>
-    <string name="month_long_august">August</string>
-    <string name="month_long_september">September</string>
-    <string name="month_long_october">October</string>
-    <string name="month_long_november">November</string>
-    <string name="month_long_december">December</string>
-
-    <string name="month_medium_january">Jan</string>
-    <string name="month_medium_february">Feb</string>
-    <string name="month_medium_march">Mar</string>
-    <string name="month_medium_april">Apr</string>
-    <string name="month_medium_may">May</string>
-    <string name="month_medium_june">Jun</string>
-    <string name="month_medium_july">Jul</string>
-    <string name="month_medium_august">Aug</string>
-    <string name="month_medium_september">Sep</string>
-    <string name="month_medium_october">Oct</string>
-    <string name="month_medium_november">Nov</string>
-    <string name="month_medium_december">Dec</string>
-
-    <string name="month_shortest_january">J</string>
-    <string name="month_shortest_february">F</string>
-    <string name="month_shortest_march">M</string>
-    <string name="month_shortest_april">A</string>
-    <string name="month_shortest_may">M</string>
-    <string name="month_shortest_june">J</string>
-    <string name="month_shortest_july">J</string>
-    <string name="month_shortest_august">A</string>
-    <string name="month_shortest_september">S</string>
-    <string name="month_shortest_october">O</string>
-    <string name="month_shortest_november">N</string>
-    <string name="month_shortest_december">D</string>
-
-    <string name="day_of_week_long_sunday">Sunday</string>
-    <string name="day_of_week_long_monday">Monday</string>
-    <string name="day_of_week_long_tuesday">Tuesday</string>
-    <string name="day_of_week_long_wednesday">Wednesday</string>
-    <string name="day_of_week_long_thursday">Thursday</string>
-    <string name="day_of_week_long_friday">Friday</string>
-    <string name="day_of_week_long_saturday">Saturday</string>
-
-    <string name="day_of_week_medium_sunday">Sun</string>
-    <string name="day_of_week_medium_monday">Mon</string>
-    <string name="day_of_week_medium_tuesday">Tue</string>
-    <string name="day_of_week_medium_wednesday">Wed</string>
-    <string name="day_of_week_medium_thursday">Thu</string>
-    <string name="day_of_week_medium_friday">Fri</string>
-    <string name="day_of_week_medium_saturday">Sat</string>
-
-    <string name="day_of_week_short_sunday">Su</string>
-    <string name="day_of_week_short_monday">Mo</string>
-    <string name="day_of_week_short_tuesday">Tu</string>
-    <string name="day_of_week_short_wednesday">We</string>
-    <string name="day_of_week_short_thursday">Th</string>
-    <string name="day_of_week_short_friday">Fr</string>
-    <string name="day_of_week_short_saturday">Sa</string>
-
-    <string name="day_of_week_shortest_sunday">S</string>
-    <string name="day_of_week_shortest_monday">M</string>
-    <string name="day_of_week_shortest_tuesday">T</string>
-    <string name="day_of_week_shortest_wednesday">W</string>
-    <string name="day_of_week_shortest_thursday">T</string>
-    <string name="day_of_week_shortest_friday">F</string>
-    <string name="day_of_week_shortest_saturday">S</string>
-
-    <string name="am">am</string>
-    <string name="pm">pm</string>
-    <string name="yesterday">Yesterday</string>
-    <string name="today">Today</string>
-    <string name="tomorrow">Tomorrow</string>
-
     <string name="hour_minute_24">%H:%M</string>
     <string name="hour_minute_ampm">%-l:%M%p</string>
     <string name="hour_minute_cap_ampm">%-l:%M%^p</string>
diff --git a/core/res/res/values/integers.xml b/core/res/res/values/integers.xml
new file mode 100644
index 0000000..053fc85
--- /dev/null
+++ b/core/res/res/values/integers.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <integer name="kg_carousel_angle">75</integer>
+    <integer name="kg_security_flip_duration">100</integer>
+    <integer name="kg_security_fade_duration">100</integer>
+    <integer name="kg_glowpad_rotation_offset">0</integer>
+</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 6334f88..a5dae7e 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
 <!-- This file defines the base public resources exported by the
      platform, which must always exist. -->
 
@@ -19,1678 +20,6 @@
      *************************************************************** -->
 <resources>
 
-  <!-- We don't want to publish private symbols in android.R as part of the
-       SDK.  Instead, put them here. -->
-  <private-symbols package="com.android.internal" />
-
-  <!-- Private symbols that we need to reference from framework code.  See
-       frameworks/base/core/res/MakeJavaSymbols.sed for how to easily generate
-       this.
-  -->
-  <java-symbol type="id" name="account_name" />
-  <java-symbol type="id" name="account_row_icon" />
-  <java-symbol type="id" name="account_row_text" />
-  <java-symbol type="id" name="account_type" />
-  <java-symbol type="id" name="action_bar" />
-  <java-symbol type="id" name="action_bar_container" />
-  <java-symbol type="id" name="action_bar_overlay_layout" />
-  <java-symbol type="id" name="action_bar_title" />
-  <java-symbol type="id" name="action_bar_subtitle" />
-  <java-symbol type="id" name="action_context_bar" />
-  <java-symbol type="id" name="action_menu_presenter" />
-  <java-symbol type="id" name="action_mode_close_button" />
-  <java-symbol type="id" name="activity_chooser_view_content" />
-  <java-symbol type="id" name="albumart" />
-  <java-symbol type="id" name="alertTitle" />
-  <java-symbol type="id" name="allow_button" />
-  <java-symbol type="id" name="alwaysUse" />
-  <java-symbol type="id" name="amPm" />
-  <java-symbol type="id" name="authtoken_type" />
-  <java-symbol type="id" name="back_button" />
-  <java-symbol type="id" name="btn_next" />
-  <java-symbol type="id" name="btn_play" />
-  <java-symbol type="id" name="btn_prev" />
-  <java-symbol type="id" name="button_bar" />
-  <java-symbol type="id" name="buttonPanel" />
-  <java-symbol type="id" name="by_common" />
-  <java-symbol type="id" name="by_org" />
-  <java-symbol type="id" name="by_org_unit" />
-  <java-symbol type="id" name="calendar_view" />
-  <java-symbol type="id" name="cancel" />
-  <java-symbol type="id" name="characterPicker" />
-  <java-symbol type="id" name="clearDefaultHint" />
-  <java-symbol type="id" name="contentPanel" />
-  <java-symbol type="id" name="customPanel" />
-  <java-symbol type="id" name="datePicker" />
-  <java-symbol type="id" name="day" />
-  <java-symbol type="id" name="day_names" />
-  <java-symbol type="id" name="decrement" />
-  <java-symbol type="id" name="default_activity_button" />
-  <java-symbol type="id" name="deny_button" />
-  <java-symbol type="id" name="description" />
-  <java-symbol type="id" name="divider" />
-  <java-symbol type="id" name="edit_query" />
-  <java-symbol type="id" name="edittext_container" />
-  <java-symbol type="id" name="enter_pin_section" />
-  <java-symbol type="id" name="expand_activities_button" />
-  <java-symbol type="id" name="expand_button" />
-  <java-symbol type="id" name="expand_button_divider" />
-  <java-symbol type="id" name="expires_on" />
-  <java-symbol type="id" name="find_next" />
-  <java-symbol type="id" name="find_prev" />
-  <java-symbol type="id" name="ffwd" />
-  <java-symbol type="id" name="fillInIntent" />
-  <java-symbol type="id" name="find" />
-  <java-symbol type="id" name="fullscreenArea" />
-  <java-symbol type="id" name="hard_keyboard_section" />
-  <java-symbol type="id" name="hard_keyboard_switch" />
-  <java-symbol type="id" name="headers" />
-  <java-symbol type="id" name="hour" />
-  <java-symbol type="id" name="icon" />
-  <java-symbol type="id" name="image" />
-  <java-symbol type="id" name="increment" />
-  <java-symbol type="id" name="internalEmpty" />
-  <java-symbol type="id" name="info" />
-  <java-symbol type="id" name="inputExtractAccessories" />
-  <java-symbol type="id" name="inputExtractAction" />
-  <java-symbol type="id" name="inputExtractEditButton" />
-  <java-symbol type="id" name="issued_on" />
-  <java-symbol type="id" name="left_icon" />
-  <java-symbol type="id" name="leftSpacer" />
-  <java-symbol type="id" name="line1" />
-  <java-symbol type="id" name="line3" />
-  <java-symbol type="id" name="list_footer" />
-  <java-symbol type="id" name="list_item" />
-  <java-symbol type="id" name="listContainer" />
-  <java-symbol type="id" name="locale" />
-  <java-symbol type="id" name="matches" />
-  <java-symbol type="id" name="mediacontroller_progress" />
-  <java-symbol type="id" name="minute" />
-  <java-symbol type="id" name="mode_normal" />
-  <java-symbol type="id" name="month" />
-  <java-symbol type="id" name="month_name" />
-  <java-symbol type="id" name="name" />
-  <java-symbol type="id" name="next" />
-  <java-symbol type="id" name="next_button" />
-  <java-symbol type="id" name="new_app_action" />
-  <java-symbol type="id" name="new_app_description" />
-  <java-symbol type="id" name="new_app_icon" />
-  <java-symbol type="id" name="no_permissions" />
-  <java-symbol type="id" name="numberpicker_input" />
-  <java-symbol type="id" name="old_app_action" />
-  <java-symbol type="id" name="old_app_description" />
-  <java-symbol type="id" name="old_app_icon" />
-  <java-symbol type="id" name="package_label" />
-  <java-symbol type="id" name="packages_list" />
-  <java-symbol type="id" name="pause" />
-  <java-symbol type="id" name="show_more" />
-  <java-symbol type="id" name="perm_icon" />
-  <java-symbol type="id" name="show_more_icon" />
-  <java-symbol type="id" name="show_more_text" />
-  <java-symbol type="id" name="dangerous_perms_list" />
-  <java-symbol type="id" name="non_dangerous_perms_list" />
-  <java-symbol type="id" name="permission_group" />
-  <java-symbol type="id" name="permission_list" />
-  <java-symbol type="id" name="pickers" />
-  <java-symbol type="id" name="prefs" />
-  <java-symbol type="id" name="prefs_frame" />
-  <java-symbol type="id" name="prev" />
-  <java-symbol type="id" name="progress" />
-  <java-symbol type="id" name="progress_circular" />
-  <java-symbol type="id" name="progress_horizontal" />
-  <java-symbol type="id" name="progress_number" />
-  <java-symbol type="id" name="progress_percent" />
-  <java-symbol type="id" name="progressContainer" />
-  <java-symbol type="id" name="rew" />
-  <java-symbol type="id" name="rightSpacer" />
-  <java-symbol type="id" name="rowTypeId" />
-  <java-symbol type="id" name="scrollView" />
-  <java-symbol type="id" name="search_app_icon" />
-  <java-symbol type="id" name="search_badge" />
-  <java-symbol type="id" name="search_bar" />
-  <java-symbol type="id" name="search_button" />
-  <java-symbol type="id" name="search_close_btn" />
-  <java-symbol type="id" name="search_edit_frame" />
-  <java-symbol type="id" name="search_go_btn" />
-  <java-symbol type="id" name="search_mag_icon" />
-  <java-symbol type="id" name="search_plate" />
-  <java-symbol type="id" name="search_src_text" />
-  <java-symbol type="id" name="search_view" />
-  <java-symbol type="id" name="search_voice_btn" />
-  <java-symbol type="id" name="select_all" />
-  <java-symbol type="id" name="serial_number" />
-  <java-symbol type="id" name="seekbar" />
-  <java-symbol type="id" name="sha1_fingerprint" />
-  <java-symbol type="id" name="sha256_fingerprint" />
-  <java-symbol type="id" name="share" />
-  <java-symbol type="id" name="shortcut" />
-  <java-symbol type="id" name="skip_button" />
-  <java-symbol type="id" name="slider_group" />
-  <java-symbol type="id" name="split_action_bar" />
-  <java-symbol type="id" name="stream_icon" />
-  <java-symbol type="id" name="submit_area" />
-  <java-symbol type="id" name="switch_new" />
-  <java-symbol type="id" name="switch_old" />
-  <java-symbol type="id" name="switchWidget" />
-  <java-symbol type="id" name="text" />
-  <java-symbol type="id" name="time" />
-  <java-symbol type="id" name="time_current" />
-  <java-symbol type="id" name="timeDisplayBackground" />
-  <java-symbol type="id" name="timeDisplayForeground" />
-  <java-symbol type="id" name="titleDivider" />
-  <java-symbol type="id" name="titleDividerTop" />
-  <java-symbol type="id" name="timePicker" />
-  <java-symbol type="id" name="title_template" />
-  <java-symbol type="id" name="to_common" />
-  <java-symbol type="id" name="to_org" />
-  <java-symbol type="id" name="to_org_unit" />
-  <java-symbol type="id" name="top_action_bar" />
-  <java-symbol type="id" name="topPanel" />
-  <java-symbol type="id" name="up" />
-  <java-symbol type="id" name="value" />
-  <java-symbol type="id" name="visible_panel" />
-  <java-symbol type="id" name="websearch" />
-  <java-symbol type="id" name="wifi_p2p_wps_pin" />
-  <java-symbol type="id" name="year" />
-  <java-symbol type="id" name="zoomControls" />
-  <java-symbol type="id" name="zoomIn" />
-  <java-symbol type="id" name="zoomMagnify" />
-  <java-symbol type="id" name="zoomOut" />
-  <java-symbol type="id" name="actions" />
-  <java-symbol type="id" name="action0" />
-  <java-symbol type="id" name="action1" />
-  <java-symbol type="id" name="action2" />
-  <java-symbol type="id" name="big_picture" />
-  <java-symbol type="id" name="big_text" />
-  <java-symbol type="id" name="chronometer" />
-  <java-symbol type="id" name="inbox_text0" />
-  <java-symbol type="id" name="inbox_text1" />
-  <java-symbol type="id" name="inbox_text2" />
-  <java-symbol type="id" name="inbox_text3" />
-  <java-symbol type="id" name="inbox_text4" />
-  <java-symbol type="id" name="inbox_text5" />
-  <java-symbol type="id" name="inbox_text6" />
-  <java-symbol type="id" name="inbox_more" />
-  <java-symbol type="id" name="status_bar_latest_event_content" />
-  <java-symbol type="id" name="action_divider" />
-  <java-symbol type="id" name="overflow_divider" />
-
-  <java-symbol type="attr" name="actionModeShareDrawable" />
-  <java-symbol type="attr" name="alertDialogCenterButtons" />
-  <java-symbol type="attr" name="gestureOverlayViewStyle" />
-  <java-symbol type="attr" name="keyboardViewStyle" />
-  <java-symbol type="attr" name="numberPickerStyle" />
-  <java-symbol type="attr" name="pointerStyle" />
-  <java-symbol type="attr" name="preferenceFrameLayoutStyle" />
-  <java-symbol type="attr" name="searchDialogTheme" />
-  <java-symbol type="attr" name="searchViewSearchIcon" />
-  <java-symbol type="attr" name="stackViewStyle" />
-  <java-symbol type="attr" name="switchStyle" />
-  <java-symbol type="attr" name="textAppearanceAutoCorrectionSuggestion" />
-  <java-symbol type="attr" name="textAppearanceEasyCorrectSuggestion" />
-  <java-symbol type="attr" name="textAppearanceMisspelledSuggestion" />
-  <java-symbol type="attr" name="textColorSearchUrl" />
-  <java-symbol type="attr" name="timePickerStyle" />
-  <java-symbol type="attr" name="windowFixedWidthMajor" />
-  <java-symbol type="attr" name="windowFixedWidthMinor" />
-  <java-symbol type="attr" name="windowFixedHeightMajor" />
-  <java-symbol type="attr" name="windowFixedHeightMinor" />
-  <java-symbol type="attr" name="accessibilityFocusedDrawable"/>
-
-  <java-symbol type="bool" name="action_bar_embed_tabs" />
-  <java-symbol type="bool" name="action_bar_embed_tabs_pre_jb" />
-  <java-symbol type="bool" name="action_bar_expanded_action_views_exclusive" />
-  <java-symbol type="bool" name="config_allowActionMenuItemTextWithIcon" />
-  <java-symbol type="bool" name="config_bluetooth_adapter_quick_switch" />
-  <java-symbol type="bool" name="config_bluetooth_sco_off_call" />
-  <java-symbol type="bool" name="config_cellBroadcastAppLinks" />
-  <java-symbol type="bool" name="config_duplicate_port_omadm_wappush" />
-  <java-symbol type="bool" name="config_enable_emergency_call_while_sim_locked" />
-  <java-symbol type="bool" name="config_enable_puk_unlock_screen" />
-  <java-symbol type="bool" name="config_mms_content_disposition_support" />
-  <java-symbol type="bool" name="config_showMenuShortcutsWhenKeyboardPresent" />
-  <java-symbol type="bool" name="config_sip_wifi_only" />
-  <java-symbol type="bool" name="config_sms_capable" />
-  <java-symbol type="bool" name="config_sms_utf8_support" />
-  <java-symbol type="bool" name="config_swipeDisambiguation" />
-  <java-symbol type="bool" name="config_syncstorageengine_masterSyncAutomatically" />
-  <java-symbol type="bool" name="config_telephony_use_own_number_for_voicemail" />
-  <java-symbol type="bool" name="config_ui_enableFadingMarquee" />
-  <java-symbol type="bool" name="config_use_strict_phone_number_comparation" />
-  <java-symbol type="bool" name="config_voice_capable" />
-  <java-symbol type="bool" name="preferences_prefer_dual_pane" />
-  <java-symbol type="bool" name="skip_restoring_network_selection" />
-  <java-symbol type="bool" name="split_action_bar_is_narrow" />
-  <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" />
-  <java-symbol type="integer" name="config_max_pan_devices" />
-  <java-symbol type="integer" name="config_ntpTimeout" />
-  <java-symbol type="integer" name="config_wifi_framework_scan_interval" />
-  <java-symbol type="integer" name="config_wifi_supplicant_scan_interval" />
-  <java-symbol type="integer" name="db_connection_pool_size" />
-  <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="integer" name="config_soundEffectVolumeDb" />
-  <java-symbol type="integer" name="config_lockSoundVolumeDb" />
-
-  <java-symbol type="color" name="tab_indicator_text_v4" />
-
-  <java-symbol type="dimen" name="config_prefDialogWidth" />
-  <java-symbol type="dimen" name="config_viewConfigurationTouchSlop" />
-  <java-symbol type="dimen" name="default_app_widget_padding_bottom" />
-  <java-symbol type="dimen" name="default_app_widget_padding_left" />
-  <java-symbol type="dimen" name="default_app_widget_padding_right" />
-  <java-symbol type="dimen" name="default_app_widget_padding_top" />
-  <java-symbol type="dimen" name="default_gap" />
-  <java-symbol type="dimen" name="dropdownitem_icon_width" />
-  <java-symbol type="dimen" name="dropdownitem_text_padding_left" />
-  <java-symbol type="dimen" name="fastscroll_overlay_size" />
-  <java-symbol type="dimen" name="fastscroll_thumb_height" />
-  <java-symbol type="dimen" name="fastscroll_thumb_width" />
-  <java-symbol type="dimen" name="fastscroll_thumb_width" />
-  <java-symbol type="dimen" name="password_keyboard_spacebar_vertical_correction" />
-  <java-symbol type="dimen" name="search_view_preferred_width" />
-  <java-symbol type="dimen" name="textview_error_popup_default_width" />
-  <java-symbol type="dimen" name="toast_y_offset" />
-  <java-symbol type="dimen" name="volume_panel_top" />
-  <java-symbol type="dimen" name="action_bar_stacked_max_height" />
-  <java-symbol type="dimen" name="action_bar_stacked_tab_max_width" />
-  <java-symbol type="dimen" name="notification_text_size" />
-  <java-symbol type="dimen" name="notification_title_text_size" />
-  <java-symbol type="dimen" name="notification_subtext_size" />
-
-  <java-symbol type="string" name="add_account_button_label" />
-  <java-symbol type="string" name="addToDictionary" />
-  <java-symbol type="string" name="action_bar_home_description" />
-  <java-symbol type="string" name="action_bar_up_description" />
-  <java-symbol type="string" name="delete" />
-  <java-symbol type="string" name="deleteText" />
-  <java-symbol type="string" name="ellipsis_two_dots" />
-  <java-symbol type="string" name="ellipsis" />
-  <java-symbol type="string" name="grant_permissions_header_text" />
-  <java-symbol type="string" name="list_delimeter" />
-  <java-symbol type="string" name="menu_delete_shortcut_label" />
-  <java-symbol type="string" name="menu_enter_shortcut_label" />
-  <java-symbol type="string" name="menu_space_shortcut_label" />
-  <java-symbol type="string" name="notification_title" />
-  <java-symbol type="string" name="permission_request_notification_with_subtitle" />
-  <java-symbol type="string" name="prepend_shortcut_label" />
-  <java-symbol type="string" name="replace" />
-  <java-symbol type="string" name="textSelectionCABTitle" />
-  <java-symbol type="string" name="BaMmi" />
-  <java-symbol type="string" name="CLIRDefaultOffNextCallOff" />
-  <java-symbol type="string" name="CLIRDefaultOffNextCallOn" />
-  <java-symbol type="string" name="CLIRDefaultOnNextCallOff" />
-  <java-symbol type="string" name="CLIRDefaultOnNextCallOn" />
-  <java-symbol type="string" name="CLIRPermanent" />
-  <java-symbol type="string" name="CfMmi" />
-  <java-symbol type="string" name="ClipMmi" />
-  <java-symbol type="string" name="ClirMmi" />
-  <java-symbol type="string" name="CwMmi" />
-  <java-symbol type="string" name="Midnight" />
-  <java-symbol type="string" name="Noon" />
-  <java-symbol type="string" name="PinMmi" />
-  <java-symbol type="string" name="PwdMmi" />
-  <java-symbol type="string" name="RestrictedChangedTitle" />
-  <java-symbol type="string" name="RestrictedOnAllVoice" />
-  <java-symbol type="string" name="RestrictedOnData" />
-  <java-symbol type="string" name="RestrictedOnEmergency" />
-  <java-symbol type="string" name="RestrictedOnNormal" />
-  <java-symbol type="string" name="SetupCallDefault" />
-  <java-symbol type="string" name="abbrev_month" />
-  <java-symbol type="string" name="abbrev_month_day" />
-  <java-symbol type="string" name="abbrev_month_day_year" />
-  <java-symbol type="string" name="abbrev_month_year" />
-  <java-symbol type="string" name="accept" />
-  <java-symbol type="string" name="activity_chooser_view_see_all" />
-  <java-symbol type="string" name="activitychooserview_choose_application" />
-  <java-symbol type="string" name="alternate_eri_file" />
-  <java-symbol type="string" name="alwaysUse" />
-  <java-symbol type="string" name="am" />
-  <java-symbol type="string" name="autofill_address_line_1_label_re" />
-  <java-symbol type="string" name="autofill_address_line_1_re" />
-  <java-symbol type="string" name="autofill_address_line_2_re" />
-  <java-symbol type="string" name="autofill_address_line_3_re" />
-  <java-symbol type="string" name="autofill_address_name_separator" />
-  <java-symbol type="string" name="autofill_address_summary_format" />
-  <java-symbol type="string" name="autofill_address_summary_name_format" />
-  <java-symbol type="string" name="autofill_address_summary_separator" />
-  <java-symbol type="string" name="autofill_address_type_same_as_re" />
-  <java-symbol type="string" name="autofill_address_type_use_my_re" />
-  <java-symbol type="string" name="autofill_area" />
-  <java-symbol type="string" name="autofill_area_code_notext_re" />
-  <java-symbol type="string" name="autofill_area_code_re" />
-  <java-symbol type="string" name="autofill_attention_ignored_re" />
-  <java-symbol type="string" name="autofill_billing_designator_re" />
-  <java-symbol type="string" name="autofill_card_cvc_re" />
-  <java-symbol type="string" name="autofill_card_ignored_re" />
-  <java-symbol type="string" name="autofill_card_number_re" />
-  <java-symbol type="string" name="autofill_city_re" />
-  <java-symbol type="string" name="autofill_company_re" />
-  <java-symbol type="string" name="autofill_country_code_re" />
-  <java-symbol type="string" name="autofill_country_re" />
-  <java-symbol type="string" name="autofill_county" />
-  <java-symbol type="string" name="autofill_department" />
-  <java-symbol type="string" name="autofill_district" />
-  <java-symbol type="string" name="autofill_email_re" />
-  <java-symbol type="string" name="autofill_emirate" />
-  <java-symbol type="string" name="autofill_expiration_date_re" />
-  <java-symbol type="string" name="autofill_expiration_month_re" />
-  <java-symbol type="string" name="autofill_fax_re" />
-  <java-symbol type="string" name="autofill_first_name_re" />
-  <java-symbol type="string" name="autofill_island" />
-  <java-symbol type="string" name="autofill_last_name_re" />
-  <java-symbol type="string" name="autofill_middle_initial_re" />
-  <java-symbol type="string" name="autofill_middle_name_re" />
-  <java-symbol type="string" name="autofill_name_on_card_contextual_re" />
-  <java-symbol type="string" name="autofill_name_on_card_re" />
-  <java-symbol type="string" name="autofill_name_re" />
-  <java-symbol type="string" name="autofill_name_specific_re" />
-  <java-symbol type="string" name="autofill_parish" />
-  <java-symbol type="string" name="autofill_phone_extension_re" />
-  <java-symbol type="string" name="autofill_phone_prefix_re" />
-  <java-symbol type="string" name="autofill_phone_prefix_separator_re" />
-  <java-symbol type="string" name="autofill_phone_re" />
-  <java-symbol type="string" name="autofill_phone_suffix_re" />
-  <java-symbol type="string" name="autofill_phone_suffix_separator_re" />
-  <java-symbol type="string" name="autofill_postal_code" />
-  <java-symbol type="string" name="autofill_prefecture" />
-  <java-symbol type="string" name="autofill_province" />
-  <java-symbol type="string" name="autofill_region_ignored_re" />
-  <java-symbol type="string" name="autofill_shipping_designator_re" />
-  <java-symbol type="string" name="autofill_state" />
-  <java-symbol type="string" name="autofill_state_re" />
-  <java-symbol type="string" name="autofill_this_form" />
-  <java-symbol type="string" name="autofill_username_re" />
-  <java-symbol type="string" name="autofill_zip_4_re" />
-  <java-symbol type="string" name="autofill_zip_code" />
-  <java-symbol type="string" name="autofill_zip_code_re" />
-  <java-symbol type="string" name="badPin" />
-  <java-symbol type="string" name="badPuk" />
-  <java-symbol type="string" name="byteShort" />
-  <java-symbol type="string" name="cfTemplateForwarded" />
-  <java-symbol type="string" name="cfTemplateForwardedTime" />
-  <java-symbol type="string" name="cfTemplateNotForwarded" />
-  <java-symbol type="string" name="cfTemplateRegistered" />
-  <java-symbol type="string" name="cfTemplateRegisteredTime" />
-  <java-symbol type="string" name="chooseActivity" />
-  <java-symbol type="string" name="config_default_dns_server" />
-  <java-symbol type="string" name="config_ethernet_iface_regex" />
-  <java-symbol type="string" name="config_ntpServer" />
-  <java-symbol type="string" name="config_tether_apndata" />
-  <java-symbol type="string" name="config_useragentprofile_url" />
-  <java-symbol type="string" name="config_wifi_p2p_device_type" />
-  <java-symbol type="string" name="contentServiceSync" />
-  <java-symbol type="string" name="contentServiceSyncNotificationTitle" />
-  <java-symbol type="string" name="contentServiceTooManyDeletesNotificationDesc" />
-  <java-symbol type="string" name="date1_date2" />
-  <java-symbol type="string" name="date1_time1_date2_time2" />
-  <java-symbol type="string" name="date_and_time" />
-  <java-symbol type="string" name="date_picker_decrement_day_button" />
-  <java-symbol type="string" name="date_picker_decrement_month_button" />
-  <java-symbol type="string" name="date_picker_decrement_year_button" />
-  <java-symbol type="string" name="date_picker_dialog_title" />
-  <java-symbol type="string" name="date_picker_increment_day_button" />
-  <java-symbol type="string" name="date_picker_increment_month_button" />
-  <java-symbol type="string" name="date_picker_increment_year_button" />
-  <java-symbol type="string" name="date_time" />
-  <java-symbol type="string" name="date_time_set" />
-  <java-symbol type="string" name="date_time_done" />
-  <java-symbol type="string" name="day_of_week_long_friday" />
-  <java-symbol type="string" name="day_of_week_long_monday" />
-  <java-symbol type="string" name="day_of_week_long_saturday" />
-  <java-symbol type="string" name="day_of_week_long_sunday" />
-  <java-symbol type="string" name="day_of_week_long_thursday" />
-  <java-symbol type="string" name="day_of_week_long_tuesday" />
-  <java-symbol type="string" name="day_of_week_long_wednesday" />
-  <java-symbol type="string" name="day_of_week_medium_friday" />
-  <java-symbol type="string" name="day_of_week_medium_monday" />
-  <java-symbol type="string" name="day_of_week_medium_saturday" />
-  <java-symbol type="string" name="day_of_week_medium_sunday" />
-  <java-symbol type="string" name="day_of_week_medium_thursday" />
-  <java-symbol type="string" name="day_of_week_medium_tuesday" />
-  <java-symbol type="string" name="day_of_week_medium_wednesday" />
-  <java-symbol type="string" name="day_of_week_short_friday" />
-  <java-symbol type="string" name="day_of_week_short_monday" />
-  <java-symbol type="string" name="day_of_week_short_saturday" />
-  <java-symbol type="string" name="day_of_week_short_sunday" />
-  <java-symbol type="string" name="day_of_week_short_thursday" />
-  <java-symbol type="string" name="day_of_week_short_tuesday" />
-  <java-symbol type="string" name="day_of_week_short_wednesday" />
-  <java-symbol type="string" name="day_of_week_shortest_friday" />
-  <java-symbol type="string" name="day_of_week_shortest_monday" />
-  <java-symbol type="string" name="day_of_week_shortest_saturday" />
-  <java-symbol type="string" name="day_of_week_shortest_sunday" />
-  <java-symbol type="string" name="day_of_week_shortest_thursday" />
-  <java-symbol type="string" name="day_of_week_shortest_tuesday" />
-  <java-symbol type="string" name="day_of_week_shortest_wednesday" />
-  <java-symbol type="string" name="db_default_journal_mode" />
-  <java-symbol type="string" name="db_default_sync_mode" />
-  <java-symbol type="string" name="db_wal_sync_mode" />
-  <java-symbol type="string" name="decline" />
-  <java-symbol type="string" name="default_text_encoding" />
-  <java-symbol type="string" name="description_target_unlock_tablet" />
-  <java-symbol type="string" name="double_tap_toast" />
-  <java-symbol type="string" name="elapsed_time_short_format_h_mm_ss" />
-  <java-symbol type="string" name="elapsed_time_short_format_mm_ss" />
-  <java-symbol type="string" name="emailTypeCustom" />
-  <java-symbol type="string" name="emailTypeHome" />
-  <java-symbol type="string" name="emailTypeMobile" />
-  <java-symbol type="string" name="emailTypeOther" />
-  <java-symbol type="string" name="emailTypeWork" />
-  <java-symbol type="string" name="emergency_call_dialog_number_for_display" />
-  <java-symbol type="string" name="emergency_calls_only" />
-  <java-symbol type="string" name="eventTypeAnniversary" />
-  <java-symbol type="string" name="eventTypeBirthday" />
-  <java-symbol type="string" name="eventTypeCustom" />
-  <java-symbol type="string" name="eventTypeOther" />
-  <java-symbol type="string" name="extmedia_format_button_format" />
-  <java-symbol type="string" name="extmedia_format_message" />
-  <java-symbol type="string" name="extmedia_format_title" />
-  <java-symbol type="string" name="fileSizeSuffix" />
-  <java-symbol type="string" name="force_close" />
-  <java-symbol type="string" name="format_error" />
-  <java-symbol type="string" name="gadget_host_error_inflating" />
-  <java-symbol type="string" name="gigabyteShort" />
-  <java-symbol type="string" name="gpsNotifMessage" />
-  <java-symbol type="string" name="gpsNotifTicker" />
-  <java-symbol type="string" name="gpsNotifTitle" />
-  <java-symbol type="string" name="gpsVerifNo" />
-  <java-symbol type="string" name="gpsVerifYes" />
-  <java-symbol type="string" name="gsm_alphabet_default_charset" />
-  <java-symbol type="string" name="hour_ampm" />
-  <java-symbol type="string" name="hour_cap_ampm" />
-  <java-symbol type="string" name="hour_minute_24" />
-  <java-symbol type="string" name="hour_minute_ampm" />
-  <java-symbol type="string" name="hour_minute_cap_ampm" />
-  <java-symbol type="string" name="httpError" />
-  <java-symbol type="string" name="httpErrorAuth" />
-  <java-symbol type="string" name="httpErrorConnect" />
-  <java-symbol type="string" name="httpErrorFailedSslHandshake" />
-  <java-symbol type="string" name="httpErrorFile" />
-  <java-symbol type="string" name="httpErrorFileNotFound" />
-  <java-symbol type="string" name="httpErrorIO" />
-  <java-symbol type="string" name="httpErrorLookup" />
-  <java-symbol type="string" name="httpErrorOk" />
-  <java-symbol type="string" name="httpErrorProxyAuth" />
-  <java-symbol type="string" name="httpErrorRedirectLoop" />
-  <java-symbol type="string" name="httpErrorTimeout" />
-  <java-symbol type="string" name="httpErrorTooManyRequests" />
-  <java-symbol type="string" name="httpErrorUnsupportedAuthScheme" />
-  <java-symbol type="string" name="imProtocolAim" />
-  <java-symbol type="string" name="imProtocolCustom" />
-  <java-symbol type="string" name="imProtocolGoogleTalk" />
-  <java-symbol type="string" name="imProtocolIcq" />
-  <java-symbol type="string" name="imProtocolJabber" />
-  <java-symbol type="string" name="imProtocolMsn" />
-  <java-symbol type="string" name="imProtocolNetMeeting" />
-  <java-symbol type="string" name="imProtocolQq" />
-  <java-symbol type="string" name="imProtocolSkype" />
-  <java-symbol type="string" name="imProtocolYahoo" />
-  <java-symbol type="string" name="imTypeCustom" />
-  <java-symbol type="string" name="imTypeHome" />
-  <java-symbol type="string" name="imTypeOther" />
-  <java-symbol type="string" name="imTypeWork" />
-  <java-symbol type="string" name="ime_action_default" />
-  <java-symbol type="string" name="ime_action_done" />
-  <java-symbol type="string" name="ime_action_go" />
-  <java-symbol type="string" name="ime_action_next" />
-  <java-symbol type="string" name="ime_action_previous" />
-  <java-symbol type="string" name="ime_action_search" />
-  <java-symbol type="string" name="ime_action_send" />
-  <java-symbol type="string" name="invalidPin" />
-  <java-symbol type="string" name="js_dialog_before_unload" />
-  <java-symbol type="string" name="js_dialog_title" />
-  <java-symbol type="string" name="js_dialog_title_default" />
-  <java-symbol type="string" name="keyboard_headset_required_to_hear_password" />
-  <java-symbol type="string" name="keyboard_password_character_no_headset" />
-  <java-symbol type="string" name="keyboardview_keycode_alt" />
-  <java-symbol type="string" name="keyboardview_keycode_cancel" />
-  <java-symbol type="string" name="keyboardview_keycode_delete" />
-  <java-symbol type="string" name="keyboardview_keycode_done" />
-  <java-symbol type="string" name="keyboardview_keycode_enter" />
-  <java-symbol type="string" name="keyboardview_keycode_mode_change" />
-  <java-symbol type="string" name="keyboardview_keycode_shift" />
-  <java-symbol type="string" name="kilobyteShort" />
-  <java-symbol type="string" name="last_month" />
-  <java-symbol type="string" name="launchBrowserDefault" />
-  <java-symbol type="string" name="lockscreen_access_pattern_cell_added" />
-  <java-symbol type="string" name="lockscreen_access_pattern_cleared" />
-  <java-symbol type="string" name="lockscreen_access_pattern_detected" />
-  <java-symbol type="string" name="lockscreen_access_pattern_start" />
-  <java-symbol type="string" name="lockscreen_emergency_call" />
-  <java-symbol type="string" name="lockscreen_return_to_call" />
-  <java-symbol type="string" name="lockscreen_transport_pause_description" />
-  <java-symbol type="string" name="lockscreen_transport_play_description" />
-  <java-symbol type="string" name="lockscreen_transport_stop_description" />
-  <java-symbol type="string" name="low_memory" />
-  <java-symbol type="string" name="media_bad_removal" />
-  <java-symbol type="string" name="media_checking" />
-  <java-symbol type="string" name="media_removed" />
-  <java-symbol type="string" name="media_shared" />
-  <java-symbol type="string" name="media_unknown_state" />
-  <java-symbol type="string" name="megabyteShort" />
-  <java-symbol type="string" name="midnight" />
-  <java-symbol type="string" name="mismatchPin" />
-  <java-symbol type="string" name="mmiComplete" />
-  <java-symbol type="string" name="mmiError" />
-  <java-symbol type="string" name="mmiFdnError" />
-  <java-symbol type="string" name="month" />
-  <java-symbol type="string" name="month_day" />
-  <java-symbol type="string" name="month_day_year" />
-  <java-symbol type="string" name="month_long_april" />
-  <java-symbol type="string" name="month_long_august" />
-  <java-symbol type="string" name="month_long_december" />
-  <java-symbol type="string" name="month_long_february" />
-  <java-symbol type="string" name="month_long_january" />
-  <java-symbol type="string" name="month_long_july" />
-  <java-symbol type="string" name="month_long_june" />
-  <java-symbol type="string" name="month_long_march" />
-  <java-symbol type="string" name="month_long_may" />
-  <java-symbol type="string" name="month_long_november" />
-  <java-symbol type="string" name="month_long_october" />
-  <java-symbol type="string" name="month_long_september" />
-  <java-symbol type="string" name="month_long_standalone_april" />
-  <java-symbol type="string" name="month_long_standalone_august" />
-  <java-symbol type="string" name="month_long_standalone_december" />
-  <java-symbol type="string" name="month_long_standalone_february" />
-  <java-symbol type="string" name="month_long_standalone_january" />
-  <java-symbol type="string" name="month_long_standalone_july" />
-  <java-symbol type="string" name="month_long_standalone_june" />
-  <java-symbol type="string" name="month_long_standalone_march" />
-  <java-symbol type="string" name="month_long_standalone_may" />
-  <java-symbol type="string" name="month_long_standalone_november" />
-  <java-symbol type="string" name="month_long_standalone_october" />
-  <java-symbol type="string" name="month_long_standalone_september" />
-  <java-symbol type="string" name="month_medium_april" />
-  <java-symbol type="string" name="month_medium_august" />
-  <java-symbol type="string" name="month_medium_december" />
-  <java-symbol type="string" name="month_medium_february" />
-  <java-symbol type="string" name="month_medium_january" />
-  <java-symbol type="string" name="month_medium_july" />
-  <java-symbol type="string" name="month_medium_june" />
-  <java-symbol type="string" name="month_medium_march" />
-  <java-symbol type="string" name="month_medium_may" />
-  <java-symbol type="string" name="month_medium_november" />
-  <java-symbol type="string" name="month_medium_october" />
-  <java-symbol type="string" name="month_medium_september" />
-  <java-symbol type="string" name="month_shortest_april" />
-  <java-symbol type="string" name="month_shortest_august" />
-  <java-symbol type="string" name="month_shortest_december" />
-  <java-symbol type="string" name="month_shortest_february" />
-  <java-symbol type="string" name="month_shortest_january" />
-  <java-symbol type="string" name="month_shortest_july" />
-  <java-symbol type="string" name="month_shortest_june" />
-  <java-symbol type="string" name="month_shortest_march" />
-  <java-symbol type="string" name="month_shortest_may" />
-  <java-symbol type="string" name="month_shortest_november" />
-  <java-symbol type="string" name="month_shortest_october" />
-  <java-symbol type="string" name="month_shortest_september" />
-  <java-symbol type="string" name="month_year" />
-  <java-symbol type="string" name="more_item_label" />
-  <java-symbol type="string" name="needPuk" />
-  <java-symbol type="string" name="needPuk2" />
-  <java-symbol type="string" name="new_app_action" />
-  <java-symbol type="string" name="new_app_description" />
-  <java-symbol type="string" name="noApplications" />
-  <java-symbol type="string" name="no_file_chosen" />
-  <java-symbol type="string" name="no_matches" />
-  <java-symbol type="string" name="noon" />
-  <java-symbol type="string" name="number_picker_increment_scroll_action" />
-  <java-symbol type="string" name="number_picker_increment_scroll_mode" />
-  <java-symbol type="string" name="numeric_date" />
-  <java-symbol type="string" name="numeric_date_format" />
-  <java-symbol type="string" name="numeric_date_template" />
-  <java-symbol type="string" name="numeric_md1_md2" />
-  <java-symbol type="string" name="numeric_md1_time1_md2_time2" />
-  <java-symbol type="string" name="numeric_mdy1_mdy2" />
-  <java-symbol type="string" name="numeric_mdy1_time1_mdy2_time2" />
-  <java-symbol type="string" name="numeric_wday1_md1_time1_wday2_md2_time2" />
-  <java-symbol type="string" name="numeric_wday1_md1_wday2_md2" />
-  <java-symbol type="string" name="numeric_wday1_mdy1_time1_wday2_mdy2_time2" />
-  <java-symbol type="string" name="numeric_wday1_mdy1_wday2_mdy2" />
-  <java-symbol type="string" name="old_app_action" />
-  <java-symbol type="string" name="old_app_description" />
-  <java-symbol type="string" name="older" />
-  <java-symbol type="string" name="open_permission_deny" />
-  <java-symbol type="string" name="orgTypeCustom" />
-  <java-symbol type="string" name="orgTypeOther" />
-  <java-symbol type="string" name="orgTypeWork" />
-  <java-symbol type="string" name="passwordIncorrect" />
-  <java-symbol type="string" name="perms_description_app" />
-  <java-symbol type="string" name="perms_new_perm_prefix" />
-  <java-symbol type="string" name="perms_hide" />
-  <java-symbol type="string" name="perms_show_all" />
-  <java-symbol type="string" name="default_permission_group" />
-  <java-symbol type="string" name="permissions_format" />
-  <java-symbol type="string" name="petabyteShort" />
-  <java-symbol type="string" name="phoneTypeAssistant" />
-  <java-symbol type="string" name="phoneTypeCallback" />
-  <java-symbol type="string" name="phoneTypeCar" />
-  <java-symbol type="string" name="phoneTypeCompanyMain" />
-  <java-symbol type="string" name="phoneTypeCustom" />
-  <java-symbol type="string" name="phoneTypeFaxHome" />
-  <java-symbol type="string" name="phoneTypeFaxWork" />
-  <java-symbol type="string" name="phoneTypeHome" />
-  <java-symbol type="string" name="phoneTypeIsdn" />
-  <java-symbol type="string" name="phoneTypeMain" />
-  <java-symbol type="string" name="phoneTypeMms" />
-  <java-symbol type="string" name="phoneTypeMobile" />
-  <java-symbol type="string" name="phoneTypeOther" />
-  <java-symbol type="string" name="phoneTypeOtherFax" />
-  <java-symbol type="string" name="phoneTypePager" />
-  <java-symbol type="string" name="phoneTypeRadio" />
-  <java-symbol type="string" name="phoneTypeTelex" />
-  <java-symbol type="string" name="phoneTypeTtyTdd" />
-  <java-symbol type="string" name="phoneTypeWork" />
-  <java-symbol type="string" name="phoneTypeWorkMobile" />
-  <java-symbol type="string" name="phoneTypeWorkPager" />
-  <java-symbol type="string" name="pm" />
-  <java-symbol type="string" name="policydesc_disableCamera" />
-  <java-symbol type="string" name="policydesc_encryptedStorage" />
-  <java-symbol type="string" name="policydesc_expirePassword" />
-  <java-symbol type="string" name="policydesc_forceLock" />
-  <java-symbol type="string" name="policydesc_limitPassword" />
-  <java-symbol type="string" name="policydesc_resetPassword" />
-  <java-symbol type="string" name="policydesc_setGlobalProxy" />
-  <java-symbol type="string" name="policydesc_watchLogin" />
-  <java-symbol type="string" name="policydesc_wipeData" />
-  <java-symbol type="string" name="policylab_disableCamera" />
-  <java-symbol type="string" name="policylab_encryptedStorage" />
-  <java-symbol type="string" name="policylab_expirePassword" />
-  <java-symbol type="string" name="policylab_forceLock" />
-  <java-symbol type="string" name="policylab_limitPassword" />
-  <java-symbol type="string" name="policylab_resetPassword" />
-  <java-symbol type="string" name="policylab_setGlobalProxy" />
-  <java-symbol type="string" name="policylab_watchLogin" />
-  <java-symbol type="string" name="policylab_wipeData" />
-  <java-symbol type="string" name="postalTypeCustom" />
-  <java-symbol type="string" name="postalTypeHome" />
-  <java-symbol type="string" name="postalTypeOther" />
-  <java-symbol type="string" name="postalTypeWork" />
-  <java-symbol type="string" name="power_off" />
-  <java-symbol type="string" name="preposition_for_date" />
-  <java-symbol type="string" name="preposition_for_time" />
-  <java-symbol type="string" name="progress_erasing" />
-  <java-symbol type="string" name="progress_unmounting" />
-  <java-symbol type="string" name="reboot_safemode_confirm" />
-  <java-symbol type="string" name="reboot_safemode_title" />
-  <java-symbol type="string" name="relationTypeAssistant" />
-  <java-symbol type="string" name="relationTypeBrother" />
-  <java-symbol type="string" name="relationTypeChild" />
-  <java-symbol type="string" name="relationTypeDomesticPartner" />
-  <java-symbol type="string" name="relationTypeFather" />
-  <java-symbol type="string" name="relationTypeFriend" />
-  <java-symbol type="string" name="relationTypeManager" />
-  <java-symbol type="string" name="relationTypeMother" />
-  <java-symbol type="string" name="relationTypeParent" />
-  <java-symbol type="string" name="relationTypePartner" />
-  <java-symbol type="string" name="relationTypeReferredBy" />
-  <java-symbol type="string" name="relationTypeRelative" />
-  <java-symbol type="string" name="relationTypeSister" />
-  <java-symbol type="string" name="relationTypeSpouse" />
-  <java-symbol type="string" name="relative_time" />
-  <java-symbol type="string" name="reset" />
-  <java-symbol type="string" name="ringtone_default" />
-  <java-symbol type="string" name="ringtone_default_with_actual" />
-  <java-symbol type="string" name="ringtone_picker_title" />
-  <java-symbol type="string" name="ringtone_silent" />
-  <java-symbol type="string" name="ringtone_unknown" />
-  <java-symbol type="string" name="roamingText0" />
-  <java-symbol type="string" name="roamingText1" />
-  <java-symbol type="string" name="roamingText10" />
-  <java-symbol type="string" name="roamingText11" />
-  <java-symbol type="string" name="roamingText12" />
-  <java-symbol type="string" name="roamingText2" />
-  <java-symbol type="string" name="roamingText3" />
-  <java-symbol type="string" name="roamingText4" />
-  <java-symbol type="string" name="roamingText5" />
-  <java-symbol type="string" name="roamingText6" />
-  <java-symbol type="string" name="roamingText7" />
-  <java-symbol type="string" name="roamingText8" />
-  <java-symbol type="string" name="roamingText9" />
-  <java-symbol type="string" name="roamingTextSearching" />
-  <java-symbol type="string" name="same_month_md1_md2" />
-  <java-symbol type="string" name="same_month_md1_time1_md2_time2" />
-  <java-symbol type="string" name="same_month_mdy1_mdy2" />
-  <java-symbol type="string" name="same_month_mdy1_time1_mdy2_time2" />
-  <java-symbol type="string" name="same_month_wday1_md1_time1_wday2_md2_time2" />
-  <java-symbol type="string" name="same_month_wday1_md1_wday2_md2" />
-  <java-symbol type="string" name="same_month_wday1_mdy1_time1_wday2_mdy2_time2" />
-  <java-symbol type="string" name="same_month_wday1_mdy1_wday2_mdy2" />
-  <java-symbol type="string" name="same_year_md1_md2" />
-  <java-symbol type="string" name="same_year_md1_time1_md2_time2" />
-  <java-symbol type="string" name="same_year_mdy1_mdy2" />
-  <java-symbol type="string" name="same_year_mdy1_time1_mdy2_time2" />
-  <java-symbol type="string" name="same_year_wday1_md1_time1_wday2_md2_time2" />
-  <java-symbol type="string" name="same_year_wday1_md1_wday2_md2" />
-  <java-symbol type="string" name="same_year_wday1_mdy1_time1_wday2_mdy2_time2" />
-  <java-symbol type="string" name="same_year_wday1_mdy1_wday2_mdy2" />
-  <java-symbol type="string" name="save_password_label" />
-  <java-symbol type="string" name="save_password_message" />
-  <java-symbol type="string" name="save_password_never" />
-  <java-symbol type="string" name="save_password_notnow" />
-  <java-symbol type="string" name="save_password_remember" />
-  <java-symbol type="string" name="sendText" />
-  <java-symbol type="string" name="sending" />
-  <java-symbol type="string" name="serviceClassData" />
-  <java-symbol type="string" name="serviceClassDataAsync" />
-  <java-symbol type="string" name="serviceClassDataSync" />
-  <java-symbol type="string" name="serviceClassFAX" />
-  <java-symbol type="string" name="serviceClassPAD" />
-  <java-symbol type="string" name="serviceClassPacket" />
-  <java-symbol type="string" name="serviceClassSMS" />
-  <java-symbol type="string" name="serviceClassVoice" />
-  <java-symbol type="string" name="serviceDisabled" />
-  <java-symbol type="string" name="serviceEnabled" />
-  <java-symbol type="string" name="serviceEnabledFor" />
-  <java-symbol type="string" name="serviceErased" />
-  <java-symbol type="string" name="serviceNotProvisioned" />
-  <java-symbol type="string" name="serviceRegistered" />
-  <java-symbol type="string" name="setup_autofill" />
-  <java-symbol type="string" name="share" />
-  <java-symbol type="string" name="shareactionprovider_share_with" />
-  <java-symbol type="string" name="shareactionprovider_share_with_application" />
-  <java-symbol type="string" name="short_format_month" />
-  <java-symbol type="string" name="shutdown_confirm" />
-  <java-symbol type="string" name="shutdown_confirm_question" />
-  <java-symbol type="string" name="shutdown_progress" />
-  <java-symbol type="string" name="sim_added_message" />
-  <java-symbol type="string" name="sim_added_title" />
-  <java-symbol type="string" name="sim_removed_message" />
-  <java-symbol type="string" name="sim_removed_title" />
-  <java-symbol type="string" name="sim_restart_button" />
-  <java-symbol type="string" name="sipAddressTypeCustom" />
-  <java-symbol type="string" name="sipAddressTypeHome" />
-  <java-symbol type="string" name="sipAddressTypeOther" />
-  <java-symbol type="string" name="sipAddressTypeWork" />
-  <java-symbol type="string" name="sms_control_message" />
-  <java-symbol type="string" name="sms_control_title" />
-  <java-symbol type="string" name="sms_control_no" />
-  <java-symbol type="string" name="sms_control_yes" />
-  <java-symbol type="string" name="sms_premium_short_code_confirm_message" />
-  <java-symbol type="string" name="sms_premium_short_code_confirm_title" />
-  <java-symbol type="string" name="sms_short_code_confirm_allow" />
-  <java-symbol type="string" name="sms_short_code_confirm_deny" />
-  <java-symbol type="string" name="sms_short_code_confirm_message" />
-  <java-symbol type="string" name="sms_short_code_confirm_report" />
-  <java-symbol type="string" name="sms_short_code_confirm_title" />
-  <java-symbol type="string" name="submit" />
-  <java-symbol type="string" name="sync_binding_label" />
-  <java-symbol type="string" name="sync_do_nothing" />
-  <java-symbol type="string" name="sync_really_delete" />
-  <java-symbol type="string" name="sync_too_many_deletes_desc" />
-  <java-symbol type="string" name="sync_undo_deletes" />
-  <java-symbol type="string" name="terabyteShort" />
-  <java-symbol type="string" name="text_copied" />
-  <java-symbol type="string" name="time1_time2" />
-  <java-symbol type="string" name="time_date" />
-  <java-symbol type="string" name="time_of_day" />
-  <java-symbol type="string" name="time_picker_decrement_hour_button" />
-  <java-symbol type="string" name="time_picker_decrement_minute_button" />
-  <java-symbol type="string" name="time_picker_decrement_set_am_button" />
-  <java-symbol type="string" name="time_picker_dialog_title" />
-  <java-symbol type="string" name="time_picker_increment_hour_button" />
-  <java-symbol type="string" name="time_picker_increment_minute_button" />
-  <java-symbol type="string" name="time_picker_increment_set_pm_button" />
-  <java-symbol type="string" name="time_picker_separator" />
-  <java-symbol type="string" name="time_wday" />
-  <java-symbol type="string" name="time_wday_date" />
-  <java-symbol type="string" name="today" />
-  <java-symbol type="string" name="tomorrow" />
-  <java-symbol type="string" name="twelve_hour_time_format" />
-  <java-symbol type="string" name="twenty_four_hour_time_format" />
-  <java-symbol type="string" name="upload_file" />
-  <java-symbol type="string" name="volume_alarm" />
-  <java-symbol type="string" name="volume_icon_description_bluetooth" />
-  <java-symbol type="string" name="volume_icon_description_incall" />
-  <java-symbol type="string" name="volume_icon_description_media" />
-  <java-symbol type="string" name="volume_icon_description_notification" />
-  <java-symbol type="string" name="volume_icon_description_ringer" />
-  <java-symbol type="string" name="wait" />
-  <java-symbol type="string" name="wday1_date1_time1_wday2_date2_time2" />
-  <java-symbol type="string" name="wday1_date1_wday2_date2" />
-  <java-symbol type="string" name="wday_date" />
-  <java-symbol type="string" name="web_user_agent" />
-  <java-symbol type="string" name="web_user_agent_target_content" />
-  <java-symbol type="string" name="webpage_unresponsive" />
-  <java-symbol type="string" name="whichApplication" />
-  <java-symbol type="string" name="wifi_available_sign_in" />
-  <java-symbol type="string" name="wifi_available_sign_in_detailed" />
-  <java-symbol type="string" name="wifi_p2p_dialog_title" />
-  <java-symbol type="string" name="wifi_p2p_enabled_notification_message" />
-  <java-symbol type="string" name="wifi_p2p_enabled_notification_title" />
-  <java-symbol type="string" name="wifi_p2p_failed_message" />
-  <java-symbol type="string" name="wifi_p2p_from_message" />
-  <java-symbol type="string" name="wifi_p2p_invitation_sent_title" />
-  <java-symbol type="string" name="wifi_p2p_invitation_to_connect_title" />
-  <java-symbol type="string" name="wifi_p2p_show_pin_message" />
-  <java-symbol type="string" name="wifi_p2p_to_message" />
-  <java-symbol type="string" name="wifi_p2p_turnon_message" />
-  <java-symbol type="string" name="wifi_tether_configure_ssid_default" />
-  <java-symbol type="string" name="wifi_watchdog_network_disabled" />
-  <java-symbol type="string" name="wifi_watchdog_network_disabled_detailed" />
-  <java-symbol type="string" name="yesterday" />
-  <java-symbol type="string" name="imei" />
-  <java-symbol type="string" name="meid" />
-  <java-symbol type="string" name="granularity_label_character" />
-  <java-symbol type="string" name="granularity_label_word" />
-  <java-symbol type="string" name="granularity_label_link" />
-  <java-symbol type="string" name="granularity_label_line" />
-  <java-symbol type="string" name="default_audio_route_name" />
-  <java-symbol type="string" name="default_audio_route_name_headphones" />
-  <java-symbol type="string" name="default_audio_route_name_dock_speakers" />
-  <java-symbol type="string" name="default_audio_route_name_hdmi" />
-  <java-symbol type="string" name="default_audio_route_category_name" />
-
-  <java-symbol type="plurals" name="abbrev_in_num_days" />
-  <java-symbol type="plurals" name="abbrev_in_num_hours" />
-  <java-symbol type="plurals" name="abbrev_in_num_minutes" />
-  <java-symbol type="plurals" name="abbrev_in_num_seconds" />
-  <java-symbol type="plurals" name="abbrev_num_days_ago" />
-  <java-symbol type="plurals" name="abbrev_num_hours_ago" />
-  <java-symbol type="plurals" name="abbrev_num_minutes_ago" />
-  <java-symbol type="plurals" name="abbrev_num_seconds_ago" />
-  <java-symbol type="plurals" name="in_num_days" />
-  <java-symbol type="plurals" name="in_num_hours" />
-  <java-symbol type="plurals" name="in_num_minutes" />
-  <java-symbol type="plurals" name="in_num_seconds" />
-  <java-symbol type="plurals" name="last_num_days" />
-  <java-symbol type="plurals" name="matches_found" />
-  <java-symbol type="plurals" name="num_days_ago" />
-  <java-symbol type="plurals" name="num_hours_ago" />
-  <java-symbol type="plurals" name="num_minutes_ago" />
-  <java-symbol type="plurals" name="num_seconds_ago" />
-
-  <java-symbol type="array" name="carrier_properties" />
-  <java-symbol type="array" name="config_data_usage_network_types" />
-  <java-symbol type="array" name="config_sms_enabled_locking_shift_tables" />
-  <java-symbol type="array" name="config_sms_enabled_single_shift_tables" />
-  <java-symbol type="array" name="config_twoDigitNumberPattern" />
-  <java-symbol type="array" name="networkAttributes" />
-  <java-symbol type="array" name="preloaded_color_state_lists" />
-  <java-symbol type="array" name="preloaded_drawables" />
-  <java-symbol type="array" name="special_locale_codes" />
-  <java-symbol type="array" name="special_locale_names" />
-  <java-symbol type="array" name="config_masterVolumeRamp" />
-  <java-symbol type="array" name="config_cdma_dun_supported_types" />
-
-  <java-symbol type="drawable" name="default_wallpaper" />
-  <java-symbol type="drawable" name="ic_suggestions_add" />
-  <java-symbol type="drawable" name="ic_suggestions_delete" />
-  <java-symbol type="drawable" name="indicator_input_error" />
-  <java-symbol type="drawable" name="overscroll_edge" />
-  <java-symbol type="drawable" name="overscroll_glow" />
-  <java-symbol type="drawable" name="popup_bottom_dark" />
-  <java-symbol type="drawable" name="popup_bottom_bright" />
-  <java-symbol type="drawable" name="popup_bottom_medium" />
-  <java-symbol type="drawable" name="popup_center_dark" />
-  <java-symbol type="drawable" name="popup_center_bright" />
-  <java-symbol type="drawable" name="popup_full_dark" />
-  <java-symbol type="drawable" name="popup_full_bright" />
-  <java-symbol type="drawable" name="popup_top_dark" />
-  <java-symbol type="drawable" name="popup_top_bright" />
-  <java-symbol type="drawable" name="search_spinner" />
-  <java-symbol type="drawable" name="sym_app_on_sd_unavailable_icon" />
-  <java-symbol type="drawable" name="text_edit_side_paste_window" />
-  <java-symbol type="drawable" name="text_edit_paste_window" />
-  <java-symbol type="drawable" name="btn_check_off" />
-  <java-symbol type="drawable" name="btn_code_lock_default_holo" />
-  <java-symbol type="drawable" name="btn_code_lock_touched_holo" />
-  <java-symbol type="drawable" name="clock_dial" />
-  <java-symbol type="drawable" name="clock_hand_hour" />
-  <java-symbol type="drawable" name="clock_hand_minute" />
-  <java-symbol type="drawable" name="emo_im_angel" />
-  <java-symbol type="drawable" name="emo_im_cool" />
-  <java-symbol type="drawable" name="emo_im_crying" />
-  <java-symbol type="drawable" name="emo_im_embarrassed" />
-  <java-symbol type="drawable" name="emo_im_foot_in_mouth" />
-  <java-symbol type="drawable" name="emo_im_happy" />
-  <java-symbol type="drawable" name="emo_im_kissing" />
-  <java-symbol type="drawable" name="emo_im_laughing" />
-  <java-symbol type="drawable" name="emo_im_lips_are_sealed" />
-  <java-symbol type="drawable" name="emo_im_money_mouth" />
-  <java-symbol type="drawable" name="emo_im_sad" />
-  <java-symbol type="drawable" name="emo_im_surprised" />
-  <java-symbol type="drawable" name="emo_im_tongue_sticking_out" />
-  <java-symbol type="drawable" name="emo_im_undecided" />
-  <java-symbol type="drawable" name="emo_im_winking" />
-  <java-symbol type="drawable" name="emo_im_wtf" />
-  <java-symbol type="drawable" name="emo_im_yelling" />
-  <java-symbol type="drawable" name="expander_close_holo_dark" />
-  <java-symbol type="drawable" name="expander_open_holo_dark" />
-  <java-symbol type="drawable" name="ic_audio_alarm" />
-  <java-symbol type="drawable" name="ic_audio_alarm_mute" />
-  <java-symbol type="drawable" name="ic_audio_bt" />
-  <java-symbol type="drawable" name="ic_audio_bt_mute" />
-  <java-symbol type="drawable" name="ic_audio_notification" />
-  <java-symbol type="drawable" name="ic_audio_notification_mute" />
-  <java-symbol type="drawable" name="ic_audio_phone" />
-  <java-symbol type="drawable" name="ic_audio_ring_notif" />
-  <java-symbol type="drawable" name="ic_audio_ring_notif_mute" />
-  <java-symbol type="drawable" name="ic_audio_ring_notif_vibrate" />
-  <java-symbol type="drawable" name="ic_audio_vol" />
-  <java-symbol type="drawable" name="ic_audio_vol_mute" />
-  <java-symbol type="drawable" name="ic_bullet_key_permission" />
-  <java-symbol type="drawable" name="ic_contact_picture" />
-  <java-symbol type="drawable" name="ic_dialog_usb" />
-  <java-symbol type="drawable" name="ic_emergency" />
-  <java-symbol type="drawable" name="ic_media_stop" />
-  <java-symbol type="drawable" name="ic_text_dot" />
-  <java-symbol type="drawable" name="indicator_code_lock_drag_direction_green_up" />
-  <java-symbol type="drawable" name="indicator_code_lock_drag_direction_red_up" />
-  <java-symbol type="drawable" name="indicator_code_lock_point_area_default_holo" />
-  <java-symbol type="drawable" name="indicator_code_lock_point_area_green_holo" />
-  <java-symbol type="drawable" name="indicator_code_lock_point_area_red_holo" />
-  <java-symbol type="drawable" name="jog_dial_arrow_long_left_green" />
-  <java-symbol type="drawable" name="jog_dial_arrow_long_right_red" />
-  <java-symbol type="drawable" name="jog_dial_arrow_short_left_and_right" />
-  <java-symbol type="drawable" name="jog_dial_bg" />
-  <java-symbol type="drawable" name="jog_dial_dimple" />
-  <java-symbol type="drawable" name="jog_dial_dimple_dim" />
-  <java-symbol type="drawable" name="jog_tab_bar_left_generic" />
-  <java-symbol type="drawable" name="jog_tab_bar_right_generic" />
-  <java-symbol type="drawable" name="jog_tab_left_generic" />
-  <java-symbol type="drawable" name="jog_tab_right_generic" />
-  <java-symbol type="drawable" name="jog_tab_target_gray" />
-  <java-symbol type="drawable" name="picture_emergency" />
-  <java-symbol type="drawable" name="platlogo" />
-  <java-symbol type="drawable" name="platlogo_alt" />
-  <java-symbol type="drawable" name="stat_notify_sync_error" />
-  <java-symbol type="drawable" name="stat_notify_wifi_in_range" />
-  <java-symbol type="drawable" name="stat_sys_gps_on" />
-  <java-symbol type="drawable" name="stat_sys_tether_wifi" />
-  <java-symbol type="drawable" name="status_bar_background" />
-  <java-symbol type="drawable" name="sym_keyboard_shift" />
-  <java-symbol type="drawable" name="sym_keyboard_shift_locked" />
-  <java-symbol type="drawable" name="tab_bottom_left" />
-  <java-symbol type="drawable" name="tab_bottom_left_v4" />
-  <java-symbol type="drawable" name="tab_bottom_right" />
-  <java-symbol type="drawable" name="tab_bottom_right_v4" />
-  <java-symbol type="drawable" name="tab_indicator_v4" />
-  <java-symbol type="drawable" name="text_select_handle_left" />
-  <java-symbol type="drawable" name="text_select_handle_middle" />
-  <java-symbol type="drawable" name="text_select_handle_right" />
-  <java-symbol type="drawable" name="unknown_image" />
-  <java-symbol type="drawable" name="unlock_default" />
-  <java-symbol type="drawable" name="unlock_halo" />
-  <java-symbol type="drawable" name="unlock_ring" />
-  <java-symbol type="drawable" name="unlock_wave" />
-  <java-symbol type="drawable" name="ic_lockscreen_camera" />
-  <java-symbol type="drawable" name="ic_lockscreen_silent" />
-  <java-symbol type="drawable" name="ic_lockscreen_unlock" />
-  <java-symbol type="drawable" name="ic_action_assist_generic" />
-  <java-symbol type="drawable" name="notification_bg" />
-  <java-symbol type="drawable" name="notification_bg_low" />
-  <java-symbol type="drawable" name="notification_template_icon_bg" />
-  <java-symbol type="drawable" name="notification_template_icon_low_bg" />
-  <java-symbol type="drawable" name="ic_lockscreen_unlock_phantom" />
-  <java-symbol type="drawable" name="ic_media_route_on_holo_dark" />
-  <java-symbol type="drawable" name="ic_media_route_disabled_holo_dark" />
-
-  <java-symbol type="layout" name="action_bar_home" />
-  <java-symbol type="layout" name="action_bar_title_item" />
-  <java-symbol type="layout" name="action_menu_item_layout" />
-  <java-symbol type="layout" name="action_menu_layout" />
-  <java-symbol type="layout" name="action_mode_close_item" />
-  <java-symbol type="layout" name="alert_dialog" />
-  <java-symbol type="layout" name="choose_account" />
-  <java-symbol type="layout" name="choose_account_row" />
-  <java-symbol type="layout" name="choose_account_type" />
-  <java-symbol type="layout" name="choose_type_and_account" />
-  <java-symbol type="layout" name="grant_credentials_permission" />
-  <java-symbol type="layout" name="number_picker" />
-  <java-symbol type="layout" name="permissions_package_list_item" />
-  <java-symbol type="layout" name="popup_menu_item_layout" />
-  <java-symbol type="layout" name="remote_views_adapter_default_loading_view" />
-  <java-symbol type="layout" name="search_bar" />
-  <java-symbol type="layout" name="search_dropdown_item_icons_2line" />
-  <java-symbol type="layout" name="search_view" />
-  <java-symbol type="layout" name="select_dialog" />
-  <java-symbol type="layout" name="simple_dropdown_hint" />
-  <java-symbol type="layout" name="status_bar_latest_event_content" />
-  <java-symbol type="layout" name="status_bar_latest_event_ticker" />
-  <java-symbol type="layout" name="status_bar_latest_event_ticker_large_icon" />
-  <java-symbol type="layout" name="text_edit_action_popup_text" />
-  <java-symbol type="layout" name="text_drag_thumbnail" />
-  <java-symbol type="layout" name="typing_filter" />
-  <java-symbol type="layout" name="activity_chooser_view" />
-  <java-symbol type="layout" name="activity_chooser_view_list_item" />
-  <java-symbol type="layout" name="activity_list" />
-  <java-symbol type="layout" name="activity_list_item_2" />
-  <java-symbol type="layout" name="alert_dialog_progress" />
-  <java-symbol type="layout" name="always_use_checkbox" />
-  <java-symbol type="layout" name="app_permission_item" />
-  <java-symbol type="layout" name="app_permission_item_old" />
-  <java-symbol type="layout" name="app_perms_summary" />
-  <java-symbol type="layout" name="calendar_view" />
-  <java-symbol type="layout" name="character_picker" />
-  <java-symbol type="layout" name="character_picker_button" />
-  <java-symbol type="layout" name="date_picker" />
-  <java-symbol type="layout" name="date_picker_dialog" />
-  <java-symbol type="layout" name="expanded_menu_layout" />
-  <java-symbol type="layout" name="fragment_bread_crumb_item" />
-  <java-symbol type="layout" name="fragment_bread_crumbs" />
-  <java-symbol type="layout" name="heavy_weight_switcher" />
-  <java-symbol type="layout" name="icon_menu_item_layout" />
-  <java-symbol type="layout" name="icon_menu_layout" />
-  <java-symbol type="layout" name="input_method" />
-  <java-symbol type="layout" name="input_method_extract_view" />
-  <java-symbol type="layout" name="input_method_switch_dialog_title" />
-  <java-symbol type="layout" name="js_prompt" />
-  <java-symbol type="layout" name="list_content_simple" />
-  <java-symbol type="layout" name="list_menu_item_checkbox" />
-  <java-symbol type="layout" name="list_menu_item_icon" />
-  <java-symbol type="layout" name="list_menu_item_layout" />
-  <java-symbol type="layout" name="list_menu_item_radio" />
-  <java-symbol type="layout" name="locale_picker_item" />
-  <java-symbol type="layout" name="media_controller" />
-  <java-symbol type="layout" name="preference" />
-  <java-symbol type="layout" name="preference_header_item" />
-  <java-symbol type="layout" name="preference_list_content" />
-  <java-symbol type="layout" name="preference_list_content_single" />
-  <java-symbol type="layout" name="preference_list_fragment" />
-  <java-symbol type="layout" name="preference_widget_seekbar" />
-  <java-symbol type="layout" name="progress_dialog" />
-  <java-symbol type="layout" name="resolve_list_item" />
-  <java-symbol type="layout" name="seekbar_dialog" />
-  <java-symbol type="layout" name="select_dialog_singlechoice_holo" />
-  <java-symbol type="layout" name="ssl_certificate" />
-  <java-symbol type="layout" name="tab_content" />
-  <java-symbol type="layout" name="tab_indicator_holo" />
-  <java-symbol type="layout" name="textview_hint" />
-  <java-symbol type="layout" name="time_picker" />
-  <java-symbol type="layout" name="time_picker_dialog" />
-  <java-symbol type="layout" name="transient_notification" />
-  <java-symbol type="layout" name="volume_adjust" />
-  <java-symbol type="layout" name="volume_adjust_item" />
-  <java-symbol type="layout" name="web_text_view_dropdown" />
-  <java-symbol type="layout" name="webview_find" />
-  <java-symbol type="layout" name="webview_select_singlechoice" />
-  <java-symbol type="layout" name="wifi_p2p_dialog" />
-  <java-symbol type="layout" name="wifi_p2p_dialog_row" />
-  <java-symbol type="layout" name="zoom_container" />
-  <java-symbol type="layout" name="zoom_controls" />
-  <java-symbol type="layout" name="zoom_magnify" />
-  <java-symbol type="layout" name="notification_action" />
-  <java-symbol type="layout" name="notification_action_tombstone" />
-  <java-symbol type="layout" name="notification_intruder_content" />
-  <java-symbol type="layout" name="notification_template_base" />
-  <java-symbol type="layout" name="notification_template_big_base" />
-  <java-symbol type="layout" name="notification_template_big_picture" />
-  <java-symbol type="layout" name="notification_template_big_text" />
-  <java-symbol type="layout" name="notification_template_part_time" />
-  <java-symbol type="layout" name="notification_template_part_chronometer" />
-  <java-symbol type="layout" name="notification_template_inbox" />
-
-  <java-symbol type="anim" name="slide_in_child_bottom" />
-  <java-symbol type="anim" name="slide_in_right" />
-  <java-symbol type="anim" name="slide_out_left" />
-
-  <java-symbol type="menu" name="webview_copy" />
-  <java-symbol type="menu" name="webview_find" />
-
-  <java-symbol type="xml" name="password_kbd_qwerty" />
-  <java-symbol type="xml" name="autotext" />
-  <java-symbol type="xml" name="eri" />
-  <java-symbol type="xml" name="password_kbd_numeric" />
-  <java-symbol type="xml" name="password_kbd_qwerty_shifted" />
-  <java-symbol type="xml" name="password_kbd_symbols" />
-  <java-symbol type="xml" name="password_kbd_symbols_shift" />
-  <java-symbol type="xml" name="power_profile" />
-  <java-symbol type="xml" name="time_zones_by_country" />
-  <java-symbol type="xml" name="sms_short_codes" />
-
-  <java-symbol type="raw" name="accessibility_gestures" />
-  <java-symbol type="raw" name="incognito_mode_start_page" />
-  <java-symbol type="raw" name="loaderror" />
-  <java-symbol type="raw" name="nodomain" />
-
-  <java-symbol type="style" name="Animation.DropDownUp" />
-  <java-symbol type="style" name="Animation.DropDownDown" />
-  <java-symbol type="style" name="Animation.PopupWindow" />
-  <java-symbol type="style" name="Animation.TypingFilter" />
-  <java-symbol type="style" name="Animation.TypingFilterRestore" />
-  <java-symbol type="style" name="Animation.Dream" />
-  <java-symbol type="style" name="Theme.DeviceDefault.Dialog.Alert" />
-  <java-symbol type="style" name="Theme.DeviceDefault.Light.Dialog.Alert" />
-  <java-symbol type="style" name="Theme.Dialog.Alert" />
-  <java-symbol type="style" name="Theme.Holo.Dialog.Alert" />
-  <java-symbol type="style" name="Theme.Holo.Light.Dialog.Alert" />
-  <java-symbol type="style" name="ActiveWallpaperSettings" />
-  <java-symbol type="style" name="Animation.InputMethodFancy" />
-  <java-symbol type="style" name="Animation.Wallpaper" />
-  <java-symbol type="style" name="Animation.ZoomButtons" />
-  <java-symbol type="style" name="PreviewWallpaperSettings" />
-  <java-symbol type="style" name="TextAppearance.SlidingTabActive" />
-  <java-symbol type="style" name="TextAppearance.SlidingTabNormal" />
-  <java-symbol type="style" name="Theme.DeviceDefault.Dialog.NoFrame" />
-  <java-symbol type="style" name="Theme.IconMenu" />
-  <java-symbol type="style" name="Theme.Panel.Volume" />
-
-  <java-symbol type="attr" name="mediaRouteButtonStyle" />
-  <java-symbol type="attr" name="externalRouteEnabledDrawable" />
-  <java-symbol type="id" name="extended_settings" />
-  <java-symbol type="id" name="check" />
-  <java-symbol type="id" name="volume_slider" />
-  <java-symbol type="id" name="volume_icon" />
-  <java-symbol type="drawable" name="ic_media_route_on_holo_dark" />
-  <java-symbol type="layout" name="media_route_chooser_layout" />
-  <java-symbol type="layout" name="media_route_list_item_top_header" />
-  <java-symbol type="layout" name="media_route_list_item_section_header" />
-  <java-symbol type="layout" name="media_route_list_item" />
-  <java-symbol type="layout" name="media_route_list_item_checkable" />
-  <java-symbol type="layout" name="media_route_list_item_collapse_group" />
-  <java-symbol type="string" name="bluetooth_a2dp_audio_route_name" />
-
-  <!-- From android.policy -->
-  <java-symbol type="anim" name="app_starting_exit" />
-  <java-symbol type="anim" name="lock_screen_behind_enter" />
-  <java-symbol type="anim" name="lock_screen_wallpaper_behind_enter" />
-  <java-symbol type="anim" name="dock_top_enter" />
-  <java-symbol type="anim" name="dock_top_exit" />
-  <java-symbol type="anim" name="dock_bottom_enter" />
-  <java-symbol type="anim" name="dock_bottom_exit" />
-  <java-symbol type="anim" name="dock_left_enter" />
-  <java-symbol type="anim" name="dock_left_exit" />
-  <java-symbol type="anim" name="dock_right_enter" />
-  <java-symbol type="anim" name="dock_right_exit" />
-  <java-symbol type="array" name="config_keyboardTapVibePattern" />
-  <java-symbol type="array" name="config_longPressVibePattern" />
-  <java-symbol type="array" name="config_safeModeDisabledVibePattern" />
-  <java-symbol type="array" name="config_safeModeEnabledVibePattern" />
-  <java-symbol type="array" name="config_virtualKeyVibePattern" />
-  <java-symbol type="array" name="lockscreen_targets_when_silent" />
-  <java-symbol type="array" name="lockscreen_targets_when_soundon" />
-  <java-symbol type="array" name="lockscreen_targets_with_camera" />
-  <java-symbol type="attr" name="actionModePopupWindowStyle" />
-  <java-symbol type="attr" name="dialogCustomTitleDecorLayout" />
-  <java-symbol type="attr" name="dialogTitleDecorLayout" />
-  <java-symbol type="attr" name="dialogTitleIconsDecorLayout" />
-  <java-symbol type="bool" name="config_allowAllRotations" />
-  <java-symbol type="bool" name="config_annoy_dianne" />
-  <java-symbol type="bool" name="config_carDockEnablesAccelerometer" />
-  <java-symbol type="bool" name="config_deskDockEnablesAccelerometer" />
-  <java-symbol type="bool" name="config_disableMenuKeyInLockScreen" />
-  <java-symbol type="bool" name="config_enableLockBeforeUnlockScreen" />
-  <java-symbol type="bool" name="config_enableLockScreenRotation" />
-  <java-symbol type="bool" name="config_lidControlsSleep" />
-  <java-symbol type="bool" name="config_reverseDefaultRotation" />
-  <java-symbol type="bool" name="config_showNavigationBar" />
-  <java-symbol type="bool" name="target_honeycomb_needs_options_menu" />
-  <java-symbol type="dimen" name="navigation_bar_height" />
-  <java-symbol type="dimen" name="navigation_bar_height_landscape" />
-  <java-symbol type="dimen" name="navigation_bar_width" />
-  <java-symbol type="dimen" name="status_bar_height" />
-  <java-symbol type="drawable" name="ic_jog_dial_sound_off" />
-  <java-symbol type="drawable" name="ic_jog_dial_sound_on" />
-  <java-symbol type="drawable" name="ic_jog_dial_unlock" />
-  <java-symbol type="drawable" name="ic_jog_dial_vibrate_on" />
-  <java-symbol type="drawable" name="ic_lock_airplane_mode" />
-  <java-symbol type="drawable" name="ic_lock_airplane_mode_off" />
-  <java-symbol type="drawable" name="ic_menu_cc" />
-  <java-symbol type="drawable" name="jog_tab_bar_left_unlock" />
-  <java-symbol type="drawable" name="jog_tab_bar_right_sound_off" />
-  <java-symbol type="drawable" name="jog_tab_bar_right_sound_on" />
-  <java-symbol type="drawable" name="jog_tab_left_unlock" />
-  <java-symbol type="drawable" name="jog_tab_right_sound_off" />
-  <java-symbol type="drawable" name="jog_tab_right_sound_on" />
-  <java-symbol type="drawable" name="jog_tab_target_green" />
-  <java-symbol type="drawable" name="jog_tab_target_yellow" />
-  <java-symbol type="drawable" name="menu_background" />
-  <java-symbol type="drawable" name="stat_sys_secure" />
-  <java-symbol type="id" name="action_mode_bar_stub" />
-  <java-symbol type="id" name="alarm_status" />
-  <java-symbol type="id" name="backspace" />
-  <java-symbol type="id" name="button0" />
-  <java-symbol type="id" name="button4" />
-  <java-symbol type="id" name="button5" />
-  <java-symbol type="id" name="button6" />
-  <java-symbol type="id" name="button7" />
-  <java-symbol type="id" name="carrier" />
-  <java-symbol type="id" name="date" />
-  <java-symbol type="id" name="eight" />
-  <java-symbol type="id" name="emergencyCallButton" />
-  <java-symbol type="id" name="faceLockAreaView" />
-  <java-symbol type="id" name="five" />
-  <java-symbol type="id" name="forgotPatternButton" />
-  <java-symbol type="id" name="four" />
-  <java-symbol type="id" name="headerText" />
-  <java-symbol type="id" name="icon_menu_presenter" />
-  <java-symbol type="id" name="instructions" />
-  <java-symbol type="id" name="keyboard" />
-  <java-symbol type="id" name="list_menu_presenter" />
-  <java-symbol type="id" name="lockPattern" />
-  <java-symbol type="id" name="lock_screen" />
-  <java-symbol type="id" name="login" />
-  <java-symbol type="id" name="nine" />
-  <java-symbol type="id" name="no_applications_message" />
-  <java-symbol type="id" name="ok" />
-  <java-symbol type="id" name="one" />
-  <java-symbol type="id" name="option1" />
-  <java-symbol type="id" name="option2" />
-  <java-symbol type="id" name="option3" />
-  <java-symbol type="id" name="password" />
-  <java-symbol type="id" name="passwordEntry" />
-  <java-symbol type="id" name="pinDel" />
-  <java-symbol type="id" name="pinDisplay" />
-  <java-symbol type="id" name="propertyOf" />
-  <java-symbol type="id" name="pukDel" />
-  <java-symbol type="id" name="pukDisplay" />
-  <java-symbol type="id" name="right_icon" />
-  <java-symbol type="id" name="seven" />
-  <java-symbol type="id" name="six" />
-  <java-symbol type="id" name="status" />
-  <java-symbol type="id" name="status1" />
-  <java-symbol type="id" name="switch_ime_button" />
-  <java-symbol type="id" name="three" />
-  <java-symbol type="id" name="title_container" />
-  <java-symbol type="id" name="topHeader" />
-  <java-symbol type="id" name="transport" />
-  <java-symbol type="id" name="transport_bg_protect" />
-  <java-symbol type="id" name="two" />
-  <java-symbol type="id" name="unlock_widget" />
-  <java-symbol type="id" name="zero" />
-  <java-symbol type="integer" name="config_carDockRotation" />
-  <java-symbol type="integer" name="config_defaultUiModeType" />
-  <java-symbol type="integer" name="config_deskDockRotation" />
-  <java-symbol type="integer" name="config_lidKeyboardAccessibility" />
-  <java-symbol type="integer" name="config_lidNavigationAccessibility" />
-  <java-symbol type="integer" name="config_lidOpenRotation" />
-  <java-symbol type="integer" name="config_longPressOnHomeBehavior" />
-  <java-symbol type="layout" name="global_actions_item" />
-  <java-symbol type="layout" name="global_actions_silent_mode" />
-  <java-symbol type="layout" name="keyguard_screen_glogin_unlock" />
-  <java-symbol type="layout" name="keyguard_screen_password_landscape" />
-  <java-symbol type="layout" name="keyguard_screen_password_portrait" />
-  <java-symbol type="layout" name="keyguard_screen_sim_pin_landscape" />
-  <java-symbol type="layout" name="keyguard_screen_sim_pin_portrait" />
-  <java-symbol type="layout" name="keyguard_screen_sim_puk_landscape" />
-  <java-symbol type="layout" name="keyguard_screen_sim_puk_portrait" />
-  <java-symbol type="layout" name="keyguard_screen_tab_unlock" />
-  <java-symbol type="layout" name="keyguard_screen_tab_unlock_land" />
-  <java-symbol type="layout" name="keyguard_screen_unlock_landscape" />
-  <java-symbol type="layout" name="keyguard_screen_unlock_portrait" />
-  <java-symbol type="layout" name="recent_apps_dialog" />
-  <java-symbol type="layout" name="screen_action_bar" />
-  <java-symbol type="layout" name="screen_action_bar_overlay" />
-  <java-symbol type="layout" name="screen_custom_title" />
-  <java-symbol type="layout" name="screen_progress" />
-  <java-symbol type="layout" name="screen_simple" />
-  <java-symbol type="layout" name="screen_simple_overlay_action_mode" />
-  <java-symbol type="layout" name="screen_title" />
-  <java-symbol type="layout" name="screen_title_icons" />
-  <java-symbol type="string" name="abbrev_wday_month_day_no_year" />
-  <java-symbol type="string" name="android_upgrading_title" />
-  <java-symbol type="string" name="faceunlock_multiple_failures" />
-  <java-symbol type="string" name="global_action_power_off" />
-  <java-symbol type="string" name="global_actions_airplane_mode_off_status" />
-  <java-symbol type="string" name="global_actions_airplane_mode_on_status" />
-  <java-symbol type="string" name="global_actions_toggle_airplane_mode" />
-  <java-symbol type="string" name="global_action_silent_mode_off_status" />
-  <java-symbol type="string" name="global_action_silent_mode_on_status" />
-  <java-symbol type="string" name="global_action_toggle_silent_mode" />
-  <java-symbol type="string" name="invalidPuk" />
-  <java-symbol type="string" name="keyguard_password_enter_pin_code" />
-  <java-symbol type="string" name="keyguard_password_enter_puk_code" />
-  <java-symbol type="string" name="keyguard_password_wrong_pin_code" />
-  <java-symbol type="string" name="lockscreen_carrier_default" />
-  <java-symbol type="string" name="lockscreen_charged" />
-  <java-symbol type="string" name="lockscreen_failed_attempts_almost_at_wipe" />
-  <java-symbol type="string" name="lockscreen_failed_attempts_almost_glogin" />
-  <java-symbol type="string" name="lockscreen_failed_attempts_now_wiping" />
-  <java-symbol type="string" name="lockscreen_forgot_pattern_button_text" />
-  <java-symbol type="string" name="lockscreen_glogin_checking_password" />
-  <java-symbol type="string" name="lockscreen_glogin_forgot_pattern" />
-  <java-symbol type="string" name="lockscreen_glogin_invalid_input" />
-  <java-symbol type="string" name="lockscreen_glogin_too_many_attempts" />
-  <java-symbol type="string" name="lockscreen_instructions_when_pattern_disabled" />
-  <java-symbol type="string" name="lockscreen_low_battery" />
-  <java-symbol type="string" name="lockscreen_missing_sim_instructions" />
-  <java-symbol type="string" name="lockscreen_missing_sim_instructions_long" />
-  <java-symbol type="string" name="lockscreen_missing_sim_message_short" />
-  <java-symbol type="string" name="lockscreen_network_locked_message" />
-  <java-symbol type="string" name="lockscreen_password_wrong" />
-  <java-symbol type="string" name="lockscreen_pattern_instructions" />
-  <java-symbol type="string" name="lockscreen_pattern_wrong" />
-  <java-symbol type="string" name="lockscreen_permanent_disabled_sim_message_short" />
-  <java-symbol type="string" name="lockscreen_permanent_disabled_sim_instructions" />
-  <java-symbol type="string" name="lockscreen_plugged_in" />
-  <java-symbol type="string" name="lockscreen_sim_locked_message" />
-  <java-symbol type="string" name="lockscreen_sim_puk_locked_message" />
-  <java-symbol type="string" name="lockscreen_sim_unlock_progress_dialog_message" />
-  <java-symbol type="string" name="lockscreen_sound_off_label" />
-  <java-symbol type="string" name="lockscreen_sound_on_label" />
-  <java-symbol type="string" name="lockscreen_too_many_failed_attempts_countdown" />
-  <java-symbol type="string" name="lockscreen_too_many_failed_attempts_dialog_message" />
-  <java-symbol type="string" name="lockscreen_too_many_failed_password_attempts_dialog_message" />
-  <java-symbol type="string" name="lockscreen_too_many_failed_pin_attempts_dialog_message" />
-  <java-symbol type="string" name="lockscreen_unlock_label" />
-  <java-symbol type="string" name="status_bar_device_locked" />
-  <java-symbol type="style" name="Animation.LockScreen" />
-  <java-symbol type="style" name="Theme.Dialog.RecentApplications" />
-  <java-symbol type="style" name="Theme.ExpandedMenu" />
-
-  <!-- From services -->
-  <java-symbol type="anim" name="screen_rotate_0_enter" />
-  <java-symbol type="anim" name="screen_rotate_0_exit" />
-  <java-symbol type="anim" name="screen_rotate_0_frame" />
-  <java-symbol type="anim" name="screen_rotate_180_enter" />
-  <java-symbol type="anim" name="screen_rotate_180_exit" />
-  <java-symbol type="anim" name="screen_rotate_180_frame" />
-  <java-symbol type="anim" name="screen_rotate_finish_enter" />
-  <java-symbol type="anim" name="screen_rotate_finish_exit" />
-  <java-symbol type="anim" name="screen_rotate_finish_frame" />
-  <java-symbol type="anim" name="screen_rotate_minus_90_enter" />
-  <java-symbol type="anim" name="screen_rotate_minus_90_exit" />
-  <java-symbol type="anim" name="screen_rotate_minus_90_frame" />
-  <java-symbol type="anim" name="screen_rotate_plus_90_enter" />
-  <java-symbol type="anim" name="screen_rotate_plus_90_exit" />
-  <java-symbol type="anim" name="screen_rotate_plus_90_frame" />
-  <java-symbol type="anim" name="screen_rotate_start_enter" />
-  <java-symbol type="anim" name="screen_rotate_start_exit" />
-  <java-symbol type="anim" name="screen_rotate_start_frame" />
-  <java-symbol type="anim" name="window_move_from_decor" />
-  <java-symbol type="array" name="config_autoBrightnessButtonBacklightValues" />
-  <java-symbol type="array" name="config_autoBrightnessKeyboardBacklightValues" />
-  <java-symbol type="array" name="config_autoBrightnessLcdBacklightValues" />
-  <java-symbol type="array" name="config_autoBrightnessLevels" />
-  <java-symbol type="array" name="config_protectedNetworks" />
-  <java-symbol type="array" name="config_statusBarIcons" />
-  <java-symbol type="array" name="config_tether_bluetooth_regexs" />
-  <java-symbol type="array" name="config_tether_dhcp_range" />
-  <java-symbol type="array" name="config_tether_upstream_types" />
-  <java-symbol type="array" name="config_tether_usb_regexs" />
-  <java-symbol type="array" name="config_tether_wifi_regexs" />
-  <java-symbol type="array" name="config_usbHostBlacklist" />
-  <java-symbol type="array" name="config_serialPorts" />
-  <java-symbol type="array" name="radioAttributes" />
-  <java-symbol type="array" name="config_oemUsbModeOverride" />
-  <java-symbol type="bool" name="config_animateScreenLights" />
-  <java-symbol type="bool" name="config_automatic_brightness_available" />
-  <java-symbol type="bool" name="config_sf_limitedAlpha" />
-  <java-symbol type="bool" name="config_unplugTurnsOnScreen" />
-  <java-symbol type="bool" name="config_wifi_background_scan_support" />
-  <java-symbol type="bool" name="config_wifi_dual_band_support" />
-  <java-symbol type="bool" name="config_wimaxEnabled" />
-  <java-symbol type="bool" name="show_ongoing_ime_switcher" />
-  <java-symbol type="color" name="config_defaultNotificationColor" />
-  <java-symbol type="drawable" name="ic_notification_ime_default" />
-  <java-symbol type="drawable" name="stat_notify_car_mode" />
-  <java-symbol type="drawable" name="stat_notify_disabled" />
-  <java-symbol type="drawable" name="stat_notify_disk_full" />
-  <java-symbol type="drawable" name="stat_sys_adb" />
-  <java-symbol type="drawable" name="stat_sys_battery" />
-  <java-symbol type="drawable" name="stat_sys_battery_charge" />
-  <java-symbol type="drawable" name="stat_sys_battery_unknown" />
-  <java-symbol type="drawable" name="stat_sys_data_usb" />
-  <java-symbol type="drawable" name="stat_sys_tether_bluetooth" />
-  <java-symbol type="drawable" name="stat_sys_tether_general" />
-  <java-symbol type="drawable" name="stat_sys_tether_usb" />
-  <java-symbol type="drawable" name="stat_sys_throttled" />
-  <java-symbol type="drawable" name="vpn_connected" />
-  <java-symbol type="id" name="ask_checkbox" />
-  <java-symbol type="id" name="compat_checkbox" />
-  <java-symbol type="id" name="original_app_icon" />
-  <java-symbol type="id" name="original_message" />
-  <java-symbol type="id" name="radio" />
-  <java-symbol type="id" name="reask_hint" />
-  <java-symbol type="id" name="replace_app_icon" />
-  <java-symbol type="id" name="replace_message" />
-  <java-symbol type="fraction" name="config_dimBehindFadeDuration" />
-  <java-symbol type="integer" name="config_carDockKeepsScreenOn" />
-  <java-symbol type="integer" name="config_criticalBatteryWarningLevel" />
-  <java-symbol type="integer" name="config_datause_notification_type" />
-  <java-symbol type="integer" name="config_datause_polling_period_sec" />
-  <java-symbol type="integer" name="config_datause_threshold_bytes" />
-  <java-symbol type="integer" name="config_datause_throttle_kbitsps" />
-  <java-symbol type="integer" name="config_defaultNotificationLedOff" />
-  <java-symbol type="integer" name="config_defaultNotificationLedOn" />
-  <java-symbol type="integer" name="config_deskDockKeepsScreenOn" />
-  <java-symbol type="integer" name="config_lightSensorWarmupTime" />
-  <java-symbol type="integer" name="config_lowBatteryCloseWarningLevel" />
-  <java-symbol type="integer" name="config_lowBatteryWarningLevel" />
-  <java-symbol type="integer" name="config_networkPolicyDefaultWarning" />
-  <java-symbol type="integer" name="config_networkTransitionTimeout" />
-  <java-symbol type="integer" name="config_notificationsBatteryFullARGB" />
-  <java-symbol type="integer" name="config_notificationsBatteryLedOff" />
-  <java-symbol type="integer" name="config_notificationsBatteryLedOn" />
-  <java-symbol type="integer" name="config_notificationsBatteryLowARGB" />
-  <java-symbol type="integer" name="config_notificationsBatteryMediumARGB" />
-  <java-symbol type="integer" name="config_radioScanningTimeout" />
-  <java-symbol type="integer" name="config_screenBrightnessDim" />
-  <java-symbol type="integer" name="config_virtualKeyQuietTimeMillis" />
-  <java-symbol type="layout" name="am_compat_mode_dialog" />
-  <java-symbol type="layout" name="launch_warning" />
-  <java-symbol type="layout" name="safe_mode" />
-  <java-symbol type="layout" name="simple_list_item_2_single_choice" />
-  <java-symbol type="plurals" name="wifi_available" />
-  <java-symbol type="plurals" name="wifi_available_detailed" />
-  <java-symbol type="string" name="accessibility_binding_label" />
-  <java-symbol type="string" name="adb_active_notification_message" />
-  <java-symbol type="string" name="adb_active_notification_title" />
-  <java-symbol type="string" name="aerr_application" />
-  <java-symbol type="string" name="aerr_process" />
-  <java-symbol type="string" name="aerr_title" />
-  <java-symbol type="string" name="android_upgrading_apk" />
-  <java-symbol type="string" name="android_upgrading_complete" />
-  <java-symbol type="string" name="android_upgrading_starting_apps" />
-  <java-symbol type="string" name="anr_activity_application" />
-  <java-symbol type="string" name="anr_activity_process" />
-  <java-symbol type="string" name="anr_application_process" />
-  <java-symbol type="string" name="anr_process" />
-  <java-symbol type="string" name="anr_title" />
-  <java-symbol type="string" name="car_mode_disable_notification_message" />
-  <java-symbol type="string" name="car_mode_disable_notification_title" />
-  <java-symbol type="string" name="chooser_wallpaper" />
-  <java-symbol type="string" name="config_datause_iface" />
-  <java-symbol type="string" name="config_geocodeProviderPackageName" />
-  <java-symbol type="string" name="config_networkLocationProviderPackageName" />
-  <java-symbol type="string" name="config_wimaxManagerClassname" />
-  <java-symbol type="string" name="config_wimaxNativeLibLocation" />
-  <java-symbol type="string" name="config_wimaxServiceClassname" />
-  <java-symbol type="string" name="config_wimaxServiceJarLocation" />
-  <java-symbol type="string" name="config_wimaxStateTrackerClassname" />
-  <java-symbol type="string" name="configure_input_methods" />
-  <java-symbol type="string" name="data_usage_3g_limit_snoozed_title" />
-  <java-symbol type="string" name="data_usage_3g_limit_title" />
-  <java-symbol type="string" name="data_usage_4g_limit_snoozed_title" />
-  <java-symbol type="string" name="data_usage_4g_limit_title" />
-  <java-symbol type="string" name="data_usage_limit_body" />
-  <java-symbol type="string" name="data_usage_limit_snoozed_body" />
-  <java-symbol type="string" name="data_usage_mobile_limit_snoozed_title" />
-  <java-symbol type="string" name="data_usage_mobile_limit_title" />
-  <java-symbol type="string" name="data_usage_restricted_body" />
-  <java-symbol type="string" name="data_usage_restricted_title" />
-  <java-symbol type="string" name="data_usage_warning_body" />
-  <java-symbol type="string" name="data_usage_warning_title" />
-  <java-symbol type="string" name="data_usage_wifi_limit_snoozed_title" />
-  <java-symbol type="string" name="data_usage_wifi_limit_title" />
-  <java-symbol type="string" name="default_wallpaper_component" />
-  <java-symbol type="string" name="dlg_ok" />
-  <java-symbol type="string" name="factorytest_failed" />
-  <java-symbol type="string" name="factorytest_no_action" />
-  <java-symbol type="string" name="factorytest_not_system" />
-  <java-symbol type="string" name="factorytest_reboot" />
-  <java-symbol type="string" name="hardware" />
-  <java-symbol type="string" name="heavy_weight_notification" />
-  <java-symbol type="string" name="heavy_weight_notification_detail" />
-  <java-symbol type="string" name="input_method_binding_label" />
-  <java-symbol type="string" name="launch_warning_original" />
-  <java-symbol type="string" name="launch_warning_replace" />
-  <java-symbol type="string" name="launch_warning_title" />
-  <java-symbol type="string" name="low_internal_storage_view_text" />
-  <java-symbol type="string" name="low_internal_storage_view_title" />
-  <java-symbol type="string" name="report" />
-  <java-symbol type="string" name="select_input_method" />
-  <java-symbol type="string" name="select_keyboard_layout_notification_title" />
-  <java-symbol type="string" name="select_keyboard_layout_notification_message" />
-  <java-symbol type="string" name="smv_application" />
-  <java-symbol type="string" name="smv_process" />
-  <java-symbol type="string" name="tethered_notification_message" />
-  <java-symbol type="string" name="tethered_notification_title" />
-  <java-symbol type="string" name="throttle_warning_notification_message" />
-  <java-symbol type="string" name="throttle_warning_notification_title" />
-  <java-symbol type="string" name="throttled_notification_message" />
-  <java-symbol type="string" name="throttled_notification_title" />
-  <java-symbol type="string" name="usb_accessory_notification_title" />
-  <java-symbol type="string" name="usb_cd_installer_notification_title" />
-  <java-symbol type="string" name="usb_mtp_notification_title" />
-  <java-symbol type="string" name="usb_notification_message" />
-  <java-symbol type="string" name="use_physical_keyboard" />
-  <java-symbol type="string" name="usb_ptp_notification_title" />
-  <java-symbol type="string" name="vpn_text" />
-  <java-symbol type="string" name="vpn_text_long" />
-  <java-symbol type="string" name="vpn_title" />
-  <java-symbol type="string" name="vpn_title_long" />
-  <java-symbol type="string" name="wallpaper_binding_label" />
-  <java-symbol type="style" name="Theme.Dialog.AppError" />
-  <java-symbol type="style" name="Theme.Toast" />
-  <java-symbol type="xml" name="storage_list" />
-  <java-symbol type="bool" name="config_enableDreams" />
-  <java-symbol type="string" name="config_defaultDreamComponent" />
-  <java-symbol type="string" name="enable_explore_by_touch_warning_title" />
-  <java-symbol type="string" name="enable_explore_by_touch_warning_message" />
-
-  <java-symbol type="layout" name="resolver_grid" />
-  <java-symbol type="id" name="resolver_grid" />
-  <java-symbol type="id" name="button_once" />
-  <java-symbol type="id" name="button_always" />
-  <java-symbol type="integer" name="config_maxResolverActivityColumns" />
-
-  <!-- From SystemUI -->
-  <java-symbol type="anim" name="push_down_in" />
-  <java-symbol type="anim" name="push_down_out" />
-  <java-symbol type="anim" name="push_up_in" />
-  <java-symbol type="anim" name="push_up_out" />
-  <java-symbol type="bool" name="config_alwaysUseCdmaRssi" />
-  <java-symbol type="dimen" name="status_bar_icon_size" />
-  <java-symbol type="dimen" name="system_bar_icon_size" />
-  <java-symbol type="drawable" name="list_selector_pressed_holo_dark" />
-  <java-symbol type="drawable" name="scrubber_control_disabled_holo" />
-  <java-symbol type="drawable" name="scrubber_control_selector_holo" />
-  <java-symbol type="drawable" name="scrubber_progress_horizontal_holo_dark" />
-  <java-symbol type="drawable" name="usb_android" />
-  <java-symbol type="drawable" name="usb_android_connected" />
-  <java-symbol type="id" name="banner" />
-  <java-symbol type="id" name="mount_button" />
-  <java-symbol type="id" name="unmount_button" />
-  <java-symbol type="layout" name="usb_storage_activity" />
-  <java-symbol type="string" name="chooseUsbActivity" />
-  <java-symbol type="string" name="dlg_confirm_kill_storage_users_text" />
-  <java-symbol type="string" name="dlg_confirm_kill_storage_users_title" />
-  <java-symbol type="string" name="dlg_error_title" />
-  <java-symbol type="string" name="ext_media_badremoval_notification_message" />
-  <java-symbol type="string" name="ext_media_badremoval_notification_title" />
-  <java-symbol type="string" name="ext_media_checking_notification_message" />
-  <java-symbol type="string" name="ext_media_checking_notification_title" />
-  <java-symbol type="string" name="ext_media_nofs_notification_message" />
-  <java-symbol type="string" name="ext_media_nofs_notification_title" />
-  <java-symbol type="string" name="ext_media_nomedia_notification_message" />
-  <java-symbol type="string" name="ext_media_nomedia_notification_title" />
-  <java-symbol type="string" name="ext_media_safe_unmount_notification_message" />
-  <java-symbol type="string" name="ext_media_safe_unmount_notification_title" />
-  <java-symbol type="string" name="ext_media_unmountable_notification_message" />
-  <java-symbol type="string" name="ext_media_unmountable_notification_title" />
-  <java-symbol type="string" name="usb_storage_error_message" />
-  <java-symbol type="string" name="usb_storage_message" />
-  <java-symbol type="string" name="usb_storage_notification_message" />
-  <java-symbol type="string" name="usb_storage_notification_title" />
-  <java-symbol type="string" name="usb_storage_stop_message" />
-  <java-symbol type="string" name="usb_storage_stop_notification_message" />
-  <java-symbol type="string" name="usb_storage_stop_notification_title" />
-  <java-symbol type="string" name="usb_storage_stop_title" />
-  <java-symbol type="string" name="usb_storage_title" />
-  <java-symbol type="style" name="Animation.RecentApplications" />
-
-  <!-- ImfTest -->
-  <java-symbol type="layout" name="auto_complete_list" />
-
-  <!-- From SettingsProvider -->
-  <java-symbol type="raw" name="fallbackring" />
-
-  <!-- From Settings -->
-  <java-symbol type="array" name="config_mobile_hotspot_provision_app" />
-  <java-symbol type="bool" name="config_intrusiveNotificationLed" />
-  <java-symbol type="dimen" name="preference_fragment_padding_bottom" />
-  <java-symbol type="dimen" name="preference_fragment_padding_side" />
-  <java-symbol type="drawable" name="expander_ic_maximized" />
-  <java-symbol type="drawable" name="expander_ic_minimized" />
-  <java-symbol type="drawable" name="ic_menu_archive" />
-  <java-symbol type="drawable" name="ic_menu_goto" />
-  <java-symbol type="drawable" name="ic_settings_language" />
-  <java-symbol type="drawable" name="title_bar_medium" />
-  <java-symbol type="id" name="body" />
-  <java-symbol type="string" name="fast_scroll_alphabet" />
-  <java-symbol type="string" name="ssl_certificate" />
-
-  <!-- From Phone -->
-  <java-symbol type="bool" name="config_built_in_sip_phone" />
-
-  <!-- From TelephonyProvider -->
-  <java-symbol type="xml" name="apns" />
-
-  <!-- From ContactsProvider -->
-  <java-symbol type="array" name="common_nicknames" />
-  <java-symbol type="drawable" name="call_contact" />
-  <java-symbol type="drawable" name="create_contact" />
-  <java-symbol type="string" name="common_name_prefixes" />
-  <java-symbol type="string" name="common_last_name_prefixes" />
-  <java-symbol type="string" name="common_name_suffixes" />
-  <java-symbol type="string" name="common_name_conjunctions" />
-  <java-symbol type="string" name="dial_number_using" />
-  <java-symbol type="string" name="create_contact_using" />
-
-  <!-- From DownloadProvider -->
-  <java-symbol type="integer" name="config_MaxConcurrentDownloadsAllowed" />
-  <java-symbol type="integer" name="config_downloadDataDirSize" />
-  <java-symbol type="integer" name="config_downloadDataDirLowSpaceThreshold" />
-
-  <!-- From Contacts -->
-  <java-symbol type="drawable" name="quickcontact_badge_overlay_dark" />
-
-  <!-- From Browser -->
-  <java-symbol type="drawable" name="ic_menu_moreoverflow_normal_holo_dark" />
-  <java-symbol type="id" name="placeholder" />
-  <java-symbol type="string" name="ssl_certificate_is_valid" />
-
-  <!-- From Mms -->
-  <java-symbol type="drawable" name="ic_menu_play_clip" />
-
-  <!-- From Stk -->
-  <java-symbol type="bool" name="config_sf_slowBlur" />
-  <java-symbol type="drawable" name="ic_volume" />
-  <java-symbol type="drawable" name="stat_notify_sim_toolkit" />
-
-  <!-- From maps library -->
-  <java-symbol type="array" name="maps_starting_lat_lng" />
-  <java-symbol type="array" name="maps_starting_zoom" />
-  <java-symbol type="attr" name="mapViewStyle" />
-  <java-symbol type="attr" name="state_focused" />
-  <java-symbol type="attr" name="state_selected" />
-  <java-symbol type="attr" name="state_pressed" />
-  <java-symbol type="drawable" name="compass_arrow" />
-  <java-symbol type="drawable" name="compass_base" />
-  <java-symbol type="drawable" name="ic_maps_indicator_current_position_anim" />
-  <java-symbol type="drawable" name="loading_tile_android" />
-  <java-symbol type="drawable" name="maps_google_logo" />
-  <java-symbol type="drawable" name="no_tile_256" />
-  <java-symbol type="drawable" name="reticle" />
-
-  <!-- From PinyinIME(!!!) -->
-  <java-symbol type="string" name="inputMethod" />
-
-  <!-- AndroidManifest.xml attributes. -->
-  <eat-comment />
-
 <!-- ===============================================================
      Resources for version 1 of the platform.
      =============================================================== -->
@@ -3648,17 +1977,55 @@
      =============================================================== -->
   <eat-comment />
   <public type="attr" name="parentActivityName" id="0x010103a7" />
-  <public type="attr" name="permissionGroupFlags" id="0x010103a8" />
   <public type="attr" name="isolatedProcess" id="0x010103a9" />
   <public type="attr" name="importantForAccessibility" id="0x010103aa" />
   <public type="attr" name="keyboardLayout" id="0x010103ab" />
   <public type="attr" name="fontFamily" id="0x010103ac" />
-
   <public type="attr" name="mediaRouteButtonStyle" id="0x010103ad" />
   <public type="attr" name="mediaRouteTypes" id="0x010103ae" />
+
   <public type="style" name="Widget.Holo.MediaRouteButton" id="0x010301d5" />
   <public type="style" name="Widget.Holo.Light.MediaRouteButton" id="0x010301d6" />
   <public type="style" name="Widget.DeviceDefault.MediaRouteButton" id="0x010301d7" />
   <public type="style" name="Widget.DeviceDefault.Light.MediaRouteButton" id="0x010301d8" />
 
+<!-- ===============================================================
+     Resources added in version 17 of the platform (Jelly Bean MR1)
+     =============================================================== -->
+  <eat-comment />
+  <public type="attr" name="supportsRtl" id="0x010103af" />
+  <public type="attr" name="textDirection" id="0x010103b0" />
+  <public type="attr" name="textAlignment" id="0x010103b1" />
+  <public type="attr" name="layoutDirection" id="0x010103b2" />
+  <public type="attr" name="paddingStart" id="0x010103b3" />
+  <public type="attr" name="paddingEnd" id="0x010103b4" />
+  <public type="attr" name="layout_marginStart" id="0x010103b5" />
+  <public type="attr" name="layout_marginEnd" id="0x010103b6" />
+  <public type="attr" name="layout_toStartOf" id="0x010103b7" />
+  <public type="attr" name="layout_toEndOf" id="0x010103b8" />
+  <public type="attr" name="layout_alignStart" id="0x010103b9" />
+  <public type="attr" name="layout_alignEnd" id="0x010103ba" />
+  <public type="attr" name="layout_alignParentStart" id="0x010103bb" />
+  <public type="attr" name="layout_alignParentEnd" id="0x010103bc" />
+  <public type="attr" name="listPreferredItemPaddingStart" id="0x010103bd" />
+  <public type="attr" name="listPreferredItemPaddingEnd" id="0x010103be" />
+  <public type="attr" name="singleUser" id="0x010103bf" />
+  <public type="attr" name="presentationTheme" id="0x010103c0" />
+  <public type="attr" name="subtypeId" id="0x010103c1" />
+  <public type="attr" name="initialKeyguardLayout" id="0x010103c2" />
+  <public type="attr" name="widgetCategory" id="0x010103c4" />
+  <public type="attr" name="permissionGroupFlags" id="0x010103c5" />
+  <public type="attr" name="labelFor" id="0x010103c6" />
+  <public type="attr" name="permissionFlags" id="0x010103c7" />
+  <public type="attr" name="checkedTextViewStyle" id="0x010103c8" />
+  <public type="attr" name="showOnLockScreen" id="0x010103c9" />
+  <public type="attr" name="format12Hour" id="0x010103ca" />
+  <public type="attr" name="format24Hour" id="0x010103cb" />
+  <public type="attr" name="timeZone" id="0x010103cc" />
+
+  <public type="style" name="Widget.Holo.CheckedTextView" id="0x010301d9" />
+  <public type="style" name="Widget.Holo.Light.CheckedTextView" id="0x010301da" />
+  <public type="style" name="Widget.DeviceDefault.CheckedTextView" id="0x010301db" />
+  <public type="style" name="Widget.DeviceDefault.Light.CheckedTextView" id="0x010301dc" />
+
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3582768..9932d1e 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -346,6 +346,17 @@
     <!-- label for item that turns off power in phone options dialog -->
     <string name="global_action_power_off">Power off</string>
 
+    <!-- label for item that generates a bug report in the phone options dialog -->
+    <string name="global_action_bug_report">Bug report</string>
+
+    <!-- Take bug report menu title [CHAR LIMIT=NONE] -->
+    <string name="bugreport_title">Take bug report</string>
+    <!-- Message in bugreport dialog describing what it does [CHAR LIMIT=NONE] -->
+    <string name="bugreport_message">This will collect information about your
+        current device state, to send as an e-mail message.  It will take a little
+        time from starting the bug report until it is ready to be sent; please be
+        patient.</string>
+
     <!-- label for item that enables silent mode in phone options dialog -->
     <string name="global_action_toggle_silent_mode">Silent mode</string>
 
@@ -390,11 +401,12 @@
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_personalInfo">Your personal information</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgroupdesc_personalInfo" product="tablet">Direct access to your contacts
-        and calendar stored on the tablet.</string>
+    <string name="permgroupdesc_personalInfo">Direct access to information about you, stored in on your contact card.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_socialInfo">Your social information</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgroupdesc_personalInfo" product="default">Direct access to your contacts
-        and calendar stored on the phone.</string>
+    <string name="permgroupdesc_socialInfo">Direct access to information about your contacts and social connections.</string>
 
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_location">Your location</string>
@@ -407,6 +419,86 @@
     <string name="permgroupdesc_network">Access various network features.</string>
 
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_bluetoothNetwork">Bluetooth</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_bluetoothNetwork">Access devices and networks through Bluetooth.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_audioSettings">Audio Settings</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_audioSettings">Change audio settings.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_affectsBattery">Affects Battery</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_affectsBattery">Use features that can quickly drain battery.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_calendar">Calendar</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_calendar">Direct access to calendar and events.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_dictionary">Read User Dictionary</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_dictionary">Read words in user dictionary.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_writeDictionary">Write User Dictionary</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_writeDictionary">Add words to the user dictionary.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_bookmarks">Bookmarks and History</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_bookmarks">Direct access to bookmarks and browser history.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_deviceAlarms">Alarm</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_deviceAlarms">Set the alarm clock.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_voicemail">Voicemail</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_voicemail">Direct access to voicemail.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_microphone">Microphone</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_microphone">Direct access to the microphone to record audio.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_camera">Camera</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_camera">Direct access to camera for image or video capture.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_appInfo">Your applications information</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_appInfo">Ability to affect behavior of other applications on your device.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_wallpaper">Wallpaper</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_wallpaper">Change the device wallpaper settings.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_systemClock">Clock</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_systemClock">Change the device time or timezone.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_statusBar">Status Bar</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_statusBar">Change the device status bar settings.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_syncSettings">Sync Settings</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_syncSettings">Access to the sync settings.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_accounts">Your accounts</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgroupdesc_accounts">Access the available accounts.</string>
@@ -432,6 +524,11 @@
     <string name="permgroupdesc_developmentTools">Features only needed for app developers.</string>
 
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_display">Other Application UI</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_display">Effect the UI of other applications.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_storage">Storage</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this.   [CHAR LIMIT=30] -->
     <string name="permgroupdesc_storage" product="nosdcard">Access the USB storage.</string>
@@ -538,11 +635,28 @@
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_getTasks">retrieve running apps</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-
     <string name="permdesc_getTasks">Allows the app to retrieve information
        about currently and recently running tasks.  This may allow the app to
        discover information about which applications are used on the device.</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+    <string name="permlab_interactAcrossUsers">interact across users</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+    <string name="permdesc_interactAcrossUsers">Allows the app to perform actions
+        across different users on the device.  Malicious apps may use this to violate
+        the protection between users.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+    <string name="permlab_interactAcrossUsersFull">full license to interact across users</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+    <string name="permdesc_interactAcrossUsersFull">Allows all possible interactions across
+        users.</string>
+
+    <!--  Title of an application permission, listed so the user can choose whether they want to allow the application to create/remove/query users. [CHAR LIMIT=none] -->
+    <string name="permlab_manageUsers">manage users</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to create/remove/query users. [CHAR LIMIT=NONE] -->
+    <string name="permdesc_manageUsers">Allows apps to manage users on the device, including query, creation and deletion.</string>
+
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=50] -->
     <string name="permlab_getDetailedTasks">retrieve details of running apps</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
@@ -630,6 +744,34 @@
         the entire window content and examine all its text except passwords.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_temporary_enable_accessibility">temporary enable accessibility</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_temporary_enable_accessibility">Allows an application to temporarily
+         enable accessibility on the device. Malicious apps may enable accessibility without
+         user consent.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_retrieve_window_info">retrieve window info</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_retrieve_window_info">Allows an application to retrieve
+         information about the the windows from the window manager. Malicious apps may
+         retrieve information that is intended for internal system usage.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_filter_events">filter events</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_filter_events">Allows an application to register an input filter
+            which filters the stream of all user events before they are dispatched. Malicious app
+            may control the system UI whtout user intervention.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_magnify_display">magnify display</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_magnify_display">Allows an application to magnify the content of a
+        display. Malicious apps may transform the display content in a way that renders the
+        device unusable.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_shutdown">partial shutdown</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_shutdown">Puts the activity manager into a shutdown
@@ -687,10 +829,17 @@
         to control whether activities are always finished as soon as they
         go to the background. Never needed for normal apps.</string>
 
-    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_batteryStats">modify battery statistics</string>
-    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_batteryStats">Allows the app to modify
+    <!-- [CHAR LIMIT=NONE] Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_batteryStats">read battery statistics</string>
+    <!-- [CHAR LIMIT=NONE] Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_batteryStats">Allows an application to read the current low-level
+        battery use data.  May allow the application to find out detailed information about
+        which apps you use.</string>
+
+    <!-- [CHAR LIMIT=NONE] Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_updateBatteryStats">modify battery statistics</string>
+    <!-- [CHAR LIMIT=NONE] Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_updateBatteryStats">Allows the app to modify
         collected battery statistics. Not for use by normal apps.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -713,9 +862,10 @@
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_systemAlertWindow">draw over other apps</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_systemAlertWindow">Allows the app to show system
-      alert windows.  Some alert windows may take over the entire screen.
-      </string>
+    <string name="permdesc_systemAlertWindow">Allows the app to draw on top of other
+        applications or parts of the user interface.  They may interfere with your
+        use of the interface in any application, or change what you think you are
+        seeing in other applications.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_setAnimationScale">modify global animation speed</string>
@@ -730,6 +880,12 @@
         create and manage their own tokens, bypassing their normal
         Z-ordering. Should never be needed for normal apps.</string>
 
+    <!-- [CHAR LIMIT=NONE] Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_freezeScreen">freeze screen</string>
+    <!-- [CHAR LIMIT=NONE] Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_freezeScreen">Allows the application to temporarily freeze
+        the screen for a full-screen transition.</string>
+
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_injectEvents">press keys and control buttons</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -854,12 +1010,12 @@
     <string name="permlab_clearAppCache">delete all app cache data</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_clearAppCache" product="tablet">Allows the app to free tablet storage
-        by deleting files in app cache directory. Access is very
-        restricted usually to system process.</string>
+        by deleting files in the cache directories of other applications.  This may cause other
+        applications to start up more slowly as they need to re-retrieve their data.</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_clearAppCache" product="default">Allows the app to free phone storage
-        by deleting files in app cache directory. Access is very
-        restricted usually to system process.</string>
+        by deleting files in the cache directories of other applications.  This may cause other
+        applications to start up more slowly as they need to re-retrieve their data.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_movePackage">move app resources</string>
@@ -1109,26 +1265,26 @@
       such as GPS or location providers.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_accessFineLocation">precise (GPS) location</string>
+    <string name="permlab_accessFineLocation">precise location (GPS and
+      network-based)</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_accessFineLocation" product="tablet">Access precise
-      location sources such as the Global Positioning System on the tablet. When
-      location services are available and turned on, this permission allows the
-      app to determine your precise location.</string>
-    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_accessFineLocation" product="default">Access precise
-      location sources such as the Global Positioning System on the phone. When
-      location services are available and turned on, this permission allows the
-      app to determine your precise location.</string>
+    <string name="permdesc_accessFineLocation">Allows the app to get your
+      precise location using the Global Positioning System (GPS) or network
+      location sources such as cell towers and Wi-Fi. These location services
+      must be turned on and available to your device for the app to use them.
+      Apps may use this to determine where you are, and may consume additional
+      battery power.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_accessCoarseLocation">approximate (network-based) location</string>
+    <string name="permlab_accessCoarseLocation">approximate location
+      (network-based)</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_accessCoarseLocation">Access
-      approximate location from location providers using network sources such as
-      cell tower and Wi-Fi. When these location services are available and turned
-      on, this permission allows the app to determine your approximate
-      location.</string>
+    <string name="permdesc_accessCoarseLocation">Allows the app to get your
+      approximate location. This location is derived by location services using
+      network location sources such as cell towers and Wi-Fi. These location
+      services must be turned on and available to your device for the app to
+      use them. Apps may use this to determine approximately where you
+      are.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_accessSurfaceFlinger">access SurfaceFlinger</string>
@@ -1141,6 +1297,16 @@
     <string name="permdesc_readFrameBuffer">Allows the app to read the content of the frame buffer.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_configureWifiDisplay">configure Wifi displays</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_configureWifiDisplay">Allows the app to configure and connect to Wifi displays.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_controlWifiDisplay">control Wifi displays</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_controlWifiDisplay">Allows the app to control low-level features of Wifi displays.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_modifyAudioSettings">change your audio settings</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_modifyAudioSettings">Allows the app to modify global audio settings such as volume and which speaker is used for output.</string>
@@ -1476,7 +1642,7 @@
     <string name="permdesc_bluetoothAdmin" product="default">Allows the app to configure
       the local Bluetooth phone, and to discover and pair with remote devices.</string>
 
-    <string name="permlab_accessWimaxState">View WiMAX connections</string>
+    <string name="permlab_accessWimaxState">connect and disconnect from WiMAX</string>
     <string name="permdesc_accessWimaxState">Allows the app to determine whether
      WiMAX is enabled and information about any WiMAX networks that are
      connected. </string>
@@ -1545,7 +1711,7 @@
        names and phrases that the user may have stored in the user dictionary.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_writeDictionary">write to user-defined dictionary</string>
+    <string name="permlab_writeDictionary">add words to user-defined dictionary</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_writeDictionary">Allows the app to write new words into the
       user dictionary.</string>
@@ -1555,7 +1721,7 @@
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_sdcardRead" product="default">test access to protected storage</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
-    <string name="permdesc_sdcardRead" product="nosdcard">Allows the app to test a permission for USB storage that will be availabe on future devices. </string>
+    <string name="permdesc_sdcardRead" product="nosdcard">Allows the app to test a permission for USB storage that will be available on future devices. </string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_sdcardRead" product="default">Allows the app to test a permission for the SD card that will be available on future devices.</string>
 
@@ -1573,6 +1739,11 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
     <string name="permdesc_mediaStorageWrite" product="default">Allows the app to modify the contents of the internal media storage.</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
+    <string name="permlab_sdcardAccessAll">access external storage of all users</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_sdcardAccessAll">Allows the app to access external storage for all users.</string>
+
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_cache_filesystem">access the cache filesystem</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -1645,6 +1816,10 @@
     <string name="policylab_disableCamera">Disable cameras</string>
     <!-- Description of policy access to disable all device cameras [CHAR LIMIT=110]-->
     <string name="policydesc_disableCamera">Prevent use of all device cameras.</string>
+    <!-- Title of policy access to disable all device cameras [CHAR LIMIT=30]-->
+    <string name="policylab_disableKeyguardFeatures">Disable features in keyguard</string>
+    <!-- Description of policy access to disable all device cameras [CHAR LIMIT=110]-->
+    <string name="policydesc_disableKeyguardFeatures">Prevent use of some features in keyguard.</string>
 
     <!-- The order of these is important, don't reorder without changing Contacts.java --> <skip />
     <!-- Phone number types from android.provider.Contacts. This could be used when adding a new phone number for a contact, for example. -->
@@ -1926,7 +2101,7 @@
     <string name="lockscreen_plugged_in">Charging, <xliff:g id="number">%d</xliff:g><xliff:g id="percent">%%</xliff:g></string>
     <!-- When the lock screen is showing, the phone is plugged in and the battery is fully
          charged, say that it is charged. -->
-    <string name="lockscreen_charged">Charged.</string>
+    <string name="lockscreen_charged">Charged</string>
     <!-- A short representation of charging information, e.g "34%" -->
     <string name="lockscreen_battery_short"><xliff:g id="number">%d</xliff:g><xliff:g id="percent">%%</xliff:g></string>
 
@@ -1935,7 +2110,7 @@
     <string name="lockscreen_low_battery">Connect your charger.</string>
 
     <!-- Shown in the lock screen when there is no SIM card. -->
-    <string name="lockscreen_missing_sim_message_short">No SIM card.</string>
+    <string name="lockscreen_missing_sim_message_short">No SIM card</string>
     <!-- Shown in the lock screen when there is no SIM card. -->
     <string name="lockscreen_missing_sim_message" product="tablet">No SIM card in tablet.</string>
     <!-- Shown in the lock screen when there is no SIM card. -->
@@ -2097,6 +2272,47 @@
     <!-- Accessibility description sent when user completes drawing a pattern. [CHAR LIMIT=NONE] -->
     <string name="lockscreen_access_pattern_detected">Pattern completed</string>
 
+    <!-- Accessibility description of the add widget button. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_add_widget">Add widget.</string>
+    <!-- Accessibility description of the empty sidget slot (place holder for a new widget). [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_widget_empty_slot">Empty</string>
+    <!-- Accessibility description of the event of expanding an unlock area. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_unlock_area_expanded">Unlock area expanded.</string>
+    <!-- Accessibility description of the event of collapsing an unlock area. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_unlock_area_collapsed">Unlock area collapsed.</string>
+    <!-- Accessibility description of a lock screen widget. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_widget"><xliff:g id="widget_index">%1$s</xliff:g> widget.</string>
+    <!-- Accessibility description of the lock screen user selector widget. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_user_selector">User selector</string>
+    <!-- Accessibility description of the lock screen status widget. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_status">Status</string>
+    <!-- Accessibility description of the camera widget. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_camera">Camera</string>
+    <!-- Accessibility description of the lock media control widget. [CHAR_LIMIT=none] -->
+    <string name="keygaurd_accessibility_media_controls">Media controls</string>
+    <!-- Accessibility description of widget reordering start. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_widget_reorder_start">Widget reordering started.</string>
+    <!-- Accessibility description of widget reordering end. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_widget_reorder_end">Widget reordering ended.</string>
+    <!-- Accessibility description of the a widget deletion event. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_widget_deleted">Widget <xliff:g id="widget_index">%1$s</xliff:g> deleted.</string>
+    <!-- Accessibility description of the button to expand the lock area. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_expand_lock_area">Expand unlock area.</string>
+    <!-- Accessibility description of the slide unlock. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_slide_unlock">Slide unlock.</string>
+    <!-- Accessibility description of the pattern unlock. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_pattern_unlock">Pattern unlock.</string>
+    <!-- Accessibility description of the face unlock. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_face_unlock">Face unlock.</string>
+    <!-- Accessibility description of the pin lock. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_pin_unlock">Pin unlock.</string>
+    <!-- Accessibility description of the password lock. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_password_unlock">Password unlock.</string>
+    <!-- Accessibility description of the unlock pattern area. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_pattern_area">Pattern area.</string>
+    <!-- Accessibility description of the unlock slide area. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_slide_area">Slide area.</string>
+
     <!-- Password keyboard strings. Used by LockScreen and Settings --><skip />
     <!-- Label for "switch to symbols" key.  Must be short to fit on key! -->
     <string name="password_keyboard_label_symbol_key">\?123</string>
@@ -2693,10 +2909,10 @@
     <string name="textSelectionCABTitle">Text selection</string>
 
     <!-- Option to add the current misspelled word to the user dictionary. [CHAR LIMIT=25] -->
-    <string name="addToDictionary">add to dictionary</string>
+    <string name="addToDictionary">Add to dictionary</string>
 
     <!-- Option to delete the highlighted part of the text from the suggestion popup. [CHAR LIMIT=25] -->
-    <string name="deleteText">delete</string>
+    <string name="deleteText">Delete</string>
 
     <!-- EditText context menu -->
     <string name="inputMethod">Input method</string>
@@ -2880,11 +3096,14 @@
         <item quantity="other">Open Wi-Fi networks available</item>
     </plurals>
 
-    <!-- A notification is shown when a captive portal network is detected.  This is the notification's title. -->
+    <!-- A notification is shown when a wifi captive portal network is detected.  This is the notification's title. -->
     <string name="wifi_available_sign_in">Sign into Wi-Fi network</string>
 
+    <!-- A notification is shown when a captive portal network is detected.  This is the notification's title. -->
+    <string name="network_available_sign_in">Sign into network</string>
+
     <!-- A notification is shown when a captive portal network is detected.  This is the notification's message. -->
-    <string name="wifi_available_sign_in_detailed"><xliff:g id="wifi_network_ssid">%1$s</xliff:g></string>
+    <string name="network_available_sign_in_detailed"><xliff:g id="network_ssid">%1$s</xliff:g></string>
 
      <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems.  This is the notification's title / ticker. -->
      <string name="wifi_watchdog_network_disabled">Couldn\'t connect to Wi-Fi</string>
@@ -2910,6 +3129,8 @@
     <string name="wifi_p2p_enter_pin_message">Type the required PIN: </string>
     <string name="wifi_p2p_show_pin_message">PIN: </string>
 
+    <string name="wifi_p2p_frequency_conflict_message">The phone will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="device_name">%1$s</xliff:g></string>
+
     <!-- Name of the dialog that lets the user choose an accented character to insert -->
     <string name="select_character">Insert character</string>
 
@@ -2924,20 +3145,25 @@
     <string name="sms_control_no">Deny</string>
 
     <!-- SMS short code verification dialog. --> <skip />
-    <!-- The dialog title for the SMS short code confirmation dialog. [CHAR LIMIT=30] -->
-    <string name="sms_short_code_confirm_title">Send SMS to short code?</string>
-    <!-- The dialog title for the SMS premium short code confirmation dialog. [CHAR LIMIT=30] -->
-    <string name="sms_premium_short_code_confirm_title">Send premium SMS?</string>
     <!-- The message text for the SMS short code confirmation dialog. [CHAR LIMIT=NONE] -->
-    <string name="sms_short_code_confirm_message">&lt;b><xliff:g id="app_name">%1$s</xliff:g>&lt;/b> would like to send a text message to &lt;b><xliff:g id="dest_address">%2$s</xliff:g>&lt;/b>, which appears to be an SMS short code.&lt;p>Sending text messages to some short codes may cause your mobile account to be billed for premium services.&lt;p>Do you want to allow this app to send the message?</string>
-    <!-- The message text for the SMS short code confirmation dialog. [CHAR LIMIT=NONE] -->
-    <string name="sms_premium_short_code_confirm_message">&lt;b><xliff:g id="app_name">%1$s</xliff:g>&lt;/b> would like to send a text message to &lt;b><xliff:g id="dest_address">%2$s</xliff:g>&lt;/b>, which is a premium SMS short code.&lt;p>&lt;b>Sending a message to this destination will cause your mobile account to be billed for premium services.&lt;/b>&lt;p>Do you want to allow this app to send the message?</string>
-    <!-- Text of the approval button for the SMS short code confirmation dialog. [CHAR LIMIT=50] -->
-    <string name="sms_short_code_confirm_allow">Send message</string>
+    <string name="sms_short_code_confirm_message">&lt;b><xliff:g id="app_name">%1$s</xliff:g>&lt;/b> would like to send a message to &lt;b><xliff:g id="dest_address">%2$s</xliff:g>&lt;/b>.</string>
+    <!-- Message details for the SMS short code confirmation dialog (possible premium short code). [CHAR LIMIT=NONE] -->
+    <string name="sms_short_code_details">This <font fgcolor="#ffffb060">may cause charges</font> on your mobile account.</string>
+    <!-- Message details for the SMS short code confirmation dialog (premium short code). [CHAR LIMIT=NONE] -->
+    <string name="sms_premium_short_code_details"><font fgcolor="#ffffb060">This will cause charges on your mobile account.</font></string>
+    <!-- Text of the approval button for the SMS short code confirmation dialog. [CHAR LIMIT=30] -->
+    <string name="sms_short_code_confirm_allow">Send</string>
     <!-- Text of the cancel button for the SMS short code confirmation dialog. [CHAR LIMIT=30] -->
-    <string name="sms_short_code_confirm_deny">Don\'t send</string>
-    <!-- Text of the button for the SMS short code confirmation dialog to report a malicious app. [CHAR LIMIT=30] -->
-    <string name="sms_short_code_confirm_report">Report malicious app</string>
+    <string name="sms_short_code_confirm_deny">Cancel</string>
+    <!-- Text of the checkbox for the SMS short code confirmation dialog to remember the user's choice. [CHAR LIMIT=40] -->
+    <string name="sms_short_code_remember_choice">Remember my choice</string>
+    <!-- Text shown when remember checkbox is checked to inform the user how they may undo the setting. [CHAR LIMIT=40] -->
+    <string name="sms_short_code_remember_undo_instruction">You can change this later in Settings\u00A0>\u00A0Apps"</string>
+
+    <!-- Text of the approval button for the SMS short code confirmation dialog when checkbox is checked. [CHAR LIMIT=30] -->
+    <string name="sms_short_code_confirm_always_allow">Always Allow</string>
+    <!-- Text of the cancel button for the SMS short code confirmation dialog when checkbox is checked. [CHAR LIMIT=30] -->
+    <string name="sms_short_code_confirm_never_allow">Never Allow</string>
 
     <!-- SIM swap and device reboot Dialog --> <skip />
     <!-- See SIM_REMOVED_DIALOG.  This is the title of that dialog. -->
@@ -2964,23 +3190,15 @@
     <!-- Name of the button in the date/time picker to accept the date/time change -->
     <string name="date_time_done">Done</string>
 
-    <!-- Security Permissions strings (old)-->
-    <!-- The default permission group for any permissions that have not explicitly set a group. -->
-    <string name="default_permission_group">Default</string>
-    <!-- Do not translate. -->
-    <string name="permissions_format"><xliff:g id="perm_line1">%1$s</xliff:g>, <xliff:g id="perm_line2">%2$s</xliff:g></string>
-    <!-- Shown for an application when it doesn't require any permission grants. -->
-    <string name="no_permissions">No permissions required</string>
-    <!-- When installing an application, the less-dangerous permissions are hidden.  If the user showed those, this is the text to hide them again.  -->
-    <string name="perms_hide"><b>Hide</b></string>
-    <!-- When installing an application, the less-dangerous permissions are hidden.  This is the text to show those. -->
-    <string name="perms_show_all"><b>Show all</b></string>
-
-    <!-- Security Permissions strings (new)-->
+    <!-- Security Permissions strings-->
     <!-- Text that is placed at the front of a permission name that is being added to an app [CHAR LIMIT=NONE] -->
-    <string name="perms_new_perm_prefix"><font size="12" fgcolor="#ff900000">NEW: </font></string>
+    <string name="perms_new_perm_prefix"><font size="12" fgcolor="#ff33b5e5">NEW: </font></string>
     <!-- Text that is placed at the front of a permission name that is being added to an app [CHAR LIMIT=NONE] -->
     <string name="perms_description_app">Provided by <xliff:g id="app_name">%1$s</xliff:g>.</string>
+    <!-- Shown for an application when it doesn't require any permission grants. -->
+    <string name="no_permissions">No permissions required</string>
+    <!-- [CHAR LIMIT=NONE] Additional text in permission description for perms that can cost money. -->
+    <string name="perm_costs_money">this may cost you money</string>
 
     <!-- USB storage dialog strings -->
     <!-- This is the title for the activity's window. -->
@@ -3229,6 +3447,15 @@
     <!-- The text of the notification when VPN is active with a session name. -->
     <string name="vpn_text_long">Connected to <xliff:g id="session" example="office">%s</xliff:g>. Touch to manage the network.</string>
 
+    <!-- Notification title when connecting to lockdown VPN. -->
+    <string name="vpn_lockdown_connecting">Always-on VPN connecting\u2026</string>
+    <!-- Notification title when connected to lockdown VPN. -->
+    <string name="vpn_lockdown_connected">Always-on VPN connected</string>
+    <!-- Notification title when error connecting to lockdown VPN. -->
+    <string name="vpn_lockdown_error">Always-on VPN error</string>
+    <!-- Notification body that indicates user can touch to cycle lockdown VPN connection. -->
+    <string name="vpn_lockdown_reset">Touch to reset connection</string>
+
     <!-- Localized strings for WebView -->
     <!-- Label for button in a WebView that will open a chooser to choose a file to upload -->
     <string name="upload_file">Choose file</string>
@@ -3319,6 +3546,10 @@
     <string name="find">Find</string>
     <!-- ActionBar action to use the current selection to perform a web search [CHAR-LIMIT=16] -->
     <string name="websearch">Web Search</string>
+    <!-- ActionBar action to find the next match in the page [CHAR LIMIT=24] -->
+    <string name="find_next">Find next</string>
+    <!-- ActionBar action to find the previous match in the page [CHAR LIMIT=24] -->
+    <string name="find_previous">Find previous</string>
 
     <!-- Network positioning notification ticker. The name of the user (e.g. John Doe) who sent
          the request is shown as a dynamic string. -->
@@ -3581,8 +3812,8 @@
     <!-- Name of the default audio route when an audio dock is connected. [CHAR LIMIT=50] -->
     <string name="default_audio_route_name_dock_speakers">Dock speakers</string>
 
-    <!-- Name of the default audio route when HDMI is connected. [CHAR LIMIT=50] -->
-    <string name="default_audio_route_name_hdmi">HDMI audio</string>
+    <!-- Name of the default media route when HDMI is connected. [CHAR LIMIT=50] -->
+    <string name="default_media_route_name_hdmi">HDMI</string>
 
     <!-- Name of the default audio route category. [CHAR LIMIT=50] -->
     <string name="default_audio_route_category_name">System</string>
@@ -3592,4 +3823,171 @@
 
     <!-- "Done" button for MediaRouter chooser dialog when grouping routes. [CHAR LIMIT=NONE] -->
     <string name="media_route_chooser_grouping_done">Done</string>
+
+    <!-- Content description of a MediaRouteButton for accessibility support -->
+    <string name="media_route_button_content_description">Media output</string>
+
+    <!-- Status message for remote routes attempting to scan/determine availability -->
+    <string name="media_route_status_scanning">Scanning...</string>
+
+    <!-- Status message for a remote route attempting to connect -->
+    <string name="media_route_status_connecting">Connecting...</string>
+
+    <!-- Status message for a remote route that is confirmed to be available for connection -->
+    <string name="media_route_status_available">Available</string>
+
+    <!-- Status message for remote routes that are not available for connection right now -->
+    <string name="media_route_status_not_available">Not available</string>
+
+    <!-- Display manager service -->
+
+    <!-- Name of the built-in display.  [CHAR LIMIT=50] -->
+    <string name="display_manager_built_in_display_name">Built-in Screen</string>
+
+    <!-- Name of the HDMI display.  [CHAR LIMIT=50] -->
+    <string name="display_manager_hdmi_display_name">HDMI Screen</string>
+
+    <!-- Name of the N'th overlay display for testing.  [CHAR LIMIT=50] -->
+    <string name="display_manager_overlay_display_name">Overlay #<xliff:g id="id">%1$d</xliff:g></string>
+
+    <!-- Title text to show within the overlay.  [CHAR LIMIT=50] -->
+    <string name="display_manager_overlay_display_title"><xliff:g id="name">%1$s</xliff:g>: <xliff:g id="width">%2$d</xliff:g>x<xliff:g id="height">%3$d</xliff:g>, <xliff:g id="dpi">%4$d</xliff:g> dpi</string>
+
+    <!-- Title of the notification to indicate an active wifi display connection.  [CHAR LIMIT=50] -->
+    <string name="wifi_display_notification_title">Wireless display is connected</string>
+    <!-- Message of the notification to indicate an active wifi display connection.  [CHAR LIMIT=80] -->
+    <string name="wifi_display_notification_message">This screen is showing on another device</string>
+    <!-- Label of a button to disconnect an active wifi display connection.  [CHAR LIMIT=25] -->
+    <string name="wifi_display_notification_disconnect">Disconnect</string>
+
+    <!-- Keyguard strings -->
+    <!-- Label shown on emergency call button in keyguard -->
+    <string name="kg_emergency_call_label">Emergency call</string>
+    <!-- Message shown in pattern unlock after some number of unsuccessful attempts -->
+    <string name="kg_forgot_pattern_button_text">Forgot Pattern</string>
+    <!-- Message shown when user enters wrong pattern -->
+    <string name="kg_wrong_pattern">Wrong Pattern</string>
+    <!-- Message shown when user enters wrong password -->
+    <string name="kg_wrong_password">Wrong Password</string>
+    <!-- Message shown when user enters wrong PIN -->
+    <string name="kg_wrong_pin">Wrong PIN</string>
+    <!-- Countdown message shown after too many failed unlock attempts -->
+    <string name="kg_too_many_failed_attempts_countdown">Try again in <xliff:g id="number">%d</xliff:g> seconds.</string>
+    <!-- Instructions for using the pattern unlock screen -->
+    <string name="kg_pattern_instructions">Draw your pattern</string>
+    <!-- Instructions for using the SIM PIN unlock screen -->
+    <string name="kg_sim_pin_instructions">Enter SIM PIN</string>
+    <!-- Instructions for using the PIN unlock screen -->
+    <string name="kg_pin_instructions">Enter PIN</string>
+    <!-- Instructions for using the password unlock screen -->
+    <string name="kg_password_instructions">Enter Password</string>
+    <!-- Hint shown in the PUK screen that asks the user to enter the PUK code given to them by their provider -->
+    <string name="kg_puk_enter_puk_hint">SIM is now disabled. Enter PUK code to continue. Contact carrier for details.</string>
+    <!-- Hint shown in the PUK unlock screen PIN TextView -->
+    <string name="kg_puk_enter_pin_hint">Enter desired PIN code</string>
+    <!-- Message shown when the user needs to confirm the PIN they just entered in the PUK screen -->
+    <string name="kg_enter_confirm_pin_hint">Confirm desired PIN code</string>
+    <!-- Message shown in dialog while the device is unlocking the SIM card -->
+    <string name="kg_sim_unlock_progress_dialog_message">Unlocking SIM card\u2026</string>
+    <!-- Message shown when the user enters the wrong PIN code -->
+    <string name="kg_password_wrong_pin_code">Incorrect PIN code.</string>
+    <!-- Message shown when the user enters an invalid SIM pin password in PUK screen -->
+    <string name="kg_invalid_sim_pin_hint">Type a PIN that is 4 to 8 numbers.</string>
+    <!-- Message shown when the user enters an invalid PUK code in the PUK screen -->
+    <string name="kg_invalid_sim_puk_hint">PUK code should be 8 numbers or more.</string>
+    <!-- Message shown when the user enters an invalid PUK code -->
+    <string name="kg_invalid_puk">Re-enter the correct PUK code. Repeated attempts will permanently disable the SIM.</string>
+      <!-- String shown in PUK screen when PIN codes don't match -->
+    <string name="kg_invalid_confirm_pin_hint" product="default">PIN codes does not match</string>
+    <!-- Message shown when the user exceeds the maximum number of pattern attempts -->
+    <string name="kg_login_too_many_attempts">Too many pattern attempts</string>
+    <!-- Instructions show in account unlock screen allowing user to enter their email password -->
+    <string name="kg_login_instructions">To unlock, sign in with your Google account.</string>
+    <!-- Hint shown in TextView in account unlock screen of keyguard -->
+    <string name="kg_login_username_hint">Username (email)</string>
+    <!-- Hint shown in TextView in account unlock screen of keyguard -->
+    <string name="kg_login_password_hint">Password</string>
+    <!-- Label shown on sign in button on account unlock screen of keyguard -->
+    <string name="kg_login_submit_button">Sign in</string>
+    <!-- Message shown when the user enters an invalid username/password combination in account unlock screen of keyguard -->
+    <string name="kg_login_invalid_input">Invalid username or password.</string>
+    <!-- Hint text shown when user has too many failed password attempts in account unlock screen of keyguard -->
+    <string name="kg_login_account_recovery_hint">Forgot your username or password\?\nVisit <b>google.com/accounts/recovery</b>.</string>
+    <!-- Message shown while device checks username/password in account unlock screen of keyguard -->
+    <string name="kg_login_checking_password">Checking account\u2026</string>
+    <!-- Message shown in dialog when max number of attempts are reached for PIN screen of keyguard -->
+    <string name="kg_too_many_failed_pin_attempts_dialog_message">
+        You have incorrectly typed your PIN <xliff:g id="number">%d</xliff:g> times.
+        \n\nTry again in <xliff:g id="number">%d</xliff:g> seconds.
+    </string>
+    <!-- Message shown in dialog when max number of attempts are reached for password screen of keyguard -->
+    <string name="kg_too_many_failed_password_attempts_dialog_message">
+        You have incorrectly typed your password <xliff:g id="number">%d</xliff:g> times.
+        \n\nTry again in <xliff:g id="number">%d</xliff:g> seconds.
+    </string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message">
+        You have incorrectly drawn your unlock pattern <xliff:g id="number">%d</xliff:g> times.
+        \n\nTry again in <xliff:g id="number">%d</xliff:g> seconds.
+    </string>
+    <!-- Message shown when user is almost at the limit of password attempts where the device will be wiped. -->
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet">
+       You have incorrectly attempted to unlock the tablet <xliff:g id="number">%d</xliff:g> times.
+       After <xliff:g id="number">%d</xliff:g> more unsuccessful attempts,
+       the tablet will be reset to factory default and all user data will be lost.
+    </string>
+    <!-- Message shown when user is almost at the limit of password attempts where the device will be wiped. -->
+    <string name="kg_failed_attempts_almost_at_wipe" product="default">
+       You have incorrectly attempted to unlock the phone <xliff:g id="number">%d</xliff:g> times.
+       After <xliff:g id="number">%d</xliff:g> more unsuccessful attempts,
+       the phone will be reset to factory default and all user data will be lost.
+    </string>
+    <!-- Message shown in dialog when user has exceeded the maximum attempts and the device will now be wiped -->
+    <string name="kg_failed_attempts_now_wiping" product="tablet">
+       You have incorrectly attempted to unlock the tablet <xliff:g id="number">%d</xliff:g> times.
+       The tablet will now be reset to factory default.
+    </string>
+    <!-- Message shown in dialog when user has exceeded the maximum attempts and the device will now be wiped -->
+    <string name="kg_failed_attempts_now_wiping" product="default">
+       You have incorrectly attempted to unlock the phone <xliff:g id="number">%d</xliff:g> times.
+       The phone will now be reset to factory default.
+    </string>
+    <!-- Message shown in dialog when user is almost at the limit where they will be
+    locked out and may have to enter an alternate username/password to unlock the phone -->
+    <string name="kg_failed_attempts_almost_at_login" product="tablet">
+       You have incorrectly drawn your unlock pattern <xliff:g id="number">%d</xliff:g> times.
+       After <xliff:g id="number">%d</xliff:g> more unsuccessful attempts,
+       you will be asked to unlock your tablet using an email account.\n\n
+       Try again in <xliff:g id="number">%d</xliff:g> seconds.
+    </string>
+    <!-- Message shown in dialog when user is almost at the limit where they will be
+    locked out and may have to enter an alternate username/password to unlock the phone -->
+    <string name="kg_failed_attempts_almost_at_login" product="default">
+       You have incorrectly drawn your unlock pattern <xliff:g id="number">%d</xliff:g> times.
+       After <xliff:g id="number">%d</xliff:g> more unsuccessful attempts,
+       you will be asked to unlock your phone using an email account.\n\n
+       Try again in <xliff:g id="number">%d</xliff:g> seconds.
+    </string>
+    <!-- Sequence of characters used to separate message strings in keyguard. Typically just em-dash
+         with spaces on either side. [CHAR LIMIT=3] -->
+    <string name="kg_text_message_separator" product="default">" \u2014 "</string>
+    <!-- The delete-widget drop target button text -->
+    <string name="kg_reordering_delete_drop_target_text">Remove</string>
+
+    <!-- Message shown in dialog when user is attempting to set the music volume above the
+    recommended maximum level for headphones -->
+    <string name="safe_media_volume_warning" product="default">
+       "Raise volume above safe level?\nListening at high volume for long periods may damage your hearing."
+    </string>
+
+    <!-- Text spoken when the user is performing a gesture that will enable accessibility. [CHAR LIMIT=none] -->
+    <string name="continue_to_enable_accessibility">Keep holding down two fingers to enable accessibility.</string>
+    <!-- Text spoken when the user enabled accessibility. [CHAR LIMIT=none] -->
+    <string name="accessibility_enabled">Accessibility enabled.</string>
+    <!-- Text spoken when the user stops preforming a gesture that would enable accessibility. [CHAR LIMIT=none] -->
+    <string name="enable_accessibility_canceled">Accessibility canceled.</string>
+    <!-- Text spoken when the current user is switched if accessibility is enabled. [CHAR LIMIT=none] -->
+    <string name="user_switched">Current user <xliff:g id="name" example="Bob">%1$s</xliff:g>.</string>
+    <!-- Default name of the owner user [CHAR LIMIT=20] -->
+    <string name="owner_name" msgid="3879126011135546571">Owner</string>
+
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index e4fc26b..f489786 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -339,21 +339,18 @@
         <item name="android:clickable">true</item>
         <item name="android:textAppearance">?android:attr/textAppearance</item>
         <item name="android:textColor">?android:attr/textColorPrimaryDisableOnly</item>
-        <item name="android:gravity">center_vertical|left</item>
+        <item name="android:gravity">center_vertical|start</item>
     </style>
 
     <style name="Widget.CompoundButton.CheckBox">
-        <item name="android:background">@android:drawable/btn_check_label_background</item>
         <item name="android:button">?android:attr/listChoiceIndicatorMultiple</item>
     </style>
 
     <style name="Widget.CompoundButton.RadioButton">
-        <item name="android:background">@android:drawable/btn_radio_label_background</item>
         <item name="android:button">?android:attr/listChoiceIndicatorSingle</item>
     </style>
 
     <style name="Widget.CompoundButton.Star">
-        <item name="android:background">@android:drawable/btn_star_label_background</item>
         <item name="android:button">@android:drawable/btn_star</item>
     </style>
 
@@ -467,7 +464,11 @@
         <item name="android:textEditSuggestionItemLayout">?android:attr/textEditSuggestionItemLayout</item>
         <item name="android:textCursorDrawable">?android:attr/textCursorDrawable</item>
     </style>
-    
+
+    <style name="Widget.CheckedTextView">
+        <item name="android:textAlignment">viewStart</item>
+    </style>
+
     <style name="Widget.TextView.ListSeparator">
         <item name="android:background">@android:drawable/dark_header_dither</item>
         <item name="android:layout_width">match_parent</item>
@@ -476,7 +477,7 @@
         <item name="android:textColor">?textColorSecondary</item>
         <item name="android:textSize">14sp</item>
         <item name="android:gravity">center_vertical</item>
-        <item name="android:paddingLeft">8dip</item>
+        <item name="android:paddingStart">8dip</item>
     </style>
 
     <style name="Widget.TextView.ListSeparator.White">
@@ -587,8 +588,8 @@
 
     <style name="Widget.DropDownItem">
         <item name="android:textAppearance">@style/TextAppearance.Widget.DropDownItem</item>
-        <item name="android:paddingLeft">@dimen/dropdownitem_text_padding_left</item>
-        <item name="android:paddingRight">@dimen/dropdownitem_text_padding_right</item>
+        <item name="android:paddingStart">@dimen/dropdownitem_text_padding_left</item>
+        <item name="android:paddingEnd">@dimen/dropdownitem_text_padding_right</item>
         <item name="android:gravity">center_vertical</item>
     </style>
     
@@ -928,8 +929,8 @@
     </style>
 
     <style name="PreferenceFragment">
-        <item name="android:paddingLeft">0dp</item>
-        <item name="android:paddingRight">0dp</item>
+        <item name="android:paddingStart">0dp</item>
+        <item name="android:paddingEnd">0dp</item>
     </style>
 
     <style name="Preference.Information">
@@ -983,8 +984,8 @@
     </style>
 
     <style name="PreferenceFragment.Holo">
-        <item name="android:paddingLeft">@dimen/preference_fragment_padding_side</item>
-        <item name="android:paddingRight">@dimen/preference_fragment_padding_side</item>
+        <item name="android:paddingStart">@dimen/preference_fragment_padding_side</item>
+        <item name="android:paddingEnd">@dimen/preference_fragment_padding_side</item>
     </style>
 
     <style name="Preference.Holo.Information">
@@ -1040,8 +1041,8 @@
     <!-- The attributes are overridden here because the x-large or large resources may have
          changed the margins and background in the parent PreferencePanel style. -->
     <style name="PreferencePanel.Dialog">
-        <item name="android:layout_marginLeft">0dip</item>
-        <item name="android:layout_marginRight">0dip</item>
+        <item name="android:layout_marginStart">0dip</item>
+        <item name="android:layout_marginEnd">0dip</item>
         <item name="android:layout_marginTop">0dip</item>
         <item name="android:layout_marginBottom">0dip</item>
         <item name="android:background">@null</item>
@@ -1082,8 +1083,8 @@
 
     <style name="ZoomControls">
         <item name="android:gravity">bottom</item>
-        <item name="android:paddingLeft">15dip</item>
-        <item name="android:paddingRight">15dip</item>
+        <item name="android:paddingStart">15dip</item>
+        <item name="android:paddingEnd">15dip</item>
     </style>
     
     <!-- Style you can use with a container (typically a horizontal
@@ -1091,8 +1092,8 @@
          spacing. @hide -->
     <style name="ButtonBar">
         <item name="android:paddingTop">5dip</item>
-        <item name="android:paddingLeft">4dip</item>
-        <item name="android:paddingRight">4dip</item>
+        <item name="android:paddingStart">4dip</item>
+        <item name="android:paddingEnd">4dip</item>
         <item name="android:paddingBottom">1dip</item>
         <item name="android:background">@android:drawable/bottom_bar</item>
     </style>
@@ -1128,9 +1129,9 @@
         <item name="android:displayOptions">useLogo|showHome|showTitle</item>
         <item name="android:divider">@android:drawable/action_bar_divider</item>
         <item name="android:height">?android:attr/actionBarSize</item>
-        <item name="android:paddingLeft">0dip</item>
+        <item name="android:paddingStart">0dip</item>
         <item name="android:paddingTop">0dip</item>
-        <item name="android:paddingRight">0dip</item>
+        <item name="android:paddingEnd">0dip</item>
         <item name="android:paddingBottom">0dip</item>
         <item name="android:titleTextStyle">@android:style/TextAppearance.Widget.ActionBar.Title</item>
         <item name="android:subtitleTextStyle">@android:style/TextAppearance.Widget.ActionBar.Subtitle</item>
@@ -1166,8 +1167,8 @@
 
     <style name="Widget.ActionButton">
         <item name="android:background">?android:attr/actionBarItemBackground</item>
-        <item name="android:paddingLeft">12dip</item>
-        <item name="android:paddingRight">12dip</item>
+        <item name="android:paddingStart">12dip</item>
+        <item name="android:paddingEnd">12dip</item>
         <item name="android:minWidth">@android:dimen/action_button_min_width</item>
         <item name="android:minHeight">?android:attr/actionBarSize</item>
         <item name="android:gravity">center</item>
@@ -1185,8 +1186,8 @@
     <style name="Widget.ActionBar.TabView" parent="Widget">
         <item name="android:gravity">center_horizontal</item>
         <item name="android:background">@drawable/minitab_lt</item>
-        <item name="android:paddingLeft">4dip</item>
-        <item name="android:paddingRight">4dip</item>
+        <item name="android:paddingStart">4dip</item>
+        <item name="android:paddingEnd">4dip</item>
     </style>
 
     <style name="Widget.ActionBar.TabBar" parent="Widget">
@@ -1262,7 +1263,7 @@
     </style>
 
     <style name="TextAppearance.Holo.Small.Inverse">
-        <item name="android:textColor">?textColorPrimaryInverse</item>
+        <item name="android:textColor">?textColorSecondaryInverse</item>
         <item name="android:textColorHint">?textColorHintInverse</item>
         <item name="android:textColorHighlight">?textColorHighlightInverse</item>
         <item name="android:textColorLink">?textColorLinkInverse</item>
@@ -1395,6 +1396,13 @@
     </style>
 
     <style name="TextAppearance.Holo.Widget.Switch" parent="TextAppearance.Holo.Small">
+        <!-- Switch thumb asset presents a dark background. -->
+        <item name="android:textColor">@android:color/secondary_text_holo_dark</item>
+    </style>
+
+    <style name="TextAppearance.Holo.Light.Widget.Switch" parent="TextAppearance.Holo.Small">
+        <!-- Switch thumb asset presents a dark background. -->
+        <item name="android:textColor">@android:color/primary_text_holo_dark</item>
     </style>
 
     <style name="TextAppearance.Holo.WindowTitle">
@@ -1533,8 +1541,8 @@
 
     <style name="Widget.Holo.Button.Borderless">
         <item name="android:background">?android:attr/selectableItemBackground</item>
-        <item name="android:paddingLeft">4dip</item>
-        <item name="android:paddingRight">4dip</item>
+        <item name="android:paddingStart">4dip</item>
+        <item name="android:paddingEnd">4dip</item>
     </style>
 
     <style name="Widget.Holo.Button.Borderless.Small">
@@ -1564,8 +1572,8 @@
 
     <style name="Holo.ButtonBar" parent="ButtonBar">
         <item name="android:paddingTop">0dip</item>
-        <item name="android:paddingLeft">0dip</item>
-        <item name="android:paddingRight">0dip</item>
+        <item name="android:paddingStart">0dip</item>
+        <item name="android:paddingEnd">0dip</item>
         <item name="android:paddingBottom">0dip</item>
         <item name="divider">?android:attr/dividerVertical</item>
         <item name="showDividers">middle</item>
@@ -1585,6 +1593,9 @@
     <style name="Widget.Holo.TextView" parent="Widget.TextView">
     </style>
 
+    <style name="Widget.Holo.CheckedTextView" parent="Widget.CheckedTextView">
+    </style>
+
     <style name="Widget.Holo.TextView.ListSeparator" parent="Widget.TextView.ListSeparator">
         <item name="android:background">@android:drawable/list_section_divider_holo_dark</item>
         <item name="android:textAllCaps">true</item>
@@ -1732,8 +1743,8 @@
         <item name="android:thumb">@android:drawable/scrubber_control_selector_holo</item>
         <item name="android:thumbOffset">16dip</item>
         <item name="android:focusable">true</item>
-        <item name="android:paddingLeft">16dip</item>
-        <item name="android:paddingRight">16dip</item>
+        <item name="android:paddingStart">16dip</item>
+        <item name="android:paddingEnd">16dip</item>
     </style>
 
     <style name="Widget.Holo.RatingBar" parent="Widget.RatingBar">
@@ -1772,7 +1783,7 @@
         <item name="android:dropDownHorizontalOffset">0dip</item>
         <item name="android:dropDownWidth">wrap_content</item>
         <item name="android:popupPromptView">@android:layout/simple_dropdown_hint</item>
-        <item name="android:gravity">left|center_vertical</item>
+        <item name="android:gravity">start|center_vertical</item>
         <item name="android:disableChildrenWhenDisabled">true</item>
     </style>
 
@@ -1817,8 +1828,8 @@
 
     <style name="Widget.Holo.DropDownItem" parent="Widget.DropDownItem">
         <item name="android:textAppearance">@style/TextAppearance.Holo.Widget.DropDownItem</item>
-        <item name="android:paddingLeft">8dp</item>
-        <item name="android:paddingRight">8dp</item>
+        <item name="android:paddingStart">8dp</item>
+        <item name="android:paddingEnd">8dp</item>
     </style>
 
     <style name="Widget.Holo.DropDownItem.Spinner">
@@ -1826,8 +1837,8 @@
 
     <style name="Widget.Holo.TextView.SpinnerItem" parent="Widget.TextView.SpinnerItem">
         <item name="android:textAppearance">@style/TextAppearance.Holo.Widget.TextView.SpinnerItem</item>
-        <item name="android:paddingLeft">8dp</item>
-        <item name="android:paddingRight">8dp</item>
+        <item name="android:paddingStart">8dp</item>
+        <item name="android:paddingEnd">8dp</item>
     </style>
 
     <style name="Widget.Holo.KeyboardView" parent="Widget.KeyboardView">
@@ -1872,8 +1883,8 @@
     <style name="Widget.Holo.ActionButton" parent="Widget.ActionButton">
         <item name="android:minWidth">@android:dimen/action_button_min_width</item>
         <item name="android:gravity">center</item>
-        <item name="android:paddingLeft">12dip</item>
-        <item name="android:paddingRight">12dip</item>
+        <item name="android:paddingStart">12dip</item>
+        <item name="android:paddingEnd">12dip</item>
         <item name="android:scaleType">center</item>
         <item name="android:maxLines">2</item>
     </style>
@@ -1889,8 +1900,8 @@
 
     <style name="Widget.Holo.ActionBar.TabView" parent="Widget.ActionBar.TabView">
         <item name="android:background">@drawable/tab_indicator_ab_holo</item>
-        <item name="android:paddingLeft">16dip</item>
-        <item name="android:paddingRight">16dip</item>
+        <item name="android:paddingStart">16dip</item>
+        <item name="android:paddingEnd">16dip</item>
     </style>
 
     <style name="Widget.Holo.ActionBar.TabBar" parent="Widget.ActionBar.TabBar">
@@ -1970,8 +1981,8 @@
 
     <style name="Widget.Holo.Light.Button.Borderless">
         <item name="android:background">?android:attr/selectableItemBackground</item>
-        <item name="android:paddingLeft">4dip</item>
-        <item name="android:paddingRight">4dip</item>
+        <item name="android:paddingStart">4dip</item>
+        <item name="android:paddingEnd">4dip</item>
     </style>
 
     <style name="Widget.Holo.Light.Button.Borderless.Small">
@@ -2013,6 +2024,9 @@
     <style name="Widget.Holo.Light.TextView" parent="Widget.TextView">
     </style>
 
+    <style name="Widget.Holo.Light.CheckedTextView" parent="Widget.CheckedTextView">
+    </style>
+
     <style name="Widget.Holo.Light.TextView.ListSeparator" parent="Widget.TextView.ListSeparator">
         <item name="android:background">@android:drawable/list_section_divider_holo_light</item>
         <item name="android:textAllCaps">true</item>
@@ -2320,7 +2334,7 @@
     <style name="Widget.Holo.Light.CompoundButton.Switch" parent="Widget.CompoundButton.Switch">
         <item name="android:track">@android:drawable/switch_track_holo_light</item>
         <item name="android:thumb">@android:drawable/switch_inner_holo_light</item>
-        <item name="android:switchTextAppearance">@android:style/TextAppearance.Holo.Widget.Switch</item>
+        <item name="android:switchTextAppearance">@android:style/TextAppearance.Holo.Light.Widget.Switch</item>
         <item name="android:textOn">@android:string/capital_on</item>
         <item name="android:textOff">@android:string/capital_off</item>
         <item name="android:thumbTextPadding">12dip</item>
@@ -2419,10 +2433,10 @@
         <item name="android:layout_width">200dip</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_marginTop">8dip</item>
-        <item name="android:layout_marginLeft">16dip</item>
-        <item name="android:layout_marginRight">16dip</item>
+        <item name="android:layout_marginStart">16dip</item>
+        <item name="android:layout_marginEnd">16dip</item>
         <item name="android:orientation">vertical</item>
-        <item name="android:gravity">left</item>
+        <item name="android:gravity">start</item>
     </style>
 
     <!-- @hide -->
@@ -2451,6 +2465,8 @@
         <item name="android:externalRouteEnabledDrawable">@drawable/ic_media_route_holo_dark</item>
         <item name="android:minWidth">56dp</item>
         <item name="android:minHeight">48dp</item>
+        <item name="android:focusable">true</item>
+        <item name="android:contentDescription">@android:string/media_route_button_content_description</item>
     </style>
 
     <style name="Widget.Holo.Light.MediaRouteButton">
@@ -2458,6 +2474,35 @@
         <item name="android:externalRouteEnabledDrawable">@drawable/ic_media_route_holo_light</item>
         <item name="android:minWidth">56dp</item>
         <item name="android:minHeight">48dp</item>
+        <item name="android:focusable">true</item>
+        <item name="android:contentDescription">@android:string/media_route_button_content_description</item>
+    </style>
+
+    <!-- Keyguard PIN pad styles -->
+    <style name="Widget.Button.NumPadKey"
+            parent="@android:style/Widget.Button">
+        <item name="android:singleLine">true</item>
+        <item name="android:gravity">left|center_vertical</item>
+        <item name="android:background">?android:attr/selectableItemBackground</item>
+        <item name="android:textSize">34dp</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:textStyle">normal</item>
+        <item name="android:textColor">#ffffff</item>
+        <item name="android:paddingBottom">10dp</item>
+        <item name="android:paddingLeft">20dp</item>
+    </style>
+    <style name="TextAppearance.NumPadKey"
+            parent="@android:style/TextAppearance">
+        <item name="android:textSize">34dp</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:textStyle">normal</item>
+        <item name="android:textColor">#ffffff</item>
+    </style>
+    <style name="TextAppearance.NumPadKey.Klondike">
+        <item name="android:textSize">20dp</item>
+        <item name="android:fontFamily">sans-serif-condensed</item>
+        <item name="android:textStyle">normal</item>
+        <item name="android:textColor">#80ffffff</item>
     </style>
 
 </resources>
diff --git a/core/res/res/values/styles_device_defaults.xml b/core/res/res/values/styles_device_defaults.xml
index 28fed45..edeba02 100644
--- a/core/res/res/values/styles_device_defaults.xml
+++ b/core/res/res/values/styles_device_defaults.xml
@@ -50,6 +50,9 @@
     <style name="Widget.DeviceDefault.TextView" parent="Widget.Holo.TextView" >
 
     </style>
+    <style name="Widget.DeviceDefault.CheckedTextView" parent="Widget.Holo.CheckedTextView" >
+
+    </style>
     <style name="Widget.DeviceDefault.AutoCompleteTextView" parent="Widget.Holo.AutoCompleteTextView" >
 
     </style>
@@ -288,6 +291,9 @@
     <style name="Widget.DeviceDefault.Light.TextView" parent="Widget.Holo.Light.TextView" >
 
     </style>
+    <style name="Widget.DeviceDefault.Light.CheckedTextView" parent="Widget.Holo.Light.CheckedTextView" >
+
+    </style>
     <style name="Widget.DeviceDefault.Light.AutoCompleteTextView" parent="Widget.Holo.Light.AutoCompleteTextView" >
 
     </style>
@@ -673,7 +679,6 @@
 
     </style>
 
-
     <!-- Animation Styles -->
     <style name="Animation.DeviceDefault.Activity" parent="Animation.Holo.Activity">
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
new file mode 100644
index 0000000..68a0289
--- /dev/null
+++ b/core/res/res/values/symbols.xml
@@ -0,0 +1,1816 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+
+  <!-- We don't want to publish private symbols in android.R as part of the
+       SDK.  Instead, put them here. -->
+  <private-symbols package="com.android.internal" />
+
+  <!-- Private symbols that we need to reference from framework code.  See
+       frameworks/base/core/res/MakeJavaSymbols.sed for how to easily generate
+       this.
+  -->
+  <java-symbol type="id" name="account_name" />
+  <java-symbol type="id" name="account_row_icon" />
+  <java-symbol type="id" name="account_row_text" />
+  <java-symbol type="id" name="account_type" />
+  <java-symbol type="id" name="action_bar" />
+  <java-symbol type="id" name="action_bar_container" />
+  <java-symbol type="id" name="action_bar_overlay_layout" />
+  <java-symbol type="id" name="action_bar_title" />
+  <java-symbol type="id" name="action_bar_subtitle" />
+  <java-symbol type="id" name="action_context_bar" />
+  <java-symbol type="id" name="action_menu_presenter" />
+  <java-symbol type="id" name="action_mode_close_button" />
+  <java-symbol type="id" name="activity_chooser_view_content" />
+  <java-symbol type="id" name="albumart" />
+  <java-symbol type="id" name="alertTitle" />
+  <java-symbol type="id" name="allow_button" />
+  <java-symbol type="id" name="alwaysUse" />
+  <java-symbol type="id" name="amPm" />
+  <java-symbol type="id" name="authtoken_type" />
+  <java-symbol type="id" name="back_button" />
+  <java-symbol type="id" name="btn_next" />
+  <java-symbol type="id" name="btn_play" />
+  <java-symbol type="id" name="btn_prev" />
+  <java-symbol type="id" name="button_bar" />
+  <java-symbol type="id" name="buttonPanel" />
+  <java-symbol type="id" name="by_common" />
+  <java-symbol type="id" name="by_org" />
+  <java-symbol type="id" name="by_org_unit" />
+  <java-symbol type="id" name="calendar_view" />
+  <java-symbol type="id" name="cancel" />
+  <java-symbol type="id" name="characterPicker" />
+  <java-symbol type="id" name="clearDefaultHint" />
+  <java-symbol type="id" name="contentPanel" />
+  <java-symbol type="id" name="customPanel" />
+  <java-symbol type="id" name="datePicker" />
+  <java-symbol type="id" name="day" />
+  <java-symbol type="id" name="day_names" />
+  <java-symbol type="id" name="decrement" />
+  <java-symbol type="id" name="default_activity_button" />
+  <java-symbol type="id" name="deny_button" />
+  <java-symbol type="id" name="description" />
+  <java-symbol type="id" name="divider" />
+  <java-symbol type="id" name="edit_query" />
+  <java-symbol type="id" name="edittext_container" />
+  <java-symbol type="id" name="enter_pin_section" />
+  <java-symbol type="id" name="expand_activities_button" />
+  <java-symbol type="id" name="expand_button" />
+  <java-symbol type="id" name="expand_button_divider" />
+  <java-symbol type="id" name="expires_on" />
+  <java-symbol type="id" name="find_next" />
+  <java-symbol type="id" name="find_prev" />
+  <java-symbol type="id" name="ffwd" />
+  <java-symbol type="id" name="fillInIntent" />
+  <java-symbol type="id" name="find" />
+  <java-symbol type="id" name="fullscreenArea" />
+  <java-symbol type="id" name="hard_keyboard_section" />
+  <java-symbol type="id" name="hard_keyboard_switch" />
+  <java-symbol type="id" name="headers" />
+  <java-symbol type="id" name="hour" />
+  <java-symbol type="id" name="icon" />
+  <java-symbol type="id" name="image" />
+  <java-symbol type="id" name="increment" />
+  <java-symbol type="id" name="internalEmpty" />
+  <java-symbol type="id" name="info" />
+  <java-symbol type="id" name="inputExtractAccessories" />
+  <java-symbol type="id" name="inputExtractAction" />
+  <java-symbol type="id" name="inputExtractEditButton" />
+  <java-symbol type="id" name="issued_on" />
+  <java-symbol type="id" name="left_icon" />
+  <java-symbol type="id" name="leftSpacer" />
+  <java-symbol type="id" name="line1" />
+  <java-symbol type="id" name="line3" />
+  <java-symbol type="id" name="list_footer" />
+  <java-symbol type="id" name="list_item" />
+  <java-symbol type="id" name="listContainer" />
+  <java-symbol type="id" name="locale" />
+  <java-symbol type="id" name="matches" />
+  <java-symbol type="id" name="mediacontroller_progress" />
+  <java-symbol type="id" name="minute" />
+  <java-symbol type="id" name="mode_normal" />
+  <java-symbol type="id" name="month" />
+  <java-symbol type="id" name="month_name" />
+  <java-symbol type="id" name="name" />
+  <java-symbol type="id" name="next" />
+  <java-symbol type="id" name="next_button" />
+  <java-symbol type="id" name="new_app_action" />
+  <java-symbol type="id" name="new_app_description" />
+  <java-symbol type="id" name="new_app_icon" />
+  <java-symbol type="id" name="no_permissions" />
+  <java-symbol type="id" name="numberpicker_input" />
+  <java-symbol type="id" name="old_app_action" />
+  <java-symbol type="id" name="old_app_description" />
+  <java-symbol type="id" name="old_app_icon" />
+  <java-symbol type="id" name="overlay_display_window_texture" />
+  <java-symbol type="id" name="overlay_display_window_title" />
+  <java-symbol type="id" name="package_label" />
+  <java-symbol type="id" name="packages_list" />
+  <java-symbol type="id" name="pause" />
+  <java-symbol type="id" name="perms_list" />
+  <java-symbol type="id" name="perm_icon" />
+  <java-symbol type="id" name="perm_name" />
+  <java-symbol type="id" name="permission_group" />
+  <java-symbol type="id" name="permission_list" />
+  <java-symbol type="id" name="pickers" />
+  <java-symbol type="id" name="prefs" />
+  <java-symbol type="id" name="prefs_frame" />
+  <java-symbol type="id" name="prev" />
+  <java-symbol type="id" name="progress" />
+  <java-symbol type="id" name="progress_circular" />
+  <java-symbol type="id" name="progress_horizontal" />
+  <java-symbol type="id" name="progress_number" />
+  <java-symbol type="id" name="progress_percent" />
+  <java-symbol type="id" name="progressContainer" />
+  <java-symbol type="id" name="rew" />
+  <java-symbol type="id" name="rightSpacer" />
+  <java-symbol type="id" name="rowTypeId" />
+  <java-symbol type="id" name="scrollView" />
+  <java-symbol type="id" name="search_app_icon" />
+  <java-symbol type="id" name="search_badge" />
+  <java-symbol type="id" name="search_bar" />
+  <java-symbol type="id" name="search_button" />
+  <java-symbol type="id" name="search_close_btn" />
+  <java-symbol type="id" name="search_edit_frame" />
+  <java-symbol type="id" name="search_go_btn" />
+  <java-symbol type="id" name="search_mag_icon" />
+  <java-symbol type="id" name="search_plate" />
+  <java-symbol type="id" name="search_src_text" />
+  <java-symbol type="id" name="search_view" />
+  <java-symbol type="id" name="search_voice_btn" />
+  <java-symbol type="id" name="select_all" />
+  <java-symbol type="id" name="serial_number" />
+  <java-symbol type="id" name="seekbar" />
+  <java-symbol type="id" name="sha1_fingerprint" />
+  <java-symbol type="id" name="sha256_fingerprint" />
+  <java-symbol type="id" name="share" />
+  <java-symbol type="id" name="shortcut" />
+  <java-symbol type="id" name="skip_button" />
+  <java-symbol type="id" name="slider_group" />
+  <java-symbol type="id" name="split_action_bar" />
+  <java-symbol type="id" name="stream_icon" />
+  <java-symbol type="id" name="submit_area" />
+  <java-symbol type="id" name="switch_new" />
+  <java-symbol type="id" name="switch_old" />
+  <java-symbol type="id" name="switchWidget" />
+  <java-symbol type="id" name="text" />
+  <java-symbol type="id" name="time" />
+  <java-symbol type="id" name="time_current" />
+  <java-symbol type="id" name="timeDisplayBackground" />
+  <java-symbol type="id" name="timeDisplayForeground" />
+  <java-symbol type="id" name="titleDivider" />
+  <java-symbol type="id" name="titleDividerTop" />
+  <java-symbol type="id" name="timePicker" />
+  <java-symbol type="id" name="title_template" />
+  <java-symbol type="id" name="to_common" />
+  <java-symbol type="id" name="to_org" />
+  <java-symbol type="id" name="to_org_unit" />
+  <java-symbol type="id" name="top_action_bar" />
+  <java-symbol type="id" name="topPanel" />
+  <java-symbol type="id" name="up" />
+  <java-symbol type="id" name="value" />
+  <java-symbol type="id" name="visible_panel" />
+  <java-symbol type="id" name="websearch" />
+  <java-symbol type="id" name="wifi_p2p_wps_pin" />
+  <java-symbol type="id" name="year" />
+  <java-symbol type="id" name="zoomControls" />
+  <java-symbol type="id" name="zoomIn" />
+  <java-symbol type="id" name="zoomMagnify" />
+  <java-symbol type="id" name="zoomOut" />
+  <java-symbol type="id" name="actions" />
+  <java-symbol type="id" name="action0" />
+  <java-symbol type="id" name="action1" />
+  <java-symbol type="id" name="action2" />
+  <java-symbol type="id" name="big_picture" />
+  <java-symbol type="id" name="big_text" />
+  <java-symbol type="id" name="chronometer" />
+  <java-symbol type="id" name="inbox_text0" />
+  <java-symbol type="id" name="inbox_text1" />
+  <java-symbol type="id" name="inbox_text2" />
+  <java-symbol type="id" name="inbox_text3" />
+  <java-symbol type="id" name="inbox_text4" />
+  <java-symbol type="id" name="inbox_text5" />
+  <java-symbol type="id" name="inbox_text6" />
+  <java-symbol type="id" name="inbox_more" />
+  <java-symbol type="id" name="inbox_end_pad" />
+  <java-symbol type="id" name="status_bar_latest_event_content" />
+  <java-symbol type="id" name="action_divider" />
+  <java-symbol type="id" name="overflow_divider" />
+  <java-symbol type="id" name="sms_short_code_confirm_message" />
+  <java-symbol type="id" name="sms_short_code_detail_layout" />
+  <java-symbol type="id" name="sms_short_code_detail_message" />
+  <java-symbol type="id" name="sms_short_code_remember_choice_checkbox" />
+  <java-symbol type="id" name="sms_short_code_remember_undo_instruction" />
+  <java-symbol type="id" name="breadcrumb_section" />
+
+  <java-symbol type="attr" name="actionModeShareDrawable" />
+  <java-symbol type="attr" name="alertDialogCenterButtons" />
+  <java-symbol type="attr" name="gestureOverlayViewStyle" />
+  <java-symbol type="attr" name="keyboardViewStyle" />
+  <java-symbol type="attr" name="numberPickerStyle" />
+  <java-symbol type="attr" name="pointerStyle" />
+  <java-symbol type="attr" name="preferenceFrameLayoutStyle" />
+  <java-symbol type="attr" name="searchDialogTheme" />
+  <java-symbol type="attr" name="searchViewSearchIcon" />
+  <java-symbol type="attr" name="stackViewStyle" />
+  <java-symbol type="attr" name="switchStyle" />
+  <java-symbol type="attr" name="textAppearanceAutoCorrectionSuggestion" />
+  <java-symbol type="attr" name="textAppearanceEasyCorrectSuggestion" />
+  <java-symbol type="attr" name="textAppearanceMisspelledSuggestion" />
+  <java-symbol type="attr" name="textColorSearchUrl" />
+  <java-symbol type="attr" name="timePickerStyle" />
+  <java-symbol type="attr" name="windowFixedWidthMajor" />
+  <java-symbol type="attr" name="windowFixedWidthMinor" />
+  <java-symbol type="attr" name="windowFixedHeightMajor" />
+  <java-symbol type="attr" name="windowFixedHeightMinor" />
+  <java-symbol type="attr" name="accessibilityFocusedDrawable"/>
+
+  <java-symbol type="bool" name="action_bar_embed_tabs" />
+  <java-symbol type="bool" name="action_bar_embed_tabs_pre_jb" />
+  <java-symbol type="bool" name="action_bar_expanded_action_views_exclusive" />
+  <java-symbol type="bool" name="config_allowActionMenuItemTextWithIcon" />
+  <java-symbol type="bool" name="config_bluetooth_address_validation" />
+  <java-symbol type="bool" name="config_bluetooth_sco_off_call" />
+  <java-symbol type="bool" name="config_cellBroadcastAppLinks" />
+  <java-symbol type="bool" name="config_duplicate_port_omadm_wappush" />
+  <java-symbol type="bool" name="config_enable_emergency_call_while_sim_locked" />
+  <java-symbol type="bool" name="config_enable_puk_unlock_screen" />
+  <java-symbol type="bool" name="config_mms_content_disposition_support" />
+  <java-symbol type="bool" name="config_showMenuShortcutsWhenKeyboardPresent" />
+  <java-symbol type="bool" name="config_sip_wifi_only" />
+  <java-symbol type="bool" name="config_sms_capable" />
+  <java-symbol type="bool" name="config_sms_utf8_support" />
+  <java-symbol type="bool" name="config_swipeDisambiguation" />
+  <java-symbol type="bool" name="config_syncstorageengine_masterSyncAutomatically" />
+  <java-symbol type="bool" name="config_telephony_use_own_number_for_voicemail" />
+  <java-symbol type="bool" name="config_ui_enableFadingMarquee" />
+  <java-symbol type="bool" name="config_use_strict_phone_number_comparation" />
+  <java-symbol type="bool" name="config_voice_capable" />
+  <java-symbol type="bool" name="config_wifiDisplaySupportsProtectedBuffers" />
+  <java-symbol type="bool" name="preferences_prefer_dual_pane" />
+  <java-symbol type="bool" name="skip_restoring_network_selection" />
+  <java-symbol type="bool" name="split_action_bar_is_narrow" />
+  <java-symbol type="bool" name="config_useMasterVolume" />
+  <java-symbol type="bool" name="config_useVolumeKeySounds" />
+  <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="bool" name="config_enableWifiDisplay" />
+  <java-symbol type="bool" name="config_useDevInputEventForAudioJack" />
+  <java-symbol type="bool" name="config_safe_media_volume_enabled" />
+  <java-symbol type="bool" name="config_camera_sound_forced" />
+  <java-symbol type="bool" name="config_dontPreferApn" />
+
+  <java-symbol type="integer" name="config_cursorWindowSize" />
+  <java-symbol type="integer" name="config_longPressOnPowerBehavior" />
+  <java-symbol type="integer" name="config_max_pan_devices" />
+  <java-symbol type="integer" name="config_ntpTimeout" />
+  <java-symbol type="integer" name="config_wifi_framework_scan_interval" />
+  <java-symbol type="integer" name="config_wifi_supplicant_scan_interval" />
+  <java-symbol type="integer" name="config_wifi_scan_interval_p2p_connected" />
+  <java-symbol type="integer" name="db_connection_pool_size" />
+  <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="integer" name="config_soundEffectVolumeDb" />
+  <java-symbol type="integer" name="config_lockSoundVolumeDb" />
+  <java-symbol type="integer" name="config_multiuserMaximumUsers" />
+  <java-symbol type="integer" name="config_safe_media_volume_index" />
+
+  <java-symbol type="color" name="tab_indicator_text_v4" />
+
+  <java-symbol type="dimen" name="accessibility_touch_slop" />
+  <java-symbol type="dimen" name="config_prefDialogWidth" />
+  <java-symbol type="dimen" name="config_viewConfigurationTouchSlop" />
+  <java-symbol type="dimen" name="default_app_widget_padding_bottom" />
+  <java-symbol type="dimen" name="default_app_widget_padding_left" />
+  <java-symbol type="dimen" name="default_app_widget_padding_right" />
+  <java-symbol type="dimen" name="default_app_widget_padding_top" />
+  <java-symbol type="dimen" name="default_gap" />
+  <java-symbol type="dimen" name="dropdownitem_icon_width" />
+  <java-symbol type="dimen" name="dropdownitem_text_padding_left" />
+  <java-symbol type="dimen" name="fastscroll_overlay_size" />
+  <java-symbol type="dimen" name="fastscroll_thumb_height" />
+  <java-symbol type="dimen" name="fastscroll_thumb_width" />
+  <java-symbol type="dimen" name="fastscroll_thumb_width" />
+  <java-symbol type="dimen" name="password_keyboard_spacebar_vertical_correction" />
+  <java-symbol type="dimen" name="search_view_preferred_width" />
+  <java-symbol type="dimen" name="textview_error_popup_default_width" />
+  <java-symbol type="dimen" name="toast_y_offset" />
+  <java-symbol type="dimen" name="volume_panel_top" />
+  <java-symbol type="dimen" name="action_bar_stacked_max_height" />
+  <java-symbol type="dimen" name="action_bar_stacked_tab_max_width" />
+  <java-symbol type="dimen" name="notification_text_size" />
+  <java-symbol type="dimen" name="notification_title_text_size" />
+  <java-symbol type="dimen" name="notification_subtext_size" />
+
+  <java-symbol type="string" name="add_account_button_label" />
+  <java-symbol type="string" name="addToDictionary" />
+  <java-symbol type="string" name="action_bar_home_description" />
+  <java-symbol type="string" name="action_bar_up_description" />
+  <java-symbol type="string" name="delete" />
+  <java-symbol type="string" name="deleteText" />
+  <java-symbol type="string" name="ellipsis_two_dots" />
+  <java-symbol type="string" name="ellipsis" />
+  <java-symbol type="string" name="grant_permissions_header_text" />
+  <java-symbol type="string" name="list_delimeter" />
+  <java-symbol type="string" name="menu_delete_shortcut_label" />
+  <java-symbol type="string" name="menu_enter_shortcut_label" />
+  <java-symbol type="string" name="menu_space_shortcut_label" />
+  <java-symbol type="string" name="notification_title" />
+  <java-symbol type="string" name="permission_request_notification_with_subtitle" />
+  <java-symbol type="string" name="prepend_shortcut_label" />
+  <java-symbol type="string" name="replace" />
+  <java-symbol type="string" name="textSelectionCABTitle" />
+  <java-symbol type="string" name="BaMmi" />
+  <java-symbol type="string" name="CLIRDefaultOffNextCallOff" />
+  <java-symbol type="string" name="CLIRDefaultOffNextCallOn" />
+  <java-symbol type="string" name="CLIRDefaultOnNextCallOff" />
+  <java-symbol type="string" name="CLIRDefaultOnNextCallOn" />
+  <java-symbol type="string" name="CLIRPermanent" />
+  <java-symbol type="string" name="CfMmi" />
+  <java-symbol type="string" name="ClipMmi" />
+  <java-symbol type="string" name="ClirMmi" />
+  <java-symbol type="string" name="CwMmi" />
+  <java-symbol type="string" name="Midnight" />
+  <java-symbol type="string" name="Noon" />
+  <java-symbol type="string" name="PinMmi" />
+  <java-symbol type="string" name="PwdMmi" />
+  <java-symbol type="string" name="RestrictedChangedTitle" />
+  <java-symbol type="string" name="RestrictedOnAllVoice" />
+  <java-symbol type="string" name="RestrictedOnData" />
+  <java-symbol type="string" name="RestrictedOnEmergency" />
+  <java-symbol type="string" name="RestrictedOnNormal" />
+  <java-symbol type="string" name="SetupCallDefault" />
+  <java-symbol type="string" name="abbrev_month" />
+  <java-symbol type="string" name="abbrev_month_day" />
+  <java-symbol type="string" name="abbrev_month_day_year" />
+  <java-symbol type="string" name="abbrev_month_year" />
+  <java-symbol type="string" name="accept" />
+  <java-symbol type="string" name="accessibility_enabled" />
+  <java-symbol type="string" name="activity_chooser_view_see_all" />
+  <java-symbol type="string" name="activitychooserview_choose_application" />
+  <java-symbol type="string" name="alternate_eri_file" />
+  <java-symbol type="string" name="alwaysUse" />
+  <java-symbol type="string" name="autofill_address_line_1_label_re" />
+  <java-symbol type="string" name="autofill_address_line_1_re" />
+  <java-symbol type="string" name="autofill_address_line_2_re" />
+  <java-symbol type="string" name="autofill_address_line_3_re" />
+  <java-symbol type="string" name="autofill_address_name_separator" />
+  <java-symbol type="string" name="autofill_address_summary_format" />
+  <java-symbol type="string" name="autofill_address_summary_name_format" />
+  <java-symbol type="string" name="autofill_address_summary_separator" />
+  <java-symbol type="string" name="autofill_address_type_same_as_re" />
+  <java-symbol type="string" name="autofill_address_type_use_my_re" />
+  <java-symbol type="string" name="autofill_area" />
+  <java-symbol type="string" name="autofill_area_code_notext_re" />
+  <java-symbol type="string" name="autofill_area_code_re" />
+  <java-symbol type="string" name="autofill_attention_ignored_re" />
+  <java-symbol type="string" name="autofill_billing_designator_re" />
+  <java-symbol type="string" name="autofill_card_cvc_re" />
+  <java-symbol type="string" name="autofill_card_ignored_re" />
+  <java-symbol type="string" name="autofill_card_number_re" />
+  <java-symbol type="string" name="autofill_city_re" />
+  <java-symbol type="string" name="autofill_company_re" />
+  <java-symbol type="string" name="autofill_country_code_re" />
+  <java-symbol type="string" name="autofill_country_re" />
+  <java-symbol type="string" name="autofill_county" />
+  <java-symbol type="string" name="autofill_department" />
+  <java-symbol type="string" name="autofill_district" />
+  <java-symbol type="string" name="autofill_email_re" />
+  <java-symbol type="string" name="autofill_emirate" />
+  <java-symbol type="string" name="autofill_expiration_date_re" />
+  <java-symbol type="string" name="autofill_expiration_month_re" />
+  <java-symbol type="string" name="autofill_fax_re" />
+  <java-symbol type="string" name="autofill_first_name_re" />
+  <java-symbol type="string" name="autofill_island" />
+  <java-symbol type="string" name="autofill_last_name_re" />
+  <java-symbol type="string" name="autofill_middle_initial_re" />
+  <java-symbol type="string" name="autofill_middle_name_re" />
+  <java-symbol type="string" name="autofill_name_on_card_contextual_re" />
+  <java-symbol type="string" name="autofill_name_on_card_re" />
+  <java-symbol type="string" name="autofill_name_re" />
+  <java-symbol type="string" name="autofill_name_specific_re" />
+  <java-symbol type="string" name="autofill_parish" />
+  <java-symbol type="string" name="autofill_phone_extension_re" />
+  <java-symbol type="string" name="autofill_phone_prefix_re" />
+  <java-symbol type="string" name="autofill_phone_prefix_separator_re" />
+  <java-symbol type="string" name="autofill_phone_re" />
+  <java-symbol type="string" name="autofill_phone_suffix_re" />
+  <java-symbol type="string" name="autofill_phone_suffix_separator_re" />
+  <java-symbol type="string" name="autofill_postal_code" />
+  <java-symbol type="string" name="autofill_prefecture" />
+  <java-symbol type="string" name="autofill_province" />
+  <java-symbol type="string" name="autofill_region_ignored_re" />
+  <java-symbol type="string" name="autofill_shipping_designator_re" />
+  <java-symbol type="string" name="autofill_state" />
+  <java-symbol type="string" name="autofill_state_re" />
+  <java-symbol type="string" name="autofill_this_form" />
+  <java-symbol type="string" name="autofill_username_re" />
+  <java-symbol type="string" name="autofill_zip_4_re" />
+  <java-symbol type="string" name="autofill_zip_code" />
+  <java-symbol type="string" name="autofill_zip_code_re" />
+  <java-symbol type="string" name="badPin" />
+  <java-symbol type="string" name="badPuk" />
+  <java-symbol type="string" name="byteShort" />
+  <java-symbol type="string" name="cfTemplateForwarded" />
+  <java-symbol type="string" name="cfTemplateForwardedTime" />
+  <java-symbol type="string" name="cfTemplateNotForwarded" />
+  <java-symbol type="string" name="cfTemplateRegistered" />
+  <java-symbol type="string" name="cfTemplateRegisteredTime" />
+  <java-symbol type="string" name="chooseActivity" />
+  <java-symbol type="string" name="config_default_dns_server" />
+  <java-symbol type="string" name="config_ethernet_iface_regex" />
+  <java-symbol type="string" name="config_ntpServer" />
+  <java-symbol type="string" name="config_tether_apndata" />
+  <java-symbol type="string" name="config_useragentprofile_url" />
+  <java-symbol type="string" name="config_wifi_p2p_device_type" />
+  <java-symbol type="string" name="contentServiceSync" />
+  <java-symbol type="string" name="contentServiceSyncNotificationTitle" />
+  <java-symbol type="string" name="contentServiceTooManyDeletesNotificationDesc" />
+  <java-symbol type="string" name="continue_to_enable_accessibility" />
+  <java-symbol type="string" name="date1_date2" />
+  <java-symbol type="string" name="date1_time1_date2_time2" />
+  <java-symbol type="string" name="date_and_time" />
+  <java-symbol type="string" name="date_picker_decrement_day_button" />
+  <java-symbol type="string" name="date_picker_decrement_month_button" />
+  <java-symbol type="string" name="date_picker_decrement_year_button" />
+  <java-symbol type="string" name="date_picker_dialog_title" />
+  <java-symbol type="string" name="date_picker_increment_day_button" />
+  <java-symbol type="string" name="date_picker_increment_month_button" />
+  <java-symbol type="string" name="date_picker_increment_year_button" />
+  <java-symbol type="string" name="date_time" />
+  <java-symbol type="string" name="date_time_set" />
+  <java-symbol type="string" name="date_time_done" />
+  <java-symbol type="string" name="db_default_journal_mode" />
+  <java-symbol type="string" name="db_default_sync_mode" />
+  <java-symbol type="string" name="db_wal_sync_mode" />
+  <java-symbol type="string" name="decline" />
+  <java-symbol type="string" name="default_text_encoding" />
+  <java-symbol type="string" name="description_target_unlock_tablet" />
+  <java-symbol type="string" name="display_manager_built_in_display_name" />
+  <java-symbol type="string" name="display_manager_hdmi_display_name" />
+  <java-symbol type="string" name="display_manager_overlay_display_name" />
+  <java-symbol type="string" name="display_manager_overlay_display_title" />
+  <java-symbol type="string" name="double_tap_toast" />
+  <java-symbol type="string" name="elapsed_time_short_format_h_mm_ss" />
+  <java-symbol type="string" name="elapsed_time_short_format_mm_ss" />
+  <java-symbol type="string" name="emailTypeCustom" />
+  <java-symbol type="string" name="emailTypeHome" />
+  <java-symbol type="string" name="emailTypeMobile" />
+  <java-symbol type="string" name="emailTypeOther" />
+  <java-symbol type="string" name="emailTypeWork" />
+  <java-symbol type="string" name="emergency_call_dialog_number_for_display" />
+  <java-symbol type="string" name="widget_default_package_name" />
+  <java-symbol type="string" name="widget_default_class_name" />
+  <java-symbol type="string" name="emergency_calls_only" />
+  <java-symbol type="string" name="enable_accessibility_canceled" />
+  <java-symbol type="string" name="eventTypeAnniversary" />
+  <java-symbol type="string" name="eventTypeBirthday" />
+  <java-symbol type="string" name="eventTypeCustom" />
+  <java-symbol type="string" name="eventTypeOther" />
+  <java-symbol type="string" name="extmedia_format_button_format" />
+  <java-symbol type="string" name="extmedia_format_message" />
+  <java-symbol type="string" name="extmedia_format_title" />
+  <java-symbol type="string" name="fileSizeSuffix" />
+  <java-symbol type="string" name="force_close" />
+  <java-symbol type="string" name="format_error" />
+  <java-symbol type="string" name="gadget_host_error_inflating" />
+  <java-symbol type="string" name="gigabyteShort" />
+  <java-symbol type="string" name="gpsNotifMessage" />
+  <java-symbol type="string" name="gpsNotifTicker" />
+  <java-symbol type="string" name="gpsNotifTitle" />
+  <java-symbol type="string" name="gpsVerifNo" />
+  <java-symbol type="string" name="gpsVerifYes" />
+  <java-symbol type="string" name="gsm_alphabet_default_charset" />
+  <java-symbol type="string" name="hour_ampm" />
+  <java-symbol type="string" name="hour_cap_ampm" />
+  <java-symbol type="string" name="hour_minute_24" />
+  <java-symbol type="string" name="hour_minute_ampm" />
+  <java-symbol type="string" name="hour_minute_cap_ampm" />
+  <java-symbol type="string" name="httpError" />
+  <java-symbol type="string" name="httpErrorAuth" />
+  <java-symbol type="string" name="httpErrorConnect" />
+  <java-symbol type="string" name="httpErrorFailedSslHandshake" />
+  <java-symbol type="string" name="httpErrorFile" />
+  <java-symbol type="string" name="httpErrorFileNotFound" />
+  <java-symbol type="string" name="httpErrorIO" />
+  <java-symbol type="string" name="httpErrorLookup" />
+  <java-symbol type="string" name="httpErrorOk" />
+  <java-symbol type="string" name="httpErrorProxyAuth" />
+  <java-symbol type="string" name="httpErrorRedirectLoop" />
+  <java-symbol type="string" name="httpErrorTimeout" />
+  <java-symbol type="string" name="httpErrorTooManyRequests" />
+  <java-symbol type="string" name="httpErrorUnsupportedAuthScheme" />
+  <java-symbol type="string" name="imProtocolAim" />
+  <java-symbol type="string" name="imProtocolCustom" />
+  <java-symbol type="string" name="imProtocolGoogleTalk" />
+  <java-symbol type="string" name="imProtocolIcq" />
+  <java-symbol type="string" name="imProtocolJabber" />
+  <java-symbol type="string" name="imProtocolMsn" />
+  <java-symbol type="string" name="imProtocolNetMeeting" />
+  <java-symbol type="string" name="imProtocolQq" />
+  <java-symbol type="string" name="imProtocolSkype" />
+  <java-symbol type="string" name="imProtocolYahoo" />
+  <java-symbol type="string" name="imTypeCustom" />
+  <java-symbol type="string" name="imTypeHome" />
+  <java-symbol type="string" name="imTypeOther" />
+  <java-symbol type="string" name="imTypeWork" />
+  <java-symbol type="string" name="ime_action_default" />
+  <java-symbol type="string" name="ime_action_done" />
+  <java-symbol type="string" name="ime_action_go" />
+  <java-symbol type="string" name="ime_action_next" />
+  <java-symbol type="string" name="ime_action_previous" />
+  <java-symbol type="string" name="ime_action_search" />
+  <java-symbol type="string" name="ime_action_send" />
+  <java-symbol type="string" name="invalidPin" />
+  <java-symbol type="string" name="js_dialog_before_unload" />
+  <java-symbol type="string" name="js_dialog_title" />
+  <java-symbol type="string" name="js_dialog_title_default" />
+  <java-symbol type="string" name="keyboard_headset_required_to_hear_password" />
+  <java-symbol type="string" name="keyboard_password_character_no_headset" />
+  <java-symbol type="string" name="keyboardview_keycode_alt" />
+  <java-symbol type="string" name="keyboardview_keycode_cancel" />
+  <java-symbol type="string" name="keyboardview_keycode_delete" />
+  <java-symbol type="string" name="keyboardview_keycode_done" />
+  <java-symbol type="string" name="keyboardview_keycode_enter" />
+  <java-symbol type="string" name="keyboardview_keycode_mode_change" />
+  <java-symbol type="string" name="keyboardview_keycode_shift" />
+  <java-symbol type="string" name="keyguard_accessibility_add_widget" />
+  <java-symbol type="string" name="keyguard_accessibility_camera" />
+  <java-symbol type="string" name="keyguard_accessibility_expand_lock_area" />
+  <java-symbol type="string" name="keyguard_accessibility_face_unlock" />
+  <java-symbol type="string" name="keygaurd_accessibility_media_controls" />
+  <java-symbol type="string" name="keyguard_accessibility_pattern_area" />
+  <java-symbol type="string" name="keyguard_accessibility_pattern_unlock" />
+  <java-symbol type="string" name="keyguard_accessibility_password_unlock" />
+  <java-symbol type="string" name="keyguard_accessibility_pin_unlock" />
+  <java-symbol type="string" name="keyguard_accessibility_slide_area" />
+  <java-symbol type="string" name="keyguard_accessibility_slide_unlock" />
+  <java-symbol type="string" name="keyguard_accessibility_status" />
+  <java-symbol type="string" name="keyguard_accessibility_user_selector" />
+  <java-symbol type="string" name="keyguard_accessibility_widget" />
+  <java-symbol type="string" name="keyguard_accessibility_widget_deleted" />
+  <java-symbol type="string" name="keyguard_accessibility_widget_empty_slot" />
+  <java-symbol type="string" name="keyguard_accessibility_widget_reorder_start" />
+  <java-symbol type="string" name="keyguard_accessibility_widget_reorder_end" />
+  <java-symbol type="string" name="keyguard_accessibility_unlock_area_collapsed" />
+  <java-symbol type="string" name="keyguard_accessibility_unlock_area_expanded" />
+  <java-symbol type="string" name="kilobyteShort" />
+  <java-symbol type="string" name="last_month" />
+  <java-symbol type="string" name="launchBrowserDefault" />
+  <java-symbol type="string" name="lockscreen_access_pattern_cell_added" />
+  <java-symbol type="string" name="lockscreen_access_pattern_cleared" />
+  <java-symbol type="string" name="lockscreen_access_pattern_detected" />
+  <java-symbol type="string" name="lockscreen_access_pattern_start" />
+  <java-symbol type="string" name="lockscreen_emergency_call" />
+  <java-symbol type="string" name="lockscreen_return_to_call" />
+  <java-symbol type="string" name="lockscreen_transport_pause_description" />
+  <java-symbol type="string" name="lockscreen_transport_play_description" />
+  <java-symbol type="string" name="lockscreen_transport_stop_description" />
+  <java-symbol type="string" name="low_memory" />
+  <java-symbol type="string" name="media_bad_removal" />
+  <java-symbol type="string" name="media_checking" />
+  <java-symbol type="string" name="media_removed" />
+  <java-symbol type="string" name="media_shared" />
+  <java-symbol type="string" name="media_unknown_state" />
+  <java-symbol type="string" name="megabyteShort" />
+  <java-symbol type="string" name="midnight" />
+  <java-symbol type="string" name="mismatchPin" />
+  <java-symbol type="string" name="mmiComplete" />
+  <java-symbol type="string" name="mmiError" />
+  <java-symbol type="string" name="mmiFdnError" />
+  <java-symbol type="string" name="month" />
+  <java-symbol type="string" name="month_day" />
+  <java-symbol type="string" name="month_day_year" />
+  <java-symbol type="string" name="month_year" />
+  <java-symbol type="string" name="more_item_label" />
+  <java-symbol type="string" name="needPuk" />
+  <java-symbol type="string" name="needPuk2" />
+  <java-symbol type="string" name="new_app_action" />
+  <java-symbol type="string" name="new_app_description" />
+  <java-symbol type="string" name="noApplications" />
+  <java-symbol type="string" name="no_file_chosen" />
+  <java-symbol type="string" name="no_matches" />
+  <java-symbol type="string" name="noon" />
+  <java-symbol type="string" name="number_picker_increment_scroll_action" />
+  <java-symbol type="string" name="number_picker_increment_scroll_mode" />
+  <java-symbol type="string" name="numeric_date" />
+  <java-symbol type="string" name="numeric_date_format" />
+  <java-symbol type="string" name="numeric_date_template" />
+  <java-symbol type="string" name="numeric_md1_md2" />
+  <java-symbol type="string" name="numeric_md1_time1_md2_time2" />
+  <java-symbol type="string" name="numeric_mdy1_mdy2" />
+  <java-symbol type="string" name="numeric_mdy1_time1_mdy2_time2" />
+  <java-symbol type="string" name="numeric_wday1_md1_time1_wday2_md2_time2" />
+  <java-symbol type="string" name="numeric_wday1_md1_wday2_md2" />
+  <java-symbol type="string" name="numeric_wday1_mdy1_time1_wday2_mdy2_time2" />
+  <java-symbol type="string" name="numeric_wday1_mdy1_wday2_mdy2" />
+  <java-symbol type="string" name="old_app_action" />
+  <java-symbol type="string" name="old_app_description" />
+  <java-symbol type="string" name="older" />
+  <java-symbol type="string" name="open_permission_deny" />
+  <java-symbol type="string" name="orgTypeCustom" />
+  <java-symbol type="string" name="orgTypeOther" />
+  <java-symbol type="string" name="orgTypeWork" />
+  <java-symbol type="string" name="passwordIncorrect" />
+  <java-symbol type="string" name="perms_description_app" />
+  <java-symbol type="string" name="perms_new_perm_prefix" />
+  <java-symbol type="string" name="petabyteShort" />
+  <java-symbol type="string" name="phoneTypeAssistant" />
+  <java-symbol type="string" name="phoneTypeCallback" />
+  <java-symbol type="string" name="phoneTypeCar" />
+  <java-symbol type="string" name="phoneTypeCompanyMain" />
+  <java-symbol type="string" name="phoneTypeCustom" />
+  <java-symbol type="string" name="phoneTypeFaxHome" />
+  <java-symbol type="string" name="phoneTypeFaxWork" />
+  <java-symbol type="string" name="phoneTypeHome" />
+  <java-symbol type="string" name="phoneTypeIsdn" />
+  <java-symbol type="string" name="phoneTypeMain" />
+  <java-symbol type="string" name="phoneTypeMms" />
+  <java-symbol type="string" name="phoneTypeMobile" />
+  <java-symbol type="string" name="phoneTypeOther" />
+  <java-symbol type="string" name="phoneTypeOtherFax" />
+  <java-symbol type="string" name="phoneTypePager" />
+  <java-symbol type="string" name="phoneTypeRadio" />
+  <java-symbol type="string" name="phoneTypeTelex" />
+  <java-symbol type="string" name="phoneTypeTtyTdd" />
+  <java-symbol type="string" name="phoneTypeWork" />
+  <java-symbol type="string" name="phoneTypeWorkMobile" />
+  <java-symbol type="string" name="phoneTypeWorkPager" />
+  <java-symbol type="string" name="policydesc_disableCamera" />
+  <java-symbol type="string" name="policydesc_encryptedStorage" />
+  <java-symbol type="string" name="policydesc_expirePassword" />
+  <java-symbol type="string" name="policydesc_forceLock" />
+  <java-symbol type="string" name="policydesc_limitPassword" />
+  <java-symbol type="string" name="policydesc_resetPassword" />
+  <java-symbol type="string" name="policydesc_setGlobalProxy" />
+  <java-symbol type="string" name="policydesc_watchLogin" />
+  <java-symbol type="string" name="policydesc_wipeData" />
+  <java-symbol type="string" name="policydesc_disableKeyguardFeatures" />
+  <java-symbol type="string" name="policylab_disableCamera" />
+  <java-symbol type="string" name="policylab_encryptedStorage" />
+  <java-symbol type="string" name="policylab_expirePassword" />
+  <java-symbol type="string" name="policylab_forceLock" />
+  <java-symbol type="string" name="policylab_limitPassword" />
+  <java-symbol type="string" name="policylab_resetPassword" />
+  <java-symbol type="string" name="policylab_setGlobalProxy" />
+  <java-symbol type="string" name="policylab_watchLogin" />
+  <java-symbol type="string" name="policylab_wipeData" />
+  <java-symbol type="string" name="policylab_disableKeyguardFeatures" />
+  <java-symbol type="string" name="postalTypeCustom" />
+  <java-symbol type="string" name="postalTypeHome" />
+  <java-symbol type="string" name="postalTypeOther" />
+  <java-symbol type="string" name="postalTypeWork" />
+  <java-symbol type="string" name="power_off" />
+  <java-symbol type="string" name="preposition_for_date" />
+  <java-symbol type="string" name="preposition_for_time" />
+  <java-symbol type="string" name="progress_erasing" />
+  <java-symbol type="string" name="progress_unmounting" />
+  <java-symbol type="string" name="reboot_safemode_confirm" />
+  <java-symbol type="string" name="reboot_safemode_title" />
+  <java-symbol type="string" name="relationTypeAssistant" />
+  <java-symbol type="string" name="relationTypeBrother" />
+  <java-symbol type="string" name="relationTypeChild" />
+  <java-symbol type="string" name="relationTypeDomesticPartner" />
+  <java-symbol type="string" name="relationTypeFather" />
+  <java-symbol type="string" name="relationTypeFriend" />
+  <java-symbol type="string" name="relationTypeManager" />
+  <java-symbol type="string" name="relationTypeMother" />
+  <java-symbol type="string" name="relationTypeParent" />
+  <java-symbol type="string" name="relationTypePartner" />
+  <java-symbol type="string" name="relationTypeReferredBy" />
+  <java-symbol type="string" name="relationTypeRelative" />
+  <java-symbol type="string" name="relationTypeSister" />
+  <java-symbol type="string" name="relationTypeSpouse" />
+  <java-symbol type="string" name="relative_time" />
+  <java-symbol type="string" name="reset" />
+  <java-symbol type="string" name="ringtone_default" />
+  <java-symbol type="string" name="ringtone_default_with_actual" />
+  <java-symbol type="string" name="ringtone_picker_title" />
+  <java-symbol type="string" name="ringtone_silent" />
+  <java-symbol type="string" name="ringtone_unknown" />
+  <java-symbol type="string" name="roamingText0" />
+  <java-symbol type="string" name="roamingText1" />
+  <java-symbol type="string" name="roamingText10" />
+  <java-symbol type="string" name="roamingText11" />
+  <java-symbol type="string" name="roamingText12" />
+  <java-symbol type="string" name="roamingText2" />
+  <java-symbol type="string" name="roamingText3" />
+  <java-symbol type="string" name="roamingText4" />
+  <java-symbol type="string" name="roamingText5" />
+  <java-symbol type="string" name="roamingText6" />
+  <java-symbol type="string" name="roamingText7" />
+  <java-symbol type="string" name="roamingText8" />
+  <java-symbol type="string" name="roamingText9" />
+  <java-symbol type="string" name="roamingTextSearching" />
+  <java-symbol type="string" name="same_month_md1_md2" />
+  <java-symbol type="string" name="same_month_md1_time1_md2_time2" />
+  <java-symbol type="string" name="same_month_mdy1_mdy2" />
+  <java-symbol type="string" name="same_month_mdy1_time1_mdy2_time2" />
+  <java-symbol type="string" name="same_month_wday1_md1_time1_wday2_md2_time2" />
+  <java-symbol type="string" name="same_month_wday1_md1_wday2_md2" />
+  <java-symbol type="string" name="same_month_wday1_mdy1_time1_wday2_mdy2_time2" />
+  <java-symbol type="string" name="same_month_wday1_mdy1_wday2_mdy2" />
+  <java-symbol type="string" name="same_year_md1_md2" />
+  <java-symbol type="string" name="same_year_md1_time1_md2_time2" />
+  <java-symbol type="string" name="same_year_mdy1_mdy2" />
+  <java-symbol type="string" name="same_year_mdy1_time1_mdy2_time2" />
+  <java-symbol type="string" name="same_year_wday1_md1_time1_wday2_md2_time2" />
+  <java-symbol type="string" name="same_year_wday1_md1_wday2_md2" />
+  <java-symbol type="string" name="same_year_wday1_mdy1_time1_wday2_mdy2_time2" />
+  <java-symbol type="string" name="same_year_wday1_mdy1_wday2_mdy2" />
+  <java-symbol type="string" name="save_password_label" />
+  <java-symbol type="string" name="save_password_message" />
+  <java-symbol type="string" name="save_password_never" />
+  <java-symbol type="string" name="save_password_notnow" />
+  <java-symbol type="string" name="save_password_remember" />
+  <java-symbol type="string" name="sendText" />
+  <java-symbol type="string" name="sending" />
+  <java-symbol type="string" name="serviceClassData" />
+  <java-symbol type="string" name="serviceClassDataAsync" />
+  <java-symbol type="string" name="serviceClassDataSync" />
+  <java-symbol type="string" name="serviceClassFAX" />
+  <java-symbol type="string" name="serviceClassPAD" />
+  <java-symbol type="string" name="serviceClassPacket" />
+  <java-symbol type="string" name="serviceClassSMS" />
+  <java-symbol type="string" name="serviceClassVoice" />
+  <java-symbol type="string" name="serviceDisabled" />
+  <java-symbol type="string" name="serviceEnabled" />
+  <java-symbol type="string" name="serviceEnabledFor" />
+  <java-symbol type="string" name="serviceErased" />
+  <java-symbol type="string" name="serviceNotProvisioned" />
+  <java-symbol type="string" name="serviceRegistered" />
+  <java-symbol type="string" name="setup_autofill" />
+  <java-symbol type="string" name="share" />
+  <java-symbol type="string" name="shareactionprovider_share_with" />
+  <java-symbol type="string" name="shareactionprovider_share_with_application" />
+  <java-symbol type="string" name="short_format_month" />
+  <java-symbol type="string" name="shutdown_confirm" />
+  <java-symbol type="string" name="shutdown_confirm_question" />
+  <java-symbol type="string" name="shutdown_progress" />
+  <java-symbol type="string" name="sim_added_message" />
+  <java-symbol type="string" name="sim_added_title" />
+  <java-symbol type="string" name="sim_removed_message" />
+  <java-symbol type="string" name="sim_removed_title" />
+  <java-symbol type="string" name="sim_restart_button" />
+  <java-symbol type="string" name="sipAddressTypeCustom" />
+  <java-symbol type="string" name="sipAddressTypeHome" />
+  <java-symbol type="string" name="sipAddressTypeOther" />
+  <java-symbol type="string" name="sipAddressTypeWork" />
+  <java-symbol type="string" name="sms_control_message" />
+  <java-symbol type="string" name="sms_control_title" />
+  <java-symbol type="string" name="sms_control_no" />
+  <java-symbol type="string" name="sms_control_yes" />
+  <java-symbol type="string" name="sms_short_code_confirm_allow" />
+  <java-symbol type="string" name="sms_short_code_confirm_deny" />
+  <java-symbol type="string" name="sms_short_code_confirm_always_allow" />
+  <java-symbol type="string" name="sms_short_code_confirm_never_allow" />
+  <java-symbol type="string" name="sms_short_code_confirm_message" />
+  <java-symbol type="string" name="sms_short_code_details" />
+  <java-symbol type="string" name="sms_premium_short_code_details" />
+  <java-symbol type="string" name="sms_short_code_remember_undo_instruction" />
+  <java-symbol type="string" name="submit" />
+  <java-symbol type="string" name="sync_binding_label" />
+  <java-symbol type="string" name="sync_do_nothing" />
+  <java-symbol type="string" name="sync_really_delete" />
+  <java-symbol type="string" name="sync_too_many_deletes_desc" />
+  <java-symbol type="string" name="sync_undo_deletes" />
+  <java-symbol type="string" name="terabyteShort" />
+  <java-symbol type="string" name="text_copied" />
+  <java-symbol type="string" name="time1_time2" />
+  <java-symbol type="string" name="time_date" />
+  <java-symbol type="string" name="time_of_day" />
+  <java-symbol type="string" name="time_picker_decrement_hour_button" />
+  <java-symbol type="string" name="time_picker_decrement_minute_button" />
+  <java-symbol type="string" name="time_picker_decrement_set_am_button" />
+  <java-symbol type="string" name="time_picker_dialog_title" />
+  <java-symbol type="string" name="time_picker_increment_hour_button" />
+  <java-symbol type="string" name="time_picker_increment_minute_button" />
+  <java-symbol type="string" name="time_picker_increment_set_pm_button" />
+  <java-symbol type="string" name="time_picker_separator" />
+  <java-symbol type="string" name="time_wday" />
+  <java-symbol type="string" name="time_wday_date" />
+  <java-symbol type="string" name="twelve_hour_time_format" />
+  <java-symbol type="string" name="twenty_four_hour_time_format" />
+  <java-symbol type="string" name="upload_file" />
+  <java-symbol type="string" name="user_switched" />
+  <java-symbol type="string" name="volume_alarm" />
+  <java-symbol type="string" name="volume_icon_description_bluetooth" />
+  <java-symbol type="string" name="volume_icon_description_incall" />
+  <java-symbol type="string" name="volume_icon_description_media" />
+  <java-symbol type="string" name="volume_icon_description_notification" />
+  <java-symbol type="string" name="volume_icon_description_ringer" />
+  <java-symbol type="string" name="wait" />
+  <java-symbol type="string" name="wday1_date1_time1_wday2_date2_time2" />
+  <java-symbol type="string" name="wday1_date1_wday2_date2" />
+  <java-symbol type="string" name="wday_date" />
+  <java-symbol type="string" name="web_user_agent" />
+  <java-symbol type="string" name="web_user_agent_target_content" />
+  <java-symbol type="string" name="webpage_unresponsive" />
+  <java-symbol type="string" name="whichApplication" />
+  <java-symbol type="string" name="wifi_available_sign_in" />
+  <java-symbol type="string" name="network_available_sign_in" />
+  <java-symbol type="string" name="network_available_sign_in_detailed" />
+  <java-symbol type="string" name="wifi_p2p_dialog_title" />
+  <java-symbol type="string" name="wifi_p2p_enabled_notification_message" />
+  <java-symbol type="string" name="wifi_p2p_enabled_notification_title" />
+  <java-symbol type="string" name="wifi_p2p_failed_message" />
+  <java-symbol type="string" name="wifi_p2p_from_message" />
+  <java-symbol type="string" name="wifi_p2p_invitation_sent_title" />
+  <java-symbol type="string" name="wifi_p2p_invitation_to_connect_title" />
+  <java-symbol type="string" name="wifi_p2p_show_pin_message" />
+  <java-symbol type="string" name="wifi_p2p_to_message" />
+  <java-symbol type="string" name="wifi_p2p_turnon_message" />
+  <java-symbol type="string" name="wifi_p2p_frequency_conflict_message" />
+  <java-symbol type="string" name="wifi_tether_configure_ssid_default" />
+  <java-symbol type="string" name="wifi_watchdog_network_disabled" />
+  <java-symbol type="string" name="wifi_watchdog_network_disabled_detailed" />
+  <java-symbol type="string" name="imei" />
+  <java-symbol type="string" name="meid" />
+  <java-symbol type="string" name="granularity_label_character" />
+  <java-symbol type="string" name="granularity_label_word" />
+  <java-symbol type="string" name="granularity_label_link" />
+  <java-symbol type="string" name="granularity_label_line" />
+  <java-symbol type="string" name="default_audio_route_name" />
+  <java-symbol type="string" name="default_audio_route_name_headphones" />
+  <java-symbol type="string" name="default_audio_route_name_dock_speakers" />
+  <java-symbol type="string" name="default_media_route_name_hdmi" />
+  <java-symbol type="string" name="default_audio_route_category_name" />
+  <java-symbol type="string" name="safe_media_volume_warning" />
+  <java-symbol type="string" name="media_route_status_scanning" />
+  <java-symbol type="string" name="media_route_status_connecting" />
+  <java-symbol type="string" name="media_route_status_available" />
+  <java-symbol type="string" name="media_route_status_not_available" />
+  <java-symbol type="string" name="owner_name" />
+
+  <java-symbol type="plurals" name="abbrev_in_num_days" />
+  <java-symbol type="plurals" name="abbrev_in_num_hours" />
+  <java-symbol type="plurals" name="abbrev_in_num_minutes" />
+  <java-symbol type="plurals" name="abbrev_in_num_seconds" />
+  <java-symbol type="plurals" name="abbrev_num_days_ago" />
+  <java-symbol type="plurals" name="abbrev_num_hours_ago" />
+  <java-symbol type="plurals" name="abbrev_num_minutes_ago" />
+  <java-symbol type="plurals" name="abbrev_num_seconds_ago" />
+  <java-symbol type="plurals" name="in_num_days" />
+  <java-symbol type="plurals" name="in_num_hours" />
+  <java-symbol type="plurals" name="in_num_minutes" />
+  <java-symbol type="plurals" name="in_num_seconds" />
+  <java-symbol type="plurals" name="last_num_days" />
+  <java-symbol type="plurals" name="matches_found" />
+  <java-symbol type="plurals" name="num_days_ago" />
+  <java-symbol type="plurals" name="num_hours_ago" />
+  <java-symbol type="plurals" name="num_minutes_ago" />
+  <java-symbol type="plurals" name="num_seconds_ago" />
+
+  <java-symbol type="array" name="carrier_properties" />
+  <java-symbol type="array" name="config_data_usage_network_types" />
+  <java-symbol type="array" name="config_sms_enabled_locking_shift_tables" />
+  <java-symbol type="array" name="config_sms_enabled_single_shift_tables" />
+  <java-symbol type="array" name="config_twoDigitNumberPattern" />
+  <java-symbol type="array" name="networkAttributes" />
+  <java-symbol type="array" name="preloaded_color_state_lists" />
+  <java-symbol type="array" name="preloaded_drawables" />
+  <java-symbol type="array" name="special_locale_codes" />
+  <java-symbol type="array" name="special_locale_names" />
+  <java-symbol type="array" name="config_masterVolumeRamp" />
+  <java-symbol type="array" name="config_cdma_dun_supported_types" />
+
+  <java-symbol type="drawable" name="default_wallpaper" />
+  <java-symbol type="drawable" name="indicator_input_error" />
+  <java-symbol type="drawable" name="overscroll_edge" />
+  <java-symbol type="drawable" name="overscroll_glow" />
+  <java-symbol type="drawable" name="popup_bottom_dark" />
+  <java-symbol type="drawable" name="popup_bottom_bright" />
+  <java-symbol type="drawable" name="popup_bottom_medium" />
+  <java-symbol type="drawable" name="popup_center_dark" />
+  <java-symbol type="drawable" name="popup_center_bright" />
+  <java-symbol type="drawable" name="popup_full_dark" />
+  <java-symbol type="drawable" name="popup_full_bright" />
+  <java-symbol type="drawable" name="popup_top_dark" />
+  <java-symbol type="drawable" name="popup_top_bright" />
+  <java-symbol type="drawable" name="search_spinner" />
+  <java-symbol type="drawable" name="sym_app_on_sd_unavailable_icon" />
+  <java-symbol type="drawable" name="text_edit_side_paste_window" />
+  <java-symbol type="drawable" name="text_edit_paste_window" />
+  <java-symbol type="drawable" name="btn_check_off" />
+  <java-symbol type="drawable" name="btn_code_lock_default_holo" />
+  <java-symbol type="drawable" name="btn_code_lock_touched_holo" />
+  <java-symbol type="drawable" name="clock_dial" />
+  <java-symbol type="drawable" name="clock_hand_hour" />
+  <java-symbol type="drawable" name="clock_hand_minute" />
+  <java-symbol type="drawable" name="emo_im_angel" />
+  <java-symbol type="drawable" name="emo_im_cool" />
+  <java-symbol type="drawable" name="emo_im_crying" />
+  <java-symbol type="drawable" name="emo_im_embarrassed" />
+  <java-symbol type="drawable" name="emo_im_foot_in_mouth" />
+  <java-symbol type="drawable" name="emo_im_happy" />
+  <java-symbol type="drawable" name="emo_im_kissing" />
+  <java-symbol type="drawable" name="emo_im_laughing" />
+  <java-symbol type="drawable" name="emo_im_lips_are_sealed" />
+  <java-symbol type="drawable" name="emo_im_money_mouth" />
+  <java-symbol type="drawable" name="emo_im_sad" />
+  <java-symbol type="drawable" name="emo_im_surprised" />
+  <java-symbol type="drawable" name="emo_im_tongue_sticking_out" />
+  <java-symbol type="drawable" name="emo_im_undecided" />
+  <java-symbol type="drawable" name="emo_im_winking" />
+  <java-symbol type="drawable" name="emo_im_wtf" />
+  <java-symbol type="drawable" name="emo_im_yelling" />
+  <java-symbol type="drawable" name="expander_close_holo_dark" />
+  <java-symbol type="drawable" name="expander_open_holo_dark" />
+  <java-symbol type="drawable" name="ic_audio_alarm" />
+  <java-symbol type="drawable" name="ic_audio_alarm_mute" />
+  <java-symbol type="drawable" name="ic_audio_bt" />
+  <java-symbol type="drawable" name="ic_audio_bt_mute" />
+  <java-symbol type="drawable" name="ic_audio_notification" />
+  <java-symbol type="drawable" name="ic_audio_notification_mute" />
+  <java-symbol type="drawable" name="ic_audio_phone" />
+  <java-symbol type="drawable" name="ic_audio_ring_notif" />
+  <java-symbol type="drawable" name="ic_audio_ring_notif_mute" />
+  <java-symbol type="drawable" name="ic_audio_ring_notif_vibrate" />
+  <java-symbol type="drawable" name="ic_audio_vol" />
+  <java-symbol type="drawable" name="ic_audio_vol_mute" />
+  <java-symbol type="drawable" name="ic_bullet_key_permission" />
+  <java-symbol type="drawable" name="ic_contact_picture" />
+  <java-symbol type="drawable" name="ic_dialog_usb" />
+  <java-symbol type="drawable" name="ic_emergency" />
+  <java-symbol type="drawable" name="ic_media_stop" />
+  <java-symbol type="drawable" name="ic_text_dot" />
+  <java-symbol type="drawable" name="indicator_code_lock_drag_direction_green_up" />
+  <java-symbol type="drawable" name="indicator_code_lock_drag_direction_red_up" />
+  <java-symbol type="drawable" name="indicator_code_lock_point_area_default_holo" />
+  <java-symbol type="drawable" name="indicator_code_lock_point_area_green_holo" />
+  <java-symbol type="drawable" name="indicator_code_lock_point_area_red_holo" />
+  <java-symbol type="drawable" name="jog_dial_arrow_long_left_green" />
+  <java-symbol type="drawable" name="jog_dial_arrow_long_right_red" />
+  <java-symbol type="drawable" name="jog_dial_arrow_short_left_and_right" />
+  <java-symbol type="drawable" name="jog_dial_bg" />
+  <java-symbol type="drawable" name="jog_dial_dimple" />
+  <java-symbol type="drawable" name="jog_dial_dimple_dim" />
+  <java-symbol type="drawable" name="jog_tab_bar_left_generic" />
+  <java-symbol type="drawable" name="jog_tab_bar_right_generic" />
+  <java-symbol type="drawable" name="jog_tab_left_generic" />
+  <java-symbol type="drawable" name="jog_tab_right_generic" />
+  <java-symbol type="drawable" name="jog_tab_target_gray" />
+  <java-symbol type="drawable" name="picture_emergency" />
+  <java-symbol type="drawable" name="platlogo" />
+  <java-symbol type="drawable" name="platlogo_alt" />
+  <java-symbol type="drawable" name="stat_notify_sync_error" />
+  <java-symbol type="drawable" name="stat_notify_wifi_in_range" />
+  <java-symbol type="drawable" name="stat_notify_rssi_in_range" />
+  <java-symbol type="drawable" name="stat_sys_gps_on" />
+  <java-symbol type="drawable" name="stat_sys_tether_wifi" />
+  <java-symbol type="drawable" name="status_bar_background" />
+  <java-symbol type="drawable" name="sym_keyboard_shift" />
+  <java-symbol type="drawable" name="sym_keyboard_shift_locked" />
+  <java-symbol type="drawable" name="sym_keyboard_return_holo" />
+  <java-symbol type="drawable" name="tab_bottom_left" />
+  <java-symbol type="drawable" name="tab_bottom_left_v4" />
+  <java-symbol type="drawable" name="tab_bottom_right" />
+  <java-symbol type="drawable" name="tab_bottom_right_v4" />
+  <java-symbol type="drawable" name="tab_indicator_v4" />
+  <java-symbol type="drawable" name="text_select_handle_left" />
+  <java-symbol type="drawable" name="text_select_handle_middle" />
+  <java-symbol type="drawable" name="text_select_handle_right" />
+  <java-symbol type="drawable" name="unknown_image" />
+  <java-symbol type="drawable" name="unlock_default" />
+  <java-symbol type="drawable" name="unlock_halo" />
+  <java-symbol type="drawable" name="unlock_ring" />
+  <java-symbol type="drawable" name="unlock_wave" />
+  <java-symbol type="drawable" name="ic_lockscreen_camera" />
+  <java-symbol type="drawable" name="ic_lockscreen_silent" />
+  <java-symbol type="drawable" name="ic_lockscreen_unlock" />
+  <java-symbol type="drawable" name="ic_action_assist_generic" />
+  <java-symbol type="drawable" name="ic_lockscreen_alarm" />
+  <java-symbol type="drawable" name="notification_bg" />
+  <java-symbol type="drawable" name="notification_bg_low" />
+  <java-symbol type="drawable" name="notification_template_icon_bg" />
+  <java-symbol type="drawable" name="notification_template_icon_low_bg" />
+  <java-symbol type="drawable" name="ic_lockscreen_unlock_phantom" />
+  <java-symbol type="drawable" name="ic_media_route_on_holo_dark" />
+  <java-symbol type="drawable" name="ic_media_route_disabled_holo_dark" />
+
+  <java-symbol type="layout" name="action_bar_home" />
+  <java-symbol type="layout" name="action_bar_title_item" />
+  <java-symbol type="layout" name="action_menu_item_layout" />
+  <java-symbol type="layout" name="action_menu_layout" />
+  <java-symbol type="layout" name="action_mode_close_item" />
+  <java-symbol type="layout" name="alert_dialog" />
+  <java-symbol type="layout" name="choose_account" />
+  <java-symbol type="layout" name="choose_account_row" />
+  <java-symbol type="layout" name="choose_account_type" />
+  <java-symbol type="layout" name="choose_type_and_account" />
+  <java-symbol type="layout" name="grant_credentials_permission" />
+  <java-symbol type="layout" name="number_picker" />
+  <java-symbol type="layout" name="permissions_package_list_item" />
+  <java-symbol type="layout" name="popup_menu_item_layout" />
+  <java-symbol type="layout" name="remote_views_adapter_default_loading_view" />
+  <java-symbol type="layout" name="search_bar" />
+  <java-symbol type="layout" name="search_dropdown_item_icons_2line" />
+  <java-symbol type="layout" name="search_view" />
+  <java-symbol type="layout" name="select_dialog" />
+  <java-symbol type="layout" name="simple_dropdown_hint" />
+  <java-symbol type="layout" name="status_bar_latest_event_content" />
+  <java-symbol type="layout" name="status_bar_latest_event_ticker" />
+  <java-symbol type="layout" name="status_bar_latest_event_ticker_large_icon" />
+  <java-symbol type="layout" name="text_edit_action_popup_text" />
+  <java-symbol type="layout" name="text_drag_thumbnail" />
+  <java-symbol type="layout" name="typing_filter" />
+  <java-symbol type="layout" name="activity_chooser_view" />
+  <java-symbol type="layout" name="activity_chooser_view_list_item" />
+  <java-symbol type="layout" name="activity_list" />
+  <java-symbol type="layout" name="activity_list_item_2" />
+  <java-symbol type="layout" name="alert_dialog_progress" />
+  <java-symbol type="layout" name="always_use_checkbox" />
+  <java-symbol type="layout" name="app_permission_item" />
+  <java-symbol type="layout" name="app_permission_item_money" />
+  <java-symbol type="layout" name="app_permission_item_old" />
+  <java-symbol type="layout" name="app_perms_summary" />
+  <java-symbol type="layout" name="calendar_view" />
+  <java-symbol type="layout" name="character_picker" />
+  <java-symbol type="layout" name="character_picker_button" />
+  <java-symbol type="layout" name="date_picker" />
+  <java-symbol type="layout" name="date_picker_dialog" />
+  <java-symbol type="layout" name="expanded_menu_layout" />
+  <java-symbol type="layout" name="fragment_bread_crumb_item" />
+  <java-symbol type="layout" name="fragment_bread_crumbs" />
+  <java-symbol type="layout" name="heavy_weight_switcher" />
+  <java-symbol type="layout" name="icon_menu_item_layout" />
+  <java-symbol type="layout" name="icon_menu_layout" />
+  <java-symbol type="layout" name="input_method" />
+  <java-symbol type="layout" name="input_method_extract_view" />
+  <java-symbol type="layout" name="input_method_switch_dialog_title" />
+  <java-symbol type="layout" name="js_prompt" />
+  <java-symbol type="layout" name="list_content_simple" />
+  <java-symbol type="layout" name="list_menu_item_checkbox" />
+  <java-symbol type="layout" name="list_menu_item_icon" />
+  <java-symbol type="layout" name="list_menu_item_layout" />
+  <java-symbol type="layout" name="list_menu_item_radio" />
+  <java-symbol type="layout" name="locale_picker_item" />
+  <java-symbol type="layout" name="media_controller" />
+  <java-symbol type="layout" name="overlay_display_window" />
+  <java-symbol type="layout" name="preference" />
+  <java-symbol type="layout" name="preference_header_item" />
+  <java-symbol type="layout" name="preference_list_content" />
+  <java-symbol type="layout" name="preference_list_content_single" />
+  <java-symbol type="layout" name="preference_list_fragment" />
+  <java-symbol type="layout" name="preference_widget_seekbar" />
+  <java-symbol type="layout" name="progress_dialog" />
+  <java-symbol type="layout" name="resolve_list_item" />
+  <java-symbol type="layout" name="seekbar_dialog" />
+  <java-symbol type="layout" name="select_dialog_singlechoice_holo" />
+  <java-symbol type="layout" name="ssl_certificate" />
+  <java-symbol type="layout" name="tab_content" />
+  <java-symbol type="layout" name="tab_indicator_holo" />
+  <java-symbol type="layout" name="textview_hint" />
+  <java-symbol type="layout" name="time_picker" />
+  <java-symbol type="layout" name="time_picker_dialog" />
+  <java-symbol type="layout" name="transient_notification" />
+  <java-symbol type="layout" name="volume_adjust" />
+  <java-symbol type="layout" name="volume_adjust_item" />
+  <java-symbol type="layout" name="web_text_view_dropdown" />
+  <java-symbol type="layout" name="webview_find" />
+  <java-symbol type="layout" name="webview_select_singlechoice" />
+  <java-symbol type="layout" name="wifi_p2p_dialog" />
+  <java-symbol type="layout" name="wifi_p2p_dialog_row" />
+  <java-symbol type="layout" name="zoom_container" />
+  <java-symbol type="layout" name="zoom_controls" />
+  <java-symbol type="layout" name="zoom_magnify" />
+  <java-symbol type="layout" name="notification_action" />
+  <java-symbol type="layout" name="notification_action_tombstone" />
+  <java-symbol type="layout" name="notification_intruder_content" />
+  <java-symbol type="layout" name="notification_template_base" />
+  <java-symbol type="layout" name="notification_template_big_base" />
+  <java-symbol type="layout" name="notification_template_big_picture" />
+  <java-symbol type="layout" name="notification_template_big_text" />
+  <java-symbol type="layout" name="notification_template_part_time" />
+  <java-symbol type="layout" name="notification_template_part_chronometer" />
+  <java-symbol type="layout" name="notification_template_inbox" />
+  <java-symbol type="layout" name="keyguard_multi_user_avatar" />
+  <java-symbol type="layout" name="keyguard_multi_user_selector_widget" />
+  <java-symbol type="layout" name="sms_short_code_confirmation_dialog" />
+  <java-symbol type="layout" name="keyguard_add_widget" />
+
+  <java-symbol type="anim" name="slide_in_child_bottom" />
+  <java-symbol type="anim" name="slide_in_right" />
+  <java-symbol type="anim" name="slide_out_left" />
+
+  <java-symbol type="menu" name="webview_copy" />
+  <java-symbol type="menu" name="webview_find" />
+
+  <java-symbol type="xml" name="password_kbd_qwerty" />
+  <java-symbol type="xml" name="autotext" />
+  <java-symbol type="xml" name="eri" />
+  <java-symbol type="xml" name="password_kbd_numeric" />
+  <java-symbol type="xml" name="password_kbd_qwerty_shifted" />
+  <java-symbol type="xml" name="password_kbd_symbols" />
+  <java-symbol type="xml" name="password_kbd_symbols_shift" />
+  <java-symbol type="xml" name="kg_password_kbd_numeric" />
+  <java-symbol type="xml" name="power_profile" />
+  <java-symbol type="xml" name="time_zones_by_country" />
+  <java-symbol type="xml" name="sms_short_codes" />
+
+  <java-symbol type="raw" name="accessibility_gestures" />
+  <java-symbol type="raw" name="incognito_mode_start_page" />
+  <java-symbol type="raw" name="loaderror" />
+  <java-symbol type="raw" name="nodomain" />
+
+  <java-symbol type="style" name="Animation.DropDownUp" />
+  <java-symbol type="style" name="Animation.DropDownDown" />
+  <java-symbol type="style" name="Animation.PopupWindow" />
+  <java-symbol type="style" name="Animation.TypingFilter" />
+  <java-symbol type="style" name="Animation.TypingFilterRestore" />
+  <java-symbol type="style" name="Animation.Dream" />
+  <java-symbol type="style" name="Theme.DeviceDefault.Dialog.Alert" />
+  <java-symbol type="style" name="Theme.DeviceDefault.Light.Dialog.Alert" />
+  <java-symbol type="style" name="Theme.Dialog.Alert" />
+  <java-symbol type="style" name="Theme.Holo.Dialog.Alert" />
+  <java-symbol type="style" name="Theme.Holo.Light.Dialog.Alert" />
+  <java-symbol type="style" name="ActiveWallpaperSettings" />
+  <java-symbol type="style" name="Animation.InputMethodFancy" />
+  <java-symbol type="style" name="Animation.Wallpaper" />
+  <java-symbol type="style" name="Animation.ZoomButtons" />
+  <java-symbol type="style" name="PreviewWallpaperSettings" />
+  <java-symbol type="style" name="TextAppearance.SlidingTabActive" />
+  <java-symbol type="style" name="TextAppearance.SlidingTabNormal" />
+  <java-symbol type="style" name="Theme.DeviceDefault.Dialog.NoFrame" />
+  <java-symbol type="style" name="Theme.IconMenu" />
+  <java-symbol type="style" name="Theme.Panel.Volume" />
+
+  <java-symbol type="attr" name="mediaRouteButtonStyle" />
+  <java-symbol type="attr" name="externalRouteEnabledDrawable" />
+  <java-symbol type="id" name="extended_settings" />
+  <java-symbol type="id" name="check" />
+  <java-symbol type="id" name="volume_slider" />
+  <java-symbol type="id" name="volume_icon" />
+  <java-symbol type="drawable" name="ic_media_route_on_holo_dark" />
+  <java-symbol type="layout" name="media_route_chooser_layout" />
+  <java-symbol type="layout" name="media_route_list_item_top_header" />
+  <java-symbol type="layout" name="media_route_list_item_section_header" />
+  <java-symbol type="layout" name="media_route_list_item" />
+  <java-symbol type="layout" name="media_route_list_item_checkable" />
+  <java-symbol type="layout" name="media_route_list_item_collapse_group" />
+  <java-symbol type="string" name="bluetooth_a2dp_audio_route_name" />
+
+  <java-symbol type="dimen" name="config_minScalingSpan" />
+  <java-symbol type="dimen" name="config_minScalingTouchMajor" />
+
+  <!-- From android.policy -->
+  <java-symbol type="anim" name="app_starting_exit" />
+  <java-symbol type="anim" name="lock_screen_behind_enter" />
+  <java-symbol type="anim" name="lock_screen_wallpaper_behind_enter" />
+  <java-symbol type="anim" name="dock_top_enter" />
+  <java-symbol type="anim" name="dock_top_exit" />
+  <java-symbol type="anim" name="dock_bottom_enter" />
+  <java-symbol type="anim" name="dock_bottom_exit" />
+  <java-symbol type="anim" name="dock_left_enter" />
+  <java-symbol type="anim" name="dock_left_exit" />
+  <java-symbol type="anim" name="dock_right_enter" />
+  <java-symbol type="anim" name="dock_right_exit" />
+  <java-symbol type="anim" name="keyguard_security_animate_in" />
+  <java-symbol type="anim" name="keyguard_security_animate_out" />
+  <java-symbol type="anim" name="keyguard_security_fade_in" />
+  <java-symbol type="anim" name="keyguard_security_fade_out" />
+  <java-symbol type="anim" name="keyguard_action_assist_exit" />
+  <java-symbol type="anim" name="keyguard_action_assist_enter" />
+
+  <java-symbol type="array" name="config_keyboardTapVibePattern" />
+  <java-symbol type="array" name="config_longPressVibePattern" />
+  <java-symbol type="array" name="config_safeModeDisabledVibePattern" />
+  <java-symbol type="array" name="config_safeModeEnabledVibePattern" />
+  <java-symbol type="array" name="config_virtualKeyVibePattern" />
+  <java-symbol type="array" name="lockscreen_targets_when_silent" />
+  <java-symbol type="array" name="lockscreen_targets_when_soundon" />
+  <java-symbol type="array" name="lockscreen_targets_with_camera" />
+  <java-symbol type="array" name="lockscreen_num_pad_klondike" />
+  <java-symbol type="attr" name="actionModePopupWindowStyle" />
+  <java-symbol type="attr" name="dialogCustomTitleDecorLayout" />
+  <java-symbol type="attr" name="dialogTitleDecorLayout" />
+  <java-symbol type="attr" name="dialogTitleIconsDecorLayout" />
+  <java-symbol type="bool" name="config_allowAllRotations" />
+  <java-symbol type="bool" name="config_annoy_dianne" />
+  <java-symbol type="bool" name="config_carDockEnablesAccelerometer" />
+  <java-symbol type="bool" name="config_deskDockEnablesAccelerometer" />
+  <java-symbol type="bool" name="config_disableMenuKeyInLockScreen" />
+  <java-symbol type="bool" name="config_enableLockBeforeUnlockScreen" />
+  <java-symbol type="bool" name="config_enableLockScreenRotation" />
+  <java-symbol type="bool" name="config_lidControlsSleep" />
+  <java-symbol type="bool" name="config_reverseDefaultRotation" />
+  <java-symbol type="bool" name="config_showNavigationBar" />
+  <java-symbol type="bool" name="kg_enable_camera_default_widget" />
+  <java-symbol type="bool" name="kg_share_status_area" />
+  <java-symbol type="bool" name="kg_sim_puk_account_full_screen" />
+  <java-symbol type="bool" name="kg_top_align_page_shrink_on_bouncer_visible" />
+  <java-symbol type="bool" name="target_honeycomb_needs_options_menu" />
+  <java-symbol type="bool" name="kg_center_small_widgets_vertically" />
+  <java-symbol type="bool" name="kg_show_ime_at_screen_on" />
+  <java-symbol type="color" name="kg_multi_user_text_active" />
+  <java-symbol type="color" name="kg_multi_user_text_inactive" />
+  <java-symbol type="color" name="kg_widget_pager_gradient" />
+  <java-symbol type="color" name="keyguard_avatar_frame_color" />
+  <java-symbol type="color" name="keyguard_avatar_frame_pressed_color" />
+  <java-symbol type="color" name="keyguard_avatar_frame_shadow_color" />
+  <java-symbol type="color" name="keyguard_avatar_nick_color" />
+  <java-symbol type="dimen" name="navigation_bar_height" />
+  <java-symbol type="dimen" name="navigation_bar_height_landscape" />
+  <java-symbol type="dimen" name="navigation_bar_width" />
+  <java-symbol type="dimen" name="status_bar_height" />
+  <java-symbol type="dimen" name="kg_widget_pager_horizontal_padding" />
+  <java-symbol type="dimen" name="kg_widget_pager_top_padding" />
+  <java-symbol type="dimen" name="kg_widget_pager_bottom_padding" />
+  <java-symbol type="dimen" name="keyguard_avatar_size" />
+  <java-symbol type="dimen" name="keyguard_avatar_frame_stroke_width" />
+  <java-symbol type="dimen" name="keyguard_avatar_frame_shadow_radius" />
+  <java-symbol type="dimen" name="kg_edge_swipe_region_size" />
+  <java-symbol type="dimen" name="kg_squashed_layout_threshold" />
+  <java-symbol type="dimen" name="kg_small_widget_height" />
+  <java-symbol type="drawable" name="ic_jog_dial_sound_off" />
+  <java-symbol type="drawable" name="ic_jog_dial_sound_on" />
+  <java-symbol type="drawable" name="ic_jog_dial_unlock" />
+  <java-symbol type="drawable" name="ic_jog_dial_vibrate_on" />
+  <java-symbol type="drawable" name="ic_lock_airplane_mode" />
+  <java-symbol type="drawable" name="ic_lock_airplane_mode_off" />
+  <java-symbol type="drawable" name="ic_menu_cc" />
+  <java-symbol type="drawable" name="jog_tab_bar_left_unlock" />
+  <java-symbol type="drawable" name="jog_tab_bar_right_sound_off" />
+  <java-symbol type="drawable" name="jog_tab_bar_right_sound_on" />
+  <java-symbol type="drawable" name="jog_tab_left_unlock" />
+  <java-symbol type="drawable" name="jog_tab_right_sound_off" />
+  <java-symbol type="drawable" name="jog_tab_right_sound_on" />
+  <java-symbol type="drawable" name="jog_tab_target_green" />
+  <java-symbol type="drawable" name="jog_tab_target_yellow" />
+  <java-symbol type="drawable" name="magnified_region_frame" />
+  <java-symbol type="drawable" name="menu_background" />
+  <java-symbol type="drawable" name="stat_sys_secure" />
+  <java-symbol type="drawable" name="kg_widget_bg_padded" />
+  <java-symbol type="id" name="action_mode_bar_stub" />
+  <java-symbol type="id" name="alarm_status" />
+  <java-symbol type="id" name="backspace" />
+  <java-symbol type="id" name="button0" />
+  <java-symbol type="id" name="button4" />
+  <java-symbol type="id" name="button5" />
+  <java-symbol type="id" name="button6" />
+  <java-symbol type="id" name="button7" />
+  <java-symbol type="id" name="carrier" />
+  <java-symbol type="id" name="date" />
+  <java-symbol type="id" name="eight" />
+  <java-symbol type="id" name="emergencyCallButton" />
+  <java-symbol type="id" name="face_unlock_area_view" />
+  <java-symbol type="id" name="face_unlock_cancel_button" />
+  <java-symbol type="id" name="five" />
+  <java-symbol type="id" name="forgotPatternButton" />
+  <java-symbol type="id" name="four" />
+  <java-symbol type="id" name="headerText" />
+  <java-symbol type="id" name="icon_menu_presenter" />
+  <java-symbol type="id" name="instructions" />
+  <java-symbol type="id" name="keyboard" />
+  <java-symbol type="id" name="list_menu_presenter" />
+  <java-symbol type="id" name="lockPattern" />
+  <java-symbol type="id" name="lock_screen" />
+  <java-symbol type="id" name="login" />
+  <java-symbol type="id" name="nine" />
+  <java-symbol type="id" name="no_applications_message" />
+  <java-symbol type="id" name="ok" />
+  <java-symbol type="id" name="one" />
+  <java-symbol type="id" name="option1" />
+  <java-symbol type="id" name="option2" />
+  <java-symbol type="id" name="option3" />
+  <java-symbol type="id" name="password" />
+  <java-symbol type="id" name="passwordEntry" />
+  <java-symbol type="id" name="pinEntry" />
+  <java-symbol type="id" name="pinDel" />
+  <java-symbol type="id" name="pinDisplay" />
+  <java-symbol type="id" name="owner_info" />
+  <java-symbol type="id" name="pukDel" />
+  <java-symbol type="id" name="pukDisplay" />
+  <java-symbol type="id" name="right_icon" />
+  <java-symbol type="id" name="seven" />
+  <java-symbol type="id" name="six" />
+  <java-symbol type="id" name="status" />
+  <java-symbol type="id" name="status1" />
+  <java-symbol type="id" name="switch_ime_button" />
+  <java-symbol type="id" name="three" />
+  <java-symbol type="id" name="title_container" />
+  <java-symbol type="id" name="topHeader" />
+  <java-symbol type="id" name="transport" />
+  <java-symbol type="id" name="transport_bg_protect" />
+  <java-symbol type="id" name="two" />
+  <java-symbol type="id" name="unlock_widget" />
+  <java-symbol type="id" name="zero" />
+  <java-symbol type="id" name="keyguard_message_area" />
+  <java-symbol type="id" name="keyguard_click_area" />
+  <java-symbol type="id" name="keyguard_selector_view" />
+  <java-symbol type="id" name="keyguard_pattern_view" />
+  <java-symbol type="id" name="keyguard_password_view" />
+  <java-symbol type="id" name="keyguard_pin_view" />
+  <java-symbol type="id" name="keyguard_face_unlock_view" />
+  <java-symbol type="id" name="keyguard_sim_pin_view" />
+  <java-symbol type="id" name="keyguard_sim_puk_view" />
+  <java-symbol type="id" name="keyguard_account_view" />
+  <java-symbol type="id" name="keyguard_selector_fade_container" />
+  <java-symbol type="id" name="keyguard_widget_pager_delete_target" />
+  <java-symbol type="id" name="keyguard_bouncer_frame" />
+  <java-symbol type="id" name="app_widget_container" />
+  <java-symbol type="id" name="view_flipper" />
+  <java-symbol type="id" name="emergency_call_button" />
+  <java-symbol type="id" name="keyguard_host_view" />
+  <java-symbol type="id" name="delete_button" />
+  <java-symbol type="id" name="lockPatternView" />
+  <java-symbol type="id" name="forgot_password_button" />
+  <java-symbol type="id" name="glow_pad_view" />
+  <java-symbol type="id" name="delete_button" />
+  <java-symbol type="id" name="keyguard_user_avatar" />
+  <java-symbol type="id" name="keyguard_user_name" />
+  <java-symbol type="id" name="keyguard_transport_control" />
+  <java-symbol type="id" name="keyguard_status_view" />
+  <java-symbol type="id" name="keyguard_status_view_face_palm" />
+  <java-symbol type="id" name="keyguard_users_grid" />
+  <java-symbol type="id" name="clock_text" />
+  <java-symbol type="id" name="clock_view" />
+  <java-symbol type="id" name="keyguard_multi_user_selector" />
+  <java-symbol type="id" name="sliding_layout" />
+  <java-symbol type="id" name="keyguard_add_widget" />
+  <java-symbol type="id" name="keyguard_add_widget_view" />
+  <java-symbol type="id" name="sliding_layout" />
+  <java-symbol type="id" name="multi_pane_challenge" />
+  <java-symbol type="id" name="keyguard_user_selector" />
+  <java-symbol type="id" name="key_enter" />
+  <java-symbol type="id" name="keyguard_selector_view_frame" />
+  <java-symbol type="integer" name="config_carDockRotation" />
+  <java-symbol type="integer" name="config_defaultUiModeType" />
+  <java-symbol type="integer" name="config_deskDockRotation" />
+  <java-symbol type="integer" name="config_lidKeyboardAccessibility" />
+  <java-symbol type="integer" name="config_lidNavigationAccessibility" />
+  <java-symbol type="integer" name="config_lidOpenRotation" />
+  <java-symbol type="integer" name="config_longPressOnHomeBehavior" />
+  <java-symbol type="integer" name="kg_security_flip_duration" />
+  <java-symbol type="integer" name="kg_carousel_angle" />
+  <java-symbol type="layout" name="global_actions_item" />
+  <java-symbol type="layout" name="global_actions_silent_mode" />
+  <java-symbol type="layout" name="keyguard_screen_glogin_unlock" />
+  <java-symbol type="layout" name="keyguard_screen_password_landscape" />
+  <java-symbol type="layout" name="keyguard_screen_password_portrait" />
+  <java-symbol type="layout" name="keyguard_screen_sim_pin_landscape" />
+  <java-symbol type="layout" name="keyguard_screen_sim_pin_portrait" />
+  <java-symbol type="layout" name="keyguard_screen_sim_puk_landscape" />
+  <java-symbol type="layout" name="keyguard_screen_sim_puk_portrait" />
+  <java-symbol type="layout" name="keyguard_screen_tab_unlock" />
+  <java-symbol type="layout" name="keyguard_screen_tab_unlock_land" />
+  <java-symbol type="layout" name="keyguard_screen_unlock_landscape" />
+  <java-symbol type="layout" name="keyguard_screen_unlock_portrait" />
+  <java-symbol type="layout" name="keyguard_selector_view" />
+  <java-symbol type="layout" name="keyguard_pattern_view" />
+  <java-symbol type="layout" name="keyguard_password_view" />
+  <java-symbol type="layout" name="keyguard_pin_view" />
+  <java-symbol type="layout" name="keyguard_face_unlock_view" />
+  <java-symbol type="layout" name="keyguard_sim_pin_view" />
+  <java-symbol type="layout" name="keyguard_sim_puk_view" />
+  <java-symbol type="layout" name="keyguard_account_view" />
+  <java-symbol type="layout" name="recent_apps_dialog" />
+  <java-symbol type="layout" name="screen_action_bar" />
+  <java-symbol type="layout" name="screen_action_bar_overlay" />
+  <java-symbol type="layout" name="screen_custom_title" />
+  <java-symbol type="layout" name="screen_progress" />
+  <java-symbol type="layout" name="screen_simple" />
+  <java-symbol type="layout" name="screen_simple_overlay_action_mode" />
+  <java-symbol type="layout" name="screen_title" />
+  <java-symbol type="layout" name="screen_title_icons" />
+  <java-symbol type="layout" name="keyguard_host_view" />
+  <java-symbol type="layout" name="keyguard_transport_control_view" />
+  <java-symbol type="layout" name="keyguard_status_view" />
+  <java-symbol type="string" name="abbrev_wday_month_day_no_year" />
+  <java-symbol type="string" name="android_upgrading_title" />
+  <java-symbol type="string" name="bugreport_title" />
+  <java-symbol type="string" name="bugreport_message" />
+  <java-symbol type="string" name="faceunlock_multiple_failures" />
+  <java-symbol type="string" name="global_action_power_off" />
+  <java-symbol type="string" name="global_actions_airplane_mode_off_status" />
+  <java-symbol type="string" name="global_actions_airplane_mode_on_status" />
+  <java-symbol type="string" name="global_actions_toggle_airplane_mode" />
+  <java-symbol type="string" name="global_action_bug_report" />
+  <java-symbol type="string" name="global_action_silent_mode_off_status" />
+  <java-symbol type="string" name="global_action_silent_mode_on_status" />
+  <java-symbol type="string" name="global_action_toggle_silent_mode" />
+  <java-symbol type="string" name="invalidPuk" />
+  <java-symbol type="string" name="keyguard_password_enter_pin_code" />
+  <java-symbol type="string" name="keyguard_password_enter_puk_code" />
+  <java-symbol type="string" name="keyguard_password_wrong_pin_code" />
+  <java-symbol type="string" name="lockscreen_carrier_default" />
+  <java-symbol type="string" name="lockscreen_charged" />
+  <java-symbol type="string" name="lockscreen_failed_attempts_almost_at_wipe" />
+  <java-symbol type="string" name="lockscreen_failed_attempts_almost_glogin" />
+  <java-symbol type="string" name="lockscreen_failed_attempts_now_wiping" />
+  <java-symbol type="string" name="lockscreen_forgot_pattern_button_text" />
+  <java-symbol type="string" name="lockscreen_glogin_checking_password" />
+  <java-symbol type="string" name="lockscreen_glogin_forgot_pattern" />
+  <java-symbol type="string" name="lockscreen_glogin_invalid_input" />
+  <java-symbol type="string" name="lockscreen_glogin_too_many_attempts" />
+  <java-symbol type="string" name="lockscreen_instructions_when_pattern_disabled" />
+  <java-symbol type="string" name="lockscreen_low_battery" />
+  <java-symbol type="string" name="lockscreen_missing_sim_instructions" />
+  <java-symbol type="string" name="lockscreen_missing_sim_instructions_long" />
+  <java-symbol type="string" name="lockscreen_missing_sim_message_short" />
+  <java-symbol type="string" name="lockscreen_network_locked_message" />
+  <java-symbol type="string" name="lockscreen_password_wrong" />
+  <java-symbol type="string" name="lockscreen_pattern_instructions" />
+  <java-symbol type="string" name="lockscreen_pattern_wrong" />
+  <java-symbol type="string" name="lockscreen_permanent_disabled_sim_message_short" />
+  <java-symbol type="string" name="lockscreen_permanent_disabled_sim_instructions" />
+  <java-symbol type="string" name="lockscreen_plugged_in" />
+  <java-symbol type="string" name="lockscreen_sim_locked_message" />
+  <java-symbol type="string" name="lockscreen_sim_puk_locked_message" />
+  <java-symbol type="string" name="lockscreen_sim_unlock_progress_dialog_message" />
+  <java-symbol type="string" name="lockscreen_sound_off_label" />
+  <java-symbol type="string" name="lockscreen_sound_on_label" />
+  <java-symbol type="string" name="lockscreen_too_many_failed_attempts_countdown" />
+  <java-symbol type="string" name="lockscreen_too_many_failed_attempts_dialog_message" />
+  <java-symbol type="string" name="lockscreen_too_many_failed_password_attempts_dialog_message" />
+  <java-symbol type="string" name="lockscreen_too_many_failed_pin_attempts_dialog_message" />
+  <java-symbol type="string" name="lockscreen_unlock_label" />
+  <java-symbol type="string" name="status_bar_device_locked" />
+  <java-symbol type="style" name="Animation.LockScreen" />
+  <java-symbol type="style" name="Theme.Dialog.RecentApplications" />
+  <java-symbol type="style" name="Theme.ExpandedMenu" />
+  <java-symbol type="style" name="Widget.Button.NumPadKey" />
+  <java-symbol type="style" name="TextAppearance.NumPadKey" />
+  <java-symbol type="style" name="TextAppearance.NumPadKey.Klondike" />
+  <java-symbol type="string" name="kg_emergency_call_label" />
+  <java-symbol type="string" name="kg_forgot_pattern_button_text" />
+  <java-symbol type="string" name="kg_wrong_pattern" />
+  <java-symbol type="string" name="kg_wrong_password" />
+  <java-symbol type="string" name="kg_wrong_pin" />
+  <java-symbol type="string" name="kg_too_many_failed_attempts_countdown" />
+  <java-symbol type="string" name="kg_pattern_instructions" />
+  <java-symbol type="string" name="kg_sim_pin_instructions" />
+  <java-symbol type="string" name="kg_pin_instructions" />
+  <java-symbol type="string" name="kg_password_instructions" />
+  <java-symbol type="string" name="kg_puk_enter_puk_hint" />
+  <java-symbol type="string" name="kg_puk_enter_pin_hint" />
+  <java-symbol type="string" name="kg_sim_unlock_progress_dialog_message" />
+  <java-symbol type="string" name="kg_password_wrong_pin_code" />
+  <java-symbol type="string" name="kg_invalid_sim_pin_hint" />
+  <java-symbol type="string" name="kg_invalid_sim_puk_hint" />
+  <java-symbol type="string" name="kg_invalid_puk" />
+  <java-symbol type="string" name="kg_login_too_many_attempts" />
+  <java-symbol type="string" name="kg_login_instructions" />
+  <java-symbol type="string" name="kg_login_username_hint" />
+  <java-symbol type="string" name="kg_login_password_hint" />
+  <java-symbol type="string" name="kg_login_submit_button" />
+  <java-symbol type="string" name="kg_login_invalid_input" />
+  <java-symbol type="string" name="kg_login_account_recovery_hint" />
+  <java-symbol type="string" name="kg_login_checking_password" />
+  <java-symbol type="string" name="kg_too_many_failed_pin_attempts_dialog_message" />
+  <java-symbol type="string" name="kg_too_many_failed_pattern_attempts_dialog_message" />
+  <java-symbol type="string" name="kg_too_many_failed_password_attempts_dialog_message" />
+  <java-symbol type="string" name="kg_failed_attempts_almost_at_wipe" />
+  <java-symbol type="string" name="kg_failed_attempts_now_wiping" />
+  <java-symbol type="string" name="kg_failed_attempts_almost_at_login" />
+  <java-symbol type="string" name="kg_enter_confirm_pin_hint" />
+  <java-symbol type="string" name="kg_invalid_confirm_pin_hint" />
+  <java-symbol type="string" name="kg_text_message_separator" />
+
+  <!-- From services -->
+  <java-symbol type="anim" name="screen_rotate_0_enter" />
+  <java-symbol type="anim" name="screen_rotate_0_exit" />
+  <java-symbol type="anim" name="screen_rotate_0_frame" />
+  <java-symbol type="anim" name="screen_rotate_180_enter" />
+  <java-symbol type="anim" name="screen_rotate_180_exit" />
+  <java-symbol type="anim" name="screen_rotate_180_frame" />
+  <java-symbol type="anim" name="screen_rotate_finish_enter" />
+  <java-symbol type="anim" name="screen_rotate_finish_exit" />
+  <java-symbol type="anim" name="screen_rotate_finish_frame" />
+  <java-symbol type="anim" name="screen_rotate_minus_90_enter" />
+  <java-symbol type="anim" name="screen_rotate_minus_90_exit" />
+  <java-symbol type="anim" name="screen_rotate_minus_90_frame" />
+  <java-symbol type="anim" name="screen_rotate_plus_90_enter" />
+  <java-symbol type="anim" name="screen_rotate_plus_90_exit" />
+  <java-symbol type="anim" name="screen_rotate_plus_90_frame" />
+  <java-symbol type="anim" name="screen_rotate_start_enter" />
+  <java-symbol type="anim" name="screen_rotate_start_exit" />
+  <java-symbol type="anim" name="screen_rotate_start_frame" />
+  <java-symbol type="anim" name="screen_user_exit" />
+  <java-symbol type="anim" name="screen_user_enter" />
+  <java-symbol type="anim" name="window_move_from_decor" />
+  <java-symbol type="array" name="config_autoBrightnessButtonBacklightValues" />
+  <java-symbol type="array" name="config_autoBrightnessKeyboardBacklightValues" />
+  <java-symbol type="array" name="config_autoBrightnessLcdBacklightValues" />
+  <java-symbol type="array" name="config_autoBrightnessLevels" />
+  <java-symbol type="array" name="config_protectedNetworks" />
+  <java-symbol type="array" name="config_statusBarIcons" />
+  <java-symbol type="array" name="config_tether_bluetooth_regexs" />
+  <java-symbol type="array" name="config_tether_dhcp_range" />
+  <java-symbol type="array" name="config_tether_upstream_types" />
+  <java-symbol type="array" name="config_tether_usb_regexs" />
+  <java-symbol type="array" name="config_tether_wifi_regexs" />
+  <java-symbol type="array" name="config_usbHostBlacklist" />
+  <java-symbol type="array" name="config_serialPorts" />
+  <java-symbol type="array" name="radioAttributes" />
+  <java-symbol type="array" name="config_oemUsbModeOverride" />
+  <java-symbol type="array" name="config_locationProviderPackageNames" />
+  <java-symbol type="bool" name="config_animateScreenLights" />
+  <java-symbol type="bool" name="config_automatic_brightness_available" />
+  <java-symbol type="bool" name="config_sf_limitedAlpha" />
+  <java-symbol type="bool" name="config_unplugTurnsOnScreen" />
+  <java-symbol type="bool" name="config_wifi_background_scan_support" />
+  <java-symbol type="bool" name="config_wifi_dual_band_support" />
+  <java-symbol type="bool" name="config_wimaxEnabled" />
+  <java-symbol type="bool" name="show_ongoing_ime_switcher" />
+  <java-symbol type="color" name="config_defaultNotificationColor" />
+  <java-symbol type="drawable" name="ic_notification_ime_default" />
+  <java-symbol type="drawable" name="ic_notify_wifidisplay" />
+  <java-symbol type="drawable" name="stat_notify_car_mode" />
+  <java-symbol type="drawable" name="stat_notify_disabled" />
+  <java-symbol type="drawable" name="stat_notify_disk_full" />
+  <java-symbol type="drawable" name="stat_sys_adb" />
+  <java-symbol type="drawable" name="stat_sys_battery" />
+  <java-symbol type="drawable" name="stat_sys_battery_charge" />
+  <java-symbol type="drawable" name="stat_sys_battery_unknown" />
+  <java-symbol type="drawable" name="stat_sys_data_usb" />
+  <java-symbol type="drawable" name="stat_sys_tether_bluetooth" />
+  <java-symbol type="drawable" name="stat_sys_tether_general" />
+  <java-symbol type="drawable" name="stat_sys_tether_usb" />
+  <java-symbol type="drawable" name="stat_sys_throttled" />
+  <java-symbol type="drawable" name="vpn_connected" />
+  <java-symbol type="drawable" name="vpn_disconnected" />
+  <java-symbol type="id" name="ask_checkbox" />
+  <java-symbol type="id" name="compat_checkbox" />
+  <java-symbol type="id" name="original_app_icon" />
+  <java-symbol type="id" name="original_message" />
+  <java-symbol type="id" name="radio" />
+  <java-symbol type="id" name="reask_hint" />
+  <java-symbol type="id" name="replace_app_icon" />
+  <java-symbol type="id" name="replace_message" />
+  <java-symbol type="fraction" name="config_dimBehindFadeDuration" />
+  <java-symbol type="integer" name="config_carDockKeepsScreenOn" />
+  <java-symbol type="integer" name="config_criticalBatteryWarningLevel" />
+  <java-symbol type="integer" name="config_datause_notification_type" />
+  <java-symbol type="integer" name="config_datause_polling_period_sec" />
+  <java-symbol type="integer" name="config_datause_threshold_bytes" />
+  <java-symbol type="integer" name="config_datause_throttle_kbitsps" />
+  <java-symbol type="integer" name="config_defaultNotificationLedOff" />
+  <java-symbol type="integer" name="config_defaultNotificationLedOn" />
+  <java-symbol type="integer" name="config_deskDockKeepsScreenOn" />
+  <java-symbol type="integer" name="config_lightSensorWarmupTime" />
+  <java-symbol type="integer" name="config_lowBatteryCloseWarningLevel" />
+  <java-symbol type="integer" name="config_lowBatteryWarningLevel" />
+  <java-symbol type="integer" name="config_networkPolicyDefaultWarning" />
+  <java-symbol type="integer" name="config_networkTransitionTimeout" />
+  <java-symbol type="integer" name="config_notificationsBatteryFullARGB" />
+  <java-symbol type="integer" name="config_notificationsBatteryLedOff" />
+  <java-symbol type="integer" name="config_notificationsBatteryLedOn" />
+  <java-symbol type="integer" name="config_notificationsBatteryLowARGB" />
+  <java-symbol type="integer" name="config_notificationsBatteryMediumARGB" />
+  <java-symbol type="integer" name="config_radioScanningTimeout" />
+  <java-symbol type="integer" name="config_screenBrightnessSettingMinimum" />
+  <java-symbol type="integer" name="config_screenBrightnessSettingMaximum" />
+  <java-symbol type="integer" name="config_screenBrightnessSettingDefault" />
+  <java-symbol type="integer" name="config_screenBrightnessDim" />
+  <java-symbol type="integer" name="config_shutdownBatteryTemperature" />
+  <java-symbol type="integer" name="config_virtualKeyQuietTimeMillis" />
+  <java-symbol type="layout" name="am_compat_mode_dialog" />
+  <java-symbol type="layout" name="launch_warning" />
+  <java-symbol type="layout" name="safe_mode" />
+  <java-symbol type="layout" name="simple_list_item_2_single_choice" />
+  <java-symbol type="plurals" name="wifi_available" />
+  <java-symbol type="plurals" name="wifi_available_detailed" />
+  <java-symbol type="string" name="accessibility_binding_label" />
+  <java-symbol type="string" name="adb_active_notification_message" />
+  <java-symbol type="string" name="adb_active_notification_title" />
+  <java-symbol type="string" name="aerr_application" />
+  <java-symbol type="string" name="aerr_process" />
+  <java-symbol type="string" name="aerr_title" />
+  <java-symbol type="string" name="android_upgrading_apk" />
+  <java-symbol type="string" name="android_upgrading_complete" />
+  <java-symbol type="string" name="android_upgrading_starting_apps" />
+  <java-symbol type="string" name="anr_activity_application" />
+  <java-symbol type="string" name="anr_activity_process" />
+  <java-symbol type="string" name="anr_application_process" />
+  <java-symbol type="string" name="anr_process" />
+  <java-symbol type="string" name="anr_title" />
+  <java-symbol type="string" name="car_mode_disable_notification_message" />
+  <java-symbol type="string" name="car_mode_disable_notification_title" />
+  <java-symbol type="string" name="chooser_wallpaper" />
+  <java-symbol type="string" name="config_datause_iface" />
+  <java-symbol type="string" name="config_wimaxManagerClassname" />
+  <java-symbol type="string" name="config_wimaxNativeLibLocation" />
+  <java-symbol type="string" name="config_wimaxServiceClassname" />
+  <java-symbol type="string" name="config_wimaxServiceJarLocation" />
+  <java-symbol type="string" name="config_wimaxStateTrackerClassname" />
+  <java-symbol type="string" name="configure_input_methods" />
+  <java-symbol type="string" name="data_usage_3g_limit_snoozed_title" />
+  <java-symbol type="string" name="data_usage_3g_limit_title" />
+  <java-symbol type="string" name="data_usage_4g_limit_snoozed_title" />
+  <java-symbol type="string" name="data_usage_4g_limit_title" />
+  <java-symbol type="string" name="data_usage_limit_body" />
+  <java-symbol type="string" name="data_usage_limit_snoozed_body" />
+  <java-symbol type="string" name="data_usage_mobile_limit_snoozed_title" />
+  <java-symbol type="string" name="data_usage_mobile_limit_title" />
+  <java-symbol type="string" name="data_usage_restricted_body" />
+  <java-symbol type="string" name="data_usage_restricted_title" />
+  <java-symbol type="string" name="data_usage_warning_body" />
+  <java-symbol type="string" name="data_usage_warning_title" />
+  <java-symbol type="string" name="data_usage_wifi_limit_snoozed_title" />
+  <java-symbol type="string" name="data_usage_wifi_limit_title" />
+  <java-symbol type="string" name="default_wallpaper_component" />
+  <java-symbol type="string" name="dlg_ok" />
+  <java-symbol type="string" name="factorytest_failed" />
+  <java-symbol type="string" name="factorytest_no_action" />
+  <java-symbol type="string" name="factorytest_not_system" />
+  <java-symbol type="string" name="factorytest_reboot" />
+  <java-symbol type="string" name="hardware" />
+  <java-symbol type="string" name="heavy_weight_notification" />
+  <java-symbol type="string" name="heavy_weight_notification_detail" />
+  <java-symbol type="string" name="input_method_binding_label" />
+  <java-symbol type="string" name="launch_warning_original" />
+  <java-symbol type="string" name="launch_warning_replace" />
+  <java-symbol type="string" name="launch_warning_title" />
+  <java-symbol type="string" name="low_internal_storage_view_text" />
+  <java-symbol type="string" name="low_internal_storage_view_title" />
+  <java-symbol type="string" name="report" />
+  <java-symbol type="string" name="select_input_method" />
+  <java-symbol type="string" name="select_keyboard_layout_notification_title" />
+  <java-symbol type="string" name="select_keyboard_layout_notification_message" />
+  <java-symbol type="string" name="smv_application" />
+  <java-symbol type="string" name="smv_process" />
+  <java-symbol type="string" name="tethered_notification_message" />
+  <java-symbol type="string" name="tethered_notification_title" />
+  <java-symbol type="string" name="throttle_warning_notification_message" />
+  <java-symbol type="string" name="throttle_warning_notification_title" />
+  <java-symbol type="string" name="throttled_notification_message" />
+  <java-symbol type="string" name="throttled_notification_title" />
+  <java-symbol type="string" name="usb_accessory_notification_title" />
+  <java-symbol type="string" name="usb_cd_installer_notification_title" />
+  <java-symbol type="string" name="usb_mtp_notification_title" />
+  <java-symbol type="string" name="usb_notification_message" />
+  <java-symbol type="string" name="use_physical_keyboard" />
+  <java-symbol type="string" name="usb_ptp_notification_title" />
+  <java-symbol type="string" name="vpn_text" />
+  <java-symbol type="string" name="vpn_text_long" />
+  <java-symbol type="string" name="vpn_title" />
+  <java-symbol type="string" name="vpn_title_long" />
+  <java-symbol type="string" name="vpn_lockdown_connecting" />
+  <java-symbol type="string" name="vpn_lockdown_connected" />
+  <java-symbol type="string" name="vpn_lockdown_error" />
+  <java-symbol type="string" name="vpn_lockdown_reset" />
+  <java-symbol type="string" name="wallpaper_binding_label" />
+  <java-symbol type="string" name="wifi_display_notification_title" />
+  <java-symbol type="string" name="wifi_display_notification_message" />
+  <java-symbol type="string" name="wifi_display_notification_disconnect" />
+  <java-symbol type="style" name="Theme.Dialog.AppError" />
+  <java-symbol type="style" name="Theme.Toast" />
+  <java-symbol type="xml" name="storage_list" />
+  <java-symbol type="bool" name="config_dreamsSupported" />
+  <java-symbol type="bool" name="config_dreamsEnabledByDefault" />
+  <java-symbol type="bool" name="config_dreamsActivatedOnDockByDefault" />
+  <java-symbol type="bool" name="config_dreamsActivatedOnSleepByDefault" />
+  <java-symbol type="string" name="config_dreamsDefaultComponent" />
+  <java-symbol type="string" name="enable_explore_by_touch_warning_title" />
+  <java-symbol type="string" name="enable_explore_by_touch_warning_message" />
+
+  <java-symbol type="layout" name="resolver_grid" />
+  <java-symbol type="id" name="resolver_grid" />
+  <java-symbol type="id" name="button_once" />
+  <java-symbol type="id" name="button_always" />
+  <java-symbol type="integer" name="config_maxResolverActivityColumns" />
+
+  <!-- From SystemUI -->
+  <java-symbol type="anim" name="push_down_in" />
+  <java-symbol type="anim" name="push_down_out" />
+  <java-symbol type="anim" name="push_up_in" />
+  <java-symbol type="anim" name="push_up_out" />
+  <java-symbol type="bool" name="config_alwaysUseCdmaRssi" />
+  <java-symbol type="dimen" name="status_bar_icon_size" />
+  <java-symbol type="dimen" name="system_bar_icon_size" />
+  <java-symbol type="drawable" name="list_selector_pressed_holo_dark" />
+  <java-symbol type="drawable" name="scrubber_control_disabled_holo" />
+  <java-symbol type="drawable" name="scrubber_control_selector_holo" />
+  <java-symbol type="drawable" name="scrubber_progress_horizontal_holo_dark" />
+  <java-symbol type="drawable" name="usb_android" />
+  <java-symbol type="drawable" name="usb_android_connected" />
+  <java-symbol type="id" name="banner" />
+  <java-symbol type="id" name="mount_button" />
+  <java-symbol type="id" name="unmount_button" />
+  <java-symbol type="layout" name="usb_storage_activity" />
+  <java-symbol type="string" name="chooseUsbActivity" />
+  <java-symbol type="string" name="dlg_confirm_kill_storage_users_text" />
+  <java-symbol type="string" name="dlg_confirm_kill_storage_users_title" />
+  <java-symbol type="string" name="dlg_error_title" />
+  <java-symbol type="string" name="ext_media_badremoval_notification_message" />
+  <java-symbol type="string" name="ext_media_badremoval_notification_title" />
+  <java-symbol type="string" name="ext_media_checking_notification_message" />
+  <java-symbol type="string" name="ext_media_checking_notification_title" />
+  <java-symbol type="string" name="ext_media_nofs_notification_message" />
+  <java-symbol type="string" name="ext_media_nofs_notification_title" />
+  <java-symbol type="string" name="ext_media_nomedia_notification_message" />
+  <java-symbol type="string" name="ext_media_nomedia_notification_title" />
+  <java-symbol type="string" name="ext_media_safe_unmount_notification_message" />
+  <java-symbol type="string" name="ext_media_safe_unmount_notification_title" />
+  <java-symbol type="string" name="ext_media_unmountable_notification_message" />
+  <java-symbol type="string" name="ext_media_unmountable_notification_title" />
+  <java-symbol type="string" name="usb_storage_error_message" />
+  <java-symbol type="string" name="usb_storage_message" />
+  <java-symbol type="string" name="usb_storage_notification_message" />
+  <java-symbol type="string" name="usb_storage_notification_title" />
+  <java-symbol type="string" name="usb_storage_stop_message" />
+  <java-symbol type="string" name="usb_storage_stop_notification_message" />
+  <java-symbol type="string" name="usb_storage_stop_notification_title" />
+  <java-symbol type="string" name="usb_storage_stop_title" />
+  <java-symbol type="string" name="usb_storage_title" />
+  <java-symbol type="style" name="Animation.RecentApplications" />
+
+  <!-- ImfTest -->
+  <java-symbol type="layout" name="auto_complete_list" />
+
+  <!-- From SettingsProvider -->
+  <java-symbol type="raw" name="fallbackring" />
+
+  <!-- From Settings -->
+  <java-symbol type="array" name="config_mobile_hotspot_provision_app" />
+  <java-symbol type="bool" name="config_intrusiveNotificationLed" />
+  <java-symbol type="dimen" name="preference_fragment_padding_bottom" />
+  <java-symbol type="dimen" name="preference_fragment_padding_side" />
+  <java-symbol type="drawable" name="expander_ic_maximized" />
+  <java-symbol type="drawable" name="expander_ic_minimized" />
+  <java-symbol type="drawable" name="ic_menu_archive" />
+  <java-symbol type="drawable" name="ic_menu_goto" />
+  <java-symbol type="drawable" name="ic_settings_language" />
+  <java-symbol type="drawable" name="title_bar_medium" />
+  <java-symbol type="id" name="body" />
+  <java-symbol type="string" name="fast_scroll_alphabet" />
+  <java-symbol type="string" name="ssl_certificate" />
+
+  <!-- From Phone -->
+  <java-symbol type="bool" name="config_built_in_sip_phone" />
+
+  <!-- From TelephonyProvider -->
+  <java-symbol type="xml" name="apns" />
+
+  <!-- From ContactsProvider -->
+  <java-symbol type="array" name="common_nicknames" />
+  <java-symbol type="drawable" name="call_contact" />
+  <java-symbol type="drawable" name="create_contact" />
+  <java-symbol type="string" name="common_name_prefixes" />
+  <java-symbol type="string" name="common_last_name_prefixes" />
+  <java-symbol type="string" name="common_name_suffixes" />
+  <java-symbol type="string" name="common_name_conjunctions" />
+  <java-symbol type="string" name="dial_number_using" />
+  <java-symbol type="string" name="create_contact_using" />
+
+  <!-- From DownloadProvider -->
+  <java-symbol type="integer" name="config_MaxConcurrentDownloadsAllowed" />
+  <java-symbol type="integer" name="config_downloadDataDirSize" />
+  <java-symbol type="integer" name="config_downloadDataDirLowSpaceThreshold" />
+
+  <!-- From Contacts -->
+  <java-symbol type="drawable" name="quickcontact_badge_overlay_dark" />
+
+  <!-- From Browser -->
+  <java-symbol type="drawable" name="ic_menu_moreoverflow_normal_holo_dark" />
+  <java-symbol type="id" name="placeholder" />
+  <java-symbol type="string" name="ssl_certificate_is_valid" />
+
+  <!-- From Mms -->
+  <java-symbol type="drawable" name="ic_menu_play_clip" />
+
+  <!-- From Stk -->
+  <java-symbol type="bool" name="config_sf_slowBlur" />
+  <java-symbol type="drawable" name="ic_volume" />
+  <java-symbol type="drawable" name="stat_notify_sim_toolkit" />
+
+  <!-- From maps library -->
+  <java-symbol type="array" name="maps_starting_lat_lng" />
+  <java-symbol type="array" name="maps_starting_zoom" />
+  <java-symbol type="attr" name="mapViewStyle" />
+  <java-symbol type="attr" name="state_focused" />
+  <java-symbol type="attr" name="state_selected" />
+  <java-symbol type="attr" name="state_pressed" />
+  <java-symbol type="drawable" name="compass_arrow" />
+  <java-symbol type="drawable" name="compass_base" />
+  <java-symbol type="drawable" name="ic_maps_indicator_current_position_anim" />
+  <java-symbol type="drawable" name="loading_tile_android" />
+  <java-symbol type="drawable" name="maps_google_logo" />
+  <java-symbol type="drawable" name="no_tile_256" />
+  <java-symbol type="drawable" name="reticle" />
+
+  <!-- From PinyinIME(!!!) -->
+  <java-symbol type="string" name="inputMethod" />
+
+</resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 481ca7f..75850dd 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -128,6 +128,8 @@
         <item name="textAppearanceListItemSmall">?android:attr/textAppearanceLarge</item>
         <item name="listPreferredItemPaddingLeft">6dip</item>
         <item name="listPreferredItemPaddingRight">6dip</item>
+        <item name="listPreferredItemPaddingStart">6dip</item>
+        <item name="listPreferredItemPaddingEnd">6dip</item>
 
         <!-- @hide -->
         <item name="searchResultListItemHeight">58dip</item>
@@ -184,17 +186,24 @@
         <item name="windowFixedHeightMinor">0dp</item>
 
         <!-- Dialog attributes -->
-        <item name="alertDialogStyle">@android:style/AlertDialog</item>
         <item name="dialogTheme">@android:style/Theme.Dialog</item>
         <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons</item>
         <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title</item>
         <item name="dialogTitleDecorLayout">@layout/dialog_title</item>
+
+        <!-- AlertDialog attributes -->
         <item name="alertDialogTheme">@android:style/Theme.Dialog.Alert</item>
+        <item name="alertDialogStyle">@android:style/AlertDialog</item>
         <item name="alertDialogCenterButtons">true</item>
         <item name="alertDialogIcon">@android:drawable/ic_dialog_alert</item>
 
+        <!-- Presentation attributes (introduced after API level 10 so does not
+             have a special old-style theme. -->
+        <item name="presentationTheme">@android:style/Theme.DeviceDefault.Dialog.Presentation</item>
+
+        <!-- Toast attributes -->
         <item name="toastFrameBackground">@android:drawable/toast_frame</item>
-        
+
         <!-- Panel attributes -->
         <item name="panelBackground">@android:drawable/menu_background</item>
         <item name="panelFullBackground">@android:drawable/menu_background_fill_parent_width</item>
@@ -232,6 +241,7 @@
         <item name="absListViewStyle">@android:style/Widget.AbsListView</item>
         <item name="autoCompleteTextViewStyle">@android:style/Widget.AutoCompleteTextView</item>        
         <item name="checkboxStyle">@android:style/Widget.CompoundButton.CheckBox</item>
+        <item name="checkedTextViewStyle">@android:style/Widget.CheckedTextView</item>
         <item name="dropDownListViewStyle">@android:style/Widget.ListView.DropDown</item>
         <item name="editTextStyle">@android:style/Widget.EditText</item>
         <item name="expandableListViewStyle">@android:style/Widget.ExpandableListView</item>
@@ -637,6 +647,10 @@
 
         <item name="listPreferredItemPaddingLeft">10dip</item>
         <item name="listPreferredItemPaddingRight">10dip</item>
+        <item name="listPreferredItemPaddingStart">10dip</item>
+        <item name="listPreferredItemPaddingEnd">10dip</item>
+
+        <item name="preferencePanelStyle">@style/PreferencePanel.Dialog</item>
     </style>
 
     <!-- Variant of {@link Theme_Dialog} that does not include a frame (or background).
@@ -863,12 +877,12 @@
          <p>This is the default system theme for apps that target API level 11 - 13. Starting
          with API level 14, the default system theme is supplied by {@link #Theme_DeviceDefault},
          which might apply a different style on different devices. If you want to ensure that your
-         app consistenly uses the Holo theme at all times, you must explicitly declare it in your
+         app consistently uses the Holo theme at all times, you must explicitly declare it in your
          manifest. For example, {@code &lt;application android:theme="@android:style/Theme.Holo"&gt;}.
          For more information, read <a
          href="http://android-developers.blogspot.com/2012/01/holo-everywhere.html">Holo
          Everywhere</a>.</p>
-         <p>The widgets in the holographic theme are translucent on their brackground, so
+         <p>The widgets in the holographic theme are translucent on their background, so
          applications must ensure that any background they use with this theme is itself
          dark; otherwise, it will be difficult to see the widgets. This UI style also includes a
          full action bar by default.</p>
@@ -962,6 +976,8 @@
         <item name="textAppearanceListItemSmall">?android:attr/textAppearanceMedium</item>
         <item name="listPreferredItemPaddingLeft">8dip</item>
         <item name="listPreferredItemPaddingRight">8dip</item>
+        <item name="listPreferredItemPaddingStart">8dip</item>
+        <item name="listPreferredItemPaddingEnd">8dip</item>
 
         <!-- @hide -->
         <item name="searchResultListItemHeight">58dip</item>
@@ -1006,17 +1022,23 @@
         <item name="windowActionModeOverlay">false</item>
 
         <!-- Dialog attributes -->
-        <item name="alertDialogStyle">@android:style/AlertDialog.Holo</item>
         <item name="dialogTheme">@android:style/Theme.Holo.Dialog</item>
         <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_holo</item>
         <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_holo</item>
         <item name="dialogTitleDecorLayout">@layout/dialog_title_holo</item>
+
+        <!-- AlertDialog attributes -->
         <item name="alertDialogTheme">@android:style/Theme.Holo.Dialog.Alert</item>
+        <item name="alertDialogStyle">@android:style/AlertDialog.Holo</item>
         <item name="alertDialogCenterButtons">false</item>
         <item name="alertDialogIcon">@android:drawable/ic_dialog_alert_holo_dark</item>
 
+        <!-- Presentation attributes -->
+        <item name="presentationTheme">@android:style/Theme.Holo.Dialog.Presentation</item>
+
+        <!-- Toast attributes -->
         <item name="toastFrameBackground">@android:drawable/toast_frame_holo</item>
-        
+
         <!-- Panel attributes -->
         <item name="panelBackground">@android:drawable/menu_hardkey_panel_holo_dark</item>
         <item name="panelFullBackground">@android:drawable/menu_background_fill_parent_width</item>
@@ -1050,6 +1072,7 @@
         <item name="absListViewStyle">@android:style/Widget.Holo.AbsListView</item>
         <item name="autoCompleteTextViewStyle">@android:style/Widget.Holo.AutoCompleteTextView</item>
         <item name="checkboxStyle">@android:style/Widget.Holo.CompoundButton.CheckBox</item>
+        <item name="checkedTextViewStyle">@android:style/Widget.Holo.CheckedTextView</item>
         <item name="dropDownListViewStyle">@android:style/Widget.Holo.ListView.DropDown</item>
         <item name="editTextStyle">@android:style/Widget.Holo.EditText</item>
         <item name="expandableListViewStyle">@android:style/Widget.Holo.ExpandableListView</item>
@@ -1267,6 +1290,8 @@
         <item name="textAppearanceListItemSmall">?android:attr/textAppearanceMedium</item>
         <item name="listPreferredItemPaddingLeft">8dip</item>
         <item name="listPreferredItemPaddingRight">8dip</item>
+        <item name="listPreferredItemPaddingStart">8dip</item>
+        <item name="listPreferredItemPaddingEnd">8dip</item>
 
         <!-- @hide -->
         <item name="searchResultListItemHeight">58dip</item>
@@ -1311,17 +1336,23 @@
         <item name="windowActionModeOverlay">false</item>
 
         <!-- Dialog attributes -->
-        <item name="alertDialogStyle">@android:style/AlertDialog.Holo.Light</item>
         <item name="dialogTheme">@android:style/Theme.Holo.Light.Dialog</item>
         <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_holo</item>
         <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_holo</item>
         <item name="dialogTitleDecorLayout">@layout/dialog_title_holo</item>
-        <item name="alertDialogCenterButtons">false</item>
+
+        <!-- AlertDialog attributes -->
         <item name="alertDialogTheme">@android:style/Theme.Holo.Light.Dialog.Alert</item>
+        <item name="alertDialogStyle">@android:style/AlertDialog.Holo.Light</item>
+        <item name="alertDialogCenterButtons">false</item>
         <item name="alertDialogIcon">@android:drawable/ic_dialog_alert_holo_light</item>
 
+        <!-- Presentation attributes -->
+        <item name="presentationTheme">@android:style/Theme.Holo.Light.Dialog.Presentation</item>
+
+        <!-- Toast attributes -->
         <item name="toastFrameBackground">@android:drawable/toast_frame_holo</item>
-        
+
         <!-- Panel attributes -->
         <item name="panelBackground">@android:drawable/menu_hardkey_panel_holo_light</item>
         <item name="panelFullBackground">@android:drawable/menu_background_fill_parent_width</item>
@@ -1355,6 +1386,7 @@
         <item name="absListViewStyle">@android:style/Widget.Holo.Light.AbsListView</item>
         <item name="autoCompleteTextViewStyle">@android:style/Widget.Holo.Light.AutoCompleteTextView</item>
         <item name="checkboxStyle">@android:style/Widget.Holo.Light.CompoundButton.CheckBox</item>
+        <item name="checkedTextViewStyle">@android:style/Widget.Holo.Light.CheckedTextView</item>
         <item name="dropDownListViewStyle">@android:style/Widget.Holo.ListView.DropDown</item>
         <item name="editTextStyle">@android:style/Widget.Holo.Light.EditText</item>
         <item name="expandableListViewStyle">@android:style/Widget.Holo.Light.ExpandableListView</item>
@@ -1576,6 +1608,10 @@
 
         <item name="listPreferredItemPaddingLeft">16dip</item>
         <item name="listPreferredItemPaddingRight">16dip</item>
+        <item name="listPreferredItemPaddingStart">16dip</item>
+        <item name="listPreferredItemPaddingEnd">16dip</item>
+
+        <item name="preferencePanelStyle">@style/PreferencePanel.Dialog</item>
     </style>
 
     <!-- Variant of Theme.Holo.Dialog that has a nice minimum width for
@@ -1653,6 +1689,10 @@
     <style name="Theme.Holo.DialogWhenLarge.NoActionBar" parent="@android:style/Theme.Holo.NoActionBar">
     </style>
 
+    <!-- Theme for a presentation window on a secondary display. -->
+    <style name="Theme.Holo.Dialog.Presentation" parent="@android:style/Theme.Holo.NoActionBar.Fullscreen">
+    </style>
+
     <!-- Light holo dialog themes -->
 
     <!-- Holo light theme for dialog windows and activities, which is used by the
@@ -1684,6 +1724,10 @@
 
         <item name="listPreferredItemPaddingLeft">16dip</item>
         <item name="listPreferredItemPaddingRight">16dip</item>
+        <item name="listPreferredItemPaddingStart">16dip</item>
+        <item name="listPreferredItemPaddingEnd">16dip</item>
+
+        <item name="preferencePanelStyle">@style/PreferencePanel.Dialog</item>
     </style>
 
     <!-- Variant of Theme.Holo.Light.Dialog that has a nice minimum width for
@@ -1748,6 +1792,10 @@
         <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>
     </style>
 
+    <!-- Theme for a presentation window on a secondary display. -->
+    <style name="Theme.Holo.Light.Dialog.Presentation" parent="@android:style/Theme.Holo.Light.NoActionBar.Fullscreen" >
+    </style>
+
     <!-- Default holographic (dark) for windows that want to have the user's selected
          wallpaper appear behind them.  -->
     <style name="Theme.Holo.Wallpaper">
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index eef831f..4178cc4 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -87,9 +87,14 @@
         <item name="android:windowAnimationStyle">@android:style/Animation.DeviceDefault.Activity</item>
 
         <!-- Dialog attributes -->
-        <item name="alertDialogStyle">@android:style/AlertDialog.DeviceDefault</item>
         <item name="dialogTheme">@android:style/Theme.DeviceDefault.Dialog</item>
+
+        <!-- AlertDialog attributes -->
         <item name="alertDialogTheme">@android:style/Theme.DeviceDefault.Dialog.Alert</item>
+        <item name="alertDialogStyle">@android:style/AlertDialog.DeviceDefault</item>
+
+        <!-- Presentation attributes -->
+        <item name="presentationTheme">@android:style/Theme.DeviceDefault.Dialog.Presentation</item>
 
         <!-- Text selection handle attributes -->
         <item name="textSelectHandleWindowStyle">@android:style/Widget.DeviceDefault.TextSelectHandle</item>
@@ -99,6 +104,7 @@
         <item name="absListViewStyle">@android:style/Widget.DeviceDefault.AbsListView</item>
         <item name="autoCompleteTextViewStyle">@android:style/Widget.DeviceDefault.AutoCompleteTextView</item>
         <item name="checkboxStyle">@android:style/Widget.DeviceDefault.CompoundButton.CheckBox</item>
+        <item name="checkedTextViewStyle">@android:style/Widget.DeviceDefault.CheckedTextView</item>
         <item name="dropDownListViewStyle">@android:style/Widget.DeviceDefault.ListView.DropDown</item>
         <item name="editTextStyle">@android:style/Widget.DeviceDefault.EditText</item>
         <item name="expandableListViewStyle">@android:style/Widget.DeviceDefault.ExpandableListView</item>
@@ -239,9 +245,14 @@
         <item name="android:windowAnimationStyle">@android:style/Animation.DeviceDefault.Activity</item>
 
         <!-- Dialog attributes -->
-        <item name="alertDialogStyle">@android:style/AlertDialog.DeviceDefault.Light</item>
         <item name="dialogTheme">@android:style/Theme.DeviceDefault.Light.Dialog</item>
+
+        <!-- AlertDialog attributes -->
         <item name="alertDialogTheme">@android:style/Theme.DeviceDefault.Light.Dialog.Alert</item>
+        <item name="alertDialogStyle">@android:style/AlertDialog.DeviceDefault.Light</item>
+
+        <!-- Presentation attributes -->
+        <item name="presentationTheme">@android:style/Theme.DeviceDefault.Light.Dialog.Presentation</item>
 
         <!-- Text selection handle attributes -->
         <item name="textSelectHandleWindowStyle">@android:style/Widget.DeviceDefault.TextSelectHandle</item>
@@ -251,7 +262,8 @@
         <item name="absListViewStyle">@android:style/Widget.DeviceDefault.Light.AbsListView</item>
         <item name="autoCompleteTextViewStyle">@android:style/Widget.DeviceDefault.Light.AutoCompleteTextView</item>
         <item name="checkboxStyle">@android:style/Widget.DeviceDefault.Light.CompoundButton.CheckBox</item>
-        <item name="dropDownListViewStyle">@android:style/Widget.DeviceDefault.ListView.DropDown</item>
+        <item name="checkedTextViewStyle">@android:style/Widget.DeviceDefault.Light.CheckedTextView</item>
+        <item name="dropDownListViewStyle">@android:style/Widget.DeviceDefault.Light.ListView.DropDown</item>
         <item name="editTextStyle">@android:style/Widget.DeviceDefault.Light.EditText</item>
         <item name="expandableListViewStyle">@android:style/Widget.DeviceDefault.Light.ExpandableListView</item>
         <item name="expandableListViewWhiteStyle">@android:style/Widget.DeviceDefault.Light.ExpandableListView.White</item>
@@ -286,7 +298,7 @@
         <item name="webViewStyle">@android:style/Widget.DeviceDefault.Light.WebView</item>
         <item name="dropDownItemStyle">@android:style/Widget.DeviceDefault.Light.DropDownItem</item>
         <item name="spinnerDropDownItemStyle">@android:style/Widget.DeviceDefault.Light.DropDownItem.Spinner</item>
-        <item name="spinnerItemStyle">@android:style/Widget.DeviceDefault.TextView.SpinnerItem</item>
+        <item name="spinnerItemStyle">@android:style/Widget.DeviceDefault.Light.TextView.SpinnerItem</item>
         <item name="dropDownHintAppearance">@android:style/TextAppearance.DeviceDefault.Widget.DropDownHint</item>
         <item name="keyboardViewStyle">@android:style/Widget.DeviceDefault.KeyboardView</item>
         <item name="quickContactBadgeStyleWindowSmall">@android:style/Widget.DeviceDefault.QuickContactBadge.WindowSmall</item>
@@ -460,6 +472,15 @@
     <style name="Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar" parent="Theme.Holo.Light.DialogWhenLarge.NoActionBar" >
 
     </style>
+
+    <!-- DeviceDefault theme for a presentation window on a secondary display. -->
+    <style name="Theme.DeviceDefault.Dialog.Presentation" parent="Theme.Holo.Dialog.Presentation">
+    </style>
+
+    <!-- DeviceDefault light theme for a presentation window on a secondary display. -->
+    <style name="Theme.DeviceDefault.Light.Dialog.Presentation" parent="Theme.Holo.Light.Dialog.Presentation">
+    </style>
+
     <!-- DeviceDefault theme for panel windows. This removes all extraneous window
     decorations, so you basically have an empty rectangle in which to place your content. It makes
     the window floating, with a transparent background, and turns off dimming behind the window. -->
diff --git a/core/res/res/xml/kg_password_kbd_numeric.xml b/core/res/res/xml/kg_password_kbd_numeric.xml
new file mode 100755
index 0000000..93b32af
--- /dev/null
+++ b/core/res/res/xml/kg_password_kbd_numeric.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
+    android:keyWidth="33.33%p"
+    android:horizontalGap="@dimen/kg_key_horizontal_gap"
+    android:verticalGap="@dimen/kg_key_vertical_gap"
+    android:keyHeight="@dimen/kg_pin_key_height">
+
+    <Row android:rowEdgeFlags="top">
+        <Key android:codes="49" android:keyIcon="@*android:drawable/sym_keyboard_num1"
+             android:keyEdgeFlags="left"/>
+        <Key android:codes="50" android:keyIcon="@*android:drawable/sym_keyboard_num2"/>
+        <Key android:codes="51" android:keyIcon="@*android:drawable/sym_keyboard_num3"
+             android:keyEdgeFlags="right"/>
+    </Row>
+
+    <Row>
+        <Key android:codes="52" android:keyIcon="@*android:drawable/sym_keyboard_num4"
+             android:keyEdgeFlags="left"/>
+        <Key android:codes="53" android:keyIcon="@*android:drawable/sym_keyboard_num5"/>
+        <Key android:codes="54" android:keyIcon="@*android:drawable/sym_keyboard_num6"
+             android:keyEdgeFlags="right"/>
+    </Row>
+
+    <Row>
+        <Key android:codes="55" android:keyIcon="@*android:drawable/sym_keyboard_num7"
+             android:keyEdgeFlags="left"/>
+        <Key android:codes="56" android:keyIcon="@*android:drawable/sym_keyboard_num8"/>
+        <Key android:codes="57" android:keyIcon="@*android:drawable/sym_keyboard_num9"
+             android:keyEdgeFlags="right"/>
+    </Row>
+
+    <Row android:rowEdgeFlags="bottom">
+        <Key android:codes="48" android:keyIcon="@*android:drawable/sym_keyboard_num0_no_plus"
+             android:keyWidth="33.33%p"
+             android:keyEdgeFlags="left"/>
+        <Key android:codes="10" android:keyIcon="@*android:drawable/sym_keyboard_enter"
+             android:keyWidth="66.67%p"
+             android:keyEdgeFlags="right"/>
+    </Row>
+
+</Keyboard>
diff --git a/core/res/res/xml/password_kbd_numeric.xml b/core/res/res/xml/password_kbd_numeric.xml
index 560f867..7593ad8 100755
--- a/core/res/res/xml/password_kbd_numeric.xml
+++ b/core/res/res/xml/password_kbd_numeric.xml
@@ -51,7 +51,7 @@
     <Row android:rowEdgeFlags="bottom">
         <Key android:codes="48" android:keyIcon="@drawable/sym_keyboard_num0_no_plus"
              android:keyWidth="66.66%p" android:keyEdgeFlags="left"/>
-        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_ok"
+        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_enter"
              android:keyEdgeFlags="right"/>
     </Row>
 
diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml
index 30312b3..7af3b9c 100644
--- a/core/res/res/xml/power_profile.xml
+++ b/core/res/res/xml/power_profile.xml
@@ -18,37 +18,44 @@
 -->
 
 <device name="Android">
-  <!-- All values are in mAh except as noted -->
+  <!-- Most values are the incremental current used by a feature,
+       in mA (measured at nominal voltage).
+       The default values are deliberately incorrect dummy values.
+       OEM's must measure and provide actual values before
+       shipping a device.
+       Example real-world values are given in comments, but they
+       are totally dependent on the platform and can vary
+       significantly, so should be measured on the shipping platform
+       with a power meter. -->
   <item name="none">0</item>
-  <item name="screen.on">0.1</item>
-  <item name="bluetooth.active">0.1</item>
-  <item name="bluetooth.on">0.1</item>
-  <item name="screen.full">0.1</item>
-  <item name="wifi.on">0.1</item>
-  <item name="wifi.active">0.1</item>
-  <item name="wifi.scan">0.1</item>
-  <item name="dsp.audio">0.1</item>
-  <item name="dsp.video">0.1</item>
-  <item name="radio.active">1</item>
-  <!-- The current consumed by the radio when it is scanning for a signal -->
-  <item name="radio.scanning">0.5</item>
-  <item name="gps.on">1</item>
+  <item name="screen.on">0.1</item>  <!-- ~200mA -->
+  <item name="screen.full">0.1</item>  <!-- ~300mA -->
+  <item name="bluetooth.active">0.1</item> <!-- Bluetooth data transfer, ~10mA -->
+  <item name="bluetooth.on">0.1</item>  <!-- Bluetooth on & connectable, but not connected, ~0.1mA -->
+  <item name="wifi.on">0.1</item>  <!-- ~3mA -->
+  <item name="wifi.active">0.1</item>  <!-- WIFI data transfer, ~200mA -->
+  <item name="wifi.scan">0.1</item>  <!-- WIFI network scanning, ~100mA -->
+  <item name="dsp.audio">0.1</item> <!-- ~10mA -->
+  <item name="dsp.video">0.1</item> <!-- ~50mA -->
+  <item name="radio.active">0.1</item> <!-- ~200mA -->
+  <item name="radio.scanning">0.1</item> <!-- cellular radio scanning for signal, ~10mA -->
+  <item name="gps.on">0.1</item> <!-- ~50mA -->
   <!-- Current consumed by the radio at different signal strengths, when paging -->
   <array name="radio.on"> <!-- Strength 0 to BINS-1 -->
-      <value>0.2</value>
-      <value>0.1</value>
+      <value>0.2</value> <!-- ~2mA -->
+      <value>0.1</value> <!-- ~1mA -->
   </array>
   <!-- Different CPU speeds as reported in
        /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state -->
   <array name="cpu.speeds">
       <value>400000</value> <!-- 400 MHz CPU speed -->
   </array>
-  <!-- Power consumption when CPU is idle -->
+  <!-- Current when CPU is idle -->
   <item name="cpu.idle">0.1</item>
-  <!-- Power consumption at different speeds -->
+  <!-- Current at each CPU speed, as per 'cpu.speeds' -->
   <array name="cpu.active">
-      <value>0.2</value>
+      <value>0.1</value>  <!-- ~100mA -->
   </array>
-  <!-- This is the battery capacity in mAh -->
+  <!-- This is the battery capacity in mAh (measured at nominal voltage) -->
   <item name="battery.capacity">1000</item>
 </device>
diff --git a/core/tests/ConnectivityManagerTest/AndroidManifest.xml b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
index 05f8b39..5db7ffc 100644
--- a/core/tests/ConnectivityManagerTest/AndroidManifest.xml
+++ b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
@@ -72,5 +72,7 @@
     <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-permission android:name="android.permission.DEVICE_POWER" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+    <uses-permission android:name="android.permission.INJECT_EVENTS" />
 </manifest>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index f01562c..245f537 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -36,6 +36,7 @@
 import android.os.PowerManager;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -64,6 +65,8 @@
     public static final long LONG_TIMEOUT = 50 * 1000;
     // 2 minutes timer between wifi stop and start
     public static final long  WIFI_STOP_START_INTERVAL = 2 * 60 * 1000;
+    // Set ping test timer to be 3 minutes
+    public static final long PING_TIMER = 3 * 60 *1000;
     public static final int SUCCESS = 0;  // for Wifi tethering state change
     public static final int FAILURE = 1;
     public static final int INIT = -1;
@@ -94,7 +97,6 @@
      * Control Wifi States
      */
     public WifiManager mWifiManager;
-    public WifiManager.Channel mChannel;
 
     /*
      * Verify connectivity state
@@ -242,7 +244,6 @@
         // Get an instance of WifiManager
         mWifiManager =(WifiManager)getSystemService(Context.WIFI_SERVICE);
         mContext = this;
-        mChannel = mWifiManager.initialize(mContext, mContext.getMainLooper(), null);
 
         if (mWifiManager.isWifiApEnabled()) {
             // if soft AP is enabled, disable it
@@ -502,19 +503,15 @@
         log("Turn screen off");
         PowerManager pm =
             (PowerManager) getSystemService(Context.POWER_SERVICE);
-        pm.goToSleep(SystemClock.uptimeMillis() + 100);
+        pm.goToSleep(SystemClock.uptimeMillis());
     }
 
     // Turn screen on
     public void turnScreenOn() {
         log("Turn screen on");
-        IPowerManager mPowerManagerService = IPowerManager.Stub.asInterface(
-                ServiceManager.getService("power"));;
-        try {
-            mPowerManagerService.userActivityWithForce(SystemClock.uptimeMillis(), false, true);
-        } catch (Exception e) {
-            log(e.toString());
-        }
+        PowerManager pm =
+                (PowerManager) getSystemService(Context.POWER_SERVICE);
+        pm.wakeUp(SystemClock.uptimeMillis());
     }
 
     /**
@@ -522,37 +519,36 @@
      * @return true if the ping test is successful, false otherwise.
      */
     public boolean pingTest(String[] pingServerList) {
-        boolean result = false;
         String[] hostList = {"www.google.com", "www.yahoo.com",
                 "www.bing.com", "www.facebook.com", "www.ask.com"};
         if (pingServerList != null) {
             hostList = pingServerList;
         }
-        try {
-            // assume the chance that all servers are down is very small
-            for (int i = 0; i < hostList.length; i++ ) {
-                String host = hostList[i];
-                log("Start ping test, ping " + host);
-                Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + host);
-                int status = p.waitFor();
-                if (status == 0) {
-                    // if any of the ping test is successful, return true
-                    result = true;
-                    break;
-                } else {
-                    result = false;
-                    log("ping " + host + " failed.");
+
+        long startTime = System.currentTimeMillis();
+        while ((System.currentTimeMillis() - startTime) < PING_TIMER) {
+            try {
+                // assume the chance that all servers are down is very small
+                for (int i = 0; i < hostList.length; i++ ) {
+                    String host = hostList[i];
+                    log("Start ping test, ping " + host);
+                    Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + host);
+                    int status = p.waitFor();
+                    if (status == 0) {
+                        // if any of the ping test is successful, return true
+                        return true;
+                    }
                 }
+            } catch (UnknownHostException e) {
+                log("Ping test Fail: Unknown Host");
+            } catch (IOException e) {
+                log("Ping test Fail:  IOException");
+            } catch (InterruptedException e) {
+                log("Ping test Fail: InterruptedException");
             }
-        } catch (UnknownHostException e) {
-            log("Ping test Fail: Unknown Host");
-        } catch (IOException e) {
-            log("Ping test Fail:  IOException");
-        } catch (InterruptedException e) {
-            log("Ping test Fail: InterruptedException");
         }
-        log("return");
-        return result;
+        // ping test timeout
+        return false;
     }
 
     /**
@@ -599,7 +595,7 @@
                         log("found " + ssid + " in the scan result list");
                         log("retry: " + retry);
                         foundApInScanResults = true;
-                        mWifiManager.connect(mChannel, config,
+                        mWifiManager.connect(config,
                                 new WifiManager.ActionListener() {
                                     public void onSuccess() {
                                     }
@@ -658,7 +654,7 @@
         for (WifiConfiguration wifiConfig: wifiConfigList) {
             log("remove wifi configuration: " + wifiConfig.networkId);
             int netId = wifiConfig.networkId;
-            mWifiManager.forget(mChannel, netId, new WifiManager.ActionListener() {
+            mWifiManager.forget(netId, new WifiManager.ActionListener() {
                     public void onSuccess() {
                     }
                     public void onFailure(int reason) {
@@ -702,12 +698,12 @@
      */
     public void setAirplaneMode(Context context, boolean enableAM) {
         //set the airplane mode
-        Settings.System.putInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
+        Settings.Global.putInt(context.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON,
                 enableAM ? 1 : 0);
         // Post the intent
         Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
         intent.putExtra("state", enableAM);
-        context.sendBroadcast(intent);
+        context.sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     protected static String convertToQuotedString(String string) {
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
index bf188d3..7928822 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -59,8 +59,8 @@
         wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "CMWakeLock");
         wl.acquire();
         // Each test case will start with cellular connection
-        if (Settings.System.getInt(getInstrumentation().getContext().getContentResolver(),
-                Settings.System.AIRPLANE_MODE_ON) == 1) {
+        if (Settings.Global.getInt(getInstrumentation().getContext().getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON) == 1) {
             log("airplane is not disabled, disable it.");
             cmActivity.setAirplaneMode(getInstrumentation().getContext(), false);
         }
@@ -84,8 +84,8 @@
         wl.release();
         cmActivity.removeConfiguredNetworksAndDisableWifi();
         // if airplane mode is set, disable it.
-        if (Settings.System.getInt(getInstrumentation().getContext().getContentResolver(),
-                Settings.System.AIRPLANE_MODE_ON) == 1) {
+        if (Settings.Global.getInt(getInstrumentation().getContext().getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON) == 1) {
             log("disable airplane mode if it is enabled");
             cmActivity.setAirplaneMode(getInstrumentation().getContext(), false);
         }
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
index 8d73bc0..81075ef 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
@@ -63,7 +63,6 @@
     private ConnectivityManagerTestActivity mAct;
     private ConnectivityManagerTestRunner mRunner;
     private WifiManager mWifiManager = null;
-    private WifiManager.Channel mChannel;
     private Set<WifiConfiguration> enabledNetworks = null;
 
     public WifiConnectionTest() {
@@ -77,7 +76,6 @@
         mWifiManager = (WifiManager) mRunner.getContext().getSystemService(Context.WIFI_SERVICE);
 
         mAct = getActivity();
-        mChannel = mWifiManager.initialize(mAct, mAct.getMainLooper(), null);
 
         networks = mAct.loadNetworkConfigurations();
         if (DEBUG) {
@@ -93,24 +91,6 @@
         assertTrue("wpa_supplicant is not started ", mAct.mWifiManager.pingSupplicant());
     }
 
-    private class WifiServiceHandler extends Handler {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
-                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
-                        //AsyncChannel in msg.obj
-                    } else {
-                        log("Failed to establish AsyncChannel connection");
-                    }
-                    break;
-                default:
-                    //Ignore
-                    break;
-            }
-        }
-    }
-
     private void printNetworkConfigurations() {
         log("==== print network configurations parsed from XML file ====");
         log("number of access points: " + networks.size());
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
index 39e2cf2..7bfb594 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -28,6 +28,7 @@
 import android.os.Environment;
 import android.os.PowerManager;
 import android.provider.Settings;
+import android.view.KeyEvent;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
@@ -219,15 +220,16 @@
     // Stress Wifi reconnection to secure net after sleep
     @LargeTest
     public void testWifiReconnectionAfterSleep() {
-        int value = Settings.System.getInt(mRunner.getContext().getContentResolver(),
-                Settings.System.WIFI_SLEEP_POLICY, -1);
-        if (value < 0) {
-            Settings.System.putInt(mRunner.getContext().getContentResolver(),
-                    Settings.System.WIFI_SLEEP_POLICY, Settings.System.WIFI_SLEEP_POLICY_DEFAULT);
+        int value = Settings.Global.getInt(mRunner.getContext().getContentResolver(),
+                Settings.Global.WIFI_SLEEP_POLICY, -1);
+        log("wifi sleep policy is: " + value);
+        if (value != Settings.Global.WIFI_SLEEP_POLICY_DEFAULT) {
+            Settings.Global.putInt(mRunner.getContext().getContentResolver(),
+                    Settings.Global.WIFI_SLEEP_POLICY, Settings.Global.WIFI_SLEEP_POLICY_DEFAULT);
             log("set wifi sleep policy to default value");
         }
-        Settings.Secure.putLong(mRunner.getContext().getContentResolver(),
-                Settings.Secure.WIFI_IDLE_MS, WIFI_IDLE_MS);
+        Settings.Global.putLong(mRunner.getContext().getContentResolver(),
+                Settings.Global.WIFI_IDLE_MS, WIFI_IDLE_MS);
 
         // Connect to a Wi-Fi network
         WifiConfiguration config = new WifiConfiguration();
@@ -288,6 +290,11 @@
 
             // Turn screen on again
             mAct.turnScreenOn();
+            // Wait for 2 seconds for the lock screen
+            sleep(2 * 1000, "wait 2 seconds for lock screen");
+            // Disable lock screen by inject menu key event
+            mRunner.sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
+
             // Measure the time for Wi-Fi to get connected
             long startTime = System.currentTimeMillis();
             assertTrue("Wait for Wi-Fi enable timeout after wake up",
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
index c3cc7c5..d5fcc1c 100644
--- a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
@@ -74,7 +74,6 @@
     private int mWifiState;
     private NetworkInfo mWifiNetworkInfo;
     private WifiManager mWifiManager;
-    private WifiManager.Channel mChannel;
     private Context mContext;
     // Verify connectivity state
     private static final int NUM_NETWORK_TYPES = ConnectivityManager.MAX_NETWORK_TYPE + 1;
@@ -115,7 +114,6 @@
 
         // Get an instance of WifiManager
         mWifiManager =(WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
-        mChannel = mWifiManager.initialize(mContext, mContext.getMainLooper(), null);
 
         mDownloadManager = (DownloadManager)mContext.getSystemService(Context.DOWNLOAD_SERVICE);
 
@@ -574,7 +572,7 @@
                         Log.v(LOG_TAG, "Found " + ssid + " in the scan result list.");
                         Log.v(LOG_TAG, "Retry: " + retry);
                         foundApInScanResults = true;
-                        mWifiManager.connect(mChannel, config, new WifiManager.ActionListener() {
+                        mWifiManager.connect(config, new WifiManager.ActionListener() {
                                 public void onSuccess() {
                                 }
                                 public void onFailure(int reason) {
@@ -628,7 +626,7 @@
         for (WifiConfiguration wifiConfig: wifiConfigList) {
             Log.v(LOG_TAG, "Remove wifi configuration: " + wifiConfig.networkId);
             int netId = wifiConfig.networkId;
-            mWifiManager.forget(mChannel, netId, new WifiManager.ActionListener() {
+            mWifiManager.forget(netId, new WifiManager.ActionListener() {
                     public void onSuccess() {
                     }
                     public void onFailure(int reason) {
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index dcd1bab..41f8536 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -69,6 +69,10 @@
     <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" />
     <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.ALL_SERVICES" />
 
+    <uses-permission android:name="android.permission.MANAGE_USERS" />
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+
     <uses-permission android:name="android.permission.RECEIVE_SMS"/>
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.READ_CONTACTS" />
diff --git a/core/tests/coretests/apks/FrameworkCoreTests_apk.mk b/core/tests/coretests/apks/FrameworkCoreTests_apk.mk
index ac545ca..1e03270 100644
--- a/core/tests/coretests/apks/FrameworkCoreTests_apk.mk
+++ b/core/tests/coretests/apks/FrameworkCoreTests_apk.mk
@@ -7,6 +7,9 @@
 # Make sure every package name gets the FrameworkCoreTests_ prefix.
 LOCAL_PACKAGE_NAME := FrameworkCoreTests_$(LOCAL_PACKAGE_NAME)
 
+# Every package should have a native library
+LOCAL_JNI_SHARED_LIBRARIES := libframeworks_coretests_jni
+
 FrameworkCoreTests_all_apks += $(LOCAL_PACKAGE_NAME)
 
 include $(BUILD_PACKAGE)
diff --git a/core/tests/coretests/apks/install_bad_dex/Android.mk b/core/tests/coretests/apks/install_bad_dex/Android.mk
new file mode 100644
index 0000000..769a1b0
--- /dev/null
+++ b/core/tests/coretests/apks/install_bad_dex/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := install_bad_dex
+
+LOCAL_JAVA_RESOURCE_FILES := $(LOCAL_PATH)/classes.dex
+
+include $(FrameworkCoreTests_BUILD_PACKAGE)
diff --git a/core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml b/core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml
new file mode 100644
index 0000000..76f0fe5
--- /dev/null
+++ b/core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.frameworks.coretests.install_bad_dex">
+
+    <application android:hasCode="true">
+        <activity
+            android:name="com.android.frameworks.coretests.TestActivity">
+        </activity>
+    </application>
+</manifest>
diff --git a/core/tests/coretests/apks/install_bad_dex/classes.dex b/core/tests/coretests/apks/install_bad_dex/classes.dex
new file mode 100644
index 0000000..284b6d4
--- /dev/null
+++ b/core/tests/coretests/apks/install_bad_dex/classes.dex
@@ -0,0 +1 @@
+This is a bad dex
diff --git a/core/tests/coretests/apks/install_bad_dex/res/values/strings.xml b/core/tests/coretests/apks/install_bad_dex/res/values/strings.xml
new file mode 100644
index 0000000..3b8b3b1
--- /dev/null
+++ b/core/tests/coretests/apks/install_bad_dex/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string name="dummy">dummy</string>
+</resources>
diff --git a/core/tests/coretests/apks/install_bad_dex/src/com/android/frameworks/coretests/TestActivity.java b/core/tests/coretests/apks/install_bad_dex/src/com/android/frameworks/coretests/TestActivity.java
new file mode 100644
index 0000000..10d0551
--- /dev/null
+++ b/core/tests/coretests/apks/install_bad_dex/src/com/android/frameworks/coretests/TestActivity.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ *
+ */
+
+package com.android.frameworks.coretests;
+
+import android.app.Activity;
+
+public class TestActivity extends Activity {
+
+}
diff --git a/core/tests/coretests/apks/install_jni_lib/Android.mk b/core/tests/coretests/apks/install_jni_lib/Android.mk
new file mode 100644
index 0000000..b61ea8e
--- /dev/null
+++ b/core/tests/coretests/apks/install_jni_lib/Android.mk
@@ -0,0 +1,28 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    com_android_frameworks_coretests_JNITest.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libnativehelper
+
+LOCAL_MODULE := libframeworks_coretests_jni
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp b/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp
new file mode 100644
index 0000000..957fc4a
--- /dev/null
+++ b/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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 "nativehelper/JNIHelp.h"
+
+namespace android {
+
+static jint checkFunction(JNIEnv*, jclass) {
+    return 1;
+}
+
+static JNINativeMethod sMethods[] = {
+    /* name, signature, funcPtr */
+    { "checkFunction", "()I", (void*) checkFunction },
+};
+
+int register_com_android_framework_coretests_JNITests(JNIEnv* env) {
+    return jniRegisterNativeMethods(env, "com/android/framework/coretests/JNITests", sMethods,
+            NELEM(sMethods));
+}
+
+}
+
+/*
+ * JNI Initialization
+ */
+jint JNI_OnLoad(JavaVM *jvm, void *reserved) {
+    JNIEnv *e;
+    int status;
+
+    // Check JNI version
+    if (jvm->GetEnv((void **) &e, JNI_VERSION_1_6)) {
+        return JNI_ERR;
+    }
+
+    if ((status = android::register_com_android_framework_coretests_JNITests(e)) < 0) {
+        return JNI_ERR;
+    }
+
+    return JNI_VERSION_1_6;
+}
diff --git a/core/tests/coretests/apks/version/Android.mk b/core/tests/coretests/apks/version/Android.mk
new file mode 100644
index 0000000..3635a58
--- /dev/null
+++ b/core/tests/coretests/apks/version/Android.mk
@@ -0,0 +1,36 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := version_1
+LOCAL_AAPT_FLAGS := --version-code 1 --version-name 1.0
+LOCAL_CERTIFICATE := $(LOCAL_PATH)/../../certs/unit_test
+include $(FrameworkCoreTests_BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := version_2
+LOCAL_AAPT_FLAGS := --version-code 2 --version-name 2.0
+LOCAL_CERTIFICATE := $(LOCAL_PATH)/../../certs/unit_test
+include $(FrameworkCoreTests_BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := version_3
+LOCAL_AAPT_FLAGS := --version-code 3 --version-name 3.0
+LOCAL_CERTIFICATE := $(LOCAL_PATH)/../../certs/unit_test
+include $(FrameworkCoreTests_BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := version_1_diff
+LOCAL_AAPT_FLAGS := --version-code 1 --version-name 1.0
+LOCAL_CERTIFICATE := $(LOCAL_PATH)/../../certs/unit_test_diff
+include $(FrameworkCoreTests_BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := version_2_diff
+LOCAL_AAPT_FLAGS := --version-code 2 --version-name 2.0
+LOCAL_CERTIFICATE := $(LOCAL_PATH)/../../certs/unit_test_diff
+include $(FrameworkCoreTests_BUILD_PACKAGE)
diff --git a/core/tests/coretests/apks/version/AndroidManifest.xml b/core/tests/coretests/apks/version/AndroidManifest.xml
new file mode 100644
index 0000000..c35ae63
--- /dev/null
+++ b/core/tests/coretests/apks/version/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.frameworks.coretests.version_test">
+
+    <!-- Which permission it uses is not important as long as it's a system-only
+         permission -->
+    <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
+
+    <!-- Which permission it uses is not important as long as it's a normal
+         permission -->
+    <uses-permission android:name="android.permission.VIBRATE" />
+
+    <application android:hasCode="false"/>
+</manifest>
diff --git a/core/tests/coretests/apks/version/res/values/strings.xml b/core/tests/coretests/apks/version/res/values/strings.xml
new file mode 100644
index 0000000..3b8b3b1
--- /dev/null
+++ b/core/tests/coretests/apks/version/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string name="dummy">dummy</string>
+</resources>
diff --git a/core/tests/coretests/apks/version/src/com/android/frameworks/coretests/version_test/NullProvider.java b/core/tests/coretests/apks/version/src/com/android/frameworks/coretests/version_test/NullProvider.java
new file mode 100644
index 0000000..f5742f0
--- /dev/null
+++ b/core/tests/coretests/apks/version/src/com/android/frameworks/coretests/version_test/NullProvider.java
@@ -0,0 +1,39 @@
+package com.android.frameworks.coretests.version_test;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+public class NullProvider extends ContentProvider {
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        return null;
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return "text/plain";
+    }
+}
diff --git a/core/tests/coretests/certs/README b/core/tests/coretests/certs/README
new file mode 100644
index 0000000..00917a1
--- /dev/null
+++ b/core/tests/coretests/certs/README
@@ -0,0 +1,4 @@
+Generate with:
+
+development/tools/make_key unit_test         '/CN=unit_test'
+development/tools/make_key unit_test_diff    '/CN=unit_test_diff'
diff --git a/core/tests/coretests/certs/unit_test.pk8 b/core/tests/coretests/certs/unit_test.pk8
new file mode 100644
index 0000000..f935e3e
--- /dev/null
+++ b/core/tests/coretests/certs/unit_test.pk8
Binary files differ
diff --git a/core/tests/coretests/certs/unit_test.x509.pem b/core/tests/coretests/certs/unit_test.x509.pem
new file mode 100644
index 0000000..21c4beb
--- /dev/null
+++ b/core/tests/coretests/certs/unit_test.x509.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDHjCCAgagAwIBAgIJAJnvhSUT7hwkMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV
+BAMUCXVuaXRfdGVzdDAeFw0xMjA1MDgwNTUwMDJaFw0zOTA5MjQwNTUwMDJaMBQx
+EjAQBgNVBAMUCXVuaXRfdGVzdDCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgC
+ggEBAOm2mt+vcNjDqTx1SVMj0tQcAJU49zao6rKigV+D7QdLfVOYbzdlJjL7CVZQ
+7+Tjq/mXHmNyUi7eI/eTgzZOXEjuf1moFoFvqxFeIHgR1iWAkODJ5FTGZEDiK4gY
+amfS7LVwqsr1ExE6XfBUb5n/34V/Twr6suSRVjcS3OI5X3Yh/Ip/I2SNCJ6Kz5EX
+RVk0T+I0zhIHX8+57Dp+0j3Cq0hb7ROylIbxrKzv1cpxt3FUrZXpLspalYvUoYLU
+Jr3XA9vfbSf2NPqGz8VeUxvqoWcMhyMEuswwQF1YPU9HCIKhC76Xd8O5hIKy7jlo
+ZNSiKmKySyy8IJB4w+Hxd70h6TMCAQOjdTBzMB0GA1UdDgQWBBSDs4X8MYwKBmiw
+f+RqeLc8R8XaoTBEBgNVHSMEPTA7gBSDs4X8MYwKBmiwf+RqeLc8R8XaoaEYpBYw
+FDESMBAGA1UEAxQJdW5pdF90ZXN0ggkAme+FJRPuHCQwDAYDVR0TBAUwAwEB/zAN
+BgkqhkiG9w0BAQUFAAOCAQEAmRIybRohluR/zcrwRK5TpJIfArSNBdWLbfEyo+ug
+mzMLq/RUHXXJSmqXaX/4tcW/LfjiCZjKmoauGSe9u979lX8nTKLBfeRWQpNUgwux
+pBBt2Ein14IP7rZI34bB3iN06KTTBfpK60XZR23n9gkWClmMuTSd8scX/XoYXfeW
+B0ePwQAMk1S1Ge5wbQCSJOCP5hTKzWio2S2rfw5pXa+ppHwXe0SWXtQHvMDu5WVy
+Cgwqu4yxrneHYGV3mphtHXdtCAgfh4L+/4ooHwzBfxVaDhyZ1UvoEntczEi/VEV2
+liP8IbwSp1x8Mdg8TIVJrDjvAoR6j8ie8i3IHNRzZLNJ0A==
+-----END CERTIFICATE-----
diff --git a/core/tests/coretests/certs/unit_test_diff.pk8 b/core/tests/coretests/certs/unit_test_diff.pk8
new file mode 100644
index 0000000..a85ec86
--- /dev/null
+++ b/core/tests/coretests/certs/unit_test_diff.pk8
Binary files differ
diff --git a/core/tests/coretests/certs/unit_test_diff.x509.pem b/core/tests/coretests/certs/unit_test_diff.x509.pem
new file mode 100644
index 0000000..e3e2197
--- /dev/null
+++ b/core/tests/coretests/certs/unit_test_diff.x509.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDLTCCAhWgAwIBAgIJAOZy2AGEfSxzMA0GCSqGSIb3DQEBBQUAMBkxFzAVBgNV
+BAMUDnVuaXRfdGVzdF9kaWZmMB4XDTEyMDUwODE5MjYwN1oXDTM5MDkyNDE5MjYw
+N1owGTEXMBUGA1UEAxQOdW5pdF90ZXN0X2RpZmYwggEgMA0GCSqGSIb3DQEBAQUA
+A4IBDQAwggEIAoIBAQDKuDr+3vZZrjJ2AeTDFZJjeQdFrwRQJ1BOBM5aot/uTCfX
+fe/CAm6Kn1rDtx+/srlLEqmjZDzzKYSpU7Vr0rOsTCTjWgis1/6jVydJgrsL6nXF
+oz8swqTa+IYpa4gjs08EEqfjbbGTtSfVi6jziw/Nebtl5XRBoREpV8cTJk+DZH/B
+8c0Ns8XpSawpFUDH9UXoEzNdje033HpTROWN7gbX9nA3x0YXdUnb8I0VcVf16m+3
+Tk07UkE/f7geOZ4CDF/a9dri9z5KWUlODOw7hlQG658N6gILmTc+5Vrree5eBLXo
+qeIyg2w0pZZLLATomVCVUm9CaGna+cUai3Hfb+bFAgEDo3oweDAdBgNVHQ4EFgQU
+xqP+zV47zj1Dsup1FU+PG1PBFZ4wSQYDVR0jBEIwQIAUxqP+zV47zj1Dsup1FU+P
+G1PBFZ6hHaQbMBkxFzAVBgNVBAMUDnVuaXRfdGVzdF9kaWZmggkA5nLYAYR9LHMw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAg5rZis/BVK8EYhdr8F6p
+yG7qYbHyYtswmGGu9MPcNKR9eclNd1VQktIEXoIqCq7DhHn0LWgedh4WHfCtbHmI
+iPi9HUjMBzLiUUsuRloPPe1DykFZJY3EUYH9JI0p+J+18grGakrlPKqbF6ymVN9w
+iaznMgf0qSpyIMFLgltLkiXPJUByTfADQBDsQe7njQlG4A+wSHTUN7XY32IIlQJ1
+lvmjBywZk4eJSv5qlefC2n/Zc4dl6jsiqhmx2aviO6fmuIsf4UprCRHlHOiNSmdL
+M2ggtqpnzoOVSZlsXvYITmnsWNxiavz1DvIbnwglngmaqeaB/0qepdRKH1BJkW8q
+9w==
+-----END CERTIFICATE-----
diff --git a/core/tests/coretests/res/raw/test1.obb b/core/tests/coretests/res/raw/test1.obb
deleted file mode 100644
index 8466588..0000000
--- a/core/tests/coretests/res/raw/test1.obb
+++ /dev/null
Binary files differ
diff --git a/core/tests/coretests/src/android/accounts/AccountManagerServiceTest.java b/core/tests/coretests/src/android/accounts/AccountManagerServiceTest.java
index 33a73b5..84c9957 100644
--- a/core/tests/coretests/src/android/accounts/AccountManagerServiceTest.java
+++ b/core/tests/coretests/src/android/accounts/AccountManagerServiceTest.java
@@ -23,6 +23,7 @@
 import android.content.pm.RegisteredServicesCacheListener;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.UserHandle;
 import android.test.AndroidTestCase;
 import android.test.IsolatedContext;
 import android.test.RenamingDelegatingContext;
@@ -196,7 +197,9 @@
             mServices.add(new ServiceInfo<AuthenticatorDescription>(d2, null, 0));
         }
 
-        public ServiceInfo<AuthenticatorDescription> getServiceInfo(AuthenticatorDescription type) {
+        @Override
+        public ServiceInfo<AuthenticatorDescription> getServiceInfo(
+                AuthenticatorDescription type, int userId) {
             for (ServiceInfo<AuthenticatorDescription> service : mServices) {
                 if (service.type.equals(type)) {
                     return service;
@@ -205,21 +208,25 @@
             return null;
         }
 
-        public Collection<ServiceInfo<AuthenticatorDescription>> getAllServices() {
+        @Override
+        public Collection<ServiceInfo<AuthenticatorDescription>> getAllServices(int userId) {
             return mServices;
         }
 
-        public void dump(final FileDescriptor fd, final PrintWriter fout, final String[] args) {
+        @Override
+        public void dump(
+                final FileDescriptor fd, final PrintWriter fout, final String[] args, int userId) {
         }
 
+        @Override
         public void setListener(
                 final RegisteredServicesCacheListener<AuthenticatorDescription> listener,
                 final Handler handler) {
         }
 
-        @Override
-        public void generateServicesMap() {
-        }
+		@Override
+		public void invalidateCache(int userId) {
+		}
     }
 
     static public class MyMockContext extends MockContext {
@@ -243,11 +250,11 @@
         }
 
         @Override
-        protected void installNotification(final int notificationId, final Notification n) {
+        protected void installNotification(final int notificationId, final Notification n, UserHandle user) {
         }
 
         @Override
-        protected void cancelNotification(final int id) {
+        protected void cancelNotification(final int id, UserHandle user) {
         }
     }
 }
diff --git a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
index b2075ae..af2a944 100644
--- a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
+++ b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
@@ -29,6 +29,7 @@
 import android.net.wifi.WifiManager;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
 import android.os.ParcelFileDescriptor.AutoCloseInputStream;
 import android.os.SystemClock;
 import android.provider.Settings;
@@ -553,7 +554,7 @@
         int state = enable ? 1 : 0;
 
         // Change the system setting
-        Settings.System.putInt(mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON,
                 state);
 
         String timeoutMessage = "Timed out waiting for airplane mode to be " +
@@ -561,8 +562,8 @@
 
         // wait for airplane mode to change state
         int currentWaitTime = 0;
-        while (Settings.System.getInt(mContext.getContentResolver(),
-                Settings.System.AIRPLANE_MODE_ON, -1) != state) {
+        while (Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, -1) != state) {
             timeoutWait(currentWaitTime, DEFAULT_WAIT_POLL_TIME, DEFAULT_MAX_WAIT_TIME,
                     timeoutMessage);
         }
@@ -570,7 +571,7 @@
         // Post the intent
         Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
         intent.putExtra("state", true);
-        mContext.sendBroadcast(intent);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     /**
diff --git a/core/tests/coretests/src/android/app/InstrumentationTest.java b/core/tests/coretests/src/android/app/InstrumentationTest.java
new file mode 100644
index 0000000..ee3834c
--- /dev/null
+++ b/core/tests/coretests/src/android/app/InstrumentationTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.os.Bundle;
+import android.test.InstrumentationTestCase;
+
+public class InstrumentationTest extends InstrumentationTestCase {
+
+    /**
+     * Simple stress test for {@link Instrumentation#sendStatus(int, android.os.Bundle)}, to
+     * ensure it can handle many rapid calls without failing.
+     */
+    public void testSendStatus() {
+        for (int i = 0; i < 10000; i++) {
+            Bundle bundle = new Bundle();
+            bundle.putInt("iterations", i);
+            getInstrumentation().sendStatus(-1, bundle);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/app/SearchablesTest.java b/core/tests/coretests/src/android/app/SearchablesTest.java
index 6cb31d4..4d3b144 100644
--- a/core/tests/coretests/src/android/app/SearchablesTest.java
+++ b/core/tests/coretests/src/android/app/SearchablesTest.java
@@ -71,7 +71,7 @@
      */
     public void testNonSearchable() {
         // test basic array & hashmap
-        Searchables searchables = new Searchables(mContext);
+        Searchables searchables = new Searchables(mContext, 0);
         searchables.buildSearchableList();
 
         // confirm that we return null for non-searchy activities
@@ -103,7 +103,7 @@
 
         // build item list with real-world source data
         mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_PASSTHROUGH);
-        Searchables searchables = new Searchables(mockContext);
+        Searchables searchables = new Searchables(mockContext, 0);
         searchables.buildSearchableList();
         // tests with "real" searchables (deprecate, this should be a unit test)
         ArrayList<SearchableInfo> searchablesList = searchables.getSearchablesList();
@@ -122,7 +122,7 @@
         MyMockContext mockContext = new MyMockContext(mContext, mockPM);
 
         mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_MOCK_ZERO);
-        Searchables searchables = new Searchables(mockContext);
+        Searchables searchables = new Searchables(mockContext, 0);
         searchables.buildSearchableList();
         ArrayList<SearchableInfo> searchablesList = searchables.getSearchablesList();
         assertNotNull(searchablesList);
diff --git a/core/tests/coretests/src/android/app/activity/BroadcastTest.java b/core/tests/coretests/src/android/app/activity/BroadcastTest.java
index d527c0d..f28ba7e 100644
--- a/core/tests/coretests/src/android/app/activity/BroadcastTest.java
+++ b/core/tests/coretests/src/android/app/activity/BroadcastTest.java
@@ -26,6 +26,7 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Parcel;
+import android.os.UserHandle;
 import android.test.FlakyTest;
 import android.test.suitebuilder.annotation.Suppress;
 import android.util.Log;
@@ -304,9 +305,9 @@
         Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null);
         intent.putExtra("test", LaunchpadActivity.DATA_1);
         ActivityManagerNative.getDefault().unbroadcastIntent(null, intent,
-                Binder.getOrigCallingUser());
+                UserHandle.myUserId());
 
-        ActivityManagerNative.broadcastStickyIntent(intent, null);
+        ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.myUserId());
         addIntermediate("finished-broadcast");
 
         IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1);
@@ -318,11 +319,11 @@
     public void testClearSticky() throws Exception {
         Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null);
         intent.putExtra("test", LaunchpadActivity.DATA_1);
-        ActivityManagerNative.broadcastStickyIntent(intent, null);
+        ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.myUserId());
 
         ActivityManagerNative.getDefault().unbroadcastIntent(
                 null, new Intent(LaunchpadActivity.BROADCAST_STICKY1, null),
-                Binder.getOrigCallingUser());
+                UserHandle.myUserId());
         addIntermediate("finished-unbroadcast");
 
         IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1);
@@ -333,10 +334,10 @@
     public void testReplaceSticky() throws Exception {
         Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null);
         intent.putExtra("test", LaunchpadActivity.DATA_1);
-        ActivityManagerNative.broadcastStickyIntent(intent, null);
+        ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.myUserId());
         intent.putExtra("test", LaunchpadActivity.DATA_2);
 
-        ActivityManagerNative.broadcastStickyIntent(intent, null);
+        ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.myUserId());
         addIntermediate("finished-broadcast");
 
         IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1);
@@ -350,7 +351,7 @@
     public void testReceiveSticky() throws Exception {
         Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null);
         intent.putExtra("test", LaunchpadActivity.DATA_1);
-        ActivityManagerNative.broadcastStickyIntent(intent, null);
+        ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.myUserId());
 
         runLaunchpad(LaunchpadActivity.BROADCAST_STICKY1);
     }
@@ -360,10 +361,10 @@
     public void testReceive2Sticky() throws Exception {
         Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null);
         intent.putExtra("test", LaunchpadActivity.DATA_1);
-        ActivityManagerNative.broadcastStickyIntent(intent, null);
+        ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.myUserId());
         intent = new Intent(LaunchpadActivity.BROADCAST_STICKY2, null);
         intent.putExtra("test", LaunchpadActivity.DATA_2);
-        ActivityManagerNative.broadcastStickyIntent(intent, null);
+        ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.myUserId());
 
         runLaunchpad(LaunchpadActivity.BROADCAST_STICKY2);
     }
diff --git a/core/tests/coretests/src/android/content/ObserverNodeTest.java b/core/tests/coretests/src/android/content/ObserverNodeTest.java
index 95b8465..1acff9c 100644
--- a/core/tests/coretests/src/android/content/ObserverNodeTest.java
+++ b/core/tests/coretests/src/android/content/ObserverNodeTest.java
@@ -23,6 +23,7 @@
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.UserHandle;
 import android.test.AndroidTestCase;
 
 public class ObserverNodeTest extends AndroidTestCase {
@@ -33,6 +34,8 @@
     }
 
     public void testUri() {
+        final int myUserHandle = UserHandle.myUserId();
+
         ObserverNode root = new ObserverNode("");
         Uri[] uris = new Uri[] {
             Uri.parse("content://c/a/"),
@@ -48,21 +51,25 @@
         int[] nums = new int[] {4, 7, 1, 4, 2, 2, 3, 3};
 
         // special case
-        root.addObserverLocked(uris[0], new TestObserver().getContentObserver(), false, root, 0, 0);
+        root.addObserverLocked(uris[0], new TestObserver().getContentObserver(), false, root,
+                0, 0, myUserHandle);
         for(int i = 1; i < uris.length; i++) {
-            root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), true, root, 0, 0);
+            root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), true, root,
+                    0, 0, myUserHandle);
         }
 
         ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
 
         for (int i = nums.length - 1; i >=0; --i) {
-            root.collectObserversLocked(uris[i], 0, null, false, calls);
+            root.collectObserversLocked(uris[i], 0, null, false, myUserHandle, calls);
             assertEquals(nums[i], calls.size());
             calls.clear();
         }
     }
 
     public void testUriNotNotify() {
+        final int myUserHandle = UserHandle.myUserId();
+
         ObserverNode root = new ObserverNode("");
         Uri[] uris = new Uri[] {
             Uri.parse("content://c/"),
@@ -77,13 +84,14 @@
         int[] nums = new int[] {7, 1, 3, 3, 1, 1, 1, 1};
 
         for(int i = 0; i < uris.length; i++) {
-            root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), false, root, 0, 0);
+            root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), false, root,
+                    0, 0, myUserHandle);
         }
 
         ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
 
         for (int i = uris.length - 1; i >=0; --i) {
-            root.collectObserversLocked(uris[i], 0, null, false, calls);
+            root.collectObserversLocked(uris[i], 0, null, false, myUserHandle, calls);
             assertEquals(nums[i], calls.size());
             calls.clear();
         }
diff --git a/core/tests/coretests/src/android/content/pm/AppCacheTest.java b/core/tests/coretests/src/android/content/pm/AppCacheTest.java
index 0c31e2d..aae55e8 100755
--- a/core/tests/coretests/src/android/content/pm/AppCacheTest.java
+++ b/core/tests/coretests/src/android/content/pm/AppCacheTest.java
@@ -24,7 +24,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StatFs;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
@@ -570,7 +570,7 @@
             PackageStatsObserver observer = new PackageStatsObserver();
             //wait on observer
             synchronized(observer) {
-                getPm().getPackageSizeInfo(packageName, observer);
+                getPm().getPackageSizeInfo(packageName, UserHandle.myUserId(), observer);
                 long waitTime = 0;
                 while((!observer.isDone()) || (waitTime > MAX_WAIT_TIME) ) {
                     observer.wait(WAIT_TIME_INCR);
@@ -719,7 +719,7 @@
     File getDataDir() {
         try {
             ApplicationInfo appInfo = getPm().getApplicationInfo(mContext.getPackageName(), 0,
-                    UserId.myUserId());
+                    UserHandle.myUserId());
             return new File(appInfo.dataDir);
         } catch (RemoteException e) {
             throw new RuntimeException("Pacakge manager dead", e);
@@ -748,7 +748,7 @@
     
     @LargeTest
     public void testClearApplicationUserDataNoObserver() throws Exception {
-        getPm().clearApplicationUserData(mContext.getPackageName(), null, UserId.myUserId());
+        getPm().clearApplicationUserData(mContext.getPackageName(), null, UserHandle.myUserId());
         //sleep for 1 minute
         Thread.sleep(60*1000);
         //confirm files dont exist
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 6e1b9d6..04f8009 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -16,6 +16,8 @@
 
 package android.content.pm;
 
+import static libcore.io.OsConstants.*;
+
 import com.android.frameworks.coretests.R;
 import com.android.internal.content.PackageHelper;
 
@@ -32,9 +34,12 @@
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.IBinder;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StatFs;
+import android.os.SystemClock;
+import android.os.UserManager;
 import android.os.storage.IMountService;
 import android.os.storage.StorageListener;
 import android.os.storage.StorageManager;
@@ -52,22 +57,39 @@
 import java.io.InputStream;
 
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import libcore.io.ErrnoException;
+import libcore.io.Libcore;
+import libcore.io.StructStat;
 
 public class PackageManagerTests extends AndroidTestCase {
     private static final boolean localLOGV = true;
-    public static final String TAG="PackageManagerTests";
-    public final long MAX_WAIT_TIME = 25*1000;
-    public final long WAIT_TIME_INCR = 5*1000;
-    private static final String SECURE_CONTAINERS_PREFIX = "/mnt/asec";
+
+    public static final String TAG = "PackageManagerTests";
+
+    public final long MAX_WAIT_TIME = 25 * 1000;
+
+    public final long WAIT_TIME_INCR = 5 * 1000;
+
+    private static final String APP_LIB_DIR_PREFIX = "/data/app-lib/";
+
+    private static final String SECURE_CONTAINERS_PREFIX = "/mnt/asec/";
+
     private static final int APP_INSTALL_AUTO = PackageHelper.APP_INSTALL_AUTO;
+
     private static final int APP_INSTALL_DEVICE = PackageHelper.APP_INSTALL_INTERNAL;
+
     private static final int APP_INSTALL_SDCARD = PackageHelper.APP_INSTALL_EXTERNAL;
+
     private boolean mOrigState;
 
     void failStr(String errMsg) {
-        Log.w(TAG, "errMsg="+errMsg);
+        Log.w(TAG, "errMsg=" + errMsg);
         fail(errMsg);
     }
+
     void failStr(Exception e) {
         failStr(e.getMessage());
     }
@@ -97,10 +119,11 @@
 
     private class PackageInstallObserver extends IPackageInstallObserver.Stub {
         public int returnCode;
+
         private boolean doneFlag = false;
 
         public void packageInstalled(String packageName, int returnCode) {
-            synchronized(this) {
+            synchronized (this) {
                 this.returnCode = returnCode;
                 doneFlag = true;
                 notifyAll();
@@ -114,10 +137,15 @@
 
     abstract class GenericReceiver extends BroadcastReceiver {
         private boolean doneFlag = false;
+
         boolean received = false;
+
         Intent intent;
+
         IntentFilter filter;
+
         abstract boolean notifyNow(Intent intent);
+
         @Override
         public void onReceive(Context context, Intent intent) {
             if (notifyNow(intent)) {
@@ -179,11 +207,11 @@
         mContext.registerReceiver(receiver, receiver.filter);
         try {
             // Wait on observer
-            synchronized(observer) {
+            synchronized (observer) {
                 synchronized (receiver) {
                     getPm().installPackage(packageURI, observer, flags, null);
                     long waitTime = 0;
-                    while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
+                    while ((!observer.isDone()) && (waitTime < MAX_WAIT_TIME)) {
                         try {
                             observer.wait(WAIT_TIME_INCR);
                             waitTime += WAIT_TIME_INCR;
@@ -191,7 +219,7 @@
                             Log.i(TAG, "Interrupted during sleep", e);
                         }
                     }
-                    if(!observer.isDone()) {
+                    if (!observer.isDone()) {
                         fail("Timed out waiting for packageInstalled callback");
                     }
 
@@ -214,7 +242,7 @@
 
                     // Verify we received the broadcast
                     waitTime = 0;
-                    while((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
+                    while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {
                         try {
                             receiver.wait(WAIT_TIME_INCR);
                             waitTime += WAIT_TIME_INCR;
@@ -222,7 +250,7 @@
                             Log.i(TAG, "Interrupted during sleep", e);
                         }
                     }
-                    if(!receiver.isDone()) {
+                    if (!receiver.isDone()) {
                         fail("Timed out waiting for PACKAGE_ADDED notification");
                     }
                 }
@@ -236,10 +264,10 @@
         PackageInstallObserver observer = new PackageInstallObserver();
         try {
             // Wait on observer
-            synchronized(observer) {
+            synchronized (observer) {
                 getPm().installPackage(packageURI, observer, flags, null);
                 long waitTime = 0;
-                while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
+                while ((!observer.isDone()) && (waitTime < MAX_WAIT_TIME)) {
                     try {
                         observer.wait(WAIT_TIME_INCR);
                         waitTime += WAIT_TIME_INCR;
@@ -247,7 +275,7 @@
                         Log.i(TAG, "Interrupted during sleep", e);
                     }
                 }
-                if(!observer.isDone()) {
+                if (!observer.isDone()) {
                     fail("Timed out waiting for packageInstalled callback");
                 }
                 assertEquals(expectedResult, observer.returnCode);
@@ -280,39 +308,42 @@
         File sourceFile = new File(archiveFilePath);
         DisplayMetrics metrics = new DisplayMetrics();
         metrics.setToDefaults();
-        PackageParser.Package pkg = packageParser.parsePackage(sourceFile, archiveFilePath, metrics, 0);
+        PackageParser.Package pkg = packageParser.parsePackage(sourceFile, archiveFilePath,
+                metrics, 0);
         packageParser = null;
         return pkg;
     }
+
     private boolean checkSd(long pkgLen) {
         String status = Environment.getExternalStorageState();
         if (!status.equals(Environment.MEDIA_MOUNTED)) {
             return false;
         }
         long sdSize = -1;
-        StatFs sdStats = new StatFs(
-                Environment.getExternalStorageDirectory().getPath());
-        sdSize = (long)sdStats.getAvailableBlocks() *
-                (long)sdStats.getBlockSize();
+        StatFs sdStats = new StatFs(Environment.getExternalStorageDirectory().getPath());
+        sdSize = (long) sdStats.getAvailableBlocks() * (long) sdStats.getBlockSize();
         // TODO check for thresholds here
         return pkgLen <= sdSize;
 
     }
+
     private boolean checkInt(long pkgLen) {
         StatFs intStats = new StatFs(Environment.getDataDirectory().getPath());
-        long intSize = (long)intStats.getBlockCount() *
-                (long)intStats.getBlockSize();
-        long iSize = (long)intStats.getAvailableBlocks() *
-                (long)intStats.getBlockSize();
+        long intSize = (long) intStats.getBlockCount() * (long) intStats.getBlockSize();
+        long iSize = (long) intStats.getAvailableBlocks() * (long) intStats.getBlockSize();
         // TODO check for thresholds here?
         return pkgLen <= iSize;
     }
+
     private static final int INSTALL_LOC_INT = 1;
+
     private static final int INSTALL_LOC_SD = 2;
+
     private static final int INSTALL_LOC_ERR = -1;
+
     private int getInstallLoc(int flags, int expInstallLocation, long pkgLen) {
         // Flags explicitly over ride everything else.
-        if ((flags & PackageManager.INSTALL_EXTERNAL) != 0 ) {
+        if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
             return INSTALL_LOC_SD;
         } else if ((flags & PackageManager.INSTALL_INTERNAL) != 0) {
             return INSTALL_LOC_INT;
@@ -320,7 +351,7 @@
         // Manifest option takes precedence next
         if (expInstallLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
             if (checkSd(pkgLen)) {
-               return INSTALL_LOC_SD;
+                return INSTALL_LOC_SD;
             }
             if (checkInt(pkgLen)) {
                 return INSTALL_LOC_INT;
@@ -386,20 +417,32 @@
                 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
                     assertTrue("The application should be installed forward locked",
                             (info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
-                    assertTrue("The APK path (" + srcPath + ") should start with "
-                            + SECURE_CONTAINERS_PREFIX,
-                            srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
-                    assertTrue("The public APK path (" + publicSrcPath + ") should start with "
-                            + SECURE_CONTAINERS_PREFIX,
-                            publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
-                    assertTrue("The native library path (" + info.nativeLibraryDir
-                            + ") should start with " + SECURE_CONTAINERS_PREFIX,
-                            info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
+                    assertStartsWith("The APK path should point to the ASEC",
+                            SECURE_CONTAINERS_PREFIX, srcPath);
+                    assertStartsWith("The public APK path should point to the ASEC",
+                            SECURE_CONTAINERS_PREFIX, publicSrcPath);
+                    assertStartsWith("The native library path should point to the ASEC",
+                            SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir);
+                    try {
+                        String compatLib = new File(info.dataDir + "/lib").getCanonicalPath();
+                        assertEquals("The compatibility lib directory should be a symbolic link to "
+                                + info.nativeLibraryDir,
+                                info.nativeLibraryDir, compatLib);
+                    } catch (IOException e) {
+                        fail("compat check: Can't read " + info.dataDir + "/lib");
+                    }
                 } else {
                     assertFalse((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
                     assertEquals(srcPath, appInstallPath);
                     assertEquals(publicSrcPath, appInstallPath);
-                    assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath()));
+                    assertStartsWith("Native library should point to shared lib directory",
+                            new File(APP_LIB_DIR_PREFIX, info.packageName).getPath(),
+                            info.nativeLibraryDir);
+                    assertDirOwnerGroupPerms(
+                            "Native library directory should be owned by system:system and 0755",
+                            Process.SYSTEM_UID, Process.SYSTEM_UID,
+                            S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH,
+                            info.nativeLibraryDir);
                 }
                 assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
 
@@ -409,12 +452,11 @@
                         nativeLibDir.exists());
                 try {
                     assertEquals("Native library dir should not be a symlink",
-                            info.nativeLibraryDir,
-                            nativeLibDir.getCanonicalPath());
+                            info.nativeLibraryDir, nativeLibDir.getCanonicalPath());
                 } catch (IOException e) {
                     fail("Can't read " + nativeLibDir.getPath());
                 }
-            } else if (rLoc == INSTALL_LOC_SD){
+            } else if (rLoc == INSTALL_LOC_SD) {
                 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
                     assertTrue("The application should be installed forward locked",
                             (info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
@@ -427,14 +469,12 @@
                         (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
                 // Might need to check:
                 // ((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0)
-                assertTrue("The APK path (" + srcPath + ") should start with "
-                        + SECURE_CONTAINERS_PREFIX, srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
-                assertTrue("The public APK path (" + publicSrcPath + ") should start with "
-                        + SECURE_CONTAINERS_PREFIX,
-                        publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
-                assertTrue("The native library path (" + info.nativeLibraryDir
-                        + ") should start with " + SECURE_CONTAINERS_PREFIX,
-                        info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
+                assertStartsWith("The APK path should point to the ASEC",
+                        SECURE_CONTAINERS_PREFIX, srcPath);
+                assertStartsWith("The public APK path should point to the ASEC",
+                        SECURE_CONTAINERS_PREFIX, publicSrcPath);
+                assertStartsWith("The native library path should point to the ASEC",
+                        SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir);
 
                 // Make sure the native library in /data/data/<app>/lib is a
                 // symlink to the ASEC
@@ -443,8 +483,8 @@
                         nativeLibSymLink.exists());
                 try {
                     assertEquals(nativeLibSymLink.getPath() + " should be a symlink to "
-                            + info.nativeLibraryDir, info.nativeLibraryDir, nativeLibSymLink
-                            .getCanonicalPath());
+                            + info.nativeLibraryDir, info.nativeLibraryDir,
+                            nativeLibSymLink.getCanonicalPath());
                 } catch (IOException e) {
                     fail("Can't read " + nativeLibSymLink.getPath());
                 }
@@ -457,40 +497,116 @@
         }
     }
 
+    private void assertDirOwnerGroupPerms(String reason, int uid, int gid, int perms, String path) {
+        final StructStat stat;
+
+        try {
+            stat = Libcore.os.lstat(path);
+        } catch (ErrnoException e) {
+            throw new AssertionError(reason + "\n" + "Got: " + path + " does not exist");
+        }
+
+        StringBuilder sb = new StringBuilder();
+
+        if (!S_ISDIR(stat.st_mode)) {
+            sb.append("\nExpected type: ");
+            sb.append(S_IFDIR);
+            sb.append("\ngot type: ");
+            sb.append((stat.st_mode & S_IFMT));
+        }
+
+        if (stat.st_uid != uid) {
+            sb.append("\nExpected owner: ");
+            sb.append(uid);
+            sb.append("\nGot owner: ");
+            sb.append(stat.st_uid);
+        }
+
+        if (stat.st_gid != gid) {
+            sb.append("\nExpected group: ");
+            sb.append(gid);
+            sb.append("\nGot group: ");
+            sb.append(stat.st_gid);
+        }
+
+        if ((stat.st_mode & ~S_IFMT) != perms) {
+            sb.append("\nExpected permissions: ");
+            sb.append(Integer.toOctalString(perms));
+            sb.append("\nGot permissions: ");
+            sb.append(Integer.toOctalString(stat.st_mode & ~S_IFMT));
+        }
+
+        if (sb.length() > 0) {
+            throw new AssertionError(reason + sb.toString());
+        }
+    }
+
+    private static void assertStartsWith(String prefix, String actual) {
+        assertStartsWith("", prefix, actual);
+    }
+
+    private static void assertStartsWith(String description, String prefix, String actual) {
+        if (!actual.startsWith(prefix)) {
+            StringBuilder sb = new StringBuilder(description);
+            sb.append("\nExpected prefix: ");
+            sb.append(prefix);
+            sb.append("\n     got: ");
+            sb.append(actual);
+            sb.append('\n');
+            throw new AssertionError(sb.toString());
+        }
+    }
+
     private void assertNotInstalled(String pkgName) {
         try {
             ApplicationInfo info = getPm().getApplicationInfo(pkgName, 0);
             fail(pkgName + " shouldnt be installed");
         } catch (NameNotFoundException e) {
         }
+
+        UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        List<UserInfo> users = um.getUsers();
+        for (UserInfo user : users) {
+            String dataDir = PackageManager.getDataDirForUser(user.id, pkgName);
+            assertFalse("Application data directory should not exist: " + dataDir,
+                    new File(dataDir).exists());
+        }
     }
 
     class InstallParams {
         Uri packageURI;
+
         PackageParser.Package pkg;
+
         InstallParams(String outFileName, int rawResId) {
             this.pkg = getParsedPackage(outFileName, rawResId);
             this.packageURI = Uri.fromFile(new File(pkg.mScanPath));
         }
+
         InstallParams(PackageParser.Package pkg) {
             this.packageURI = Uri.fromFile(new File(pkg.mScanPath));
             this.pkg = pkg;
         }
+
         long getApkSize() {
             File file = new File(pkg.mScanPath);
             return file.length();
         }
     }
 
-    private InstallParams sampleInstallFromRawResource(int flags, boolean cleanUp) {
-        return installFromRawResource("install.apk", R.raw.install, flags, cleanUp,
-                false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+    private InstallParams sampleInstallFromRawResource(int flags, boolean cleanUp) throws Exception {
+        return installFromRawResource("install.apk", R.raw.install, flags, cleanUp, false, -1,
+                PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
     }
 
     static final String PERM_PACKAGE = "package";
+
     static final String PERM_DEFINED = "defined";
+
     static final String PERM_UNDEFINED = "undefined";
+
     static final String PERM_USED = "used";
+
     static final String PERM_NOTUSED = "notused";
 
     private void assertPermissions(String[] cmds) {
@@ -522,7 +638,7 @@
                         assertEquals(pi.name, cmd);
                         assertNotNull(pkgInfo);
                         boolean found = false;
-                        for (int j=0; j<pkgInfo.permissions.length && !found; j++) {
+                        for (int j = 0; j < pkgInfo.permissions.length && !found; j++) {
                             if (pkgInfo.permissions[j].name.equals(cmd)) {
                                 found = true;
                             }
@@ -541,7 +657,7 @@
                     }
                     if (pkgInfo != null) {
                         boolean found = false;
-                        for (int j=0; j<pkgInfo.permissions.length && !found; j++) {
+                        for (int j = 0; j < pkgInfo.permissions.length && !found; j++) {
                             if (pkgInfo.permissions[j].name.equals(cmd)) {
                                 found = true;
                             }
@@ -552,7 +668,7 @@
                     }
                 } else if (mode == PERM_USED || mode == PERM_NOTUSED) {
                     boolean found = false;
-                    for (int j=0; j<pkgInfo.requestedPermissions.length && !found; j++) {
+                    for (int j = 0; j < pkgInfo.requestedPermissions.length && !found; j++) {
                         if (pkgInfo.requestedPermissions[j].equals(cmd)) {
                             found = true;
                         }
@@ -561,13 +677,11 @@
                         fail("Permission not requested: " + cmd);
                     }
                     if (mode == PERM_USED) {
-                        if (pm.checkPermission(cmd, pkg)
-                                != PackageManager.PERMISSION_GRANTED) {
+                        if (pm.checkPermission(cmd, pkg) != PackageManager.PERMISSION_GRANTED) {
                             fail("Permission not granted: " + cmd);
                         }
                     } else {
-                        if (pm.checkPermission(cmd, pkg)
-                                != PackageManager.PERMISSION_DENIED) {
+                        if (pm.checkPermission(cmd, pkg) != PackageManager.PERMISSION_DENIED) {
                             fail("Permission granted: " + cmd);
                         }
                     }
@@ -590,9 +704,8 @@
      * copies it into own data directory and invokes
      * PackageManager api to install it.
      */
-    private void installFromRawResource(InstallParams ip,
-            int flags, boolean cleanUp, boolean fail, int result,
-            int expInstallLocation) {
+    private void installFromRawResource(InstallParams ip, int flags, boolean cleanUp, boolean fail,
+            int result, int expInstallLocation) throws Exception {
         PackageManager pm = mContext.getPackageManager();
         PackageParser.Package pkg = ip.pkg;
         Uri packageURI = ip.packageURI;
@@ -603,9 +716,7 @@
                         PackageManager.GET_UNINSTALLED_PACKAGES);
                 GenericReceiver receiver = new DeleteReceiver(pkg.packageName);
                 invokeDeletePackage(pkg.packageName, 0, receiver);
-            } catch (NameNotFoundException e1) {
-            } catch (Exception e) {
-                failStr(e);
+            } catch (NameNotFoundException e) {
             }
         }
         try {
@@ -632,26 +743,25 @@
      * copies it into own data directory and invokes
      * PackageManager api to install it.
      */
-    private InstallParams installFromRawResource(String outFileName,
-            int rawResId, int flags, boolean cleanUp, boolean fail, int result,
-            int expInstallLocation) {
+    private InstallParams installFromRawResource(String outFileName, int rawResId, int flags,
+            boolean cleanUp, boolean fail, int result, int expInstallLocation) throws Exception {
         InstallParams ip = new InstallParams(outFileName, rawResId);
         installFromRawResource(ip, flags, cleanUp, fail, result, expInstallLocation);
         return ip;
     }
 
     @LargeTest
-    public void testInstallNormalInternal() {
+    public void testInstallNormalInternal() throws Exception {
         sampleInstallFromRawResource(0, true);
     }
 
     @LargeTest
-    public void testInstallFwdLockedInternal() {
+    public void testInstallFwdLockedInternal() throws Exception {
         sampleInstallFromRawResource(PackageManager.INSTALL_FORWARD_LOCK, true);
     }
 
     @LargeTest
-    public void testInstallSdcard() {
+    public void testInstallSdcard() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -661,14 +771,20 @@
         sampleInstallFromRawResource(PackageManager.INSTALL_EXTERNAL, true);
     }
 
-    /* ------------------------- Test replacing packages --------------*/
+    /* ------------------------- Test replacing packages -------------- */
     class ReplaceReceiver extends GenericReceiver {
         String pkgName;
+
         final static int INVALID = -1;
+
         final static int REMOVED = 1;
+
         final static int ADDED = 2;
+
         final static int REPLACED = 3;
+
         int removed = INVALID;
+
         // for updated system apps only
         boolean update = false;
 
@@ -721,7 +837,7 @@
      * PackageManager api to install first and then replace it
      * again.
      */
-    private void sampleReplaceFromRawResource(int flags) {
+    private void sampleReplaceFromRawResource(int flags) throws Exception {
         InstallParams ip = sampleInstallFromRawResource(flags, false);
         boolean replace = ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0);
         Log.i(TAG, "replace=" + replace);
@@ -743,17 +859,17 @@
     }
 
     @LargeTest
-    public void testReplaceFailNormalInternal() {
+    public void testReplaceFailNormalInternal() throws Exception {
         sampleReplaceFromRawResource(0);
     }
 
     @LargeTest
-    public void testReplaceFailFwdLockedInternal() {
+    public void testReplaceFailFwdLockedInternal() throws Exception {
         sampleReplaceFromRawResource(PackageManager.INSTALL_FORWARD_LOCK);
     }
 
     @LargeTest
-    public void testReplaceFailSdcard() {
+    public void testReplaceFailSdcard() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -763,43 +879,72 @@
     }
 
     @LargeTest
-    public void testReplaceNormalInternal() {
+    public void testReplaceNormalInternal() throws Exception {
         sampleReplaceFromRawResource(PackageManager.INSTALL_REPLACE_EXISTING);
     }
 
     @LargeTest
-    public void testReplaceFwdLockedInternal() {
-        sampleReplaceFromRawResource(PackageManager.INSTALL_REPLACE_EXISTING |
-                PackageManager.INSTALL_FORWARD_LOCK);
+    public void testReplaceFwdLockedInternal() throws Exception {
+        sampleReplaceFromRawResource(PackageManager.INSTALL_REPLACE_EXISTING
+                | PackageManager.INSTALL_FORWARD_LOCK);
     }
 
     @LargeTest
-    public void testReplaceSdcard() {
+    public void testReplaceSdcard() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
         }
 
-        sampleReplaceFromRawResource(PackageManager.INSTALL_REPLACE_EXISTING |
-                PackageManager.INSTALL_EXTERNAL);
+        sampleReplaceFromRawResource(PackageManager.INSTALL_REPLACE_EXISTING
+                | PackageManager.INSTALL_EXTERNAL);
     }
 
-    /* -------------- Delete tests ---*/
-    class DeleteObserver extends IPackageDeleteObserver.Stub {
+    /* -------------- Delete tests --- */
+    private static class DeleteObserver extends IPackageDeleteObserver.Stub {
+        private CountDownLatch mLatch = new CountDownLatch(1);
 
-        public boolean succeeded;
-        private boolean doneFlag = false;
+        private int mReturnCode;
 
-        public boolean isDone() {
-            return doneFlag;
+        private final String mPackageName;
+
+        private String mObservedPackage;
+
+        public DeleteObserver(String packageName) {
+            mPackageName = packageName;
+        }
+
+        public boolean isSuccessful() {
+            return mReturnCode == PackageManager.DELETE_SUCCEEDED;
         }
 
         public void packageDeleted(String packageName, int returnCode) throws RemoteException {
-            synchronized(this) {
-                this.succeeded = returnCode == PackageManager.DELETE_SUCCEEDED;
-                doneFlag = true;
-                notifyAll();
+            mObservedPackage = packageName;
+
+            mReturnCode = returnCode;
+
+            mLatch.countDown();
+        }
+
+        public void waitForCompletion(long timeoutMillis) {
+            final long deadline = SystemClock.uptimeMillis() + timeoutMillis;
+
+            long waitTime = timeoutMillis;
+            while (waitTime > 0) {
+                try {
+                    boolean done = mLatch.await(waitTime, TimeUnit.MILLISECONDS);
+                    if (done) {
+                        assertEquals(mPackageName, mObservedPackage);
+                        return;
+                    }
+                } catch (InterruptedException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                }
+                waitTime = deadline - SystemClock.uptimeMillis();
             }
+
+            throw new AssertionError("Timeout waiting for package deletion");
         }
     }
 
@@ -827,53 +972,54 @@
         }
     }
 
-    public boolean invokeDeletePackage(final String pkgName, int flags,
-            GenericReceiver receiver) throws Exception {
-        DeleteObserver observer = new DeleteObserver();
-        final boolean received = false;
+    public boolean invokeDeletePackage(final String pkgName, int flags, GenericReceiver receiver)
+            throws Exception {
+        ApplicationInfo info = getPm().getApplicationInfo(pkgName,
+                PackageManager.GET_UNINSTALLED_PACKAGES);
+
         mContext.registerReceiver(receiver, receiver.filter);
         try {
-            // Wait on observer
-            synchronized(observer) {
-                synchronized (receiver) {
-                    getPm().deletePackage(pkgName, observer, flags);
-                    long waitTime = 0;
-                    while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
-                        observer.wait(WAIT_TIME_INCR);
-                        waitTime += WAIT_TIME_INCR;
-                    }
-                    if(!observer.isDone()) {
-                        throw new Exception("Timed out waiting for packageInstalled callback");
-                    }
-                    // Verify we received the broadcast
-                    waitTime = 0;
-                    while((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
-                        receiver.wait(WAIT_TIME_INCR);
-                        waitTime += WAIT_TIME_INCR;
-                    }
-                    if(!receiver.isDone()) {
-                        throw new Exception("Timed out waiting for PACKAGE_REMOVED notification");
-                    }
-                    return receiver.received;
+            DeleteObserver observer = new DeleteObserver(pkgName);
+
+            getPm().deletePackage(pkgName, observer, flags | PackageManager.DELETE_ALL_USERS);
+            observer.waitForCompletion(MAX_WAIT_TIME);
+
+            assertUninstalled(info);
+
+            // Verify we received the broadcast
+            // TODO replace this with a CountDownLatch
+            synchronized (receiver) {
+                long waitTime = 0;
+                while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {
+                    receiver.wait(WAIT_TIME_INCR);
+                    waitTime += WAIT_TIME_INCR;
+                }
+                if (!receiver.isDone()) {
+                    throw new Exception("Timed out waiting for PACKAGE_REMOVED notification");
                 }
             }
+            return receiver.received;
         } finally {
             mContext.unregisterReceiver(receiver);
         }
     }
 
-    public void deleteFromRawResource(int iFlags, int dFlags) {
+    private static void assertUninstalled(ApplicationInfo info) throws Exception {
+        File nativeLibraryFile = new File(info.nativeLibraryDir);
+        assertFalse("Native library directory should be erased", nativeLibraryFile.exists());
+    }
+
+    public void deleteFromRawResource(int iFlags, int dFlags) throws Exception {
         InstallParams ip = sampleInstallFromRawResource(iFlags, false);
-        boolean retainData = ((dFlags & PackageManager.DONT_DELETE_DATA) != 0);
+        boolean retainData = ((dFlags & PackageManager.DELETE_KEEP_DATA) != 0);
         GenericReceiver receiver = new DeleteReceiver(ip.pkg.packageName);
-        DeleteObserver observer = new DeleteObserver();
         try {
             assertTrue(invokeDeletePackage(ip.pkg.packageName, dFlags, receiver));
             ApplicationInfo info = null;
             Log.i(TAG, "okay4");
             try {
-            info = getPm().getApplicationInfo(ip.pkg.packageName,
-                    PackageManager.GET_UNINSTALLED_PACKAGES);
+                info = getPm().getApplicationInfo(ip.pkg.packageName,
+                        PackageManager.GET_UNINSTALLED_PACKAGES);
             } catch (NameNotFoundException e) {
                 info = null;
             }
@@ -893,17 +1039,17 @@
     }
 
     @LargeTest
-    public void testDeleteNormalInternal() {
+    public void testDeleteNormalInternal() throws Exception {
         deleteFromRawResource(0, 0);
     }
 
     @LargeTest
-    public void testDeleteFwdLockedInternal() {
+    public void testDeleteFwdLockedInternal() throws Exception {
         deleteFromRawResource(PackageManager.INSTALL_FORWARD_LOCK, 0);
     }
 
     @LargeTest
-    public void testDeleteSdcard() {
+    public void testDeleteSdcard() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -913,29 +1059,30 @@
     }
 
     @LargeTest
-    public void testDeleteNormalInternalRetainData() {
-        deleteFromRawResource(0, PackageManager.DONT_DELETE_DATA);
+    public void testDeleteNormalInternalRetainData() throws Exception {
+        deleteFromRawResource(0, PackageManager.DELETE_KEEP_DATA);
     }
 
     @LargeTest
-    public void testDeleteFwdLockedInternalRetainData() {
-        deleteFromRawResource(PackageManager.INSTALL_FORWARD_LOCK, PackageManager.DONT_DELETE_DATA);
+    public void testDeleteFwdLockedInternalRetainData() throws Exception {
+        deleteFromRawResource(PackageManager.INSTALL_FORWARD_LOCK, PackageManager.DELETE_KEEP_DATA);
     }
 
     @LargeTest
-    public void testDeleteSdcardRetainData() {
+    public void testDeleteSdcardRetainData() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
         }
 
-        deleteFromRawResource(PackageManager.INSTALL_EXTERNAL, PackageManager.DONT_DELETE_DATA);
+        deleteFromRawResource(PackageManager.INSTALL_EXTERNAL, PackageManager.DELETE_KEEP_DATA);
     }
 
-    /* sdcard mount/unmount tests ******/
+    /* sdcard mount/unmount tests ***** */
 
     class SdMountReceiver extends GenericReceiver {
         String pkgNames[];
+
         boolean status = true;
 
         SdMountReceiver(String[] pkgNames) {
@@ -970,6 +1117,7 @@
 
     class SdUnMountReceiver extends GenericReceiver {
         String pkgNames[];
+
         boolean status = true;
 
         SdUnMountReceiver(String[] pkgNames) {
@@ -1081,14 +1229,14 @@
         sm.registerListener(observer);
         try {
             // Wait on observer
-            synchronized(observer) {
+            synchronized (observer) {
                 getMs().unmountVolume(path, true, false);
                 long waitTime = 0;
-                while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
+                while ((!observer.isDone()) && (waitTime < MAX_WAIT_TIME)) {
                     observer.wait(WAIT_TIME_INCR);
                     waitTime += WAIT_TIME_INCR;
                 }
-                if(!observer.isDone()) {
+                if (!observer.isDone()) {
                     throw new Exception("Timed out waiting for unmount media notification");
                 }
                 return true;
@@ -1101,7 +1249,7 @@
         }
     }
 
-    private boolean mountFromRawResource() {
+    private boolean mountFromRawResource() throws Exception {
         // Install pkg on sdcard
         InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_EXTERNAL, false);
         if (localLOGV) Log.i(TAG, "Installed pkg on sdcard");
@@ -1128,7 +1276,7 @@
                 long waitTime = 0;
                 // Verify we received the broadcast
                 waitTime = 0;
-                while((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
+                while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {
                     receiver.wait(WAIT_TIME_INCR);
                     waitTime += WAIT_TIME_INCR;
                 }
@@ -1141,7 +1289,9 @@
             failStr(e);
             return false;
         } finally {
-            if (registeredReceiver) mContext.unregisterReceiver(receiver);
+            if (registeredReceiver) {
+                mContext.unregisterReceiver(receiver);
+            }
             // Restore original media state
             if (origState) {
                 mountMedia();
@@ -1159,7 +1309,7 @@
      * Make sure the installed package is available.
      */
     @LargeTest
-    public void testMountSdNormalInternal() {
+    public void testMountSdNormalInternal() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1168,19 +1318,38 @@
         assertTrue(mountFromRawResource());
     }
 
-    void cleanUpInstall(InstallParams ip) {
+    void cleanUpInstall(InstallParams ip) throws Exception {
         if (ip == null) {
             return;
         }
         Runtime.getRuntime().gc();
-        Log.i(TAG, "Deleting package : " + ip.pkg.packageName);
-        getPm().deletePackage(ip.pkg.packageName, null, 0);
-        File outFile = new File(ip.pkg.mScanPath);
-        if (outFile != null && outFile.exists()) {
-            outFile.delete();
+
+        final String packageName = ip.pkg.packageName;
+        Log.i(TAG, "Deleting package : " + packageName);
+
+        ApplicationInfo info = null;
+        try {
+            info = getPm().getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
+        } catch (NameNotFoundException ignored) {
+        }
+
+        DeleteObserver observer = new DeleteObserver(packageName);
+        getPm().deletePackage(packageName, observer, PackageManager.DELETE_ALL_USERS);
+        observer.waitForCompletion(MAX_WAIT_TIME);
+
+        try {
+            if (info != null) {
+                assertUninstalled(info);
+            }
+        } finally {
+            File outFile = new File(ip.pkg.mScanPath);
+            if (outFile != null && outFile.exists()) {
+                outFile.delete();
+            }
         }
     }
-    void cleanUpInstall(String pkgName) {
+
+    private void cleanUpInstall(String pkgName) throws Exception {
         if (pkgName == null) {
             return;
         }
@@ -1188,20 +1357,25 @@
         try {
             ApplicationInfo info = getPm().getApplicationInfo(pkgName,
                     PackageManager.GET_UNINSTALLED_PACKAGES);
+
             if (info != null) {
-                getPm().deletePackage(pkgName, null, 0);
+                DeleteObserver observer = new DeleteObserver(pkgName);
+                getPm().deletePackage(pkgName, observer, PackageManager.DELETE_ALL_USERS);
+                observer.waitForCompletion(MAX_WAIT_TIME);
+                assertUninstalled(info);
             }
-        } catch (NameNotFoundException e) {}
+        } catch (NameNotFoundException e) {
+        }
     }
 
     @LargeTest
-    public void testManifestInstallLocationInternal() {
+    public void testManifestInstallLocationInternal() throws Exception {
         installFromRawResource("install.apk", R.raw.install_loc_internal,
                 0, true, false, -1, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
     }
 
     @LargeTest
-    public void testManifestInstallLocationSdcard() {
+    public void testManifestInstallLocationSdcard() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1212,19 +1386,19 @@
     }
 
     @LargeTest
-    public void testManifestInstallLocationAuto() {
+    public void testManifestInstallLocationAuto() throws Exception {
         installFromRawResource("install.apk", R.raw.install_loc_auto,
                 0, true, false, -1, PackageInfo.INSTALL_LOCATION_AUTO);
     }
 
     @LargeTest
-    public void testManifestInstallLocationUnspecified() {
+    public void testManifestInstallLocationUnspecified() throws Exception {
         installFromRawResource("install.apk", R.raw.install_loc_unspecified,
                 0, true, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
     }
 
     @LargeTest
-    public void testManifestInstallLocationFwdLockedFlagSdcard() {
+    public void testManifestInstallLocationFwdLockedFlagSdcard() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1237,15 +1411,14 @@
     }
 
     @LargeTest
-    public void testManifestInstallLocationFwdLockedSdcard() {
+    public void testManifestInstallLocationFwdLockedSdcard() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
         }
 
         installFromRawResource("install.apk", R.raw.install_loc_sdcard,
-                PackageManager.INSTALL_FORWARD_LOCK, true, false,
-                -1,
+                PackageManager.INSTALL_FORWARD_LOCK, true, false, -1,
                 PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
     }
 
@@ -1255,7 +1428,7 @@
      * the old install location.
      */
     @LargeTest
-    public void testReplaceFlagInternalSdcard() {
+    public void testReplaceFlagInternalSdcard() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1282,7 +1455,7 @@
      * install location is retained.
      */
     @LargeTest
-    public void testReplaceFlagSdcardInternal() {
+    public void testReplaceFlagSdcardInternal() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1304,7 +1477,7 @@
     }
 
     @LargeTest
-    public void testManifestInstallLocationReplaceInternalSdcard() {
+    public void testManifestInstallLocationReplaceInternalSdcard() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1332,7 +1505,7 @@
     }
 
     @LargeTest
-    public void testManifestInstallLocationReplaceSdcardInternal() {
+    public void testManifestInstallLocationReplaceSdcardInternal() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1360,9 +1533,13 @@
 
     class MoveReceiver extends GenericReceiver {
         String pkgName;
+
         final static int INVALID = -1;
+
         final static int REMOVED = 1;
+
         final static int ADDED = 2;
+
         int removed = INVALID;
 
         MoveReceiver(String pkgName) {
@@ -1406,17 +1583,21 @@
 
     private class PackageMoveObserver extends IPackageMoveObserver.Stub {
         public int returnCode;
+
         private boolean doneFlag = false;
+
         public String packageName;
+
         public PackageMoveObserver(String pkgName) {
             packageName = pkgName;
         }
+
         public void packageMoved(String packageName, int returnCode) {
             Log.i("DEBUG_MOVE::", "pkg = " + packageName + ", " + "ret = " + returnCode);
             if (!packageName.equals(this.packageName)) {
                 return;
             }
-            synchronized(this) {
+            synchronized (this) {
                 this.returnCode = returnCode;
                 doneFlag = true;
                 notifyAll();
@@ -1428,22 +1609,22 @@
         }
     }
 
-    public boolean invokeMovePackage(String pkgName, int flags,
-            GenericReceiver receiver) throws Exception {
+    public boolean invokeMovePackage(String pkgName, int flags, GenericReceiver receiver)
+            throws Exception {
         PackageMoveObserver observer = new PackageMoveObserver(pkgName);
         final boolean received = false;
         mContext.registerReceiver(receiver, receiver.filter);
         try {
             // Wait on observer
-            synchronized(observer) {
+            synchronized (observer) {
                 synchronized (receiver) {
                     getPm().movePackage(pkgName, observer, flags);
                     long waitTime = 0;
-                    while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
+                    while ((!observer.isDone()) && (waitTime < MAX_WAIT_TIME)) {
                         observer.wait(WAIT_TIME_INCR);
                         waitTime += WAIT_TIME_INCR;
                     }
-                    if(!observer.isDone()) {
+                    if (!observer.isDone()) {
                         throw new Exception("Timed out waiting for pkgmove callback");
                     }
                     if (observer.returnCode != PackageManager.MOVE_SUCCEEDED) {
@@ -1451,11 +1632,11 @@
                     }
                     // Verify we received the broadcast
                     waitTime = 0;
-                    while((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
+                    while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {
                         receiver.wait(WAIT_TIME_INCR);
                         waitTime += WAIT_TIME_INCR;
                     }
-                    if(!receiver.isDone()) {
+                    if (!receiver.isDone()) {
                         throw new Exception("Timed out waiting for MOVE notifications");
                     }
                     return receiver.received;
@@ -1465,18 +1646,19 @@
             mContext.unregisterReceiver(receiver);
         }
     }
+
     private boolean invokeMovePackageFail(String pkgName, int flags, int errCode) throws Exception {
         PackageMoveObserver observer = new PackageMoveObserver(pkgName);
         try {
             // Wait on observer
-            synchronized(observer) {
+            synchronized (observer) {
                 getPm().movePackage(pkgName, observer, flags);
                 long waitTime = 0;
-                while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
+                while ((!observer.isDone()) && (waitTime < MAX_WAIT_TIME)) {
                     observer.wait(WAIT_TIME_INCR);
                     waitTime += WAIT_TIME_INCR;
                 }
-                if(!observer.isDone()) {
+                if (!observer.isDone()) {
                     throw new Exception("Timed out waiting for pkgmove callback");
                 }
                 assertEquals(errCode, observer.returnCode);
@@ -1489,16 +1671,18 @@
     private int getDefaultInstallLoc() {
         int origDefaultLoc = PackageInfo.INSTALL_LOCATION_AUTO;
         try {
-            origDefaultLoc = Settings.System.getInt(mContext.getContentResolver(), Settings.Secure.DEFAULT_INSTALL_LOCATION);
+            origDefaultLoc = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.DEFAULT_INSTALL_LOCATION);
         } catch (SettingNotFoundException e1) {
         }
         return origDefaultLoc;
     }
 
     private void setInstallLoc(int loc) {
-        Settings.System.putInt(mContext.getContentResolver(),
-                Settings.Secure.DEFAULT_INSTALL_LOCATION, loc);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.DEFAULT_INSTALL_LOCATION, loc);
     }
+
     /*
      * Tests for moving apps between internal and external storage
      */
@@ -1509,9 +1693,8 @@
      * again.
      */
 
-    private void moveFromRawResource(String outFileName,
-            int rawResId, int installFlags, int moveFlags, boolean cleanUp,
-            boolean fail, int result) {
+    private void moveFromRawResource(String outFileName, int rawResId, int installFlags,
+            int moveFlags, boolean cleanUp, boolean fail, int result) throws Exception {
         int origDefaultLoc = getDefaultInstallLoc();
         InstallParams ip = null;
         try {
@@ -1528,8 +1711,7 @@
             } else {
                 // Create receiver based on expRetCode
                 MoveReceiver receiver = new MoveReceiver(ip.pkg.packageName);
-                boolean retCode = invokeMovePackage(ip.pkg.packageName, moveFlags,
-                        receiver);
+                boolean retCode = invokeMovePackage(ip.pkg.packageName, moveFlags, receiver);
                 assertTrue(retCode);
                 ApplicationInfo info = getPm().getApplicationInfo(ip.pkg.packageName, 0);
                 assertNotNull("ApplicationInfo for recently installed application should exist",
@@ -1537,16 +1719,16 @@
                 if ((moveFlags & PackageManager.MOVE_INTERNAL) != 0) {
                     assertTrue("ApplicationInfo.FLAG_EXTERNAL_STORAGE flag should NOT be set",
                             (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0);
-                    assertTrue("ApplicationInfo.nativeLibraryDir should start with " + info.dataDir,
-                            info.nativeLibraryDir.startsWith(info.dataDir));
-                } else if ((moveFlags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0){
+                    assertStartsWith("Native library dir should be in dataDir",
+                            info.dataDir, info.nativeLibraryDir);
+                } else if ((moveFlags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0) {
                     assertTrue("ApplicationInfo.FLAG_EXTERNAL_STORAGE flag should be set",
                             (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
-                    assertTrue("ApplicationInfo.nativeLibraryDir should start with " + SECURE_CONTAINERS_PREFIX,
-                            info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
+                    assertStartsWith("Native library dir should point to ASEC",
+                            SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir);
                     final File nativeLibSymLink = new File(info.dataDir, "lib");
-                    assertTrue("The data directory should have a 'lib' symlink that points to the ASEC container",
-                            nativeLibSymLink.getCanonicalPath().startsWith(SECURE_CONTAINERS_PREFIX));
+                    assertStartsWith("The data directory should have a 'lib' symlink that points to the ASEC container",
+                            SECURE_CONTAINERS_PREFIX, nativeLibSymLink.getCanonicalPath());
                 }
             }
         } catch (NameNotFoundException e) {
@@ -1561,15 +1743,16 @@
             setInstallLoc(origDefaultLoc);
         }
     }
+
     private void sampleMoveFromRawResource(int installFlags, int moveFlags, boolean fail,
-            int result) {
+            int result) throws Exception {
         moveFromRawResource("install.apk",
                 R.raw.install, installFlags, moveFlags, true,
                 fail, result);
     }
 
     @LargeTest
-    public void testMoveAppInternalToExternal() {
+    public void testMoveAppInternalToExternal() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1583,7 +1766,7 @@
     }
 
     @LargeTest
-    public void testMoveAppInternalToInternal() {
+    public void testMoveAppInternalToInternal() throws Exception {
         int installFlags = PackageManager.INSTALL_INTERNAL;
         int moveFlags = PackageManager.MOVE_INTERNAL;
         boolean fail = true;
@@ -1592,7 +1775,7 @@
     }
 
     @LargeTest
-    public void testMoveAppExternalToExternal() {
+    public void testMoveAppExternalToExternal() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1606,7 +1789,7 @@
     }
 
     @LargeTest
-    public void testMoveAppExternalToInternal() {
+    public void testMoveAppExternalToInternal() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1620,7 +1803,7 @@
     }
 
     @LargeTest
-    public void testMoveAppForwardLocked() {
+    public void testMoveAppForwardLocked() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1634,7 +1817,7 @@
     }
 
     @LargeTest
-    public void testMoveAppFailInternalToExternalDelete() {
+    public void testMoveAppFailInternalToExternalDelete() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1656,7 +1839,7 @@
                     false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
             // Delete the package now retaining data.
             GenericReceiver receiver = new DeleteReceiver(ip.pkg.packageName);
-            invokeDeletePackage(ip.pkg.packageName, PackageManager.DONT_DELETE_DATA, receiver);
+            invokeDeletePackage(ip.pkg.packageName, PackageManager.DELETE_KEEP_DATA, receiver);
             assertTrue(invokeMovePackageFail(ip.pkg.packageName, moveFlags, result));
         } catch (Exception e) {
             failStr(e);
@@ -1674,7 +1857,7 @@
      * and package installed on sdcard via package manager flag.
      */
     @LargeTest
-    public void testInstallSdcardUnmount() {
+    public void testInstallSdcardUnmount() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1704,7 +1887,7 @@
      * on sdcard. Make sure it gets installed on internal flash.
      */
     @LargeTest
-    public void testInstallManifestSdcardUnmount() {
+    public void testInstallManifestSdcardUnmount() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1727,22 +1910,22 @@
         }
     }
 
-   /*---------- Recommended install location tests ----*/
-   /* Precedence: FlagManifestExistingUser
-    * PrecedenceSuffixes:
-    * Flag : FlagI, FlagE, FlagF
-    * I - internal, E - external, F - forward locked, Flag suffix absent if not using any option.
-    * Manifest: ManifestI, ManifestE, ManifestA, Manifest suffix absent if not using any option.
-    * Existing: Existing suffix absent if not existing.
-    * User: UserI, UserE, UserA, User suffix absent if not existing.
-    *
-    */
+    /*---------- Recommended install location tests ----*/
+    /*
+     * PrecedenceSuffixes:
+     * Flag : FlagI, FlagE, FlagF
+     * I - internal, E - external, F - forward locked, Flag suffix absent if not using any option.
+     * Manifest: ManifestI, ManifestE, ManifestA, Manifest suffix absent if not using any option.
+     * Existing: Existing suffix absent if not existing.
+     * User: UserI, UserE, UserA, User suffix absent if not existing.
+     *
+     */
 
     /*
      * Install an app on internal flash
      */
     @LargeTest
-    public void testFlagI() {
+    public void testFlagI() throws Exception {
         sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, true);
     }
 
@@ -1750,7 +1933,7 @@
      * Install an app on sdcard.
      */
     @LargeTest
-    public void testFlagE() {
+    public void testFlagE() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1763,7 +1946,7 @@
      * Install an app forward-locked.
      */
     @LargeTest
-    public void testFlagF() {
+    public void testFlagF() throws Exception {
         sampleInstallFromRawResource(PackageManager.INSTALL_FORWARD_LOCK, true);
     }
 
@@ -1771,7 +1954,7 @@
      * Install an app with both internal and external flags set. should fail
      */
     @LargeTest
-    public void testFlagIE() {
+    public void testFlagIE() throws Exception {
         installFromRawResource("install.apk", R.raw.install,
                 PackageManager.INSTALL_EXTERNAL | PackageManager.INSTALL_INTERNAL,
                 false,
@@ -1783,7 +1966,7 @@
      * Install an app with both internal and forward-lock flags set.
      */
     @LargeTest
-    public void testFlagIF() {
+    public void testFlagIF() throws Exception {
         sampleInstallFromRawResource(PackageManager.INSTALL_FORWARD_LOCK
                 | PackageManager.INSTALL_INTERNAL, true);
     }
@@ -1792,7 +1975,7 @@
      * Install an app with both external and forward-lock flags set.
      */
     @LargeTest
-    public void testFlagEF() {
+    public void testFlagEF() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1807,7 +1990,7 @@
      * lock. Should fail.
      */
     @LargeTest
-    public void testFlagIEF() {
+    public void testFlagIEF() throws Exception {
         installFromRawResource("install.apk", R.raw.install,
                 PackageManager.INSTALL_FORWARD_LOCK | PackageManager.INSTALL_INTERNAL |
                 PackageManager.INSTALL_EXTERNAL,
@@ -1816,66 +1999,66 @@
                 PackageInfo.INSTALL_LOCATION_AUTO);
     }
 
-   /*
-    * Install an app with both internal and manifest option set.
-    * should install on internal.
-    */
-   @LargeTest
-   public void testFlagIManifestI() {
-       installFromRawResource("install.apk", R.raw.install_loc_internal,
-               PackageManager.INSTALL_INTERNAL,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
-   }
-   /*
-    * Install an app with both internal and manifest preference for
-    * preferExternal. Should install on internal.
-    */
-   @LargeTest
-   public void testFlagIManifestE() {
-       installFromRawResource("install.apk", R.raw.install_loc_sdcard,
-               PackageManager.INSTALL_INTERNAL,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
-   }
-   /*
-    * Install an app with both internal and manifest preference for
-    * auto. should install internal.
-    */
-   @LargeTest
-   public void testFlagIManifestA() {
-       installFromRawResource("install.apk", R.raw.install_loc_auto,
-               PackageManager.INSTALL_INTERNAL,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
-   }
-   /*
-    * Install an app with both external and manifest option set.
-    * should install externally.
-    */
-   @LargeTest
-   public void testFlagEManifestI() {
+    /*
+     * Install an app with both internal and manifest option set.
+     * should install on internal.
+     */
+    @LargeTest
+    public void testFlagIManifestI() throws Exception {
+        installFromRawResource("install.apk", R.raw.install_loc_internal,
+                PackageManager.INSTALL_INTERNAL,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+    }
+    /*
+     * Install an app with both internal and manifest preference for
+     * preferExternal. Should install on internal.
+     */
+    @LargeTest
+    public void testFlagIManifestE() throws Exception {
+        installFromRawResource("install.apk", R.raw.install_loc_sdcard,
+                PackageManager.INSTALL_INTERNAL,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+    }
+    /*
+     * Install an app with both internal and manifest preference for
+     * auto. should install internal.
+     */
+    @LargeTest
+    public void testFlagIManifestA() throws Exception {
+        installFromRawResource("install.apk", R.raw.install_loc_auto,
+                PackageManager.INSTALL_INTERNAL,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+    }
+    /*
+     * Install an app with both external and manifest option set.
+     * should install externally.
+     */
+    @LargeTest
+    public void testFlagEManifestI() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
         }
 
-       installFromRawResource("install.apk", R.raw.install_loc_internal,
-               PackageManager.INSTALL_EXTERNAL,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
-   }
+        installFromRawResource("install.apk", R.raw.install_loc_internal,
+                PackageManager.INSTALL_EXTERNAL,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+    }
 
-   /*
-    * Install an app with both external and manifest preference for
-    * preferExternal. Should install externally.
-    */
-   @LargeTest
-   public void testFlagEManifestE() {
+    /*
+     * Install an app with both external and manifest preference for
+     * preferExternal. Should install externally.
+     */
+    @LargeTest
+    public void testFlagEManifestE() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1893,7 +2076,7 @@
      * auto. should install on external media.
      */
     @LargeTest
-    public void testFlagEManifestA() {
+    public void testFlagEManifestA() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1911,7 +2094,7 @@
      * internal. should install internally.
      */
     @LargeTest
-    public void testFlagFManifestI() {
+    public void testFlagFManifestI() throws Exception {
         installFromRawResource("install.apk", R.raw.install_loc_internal,
                 PackageManager.INSTALL_FORWARD_LOCK,
                 true,
@@ -1924,7 +2107,7 @@
      * preferExternal. Should install externally.
      */
     @LargeTest
-    public void testFlagFManifestE() {
+    public void testFlagFManifestE() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1942,7 +2125,7 @@
      * should install externally.
      */
     @LargeTest
-    public void testFlagFManifestA() {
+    public void testFlagFManifestA() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -1955,7 +2138,8 @@
                 PackageInfo.INSTALL_LOCATION_AUTO);
     }
 
-    /* The following test functions verify install location for existing apps.
+    /*
+     * The following test functions verify install location for existing apps.
      * ie existing app can be installed internally or externally. If install
      * flag is explicitly set it should override current location. If manifest location
      * is set, that should over ride current location too. if not the existing install
@@ -1963,7 +2147,7 @@
      * testFlagI/E/F/ExistingI/E -
      */
     @LargeTest
-    public void testFlagIExistingI() {
+    public void testFlagIExistingI() throws Exception {
         int iFlags = PackageManager.INSTALL_INTERNAL;
         int rFlags = PackageManager.INSTALL_INTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
         // First install.
@@ -1981,7 +2165,7 @@
     }
 
     @LargeTest
-    public void testFlagIExistingE() {
+    public void testFlagIExistingE() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2004,7 +2188,7 @@
     }
 
     @LargeTest
-    public void testFlagEExistingI() {
+    public void testFlagEExistingI() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2027,7 +2211,7 @@
     }
 
     @LargeTest
-    public void testFlagEExistingE() {
+    public void testFlagEExistingE() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2050,7 +2234,7 @@
     }
 
     @LargeTest
-    public void testFlagFExistingI() {
+    public void testFlagFExistingI() throws Exception {
         int iFlags = PackageManager.INSTALL_INTERNAL;
         int rFlags = PackageManager.INSTALL_FORWARD_LOCK | PackageManager.INSTALL_REPLACE_EXISTING;
         // First install.
@@ -2068,7 +2252,7 @@
     }
 
     @LargeTest
-    public void testFlagFExistingE() {
+    public void testFlagFExistingE() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2098,7 +2282,7 @@
      * TODO out of memory fall back behaviour.
      */
     @LargeTest
-    public void testManifestI() {
+    public void testManifestI() throws Exception {
         installFromRawResource("install.apk", R.raw.install_loc_internal,
                 0,
                 true,
@@ -2107,7 +2291,7 @@
     }
 
     @LargeTest
-    public void testManifestE() {
+    public void testManifestE() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2121,7 +2305,7 @@
     }
 
     @LargeTest
-    public void testManifestA() {
+    public void testManifestA() throws Exception {
         installFromRawResource("install.apk", R.raw.install_loc_auto,
                 0,
                 true,
@@ -2137,7 +2321,7 @@
      * testManifestI/E/AExistingI/E
      */
     @LargeTest
-    public void testManifestIExistingI() {
+    public void testManifestIExistingI() throws Exception {
         int iFlags = PackageManager.INSTALL_INTERNAL;
         int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
         // First install.
@@ -2155,7 +2339,7 @@
     }
 
     @LargeTest
-    public void testManifestIExistingE() {
+    public void testManifestIExistingE() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2178,7 +2362,7 @@
     }
 
     @LargeTest
-    public void testManifestEExistingI() {
+    public void testManifestEExistingI() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2201,7 +2385,7 @@
     }
 
     @LargeTest
-    public void testManifestEExistingE() {
+    public void testManifestEExistingE() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2224,7 +2408,7 @@
     }
 
     @LargeTest
-    public void testManifestAExistingI() {
+    public void testManifestAExistingI() throws Exception {
         int iFlags = PackageManager.INSTALL_INTERNAL;
         int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
         // First install.
@@ -2242,7 +2426,7 @@
     }
 
     @LargeTest
-    public void testManifestAExistingE() {
+    public void testManifestAExistingE() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2264,55 +2448,56 @@
                 PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
     }
 
-   /*
-    * The following set of tests check install location for existing
-    * application based on user setting.
-    */
-   private int getExpectedInstallLocation(int userSetting) {
-       int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
-       boolean enable = getUserSettingSetInstallLocation();
-       if (enable) {
-           if (userSetting == PackageHelper.APP_INSTALL_AUTO) {
-               iloc = PackageInfo.INSTALL_LOCATION_AUTO;
-           } else if (userSetting == PackageHelper.APP_INSTALL_EXTERNAL) {
-               iloc = PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL;
-           } else if (userSetting == PackageHelper.APP_INSTALL_INTERNAL) {
-               iloc = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
-           }
-       }
-       return iloc;
-   }
-   private void setExistingXUserX(int userSetting, int iFlags, int iloc) {
-       int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
-       // First install.
-       installFromRawResource("install.apk", R.raw.install,
-               iFlags,
-               false,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
-       int origSetting = getDefaultInstallLoc();
-       try {
-           // Set user setting
-           setInstallLoc(userSetting);
-           // Replace now
-           installFromRawResource("install.apk", R.raw.install,
-                   rFlags,
-                   true,
-                   false, -1,
-                   iloc);
-       } finally {
-           setInstallLoc(origSetting);
-       }
-   }
-   @LargeTest
-   public void testExistingIUserI() {
-       int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
-       int iFlags = PackageManager.INSTALL_INTERNAL;
-       setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
-   }
+    /*
+     * The following set of tests check install location for existing
+     * application based on user setting.
+     */
+    private int getExpectedInstallLocation(int userSetting) {
+        int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+        boolean enable = getUserSettingSetInstallLocation();
+        if (enable) {
+            if (userSetting == PackageHelper.APP_INSTALL_AUTO) {
+                iloc = PackageInfo.INSTALL_LOCATION_AUTO;
+            } else if (userSetting == PackageHelper.APP_INSTALL_EXTERNAL) {
+                iloc = PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL;
+            } else if (userSetting == PackageHelper.APP_INSTALL_INTERNAL) {
+                iloc = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
+            }
+        }
+        return iloc;
+    }
+
+    private void setExistingXUserX(int userSetting, int iFlags, int iloc) throws Exception {
+        int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+        // First install.
+        installFromRawResource("install.apk", R.raw.install,
+                iFlags,
+                false,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+        int origSetting = getDefaultInstallLoc();
+        try {
+            // Set user setting
+            setInstallLoc(userSetting);
+            // Replace now
+            installFromRawResource("install.apk", R.raw.install,
+                    rFlags,
+                    true,
+                    false, -1,
+                    iloc);
+        } finally {
+            setInstallLoc(origSetting);
+        }
+    }
+    @LargeTest
+    public void testExistingIUserI() throws Exception {
+        int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
+        int iFlags = PackageManager.INSTALL_INTERNAL;
+        setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+    }
 
     @LargeTest
-    public void testExistingIUserE() {
+    public void testExistingIUserE() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2323,15 +2508,15 @@
         setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
     }
 
-   @LargeTest
-   public void testExistingIUserA() {
-       int userSetting = PackageHelper.APP_INSTALL_AUTO;
-       int iFlags = PackageManager.INSTALL_INTERNAL;
-       setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
-   }
+    @LargeTest
+    public void testExistingIUserA() throws Exception {
+        int userSetting = PackageHelper.APP_INSTALL_AUTO;
+        int iFlags = PackageManager.INSTALL_INTERNAL;
+        setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+    }
 
     @LargeTest
-    public void testExistingEUserI() {
+    public void testExistingEUserI() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2343,7 +2528,7 @@
     }
 
     @LargeTest
-    public void testExistingEUserE() {
+    public void testExistingEUserE() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2355,7 +2540,7 @@
     }
 
     @LargeTest
-    public void testExistingEUserA() {
+    public void testExistingEUserA() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2366,52 +2551,53 @@
         setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
     }
 
-   /*
-    * The following set of tests verify that the user setting defines
-    * the install location.
-    *
-    */
-   private boolean getUserSettingSetInstallLocation() {
-       try {
-           return Settings.System.getInt(mContext.getContentResolver(), Settings.Secure.SET_INSTALL_LOCATION) != 0;
+    /*
+     * The following set of tests verify that the user setting defines
+     * the install location.
+     *
+     */
+    private boolean getUserSettingSetInstallLocation() {
+        try {
+            return Settings.Global.getInt(
+                    mContext.getContentResolver(), Settings.Global.SET_INSTALL_LOCATION) != 0;
+        } catch (SettingNotFoundException e1) {
+        }
+        return false;
+    }
 
-       } catch (SettingNotFoundException e1) {
-       }
-       return false;
-   }
+    private void setUserSettingSetInstallLocation(boolean value) {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.SET_INSTALL_LOCATION, value ? 1 : 0);
+    }
 
-   private void setUserSettingSetInstallLocation(boolean value) {
-       Settings.System.putInt(mContext.getContentResolver(),
-               Settings.Secure.SET_INSTALL_LOCATION, value ? 1 : 0);
-   }
-   private void setUserX(boolean enable, int userSetting, int iloc) {
-       boolean origUserSetting = getUserSettingSetInstallLocation();
-       int origSetting = getDefaultInstallLoc();
-       try {
-           setUserSettingSetInstallLocation(enable);
-           // Set user setting
-           setInstallLoc(userSetting);
-           // Replace now
-           installFromRawResource("install.apk", R.raw.install,
-                   0,
-                   true,
-                   false, -1,
-                   iloc);
-       } finally {
-           // Restore original setting
-           setUserSettingSetInstallLocation(origUserSetting);
-           setInstallLoc(origSetting);
-       }
-   }
-   @LargeTest
-   public void testUserI() {
-       int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
-       int iloc = getExpectedInstallLocation(userSetting);
-       setUserX(true, userSetting, iloc);
-   }
+    private void setUserX(boolean enable, int userSetting, int iloc) throws Exception {
+        boolean origUserSetting = getUserSettingSetInstallLocation();
+        int origSetting = getDefaultInstallLoc();
+        try {
+            setUserSettingSetInstallLocation(enable);
+            // Set user setting
+            setInstallLoc(userSetting);
+            // Replace now
+            installFromRawResource("install.apk", R.raw.install,
+                    0,
+                    true,
+                    false, -1,
+                    iloc);
+        } finally {
+            // Restore original setting
+            setUserSettingSetInstallLocation(origUserSetting);
+            setInstallLoc(origSetting);
+        }
+    }
+    @LargeTest
+    public void testUserI() throws Exception {
+        int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
+        int iloc = getExpectedInstallLocation(userSetting);
+        setUserX(true, userSetting, iloc);
+    }
 
     @LargeTest
-    public void testUserE() {
+    public void testUserE() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2422,25 +2608,26 @@
         setUserX(true, userSetting, iloc);
     }
 
-   @LargeTest
-   public void testUserA() {
-       int userSetting = PackageHelper.APP_INSTALL_AUTO;
-       int iloc = getExpectedInstallLocation(userSetting);
-       setUserX(true, userSetting, iloc);
-   }
-   /*
-    * The following set of tests turn on/off the basic
-    * user setting for turning on install location.
-    */
-   @LargeTest
-   public void testUserPrefOffUserI() {
-       int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
-       int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
-       setUserX(false, userSetting, iloc);
-   }
+    @LargeTest
+    public void testUserA() throws Exception {
+        int userSetting = PackageHelper.APP_INSTALL_AUTO;
+        int iloc = getExpectedInstallLocation(userSetting);
+        setUserX(true, userSetting, iloc);
+    }
+
+    /*
+     * The following set of tests turn on/off the basic
+     * user setting for turning on install location.
+     */
+    @LargeTest
+    public void testUserPrefOffUserI() throws Exception {
+        int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
+        int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+        setUserX(false, userSetting, iloc);
+    }
 
     @LargeTest
-    public void testUserPrefOffUserE() {
+    public void testUserPrefOffUserE() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2451,12 +2638,12 @@
         setUserX(false, userSetting, iloc);
     }
 
-   @LargeTest
-   public void testUserPrefOffA() {
-       int userSetting = PackageHelper.APP_INSTALL_AUTO;
-       int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
-       setUserX(false, userSetting, iloc);
-   }
+    @LargeTest
+    public void testUserPrefOffA() throws Exception {
+        int userSetting = PackageHelper.APP_INSTALL_AUTO;
+        int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+        setUserX(false, userSetting, iloc);
+    }
 
     static final String BASE_PERMISSIONS_DEFINED[] = new String[] {
         PERM_PACKAGE, "com.android.unit_tests.install_decl_perm",
@@ -2503,7 +2690,7 @@
      * Ensure that permissions are properly declared.
      */
     @LargeTest
-    public void testInstallDeclaresPermissions() {
+    public void testInstallDeclaresPermissions() throws Exception {
         InstallParams ip = null;
         InstallParams ip2 = null;
         try {
@@ -2532,7 +2719,7 @@
             GenericReceiver receiver = new DeleteReceiver(ip.pkg.packageName);
 
             try {
-                invokeDeletePackage(ip.pkg.packageName, PackageManager.DONT_DELETE_DATA, receiver);
+                invokeDeletePackage(ip.pkg.packageName, PackageManager.DELETE_KEEP_DATA, receiver);
             } catch (Exception e) {
                 failStr(e);
             }
@@ -2629,7 +2816,7 @@
      * Ensure that permissions are properly declared.
      */
     @LargeTest
-    public void testInstallOnSdPermissionsUnmount() {
+    public void testInstallOnSdPermissionsUnmount() throws Exception {
         InstallParams ip = null;
         boolean origMediaState = checkMediaState(Environment.MEDIA_MOUNTED);
         try {
@@ -2661,7 +2848,7 @@
      * naming convention for secure containers.
      */
     @LargeTest
-    public void testInstallSdcardStaleContainer() {
+    public void testInstallSdcardStaleContainer() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2710,7 +2897,7 @@
      * and verified that the re-installation on internal storage takes precedence.
      */
     @LargeTest
-    public void testInstallSdcardStaleContainerReinstall() {
+    public void testInstallSdcardStaleContainerReinstall() throws Exception {
         // Do not run on devices with emulated external storage.
         if (Environment.isExternalStorageEmulated()) {
             return;
@@ -2740,7 +2927,7 @@
                     false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
             mountMedia();
             // Verify that the app installed is on internal storage.
-            assertInstall(pkg, 0, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);            
+            assertInstall(pkg, 0, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
         } catch (Exception e) {
             failStr(e.getMessage());
         } finally {
@@ -2757,18 +2944,29 @@
      * different certificates.
      */
     private int APP1_UNSIGNED = R.raw.install_app1_unsigned;
+
     private int APP1_CERT1 = R.raw.install_app1_cert1;
+
     private int APP1_CERT2 = R.raw.install_app1_cert2;
+
     private int APP1_CERT1_CERT2 = R.raw.install_app1_cert1_cert2;
+
     private int APP1_CERT3_CERT4 = R.raw.install_app1_cert3_cert4;
+
     private int APP1_CERT3 = R.raw.install_app1_cert3;
+
     private int APP2_UNSIGNED = R.raw.install_app2_unsigned;
+
     private int APP2_CERT1 = R.raw.install_app2_cert1;
+
     private int APP2_CERT2 = R.raw.install_app2_cert2;
+
     private int APP2_CERT1_CERT2 = R.raw.install_app2_cert1_cert2;
+
     private int APP2_CERT3 = R.raw.install_app2_cert3;
 
-    private InstallParams replaceCerts(int apk1, int apk2, boolean cleanUp, boolean fail, int retCode) {
+    private InstallParams replaceCerts(int apk1, int apk2, boolean cleanUp, boolean fail,
+            int retCode) throws Exception {
         int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
         String apk1Name = "install1.apk";
         String apk2Name = "install2.apk";
@@ -2788,12 +2986,13 @@
         }
         return null;
     }
+
     /*
      * Test that an app signed with two certificates can be upgraded by the
      * same app signed with two certificates.
      */
     @LargeTest
-    public void testReplaceMatchAllCerts() {
+    public void testReplaceMatchAllCerts() throws Exception {
         replaceCerts(APP1_CERT1_CERT2, APP1_CERT1_CERT2, true, false, -1);
     }
 
@@ -2802,53 +3001,58 @@
      * by an app signed with a different certificate.
      */
     @LargeTest
-    public void testReplaceMatchNoCerts1() {
+    public void testReplaceMatchNoCerts1() throws Exception {
         replaceCerts(APP1_CERT1_CERT2, APP1_CERT3, true, true,
                 PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES);
     }
+
     /*
      * Test that an app signed with two certificates cannot be upgraded
      * by an app signed with a different certificate.
      */
     @LargeTest
-    public void testReplaceMatchNoCerts2() {
+    public void testReplaceMatchNoCerts2() throws Exception {
         replaceCerts(APP1_CERT1_CERT2, APP1_CERT3_CERT4, true, true,
                 PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES);
     }
+
     /*
      * Test that an app signed with two certificates cannot be upgraded by
      * an app signed with a subset of initial certificates.
      */
     @LargeTest
-    public void testReplaceMatchSomeCerts1() {
+    public void testReplaceMatchSomeCerts1() throws Exception {
         replaceCerts(APP1_CERT1_CERT2, APP1_CERT1, true, true,
                 PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES);
     }
+
     /*
      * Test that an app signed with two certificates cannot be upgraded by
      * an app signed with the last certificate.
      */
     @LargeTest
-    public void testReplaceMatchSomeCerts2() {
+    public void testReplaceMatchSomeCerts2() throws Exception {
         replaceCerts(APP1_CERT1_CERT2, APP1_CERT2, true, true,
                 PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES);
     }
+
     /*
      * Test that an app signed with a certificate can be upgraded by app
      * signed with a superset of certificates.
      */
     @LargeTest
-    public void testReplaceMatchMoreCerts() {
+    public void testReplaceMatchMoreCerts() throws Exception {
         replaceCerts(APP1_CERT1, APP1_CERT1_CERT2, true, true,
                 PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES);
     }
+
     /*
      * Test that an app signed with a certificate can be upgraded by app
      * signed with a superset of certificates. Then verify that the an app
      * signed with the original set of certs cannot upgrade the new one.
      */
     @LargeTest
-    public void testReplaceMatchMoreCertsReplaceSomeCerts() {
+    public void testReplaceMatchMoreCertsReplaceSomeCerts() throws Exception {
         InstallParams ip = replaceCerts(APP1_CERT1, APP1_CERT1_CERT2, false, true,
                 PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES);
         try {
@@ -2864,45 +3068,51 @@
             }
         }
     }
-    /*
-     * The following tests are related to testing the checkSignatures
-     * api.
+
+    /**
+     * The following tests are related to testing the checkSignatures api.
      */
-    private void checkSignatures(int apk1, int apk2, int expMatchResult) {
+    private void checkSignatures(int apk1, int apk2, int expMatchResult) throws Exception {
         checkSharedSignatures(apk1, apk2, true, false, -1, expMatchResult);
     }
+
     @LargeTest
-    public void testCheckSignaturesAllMatch() {
+    public void testCheckSignaturesAllMatch() throws Exception {
         int apk1 = APP1_CERT1_CERT2;
         int apk2 = APP2_CERT1_CERT2;
         checkSignatures(apk1, apk2, PackageManager.SIGNATURE_MATCH);
     }
+
     @LargeTest
-    public void testCheckSignaturesNoMatch() {
+    public void testCheckSignaturesNoMatch() throws Exception {
         int apk1 = APP1_CERT1;
         int apk2 = APP2_CERT2;
         checkSignatures(apk1, apk2, PackageManager.SIGNATURE_NO_MATCH);
     }
+
     @LargeTest
-    public void testCheckSignaturesSomeMatch1() {
+    public void testCheckSignaturesSomeMatch1() throws Exception {
         int apk1 = APP1_CERT1_CERT2;
         int apk2 = APP2_CERT1;
         checkSignatures(apk1, apk2, PackageManager.SIGNATURE_NO_MATCH);
     }
+
     @LargeTest
-    public void testCheckSignaturesSomeMatch2() {
+    public void testCheckSignaturesSomeMatch2() throws Exception {
         int apk1 = APP1_CERT1_CERT2;
         int apk2 = APP2_CERT2;
         checkSignatures(apk1, apk2, PackageManager.SIGNATURE_NO_MATCH);
     }
+
     @LargeTest
-    public void testCheckSignaturesMoreMatch() {
+    public void testCheckSignaturesMoreMatch() throws Exception {
         int apk1 = APP1_CERT1;
         int apk2 = APP2_CERT1_CERT2;
         checkSignatures(apk1, apk2, PackageManager.SIGNATURE_NO_MATCH);
     }
+
     @LargeTest
-    public void testCheckSignaturesUnknown() {
+    public void testCheckSignaturesUnknown() throws Exception {
         int apk1 = APP1_CERT1_CERT2;
         int apk2 = APP2_CERT1_CERT2;
         String apk1Name = "install1.apk";
@@ -2919,7 +3129,7 @@
             int rawResId = apk2;
             Uri packageURI = getInstallablePackage(rawResId, outFile);
             PackageParser.Package pkg = parsePackage(packageURI);
-            getPm().deletePackage(pkg.packageName, null, 0);
+            getPm().deletePackage(pkg.packageName, null, PackageManager.DELETE_ALL_USERS);
             // Check signatures now
             int match = mContext.getPackageManager().checkSignatures(
                     ip1.pkg.packageName, pkg.packageName);
@@ -2930,8 +3140,9 @@
             }
         }
     }
+
     @LargeTest
-    public void testInstallNoCertificates() {
+    public void testInstallNoCertificates() throws Exception {
         int apk1 = APP1_UNSIGNED;
         String apk1Name = "install1.apk";
         InstallParams ip1 = null;
@@ -2943,18 +3154,29 @@
         } finally {
         }
     }
-    /* The following tests are related to apps using shared uids signed
-     * with different certs.
+
+    /*
+     * The following tests are related to apps using shared uids signed with
+     * different certs.
      */
     private int SHARED1_UNSIGNED = R.raw.install_shared1_unsigned;
+
     private int SHARED1_CERT1 = R.raw.install_shared1_cert1;
+
     private int SHARED1_CERT2 = R.raw.install_shared1_cert2;
+
     private int SHARED1_CERT1_CERT2 = R.raw.install_shared1_cert1_cert2;
+
     private int SHARED2_UNSIGNED = R.raw.install_shared2_unsigned;
+
     private int SHARED2_CERT1 = R.raw.install_shared2_cert1;
+
     private int SHARED2_CERT2 = R.raw.install_shared2_cert2;
+
     private int SHARED2_CERT1_CERT2 = R.raw.install_shared2_cert1_cert2;
-    private void checkSharedSignatures(int apk1, int apk2, boolean cleanUp, boolean fail, int retCode, int expMatchResult) {
+
+    private void checkSharedSignatures(int apk1, int apk2, boolean cleanUp, boolean fail,
+            int retCode, int expMatchResult) throws Exception {
         String apk1Name = "install1.apk";
         String apk2Name = "install2.apk";
         PackageParser.Package pkg1 = getParsedPackage(apk1Name, apk1);
@@ -2964,16 +3186,16 @@
             // Clean up before testing first.
             cleanUpInstall(pkg1.packageName);
             cleanUpInstall(pkg2.packageName);
-            installFromRawResource(apk1Name, apk1, 0, false,
-                    false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+            installFromRawResource(apk1Name, apk1, 0, false, false, -1,
+                    PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
             if (fail) {
-                installFromRawResource(apk2Name, apk2, 0, false,
-                        true, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+                installFromRawResource(apk2Name, apk2, 0, false, true, retCode,
+                        PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
             } else {
-                installFromRawResource(apk2Name, apk2, 0, false,
-                        false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
-                int match = mContext.getPackageManager().checkSignatures(
-                        pkg1.packageName, pkg2.packageName);
+                installFromRawResource(apk2Name, apk2, 0, false, false, -1,
+                        PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+                int match = mContext.getPackageManager().checkSignatures(pkg1.packageName,
+                        pkg2.packageName);
                 assertEquals(expMatchResult, match);
             }
         } finally {
@@ -2983,8 +3205,9 @@
             }
         }
     }
+
     @LargeTest
-    public void testCheckSignaturesSharedAllMatch() {
+    public void testCheckSignaturesSharedAllMatch() throws Exception {
         int apk1 = SHARED1_CERT1_CERT2;
         int apk2 = SHARED2_CERT1_CERT2;
         boolean fail = false;
@@ -2992,8 +3215,9 @@
         int expMatchResult = PackageManager.SIGNATURE_MATCH;
         checkSharedSignatures(apk1, apk2, true, fail, retCode, expMatchResult);
     }
+
     @LargeTest
-    public void testCheckSignaturesSharedNoMatch() {
+    public void testCheckSignaturesSharedNoMatch() throws Exception {
         int apk1 = SHARED1_CERT1;
         int apk2 = SHARED2_CERT2;
         boolean fail = true;
@@ -3001,11 +3225,13 @@
         int expMatchResult = -1;
         checkSharedSignatures(apk1, apk2, true, fail, retCode, expMatchResult);
     }
+
     /*
-     * Test that an app signed with cert1 and cert2 cannot be replaced when signed with cert1 alone.
+     * Test that an app signed with cert1 and cert2 cannot be replaced when
+     * signed with cert1 alone.
      */
     @LargeTest
-    public void testCheckSignaturesSharedSomeMatch1() {
+    public void testCheckSignaturesSharedSomeMatch1() throws Exception {
         int apk1 = SHARED1_CERT1_CERT2;
         int apk2 = SHARED2_CERT1;
         boolean fail = true;
@@ -3013,11 +3239,13 @@
         int expMatchResult = -1;
         checkSharedSignatures(apk1, apk2, true, fail, retCode, expMatchResult);
     }
+
     /*
-     * Test that an app signed with cert1 and cert2 cannot be replaced when signed with cert2 alone.
+     * Test that an app signed with cert1 and cert2 cannot be replaced when
+     * signed with cert2 alone.
      */
     @LargeTest
-    public void testCheckSignaturesSharedSomeMatch2() {
+    public void testCheckSignaturesSharedSomeMatch2() throws Exception {
         int apk1 = SHARED1_CERT1_CERT2;
         int apk2 = SHARED2_CERT2;
         boolean fail = true;
@@ -3025,8 +3253,9 @@
         int expMatchResult = -1;
         checkSharedSignatures(apk1, apk2, true, fail, retCode, expMatchResult);
     }
+
     @LargeTest
-    public void testCheckSignaturesSharedUnknown() {
+    public void testCheckSignaturesSharedUnknown() throws Exception {
         int apk1 = SHARED1_CERT1_CERT2;
         int apk2 = SHARED2_CERT1_CERT2;
         String apk1Name = "install1.apk";
@@ -3039,7 +3268,7 @@
             PackageManager pm = mContext.getPackageManager();
             // Delete app2
             PackageParser.Package pkg = getParsedPackage(apk2Name, apk2);
-            getPm().deletePackage(pkg.packageName, null, 0);
+            getPm().deletePackage(pkg.packageName, null, PackageManager.DELETE_ALL_USERS);
             // Check signatures now
             int match = mContext.getPackageManager().checkSignatures(
                     ip1.pkg.packageName, pkg.packageName);
@@ -3052,23 +3281,25 @@
     }
 
     @LargeTest
-    public void testReplaceFirstSharedMatchAllCerts() {
+    public void testReplaceFirstSharedMatchAllCerts() throws Exception {
         int apk1 = SHARED1_CERT1;
         int apk2 = SHARED2_CERT1;
         int rapk1 = SHARED1_CERT1;
         checkSignatures(apk1, apk2, PackageManager.SIGNATURE_MATCH);
         replaceCerts(apk1, rapk1, true, false, -1);
     }
+
     @LargeTest
-    public void testReplaceSecondSharedMatchAllCerts() {
+    public void testReplaceSecondSharedMatchAllCerts() throws Exception {
         int apk1 = SHARED1_CERT1;
         int apk2 = SHARED2_CERT1;
         int rapk2 = SHARED2_CERT1;
         checkSignatures(apk1, apk2, PackageManager.SIGNATURE_MATCH);
         replaceCerts(apk2, rapk2, true, false, -1);
     }
+
     @LargeTest
-    public void testReplaceFirstSharedMatchSomeCerts() {
+    public void testReplaceFirstSharedMatchSomeCerts() throws Exception {
         int apk1 = SHARED1_CERT1_CERT2;
         int apk2 = SHARED2_CERT1_CERT2;
         int rapk1 = SHARED1_CERT1;
@@ -3078,8 +3309,9 @@
         installFromRawResource("install.apk", rapk1, PackageManager.INSTALL_REPLACE_EXISTING, true,
                 fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
     }
+
     @LargeTest
-    public void testReplaceSecondSharedMatchSomeCerts() {
+    public void testReplaceSecondSharedMatchSomeCerts() throws Exception {
         int apk1 = SHARED1_CERT1_CERT2;
         int apk2 = SHARED2_CERT1_CERT2;
         int rapk2 = SHARED2_CERT1;
@@ -3089,8 +3321,9 @@
         installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true,
                 fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
     }
+
     @LargeTest
-    public void testReplaceFirstSharedMatchNoCerts() {
+    public void testReplaceFirstSharedMatchNoCerts() throws Exception {
         int apk1 = SHARED1_CERT1;
         int apk2 = SHARED2_CERT1;
         int rapk1 = SHARED1_CERT2;
@@ -3100,8 +3333,9 @@
         installFromRawResource("install.apk", rapk1, PackageManager.INSTALL_REPLACE_EXISTING, true,
                 fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
     }
+
     @LargeTest
-    public void testReplaceSecondSharedMatchNoCerts() {
+    public void testReplaceSecondSharedMatchNoCerts() throws Exception {
         int apk1 = SHARED1_CERT1;
         int apk2 = SHARED2_CERT1;
         int rapk2 = SHARED2_CERT2;
@@ -3111,8 +3345,9 @@
         installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true,
                 fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
     }
+
     @LargeTest
-    public void testReplaceFirstSharedMatchMoreCerts() {
+    public void testReplaceFirstSharedMatchMoreCerts() throws Exception {
         int apk1 = SHARED1_CERT1;
         int apk2 = SHARED2_CERT1;
         int rapk1 = SHARED1_CERT1_CERT2;
@@ -3122,8 +3357,9 @@
         installFromRawResource("install.apk", rapk1, PackageManager.INSTALL_REPLACE_EXISTING, true,
                 fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
     }
+
     @LargeTest
-    public void testReplaceSecondSharedMatchMoreCerts() {
+    public void testReplaceSecondSharedMatchMoreCerts() throws Exception {
         int apk1 = SHARED1_CERT1;
         int apk2 = SHARED2_CERT1;
         int rapk2 = SHARED2_CERT1_CERT2;
@@ -3144,34 +3380,34 @@
      * features.
      */
     @LargeTest
-    public void testUsesFeatureUnknownFeature() {
+    public void testUsesFeatureUnknownFeature() throws Exception {
         int retCode = PackageManager.INSTALL_SUCCEEDED;
         installFromRawResource("install.apk", R.raw.install_uses_feature, 0, true, false, retCode,
                 PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
     }
 
     @LargeTest
-    public void testInstallNonexistentFile() {
+    public void testInstallNonexistentFile() throws Exception {
         int retCode = PackageManager.INSTALL_FAILED_INVALID_URI;
         File invalidFile = new File("/nonexistent-file.apk");
         invokeInstallPackageFail(Uri.fromFile(invalidFile), 0, retCode);
     }
 
     @SmallTest
-    public void testGetVerifierDeviceIdentity() {
+    public void testGetVerifierDeviceIdentity() throws Exception {
         PackageManager pm = getPm();
         VerifierDeviceIdentity id = pm.getVerifierDeviceIdentity();
 
         assertNotNull("Verifier device identity should not be null", id);
     }
 
-    public void testGetInstalledPackages() {
+    public void testGetInstalledPackages() throws Exception {
         List<PackageInfo> packages = getPm().getInstalledPackages(0);
         assertNotNull("installed packages cannot be null", packages);
         assertTrue("installed packages cannot be empty", packages.size() > 0);
     }
 
-    public void testGetUnInstalledPackages() {
+    public void testGetUnInstalledPackages() throws Exception {
         List<PackageInfo> packages = getPm().getInstalledPackages(
                 PackageManager.GET_UNINSTALLED_PACKAGES);
         assertNotNull("installed packages cannot be null", packages);
@@ -3179,10 +3415,9 @@
     }
 
     /**
-     * Test that getInstalledPackages returns all the data specified in
-     * flags.
+     * Test that getInstalledPackages returns all the data specified in flags.
      */
-    public void testGetInstalledPackagesAll() {
+    public void testGetInstalledPackagesAll() throws Exception {
         int flags = PackageManager.GET_ACTIVITIES | PackageManager.GET_GIDS
                 | PackageManager.GET_CONFIGURATIONS | PackageManager.GET_INSTRUMENTATION
                 | PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS
@@ -3218,7 +3453,7 @@
      * Test that getInstalledPackages returns all the data specified in
      * flags when the GET_UNINSTALLED_PACKAGES flag is set.
      */
-    public void testGetUnInstalledPackagesAll() {
+    public void testGetUnInstalledPackagesAll() throws Exception {
         int flags = PackageManager.GET_UNINSTALLED_PACKAGES
                 | PackageManager.GET_ACTIVITIES | PackageManager.GET_GIDS
                 | PackageManager.GET_CONFIGURATIONS | PackageManager.GET_INSTRUMENTATION
@@ -3251,6 +3486,12 @@
         assertNotNull("signatures should not be null", packageInfo.signatures);
     }
 
+    public void testInstall_BadDex_CleanUp() throws Exception {
+        int retCode = PackageManager.INSTALL_FAILED_DEXOPT;
+        installFromRawResource("install.apk", R.raw.install_bad_dex, 0, true, true, retCode,
+                PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+    }
+
     /*---------- Recommended install location tests ----*/
     /*
      * TODO's
diff --git a/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java b/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
new file mode 100644
index 0000000..9b216cb
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.content.pm.ManifestDigest;
+import android.content.pm.VerificationParams;
+import android.net.Uri;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+/**
+ * Tests the android.content.pm.VerificationParams class
+ *
+ * To test run:
+ * ./development/testrunner/runtest.py frameworks-core -c android.content.pm.VerificationParamsTest
+ */
+public class VerificationParamsTest extends AndroidTestCase {
+
+    private final static String VERIFICATION_URI_STRING = "http://verification.uri/path";
+    private final static String ORIGINATING_URI_STRING = "http://originating.uri/path";
+    private final static String REFERRER_STRING = "http://referrer.uri/path";
+    private final static byte[] DIGEST_BYTES = "fake digest".getBytes();
+    private final static int INSTALLER_UID = 42;
+
+    private final static Uri VERIFICATION_URI = Uri.parse(VERIFICATION_URI_STRING);
+    private final static Uri ORIGINATING_URI = Uri.parse(ORIGINATING_URI_STRING);
+    private final static Uri REFERRER = Uri.parse(REFERRER_STRING);
+
+    private final static int ORIGINATING_UID = 10042;
+
+    private final static ManifestDigest MANIFEST_DIGEST = new ManifestDigest(DIGEST_BYTES);
+
+    public void testParcel() throws Exception {
+        VerificationParams expected = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+        Parcel parcel = Parcel.obtain();
+        expected.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        VerificationParams actual = VerificationParams.CREATOR.createFromParcel(parcel);
+
+        assertEquals(VERIFICATION_URI, actual.getVerificationURI());
+
+        assertEquals(ORIGINATING_URI, actual.getOriginatingURI());
+
+        assertEquals(REFERRER, actual.getReferrer());
+
+        assertEquals(ORIGINATING_UID, actual.getOriginatingUid());
+
+        assertEquals(MANIFEST_DIGEST, actual.getManifestDigest());
+    }
+
+    public void testEquals_Success() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), ORIGINATING_UID, new ManifestDigest(DIGEST_BYTES));
+
+        assertEquals(params1, params2);
+    }
+
+    public void testEquals_VerificationUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse("http://a.different.uri/"), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), ORIGINATING_UID, new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_OriginatingUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse("http://a.different.uri/"),
+                Uri.parse(REFERRER_STRING), ORIGINATING_UID, new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_Referrer_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse("http://a.different.uri/"), ORIGINATING_UID,
+                new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_Originating_Uid_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), 12345, new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_ManifestDigest_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), ORIGINATING_UID,
+                new ManifestDigest("a different digest".getBytes()));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_InstallerUid_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), ORIGINATING_UID, new ManifestDigest(DIGEST_BYTES));
+        params2.setInstallerUid(INSTALLER_UID);
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testHashCode_Success() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), ORIGINATING_UID, new ManifestDigest(DIGEST_BYTES));
+
+        assertEquals(params1.hashCode(), params2.hashCode());
+    }
+
+    public void testHashCode_VerificationUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(null, Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), ORIGINATING_UID, new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_OriginatingUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse("http://a.different.uri/"),
+                Uri.parse(REFERRER_STRING), ORIGINATING_UID, new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_Referrer_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING), null,
+                ORIGINATING_UID, new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_Originating_Uid_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), 12345, new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_ManifestDigest_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), ORIGINATING_UID,
+                new ManifestDigest("a different digest".getBytes()));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_InstallerUid_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, ORIGINATING_UID, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), ORIGINATING_UID,
+                new ManifestDigest("a different digest".getBytes()));
+        params2.setInstallerUid(INSTALLER_UID);
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+}
diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java
index 098464f..6331964 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java
@@ -287,7 +287,7 @@
                 .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L)
                 .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 128L, 8L, 0L, 0L, 0L);
 
-        final NetworkStats after = before.withoutUid(100);
+        final NetworkStats after = before.withoutUids(new int[] { 100 });
         assertEquals(6, before.size());
         assertEquals(2, after.size());
         assertValues(after, 0, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L);
diff --git a/core/tests/coretests/src/android/net/http/X509TrustManagerExtensionsTest.java b/core/tests/coretests/src/android/net/http/X509TrustManagerExtensionsTest.java
new file mode 100644
index 0000000..60c40db
--- /dev/null
+++ b/core/tests/coretests/src/android/net/http/X509TrustManagerExtensionsTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.net.http;
+
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.xnet.provider.jsse.TrustManagerImpl;
+
+public class X509TrustManagerExtensionsTest extends TestCase {
+
+    private class NotATrustManagerImpl implements X509TrustManager {
+
+        public void checkClientTrusted(X509Certificate[] chain, String authType) {}
+
+        public void checkServerTrusted(X509Certificate[] chain, String authType) {}
+
+        public X509Certificate[] getAcceptedIssuers() {
+            return new X509Certificate[0];
+        }
+    }
+
+    public void testBadCast() throws Exception {
+        NotATrustManagerImpl ntmi = new NotATrustManagerImpl();
+        try {
+            X509TrustManagerExtensions tme = new X509TrustManagerExtensions(ntmi);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testGoodCast() throws Exception {
+        String defaultType = KeyStore.getDefaultType();
+        TrustManagerImpl tmi = new TrustManagerImpl(KeyStore.getInstance(defaultType));
+        X509TrustManagerExtensions tme = new X509TrustManagerExtensions(tmi);
+    }
+
+    public void testNormalUseCase() throws Exception {
+        String defaultAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance(defaultAlgorithm);
+        String defaultKeystoreType = KeyStore.getDefaultType();
+        tmf.init(KeyStore.getInstance(defaultKeystoreType));
+        TrustManager[] tms = tmf.getTrustManagers();
+        for (TrustManager tm : tms) {
+            if (tm instanceof X509TrustManager) {
+                new X509TrustManagerExtensions((X509TrustManager)tm);
+                return;
+            }
+        }
+        fail();
+    }
+}
diff --git a/core/tests/coretests/src/android/os/BrightnessLimit.java b/core/tests/coretests/src/android/os/BrightnessLimit.java
index 5e9b906..f4a5e09 100644
--- a/core/tests/coretests/src/android/os/BrightnessLimit.java
+++ b/core/tests/coretests/src/android/os/BrightnessLimit.java
@@ -49,7 +49,7 @@
                 ServiceManager.getService("power"));
         if (power != null) {
             try {
-                power.setBacklightBrightness(0);
+                power.setTemporaryScreenBrightnessSettingOverride(0);
             } catch (RemoteException darn) {
                 
             }
diff --git a/core/tests/coretests/src/android/os/ProcessTest.java b/core/tests/coretests/src/android/os/ProcessTest.java
new file mode 100644
index 0000000..1f5b7c8
--- /dev/null
+++ b/core/tests/coretests/src/android/os/ProcessTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.os;
+
+import android.os.Process;
+import android.os.UserHandle;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.TestCase;
+
+
+public class ProcessTest extends TestCase {
+
+    @MediumTest
+    public void testProcessGetUidFromName() throws Exception {
+        assertEquals(android.os.Process.SYSTEM_UID, Process.getUidForName("system"));
+        assertEquals(Process.BLUETOOTH_UID, Process.getUidForName("bluetooth"));
+        assertEquals(Process.FIRST_APPLICATION_UID, Process.getUidForName("u0_a0"));
+        assertEquals(UserHandle.getUid(1, Process.SYSTEM_UID), Process.getUidForName("u1_system"));
+        assertEquals(UserHandle.getUid(2, Process.FIRST_ISOLATED_UID),
+                Process.getUidForName("u2_i0"));
+        assertEquals(UserHandle.getUid(3, Process.FIRST_APPLICATION_UID + 100),
+                Process.getUidForName("u3_a100"));
+    }
+
+    @MediumTest
+    public void testProcessGetUidFromNameFailure() throws Exception {
+        // Failure cases
+        assertEquals(-1, Process.getUidForName("u2a_foo"));
+        assertEquals(-1, Process.getUidForName("u1_abcdef"));
+        assertEquals(-1, Process.getUidForName("u23"));
+        assertEquals(-1, Process.getUidForName("u2_i34a"));
+        assertEquals(-1, Process.getUidForName("akjhwiuefhiuhsf"));
+        assertEquals(-1, Process.getUidForName("u5_radio5"));
+        assertEquals(-1, Process.getUidForName("u2jhsajhfkjhsafkhskafhkashfkjashfkjhaskjfdhakj3"));
+    }
+
+}
diff --git a/core/tests/coretests/src/android/provider/SettingsProviderTest.java b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
index 3e96dc4..6edd2dc 100644
--- a/core/tests/coretests/src/android/provider/SettingsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
@@ -19,11 +19,15 @@
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
@@ -197,6 +201,53 @@
                 Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
      }
 
+    private boolean findUser(UserManager um, int userHandle) {
+        for (UserInfo user : um.getUsers()) {
+            if (user.id == userHandle) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @MediumTest
+    public void testPerUserSettings() {
+        UserManager um = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
+        ContentResolver r = getContext().getContentResolver();
+
+        // Make sure there's an owner
+        assertTrue(findUser(um, UserHandle.USER_OWNER));
+
+        // create a new user to use for testing
+        UserInfo user = um.createUser("TestUser1", UserInfo.FLAG_GUEST);
+        assertTrue(user != null);
+
+        try {
+            // Write some settings for that user as well as the current user
+            final String TEST_KEY = "test_setting";
+            final int SELF_VALUE = 40;
+            final int OTHER_VALUE = 27;
+
+            Settings.System.putInt(r, TEST_KEY, SELF_VALUE);
+            Settings.System.putIntForUser(r, TEST_KEY, OTHER_VALUE, user.id);
+
+            // Verify that they read back as intended
+            int myValue = Settings.System.getInt(r, TEST_KEY, 0);
+            int otherValue = Settings.System.getIntForUser(r, TEST_KEY, 0, user.id);
+            assertTrue("Running as user " + UserHandle.myUserId()
+                    + " and reading/writing as user " + user.id
+                    + ", expected to read " + SELF_VALUE + " but got " + myValue,
+                    myValue == SELF_VALUE);
+            assertTrue("Running as user " + UserHandle.myUserId()
+                    + " and reading/writing as user " + user.id
+                    + ", expected to read " + OTHER_VALUE + " but got " + otherValue,
+                    otherValue == OTHER_VALUE);
+        } finally {
+            // Tidy up
+            um.removeUser(user.id);
+        }
+    }
+
      @SmallTest
      public void testSettings() {
         assertCanBeHandled(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
diff --git a/core/tests/coretests/src/android/util/ListItemFactory.java b/core/tests/coretests/src/android/util/ListItemFactory.java
index e8a498d..3f48dcc 100644
--- a/core/tests/coretests/src/android/util/ListItemFactory.java
+++ b/core/tests/coretests/src/android/util/ListItemFactory.java
@@ -247,7 +247,7 @@
         TextView t1 = new TextView(context);
         t1.setHeight(desiredHeight);
         t1.setText(text);
-        t1.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
+        t1.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
         final ViewGroup.LayoutParams lp1 = new LinearLayout.LayoutParams(
                 0,
                 ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f);
diff --git a/core/tests/coretests/src/android/util/TimeUtilsTest.java b/core/tests/coretests/src/android/util/TimeUtilsTest.java
index 8d9f8e5..74c8e04 100644
--- a/core/tests/coretests/src/android/util/TimeUtilsTest.java
+++ b/core/tests/coretests/src/android/util/TimeUtilsTest.java
@@ -18,8 +18,6 @@
 
 import junit.framework.TestCase;
 
-import android.util.TimeUtils;
-
 import java.util.Calendar;
 import java.util.TimeZone;
 
@@ -442,6 +440,13 @@
         assertFormatDuration("+10s24ms", 10024);
     }
 
+    public void testFormatHugeDuration() {
+        //assertFormatDuration("+15542d1h11m11s555ms", 1342833071555L);
+        // TODO: improve formatDuration() API
+        assertFormatDuration("+999d23h59m59s999ms", 1342833071555L);
+        assertFormatDuration("-999d23h59m59s999ms", -1342833071555L);
+    }
+
     private void assertFormatDuration(String expected, long duration) {
         StringBuilder sb = new StringBuilder();
         TimeUtils.formatDuration(duration, sb);
diff --git a/core/tests/coretests/src/android/widget/focus/VerticalFocusSearch.java b/core/tests/coretests/src/android/widget/focus/VerticalFocusSearch.java
index deb9e67..4a809e0 100644
--- a/core/tests/coretests/src/android/widget/focus/VerticalFocusSearch.java
+++ b/core/tests/coretests/src/android/widget/focus/VerticalFocusSearch.java
@@ -66,7 +66,7 @@
 
         mLayout = new LinearLayout(this);
         mLayout.setOrientation(LinearLayout.VERTICAL);
-        mLayout.setHorizontalGravity(Gravity.LEFT);
+        mLayout.setHorizontalGravity(Gravity.START);
         mLayout.setLayoutParams(new ViewGroup.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.MATCH_PARENT));
diff --git a/core/tests/coretests/src/com/android/server/MountServiceTests.java b/core/tests/coretests/src/com/android/server/MountServiceTests.java
deleted file mode 100644
index 1f8c92e..0000000
--- a/core/tests/coretests/src/com/android/server/MountServiceTests.java
+++ /dev/null
@@ -1,285 +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.
- */
-
-package com.android.server;
-
-import com.android.frameworks.coretests.R;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
-import android.os.FileUtils;
-import android.os.storage.OnObbStateChangeListener;
-import android.os.storage.StorageManager;
-import android.test.AndroidTestCase;
-import android.test.ComparisonFailure;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-
-import java.io.File;
-import java.io.InputStream;
-
-public class MountServiceTests extends AndroidTestCase {
-    private static final String TAG = "MountServiceTests";
-
-    private static final long MAX_WAIT_TIME = 25*1000;
-    private static final long WAIT_TIME_INCR = 5*1000;
-
-    private static final String OBB_MOUNT_PREFIX = "/mnt/obb/";
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-    private static void assertStartsWith(String message, String prefix, String actual) {
-        if (!actual.startsWith(prefix)) {
-            throw new ComparisonFailure(message, prefix, actual);
-        }
-    }
-
-    private static class ObbObserver extends OnObbStateChangeListener {
-        private String path;
-
-        public int state = -1;
-        boolean done = false;
-
-        @Override
-        public void onObbStateChange(String path, int state) {
-            Log.d(TAG, "Received message.  path=" + path + ", state=" + state);
-            synchronized (this) {
-                this.path = path;
-                this.state = state;
-                done = true;
-                notifyAll();
-            }
-        }
-
-        public String getPath() {
-            assertTrue("Expected ObbObserver to have received a state change.", done);
-            return path;
-        }
-
-        public int getState() {
-            assertTrue("Expected ObbObserver to have received a state change.", done);
-            return state;
-        }
-
-        public void reset() {
-            this.path = null;
-            this.state = -1;
-            done = false;
-        }
-
-        public boolean isDone() {
-            return done;
-        }
-
-        public boolean waitForCompletion() {
-            long waitTime = 0;
-            synchronized (this) {
-                while (!isDone() && waitTime < MAX_WAIT_TIME) {
-                    try {
-                        wait(WAIT_TIME_INCR);
-                        waitTime += WAIT_TIME_INCR;
-                    } catch (InterruptedException e) {
-                        Log.i(TAG, "Interrupted during sleep", e);
-                    }
-                }
-            }
-
-            return isDone();
-        }
-    }
-
-    private File getFilePath(String name) {
-        final File filesDir = mContext.getFilesDir();
-        final File outFile = new File(filesDir, name);
-        return outFile;
-    }
-
-    private void copyRawToFile(int rawResId, File outFile) {
-        Resources res = mContext.getResources();
-        InputStream is = null;
-        try {
-            is = res.openRawResource(rawResId);
-        } catch (NotFoundException e) {
-            fail("Failed to load resource with id: " + rawResId);
-        }
-        FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
-                | FileUtils.S_IRWXO, -1, -1);
-        assertTrue(FileUtils.copyToFile(is, outFile));
-        FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
-                | FileUtils.S_IRWXO, -1, -1);
-    }
-
-    private StorageManager getStorageManager() {
-        return (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE);
-    }
-
-    private void mountObb(StorageManager sm, final int resource, final File file,
-            int expectedState) {
-        copyRawToFile(resource, file);
-
-        final ObbObserver observer = new ObbObserver();
-        assertTrue("mountObb call on " + file.getPath() + " should succeed",
-                sm.mountObb(file.getPath(), null, observer));
-
-        assertTrue("Mount should have completed",
-                observer.waitForCompletion());
-
-        if (expectedState == OnObbStateChangeListener.MOUNTED) {
-            assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath()));
-        }
-
-        assertEquals("Actual file and resolved file should be the same",
-                file.getPath(), observer.getPath());
-
-        assertEquals(expectedState, observer.getState());
-    }
-
-    private ObbObserver mountObbWithoutWait(final StorageManager sm, final int resource,
-            final File file) {
-        copyRawToFile(resource, file);
-
-        final ObbObserver observer = new ObbObserver();
-        assertTrue("mountObb call on " + file.getPath() + " should succeed", sm.mountObb(file
-                .getPath(), null, observer));
-
-        return observer;
-    }
-
-    private void waitForObbActionCompletion(final StorageManager sm, final File file,
-            final ObbObserver observer, int expectedState, boolean checkPath) {
-        assertTrue("Mount should have completed", observer.waitForCompletion());
-
-        assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath()));
-
-        if (checkPath) {
-            assertEquals("Actual file and resolved file should be the same", file.getPath(),
-                    observer.getPath());
-        }
-
-        assertEquals(expectedState, observer.getState());
-    }
-
-    private String checkMountedPath(final StorageManager sm, final File file) {
-        final String mountPath = sm.getMountedObbPath(file.getPath());
-        assertStartsWith("Path should be in " + OBB_MOUNT_PREFIX,
-                OBB_MOUNT_PREFIX,
-                mountPath);
-        return mountPath;
-    }
-
-    private void unmountObb(final StorageManager sm, final File file, int expectedState) {
-        final ObbObserver observer = new ObbObserver();
-
-        assertTrue("unmountObb call on test1.obb should succeed",
- sm.unmountObb(file.getPath(),
-                false, observer));
-
-        assertTrue("Unmount should have completed",
-                observer.waitForCompletion());
-
-        assertEquals(expectedState, observer.getState());
-
-        if (expectedState == OnObbStateChangeListener.UNMOUNTED) {
-            assertFalse("OBB should not be mounted", sm.isObbMounted(file.getPath()));
-        }
-    }
-
-    @LargeTest
-    public void testMountAndUnmountObbNormal() {
-        StorageManager sm = getStorageManager();
-
-        final File outFile = getFilePath("test1.obb");
-
-        mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.MOUNTED);
-
-        mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
-
-        final String mountPath = checkMountedPath(sm, outFile);
-        final File mountDir = new File(mountPath);
-
-        assertTrue("OBB mounted path should be a directory",
-                mountDir.isDirectory());
-
-        unmountObb(sm, outFile, OnObbStateChangeListener.UNMOUNTED);
-    }
-
-    @LargeTest
-    public void testAttemptMountNonObb() {
-        StorageManager sm = getStorageManager();
-
-        final File outFile = getFilePath("test1_nosig.obb");
-
-        mountObb(sm, R.raw.test1_nosig, outFile, OnObbStateChangeListener.ERROR_INTERNAL);
-
-        assertFalse("OBB should not be mounted",
-                sm.isObbMounted(outFile.getPath()));
-
-        assertNull("OBB's mounted path should be null",
-                sm.getMountedObbPath(outFile.getPath()));
-    }
-
-    @LargeTest
-    public void testAttemptMountObbWrongPackage() {
-        StorageManager sm = getStorageManager();
-
-        final File outFile = getFilePath("test1_wrongpackage.obb");
-
-        mountObb(sm, R.raw.test1_wrongpackage, outFile,
-                OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
-
-        assertFalse("OBB should not be mounted",
-                sm.isObbMounted(outFile.getPath()));
-
-        assertNull("OBB's mounted path should be null",
-                sm.getMountedObbPath(outFile.getPath()));
-    }
-
-    @LargeTest
-    public void testMountAndUnmountTwoObbs() {
-        StorageManager sm = getStorageManager();
-
-        final File file1 = getFilePath("test1.obb");
-        final File file2 = getFilePath("test2.obb");
-
-        ObbObserver oo1 = mountObbWithoutWait(sm, R.raw.test1, file1);
-        ObbObserver oo2 = mountObbWithoutWait(sm, R.raw.test1, file2);
-
-        Log.d(TAG, "Waiting for OBB #1 to complete mount");
-        waitForObbActionCompletion(sm, file1, oo1, OnObbStateChangeListener.MOUNTED, false);
-        Log.d(TAG, "Waiting for OBB #2 to complete mount");
-        waitForObbActionCompletion(sm, file2, oo2, OnObbStateChangeListener.MOUNTED, false);
-
-        final String mountPath1 = checkMountedPath(sm, file1);
-        final File mountDir1 = new File(mountPath1);
-        assertTrue("OBB mounted path should be a directory", mountDir1.isDirectory());
-
-        final String mountPath2 = checkMountedPath(sm, file2);
-        final File mountDir2 = new File(mountPath2);
-        assertTrue("OBB mounted path should be a directory", mountDir2.isDirectory());
-
-        unmountObb(sm, file1, OnObbStateChangeListener.UNMOUNTED);
-        unmountObb(sm, file2, OnObbStateChangeListener.UNMOUNTED);
-    }
-}
diff --git a/core/tests/hosttests/Android.mk b/core/tests/hosttests/Android.mk
index 07d99cb..f26d401 100644
--- a/core/tests/hosttests/Android.mk
+++ b/core/tests/hosttests/Android.mk
@@ -16,17 +16,5 @@
 
 include $(CLEAR_VARS)
 
-#LOCAL_TEST_TYPE := hostSideOnly
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE := FrameworkCoreHostTests
-
-LOCAL_JAVA_LIBRARIES := hosttestlib ddmlib-prebuilt junit
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
 # Build the test APKs using their own makefiles
 include $(call all-makefiles-under,$(LOCAL_PATH))
-
diff --git a/core/tests/hosttests/README b/core/tests/hosttests/README
deleted file mode 100644
index d3bdb83..0000000
--- a/core/tests/hosttests/README
+++ /dev/null
@@ -1,6 +0,0 @@
-This dir contains tests which run on a host machine, and test aspects of
-package install etc via adb.
-
-To run, do:
-runtest framework-core-host
-
diff --git a/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java b/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java
deleted file mode 100644
index c698e99..0000000
--- a/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java
+++ /dev/null
@@ -1,891 +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.
- */
-
-package android.content.pm;
-
-import com.android.ddmlib.AdbCommandRejectedException;
-import com.android.ddmlib.AndroidDebugBridge;
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.IShellOutputReceiver;
-import com.android.ddmlib.InstallException;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.MultiLineReceiver;
-import com.android.ddmlib.ShellCommandUnresponsiveException;
-import com.android.ddmlib.SyncException;
-import com.android.ddmlib.TimeoutException;
-import com.android.ddmlib.SyncService.ISyncProgressMonitor;
-import com.android.ddmlib.testrunner.ITestRunListener;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.StringReader;
-import java.lang.Runtime;
-import java.lang.Process;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import junit.framework.Assert;
-
-/**
- * Set of tests that verify host side install cases
- */
-public class PackageManagerHostTestUtils extends Assert {
-
-    private static final String LOG_TAG = "PackageManagerHostTests";
-    private IDevice mDevice = null;
-
-    // TODO: get this value from Android Environment instead of hardcoding
-    private static final String APP_PRIVATE_PATH = "/data/app-private/";
-    private static final String DEVICE_APP_PATH = "/data/app/";
-    private static final String SDCARD_APP_PATH = "/mnt/secure/asec/";
-
-    private static final int MAX_WAIT_FOR_DEVICE_TIME = 120 * 1000;
-    private static final int WAIT_FOR_DEVICE_POLL_TIME = 10 * 1000;
-    private static final int MAX_WAIT_FOR_APP_LAUNCH_TIME = 60 * 1000;
-    private static final int WAIT_FOR_APP_LAUNCH_POLL_TIME = 5 * 1000;
-
-    // Install preference on the device-side
-    public static enum InstallLocPreference {
-        AUTO,
-        INTERNAL,
-        EXTERNAL
-    }
-
-    // Actual install location
-    public static enum InstallLocation {
-        DEVICE,
-        SDCARD
-    }
-
-    /**
-     * Constructor takes the device to use
-     * @param the device to use when performing operations
-     */
-    public PackageManagerHostTestUtils(IDevice device)
-    {
-          mDevice = device;
-    }
-
-    /**
-     * Disable default constructor
-     */
-    private PackageManagerHostTestUtils() {}
-
-    /**
-     * Returns the path on the device of forward-locked apps.
-     *
-     * @return path of forward-locked apps on the device
-     */
-    public static String getAppPrivatePath() {
-        return APP_PRIVATE_PATH;
-    }
-
-    /**
-     * Returns the path on the device of normal apps.
-     *
-     * @return path of forward-locked apps on the device
-     */
-    public static String getDeviceAppPath() {
-        return DEVICE_APP_PATH;
-    }
-
-    /**
-     * Returns the path of apps installed on the SD card.
-     *
-     * @return path of forward-locked apps on the device
-     */
-    public static String getSDCardAppPath() {
-        return SDCARD_APP_PATH;
-    }
-
-    /**
-     * Helper method to run tests and return the listener that collected the results.
-     *
-     * For the optional params, pass null to use the default values.
-
-     * @param pkgName Android application package for tests
-     * @param className (optional) The class containing the method to test
-     * @param methodName (optional) The method in the class of which to test
-     * @param runnerName (optional) The name of the TestRunner of the test on the device to be run
-     * @param params (optional) Any additional parameters to pass into the Test Runner
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @return the {@link CollectingTestRunListener}
-     */
-    private CollectingTestRunListener doRunTests(String pkgName, String className,
-            String methodName, String runnerName, Map<String, String> params) throws IOException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(pkgName, runnerName,
-                mDevice);
-
-        if (className != null && methodName != null) {
-            testRunner.setMethodName(className, methodName);
-        }
-
-        // Add in any additional args to pass into the test
-        if (params != null) {
-            for (Entry<String, String> argPair : params.entrySet()) {
-                testRunner.addInstrumentationArg(argPair.getKey(), argPair.getValue());
-            }
-        }
-
-        CollectingTestRunListener listener = new CollectingTestRunListener();
-        try {
-            testRunner.run(listener);
-        } catch (IOException ioe) {
-            Log.w(LOG_TAG, "encountered IOException " + ioe);
-        }
-        return listener;
-    }
-
-    /**
-     * Runs the specified packages tests, and returns whether all tests passed or not.
-     *
-     * @param pkgName Android application package for tests
-     * @param className The class containing the method to test
-     * @param methodName The method in the class of which to test
-     * @param runnerName The name of the TestRunner of the test on the device to be run
-     * @param params Any additional parameters to pass into the Test Runner
-     * @return true if test passed, false otherwise.
-     */
-    public boolean runDeviceTestsDidAllTestsPass(String pkgName, String className,
-            String methodName, String runnerName, Map<String, String> params) throws IOException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        CollectingTestRunListener listener = doRunTests(pkgName, className, methodName,
-                runnerName, params);
-        return listener.didAllTestsPass();
-    }
-
-    /**
-     * Runs the specified packages tests, and returns whether all tests passed or not.
-     *
-     * @param pkgName Android application package for tests
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @return true if every test passed, false otherwise.
-     */
-    public boolean runDeviceTestsDidAllTestsPass(String pkgName) throws IOException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        CollectingTestRunListener listener = doRunTests(pkgName, null, null, null, null);
-        return listener.didAllTestsPass();
-    }
-
-    /**
-     * Helper method to push a file to device
-     * @param apkAppPrivatePath
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     */
-    public void pushFile(final String localFilePath, final String destFilePath)
-            throws IOException, SyncException, TimeoutException, AdbCommandRejectedException {
-        mDevice.getSyncService().pushFile(localFilePath,
-                destFilePath, new NullSyncProgressMonitor());
-    }
-
-    /**
-     * Helper method to install a file
-     * @param localFilePath the absolute file system path to file on local host to install
-     * @param reinstall set to <code>true</code> if re-install of app should be performed
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed
-     */
-    public void installFile(final String localFilePath, final boolean replace) throws IOException,
-            InstallException {
-        String result = mDevice.installPackage(localFilePath, replace);
-        assertEquals(null, result);
-    }
-
-    /**
-     * Helper method to install a file that should not be install-able
-     * @param localFilePath the absolute file system path to file on local host to install
-     * @param reinstall set to <code>true</code> if re-install of app should be performed
-     * @return the string output of the failed install attempt
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed
-     */
-    public String installFileFail(final String localFilePath, final boolean replace)
-            throws IOException, InstallException {
-        String result = mDevice.installPackage(localFilePath, replace);
-        assertNotNull(result);
-        return result;
-    }
-
-    /**
-     * Helper method to install a file to device as forward locked
-     * @param localFilePath the absolute file system path to file on local host to install
-     * @param reinstall set to <code>true</code> if re-install of app should be performed
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public String installFileForwardLocked(final String localFilePath, final boolean replace)
-            throws IOException, SyncException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException, InstallException {
-        String remoteFilePath = mDevice.syncPackageToDevice(localFilePath);
-        InstallReceiver receiver = new InstallReceiver();
-        String cmd = String.format(replace ? "pm install -r -l \"%1$s\"" :
-                "pm install -l \"%1$s\"", remoteFilePath);
-        mDevice.executeShellCommand(cmd, receiver);
-        mDevice.removeRemotePackage(remoteFilePath);
-        return receiver.getErrorMessage();
-    }
-
-    /**
-     * Helper method to determine if file on device exists.
-     *
-     * @param destPath the absolute path of file on device to check
-     * @return <code>true</code> if file exists, <code>false</code> otherwise.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public boolean doesRemoteFileExist(String destPath) throws IOException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        String lsGrep = executeShellCommand(String.format("ls %s", destPath));
-        return !lsGrep.contains("No such file or directory");
-    }
-
-    /**
-     * Helper method to determine if file exists on the device containing a given string.
-     *
-     * @param destPath the absolute path of the file
-     * @return <code>true</code> if file exists containing given string,
-     *         <code>false</code> otherwise.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public boolean doesRemoteFileExistContainingString(String destPath, String searchString)
-            throws IOException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        String lsResult = executeShellCommand(String.format("ls %s", destPath));
-        return lsResult.contains(searchString);
-    }
-
-    /**
-     * Helper method to determine if package on device exists.
-     *
-     * @param packageName the Android manifest package to check.
-     * @return <code>true</code> if package exists, <code>false</code> otherwise
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public boolean doesPackageExist(String packageName) throws IOException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        String pkgGrep = executeShellCommand(String.format("pm path %s", packageName));
-        return pkgGrep.contains("package:");
-    }
-
-    /**
-     * Determines if app was installed on device.
-     *
-     * @param packageName package name to check for
-     * @return <code>true</code> if file exists, <code>false</code> otherwise.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public boolean doesAppExistOnDevice(String packageName) throws IOException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        return doesRemoteFileExistContainingString(DEVICE_APP_PATH, packageName);
-    }
-
-    /**
-     * Determines if app was installed on SD card.
-     *
-     * @param packageName package name to check for
-     * @return <code>true</code> if file exists, <code>false</code> otherwise.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public boolean doesAppExistOnSDCard(String packageName) throws IOException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        return doesRemoteFileExistContainingString(SDCARD_APP_PATH, packageName);
-    }
-
-    /**
-     * Helper method to determine if app was installed on SD card.
-     *
-     * @param packageName package name to check for
-     * @return <code>true</code> if file exists, <code>false</code> otherwise.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public boolean doesAppExistAsForwardLocked(String packageName) throws IOException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        return doesRemoteFileExistContainingString(APP_PRIVATE_PATH, packageName);
-    }
-
-    /**
-     * Waits for device's package manager to respond.
-     *
-     * @throws InterruptedException
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public void waitForPackageManager() throws InterruptedException, IOException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "waiting for device");
-        int currentWaitTime = 0;
-        // poll the package manager until it returns something for android
-        while (!doesPackageExist("android")) {
-            Thread.sleep(WAIT_FOR_DEVICE_POLL_TIME);
-            currentWaitTime += WAIT_FOR_DEVICE_POLL_TIME;
-            if (currentWaitTime > MAX_WAIT_FOR_DEVICE_TIME) {
-                Log.e(LOG_TAG, "time out waiting for device");
-                throw new InterruptedException();
-            }
-        }
-    }
-
-    /**
-     * Helper to determine if the device is currently online and visible via ADB.
-     *
-     * @return true iff the device is currently available to ADB and online, false otherwise.
-     */
-    private boolean deviceIsOnline() {
-        AndroidDebugBridge bridge = AndroidDebugBridge.getBridge();
-        IDevice[] devices = bridge.getDevices();
-
-        for (IDevice device : devices) {
-            // only online if the device appears in the devices list, and its state is online
-            if ((mDevice != null) &&
-                    mDevice.getSerialNumber().equals(device.getSerialNumber()) &&
-                    device.isOnline()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Waits for device to be online (visible to ADB) before returning, or times out if we've
-     * waited too long. Note that this only means the device is visible via ADB, not that
-     * PackageManager is fully up and running yet.
-     *
-     * @throws InterruptedException
-     * @throws IOException
-     */
-    public void waitForDeviceToComeOnline() throws InterruptedException, IOException {
-        Log.i(LOG_TAG, "waiting for device to be online");
-        int currentWaitTime = 0;
-
-        // poll ADB until we see the device is online
-        while (!deviceIsOnline()) {
-            Thread.sleep(WAIT_FOR_DEVICE_POLL_TIME);
-            currentWaitTime += WAIT_FOR_DEVICE_POLL_TIME;
-            if (currentWaitTime > MAX_WAIT_FOR_DEVICE_TIME) {
-                Log.e(LOG_TAG, "time out waiting for device");
-                throw new InterruptedException();
-            }
-        }
-        // Note: if we try to access the device too quickly after it is "officially" online,
-        // there are sometimes strange issues where it's actually not quite ready yet,
-        // so we pause for a bit once more before actually returning.
-        Thread.sleep(WAIT_FOR_DEVICE_POLL_TIME);
-    }
-
-    /**
-     * Queries package manager and waits until a package is launched (or times out)
-     *
-     * @param packageName The name of the package to wait to load
-     * @throws InterruptedException
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public void waitForApp(String packageName) throws InterruptedException, IOException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "waiting for app to launch");
-        int currentWaitTime = 0;
-        // poll the package manager until it returns something for the package we're looking for
-        while (!doesPackageExist(packageName)) {
-            Thread.sleep(WAIT_FOR_APP_LAUNCH_POLL_TIME);
-            currentWaitTime += WAIT_FOR_APP_LAUNCH_POLL_TIME;
-            if (currentWaitTime > MAX_WAIT_FOR_APP_LAUNCH_TIME) {
-                Log.e(LOG_TAG, "time out waiting for app to launch: " + packageName);
-                throw new InterruptedException();
-            }
-        }
-    }
-
-    /**
-     * Helper method which executes a adb shell command and returns output as a {@link String}
-     * @return the output of the command
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public String executeShellCommand(String command) throws IOException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, String.format("adb shell %s", command));
-        CollectingOutputReceiver receiver = new CollectingOutputReceiver();
-        mDevice.executeShellCommand(command, receiver);
-        String output = receiver.getOutput();
-        Log.i(LOG_TAG, String.format("Result: %s", output));
-        return output;
-    }
-
-    /**
-     * Helper method ensures we are in root mode on the host side. It returns only after
-     * PackageManager is actually up and running.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public void runAdbRoot() throws IOException, InterruptedException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "adb root");
-        Runtime runtime = Runtime.getRuntime();
-        Process process = runtime.exec("adb root"); // adb should be in the path
-        BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream()));
-
-        String nextLine = null;
-        while (null != (nextLine = output.readLine())) {
-            Log.i(LOG_TAG, nextLine);
-        }
-        process.waitFor();
-        waitForDeviceToComeOnline();
-        waitForPackageManager(); // now wait for package manager to actually load
-    }
-
-    /**
-     * Helper method which reboots the device and returns once the device is online again
-     * and package manager is up and running (note this function is synchronous to callers).
-     * @throws InterruptedException
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public void rebootDevice() throws IOException, InterruptedException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        String command = "reboot"; // no need for -s since mDevice is already tied to a device
-        Log.i(LOG_TAG, command);
-        CollectingOutputReceiver receiver = new CollectingOutputReceiver();
-        mDevice.executeShellCommand(command, receiver);
-        String output = receiver.getOutput();
-        Log.i(LOG_TAG, String.format("Result: %s", output));
-        waitForDeviceToComeOnline(); // wait for device to come online
-        runAdbRoot();
-    }
-
-    /**
-     * A {@link IShellOutputReceiver} which collects the whole shell output into one {@link String}
-     */
-    private class CollectingOutputReceiver extends MultiLineReceiver {
-
-        private StringBuffer mOutputBuffer = new StringBuffer();
-
-        public String getOutput() {
-            return mOutputBuffer.toString();
-        }
-
-        @Override
-        public void processNewLines(String[] lines) {
-            for (String line: lines) {
-                mOutputBuffer.append(line);
-                mOutputBuffer.append("\n");
-            }
-        }
-
-        public boolean isCancelled() {
-            return false;
-        }
-    }
-
-    private class NullSyncProgressMonitor implements ISyncProgressMonitor {
-        public void advance(int work) {
-            // ignore
-        }
-
-        public boolean isCanceled() {
-            // ignore
-            return false;
-        }
-
-        public void start(int totalWork) {
-            // ignore
-
-        }
-
-        public void startSubTask(String name) {
-            // ignore
-        }
-
-        public void stop() {
-            // ignore
-        }
-    }
-
-    // For collecting results from running device tests
-    public static class CollectingTestRunListener implements ITestRunListener {
-
-        private boolean mAllTestsPassed = true;
-        private String mTestRunErrorMessage = null;
-
-        public void testEnded(TestIdentifier test, Map<String, String> metrics) {
-            // ignore
-        }
-
-        public void testFailed(TestFailure status, TestIdentifier test,
-                String trace) {
-            Log.w(LOG_TAG, String.format("%s#%s failed: %s", test.getClassName(),
-                    test.getTestName(), trace));
-            mAllTestsPassed = false;
-        }
-
-        public void testRunEnded(long elapsedTime, Map<String, String> resultBundle) {
-            // ignore
-        }
-
-        public void testRunFailed(String errorMessage) {
-            Log.w(LOG_TAG, String.format("test run failed: %s", errorMessage));
-            mAllTestsPassed = false;
-            mTestRunErrorMessage = errorMessage;
-        }
-
-        public void testRunStarted(String runName, int testCount) {
-            // ignore
-        }
-
-        public void testRunStopped(long elapsedTime) {
-            // ignore
-        }
-
-        public void testStarted(TestIdentifier test) {
-            // ignore
-        }
-
-        boolean didAllTestsPass() {
-            return mAllTestsPassed;
-        }
-
-        /**
-         * Get the test run failure error message.
-         * @return the test run failure error message or <code>null</code> if test run completed.
-         */
-        String getTestRunErrorMessage() {
-            return mTestRunErrorMessage;
-        }
-    }
-
-    /**
-     * Output receiver for "pm install package.apk" command line.
-     *
-     */
-    private static final class InstallReceiver extends MultiLineReceiver {
-
-        private static final String SUCCESS_OUTPUT = "Success"; //$NON-NLS-1$
-        private static final Pattern FAILURE_PATTERN = Pattern.compile("Failure\\s+\\[(.*)\\]"); //$NON-NLS-1$
-
-        private String mErrorMessage = null;
-
-        public InstallReceiver() {
-        }
-
-        @Override
-        public void processNewLines(String[] lines) {
-            for (String line : lines) {
-                if (line.length() > 0) {
-                    if (line.startsWith(SUCCESS_OUTPUT)) {
-                        mErrorMessage = null;
-                    } else {
-                        Matcher m = FAILURE_PATTERN.matcher(line);
-                        if (m.matches()) {
-                            mErrorMessage = m.group(1);
-                        }
-                    }
-                }
-            }
-        }
-
-        public boolean isCancelled() {
-            return false;
-        }
-
-        public String getErrorMessage() {
-            return mErrorMessage;
-        }
-    }
-
-    /**
-     * Helper method for installing an app to wherever is specified in its manifest, and
-     * then verifying the app was installed onto SD Card.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     *
-     * @param the path of the apk to install
-     * @param the name of the package
-     * @param <code>true</code> if the app should be overwritten, <code>false</code> otherwise
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void installAppAndVerifyExistsOnSDCard(String apkPath, String pkgName, boolean overwrite)
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        // Start with a clean slate if we're not overwriting
-        if (!overwrite) {
-            // cleanup test app just in case it already exists
-            mDevice.uninstallPackage(pkgName);
-            // grep for package to make sure its not installed
-            assertFalse(doesPackageExist(pkgName));
-        }
-
-        installFile(apkPath, overwrite);
-        assertTrue(doesAppExistOnSDCard(pkgName));
-        assertFalse(doesAppExistOnDevice(pkgName));
-        waitForPackageManager();
-
-        // grep for package to make sure it is installed
-        assertTrue(doesPackageExist(pkgName));
-    }
-
-    /**
-     * Helper method for installing an app to wherever is specified in its manifest, and
-     * then verifying the app was installed onto device.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     *
-     * @param the path of the apk to install
-     * @param the name of the package
-     * @param <code>true</code> if the app should be overwritten, <code>false</code> otherwise
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void installAppAndVerifyExistsOnDevice(String apkPath, String pkgName, boolean overwrite)
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        // Start with a clean slate if we're not overwriting
-        if (!overwrite) {
-            // cleanup test app just in case it already exists
-            mDevice.uninstallPackage(pkgName);
-            // grep for package to make sure its not installed
-            assertFalse(doesPackageExist(pkgName));
-        }
-
-        installFile(apkPath, overwrite);
-        assertFalse(doesAppExistOnSDCard(pkgName));
-        assertTrue(doesAppExistOnDevice(pkgName));
-        waitForPackageManager();
-
-        // grep for package to make sure it is installed
-        assertTrue(doesPackageExist(pkgName));
-    }
-
-    /**
-     * Helper method for installing an app as forward-locked, and
-     * then verifying the app was installed in the proper forward-locked location.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     *
-     * @param the path of the apk to install
-     * @param the name of the package
-     * @param <code>true</code> if the app should be overwritten, <code>false</code> otherwise
-     * @throws InterruptedException if the thread was interrupted
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     */
-    public void installFwdLockedAppAndVerifyExists(String apkPath,
-            String pkgName, boolean overwrite) throws IOException, InterruptedException,
-            InstallException, SyncException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        // Start with a clean slate if we're not overwriting
-        if (!overwrite) {
-            // cleanup test app just in case it already exists
-            mDevice.uninstallPackage(pkgName);
-            // grep for package to make sure its not installed
-            assertFalse(doesPackageExist(pkgName));
-        }
-
-        String result = installFileForwardLocked(apkPath, overwrite);
-        assertEquals(null, result);
-        assertTrue(doesAppExistAsForwardLocked(pkgName));
-        assertFalse(doesAppExistOnSDCard(pkgName));
-        waitForPackageManager();
-
-        // grep for package to make sure it is installed
-        assertTrue(doesPackageExist(pkgName));
-    }
-
-    /**
-     * Helper method for uninstalling an app.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     *
-     * @param pkgName package name to uninstall
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the uninstall failed.
-     */
-    public void uninstallApp(String pkgName) throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        mDevice.uninstallPackage(pkgName);
-        // make sure its not installed anymore
-        assertFalse(doesPackageExist(pkgName));
-    }
-
-    /**
-     * Helper method for clearing any installed non-system apps.
-     * Useful ensuring no non-system apps are installed, and for cleaning up stale files that
-     * may be lingering on the system for whatever reason.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     *
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the uninstall failed.
-     */
-    public void wipeNonSystemApps() throws IOException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException, InstallException {
-      String allInstalledPackages = executeShellCommand("pm list packages -f");
-      BufferedReader outputReader = new BufferedReader(new StringReader(allInstalledPackages));
-
-      // First use Package Manager to uninstall all non-system apps
-      String currentLine = null;
-      while ((currentLine = outputReader.readLine()) != null) {
-          // Skip over any system apps...
-          if (currentLine.contains("/system/")) {
-              continue;
-          }
-          String packageName = currentLine.substring(currentLine.indexOf('=') + 1);
-          mDevice.uninstallPackage(packageName);
-      }
-      // Make sure there are no stale app files under these directories
-      executeShellCommand(String.format("rm %s*", SDCARD_APP_PATH, "*"));
-      executeShellCommand(String.format("rm %s*", DEVICE_APP_PATH, "*"));
-      executeShellCommand(String.format("rm %s*", APP_PRIVATE_PATH, "*"));
-    }
-
-    /**
-     * Sets the device's install location preference.
-     *
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public void setDevicePreferredInstallLocation(InstallLocPreference pref) throws IOException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        String command = "pm setInstallLocation %d";
-        int locValue = 0;
-        switch (pref) {
-            case INTERNAL:
-                locValue = 1;
-                break;
-            case EXTERNAL:
-                locValue = 2;
-                break;
-            default: // AUTO
-                locValue = 0;
-                break;
-        }
-        executeShellCommand(String.format(command, locValue));
-    }
-
-    /**
-     * Gets the device's install location preference.
-     *
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     */
-    public InstallLocPreference getDevicePreferredInstallLocation() throws IOException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        String result = executeShellCommand("pm getInstallLocation");
-        if (result.indexOf('0') != -1) {
-            return InstallLocPreference.AUTO;
-        }
-        else if (result.indexOf('1') != -1) {
-            return InstallLocPreference.INTERNAL;
-        }
-        else {
-            return InstallLocPreference.EXTERNAL;
-        }
-    }
-}
diff --git a/core/tests/hosttests/src/android/content/pm/PackageManagerHostTests.java b/core/tests/hosttests/src/android/content/pm/PackageManagerHostTests.java
deleted file mode 100644
index 22a2be6..0000000
--- a/core/tests/hosttests/src/android/content/pm/PackageManagerHostTests.java
+++ /dev/null
@@ -1,1224 +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.
- */
-
-package android.content.pm;
-
-import com.android.ddmlib.AdbCommandRejectedException;
-import com.android.ddmlib.InstallException;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.ShellCommandUnresponsiveException;
-import com.android.ddmlib.SyncException;
-import com.android.ddmlib.TimeoutException;
-import com.android.hosttest.DeviceTestCase;
-import com.android.hosttest.DeviceTestSuite;
-
-import java.io.File;
-import java.io.IOException;
-
-import junit.framework.Test;
-
-/**
- * Set of tests that verify host side install cases
- */
-public class PackageManagerHostTests extends DeviceTestCase {
-
-    private static final String LOG_TAG = "PackageManagerHostTests";
-    private PackageManagerHostTestUtils mPMHostUtils = null;
-
-    private String appPrivatePath = null;
-    private String deviceAppPath = null;
-    private String sdcardAppPath = null;
-
-    // Various test files and their corresponding package names...
-
-    // testPushAppPrivate constants
-    // these constants must match values defined in test-apps/SimpleTestApp
-    private static final String SIMPLE_APK = "SimpleTestApp.apk";
-    private static final String SIMPLE_PKG = "com.android.framework.simpletestapp";
-
-    // Apk with install location set to auto
-    private static final String AUTO_LOC_APK = "AutoLocTestApp.apk";
-    private static final String AUTO_LOC_PKG = "com.android.framework.autoloctestapp";
-    // Apk with install location set to internalOnly
-    private static final String INTERNAL_LOC_APK = "InternalLocTestApp.apk";
-    private static final String INTERNAL_LOC_PKG = "com.android.framework.internalloctestapp";
-    // Apk with install location set to preferExternal
-    private static final String EXTERNAL_LOC_APK = "ExternalLocTestApp.apk";
-    private static final String EXTERNAL_LOC_PKG = "com.android.framework.externalloctestapp";
-    // Apk with install location set to auto (2 versions, for update testing)
-    private static final String AUTO_LOC_VERSION_V1_APK = "AutoLocVersionedTestApp_v1.apk";
-    private static final String AUTO_LOC_VERSION_V2_APK = "AutoLocVersionedTestApp_v2.apk";
-    private static final String AUTO_LOC_VERSION_PKG =
-            "com.android.framework.autolocversionedtestapp";
-    // Apk with install location set to preferExternal (2 versions, for update testing)
-    private static final String EXTERNAL_LOC_VERSION_V1_APK = "ExternalLocVersionedTestApp_v1.apk";
-    private static final String EXTERNAL_LOC_VERSION_V2_APK = "ExternalLocVersionedTestApp_v2.apk";
-    private static final String EXTERNAL_LOC_VERSION_PKG =
-            "com.android.framework.externallocversionedtestapp";
-    // Apk with install location set to auto (2 versions, for update testing)
-    private static final String NO_LOC_VERSION_V1_APK = "NoLocVersionedTestApp_v1.apk";
-    private static final String NO_LOC_VERSION_V2_APK = "NoLocVersionedTestApp_v2.apk";
-    private static final String NO_LOC_VERSION_PKG =
-            "com.android.framework.nolocversionedtestapp";
-    // Apk with no install location set
-    private static final String NO_LOC_APK = "NoLocTestApp.apk";
-    private static final String NO_LOC_PKG = "com.android.framework.noloctestapp";
-    // Apk with 2 different versions - v1 is set to external, v2 has no location setting
-    private static final String UPDATE_EXTERNAL_LOC_V1_EXT_APK
-            = "UpdateExternalLocTestApp_v1_ext.apk";
-    private static final String UPDATE_EXTERNAL_LOC_V2_NONE_APK
-            = "UpdateExternalLocTestApp_v2_none.apk";
-    private static final String UPDATE_EXTERNAL_LOC_PKG
-            = "com.android.framework.updateexternalloctestapp";
-    // Apk with 2 different versions - v1 is set to external, v2 is set to internalOnly
-    private static final String UPDATE_EXT_TO_INT_LOC_V1_EXT_APK
-            = "UpdateExtToIntLocTestApp_v1_ext.apk";
-    private static final String UPDATE_EXT_TO_INT_LOC_V2_INT_APK
-            = "UpdateExtToIntLocTestApp_v2_int.apk";
-    private static final String UPDATE_EXT_TO_INT_LOC_PKG
-            = "com.android.framework.updateexttointloctestapp";
-    // Apk set to preferExternal, with Access Fine Location permissions set in its manifest
-    private static final String FL_PERMS_APK = "ExternalLocPermsFLTestApp.apk";
-    private static final String FL_PERMS_PKG = "com.android.framework.externallocpermsfltestapp";
-    // Apk set to preferExternal, with all permissions set in manifest
-    private static final String ALL_PERMS_APK = "ExternalLocAllPermsTestApp.apk";
-    private static final String ALL_PERMS_PKG = "com.android.framework.externallocallpermstestapp";
-    // Apks with the same package name, but install location set to
-    // one of: Internal, External, Auto, or None
-    private static final String VERSATILE_LOC_PKG = "com.android.framework.versatiletestapp";
-    private static final String VERSATILE_LOC_INTERNAL_APK = "VersatileTestApp_Internal.apk";
-    private static final String VERSATILE_LOC_EXTERNAL_APK = "VersatileTestApp_External.apk";
-    private static final String VERSATILE_LOC_AUTO_APK = "VersatileTestApp_Auto.apk";
-    private static final String VERSATILE_LOC_NONE_APK = "VersatileTestApp_None.apk";
-    // Apks with shared UserID
-    private static final String SHARED_PERMS_APK = "ExternalSharedPermsTestApp.apk";
-    private static final String SHARED_PERMS_PKG
-            = "com.android.framework.externalsharedpermstestapp";
-    private static final String SHARED_PERMS_FL_APK = "ExternalSharedPermsFLTestApp.apk";
-    private static final String SHARED_PERMS_FL_PKG
-            = "com.android.framework.externalsharedpermsfltestapp";
-    private static final String SHARED_PERMS_BT_APK = "ExternalSharedPermsBTTestApp.apk";
-    private static final String SHARED_PERMS_BT_PKG
-            = "com.android.framework.externalsharedpermsbttestapp";
-    // Apk with shared UserID, but signed with a different cert (the media cert)
-    private static final String SHARED_PERMS_DIFF_KEY_APK = "ExternalSharedPermsDiffKeyTestApp.apk";
-    private static final String SHARED_PERMS_DIFF_KEY_PKG
-            = "com.android.framework.externalsharedpermsdiffkeytestapp";
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        // ensure apk path has been set before test is run
-        assertNotNull(getTestAppPath());
-
-        // setup the PackageManager host tests utilities class, and get various paths we'll need...
-        mPMHostUtils = new PackageManagerHostTestUtils(getDevice());
-        appPrivatePath = mPMHostUtils.getAppPrivatePath();
-        deviceAppPath = mPMHostUtils.getDeviceAppPath();
-        sdcardAppPath = mPMHostUtils.getSDCardAppPath();
-
-        // Ensure the default is set to let the system decide where to install apps
-        // (It's ok for individual tests to override and change this during their test, but should
-        // reset it back when they're done)
-        mPMHostUtils.setDevicePreferredInstallLocation(
-                PackageManagerHostTestUtils.InstallLocPreference.AUTO);
-    }
-
-    /**
-     * Get the absolute file system location of test app with given filename
-     * @param fileName the file name of the test app apk
-     * @return {@link String} of absolute file path
-     */
-    public String getTestAppFilePath(String fileName) {
-        return String.format("%s%s%s", getTestAppPath(), File.separator, fileName);
-    }
-
-    public static Test suite() {
-        return new DeviceTestSuite(PackageManagerHostTests.class);
-    }
-
-    /**
-     * Regression test to verify that pushing an apk to the private app directory doesn't install
-     * the app, and otherwise cause the system to blow up.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public void testPushAppPrivate() throws IOException, InterruptedException, InstallException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
-            SyncException {
-        Log.i(LOG_TAG, "testing pushing an apk to /data/app-private");
-        final String apkAppPrivatePath =  appPrivatePath + SIMPLE_APK;
-
-        // cleanup test app just in case it was accidently installed
-        getDevice().uninstallPackage(SIMPLE_PKG);
-        mPMHostUtils.executeShellCommand("stop");
-        mPMHostUtils.pushFile(getTestAppFilePath(SIMPLE_APK), apkAppPrivatePath);
-
-        // sanity check to make sure file is there
-        assertTrue(mPMHostUtils.doesRemoteFileExist(apkAppPrivatePath));
-        mPMHostUtils.executeShellCommand("start");
-
-        mPMHostUtils.waitForPackageManager();
-
-        // grep for package to make sure its not installed
-        assertFalse(mPMHostUtils.doesPackageExist(SIMPLE_PKG));
-        // ensure it has been deleted from app-private
-        assertFalse(mPMHostUtils.doesRemoteFileExist(apkAppPrivatePath));
-    }
-
-    /**
-     * Helper to do a standard install of an apk and verify it installed to the correct location.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @param apkName the file name of the test app apk
-     * @param pkgName the package name of the test app apk
-     * @param expectedLocation the file name of the test app apk
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    private void doStandardInstall(String apkName, String pkgName,
-            PackageManagerHostTestUtils.InstallLocation expectedLocation)
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-
-        if (expectedLocation == PackageManagerHostTestUtils.InstallLocation.DEVICE) {
-            mPMHostUtils.installAppAndVerifyExistsOnDevice(
-                    getTestAppFilePath(apkName), pkgName, false);
-        }
-        else {
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(
-                    getTestAppFilePath(apkName), pkgName, false);
-        }
-    }
-
-    /**
-     * Installs the Auto app using the preferred device install location specified,
-     * and verifies it was installed on the device.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @param preference the device's preferred location of where to install apps
-     * @param expectedLocation the expected location of where the apk was installed
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void installAppAutoLoc(PackageManagerHostTestUtils.InstallLocPreference preference,
-            PackageManagerHostTestUtils.InstallLocation expectedLocation)
-            throws IOException, InterruptedException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException, InstallException {
-
-        PackageManagerHostTestUtils.InstallLocPreference savedPref =
-                PackageManagerHostTestUtils.InstallLocPreference.AUTO;
-
-        try {
-            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
-            mPMHostUtils.setDevicePreferredInstallLocation(preference);
-
-            doStandardInstall(AUTO_LOC_APK, AUTO_LOC_PKG, expectedLocation);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
-            mPMHostUtils.uninstallApp(AUTO_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=auto
-     * will install the app to the device when device's preference is auto.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppAutoLocPrefIsAuto() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=auto, prefer=auto gets installed on device");
-        installAppAutoLoc(PackageManagerHostTestUtils.InstallLocPreference.AUTO,
-                PackageManagerHostTestUtils.InstallLocation.DEVICE);
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=auto
-     * will install the app to the device when device's preference is internal.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppAutoLocPrefIsInternal() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=auto, prefer=internal gets installed on device");
-        installAppAutoLoc(PackageManagerHostTestUtils.InstallLocPreference.INTERNAL,
-                PackageManagerHostTestUtils.InstallLocation.DEVICE);
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=auto
-     * will install the app to the SD card when device's preference is external.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppAutoLocPrefIsExternal() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=auto, prefer=external gets installed on device");
-        installAppAutoLoc(PackageManagerHostTestUtils.InstallLocPreference.EXTERNAL,
-                PackageManagerHostTestUtils.InstallLocation.DEVICE);
-    }
-
-    /**
-     * Installs the Internal app using the preferred device install location specified,
-     * and verifies it was installed to the location expected.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @param preference the device's preferred location of where to install apps
-     * @param expectedLocation the expected location of where the apk was installed
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the (un)install failed.
-     */
-    public void installAppInternalLoc(PackageManagerHostTestUtils.InstallLocPreference preference,
-            PackageManagerHostTestUtils.InstallLocation expectedLocation)
-            throws IOException, InterruptedException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException, InstallException {
-
-        PackageManagerHostTestUtils.InstallLocPreference savedPref =
-            PackageManagerHostTestUtils.InstallLocPreference.AUTO;
-
-        try {
-            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
-            mPMHostUtils.setDevicePreferredInstallLocation(preference);
-
-            doStandardInstall(INTERNAL_LOC_APK, INTERNAL_LOC_PKG, expectedLocation);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
-            mPMHostUtils.uninstallApp(INTERNAL_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=internalOnly
-     * will install the app to the device when device's preference is auto.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppInternalLocPrefIsAuto() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=internal, prefer=auto gets installed on device");
-        installAppInternalLoc(PackageManagerHostTestUtils.InstallLocPreference.AUTO,
-                PackageManagerHostTestUtils.InstallLocation.DEVICE);
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=internalOnly
-     * will install the app to the device when device's preference is internal.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppInternalLocPrefIsInternal() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=internal, prefer=internal is installed on device");
-        installAppInternalLoc(PackageManagerHostTestUtils.InstallLocPreference.INTERNAL,
-                PackageManagerHostTestUtils.InstallLocation.DEVICE);
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=internalOnly
-     * will install the app to the device when device's preference is external.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppInternalLocPrefIsExternal() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=internal, prefer=external is installed on device");
-        installAppInternalLoc(PackageManagerHostTestUtils.InstallLocPreference.EXTERNAL,
-                PackageManagerHostTestUtils.InstallLocation.DEVICE);
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=preferExternal
-     * will install the app to the SD card.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @param preference the device's preferred location of where to install apps
-     * @param expectedLocation the expected location of where the apk was installed
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void installAppExternalLoc(PackageManagerHostTestUtils.InstallLocPreference preference,
-            PackageManagerHostTestUtils.InstallLocation expectedLocation)
-            throws IOException, InterruptedException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException, InstallException {
-
-        PackageManagerHostTestUtils.InstallLocPreference savedPref =
-            PackageManagerHostTestUtils.InstallLocPreference.AUTO;
-
-        try {
-            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
-            mPMHostUtils.setDevicePreferredInstallLocation(preference);
-
-            doStandardInstall(EXTERNAL_LOC_APK, EXTERNAL_LOC_PKG, expectedLocation);
-
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
-            mPMHostUtils.uninstallApp(EXTERNAL_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=preferExternal
-     * will install the app to the device when device's preference is auto.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppExternalLocPrefIsAuto() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=external, pref=auto gets installed on SD Card");
-        installAppExternalLoc(PackageManagerHostTestUtils.InstallLocPreference.AUTO,
-                PackageManagerHostTestUtils.InstallLocation.SDCARD);
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=preferExternal
-     * will install the app to the device when device's preference is internal.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppExternalLocPrefIsInternal() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=external, pref=internal gets installed on SD Card");
-        installAppExternalLoc(PackageManagerHostTestUtils.InstallLocPreference.INTERNAL,
-                PackageManagerHostTestUtils.InstallLocation.SDCARD);
-    }
-
-    /**
-     * Regression test to verify that an app with its manifest set to installLocation=preferExternal
-     * will install the app to the device when device's preference is external.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppExternalLocPrefIsExternal() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installLocation=external, pref=external gets installed on SD Card");
-        installAppExternalLoc(PackageManagerHostTestUtils.InstallLocPreference.EXTERNAL,
-                PackageManagerHostTestUtils.InstallLocation.SDCARD);
-    }
-
-    /**
-     * Regression test to verify that an app without installLocation in its manifest
-     * will install the app to the device by default when the system default pref is to let the
-     * system decide.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppNoLocPrefIsAuto() throws IOException, InterruptedException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
-            InstallException {
-        Log.i(LOG_TAG, "Test an app with no installLocation gets installed on device");
-
-        PackageManagerHostTestUtils.InstallLocPreference savedPref =
-            PackageManagerHostTestUtils.InstallLocPreference.AUTO;
-
-        try {
-            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
-            mPMHostUtils.setDevicePreferredInstallLocation(
-                    PackageManagerHostTestUtils.InstallLocPreference.AUTO);
-            mPMHostUtils.installAppAndVerifyExistsOnDevice(
-                    getTestAppFilePath(NO_LOC_APK), NO_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
-            mPMHostUtils.uninstallApp(NO_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app without installLocation in its manifest
-     * will install the app to the device by default when the system default pref is to install
-     * external.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppNoLocPrefIsExternal() throws IOException, InterruptedException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
-            InstallException {
-        Log.i(LOG_TAG, "Test an app with no installLocation gets installed on SD card");
-
-        PackageManagerHostTestUtils.InstallLocPreference savedPref =
-            PackageManagerHostTestUtils.InstallLocPreference.AUTO;
-
-        try {
-            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
-            mPMHostUtils.setDevicePreferredInstallLocation(
-                    PackageManagerHostTestUtils.InstallLocPreference.EXTERNAL);
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(
-                    getTestAppFilePath(NO_LOC_APK), NO_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
-            mPMHostUtils.uninstallApp(NO_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app without installLocation in its manifest
-     * will install the app to the device by default when the system default pref is to install
-     * internal.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAppNoLocPrefIsInternal() throws IOException, InterruptedException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
-            InstallException {
-        Log.i(LOG_TAG, "Test an app with no installLocation gets installed on device");
-
-        PackageManagerHostTestUtils.InstallLocPreference savedPref =
-            PackageManagerHostTestUtils.InstallLocPreference.AUTO;
-
-        try {
-            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
-            mPMHostUtils.setDevicePreferredInstallLocation(
-                    PackageManagerHostTestUtils.InstallLocPreference.INTERNAL);
-            mPMHostUtils.installAppAndVerifyExistsOnDevice(
-                    getTestAppFilePath(NO_LOC_APK), NO_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
-            mPMHostUtils.uninstallApp(NO_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with its installLocation set to internal that is
-     * forward-locked will get installed to the correct location.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallFwdLockedAppInternal() throws IOException, InterruptedException,
-            InstallException, SyncException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test an app with installLoc set to Internal gets installed to app-private");
-
-        try {
-            mPMHostUtils.installFwdLockedAppAndVerifyExists(
-                    getTestAppFilePath(INTERNAL_LOC_APK), INTERNAL_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(INTERNAL_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with its installLocation set to external that is
-     * forward-locked will get installed to the correct location.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallFwdLockedAppExternal() throws IOException, InterruptedException,
-            InstallException, SyncException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test an app with installLoc set to Internal gets installed to app-private");
-
-        try {
-            mPMHostUtils.installFwdLockedAppAndVerifyExists(
-                    getTestAppFilePath(INTERNAL_LOC_APK), INTERNAL_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(INTERNAL_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with its installLocation set to external that is
-     * forward-locked will get installed to the correct location.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallFwdLockedAppAuto() throws IOException, InterruptedException,
-            InstallException, SyncException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test an app with installLoc set to Auto gets installed to app-private");
-
-        try {
-            mPMHostUtils.installFwdLockedAppAndVerifyExists(
-                    getTestAppFilePath(AUTO_LOC_APK), AUTO_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(AUTO_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with no installLocation set and is
-     * forward-locked installed will get installed to the correct location.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallFwdLockedAppNone() throws IOException, InterruptedException,
-            InstallException, SyncException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test an app with no installLoc set gets installed to app-private");
-
-        try {
-            mPMHostUtils.installFwdLockedAppAndVerifyExists(
-                    getTestAppFilePath(NO_LOC_APK), NO_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(NO_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that we can install an app onto the device,
-     * uninstall it, and reinstall it onto the SD card.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    // TODO: This currently relies on the app's manifest to switch from device to
-    // SD card install locations. We might want to make Device's installPackage()
-    // accept a installLocation flag so we can install a package to the
-    // destination of our choosing.
-    public void testReinstallInternalToExternal() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installing an app first to the device, then to the SD Card");
-
-        try {
-            mPMHostUtils.installAppAndVerifyExistsOnDevice(
-                    getTestAppFilePath(VERSATILE_LOC_INTERNAL_APK), VERSATILE_LOC_PKG, false);
-            mPMHostUtils.uninstallApp(VERSATILE_LOC_PKG);
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(
-                    getTestAppFilePath(VERSATILE_LOC_EXTERNAL_APK), VERSATILE_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(VERSATILE_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that we can install an app onto the SD Card,
-     * uninstall it, and reinstall it onto the device.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    // TODO: This currently relies on the app's manifest to switch from device to
-    // SD card install locations. We might want to make Device's installPackage()
-    // accept a installLocation flag so we can install a package to the
-    // destination of our choosing.
-    public void testReinstallExternalToInternal() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installing an app first to the SD Care, then to the device");
-
-        try {
-            // install the app externally
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(
-                    getTestAppFilePath(VERSATILE_LOC_EXTERNAL_APK), VERSATILE_LOC_PKG, false);
-            mPMHostUtils.uninstallApp(VERSATILE_LOC_PKG);
-            // then replace the app with one marked for internalOnly
-            mPMHostUtils.installAppAndVerifyExistsOnDevice(
-                    getTestAppFilePath(VERSATILE_LOC_INTERNAL_APK), VERSATILE_LOC_PKG, false);
-        }
-        // cleanup test app
-        finally {
-          mPMHostUtils.uninstallApp(VERSATILE_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that updating an app on the SD card will install
-     * the update onto the SD card as well when location is set to external for both versions
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testUpdateBothExternal() throws IOException, InterruptedException, InstallException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test updating an app on the SD card stays on the SD card");
-
-        try {
-            // install the app externally
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    EXTERNAL_LOC_VERSION_V1_APK), EXTERNAL_LOC_VERSION_PKG, false);
-            // now replace the app with one where the location is still set to preferExternal
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    EXTERNAL_LOC_VERSION_V2_APK), EXTERNAL_LOC_VERSION_PKG, true);
-        }
-        // cleanup test app
-        finally {
-          mPMHostUtils.uninstallApp(EXTERNAL_LOC_VERSION_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that updating an app on the SD card will install
-     * the update onto the SD card as well when location is not explicitly set in the
-     * updated apps' manifest file.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testUpdateToSDCard() throws IOException, InterruptedException, InstallException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test updating an app on the SD card stays on the SD card");
-
-        try {
-            // install the app externally
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    UPDATE_EXTERNAL_LOC_V1_EXT_APK), UPDATE_EXTERNAL_LOC_PKG, false);
-            // now replace the app with one where the location is blank (app should stay external)
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    UPDATE_EXTERNAL_LOC_V2_NONE_APK), UPDATE_EXTERNAL_LOC_PKG, true);
-        }
-        // cleanup test app
-        finally {
-          mPMHostUtils.uninstallApp(UPDATE_EXTERNAL_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that updating an app on the SD card will install
-     * the update onto the device if the manifest has changed to installLocation=internalOnly
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testUpdateSDCardToDevice() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test updating an app on the SD card to the Device through manifest change");
-
-        try {
-            // install the app externally
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    UPDATE_EXT_TO_INT_LOC_V1_EXT_APK), UPDATE_EXT_TO_INT_LOC_PKG, false);
-            // now replace the app with an update marked for internalOnly...(should move internal)
-            mPMHostUtils.installAppAndVerifyExistsOnDevice(getTestAppFilePath(
-                    UPDATE_EXT_TO_INT_LOC_V2_INT_APK), UPDATE_EXT_TO_INT_LOC_PKG, true);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(UPDATE_EXT_TO_INT_LOC_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that installing and updating a forward-locked app will install
-     * the update onto the device's forward-locked location
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndUpdateExternalLocForwardLockedApp()
-            throws IOException, InterruptedException, InstallException, SyncException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test updating a forward-locked app marked preferExternal");
-
-        try {
-            // first try to install the forward-locked app externally
-            mPMHostUtils.installFwdLockedAppAndVerifyExists(getTestAppFilePath(
-                    EXTERNAL_LOC_VERSION_V1_APK), EXTERNAL_LOC_VERSION_PKG, false);
-            // now replace the app with an update marked for internalOnly and as forward locked
-            mPMHostUtils.installFwdLockedAppAndVerifyExists(getTestAppFilePath(
-                    EXTERNAL_LOC_VERSION_V2_APK), EXTERNAL_LOC_VERSION_PKG, true);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(EXTERNAL_LOC_VERSION_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that updating a forward-locked app will install
-     * the update onto the device's forward-locked location
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndUpdateNoLocForwardLockedApp()
-            throws IOException, InterruptedException, InstallException, SyncException,
-            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test updating a forward-locked app with no installLocation pref set");
-
-        try {
-            // install the app
-            mPMHostUtils.installFwdLockedAppAndVerifyExists(getTestAppFilePath(
-                    NO_LOC_VERSION_V1_APK), NO_LOC_VERSION_PKG, false);
-            // now replace the app with an update marked for internalOnly...
-            mPMHostUtils.installFwdLockedAppAndVerifyExists(getTestAppFilePath(
-                    NO_LOC_VERSION_V2_APK), NO_LOC_VERSION_PKG, true);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(NO_LOC_VERSION_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with all permissions set can be installed on SD card
-     * and then launched without crashing.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws SyncException if the sync failed for another reason.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndLaunchAllPermsAppOnSD()
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test launching an app with all perms set, installed on SD card");
-
-        try {
-            // install the app
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    ALL_PERMS_APK), ALL_PERMS_PKG, false);
-            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(ALL_PERMS_PKG);
-            assert(testsPassed);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(ALL_PERMS_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with ACCESS_FINE_LOCATION (GPS) permissions can
-     * run without permissions errors.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndLaunchFLPermsAppOnSD()
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test launching an app with location perms set, installed on SD card");
-
-        try {
-            // install the app and verify we can launch it without permissions errors
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_FL_APK), SHARED_PERMS_FL_PKG, false);
-            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_FL_PKG);
-            assert(testsPassed);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(SHARED_PERMS_FL_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with BLUE_TOOTH permissions can
-     * run without permissions errors.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndLaunchBTPermsAppOnSD()
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test launching an app with bluetooth perms set, installed on SD card");
-
-        try {
-            // install the app and verify we can launch it without permissions errors
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_BT_APK), SHARED_PERMS_BT_PKG, false);
-            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_BT_PKG);
-            assert(testsPassed);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(SHARED_PERMS_BT_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that a shared app with no explicit permissions throws a
-     * SecurityException when launched if its other shared apps are not installed.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndLaunchSharedPermsAppOnSD_NoPerms()
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test launching an app with no explicit perms set, installed on SD card");
-
-        try {
-            // Make sure the 2 shared apps with needed permissions are not installed...
-            mPMHostUtils.uninstallApp(SHARED_PERMS_FL_PKG);
-            mPMHostUtils.uninstallApp(SHARED_PERMS_BT_PKG);
-
-            // now install the app and see if when we launch it we get a permissions error
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_APK), SHARED_PERMS_PKG, false);
-
-            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_PKG);
-            assertEquals("Shared perms app should fail to run", false, testsPassed);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(SHARED_PERMS_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that a shared app with no explicit permissions can run if its other
-     * shared apps are installed.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndLaunchSharedPermsAppOnSD_GrantedPerms()
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test launching an app with no explicit perms set, installed on SD card");
-
-        try {
-            // install the 2 shared apps with needed permissions first
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_FL_APK), SHARED_PERMS_FL_PKG, false);
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_BT_APK), SHARED_PERMS_BT_PKG, false);
-
-            // now install the test app and see if we can launch it without errors
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_APK), SHARED_PERMS_PKG, false);
-            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_PKG);
-            assert(testsPassed);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(SHARED_PERMS_PKG);
-            mPMHostUtils.uninstallApp(SHARED_PERMS_BT_PKG);
-            mPMHostUtils.uninstallApp(SHARED_PERMS_FL_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that an app with ACCESS_FINE_LOCATION (GPS) permissions can
-     * run without permissions errors even after a reboot
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndLaunchFLPermsAppOnSD_Reboot()
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test launching an app with location perms set, installed on SD card");
-
-        try {
-            // install the app and verify we can launch it without permissions errors
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_FL_APK), SHARED_PERMS_FL_PKG, false);
-            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_FL_PKG);
-            assert(testsPassed);
-
-            mPMHostUtils.rebootDevice();
-
-            testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_FL_PKG);
-            assert(testsPassed);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(SHARED_PERMS_FL_PKG);
-        }
-    }
-
-    /**
-     * Regression test to verify that a shared app with no explicit permissions can run if its other
-     * shared apps are installed, even after a reboot.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     * @throws InterruptedException if the thread was interrupted
-     * @throws TimeoutException in case of a timeout on the connection.
-     * @throws AdbCommandRejectedException if adb rejects the command
-     * @throws ShellCommandUnresponsiveException if the device did not output anything for
-     * a period longer than the max time to output.
-     * @throws IOException if connection to device was lost.
-     * @throws InstallException if the install failed.
-     */
-    public void testInstallAndLaunchSharedPermsAppOnSD_Reboot()
-            throws IOException, InterruptedException, InstallException, TimeoutException,
-            AdbCommandRejectedException, ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test launching an app on SD, with no explicit perms set after reboot");
-
-        try {
-            // install the 2 shared apps with needed permissions first
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_FL_APK), SHARED_PERMS_FL_PKG, false);
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_BT_APK), SHARED_PERMS_BT_PKG, false);
-
-            // now install the test app and see if we can launch it without errors
-            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
-                    SHARED_PERMS_APK), SHARED_PERMS_PKG, false);
-            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_PKG);
-            assert(testsPassed);
-
-            // reboot
-            mPMHostUtils.rebootDevice();
-
-            // Verify we can still launch the app
-            testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_PKG);
-            assert(testsPassed);
-        }
-        // cleanup test app
-        finally {
-            mPMHostUtils.uninstallApp(SHARED_PERMS_PKG);
-            mPMHostUtils.uninstallApp(SHARED_PERMS_BT_PKG);
-            mPMHostUtils.uninstallApp(SHARED_PERMS_FL_PKG);
-        }
-    }
-}
diff --git a/core/tests/hosttests/src/android/content/pm/PackageManagerStressHostTests.java b/core/tests/hosttests/src/android/content/pm/PackageManagerStressHostTests.java
deleted file mode 100644
index a2a5dd3..0000000
--- a/core/tests/hosttests/src/android/content/pm/PackageManagerStressHostTests.java
+++ /dev/null
@@ -1,297 +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.
- */
-
-package android.content.pm;
-
-import com.android.ddmlib.AdbCommandRejectedException;
-import com.android.ddmlib.InstallException;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.ShellCommandUnresponsiveException;
-import com.android.ddmlib.TimeoutException;
-import com.android.hosttest.DeviceTestCase;
-import com.android.hosttest.DeviceTestSuite;
-
-import java.io.File;
-import java.io.IOException;
-
-import junit.framework.Test;
-
-/**
- * Set of tests that verify host side stress scenarios (large apps, multiple upgrades, etc.)
- */
-public class PackageManagerStressHostTests extends DeviceTestCase {
-
-    private static final String LOG_TAG = "PackageManagerStressHostTests";
-    private PackageManagerHostTestUtils mPMHostUtils = null;
-
-    // Path to the app repository and various subdirectories of it
-    // Note: These stress tests require large apks that cannot be checked into the tree.
-    // These variables define static locations that point to existing APKs (not built from
-    // the tree) which can be used by the the stress tests in this file.
-    private static final String LARGE_APPS_DIRECTORY_NAME = "largeApps";
-    private static final String MISC_APPS_DIRECTORY_NAME = "miscApps";
-    private static final String VERSIONED_APPS_DIRECTORY_NAME = "versionedApps";
-    private static final String MANY_APPS_DIRECTORY_NAME = "manyApps";
-
-    // Note: An external environment variable "ANDROID_TEST_APP_REPOSITORY" must be set
-    // which points to the root location of the app respository.
-    private static String AppRepositoryPath = null;
-
-    // Large apps (>1mb) - filenames and their corresponding package names:
-    private static enum APK {
-            FILENAME,
-            PACKAGENAME;
-    }
-    private static final String[][] LARGE_APPS = {
-       {"External1mb.apk", "com.appsonsd.mytests.External1mb"},
-       {"External2mb.apk", "com.appsonsd.mytests.External2mb"},
-       {"External3mb.apk", "com.appsonsd.mytests.External3mb"},
-       {"External4mb.apk", "com.appsonsd.mytests.External4mb"},
-       {"External5mb.apk", "com.appsonsd.mytests.External5mb"},
-       {"External6mb.apk", "com.appsonsd.mytests.External6mb"},
-       {"External7mb.apk", "com.appsonsd.mytests.External7mb"},
-       {"External8mb.apk", "com.appsonsd.mytests.External8mb"},
-       {"External9mb.apk", "com.appsonsd.mytests.External9mb"},
-       {"External10mb.apk", "com.appsonsd.mytests.External10mb"},
-       {"External16mb.apk", "com.appsonsd.mytests.External16mb"},
-       {"External28mb.apk", "com.appsonsd.mytests.External28mb"},
-       {"External34mb.apk", "com.appsonsd.mytests.External34mb"},
-       {"External46mb.apk", "com.appsonsd.mytests.External46mb"},
-       {"External58mb.apk", "com.appsonsd.mytests.External58mb"},
-       {"External65mb.apk", "com.appsonsd.mytests.External65mb"},
-       {"External72mb.apk", "com.appsonsd.mytests.External72mb"},
-       {"External79mb.apk", "com.appsonsd.mytests.External79mb"},
-       {"External86mb.apk", "com.appsonsd.mytests.External86mb"},
-       {"External93mb.apk", "com.appsonsd.mytests.External93mb"}};
-
-    // Various test files and their corresponding package names
-    private static final String AUTO_LOC_APK = "Auto241kb.apk";
-    private static final String AUTO_LOC_PKG = "com.appsonsd.mytests.Auto241kb";
-    private static final String INTERNAL_LOC_APK = "Internal781kb.apk";
-    private static final String INTERNAL_LOC_PKG = "com.appsonsd.mytests.Internal781kb";
-    private static final String EXTERNAL_LOC_APK = "External931kb.apk";
-    private static final String EXTERNAL_LOC_PKG = "com.appsonsd.mytests.External931kb";
-    private static final String NO_LOC_APK = "Internal751kb_EclairSDK.apk";
-    private static final String NO_LOC_PKG = "com.appsonsd.mytests.Internal751kb_EclairSDK";
-    // Versioned test apps
-    private static final String VERSIONED_APPS_FILENAME_PREFIX = "External455kb_v";
-    private static final String VERSIONED_APPS_PKG = "com.appsonsd.mytests.External455kb";
-    private static final int VERSIONED_APPS_START_VERSION = 1;  // inclusive
-    private static final int VERSIONED_APPS_END_VERSION = 250;  // inclusive
-    // Large number of app installs
-    // @TODO: increase the max when we can install more apps
-    private static final int MANY_APPS_START = 1;
-    private static final int MANY_APPS_END = 100;
-    private static final String MANY_APPS_PKG_PREFIX = "com.appsonsd.mytests.External49kb_";
-    private static final String MANY_APPS_APK_PREFIX = "External49kb_";
-
-    public static Test suite() {
-        return new DeviceTestSuite(PackageManagerStressHostTests.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        // setup the PackageManager host tests utilities class, and get various paths we'll need...
-        mPMHostUtils = new PackageManagerHostTestUtils(getDevice());
-        AppRepositoryPath = System.getenv("ANDROID_TEST_APP_REPOSITORY");
-        assertNotNull(AppRepositoryPath);
-
-        // Make sure path ends with a separator
-        if (!AppRepositoryPath.endsWith(File.separator)) {
-            AppRepositoryPath += File.separator;
-        }
-    }
-
-    /**
-     * Get the absolute file system location of repository test app with given filename
-     * @param fileName the file name of the test app apk
-     * @return {@link String} of absolute file path
-     */
-    private String getRepositoryTestAppFilePath(String fileDirectory, String fileName) {
-        return String.format("%s%s%s%s", AppRepositoryPath, fileDirectory,
-                File.separator, fileName);
-    }
-
-    /**
-     * Get the absolute file system location of test app with given filename
-     * @param fileName the file name of the test app apk
-     * @return {@link String} of absolute file path
-     */
-    public String getTestAppFilePath(String fileName) {
-        return String.format("%s%s%s", getTestAppPath(), File.separator, fileName);
-    }
-
-    /**
-     * Stress test to verify that we can update an app multiple times on the SD card.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     */
-    public void testUpdateAppManyTimesOnSD() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test updating an app on SD numerous times");
-
-        // cleanup test app just in case it already exists
-        mPMHostUtils.uninstallApp(VERSIONED_APPS_PKG);
-        // grep for package to make sure its not installed
-        assertFalse(mPMHostUtils.doesPackageExist(VERSIONED_APPS_PKG));
-
-        try {
-            for (int i = VERSIONED_APPS_START_VERSION; i <= VERSIONED_APPS_END_VERSION; ++i) {
-                String currentApkName = String.format("%s%d.apk",
-                        VERSIONED_APPS_FILENAME_PREFIX, i);
-
-                Log.i(LOG_TAG, "Installing app " + currentApkName);
-                mPMHostUtils.installFile(getRepositoryTestAppFilePath(VERSIONED_APPS_DIRECTORY_NAME,
-                        currentApkName), true);
-                mPMHostUtils.waitForPackageManager();
-                assertTrue(mPMHostUtils.doesAppExistOnSDCard(VERSIONED_APPS_PKG));
-                assertTrue(mPMHostUtils.doesPackageExist(VERSIONED_APPS_PKG));
-            }
-        }
-        finally {
-            // cleanup test app
-            mPMHostUtils.uninstallApp(VERSIONED_APPS_PKG);
-            // grep for package to make sure its not installed
-            assertFalse(mPMHostUtils.doesPackageExist(VERSIONED_APPS_PKG));
-        }
-    }
-
-    /**
-     * Stress test to verify that an app can be installed, uninstalled, and
-     * reinstalled on SD many times.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     */
-    public void testUninstallReinstallAppOnSDManyTimes() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test updating an app on the SD card stays on the SD card");
-
-        // cleanup test app just in case it was already exists
-        mPMHostUtils.uninstallApp(EXTERNAL_LOC_PKG);
-        // grep for package to make sure its not installed
-        assertFalse(mPMHostUtils.doesPackageExist(EXTERNAL_LOC_PKG));
-
-        for (int i = 0; i <= 500; ++i) {
-            Log.i(LOG_TAG, "Installing app");
-
-            try {
-                // install the app
-                mPMHostUtils.installFile(getRepositoryTestAppFilePath(MISC_APPS_DIRECTORY_NAME,
-                        EXTERNAL_LOC_APK), false);
-                mPMHostUtils.waitForPackageManager();
-                assertTrue(mPMHostUtils.doesAppExistOnSDCard(EXTERNAL_LOC_PKG));
-                assertTrue(mPMHostUtils.doesPackageExist(EXTERNAL_LOC_PKG));
-            }
-            finally {
-                // now uninstall the app
-                Log.i(LOG_TAG, "Uninstalling app");
-                mPMHostUtils.uninstallApp(EXTERNAL_LOC_PKG);
-                mPMHostUtils.waitForPackageManager();
-                assertFalse(mPMHostUtils.doesPackageExist(EXTERNAL_LOC_PKG));
-            }
-        }
-    }
-
-    /**
-     * Stress test to verify that we can install, 20 large apps (>1mb each)
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     */
-    public void testInstallManyLargeAppsOnSD() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installing 20 large apps onto the sd card");
-
-        try {
-            // Install all the large apps
-            for (int i=0; i < LARGE_APPS.length; ++i) {
-                String apkName = LARGE_APPS[i][APK.FILENAME.ordinal()];
-                String pkgName = LARGE_APPS[i][APK.PACKAGENAME.ordinal()];
-
-                // cleanup test app just in case it already exists
-                mPMHostUtils.uninstallApp(pkgName);
-                // grep for package to make sure its not installed
-                assertFalse(mPMHostUtils.doesPackageExist(pkgName));
-
-                Log.i(LOG_TAG, "Installing app " + apkName);
-                // install the app
-                mPMHostUtils.installFile(getRepositoryTestAppFilePath(LARGE_APPS_DIRECTORY_NAME,
-                        apkName), false);
-                mPMHostUtils.waitForPackageManager();
-                assertTrue(mPMHostUtils.doesAppExistOnSDCard(pkgName));
-                assertTrue(mPMHostUtils.doesPackageExist(pkgName));
-            }
-        }
-        finally {
-            // Cleanup - ensure we uninstall all large apps if they were installed
-            for (int i=0; i < LARGE_APPS.length; ++i) {
-                String apkName = LARGE_APPS[i][APK.FILENAME.ordinal()];
-                String pkgName = LARGE_APPS[i][APK.PACKAGENAME.ordinal()];
-
-                Log.i(LOG_TAG, "Uninstalling app " + apkName);
-                // cleanup test app just in case it was accidently installed
-                mPMHostUtils.uninstallApp(pkgName);
-                // grep for package to make sure its not installed anymore
-                assertFalse(mPMHostUtils.doesPackageExist(pkgName));
-                assertFalse(mPMHostUtils.doesAppExistOnSDCard(pkgName));
-            }
-        }
-    }
-
-    /**
-     * Stress test to verify that we can install many small apps onto SD.
-     * <p/>
-     * Assumes adb is running as root in device under test.
-     */
-    public void testInstallManyAppsOnSD() throws IOException, InterruptedException,
-            InstallException, TimeoutException, AdbCommandRejectedException,
-            ShellCommandUnresponsiveException {
-        Log.i(LOG_TAG, "Test installing 500 small apps onto SD");
-
-        try {
-            for (int i = MANY_APPS_START; i <= MANY_APPS_END; ++i) {
-                String currentPkgName = String.format("%s%d", MANY_APPS_PKG_PREFIX, i);
-
-                // cleanup test app just in case it already exists
-                mPMHostUtils.uninstallApp(currentPkgName);
-                // grep for package to make sure its not installed
-                assertFalse(mPMHostUtils.doesPackageExist(currentPkgName));
-
-                String currentApkName = String.format("%s%d.apk", MANY_APPS_APK_PREFIX, i);
-                Log.i(LOG_TAG, "Installing app " + currentApkName);
-                mPMHostUtils.installFile(getRepositoryTestAppFilePath(MANY_APPS_DIRECTORY_NAME,
-                        currentApkName), true);
-                mPMHostUtils.waitForPackageManager();
-                assertTrue(mPMHostUtils.doesAppExistOnSDCard(currentPkgName));
-                assertTrue(mPMHostUtils.doesPackageExist(currentPkgName));
-            }
-        }
-        finally {
-            for (int i = MANY_APPS_START; i <= MANY_APPS_END; ++i) {
-                String currentPkgName = String.format("%s%d", MANY_APPS_PKG_PREFIX, i);
-
-                // cleanup test app
-                mPMHostUtils.uninstallApp(currentPkgName);
-                // grep for package to make sure its not installed
-                assertFalse(mPMHostUtils.doesPackageExist(currentPkgName));
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/tests/hosttests/src/android/net/DownloadManagerHostTests.java b/core/tests/hosttests/src/android/net/DownloadManagerHostTests.java
deleted file mode 100644
index a94555c..0000000
--- a/core/tests/hosttests/src/android/net/DownloadManagerHostTests.java
+++ /dev/null
@@ -1,210 +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.
- */
-
-package android.net;
-
-import android.content.pm.PackageManagerHostTestUtils;
-
-import com.android.ddmlib.Log;
-import com.android.hosttest.DeviceTestCase;
-import com.android.hosttest.DeviceTestSuite;
-
-import java.io.File;
-import java.util.Hashtable;
-
-import junit.framework.Test;
-
-/**
- * Host-based tests of the DownloadManager API. (Uses a device-based app to actually invoke the
- * various tests.)
- */
-public class DownloadManagerHostTests extends DeviceTestCase {
-    protected PackageManagerHostTestUtils mPMUtils = null;
-
-    private static final String LOG_TAG = "android.net.DownloadManagerHostTests";
-    private static final String FILE_DOWNLOAD_APK = "DownloadManagerTestApp.apk";
-    private static final String FILE_DOWNLOAD_PKG = "com.android.frameworks.downloadmanagertests";
-    private static final String FILE_DOWNLOAD_CLASS =
-            "com.android.frameworks.downloadmanagertests.DownloadManagerTestApp";
-    private static final String DOWNLOAD_TEST_RUNNER_NAME =
-            "com.android.frameworks.downloadmanagertests.DownloadManagerTestRunner";
-
-    // Extra parameters to pass to the TestRunner
-    private static final String EXTERNAL_DOWNLOAD_URI_KEY = "external_download_uri";
-    // Note: External environment variable ANDROID_TEST_EXTERNAL_URI must be set to point to the
-    // external URI under which the files downloaded by the tests can be found. Note that the Uri
-    // must be accessible by the device during a test run. Correspondingly,
-    // ANDROID_TEST_EXTERNAL_LARGE_URI should point to the external URI of the folder containing
-    // large files.
-    private static String externalDownloadUriValue = null;
-
-    Hashtable<String, String> mExtraParams = null;
-
-    public static Test suite() {
-        return new DeviceTestSuite(DownloadManagerHostTests.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        // ensure apk path has been set before test is run
-        assertNotNull(getTestAppPath());
-        mPMUtils = new PackageManagerHostTestUtils(getDevice());
-        externalDownloadUriValue = System.getenv("ANDROID_TEST_EXTERNAL_URI");
-        assertNotNull(externalDownloadUriValue);
-        mExtraParams = getExtraParams();
-    }
-
-    /**
-     * Helper function to get extra params that can be used to pass into the helper app.
-     */
-    protected Hashtable<String, String> getExtraParams() {
-        Hashtable<String, String> extraParams = new Hashtable<String, String>();
-        extraParams.put(EXTERNAL_DOWNLOAD_URI_KEY, externalDownloadUriValue);
-        return extraParams;
-    }
-
-    /**
-     * Tests that a large download over WiFi
-     * @throws Exception if the test failed at any point
-     */
-    public void testLargeDownloadOverWiFi() throws Exception {
-        mPMUtils.installAppAndVerifyExistsOnDevice(String.format("%s%s%s", getTestAppPath(),
-                File.separator, FILE_DOWNLOAD_APK), FILE_DOWNLOAD_PKG, true);
-
-        boolean testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "runLargeDownloadOverWiFi", DOWNLOAD_TEST_RUNNER_NAME,
-                mExtraParams);
-
-        assertTrue("Failed to install large file over WiFi in < 10 minutes!", testPassed);
-    }
-
-    /**
-     * Spawns a device-based function to initiate a download on the device, reboots the device,
-     * then waits and verifies the download succeeded.
-     *
-     * @throws Exception if the test failed at any point
-     */
-    public void testDownloadManagerSingleReboot() throws Exception {
-        mPMUtils.installAppAndVerifyExistsOnDevice(String.format("%s%s%s", getTestAppPath(),
-                File.separator, FILE_DOWNLOAD_APK), FILE_DOWNLOAD_PKG, true);
-
-        boolean testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "initiateDownload", DOWNLOAD_TEST_RUNNER_NAME,
-                mExtraParams);
-
-        assertTrue("Failed to initiate download properly!", testPassed);
-        mPMUtils.rebootDevice();
-        testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "verifyFileDownloadSucceeded", DOWNLOAD_TEST_RUNNER_NAME,
-                mExtraParams);
-        assertTrue("Failed to verify initiated download completed properyly!", testPassed);
-    }
-
-    /**
-     * Spawns a device-based function to initiate a download on the device, reboots the device three
-     * times (using different intervals), then waits and verifies the download succeeded.
-     *
-     * @throws Exception if the test failed at any point
-     */
-    public void testDownloadManagerMultipleReboots() throws Exception {
-        mPMUtils.installAppAndVerifyExistsOnDevice(String.format("%s%s%s", getTestAppPath(),
-                File.separator, FILE_DOWNLOAD_APK), FILE_DOWNLOAD_PKG, true);
-
-        boolean testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "initiateDownload", DOWNLOAD_TEST_RUNNER_NAME,
-                mExtraParams);
-
-        assertTrue("Failed to initiate download properly!", testPassed);
-        Thread.sleep(5000);
-
-        // Do 3 random reboots - after 13, 9, and 19 seconds
-        Log.i(LOG_TAG, "First reboot...");
-        mPMUtils.rebootDevice();
-        Thread.sleep(13000);
-        Log.i(LOG_TAG, "Second reboot...");
-        mPMUtils.rebootDevice();
-        Thread.sleep(9000);
-        Log.i(LOG_TAG, "Third reboot...");
-        mPMUtils.rebootDevice();
-        Thread.sleep(19000);
-        testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "verifyFileDownloadSucceeded", DOWNLOAD_TEST_RUNNER_NAME,
-                mExtraParams);
-        assertTrue("Failed to verify initiated download completed properyly!", testPassed);
-    }
-
-    /**
-     * Spawns a device-based function to test download while WiFi is enabled/disabled multiple times
-     * during the download.
-     *
-     * @throws Exception if the test failed at any point
-     */
-    public void testDownloadMultipleWiFiEnableDisable() throws Exception {
-        mPMUtils.installAppAndVerifyExistsOnDevice(String.format("%s%s%s", getTestAppPath(),
-                File.separator, FILE_DOWNLOAD_APK), FILE_DOWNLOAD_PKG, true);
-
-        boolean testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "runDownloadMultipleWiFiEnableDisable",
-                DOWNLOAD_TEST_RUNNER_NAME, mExtraParams);
-        assertTrue(testPassed);
-    }
-
-    /**
-     * Spawns a device-based function to test switching on/off both airplane mode and WiFi
-     *
-     * @throws Exception if the test failed at any point
-     */
-    public void testDownloadMultipleSwitching() throws Exception {
-        mPMUtils.installAppAndVerifyExistsOnDevice(String.format("%s%s%s", getTestAppPath(),
-                File.separator, FILE_DOWNLOAD_APK), FILE_DOWNLOAD_PKG, true);
-
-        boolean testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "runDownloadMultipleSwitching",
-                DOWNLOAD_TEST_RUNNER_NAME, mExtraParams);
-        assertTrue(testPassed);
-    }
-
-    /**
-     * Spawns a device-based function to test switching on/off airplane mode multiple times
-     *
-     * @throws Exception if the test failed at any point
-     */
-    public void testDownloadMultipleAirplaneModeEnableDisable() throws Exception {
-        mPMUtils.installAppAndVerifyExistsOnDevice(String.format("%s%s%s", getTestAppPath(),
-                File.separator, FILE_DOWNLOAD_APK), FILE_DOWNLOAD_PKG, true);
-
-        boolean testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "runDownloadMultipleAirplaneModeEnableDisable",
-                DOWNLOAD_TEST_RUNNER_NAME, mExtraParams);
-        assertTrue(testPassed);
-    }
-
-    /**
-     * Spawns a device-based function to test 15 concurrent downloads of 5,000,000-byte files
-     *
-     * @throws Exception if the test failed at any point
-     */
-    public void testDownloadMultipleSimultaneously() throws Exception {
-        mPMUtils.installAppAndVerifyExistsOnDevice(String.format("%s%s%s", getTestAppPath(),
-                File.separator, FILE_DOWNLOAD_APK), FILE_DOWNLOAD_PKG, true);
-
-        boolean testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
-                FILE_DOWNLOAD_CLASS, "runDownloadMultipleSimultaneously",
-                DOWNLOAD_TEST_RUNNER_NAME, mExtraParams);
-        assertTrue(testPassed);
-    }
-}
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
index 09dcac5..a288058 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
@@ -25,4 +25,9 @@
 
 LOCAL_PACKAGE_NAME := DownloadManagerTestApp
 
+ifneq ($(TARGET_BUILD_VARIANT),user)
+# Need to run as system app to get access to Settings. This test won't work for user builds.
+LOCAL_CERTIFICATE := platform
+endif
+
 include $(BUILD_PACKAGE)
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/AndroidManifest.xml b/core/tests/hosttests/test-apps/DownloadManagerTestApp/AndroidManifest.xml
index 3f2be3c..c8d66ce 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/AndroidManifest.xml
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/AndroidManifest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-       package="com.android.frameworks.downloadmanagertests">
+       package="com.android.frameworks.downloadmanagertests"
+       android:sharedUserId="android.uid.system">
 
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
@@ -22,6 +23,7 @@
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
 
     <application android:label="DownloadManagerTestApp">
             <uses-library android:name="android.test.runner" />
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java
index 8e935f8..f493e9a 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java
@@ -262,7 +262,7 @@
         int state = enable ? 1 : 0;
 
         // Change the system setting
-        Settings.System.putInt(mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON,
                 state);
 
         String timeoutMessage = "Timed out waiting for airplane mode to be " +
@@ -271,7 +271,7 @@
         // wait for airplane mode to change state
         int currentWaitTime = 0;
         while (Settings.System.getInt(mContext.getContentResolver(),
-                Settings.System.AIRPLANE_MODE_ON, -1) != state) {
+                Settings.Global.AIRPLANE_MODE_ON, -1) != state) {
             timeoutWait(currentWaitTime, DEFAULT_WAIT_POLL_TIME, DEFAULT_MAX_WAIT_TIME,
                     timeoutMessage);
         }
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 833064e..13d1791 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -42,6 +42,14 @@
         <group gid="net_bt" />
     </permission>
 
+    <permission name="android.permission.BLUETOOTH_STACK" >
+        <group gid="net_bt_stack" />
+    </permission>
+
+    <permission name="android.permission.NET_TUNNELING" >
+        <group gid="vpn" />
+    </permission>
+
     <permission name="android.permission.INTERNET" >
         <group gid="inet" />
     </permission>
@@ -169,7 +177,11 @@
     <assign-permission name="android.permission.SET_SCREEN_COMPATIBILITY" uid="shell" />
     <assign-permission name="android.permission.READ_EXTERNAL_STORAGE" uid="shell" />
     <assign-permission name="android.permission.WRITE_EXTERNAL_STORAGE" uid="shell" />
-
+    <assign-permission name="android.permission.INTERACT_ACROSS_USERS" uid="shell" />
+    <assign-permission name="android.permission.INTERACT_ACROSS_USERS_FULL" uid="shell" />
+    <assign-permission name="android.permission.MANAGE_USERS" uid="shell" />
+    <assign-permission name="android.permission.BLUETOOTH_STACK" uid="shell" />
+    
     <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
     <assign-permission name="android.permission.ACCESS_DRM" uid="media" />
     <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" />
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index 3d6c9d3..e02e95a 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -76,14 +76,6 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts
 include $(BUILD_PREBUILT)
 
-include $(CLEAR_VARS)
-LOCAL_MODULE := fallback_fonts-ja.xml
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
-include $(BUILD_PREBUILT)
-
 droidsans_fallback_src := DroidSansFallbackFull.ttf
 extra_font_files := \
 	DroidSans.ttf \
@@ -91,8 +83,7 @@
 	DroidSansEthiopic-Regular.ttf \
 	DroidSansTamil-Regular.ttf \
 	DroidSansTamil-Bold.ttf \
-	MTLmr3m.ttf \
-	fallback_fonts-ja.xml
+	MTLmr3m.ttf
 endif  # SMALLER_FONT_FOOTPRINT
 
 ################################
@@ -143,6 +134,8 @@
 
 $(eval $(call create-font-symlink,Roboto-Light.ttf,Roboto-Regular.ttf))
 $(eval $(call create-font-symlink,Roboto-LightItalic.ttf,Roboto-Italic.ttf))
+$(eval $(call create-font-symlink,Roboto-Thin.ttf,Roboto-Regular.ttf))
+$(eval $(call create-font-symlink,Roboto-ThinItalic.ttf,Roboto-Italic.ttf))
 $(eval $(call create-font-symlink,RobotoCondensed-Regular.ttf,Roboto-Regular.ttf))
 $(eval $(call create-font-symlink,RobotoCondensed-Bold.ttf,Roboto-Bold.ttf))
 $(eval $(call create-font-symlink,RobotoCondensed-Italic.ttf,Roboto-Italic.ttf))
@@ -152,6 +145,8 @@
 font_src_files += \
     Roboto-Light.ttf \
     Roboto-LightItalic.ttf \
+    Roboto-Thin.ttf \
+    Roboto-ThinItalic.ttf \
     RobotoCondensed-Regular.ttf \
     RobotoCondensed-Bold.ttf \
     RobotoCondensed-Italic.ttf \
diff --git a/data/fonts/AndroidClock.ttf b/data/fonts/AndroidClock.ttf
index 3fa6d88..4781ccd 100644
--- a/data/fonts/AndroidClock.ttf
+++ b/data/fonts/AndroidClock.ttf
Binary files differ
diff --git a/data/fonts/DroidNaskh-Bold.ttf b/data/fonts/DroidNaskh-Bold.ttf
index 692b796..14d8768 100644
--- a/data/fonts/DroidNaskh-Bold.ttf
+++ b/data/fonts/DroidNaskh-Bold.ttf
Binary files differ
diff --git a/data/fonts/DroidNaskh-Regular-SystemUI.ttf b/data/fonts/DroidNaskh-Regular-SystemUI.ttf
index 2f495cf..c961de2 100644
--- a/data/fonts/DroidNaskh-Regular-SystemUI.ttf
+++ b/data/fonts/DroidNaskh-Regular-SystemUI.ttf
Binary files differ
diff --git a/data/fonts/DroidNaskh-Regular.ttf b/data/fonts/DroidNaskh-Regular.ttf
index da9a45f..03662f2 100644
--- a/data/fonts/DroidNaskh-Regular.ttf
+++ b/data/fonts/DroidNaskh-Regular.ttf
Binary files differ
diff --git a/data/fonts/DroidSansFallback.ttf b/data/fonts/DroidSansFallback.ttf
index cfbc66a..2b75113 100644
--- a/data/fonts/DroidSansFallback.ttf
+++ b/data/fonts/DroidSansFallback.ttf
Binary files differ
diff --git a/data/fonts/DroidSansFallbackFull.ttf b/data/fonts/DroidSansFallbackFull.ttf
index 0cacabe..a9df00585 100644
--- a/data/fonts/DroidSansFallbackFull.ttf
+++ b/data/fonts/DroidSansFallbackFull.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Thin.ttf b/data/fonts/Roboto-Thin.ttf
new file mode 100644
index 0000000..5ae4d7f
--- /dev/null
+++ b/data/fonts/Roboto-Thin.ttf
Binary files differ
diff --git a/data/fonts/Roboto-ThinItalic.ttf b/data/fonts/Roboto-ThinItalic.ttf
new file mode 100644
index 0000000..9cd3927
--- /dev/null
+++ b/data/fonts/Roboto-ThinItalic.ttf
Binary files differ
diff --git a/data/fonts/fallback_fonts-ja.xml b/data/fonts/fallback_fonts-ja.xml
deleted file mode 100644
index 5f9b5ed..0000000
--- a/data/fonts/fallback_fonts-ja.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Fallback Fonts
-
-    This file specifies the fonts, and the priority order, that will be searched for any
-    glyphs not handled by the default fonts specified in /system/etc/system_fonts.xml.
-    Each entry consists of a family tag and a list of files (file names) which support that
-    family. The fonts for each family are listed in the order of the styles that they
-    handle (the order is: regular, bold, italic, and bold-italic). The order in which the
-    families are listed in this file represents the order in which these fallback fonts
-    will be searched for glyphs that are not supported by the default system fonts (which are
-    found in /system/etc/system_fonts.xml).
-
-    Note that there is not nameset for fallback fonts, unlike the fonts specified in
-    system_fonts.xml. The ability to support specific names in fallback fonts may be supported
-    in the future. For now, the lack of files entries here is an indicator to the system that
-    these are fallback fonts, instead of default named system fonts.
-
-    There is another optional file in /vendor/etc/fallback_fonts.xml. That file can be used to
-    provide references to other font families that should be used in addition to the default
-    fallback fonts. That file can also specify the order in which the fallback fonts should be
-    searched, to ensure that a vendor-provided font will be used before another fallback font
-    which happens to handle the same glyph.
-
-    Han languages (Chinese, Japanese, and Korean) share a common range of unicode characters;
-    their ordering in the fallback or vendor files gives priority to the first in the list.
-    Locale-specific ordering can be configured by adding language and region codes to the end
-    of the filename (e.g. /system/etc/fallback_fonts-ja.xml). When no region code is used,
-    as with this example, all regions are matched. Use separate files for each supported locale.
-    The standard fallback file (fallback_fonts.xml) is used when a locale does not have its own
-    file. All fallback files must contain the same complete set of fonts; only their ordering
-    can differ.
--->
-<familyset>
-    <family>
-        <fileset>
-            <file>DroidNaskh-Regular-SystemUI.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>DroidSansEthiopic-Regular.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>DroidSansHebrew-Regular.ttf</file>
-            <file>DroidSansHebrew-Bold.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>DroidSansThai.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>DroidSansArmenian.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>DroidSansGeorgian.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>DroidSansDevanagari-Regular.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>DroidSansTamil-Regular.ttf</file>
-            <file>DroidSansTamil-Bold.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>AnjaliNewLipi-light.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>Lohit-Bengali.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>Lohit-Kannada.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>Lohit-Telugu.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>AndroidEmoji.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>MTLmr3m.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>DroidSansFallback.ttf</file>
-        </fileset>
-    </family>
-</familyset>
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
index 5f7017e..50ff437 100644
--- a/data/fonts/fallback_fonts.xml
+++ b/data/fonts/fallback_fonts.xml
@@ -24,17 +24,19 @@
 
     Han languages (Chinese, Japanese, and Korean) share a common range of unicode characters;
     their ordering in the fallback or vendor files gives priority to the first in the list.
-    Locale-specific ordering can be configured by adding language and region codes to the end
-    of the filename (e.g. /system/etc/fallback_fonts-ja.xml). When no region code is used,
-    as with this example, all regions are matched. Use separate files for each supported locale.
-    The standard fallback file (fallback_fonts.xml) is used when a locale does not have its own
-    file. All fallback files must contain the same complete set of fonts; only their ordering
-    can differ.
+    Language-specific ordering can be configured by adding a BCP 47-style "lang" attribute to
+    a "file" element; fonts matching the language of text being drawn will be prioritised over
+    all others.
 -->
 <familyset>
     <family>
         <fileset>
-            <file>DroidNaskh-Regular-SystemUI.ttf</file>
+            <file variant="elegant">DroidNaskh-Regular.ttf</file>
+        </fileset>
+    </family>
+    <family>
+        <fileset>
+            <file variant="compact">DroidNaskh-Regular-SystemUI.ttf</file>
         </fileset>
     </family>
     <family>
@@ -91,7 +93,7 @@
     </family>
     <family>
         <fileset>
-            <file>Lohit-Telugu.ttf</file>
+            <file>NanumGothic.ttf</file>
         </fileset>
     </family>
     <family>
@@ -106,7 +108,16 @@
     </family>
     <family>
         <fileset>
-            <file>MTLmr3m.ttf</file>
+            <file lang="ja">MTLmr3m.ttf</file>
+        </fileset>
+    </family>
+    <!--
+        Fonts below this point have problematic glyphs and should not be moved
+        higher in the fallback list until those glyphs have been fixed.
+    -->
+    <family>
+        <fileset>
+            <file>Lohit-Telugu.ttf</file> <!-- masks U+FFBC-10007 -->
         </fileset>
     </family>
 </familyset>
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index 97233d7..875795a 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -26,6 +26,8 @@
     Roboto-BoldItalic.ttf \
     Roboto-Light.ttf \
     Roboto-LightItalic.ttf \
+    Roboto-Thin.ttf \
+    Roboto-ThinItalic.ttf \
     RobotoCondensed-Regular.ttf \
     RobotoCondensed-Bold.ttf \
     RobotoCondensed-Italic.ttf \
diff --git a/data/fonts/system_fonts.xml b/data/fonts/system_fonts.xml
index 5a10523..16e4c7c 100644
--- a/data/fonts/system_fonts.xml
+++ b/data/fonts/system_fonts.xml
@@ -46,6 +46,16 @@
 
     <family>
         <nameset>
+            <name>sans-serif-thin</name>
+        </nameset>
+        <fileset>
+            <file>Roboto-Thin.ttf</file>
+            <file>Roboto-ThinItalic.ttf</file>
+        </fileset>
+    </family>
+
+    <family>
+        <nameset>
             <name>sans-serif-condensed</name>
         </nameset>
         <fileset>
diff --git a/data/fonts/vendor_fonts.xml b/data/fonts/vendor_fonts.xml
index 5850f94..8690ee1 100644
--- a/data/fonts/vendor_fonts.xml
+++ b/data/fonts/vendor_fonts.xml
@@ -7,8 +7,7 @@
     that in your makefile, this directory should be referenced as $(TARGET_COPY_OUT_VENDOR)/etc/:
 
         PRODUCT_COPY_FILES += \
-            frameworks/base/data/fonts/vendor_fonts.xml:$(TARGET_COPY_OUT_VENDOR)/etc/fallback_fonts.xml \
-            frameworks/base/data/fonts/vendor_fonts-ja.xml:$(TARGET_COPY_OUT_VENDOR)/etc/fallback_fonts-ja.xml
+            frameworks/base/data/fonts/vendor_fonts.xml:$(TARGET_COPY_OUT_VENDOR)/etc/fallback_fonts.xml
 
     For example, vendors might want to build configurations for locales that are
     better served by fonts which either handle glyphs not supported in the default fonts or which
@@ -32,32 +31,9 @@
 
     Han languages (Chinese, Japanese, and Korean) share a common range of unicode characters;
     their ordering in the fallback or vendor files gives priority to the first in the list.
-    Locale-specific ordering can be configured by adding language and region codes to the end
-    of the filename (e.g. /vendor/etc/fallback_fonts-ja.xml). When no region code is used,
-    as with this example, all regions are matched. Use separate files for each supported locale.
-    The standard fallback file (fallback_fonts.xml) is used when a locale does not have its own
-    file. All fallback files must contain the same complete set of fonts; only their ordering
-    can differ. For example, on a device supporting Japanese, but with English as the default,
-    /vendor/etc/fallback_fonts.xml might contain:
-
-        <familyset>
-            <family>
-                <fileset>
-                    <file>DroidSansJapanese.ttf</file>
-                </fileset>
-            </family>
-        </familyset>
-
-    placing the Japanese font at the end of the fallback sequence for English, with a corresponding
-    /system/vendor/etc/fallback_fonts-ja.xml, placing it at the front of the list.
-
-        <familyset>
-            <family order="0">
-                <fileset>
-                    <file>DroidSansJapanese.ttf</file>
-                </fileset>
-            </family>
-        </familyset>
+    Language-specific ordering can be configured by adding a BCP 47-style "lang" attribute to
+    a "file" element; fonts matching the language of text being drawn will be prioritised over
+    all others.
 
     The sample configuration below is an example of how one might provide two families of fonts
     that get inserted at the first and second (0  and 1) position in the overall fallback fonts.
@@ -82,4 +58,4 @@
         </fileset>
     </family>
 </familyset>
--->
\ No newline at end of file
+--->
diff --git a/data/sounds/AudioPackage10.mk b/data/sounds/AudioPackage10.mk
new file mode 100755
index 0000000..cb55bba
--- /dev/null
+++ b/data/sounds/AudioPackage10.mk
@@ -0,0 +1,64 @@
+#
+# Audio Package 10 - Mako
+# 
+# Include this file in a product makefile to include these audio files
+#
+# 
+
+LOCAL_PATH:= frameworks/base/data/sounds
+
+PRODUCT_COPY_FILES += \
+        $(LOCAL_PATH)/alarms/ogg/Argon.ogg:system/media/audio/alarms/Argon.ogg \
+        $(LOCAL_PATH)/alarms/ogg/Carbon.ogg:system/media/audio/alarms/Carbon.ogg \
+        $(LOCAL_PATH)/alarms/ogg/Helium.ogg:system/media/audio/alarms/Helium.ogg \
+        $(LOCAL_PATH)/alarms/ogg/Krypton.ogg:system/media/audio/alarms/Krypton.ogg \
+        $(LOCAL_PATH)/alarms/ogg/Neon.ogg:system/media/audio/alarms/Neon.ogg \
+        $(LOCAL_PATH)/alarms/ogg/Oxygen.ogg:system/media/audio/alarms/Oxygen.ogg \
+        $(LOCAL_PATH)/alarms/ogg/Osmium.ogg:system/media/audio/alarms/Osmium.ogg \
+        $(LOCAL_PATH)/alarms/ogg/Platinum.ogg:system/media/audio/alarms/Platinum.ogg \
+	$(LOCAL_PATH)/effects/ogg/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressStandard_120.ogg:system/media/audio/ui/KeypressStandard.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressSpacebar_120.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressDelete_120.ogg:system/media/audio/ui/KeypressDelete.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressReturn_120.ogg:system/media/audio/ui/KeypressReturn.ogg \
+	$(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+	$(LOCAL_PATH)/effects/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
+	$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
+	$(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+	$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
+	$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
+	$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
+	$(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Alya.ogg:system/media/audio/notifications/Alya.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Arcturus.ogg:system/media/audio/notifications/Arcturus.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Capella.ogg:system/media/audio/notifications/Capella.ogg \
+	$(LOCAL_PATH)/notifications/ogg/CetiAlpha.ogg:system/media/audio/notifications/CetiAlpha.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Hojus.ogg:system/media/audio/notifications/Hojus.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Mira.ogg:system/media/audio/notifications/Mira.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Pollux.ogg:system/media/audio/notifications/Pollux.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Procyon.ogg:system/media/audio/notifications/Procyon.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Shaula.ogg:system/media/audio/notifications/Shaula.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Spica.ogg:system/media/audio/notifications/Spica.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Syrma.ogg:system/media/audio/notifications/Syrma.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Talitha.ogg:system/media/audio/notifications/Talitha.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Tejat.ogg:system/media/audio/notifications/Tejat.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Andromeda.ogg:system/media/audio/ringtones/Andromeda.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Aquila.ogg:system/media/audio/ringtones/Aquila.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Atria.ogg:system/media/audio/ringtones/Atria.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/ArgoNavis.ogg:system/media/audio/ringtones/ArgoNavis.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Centaurus.ogg:system/media/audio/ringtones/Centaurus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Girtab.ogg:system/media/audio/ringtones/Girtab.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Hydra.ogg:system/media/audio/ringtones/Hydra.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Kuma.ogg:system/media/audio/ringtones/Kuma.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Machina.ogg:system/media/audio/ringtones/Machina.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Orion.ogg:system/media/audio/ringtones/Orion.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Pegasus.ogg:system/media/audio/ringtones/Pegasus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Pyxis.ogg:system/media/audio/ringtones/Pyxis.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Rasalas.ogg:system/media/audio/ringtones/Rasalas.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Scarabaeus.ogg:system/media/audio/ringtones/Scarabaeus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Sceptrum.ogg:system/media/audio/ringtones/Sceptrum.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Solarium.ogg:system/media/audio/ringtones/Solarium.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Themos.ogg:system/media/audio/ringtones/Themos.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Zeta.ogg:system/media/audio/ringtones/Zeta.ogg
diff --git a/data/sounds/AudioPackage8.mk b/data/sounds/AudioPackage8.mk
new file mode 100755
index 0000000..93c43da
--- /dev/null
+++ b/data/sounds/AudioPackage8.mk
@@ -0,0 +1,70 @@
+#
+# Audio Package 7 - Tuna
+# 
+# Include this file in a product makefile to include these audio files
+#
+# 
+
+LOCAL_PATH:= frameworks/base/data/sounds
+
+PRODUCT_COPY_FILES += \
+	$(LOCAL_PATH)/alarms/ogg/Cesium.ogg:system/media/audio/alarms/Cesium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Fermium.ogg:system/media/audio/alarms/Fermium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Hassium.ogg:system/media/audio/alarms/Hassium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Neptunium.ogg:system/media/audio/alarms/Neptunium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Nobelium.ogg:system/media/audio/alarms/Nobelium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Osmium.ogg:system/media/audio/alarms/Osmium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Plutonium.ogg:system/media/audio/alarms/Plutonium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Promethium.ogg:system/media/audio/alarms/Promethium.ogg \
+	$(LOCAL_PATH)/effects/ogg/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressStandard_120.ogg:system/media/audio/ui/KeypressStandard.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressSpacebar_120.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressDelete_120.ogg:system/media/audio/ui/KeypressDelete.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressReturn_120.ogg:system/media/audio/ui/KeypressReturn.ogg \
+	$(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+	$(LOCAL_PATH)/effects/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
+	$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
+	$(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+	$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
+	$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
+	$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
+	$(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Arcturus.ogg:system/media/audio/notifications/Arcturus.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Bellatrix.ogg:system/media/audio/notifications/Bellatrix.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Capella.ogg:system/media/audio/notifications/Capella.ogg \
+	$(LOCAL_PATH)/notifications/ogg/CetiAlpha.ogg:system/media/audio/notifications/CetiAlpha.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Hojus.ogg:system/media/audio/notifications/Hojus.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Lalande.ogg:system/media/audio/notifications/Lalande.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Mira.ogg:system/media/audio/notifications/Mira.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Polaris.ogg:system/media/audio/notifications/Polaris.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Pollux.ogg:system/media/audio/notifications/Pollux.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Procyon.ogg:system/media/audio/notifications/Procyon.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Proxima.ogg:system/media/audio/notifications/Proxima.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Shaula.ogg:system/media/audio/notifications/Shaula.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Spica.ogg:system/media/audio/notifications/Spica.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Tejat.ogg:system/media/audio/notifications/Tejat.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Upsilon.ogg:system/media/audio/notifications/Upsilon.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Andromeda.ogg:system/media/audio/ringtones/Andromeda.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Aquila.ogg:system/media/audio/ringtones/Aquila.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/ArgoNavis.ogg:system/media/audio/ringtones/ArgoNavis.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/CanisMajor.ogg:system/media/audio/ringtones/CanisMajor.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Carina.ogg:system/media/audio/ringtones/Carina.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Centaurus.ogg:system/media/audio/ringtones/Centaurus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Cygnus.ogg:system/media/audio/ringtones/Cygnus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Draco.ogg:system/media/audio/ringtones/Draco.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Girtab.ogg:system/media/audio/ringtones/Girtab.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Hydra.ogg:system/media/audio/ringtones/Hydra.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Machina.ogg:system/media/audio/ringtones/Machina.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Orion.ogg:system/media/audio/ringtones/Orion.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Pegasus.ogg:system/media/audio/ringtones/Pegasus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Perseus.ogg:system/media/audio/ringtones/Perseus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Pyxis.ogg:system/media/audio/ringtones/Pyxis.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Rigel.ogg:system/media/audio/ringtones/Rigel.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Scarabaeus.ogg:system/media/audio/ringtones/Scarabaeus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Sceptrum.ogg:system/media/audio/ringtones/Sceptrum.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Solarium.ogg:system/media/audio/ringtones/Solarium.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Themos.ogg:system/media/audio/ringtones/Themos.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/UrsaMinor.ogg:system/media/audio/ringtones/UrsaMinor.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Zeta.ogg:system/media/audio/ringtones/Zeta.ogg
diff --git a/data/sounds/AudioPackage9.mk b/data/sounds/AudioPackage9.mk
new file mode 100755
index 0000000..73e4fd3
--- /dev/null
+++ b/data/sounds/AudioPackage9.mk
@@ -0,0 +1,47 @@
+#
+# Audio Package 9 - Manta
+#
+# Include this file in a product makefile to include these audio files
+#
+#
+
+LOCAL_PATH:= frameworks/base/data/sounds
+
+PRODUCT_COPY_FILES += \
+        $(LOCAL_PATH)/alarms/ogg/Argon.ogg:system/media/audio/alarms/Argon.ogg \
+        $(LOCAL_PATH)/alarms/ogg/Carbon.ogg:system/media/audio/alarms/Carbon.ogg \
+        $(LOCAL_PATH)/alarms/ogg/Helium.ogg:system/media/audio/alarms/Helium.ogg \
+        $(LOCAL_PATH)/alarms/ogg/Krypton.ogg:system/media/audio/alarms/Krypton.ogg \
+        $(LOCAL_PATH)/alarms/ogg/Neon.ogg:system/media/audio/alarms/Neon.ogg \
+        $(LOCAL_PATH)/alarms/ogg/Oxygen.ogg:system/media/audio/alarms/Oxygen.ogg \
+        $(LOCAL_PATH)/alarms/ogg/Osmium.ogg:system/media/audio/alarms/Osmium.ogg \
+        $(LOCAL_PATH)/alarms/ogg/Platinum.ogg:system/media/audio/alarms/Platinum.ogg \
+	$(LOCAL_PATH)/effects/ogg/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressStandard_120.ogg:system/media/audio/ui/KeypressStandard.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressSpacebar_120.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressDelete_120.ogg:system/media/audio/ui/KeypressDelete.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressReturn_120.ogg:system/media/audio/ui/KeypressReturn.ogg \
+	$(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+	$(LOCAL_PATH)/effects/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
+	$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
+	$(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+	$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
+	$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
+	$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
+	$(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Alya.ogg:system/media/audio/notifications/Alya.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Arcturus.ogg:system/media/audio/notifications/Arcturus.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Capella.ogg:system/media/audio/notifications/Capella.ogg \
+	$(LOCAL_PATH)/notifications/ogg/CetiAlpha.ogg:system/media/audio/notifications/CetiAlpha.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Hojus.ogg:system/media/audio/notifications/Hojus.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Mira.ogg:system/media/audio/notifications/Mira.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Pollux.ogg:system/media/audio/notifications/Pollux.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Procyon.ogg:system/media/audio/notifications/Procyon.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Shaula.ogg:system/media/audio/notifications/Shaula.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Spica.ogg:system/media/audio/notifications/Spica.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Syrma.ogg:system/media/audio/notifications/Syrma.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Talitha.ogg:system/media/audio/notifications/Talitha.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Tejat.ogg:system/media/audio/notifications/Tejat.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Girtab.ogg:system/media/audio/ringtones/Girtab.ogg
diff --git a/data/sounds/alarms/ogg/Argon.ogg b/data/sounds/alarms/ogg/Argon.ogg
new file mode 100644
index 0000000..35addf57
--- /dev/null
+++ b/data/sounds/alarms/ogg/Argon.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Carbon.ogg b/data/sounds/alarms/ogg/Carbon.ogg
new file mode 100644
index 0000000..b02a1cc
--- /dev/null
+++ b/data/sounds/alarms/ogg/Carbon.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Fermium.ogg b/data/sounds/alarms/ogg/Fermium.ogg
index fecc2ba..d8f6124 100644
--- a/data/sounds/alarms/ogg/Fermium.ogg
+++ b/data/sounds/alarms/ogg/Fermium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Hassium.ogg b/data/sounds/alarms/ogg/Hassium.ogg
index 260bf7d..793c269 100644
--- a/data/sounds/alarms/ogg/Hassium.ogg
+++ b/data/sounds/alarms/ogg/Hassium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Helium.ogg b/data/sounds/alarms/ogg/Helium.ogg
new file mode 100644
index 0000000..36694cb
--- /dev/null
+++ b/data/sounds/alarms/ogg/Helium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Krypton.ogg b/data/sounds/alarms/ogg/Krypton.ogg
new file mode 100755
index 0000000..48f956b
--- /dev/null
+++ b/data/sounds/alarms/ogg/Krypton.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Neon.ogg b/data/sounds/alarms/ogg/Neon.ogg
new file mode 100644
index 0000000..3089a27
--- /dev/null
+++ b/data/sounds/alarms/ogg/Neon.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Neptunium.ogg b/data/sounds/alarms/ogg/Neptunium.ogg
index b1ea741..d99f133 100644
--- a/data/sounds/alarms/ogg/Neptunium.ogg
+++ b/data/sounds/alarms/ogg/Neptunium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Osmium.ogg b/data/sounds/alarms/ogg/Osmium.ogg
new file mode 100644
index 0000000..4c76080
--- /dev/null
+++ b/data/sounds/alarms/ogg/Osmium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Oxygen.ogg b/data/sounds/alarms/ogg/Oxygen.ogg
new file mode 100644
index 0000000..4dc8ade
--- /dev/null
+++ b/data/sounds/alarms/ogg/Oxygen.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Platinum.ogg b/data/sounds/alarms/ogg/Platinum.ogg
new file mode 100644
index 0000000..d5f0893
--- /dev/null
+++ b/data/sounds/alarms/ogg/Platinum.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Promethium.ogg b/data/sounds/alarms/ogg/Promethium.ogg
new file mode 100644
index 0000000..d5f0893
--- /dev/null
+++ b/data/sounds/alarms/ogg/Promethium.ogg
Binary files differ
diff --git a/data/sounds/alarms/wav/Argon.wav b/data/sounds/alarms/wav/Argon.wav
new file mode 100755
index 0000000..56e57fc
--- /dev/null
+++ b/data/sounds/alarms/wav/Argon.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Carbon.wav b/data/sounds/alarms/wav/Carbon.wav
new file mode 100755
index 0000000..2b855e1
--- /dev/null
+++ b/data/sounds/alarms/wav/Carbon.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Fermium.wav b/data/sounds/alarms/wav/Fermium.wav
index 0174884..56e57fc 100644
--- a/data/sounds/alarms/wav/Fermium.wav
+++ b/data/sounds/alarms/wav/Fermium.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Hassium.wav b/data/sounds/alarms/wav/Hassium.wav
index e3992cf..17710b0 100644
--- a/data/sounds/alarms/wav/Hassium.wav
+++ b/data/sounds/alarms/wav/Hassium.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Helium.wav b/data/sounds/alarms/wav/Helium.wav
new file mode 100644
index 0000000..17710b0
--- /dev/null
+++ b/data/sounds/alarms/wav/Helium.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Krypton.wav b/data/sounds/alarms/wav/Krypton.wav
new file mode 100644
index 0000000..9095e30
--- /dev/null
+++ b/data/sounds/alarms/wav/Krypton.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Neon.wav b/data/sounds/alarms/wav/Neon.wav
new file mode 100644
index 0000000..0e9101a
--- /dev/null
+++ b/data/sounds/alarms/wav/Neon.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Neptunium.wav b/data/sounds/alarms/wav/Neptunium.wav
index cf3684a..2b855e1 100644
--- a/data/sounds/alarms/wav/Neptunium.wav
+++ b/data/sounds/alarms/wav/Neptunium.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Osmium.wav b/data/sounds/alarms/wav/Osmium.wav
new file mode 100755
index 0000000..2dcc47f
--- /dev/null
+++ b/data/sounds/alarms/wav/Osmium.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Oxygen.wav b/data/sounds/alarms/wav/Oxygen.wav
new file mode 100644
index 0000000..bd41869
--- /dev/null
+++ b/data/sounds/alarms/wav/Oxygen.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Platinum.wav b/data/sounds/alarms/wav/Platinum.wav
new file mode 100755
index 0000000..08ea03e
--- /dev/null
+++ b/data/sounds/alarms/wav/Platinum.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Promethium.wav b/data/sounds/alarms/wav/Promethium.wav
new file mode 100755
index 0000000..08ea03e
--- /dev/null
+++ b/data/sounds/alarms/wav/Promethium.wav
Binary files differ
diff --git a/data/sounds/effects/ogg/VideoRecord.ogg b/data/sounds/effects/ogg/VideoRecord.ogg
index d2dee03..0d7bf12 100644
--- a/data/sounds/effects/ogg/VideoRecord.ogg
+++ b/data/sounds/effects/ogg/VideoRecord.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/VideoRecord_48k.ogg b/data/sounds/effects/ogg/VideoRecord_48k.ogg
new file mode 100644
index 0000000..3eefaed
--- /dev/null
+++ b/data/sounds/effects/ogg/VideoRecord_48k.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/VideoStop.ogg b/data/sounds/effects/ogg/VideoStop.ogg
index f16ed13..a20d524 100644
--- a/data/sounds/effects/ogg/VideoStop.ogg
+++ b/data/sounds/effects/ogg/VideoStop.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/VideoStop_48k.ogg b/data/sounds/effects/ogg/VideoStop_48k.ogg
new file mode 100644
index 0000000..7fd9f47
--- /dev/null
+++ b/data/sounds/effects/ogg/VideoStop_48k.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/camera_click.ogg b/data/sounds/effects/ogg/camera_click.ogg
index 44b6683..130b534 100644
--- a/data/sounds/effects/ogg/camera_click.ogg
+++ b/data/sounds/effects/ogg/camera_click.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/camera_click_48k.ogg b/data/sounds/effects/ogg/camera_click_48k.ogg
new file mode 100644
index 0000000..b836e10
--- /dev/null
+++ b/data/sounds/effects/ogg/camera_click_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Alya.ogg b/data/sounds/notifications/ogg/Alya.ogg
new file mode 100644
index 0000000..f07a0d1
--- /dev/null
+++ b/data/sounds/notifications/ogg/Alya.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Syrma.ogg b/data/sounds/notifications/ogg/Syrma.ogg
new file mode 100644
index 0000000..a615441
--- /dev/null
+++ b/data/sounds/notifications/ogg/Syrma.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Talitha.ogg b/data/sounds/notifications/ogg/Talitha.ogg
new file mode 100644
index 0000000..75f2fbd
--- /dev/null
+++ b/data/sounds/notifications/ogg/Talitha.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/ArgoNavis.ogg b/data/sounds/ringtones/ogg/ArgoNavis.ogg
index 8bee29e..d25b5e8 100644
--- a/data/sounds/ringtones/ogg/ArgoNavis.ogg
+++ b/data/sounds/ringtones/ogg/ArgoNavis.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/Atria.ogg b/data/sounds/ringtones/ogg/Atria.ogg
new file mode 100644
index 0000000..5cbb889
--- /dev/null
+++ b/data/sounds/ringtones/ogg/Atria.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/Kuma.ogg b/data/sounds/ringtones/ogg/Kuma.ogg
new file mode 100644
index 0000000..780d5d4
--- /dev/null
+++ b/data/sounds/ringtones/ogg/Kuma.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/Perseus.ogg b/data/sounds/ringtones/ogg/Perseus.ogg
index e5f3fc2..48348e5 100644
--- a/data/sounds/ringtones/ogg/Perseus.ogg
+++ b/data/sounds/ringtones/ogg/Perseus.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/Rasalas.ogg b/data/sounds/ringtones/ogg/Rasalas.ogg
new file mode 100644
index 0000000..7e62f17
--- /dev/null
+++ b/data/sounds/ringtones/ogg/Rasalas.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/Rigel.ogg b/data/sounds/ringtones/ogg/Rigel.ogg
index 4fcb3c0..de3d92f 100644
--- a/data/sounds/ringtones/ogg/Rigel.ogg
+++ b/data/sounds/ringtones/ogg/Rigel.ogg
Binary files differ
diff --git a/docs/html/about/versions/android-2.3.jd b/docs/html/about/versions/android-2.3.jd
index 8715973..89bf432 100644
--- a/docs/html/about/versions/android-2.3.jd
+++ b/docs/html/about/versions/android-2.3.jd
@@ -406,17 +406,6 @@
 </ul>
 </li>
 
-<li>WebView
-<ul>
-<li>New {@link
-android.webkit.WebSettings#setUseWebViewBackgroundForOverscrollBackground(
-boolean) setUseWebViewBackgroundForOverscrollBackground()} method lets a {@link
-android.webkit.WebView} specify whether to use its own background for the
-overscroll background. </li>
-</ul>
-</li>
-</ul>
-
 <h3 id="extralargescreens">Extra Large Screens</h3>
 
 <p>The platform now supports extra large screen sizes, such as those that might
@@ -707,4 +696,4 @@
 versions of the platform.</p>
 
 <p>For more information, read <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">What is API
-Level?</a></p>
\ No newline at end of file
+Level?</a></p>
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_10/land_back.png b/docs/html/distribute/promote/device-art-resources/nexus_10/land_back.png
new file mode 100644
index 0000000..d082d50
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_10/land_back.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_10/land_fore.png b/docs/html/distribute/promote/device-art-resources/nexus_10/land_fore.png
new file mode 100644
index 0000000..d29f818
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_10/land_fore.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_10/land_shadow.png b/docs/html/distribute/promote/device-art-resources/nexus_10/land_shadow.png
new file mode 100644
index 0000000..af1a249
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_10/land_shadow.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_10/port_back.png b/docs/html/distribute/promote/device-art-resources/nexus_10/port_back.png
new file mode 100644
index 0000000..501690b
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_10/port_back.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_10/port_fore.png b/docs/html/distribute/promote/device-art-resources/nexus_10/port_fore.png
new file mode 100644
index 0000000..689a72a3
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_10/port_fore.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_10/port_shadow.png b/docs/html/distribute/promote/device-art-resources/nexus_10/port_shadow.png
new file mode 100644
index 0000000..b2265ef
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_10/port_shadow.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_10/thumb.png b/docs/html/distribute/promote/device-art-resources/nexus_10/thumb.png
new file mode 100644
index 0000000..8d8dee9
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_10/thumb.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_4/land_back.png b/docs/html/distribute/promote/device-art-resources/nexus_4/land_back.png
new file mode 100644
index 0000000..57a011a
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_4/land_back.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_4/land_fore.png b/docs/html/distribute/promote/device-art-resources/nexus_4/land_fore.png
new file mode 100644
index 0000000..72c9654
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_4/land_fore.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_4/land_shadow.png b/docs/html/distribute/promote/device-art-resources/nexus_4/land_shadow.png
new file mode 100644
index 0000000..d80a5fd
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_4/land_shadow.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_4/port_back.png b/docs/html/distribute/promote/device-art-resources/nexus_4/port_back.png
new file mode 100644
index 0000000..e64fae4
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_4/port_back.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_4/port_fore.png b/docs/html/distribute/promote/device-art-resources/nexus_4/port_fore.png
new file mode 100644
index 0000000..c9fb062
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_4/port_fore.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_4/port_shadow.png b/docs/html/distribute/promote/device-art-resources/nexus_4/port_shadow.png
new file mode 100644
index 0000000..b2064a35
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_4/port_shadow.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_4/thumb.png b/docs/html/distribute/promote/device-art-resources/nexus_4/thumb.png
new file mode 100644
index 0000000..2988dc9
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_4/thumb.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_7/land_back.png b/docs/html/distribute/promote/device-art-resources/nexus_7/land_back.png
index 2999f35..697fb7d 100644
--- a/docs/html/distribute/promote/device-art-resources/nexus_7/land_back.png
+++ b/docs/html/distribute/promote/device-art-resources/nexus_7/land_back.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_7/land_fore.png b/docs/html/distribute/promote/device-art-resources/nexus_7/land_fore.png
index cefdd351..735262f 100644
--- a/docs/html/distribute/promote/device-art-resources/nexus_7/land_fore.png
+++ b/docs/html/distribute/promote/device-art-resources/nexus_7/land_fore.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_7/land_shadow.png b/docs/html/distribute/promote/device-art-resources/nexus_7/land_shadow.png
index 8f7aec7..cfb7952 100644
--- a/docs/html/distribute/promote/device-art-resources/nexus_7/land_shadow.png
+++ b/docs/html/distribute/promote/device-art-resources/nexus_7/land_shadow.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_7/port_back.png b/docs/html/distribute/promote/device-art-resources/nexus_7/port_back.png
index b2908a8..5bb815a 100644
--- a/docs/html/distribute/promote/device-art-resources/nexus_7/port_back.png
+++ b/docs/html/distribute/promote/device-art-resources/nexus_7/port_back.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_7/port_fore.png b/docs/html/distribute/promote/device-art-resources/nexus_7/port_fore.png
index 7f4b0b4..1be3b21 100644
--- a/docs/html/distribute/promote/device-art-resources/nexus_7/port_fore.png
+++ b/docs/html/distribute/promote/device-art-resources/nexus_7/port_fore.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_7/port_shadow.png b/docs/html/distribute/promote/device-art-resources/nexus_7/port_shadow.png
index c10bd53..7e8aff2 100644
--- a/docs/html/distribute/promote/device-art-resources/nexus_7/port_shadow.png
+++ b/docs/html/distribute/promote/device-art-resources/nexus_7/port_shadow.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_7/thumb.png b/docs/html/distribute/promote/device-art-resources/nexus_7/thumb.png
index 8b5cc5a..b5db82e 100644
--- a/docs/html/distribute/promote/device-art-resources/nexus_7/thumb.png
+++ b/docs/html/distribute/promote/device-art-resources/nexus_7/thumb.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art.jd b/docs/html/distribute/promote/device-art.jd
index 93f772a..55b846e 100644
--- a/docs/html/distribute/promote/device-art.jd
+++ b/docs/html/distribute/promote/device-art.jd
@@ -18,7 +18,9 @@
     <p>Drag a screenshot from your desktop onto a device to the right.</p>
   </div>
   <div class="layout-content-col span-10">
-    <ul id="device-list"></ul>
+    <ul class="device-list primary"></ul>
+    <a href="#" id="archive-expando">Older devices</a>
+    <ul class="device-list archive"></ul>
   </div>
 </div>
 
@@ -57,12 +59,12 @@
     text-transform: uppercase;
   }
 
-  #device-list {
+  .device-list {
     padding: 0;
     margin: 0;
   }
 
-  #device-list li {
+  .device-list li {
     display: inline-block;
     vertical-align: bottom;
     margin: 0;
@@ -70,11 +72,11 @@
     text-align: center;
   }
 
-  #device-list li .thumb-container {
+  .device-list li .thumb-container {
     display: inline-block;
   }
 
-  #device-list li .thumb-container img {
+  .device-list li .thumb-container img {
     margin-bottom: 8px;
     opacity: 0.6;
 
@@ -83,7 +85,7 @@
             transition:         transform 0.2s, opacity 0.2s;
   }
 
-  #device-list li.drag-hover .thumb-container img {
+  .device-list li.drag-hover .thumb-container img {
     opacity: 1;
 
     -webkit-transform: scale(1.1);
@@ -91,16 +93,35 @@
             transform: scale(1.1);
   }
 
-  #device-list li .device-details {
+  .device-list li .device-details {
     font-size: 13px;
     line-height: 16px;
     color: #888;
   }
 
-  #device-list li .device-url {
+  .device-list li .device-url {
     font-weight: bold;
   }
 
+  #archive-expando {
+    display: block;
+    font-size: 13px;
+    font-weight: bold;
+    color: #333;
+    text-transform: uppercase;
+    margin-top: 16px;
+    padding-top: 16px;
+    padding-left: 28px;
+    border-top: 1px solid transparent;
+    background: transparent url({@docRoot}assets/images/styles/disclosure_down.png)
+                no-repeat scroll 0 8px;
+  }
+
+  #archive-expando.expanded {
+    background-image: url({@docRoot}assets/images/styles/disclosure_up.png);
+    border-top: 1px solid #ccc;
+  }
+
   #output {
     color: #f44;
     font-style: italic;
@@ -117,7 +138,7 @@
 
   // Global constants
   var MSG_INVALID_INPUT_IMAGE = 'Invalid screenshot provided. Screenshots must be PNG files '
-      + 'matching the target device\'s screen resolution in either portrait or landscape.';
+      + 'matching the target device\'s screen aspect ratio in either portrait or landscape.';
   var MSG_NO_INPUT_IMAGE = 'Drag a screenshot (in PNG format) from your desktop onto a '
       + 'target device above.'
   var MSG_GENERATING_IMAGE = 'Generating device art&hellip;';
@@ -127,17 +148,44 @@
   // Device manifest.
   var DEVICES = [
     {
+      id: 'nexus_4',
+      title: 'Nexus 4',
+      url: 'http://www.google.com/nexus/4/',
+      physicalSize: 4.7,
+      physicalHeight: 5.23,
+      density: 'XHDPI',
+      landRes: ['shadow', 'back', 'fore'],
+      landOffset: [349,214],
+      portRes: ['shadow', 'back', 'fore'],
+      portOffset: [213,350],
+      portSize: [768,1280]
+    },
+    {
       id: 'nexus_7',
       title: 'Nexus 7',
-      url: 'http://www.android.com/devices/detail/nexus-7',
+      url: 'http://www.google.com/nexus/7/',
       physicalSize: 7,
       physicalHeight: 7.81,
-      density: 213,
+      density: '213dpi',
       landRes: ['shadow', 'back', 'fore'],
-      landOffset: [363,260],
+      landOffset: [315,270],
       portRes: ['shadow', 'back', 'fore'],
-      portOffset: [265,341],
-      portSize: [800,1280],
+      portOffset: [264,311],
+      portSize: [800,1280]
+    },
+    {
+      id: 'nexus_10',
+      title: 'Nexus 10',
+      url: 'http://www.google.com/nexus/10/',
+      physicalSize: 10,
+      physicalHeight: 7,
+      actualResolution: [1600,2560],
+      density: 'XHDPI',
+      landRes: ['shadow', 'back', 'fore'],
+      landOffset: [227,217],
+      portRes: ['shadow', 'back', 'fore'],
+      portOffset: [217,223],
+      portSize: [800,1280]
     },
     {
       id: 'xoom',
@@ -145,12 +193,13 @@
       url: 'http://www.google.com/phone/detail/motorola-xoom',
       physicalSize: 10,
       physicalHeight: 6.61,
-      density: 160,
+      density: 'MDPI',
       landRes: ['shadow', 'back', 'fore'],
       landOffset: [218,191],
       portRes: ['shadow', 'back', 'fore'],
       portOffset: [199,200],
       portSize: [800,1280],
+      archived: true
     },
     {
       id: 'galaxy_nexus',
@@ -158,12 +207,13 @@
       url: 'http://www.android.com/devices/detail/galaxy-nexus',
       physicalSize: 4.65,
       physicalHeight: 5.33,
-      density: 320,
+      density: 'XHDPI',
       landRes: ['shadow', 'back', 'fore'],
       landOffset: [371,199],
       portRes: ['shadow', 'back', 'fore'],
       portOffset: [216,353],
       portSize: [720,1280],
+      archived: true
     },
     {
       id: 'nexus_s',
@@ -171,12 +221,13 @@
       url: 'http://www.google.com/phone/detail/nexus-s',
       physicalSize: 4.0,
       physicalHeight: 4.88,
-      density: 240,
+      density: 'HDPI',
       landRes: ['shadow', 'back', 'fore'],
       landOffset: [247,135],
       portRes: ['shadow', 'back', 'fore'],
       portOffset: [134,247],
       portSize: [480,800],
+      archived: true
     }
   ];
 
@@ -250,13 +301,23 @@
     $('#output').html(MSG_NO_INPUT_IMAGE);
 
     $('#frame-customizations').hide();
+    $('.device-list.archive').hide();
 
     $('#output-shadow, #output-glare').click(function() {
-      createFrame(g_currentDevice, g_currentImage);
+      createFrame();
     });
 
     // Build device list.
     $.each(DEVICES, function() {
+      var resolution = this.actualResolution || this.portSize;
+      var scaleFactorText = '';
+      if (resolution[0] != this.portSize[0]) {
+        scaleFactorText = '<br>' + (100 * (this.portSize[0] / resolution[0])).toFixed(0) +
+            '% size output';
+      } else {
+        scaleFactorText = '<br>&nbsp;';
+      }
+
       $('<li>')
           .append($('<div>')
               .addClass('thumb-container')
@@ -269,14 +330,26 @@
               .html((this.url
                   ? ('<a class="device-url" href="' + this.url + '">' + this.title + '</a>')
                   : this.title) +
-                '<br>' +  this.physicalSize + '" @ ' + this.density + 'dpi' +
-                '<br>' + this.portSize[0] + 'x' + this.portSize[1]))
+                  '<br>' +  this.physicalSize + '" @ ' + this.density +
+                  '<br>' + (resolution[0] + 'x' + resolution[1]) + scaleFactorText))
           .data('deviceId', this.id)
-          .appendTo('#device-list');
+          .appendTo(this.archived ? '.device-list.archive' : '.device-list.primary');
+    });
+
+    // Set up "older devices" expando.
+    $('#archive-expando').click(function() {
+      if ($(this).hasClass('expanded')) {
+        $(this).removeClass('expanded');
+        $('.device-list.archive').hide();
+      } else {
+        $(this).addClass('expanded');
+        $('.device-list.archive').show();
+      }
+      return false;
     });
 
     // Set up drag and drop.
-    $('#device-list li')
+    $('.device-list li')
         .live('dragover', function(evt) {
           $(this).addClass('drag-hover');
           evt.dataTransfer.dropEffect = 'link';
@@ -335,27 +408,19 @@
    */
   function createFrame() {
     var port;
-    if (g_currentImage.naturalWidth  == g_currentDevice.portSize[0] &&
-        g_currentImage.naturalHeight == g_currentDevice.portSize[1]) {
-      if (!g_currentDevice.portRes) {
-        alert('No portrait frame is currently available for this device.');
-        $('#output').html(MSG_NO_INPUT_IMAGE);
-        return;
-      }
+
+    var aspect1 = g_currentImage.naturalWidth / g_currentImage.naturalHeight;
+    var aspect2 = g_currentDevice.portSize[0] / g_currentDevice.portSize[1];
+
+    if (aspect1 == aspect2) {
       port = true;
-    } else if (g_currentImage.naturalWidth  == g_currentDevice.portSize[1] &&
-               g_currentImage.naturalHeight == g_currentDevice.portSize[0]) {
-      if (!g_currentDevice.landRes) {
-        alert('No landscape frame is currently available for this device.');
-        $('#output').html(MSG_NO_INPUT_IMAGE);
-        return;
-      }
+    } else if (aspect1 == 1 / aspect2) {
       port = false;
     } else {
-      alert('Screenshots for ' + g_currentDevice.title + ' must be ' +
-          g_currentDevice.portSize[0] + 'x' + g_currentDevice.portSize[1] +
-          ' or ' +
-          g_currentDevice.portSize[1] + 'x' + g_currentDevice.portSize[0] + '.');
+      alert('The screenshot must have an aspect ratio of ' +
+          aspect2.toFixed(3) + ' or ' + (1 / aspect2).toFixed(3) +
+          ' (ideally ' + g_currentDevice.portSize[0] + 'x' + g_currentDevice.portSize[1] +
+          ' or ' + g_currentDevice.portSize[1] + 'x' + g_currentDevice.portSize[0] + ').');
       $('#output').html(MSG_INVALID_INPUT_IMAGE);
       return;
     }
@@ -378,6 +443,9 @@
       var width = resourceImages['back'].naturalWidth;
       var height = resourceImages['back'].naturalHeight;
       var offset = port ? g_currentDevice.portOffset : g_currentDevice.landOffset;
+      var size = port
+          ? g_currentDevice.portSize
+          : [g_currentDevice.portSize[1], g_currentDevice.portSize[0]];
 
       var canvas = document.createElement('canvas');
       canvas.width = width;
@@ -388,7 +456,9 @@
         ctx.drawImage(resourceImages['shadow'], 0, 0);
       }
       ctx.drawImage(resourceImages['back'], 0, 0);
-      ctx.drawImage(g_currentImage, offset[0], offset[1]);
+      ctx.fillStyle = '#000';
+      ctx.fillRect(offset[0], offset[1], size[0], size[1]);
+      ctx.drawImage(g_currentImage, offset[0], offset[1], size[0], size[1]);
       if (resourceImages['fore'] && $('#output-glare').is(':checked')) {
         ctx.drawImage(resourceImages['fore'], 0, 0);
       }
diff --git a/docs/html/guide/faq/security.jd b/docs/html/guide/faq/security.jd
index 52ee0d9..a6e07c8 100644
--- a/docs/html/guide/faq/security.jd
+++ b/docs/html/guide/faq/security.jd
@@ -57,9 +57,7 @@
 <p>We appreciate researchers practicing responsible disclosure by emailing us
 with a detailed summary of the issue and keeping the issue confidential while
 users are at risk. In return, we will make sure to keep the researcher informed
-of our progress in issuing a fix and will properly credit the reporter(s) when
-we provide the patch. We will always move swiftly to mitigate or fix an
-externally-reported flaw and provide updates to users. </p>
+of our progress in issuing a fix. </p>
 
 
 <a name="informed" id="informed"></a><h2>How can I stay informed about Android security?</h2>
diff --git a/docs/html/guide/google/gcm/gcm.jd b/docs/html/guide/google/gcm/gcm.jd
index 5d3ea56..a402e8e 100644
--- a/docs/html/guide/google/gcm/gcm.jd
+++ b/docs/html/guide/google/gcm/gcm.jd
@@ -659,8 +659,10 @@
     <td><code>data</code></td>
     <td>A JSON object whose fields represents the key-value pairs of the message's payload data. If present, the payload data it will be
 included in the Intent as application data, with the key being the extra's name. For instance, <code>"data":{"score":"3x1"}</code> would result in an intent extra named <code>score</code> whose value is the string <code>3x1</code>. 
+
 There is no limit on the number of key/value pairs, though there is a limit on the total size of the message (4kb). The values could be any JSON object, but we recommend using strings, since the values will be converted to strings in the GCM server anyway. If you want to include objects or other non-string data types (such as integers or booleans), you have to do the conversion to string yourself. Also note that the key cannot be a reserved word (<code>from</code> or any word starting with <code>google.</code>). To complicate things slightly, there are some reserved words (such as <code>collapse_key</code>) that are technically allowed in payload data. However, if the request also contains the word, the value in the request will overwrite the value in the payload data. Hence using words that are defined as field names in this table is not recommended, even in cases where they are technically allowed. Optional.</td>
 
+
   </tr>
   <tr>
     <td><code>delay_while_idle</code></td>
@@ -701,8 +703,10 @@
   </tr>
   <tr>
     <td><code>data.&lt;key&gt;</code></td>
+
     <td>Payload data, expressed as parameters prefixed with <code>data.</code> and suffixed as the key. For instance, a parameter of <code>data.score=3x1</code> would result in an intent extra named <code>score</code> whose value is the string <code>3x1</code>. There is no limit on the number of key/value parameters, though there is a limit on the total size of the  message. Also note that the key cannot be a reserved word (<code>from</code> or any word starting with 
 <code>google.</code>). To complicate things slightly, there are some reserved words (such as <code>collapse_key</code>) that are technically allowed in payload data. However, if the request also contains the word, the value in the request will overwrite the value in the payload data. Hence using words that are defined as field names in this table is not recommended, even in cases where they are technically allowed. Optional.</td>
+
   </tr>
   <tr>
     <td><code>delay_while_idle</code></td>
@@ -912,13 +916,11 @@
 </ul>
 Check that the token you're sending inside the <code>Authorization</code> header is the correct API key associated with your project. You can check the validity of your API key by running the following command:<br/>
 
-
 <pre># api_key=YOUR_API_KEY
 
 # curl --header "Authorization: key=$api_key" --header Content-Type:"application/json" https://android.googleapis.com/gcm/send  -d "{\"registration_ids\":[\"ABC\"]}"</pre>
 
 
-
 If you receive a 401 HTTP status code, your API key is not valid. Otherwise you should see something like this:<br/>
 
 <pre>
diff --git a/docs/html/guide/practices/security.jd b/docs/html/guide/practices/security.jd
index ce59a9d..36eeff8 100644
--- a/docs/html/guide/practices/security.jd
+++ b/docs/html/guide/practices/security.jd
@@ -1,11 +1,11 @@
-page.title=Designing for Security
+page.title=Designing for Security
 @jd:body
 
 <div id="qv-wrapper">
 <div id="qv">
 <h2>In this document</h2>
 <ol>
-<li><a href="#Dalvik">Using Davlik Code</a></li>
+<li><a href="#Dalvik">Using Dalvik Code</a></li>
 <li><a href="#Native">Using Native Code</a></li>
 <li><a href="#Data">Storing Data</a></li>
 <li><a href="#IPC">Using IPC</a></li>
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index 844be11..2aedaec 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -218,7 +218,8 @@
   <td>"{@code uiMode}"</td>
    <td>The user interface mode has changed &mdash; this can be caused when the user places the
 device into a desk/car dock or when the the night mode changes. See {@link
-android.app.UiModeManager}. <em>Introduced in API Level 8</em>.</td>
+android.app.UiModeManager}. 
+    <em>Added in API level 8</em>.</td>
   </tr><tr>
    <td>"{@code orientation}"</td>
    <td>The screen orientation has changed &mdash; the user has rotated the device. 
@@ -246,7 +247,12 @@
 your activity always handles this configuration change itself (this configuration change does not
 restart your activity, even when running on an Android 3.2 or higher device).
   <p><em>Added in API level 13.</em></p></td>
- </tr>
+ </tr><tr>
+  <td>"{@code layoutDirection}"</td>
+   <td>The layout direction has changed. For example, changing from left-to-right (LTR)
+    to right-to-left (RTL).
+   <em>Added in API level 17.</em></td>
+  </tr>
 </table>
 
 <p>
diff --git a/docs/html/guide/topics/manifest/application-element.jd b/docs/html/guide/topics/manifest/application-element.jd
index 2105a504..42cfdd5 100644
--- a/docs/html/guide/topics/manifest/application-element.jd
+++ b/docs/html/guide/topics/manifest/application-element.jd
@@ -23,6 +23,7 @@
              android:<a href="#persistent">persistent</a>=["true" | "false"]
              android:<a href="#proc">process</a>="<i>string</i>"
              android:<a href="#restoreany">restoreAnyVersion</a>=["true" | "false"]
+             android:<a href="#supportsrtl">supportsRtl</a>=["true" | "false"]
              android:<a href="#aff">taskAffinity</a>="<i>string</i>"
              android:<a href="#theme">theme</a>="<i>resource or theme</i>"
              android:<a href="#uioptions">uiOptions</a>=["none" | "splitActionBarWhenNarrow"] &gt;
@@ -271,7 +272,7 @@
 </p></dd>
 
 <dt><a name="restoreany"></a>{@code android:restoreAnyVersion}</dt>
-<dd>Indicate that the application is prepared to attempt a restore of any
+<dd>Indicates that the application is prepared to attempt a restore of any
 backed-up data set, even if the backup was stored by a newer version
 of the application than is currently installed on the device.  Setting
 this attribute to {@code true} will permit the Backup Manager to
@@ -281,6 +282,21 @@
 <p>The default value of this attribute is {@code false}.
 </p></dd>
 
+<dt><a name="supportsrtl"></a>{@code android:supportsRtl}</dt>
+<dd>Declares whether your application is willing to support right-to-left (RTL) layouts.
+<p>If set to {@code true} and <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target"
+>{@code targetSdkVersion}</a> is set to 17 or higher, various RTL APIs will be
+activated and used by the system so your app can display RTL layouts.
+If set to {@code false} or if <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target"
+>{@code targetSdkVersion}</a> is set to 16 or lower, the RTL APIs will be ignored
+or will have no effect and your app will behave the same regardless of the layout
+direction associated to the user's Locale choice (your layouts will always be left-to-right).
+
+<p>The default value of this attribute is {@code false}.</p>
+
+<p>This attribute was added in API level 17.</p>
+</dd>
+
 <dt><a name="aff"></a>{@code android:taskAffinity}</dt>
 <dd>An affinity name that applies to all activities within the application,
 except for those that set a different affinity with their own
diff --git a/docs/html/guide/topics/manifest/permission-element.jd b/docs/html/guide/topics/manifest/permission-element.jd
index c256fb1..a23fb4b 100644
--- a/docs/html/guide/topics/manifest/permission-element.jd
+++ b/docs/html/guide/topics/manifest/permission-element.jd
@@ -111,7 +111,7 @@
    <td>"{@code signatureOrSystem}"</td>
    <td>A permission that the system grants only to applications that are 
        in the Android system image <em>or</em> that are signed with the same
-       certificates as those in the system image.  Please avoid using this 
+       certificate as the application that declared the permission. Please avoid using this 
        option, as the {@code signature} protection level should be sufficient 
        for most needs and works regardless of exactly where applications are 
        installed.  The "{@code signatureOrSystem}"
diff --git a/docs/html/guide/topics/manifest/provider-element.jd b/docs/html/guide/topics/manifest/provider-element.jd
index 4558800..6cf6843 100644
--- a/docs/html/guide/topics/manifest/provider-element.jd
+++ b/docs/html/guide/topics/manifest/provider-element.jd
@@ -5,7 +5,9 @@
 
 <dl class="xml">
 <dt>syntax:</dt>
-<dd><pre class="stx">&lt;provider android:<a href="#auth">authorities</a>="<i>list</i>"
+<dd>
+<pre class="stx">
+&lt;provider android:<a href="#auth">authorities</a>="<i>list</i>"
           android:<a href="#enabled">enabled</a>=["true" | "false"]
           android:<a href="#exported">exported</a>=["true" | "false"]
           android:<a href="#gprmsn">grantUriPermissions</a>=["true" | "false"]
@@ -20,10 +22,13 @@
           android:<a href="#sync">syncable</a>=["true" | "false"]
           android:<a href="#wprmsn">writePermission</a>="<i>string</i>" &gt;
     . . .
-&lt;/provider&gt;</pre></dd>
+&lt;/provider&gt;</pre>
+</dd>
 
 <dt>contained in:</dt>
-<dd><code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code></dd>
+<dd>
+    <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
+</dd>
 
 <dt>can contain:</dt>
 <dd><code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
@@ -31,58 +36,67 @@
 <br/><code><a href="{@docRoot}guide/topics/manifest/path-permission-element.html">&lt;path-permission&gt;</a></code></dd>
 
 <dt>description:</dt>
-<dd>Declares a content provider &mdash; a subclass of 
-{@link android.content.ContentProvider} &mdash; that supplies structured 
-access to data managed by the application.  All content providers that 
-are part of the application must be represented by {@code &lt;provider&gt;} 
-elements in the manifest file.  The system cannot see, and therefore will 
-not run, any that are not declared.  (You need to declare only 
-those content providers that you develop as part of your application,
-not those developed by others that your application uses.)
-
-<p>
-The Android system identifies content providers by the authority part
- of a {@code content:} URI.  For example, suppose that the following URI 
-is passed to <code>{@link android.content.ContentResolver#query 
-ContentResolver.query()}</code>:
-
-<p style="margin-left: 2em">{@code content://com.example.project.healthcareprovider/nurses/rn}</p>
-
-<p>
-The {@code content:} scheme identifies the data as belonging to a content 
-provider and the authority ({@code com.example.project.healthcareprovider}) 
-identifies the particular provider.  The authority therefore must be unique.  
-Typically, as in this example, it's the fully qualified name of a 
-ContentProvider subclass.  The path part of a URI may be used by a content 
-provider to identify particular data subsets, but those paths are not
-declared in the manifest.
-</p>
-
-<p>
-For information on using and developing content providers, see a separate document, 
-<a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.
-</p></dd>
+<dd>
+    Declares a content provider component. A content provider is a subclass of 
+    {@link android.content.ContentProvider} that supplies structured access to data managed by the 
+    application.  All content providers in your application must be defined in a 
+    {@code &lt;provider&gt;} element in the manifest file; otherwise, the system is unaware of them 
+    and doesn't run them.
+    <p>
+        You only declare content providers that are part of your application. Content providers in
+        other applications that you use in your application should not be declared.
+    </p>  
+    <p>
+        The Android system stores references to content providers according to an <b>authority</b>
+        string, part of the provider's <b>content URI</b>. For example, suppose you want to 
+        access a content provider that stores information about health care professionals. To do
+        this, you call the method 
+        {@link android.content.ContentResolver#query ContentResolver.query()}, which among other
+        arguments takes a URI that identifies the provider:
+    </p> 
+<pre>
+content://com.example.project.healthcareprovider/nurses/rn
+</pre>
+    <p>
+        The <code>content:</code> <b>scheme</b> identifies the URI as a content URI pointing to
+        an Android content provider. The authority 
+        <code>com.example.project.healthcareprovider</code> identifies the provider itself; the
+        Android system looks up the authority in its list of known providers and their authorities. 
+        The substring <code>nurses/rn</code> is a <b>path</b>, which the content provider can use 
+        to identify subsets of the provider data.
+    </p>
+    <p>
+        Notice that when you define your provider in the <code>&lt;provider&gt;</code> element, you 
+        don't include the scheme or the path in the <code>android:name</code> argument, only the
+        authority.    
+    </p>
+    <p>
+        For information on using and developing content providers, see the API Guide, 
+        <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.
+    </p>
+</dd>
 
 <dt>attributes:</dt>
-<dd><dl class="attr">
-<dt><a name="auth"></a>{@code android:authorities}</dt>
-<dd>A list of one or more URI authorities that identify data under the purview 
-of the content provider.
-Multiple authorities are listed by separating their names with a semicolon. 
-To avoid conflicts, authority names should use a Java-style naming convention 
-(such as {@code com.example.provider.cartoonprovider}).  Typically, it's the name
-of the ContentProvider subclass.
+<dd>
+    <dl class="attr">
+        <dt><a name="auth"></a>{@code android:authorities}</dt>
+        <dd>
+        A list of one or more URI authorities that identify data offered by the content provider.
+        Multiple authorities are listed by separating their names with a semicolon. 
+        To avoid conflicts, authority names should use a Java-style naming convention 
+        (such as {@code com.example.provider.cartoonprovider}).  Typically, it's the name
+        of the {@link android.content.ContentProvider} subclass that implements the provider
+        <p>
+            There is no default.  At least one authority must be specified.
+        </p>
+        </dd>
 
-<p>
-There is no default.  At least one authority must be specified.
-</p></dd>
+        <dt><a name="enabled"></a>{@code android:enabled}</dt>
+        <dd>Whether or not the content provider can be instantiated by the system &mdash; 
+        "{@code true}" if it can be, and "{@code false}" if not.  The default value 
+        is "{@code true}".
 
-<dt><a name="enabled"></a>{@code android:enabled}</dt>
-<dd>Whether or not the content provider can be instantiated by the system &mdash; 
-"{@code true}" if it can be, and "{@code false}" if not.  The default value 
-is "{@code true}".
-
-<p>
+        <p>
 The <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element has its own 
 <code><a href="{@docRoot}guide/topics/manifest/application-element.html#enabled">enabled</a></code> attribute that applies to all 
 application components, including content providers.  The 
@@ -93,16 +107,37 @@
 </p></dd>
 
 <dt><a name="exported"></a>{@code android:exported}</dt>
-<dd>Whether or not the content provider can be used by components of other 
-applications &mdash; "{@code true}" if it can be, and "{@code false}" if not.  
-If "{@code false}", the provider is available only to components of the 
-same application or applications with the same user ID.  The default value
-is "{@code true}".
-
-<p>
-You can export a content provider but still limit access to it with the
-<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">permission</a></code> attribute.
-</p></dd> 
+<dd>
+    Whether the content provider is available for other applications to use:
+    <ul> 
+        <li>
+            <code>true</code>: The provider is available to other applications. Any application can
+            use the provider's content URI to access it, subject to the permissions specified for
+            the provider.
+        </li>
+        <li>
+            <code>false</code>: The provider is not available to other applications. Set 
+            <code>android:exported="false"</code> to limit access to the provider to your
+            applications. Only applications that have the same user ID (UID) as the provider will
+            have access to it.
+        </li>
+    </ul>
+    <p>
+        The default value is <code>"true"</code> for applications that set either 
+<code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">android:minSdkVersion</a></code>
+        or 
+<code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">android:targetSdkVersion</a></code> to 
+        <code>"16"</code> or lower. For applications that
+        set either of these attributes to <code>"17"</code> or higher, the default is 
+        <code>"false"</code>.
+    </p>
+    <p>
+        You can set <code>android:exported="false"</code> and still limit access to your
+        provider by setting permissions with the 
+   <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">permission</a></code>
+        attribute.
+    </p>
+</dd> 
 
 <dt><a name="gprmsn"></a>{@code android:grantUriPermissions}</dt>
 <dd>Whether or not those who ordinarily would not have permission to 
diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd
index a111356..10b5a33 100644
--- a/docs/html/guide/topics/manifest/uses-feature-element.jd
+++ b/docs/html/guide/topics/manifest/uses-feature-element.jd
@@ -561,7 +561,7 @@
 </td>
     </tr>
     <tr>
-       <td rowspan="4">Camera</td>
+       <td rowspan="5">Camera</td>
        <td><code>android.hardware.camera</code></td>
        <td>The application uses the device's camera. If the device supports
            multiple cameras, the application uses the camera that facing
@@ -583,6 +583,12 @@
   <td><code>android.hardware.camera.front</code></td>
   <td>Subfeature. The application uses a front-facing camera on the device.</td>
 </tr>
+<tr>
+  <td><code>android.hardware.camera.any</code></td>
+  <td>The application uses at least one camera facing in any direction. Use this
+in preference to <code>android.hardware.camera</code> if a back-facing camera is
+not required.</td>
+</tr>
 
 <tr>
   <td rowspan="3">Location</td>
diff --git a/docs/html/guide/topics/providers/content-provider-basics.jd b/docs/html/guide/topics/providers/content-provider-basics.jd
index 8c47ad7..527e713 100644
--- a/docs/html/guide/topics/providers/content-provider-basics.jd
+++ b/docs/html/guide/topics/providers/content-provider-basics.jd
@@ -2,9 +2,7 @@
 @jd:body
 <div id="qv-wrapper">
 <div id="qv">
-
-
-                    <!-- In this document -->
+<!-- In this document -->
 <h2>In this document</h2>
 <ol>
     <li>
@@ -238,15 +236,11 @@
 </p>
 <p>
     For example, to get a list of the words and their locales from the User Dictionary Provider,
-    you call {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
-    ContentResolver.query()}.
-    The {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
-    query()} method calls the
-    {@link android.content.ContentProvider#query(Uri, String[], String, String[], String)
-    ContentProvider.query()} method defined by the User Dictionary Provider. The following lines
-    of code show a
-    {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
-    ContentResolver.query()} call:
+    you call {@link android.content.ContentResolver#query ContentResolver.query()}.
+    The {@link android.content.ContentResolver#query query()} method calls the
+    {@link android.content.ContentProvider#query ContentProvider.query()} method defined by the 
+    User Dictionary Provider. The following lines of code show a
+    {@link android.content.ContentResolver#query ContentResolver.query()} call:
 <p>
 <pre>
 // Queries the user dictionary and returns results
@@ -259,7 +253,7 @@
 </pre>
 <p>
     Table 2 shows how the arguments to
-    {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
+    {@link android.content.ContentResolver#query 
     query(Uri,projection,selection,selectionArgs,sortOrder)} match an SQL SELECT statement:
 </p>
 <p class="table-caption">
@@ -344,7 +338,7 @@
     <code>4</code> from user dictionary, you can use this content URI:
 </p>
 <pre>
-Uri singleUri = ContentUri.withAppendedId(UserDictionary.Words.CONTENT_URI,4);
+Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);
 </pre>
 <p>
     You often use id values when you've retrieved a set of rows and then want to update or delete
@@ -354,7 +348,7 @@
     <strong>Note:</strong> The {@link android.net.Uri} and {@link android.net.Uri.Builder} classes
     contain convenience methods for constructing well-formed Uri objects from strings. The
     {@link android.content.ContentUris} contains convenience methods for appending id values to
-    a URI. The previous snippet uses {@link android.content.ContentUris#withAppendedId(Uri, long)
+    a URI. The previous snippet uses {@link android.content.ContentUris#withAppendedId
     withAppendedId()} to append an id to the UserDictionary content URI.
 </p>
 
@@ -367,10 +361,9 @@
 </p>
 <p class="note">
     For the sake of clarity, the code snippets in this section call
-    {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
-    ContentResolver.query()} on the "UI thread"". In actual code, however, you should
-    do queries asynchronously on a separate thread. One way to do this is to use the
-    {@link android.content.CursorLoader} class, which is described
+    {@link android.content.ContentResolver#query ContentResolver.query()} on the "UI thread"". In 
+    actual code, however, you should do queries asynchronously on a separate thread. One way to do 
+    this is to use the {@link android.content.CursorLoader} class, which is described
     in more detail in the <a href="{@docRoot}guide/components/loaders.html">
     Loaders</a> guide. Also, the lines of code are snippets only; they don't show a complete
     application.
@@ -391,8 +384,8 @@
     To retrieve data from a provider, your application needs "read access permission" for the
     provider. You can't request this permission at run-time; instead, you have to specify that
     you need this permission in your manifest, using the
-    <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">
-    &lt;uses-permission&gt;</a></code> element and the exact permission name defined by the
+<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
+    element and the exact permission name defined by the
     provider. When you specify this element in your manifest, you are in effect "requesting" this
     permission for your application. When users install your application, they implicitly grant
     this request.
@@ -436,10 +429,9 @@
 </pre>
 <p>
     The next snippet shows how to use
-    {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
-    ContentResolver.query()}, using the User Dictionary Provider as an example.
-    A provider client query is similar to an SQL query, and it contains a set of columns to return,
-    a set of selection criteria, and a sort order.
+    {@link android.content.ContentResolver#query ContentResolver.query()}, using the User Dictionary
+    Provider as an example. A provider client query is similar to an SQL query, and it contains a 
+    set of columns to return, a set of selection criteria, and a sort order.
 </p>
 <p>
     The set of columns that the query should return is called a <strong>projection</strong>
@@ -448,9 +440,9 @@
 <p>
     The expression that specifies the rows to retrieve is split into a selection clause and
     selection arguments. The selection clause is a combination of logical and Boolean expressions,
-    column names, and values (the variable <code>mSelection</code>). If you specify the replaceable
-    parameter <code>?</code> instead of a value, the query method retrieves the value from the
-    selection arguments array (the variable <code>mSelectionArgs</code>).
+    column names, and values (the variable <code>mSelectionClause</code>). If you specify the 
+    replaceable parameter <code>?</code> instead of a value, the query method retrieves the value 
+    from the selection arguments array (the variable <code>mSelectionArgs</code>).
 </p>
 <p>
     In the next snippet, if the user doesn't enter a word, the selection clause is set to
@@ -517,7 +509,7 @@
     This query is analogous to the SQL statement:
 </p>
 <pre>
-SELECT _ID, word, frequency, locale FROM words WHERE word = &lt;userinput&gt; ORDER BY word ASC;
+SELECT _ID, word, locale FROM words WHERE word = &lt;userinput&gt; ORDER BY word ASC;
 </pre>
 <p>
     In this SQL statement, the actual column names are used instead of contract class constants.
@@ -575,16 +567,15 @@
 <!-- Displaying the results -->
 <h3 id="DisplayResults">Displaying query results</h3>
 <p>
-    The {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
-    ContentResolver.query()} client method always returns a {@link android.database.Cursor}
-    containing the columns specified by the query's projection for the rows that match the query's
-    selection criteria. A {@link android.database.Cursor} object provides random read access to the
-    rows and columns it contains. Using {@link android.database.Cursor} methods,
-    you can iterate over the rows in the results, determine the data type of each column, get the
-    data out of a column, and examine other properties of the results. Some
-    {@link android.database.Cursor} implementations automatically update the object when the
-    provider's data changes, or trigger methods in an observer object when the
-    {@link android.database.Cursor} changes, or both.
+    The {@link android.content.ContentResolver#query ContentResolver.query()} client method always 
+    returns a {@link android.database.Cursor} containing the columns specified by the query's 
+    projection for the rows that match the query's selection criteria. A 
+    {@link android.database.Cursor} object provides random read access to the rows and columns it 
+    contains. Using {@link android.database.Cursor} methods, you can iterate over the rows in the 
+    results, determine the data type of each column, get the data out of a column, and examine other
+    properties of the results. Some {@link android.database.Cursor} implementations automatically 
+    update the object when the provider's data changes, or trigger methods in an observer object 
+    when the {@link android.database.Cursor} changes, or both.
 </p>
 <p class="note">
     <strong>Note:</strong> A provider may restrict access to columns based on the nature of the
@@ -594,7 +585,7 @@
 <p>
     If no rows match the selection criteria, the provider
     returns a {@link android.database.Cursor} object for which
-    {@link android.database.Cursor#getCount() Cursor.getCount()} is 0 (an empty cursor).
+    {@link android.database.Cursor#getCount Cursor.getCount()} is 0 (an empty cursor).
 </p>
 <p>
     If an internal error occurs, the results of the query depend on the particular provider. It may
@@ -685,8 +676,8 @@
 <p>
     {@link android.database.Cursor} implementations contain several "get" methods for
     retrieving different types of data from the object. For example, the previous snippet
-    uses {@link android.database.Cursor#getString(int) getString()}. They also have a
-    {@link android.database.Cursor#getType(int) getType()} method that returns a value indicating
+    uses {@link android.database.Cursor#getString getString()}. They also have a
+    {@link android.database.Cursor#getType getType()} method that returns a value indicating
     the data type of the column.
 </p>
 
@@ -713,17 +704,16 @@
 </p>
 <p>
     To get the permissions needed to access a provider, an application requests them with a
-    <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">
-    &lt;uses-permission&gt;</a></code> element in its manifest file.
-    When the Android Package Manager installs the application, a user must approve all of the
-    permissions the application requests. If the user approves all of them, Package Manager
-    continues the installation; if the user doesn't approve them, Package Manager
+<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
+    element in its manifest file. When the Android Package Manager installs the application, a user 
+    must approve all of the permissions the application requests. If the user approves all of them, 
+    Package Manager continues the installation; if the user doesn't approve them, Package Manager
     aborts the installation.
 </p>
 <p>
     The following
-    <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">
-    &lt;uses-permission&gt;</a></code> element requests read access to the User Dictionary Provider:
+<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code> 
+    element requests read access to the User Dictionary Provider:
 </p>
 <pre>
     &lt;uses-permission android:name="android.permission.READ_USER_DICTIONARY"&gt;
@@ -746,7 +736,7 @@
 <h3 id="Inserting">Inserting data</h3>
 <p>
     To insert data into a provider, you call the
-    {@link android.content.ContentResolver#insert(Uri,ContentValues) ContentResolver.insert()}
+    {@link android.content.ContentResolver#insert ContentResolver.insert()}
     method. This method inserts a new row into the provider and returns a content URI for that row.
     This snippet shows how to insert a new word into the User Dictionary Provider:
 </p>
@@ -777,8 +767,7 @@
     The data for the new row goes into a single {@link android.content.ContentValues} object, which
     is similar in form to a one-row cursor. The columns in this object don't need to have the
     same data type, and if you don't want to specify a value at all, you can set a column
-    to <code>null</code> using {@link android.content.ContentValues#putNull(String)
-    ContentValues.putNull()}.
+    to <code>null</code> using {@link android.content.ContentValues#putNull ContentValues.putNull()}.
 </p>
 <p>
     The snippet doesn't add the <code>_ID</code> column, because this column is maintained
@@ -799,17 +788,16 @@
 </p>
 <p>
     To get the value of <code>_ID</code> from the returned {@link android.net.Uri}, call
-    {@link android.content.ContentUris#parseId(Uri) ContentUris.parseId()}.
+    {@link android.content.ContentUris#parseId ContentUris.parseId()}.
 </p>
 <h3 id="Updating">Updating data</h3>
 <p>
     To update a row, you use a {@link android.content.ContentValues} object with the updated
     values just as you do with an insertion, and selection criteria just as you do with a query.
     The client method you use is
-    {@link android.content.ContentResolver#update(Uri, ContentValues, String, String[])
-    ContentResolver.update()}. You only need to add values to the
-    {@link android.content.ContentValues} object for columns you're updating. If you want to clear
-    the contents of a column, set the value to <code>null</code>.
+    {@link android.content.ContentResolver#update ContentResolver.update()}. You only need to add 
+    values to the {@link android.content.ContentValues} object for columns you're updating. If you 
+    want to clear the contents of a column, set the value to <code>null</code>.
 </p>
 <p>
     The following snippet changes all the rows whose locale has the language "en" to a
@@ -842,9 +830,8 @@
 </pre>
 <p>
     You should also sanitize user input when you call
-    {@link android.content.ContentResolver#update(Uri, ContentValues, String, String[])
-    ContentResolver.update()}. To learn more about this, read the section
-    <a href="#Injection">Protecting against malicious input</a>.
+    {@link android.content.ContentResolver#update ContentResolver.update()}. To learn more about 
+    this, read the section <a href="#Injection">Protecting against malicious input</a>.
 </p>
 <h3 id="Deleting">Deleting data</h3>
 <p>
@@ -873,9 +860,8 @@
 </pre>
 <p>
     You should also sanitize user input when you call
-    {@link android.content.ContentResolver#delete(Uri, String, String[])
-    ContentResolver.delete()}. To learn more about this, read the section
-    <a href="#Injection">Protecting against malicious input</a>.
+    {@link android.content.ContentResolver#delete ContentResolver.delete()}. To learn more about 
+    this, read the section <a href="#Injection">Protecting against malicious input</a>.
 </p>
 <!-- Provider Data Types -->
 <h2 id="DataTypes">Provider Data Types</h2>
@@ -907,7 +893,7 @@
     The data types for the User Dictionary Provider are listed in the reference documentation
     for its contract class {@link android.provider.UserDictionary.Words} (contract classes are
     described in the section <a href="#ContractClasses">Contract Classes</a>).
-    You can also determine the data type by calling {@link android.database.Cursor#getType(int)
+    You can also determine the data type by calling {@link android.database.Cursor#getType
     Cursor.getType()}.
 </p>
 <p>
@@ -918,7 +904,7 @@
     data structures or files. For example, the {@link android.provider.ContactsContract.Data}
     table in the Contacts Provider uses MIME types to label the type of contact data stored in each
     row. To get the MIME type corresponding to a content URI, call
-    {@link android.content.ContentResolver#getType(Uri) ContentResolver.getType()}.
+    {@link android.content.ContentResolver#getType ContentResolver.getType()}.
 </p>
 <p>
     The section <a href="#MIMETypeReference">MIME Type Reference</a> describes the
@@ -935,8 +921,7 @@
     <li>
         <a href="#Batch">Batch access</a>: You can create a batch of access calls with methods in
         the {@link android.content.ContentProviderOperation} class, and then apply them with
-        {@link android.content.ContentResolver#applyBatch(String, ArrayList)
-        ContentResolver.applyBatch()}.
+        {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}.
     </li>
     <li>
         Asynchronous queries: You should do queries in a separate thread. One way to do this is to
@@ -963,11 +948,10 @@
     To access a provider in "batch mode",
     you create an array of {@link android.content.ContentProviderOperation} objects and then
     dispatch them to a content provider with
-    {@link android.content.ContentResolver#applyBatch(String, ArrayList)
-    ContentResolver.applyBatch()}. You pass the content provider's <em>authority</em> to this
-    method, rather than a particular content URI, which allows each
-    {@link android.content.ContentProviderOperation} object in the array to work against a
-    different table. A call to {@link android.content.ContentResolver#applyBatch(String, ArrayList)
+    {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}. You pass the 
+    content provider's <em>authority</em> to this  method, rather than a particular content URI. 
+    This allows each {@link android.content.ContentProviderOperation} object in the array to work 
+    against a different table. A call to {@link android.content.ContentResolver#applyBatch
     ContentResolver.applyBatch()} returns an array of results.
 </p>
 <p>
@@ -1028,14 +1012,13 @@
 </p>
 <p>
     A provider defines URI permissions for content URIs in its manifest, using the
-    <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">
-    android:grantUriPermission</a></code>
-    attribute of the <a href="{@docRoot}guide/topics/manifest/provider-element.html">
-    {@code &lt;provider&gt;}</a>
+<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">android:grantUriPermission</a></code>
+    attribute of the 
+<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>
     element, as well as the
-    <a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">{@code 
-    &lt;grant-uri-permission&gt;}</a> child element of the
-    <a href="{@docRoot}guide/topics/manifest/provider-element.html">{@code &lt;provider&gt;}</a>
+<code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></code>
+    child element of the
+<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>
     element. The URI permissions mechanism is explained in more detail in the
     <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a> guide,
     in the section "URI Permissions".
@@ -1053,7 +1036,7 @@
         Your application sends an intent containing the action
         {@link android.content.Intent#ACTION_PICK} and the "contacts" MIME type
         {@link android.provider.ContactsContract.RawContacts#CONTENT_ITEM_TYPE}, using the
-        method {@link android.app.Activity#startActivityForResult(Intent, int)
+        method {@link android.app.Activity#startActivityForResult
         startActivityForResult()}.
     </li>
     <li>
@@ -1063,7 +1046,7 @@
     <li>
         In the selection activity, the user selects a
         contact to update. When this happens, the selection activity calls
-        {@link android.app.Activity#setResult(int, Intent) setResult(resultcode, intent)}
+        {@link android.app.Activity#setResult setResult(resultcode, intent)}
         to set up a intent to give back to your application. The intent contains the content URI
         of the contact the user selected, and the "extras" flags
         {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION}. These flags grant URI
@@ -1073,7 +1056,7 @@
     </li>
     <li>
         Your activity returns to the foreground, and the system calls your activity's
-        {@link android.app.Activity#onActivityResult(int, int, Intent) onActivityResult()}
+        {@link android.app.Activity#onActivityResult onActivityResult()}
         method. This method receives the result intent created by the selection activity in
         the People app.
     </li>
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index cf2c03e..b311b7f 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -329,6 +329,39 @@
 indicates the current locale.</p>
       </td>
     </tr>
+    <tr id="LayoutDirectionQualifier">
+      <td>Layout Direction</td>
+      <td><code>ldrtl</code><br/>
+        <code>ldltr</code><br/>
+      </td>
+      <td><p>The layout direction of your application. {@code ldrtl} means "layout-direction-right-to-left".
+      {@code ldltr} means "layout-direction-left-to-right" and is the default implicit value.
+      </p>
+      <p>This can apply to any resource such as layouts, drawables, or values.
+      </p>
+      <p>For example, if you want to provide some specific layout for the Arabic language and some
+      generic layout for any other "right-to-left" language (like Persian or Hebrew) then you would have:
+      </p>
+<pre class="classic no-pretty-print">
+res/
+    layout/   <span style="color:black">
+        main.xml  </span>(Default layout)
+    layout-ar/  <span style="color:black">
+        main.xml  </span>(Specific layout for Arabic)
+    layout-ldrtl/  <span style="color:black">
+        main.xml  </span>(Any "right-to-left" language, except
+                  for Arabic, because the "ar" language qualifier
+                  has a higher precedence.)
+</pre>
+        <p class="note"><strong>Note:</strong> To enable right-to-left layout features
+        for your app, you must set <a
+        href="{@docRoot}guide/topics/manifest/application-element.html#supportsrtl">{@code
+        supportsRtl}</a> to {@code "true"} and set <a
+        href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target"
+        >{@code targetSdkVersion}</a> to 17 or higher.</p>
+        <p><em>Added in API level 17.</em></p>
+      </td>
+    </tr>
     <tr id="SmallestScreenWidthQualifier">
       <td>smallestWidth</td>
       <td><code>sw&lt;N&gt;dp</code><br/><br/>
diff --git a/docs/html/guide/topics/resources/string-resource.jd b/docs/html/guide/topics/resources/string-resource.jd
index 5f5484e..da410a4 100644
--- a/docs/html/guide/topics/resources/string-resource.jd
+++ b/docs/html/guide/topics/resources/string-resource.jd
@@ -13,8 +13,7 @@
   <dt><a href="#StringArray">String Array</a></dt>
     <dd>XML resource that provides an array of strings.</dd>
   <dt><a href="#Plurals">Quantity Strings (Plurals)</a></dt>
-    <dd>XML resource that carries different strings for different quantities
-    of the same word or phrase.</dd>
+    <dd>XML resource that carries different strings for pluralization.</dd>
 </dl>
 
 <p>All strings are capable of applying some styling markup and formatting arguments. For
@@ -231,10 +230,19 @@
 {@link android.content.res.Resources#getQuantityString(int,int) getQuantityString()} to select
 the appropriate resource for you.
 
-<p>Note that the selection is made based on grammatical necessity. A string for <code>zero</code>
-in English will be ignored even if the quantity is 0, because 0 isn't grammatically different
-from 2, or any other number except 1 ("zero books", "one book", "two books", and so on).
-Don't be misled either by the fact that, say, <code>two</code> sounds like it could only apply to
+<p>Although historically called "quantity strings" (and still called that in API), quantity
+strings should <i>only</i> be used for plurals. It would be a mistake to use quantity strings to
+implement something like Gmail's "Inbox" versus "Inbox (12)" when there are unread messages, for
+example. It might seem convenient to use quantity strings instead of an {@code if} statement,
+but it's important to note that some languages (such as Chinese) don't make these grammatical
+distinctions at all, so you'll always get the <code>other</code> string.
+
+<p>The selection of which string to use is made solely based on grammatical <i>necessity</i>.
+In English, a string for <code>zero</code> will be ignored even if the quantity is 0, because 0
+isn't grammatically different from 2, or any other number except 1 ("zero books", "one book",
+"two books", and so on).
+
+<p>Don't be misled either by the fact that, say, <code>two</code> sounds like it could only apply to
 the quantity 2: a language may require that 2, 12, 102 (and so on) are all treated like one
 another but differently to other quantities. Rely on your translator to know what distinctions
 their language actually insists upon.
@@ -313,7 +321,7 @@
               <td>{@code one}</td><td>When the language requires special treatment of numbers like one (as with the number 1 in English and most other languages; in Russian, any number ending in 1 but not ending in 11 is in this class).</td>
             </tr>
             <tr>
-              <td>{@code two}</td><td>When the language requires special treatment of numbers like two (as in Welsh).</td>
+              <td>{@code two}</td><td>When the language requires special treatment of numbers like two (as with 2 in Welsh, or 102 in Slovenian).</td>
             </tr>
             <tr>
               <td>{@code few}</td><td>When the language requires special treatment of "small" numbers (as with 2, 3, and 4 in Czech; or numbers ending 2, 3, or 4 but not 12, 13, or 14 in Polish).</td>
@@ -322,7 +330,7 @@
               <td>{@code many}</td><td>When the language requires special treatment of "large" numbers (as with numbers ending 11-99 in Maltese).</td>
             </tr>
             <tr>
-              <td>{@code other}</td><td>When the language does not require special treatment of the given quantity.</td>
+              <td>{@code other}</td><td>When the language does not require special treatment of the given quantity (as with all numbers in Chinese, or 42 in English).</td>
             </tr>
           </table>
         </dd>
diff --git a/docs/html/images/testing/UIAutomatorViewer.png b/docs/html/images/testing/UIAutomatorViewer.png
new file mode 100644
index 0000000..5a4aaa4
--- /dev/null
+++ b/docs/html/images/testing/UIAutomatorViewer.png
Binary files differ
diff --git a/docs/html/images/tools/dev-options-inmilk.png b/docs/html/images/tools/dev-options-inmilk.png
new file mode 100644
index 0000000..f0e323e
--- /dev/null
+++ b/docs/html/images/tools/dev-options-inmilk.png
Binary files differ
diff --git a/docs/html/tools/building/building-cmdline.jd b/docs/html/tools/building/building-cmdline.jd
index 6154d96..e0d0d3f 100644
--- a/docs/html/tools/building/building-cmdline.jd
+++ b/docs/html/tools/building/building-cmdline.jd
@@ -261,8 +261,18 @@
   device:</p>
 
   <ul>
-    <li>Enable USB Debugging on your device. You can find the setting on most Android devices by
-    going to <strong>Settings > Applications > Development > USB debugging</strong>.</li>
+    <li>Enable <strong>USB debugging</strong> on your device.
+      <ul>
+        <li>On most devices running Android 3.2 or older, you can find the option under
+          <strong>Settings > Applications > Development</strong>.</li>
+        <li>On Android 4.0 and newer, it's in <strong>Settings > Developer options</strong>.
+          <p class="note"><strong>Note:</strong> On Android 4.2 and newer, <strong>Developer
+          options</strong> is hidden by default. To make it available, go
+          to <strong>Settings > About phone</strong> and tap <strong>Build number</strong>
+          seven times. Return to the previous screen to find <strong>Developer options</strong>.</p>
+        </li>
+      </ul>
+    </li>
 
     <li>Ensure that your development computer can detect your device when connected via USB</li>
   </ul>
diff --git a/docs/html/tools/building/building-eclipse.jd b/docs/html/tools/building/building-eclipse.jd
index c73fe97..304aa7e 100644
--- a/docs/html/tools/building/building-eclipse.jd
+++ b/docs/html/tools/building/building-eclipse.jd
@@ -84,8 +84,18 @@
     <code>android:debuggable</code> attribute of the <code>&lt;application&gt;</code>
     element to <code>true</code>. As of ADT 8.0, this is done by default when you build in debug mode.</li>
 
-    <li>Enable USB Debugging on your device. You can find the setting on most Android devices by
-    going to <strong>Settings > Applications > Development > USB debugging</strong>.</li>
+    <li>Enable <strong>USB debugging</strong> on your device.
+      <ul>
+        <li>On most devices running Android 3.2 or older, you can find the option under
+          <strong>Settings > Applications > Development</strong>.</li>
+        <li>On Android 4.0 and newer, it's in <strong>Settings > Developer options</strong>.
+          <p class="note"><strong>Note:</strong> On Android 4.2 and newer, <strong>Developer
+          options</strong> is hidden by default. To make it available, go
+          to <strong>Settings > About phone</strong> and tap <strong>Build number</strong>
+          seven times. Return to the previous screen to find <strong>Developer options</strong>.</p>
+        </li>
+      </ul>
+    </li>
 
     <li>Ensure that your development computer can detect your device when connected via USB</li>
   </ul>
diff --git a/docs/html/tools/device.jd b/docs/html/tools/device.jd
index d5fd581..61cd08a 100644
--- a/docs/html/tools/device.jd
+++ b/docs/html/tools/device.jd
@@ -58,11 +58,17 @@
     <p class="note"><strong>Note:</strong> If you manually enable debugging in the manifest
  file, be sure to disable it before you build for release (your published application
 should usually <em>not</em> be debuggable).</p></li>
-  <li>Turn on "USB Debugging" on your device.
-    <p>On the device, go to <strong>Settings > Applications > Development</strong> 
-    and enable <strong>USB debugging</strong> 
-    (on an Android 4.0 device, the setting is 
-located in <strong>Settings > Developer options</strong>).</p>
+  <li>Enable <strong>USB debugging</strong> on your device.
+    <ul>
+      <li>On most devices running Android 3.2 or older, you can find the option under
+        <strong>Settings > Applications > Development</strong>.</li>
+      <li>On Android 4.0 and newer, it's in <strong>Settings > Developer options</strong>.
+        <p class="note"><strong>Note:</strong> On Android 4.2 and newer, <strong>Developer
+        options</strong> is hidden by default. To make it available, go
+        to <strong>Settings > About phone</strong> and tap <strong>Build number</strong>
+        seven times. Return to the previous screen to find <strong>Developer options</strong>.</p>
+      </li>
+    </ul>
   </li>
   <li>Set up your system to detect your device.
     <ul>
diff --git a/docs/html/tools/help/android.jd b/docs/html/tools/help/android.jd
index 282c791..19891e8 100644
--- a/docs/html/tools/help/android.jd
+++ b/docs/html/tools/help/android.jd
@@ -280,7 +280,7 @@
     </tr>
 
     <tr>
-      <td rowspan="3"><code>create-test-project</code></td>
+      <td rowspan="3"><code>create test-project</code></td>
 
       <td><code>-n &lt;name&gt;</code></td>
 
@@ -306,7 +306,7 @@
     </tr>
 
     <tr>
-      <td rowspan="2"><code>update-test-project</code></td>
+      <td rowspan="2"><code>update test-project</code></td>
 
       <td><code>-p &lt;path&gt;</code></td>
 
@@ -324,7 +324,7 @@
     </tr>
 
     <tr>
-      <td rowspan="4"><code>create-lib-project</code></td>
+      <td rowspan="4"><code>create lib-project</code></td>
 
       <td><code>-k &lt;packageName&gt;</code></td>
 
@@ -358,7 +358,7 @@
     </tr>
 
     <tr>
-      <td rowspan="3"><code>update-lib-project</code></td>
+      <td rowspan="3"><code>update lib-project</code></td>
 
       <td><code>-p &lt;path&gt;</code></td>
 
@@ -382,6 +382,30 @@
 
       <td></td>
     </tr>
+
+    <tr>
+      <td rowspan="3"><code>create uitest-project</code></td>
+      <td><code>-n &lt;name&gt;</code></td>
+      <td>The name of the UI test project</td>
+      <td></td>
+    </tr>
+
+    <tr>
+      <td><code>-t &lt;name&gt;</code></td>
+
+      <td>Target ID of the UI test project</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td><code>-p &lt;path&gt;</code></td>
+
+      <td>Location path of the UI test project</td>
+
+      <td>Required</td>
+    </tr>
+
   </table>
 
   <h3>Update actions</h3>
diff --git a/docs/html/tools/help/uiautomator/IAutomationSupport.jd b/docs/html/tools/help/uiautomator/IAutomationSupport.jd
new file mode 100644
index 0000000..4120f2b
--- /dev/null
+++ b/docs/html/tools/help/uiautomator/IAutomationSupport.jd
@@ -0,0 +1,168 @@
+page.title=IAutomationSupport
+parent.title=uiautomator
+parent.link=index.html
+@jd:body
+<style>
+    h4.jd-details-title {background-color: #DEE8F1;}
+</style>
+
+<h2>Class Overview</h2>
+<p>Provides auxiliary support for running test cases
+
+</p>
+
+
+
+
+
+</div><!-- jd-descr -->
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<div class="jd-descr">
+
+
+<h2>Summary</h2>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="pubmethods" class="jd-sumtable"><tr><th colspan="12">Public Methods</th></tr>
+
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            abstract
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#sendStatus(int, android.os.Bundle)">sendStatus</a></span>(int resultCode, Bundle status)
+        
+        <div class="jd-descrdiv">Allows the running test cases to send out interim status</div>
+  
+  </td></tr>
+
+
+
+</table>
+
+
+
+
+
+
+
+</div><!-- jd-descr (summary) -->
+
+<!-- Details -->
+
+
+
+
+
+
+
+
+<!-- XML Attributes -->
+
+
+<!-- Enum Values -->
+
+
+<!-- Constants -->
+
+
+<!-- Fields -->
+
+
+<!-- Public ctors -->
+
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+<!-- Protected ctors -->
+
+
+
+<!-- ========= METHOD DETAIL ======== -->
+<!-- Public methdos -->
+
+<h2>Public Methods</h2>
+
+
+
+<a id="sendStatus(int, android.os.Bundle)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+        abstract 
+         
+        void
+      </span>
+      <span class="sympad">sendStatus</span>
+      <span class="normal">(int resultCode, Bundle status)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Allows the running test cases to send out interim status</p></div>
+
+    </div>
+</div>
+
+
+
diff --git a/docs/html/tools/help/uiautomator/UiAutomatorTestCase.jd b/docs/html/tools/help/uiautomator/UiAutomatorTestCase.jd
new file mode 100644
index 0000000..48c63ba
--- /dev/null
+++ b/docs/html/tools/help/uiautomator/UiAutomatorTestCase.jd
@@ -0,0 +1,1402 @@
+page.title=UiAutomatorTestCase
+parent.title=uiautomator
+parent.link=index.html
+@jd:body
+<style>
+    h4.jd-details-title {background-color: #DEE8F1;}
+</style>
+<h2>Class Overview</h2>
+<p>UI automation tests should extend this class. This class provides access
+ to the following:
+<ul>
+<li><code><a href="UiDevice.html">UiDevice</a></code> instance</li>
+<li>Bundle for command line parameters</li>
+</ul>
+</p>
+
+
+
+
+
+</div><!-- jd-descr -->
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<div class="jd-descr">
+
+
+<h2>Summary</h2>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+<table id="pubctors" class="jd-sumtable"><tr><th colspan="12">Public Constructors</th></tr>
+
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#UiAutomatorTestCase()">UiAutomatorTestCase</a></span>()
+        
+  </td></tr>
+
+
+
+</table>
+
+
+
+
+
+
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="pubmethods" class="jd-sumtable"><tr><th colspan="12">Public Methods</th></tr>
+
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="IAutomationSupport.html">IAutomationSupport</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getAutomationSupport()">getAutomationSupport</a></span>()
+        
+        <div class="jd-descrdiv">Provides support for running tests to report interim status</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            Bundle
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getParams()">getParams</a></span>()
+        
+        <div class="jd-descrdiv">Get command line parameters.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiDevice.html">UiDevice</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getUiDevice()">getUiDevice</a></span>()
+        
+        <div class="jd-descrdiv">Get current instance of <code><a href="UiDevice.html">UiDevice</a></code>.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#sleep(long)">sleep</a></span>(long ms)
+        
+        <div class="jd-descrdiv">Calls <code><a href="null#sleep(long)">sleep(long)</a></code> to sleep</div>
+  
+  </td></tr>
+
+
+
+</table>
+
+
+
+
+
+
+
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="inhmethods" class="jd-sumtable"><tr><th>
+  <a href="#" class="toggle-all" onclick="return toggleAllInherited(this, null)">[Expand]</a>
+  <div style="clear:left;">Inherited Methods</div></th></tr>
+
+
+<tr class="api apilevel-" >
+<td colspan="12">
+  <a href="#" onclick="return toggleInherited(this, null)" id="inherited-methods-junit.framework.TestCase" class="jd-expando-trigger closed"
+          ><img id="inherited-methods-junit.framework.TestCase-trigger"
+          src="../../../../../assets/images/triangle-closed.png"
+          class="jd-expando-trigger-img" /></a>
+From class
+
+  junit.framework.TestCase
+
+<div id="inherited-methods-junit.framework.TestCase">
+  <div id="inherited-methods-junit.framework.TestCase-list"
+        class="jd-inheritedlinks">
+  </div>
+  <div id="inherited-methods-junit.framework.TestCase-summary" style="display: none;">
+    <table class="jd-sumtable-expando">
+    
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">countTestCases</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">getName</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            TestResult
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">run</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">run</span>(TestResult arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">runBare</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">setName</span>(String arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">toString</span>()
+        
+  </td></tr>
+
+
+</table>
+  </div>
+</div>
+</td></tr>
+
+
+
+<tr class="api apilevel-" >
+<td colspan="12">
+  <a href="#" onclick="return toggleInherited(this, null)" id="inherited-methods-junit.framework.Assert" class="jd-expando-trigger closed"
+          ><img id="inherited-methods-junit.framework.Assert-trigger"
+          src="../../../../../assets/images/triangle-closed.png"
+          class="jd-expando-trigger-img" /></a>
+From class
+
+  junit.framework.Assert
+
+<div id="inherited-methods-junit.framework.Assert">
+  <div id="inherited-methods-junit.framework.Assert-list"
+        class="jd-inheritedlinks">
+  </div>
+  <div id="inherited-methods-junit.framework.Assert-summary" style="display: none;">
+    <table class="jd-sumtable-expando">
+    
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(short arg0, short arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(String arg0, int arg1, int arg2)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(String arg0, short arg1, short arg2)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(char arg0, char arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(String arg0, String arg1, String arg2)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(int arg0, int arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(String arg0, double arg1, double arg2, double arg3)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(String arg0, long arg1, long arg2)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(byte arg0, byte arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(Object arg0, Object arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(boolean arg0, boolean arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(String arg0, float arg1, float arg2, float arg3)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(String arg0, boolean arg1, boolean arg2)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(String arg0, String arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(float arg0, float arg1, float arg2)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(String arg0, byte arg1, byte arg2)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(double arg0, double arg1, double arg2)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(String arg0, char arg1, char arg2)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(String arg0, Object arg1, Object arg2)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertEquals</span>(long arg0, long arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertFalse</span>(String arg0, boolean arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertFalse</span>(boolean arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertNotNull</span>(String arg0, Object arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertNotNull</span>(Object arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertNotSame</span>(Object arg0, Object arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertNotSame</span>(String arg0, Object arg1, Object arg2)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertNull</span>(Object arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertNull</span>(String arg0, Object arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertSame</span>(Object arg0, Object arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertSame</span>(String arg0, Object arg1, Object arg2)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertTrue</span>(String arg0, boolean arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">assertTrue</span>(boolean arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">fail</span>(String arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">fail</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">failNotEquals</span>(String arg0, Object arg1, Object arg2)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">failNotSame</span>(String arg0, Object arg1, Object arg2)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">failSame</span>(String arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">format</span>(String arg0, Object arg1, Object arg2)
+        
+  </td></tr>
+
+
+</table>
+  </div>
+</div>
+</td></tr>
+
+
+
+<tr class="api apilevel-" >
+<td colspan="12">
+  <a href="#" onclick="return toggleInherited(this, null)" id="inherited-methods-java.lang.Object" class="jd-expando-trigger closed"
+          ><img id="inherited-methods-java.lang.Object-trigger"
+          src="../../../../../assets/images/triangle-closed.png"
+          class="jd-expando-trigger-img" /></a>
+From class
+
+  java.lang.Object
+
+<div id="inherited-methods-java.lang.Object">
+  <div id="inherited-methods-java.lang.Object-list"
+        class="jd-inheritedlinks">
+  </div>
+  <div id="inherited-methods-java.lang.Object-summary" style="display: none;">
+    <table class="jd-sumtable-expando">
+    
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">equals</span>(Object arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            Class&lt;?&gt;
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">getClass</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">hashCode</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">notify</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">notifyAll</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">toString</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>(long arg0, int arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>(long arg0)
+        
+  </td></tr>
+
+
+</table>
+  </div>
+</div>
+</td></tr>
+
+
+
+<tr class="api apilevel-" >
+<td colspan="12">
+  <a href="#" onclick="return toggleInherited(this, null)" id="inherited-methods-junit.framework.Test" class="jd-expando-trigger closed"
+          ><img id="inherited-methods-junit.framework.Test-trigger"
+          src="../../../../../assets/images/triangle-closed.png"
+          class="jd-expando-trigger-img" /></a>
+From interface
+
+  junit.framework.Test
+
+<div id="inherited-methods-junit.framework.Test">
+  <div id="inherited-methods-junit.framework.Test-list"
+        class="jd-inheritedlinks">
+  </div>
+  <div id="inherited-methods-junit.framework.Test-summary" style="display: none;">
+    <table class="jd-sumtable-expando">
+    
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            abstract
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">countTestCases</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            abstract
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">run</span>(TestResult arg0)
+        
+  </td></tr>
+
+
+</table>
+  </div>
+</div>
+</td></tr>
+
+
+</table>
+
+
+</div><!-- jd-descr (summary) -->
+
+<!-- Details -->
+
+
+
+
+
+
+
+
+<!-- XML Attributes -->
+
+
+<!-- Enum Values -->
+
+
+<!-- Constants -->
+
+
+<!-- Fields -->
+
+
+<!-- Public ctors -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+<h2>Public Constructors</h2>
+
+
+
+<a id="UiAutomatorTestCase()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        
+      </span>
+      <span class="sympad">UiAutomatorTestCase</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+    </div>
+</div>
+
+
+
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+<!-- Protected ctors -->
+
+
+
+<!-- ========= METHOD DETAIL ======== -->
+<!-- Public methdos -->
+
+<h2>Public Methods</h2>
+
+
+
+<a id="getAutomationSupport()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="IAutomationSupport.html">IAutomationSupport</a>
+      </span>
+      <span class="sympad">getAutomationSupport</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Provides support for running tests to report interim status</p></div>
+
+    </div>
+</div>
+
+
+<a id="getParams()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        Bundle
+      </span>
+      <span class="sympad">getParams</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Get command line parameters. On the command line when passing <code>-e key value</code>
+ pairs, the Bundle will have the key value pairs conveniently available to the
+ tests.
+</p></div>
+
+    </div>
+</div>
+
+
+<a id="getUiDevice()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiDevice.html">UiDevice</a>
+      </span>
+      <span class="sympad">getUiDevice</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Get current instance of <code><a href="UiDevice.html">UiDevice</a></code>. Works similar to calling the static
+ <code><a href="UiDevice.html#getInstance()">getInstance()</a></code> from anywhere in the test classes.
+</p></div>
+
+    </div>
+</div>
+
+
+<a id="sleep(long)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">sleep</span>
+      <span class="normal">(long ms)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Calls <code><a href="null#sleep(long)">sleep(long)</a></code> to sleep</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>ms</th>
+          <td>is in milliseconds.
+</td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
diff --git a/docs/html/tools/help/uiautomator/UiCollection.jd b/docs/html/tools/help/uiautomator/UiCollection.jd
new file mode 100644
index 0000000..ed92ca7
--- /dev/null
+++ b/docs/html/tools/help/uiautomator/UiCollection.jd
@@ -0,0 +1,1271 @@
+page.title=UiCollection
+parent.title=uiautomator
+parent.link=index.html
+@jd:body
+<style>
+    h4.jd-details-title {background-color: #DEE8F1;}
+</style>
+<p>Used to enumerate a container's user interface (UI) elements for the purpose of counting,
+ or targeting a sub elements by a child's text or description.
+</p>
+
+<div class="jd-descr">
+
+
+<h2>Summary</h2>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+<table id="pubctors" class="jd-sumtable"><tr><th colspan="12">Public Constructors</th></tr>
+
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#UiCollection(com.android.uiautomator.core.UiSelector)">UiCollection</a></span>(<a href="UiSelector.html">UiSelector</a> selector)
+        
+  </td></tr>
+
+
+
+</table>
+
+
+
+
+
+
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="pubmethods" class="jd-sumtable"><tr><th colspan="12">Public Methods</th></tr>
+
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getChildByDescription(com.android.uiautomator.core.UiSelector, java.lang.String)">getChildByDescription</a></span>(<a href="UiSelector.html">UiSelector</a> childPattern, String text)
+        
+        <div class="jd-descrdiv">Searches for child UI element within the constraints of this  <code><a href="UiSelector.html">UiSelector</a></code>
+ selector.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getChildByInstance(com.android.uiautomator.core.UiSelector, int)">getChildByInstance</a></span>(<a href="UiSelector.html">UiSelector</a> childPattern, int instance)
+        
+        <div class="jd-descrdiv">Searches for child UI element within the constraints of this  <code><a href="UiSelector.html">UiSelector</a></code>.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getChildByText(com.android.uiautomator.core.UiSelector, java.lang.String)">getChildByText</a></span>(<a href="UiSelector.html">UiSelector</a> childPattern, String text)
+        
+        <div class="jd-descrdiv">Searches for child UI element within the constraints of this  <code><a href="UiSelector.html">UiSelector</a></code>.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getChildCount(com.android.uiautomator.core.UiSelector)">getChildCount</a></span>(<a href="UiSelector.html">UiSelector</a> childPattern)
+        
+        <div class="jd-descrdiv">Counts child UI element instances matching the <code>childPattern</code>
+ argument.</div>
+  
+  </td></tr>
+
+
+
+</table>
+
+
+
+
+
+
+
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="inhmethods" class="jd-sumtable"><tr><th>
+  <a href="#" class="toggle-all" onclick="return toggleAllInherited(this, null)">[Expand]</a>
+  <div style="clear:left;">Inherited Methods</div></th></tr>
+
+
+<tr class="api apilevel-" >
+<td colspan="12">
+  <a href="#" onclick="return toggleInherited(this, null)" id="inherited-methods-com.android.uiautomator.core.UiObject" class="jd-expando-trigger closed"
+          ><img id="inherited-methods-com.android.uiautomator.core.UiObject-trigger"
+          src="../../../../../assets/images/triangle-closed.png"
+          class="jd-expando-trigger-img" /></a>
+From class
+
+  <a href="UiObject.html">com.android.uiautomator.core.UiObject</a>
+
+<div id="inherited-methods-com.android.uiautomator.core.UiObject">
+  <div id="inherited-methods-com.android.uiautomator.core.UiObject-list"
+        class="jd-inheritedlinks">
+  </div>
+  <div id="inherited-methods-com.android.uiautomator.core.UiObject-summary" style="display: none;">
+    <table class="jd-sumtable-expando">
+    
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#clearTextField()">clearTextField</a></span>()
+        
+        <div class="jd-descrdiv">Clears the existing text contents in an editable field.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#click()">click</a></span>()
+        
+        <div class="jd-descrdiv">Performs a click at the center of the visible bounds of the UI element represented
+ by this UiObject.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#clickAndWaitForNewWindow(long)">clickAndWaitForNewWindow</a></span>(long timeout)
+        
+        <div class="jd-descrdiv">Performs a click at the center of the visible bounds of the UI element represented
+ by this UiObject and waits for window transitions.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#clickAndWaitForNewWindow()">clickAndWaitForNewWindow</a></span>()
+        
+        <div class="jd-descrdiv">See <code><a href="UiObject.html#clickAndWaitForNewWindow(long)">clickAndWaitForNewWindow(long)</a></code>
+ This method is intended to reliably wait for window transitions that would typically take
+ longer than the usual default timeouts.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#clickBottomRight()">clickBottomRight</a></span>()
+        
+        <div class="jd-descrdiv">Clicks the bottom and right corner of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#clickTopLeft()">clickTopLeft</a></span>()
+        
+        <div class="jd-descrdiv">Clicks the top and left corner of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#exists()">exists</a></span>()
+        
+        <div class="jd-descrdiv">Check if UI element exists.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            Rect
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getBounds()">getBounds</a></span>()
+        
+        <div class="jd-descrdiv">Returns the UI element's <code>bounds</code> property.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getChild(com.android.uiautomator.core.UiSelector)">getChild</a></span>(<a href="UiSelector.html">UiSelector</a> selector)
+        
+        <div class="jd-descrdiv">Creates a new UiObject representing a child UI element of the element currently represented
+ by this UiObject.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getChildCount()">getChildCount</a></span>()
+        
+        <div class="jd-descrdiv">Counts the child UI elements immediately under the UI element currently represented by
+ this UiObject.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getContentDescription()">getContentDescription</a></span>()
+        
+        <div class="jd-descrdiv">Reads the <code>content_desc</code> property of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getFromParent(com.android.uiautomator.core.UiSelector)">getFromParent</a></span>(<a href="UiSelector.html">UiSelector</a> selector)
+        
+        <div class="jd-descrdiv">Creates a new UiObject representing a child UI element from the parent element currently
+ represented by this object.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getPackageName()">getPackageName</a></span>()
+        
+        <div class="jd-descrdiv">Reads the UI element's <code>package</code> property</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getSelector()">getSelector</a></span>()
+        
+        <div class="jd-descrdiv">Debugging helper.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getText()">getText</a></span>()
+        
+        <div class="jd-descrdiv">Reads the <code>text</code> property of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            Rect
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getVisibleBounds()">getVisibleBounds</a></span>()
+        
+        <div class="jd-descrdiv">Returns the visible bounds of the UI element.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isCheckable()">isCheckable</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>checkable</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isChecked()">isChecked</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>checked</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isClickable()">isClickable</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>clickable</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isEnabled()">isEnabled</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>enabled</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isFocusable()">isFocusable</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>focusable</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isFocused()">isFocused</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>focused</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isLongClickable()">isLongClickable</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>long-clickable</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isScrollable()">isScrollable</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>scrollable</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isSelected()">isSelected</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>selected</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#longClick()">longClick</a></span>()
+        
+        <div class="jd-descrdiv">Long clicks the center of the visible bounds of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#longClickBottomRight()">longClickBottomRight</a></span>()
+        
+        <div class="jd-descrdiv">Long clicks bottom and right corner of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#longClickTopLeft()">longClickTopLeft</a></span>()
+        
+        <div class="jd-descrdiv">Long clicks on the top and left corner of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#setText(java.lang.String)">setText</a></span>(String text)
+        
+        <div class="jd-descrdiv">Sets the text in an editable field, after clearing the field's content.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#swipeDown(int)">swipeDown</a></span>(int steps)
+        
+        <div class="jd-descrdiv">Perform the action on the UI element that is represented by this object, Also see
+ #scrollToBeginning(int), #scrollToEnd(int), #scrollBackward(),
+ #scrollForward().</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#swipeLeft(int)">swipeLeft</a></span>(int steps)
+        
+        <div class="jd-descrdiv">Perform the action on the UI element that is represented by this object.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#swipeRight(int)">swipeRight</a></span>(int steps)
+        
+        <div class="jd-descrdiv">Perform the action on the UI element that is represented by this object.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#swipeUp(int)">swipeUp</a></span>(int steps)
+        
+        <div class="jd-descrdiv">Perform the action on the UI element that is represented by this UiObject.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#waitForExists(long)">waitForExists</a></span>(long timeout)
+        
+        <div class="jd-descrdiv">Waits a specified length of time for a UI element to become visible.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#waitUntilGone(long)">waitUntilGone</a></span>(long timeout)
+        
+        <div class="jd-descrdiv">Waits a specified length of time for a UI element to become undetectable.</div>
+  
+  </td></tr>
+
+
+</table>
+  </div>
+</div>
+</td></tr>
+
+
+
+<tr class="api apilevel-" >
+<td colspan="12">
+  <a href="#" onclick="return toggleInherited(this, null)" id="inherited-methods-java.lang.Object" class="jd-expando-trigger closed"
+          ><img id="inherited-methods-java.lang.Object-trigger"
+          src="../../../../../assets/images/triangle-closed.png"
+          class="jd-expando-trigger-img" /></a>
+From class
+
+  java.lang.Object
+
+<div id="inherited-methods-java.lang.Object">
+  <div id="inherited-methods-java.lang.Object-list"
+        class="jd-inheritedlinks">
+  </div>
+  <div id="inherited-methods-java.lang.Object-summary" style="display: none;">
+    <table class="jd-sumtable-expando">
+    
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">equals</span>(Object arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            Class&lt;?&gt;
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">getClass</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">hashCode</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">notify</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">notifyAll</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">toString</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>(long arg0, int arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>(long arg0)
+        
+  </td></tr>
+
+
+</table>
+  </div>
+</div>
+</td></tr>
+
+
+</table>
+
+
+</div><!-- jd-descr (summary) -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+<h2>Public Constructors</h2>
+
+
+<a id="UiCollection(com.android.uiautomator.core.UiSelector)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        
+      </span>
+      <span class="sympad">UiCollection</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> selector)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+    </div>
+</div>
+
+
+
+<!-- ========= METHOD DETAIL ======== -->
+<!-- Public methdos -->
+
+<h2>Public Methods</h2>
+
+
+<a id="getChildByDescription(com.android.uiautomator.core.UiSelector, java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiObject.html">UiObject</a>
+      </span>
+      <span class="sympad">getChildByDescription</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> childPattern, String text)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Searches for child UI element within the constraints of this <code><a href="UiSelector.html">UiSelector</a></code>
+ selector.
+
+ It looks for any child matching the <code>childPattern</code> argument that has
+ a child UI element anywhere within its sub hierarchy that has content-description text.
+ The returned UiObject will point at the <code>childPattern</code> instance that matched the
+ search and not at the identifying child element that matched the content description.</p></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>childPattern</th>
+          <td><code><a href="UiSelector.html">UiSelector</a></code> selector of the child pattern to match and return</td>
+        </tr>
+        <tr>
+          <th>text</th>
+          <td>String of the identifying child contents of of the <code>childPattern</code></td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li><code><a href="UiObject.html">UiObject</a></code> pointing at and instance of <code>childPattern</code></li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getChildByInstance(com.android.uiautomator.core.UiSelector, int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiObject.html">UiObject</a>
+      </span>
+      <span class="sympad">getChildByInstance</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> childPattern, int instance)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Searches for child UI element within the constraints of this <code><a href="UiSelector.html">UiSelector</a></code>.
+
+ It looks for any child matching the <code>childPattern</code> argument that has
+ a child UI element anywhere within its sub hierarchy that is at the <code>instance</code>
+ specified. The operation is performed only on the visible items and no scrolling is performed
+ in this case.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>childPattern</th>
+          <td><code><a href="UiSelector.html">UiSelector</a></code> selector of the child pattern to match and return</td>
+        </tr>
+        <tr>
+          <th>instance</th>
+          <td>int the desired matched instance of this <code>childPattern</code></td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li><code><a href="UiObject.html">UiObject</a></code> pointing at and instance of <code>childPattern</code>
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getChildByText(com.android.uiautomator.core.UiSelector, java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiObject.html">UiObject</a>
+      </span>
+      <span class="sympad">getChildByText</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> childPattern, String text)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Searches for child UI element within the constraints of this <code><a href="UiSelector.html">UiSelector</a></code>
+ selector.
+
+ It looks for any child matching the <code>childPattern</code> argument that has
+ a child UI element anywhere within its sub hierarchy that has a text attribute equal to 
+ <code>text</code>. The returned UiObject will point at the <code>childPattern</code>
+ instance that matched the search and not at the identifying child element that matched the
+ text attribute.</p></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>childPattern</th>
+          <td><code><a href="UiSelector.html">UiSelector</a></code> selector of the child pattern to match and return</td>
+        </tr>
+        <tr>
+          <th>text</th>
+          <td>String of the identifying child contents of of the <code>childPattern</code></td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li><code><a href="UiObject.html">UiObject</a></code> pointing at and instance of <code>childPattern</code></li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getChildCount(com.android.uiautomator.core.UiSelector)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        int
+      </span>
+      <span class="sympad">getChildCount</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> childPattern)</span>
+    </h4>
+      <div class="api-level">
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Counts child UI element instances matching the <code>childPattern</code>
+ argument. The method returns the number of matching UI elements that are
+ currently visible.  The count does not include items of a scrollable list
+ that are off-screen.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>childPattern</th>
+          <td>a <code><a href="UiSelector.html">UiSelector</a></code> that represents the matching child UI
+ elements to count</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>the number of matched childPattern under the current <code><a href="UiCollection.html">UiCollection</a></code>
+</li></ul>
+  </div>
+
+    </div>
+</div>
+
diff --git a/docs/html/tools/help/uiautomator/UiDevice.jd b/docs/html/tools/help/uiautomator/UiDevice.jd
new file mode 100644
index 0000000..0c0c7d9
--- /dev/null
+++ b/docs/html/tools/help/uiautomator/UiDevice.jd
@@ -0,0 +1,3058 @@
+page.title=UiDevice
+parent.title=uiautomator
+parent.link=index.html
+@jd:body
+<style>
+    h4.jd-details-title {background-color: #DEE8F1;}
+</style>
+
+<h2>Class Overview</h2>
+<p>UiDevice provides access to state information about the device.
+ You can also use this class to simulate user actions on the device,
+ such as pressing the d-pad or pressing the Home and Menu buttons.</p>
+
+
+
+
+
+</div><!-- jd-descr -->
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<div class="jd-descr">
+
+
+<h2>Summary</h2>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="pubmethods" class="jd-sumtable"><tr><th colspan="12">Public Methods</th></tr>
+
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#clearLastTraversedText()">clearLastTraversedText</a></span>()
+        
+        <div class="jd-descrdiv">Clears the text from the last UI traversal event.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#click(int, int)">click</a></span>(int x, int y)
+        
+        <div class="jd-descrdiv">Perform a click at arbitrary coordinates specified by the user</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#dumpWindowHierarchy(java.lang.String)">dumpWindowHierarchy</a></span>(String fileName)
+        
+        <div class="jd-descrdiv">Helper method used for debugging to dump the current window's layout hierarchy.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#freezeRotation()">freezeRotation</a></span>()
+        
+        <div class="jd-descrdiv">Disables the sensors and freezes the device rotation at its
+ current rotation state.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getCurrentActivityName()">getCurrentActivityName</a></span>()
+        
+        <div class="jd-descrdiv">
+      <em>
+  This method is deprecated.
+      The results returned should be considered unreliable</em></div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getCurrentPackageName()">getCurrentPackageName</a></span>()
+        
+        <div class="jd-descrdiv">Retrieves the name of the last package to report accessibility events.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getDisplayHeight()">getDisplayHeight</a></span>()
+        
+        <div class="jd-descrdiv">Gets the height of the display, in pixels.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getDisplayRotation()">getDisplayRotation</a></span>()
+        
+        <div class="jd-descrdiv">Returns the current rotation of the display, as defined in Surface@return</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getDisplayWidth()">getDisplayWidth</a></span>()
+        
+        <div class="jd-descrdiv">Gets the width of the display, in pixels.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            static
+            
+            <a href="UiDevice.html">UiDevice</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getInstance()">getInstance</a></span>()
+        
+        <div class="jd-descrdiv">Retrieves a singleton instance of UiDevice</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getLastTraversedText()">getLastTraversedText</a></span>()
+        
+        <div class="jd-descrdiv">Retrieves the text from the last UI traversal event received.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getProductName()">getProductName</a></span>()
+        
+        <div class="jd-descrdiv">Retrieves the product name of the device.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#hasAnyWatcherTriggered()">hasAnyWatcherTriggered</a></span>()
+        
+        <div class="jd-descrdiv">Checks if any registered <code><a href="UiWatcher.html">UiWatcher</a></code> have triggered.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#hasWatcherTriggered(java.lang.String)">hasWatcherTriggered</a></span>(String watcherName)
+        
+        <div class="jd-descrdiv">Checks if a specific registered  <code><a href="UiWatcher.html">UiWatcher</a></code> has triggered.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#isNaturalOrientation()">isNaturalOrientation</a></span>()
+        
+        <div class="jd-descrdiv">Check if the device is in its natural orientation.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#isScreenOn()">isScreenOn</a></span>()
+        
+        <div class="jd-descrdiv">Checks the power manager if the screen is ON.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#pressBack()">pressBack</a></span>()
+        
+        <div class="jd-descrdiv">Simulates a short press on the BACK button.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#pressDPadCenter()">pressDPadCenter</a></span>()
+        
+        <div class="jd-descrdiv">Simulates a short press on the CENTER button.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#pressDPadDown()">pressDPadDown</a></span>()
+        
+        <div class="jd-descrdiv">Simulates a short press on the DOWN button.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#pressDPadLeft()">pressDPadLeft</a></span>()
+        
+        <div class="jd-descrdiv">Simulates a short press on the LEFT button.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#pressDPadRight()">pressDPadRight</a></span>()
+        
+        <div class="jd-descrdiv">Simulates a short press on the RIGHT button.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#pressDPadUp()">pressDPadUp</a></span>()
+        
+        <div class="jd-descrdiv">Simulates a short press on the UP button.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#pressDelete()">pressDelete</a></span>()
+        
+        <div class="jd-descrdiv">Simulates a short press on the DELETE key.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#pressEnter()">pressEnter</a></span>()
+        
+        <div class="jd-descrdiv">Simulates a short press on the ENTER key.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#pressHome()">pressHome</a></span>()
+        
+        <div class="jd-descrdiv">Simulates a short press on the HOME button.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#pressKeyCode(int)">pressKeyCode</a></span>(int keyCode)
+        
+        <div class="jd-descrdiv">Simulates a short press using a key code.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#pressKeyCode(int, int)">pressKeyCode</a></span>(int keyCode, int metaState)
+        
+        <div class="jd-descrdiv">Simulates a short press using a key code.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#pressMenu()">pressMenu</a></span>()
+        
+        <div class="jd-descrdiv">Simulates a short press on the MENU button.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#pressRecentApps()">pressRecentApps</a></span>()
+        
+        <div class="jd-descrdiv">Simulates a short press on the Recent Apps button.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#pressSearch()">pressSearch</a></span>()
+        
+        <div class="jd-descrdiv">Simulates a short press on the SEARCH button.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#registerWatcher(java.lang.String, com.android.uiautomator.core.UiWatcher)">registerWatcher</a></span>(String name, <a href="UiWatcher.html">UiWatcher</a> watcher)
+        
+        <div class="jd-descrdiv">Registers a <code><a href="UiWatcher.html">UiWatcher</a></code> to run automatically when the testing framework is unable to
+ find a match using a <code><a href="UiSelector.html">UiSelector</a></code>.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#removeWatcher(java.lang.String)">removeWatcher</a></span>(String name)
+        
+        <div class="jd-descrdiv">Removes a previously registered <code><a href="UiWatcher.html">UiWatcher</a></code>.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#resetWatcherTriggers()">resetWatcherTriggers</a></span>()
+        
+        <div class="jd-descrdiv">Resets a <code><a href="UiWatcher.html">UiWatcher</a></code> that has been triggered.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#runWatchers()">runWatchers</a></span>()
+        
+        <div class="jd-descrdiv">This method forces all registered watchers to run.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#setOrientationLeft()">setOrientationLeft</a></span>()
+        
+        <div class="jd-descrdiv">Simulates orienting the device to the left and also freezes rotation
+ by disabling the sensors.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#setOrientationNatural()">setOrientationNatural</a></span>()
+        
+        <div class="jd-descrdiv">Simulates orienting the device into its natural orientation and also freezes rotation
+ by disabling the sensors.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#setOrientationRight()">setOrientationRight</a></span>()
+        
+        <div class="jd-descrdiv">Simulates orienting the device to the right and also freezes rotation
+ by disabling the sensors.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#sleep()">sleep</a></span>()
+        
+        <div class="jd-descrdiv">This method simply presses the power button if the screen is ON else
+ it does nothing if the screen is already OFF.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#swipe(android.graphics.Point[], int)">swipe</a></span>(Point[] segments, int segmentSteps)
+        
+        <div class="jd-descrdiv">Performs a swipe between points in the Point array.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#swipe(int, int, int, int, int)">swipe</a></span>(int startX, int startY, int endX, int endY, int steps)
+        
+        <div class="jd-descrdiv">Performs a swipe from one coordinate to another using the number of steps
+ to determine smoothness and speed.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#takeScreenshot(java.io.File, float, int)">takeScreenshot</a></span>(File storePath, float scale, int quality)
+        
+        <div class="jd-descrdiv">Take a screenshot of current window and store it as PNG
+
+ The screenshot is adjusted per screen rotation</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#takeScreenshot(java.io.File)">takeScreenshot</a></span>(File storePath)
+        
+        <div class="jd-descrdiv">Take a screenshot of current window and store it as PNG
+
+ Default scale of 1.0f (original size) and 90% quality is used
+ The screenshot is adjusted per screen rotation</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#unfreezeRotation()">unfreezeRotation</a></span>()
+        
+        <div class="jd-descrdiv">Re-enables the sensors and un-freezes the device rotation allowing its contents
+ to rotate with the device physical rotation.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#waitForIdle(long)">waitForIdle</a></span>(long time)
+        
+        <div class="jd-descrdiv">Waits for the current application to idle.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#waitForIdle()">waitForIdle</a></span>()
+        
+        <div class="jd-descrdiv">Waits for the current application to idle.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#waitForWindowUpdate(java.lang.String, long)">waitForWindowUpdate</a></span>(String packageName, long timeout)
+        
+        <div class="jd-descrdiv">Waits for a window content update event to occur.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#wakeUp()">wakeUp</a></span>()
+        
+        <div class="jd-descrdiv">This method simulates pressing the power button if the screen is OFF else
+ it does nothing if the screen is already ON.</div>
+  
+  </td></tr>
+
+
+
+</table>
+
+
+
+
+
+
+
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="inhmethods" class="jd-sumtable"><tr><th>
+  <a href="#" class="toggle-all" onclick="return toggleAllInherited(this, null)">[Expand]</a>
+  <div style="clear:left;">Inherited Methods</div></th></tr>
+
+
+<tr class="api apilevel-" >
+<td colspan="12">
+  <a href="#" onclick="return toggleInherited(this, null)" id="inherited-methods-java.lang.Object" class="jd-expando-trigger closed"
+          ><img id="inherited-methods-java.lang.Object-trigger"
+          src="../../../../../assets/images/triangle-closed.png"
+          class="jd-expando-trigger-img" /></a>
+From class
+
+  java.lang.Object
+
+<div id="inherited-methods-java.lang.Object">
+  <div id="inherited-methods-java.lang.Object-list"
+        class="jd-inheritedlinks">
+  </div>
+  <div id="inherited-methods-java.lang.Object-summary" style="display: none;">
+    <table class="jd-sumtable-expando">
+    
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">equals</span>(Object arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            Class&lt;?&gt;
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">getClass</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">hashCode</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">notify</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">notifyAll</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">toString</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>(long arg0, int arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>(long arg0)
+        
+  </td></tr>
+
+
+</table>
+  </div>
+</div>
+</td></tr>
+
+
+</table>
+
+
+</div><!-- jd-descr (summary) -->
+
+<!-- Details -->
+
+
+
+
+
+
+
+
+<!-- XML Attributes -->
+
+
+<!-- Enum Values -->
+
+
+<!-- Constants -->
+
+
+<!-- Fields -->
+
+
+<!-- Public ctors -->
+
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+<!-- Protected ctors -->
+
+
+
+<!-- ========= METHOD DETAIL ======== -->
+<!-- Public methdos -->
+
+<h2>Public Methods</h2>
+
+
+
+<a id="clearLastTraversedText()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">clearLastTraversedText</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Clears the text from the last UI traversal event.
+ See <code><a href="#getLastTraversedText()">getLastTraversedText()</a></code>.</p></div>
+
+    </div>
+</div>
+
+
+<a id="click(int, int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">click</span>
+      <span class="normal">(int x, int y)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Perform a click at arbitrary coordinates specified by the user</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>x</th>
+          <td>coordinate</td>
+        </tr>
+        <tr>
+          <th>y</th>
+          <td>coordinate</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if the click succeeded else false</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="dumpWindowHierarchy(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">dumpWindowHierarchy</span>
+      <span class="normal">(String fileName)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Helper method used for debugging to dump the current window's layout hierarchy.
+ The file root location is /data/local/tmp</p></div>
+
+    </div>
+</div>
+
+
+<a id="freezeRotation()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">freezeRotation</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Disables the sensors and freezes the device rotation at its
+ current rotation state.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th></td>
+            <td>RemoteException</td>
+        </tr>  
+        <tr>
+            <th>RemoteException</td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getCurrentActivityName()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        String
+      </span>
+      <span class="sympad">getCurrentActivityName</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      <p>
+  <p class="caution">
+      <strong>
+  This method is deprecated.</strong><br/> The results returned should be considered unreliable
+  </p>
+  <div class="jd-tagdata jd-tagdescr"><p>Retrieves the last activity to report accessibility events.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>String name of activity</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getCurrentPackageName()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        String
+      </span>
+      <span class="sympad">getCurrentPackageName</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Retrieves the name of the last package to report accessibility events.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>String name of package</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getDisplayHeight()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        int
+      </span>
+      <span class="sympad">getDisplayHeight</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Gets the height of the display, in pixels. The size is adjusted based
+ on the current orientation of the display.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>height in pixels or zero on failure</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getDisplayRotation()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        int
+      </span>
+      <span class="sympad">getDisplayRotation</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Returns the current rotation of the display, as defined in Surface@return</p></div>
+  <div class="jd-tagdata">
+  <h5 class="jd-tagtitle">Since</h5>
+  <ul class="nolist"><li>Android API Level 17</li></ul>
+</div>
+    </div>
+</div>
+
+
+<a id="getDisplayWidth()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        int
+      </span>
+      <span class="sympad">getDisplayWidth</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Gets the width of the display, in pixels. The width and height details
+ are reported based on the current orientation of the display.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>width in pixels or zero on failure</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getInstance()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        static 
+         
+         
+         
+        <a href="UiDevice.html">UiDevice</a>
+      </span>
+      <span class="sympad">getInstance</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Retrieves a singleton instance of UiDevice</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiDevice instance</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getLastTraversedText()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        String
+      </span>
+      <span class="sympad">getLastTraversedText</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Retrieves the text from the last UI traversal event received.
+
+ You can use this method to read the contents in a WebView container
+ because the accessibility framework fires events
+ as each text is highlighted. You can write a test to perform
+ directional arrow presses to focus on different elements inside a WebView,
+ and call this method to get the text from each traversed element.
+ If you are testing a view container that can return a reference to a
+ Document Object Model (DOM) object, your test should use the view's
+ DOM instead.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>text of the last traversal event, else return an empty string</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getProductName()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        String
+      </span>
+      <span class="sympad">getProductName</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Retrieves the product name of the device.
+
+ This method provides information on what type of device the test is running on. This value is
+ the same as returned by invoking #adb shell getprop ro.product.name.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>product name of the device</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="hasAnyWatcherTriggered()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">hasAnyWatcherTriggered</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Checks if any registered <code><a href="UiWatcher.html">UiWatcher</a></code> have triggered.
+
+ See <code><a href="#registerWatcher(java.lang.String, com.android.uiautomator.core.UiWatcher)">registerWatcher(String, UiWatcher)</a></code>
+ See <code><a href="#hasWatcherTriggered(java.lang.String)">hasWatcherTriggered(String)</a></code></p></div>
+
+    </div>
+</div>
+
+
+<a id="hasWatcherTriggered(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">hasWatcherTriggered</span>
+      <span class="normal">(String watcherName)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Checks if a specific registered  <code><a href="UiWatcher.html">UiWatcher</a></code> has triggered.
+ See <code><a href="#registerWatcher(java.lang.String, com.android.uiautomator.core.UiWatcher)">registerWatcher(String, UiWatcher)</a></code>. If a UiWatcher runs and its
+ <code><a href="UiWatcher.html#checkForCondition()">checkForCondition()</a></code> call returned <code>true</code>, then
+ the UiWatcher is considered triggered. This is helpful if a watcher is detecting errors
+ from ANR or crash dialogs and the test needs to know if a UiWatcher has been triggered.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if triggered else false</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="isNaturalOrientation()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">isNaturalOrientation</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Check if the device is in its natural orientation. This is determined by checking if the
+ orientation is at 0 or 180 degrees.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if it is in natural orientation</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="isScreenOn()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">isScreenOn</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Checks the power manager if the screen is ON.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if the screen is ON else false</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th></td>
+            <td>RemoteException</td>
+        </tr>  
+        <tr>
+            <th>RemoteException</td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="pressBack()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">pressBack</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates a short press on the BACK button.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful, else return false</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="pressDPadCenter()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">pressDPadCenter</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates a short press on the CENTER button.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful, else return false</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="pressDPadDown()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">pressDPadDown</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates a short press on the DOWN button.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful, else return false</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="pressDPadLeft()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">pressDPadLeft</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates a short press on the LEFT button.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful, else return false</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="pressDPadRight()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">pressDPadRight</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates a short press on the RIGHT button.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful, else return false</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="pressDPadUp()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">pressDPadUp</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates a short press on the UP button.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful, else return false</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="pressDelete()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">pressDelete</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates a short press on the DELETE key.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful, else return false</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="pressEnter()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">pressEnter</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates a short press on the ENTER key.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful, else return false</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="pressHome()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">pressHome</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates a short press on the HOME button.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful, else return false</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="pressKeyCode(int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">pressKeyCode</span>
+      <span class="normal">(int keyCode)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates a short press using a key code.
+
+ See KeyEvent</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful, else return false</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="pressKeyCode(int, int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">pressKeyCode</span>
+      <span class="normal">(int keyCode, int metaState)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates a short press using a key code.
+
+ See KeyEvent.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>keyCode</th>
+          <td>the key code of the event.</td>
+        </tr>
+        <tr>
+          <th>metaState</th>
+          <td>an integer in which each bit set to 1 represents a pressed meta key</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful, else return false</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="pressMenu()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">pressMenu</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates a short press on the MENU button.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful, else return false</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="pressRecentApps()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">pressRecentApps</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates a short press on the Recent Apps button.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful, else return false</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th></td>
+            <td>RemoteException</td>
+        </tr>  
+        <tr>
+            <th>RemoteException</td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="pressSearch()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">pressSearch</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates a short press on the SEARCH button.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful, else return false</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="registerWatcher(java.lang.String, com.android.uiautomator.core.UiWatcher)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">registerWatcher</span>
+      <span class="normal">(String name, <a href="UiWatcher.html">UiWatcher</a> watcher)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Registers a <code><a href="UiWatcher.html">UiWatcher</a></code> to run automatically when the testing framework is unable to
+ find a match using a <code><a href="UiSelector.html">UiSelector</a></code>. See <code><a href="#runWatchers()">runWatchers()</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>name</th>
+          <td>to register the UiWatcher</td>
+        </tr>
+        <tr>
+          <th>watcher</th>
+          <td><code><a href="UiWatcher.html">UiWatcher</a></code></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="removeWatcher(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">removeWatcher</span>
+      <span class="normal">(String name)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Removes a previously registered <code><a href="UiWatcher.html">UiWatcher</a></code>.
+
+ See <code><a href="#registerWatcher(java.lang.String, com.android.uiautomator.core.UiWatcher)">registerWatcher(String, UiWatcher)</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>name</th>
+          <td>used to register the UiWatcher</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th></td>
+            <td>UiAutomationException</td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="resetWatcherTriggers()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">resetWatcherTriggers</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Resets a <code><a href="UiWatcher.html">UiWatcher</a></code> that has been triggered.
+ If a UiWatcher runs and its <code><a href="UiWatcher.html#checkForCondition()">checkForCondition()</a></code> call
+ returned <code>true</code>, then the UiWatcher is considered triggered.
+ See <code><a href="#registerWatcher(java.lang.String, com.android.uiautomator.core.UiWatcher)">registerWatcher(String, UiWatcher)</a></code></p></div>
+
+    </div>
+</div>
+
+
+<a id="runWatchers()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">runWatchers</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>This method forces all registered watchers to run.
+ See <code><a href="#registerWatcher(java.lang.String, com.android.uiautomator.core.UiWatcher)">registerWatcher(String, UiWatcher)</a></code></p></div>
+
+    </div>
+</div>
+
+
+<a id="setOrientationLeft()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">setOrientationLeft</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates orienting the device to the left and also freezes rotation
+ by disabling the sensors.
+
+ If you want to un-freeze the rotation and re-enable the sensors
+ see <code><a href="#unfreezeRotation()">unfreezeRotation()</a></code>.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th></td>
+            <td>RemoteException</td>
+        </tr>  
+        <tr>
+            <th>RemoteException</td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="setOrientationNatural()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">setOrientationNatural</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates orienting the device into its natural orientation and also freezes rotation
+ by disabling the sensors.
+
+ If you want to un-freeze the rotation and re-enable the sensors
+ see <code><a href="#unfreezeRotation()">unfreezeRotation()</a></code>.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th></td>
+            <td>RemoteException</td>
+        </tr>  
+        <tr>
+            <th>RemoteException</td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="setOrientationRight()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">setOrientationRight</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Simulates orienting the device to the right and also freezes rotation
+ by disabling the sensors.
+
+ If you want to un-freeze the rotation and re-enable the sensors
+ see <code><a href="#unfreezeRotation()">unfreezeRotation()</a></code>.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th></td>
+            <td>RemoteException</td>
+        </tr>  
+        <tr>
+            <th>RemoteException</td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="sleep()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">sleep</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>This method simply presses the power button if the screen is ON else
+ it does nothing if the screen is already OFF.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th></td>
+            <td>RemoteException</td>
+        </tr>  
+        <tr>
+            <th>RemoteException</td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="swipe(android.graphics.Point[], int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">swipe</span>
+      <span class="normal">(Point[] segments, int segmentSteps)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Performs a swipe between points in the Point array. Each step execution is throttled
+ to 5ms per step. So for a 100 steps, the swipe will take about 1/2 second to complete</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>segments</th>
+          <td>is Point array containing at least one Point object</td>
+        </tr>
+        <tr>
+          <th>segmentSteps</th>
+          <td>steps to inject between two Points</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true on success</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="swipe(int, int, int, int, int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">swipe</span>
+      <span class="normal">(int startX, int startY, int endX, int endY, int steps)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Performs a swipe from one coordinate to another using the number of steps
+ to determine smoothness and speed. Each step execution is throttled to 5ms
+ per step. So for a 100 steps, the swipe will take about 1/2 second to complete.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>steps</th>
+          <td>is the number of move steps sent to the system</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>false if the operation fails or the coordinates are invalid</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="takeScreenshot(java.io.File, float, int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">takeScreenshot</span>
+      <span class="normal">(File storePath, float scale, int quality)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Take a screenshot of current window and store it as PNG
+
+ The screenshot is adjusted per screen rotation</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>storePath</th>
+          <td>where the PNG should be written to</td>
+        </tr>
+        <tr>
+          <th>scale</th>
+          <td>scale the screenshot down if needed; 1.0f for original size</td>
+        </tr>
+        <tr>
+          <th>quality</th>
+          <td>quality of the PNG compression; range: 0-100</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if screen shot is created successfully, false otherwise</li></ul>
+  </div>
+  <div class="jd-tagdata">
+  <h5 class="jd-tagtitle">Since</h5>
+  <ul class="nolist"><li>Android API Level 17</li></ul>
+</div>
+    </div>
+</div>
+
+
+<a id="takeScreenshot(java.io.File)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">takeScreenshot</span>
+      <span class="normal">(File storePath)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Take a screenshot of current window and store it as PNG
+
+ Default scale of 1.0f (original size) and 90% quality is used
+ The screenshot is adjusted per screen rotation</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>storePath</th>
+          <td>where the PNG should be written to</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if screen shot is created successfully, false otherwise</li></ul>
+  </div>
+  <div class="jd-tagdata">
+  <h5 class="jd-tagtitle">Since</h5>
+  <ul class="nolist"><li>Android API Level 17</li></ul>
+</div>
+    </div>
+</div>
+
+
+<a id="unfreezeRotation()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">unfreezeRotation</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Re-enables the sensors and un-freezes the device rotation allowing its contents
+ to rotate with the device physical rotation. During a test execution, it is best to
+ keep the device frozen in a specific orientation until the test case execution has completed.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th>RemoteException</td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="waitForIdle(long)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">waitForIdle</span>
+      <span class="normal">(long time)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Waits for the current application to idle.</p></div>
+
+    </div>
+</div>
+
+
+<a id="waitForIdle()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">waitForIdle</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Waits for the current application to idle.
+ Default wait timeout is 10 seconds</p></div>
+
+    </div>
+</div>
+
+
+<a id="waitForWindowUpdate(java.lang.String, long)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">waitForWindowUpdate</span>
+      <span class="normal">(String packageName, long timeout)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Waits for a window content update event to occur.
+
+ If a package name for the window is specified, but the current window
+ does not have the same package name, the function returns immediately.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>packageName</th>
+          <td>the specified window package name (can be <code>null</code>).
+        If <code>null</code>, a window update from any front-end window will end the wait</td>
+        </tr>
+        <tr>
+          <th>timeout</th>
+          <td>the timeout for the wait</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if a window update occurred, false if timeout has elapsed or if the current
+         window does not have the specified package name</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="wakeUp()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">wakeUp</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>This method simulates pressing the power button if the screen is OFF else
+ it does nothing if the screen is already ON.
+
+ If the screen was OFF and it just got turned ON, this method will insert a 500ms delay
+ to allow the device time to wake up and accept input.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th></td>
+            <td>RemoteException</td>
+        </tr>  
+        <tr>
+            <th>RemoteException</td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+
+
+
+<!-- ========= METHOD DETAIL ======== -->
+
+
+
+<!-- ========= END OF CLASS DATA ========= -->
+
diff --git a/docs/html/tools/help/uiautomator/UiObject.jd b/docs/html/tools/help/uiautomator/UiObject.jd
new file mode 100644
index 0000000..799ac82
--- /dev/null
+++ b/docs/html/tools/help/uiautomator/UiObject.jd
@@ -0,0 +1,2684 @@
+page.title=UiObject
+parent.title=uiautomator
+parent.link=index.html
+@jd:body
+<style>
+    h4.jd-details-title {background-color: #DEE8F1;}
+</style>
+<p>A UiObject is a representation of a user interface (UI) element. It is not in any way directly bound to a
+ UI element as an object reference. A UiObject holds information to help it
+ locate a matching UI element at runtime based on the <code><a href="UiSelector.html">UiSelector</a></code> properties specified in
+ its constructor. Since a UiObject is a representative for a UI element, it can
+ be reused for different views with matching UI elements.
+</p>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<div class="jd-descr">
+
+
+<h2>Summary</h2>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+<table id="pubctors" class="jd-sumtable"><tr><th colspan="12">Public Constructors</th></tr>
+
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#UiObject(com.android.uiautomator.core.UiSelector)">UiObject</a></span>(<a href="UiSelector.html">UiSelector</a> selector)
+        
+        <div class="jd-descrdiv">Constructs a UiObject to represent a specific UI element matched by the specified
+ <code><a href="UiSelector.html">UiSelector</a></code> selector properties.</div>
+  
+  </td></tr>
+
+
+
+</table>
+
+
+
+
+
+
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="pubmethods" class="jd-sumtable"><tr><th colspan="12">Public Methods</th></tr>
+
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#clearTextField()">clearTextField</a></span>()
+        
+        <div class="jd-descrdiv">Clears the existing text contents in an editable field.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#click()">click</a></span>()
+        
+        <div class="jd-descrdiv">Performs a click at the center of the visible bounds of the UI element represented
+ by this UiObject.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#clickAndWaitForNewWindow(long)">clickAndWaitForNewWindow</a></span>(long timeout)
+        
+        <div class="jd-descrdiv">Performs a click at the center of the visible bounds of the UI element represented
+ by this UiObject and waits for window transitions.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#clickAndWaitForNewWindow()">clickAndWaitForNewWindow</a></span>()
+        
+        <div class="jd-descrdiv">See <code><a href="#clickAndWaitForNewWindow(long)">clickAndWaitForNewWindow(long)</a></code>
+ This method is intended to reliably wait for window transitions that would typically take
+ longer than the usual default timeouts.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#clickBottomRight()">clickBottomRight</a></span>()
+        
+        <div class="jd-descrdiv">Clicks the bottom and right corner of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#clickTopLeft()">clickTopLeft</a></span>()
+        
+        <div class="jd-descrdiv">Clicks the top and left corner of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#exists()">exists</a></span>()
+        
+        <div class="jd-descrdiv">Check if UI element exists.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            Rect
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getBounds()">getBounds</a></span>()
+        
+        <div class="jd-descrdiv">Returns the UI element's <code>bounds</code> property.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getChild(com.android.uiautomator.core.UiSelector)">getChild</a></span>(<a href="UiSelector.html">UiSelector</a> selector)
+        
+        <div class="jd-descrdiv">Creates a new UiObject representing a child UI element of the element currently represented
+ by this UiObject.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getChildCount()">getChildCount</a></span>()
+        
+        <div class="jd-descrdiv">Counts the child UI elements immediately under the UI element currently represented by
+ this UiObject.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getContentDescription()">getContentDescription</a></span>()
+        
+        <div class="jd-descrdiv">Reads the <code>content_desc</code> property of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getFromParent(com.android.uiautomator.core.UiSelector)">getFromParent</a></span>(<a href="UiSelector.html">UiSelector</a> selector)
+        
+        <div class="jd-descrdiv">Creates a new UiObject representing a child UI element from the parent element currently
+ represented by this object.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getPackageName()">getPackageName</a></span>()
+        
+        <div class="jd-descrdiv">Reads the UI element's <code>package</code> property</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getSelector()">getSelector</a></span>()
+        
+        <div class="jd-descrdiv">Debugging helper.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getText()">getText</a></span>()
+        
+        <div class="jd-descrdiv">Reads the <code>text</code> property of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            Rect
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getVisibleBounds()">getVisibleBounds</a></span>()
+        
+        <div class="jd-descrdiv">Returns the visible bounds of the UI element.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#isCheckable()">isCheckable</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>checkable</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#isChecked()">isChecked</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>checked</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#isClickable()">isClickable</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>clickable</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#isEnabled()">isEnabled</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>enabled</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#isFocusable()">isFocusable</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>focusable</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#isFocused()">isFocused</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>focused</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#isLongClickable()">isLongClickable</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>long-clickable</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#isScrollable()">isScrollable</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>scrollable</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#isSelected()">isSelected</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>selected</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#longClick()">longClick</a></span>()
+        
+        <div class="jd-descrdiv">Long clicks the center of the visible bounds of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#longClickBottomRight()">longClickBottomRight</a></span>()
+        
+        <div class="jd-descrdiv">Long clicks bottom and right corner of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#longClickTopLeft()">longClickTopLeft</a></span>()
+        
+        <div class="jd-descrdiv">Long clicks on the top and left corner of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#setText(java.lang.String)">setText</a></span>(String text)
+        
+        <div class="jd-descrdiv">Sets the text in an editable field, after clearing the field's content.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#swipeDown(int)">swipeDown</a></span>(int steps)
+        
+        <div class="jd-descrdiv">Perform the action on the UI element that is represented by this object, Also see
+ #scrollToBeginning(int), #scrollToEnd(int), #scrollBackward(),
+ #scrollForward().</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#swipeLeft(int)">swipeLeft</a></span>(int steps)
+        
+        <div class="jd-descrdiv">Perform the action on the UI element that is represented by this object.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#swipeRight(int)">swipeRight</a></span>(int steps)
+        
+        <div class="jd-descrdiv">Perform the action on the UI element that is represented by this object.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#swipeUp(int)">swipeUp</a></span>(int steps)
+        
+        <div class="jd-descrdiv">Perform the action on the UI element that is represented by this UiObject.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#waitForExists(long)">waitForExists</a></span>(long timeout)
+        
+        <div class="jd-descrdiv">Waits a specified length of time for a UI element to become visible.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#waitUntilGone(long)">waitUntilGone</a></span>(long timeout)
+        
+        <div class="jd-descrdiv">Waits a specified length of time for a UI element to become undetectable.</div>
+  
+  </td></tr>
+
+
+
+</table>
+
+
+
+
+
+
+
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="inhmethods" class="jd-sumtable"><tr><th>
+  <a href="#" class="toggle-all" onclick="return toggleAllInherited(this, null)">[Expand]</a>
+  <div style="clear:left;">Inherited Methods</div></th></tr>
+
+
+<tr class="api apilevel-" >
+<td colspan="12">
+  <a href="#" onclick="return toggleInherited(this, null)" id="inherited-methods-java.lang.Object" class="jd-expando-trigger closed"
+          ><img id="inherited-methods-java.lang.Object-trigger"
+          src="../../../../../assets/images/triangle-closed.png"
+          class="jd-expando-trigger-img" /></a>
+From class
+
+  java.lang.Object
+
+<div id="inherited-methods-java.lang.Object">
+  <div id="inherited-methods-java.lang.Object-list"
+        class="jd-inheritedlinks">
+  </div>
+  <div id="inherited-methods-java.lang.Object-summary" style="display: none;">
+    <table class="jd-sumtable-expando">
+    
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">equals</span>(Object arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            Class&lt;?&gt;
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">getClass</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">hashCode</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">notify</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">notifyAll</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">toString</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>(long arg0, int arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>(long arg0)
+        
+  </td></tr>
+
+
+</table>
+  </div>
+</div>
+</td></tr>
+
+
+</table>
+
+
+</div><!-- jd-descr (summary) -->
+
+<!-- Details -->
+
+
+
+
+
+
+
+
+<!-- XML Attributes -->
+
+
+<!-- Enum Values -->
+
+
+<!-- Constants -->
+
+
+<!-- Fields -->
+
+
+<!-- Public ctors -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+<h2>Public Constructors</h2>
+
+
+
+<a id="UiObject(com.android.uiautomator.core.UiSelector)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        
+      </span>
+      <span class="sympad">UiObject</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> selector)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Constructs a UiObject to represent a specific UI element matched by the specified
+ <code><a href="UiSelector.html">UiSelector</a></code> selector properties.</p></div>
+
+    </div>
+</div>
+
+
+
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+<!-- Protected ctors -->
+
+
+
+<!-- ========= METHOD DETAIL ======== -->
+<!-- Public methdos -->
+
+<h2>Public Methods</h2>
+
+
+
+<a id="clearTextField()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">clearTextField</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Clears the existing text contents in an editable field.
+
+ The <code><a href="UiSelector.html">UiSelector</a></code> of this object must reference a UI element that is editable.
+
+ When you call this method, the method first sets focus at the start edge of the field.
+ The method then simulates a long-press to select the existing text, and deletes the
+ selected text.
+
+ If a "Select-All" option is displayed, the method will automatically attempt to use it
+ to ensure full text selection.
+
+ Note that it is possible that not all the text in the field is selected; for example,
+ if the text contains separators such as spaces, slashes, at symbol etc.
+ Also, not all editable fields support the long-press functionality.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="click()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">click</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Performs a click at the center of the visible bounds of the UI element represented
+ by this UiObject.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true id successful else false</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="clickAndWaitForNewWindow(long)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">clickAndWaitForNewWindow</span>
+      <span class="normal">(long timeout)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Performs a click at the center of the visible bounds of the UI element represented
+ by this UiObject and waits for window transitions.
+
+ This method differ from <code><a href="#click()">click()</a></code> only in that this method waits for a
+ a new window transition as a result of the click. Some examples of a window transition:
+ <li>launching a new activity</li>
+ <li>bringing up a pop-up menu</li>
+ <li>bringing up a dialog</li></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>timeout</th>
+          <td>timeout before giving up on waiting for a new window</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if the event was triggered, else false</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="clickAndWaitForNewWindow()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">clickAndWaitForNewWindow</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>See <code><a href="#clickAndWaitForNewWindow(long)">clickAndWaitForNewWindow(long)</a></code>
+ This method is intended to reliably wait for window transitions that would typically take
+ longer than the usual default timeouts.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if the event was triggered, else false</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="clickBottomRight()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">clickBottomRight</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Clicks the bottom and right corner of the UI element</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true on success</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th>Exception</td>
+            <td></td>
+        </tr>  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="clickTopLeft()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">clickTopLeft</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Clicks the top and left corner of the UI element</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true on success</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th>Exception</td>
+            <td></td>
+        </tr>  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="exists()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">exists</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Check if UI element exists.
+
+ This methods performs a <code><a href="#waitForExists(long)">waitForExists(long)</a></code> with zero timeout. This
+ basically returns immediately whether the UI element represented by this UiObject
+ exists or not. If you need to wait longer for this UI element, then see
+ <code><a href="#waitForExists(long)">waitForExists(long)</a></code>.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if the UI element represented by this UiObject does exist
+</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getBounds()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        Rect
+      </span>
+      <span class="sympad">getBounds</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Returns the UI element's <code>bounds</code> property. See <code><a href="#getVisibleBounds()">getVisibleBounds()</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>Rect</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getChild(com.android.uiautomator.core.UiSelector)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiObject.html">UiObject</a>
+      </span>
+      <span class="sympad">getChild</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> selector)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Creates a new UiObject representing a child UI element of the element currently represented
+ by this UiObject.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>selector</th>
+          <td>for UI element to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>a new UiObject representing the matched UI element
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getChildCount()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        int
+      </span>
+      <span class="sympad">getChildCount</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Counts the child UI elements immediately under the UI element currently represented by
+ this UiObject.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>the count of child UI elements.</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getContentDescription()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        String
+      </span>
+      <span class="sympad">getContentDescription</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Reads the <code>content_desc</code> property of the UI element</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>value of node attribute "content_desc"</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getFromParent(com.android.uiautomator.core.UiSelector)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiObject.html">UiObject</a>
+      </span>
+      <span class="sympad">getFromParent</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> selector)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Creates a new UiObject representing a child UI element from the parent element currently
+ represented by this object. Essentially this is starting the search from the parent
+ element and can also be used to find sibling UI elements to the one currently represented
+ by this UiObject.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>selector</th>
+          <td>for the UI element to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>a new UiObject representing the matched UI element</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getPackageName()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        String
+      </span>
+      <span class="sympad">getPackageName</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Reads the UI element's <code>package</code> property</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if it is else false</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getSelector()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+        final 
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">getSelector</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Debugging helper. A test can dump the properties of a selector as a string
+ to its logs if needed. <code>getSelector().toString();</code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li><code><a href="UiSelector.html">UiSelector</a></code>
+</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getText()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        String
+      </span>
+      <span class="sympad">getText</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Reads the <code>text</code> property of the UI element</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>text value of the current node represented by this UiObject</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td>if no match could be found
+</td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getVisibleBounds()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        Rect
+      </span>
+      <span class="sympad">getVisibleBounds</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Returns the visible bounds of the UI element.
+
+ If a portion of the UI element is visible, only the bounds of the visible portion are
+ reported.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>Rect</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th></td>
+            <td>UiObjectNotFoundException</td>
+        </tr>  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+    </div>
+</div>
+
+
+<a id="isCheckable()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">isCheckable</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Check if the UI element's <code>checkable</code> property is currently true</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if it is else false</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="isChecked()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">isChecked</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Check if the UI element's <code>checked</code> property is currently true</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if it is else false
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="isClickable()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">isClickable</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Check if the UI element's <code>clickable</code> property is currently true</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if it is else false</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="isEnabled()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">isEnabled</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Check if the UI element's <code>enabled</code> property is currently true</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if it is else false</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="isFocusable()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">isFocusable</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Check if the UI element's <code>focusable</code> property is currently true</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if it is else false</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="isFocused()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">isFocused</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Check if the UI element's <code>focused</code> property is currently true</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if it is else false</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="isLongClickable()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">isLongClickable</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Check if the UI element's <code>long-clickable</code> property is currently true</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if it is else false</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="isScrollable()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">isScrollable</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Check if the UI element's <code>scrollable</code> property is currently true</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if it is else false</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="isSelected()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">isSelected</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Check if the UI element's <code>selected</code> property is currently true</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if it is else false</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="longClick()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">longClick</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Long clicks the center of the visible bounds of the UI element</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if operation was successful</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="longClickBottomRight()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">longClickBottomRight</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Long clicks bottom and right corner of the UI element</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if operation was successful</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="longClickTopLeft()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">longClickTopLeft</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Long clicks on the top and left corner of the UI element</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if operation was successful</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="setText(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">setText</span>
+      <span class="normal">(String text)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Sets the text in an editable field, after clearing the field's content.
+
+ The <code><a href="UiSelector.html">UiSelector</a></code> selector of this object must reference a UI element that is editable.
+
+ When you call this method, the method first simulates a <code><a href="#click()">click()</a></code> on
+ editable field to set focus. The method then clears the field's contents
+ and injects your specified text into the field.
+
+ If you want to capture the original contents of the field, call <code><a href="#getText()">getText()</a></code> first.
+ You can then modify the text and use this method to update the field.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>text</th>
+          <td>string to set</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if operation is successful</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="swipeDown(int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">swipeDown</span>
+      <span class="normal">(int steps)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Perform the action on the UI element that is represented by this object, Also see
+ #scrollToBeginning(int), #scrollToEnd(int), #scrollBackward(),
+ #scrollForward(). This method will perform the swipe gesture over any
+ surface. The targeted UI element does not need to have the attribute
+ <code>scrollable</code> set to <code>true</code> for this operation to be performed.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>steps</th>
+          <td>indicates the number of injected move steps into the system. Steps are
+ injected about 5ms apart. So a 100 steps may take about 1/2 second to complete.</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="swipeLeft(int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">swipeLeft</span>
+      <span class="normal">(int steps)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Perform the action on the UI element that is represented by this object. Also see
+ #scrollToBeginning(int), #scrollToEnd(int), #scrollBackward(),
+ #scrollForward(). This method will perform the swipe gesture over any
+ surface. The targeted UI element does not need to have the attribute
+ <code>scrollable</code> set to <code>true</code> for this operation to be performed.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>steps</th>
+          <td>indicates the number of injected move steps into the system. Steps are
+ injected about 5ms apart. So a 100 steps may take about 1/2 second to complete.</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="swipeRight(int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">swipeRight</span>
+      <span class="normal">(int steps)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Perform the action on the UI element that is represented by this object. Also see
+ #scrollToBeginning(int), #scrollToEnd(int), #scrollBackward(),
+ #scrollForward(). This method will perform the swipe gesture over any
+ surface. The targeted UI element does not need to have the attribute
+ <code>scrollable</code> set to <code>true</code> for this operation to be performed.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>steps</th>
+          <td>indicates the number of injected move steps into the system. Steps are
+ injected about 5ms apart. So a 100 steps may take about 1/2 second to complete.</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if successful</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="swipeUp(int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">swipeUp</span>
+      <span class="normal">(int steps)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Perform the action on the UI element that is represented by this UiObject. Also see
+ #scrollToBeginning(int), #scrollToEnd(int), #scrollBackward(),
+ #scrollForward().</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>steps</th>
+          <td>indicates the number of injected move steps into the system. Steps are
+ injected about 5ms apart. So a 100 steps may take about 1/2 second to complete.</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true of successful</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="waitForExists(long)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">waitForExists</span>
+      <span class="normal">(long timeout)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Waits a specified length of time for a UI element to become visible.
+
+ This method waits until the UI element becomes visible on the display, or
+ until the timeout has elapsed. You can use this method in situations where
+ the content that you want to select is not immediately displayed.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>timeout</th>
+          <td>the amount of time to wait (in milliseconds)</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if the UI element is displayed, else false if timeout elapsed while waiting
+</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="waitUntilGone(long)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">waitUntilGone</span>
+      <span class="normal">(long timeout)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Waits a specified length of time for a UI element to become undetectable.
+
+ This method waits until a UI element is no longer matchable, or until the
+ timeout has elapsed.
+
+ A UI element becomes undetectable when the <code><a href="UiSelector.html">UiSelector</a></code> of the object is
+ unable to find a match because the element has either changed its state or is no
+ longer displayed.
+
+ You can use this method when attempting to wait for some long operation
+ to compete, such as downloading a large file or connecting to a remote server.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>timeout</th>
+          <td>time to wait (in milliseconds)</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if the element is gone before timeout elapsed, else false if timeout elapsed
+ but a matching element is still found.
+</li></ul>
+  </div>
+
+    </div>
+</div>
+
diff --git a/docs/html/tools/help/uiautomator/UiObjectNotFoundException.jd b/docs/html/tools/help/uiautomator/UiObjectNotFoundException.jd
new file mode 100644
index 0000000..02c607d
--- /dev/null
+++ b/docs/html/tools/help/uiautomator/UiObjectNotFoundException.jd
@@ -0,0 +1,630 @@
+page.title=UiObjectNotFoundException
+parent.title=uiautomator
+parent.link=index.html
+@jd:body
+<style>
+    h4.jd-details-title {background-color: #DEE8F1;}
+</style>
+<p>Generated in test runs when a <code><a href="UiSelector.html">UiSelector</a></code> selector could not be matched
+ to any UI element displayed.
+</p>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<div class="jd-descr">
+
+
+<h2>Summary</h2>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+<table id="pubctors" class="jd-sumtable"><tr><th colspan="12">Public Constructors</th></tr>
+
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#UiObjectNotFoundException(java.lang.String)">UiObjectNotFoundException</a></span>(String msg)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#UiObjectNotFoundException(java.lang.String, java.lang.Throwable)">UiObjectNotFoundException</a></span>(String detailMessage, Throwable throwable)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#UiObjectNotFoundException(java.lang.Throwable)">UiObjectNotFoundException</a></span>(Throwable throwable)
+        
+  </td></tr>
+
+
+
+</table>
+
+
+
+
+
+
+
+
+
+
+
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="inhmethods" class="jd-sumtable"><tr><th>
+  <a href="#" class="toggle-all" onclick="return toggleAllInherited(this, null)">[Expand]</a>
+  <div style="clear:left;">Inherited Methods</div></th></tr>
+
+
+
+
+<tr class="api apilevel-" >
+<td colspan="12">
+  <a href="#" onclick="return toggleInherited(this, null)" id="inherited-methods-java.lang.Throwable" class="jd-expando-trigger closed"
+          ><img id="inherited-methods-java.lang.Throwable-trigger"
+          src="../../../../../assets/images/triangle-closed.png"
+          class="jd-expando-trigger-img" /></a>
+From class
+
+  java.lang.Throwable
+
+<div id="inherited-methods-java.lang.Throwable">
+  <div id="inherited-methods-java.lang.Throwable-list"
+        class="jd-inheritedlinks">
+  </div>
+  <div id="inherited-methods-java.lang.Throwable-summary" style="display: none;">
+    <table class="jd-sumtable-expando">
+    
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            synchronized
+            
+            
+            
+            Throwable
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">fillInStackTrace</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            Throwable
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">getCause</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">getLocalizedMessage</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">getMessage</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            StackTraceElement[]
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">getStackTrace</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            synchronized
+            
+            
+            
+            Throwable
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">initCause</span>(Throwable arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">printStackTrace</span>(PrintWriter arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">printStackTrace</span>(PrintStream arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">printStackTrace</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">setStackTrace</span>(StackTraceElement[] arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">toString</span>()
+        
+  </td></tr>
+
+
+</table>
+  </div>
+</div>
+</td></tr>
+
+
+
+<tr class="api apilevel-" >
+<td colspan="12">
+  <a href="#" onclick="return toggleInherited(this, null)" id="inherited-methods-java.lang.Object" class="jd-expando-trigger closed"
+          ><img id="inherited-methods-java.lang.Object-trigger"
+          src="../../../../../assets/images/triangle-closed.png"
+          class="jd-expando-trigger-img" /></a>
+From class
+
+  java.lang.Object
+
+<div id="inherited-methods-java.lang.Object">
+  <div id="inherited-methods-java.lang.Object-list"
+        class="jd-inheritedlinks">
+  </div>
+  <div id="inherited-methods-java.lang.Object-summary" style="display: none;">
+    <table class="jd-sumtable-expando">
+    
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">equals</span>(Object arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            Class&lt;?&gt;
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">getClass</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">hashCode</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">notify</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">notifyAll</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">toString</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>(long arg0, int arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>(long arg0)
+        
+  </td></tr>
+
+
+</table>
+  </div>
+</div>
+</td></tr>
+
+
+
+
+</table>
+
+
+</div><!-- jd-descr (summary) -->
+
+<!-- Details -->
+
+
+
+
+
+
+
+
+<!-- XML Attributes -->
+
+
+<!-- Enum Values -->
+
+
+<!-- Constants -->
+
+
+<!-- Fields -->
+
+
+<!-- Public ctors -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+<h2>Public Constructors</h2>
+
+
+
+<a id="UiObjectNotFoundException(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        
+      </span>
+      <span class="sympad">UiObjectNotFoundException</span>
+      <span class="normal">(String msg)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+    </div>
+</div>
+
+
+<a id="UiObjectNotFoundException(java.lang.String, java.lang.Throwable)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        
+      </span>
+      <span class="sympad">UiObjectNotFoundException</span>
+      <span class="normal">(String detailMessage, Throwable throwable)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+    </div>
+</div>
+
+
+<a id="UiObjectNotFoundException(java.lang.Throwable)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        
+      </span>
+      <span class="sympad">UiObjectNotFoundException</span>
+      <span class="normal">(Throwable throwable)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+    </div>
+</div>
diff --git a/docs/html/tools/help/uiautomator/UiScrollable.jd b/docs/html/tools/help/uiautomator/UiScrollable.jd
new file mode 100644
index 0000000..33566a2
--- /dev/null
+++ b/docs/html/tools/help/uiautomator/UiScrollable.jd
@@ -0,0 +1,2914 @@
+page.title=UiScrollable
+parent.title=uiautomator
+parent.link=index.html
+@jd:body
+<style>
+    h4.jd-details-title {background-color: #DEE8F1;}
+</style>
+<p>UiScrollable is a <code><a href="UiCollection.html">UiCollection</a></code> and provides support for searching for items in a
+ scrollable user interface (UI) elements. This class can be used with horizontally or vertically scrollable controls..
+</p>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<div class="jd-descr">
+
+
+<h2>Summary</h2>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+<table id="pubctors" class="jd-sumtable"><tr><th colspan="12">Public Constructors</th></tr>
+
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#UiScrollable(com.android.uiautomator.core.UiSelector)">UiScrollable</a></span>(<a href="UiSelector.html">UiSelector</a> container)
+        
+        <div class="jd-descrdiv">UiScrollable is a <code><a href="UiCollection.html">UiCollection</a></code> and as such requires a <code><a href="UiSelector.html">UiSelector</a></code> to
+ identify the container UI element of the scrollable collection.</div>
+  
+  </td></tr>
+
+
+
+</table>
+
+
+
+
+
+
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="pubmethods" class="jd-sumtable"><tr><th colspan="12">Public Methods</th></tr>
+
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#flingBackward()">flingBackward</a></span>()
+        
+        <div class="jd-descrdiv">See <code><a href="#scrollBackward(int)">scrollBackward(int)</a></code></div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#flingForward()">flingForward</a></span>()
+        
+        <div class="jd-descrdiv">A convenience version of <code><a href="#scrollForward(int)">scrollForward(int)</a></code>, performs a fling</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#flingToBeginning(int)">flingToBeginning</a></span>(int maxSwipes)
+        
+        <div class="jd-descrdiv">See <code><a href="#scrollToBeginning(int, int)">scrollToBeginning(int, int)</a></code></div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#flingToEnd(int)">flingToEnd</a></span>(int maxSwipes)
+        
+        <div class="jd-descrdiv">See <code><a href="#scrollToEnd(int, int)">scrollToEnd(int, int)</a></code></div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getChildByDescription(com.android.uiautomator.core.UiSelector, java.lang.String, boolean)">getChildByDescription</a></span>(<a href="UiSelector.html">UiSelector</a> childPattern, String text, boolean allowScrollSearch)
+        
+        <div class="jd-descrdiv">See <code><a href="#getChildByDescription(com.android.uiautomator.core.UiSelector, java.lang.String)">getChildByDescription(UiSelector, String)</a></code></div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getChildByDescription(com.android.uiautomator.core.UiSelector, java.lang.String)">getChildByDescription</a></span>(<a href="UiSelector.html">UiSelector</a> childPattern, String text)
+        
+        <div class="jd-descrdiv">Searches for child UI element within the constraints of this UiScrollable <code><a href="UiSelector.html">UiSelector</a></code>
+ container.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getChildByInstance(com.android.uiautomator.core.UiSelector, int)">getChildByInstance</a></span>(<a href="UiSelector.html">UiSelector</a> childPattern, int instance)
+        
+        <div class="jd-descrdiv">Searches for child UI element within the constraints of this UiScrollable <code><a href="UiSelector.html">UiSelector</a></code>
+ selector.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getChildByText(com.android.uiautomator.core.UiSelector, java.lang.String, boolean)">getChildByText</a></span>(<a href="UiSelector.html">UiSelector</a> childPattern, String text, boolean allowScrollSearch)
+        
+        <div class="jd-descrdiv">See <code><a href="#getChildByText(com.android.uiautomator.core.UiSelector, java.lang.String)">getChildByText(UiSelector, String)</a></code></div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getChildByText(com.android.uiautomator.core.UiSelector, java.lang.String)">getChildByText</a></span>(<a href="UiSelector.html">UiSelector</a> childPattern, String text)
+        
+        <div class="jd-descrdiv">Searches for child UI element within the constraints of this UiScrollable <code><a href="UiSelector.html">UiSelector</a></code>
+ container.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getMaxSearchSwipes()">getMaxSearchSwipes</a></span>()
+        
+        <div class="jd-descrdiv">#getChildByDescription(String, boolean) and #getChildByText(String, boolean)
+ use an arguments that specifies if scrolling is allowed while searching for the UI element.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            double
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#getSwipeDeadZonePercentage()">getSwipeDeadZonePercentage</a></span>()
+        
+        <div class="jd-descrdiv">Returns the percentage of a widget's size that's considered as a no touch zone when swiping.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#scrollBackward(int)">scrollBackward</a></span>(int steps)
+        
+        <div class="jd-descrdiv">Perform a scroll backward.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#scrollBackward()">scrollBackward</a></span>()
+        
+        <div class="jd-descrdiv">See <code><a href="#scrollBackward(int)">scrollBackward(int)</a></code></div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#scrollDescriptionIntoView(java.lang.String)">scrollDescriptionIntoView</a></span>(String text)
+        
+        <div class="jd-descrdiv">Performs a swipe Up on the UI element until the requested content-description
+ is visible or until swipe attempts have been exhausted.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#scrollForward()">scrollForward</a></span>()
+        
+        <div class="jd-descrdiv">A convenience version of <code><a href="#scrollForward(int)">scrollForward(int)</a></code>, performs a regular scroll</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#scrollForward(int)">scrollForward</a></span>(int steps)
+        
+        <div class="jd-descrdiv">Perform a scroll forward.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#scrollIntoView(com.android.uiautomator.core.UiSelector)">scrollIntoView</a></span>(<a href="UiSelector.html">UiSelector</a> selector)
+        
+        <div class="jd-descrdiv">Perform a scroll search for a UI element matching the <code><a href="UiSelector.html">UiSelector</a></code> selector argument.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#scrollTextIntoView(java.lang.String)">scrollTextIntoView</a></span>(String text)
+        
+        <div class="jd-descrdiv">Performs a swipe up on the UI element until the requested text is visible
+ or until swipe attempts have been exhausted.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#scrollToBeginning(int)">scrollToBeginning</a></span>(int maxSwipes)
+        
+        <div class="jd-descrdiv">See <code><a href="#scrollToBeginning(int, int)">scrollToBeginning(int, int)</a></code></div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#scrollToBeginning(int, int)">scrollToBeginning</a></span>(int maxSwipes, int steps)
+        
+        <div class="jd-descrdiv">Scrolls to the beginning of a scrollable UI element.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#scrollToEnd(int, int)">scrollToEnd</a></span>(int maxSwipes, int steps)
+        
+        <div class="jd-descrdiv">Scrolls to the end of a scrollable UI element.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#scrollToEnd(int)">scrollToEnd</a></span>(int maxSwipes)
+        
+        <div class="jd-descrdiv">See {@link UiScrollable#scrollToEnd(int, int)</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#setAsHorizontalList()">setAsHorizontalList</a></span>()
+        
+        <div class="jd-descrdiv">Set the direction of swipes when performing scroll search
+</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#setAsVerticalList()">setAsVerticalList</a></span>()
+        
+        <div class="jd-descrdiv">Set the direction of swipes when performing scroll search
+</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#setMaxSearchSwipes(int)">setMaxSearchSwipes</a></span>(int swipes)
+        
+        <div class="jd-descrdiv">#getChildByDescription(String, boolean) and #getChildByText(String, boolean)
+ use an arguments that specifies if scrolling is allowed while searching for the UI element.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#setSwipeDeadZonePercentage(double)">setSwipeDeadZonePercentage</a></span>(double swipeDeadZonePercentage)
+        
+        <div class="jd-descrdiv">Sets the percentage of a widget's size that's considered as a no touch zone when swiping.</div>
+  
+  </td></tr>
+
+
+
+</table>
+
+
+
+
+
+
+
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="inhmethods" class="jd-sumtable"><tr><th>
+  <a href="#" class="toggle-all" onclick="return toggleAllInherited(this, null)">[Expand]</a>
+  <div style="clear:left;">Inherited Methods</div></th></tr>
+
+
+<tr class="api apilevel-" >
+<td colspan="12">
+  <a href="#" onclick="return toggleInherited(this, null)" id="inherited-methods-com.android.uiautomator.core.UiCollection" class="jd-expando-trigger closed"
+          ><img id="inherited-methods-com.android.uiautomator.core.UiCollection-trigger"
+          src="../../../../../assets/images/triangle-closed.png"
+          class="jd-expando-trigger-img" /></a>
+From class
+
+  <a href="UiCollection.html">com.android.uiautomator.core.UiCollection</a>
+
+<div id="inherited-methods-com.android.uiautomator.core.UiCollection">
+  <div id="inherited-methods-com.android.uiautomator.core.UiCollection-list"
+        class="jd-inheritedlinks">
+  </div>
+  <div id="inherited-methods-com.android.uiautomator.core.UiCollection-summary" style="display: none;">
+    <table class="jd-sumtable-expando">
+    
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiCollection.html#getChildByDescription(com.android.uiautomator.core.UiSelector, java.lang.String)">getChildByDescription</a></span>(<a href="UiSelector.html">UiSelector</a> childPattern, String text)
+        
+        <div class="jd-descrdiv">Searches for child UI element within the constraints of this UiCollection <code><a href="UiSelector.html">UiSelector</a></code>
+ selector.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiCollection.html#getChildByInstance(com.android.uiautomator.core.UiSelector, int)">getChildByInstance</a></span>(<a href="UiSelector.html">UiSelector</a> childPattern, int instance)
+        
+        <div class="jd-descrdiv">Searches for child UI element within the constraints of this UiCollection <code><a href="UiSelector.html">UiSelector</a></code>
+ selector.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiCollection.html#getChildByText(com.android.uiautomator.core.UiSelector, java.lang.String)">getChildByText</a></span>(<a href="UiSelector.html">UiSelector</a> childPattern, String text)
+        
+        <div class="jd-descrdiv">Searches for child UI element within the constraints of this UiCollection <code><a href="UiSelector.html">UiSelector</a></code>
+ selector.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiCollection.html#getChildCount(com.android.uiautomator.core.UiSelector)">getChildCount</a></span>(<a href="UiSelector.html">UiSelector</a> childPattern)
+        
+        <div class="jd-descrdiv">Counts child UI element instances matching the <code>childPattern</code>
+ argument.</div>
+  
+  </td></tr>
+
+
+</table>
+  </div>
+</div>
+</td></tr>
+
+
+
+<tr class="api apilevel-" >
+<td colspan="12">
+  <a href="#" onclick="return toggleInherited(this, null)" id="inherited-methods-com.android.uiautomator.core.UiObject" class="jd-expando-trigger closed"
+          ><img id="inherited-methods-com.android.uiautomator.core.UiObject-trigger"
+          src="../../../../../assets/images/triangle-closed.png"
+          class="jd-expando-trigger-img" /></a>
+From class
+
+  <a href="UiObject.html">com.android.uiautomator.core.UiObject</a>
+
+<div id="inherited-methods-com.android.uiautomator.core.UiObject">
+  <div id="inherited-methods-com.android.uiautomator.core.UiObject-list"
+        class="jd-inheritedlinks">
+  </div>
+  <div id="inherited-methods-com.android.uiautomator.core.UiObject-summary" style="display: none;">
+    <table class="jd-sumtable-expando">
+    
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#clearTextField()">clearTextField</a></span>()
+        
+        <div class="jd-descrdiv">Clears the existing text contents in an editable field.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#click()">click</a></span>()
+        
+        <div class="jd-descrdiv">Performs a click at the center of the visible bounds of the UI element represented
+ by this UiObject.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#clickAndWaitForNewWindow(long)">clickAndWaitForNewWindow</a></span>(long timeout)
+        
+        <div class="jd-descrdiv">Performs a click at the center of the visible bounds of the UI element represented
+ by this UiObject and waits for window transitions.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#clickAndWaitForNewWindow()">clickAndWaitForNewWindow</a></span>()
+        
+        <div class="jd-descrdiv">See <code><a href="UiObject.html#clickAndWaitForNewWindow(long)">clickAndWaitForNewWindow(long)</a></code>
+ This method is intended to reliably wait for window transitions that would typically take
+ longer than the usual default timeouts.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#clickBottomRight()">clickBottomRight</a></span>()
+        
+        <div class="jd-descrdiv">Clicks the bottom and right corner of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#clickTopLeft()">clickTopLeft</a></span>()
+        
+        <div class="jd-descrdiv">Clicks the top and left corner of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#exists()">exists</a></span>()
+        
+        <div class="jd-descrdiv">Check if UI element exists.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            Rect
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getBounds()">getBounds</a></span>()
+        
+        <div class="jd-descrdiv">Returns the UI element's <code>bounds</code> property.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getChild(com.android.uiautomator.core.UiSelector)">getChild</a></span>(<a href="UiSelector.html">UiSelector</a> selector)
+        
+        <div class="jd-descrdiv">Creates a new UiObject representing a child UI element of the element currently represented
+ by this UiObject.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getChildCount()">getChildCount</a></span>()
+        
+        <div class="jd-descrdiv">Counts the child UI elements immediately under the UI element currently represented by
+ this UiObject.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getContentDescription()">getContentDescription</a></span>()
+        
+        <div class="jd-descrdiv">Reads the <code>content_desc</code> property of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiObject.html">UiObject</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getFromParent(com.android.uiautomator.core.UiSelector)">getFromParent</a></span>(<a href="UiSelector.html">UiSelector</a> selector)
+        
+        <div class="jd-descrdiv">Creates a new UiObject representing a child UI element from the parent element currently
+ represented by this object.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getPackageName()">getPackageName</a></span>()
+        
+        <div class="jd-descrdiv">Reads the UI element's <code>package</code> property</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getSelector()">getSelector</a></span>()
+        
+        <div class="jd-descrdiv">Debugging helper.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getText()">getText</a></span>()
+        
+        <div class="jd-descrdiv">Reads the <code>text</code> property of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            Rect
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#getVisibleBounds()">getVisibleBounds</a></span>()
+        
+        <div class="jd-descrdiv">Returns the visible bounds of the UI element.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isCheckable()">isCheckable</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>checkable</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isChecked()">isChecked</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>checked</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isClickable()">isClickable</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>clickable</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isEnabled()">isEnabled</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>enabled</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isFocusable()">isFocusable</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>focusable</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isFocused()">isFocused</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>focused</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isLongClickable()">isLongClickable</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>long-clickable</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isScrollable()">isScrollable</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>scrollable</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#isSelected()">isSelected</a></span>()
+        
+        <div class="jd-descrdiv">Check if the UI element's <code>selected</code> property is currently true</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#longClick()">longClick</a></span>()
+        
+        <div class="jd-descrdiv">Long clicks the center of the visible bounds of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#longClickBottomRight()">longClickBottomRight</a></span>()
+        
+        <div class="jd-descrdiv">Long clicks bottom and right corner of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#longClickTopLeft()">longClickTopLeft</a></span>()
+        
+        <div class="jd-descrdiv">Long clicks on the top and left corner of the UI element</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#setText(java.lang.String)">setText</a></span>(String text)
+        
+        <div class="jd-descrdiv">Sets the text in an editable field, after clearing the field's content.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#swipeDown(int)">swipeDown</a></span>(int steps)
+        
+        <div class="jd-descrdiv">Perform the action on the UI element that is represented by this object, Also see
+ #scrollToBeginning(int), #scrollToEnd(int), #scrollBackward(),
+ #scrollForward().</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#swipeLeft(int)">swipeLeft</a></span>(int steps)
+        
+        <div class="jd-descrdiv">Perform the action on the UI element that is represented by this object.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#swipeRight(int)">swipeRight</a></span>(int steps)
+        
+        <div class="jd-descrdiv">Perform the action on the UI element that is represented by this object.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#swipeUp(int)">swipeUp</a></span>(int steps)
+        
+        <div class="jd-descrdiv">Perform the action on the UI element that is represented by this UiObject.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#waitForExists(long)">waitForExists</a></span>(long timeout)
+        
+        <div class="jd-descrdiv">Waits a specified length of time for a UI element to become visible.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="UiObject.html#waitUntilGone(long)">waitUntilGone</a></span>(long timeout)
+        
+        <div class="jd-descrdiv">Waits a specified length of time for a UI element to become undetectable.</div>
+  
+  </td></tr>
+
+
+</table>
+  </div>
+</div>
+</td></tr>
+
+
+
+<tr class="api apilevel-" >
+<td colspan="12">
+  <a href="#" onclick="return toggleInherited(this, null)" id="inherited-methods-java.lang.Object" class="jd-expando-trigger closed"
+          ><img id="inherited-methods-java.lang.Object-trigger"
+          src="../../../../../assets/images/triangle-closed.png"
+          class="jd-expando-trigger-img" /></a>
+From class
+
+  java.lang.Object
+
+<div id="inherited-methods-java.lang.Object">
+  <div id="inherited-methods-java.lang.Object-list"
+        class="jd-inheritedlinks">
+  </div>
+  <div id="inherited-methods-java.lang.Object-summary" style="display: none;">
+    <table class="jd-sumtable-expando">
+    
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">equals</span>(Object arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            Class&lt;?&gt;
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">getClass</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">hashCode</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">notify</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">notifyAll</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">toString</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>(long arg0, int arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>(long arg0)
+        
+  </td></tr>
+
+
+</table>
+  </div>
+</div>
+</td></tr>
+
+
+</table>
+
+
+</div><!-- jd-descr (summary) -->
+
+<!-- Details -->
+
+
+
+
+
+
+
+
+<!-- XML Attributes -->
+
+
+<!-- Enum Values -->
+
+
+<!-- Constants -->
+
+
+<!-- Fields -->
+
+
+<!-- Public ctors -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+<h2>Public Constructors</h2>
+
+
+
+<a id="UiScrollable(com.android.uiautomator.core.UiSelector)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        
+      </span>
+      <span class="sympad">UiScrollable</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> container)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>UiScrollable is a <code><a href="UiCollection.html">UiCollection</a></code> and as such requires a <code><a href="UiSelector.html">UiSelector</a></code> to
+ identify the container UI element of the scrollable collection. Further operations on
+ the items in the container will require specifying UiSelector as an item selector.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>container</th>
+          <td>a <code><a href="UiSelector.html">UiSelector</a></code> selector
+</td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+<!-- Protected ctors -->
+
+
+
+<!-- ========= METHOD DETAIL ======== -->
+<!-- Public methdos -->
+
+<h2>Public Methods</h2>
+
+
+
+<a id="flingBackward()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">flingBackward</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>See <code><a href="#scrollBackward(int)">scrollBackward(int)</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if scrolled and false if the control can't scroll anymore
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="flingForward()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">flingForward</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>A convenience version of <code><a href="#scrollForward(int)">scrollForward(int)</a></code>, performs a fling</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if scrolled and false if the control can't scroll anymore
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="flingToBeginning(int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">flingToBeginning</span>
+      <span class="normal">(int maxSwipes)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>See <code><a href="#scrollToBeginning(int, int)">scrollToBeginning(int, int)</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true on scrolled else false
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="flingToEnd(int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">flingToEnd</span>
+      <span class="normal">(int maxSwipes)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>See <code><a href="#scrollToEnd(int, int)">scrollToEnd(int, int)</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true on scrolled else false
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getChildByDescription(com.android.uiautomator.core.UiSelector, java.lang.String, boolean)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiObject.html">UiObject</a>
+      </span>
+      <span class="sympad">getChildByDescription</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> childPattern, String text, boolean allowScrollSearch)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>See <code><a href="#getChildByDescription(com.android.uiautomator.core.UiSelector, java.lang.String)">getChildByDescription(UiSelector, String)</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>childPattern</th>
+          <td><code><a href="UiSelector.html">UiSelector</a></code> selector of the child pattern to match and return</td>
+        </tr>
+        <tr>
+          <th>text</th>
+          <td>String may be a partial match for the content-description of a child element.</td>
+        </tr>
+        <tr>
+          <th>allowScrollSearch</th>
+          <td>set to true if scrolling is allowed</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li><code><a href="UiObject.html">UiObject</a></code> pointing at and instance of <code>childPattern</code></li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getChildByDescription(com.android.uiautomator.core.UiSelector, java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiObject.html">UiObject</a>
+      </span>
+      <span class="sympad">getChildByDescription</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> childPattern, String text)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Searches for child UI element within the constraints of this UiScrollable <code><a href="UiSelector.html">UiSelector</a></code>
+ container. It looks for any child matching the <code>childPattern</code> argument within its
+ hierarchy with a matching content-description text. The returned UiObject will represent the
+ UI element matching the <code>childPattern</code> and not the sub element that matched the
+ content description.</p>
+ By default this operation will perform scroll search while attempting to find the UI element
+ See <code><a href="#getChildByDescription(com.android.uiautomator.core.UiSelector, java.lang.String, boolean)">getChildByDescription(UiSelector, String, boolean)</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>childPattern</th>
+          <td><code><a href="UiSelector.html">UiSelector</a></code> selector of the child pattern to match and return</td>
+        </tr>
+        <tr>
+          <th>text</th>
+          <td>String of the identifying child contents of of the <code>childPattern</code></td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li><code><a href="UiObject.html">UiObject</a></code> pointing at and instance of <code>childPattern</code></li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getChildByInstance(com.android.uiautomator.core.UiSelector, int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiObject.html">UiObject</a>
+      </span>
+      <span class="sympad">getChildByInstance</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> childPattern, int instance)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Searches for child UI element within the constraints of this UiScrollable <code><a href="UiSelector.html">UiSelector</a></code>
+ selector. It looks for any child matching the <code>childPattern</code> argument and
+ return the <code>instance</code> specified. The operation is performed only on the visible
+ items and no scrolling is performed in this case.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>childPattern</th>
+          <td><code><a href="UiSelector.html">UiSelector</a></code> selector of the child pattern to match and return</td>
+        </tr>
+        <tr>
+          <th>instance</th>
+          <td>int the desired matched instance of this <code>childPattern</code></td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li><code><a href="UiObject.html">UiObject</a></code> pointing at and instance of <code>childPattern</code>
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getChildByText(com.android.uiautomator.core.UiSelector, java.lang.String, boolean)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiObject.html">UiObject</a>
+      </span>
+      <span class="sympad">getChildByText</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> childPattern, String text, boolean allowScrollSearch)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>See <code><a href="#getChildByText(com.android.uiautomator.core.UiSelector, java.lang.String)">getChildByText(UiSelector, String)</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>childPattern</th>
+          <td><code><a href="UiSelector.html">UiSelector</a></code> selector of the child pattern to match and return</td>
+        </tr>
+        <tr>
+          <th>text</th>
+          <td>String of the identifying child contents of of the <code>childPattern</code></td>
+        </tr>
+        <tr>
+          <th>allowScrollSearch</th>
+          <td>set to true if scrolling is allowed</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li><code><a href="UiObject.html">UiObject</a></code> pointing at and instance of <code>childPattern</code></li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getChildByText(com.android.uiautomator.core.UiSelector, java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiObject.html">UiObject</a>
+      </span>
+      <span class="sympad">getChildByText</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> childPattern, String text)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Searches for child UI element within the constraints of this UiScrollable <code><a href="UiSelector.html">UiSelector</a></code>
+ container. It looks for any child matching the <code>childPattern</code> argument that has
+ a sub UI element anywhere within its sub hierarchy that has text attribute
+ <code>text</code>. The returned UiObject will point at the <code>childPattern</code>
+ instance that matched the search and not at the text matched sub element</p>
+ By default this operation will perform scroll search while attempting to find the UI
+ element.
+ See <code><a href="#getChildByText(com.android.uiautomator.core.UiSelector, java.lang.String, boolean)">getChildByText(UiSelector, String, boolean)</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>childPattern</th>
+          <td><code><a href="UiSelector.html">UiSelector</a></code> selector of the child pattern to match and return</td>
+        </tr>
+        <tr>
+          <th>text</th>
+          <td>String of the identifying child contents of of the <code>childPattern</code></td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li><code><a href="UiObject.html">UiObject</a></code> pointing at and instance of <code>childPattern</code></li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getMaxSearchSwipes()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        int
+      </span>
+      <span class="sympad">getMaxSearchSwipes</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>#getChildByDescription(String, boolean) and #getChildByText(String, boolean)
+ use an arguments that specifies if scrolling is allowed while searching for the UI element.
+ The number of scrolls currently allowed to perform a search can be read by this method.
+ See <code><a href="#setMaxSearchSwipes(int)">setMaxSearchSwipes(int)</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>max value of the number of swipes currently allowed during a scroll search
+</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="getSwipeDeadZonePercentage()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        double
+      </span>
+      <span class="sympad">getSwipeDeadZonePercentage</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Returns the percentage of a widget's size that's considered as a no touch zone when swiping.
+
+ Dead zones are set as percentage of a widget's total width or height, denoting a margin
+ around the swipable area of the widget. Swipes must start and
+ end inside this margin.
+
+ This is important when the widget being swiped may not respond to the swipe if
+ started at a point too near to the edge. The default is 10% from either edge.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>a value between 0 and 1
+</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="scrollBackward(int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">scrollBackward</span>
+      <span class="normal">(int steps)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Perform a scroll backward. If this list is set to vertical (see <code><a href="#setAsVerticalList()">setAsVerticalList()</a></code>
+ default) then the swipes will be executed from the top to bottom. If this list is set
+ to horizontal (see <code><a href="#setAsHorizontalList()">setAsHorizontalList()</a></code>) then the swipes will be executed from
+ the left to right. Caution is required on devices configured with right to left languages
+ like Arabic and Hebrew.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>steps</th>
+          <td>use steps to control the speed, so that it may be a scroll, or fling</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if scrolled and false if the control can't scroll anymore
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="scrollBackward()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">scrollBackward</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>See <code><a href="#scrollBackward(int)">scrollBackward(int)</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if scrolled and false if the control can't scroll anymore
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="scrollDescriptionIntoView(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">scrollDescriptionIntoView</span>
+      <span class="normal">(String text)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Performs a swipe Up on the UI element until the requested content-description
+ is visible or until swipe attempts have been exhausted. See <code><a href="#setMaxSearchSwipes(int)">setMaxSearchSwipes(int)</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>text</th>
+          <td>to look for anywhere within the contents of this scrollable.</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if item us found else false
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="scrollForward()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">scrollForward</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>A convenience version of <code><a href="#scrollForward(int)">scrollForward(int)</a></code>, performs a regular scroll</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if scrolled and false if the control can't scroll anymore
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="scrollForward(int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">scrollForward</span>
+      <span class="normal">(int steps)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Perform a scroll forward. If this list is set to vertical (see <code><a href="#setAsVerticalList()">setAsVerticalList()</a></code>
+ default) then the swipes will be executed from the bottom to top. If this list is set
+ to horizontal (see <code><a href="#setAsHorizontalList()">setAsHorizontalList()</a></code>) then the swipes will be executed from
+ the right to left. Caution is required on devices configured with right to left languages
+ like Arabic and Hebrew.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>steps</th>
+          <td>use steps to control the speed, so that it may be a scroll, or fling</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if scrolled and false if the control can't scroll anymore
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="scrollIntoView(com.android.uiautomator.core.UiSelector)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">scrollIntoView</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> selector)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Perform a scroll search for a UI element matching the <code><a href="UiSelector.html">UiSelector</a></code> selector argument.
+ See <code><a href="#scrollDescriptionIntoView(java.lang.String)">scrollDescriptionIntoView(String)</a></code> and <code><a href="#scrollTextIntoView(java.lang.String)">scrollTextIntoView(String)</a></code>.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>selector</th>
+          <td><code><a href="UiSelector.html">UiSelector</a></code> selector</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if the item was found and now is in view else false
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="scrollTextIntoView(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">scrollTextIntoView</span>
+      <span class="normal">(String text)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Performs a swipe up on the UI element until the requested text is visible
+ or until swipe attempts have been exhausted. See <code><a href="#setMaxSearchSwipes(int)">setMaxSearchSwipes(int)</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>text</th>
+          <td>to look for</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if item us found else false
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="scrollToBeginning(int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">scrollToBeginning</span>
+      <span class="normal">(int maxSwipes)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>See <code><a href="#scrollToBeginning(int, int)">scrollToBeginning(int, int)</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true on scrolled else false
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="scrollToBeginning(int, int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">scrollToBeginning</span>
+      <span class="normal">(int maxSwipes, int steps)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Scrolls to the beginning of a scrollable UI element. The beginning could be the top most
+ in case of vertical lists or the left most in case of horizontal lists. Caution is required
+ on devices configured with right to left languages like Arabic and Hebrew.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>steps</th>
+          <td>use steps to control the speed, so that it may be a scroll, or fling</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true on scrolled else false
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="scrollToEnd(int, int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">scrollToEnd</span>
+      <span class="normal">(int maxSwipes, int steps)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Scrolls to the end of a scrollable UI element. The end could be the bottom most
+ in case of vertical controls or the right most for horizontal controls. Caution
+ is required on devices configured with right to left languages like Arabic and Hebrew.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>steps</th>
+          <td>use steps to control the speed, so that it may be a scroll, or fling</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true on scrolled else false
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="scrollToEnd(int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">scrollToEnd</span>
+      <span class="normal">(int maxSwipes)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>See {@link UiScrollable#scrollToEnd(int, int)</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true on scrolled else false
+</li></ul>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Throws</h5>
+      <table class="jd-tagtable">  
+        <tr>
+            <th><a href="UiObjectNotFoundException.html">UiObjectNotFoundException</a></td>
+            <td></td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="setAsHorizontalList()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">setAsHorizontalList</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the direction of swipes when performing scroll search
+</p></div>
+
+    </div>
+</div>
+
+
+<a id="setAsVerticalList()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">setAsVerticalList</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the direction of swipes when performing scroll search
+</p></div>
+
+    </div>
+</div>
+
+
+<a id="setMaxSearchSwipes(int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">setMaxSearchSwipes</span>
+      <span class="normal">(int swipes)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>#getChildByDescription(String, boolean) and #getChildByText(String, boolean)
+ use an arguments that specifies if scrolling is allowed while searching for the UI element.
+ The number of scrolls allowed to perform a search can be modified by this method.
+ The current value can be read by calling <code><a href="#getMaxSearchSwipes()">getMaxSearchSwipes()</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>swipes</th>
+          <td>is the number of search swipes until abort
+</td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="setSwipeDeadZonePercentage(double)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">setSwipeDeadZonePercentage</span>
+      <span class="normal">(double swipeDeadZonePercentage)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Sets the percentage of a widget's size that's considered as a no touch zone when swiping.
+
+ Dead zones are set as percentage of a widget's total width or height, denoting a margin
+ around the swipable area of the widget. Swipes must always start and
+ end inside this margin.
+
+ This is important when the widget being swiped may not respond to the swipe if
+ started at a point too near to the edge. The default is 10% from either edge</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>swipeDeadZonePercentage</th>
+          <td>is a value between 0 and 1
+</td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
diff --git a/docs/html/tools/help/uiautomator/UiSelector.jd b/docs/html/tools/help/uiautomator/UiSelector.jd
new file mode 100644
index 0000000..96d3fd8
--- /dev/null
+++ b/docs/html/tools/help/uiautomator/UiSelector.jd
@@ -0,0 +1,2088 @@
+page.title=UiSelector
+parent.title=uiautomator
+parent.link=index.html
+@jd:body
+<style>
+    h4.jd-details-title {background-color: #DEE8F1;}
+</style>
+
+
+<h2>Class Overview</h2>
+<p>This class provides the mechanism for tests to describe the UI elements they
+ intend to target. A UI element has many properties associated with it such as
+ text value, content-description, class name and multiple state information like
+ selected, enabled, checked etc. Additionally UiSelector allows targeting of UI
+ elements within a specific display hierarchies to distinguish similar elements
+ based in the hierarchies they're in.</p>
+
+
+
+
+
+</div><!-- jd-descr -->
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<div class="jd-descr">
+
+
+<h2>Summary</h2>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+<table id="pubctors" class="jd-sumtable"><tr><th colspan="12">Public Constructors</th></tr>
+
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#UiSelector()">UiSelector</a></span>()
+        
+  </td></tr>
+
+
+
+</table>
+
+
+
+
+
+
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="pubmethods" class="jd-sumtable"><tr><th colspan="12">Public Methods</th></tr>
+
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#checked(boolean)">checked</a></span>(boolean val)
+        
+        <div class="jd-descrdiv">Set the search criteria to match widgets that
+ are currently checked (usually for checkboxes).</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#childSelector(com.android.uiautomator.core.UiSelector)">childSelector</a></span>(<a href="UiSelector.html">UiSelector</a> selector)
+        
+        <div class="jd-descrdiv">Adds a child UiSelector criteria to this selector.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#className(java.lang.String)">className</a></span>(String className)
+        
+        <div class="jd-descrdiv">Set the search criteria to match the class property
+ for a widget (for example, "android.widget.Button").</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            &lt;T&gt;
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#className(java.lang.Class<T>)">className</a></span>(Class&lt;T&gt; type)
+        
+        <div class="jd-descrdiv">Set the search criteria to match the class property
+ for a widget (for example, "android.widget.Button").</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#classNameMatches(java.lang.String)">classNameMatches</a></span>(String regex)
+        
+        <div class="jd-descrdiv">Set the search criteria to match the class property
+ for a widget (for example, "android.widget.Button").</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#clickable(boolean)">clickable</a></span>(boolean val)
+        
+        <div class="jd-descrdiv">Set the search criteria to match widgets that are clickable.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#description(java.lang.String)">description</a></span>(String desc)
+        
+        <div class="jd-descrdiv">Set the search criteria to match the content-description
+ property for a widget.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#descriptionContains(java.lang.String)">descriptionContains</a></span>(String desc)
+        
+        <div class="jd-descrdiv">Set the search criteria to match the content-description
+ property for a widget.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#descriptionMatches(java.lang.String)">descriptionMatches</a></span>(String regex)
+        
+        <div class="jd-descrdiv">Set the search criteria to match the content-description
+ property for a widget.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#descriptionStartsWith(java.lang.String)">descriptionStartsWith</a></span>(String desc)
+        
+        <div class="jd-descrdiv">Set the search criteria to match the content-description
+ property for a widget.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#enabled(boolean)">enabled</a></span>(boolean val)
+        
+        <div class="jd-descrdiv">Set the search criteria to match widgets that are enabled.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#focusable(boolean)">focusable</a></span>(boolean val)
+        
+        <div class="jd-descrdiv">Set the search criteria to match widgets that are focusable.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#focused(boolean)">focused</a></span>(boolean val)
+        
+        <div class="jd-descrdiv">Set the search criteria to match widgets that have focus.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#fromParent(com.android.uiautomator.core.UiSelector)">fromParent</a></span>(<a href="UiSelector.html">UiSelector</a> selector)
+        
+        <div class="jd-descrdiv">Adds a child UiSelector criteria to this selector which is used to
+ start search from the parent widget.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#index(int)">index</a></span>(int index)
+        
+        <div class="jd-descrdiv">Set the search criteria to match the widget by its node
+ index in the layout hierarchy.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#instance(int)">instance</a></span>(int instance)
+        
+        <div class="jd-descrdiv">Set the search criteria to match the
+ widget by its instance number.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#longClickable(boolean)">longClickable</a></span>(boolean val)
+        
+        <div class="jd-descrdiv">Set the search criteria to match widgets that are long-clickable.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#packageName(java.lang.String)">packageName</a></span>(String name)
+        
+        <div class="jd-descrdiv">Set the search criteria to match the package name
+ of the application that contains the widget.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#packageNameMatches(java.lang.String)">packageNameMatches</a></span>(String regex)
+        
+        <div class="jd-descrdiv">Set the search criteria to match the package name
+ of the application that contains the widget.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#scrollable(boolean)">scrollable</a></span>(boolean val)
+        
+        <div class="jd-descrdiv">Set the search criteria to match widgets that are scrollable.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#selected(boolean)">selected</a></span>(boolean val)
+        
+        <div class="jd-descrdiv">Set the search criteria to match widgets that
+ are currently selected.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#text(java.lang.String)">text</a></span>(String text)
+        
+        <div class="jd-descrdiv">Set the search criteria to match the visible text displayed
+ for a widget (for example, the text label to launch an app).</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#textContains(java.lang.String)">textContains</a></span>(String text)
+        
+        <div class="jd-descrdiv">Set the search criteria to match the visible text displayed
+ for a widget (for example, the text label to launch an app).</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#textMatches(java.lang.String)">textMatches</a></span>(String regex)
+        
+        <div class="jd-descrdiv">Set the search criteria to match the visible text displayed
+ for a widget (for example, the text label to launch an app).</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            <a href="UiSelector.html">UiSelector</a>
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#textStartsWith(java.lang.String)">textStartsWith</a></span>(String text)
+        
+        <div class="jd-descrdiv">Text property is usually the widget's visible text on the display.</div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#toString()">toString</a></span>()
+        
+  </td></tr>
+
+
+
+</table>
+
+
+
+
+
+
+
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="inhmethods" class="jd-sumtable"><tr><th>
+  <a href="#" class="toggle-all" onclick="return toggleAllInherited(this, null)">[Expand]</a>
+  <div style="clear:left;">Inherited Methods</div></th></tr>
+
+
+<tr class="api apilevel-" >
+<td colspan="12">
+  <a href="#" onclick="return toggleInherited(this, null)" id="inherited-methods-java.lang.Object" class="jd-expando-trigger closed"
+          ><img id="inherited-methods-java.lang.Object-trigger"
+          src="../../../../../assets/images/triangle-closed.png"
+          class="jd-expando-trigger-img" /></a>
+From class
+
+  java.lang.Object
+
+<div id="inherited-methods-java.lang.Object">
+  <div id="inherited-methods-java.lang.Object-list"
+        class="jd-inheritedlinks">
+  </div>
+  <div id="inherited-methods-java.lang.Object-summary" style="display: none;">
+    <table class="jd-sumtable-expando">
+    
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">equals</span>(Object arg0)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            Class&lt;?&gt;
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">getClass</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            int
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">hashCode</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">notify</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">notifyAll</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            
+            
+            
+            String
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">toString</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>()
+        
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>(long arg0, int arg1)
+        
+  </td></tr>
+
+
+	 
+    <tr class="api">
+        <td class="jd-typecol">
+            
+            
+            final
+            
+            
+            void
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad">wait</span>(long arg0)
+        
+  </td></tr>
+
+
+</table>
+  </div>
+</div>
+</td></tr>
+
+
+</table>
+
+
+</div><!-- jd-descr (summary) -->
+
+<!-- Details -->
+
+
+
+
+
+
+
+
+<!-- XML Attributes -->
+
+
+<!-- Enum Values -->
+
+
+<!-- Constants -->
+
+
+<!-- Fields -->
+
+
+<!-- Public ctors -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+<h2>Public Constructors</h2>
+
+
+
+<a id="UiSelector()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        
+      </span>
+      <span class="sympad">UiSelector</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+    </div>
+</div>
+
+
+
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+<!-- Protected ctors -->
+
+
+
+<!-- ========= METHOD DETAIL ======== -->
+<!-- Public methdos -->
+
+<h2>Public Methods</h2>
+
+
+
+<a id="checked(boolean)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">checked</span>
+      <span class="normal">(boolean val)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match widgets that
+ are currently checked (usually for checkboxes).
+
+ Typically, using this search criteria alone is not useful.
+ You should also include additional criteria, such as text,
+ content-description, or the class name for a widget.
+
+ If no other search criteria is specified, and there is more
+ than one matching widget, the first widget in the tree
+ is selected.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>val</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="childSelector(com.android.uiautomator.core.UiSelector)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">childSelector</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> selector)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Adds a child UiSelector criteria to this selector.
+
+ Use this selector to narrow the search scope to
+ child widgets under a specific parent widget.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with this added search criterion</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="className(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">className</span>
+      <span class="normal">(String className)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match the class property
+ for a widget (for example, "android.widget.Button").</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>className</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="className(java.lang.Class<T>)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">className</span>
+      <span class="normal">(Class&lt;T&gt; type)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match the class property
+ for a widget (for example, "android.widget.Button").</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+  <div class="jd-tagdata">
+  <h5 class="jd-tagtitle">Since</h5>
+  <ul class="nolist"><li>Android API Level 17</li></ul>
+</div>
+    </div>
+</div>
+
+
+<a id="classNameMatches(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">classNameMatches</span>
+      <span class="normal">(String regex)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match the class property
+ for a widget (for example, "android.widget.Button").</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+  <div class="jd-tagdata">
+  <h5 class="jd-tagtitle">Since</h5>
+  <ul class="nolist"><li>Android API Level 17</li></ul>
+</div>
+    </div>
+</div>
+
+
+<a id="clickable(boolean)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">clickable</span>
+      <span class="normal">(boolean val)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match widgets that are clickable.
+
+ Typically, using this search criteria alone is not useful.
+ You should also include additional criteria, such as text,
+ content-description, or the class name for a widget.
+
+ If no other search criteria is specified, and there is more
+ than one matching widget, the first widget in the tree
+ is selected.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>val</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="description(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">description</span>
+      <span class="normal">(String desc)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match the content-description
+ property for a widget.
+
+ The content-description is typically used
+ by the Android Accessibility framework to
+ provide an audio prompt for the widget when
+ the widget is selected. The content-description
+ for the widget must match exactly
+ with the string in your input argument.
+
+ Matching is case-sensitive.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>desc</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="descriptionContains(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">descriptionContains</span>
+      <span class="normal">(String desc)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match the content-description
+ property for a widget.
+
+ The content-description is typically used
+ by the Android Accessibility framework to
+ provide an audio prompt for the widget when
+ the widget is selected. The content-description
+ for the widget must contain
+ the string in your input argument.
+
+ Matching is case-insensitive.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>desc</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="descriptionMatches(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">descriptionMatches</span>
+      <span class="normal">(String regex)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match the content-description
+ property for a widget.
+
+ The content-description is typically used
+ by the Android Accessibility framework to
+ provide an audio prompt for the widget when
+ the widget is selected. The content-description
+ for the widget must match exactly
+ with the string in your input argument.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+  <div class="jd-tagdata">
+  <h5 class="jd-tagtitle">Since</h5>
+  <ul class="nolist"><li>Android API Level 17</li></ul>
+</div>
+    </div>
+</div>
+
+
+<a id="descriptionStartsWith(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">descriptionStartsWith</span>
+      <span class="normal">(String desc)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match the content-description
+ property for a widget.
+
+ The content-description is typically used
+ by the Android Accessibility framework to
+ provide an audio prompt for the widget when
+ the widget is selected. The content-description
+ for the widget must start
+ with the string in your input argument.
+
+ Matching is case-insensitive.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>desc</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="enabled(boolean)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">enabled</span>
+      <span class="normal">(boolean val)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match widgets that are enabled.
+
+ Typically, using this search criteria alone is not useful.
+ You should also include additional criteria, such as text,
+ content-description, or the class name for a widget.
+
+ If no other search criteria is specified, and there is more
+ than one matching widget, the first widget in the tree
+ is selected.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>val</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="focusable(boolean)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">focusable</span>
+      <span class="normal">(boolean val)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match widgets that are focusable.
+
+ Typically, using this search criteria alone is not useful.
+ You should also include additional criteria, such as text,
+ content-description, or the class name for a widget.
+
+ If no other search criteria is specified, and there is more
+ than one matching widget, the first widget in the tree
+ is selected.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>val</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="focused(boolean)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">focused</span>
+      <span class="normal">(boolean val)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match widgets that have focus.
+
+ Typically, using this search criteria alone is not useful.
+ You should also include additional criteria, such as text,
+ content-description, or the class name for a widget.
+
+ If no other search criteria is specified, and there is more
+ than one matching widget, the first widget in the tree
+ is selected.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>val</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="fromParent(com.android.uiautomator.core.UiSelector)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">fromParent</span>
+      <span class="normal">(<a href="UiSelector.html">UiSelector</a> selector)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Adds a child UiSelector criteria to this selector which is used to
+ start search from the parent widget.
+
+ Use this selector to narrow the search scope to
+ sibling widgets as well all child widgets under a parent.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with this added search criterion</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="index(int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">index</span>
+      <span class="normal">(int index)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match the widget by its node
+ index in the layout hierarchy.
+
+ The index value must be 0 or greater.
+
+ Using the index can be unreliable and should only
+ be used as a last resort for matching. Instead,
+ consider using the <code><a href="#instance(int)">instance(int)</a></code> method.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>index</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="instance(int)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">instance</span>
+      <span class="normal">(int instance)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match the
+ widget by its instance number.
+
+ The instance value must be 0 or greater, where
+ the first instance is 0.
+
+ For example, to simulate a user click on
+ the third image that is enabled in a UI screen, you
+ could specify a a search criteria where the instance is
+ 2, the <code><a href="#className(java.lang.String)">className(String)</a></code> matches the image
+ widget class, and <code><a href="#enabled(boolean)">enabled(boolean)</a></code> is true.
+ The code would look like this:
+ <code>
+ new UiSelector().className("android.widget.ImageView")
+    .enabled(true).instance(2);
+ </code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>instance</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="longClickable(boolean)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">longClickable</span>
+      <span class="normal">(boolean val)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match widgets that are long-clickable.
+
+ Typically, using this search criteria alone is not useful.
+ You should also include additional criteria, such as text,
+ content-description, or the class name for a widget.
+
+ If no other search criteria is specified, and there is more
+ than one matching widget, the first widget in the tree
+ is selected.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>val</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+  <div class="jd-tagdata">
+  <h5 class="jd-tagtitle">Since</h5>
+  <ul class="nolist"><li>Android API Level 17</li></ul>
+</div>
+    </div>
+</div>
+
+
+<a id="packageName(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">packageName</span>
+      <span class="normal">(String name)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match the package name
+ of the application that contains the widget.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>name</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="packageNameMatches(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">packageNameMatches</span>
+      <span class="normal">(String regex)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match the package name
+ of the application that contains the widget.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+  <div class="jd-tagdata">
+  <h5 class="jd-tagtitle">Since</h5>
+  <ul class="nolist"><li>Android API Level 17</li></ul>
+</div>
+    </div>
+</div>
+
+
+<a id="scrollable(boolean)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">scrollable</span>
+      <span class="normal">(boolean val)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match widgets that are scrollable.
+
+ Typically, using this search criteria alone is not useful.
+ You should also include additional criteria, such as text,
+ content-description, or the class name for a widget.
+
+ If no other search criteria is specified, and there is more
+ than one matching widget, the first widget in the tree
+ is selected.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>val</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="selected(boolean)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">selected</span>
+      <span class="normal">(boolean val)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match widgets that
+ are currently selected.
+
+ Typically, using this search criteria alone is not useful.
+ You should also include additional criteria, such as text,
+ content-description, or the class name for a widget.
+
+ If no other search criteria is specified, and there is more
+ than one matching widget, the first widget in the tree
+ is selected.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>val</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="text(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">text</span>
+      <span class="normal">(String text)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match the visible text displayed
+ for a widget (for example, the text label to launch an app).
+
+ The text for the widget must match exactly
+ with the string in your input argument.
+ Matching is case-sensitive.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>text</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="textContains(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">textContains</span>
+      <span class="normal">(String text)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match the visible text displayed
+ for a widget (for example, the text label to launch an app).
+
+ The text for the widget must contain the string in
+ your input argument. Matching is case-sensitive.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>text</th>
+          <td>Value to match</td>
+        </tr>
+      </table>
+  </div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="textMatches(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">textMatches</span>
+      <span class="normal">(String regex)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Set the search criteria to match the visible text displayed
+ for a widget (for example, the text label to launch an app).
+
+ The text for the widget must match exactly
+ with the string in your input argument.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with the specified search criteria</li></ul>
+  </div>
+  <div class="jd-tagdata">
+  <h5 class="jd-tagtitle">Since</h5>
+  <ul class="nolist"><li>Android API Level 17</li></ul>
+</div>
+    </div>
+</div>
+
+
+<a id="textStartsWith(java.lang.String)"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="UiSelector.html">UiSelector</a>
+      </span>
+      <span class="sympad">textStartsWith</span>
+      <span class="normal">(String text)</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Text property is usually the widget's visible text on the display.
+
+ Adding this to the search criteria indicates that the search performed
+ should match a widget with text value starting with the text parameter.
+
+ The matching will be case-insensitive.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>UiSelector with this added search criterion</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
+<a id="toString()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        String
+      </span>
+      <span class="sympad">toString</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div>
+
+</div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+    </div>
+</div>
+
+
+
+
+
+<!-- ========= METHOD DETAIL ======== -->
+
+
+
+<!-- ========= END OF CLASS DATA ========= -->
+
diff --git a/docs/html/tools/help/uiautomator/UiWatcher.jd b/docs/html/tools/help/uiautomator/UiWatcher.jd
new file mode 100644
index 0000000..b416fad
--- /dev/null
+++ b/docs/html/tools/help/uiautomator/UiWatcher.jd
@@ -0,0 +1,78 @@
+page.title=UiWatcher
+parent.title=uiautomator
+parent.link=index.html
+@jd:body
+<style>
+    h4.jd-details-title {background-color: #DEE8F1;}
+</style>
+
+<p>Represents a conditional watcher on the target device. To learn how to register a conditional 
+ watcher, see <code><a href="UiDevice.html#registerWatcher(java.lang.String, com.android.uiautomator.core.UiWatcher)">UiDevice.registerWatcher()</a></code>.
+</p>
+
+<div class="jd-descr">
+
+<h2>Summary</h2>
+
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="pubmethods" class="jd-sumtable"><tr><th colspan="12">Public Methods</th></tr>
+
+
+
+	 
+    <tr class="api" >
+        <td class="jd-typecol">
+            abstract
+            
+            
+            
+            
+            boolean
+        </td>
+        <td class="jd-linkcol" width="100%">
+        <span class="sympad"><a href="#checkForCondition()">checkForCondition</a></span>()
+        
+        <div class="jd-descrdiv">The testing framework calls this handler method automatically when the framework  
+        is unable to find a match using the <code><a href="UiSelector.html">UiSelector</a></code>.</div>
+  
+  </td></tr>
+
+</table>
+
+</div><!-- jd-descr (summary) -->
+
+
+<!-- ========= METHOD DETAIL ======== -->
+<!-- Public methdos -->
+
+<h2>Public Methods</h2>
+
+<a id="checkForCondition()"></a>
+
+<div class="jd-details api "> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+        abstract 
+         
+        boolean
+      </span>
+      <span class="sympad">checkForCondition</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+
+      </div>
+    <div class="jd-details-descr">
+      
+  <div class="jd-tagdata jd-tagdescr"><p>The testing framework calls this handler method automatically when the framework is unable to find a match using the <code><a href="UiSelector.html">UiSelector</a></code>. When a match is not found after a predetermined time has elapsed, the framework calls the checkForCondition() method of all registered watchers on the device. You can use this method to handle known blocking issues that are preventing the test from proceeding. For example, you can check if a dialog appeared that is blocking the the test, then close the dialog or perform some other appropriate action to allow the test to continue.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true to indicate a matched condition, or false if no matching condition is found
+</li></ul>
+  </div>
+
+    </div>
+</div>
diff --git a/docs/html/tools/help/uiautomator/index.jd b/docs/html/tools/help/uiautomator/index.jd
new file mode 100644
index 0000000..38ba177
--- /dev/null
+++ b/docs/html/tools/help/uiautomator/index.jd
@@ -0,0 +1,177 @@
+page.title=uiautomator
+parent.title=Tools
+parent.link=index.html
+@jd:body
+
+<div id="qv-wrapper">
+  <div id="qv">
+     <h2>In this document</h2>
+  <ul>
+     <li><a href="#syntax">Syntax</a></li>
+     <li><a href="#options">Options</a></li>
+     <lI><a href="#api">uiautomator API</a>
+        <ul>
+        <li><a href="#classes">Classes</a></li>
+        <li><a href="#interfaces">Interfaces</a></li>
+        <li><a href="#exceptions">Exceptions</a></li>
+        </ul>
+     </lI>
+  </ul>
+  </div>
+</div>
+
+<p>The {@code uiautomator} testing framework lets you test your user interface (UI) efficiently by creating automated functional UI testcases that can be run against your app on one or more devices.</p>
+<p>For more information on testing with the {@code uiautomator} framework, see <a href="{@docRoot}tools/testing/testing_ui.html">UI Testing</a>.</p>
+
+<h2 id="syntax">Syntax</h2>
+<p>To run your testcases on the target device, you can use the {@code adb shell} command to invoke the {@code uiautomator} tool.  The syntax is:
+<pre>
+adb shell uiautomator runtest &lt;jar&gt; -c &lt;test_class_or_method&gt; [options]
+</pre>
+</p>
+<p>Here’s an example:</p>
+<pre>adb shell uiautomator runtest LaunchSettings.jar -c com.uia.example.my.LaunchSettings</pre>
+
+<h2 id="options">Command-line Options</h2>
+<p>The following table describes the subcommands and options for {@code uiautomator}.</p>
+
+<p class="table-caption" id="table1">
+<strong>Table 1.</strong> Command-line options for {@code uiautomator}</p>
+<table>
+<tr>
+  <th>Subcommand</th>
+  <th>Option</th>
+  <th>Description</th>
+</tr>
+
+<tr>
+<td rowspan="6"><code>runtest</code></td>
+<td><nobr>{@code &lt;jar&gt;}</nobr></td>
+<td><strong>Required</strong>. The {@code &lt;jar&gt;} argument is the name of one or more JAR files that you deployed to the target device which contain your uiautomator testcases. You can list more than one JAR file by using a space as a separator.</td>
+</tr>
+
+<tr>
+<td><nobr><code>-c &lt;test_class_or_method&gt; </code></nobr></td>
+<td><strong>Required</strong>. The {@code &lt;test_class_or_method&gt;} argument is a list of one or more specific test classes or test methods from the JARs that you want {@code uiautomator} to run. <p>Each class or method must be fully qualified with the package name, in one of these formats:
+<ul>
+<li>{@code package_name.class_name}</li>
+<li>{@code package_name.class_name#method_name}</li>
+</ul>
+You can list multiple classes or methods by using a space as a separator.</p></td>
+</tr>
+
+<tr>
+<td><nobr><code>--nohup</code></nobr></td>
+<td>Runs the test to completion on the device even if its parent process is terminated (for example, if the device is disconnected).</td>
+</tr>
+
+<tr>
+<td><nobr><code>-e &lt;NAME&gt; &lt;VALUE&gt;</code></nobr></td>
+<td><p>Specify other name-value pairs to be passed to test classes. May be repeated.</p><p class="note"><strong>Note: </strong>The {@code -e} options cannot be combined; you must prefix each option with a separate {@code -e} flag. </p></td>
+</tr>
+
+<tr>
+<td><nobr><code>-e debug [true|false]</code></nobr></td>
+<td>Wait for debugger to connect before starting.</td>
+</tr>
+
+<tr>
+<td><nobr><code>-e runner [CLASS]</code></nobr></td>
+<td>Use the specified test runner class instead. If unspecified, the {@code uiautomator} framework’s  default runner will be used.</td>
+</tr>
+
+<tr>
+<td><code>dump</code></td>
+<td><code>[file]</code></td>
+<td>Generate an XML file with a dump of the current UI hierarchy. If a filepath is not specified, by default, the generated dump file is stored on the device in this location {@code /storage/sdcard0/window_dump.xml}.</td>
+</tr>
+
+<tr>
+<td><code>events</code></td>
+<td>&nbsp;</td>
+<td>Prints out accessibility events to the console until the connection to the device is terminated</td>
+</tr>
+</table>
+
+<h2 id="api">uiautomator API</h2>
+<p>The {@code uiautomator} API is bundled in the {@code uiautomator.jar} file under the {@code &lt;android-sdk&gt;/platforms/} directory.  The API includes these key classes, interfaces, and exceptions that allow you to capture and manipulate UI components on the target app:</p>
+
+<h3 id="classes">Classes</h3>
+<table>
+<tr>
+  <th>Class</th>
+  <th>Description</th>
+</tr>
+
+<tr>
+<td><nobr><a href="{@docRoot}tools/help/uiautomator/UiCollection.html">{@code com.android.uiautomator.core.UiCollection}</a></nobr></td>
+<td>Used to enumerate a container's user interface (UI) elements for the purpose of counting, or targeting a sub elements by a child's text or description.</td>
+</tr>
+
+<tr>
+<td><nobr><a href="{@docRoot}tools/help/uiautomator/UiDevice.html">{@code com.android.uiautomator.core.UiDevice}</a></nobr></td>
+<td>Provides access to state information about the device. You can also use this class to simulate user actions on the device, such as pressing the d-pad hardware button or pressing the Home and Menu buttons.</td>
+</tr>
+
+<tr>
+<td><nobr><a href="{@docRoot}tools/help/uiautomator/UiObject.html">{@code com.android.uiautomator.core.UiObject}</a></nobr></td>
+<td>Represents a user interface (UI) element.</td>
+</tr>
+
+<tr>
+<td><nobr><a href="{@docRoot}tools/help/uiautomator/UiScrollable.html">{@code com.android.uiautomator.core.UiScrollable}</a></nobr></td>
+<td>Provides support for searching for items in a scrollable UI container.</td>
+</tr>
+
+<tr>
+<td><nobr><a href="{@docRoot}tools/help/uiautomator/UiSelector.html">{@code com.android.uiautomator.core.UiSelector}</a></nobr></td>
+<td>Represents a query for one or more target UI elements on a device screen. </td>
+</tr>
+
+</table>
+
+<h3 id="interfaces">Interfaces</h3>
+
+<table>
+<tr>
+  <th>Interface</th>
+  <th>Description</th>
+</tr>
+
+<tr>
+<td><nobr><a href="{@docRoot}tools/help/uiautomator/UiWatcher.html">{@code com.android.uiautomator.core.UiWatcher}</a></nobr></td>
+<td>Represents a conditional watcher on the target device.</td>
+</tr>
+
+<tr>
+<td><nobr><a href="{@docRoot}tools/help/uiautomator/IAutomationSupport.html">{@code com.android.uiautomator.testrunner.IAutomationSupport}</a></nobr></td>
+<td>Provides auxiliary support for running test cases.</td>
+</tr>
+
+<tr>
+<td><nobr><a href="{@docRoot}tools/help/uiautomator/UiAutomatorTestCase.html">{@code com.android.uiautomator.testrunner.UiAutomatorTestCase}</a></nobr></td>
+<td>Defines an environment for running multiple tests. All {@code uiautomator} test cases should extend this class.</td>
+</tr>
+
+</table>
+
+<h3 id="exceptions">Exceptions</h3>
+
+<table>
+<tr>
+  <th>Exception</th>
+  <th>Description</th>
+</tr>
+
+<tr>
+<td><nobr><a href="{@docRoot}tools/help/uiautomator/UiObjectNotFoundException.html">{@code com.android.uiautomator.core.UiObjectNotFoundException}</a></nobr></td>
+<td>Indicates when a a <a href="{@docRoot}tools/help/uiautomator/UiSelector.html">{@code UiSelector}</a> could not be matched to any UI element displayed.</td>
+</tr>
+
+</table>
+
+
+
+
+
+
diff --git a/docs/html/tools/index.jd b/docs/html/tools/index.jd
index 04e0d3b..38401aa 100644
--- a/docs/html/tools/index.jd
+++ b/docs/html/tools/index.jd
@@ -17,68 +17,88 @@
 
 <div style="margin-top:20px;"></div>
 
-<div class="col-6">
+<div class="col-7" style="margin-left:0">
 <h3>Full Java IDE</h3>
 
   <ul>
-    <li>Android-specific refactoring, quick fixes, integrated navigation between Java and Android XML resources.</li> 
-    <li>Enhanced XML editors for Android XML resources</li> 
-    <li>Static analysis tools to catch performance, usability, and correctness problems</li> 
+    <li>Android-specific refactoring, quick fixes, integrated navigation between Java and XML resources.</li> 
+    <li>Enhanced XML editors for Android XML resources.</li> 
+    <li>Static analysis tools to catch performance, usability, and correctness problems.</li> 
     <li>Build support for complex projects, command-line support for CI through Ant. Includes ProGuard and app-signing. </li> 
     <li>Template-based wizard to create standard Android projects and components.</li> 
   </ul>
 </div>
 
-<div class="col-6">
+
+<div class="col-6" style="margin-right:0">
+
 <h3>Graphical UI Builders</h3>
-    
   <ul>
     <li>Build rich Android UI with drag and drop. 
     <li>Visualize your UI on tablets, phones, and other devices. Switch themes, locales, even platform versions instantly, without building.</li>
-    <li>Visual refactoring lets you extracts layout for inclusion, convert layouts, extract styles</li>
-    <li>Editor support for working with custom UI components</li>
+    <li>Visual refactoring lets you extracts layout for inclusion, convert layouts, extract styles.</li>
+    <li>Editor support for working with custom UI components.</li>
   </ul>
+
 </div>
 
-<div class="col-6" style="clear:both">
+
+<div class="col-7" style="clear:both;margin-left:0;">
+
+<h3>On-device Developer Options</h3>
+<ul>
+  <li>Enable debugging over USB.</li>
+  <li>Quickly capture bug reports onto the device.</li>
+  <li>Show CPU usage on screen.</li>
+  <li>Draw debugging information on screen such as layout bounds,
+    updates on GPU views and hardware layers, touch location, and others.</li>
+  <li>Plus many more options to simulate app stresses or enable debugging options.</li>
+</ul>
+<p>To access these on your device, open the <em>Developer options</em> in the
+system Settings. Note that on Android 4.2 and higher, the Developer options screen is
+hidden by default. To make it available, go to
+<b>Settings > About phone</b> and tap <b>Build number</b> seven times. Return to the previous
+screen to find Developer options.</p>
+
+</div>
+
+<div class="col-6" style="margin-right:0">
+  <img src="{@docRoot}images/tools/dev-options-inmilk.png" alt="" style="margin:-10px 0 0;">
+</div>
+
+
+<div class="col-7" style="clear:both;margin-left:0;">
 <h3>Develop on Hardware Devices</h3>
 
   <ul>
     <li>Use any commercial Android hardware device or multiple devices.</li> 
-    <li>Deploy your app to connected devices directy from the IDE</li> 
-    <li>Live, on-device debugging, testing, and profiling</li> 
+    <li>Deploy your app to connected devices directy from the IDE.</li> 
+    <li>Live, on-device debugging, testing, and profiling.</li> 
   </ul>
 </div>
 
-<div class="col-6">
+<div class="col-6" style="margin-right:0">
 <h3>Develop on Virtual Devices</h3>
   <ul>
     <li>Emulate any device. Use custom screen sizes, keyboards, and other hardware components. </li>
     <li>Advanced hardware emulation, including camera, sensors, multitouch, telephony.</li>
-    <li>Develop and test for broadest compatibility at lowest cost.</li>
+    <li>Develop and test for broad device compatibility.</li>
   </ul>
 
 </div>
 
 <div style="margin-top:20px;"></div>
 
-<div class="col-5">
+<div class="col-7" style="margin-left:0">
 <h3>Powerful Debugging</h3>
 
   <ul>
-    <li>Full Java debugger with on-device debugging and Android-specific tools</li>
+    <li>Full Java debugger with on-device debugging and Android-specific tools.</li>
     <li>Built-in memory analysis, performance/CPU profiling, OpenGL ES tracing.</li>
     <li>Graphical tools for debugging and optimizing UI, runtime inspecton of UI structure and performance.</li>
-    <li>Runtime graphical analysis of your app's network bandwidth usage.</li> 
+    <li>Runtime graphical analysis of your app's network bandwidth usage.</li>
   </ul>
-</div>
 
-<div style="float:right;width:360px;padding-top:1em;">
-  <img src="{@docRoot}images/debugging-tall.png" align="left">
-</div>
-
-
-<div class="col-6">
 <h3>Testing</h3>
     
   <ul>
@@ -95,3 +115,8 @@
   </ul>
 </div>
 
+<div class="col-6" style="margin-right:0">
+  <img src="{@docRoot}images/debugging-tall.png" align="left" style="margin-top:10px">
+</div>
+
+
diff --git a/docs/html/tools/testing/testing_ui.jd b/docs/html/tools/testing/testing_ui.jd
new file mode 100644
index 0000000..8349d5c
--- /dev/null
+++ b/docs/html/tools/testing/testing_ui.jd
@@ -0,0 +1,356 @@
+page.title=UI Testing
+parent.title=Testing
+parent.link=index.html
+@jd:body
+
+<div id="qv-wrapper">
+  <div id="qv">
+     <h2>In this document</h2>
+  <ol>
+     <li><a href="#overview">Overview</a></li>
+        <ul>
+        <li><a href="#workflow">Workflow</a></li>
+        </ul>
+     <li><a href="#uianalysis">Analyzing Your UI</a></li>
+     <li><a href="#prepare">Preparing to Test</a>
+        <ul>
+        <LI><a href="#loading">Load the App</a></LI>
+        <LI><a href="#identifyUI">Identify UI Components</a></LI>
+        <LI><a href="#accessibility">Ensure Accessibility</a></LI>
+        <LI><a href="#configure">Configure Development Environment</a></LI>
+        </ul>
+     </li>
+     <li><a href="#creating">Creating Tests</a>
+       <ul>
+       <LI><a href="#classes">uiautomator API</a></LI>
+        <li><a href="#sample">Sample Test Case</a>
+       </ul>
+     </li>
+     <li><a href="#builddeploy">Building and Deploying Tests</a></li>
+     <li><a href="#running">Running Tests</a></li>
+     <li><a href="#bestpractices">Best Practices</a></li>
+  </ol>
+     <h2>Key classes</h2>
+    <ol>
+      <li><a href="{@docRoot}tools/help/uiautomator/IAutomationSupport.html">IAutomationSupport</a></li>
+      <li><a href="{@docRoot}tools/help/uiautomator/UiAutomatorTestCase.html">UiAutomatorTestCase</a></li>
+      <li><a href="{@docRoot}tools/help/uiautomator/UiCollection.html">UiCollection</a></li>
+      <li><a href="{@docRoot}tools/help/uiautomator/UiDevice.html">UiDevice</a></li>
+      <li><a href="{@docRoot}tools/help/uiautomator/UiObject.html">UiObject</a></li>
+      <li><a href="{@docRoot}tools/help/uiautomator/UiScrollable.html">UiScrollable</a></li>
+      <li><a href="{@docRoot}tools/help/uiautomator/UiSelector.html">UiSelector</a></li>
+    </ol>
+    <h2>See Also</h2>
+      <ol>
+        <li>
+            <a href="{@docRoot}tools/help/uiautomator/index.html">uiautomator (reference)</a>
+        </li>
+      </ol>
+  </div>
+</div>
+
+<p>
+In addition to unit testing the individual components that make up your Android application (such as activities, services, and content providers), it is also important that you test the behavior of your application’s user interface (UI) when it is running on a device. UI testing ensures that your application returns the correct UI output in response to a sequence of user actions on a device, such as entering keyboard input or pressing toolbars, menus, dialogs, images, and other UI controls.
+</p>
+<p>
+Functional or black-box UI testing does not require testers to know the internal implementation details of the app, only its expected output when a user performs a specific action or enters a specific input. This approach allows for better separation of development and testing roles in your organization.
+</p>
+<p>One common approach to UI testing is to run tests manually and verify that the app is behaving as expected. However, this approach can be time-consuming, tedious, and error-prone. A more efficient and reliable approach is to automate the UI testing with a software testing framework. Automated testing involves creating programs to perform testing tasks (test cases) to cover specific usage scenarios, and then using the testing framework to run the test cases automatically and in a repeatable manner.</p>
+
+<h2 id="overview">Overview</h2>
+<p>The Android SDK provides the following tools to support automated, functional UI testing on your application:
+<ul>
+<LI>{@code uiautomatorviewer} - A GUI tool to scan and analyze the UI components of an Android application.</LI>
+<LI>{@code uiautomator} - A Java library containing APIs to create customized functional UI tests, and an execution engine to automate and run the tests.</LI>
+</ul></p>
+
+<p>To use these tools, you must have the following versions of the Android development tools installed:
+<ul>
+<LI>Android SDK Tools, Revision 21 or higher</LI>
+<LI>Android SDK Platform, API 16 or higher</LI>
+</ul>
+</p>
+
+<h3 id="workflow">Workflow for the the uiautomator testing framework</h3>
+<p>Here's a short overview of the steps required to automate UI testing:
+<ol>
+<LI>Prepare to test by installing the app on a test device, analyzing the app’s UI components, and ensuring that your application is accessible by the test automation framework.</LI>
+<li>Create automated tests to simulate specific user interactions on your application.</li>
+<li>Compile your test cases into a JAR file and install it on your test device along with your app.</li>
+<li>Run the tests and view the test results.</li>
+<li>Correct any bugs or defects discovered in testing.</li>
+</ol>
+</p>
+
+<h2 id="uianalysis">Analyzing Your Application's UI</h2>
+<p>Before you start writing your test cases, it's helpful to familiarize yourself with the UI components (including the views and controls) of the targeted application. You can use the {@code uiautomatorviewer} tool to take a snapshot of the foreground UI screen on any Android device that is connected to your development machine.  The {@code uiautomatorviewer} tool provides a convenient visual interface to inspect the layout hierarchy and view the properties of the individual UI components that are displayed on the test device.  Using this information, you can later create {@code uiautomator} tests with selector objects that target specific UI components to test.</p>
+
+<a href="{@docRoot}images/testing/UIAutomatorViewer.png">
+    <img src="{@docRoot}images/testing/UIAutomatorViewer.png"
+         alt="User interface of uiautomatorviewer tool" height="327px" id="figure1"/>
+</a>
+<p class="img-caption">
+    <strong>Figure 1.</strong> The {@code uiautomatorviewer} showing the captured interface of a test deviice.
+</p>
+
+<p>To analyze the UI components of the application that you want to test:</p>
+<ol>
+<li>Connect your Android device to your development machine.</li>
+<li>Open a terminal window and navigate to {@code &lt;android-sdk&gt;/tools/}.</li>
+<LI>Run the tool with this command:<pre>$ uiautomatorviewer</pre></LI>
+<li><p>To capture a screen for analysis, click the <strong>Device Screenshot</strong> button in the GUI of the {@code uiautomatorviewer} tool.</p>
+<p class="note"><strong>Note: </strong>If you have more than one device connected, specify the device for screen capture by setting the {@code ANDROID_SERIAL} environment variable:  
+   <ol type="a">
+   <li>Find the serial numbers for your connected devices by running this command:<pre>$ adb devices</pre> </li>
+   <li>Set the {@code ANDROID_SERIAL}  environment variable to select the device to test:
+      <ul>
+      <li>In Windows: <pre>set ANDROID_SERIAL=&lt;device serial number&gt;</pre></li>
+      <li>In UNIX: <pre>export ANDROID_SERIAL=&lt;device serial number&gt;</pre></li>
+      </ul>
+   </li>
+   </ol>
+If you are connected to only a single device, you do not need to set the ANDROID_SERIAL environment variable.</p>
+</li>
+<li>View the UI properties for your application:
+  <ul>
+  <LI>Hover over the snapshot in the left-hand panel to see the UI components identified by the {@code uiautomatorviewer} tool. You can view the component’s properties listed in the lower right-hand panel, and the layout hierarchy in the upper right-hand panel.</LI>
+  <li>Optionally, click on the <strong>Toggle NAF Nodes</strong> button to see UI components that are not accessible to the {@code uiautomator} testing framework. Only limited information may be available for these components.</li>
+  </ul>
+</li>
+</ol>
+
+<h2 id="prepare">Preparing to Test</h2>
+<p>Before using the {@code uiautomator} testing framework, complete these pre-flight tasks:
+</p>
+<h3 id="loading">Load the application to a device</h3>
+<p>If you are reading this document, chances are that the Android application that you want to test has not been published yet. If you have a copy of the APK file, you can install the APK onto a test device by using the {@code adb} tool. To learn how to install an APK file using the {@code adb} tool, see the <a href="@docRoot}/tools/help/adb.html#move">{@code adb}</a> documentation. </p>
+
+<h3 id="identifyUI">Identify the application’s UI components</h3>
+<p>Before writing your {@code uiautomator} tests, first identify the UI components in the application that you want to test. Typically, good candidates for testing are UI components that are visible and that users can interact with. The UI components should also have visible text labels, <a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">{@code android:contentDescription}</a> values, or both. 
+
+<p>You can inspect the visible screen objects in an application conveniently by using the {@code uiautomatorviewer} tool. For more information about how to analyze an application screen with this tool, see the section <a href="#uianalaysis">Analyzing Your Application’s UI</a>.  For more information about the common types of UI components provided by Android, see <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a>.</p>
+
+<h3 id="accessibility">Ensure that the application is accessible</h3>
+<p>This step is required because the {@code uiautomator} tool depends on the accessibility features of the Android framework to execute your functional UI tests. You should include these minimum optimizations to support the {@code uiautomator} tool:
+<ul>
+<LI>Use the <a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">{@code android:contentDescription}</a> attribute to label the {@link android.widget.ImageButton}, {@link android.widget.ImageView}, {@link android.widget.CheckBox} and other user interface controls.</LI>
+<li>Provide an {@code <a href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">android:hint</a>}  attribute <em>instead</em> of a content description for {@link android.widget.EditText} fields</li>
+<li>Associate an <a href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">android:hint</a> attribute with any graphical icons used by controls that provide feedback to the user (for example, status or state information).</li>
+<li>Make sure that all the user interface elements are accessible with a directional controller, such as a trackball or D-pad.</li>
+<li>Use the {@code uiautomatorviewer} tool to ensure that the UI component is accessible to the testing framework. You can also test the application by turning on accessibility services like TalkBack and Explore by Touch, and try using your application using only directional controls. </li>
+</ul>
+</p>
+
+<p>For more information about implementing and testing accessibility, see <a href="{@docRoot}/guide/topics/ui/accessibility/apps.html">Making Applications Accessible</a>.</p>
+
+<p class="note"><strong>Note: </strong>To identify the non-accessible components in the UI, click on the <strong>Toggle NAF Nodes</strong> option in the {@code uiautomatorviewer} tool.</p>
+
+<p>Generally, Android application developers get accessibility support for free, courtesy of the {@link android.view.View} and {@link android.view.ViewGroup} classes. However, some applications use custom view components to provide a richer user experience. Such custom components won't get the accessibility support that is provided by the standard Android UI components. If this applies to your application, ensure that the application developer exposes the custom drawn UI components to Android accessibility services, by implementing the {@link android.view.accessibility.AccessibilityNodeProvider} class. For more information about making custom view components accessible, see <a href="{@docRoot}/guide/topics/ui/accessibility/apps.html#custom-views">Making Applications Accessible</a>.</p>
+
+<h3 id="configure">Configure your development environment</h3>
+<p>If you're developing in Eclipse, the Android SDK provides additional tools that help you write test cases using {@code uiautomator} and buiild your JAR file. In order to set up Eclipse to assist you, you need to create a project that includes the {@code uiautomator} client library, along with the Android SDK library. To configure Eclipse:</p>
+<ol>
+<li>Create a new Java project in Eclipse, and give your project a name that is relevant to the tests you’re about to create (for example, "MyAppNameTests"). In the project, you will create the test cases that are specific to the application that you want to test.</li>
+<li>From the <strong>Project Explorer</strong>, right-click on the new project that you created, then select <strong>Properties > Java Build Path</strong>, and do the following:
+  <ol type="a">
+  <LI>Click <strong>Add Library > JUnit</strong> then select <strong>JUnit3</strong> to add JUnit support.</LI>
+  <li>Click <strong>Add External JARs...</strong> and navigate to the SDK directory. Under the platforms directory, select the latest SDK version and add both the {@code uiautomator.jar} and {@code android.jar} files.</li>
+  </ol>
+</li>
+</ol>
+<p>If you did not configure Eclipse as your development environment, make sure that the {@code uiautomator.jar} and {@code android.jar} files from the {@code &lt;android-sdk&gt;/platforms/&lt;sdk&gt;} directory are in your Java class path.</p>
+<p>Once you have completed these prerequisite tasks, you're almost ready to start creating your {@code uiautomator} tests. </li>
+
+<h2 id="creating">Creating uiautomator Tests</h2>
+<p>To build a test that runs in the {@code uiautomator} framework, create a test case that extends the <a href="{@docRoot}tools/help/uiautomator/UiAutomatorTestCase.html">{@code UiAutomatorTestCase}</a> class. In Eclipse, the test case file goes under the {@code src} directory in your project.  Later, you will build the test case as a JAR file, then copy this file to the test device. The test JAR file is not an APK file and resides separately from the application that you want to test on the device.</p>
+
+<p>Because the <a href="{@docRoot}tools/help/uiautomator/UiAutomatorTestCase.html">{@code UiAutomatorTestCase}</a> class extends {@code junit.framework.TestCase}, you can use the JUnit {@code Assert} class to test that UI components in the app return the expected results. To learn more about JUnit, you can read the documentation on the <a href="http://www.junit.org/">junit.org</a> home page.</p>
+
+<p>The first thing your test case should do is access the device that contains the target app. It’s also good practice to start the test from the Home screen of the device. From the Home screen (or some other starting location you’ve chosen in the target app), you can use the classes provided by the {@code uiautomator} API to simulate user actions and to test specific UI components. For an example of how to put together a {@code uiautomator} test case, see the <a href="#sample">sample test case</a>.</p>
+
+<h3 id="classes">uiautomator API</h3>
+<p>The {@code uiautomator} API is bundled in the {@code uiautomator.jar} file under the {@code &lt;android-sdk&gt;/platforms/} directory.  The API includes these key classes that allow you to capture and manipulate UI components on the target app:</p>
+<dl>
+<DT><a href="{@docRoot}tools/help/uiautomator/UiDevice.html">{@code UiDevice}</a></DT>
+<dd><p>Represents the device state.  In your tests, you can call methods on the <a href="{@docRoot}tools/help/uiautomator/UiDevice.html">{@code UiDevice}</a> instance to check for the state of various properties, such as current orientation or display size. Your tests also can use the <a href="{@docRoot}tools/help/uiautomator/UiDevice.html">{@code UiDevice}</a> instance to perform device level actions, such as forcing the device into a specific rotation, pressing the d-pad hardware button, or pressing the Home and Menu buttons.</p>
+<p>To get an instance of <a href="{@docRoot}tools/help/UiDevice.html">{@code UiDevice}</a> and simulate a Home button press:
+<pre>
+getUiDevice().pressHome();
+</pre></p></dd>
+
+<dt><a href="{@docRoot}tools/help/uiautomator/UiSelector.html">{@code UiSelector}</a></dt>
+<dd>Represents a search criteria to query and get a handle on specific elements in the currently displayed UI. 	
+If more than one matching element is found, the first matching element in the layout hierarchy is returned as the target {@code UiObject}.  When constructing a <a href="{@docRoot}tools/help/uiautomator/UiSelector.html">{@code UiSelector}</a>, you can chain together multiple properties to refine your search. If no matching UI element is found, a <a href="{@docRoot}tools/help/uiautomator/UiAutomatorObjectNotFoundException.html">{@code UiAutomatorObjectNotFoundException}</a> is thrown. You can use the <a href="{@docRoot}tools/help/uiautomator/UiSelector.html#childSelector(com.android.uiautomator.core.UiSelector)">{@code childSelector()}</a> method to nest multiple <a href="{@docRoot}tools/help/uiautomator/UiSelector.html">{@code UiSelector}</a> instances. For example, the following code example shows how to specify a search to find the first {@link android.widget.ListView} in the currently displayed UI, then search within that {@link android.widget.ListView} to find a UI element with the text property {@code Apps}.
+<pre>
+UiObject appItem = new UiObject(new UiSelector()
+   .className("android.widget.ListView").instance(1)
+   .childSelector(new UiSelector().text("Apps")));
+</pre>
+</dd>
+
+<dt><a href="{@docRoot}tools/help/uiautomator/UiObject.html">{@code UiObject}</a></dt>
+<dd>Represents a UI element. To create a <a href="{@docRoot}tools/help/uiautomator/UiObject.html">{@code UiObject}</a> instance, use a {@code UiSelector} that describes how to search for, or select, the UI element.
+<p>The following code example shows how to construct <a href="{@docRoot}tools/help/uiautomator/UiObject.html">{@code UiObject}</a> instances that represent a <strong>Cancel</strong> button and a <strong>OK</strong> button in your application.</p>
+<pre>
+UiObject cancelButton = new UiObject(new UiSelector().text("Cancel"));
+UiObject okButton = new UiObject(new UiSelector().text("OK"));
+</pre>
+<p>You can reuse the <a href="{@docRoot}tools/help/uiautomator/UiObject.html">{@code UiObject}</a> instances that you have created in other parts of your app testing, as needed.  Note that the {@code uiautomator} test framework searches the current display for a match every time your test uses a <a href="{@docRoot}tools/help/uiautomator/UiObject.html">{@code UiObject}</a> instance to click on a UI element or query a property.</p>
+<p>In the following code example, the {@code uiautomator} test framework searches for a UI element with the text property {@code OK}. If a match is found and if the element is enabled, the framework simulates a user click action on the element.</p>
+<pre>
+if(okButton.exists() && okButton.isEnabled()) 
+{
+  okButton.click();
+}
+</pre>
+<p>You can also restrict the search to find only elements of a specific class. For example, to find matches of the {@link android.widget.Button} class:</p>
+<pre>
+UiObject cancelButton = new UiObject(new UiSelector().text("Cancel")
+   .className("android.widget.Button"));
+UiObject okButton = new UiObject(new UiSelector().text("OK")
+   .className("android.widget.Button"));
+</pre>
+</dd>
+
+<dt><a href="{@docRoot}tools/help/uiautomator/UiCollection.html">{@code UiCollection}</a></dt>
+<dd>Represents a collection of items, for example songs in a music album or a list of emails in an inbox. Similar to a <a href="{@docRoot}tools/help/uiautomator/UiObject.html">{@code UiObject}</a>, you construct a <a href="{@docRoot}tools/help/uiautomator/UiCollection.html">{@code UiCollection}</a> instance by specifying a <a href="{@docRoot}tools/help/UiSelector.html">{@code UiSelector}</a>. The <a href="{@docRoot}tools/help/uiautomator/UiSelector.html">{@code UiSelector}</a> for a <a href="{@docRoot}tools/help/uiautomator/UiCollection.html">{@code UiCollection}</a> should search for a UI element that is a container or wrapper of other child UI elements (such as  a layout view that contains child UI elements).  For example, the following code snippet  shows how to construct a <a href="{@docRoot}tools/help/uiautomator/UiCollection.html">{@code UiCollection}</a> to represent a video album that is displayed within a {@link android.widget.FrameLayout}:
+<pre>
+UiCollection videos = new UiCollection(new UiSelector()
+   .className("android.widget.FrameLayout"));
+</pre>
+<p>If the videos are listed within a {@link android.widget.LinearLayout} view, and you want to to retrieve the number of videos in this collection:</p>
+<pre>
+int count = videos.getChildCount(new UiSelector()
+   .className("android.widget.LinearLayout"));
+</pre>
+<p>If you want to find a specific video that is labeled with the text element {@code Cute Baby Laughing} from the collection and simulate a user-click on the video:</p>
+<pre>
+UiObject video = videos.getChildByText(new UiSelector()
+   .className("android.widget.LinearLayout"), "Cute Baby Laughing");
+video.click();
+</pre>
+<p>Similarly, you can simulate other user actions on the UI object.  For example, if you want 
+to simulate selecting a checkbox that is associated with the video:</p>
+<pre>
+UiObject checkBox = video.getChild(new UiSelector()
+   .className("android.widget.Checkbox"));
+if(!checkBox.isSelected()) checkbox.click();
+</pre>
+</dd>
+
+<dt><a href="{@docRoot}tools/help/uiautomator/UiScrollable.html">{@code UiScrollable}</a></dt>
+<dd>Represents a scrollable collection of UI elements.  You can use the <a href="{@docRoot}tools/help/uiautomator/UiScrollable.html">{@code UiScrollable}</a> class to simulate vertical or horizontal scrolling across a display. This technique is helpful when a UI element is positioned off-screen and you need to scroll to bring it into view.
+<p>For example, the following code shows how to simulate scrolling down the Settings menu and clicking on an <strong>About tablet</strong> option:</p>
+<pre>
+UiScrollable settingsItem = new UiScrollable(new UiSelector()
+   .className("android.widget.ListView"));
+UiObject about = settingsItem.getChildByText(new UiSelector()
+   .className("android.widget.LinearLayout"), "About  tablet");
+about.click()
+</pre>
+</dd>
+</dl>
+<p>For more information about these APIs, see the <a href="{@docRoot}tools/help/uiautomator/index.html">{@code uiautomator}</a> reference.</p>
+
+<h3 id="sample">A sample uiautomator test case</h3>
+<p>The following code example shows a simple test case which simulates a user bringing up the Settings app in a stock Android device.  The test case mimics all the steps that a user would typically take to perform this task, including opening the Home screen, launching the <strong>All Apps</strong> screen, scrolling to the <strong>Settings</strong> app icon, and clicking on the icon to enter the Settings app.</p>
+<pre>
+package com.uia.example.my;
+
+// Import the uiautomator libraries
+import com.android.uiautomator.core.UiObject;
+import com.android.uiautomator.core.UiObjectNotFoundException;
+import com.android.uiautomator.core.UiScrollable;
+import com.android.uiautomator.core.UiSelector;
+import com.android.uiautomator.testrunner.UiAutomatorTestCase;
+
+public class LaunchSettings extends UiAutomatorTestCase {   
+
+   public void testDemo() throws UiObjectNotFoundException {   
+      
+      // Simulate a short press on the HOME button.
+      getUiDevice().pressHome();
+      
+      // We’re now in the home screen. Next, we want to simulate 
+      // a user bringing up the All Apps screen.
+      // If you use the uiautomatorviewer tool to capture a snapshot 
+      // of the Home screen, notice that the All Apps button’s 
+      // content-description property has the value “Apps”.  We can 
+      // use this property to create a UiSelector to find the button. 
+      UiObject allAppsButton = new UiObject(new UiSelector()
+         .description("Apps"));
+      
+      // Simulate a click to bring up the All Apps screen.
+      allAppsButton.clickAndWaitForNewWindow();
+      
+      // In the All Apps screen, the Settings app is located in 
+      // the Apps tab. To simulate the user bringing up the Apps tab,
+      // we create a UiSelector to find a tab with the text 
+      // label “Apps”.
+      UiObject appsTab = new UiObject(new UiSelector()
+         .text("Apps"));
+      
+      // Simulate a click to enter the Apps tab.
+      appsTab.click();
+
+      // Next, in the apps tabs, we can simulate a user swiping until
+      // they come to the Settings app icon.  Since the container view 
+      // is scrollable, we can use a UiScrollable object.
+      UiScrollable appViews = new UiScrollable(new UiSelector()
+         .scrollable(true));
+      
+      // Set the swiping mode to horizontal (the default is vertical)
+      appViews.setAsHorizontalList();
+      
+      // Create a UiSelector to find the Settings app and simulate      
+      // a user click to launch the app. 
+      UiObject settingsApp = appViews.getChildByText(new UiSelector()
+         .className(android.widget.TextView.class.getName()), 
+         "Settings");
+      settingsApp.clickAndWaitForNewWindow();
+      
+      // Validate that the package name is the expected one
+      UiObject settingsValidation = new UiObject(new UiSelector()
+         .packageName("com.android.settings"));
+      assertTrue("Unable to detect Settings", 
+         settingsValidation.exists());   
+  }   
+}
+</pre>
+
+<h2 id="builddeploy">Building and Deploying Your uiautomator Tests</h2>
+<p>Once you have coded your test, follow these steps to build and deploy your test JAR to your target Android test device:</p>
+<ol>
+<li>Create the required build configuration files to build the output JAR. To generate the build configuration files, open a terminal and run the following command:
+<pre>&lt;android-sdk&gt;/tools/android uitest-project -n &lt;name&gt; -t 1 -p &lt;path&gt;</pre>
+The {@code &lt;name&gt;} is the name of the project that contains your {@code uiautomator} test source files, and the {@code &lt;path&gt;} is the path to the corresponding project directory. 
+</li>
+<LI>From the command line, set the {@code ANDROID_HOME} variable: 
+<ul>
+<li>In Windows: 
+<pre>set ANDROID_HOME=&lt;path_to_your_sdk&gt;</pre>
+</li>
+<li>In UNIX: 
+<pre>export ANDROID_HOME=&lt;path_to_your_sdk&gt;</pre>
+</li>
+</ul>
+</LI>
+<li>Go to the project directory where your {@code build.xml} file is located and build your test JAR. <pre>ant build</pre></li>
+<li>Deploy your generated test JAR file to the test device by using the {@code adb push} command: <pre>adb push &lt;path_to_output_jar&gt; /data/local/tmp/</pre>
+<p>Here’s an example: <pre>adb push ~/dev/workspace/LaunchSettings/bin/LaunchSettings.jar /data/local/tmp/</pre></p>
+</li>
+</ol>
+
+<h2 id="running">Running uiautomator Tests</h2>
+<p>Here’s an example of how to run a test that is implemented in the {@code LaunchSettings.jar} file. The tests are bundled in the {@code com.uia.example.my} package:</p>
+<pre>adb shell uiautomator runtest LaunchSettings.jar -c com.uia.example.my.LaunchSettings</pre>
+<p>To learn more about the syntax, subcommands, and options for {@code uiautomator}, see the <a href="{@docRoot}tools/help/uiautomator/index.html">{@code uiautomator}</a> reference.</p>
+
+
+<h2 id="bestpractices">Best Practices</h2>
+<p>Here are some best practices for functional UI testing with the {@code uiautomator} framework: </p>
+<ul>
+<LI>Ensure that you validate the same UI functions on your application across the various types of devices that your application might run on (for example, devices with different screen densities).</LI>
+<li>You should also test your UI against common scenarios such as in-coming phone calls, network interruptions, and user-initiated switching to other applications on the device.</li>
+</ul>
+
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index 6e58100..3c8732f 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -93,6 +93,10 @@
             <a href="<?cs var:toroot?>tools/testing/testing_accessibility.html">
             <span class="en">Accessibility Testing</span></a>
           </li>
+           <li>
+            <a href="<?cs var:toroot?>tools/testing/testing_ui.html">
+            <span class="en">UI Testing</span></a>
+          </li>
           <li>
             <a href="<?cs var:toroot ?>tools/testing/what_to_test.html">
             <span class="en">What To Test</span></a>
@@ -166,6 +170,20 @@
        <li><a href="<?cs var:toroot ?>tools/help/systrace.html">Systrace</a></li>
        <li><a href="<?cs var:toroot ?>tools/help/gltracer.html">Tracer for OpenGL ES</a></li>
        <li><a href="<?cs var:toroot ?>tools/help/traceview.html">Traceview</a></li>
+       <li class="nav-section">
+          <div class="nav-section-header"><a href="<?cs var:toroot ?>tools/help/uiautomator/index.html"><span class="en">uiautomator</span></a></div>
+          <ul>
+             <li><a href="<?cs var:toroot ?>tools/help/uiautomator/IAutomationSupport.html"><span class="en">IAutomationSupport</span></a></li>
+             <li><a href="<?cs var:toroot ?>tools/help/uiautomator/UiAutomatorTestCase.html"><span class="en">UiAutomatorTestCase</span></a></li>
+             <li><a href="<?cs var:toroot ?>tools/help/uiautomator/UiCollection.html"><span class="en">UiCollection</span></a></li>
+             <li><a href="<?cs var:toroot ?>tools/help/uiautomator/UiDevice.html"><span class="en">UiDevice</span></a></li>
+             <li><a href="<?cs var:toroot ?>tools/help/uiautomator/UiObject.html"><span class="en">UiObject</span></a></li>
+             <li><a href="<?cs var:toroot ?>tools/help/uiautomator/UiObjectNotFoundException.html"><span class="en">UiObjectNotFoundException</span></a></li>
+             <li><a href="<?cs var:toroot ?>tools/help/uiautomator/UiScrollable.html"><span class="en">UiScrollable</span></a></li>
+             <li><a href="<?cs var:toroot ?>tools/help/uiautomator/UiSelector.html"><span class="en">UiSelector</span></a></li>
+             <li><a href="<?cs var:toroot ?>tools/help/uiautomator/UiWatcher.html"><span class="en">UiWatcher</span></a></li>
+          </ul>
+       </li>
        <li><a href="<?cs var:toroot ?>tools/help/zipalign.html">zipalign</a></li>
     </ul>
   </li>
diff --git a/docs/html/training/basics/firstapp/running-app.jd b/docs/html/training/basics/firstapp/running-app.jd
index 0c428e7..80603b2 100644
--- a/docs/html/training/basics/firstapp/running-app.jd
+++ b/docs/html/training/basics/firstapp/running-app.jd
@@ -40,7 +40,7 @@
 immediately run the app.</p>
 
 <p>How you run your app depends on two things: whether you have a real Android-powered device and
-whether you’re using Eclipse. This lesson shows you how to install and run your app on a
+whether you're using Eclipse. This lesson shows you how to install and run your app on a
 real device and on the Android emulator, and in both cases with either Eclipse or the command line
 tools.</p>
 
@@ -85,12 +85,21 @@
 
 <ol>
   <li>Plug in your device to your development machine with a USB cable.
-If you’re developing on Windows, you might need to install the appropriate USB driver for your
+If you're developing on Windows, you might need to install the appropriate USB driver for your
 device. For help installing drivers, see the <a href="{@docRoot}tools/extras/oem-usb.html">OEM USB
-Drivers</a> document.</li>
-  <li>Ensure that <strong>USB debugging</strong> is enabled in the device Settings (open Settings
-and navitage to <strong>Applications > Development</strong> on most devices, or click
-<strong>Developer options</strong> on Android 4.0 and higher).</li>
+Drivers</a> document.</li>  
+  <li>Enable <strong>USB debugging</strong> on your device.
+    <ul>
+      <li>On most devices running Android 3.2 or older, you can find the option under
+        <strong>Settings > Applications > Development</strong>.</li>
+      <li>On Android 4.0 and newer, it's in <strong>Settings > Developer options</strong>.
+        <p class="note"><strong>Note:</strong> On Android 4.2 and newer, <strong>Developer
+        options</strong> is hidden by default. To make it available, go
+        to <strong>Settings > About phone</strong> and tap <strong>Build number</strong>
+        seven times. Return to the previous screen to find <strong>Developer options</strong>.</p>
+      </li>
+    </ul>
+  </li>
 </ol>
 
 <p>To run the app from Eclipse, open one of your project's files and click
@@ -118,7 +127,7 @@
 
 <h2 id="Emulator">Run on the Emulator</h2>
 
-<p>Whether you’re using Eclipse or the command line, to run your app on the emulator you need to
+<p>Whether you're using Eclipse or the command line, to run your app on the emulator you need to
 first create an <a href="{@docRoot}tools/devices/index.html">Android Virtual Device</a> (AVD). An
 AVD is a device configuration for the Android emulator that allows you to model different
 devices.</p>
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java
index 4b51994..2907f10 100755
--- a/drm/java/android/drm/DrmManagerClient.java
+++ b/drm/java/android/drm/DrmManagerClient.java
@@ -29,6 +29,9 @@
 import android.provider.MediaStore;
 import android.util.Log;
 
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -582,7 +585,28 @@
         if (null == path || path.equals("")) {
             throw new IllegalArgumentException("Given path should be non null");
         }
-        return _getOriginalMimeType(mUniqueId, path);
+
+        String mime = null;
+
+        FileInputStream is = null;
+        try {
+            FileDescriptor fd = null;
+            File file = new File(path);
+            if (file.exists()) {
+                is = new FileInputStream(file);
+                fd = is.getFD();
+            }
+            mime = _getOriginalMimeType(mUniqueId, path, fd);
+        } catch (IOException ioe) {
+        } finally {
+            if (is != null) {
+                try {
+                    is.close();
+                } catch(IOException e) {}
+            }
+        }
+
+        return mime;
     }
 
     /**
@@ -848,7 +872,7 @@
 
     private native int _getDrmObjectType(int uniqueId, String path, String mimeType);
 
-    private native String _getOriginalMimeType(int uniqueId, String path);
+    private native String _getOriginalMimeType(int uniqueId, String path, FileDescriptor fd);
 
     private native int _checkRightsStatus(int uniqueId, String path, int action);
 
diff --git a/drm/jni/android_drm_DrmManagerClient.cpp b/drm/jni/android_drm_DrmManagerClient.cpp
index fb685a2..baddf62 100644
--- a/drm/jni/android_drm_DrmManagerClient.cpp
+++ b/drm/jni/android_drm_DrmManagerClient.cpp
@@ -587,22 +587,28 @@
 }
 
 static jstring android_drm_DrmManagerClient_getOriginalMimeType(
-            JNIEnv* env, jobject thiz, jint uniqueId, jstring path) {
+            JNIEnv* env, jobject thiz, jint uniqueId, jstring path, jobject fileDescriptor) {
     ALOGV("getOriginalMimeType Enter");
+
+    int fd = (fileDescriptor == NULL)
+                ? -1
+                : jniGetFDFromFileDescriptor(env, fileDescriptor);
+
     String8 mimeType
         = getDrmManagerClientImpl(env, thiz)
-            ->getOriginalMimeType(uniqueId, Utility::getStringValue(env, path));
+            ->getOriginalMimeType(uniqueId,
+                                  Utility::getStringValue(env, path), fd);
     ALOGV("getOriginalMimeType Exit");
     return env->NewStringUTF(mimeType.string());
 }
 
 static jint android_drm_DrmManagerClient_checkRightsStatus(
             JNIEnv* env, jobject thiz, jint uniqueId, jstring path, int action) {
-    ALOGV("getOriginalMimeType Enter");
+    ALOGV("checkRightsStatus Enter");
     int rightsStatus
         = getDrmManagerClientImpl(env, thiz)
             ->checkRightsStatus(uniqueId, Utility::getStringValue(env, path), action);
-    ALOGV("getOriginalMimeType Exit");
+    ALOGV("checkRightsStatus Exit");
     return rightsStatus;
 }
 
@@ -730,7 +736,7 @@
     {"_getDrmObjectType", "(ILjava/lang/String;Ljava/lang/String;)I",
                                     (void*)android_drm_DrmManagerClient_getDrmObjectType},
 
-    {"_getOriginalMimeType", "(ILjava/lang/String;)Ljava/lang/String;",
+    {"_getOriginalMimeType", "(ILjava/lang/String;Ljava/io/FileDescriptor;)Ljava/lang/String;",
                                     (void*)android_drm_DrmManagerClient_getOriginalMimeType},
 
     {"_checkRightsStatus", "(ILjava/lang/String;I)I",
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index c726d0e..688fd7a 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -27,7 +27,6 @@
 import java.nio.ShortBuffer;
 
 public final class Bitmap implements Parcelable {
-
     /**
      * Indicates that the bitmap was created for an unknown pixel density.
      *
@@ -64,7 +63,7 @@
     private boolean mRecycled;
 
     // Package-scoped for fast access.
-    /*package*/ int mDensity = sDefaultDensity = getDefaultDensity();
+    int mDensity = getDefaultDensity();
 
     private static volatile Matrix sScaleMatrix;
 
@@ -78,15 +77,15 @@
     public static void setDefaultDensity(int density) {
         sDefaultDensity = density;
     }
-    
-    /*package*/ static int getDefaultDensity() {
+
+    static int getDefaultDensity() {
         if (sDefaultDensity >= 0) {
             return sDefaultDensity;
         }
         sDefaultDensity = DisplayMetrics.DENSITY_DEVICE;
         return sDefaultDensity;
     }
-    
+
     /**
      * @noinspection UnusedDeclaration
      */
@@ -95,7 +94,7 @@
 
         This can be called from JNI code.
     */
-    /*package*/ Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
+    Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
             int density) {
         this(nativeBitmap, buffer, isMutable, ninePatchChunk, null, density);
     }
@@ -108,7 +107,7 @@
 
         This can be called from JNI code.
     */
-    /*package*/ Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
+    Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
             int[] layoutBounds, int density) {
         if (nativeBitmap == 0) {
             throw new RuntimeException("internal error: native bitmap is 0");
@@ -202,9 +201,14 @@
      */
     public void recycle() {
         if (!mRecycled) {
-            mBuffer = null;
-            nativeRecycle(mNativeBitmap);
-            mNinePatchChunk = null;
+            if (nativeRecycle(mNativeBitmap)) {
+                // return value indicates whether native pixel object was actually recycled.
+                // false indicates that it is still in use at the native level and these
+                // objects should not be collected now. They will be collected later when the
+                // Bitmap itself is collected.
+                mBuffer = null;
+                mNinePatchChunk = null;
+            }
             mRecycled = true;
         }
     }
@@ -347,11 +351,15 @@
     }
 
     /**
-     * Copy the bitmap's pixels into the specified buffer (allocated by the
+     * <p>Copy the bitmap's pixels into the specified buffer (allocated by the
      * caller). An exception is thrown if the buffer is not large enough to
      * hold all of the pixels (taking into account the number of bytes per
      * pixel) or if the Buffer subclass is not one of the support types
-     * (ByteBuffer, ShortBuffer, IntBuffer).
+     * (ByteBuffer, ShortBuffer, IntBuffer).</p>
+     * <p>The content of the bitmap is copied into the buffer as-is. This means
+     * that if this bitmap stores its pixels pre-multiplied
+     * (see {@link #isPremultiplied()}, the values in the buffer will also be
+     * pre-multiplied.</p>
      */
     public void copyPixelsToBuffer(Buffer dst) {
         int elements = dst.remaining();
@@ -382,10 +390,10 @@
     }
 
     /**
-     * Copy the pixels from the buffer, beginning at the current position,
+     * <p>Copy the pixels from the buffer, beginning at the current position,
      * overwriting the bitmap's pixels. The data in the buffer is not changed
      * in any way (unlike setPixels(), which converts from unpremultipled 32bit
-     * to whatever the bitmap's native format is.
+     * to whatever the bitmap's native format is.</p>
      */
     public void copyPixelsFromBuffer(Buffer src) {
         checkRecycled("copyPixelsFromBuffer called on recycled bitmap");
@@ -402,7 +410,7 @@
             throw new RuntimeException("unsupported Buffer subclass");
         }
 
-        long bufferBytes = (long)elements << shift;
+        long bufferBytes = (long) elements << shift;
         long bitmapBytes = getByteCount();
 
         if (bufferBytes < bitmapBytes) {
@@ -410,6 +418,11 @@
         }
 
         nativeCopyPixelsFromBuffer(mNativeBitmap, src);
+
+        // now update the buffer's position
+        int position = src.position();
+        position += bitmapBytes >> shift;
+        src.position(position);
     }
 
     /**
@@ -622,6 +635,22 @@
 
     /**
      * Returns a mutable bitmap with the specified width and height.  Its
+     * initial density is determined from the given {@link DisplayMetrics}.
+     *
+     * @param display  Display metrics for the display this bitmap will be
+     *                 drawn on.
+     * @param width    The width of the bitmap
+     * @param height   The height of the bitmap
+     * @param config   The bitmap config to create.
+     * @throws IllegalArgumentException if the width or height are <= 0
+     */
+    public static Bitmap createBitmap(DisplayMetrics display, int width,
+            int height, Config config) {
+        return createBitmap(display, width, height, config, true);
+    }
+
+    /**
+     * Returns a mutable bitmap with the specified width and height.  Its
      * initial density is as per {@link #getDensity}.
      *
      * @param width    The width of the bitmap
@@ -634,10 +663,33 @@
      * @throws IllegalArgumentException if the width or height are <= 0
      */
     private static Bitmap createBitmap(int width, int height, Config config, boolean hasAlpha) {
+        return createBitmap(null, width, height, config, hasAlpha);
+    }
+
+    /**
+     * Returns a mutable bitmap with the specified width and height.  Its
+     * initial density is determined from the given {@link DisplayMetrics}.
+     *
+     * @param display  Display metrics for the display this bitmap will be
+     *                 drawn on.
+     * @param width    The width of the bitmap
+     * @param height   The height of the bitmap
+     * @param config   The bitmap config to create.
+     * @param hasAlpha If the bitmap is ARGB_8888 this flag can be used to mark the
+     *                 bitmap as opaque. Doing so will clear the bitmap in black
+     *                 instead of transparent.  
+     * 
+     * @throws IllegalArgumentException if the width or height are <= 0
+     */
+    private static Bitmap createBitmap(DisplayMetrics display, int width, int height,
+            Config config, boolean hasAlpha) {
         if (width <= 0 || height <= 0) {
             throw new IllegalArgumentException("width and height must be > 0");
         }
         Bitmap bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true);
+        if (display != null) {
+            bm.mDensity = display.densityDpi;
+        }
         if (config == Config.ARGB_8888 && !hasAlpha) {
             nativeErase(bm.mNativeBitmap, 0xff000000);
             nativeSetHasAlpha(bm.mNativeBitmap, hasAlpha);
@@ -670,6 +722,31 @@
      */
     public static Bitmap createBitmap(int colors[], int offset, int stride,
             int width, int height, Config config) {
+        return createBitmap(null, colors, offset, stride, width, height, config);
+    }
+
+    /**
+     * Returns a immutable bitmap with the specified width and height, with each
+     * pixel value set to the corresponding value in the colors array.  Its
+     * initial density is determined from the given {@link DisplayMetrics}.
+     *
+     * @param display  Display metrics for the display this bitmap will be
+     *                 drawn on.
+     * @param colors   Array of {@link Color} used to initialize the pixels.
+     * @param offset   Number of values to skip before the first color in the
+     *                 array of colors.
+     * @param stride   Number of colors in the array between rows (must be >=
+     *                 width or <= -width).
+     * @param width    The width of the bitmap
+     * @param height   The height of the bitmap
+     * @param config   The bitmap config to create. If the config does not
+     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
+     *                 bytes in the colors[] will be ignored (assumed to be FF)
+     * @throws IllegalArgumentException if the width or height are <= 0, or if
+     *         the color array's length is less than the number of pixels.
+     */
+    public static Bitmap createBitmap(DisplayMetrics display, int colors[],
+            int offset, int stride, int width, int height, Config config) {
 
         checkWidthHeight(width, height);
         if (Math.abs(stride) < width) {
@@ -684,8 +761,12 @@
         if (width <= 0 || height <= 0) {
             throw new IllegalArgumentException("width and height must be > 0");
         }
-        return nativeCreate(colors, offset, stride, width, height,
+        Bitmap bm = nativeCreate(colors, offset, stride, width, height,
                             config.nativeInt, false);
+        if (display != null) {
+            bm.mDensity = display.densityDpi;
+        }
+        return bm;
     }
 
     /**
@@ -704,7 +785,29 @@
      *         the color array's length is less than the number of pixels.
      */
     public static Bitmap createBitmap(int colors[], int width, int height, Config config) {
-        return createBitmap(colors, 0, width, width, height, config);
+        return createBitmap(null, colors, 0, width, width, height, config);
+    }
+
+    /**
+     * Returns a immutable bitmap with the specified width and height, with each
+     * pixel value set to the corresponding value in the colors array.  Its
+     * initial density is determined from the given {@link DisplayMetrics}.
+     *
+     * @param display  Display metrics for the display this bitmap will be
+     *                 drawn on.
+     * @param colors   Array of {@link Color} used to initialize the pixels.
+     *                 This array must be at least as large as width * height.
+     * @param width    The width of the bitmap
+     * @param height   The height of the bitmap
+     * @param config   The bitmap config to create. If the config does not
+     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
+     *                 bytes in the colors[] will be ignored (assumed to be FF)
+     * @throws IllegalArgumentException if the width or height are <= 0, or if
+     *         the color array's length is less than the number of pixels.
+     */
+    public static Bitmap createBitmap(DisplayMetrics display, int colors[],
+            int width, int height, Config config) {
+        return createBitmap(display, colors, 0, width, width, height, config);
     }
 
     /**
@@ -780,6 +883,27 @@
         return mIsMutable;
     }
 
+    /**
+     * <p>Indicates whether pixels stored in this bitmaps are stored pre-multiplied.
+     * When a pixel is pre-multiplied, the RGB components have been multiplied by
+     * the alpha component. For instance, if the original color is a 50%
+     * translucent red <code>(128, 255, 0, 0)</code>, the pre-multiplied form is 
+     * <code>(128, 128, 0, 0)</code>.</p>
+     * 
+     * <p>This method always returns false if {@link #getConfig()} is
+     * {@link Bitmap.Config#RGB_565}.</p>
+     * 
+     * <p>This method only returns true if {@link #hasAlpha()} returns true.
+     * A bitmap with no alpha channel can be used both as a pre-multiplied and
+     * as a non pre-multiplied bitmap.</p>
+     * 
+     * @return true if the underlying pixels have been pre-multiplied, false
+     *         otherwise
+     */
+    public final boolean isPremultiplied() {
+        return getConfig() != Config.RGB_565 && hasAlpha();
+    }
+
     /** Returns the bitmap's width */
     public final int getWidth() {
         return mWidth == -1 ? mWidth = nativeWidth(mNativeBitmap) : mWidth;
@@ -848,7 +972,7 @@
      * @hide
      */
     static public int scaleFromDensity(int size, int sdensity, int tdensity) {
-        if (sdensity == DENSITY_NONE || sdensity == tdensity) {
+        if (sdensity == DENSITY_NONE || tdensity == DENSITY_NONE || sdensity == tdensity) {
             return size;
         }
         
@@ -911,6 +1035,51 @@
     }
 
     /**
+     * Indicates whether the renderer responsible for drawing this
+     * bitmap should attempt to use mipmaps when this bitmap is drawn
+     * scaled down.
+     * 
+     * If you know that you are going to draw this bitmap at less than
+     * 50% of its original size, you may be able to obtain a higher
+     * quality
+     * 
+     * This property is only a suggestion that can be ignored by the
+     * renderer. It is not guaranteed to have any effect.
+     * 
+     * @return true if the renderer should attempt to use mipmaps,
+     *         false otherwise
+     * 
+     * @see #setHasMipMap(boolean)
+     */
+    public final boolean hasMipMap() {
+        return nativeHasMipMap(mNativeBitmap);
+    }
+
+    /**
+     * Set a hint for the renderer responsible for drawing this bitmap
+     * indicating that it should attempt to use mipmaps when this bitmap
+     * is drawn scaled down.
+     *
+     * If you know that you are going to draw this bitmap at less than
+     * 50% of its original size, you may be able to obtain a higher
+     * quality by turning this property on.
+     * 
+     * Note that if the renderer respects this hint it might have to
+     * allocate extra memory to hold the mipmap levels for this bitmap.
+     *
+     * This property is only a suggestion that can be ignored by the
+     * renderer. It is not guaranteed to have any effect.
+     *
+     * @param hasMipMap indicates whether the renderer should attempt
+     *                  to use mipmaps
+     *
+     * @see #hasMipMap()
+     */
+    public final void setHasMipMap(boolean hasMipMap) {
+        nativeSetHasMipMap(mNativeBitmap, hasMipMap);
+    }
+
+    /**
      * Fills the bitmap's pixels with the specified {@link Color}.
      *
      * @throws IllegalStateException if the bitmap is not mutable.
@@ -926,7 +1095,7 @@
     /**
      * Returns the {@link Color} at the specified location. Throws an exception
      * if x or y are out of bounds (negative or >= to the width or height
-     * respectively).
+     * respectively). The returned color is a non-premultiplied ARGB value.
      *
      * @param x    The x coordinate (0...width-1) of the pixel to return
      * @param y    The y coordinate (0...height-1) of the pixel to return
@@ -944,6 +1113,7 @@
      * a packed int representing a {@link Color}. The stride parameter allows
      * the caller to allow for gaps in the returned pixels array between
      * rows. For normal packed results, just pass width for the stride value.
+     * The returned colors are non-premultiplied ARGB values.
      *
      * @param pixels   The array to receive the bitmap's colors
      * @param offset   The first index to write into pixels[]
@@ -955,6 +1125,7 @@
      *                 the bitmap
      * @param width    The number of pixels to read from each row
      * @param height   The number of rows to read
+     *
      * @throws IllegalArgumentException if x, y, width, height exceed the
      *         bounds of the bitmap, or if abs(stride) < width.
      * @throws ArrayIndexOutOfBoundsException if the pixels array is too small
@@ -974,6 +1145,7 @@
     /**
      * Shared code to check for illegal arguments passed to getPixel()
      * or setPixel()
+     * 
      * @param x x coordinate of the pixel
      * @param y y coordinate of the pixel
      */
@@ -1029,12 +1201,14 @@
     }
 
     /**
-     * Write the specified {@link Color} into the bitmap (assuming it is
-     * mutable) at the x,y coordinate.
+     * <p>Write the specified {@link Color} into the bitmap (assuming it is
+     * mutable) at the x,y coordinate. The color must be a
+     * non-premultiplied ARGB value.</p>
      *
      * @param x     The x coordinate of the pixel to replace (0...width-1)
      * @param y     The y coordinate of the pixel to replace (0...height-1)
-     * @param color The {@link Color} to write into the bitmap
+     * @param color The ARGB color to write into the bitmap
+     *
      * @throws IllegalStateException if the bitmap is not mutable
      * @throws IllegalArgumentException if x, y are outside of the bitmap's
      *         bounds.
@@ -1049,8 +1223,9 @@
     }
 
     /**
-     * Replace pixels in the bitmap with the colors in the array. Each element
-     * in the array is a packed int prepresenting a {@link Color}
+     * <p>Replace pixels in the bitmap with the colors in the array. Each element
+     * in the array is a packed int prepresenting a non-premultiplied ARGB
+     * {@link Color}.</p>
      *
      * @param pixels   The colors to write to the bitmap
      * @param offset   The index of the first color to read from pixels[]
@@ -1063,6 +1238,7 @@
      *                 the bitmap.
      * @param width    The number of colors to copy from pixels[] per row
      * @param height   The number of rows to write to the bitmap
+     *
      * @throws IllegalStateException if the bitmap is not mutable
      * @throws IllegalArgumentException if x, y, width, height are outside of
      *         the bitmap's bounds.
@@ -1070,7 +1246,7 @@
      *         to receive the specified number of pixels.
      */
     public void setPixels(int[] pixels, int offset, int stride,
-                          int x, int y, int width, int height) {
+            int x, int y, int width, int height) {
         checkRecycled("Can't call setPixels() on a recycled bitmap");
         if (!isMutable()) {
             throw new IllegalStateException();
@@ -1220,7 +1396,7 @@
     private static native Bitmap nativeCopy(int srcBitmap, int nativeConfig,
                                             boolean isMutable);
     private static native void nativeDestructor(int nativeBitmap);
-    private static native void nativeRecycle(int nativeBitmap);
+    private static native boolean nativeRecycle(int nativeBitmap);
 
     private static native boolean nativeCompress(int nativeBitmap, int format,
                                             int quality, OutputStream stream,
@@ -1230,7 +1406,6 @@
     private static native int nativeHeight(int nativeBitmap);
     private static native int nativeRowBytes(int nativeBitmap);
     private static native int nativeConfig(int nativeBitmap);
-    private static native boolean nativeHasAlpha(int nativeBitmap);
 
     private static native int nativeGetPixel(int nativeBitmap, int x, int y);
     private static native void nativeGetPixels(int nativeBitmap, int[] pixels,
@@ -1259,7 +1434,10 @@
                                                     int[] offsetXY);
 
     private static native void nativePrepareToDraw(int nativeBitmap);
+    private static native boolean nativeHasAlpha(int nativeBitmap);
     private static native void nativeSetHasAlpha(int nBitmap, boolean hasAlpha);
+    private static native boolean nativeHasMipMap(int nativeBitmap);
+    private static native void nativeSetHasMipMap(int nBitmap, boolean hasMipMap);
     private static native boolean nativeSameAs(int nb0, int nb1);
     
     /* package */ final int ni() {
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 5094df18..381e65b 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -19,6 +19,7 @@
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.util.TypedValue;
 
 import java.io.BufferedInputStream;
@@ -303,6 +304,7 @@
             /*  do nothing.
                 If the exception happened on open, bm will be null.
             */
+            Log.e("BitmapFactory", "Unable to decode stream: " + e);
         } finally {
             if (stream != null) {
                 try {
diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java
index c1d3407..b38d107 100644
--- a/graphics/java/android/graphics/BitmapRegionDecoder.java
+++ b/graphics/java/android/graphics/BitmapRegionDecoder.java
@@ -36,6 +36,9 @@
 public final class BitmapRegionDecoder {
     private int mNativeBitmapRegionDecoder;
     private boolean mRecycled;
+    // ensures that the native decoder object exists and that only one decode can
+    // occur at a time.
+    private final Object mNativeLock = new Object();
 
     /**
      * Create a BitmapRegionDecoder from the specified byte array.
@@ -179,24 +182,30 @@
      *         decoded.
      */
     public Bitmap decodeRegion(Rect rect, BitmapFactory.Options options) {
-        checkRecycled("decodeRegion called on recycled region decoder");
-        if (rect.right <= 0 || rect.bottom <= 0 || rect.left >= getWidth()
-                || rect.top >= getHeight())
-            throw new IllegalArgumentException("rectangle is outside the image");
-        return nativeDecodeRegion(mNativeBitmapRegionDecoder, rect.left, rect.top,
-                rect.right - rect.left, rect.bottom - rect.top, options);
+        synchronized (mNativeLock) {
+            checkRecycled("decodeRegion called on recycled region decoder");
+            if (rect.right <= 0 || rect.bottom <= 0 || rect.left >= getWidth()
+                    || rect.top >= getHeight())
+                throw new IllegalArgumentException("rectangle is outside the image");
+            return nativeDecodeRegion(mNativeBitmapRegionDecoder, rect.left, rect.top,
+                    rect.right - rect.left, rect.bottom - rect.top, options);
+        }
     }
 
     /** Returns the original image's width */
     public int getWidth() {
-        checkRecycled("getWidth called on recycled region decoder");
-        return nativeGetWidth(mNativeBitmapRegionDecoder);
+        synchronized (mNativeLock) {
+            checkRecycled("getWidth called on recycled region decoder");
+            return nativeGetWidth(mNativeBitmapRegionDecoder);
+        }
     }
 
     /** Returns the original image's height */
     public int getHeight() {
-        checkRecycled("getHeight called on recycled region decoder");
-        return nativeGetHeight(mNativeBitmapRegionDecoder);
+        synchronized (mNativeLock) {
+            checkRecycled("getHeight called on recycled region decoder");
+            return nativeGetHeight(mNativeBitmapRegionDecoder);
+        }
     }
 
     /**
@@ -210,9 +219,11 @@
      * memory when there are no more references to this region decoder.
      */
     public void recycle() {
-        if (!mRecycled) {
-            nativeClean(mNativeBitmapRegionDecoder);
-            mRecycled = true;
+        synchronized (mNativeLock) {
+            if (!mRecycled) {
+                nativeClean(mNativeBitmapRegionDecoder);
+                mRecycled = true;
+            }
         }
     }
 
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index f9b8a5f..4170cfe 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -371,12 +371,30 @@
     public void reset() {
         native_reset(mNativePaint);
         setFlags(DEFAULT_PAINT_FLAGS);
+
         // TODO: Turning off hinting has undesirable side effects, we need to
         //       revisit hinting once we add support for subpixel positioning
         // setHinting(DisplayMetrics.DENSITY_DEVICE >= DisplayMetrics.DENSITY_TV
         //        ? HINTING_OFF : HINTING_ON);
+
+        mColorFilter = null;
+        mMaskFilter = null;
+        mPathEffect = null;
+        mRasterizer = null;
+        mShader = null;
+        mTypeface = null;
+        mXfermode = null;
+
         mHasCompatScaling = false;
-        mCompatScaling = mInvCompatScaling = 1;
+        mCompatScaling = 1;
+        mInvCompatScaling = 1;
+
+        hasShadow = false;
+        shadowDx = 0;
+        shadowDy = 0;
+        shadowRadius = 0;
+        shadowColor = 0;
+
         mBidiFlags = BIDI_DEFAULT_LTR;
         setTextLocale(Locale.getDefault());
     }
@@ -1055,7 +1073,6 @@
      * Get the text Locale.
      *
      * @return the paint's Locale used for drawing text, never null.
-     * @hide
      */
     public Locale getTextLocale() {
         return mLocale;
@@ -1086,7 +1103,6 @@
      * job in certain ambiguous cases
      *
      * @param locale the paint's locale value for drawing text, must not be null.
-     * @hide
      */
     public void setTextLocale(Locale locale) {
         if (locale == null) {
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 6c204ab..8b5609f 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -69,10 +69,14 @@
      *          rectangle.
      */
     public Rect(Rect r) {
-        left = r.left;
-        top = r.top;
-        right = r.right;
-        bottom = r.bottom;
+        if (r == null) {
+            left = top = right = bottom = 0;
+        } else {
+            left = r.left;
+            top = r.top;
+            right = r.right;
+            bottom = r.bottom;
+        }
     }
 
     @Override
diff --git a/graphics/java/android/graphics/RectF.java b/graphics/java/android/graphics/RectF.java
index 108b7f9..53178b0 100644
--- a/graphics/java/android/graphics/RectF.java
+++ b/graphics/java/android/graphics/RectF.java
@@ -66,17 +66,25 @@
      *          rectangle.
      */
     public RectF(RectF r) {
-        left = r.left;
-        top = r.top;
-        right = r.right;
-        bottom = r.bottom;
+        if (r == null) {
+            left = top = right = bottom = 0.0f;
+        } else {
+            left = r.left;
+            top = r.top;
+            right = r.right;
+            bottom = r.bottom;
+        }
     }
     
     public RectF(Rect r) {
-        left = r.left;
-        top = r.top;
-        right = r.right;
-        bottom = r.bottom;
+        if (r == null) {
+            left = top = right = bottom = 0.0f;
+        } else {
+            left = r.left;
+            top = r.top;
+            right = r.right;
+            bottom = r.bottom;
+        }
     }
 
     @Override
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 87421b1..e82ccd4 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -385,7 +385,7 @@
             Shader shader = state.mPaint.getShader();
             if (shader == null) {
                 if (mApplyGravity) {
-                    final int layoutDirection = getResolvedLayoutDirectionSelf();
+                    final int layoutDirection = getLayoutDirection();
                     Gravity.apply(state.mGravity, mBitmapWidth, mBitmapHeight,
                             getBounds(), mDstRect, layoutDirection);
                     mApplyGravity = false;
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index c41dd07..b7429d4 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -209,7 +209,7 @@
         if ((mClipState.mOrientation & VERTICAL) != 0) {
             h -= (h - ih) * (10000 - level) / 10000;
         }
-        final int layoutDirection = getResolvedLayoutDirectionSelf();
+        final int layoutDirection = getLayoutDirection();
         Gravity.apply(mClipState.mGravity, w, h, bounds, r, layoutDirection);
 
         if (w > 0 && h > 0) {
@@ -239,7 +239,12 @@
         return null;
     }
 
-    
+    /** @hide */
+    @Override
+    public void setLayoutDirection(int layoutDirection) {
+        mClipState.mDrawable.setLayoutDirection(layoutDirection);
+        super.setLayoutDirection(layoutDirection);
+    }
 
     final static class ClipState extends ConstantState {
         Drawable mDrawable;
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index 88c9155..d11e554 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -20,6 +20,7 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
+import android.view.ViewDebug;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -34,8 +35,10 @@
  * @attr ref android.R.styleable#ColorDrawable_color
  */
 public class ColorDrawable extends Drawable {
+    @ViewDebug.ExportedProperty(deepExport = true, prefix = "state_")
     private ColorState mState;
     private final Paint mPaint = new Paint();
+    private boolean mMutated;
 
     /**
      * Creates a new black ColorDrawable.
@@ -63,6 +66,21 @@
         return super.getChangingConfigurations() | mState.mChangingConfigurations;
     }
 
+    /**
+     * A mutable BitmapDrawable still shares its Bitmap with any other Drawable
+     * that comes from the same resource.
+     *
+     * @return This drawable.
+     */
+    @Override
+    public Drawable mutate() {
+        if (!mMutated && super.mutate() == this) {
+            mState = new ColorState(mState);
+            mMutated = true;
+        }
+        return this;
+    }
+
     @Override
     public void draw(Canvas canvas) {
         if ((mState.mUseColor >>> 24) != 0) {
@@ -158,6 +176,7 @@
 
     final static class ColorState extends ConstantState {
         int mBaseColor; // base color, independent of setAlpha()
+        @ViewDebug.ExportedProperty
         int mUseColor;  // basecolor modulated by setAlpha()
         int mChangingConfigurations;
 
@@ -165,6 +184,7 @@
             if (state != null) {
                 mBaseColor = state.mBaseColor;
                 mUseColor = state.mUseColor;
+                mChangingConfigurations = state.mChangingConfigurations;
             }
         }
 
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 785582c..f9392e4 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -37,7 +37,6 @@
 import android.util.StateSet;
 import android.util.TypedValue;
 import android.util.Xml;
-import android.view.View;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -124,6 +123,8 @@
     private WeakReference<Callback> mCallback = null;
     private boolean mVisible = true;
 
+    private int mLayoutDirection;
+
     /**
      * Draw in its bounds (set via setBounds) respecting optional effects such
      * as alpha (set via setAlpha) and color filter (set via setColorFilter).
@@ -296,19 +297,6 @@
     }
 
     /**
-     * Implement this interface if you want to create an drawable that is RTL aware
-     * @hide
-     */
-    public static interface Callback2 extends Callback {
-        /**
-         * A Drawable can call this to get the resolved layout direction of the <var>who</var>.
-         *
-         * @param who The drawable being queried.
-         */
-        public int getResolvedLayoutDirection(Drawable who);
-    }
-
-    /**
      * Bind a {@link Callback} object to this Drawable.  Required for clients
      * that want to support animated drawables.
      *
@@ -385,15 +373,30 @@
     }
 
     /**
-     * Get the resolved layout direction of this Drawable.
+     * Returns the resolved layout direction for this Drawable.
+     *
+     * @return One of {@link android.view.View#LAYOUT_DIRECTION_LTR},
+     *   {@link android.view.View#LAYOUT_DIRECTION_RTL}
+     *
      * @hide
      */
-    public int getResolvedLayoutDirectionSelf() {
-        final Callback callback = getCallback();
-        if (callback == null || !(callback instanceof Callback2)) {
-            return View.LAYOUT_DIRECTION_LTR;
+    public int getLayoutDirection() {
+        return mLayoutDirection;
+    }
+
+    /**
+     * Set the layout direction for this drawable. Should be a resolved direction as the
+     * Drawable as no capacity to do the resolution on his own.
+     *
+     * @param layoutDirection One of {@link android.view.View#LAYOUT_DIRECTION_LTR},
+     *   {@link android.view.View#LAYOUT_DIRECTION_RTL}
+     *
+     * @hide
+     */
+    public void setLayoutDirection(int layoutDirection) {
+        if (getLayoutDirection() != layoutDirection) {
+            mLayoutDirection = layoutDirection;
         }
-        return ((Callback2) callback).getResolvedLayoutDirection(this);
     }
 
     /**
@@ -777,7 +780,8 @@
         // to the compatibility density only to have them scaled back up when
         // drawn to the screen.
         if (opts == null) opts = new BitmapFactory.Options();
-        opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
+        opts.inScreenDensity = res != null
+                ? res.getDisplayMetrics().noncompatDensityDpi : DisplayMetrics.DENSITY_DEVICE;
         Bitmap  bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);
         if (bm != null) {
             byte[] np = bm.getNinePatchChunk();
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 15b2c0b..41b272d 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -105,7 +105,7 @@
             mAlpha = alpha;
             if (mCurrDrawable != null) {
                 if (mEnterAnimationEnd == 0) {
-                    mCurrDrawable.setAlpha(alpha);
+                    mCurrDrawable.mutate().setAlpha(alpha);
                 } else {
                     animate(false);
                 }
@@ -118,7 +118,7 @@
         if (mDrawableContainerState.mDither != dither) {
             mDrawableContainerState.mDither = dither;
             if (mCurrDrawable != null) {
-                mCurrDrawable.setDither(mDrawableContainerState.mDither);
+                mCurrDrawable.mutate().setDither(mDrawableContainerState.mDither);
             }
         }
     }
@@ -128,7 +128,7 @@
         if (mColorFilter != cf) {
             mColorFilter = cf;
             if (mCurrDrawable != null) {
-                mCurrDrawable.setColorFilter(cf);
+                mCurrDrawable.mutate().setColorFilter(cf);
             }
         }
     }
@@ -176,7 +176,7 @@
         }
         if (mCurrDrawable != null) {
             mCurrDrawable.jumpToCurrentState();
-            mCurrDrawable.setAlpha(mAlpha);
+            mCurrDrawable.mutate().setAlpha(mAlpha);
         }
         if (mExitAnimationEnd != 0) {
             mExitAnimationEnd = 0;
@@ -312,6 +312,7 @@
             mCurrDrawable = d;
             mCurIndex = idx;
             if (d != null) {
+                d.mutate();
                 if (mDrawableContainerState.mEnterFadeDuration > 0) {
                     mEnterAnimationEnd = now + mDrawableContainerState.mEnterFadeDuration;
                 } else {
@@ -355,13 +356,13 @@
         if (mCurrDrawable != null) {
             if (mEnterAnimationEnd != 0) {
                 if (mEnterAnimationEnd <= now) {
-                    mCurrDrawable.setAlpha(mAlpha);
+                    mCurrDrawable.mutate().setAlpha(mAlpha);
                     mEnterAnimationEnd = 0;
                 } else {
                     int animAlpha = (int)((mEnterAnimationEnd-now)*255)
                             / mDrawableContainerState.mEnterFadeDuration;
                     if (DEBUG) android.util.Log.i(TAG, toString() + " cur alpha " + animAlpha);
-                    mCurrDrawable.setAlpha(((255-animAlpha)*mAlpha)/255);
+                    mCurrDrawable.mutate().setAlpha(((255-animAlpha)*mAlpha)/255);
                     animating = true;
                 }
             }
@@ -378,7 +379,7 @@
                     int animAlpha = (int)((mExitAnimationEnd-now)*255)
                             / mDrawableContainerState.mExitFadeDuration;
                     if (DEBUG) android.util.Log.i(TAG, toString() + " last alpha " + animAlpha);
-                    mLastDrawable.setAlpha((animAlpha*mAlpha)/255);
+                    mLastDrawable.mutate().setAlpha((animAlpha*mAlpha)/255);
                     animating = true;
                 }
             }
@@ -443,7 +444,6 @@
         int         mConstantMinimumWidth;
         int         mConstantMinimumHeight;
 
-        boolean     mHaveOpacity = false;
         int         mOpacity;
 
         boolean     mHaveStateful = false;
@@ -492,7 +492,6 @@
                 mConstantWidth = orig.mConstantWidth;
                 mConstantHeight = orig.mConstantHeight;
                 
-                mHaveOpacity = orig.mHaveOpacity;
                 mOpacity = orig.mOpacity;
                 mHaveStateful = orig.mHaveStateful;
                 mStateful = orig.mStateful;
@@ -527,7 +526,6 @@
             mDrawables[pos] = dr;
             mNumChildren++;
             mChildrenChangingConfigurations |= dr.getChangingConfigurations();
-            mHaveOpacity = false;
             mHaveStateful = false;
 
             mConstantPadding = null;
@@ -655,10 +653,6 @@
         }
 
         public final int getOpacity() {
-            if (mHaveOpacity) {
-                return mOpacity;
-            }
-
             final int N = getChildCount();
             final Drawable[] drawables = mDrawables;
             int op = N > 0 ? drawables[0].getOpacity() : PixelFormat.TRANSPARENT;
@@ -666,7 +660,6 @@
                 op = Drawable.resolveOpacity(op, drawables[i].getOpacity());
             }
             mOpacity = op;
-            mHaveOpacity = true;
             return op;
         }
 
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 5b50beb..0623a9e 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -435,7 +435,8 @@
         final int currFillAlpha = modulateAlpha(prevFillAlpha);
         final int currStrokeAlpha = modulateAlpha(prevStrokeAlpha);
 
-        final boolean haveStroke = currStrokeAlpha > 0 && mStrokePaint.getStrokeWidth() > 0;
+        final boolean haveStroke = currStrokeAlpha > 0 && mStrokePaint != null &&
+                mStrokePaint.getStrokeWidth() > 0;
         final boolean haveFill = currFillAlpha > 0;
         final GradientState st = mGradientState;
         /*  we need a layer iff we're drawing both a fill and stroke, and the
@@ -477,6 +478,9 @@
             mFillPaint.setAlpha(currFillAlpha);
             mFillPaint.setDither(mDither);
             mFillPaint.setColorFilter(mColorFilter);
+            if (mColorFilter != null && !mGradientState.mHasSolidColor) {
+                mFillPaint.setColor(0xff000000);
+            }
             if (haveStroke) {
                 mStrokePaint.setAlpha(currStrokeAlpha);
                 mStrokePaint.setDither(mDither);
@@ -512,7 +516,10 @@
                         canvas.drawRoundRect(mRect, rad, rad, mStrokePaint);
                     }
                 } else {
-                    canvas.drawRect(mRect, mFillPaint);
+                    if (mFillPaint.getColor() != 0 || mColorFilter != null ||
+                            mFillPaint.getShader() != null) {
+                        canvas.drawRect(mRect, mFillPaint);
+                    }
                     if (haveStroke) {
                         canvas.drawRect(mRect, mStrokePaint);
                     }
@@ -603,9 +610,9 @@
 
     /**
      * <p>Changes this drawbale to use a single color instead of a gradient.</p>
-     * <p><strong>Note</strong>: changing orientation will affect all instances
+     * <p><strong>Note</strong>: changing color will affect all instances
      * of a drawable loaded from a resource. It is recommended to invoke
-     * {@link #mutate()} before changing the orientation.</p>
+     * {@link #mutate()} before changing the color.</p>
      *
      * @param argb The color used to fill the shape
      *
@@ -649,7 +656,7 @@
 
     @Override
     public int getOpacity() {
-        return PixelFormat.TRANSLUCENT;
+        return mGradientState.mOpaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
     }
 
     @Override
@@ -735,6 +742,9 @@
 
                     mFillPaint.setShader(new LinearGradient(x0, y0, x1, y1,
                             colors, st.mPositions, Shader.TileMode.CLAMP));
+                    if (!mGradientState.mHasSolidColor) {
+                        mFillPaint.setColor(0xff000000);
+                    }
                 } else if (st.mGradient == RADIAL_GRADIENT) {
                     x0 = r.left + (r.right - r.left) * st.mCenterX;
                     y0 = r.top + (r.bottom - r.top) * st.mCenterY;
@@ -744,6 +754,9 @@
                     mFillPaint.setShader(new RadialGradient(x0, y0,
                             level * st.mGradientRadius, colors, null,
                             Shader.TileMode.CLAMP));
+                    if (!mGradientState.mHasSolidColor) {
+                        mFillPaint.setColor(0xff000000);
+                    }
                 } else if (st.mGradient == SWEEP_GRADIENT) {
                     x0 = r.left + (r.right - r.left) * st.mCenterX;
                     y0 = r.top + (r.bottom - r.top) * st.mCenterY;
@@ -774,6 +787,9 @@
 
                     }
                     mFillPaint.setShader(new SweepGradient(x0, y0, tempColors, tempPositions));
+                    if (!mGradientState.mHasSolidColor) {
+                        mFillPaint.setColor(0xff000000);
+                    }
                 }
             }
         }
@@ -1011,7 +1027,10 @@
             } else {
                 Log.w("drawable", "Bad element under <shape>: " + name);
             }
+
         }
+
+        mGradientState.computeOpacity();
     }
 
     private static float getFloatOrFraction(TypedArray a, int index, float defaultValue) {
@@ -1079,10 +1098,11 @@
         private float mGradientRadius = 0.5f;
         private boolean mUseLevel;
         private boolean mUseLevelForShape;
+        private boolean mOpaque;
 
         GradientState(Orientation orientation, int[] colors) {
             mOrientation = orientation;
-            mColors = colors;
+            setColors(colors);
         }
 
         public GradientState(GradientState state) {
@@ -1120,6 +1140,7 @@
             mGradientRadius = state.mGradientRadius;
             mUseLevel = state.mUseLevel;
             mUseLevelForShape = state.mUseLevelForShape;
+            mOpaque = state.mOpaque;
         }
 
         @Override
@@ -1139,6 +1160,7 @@
 
         public void setShape(int shape) {
             mShape = shape;
+            computeOpacity();
         }
 
         public void setGradientType(int gradient) {
@@ -1153,24 +1175,65 @@
         public void setColors(int[] colors) {
             mHasSolidColor = false;
             mColors = colors;
+            computeOpacity();
         }
         
         public void setSolidColor(int argb) {
             mHasSolidColor = true;
             mSolidColor = argb;
             mColors = null;
+            computeOpacity();
+        }
+
+        private void computeOpacity() {
+            if (mShape != RECTANGLE) {
+                mOpaque = false;
+                return;
+            }
+
+            if (mRadius > 0 || mRadiusArray != null) {
+                mOpaque = false;
+                return;
+            }
+
+            if (mStrokeWidth > 0 && !isOpaque(mStrokeColor)) {
+                mOpaque = false;
+                return;
+            }
+            
+            if (mHasSolidColor) {
+                mOpaque = isOpaque(mSolidColor);
+                return;
+            }
+
+            if (mColors != null) {
+                for (int i = 0; i < mColors.length; i++) {
+                    if (!isOpaque(mColors[i])) {
+                        mOpaque = false;
+                        return;
+                    }
+                }
+            }
+
+            mOpaque = true;
+        }
+
+        private static boolean isOpaque(int color) {
+            return ((color >> 24) & 0xff) == 0xff;
         }
 
         public void setStroke(int width, int color) {
             mStrokeWidth = width;
             mStrokeColor = color;
+            computeOpacity();
         }
-        
+
         public void setStroke(int width, int color, float dashWidth, float dashGap) {
             mStrokeWidth = width;
             mStrokeColor = color;
             mStrokeDashWidth = dashWidth;
             mStrokeDashGap = dashGap;
+            computeOpacity();
         }
 
         public void setCornerRadius(float radius) {
@@ -1180,14 +1243,14 @@
             mRadius = radius;
             mRadiusArray = null;
         }
-        
+
         public void setCornerRadii(float[] radii) {
             mRadiusArray = radii;
             if (radii == null) {
                 mRadius = 0;
             }
         }
-        
+
         public void setSize(int width, int height) {
             mWidth = width;
             mHeight = height;
@@ -1202,11 +1265,17 @@
         mGradientState = state;
         initializeWithState(state);
         mRectIsDirty = true;
+        mMutated = false;
     }
 
     private void initializeWithState(GradientState state) {
         if (state.mHasSolidColor) {
             mFillPaint.setColor(state.mSolidColor);
+        } else if (state.mColors == null) {
+            // If we don't have a solid color and we don't have a gradient,
+            // the app is stroking the shape, set the color to the default
+            // value of state.mSolidColor
+            mFillPaint.setColor(0);
         }
         mPadding = state.mPadding;
         if (state.mStrokeWidth >= 0) {
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 383fe71..0351b71 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -590,6 +590,19 @@
         return this;
     }
 
+    /** @hide */
+    @Override
+    public void setLayoutDirection(int layoutDirection) {
+        if (getLayoutDirection() != layoutDirection) {
+            final ChildDrawable[] array = mLayerState.mChildren;
+            final int N = mLayerState.mNum;
+            for (int i = 0; i < N; i++) {
+                array[i].mDrawable.setLayoutDirection(layoutDirection);
+            }
+        }
+        super.setLayoutDirection(layoutDirection);
+    }
+
     static class ChildDrawable {
         public Drawable mDrawable;
         public int mInsetL, mInsetT, mInsetR, mInsetB;
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index b68b267..2ee6233 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -181,7 +181,7 @@
         }
     }
 
-    private Insets scaleFromDensity(Insets insets, int sdensity, int tdensity) {
+    private static Insets scaleFromDensity(Insets insets, int sdensity, int tdensity) {
         int left = Bitmap.scaleFromDensity(insets.left, sdensity, tdensity);
         int top = Bitmap.scaleFromDensity(insets.top, sdensity, tdensity);
         int right = Bitmap.scaleFromDensity(insets.right, sdensity, tdensity);
@@ -296,7 +296,7 @@
         if (dither) {
             options.inDither = false;
         }
-        options.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
+        options.inScreenDensity = r.getDisplayMetrics().noncompatDensityDpi;
 
         final Rect padding = new Rect();
         final Rect layoutInsets = new Rect();
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index ccad250..bd2b2f0 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -221,7 +221,7 @@
             final int ih = min ? mScaleState.mDrawable.getIntrinsicHeight() : 0;
             h -= (int) ((h - ih) * (10000 - level) * mScaleState.mScaleHeight / 10000);
         }
-        final int layoutDirection = getResolvedLayoutDirectionSelf();
+        final int layoutDirection = getLayoutDirection();
         Gravity.apply(mScaleState.mGravity, w, h, bounds, r, layoutDirection);
 
         if (w > 0 && h > 0) {
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index a3622a2..2ec1293 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -373,8 +373,16 @@
     @Override
     public Drawable mutate() {
         if (!mMutated && super.mutate() == this) {
-            mShapeState.mPaint = new Paint(mShapeState.mPaint);
-            mShapeState.mPadding = new Rect(mShapeState.mPadding);
+            if (mShapeState.mPaint != null) {
+                mShapeState.mPaint = new Paint(mShapeState.mPaint);
+            } else {
+                mShapeState.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            }
+            if (mShapeState.mPadding != null) {
+                mShapeState.mPadding = new Rect(mShapeState.mPadding);
+            } else {
+                mShapeState.mPadding = new Rect();
+            }
             try {
                 mShapeState.mShape = mShapeState.mShape.clone();
             } catch (CloneNotSupportedException e) {
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index 384ca81..f8f3ac9 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -261,6 +261,16 @@
         return this;
     }
 
+    /** @hide */
+    @Override
+    public void setLayoutDirection(int layoutDirection) {
+        final int numStates = getStateCount();
+        for (int i = 0; i < numStates; i++) {
+            getStateDrawable(i).setLayoutDirection(layoutDirection);
+        }
+        super.setLayoutDirection(layoutDirection);
+    }
+
     static final class StateListState extends DrawableContainerState {
         int[][] mStateSets;
 
diff --git a/graphics/java/android/renderscript/Matrix2f.java b/graphics/java/android/renderscript/Matrix2f.java
index acc5bd8..39abd4f 100644
--- a/graphics/java/android/renderscript/Matrix2f.java
+++ b/graphics/java/android/renderscript/Matrix2f.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2009-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.
@@ -59,23 +59,23 @@
     /**
     * Returns the value for a given row and column
     *
-    * @param i row of the value to return
-    * @param j column of the value to return
+    * @param x column of the value to return
+    * @param y row of the value to return
     *
-    * @return value in the ith row and jth column
+    * @return value in the yth row and xth column
     */
-    public float get(int i, int j) {
-        return mMat[i*2 + j];
+    public float get(int x, int y) {
+        return mMat[x*2 + y];
     }
 
     /**
     * Sets the value for a given row and column
     *
-    * @param i row of the value to set
-    * @param j column of the value to set
+    * @param x column of the value to set
+    * @param y row of the value to set
     */
-    public void set(int i, int j, float v) {
-        mMat[i*2 + j] = v;
+    public void set(int x, int y, float v) {
+        mMat[x*2 + y] = v;
     }
 
     /**
diff --git a/graphics/java/android/renderscript/Matrix3f.java b/graphics/java/android/renderscript/Matrix3f.java
index 253506d..66f2c81 100644
--- a/graphics/java/android/renderscript/Matrix3f.java
+++ b/graphics/java/android/renderscript/Matrix3f.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2009-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.
@@ -59,23 +59,23 @@
     /**
     * Returns the value for a given row and column
     *
-    * @param i row of the value to return
-    * @param j column of the value to return
+    * @param x column of the value to return
+    * @param y row of the value to return
     *
-    * @return value in the ith row and jth column
+    * @return value in the yth row and xth column
     */
-    public float get(int i, int j) {
-        return mMat[i*3 + j];
+    public float get(int x, int y) {
+        return mMat[x*3 + y];
     }
 
     /**
     * Sets the value for a given row and column
     *
-    * @param i row of the value to set
-    * @param j column of the value to set
+    * @param x column of the value to set
+    * @param y row of the value to set
     */
-    public void set(int i, int j, float v) {
-        mMat[i*3 + j] = v;
+    public void set(int x, int y, float v) {
+        mMat[x*3 + y] = v;
     }
 
     /**
diff --git a/graphics/java/android/renderscript/Matrix4f.java b/graphics/java/android/renderscript/Matrix4f.java
index adc1806..4600424 100644
--- a/graphics/java/android/renderscript/Matrix4f.java
+++ b/graphics/java/android/renderscript/Matrix4f.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2009-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.
@@ -59,23 +59,23 @@
     /**
     * Returns the value for a given row and column
     *
-    * @param i row of the value to return
-    * @param j column of the value to return
+    * @param x column of the value to return
+    * @param y row of the value to return
     *
-    * @return value in the ith row and jth column
+    * @return value in the yth row and xth column
     */
-    public float get(int i, int j) {
-        return mMat[i*4 + j];
+    public float get(int x, int y) {
+        return mMat[x*4 + y];
     }
 
     /**
     * Sets the value for a given row and column
     *
-    * @param i row of the value to set
-    * @param j column of the value to set
+    * @param x column of the value to set
+    * @param y row of the value to set
     */
-    public void set(int i, int j, float v) {
-        mMat[i*4 + j] = v;
+    public void set(int x, int y, float v) {
+        mMat[x*4 + y] = v;
     }
 
     /**
@@ -113,6 +113,34 @@
     }
 
     /**
+    * Sets the values of the matrix to those of the parameter
+    *
+    * @param src matrix to load the values from
+    * @hide
+    */
+    public void load(Matrix3f src) {
+        mMat[0] = src.mMat[0];
+        mMat[1] = src.mMat[1];
+        mMat[2] = src.mMat[2];
+        mMat[3] = 0;
+
+        mMat[4] = src.mMat[3];
+        mMat[5] = src.mMat[4];
+        mMat[6] = src.mMat[5];
+        mMat[7] = 0;
+
+        mMat[8] = src.mMat[6];
+        mMat[9] = src.mMat[7];
+        mMat[10] = src.mMat[8];
+        mMat[11] = 0;
+
+        mMat[12] = 0;
+        mMat[13] = 0;
+        mMat[14] = 0;
+        mMat[15] = 1;
+    }
+
+    /**
     * Sets current values to be a rotation matrix of certain angle
     * about a given axis
     *
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 2032f67..76edb0a 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -561,6 +561,48 @@
         return rsnScriptCCreate(mContext, resName, cacheDir, script, length);
     }
 
+    native int  rsnScriptIntrinsicCreate(int con, int id, int eid);
+    synchronized int nScriptIntrinsicCreate(int id, int eid) {
+        validate();
+        return rsnScriptIntrinsicCreate(mContext, id, eid);
+    }
+
+    native int  rsnScriptKernelIDCreate(int con, int sid, int slot, int sig);
+    synchronized int nScriptKernelIDCreate(int sid, int slot, int sig) {
+        validate();
+        return rsnScriptKernelIDCreate(mContext, sid, slot, sig);
+    }
+
+    native int  rsnScriptFieldIDCreate(int con, int sid, int slot);
+    synchronized int nScriptFieldIDCreate(int sid, int slot) {
+        validate();
+        return rsnScriptFieldIDCreate(mContext, sid, slot);
+    }
+
+    native int  rsnScriptGroupCreate(int con, int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types);
+    synchronized int nScriptGroupCreate(int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types) {
+        validate();
+        return rsnScriptGroupCreate(mContext, kernels, src, dstk, dstf, types);
+    }
+
+    native void rsnScriptGroupSetInput(int con, int group, int kernel, int alloc);
+    synchronized void nScriptGroupSetInput(int group, int kernel, int alloc) {
+        validate();
+        rsnScriptGroupSetInput(mContext, group, kernel, alloc);
+    }
+
+    native void rsnScriptGroupSetOutput(int con, int group, int kernel, int alloc);
+    synchronized void nScriptGroupSetOutput(int group, int kernel, int alloc) {
+        validate();
+        rsnScriptGroupSetOutput(mContext, group, kernel, alloc);
+    }
+
+    native void rsnScriptGroupExecute(int con, int group);
+    synchronized void nScriptGroupExecute(int group) {
+        validate();
+        rsnScriptGroupExecute(mContext, group);
+    }
+
     native int  rsnSamplerCreate(int con, int magFilter, int minFilter,
                                  int wrapS, int wrapT, int wrapR, float aniso);
     synchronized int nSamplerCreate(int magFilter, int minFilter,
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index bbf5e7e..3fe3261 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -16,10 +16,105 @@
 
 package android.renderscript;
 
+import android.util.SparseArray;
+
 /**
  *
  **/
 public class Script extends BaseObj {
+
+    /**
+     * KernelID is an identifier for a Script + root function pair. It is used
+     * as an identifier for ScriptGroup creation.
+     *
+     * This class should not be directly created. Instead use the method in the
+     * reflected or intrinsic code "getKernelID_funcname()".
+     *
+     */
+    public static final class KernelID extends BaseObj {
+        Script mScript;
+        int mSlot;
+        int mSig;
+        KernelID(int id, RenderScript rs, Script s, int slot, int sig) {
+            super(id, rs);
+            mScript = s;
+            mSlot = slot;
+            mSig = sig;
+        }
+    }
+
+    private final SparseArray<KernelID> mKIDs = new SparseArray<KernelID>();
+    /**
+     * Only to be used by generated reflected classes.
+     *
+     *
+     * @param slot
+     * @param sig
+     * @param ein
+     * @param eout
+     *
+     * @return KernelID
+     */
+    protected KernelID createKernelID(int slot, int sig, Element ein, Element eout) {
+        KernelID k = mKIDs.get(slot);
+        if (k != null) {
+            return k;
+        }
+
+        int id = mRS.nScriptKernelIDCreate(getID(mRS), slot, sig);
+        if (id == 0) {
+            throw new RSDriverException("Failed to create KernelID");
+        }
+
+        k = new KernelID(id, mRS, this, slot, sig);
+        mKIDs.put(slot, k);
+        return k;
+    }
+
+    /**
+     * FieldID is an identifier for a Script + exported field pair. It is used
+     * as an identifier for ScriptGroup creation.
+     *
+     * This class should not be directly created. Instead use the method in the
+     * reflected or intrinsic code "getFieldID_funcname()".
+     *
+     */
+    public static final class FieldID extends BaseObj {
+        Script mScript;
+        int mSlot;
+        FieldID(int id, RenderScript rs, Script s, int slot) {
+            super(id, rs);
+            mScript = s;
+            mSlot = slot;
+        }
+    }
+
+    private final SparseArray<FieldID> mFIDs = new SparseArray();
+    /**
+     * Only to be used by generated reflected classes.
+     *
+     * @param slot
+     * @param e
+     *
+     * @return FieldID
+     */
+    protected FieldID createFieldID(int slot, Element e) {
+        FieldID f = mFIDs.get(slot);
+        if (f != null) {
+            return f;
+        }
+
+        int id = mRS.nScriptFieldIDCreate(getID(mRS), slot);
+        if (id == 0) {
+            throw new RSDriverException("Failed to create FieldID");
+        }
+
+        f = new FieldID(id, mRS, this, slot);
+        mFIDs.put(slot, f);
+        return f;
+    }
+
+
     /**
      * Only intended for use by generated reflected code.
      *
diff --git a/graphics/java/android/renderscript/ScriptGroup.java b/graphics/java/android/renderscript/ScriptGroup.java
new file mode 100644
index 0000000..7afdb397
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptGroup.java
@@ -0,0 +1,464 @@
+/*
+ * 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.renderscript;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+/**
+ * ScriptGroup creates a groups of scripts which are executed
+ * together based upon upon one execution call as if they were
+ * all part of a single script.  The scripts may be connected
+ * internally or to an external allocation. For the internal
+ * connections the intermediate results are not observable after
+ * the execution of the script.
+ * <p>
+ * The external connections are grouped into inputs and outputs.
+ * All outputs are produced by a script kernel and placed into a
+ * user supplied allocation. Inputs are similar but supply the
+ * input of a kernal. Inputs bounds to a script are set directly
+ * upon the script.
+ * <p>
+ * A ScriptGroup must contain at least one kernel. A ScriptGroup
+ * must contain only a single directed acyclic graph (DAG) of
+ * script kernels and connections. Attempting to create a
+ * ScriptGroup with multiple DAGs or attempting to create
+ * a cycle within a ScriptGroup will throw an exception.
+ *
+ **/
+public final class ScriptGroup extends BaseObj {
+    IO mOutputs[];
+    IO mInputs[];
+
+    static class IO {
+        Script.KernelID mKID;
+        Allocation mAllocation;
+
+        IO(Script.KernelID s) {
+            mKID = s;
+        }
+    }
+
+    static class ConnectLine {
+        ConnectLine(Type t, Script.KernelID from, Script.KernelID to) {
+            mFrom = from;
+            mToK = to;
+            mAllocationType = t;
+        }
+
+        ConnectLine(Type t, Script.KernelID from, Script.FieldID to) {
+            mFrom = from;
+            mToF = to;
+            mAllocationType = t;
+        }
+
+        Script.FieldID mToF;
+        Script.KernelID mToK;
+        Script.KernelID mFrom;
+        Type mAllocationType;
+    }
+
+    static class Node {
+        Script mScript;
+        ArrayList<Script.KernelID> mKernels = new ArrayList<Script.KernelID>();
+        ArrayList<ConnectLine> mInputs = new ArrayList<ConnectLine>();
+        ArrayList<ConnectLine> mOutputs = new ArrayList<ConnectLine>();
+        int dagNumber;
+
+        Node mNext;
+
+        Node(Script s) {
+            mScript = s;
+        }
+    }
+
+
+    ScriptGroup(int id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Sets an input of the ScriptGroup. This specifies an
+     * Allocation to be used for the kernels which require a kernel
+     * input and that input is provided external to the group.
+     *
+     * @param s The ID of the kernel where the allocation should be
+     *          connected.
+     * @param a The allocation to connect.
+     */
+    public void setInput(Script.KernelID s, Allocation a) {
+        for (int ct=0; ct < mInputs.length; ct++) {
+            if (mInputs[ct].mKID == s) {
+                mInputs[ct].mAllocation = a;
+                mRS.nScriptGroupSetInput(getID(mRS), s.getID(mRS), mRS.safeID(a));
+                return;
+            }
+        }
+        throw new RSIllegalArgumentException("Script not found");
+    }
+
+    /**
+     * Sets an output of the ScriptGroup. This specifies an
+     * Allocation to be used for the kernels which require a kernel
+     * output and that output is provided external to the group.
+     *
+     * @param s The ID of the kernel where the allocation should be
+     *          connected.
+     * @param a The allocation to connect.
+     */
+    public void setOutput(Script.KernelID s, Allocation a) {
+        for (int ct=0; ct < mOutputs.length; ct++) {
+            if (mOutputs[ct].mKID == s) {
+                mOutputs[ct].mAllocation = a;
+                mRS.nScriptGroupSetOutput(getID(mRS), s.getID(mRS), mRS.safeID(a));
+                return;
+            }
+        }
+        throw new RSIllegalArgumentException("Script not found");
+    }
+
+    /**
+     * Execute the ScriptGroup.  This will run all the kernels in
+     * the script.  The state of the connecting lines will not be
+     * observable after this operation.
+     */
+    public void execute() {
+        mRS.nScriptGroupExecute(getID(mRS));
+    }
+
+
+    /**
+     * Create a ScriptGroup. There are two steps to creating a
+     * ScriptGoup.
+     * <p>
+     * First all the Kernels to be used by the group should be
+     * added.  Once this is done the kernels should be connected.
+     * Kernels cannot be added once a connection has been made.
+     * <p>
+     * Second, add connections. There are two forms of connections.
+     * Kernel to Kernel and Kernel to Field. Kernel to Kernel is
+     * higher performance and should be used where possible. The
+     * line of connections cannot form a loop. If a loop is detected
+     * an exception is thrown.
+     * <p>
+     * Once all the connections are made a call to create will
+     * return the ScriptGroup object.
+     *
+     */
+    public static final class Builder {
+        private RenderScript mRS;
+        private ArrayList<Node> mNodes = new ArrayList<Node>();
+        private ArrayList<ConnectLine> mLines = new ArrayList<ConnectLine>();
+        private int mKernelCount;
+
+        /**
+         * Create a builder for generating a ScriptGroup.
+         *
+         *
+         * @param rs The Renderscript context.
+         */
+        public Builder(RenderScript rs) {
+            mRS = rs;
+        }
+
+        // do a DFS from original node, looking for original node
+        // any cycle that could be created must contain original node
+        private void validateCycle(Node target, Node original) {
+            for (int ct = 0; ct < target.mOutputs.size(); ct++) {
+                final ConnectLine cl = target.mOutputs.get(ct);
+                if (cl.mToK != null) {
+                    Node tn = findNode(cl.mToK.mScript);
+                    if (tn.equals(original)) {
+                        throw new RSInvalidStateException("Loops in group not allowed.");
+                    }
+                    validateCycle(tn, original);
+                }
+                if (cl.mToF != null) {
+                    Node tn = findNode(cl.mToF.mScript);
+                    if (tn.equals(original)) {
+                        throw new RSInvalidStateException("Loops in group not allowed.");
+                    }
+                    validateCycle(tn, original);
+                }
+            }
+        }
+
+        private void mergeDAGs(int valueUsed, int valueKilled) {
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                if (mNodes.get(ct).dagNumber == valueKilled)
+                    mNodes.get(ct).dagNumber = valueUsed;
+            }
+        }
+
+        private void validateDAGRecurse(Node n, int dagNumber) {
+            // combine DAGs if this node has been seen already
+            if (n.dagNumber != 0 && n.dagNumber != dagNumber) {
+                mergeDAGs(n.dagNumber, dagNumber);
+                return;
+            }
+
+            n.dagNumber = dagNumber;
+            for (int ct=0; ct < n.mOutputs.size(); ct++) {
+                final ConnectLine cl = n.mOutputs.get(ct);
+                if (cl.mToK != null) {
+                    Node tn = findNode(cl.mToK.mScript);
+                    validateDAGRecurse(tn, dagNumber);
+                }
+                if (cl.mToF != null) {
+                    Node tn = findNode(cl.mToF.mScript);
+                    validateDAGRecurse(tn, dagNumber);
+                }
+            }
+        }
+
+        private void validateDAG() {
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                Node n = mNodes.get(ct);
+                if (n.mInputs.size() == 0) {
+                    if (n.mOutputs.size() == 0 && mNodes.size() > 1) {
+                        throw new RSInvalidStateException("Groups cannot contain unconnected scripts");
+                    }
+                    validateDAGRecurse(n, ct+1);
+                }
+            }
+            int dagNumber = mNodes.get(0).dagNumber;
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                if (mNodes.get(ct).dagNumber != dagNumber) {
+                    throw new RSInvalidStateException("Multiple DAGs in group not allowed.");
+                }
+            }
+        }
+
+        private Node findNode(Script s) {
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                if (s == mNodes.get(ct).mScript) {
+                    return mNodes.get(ct);
+                }
+            }
+            return null;
+        }
+
+        private Node findNode(Script.KernelID k) {
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                Node n = mNodes.get(ct);
+                for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
+                    if (k == n.mKernels.get(ct2)) {
+                        return n;
+                    }
+                }
+            }
+            return null;
+        }
+
+        /**
+         * Adds a Kernel to the group.
+         *
+         *
+         * @param k The kernel to add.
+         *
+         * @return Builder Returns this.
+         */
+        public Builder addKernel(Script.KernelID k) {
+            if (mLines.size() != 0) {
+                throw new RSInvalidStateException(
+                    "Kernels may not be added once connections exist.");
+            }
+
+            //android.util.Log.v("RSR", "addKernel 1 k=" + k);
+            if (findNode(k) != null) {
+                return this;
+            }
+            //android.util.Log.v("RSR", "addKernel 2 ");
+            mKernelCount++;
+            Node n = findNode(k.mScript);
+            if (n == null) {
+                //android.util.Log.v("RSR", "addKernel 3 ");
+                n = new Node(k.mScript);
+                mNodes.add(n);
+            }
+            n.mKernels.add(k);
+            return this;
+        }
+
+        /**
+         * Adds a connection to the group.
+         *
+         *
+         * @param t The type of the connection. This is used to
+         *          determine the kernel launch sizes on the source side
+         *          of this connection.
+         * @param from The source for the connection.
+         * @param to The destination of the connection.
+         *
+         * @return Builder Returns this
+         */
+        public Builder addConnection(Type t, Script.KernelID from, Script.FieldID to) {
+            //android.util.Log.v("RSR", "addConnection " + t +", " + from + ", " + to);
+
+            Node nf = findNode(from);
+            if (nf == null) {
+                throw new RSInvalidStateException("From script not found.");
+            }
+
+            Node nt = findNode(to.mScript);
+            if (nt == null) {
+                throw new RSInvalidStateException("To script not found.");
+            }
+
+            ConnectLine cl = new ConnectLine(t, from, to);
+            mLines.add(new ConnectLine(t, from, to));
+
+            nf.mOutputs.add(cl);
+            nt.mInputs.add(cl);
+
+            validateCycle(nf, nf);
+            return this;
+        }
+
+        /**
+         * Adds a connection to the group.
+         *
+         *
+         * @param t The type of the connection. This is used to
+         *          determine the kernel launch sizes for both sides of
+         *          this connection.
+         * @param from The source for the connection.
+         * @param to The destination of the connection.
+         *
+         * @return Builder Returns this
+         */
+        public Builder addConnection(Type t, Script.KernelID from, Script.KernelID to) {
+            //android.util.Log.v("RSR", "addConnection " + t +", " + from + ", " + to);
+
+            Node nf = findNode(from);
+            if (nf == null) {
+                throw new RSInvalidStateException("From script not found.");
+            }
+
+            Node nt = findNode(to);
+            if (nt == null) {
+                throw new RSInvalidStateException("To script not found.");
+            }
+
+            ConnectLine cl = new ConnectLine(t, from, to);
+            mLines.add(new ConnectLine(t, from, to));
+
+            nf.mOutputs.add(cl);
+            nt.mInputs.add(cl);
+
+            validateCycle(nf, nf);
+            return this;
+        }
+
+
+
+        /**
+         * Creates the Script group.
+         *
+         *
+         * @return ScriptGroup The new ScriptGroup
+         */
+        public ScriptGroup create() {
+
+            if (mNodes.size() == 0) {
+                throw new RSInvalidStateException("Empty script groups are not allowed");
+            }
+
+            // reset DAG numbers in case we're building a second group
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                mNodes.get(ct).dagNumber = 0;
+            }
+            validateDAG();
+
+            ArrayList<IO> inputs = new ArrayList<IO>();
+            ArrayList<IO> outputs = new ArrayList<IO>();
+
+            int[] kernels = new int[mKernelCount];
+            int idx = 0;
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                Node n = mNodes.get(ct);
+                for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
+                    final Script.KernelID kid = n.mKernels.get(ct2);
+                    kernels[idx++] = kid.getID(mRS);
+
+                    boolean hasInput = false;
+                    boolean hasOutput = false;
+                    for (int ct3=0; ct3 < n.mInputs.size(); ct3++) {
+                        if (n.mInputs.get(ct3).mToK == kid) {
+                            hasInput = true;
+                        }
+                    }
+                    for (int ct3=0; ct3 < n.mOutputs.size(); ct3++) {
+                        if (n.mOutputs.get(ct3).mFrom == kid) {
+                            hasOutput = true;
+                        }
+                    }
+                    if (!hasInput) {
+                        inputs.add(new IO(kid));
+                    }
+                    if (!hasOutput) {
+                        outputs.add(new IO(kid));
+                    }
+
+                }
+            }
+            if (idx != mKernelCount) {
+                throw new RSRuntimeException("Count mismatch, should not happen.");
+            }
+
+            int[] src = new int[mLines.size()];
+            int[] dstk = new int[mLines.size()];
+            int[] dstf = new int[mLines.size()];
+            int[] types = new int[mLines.size()];
+
+            for (int ct=0; ct < mLines.size(); ct++) {
+                ConnectLine cl = mLines.get(ct);
+                src[ct] = cl.mFrom.getID(mRS);
+                if (cl.mToK != null) {
+                    dstk[ct] = cl.mToK.getID(mRS);
+                }
+                if (cl.mToF != null) {
+                    dstf[ct] = cl.mToF.getID(mRS);
+                }
+                types[ct] = cl.mAllocationType.getID(mRS);
+            }
+
+            int id = mRS.nScriptGroupCreate(kernels, src, dstk, dstf, types);
+            if (id == 0) {
+                throw new RSRuntimeException("Object creation error, should not happen.");
+            }
+
+            ScriptGroup sg = new ScriptGroup(id, mRS);
+            sg.mOutputs = new IO[outputs.size()];
+            for (int ct=0; ct < outputs.size(); ct++) {
+                sg.mOutputs[ct] = outputs.get(ct);
+            }
+
+            sg.mInputs = new IO[inputs.size()];
+            for (int ct=0; ct < inputs.size(); ct++) {
+                sg.mInputs[ct] = inputs.get(ct);
+            }
+
+            return sg;
+        }
+
+    }
+
+
+}
+
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsic.java b/graphics/java/android/renderscript/ScriptIntrinsic.java
new file mode 100644
index 0000000..f54943a
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsic.java
@@ -0,0 +1,36 @@
+/*
+ * 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.renderscript;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+
+/**
+ * Base class for all Intrinsic scripts. An intrinsic a script
+ * which implements a pre-defined function. Intrinsics are
+ * provided to provide effecient implemtations of common
+ * operations.
+ *
+ * Not intended for direct use.
+ **/
+public abstract class ScriptIntrinsic extends Script {
+    ScriptIntrinsic(int id, RenderScript rs) {
+        super(id, rs);
+    }
+}
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicBlend.java b/graphics/java/android/renderscript/ScriptIntrinsicBlend.java
new file mode 100644
index 0000000..65c69c0
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicBlend.java
@@ -0,0 +1,465 @@
+/*
+ * 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.renderscript;
+
+
+/**
+ * Intrinsic kernels for blending two buffers. Each blend function is a separate
+ * kernel to make it easy to change between blend modes.
+ **/
+public class ScriptIntrinsicBlend extends ScriptIntrinsic {
+    ScriptIntrinsicBlend(int id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Supported elements types are uchar4
+     *
+     *
+     * @param rs
+     * @param e
+     *
+     * @return ScriptIntrinsicBlend
+     */
+    public static ScriptIntrinsicBlend create(RenderScript rs, Element e) {
+        // 7 comes from RS_SCRIPT_INTRINSIC_ID_BLEND in rsDefines.h
+        int id = rs.nScriptIntrinsicCreate(7, e.getID(rs));
+        return new ScriptIntrinsicBlend(id, rs);
+
+    }
+
+    private void blend(int id, Allocation ain, Allocation aout) {
+        if (!ain.getElement().isCompatible(Element.U8_4(mRS))) {
+            throw new RSIllegalArgumentException("Input is not of expected format.");
+        }
+        if (!aout.getElement().isCompatible(Element.U8_4(mRS))) {
+            throw new RSIllegalArgumentException("Output is not of expected format.");
+        }
+        forEach(id, ain, aout, null);
+    }
+
+    /**
+     * dst = {0, 0, 0, 0}
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachClear(Allocation ain, Allocation aout) {
+        blend(0, ain, aout);
+    }
+
+    /**
+     * Get a KernelID for the Clear kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDClear() {
+        return createKernelID(0, 3, null, null);
+    }
+
+
+    /**
+     * dst = src
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachSrc(Allocation ain, Allocation aout) {
+        blend(1, ain, aout);
+    }
+
+    /**
+     * Get a KernelID for the Src kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDSrc() {
+        return createKernelID(1, 3, null, null);
+    }
+
+    /**
+     * dst = dst
+     * This is a NOP
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachDst(Allocation ain, Allocation aout) {
+        // NOP
+    }
+
+    /**
+     * Get a KernelID for the Dst kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDDst() {
+        return createKernelID(2, 3, null, null);
+    }
+
+    /**
+     * dst = src + dst * (1.0 - src.a)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachSrcOver(Allocation ain, Allocation aout) {
+        blend(3, ain, aout);
+    }
+
+    /**
+     * Get a KernelID for the SrcOver kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDSrcOver() {
+        return createKernelID(3, 3, null, null);
+    }
+
+    /**
+     * dst = dst + src * (1.0 - dst.a)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachDstOver(Allocation ain, Allocation aout) {
+        blend(4, ain, aout);
+    }
+
+    /**
+     * Get a KernelID for the DstOver kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDDstOver() {
+        return createKernelID(4, 3, null, null);
+    }
+
+    /**
+     * dst = src * dst.a
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachSrcIn(Allocation ain, Allocation aout) {
+        blend(5, ain, aout);
+    }
+
+    /**
+     * Get a KernelID for the SrcIn kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDSrcIn() {
+        return createKernelID(5, 3, null, null);
+    }
+
+    /**
+     * dst = dst * src.a
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachDstIn(Allocation ain, Allocation aout) {
+        blend(6, ain, aout);
+    }
+
+    /**
+     * Get a KernelID for the DstIn kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDDstIn() {
+        return createKernelID(6, 3, null, null);
+    }
+
+    /**
+     * dst = src * (1.0 - dst.a)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachSrcOut(Allocation ain, Allocation aout) {
+        blend(7, ain, aout);
+    }
+
+    /**
+     * Get a KernelID for the SrcOut kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDSrcOut() {
+        return createKernelID(7, 3, null, null);
+    }
+
+    /**
+     * dst = dst * (1.0 - src.a)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachDstOut(Allocation ain, Allocation aout) {
+        blend(8, ain, aout);
+    }
+
+    /**
+     * Get a KernelID for the DstOut kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDDstOut() {
+        return createKernelID(8, 3, null, null);
+    }
+
+    /**
+     * dst.rgb = src.rgb * dst.a + (1.0 - src.a) * dst.rgb
+     * dst.a = dst.a
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachSrcAtop(Allocation ain, Allocation aout) {
+        blend(9, ain, aout);
+    }
+
+    /**
+     * Get a KernelID for the SrcAtop kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDSrcAtop() {
+        return createKernelID(9, 3, null, null);
+    }
+
+    /**
+     * dst = dst.rgb * src.a + (1.0 - dst.a) * src.rgb
+     * dst.a = src.a
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachDstAtop(Allocation ain, Allocation aout) {
+        blend(10, ain, aout);
+    }
+
+    /**
+     * Get a KernelID for the DstAtop kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDDstAtop() {
+        return createKernelID(10, 3, null, null);
+    }
+
+    /**
+     * dst = {src.r ^ dst.r, src.g ^ dst.g, src.b ^ dst.b, src.a ^ dst.a}
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachXor(Allocation ain, Allocation aout) {
+        blend(11, ain, aout);
+    }
+
+    /**
+     * Get a KernelID for the Xor kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDXor() {
+        return createKernelID(11, 3, null, null);
+    }
+
+    ////////
+/*
+    public void forEachNormal(Allocation ain, Allocation aout) {
+        blend(12, ain, aout);
+    }
+
+    public void forEachAverage(Allocation ain, Allocation aout) {
+        blend(13, ain, aout);
+    }
+*/
+    /**
+     * dst = src * dst
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachMultiply(Allocation ain, Allocation aout) {
+        blend(14, ain, aout);
+    }
+
+    /**
+     * Get a KernelID for the Multiply kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDMultiply() {
+        return createKernelID(14, 3, null, null);
+    }
+
+/*
+    public void forEachScreen(Allocation ain, Allocation aout) {
+        blend(15, ain, aout);
+    }
+
+    public void forEachDarken(Allocation ain, Allocation aout) {
+        blend(16, ain, aout);
+    }
+
+    public void forEachLighten(Allocation ain, Allocation aout) {
+        blend(17, ain, aout);
+    }
+
+    public void forEachOverlay(Allocation ain, Allocation aout) {
+        blend(18, ain, aout);
+    }
+
+    public void forEachHardlight(Allocation ain, Allocation aout) {
+        blend(19, ain, aout);
+    }
+
+    public void forEachSoftlight(Allocation ain, Allocation aout) {
+        blend(20, ain, aout);
+    }
+
+    public void forEachDifference(Allocation ain, Allocation aout) {
+        blend(21, ain, aout);
+    }
+
+    public void forEachNegation(Allocation ain, Allocation aout) {
+        blend(22, ain, aout);
+    }
+
+    public void forEachExclusion(Allocation ain, Allocation aout) {
+        blend(23, ain, aout);
+    }
+
+    public void forEachColorDodge(Allocation ain, Allocation aout) {
+        blend(24, ain, aout);
+    }
+
+    public void forEachInverseColorDodge(Allocation ain, Allocation aout) {
+        blend(25, ain, aout);
+    }
+
+    public void forEachSoftDodge(Allocation ain, Allocation aout) {
+        blend(26, ain, aout);
+    }
+
+    public void forEachColorBurn(Allocation ain, Allocation aout) {
+        blend(27, ain, aout);
+    }
+
+    public void forEachInverseColorBurn(Allocation ain, Allocation aout) {
+        blend(28, ain, aout);
+    }
+
+    public void forEachSoftBurn(Allocation ain, Allocation aout) {
+        blend(29, ain, aout);
+    }
+
+    public void forEachReflect(Allocation ain, Allocation aout) {
+        blend(30, ain, aout);
+    }
+
+    public void forEachGlow(Allocation ain, Allocation aout) {
+        blend(31, ain, aout);
+    }
+
+    public void forEachFreeze(Allocation ain, Allocation aout) {
+        blend(32, ain, aout);
+    }
+
+    public void forEachHeat(Allocation ain, Allocation aout) {
+        blend(33, ain, aout);
+    }
+*/
+    /**
+     * dst = min(src + dst, 1.0)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachAdd(Allocation ain, Allocation aout) {
+        blend(34, ain, aout);
+    }
+
+    /**
+     * Get a KernelID for the Add kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDAdd() {
+        return createKernelID(34, 3, null, null);
+    }
+
+    /**
+     * dst = max(dst - src, 0.0)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachSubtract(Allocation ain, Allocation aout) {
+        blend(35, ain, aout);
+    }
+
+    /**
+     * Get a KernelID for the Subtract kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDSubtract() {
+        return createKernelID(35, 3, null, null);
+    }
+
+/*
+    public void forEachStamp(Allocation ain, Allocation aout) {
+        blend(36, ain, aout);
+    }
+
+    public void forEachRed(Allocation ain, Allocation aout) {
+        blend(37, ain, aout);
+    }
+
+    public void forEachGreen(Allocation ain, Allocation aout) {
+        blend(38, ain, aout);
+    }
+
+    public void forEachBlue(Allocation ain, Allocation aout) {
+        blend(39, ain, aout);
+    }
+
+    public void forEachHue(Allocation ain, Allocation aout) {
+        blend(40, ain, aout);
+    }
+
+    public void forEachSaturation(Allocation ain, Allocation aout) {
+        blend(41, ain, aout);
+    }
+
+    public void forEachColor(Allocation ain, Allocation aout) {
+        blend(42, ain, aout);
+    }
+
+    public void forEachLuminosity(Allocation ain, Allocation aout) {
+        blend(43, ain, aout);
+    }
+*/
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicBlur.java b/graphics/java/android/renderscript/ScriptIntrinsicBlur.java
new file mode 100644
index 0000000..11164e3
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicBlur.java
@@ -0,0 +1,112 @@
+/*
+ * 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.renderscript;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+/**
+ * Intrinsic Gausian blur filter. Applies a gaussian blur of the
+ * specified radius to all elements of an allocation.
+ *
+ *
+ **/
+public final class ScriptIntrinsicBlur extends ScriptIntrinsic {
+    private final float[] mValues = new float[9];
+    private Allocation mInput;
+
+    private ScriptIntrinsicBlur(int id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Create an intrinsic for applying a blur to an allocation. The
+     * default radius is 5.0.
+     *
+     * Supported elements types are {@link Element#U8_4}
+     *
+     * @param rs The Renderscript context
+     * @param e Element type for inputs and outputs
+     *
+     * @return ScriptIntrinsicBlur
+     */
+    public static ScriptIntrinsicBlur create(RenderScript rs, Element e) {
+        if (e != Element.U8_4(rs)) {
+            throw new RSIllegalArgumentException("Unsuported element type.");
+        }
+        int id = rs.nScriptIntrinsicCreate(5, e.getID(rs));
+        ScriptIntrinsicBlur sib = new ScriptIntrinsicBlur(id, rs);
+        sib.setRadius(5.f);
+        return sib;
+    }
+
+    /**
+     * Set the input of the blur.
+     * Must match the element type supplied during create.
+     *
+     * @param ain The input allocation
+     */
+    public void setInput(Allocation ain) {
+        mInput = ain;
+        setVar(1, ain);
+    }
+
+    /**
+     * Set the radius of the Blur.
+     *
+     * Supported range 0 < radius <= 25
+     *
+     * @param radius The radius of the blur
+     */
+    public void setRadius(float radius) {
+        if (radius <= 0 || radius > 25) {
+            throw new RSIllegalArgumentException("Radius out of range (0 < r <= 25).");
+        }
+        setVar(0, radius);
+    }
+
+    /**
+     * Apply the filter to the input and save to the specified
+     * allocation.
+     *
+     * @param aout Output allocation. Must match creation element
+     *             type.
+     */
+    public void forEach(Allocation aout) {
+        forEach(0, null, aout, null);
+    }
+
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 2, null, null);
+    }
+
+    /**
+     * Get a FieldID for the input field of this intrinsic.
+     *
+     * @return Script.FieldID The FieldID object.
+     */
+    public Script.FieldID getFieldID_Input() {
+        return createFieldID(1, null);
+    }
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java b/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java
new file mode 100644
index 0000000..cb458ba
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java
@@ -0,0 +1,167 @@
+/*
+ * 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.renderscript;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+/**
+ * Intrinsic for applying a color matrix to allocations.
+ *
+ * This has the same effect as loading each element and
+ * converting it to a {@link Element#F32_4}, multiplying the
+ * result by the 4x4 color matrix as performed by
+ * rsMatrixMultiply() and writing it to the output after
+ * conversion back to {@link Element#U8_4}.
+ **/
+public final class ScriptIntrinsicColorMatrix extends ScriptIntrinsic {
+    private final Matrix4f mMatrix = new Matrix4f();
+    private Allocation mInput;
+
+    private ScriptIntrinsicColorMatrix(int id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Create an intrinsic for applying a color matrix to an
+     * allocation.
+     *
+     * Supported elements types are {@link Element#U8_4}
+     *
+     * @param rs The Renderscript context
+     * @param e Element type for intputs and outputs
+     *
+     * @return ScriptIntrinsicColorMatrix
+     */
+    public static ScriptIntrinsicColorMatrix create(RenderScript rs, Element e) {
+        if (e != Element.U8_4(rs)) {
+            throw new RSIllegalArgumentException("Unsuported element type.");
+        }
+        int id = rs.nScriptIntrinsicCreate(2, e.getID(rs));
+        return new ScriptIntrinsicColorMatrix(id, rs);
+
+    }
+
+    private void setMatrix() {
+        FieldPacker fp = new FieldPacker(16*4);
+        fp.addMatrix(mMatrix);
+        setVar(0, fp);
+    }
+
+    /**
+     * Set the color matrix which will be applied to each cell of
+     * the image.
+     *
+     * @param m The 4x4 matrix to set.
+     */
+    public void setColorMatrix(Matrix4f m) {
+        mMatrix.load(m);
+        setMatrix();
+    }
+
+    /**
+     * Set the color matrix which will be applied to each cell of the image.
+     * This will set the alpha channel to be a copy.
+     *
+     * @param m The 3x3 matrix to set.
+     */
+    public void setColorMatrix(Matrix3f m) {
+        mMatrix.load(m);
+        setMatrix();
+    }
+
+    /**
+     * Set a color matrix to convert from RGB to luminance. The alpha channel
+     * will be a copy.
+     *
+     */
+    public void setGreyscale() {
+        mMatrix.loadIdentity();
+        mMatrix.set(0, 0, 0.299f);
+        mMatrix.set(1, 0, 0.587f);
+        mMatrix.set(2, 0, 0.114f);
+        mMatrix.set(0, 1, 0.299f);
+        mMatrix.set(1, 1, 0.587f);
+        mMatrix.set(2, 1, 0.114f);
+        mMatrix.set(0, 2, 0.299f);
+        mMatrix.set(1, 2, 0.587f);
+        mMatrix.set(2, 2, 0.114f);
+        setMatrix();
+    }
+
+    /**
+     * Set the matrix to convert from YUV to RGB with a direct copy of the 4th
+     * channel.
+     *
+     */
+    public void setYUVtoRGB() {
+        mMatrix.loadIdentity();
+        mMatrix.set(0, 0, 1.f);
+        mMatrix.set(1, 0, 0.f);
+        mMatrix.set(2, 0, 1.13983f);
+        mMatrix.set(0, 1, 1.f);
+        mMatrix.set(1, 1, -0.39465f);
+        mMatrix.set(2, 1, -0.5806f);
+        mMatrix.set(0, 2, 1.f);
+        mMatrix.set(1, 2, 2.03211f);
+        mMatrix.set(2, 2, 0.f);
+        setMatrix();
+    }
+
+    /**
+     * Set the matrix to convert from RGB to YUV with a direct copy of the 4th
+     * channel.
+     *
+     */
+    public void setRGBtoYUV() {
+        mMatrix.loadIdentity();
+        mMatrix.set(0, 0, 0.299f);
+        mMatrix.set(1, 0, 0.587f);
+        mMatrix.set(2, 0, 0.114f);
+        mMatrix.set(0, 1, -0.14713f);
+        mMatrix.set(1, 1, -0.28886f);
+        mMatrix.set(2, 1, 0.436f);
+        mMatrix.set(0, 2, 0.615f);
+        mMatrix.set(1, 2, -0.51499f);
+        mMatrix.set(2, 2, -0.10001f);
+        setMatrix();
+    }
+
+
+    /**
+     * Invoke the kernel and apply the matrix to each cell of ain and copy to
+     * aout.
+     *
+     * @param ain Input allocation
+     * @param aout Output allocation
+     */
+    public void forEach(Allocation ain, Allocation aout) {
+        forEach(0, ain, aout, null);
+    }
+
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 3, null, null);
+    }
+
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java b/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
new file mode 100644
index 0000000..91efa02
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
@@ -0,0 +1,125 @@
+/*
+ * 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.renderscript;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+/**
+ * Intrinsic for applying a 3x3 convolve to an allocation.
+ *
+ **/
+public final class ScriptIntrinsicConvolve3x3 extends ScriptIntrinsic {
+    private final float[] mValues = new float[9];
+    private Allocation mInput;
+
+    private ScriptIntrinsicConvolve3x3(int id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Supported elements types are {@link Element#U8_4}
+     *
+     * The default coefficients are.
+     *
+     * <code>
+     * <p> [ 0,  0,  0 ]
+     * <p> [ 0,  1,  0 ]
+     * <p> [ 0,  0,  0 ]
+     * </code>
+     *
+     * @param rs The Renderscript context
+     * @param e Element type for intputs and outputs
+     *
+     * @return ScriptIntrinsicConvolve3x3
+     */
+    public static ScriptIntrinsicConvolve3x3 create(RenderScript rs, Element e) {
+        float f[] = { 0, 0, 0, 0, 1, 0, 0, 0, 0};
+        if (e != Element.U8_4(rs)) {
+            throw new RSIllegalArgumentException("Unsuported element type.");
+        }
+        int id = rs.nScriptIntrinsicCreate(1, e.getID(rs));
+        ScriptIntrinsicConvolve3x3 si = new ScriptIntrinsicConvolve3x3(id, rs);
+        si.setCoefficients(f);
+        return si;
+
+    }
+
+    /**
+     * Set the input of the blur.
+     * Must match the element type supplied during create.
+     *
+     * @param ain The input allocation.
+     */
+    public void setInput(Allocation ain) {
+        mInput = ain;
+        setVar(1, ain);
+    }
+
+    /**
+     * Set the coefficients for the convolve.
+     *
+     * The convolve layout is
+     * <code>
+     * <p> [ 0,  1,  2 ]
+     * <p> [ 3,  4,  5 ]
+     * <p> [ 6,  7,  8 ]
+     * </code>
+     *
+     * @param v The array of coefficients to set
+     */
+    public void setCoefficients(float v[]) {
+        FieldPacker fp = new FieldPacker(9*4);
+        for (int ct=0; ct < mValues.length; ct++) {
+            mValues[ct] = v[ct];
+            fp.addF32(mValues[ct]);
+        }
+        setVar(0, fp);
+    }
+
+    /**
+     * Apply the filter to the input and save to the specified
+     * allocation.
+     *
+     * @param aout Output allocation. Must match creation element
+     *             type.
+     */
+    public void forEach(Allocation aout) {
+        forEach(0, null, aout, null);
+    }
+
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 2, null, null);
+    }
+
+    /**
+     * Get a FieldID for the input field of this intrinsic.
+     *
+     * @return Script.FieldID The FieldID object.
+     */
+    public Script.FieldID getFieldID_Input() {
+        return createFieldID(1, null);
+    }
+
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java b/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
new file mode 100644
index 0000000..1f52e3f
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
@@ -0,0 +1,119 @@
+/*
+ * 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.renderscript;
+
+import android.util.Log;
+
+/**
+ * Intrinsic for applying a 5x5 convolve to an allocation.
+ *
+ **/
+public final class ScriptIntrinsicConvolve5x5 extends ScriptIntrinsic {
+    private final float[] mValues = new float[25];
+    private Allocation mInput;
+
+    private ScriptIntrinsicConvolve5x5(int id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Supported elements types are {@link Element#U8_4}
+     *
+     * The default coefficients are.
+     * <code>
+     * <p> [ 0,  0,  0,  0,  0  ]
+     * <p> [ 0,  0,  0,  0,  0  ]
+     * <p> [ 0,  0,  1,  0,  0  ]
+     * <p> [ 0,  0,  0,  0,  0  ]
+     * <p> [ 0,  0,  0,  0,  0  ]
+     * </code>
+     *
+     * @param rs The Renderscript context
+     * @param e Element type for intputs and outputs
+     *
+     * @return ScriptIntrinsicConvolve5x5
+     */
+    public static ScriptIntrinsicConvolve5x5 create(RenderScript rs, Element e) {
+        int id = rs.nScriptIntrinsicCreate(4, e.getID(rs));
+        return new ScriptIntrinsicConvolve5x5(id, rs);
+
+    }
+
+    /**
+     * Set the input of the blur.
+     * Must match the element type supplied during create.
+     *
+     * @param ain The input allocation.
+     */
+    public void setInput(Allocation ain) {
+        mInput = ain;
+        setVar(1, ain);
+    }
+
+    /**
+    * Set the coefficients for the convolve.
+    *
+    * The convolve layout is
+    * <code>
+    * <p> [ 0,  1,  2,  3,  4  ]
+    * <p> [ 5,  6,  7,  8,  9  ]
+    * <p> [ 10, 11, 12, 13, 14 ]
+    * <p> [ 15, 16, 17, 18, 19 ]
+    * <p> [ 20, 21, 22, 23, 24 ]
+    * </code>
+    *
+    * @param v The array of coefficients to set
+    */
+    public void setCoefficients(float v[]) {
+        FieldPacker fp = new FieldPacker(25*4);
+        for (int ct=0; ct < mValues.length; ct++) {
+            mValues[ct] = v[ct];
+            fp.addF32(mValues[ct]);
+        }
+        setVar(0, fp);
+    }
+
+    /**
+     * Apply the filter to the input and save to the specified
+     * allocation.
+     *
+     * @param aout Output allocation. Must match creation element
+     *             type.
+     */
+    public void forEach(Allocation aout) {
+        forEach(0, null, aout, null);
+    }
+
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 2, null, null);
+    }
+
+    /**
+     * Get a FieldID for the input field of this intrinsic.
+     *
+     * @return Script.FieldID The FieldID object.
+     */
+    public Script.FieldID getFieldID_Input() {
+        return createFieldID(1, null);
+    }
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicLUT.java b/graphics/java/android/renderscript/ScriptIntrinsicLUT.java
new file mode 100644
index 0000000..41bdd25
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicLUT.java
@@ -0,0 +1,146 @@
+/*
+ * 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.renderscript;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+/**
+ * Intrinsic for applying a per-channel lookup table. Each
+ * channel of the input has an independant lookup table. The
+ * tables are 256 entries in size and can cover the full value
+ * range of {@link Element#U8_4}.
+ **/
+public final class ScriptIntrinsicLUT extends ScriptIntrinsic {
+    private final Matrix4f mMatrix = new Matrix4f();
+    private Allocation mTables;
+    private final byte mCache[] = new byte[1024];
+    private boolean mDirty = true;
+
+    private ScriptIntrinsicLUT(int id, RenderScript rs) {
+        super(id, rs);
+        mTables = Allocation.createSized(rs, Element.U8(rs), 1024);
+        for (int ct=0; ct < 256; ct++) {
+            mCache[ct] = (byte)ct;
+            mCache[ct + 256] = (byte)ct;
+            mCache[ct + 512] = (byte)ct;
+            mCache[ct + 768] = (byte)ct;
+        }
+        setVar(0, mTables);
+    }
+
+    /**
+     * Supported elements types are {@link Element#U8_4}
+     *
+     * The defaults tables are identity.
+     *
+     * @param rs The Renderscript context
+     * @param e Element type for intputs and outputs
+     *
+     * @return ScriptIntrinsicLUT
+     */
+    public static ScriptIntrinsicLUT create(RenderScript rs, Element e) {
+        int id = rs.nScriptIntrinsicCreate(3, e.getID(rs));
+        return new ScriptIntrinsicLUT(id, rs);
+
+    }
+
+
+    private void validate(int index, int value) {
+        if (index < 0 || index > 255) {
+            throw new RSIllegalArgumentException("Index out of range (0-255).");
+        }
+        if (value < 0 || value > 255) {
+            throw new RSIllegalArgumentException("Value out of range (0-255).");
+        }
+    }
+
+    /**
+     * Set an entry in the red channel lookup table
+     *
+     * @param index Must be 0-255
+     * @param value Must be 0-255
+     */
+    public void setRed(int index, int value) {
+        validate(index, value);
+        mCache[index] = (byte)value;
+        mDirty = true;
+    }
+
+    /**
+     * Set an entry in the green channel lookup table
+     *
+     * @param index Must be 0-255
+     * @param value Must be 0-255
+     */
+    public void setGreen(int index, int value) {
+        validate(index, value);
+        mCache[index+256] = (byte)value;
+        mDirty = true;
+    }
+
+    /**
+     * Set an entry in the blue channel lookup table
+     *
+     * @param index Must be 0-255
+     * @param value Must be 0-255
+     */
+    public void setBlue(int index, int value) {
+        validate(index, value);
+        mCache[index+512] = (byte)value;
+        mDirty = true;
+    }
+
+    /**
+     * Set an entry in the alpha channel lookup table
+     *
+     * @param index Must be 0-255
+     * @param value Must be 0-255
+     */
+    public void setAlpha(int index, int value) {
+        validate(index, value);
+        mCache[index+768] = (byte)value;
+        mDirty = true;
+    }
+
+
+    /**
+     * Invoke the kernel and apply the lookup to each cell of ain
+     * and copy to aout.
+     *
+     * @param ain Input allocation
+     * @param aout Output allocation
+     */
+    public void forEach(Allocation ain, Allocation aout) {
+        if (mDirty) {
+            mDirty = false;
+            mTables.copyFromUnchecked(mCache);
+        }
+        forEach(0, ain, aout, null);
+    }
+
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 3, null, null);
+    }
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java b/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
new file mode 100644
index 0000000..dc8a5aa
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
@@ -0,0 +1,89 @@
+/*
+ * 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.renderscript;
+
+
+/**
+ * Intrinsic for converting an Android YUV buffer to RGB.
+ *
+ * The input allocation is supplied in NV21 format as a U8
+ * element type. The output is RGBA, the alpha channel will be
+ * set to 255.
+ */
+public final class ScriptIntrinsicYuvToRGB extends ScriptIntrinsic {
+    private Allocation mInput;
+
+    ScriptIntrinsicYuvToRGB(int id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Create an intrinsic for converting YUV to RGB.
+     *
+     * Supported elements types are {@link Element#U8_4}
+     *
+     * @param rs The Renderscript context
+     * @param e Element type for output
+     *
+     * @return ScriptIntrinsicYuvToRGB
+     */
+    public static ScriptIntrinsicYuvToRGB create(RenderScript rs, Element e) {
+        // 6 comes from RS_SCRIPT_INTRINSIC_YUV_TO_RGB in rsDefines.h
+        int id = rs.nScriptIntrinsicCreate(6, e.getID(rs));
+        ScriptIntrinsicYuvToRGB si = new ScriptIntrinsicYuvToRGB(id, rs);
+        return si;
+    }
+
+
+    /**
+     * Set the input yuv allocation, must be {@link Element#U8}.
+     *
+     * @param ain The input allocation.
+     */
+    public void setInput(Allocation ain) {
+        mInput = ain;
+        setVar(0, ain);
+    }
+
+    /**
+     * Convert the image to RGB.
+     *
+     * @param aout Output allocation. Must match creation element
+     *             type.
+     */
+    public void forEach(Allocation aout) {
+        forEach(0, null, aout, null);
+    }
+
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 2, null, null);
+    }
+
+    /**
+     * Get a FieldID for the input field of this intrinsic.
+     *
+     * @return Script.FieldID The FieldID object.
+     */
+    public Script.FieldID getFieldID_Input() {
+        return createFieldID(0, null);
+    }
+}
diff --git a/graphics/jni/Android.mk b/graphics/jni/Android.mk
index e85a23c..80d7728 100644
--- a/graphics/jni/Android.mk
+++ b/graphics/jni/Android.mk
@@ -32,6 +32,6 @@
 LOCAL_MODULE:= librs_jni
 LOCAL_ADDITIONAL_DEPENDENCIES += $(rs_generated_source)
 LOCAL_MODULE_TAGS := optional
-LOCAL_REQUIRED_MODULES := libRS
+LOCAL_REQUIRED_MODULES := libRS libRSDriver
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 3d5d1a9..3f642e8 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -230,7 +230,7 @@
     if (wnd == NULL) {
 
     } else {
-        window = android_Surface_getNativeWindow(_env, wnd).get();
+        window = android_view_Surface_getNativeWindow(_env, wnd).get();
     }
 
     rsContextSetSurface(con, width, height, window);
@@ -489,12 +489,12 @@
 static void
 nAllocationSetSurface(JNIEnv *_env, jobject _this, RsContext con, RsAllocation alloc, jobject sur)
 {
-    LOG_API("nAllocationSetSurfaceTexture, con(%p), alloc(%p), surface(%p)",
+    LOG_API("nAllocationSetSurface, con(%p), alloc(%p), surface(%p)",
             con, alloc, (Surface *)sur);
 
     sp<Surface> s;
     if (sur != 0) {
-        s = Surface_getSurface(_env, sur);
+        s = android_view_Surface_getSurface(_env, sur);
     }
 
     rsAllocationSetSurface(con, alloc, static_cast<ANativeWindow *>(s.get()));
@@ -718,7 +718,7 @@
     LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
     jint *ptr = _env->GetIntArrayElements(data, NULL);
     jsize length = _env->GetArrayLength(data);
-    rsAllocationRead(con, (RsAllocation)alloc, ptr, length);
+    rsAllocationRead(con, (RsAllocation)alloc, ptr, length * sizeof(int));
     _env->ReleaseIntArrayElements(data, ptr, 0);
 }
 
@@ -729,7 +729,7 @@
     LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
     jshort *ptr = _env->GetShortArrayElements(data, NULL);
     jsize length = _env->GetArrayLength(data);
-    rsAllocationRead(con, (RsAllocation)alloc, ptr, length);
+    rsAllocationRead(con, (RsAllocation)alloc, ptr, length * sizeof(short));
     _env->ReleaseShortArrayElements(data, ptr, 0);
 }
 
@@ -740,7 +740,7 @@
     LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
     jbyte *ptr = _env->GetByteArrayElements(data, NULL);
     jsize length = _env->GetArrayLength(data);
-    rsAllocationRead(con, (RsAllocation)alloc, ptr, length);
+    rsAllocationRead(con, (RsAllocation)alloc, ptr, length * sizeof(char));
     _env->ReleaseByteArrayElements(data, ptr, 0);
 }
 
@@ -751,7 +751,7 @@
     LOG_API("nAllocationRead_f, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
     jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
     jsize length = _env->GetArrayLength(data);
-    rsAllocationRead(con, (RsAllocation)alloc, ptr, length);
+    rsAllocationRead(con, (RsAllocation)alloc, ptr, length * sizeof(float));
     _env->ReleaseFloatArrayElements(data, ptr, 0);
 }
 
@@ -1071,6 +1071,82 @@
     return ret;
 }
 
+static jint
+nScriptIntrinsicCreate(JNIEnv *_env, jobject _this, RsContext con, jint id, jint eid)
+{
+    LOG_API("nScriptIntrinsicCreate, con(%p) id(%i) element(%p)", con, id, (void *)eid);
+    return (jint)rsScriptIntrinsicCreate(con, id, (RsElement)eid);
+}
+
+static jint
+nScriptKernelIDCreate(JNIEnv *_env, jobject _this, RsContext con, jint sid, jint slot, jint sig)
+{
+    LOG_API("nScriptKernelIDCreate, con(%p) script(%p), slot(%i), sig(%i)", con, (void *)sid, slot, sig);
+    return (jint)rsScriptKernelIDCreate(con, (RsScript)sid, slot, sig);
+}
+
+static jint
+nScriptFieldIDCreate(JNIEnv *_env, jobject _this, RsContext con, jint sid, jint slot)
+{
+    LOG_API("nScriptFieldIDCreate, con(%p) script(%p), slot(%i)", con, (void *)sid, slot);
+    return (jint)rsScriptFieldIDCreate(con, (RsScript)sid, slot);
+}
+
+static jint
+nScriptGroupCreate(JNIEnv *_env, jobject _this, RsContext con, jintArray _kernels, jintArray _src,
+    jintArray _dstk, jintArray _dstf, jintArray _types)
+{
+    LOG_API("nScriptGroupCreate, con(%p)", con);
+
+    jint kernelsLen = _env->GetArrayLength(_kernels) * sizeof(int);
+    jint *kernelsPtr = _env->GetIntArrayElements(_kernels, NULL);
+    jint srcLen = _env->GetArrayLength(_src) * sizeof(int);
+    jint *srcPtr = _env->GetIntArrayElements(_src, NULL);
+    jint dstkLen = _env->GetArrayLength(_dstk) * sizeof(int);
+    jint *dstkPtr = _env->GetIntArrayElements(_dstk, NULL);
+    jint dstfLen = _env->GetArrayLength(_dstf) * sizeof(int);
+    jint *dstfPtr = _env->GetIntArrayElements(_dstf, NULL);
+    jint typesLen = _env->GetArrayLength(_types) * sizeof(int);
+    jint *typesPtr = _env->GetIntArrayElements(_types, NULL);
+
+    int id = (int)rsScriptGroupCreate(con,
+                               (RsScriptKernelID *)kernelsPtr, kernelsLen,
+                               (RsScriptKernelID *)srcPtr, srcLen,
+                               (RsScriptKernelID *)dstkPtr, dstkLen,
+                               (RsScriptFieldID *)dstfPtr, dstfLen,
+                               (RsType *)typesPtr, typesLen);
+
+    _env->ReleaseIntArrayElements(_kernels, kernelsPtr, 0);
+    _env->ReleaseIntArrayElements(_src, srcPtr, 0);
+    _env->ReleaseIntArrayElements(_dstk, dstkPtr, 0);
+    _env->ReleaseIntArrayElements(_dstf, dstfPtr, 0);
+    _env->ReleaseIntArrayElements(_types, typesPtr, 0);
+    return id;
+}
+
+static void
+nScriptGroupSetInput(JNIEnv *_env, jobject _this, RsContext con, jint gid, jint kid, jint alloc)
+{
+    LOG_API("nScriptGroupSetInput, con(%p) group(%p), kernelId(%p), alloc(%p)", con,
+        (void *)gid, (void *)kid, (void *)alloc);
+    rsScriptGroupSetInput(con, (RsScriptGroup)gid, (RsScriptKernelID)kid, (RsAllocation)alloc);
+}
+
+static void
+nScriptGroupSetOutput(JNIEnv *_env, jobject _this, RsContext con, jint gid, jint kid, jint alloc)
+{
+    LOG_API("nScriptGroupSetOutput, con(%p) group(%p), kernelId(%p), alloc(%p)", con,
+        (void *)gid, (void *)kid, (void *)alloc);
+    rsScriptGroupSetOutput(con, (RsScriptGroup)gid, (RsScriptKernelID)kid, (RsAllocation)alloc);
+}
+
+static void
+nScriptGroupExecute(JNIEnv *_env, jobject _this, RsContext con, jint gid)
+{
+    LOG_API("nScriptGroupSetOutput, con(%p) group(%p)", con, (void *)gid);
+    rsScriptGroupExecute(con, (RsScriptGroup)gid);
+}
+
 // ---------------------------------------------------------------------------
 
 static jint
@@ -1412,6 +1488,13 @@
 {"rsnScriptSetVarObj",               "(IIII)V",                               (void*)nScriptSetVarObj },
 
 {"rsnScriptCCreate",                 "(ILjava/lang/String;Ljava/lang/String;[BI)I",  (void*)nScriptCCreate },
+{"rsnScriptIntrinsicCreate",         "(III)I",                                (void*)nScriptIntrinsicCreate },
+{"rsnScriptKernelIDCreate",          "(IIII)I",                               (void*)nScriptKernelIDCreate },
+{"rsnScriptFieldIDCreate",           "(III)I",                                (void*)nScriptFieldIDCreate },
+{"rsnScriptGroupCreate",             "(I[I[I[I[I[I)I",                        (void*)nScriptGroupCreate },
+{"rsnScriptGroupSetInput",           "(IIII)V",                               (void*)nScriptGroupSetInput },
+{"rsnScriptGroupSetOutput",          "(IIII)V",                               (void*)nScriptGroupSetOutput },
+{"rsnScriptGroupExecute",            "(II)V",                                 (void*)nScriptGroupExecute },
 
 {"rsnProgramStoreCreate",            "(IZZZZZZIII)I",                         (void*)nProgramStoreCreate },
 
diff --git a/include/android_runtime/android_view_Surface.h b/include/android_runtime/android_view_Surface.h
index fb0b057..df0fe72 100644
--- a/include/android_runtime/android_view_Surface.h
+++ b/include/android_runtime/android_view_Surface.h
@@ -24,13 +24,21 @@
 namespace android {
 
 class Surface;
+class ISurfaceTexture;
 
-extern sp<ANativeWindow> android_Surface_getNativeWindow(
-        JNIEnv* env, jobject clazz);
-extern bool android_Surface_isInstanceOf(JNIEnv* env, jobject obj);
+/* Gets the underlying ANativeWindow for a Surface. */
+extern sp<ANativeWindow> android_view_Surface_getNativeWindow(
+        JNIEnv* env, jobject surfaceObj);
+
+/* Returns true if the object is an instance of Surface. */
+extern bool android_view_Surface_isInstanceOf(JNIEnv* env, jobject obj);
 
 /* Gets the underlying Surface from a Surface Java object. */
-extern sp<Surface> Surface_getSurface(JNIEnv* env, jobject thiz);
+extern sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj);
+
+/* Creates a Surface from an ISurfaceTexture. */
+extern jobject android_view_Surface_createFromISurfaceTexture(JNIEnv* env,
+        const sp<ISurfaceTexture>& surfaceTexture);
 
 } // namespace android
 
diff --git a/include/android_runtime/android_view_SurfaceSession.h b/include/android_runtime/android_view_SurfaceSession.h
new file mode 100644
index 0000000..3748f6c
--- /dev/null
+++ b/include/android_runtime/android_view_SurfaceSession.h
@@ -0,0 +1,32 @@
+/*
+ * 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 _ANDROID_VIEW_SURFACE_SESSION_H
+#define _ANDROID_VIEW_SURFACE_SESSION_H
+
+#include "jni.h"
+
+namespace android {
+
+class SurfaceComposerClient;
+
+/* Gets the underlying SurfaceComposerClient for a SurfaceSession. */
+extern sp<SurfaceComposerClient> android_view_SurfaceSession_getClient(
+        JNIEnv* env, jobject surfaceSessionObj);
+
+} // namespace android
+
+#endif // _ANDROID_VIEW_SURFACE_SESSION_H
diff --git a/include/androidfw/Input.h b/include/androidfw/Input.h
index 2c91fab..e88835e 100644
--- a/include/androidfw/Input.h
+++ b/include/androidfw/Input.h
@@ -49,6 +49,15 @@
 };
 
 enum {
+    /* Used when a motion event is not associated with any display.
+     * Typically used for non-pointer events. */
+    ADISPLAY_ID_NONE = -1,
+
+    /* The default display id. */
+    ADISPLAY_ID_DEFAULT = 0,
+};
+
+enum {
     /*
      * Indicates that an input device has switches.
      * This input source flag is hidden from the API because switches are only used by the system
diff --git a/include/androidfw/PowerManager.h b/include/androidfw/PowerManager.h
index 59e993a..ba98db0 100644
--- a/include/androidfw/PowerManager.h
+++ b/include/androidfw/PowerManager.h
@@ -21,11 +21,11 @@
 namespace android {
 
 enum {
-    POWER_MANAGER_OTHER_EVENT = 0,
-    POWER_MANAGER_BUTTON_EVENT = 1,
-    POWER_MANAGER_TOUCH_EVENT = 2,
+    USER_ACTIVITY_EVENT_OTHER = 0,
+    USER_ACTIVITY_EVENT_BUTTON = 1,
+    USER_ACTIVITY_EVENT_TOUCH = 2,
 
-    POWER_MANAGER_LAST_EVENT = POWER_MANAGER_TOUCH_EVENT, // Last valid event code.
+    USER_ACTIVITY_EVENT_LAST = USER_ACTIVITY_EVENT_TOUCH, // Last valid event code.
 };
 
 } // namespace android
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 23bca3e..48f5bf3 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -957,6 +957,13 @@
         SCREENLONG_ANY = ACONFIGURATION_SCREENLONG_ANY << SHIFT_SCREENLONG,
         SCREENLONG_NO = ACONFIGURATION_SCREENLONG_NO << SHIFT_SCREENLONG,
         SCREENLONG_YES = ACONFIGURATION_SCREENLONG_YES << SHIFT_SCREENLONG,
+
+        // screenLayout bits for layout direction.
+        MASK_LAYOUTDIR = 0xC0,
+        SHIFT_LAYOUTDIR = 6,
+        LAYOUTDIR_ANY = ACONFIGURATION_LAYOUTDIR_ANY << SHIFT_LAYOUTDIR,
+        LAYOUTDIR_LTR = ACONFIGURATION_LAYOUTDIR_LTR << SHIFT_LAYOUTDIR,
+        LAYOUTDIR_RTL = ACONFIGURATION_LAYOUTDIR_RTL << SHIFT_LAYOUTDIR,
     };
     
     enum {
@@ -1020,7 +1027,8 @@
         CONFIG_SMALLEST_SCREEN_SIZE = ACONFIGURATION_SMALLEST_SCREEN_SIZE,
         CONFIG_VERSION = ACONFIGURATION_VERSION,
         CONFIG_SCREEN_LAYOUT = ACONFIGURATION_SCREEN_LAYOUT,
-        CONFIG_UI_MODE = ACONFIGURATION_UI_MODE
+        CONFIG_UI_MODE = ACONFIGURATION_UI_MODE,
+        CONFIG_LAYOUTDIR = ACONFIGURATION_LAYOUTDIR,
     };
     
     // Compare two configuration, returning CONFIG_* flags set for each value
@@ -1061,7 +1069,7 @@
  * There should be one of these chunks for each resource type.
  *
  * This structure is followed by an array of integers providing the set of
- * configuation change flags (ResTable_config::CONFIG_*) that have multiple
+ * configuration change flags (ResTable_config::CONFIG_*) that have multiple
  * resources for that configuration.  In addition, the high bit is set if that
  * resource has been made public.
  */
diff --git a/include/storage/IMountService.h b/include/storage/IMountService.h
index 43df7f0..c3d34d8 100644
--- a/include/storage/IMountService.h
+++ b/include/storage/IMountService.h
@@ -21,6 +21,8 @@
 #include <storage/IMountShutdownObserver.h>
 #include <storage/IObbActionListener.h>
 
+#include <utils/String8.h>
+
 #include <binder/IInterface.h>
 #include <binder/Parcel.h>
 
@@ -60,8 +62,9 @@
             String16*& containers) = 0;
     virtual void shutdown(const sp<IMountShutdownObserver>& observer) = 0;
     virtual void finishMediaUpdate() = 0;
-    virtual void mountObb(const String16& filename, const String16& key,
-            const sp<IObbActionListener>& token, const int32_t nonce) = 0;
+    virtual void mountObb(const String16& rawPath, const String16& canonicalPath,
+            const String16& key, const sp<IObbActionListener>& token,
+            const int32_t nonce) = 0;
     virtual void unmountObb(const String16& filename, const bool force,
             const sp<IObbActionListener>& token, const int32_t nonce) = 0;
     virtual bool isObbMounted(const String16& filename) = 0;
diff --git a/keystore/java/android/security/AndroidKeyPairGenerator.java b/keystore/java/android/security/AndroidKeyPairGenerator.java
new file mode 100644
index 0000000..c42001b
--- /dev/null
+++ b/keystore/java/android/security/AndroidKeyPairGenerator.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import com.android.org.bouncycastle.x509.X509V3CertificateGenerator;
+
+import org.apache.harmony.xnet.provider.jsse.OpenSSLEngine;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyPairGeneratorSpi;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+
+/**
+ * Provides a way to create instances of a KeyPair which will be placed in the
+ * Android keystore service usable only by the application that called it. This
+ * can be used in conjunction with
+ * {@link java.security.KeyStore#getInstance(String)} using the
+ * {@code "AndroidKeyStore"} type.
+ * <p>
+ * This class can not be directly instantiated and must instead be used via the
+ * {@link KeyPairGenerator#getInstance(String)
+ * KeyPairGenerator.getInstance("AndroidKeyPairGenerator")} API.
+ *
+ * {@hide}
+ */
+@SuppressWarnings("deprecation")
+public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi {
+    public static final String NAME = "AndroidKeyPairGenerator";
+
+    private android.security.KeyStore mKeyStore;
+
+    private AndroidKeyPairGeneratorSpec mSpec;
+
+    /**
+     * Generate a KeyPair which is backed by the Android keystore service. You
+     * must call {@link KeyPairGenerator#initialize(AlgorithmParameterSpec)}
+     * with an {@link AndroidKeyPairGeneratorSpec} as the {@code params}
+     * argument before calling this otherwise an {@code IllegalStateException}
+     * will be thrown.
+     * <p>
+     * This will create an entry in the Android keystore service with a
+     * self-signed certificate using the {@code params} specified in the
+     * {@code initialize(params)} call.
+     *
+     * @throws IllegalStateException when called before calling
+     *             {@link KeyPairGenerator#initialize(AlgorithmParameterSpec)}
+     * @see java.security.KeyPairGeneratorSpi#generateKeyPair()
+     */
+    @Override
+    public KeyPair generateKeyPair() {
+        if (mKeyStore == null || mSpec == null) {
+            throw new IllegalStateException(
+                    "Must call initialize with an AndroidKeyPairGeneratorSpec first");
+        }
+
+        final String alias = mSpec.getKeystoreAlias();
+
+        Credentials.deleteAllTypesForAlias(mKeyStore, alias);
+
+        final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + alias;
+        mKeyStore.generate(privateKeyAlias);
+
+        final PrivateKey privKey;
+        final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore");
+        try {
+            privKey = engine.getPrivateKeyById(privateKeyAlias);
+        } catch (InvalidKeyException e) {
+            throw new RuntimeException("Can't get key", e);
+        }
+
+        final byte[] pubKeyBytes = mKeyStore.getPubkey(privateKeyAlias);
+
+        final PublicKey pubKey;
+        try {
+            final KeyFactory keyFact = KeyFactory.getInstance("RSA");
+            pubKey = keyFact.generatePublic(new X509EncodedKeySpec(pubKeyBytes));
+        } catch (NoSuchAlgorithmException e) {
+            throw new IllegalStateException("Can't instantiate RSA key generator", e);
+        } catch (InvalidKeySpecException e) {
+            throw new IllegalStateException("keystore returned invalid key encoding", e);
+        }
+
+        final X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+        certGen.setPublicKey(pubKey);
+        certGen.setSerialNumber(mSpec.getSerialNumber());
+        certGen.setSubjectDN(mSpec.getSubjectDN());
+        certGen.setIssuerDN(mSpec.getSubjectDN());
+        certGen.setNotBefore(mSpec.getStartDate());
+        certGen.setNotAfter(mSpec.getEndDate());
+        certGen.setSignatureAlgorithm("sha1WithRSA");
+
+        final X509Certificate cert;
+        try {
+            cert = certGen.generate(privKey);
+        } catch (Exception e) {
+            Credentials.deleteAllTypesForAlias(mKeyStore, alias);
+            throw new IllegalStateException("Can't generate certificate", e);
+        }
+
+        byte[] certBytes;
+        try {
+            certBytes = cert.getEncoded();
+        } catch (CertificateEncodingException e) {
+            Credentials.deleteAllTypesForAlias(mKeyStore, alias);
+            throw new IllegalStateException("Can't get encoding of certificate", e);
+        }
+
+        if (!mKeyStore.put(Credentials.USER_CERTIFICATE + alias, certBytes)) {
+            Credentials.deleteAllTypesForAlias(mKeyStore, alias);
+            throw new IllegalStateException("Can't store certificate in AndroidKeyStore");
+        }
+
+        return new KeyPair(pubKey, privKey);
+    }
+
+    @Override
+    public void initialize(int keysize, SecureRandom random) {
+        throw new IllegalArgumentException("cannot specify keysize with AndroidKeyPairGenerator");
+    }
+
+    @Override
+    public void initialize(AlgorithmParameterSpec params, SecureRandom random)
+            throws InvalidAlgorithmParameterException {
+        if (params == null) {
+            throw new InvalidAlgorithmParameterException(
+                    "must supply params of type AndroidKeyPairGenericSpec");
+        } else if (!(params instanceof AndroidKeyPairGeneratorSpec)) {
+            throw new InvalidAlgorithmParameterException(
+                    "params must be of type AndroidKeyPairGeneratorSpec");
+        }
+
+        AndroidKeyPairGeneratorSpec spec = (AndroidKeyPairGeneratorSpec) params;
+
+        mSpec = spec;
+        mKeyStore = android.security.KeyStore.getInstance();
+    }
+}
diff --git a/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java b/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java
new file mode 100644
index 0000000..79a7630
--- /dev/null
+++ b/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Date;
+
+import javax.security.auth.x500.X500Principal;
+
+/**
+ * This provides the required parameters needed for initializing the KeyPair
+ * generator that works with
+ * <a href="{@docRoot}guide/topics/security/keystore.html">Android KeyStore
+ * facility</a>.
+ * @hide
+ */
+public class AndroidKeyPairGeneratorSpec implements AlgorithmParameterSpec {
+    private final String mKeystoreAlias;
+
+    private final Context mContext;
+
+    private final X500Principal mSubjectDN;
+
+    private final BigInteger mSerialNumber;
+
+    private final Date mStartDate;
+
+    private final Date mEndDate;
+
+    /**
+     * Parameter specification for the "{@code AndroidKeyPairGenerator}"
+     * instance of the {@link java.security.KeyPairGenerator} API. The
+     * {@code context} passed in may be used to pop up some UI to ask the user
+     * to unlock or initialize the Android keystore facility.
+     * <p>
+     * After generation, the {@code keyStoreAlias} is used with the
+     * {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter)}
+     * interface to retrieve the {@link PrivateKey} and its associated
+     * {@link Certificate} chain.
+     * <p>
+     * The KeyPair generator will create a self-signed certificate with the
+     * properties of {@code subjectDN} as its X.509v3 Subject Distinguished Name
+     * and as its X.509v3 Issuer Distinguished Name, using the specified
+     * {@code serialNumber}, and the validity date starting at {@code startDate}
+     * and ending at {@code endDate}.
+     *
+     * @param context Android context for the activity
+     * @param keyStoreAlias name to use for the generated key in the Android
+     *            keystore
+     * @param subjectDN X.509 v3 Subject Distinguished Name
+     * @param serialNumber X509 v3 certificate serial number
+     * @param startDate the start of the self-signed certificate validity period
+     * @param endDate the end date of the self-signed certificate validity
+     *            period
+     * @throws IllegalArgumentException when any argument is {@code null} or
+     *             {@code endDate} is before {@code startDate}.
+     */
+    public AndroidKeyPairGeneratorSpec(Context context, String keyStoreAlias,
+            X500Principal subjectDN, BigInteger serialNumber, Date startDate, Date endDate) {
+        if (context == null) {
+            throw new IllegalArgumentException("context == null");
+        } else if (TextUtils.isEmpty(keyStoreAlias)) {
+            throw new IllegalArgumentException("keyStoreAlias must not be empty");
+        } else if (subjectDN == null) {
+            throw new IllegalArgumentException("subjectDN == null");
+        } else if (serialNumber == null) {
+            throw new IllegalArgumentException("serialNumber == null");
+        } else if (startDate == null) {
+            throw new IllegalArgumentException("startDate == null");
+        } else if (endDate == null) {
+            throw new IllegalArgumentException("endDate == null");
+        } else if (endDate.before(startDate)) {
+            throw new IllegalArgumentException("endDate < startDate");
+        }
+
+        mContext = context;
+        mKeystoreAlias = keyStoreAlias;
+        mSubjectDN = subjectDN;
+        mSerialNumber = serialNumber;
+        mStartDate = startDate;
+        mEndDate = endDate;
+    }
+
+    /**
+     * @hide
+     */
+    String getKeystoreAlias() {
+        return mKeystoreAlias;
+    }
+
+    /**
+     * @hide
+     */
+    Context getContext() {
+        return mContext;
+    }
+
+    /**
+     * @hide
+     */
+    X500Principal getSubjectDN() {
+        return mSubjectDN;
+    }
+
+    /**
+     * @hide
+     */
+    BigInteger getSerialNumber() {
+        return mSerialNumber;
+    }
+
+    /**
+     * @hide
+     */
+    Date getStartDate() {
+        return mStartDate;
+    }
+
+    /**
+     * @hide
+     */
+    Date getEndDate() {
+        return mEndDate;
+    }
+}
diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java
new file mode 100644
index 0000000..aabfcae
--- /dev/null
+++ b/keystore/java/android/security/AndroidKeyStore.java
@@ -0,0 +1,518 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import org.apache.harmony.xnet.provider.jsse.OpenSSLDSAPrivateKey;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLEngine;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLRSAPrivateKey;
+
+import android.util.Log;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyStoreException;
+import java.security.KeyStoreSpi;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * A java.security.KeyStore interface for the Android KeyStore. An instance of
+ * it can be created via the {@link java.security.KeyStore#getInstance(String)
+ * KeyStore.getInstance("AndroidKeyStore")} interface. This returns a
+ * java.security.KeyStore backed by this "AndroidKeyStore" implementation.
+ * <p>
+ * This is built on top of Android's keystore daemon. The convention of alias
+ * use is:
+ * <p>
+ * PrivateKeyEntry will have a Credentials.USER_PRIVATE_KEY as the private key,
+ * Credentials.USER_CERTIFICATE as the first certificate in the chain (the one
+ * that corresponds to the private key), and then a Credentials.CA_CERTIFICATE
+ * entry which will have the rest of the chain concatenated in BER format.
+ * <p>
+ * TrustedCertificateEntry will just have a Credentials.CA_CERTIFICATE entry
+ * with a single certificate.
+ *
+ * @hide
+ */
+public class AndroidKeyStore extends KeyStoreSpi {
+    public static final String NAME = "AndroidKeyStore";
+
+    private android.security.KeyStore mKeyStore;
+
+    @Override
+    public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException,
+            UnrecoverableKeyException {
+        if (!isKeyEntry(alias)) {
+            return null;
+        }
+
+        final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore");
+        try {
+            return engine.getPrivateKeyById(Credentials.USER_PRIVATE_KEY + alias);
+        } catch (InvalidKeyException e) {
+            UnrecoverableKeyException t = new UnrecoverableKeyException("Can't get key");
+            t.initCause(e);
+            throw t;
+        }
+    }
+
+    @Override
+    public Certificate[] engineGetCertificateChain(String alias) {
+        if (alias == null) {
+            throw new NullPointerException("alias == null");
+        }
+
+        final X509Certificate leaf = (X509Certificate) engineGetCertificate(alias);
+        if (leaf == null) {
+            return null;
+        }
+
+        final Certificate[] caList;
+
+        final byte[] caBytes = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
+        if (caBytes != null) {
+            final Collection<X509Certificate> caChain = toCertificates(caBytes);
+
+            caList = new Certificate[caChain.size() + 1];
+
+            final Iterator<X509Certificate> it = caChain.iterator();
+            int i = 1;
+            while (it.hasNext()) {
+                caList[i++] = it.next();
+            }
+        } else {
+            caList = new Certificate[1];
+        }
+
+        caList[0] = leaf;
+
+        return caList;
+    }
+
+    @Override
+    public Certificate engineGetCertificate(String alias) {
+        if (alias == null) {
+            throw new NullPointerException("alias == null");
+        }
+
+        byte[] certificate = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
+        if (certificate != null) {
+            return toCertificate(certificate);
+        }
+
+        certificate = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
+        if (certificate != null) {
+            return toCertificate(certificate);
+        }
+
+        return null;
+    }
+
+    private static X509Certificate toCertificate(byte[] bytes) {
+        try {
+            final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+            return (X509Certificate) certFactory
+                    .generateCertificate(new ByteArrayInputStream(bytes));
+        } catch (CertificateException e) {
+            Log.w(NAME, "Couldn't parse certificate in keystore", e);
+            return null;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static Collection<X509Certificate> toCertificates(byte[] bytes) {
+        try {
+            final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+            return (Collection<X509Certificate>) certFactory
+                    .generateCertificates(new ByteArrayInputStream(bytes));
+        } catch (CertificateException e) {
+            Log.w(NAME, "Couldn't parse certificates in keystore", e);
+            return new ArrayList<X509Certificate>();
+        }
+    }
+
+    private Date getModificationDate(String alias) {
+        final long epochMillis = mKeyStore.getmtime(alias);
+        if (epochMillis == -1L) {
+            return null;
+        }
+
+        return new Date(epochMillis);
+    }
+
+    @Override
+    public Date engineGetCreationDate(String alias) {
+        if (alias == null) {
+            throw new NullPointerException("alias == null");
+        }
+
+        Date d = getModificationDate(Credentials.USER_PRIVATE_KEY + alias);
+        if (d != null) {
+            return d;
+        }
+
+        d = getModificationDate(Credentials.USER_CERTIFICATE + alias);
+        if (d != null) {
+            return d;
+        }
+
+        return getModificationDate(Credentials.CA_CERTIFICATE + alias);
+    }
+
+    @Override
+    public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain)
+            throws KeyStoreException {
+        if ((password != null) && (password.length > 0)) {
+            throw new KeyStoreException("entries cannot be protected with passwords");
+        }
+
+        if (key instanceof PrivateKey) {
+            setPrivateKeyEntry(alias, (PrivateKey) key, chain);
+        } else {
+            throw new KeyStoreException("Only PrivateKeys are supported");
+        }
+    }
+
+    private void setPrivateKeyEntry(String alias, PrivateKey key, Certificate[] chain)
+            throws KeyStoreException {
+        byte[] keyBytes = null;
+
+        final String pkeyAlias;
+        if (key instanceof OpenSSLRSAPrivateKey) {
+            pkeyAlias = ((OpenSSLRSAPrivateKey) key).getPkeyAlias();
+        } else if (key instanceof OpenSSLDSAPrivateKey) {
+            pkeyAlias = ((OpenSSLDSAPrivateKey) key).getPkeyAlias();
+        } else {
+            pkeyAlias = null;
+        }
+
+        final boolean shouldReplacePrivateKey;
+        if (pkeyAlias != null && pkeyAlias.startsWith(Credentials.USER_PRIVATE_KEY)) {
+            final String keySubalias = pkeyAlias.substring(Credentials.USER_PRIVATE_KEY.length());
+            if (!alias.equals(keySubalias)) {
+                throw new KeyStoreException("Can only replace keys with same alias: " + alias
+                        + " != " + keySubalias);
+            }
+
+            shouldReplacePrivateKey = false;
+        } else {
+            // Make sure the PrivateKey format is the one we support.
+            final String keyFormat = key.getFormat();
+            if ((keyFormat == null) || (!"PKCS#8".equals(keyFormat))) {
+                throw new KeyStoreException(
+                        "Only PrivateKeys that can be encoded into PKCS#8 are supported");
+            }
+
+            // Make sure we can actually encode the key.
+            keyBytes = key.getEncoded();
+            if (keyBytes == null) {
+                throw new KeyStoreException("PrivateKey has no encoding");
+            }
+
+            shouldReplacePrivateKey = true;
+        }
+
+        // Make sure the chain exists since this is a PrivateKey
+        if ((chain == null) || (chain.length == 0)) {
+            throw new KeyStoreException("Must supply at least one Certificate with PrivateKey");
+        }
+
+        // Do chain type checking.
+        X509Certificate[] x509chain = new X509Certificate[chain.length];
+        for (int i = 0; i < chain.length; i++) {
+            if (!"X.509".equals(chain[i].getType())) {
+                throw new KeyStoreException("Certificates must be in X.509 format: invalid cert #"
+                        + i);
+            }
+
+            if (!(chain[i] instanceof X509Certificate)) {
+                throw new KeyStoreException("Certificates must be in X.509 format: invalid cert #"
+                        + i);
+            }
+
+            x509chain[i] = (X509Certificate) chain[i];
+        }
+
+        final byte[] userCertBytes;
+        try {
+            userCertBytes = x509chain[0].getEncoded();
+        } catch (CertificateEncodingException e) {
+            throw new KeyStoreException("Couldn't encode certificate #1", e);
+        }
+
+        /*
+         * If we have a chain, store it in the CA certificate slot for this
+         * alias as concatenated DER-encoded certificates. These can be
+         * deserialized by {@link CertificateFactory#generateCertificates}.
+         */
+        final byte[] chainBytes;
+        if (chain.length > 1) {
+            /*
+             * The chain is passed in as {user_cert, ca_cert_1, ca_cert_2, ...}
+             * so we only need the certificates starting at index 1.
+             */
+            final byte[][] certsBytes = new byte[x509chain.length - 1][];
+            int totalCertLength = 0;
+            for (int i = 0; i < certsBytes.length; i++) {
+                try {
+                    certsBytes[i] = x509chain[i + 1].getEncoded();
+                    totalCertLength += certsBytes[i].length;
+                } catch (CertificateEncodingException e) {
+                    throw new KeyStoreException("Can't encode Certificate #" + i, e);
+                }
+            }
+
+            /*
+             * Serialize this into one byte array so we can later call
+             * CertificateFactory#generateCertificates to recover them.
+             */
+            chainBytes = new byte[totalCertLength];
+            int outputOffset = 0;
+            for (int i = 0; i < certsBytes.length; i++) {
+                final int certLength = certsBytes[i].length;
+                System.arraycopy(certsBytes[i], 0, chainBytes, outputOffset, certLength);
+                outputOffset += certLength;
+                certsBytes[i] = null;
+            }
+        } else {
+            chainBytes = null;
+        }
+
+        /*
+         * Make sure we clear out all the appropriate types before trying to
+         * write.
+         */
+        if (shouldReplacePrivateKey) {
+            Credentials.deleteAllTypesForAlias(mKeyStore, alias);
+        } else {
+            Credentials.deleteCertificateTypesForAlias(mKeyStore, alias);
+        }
+
+        if (shouldReplacePrivateKey
+                && !mKeyStore.importKey(Credentials.USER_PRIVATE_KEY + alias, keyBytes)) {
+            Credentials.deleteAllTypesForAlias(mKeyStore, alias);
+            throw new KeyStoreException("Couldn't put private key in keystore");
+        } else if (!mKeyStore.put(Credentials.USER_CERTIFICATE + alias, userCertBytes)) {
+            Credentials.deleteAllTypesForAlias(mKeyStore, alias);
+            throw new KeyStoreException("Couldn't put certificate #1 in keystore");
+        } else if (chainBytes != null
+                && !mKeyStore.put(Credentials.CA_CERTIFICATE + alias, chainBytes)) {
+            Credentials.deleteAllTypesForAlias(mKeyStore, alias);
+            throw new KeyStoreException("Couldn't put certificate chain in keystore");
+        }
+    }
+
+    @Override
+    public void engineSetKeyEntry(String alias, byte[] userKey, Certificate[] chain)
+            throws KeyStoreException {
+        throw new KeyStoreException("Operation not supported because key encoding is unknown");
+    }
+
+    @Override
+    public void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException {
+        if (isKeyEntry(alias)) {
+            throw new KeyStoreException("Entry exists and is not a trusted certificate");
+        }
+
+        // We can't set something to null.
+        if (cert == null) {
+            throw new NullPointerException("cert == null");
+        }
+
+        final byte[] encoded;
+        try {
+            encoded = cert.getEncoded();
+        } catch (CertificateEncodingException e) {
+            throw new KeyStoreException(e);
+        }
+
+        if (!mKeyStore.put(Credentials.CA_CERTIFICATE + alias, encoded)) {
+            throw new KeyStoreException("Couldn't insert certificate; is KeyStore initialized?");
+        }
+    }
+
+    @Override
+    public void engineDeleteEntry(String alias) throws KeyStoreException {
+        if (!isKeyEntry(alias) && !isCertificateEntry(alias)) {
+            return;
+        }
+
+        if (!Credentials.deleteAllTypesForAlias(mKeyStore, alias)) {
+            throw new KeyStoreException("No such entry " + alias);
+        }
+    }
+
+    private Set<String> getUniqueAliases() {
+        final String[] rawAliases = mKeyStore.saw("");
+        if (rawAliases == null) {
+            return new HashSet<String>();
+        }
+
+        final Set<String> aliases = new HashSet<String>(rawAliases.length);
+        for (String alias : rawAliases) {
+            final int idx = alias.indexOf('_');
+            if ((idx == -1) || (alias.length() <= idx)) {
+                Log.e(NAME, "invalid alias: " + alias);
+                continue;
+            }
+
+            aliases.add(new String(alias.substring(idx + 1)));
+        }
+
+        return aliases;
+    }
+
+    @Override
+    public Enumeration<String> engineAliases() {
+        return Collections.enumeration(getUniqueAliases());
+    }
+
+    @Override
+    public boolean engineContainsAlias(String alias) {
+        if (alias == null) {
+            throw new NullPointerException("alias == null");
+        }
+
+        return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias)
+                || mKeyStore.contains(Credentials.USER_CERTIFICATE + alias)
+                || mKeyStore.contains(Credentials.CA_CERTIFICATE + alias);
+    }
+
+    @Override
+    public int engineSize() {
+        return getUniqueAliases().size();
+    }
+
+    @Override
+    public boolean engineIsKeyEntry(String alias) {
+        return isKeyEntry(alias);
+    }
+
+    private boolean isKeyEntry(String alias) {
+        if (alias == null) {
+            throw new NullPointerException("alias == null");
+        }
+
+        return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias);
+    }
+
+    private boolean isCertificateEntry(String alias) {
+        if (alias == null) {
+            throw new NullPointerException("alias == null");
+        }
+
+        return mKeyStore.contains(Credentials.CA_CERTIFICATE + alias);
+    }
+
+    @Override
+    public boolean engineIsCertificateEntry(String alias) {
+        return !isKeyEntry(alias) && isCertificateEntry(alias);
+    }
+
+    @Override
+    public String engineGetCertificateAlias(Certificate cert) {
+        if (cert == null) {
+            return null;
+        }
+
+        final Set<String> nonCaEntries = new HashSet<String>();
+
+        /*
+         * First scan the PrivateKeyEntry types. The KeyStoreSpi documentation
+         * says to only compare the first certificate in the chain which is
+         * equivalent to the USER_CERTIFICATE prefix for the Android keystore
+         * convention.
+         */
+        final String[] certAliases = mKeyStore.saw(Credentials.USER_CERTIFICATE);
+        for (String alias : certAliases) {
+            final byte[] certBytes = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
+            if (certBytes == null) {
+                continue;
+            }
+
+            final Certificate c = toCertificate(certBytes);
+            nonCaEntries.add(alias);
+
+            if (cert.equals(c)) {
+                return alias;
+            }
+        }
+
+        /*
+         * Look at all the TrustedCertificateEntry types. Skip all the
+         * PrivateKeyEntry we looked at above.
+         */
+        final String[] caAliases = mKeyStore.saw(Credentials.CA_CERTIFICATE);
+        for (String alias : caAliases) {
+            if (nonCaEntries.contains(alias)) {
+                continue;
+            }
+
+            final byte[] certBytes = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
+            if (certBytes == null) {
+                continue;
+            }
+
+            final Certificate c = toCertificate(mKeyStore.get(Credentials.CA_CERTIFICATE + alias));
+            if (cert.equals(c)) {
+                return alias;
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public void engineStore(OutputStream stream, char[] password) throws IOException,
+            NoSuchAlgorithmException, CertificateException {
+        throw new UnsupportedOperationException("Can not serialize AndroidKeyStore to OutputStream");
+    }
+
+    @Override
+    public void engineLoad(InputStream stream, char[] password) throws IOException,
+            NoSuchAlgorithmException, CertificateException {
+        if (stream != null) {
+            throw new IllegalArgumentException("InputStream not supported");
+        }
+
+        if (password != null) {
+            throw new IllegalArgumentException("password not supported");
+        }
+
+        // Unfortunate name collision.
+        mKeyStore = android.security.KeyStore.getInstance();
+    }
+
+}
diff --git a/keystore/java/android/security/AndroidKeyStoreProvider.java b/keystore/java/android/security/AndroidKeyStoreProvider.java
new file mode 100644
index 0000000..40d7e1a
--- /dev/null
+++ b/keystore/java/android/security/AndroidKeyStoreProvider.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import java.security.Provider;
+
+/**
+ * A provider focused on providing JCA interfaces for the Android KeyStore.
+ *
+ * @hide
+ */
+public class AndroidKeyStoreProvider extends Provider {
+    public static final String PROVIDER_NAME = "AndroidKeyStoreProvider";
+
+    public AndroidKeyStoreProvider() {
+        super(PROVIDER_NAME, 1.0, "Android KeyStore security provider");
+
+        // java.security.KeyStore
+        put("KeyStore." + AndroidKeyStore.NAME, AndroidKeyStore.class.getName());
+
+        // java.security.KeyPairGenerator
+        put("KeyPairGenerator." + AndroidKeyPairGenerator.NAME,
+                AndroidKeyPairGenerator.class.getName());
+    }
+}
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index 68ba2b1..d8109ce 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -20,8 +20,9 @@
 import android.content.Context;
 import android.content.Intent;
 import android.util.Log;
-import com.android.org.bouncycastle.openssl.PEMReader;
-import com.android.org.bouncycastle.openssl.PEMWriter;
+import com.android.org.bouncycastle.util.io.pem.PemObject;
+import com.android.org.bouncycastle.util.io.pem.PemReader;
+import com.android.org.bouncycastle.util.io.pem.PemWriter;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -32,6 +33,10 @@
 import java.io.Writer;
 import java.nio.charset.Charsets;
 import java.security.KeyPair;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.List;
@@ -61,6 +66,9 @@
     /** Key prefix for WIFI. */
     public static final String WIFI = "WIFI_";
 
+    /** Key containing suffix of lockdown VPN profile. */
+    public static final String LOCKDOWN_VPN = "LOCKDOWN_VPN";
+
     /** Data type for public keys. */
     public static final String EXTRA_PUBLIC_KEY = "KEY";
 
@@ -105,34 +113,41 @@
     public static final String EXTRA_CA_CERTIFICATES_DATA = "ca_certificates_data";
 
     /**
-     * Convert objects to a PEM format, which is used for
-     * CA_CERTIFICATE, USER_CERTIFICATE, and USER_PRIVATE_KEY
-     * entries.
+     * Convert objects to a PEM format which is used for
+     * CA_CERTIFICATE and USER_CERTIFICATE entries.
      */
-    public static byte[] convertToPem(Object... objects) throws IOException {
+    public static byte[] convertToPem(Certificate... objects)
+            throws IOException, CertificateEncodingException {
         ByteArrayOutputStream bao = new ByteArrayOutputStream();
         Writer writer = new OutputStreamWriter(bao, Charsets.US_ASCII);
-        PEMWriter pw = new PEMWriter(writer);
-        for (Object o : objects) {
-            pw.writeObject(o);
+        PemWriter pw = new PemWriter(writer);
+        for (Certificate o : objects) {
+            pw.writeObject(new PemObject("CERTIFICATE", o.getEncoded()));
         }
         pw.close();
         return bao.toByteArray();
     }
     /**
      * Convert objects from PEM format, which is used for
-     * CA_CERTIFICATE, USER_CERTIFICATE, and USER_PRIVATE_KEY
-     * entries.
+     * CA_CERTIFICATE and USER_CERTIFICATE entries.
      */
-    public static List<Object> convertFromPem(byte[] bytes) throws IOException {
+    public static List<X509Certificate> convertFromPem(byte[] bytes)
+            throws IOException, CertificateException {
         ByteArrayInputStream bai = new ByteArrayInputStream(bytes);
         Reader reader = new InputStreamReader(bai, Charsets.US_ASCII);
-        PEMReader pr = new PEMReader(reader);
+        PemReader pr = new PemReader(reader);
 
-        List<Object> result = new ArrayList<Object>();
-        Object o;
-        while ((o = pr.readObject()) != null) {
-            result.add(o);
+        CertificateFactory cf = CertificateFactory.getInstance("X509");
+
+        List<X509Certificate> result = new ArrayList<X509Certificate>();
+        PemObject o;
+        while ((o = pr.readPemObject()) != null) {
+            if (o.getType().equals("CERTIFICATE")) {
+                Certificate c = cf.generateCertificate(new ByteArrayInputStream(o.getContent()));
+                result.add((X509Certificate) c);
+            } else {
+                throw new IllegalArgumentException("Unknown type " + o.getType());
+            }
         }
         pr.close();
         return result;
@@ -185,4 +200,32 @@
             Log.w(LOGTAG, e.toString());
         }
     }
+
+    /**
+     * Delete all types (private key, certificate, CA certificate) for a
+     * particular {@code alias}. All three can exist for any given alias.
+     * Returns {@code true} if there was at least one of those types.
+     */
+    static boolean deleteAllTypesForAlias(KeyStore keystore, String alias) {
+        /*
+         * Make sure every type is deleted. There can be all three types, so
+         * don't use a conditional here.
+         */
+        return keystore.delKey(Credentials.USER_PRIVATE_KEY + alias)
+                | deleteCertificateTypesForAlias(keystore, alias);
+    }
+
+    /**
+     * Delete all types (private key, certificate, CA certificate) for a
+     * particular {@code alias}. All three can exist for any given alias.
+     * Returns {@code true} if there was at least one of those types.
+     */
+    static boolean deleteCertificateTypesForAlias(KeyStore keystore, String alias) {
+        /*
+         * Make sure every certificate type is deleted. There can be two types,
+         * so don't use a conditional here.
+         */
+        return keystore.delete(Credentials.USER_CERTIFICATE + alias)
+                | keystore.delete(Credentials.CA_CERTIFICATE + alias);
+    }
 }
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 483ccb2..31c38d5 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -26,20 +26,16 @@
 import android.os.RemoteException;
 import java.io.ByteArrayInputStream;
 import java.io.Closeable;
-import java.io.IOException;
 import java.security.InvalidKeyException;
-import java.security.KeyPair;
 import java.security.Principal;
 import java.security.PrivateKey;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
-import libcore.util.Objects;
 
 import org.apache.harmony.xnet.provider.jsse.OpenSSLEngine;
 import org.apache.harmony.xnet.provider.jsse.TrustedCertificateStore;
@@ -341,20 +337,9 @@
         try {
             IKeyChainService keyChainService = keyChainConnection.getService();
             byte[] certificateBytes = keyChainService.getCertificate(alias);
-            List<X509Certificate> chain = new ArrayList<X509Certificate>();
-            chain.add(toCertificate(certificateBytes));
             TrustedCertificateStore store = new TrustedCertificateStore();
-            for (int i = 0; true; i++) {
-                X509Certificate cert = chain.get(i);
-                if (Objects.equal(cert.getSubjectX500Principal(), cert.getIssuerX500Principal())) {
-                    break;
-                }
-                X509Certificate issuer = store.findIssuer(cert);
-                if (issuer == null) {
-                    break;
-                }
-                chain.add(issuer);
-            }
+            List<X509Certificate> chain = store
+                    .getCertificateChain(toCertificate(certificateBytes));
             return chain.toArray(new X509Certificate[chain.size()]);
         } catch (RemoteException e) {
             throw new KeyChainException(e);
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index f49c429..4637991 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -26,6 +26,7 @@
 import java.nio.charset.Charsets;
 import java.nio.charset.ModifiedUtf8;
 import java.util.ArrayList;
+import java.util.Date;
 
 /**
  * @hide This should not be made public in its present form because it
@@ -228,6 +229,23 @@
         return ungrant(getKeyBytes(key), getUidBytes(uid));
     }
 
+    private long getmtime(byte[] key) {
+        final ArrayList<byte[]> values = execute('c', key);
+        if (values == null || values.isEmpty()) {
+            return -1L;
+        }
+
+        return Long.parseLong(new String(values.get(0))) * 1000L;
+    }
+
+    /**
+     * Returns the last modification time of the key in milliseconds since the
+     * epoch. Will return -1L if the key could not be found or other error.
+     */
+    public long getmtime(String key) {
+        return getmtime(getKeyBytes(key));
+    }
+
     public int getLastError() {
         return mError;
     }
diff --git a/keystore/java/android/security/package.html b/keystore/java/android/security/package.html
new file mode 100644
index 0000000..610cbf0
--- /dev/null
+++ b/keystore/java/android/security/package.html
@@ -0,0 +1,9 @@
+<HTML>
+<BODY>
+  <p>Provides access to a few facilities of the Android security
+    subsystems.</p>
+  <p>For information on how to use this facility, see the <a
+      href="{@docRoot}guide/topics/security/keystore.html">Android
+      KeyStore facility</a> guide.</p>
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/keystore/tests/Android.mk b/keystore/tests/Android.mk
index 95604c6..61cf640 100644
--- a/keystore/tests/Android.mk
+++ b/keystore/tests/Android.mk
@@ -5,7 +5,7 @@
 LOCAL_MODULE_TAGS := tests
 LOCAL_CERTIFICATE := platform
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner bouncycastle
 
 # Include all test java files.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java b/keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java
new file mode 100644
index 0000000..e6a3750
--- /dev/null
+++ b/keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import android.test.AndroidTestCase;
+
+import java.math.BigInteger;
+import java.util.Date;
+
+import javax.security.auth.x500.X500Principal;
+
+public class AndroidKeyPairGeneratorSpecTest extends AndroidTestCase {
+    private static final String TEST_ALIAS_1 = "test1";
+
+    private static final X500Principal TEST_DN_1 = new X500Principal("CN=test1");
+
+    private static final long NOW_MILLIS = System.currentTimeMillis();
+
+    private static final BigInteger SERIAL_1 = BigInteger.ONE;
+
+    /* We have to round this off because X509v3 doesn't store milliseconds. */
+    private static final Date NOW = new Date(NOW_MILLIS - (NOW_MILLIS % 1000L));
+
+    @SuppressWarnings("deprecation")
+    private static final Date NOW_PLUS_10_YEARS = new Date(NOW.getYear() + 10, 0, 1);
+
+    public void testConstructor_Success() throws Exception {
+        AndroidKeyPairGeneratorSpec spec = new AndroidKeyPairGeneratorSpec(getContext(),
+                TEST_ALIAS_1, TEST_DN_1, SERIAL_1, NOW, NOW_PLUS_10_YEARS);
+
+        assertEquals("Context should be the one specified", getContext(), spec.getContext());
+
+        assertEquals("Alias should be the one specified", TEST_ALIAS_1, spec.getKeystoreAlias());
+
+        assertEquals("subjectDN should be the one specified", TEST_DN_1, spec.getSubjectDN());
+
+        assertEquals("startDate should be the one specified", NOW, spec.getStartDate());
+
+        assertEquals("endDate should be the one specified", NOW_PLUS_10_YEARS, spec.getEndDate());
+    }
+
+    public void testConstructor_NullContext_Failure() throws Exception {
+        try {
+            new AndroidKeyPairGeneratorSpec(null, TEST_ALIAS_1, TEST_DN_1, SERIAL_1, NOW,
+                    NOW_PLUS_10_YEARS);
+            fail("Should throw IllegalArgumentException when context is null");
+        } catch (IllegalArgumentException success) {
+        }
+    }
+
+    public void testConstructor_NullKeystoreAlias_Failure() throws Exception {
+        try {
+            new AndroidKeyPairGeneratorSpec(getContext(), null, TEST_DN_1, SERIAL_1, NOW,
+                    NOW_PLUS_10_YEARS);
+            fail("Should throw IllegalArgumentException when keystoreAlias is null");
+        } catch (IllegalArgumentException success) {
+        }
+    }
+
+    public void testConstructor_NullSubjectDN_Failure() throws Exception {
+        try {
+            new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, null, SERIAL_1, NOW,
+                    NOW_PLUS_10_YEARS);
+            fail("Should throw IllegalArgumentException when subjectDN is null");
+        } catch (IllegalArgumentException success) {
+        }
+    }
+
+    public void testConstructor_NullSerial_Failure() throws Exception {
+        try {
+            new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, null, NOW,
+                    NOW_PLUS_10_YEARS);
+            fail("Should throw IllegalArgumentException when startDate is null");
+        } catch (IllegalArgumentException success) {
+        }
+    }
+
+    public void testConstructor_NullStartDate_Failure() throws Exception {
+        try {
+            new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, SERIAL_1, null,
+                    NOW_PLUS_10_YEARS);
+            fail("Should throw IllegalArgumentException when startDate is null");
+        } catch (IllegalArgumentException success) {
+        }
+    }
+
+    public void testConstructor_NullEndDate_Failure() throws Exception {
+        try {
+            new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, SERIAL_1, NOW,
+                    null);
+            fail("Should throw IllegalArgumentException when keystoreAlias is null");
+        } catch (IllegalArgumentException success) {
+        }
+    }
+
+    public void testConstructor_EndBeforeStart_Failure() throws Exception {
+        try {
+            new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, SERIAL_1,
+                    NOW_PLUS_10_YEARS, NOW);
+            fail("Should throw IllegalArgumentException when end is before start");
+        } catch (IllegalArgumentException success) {
+        }
+    }
+}
diff --git a/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java b/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java
new file mode 100644
index 0000000..d108caaa
--- /dev/null
+++ b/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import android.test.AndroidTestCase;
+
+import java.io.ByteArrayInputStream;
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
+import javax.security.auth.x500.X500Principal;
+
+public class AndroidKeyPairGeneratorTest extends AndroidTestCase {
+    private android.security.KeyStore mAndroidKeyStore;
+
+    private java.security.KeyPairGenerator mGenerator;
+
+    private static final String TEST_ALIAS_1 = "test1";
+
+    private static final String TEST_ALIAS_2 = "test2";
+
+    private static final X500Principal TEST_DN_1 = new X500Principal("CN=test1");
+
+    private static final X500Principal TEST_DN_2 = new X500Principal("CN=test2");
+
+    private static final BigInteger TEST_SERIAL_1 = BigInteger.ONE;
+
+    private static final BigInteger TEST_SERIAL_2 = BigInteger.valueOf(2L);
+
+    private static final long NOW_MILLIS = System.currentTimeMillis();
+
+    /* We have to round this off because X509v3 doesn't store milliseconds. */
+    private static final Date NOW = new Date(NOW_MILLIS - (NOW_MILLIS % 1000L));
+
+    @SuppressWarnings("deprecation")
+    private static final Date NOW_PLUS_10_YEARS = new Date(NOW.getYear() + 10, 0, 1);
+
+    @Override
+    protected void setUp() throws Exception {
+        mAndroidKeyStore = android.security.KeyStore.getInstance();
+
+        assertTrue(mAndroidKeyStore.reset());
+
+        assertEquals(android.security.KeyStore.State.UNINITIALIZED, mAndroidKeyStore.state());
+
+        assertTrue(mAndroidKeyStore.password("1111"));
+
+        assertEquals(android.security.KeyStore.State.UNLOCKED, mAndroidKeyStore.state());
+
+        assertEquals(0, mAndroidKeyStore.saw("").length);
+
+        mGenerator = java.security.KeyPairGenerator.getInstance(AndroidKeyPairGenerator.NAME);
+    }
+
+    public void testKeyPairGenerator_Initialize_Params_Success() throws Exception {
+        mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1,
+                TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS));
+    }
+
+    public void testKeyPairGenerator_Initialize_KeySize_Failure() throws Exception {
+        try {
+            mGenerator.initialize(1024);
+            fail("KeyPairGenerator should not support setting the key size");
+        } catch (IllegalArgumentException success) {
+        }
+    }
+
+    public void testKeyPairGenerator_Initialize_KeySizeAndSecureRandom_Failure() throws Exception {
+        try {
+            mGenerator.initialize(1024, new SecureRandom());
+            fail("KeyPairGenerator should not support setting the key size");
+        } catch (IllegalArgumentException success) {
+        }
+    }
+
+    public void testKeyPairGenerator_Initialize_ParamsAndSecureRandom_Failure() throws Exception {
+        mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1,
+                TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS), new SecureRandom());
+    }
+
+    public void testKeyPairGenerator_GenerateKeyPair_Success() throws Exception {
+        mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1,
+                TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS));
+
+        final KeyPair pair = mGenerator.generateKeyPair();
+        assertNotNull("The KeyPair returned should not be null", pair);
+
+        assertKeyPairCorrect(pair, TEST_ALIAS_1, TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS);
+    }
+
+    public void testKeyPairGenerator_GenerateKeyPair_Replaced_Success() throws Exception {
+        // Generate the first key
+        {
+            mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1,
+                    TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS));
+            final KeyPair pair1 = mGenerator.generateKeyPair();
+            assertNotNull("The KeyPair returned should not be null", pair1);
+            assertKeyPairCorrect(pair1, TEST_ALIAS_1, TEST_DN_1, TEST_SERIAL_1, NOW,
+                    NOW_PLUS_10_YEARS);
+        }
+
+        // Replace the original key
+        {
+            mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_2,
+                    TEST_DN_2, TEST_SERIAL_2, NOW, NOW_PLUS_10_YEARS));
+            final KeyPair pair2 = mGenerator.generateKeyPair();
+            assertNotNull("The KeyPair returned should not be null", pair2);
+            assertKeyPairCorrect(pair2, TEST_ALIAS_2, TEST_DN_2, TEST_SERIAL_2, NOW,
+                    NOW_PLUS_10_YEARS);
+        }
+    }
+
+    private void assertKeyPairCorrect(KeyPair pair, String alias, X500Principal dn,
+            BigInteger serial, Date start, Date end) throws Exception {
+        final PublicKey pubKey = pair.getPublic();
+        assertNotNull("The PublicKey for the KeyPair should be not null", pubKey);
+
+        final PrivateKey privKey = pair.getPrivate();
+        assertNotNull("The PrivateKey for the KeyPair should be not null", privKey);
+
+        final byte[] userCertBytes = mAndroidKeyStore.get(Credentials.USER_CERTIFICATE + alias);
+        assertNotNull("The user certificate should exist for the generated entry", userCertBytes);
+
+        final CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        final Certificate userCert = cf
+                .generateCertificate(new ByteArrayInputStream(userCertBytes));
+
+        assertTrue("Certificate should be in X.509 format", userCert instanceof X509Certificate);
+
+        final X509Certificate x509userCert = (X509Certificate) userCert;
+
+        assertEquals("PublicKey used to sign certificate should match one returned in KeyPair",
+                pubKey, x509userCert.getPublicKey());
+
+        assertEquals("The Subject DN should be the one passed into the params", dn,
+                x509userCert.getSubjectDN());
+
+        assertEquals("The Issuer DN should be the same as the Subject DN", dn,
+                x509userCert.getIssuerDN());
+
+        assertEquals("The Serial should be the one passed into the params", serial,
+                x509userCert.getSerialNumber());
+
+        assertEquals("The notBefore date should be the one passed into the params", start,
+                x509userCert.getNotBefore());
+
+        assertEquals("The notAfter date should be the one passed into the params", end,
+                x509userCert.getNotAfter());
+
+        x509userCert.verify(pubKey);
+
+        final byte[] caCerts = mAndroidKeyStore.get(Credentials.CA_CERTIFICATE + alias);
+        assertNull("A list of CA certificates should not exist for the generated entry", caCerts);
+
+        final byte[] pubKeyBytes = mAndroidKeyStore.getPubkey(Credentials.USER_PRIVATE_KEY + alias);
+        assertNotNull("The keystore should return the public key for the generated key",
+                pubKeyBytes);
+    }
+}
diff --git a/keystore/tests/src/android/security/AndroidKeyStoreTest.java b/keystore/tests/src/android/security/AndroidKeyStoreTest.java
new file mode 100644
index 0000000..49e2f12
--- /dev/null
+++ b/keystore/tests/src/android/security/AndroidKeyStoreTest.java
@@ -0,0 +1,1554 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import com.android.org.bouncycastle.x509.X509V3CertificateGenerator;
+
+import org.apache.harmony.xnet.provider.jsse.OpenSSLEngine;
+
+import android.test.AndroidTestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.KeyStore.Entry;
+import java.security.KeyStore.PrivateKeyEntry;
+import java.security.KeyStore.TrustedCertificateEntry;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.security.auth.x500.X500Principal;
+
+public class AndroidKeyStoreTest extends AndroidTestCase {
+    private android.security.KeyStore mAndroidKeyStore;
+
+    private java.security.KeyStore mKeyStore;
+
+    private static final String TEST_ALIAS_1 = "test1";
+
+    private static final String TEST_ALIAS_2 = "test2";
+
+    private static final String TEST_ALIAS_3 = "test3";
+
+    private static final X500Principal TEST_DN_1 = new X500Principal("CN=test1");
+
+    private static final X500Principal TEST_DN_2 = new X500Principal("CN=test2");
+
+    private static final BigInteger TEST_SERIAL_1 = BigInteger.ONE;
+
+    private static final BigInteger TEST_SERIAL_2 = BigInteger.valueOf(2L);
+
+    private static final long NOW_MILLIS = System.currentTimeMillis();
+
+    /* We have to round this off because X509v3 doesn't store milliseconds. */
+    private static final Date NOW = new Date(NOW_MILLIS - (NOW_MILLIS % 1000L));
+
+    @SuppressWarnings("deprecation")
+    private static final Date NOW_PLUS_10_YEARS = new Date(NOW.getYear() + 10, 0, 1);
+
+    /*
+     * The keys and certificates below are generated with:
+     *
+     * openssl req -new -x509 -days 3650 -extensions v3_ca -keyout cakey.pem -out cacert.pem
+     * openssl req -newkey rsa:1024 -keyout userkey.pem -nodes -days 3650 -out userkey.req
+     * mkdir -p demoCA/newcerts
+     * touch demoCA/index.txt
+     * echo "01" > demoCA/serial
+     * openssl ca -out usercert.pem -in userkey.req -cert cacert.pem -keyfile cakey.pem -days 3650
+     */
+
+    /**
+     * Generated from above and converted with:
+     *
+     * openssl x509 -outform d -in cacert.pem | xxd -i | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] FAKE_CA_1 = {
+            (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0xce, (byte) 0x30, (byte) 0x82,
+            (byte) 0x02, (byte) 0x37, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01,
+            (byte) 0x02, (byte) 0x02, (byte) 0x09, (byte) 0x00, (byte) 0xe1, (byte) 0x6a,
+            (byte) 0xa2, (byte) 0xf4, (byte) 0x2e, (byte) 0x55, (byte) 0x48, (byte) 0x0a,
+            (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
+            (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
+            (byte) 0x05, (byte) 0x05, (byte) 0x00, (byte) 0x30, (byte) 0x4f, (byte) 0x31,
+            (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53,
+            (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03,
+            (byte) 0x55, (byte) 0x04, (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43,
+            (byte) 0x41, (byte) 0x31, (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06,
+            (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d,
+            (byte) 0x4d, (byte) 0x6f, (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61,
+            (byte) 0x69, (byte) 0x6e, (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65,
+            (byte) 0x77, (byte) 0x31, (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06,
+            (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12,
+            (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69,
+            (byte) 0x64, (byte) 0x20, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74,
+            (byte) 0x20, (byte) 0x43, (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73,
+            (byte) 0x30, (byte) 0x1e, (byte) 0x17, (byte) 0x0d, (byte) 0x31, (byte) 0x32,
+            (byte) 0x30, (byte) 0x38, (byte) 0x31, (byte) 0x34, (byte) 0x31, (byte) 0x36,
+            (byte) 0x35, (byte) 0x35, (byte) 0x34, (byte) 0x34, (byte) 0x5a, (byte) 0x17,
+            (byte) 0x0d, (byte) 0x32, (byte) 0x32, (byte) 0x30, (byte) 0x38, (byte) 0x31,
+            (byte) 0x32, (byte) 0x31, (byte) 0x36, (byte) 0x35, (byte) 0x35, (byte) 0x34,
+            (byte) 0x34, (byte) 0x5a, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b,
+            (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+            (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31,
+            (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41,
+            (byte) 0x31, (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03,
+            (byte) 0x55, (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d,
+            (byte) 0x6f, (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69,
+            (byte) 0x6e, (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77,
+            (byte) 0x31, (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03,
+            (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41,
+            (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64,
+            (byte) 0x20, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20,
+            (byte) 0x43, (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x30,
+            (byte) 0x81, (byte) 0x9f, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09,
+            (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d,
+            (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x03,
+            (byte) 0x81, (byte) 0x8d, (byte) 0x00, (byte) 0x30, (byte) 0x81, (byte) 0x89,
+            (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0xa3, (byte) 0x72,
+            (byte) 0xab, (byte) 0xd0, (byte) 0xe4, (byte) 0xad, (byte) 0x2f, (byte) 0xe7,
+            (byte) 0xe2, (byte) 0x79, (byte) 0x07, (byte) 0x36, (byte) 0x3d, (byte) 0x0c,
+            (byte) 0x8d, (byte) 0x42, (byte) 0x9a, (byte) 0x0a, (byte) 0x33, (byte) 0x64,
+            (byte) 0xb3, (byte) 0xcd, (byte) 0xb2, (byte) 0xd7, (byte) 0x3a, (byte) 0x42,
+            (byte) 0x06, (byte) 0x77, (byte) 0x45, (byte) 0x29, (byte) 0xe9, (byte) 0xcb,
+            (byte) 0xb7, (byte) 0x4a, (byte) 0xd6, (byte) 0xee, (byte) 0xad, (byte) 0x01,
+            (byte) 0x91, (byte) 0x9b, (byte) 0x0c, (byte) 0x59, (byte) 0xa1, (byte) 0x03,
+            (byte) 0xfa, (byte) 0xf0, (byte) 0x5a, (byte) 0x7c, (byte) 0x4f, (byte) 0xf7,
+            (byte) 0x8d, (byte) 0x36, (byte) 0x0f, (byte) 0x1f, (byte) 0x45, (byte) 0x7d,
+            (byte) 0x1b, (byte) 0x31, (byte) 0xa1, (byte) 0x35, (byte) 0x0b, (byte) 0x00,
+            (byte) 0xed, (byte) 0x7a, (byte) 0xb6, (byte) 0xc8, (byte) 0x4e, (byte) 0xa9,
+            (byte) 0x86, (byte) 0x4c, (byte) 0x7b, (byte) 0x99, (byte) 0x57, (byte) 0x41,
+            (byte) 0x12, (byte) 0xef, (byte) 0x6b, (byte) 0xbc, (byte) 0x3d, (byte) 0x60,
+            (byte) 0xf2, (byte) 0x99, (byte) 0x1a, (byte) 0xcd, (byte) 0xed, (byte) 0x56,
+            (byte) 0xa4, (byte) 0xe5, (byte) 0x36, (byte) 0x9f, (byte) 0x24, (byte) 0x1f,
+            (byte) 0xdc, (byte) 0x89, (byte) 0x40, (byte) 0xc8, (byte) 0x99, (byte) 0x92,
+            (byte) 0xab, (byte) 0x4a, (byte) 0xb5, (byte) 0x61, (byte) 0x45, (byte) 0x62,
+            (byte) 0xff, (byte) 0xa3, (byte) 0x45, (byte) 0x65, (byte) 0xaf, (byte) 0xf6,
+            (byte) 0x27, (byte) 0x30, (byte) 0x51, (byte) 0x0e, (byte) 0x0e, (byte) 0xeb,
+            (byte) 0x79, (byte) 0x0c, (byte) 0xbe, (byte) 0xb3, (byte) 0x0a, (byte) 0x6f,
+            (byte) 0x29, (byte) 0x06, (byte) 0xdc, (byte) 0x2f, (byte) 0x6b, (byte) 0x51,
+            (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xa3,
+            (byte) 0x81, (byte) 0xb1, (byte) 0x30, (byte) 0x81, (byte) 0xae, (byte) 0x30,
+            (byte) 0x1d, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e,
+            (byte) 0x04, (byte) 0x16, (byte) 0x04, (byte) 0x14, (byte) 0x33, (byte) 0x05,
+            (byte) 0xee, (byte) 0xfe, (byte) 0x6f, (byte) 0x60, (byte) 0xc7, (byte) 0xf9,
+            (byte) 0xa9, (byte) 0xd2, (byte) 0x73, (byte) 0x5c, (byte) 0x8f, (byte) 0x6d,
+            (byte) 0xa2, (byte) 0x2f, (byte) 0x97, (byte) 0x8e, (byte) 0x5d, (byte) 0x51,
+            (byte) 0x30, (byte) 0x7f, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d,
+            (byte) 0x23, (byte) 0x04, (byte) 0x78, (byte) 0x30, (byte) 0x76, (byte) 0x80,
+            (byte) 0x14, (byte) 0x33, (byte) 0x05, (byte) 0xee, (byte) 0xfe, (byte) 0x6f,
+            (byte) 0x60, (byte) 0xc7, (byte) 0xf9, (byte) 0xa9, (byte) 0xd2, (byte) 0x73,
+            (byte) 0x5c, (byte) 0x8f, (byte) 0x6d, (byte) 0xa2, (byte) 0x2f, (byte) 0x97,
+            (byte) 0x8e, (byte) 0x5d, (byte) 0x51, (byte) 0xa1, (byte) 0x53, (byte) 0xa4,
+            (byte) 0x51, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
+            (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06,
+            (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x0b,
+            (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+            (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, (byte) 0x31,
+            (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d, (byte) 0x6f,
+            (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69, (byte) 0x6e,
+            (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77, (byte) 0x31,
+            (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, (byte) 0x6e,
+            (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20,
+            (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x43,
+            (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x82, (byte) 0x09,
+            (byte) 0x00, (byte) 0xe1, (byte) 0x6a, (byte) 0xa2, (byte) 0xf4, (byte) 0x2e,
+            (byte) 0x55, (byte) 0x48, (byte) 0x0a, (byte) 0x30, (byte) 0x0c, (byte) 0x06,
+            (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x13, (byte) 0x04, (byte) 0x05,
+            (byte) 0x30, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0xff, (byte) 0x30,
+            (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48,
+            (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x05,
+            (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x81, (byte) 0x00,
+            (byte) 0x8c, (byte) 0x30, (byte) 0x42, (byte) 0xfa, (byte) 0xeb, (byte) 0x1a,
+            (byte) 0x26, (byte) 0xeb, (byte) 0xda, (byte) 0x56, (byte) 0x32, (byte) 0xf2,
+            (byte) 0x9d, (byte) 0xa5, (byte) 0x24, (byte) 0xd8, (byte) 0x3a, (byte) 0xda,
+            (byte) 0x30, (byte) 0xa6, (byte) 0x8b, (byte) 0x46, (byte) 0xfe, (byte) 0xfe,
+            (byte) 0xdb, (byte) 0xf1, (byte) 0xe6, (byte) 0xe1, (byte) 0x7c, (byte) 0x1b,
+            (byte) 0xe7, (byte) 0x77, (byte) 0x00, (byte) 0xa1, (byte) 0x1c, (byte) 0x19,
+            (byte) 0x17, (byte) 0x73, (byte) 0xb0, (byte) 0xf0, (byte) 0x9d, (byte) 0xf3,
+            (byte) 0x4f, (byte) 0xb6, (byte) 0xbc, (byte) 0xc7, (byte) 0x47, (byte) 0x85,
+            (byte) 0x2a, (byte) 0x4a, (byte) 0xa1, (byte) 0xa5, (byte) 0x58, (byte) 0xf5,
+            (byte) 0xc5, (byte) 0x1a, (byte) 0x51, (byte) 0xb1, (byte) 0x04, (byte) 0x80,
+            (byte) 0xee, (byte) 0x3a, (byte) 0xec, (byte) 0x2f, (byte) 0xe1, (byte) 0xfd,
+            (byte) 0x58, (byte) 0xeb, (byte) 0xed, (byte) 0x82, (byte) 0x9e, (byte) 0x38,
+            (byte) 0xa3, (byte) 0x24, (byte) 0x75, (byte) 0xf7, (byte) 0x3e, (byte) 0xc2,
+            (byte) 0xc5, (byte) 0x27, (byte) 0xeb, (byte) 0x6f, (byte) 0x7b, (byte) 0x50,
+            (byte) 0xda, (byte) 0x43, (byte) 0xdc, (byte) 0x3b, (byte) 0x0b, (byte) 0x6f,
+            (byte) 0x78, (byte) 0x8f, (byte) 0xb0, (byte) 0x66, (byte) 0xe1, (byte) 0x12,
+            (byte) 0x87, (byte) 0x5f, (byte) 0x97, (byte) 0x7b, (byte) 0xca, (byte) 0x14,
+            (byte) 0x79, (byte) 0xf7, (byte) 0xe8, (byte) 0x6c, (byte) 0x72, (byte) 0xdb,
+            (byte) 0x91, (byte) 0x65, (byte) 0x17, (byte) 0x54, (byte) 0xe0, (byte) 0x74,
+            (byte) 0x1d, (byte) 0xac, (byte) 0x47, (byte) 0x04, (byte) 0x12, (byte) 0xe0,
+            (byte) 0xc3, (byte) 0x66, (byte) 0x19, (byte) 0x05, (byte) 0x2e, (byte) 0x7e,
+            (byte) 0xf1, (byte) 0x61
+    };
+
+    /**
+     * Generated from above and converted with:
+     *
+     * openssl pkcs8 -topk8 -outform d -in userkey.pem -nocrypt | xxd -i | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] FAKE_KEY_1 = new byte[] {
+            (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x78, (byte) 0x02, (byte) 0x01,
+            (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a,
+            (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01,
+            (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x82,
+            (byte) 0x02, (byte) 0x62, (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x5e,
+            (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x81, (byte) 0x81,
+            (byte) 0x00, (byte) 0xce, (byte) 0x29, (byte) 0xeb, (byte) 0xf6, (byte) 0x5b,
+            (byte) 0x25, (byte) 0xdc, (byte) 0xa1, (byte) 0xa6, (byte) 0x2c, (byte) 0x66,
+            (byte) 0xcb, (byte) 0x20, (byte) 0x90, (byte) 0x27, (byte) 0x86, (byte) 0x8a,
+            (byte) 0x44, (byte) 0x71, (byte) 0x50, (byte) 0xda, (byte) 0xd3, (byte) 0x02,
+            (byte) 0x77, (byte) 0x55, (byte) 0xe9, (byte) 0xe8, (byte) 0x08, (byte) 0xf3,
+            (byte) 0x36, (byte) 0x9a, (byte) 0xae, (byte) 0xab, (byte) 0x04, (byte) 0x6d,
+            (byte) 0x00, (byte) 0x99, (byte) 0xbf, (byte) 0x7d, (byte) 0x0f, (byte) 0x67,
+            (byte) 0x8b, (byte) 0x1d, (byte) 0xd4, (byte) 0x2b, (byte) 0x7c, (byte) 0xcb,
+            (byte) 0xcd, (byte) 0x33, (byte) 0xc7, (byte) 0x84, (byte) 0x30, (byte) 0xe2,
+            (byte) 0x45, (byte) 0x21, (byte) 0xb3, (byte) 0x75, (byte) 0xf5, (byte) 0x79,
+            (byte) 0x02, (byte) 0xda, (byte) 0x50, (byte) 0xa3, (byte) 0x8b, (byte) 0xce,
+            (byte) 0xc3, (byte) 0x8e, (byte) 0x0f, (byte) 0x25, (byte) 0xeb, (byte) 0x08,
+            (byte) 0x2c, (byte) 0xdd, (byte) 0x1c, (byte) 0xcf, (byte) 0xff, (byte) 0x3b,
+            (byte) 0xde, (byte) 0xb6, (byte) 0xaa, (byte) 0x2a, (byte) 0xa9, (byte) 0xc4,
+            (byte) 0x8a, (byte) 0x24, (byte) 0x24, (byte) 0xe6, (byte) 0x29, (byte) 0x0d,
+            (byte) 0x98, (byte) 0x4c, (byte) 0x32, (byte) 0xa1, (byte) 0x7b, (byte) 0x23,
+            (byte) 0x2b, (byte) 0x42, (byte) 0x30, (byte) 0xee, (byte) 0x78, (byte) 0x08,
+            (byte) 0x47, (byte) 0xad, (byte) 0xf2, (byte) 0x96, (byte) 0xd5, (byte) 0xf1,
+            (byte) 0x62, (byte) 0x42, (byte) 0x2d, (byte) 0x35, (byte) 0x19, (byte) 0xb4,
+            (byte) 0x3c, (byte) 0xc9, (byte) 0xc3, (byte) 0x5f, (byte) 0x03, (byte) 0x16,
+            (byte) 0x3a, (byte) 0x23, (byte) 0xac, (byte) 0xcb, (byte) 0xce, (byte) 0x9e,
+            (byte) 0x51, (byte) 0x2e, (byte) 0x6d, (byte) 0x02, (byte) 0x03, (byte) 0x01,
+            (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x81, (byte) 0x80, (byte) 0x16,
+            (byte) 0x59, (byte) 0xc3, (byte) 0x24, (byte) 0x1d, (byte) 0x33, (byte) 0x98,
+            (byte) 0x9c, (byte) 0xc9, (byte) 0xc8, (byte) 0x2c, (byte) 0x88, (byte) 0xbf,
+            (byte) 0x0a, (byte) 0x01, (byte) 0xce, (byte) 0xfb, (byte) 0x34, (byte) 0x7a,
+            (byte) 0x58, (byte) 0x7a, (byte) 0xb0, (byte) 0xbf, (byte) 0xa6, (byte) 0xb2,
+            (byte) 0x60, (byte) 0xbe, (byte) 0x70, (byte) 0x21, (byte) 0xf5, (byte) 0xfc,
+            (byte) 0x85, (byte) 0x0d, (byte) 0x33, (byte) 0x58, (byte) 0xa1, (byte) 0xe5,
+            (byte) 0x09, (byte) 0x36, (byte) 0x84, (byte) 0xb2, (byte) 0x04, (byte) 0x0a,
+            (byte) 0x02, (byte) 0xd3, (byte) 0x88, (byte) 0x1f, (byte) 0x0c, (byte) 0x2b,
+            (byte) 0x1d, (byte) 0xe9, (byte) 0x3d, (byte) 0xe7, (byte) 0x79, (byte) 0xf9,
+            (byte) 0x32, (byte) 0x5c, (byte) 0x8a, (byte) 0x75, (byte) 0x49, (byte) 0x12,
+            (byte) 0xe4, (byte) 0x05, (byte) 0x26, (byte) 0xd4, (byte) 0x2e, (byte) 0x9e,
+            (byte) 0x1f, (byte) 0xcc, (byte) 0x54, (byte) 0xad, (byte) 0x33, (byte) 0x8d,
+            (byte) 0x99, (byte) 0x00, (byte) 0xdc, (byte) 0xf5, (byte) 0xb4, (byte) 0xa2,
+            (byte) 0x2f, (byte) 0xba, (byte) 0xe5, (byte) 0x62, (byte) 0x30, (byte) 0x6d,
+            (byte) 0xe6, (byte) 0x3d, (byte) 0xeb, (byte) 0x24, (byte) 0xc2, (byte) 0xdc,
+            (byte) 0x5f, (byte) 0xb7, (byte) 0x16, (byte) 0x35, (byte) 0xa3, (byte) 0x98,
+            (byte) 0x98, (byte) 0xa8, (byte) 0xef, (byte) 0xe8, (byte) 0xc4, (byte) 0x96,
+            (byte) 0x6d, (byte) 0x38, (byte) 0xab, (byte) 0x26, (byte) 0x6d, (byte) 0x30,
+            (byte) 0xc2, (byte) 0xa0, (byte) 0x44, (byte) 0xe4, (byte) 0xff, (byte) 0x7e,
+            (byte) 0xbe, (byte) 0x7c, (byte) 0x33, (byte) 0xa5, (byte) 0x10, (byte) 0xad,
+            (byte) 0xd7, (byte) 0x1e, (byte) 0x13, (byte) 0x20, (byte) 0xb3, (byte) 0x1f,
+            (byte) 0x41, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xf1, (byte) 0x89,
+            (byte) 0x07, (byte) 0x0f, (byte) 0xe8, (byte) 0xcf, (byte) 0xab, (byte) 0x13,
+            (byte) 0x2a, (byte) 0x8f, (byte) 0x88, (byte) 0x80, (byte) 0x11, (byte) 0x9a,
+            (byte) 0x79, (byte) 0xb6, (byte) 0x59, (byte) 0x3a, (byte) 0x50, (byte) 0x6e,
+            (byte) 0x57, (byte) 0x37, (byte) 0xab, (byte) 0x2a, (byte) 0xd2, (byte) 0xaa,
+            (byte) 0xd9, (byte) 0x72, (byte) 0x73, (byte) 0xff, (byte) 0x8b, (byte) 0x47,
+            (byte) 0x76, (byte) 0xdd, (byte) 0xdc, (byte) 0xf5, (byte) 0x97, (byte) 0x44,
+            (byte) 0x3a, (byte) 0x78, (byte) 0xbe, (byte) 0x17, (byte) 0xb4, (byte) 0x22,
+            (byte) 0x6f, (byte) 0xe5, (byte) 0x23, (byte) 0x70, (byte) 0x1d, (byte) 0x10,
+            (byte) 0x5d, (byte) 0xba, (byte) 0x16, (byte) 0x81, (byte) 0xf1, (byte) 0x45,
+            (byte) 0xce, (byte) 0x30, (byte) 0xb4, (byte) 0xab, (byte) 0x80, (byte) 0xe4,
+            (byte) 0x98, (byte) 0x31, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xda,
+            (byte) 0x82, (byte) 0x9d, (byte) 0x3f, (byte) 0xca, (byte) 0x2f, (byte) 0xe1,
+            (byte) 0xd4, (byte) 0x86, (byte) 0x77, (byte) 0x48, (byte) 0xa6, (byte) 0xab,
+            (byte) 0xab, (byte) 0x1c, (byte) 0x42, (byte) 0x5c, (byte) 0xd5, (byte) 0xc7,
+            (byte) 0x46, (byte) 0x59, (byte) 0x91, (byte) 0x3f, (byte) 0xfc, (byte) 0xcc,
+            (byte) 0xec, (byte) 0xc2, (byte) 0x40, (byte) 0x12, (byte) 0x2c, (byte) 0x8d,
+            (byte) 0x1f, (byte) 0xa2, (byte) 0x18, (byte) 0x88, (byte) 0xee, (byte) 0x82,
+            (byte) 0x4a, (byte) 0x5a, (byte) 0x5e, (byte) 0x88, (byte) 0x20, (byte) 0xe3,
+            (byte) 0x7b, (byte) 0xe0, (byte) 0xd8, (byte) 0x3a, (byte) 0x52, (byte) 0x9a,
+            (byte) 0x26, (byte) 0x6a, (byte) 0x04, (byte) 0xec, (byte) 0xe8, (byte) 0xb9,
+            (byte) 0x48, (byte) 0x40, (byte) 0xe1, (byte) 0xe1, (byte) 0x83, (byte) 0xa6,
+            (byte) 0x67, (byte) 0xa6, (byte) 0xfd, (byte) 0x02, (byte) 0x41, (byte) 0x00,
+            (byte) 0x89, (byte) 0x72, (byte) 0x3e, (byte) 0xb0, (byte) 0x90, (byte) 0xfd,
+            (byte) 0x4c, (byte) 0x0e, (byte) 0xd6, (byte) 0x13, (byte) 0x63, (byte) 0xcb,
+            (byte) 0xed, (byte) 0x38, (byte) 0x88, (byte) 0xb6, (byte) 0x79, (byte) 0xc4,
+            (byte) 0x33, (byte) 0x6c, (byte) 0xf6, (byte) 0xf8, (byte) 0xd8, (byte) 0xd0,
+            (byte) 0xbf, (byte) 0x9d, (byte) 0x35, (byte) 0xac, (byte) 0x69, (byte) 0xd2,
+            (byte) 0x2b, (byte) 0xc1, (byte) 0xf9, (byte) 0x24, (byte) 0x7b, (byte) 0xce,
+            (byte) 0xcd, (byte) 0xcb, (byte) 0xa7, (byte) 0xb2, (byte) 0x7a, (byte) 0x0a,
+            (byte) 0x27, (byte) 0x19, (byte) 0xc9, (byte) 0xaf, (byte) 0x0d, (byte) 0x21,
+            (byte) 0x89, (byte) 0x88, (byte) 0x7c, (byte) 0xad, (byte) 0x9e, (byte) 0x8d,
+            (byte) 0x47, (byte) 0x6d, (byte) 0x3f, (byte) 0xce, (byte) 0x7b, (byte) 0xa1,
+            (byte) 0x74, (byte) 0xf1, (byte) 0xa0, (byte) 0xa1, (byte) 0x02, (byte) 0x41,
+            (byte) 0x00, (byte) 0xd9, (byte) 0xa8, (byte) 0xf5, (byte) 0xfe, (byte) 0xce,
+            (byte) 0xe6, (byte) 0x77, (byte) 0x6b, (byte) 0xfe, (byte) 0x2d, (byte) 0xe0,
+            (byte) 0x1e, (byte) 0xb6, (byte) 0x2e, (byte) 0x12, (byte) 0x4e, (byte) 0x40,
+            (byte) 0xaf, (byte) 0x6a, (byte) 0x7b, (byte) 0x37, (byte) 0x49, (byte) 0x2a,
+            (byte) 0x96, (byte) 0x25, (byte) 0x83, (byte) 0x49, (byte) 0xd4, (byte) 0x0c,
+            (byte) 0xc6, (byte) 0x78, (byte) 0x25, (byte) 0x24, (byte) 0x90, (byte) 0x90,
+            (byte) 0x06, (byte) 0x15, (byte) 0x9e, (byte) 0xfe, (byte) 0xf9, (byte) 0xdf,
+            (byte) 0x5b, (byte) 0xf3, (byte) 0x7e, (byte) 0x38, (byte) 0x70, (byte) 0xeb,
+            (byte) 0x57, (byte) 0xd0, (byte) 0xd9, (byte) 0xa7, (byte) 0x0e, (byte) 0x14,
+            (byte) 0xf7, (byte) 0x95, (byte) 0x68, (byte) 0xd5, (byte) 0xc8, (byte) 0xab,
+            (byte) 0x9d, (byte) 0x3a, (byte) 0x2b, (byte) 0x51, (byte) 0xf9, (byte) 0x02,
+            (byte) 0x41, (byte) 0x00, (byte) 0x96, (byte) 0xdf, (byte) 0xe9, (byte) 0x67,
+            (byte) 0x6c, (byte) 0xdc, (byte) 0x90, (byte) 0x14, (byte) 0xb4, (byte) 0x1d,
+            (byte) 0x22, (byte) 0x33, (byte) 0x4a, (byte) 0x31, (byte) 0xc1, (byte) 0x9d,
+            (byte) 0x2e, (byte) 0xff, (byte) 0x9a, (byte) 0x2a, (byte) 0x95, (byte) 0x4b,
+            (byte) 0x27, (byte) 0x74, (byte) 0xcb, (byte) 0x21, (byte) 0xc3, (byte) 0xd2,
+            (byte) 0x0b, (byte) 0xb2, (byte) 0x46, (byte) 0x87, (byte) 0xf8, (byte) 0x28,
+            (byte) 0x01, (byte) 0x8b, (byte) 0xd8, (byte) 0xb9, (byte) 0x4b, (byte) 0xcd,
+            (byte) 0x9a, (byte) 0x96, (byte) 0x41, (byte) 0x0e, (byte) 0x36, (byte) 0x6d,
+            (byte) 0x40, (byte) 0x42, (byte) 0xbc, (byte) 0xd9, (byte) 0xd3, (byte) 0x7b,
+            (byte) 0xbc, (byte) 0xa7, (byte) 0x92, (byte) 0x90, (byte) 0xdd, (byte) 0xa1,
+            (byte) 0x9c, (byte) 0xce, (byte) 0xa1, (byte) 0x87, (byte) 0x11, (byte) 0x51
+    };
+
+    /**
+     * Generated from above and converted with:
+     *
+     * openssl x509 -outform d -in usercert.pem | xxd -i | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] FAKE_USER_1 = new byte[] {
+            (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x95, (byte) 0x30, (byte) 0x82,
+            (byte) 0x01, (byte) 0xfe, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01,
+            (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x30, (byte) 0x0d,
+            (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
+            (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x05,
+            (byte) 0x00, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
+            (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06,
+            (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x0b,
+            (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+            (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, (byte) 0x31,
+            (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d, (byte) 0x6f,
+            (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69, (byte) 0x6e,
+            (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77, (byte) 0x31,
+            (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, (byte) 0x6e,
+            (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20,
+            (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x43,
+            (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x30, (byte) 0x1e,
+            (byte) 0x17, (byte) 0x0d, (byte) 0x31, (byte) 0x32, (byte) 0x30, (byte) 0x38,
+            (byte) 0x31, (byte) 0x34, (byte) 0x32, (byte) 0x33, (byte) 0x32, (byte) 0x35,
+            (byte) 0x34, (byte) 0x38, (byte) 0x5a, (byte) 0x17, (byte) 0x0d, (byte) 0x32,
+            (byte) 0x32, (byte) 0x30, (byte) 0x38, (byte) 0x31, (byte) 0x32, (byte) 0x32,
+            (byte) 0x33, (byte) 0x32, (byte) 0x35, (byte) 0x34, (byte) 0x38, (byte) 0x5a,
+            (byte) 0x30, (byte) 0x55, (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09,
+            (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06, (byte) 0x13,
+            (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
+            (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x08,
+            (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, (byte) 0x31, (byte) 0x1b,
+            (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+            (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, (byte) 0x6e, (byte) 0x64,
+            (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20, (byte) 0x54,
+            (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x43, (byte) 0x61,
+            (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x31, (byte) 0x1c, (byte) 0x30,
+            (byte) 0x1a, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x03,
+            (byte) 0x13, (byte) 0x13, (byte) 0x73, (byte) 0x65, (byte) 0x72, (byte) 0x76,
+            (byte) 0x65, (byte) 0x72, (byte) 0x31, (byte) 0x2e, (byte) 0x65, (byte) 0x78,
+            (byte) 0x61, (byte) 0x6d, (byte) 0x70, (byte) 0x6c, (byte) 0x65, (byte) 0x2e,
+            (byte) 0x63, (byte) 0x6f, (byte) 0x6d, (byte) 0x30, (byte) 0x81, (byte) 0x9f,
+            (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
+            (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
+            (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x8d,
+            (byte) 0x00, (byte) 0x30, (byte) 0x81, (byte) 0x89, (byte) 0x02, (byte) 0x81,
+            (byte) 0x81, (byte) 0x00, (byte) 0xce, (byte) 0x29, (byte) 0xeb, (byte) 0xf6,
+            (byte) 0x5b, (byte) 0x25, (byte) 0xdc, (byte) 0xa1, (byte) 0xa6, (byte) 0x2c,
+            (byte) 0x66, (byte) 0xcb, (byte) 0x20, (byte) 0x90, (byte) 0x27, (byte) 0x86,
+            (byte) 0x8a, (byte) 0x44, (byte) 0x71, (byte) 0x50, (byte) 0xda, (byte) 0xd3,
+            (byte) 0x02, (byte) 0x77, (byte) 0x55, (byte) 0xe9, (byte) 0xe8, (byte) 0x08,
+            (byte) 0xf3, (byte) 0x36, (byte) 0x9a, (byte) 0xae, (byte) 0xab, (byte) 0x04,
+            (byte) 0x6d, (byte) 0x00, (byte) 0x99, (byte) 0xbf, (byte) 0x7d, (byte) 0x0f,
+            (byte) 0x67, (byte) 0x8b, (byte) 0x1d, (byte) 0xd4, (byte) 0x2b, (byte) 0x7c,
+            (byte) 0xcb, (byte) 0xcd, (byte) 0x33, (byte) 0xc7, (byte) 0x84, (byte) 0x30,
+            (byte) 0xe2, (byte) 0x45, (byte) 0x21, (byte) 0xb3, (byte) 0x75, (byte) 0xf5,
+            (byte) 0x79, (byte) 0x02, (byte) 0xda, (byte) 0x50, (byte) 0xa3, (byte) 0x8b,
+            (byte) 0xce, (byte) 0xc3, (byte) 0x8e, (byte) 0x0f, (byte) 0x25, (byte) 0xeb,
+            (byte) 0x08, (byte) 0x2c, (byte) 0xdd, (byte) 0x1c, (byte) 0xcf, (byte) 0xff,
+            (byte) 0x3b, (byte) 0xde, (byte) 0xb6, (byte) 0xaa, (byte) 0x2a, (byte) 0xa9,
+            (byte) 0xc4, (byte) 0x8a, (byte) 0x24, (byte) 0x24, (byte) 0xe6, (byte) 0x29,
+            (byte) 0x0d, (byte) 0x98, (byte) 0x4c, (byte) 0x32, (byte) 0xa1, (byte) 0x7b,
+            (byte) 0x23, (byte) 0x2b, (byte) 0x42, (byte) 0x30, (byte) 0xee, (byte) 0x78,
+            (byte) 0x08, (byte) 0x47, (byte) 0xad, (byte) 0xf2, (byte) 0x96, (byte) 0xd5,
+            (byte) 0xf1, (byte) 0x62, (byte) 0x42, (byte) 0x2d, (byte) 0x35, (byte) 0x19,
+            (byte) 0xb4, (byte) 0x3c, (byte) 0xc9, (byte) 0xc3, (byte) 0x5f, (byte) 0x03,
+            (byte) 0x16, (byte) 0x3a, (byte) 0x23, (byte) 0xac, (byte) 0xcb, (byte) 0xce,
+            (byte) 0x9e, (byte) 0x51, (byte) 0x2e, (byte) 0x6d, (byte) 0x02, (byte) 0x03,
+            (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xa3, (byte) 0x7b, (byte) 0x30,
+            (byte) 0x79, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x1d, (byte) 0x13, (byte) 0x04, (byte) 0x02, (byte) 0x30, (byte) 0x00,
+            (byte) 0x30, (byte) 0x2c, (byte) 0x06, (byte) 0x09, (byte) 0x60, (byte) 0x86,
+            (byte) 0x48, (byte) 0x01, (byte) 0x86, (byte) 0xf8, (byte) 0x42, (byte) 0x01,
+            (byte) 0x0d, (byte) 0x04, (byte) 0x1f, (byte) 0x16, (byte) 0x1d, (byte) 0x4f,
+            (byte) 0x70, (byte) 0x65, (byte) 0x6e, (byte) 0x53, (byte) 0x53, (byte) 0x4c,
+            (byte) 0x20, (byte) 0x47, (byte) 0x65, (byte) 0x6e, (byte) 0x65, (byte) 0x72,
+            (byte) 0x61, (byte) 0x74, (byte) 0x65, (byte) 0x64, (byte) 0x20, (byte) 0x43,
+            (byte) 0x65, (byte) 0x72, (byte) 0x74, (byte) 0x69, (byte) 0x66, (byte) 0x69,
+            (byte) 0x63, (byte) 0x61, (byte) 0x74, (byte) 0x65, (byte) 0x30, (byte) 0x1d,
+            (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e, (byte) 0x04,
+            (byte) 0x16, (byte) 0x04, (byte) 0x14, (byte) 0x32, (byte) 0xa1, (byte) 0x1e,
+            (byte) 0x6b, (byte) 0x69, (byte) 0x04, (byte) 0xfe, (byte) 0xb3, (byte) 0xcd,
+            (byte) 0xf8, (byte) 0xbb, (byte) 0x14, (byte) 0xcd, (byte) 0xff, (byte) 0xd4,
+            (byte) 0x16, (byte) 0xc3, (byte) 0xab, (byte) 0x44, (byte) 0x2f, (byte) 0x30,
+            (byte) 0x1f, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x23,
+            (byte) 0x04, (byte) 0x18, (byte) 0x30, (byte) 0x16, (byte) 0x80, (byte) 0x14,
+            (byte) 0x33, (byte) 0x05, (byte) 0xee, (byte) 0xfe, (byte) 0x6f, (byte) 0x60,
+            (byte) 0xc7, (byte) 0xf9, (byte) 0xa9, (byte) 0xd2, (byte) 0x73, (byte) 0x5c,
+            (byte) 0x8f, (byte) 0x6d, (byte) 0xa2, (byte) 0x2f, (byte) 0x97, (byte) 0x8e,
+            (byte) 0x5d, (byte) 0x51, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09,
+            (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d,
+            (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x05, (byte) 0x00, (byte) 0x03,
+            (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0x46, (byte) 0x42, (byte) 0xef,
+            (byte) 0x56, (byte) 0x89, (byte) 0x78, (byte) 0x90, (byte) 0x38, (byte) 0x24,
+            (byte) 0x9f, (byte) 0x8c, (byte) 0x7a, (byte) 0xce, (byte) 0x7a, (byte) 0xa5,
+            (byte) 0xb5, (byte) 0x1e, (byte) 0x74, (byte) 0x96, (byte) 0x34, (byte) 0x49,
+            (byte) 0x8b, (byte) 0xed, (byte) 0x44, (byte) 0xb3, (byte) 0xc9, (byte) 0x05,
+            (byte) 0xd7, (byte) 0x48, (byte) 0x55, (byte) 0x52, (byte) 0x59, (byte) 0x15,
+            (byte) 0x0b, (byte) 0xaa, (byte) 0x16, (byte) 0x86, (byte) 0xd2, (byte) 0x8e,
+            (byte) 0x16, (byte) 0x99, (byte) 0xe8, (byte) 0x5f, (byte) 0x11, (byte) 0x71,
+            (byte) 0x42, (byte) 0x55, (byte) 0xd1, (byte) 0xc4, (byte) 0x6f, (byte) 0x2e,
+            (byte) 0xa9, (byte) 0x64, (byte) 0x6f, (byte) 0xd8, (byte) 0xfd, (byte) 0x43,
+            (byte) 0x13, (byte) 0x24, (byte) 0xaa, (byte) 0x67, (byte) 0xe6, (byte) 0xf5,
+            (byte) 0xca, (byte) 0x80, (byte) 0x5e, (byte) 0x3a, (byte) 0x3e, (byte) 0xcc,
+            (byte) 0x4f, (byte) 0xba, (byte) 0x87, (byte) 0xe6, (byte) 0xae, (byte) 0xbf,
+            (byte) 0x8f, (byte) 0xd5, (byte) 0x28, (byte) 0x38, (byte) 0x58, (byte) 0x30,
+            (byte) 0x24, (byte) 0xf6, (byte) 0x53, (byte) 0x5b, (byte) 0x41, (byte) 0x53,
+            (byte) 0xe6, (byte) 0x45, (byte) 0xbc, (byte) 0xbe, (byte) 0xe6, (byte) 0xbb,
+            (byte) 0x5d, (byte) 0xd8, (byte) 0xa7, (byte) 0xf9, (byte) 0x64, (byte) 0x99,
+            (byte) 0x04, (byte) 0x43, (byte) 0x75, (byte) 0xd7, (byte) 0x2d, (byte) 0x32,
+            (byte) 0x0a, (byte) 0x94, (byte) 0xaf, (byte) 0x06, (byte) 0x34, (byte) 0xae,
+            (byte) 0x46, (byte) 0xbd, (byte) 0xda, (byte) 0x00, (byte) 0x0e, (byte) 0x25,
+            (byte) 0xc2, (byte) 0xf7, (byte) 0xc9, (byte) 0xc3, (byte) 0x65, (byte) 0xd2,
+            (byte) 0x08, (byte) 0x41, (byte) 0x0a, (byte) 0xf3, (byte) 0x72
+    };
+
+    /**
+     * The amount of time to allow before and after expected time for variance
+     * in timing tests.
+     */
+    private static final long SLOP_TIME_MILLIS = 15000L;
+
+    @Override
+    protected void setUp() throws Exception {
+        mAndroidKeyStore = android.security.KeyStore.getInstance();
+
+        assertTrue(mAndroidKeyStore.reset());
+
+        assertEquals(android.security.KeyStore.State.UNINITIALIZED, mAndroidKeyStore.state());
+
+        assertTrue(mAndroidKeyStore.password("1111"));
+
+        assertEquals(android.security.KeyStore.State.UNLOCKED, mAndroidKeyStore.state());
+
+        assertEquals(0, mAndroidKeyStore.saw("").length);
+
+        mKeyStore = java.security.KeyStore.getInstance(AndroidKeyStore.NAME);
+    }
+
+    private void assertAliases(final String[] expectedAliases) throws KeyStoreException {
+        final Enumeration<String> aliases = mKeyStore.aliases();
+        int count = 0;
+
+        final Set<String> expectedSet = new HashSet<String>();
+        expectedSet.addAll(Arrays.asList(expectedAliases));
+
+        while (aliases.hasMoreElements()) {
+            count++;
+            final String alias = aliases.nextElement();
+            assertTrue("The alias should be in the expected set", expectedSet.contains(alias));
+            expectedSet.remove(alias);
+        }
+        assertTrue("The expected set and actual set should be exactly equal", expectedSet.isEmpty());
+        assertEquals("There should be the correct number of keystore entries",
+                expectedAliases.length, count);
+    }
+
+    public void testKeyStore_Aliases_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertAliases(new String[] {});
+
+        assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1));
+
+        assertAliases(new String[] { TEST_ALIAS_1 });
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+        assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2 });
+    }
+
+    public void testKeyStore_Aliases_NotInitialized_Failure() throws Exception {
+        try {
+            mKeyStore.aliases();
+            fail("KeyStore should throw exception when not initialized");
+        } catch (KeyStoreException success) {
+        }
+    }
+
+    public void testKeyStore_ContainsAliases_PrivateAndCA_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertAliases(new String[] {});
+
+        assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1));
+
+        assertTrue("Should contain generated private key", mKeyStore.containsAlias(TEST_ALIAS_1));
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+        assertTrue("Should contain added CA certificate", mKeyStore.containsAlias(TEST_ALIAS_2));
+
+        assertFalse("Should not contain unadded certificate alias",
+                mKeyStore.containsAlias(TEST_ALIAS_3));
+    }
+
+    public void testKeyStore_ContainsAliases_CAOnly_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+        assertTrue("Should contain added CA certificate", mKeyStore.containsAlias(TEST_ALIAS_2));
+    }
+
+    public void testKeyStore_ContainsAliases_NonExistent_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertFalse("Should contain added CA certificate", mKeyStore.containsAlias(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_DeleteEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        // TEST_ALIAS_1
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        // TEST_ALIAS_2
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+        // TEST_ALIAS_3
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_3, FAKE_CA_1));
+
+        assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2, TEST_ALIAS_3 });
+
+        mKeyStore.deleteEntry(TEST_ALIAS_1);
+
+        assertAliases(new String[] { TEST_ALIAS_2, TEST_ALIAS_3 });
+
+        mKeyStore.deleteEntry(TEST_ALIAS_3);
+
+        assertAliases(new String[] { TEST_ALIAS_2 });
+
+        mKeyStore.deleteEntry(TEST_ALIAS_2);
+
+        assertAliases(new String[] { });
+    }
+
+    public void testKeyStore_DeleteEntry_EmptyStore_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        try {
+            mKeyStore.deleteEntry(TEST_ALIAS_1);
+            fail("Should throw KeyStoreException with non-existent alias");
+        } catch (KeyStoreException success) {
+        }
+    }
+
+    public void testKeyStore_DeleteEntry_NonExistent_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        // TEST_ALIAS_1
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        try {
+            mKeyStore.deleteEntry(TEST_ALIAS_2);
+            fail("Should throw KeyStoreException with non-existent alias");
+        } catch (KeyStoreException success) {
+        }
+    }
+
+    public void testKeyStore_GetCertificate_Single_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertAliases(new String[] { TEST_ALIAS_1 });
+
+        assertNull("Certificate should not exist in keystore",
+                mKeyStore.getCertificate(TEST_ALIAS_2));
+
+        Certificate retrieved = mKeyStore.getCertificate(TEST_ALIAS_1);
+
+        assertNotNull("Retrieved certificate should not be null", retrieved);
+
+        CertificateFactory f = CertificateFactory.getInstance("X.509");
+        Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        assertEquals("Actual and retrieved certificates should be the same", actual, retrieved);
+    }
+
+    public void testKeyStore_GetCertificate_NonExist_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertNull("Certificate should not exist in keystore",
+                mKeyStore.getCertificate(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_GetCertificateAlias_CAEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        CertificateFactory f = CertificateFactory.getInstance("X.509");
+        Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        assertEquals("Stored certificate alias should be found", TEST_ALIAS_1,
+                mKeyStore.getCertificateAlias(actual));
+    }
+
+    public void testKeyStore_GetCertificateAlias_PrivateKeyEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        CertificateFactory f = CertificateFactory.getInstance("X.509");
+        Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+
+        assertEquals("Stored certificate alias should be found", TEST_ALIAS_1,
+                mKeyStore.getCertificateAlias(actual));
+    }
+
+    public void testKeyStore_GetCertificateAlias_CAEntry_WithPrivateKeyUsingCA_Success()
+            throws Exception {
+        mKeyStore.load(null, null);
+
+        // Insert TrustedCertificateEntry with CA name
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+        // Insert PrivateKeyEntry that uses the same CA
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        CertificateFactory f = CertificateFactory.getInstance("X.509");
+        Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        assertEquals("Stored certificate alias should be found", TEST_ALIAS_2,
+                mKeyStore.getCertificateAlias(actual));
+    }
+
+    public void testKeyStore_GetCertificateAlias_NonExist_Empty_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        CertificateFactory f = CertificateFactory.getInstance("X.509");
+        Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        assertNull("Stored certificate alias should not be found",
+                mKeyStore.getCertificateAlias(actual));
+    }
+
+    public void testKeyStore_GetCertificateAlias_NonExist_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        CertificateFactory f = CertificateFactory.getInstance("X.509");
+        Certificate userCert = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+
+        assertNull("Stored certificate alias should be found",
+                mKeyStore.getCertificateAlias(userCert));
+    }
+
+    public void testKeyStore_GetCertificateChain_SingleLength_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        Certificate[] expected = new Certificate[2];
+        expected[0] = cf.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+        expected[1] = cf.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        Certificate[] actual = mKeyStore.getCertificateChain(TEST_ALIAS_1);
+
+        assertNotNull("Returned certificate chain should not be null", actual);
+        assertEquals("Returned certificate chain should be correct size", expected.length,
+                actual.length);
+        assertEquals("First certificate should be user certificate", expected[0], actual[0]);
+        assertEquals("Second certificate should be CA certificate", expected[1], actual[1]);
+
+        // Negative test when keystore is populated.
+        assertNull("Stored certificate alias should not be found",
+                mKeyStore.getCertificateChain(TEST_ALIAS_2));
+    }
+
+    public void testKeyStore_GetCertificateChain_NonExist_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertNull("Stored certificate alias should not be found",
+                mKeyStore.getCertificateChain(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_GetCreationDate_PrivateKeyEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        Date now = new Date();
+        Date actual = mKeyStore.getCreationDate(TEST_ALIAS_1);
+
+        Date expectedAfter = new Date(now.getTime() - SLOP_TIME_MILLIS);
+        Date expectedBefore = new Date(now.getTime() + SLOP_TIME_MILLIS);
+
+        assertTrue("Time should be close to current time", actual.before(expectedBefore));
+        assertTrue("Time should be close to current time", actual.after(expectedAfter));
+    }
+
+    public void testKeyStore_GetCreationDate_CAEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        Date now = new Date();
+        Date actual = mKeyStore.getCreationDate(TEST_ALIAS_1);
+        assertNotNull("Certificate should be found", actual);
+
+        Date expectedAfter = new Date(now.getTime() - SLOP_TIME_MILLIS);
+        Date expectedBefore = new Date(now.getTime() + SLOP_TIME_MILLIS);
+
+        assertTrue("Time should be close to current time", actual.before(expectedBefore));
+        assertTrue("Time should be close to current time", actual.after(expectedAfter));
+    }
+
+    public void testKeyStore_GetEntry_NullParams_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        Entry entry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+        assertNotNull("Entry should exist", entry);
+
+        assertTrue("Should be a PrivateKeyEntry", entry instanceof PrivateKeyEntry);
+
+        PrivateKeyEntry keyEntry = (PrivateKeyEntry) entry;
+
+        assertPrivateKeyEntryEquals(keyEntry, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void assertPrivateKeyEntryEquals(PrivateKeyEntry keyEntry, byte[] key, byte[] cert,
+            byte[] ca) throws Exception {
+        KeyFactory keyFact = KeyFactory.getInstance("RSA");
+        PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(key));
+
+        CertificateFactory certFact = CertificateFactory.getInstance("X.509");
+        Certificate expectedCert = certFact.generateCertificate(new ByteArrayInputStream(cert));
+
+        final Collection<Certificate> expectedChain;
+        if (ca != null) {
+            expectedChain = (Collection<Certificate>) certFact
+                    .generateCertificates(new ByteArrayInputStream(ca));
+        } else {
+            expectedChain = null;
+        }
+
+        assertPrivateKeyEntryEquals(keyEntry, expectedKey, expectedCert, expectedChain);
+    }
+
+    private void assertPrivateKeyEntryEquals(PrivateKeyEntry keyEntry, PrivateKey expectedKey,
+            Certificate expectedCert, Collection<Certificate> expectedChain) throws Exception {
+        assertEquals("Returned PrivateKey should be what we inserted", expectedKey,
+                keyEntry.getPrivateKey());
+
+        assertEquals("Returned Certificate should be what we inserted", expectedCert,
+                keyEntry.getCertificate());
+
+        Certificate[] actualChain = keyEntry.getCertificateChain();
+
+        assertEquals("First certificate in chain should be user cert", expectedCert, actualChain[0]);
+
+        if (expectedChain == null) {
+            assertEquals("Certificate chain should not include CAs", 1, actualChain.length);
+        } else {
+            int i = 1;
+            final Iterator<Certificate> it = expectedChain.iterator();
+            while (it.hasNext()) {
+                assertEquals("CA chain certificate should equal what we put in", it.next(),
+                        actualChain[i++]);
+            }
+        }
+    }
+
+    public void testKeyStore_GetEntry_Nonexistent_NullParams_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertNull("A non-existent entry should return null",
+                mKeyStore.getEntry(TEST_ALIAS_1, null));
+    }
+
+    public void testKeyStore_GetKey_NoPassword_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        Key key = mKeyStore.getKey(TEST_ALIAS_1, null);
+        assertNotNull("Key should exist", key);
+
+        assertTrue("Should be a RSAPrivateKey", key instanceof RSAPrivateKey);
+
+        RSAPrivateKey actualKey = (RSAPrivateKey) key;
+
+        KeyFactory keyFact = KeyFactory.getInstance("RSA");
+        PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+
+        assertEquals("Inserted key should be same as retrieved key", actualKey, expectedKey);
+    }
+
+    public void testKeyStore_GetKey_Certificate_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertNull("Certificate entries should return null", mKeyStore.getKey(TEST_ALIAS_1, null));
+    }
+
+    public void testKeyStore_GetKey_NonExistent_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertNull("A non-existent entry should return null", mKeyStore.getKey(TEST_ALIAS_1, null));
+    }
+
+    public void testKeyStore_GetProvider_Success() throws Exception {
+        assertEquals(AndroidKeyStoreProvider.PROVIDER_NAME, mKeyStore.getProvider().getName());
+    }
+
+    public void testKeyStore_GetType_Success() throws Exception {
+        assertEquals(AndroidKeyStore.NAME, mKeyStore.getType());
+    }
+
+    public void testKeyStore_IsCertificateEntry_CA_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertTrue("Should return true for CA certificate",
+                mKeyStore.isCertificateEntry(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_IsCertificateEntry_PrivateKey_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertFalse("Should return false for PrivateKeyEntry",
+                mKeyStore.isCertificateEntry(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_IsCertificateEntry_NonExist_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertFalse("Should return false for non-existent entry",
+                mKeyStore.isCertificateEntry(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_IsKeyEntry_PrivateKey_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertTrue("Should return true for PrivateKeyEntry", mKeyStore.isKeyEntry(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_IsKeyEntry_CA_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertFalse("Should return false for CA certificate", mKeyStore.isKeyEntry(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_IsKeyEntry_NonExist_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertFalse("Should return false for non-existent entry",
+                mKeyStore.isKeyEntry(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_SetCertificate_CA_Success() throws Exception {
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+        final Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        mKeyStore.load(null, null);
+
+        mKeyStore.setCertificateEntry(TEST_ALIAS_1, actual);
+        assertAliases(new String[] { TEST_ALIAS_1 });
+
+        Certificate retrieved = mKeyStore.getCertificate(TEST_ALIAS_1);
+
+        assertEquals("Retrieved certificate should be the same as the one inserted", actual,
+                retrieved);
+    }
+
+    public void testKeyStore_SetCertificate_CAExists_Overwrite_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertAliases(new String[] { TEST_ALIAS_1 });
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+        final Certificate cert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        // TODO have separate FAKE_CA for second test
+        mKeyStore.setCertificateEntry(TEST_ALIAS_1, cert);
+
+        assertAliases(new String[] { TEST_ALIAS_1 });
+    }
+
+    public void testKeyStore_SetCertificate_PrivateKeyExists_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertAliases(new String[] { TEST_ALIAS_1 });
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+        final Certificate cert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        try {
+            mKeyStore.setCertificateEntry(TEST_ALIAS_1, cert);
+            fail("Should throw when trying to overwrite a PrivateKey entry with a Certificate");
+        } catch (KeyStoreException success) {
+        }
+    }
+
+    public void testKeyStore_SetEntry_PrivateKeyEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        KeyFactory keyFact = KeyFactory.getInstance("RSA");
+        PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        final Certificate[] expectedChain = new Certificate[2];
+        expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+        expectedChain[1] = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        PrivateKeyEntry expected = new PrivateKeyEntry(expectedKey, expectedChain);
+
+        mKeyStore.setEntry(TEST_ALIAS_1, expected, null);
+
+        Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+        assertNotNull("Retrieved entry should exist", actualEntry);
+
+        assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                actualEntry instanceof PrivateKeyEntry);
+
+        PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+        assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+    }
+
+    public void testKeyStore_SetEntry_PrivateKeyEntry_Overwrites_PrivateKeyEntry_Success()
+            throws Exception {
+        mKeyStore.load(null, null);
+
+        final KeyFactory keyFact = KeyFactory.getInstance("RSA");
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        // Start with PrivateKeyEntry
+        {
+            PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+
+            final Certificate[] expectedChain = new Certificate[2];
+            expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+            expectedChain[1] = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+            PrivateKeyEntry expected = new PrivateKeyEntry(expectedKey, expectedChain);
+
+            mKeyStore.setEntry(TEST_ALIAS_1, expected, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+
+            assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                    actualEntry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+            assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+        }
+
+        // TODO make entirely new test vector for the overwrite
+        // Replace with PrivateKeyEntry
+        {
+            PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+
+            final Certificate[] expectedChain = new Certificate[2];
+            expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+            expectedChain[1] = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+            PrivateKeyEntry expected = new PrivateKeyEntry(expectedKey, expectedChain);
+
+            mKeyStore.setEntry(TEST_ALIAS_1, expected, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+
+            assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                    actualEntry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+            assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+        }
+    }
+
+    public void testKeyStore_SetEntry_CAEntry_Overwrites_PrivateKeyEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        // Start with TrustedCertificateEntry
+        {
+            final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+            TrustedCertificateEntry expectedCertEntry = new TrustedCertificateEntry(caCert);
+            mKeyStore.setEntry(TEST_ALIAS_1, expectedCertEntry, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+            assertTrue("Retrieved entry should be of type TrustedCertificateEntry",
+                    actualEntry instanceof TrustedCertificateEntry);
+            TrustedCertificateEntry actualCertEntry = (TrustedCertificateEntry) actualEntry;
+            assertEquals("Stored and retrieved certificates should be the same",
+                    expectedCertEntry.getTrustedCertificate(),
+                    actualCertEntry.getTrustedCertificate());
+        }
+
+        // Replace with PrivateKeyEntry
+        {
+            KeyFactory keyFact = KeyFactory.getInstance("RSA");
+            PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+            final Certificate[] expectedChain = new Certificate[2];
+            expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+            expectedChain[1] = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+            PrivateKeyEntry expectedPrivEntry = new PrivateKeyEntry(expectedKey, expectedChain);
+
+            mKeyStore.setEntry(TEST_ALIAS_1, expectedPrivEntry, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+            assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                    actualEntry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry actualPrivEntry = (PrivateKeyEntry) actualEntry;
+            assertPrivateKeyEntryEquals(actualPrivEntry, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+        }
+    }
+
+    public void testKeyStore_SetEntry_PrivateKeyEntry_Overwrites_CAEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        // Start with PrivateKeyEntry
+        {
+            KeyFactory keyFact = KeyFactory.getInstance("RSA");
+            PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+            final Certificate[] expectedChain = new Certificate[2];
+            expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+            expectedChain[1] = caCert;
+
+            PrivateKeyEntry expectedPrivEntry = new PrivateKeyEntry(expectedKey, expectedChain);
+
+            mKeyStore.setEntry(TEST_ALIAS_1, expectedPrivEntry, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+            assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                    actualEntry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry actualPrivEntry = (PrivateKeyEntry) actualEntry;
+            assertPrivateKeyEntryEquals(actualPrivEntry, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+        }
+
+        // Replace with TrustedCertificateEntry
+        {
+            TrustedCertificateEntry expectedCertEntry = new TrustedCertificateEntry(caCert);
+            mKeyStore.setEntry(TEST_ALIAS_1, expectedCertEntry, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+            assertTrue("Retrieved entry should be of type TrustedCertificateEntry",
+                    actualEntry instanceof TrustedCertificateEntry);
+            TrustedCertificateEntry actualCertEntry = (TrustedCertificateEntry) actualEntry;
+            assertEquals("Stored and retrieved certificates should be the same",
+                    expectedCertEntry.getTrustedCertificate(),
+                    actualCertEntry.getTrustedCertificate());
+        }
+    }
+
+    public void testKeyStore_SetEntry_PrivateKeyEntry_Overwrites_ShortPrivateKeyEntry_Success()
+            throws Exception {
+        mKeyStore.load(null, null);
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        // Start with PrivateKeyEntry
+        {
+            KeyFactory keyFact = KeyFactory.getInstance("RSA");
+            PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+            final Certificate[] expectedChain = new Certificate[2];
+            expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+            expectedChain[1] = caCert;
+
+            PrivateKeyEntry expectedPrivEntry = new PrivateKeyEntry(expectedKey, expectedChain);
+
+            mKeyStore.setEntry(TEST_ALIAS_1, expectedPrivEntry, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+            assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                    actualEntry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry actualPrivEntry = (PrivateKeyEntry) actualEntry;
+            assertPrivateKeyEntryEquals(actualPrivEntry, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+        }
+
+        // Replace with PrivateKeyEntry that has no chain
+        {
+            KeyFactory keyFact = KeyFactory.getInstance("RSA");
+            PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+            final Certificate[] expectedChain = new Certificate[1];
+            expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+
+            PrivateKeyEntry expectedPrivEntry = new PrivateKeyEntry(expectedKey, expectedChain);
+
+            mKeyStore.setEntry(TEST_ALIAS_1, expectedPrivEntry, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+            assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                    actualEntry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry actualPrivEntry = (PrivateKeyEntry) actualEntry;
+            assertPrivateKeyEntryEquals(actualPrivEntry, FAKE_KEY_1, FAKE_USER_1, null);
+        }
+    }
+
+    public void testKeyStore_SetEntry_CAEntry_Overwrites_CAEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        // Insert TrustedCertificateEntry
+        {
+            final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+            TrustedCertificateEntry expectedCertEntry = new TrustedCertificateEntry(caCert);
+            mKeyStore.setEntry(TEST_ALIAS_1, expectedCertEntry, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+            assertTrue("Retrieved entry should be of type TrustedCertificateEntry",
+                    actualEntry instanceof TrustedCertificateEntry);
+            TrustedCertificateEntry actualCertEntry = (TrustedCertificateEntry) actualEntry;
+            assertEquals("Stored and retrieved certificates should be the same",
+                    expectedCertEntry.getTrustedCertificate(),
+                    actualCertEntry.getTrustedCertificate());
+        }
+
+        // Replace with TrustedCertificateEntry of USER
+        {
+            final Certificate userCert = f
+                    .generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+
+            TrustedCertificateEntry expectedUserEntry = new TrustedCertificateEntry(userCert);
+            mKeyStore.setEntry(TEST_ALIAS_1, expectedUserEntry, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+            assertTrue("Retrieved entry should be of type TrustedCertificateEntry",
+                    actualEntry instanceof TrustedCertificateEntry);
+            TrustedCertificateEntry actualUserEntry = (TrustedCertificateEntry) actualEntry;
+            assertEquals("Stored and retrieved certificates should be the same",
+                    expectedUserEntry.getTrustedCertificate(),
+                    actualUserEntry.getTrustedCertificate());
+        }
+    }
+
+    public void testKeyStore_SetKeyEntry_ProtectedKey_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        KeyFactory keyFact = KeyFactory.getInstance("RSA");
+        PrivateKey privKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+        final Certificate[] chain = new Certificate[2];
+        chain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+        chain[1] = caCert;
+
+        try {
+            mKeyStore.setKeyEntry(TEST_ALIAS_1, privKey, "foo".toCharArray(), chain);
+            fail("Should fail when a password is specified");
+        } catch (KeyStoreException success) {
+        }
+    }
+
+    public void testKeyStore_SetKeyEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        KeyFactory keyFact = KeyFactory.getInstance("RSA");
+        PrivateKey privKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+        final Certificate[] chain = new Certificate[2];
+        chain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+        chain[1] = caCert;
+
+        mKeyStore.setKeyEntry(TEST_ALIAS_1, privKey, null, chain);
+
+        Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+        assertNotNull("Retrieved entry should exist", actualEntry);
+
+        assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                actualEntry instanceof PrivateKeyEntry);
+
+        PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+        assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+    }
+
+    public void testKeyStore_SetKeyEntry_Replaced_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        // Insert initial key
+        {
+            KeyFactory keyFact = KeyFactory.getInstance("RSA");
+            PrivateKey privKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+            final Certificate[] chain = new Certificate[2];
+            chain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+            chain[1] = caCert;
+
+            mKeyStore.setKeyEntry(TEST_ALIAS_1, privKey, null, chain);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+
+            assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                    actualEntry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+            assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+        }
+
+        // TODO make a separate key
+        // Replace key
+        {
+            KeyFactory keyFact = KeyFactory.getInstance("RSA");
+            PrivateKey privKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+            final Certificate[] chain = new Certificate[2];
+            chain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+            chain[1] = caCert;
+
+            mKeyStore.setKeyEntry(TEST_ALIAS_1, privKey, null, chain);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+
+            assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                    actualEntry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+            assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private static X509Certificate generateCertificate(android.security.KeyStore keyStore,
+            String alias, BigInteger serialNumber, X500Principal subjectDN, Date notBefore,
+            Date notAfter) throws Exception {
+        final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + alias;
+
+        final PrivateKey privKey;
+        final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore");
+        try {
+            privKey = engine.getPrivateKeyById(privateKeyAlias);
+        } catch (InvalidKeyException e) {
+            throw new RuntimeException("Can't get key", e);
+        }
+
+        final byte[] pubKeyBytes = keyStore.getPubkey(privateKeyAlias);
+
+        final PublicKey pubKey;
+        try {
+            final KeyFactory keyFact = KeyFactory.getInstance("RSA");
+            pubKey = keyFact.generatePublic(new X509EncodedKeySpec(pubKeyBytes));
+        } catch (NoSuchAlgorithmException e) {
+            throw new IllegalStateException("Can't instantiate RSA key generator", e);
+        } catch (InvalidKeySpecException e) {
+            throw new IllegalStateException("keystore returned invalid key encoding", e);
+        }
+
+        final X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+        certGen.setPublicKey(pubKey);
+        certGen.setSerialNumber(serialNumber);
+        certGen.setSubjectDN(subjectDN);
+        certGen.setIssuerDN(subjectDN);
+        certGen.setNotBefore(notBefore);
+        certGen.setNotAfter(notAfter);
+        certGen.setSignatureAlgorithm("sha1WithRSA");
+
+        final X509Certificate cert = certGen.generate(privKey);
+
+        return cert;
+    }
+
+    public void testKeyStore_SetKeyEntry_ReplacedChain_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        // Create key #1
+        {
+            final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1;
+            assertTrue(mAndroidKeyStore.generate(privateKeyAlias));
+
+            Key key = mKeyStore.getKey(TEST_ALIAS_1, null);
+
+            assertTrue(key instanceof PrivateKey);
+
+            PrivateKey expectedKey = (PrivateKey) key;
+
+            X509Certificate expectedCert = generateCertificate(mAndroidKeyStore, TEST_ALIAS_1,
+                    TEST_SERIAL_1, TEST_DN_1, NOW, NOW_PLUS_10_YEARS);
+
+            assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1,
+                    expectedCert.getEncoded()));
+
+            Entry entry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+
+            assertTrue(entry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry keyEntry = (PrivateKeyEntry) entry;
+
+            assertPrivateKeyEntryEquals(keyEntry, expectedKey, expectedCert, null);
+        }
+
+        // Replace key #1 with new chain
+        {
+            Key key = mKeyStore.getKey(TEST_ALIAS_1, null);
+
+            assertTrue(key instanceof PrivateKey);
+
+            PrivateKey expectedKey = (PrivateKey) key;
+
+            X509Certificate expectedCert = generateCertificate(mAndroidKeyStore, TEST_ALIAS_1,
+                    TEST_SERIAL_2, TEST_DN_2, NOW, NOW_PLUS_10_YEARS);
+
+            mKeyStore.setKeyEntry(TEST_ALIAS_1, expectedKey, null,
+                    new Certificate[] { expectedCert });
+
+            Entry entry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+
+            assertTrue(entry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry keyEntry = (PrivateKeyEntry) entry;
+
+            assertPrivateKeyEntryEquals(keyEntry, expectedKey, expectedCert, null);
+        }
+    }
+
+    public void testKeyStore_SetKeyEntry_ReplacedChain_DifferentPrivateKey_Failure()
+            throws Exception {
+        mKeyStore.load(null, null);
+
+        // Create key #1
+        {
+            final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1;
+            assertTrue(mAndroidKeyStore.generate(privateKeyAlias));
+
+            X509Certificate cert = generateCertificate(mAndroidKeyStore, TEST_ALIAS_1,
+                    TEST_SERIAL_1, TEST_DN_1, NOW, NOW_PLUS_10_YEARS);
+
+            assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1,
+                    cert.getEncoded()));
+        }
+
+        // Create key #2
+        {
+            final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + TEST_ALIAS_2;
+            assertTrue(mAndroidKeyStore.generate(privateKeyAlias));
+
+            X509Certificate cert = generateCertificate(mAndroidKeyStore, TEST_ALIAS_2,
+                    TEST_SERIAL_2, TEST_DN_2, NOW, NOW_PLUS_10_YEARS);
+
+            assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_2,
+                    cert.getEncoded()));
+        }
+
+        // Replace key #1 with key #2
+        {
+            Key key1 = mKeyStore.getKey(TEST_ALIAS_2, null);
+
+            X509Certificate cert = generateCertificate(mAndroidKeyStore, TEST_ALIAS_2,
+                    TEST_SERIAL_2, TEST_DN_2, NOW, NOW_PLUS_10_YEARS);
+
+            try {
+                mKeyStore.setKeyEntry(TEST_ALIAS_1, key1, null, new Certificate[] { cert });
+                fail("Should not allow setting of KeyEntry with wrong PrivaetKey");
+            } catch (KeyStoreException success) {
+            }
+        }
+    }
+
+    public void testKeyStore_Size_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertEquals("The keystore size should match expected", 1, mKeyStore.size());
+        assertAliases(new String[] { TEST_ALIAS_1 });
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+        assertEquals("The keystore size should match expected", 2, mKeyStore.size());
+        assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2 });
+
+        assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_3));
+
+        assertEquals("The keystore size should match expected", 3, mKeyStore.size());
+        assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2, TEST_ALIAS_3 });
+
+        assertTrue(mAndroidKeyStore.delete(Credentials.CA_CERTIFICATE + TEST_ALIAS_1));
+
+        assertEquals("The keystore size should match expected", 2, mKeyStore.size());
+        assertAliases(new String[] { TEST_ALIAS_2, TEST_ALIAS_3 });
+
+        assertTrue(mAndroidKeyStore.delKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_3));
+
+        assertEquals("The keystore size should match expected", 1, mKeyStore.size());
+        assertAliases(new String[] { TEST_ALIAS_2 });
+    }
+
+    public void testKeyStore_Store_LoadStoreParam_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        try {
+            mKeyStore.store(null);
+            fail("Should throw UnsupportedOperationException when trying to store");
+        } catch (UnsupportedOperationException success) {
+        }
+    }
+
+    public void testKeyStore_Load_InputStreamSupplied_Failure() throws Exception {
+        byte[] buf = "FAKE KEYSTORE".getBytes();
+        ByteArrayInputStream is = new ByteArrayInputStream(buf);
+
+        try {
+            mKeyStore.load(is, null);
+            fail("Should throw IllegalArgumentException when InputStream is supplied");
+        } catch (IllegalArgumentException success) {
+        }
+    }
+
+    public void testKeyStore_Load_PasswordSupplied_Failure() throws Exception {
+        try {
+            mKeyStore.load(null, "password".toCharArray());
+            fail("Should throw IllegalArgumentException when password is supplied");
+        } catch (IllegalArgumentException success) {
+        }
+    }
+
+    public void testKeyStore_Store_OutputStream_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        OutputStream sink = new ByteArrayOutputStream();
+        try {
+            mKeyStore.store(sink, null);
+            fail("Should throw UnsupportedOperationException when trying to store");
+        } catch (UnsupportedOperationException success) {
+        }
+
+        try {
+            mKeyStore.store(sink, "blah".toCharArray());
+            fail("Should throw UnsupportedOperationException when trying to store");
+        } catch (UnsupportedOperationException success) {
+        }
+    }
+}
diff --git a/keystore/tests/src/android/security/KeyStoreTest.java b/keystore/tests/src/android/security/KeyStoreTest.java
index 9f35b8d..07a2d7b 100755
--- a/keystore/tests/src/android/security/KeyStoreTest.java
+++ b/keystore/tests/src/android/security/KeyStoreTest.java
@@ -19,9 +19,11 @@
 import android.app.Activity;
 import android.security.KeyStore;
 import android.test.ActivityUnitTestCase;
+import android.test.AssertionFailedError;
 import android.test.suitebuilder.annotation.MediumTest;
 import java.nio.charset.Charsets;
 import java.util.Arrays;
+import java.util.Date;
 import java.util.HashSet;
 
 /**
@@ -403,4 +405,52 @@
         assertFalse("Should fail to ungrant key to other user second time",
                 mKeyStore.ungrant(TEST_KEYNAME, 0));
     }
+
+    /**
+     * The amount of time to allow before and after expected time for variance
+     * in timing tests.
+     */
+    private static final long SLOP_TIME_MILLIS = 15000L;
+
+    public void testGetmtime_Success() throws Exception {
+        assertTrue("Password should work for keystore",
+                mKeyStore.password(TEST_PASSWD));
+
+        assertTrue("Should be able to import key when unlocked",
+                mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
+
+        long now = System.currentTimeMillis();
+        long actual = mKeyStore.getmtime(TEST_KEYNAME);
+
+        long expectedAfter = now - SLOP_TIME_MILLIS;
+        long expectedBefore = now + SLOP_TIME_MILLIS;
+
+        assertLessThan("Time should be close to current time", expectedBefore, actual);
+        assertGreaterThan("Time should be close to current time", expectedAfter, actual);
+    }
+
+    private static void assertLessThan(String explanation, long expectedBefore, long actual) {
+        if (actual >= expectedBefore) {
+            throw new AssertionFailedError(explanation + ": actual=" + actual
+                    + ", expected before: " + expectedBefore);
+        }
+    }
+
+    private static void assertGreaterThan(String explanation, long expectedAfter, long actual) {
+        if (actual <= expectedAfter) {
+            throw new AssertionFailedError(explanation + ": actual=" + actual
+                    + ", expected after: " + expectedAfter);
+        }
+    }
+
+    public void testGetmtime_NonExist_Failure() throws Exception {
+        assertTrue("Password should work for keystore",
+                mKeyStore.password(TEST_PASSWD));
+
+        assertTrue("Should be able to import key when unlocked",
+                mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
+
+        assertEquals("-1 should be returned for non-existent key",
+                -1L, mKeyStore.getmtime(TEST_KEYNAME2));
+    }
 }
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 8d59d8e..8bd805c 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -98,6 +98,24 @@
 
         return path;
     }
+
+    /*
+     * Like strdup(), but uses C++ "new" operator instead of malloc.
+     */
+    static char* strdupNew(const char* str)
+    {
+        char* newStr;
+        int len;
+
+        if (str == NULL)
+            return NULL;
+
+        len = strlen(str);
+        newStr = new char[len+1];
+        memcpy(newStr, str, len+1);
+
+        return newStr;
+    }
 }
 
 /*
diff --git a/libs/androidfw/BackupData.cpp b/libs/androidfw/BackupData.cpp
index 7b1bcba..4e3b522 100644
--- a/libs/androidfw/BackupData.cpp
+++ b/libs/androidfw/BackupData.cpp
@@ -327,6 +327,7 @@
         if (pos == -1) {
             return errno;
         }
+        m_pos = pos;
     }
     SKIP_PADDING();
     return NO_ERROR;
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 8cce191..0107da4 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -1470,6 +1470,9 @@
     if (country[1] != o.country[1]) {
         return country[1] < o.country[1] ? -1 : 1;
     }
+    if ((screenLayout & MASK_LAYOUTDIR) != (o.screenLayout & MASK_LAYOUTDIR)) {
+        return (screenLayout & MASK_LAYOUTDIR) < (o.screenLayout & MASK_LAYOUTDIR) ? -1 : 1;
+    }
     if (smallestScreenWidthDp != o.smallestScreenWidthDp) {
         return smallestScreenWidthDp < o.smallestScreenWidthDp ? -1 : 1;
     }
@@ -1558,6 +1561,13 @@
         }
     }
 
+    if (screenLayout || o.screenLayout) {
+        if (((screenLayout^o.screenLayout) & MASK_LAYOUTDIR) != 0) {
+            if (!(screenLayout & MASK_LAYOUTDIR)) return false;
+            if (!(o.screenLayout & MASK_LAYOUTDIR)) return true;
+        }
+    }
+
     if (smallestScreenWidthDp || o.smallestScreenWidthDp) {
         if (smallestScreenWidthDp != o.smallestScreenWidthDp) {
             if (!smallestScreenWidthDp) return false;
@@ -1683,6 +1693,15 @@
             }
         }
 
+        if (screenLayout || o.screenLayout) {
+            if (((screenLayout^o.screenLayout) & MASK_LAYOUTDIR) != 0
+                    && (requested->screenLayout & MASK_LAYOUTDIR)) {
+                int myLayoutDir = screenLayout & MASK_LAYOUTDIR;
+                int oLayoutDir = o.screenLayout & MASK_LAYOUTDIR;
+                return (myLayoutDir > oLayoutDir);
+            }
+        }
+
         if (smallestScreenWidthDp || o.smallestScreenWidthDp) {
             // The configuration closest to the actual size is best.
             // We assume that larger configs have already been filtered
@@ -1906,6 +1925,12 @@
         }
     }
     if (screenConfig != 0) {
+        const int layoutDir = screenLayout&MASK_LAYOUTDIR;
+        const int setLayoutDir = settings.screenLayout&MASK_LAYOUTDIR;
+        if (layoutDir != 0 && layoutDir != setLayoutDir) {
+            return false;
+        }
+
         const int screenSize = screenLayout&MASK_SCREENSIZE;
         const int setScreenSize = settings.screenLayout&MASK_SCREENSIZE;
         // Any screen sizes for larger screens than the setting do not
@@ -2032,6 +2057,21 @@
         if (res.size() > 0) res.append("-");
         res.append(country, 2);
     }
+    if ((screenLayout&MASK_LAYOUTDIR) != 0) {
+        if (res.size() > 0) res.append("-");
+        switch (screenLayout&ResTable_config::MASK_LAYOUTDIR) {
+            case ResTable_config::LAYOUTDIR_LTR:
+                res.append("ldltr");
+                break;
+            case ResTable_config::LAYOUTDIR_RTL:
+                res.append("ldrtl");
+                break;
+            default:
+                res.appendFormat("layoutDir=%d",
+                        dtohs(screenLayout&ResTable_config::MASK_LAYOUTDIR));
+                break;
+        }
+    }
     if (smallestScreenWidthDp != 0) {
         if (res.size() > 0) res.append("-");
         res.appendFormat("sw%ddp", dtohs(smallestScreenWidthDp));
diff --git a/libs/androidfw/tests/ObbFile_test.cpp b/libs/androidfw/tests/ObbFile_test.cpp
index 09d4d7d..2c9f650 100644
--- a/libs/androidfw/tests/ObbFile_test.cpp
+++ b/libs/androidfw/tests/ObbFile_test.cpp
@@ -22,6 +22,8 @@
 
 #include <gtest/gtest.h>
 
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <fcntl.h>
 #include <string.h>
 
@@ -43,7 +45,7 @@
         mFileName = new char[totalLen];
         snprintf(mFileName, totalLen, "%s%s", mExternalStorage, TEST_FILENAME);
 
-        int fd = ::open(mFileName, O_CREAT | O_TRUNC);
+        int fd = ::open(mFileName, O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
         if (fd < 0) {
             FAIL() << "Couldn't create " << mFileName << " for tests";
         }
diff --git a/libs/diskusage/dirsize.c b/libs/diskusage/dirsize.c
index 45e7b2a..6703783 100644
--- a/libs/diskusage/dirsize.c
+++ b/libs/diskusage/dirsize.c
@@ -49,6 +49,9 @@
 
     while ((de = readdir(d))) {
         const char *name = de->d_name;
+        if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+            size += stat_size(&s);
+        }
         if (de->d_type == DT_DIR) {
             int subfd;
 
@@ -64,10 +67,6 @@
             if (subfd >= 0) {
                 size += calculate_dir_size(subfd);
             }
-        } else {
-            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
-                size += stat_size(&s);
-            }
         }
     }
     closedir(d);
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 5ec3983..549edd2 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -6,17 +6,22 @@
 ifeq ($(USE_OPENGL_RENDERER),true)
 	LOCAL_SRC_FILES:= \
 		utils/SortedListImpl.cpp \
+		font/CacheTexture.cpp \
+		font/Font.cpp \
 		FontRenderer.cpp \
 		GammaFontRenderer.cpp \
 		Caches.cpp \
 		DisplayListLogBuffer.cpp \
 		DisplayListRenderer.cpp \
+		Dither.cpp \
 		FboCache.cpp \
 		GradientCache.cpp \
+		Layer.cpp \
 		LayerCache.cpp \
 		LayerRenderer.cpp \
 		Matrix.cpp \
 		OpenGLRenderer.cpp \
+		PathRenderer.cpp \
 		Patch.cpp \
 		PatchCache.cpp \
 		PathCache.cpp \
@@ -27,9 +32,10 @@
 		SkiaColorFilter.cpp \
 		SkiaShader.cpp \
 		Snapshot.cpp \
+		Stencil.cpp \
 		TextureCache.cpp \
 		TextDropShadowCache.cpp
-	
+
 	LOCAL_C_INCLUDES += \
 		$(JNI_H_INCLUDE) \
 		$(LOCAL_PATH)/../../include/utils \
@@ -40,12 +46,19 @@
 		external/skia/include/utils
 
 	LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER -DGL_GLEXT_PROTOTYPES
-	LOCAL_CFLAGS += -fvisibility=hidden
 	LOCAL_MODULE_CLASS := SHARED_LIBRARIES
 	LOCAL_SHARED_LIBRARIES := libcutils libutils libGLESv2 libskia libui
 	LOCAL_MODULE := libhwui
 	LOCAL_MODULE_TAGS := optional
-	
+
+	ifndef HWUI_COMPILE_SYMBOLS
+		LOCAL_CFLAGS += -fvisibility=hidden
+	endif
+
+	ifdef HWUI_COMPILE_FOR_PERF
+		LOCAL_CFLAGS += -fno-omit-frame-pointer -marm -mapcs
+	endif
+
 	include $(BUILD_SHARED_LIBRARY)
 
     include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index f210820..e7085b0 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -49,15 +49,13 @@
 
 Caches::Caches(): Singleton<Caches>(), mInitialized(false) {
     init();
+    initFont();
     initExtensions();
     initConstraints();
+    initProperties();
 
     mDebugLevel = readDebugLevel();
     ALOGD("Enabling debug mode %d", mDebugLevel);
-
-#if RENDER_LAYERS_AS_REGIONS
-    INIT_LOGD("Layers will be composited as regions");
-#endif
 }
 
 void Caches::init() {
@@ -70,10 +68,13 @@
     mCurrentBuffer = meshBuffer;
     mCurrentIndicesBuffer = 0;
     mCurrentPositionPointer = this;
+    mCurrentPositionStride = 0;
     mCurrentTexCoordsPointer = this;
 
     mTexCoordsArrayEnabled = false;
 
+    glDisable(GL_SCISSOR_TEST);
+    scissorEnabled = false;
     mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
 
     glActiveTexture(gTextureUnits[0]);
@@ -86,9 +87,15 @@
     lastDstMode = GL_ZERO;
     currentProgram = NULL;
 
+    mFunctorsCount = 0;
+
     mInitialized = true;
 }
 
+void Caches::initFont() {
+    fontRenderer = GammaFontRenderer::createRenderer();
+}
+
 void Caches::initExtensions() {
     if (extensions.hasDebugMarker()) {
         eventMark = glInsertEventMarkerEXT;
@@ -119,6 +126,23 @@
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
 }
 
+void Caches::initProperties() {
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get(PROPERTY_DEBUG_LAYERS_UPDATES, property, NULL) > 0) {
+        INIT_LOGD("  Layers updates debug enabled: %s", property);
+        debugLayersUpdates = !strcmp(property, "true");
+    } else {
+        debugLayersUpdates = false;
+    }
+
+    if (property_get(PROPERTY_DEBUG_OVERDRAW, property, NULL) > 0) {
+        INIT_LOGD("  Overdraw debug enabled: %s", property);
+        debugOverdraw = !strcmp(property, "true");
+    } else {
+        debugOverdraw = false;
+    }
+}
+
 void Caches::terminate() {
     if (!mInitialized) return;
 
@@ -169,8 +193,8 @@
             arcShapeCache.getSize(), arcShapeCache.getMaxSize());
     log.appendFormat("  TextDropShadowCache  %8d / %8d\n", dropShadowCache.getSize(),
             dropShadowCache.getMaxSize());
-    for (uint32_t i = 0; i < fontRenderer.getFontRendererCount(); i++) {
-        const uint32_t size = fontRenderer.getFontRendererSize(i);
+    for (uint32_t i = 0; i < fontRenderer->getFontRendererCount(); i++) {
+        const uint32_t size = fontRenderer->getFontRendererSize(i);
         log.appendFormat("  FontRenderer %d       %8d / %8d\n", i, size, size);
     }
     log.appendFormat("Other:\n");
@@ -190,8 +214,8 @@
     total += ovalShapeCache.getSize();
     total += rectShapeCache.getSize();
     total += arcShapeCache.getSize();
-    for (uint32_t i = 0; i < fontRenderer.getFontRendererCount(); i++) {
-        total += fontRenderer.getFontRendererSize(i);
+    for (uint32_t i = 0; i < fontRenderer->getFontRendererCount(); i++) {
+        total += fontRenderer->getFontRendererSize(i);
     }
 
     log.appendFormat("Total memory usage:\n");
@@ -206,21 +230,29 @@
     textureCache.clearGarbage();
     pathCache.clearGarbage();
 
-    Mutex::Autolock _l(mGarbageLock);
+    Vector<DisplayList*> displayLists;
+    Vector<Layer*> layers;
 
-    size_t count = mLayerGarbage.size();
-    for (size_t i = 0; i < count; i++) {
-        Layer* layer = mLayerGarbage.itemAt(i);
-        LayerRenderer::destroyLayer(layer);
+    { // scope for the lock
+        Mutex::Autolock _l(mGarbageLock);
+        displayLists = mDisplayListGarbage;
+        layers = mLayerGarbage;
+        mDisplayListGarbage.clear();
+        mLayerGarbage.clear();
     }
-    mLayerGarbage.clear();
 
-    count = mDisplayListGarbage.size();
+    size_t count = displayLists.size();
     for (size_t i = 0; i < count; i++) {
-        DisplayList* displayList = mDisplayListGarbage.itemAt(i);
+        DisplayList* displayList = displayLists.itemAt(i);
         delete displayList;
     }
-    mDisplayListGarbage.clear();
+
+    count = layers.size();
+    for (size_t i = 0; i < count; i++) {
+        Layer* layer = layers.itemAt(i);
+        delete layer;
+    }
+    layers.clear();
 }
 
 void Caches::deleteLayerDeferred(Layer* layer) {
@@ -236,18 +268,17 @@
 void Caches::flush(FlushMode mode) {
     FLUSH_LOGD("Flushing caches (mode %d)", mode);
 
-    clearGarbage();
-
     switch (mode) {
         case kFlushMode_Full:
             textureCache.clear();
             patchCache.clear();
             dropShadowCache.clear();
             gradientCache.clear();
-            fontRenderer.clear();
+            fontRenderer->clear();
+            dither.clear();
             // fall through
         case kFlushMode_Moderate:
-            fontRenderer.flush();
+            fontRenderer->flush();
             textureCache.flush();
             pathCache.clear();
             roundRectShapeCache.clear();
@@ -260,6 +291,8 @@
             layerCache.clear();
             break;
     }
+
+    clearGarbage();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -306,15 +339,22 @@
     return false;
 }
 
-void Caches::bindPositionVertexPointer(bool force, GLuint slot, GLvoid* vertices, GLsizei stride) {
-    if (force || vertices != mCurrentPositionPointer) {
+///////////////////////////////////////////////////////////////////////////////
+// Meshes and textures
+///////////////////////////////////////////////////////////////////////////////
+
+void Caches::bindPositionVertexPointer(bool force, GLvoid* vertices, GLsizei stride) {
+    if (force || vertices != mCurrentPositionPointer || stride != mCurrentPositionStride) {
+        GLuint slot = currentProgram->position;
         glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
         mCurrentPositionPointer = vertices;
+        mCurrentPositionStride = stride;
     }
 }
 
-void Caches::bindTexCoordsVertexPointer(bool force, GLuint slot, GLvoid* vertices) {
+void Caches::bindTexCoordsVertexPointer(bool force, GLvoid* vertices) {
     if (force || vertices != mCurrentTexCoordsPointer) {
+        GLuint slot = currentProgram->texCoords;
         glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, gMeshStride, vertices);
         mCurrentTexCoordsPointer = vertices;
     }
@@ -351,14 +391,64 @@
     }
 }
 
-void Caches::setScissor(GLint x, GLint y, GLint width, GLint height) {
-    if (x != mScissorX || y != mScissorY || width != mScissorWidth || height != mScissorHeight) {
+///////////////////////////////////////////////////////////////////////////////
+// Scissor
+///////////////////////////////////////////////////////////////////////////////
+
+bool Caches::setScissor(GLint x, GLint y, GLint width, GLint height) {
+    if (scissorEnabled && (x != mScissorX || y != mScissorY ||
+            width != mScissorWidth || height != mScissorHeight)) {
+
+        if (x < 0) {
+            width += x;
+            x = 0;
+        }
+        if (y < 0) {
+            height += y;
+            y = 0;
+        }
+        if (width < 0) {
+            width = 0;
+        }
+        if (height < 0) {
+            height = 0;
+        }
         glScissor(x, y, width, height);
 
         mScissorX = x;
         mScissorY = y;
         mScissorWidth = width;
         mScissorHeight = height;
+
+        return true;
+    }
+    return false;
+}
+
+bool Caches::enableScissor() {
+    if (!scissorEnabled) {
+        glEnable(GL_SCISSOR_TEST);
+        scissorEnabled = true;
+        resetScissor();
+        return true;
+    }
+    return false;
+}
+
+bool Caches::disableScissor() {
+    if (scissorEnabled) {
+        glDisable(GL_SCISSOR_TEST);
+        scissorEnabled = false;
+        return true;
+    }
+    return false;
+}
+
+void Caches::setScissorEnabled(bool enabled) {
+    if (scissorEnabled != enabled) {
+        if (enabled) glEnable(GL_SCISSOR_TEST);
+        else glDisable(GL_SCISSOR_TEST);
+        scissorEnabled = enabled;
     }
 }
 
@@ -366,6 +456,42 @@
     mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
 }
 
+///////////////////////////////////////////////////////////////////////////////
+// Tiling
+///////////////////////////////////////////////////////////////////////////////
+
+void Caches::startTiling(GLuint x, GLuint y, GLuint width, GLuint height, bool opaque) {
+    if (extensions.hasTiledRendering() && !debugOverdraw) {
+        glStartTilingQCOM(x, y, width, height, (opaque ? GL_NONE : GL_COLOR_BUFFER_BIT0_QCOM));
+    }
+}
+
+void Caches::endTiling() {
+    if (extensions.hasTiledRendering() && !debugOverdraw) {
+        glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM);
+    }
+}
+
+bool Caches::hasRegisteredFunctors() {
+    return mFunctorsCount > 0;
+}
+
+void Caches::registerFunctors(uint32_t functorCount) {
+    mFunctorsCount += functorCount;
+}
+
+void Caches::unregisterFunctors(uint32_t functorCount) {
+    if (functorCount > mFunctorsCount) {
+        mFunctorsCount = 0;
+    } else {
+        mFunctorsCount -= functorCount;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Regions
+///////////////////////////////////////////////////////////////////////////////
+
 TextureVertex* Caches::getRegionMesh() {
     // Create the mesh, 2 triangles and 4 vertices per rectangle in the region
     if (!mRegionMesh) {
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 58361c9..ad1ff6f 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -38,6 +38,8 @@
 #include "TextDropShadowCache.h"
 #include "FboCache.h"
 #include "ResourceCache.h"
+#include "Stencil.h"
+#include "Dither.h"
 
 namespace android {
 namespace uirenderer {
@@ -66,6 +68,7 @@
 static const GLsizei gAlphaVertexStride = sizeof(AlphaVertex);
 static const GLsizei gAAVertexStride = sizeof(AAVertex);
 static const GLsizei gMeshTextureOffset = 2 * sizeof(float);
+static const GLsizei gVertexAlphaOffset = 2 * sizeof(float);
 static const GLsizei gVertexAAWidthOffset = 2 * sizeof(float);
 static const GLsizei gVertexAALengthOffset = 3 * sizeof(float);
 static const GLsizei gMeshCount = 4;
@@ -170,14 +173,13 @@
      * Binds an attrib to the specified float vertex pointer.
      * Assumes a stride of gMeshStride and a size of 2.
      */
-    void bindPositionVertexPointer(bool force, GLuint slot, GLvoid* vertices,
-            GLsizei stride = gMeshStride);
+    void bindPositionVertexPointer(bool force, GLvoid* vertices, GLsizei stride = gMeshStride);
 
     /**
      * Binds an attrib to the specified float vertex pointer.
      * Assumes a stride of gMeshStride and a size of 2.
      */
-    void bindTexCoordsVertexPointer(bool force, GLuint slot, GLvoid* vertices);
+    void bindTexCoordsVertexPointer(bool force, GLvoid* vertices);
 
     /**
      * Resets the vertex pointers.
@@ -197,13 +199,20 @@
     /**
      * Sets the scissor for the current surface.
      */
-    void setScissor(GLint x, GLint y, GLint width, GLint height);
+    bool setScissor(GLint x, GLint y, GLint width, GLint height);
 
     /**
      * Resets the scissor state.
      */
     void resetScissor();
 
+    bool enableScissor();
+    bool disableScissor();
+    void setScissorEnabled(bool enabled);
+
+    void startTiling(GLuint x, GLuint y, GLuint width, GLuint height, bool opaque);
+    void endTiling();
+
     /**
      * Returns the mesh used to draw regions. Calling this method will
      * bind a VBO of type GL_ELEMENT_ARRAY_BUFFER that contains the
@@ -217,10 +226,15 @@
     void dumpMemoryUsage();
     void dumpMemoryUsage(String8& log);
 
+    bool hasRegisteredFunctors();
+    void registerFunctors(uint32_t functorCount);
+    void unregisterFunctors(uint32_t functorCount);
+
     bool blend;
     GLenum lastSrcMode;
     GLenum lastDstMode;
     Program* currentProgram;
+    bool scissorEnabled;
 
     // VBO to draw with
     GLuint meshBuffer;
@@ -230,6 +244,8 @@
 
     // Misc
     GLint maxTextureSize;
+    bool debugLayersUpdates;
+    bool debugOverdraw;
 
     TextureCache textureCache;
     LayerCache layerCache;
@@ -244,9 +260,15 @@
     PatchCache patchCache;
     TextDropShadowCache dropShadowCache;
     FboCache fboCache;
-    GammaFontRenderer fontRenderer;
     ResourceCache resourceCache;
 
+    GammaFontRenderer* fontRenderer;
+
+    Dither dither;
+#if STENCIL_BUFFER_SIZE
+    Stencil stencil;
+#endif
+
     // Debug methods
     PFNGLINSERTEVENTMARKEREXTPROC eventMark;
     PFNGLPUSHGROUPMARKEREXTPROC startMark;
@@ -256,8 +278,10 @@
     PFNGLGETOBJECTLABELEXTPROC getLabel;
 
 private:
+    void initFont();
     void initExtensions();
     void initConstraints();
+    void initProperties();
 
     static void eventMarkNull(GLsizei length, const GLchar* marker) { }
     static void startMarkNull(GLsizei length, const GLchar* marker) { }
@@ -274,6 +298,7 @@
     GLuint mCurrentBuffer;
     GLuint mCurrentIndicesBuffer;
     void* mCurrentPositionPointer;
+    GLsizei mCurrentPositionStride;
     void* mCurrentTexCoordsPointer;
 
     bool mTexCoordsArrayEnabled;
@@ -295,6 +320,8 @@
 
     DebugLevel mDebugLevel;
     bool mInitialized;
+
+    uint32_t mFunctorsCount;
 }; // class Caches
 
 }; // namespace uirenderer
diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h
index 55a860e..6795ac3 100644
--- a/libs/hwui/Debug.h
+++ b/libs/hwui/Debug.h
@@ -68,6 +68,9 @@
 // Turn on to dump display list state
 #define DEBUG_DISPLAY_LIST 0
 
+// Turn on to insert an event marker for each display list op
+#define DEBUG_DISPLAY_LIST_OPS_AS_EVENTS 0
+
 #if DEBUG_INIT
     #define INIT_LOGD(...) ALOGD(__VA_ARGS__)
 #else
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 0c89014..7a38b40 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -61,9 +61,9 @@
     "DrawPath",
     "DrawLines",
     "DrawPoints",
-    "DrawText",
     "DrawTextOnPath",
     "DrawPosText",
+    "DrawText",
     "ResetShader",
     "SetupShader",
     "ResetColorFilter",
@@ -105,7 +105,179 @@
     clearResources();
 }
 
-void DisplayList::initProperties() {
+void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
+    if (displayList) {
+        DISPLAY_LIST_LOGD("Deferring display list destruction");
+        Caches::getInstance().deleteDisplayListDeferred(displayList);
+    }
+}
+
+void DisplayList::clearResources() {
+    sk_free((void*) mReader.base());
+    mReader.setMemory(NULL, 0);
+
+    delete mTransformMatrix;
+    delete mTransformCamera;
+    delete mTransformMatrix3D;
+    delete mStaticMatrix;
+    delete mAnimationMatrix;
+
+    mTransformMatrix = NULL;
+    mTransformCamera = NULL;
+    mTransformMatrix3D = NULL;
+    mStaticMatrix = NULL;
+    mAnimationMatrix = NULL;
+
+    Caches& caches = Caches::getInstance();
+    caches.unregisterFunctors(mFunctorCount);
+    caches.resourceCache.lock();
+
+    for (size_t i = 0; i < mBitmapResources.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i));
+    }
+
+    for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
+        SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i);
+        caches.resourceCache.decrementRefcountLocked(bitmap);
+        caches.resourceCache.destructorLocked(bitmap);
+    }
+
+    for (size_t i = 0; i < mFilterResources.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i));
+    }
+
+    for (size_t i = 0; i < mShaders.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
+        caches.resourceCache.destructorLocked(mShaders.itemAt(i));
+    }
+
+    for (size_t i = 0; i < mSourcePaths.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i));
+    }
+
+    for (size_t i = 0; i < mLayers.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i));
+    }
+
+    caches.resourceCache.unlock();
+
+    for (size_t i = 0; i < mPaints.size(); i++) {
+        delete mPaints.itemAt(i);
+    }
+
+    for (size_t i = 0; i < mPaths.size(); i++) {
+        SkPath* path = mPaths.itemAt(i);
+        caches.pathCache.remove(path);
+        delete path;
+    }
+
+    for (size_t i = 0; i < mMatrices.size(); i++) {
+        delete mMatrices.itemAt(i);
+    }
+
+    mBitmapResources.clear();
+    mOwnedBitmapResources.clear();
+    mFilterResources.clear();
+    mShaders.clear();
+    mSourcePaths.clear();
+    mPaints.clear();
+    mPaths.clear();
+    mMatrices.clear();
+    mLayers.clear();
+}
+
+void DisplayList::reset() {
+    clearResources();
+    init();
+}
+
+void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) {
+
+    if (reusing) {
+        // re-using display list - clear out previous allocations
+        clearResources();
+    }
+
+    init();
+
+    const SkWriter32& writer = recorder.writeStream();
+    if (writer.size() == 0) {
+        return;
+    }
+
+    mSize = writer.size();
+    void* buffer = sk_malloc_throw(mSize);
+    writer.flatten(buffer);
+    mReader.setMemory(buffer, mSize);
+
+    mFunctorCount = recorder.getFunctorCount();
+
+    Caches& caches = Caches::getInstance();
+    caches.registerFunctors(mFunctorCount);
+    caches.resourceCache.lock();
+
+    const Vector<SkBitmap*>& bitmapResources = recorder.getBitmapResources();
+    for (size_t i = 0; i < bitmapResources.size(); i++) {
+        SkBitmap* resource = bitmapResources.itemAt(i);
+        mBitmapResources.add(resource);
+        caches.resourceCache.incrementRefcountLocked(resource);
+    }
+
+    const Vector<SkBitmap*> &ownedBitmapResources = recorder.getOwnedBitmapResources();
+    for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
+        SkBitmap* resource = ownedBitmapResources.itemAt(i);
+        mOwnedBitmapResources.add(resource);
+        caches.resourceCache.incrementRefcountLocked(resource);
+    }
+
+    const Vector<SkiaColorFilter*>& filterResources = recorder.getFilterResources();
+    for (size_t i = 0; i < filterResources.size(); i++) {
+        SkiaColorFilter* resource = filterResources.itemAt(i);
+        mFilterResources.add(resource);
+        caches.resourceCache.incrementRefcountLocked(resource);
+    }
+
+    const Vector<SkiaShader*>& shaders = recorder.getShaders();
+    for (size_t i = 0; i < shaders.size(); i++) {
+        SkiaShader* resource = shaders.itemAt(i);
+        mShaders.add(resource);
+        caches.resourceCache.incrementRefcountLocked(resource);
+    }
+
+    const SortedVector<SkPath*>& sourcePaths = recorder.getSourcePaths();
+    for (size_t i = 0; i < sourcePaths.size(); i++) {
+        mSourcePaths.add(sourcePaths.itemAt(i));
+        caches.resourceCache.incrementRefcountLocked(sourcePaths.itemAt(i));
+    }
+
+    const Vector<Layer*>& layers = recorder.getLayers();
+    for (size_t i = 0; i < layers.size(); i++) {
+        mLayers.add(layers.itemAt(i));
+        caches.resourceCache.incrementRefcountLocked(layers.itemAt(i));
+    }
+
+    caches.resourceCache.unlock();
+
+    const Vector<SkPaint*>& paints = recorder.getPaints();
+    for (size_t i = 0; i < paints.size(); i++) {
+        mPaints.add(paints.itemAt(i));
+    }
+
+    const Vector<SkPath*>& paths = recorder.getPaths();
+    for (size_t i = 0; i < paths.size(); i++) {
+        mPaths.add(paths.itemAt(i));
+    }
+
+    const Vector<SkMatrix*>& matrices = recorder.getMatrices();
+    for (size_t i = 0; i < matrices.size(); i++) {
+        mMatrices.add(matrices.itemAt(i));
+    }
+}
+
+void DisplayList::init() {
+    mSize = 0;
+    mIsRenderable = true;
+    mFunctorCount = 0;
     mLeft = 0;
     mTop = 0;
     mRight = 0;
@@ -134,151 +306,6 @@
     mCaching = false;
 }
 
-void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
-    if (displayList) {
-        DISPLAY_LIST_LOGD("Deferring display list destruction");
-        Caches::getInstance().deleteDisplayListDeferred(displayList);
-    }
-}
-
-void DisplayList::clearResources() {
-    sk_free((void*) mReader.base());
-
-    delete mTransformMatrix;
-    delete mTransformCamera;
-    delete mTransformMatrix3D;
-    delete mStaticMatrix;
-    delete mAnimationMatrix;
-    mTransformMatrix = NULL;
-    mTransformCamera = NULL;
-    mTransformMatrix3D = NULL;
-    mStaticMatrix = NULL;
-    mAnimationMatrix = NULL;
-
-    Caches& caches = Caches::getInstance();
-
-    for (size_t i = 0; i < mBitmapResources.size(); i++) {
-        caches.resourceCache.decrementRefcount(mBitmapResources.itemAt(i));
-    }
-    mBitmapResources.clear();
-
-    for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
-        SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i);
-        caches.resourceCache.decrementRefcount(bitmap);
-        caches.resourceCache.destructor(bitmap);
-    }
-    mOwnedBitmapResources.clear();
-
-    for (size_t i = 0; i < mFilterResources.size(); i++) {
-        caches.resourceCache.decrementRefcount(mFilterResources.itemAt(i));
-    }
-    mFilterResources.clear();
-
-    for (size_t i = 0; i < mShaders.size(); i++) {
-        caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
-        caches.resourceCache.destructor(mShaders.itemAt(i));
-    }
-    mShaders.clear();
-
-    for (size_t i = 0; i < mPaints.size(); i++) {
-        delete mPaints.itemAt(i);
-    }
-    mPaints.clear();
-
-    for (size_t i = 0; i < mPaths.size(); i++) {
-        SkPath* path = mPaths.itemAt(i);
-        caches.pathCache.remove(path);
-        delete path;
-    }
-    mPaths.clear();
-
-    for (size_t i = 0; i < mSourcePaths.size(); i++) {
-        caches.resourceCache.decrementRefcount(mSourcePaths.itemAt(i));
-    }
-    mSourcePaths.clear();
-
-    for (size_t i = 0; i < mMatrices.size(); i++) {
-        delete mMatrices.itemAt(i);
-    }
-    mMatrices.clear();
-}
-
-void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) {
-    const SkWriter32& writer = recorder.writeStream();
-    init();
-
-    if (writer.size() == 0) {
-        return;
-    }
-
-    if (reusing) {
-        // re-using display list - clear out previous allocations
-        clearResources();
-    }
-    initProperties();
-
-    mSize = writer.size();
-    void* buffer = sk_malloc_throw(mSize);
-    writer.flatten(buffer);
-    mReader.setMemory(buffer, mSize);
-
-    Caches& caches = Caches::getInstance();
-
-    const Vector<SkBitmap*>& bitmapResources = recorder.getBitmapResources();
-    for (size_t i = 0; i < bitmapResources.size(); i++) {
-        SkBitmap* resource = bitmapResources.itemAt(i);
-        mBitmapResources.add(resource);
-        caches.resourceCache.incrementRefcount(resource);
-    }
-
-    const Vector<SkBitmap*> &ownedBitmapResources = recorder.getOwnedBitmapResources();
-    for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
-        SkBitmap* resource = ownedBitmapResources.itemAt(i);
-        mOwnedBitmapResources.add(resource);
-        caches.resourceCache.incrementRefcount(resource);
-    }
-
-    const Vector<SkiaColorFilter*>& filterResources = recorder.getFilterResources();
-    for (size_t i = 0; i < filterResources.size(); i++) {
-        SkiaColorFilter* resource = filterResources.itemAt(i);
-        mFilterResources.add(resource);
-        caches.resourceCache.incrementRefcount(resource);
-    }
-
-    const Vector<SkiaShader*>& shaders = recorder.getShaders();
-    for (size_t i = 0; i < shaders.size(); i++) {
-        SkiaShader* resource = shaders.itemAt(i);
-        mShaders.add(resource);
-        caches.resourceCache.incrementRefcount(resource);
-    }
-
-    const Vector<SkPaint*>& paints = recorder.getPaints();
-    for (size_t i = 0; i < paints.size(); i++) {
-        mPaints.add(paints.itemAt(i));
-    }
-
-    const Vector<SkPath*>& paths = recorder.getPaths();
-    for (size_t i = 0; i < paths.size(); i++) {
-        mPaths.add(paths.itemAt(i));
-    }
-
-    const SortedVector<SkPath*>& sourcePaths = recorder.getSourcePaths();
-    for (size_t i = 0; i < sourcePaths.size(); i++) {
-        mSourcePaths.add(sourcePaths.itemAt(i));
-        caches.resourceCache.incrementRefcount(sourcePaths.itemAt(i));
-    }
-
-    const Vector<SkMatrix*>& matrices = recorder.getMatrices();
-    for (size_t i = 0; i < matrices.size(); i++) {
-        mMatrices.add(matrices.itemAt(i));
-    }
-}
-
-void DisplayList::init() {
-    mSize = 0;
-    mIsRenderable = true;
-}
-
 size_t DisplayList::getSize() {
     return mSize;
 }
@@ -486,7 +513,8 @@
                 float top = getFloat();
                 float right = getFloat();
                 float bottom = getFloat();
-                SkPaint* paint = getPaint(renderer);
+                int alpha = getInt();
+                SkXfermode::Mode mode = (SkXfermode::Mode) getInt();
                 ALOGD("%s%s %.2f, %.2f, %.2f, %.2f", (char*) indent, OP_NAMES[op],
                         left, top, right, bottom);
             }
@@ -571,17 +599,6 @@
                 ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
             }
             break;
-            case DrawText: {
-                getText(&text);
-                int32_t count = getInt();
-                float x = getFloat();
-                float y = getFloat();
-                SkPaint* paint = getPaint(renderer);
-                float length = getFloat();
-                ALOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent, OP_NAMES[op],
-                        text.text(), text.length(), count, x, y, paint, length);
-            }
-            break;
             case DrawTextOnPath: {
                 getText(&text);
                 int32_t count = getInt();
@@ -602,6 +619,20 @@
                 ALOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
                         text.text(), text.length(), count, paint);
             }
+            break;
+            case DrawText: {
+                getText(&text);
+                int32_t count = getInt();
+                float x = getFloat();
+                float y = getFloat();
+                int32_t positionsCount = 0;
+                float* positions = getFloats(positionsCount);
+                SkPaint* paint = getPaint(renderer);
+                float length = getFloat();
+                ALOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
+                        text.text(), text.length(), count, paint);
+            }
+            break;
             case ResetShader: {
                 ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
             }
@@ -732,16 +763,17 @@
         }
     }
     if (mAlpha < 1 && !mCaching) {
-        // TODO: should be able to store the size of a DL at record time and not
-        // have to pass it into this call. In fact, this information might be in the
-        // location/size info that we store with the new native transform data.
-        int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
-        if (mClipChildren) {
-            flags |= SkCanvas::kClipToLayer_SaveFlag;
+        if (!mHasOverlappingRendering) {
+            ALOGD("%s%s %.2f", indent, "SetAlpha", mAlpha);
+        } else {
+            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
+            if (mClipChildren) {
+                flags |= SkCanvas::kClipToLayer_SaveFlag;
+            }
+            ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha",
+                    (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
+                    mMultipliedAlpha, flags);
         }
-        ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha",
-                (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
-                mMultipliedAlpha, flags);
     }
     if (mClipChildren) {
         ALOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f,
@@ -851,11 +883,13 @@
 #endif
 
     renderer.startMark(mName.string());
+
     int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
     DISPLAY_LIST_LOGD("%s%s %d %d", indent, "Save",
             SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);
     setViewProperties(renderer, level);
-    if (renderer.quickReject(0, 0, mWidth, mHeight)) {
+
+    if (renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) {
         DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, "RestoreToCount", restoreTo);
         renderer.restoreToCount(restoreTo);
         renderer.endMark();
@@ -864,6 +898,7 @@
 
     DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
     int saveCount = renderer.getSaveCount() - 1;
+
     while (!mReader.eof()) {
         int op = mReader.readInt();
         if (op & OP_MAY_BE_SKIPPED_MASK) {
@@ -879,6 +914,10 @@
         }
         logBuffer.writeCommand(level, op);
 
+#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
+        Caches::getInstance().eventMark(strlen(OP_NAMES[op]), OP_NAMES[op]);
+#endif
+
         switch (op) {
             case DrawGLFunction: {
                 Functor *functor = (Functor *) getInt();
@@ -993,29 +1032,39 @@
             }
             break;
             case DrawLayer: {
+                int oldAlpha = -1;
                 Layer* layer = (Layer*) getInt();
                 float x = getFloat();
                 float y = getFloat();
                 SkPaint* paint = getPaint(renderer);
-                if (mCaching) {
-                    paint->setAlpha(mMultipliedAlpha);
+                if (mCaching && mMultipliedAlpha < 255) {
+                    oldAlpha = layer->getAlpha();
+                    layer->setAlpha(mMultipliedAlpha);
                 }
                 DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
                         layer, x, y, paint);
                 drawGlStatus |= renderer.drawLayer(layer, x, y, paint);
+                if (oldAlpha >= 0) {
+                    layer->setAlpha(oldAlpha);
+                }
             }
             break;
             case DrawBitmap: {
+                int oldAlpha = -1;
                 SkBitmap* bitmap = getBitmap();
                 float x = getFloat();
                 float y = getFloat();
                 SkPaint* paint = getPaint(renderer);
-                if (mCaching) {
+                if (mCaching && mMultipliedAlpha < 255) {
+                    oldAlpha = paint->getAlpha();
                     paint->setAlpha(mMultipliedAlpha);
                 }
                 DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
                         bitmap, x, y, paint);
                 drawGlStatus |= renderer.drawBitmap(bitmap, x, y, paint);
+                if (oldAlpha >= 0) {
+                    paint->setAlpha(oldAlpha);
+                }
             }
             break;
             case DrawBitmapMatrix: {
@@ -1089,11 +1138,14 @@
                 float top = getFloat();
                 float right = getFloat();
                 float bottom = getFloat();
-                SkPaint* paint = getPaint(renderer);
+
+                int alpha = getInt();
+                SkXfermode::Mode mode = (SkXfermode::Mode) getInt();
 
                 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
                 drawGlStatus |= renderer.drawPatch(bitmap, xDivs, yDivs, colors,
-                        xDivsCount, yDivsCount, numColors, left, top, right, bottom, paint);
+                        xDivsCount, yDivsCount, numColors, left, top, right, bottom,
+                        alpha, mode);
             }
             break;
             case DrawColor: {
@@ -1185,19 +1237,6 @@
                 drawGlStatus |= renderer.drawPoints(points, count, paint);
             }
             break;
-            case DrawText: {
-                getText(&text);
-                int32_t count = getInt();
-                float x = getFloat();
-                float y = getFloat();
-                SkPaint* paint = getPaint(renderer);
-                float length = getFloat();
-                DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent,
-                        OP_NAMES[op], text.text(), text.length(), count, x, y, paint, length);
-                drawGlStatus |= renderer.drawText(text.text(), text.length(), count, x, y,
-                        paint, length);
-            }
-            break;
             case DrawTextOnPath: {
                 getText(&text);
                 int32_t count = getInt();
@@ -1223,6 +1262,21 @@
                         positions, paint);
             }
             break;
+            case DrawText: {
+                getText(&text);
+                int32_t count = getInt();
+                float x = getFloat();
+                float y = getFloat();
+                int32_t positionsCount = 0;
+                float* positions = getFloats(positionsCount);
+                SkPaint* paint = getPaint(renderer);
+                float length = getFloat();
+                DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent,
+                        OP_NAMES[op], text.text(), text.length(), count, x, y, paint, length);
+                drawGlStatus |= renderer.drawText(text.text(), text.length(), count,
+                        x, y, positions, paint, length);
+            }
+            break;
             case ResetShader: {
                 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
                 renderer.resetShader();
@@ -1293,8 +1347,10 @@
 // Base structure
 ///////////////////////////////////////////////////////////////////////////////
 
-DisplayListRenderer::DisplayListRenderer() : mWriter(MIN_WRITER_SIZE),
-        mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false), mHasDrawOps(false) {
+DisplayListRenderer::DisplayListRenderer():
+        mCaches(Caches::getInstance()), mWriter(MIN_WRITER_SIZE),
+        mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false),
+        mHasDrawOps(false), mFunctorCount(0) {
 }
 
 DisplayListRenderer::~DisplayListRenderer() {
@@ -1304,34 +1360,42 @@
 void DisplayListRenderer::reset() {
     mWriter.reset();
 
-    Caches& caches = Caches::getInstance();
+    mCaches.resourceCache.lock();
+
     for (size_t i = 0; i < mBitmapResources.size(); i++) {
-        caches.resourceCache.decrementRefcount(mBitmapResources.itemAt(i));
+        mCaches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i));
     }
-    mBitmapResources.clear();
 
     for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
-        SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i);
-        caches.resourceCache.decrementRefcount(bitmap);
+        mCaches.resourceCache.decrementRefcountLocked(mOwnedBitmapResources.itemAt(i));
     }
-    mOwnedBitmapResources.clear();
 
     for (size_t i = 0; i < mFilterResources.size(); i++) {
-        caches.resourceCache.decrementRefcount(mFilterResources.itemAt(i));
+        mCaches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i));
     }
-    mFilterResources.clear();
 
     for (size_t i = 0; i < mShaders.size(); i++) {
-        caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
+        mCaches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
     }
-    mShaders.clear();
-    mShaderMap.clear();
 
     for (size_t i = 0; i < mSourcePaths.size(); i++) {
-        caches.resourceCache.decrementRefcount(mSourcePaths.itemAt(i));
+        mCaches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i));
     }
+
+    for (size_t i = 0; i < mLayers.size(); i++) {
+        mCaches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i));
+    }
+
+    mCaches.resourceCache.unlock();
+
+    mBitmapResources.clear();
+    mOwnedBitmapResources.clear();
+    mFilterResources.clear();
     mSourcePaths.clear();
 
+    mShaders.clear();
+    mShaderMap.clear();
+
     mPaints.clear();
     mPaintMap.clear();
 
@@ -1340,7 +1404,10 @@
 
     mMatrices.clear();
 
+    mLayers.clear();
+
     mHasDrawOps = false;
+    mFunctorCount = 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1368,13 +1435,17 @@
     mHeight = height;
 }
 
-int DisplayListRenderer::prepareDirty(float left, float top,
+status_t DisplayListRenderer::prepareDirty(float left, float top,
         float right, float bottom, bool opaque) {
     mSnapshot = new Snapshot(mFirstSnapshot,
             SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
     mSaveCount = 1;
+
     mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight);
+    mDirtyClip = opaque;
+
     mRestoreSaveCount = -1;
+
     return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
 }
 
@@ -1393,6 +1464,7 @@
     // Ignore dirty during recording, it matters only when we replay
     addOp(DisplayList::DrawGLFunction);
     addInt((int) functor);
+    mFunctorCount++;
     return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
 }
 
@@ -1496,14 +1568,15 @@
 
 status_t DisplayListRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
     addOp(DisplayList::DrawLayer);
-    addInt((int) layer);
+    addLayer(layer);
     addPoint(x, y);
     addPaint(paint);
     return DrawGlInfo::kStatusDone;
 }
 
 status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
-    const bool reject = quickReject(left, top, left + bitmap->width(), top + bitmap->height());
+    const bool reject = quickRejectNoScissor(left, top,
+            left + bitmap->width(), top + bitmap->height());
     uint32_t* location = addOp(DisplayList::DrawBitmap, reject);
     addBitmap(bitmap);
     addPoint(left, top);
@@ -1517,7 +1590,7 @@
     const mat4 transform(*matrix);
     transform.mapRect(r);
 
-    const bool reject = quickReject(r.left, r.top, r.right, r.bottom);
+    const bool reject = quickRejectNoScissor(r.left, r.top, r.right, r.bottom);
     uint32_t* location = addOp(DisplayList::DrawBitmapMatrix, reject);
     addBitmap(bitmap);
     addMatrix(matrix);
@@ -1529,7 +1602,7 @@
 status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
         float srcRight, float srcBottom, float dstLeft, float dstTop,
         float dstRight, float dstBottom, SkPaint* paint) {
-    const bool reject = quickReject(dstLeft, dstTop, dstRight, dstBottom);
+    const bool reject = quickRejectNoScissor(dstLeft, dstTop, dstRight, dstBottom);
     uint32_t* location = addOp(DisplayList::DrawBitmapRect, reject);
     addBitmap(bitmap);
     addBounds(srcLeft, srcTop, srcRight, srcBottom);
@@ -1541,7 +1614,8 @@
 
 status_t DisplayListRenderer::drawBitmapData(SkBitmap* bitmap, float left, float top,
         SkPaint* paint) {
-    const bool reject = quickReject(left, top, left + bitmap->width(), top + bitmap->height());
+    const bool reject = quickRejectNoScissor(left, top,
+            left + bitmap->width(), top + bitmap->height());
     uint32_t* location = addOp(DisplayList::DrawBitmapData, reject);
     addBitmapData(bitmap);
     addPoint(left, top);
@@ -1570,14 +1644,19 @@
 status_t DisplayListRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs,
         const int32_t* yDivs, const uint32_t* colors, uint32_t width, uint32_t height,
         int8_t numColors, float left, float top, float right, float bottom, SkPaint* paint) {
-    const bool reject = quickReject(left, top, right, bottom);
+    int alpha;
+    SkXfermode::Mode mode;
+    OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
+
+    const bool reject = quickRejectNoScissor(left, top, right, bottom);
     uint32_t* location = addOp(DisplayList::DrawPatch, reject);
     addBitmap(bitmap);
     addInts(xDivs, width);
     addInts(yDivs, height);
     addUInts(colors, numColors);
     addBounds(left, top, right, bottom);
-    addPaint(paint);
+    addInt(alpha);
+    addInt(mode);
     addSkip(location);
     return DrawGlInfo::kStatusDone;
 }
@@ -1592,7 +1671,7 @@
 status_t DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
         SkPaint* paint) {
     const bool reject = paint->getStyle() == SkPaint::kFill_Style &&
-            quickReject(left, top, right, bottom);
+            quickRejectNoScissor(left, top, right, bottom);
     uint32_t* location = addOp(DisplayList::DrawRect, reject);
     addBounds(left, top, right, bottom);
     addPaint(paint);
@@ -1603,7 +1682,7 @@
 status_t DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
         float rx, float ry, SkPaint* paint) {
     const bool reject = paint->getStyle() == SkPaint::kFill_Style &&
-            quickReject(left, top, right, bottom);
+            quickRejectNoScissor(left, top, right, bottom);
     uint32_t* location = addOp(DisplayList::DrawRoundRect, reject);
     addBounds(left, top, right, bottom);
     addPoint(rx, ry);
@@ -1646,7 +1725,7 @@
     left -= offset;
     top -= offset;
 
-    const bool reject = quickReject(left, top, left + width, top + height);
+    const bool reject = quickRejectNoScissor(left, top, left + width, top + height);
     uint32_t* location = addOp(DisplayList::DrawPath, reject);
     addPath(path);
     addPaint(paint);
@@ -1668,8 +1747,38 @@
     return DrawGlInfo::kStatusDone;
 }
 
+status_t DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
+        SkPath* path, float hOffset, float vOffset, SkPaint* paint) {
+    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
+    addOp(DisplayList::DrawTextOnPath);
+    addText(text, bytesCount);
+    addInt(count);
+    addPath(path);
+    addFloat(hOffset);
+    addFloat(vOffset);
+    paint->setAntiAlias(true);
+    SkPaint* addedPaint = addPaint(paint);
+    FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(addedPaint);
+    fontRenderer.precache(addedPaint, text, count);
+    return DrawGlInfo::kStatusDone;
+}
+
+status_t DisplayListRenderer::drawPosText(const char* text, int bytesCount, int count,
+        const float* positions, SkPaint* paint) {
+    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
+    addOp(DisplayList::DrawPosText);
+    addText(text, bytesCount);
+    addInt(count);
+    addFloats(positions, count * 2);
+    paint->setAntiAlias(true);
+    SkPaint* addedPaint = addPaint(paint);
+    FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(addedPaint);
+    fontRenderer.precache(addedPaint, text, count);
+    return DrawGlInfo::kStatusDone;
+}
+
 status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
-        float x, float y, SkPaint* paint, float length) {
+        float x, float y, const float* positions, SkPaint* paint, float length) {
     if (!text || count <= 0) return DrawGlInfo::kStatusDone;
 
     // TODO: We should probably make a copy of the paint instead of modifying
@@ -1686,45 +1795,25 @@
     if (CC_LIKELY(paint->getTextAlign() == SkPaint::kLeft_Align)) {
         SkPaint::FontMetrics metrics;
         paint->getFontMetrics(&metrics, 0.0f);
-        reject = quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom);
+        reject = quickRejectNoScissor(x, y + metrics.fTop, x + length, y + metrics.fBottom);
     }
 
     uint32_t* location = addOp(DisplayList::DrawText, reject);
     addText(text, bytesCount);
     addInt(count);
-    addPoint(x, y);
-    addPaint(paint);
+    addFloat(x);
+    addFloat(y);
+    addFloats(positions, count * 2);
+    SkPaint* addedPaint = addPaint(paint);
+    if (!reject) {
+        FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(addedPaint);
+        fontRenderer.precache(addedPaint, text, count);
+    }
     addFloat(length);
     addSkip(location);
     return DrawGlInfo::kStatusDone;
 }
 
-status_t DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
-        SkPath* path, float hOffset, float vOffset, SkPaint* paint) {
-    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
-    addOp(DisplayList::DrawTextOnPath);
-    addText(text, bytesCount);
-    addInt(count);
-    addPath(path);
-    addFloat(hOffset);
-    addFloat(vOffset);
-    paint->setAntiAlias(true);
-    addPaint(paint);
-    return DrawGlInfo::kStatusDone;
-}
-
-status_t DisplayListRenderer::drawPosText(const char* text, int bytesCount, int count,
-        const float* positions, SkPaint* paint) {
-    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
-    addOp(DisplayList::DrawPosText);
-    addText(text, bytesCount);
-    addInt(count);
-    addFloats(positions, count * 2);
-    paint->setAntiAlias(true);
-    addPaint(paint);
-    return DrawGlInfo::kStatusDone;
-}
-
 void DisplayListRenderer::resetShader() {
     addOp(DisplayList::ResetShader);
 }
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 6b4c6b2..e42def5 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -103,9 +103,9 @@
         DrawPath,
         DrawLines,
         DrawPoints,
-        DrawText,
         DrawTextOnPath,
         DrawPosText,
+        DrawText,
         ResetShader,
         SetupShader,
         ResetColorFilter,
@@ -137,6 +137,8 @@
 
     void output(OpenGLRenderer& renderer, uint32_t level = 0);
 
+    ANDROID_API void reset();
+
     void setRenderable(bool renderable) {
         mIsRenderable = renderable;
     }
@@ -399,7 +401,6 @@
 
 private:
     void init();
-    void initProperties();
 
     void clearResources();
 
@@ -496,12 +497,14 @@
     SortedVector<SkPath*> mSourcePaths;
     Vector<SkMatrix*> mMatrices;
     Vector<SkiaShader*> mShaders;
+    Vector<Layer*> mLayers;
 
     mutable SkFlattenableReadBuffer mReader;
 
     size_t mSize;
 
     bool mIsRenderable;
+    uint32_t mFunctorCount;
 
     String8 mName;
 
@@ -547,7 +550,7 @@
     virtual bool isDeferred();
 
     virtual void setViewport(int width, int height);
-    virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
+    virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
     virtual void finish();
 
     virtual status_t callDrawGLFunction(Functor *functor, Rect& dirty);
@@ -599,12 +602,12 @@
     virtual status_t drawPath(SkPath* path, SkPaint* paint);
     virtual status_t drawLines(float* points, int count, SkPaint* paint);
     virtual status_t drawPoints(float* points, int count, SkPaint* paint);
-    virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y,
-            SkPaint* paint, float length = -1.0f);
     virtual status_t drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
             float hOffset, float vOffset, SkPaint* paint);
     virtual status_t drawPosText(const char* text, int bytesCount, int count,
             const float* positions, SkPaint* paint);
+    virtual status_t drawText(const char* text, int bytesCount, int count,
+            float x, float y, const float* positions, SkPaint* paint, float length);
 
     virtual void resetShader();
     virtual void setupShader(SkiaShader* shader);
@@ -652,10 +655,18 @@
         return mSourcePaths;
     }
 
+    const Vector<Layer*>& getLayers() const {
+        return mLayers;
+    }
+
     const Vector<SkMatrix*>& getMatrices() const {
         return mMatrices;
     }
 
+    uint32_t getFunctorCount() const {
+        return mFunctorCount;
+    }
+
 private:
     void insertRestoreToCount() {
         if (mRestoreSaveCount >= 0) {
@@ -763,17 +774,17 @@
             mPaths.add(pathCopy);
         }
         if (mSourcePaths.indexOf(path) < 0) {
-            Caches::getInstance().resourceCache.incrementRefcount(path);
+            mCaches.resourceCache.incrementRefcount(path);
             mSourcePaths.add(path);
         }
 
         addInt((int) pathCopy);
     }
 
-    inline void addPaint(SkPaint* paint) {
+    inline SkPaint* addPaint(SkPaint* paint) {
         if (!paint) {
             addInt((int) NULL);
-            return;
+            return paint;
         }
 
         SkPaint* paintCopy = mPaintMap.valueFor(paint);
@@ -785,6 +796,8 @@
         }
 
         addInt((int) paintCopy);
+
+        return paintCopy;
     }
 
     inline void addDisplayList(DisplayList* displayList) {
@@ -802,6 +815,12 @@
         mMatrices.add(copy);
     }
 
+    inline void addLayer(Layer* layer) {
+        addInt((int) layer);
+        mLayers.add(layer);
+        mCaches.resourceCache.incrementRefcount(layer);
+    }
+
     inline void addBitmap(SkBitmap* bitmap) {
         // Note that this assumes the bitmap is immutable. There are cases this won't handle
         // correctly, such as creating the bitmap from scratch, drawing with it, changing its
@@ -809,13 +828,13 @@
         // which doesn't seem worth the extra cycles for this unlikely case.
         addInt((int) bitmap);
         mBitmapResources.add(bitmap);
-        Caches::getInstance().resourceCache.incrementRefcount(bitmap);
+        mCaches.resourceCache.incrementRefcount(bitmap);
     }
 
     void addBitmapData(SkBitmap* bitmap) {
         addInt((int) bitmap);
         mOwnedBitmapResources.add(bitmap);
-        Caches::getInstance().resourceCache.incrementRefcount(bitmap);
+        mCaches.resourceCache.incrementRefcount(bitmap);
     }
 
     inline void addShader(SkiaShader* shader) {
@@ -831,7 +850,7 @@
             // replaceValueFor() performs an add if the entry doesn't exist
             mShaderMap.replaceValueFor(shader, shaderCopy);
             mShaders.add(shaderCopy);
-            Caches::getInstance().resourceCache.incrementRefcount(shaderCopy);
+            mCaches.resourceCache.incrementRefcount(shaderCopy);
         }
 
         addInt((int) shaderCopy);
@@ -840,7 +859,7 @@
     inline void addColorFilter(SkiaColorFilter* colorFilter) {
         addInt((int) colorFilter);
         mFilterResources.add(colorFilter);
-        Caches::getInstance().resourceCache.incrementRefcount(colorFilter);
+        mCaches.resourceCache.incrementRefcount(colorFilter);
     }
 
     Vector<SkBitmap*> mBitmapResources;
@@ -860,17 +879,22 @@
 
     Vector<SkMatrix*> mMatrices;
 
-    SkWriter32 mWriter;
+    Vector<Layer*> mLayers;
+
     uint32_t mBufferSize;
 
     int mRestoreSaveCount;
 
+    Caches& mCaches;
+    SkWriter32 mWriter;
+
     float mTranslateX;
     float mTranslateY;
     bool mHasTranslate;
-
     bool mHasDrawOps;
 
+    uint32_t mFunctorCount;
+
     friend class DisplayList;
 
 }; // class DisplayListRenderer
diff --git a/libs/hwui/Dither.cpp b/libs/hwui/Dither.cpp
new file mode 100755
index 0000000..e80b325
--- /dev/null
+++ b/libs/hwui/Dither.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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 "Caches.h"
+#include "Dither.h"
+
+namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+// Must be a power of two
+#define DITHER_KERNEL_SIZE 4
+
+///////////////////////////////////////////////////////////////////////////////
+// Lifecycle
+///////////////////////////////////////////////////////////////////////////////
+
+void Dither::bindDitherTexture() {
+    if (!mInitialized) {
+        const uint8_t pattern[] = {
+             0,  8,  2, 10,
+            12,  4, 14,  6,
+             3, 11,  1,  9,
+            15,  7, 13,  5
+        };
+
+        glGenTextures(1, &mDitherTexture);
+        glBindTexture(GL_TEXTURE_2D, mDitherTexture);
+
+        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, DITHER_KERNEL_SIZE, DITHER_KERNEL_SIZE, 0,
+                GL_ALPHA, GL_UNSIGNED_BYTE, &pattern);
+
+        mInitialized = true;
+    } else {
+        glBindTexture(GL_TEXTURE_2D, mDitherTexture);
+    }
+}
+
+void Dither::clear() {
+    if (mInitialized) {
+        glDeleteTextures(1, &mDitherTexture);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Program management
+///////////////////////////////////////////////////////////////////////////////
+
+void Dither::setupProgram(Program* program, GLuint* textureUnit) {
+    GLuint textureSlot = (*textureUnit)++;
+    Caches::getInstance().activeTexture(textureSlot);
+
+    bindDitherTexture();
+
+    float ditherSize = 1.0f / DITHER_KERNEL_SIZE;
+    glUniform1i(program->getUniform("ditherSampler"), textureSlot);
+    glUniform1f(program->getUniform("ditherSize"), ditherSize);
+    glUniform1f(program->getUniform("ditherSizeSquared"), ditherSize * ditherSize);
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Dither.h b/libs/hwui/Dither.h
new file mode 100755
index 0000000..34cf9bf
--- /dev/null
+++ b/libs/hwui/Dither.h
@@ -0,0 +1,47 @@
+/*
+ * 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 ANDROID_HWUI_DITHER_H
+#define ANDROID_HWUI_DITHER_H
+
+#include <GLES2/gl2.h>
+
+#include "Program.h"
+
+namespace android {
+namespace uirenderer {
+
+/**
+ * Handles dithering for programs.
+ */
+class Dither {
+public:
+    Dither(): mInitialized(false), mDitherTexture(0) { }
+
+    void clear();
+    void setupProgram(Program* program, GLuint* textureUnit);
+
+private:
+    void bindDitherTexture();
+
+    bool mInitialized;
+    GLuint mDitherTexture;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_DITHER_H
diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h
index 6b174d6..bdaa3cc 100644
--- a/libs/hwui/Extensions.h
+++ b/libs/hwui/Extensions.h
@@ -39,9 +39,6 @@
     #define EXT_LOGD(...)
 #endif
 
-// Vendor strings
-#define VENDOR_IMG "Imagination Technologies"
-
 ///////////////////////////////////////////////////////////////////////////////
 // Classes
 ///////////////////////////////////////////////////////////////////////////////
@@ -68,23 +65,21 @@
         mHasDiscardFramebuffer = hasExtension("GL_EXT_discard_framebuffer");
         mHasDebugMarker = hasExtension("GL_EXT_debug_marker");
         mHasDebugLabel = hasExtension("GL_EXT_debug_label");
+        mHasTiledRendering = hasExtension("GL_QCOM_tiled_rendering");
 
-        const char* vendor = (const char*) glGetString(GL_VENDOR);
-        EXT_LOGD("Vendor: %s", vendor);
-        mNeedsHighpTexCoords = strcmp(vendor, VENDOR_IMG) == 0;
+        mExtensions = strdup(buffer);
+    }
 
-        // We don't need to copy the string, the OpenGL ES spec
-        // guarantees the result of glGetString to point to a
-        // static string as long as our OpenGL context is valid
-        mExtensions = buffer;
+    ~Extensions() {
+        free(mExtensions);
     }
 
     inline bool hasNPot() const { return mHasNPot; }
     inline bool hasFramebufferFetch() const { return mHasFramebufferFetch; }
-    inline bool needsHighpTexCoords() const { return mNeedsHighpTexCoords; }
     inline bool hasDiscardFramebuffer() const { return mHasDiscardFramebuffer; }
     inline bool hasDebugMarker() const { return mHasDebugMarker; }
     inline bool hasDebugLabel() const { return mHasDebugLabel; }
+    inline bool hasTiledRendering() const { return mHasTiledRendering; }
 
     bool hasExtension(const char* extension) const {
         const String8 s(extension);
@@ -98,14 +93,14 @@
 private:
     SortedVector<String8> mExtensionList;
 
-    const char* mExtensions;
+    char* mExtensions;
 
     bool mHasNPot;
-    bool mNeedsHighpTexCoords;
     bool mHasFramebufferFetch;
     bool mHasDiscardFramebuffer;
     bool mHasDebugMarker;
     bool mHasDebugLabel;
+    bool mHasTiledRendering;
 }; // class Extensions
 
 }; // namespace uirenderer
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index b51b1e1..4e97c88 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -25,436 +25,12 @@
 #include "Caches.h"
 #include "Debug.h"
 #include "FontRenderer.h"
-#include "Caches.h"
+#include "Rect.h"
 
 namespace android {
 namespace uirenderer {
 
 ///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
-#define DEFAULT_TEXT_CACHE_WIDTH 1024
-#define DEFAULT_TEXT_CACHE_HEIGHT 256
-#define MAX_TEXT_CACHE_WIDTH 2048
-#define TEXTURE_BORDER_SIZE 2
-
-#define AUTO_KERN(prev, next) (((next) - (prev) + 32) >> 6 << 16)
-
-///////////////////////////////////////////////////////////////////////////////
-// CacheTextureLine
-///////////////////////////////////////////////////////////////////////////////
-
-bool CacheTextureLine::fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
-    if (glyph.fHeight + TEXTURE_BORDER_SIZE > mMaxHeight) {
-        return false;
-    }
-
-    if (mCurrentCol + glyph.fWidth + TEXTURE_BORDER_SIZE < mMaxWidth) {
-        *retOriginX = mCurrentCol + 1;
-        *retOriginY = mCurrentRow + 1;
-        mCurrentCol += glyph.fWidth + TEXTURE_BORDER_SIZE;
-        mDirty = true;
-        return true;
-    }
-
-    return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Font
-///////////////////////////////////////////////////////////////////////////////
-
-Font::Font(FontRenderer* state, uint32_t fontId, float fontSize,
-        int flags, uint32_t italicStyle, uint32_t scaleX,
-        SkPaint::Style style, uint32_t strokeWidth) :
-        mState(state), mFontId(fontId), mFontSize(fontSize),
-        mFlags(flags), mItalicStyle(italicStyle), mScaleX(scaleX),
-        mStyle(style), mStrokeWidth(mStrokeWidth) {
-}
-
-
-Font::~Font() {
-    for (uint32_t ct = 0; ct < mState->mActiveFonts.size(); ct++) {
-        if (mState->mActiveFonts[ct] == this) {
-            mState->mActiveFonts.removeAt(ct);
-            break;
-        }
-    }
-
-    for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) {
-        delete mCachedGlyphs.valueAt(i);
-    }
-}
-
-void Font::invalidateTextureCache(CacheTextureLine *cacheLine) {
-    for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) {
-        CachedGlyphInfo* cachedGlyph = mCachedGlyphs.valueAt(i);
-        if (cacheLine == NULL || cachedGlyph->mCachedTextureLine == cacheLine) {
-            cachedGlyph->mIsValid = false;
-        }
-    }
-}
-
-void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
-        uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) {
-    int nPenX = x + glyph->mBitmapLeft;
-    int nPenY = y + glyph->mBitmapTop;
-
-    int width = (int) glyph->mBitmapWidth;
-    int height = (int) glyph->mBitmapHeight;
-
-    if (bounds->bottom > nPenY) {
-        bounds->bottom = nPenY;
-    }
-    if (bounds->left > nPenX) {
-        bounds->left = nPenX;
-    }
-    if (bounds->right < nPenX + width) {
-        bounds->right = nPenX + width;
-    }
-    if (bounds->top < nPenY + height) {
-        bounds->top = nPenY + height;
-    }
-}
-
-void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
-        uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) {
-    int nPenX = x + glyph->mBitmapLeft;
-    int nPenY = y + glyph->mBitmapTop + glyph->mBitmapHeight;
-
-    float u1 = glyph->mBitmapMinU;
-    float u2 = glyph->mBitmapMaxU;
-    float v1 = glyph->mBitmapMinV;
-    float v2 = glyph->mBitmapMaxV;
-
-    int width = (int) glyph->mBitmapWidth;
-    int height = (int) glyph->mBitmapHeight;
-
-    mState->appendMeshQuad(nPenX, nPenY, u1, v2,
-            nPenX + width, nPenY, u2, v2,
-            nPenX + width, nPenY - height, u2, v1,
-            nPenX, nPenY - height, u1, v1, glyph->mCachedTextureLine->mCacheTexture);
-}
-
-void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
-        uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) {
-    int nPenX = x + glyph->mBitmapLeft;
-    int nPenY = y + glyph->mBitmapTop;
-
-    uint32_t endX = glyph->mStartX + glyph->mBitmapWidth;
-    uint32_t endY = glyph->mStartY + glyph->mBitmapHeight;
-
-    CacheTexture *cacheTexture = glyph->mCachedTextureLine->mCacheTexture;
-    uint32_t cacheWidth = cacheTexture->mWidth;
-    const uint8_t* cacheBuffer = cacheTexture->mTexture;
-
-    uint32_t cacheX = 0, cacheY = 0;
-    int32_t bX = 0, bY = 0;
-    for (cacheX = glyph->mStartX, bX = nPenX; cacheX < endX; cacheX++, bX++) {
-        for (cacheY = glyph->mStartY, bY = nPenY; cacheY < endY; cacheY++, bY++) {
-#if DEBUG_FONT_RENDERER
-            if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) {
-                ALOGE("Skipping invalid index");
-                continue;
-            }
-#endif
-            uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX];
-            bitmap[bY * bitmapW + bX] = tempCol;
-        }
-    }
-}
-
-void Font::drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset,
-        SkPathMeasure& measure, SkPoint* position, SkVector* tangent) {
-    const float halfWidth = glyph->mBitmapWidth * 0.5f;
-    const float height = glyph->mBitmapHeight;
-
-    vOffset += glyph->mBitmapTop + height;
-
-    SkPoint destination[4];
-    measure.getPosTan(x + hOffset +  glyph->mBitmapLeft + halfWidth, position, tangent);
-
-    // Move along the tangent and offset by the normal
-    destination[0].set(-tangent->fX * halfWidth - tangent->fY * vOffset,
-            -tangent->fY * halfWidth + tangent->fX * vOffset);
-    destination[1].set(tangent->fX * halfWidth - tangent->fY * vOffset,
-            tangent->fY * halfWidth + tangent->fX * vOffset);
-    destination[2].set(destination[1].fX + tangent->fY * height,
-            destination[1].fY - tangent->fX * height);
-    destination[3].set(destination[0].fX + tangent->fY * height,
-            destination[0].fY - tangent->fX * height);
-
-    const float u1 = glyph->mBitmapMinU;
-    const float u2 = glyph->mBitmapMaxU;
-    const float v1 = glyph->mBitmapMinV;
-    const float v2 = glyph->mBitmapMaxV;
-
-    mState->appendRotatedMeshQuad(
-            position->fX + destination[0].fX,
-            position->fY + destination[0].fY, u1, v2,
-            position->fX + destination[1].fX,
-            position->fY + destination[1].fY, u2, v2,
-            position->fX + destination[2].fX,
-            position->fY + destination[2].fY, u2, v1,
-            position->fX + destination[3].fX,
-            position->fY + destination[3].fY, u1, v1,
-            glyph->mCachedTextureLine->mCacheTexture);
-}
-
-CachedGlyphInfo* Font::getCachedGlyph(SkPaint* paint, glyph_t textUnit) {
-    CachedGlyphInfo* cachedGlyph = NULL;
-    ssize_t index = mCachedGlyphs.indexOfKey(textUnit);
-    if (index >= 0) {
-        cachedGlyph = mCachedGlyphs.valueAt(index);
-    } else {
-        cachedGlyph = cacheGlyph(paint, textUnit);
-    }
-
-    // Is the glyph still in texture cache?
-    if (!cachedGlyph->mIsValid) {
-        const SkGlyph& skiaGlyph = GET_METRICS(paint, textUnit);
-        updateGlyphCache(paint, skiaGlyph, cachedGlyph);
-    }
-
-    return cachedGlyph;
-}
-
-void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
-        int numGlyphs, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
-    if (bitmap != NULL && bitmapW > 0 && bitmapH > 0) {
-        render(paint, text, start, len, numGlyphs, x, y, BITMAP, bitmap,
-                bitmapW, bitmapH, NULL, NULL);
-    } else {
-        render(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL,
-                0, 0, NULL, NULL);
-    }
-}
-
-void Font::render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
-            int numGlyphs, int x, int y, const float* positions) {
-    render(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL,
-            0, 0, NULL, positions);
-}
-
-void Font::render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
-        int numGlyphs, SkPath* path, float hOffset, float vOffset) {
-    if (numGlyphs == 0 || text == NULL || len == 0) {
-        return;
-    }
-
-    text += start;
-
-    int glyphsCount = 0;
-    SkFixed prevRsbDelta = 0;
-
-    float penX = 0.0f;
-
-    SkPoint position;
-    SkVector tangent;
-
-    SkPathMeasure measure(*path, false);
-    float pathLength = SkScalarToFloat(measure.getLength());
-
-    if (paint->getTextAlign() != SkPaint::kLeft_Align) {
-        float textWidth = SkScalarToFloat(paint->measureText(text, len));
-        float pathOffset = pathLength;
-        if (paint->getTextAlign() == SkPaint::kCenter_Align) {
-            textWidth *= 0.5f;
-            pathOffset *= 0.5f;
-        }
-        penX += pathOffset - textWidth;
-    }
-
-    while (glyphsCount < numGlyphs && penX < pathLength) {
-        glyph_t glyph = GET_GLYPH(text);
-
-        if (IS_END_OF_STRING(glyph)) {
-            break;
-        }
-
-        CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph);
-        penX += SkFixedToFloat(AUTO_KERN(prevRsbDelta, cachedGlyph->mLsbDelta));
-        prevRsbDelta = cachedGlyph->mRsbDelta;
-
-        if (cachedGlyph->mIsValid) {
-            drawCachedGlyph(cachedGlyph, penX, hOffset, vOffset, measure, &position, &tangent);
-        }
-
-        penX += SkFixedToFloat(cachedGlyph->mAdvanceX);
-
-        glyphsCount++;
-    }
-}
-
-void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
-        int numGlyphs, Rect *bounds) {
-    if (bounds == NULL) {
-        ALOGE("No return rectangle provided to measure text");
-        return;
-    }
-    bounds->set(1e6, -1e6, -1e6, 1e6);
-    render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds, NULL);
-}
-
-void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
-        int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
-        uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* positions) {
-    if (numGlyphs == 0 || text == NULL || len == 0) {
-        return;
-    }
-
-    static RenderGlyph gRenderGlyph[] = {
-            &android::uirenderer::Font::drawCachedGlyph,
-            &android::uirenderer::Font::drawCachedGlyphBitmap,
-            &android::uirenderer::Font::measureCachedGlyph
-    };
-    RenderGlyph render = gRenderGlyph[mode];
-
-    text += start;
-    int glyphsCount = 0;
-
-    if (CC_LIKELY(positions == NULL)) {
-        SkFixed prevRsbDelta = 0;
-
-        float penX = x + 0.5f;
-        int penY = y;
-
-        while (glyphsCount < numGlyphs) {
-            glyph_t glyph = GET_GLYPH(text);
-
-            // Reached the end of the string
-            if (IS_END_OF_STRING(glyph)) {
-                break;
-            }
-
-            CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph);
-            penX += SkFixedToFloat(AUTO_KERN(prevRsbDelta, cachedGlyph->mLsbDelta));
-            prevRsbDelta = cachedGlyph->mRsbDelta;
-
-            // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage
-            if (cachedGlyph->mIsValid) {
-                (*this.*render)(cachedGlyph, (int) floorf(penX), penY,
-                        bitmap, bitmapW, bitmapH, bounds, positions);
-            }
-
-            penX += SkFixedToFloat(cachedGlyph->mAdvanceX);
-
-            glyphsCount++;
-        }
-    } else {
-        const SkPaint::Align align = paint->getTextAlign();
-
-        // This is for renderPosText()
-        while (glyphsCount < numGlyphs) {
-            glyph_t glyph = GET_GLYPH(text);
-
-            // Reached the end of the string
-            if (IS_END_OF_STRING(glyph)) {
-                break;
-            }
-
-            CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph);
-
-            // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage
-            if (cachedGlyph->mIsValid) {
-                int penX = x + positions[(glyphsCount << 1)];
-                int penY = y + positions[(glyphsCount << 1) + 1];
-
-                switch (align) {
-                    case SkPaint::kRight_Align:
-                        penX -= SkFixedToFloat(cachedGlyph->mAdvanceX);
-                        penY -= SkFixedToFloat(cachedGlyph->mAdvanceY);
-                        break;
-                    case SkPaint::kCenter_Align:
-                        penX -= SkFixedToFloat(cachedGlyph->mAdvanceX >> 1);
-                        penY -= SkFixedToFloat(cachedGlyph->mAdvanceY >> 1);
-                    default:
-                        break;
-                }
-
-                (*this.*render)(cachedGlyph, penX, penY,
-                        bitmap, bitmapW, bitmapH, bounds, positions);
-            }
-
-            glyphsCount++;
-        }
-    }
-}
-
-void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph) {
-    glyph->mAdvanceX = skiaGlyph.fAdvanceX;
-    glyph->mAdvanceY = skiaGlyph.fAdvanceY;
-    glyph->mBitmapLeft = skiaGlyph.fLeft;
-    glyph->mBitmapTop = skiaGlyph.fTop;
-    glyph->mLsbDelta = skiaGlyph.fLsbDelta;
-    glyph->mRsbDelta = skiaGlyph.fRsbDelta;
-
-    uint32_t startX = 0;
-    uint32_t startY = 0;
-
-    // Get the bitmap for the glyph
-    paint->findImage(skiaGlyph);
-    mState->cacheBitmap(skiaGlyph, glyph, &startX, &startY);
-
-    if (!glyph->mIsValid) {
-        return;
-    }
-
-    uint32_t endX = startX + skiaGlyph.fWidth;
-    uint32_t endY = startY + skiaGlyph.fHeight;
-
-    glyph->mStartX = startX;
-    glyph->mStartY = startY;
-    glyph->mBitmapWidth = skiaGlyph.fWidth;
-    glyph->mBitmapHeight = skiaGlyph.fHeight;
-
-    uint32_t cacheWidth = glyph->mCachedTextureLine->mCacheTexture->mWidth;
-    uint32_t cacheHeight = glyph->mCachedTextureLine->mCacheTexture->mHeight;
-
-    glyph->mBitmapMinU = (float) startX / (float) cacheWidth;
-    glyph->mBitmapMinV = (float) startY / (float) cacheHeight;
-    glyph->mBitmapMaxU = (float) endX / (float) cacheWidth;
-    glyph->mBitmapMaxV = (float) endY / (float) cacheHeight;
-
-    mState->mUploadTexture = true;
-}
-
-CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, glyph_t glyph) {
-    CachedGlyphInfo* newGlyph = new CachedGlyphInfo();
-    mCachedGlyphs.add(glyph, newGlyph);
-
-    const SkGlyph& skiaGlyph = GET_METRICS(paint, glyph);
-    newGlyph->mGlyphIndex = skiaGlyph.fID;
-    newGlyph->mIsValid = false;
-
-    updateGlyphCache(paint, skiaGlyph, newGlyph);
-
-    return newGlyph;
-}
-
-Font* Font::create(FontRenderer* state, uint32_t fontId, float fontSize,
-        int flags, uint32_t italicStyle, uint32_t scaleX,
-        SkPaint::Style style, uint32_t strokeWidth) {
-    Vector<Font*> &activeFonts = state->mActiveFonts;
-
-    for (uint32_t i = 0; i < activeFonts.size(); i++) {
-        Font* font = activeFonts[i];
-        if (font->mFontId == fontId && font->mFontSize == fontSize &&
-                font->mFlags == flags && font->mItalicStyle == italicStyle &&
-                font->mScaleX == scaleX && font->mStyle == style &&
-                (style == SkPaint::kFill_Style || font->mStrokeWidth == strokeWidth)) {
-            return font;
-        }
-    }
-
-    Font* newFont = new Font(state, fontId, fontSize, flags, italicStyle,
-            scaleX, style, strokeWidth);
-    activeFonts.push(newFont);
-    return newFont;
-}
-
-///////////////////////////////////////////////////////////////////////////////
 // FontRenderer
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -470,63 +46,65 @@
     mMaxNumberOfQuads = 1024;
     mCurrentQuadIndex = 0;
 
-    mTextMeshPtr = NULL;
+    mTextMesh = NULL;
     mCurrentCacheTexture = NULL;
     mLastCacheTexture = NULL;
-    mCacheTextureSmall = NULL;
-    mCacheTexture128 = NULL;
-    mCacheTexture256 = NULL;
-    mCacheTexture512 = NULL;
 
     mLinearFiltering = false;
 
     mIndexBufferID = 0;
 
-    mSmallCacheWidth = DEFAULT_TEXT_CACHE_WIDTH;
-    mSmallCacheHeight = DEFAULT_TEXT_CACHE_HEIGHT;
+    mSmallCacheWidth = DEFAULT_TEXT_SMALL_CACHE_WIDTH;
+    mSmallCacheHeight = DEFAULT_TEXT_SMALL_CACHE_HEIGHT;
+    mLargeCacheWidth = DEFAULT_TEXT_LARGE_CACHE_WIDTH;
+    mLargeCacheHeight = DEFAULT_TEXT_LARGE_CACHE_HEIGHT;
 
     char property[PROPERTY_VALUE_MAX];
-    if (property_get(PROPERTY_TEXT_CACHE_WIDTH, property, NULL) > 0) {
-        if (sLogFontRendererCreate) {
-            INIT_LOGD("  Setting text cache width to %s pixels", property);
-        }
+    if (property_get(PROPERTY_TEXT_SMALL_CACHE_WIDTH, property, NULL) > 0) {
         mSmallCacheWidth = atoi(property);
-    } else {
-        if (sLogFontRendererCreate) {
-            INIT_LOGD("  Using default text cache width of %i pixels", mSmallCacheWidth);
-        }
     }
 
-    if (property_get(PROPERTY_TEXT_CACHE_HEIGHT, property, NULL) > 0) {
-        if (sLogFontRendererCreate) {
-            INIT_LOGD("  Setting text cache width to %s pixels", property);
-        }
+    if (property_get(PROPERTY_TEXT_SMALL_CACHE_HEIGHT, property, NULL) > 0) {
         mSmallCacheHeight = atoi(property);
-    } else {
-        if (sLogFontRendererCreate) {
-            INIT_LOGD("  Using default text cache height of %i pixels", mSmallCacheHeight);
-        }
+    }
+
+    if (property_get(PROPERTY_TEXT_LARGE_CACHE_WIDTH, property, NULL) > 0) {
+        mLargeCacheWidth = atoi(property);
+    }
+
+    if (property_get(PROPERTY_TEXT_LARGE_CACHE_HEIGHT, property, NULL) > 0) {
+        mLargeCacheHeight = atoi(property);
+    }
+
+    uint32_t maxTextureSize = (uint32_t) Caches::getInstance().maxTextureSize;
+    mSmallCacheWidth = mSmallCacheWidth > maxTextureSize ? maxTextureSize : mSmallCacheWidth;
+    mSmallCacheHeight = mSmallCacheHeight > maxTextureSize ? maxTextureSize : mSmallCacheHeight;
+    mLargeCacheWidth = mLargeCacheWidth > maxTextureSize ? maxTextureSize : mLargeCacheWidth;
+    mLargeCacheHeight = mLargeCacheHeight > maxTextureSize ? maxTextureSize : mLargeCacheHeight;
+
+    if (sLogFontRendererCreate) {
+        INIT_LOGD("  Text cache sizes, in pixels: %i x %i, %i x %i, %i x %i, %i x %i",
+                mSmallCacheWidth, mSmallCacheHeight,
+                mLargeCacheWidth, mLargeCacheHeight >> 1,
+                mLargeCacheWidth, mLargeCacheHeight >> 1,
+                mLargeCacheWidth, mLargeCacheHeight);
     }
 
     sLogFontRendererCreate = false;
 }
 
 FontRenderer::~FontRenderer() {
-    for (uint32_t i = 0; i < mCacheLines.size(); i++) {
-        delete mCacheLines[i];
+    for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
+        delete mCacheTextures[i];
     }
-    mCacheLines.clear();
+    mCacheTextures.clear();
 
     if (mInitialized) {
         // Unbinding the buffer shouldn't be necessary but it crashes with some drivers
         Caches::getInstance().unbindIndicesBuffer();
         glDeleteBuffers(1, &mIndexBufferID);
 
-        delete[] mTextMeshPtr;
-        delete mCacheTextureSmall;
-        delete mCacheTexture128;
-        delete mCacheTexture256;
-        delete mCacheTexture512;
+        delete[] mTextMesh;
     }
 
     Vector<Font*> fontsToDereference = mActiveFonts;
@@ -545,80 +123,57 @@
         mActiveFonts[i]->invalidateTextureCache();
     }
 
-    for (uint32_t i = 0; i < mCacheLines.size(); i++) {
-        mCacheLines[i]->mCurrentCol = 0;
+    for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
+        mCacheTextures[i]->init();
     }
-}
 
-void FontRenderer::deallocateTextureMemory(CacheTexture *cacheTexture) {
-    if (cacheTexture && cacheTexture->mTexture) {
-        glDeleteTextures(1, &cacheTexture->mTextureId);
-        delete[] cacheTexture->mTexture;
-        cacheTexture->mTexture = NULL;
-        cacheTexture->mTextureId = 0;
+#if DEBUG_FONT_RENDERER
+    uint16_t totalGlyphs = 0;
+    for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
+        totalGlyphs += mCacheTextures[i]->getGlyphCount();
+        // Erase caches, just as a debugging facility
+        if (mCacheTextures[i]->getTexture()) {
+            memset(mCacheTextures[i]->getTexture(), 0,
+                    mCacheTextures[i]->getWidth() * mCacheTextures[i]->getHeight());
+        }
     }
+    ALOGD("Flushing caches: glyphs cached = %d", totalGlyphs);
+#endif
 }
 
 void FontRenderer::flushLargeCaches() {
-    if ((!mCacheTexture128 || !mCacheTexture128->mTexture) &&
-            (!mCacheTexture256 || !mCacheTexture256->mTexture) &&
-            (!mCacheTexture512 || !mCacheTexture512->mTexture)) {
-        // Typical case; no large glyph caches allocated
-        return;
-    }
-
-    for (uint32_t i = 0; i < mCacheLines.size(); i++) {
-        CacheTextureLine* cacheLine = mCacheLines[i];
-        if ((cacheLine->mCacheTexture == mCacheTexture128 ||
-                cacheLine->mCacheTexture == mCacheTexture256 ||
-                cacheLine->mCacheTexture == mCacheTexture512) &&
-                cacheLine->mCacheTexture->mTexture != NULL) {
-            cacheLine->mCurrentCol = 0;
-            for (uint32_t i = 0; i < mActiveFonts.size(); i++) {
-                mActiveFonts[i]->invalidateTextureCache(cacheLine);
+    // Start from 1; don't deallocate smallest/default texture
+    for (uint32_t i = 1; i < mCacheTextures.size(); i++) {
+        CacheTexture* cacheTexture = mCacheTextures[i];
+        if (cacheTexture->getTexture()) {
+            cacheTexture->init();
+            for (uint32_t j = 0; j < mActiveFonts.size(); j++) {
+                mActiveFonts[j]->invalidateTextureCache(cacheTexture);
             }
+            cacheTexture->releaseTexture();
         }
     }
-
-    deallocateTextureMemory(mCacheTexture128);
-    deallocateTextureMemory(mCacheTexture256);
-    deallocateTextureMemory(mCacheTexture512);
 }
 
-void FontRenderer::allocateTextureMemory(CacheTexture* cacheTexture) {
-    int width = cacheTexture->mWidth;
-    int height = cacheTexture->mHeight;
-
-    cacheTexture->mTexture = new uint8_t[width * height];
-#if DEBUG_FONT_RENDERER
-    memset(cacheTexture->mTexture, 0, width * height * sizeof(uint8_t));
-#endif
-
-    if (!cacheTexture->mTextureId) {
-        glGenTextures(1, &cacheTexture->mTextureId);
+CacheTexture* FontRenderer::cacheBitmapInTexture(const SkGlyph& glyph,
+        uint32_t* startX, uint32_t* startY) {
+    for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
+        if (mCacheTextures[i]->fitBitmap(glyph, startX, startY)) {
+            return mCacheTextures[i];
+        }
     }
-
-    Caches::getInstance().activeTexture(0);
-    glBindTexture(GL_TEXTURE_2D, cacheTexture->mTextureId);
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-    // Initialize texture dimensions
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
-            GL_ALPHA, GL_UNSIGNED_BYTE, 0);
-
-    const GLenum filtering = cacheTexture->mLinearFiltering ? GL_LINEAR : GL_NEAREST;
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
-
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    // Could not fit glyph into current cache textures
+    return NULL;
 }
 
 void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
-        uint32_t* retOriginX, uint32_t* retOriginY) {
+        uint32_t* retOriginX, uint32_t* retOriginY, bool precaching) {
+    checkInit();
     cachedGlyph->mIsValid = false;
     // If the glyph is too tall, don't cache it
-    if (mCacheLines.size() != 0  && (glyph.fHeight + TEXTURE_BORDER_SIZE > mCacheLines[mCacheLines.size() - 1]->mMaxHeight)) {
-        ALOGE("Font size to large to fit in cache. width, height = %i, %i",
+    if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 >
+                mCacheTextures[mCacheTextures.size() - 1]->getHeight()) {
+        ALOGE("Font size too large to fit in cache. width, height = %i, %i",
                 (int) glyph.fWidth, (int) glyph.fHeight);
         return;
     }
@@ -627,36 +182,23 @@
     uint32_t startX = 0;
     uint32_t startY = 0;
 
-    bool bitmapFit = false;
-    CacheTextureLine *cacheLine;
-    for (uint32_t i = 0; i < mCacheLines.size(); i++) {
-        bitmapFit = mCacheLines[i]->fitBitmap(glyph, &startX, &startY);
-        if (bitmapFit) {
-            cacheLine = mCacheLines[i];
-            break;
-        }
-    }
+    CacheTexture* cacheTexture = cacheBitmapInTexture(glyph, &startX, &startY);
 
-    // If the new glyph didn't fit, flush the state so far and invalidate everything
-    if (!bitmapFit) {
-        flushAllAndInvalidate();
-
-        // Try to fit it again
-        for (uint32_t i = 0; i < mCacheLines.size(); i++) {
-            bitmapFit = mCacheLines[i]->fitBitmap(glyph, &startX, &startY);
-            if (bitmapFit) {
-                cacheLine = mCacheLines[i];
-                break;
-            }
+    if (!cacheTexture) {
+        if (!precaching) {
+            // If the new glyph didn't fit and we are not just trying to precache it,
+            // clear out the cache and try again
+            flushAllAndInvalidate();
+            cacheTexture = cacheBitmapInTexture(glyph, &startX, &startY);
         }
 
-        // if we still don't fit, something is wrong and we shouldn't draw
-        if (!bitmapFit) {
+        if (!cacheTexture) {
+            // either the glyph didn't fit or we're precaching and will cache it when we draw
             return;
         }
     }
 
-    cachedGlyph->mCachedTextureLine = cacheLine;
+    cachedGlyph->mCacheTexture = cacheTexture;
 
     *retOriginX = startX;
     *retOriginY = startY;
@@ -664,23 +206,44 @@
     uint32_t endX = startX + glyph.fWidth;
     uint32_t endY = startY + glyph.fHeight;
 
-    uint32_t cacheWidth = cacheLine->mMaxWidth;
+    uint32_t cacheWidth = cacheTexture->getWidth();
 
-    CacheTexture* cacheTexture = cacheLine->mCacheTexture;
-    if (!cacheTexture->mTexture) {
+    if (!cacheTexture->getTexture()) {
+        Caches::getInstance().activeTexture(0);
         // Large-glyph texture memory is allocated only as needed
-        allocateTextureMemory(cacheTexture);
+        cacheTexture->allocateTexture();
     }
 
-    uint8_t* cacheBuffer = cacheTexture->mTexture;
+    uint8_t* cacheBuffer = cacheTexture->getTexture();
     uint8_t* bitmapBuffer = (uint8_t*) glyph.fImage;
     unsigned int stride = glyph.rowBytes();
 
     uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
-    for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
-        for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY++) {
-            uint8_t tempCol = bitmapBuffer[bY * stride + bX];
-            cacheBuffer[cacheY * cacheWidth + cacheX] = mGammaTable[tempCol];
+
+    for (cacheX = startX - TEXTURE_BORDER_SIZE; cacheX < endX + TEXTURE_BORDER_SIZE; cacheX++) {
+        cacheBuffer[(startY - TEXTURE_BORDER_SIZE) * cacheWidth + cacheX] = 0;
+        cacheBuffer[(endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + cacheX] = 0;
+    }
+
+    for (cacheY = startY - TEXTURE_BORDER_SIZE + 1;
+            cacheY < endY + TEXTURE_BORDER_SIZE - 1; cacheY++) {
+        cacheBuffer[cacheY * cacheWidth + startX - TEXTURE_BORDER_SIZE] = 0;
+        cacheBuffer[cacheY * cacheWidth + endX + TEXTURE_BORDER_SIZE - 1] = 0;
+    }
+
+    if (mGammaTable) {
+        for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
+            for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY++) {
+                uint8_t tempCol = bitmapBuffer[bY * stride + bX];
+                cacheBuffer[cacheY * cacheWidth + cacheX] = mGammaTable[tempCol];
+            }
+        }
+    } else {
+        for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
+            for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY++) {
+                uint8_t tempCol = bitmapBuffer[bY * stride + bX];
+                cacheBuffer[cacheY * cacheWidth + cacheX] = tempCol;
+            }
         }
     }
 
@@ -688,68 +251,28 @@
 }
 
 CacheTexture* FontRenderer::createCacheTexture(int width, int height, bool allocate) {
-    uint8_t* textureMemory = NULL;
-    CacheTexture* cacheTexture = new CacheTexture(textureMemory, width, height);
+    CacheTexture* cacheTexture = new CacheTexture(width, height);
 
     if (allocate) {
-        allocateTextureMemory(cacheTexture);
+        Caches::getInstance().activeTexture(0);
+        cacheTexture->allocateTexture();
     }
 
     return cacheTexture;
 }
 
 void FontRenderer::initTextTexture() {
-    for (uint32_t i = 0; i < mCacheLines.size(); i++) {
-        delete mCacheLines[i];
+    for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
+        delete mCacheTextures[i];
     }
-    mCacheLines.clear();
-
-    if (mCacheTextureSmall) {
-        delete mCacheTextureSmall;
-        delete mCacheTexture128;
-        delete mCacheTexture256;
-        delete mCacheTexture512;
-    }
-
-    // Next, use other, separate caches for large glyphs.
-    uint16_t maxWidth = 0;
-    if (Caches::hasInstance()) {
-        maxWidth = Caches::getInstance().maxTextureSize;
-    }
-
-    if (maxWidth > MAX_TEXT_CACHE_WIDTH || maxWidth == 0) {
-        maxWidth = MAX_TEXT_CACHE_WIDTH;
-    }
-
-    mCacheTextureSmall = createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, true);
-    mCacheTexture128 = createCacheTexture(maxWidth, 256, false);
-    mCacheTexture256 = createCacheTexture(maxWidth, 256, false);
-    mCacheTexture512 = createCacheTexture(maxWidth, 512, false);
-    mCurrentCacheTexture = mCacheTextureSmall;
+    mCacheTextures.clear();
 
     mUploadTexture = false;
-    // Split up our default cache texture into lines of certain widths
-    int nextLine = 0;
-    mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 18, nextLine, 0, mCacheTextureSmall));
-    nextLine += mCacheLines.top()->mMaxHeight;
-    mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 26, nextLine, 0, mCacheTextureSmall));
-    nextLine += mCacheLines.top()->mMaxHeight;
-    mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 26, nextLine, 0, mCacheTextureSmall));
-    nextLine += mCacheLines.top()->mMaxHeight;
-    mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 34, nextLine, 0, mCacheTextureSmall));
-    nextLine += mCacheLines.top()->mMaxHeight;
-    mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 34, nextLine, 0, mCacheTextureSmall));
-    nextLine += mCacheLines.top()->mMaxHeight;
-    mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 42, nextLine, 0, mCacheTextureSmall));
-    nextLine += mCacheLines.top()->mMaxHeight;
-    mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, mSmallCacheHeight - nextLine,
-            nextLine, 0, mCacheTextureSmall));
-
-    //  The first cache is split into 2 lines of height 128, the rest have just one cache line.
-    mCacheLines.push(new CacheTextureLine(maxWidth, 128, 0, 0, mCacheTexture128));
-    mCacheLines.push(new CacheTextureLine(maxWidth, 128, 128, 0, mCacheTexture128));
-    mCacheLines.push(new CacheTextureLine(maxWidth, 256, 0, 0, mCacheTexture256));
-    mCacheLines.push(new CacheTextureLine(maxWidth, 512, 0, 0, mCacheTexture512));
+    mCacheTextures.push(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, true));
+    mCacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, false));
+    mCacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, false));
+    mCacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight, false));
+    mCurrentCacheTexture = mCacheTextures[0];
 }
 
 // Avoid having to reallocate memory and render quad by quad
@@ -782,7 +305,7 @@
     uint32_t uvSize = 2;
     uint32_t vertsPerQuad = 4;
     uint32_t vertexBufferSize = mMaxNumberOfQuads * vertsPerQuad * coordSize * uvSize;
-    mTextMeshPtr = new float[vertexBufferSize];
+    mTextMesh = new float[vertexBufferSize];
 }
 
 // We don't want to allocate anything unless we actually draw text
@@ -804,37 +327,38 @@
 
     Caches& caches = Caches::getInstance();
     GLuint lastTextureId = 0;
-    // Iterate over all the cache lines and see which ones need to be updated
-    for (uint32_t i = 0; i < mCacheLines.size(); i++) {
-        CacheTextureLine* cl = mCacheLines[i];
-        if (cl->mDirty && cl->mCacheTexture->mTexture != NULL) {
-            CacheTexture* cacheTexture = cl->mCacheTexture;
-            uint32_t xOffset = 0;
-            uint32_t yOffset = cl->mCurrentRow;
-            uint32_t width   = cl->mMaxWidth;
-            uint32_t height  = cl->mMaxHeight;
-            void* textureData = cacheTexture->mTexture + (yOffset * width);
+    // Iterate over all the cache textures and see which ones need to be updated
+    for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
+        CacheTexture* cacheTexture = mCacheTextures[i];
+        if (cacheTexture->isDirty() && cacheTexture->getTexture()) {
+            // Can't copy inner rect; glTexSubimage expects pointer to deal with entire buffer
+            // of data. So expand the dirty rect to the encompassing horizontal stripe.
+            const Rect* dirtyRect = cacheTexture->getDirtyRect();
+            uint32_t x = 0;
+            uint32_t y = dirtyRect->top;
+            uint32_t width = cacheTexture->getWidth();
+            uint32_t height = dirtyRect->getHeight();
+            void* textureData = cacheTexture->getTexture() + y * width;
 
-            if (cacheTexture->mTextureId != lastTextureId) {
+            if (cacheTexture->getTextureId() != lastTextureId) {
+                lastTextureId = cacheTexture->getTextureId();
                 caches.activeTexture(0);
-                glBindTexture(GL_TEXTURE_2D, cacheTexture->mTextureId);
-                lastTextureId = cacheTexture->mTextureId;
+                glBindTexture(GL_TEXTURE_2D, lastTextureId);
             }
-            glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, width, height,
+#if DEBUG_FONT_RENDERER
+            ALOGD("glTexSubimage for cacheTexture %d: x, y, width height = %d, %d, %d, %d",
+                    i, x, y, width, height);
+#endif
+            glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height,
                     GL_ALPHA, GL_UNSIGNED_BYTE, textureData);
-
-            cl->mDirty = false;
+            cacheTexture->setDirty(false);
         }
     }
 
     caches.activeTexture(0);
-    glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
-    if (mLinearFiltering != mCurrentCacheTexture->mLinearFiltering) {
-        const GLenum filtering = mLinearFiltering ? GL_LINEAR : GL_NEAREST;
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
-        mCurrentCacheTexture->mLinearFiltering = mLinearFiltering;
-    }
+    glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->getTextureId());
+
+    mCurrentCacheTexture->setLinearFiltering(mLinearFiltering, false);
     mLastCacheTexture = mCurrentCacheTexture;
 
     mUploadTexture = false;
@@ -846,13 +370,12 @@
     Caches& caches = Caches::getInstance();
     caches.bindIndicesBuffer(mIndexBufferID);
     if (!mDrawn) {
-        float* buffer = mTextMeshPtr;
+        float* buffer = mTextMesh;
         int offset = 2;
 
         bool force = caches.unbindMeshBuffer();
-        caches.bindPositionVertexPointer(force, caches.currentProgram->position, buffer);
-        caches.bindTexCoordsVertexPointer(force, caches.currentProgram->texCoords,
-                buffer + offset);
+        caches.bindPositionVertexPointer(force, buffer);
+        caches.bindTexCoordsVertexPointer(force, buffer + offset);
     }
 
     glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, NULL);
@@ -875,7 +398,7 @@
 
     const uint32_t vertsPerQuad = 4;
     const uint32_t floatsPerVert = 4;
-    float* currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert;
+    float* currentPos = mTextMesh + mCurrentQuadIndex * vertsPerQuad * floatsPerVert;
 
     (*currentPos++) = x1;
     (*currentPos++) = y1;
@@ -943,43 +466,7 @@
     }
 }
 
-uint32_t FontRenderer::getRemainingCacheCapacity() {
-    uint32_t remainingCapacity = 0;
-    float totalPixels = 0;
-
-    //avoid divide by zero if the size is 0
-    if (mCacheLines.size() == 0) {
-        return 0;
-    }
-    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
-         remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol);
-         totalPixels += mCacheLines[i]->mMaxWidth;
-    }
-    remainingCapacity = (remainingCapacity * 100) / totalPixels;
-    return remainingCapacity;
-}
-
-void FontRenderer::precacheLatin(SkPaint* paint) {
-    // Remaining capacity is measured in %
-    uint32_t remainingCapacity = getRemainingCacheCapacity();
-    uint32_t precacheIndex = 0;
-
-    // We store a string with letters in a rough frequency of occurrence
-    String16 l("eisarntolcdugpmhbyfvkwzxjq EISARNTOLCDUGPMHBYFVKWZXJQ,.?!()-+@;:'0123456789");
-
-    size_t size = l.size();
-    uint16_t latin[size];
-    paint->utfToGlyphs(l.string(), SkPaint::kUTF16_TextEncoding, size * sizeof(char16_t), latin);
-
-    while (remainingCapacity > 25 && precacheIndex < size) {
-        mCurrentFont->getCachedGlyph(paint, TO_GLYPH(latin[precacheIndex]));
-        remainingCapacity = getRemainingCacheCapacity();
-        precacheIndex++;
-    }
-}
-
 void FontRenderer::setFont(SkPaint* paint, uint32_t fontId, float fontSize) {
-    uint32_t currentNumFonts = mActiveFonts.size();
     int flags = 0;
     if (paint->isFakeBoldText()) {
         flags |= Font::kFakeBold;
@@ -995,16 +482,10 @@
     mCurrentFont = Font::create(this, fontId, fontSize, flags, italicStyle,
             scaleX, style, strokeWidth);
 
-    const float maxPrecacheFontSize = 40.0f;
-    bool isNewFont = currentNumFonts != mActiveFonts.size();
-
-    if (isNewFont && fontSize <= maxPrecacheFontSize) {
-        precacheLatin(paint);
-    }
 }
 
 FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const char *text,
-        uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius) {
+        uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius, const float* positions) {
     checkInit();
 
     if (!mCurrentFont) {
@@ -1022,7 +503,7 @@
     mBounds = NULL;
 
     Rect bounds;
-    mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds);
+    mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds, positions);
 
     uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius;
     uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius;
@@ -1036,7 +517,7 @@
     int penY = radius - bounds.bottom;
 
     mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY,
-            dataBuffer, paddedWidth, paddedHeight);
+            Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, NULL, positions);
     blurImage(dataBuffer, paddedWidth, paddedHeight, radius);
 
     DropShadow image;
@@ -1067,6 +548,25 @@
     }
 }
 
+void FontRenderer::precache(SkPaint* paint, const char* text, int numGlyphs) {
+    int flags = 0;
+    if (paint->isFakeBoldText()) {
+        flags |= Font::kFakeBold;
+    }
+    const float skewX = paint->getTextSkewX();
+    uint32_t italicStyle = *(uint32_t*) &skewX;
+    const float scaleXFloat = paint->getTextScaleX();
+    uint32_t scaleX = *(uint32_t*) &scaleXFloat;
+    SkPaint::Style style = paint->getStyle();
+    const float strokeWidthFloat = paint->getStrokeWidth();
+    uint32_t strokeWidth = *(uint32_t*) &strokeWidthFloat;
+    float fontSize = paint->getTextSize();
+    Font* font = Font::create(this, SkTypeface::UniqueID(paint->getTypeface()),
+            fontSize, flags, italicStyle, scaleX, style, strokeWidth);
+
+    font->precache(paint, text, numGlyphs);
+}
+
 bool FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text,
         uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, Rect* bounds) {
     if (!mCurrentFont) {
@@ -1111,6 +611,19 @@
     return mDrawn;
 }
 
+void FontRenderer::removeFont(const Font* font) {
+    for (uint32_t ct = 0; ct < mActiveFonts.size(); ct++) {
+        if (mActiveFonts[ct] == font) {
+            mActiveFonts.removeAt(ct);
+            break;
+        }
+    }
+
+    if (mCurrentFont == font) {
+        mCurrentFont = NULL;
+    }
+}
+
 void FontRenderer::computeGaussianWeights(float* weights, int32_t radius) {
     // Compute gaussian weights for the blur
     // e is the euler's number
@@ -1198,7 +711,6 @@
     float currentPixel = 0.0f;
 
     for (int32_t y = 0; y < height; y ++) {
-
         uint8_t* output = dest + y * width;
 
         for (int32_t x = 0; x < width; x ++) {
@@ -1232,7 +744,7 @@
                 }
             }
             *output = (uint8_t) blurredPixel;
-            output ++;
+            output++;
         }
     }
 }
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 2ab680e..405db09 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -17,219 +17,22 @@
 #ifndef ANDROID_HWUI_FONT_RENDERER_H
 #define ANDROID_HWUI_FONT_RENDERER_H
 
-#include <utils/String8.h>
-#include <utils/String16.h>
 #include <utils/Vector.h>
-#include <utils/KeyedVector.h>
 
-#include <SkScalerContext.h>
 #include <SkPaint.h>
-#include <SkPathMeasure.h>
-#include <SkPoint.h>
 
 #include <GLES2/gl2.h>
 
-#include "Rect.h"
+#include "font/FontUtil.h"
+#include "font/CacheTexture.h"
+#include "font/CachedGlyphInfo.h"
+#include "font/Font.h"
 #include "Properties.h"
 
 namespace android {
 namespace uirenderer {
 
 ///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
-#if RENDER_TEXT_AS_GLYPHS
-    typedef uint16_t glyph_t;
-    #define TO_GLYPH(g) g
-    #define GET_METRICS(paint, glyph) paint->getGlyphMetrics(glyph)
-    #define GET_GLYPH(text) nextGlyph((const uint16_t**) &text)
-    #define IS_END_OF_STRING(glyph) false
-#else
-    typedef SkUnichar glyph_t;
-    #define TO_GLYPH(g) ((SkUnichar) g)
-    #define GET_METRICS(paint, glyph) paint->getUnicharMetrics(glyph)
-    #define GET_GLYPH(text) SkUTF16_NextUnichar((const uint16_t**) &text)
-    #define IS_END_OF_STRING(glyph) glyph < 0
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// Declarations
-///////////////////////////////////////////////////////////////////////////////
-
-class FontRenderer;
-
-class CacheTexture {
-public:
-    CacheTexture() { }
-    CacheTexture(uint8_t* texture, uint16_t width, uint16_t height) :
-            mTexture(texture), mTextureId(0), mWidth(width), mHeight(height),
-            mLinearFiltering(false) { }
-    ~CacheTexture() {
-        if (mTexture) {
-            delete[] mTexture;
-        }
-        if (mTextureId) {
-            glDeleteTextures(1, &mTextureId);
-        }
-    }
-
-    uint8_t* mTexture;
-    GLuint mTextureId;
-    uint16_t mWidth;
-    uint16_t mHeight;
-    bool mLinearFiltering;
-};
-
-class CacheTextureLine {
-public:
-    CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
-            uint32_t currentCol, CacheTexture* cacheTexture):
-                mMaxHeight(maxHeight),
-                mMaxWidth(maxWidth),
-                mCurrentRow(currentRow),
-                mCurrentCol(currentCol),
-                mDirty(false),
-                mCacheTexture(cacheTexture) {
-    }
-
-    bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
-
-    uint16_t mMaxHeight;
-    uint16_t mMaxWidth;
-    uint32_t mCurrentRow;
-    uint32_t mCurrentCol;
-    bool mDirty;
-    CacheTexture* mCacheTexture;
-};
-
-struct CachedGlyphInfo {
-    // Has the cache been invalidated?
-    bool mIsValid;
-    // Location of the cached glyph in the bitmap
-    // in case we need to resize the texture or
-    // render to bitmap
-    uint32_t mStartX;
-    uint32_t mStartY;
-    uint32_t mBitmapWidth;
-    uint32_t mBitmapHeight;
-    // Also cache texture coords for the quad
-    float mBitmapMinU;
-    float mBitmapMinV;
-    float mBitmapMaxU;
-    float mBitmapMaxV;
-    // Minimize how much we call freetype
-    uint32_t mGlyphIndex;
-    uint32_t mAdvanceX;
-    uint32_t mAdvanceY;
-    // Values below contain a glyph's origin in the bitmap
-    int32_t mBitmapLeft;
-    int32_t mBitmapTop;
-    // Auto-kerning
-    SkFixed mLsbDelta;
-    SkFixed mRsbDelta;
-    CacheTextureLine* mCachedTextureLine;
-};
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Font
-///////////////////////////////////////////////////////////////////////////////
-
-/**
- * Represents a font, defined by a Skia font id and a font size. A font is used
- * to generate glyphs and cache them in the FontState.
- */
-class Font {
-public:
-    enum Style {
-        kFakeBold = 1
-    };
-
-    ~Font();
-
-    /**
-     * Renders the specified string of text.
-     * If bitmap is specified, it will be used as the render target
-     */
-    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
-            int numGlyphs, int x, int y, uint8_t *bitmap = NULL,
-            uint32_t bitmapW = 0, uint32_t bitmapH = 0);
-
-    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
-            int numGlyphs, int x, int y, const float* positions);
-
-    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
-            int numGlyphs, SkPath* path, float hOffset, float vOffset);
-
-    /**
-     * Creates a new font associated with the specified font state.
-     */
-    static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
-            int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style,
-            uint32_t strokeWidth);
-
-protected:
-    friend class FontRenderer;
-    typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*,
-            uint32_t, uint32_t, Rect*, const float*);
-
-    enum RenderMode {
-        FRAMEBUFFER,
-        BITMAP,
-        MEASURE,
-    };
-
-    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
-            int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
-            uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions);
-
-    void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
-            int numGlyphs, Rect *bounds);
-
-    Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
-            uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
-
-    // Cache of glyphs
-    DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
-
-    void invalidateTextureCache(CacheTextureLine *cacheLine = NULL);
-
-    CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
-    void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph);
-
-    void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
-            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
-            Rect* bounds, const float* pos);
-    void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
-            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
-            Rect* bounds, const float* pos);
-    void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
-            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
-            Rect* bounds, const float* pos);
-    void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset,
-            SkPathMeasure& measure, SkPoint* position, SkVector* tangent);
-
-    CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
-
-    static glyph_t nextGlyph(const uint16_t** srcPtr) {
-        const uint16_t* src = *srcPtr;
-        glyph_t g = *src++;
-        *srcPtr = src;
-        return g;
-    }
-
-    FontRenderer* mState;
-    uint32_t mFontId;
-    float mFontSize;
-    int mFlags;
-    uint32_t mItalicStyle;
-    uint32_t mScaleX;
-    SkPaint::Style mStyle;
-    uint32_t mStrokeWidth;
-};
-
-///////////////////////////////////////////////////////////////////////////////
 // Renderer
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -245,6 +48,9 @@
     }
 
     void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
+
+    void precache(SkPaint* paint, const char* text, int numGlyphs);
+
     // bounds is an out parameter
     bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
             uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
@@ -274,42 +80,29 @@
     // After renderDropShadow returns, the called owns the memory in DropShadow.image
     // and is responsible for releasing it when it's done with it
     DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
-            uint32_t len, int numGlyphs, uint32_t radius);
+            uint32_t len, int numGlyphs, uint32_t radius, const float* positions);
 
     GLuint getTexture(bool linearFiltering = false) {
         checkInit();
 
-        if (linearFiltering != mCurrentCacheTexture->mLinearFiltering) {
-            mCurrentCacheTexture->mLinearFiltering = linearFiltering;
-            mLinearFiltering = linearFiltering;
-            const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
+        mCurrentCacheTexture->setLinearFiltering(linearFiltering);
+        mLinearFiltering = linearFiltering;
 
-            glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
-        }
-
-        return mCurrentCacheTexture->mTextureId;
+        return mCurrentCacheTexture->getTextureId();
     }
 
     uint32_t getCacheSize() const {
         uint32_t size = 0;
-        if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
-            size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
-        }
-        if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
-            size += mCacheTexture128->mWidth * mCacheTexture128->mHeight;
-        }
-        if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) {
-            size += mCacheTexture256->mWidth * mCacheTexture256->mHeight;
-        }
-        if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) {
-            size += mCacheTexture512->mWidth * mCacheTexture512->mHeight;
+        for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
+            CacheTexture* cacheTexture = mCacheTextures[i];
+            if (cacheTexture && cacheTexture->getTexture()) {
+                size += cacheTexture->getWidth() * cacheTexture->getHeight();
+            }
         }
         return size;
     }
 
-protected:
+private:
     friend class Font;
 
     const uint8_t* mGammaTable;
@@ -319,7 +112,8 @@
     void initTextTexture();
     CacheTexture* createCacheTexture(int width, int height, bool allocate);
     void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
-            uint32_t *retOriginX, uint32_t *retOriginY);
+            uint32_t *retOriginX, uint32_t *retOriginY, bool precaching);
+    CacheTexture* cacheBitmapInTexture(const SkGlyph& glyph, uint32_t* startX, uint32_t* startY);
 
     void flushAllAndInvalidate();
     void initVertexArrayBuffers();
@@ -328,8 +122,6 @@
     void initRender(const Rect* clip, Rect* bounds);
     void finishRender();
 
-    void precacheLatin(SkPaint* paint);
-
     void issueDrawCommand();
     void appendMeshQuadNoClip(float x1, float y1, float u1, float v1,
             float x2, float y2, float u2, float v2,
@@ -344,27 +136,31 @@
             float x3, float y3, float u3, float v3,
             float x4, float y4, float u4, float v4, CacheTexture* texture);
 
+    void removeFont(const Font* font);
+
+    void checkTextureUpdate();
+
+    void setTextureDirty() {
+        mUploadTexture = true;
+    }
+
     uint32_t mSmallCacheWidth;
     uint32_t mSmallCacheHeight;
+    uint32_t mLargeCacheWidth;
+    uint32_t mLargeCacheHeight;
 
-    Vector<CacheTextureLine*> mCacheLines;
-    uint32_t getRemainingCacheCapacity();
+    Vector<CacheTexture*> mCacheTextures;
 
     Font* mCurrentFont;
     Vector<Font*> mActiveFonts;
 
     CacheTexture* mCurrentCacheTexture;
     CacheTexture* mLastCacheTexture;
-    CacheTexture* mCacheTextureSmall;
-    CacheTexture* mCacheTexture128;
-    CacheTexture* mCacheTexture256;
-    CacheTexture* mCacheTexture512;
 
-    void checkTextureUpdate();
     bool mUploadTexture;
 
     // Pointer to vertex data to speed up frame to frame work
-    float *mTextMeshPtr;
+    float* mTextMesh;
     uint32_t mCurrentQuadIndex;
     uint32_t mMaxNumberOfQuads;
 
@@ -378,12 +174,13 @@
 
     bool mLinearFiltering;
 
-    void computeGaussianWeights(float* weights, int32_t radius);
-    void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
+    /** We should consider multi-threading this code or using Renderscript **/
+    static void computeGaussianWeights(float* weights, int32_t radius);
+    static void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
             int32_t width, int32_t height);
-    void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
+    static void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
             int32_t width, int32_t height);
-    void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
+    static void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
 };
 
 }; // namespace uirenderer
diff --git a/libs/hwui/GammaFontRenderer.cpp b/libs/hwui/GammaFontRenderer.cpp
index 1be957f..bd0a4b3 100644
--- a/libs/hwui/GammaFontRenderer.cpp
+++ b/libs/hwui/GammaFontRenderer.cpp
@@ -24,20 +24,46 @@
 namespace uirenderer {
 
 ///////////////////////////////////////////////////////////////////////////////
-// Constructors/destructor
+// Utils
 ///////////////////////////////////////////////////////////////////////////////
 
-GammaFontRenderer::GammaFontRenderer() {
-    INIT_LOGD("Creating gamma font renderer");
+static int luminance(const SkPaint* paint) {
+    uint32_t c = paint->getColor();
+    const int r = (c >> 16) & 0xFF;
+    const int g = (c >>  8) & 0xFF;
+    const int b = (c      ) & 0xFF;
+    return (r * 2 + g * 5 + b) >> 3;
+}
 
+///////////////////////////////////////////////////////////////////////////////
+// Base class GammaFontRenderer
+///////////////////////////////////////////////////////////////////////////////
+
+GammaFontRenderer* GammaFontRenderer::createRenderer() {
+    // Choose the best renderer
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get(PROPERTY_TEXT_GAMMA_METHOD, property, DEFAULT_TEXT_GAMMA_METHOD) > 0) {
+        if (!strcasecmp(property, "lookup")) {
+            return new LookupGammaFontRenderer();
+        } else if (!strcasecmp(property, "shader")) {
+            return new ShaderGammaFontRenderer(false);
+        } else if (!strcasecmp(property, "shader3")) {
+            return new ShaderGammaFontRenderer(true);
+        }
+    }
+
+    return new Lookup3GammaFontRenderer();
+}
+
+GammaFontRenderer::GammaFontRenderer() {
     // Get the renderer properties
     char property[PROPERTY_VALUE_MAX];
 
     // Get the gamma
-    float gamma = DEFAULT_TEXT_GAMMA;
+    mGamma = DEFAULT_TEXT_GAMMA;
     if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) {
         INIT_LOGD("  Setting text gamma to %s", property);
-        gamma = atof(property);
+        mGamma = atof(property);
     } else {
         INIT_LOGD("  Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA);
     }
@@ -61,18 +87,82 @@
         INIT_LOGD("  Using default white black gamma threshold of %d",
                 DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD);
     }
+}
+
+GammaFontRenderer::~GammaFontRenderer() {
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Shader-based renderer
+///////////////////////////////////////////////////////////////////////////////
+
+ShaderGammaFontRenderer::ShaderGammaFontRenderer(bool multiGamma): GammaFontRenderer() {
+    INIT_LOGD("Creating shader gamma font renderer");
+    mRenderer = NULL;
+    mMultiGamma = multiGamma;
+}
+
+void ShaderGammaFontRenderer::describe(ProgramDescription& description,
+        const SkPaint* paint) const {
+    if (paint->getShader() == NULL) {
+        if (mMultiGamma) {
+            const int l = luminance(paint);
+
+            if (l <= mBlackThreshold) {
+                description.hasGammaCorrection = true;
+                description.gamma = mGamma;
+            } else if (l >= mWhiteThreshold) {
+                description.hasGammaCorrection = true;
+                description.gamma = 1.0f / mGamma;
+            }
+        } else {
+            description.hasGammaCorrection = true;
+            description.gamma = 1.0f / mGamma;
+        }
+    }
+}
+
+void ShaderGammaFontRenderer::setupProgram(ProgramDescription& description,
+        Program* program) const {
+    if (description.hasGammaCorrection) {
+        glUniform1f(program->getUniform("gamma"), description.gamma);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Lookup-based renderer
+///////////////////////////////////////////////////////////////////////////////
+
+LookupGammaFontRenderer::LookupGammaFontRenderer(): GammaFontRenderer() {
+    INIT_LOGD("Creating lookup gamma font renderer");
 
     // Compute the gamma tables
-    const float blackGamma = gamma;
-    const float whiteGamma = 1.0f / gamma;
+    const float gamma = 1.0f / mGamma;
 
     for (uint32_t i = 0; i <= 255; i++) {
-        mGammaTable[i] = i;
+        mGammaTable[i] = uint8_t((float)::floor(pow(i / 255.0f, gamma) * 255.0f + 0.5f));
+    }
 
+    mRenderer = NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Lookup-based renderer, using 3 different correction tables
+///////////////////////////////////////////////////////////////////////////////
+
+Lookup3GammaFontRenderer::Lookup3GammaFontRenderer(): GammaFontRenderer() {
+    INIT_LOGD("Creating lookup3 gamma font renderer");
+
+    // Compute the gamma tables
+    const float blackGamma = mGamma;
+    const float whiteGamma = 1.0f / mGamma;
+
+    for (uint32_t i = 0; i <= 255; i++) {
         const float v = i / 255.0f;
         const float black = pow(v, blackGamma);
         const float white = pow(v, whiteGamma);
 
+        mGammaTable[i] = i;
         mGammaTable[256 + i] = uint8_t((float)::floor(black * 255.0f + 0.5f));
         mGammaTable[512 + i] = uint8_t((float)::floor(white * 255.0f + 0.5f));
     }
@@ -81,20 +171,20 @@
     memset(mRenderersUsageCount, 0, sizeof(uint32_t) * kGammaCount);
 }
 
-GammaFontRenderer::~GammaFontRenderer() {
+Lookup3GammaFontRenderer::~Lookup3GammaFontRenderer() {
     for (int i = 0; i < kGammaCount; i++) {
         delete mRenderers[i];
     }
 }
 
-void GammaFontRenderer::clear() {
+void Lookup3GammaFontRenderer::clear() {
     for (int i = 0; i < kGammaCount; i++) {
         delete mRenderers[i];
         mRenderers[i] = NULL;
     }
 }
 
-void GammaFontRenderer::flush() {
+void Lookup3GammaFontRenderer::flush() {
     int count = 0;
     int min = -1;
     uint32_t minCount = UINT_MAX;
@@ -122,7 +212,7 @@
     }
 }
 
-FontRenderer* GammaFontRenderer::getRenderer(Gamma gamma) {
+FontRenderer* Lookup3GammaFontRenderer::getRenderer(Gamma gamma) {
     FontRenderer* renderer = mRenderers[gamma];
     if (!renderer) {
         renderer = new FontRenderer();
@@ -133,17 +223,13 @@
     return renderer;
 }
 
-FontRenderer& GammaFontRenderer::getFontRenderer(const SkPaint* paint) {
+FontRenderer& Lookup3GammaFontRenderer::getFontRenderer(const SkPaint* paint) {
     if (paint->getShader() == NULL) {
-        uint32_t c = paint->getColor();
-        const int r = (c >> 16) & 0xFF;
-        const int g = (c >>  8) & 0xFF;
-        const int b = (c      ) & 0xFF;
-        const int luminance = (r * 2 + g * 5 + b) >> 3;
+        const int l = luminance(paint);
 
-        if (luminance <= mBlackThreshold) {
+        if (l <= mBlackThreshold) {
             return *getRenderer(kGammaBlack);
-        } else if (luminance >= mWhiteThreshold) {
+        } else if (l >= mWhiteThreshold) {
             return *getRenderer(kGammaWhite);
         }
     }
diff --git a/libs/hwui/GammaFontRenderer.h b/libs/hwui/GammaFontRenderer.h
index 99f08f0..5c1860e 100644
--- a/libs/hwui/GammaFontRenderer.h
+++ b/libs/hwui/GammaFontRenderer.h
@@ -20,20 +20,132 @@
 #include <SkPaint.h>
 
 #include "FontRenderer.h"
+#include "Program.h"
 
 namespace android {
 namespace uirenderer {
 
-struct GammaFontRenderer {
-    GammaFontRenderer();
-    ~GammaFontRenderer();
+class GammaFontRenderer {
+public:
+    virtual ~GammaFontRenderer();
 
-    enum Gamma {
-        kGammaDefault = 0,
-        kGammaBlack = 1,
-        kGammaWhite = 2,
-        kGammaCount = 3
-    };
+    virtual void clear() = 0;
+    virtual void flush() = 0;
+
+    virtual FontRenderer& getFontRenderer(const SkPaint* paint) = 0;
+
+    virtual uint32_t getFontRendererCount() const = 0;
+    virtual uint32_t getFontRendererSize(uint32_t fontRenderer) const = 0;
+
+    virtual void describe(ProgramDescription& description, const SkPaint* paint) const = 0;
+    virtual void setupProgram(ProgramDescription& description, Program* program) const = 0;
+
+    static GammaFontRenderer* createRenderer();
+
+protected:
+    GammaFontRenderer();
+
+    int mBlackThreshold;
+    int mWhiteThreshold;
+
+    float mGamma;
+};
+
+class ShaderGammaFontRenderer: public GammaFontRenderer {
+public:
+    ~ShaderGammaFontRenderer() {
+        delete mRenderer;
+    }
+
+    void clear() {
+        delete mRenderer;
+        mRenderer = NULL;
+    }
+
+    void flush() {
+        if (mRenderer) {
+            mRenderer->flushLargeCaches();
+        }
+    }
+
+    FontRenderer& getFontRenderer(const SkPaint* paint) {
+        if (!mRenderer) {
+            mRenderer = new FontRenderer;
+        }
+        return *mRenderer;
+    }
+
+    uint32_t getFontRendererCount() const {
+        return 1;
+    }
+
+    uint32_t getFontRendererSize(uint32_t fontRenderer) const {
+        return mRenderer ? mRenderer->getCacheSize() : 0;
+    }
+
+    void describe(ProgramDescription& description, const SkPaint* paint) const;
+    void setupProgram(ProgramDescription& description, Program* program) const;
+
+private:
+    ShaderGammaFontRenderer(bool multiGamma);
+
+    FontRenderer* mRenderer;
+    bool mMultiGamma;
+
+    friend class GammaFontRenderer;
+};
+
+class LookupGammaFontRenderer: public GammaFontRenderer {
+public:
+    ~LookupGammaFontRenderer() {
+        delete mRenderer;
+    }
+
+    void clear() {
+        delete mRenderer;
+        mRenderer = NULL;
+    }
+
+    void flush() {
+        if (mRenderer) {
+            mRenderer->flushLargeCaches();
+        }
+    }
+
+    FontRenderer& getFontRenderer(const SkPaint* paint) {
+        if (!mRenderer) {
+            mRenderer = new FontRenderer;
+            mRenderer->setGammaTable(&mGammaTable[0]);
+        }
+        return *mRenderer;
+    }
+
+    uint32_t getFontRendererCount() const {
+        return 1;
+    }
+
+    uint32_t getFontRendererSize(uint32_t fontRenderer) const {
+        return mRenderer ? mRenderer->getCacheSize() : 0;
+    }
+
+    void describe(ProgramDescription& description, const SkPaint* paint) const {
+    }
+
+    void setupProgram(ProgramDescription& description, Program* program) const {
+    }
+
+private:
+    LookupGammaFontRenderer();
+
+    FontRenderer* mRenderer;
+    uint8_t mGammaTable[256];
+
+    friend class GammaFontRenderer;
+};
+
+class Lookup3GammaFontRenderer: public GammaFontRenderer {
+public:
+    ~Lookup3GammaFontRenderer();
 
     void clear();
     void flush();
@@ -53,16 +165,30 @@
         return renderer->getCacheSize();
     }
 
+    void describe(ProgramDescription& description, const SkPaint* paint) const {
+    }
+
+    void setupProgram(ProgramDescription& description, Program* program) const {
+    }
+
 private:
+    Lookup3GammaFontRenderer();
+
+    enum Gamma {
+        kGammaDefault = 0,
+        kGammaBlack = 1,
+        kGammaWhite = 2,
+        kGammaCount = 3
+    };
+
     FontRenderer* getRenderer(Gamma gamma);
 
     uint32_t mRenderersUsageCount[kGammaCount];
     FontRenderer* mRenderers[kGammaCount];
 
-    int mBlackThreshold;
-    int mWhiteThreshold;
-
     uint8_t mGammaTable[256 * kGammaCount];
+
+    friend class GammaFontRenderer;
 };
 
 }; // namespace uirenderer
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 3678788..2e4e349 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -16,13 +16,9 @@
 
 #define LOG_TAG "OpenGLRenderer"
 
-#include <GLES2/gl2.h>
-
-#include <SkCanvas.h>
-#include <SkGradientShader.h>
-
 #include <utils/threads.h>
 
+#include "Caches.h"
 #include "Debug.h"
 #include "GradientCache.h"
 #include "Properties.h"
@@ -31,6 +27,22 @@
 namespace uirenderer {
 
 ///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+#define GRADIENT_TEXTURE_HEIGHT 2
+#define GRADIENT_BYTES_PER_PIXEL 4
+
+///////////////////////////////////////////////////////////////////////////////
+// Functions
+///////////////////////////////////////////////////////////////////////////////
+
+template<typename T>
+static inline T min(T a, T b) {
+    return a < b ? a : b;
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // Constructors/destructor
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -45,6 +57,8 @@
         INIT_LOGD("  Using default gradient cache size of %.2fMB", DEFAULT_GRADIENT_CACHE_SIZE);
     }
 
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
+
     mCache.setOnEntryRemovedListener(this);
 }
 
@@ -83,7 +97,7 @@
 
 void GradientCache::operator()(GradientCacheEntry& shader, Texture*& texture) {
     if (texture) {
-        const uint32_t size = texture->width * texture->height * 4;
+        const uint32_t size = texture->width * texture->height * GRADIENT_BYTES_PER_PIXEL;
         mSize -= size;
     }
 
@@ -97,14 +111,13 @@
 // Caching
 ///////////////////////////////////////////////////////////////////////////////
 
-Texture* GradientCache::get(uint32_t* colors, float* positions,
-        int count, SkShader::TileMode tileMode) {
+Texture* GradientCache::get(uint32_t* colors, float* positions, int count) {
 
-    GradientCacheEntry gradient(colors, positions, count, tileMode);
+    GradientCacheEntry gradient(colors, positions, count);
     Texture* texture = mCache.get(gradient);
 
     if (!texture) {
-        texture = addLinearGradient(gradient, colors, positions, count, tileMode);
+        texture = addLinearGradient(gradient, colors, positions, count);
     }
 
     return texture;
@@ -114,36 +127,45 @@
     mCache.clear();
 }
 
+void GradientCache::getGradientInfo(const uint32_t* colors, const int count,
+        GradientInfo& info) {
+    uint32_t width = 256 * (count - 1);
+
+    if (!Caches::getInstance().extensions.hasNPot()) {
+        width = 1 << (31 - __builtin_clz(width));
+    }
+
+    bool hasAlpha = false;
+    for (int i = 0; i < count; i++) {
+        if (((colors[i] >> 24) & 0xff) < 255) {
+            hasAlpha = true;
+            break;
+        }
+    }
+
+    info.width = min(width, uint32_t(mMaxTextureSize));
+    info.hasAlpha = hasAlpha;
+}
+
 Texture* GradientCache::addLinearGradient(GradientCacheEntry& gradient,
-        uint32_t* colors, float* positions, int count, SkShader::TileMode tileMode) {
-    SkBitmap bitmap;
-    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1024, 1);
-    bitmap.allocPixels();
-    bitmap.eraseColor(0);
+        uint32_t* colors, float* positions, int count) {
 
-    SkCanvas canvas(bitmap);
+    GradientInfo info;
+    getGradientInfo(colors, count, info);
 
-    SkPoint points[2];
-    points[0].set(0.0f, 0.0f);
-    points[1].set(bitmap.width(), 0.0f);
-
-    SkShader* localShader = SkGradientShader::CreateLinear(points,
-            reinterpret_cast<const SkColor*>(colors), positions, count, tileMode);
-
-    SkPaint p;
-    p.setStyle(SkPaint::kStrokeAndFill_Style);
-    p.setShader(localShader)->unref();
-
-    canvas.drawRectCoords(0.0f, 0.0f, bitmap.width(), 1.0f, p);
+    Texture* texture = new Texture;
+    texture->width = info.width;
+    texture->height = GRADIENT_TEXTURE_HEIGHT;
+    texture->blend = info.hasAlpha;
+    texture->generation = 1;
 
     // Asume the cache is always big enough
-    const uint32_t size = bitmap.rowBytes() * bitmap.height();
+    const uint32_t size = texture->width * texture->height * GRADIENT_BYTES_PER_PIXEL;
     while (mSize + size > mMaxSize) {
         mCache.removeOldest();
     }
 
-    Texture* texture = new Texture;
-    generateTexture(&bitmap, texture);
+    generateTexture(colors, positions, count, texture);
 
     mSize += size;
     mCache.put(gradient, texture);
@@ -151,25 +173,69 @@
     return texture;
 }
 
-void GradientCache::generateTexture(SkBitmap* bitmap, Texture* texture) {
-    SkAutoLockPixels autoLock(*bitmap);
-    if (!bitmap->readyToDraw()) {
-        ALOGE("Cannot generate texture from shader");
-        return;
+void GradientCache::generateTexture(uint32_t* colors, float* positions,
+        int count, Texture* texture) {
+
+    const uint32_t width = texture->width;
+    const GLsizei rowBytes = width * GRADIENT_BYTES_PER_PIXEL;
+    uint32_t pixels[width * texture->height];
+
+    int currentPos = 1;
+
+    float startA = (colors[0] >> 24) & 0xff;
+    float startR = (colors[0] >> 16) & 0xff;
+    float startG = (colors[0] >>  8) & 0xff;
+    float startB = (colors[0] >>  0) & 0xff;
+
+    float endA = (colors[1] >> 24) & 0xff;
+    float endR = (colors[1] >> 16) & 0xff;
+    float endG = (colors[1] >>  8) & 0xff;
+    float endB = (colors[1] >>  0) & 0xff;
+
+    float start = positions[0];
+    float distance = positions[1] - start;
+
+    uint8_t* p = (uint8_t*) pixels;
+    for (uint32_t x = 0; x < width; x++) {
+        float pos = x / float(width - 1);
+        if (pos > positions[currentPos]) {
+            startA = endA;
+            startR = endR;
+            startG = endG;
+            startB = endB;
+            start = positions[currentPos];
+
+            currentPos++;
+
+            endA = (colors[currentPos] >> 24) & 0xff;
+            endR = (colors[currentPos] >> 16) & 0xff;
+            endG = (colors[currentPos] >>  8) & 0xff;
+            endB = (colors[currentPos] >>  0) & 0xff;
+            distance = positions[currentPos] - start;
+        }
+
+        float amount = (pos - start) / distance;
+        float oppAmount = 1.0f - amount;
+
+        const float alpha = startA * oppAmount + endA * amount;
+        const float a = alpha / 255.0f;
+        *p++ = uint8_t(a * (startR * oppAmount + endR * amount));
+        *p++ = uint8_t(a * (startG * oppAmount + endG * amount));
+        *p++ = uint8_t(a * (startB * oppAmount + endB * amount));
+        *p++ = uint8_t(alpha);
     }
 
-    texture->generation = bitmap->getGenerationID();
-    texture->width = bitmap->width();
-    texture->height = bitmap->height();
+    for (int i = 1; i < GRADIENT_TEXTURE_HEIGHT; i++) {
+        memcpy(pixels + width * i, pixels, rowBytes);
+    }
 
     glGenTextures(1, &texture->id);
 
     glBindTexture(GL_TEXTURE_2D, texture->id);
-    glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel());
+    glPixelStorei(GL_UNPACK_ALIGNMENT, GRADIENT_BYTES_PER_PIXEL);
 
-    texture->blend = !bitmap->isOpaque();
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height, 0,
-            GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, texture->height, 0,
+            GL_RGBA, GL_UNSIGNED_BYTE, pixels);
 
     texture->setFilter(GL_LINEAR);
     texture->setWrap(GL_CLAMP_TO_EDGE);
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index ac34684..3b7c1fa 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_HWUI_GRADIENT_CACHE_H
 #define ANDROID_HWUI_GRADIENT_CACHE_H
 
+#include <GLES2/gl2.h>
+
 #include <SkShader.h>
 
 #include <utils/Mutex.h>
@@ -34,16 +36,14 @@
         count = 0;
         colors = NULL;
         positions = NULL;
-        tileMode = SkShader::kClamp_TileMode;
     }
 
-    GradientCacheEntry(uint32_t* colors, float* positions, int count,
-            SkShader::TileMode tileMode) {
-        copy(colors, positions, count, tileMode);
+    GradientCacheEntry(uint32_t* colors, float* positions, int count) {
+        copy(colors, positions, count);
     }
 
     GradientCacheEntry(const GradientCacheEntry& entry) {
-        copy(entry.colors, entry.positions, entry.count, entry.tileMode);
+        copy(entry.colors, entry.positions, entry.count);
     }
 
     ~GradientCacheEntry() {
@@ -56,7 +56,7 @@
             delete[] colors;
             delete[] positions;
 
-            copy(entry.colors, entry.positions, entry.count, entry.tileMode);
+            copy(entry.colors, entry.positions, entry.count);
         }
 
         return *this;
@@ -65,13 +65,11 @@
     bool operator<(const GradientCacheEntry& r) const {
         const GradientCacheEntry& rhs = (const GradientCacheEntry&) r;
         LTE_INT(count) {
-            LTE_INT(tileMode) {
-                int result = memcmp(colors, rhs.colors, count * sizeof(uint32_t));
-                if (result< 0) return true;
-                else if (result == 0) {
-                    result = memcmp(positions, rhs.positions, count * sizeof(float));
-                    if (result < 0) return true;
-                }
+            int result = memcmp(colors, rhs.colors, count * sizeof(uint32_t));
+            if (result< 0) return true;
+            else if (result == 0) {
+                result = memcmp(positions, rhs.positions, count * sizeof(float));
+                if (result < 0) return true;
             }
         }
         return false;
@@ -84,11 +82,10 @@
 
 private:
 
-    void copy(uint32_t* colors, float* positions, int count, SkShader::TileMode tileMode) {
+    void copy(uint32_t* colors, float* positions, int count) {
         this->count = count;
         this->colors = new uint32_t[count];
         this->positions = new float[count];
-        this->tileMode = tileMode;
 
         memcpy(this->colors, colors, count * sizeof(uint32_t));
         memcpy(this->positions, positions, count * sizeof(float));
@@ -116,8 +113,8 @@
     /**
      * Returns the texture associated with the specified shader.
      */
-    Texture* get(uint32_t* colors, float* positions,
-            int count, SkShader::TileMode tileMode = SkShader::kClamp_TileMode);
+    Texture* get(uint32_t* colors, float* positions, int count);
+
     /**
      * Clears the cache. This causes all textures to be deleted.
      */
@@ -142,16 +139,24 @@
      * returned.
      */
     Texture* addLinearGradient(GradientCacheEntry& gradient,
-            uint32_t* colors, float* positions, int count,
-            SkShader::TileMode tileMode = SkShader::kClamp_TileMode);
+            uint32_t* colors, float* positions, int count);
 
-    void generateTexture(SkBitmap* bitmap, Texture* texture);
+    void generateTexture(uint32_t* colors, float* positions, int count, Texture* texture);
+
+    struct GradientInfo {
+        uint32_t width;
+        bool hasAlpha;
+    };
+
+    void getGradientInfo(const uint32_t* colors, const int count, GradientInfo& info);
 
     GenerationCache<GradientCacheEntry, Texture*> mCache;
 
     uint32_t mSize;
     uint32_t mMaxSize;
 
+    GLint mMaxTextureSize;
+
     Vector<SkShader*> mGarbage;
     mutable Mutex mLock;
 }; // class GradientCache
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
new file mode 100644
index 0000000..1cdc063
--- /dev/null
+++ b/libs/hwui/Layer.cpp
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+
+#include <utils/Log.h>
+
+#include "Layer.h"
+#include "LayerRenderer.h"
+#include "OpenGLRenderer.h"
+#include "Caches.h"
+
+namespace android {
+namespace uirenderer {
+
+Layer::Layer(const uint32_t layerWidth, const uint32_t layerHeight) {
+    mesh = NULL;
+    meshIndices = NULL;
+    meshElementCount = 0;
+    cacheable = true;
+    dirty = false;
+    textureLayer = false;
+    renderTarget = GL_TEXTURE_2D;
+    texture.width = layerWidth;
+    texture.height = layerHeight;
+    colorFilter = NULL;
+    deferredUpdateScheduled = false;
+    renderer = NULL;
+    displayList = NULL;
+    fbo = 0;
+    Caches::getInstance().resourceCache.incrementRefcount(this);
+}
+
+Layer::~Layer() {
+    if (mesh) delete mesh;
+    if (meshIndices) delete meshIndices;
+    if (colorFilter) Caches::getInstance().resourceCache.decrementRefcount(colorFilter);
+    removeFbo();
+    deleteTexture();
+}
+
+void Layer::removeFbo() {
+    if (fbo) {
+        LayerRenderer::flushLayer(this);
+        Caches::getInstance().fboCache.put(fbo);
+        fbo = 0;
+    }
+}
+
+void Layer::setPaint(SkPaint* paint) {
+    OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
+}
+
+void Layer::setColorFilter(SkiaColorFilter* filter) {
+    if (colorFilter) {
+        Caches::getInstance().resourceCache.decrementRefcount(colorFilter);
+    }
+    colorFilter = filter;
+    if (colorFilter) {
+        Caches::getInstance().resourceCache.incrementRefcount(colorFilter);
+    }
+}
+
+
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index f243177..e1f6a70 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -45,25 +45,10 @@
  * A layer has dimensions and is backed by an OpenGL texture or FBO.
  */
 struct Layer {
-    Layer(const uint32_t layerWidth, const uint32_t layerHeight) {
-        mesh = NULL;
-        meshIndices = NULL;
-        meshElementCount = 0;
-        cacheable = true;
-        textureLayer = false;
-        renderTarget = GL_TEXTURE_2D;
-        texture.width = layerWidth;
-        texture.height = layerHeight;
-        colorFilter = NULL;
-        deferredUpdateScheduled = false;
-        renderer = NULL;
-        displayList = NULL;
-    }
+    Layer(const uint32_t layerWidth, const uint32_t layerHeight);
+    ~Layer();
 
-    ~Layer() {
-        if (mesh) delete mesh;
-        if (meshIndices) delete meshIndices;
-    }
+    void removeFbo();
 
     /**
      * Sets this layer's region to a rectangle. Computes the appropriate
@@ -106,6 +91,8 @@
         texture.height = height;
     }
 
+    ANDROID_API void setPaint(SkPaint* paint);
+
     inline void setBlend(bool blend) {
         texture.blend = blend;
     }
@@ -147,10 +134,6 @@
         return fbo;
     }
 
-    inline GLuint* getTexturePointer() {
-        return &texture.id;
-    }
-
     inline GLuint getTexture() {
         return texture.id;
     }
@@ -179,6 +162,14 @@
         this->cacheable = cacheable;
     }
 
+    inline bool isDirty() {
+        return dirty;
+    }
+
+    inline void setDirty(bool dirty) {
+        this->dirty = dirty;
+    }
+
     inline bool isTextureLayer() {
         return textureLayer;
     }
@@ -191,20 +182,34 @@
         return colorFilter;
     }
 
-    inline void setColorFilter(SkiaColorFilter* filter) {
-        colorFilter = filter;
-    }
+    ANDROID_API void setColorFilter(SkiaColorFilter* filter);
 
     inline void bindTexture() {
-        glBindTexture(renderTarget, texture.id);
+        if (texture.id) {
+            glBindTexture(renderTarget, texture.id);
+        }
     }
 
     inline void generateTexture() {
-        glGenTextures(1, &texture.id);
+        if (!texture.id) {
+            glGenTextures(1, &texture.id);
+        }
     }
 
     inline void deleteTexture() {
-        if (texture.id) glDeleteTextures(1, &texture.id);
+        if (texture.id) {
+            glDeleteTextures(1, &texture.id);
+            texture.id = 0;
+        }
+    }
+
+    /**
+     * When the caller frees the texture itself, the caller
+     * must call this method to tell this layer that it lost
+     * the texture.
+     */
+    void clearTexture() {
+        texture.id = 0;
     }
 
     inline void deleteFbo() {
@@ -212,6 +217,9 @@
     }
 
     inline void allocateTexture(GLenum format, GLenum storage) {
+#if DEBUG_LAYERS
+        ALOGD("  Allocate layer: %dx%d", getWidth(), getHeight());
+#endif
         glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL);
     }
 
@@ -287,6 +295,12 @@
     bool textureLayer;
 
     /**
+     * When set to true, this layer is dirty and should be cleared
+     * before any rendering occurs.
+     */
+    bool dirty;
+
+    /**
      * Indicates the render target.
      */
     GLenum renderTarget;
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index eea707e..ce74cee 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -69,15 +69,10 @@
 
 void LayerCache::deleteLayer(Layer* layer) {
     if (layer) {
-        GLuint fbo = layer->getFbo();
-        LAYER_LOGD("Destroying layer %dx%d, fbo %d", layer->getWidth(), layer->getHeight(), fbo);
-
+        LAYER_LOGD("Destroying layer %dx%d, fbo %d", layer->getWidth(), layer->getHeight(),
+                layer->getFbo());
         mSize -= layer->getWidth() * layer->getHeight() * 4;
-
-        if (fbo) Caches::getInstance().fboCache.put(fbo);
-        layer->deleteTexture();
-
-        delete layer;
+        Caches::getInstance().resourceCache.decrementRefcount(layer);
     }
 }
 
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 65f8c7c..3484d41 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -18,6 +18,8 @@
 
 #include <ui/Rect.h>
 
+#include <private/hwui/DrawGlInfo.h>
+
 #include "LayerCache.h"
 #include "LayerRenderer.h"
 #include "Matrix.h"
@@ -37,7 +39,12 @@
 LayerRenderer::~LayerRenderer() {
 }
 
-int LayerRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
+void LayerRenderer::setViewport(int width, int height) {
+    initViewport(width, height);
+}
+
+status_t LayerRenderer::prepareDirty(float left, float top, float right, float bottom,
+        bool opaque) {
     LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo());
 
     glBindFramebuffer(GL_FRAMEBUFFER, mLayer->getFbo());
@@ -45,7 +52,6 @@
     const float width = mLayer->layer.getWidth();
     const float height = mLayer->layer.getHeight();
 
-#if RENDER_LAYERS_AS_REGIONS
     Rect dirty(left, top, right, bottom);
     if (dirty.isEmpty() || (dirty.left <= 0 && dirty.top <= 0 &&
             dirty.right >= width && dirty.bottom >= height)) {
@@ -58,9 +64,20 @@
     }
 
     return OpenGLRenderer::prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, opaque);
-#else
-    return OpenGLRenderer::prepareDirty(0.0f, 0.0f, width, height, opaque);
-#endif
+}
+
+status_t LayerRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
+    if (mLayer->isDirty()) {
+        getCaches().disableScissor();
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        getCaches().resetScissor();
+        mLayer->setDirty(false);
+
+        return DrawGlInfo::kStatusDone;
+    }
+
+    return OpenGLRenderer::clear(left, top, right, bottom, opaque);
 }
 
 void LayerRenderer::finish() {
@@ -78,6 +95,10 @@
     return mLayer->getFbo();
 }
 
+bool LayerRenderer::suppressErrorChecks() {
+    return true;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // Dirty region tracking
 ///////////////////////////////////////////////////////////////////////////////
@@ -87,14 +108,10 @@
 }
 
 Region* LayerRenderer::getRegion() {
-#if RENDER_LAYERS_AS_REGIONS
     if (getSnapshot()->flags & Snapshot::kFlagFboTarget) {
         return OpenGLRenderer::getRegion();
     }
     return &mLayer->region;
-#else
-    return OpenGLRenderer::getRegion();
-#endif
 }
 
 // TODO: This implementation is flawed and can generate T-junctions
@@ -105,7 +122,6 @@
 //       In practice, T-junctions do not appear often so this has yet
 //       to be fixed.
 void LayerRenderer::generateMesh() {
-#if RENDER_LAYERS_AS_REGIONS
     if (mLayer->region.isRect() || mLayer->region.isEmpty()) {
         if (mLayer->mesh) {
             delete mLayer->mesh;
@@ -172,7 +188,6 @@
             indices[index + 5] = quad + 3;   // bottom-right
         }
     }
-#endif
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -203,6 +218,7 @@
     layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
     layer->setBlend(!isOpaque);
     layer->setColorFilter(NULL);
+    layer->setDirty(true);
     layer->region.clear();
 
     GLuint previousFbo;
@@ -221,10 +237,8 @@
                     fbo, width, height);
 
             glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-            caches.fboCache.put(fbo);
 
-            layer->deleteTexture();
-            delete layer;
+            Caches::getInstance().resourceCache.decrementRefcount(layer);
 
             return NULL;
         }
@@ -233,10 +247,6 @@
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
             layer->getTexture(), 0);
 
-    glDisable(GL_SCISSOR_TEST);
-    glClear(GL_COLOR_BUFFER_BIT);
-    glEnable(GL_SCISSOR_TEST);
-
     glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
 
     return layer;
@@ -251,8 +261,7 @@
             layer->texCoords.set(0.0f, height / float(layer->getHeight()),
                     width / float(layer->getWidth()), 0.0f);
         } else {
-            layer->deleteTexture();
-            delete layer;
+            Caches::getInstance().resourceCache.decrementRefcount(layer);
             return false;
         }
     }
@@ -305,22 +314,15 @@
         LAYER_RENDERER_LOGD("Recycling layer, %dx%d fbo = %d",
                 layer->getWidth(), layer->getHeight(), layer->getFbo());
 
-        GLuint fbo = layer->getFbo();
-        if (fbo) {
-            flushLayer(layer);
-            Caches::getInstance().fboCache.put(fbo);
-            layer->setFbo(0);
-        }
-
         if (!Caches::getInstance().layerCache.put(layer)) {
             LAYER_RENDERER_LOGD("  Destroyed!");
-            layer->deleteTexture();
-            delete layer;
+            Caches::getInstance().resourceCache.decrementRefcount(layer);
         } else {
             LAYER_RENDERER_LOGD("  Cached!");
 #if DEBUG_LAYER_RENDERER
             Caches::getInstance().layerCache.dump();
 #endif
+            layer->removeFbo();
             layer->region.clear();
         }
     }
@@ -343,10 +345,10 @@
         if (Caches::getInstance().extensions.hasDiscardFramebuffer()) {
             GLuint previousFbo;
             glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
-
-            GLenum attachments = GL_COLOR_ATTACHMENT0;
             if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, fbo);
-            glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachments);
+
+            const GLenum attachments[] = { GL_COLOR_ATTACHMENT0 };
+            glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, attachments);
 
             if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
         }
@@ -356,7 +358,7 @@
 
 bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) {
     Caches& caches = Caches::getInstance();
-    if (layer && layer->isTextureLayer() && bitmap->width() <= caches.maxTextureSize &&
+    if (layer && bitmap->width() <= caches.maxTextureSize &&
             bitmap->height() <= caches.maxTextureSize) {
 
         GLuint fbo = caches.fboCache.get();
@@ -369,6 +371,7 @@
 
         GLuint texture;
         GLuint previousFbo;
+        GLuint previousViewport[4];
 
         GLenum format;
         GLenum type;
@@ -398,11 +401,13 @@
 
         float alpha = layer->getAlpha();
         SkXfermode::Mode mode = layer->getMode();
+        GLuint previousLayerFbo = layer->getFbo();
 
         layer->setAlpha(255, SkXfermode::kSrc_Mode);
         layer->setFbo(fbo);
 
         glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
+        glGetIntegerv(GL_VIEWPORT, (GLint*) &previousViewport);
         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
 
         glGenTextures(1, &texture);
@@ -411,6 +416,8 @@
         caches.activeTexture(0);
         glBindTexture(GL_TEXTURE_2D, texture);
 
+        glPixelStorei(GL_PACK_ALIGNMENT, bitmap->bytesPerPixel());
+
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
@@ -431,7 +438,7 @@
             renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f,
                     bitmap->width(), bitmap->height(), !layer->isBlend());
 
-            glDisable(GL_SCISSOR_TEST);
+            caches.disableScissor();
             renderer.translate(0.0f, bitmap->height());
             renderer.scale(1.0f, -1.0f);
 
@@ -460,8 +467,6 @@
         }
 
 error:
-        glEnable(GL_SCISSOR_TEST);
-
 #if DEBUG_OPENGL
         if (error != GL_NO_ERROR) {
             ALOGD("GL error while copying layer into bitmap = 0x%x", error);
@@ -470,9 +475,11 @@
 
         glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
         layer->setAlpha(alpha, mode);
-        layer->setFbo(0);
+        layer->setFbo(previousLayerFbo);
         glDeleteTextures(1, &texture);
         caches.fboCache.put(fbo);
+        glViewport(previousViewport[0], previousViewport[1],
+                previousViewport[2], previousViewport[3]);
 
         return status;
     }
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index 8f3a0a3..c44abce 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -47,13 +47,11 @@
     ANDROID_API LayerRenderer(Layer* layer);
     virtual ~LayerRenderer();
 
-    virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
+    virtual void setViewport(int width, int height);
+    virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
+    virtual status_t clear(float left, float top, float right, float bottom, bool opaque);
     virtual void finish();
 
-    virtual bool hasLayer();
-    virtual Region* getRegion();
-    virtual GLint getTargetFbo();
-
     ANDROID_API static Layer* createTextureLayer(bool isOpaque);
     ANDROID_API static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false);
     ANDROID_API static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
@@ -61,9 +59,16 @@
             bool isOpaque, GLenum renderTarget, float* transform);
     ANDROID_API static void destroyLayer(Layer* layer);
     ANDROID_API static void destroyLayerDeferred(Layer* layer);
-    ANDROID_API static void flushLayer(Layer* layer);
     ANDROID_API static bool copyLayer(Layer* layer, SkBitmap* bitmap);
 
+    static void flushLayer(Layer* layer);
+
+protected:
+    virtual bool hasLayer();
+    virtual Region* getRegion();
+    virtual GLint getTargetFbo();
+    virtual bool suppressErrorChecks();
+
 private:
     void generateMesh();
 
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index 7348f4d..a924362 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -55,24 +55,29 @@
     mSimpleMatrix = true;
 }
 
-bool Matrix4::changesBounds() {
+bool Matrix4::changesBounds() const {
     return !(data[0] == 1.0f && data[1] == 0.0f && data[2] == 0.0f && data[4] == 0.0f &&
              data[5] == 1.0f && data[6] == 0.0f && data[8] == 0.0f && data[9] == 0.0f &&
              data[10] == 1.0f);
 }
 
-bool Matrix4::isPureTranslate() {
+bool Matrix4::isPureTranslate() const {
     return mSimpleMatrix && data[kScaleX] == 1.0f && data[kScaleY] == 1.0f;
 }
 
-bool Matrix4::isSimple() {
+bool Matrix4::isSimple() const {
     return mSimpleMatrix;
 }
 
-bool Matrix4::isIdentity() {
+bool Matrix4::isIdentity() const {
     return mIsIdentity;
 }
 
+bool Matrix4::isPerspective() const {
+    return data[kPerspective0] != 0.0f || data[kPerspective1] != 0.0f ||
+            data[kPerspective2] != 1.0f;
+}
+
 void Matrix4::load(const float* v) {
     memcpy(data, v, sizeof(data));
     // TODO: Do something smarter here
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index 22220a9..f86823d 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -112,11 +112,12 @@
         multiply(u);
     }
 
-    bool isPureTranslate();
-    bool isSimple();
-    bool isIdentity();
+    bool isPureTranslate() const;
+    bool isSimple() const;
+    bool isIdentity() const;
+    bool isPerspective() const;
 
-    bool changesBounds();
+    bool changesBounds() const;
 
     void copyTo(float* v) const;
     void copyTo(SkMatrix& v) const;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 9a90bfd..6787705 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -33,6 +33,8 @@
 
 #include "OpenGLRenderer.h"
 #include "DisplayListRenderer.h"
+#include "PathRenderer.h"
+#include "Properties.h"
 #include "Vector.h"
 
 namespace android {
@@ -45,10 +47,9 @@
 #define RAD_TO_DEG (180.0f / 3.14159265f)
 #define MIN_ANGLE 0.001f
 
-// TODO: This should be set in properties
-#define ALPHA_THRESHOLD (0x7f / PANEL_BIT_DEPTH)
+#define ALPHA_THRESHOLD 0
 
-#define FILTER(paint) (paint && paint->isFilterBitmap() ? GL_LINEAR : GL_NEAREST)
+#define FILTER(paint) (!paint || paint->isFilterBitmap() ? GL_LINEAR : GL_NEAREST)
 
 ///////////////////////////////////////////////////////////////////////////////
 // Globals
@@ -117,6 +118,8 @@
     memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
 
     mFirstSnapshot = new Snapshot;
+
+    mScissorOptimizationDisabled = false;
 }
 
 OpenGLRenderer::~OpenGLRenderer() {
@@ -124,31 +127,35 @@
     // GL APIs. All GL state should be kept in Caches.h
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// Debug
-///////////////////////////////////////////////////////////////////////////////
-
-void OpenGLRenderer::startMark(const char* name) const {
-    mCaches.startMark(0, name);
-}
-
-void OpenGLRenderer::endMark() const {
-    mCaches.endMark();
+void OpenGLRenderer::initProperties() {
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get(PROPERTY_DISABLE_SCISSOR_OPTIMIZATION, property, "false")) {
+        mScissorOptimizationDisabled = !strcasecmp(property, "true");
+        INIT_LOGD("  Scissor optimization %s",
+                mScissorOptimizationDisabled ? "disabled" : "enabled");
+    } else {
+        INIT_LOGD("  Scissor optimization enabled");
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // Setup
 ///////////////////////////////////////////////////////////////////////////////
 
-uint32_t OpenGLRenderer::getStencilSize() {
-    return STENCIL_BUFFER_SIZE;
-}
-
 bool OpenGLRenderer::isDeferred() {
     return false;
 }
 
 void OpenGLRenderer::setViewport(int width, int height) {
+    initViewport(width, height);
+
+    glDisable(GL_DITHER);
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+    glEnableVertexAttribArray(Program::kBindingPosition);
+}
+
+void OpenGLRenderer::initViewport(int width, int height) {
     mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
 
     mWidth = width;
@@ -156,19 +163,14 @@
 
     mFirstSnapshot->height = height;
     mFirstSnapshot->viewport.set(0, 0, width, height);
-
-    glDisable(GL_DITHER);
-    glEnable(GL_SCISSOR_TEST);
-    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-
-    glEnableVertexAttribArray(Program::kBindingPosition);
 }
 
-int OpenGLRenderer::prepare(bool opaque) {
+status_t OpenGLRenderer::prepare(bool opaque) {
     return prepareDirty(0.0f, 0.0f, mWidth, mHeight, opaque);
 }
 
-int OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
+status_t OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom,
+        bool opaque) {
     mCaches.clearGarbage();
 
     mSnapshot = new Snapshot(mFirstSnapshot,
@@ -177,18 +179,43 @@
     mSaveCount = 1;
 
     mSnapshot->setClip(left, top, right, bottom);
-    mDirtyClip = opaque;
+    mDirtyClip = true;
+
+    updateLayers();
+
+    // If we know that we are going to redraw the entire framebuffer,
+    // perform a discard to let the driver know we don't need to preserve
+    // the back buffer for this frame.
+    if (mCaches.extensions.hasDiscardFramebuffer() &&
+            left <= 0.0f && top <= 0.0f && right >= mWidth && bottom >= mHeight) {
+        const GLenum attachments[] = { getTargetFbo() == 0 ? GL_COLOR_EXT : GL_COLOR_ATTACHMENT0 };
+        glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, attachments);
+    }
 
     syncState();
 
+    // Functors break the tiling extension in pretty spectacular ways
+    // This ensures we don't use tiling when a functor is going to be
+    // invoked during the frame
+    mSuppressTiling = mCaches.hasRegisteredFunctors();
+
+    mTilingSnapshot = mSnapshot;
+    startTiling(mTilingSnapshot, true);
+
+    debugOverdraw(true, true);
+
+    return clear(left, top, right, bottom, opaque);
+}
+
+status_t OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
     if (!opaque) {
+        mCaches.enableScissor();
         mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
         glClear(GL_COLOR_BUFFER_BIT);
         return DrawGlInfo::kStatusDrew;
-    } else {
-        mCaches.resetScissor();
     }
 
+    mCaches.resetScissor();
     return DrawGlInfo::kStatusDone;
 }
 
@@ -202,34 +229,56 @@
     }
 }
 
-void OpenGLRenderer::finish() {
-#if DEBUG_OPENGL
-    GLenum status = GL_NO_ERROR;
-    while ((status = glGetError()) != GL_NO_ERROR) {
-        ALOGD("GL error from OpenGLRenderer: 0x%x", status);
-        switch (status) {
-            case GL_INVALID_ENUM:
-                ALOGE("  GL_INVALID_ENUM");
-                break;
-            case GL_INVALID_VALUE:
-                ALOGE("  GL_INVALID_VALUE");
-                break;
-            case GL_INVALID_OPERATION:
-                ALOGE("  GL_INVALID_OPERATION");
-                break;
-            case GL_OUT_OF_MEMORY:
-                ALOGE("  Out of memory!");
-                break;
+void OpenGLRenderer::startTiling(const sp<Snapshot>& s, bool opaque) {
+    if (!mSuppressTiling) {
+        Rect* clip = mTilingSnapshot->clipRect;
+        if (s->flags & Snapshot::kFlagIsFboLayer) {
+            clip = s->clipRect;
         }
+
+        mCaches.startTiling(clip->left, s->height - clip->bottom,
+                clip->right - clip->left, clip->bottom - clip->top, opaque);
     }
+}
+
+void OpenGLRenderer::endTiling() {
+    if (!mSuppressTiling) mCaches.endTiling();
+}
+
+void OpenGLRenderer::finish() {
+    renderOverdraw();
+    endTiling();
+
+    if (!suppressErrorChecks()) {
+#if DEBUG_OPENGL
+        GLenum status = GL_NO_ERROR;
+        while ((status = glGetError()) != GL_NO_ERROR) {
+            ALOGD("GL error from OpenGLRenderer: 0x%x", status);
+            switch (status) {
+                case GL_INVALID_ENUM:
+                    ALOGE("  GL_INVALID_ENUM");
+                    break;
+                case GL_INVALID_VALUE:
+                    ALOGE("  GL_INVALID_VALUE");
+                    break;
+                case GL_INVALID_OPERATION:
+                    ALOGE("  GL_INVALID_OPERATION");
+                    break;
+                case GL_OUT_OF_MEMORY:
+                    ALOGE("  Out of memory!");
+                    break;
+            }
+        }
 #endif
+
 #if DEBUG_MEMORY_USAGE
-    mCaches.dumpMemoryUsage();
-#else
-    if (mCaches.getDebugLevel() & kDebugMemory) {
         mCaches.dumpMemoryUsage();
-    }
+#else
+        if (mCaches.getDebugLevel() & kDebugMemory) {
+            mCaches.dumpMemoryUsage();
+        }
 #endif
+    }
 }
 
 void OpenGLRenderer::interrupt() {
@@ -243,20 +292,23 @@
     mCaches.unbindIndicesBuffer();
     mCaches.resetVertexPointers();
     mCaches.disbaleTexCoordsVertexArray();
+    debugOverdraw(false, false);
 }
 
 void OpenGLRenderer::resume() {
     sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
-
     glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
+    glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
+    debugOverdraw(true, false);
+
     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
-    glEnable(GL_SCISSOR_TEST);
+    mCaches.scissorEnabled = glIsEnabled(GL_SCISSOR_TEST);
+    mCaches.enableScissor();
     mCaches.resetScissor();
     dirtyClip();
 
     mCaches.activeTexture(0);
-    glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
 
     mCaches.blend = true;
     glEnable(GL_BLEND);
@@ -264,6 +316,16 @@
     glBlendEquation(GL_FUNC_ADD);
 }
 
+void OpenGLRenderer::resumeAfterLayer() {
+    sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
+    glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
+    glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
+    debugOverdraw(true, false);
+
+    mCaches.resetScissor();
+    dirtyClip();
+}
+
 void OpenGLRenderer::detachFunctor(Functor* functor) {
     mFunctors.remove(functor);
 }
@@ -303,10 +365,12 @@
                 mFunctors.add(f);
             }
         }
+        // protect against functors binding to other buffers
+        mCaches.unbindMeshBuffer();
+        mCaches.unbindIndicesBuffer();
+        mCaches.activeTexture(0);
     }
 
-    mCaches.activeTexture(0);
-
     return result;
 }
 
@@ -314,6 +378,7 @@
     interrupt();
     detachFunctor(functor);
 
+    mCaches.enableScissor();
     if (mDirtyClip) {
         setScissorFromClip();
     }
@@ -321,13 +386,11 @@
     Rect clip(*mSnapshot->clipRect);
     clip.snapToPixelBoundaries();
 
-#if RENDER_LAYERS_AS_REGIONS
     // Since we don't know what the functor will draw, let's dirty
     // tne entire clip region
     if (hasLayer()) {
         dirtyLayerUnchecked(clip, getRegion());
     }
-#endif
 
     DrawGlInfo info;
     info.clipLeft = clip.left;
@@ -355,6 +418,124 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// Debug
+///////////////////////////////////////////////////////////////////////////////
+
+void OpenGLRenderer::startMark(const char* name) const {
+    mCaches.startMark(0, name);
+}
+
+void OpenGLRenderer::endMark() const {
+    mCaches.endMark();
+}
+
+void OpenGLRenderer::debugOverdraw(bool enable, bool clear) {
+    if (mCaches.debugOverdraw && getTargetFbo() == 0) {
+        if (clear) {
+            mCaches.disableScissor();
+            mCaches.stencil.clear();
+        }
+        if (enable) {
+            mCaches.stencil.enableDebugWrite();
+        } else {
+            mCaches.stencil.disable();
+        }
+    }
+}
+
+void OpenGLRenderer::renderOverdraw() {
+    if (mCaches.debugOverdraw && getTargetFbo() == 0) {
+        const Rect* clip = mTilingSnapshot->clipRect;
+
+        mCaches.enableScissor();
+        mCaches.setScissor(clip->left, mTilingSnapshot->height - clip->bottom,
+                clip->right - clip->left, clip->bottom - clip->top);
+
+        mCaches.stencil.enableDebugTest(2);
+        drawColor(0x2f0000ff, SkXfermode::kSrcOver_Mode);
+        mCaches.stencil.enableDebugTest(3);
+        drawColor(0x2f00ff00, SkXfermode::kSrcOver_Mode);
+        mCaches.stencil.enableDebugTest(4);
+        drawColor(0x3fff0000, SkXfermode::kSrcOver_Mode);
+        mCaches.stencil.enableDebugTest(4, true);
+        drawColor(0x7fff0000, SkXfermode::kSrcOver_Mode);
+        mCaches.stencil.disable();
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Layers
+///////////////////////////////////////////////////////////////////////////////
+
+bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
+    if (layer->deferredUpdateScheduled && layer->renderer && layer->displayList) {
+        OpenGLRenderer* renderer = layer->renderer;
+        Rect& dirty = layer->dirtyRect;
+
+        if (inFrame) {
+            endTiling();
+            debugOverdraw(false, false);
+        }
+
+        renderer->setViewport(layer->layer.getWidth(), layer->layer.getHeight());
+        renderer->prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, !layer->isBlend());
+        renderer->drawDisplayList(layer->displayList, dirty, DisplayList::kReplayFlag_ClipChildren);
+        renderer->finish();
+
+        if (inFrame) {
+            resumeAfterLayer();
+            startTiling(mSnapshot);
+        }
+
+        dirty.setEmpty();
+        layer->deferredUpdateScheduled = false;
+        layer->renderer = NULL;
+        layer->displayList = NULL;
+
+        return true;
+    }
+
+    return false;
+}
+
+void OpenGLRenderer::updateLayers() {
+    int count = mLayerUpdates.size();
+    if (count > 0) {
+        startMark("Layer Updates");
+
+        // Note: it is very important to update the layers in reverse order
+        for (int i = count - 1; i >= 0; i--) {
+            Layer* layer = mLayerUpdates.itemAt(i);
+            updateLayer(layer, false);
+            mCaches.resourceCache.decrementRefcount(layer);
+        }
+        mLayerUpdates.clear();
+
+        glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo());
+        endMark();
+    }
+}
+
+void OpenGLRenderer::pushLayerUpdate(Layer* layer) {
+    if (layer) {
+        mLayerUpdates.push_back(layer);
+        mCaches.resourceCache.incrementRefcount(layer);
+    }
+}
+
+void OpenGLRenderer::clearLayerUpdates() {
+    size_t count = mLayerUpdates.size();
+    if (count > 0) {
+        mCaches.resourceCache.lock();
+        for (size_t i = 0; i < count; i++) {
+            mCaches.resourceCache.decrementRefcountLocked(mLayerUpdates.itemAt(i));
+        }
+        mCaches.resourceCache.unlock();
+        mLayerUpdates.clear();
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // State management
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -428,20 +609,12 @@
 
         if (p) {
             alpha = p->getAlpha();
-            if (!mCaches.extensions.hasFramebufferFetch()) {
-                const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode);
-                if (!isMode) {
-                    // Assume SRC_OVER
-                    mode = SkXfermode::kSrcOver_Mode;
-                }
-            } else {
-                mode = getXfermode(p->getXfermode());
-            }
+            mode = getXfermode(p->getXfermode());
         } else {
             mode = SkXfermode::kSrcOver_Mode;
         }
 
-        createLayer(mSnapshot, left, top, right, bottom, alpha, mode, flags, previousFbo);
+        createLayer(left, top, right, bottom, alpha, mode, flags, previousFbo);
     }
 
     return count;
@@ -449,7 +622,7 @@
 
 int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
         int alpha, int flags) {
-    if (alpha >= 255 - ALPHA_THRESHOLD) {
+    if (alpha >= 255) {
         return saveLayer(left, top, right, bottom, NULL, flags);
     } else {
         SkPaint paint;
@@ -509,44 +682,56 @@
  *     buffer is left untouched until the first drawing operation. Only when
  *     something actually gets drawn are the layers regions cleared.
  */
-bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
-        float right, float bottom, int alpha, SkXfermode::Mode mode,
-        int flags, GLuint previousFbo) {
+bool OpenGLRenderer::createLayer(float left, float top, float right, float bottom,
+        int alpha, SkXfermode::Mode mode, int flags, GLuint previousFbo) {
     LAYER_LOGD("Requesting layer %.2fx%.2f", right - left, bottom - top);
     LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize());
 
     const bool fboLayer = flags & SkCanvas::kClipToLayer_SaveFlag;
 
     // Window coordinates of the layer
+    Rect clip;
     Rect bounds(left, top, right, bottom);
-    if (!fboLayer) {
-        mSnapshot->transform->mapRect(bounds);
+    Rect untransformedBounds(bounds);
+    mSnapshot->transform->mapRect(bounds);
 
-        // Layers only make sense if they are in the framebuffer's bounds
-        if (bounds.intersect(*snapshot->clipRect)) {
-            // We cannot work with sub-pixels in this case
-            bounds.snapToPixelBoundaries();
+    // Layers only make sense if they are in the framebuffer's bounds
+    if (bounds.intersect(*mSnapshot->clipRect)) {
+        // We cannot work with sub-pixels in this case
+        bounds.snapToPixelBoundaries();
 
-            // When the layer is not an FBO, we may use glCopyTexImage so we
-            // need to make sure the layer does not extend outside the bounds
-            // of the framebuffer
-            if (!bounds.intersect(snapshot->previous->viewport)) {
-                bounds.setEmpty();
-            }
-        } else {
+        // When the layer is not an FBO, we may use glCopyTexImage so we
+        // need to make sure the layer does not extend outside the bounds
+        // of the framebuffer
+        if (!bounds.intersect(mSnapshot->previous->viewport)) {
             bounds.setEmpty();
+        } else if (fboLayer) {
+            clip.set(bounds);
+            mat4 inverse;
+            inverse.loadInverse(*mSnapshot->transform);
+            inverse.mapRect(clip);
+            clip.snapToPixelBoundaries();
+            if (clip.intersect(untransformedBounds)) {
+                clip.translate(-left, -top);
+                bounds.set(untransformedBounds);
+            } else {
+                clip.setEmpty();
+            }
         }
+    } else {
+        bounds.setEmpty();
     }
 
     if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize ||
-            bounds.getHeight() > mCaches.maxTextureSize) {
-        snapshot->empty = fboLayer;
+            bounds.getHeight() > mCaches.maxTextureSize ||
+            (fboLayer && clip.isEmpty())) {
+        mSnapshot->empty = fboLayer;
     } else {
-        snapshot->invisible = snapshot->invisible || (alpha <= ALPHA_THRESHOLD && fboLayer);
+        mSnapshot->invisible = mSnapshot->invisible || (alpha <= ALPHA_THRESHOLD && fboLayer);
     }
 
     // Bail out if we won't draw in this snapshot
-    if (snapshot->invisible || snapshot->empty) {
+    if (mSnapshot->invisible || mSnapshot->empty) {
         return false;
     }
 
@@ -562,25 +747,26 @@
             bounds.getWidth() / float(layer->getWidth()), 0.0f);
     layer->setColorFilter(mColorFilter);
     layer->setBlend(true);
+    layer->setDirty(false);
 
     // Save the layer in the snapshot
-    snapshot->flags |= Snapshot::kFlagIsLayer;
-    snapshot->layer = layer;
+    mSnapshot->flags |= Snapshot::kFlagIsLayer;
+    mSnapshot->layer = layer;
 
     if (fboLayer) {
-        return createFboLayer(layer, bounds, snapshot, previousFbo);
+        return createFboLayer(layer, bounds, clip, previousFbo);
     } else {
         // Copy the framebuffer into the layer
         layer->bindTexture();
         if (!bounds.isEmpty()) {
             if (layer->isEmpty()) {
                 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
-                        bounds.left, snapshot->height - bounds.bottom,
+                        bounds.left, mSnapshot->height - bounds.bottom,
                         layer->getWidth(), layer->getHeight(), 0);
                 layer->setEmpty(false);
             } else {
                 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left,
-                        snapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight());
+                        mSnapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight());
             }
 
             // Enqueue the buffer coordinates to clear the corresponding region later
@@ -591,38 +777,23 @@
     return true;
 }
 
-bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, sp<Snapshot> snapshot,
-        GLuint previousFbo) {
+bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip, GLuint previousFbo) {
     layer->setFbo(mCaches.fboCache.get());
 
-#if RENDER_LAYERS_AS_REGIONS
-    snapshot->region = &snapshot->layer->region;
-    snapshot->flags |= Snapshot::kFlagFboTarget;
-#endif
+    mSnapshot->region = &mSnapshot->layer->region;
+    mSnapshot->flags |= Snapshot::kFlagFboTarget;
 
-    Rect clip(bounds);
-    snapshot->transform->mapRect(clip);
-    clip.intersect(*snapshot->clipRect);
-    clip.snapToPixelBoundaries();
-    clip.intersect(snapshot->previous->viewport);
+    mSnapshot->flags |= Snapshot::kFlagIsFboLayer;
+    mSnapshot->fbo = layer->getFbo();
+    mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
+    mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
+    mSnapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
+    mSnapshot->height = bounds.getHeight();
+    mSnapshot->flags |= Snapshot::kFlagDirtyOrtho;
+    mSnapshot->orthoMatrix.load(mOrthoMatrix);
 
-    mat4 inverse;
-    inverse.loadInverse(*mSnapshot->transform);
-
-    inverse.mapRect(clip);
-    clip.snapToPixelBoundaries();
-    clip.intersect(bounds);
-    clip.translate(-bounds.left, -bounds.top);
-
-    snapshot->flags |= Snapshot::kFlagIsFboLayer;
-    snapshot->fbo = layer->getFbo();
-    snapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
-    snapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
-    snapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
-    snapshot->height = bounds.getHeight();
-    snapshot->flags |= Snapshot::kFlagDirtyOrtho;
-    snapshot->orthoMatrix.load(mOrthoMatrix);
-
+    endTiling();
+    debugOverdraw(false, false);
     // Bind texture to FBO
     glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo());
     layer->bindTexture();
@@ -636,22 +807,10 @@
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
             layer->getTexture(), 0);
 
-#if DEBUG_LAYERS_AS_REGIONS
-    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-    if (status != GL_FRAMEBUFFER_COMPLETE) {
-        ALOGE("Framebuffer incomplete (GL error code 0x%x)", status);
-
-        glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-        layer->deleteTexture();
-        mCaches.fboCache.put(layer->getFbo());
-
-        delete layer;
-
-        return false;
-    }
-#endif
+    startTiling(mSnapshot);
 
     // Clear the FBO, expand the clear region by 1 to get nice bilinear filtering
+    mCaches.enableScissor();
     mCaches.setScissor(clip.left - 1.0f, bounds.getHeight() - clip.bottom - 1.0f,
             clip.getWidth() + 2.0f, clip.getHeight() + 2.0f);
     glClear(GL_COLOR_BUFFER_BIT);
@@ -677,11 +836,15 @@
     const bool fboLayer = current->flags & Snapshot::kFlagIsFboLayer;
 
     if (fboLayer) {
+        endTiling();
+
         // Detach the texture from the FBO
         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
-
         // Unbind current FBO and restore previous one
         glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo);
+        debugOverdraw(true, false);
+
+        startTiling(previous);
     }
 
     Layer* layer = current->layer;
@@ -730,20 +893,13 @@
     // Failing to add the layer to the cache should happen only if the layer is too large
     if (!mCaches.layerCache.put(layer)) {
         LAYER_LOGD("Deleting layer");
-        layer->deleteTexture();
-        delete layer;
+        Caches::getInstance().resourceCache.decrementRefcount(layer);
     }
 }
 
 void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
     float alpha = layer->getAlpha() / 255.0f;
 
-    mat4& transform = layer->getTransform();
-    if (!transform.isIdentity()) {
-        save(0);
-        mSnapshot->transform->multiply(transform);
-    }
-
     setupDraw();
     if (layer->getRenderTarget() == GL_TEXTURE_2D) {
         setupDrawWithTexture();
@@ -780,10 +936,6 @@
     glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
 
     finishDrawTexture();
-
-    if (!transform.isIdentity()) {
-        restore();
-    }
 }
 
 void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
@@ -825,7 +977,6 @@
 }
 
 void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
-#if RENDER_LAYERS_AS_REGIONS
     if (layer->region.isRect()) {
         layer->setRegionAsRect();
 
@@ -906,9 +1057,6 @@
 
         layer->region.clear();
     }
-#else
-    composeLayerRect(layer, rect);
-#endif
 }
 
 void OpenGLRenderer::drawRegionRects(const Region& region) {
@@ -939,27 +1087,22 @@
 
 void OpenGLRenderer::dirtyLayer(const float left, const float top,
         const float right, const float bottom, const mat4 transform) {
-#if RENDER_LAYERS_AS_REGIONS
     if (hasLayer()) {
         Rect bounds(left, top, right, bottom);
         transform.mapRect(bounds);
         dirtyLayerUnchecked(bounds, getRegion());
     }
-#endif
 }
 
 void OpenGLRenderer::dirtyLayer(const float left, const float top,
         const float right, const float bottom) {
-#if RENDER_LAYERS_AS_REGIONS
     if (hasLayer()) {
         Rect bounds(left, top, right, bottom);
         dirtyLayerUnchecked(bounds, getRegion());
     }
-#endif
 }
 
 void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) {
-#if RENDER_LAYERS_AS_REGIONS
     if (bounds.intersect(*mSnapshot->clipRect)) {
         bounds.snapToPixelBoundaries();
         android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
@@ -967,7 +1110,6 @@
             region->orSelf(dirty);
         }
     }
-#endif
 }
 
 void OpenGLRenderer::clearLayerRegions() {
@@ -982,7 +1124,7 @@
         // The list contains bounds that have already been clipped
         // against their initial clip rect, and the current clip
         // is likely different so we need to disable clipping here
-        glDisable(GL_SCISSOR_TEST);
+        bool scissorChanged = mCaches.disableScissor();
 
         Vertex mesh[count * 6];
         Vertex* vertex = mesh;
@@ -1010,7 +1152,7 @@
 
         glDrawArrays(GL_TRIANGLES, 0, count * 6);
 
-        glEnable(GL_SCISSOR_TEST);
+        if (scissorChanged) mCaches.enableScissor();
     } else {
         for (uint32_t i = 0; i < count; i++) {
             delete mLayers.itemAt(i);
@@ -1067,17 +1209,17 @@
     Rect clip(*mSnapshot->clipRect);
     clip.snapToPixelBoundaries();
 
-    mCaches.setScissor(clip.left, mSnapshot->height - clip.bottom,
-            clip.getWidth(), clip.getHeight());
-
-    mDirtyClip = false;
+    if (mCaches.setScissor(clip.left, mSnapshot->height - clip.bottom,
+            clip.getWidth(), clip.getHeight())) {
+        mDirtyClip = false;
+    }
 }
 
 const Rect& OpenGLRenderer::getClipBounds() {
     return mSnapshot->getLocalClip();
 }
 
-bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) {
+bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, float bottom) {
     if (mSnapshot->isIgnored()) {
         return true;
     }
@@ -1092,6 +1234,51 @@
     return !clipRect.intersects(r);
 }
 
+bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, float bottom,
+        Rect& transformed, Rect& clip) {
+    if (mSnapshot->isIgnored()) {
+        return true;
+    }
+
+    transformed.set(left, top, right, bottom);
+    mSnapshot->transform->mapRect(transformed);
+    transformed.snapToPixelBoundaries();
+
+    clip.set(*mSnapshot->clipRect);
+    clip.snapToPixelBoundaries();
+
+    return !clip.intersects(transformed);
+}
+
+bool OpenGLRenderer::quickRejectPreStroke(float left, float top, float right, float bottom, SkPaint* paint) {
+    if (paint->getStyle() != SkPaint::kFill_Style) {
+        float outset = paint->getStrokeWidth() * 0.5f;
+        return quickReject(left - outset, top - outset, right + outset, bottom + outset);
+    } else {
+        return quickReject(left, top, right, bottom);
+    }
+}
+
+bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) {
+    if (mSnapshot->isIgnored() || bottom <= top || right <= left) {
+        return true;
+    }
+
+    Rect r(left, top, right, bottom);
+    mSnapshot->transform->mapRect(r);
+    r.snapToPixelBoundaries();
+
+    Rect clipRect(*mSnapshot->clipRect);
+    clipRect.snapToPixelBoundaries();
+
+    bool rejected = !clipRect.intersects(r);
+    if (!isDeferred() && !rejected) {
+        mCaches.setScissorEnabled(mScissorOptimizationDisabled || !clipRect.contains(r));
+    }
+
+    return rejected;
+}
+
 bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
     bool clipped = mSnapshot->clip(left, top, right, bottom, op);
     if (clipped) {
@@ -1109,6 +1296,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void OpenGLRenderer::setupDraw(bool clear) {
+    // TODO: It would be best if we could do this before quickReject()
+    //       changes the scissor test state
     if (clear) clearLayerRegions();
     if (mDirtyClip) {
         setScissorFromClip();
@@ -1134,10 +1323,14 @@
     mCaches.disbaleTexCoordsVertexArray();
 }
 
-void OpenGLRenderer::setupDrawAALine() {
+void OpenGLRenderer::setupDrawAA() {
     mDescription.isAA = true;
 }
 
+void OpenGLRenderer::setupDrawVertexShape() {
+    mDescription.isVertexShape = true;
+}
+
 void OpenGLRenderer::setupDrawPoint(float pointSize) {
     mDescription.isPoint = true;
     mDescription.pointSize = pointSize;
@@ -1171,6 +1364,10 @@
     mSetShaderColor = mDescription.setAlpha8Color(mColorR, mColorG, mColorB, mColorA);
 }
 
+void OpenGLRenderer::setupDrawTextGamma(const SkPaint* paint) {
+    mCaches.fontRenderer->describe(mDescription, paint);
+}
+
 void OpenGLRenderer::setupDrawColor(float r, float g, float b, float a) {
     mColorA = a;
     mColorR = r;
@@ -1212,8 +1409,8 @@
     // When the blending mode is kClear_Mode, we need to use a modulate color
     // argb=1,0,0,0
     accountForClear(mode);
-    chooseBlending(blend || (mColorSet && mColorA < 1.0f) || (mShader && mShader->blend()), mode,
-            mDescription, swapSrcDst);
+    chooseBlending(blend || (mColorSet && mColorA < 1.0f) || (mShader && mShader->blend()) ||
+            (mColorFilter && mColorFilter->blend()), mode, mDescription, swapSrcDst);
 }
 
 void OpenGLRenderer::setupDrawProgram() {
@@ -1298,9 +1495,13 @@
     }
 }
 
+void OpenGLRenderer::setupDrawTextGammaUniforms() {
+    mCaches.fontRenderer->setupProgram(mDescription, mCaches.currentProgram);
+}
+
 void OpenGLRenderer::setupDrawSimpleMesh() {
     bool force = mCaches.bindMeshBuffer();
-    mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, 0);
+    mCaches.bindPositionVertexPointer(force, 0);
     mCaches.unbindIndicesBuffer();
 }
 
@@ -1333,9 +1534,9 @@
         force = mCaches.unbindMeshBuffer();
     }
 
-    mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, vertices);
+    mCaches.bindPositionVertexPointer(force, vertices);
     if (mCaches.currentProgram->texCoords >= 0) {
-        mCaches.bindTexCoordsVertexPointer(force, mCaches.currentProgram->texCoords, texCoords);
+        mCaches.bindTexCoordsVertexPointer(force, texCoords);
     }
 
     mCaches.unbindIndicesBuffer();
@@ -1343,16 +1544,15 @@
 
 void OpenGLRenderer::setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords) {
     bool force = mCaches.unbindMeshBuffer();
-    mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, vertices);
+    mCaches.bindPositionVertexPointer(force, vertices);
     if (mCaches.currentProgram->texCoords >= 0) {
-        mCaches.bindTexCoordsVertexPointer(force, mCaches.currentProgram->texCoords, texCoords);
+        mCaches.bindTexCoordsVertexPointer(force, texCoords);
     }
 }
 
 void OpenGLRenderer::setupDrawVertices(GLvoid* vertices) {
     bool force = mCaches.unbindMeshBuffer();
-    mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position,
-            vertices, gVertexStride);
+    mCaches.bindPositionVertexPointer(force, vertices, gVertexStride);
     mCaches.unbindIndicesBuffer();
 }
 
@@ -1370,8 +1570,7 @@
 void OpenGLRenderer::setupDrawAALine(GLvoid* vertices, GLvoid* widthCoords,
         GLvoid* lengthCoords, float boundaryWidthProportion, int& widthSlot, int& lengthSlot) {
     bool force = mCaches.unbindMeshBuffer();
-    mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position,
-            vertices, gAAVertexStride);
+    mCaches.bindPositionVertexPointer(force, vertices, gAAVertexStride);
     mCaches.resetTexCoordsVertexPointer();
     mCaches.unbindIndicesBuffer();
 
@@ -1385,10 +1584,6 @@
 
     int boundaryWidthSlot = mCaches.currentProgram->getUniform("boundaryWidth");
     glUniform1f(boundaryWidthSlot, boundaryWidthProportion);
-
-    // Setting the inverse value saves computations per-fragment in the shader
-    int inverseBoundaryWidthSlot = mCaches.currentProgram->getUniform("inverseBoundaryWidth");
-    glUniform1f(inverseBoundaryWidthSlot, 1.0f / boundaryWidthProportion);
 }
 
 void OpenGLRenderer::finishDrawAALine(const int widthSlot, const int lengthSlot) {
@@ -1530,39 +1725,22 @@
 
 status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
         float* vertices, int* colors, SkPaint* paint) {
-    // TODO: Do a quickReject
     if (!vertices || mSnapshot->isIgnored()) {
         return DrawGlInfo::kStatusDone;
     }
 
-    mCaches.activeTexture(0);
-    Texture* texture = mCaches.textureCache.get(bitmap);
-    if (!texture) return DrawGlInfo::kStatusDone;
-    const AutoTexture autoCleanup(texture);
-
-    texture->setWrap(GL_CLAMP_TO_EDGE, true);
-    texture->setFilter(FILTER(paint), true);
-
-    int alpha;
-    SkXfermode::Mode mode;
-    getAlphaAndMode(paint, &alpha, &mode);
-
-    const uint32_t count = meshWidth * meshHeight * 6;
-
+    // TODO: We should compute the bounding box when recording the display list
     float left = FLT_MAX;
     float top = FLT_MAX;
     float right = FLT_MIN;
     float bottom = FLT_MIN;
 
-#if RENDER_LAYERS_AS_REGIONS
-    const bool hasActiveLayer = hasLayer();
-#else
-    const bool hasActiveLayer = false;
-#endif
+    const uint32_t count = meshWidth * meshHeight * 6;
 
     // TODO: Support the colors array
     TextureVertex mesh[count];
     TextureVertex* vertex = mesh;
+
     for (int32_t y = 0; y < meshHeight; y++) {
         for (int32_t x = 0; x < meshWidth; x++) {
             uint32_t i = (y * (meshWidth + 1) + x) * 2;
@@ -1589,23 +1767,33 @@
             TextureVertex::set(vertex++, vertices[cx], vertices[cy], u2, v1);
             TextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2);
 
-#if RENDER_LAYERS_AS_REGIONS
-            if (hasActiveLayer) {
-                // TODO: This could be optimized to avoid unnecessary ops
-                left = fminf(left, fminf(vertices[ax], fminf(vertices[bx], vertices[cx])));
-                top = fminf(top, fminf(vertices[ay], fminf(vertices[by], vertices[cy])));
-                right = fmaxf(right, fmaxf(vertices[ax], fmaxf(vertices[bx], vertices[cx])));
-                bottom = fmaxf(bottom, fmaxf(vertices[ay], fmaxf(vertices[by], vertices[cy])));
-            }
-#endif
+            // TODO: This could be optimized to avoid unnecessary ops
+            left = fminf(left, fminf(vertices[ax], fminf(vertices[bx], vertices[cx])));
+            top = fminf(top, fminf(vertices[ay], fminf(vertices[by], vertices[cy])));
+            right = fmaxf(right, fmaxf(vertices[ax], fmaxf(vertices[bx], vertices[cx])));
+            bottom = fmaxf(bottom, fmaxf(vertices[ay], fmaxf(vertices[by], vertices[cy])));
         }
     }
 
-#if RENDER_LAYERS_AS_REGIONS
-    if (hasActiveLayer) {
+    if (quickReject(left, top, right, bottom)) {
+        return DrawGlInfo::kStatusDone;
+    }
+
+    mCaches.activeTexture(0);
+    Texture* texture = mCaches.textureCache.get(bitmap);
+    if (!texture) return DrawGlInfo::kStatusDone;
+    const AutoTexture autoCleanup(texture);
+
+    texture->setWrap(GL_CLAMP_TO_EDGE, true);
+    texture->setFilter(FILTER(paint), true);
+
+    int alpha;
+    SkXfermode::Mode mode;
+    getAlphaAndMode(paint, &alpha, &mode);
+
+    if (hasLayer()) {
         dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
     }
-#endif
 
     drawTextureMesh(0.0f, 0.0f, 1.0f, 1.0f, texture->id, alpha / 255.0f,
             mode, texture->blend, &mesh[0].position[0], &mesh[0].texture[0],
@@ -1674,10 +1862,23 @@
 status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
         const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
         float left, float top, float right, float bottom, SkPaint* paint) {
+    int alpha;
+    SkXfermode::Mode mode;
+    getAlphaAndModeDirect(paint, &alpha, &mode);
+
+    return drawPatch(bitmap, xDivs, yDivs, colors, width, height, numColors,
+            left, top, right, bottom, alpha, mode);
+}
+
+status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
+        const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
+        float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode) {
     if (quickReject(left, top, right, bottom)) {
         return DrawGlInfo::kStatusDone;
     }
 
+    alpha *= mSnapshot->alpha;
+
     mCaches.activeTexture(0);
     Texture* texture = mCaches.textureCache.get(bitmap);
     if (!texture) return DrawGlInfo::kStatusDone;
@@ -1685,16 +1886,11 @@
     texture->setWrap(GL_CLAMP_TO_EDGE, true);
     texture->setFilter(GL_LINEAR, true);
 
-    int alpha;
-    SkXfermode::Mode mode;
-    getAlphaAndMode(paint, &alpha, &mode);
-
     const Patch* mesh = mCaches.patchCache.get(bitmap->width(), bitmap->height(),
             right - left, bottom - top, xDivs, yDivs, colors, width, height, numColors);
 
     if (CC_LIKELY(mesh && mesh->verticesCount > 0)) {
         const bool pureTranslate = mSnapshot->transform->isPureTranslate();
-#if RENDER_LAYERS_AS_REGIONS
         // Mark the current layer dirty where we are going to draw the patch
         if (hasLayer() && mesh->hasEmptyQuads) {
             const float offsetX = left + mSnapshot->transform->getTranslateX();
@@ -1712,7 +1908,6 @@
                 }
             }
         }
-#endif
 
         if (CC_LIKELY(pureTranslate)) {
             const float x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f);
@@ -1734,83 +1929,67 @@
 }
 
 /**
- * This function uses a similar approach to that of AA lines in the drawLines() function.
- * We expand the rectangle by a half pixel in screen space on all sides, and use a fragment
- * shader to compute the translucency of the color, determined by whether a given pixel is
- * within that boundary region and how far into the region it is.
+ * Renders a convex path via tessellation. For AA paths, this function uses a similar approach to
+ * that of AA lines in the drawLines() function.  We expand the convex path by a half pixel in
+ * screen space in all directions. However, instead of using a fragment shader to compute the
+ * translucency of the color from its position, we simply use a varying parameter to define how far
+ * a given pixel is from the edge. For non-AA paths, the expansion and alpha varying are not used.
+ *
+ * Doesn't yet support joins, caps, or path effects.
  */
-void OpenGLRenderer::drawAARect(float left, float top, float right, float bottom,
-        int color, SkXfermode::Mode mode) {
-    float inverseScaleX = 1.0f;
-    float inverseScaleY = 1.0f;
-    // The quad that we use needs to account for scaling.
-    if (CC_UNLIKELY(!mSnapshot->transform->isPureTranslate())) {
-        Matrix4 *mat = mSnapshot->transform;
-        float m00 = mat->data[Matrix4::kScaleX];
-        float m01 = mat->data[Matrix4::kSkewY];
-        float m02 = mat->data[2];
-        float m10 = mat->data[Matrix4::kSkewX];
-        float m11 = mat->data[Matrix4::kScaleX];
-        float m12 = mat->data[6];
-        float scaleX = sqrt(m00 * m00 + m01 * m01);
-        float scaleY = sqrt(m10 * m10 + m11 * m11);
-        inverseScaleX = (scaleX != 0) ? (inverseScaleX / scaleX) : 0;
-        inverseScaleY = (scaleY != 0) ? (inverseScaleY / scaleY) : 0;
+void OpenGLRenderer::drawConvexPath(const SkPath& path, SkPaint* paint) {
+    int color = paint->getColor();
+    SkPaint::Style style = paint->getStyle();
+    SkXfermode::Mode mode = getXfermode(paint->getXfermode());
+    bool isAA = paint->isAntiAlias();
+
+    VertexBuffer vertexBuffer;
+    // TODO: try clipping large paths to viewport
+    PathRenderer::convexPathVertices(path, paint, mSnapshot->transform, vertexBuffer);
+
+    if (!vertexBuffer.getSize()) {
+        // no vertices to draw
+        return;
     }
 
     setupDraw();
     setupDrawNoTexture();
-    setupDrawAALine();
+    if (isAA) setupDrawAA();
+    setupDrawVertexShape();
     setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
     setupDrawColorFilter();
     setupDrawShader();
-    setupDrawBlending(true, mode);
+    setupDrawBlending(isAA, mode);
     setupDrawProgram();
-    setupDrawModelViewIdentity(true);
+    setupDrawModelViewIdentity();
     setupDrawColorUniforms();
     setupDrawColorFilterUniforms();
     setupDrawShaderIdentityUniforms();
 
-    AAVertex rects[4];
-    AAVertex* aaVertices = &rects[0];
-    void* widthCoords = ((GLbyte*) aaVertices) + gVertexAAWidthOffset;
-    void* lengthCoords = ((GLbyte*) aaVertices) + gVertexAALengthOffset;
+    void* vertices = vertexBuffer.getBuffer();
+    bool force = mCaches.unbindMeshBuffer();
+    mCaches.bindPositionVertexPointer(true, vertices, isAA ? gAlphaVertexStride : gVertexStride);
+    mCaches.resetTexCoordsVertexPointer();
+    mCaches.unbindIndicesBuffer();
 
-    float boundarySizeX = .5 * inverseScaleX;
-    float boundarySizeY = .5 * inverseScaleY;
+    int alphaSlot = -1;
+    if (isAA) {
+        void* alphaCoords = ((GLbyte*) vertices) + gVertexAlphaOffset;
+        alphaSlot = mCaches.currentProgram->getAttrib("vtxAlpha");
 
-    // Adjust the rect by the AA boundary padding
-    left -= boundarySizeX;
-    right += boundarySizeX;
-    top -= boundarySizeY;
-    bottom += boundarySizeY;
-
-    float width = right - left;
-    float height = bottom - top;
-
-    int widthSlot;
-    int lengthSlot;
-
-    float boundaryWidthProportion = (width != 0) ? (2 * boundarySizeX) / width : 0;
-    float boundaryHeightProportion = (height != 0) ? (2 * boundarySizeY) / height : 0;
-    setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords,
-            boundaryWidthProportion, widthSlot, lengthSlot);
-
-    int boundaryLengthSlot = mCaches.currentProgram->getUniform("boundaryLength");
-    int inverseBoundaryLengthSlot = mCaches.currentProgram->getUniform("inverseBoundaryLength");
-    glUniform1f(boundaryLengthSlot, boundaryHeightProportion);
-    glUniform1f(inverseBoundaryLengthSlot, (1.0f / boundaryHeightProportion));
-
-    if (!quickReject(left, top, right, bottom)) {
-        AAVertex::set(aaVertices++, left, bottom, 1, 1);
-        AAVertex::set(aaVertices++, left, top, 1, 0);
-        AAVertex::set(aaVertices++, right, bottom, 0, 1);
-        AAVertex::set(aaVertices++, right, top, 0, 0);
-        dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
-        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+        // TODO: avoid enable/disable in back to back uses of the alpha attribute
+        glEnableVertexAttribArray(alphaSlot);
+        glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, gAlphaVertexStride, alphaCoords);
     }
 
-    finishDrawAALine(widthSlot, lengthSlot);
+    SkRect bounds = PathRenderer::computePathBounds(path, paint);
+    dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *mSnapshot->transform);
+
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getSize());
+
+    if (isAA) {
+        glDisableVertexAttribArray(alphaSlot);
+    }
 }
 
 /**
@@ -1864,10 +2043,8 @@
             Matrix4 *mat = mSnapshot->transform;
             float m00 = mat->data[Matrix4::kScaleX];
             float m01 = mat->data[Matrix4::kSkewY];
-            float m02 = mat->data[2];
             float m10 = mat->data[Matrix4::kSkewX];
-            float m11 = mat->data[Matrix4::kScaleX];
-            float m12 = mat->data[6];
+            float m11 = mat->data[Matrix4::kScaleY];
 
             float scaleX = sqrtf(m00 * m00 + m01 * m01);
             float scaleY = sqrtf(m10 * m10 + m11 * m11);
@@ -1882,10 +2059,13 @@
     }
 
     getAlphaAndMode(paint, &alpha, &mode);
+
+    mCaches.enableScissor();
+
     setupDraw();
     setupDrawNoTexture();
     if (isAA) {
-        setupDrawAALine();
+        setupDrawAA();
     }
     setupDrawColor(paint->getColor(), alpha);
     setupDrawColorFilter();
@@ -1924,7 +2104,7 @@
         // This value is used in the fragment shader to determine how to fill fragments.
         // We will need to calculate the actual width proportion on each segment for
         // scaled non-hairlines, since the boundary proportion may differ per-axis when scaled.
-        float boundaryWidthProportion = 1 / (2 * halfStrokeWidth);
+        float boundaryWidthProportion = .5 - 1 / (2 * halfStrokeWidth);
         setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords,
                 boundaryWidthProportion, widthSlot, lengthSlot);
     }
@@ -1933,9 +2113,7 @@
     Vertex* prevVertex = NULL;
 
     int boundaryLengthSlot = -1;
-    int inverseBoundaryLengthSlot = -1;
     int boundaryWidthSlot = -1;
-    int inverseBoundaryWidthSlot = -1;
 
     for (int i = 0; i < count; i += 4) {
         // a = start point, b = end point
@@ -1948,6 +2126,10 @@
 
         // Find the normal to the line
         vec2 n = (b - a).copyNormalized() * halfStrokeWidth;
+        float x = n.x;
+        n.x = -n.y;
+        n.y = x;
+
         if (isHairLine) {
             if (isAA) {
                 float wideningFactor;
@@ -1972,14 +2154,10 @@
 
             float extendedNLength = extendedN.length();
             // We need to set this value on the shader prior to drawing
-            boundaryWidthProportion = extendedNLength / (halfStrokeWidth + extendedNLength);
+            boundaryWidthProportion = .5 - extendedNLength / (halfStrokeWidth + extendedNLength);
             n += extendedN;
         }
 
-        float x = n.x;
-        n.x = -n.y;
-        n.y = x;
-
         // aa lines expand the endpoint vertices to encompass the AA boundary
         if (isAA) {
             vec2 abVector = (b - a);
@@ -1990,9 +2168,9 @@
                 abVector.x *= inverseScaleX;
                 abVector.y *= inverseScaleY;
                 float abLength = abVector.length();
-                boundaryLengthProportion = abLength / (length + abLength);
+                boundaryLengthProportion = .5 - abLength / (length + abLength);
             } else {
-                boundaryLengthProportion = .5 / (length + 1);
+                boundaryLengthProportion = .5 - .5 / (length + 1);
             }
 
             abVector /= 2;
@@ -2012,7 +2190,7 @@
         const float top = fmin(p1.y, fmin(p2.y, fmin(p3.y, p4.y)));
         const float bottom = fmax(p1.y, fmax(p2.y, fmax(p3.y, p4.y)));
 
-        if (!quickReject(left, top, right, bottom)) {
+        if (!quickRejectNoScissor(left, top, right, bottom)) {
             if (!isAA) {
                 if (prevVertex != NULL) {
                     // Issue two repeat vertices to create degenerate triangles to bridge
@@ -2038,22 +2216,16 @@
                     if (boundaryWidthSlot < 0) {
                         boundaryWidthSlot =
                                 mCaches.currentProgram->getUniform("boundaryWidth");
-                        inverseBoundaryWidthSlot =
-                                mCaches.currentProgram->getUniform("inverseBoundaryWidth");
                     }
 
                     glUniform1f(boundaryWidthSlot, boundaryWidthProportion);
-                    glUniform1f(inverseBoundaryWidthSlot, (1 / boundaryWidthProportion));
                 }
 
                 if (boundaryLengthSlot < 0) {
                     boundaryLengthSlot = mCaches.currentProgram->getUniform("boundaryLength");
-                    inverseBoundaryLengthSlot =
-                            mCaches.currentProgram->getUniform("inverseBoundaryLength");
                 }
 
                 glUniform1f(boundaryLengthSlot, boundaryLengthProportion);
-                glUniform1f(inverseBoundaryLengthSlot, (1 / boundaryLengthProportion));
 
                 if (prevAAVertex != NULL) {
                     // Issue two repeat vertices to create degenerate triangles to bridge
@@ -2117,6 +2289,10 @@
     TextureVertex pointsData[verticesCount];
     TextureVertex* vertex = &pointsData[0];
 
+    // TODO: We should optimize this method to not generate vertices for points
+    // that lie outside of the clip.
+    mCaches.enableScissor();
+
     setupDraw();
     setupDrawNoTexture();
     setupDrawPoint(strokeWidth);
@@ -2175,85 +2351,191 @@
 }
 
 status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom,
-        float rx, float ry, SkPaint* paint) {
-    if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone;
-
-    mCaches.activeTexture(0);
-    const PathTexture* texture = mCaches.roundRectShapeCache.getRoundRect(
-            right - left, bottom - top, rx, ry, paint);
-    return drawShape(left, top, texture, paint);
-}
-
-status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) {
-    if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone;
-
-    mCaches.activeTexture(0);
-    const PathTexture* texture = mCaches.circleShapeCache.getCircle(radius, paint);
-    return drawShape(x - radius, y - radius, texture, paint);
-}
-
-status_t OpenGLRenderer::drawOval(float left, float top, float right, float bottom,
-        SkPaint* paint) {
-    if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone;
-
-    mCaches.activeTexture(0);
-    const PathTexture* texture = mCaches.ovalShapeCache.getOval(right - left, bottom - top, paint);
-    return drawShape(left, top, texture, paint);
-}
-
-status_t OpenGLRenderer::drawArc(float left, float top, float right, float bottom,
-        float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) {
-    if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone;
-
-    if (fabs(sweepAngle) >= 360.0f) {
-        return drawOval(left, top, right, bottom, paint);
-    }
-
-    mCaches.activeTexture(0);
-    const PathTexture* texture = mCaches.arcShapeCache.getArc(right - left, bottom - top,
-            startAngle, sweepAngle, useCenter, paint);
-    return drawShape(left, top, texture, paint);
-}
-
-status_t OpenGLRenderer::drawRectAsShape(float left, float top, float right, float bottom,
-        SkPaint* paint) {
-    if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone;
-
-    mCaches.activeTexture(0);
-    const PathTexture* texture = mCaches.rectShapeCache.getRect(right - left, bottom - top, paint);
-    return drawShape(left, top, texture, paint);
-}
-
-status_t OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* p) {
-    if (p->getStyle() != SkPaint::kFill_Style) {
-        return drawRectAsShape(left, top, right, bottom, p);
-    }
-
-    if (quickReject(left, top, right, bottom)) {
+        float rx, float ry, SkPaint* p) {
+    if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p)) {
         return DrawGlInfo::kStatusDone;
     }
 
-    SkXfermode::Mode mode;
-    if (!mCaches.extensions.hasFramebufferFetch()) {
-        const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode);
-        if (!isMode) {
-            // Assume SRC_OVER
-            mode = SkXfermode::kSrcOver_Mode;
-        }
-    } else {
-        mode = getXfermode(p->getXfermode());
+    if (p->getPathEffect() != 0) {
+        mCaches.activeTexture(0);
+        const PathTexture* texture = mCaches.roundRectShapeCache.getRoundRect(
+                right - left, bottom - top, rx, ry, p);
+        return drawShape(left, top, texture, p);
     }
 
-    int color = p->getColor();
-    if (p->isAntiAlias() && !mSnapshot->transform->isSimple()) {
-        drawAARect(left, top, right, bottom, color, mode);
+    SkPath path;
+    SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
+    if (p->getStyle() == SkPaint::kStrokeAndFill_Style) {
+        float outset = p->getStrokeWidth() / 2;
+        rect.outset(outset, outset);
+        rx += outset;
+        ry += outset;
+    }
+    path.addRoundRect(rect, rx, ry);
+    drawConvexPath(path, p);
+
+    return DrawGlInfo::kStatusDrew;
+}
+
+status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* p) {
+    if (mSnapshot->isIgnored() || quickRejectPreStroke(x - radius, y - radius,
+            x + radius, y + radius, p)) {
+        return DrawGlInfo::kStatusDone;
+    }
+    if (p->getPathEffect() != 0) {
+        mCaches.activeTexture(0);
+        const PathTexture* texture = mCaches.circleShapeCache.getCircle(radius, p);
+        return drawShape(x - radius, y - radius, texture, p);
+    }
+
+    SkPath path;
+    if (p->getStyle() == SkPaint::kStrokeAndFill_Style) {
+        path.addCircle(x, y, radius + p->getStrokeWidth() / 2);
     } else {
-        drawColorRect(left, top, right, bottom, color, mode);
+        path.addCircle(x, y, radius);
+    }
+    drawConvexPath(path, p);
+
+    return DrawGlInfo::kStatusDrew;
+}
+
+status_t OpenGLRenderer::drawOval(float left, float top, float right, float bottom,
+        SkPaint* p) {
+    if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p)) {
+        return DrawGlInfo::kStatusDone;
+    }
+
+    if (p->getPathEffect() != 0) {
+        mCaches.activeTexture(0);
+        const PathTexture* texture = mCaches.ovalShapeCache.getOval(right - left, bottom - top, p);
+        return drawShape(left, top, texture, p);
+    }
+
+    SkPath path;
+    SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
+    if (p->getStyle() == SkPaint::kStrokeAndFill_Style) {
+        rect.outset(p->getStrokeWidth() / 2, p->getStrokeWidth() / 2);
+    }
+    path.addOval(rect);
+    drawConvexPath(path, p);
+
+    return DrawGlInfo::kStatusDrew;
+}
+
+status_t OpenGLRenderer::drawArc(float left, float top, float right, float bottom,
+        float startAngle, float sweepAngle, bool useCenter, SkPaint* p) {
+    if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p)) {
+        return DrawGlInfo::kStatusDone;
+    }
+
+    if (fabs(sweepAngle) >= 360.0f) {
+        return drawOval(left, top, right, bottom, p);
+    }
+
+    // TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180)
+    if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != 0 || p->getStrokeCap() != SkPaint::kButt_Cap || useCenter) {
+        mCaches.activeTexture(0);
+        const PathTexture* texture = mCaches.arcShapeCache.getArc(right - left, bottom - top,
+                startAngle, sweepAngle, useCenter, p);
+        return drawShape(left, top, texture, p);
+    }
+
+    SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
+    if (p->getStyle() == SkPaint::kStrokeAndFill_Style) {
+        rect.outset(p->getStrokeWidth() / 2, p->getStrokeWidth() / 2);
+    }
+
+    SkPath path;
+    if (useCenter) {
+        path.moveTo(rect.centerX(), rect.centerY());
+    }
+    path.arcTo(rect, startAngle, sweepAngle, !useCenter);
+    if (useCenter) {
+        path.close();
+    }
+    drawConvexPath(path, p);
+
+    return DrawGlInfo::kStatusDrew;
+}
+
+// See SkPaintDefaults.h
+#define SkPaintDefaults_MiterLimit SkIntToScalar(4)
+
+status_t OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* p) {
+    if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p)) {
+        return DrawGlInfo::kStatusDone;
+    }
+
+    if (p->getStyle() != SkPaint::kFill_Style) {
+        // only fill style is supported by drawConvexPath, since others have to handle joins
+        if (p->getPathEffect() != 0 || p->getStrokeJoin() != SkPaint::kMiter_Join ||
+                p->getStrokeMiter() != SkPaintDefaults_MiterLimit) {
+            mCaches.activeTexture(0);
+            const PathTexture* texture =
+                    mCaches.rectShapeCache.getRect(right - left, bottom - top, p);
+            return drawShape(left, top, texture, p);
+        }
+
+        SkPath path;
+        SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
+        if (p->getStyle() == SkPaint::kStrokeAndFill_Style) {
+            rect.outset(p->getStrokeWidth() / 2, p->getStrokeWidth() / 2);
+        }
+        path.addRect(rect);
+        drawConvexPath(path, p);
+
+        return DrawGlInfo::kStatusDrew;
+    }
+
+    if (p->isAntiAlias() && !mSnapshot->transform->isSimple()) {
+        SkPath path;
+        path.addRect(left, top, right, bottom);
+        drawConvexPath(path, p);
+    } else {
+        drawColorRect(left, top, right, bottom, p->getColor(), getXfermode(p->getXfermode()));
     }
 
     return DrawGlInfo::kStatusDrew;
 }
 
+void OpenGLRenderer::drawTextShadow(SkPaint* paint, const char* text, int bytesCount, int count,
+        const float* positions, FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode,
+        float x, float y) {
+    mCaches.activeTexture(0);
+
+    // NOTE: The drop shadow will not perform gamma correction
+    //       if shader-based correction is enabled
+    mCaches.dropShadowCache.setFontRenderer(fontRenderer);
+    const ShadowTexture* shadow = mCaches.dropShadowCache.get(
+            paint, text, bytesCount, count, mShadowRadius, positions);
+    const AutoTexture autoCleanup(shadow);
+
+    const float sx = x - shadow->left + mShadowDx;
+    const float sy = y - shadow->top + mShadowDy;
+
+    const int shadowAlpha = ((mShadowColor >> 24) & 0xFF) * mSnapshot->alpha;
+    int shadowColor = mShadowColor;
+    if (mShader) {
+        shadowColor = 0xffffffff;
+    }
+
+    setupDraw();
+    setupDrawWithTexture(true);
+    setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha);
+    setupDrawColorFilter();
+    setupDrawShader();
+    setupDrawBlending(true, mode);
+    setupDrawProgram();
+    setupDrawModelView(sx, sy, sx + shadow->width, sy + shadow->height);
+    setupDrawTexture(shadow->id);
+    setupDrawPureColorUniforms();
+    setupDrawColorFilterUniforms();
+    setupDrawShaderUniforms();
+    setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
+
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+}
+
 status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count,
         const float* positions, SkPaint* paint) {
     if (text == NULL || count == 0 || mSnapshot->isIgnored() ||
@@ -2274,7 +2556,7 @@
         y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f);
     }
 
-    FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer(paint);
+    FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
     fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()),
             paint->getTextSize());
 
@@ -2282,6 +2564,11 @@
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
 
+    if (CC_UNLIKELY(mHasShadow)) {
+        drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer, alpha, mode,
+                0.0f, 0.0f);
+    }
+
     // Pick the appropriate texture filtering
     bool linearFilter = mSnapshot->transform->changesBounds();
     if (pureTranslate && !linearFilter) {
@@ -2290,6 +2577,7 @@
 
     mCaches.activeTexture(0);
     setupDraw();
+    setupDrawTextGamma(paint);
     setupDrawDirtyRegionsDisabled();
     setupDrawWithTexture(true);
     setupDrawAlpha8Color(paint->getColor(), alpha);
@@ -2302,33 +2590,28 @@
     setupDrawPureColorUniforms();
     setupDrawColorFilterUniforms();
     setupDrawShaderUniforms(pureTranslate);
+    setupDrawTextGammaUniforms();
 
     const Rect* clip = pureTranslate ? mSnapshot->clipRect : &mSnapshot->getLocalClip();
     Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
 
-#if RENDER_LAYERS_AS_REGIONS
     const bool hasActiveLayer = hasLayer();
-#else
-    const bool hasActiveLayer = false;
-#endif
 
     if (fontRenderer.renderPosText(paint, clip, text, 0, bytesCount, count, x, y,
             positions, hasActiveLayer ? &bounds : NULL)) {
-#if RENDER_LAYERS_AS_REGIONS
         if (hasActiveLayer) {
             if (!pureTranslate) {
                 mSnapshot->transform->mapRect(bounds);
             }
             dirtyLayerUnchecked(bounds, getRegion());
         }
-#endif
     }
 
     return DrawGlInfo::kStatusDrew;
 }
 
 status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
-        float x, float y, SkPaint* paint, float length) {
+        float x, float y, const float* positions, SkPaint* paint, float length) {
     if (text == NULL || count == 0 || mSnapshot->isIgnored() ||
             (paint->getAlpha() * mSnapshot->alpha == 0 && paint->getXfermode() == NULL)) {
         return DrawGlInfo::kStatusDone;
@@ -2361,10 +2644,11 @@
     }
 
 #if DEBUG_GLYPHS
-    ALOGD("OpenGLRenderer drawText() with FontID=%d", SkTypeface::UniqueID(paint->getTypeface()));
+    ALOGD("OpenGLRenderer drawText() with FontID=%d",
+            SkTypeface::UniqueID(paint->getTypeface()));
 #endif
 
-    FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer(paint);
+    FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
     fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()),
             paint->getTextSize());
 
@@ -2373,37 +2657,8 @@
     getAlphaAndMode(paint, &alpha, &mode);
 
     if (CC_UNLIKELY(mHasShadow)) {
-        mCaches.activeTexture(0);
-
-        mCaches.dropShadowCache.setFontRenderer(fontRenderer);
-        const ShadowTexture* shadow = mCaches.dropShadowCache.get(
-                paint, text, bytesCount, count, mShadowRadius);
-        const AutoTexture autoCleanup(shadow);
-
-        const float sx = oldX - shadow->left + mShadowDx;
-        const float sy = oldY - shadow->top + mShadowDy;
-
-        const int shadowAlpha = ((mShadowColor >> 24) & 0xFF) * mSnapshot->alpha;
-        int shadowColor = mShadowColor;
-        if (mShader) {
-            shadowColor = 0xffffffff;
-        }
-
-        setupDraw();
-        setupDrawWithTexture(true);
-        setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha);
-        setupDrawColorFilter();
-        setupDrawShader();
-        setupDrawBlending(true, mode);
-        setupDrawProgram();
-        setupDrawModelView(sx, sy, sx + shadow->width, sy + shadow->height);
-        setupDrawTexture(shadow->id);
-        setupDrawPureColorUniforms();
-        setupDrawColorFilterUniforms();
-        setupDrawShaderUniforms();
-        setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
-
-        glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+        drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer, alpha, mode,
+                oldX, oldY);
     }
 
     // Pick the appropriate texture filtering
@@ -2415,6 +2670,7 @@
     // The font renderer will always use texture unit 0
     mCaches.activeTexture(0);
     setupDraw();
+    setupDrawTextGamma(paint);
     setupDrawDirtyRegionsDisabled();
     setupDrawWithTexture(true);
     setupDrawAlpha8Color(paint->getColor(), alpha);
@@ -2429,26 +2685,30 @@
     setupDrawPureColorUniforms();
     setupDrawColorFilterUniforms();
     setupDrawShaderUniforms(pureTranslate);
+    setupDrawTextGammaUniforms();
 
-    const Rect* clip = pureTranslate ? mSnapshot->clipRect : &mSnapshot->getLocalClip();
+    const Rect* clip = pureTranslate ? mSnapshot->clipRect :
+            (mSnapshot->hasPerspectiveTransform() ? NULL : &mSnapshot->getLocalClip());
     Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
 
-#if RENDER_LAYERS_AS_REGIONS
     const bool hasActiveLayer = hasLayer();
-#else
-    const bool hasActiveLayer = false;
-#endif
 
-    if (fontRenderer.renderText(paint, clip, text, 0, bytesCount, count, x, y,
-            hasActiveLayer ? &bounds : NULL)) {
-#if RENDER_LAYERS_AS_REGIONS
-        if (hasActiveLayer) {
-            if (!pureTranslate) {
-                mSnapshot->transform->mapRect(bounds);
-            }
-            dirtyLayerUnchecked(bounds, getRegion());
+    bool status;
+    if (CC_UNLIKELY(paint->getTextAlign() != SkPaint::kLeft_Align)) {
+        SkPaint paintCopy(*paint);
+        paintCopy.setTextAlign(SkPaint::kLeft_Align);
+        status = fontRenderer.renderPosText(&paintCopy, clip, text, 0, bytesCount, count, x, y,
+                positions, hasActiveLayer ? &bounds : NULL);
+    } else {
+        status = fontRenderer.renderPosText(paint, clip, text, 0, bytesCount, count, x, y,
+                positions, hasActiveLayer ? &bounds : NULL);
+    }
+
+    if (status && hasActiveLayer) {
+        if (!pureTranslate) {
+            mSnapshot->transform->mapRect(bounds);
         }
-#endif
+        dirtyLayerUnchecked(bounds, getRegion());
     }
 
     drawTextDecorations(text, bytesCount, length, oldX, oldY, paint);
@@ -2463,7 +2723,7 @@
         return DrawGlInfo::kStatusDone;
     }
 
-    FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer(paint);
+    FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
     fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()),
             paint->getTextSize());
 
@@ -2473,6 +2733,7 @@
 
     mCaches.activeTexture(0);
     setupDraw();
+    setupDrawTextGamma(paint);
     setupDrawDirtyRegionsDisabled();
     setupDrawWithTexture(true);
     setupDrawAlpha8Color(paint->getColor(), alpha);
@@ -2485,24 +2746,19 @@
     setupDrawPureColorUniforms();
     setupDrawColorFilterUniforms();
     setupDrawShaderUniforms(false);
+    setupDrawTextGammaUniforms();
 
     const Rect* clip = &mSnapshot->getLocalClip();
     Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
 
-#if RENDER_LAYERS_AS_REGIONS
     const bool hasActiveLayer = hasLayer();
-#else
-    const bool hasActiveLayer = false;
-#endif
 
     if (fontRenderer.renderTextOnPath(paint, clip, text, 0, bytesCount, count, path,
             hOffset, vOffset, hasActiveLayer ? &bounds : NULL)) {
-#if RENDER_LAYERS_AS_REGIONS
         if (hasActiveLayer) {
             mSnapshot->transform->mapRect(bounds);
             dirtyLayerUnchecked(bounds, getRegion());
         }
-#endif
     }
 
     return DrawGlInfo::kStatusDrew;
@@ -2527,43 +2783,47 @@
 }
 
 status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
-    if (!layer || quickReject(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight())) {
+    if (!layer) {
         return DrawGlInfo::kStatusDone;
     }
 
-    if (layer->deferredUpdateScheduled && layer->renderer && layer->displayList) {
-        OpenGLRenderer* renderer = layer->renderer;
-        Rect& dirty = layer->dirtyRect;
-
-        interrupt();
-        renderer->setViewport(layer->layer.getWidth(), layer->layer.getHeight());
-        renderer->prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, !layer->isBlend());
-        renderer->drawDisplayList(layer->displayList, dirty, DisplayList::kReplayFlag_ClipChildren);
-        renderer->finish();
-        resume();
-
-        dirty.setEmpty();
-        layer->deferredUpdateScheduled = false;
-        layer->renderer = NULL;
-        layer->displayList = NULL;
+    mat4* transform = NULL;
+    if (layer->isTextureLayer()) {
+        transform = &layer->getTransform();
+        if (!transform->isIdentity()) {
+            save(0);
+            mSnapshot->transform->multiply(*transform);
+        }
     }
 
+    Rect transformed;
+    Rect clip;
+    const bool rejected = quickRejectNoScissor(x, y,
+            x + layer->layer.getWidth(), y + layer->layer.getHeight(), transformed, clip);
+
+    if (rejected) {
+        if (transform && !transform->isIdentity()) {
+            restore();
+        }
+        return DrawGlInfo::kStatusDone;
+    }
+
+    bool debugLayerUpdate = false;
+    if (updateLayer(layer, true)) {
+        debugLayerUpdate = mCaches.debugLayersUpdates;
+    }
+
+    mCaches.setScissorEnabled(mScissorOptimizationDisabled || !clip.contains(transformed));
     mCaches.activeTexture(0);
 
-    int alpha;
-    SkXfermode::Mode mode;
-    getAlphaAndMode(paint, &alpha, &mode);
-
-    layer->setAlpha(alpha, mode);
-
-#if RENDER_LAYERS_AS_REGIONS
     if (CC_LIKELY(!layer->region.isEmpty())) {
+        SkiaColorFilter* oldFilter = mColorFilter;
+        mColorFilter = layer->getColorFilter();
+
         if (layer->region.isRect()) {
             composeLayerRect(layer, layer->regionRect);
         } else if (layer->mesh) {
-            const float a = alpha / 255.0f;
-            const Rect& rect = layer->layer;
-
+            const float a = layer->getAlpha() / 255.0f;
             setupDraw();
             setupDrawWithTexture();
             setupDrawColor(a, a, a, a);
@@ -2574,12 +2834,12 @@
             setupDrawColorFilterUniforms();
             setupDrawTexture(layer->getTexture());
             if (CC_LIKELY(mSnapshot->transform->isPureTranslate())) {
-                x = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f);
-                y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f);
+                int tx = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f);
+                int ty = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f);
 
                 layer->setFilter(GL_NEAREST);
-                setupDrawModelViewTranslate(x, y,
-                        x + layer->layer.getWidth(), y + layer->layer.getHeight(), true);
+                setupDrawModelViewTranslate(tx, ty,
+                        tx + layer->layer.getWidth(), ty + layer->layer.getHeight(), true);
             } else {
                 layer->setFilter(GL_LINEAR);
                 setupDrawModelViewTranslate(x, y,
@@ -2596,11 +2856,18 @@
             drawRegionRects(layer->region);
 #endif
         }
+
+        mColorFilter = oldFilter;
+
+        if (debugLayerUpdate) {
+            drawColorRect(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight(),
+                    0x7f00ff00, SkXfermode::kSrcOver_Mode);
+        }
     }
-#else
-    const Rect r(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight());
-    composeLayerRect(layer, r);
-#endif
+
+    if (transform && !transform->isIdentity()) {
+        restore();
+    }
 
     return DrawGlInfo::kStatusDrew;
 }
@@ -2723,23 +2990,11 @@
             underlineWidth = paintCopy.measureText(text, bytesCount);
         }
 
-        float offsetX = 0;
-        switch (paintCopy.getTextAlign()) {
-            case SkPaint::kCenter_Align:
-                offsetX = underlineWidth * 0.5f;
-                break;
-            case SkPaint::kRight_Align:
-                offsetX = underlineWidth;
-                break;
-            default:
-                break;
-        }
-
         if (CC_LIKELY(underlineWidth > 0.0f)) {
             const float textSize = paintCopy.getTextSize();
             const float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
 
-            const float left = x - offsetX;
+            const float left = x;
             float top = 0.0f;
 
             int linesCount = 0;
@@ -2865,7 +3120,7 @@
         // the blending, turn blending off here
         // If the blend mode cannot be implemented using shaders, fall
         // back to the default SrcOver blend mode instead
-        if CC_UNLIKELY((mode > SkXfermode::kScreen_Mode)) {
+        if (CC_UNLIKELY(mode > SkXfermode::kScreen_Mode)) {
             if (CC_UNLIKELY(mCaches.extensions.hasFramebufferFetch())) {
                 description.framebufferMode = mode;
                 description.swapSrcDst = swapSrcDst;
@@ -2918,30 +3173,9 @@
 }
 
 void OpenGLRenderer::getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
-    if (paint) {
-        *mode = getXfermode(paint->getXfermode());
-
-        // Skia draws using the color's alpha channel if < 255
-        // Otherwise, it uses the paint's alpha
-        int color = paint->getColor();
-        *alpha = (color >> 24) & 0xFF;
-        if (*alpha == 255) {
-            *alpha = paint->getAlpha();
-        }
-    } else {
-        *mode = SkXfermode::kSrcOver_Mode;
-        *alpha = 255;
-    }
+    getAlphaAndModeDirect(paint, alpha,  mode);
     *alpha *= mSnapshot->alpha;
 }
 
-SkXfermode::Mode OpenGLRenderer::getXfermode(SkXfermode* mode) {
-    SkXfermode::Mode resultMode;
-    if (!SkXfermode::AsMode(mode, &resultMode)) {
-        resultMode = SkXfermode::kSrcOver_Mode;
-    }
-    return resultMode;
-}
-
 }; // namespace uirenderer
 }; // namespace android
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 7aac87c..c5e4c8e 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -63,16 +63,74 @@
     ANDROID_API OpenGLRenderer();
     virtual ~OpenGLRenderer();
 
+    /**
+     * Read externally defined properties to control the behavior
+     * of the renderer.
+     */
+    ANDROID_API void initProperties();
+
+    /**
+     * Indicates whether this renderer executes drawing commands immediately.
+     * If this method returns true, the drawing commands will be executed
+     * later.
+     */
     virtual bool isDeferred();
 
+    /**
+     * Sets the dimension of the underlying drawing surface. This method must
+     * be called at least once every time the drawing surface changes size.
+     *
+     * @param width The width in pixels of the underlysing surface
+     * @param height The height in pixels of the underlysing surface
+     */
     virtual void setViewport(int width, int height);
 
-    ANDROID_API int prepare(bool opaque);
-    virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
+    /**
+     * Prepares the renderer to draw a frame. This method must be invoked
+     * at the beginning of each frame. When this method is invoked, the
+     * entire drawing surface is assumed to be redrawn.
+     *
+     * @param opaque If true, the target surface is considered opaque
+     *               and will not be cleared. If false, the target surface
+     *               will be cleared
+     */
+    ANDROID_API status_t prepare(bool opaque);
+
+    /**
+     * Prepares the renderer to draw a frame. This method must be invoked
+     * at the beginning of each frame. Only the specified rectangle of the
+     * frame is assumed to be dirty. A clip will automatically be set to
+     * the specified rectangle.
+     *
+     * @param left The left coordinate of the dirty rectangle
+     * @param top The top coordinate of the dirty rectangle
+     * @param right The right coordinate of the dirty rectangle
+     * @param bottom The bottom coordinate of the dirty rectangle
+     * @param opaque If true, the target surface is considered opaque
+     *               and will not be cleared. If false, the target surface
+     *               will be cleared in the specified dirty rectangle
+     */
+    virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
+
+    /**
+     * Indicates the end of a frame. This method must be invoked whenever
+     * the caller is done rendering a frame.
+     */
     virtual void finish();
 
-    // These two calls must not be recorded in display lists
+    /**
+     * This method must be invoked before handing control over to a draw functor.
+     * See callDrawGLFunction() for instance.
+     *
+     * This command must not be recorded inside display lists.
+     */
     virtual void interrupt();
+
+    /**
+     * This method must be invoked after getting control back from a draw functor.
+     *
+     * This command must not be recorded inside display lists.
+     */
     virtual void resume();
 
     ANDROID_API status_t invokeFunctors(Rect& dirty);
@@ -80,6 +138,9 @@
     ANDROID_API void attachFunctor(Functor* functor);
     virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty);
 
+    ANDROID_API void pushLayerUpdate(Layer* layer);
+    ANDROID_API void clearLayerUpdates();
+
     ANDROID_API int getSaveCount() const;
     virtual int save(int flags);
     virtual void restore();
@@ -90,10 +151,6 @@
     virtual int saveLayerAlpha(float left, float top, float right, float bottom,
             int alpha, int flags);
 
-    void setAlpha(float alpha) {
-        mSnapshot->alpha = alpha;
-    }
-
     virtual void translate(float dx, float dy);
     virtual void rotate(float degrees);
     virtual void scale(float sx, float sy);
@@ -105,6 +162,7 @@
 
     ANDROID_API const Rect& getClipBounds();
     ANDROID_API bool quickReject(float left, float top, float right, float bottom);
+    bool quickRejectNoScissor(float left, float top, float right, float bottom);
     virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
     virtual Rect* getClipRect();
 
@@ -123,6 +181,9 @@
     virtual status_t drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
             const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
             float left, float top, float right, float bottom, SkPaint* paint);
+    status_t drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
+            const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
+            float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode);
     virtual status_t drawColor(int color, SkXfermode::Mode mode);
     virtual status_t drawRect(float left, float top, float right, float bottom, SkPaint* paint);
     virtual status_t drawRoundRect(float left, float top, float right, float bottom,
@@ -134,12 +195,12 @@
     virtual status_t drawPath(SkPath* path, SkPaint* paint);
     virtual status_t drawLines(float* points, int count, SkPaint* paint);
     virtual status_t drawPoints(float* points, int count, SkPaint* paint);
-    virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y,
-            SkPaint* paint, float length = -1.0f);
     virtual status_t drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
             float hOffset, float vOffset, SkPaint* paint);
     virtual status_t drawPosText(const char* text, int bytesCount, int count,
             const float* positions, SkPaint* paint);
+    virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y,
+            const float* positions, SkPaint* paint, float length = -1.0f);
 
     virtual void resetShader();
     virtual void setupShader(SkiaShader* shader);
@@ -155,13 +216,70 @@
 
     SkPaint* filterPaint(SkPaint* paint);
 
-    ANDROID_API static uint32_t getStencilSize();
+    /**
+     * Sets the alpha on the current snapshot. This alpha value will be modulated
+     * with other alpha values when drawing primitives.
+     */
+    void setAlpha(float alpha) {
+        mSnapshot->alpha = alpha;
+    }
 
+    /**
+     * Inserts a named group marker in the stream of GL commands. This marker
+     * can be used by tools to group commands into logical groups. A call to
+     * this method must always be followed later on by a call to endMark().
+     */
     void startMark(const char* name) const;
+
+    /**
+     * Closes the last group marker opened by startMark().
+     */
     void endMark() const;
 
+    /**
+     * Gets the alpha and xfermode out of a paint object. If the paint is null
+     * alpha will be 255 and the xfermode will be SRC_OVER. This method does
+     * not multiply the paint's alpha by the current snapshot's alpha.
+     *
+     * @param paint The paint to extract values from
+     * @param alpha Where to store the resulting alpha
+     * @param mode Where to store the resulting xfermode
+     */
+    static inline void getAlphaAndModeDirect(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
+        if (paint) {
+            *mode = getXfermode(paint->getXfermode());
+
+            // Skia draws using the color's alpha channel if < 255
+            // Otherwise, it uses the paint's alpha
+            int color = paint->getColor();
+            *alpha = (color >> 24) & 0xFF;
+            if (*alpha == 255) {
+                *alpha = paint->getAlpha();
+            }
+        } else {
+            *mode = SkXfermode::kSrcOver_Mode;
+            *alpha = 255;
+        }
+    }
+
 protected:
     /**
+     * Computes the projection matrix, initialize the first snapshot
+     * and stores the dimensions of the render target.
+     */
+    void initViewport(int width, int height);
+
+    /**
+     * Clears the underlying surface if needed.
+     */
+    virtual status_t clear(float left, float top, float right, float bottom, bool opaque);
+
+    /**
+     * Call this method after updating a layer during a drawing pass.
+     */
+    void resumeAfterLayer();
+
+    /**
      * Compose the layer defined in the current snapshot with the layer
      * defined by the previous snapshot.
      *
@@ -213,6 +331,39 @@
      */
     void drawTextureLayer(Layer* layer, const Rect& rect);
 
+    /**
+     * Gets the alpha and xfermode out of a paint object. If the paint is null
+     * alpha will be 255 and the xfermode will be SRC_OVER.
+     *
+     * @param paint The paint to extract values from
+     * @param alpha Where to store the resulting alpha
+     * @param mode Where to store the resulting xfermode
+     */
+    inline void getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode);
+
+    /**
+     * Safely retrieves the mode from the specified xfermode. If the specified
+     * xfermode is null, the mode is assumed to be SkXfermode::kSrcOver_Mode.
+     */
+    static inline SkXfermode::Mode getXfermode(SkXfermode* mode) {
+        SkXfermode::Mode resultMode;
+        if (!SkXfermode::AsMode(mode, &resultMode)) {
+            resultMode = SkXfermode::kSrcOver_Mode;
+        }
+        return resultMode;
+    }
+
+    /**
+     * Set to true to suppress error checks at the end of a frame.
+     */
+    virtual bool suppressErrorChecks() {
+        return false;
+    }
+
+    Caches& getCaches() {
+        return mCaches;
+    }
+
 private:
     /**
      * Ensures the state of the renderer is the same as the state of
@@ -221,6 +372,19 @@
     void syncState();
 
     /**
+     * Tells the GPU what part of the screen is about to be redrawn.
+     * This method needs to be invoked every time getTargetFbo() is
+     * bound again.
+     */
+    void startTiling(const sp<Snapshot>& snapshot, bool opaque = false);
+
+    /**
+     * Tells the GPU that we are done drawing the frame or that we
+     * are switching to another render target.
+     */
+    void endTiling();
+
+    /**
      * Saves the current state of the renderer as a new snapshot.
      * The new snapshot is saved in mSnapshot and the previous snapshot
      * is linked from mSnapshot->previous.
@@ -245,6 +409,18 @@
     void setScissorFromClip();
 
     /**
+     * Performs a quick reject but does not affect the scissor. Returns
+     * the transformed rect to test and the current clip.
+     */
+    bool quickRejectNoScissor(float left, float top, float right, float bottom,
+            Rect& transformed, Rect& clip);
+
+    /**
+     * Performs a quick reject but adjust the bounds to account for stroke width if necessary
+     */
+    bool quickRejectPreStroke(float left, float top, float right, float bottom, SkPaint* paint);
+
+    /**
      * Creates a new layer stored in the specified snapshot.
      *
      * @param snapshot The snapshot associated with the new layer
@@ -259,7 +435,7 @@
      *
      * @return True if the layer was successfully created, false otherwise
      */
-    bool createLayer(sp<Snapshot> snapshot, float left, float top, float right, float bottom,
+    bool createLayer(float left, float top, float right, float bottom,
             int alpha, SkXfermode::Mode mode, int flags, GLuint previousFbo);
 
     /**
@@ -270,8 +446,7 @@
      * @param bounds The bounds of the layer
      * @param previousFbo The name of the current framebuffer
      */
-    bool createFboLayer(Layer* layer, Rect& bounds, sp<Snapshot> snapshot,
-            GLuint previousFbo);
+    bool createFboLayer(Layer* layer, Rect& bounds, Rect& clip, GLuint previousFbo);
 
     /**
      * Compose the specified layer as a region.
@@ -320,7 +495,6 @@
      * @param color The rectangle's ARGB color, defined as a packed 32 bits word
      * @param mode The Skia xfermode to use
      * @param ignoreTransform True if the current transform should be ignored
-     * @param ignoreBlending True if the blending is set by the caller
      */
     void drawColorRect(float left, float top, float right, float bottom,
             int color, SkXfermode::Mode mode, bool ignoreTransform = false);
@@ -339,19 +513,6 @@
     status_t drawShape(float left, float top, const PathTexture* texture, SkPaint* paint);
 
     /**
-     * Renders the rect defined by the specified bounds as a shape.
-     * This will render the rect using a path texture, which is used to render
-     * rects with stroke effects.
-     *
-     * @param left The left coordinate of the rect to draw
-     * @param top The top coordinate of the rect to draw
-     * @param right The right coordinate of the rect to draw
-     * @param bottom The bottom coordinate of the rect to draw
-     * @param p The paint to draw the rect with
-     */
-    status_t drawRectAsShape(float left, float top, float right, float bottom, SkPaint* p);
-
-    /**
      * Draws the specified texture as an alpha bitmap. Alpha bitmaps obey
      * different compositing rules.
      *
@@ -363,17 +524,12 @@
     void drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint);
 
     /**
-     * Renders the rect defined by the specified bounds as an anti-aliased rect.
+     * Renders the convex hull defined by the specified path as a strip of polygons.
      *
-     * @param left The left coordinate of the rect to draw
-     * @param top The top coordinate of the rect to draw
-     * @param right The right coordinate of the rect to draw
-     * @param bottom The bottom coordinate of the rect to draw
-     * @param color The color of the rect
-     * @param mode The blending mode to draw the rect
+     * @param path The hull of the path to draw
+     * @param paint The paint to render with
      */
-    void drawAARect(float left, float top, float right, float bottom,
-            int color, SkXfermode::Mode mode);
+    void drawConvexPath(const SkPath& path, SkPaint* paint);
 
     /**
      * Draws a textured rectangle with the specified texture. The specified coordinates
@@ -446,6 +602,24 @@
     void drawTextDecorations(const char* text, int bytesCount, float length,
             float x, float y, SkPaint* paint);
 
+   /**
+     * Draws shadow layer on text (with optional positions).
+     *
+     * @param paint The paint to draw the shadow with
+     * @param text The text to draw
+     * @param bytesCount The number of bytes in the text
+     * @param count The number of glyphs in the text
+     * @param positions The x, y positions of individual glyphs (or NULL)
+     * @param fontRenderer The font renderer object
+     * @param alpha The alpha value for drawing the shadow
+     * @param mode The xfermode for drawing the shadow
+     * @param x The x coordinate where the shadow will be drawn
+     * @param y The y coordinate where the shadow will be drawn
+     */
+    void drawTextShadow(SkPaint* paint, const char* text, int bytesCount, int count,
+            const float* positions, FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode,
+            float x, float y);
+
     /**
      * Draws a path texture. Path textures are alpha8 bitmaps that need special
      * compositing to apply colors/filters/etc.
@@ -455,7 +629,7 @@
      * @param y The y coordinate where the texture will be drawn
      * @param paint The paint to draw the texture with
      */
-    void drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint);
+     void drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint);
 
     /**
      * Resets the texture coordinates stored in mMeshVertices. Setting the values
@@ -471,16 +645,6 @@
     void resetDrawTextureTexCoords(float u1, float v1, float u2, float v2);
 
     /**
-     * Gets the alpha and xfermode out of a paint object. If the paint is null
-     * alpha will be 255 and the xfermode will be SRC_OVER.
-     *
-     * @param paint The paint to extract values from
-     * @param alpha Where to store the resulting alpha
-     * @param mode Where to store the resulting xfermode
-     */
-    inline void getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode);
-
-    /**
      * Binds the specified texture. The texture unit must have been selected
      * prior to calling this method.
      */
@@ -504,12 +668,6 @@
             bool swapSrcDst = false);
 
     /**
-     * Safely retrieves the mode from the specified xfermode. If the specified
-     * xfermode is null, the mode is assumed to be SkXfermode::kSrcOver_Mode.
-     */
-    inline SkXfermode::Mode getXfermode(SkXfermode* mode);
-
-    /**
      * Use the specified program with the current GL context. If the program is already
      * in use, it will not be bound again. If it is not in use, the current program is
      * marked unused and the specified program becomes used and becomes the new
@@ -525,18 +683,21 @@
      * Invoked before any drawing operation. This sets required state.
      */
     void setupDraw(bool clear = true);
+
     /**
      * Various methods to setup OpenGL rendering.
      */
     void setupDrawWithTexture(bool isAlpha8 = false);
     void setupDrawWithExternalTexture();
     void setupDrawNoTexture();
-    void setupDrawAALine();
+    void setupDrawAA();
+    void setupDrawVertexShape();
     void setupDrawPoint(float pointSize);
     void setupDrawColor(int color);
     void setupDrawColor(int color, int alpha);
     void setupDrawColor(float r, float g, float b, float a);
     void setupDrawAlpha8Color(int color, int alpha);
+    void setupDrawTextGamma(const SkPaint* paint);
     void setupDrawShader();
     void setupDrawColorFilter();
     void setupDrawBlending(SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode,
@@ -561,6 +722,7 @@
     void setupDrawExternalTexture(GLuint texture);
     void setupDrawTextureTransform();
     void setupDrawTextureTransformUniforms(mat4& transform);
+    void setupDrawTextGammaUniforms();
     void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords = NULL, GLuint vbo = 0);
     void setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords);
     void setupDrawVertices(GLvoid* vertices);
@@ -570,8 +732,18 @@
     void finishDrawTexture();
     void accountForClear(SkXfermode::Mode mode);
 
+    bool updateLayer(Layer* layer, bool inFrame);
+    void updateLayers();
+
+    /**
+     * Renders the specified region as a series of rectangles. This method
+     * is used for debugging only.
+     */
     void drawRegionRects(const Region& region);
 
+    void debugOverdraw(bool enable, bool clear);
+    void renderOverdraw();
+
     /**
      * Should be invoked every time the glScissor is modified.
      */
@@ -594,6 +766,8 @@
     sp<Snapshot> mFirstSnapshot;
     // Current state
     sp<Snapshot> mSnapshot;
+    // State used to define the clipping region
+    sp<Snapshot> mTilingSnapshot;
 
     // Shaders
     SkiaShader* mShader;
@@ -624,6 +798,8 @@
     Vector<Rect*> mLayers;
     // List of functors to invoke after a frame is drawn
     SortedVector<Functor*> mFunctors;
+    // List of layers to update at the beginning of a frame
+    Vector<Layer*> mLayerUpdates;
 
     // Indentity matrix
     const mat4 mIdentity;
@@ -643,6 +819,15 @@
     GLuint mTextureUnit;
     // Track dirty regions, true by default
     bool mTrackDirtyRegions;
+    // Indicate whether we are drawing an opaque frame
+    bool mOpaqueFrame;
+
+    // See PROPERTY_DISABLE_SCISSOR_OPTIMIZATION in
+    // Properties.h
+    bool mScissorOptimizationDisabled;
+
+    // No-ops start/endTiling when set
+    bool mSuppressTiling;
 
     friend class DisplayListRenderer;
 
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 27f530c..902c82f 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -108,9 +108,7 @@
 
 void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
         float left, float top, float right, float bottom) {
-#if RENDER_LAYERS_AS_REGIONS
     if (hasEmptyQuads) quads.clear();
-#endif
 
     // Reset the vertices count here, we will count exactly how many
     // vertices we actually need when generating the quads
@@ -120,7 +118,10 @@
     const uint32_t yStretchCount = (mYCount + 1) >> 1;
 
     float stretchX = 0.0f;
-    float stretchY = 0.0;
+    float stretchY = 0.0f;
+
+    float rescaleX = 1.0f;
+    float rescaleY = 1.0f;
 
     const float meshWidth = right - left;
 
@@ -131,8 +132,9 @@
         }
         const float xStretchTex = stretchSize;
         const float fixed = bitmapWidth - stretchSize;
-        const float xStretch = right - left - fixed;
+        const float xStretch = fmaxf(right - left - fixed, 0.0f);
         stretchX = xStretch / xStretchTex;
+        rescaleX = fixed == 0.0f ? 0.0f : fminf(fmaxf(right - left, 0.0f) / fixed, 1.0f);
     }
 
     if (yStretchCount > 0) {
@@ -142,8 +144,9 @@
         }
         const float yStretchTex = stretchSize;
         const float fixed = bitmapHeight - stretchSize;
-        const float yStretch = bottom - top - fixed;
+        const float yStretch = fmaxf(bottom - top - fixed, 0.0f);
         stretchY = yStretch / yStretchTex;
+        rescaleY = fixed == 0.0f ? 0.0f : fminf(fmaxf(bottom - top, 0.0f) / fixed, 1.0f);
     }
 
     TextureVertex* vertex = mVertices;
@@ -162,7 +165,7 @@
         if (i & 1) {
             y2 = y1 + floorf(segment * stretchY + 0.5f);
         } else {
-            y2 = y1 + segment;
+            y2 = y1 + segment * rescaleY;
         }
 
         float vOffset = y1 == y2 ? 0.0f : 0.5 - (0.5 * segment / (y2 - y1));
@@ -174,7 +177,7 @@
             y1 += i * EXPLODE_GAP;
             y2 += i * EXPLODE_GAP;
 #endif
-            generateRow(vertex, y1, y2, v1, v2, stretchX, right - left,
+            generateRow(vertex, y1, y2, v1, v2, stretchX, rescaleX, right - left,
                     bitmapWidth, quadCount);
 #if DEBUG_EXPLODE_PATCHES
             y2 -= i * EXPLODE_GAP;
@@ -193,7 +196,8 @@
         y1 += mYCount * EXPLODE_GAP;
         y2 += mYCount * EXPLODE_GAP;
 #endif
-        generateRow(vertex, y1, y2, v1, 1.0f, stretchX, right - left, bitmapWidth, quadCount);
+        generateRow(vertex, y1, y2, v1, 1.0f, stretchX, rescaleX, right - left,
+                bitmapWidth, quadCount);
     }
 
     if (verticesCount > 0) {
@@ -214,7 +218,7 @@
 }
 
 void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float v1, float v2,
-        float stretchX, float width, float bitmapWidth, uint32_t& quadCount) {
+        float stretchX, float rescaleX, float width, float bitmapWidth, uint32_t& quadCount) {
     float previousStepX = 0.0f;
 
     float x1 = 0.0f;
@@ -229,7 +233,7 @@
         if (i & 1) {
             x2 = x1 + floorf(segment * stretchX + 0.5f);
         } else {
-            x2 = x1 + segment;
+            x2 = x1 + segment * rescaleX;
         }
 
         float uOffset = x1 == x2 ? 0.0f : 0.5 - (0.5 * segment / (x2 - x1));
@@ -268,8 +272,13 @@
     const uint32_t oldQuadCount = quadCount;
     quadCount++;
 
+    if (x1 < 0.0f) x1 = 0.0f;
+    if (x2 < 0.0f) x2 = 0.0f;
+    if (y1 < 0.0f) y1 = 0.0f;
+    if (y2 < 0.0f) y2 = 0.0f;
+
     // Skip degenerate and transparent (empty) quads
-    if ((mColorKey >> oldQuadCount) & 0x1) {
+    if (((mColorKey >> oldQuadCount) & 0x1) || x1 >= x2 || y1 >= y2) {
 #if DEBUG_PATCHES_EMPTY_VERTICES
         PATCH_LOGD("    quad %d (empty)", oldQuadCount);
         PATCH_LOGD("        left,  top    = %.2f, %.2f\t\tu1, v1 = %.4f, %.4f", x1, y1, u1, v1);
@@ -278,13 +287,11 @@
         return;
     }
 
-#if RENDER_LAYERS_AS_REGIONS
     // Record all non empty quads
     if (hasEmptyQuads) {
         Rect bounds(x1, y1, x2, y2);
         quads.add(bounds);
     }
-#endif
 
     // Left triangle
     TextureVertex::set(vertex++, x1, y1, u1, v1);
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index 28c9048..0518d91 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -75,8 +75,8 @@
     void copy(const int32_t* yDivs);
 
     void generateRow(TextureVertex*& vertex, float y1, float y2,
-            float v1, float v2, float stretchX, float width, float bitmapWidth,
-            uint32_t& quadCount);
+            float v1, float v2, float stretchX, float rescaleX,
+            float width, float bitmapWidth, uint32_t& quadCount);
     void generateQuad(TextureVertex*& vertex,
             float x1, float y1, float x2, float y2,
             float u1, float v1, float u2, float v2,
diff --git a/libs/hwui/PathRenderer.cpp b/libs/hwui/PathRenderer.cpp
new file mode 100644
index 0000000..dd13d79
--- /dev/null
+++ b/libs/hwui/PathRenderer.cpp
@@ -0,0 +1,721 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "PathRenderer"
+#define LOG_NDEBUG 1
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#define VERTEX_DEBUG 0
+
+#include <SkPath.h>
+#include <SkPaint.h>
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include "PathRenderer.h"
+#include "Matrix.h"
+#include "Vector.h"
+#include "Vertex.h"
+
+namespace android {
+namespace uirenderer {
+
+#define THRESHOLD 0.5f
+
+SkRect PathRenderer::computePathBounds(const SkPath& path, const SkPaint* paint) {
+    SkRect bounds = path.getBounds();
+    if (paint->getStyle() != SkPaint::kFill_Style) {
+        float outset = paint->getStrokeWidth() * 0.5f;
+        bounds.outset(outset, outset);
+    }
+    return bounds;
+}
+
+void computeInverseScales(const mat4 *transform, float &inverseScaleX, float& inverseScaleY) {
+    if (CC_UNLIKELY(!transform->isPureTranslate())) {
+        float m00 = transform->data[Matrix4::kScaleX];
+        float m01 = transform->data[Matrix4::kSkewY];
+        float m10 = transform->data[Matrix4::kSkewX];
+        float m11 = transform->data[Matrix4::kScaleY];
+        float scaleX = sqrt(m00 * m00 + m01 * m01);
+        float scaleY = sqrt(m10 * m10 + m11 * m11);
+        inverseScaleX = (scaleX != 0) ? (1.0f / scaleX) : 1.0f;
+        inverseScaleY = (scaleY != 0) ? (1.0f / scaleY) : 1.0f;
+    } else {
+        inverseScaleX = 1.0f;
+        inverseScaleY = 1.0f;
+    }
+}
+
+inline void copyVertex(Vertex* destPtr, const Vertex* srcPtr) {
+    Vertex::set(destPtr, srcPtr->position[0], srcPtr->position[1]);
+}
+
+inline void copyAlphaVertex(AlphaVertex* destPtr, const AlphaVertex* srcPtr) {
+    AlphaVertex::set(destPtr, srcPtr->position[0], srcPtr->position[1], srcPtr->alpha);
+}
+
+/**
+ * Produces a pseudo-normal for a vertex, given the normals of the two incoming lines. If the offset
+ * from each vertex in a perimeter is calculated, the resultant lines connecting the offset vertices
+ * will be offset by 1.0
+ *
+ * Note that we can't add and normalize the two vectors, that would result in a rectangle having an
+ * offset of (sqrt(2)/2, sqrt(2)/2) at each corner, instead of (1, 1)
+ *
+ * NOTE: assumes angles between normals 90 degrees or less
+ */
+inline vec2 totalOffsetFromNormals(const vec2& normalA, const vec2& normalB) {
+    return (normalA + normalB) / (1 + fabs(normalA.dot(normalB)));
+}
+
+inline void scaleOffsetForStrokeWidth(vec2& offset, float halfStrokeWidth,
+        float inverseScaleX, float inverseScaleY) {
+    if (halfStrokeWidth == 0.0f) {
+        // hairline - compensate for scale
+        offset.x *= 0.5f * inverseScaleX;
+        offset.y *= 0.5f * inverseScaleY;
+    } else {
+        offset *= halfStrokeWidth;
+    }
+}
+
+void getFillVerticesFromPerimeter(const Vector<Vertex>& perimeter, VertexBuffer& vertexBuffer) {
+    Vertex* buffer = vertexBuffer.alloc<Vertex>(perimeter.size());
+
+    int currentIndex = 0;
+    // zig zag between all previous points on the inside of the hull to create a
+    // triangle strip that fills the hull
+    int srcAindex = 0;
+    int srcBindex = perimeter.size() - 1;
+    while (srcAindex <= srcBindex) {
+        copyVertex(&buffer[currentIndex++], &perimeter[srcAindex]);
+        if (srcAindex == srcBindex) break;
+        copyVertex(&buffer[currentIndex++], &perimeter[srcBindex]);
+        srcAindex++;
+        srcBindex--;
+    }
+}
+
+void getStrokeVerticesFromPerimeter(const Vector<Vertex>& perimeter, float halfStrokeWidth,
+        VertexBuffer& vertexBuffer, float inverseScaleX, float inverseScaleY) {
+    Vertex* buffer = vertexBuffer.alloc<Vertex>(perimeter.size() * 2 + 2);
+
+    int currentIndex = 0;
+    const Vertex* last = &(perimeter[perimeter.size() - 1]);
+    const Vertex* current = &(perimeter[0]);
+    vec2 lastNormal(current->position[1] - last->position[1],
+            last->position[0] - current->position[0]);
+    lastNormal.normalize();
+    for (unsigned int i = 0; i < perimeter.size(); i++) {
+        const Vertex* next = &(perimeter[i + 1 >= perimeter.size() ? 0 : i + 1]);
+        vec2 nextNormal(next->position[1] - current->position[1],
+                current->position[0] - next->position[0]);
+        nextNormal.normalize();
+
+        vec2 totalOffset = totalOffsetFromNormals(lastNormal, nextNormal);
+        scaleOffsetForStrokeWidth(totalOffset, halfStrokeWidth, inverseScaleX, inverseScaleY);
+
+        Vertex::set(&buffer[currentIndex++],
+                current->position[0] + totalOffset.x,
+                current->position[1] + totalOffset.y);
+
+        Vertex::set(&buffer[currentIndex++],
+                current->position[0] - totalOffset.x,
+                current->position[1] - totalOffset.y);
+
+        last = current;
+        current = next;
+        lastNormal = nextNormal;
+    }
+
+    // wrap around to beginning
+    copyVertex(&buffer[currentIndex++], &buffer[0]);
+    copyVertex(&buffer[currentIndex++], &buffer[1]);
+}
+
+void getStrokeVerticesFromUnclosedVertices(const Vector<Vertex>& vertices, float halfStrokeWidth,
+        VertexBuffer& vertexBuffer, float inverseScaleX, float inverseScaleY) {
+    Vertex* buffer = vertexBuffer.alloc<Vertex>(vertices.size() * 2);
+
+    int currentIndex = 0;
+    const Vertex* current = &(vertices[0]);
+    vec2 lastNormal;
+    for (unsigned int i = 0; i < vertices.size() - 1; i++) {
+        const Vertex* next = &(vertices[i + 1]);
+        vec2 nextNormal(next->position[1] - current->position[1],
+                current->position[0] - next->position[0]);
+        nextNormal.normalize();
+
+        vec2 totalOffset;
+        if (i == 0) {
+            totalOffset = nextNormal;
+        } else {
+            totalOffset = totalOffsetFromNormals(lastNormal, nextNormal);
+        }
+        scaleOffsetForStrokeWidth(totalOffset, halfStrokeWidth, inverseScaleX, inverseScaleY);
+
+        Vertex::set(&buffer[currentIndex++],
+                current->position[0] + totalOffset.x,
+                current->position[1] + totalOffset.y);
+
+        Vertex::set(&buffer[currentIndex++],
+                current->position[0] - totalOffset.x,
+                current->position[1] - totalOffset.y);
+
+        current = next;
+        lastNormal = nextNormal;
+    }
+
+    vec2 totalOffset = lastNormal;
+    scaleOffsetForStrokeWidth(totalOffset, halfStrokeWidth, inverseScaleX, inverseScaleY);
+
+    Vertex::set(&buffer[currentIndex++],
+            current->position[0] + totalOffset.x,
+            current->position[1] + totalOffset.y);
+    Vertex::set(&buffer[currentIndex++],
+            current->position[0] - totalOffset.x,
+            current->position[1] - totalOffset.y);
+#if VERTEX_DEBUG
+    for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) {
+        ALOGD("point at %f %f", buffer[i].position[0], buffer[i].position[1]);
+    }
+#endif
+}
+
+void getFillVerticesFromPerimeterAA(const Vector<Vertex>& perimeter, VertexBuffer& vertexBuffer,
+         float inverseScaleX, float inverseScaleY) {
+    AlphaVertex* buffer = vertexBuffer.alloc<AlphaVertex>(perimeter.size() * 3 + 2);
+
+    // generate alpha points - fill Alpha vertex gaps in between each point with
+    // alpha 0 vertex, offset by a scaled normal.
+    int currentIndex = 0;
+    const Vertex* last = &(perimeter[perimeter.size() - 1]);
+    const Vertex* current = &(perimeter[0]);
+    vec2 lastNormal(current->position[1] - last->position[1],
+            last->position[0] - current->position[0]);
+    lastNormal.normalize();
+    for (unsigned int i = 0; i < perimeter.size(); i++) {
+        const Vertex* next = &(perimeter[i + 1 >= perimeter.size() ? 0 : i + 1]);
+        vec2 nextNormal(next->position[1] - current->position[1],
+                current->position[0] - next->position[0]);
+        nextNormal.normalize();
+
+        // AA point offset from original point is that point's normal, such that each side is offset
+        // by .5 pixels
+        vec2 totalOffset = totalOffsetFromNormals(lastNormal, nextNormal);
+        totalOffset.x *= 0.5f * inverseScaleX;
+        totalOffset.y *= 0.5f * inverseScaleY;
+
+        AlphaVertex::set(&buffer[currentIndex++],
+                current->position[0] + totalOffset.x,
+                current->position[1] + totalOffset.y,
+                0.0f);
+        AlphaVertex::set(&buffer[currentIndex++],
+                current->position[0] - totalOffset.x,
+                current->position[1] - totalOffset.y,
+                1.0f);
+
+        last = current;
+        current = next;
+        lastNormal = nextNormal;
+    }
+
+    // wrap around to beginning
+    copyAlphaVertex(&buffer[currentIndex++], &buffer[0]);
+    copyAlphaVertex(&buffer[currentIndex++], &buffer[1]);
+
+    // zig zag between all previous points on the inside of the hull to create a
+    // triangle strip that fills the hull, repeating the first inner point to
+    // create degenerate tris to start inside path
+    int srcAindex = 0;
+    int srcBindex = perimeter.size() - 1;
+    while (srcAindex <= srcBindex) {
+        copyAlphaVertex(&buffer[currentIndex++], &buffer[srcAindex * 2 + 1]);
+        if (srcAindex == srcBindex) break;
+        copyAlphaVertex(&buffer[currentIndex++], &buffer[srcBindex * 2 + 1]);
+        srcAindex++;
+        srcBindex--;
+    }
+
+#if VERTEX_DEBUG
+    for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) {
+        ALOGD("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha);
+    }
+#endif
+}
+
+
+void getStrokeVerticesFromUnclosedVerticesAA(const Vector<Vertex>& vertices, float halfStrokeWidth,
+        VertexBuffer& vertexBuffer, float inverseScaleX, float inverseScaleY) {
+    AlphaVertex* buffer = vertexBuffer.alloc<AlphaVertex>(6 * vertices.size() + 2);
+
+    // avoid lines smaller than hairline since they break triangle based sampling. instead reducing
+    // alpha value (TODO: support different X/Y scale)
+    float maxAlpha = 1.0f;
+    if (halfStrokeWidth != 0 && inverseScaleX == inverseScaleY &&
+            halfStrokeWidth * inverseScaleX < 0.5f) {
+        maxAlpha *= (2 * halfStrokeWidth) / inverseScaleX;
+        halfStrokeWidth = 0.0f;
+    }
+
+    // there is no outer/inner here, using them for consistency with below approach
+    int offset = 2 * (vertices.size() - 2);
+    int currentAAOuterIndex = 2;
+    int currentAAInnerIndex = 2 * offset + 5; // reversed
+    int currentStrokeIndex = currentAAInnerIndex + 7;
+
+    const Vertex* last = &(vertices[0]);
+    const Vertex* current = &(vertices[1]);
+    vec2 lastNormal(current->position[1] - last->position[1],
+            last->position[0] - current->position[0]);
+    lastNormal.normalize();
+
+    {
+        // start cap
+        vec2 totalOffset = lastNormal;
+        vec2 AAOffset = totalOffset;
+        AAOffset.x *= 0.5f * inverseScaleX;
+        AAOffset.y *= 0.5f * inverseScaleY;
+
+        vec2 innerOffset = totalOffset;
+        scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY);
+        vec2 outerOffset = innerOffset + AAOffset;
+        innerOffset -= AAOffset;
+
+        // TODO: support square cap by changing this offset to incorporate halfStrokeWidth
+        vec2 capAAOffset(AAOffset.y, -AAOffset.x);
+        AlphaVertex::set(&buffer[0],
+                last->position[0] + outerOffset.x + capAAOffset.x,
+                last->position[1] + outerOffset.y + capAAOffset.y,
+                0.0f);
+        AlphaVertex::set(&buffer[1],
+                last->position[0] + innerOffset.x - capAAOffset.x,
+                last->position[1] + innerOffset.y - capAAOffset.y,
+                maxAlpha);
+
+        AlphaVertex::set(&buffer[2 * offset + 6],
+                last->position[0] - outerOffset.x + capAAOffset.x,
+                last->position[1] - outerOffset.y + capAAOffset.y,
+                0.0f);
+        AlphaVertex::set(&buffer[2 * offset + 7],
+                last->position[0] - innerOffset.x - capAAOffset.x,
+                last->position[1] - innerOffset.y - capAAOffset.y,
+                maxAlpha);
+        copyAlphaVertex(&buffer[2 * offset + 8], &buffer[0]);
+        copyAlphaVertex(&buffer[2 * offset + 9], &buffer[1]);
+        copyAlphaVertex(&buffer[2 * offset + 10], &buffer[1]); // degenerate tris (the only two!)
+        copyAlphaVertex(&buffer[2 * offset + 11], &buffer[2 * offset + 7]);
+    }
+
+    for (unsigned int i = 1; i < vertices.size() - 1; i++) {
+        const Vertex* next = &(vertices[i + 1]);
+        vec2 nextNormal(next->position[1] - current->position[1],
+                current->position[0] - next->position[0]);
+        nextNormal.normalize();
+
+        vec2 totalOffset = totalOffsetFromNormals(lastNormal, nextNormal);
+        vec2 AAOffset = totalOffset;
+        AAOffset.x *= 0.5f * inverseScaleX;
+        AAOffset.y *= 0.5f * inverseScaleY;
+
+        vec2 innerOffset = totalOffset;
+        scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY);
+        vec2 outerOffset = innerOffset + AAOffset;
+        innerOffset -= AAOffset;
+
+        AlphaVertex::set(&buffer[currentAAOuterIndex++],
+                current->position[0] + outerOffset.x,
+                current->position[1] + outerOffset.y,
+                0.0f);
+        AlphaVertex::set(&buffer[currentAAOuterIndex++],
+                current->position[0] + innerOffset.x,
+                current->position[1] + innerOffset.y,
+                maxAlpha);
+
+        AlphaVertex::set(&buffer[currentStrokeIndex++],
+                current->position[0] + innerOffset.x,
+                current->position[1] + innerOffset.y,
+                maxAlpha);
+        AlphaVertex::set(&buffer[currentStrokeIndex++],
+                current->position[0] - innerOffset.x,
+                current->position[1] - innerOffset.y,
+                maxAlpha);
+
+        AlphaVertex::set(&buffer[currentAAInnerIndex--],
+                current->position[0] - innerOffset.x,
+                current->position[1] - innerOffset.y,
+                maxAlpha);
+        AlphaVertex::set(&buffer[currentAAInnerIndex--],
+                current->position[0] - outerOffset.x,
+                current->position[1] - outerOffset.y,
+                0.0f);
+
+        last = current;
+        current = next;
+        lastNormal = nextNormal;
+    }
+
+    {
+        // end cap
+        vec2 totalOffset = lastNormal;
+        vec2 AAOffset = totalOffset;
+        AAOffset.x *= 0.5f * inverseScaleX;
+        AAOffset.y *= 0.5f * inverseScaleY;
+
+        vec2 innerOffset = totalOffset;
+        scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY);
+        vec2 outerOffset = innerOffset + AAOffset;
+        innerOffset -= AAOffset;
+
+        // TODO: support square cap by changing this offset to incorporate halfStrokeWidth
+        vec2 capAAOffset(-AAOffset.y, AAOffset.x);
+
+        AlphaVertex::set(&buffer[offset + 2],
+                current->position[0] + outerOffset.x + capAAOffset.x,
+                current->position[1] + outerOffset.y + capAAOffset.y,
+                0.0f);
+        AlphaVertex::set(&buffer[offset + 3],
+                current->position[0] + innerOffset.x - capAAOffset.x,
+                current->position[1] + innerOffset.y - capAAOffset.y,
+                maxAlpha);
+
+        AlphaVertex::set(&buffer[offset + 4],
+                current->position[0] - outerOffset.x + capAAOffset.x,
+                current->position[1] - outerOffset.y + capAAOffset.y,
+                0.0f);
+        AlphaVertex::set(&buffer[offset + 5],
+                current->position[0] - innerOffset.x - capAAOffset.x,
+                current->position[1] - innerOffset.y - capAAOffset.y,
+                maxAlpha);
+
+        copyAlphaVertex(&buffer[vertexBuffer.getSize() - 2], &buffer[offset + 3]);
+        copyAlphaVertex(&buffer[vertexBuffer.getSize() - 1], &buffer[offset + 5]);
+    }
+
+#if VERTEX_DEBUG
+    for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) {
+        ALOGD("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha);
+    }
+#endif
+}
+
+
+void getStrokeVerticesFromPerimeterAA(const Vector<Vertex>& perimeter, float halfStrokeWidth,
+        VertexBuffer& vertexBuffer, float inverseScaleX, float inverseScaleY) {
+    AlphaVertex* buffer = vertexBuffer.alloc<AlphaVertex>(6 * perimeter.size() + 8);
+
+    // avoid lines smaller than hairline since they break triangle based sampling. instead reducing
+    // alpha value (TODO: support different X/Y scale)
+    float maxAlpha = 1.0f;
+    if (halfStrokeWidth != 0 && inverseScaleX == inverseScaleY &&
+            halfStrokeWidth * inverseScaleX < 0.5f) {
+        maxAlpha *= (2 * halfStrokeWidth) / inverseScaleX;
+        halfStrokeWidth = 0.0f;
+    }
+
+    int offset = 2 * perimeter.size() + 3;
+    int currentAAOuterIndex = 0;
+    int currentStrokeIndex = offset;
+    int currentAAInnerIndex = offset * 2;
+
+    const Vertex* last = &(perimeter[perimeter.size() - 1]);
+    const Vertex* current = &(perimeter[0]);
+    vec2 lastNormal(current->position[1] - last->position[1],
+            last->position[0] - current->position[0]);
+    lastNormal.normalize();
+    for (unsigned int i = 0; i < perimeter.size(); i++) {
+        const Vertex* next = &(perimeter[i + 1 >= perimeter.size() ? 0 : i + 1]);
+        vec2 nextNormal(next->position[1] - current->position[1],
+                current->position[0] - next->position[0]);
+        nextNormal.normalize();
+
+        vec2 totalOffset = totalOffsetFromNormals(lastNormal, nextNormal);
+        vec2 AAOffset = totalOffset;
+        AAOffset.x *= 0.5f * inverseScaleX;
+        AAOffset.y *= 0.5f * inverseScaleY;
+
+        vec2 innerOffset = totalOffset;
+        scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY);
+        vec2 outerOffset = innerOffset + AAOffset;
+        innerOffset -= AAOffset;
+
+        AlphaVertex::set(&buffer[currentAAOuterIndex++],
+                current->position[0] + outerOffset.x,
+                current->position[1] + outerOffset.y,
+                0.0f);
+        AlphaVertex::set(&buffer[currentAAOuterIndex++],
+                current->position[0] + innerOffset.x,
+                current->position[1] + innerOffset.y,
+                maxAlpha);
+
+        AlphaVertex::set(&buffer[currentStrokeIndex++],
+                current->position[0] + innerOffset.x,
+                current->position[1] + innerOffset.y,
+                maxAlpha);
+        AlphaVertex::set(&buffer[currentStrokeIndex++],
+                current->position[0] - innerOffset.x,
+                current->position[1] - innerOffset.y,
+                maxAlpha);
+
+        AlphaVertex::set(&buffer[currentAAInnerIndex++],
+                current->position[0] - innerOffset.x,
+                current->position[1] - innerOffset.y,
+                maxAlpha);
+        AlphaVertex::set(&buffer[currentAAInnerIndex++],
+                current->position[0] - outerOffset.x,
+                current->position[1] - outerOffset.y,
+                0.0f);
+
+        last = current;
+        current = next;
+        lastNormal = nextNormal;
+    }
+
+    // wrap each strip around to beginning, creating degenerate tris to bridge strips
+    copyAlphaVertex(&buffer[currentAAOuterIndex++], &buffer[0]);
+    copyAlphaVertex(&buffer[currentAAOuterIndex++], &buffer[1]);
+    copyAlphaVertex(&buffer[currentAAOuterIndex++], &buffer[1]);
+
+    copyAlphaVertex(&buffer[currentStrokeIndex++], &buffer[offset]);
+    copyAlphaVertex(&buffer[currentStrokeIndex++], &buffer[offset + 1]);
+    copyAlphaVertex(&buffer[currentStrokeIndex++], &buffer[offset + 1]);
+
+    copyAlphaVertex(&buffer[currentAAInnerIndex++], &buffer[2 * offset]);
+    copyAlphaVertex(&buffer[currentAAInnerIndex++], &buffer[2 * offset + 1]);
+    // don't need to create last degenerate tri
+
+#if VERTEX_DEBUG
+    for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) {
+        ALOGD("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha);
+    }
+#endif
+}
+
+void PathRenderer::convexPathVertices(const SkPath &path, const SkPaint* paint,
+        const mat4 *transform, VertexBuffer& vertexBuffer) {
+    ATRACE_CALL();
+
+    SkPaint::Style style = paint->getStyle();
+    bool isAA = paint->isAntiAlias();
+
+    float inverseScaleX, inverseScaleY;
+    computeInverseScales(transform, inverseScaleX, inverseScaleY);
+
+    Vector<Vertex> tempVertices;
+    float threshInvScaleX = inverseScaleX;
+    float threshInvScaleY = inverseScaleY;
+    if (style == SkPaint::kStroke_Style) {
+        // alter the bezier recursion threshold values we calculate in order to compensate for
+        // expansion done after the path vertices are found
+        SkRect bounds = path.getBounds();
+        if (!bounds.isEmpty()) {
+            threshInvScaleX *= bounds.width() / (bounds.width() + paint->getStrokeWidth());
+            threshInvScaleY *= bounds.height() / (bounds.height() + paint->getStrokeWidth());
+        }
+    }
+
+    // force close if we're filling the path, since fill path expects closed perimeter.
+    bool forceClose = style != SkPaint::kStroke_Style;
+    bool wasClosed = convexPathPerimeterVertices(path, forceClose, threshInvScaleX * threshInvScaleX,
+            threshInvScaleY * threshInvScaleY, tempVertices);
+
+    if (!tempVertices.size()) {
+        // path was empty, return without allocating vertex buffer
+        return;
+    }
+
+#if VERTEX_DEBUG
+    for (unsigned int i = 0; i < tempVertices.size(); i++) {
+        ALOGD("orig path: point at %f %f", tempVertices[i].position[0], tempVertices[i].position[1]);
+    }
+#endif
+
+    if (style == SkPaint::kStroke_Style) {
+        float halfStrokeWidth = paint->getStrokeWidth() * 0.5f;
+        if (!isAA) {
+            if (wasClosed) {
+                getStrokeVerticesFromPerimeter(tempVertices, halfStrokeWidth, vertexBuffer,
+                        inverseScaleX, inverseScaleY);
+            } else {
+                getStrokeVerticesFromUnclosedVertices(tempVertices, halfStrokeWidth, vertexBuffer,
+                        inverseScaleX, inverseScaleY);
+            }
+
+        } else {
+            if (wasClosed) {
+                getStrokeVerticesFromPerimeterAA(tempVertices, halfStrokeWidth, vertexBuffer,
+                        inverseScaleX, inverseScaleY);
+            } else {
+                getStrokeVerticesFromUnclosedVerticesAA(tempVertices, halfStrokeWidth, vertexBuffer,
+                        inverseScaleX, inverseScaleY);
+            }
+        }
+    } else {
+        // For kStrokeAndFill style, the path should be adjusted externally, as it will be treated as a fill here.
+        if (!isAA) {
+            getFillVerticesFromPerimeter(tempVertices, vertexBuffer);
+        } else {
+            getFillVerticesFromPerimeterAA(tempVertices, vertexBuffer, inverseScaleX, inverseScaleY);
+        }
+    }
+}
+
+
+void pushToVector(Vector<Vertex>& vertices, float x, float y) {
+    // TODO: make this not yuck
+    vertices.push();
+    Vertex* newVertex = &(vertices.editArray()[vertices.size() - 1]);
+    Vertex::set(newVertex, x, y);
+}
+
+bool PathRenderer::convexPathPerimeterVertices(const SkPath& path, bool forceClose,
+        float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex>& outputVertices) {
+    ATRACE_CALL();
+
+    // TODO: to support joins other than sharp miter, join vertices should be labelled in the
+    // perimeter, or resolved into more vertices. Reconsider forceClose-ing in that case.
+    SkPath::Iter iter(path, forceClose);
+    SkPoint pts[4];
+    SkPath::Verb v;
+    Vertex* newVertex = 0;
+    while (SkPath::kDone_Verb != (v = iter.next(pts))) {
+            switch (v) {
+                case SkPath::kMove_Verb:
+                    pushToVector(outputVertices, pts[0].x(), pts[0].y());
+                    ALOGV("Move to pos %f %f", pts[0].x(), pts[0].y());
+                    break;
+                case SkPath::kClose_Verb:
+                    ALOGV("Close at pos %f %f", pts[0].x(), pts[0].y());
+                    break;
+                case SkPath::kLine_Verb:
+                    ALOGV("kLine_Verb %f %f -> %f %f",
+                            pts[0].x(), pts[0].y(),
+                            pts[1].x(), pts[1].y());
+
+                    pushToVector(outputVertices, pts[1].x(), pts[1].y());
+                    break;
+                case SkPath::kQuad_Verb:
+                    ALOGV("kQuad_Verb");
+                    recursiveQuadraticBezierVertices(
+                            pts[0].x(), pts[0].y(),
+                            pts[2].x(), pts[2].y(),
+                            pts[1].x(), pts[1].y(),
+                            sqrInvScaleX, sqrInvScaleY, outputVertices);
+                    break;
+                case SkPath::kCubic_Verb:
+                    ALOGV("kCubic_Verb");
+                    recursiveCubicBezierVertices(
+                            pts[0].x(), pts[0].y(),
+                            pts[1].x(), pts[1].y(),
+                            pts[3].x(), pts[3].y(),
+                            pts[2].x(), pts[2].y(),
+                        sqrInvScaleX, sqrInvScaleY, outputVertices);
+                    break;
+                default:
+                    break;
+            }
+    }
+
+    int size = outputVertices.size();
+    if (size >= 2 && outputVertices[0].position[0] == outputVertices[size - 1].position[0] &&
+            outputVertices[0].position[1] == outputVertices[size - 1].position[1]) {
+        outputVertices.pop();
+        return true;
+    }
+    return false;
+}
+
+void PathRenderer::recursiveCubicBezierVertices(
+        float p1x, float p1y, float c1x, float c1y,
+        float p2x, float p2y, float c2x, float c2y,
+        float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex>& outputVertices) {
+    float dx = p2x - p1x;
+    float dy = p2y - p1y;
+    float d1 = fabs((c1x - p2x) * dy - (c1y - p2y) * dx);
+    float d2 = fabs((c2x - p2x) * dy - (c2y - p2y) * dx);
+    float d = d1 + d2;
+
+    // multiplying by sqrInvScaleY/X equivalent to multiplying in dimensional scale factors
+
+    if (d * d < THRESHOLD * THRESHOLD * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
+        // below thresh, draw line by adding endpoint
+        pushToVector(outputVertices, p2x, p2y);
+    } else {
+        float p1c1x = (p1x + c1x) * 0.5f;
+        float p1c1y = (p1y + c1y) * 0.5f;
+        float p2c2x = (p2x + c2x) * 0.5f;
+        float p2c2y = (p2y + c2y) * 0.5f;
+
+        float c1c2x = (c1x + c2x) * 0.5f;
+        float c1c2y = (c1y + c2y) * 0.5f;
+
+        float p1c1c2x = (p1c1x + c1c2x) * 0.5f;
+        float p1c1c2y = (p1c1y + c1c2y) * 0.5f;
+
+        float p2c1c2x = (p2c2x + c1c2x) * 0.5f;
+        float p2c1c2y = (p2c2y + c1c2y) * 0.5f;
+
+        float mx = (p1c1c2x + p2c1c2x) * 0.5f;
+        float my = (p1c1c2y + p2c1c2y) * 0.5f;
+
+        recursiveCubicBezierVertices(
+                p1x, p1y, p1c1x, p1c1y,
+                mx, my, p1c1c2x, p1c1c2y,
+                sqrInvScaleX, sqrInvScaleY, outputVertices);
+        recursiveCubicBezierVertices(
+                mx, my, p2c1c2x, p2c1c2y,
+                p2x, p2y, p2c2x, p2c2y,
+                sqrInvScaleX, sqrInvScaleY, outputVertices);
+    }
+}
+
+void PathRenderer::recursiveQuadraticBezierVertices(
+        float ax, float ay,
+        float bx, float by,
+        float cx, float cy,
+        float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex>& outputVertices) {
+    float dx = bx - ax;
+    float dy = by - ay;
+    float d = (cx - bx) * dy - (cy - by) * dx;
+
+    if (d * d < THRESHOLD * THRESHOLD * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
+        // below thresh, draw line by adding endpoint
+        pushToVector(outputVertices, bx, by);
+    } else {
+        float acx = (ax + cx) * 0.5f;
+        float bcx = (bx + cx) * 0.5f;
+        float acy = (ay + cy) * 0.5f;
+        float bcy = (by + cy) * 0.5f;
+
+        // midpoint
+        float mx = (acx + bcx) * 0.5f;
+        float my = (acy + bcy) * 0.5f;
+
+        recursiveQuadraticBezierVertices(ax, ay, mx, my, acx, acy,
+                sqrInvScaleX, sqrInvScaleY, outputVertices);
+        recursiveQuadraticBezierVertices(mx, my, bx, by, bcx, bcy,
+                sqrInvScaleX, sqrInvScaleY, outputVertices);
+    }
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/PathRenderer.h b/libs/hwui/PathRenderer.h
new file mode 100644
index 0000000..e9f347b
--- /dev/null
+++ b/libs/hwui/PathRenderer.h
@@ -0,0 +1,104 @@
+/*
+ * 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 ANDROID_HWUI_PATH_RENDERER_H
+#define ANDROID_HWUI_PATH_RENDERER_H
+
+#include <utils/Vector.h>
+
+#include "Vertex.h"
+
+namespace android {
+namespace uirenderer {
+
+class Matrix4;
+typedef Matrix4 mat4;
+
+class VertexBuffer {
+public:
+    VertexBuffer():
+        mBuffer(0),
+        mSize(0),
+        mCleanupMethod(0)
+    {}
+
+    ~VertexBuffer() {
+        if (mCleanupMethod)
+            mCleanupMethod(mBuffer);
+    }
+
+    template <class TYPE>
+    TYPE* alloc(int size) {
+        mSize = size;
+        mBuffer = (void*)new TYPE[size];
+        mCleanupMethod = &(cleanup<TYPE>);
+
+        return (TYPE*)mBuffer;
+    }
+
+    void* getBuffer() { return mBuffer; }
+    unsigned int getSize() { return mSize; }
+
+private:
+    template <class TYPE>
+    static void cleanup(void* buffer) {
+        delete[] (TYPE*)buffer;
+    }
+
+    void* mBuffer;
+    unsigned int mSize;
+    void (*mCleanupMethod)(void*);
+};
+
+class PathRenderer {
+public:
+    static SkRect computePathBounds(const SkPath& path, const SkPaint* paint);
+
+    static void convexPathVertices(const SkPath& path, const SkPaint* paint,
+            const mat4 *transform, VertexBuffer& vertexBuffer);
+
+private:
+    static bool convexPathPerimeterVertices(const SkPath &path, bool forceClose,
+        float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex> &outputVertices);
+
+/*
+  endpoints a & b,
+  control c
+ */
+    static void recursiveQuadraticBezierVertices(
+            float ax, float ay,
+            float bx, float by,
+            float cx, float cy,
+            float sqrInvScaleX, float sqrInvScaleY,
+            Vector<Vertex> &outputVertices);
+
+/*
+  endpoints p1, p2
+  control c1, c2
+ */
+    static void recursiveCubicBezierVertices(
+            float p1x, float p1y,
+            float c1x, float c1y,
+            float p2x, float p2y,
+            float c2x, float c2y,
+            float sqrInvScaleX, float sqrInvScaleY,
+            Vector<Vertex> &outputVertices);
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_PATH_RENDERER_H
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index 984461c..f0b5553 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -81,6 +81,7 @@
 
     if (mInitialized) {
         transform = addUniform("transform");
+        projection = addUniform("projection");
     }
 }
 
@@ -152,18 +153,20 @@
 
 void Program::set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
         const mat4& transformMatrix, bool offset) {
-    mat4 t(projectionMatrix);
+    mat4 p(projectionMatrix);
     if (offset) {
         // offset screenspace xy by an amount that compensates for typical precision
         // issues in GPU hardware that tends to paint hor/vert lines in pixels shifted
         // up and to the left.
         // This offset value is based on an assumption that some hardware may use as
         // little as 12.4 precision, so we offset by slightly more than 1/16.
-        t.translate(.375, .375, 0);
+        p.translate(.375, .375, 0);
     }
-    t.multiply(transformMatrix);
+
+    mat4 t(transformMatrix);
     t.multiply(modelViewMatrix);
 
+    glUniformMatrix4fv(projection, 1, GL_FALSE, &p.data[0]);
     glUniformMatrix4fv(transform, 1, GL_FALSE, &t.data[0]);
 }
 
@@ -178,7 +181,7 @@
 void Program::use() {
     glUseProgram(mProgramId);
     if (texCoords >= 0 && !mHasSampler) {
-        glUniform1i(getUniform("sampler"), 0);
+        glUniform1i(getUniform("baseSampler"), 0);
         mHasSampler = true;
     }
     mUse = true;
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index eb9ee7b..7e3aacf 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -41,8 +41,8 @@
     #define PROGRAM_LOGD(...)
 #endif
 
-#define COLOR_COMPONENT_THRESHOLD (1.0f - (0.5f / PANEL_BIT_DEPTH))
-#define COLOR_COMPONENT_INV_THRESHOLD (0.5f / PANEL_BIT_DEPTH)
+#define COLOR_COMPONENT_THRESHOLD 1.0f
+#define COLOR_COMPONENT_INV_THRESHOLD 0.0f
 
 #define PROGRAM_KEY_TEXTURE 0x1
 #define PROGRAM_KEY_A8_TEXTURE 0x2
@@ -77,6 +77,12 @@
 #define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38
 #define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39
 
+#define PROGRAM_HAS_GAMMA_CORRECTION 40
+
+#define PROGRAM_IS_SIMPLE_GRADIENT 41
+
+#define PROGRAM_IS_VERTEX_SHAPE_SHIFT 42
+
 ///////////////////////////////////////////////////////////////////////////////
 // Types
 ///////////////////////////////////////////////////////////////////////////////
@@ -94,14 +100,14 @@
  */
 struct ProgramDescription {
     enum ColorModifier {
-        kColorNone,
+        kColorNone = 0,
         kColorMatrix,
         kColorLighting,
         kColorBlend
     };
 
     enum Gradient {
-        kGradientLinear,
+        kGradientLinear = 0,
         kGradientCircular,
         kGradientSweep
     };
@@ -124,9 +130,11 @@
     bool isBitmapNpot;
 
     bool isAA;
+    bool isVertexShape;
 
     bool hasGradient;
     Gradient gradientType;
+    bool isSimpleGradient;
 
     SkXfermode::Mode shadersMode;
 
@@ -146,6 +154,9 @@
     bool isPoint;
     float pointSize;
 
+    bool hasGammaCorrection;
+    float gamma;
+
     /**
      * Resets this description. All fields are reset back to the default
      * values they hold after building a new instance.
@@ -157,6 +168,7 @@
         hasTextureTransform = false;
 
         isAA = false;
+        isVertexShape = false;
 
         modulate = false;
 
@@ -165,6 +177,7 @@
 
         hasGradient = false;
         gradientType = kGradientLinear;
+        isSimpleGradient = false;
 
         shadersMode = SkXfermode::kClear_Mode;
 
@@ -180,6 +193,9 @@
 
         isPoint = false;
         pointSize = 0.0f;
+
+        hasGammaCorrection = false;
+        gamma = 2.2f;
     }
 
     /**
@@ -188,8 +204,7 @@
      * be provided with a modulation color.
      */
     bool setColor(const float r, const float g, const float b, const float a) {
-        modulate = a < COLOR_COMPONENT_THRESHOLD || r < COLOR_COMPONENT_THRESHOLD ||
-                g < COLOR_COMPONENT_THRESHOLD || b < COLOR_COMPONENT_THRESHOLD;
+        modulate = a < COLOR_COMPONENT_THRESHOLD;
         return modulate;
     }
 
@@ -246,6 +261,9 @@
         if (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT;
         if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
         if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
+        if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION;
+        if (isSimpleGradient) key |= programid(0x1) << PROGRAM_IS_SIMPLE_GRADIENT;
+        if (isVertexShape) key |= programid(0x1) << PROGRAM_IS_VERTEX_SHAPE_SHIFT;
         return key;
     }
 
@@ -261,7 +279,7 @@
     }
 
 private:
-    inline uint32_t getEnumForWrap(GLenum wrap) const {
+    static inline uint32_t getEnumForWrap(GLenum wrap) {
         switch (wrap) {
             case GL_CLAMP_TO_EDGE:
                 return 0;
@@ -356,6 +374,11 @@
      */
     int transform;
 
+    /**
+     * Name of the projection uniform.
+     */
+    int projection;
+
 protected:
     /**
      * Adds an attribute with the specified name.
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index a7f1277..f536ade 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -40,50 +40,61 @@
         "attribute vec4 position;\n";
 const char* gVS_Header_Attributes_TexCoords =
         "attribute vec2 texCoords;\n";
-const char* gVS_Header_Attributes_AAParameters =
+const char* gVS_Header_Attributes_AALineParameters =
         "attribute float vtxWidth;\n"
         "attribute float vtxLength;\n";
+const char* gVS_Header_Attributes_AAVertexShapeParameters =
+        "attribute float vtxAlpha;\n";
 const char* gVS_Header_Uniforms_TextureTransform =
         "uniform mat4 mainTextureTransform;\n";
 const char* gVS_Header_Uniforms =
+        "uniform mat4 projection;\n" \
         "uniform mat4 transform;\n";
 const char* gVS_Header_Uniforms_IsPoint =
         "uniform mediump float pointSize;\n";
 const char* gVS_Header_Uniforms_HasGradient[3] = {
         // Linear
-        "uniform mat4 screenSpace;\n",
+        "uniform mat4 screenSpace;\n"
+        "uniform float ditherSize;\n",
         // Circular
-        "uniform mat4 screenSpace;\n",
+        "uniform mat4 screenSpace;\n"
+        "uniform float ditherSize;\n",
         // Sweep
         "uniform mat4 screenSpace;\n"
+        "uniform float ditherSize;\n"
 };
 const char* gVS_Header_Uniforms_HasBitmap =
         "uniform mat4 textureTransform;\n"
         "uniform mediump vec2 textureDimension;\n";
 const char* gVS_Header_Varyings_HasTexture =
         "varying vec2 outTexCoords;\n";
-const char* gVS_Header_Varyings_IsAA =
+const char* gVS_Header_Varyings_IsAALine =
         "varying float widthProportion;\n"
         "varying float lengthProportion;\n";
-const char* gVS_Header_Varyings_HasBitmap[2] = {
-        // Default precision
-        "varying vec2 outBitmapTexCoords;\n",
-        // High precision
-        "varying highp vec2 outBitmapTexCoords;\n"
-};
-const char* gVS_Header_Varyings_PointHasBitmap[2] = {
-        // Default precision
-        "varying vec2 outPointBitmapTexCoords;\n",
-        // High precision
-        "varying highp vec2 outPointBitmapTexCoords;\n"
-};
-const char* gVS_Header_Varyings_HasGradient[3] = {
+const char* gVS_Header_Varyings_IsAAVertexShape =
+        "varying float alpha;\n";
+const char* gVS_Header_Varyings_HasBitmap =
+        "varying highp vec2 outBitmapTexCoords;\n";
+const char* gVS_Header_Varyings_PointHasBitmap =
+        "varying highp vec2 outPointBitmapTexCoords;\n";
+const char* gVS_Header_Varyings_HasGradient[6] = {
         // Linear
-        "varying vec2 linear;\n",
+        "varying highp vec2 linear;\n"
+        "varying vec2 ditherTexCoords;\n",
+        "varying float linear;\n"
+        "varying vec2 ditherTexCoords;\n",
+
         // Circular
-        "varying vec2 circular;\n",
+        "varying highp vec2 circular;\n"
+        "varying vec2 ditherTexCoords;\n",
+        "varying highp vec2 circular;\n"
+        "varying vec2 ditherTexCoords;\n",
+
         // Sweep
-        "varying vec2 sweep;\n"
+        "varying highp vec2 sweep;\n"
+        "varying vec2 ditherTexCoords;\n",
+        "varying highp vec2 sweep;\n"
+        "varying vec2 ditherTexCoords;\n",
 };
 const char* gVS_Main =
         "\nvoid main(void) {\n";
@@ -91,25 +102,38 @@
         "    outTexCoords = texCoords;\n";
 const char* gVS_Main_OutTransformedTexCoords =
         "    outTexCoords = (mainTextureTransform * vec4(texCoords, 0.0, 1.0)).xy;\n";
-const char* gVS_Main_OutGradient[3] = {
+const char* gVS_Main_OutGradient[6] = {
         // Linear
-        "    linear = vec2((screenSpace * position).x, 0.5);\n",
+        "    linear = vec2((screenSpace * position).x, 0.5);\n"
+        "    ditherTexCoords = (transform * position).xy * ditherSize;\n",
+        "    linear = (screenSpace * position).x;\n"
+        "    ditherTexCoords = (transform * position).xy * ditherSize;\n",
+
         // Circular
-        "    circular = (screenSpace * position).xy;\n",
+        "    circular = (screenSpace * position).xy;\n"
+        "    ditherTexCoords = (transform * position).xy * ditherSize;\n",
+        "    circular = (screenSpace * position).xy;\n"
+        "    ditherTexCoords = (transform * position).xy * ditherSize;\n",
+
         // Sweep
         "    sweep = (screenSpace * position).xy;\n"
+        "    ditherTexCoords = (transform * position).xy * ditherSize;\n",
+        "    sweep = (screenSpace * position).xy;\n"
+        "    ditherTexCoords = (transform * position).xy * ditherSize;\n",
 };
 const char* gVS_Main_OutBitmapTexCoords =
         "    outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n";
 const char* gVS_Main_OutPointBitmapTexCoords =
         "    outPointBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n";
 const char* gVS_Main_Position =
-        "    gl_Position = transform * position;\n";
+        "    gl_Position = projection * transform * position;\n";
 const char* gVS_Main_PointSize =
         "    gl_PointSize = pointSize;\n";
-const char* gVS_Main_AA =
+const char* gVS_Main_AALine =
         "    widthProportion = vtxWidth;\n"
         "    lengthProportion = vtxLength;\n";
+const char* gVS_Main_AAVertexShape =
+        "    alpha = vtxAlpha;\n";
 const char* gVS_Footer =
         "}\n\n";
 
@@ -125,25 +149,34 @@
         "precision mediump float;\n\n";
 const char* gFS_Uniforms_Color =
         "uniform vec4 color;\n";
-const char* gFS_Uniforms_AA =
+const char* gFS_Uniforms_AALine =
         "uniform float boundaryWidth;\n"
-        "uniform float inverseBoundaryWidth;\n"
-        "uniform float boundaryLength;\n"
-        "uniform float inverseBoundaryLength;\n";
+        "uniform float boundaryLength;\n";
 const char* gFS_Header_Uniforms_PointHasBitmap =
         "uniform vec2 textureDimension;\n"
         "uniform float pointSize;\n";
 const char* gFS_Uniforms_TextureSampler =
-        "uniform sampler2D sampler;\n";
+        "uniform sampler2D baseSampler;\n";
 const char* gFS_Uniforms_ExternalTextureSampler =
-        "uniform samplerExternalOES sampler;\n";
-const char* gFS_Uniforms_GradientSampler[3] = {
+        "uniform samplerExternalOES baseSampler;\n";
+#define FS_UNIFORMS_DITHER \
+        "uniform float ditherSizeSquared;\n" \
+        "uniform sampler2D ditherSampler;\n"
+#define FS_UNIFORMS_GRADIENT \
+        "uniform vec4 startColor;\n" \
+        "uniform vec4 endColor;\n"
+const char* gFS_Uniforms_GradientSampler[6] = {
         // Linear
-        "uniform sampler2D gradientSampler;\n",
+        FS_UNIFORMS_DITHER "uniform sampler2D gradientSampler;\n",
+        FS_UNIFORMS_DITHER FS_UNIFORMS_GRADIENT,
+
         // Circular
-        "uniform sampler2D gradientSampler;\n",
+        FS_UNIFORMS_DITHER "uniform sampler2D gradientSampler;\n",
+        FS_UNIFORMS_DITHER FS_UNIFORMS_GRADIENT,
+
         // Sweep
-        "uniform sampler2D gradientSampler;\n"
+        FS_UNIFORMS_DITHER "uniform sampler2D gradientSampler;\n",
+        FS_UNIFORMS_DITHER FS_UNIFORMS_GRADIENT
 };
 const char* gFS_Uniforms_BitmapSampler =
         "uniform sampler2D bitmapSampler;\n";
@@ -159,14 +192,22 @@
         // PorterDuff
         "uniform vec4 colorBlend;\n"
 };
+const char* gFS_Uniforms_Gamma =
+        "uniform float gamma;\n";
+
 const char* gFS_Main =
         "\nvoid main(void) {\n"
         "    lowp vec4 fragColor;\n";
 
 const char* gFS_Main_PointBitmapTexCoords =
-        "    vec2 outBitmapTexCoords = outPointBitmapTexCoords + "
+        "    highp vec2 outBitmapTexCoords = outPointBitmapTexCoords + "
         "((gl_PointCoord - vec2(0.5, 0.5)) * textureDimension * vec2(pointSize, pointSize));\n";
 
+#define FS_MAIN_DITHER \
+        "texture2D(ditherSampler, ditherTexCoords).a * ditherSizeSquared"
+const char* gFS_Main_AddDitherToGradient =
+        "    gradientColor += " FS_MAIN_DITHER ";\n";
+
 // Fast cases
 const char* gFS_Fast_SingleColor =
         "\nvoid main(void) {\n"
@@ -174,66 +215,87 @@
         "}\n\n";
 const char* gFS_Fast_SingleTexture =
         "\nvoid main(void) {\n"
-        "    gl_FragColor = texture2D(sampler, outTexCoords);\n"
+        "    gl_FragColor = texture2D(baseSampler, outTexCoords);\n"
         "}\n\n";
 const char* gFS_Fast_SingleModulateTexture =
         "\nvoid main(void) {\n"
-        "    gl_FragColor = color.a * texture2D(sampler, outTexCoords);\n"
+        "    gl_FragColor = color.a * texture2D(baseSampler, outTexCoords);\n"
         "}\n\n";
 const char* gFS_Fast_SingleA8Texture =
         "\nvoid main(void) {\n"
-        "    gl_FragColor = texture2D(sampler, outTexCoords);\n"
+        "    gl_FragColor = texture2D(baseSampler, outTexCoords);\n"
+        "}\n\n";
+const char* gFS_Fast_SingleA8Texture_ApplyGamma =
+        "\nvoid main(void) {\n"
+        "    gl_FragColor = vec4(0.0, 0.0, 0.0, pow(texture2D(baseSampler, outTexCoords).a, gamma));\n"
         "}\n\n";
 const char* gFS_Fast_SingleModulateA8Texture =
         "\nvoid main(void) {\n"
-        "    gl_FragColor = color * texture2D(sampler, outTexCoords).a;\n"
+        "    gl_FragColor = color * texture2D(baseSampler, outTexCoords).a;\n"
         "}\n\n";
-const char* gFS_Fast_SingleGradient =
+const char* gFS_Fast_SingleModulateA8Texture_ApplyGamma =
         "\nvoid main(void) {\n"
-        "    gl_FragColor = texture2D(gradientSampler, linear);\n"
+        "    gl_FragColor = color * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n"
         "}\n\n";
-const char* gFS_Fast_SingleModulateGradient =
+const char* gFS_Fast_SingleGradient[2] = {
         "\nvoid main(void) {\n"
-        "    gl_FragColor = color.a * texture2D(gradientSampler, linear);\n"
-        "}\n\n";
+        "    gl_FragColor = " FS_MAIN_DITHER " + texture2D(gradientSampler, linear);\n"
+        "}\n\n",
+        "\nvoid main(void) {\n"
+        "    gl_FragColor = " FS_MAIN_DITHER " + mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
+        "}\n\n"
+};
+const char* gFS_Fast_SingleModulateGradient[2] = {
+        "\nvoid main(void) {\n"
+        "    gl_FragColor = " FS_MAIN_DITHER " + color.a * texture2D(gradientSampler, linear);\n"
+        "}\n\n",
+        "\nvoid main(void) {\n"
+        "    gl_FragColor = " FS_MAIN_DITHER " + color.a * mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
+        "}\n\n"
+};
 
 // General case
 const char* gFS_Main_FetchColor =
         "    fragColor = color;\n";
 const char* gFS_Main_ModulateColor =
         "    fragColor *= color.a;\n";
-const char* gFS_Main_AccountForAA =
-        "    if (widthProportion < boundaryWidth) {\n"
-        "        fragColor *= (widthProportion * inverseBoundaryWidth);\n"
-        "    } else if (widthProportion > (1.0 - boundaryWidth)) {\n"
-        "        fragColor *= ((1.0 - widthProportion) * inverseBoundaryWidth);\n"
-        "    }\n"
-        "    if (lengthProportion < boundaryLength) {\n"
-        "        fragColor *= (lengthProportion * inverseBoundaryLength);\n"
-        "    } else if (lengthProportion > (1.0 - boundaryLength)) {\n"
-        "        fragColor *= ((1.0 - lengthProportion) * inverseBoundaryLength);\n"
-        "    }\n";
+const char* gFS_Main_AccountForAALine =
+        "    fragColor *= (1.0 - smoothstep(boundaryWidth, 0.5, abs(0.5 - widthProportion)))\n"
+        "               * (1.0 - smoothstep(boundaryLength, 0.5, abs(0.5 - lengthProportion)));\n";
+const char* gFS_Main_AccountForAAVertexShape =
+        "    fragColor *= alpha;\n";
+
 const char* gFS_Main_FetchTexture[2] = {
         // Don't modulate
-        "    fragColor = texture2D(sampler, outTexCoords);\n",
+        "    fragColor = texture2D(baseSampler, outTexCoords);\n",
         // Modulate
-        "    fragColor = color * texture2D(sampler, outTexCoords);\n"
+        "    fragColor = color * texture2D(baseSampler, outTexCoords);\n"
 };
-const char* gFS_Main_FetchA8Texture[2] = {
+const char* gFS_Main_FetchA8Texture[4] = {
         // Don't modulate
-        "    fragColor = texture2D(sampler, outTexCoords);\n",
+        "    fragColor = texture2D(baseSampler, outTexCoords);\n",
+        "    fragColor = texture2D(baseSampler, outTexCoords);\n",
         // Modulate
-        "    fragColor = color * texture2D(sampler, outTexCoords).a;\n"
+        "    fragColor = color * texture2D(baseSampler, outTexCoords).a;\n",
+        "    fragColor = color * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n"
 };
-const char* gFS_Main_FetchGradient[3] = {
+const char* gFS_Main_FetchGradient[6] = {
         // Linear
         "    vec4 gradientColor = texture2D(gradientSampler, linear);\n",
+
+        "    vec4 gradientColor = mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n",
+
         // Circular
-        "    float index = length(circular);\n"
-        "    vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n",
+        "    vec4 gradientColor = texture2D(gradientSampler, vec2(length(circular), 0.5));\n",
+
+        "    vec4 gradientColor = mix(startColor, endColor, clamp(length(circular), 0.0, 1.0));\n",
+
         // Sweep
-        "    float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
-        "    vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n"
+        "    highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
+        "    vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n",
+
+        "    highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
+        "    vec4 gradientColor = mix(startColor, endColor, clamp(index - floor(index), 0.0, 1.0));\n"
 };
 const char* gFS_Main_FetchBitmap =
         "    vec4 bitmapColor = texture2D(bitmapSampler, outBitmapTexCoords);\n";
@@ -243,29 +305,38 @@
         "    fragColor = blendShaders(gradientColor, bitmapColor)";
 const char* gFS_Main_BlendShadersGB =
         "    fragColor = blendShaders(bitmapColor, gradientColor)";
-const char* gFS_Main_BlendShaders_Modulate[3] = {
+const char* gFS_Main_BlendShaders_Modulate[6] = {
         // Don't modulate
         ";\n",
+        ";\n",
         // Modulate
-        " * fragColor.a;\n",
+        " * color.a;\n",
+        " * color.a;\n",
         // Modulate with alpha 8 texture
-        " * texture2D(sampler, outTexCoords).a;\n"
+        " * texture2D(baseSampler, outTexCoords).a;\n",
+        " * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n"
 };
-const char* gFS_Main_GradientShader_Modulate[3] = {
+const char* gFS_Main_GradientShader_Modulate[6] = {
         // Don't modulate
         "    fragColor = gradientColor;\n",
+        "    fragColor = gradientColor;\n",
         // Modulate
-        "    fragColor = gradientColor * fragColor.a;\n",
+        "    fragColor = gradientColor * color.a;\n",
+        "    fragColor = gradientColor * color.a;\n",
         // Modulate with alpha 8 texture
-        "    fragColor = gradientColor * texture2D(sampler, outTexCoords).a;\n"
+        "    fragColor = gradientColor * texture2D(baseSampler, outTexCoords).a;\n",
+        "    fragColor = gradientColor * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n"
     };
-const char* gFS_Main_BitmapShader_Modulate[3] = {
+const char* gFS_Main_BitmapShader_Modulate[6] = {
         // Don't modulate
         "    fragColor = bitmapColor;\n",
+        "    fragColor = bitmapColor;\n",
         // Modulate
-        "    fragColor = bitmapColor * fragColor.a;\n",
+        "    fragColor = bitmapColor * color.a;\n",
+        "    fragColor = bitmapColor * color.a;\n",
         // Modulate with alpha 8 texture
-        "    fragColor = bitmapColor * texture2D(sampler, outTexCoords).a;\n"
+        "    fragColor = bitmapColor * texture2D(baseSampler, outTexCoords).a;\n",
+        "    fragColor = bitmapColor * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n"
     };
 const char* gFS_Main_FragColor =
         "    gl_FragColor = fragColor;\n";
@@ -277,7 +348,6 @@
         // None
         "",
         // Matrix
-        // TODO: Fix premultiplied alpha computations for color matrix
         "    fragColor *= colorMatrix;\n"
         "    fragColor += colorMatrixVector;\n"
         "    fragColor.rgb *= fragColor.a;\n",
@@ -388,8 +458,11 @@
     String8 vertexShader = generateVertexShader(description);
     String8 fragmentShader = generateFragmentShader(description);
 
-    Program* program = new Program(description, vertexShader.string(), fragmentShader.string());
-    return program;
+    return new Program(description, vertexShader.string(), fragmentShader.string());
+}
+
+static inline size_t gradientIndex(const ProgramDescription& description) {
+    return description.gradientType * 2 + description.isSimpleGradient;
 }
 
 String8 ProgramCache::generateVertexShader(const ProgramDescription& description) {
@@ -399,7 +472,11 @@
         shader.append(gVS_Header_Attributes_TexCoords);
     }
     if (description.isAA) {
-        shader.append(gVS_Header_Attributes_AAParameters);
+        if (description.isVertexShape) {
+            shader.append(gVS_Header_Attributes_AAVertexShapeParameters);
+        } else {
+            shader.append(gVS_Header_Attributes_AALineParameters);
+        }
     }
     // Uniforms
     shader.append(gVS_Header_Uniforms);
@@ -420,16 +497,19 @@
         shader.append(gVS_Header_Varyings_HasTexture);
     }
     if (description.isAA) {
-        shader.append(gVS_Header_Varyings_IsAA);
+        if (description.isVertexShape) {
+            shader.append(gVS_Header_Varyings_IsAAVertexShape);
+        } else {
+            shader.append(gVS_Header_Varyings_IsAALine);
+        }
     }
     if (description.hasGradient) {
-        shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]);
+        shader.append(gVS_Header_Varyings_HasGradient[gradientIndex(description)]);
     }
     if (description.hasBitmap) {
-        int index = Caches::getInstance().extensions.needsHighpTexCoords() ? 1 : 0;
         shader.append(description.isPoint ?
-                gVS_Header_Varyings_PointHasBitmap[index] :
-                gVS_Header_Varyings_HasBitmap[index]);
+                gVS_Header_Varyings_PointHasBitmap :
+                gVS_Header_Varyings_HasBitmap);
     }
 
     // Begin the shader
@@ -440,10 +520,11 @@
             shader.append(gVS_Main_OutTexCoords);
         }
         if (description.isAA) {
-            shader.append(gVS_Main_AA);
-        }
-        if (description.hasGradient) {
-            shader.append(gVS_Main_OutGradient[description.gradientType]);
+            if (description.isVertexShape) {
+                shader.append(gVS_Main_AAVertexShape);
+            } else {
+                shader.append(gVS_Main_AALine);
+            }
         }
         if (description.hasBitmap) {
             shader.append(description.isPoint ?
@@ -455,6 +536,9 @@
         }
         // Output transformed position
         shader.append(gVS_Main_Position);
+        if (description.hasGradient) {
+            shader.append(gVS_Main_OutGradient[gradientIndex(description)]);
+        }
     }
     // End the shader
     shader.append(gVS_Footer);
@@ -464,6 +548,14 @@
     return shader;
 }
 
+static bool shaderOp(const ProgramDescription& description, String8& shader,
+        const int modulateOp, const char** snippets) {
+    int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp;
+    op = op * 2 + description.hasGammaCorrection;
+    shader.append(snippets[op]);
+    return description.hasAlpha8Texture;
+}
+
 String8 ProgramCache::generateFragmentShader(const ProgramDescription& description) {
     String8 shader;
 
@@ -482,16 +574,19 @@
         shader.append(gVS_Header_Varyings_HasTexture);
     }
     if (description.isAA) {
-        shader.append(gVS_Header_Varyings_IsAA);
+        if (description.isVertexShape) {
+            shader.append(gVS_Header_Varyings_IsAAVertexShape);
+        } else {
+            shader.append(gVS_Header_Varyings_IsAALine);
+        }
     }
     if (description.hasGradient) {
-        shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]);
+        shader.append(gVS_Header_Varyings_HasGradient[gradientIndex(description)]);
     }
     if (description.hasBitmap) {
-        int index = Caches::getInstance().extensions.needsHighpTexCoords() ? 1 : 0;
         shader.append(description.isPoint ?
-                gVS_Header_Varyings_PointHasBitmap[index] :
-                gVS_Header_Varyings_HasBitmap[index]);
+                gVS_Header_Varyings_PointHasBitmap :
+                gVS_Header_Varyings_HasBitmap);
     }
 
     // Uniforms
@@ -508,19 +603,23 @@
     } else if (description.hasExternalTexture) {
         shader.append(gFS_Uniforms_ExternalTextureSampler);
     }
-    if (description.isAA) {
-        shader.append(gFS_Uniforms_AA);
+    if (description.isAA && !description.isVertexShape) {
+        shader.append(gFS_Uniforms_AALine);
     }
     if (description.hasGradient) {
-        shader.append(gFS_Uniforms_GradientSampler[description.gradientType]);
+        shader.append(gFS_Uniforms_GradientSampler[gradientIndex(description)]);
     }
     if (description.hasBitmap && description.isPoint) {
         shader.append(gFS_Header_Uniforms_PointHasBitmap);
     }
+    if (description.hasGammaCorrection) {
+        shader.append(gFS_Uniforms_Gamma);
+    }
 
     // Optimization for common cases
     if (!description.isAA && !blendFramebuffer &&
-            description.colorOp == ProgramDescription::kColorNone && !description.isPoint) {
+            description.colorOp == ProgramDescription::kColorNone &&
+            !description.isPoint && !description.isVertexShape) {
         bool fast = false;
 
         const bool noShader = !description.hasGradient && !description.hasBitmap;
@@ -544,16 +643,24 @@
             fast = true;
         } else if (singleA8Texture) {
             if (!description.modulate) {
-                shader.append(gFS_Fast_SingleA8Texture);
+                if (description.hasGammaCorrection) {
+                    shader.append(gFS_Fast_SingleA8Texture_ApplyGamma);
+                } else {
+                    shader.append(gFS_Fast_SingleA8Texture);
+                }
             } else {
-                shader.append(gFS_Fast_SingleModulateA8Texture);
+                if (description.hasGammaCorrection) {
+                    shader.append(gFS_Fast_SingleModulateA8Texture_ApplyGamma);
+                } else {
+                    shader.append(gFS_Fast_SingleModulateA8Texture);
+                }
             }
             fast = true;
         } else if (singleGradient) {
             if (!description.modulate) {
-                shader.append(gFS_Fast_SingleGradient);
+                shader.append(gFS_Fast_SingleGradient[description.isSimpleGradient]);
             } else {
-                shader.append(gFS_Fast_SingleModulateGradient);
+                shader.append(gFS_Fast_SingleModulateGradient[description.isSimpleGradient]);
             }
             fast = true;
         }
@@ -594,21 +701,20 @@
         if (description.hasTexture || description.hasExternalTexture) {
             if (description.hasAlpha8Texture) {
                 if (!description.hasGradient && !description.hasBitmap) {
-                    shader.append(gFS_Main_FetchA8Texture[modulateOp]);
+                    shader.append(gFS_Main_FetchA8Texture[modulateOp * 2 +
+                                                          description.hasGammaCorrection]);
                 }
             } else {
                 shader.append(gFS_Main_FetchTexture[modulateOp]);
             }
         } else {
-            if ((!description.hasGradient && !description.hasBitmap) || description.modulate) {
+            if (!description.hasGradient && !description.hasBitmap) {
                 shader.append(gFS_Main_FetchColor);
             }
         }
-        if (description.isAA) {
-            shader.append(gFS_Main_AccountForAA);
-        }
         if (description.hasGradient) {
-            shader.append(gFS_Main_FetchGradient[description.gradientType]);
+            shader.append(gFS_Main_FetchGradient[gradientIndex(description)]);
+            shader.append(gFS_Main_AddDitherToGradient);
         }
         if (description.hasBitmap) {
             if (description.isPoint) {
@@ -623,30 +729,38 @@
         bool applyModulate = false;
         // Case when we have two shaders set
         if (description.hasGradient && description.hasBitmap) {
-            int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp;
             if (description.isBitmapFirst) {
                 shader.append(gFS_Main_BlendShadersBG);
             } else {
                 shader.append(gFS_Main_BlendShadersGB);
             }
-            shader.append(gFS_Main_BlendShaders_Modulate[op]);
-            applyModulate = true;
+            applyModulate = shaderOp(description, shader, modulateOp,
+                    gFS_Main_BlendShaders_Modulate);
         } else {
             if (description.hasGradient) {
-                int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp;
-                shader.append(gFS_Main_GradientShader_Modulate[op]);
-                applyModulate = true;
+                applyModulate = shaderOp(description, shader, modulateOp,
+                        gFS_Main_GradientShader_Modulate);
             } else if (description.hasBitmap) {
-                int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp;
-                shader.append(gFS_Main_BitmapShader_Modulate[op]);
-                applyModulate = true;
+                applyModulate = shaderOp(description, shader, modulateOp,
+                        gFS_Main_BitmapShader_Modulate);
             }
         }
+
         if (description.modulate && applyModulate) {
             shader.append(gFS_Main_ModulateColor);
         }
+
         // Apply the color op if needed
         shader.append(gFS_Main_ApplyColorOp[description.colorOp]);
+
+        if (description.isAA) {
+            if (description.isVertexShape) {
+                shader.append(gFS_Main_AccountForAAVertexShape);
+            } else {
+                shader.append(gFS_Main_AccountForAALine);
+            }
+        }
+
         // Output the fragment
         if (!blendFramebuffer) {
             shader.append(gFS_Main_FragColor);
@@ -676,13 +790,13 @@
 }
 
 void ProgramCache::generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT) {
-    shader.append("\nvec2 wrap(vec2 texCoords) {\n");
+    shader.append("\nhighp vec2 wrap(highp vec2 texCoords) {\n");
     if (wrapS == GL_MIRRORED_REPEAT) {
-        shader.append("    float xMod2 = mod(texCoords.x, 2.0);\n");
+        shader.append("    highp float xMod2 = mod(texCoords.x, 2.0);\n");
         shader.append("    if (xMod2 > 1.0) xMod2 = 2.0 - xMod2;\n");
     }
     if (wrapT == GL_MIRRORED_REPEAT) {
-        shader.append("    float yMod2 = mod(texCoords.y, 2.0);\n");
+        shader.append("    highp float yMod2 = mod(texCoords.y, 2.0);\n");
         shader.append("    if (yMod2 > 1.0) yMod2 = 2.0 - yMod2;\n");
     }
     shader.append("    return vec2(");
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 7854729..1e8765b 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -25,9 +25,6 @@
  * the OpenGLRenderer.
  */
 
-// If turned on, layers drawn inside FBOs are optimized with regions
-#define RENDER_LAYERS_AS_REGIONS 1
-
 // If turned on, text is interpreted as glyphs instead of UTF-16
 #define RENDER_TEXT_AS_GLYPHS 1
 
@@ -40,12 +37,13 @@
 // Defines the size in bits of the stencil buffer
 // Note: Only 1 bit is required for clipping but more bits are required
 // to properly implement the winding fill rule when rasterizing paths
-#define STENCIL_BUFFER_SIZE 0
+#define STENCIL_BUFFER_SIZE 8
 
 /**
- * Debug level for app developers.
+ * Debug level for app developers. The value is a numeric value defined
+ * by the DebugLevel enum below.
  */
-#define PROPERTY_DEBUG "hwui.debug_level"
+#define PROPERTY_DEBUG "debug.hwui.level"
 
 /**
  * Debug levels. Debug levels are used as flags.
@@ -57,6 +55,33 @@
     kDebugMoreCaches = kDebugMemory | kDebugCaches
 };
 
+/**
+ * Used to enable/disable layers update debugging. The accepted values are
+ * "true" and "false". The default value is "false".
+ */
+#define PROPERTY_DEBUG_LAYERS_UPDATES "debug.hwui.show_layers_updates"
+
+/**
+ * Used to enable/disable overdraw debugging. The accepted values are
+ * "true" and "false". The default value is "false".
+ */
+#define PROPERTY_DEBUG_OVERDRAW "debug.hwui.show_overdraw"
+
+/**
+ * Used to enable/disable scissor optimization. The accepted values are
+ * "true" and "false". The default value is "false".
+ *
+ * When scissor optimization is enabled, OpenGLRenderer will attempt to
+ * minimize the use of scissor by selectively enabling and disabling the
+ * GL scissor test.
+ * When the optimization is disabled, OpenGLRenderer will keep the GL
+ * scissor test enabled and change the scissor rect as needed.
+ * Some GPUs (for instance the SGX 540) perform better when changing
+ * the scissor rect often than when enabling/disabling the scissor test
+ * often.
+ */
+#define PROPERTY_DISABLE_SCISSOR_OPTIMIZATION "ro.hwui.disable_scissor_opt"
+
 // These properties are defined in mega-bytes
 #define PROPERTY_TEXTURE_CACHE_SIZE "ro.hwui.texture_cache_size"
 #define PROPERTY_LAYER_CACHE_SIZE "ro.hwui.layer_cache_size"
@@ -70,16 +95,35 @@
 #define PROPERTY_TEXTURE_CACHE_FLUSH_RATE "ro.hwui.texture_cache_flush_rate"
 
 // These properties are defined in pixels
-#define PROPERTY_TEXT_CACHE_WIDTH "ro.hwui.text_cache_width"
-#define PROPERTY_TEXT_CACHE_HEIGHT "ro.hwui.text_cache_height"
+#define PROPERTY_TEXT_SMALL_CACHE_WIDTH "ro.hwui.text_small_cache_width"
+#define PROPERTY_TEXT_SMALL_CACHE_HEIGHT "ro.hwui.text_small_cache_height"
+#define PROPERTY_TEXT_LARGE_CACHE_WIDTH "ro.hwui.text_large_cache_width"
+#define PROPERTY_TEXT_LARGE_CACHE_HEIGHT "ro.hwui.text_large_cache_height"
+
+// Indicates whether gamma correction should be applied in the shaders
+// or in lookup tables. Accepted values:
+//
+//     - "lookup3", correction based on lookup tables. Gamma correction
+//        is different for black and white text (see thresholds below)
+//
+//     - "lookup", correction based on a single lookup table
+//
+//     - "shader3", correction applied by a GLSL shader. Gamma correction
+//        is different for black and white text (see thresholds below)
+//
+//     - "shader", correction applied by a GLSL shader
+//
+// See PROPERTY_TEXT_GAMMA, PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD and
+// PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD for more control.
+#define PROPERTY_TEXT_GAMMA_METHOD "hwui.text_gamma_correction"
+#define DEFAULT_TEXT_GAMMA_METHOD "lookup"
 
 // Gamma (>= 1.0, <= 10.0)
-#define PROPERTY_TEXT_GAMMA "ro.text_gamma"
-#define PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD "ro.text_gamma.black_threshold"
-#define PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD "ro.text_gamma.white_threshold"
-
-// TODO: This should be set by a system property
-#define PANEL_BIT_DEPTH 20
+#define PROPERTY_TEXT_GAMMA "hwui.text_gamma"
+// Luminance threshold below which black gamma correction is applied. Range: [0..255]
+#define PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD "hwui.text_gamma.black_threshold"
+// Lumincance threshold above which white gamma correction is applied. Range: [0..255]
+#define PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD "hwui.text_gamma.white_threshold"
 
 // Converts a number of mega-bytes into bytes
 #define MB(s) s * 1024 * 1024
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index 2ca4f50..80f39ff90 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -125,11 +125,11 @@
         return intersect(r.left, r.top, r.right, r.bottom);
     }
 
-    bool contains(float l, float t, float r, float b) {
+    inline bool contains(float l, float t, float r, float b) {
         return l >= left && t >= top && r <= right && b <= bottom;
     }
 
-    bool contains(const Rect& r) {
+    inline bool contains(const Rect& r) {
         return contains(r.left, r.top, r.right, r.bottom);
     }
 
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index cf5f822..347bd78 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -38,7 +38,7 @@
 
 ResourceCache::ResourceCache() {
     Mutex::Autolock _l(mLock);
-    mCache = new KeyedVector<void *, ResourceReference *>();
+    mCache = new KeyedVector<void*, ResourceReference*>();
 }
 
 ResourceCache::~ResourceCache() {
@@ -46,14 +46,17 @@
     delete mCache;
 }
 
+void ResourceCache::lock() {
+    mLock.lock();
+}
+
+void ResourceCache::unlock() {
+    mLock.unlock();
+}
+
 void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
-    if (ref == NULL || mCache->size() == 0) {
-        ref = new ResourceReference(resourceType);
-        mCache->add(resource, ref);
-    }
-    ref->refCount++;
+    incrementRefcountLocked(resource, resourceType);
 }
 
 void ResourceCache::incrementRefcount(SkBitmap* bitmapResource) {
@@ -76,17 +79,47 @@
     incrementRefcount((void*) filterResource, kColorFilter);
 }
 
+void ResourceCache::incrementRefcount(Layer* layerResource) {
+    incrementRefcount((void*) layerResource, kLayer);
+}
+
+void ResourceCache::incrementRefcountLocked(void* resource, ResourceType resourceType) {
+    ssize_t index = mCache->indexOfKey(resource);
+    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
+    if (ref == NULL || mCache->size() == 0) {
+        ref = new ResourceReference(resourceType);
+        mCache->add(resource, ref);
+    }
+    ref->refCount++;
+}
+
+void ResourceCache::incrementRefcountLocked(SkBitmap* bitmapResource) {
+    SkSafeRef(bitmapResource->pixelRef());
+    SkSafeRef(bitmapResource->getColorTable());
+    incrementRefcountLocked((void*) bitmapResource, kBitmap);
+}
+
+void ResourceCache::incrementRefcountLocked(SkPath* pathResource) {
+    incrementRefcountLocked((void*) pathResource, kPath);
+}
+
+void ResourceCache::incrementRefcountLocked(SkiaShader* shaderResource) {
+    SkSafeRef(shaderResource->getSkShader());
+    incrementRefcountLocked((void*) shaderResource, kShader);
+}
+
+void ResourceCache::incrementRefcountLocked(SkiaColorFilter* filterResource) {
+    SkSafeRef(filterResource->getSkColorFilter());
+    incrementRefcountLocked((void*) filterResource, kColorFilter);
+}
+
+void ResourceCache::incrementRefcountLocked(Layer* layerResource) {
+    incrementRefcountLocked((void*) layerResource, kLayer);
+}
+
 void ResourceCache::decrementRefcount(void* resource) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
-    if (ref == NULL) {
-        // Should not get here - shouldn't get a call to decrement if we're not yet tracking it
-        return;
-    }
-    ref->refCount--;
-    if (ref->refCount == 0) {
-        deleteResourceReference(resource, ref);
-    }
+    decrementRefcountLocked(resource);
 }
 
 void ResourceCache::decrementRefcount(SkBitmap* bitmapResource) {
@@ -109,27 +142,55 @@
     decrementRefcount((void*) filterResource);
 }
 
-void ResourceCache::recycle(SkBitmap* resource) {
-    Mutex::Autolock _l(mLock);
-    if (mCache->indexOfKey(resource) < 0) {
-        // not tracking this resource; just recycle the pixel data
-        resource->setPixels(NULL, NULL);
-        return;
-    }
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+void ResourceCache::decrementRefcount(Layer* layerResource) {
+    decrementRefcount((void*) layerResource);
+}
+
+void ResourceCache::decrementRefcountLocked(void* resource) {
+    ssize_t index = mCache->indexOfKey(resource);
+    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
     if (ref == NULL) {
-        // Should not get here - shouldn't get a call to recycle if we're not yet tracking it
+        // Should not get here - shouldn't get a call to decrement if we're not yet tracking it
         return;
     }
-    ref->recycled = true;
+    ref->refCount--;
     if (ref->refCount == 0) {
-        deleteResourceReference(resource, ref);
+        deleteResourceReferenceLocked(resource, ref);
     }
 }
 
+void ResourceCache::decrementRefcountLocked(SkBitmap* bitmapResource) {
+    SkSafeUnref(bitmapResource->pixelRef());
+    SkSafeUnref(bitmapResource->getColorTable());
+    decrementRefcountLocked((void*) bitmapResource);
+}
+
+void ResourceCache::decrementRefcountLocked(SkPath* pathResource) {
+    decrementRefcountLocked((void*) pathResource);
+}
+
+void ResourceCache::decrementRefcountLocked(SkiaShader* shaderResource) {
+    SkSafeUnref(shaderResource->getSkShader());
+    decrementRefcountLocked((void*) shaderResource);
+}
+
+void ResourceCache::decrementRefcountLocked(SkiaColorFilter* filterResource) {
+    SkSafeUnref(filterResource->getSkColorFilter());
+    decrementRefcountLocked((void*) filterResource);
+}
+
+void ResourceCache::decrementRefcountLocked(Layer* layerResource) {
+    decrementRefcountLocked((void*) layerResource);
+}
+
 void ResourceCache::destructor(SkPath* resource) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    destructorLocked(resource);
+}
+
+void ResourceCache::destructorLocked(SkPath* resource) {
+    ssize_t index = mCache->indexOfKey(resource);
+    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
     if (ref == NULL) {
         // If we're not tracking this resource, just delete it
         if (Caches::hasInstance()) {
@@ -140,13 +201,18 @@
     }
     ref->destroyed = true;
     if (ref->refCount == 0) {
-        deleteResourceReference(resource, ref);
+        deleteResourceReferenceLocked(resource, ref);
     }
 }
 
 void ResourceCache::destructor(SkBitmap* resource) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    destructorLocked(resource);
+}
+
+void ResourceCache::destructorLocked(SkBitmap* resource) {
+    ssize_t index = mCache->indexOfKey(resource);
+    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
     if (ref == NULL) {
         // If we're not tracking this resource, just delete it
         if (Caches::hasInstance()) {
@@ -157,13 +223,18 @@
     }
     ref->destroyed = true;
     if (ref->refCount == 0) {
-        deleteResourceReference(resource, ref);
+        deleteResourceReferenceLocked(resource, ref);
     }
 }
 
 void ResourceCache::destructor(SkiaShader* resource) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    destructorLocked(resource);
+}
+
+void ResourceCache::destructorLocked(SkiaShader* resource) {
+    ssize_t index = mCache->indexOfKey(resource);
+    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
     if (ref == NULL) {
         // If we're not tracking this resource, just delete it
         delete resource;
@@ -171,13 +242,18 @@
     }
     ref->destroyed = true;
     if (ref->refCount == 0) {
-        deleteResourceReference(resource, ref);
+        deleteResourceReferenceLocked(resource, ref);
     }
 }
 
 void ResourceCache::destructor(SkiaColorFilter* resource) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    destructorLocked(resource);
+}
+
+void ResourceCache::destructorLocked(SkiaColorFilter* resource) {
+    ssize_t index = mCache->indexOfKey(resource);
+    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
     if (ref == NULL) {
         // If we're not tracking this resource, just delete it
         delete resource;
@@ -185,19 +261,53 @@
     }
     ref->destroyed = true;
     if (ref->refCount == 0) {
-        deleteResourceReference(resource, ref);
+        deleteResourceReferenceLocked(resource, ref);
     }
 }
 
 /**
+ * Return value indicates whether resource was actually recycled, which happens when RefCnt
+ * reaches 0.
+ */
+bool ResourceCache::recycle(SkBitmap* resource) {
+    Mutex::Autolock _l(mLock);
+    return recycleLocked(resource);
+}
+
+/**
+ * Return value indicates whether resource was actually recycled, which happens when RefCnt
+ * reaches 0.
+ */
+bool ResourceCache::recycleLocked(SkBitmap* resource) {
+    ssize_t index = mCache->indexOfKey(resource);
+    if (index < 0) {
+        // not tracking this resource; just recycle the pixel data
+        resource->setPixels(NULL, NULL);
+        return true;
+    }
+    ResourceReference* ref = mCache->valueAt(index);
+    if (ref == NULL) {
+        // Should not get here - shouldn't get a call to recycle if we're not yet tracking it
+        return true;
+    }
+    ref->recycled = true;
+    if (ref->refCount == 0) {
+        deleteResourceReferenceLocked(resource, ref);
+        return true;
+    }
+    // Still referring to resource, don't recycle yet
+    return false;
+}
+
+/**
  * This method should only be called while the mLock mutex is held (that mutex is grabbed
  * by the various destructor() and recycle() methods which call this method).
  */
-void ResourceCache::deleteResourceReference(void* resource, ResourceReference* ref) {
+void ResourceCache::deleteResourceReferenceLocked(void* resource, ResourceReference* ref) {
     if (ref->recycled && ref->resourceType == kBitmap) {
         ((SkBitmap*) resource)->setPixels(NULL, NULL);
     }
-    if (ref->destroyed) {
+    if (ref->destroyed || ref->resourceType == kLayer) {
         switch (ref->resourceType) {
             case kBitmap: {
                 SkBitmap* bitmap = (SkBitmap*) resource;
@@ -225,6 +335,11 @@
                 delete filter;
             }
             break;
+            case kLayer: {
+                Layer* layer = (Layer*) resource;
+                Caches::getInstance().deleteLayerDeferred(layer);
+            }
+            break;
         }
     }
     mCache->removeItem(resource);
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 8cf466b..ab493e5 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -23,6 +23,7 @@
 #include <SkiaColorFilter.h>
 #include <SkiaShader.h>
 #include <utils/KeyedVector.h>
+#include "Layer.h"
 
 namespace android {
 namespace uirenderer {
@@ -35,6 +36,7 @@
     kShader,
     kColorFilter,
     kPath,
+    kLayer
 };
 
 class ResourceReference {
@@ -52,28 +54,63 @@
 };
 
 class ANDROID_API ResourceCache {
-    KeyedVector<void *, ResourceReference *>* mCache;
 public:
     ResourceCache();
     ~ResourceCache();
+
+    /**
+     * When using these two methods, make sure to only invoke the *Locked()
+     * variants of increment/decrementRefcount(), recyle() and destructor()
+     */
+    void lock();
+    void unlock();
+
     void incrementRefcount(SkPath* resource);
     void incrementRefcount(SkBitmap* resource);
     void incrementRefcount(SkiaShader* resource);
     void incrementRefcount(SkiaColorFilter* resource);
-    void incrementRefcount(const void* resource, ResourceType resourceType);
-    void decrementRefcount(void* resource);
+    void incrementRefcount(Layer* resource);
+
+    void incrementRefcountLocked(SkPath* resource);
+    void incrementRefcountLocked(SkBitmap* resource);
+    void incrementRefcountLocked(SkiaShader* resource);
+    void incrementRefcountLocked(SkiaColorFilter* resource);
+    void incrementRefcountLocked(Layer* resource);
+
     void decrementRefcount(SkBitmap* resource);
     void decrementRefcount(SkPath* resource);
     void decrementRefcount(SkiaShader* resource);
     void decrementRefcount(SkiaColorFilter* resource);
-    void recycle(SkBitmap* resource);
+    void decrementRefcount(Layer* resource);
+
+    void decrementRefcountLocked(SkBitmap* resource);
+    void decrementRefcountLocked(SkPath* resource);
+    void decrementRefcountLocked(SkiaShader* resource);
+    void decrementRefcountLocked(SkiaColorFilter* resource);
+    void decrementRefcountLocked(Layer* resource);
+
     void destructor(SkPath* resource);
     void destructor(SkBitmap* resource);
     void destructor(SkiaShader* resource);
     void destructor(SkiaColorFilter* resource);
+
+    void destructorLocked(SkPath* resource);
+    void destructorLocked(SkBitmap* resource);
+    void destructorLocked(SkiaShader* resource);
+    void destructorLocked(SkiaColorFilter* resource);
+
+    bool recycle(SkBitmap* resource);
+    bool recycleLocked(SkBitmap* resource);
+
 private:
-    void deleteResourceReference(void* resource, ResourceReference* ref);
+    void deleteResourceReferenceLocked(void* resource, ResourceReference* ref);
+
     void incrementRefcount(void* resource, ResourceType resourceType);
+    void incrementRefcountLocked(void* resource, ResourceType resourceType);
+
+    void decrementRefcount(void* resource);
+    void decrementRefcountLocked(void* resource);
+
     void logCache();
 
     /**
@@ -82,6 +119,8 @@
      * or a reference queue finalization thread.
      */
     mutable Mutex mLock;
+
+    KeyedVector<void*, ResourceReference*>* mCache;
 };
 
 }; // namespace uirenderer
diff --git a/libs/hwui/SkiaColorFilter.cpp b/libs/hwui/SkiaColorFilter.cpp
index b86bbc5..df918be 100644
--- a/libs/hwui/SkiaColorFilter.cpp
+++ b/libs/hwui/SkiaColorFilter.cpp
@@ -34,13 +34,16 @@
 // Color matrix filter
 ///////////////////////////////////////////////////////////////////////////////
 
-SkiaColorMatrixFilter::SkiaColorMatrixFilter(SkColorFilter *skFilter, float* matrix, float* vector):
+SkiaColorMatrixFilter::SkiaColorMatrixFilter(SkColorFilter* skFilter, float* matrix, float* vector):
         SkiaColorFilter(skFilter, kColorMatrix, true), mMatrix(matrix), mVector(vector) {
     // Skia uses the range [0..255] for the addition vector, but we need
     // the [0..1] range to apply the vector in GLSL
     for (int i = 0; i < 4; i++) {
         mVector[i] /= 255.0f;
     }
+
+    // TODO: We should be smarter about this
+    mBlend = true;
 }
 
 SkiaColorMatrixFilter::~SkiaColorMatrixFilter() {
@@ -62,7 +65,7 @@
 // Lighting color filter
 ///////////////////////////////////////////////////////////////////////////////
 
-SkiaLightingFilter::SkiaLightingFilter(SkColorFilter *skFilter, int multiply, int add):
+SkiaLightingFilter::SkiaLightingFilter(SkColorFilter* skFilter, int multiply, int add):
         SkiaColorFilter(skFilter, kLighting, true) {
     mMulR = ((multiply >> 16) & 0xFF) / 255.0f;
     mMulG = ((multiply >>  8) & 0xFF) / 255.0f;
@@ -71,6 +74,9 @@
     mAddR = ((add >> 16) & 0xFF) / 255.0f;
     mAddG = ((add >>  8) & 0xFF) / 255.0f;
     mAddB = ((add      ) & 0xFF) / 255.0f;
+
+    // A lighting filter always ignores alpha
+    mBlend = false;
 }
 
 void SkiaLightingFilter::describe(ProgramDescription& description, const Extensions& extensions) {
@@ -86,13 +92,16 @@
 // Blend color filter
 ///////////////////////////////////////////////////////////////////////////////
 
-SkiaBlendFilter::SkiaBlendFilter(SkColorFilter *skFilter, int color, SkXfermode::Mode mode):
+SkiaBlendFilter::SkiaBlendFilter(SkColorFilter* skFilter, int color, SkXfermode::Mode mode):
         SkiaColorFilter(skFilter, kBlend, true), mMode(mode) {
     const int alpha = (color >> 24) & 0xFF;
     mA = alpha / 255.0f;
     mR = mA * ((color >> 16) & 0xFF) / 255.0f;
     mG = mA * ((color >>  8) & 0xFF) / 255.0f;
     mB = mA * ((color      ) & 0xFF) / 255.0f;
+
+    // TODO: We should do something smarter here
+    mBlend = true;
 }
 
 void SkiaBlendFilter::describe(ProgramDescription& description, const Extensions& extensions) {
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 66993a4..9013fd5 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -38,6 +38,22 @@
         GL_MIRRORED_REPEAT  // == SkShader::kMirror_TileMode
 };
 
+/**
+ * This function does not work for n == 0.
+ */
+static inline bool isPowerOfTwo(unsigned int n) {
+    return !(n & (n - 1));
+}
+
+static inline void bindUniformColor(int slot, uint32_t color) {
+    const float a = ((color >> 24) & 0xff) / 255.0f;
+    glUniform4f(slot,
+            a * ((color >> 16) & 0xff) / 255.0f,
+            a * ((color >>  8) & 0xff) / 255.0f,
+            a * ((color      ) & 0xff) / 255.0f,
+            a);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // Base shader
 ///////////////////////////////////////////////////////////////////////////////
@@ -139,10 +155,6 @@
 
     // Uniforms
     bindTexture(texture, mWrapS, mWrapT);
-    // Assume linear here; we should really check the transform in
-    // ::updateTransforms() but we don't have the texture object
-    // available at that point. The optimization is not worth the
-    // effort for now.
     texture->setFilter(GL_LINEAR);
 
     glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
@@ -151,14 +163,6 @@
     glUniform2f(program->getUniform("textureDimension"), 1.0f / width, 1.0f / height);
 }
 
-void SkiaBitmapShader::updateTransforms(Program* program, const mat4& modelView,
-        const Snapshot& snapshot) {
-    mat4 textureTransform;
-    computeScreenSpaceMatrix(textureTransform, modelView);
-    glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
-            GL_FALSE, &textureTransform.data[0]);
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // Linear gradient shader
 ///////////////////////////////////////////////////////////////////////////////
@@ -188,6 +192,8 @@
     mUnitMatrix.load(unitMatrix);
 
     updateLocalMatrix(matrix);
+
+    mIsSimple = count == 2 && tileMode == SkShader::kClamp_TileMode;
 }
 
 SkiaLinearGradientShader::~SkiaLinearGradientShader() {
@@ -206,6 +212,7 @@
     copy->mPositions = new float[mCount];
     memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
     copy->mCount = mCount;
+    copy->mIsSimple = mIsSimple;
     return copy;
 }
 
@@ -213,26 +220,27 @@
         const Extensions& extensions) {
     description.hasGradient = true;
     description.gradientType = ProgramDescription::kGradientLinear;
+    description.isSimpleGradient = mIsSimple;
 }
 
 void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelView,
         const Snapshot& snapshot, GLuint* textureUnit) {
-    GLuint textureSlot = (*textureUnit)++;
-    Caches::getInstance().activeTexture(textureSlot);
+    if (CC_UNLIKELY(!mIsSimple)) {
+        GLuint textureSlot = (*textureUnit)++;
+        Caches::getInstance().activeTexture(textureSlot);
 
-    Texture* texture = mGradientCache->get(mColors, mPositions, mCount, mTileX);
+        Texture* texture = mGradientCache->get(mColors, mPositions, mCount);
 
-    mat4 screenSpace;
-    computeScreenSpaceMatrix(screenSpace, modelView);
+        // Uniforms
+        bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
+        glUniform1i(program->getUniform("gradientSampler"), textureSlot);
+    } else {
+        bindUniformColor(program->getUniform("startColor"), mColors[0]);
+        bindUniformColor(program->getUniform("endColor"), mColors[1]);
+    }
 
-    // Uniforms
-    bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
-    glUniform1i(program->getUniform("gradientSampler"), textureSlot);
-    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
-}
+    Caches::getInstance().dither.setupProgram(program, textureUnit);
 
-void SkiaLinearGradientShader::updateTransforms(Program* program, const mat4& modelView,
-        const Snapshot& snapshot) {
     mat4 screenSpace;
     computeScreenSpaceMatrix(screenSpace, modelView);
     glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
@@ -269,6 +277,7 @@
     copy->mPositions = new float[mCount];
     memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
     copy->mCount = mCount;
+    copy->mIsSimple = mIsSimple;
     return copy;
 }
 
@@ -276,6 +285,7 @@
         const Extensions& extensions) {
     description.hasGradient = true;
     description.gradientType = ProgramDescription::kGradientCircular;
+    description.isSimpleGradient = mIsSimple;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -296,6 +306,8 @@
     mUnitMatrix.load(unitMatrix);
 
     updateLocalMatrix(matrix);
+
+    mIsSimple = count == 2;
 }
 
 SkiaSweepGradientShader::SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors,
@@ -303,6 +315,8 @@
         SkMatrix* matrix, bool blend):
         SkiaShader(type, key, tileMode, tileMode, matrix, blend),
         mColors(colors), mPositions(positions), mCount(count) {
+
+    mIsSimple = count == 2 && tileMode == SkShader::kClamp_TileMode;
 }
 
 SkiaSweepGradientShader::~SkiaSweepGradientShader() {
@@ -318,6 +332,7 @@
     copy->mPositions = new float[mCount];
     memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
     copy->mCount = mCount;
+    copy->mIsSimple = mIsSimple;
     return copy;
 }
 
@@ -325,26 +340,27 @@
         const Extensions& extensions) {
     description.hasGradient = true;
     description.gradientType = ProgramDescription::kGradientSweep;
+    description.isSimpleGradient = mIsSimple;
 }
 
 void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelView,
         const Snapshot& snapshot, GLuint* textureUnit) {
-    GLuint textureSlot = (*textureUnit)++;
-    Caches::getInstance().activeTexture(textureSlot);
+    if (CC_UNLIKELY(!mIsSimple)) {
+        GLuint textureSlot = (*textureUnit)++;
+        Caches::getInstance().activeTexture(textureSlot);
 
-    Texture* texture = mGradientCache->get(mColors, mPositions, mCount);
+        Texture* texture = mGradientCache->get(mColors, mPositions, mCount);
 
-    mat4 screenSpace;
-    computeScreenSpaceMatrix(screenSpace, modelView);
+        // Uniforms
+        bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
+        glUniform1i(program->getUniform("gradientSampler"), textureSlot);
+    } else {
+       bindUniformColor(program->getUniform("startColor"), mColors[0]);
+       bindUniformColor(program->getUniform("endColor"), mColors[1]);
+    }
 
-    // Uniforms
-    bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
-    glUniform1i(program->getUniform("gradientSampler"), textureSlot);
-    glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
-}
+    Caches::getInstance().dither.setupProgram(program, textureUnit);
 
-void SkiaSweepGradientShader::updateTransforms(Program* program, const mat4& modelView,
-        const Snapshot& snapshot) {
     mat4 screenSpace;
     computeScreenSpaceMatrix(screenSpace, modelView);
     glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 2de9a93..2687592 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -82,10 +82,6 @@
         mGradientCache = gradientCache;
     }
 
-    virtual void updateTransforms(Program* program, const mat4& modelView,
-            const Snapshot& snapshot) {
-    }
-
     uint32_t getGenerationId() {
         return mGenerationId;
     }
@@ -148,19 +144,11 @@
     void describe(ProgramDescription& description, const Extensions& extensions);
     void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
             GLuint* textureUnit);
-    void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);
 
 private:
     SkiaBitmapShader() {
     }
 
-    /**
-     * This method does not work for n == 0.
-     */
-    inline bool isPowerOfTwo(unsigned int n) {
-        return !(n & (n - 1));
-    }
-
     SkBitmap* mBitmap;
     Texture* mTexture;
     GLenum mWrapS;
@@ -179,12 +167,12 @@
     void describe(ProgramDescription& description, const Extensions& extensions);
     void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
             GLuint* textureUnit);
-    void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);
 
 private:
     SkiaLinearGradientShader() {
     }
 
+    bool mIsSimple;
     float* mBounds;
     uint32_t* mColors;
     float* mPositions;
@@ -203,7 +191,6 @@
     virtual void describe(ProgramDescription& description, const Extensions& extensions);
     void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
             GLuint* textureUnit);
-    void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);
 
 protected:
     SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors, float* positions,
@@ -211,6 +198,7 @@
     SkiaSweepGradientShader() {
     }
 
+    bool mIsSimple;
     uint32_t* mColors;
     float* mPositions;
     int mCount;
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 5d5961a..fbc8455 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -57,7 +57,7 @@
         clipRect = &mClipRectRoot;
 #if STENCIL_BUFFER_SIZE
         if (s->clipRegion) {
-            mClipRegionRoot.merge(*s->clipRegion);
+            mClipRegionRoot.op(*s->clipRegion, SkRegion::kUnion_Op);
             clipRegion = &mClipRegionRoot;
         }
 #endif
@@ -84,8 +84,7 @@
 #if STENCIL_BUFFER_SIZE
     if (!clipRegion) {
         clipRegion = &mClipRegionRoot;
-        android::Rect tmp(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
-        clipRegion->set(tmp);
+        clipRegion->setRect(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
     }
 #endif
 }
@@ -93,11 +92,11 @@
 void Snapshot::copyClipRectFromRegion() {
 #if STENCIL_BUFFER_SIZE
     if (!clipRegion->isEmpty()) {
-        android::Rect bounds(clipRegion->bounds());
-        clipRect->set(bounds.left, bounds.top, bounds.right, bounds.bottom);
+        const SkIRect& bounds = clipRegion->getBounds();
+        clipRect->set(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
 
         if (clipRegion->isRect()) {
-            clipRegion->clear();
+            clipRegion->setEmpty();
             clipRegion = NULL;
         }
     } else {
@@ -107,43 +106,11 @@
 #endif
 }
 
-bool Snapshot::clipRegionOr(float left, float top, float right, float bottom) {
+bool Snapshot::clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op) {
 #if STENCIL_BUFFER_SIZE
-    android::Rect tmp(left, top, right, bottom);
-    clipRegion->orSelf(tmp);
-    copyClipRectFromRegion();
-    return true;
-#else
-    return false;
-#endif
-}
-
-bool Snapshot::clipRegionXor(float left, float top, float right, float bottom) {
-#if STENCIL_BUFFER_SIZE
-    android::Rect tmp(left, top, right, bottom);
-    clipRegion->xorSelf(tmp);
-    copyClipRectFromRegion();
-    return true;
-#else
-    return false;
-#endif
-}
-
-bool Snapshot::clipRegionAnd(float left, float top, float right, float bottom) {
-#if STENCIL_BUFFER_SIZE
-    android::Rect tmp(left, top, right, bottom);
-    clipRegion->andSelf(tmp);
-    copyClipRectFromRegion();
-    return true;
-#else
-    return false;
-#endif
-}
-
-bool Snapshot::clipRegionNand(float left, float top, float right, float bottom) {
-#if STENCIL_BUFFER_SIZE
-    android::Rect tmp(left, top, right, bottom);
-    clipRegion->subtractSelf(tmp);
+    SkIRect tmp;
+    tmp.set(left, top, right, bottom);
+    clipRegion->op(tmp, op);
     copyClipRectFromRegion();
     return true;
 #else
@@ -161,14 +128,9 @@
     bool clipped = false;
 
     switch (op) {
-        case SkRegion::kDifference_Op: {
-            ensureClipRegion();
-            clipped = clipRegionNand(r.left, r.top, r.right, r.bottom);
-            break;
-        }
         case SkRegion::kIntersect_Op: {
             if (CC_UNLIKELY(clipRegion)) {
-                clipped = clipRegionOr(r.left, r.top, r.right, r.bottom);
+                clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op);
             } else {
                 clipped = clipRect->intersect(r);
                 if (!clipped) {
@@ -180,26 +142,22 @@
         }
         case SkRegion::kUnion_Op: {
             if (CC_UNLIKELY(clipRegion)) {
-                clipped = clipRegionAnd(r.left, r.top, r.right, r.bottom);
+                clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kUnion_Op);
             } else {
                 clipped = clipRect->unionWith(r);
             }
             break;
         }
-        case SkRegion::kXOR_Op: {
-            ensureClipRegion();
-            clipped = clipRegionXor(r.left, r.top, r.right, r.bottom);
-            break;
-        }
-        case SkRegion::kReverseDifference_Op: {
-            // TODO!!!!!!!
-            break;
-        }
         case SkRegion::kReplace_Op: {
             setClip(r.left, r.top, r.right, r.bottom);
             clipped = true;
             break;
         }
+        default: {
+            ensureClipRegion();
+            clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, op);
+            break;
+        }
     }
 
     if (clipped) {
@@ -213,13 +171,17 @@
     clipRect->set(left, top, right, bottom);
 #if STENCIL_BUFFER_SIZE
     if (clipRegion) {
-        clipRegion->clear();
+        clipRegion->setEmpty();
         clipRegion = NULL;
     }
 #endif
     flags |= Snapshot::kFlagClipSet;
 }
 
+bool Snapshot::hasPerspectiveTransform() const {
+    return transform->isPerspective();
+}
+
 const Rect& Snapshot::getLocalClip() {
     mat4 inverse;
     inverse.loadInverse(*transform);
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 30b03fc..9c612ff 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -121,6 +121,11 @@
     bool isIgnored() const;
 
     /**
+     * Indicates whether the current transform has perspective components.
+     */
+    bool hasPerspectiveTransform() const;
+
+    /**
      * Dirty flags.
      */
     int flags;
@@ -198,7 +203,7 @@
      *
      * This field is used only if STENCIL_BUFFER_SIZE is > 0.
      */
-    Region* clipRegion;
+    SkRegion* clipRegion;
 
     /**
      * The ancestor layer's dirty region.
@@ -223,17 +228,14 @@
     void ensureClipRegion();
     void copyClipRectFromRegion();
 
-    bool clipRegionOr(float left, float top, float right, float bottom);
-    bool clipRegionXor(float left, float top, float right, float bottom);
-    bool clipRegionAnd(float left, float top, float right, float bottom);
-    bool clipRegionNand(float left, float top, float right, float bottom);
+    bool clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op);
 
     mat4 mTransformRoot;
     Rect mClipRectRoot;
     Rect mLocalClip;
 
 #if STENCIL_BUFFER_SIZE
-    Region mClipRegionRoot;
+    SkRegion mClipRegionRoot;
 #endif
 
 }; // class Snapshot
diff --git a/libs/hwui/Stencil.cpp b/libs/hwui/Stencil.cpp
new file mode 100644
index 0000000..84df82b
--- /dev/null
+++ b/libs/hwui/Stencil.cpp
@@ -0,0 +1,92 @@
+/*
+ * 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 <GLES2/gl2.h>
+
+#include "Properties.h"
+#include "Stencil.h"
+
+namespace android {
+namespace uirenderer {
+
+Stencil::Stencil(): mState(kDisabled) {
+}
+
+uint32_t Stencil::getStencilSize() {
+    return STENCIL_BUFFER_SIZE;
+}
+
+void Stencil::clear() {
+    glClearStencil(0);
+    glClear(GL_STENCIL_BUFFER_BIT);
+}
+
+void Stencil::enableTest() {
+    if (mState != kTest) {
+        enable();
+        glStencilFunc(GL_EQUAL, 0x1, 0x1);
+        // We only want to test, let's keep everything
+        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+        mState = kTest;
+    }
+}
+
+void Stencil::enableWrite() {
+    if (mState != kWrite) {
+        enable();
+        glStencilFunc(GL_ALWAYS, 0x1, 0x1);
+        // The test always passes so the first two values are meaningless
+        glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+        mState = kWrite;
+    }
+}
+
+void Stencil::enableDebugTest(GLint value, bool greater) {
+    enable();
+    glStencilFunc(greater ? GL_LESS : GL_EQUAL, value, 0xffffffff);
+    // We only want to test, let's keep everything
+    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+    mState = kTest;
+}
+
+void Stencil::enableDebugWrite() {
+    if (mState != kWrite) {
+        enable();
+        glStencilFunc(GL_ALWAYS, 0x1, 0xffffffff);
+        // The test always passes so the first two values are meaningless
+        glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
+        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+        mState = kWrite;
+    }
+}
+
+void Stencil::enable() {
+    if (mState == kDisabled) {
+        glEnable(GL_STENCIL_TEST);
+    }
+}
+
+void Stencil::disable() {
+    if (mState != kDisabled) {
+        glDisable(GL_STENCIL_TEST);
+        mState = kDisabled;
+    }
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Stencil.h b/libs/hwui/Stencil.h
new file mode 100644
index 0000000..2f8a66a
--- /dev/null
+++ b/libs/hwui/Stencil.h
@@ -0,0 +1,99 @@
+/*
+ * 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 ANDROID_HWUI_STENCIL_H
+#define ANDROID_HWUI_STENCIL_H
+
+#ifndef LOG_TAG
+    #define LOG_TAG "OpenGLRenderer"
+#endif
+
+#include <cutils/compiler.h>
+
+namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Stencil buffer management
+///////////////////////////////////////////////////////////////////////////////
+
+class ANDROID_API Stencil {
+public:
+    Stencil();
+
+    /**
+     * Returns the desired size for the stencil buffer. If the returned value
+     * is 0, then no stencil buffer is required.
+     */
+    ANDROID_API static uint32_t getStencilSize();
+
+    /**
+     * Clears the stencil buffer.
+     */
+    void clear();
+
+    /**
+     * Enables stencil test. When the stencil test is enabled the stencil
+     * buffer is not written into.
+     */
+    void enableTest();
+
+    /**
+     * Enables stencil write. When stencil write is enabled, the stencil
+     * test always succeeds and the value 0x1 is written in the stencil
+     * buffer for each fragment.
+     */
+    void enableWrite();
+
+    /**
+     * The test passes only when equal to the specified value.
+     */
+    void enableDebugTest(GLint value, bool greater = false);
+
+    /**
+     * Used for debugging. The stencil test always passes and increments.
+     */
+    void enableDebugWrite();
+
+    /**
+     * Disables stencil test and write.
+     */
+    void disable();
+
+    /**
+     * Indicates whether either test or write is enabled.
+     */
+    bool isEnabled() {
+        return mState != kDisabled;
+    }
+
+private:
+    void enable();
+
+    enum StencilState {
+        kDisabled,
+        kTest,
+        kWrite
+    };
+
+    StencilState mState;
+
+}; // class Stencil
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_STENCIL_H
diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp
index bef1373..8426f58 100644
--- a/libs/hwui/TextDropShadowCache.cpp
+++ b/libs/hwui/TextDropShadowCache.cpp
@@ -102,13 +102,15 @@
 }
 
 ShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32_t len,
-        int numGlyphs, uint32_t radius) {
-    ShadowText entry(paint, radius, len, text);
+        int numGlyphs, uint32_t radius, const float* positions) {
+    ShadowText entry(paint, radius, len, text, positions);
     ShadowTexture* texture = mCache.get(entry);
 
     if (!texture) {
-        FontRenderer::DropShadow shadow = mRenderer->renderDropShadow(paint, text, 0,
-                len, numGlyphs, radius);
+        SkPaint paintCopy(*paint);
+        paintCopy.setTextAlign(SkPaint::kLeft_Align);
+        FontRenderer::DropShadow shadow = mRenderer->renderDropShadow(&paintCopy, text, 0,
+                len, numGlyphs, radius, positions);
 
         texture = new ShadowTexture;
         texture->left = shadow.penX;
diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h
index e2bdde1..bae0c49 100644
--- a/libs/hwui/TextDropShadowCache.h
+++ b/libs/hwui/TextDropShadowCache.h
@@ -35,8 +35,9 @@
     ShadowText(): radius(0), len(0), textSize(0.0f), typeface(NULL) {
     }
 
-    ShadowText(SkPaint* paint, uint32_t radius, uint32_t len, const char* srcText):
-            radius(radius), len(len) {
+    ShadowText(SkPaint* paint, uint32_t radius, uint32_t len, const char* srcText,
+            const float* positions):
+            radius(radius), len(len), positions(positions) {
         // TODO: Propagate this through the API, we should not cast here
         text = (const char16_t*) srcText;
 
@@ -66,11 +67,18 @@
     uint32_t italicStyle;
     uint32_t scaleX;
     const char16_t* text;
+    const float* positions;
     String16 str;
+    Vector<float> positionsCopy;
 
     void copyTextLocally() {
         str.setTo((const char16_t*) text, len >> 1);
         text = str.string();
+        if (positions != NULL) {
+            positionsCopy.clear();
+            positionsCopy.appendArray(positions, len);
+            positions = positionsCopy.array();
+        }
     }
 
     bool operator<(const ShadowText& rhs) const {
@@ -81,7 +89,12 @@
                         LTE_INT(flags) {
                             LTE_INT(italicStyle) {
                                 LTE_INT(scaleX) {
-                                    return memcmp(text, rhs.text, len) < 0;
+                                    int cmp = memcmp(text, rhs.text, len);
+                                    if (cmp < 0) return true;
+                                    if (cmp == 0 && rhs.positions != NULL) {
+                                        if (positions == NULL) return true;
+                                        return memcmp(positions, rhs.positions, len << 2) < 0;
+                                    }
                                 }
                             }
                         }
@@ -117,7 +130,7 @@
     void operator()(ShadowText& text, ShadowTexture*& texture);
 
     ShadowTexture* get(SkPaint* paint, const char* text, uint32_t len,
-            int numGlyphs, uint32_t radius);
+            int numGlyphs, uint32_t radius, const float* positions);
 
     /**
      * Clears the cache. This causes all textures to be deleted.
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index 1adf2c7..8d88bdc 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -36,8 +36,12 @@
         minFilter = GL_NEAREST;
         magFilter = GL_NEAREST;
 
+        mipMap = false;
+
         firstFilter = true;
         firstWrap = true;
+
+        id = 0;
     }
 
     void setWrap(GLenum wrap, bool bindTexture = false, bool force = false,
@@ -81,6 +85,8 @@
                 glBindTexture(renderTarget, id);
             }
 
+            if (mipMap && min == GL_LINEAR) min = GL_LINEAR_MIPMAP_LINEAR;
+
             glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min);
             glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag);
         }
@@ -114,7 +120,12 @@
      * Optional, size of the original bitmap.
      */
     uint32_t bitmapSize;
+    /**
+     * Indicates whether this texture will use trilinear filtering.
+     */
+    bool mipMap;
 
+private:
     /**
      * Last wrap modes set on this texture. Defaults to GL_CLAMP_TO_EDGE.
      */
@@ -127,7 +138,6 @@
     GLenum minFilter;
     GLenum magFilter;
 
-private:
     bool firstFilter;
     bool firstWrap;
 }; // struct Texture
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 9fb61e4..10d112a 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -22,6 +22,7 @@
 
 #include <utils/threads.h>
 
+#include "Caches.h"
 #include "TextureCache.h"
 #include "Properties.h"
 
@@ -216,8 +217,15 @@
         return;
     }
 
+    // We could also enable mipmapping if both bitmap dimensions are powers
+    // of 2 but we'd have to deal with size changes. Let's keep this simple
+    const bool canMipMap = Caches::getInstance().extensions.hasNPot();
+
+    // If the texture had mipmap enabled but not anymore,
+    // force a glTexImage2D to discard the mipmap levels
     const bool resize = !regenerate || bitmap->width() != int(texture->width) ||
-            bitmap->height() != int(texture->height);
+            bitmap->height() != int(texture->height) ||
+            (regenerate && canMipMap && texture->mipMap && !bitmap->hasHardwareMipMap());
 
     if (!regenerate) {
         glGenTextures(1, &texture->id);
@@ -228,25 +236,22 @@
     texture->height = bitmap->height();
 
     glBindTexture(GL_TEXTURE_2D, texture->id);
-    if (!regenerate) {
-        glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel());
-    }
 
     switch (bitmap->getConfig()) {
     case SkBitmap::kA8_Config:
-        if (!regenerate) {
-            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-        }
+        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
         uploadToTexture(resize, GL_ALPHA, bitmap->rowBytesAsPixels(), texture->height,
                 GL_UNSIGNED_BYTE, bitmap->getPixels());
         texture->blend = true;
         break;
     case SkBitmap::kRGB_565_Config:
+        glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel());
         uploadToTexture(resize, GL_RGB, bitmap->rowBytesAsPixels(), texture->height,
                 GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels());
         texture->blend = false;
         break;
     case SkBitmap::kARGB_8888_Config:
+        glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel());
         uploadToTexture(resize, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height,
                 GL_UNSIGNED_BYTE, bitmap->getPixels());
         // Do this after calling getPixels() to make sure Skia's deferred
@@ -255,6 +260,7 @@
         break;
     case SkBitmap::kARGB_4444_Config:
     case SkBitmap::kIndex8_Config:
+        glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel());
         uploadLoFiTexture(resize, bitmap, texture->width, texture->height);
         texture->blend = !bitmap->isOpaque();
         break;
@@ -263,6 +269,13 @@
         break;
     }
 
+    if (canMipMap) {
+        texture->mipMap = bitmap->hasHardwareMipMap();
+        if (texture->mipMap) {
+            glGenerateMipmap(GL_TEXTURE_2D);
+        }
+    }
+
     if (!regenerate) {
         texture->setFilter(GL_NEAREST);
         texture->setWrap(GL_CLAMP_TO_EDGE);
diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp
new file mode 100644
index 0000000..f653592
--- /dev/null
+++ b/libs/hwui/font/CacheTexture.cpp
@@ -0,0 +1,195 @@
+/*
+ * 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 <utils/Log.h>
+
+#include "Debug.h"
+#include "CacheTexture.h"
+
+namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// CacheBlock
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Insert new block into existing linked list of blocks. Blocks are sorted in increasing-width
+ * order, except for the final block (the remainder space at the right, since we fill from the
+ * left).
+ */
+CacheBlock* CacheBlock::insertBlock(CacheBlock* head, CacheBlock* newBlock) {
+#if DEBUG_FONT_RENDERER
+    ALOGD("insertBlock: this, x, y, w, h = %p, %d, %d, %d, %d",
+            newBlock, newBlock->mX, newBlock->mY,
+            newBlock->mWidth, newBlock->mHeight);
+#endif
+
+    CacheBlock* currBlock = head;
+    CacheBlock* prevBlock = NULL;
+
+    while (currBlock && currBlock->mY != TEXTURE_BORDER_SIZE) {
+        if (newBlock->mWidth < currBlock->mWidth) {
+            newBlock->mNext = currBlock;
+            newBlock->mPrev = prevBlock;
+            currBlock->mPrev = newBlock;
+
+            if (prevBlock) {
+                prevBlock->mNext = newBlock;
+                return head;
+            } else {
+                return newBlock;
+            }
+        }
+
+        prevBlock = currBlock;
+        currBlock = currBlock->mNext;
+    }
+
+    // new block larger than all others - insert at end (but before the remainder space, if there)
+    newBlock->mNext = currBlock;
+    newBlock->mPrev = prevBlock;
+
+    if (currBlock) {
+        currBlock->mPrev = newBlock;
+    }
+
+    if (prevBlock) {
+        prevBlock->mNext = newBlock;
+        return head;
+    } else {
+        return newBlock;
+    }
+}
+
+CacheBlock* CacheBlock::removeBlock(CacheBlock* head, CacheBlock* blockToRemove) {
+#if DEBUG_FONT_RENDERER
+    ALOGD("removeBlock: this, x, y, w, h = %p, %d, %d, %d, %d",
+            blockToRemove, blockToRemove->mX, blockToRemove->mY,
+            blockToRemove->mWidth, blockToRemove->mHeight);
+#endif
+
+    CacheBlock* newHead = head;
+    CacheBlock* nextBlock = blockToRemove->mNext;
+    CacheBlock* prevBlock = blockToRemove->mPrev;
+
+    if (prevBlock) {
+        prevBlock->mNext = nextBlock;
+    } else {
+        newHead = nextBlock;
+    }
+
+    if (nextBlock) {
+        nextBlock->mPrev = prevBlock;
+    }
+
+    delete blockToRemove;
+
+    return newHead;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// CacheTexture
+///////////////////////////////////////////////////////////////////////////////
+
+bool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY) {
+    if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > mHeight) {
+        return false;
+    }
+
+    uint16_t glyphW = glyph.fWidth + TEXTURE_BORDER_SIZE;
+    uint16_t glyphH = glyph.fHeight + TEXTURE_BORDER_SIZE;
+
+    // roundedUpW equals glyphW to the next multiple of CACHE_BLOCK_ROUNDING_SIZE.
+    // This columns for glyphs that are close but not necessarily exactly the same size. It trades
+    // off the loss of a few pixels for some glyphs against the ability to store more glyphs
+    // of varying sizes in one block.
+    uint16_t roundedUpW = (glyphW + CACHE_BLOCK_ROUNDING_SIZE - 1) & -CACHE_BLOCK_ROUNDING_SIZE;
+
+    CacheBlock* cacheBlock = mCacheBlocks;
+    while (cacheBlock) {
+        // Store glyph in this block iff: it fits the block's remaining space and:
+        // it's the remainder space (mY == 0) or there's only enough height for this one glyph
+        // or it's within ROUNDING_SIZE of the block width
+        if (roundedUpW <= cacheBlock->mWidth && glyphH <= cacheBlock->mHeight &&
+                (cacheBlock->mY == TEXTURE_BORDER_SIZE ||
+                        (cacheBlock->mWidth - roundedUpW < CACHE_BLOCK_ROUNDING_SIZE))) {
+            if (cacheBlock->mHeight - glyphH < glyphH) {
+                // Only enough space for this glyph - don't bother rounding up the width
+                roundedUpW = glyphW;
+            }
+
+            *retOriginX = cacheBlock->mX;
+            *retOriginY = cacheBlock->mY;
+
+            // If this is the remainder space, create a new cache block for this column. Otherwise,
+            // adjust the info about this column.
+            if (cacheBlock->mY == TEXTURE_BORDER_SIZE) {
+                uint16_t oldX = cacheBlock->mX;
+                // Adjust remainder space dimensions
+                cacheBlock->mWidth -= roundedUpW;
+                cacheBlock->mX += roundedUpW;
+
+                if (mHeight - glyphH >= glyphH) {
+                    // There's enough height left over to create a new CacheBlock
+                    CacheBlock* newBlock = new CacheBlock(oldX, glyphH + TEXTURE_BORDER_SIZE,
+                            roundedUpW, mHeight - glyphH - TEXTURE_BORDER_SIZE);
+#if DEBUG_FONT_RENDERER
+                    ALOGD("fitBitmap: Created new block: this, x, y, w, h = %p, %d, %d, %d, %d",
+                            newBlock, newBlock->mX, newBlock->mY,
+                            newBlock->mWidth, newBlock->mHeight);
+#endif
+                    mCacheBlocks = CacheBlock::insertBlock(mCacheBlocks, newBlock);
+                }
+            } else {
+                // Insert into current column and adjust column dimensions
+                cacheBlock->mY += glyphH;
+                cacheBlock->mHeight -= glyphH;
+#if DEBUG_FONT_RENDERER
+                ALOGD("fitBitmap: Added to existing block: this, x, y, w, h = %p, %d, %d, %d, %d",
+                        cacheBlock, cacheBlock->mX, cacheBlock->mY,
+                        cacheBlock->mWidth, cacheBlock->mHeight);
+#endif
+            }
+
+            if (cacheBlock->mHeight < fmin(glyphH, glyphW)) {
+                // If remaining space in this block is too small to be useful, remove it
+                mCacheBlocks = CacheBlock::removeBlock(mCacheBlocks, cacheBlock);
+            }
+
+            mDirty = true;
+            const Rect r(*retOriginX - TEXTURE_BORDER_SIZE, *retOriginY - TEXTURE_BORDER_SIZE,
+                    *retOriginX + glyphW, *retOriginY + glyphH);
+            mDirtyRect.unionWith(r);
+            mNumGlyphs++;
+
+#if DEBUG_FONT_RENDERER
+            ALOGD("fitBitmap: current block list:");
+            mCacheBlocks->output();
+#endif
+
+            return true;
+        }
+        cacheBlock = cacheBlock->mNext;
+    }
+#if DEBUG_FONT_RENDERER
+    ALOGD("fitBitmap: returning false for glyph of size %d, %d", glyphW, glyphH);
+#endif
+    return false;
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/font/CacheTexture.h b/libs/hwui/font/CacheTexture.h
new file mode 100644
index 0000000..fdd1623
--- /dev/null
+++ b/libs/hwui/font/CacheTexture.h
@@ -0,0 +1,211 @@
+/*
+ * 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 ANDROID_HWUI_CACHE_TEXTURE_H
+#define ANDROID_HWUI_CACHE_TEXTURE_H
+
+#include <GLES2/gl2.h>
+
+#include <SkScalerContext.h>
+
+#include <utils/Log.h>
+
+#include "FontUtil.h"
+#include "Rect.h"
+
+namespace android {
+namespace uirenderer {
+
+/**
+ * CacheBlock is a node in a linked list of current free space areas in a CacheTexture.
+ * Using CacheBlocks enables us to pack the cache from top to bottom as well as left to right.
+ * When we add a glyph to the cache, we see if it fits within one of the existing columns that
+ * have already been started (this is the case if the glyph fits vertically as well as
+ * horizontally, and if its width is sufficiently close to the column width to avoid
+ * sub-optimal packing of small glyphs into wide columns). If there is no column in which the
+ * glyph fits, we check the final node, which is the remaining space in the cache, creating
+ * a new column as appropriate.
+ *
+ * As columns fill up, we remove their CacheBlock from the list to avoid having to check
+ * small blocks in the future.
+ */
+struct CacheBlock {
+    uint16_t mX;
+    uint16_t mY;
+    uint16_t mWidth;
+    uint16_t mHeight;
+    CacheBlock* mNext;
+    CacheBlock* mPrev;
+
+    CacheBlock(uint16_t x, uint16_t y, uint16_t width, uint16_t height, bool empty = false):
+            mX(x), mY(y), mWidth(width), mHeight(height), mNext(NULL), mPrev(NULL) {
+    }
+
+    static CacheBlock* insertBlock(CacheBlock* head, CacheBlock* newBlock);
+
+    static CacheBlock* removeBlock(CacheBlock* head, CacheBlock* blockToRemove);
+
+    void output() {
+        CacheBlock* currBlock = this;
+        while (currBlock) {
+            ALOGD("Block: this, x, y, w, h = %p, %d, %d, %d, %d",
+                    currBlock, currBlock->mX, currBlock->mY, currBlock->mWidth, currBlock->mHeight);
+            currBlock = currBlock->mNext;
+        }
+    }
+};
+
+class CacheTexture {
+public:
+    CacheTexture(uint16_t width, uint16_t height) :
+            mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height),
+            mLinearFiltering(false), mDirty(false), mNumGlyphs(0) {
+        mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
+                mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE, true);
+    }
+
+    ~CacheTexture() {
+        releaseTexture();
+        reset();
+    }
+
+    void reset() {
+        // Delete existing cache blocks
+        while (mCacheBlocks != NULL) {
+            CacheBlock* tmpBlock = mCacheBlocks;
+            mCacheBlocks = mCacheBlocks->mNext;
+            delete tmpBlock;
+        }
+        mNumGlyphs = 0;
+    }
+
+    void init() {
+        // reset, then create a new remainder space to start again
+        reset();
+        mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
+                mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE, true);
+    }
+
+    void releaseTexture() {
+        if (mTexture) {
+            delete[] mTexture;
+            mTexture = NULL;
+        }
+        if (mTextureId) {
+            glDeleteTextures(1, &mTextureId);
+            mTextureId = 0;
+        }
+        mDirty = false;
+    }
+
+    /**
+     * This method assumes that the proper texture unit is active.
+     */
+    void allocateTexture() {
+        if (!mTexture) {
+            mTexture = new uint8_t[mWidth * mHeight];
+        }
+
+        if (!mTextureId) {
+            glGenTextures(1, &mTextureId);
+
+            glBindTexture(GL_TEXTURE_2D, mTextureId);
+            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+            // Initialize texture dimensions
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, mWidth, mHeight, 0,
+                    GL_ALPHA, GL_UNSIGNED_BYTE, 0);
+
+            const GLenum filtering = getLinearFiltering() ? GL_LINEAR : GL_NEAREST;
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
+
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        }
+    }
+
+    bool fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY);
+
+    inline uint16_t getWidth() const {
+        return mWidth;
+    }
+
+    inline uint16_t getHeight() const {
+        return mHeight;
+    }
+
+    inline const Rect* getDirtyRect() const {
+        return &mDirtyRect;
+    }
+
+    inline uint8_t* getTexture() const {
+        return mTexture;
+    }
+
+    GLuint getTextureId() {
+        allocateTexture();
+        return mTextureId;
+    }
+
+    inline bool isDirty() const {
+        return mDirty;
+    }
+
+    inline void setDirty(bool dirty) {
+        mDirty = dirty;
+        if (!dirty) {
+            mDirtyRect.setEmpty();
+        }
+    }
+
+    inline bool getLinearFiltering() const {
+        return mLinearFiltering;
+    }
+
+    /**
+     * This method assumes that the proper texture unit is active.
+     */
+    void setLinearFiltering(bool linearFiltering, bool bind = true) {
+        if (linearFiltering != mLinearFiltering) {
+            mLinearFiltering = linearFiltering;
+
+            const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
+            if (bind) glBindTexture(GL_TEXTURE_2D, getTextureId());
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
+        }
+    }
+
+    inline uint16_t getGlyphCount() const {
+        return mNumGlyphs;
+    }
+
+private:
+    uint8_t* mTexture;
+    GLuint mTextureId;
+    uint16_t mWidth;
+    uint16_t mHeight;
+    bool mLinearFiltering;
+    bool mDirty;
+    uint16_t mNumGlyphs;
+    CacheBlock* mCacheBlocks;
+    Rect mDirtyRect;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_CACHE_TEXTURE_H
diff --git a/libs/hwui/font/CachedGlyphInfo.h b/libs/hwui/font/CachedGlyphInfo.h
new file mode 100644
index 0000000..6680a00
--- /dev/null
+++ b/libs/hwui/font/CachedGlyphInfo.h
@@ -0,0 +1,58 @@
+/*
+ * 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 ANDROID_HWUI_CACHED_GLYPH_INFO_H
+#define ANDROID_HWUI_CACHED_GLYPH_INFO_H
+
+#include <SkFixed.h>
+
+#include "CacheTexture.h"
+
+namespace android {
+namespace uirenderer {
+
+struct CachedGlyphInfo {
+    // Has the cache been invalidated?
+    bool mIsValid;
+    // Location of the cached glyph in the bitmap
+    // in case we need to resize the texture or
+    // render to bitmap
+    uint32_t mStartX;
+    uint32_t mStartY;
+    uint32_t mBitmapWidth;
+    uint32_t mBitmapHeight;
+    // Also cache texture coords for the quad
+    float mBitmapMinU;
+    float mBitmapMinV;
+    float mBitmapMaxU;
+    float mBitmapMaxV;
+    // Minimize how much we call freetype
+    uint32_t mGlyphIndex;
+    uint32_t mAdvanceX;
+    uint32_t mAdvanceY;
+    // Values below contain a glyph's origin in the bitmap
+    int32_t mBitmapLeft;
+    int32_t mBitmapTop;
+    // Auto-kerning
+    SkFixed mLsbDelta;
+    SkFixed mRsbDelta;
+    CacheTexture* mCacheTexture;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_CACHED_GLYPH_INFO_H
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
new file mode 100644
index 0000000..7bfa63d
--- /dev/null
+++ b/libs/hwui/font/Font.cpp
@@ -0,0 +1,443 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+
+#include <cutils/compiler.h>
+
+#include <SkUtils.h>
+
+#include "Debug.h"
+#include "FontUtil.h"
+#include "Font.h"
+#include "FontRenderer.h"
+#include "Properties.h"
+
+namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Font
+///////////////////////////////////////////////////////////////////////////////
+
+Font::Font(FontRenderer* state, uint32_t fontId, float fontSize,
+        int flags, uint32_t italicStyle, uint32_t scaleX,
+        SkPaint::Style style, uint32_t strokeWidth) :
+        mState(state), mFontId(fontId), mFontSize(fontSize),
+        mFlags(flags), mItalicStyle(italicStyle), mScaleX(scaleX),
+        mStyle(style), mStrokeWidth(mStrokeWidth) {
+}
+
+
+Font::~Font() {
+    mState->removeFont(this);
+
+    for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) {
+        delete mCachedGlyphs.valueAt(i);
+    }
+}
+
+void Font::invalidateTextureCache(CacheTexture* cacheTexture) {
+    for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) {
+        CachedGlyphInfo* cachedGlyph = mCachedGlyphs.valueAt(i);
+        if (!cacheTexture || cachedGlyph->mCacheTexture == cacheTexture) {
+            cachedGlyph->mIsValid = false;
+        }
+    }
+}
+
+void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
+        uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) {
+    int nPenX = x + glyph->mBitmapLeft;
+    int nPenY = y + glyph->mBitmapTop;
+
+    int width = (int) glyph->mBitmapWidth;
+    int height = (int) glyph->mBitmapHeight;
+
+    if (bounds->bottom > nPenY) {
+        bounds->bottom = nPenY;
+    }
+    if (bounds->left > nPenX) {
+        bounds->left = nPenX;
+    }
+    if (bounds->right < nPenX + width) {
+        bounds->right = nPenX + width;
+    }
+    if (bounds->top < nPenY + height) {
+        bounds->top = nPenY + height;
+    }
+}
+
+void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
+        uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) {
+    int nPenX = x + glyph->mBitmapLeft;
+    int nPenY = y + glyph->mBitmapTop + glyph->mBitmapHeight;
+
+    float u1 = glyph->mBitmapMinU;
+    float u2 = glyph->mBitmapMaxU;
+    float v1 = glyph->mBitmapMinV;
+    float v2 = glyph->mBitmapMaxV;
+
+    int width = (int) glyph->mBitmapWidth;
+    int height = (int) glyph->mBitmapHeight;
+
+    mState->appendMeshQuad(nPenX, nPenY, u1, v2,
+            nPenX + width, nPenY, u2, v2,
+            nPenX + width, nPenY - height, u2, v1,
+            nPenX, nPenY - height, u1, v1, glyph->mCacheTexture);
+}
+
+void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
+        uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) {
+    int nPenX = x + glyph->mBitmapLeft;
+    int nPenY = y + glyph->mBitmapTop;
+
+    uint32_t endX = glyph->mStartX + glyph->mBitmapWidth;
+    uint32_t endY = glyph->mStartY + glyph->mBitmapHeight;
+
+    CacheTexture* cacheTexture = glyph->mCacheTexture;
+    uint32_t cacheWidth = cacheTexture->getWidth();
+    const uint8_t* cacheBuffer = cacheTexture->getTexture();
+
+    uint32_t cacheX = 0, cacheY = 0;
+    int32_t bX = 0, bY = 0;
+    for (cacheX = glyph->mStartX, bX = nPenX; cacheX < endX; cacheX++, bX++) {
+        for (cacheY = glyph->mStartY, bY = nPenY; cacheY < endY; cacheY++, bY++) {
+#if DEBUG_FONT_RENDERER
+            if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) {
+                ALOGE("Skipping invalid index");
+                continue;
+            }
+#endif
+            uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX];
+            bitmap[bY * bitmapW + bX] = tempCol;
+        }
+    }
+}
+
+void Font::drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset,
+        SkPathMeasure& measure, SkPoint* position, SkVector* tangent) {
+    const float halfWidth = glyph->mBitmapWidth * 0.5f;
+    const float height = glyph->mBitmapHeight;
+
+    vOffset += glyph->mBitmapTop + height;
+
+    SkPoint destination[4];
+    measure.getPosTan(x + hOffset +  glyph->mBitmapLeft + halfWidth, position, tangent);
+
+    // Move along the tangent and offset by the normal
+    destination[0].set(-tangent->fX * halfWidth - tangent->fY * vOffset,
+            -tangent->fY * halfWidth + tangent->fX * vOffset);
+    destination[1].set(tangent->fX * halfWidth - tangent->fY * vOffset,
+            tangent->fY * halfWidth + tangent->fX * vOffset);
+    destination[2].set(destination[1].fX + tangent->fY * height,
+            destination[1].fY - tangent->fX * height);
+    destination[3].set(destination[0].fX + tangent->fY * height,
+            destination[0].fY - tangent->fX * height);
+
+    const float u1 = glyph->mBitmapMinU;
+    const float u2 = glyph->mBitmapMaxU;
+    const float v1 = glyph->mBitmapMinV;
+    const float v2 = glyph->mBitmapMaxV;
+
+    mState->appendRotatedMeshQuad(
+            position->fX + destination[0].fX,
+            position->fY + destination[0].fY, u1, v2,
+            position->fX + destination[1].fX,
+            position->fY + destination[1].fY, u2, v2,
+            position->fX + destination[2].fX,
+            position->fY + destination[2].fY, u2, v1,
+            position->fX + destination[3].fX,
+            position->fY + destination[3].fY, u1, v1,
+            glyph->mCacheTexture);
+}
+
+CachedGlyphInfo* Font::getCachedGlyph(SkPaint* paint, glyph_t textUnit, bool precaching) {
+    CachedGlyphInfo* cachedGlyph = NULL;
+    ssize_t index = mCachedGlyphs.indexOfKey(textUnit);
+    if (index >= 0) {
+        cachedGlyph = mCachedGlyphs.valueAt(index);
+    } else {
+        cachedGlyph = cacheGlyph(paint, textUnit, precaching);
+    }
+
+    // Is the glyph still in texture cache?
+    if (!cachedGlyph->mIsValid) {
+        const SkGlyph& skiaGlyph = GET_METRICS(paint, textUnit);
+        updateGlyphCache(paint, skiaGlyph, cachedGlyph, precaching);
+    }
+
+    return cachedGlyph;
+}
+
+void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+        int numGlyphs, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
+    if (bitmap != NULL && bitmapW > 0 && bitmapH > 0) {
+        render(paint, text, start, len, numGlyphs, x, y, BITMAP, bitmap,
+                bitmapW, bitmapH, NULL, NULL);
+    } else {
+        render(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL,
+                0, 0, NULL, NULL);
+    }
+}
+
+void Font::render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
+            int numGlyphs, int x, int y, const float* positions) {
+    render(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL,
+            0, 0, NULL, positions);
+}
+
+void Font::render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
+        int numGlyphs, SkPath* path, float hOffset, float vOffset) {
+    if (numGlyphs == 0 || text == NULL || len == 0) {
+        return;
+    }
+
+    text += start;
+
+    int glyphsCount = 0;
+    SkFixed prevRsbDelta = 0;
+
+    float penX = 0.0f;
+
+    SkPoint position;
+    SkVector tangent;
+
+    SkPathMeasure measure(*path, false);
+    float pathLength = SkScalarToFloat(measure.getLength());
+
+    if (paint->getTextAlign() != SkPaint::kLeft_Align) {
+        float textWidth = SkScalarToFloat(paint->measureText(text, len));
+        float pathOffset = pathLength;
+        if (paint->getTextAlign() == SkPaint::kCenter_Align) {
+            textWidth *= 0.5f;
+            pathOffset *= 0.5f;
+        }
+        penX += pathOffset - textWidth;
+    }
+
+    while (glyphsCount < numGlyphs && penX < pathLength) {
+        glyph_t glyph = GET_GLYPH(text);
+
+        if (IS_END_OF_STRING(glyph)) {
+            break;
+        }
+
+        CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph);
+        penX += SkFixedToFloat(AUTO_KERN(prevRsbDelta, cachedGlyph->mLsbDelta));
+        prevRsbDelta = cachedGlyph->mRsbDelta;
+
+        if (cachedGlyph->mIsValid) {
+            drawCachedGlyph(cachedGlyph, penX, hOffset, vOffset, measure, &position, &tangent);
+        }
+
+        penX += SkFixedToFloat(cachedGlyph->mAdvanceX);
+
+        glyphsCount++;
+    }
+}
+
+void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+        int numGlyphs, Rect *bounds, const float* positions) {
+    if (bounds == NULL) {
+        ALOGE("No return rectangle provided to measure text");
+        return;
+    }
+    bounds->set(1e6, -1e6, -1e6, 1e6);
+    render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds, positions);
+}
+
+void Font::precache(SkPaint* paint, const char* text, int numGlyphs) {
+
+    if (numGlyphs == 0 || text == NULL) {
+        return;
+    }
+    int glyphsCount = 0;
+
+    while (glyphsCount < numGlyphs) {
+        glyph_t glyph = GET_GLYPH(text);
+
+        // Reached the end of the string
+        if (IS_END_OF_STRING(glyph)) {
+            break;
+        }
+
+        CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph, true);
+
+        glyphsCount++;
+    }
+}
+
+void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+        int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
+        uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* positions) {
+    if (numGlyphs == 0 || text == NULL || len == 0) {
+        return;
+    }
+
+    static RenderGlyph gRenderGlyph[] = {
+            &android::uirenderer::Font::drawCachedGlyph,
+            &android::uirenderer::Font::drawCachedGlyphBitmap,
+            &android::uirenderer::Font::measureCachedGlyph
+    };
+    RenderGlyph render = gRenderGlyph[mode];
+
+    text += start;
+    int glyphsCount = 0;
+
+    if (CC_LIKELY(positions == NULL)) {
+        SkFixed prevRsbDelta = 0;
+
+        float penX = x + 0.5f;
+        int penY = y;
+
+        while (glyphsCount < numGlyphs) {
+            glyph_t glyph = GET_GLYPH(text);
+
+            // Reached the end of the string
+            if (IS_END_OF_STRING(glyph)) {
+                break;
+            }
+
+            CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph);
+            penX += SkFixedToFloat(AUTO_KERN(prevRsbDelta, cachedGlyph->mLsbDelta));
+            prevRsbDelta = cachedGlyph->mRsbDelta;
+
+            // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage
+            if (cachedGlyph->mIsValid) {
+                (*this.*render)(cachedGlyph, (int) floorf(penX), penY,
+                        bitmap, bitmapW, bitmapH, bounds, positions);
+            }
+
+            penX += SkFixedToFloat(cachedGlyph->mAdvanceX);
+
+            glyphsCount++;
+        }
+    } else {
+        const SkPaint::Align align = paint->getTextAlign();
+
+        // This is for renderPosText()
+        while (glyphsCount < numGlyphs) {
+            glyph_t glyph = GET_GLYPH(text);
+
+            // Reached the end of the string
+            if (IS_END_OF_STRING(glyph)) {
+                break;
+            }
+
+            CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph);
+
+            // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage
+            if (cachedGlyph->mIsValid) {
+                int penX = x + positions[(glyphsCount << 1)];
+                int penY = y + positions[(glyphsCount << 1) + 1];
+
+                switch (align) {
+                    case SkPaint::kRight_Align:
+                        penX -= SkFixedToFloat(cachedGlyph->mAdvanceX);
+                        penY -= SkFixedToFloat(cachedGlyph->mAdvanceY);
+                        break;
+                    case SkPaint::kCenter_Align:
+                        penX -= SkFixedToFloat(cachedGlyph->mAdvanceX >> 1);
+                        penY -= SkFixedToFloat(cachedGlyph->mAdvanceY >> 1);
+                    default:
+                        break;
+                }
+
+                (*this.*render)(cachedGlyph, penX, penY,
+                        bitmap, bitmapW, bitmapH, bounds, positions);
+            }
+
+            glyphsCount++;
+        }
+    }
+}
+
+void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph,
+        bool precaching) {
+    glyph->mAdvanceX = skiaGlyph.fAdvanceX;
+    glyph->mAdvanceY = skiaGlyph.fAdvanceY;
+    glyph->mBitmapLeft = skiaGlyph.fLeft;
+    glyph->mBitmapTop = skiaGlyph.fTop;
+    glyph->mLsbDelta = skiaGlyph.fLsbDelta;
+    glyph->mRsbDelta = skiaGlyph.fRsbDelta;
+
+    uint32_t startX = 0;
+    uint32_t startY = 0;
+
+    // Get the bitmap for the glyph
+    paint->findImage(skiaGlyph);
+    mState->cacheBitmap(skiaGlyph, glyph, &startX, &startY, precaching);
+
+    if (!glyph->mIsValid) {
+        return;
+    }
+
+    uint32_t endX = startX + skiaGlyph.fWidth;
+    uint32_t endY = startY + skiaGlyph.fHeight;
+
+    glyph->mStartX = startX;
+    glyph->mStartY = startY;
+    glyph->mBitmapWidth = skiaGlyph.fWidth;
+    glyph->mBitmapHeight = skiaGlyph.fHeight;
+
+    uint32_t cacheWidth = glyph->mCacheTexture->getWidth();
+    uint32_t cacheHeight = glyph->mCacheTexture->getHeight();
+
+    glyph->mBitmapMinU = startX / (float) cacheWidth;
+    glyph->mBitmapMinV = startY / (float) cacheHeight;
+    glyph->mBitmapMaxU = endX / (float) cacheWidth;
+    glyph->mBitmapMaxV = endY / (float) cacheHeight;
+
+    mState->setTextureDirty();
+}
+
+CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, glyph_t glyph, bool precaching) {
+    CachedGlyphInfo* newGlyph = new CachedGlyphInfo();
+    mCachedGlyphs.add(glyph, newGlyph);
+
+    const SkGlyph& skiaGlyph = GET_METRICS(paint, glyph);
+    newGlyph->mGlyphIndex = skiaGlyph.fID;
+    newGlyph->mIsValid = false;
+
+    updateGlyphCache(paint, skiaGlyph, newGlyph, precaching);
+
+    return newGlyph;
+}
+
+Font* Font::create(FontRenderer* state, uint32_t fontId, float fontSize,
+        int flags, uint32_t italicStyle, uint32_t scaleX,
+        SkPaint::Style style, uint32_t strokeWidth) {
+    Vector<Font*> &activeFonts = state->mActiveFonts;
+
+    for (uint32_t i = 0; i < activeFonts.size(); i++) {
+        Font* font = activeFonts[i];
+        if (font->mFontId == fontId && font->mFontSize == fontSize &&
+                font->mFlags == flags && font->mItalicStyle == italicStyle &&
+                font->mScaleX == scaleX && font->mStyle == style &&
+                (style == SkPaint::kFill_Style || font->mStrokeWidth == strokeWidth)) {
+            return font;
+        }
+    }
+
+    Font* newFont = new Font(state, fontId, fontSize, flags, italicStyle,
+            scaleX, style, strokeWidth);
+    activeFonts.push(newFont);
+    return newFont;
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/font/Font.h b/libs/hwui/font/Font.h
new file mode 100644
index 0000000..7cab31e
--- /dev/null
+++ b/libs/hwui/font/Font.h
@@ -0,0 +1,130 @@
+/*
+ * 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 ANDROID_HWUI_FONT_H
+#define ANDROID_HWUI_FONT_H
+
+#include <utils/KeyedVector.h>
+
+#include <SkScalerContext.h>
+#include <SkPaint.h>
+#include <SkPathMeasure.h>
+
+#include "CachedGlyphInfo.h"
+#include "../Rect.h"
+
+namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Font
+///////////////////////////////////////////////////////////////////////////////
+
+class FontRenderer;
+
+/**
+ * Represents a font, defined by a Skia font id and a font size. A font is used
+ * to generate glyphs and cache them in the FontState.
+ */
+class Font {
+public:
+    enum Style {
+        kFakeBold = 1
+    };
+
+    ~Font();
+
+    /**
+     * Renders the specified string of text.
+     * If bitmap is specified, it will be used as the render target
+     */
+    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
+            int numGlyphs, int x, int y, uint8_t *bitmap = NULL,
+            uint32_t bitmapW = 0, uint32_t bitmapH = 0);
+
+    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
+            int numGlyphs, int x, int y, const float* positions);
+
+    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
+            int numGlyphs, SkPath* path, float hOffset, float vOffset);
+
+    /**
+     * Creates a new font associated with the specified font state.
+     */
+    static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
+            int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style,
+            uint32_t strokeWidth);
+
+private:
+    friend class FontRenderer;
+    typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*,
+            uint32_t, uint32_t, Rect*, const float*);
+
+    enum RenderMode {
+        FRAMEBUFFER,
+        BITMAP,
+        MEASURE,
+    };
+
+    void precache(SkPaint* paint, const char* text, int numGlyphs);
+
+    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
+            int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
+            uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions);
+
+    void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+            int numGlyphs, Rect *bounds, const float* positions);
+
+    Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
+            uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
+
+    // Cache of glyphs
+    DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
+
+    void invalidateTextureCache(CacheTexture* cacheTexture = NULL);
+
+    CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph, bool precaching);
+    void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph,
+            bool precaching);
+
+    void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
+            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
+            Rect* bounds, const float* pos);
+    void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
+            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
+            Rect* bounds, const float* pos);
+    void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
+            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
+            Rect* bounds, const float* pos);
+    void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset,
+            SkPathMeasure& measure, SkPoint* position, SkVector* tangent);
+
+    CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit, bool precaching = false);
+
+    FontRenderer* mState;
+    uint32_t mFontId;
+    float mFontSize;
+    int mFlags;
+    uint32_t mItalicStyle;
+    uint32_t mScaleX;
+    SkPaint::Style mStyle;
+    uint32_t mStrokeWidth;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_FONT_H
diff --git a/libs/hwui/font/FontUtil.h b/libs/hwui/font/FontUtil.h
new file mode 100644
index 0000000..12247ba
--- /dev/null
+++ b/libs/hwui/font/FontUtil.h
@@ -0,0 +1,60 @@
+/*
+ * 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 ANDROID_HWUI_FONT_UTIL_H
+#define ANDROID_HWUI_FONT_UTIL_H
+
+#include <SkUtils.h>
+
+#include "Properties.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+#define DEFAULT_TEXT_SMALL_CACHE_WIDTH 1024
+#define DEFAULT_TEXT_SMALL_CACHE_HEIGHT 256
+#define DEFAULT_TEXT_LARGE_CACHE_WIDTH 2048
+#define DEFAULT_TEXT_LARGE_CACHE_HEIGHT 512
+
+#define TEXTURE_BORDER_SIZE 1
+
+#define CACHE_BLOCK_ROUNDING_SIZE 4
+
+#if RENDER_TEXT_AS_GLYPHS
+    typedef uint16_t glyph_t;
+    #define TO_GLYPH(g) g
+    #define GET_METRICS(paint, glyph) paint->getGlyphMetrics(glyph)
+    #define GET_GLYPH(text) nextGlyph((const uint16_t**) &text)
+    #define IS_END_OF_STRING(glyph) false
+
+    static glyph_t nextGlyph(const uint16_t** srcPtr) {
+        const uint16_t* src = *srcPtr;
+        glyph_t g = *src++;
+        *srcPtr = src;
+        return g;
+    }
+#else
+    typedef SkUnichar glyph_t;
+    #define TO_GLYPH(g) ((SkUnichar) g)
+    #define GET_METRICS(paint, glyph) paint->getUnicharMetrics(glyph)
+    #define GET_GLYPH(text) SkUTF16_NextUnichar((const uint16_t**) &text)
+    #define IS_END_OF_STRING(glyph) glyph < 0
+#endif
+
+#define AUTO_KERN(prev, next) (((next) - (prev) + 32) >> 6 << 16)
+
+#endif // ANDROID_HWUI_FONT_UTIL_H
diff --git a/libs/storage/IMountService.cpp b/libs/storage/IMountService.cpp
index 4ec8b25..5701678 100644
--- a/libs/storage/IMountService.cpp
+++ b/libs/storage/IMountService.cpp
@@ -433,12 +433,13 @@
         reply.readExceptionCode();
     }
 
-    void mountObb(const String16& filename, const String16& key,
+    void mountObb(const String16& rawPath, const String16& canonicalPath, const String16& key,
             const sp<IObbActionListener>& token, int32_t nonce)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
-        data.writeString16(filename);
+        data.writeString16(rawPath);
+        data.writeString16(canonicalPath);
         data.writeString16(key);
         data.writeStrongBinder(token->asBinder());
         data.writeInt32(nonce);
diff --git a/location/java/android/location/Criteria.java b/location/java/android/location/Criteria.java
index 1f3fb7a..a6099be 100644
--- a/location/java/android/location/Criteria.java
+++ b/location/java/android/location/Criteria.java
@@ -326,6 +326,7 @@
 
     public static final Parcelable.Creator<Criteria> CREATOR =
         new Parcelable.Creator<Criteria>() {
+        @Override
         public Criteria createFromParcel(Parcel in) {
             Criteria c = new Criteria();
             c.mHorizontalAccuracy = in.readInt();
@@ -340,15 +341,18 @@
             return c;
         }
 
+        @Override
         public Criteria[] newArray(int size) {
             return new Criteria[size];
         }
     };
 
+    @Override
     public int describeContents() {
         return 0;
     }
 
+    @Override
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeInt(mHorizontalAccuracy);
         parcel.writeInt(mVerticalAccuracy);
@@ -360,4 +364,43 @@
         parcel.writeInt(mSpeedRequired ? 1 : 0);
         parcel.writeInt(mCostAllowed ? 1 : 0);
     }
+
+    private static String powerToString(int power) {
+        switch (power) {
+            case NO_REQUIREMENT:
+                return "NO_REQ";
+            case POWER_LOW:
+                return "LOW";
+            case POWER_MEDIUM:
+                return "MEDIUM";
+            case POWER_HIGH:
+                return "HIGH";
+            default:
+                return "???";
+        }
+    }
+
+    private static String accuracyToString(int accuracy) {
+        switch (accuracy) {
+            case NO_REQUIREMENT:
+                return "---";
+            case ACCURACY_HIGH:
+                return "HIGH";
+            case ACCURACY_MEDIUM:
+                return "MEDIUM";
+            case ACCURACY_LOW:
+                return "LOW";
+            default:
+                return "???";
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder s = new StringBuilder();
+        s.append("Criteria[power=").append(powerToString(mPowerRequirement));
+        s.append(" acc=").append(accuracyToString(mHorizontalAccuracy));
+        s.append(']');
+        return s.toString();
+    }
 }
diff --git a/location/java/android/location/Geofence.aidl b/location/java/android/location/Geofence.aidl
new file mode 100644
index 0000000..a5c6aa0
--- /dev/null
+++ b/location/java/android/location/Geofence.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.location;
+
+parcelable Geofence;
diff --git a/location/java/android/location/Geofence.java b/location/java/android/location/Geofence.java
new file mode 100644
index 0000000..5fef626
--- /dev/null
+++ b/location/java/android/location/Geofence.java
@@ -0,0 +1,182 @@
+/*
+ * 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.location;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents a geographical boundary, also known as a geofence.
+ *
+ * <p>Currently only circular geofences are supported and they do not support altitude changes.
+ *
+ * @hide
+ */
+public final class Geofence implements Parcelable {
+    /** @hide */
+    public static final int TYPE_HORIZONTAL_CIRCLE = 1;
+
+    private final int mType;
+    private final double mLatitude;
+    private final double mLongitude;
+    private final float mRadius;
+
+    /**
+     * Create a circular geofence (on a flat, horizontal plane).
+     *
+     * @param latitude latitude in degrees
+     * @param longitude longitude in degrees
+     * @param radius radius in meters
+     * @return a new geofence
+     * @throws IllegalArgumentException if any parameters are out of range
+     */
+    public static Geofence createCircle(double latitude, double longitude, float radius) {
+        return new Geofence(latitude, longitude, radius);
+    }
+
+    private Geofence(double latitude, double longitude, float radius) {
+        checkRadius(radius);
+        checkLatLong(latitude, longitude);
+        mType = TYPE_HORIZONTAL_CIRCLE;
+        mLatitude = latitude;
+        mLongitude = longitude;
+        mRadius = radius;
+    }
+
+    /** @hide */
+    public int getType() {
+        return mType;
+    }
+
+    /** @hide */
+    public double getLatitude() {
+        return mLatitude;
+    }
+
+    /** @hide */
+    public double getLongitude() {
+        return mLongitude;
+    }
+
+    /** @hide */
+    public float getRadius() {
+        return mRadius;
+    }
+
+    private static void checkRadius(float radius) {
+        if (radius <= 0) {
+            throw new IllegalArgumentException("invalid radius: " + radius);
+        }
+    }
+
+    private static void checkLatLong(double latitude, double longitude) {
+        if (latitude > 90.0 || latitude < -90.0) {
+            throw new IllegalArgumentException("invalid latitude: " + latitude);
+        }
+        if (longitude > 180.0 || longitude < -180.0) {
+            throw new IllegalArgumentException("invalid longitude: " + longitude);
+        }
+    }
+
+    private static void checkType(int type) {
+        if (type != TYPE_HORIZONTAL_CIRCLE) {
+            throw new IllegalArgumentException("invalid type: " + type);
+        }
+    }
+
+    public static final Parcelable.Creator<Geofence> CREATOR = new Parcelable.Creator<Geofence>() {
+        @Override
+        public Geofence createFromParcel(Parcel in) {
+            int type = in.readInt();
+            double latitude = in.readDouble();
+            double longitude = in.readDouble();
+            float radius = in.readFloat();
+            checkType(type);
+            return Geofence.createCircle(latitude, longitude, radius);
+        }
+        @Override
+        public Geofence[] newArray(int size) {
+            return new Geofence[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(mType);
+        parcel.writeDouble(mLatitude);
+        parcel.writeDouble(mLongitude);
+        parcel.writeFloat(mRadius);
+    }
+
+    private static String typeToString(int type) {
+        switch (type) {
+            case TYPE_HORIZONTAL_CIRCLE:
+                return "CIRCLE";
+            default:
+                checkType(type);
+                return null;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return String.format("Geofence[%s %.6f, %.6f %.0fm]",
+                typeToString(mType), mLatitude, mLongitude, mRadius);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        long temp;
+        temp = Double.doubleToLongBits(mLatitude);
+        result = prime * result + (int) (temp ^ (temp >>> 32));
+        temp = Double.doubleToLongBits(mLongitude);
+        result = prime * result + (int) (temp ^ (temp >>> 32));
+        result = prime * result + Float.floatToIntBits(mRadius);
+        result = prime * result + mType;
+        return result;
+    }
+
+    /**
+     * Two geofences are equal if they have identical properties.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (!(obj instanceof Geofence))
+            return false;
+        Geofence other = (Geofence) obj;
+        if (mRadius != other.mRadius)
+            return false;
+        if (mLatitude != other.mLatitude)
+            return false;
+        if (mLongitude != other.mLongitude)
+            return false;
+        if (mType != other.mType)
+            return false;
+        return true;
+    }
+}
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 38a29d3..f663e0a 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -20,53 +20,36 @@
 import android.location.Address;
 import android.location.Criteria;
 import android.location.GeocoderParams;
+import android.location.Geofence;
 import android.location.IGeocodeProvider;
 import android.location.IGpsStatusListener;
 import android.location.ILocationListener;
 import android.location.Location;
+import android.location.LocationRequest;
 import android.os.Bundle;
 
+import com.android.internal.location.ProviderProperties;
+
 /**
  * System private API for talking with the location service.
  *
- * {@hide}
+ * @hide
  */
 interface ILocationManager
 {
-    List<String> getAllProviders();
-    List<String> getProviders(in Criteria criteria, boolean enabledOnly);
-    String getBestProvider(in Criteria criteria, boolean enabledOnly);
-    boolean providerMeetsCriteria(String provider, in Criteria criteria);
+    void requestLocationUpdates(in LocationRequest request, in ILocationListener listener,
+            in PendingIntent intent, String packageName);
+    void removeUpdates(in ILocationListener listener, in PendingIntent intent, String packageName);
 
-    void requestLocationUpdates(String provider, in Criteria criteria, long minTime, float minDistance,
-        boolean singleShot, in ILocationListener listener, String packageName);
-    void requestLocationUpdatesPI(String provider, in Criteria criteria, long minTime, float minDistance,
-        boolean singleShot, in PendingIntent intent, String packageName);
-    void removeUpdates(in ILocationListener listener, String packageName);
-    void removeUpdatesPI(in PendingIntent intent, String packageName);
+    void requestGeofence(in LocationRequest request, in Geofence geofence,
+            in PendingIntent intent, String packageName);
+    void removeGeofence(in Geofence fence, in PendingIntent intent, String packageName);
+
+    Location getLastLocation(in LocationRequest request, String packageName);
 
     boolean addGpsStatusListener(IGpsStatusListener listener);
     void removeGpsStatusListener(IGpsStatusListener listener);
 
-    // for reporting callback completion
-    void locationCallbackFinished(ILocationListener listener);
-
-    boolean sendExtraCommand(String provider, String command, inout Bundle extras);
-
-    void addProximityAlert(double latitude, double longitude, float distance,
-        long expiration, in PendingIntent intent, String packageName);
-    void removeProximityAlert(in PendingIntent intent);
-
-    Bundle getProviderInfo(String provider);
-    boolean isProviderEnabled(String provider);
-
-    Location getLastKnownLocation(String provider, String packageName);
-
-    // Used by location providers to tell the location manager when it has a new location.
-    // Passive is true if the location is coming from the passive provider, in which case
-    // it need not be shared with other providers.
-    void reportLocation(in Location location, boolean passive);
-
     boolean geocoderIsPresent();
     String getFromLocation(double latitude, double longitude, int maxResults,
         in GeocoderParams params, out List<Address> addrs);
@@ -75,9 +58,17 @@
         double upperRightLatitude, double upperRightLongitude, int maxResults,
         in GeocoderParams params, out List<Address> addrs);
 
-    void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite,
-        boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
-        boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy);
+    boolean sendNiResponse(int notifId, int userResponse);
+
+    // --- deprecated ---
+    List<String> getAllProviders();
+    List<String> getProviders(in Criteria criteria, boolean enabledOnly);
+    String getBestProvider(in Criteria criteria, boolean enabledOnly);
+    boolean providerMeetsCriteria(String provider, in Criteria criteria);
+    ProviderProperties getProviderProperties(String provider);
+    boolean isProviderEnabled(String provider);
+
+    void addTestProvider(String name, in ProviderProperties properties);
     void removeTestProvider(String provider);
     void setTestProviderLocation(String provider, in Location loc);
     void clearTestProviderLocation(String provider);
@@ -86,6 +77,17 @@
     void setTestProviderStatus(String provider, int status, in Bundle extras, long updateTime);
     void clearTestProviderStatus(String provider);
 
-    // for NI support
-    boolean sendNiResponse(int notifId, int userResponse);
+    boolean sendExtraCommand(String provider, String command, inout Bundle extras);
+
+    // --- internal ---
+
+    // Used by location providers to tell the location manager when it has a new location.
+    // Passive is true if the location is coming from the passive provider, in which case
+    // it need not be shared with other providers.
+    void reportLocation(in Location location, boolean passive);
+
+    // for reporting callback completion
+    void locationCallbackFinished(ILocationListener listener);
+
+
 }
diff --git a/location/java/android/location/ILocationProvider.aidl b/location/java/android/location/ILocationProvider.aidl
deleted file mode 100644
index ecf6789..0000000
--- a/location/java/android/location/ILocationProvider.aidl
+++ /dev/null
@@ -1,53 +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.
- */
-
-package android.location;
-
-import android.location.Criteria;
-import android.location.Location;
-import android.net.NetworkInfo;
-import android.os.Bundle;
-import android.os.WorkSource;
-
-/**
- * Binder interface for services that implement location providers.
- *
- * {@hide}
- */
-interface ILocationProvider {
-    boolean requiresNetwork();
-    boolean requiresSatellite();
-    boolean requiresCell();
-    boolean hasMonetaryCost();
-    boolean supportsAltitude();
-    boolean supportsSpeed();
-    boolean supportsBearing();
-    int getPowerRequirement();
-    boolean meetsCriteria(in Criteria criteria);
-    int getAccuracy();
-    void enable();
-    void disable();
-    int getStatus(out Bundle extras);
-    long getStatusUpdateTime();
-    String getInternalState();
-    void enableLocationTracking(boolean enable);
-    void setMinTime(long minTime, in WorkSource ws);
-    void updateNetworkState(int state, in NetworkInfo info);
-    void updateLocation(in Location location);
-    boolean sendExtraCommand(String command, inout Bundle extras);
-    void addListener(int uid);
-    void removeListener(int uid);
-}
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index aacf857..9b32667 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -19,21 +19,23 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SystemClock;
 import android.util.Printer;
+import android.util.TimeUtils;
 
 import java.text.DecimalFormat;
 import java.util.StringTokenizer;
 
 /**
- * A class representing a geographic location sensed at a particular
- * time (a "fix").  A location consists of a latitude and longitude, a
- * UTC timestamp. and optionally information on altitude, speed, and
- * bearing.
+ * A data class representing a geographic location.
  *
- * <p> Information specific to a particular provider or class of
- * providers may be communicated to the application using getExtras,
- * which returns a Bundle of key/value pairs.  Each provider will only
- * provide those entries for which information is available.
+ * <p>A location can consist of a latitude, longitude, timestamp,
+ * and other information such as bearing, altitude and velocity.
+ *
+ * <p>All locations generated by the {@link LocationManager} are
+ * guaranteed to have a valid latitude, longitude, and timestamp
+ * (both UTC time and elapsed real-time since boot), all other
+ * parameters are optional.
  */
 public class Location implements Parcelable {
     /**
@@ -57,8 +59,27 @@
      */
     public static final int FORMAT_SECONDS = 2;
 
+    /**
+     * Bundle key for a version of the location that has been fed through
+     * LocationFudger. Allows location providers to flag locations as being
+     * safe for use with ACCESS_COARSE_LOCATION permission.
+     *
+     * @hide
+     */
+    public static final String EXTRA_COARSE_LOCATION = "coarseLocation";
+
+    /**
+     * Bundle key for a version of the location containing no GPS data.
+     * Allows location providers to flag locations as being safe to
+     * feed to LocationFudger.
+     *
+     * @hide
+     */
+    public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";
+
     private String mProvider;
     private long mTime = 0;
+    private long mElapsedRealtimeNanos = 0;
     private double mLatitude = 0.0;
     private double mLongitude = 0.0;
     private boolean mHasAltitude = false;
@@ -80,33 +101,22 @@
     private float mDistance = 0.0f;
     private float mInitialBearing = 0.0f;
     // Scratchpad
-    private float[] mResults = new float[2];
+    private final float[] mResults = new float[2];
 
-    public void dump(Printer pw, String prefix) {
-        pw.println(prefix + "mProvider=" + mProvider + " mTime=" + mTime);
-        pw.println(prefix + "mLatitude=" + mLatitude + " mLongitude=" + mLongitude);
-        pw.println(prefix + "mHasAltitude=" + mHasAltitude + " mAltitude=" + mAltitude);
-        pw.println(prefix + "mHasSpeed=" + mHasSpeed + " mSpeed=" + mSpeed);
-        pw.println(prefix + "mHasBearing=" + mHasBearing + " mBearing=" + mBearing);
-        pw.println(prefix + "mHasAccuracy=" + mHasAccuracy + " mAccuracy=" + mAccuracy);
-        pw.println(prefix + "mExtras=" + mExtras);
-    }
-    
     /**
-     * Constructs a new Location.  By default, time, latitude,
-     * longitude, and numSatellites are 0; hasAltitude, hasSpeed, and
-     * hasBearing are false; and there is no extra information.
+     * Construct a new Location with a named provider.
      *
-     * @param provider the name of the location provider that generated this
-     * location fix.
+     * <p>By default time, latitude and longitude are 0, and the location
+     * has no bearing, altitude, speed, accuracy or extras.
+     *
+     * @param provider the name of the provider that generated this location
      */
     public Location(String provider) {
         mProvider = provider;
     }
 
     /**
-     * Constructs a new Location object that is a copy of the given
-     * location.
+     * Construct a new Location object that is copied from an existing one.
      */
     public Location(Location l) {
         set(l);
@@ -118,6 +128,7 @@
     public void set(Location l) {
         mProvider = l.mProvider;
         mTime = l.mTime;
+        mElapsedRealtimeNanos = l.mElapsedRealtimeNanos;
         mLatitude = l.mLatitude;
         mLongitude = l.mLongitude;
         mHasAltitude = l.mHasAltitude;
@@ -137,6 +148,7 @@
     public void reset() {
         mProvider = null;
         mTime = 0;
+        mElapsedRealtimeNanos = 0;
         mLatitude = 0;
         mLongitude = 0;
         mHasAltitude = false;
@@ -452,8 +464,9 @@
     }
 
     /**
-     * Returns the name of the provider that generated this fix,
-     * or null if it is not associated with a provider.
+     * Returns the name of the provider that generated this fix.
+     *
+     * @return the provider, or null if it has not been set
      */
     public String getProvider() {
         return mProvider;
@@ -467,68 +480,118 @@
     }
 
     /**
-     * Returns the UTC time of this fix, in milliseconds since January 1,
-     * 1970.
+     * Return the UTC time of this fix, in milliseconds since January 1, 1970.
+     *
+     * <p>Note that the UTC time on a device is not monotonic: it
+     * can jump forwards or backwards unpredictably. So always use
+     * {@link #getElapsedRealtimeNanos} when calculating time deltas.
+     *
+     * <p>On the other hand, {@link #getTime} is useful for presenting
+     * a human readable time to the user, or for carefully comparing
+     * location fixes across reboot or across devices.
+     *
+     * <p>All locations generated by the {@link LocationManager}
+     * are guaranteed to have a valid UTC time, however remember that
+     * the system time may have changed since the location was generated.
+     *
+     * @return time of fix, in milliseconds since January 1, 1970.
      */
     public long getTime() {
         return mTime;
     }
 
     /**
-     * Sets the UTC time of this fix, in milliseconds since January 1,
+     * Set the UTC time of this fix, in milliseconds since January 1,
      * 1970.
+     *
+     * @param time UTC time of this fix, in milliseconds since January 1, 1970
      */
     public void setTime(long time) {
         mTime = time;
     }
 
     /**
-     * Returns the latitude of this fix.
+     * Return the time of this fix, in elapsed real-time since system boot.
+     *
+     * <p>This value can be reliably compared to
+     * {@link android.os.SystemClock#elapsedRealtimeNanos},
+     * to calculate the age of a fix and to compare Location fixes. This
+     * is reliable because elapsed real-time is guaranteed monotonic for
+     * each system boot and continues to increment even when the system
+     * is in deep sleep (unlike {@link #getTime}.
+     *
+     * <p>All locations generated by the {@link LocationManager}
+     * are guaranteed to have a valid elapsed real-time.
+     *
+     * @return elapsed real-time of fix, in nanoseconds since system boot.
+     */
+    public long getElapsedRealtimeNanos() {
+        return mElapsedRealtimeNanos;
+    }
+
+    /**
+     * Set the time of this fix, in elapsed real-time since system boot.
+     *
+     * @param time elapsed real-time of fix, in nanoseconds since system boot.
+     */
+    public void setElapsedRealtimeNanos(long time) {
+        mElapsedRealtimeNanos = time;
+    }
+
+    /**
+     * Get the latitude, in degrees.
+     *
+     * <p>All locations generated by the {@link LocationManager}
+     * will have a valid latitude.
      */
     public double getLatitude() {
         return mLatitude;
     }
 
     /**
-     * Sets the latitude of this fix.
+     * Set the latitude, in degrees.
      */
     public void setLatitude(double latitude) {
         mLatitude = latitude;
     }
 
     /**
-     * Returns the longitude of this fix.
+     * Get the longitude, in degrees.
+     *
+     * <p>All locations generated by the {@link LocationManager}
+     * will have a valid longitude.
      */
     public double getLongitude() {
         return mLongitude;
     }
 
     /**
-     * Sets the longitude of this fix.
+     * Set the longitude, in degrees.
      */
     public void setLongitude(double longitude) {
         mLongitude = longitude;
     }
 
     /**
-     * Returns true if this fix contains altitude information, false
-     * otherwise.
+     * True if this location has an altitude.
      */
     public boolean hasAltitude() {
         return mHasAltitude;
     }
 
     /**
-     * Returns the altitude of this fix.  If {@link #hasAltitude} is false,
-     * 0.0f is returned.
+     * Get the altitude if available, in meters above sea level.
+     *
+     * <p>If this location does not have an altitude then 0.0 is returned.
      */
     public double getAltitude() {
         return mAltitude;
     }
 
     /**
-     * Sets the altitude of this fix.  Following this call,
-     * hasAltitude() will return true.
+     * Set the altitude, in meters above sea level.
+     *
+     * <p>Following this call {@link #hasAltitude} will return true.
      */
     public void setAltitude(double altitude) {
         mAltitude = altitude;
@@ -536,8 +599,10 @@
     }
 
     /**
-     * Clears the altitude of this fix.  Following this call,
-     * hasAltitude() will return false.
+     * Remove the altitude from this location.
+     *
+     * <p>Following this call {@link #hasAltitude} will return false,
+     * and {@link #getAltitude} will return 0.0.
      */
     public void removeAltitude() {
         mAltitude = 0.0f;
@@ -545,24 +610,25 @@
     }
 
     /**
-     * Returns true if this fix contains speed information, false
-     * otherwise.  The default implementation returns false.
+     * True if this location has a speed.
      */
     public boolean hasSpeed() {
         return mHasSpeed;
     }
 
     /**
-     * Returns the speed of the device over ground in meters/second.
-     * If hasSpeed() is false, 0.0f is returned.
+     * Get the speed if it is available, in meters/second over ground.
+     *
+     * <p>If this location does not have a speed then 0.0 is returned.
      */
     public float getSpeed() {
         return mSpeed;
     }
 
     /**
-     * Sets the speed of this fix, in meters/second.  Following this
-     * call, hasSpeed() will return true.
+     * Set the speed, in meters/second over ground.
+     *
+     * <p>Following this call {@link #hasSpeed} will return true.
      */
     public void setSpeed(float speed) {
         mSpeed = speed;
@@ -570,8 +636,10 @@
     }
 
     /**
-     * Clears the speed of this fix.  Following this call, hasSpeed()
-     * will return false.
+     * Remove the speed from this location.
+     *
+     * <p>Following this call {@link #hasSpeed} will return false,
+     * and {@link #getSpeed} will return 0.0.
      */
     public void removeSpeed() {
         mSpeed = 0.0f;
@@ -579,24 +647,32 @@
     }
 
     /**
-     * Returns true if the provider is able to report bearing information,
-     * false otherwise.  The default implementation returns false.
+     * True if this location has a bearing.
      */
     public boolean hasBearing() {
         return mHasBearing;
     }
 
     /**
-     * Returns the direction of travel in degrees East of true
-     * North. If hasBearing() is false, 0.0 is returned.
+     * Get the bearing, in degrees.
+     *
+     * <p>Bearing is the horizontal direction of travel of this device,
+     * and is not related to the device orientation. It is guaranteed to
+     * be in the range (0.0, 360.0] if the device has a bearing.
+     *
+     * <p>If this location does not have a bearing then 0.0 is returned.
      */
     public float getBearing() {
         return mBearing;
     }
 
     /**
-     * Sets the bearing of this fix.  Following this call, hasBearing()
-     * will return true.
+     * Set the bearing, in degrees.
+     *
+     * <p>Bearing is the horizontal direction of travel of this device,
+     * and is not related to the device orientation.
+     *
+     * <p>The input will be wrapped into the range (0.0, 360.0].
      */
     public void setBearing(float bearing) {
         while (bearing < 0.0f) {
@@ -610,8 +686,10 @@
     }
 
     /**
-     * Clears the bearing of this fix.  Following this call, hasBearing()
-     * will return false.
+     * Remove the bearing from this location.
+     *
+     * <p>Following this call {@link #hasBearing} will return false,
+     * and {@link #getBearing} will return 0.0.
      */
     public void removeBearing() {
         mBearing = 0.0f;
@@ -619,24 +697,47 @@
     }
 
     /**
-     * Returns true if the provider is able to report accuracy information,
-     * false otherwise.  The default implementation returns false.
+     * True if this location has an accuracy.
+     *
+     * <p>All locations generated by the {@link LocationManager} have an
+     * accuracy.
      */
     public boolean hasAccuracy() {
         return mHasAccuracy;
     }
 
     /**
-     * Returns the accuracy of the fix in meters. If hasAccuracy() is false,
-     * 0.0 is returned.
+     * Get the estimated accuracy of this location, in meters.
+     *
+     * <p>We define accuracy as the radius of 68% confidence. In other
+     * words, if you draw a circle centered at this location's
+     * latitude and longitude, and with a radius equal to the accuracy,
+     * then there is a 68% probability that the true location is inside
+     * the circle.
+     *
+     * <p>In statistical terms, it is assumed that location errors
+     * are random with a normal distribution, so the 68% confidence circle
+     * represents one standard deviation. Note that in practice, location
+     * errors do not always follow such a simple distribution.
+     *
+     * <p>This accuracy estimation is only concerned with horizontal
+     * accuracy, and does not indicate the accuracy of bearing,
+     * velocity or altitude if those are included in this Location.
+     *
+     * <p>If this location does not have an accuracy, then 0.0 is returned.
+     * All locations generated by the {@link LocationManager} include
+     * an accuracy.
      */
     public float getAccuracy() {
         return mAccuracy;
     }
 
     /**
-     * Sets the accuracy of this fix.  Following this call, hasAccuracy()
-     * will return true.
+     * Set the estimated accuracy of this location, meters.
+     *
+     * <p>See {@link #getAccuracy} for the definition of accuracy.
+     *
+     * <p>Following this call {@link #hasAccuracy} will return true.
      */
     public void setAccuracy(float accuracy) {
         mAccuracy = accuracy;
@@ -644,8 +745,10 @@
     }
 
     /**
-     * Clears the accuracy of this fix.  Following this call, hasAccuracy()
-     * will return false.
+     * Remove the accuracy from this location.
+     *
+     * <p>Following this call {@link #hasAccuracy} will return false, and
+     * {@link #getAccuracy} will return 0.0.
      */
     public void removeAccuracy() {
         mAccuracy = 0.0f;
@@ -653,6 +756,45 @@
     }
 
     /**
+     * Return true if this Location object is complete.
+     *
+     * <p>A location object is currently considered complete if it has
+     * a valid provider, accuracy, wall-clock time and elapsed real-time.
+     *
+     * <p>All locations supplied by the {@link LocationManager} to
+     * applications must be complete.
+     *
+     * @see #makeComplete
+     * @hide
+     */
+    public boolean isComplete() {
+        if (mProvider == null) return false;
+        if (!mHasAccuracy) return false;
+        if (mTime == 0) return false;
+        if (mElapsedRealtimeNanos == 0) return false;
+        return true;
+    }
+
+    /**
+     * Helper to fill incomplete fields.
+     *
+     * <p>Used to assist in backwards compatibility with
+     * Location objects received from applications.
+     *
+     * @see #isComplete
+     * @hide
+     */
+    public void makeComplete() {
+        if (mProvider == null) mProvider = "?";
+        if (!mHasAccuracy) {
+            mHasAccuracy = true;
+            mAccuracy = 100.0f;
+        }
+        if (mTime == 0) mTime = System.currentTimeMillis();
+        if (mElapsedRealtimeNanos == 0) mElapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
+    }
+
+    /**
      * Returns additional provider-specific information about the
      * location fix as a Bundle.  The keys and values are determined
      * by the provider.  If no additional information is available,
@@ -678,28 +820,46 @@
         mExtras = (extras == null) ? null : new Bundle(extras);
     }
 
-    @Override public String toString() {
-        return "Location[mProvider=" + mProvider +
-            ",mTime=" + mTime +
-            ",mLatitude=" + mLatitude +
-            ",mLongitude=" + mLongitude +
-            ",mHasAltitude=" + mHasAltitude +
-            ",mAltitude=" + mAltitude +
-            ",mHasSpeed=" + mHasSpeed +
-            ",mSpeed=" + mSpeed +
-            ",mHasBearing=" + mHasBearing +
-            ",mBearing=" + mBearing +
-            ",mHasAccuracy=" + mHasAccuracy +
-            ",mAccuracy=" + mAccuracy +
-            ",mExtras=" + mExtras + "]";
+    @Override
+    public String toString() {
+        StringBuilder s = new StringBuilder();
+        s.append("Location[");
+        s.append(mProvider);
+        s.append(String.format(" %.6f,%.6f", mLatitude, mLongitude));
+        if (mHasAccuracy) s.append(String.format(" acc=%.0f", mAccuracy));
+        else s.append(" acc=???");
+        if (mTime == 0) {
+            s.append(" t=?!?");
+        }
+        if (mElapsedRealtimeNanos == 0) {
+            s.append(" et=?!?");
+        } else {
+            s.append(" et=");
+            TimeUtils.formatDuration(mElapsedRealtimeNanos / 1000000L, s);
+        }
+        if (mHasAltitude) s.append(" alt=").append(mAltitude);
+        if (mHasSpeed) s.append(" vel=").append(mSpeed);
+        if (mHasBearing) s.append(" bear=").append(mBearing);
+
+        if (mExtras != null) {
+            s.append(" {").append(mExtras).append('}');
+        }
+        s.append(']');
+        return s.toString();
+    }
+
+    public void dump(Printer pw, String prefix) {
+        pw.println(prefix + toString());
     }
 
     public static final Parcelable.Creator<Location> CREATOR =
         new Parcelable.Creator<Location>() {
+        @Override
         public Location createFromParcel(Parcel in) {
             String provider = in.readString();
             Location l = new Location(provider);
             l.mTime = in.readLong();
+            l.mElapsedRealtimeNanos = in.readLong();
             l.mLatitude = in.readDouble();
             l.mLongitude = in.readDouble();
             l.mHasAltitude = in.readInt() != 0;
@@ -714,18 +874,22 @@
             return l;
         }
 
+        @Override
         public Location[] newArray(int size) {
             return new Location[size];
         }
     };
 
+    @Override
     public int describeContents() {
         return 0;
     }
 
+    @Override
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeString(mProvider);
         parcel.writeLong(mTime);
+        parcel.writeLong(mElapsedRealtimeNanos);
         parcel.writeDouble(mLatitude);
         parcel.writeDouble(mLongitude);
         parcel.writeInt(mHasAltitude ? 1 : 0);
@@ -737,5 +901,37 @@
         parcel.writeInt(mHasAccuracy ? 1 : 0);
         parcel.writeFloat(mAccuracy);
         parcel.writeBundle(mExtras);
-   }
+    }
+
+    /**
+     * Returns one of the optional extra {@link Location}s that can be attached
+     * to this Location.
+     *
+     * @param key the key associated with the desired extra Location
+     * @return the extra Location, or null if unavailable
+     * @hide
+     */
+    public Location getExtraLocation(String key) {
+        if (mExtras != null) {
+            Parcelable value = mExtras.getParcelable(key);
+            if (value instanceof Location) {
+                return (Location) value;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Attaches an extra {@link Location} to this Location.
+     *
+     * @param key the key associated with the Location extra
+     * @param location the Location to attach
+     * @hide
+     */
+    public void setExtraLocation(String key, Location value) {
+        if (mExtras == null) {
+            mExtras = new Bundle();
+        }
+        mExtras.putParcelable(key, value);
+    }
 }
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 5c256a3..5a2f71b 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -19,6 +19,7 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Looper;
 import android.os.RemoteException;
@@ -26,12 +27,13 @@
 import android.os.Message;
 import android.util.Log;
 
-import com.android.internal.location.DummyLocationProvider;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 
+import com.android.internal.location.ProviderProperties;
+
 /**
  * This class provides access to the system location services.  These
  * services allow applications to obtain periodic updates of the
@@ -44,16 +46,19 @@
  * {@link android.content.Context#getSystemService
  * Context.getSystemService(Context.LOCATION_SERVICE)}.
  *
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>For more information about using location services, read the
- * <a href="{@docRoot}guide/topics/location/index.html">Location and Maps</a>
- * developer guide.</p>
- * </div>
+ * <p class="note">Unless noted, all Location API methods require
+ * the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} or
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permissions.
+ * If your application only has the coarse permission then it will not have
+ * access to the GPS or passive location providers. Other providers will still
+ * return location results, but the update rate will be throttled and the exact
+ * location will be obfuscated to a coarse level of accuracy.
  */
 public class LocationManager {
     private static final String TAG = "LocationManager";
-    private ILocationManager mService;
+
+    private final Context mContext;
+    private final ILocationManager mService;
     private final HashMap<GpsStatus.Listener, GpsStatusListenerTransport> mGpsStatusListeners =
             new HashMap<GpsStatus.Listener, GpsStatusListenerTransport>();
     private final HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport> mNmeaListeners =
@@ -61,25 +66,23 @@
     private final GpsStatus mGpsStatus = new GpsStatus();
 
     /**
-     * Name of the network location provider.  This provider determines location based on
+     * Name of the network location provider.
+     * <p>This provider determines location based on
      * availability of cell tower and WiFi access points. Results are retrieved
      * by means of a network lookup.
-     *
-     * Requires either of the permissions android.permission.ACCESS_COARSE_LOCATION
-     * or android.permission.ACCESS_FINE_LOCATION.
      */
     public static final String NETWORK_PROVIDER = "network";
 
     /**
-     * Name of the GPS location provider. This provider determines location using
-     * satellites. Depending on conditions, this provider may take a while to return
-     * a location fix.
+     * Name of the GPS location provider.
      *
-     * Requires the permission android.permission.ACCESS_FINE_LOCATION.
+     * <p>This provider determines location using
+     * satellites. Depending on conditions, this provider may take a while to return
+     * a location fix. Requires the permission
+     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
      *
      * <p> The extras Bundle for the GPS location provider can contain the
      * following key/value pairs:
-     *
      * <ul>
      * <li> satellites - the number of satellites used to derive the fix
      * </ul>
@@ -88,18 +91,31 @@
 
     /**
      * A special location provider for receiving locations without actually initiating
-     * a location fix. This provider can be used to passively receive location updates
+     * a location fix.
+     *
+     * <p>This provider can be used to passively receive location updates
      * when other applications or services request them without actually requesting
      * the locations yourself.  This provider will return locations generated by other
      * providers.  You can query the {@link Location#getProvider()} method to determine
-     * the origin of the location update.
-     *
-     * Requires the permission android.permission.ACCESS_FINE_LOCATION, although if the GPS
-     * is not enabled this provider might only return coarse fixes.
+     * the origin of the location update. Requires the permission
+     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}, although if the GPS is
+     * not enabled this provider might only return coarse fixes.
      */
     public static final String PASSIVE_PROVIDER = "passive";
 
     /**
+     * Name of the Fused location provider.
+     *
+     * <p>This provider combines inputs for all possible location sources
+     * to provide the best possible Location fix. It is implicitly
+     * used for all API's that involve the {@link LocationRequest}
+     * object.
+     *
+     * @hide
+     */
+    public static final String FUSED_PROVIDER = "fused";
+
+    /**
      * Key used for the Bundle extra holding a boolean indicating whether
      * a proximity alert is entering (true) or exiting (false)..
      */
@@ -129,7 +145,7 @@
      * where {@code true} means enabled.
      * @see #EXTRA_GPS_ENABLED
      *
-     * {@hide}
+     * @hide
      */
     public static final String GPS_ENABLED_CHANGE_ACTION =
         "android.location.GPS_ENABLED_CHANGE";
@@ -147,7 +163,7 @@
      * boolean, where {@code true} means that the GPS is actively receiving fixes.
      * @see #EXTRA_GPS_ENABLED
      *
-     * {@hide}
+     * @hide
      */
     public static final String GPS_FIX_CHANGE_ACTION =
         "android.location.GPS_FIX_CHANGE";
@@ -157,12 +173,10 @@
      * disabled. {@code true} means GPS is enabled. Retrieve it with
      * {@link android.content.Intent#getBooleanExtra(String,boolean)}.
      *
-     * {@hide}
+     * @hide
      */
     public static final String EXTRA_GPS_ENABLED = "enabled";
 
-    private final Context mContext;
-
     // Map from LocationListeners to their associated ListenerTransport objects
     private HashMap<LocationListener,ListenerTransport> mListeners =
         new HashMap<LocationListener,ListenerTransport>();
@@ -196,6 +210,7 @@
             }
         }
 
+        @Override
         public void onLocationChanged(Location location) {
             Message msg = Message.obtain();
             msg.what = TYPE_LOCATION_CHANGED;
@@ -203,6 +218,7 @@
             mListenerHandler.sendMessage(msg);
         }
 
+        @Override
         public void onStatusChanged(String provider, int status, Bundle extras) {
             Message msg = Message.obtain();
             msg.what = TYPE_STATUS_CHANGED;
@@ -216,6 +232,7 @@
             mListenerHandler.sendMessage(msg);
         }
 
+        @Override
         public void onProviderEnabled(String provider) {
             Message msg = Message.obtain();
             msg.what = TYPE_PROVIDER_ENABLED;
@@ -223,6 +240,7 @@
             mListenerHandler.sendMessage(msg);
         }
 
+        @Override
         public void onProviderDisabled(String provider) {
             Message msg = Message.obtain();
             msg.what = TYPE_PROVIDER_DISABLED;
@@ -257,6 +275,7 @@
             }
         }
     }
+
     /**
      * @hide - hide this constructor because it has a parameter
      * of type ILocationManager, which is a system private class. The
@@ -268,43 +287,28 @@
         mContext = context;
     }
 
-    private LocationProvider createProvider(String name, Bundle info) {
-        DummyLocationProvider provider =
-            new DummyLocationProvider(name, mService);
-        provider.setRequiresNetwork(info.getBoolean("network"));
-        provider.setRequiresSatellite(info.getBoolean("satellite"));
-        provider.setRequiresCell(info.getBoolean("cell"));
-        provider.setHasMonetaryCost(info.getBoolean("cost"));
-        provider.setSupportsAltitude(info.getBoolean("altitude"));
-        provider.setSupportsSpeed(info.getBoolean("speed"));
-        provider.setSupportsBearing(info.getBoolean("bearing"));
-        provider.setPowerRequirement(info.getInt("power"));
-        provider.setAccuracy(info.getInt("accuracy"));
-        return provider;
+    private LocationProvider createProvider(String name, ProviderProperties properties) {
+        return new LocationProvider(name, properties);
     }
 
     /**
-     * Returns a list of the names of all known location providers.  All
-     * providers are returned, including ones that are not permitted to be
-     * accessed by the calling activity or are currently disabled.
+     * Returns a list of the names of all known location providers.
+     * <p>All providers are returned, including ones that are not permitted to
+     * be accessed by the calling activity or are currently disabled.
      *
-     * @return list of Strings containing names of the providers
+     * @return list of Strings containing names of the provider
      */
     public List<String> getAllProviders() {
-        if (false) {
-            Log.d(TAG, "getAllProviders");
-        }
         try {
             return mService.getAllProviders();
-        } catch (RemoteException ex) {
-            Log.e(TAG, "getAllProviders: RemoteException", ex);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
         return null;
     }
 
     /**
-     * Returns a list of the names of location providers.  Only providers that
-     * are permitted to be accessed by the calling activity will be returned.
+     * Returns a list of the names of location providers.
      *
      * @param enabledOnly if true then only the providers which are currently
      * enabled are returned.
@@ -313,8 +317,8 @@
     public List<String> getProviders(boolean enabledOnly) {
         try {
             return mService.getProviders(null, enabledOnly);
-        } catch (RemoteException ex) {
-            Log.e(TAG, "getProviders: RemoteException", ex);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
         return null;
     }
@@ -326,22 +330,20 @@
      * @param name the provider name
      * @return a LocationProvider, or null
      *
-     * @throws IllegalArgumentException if name is null
+     * @throws IllegalArgumentException if name is null or does not exist
      * @throws SecurityException if the caller is not permitted to access the
      * given provider.
      */
     public LocationProvider getProvider(String name) {
-        if (name == null) {
-            throw new IllegalArgumentException("name==null");
-        }
+        checkProvider(name);
         try {
-            Bundle info = mService.getProviderInfo(name);
-            if (info == null) {
+            ProviderProperties properties = mService.getProviderProperties(name);
+            if (properties == null) {
                 return null;
             }
-            return createProvider(name, info);
-        } catch (RemoteException ex) {
-            Log.e(TAG, "getProvider: RemoteException", ex);
+            return createProvider(name, properties);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
         return null;
     }
@@ -357,13 +359,11 @@
      * @return list of Strings containing names of the providers
      */
     public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
-        if (criteria == null) {
-            throw new IllegalArgumentException("criteria==null");
-        }
+        checkCriteria(criteria);
         try {
             return mService.getProviders(criteria, enabledOnly);
-        } catch (RemoteException ex) {
-            Log.e(TAG, "getProviders: RemoteException", ex);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
         return null;
     }
@@ -391,81 +391,26 @@
      * @return name of the provider that best matches the requirements
      */
     public String getBestProvider(Criteria criteria, boolean enabledOnly) {
-        if (criteria == null) {
-            throw new IllegalArgumentException("criteria==null");
-        }
+        checkCriteria(criteria);
         try {
             return mService.getBestProvider(criteria, enabledOnly);
-        } catch (RemoteException ex) {
-            Log.e(TAG, "getBestProvider: RemoteException", ex);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
         return null;
     }
 
     /**
-     * Registers the current activity to be notified periodically by
-     * the named provider.  Periodically, the supplied LocationListener will
-     * be called with the current Location or with status updates.
+     * Register for location updates using the named provider, and a
+     * pending intent.
      *
-     * <p> It may take a while to receive the first location update. If
-     * an immediate location is required, applications may use the
-     * {@link #getLastKnownLocation(String)} method.
-     *
-     * <p> In case the provider is disabled by the user, updates will stop,
-     * and the {@link LocationListener#onProviderDisabled(String)}
-     * method will be called. As soon as the provider is enabled again,
-     * the {@link LocationListener#onProviderEnabled(String)} method will
-     * be called and location updates will start again.
-     *
-     * <p> The update interval can be controlled using the minTime parameter.
-     * The elapsed time between location updates will never be less than
-     * minTime, although it can be more depending on the Location Provider
-     * implementation and the update interval requested by other applications.
-     *
-     * <p> Choosing a sensible value for minTime is important to conserve
-     * battery life. Each location update requires power from
-     * GPS, WIFI, Cell and other radios. Select a minTime value as high as
-     * possible while still providing a reasonable user experience.
-     * If your application is not in the foreground and showing
-     * location to the user then your application should avoid using an active
-     * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}),
-     * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes)
-     * or greater. If your application is in the foreground and showing
-     * location to the user then it is appropriate to select a faster
-     * update interval.
-     *
-     * <p> The minDistance parameter can also be used to control the
-     * frequency of location updates. If it is greater than 0 then the
-     * location provider will only send your application an update when
-     * the location has changed by at least minDistance meters, AND
-     * at least minTime milliseconds have passed. However it is more
-     * difficult for location providers to save power using the minDistance
-     * parameter, so minTime should be the primary tool to conserving battery
-     * life.
-     *
-     * <p> If your application wants to passively observe location
-     * updates triggered by other applications, but not consume
-     * any additional power otherwise, then use the {@link #PASSIVE_PROVIDER}
-     * This provider does not actively turn on or modify active location
-     * providers, so you do not need to be as careful about minTime and
-     * minDistance. However if your application performs heavy work
-     * on a location update (such as network activity) then you should
-     * select non-zero values for minTime and/or minDistance to rate-limit
-     * your update frequency in the case another application enables a
-     * location provider with extremely fast updates.
-     *
-     * <p> The calling thread must be a {@link android.os.Looper} thread such as
-     * the main thread of the calling Activity.
-     *
-     * <p class="note"> Prior to Jellybean, the minTime parameter was
-     * only a hint, and some location provider implementations ignored it.
-     * From Jellybean and onwards it is mandatory for Android compatible
-     * devices to observe both the minTime and minDistance parameters.
+     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
+     * for more detail on how to use this method.
      *
      * @param provider the name of the provider with which to register
      * @param minTime minimum time interval between location updates, in milliseconds
      * @param minDistance minimum distance between location updates, in meters
-     * @param listener a {#link LocationListener} whose
+     * @param listener a {@link LocationListener} whose
      * {@link LocationListener#onLocationChanged} method will be called for
      * each location update
      *
@@ -473,302 +418,128 @@
      * on this device
      * @throws IllegalArgumentException if listener is null
      * @throws RuntimeException if the calling thread has no Looper
-     * @throws SecurityException if no suitable permission is present for the provider.
+     * @throws SecurityException if no suitable permission is present
      */
-    public void requestLocationUpdates(String provider,
-        long minTime, float minDistance, LocationListener listener) {
-        if (provider == null) {
-            throw new IllegalArgumentException("provider==null");
-        }
-        if (listener == null) {
-            throw new IllegalArgumentException("listener==null");
-        }
-        _requestLocationUpdates(provider, null, minTime, minDistance, false, listener, null);
+    public void requestLocationUpdates(String provider, long minTime, float minDistance,
+            LocationListener listener) {
+        checkProvider(provider);
+        checkListener(listener);
+
+        LocationRequest request = LocationRequest.createFromDeprecatedProvider(
+                provider, minTime, minDistance, false);
+        requestLocationUpdates(request, listener, null, null);
     }
 
     /**
-     * Registers the current activity to be notified periodically by
-     * the named provider.  Periodically, the supplied LocationListener will
-     * be called with the current Location or with status updates.
+     * Register for location updates using the named provider, and a callback on
+     * the specified looper thread.
      *
-     * <p> It may take a while to receive the first location update. If
-     * an immediate location is required, applications may use the
-     * {@link #getLastKnownLocation(String)} method.
-     *
-     * <p> In case the provider is disabled by the user, updates will stop,
-     * and the {@link LocationListener#onProviderDisabled(String)}
-     * method will be called. As soon as the provider is enabled again,
-     * the {@link LocationListener#onProviderEnabled(String)} method will
-     * be called and location updates will start again.
-     *
-     * <p> The update interval can be controlled using the minTime parameter.
-     * The elapsed time between location updates will never be less than
-     * minTime, although it can be more depending on the Location Provider
-     * implementation and the update interval requested by other applications.
-     *
-     * <p> Choosing a sensible value for minTime is important to conserve
-     * battery life. Each location update requires power from
-     * GPS, WIFI, Cell and other radios. Select a minTime value as high as
-     * possible while still providing a reasonable user experience.
-     * If your application is not in the foreground and showing
-     * location to the user then your application should avoid using an active
-     * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}),
-     * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes)
-     * or greater. If your application is in the foreground and showing
-     * location to the user then it is appropriate to select a faster
-     * update interval.
-     *
-     * <p> The minDistance parameter can also be used to control the
-     * frequency of location updates. If it is greater than 0 then the
-     * location provider will only send your application an update when
-     * the location has changed by at least minDistance meters, AND
-     * at least minTime milliseconds have passed. However it is more
-     * difficult for location providers to save power using the minDistance
-     * parameter, so minTime should be the primary tool to conserving battery
-     * life.
-     *
-     * <p> If your application wants to passively observe location
-     * updates triggered by other applications, but not consume
-     * any additional power otherwise, then use the {@link #PASSIVE_PROVIDER}
-     * This provider does not actively turn on or modify active location
-     * providers, so you do not need to be as careful about minTime and
-     * minDistance. However if your application performs heavy work
-     * on a location update (such as network activity) then you should
-     * select non-zero values for minTime and/or minDistance to rate-limit
-     * your update frequency in the case another application enables a
-     * location provider with extremely fast updates.
-     *
-     * <p> The supplied Looper is used to implement the callback mechanism.
-     *
-     * <p class="note"> Prior to Jellybean, the minTime parameter was
-     * only a hint, and some location provider implementations ignored it.
-     * From Jellybean and onwards it is mandatory for Android compatible
-     * devices to observe both the minTime and minDistance parameters.
+     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
+     * for more detail on how to use this method.
      *
      * @param provider the name of the provider with which to register
      * @param minTime minimum time interval between location updates, in milliseconds
      * @param minDistance minimum distance between location updates, in meters
-     * @param listener a {#link LocationListener} whose
+     * @param listener a {@link LocationListener} whose
      * {@link LocationListener#onLocationChanged} method will be called for
      * each location update
      * @param looper a Looper object whose message queue will be used to
-     * implement the callback mechanism, or null to make callbacks on the
-     * main thread
+     * implement the callback mechanism, or null to make callbacks on the calling
+     * thread
      *
      * @throws IllegalArgumentException if provider is null or doesn't exist
      * @throws IllegalArgumentException if listener is null
-     * @throws SecurityException if no suitable permission is present for the provider.
+     * @throws SecurityException if no suitable permission is present
      */
-    public void requestLocationUpdates(String provider,
-        long minTime, float minDistance, LocationListener listener,
-        Looper looper) {
-        if (provider == null) {
-            throw new IllegalArgumentException("provider==null");
-        }
-        if (listener == null) {
-            throw new IllegalArgumentException("listener==null");
-        }
-        _requestLocationUpdates(provider, null, minTime, minDistance, false, listener, looper);
+    public void requestLocationUpdates(String provider, long minTime, float minDistance,
+            LocationListener listener, Looper looper) {
+        checkProvider(provider);
+        checkListener(listener);
+
+        LocationRequest request = LocationRequest.createFromDeprecatedProvider(
+                provider, minTime, minDistance, false);
+        requestLocationUpdates(request, listener, looper, null);
     }
 
     /**
-     * Registers the current activity to be notified periodically based on
-     * the supplied criteria.  Periodically, the supplied LocationListener will
-     * be called with the current Location or with status updates.
+     * Register for location updates using a Criteria, and a callback
+     * on the specified looper thread.
      *
-     * <p> It may take a while to receive the first location update. If
-     * an immediate location is required, applications may use the
-     * {@link #getLastKnownLocation(String)} method.
-     *
-     * <p> In case the provider is disabled by the user, updates will stop,
-     * and the {@link LocationListener#onProviderDisabled(String)}
-     * method will be called. As soon as the provider is enabled again,
-     * the {@link LocationListener#onProviderEnabled(String)} method will
-     * be called and location updates will start again.
-     *
-     * <p> The update interval can be controlled using the minTime parameter.
-     * The elapsed time between location updates will never be less than
-     * minTime, although it can be more depending on the Location Provider
-     * implementation and the update interval requested by other applications.
-     *
-     * <p> Choosing a sensible value for minTime is important to conserve
-     * battery life. Each location update requires power from
-     * GPS, WIFI, Cell and other radios. Select a minTime value as high as
-     * possible while still providing a reasonable user experience.
-     * If your application is not in the foreground and showing
-     * location to the user then your application should avoid using an active
-     * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}),
-     * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes)
-     * or greater. If your application is in the foreground and showing
-     * location to the user then it is appropriate to select a faster
-     * update interval.
-     *
-     * <p> The minDistance parameter can also be used to control the
-     * frequency of location updates. If it is greater than 0 then the
-     * location provider will only send your application an update when
-     * the location has changed by at least minDistance meters, AND
-     * at least minTime milliseconds have passed. However it is more
-     * difficult for location providers to save power using the minDistance
-     * parameter, so minTime should be the primary tool to conserving battery
-     * life.
-     *
-     * <p> The supplied Looper is used to implement the callback mechanism.
-     *
-     * <p class="note"> Prior to Jellybean, the minTime parameter was
-     * only a hint, and some location provider implementations ignored it.
-     * From Jellybean and onwards it is mandatory for Android compatible
-     * devices to observe both the minTime and minDistance parameters.
+     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
+     * for more detail on how to use this method.
      *
      * @param minTime minimum time interval between location updates, in milliseconds
      * @param minDistance minimum distance between location updates, in meters
      * @param criteria contains parameters for the location manager to choose the
      * appropriate provider and parameters to compute the location
-     * @param listener a {#link LocationListener} whose
+     * @param listener a {@link LocationListener} whose
      * {@link LocationListener#onLocationChanged} method will be called for
      * each location update
      * @param looper a Looper object whose message queue will be used to
-     * implement the callback mechanism, or null to make callbacks on the
-     * main thread.
+     * implement the callback mechanism, or null to make callbacks on the calling
+     * thread
      *
      * @throws IllegalArgumentException if criteria is null
      * @throws IllegalArgumentException if listener is null
-     * @throws SecurityException if no suitable permission is present for the provider.
+     * @throws SecurityException if no suitable permission is present
      */
-    public void requestLocationUpdates(long minTime, float minDistance,
-            Criteria criteria, LocationListener listener, Looper looper) {
-        if (criteria == null) {
-            throw new IllegalArgumentException("criteria==null");
-        }
-        if (listener == null) {
-            throw new IllegalArgumentException("listener==null");
-        }
-        _requestLocationUpdates(null, criteria, minTime, minDistance, false, listener, looper);
-    }
+    public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria,
+            LocationListener listener, Looper looper) {
+        checkCriteria(criteria);
+        checkListener(listener);
 
-    private void _requestLocationUpdates(String provider, Criteria criteria, long minTime,
-            float minDistance, boolean singleShot, LocationListener listener, Looper looper) {
-        if (minTime < 0L) {
-            minTime = 0L;
-        }
-        if (minDistance < 0.0f) {
-            minDistance = 0.0f;
-        }
-
-        try {
-            synchronized (mListeners) {
-                ListenerTransport transport = mListeners.get(listener);
-                if (transport == null) {
-                    transport = new ListenerTransport(listener, looper);
-                }
-                mListeners.put(listener, transport);
-                mService.requestLocationUpdates(provider, criteria, minTime, minDistance,
-                        singleShot, transport, mContext.getPackageName());
-            }
-        } catch (RemoteException ex) {
-            Log.e(TAG, "requestLocationUpdates: DeadObjectException", ex);
-        }
+        LocationRequest request = LocationRequest.createFromDeprecatedCriteria(
+                criteria, minTime, minDistance, false);
+        requestLocationUpdates(request, listener, looper, null);
     }
 
     /**
-     * Registers the current activity to be notified periodically by
-     * the named provider.  Periodically, the supplied PendingIntent will
-     * be broadcast with the current Location or with status updates.
+     * Register for location updates using the named provider, and a
+     * pending intent.
      *
-     * <p> Location updates are sent with a key of
-     * {@link #KEY_LOCATION_CHANGED} and a {@link android.location.Location} value.
-     *
-     * <p> It may take a while to receive the first location update. If
-     * an immediate location is required, applications may use the
-     * {@link #getLastKnownLocation(String)} method.
-     *
-     * <p> The update interval can be controlled using the minTime parameter.
-     * The elapsed time between location updates will never be less than
-     * minTime, although it can be more depending on the Location Provider
-     * implementation and the update interval requested by other applications.
-     *
-     * <p> Choosing a sensible value for minTime is important to conserve
-     * battery life. Each location update requires power from
-     * GPS, WIFI, Cell and other radios. Select a minTime value as high as
-     * possible while still providing a reasonable user experience.
-     * If your application is not in the foreground and showing
-     * location to the user then your application should avoid using an active
-     * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}),
-     * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes)
-     * or greater. If your application is in the foreground and showing
-     * location to the user then it is appropriate to select a faster
-     * update interval.
-     *
-     * <p> The minDistance parameter can also be used to control the
-     * frequency of location updates. If it is greater than 0 then the
-     * location provider will only send your application an update when
-     * the location has changed by at least minDistance meters, AND
-     * at least minTime milliseconds have passed. However it is more
-     * difficult for location providers to save power using the minDistance
-     * parameter, so minTime should be the primary tool to conserving battery
-     * life.
-     *
-     * <p> If your application wants to passively observe location
-     * updates triggered by other applications, but not consume
-     * any additional power otherwise, then use the {@link #PASSIVE_PROVIDER}
-     * This provider does not actively turn on or modify active location
-     * providers, so you do not need to be as careful about minTime and
-     * minDistance. However if your application performs heavy work
-     * on a location update (such as network activity) then you should
-     * select non-zero values for minTime and/or minDistance to rate-limit
-     * your update frequency in the case another application enables a
-     * location provider with extremely fast updates.
-     *
-     * <p> If the provider is disabled by the user, updates will stop,
-     * and an intent will be sent with an extra with key
-     * {@link #KEY_PROVIDER_ENABLED} and a boolean value of false.
-     * If the provider is re-enabled, an intent will be sent with an
-     * extra with key {@link #KEY_PROVIDER_ENABLED} and a boolean value of
-     * true and location updates will start again.
-     *
-     * <p> If the provider's status changes, an intent will be sent with
-     * an extra with key {@link #KEY_STATUS_CHANGED} and an integer value
-     * indicating the new status.  Any extras associated with the status
-     * update will be sent as well.
-     *
-     * <p class="note"> Prior to Jellybean, the minTime parameter was
-     * only a hint, and some location provider implementations ignored it.
-     * From Jellybean and onwards it is mandatory for Android compatible
-     * devices to observe both the minTime and minDistance parameters.
+     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
+     * for more detail on how to use this method.
      *
      * @param provider the name of the provider with which to register
      * @param minTime minimum time interval between location updates, in milliseconds
      * @param minDistance minimum distance between location updates, in meters
-     * @param intent a {#link PendingIntent} to be sent for each location update
+     * @param intent a {@link PendingIntent} to be sent for each location update
      *
      * @throws IllegalArgumentException if provider is null or doesn't exist
      * on this device
      * @throws IllegalArgumentException if intent is null
-     * @throws SecurityException if no suitable permission is present for the provider.
+     * @throws SecurityException if no suitable permission is present
      */
-    public void requestLocationUpdates(String provider,
-            long minTime, float minDistance, PendingIntent intent) {
-        if (provider == null) {
-            throw new IllegalArgumentException("provider==null");
-        }
-        if (intent == null) {
-            throw new IllegalArgumentException("intent==null");
-        }
-        _requestLocationUpdates(provider, null, minTime, minDistance, false, intent);
+    public void requestLocationUpdates(String provider, long minTime, float minDistance,
+            PendingIntent intent) {
+        checkProvider(provider);
+        checkPendingIntent(intent);
+
+        LocationRequest request = LocationRequest.createFromDeprecatedProvider(
+                provider, minTime, minDistance, false);
+        requestLocationUpdates(request, null, null, intent);
     }
 
     /**
-     * Registers the current activity to be notified periodically based on
-     * the supplied criteria.  Periodically, the supplied PendingIntent will
-     * be broadcast with the current Location or with status updates.
+     * Register for location updates using a Criteria and pending intent.
      *
-     * <p> Location updates are sent with a key of
-     * {@link #KEY_LOCATION_CHANGED} and a {@link android.location.Location} value.
+     * <p>The <code>requestLocationUpdates()</code> and
+     * <code>requestSingleUpdate()</code> register the current activity to be
+     * updated periodically by the named provider, or by the provider matching
+     * the specified {@link Criteria}, with location and status updates.
      *
      * <p> It may take a while to receive the first location update. If
      * an immediate location is required, applications may use the
      * {@link #getLastKnownLocation(String)} method.
      *
-     * <p> The update interval can be controlled using the minTime parameter.
+     * <p> Location updates are received either by {@link LocationListener}
+     * callbacks, or by broadcast intents to a supplied {@link PendingIntent}.
+     *
+     * <p> If the caller supplied a pending intent, then location updates
+     * are sent with a key of {@link #KEY_LOCATION_CHANGED} and a
+     * {@link android.location.Location} value.
+     *
+     * <p> The location update interval can be controlled using the minTime parameter.
      * The elapsed time between location updates will never be less than
      * minTime, although it can be more depending on the Location Provider
      * implementation and the update interval requested by other applications.
@@ -794,17 +565,36 @@
      * parameter, so minTime should be the primary tool to conserving battery
      * life.
      *
-     * <p> If the provider is disabled by the user, updates will stop,
-     * and an intent will be sent with an extra with key
-     * {@link #KEY_PROVIDER_ENABLED} and a boolean value of false.
-     * If the provider is re-enabled, an intent will be sent with an
-     * extra with key {@link #KEY_PROVIDER_ENABLED} and a boolean value of
-     * true and location updates will start again.
+     * <p> If your application wants to passively observe location
+     * updates triggered by other applications, but not consume
+     * any additional power otherwise, then use the {@link #PASSIVE_PROVIDER}
+     * This provider does not actively turn on or modify active location
+     * providers, so you do not need to be as careful about minTime and
+     * minDistance. However if your application performs heavy work
+     * on a location update (such as network activity) then you should
+     * select non-zero values for minTime and/or minDistance to rate-limit
+     * your update frequency in the case another application enables a
+     * location provider with extremely fast updates.
      *
-     * <p> If the provider's status changes, an intent will be sent with
-     * an extra with key {@link #KEY_STATUS_CHANGED} and an integer value
-     * indicating the new status.  Any extras associated with the status
-     * update will be sent as well.
+     * <p>In case the provider is disabled by the user, updates will stop,
+     * and a provider availability update will be sent.
+     * As soon as the provider is enabled again,
+     * location updates will immediately resume and a provider availability
+     * update sent. Providers can also send status updates, at any time,
+     * with extra's specific to the provider. If a callback was supplied
+     * then status and availability updates are via
+     * {@link LocationListener#onProviderDisabled},
+     * {@link LocationListener#onProviderEnabled} or
+     * {@link LocationListener#onStatusChanged}. Alternately, if a
+     * pending intent was supplied then status and availability updates
+     * are broadcast intents with extra keys of
+     * {@link #KEY_PROVIDER_ENABLED} or {@link #KEY_STATUS_CHANGED}.
+     *
+     * <p> If a {@link LocationListener} is used but with no Looper specified
+     * then the calling thread must already
+     * be a {@link android.os.Looper} thread such as the main thread of the
+     * calling Activity. If a Looper is specified with a {@link LocationListener}
+     * then callbacks are made on the supplied Looper thread.
      *
      * <p class="note"> Prior to Jellybean, the minTime parameter was
      * only a hint, and some location provider implementations ignored it.
@@ -815,234 +605,290 @@
      * @param minDistance minimum distance between location updates, in meters
      * @param criteria contains parameters for the location manager to choose the
      * appropriate provider and parameters to compute the location
-     * @param intent a {#link PendingIntent} to be sent for each location update
+     * @param intent a {@link PendingIntent} to be sent for each location update
      *
      * @throws IllegalArgumentException if criteria is null
      * @throws IllegalArgumentException if intent is null
-     * @throws SecurityException if no suitable permission is present for the provider.
+     * @throws SecurityException if no suitable permission is present
      */
     public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria,
             PendingIntent intent) {
-        if (criteria == null) {
-            throw new IllegalArgumentException("criteria==null");
-        }
-        if (intent == null) {
-            throw new IllegalArgumentException("intent==null");
-        }
-        _requestLocationUpdates(null, criteria, minTime, minDistance, false, intent);
-    }
+        checkCriteria(criteria);
+        checkPendingIntent(intent);
 
-    private void _requestLocationUpdates(String provider, Criteria criteria,
-            long minTime, float minDistance, boolean singleShot, PendingIntent intent) {
-        if (minTime < 0L) {
-            minTime = 0L;
-        }
-        if (minDistance < 0.0f) {
-            minDistance = 0.0f;
-        }
-
-        try {
-            mService.requestLocationUpdatesPI(provider, criteria, minTime, minDistance, singleShot,
-                    intent, mContext.getPackageName());
-        } catch (RemoteException ex) {
-            Log.e(TAG, "requestLocationUpdates: RemoteException", ex);
-        }
+        LocationRequest request = LocationRequest.createFromDeprecatedCriteria(
+                criteria, minTime, minDistance, false);
+        requestLocationUpdates(request, null, null, intent);
     }
 
     /**
-     * Requests a single location update from the named provider.
+     * Register for a single location update using the named provider and
+     * a callback.
      *
-     * <p> It may take a while to receive the most recent location. If
-     * an immediate location is required, applications may use the
-     * {@link #getLastKnownLocation(String)} method.
-     *
-     * <p> In case the provider is disabled by the user, the update will not be received,
-     * and the {@link LocationListener#onProviderDisabled(String)}
-     * method will be called. As soon as the provider is enabled again,
-     * the {@link LocationListener#onProviderEnabled(String)} method will
-     * be called and location updates will start again.
-     *
-     * <p> The supplied Looper is used to implement the callback mechanism.
+     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
+     * for more detail on how to use this method.
      *
      * @param provider the name of the provider with which to register
-     * @param listener a {#link LocationListener} whose
+     * @param listener a {@link LocationListener} whose
      * {@link LocationListener#onLocationChanged} method will be called when
      * the location update is available
      * @param looper a Looper object whose message queue will be used to
-     * implement the callback mechanism, or null to make callbacks on the
-     * main thread
+     * implement the callback mechanism, or null to make callbacks on the calling
+     * thread
      *
      * @throws IllegalArgumentException if provider is null or doesn't exist
      * @throws IllegalArgumentException if listener is null
-     * @throws SecurityException if no suitable permission is present for the provider
+     * @throws SecurityException if no suitable permission is present
      */
     public void requestSingleUpdate(String provider, LocationListener listener, Looper looper) {
-        if (provider == null) {
-            throw new IllegalArgumentException("provider==null");
-        }
-        if (listener == null) {
-            throw new IllegalArgumentException("listener==null");
-        }
-        _requestLocationUpdates(provider, null, 0L, 0.0f, true, listener, looper);
+        checkProvider(provider);
+        checkListener(listener);
+
+        LocationRequest request = LocationRequest.createFromDeprecatedProvider(
+                provider, 0, 0, true);
+        requestLocationUpdates(request, listener, looper, null);
     }
 
     /**
-     * Requests a single location update based on the specified criteria.
+     * Register for a single location update using a Criteria and
+     * a callback.
      *
-     * <p> It may take a while to receive the most recent location. If
-     * an immediate location is required, applications may use the
-     * {@link #getLastKnownLocation(String)} method.
-     *
-     * <p> In case the provider is disabled by the user, the update will not be received,
-     * and the {@link LocationListener#onProviderDisabled(String)}
-     * method will be called. As soon as the provider is enabled again,
-     * the {@link LocationListener#onProviderEnabled(String)} method will
-     * be called and location updates will start again.
-     *
-     * <p> The supplied Looper is used to implement the callback mechanism.
+     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
+     * for more detail on how to use this method.
      *
      * @param criteria contains parameters for the location manager to choose the
      * appropriate provider and parameters to compute the location
-     * @param listener a {#link LocationListener} whose
+     * @param listener a {@link LocationListener} whose
      * {@link LocationListener#onLocationChanged} method will be called when
      * the location update is available
      * @param looper a Looper object whose message queue will be used to
-     * implement the callback mechanism, or null to make callbacks on the
-     * main thread
+     * implement the callback mechanism, or null to make callbacks on the calling
+     * thread
      *
      * @throws IllegalArgumentException if criteria is null
      * @throws IllegalArgumentException if listener is null
-     * @throws SecurityException if no suitable permission is present to access
-     * the location services
+     * @throws SecurityException if no suitable permission is present
      */
     public void requestSingleUpdate(Criteria criteria, LocationListener listener, Looper looper) {
-        if (criteria == null) {
-            throw new IllegalArgumentException("criteria==null");
-        }
-        if (listener == null) {
-            throw new IllegalArgumentException("listener==null");
-        }
-        _requestLocationUpdates(null, criteria, 0L, 0.0f, true, listener, looper);
+        checkCriteria(criteria);
+        checkListener(listener);
+
+        LocationRequest request = LocationRequest.createFromDeprecatedCriteria(
+                criteria, 0, 0, true);
+        requestLocationUpdates(request, listener, looper, null);
     }
 
     /**
-     * Requests a single location update from the named provider.
+     * Register for a single location update using a named provider and pending intent.
      *
-     * <p> It may take a while to receive the most recent location. If
-     * an immediate location is required, applications may use the
-     * {@link #getLastKnownLocation(String)} method.
-     *
-     * <p> Location updates are sent with a key of
-     * {@link #KEY_LOCATION_CHANGED} and a {@link android.location.Location} value.
-     *
-     * <p> In case the provider is disabled by the user, the update will not be received,
-     * and the {@link LocationListener#onProviderDisabled(String)}
-     * method will be called. As soon as the provider is enabled again,
-     * the {@link LocationListener#onProviderEnabled(String)} method will
-     * be called and location updates will start again.
+     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
+     * for more detail on how to use this method.
      *
      * @param provider the name of the provider with which to register
-     * @param intent a {#link PendingIntent} to be sent for the location update
+     * @param intent a {@link PendingIntent} to be sent for the location update
      *
      * @throws IllegalArgumentException if provider is null or doesn't exist
      * @throws IllegalArgumentException if intent is null
-     * @throws SecurityException if no suitable permission is present for the provider
+     * @throws SecurityException if no suitable permission is present
      */
     public void requestSingleUpdate(String provider, PendingIntent intent) {
-        if (provider == null) {
-            throw new IllegalArgumentException("provider==null");
-        }
-        if (intent == null) {
-            throw new IllegalArgumentException("intent==null");
-        }
-        _requestLocationUpdates(provider, null, 0L, 0.0f, true, intent);
+        checkProvider(provider);
+        checkPendingIntent(intent);
+
+        LocationRequest request = LocationRequest.createFromDeprecatedProvider(
+                provider, 0, 0, true);
+        requestLocationUpdates(request, null, null, intent);
     }
 
     /**
-     * Requests a single location update based on the specified criteria.
+     * Register for a single location update using a Criteria and pending intent.
      *
-     * <p> It may take a while to receive the most recent location. If
-     * an immediate location is required, applications may use the
-     * {@link #getLastKnownLocation(String)} method.
-     *
-     * <p> Location updates are sent with a key of
-     * {@link #KEY_LOCATION_CHANGED} and a {@link android.location.Location} value.
-     *
-     * <p> If the provider is disabled by the user, an update will not be
-     * received, and an intent will be sent with an extra with key
-     * {@link #KEY_PROVIDER_ENABLED} and a boolean value of false.
-     * If the provider is re-enabled, an intent will be sent with an
-     * extra with key {@link #KEY_PROVIDER_ENABLED} and a boolean value of
-     * true and the location update will occur.
+     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
+     * for more detail on how to use this method.
      *
      * @param criteria contains parameters for the location manager to choose the
      * appropriate provider and parameters to compute the location
-     * @param intent a {#link PendingIntent} to be sent for the location update
+     * @param intent a {@link PendingIntent} to be sent for the location update
      *
      * @throws IllegalArgumentException if provider is null or doesn't exist
      * @throws IllegalArgumentException if intent is null
-     * @throws SecurityException if no suitable permission is present for the provider
+     * @throws SecurityException if no suitable permission is present
      */
     public void requestSingleUpdate(Criteria criteria, PendingIntent intent) {
-        if (criteria == null) {
-            throw new IllegalArgumentException("criteria==null");
-        }
-        if (intent == null) {
-            throw new IllegalArgumentException("intent==null");
-        }
-        _requestLocationUpdates(null, criteria, 0L, 0.0f, true, intent);
+        checkCriteria(criteria);
+        checkPendingIntent(intent);
+
+        LocationRequest request = LocationRequest.createFromDeprecatedCriteria(
+                criteria, 0, 0, true);
+        requestLocationUpdates(request, null, null, intent);
     }
 
     /**
-     * Removes any current registration for location updates of the current activity
-     * with the given LocationListener.  Following this call, updates will no longer
+     * Register for fused location updates using a LocationRequest and callback.
+     *
+     * <p>Upon a location update, the system delivers the new {@link Location} to the
+     * provided {@link LocationListener}, by calling its {@link
+     * LocationListener#onLocationChanged} method.</p>
+     *
+     * <p>The system will automatically select and enable the best providers
+     * to compute a location for your application. It may use only passive
+     * locations, or just a single location source, or it may fuse together
+     * multiple location sources in order to produce the best possible
+     * result, depending on the quality of service requested in the
+     * {@link LocationRequest}.
+     *
+     * <p>LocationRequest can be null, in which case the system will choose
+     * default, low power parameters for location updates. You will occasionally
+     * receive location updates as available, without a major power impact on the
+     * system. If your application just needs an occasional location update
+     * without any strict demands, then pass a null LocationRequest.
+     *
+     * <p>Only one LocationRequest can be registered for each unique callback
+     * or pending intent. So a subsequent request with the same callback or
+     * pending intent will over-write the previous LocationRequest.
+     *
+     * <p> If a pending intent is supplied then location updates
+     * are sent with a key of {@link #KEY_LOCATION_CHANGED} and a
+     * {@link android.location.Location} value. If a callback is supplied
+     * then location updates are made using the
+     * {@link LocationListener#onLocationChanged} callback, on the specified
+     * Looper thread. If a {@link LocationListener} is used
+     * but with a null Looper then the calling thread must already
+     * be a {@link android.os.Looper} thread (such as the main thread) and
+     * callbacks will occur on this thread.
+     *
+     * <p> Provider status updates and availability updates are deprecated
+     * because the system is performing provider fusion on the applications
+     * behalf. So {@link LocationListener#onProviderDisabled},
+     * {@link LocationListener#onProviderEnabled}, {@link LocationListener#onStatusChanged}
+     * will not be called, and intents with extra keys of
+     * {@link #KEY_PROVIDER_ENABLED} or {@link #KEY_STATUS_CHANGED} will not
+     * be received.
+     *
+     * <p> To unregister for Location updates, use: {@link #removeUpdates(LocationListener)}.
+     *
+     * @param request quality of service required, null for default low power
+     * @param listener a {@link LocationListener} whose
+     * {@link LocationListener#onLocationChanged} method will be called when
+     * the location update is available
+     * @param looper a Looper object whose message queue will be used to
+     * implement the callback mechanism, or null to make callbacks on the calling
+     * thread
+     *
+     * @throws IllegalArgumentException if listener is null
+     * @throws SecurityException if no suitable permission is present
+     *
+     * @hide
+     */
+    public void requestLocationUpdates(LocationRequest request, LocationListener listener,
+            Looper looper) {
+        checkListener(listener);
+        requestLocationUpdates(request, listener, looper, null);
+    }
+
+
+    /**
+     * Register for fused location updates using a LocationRequest and a pending intent.
+     *
+     * <p>Upon a location update, the system delivers the new {@link Location} with your provided
+     * {@link PendingIntent}, as the value for {@link LocationManager#KEY_LOCATION_CHANGED}
+     * in the intent's extras.</p>
+     *
+     * <p> To unregister for Location updates, use: {@link #removeUpdates(PendingIntent)}.
+     *
+     * <p> See {@link #requestLocationUpdates(LocationRequest, LocationListener, Looper)}
+     * for more detail.
+     *
+     * @param request quality of service required, null for default low power
+     * @param intent a {@link PendingIntent} to be sent for the location update
+     *
+     * @throws IllegalArgumentException if intent is null
+     * @throws SecurityException if no suitable permission is present
+     *
+     * @hide
+     */
+    public void requestLocationUpdates(LocationRequest request, PendingIntent intent) {
+        checkPendingIntent(intent);
+        requestLocationUpdates(request, null, null, intent);
+    }
+
+    private ListenerTransport wrapListener(LocationListener listener, Looper looper) {
+        if (listener == null) return null;
+        synchronized (mListeners) {
+            ListenerTransport transport = mListeners.get(listener);
+            if (transport == null) {
+                transport = new ListenerTransport(listener, looper);
+            }
+            mListeners.put(listener, transport);
+            return transport;
+        }
+    }
+
+    private void requestLocationUpdates(LocationRequest request, LocationListener listener,
+            Looper looper, PendingIntent intent) {
+
+        String packageName = mContext.getPackageName();
+
+        // wrap the listener class
+        ListenerTransport transport = wrapListener(listener, looper);
+
+        try {
+            mService.requestLocationUpdates(request, transport, intent, packageName);
+       } catch (RemoteException e) {
+           Log.e(TAG, "RemoteException", e);
+       }
+    }
+
+    /**
+     * Removes all location updates for the specified LocationListener.
+     *
+     * <p>Following this call, updates will no longer
      * occur for this listener.
      *
-     * @param listener {#link LocationListener} object that no longer needs location updates
+     * @param listener listener object that no longer needs location updates
      * @throws IllegalArgumentException if listener is null
      */
     public void removeUpdates(LocationListener listener) {
-        if (listener == null) {
-            throw new IllegalArgumentException("listener==null");
+        checkListener(listener);
+        String packageName = mContext.getPackageName();
+
+        ListenerTransport transport;
+        synchronized (mListeners) {
+            transport = mListeners.remove(listener);
         }
-        if (false) {
-            Log.d(TAG, "removeUpdates: listener = " + listener);
-        }
+        if (transport == null) return;
+
         try {
-            ListenerTransport transport = mListeners.remove(listener);
-            if (transport != null) {
-                mService.removeUpdates(transport, mContext.getPackageName());
-            }
-        } catch (RemoteException ex) {
-            Log.e(TAG, "removeUpdates: DeadObjectException", ex);
+            mService.removeUpdates(transport, null, packageName);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
     }
 
     /**
-     * Removes any current registration for location updates of the current activity
-     * with the given PendingIntent.  Following this call, updates will no longer
-     * occur for this intent.
+     * Removes all location updates for the specified pending intent.
      *
-     * @param intent {#link PendingIntent} object that no longer needs location updates
+     * <p>Following this call, updates will no longer for this pending intent.
+     *
+     * @param intent pending intent object that no longer needs location updates
      * @throws IllegalArgumentException if intent is null
      */
     public void removeUpdates(PendingIntent intent) {
-        if (intent == null) {
-            throw new IllegalArgumentException("intent==null");
-        }
-        if (false) {
-            Log.d(TAG, "removeUpdates: intent = " + intent);
-        }
+        checkPendingIntent(intent);
+        String packageName = mContext.getPackageName();
+
         try {
-            mService.removeUpdatesPI(intent, mContext.getPackageName());
-        } catch (RemoteException ex) {
-            Log.e(TAG, "removeUpdates: RemoteException", ex);
+            mService.removeUpdates(null, intent, packageName);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
     }
 
     /**
-     * Sets a proximity alert for the location given by the position
-     * (latitude, longitude) and the given radius.  When the device
+     * Set a proximity alert for the location given by the position
+     * (latitude, longitude) and the given radius.
+     *
+     * <p> When the device
      * detects that it has entered or exited the area surrounding the
      * location, the given PendingIntent will be used to create an Intent
      * to be fired.
@@ -1062,13 +908,15 @@
      * alert and no longer monitor it.  A value of -1 indicates that
      * there should be no expiration time.
      *
-     * <p> In case the screen goes to sleep, checks for proximity alerts
-     * happen only once every 4 minutes. This conserves battery life by
-     * ensuring that the device isn't perpetually awake.
-     *
      * <p> Internally, this method uses both {@link #NETWORK_PROVIDER}
      * and {@link #GPS_PROVIDER}.
      *
+     * <p>Before API version 17, this method could be used with
+     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
+     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
+     * From API version 17 and onwards, this method requires
+     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission.
+     *
      * @param latitude the latitude of the central point of the
      * alert region
      * @param longitude the longitude of the central point of the
@@ -1080,68 +928,200 @@
      * @param intent a PendingIntent that will be used to generate an Intent to
      * fire when entry to or exit from the alert region is detected
      *
-     * @throws SecurityException if no permission exists for the required
-     * providers.
+     * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
+     * permission is not present
      */
-    public void addProximityAlert(double latitude, double longitude,
-        float radius, long expiration, PendingIntent intent) {
-        if (false) {
-            Log.d(TAG, "addProximityAlert: latitude = " + latitude +
-                ", longitude = " + longitude + ", radius = " + radius +
-                ", expiration = " + expiration +
-                ", intent = " + intent);
-        }
+    public void addProximityAlert(double latitude, double longitude, float radius, long expiration,
+            PendingIntent intent) {
+        checkPendingIntent(intent);
+        if (expiration < 0) expiration = Long.MAX_VALUE;
+
+        Geofence fence = Geofence.createCircle(latitude, longitude, radius);
+        LocationRequest request = new LocationRequest().setExpireIn(expiration);
         try {
-            mService.addProximityAlert(latitude, longitude, radius,
-                                       expiration, intent, mContext.getPackageName());
-        } catch (RemoteException ex) {
-            Log.e(TAG, "addProximityAlert: RemoteException", ex);
+            mService.requestGeofence(request, fence, intent, mContext.getPackageName());
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
+        }
+    }
+
+    /**
+     * Add a geofence with the specified LocationRequest quality of service.
+     *
+     * <p> When the device
+     * detects that it has entered or exited the area surrounding the
+     * location, the given PendingIntent will be used to create an Intent
+     * to be fired.
+     *
+     * <p> The fired Intent will have a boolean extra added with key
+     * {@link #KEY_PROXIMITY_ENTERING}. If the value is true, the device is
+     * entering the proximity region; if false, it is exiting.
+     *
+     * <p> The geofence engine fuses results from all location providers to
+     * provide the best balance between accuracy and power. Applications
+     * can choose the quality of service required using the
+     * {@link LocationRequest} object. If it is null then a default,
+     * low power geo-fencing implementation is used. It is possible to cross
+     * a geo-fence without notification, but the system will do its best
+     * to detect, using {@link LocationRequest} as a hint to trade-off
+     * accuracy and power.
+     *
+     * <p> The power required by the geofence engine can depend on many factors,
+     * such as quality and interval requested in {@link LocationRequest},
+     * distance to nearest geofence and current device velocity.
+     *
+     * @param request quality of service required, null for default low power
+     * @param fence a geographical description of the geofence area
+     * @param intent pending intent to receive geofence updates
+     *
+     * @throws IllegalArgumentException if fence is null
+     * @throws IllegalArgumentException if intent is null
+     * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
+     * permission is not present
+     *
+     * @hide
+     */
+    public void addGeofence(LocationRequest request, Geofence fence, PendingIntent intent) {
+        checkPendingIntent(intent);
+        checkGeofence(fence);
+
+        try {
+            mService.requestGeofence(request, fence, intent, mContext.getPackageName());
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
     }
 
     /**
      * Removes the proximity alert with the given PendingIntent.
      *
+     * <p>Before API version 17, this method could be used with
+     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
+     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
+     * From API version 17 and onwards, this method requires
+     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission.
+     *
      * @param intent the PendingIntent that no longer needs to be notified of
      * proximity alerts
+     *
+     * @throws IllegalArgumentException if intent is null
+     * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
+     * permission is not present
      */
     public void removeProximityAlert(PendingIntent intent) {
-        if (false) {
-            Log.d(TAG, "removeProximityAlert: intent = " + intent);
-        }
+        checkPendingIntent(intent);
+        String packageName = mContext.getPackageName();
+
         try {
-            mService.removeProximityAlert(intent);
-        } catch (RemoteException ex) {
-            Log.e(TAG, "removeProximityAlert: RemoteException", ex);
+            mService.removeGeofence(null, intent, packageName);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
     }
 
     /**
-     * Returns the current enabled/disabled status of the given provider. If the
-     * user has enabled this provider in the Settings menu, true is returned
-     * otherwise false is returned
+     * Remove a single geofence.
+     *
+     * <p>This removes only the specified geofence associated with the
+     * specified pending intent. All other geofences remain unchanged.
+     *
+     * @param fence a geofence previously passed to {@link #addGeofence}
+     * @param intent a pending intent previously passed to {@link #addGeofence}
+     *
+     * @throws IllegalArgumentException if fence is null
+     * @throws IllegalArgumentException if intent is null
+     * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
+     * permission is not present
+     *
+     * @hide
+     */
+    public void removeGeofence(Geofence fence, PendingIntent intent) {
+        checkPendingIntent(intent);
+        checkGeofence(fence);
+        String packageName = mContext.getPackageName();
+
+        try {
+            mService.removeGeofence(fence, intent, packageName);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
+        }
+    }
+
+    /**
+     * Remove all geofences registered to the specified pending intent.
+     *
+     * @param intent a pending intent previously passed to {@link #addGeofence}
+     *
+     * @throws IllegalArgumentException if intent is null
+     * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
+     * permission is not present
+     *
+     * @hide
+     */
+    public void removeAllGeofences(PendingIntent intent) {
+        checkPendingIntent(intent);
+        String packageName = mContext.getPackageName();
+
+        try {
+            mService.removeGeofence(null, intent, packageName);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
+        }
+    }
+
+    /**
+     * Returns the current enabled/disabled status of the given provider.
+     *
+     * <p>If the user has enabled this provider in the Settings menu, true
+     * is returned otherwise false is returned
      *
      * @param provider the name of the provider
      * @return true if the provider is enabled
      *
-     * @throws SecurityException if no suitable permission is present for the provider.
      * @throws IllegalArgumentException if provider is null
+     * @throws SecurityException if no suitable permission is present
      */
     public boolean isProviderEnabled(String provider) {
-        if (provider == null) {
-            throw new IllegalArgumentException("provider==null");
-        }
+        checkProvider(provider);
+
         try {
             return mService.isProviderEnabled(provider);
-        } catch (RemoteException ex) {
-            Log.e(TAG, "isProviderEnabled: RemoteException", ex);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
             return false;
         }
     }
 
     /**
+     * Get the last known location.
+     *
+     * <p>This location could be very old so use
+     * {@link Location#getElapsedRealtimeNanos} to calculate its age. It can
+     * also return null if no previous location is available.
+     *
+     * <p>Always returns immediately.
+     *
+     * @return The last known location, or null if not available
+     * @throws SecurityException if no suitable permission is present
+     *
+     * @hide
+     */
+    public Location getLastLocation() {
+        String packageName = mContext.getPackageName();
+
+        try {
+            return mService.getLastLocation(null, packageName);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
+            return null;
+        }
+    }
+
+    /**
      * Returns a Location indicating the data from the last known
-     * location fix obtained from the given provider.  This can be done
+     * location fix obtained from the given provider.
+     *
+     * <p> This can be done
      * without starting the provider.  Note that this location could
      * be out-of-date, for example if the device was turned off and
      * moved to another location.
@@ -1151,36 +1131,31 @@
      * @param provider the name of the provider
      * @return the last known location for the provider, or null
      *
-     * @throws SecurityException if no suitable permission is present for the provider.
+     * @throws SecurityException if no suitable permission is present
      * @throws IllegalArgumentException if provider is null or doesn't exist
      */
     public Location getLastKnownLocation(String provider) {
-        if (provider == null) {
-            throw new IllegalArgumentException("provider==null");
-        }
+        checkProvider(provider);
+        String packageName = mContext.getPackageName();
+        LocationRequest request = LocationRequest.createFromDeprecatedProvider(
+                provider, 0, 0, true);
+
         try {
-            return mService.getLastKnownLocation(provider, mContext.getPackageName());
-        } catch (RemoteException ex) {
-            Log.e(TAG, "getLastKnowLocation: RemoteException", ex);
+            return mService.getLastLocation(request, packageName);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
             return null;
         }
     }
 
-    // Mock provider support
+    // --- Mock provider support ---
+    // TODO: It would be fantastic to deprecate mock providers entirely, and replace
+    // with something closer to LocationProviderBase.java
 
     /**
      * Creates a mock location provider and adds it to the set of active providers.
      *
      * @param name the provider name
-     * @param requiresNetwork
-     * @param requiresSatellite
-     * @param requiresCell
-     * @param hasMonetaryCost
-     * @param supportsAltitude
-     * @param supportsSpeed
-     * @param supportsBearing
-     * @param powerRequirement
-     * @param accuracy
      *
      * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present
      * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
@@ -1188,14 +1163,19 @@
      * @throws IllegalArgumentException if a provider with the given name already exists
      */
     public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite,
-        boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
-        boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
+            boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
+            boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
+        ProviderProperties properties = new ProviderProperties(requiresNetwork,
+                requiresSatellite, requiresCell, hasMonetaryCost, supportsAltitude, supportsSpeed,
+                supportsBearing, powerRequirement, accuracy);
+        if (name.matches(LocationProvider.BAD_CHARS_REGEX)) {
+            throw new IllegalArgumentException("provider name contains illegal character: " + name);
+        }
+
         try {
-            mService.addTestProvider(name, requiresNetwork, requiresSatellite, requiresCell,
-                hasMonetaryCost, supportsAltitude, supportsSpeed, supportsBearing, powerRequirement,
-                accuracy);
-        } catch (RemoteException ex) {
-            Log.e(TAG, "addTestProvider: RemoteException", ex);
+            mService.addTestProvider(name, properties);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
     }
 
@@ -1212,14 +1192,17 @@
     public void removeTestProvider(String provider) {
         try {
             mService.removeTestProvider(provider);
-        } catch (RemoteException ex) {
-            Log.e(TAG, "removeTestProvider: RemoteException", ex);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
     }
 
     /**
-     * Sets a mock location for the given provider.  This location will be used in place
-     * of any actual location from the provider.
+     * Sets a mock location for the given provider.
+     * <p>This location will be used in place of any actual location from the provider.
+     * The location object must have a minimum number of fields set to be
+     * considered a valid LocationProvider Location, as per documentation
+     * on {@link Location} class.
      *
      * @param provider the provider name
      * @param loc the mock location
@@ -1228,12 +1211,26 @@
      * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
      * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
      * @throws IllegalArgumentException if no provider with the given name exists
+     * @throws IllegalArgumentException if the location is incomplete
      */
     public void setTestProviderLocation(String provider, Location loc) {
+        if (!loc.isComplete()) {
+            IllegalArgumentException e = new IllegalArgumentException(
+                    "Incomplete location object, missing timestamp or accuracy? " + loc);
+            if (mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN) {
+                // just log on old platform (for backwards compatibility)
+                Log.w(TAG, e);
+                loc.makeComplete();
+            } else {
+                // really throw it!
+                throw e;
+            }
+        }
+
         try {
             mService.setTestProviderLocation(provider, loc);
-        } catch (RemoteException ex) {
-            Log.e(TAG, "setTestProviderLocation: RemoteException", ex);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
     }
 
@@ -1250,8 +1247,8 @@
     public void clearTestProviderLocation(String provider) {
         try {
             mService.clearTestProviderLocation(provider);
-        } catch (RemoteException ex) {
-            Log.e(TAG, "clearTestProviderLocation: RemoteException", ex);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
     }
 
@@ -1270,8 +1267,8 @@
     public void setTestProviderEnabled(String provider, boolean enabled) {
         try {
             mService.setTestProviderEnabled(provider, enabled);
-        } catch (RemoteException ex) {
-            Log.e(TAG, "setTestProviderEnabled: RemoteException", ex);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
     }
 
@@ -1288,10 +1285,9 @@
     public void clearTestProviderEnabled(String provider) {
         try {
             mService.clearTestProviderEnabled(provider);
-        } catch (RemoteException ex) {
-            Log.e(TAG, "clearTestProviderEnabled: RemoteException", ex);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
-
     }
 
     /**
@@ -1311,8 +1307,8 @@
     public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
         try {
             mService.setTestProviderStatus(provider, status, extras, updateTime);
-        } catch (RemoteException ex) {
-            Log.e(TAG, "setTestProviderStatus: RemoteException", ex);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
     }
 
@@ -1329,12 +1325,12 @@
     public void clearTestProviderStatus(String provider) {
         try {
             mService.clearTestProviderStatus(provider);
-        } catch (RemoteException ex) {
-            Log.e(TAG, "clearTestProviderStatus: RemoteException", ex);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
         }
     }
 
-    // GPS-specific support
+    // --- GPS-specific support ---
 
     // This class is used to send GPS status events to the client's main thread.
     private class GpsStatusListenerTransport extends IGpsStatusListener.Stub {
@@ -1367,6 +1363,7 @@
             mNmeaBuffer = new ArrayList<Nmea>();
         }
 
+        @Override
         public void onGpsStarted() {
             if (mListener != null) {
                 Message msg = Message.obtain();
@@ -1375,6 +1372,7 @@
             }
         }
 
+        @Override
         public void onGpsStopped() {
             if (mListener != null) {
                 Message msg = Message.obtain();
@@ -1383,6 +1381,7 @@
             }
         }
 
+        @Override
         public void onFirstFix(int ttff) {
             if (mListener != null) {
                 mGpsStatus.setTimeToFirstFix(ttff);
@@ -1392,6 +1391,7 @@
             }
         }
 
+        @Override
         public void onSvStatusChanged(int svCount, int[] prns, float[] snrs,
                 float[] elevations, float[] azimuths, int ephemerisMask,
                 int almanacMask, int usedInFixMask) {
@@ -1407,6 +1407,7 @@
             }
         }
 
+        @Override
         public void onNmeaReceived(long timestamp, String nmea) {
             if (mNmeaListener != null) {
                 synchronized (mNmeaBuffer) {
@@ -1491,7 +1492,7 @@
     /**
      * Adds an NMEA listener.
      *
-     * @param listener a {#link GpsStatus.NmeaListener} object to register
+     * @param listener a {@link GpsStatus.NmeaListener} object to register
      *
      * @return true if the listener was successfully added
      *
@@ -1521,7 +1522,7 @@
     /**
      * Removes an NMEA listener.
      *
-     * @param listener a {#link GpsStatus.NmeaListener} object to remove
+     * @param listener a {@link GpsStatus.NmeaListener} object to remove
      */
     public void removeNmeaListener(GpsStatus.NmeaListener listener) {
         try {
@@ -1577,7 +1578,7 @@
      * Used by NetInitiatedActivity to report user response
      * for network initiated GPS fix requests.
      *
-     * {@hide}
+     * @hide
      */
     public boolean sendNiResponse(int notifId, int userResponse) {
     	try {
@@ -1588,4 +1589,42 @@
         }
     }
 
+    private static void checkProvider(String provider) {
+        if (provider == null) {
+            throw new IllegalArgumentException("invalid provider: " + provider);
+        }
+    }
+
+    private static void checkCriteria(Criteria criteria) {
+        if (criteria == null) {
+            throw new IllegalArgumentException("invalid criteria: " + criteria);
+        }
+    }
+
+    private static void checkListener(LocationListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("invalid listener: " + listener);
+        }
+    }
+
+    private void checkPendingIntent(PendingIntent intent) {
+        if (intent == null) {
+            throw new IllegalArgumentException("invalid pending intent: " + intent);
+        }
+        if (!intent.isTargetedToPackage()) {
+            IllegalArgumentException e = new IllegalArgumentException(
+                    "pending intent msut be targeted to package");
+            if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.JELLY_BEAN) {
+                throw e;
+            } else {
+                Log.w(TAG, e);
+            }
+        }
+    }
+
+    private static void checkGeofence(Geofence fence) {
+        if (fence == null) {
+            throw new IllegalArgumentException("invalid geofence: " + fence);
+        }
+    }
 }
diff --git a/location/java/android/location/LocationProvider.java b/location/java/android/location/LocationProvider.java
index 8c16580..c4fd097 100644
--- a/location/java/android/location/LocationProvider.java
+++ b/location/java/android/location/LocationProvider.java
@@ -16,8 +16,8 @@
 
 package android.location;
 
-import android.os.RemoteException;
-import android.util.Log;
+
+import com.android.internal.location.ProviderProperties;
 
 /**
  * An abstract superclass for location providers.  A location provider
@@ -33,34 +33,35 @@
  * Criteria} class allows providers to be selected based on
  * user-specified criteria.
  */
-public abstract class LocationProvider {
-    private static final String TAG = "LocationProvider";
-    // A regular expression matching characters that may not appear
-    // in the name of a LocationProvider.
-    static final String BAD_CHARS_REGEX = "[^a-zA-Z0-9]";
-
-    private final String mName;
-    private final ILocationManager mService;
-
+public class LocationProvider {
     public static final int OUT_OF_SERVICE = 0;
     public static final int TEMPORARILY_UNAVAILABLE = 1;
     public static final int AVAILABLE = 2;
 
     /**
+     * A regular expression matching characters that may not appear
+     * in the name of a LocationProvider
+     * @hide
+     */
+    public static final String BAD_CHARS_REGEX = "[^a-zA-Z0-9]";
+
+    private final String mName;
+    private final ProviderProperties mProperties;
+
+    /**
      * Constructs a LocationProvider with the given name.   Provider names must
      * consist only of the characters [a-zA-Z0-9].
      *
      * @throws IllegalArgumentException if name contains an illegal character
      *
-     * {@hide}
+     * @hide
      */
-    public LocationProvider(String name, ILocationManager service) {
+    public LocationProvider(String name, ProviderProperties properties) {
         if (name.matches(BAD_CHARS_REGEX)) {
-            throw new IllegalArgumentException("name " + name +
-                " contains an illegal character");
+            throw new IllegalArgumentException("provider name contains illegal character: " + name);
         }
         mName = name;
-        mService = service;
+        mProperties = properties;
     }
 
     /**
@@ -75,40 +76,81 @@
      * false otherwise.
      */
     public boolean meetsCriteria(Criteria criteria) {
-        try {
-            return mService.providerMeetsCriteria(mName, criteria);
-        } catch (RemoteException e) {
-            Log.e(TAG, "meetsCriteria: RemoteException", e);
+        return propertiesMeetCriteria(mName, mProperties, criteria);
+    }
+
+    /**
+     * @hide
+     */
+    public static boolean propertiesMeetCriteria(String name, ProviderProperties properties,
+            Criteria criteria) {
+        if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
+            // passive provider never matches
             return false;
         }
+        if (properties == null) {
+            // unfortunately this can happen for provider in remote services
+            // that have not finished binding yet
+            return false;
+        }
+
+        if (criteria.getAccuracy() != Criteria.NO_REQUIREMENT &&
+                criteria.getAccuracy() < properties.mAccuracy) {
+            return false;
+        }
+        if (criteria.getPowerRequirement() != Criteria.NO_REQUIREMENT &&
+                criteria.getPowerRequirement() < properties.mPowerRequirement) {
+            return false;
+        }
+        if (criteria.isAltitudeRequired() && !properties.mSupportsAltitude) {
+            return false;
+        }
+        if (criteria.isSpeedRequired() && !properties.mSupportsSpeed) {
+            return false;
+        }
+        if (criteria.isBearingRequired() && !properties.mSupportsBearing) {
+            return false;
+        }
+        if (!criteria.isCostAllowed() && properties.mHasMonetaryCost) {
+            return false;
+        }
+        return true;
     }
 
     /**
      * Returns true if the provider requires access to a
      * data network (e.g., the Internet), false otherwise.
      */
-    public abstract boolean requiresNetwork();
+    public boolean requiresNetwork() {
+        return mProperties.mRequiresNetwork;
+    }
 
     /**
      * Returns true if the provider requires access to a
      * satellite-based positioning system (e.g., GPS), false
      * otherwise.
      */
-    public abstract boolean requiresSatellite();
+    public boolean requiresSatellite() {
+        return mProperties.mRequiresSatellite;
+    }
 
     /**
      * Returns true if the provider requires access to an appropriate
      * cellular network (e.g., to make use of cell tower IDs), false
      * otherwise.
      */
-    public abstract boolean requiresCell();
+    public boolean requiresCell() {
+        return mProperties.mRequiresCell;
+    }
 
     /**
      * Returns true if the use of this provider may result in a
      * monetary charge to the user, false if use is free.  It is up to
      * each provider to give accurate information.
      */
-    public abstract boolean hasMonetaryCost();
+    public boolean hasMonetaryCost() {
+        return mProperties.mHasMonetaryCost;
+    }
 
     /**
      * Returns true if the provider is able to provide altitude
@@ -116,7 +158,9 @@
      * under most circumstances but may occassionally not report it
      * should return true.
      */
-    public abstract boolean supportsAltitude();
+    public boolean supportsAltitude() {
+        return mProperties.mSupportsAltitude;
+    }
 
     /**
      * Returns true if the provider is able to provide speed
@@ -124,7 +168,9 @@
      * under most circumstances but may occassionally not report it
      * should return true.
      */
-    public abstract boolean supportsSpeed();
+    public boolean supportsSpeed() {
+        return mProperties.mSupportsSpeed;
+    }
 
     /**
      * Returns true if the provider is able to provide bearing
@@ -132,7 +178,9 @@
      * under most circumstances but may occassionally not report it
      * should return true.
      */
-    public abstract boolean supportsBearing();
+    public boolean supportsBearing() {
+        return mProperties.mSupportsBearing;
+    }
 
     /**
      * Returns the power requirement for this provider.
@@ -140,7 +188,9 @@
      * @return the power requirement for this provider, as one of the
      * constants Criteria.POWER_REQUIREMENT_*.
      */
-    public abstract int getPowerRequirement();
+    public int getPowerRequirement() {
+        return mProperties.mPowerRequirement;
+    }
 
     /**
      * Returns a constant describing horizontal accuracy of this provider.
@@ -149,5 +199,7 @@
      * location is only approximate then {@link Criteria#ACCURACY_COARSE}
      * is returned.
      */
-    public abstract int getAccuracy();
+    public int getAccuracy() {
+        return mProperties.mAccuracy;
+    }
 }
diff --git a/location/java/android/location/LocationRequest.aidl b/location/java/android/location/LocationRequest.aidl
new file mode 100644
index 0000000..b1a8647
--- /dev/null
+++ b/location/java/android/location/LocationRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.location;
+
+parcelable LocationRequest;
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
new file mode 100644
index 0000000..68f540b
--- /dev/null
+++ b/location/java/android/location/LocationRequest.java
@@ -0,0 +1,607 @@
+/*
+ * 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.location;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.SystemClock;
+import android.util.TimeUtils;
+
+
+/**
+ * A data object that contains quality of service parameters for requests
+ * to the {@link LocationManager}.
+ *
+ * <p>LocationRequest objects are used to request a quality of service
+ * for location updates from the Location Manager.
+ *
+ * <p>For example, if your application wants high accuracy location
+ * it should create a location request with {@link #setQuality} set to
+ * {@link #ACCURACY_FINE} or {@link #POWER_HIGH}, and it should set
+ * {@link #setInterval} to less than one second. This would be
+ * appropriate for mapping applications that are showing your location
+ * in real-time.
+ *
+ * <p>At the other extreme, if you want negligible power
+ * impact, but to still receive location updates when available, then use
+ * {@link #setQuality} with {@link #POWER_NONE}. With this request your
+ * application will not trigger (and therefore will not receive any
+ * power blame) any location updates, but will receive locations
+ * triggered by other applications. This would be appropriate for
+ * applications that have no firm requirement for location, but can
+ * take advantage when available.
+ *
+ * <p>In between these two extremes is a very common use-case, where
+ * applications definitely want to receive
+ * updates at a specified interval, and can receive them faster when
+ * available, but still want a low power impact. These applications
+ * should consider {@link #POWER_LOW} combined with a faster
+ * {@link #setFastestInterval} (such as 1 minute) and a slower
+ * {@link #setInterval} (such as 60 minutes). They will only be assigned
+ * power blame for the interval set by {@link #setInterval}, but can
+ * still receive locations triggered by other applications at a rate up
+ * to {@link #setFastestInterval}. This style of request is appropriate for
+ * many location aware applications, including background usage. Do be
+ * careful to also throttle {@link #setFastestInterval} if you perform
+ * heavy-weight work after receiving an update - such as using the network.
+ *
+ * <p>Activities should strongly consider removing all location
+ * request when entering the background
+ * (for example at {@link android.app.Activity#onPause}), or
+ * at least swap the request to a larger interval and lower quality.
+ * Future version of the location manager may automatically perform background
+ * throttling on behalf of applications.
+ *
+ * <p>Applications cannot specify the exact location sources that are
+ * used by Android's <em>Fusion Engine</em>. In fact, the system
+ * may have multiple location sources (providers) running and may
+ * fuse the results from several sources into a single Location object.
+ *
+ * <p>Location requests from applications with
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} and not
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} will
+ * be automatically throttled to a slower interval, and the location
+ * object will be obfuscated to only show a coarse level of accuracy.
+ *
+ * <p>All location requests are considered hints, and you may receive
+ * locations that are more accurate, less accurate, and slower
+ * than requested.
+ *
+ * @hide
+ */
+public final class LocationRequest implements Parcelable {
+    /**
+     * Used with {@link #setQuality} to request the most accurate locations available.
+     *
+     * <p>This may be up to 1 meter accuracy, although this is implementation dependent.
+     */
+    public static final int ACCURACY_FINE = 100;
+
+    /**
+     * Used with {@link #setQuality} to request "block" level accuracy.
+     *
+     * <p>Block level accuracy is considered to be about 100 meter accuracy,
+     * although this is implementation dependent. Using a coarse accuracy
+     * such as this often consumes less power.
+     */
+    public static final int ACCURACY_BLOCK = 102;
+
+    /**
+     * Used with {@link #setQuality} to request "city" level accuracy.
+     *
+     * <p>City level accuracy is considered to be about 10km accuracy,
+     * although this is implementation dependent. Using a coarse accuracy
+     * such as this often consumes less power.
+     */
+    public static final int ACCURACY_CITY = 104;
+
+    /**
+     * Used with {@link #setQuality} to require no direct power impact (passive locations).
+     *
+     * <p>This location request will not trigger any active location requests,
+     * but will receive locations triggered by other applications. Your application
+     * will not receive any direct power blame for location work.
+     */
+    public static final int POWER_NONE = 200;
+
+    /**
+     * Used with {@link #setQuality} to request low power impact.
+     *
+     * <p>This location request will avoid high power location work where
+     * possible.
+     */
+    public static final int POWER_LOW = 201;
+
+    /**
+     * Used with {@link #setQuality} to allow high power consumption for location.
+     *
+     * <p>This location request will allow high power location work.
+     */
+    public static final int POWER_HIGH = 203;
+
+    /**
+     * By default, mFastestInterval = FASTEST_INTERVAL_MULTIPLE * mInterval
+     */
+    private static final double FASTEST_INTERVAL_FACTOR = 6.0;  // 6x
+
+    private int mQuality = POWER_LOW;
+    private long mInterval = 60 * 60 * 1000;   // 60 minutes
+    private long mFastestInterval = (long)(mInterval / FASTEST_INTERVAL_FACTOR);  // 10 minutes
+    private boolean mExplicitFastestInterval = false;
+    private long mExpireAt = Long.MAX_VALUE;  // no expiry
+    private int mNumUpdates = Integer.MAX_VALUE;  // no expiry
+    private float mSmallestDisplacement = 0.0f;    // meters
+
+    private String mProvider = LocationManager.FUSED_PROVIDER;  // for deprecated APIs that explicitly request a provider
+
+    /**
+     * Create a location request with default parameters.
+     *
+     * <p>Default parameters are for a low power, slowly updated location.
+     * It can then be adjusted as required by the applications before passing
+     * to the {@link LocationManager}
+     *
+     * @return a new location request
+     */
+    public static LocationRequest create() {
+        LocationRequest request = new LocationRequest();
+        return request;
+    }
+
+    /** @hide */
+    public static LocationRequest createFromDeprecatedProvider(String provider, long minTime,
+            float minDistance, boolean singleShot) {
+        if (minTime < 0) minTime = 0;
+        if (minDistance < 0) minDistance = 0;
+
+        int quality;
+        if (LocationManager.PASSIVE_PROVIDER.equals(provider)) {
+            quality = POWER_NONE;
+        } else if (LocationManager.GPS_PROVIDER.equals(provider)) {
+            quality = ACCURACY_FINE;
+        } else {
+            quality = POWER_LOW;
+        }
+
+        LocationRequest request = new LocationRequest()
+            .setProvider(provider)
+            .setQuality(quality)
+            .setInterval(minTime)
+            .setFastestInterval(minTime)
+            .setSmallestDisplacement(minDistance);
+        if (singleShot) request.setNumUpdates(1);
+        return request;
+    }
+
+    /** @hide */
+    public static LocationRequest createFromDeprecatedCriteria(Criteria criteria, long minTime,
+            float minDistance, boolean singleShot) {
+        if (minTime < 0) minTime = 0;
+        if (minDistance < 0) minDistance = 0;
+
+        int quality;
+        switch (criteria.getAccuracy()) {
+            case Criteria.ACCURACY_COARSE:
+                quality = ACCURACY_BLOCK;
+                break;
+            case Criteria.ACCURACY_FINE:
+                quality = ACCURACY_FINE;
+                break;
+            default: {
+                switch (criteria.getPowerRequirement()) {
+                    case Criteria.POWER_HIGH:
+                        quality = POWER_HIGH;
+                    default:
+                        quality = POWER_LOW;
+                }
+            }
+        }
+
+        LocationRequest request = new LocationRequest()
+            .setQuality(quality)
+            .setInterval(minTime)
+            .setFastestInterval(minTime)
+            .setSmallestDisplacement(minDistance);
+        if (singleShot) request.setNumUpdates(1);
+        return request;
+    }
+
+    /** @hide */
+    public LocationRequest() { }
+
+    /** @hide */
+    public LocationRequest(LocationRequest src) {
+        mQuality = src.mQuality;
+        mInterval = src.mInterval;
+        mFastestInterval = src.mFastestInterval;
+        mExplicitFastestInterval = src.mExplicitFastestInterval;
+        mExpireAt = src.mExpireAt;
+        mNumUpdates = src.mNumUpdates;
+        mSmallestDisplacement = src.mSmallestDisplacement;
+        mProvider = src.mProvider;
+    }
+
+    /**
+     * Set the quality of the request.
+     *
+     * <p>Use with a accuracy constant such as {@link #ACCURACY_FINE}, or a power
+     * constant such as {@link #POWER_LOW}. You cannot request both and accuracy and
+     * power, only one or the other can be specified. The system will then
+     * maximize accuracy or minimize power as appropriate.
+     *
+     * <p>The quality of the request is a strong hint to the system for which
+     * location sources to use. For example, {@link #ACCURACY_FINE} is more likely
+     * to use GPS, and {@link #POWER_LOW} is more likely to use WIFI & Cell tower
+     * positioning, but it also depends on many other factors (such as which sources
+     * are available) and is implementation dependent.
+     *
+     * <p>{@link #setQuality} and {@link #setInterval} are the most important parameters
+     * on a location request.
+     *
+     * @param quality an accuracy or power constant
+     * @throws InvalidArgumentException if the quality constant is not valid
+     * @return the same object, so that setters can be chained
+     */
+    public LocationRequest setQuality(int quality) {
+        checkQuality(quality);
+        mQuality = quality;
+        return this;
+    }
+
+    /**
+     * Get the quality of the request.
+     *
+     * @return an accuracy or power constant
+     */
+    public int getQuality() {
+        return mQuality;
+    }
+
+    /**
+     * Set the desired interval for active location updates, in milliseconds.
+     *
+     * <p>The location manager will actively try to obtain location updates
+     * for your application at this interval, so it has a
+     * direct influence on the amount of power used by your application.
+     * Choose your interval wisely.
+     *
+     * <p>This interval is inexact. You may not receive updates at all (if
+     * no location sources are available), or you may receive them
+     * slower than requested. You may also receive them faster than
+     * requested (if other applications are requesting location at a
+     * faster interval). The fastest rate that that you will receive
+     * updates can be controlled with {@link #setFastestInterval}.
+     *
+     * <p>Applications with only the coarse location permission may have their
+     * interval silently throttled.
+     *
+     * <p>An interval of 0 is allowed, but not recommended, since
+     * location updates may be extremely fast on future implementations.
+     *
+     * <p>{@link #setQuality} and {@link #setInterval} are the most important parameters
+     * on a location request.
+     *
+     * @param millis desired interval in millisecond, inexact
+     * @throws InvalidArgumentException if the interval is less than zero
+     * @return the same object, so that setters can be chained
+     */
+    public LocationRequest setInterval(long millis) {
+        checkInterval(millis);
+        mInterval = millis;
+        if (!mExplicitFastestInterval) {
+            mFastestInterval = (long)(mInterval / FASTEST_INTERVAL_FACTOR);
+        }
+        return this;
+    }
+
+    /**
+     * Get the desired interval of this request, in milliseconds.
+     *
+     * @return desired interval in milliseconds, inexact
+     */
+    public long getInterval() {
+        return mInterval;
+    }
+
+    /**
+     * Explicitly set the fastest interval for location updates, in
+     * milliseconds.
+     *
+     * <p>This controls the fastest rate at which your application will
+     * receive location updates, which might be faster than
+     * {@link #setInterval} in some situations (for example, if other
+     * applications are triggering location updates).
+     *
+     * <p>This allows your application to passively acquire locations
+     * at a rate faster than it actively acquires locations, saving power.
+     *
+     * <p>Unlike {@link #setInterval}, this parameter is exact. Your
+     * application will never receive updates faster than this value.
+     *
+     * <p>If you don't call this method, a fastest interval
+     * will be selected for you. It will be a value faster than your
+     * active interval ({@link #setInterval}).
+     *
+     * <p>An interval of 0 is allowed, but not recommended, since
+     * location updates may be extremely fast on future implementations.
+     *
+     * <p>If {@link #setFastestInterval} is set slower than {@link #setInterval},
+     * then your effective fastest interval is {@link #setInterval}.
+     *
+     * @param millis fastest interval for updates in milliseconds, exact
+     * @throws InvalidArgumentException if the interval is less than zero
+     * @return the same object, so that setters can be chained
+     */
+    public LocationRequest setFastestInterval(long millis) {
+        checkInterval(millis);
+        mExplicitFastestInterval = true;
+        mFastestInterval = millis;
+        return this;
+    }
+
+    /**
+     * Get the fastest interval of this request, in milliseconds.
+     *
+     * <p>The system will never provide location updates faster
+     * than the minimum of {@link #getFastestInterval} and
+     * {@link #getInterval}.
+     *
+     * @return fastest interval in milliseconds, exact
+     */
+    public long getFastestInterval() {
+        return mFastestInterval;
+    }
+
+    /**
+     * Set the duration of this request, in milliseconds.
+     *
+     * <p>The duration begins immediately (and not when the request
+     * is passed to the location manager), so call this method again
+     * if the request is re-used at a later time.
+     *
+     * <p>The location manager will automatically stop updates after
+     * the request expires.
+     *
+     * <p>The duration includes suspend time. Values less than 0
+     * are allowed, but indicate that the request has already expired.
+     *
+     * @param millis duration of request in milliseconds
+     * @return the same object, so that setters can be chained
+     */
+    public LocationRequest setExpireIn(long millis) {
+        long elapsedRealtime = SystemClock.elapsedRealtime();
+
+        // Check for > Long.MAX_VALUE overflow (elapsedRealtime > 0):
+        if (millis > Long.MAX_VALUE - elapsedRealtime) {
+          mExpireAt = Long.MAX_VALUE;
+        } else {
+          mExpireAt = millis + elapsedRealtime;
+        }
+
+        if (mExpireAt < 0) mExpireAt = 0;
+        return this;
+    }
+
+    /**
+     * Set the request expiration time, in millisecond since boot.
+     *
+     * <p>This expiration time uses the same time base as {@link SystemClock#elapsedRealtime}.
+     *
+     * <p>The location manager will automatically stop updates after
+     * the request expires.
+     *
+     * <p>The duration includes suspend time. Values before {@link SystemClock#elapsedRealtime}
+     * are allowed,  but indicate that the request has already expired.
+     *
+     * @param millis expiration time of request, in milliseconds since boot including suspend
+     * @return the same object, so that setters can be chained
+     */
+    public LocationRequest setExpireAt(long millis) {
+        mExpireAt = millis;
+        if (mExpireAt < 0) mExpireAt = 0;
+        return this;
+    }
+
+    /**
+     * Get the request expiration time, in milliseconds since boot.
+     *
+     * <p>This value can be compared to {@link SystemClock#elapsedRealtime} to determine
+     * the time until expiration.
+     *
+     * @return expiration time of request, in milliseconds since boot including suspend
+     */
+    public long getExpireAt() {
+        return mExpireAt;
+    }
+
+    /**
+     * Set the number of location updates.
+     *
+     * <p>By default locations are continuously updated until the request is explicitly
+     * removed, however you can optionally request a set number of updates.
+     * For example, if your application only needs a single fresh location,
+     * then call this method with a value of 1 before passing the request
+     * to the location manager.
+     *
+     * @param numUpdates the number of location updates requested
+     * @throws InvalidArgumentException if numUpdates is 0 or less
+     * @return the same object, so that setters can be chained
+     */
+    public LocationRequest setNumUpdates(int numUpdates) {
+        if (numUpdates <= 0) throw new IllegalArgumentException("invalid numUpdates: " + numUpdates);
+        mNumUpdates = numUpdates;
+        return this;
+    }
+
+    /**
+     * Get the number of updates requested.
+     *
+     * <p>By default this is {@link Integer#MAX_VALUE}, which indicates that
+     * locations are updated until the request is explicitly removed.
+     * @return number of updates
+     */
+    public int getNumUpdates() {
+        return mNumUpdates;
+    }
+
+    /** @hide */
+    public void decrementNumUpdates() {
+        if (mNumUpdates != Integer.MAX_VALUE) {
+            mNumUpdates--;
+        }
+        if (mNumUpdates < 0) {
+            mNumUpdates = 0;
+        }
+    }
+
+
+    /** @hide */
+    public LocationRequest setProvider(String provider) {
+        checkProvider(provider);
+        mProvider = provider;
+        return this;
+    }
+
+    /** @hide */
+    public String getProvider() {
+        return mProvider;
+    }
+
+    /** @hide */
+    public LocationRequest setSmallestDisplacement(float meters) {
+        checkDisplacement(meters);
+        mSmallestDisplacement = meters;
+        return this;
+    }
+
+    /** @hide */
+    public float getSmallestDisplacement() {
+        return mSmallestDisplacement;
+    }
+
+    private static void checkInterval(long millis) {
+        if (millis < 0) {
+            throw new IllegalArgumentException("invalid interval: " + millis);
+        }
+    }
+
+    private static void checkQuality(int quality) {
+        switch (quality) {
+            case ACCURACY_FINE:
+            case ACCURACY_BLOCK:
+            case ACCURACY_CITY:
+            case POWER_NONE:
+            case POWER_LOW:
+            case POWER_HIGH:
+                break;
+            default:
+                throw new IllegalArgumentException("invalid quality: " + quality);
+        }
+    }
+
+    private static void checkDisplacement(float meters) {
+        if (meters < 0.0f) {
+            throw new IllegalArgumentException("invalid displacement: " + meters);
+        }
+    }
+
+    private static void checkProvider(String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("invalid provider: " + name);
+        }
+    }
+
+    public static final Parcelable.Creator<LocationRequest> CREATOR =
+            new Parcelable.Creator<LocationRequest>() {
+        @Override
+        public LocationRequest createFromParcel(Parcel in) {
+            LocationRequest request = new LocationRequest();
+            request.setQuality(in.readInt());
+            request.setFastestInterval(in.readLong());
+            request.setInterval(in.readLong());
+            request.setExpireAt(in.readLong());
+            request.setNumUpdates(in.readInt());
+            request.setSmallestDisplacement(in.readFloat());
+            String provider = in.readString();
+            if (provider != null) request.setProvider(provider);
+            return request;
+        }
+        @Override
+        public LocationRequest[] newArray(int size) {
+            return new LocationRequest[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(mQuality);
+        parcel.writeLong(mFastestInterval);
+        parcel.writeLong(mInterval);
+        parcel.writeLong(mExpireAt);
+        parcel.writeInt(mNumUpdates);
+        parcel.writeFloat(mSmallestDisplacement);
+        parcel.writeString(mProvider);
+    }
+
+    /** @hide */
+    public static String qualityToString(int quality) {
+        switch (quality) {
+            case ACCURACY_FINE:
+                return "ACCURACY_FINE";
+            case ACCURACY_BLOCK:
+                return "ACCURACY_BLOCK";
+            case ACCURACY_CITY:
+                return "ACCURACY_CITY";
+            case POWER_NONE:
+                return "POWER_NONE";
+            case POWER_LOW:
+                return "POWER_LOW";
+            case POWER_HIGH:
+                return "POWER_HIGH";
+            default:
+                return "???";
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder s = new StringBuilder();
+        s.append("Request[").append(qualityToString(mQuality));
+        if (mProvider != null) s.append(' ').append(mProvider);
+        if (mQuality != POWER_NONE) {
+            s.append(" requested=");
+            TimeUtils.formatDuration(mInterval, s);
+        }
+        s.append(" fastest=");
+        TimeUtils.formatDuration(mFastestInterval, s);
+        if (mExpireAt != Long.MAX_VALUE) {
+            long expireIn = mExpireAt - SystemClock.elapsedRealtime();
+            s.append(" expireIn=");
+            TimeUtils.formatDuration(expireIn, s);
+        }
+        if (mNumUpdates != Integer.MAX_VALUE){
+            s.append(" num=").append(mNumUpdates);
+        }
+        s.append(']');
+        return s.toString();
+    }
+}
diff --git a/location/java/com/android/internal/location/DummyLocationProvider.java b/location/java/com/android/internal/location/DummyLocationProvider.java
deleted file mode 100644
index e7b5143..0000000
--- a/location/java/com/android/internal/location/DummyLocationProvider.java
+++ /dev/null
@@ -1,171 +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.
- */
-
-package com.android.internal.location;
-
-import android.location.ILocationManager;
-import android.location.LocationProvider;
-
-/**
- * A stub implementation of LocationProvider used by LocationManager.
- * A DummyLocationProvider may be queried to determine the properties
- * of the provider whcih it shadows, but does not actually provide location
- * data.
- * 
- * {@hide}
- */
-public class DummyLocationProvider extends LocationProvider {
-
-    private static final String TAG = "DummyLocationProvider";
-
-    String mName;
-    boolean mRequiresNetwork;
-    boolean mRequiresSatellite;
-    boolean mRequiresCell;
-    boolean mHasMonetaryCost;
-    boolean mSupportsAltitude;
-    boolean mSupportsSpeed;
-    boolean mSupportsBearing;
-    int mPowerRequirement;
-    int mAccuracy;
-
-    public DummyLocationProvider(String name, ILocationManager service) {
-        super(name, service);
-    }
-
-    public void setRequiresNetwork(boolean requiresNetwork) {
-        mRequiresNetwork = requiresNetwork;
-    }
-
-    public void setRequiresSatellite(boolean requiresSatellite) {
-        mRequiresSatellite = requiresSatellite;
-    }
-
-    public void setRequiresCell(boolean requiresCell) {
-        mRequiresCell = requiresCell;
-    }
-
-    public void setHasMonetaryCost(boolean hasMonetaryCost) {
-        mHasMonetaryCost = hasMonetaryCost;
-    }
-
-    public void setSupportsAltitude(boolean supportsAltitude) {
-        mSupportsAltitude = supportsAltitude;
-    }
-
-    public void setSupportsSpeed(boolean supportsSpeed) {
-        mSupportsSpeed = supportsSpeed;
-    }
-
-    public void setSupportsBearing(boolean supportsBearing) {
-        mSupportsBearing = supportsBearing;
-    }
-
-    public void setPowerRequirement(int powerRequirement) {
-        mPowerRequirement = powerRequirement;
-    }
-
-    public void setAccuracy(int accuracy) {
-        mAccuracy = accuracy;
-    }
-
-    /**
-     * Returns true if the provider requires access to a
-     * data network (e.g., the Internet), false otherwise.
-     */
-    public boolean requiresNetwork() {
-        return mRequiresNetwork;
-    }
-
-    /**
-     * Returns true if the provider requires access to a
-     * satellite-based positioning system (e.g., GPS), false
-     * otherwise.
-     */
-    public boolean requiresSatellite() {
-        return mRequiresSatellite;
-    }
-
-    /**
-     * Returns true if the provider requires access to an appropriate
-     * cellular network (e.g., to make use of cell tower IDs), false
-     * otherwise.
-     */
-    public boolean requiresCell() {
-        return mRequiresCell;
-    }
-
-    /**
-     * Returns true if the use of this provider may result in a
-     * monetary charge to the user, false if use is free.  It is up to
-     * each provider to give accurate information.
-     */
-    public boolean hasMonetaryCost() {
-        return mHasMonetaryCost;
-    }
-
-    /**
-     * Returns true if the provider is able to provide altitude
-     * information, false otherwise.  A provider that reports altitude
-     * under most circumstances but may occassionally not report it
-     * should return true.
-     */
-    public boolean supportsAltitude() {
-        return mSupportsAltitude;
-    }
-
-    /**
-     * Returns true if the provider is able to provide speed
-     * information, false otherwise.  A provider that reports speed
-     * under most circumstances but may occassionally not report it
-     * should return true.
-     */
-    public boolean supportsSpeed() {
-        return mSupportsSpeed;
-    }
-
-    /**
-     * Returns true if the provider is able to provide bearing
-     * information, false otherwise.  A provider that reports bearing
-     * under most circumstances but may occassionally not report it
-     * should return true.
-     */
-    public boolean supportsBearing() {
-        return mSupportsBearing;
-    }
-
-    /**
-     * Returns the power requirement for this provider.
-     *
-     * @return the power requirement for this provider, as one of the
-     * constants Criteria.POWER_REQUIREMENT_*.
-     */
-    public int getPowerRequirement() {
-        return mPowerRequirement;
-    }
-
-    /**
-     * Returns a constant describing the horizontal accuracy returned
-     * by this provider.
-     *
-     * @return the horizontal accuracy for this provider, as one of the
-     * constants Criteria.ACCURACY_*.
-     */
-    public int getAccuracy() {
-        return mAccuracy;
-    }
-}
-
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 0adba06..57e2786 100755
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -26,6 +26,7 @@
 import android.location.LocationManager;
 import android.os.Bundle;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.Log;
 
 import com.android.internal.R;
@@ -89,7 +90,6 @@
     
     // configuration of notificaiton behavior
     private boolean mPlaySounds = false;
-    private boolean visible = true;
     private boolean mPopupImmediately = true;
     
     // Set to true if string from HAL is encoded as Hex, e.g., "3F0039"    
@@ -213,11 +213,8 @@
         PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);                
         mNiNotification.setLatestEventInfo(mContext, title, message, pi);
 
-        if (visible) {
-            notificationManager.notify(notif.notificationId, mNiNotification);
-        } else {
-            notificationManager.cancel(notif.notificationId);
-        }
+        notificationManager.notifyAsUser(null, notif.notificationId, mNiNotification,
+                UserHandle.ALL);
     }
 
     // Opens the notification dialog and waits for user input
diff --git a/location/java/com/android/internal/location/ILocationProvider.aidl b/location/java/com/android/internal/location/ILocationProvider.aidl
new file mode 100644
index 0000000..39c2d92
--- /dev/null
+++ b/location/java/com/android/internal/location/ILocationProvider.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.location;
+
+import android.location.Location;
+import android.net.NetworkInfo;
+import android.os.Bundle;
+import android.os.WorkSource;
+
+import com.android.internal.location.ProviderProperties;
+import com.android.internal.location.ProviderRequest;
+
+/**
+ * Binder interface for services that implement location providers.
+ * <p>Use {@link LocationProviderBase} as a helper to implement this
+ * interface.
+ * @hide
+ */
+interface ILocationProvider {
+    void enable();
+    void disable();
+
+    void setRequest(in ProviderRequest request, in WorkSource ws);
+
+    // --- deprecated (but still supported) ---
+    ProviderProperties getProperties();
+    int getStatus(out Bundle extras);
+    long getStatusUpdateTime();
+    boolean sendExtraCommand(String command, inout Bundle extras);
+}
diff --git a/location/java/com/android/internal/location/ProviderProperties.aidl b/location/java/com/android/internal/location/ProviderProperties.aidl
new file mode 100644
index 0000000..b901444
--- /dev/null
+++ b/location/java/com/android/internal/location/ProviderProperties.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.internal.location;
+
+parcelable ProviderProperties;
diff --git a/location/java/com/android/internal/location/ProviderProperties.java b/location/java/com/android/internal/location/ProviderProperties.java
new file mode 100644
index 0000000..def96f0
--- /dev/null
+++ b/location/java/com/android/internal/location/ProviderProperties.java
@@ -0,0 +1,152 @@
+/*
+ * 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.internal.location;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A Parcelable containing (legacy) location provider properties.
+ * This object is just used inside the framework and system services.
+ * @hide
+ */
+public final class ProviderProperties implements Parcelable {
+    /**
+     * True if provider requires access to a
+     * data network (e.g., the Internet), false otherwise.
+     */
+    public final boolean mRequiresNetwork;
+
+    /**
+     * True if the provider requires access to a
+     * satellite-based positioning system (e.g., GPS), false
+     * otherwise.
+     */
+    public final boolean mRequiresSatellite;
+
+    /**
+     * True if the provider requires access to an appropriate
+     * cellular network (e.g., to make use of cell tower IDs), false
+     * otherwise.
+     */
+    public final boolean mRequiresCell;
+
+    /**
+     * True if the use of this provider may result in a
+     * monetary charge to the user, false if use is free.  It is up to
+     * each provider to give accurate information. Cell (network) usage
+     * is not considered monetary cost.
+     */
+    public final boolean mHasMonetaryCost;
+
+    /**
+     * True if the provider is able to provide altitude
+     * information, false otherwise.  A provider that reports altitude
+     * under most circumstances but may occasionally not report it
+     * should return true.
+     */
+    public final boolean mSupportsAltitude;
+
+    /**
+     * True if the provider is able to provide speed
+     * information, false otherwise.  A provider that reports speed
+     * under most circumstances but may occasionally not report it
+     * should return true.
+     */
+    public final boolean mSupportsSpeed;
+
+    /**
+     * True if the provider is able to provide bearing
+     * information, false otherwise.  A provider that reports bearing
+     * under most circumstances but may occasionally not report it
+     * should return true.
+     */
+    public final boolean mSupportsBearing;
+
+    /**
+     * Power requirement for this provider.
+     *
+     * @return the power requirement for this provider, as one of the
+     * constants Criteria.POWER_*.
+     */
+    public final int mPowerRequirement;
+
+    /**
+     * Constant describing the horizontal accuracy returned
+     * by this provider.
+     *
+     * @return the horizontal accuracy for this provider, as one of the
+     * constants Criteria.ACCURACY_COARSE or Criteria.ACCURACY_FINE
+     */
+    public final int mAccuracy;
+
+    public ProviderProperties(boolean mRequiresNetwork,
+            boolean mRequiresSatellite, boolean mRequiresCell, boolean mHasMonetaryCost,
+            boolean mSupportsAltitude, boolean mSupportsSpeed, boolean mSupportsBearing,
+            int mPowerRequirement, int mAccuracy) {
+        this.mRequiresNetwork = mRequiresNetwork;
+        this.mRequiresSatellite = mRequiresSatellite;
+        this.mRequiresCell = mRequiresCell;
+        this.mHasMonetaryCost = mHasMonetaryCost;
+        this.mSupportsAltitude = mSupportsAltitude;
+        this.mSupportsSpeed = mSupportsSpeed;
+        this.mSupportsBearing = mSupportsBearing;
+        this.mPowerRequirement = mPowerRequirement;
+        this.mAccuracy = mAccuracy;
+    }
+
+    public static final Parcelable.Creator<ProviderProperties> CREATOR =
+            new Parcelable.Creator<ProviderProperties>() {
+        @Override
+        public ProviderProperties createFromParcel(Parcel in) {
+            boolean requiresNetwork = in.readInt() == 1;
+            boolean requiresSatellite = in.readInt() == 1;
+            boolean requiresCell = in.readInt() == 1;
+            boolean hasMonetaryCost = in.readInt() == 1;
+            boolean supportsAltitude = in.readInt() == 1;
+            boolean supportsSpeed = in.readInt() == 1;
+            boolean supportsBearing = in.readInt() == 1;
+            int powerRequirement = in.readInt();
+            int accuracy = in.readInt();
+            return new ProviderProperties(requiresNetwork, requiresSatellite,
+                    requiresCell, hasMonetaryCost, supportsAltitude, supportsSpeed, supportsBearing,
+                    powerRequirement, accuracy);
+        }
+        @Override
+        public ProviderProperties[] newArray(int size) {
+            return new ProviderProperties[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(mRequiresNetwork ? 1 : 0);
+        parcel.writeInt(mRequiresSatellite ? 1 : 0);
+        parcel.writeInt(mRequiresCell ? 1 : 0);
+        parcel.writeInt(mHasMonetaryCost ? 1 : 0);
+        parcel.writeInt(mSupportsAltitude ? 1 : 0);
+        parcel.writeInt(mSupportsSpeed ? 1 : 0);
+        parcel.writeInt(mSupportsBearing ? 1 : 0);
+        parcel.writeInt(mPowerRequirement);
+        parcel.writeInt(mAccuracy);
+    }
+}
diff --git a/location/java/com/android/internal/location/ProviderRequest.aidl b/location/java/com/android/internal/location/ProviderRequest.aidl
new file mode 100644
index 0000000..4e1ea95
--- /dev/null
+++ b/location/java/com/android/internal/location/ProviderRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.internal.location;
+
+parcelable ProviderRequest;
diff --git a/location/java/com/android/internal/location/ProviderRequest.java b/location/java/com/android/internal/location/ProviderRequest.java
new file mode 100644
index 0000000..26243e7
--- /dev/null
+++ b/location/java/com/android/internal/location/ProviderRequest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.internal.location;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.location.LocationRequest;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.TimeUtils;
+
+/** @hide */
+public final class ProviderRequest implements Parcelable {
+    /** Location reporting is requested (true) */
+    public boolean reportLocation = false;
+
+    /** The smallest requested interval */
+    public long interval = Long.MAX_VALUE;
+
+    /**
+     * A more detailed set of requests.
+     * <p>Location Providers can optionally use this to
+     * fine tune location updates, for example when there
+     * is a high power slow interval request and a
+     * low power fast interval request.
+     */
+    public List<LocationRequest> locationRequests = new ArrayList<LocationRequest>();
+
+    public ProviderRequest() { }
+
+    public static final Parcelable.Creator<ProviderRequest> CREATOR =
+            new Parcelable.Creator<ProviderRequest>() {
+        @Override
+        public ProviderRequest createFromParcel(Parcel in) {
+            ProviderRequest request = new ProviderRequest();
+            request.reportLocation = in.readInt() == 1;
+            request.interval = in.readLong();
+            int count = in.readInt();
+            for (int i = 0; i < count; i++) {
+                request.locationRequests.add(LocationRequest.CREATOR.createFromParcel(in));
+            }
+            return request;
+        }
+        @Override
+        public ProviderRequest[] newArray(int size) {
+            return new ProviderRequest[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(reportLocation ? 1 : 0);
+        parcel.writeLong(interval);
+        parcel.writeInt(locationRequests.size());
+        for (LocationRequest request : locationRequests) {
+            request.writeToParcel(parcel, flags);
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder s = new StringBuilder();
+        s.append("ProviderRequest[");
+        if (reportLocation) {
+            s.append("ON");
+            s.append(" interval=");
+            TimeUtils.formatDuration(interval, s);
+        } else {
+            s.append("OFF");
+        }
+        s.append(']');
+        return s.toString();
+    }
+}
diff --git a/location/lib/Android.mk b/location/lib/Android.mk
index a06478a..62f5677 100644
--- a/location/lib/Android.mk
+++ b/location/lib/Android.mk
@@ -23,7 +23,8 @@
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_SRC_FILES := \
-            $(call all-subdir-java-files)
+            $(call all-subdir-java-files) \
+            $(call all-aidl-files-under, java)
 
 include $(BUILD_JAVA_LIBRARY)
 
diff --git a/location/lib/README.txt b/location/lib/README.txt
new file mode 100644
index 0000000..400a7dd
--- /dev/null
+++ b/location/lib/README.txt
@@ -0,0 +1,30 @@
+This library (com.android.location.provider.jar) is a shared java library
+containing classes required by unbundled location providers.
+
+--- Rules of this library ---
+o This library is effectively a PUBLIC API for unbundled location providers
+  that may be distributed outside the system image. So it MUST BE API STABLE.
+  You can add but not remove. The rules are the same as for the
+  public platform SDK API.
+o This library can see and instantiate internal platform classes (such as
+  ProviderRequest.java), but it must not expose them in any public method
+  (or by extending them via inheritance). This would break clients of the
+  library because they cannot see the internal platform classes.
+
+This library is distributed in the system image, and loaded as
+a shared library. So you can change the implementation, but not
+the interface. In this way it is like framework.jar.
+
+--- Why does this library exists? ---
+
+Unbundled location providers (such as the NetworkLocationProvider)
+can not use internal platform classes.
+
+So ideally all of these classes would be part of the public platform SDK API,
+but that doesn't seem like a great idea when only applications with a special
+signature can implement this API.
+
+The compromise is this library.
+
+It wraps internal platform classes (like ProviderRequest) with a stable
+API that does not leak the internal classes.
diff --git a/location/lib/java/com/android/location/provider/GeocodeProvider.java b/location/lib/java/com/android/location/provider/GeocodeProvider.java
index 666bb02..d7a34af 100644
--- a/location/lib/java/com/android/location/provider/GeocodeProvider.java
+++ b/location/lib/java/com/android/location/provider/GeocodeProvider.java
@@ -25,12 +25,14 @@
 import java.util.List;
 
 /**
- * An abstract superclass for geocode providers that are implemented
- * outside of the core android platform.
- * Geocode providers can be implemented as services and return the result of
+ * Base class for geocode providers implemented as unbundled services.
+ *
+ * <p>Geocode providers can be implemented as services and return the result of
  * {@link GeocodeProvider#getBinder()} in its getBinder() method.
  *
- * @hide
+ * <p>IMPORTANT: This class is effectively a public API for unbundled
+ * applications, and must remain API stable. See README.txt in the root
+ * of this package for more information.
  */
 public abstract class GeocodeProvider {
 
diff --git a/location/lib/java/com/android/location/provider/LocationProvider.java b/location/lib/java/com/android/location/provider/LocationProvider.java
deleted file mode 100644
index 3714f40..0000000
--- a/location/lib/java/com/android/location/provider/LocationProvider.java
+++ /dev/null
@@ -1,358 +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.
- */
-
-package com.android.location.provider;
-
-import android.content.Context;
-import android.net.NetworkInfo;
-import android.location.Criteria;
-import android.location.ILocationManager;
-import android.location.ILocationProvider;
-import android.location.Location;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.WorkSource;
-import android.util.Log;
-
-/**
- * An abstract superclass for location providers that are implemented
- * outside of the core android platform.
- * Location providers can be implemented as services and return the result of
- * {@link LocationProvider#getBinder()} in its getBinder() method.
- *
- * @hide
- */
-public abstract class LocationProvider {
-
-    private static final String TAG = "LocationProvider";
-
-    private ILocationManager mLocationManager;
-
-    private ILocationProvider.Stub mProvider = new ILocationProvider.Stub() {
-
-        public boolean requiresNetwork() {
-            return LocationProvider.this.onRequiresNetwork();
-        }
-
-        public boolean requiresSatellite() {
-            return LocationProvider.this.onRequiresSatellite();
-        }
-
-        public boolean requiresCell() {
-            return LocationProvider.this.onRequiresCell();
-        }
-
-        public boolean hasMonetaryCost() {
-            return LocationProvider.this.onHasMonetaryCost();
-        }
-
-        public boolean supportsAltitude() {
-            return LocationProvider.this.onSupportsAltitude();
-        }
-
-        public boolean supportsSpeed() {
-            return LocationProvider.this.onSupportsSpeed();
-        }
-
-        public boolean supportsBearing() {
-            return LocationProvider.this.onSupportsBearing();
-        }
-
-        public int getPowerRequirement() {
-            return LocationProvider.this.onGetPowerRequirement();
-        }
-
-        public boolean meetsCriteria(Criteria criteria) {
-            return LocationProvider.this.onMeetsCriteria(criteria);
-        }
-
-        public int getAccuracy() {
-            return LocationProvider.this.onGetAccuracy();
-        }
-
-        public void enable() {
-            LocationProvider.this.onEnable();
-        }
-
-        public void disable() {
-            LocationProvider.this.onDisable();
-        }
-
-        public int getStatus(Bundle extras) {
-            return LocationProvider.this.onGetStatus(extras);
-        }
-
-        public long getStatusUpdateTime() {
-            return LocationProvider.this.onGetStatusUpdateTime();
-        }
-
-        public String getInternalState() {
-            return LocationProvider.this.onGetInternalState();
-        }
-
-        public void enableLocationTracking(boolean enable) {
-            LocationProvider.this.onEnableLocationTracking(enable);
-        }
-
-        public void setMinTime(long minTime, WorkSource ws) {
-            LocationProvider.this.onSetMinTime(minTime, ws);
-        }
-
-        public void updateNetworkState(int state, NetworkInfo info) {
-            LocationProvider.this.onUpdateNetworkState(state, info);
-        }
-
-        public void updateLocation(Location location) {
-            LocationProvider.this.onUpdateLocation(location);
-        }
-
-        public boolean sendExtraCommand(String command, Bundle extras) {
-            return LocationProvider.this.onSendExtraCommand(command, extras);
-        }
-
-        public void addListener(int uid) {
-            LocationProvider.this.onAddListener(uid, new WorkSource(uid));
-        }
-
-        public void removeListener(int uid) {
-            LocationProvider.this.onRemoveListener(uid, new WorkSource(uid));
-        }
-    };
-
-    public LocationProvider() {
-        IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE);
-        mLocationManager = ILocationManager.Stub.asInterface(b);
-    }
-
-    /**
-     * {@hide}
-     */
-    /* package */ ILocationProvider getInterface() {
-        return mProvider;
-    }
-
-    /**
-     * Returns the Binder interface for the location provider.
-     * This is intended to be used for the onBind() method of
-     * a service that implements a location provider service.
-     *
-     * @return the IBinder instance for the provider
-     */
-    public IBinder getBinder() {
-        return mProvider;
-    }
-
-    /**
-     * Used by the location provider to report new locations.
-     *
-     * @param location new Location to report
-     *
-     * Requires the android.permission.INSTALL_LOCATION_PROVIDER permission.
-     */
-    public void reportLocation(Location location) {
-        try {
-            mLocationManager.reportLocation(location, false);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in reportLocation: ", e);
-        }
-    }
-
-    /**
-     * Returns true if the provider requires access to a
-     * data network (e.g., the Internet), false otherwise.
-     */
-    public abstract boolean onRequiresNetwork();
-
-    /**
-     * Returns true if the provider requires access to a
-     * satellite-based positioning system (e.g., GPS), false
-     * otherwise.
-     */
-    public abstract boolean onRequiresSatellite();
-
-    /**
-     * Returns true if the provider requires access to an appropriate
-     * cellular network (e.g., to make use of cell tower IDs), false
-     * otherwise.
-     */
-    public abstract boolean onRequiresCell();
-
-    /**
-     * Returns true if the use of this provider may result in a
-     * monetary charge to the user, false if use is free.  It is up to
-     * each provider to give accurate information.
-     */
-    public abstract boolean onHasMonetaryCost();
-
-    /**
-     * Returns true if the provider is able to provide altitude
-     * information, false otherwise.  A provider that reports altitude
-     * under most circumstances but may occassionally not report it
-     * should return true.
-     */
-    public abstract boolean onSupportsAltitude();
-
-    /**
-     * Returns true if the provider is able to provide speed
-     * information, false otherwise.  A provider that reports speed
-     * under most circumstances but may occassionally not report it
-     * should return true.
-     */
-    public abstract boolean onSupportsSpeed();
-
-    /**
-     * Returns true if the provider is able to provide bearing
-     * information, false otherwise.  A provider that reports bearing
-     * under most circumstances but may occassionally not report it
-     * should return true.
-     */
-    public abstract boolean onSupportsBearing();
-
-    /**
-     * Returns the power requirement for this provider.
-     *
-     * @return the power requirement for this provider, as one of the
-     * constants Criteria.POWER_REQUIREMENT_*.
-     */
-    public abstract int onGetPowerRequirement();
-
-    /**
-     * Returns true if this provider meets the given criteria,
-     * false otherwise.
-     */
-    public abstract boolean onMeetsCriteria(Criteria criteria);
-
-    /**
-     * Returns a constant describing horizontal accuracy of this provider.
-     * If the provider returns finer grain or exact location,
-     * {@link Criteria#ACCURACY_FINE} is returned, otherwise if the
-     * location is only approximate then {@link Criteria#ACCURACY_COARSE}
-     * is returned.
-     */
-    public abstract int onGetAccuracy();
-
-    /**
-     * Enables the location provider
-     */
-    public abstract void onEnable();
-
-    /**
-     * Disables the location provider
-     */
-    public abstract void onDisable();
-
-    /**
-     * Returns a information on the status of this provider.
-     * {@link android.location.LocationProvider#OUT_OF_SERVICE} is returned if the provider is
-     * out of service, and this is not expected to change in the near
-     * future; {@link android.location.LocationProvider#TEMPORARILY_UNAVAILABLE} is returned if
-     * the provider is temporarily unavailable but is expected to be
-     * available shortly; and {@link android.location.LocationProvider#AVAILABLE} is returned
-     * if the provider is currently available.
-     *
-     * <p> If extras is non-null, additional status information may be
-     * added to it in the form of provider-specific key/value pairs.
-     */
-    public abstract int onGetStatus(Bundle extras);
-
-    /**
-     * Returns the time at which the status was last updated. It is the
-     * responsibility of the provider to appropriately set this value using
-     * {@link android.os.SystemClock#elapsedRealtime SystemClock.elapsedRealtime()}.
-     * there is a status update that it wishes to broadcast to all its
-     * listeners. The provider should be careful not to broadcast
-     * the same status again.
-     *
-     * @return time of last status update in millis since last reboot
-     */
-    public abstract long onGetStatusUpdateTime();
-
-    /**
-     * Returns debugging information about the location provider.
-     *
-     * @return string describing the internal state of the location provider, or null.
-     */
-    public abstract String onGetInternalState();
-
-    /**
-     * Notifies the location provider that clients are listening for locations.
-     * Called with enable set to true when the first client is added and
-     * called with enable set to false when the last client is removed.
-     * This allows the provider to prepare for receiving locations,
-     * and to shut down when no clients are remaining.
-     *
-     * @param enable true if location tracking should be enabled.
-     */
-    public abstract void onEnableLocationTracking(boolean enable);
-
-    /**
-     * Notifies the location provider of the smallest minimum time between updates amongst
-     * all clients that are listening for locations.  This allows the provider to reduce
-     * the frequency of updates to match the requested frequency.
-     *
-     * @param minTime the smallest minTime value over all listeners for this provider.
-     * @param ws the source this work is coming from.
-     */
-    public abstract void onSetMinTime(long minTime, WorkSource ws);
-
-    /**
-     * Updates the network state for the given provider. This function must
-     * be overwritten if {@link android.location.LocationProvider#requiresNetwork} returns true.
-     * The state is {@link android.location.LocationProvider#TEMPORARILY_UNAVAILABLE} (disconnected)
-     * OR {@link android.location.LocationProvider#AVAILABLE} (connected or connecting).
-     *
-     * @param state data state
-     */
-    public abstract void onUpdateNetworkState(int state, NetworkInfo info);
-
-    /**
-     * Informs the provider when a new location has been computed by a different
-     * location provider.  This is intended to be used as aiding data for the
-     * receiving provider.
-     *
-     * @param location new location from other location provider
-     */
-    public abstract void onUpdateLocation(Location location);
-
-    /**
-     * Implements addditional location provider specific additional commands.
-     *
-     * @param command name of the command to send to the provider.
-     * @param extras optional arguments for the command (or null).
-     * The provider may optionally fill the extras Bundle with results from the command.
-     *
-     * @return true if the command succeeds.
-     */
-    public abstract boolean onSendExtraCommand(String command, Bundle extras);
-
-    /**
-     * Notifies the location provider when a new client is listening for locations.
-     *
-     * @param uid user ID of the new client.
-     * @param ws a WorkSource representation of the client.
-     */
-    public abstract void onAddListener(int uid, WorkSource ws);
-
-    /**
-     * Notifies the location provider when a client is no longer listening for locations.
-     *
-     * @param uid user ID of the client no longer listening.
-     * @param ws a WorkSource representation of the client.
-     */
-    public abstract void onRemoveListener(int uid, WorkSource ws);
-}
diff --git a/location/lib/java/com/android/location/provider/LocationProviderBase.java b/location/lib/java/com/android/location/provider/LocationProviderBase.java
new file mode 100644
index 0000000..8a5a739
--- /dev/null
+++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java
@@ -0,0 +1,213 @@
+/*
+ * 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.
+ */
+
+package com.android.location.provider;
+
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+
+import android.content.Context;
+import android.location.ILocationManager;
+import android.location.Location;
+import android.location.LocationManager;
+import android.location.LocationRequest;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.WorkSource;
+import android.util.Log;
+
+import com.android.internal.location.ILocationProvider;
+import com.android.internal.location.ProviderProperties;
+import com.android.internal.location.ProviderRequest;
+
+/**
+ * Base class for location providers implemented as unbundled services.
+ *
+ * <p>The network location provider must export a service with action
+ * "com.android.location.service.v2.NetworkLocationProvider"
+ * and a valid minor version in a meta-data field on the service, and
+ * then return the result of {@link #getBinder()} on service binding.
+ *
+ * <p>The fused location provider must export a service with action
+ * "com.android.location.service.FusedLocationProvider"
+ * and a valid minor version in a meta-data field on the service, and
+ * then return the result of {@link #getBinder()} on service binding.
+ *
+ * <p>IMPORTANT: This class is effectively a public API for unbundled
+ * applications, and must remain API stable. See README.txt in the root
+ * of this package for more information.
+ */
+public abstract class LocationProviderBase {
+    private final String TAG;
+
+    protected final ILocationManager mLocationManager;
+    private final ProviderProperties mProperties;
+    private final IBinder mBinder;
+
+    /**
+     * Bundle key for a version of the location containing no GPS data.
+     * Allows location providers to flag locations as being safe to
+     * feed to LocationFudger.
+     */
+    public static final String EXTRA_NO_GPS_LOCATION = Location.EXTRA_NO_GPS_LOCATION;
+
+    /**
+     * Name of the Fused location provider.
+     *
+     * <p>This provider combines inputs for all possible location sources
+     * to provide the best possible Location fix.
+     */
+    public static final String FUSED_PROVIDER = LocationManager.FUSED_PROVIDER;
+
+    private final class Service extends ILocationProvider.Stub {
+        @Override
+        public void enable() {
+            onEnable();
+        }
+        @Override
+        public void disable() {
+            onDisable();
+        }
+        @Override
+        public void setRequest(ProviderRequest request, WorkSource ws) {
+            onSetRequest(new ProviderRequestUnbundled(request), ws);
+        }
+        @Override
+        public ProviderProperties getProperties() {
+            return mProperties;
+        }
+        @Override
+        public int getStatus(Bundle extras) {
+            return onGetStatus(extras);
+        }
+        @Override
+        public long getStatusUpdateTime() {
+            return onGetStatusUpdateTime();
+        }
+        @Override
+        public boolean sendExtraCommand(String command, Bundle extras) {
+            return onSendExtraCommand(command, extras);
+        }
+        @Override
+        public void dump(FileDescriptor fd, String[] args) {
+            PrintWriter pw = new PrintWriter(new FileOutputStream(fd));
+            onDump(fd, pw, args);
+            pw.flush();
+        }
+    }
+
+    public LocationProviderBase(String tag, ProviderPropertiesUnbundled properties) {
+        TAG = tag;
+        IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE);
+        mLocationManager = ILocationManager.Stub.asInterface(b);
+        mProperties = properties.getProviderProperties();
+        mBinder = new Service();
+    }
+
+    public IBinder getBinder() {
+        return mBinder;
+    }
+
+    /**
+     * Used by the location provider to report new locations.
+     *
+     * @param location new Location to report
+     *
+     * Requires the android.permission.INSTALL_LOCATION_PROVIDER permission.
+     */
+    public final void reportLocation(Location location) {
+        try {
+            mLocationManager.reportLocation(location, false);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException", e);
+        } catch (Exception e) {
+            // never crash provider, might be running in a system process
+            Log.e(TAG, "Exception", e);
+        }
+    }
+
+    /**
+     * Enable the location provider.
+     * <p>The provider may initialize resources, but does
+     * not yet need to report locations.
+     */
+    public abstract void onEnable();
+
+    /**
+     * Disable the location provider.
+     * <p>The provider must release resources, and stop
+     * performing work. It may no longer report locations.
+     */
+    public abstract void onDisable();
+
+    /**
+     * Set the {@link ProviderRequest} requirements for this provider.
+     * <p>Each call to this method overrides all previous requests.
+     * <p>This method might trigger the provider to start returning
+     * locations, or to stop returning locations, depending on the
+     * parameters in the request.
+     */
+    public abstract void onSetRequest(ProviderRequestUnbundled request, WorkSource source);
+
+    /**
+     * Dump debug information.
+     */
+    public void onDump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    }
+
+    /**
+     * Returns a information on the status of this provider.
+     * <p>{@link android.location.LocationProvider#OUT_OF_SERVICE} is returned if the provider is
+     * out of service, and this is not expected to change in the near
+     * future; {@link android.location.LocationProvider#TEMPORARILY_UNAVAILABLE} is returned if
+     * the provider is temporarily unavailable but is expected to be
+     * available shortly; and {@link android.location.LocationProvider#AVAILABLE} is returned
+     * if the provider is currently available.
+     *
+     * <p>If extras is non-null, additional status information may be
+     * added to it in the form of provider-specific key/value pairs.
+     */
+    public abstract int onGetStatus(Bundle extras);
+
+    /**
+     * Returns the time at which the status was last updated. It is the
+     * responsibility of the provider to appropriately set this value using
+     * {@link android.os.SystemClock#elapsedRealtime SystemClock.elapsedRealtime()}.
+     * there is a status update that it wishes to broadcast to all its
+     * listeners. The provider should be careful not to broadcast
+     * the same status again.
+     *
+     * @return time of last status update in millis since last reboot
+     */
+    public abstract long onGetStatusUpdateTime();
+
+    /**
+     * Implements addditional location provider specific additional commands.
+     *
+     * @param command name of the command to send to the provider.
+     * @param extras optional arguments for the command (or null).
+     * The provider may optionally fill the extras Bundle with results from the command.
+     *
+     * @return true if the command succeeds.
+     */
+    public boolean onSendExtraCommand(String command, Bundle extras) {
+        // default implementation
+        return false;
+    }
+}
diff --git a/location/lib/java/com/android/location/provider/LocationRequestUnbundled.java b/location/lib/java/com/android/location/provider/LocationRequestUnbundled.java
new file mode 100644
index 0000000..41fd769
--- /dev/null
+++ b/location/lib/java/com/android/location/provider/LocationRequestUnbundled.java
@@ -0,0 +1,128 @@
+/*
+ * 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.location.provider;
+
+import android.location.LocationRequest;
+
+/**
+ * This class is an interface to LocationRequests for unbundled applications.
+ *
+ * <p>IMPORTANT: This class is effectively a public API for unbundled
+ * applications, and must remain API stable. See README.txt in the root
+ * of this package for more information.
+ */
+public final class LocationRequestUnbundled {
+    /**
+     * Returned by {@link #getQuality} when requesting the most accurate locations available.
+     *
+     * <p>This may be up to 1 meter accuracy, although this is implementation dependent.
+     */
+    public static final int ACCURACY_FINE = LocationRequest.ACCURACY_FINE;
+
+    /**
+     * Returned by {@link #getQuality} when requesting "block" level accuracy.
+     *
+     * <p>Block level accuracy is considered to be about 100 meter accuracy,
+     * although this is implementation dependent. Using a coarse accuracy
+     * such as this often consumes less power.
+     */
+    public static final int ACCURACY_BLOCK = LocationRequest.ACCURACY_BLOCK;
+
+    /**
+     * Returned by {@link #getQuality} when requesting "city" level accuracy.
+     *
+     * <p>City level accuracy is considered to be about 10km accuracy,
+     * although this is implementation dependent. Using a coarse accuracy
+     * such as this often consumes less power.
+     */
+    public static final int ACCURACY_CITY = LocationRequest.ACCURACY_CITY;
+
+    /**
+     * Returned by {@link #getQuality} when requiring no direct power impact (passive locations).
+     *
+     * <p>This location request will not trigger any active location requests,
+     * but will receive locations triggered by other applications. Your application
+     * will not receive any direct power blame for location work.
+     */
+    public static final int POWER_NONE = LocationRequest.POWER_NONE;
+
+    /**
+     * Returned by {@link #getQuality} when requesting low power impact.
+     *
+     * <p>This location request will avoid high power location work where
+     * possible.
+     */
+    public static final int POWER_LOW = LocationRequest.POWER_LOW;
+
+    /**
+     * Returned by {@link #getQuality} when allowing high power consumption for location.
+     *
+     * <p>This location request will allow high power location work.
+     */
+    public static final int POWER_HIGH = LocationRequest.POWER_HIGH;
+
+    private final LocationRequest delegate;
+
+    LocationRequestUnbundled(LocationRequest delegate) {
+        this.delegate = delegate;
+    }
+
+    /**
+     * Get the desired interval of this request, in milliseconds.
+     *
+     * @return desired interval in milliseconds, inexact
+     */
+    public long getInterval() {
+        return delegate.getInterval();
+    }
+
+    /**
+     * Get the fastest interval of this request, in milliseconds.
+     *
+     * <p>The system will never provide location updates faster
+     * than the minimum of {@link #getFastestInterval} and
+     * {@link #getInterval}.
+     *
+     * @return fastest interval in milliseconds, exact
+     */
+    public long getFastestInterval() {
+        return delegate.getFastestInterval();
+    }
+
+    /**
+     * Get the quality of the request.
+     *
+     * @return an accuracy or power constant
+     */
+    public int getQuality() {
+        return delegate.getQuality();
+    }
+
+    /**
+     * Get the minimum distance between location updates, in meters.
+     *
+     * @return minimum distance between location updates in meters
+     */
+    public float getSmallestDisplacement() {
+        return delegate.getSmallestDisplacement();
+    }
+
+    @Override
+    public String toString() {
+      return delegate.toString();
+    }
+}
diff --git a/location/lib/java/com/android/location/provider/ProviderPropertiesUnbundled.java b/location/lib/java/com/android/location/provider/ProviderPropertiesUnbundled.java
new file mode 100644
index 0000000..9ee4df21
--- /dev/null
+++ b/location/lib/java/com/android/location/provider/ProviderPropertiesUnbundled.java
@@ -0,0 +1,52 @@
+/*
+ * 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.location.provider;
+
+import com.android.internal.location.ProviderProperties;
+
+/**
+ * This class is an interface to Provider Properties for unbundled applications.
+ *
+ * <p>IMPORTANT: This class is effectively a public API for unbundled
+ * applications, and must remain API stable. See README.txt in the root
+ * of this package for more information.
+ */
+public final class ProviderPropertiesUnbundled {
+    private final ProviderProperties mProperties;
+
+    public static ProviderPropertiesUnbundled create(boolean requiresNetwork,
+            boolean requiresSatellite, boolean requiresCell, boolean hasMonetaryCost,
+            boolean supportsAltitude, boolean supportsSpeed, boolean supportsBearing,
+            int powerRequirement, int accuracy) {
+        return new ProviderPropertiesUnbundled(new ProviderProperties(requiresNetwork,
+                requiresSatellite, requiresCell, hasMonetaryCost, supportsAltitude, supportsSpeed,
+                supportsBearing, powerRequirement, accuracy));
+    }
+
+    private ProviderPropertiesUnbundled(ProviderProperties properties) {
+        mProperties = properties;
+    }
+
+    public ProviderProperties getProviderProperties() {
+        return mProperties;
+    }
+
+    @Override
+    public String toString() {
+        return mProperties.toString();
+    }
+}
diff --git a/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java b/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java
new file mode 100644
index 0000000..ad3d1df
--- /dev/null
+++ b/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java
@@ -0,0 +1,64 @@
+/*
+ * 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.location.provider;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.location.LocationRequest;
+
+import com.android.internal.location.ProviderRequest;
+
+/**
+ * This class is an interface to Provider Requests for unbundled applications.
+ *
+ * <p>IMPORTANT: This class is effectively a public API for unbundled
+ * applications, and must remain API stable. See README.txt in the root
+ * of this package for more information.
+ */
+public final class ProviderRequestUnbundled {
+    private final ProviderRequest mRequest;
+
+    public ProviderRequestUnbundled(ProviderRequest request) {
+        mRequest = request;
+    }
+
+    public boolean getReportLocation() {
+        return mRequest.reportLocation;
+    }
+
+    public long getInterval() {
+        return mRequest.interval;
+    }
+
+    /**
+     * Never null.
+     */
+    public List<LocationRequestUnbundled> getLocationRequests() {
+        List<LocationRequestUnbundled> result = new ArrayList<LocationRequestUnbundled>(
+                mRequest.locationRequests.size());
+        for (LocationRequest r : mRequest.locationRequests) {
+          result.add(new LocationRequestUnbundled(r));
+        }
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return mRequest.toString();
+    }
+}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index b6e4659..035b282 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -49,6 +49,7 @@
     private final Context mContext;
     private long mVolumeKeyUpTime;
     private final boolean mUseMasterVolume;
+    private final boolean mUseVolumeKeySounds;
     private static String TAG = "AudioManager";
 
     /**
@@ -313,6 +314,13 @@
     public static final int FLAG_VIBRATE = 1 << 4;
 
     /**
+     * Indicates to VolumePanel that the volume slider should be disabled as user
+     * cannot change the stream volume
+     * @hide
+     */
+    public static final int FLAG_FIXED_VOLUME = 1 << 5;
+
+    /**
      * Ringer mode that will be silent and will not vibrate. (This overrides the
      * vibrate setting.)
      *
@@ -412,6 +420,8 @@
         mContext = context;
         mUseMasterVolume = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_useMasterVolume);
+        mUseVolumeKeySounds = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_useVolumeKeySounds);
     }
 
     private static IAudioService getService()
@@ -463,6 +473,7 @@
                  * responsive to the user.
                  */
                 int flags = FLAG_SHOW_UI | FLAG_VIBRATE;
+
                 if (mUseMasterVolume) {
                     adjustMasterVolume(
                             keyCode == KeyEvent.KEYCODE_VOLUME_UP
@@ -502,18 +513,17 @@
                  * Play a sound. This is done on key up since we don't want the
                  * sound to play when a user holds down volume down to mute.
                  */
-                if (mUseMasterVolume) {
-                    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
+                if (mUseVolumeKeySounds) {
+                    if (mUseMasterVolume) {
                         adjustMasterVolume(ADJUST_SAME, FLAG_PLAY_SOUND);
+                    } else {
+                        int flags = FLAG_PLAY_SOUND;
+                        adjustSuggestedStreamVolume(
+                                ADJUST_SAME,
+                                stream,
+                                flags);
                     }
-                } else {
-                    int flags = FLAG_PLAY_SOUND;
-                    adjustSuggestedStreamVolume(
-                            ADJUST_SAME,
-                            stream,
-                            flags);
                 }
-
                 mVolumeKeyUpTime = SystemClock.uptimeMillis();
                 break;
         }
@@ -1161,7 +1171,7 @@
     /**
      * Indicates if current platform supports use of SCO for off call use cases.
      * Application wanted to use bluetooth SCO audio when the phone is not in call
-     * must first call thsi method to make sure that the platform supports this
+     * must first call this method to make sure that the platform supports this
      * feature.
      * @return true if bluetooth SCO can be used for audio when not in call
      *         false otherwise
@@ -1297,6 +1307,19 @@
     }
 
     /**
+     * @hide
+     * Signals whether remote submix audio rerouting is enabled.
+     */
+    public void setRemoteSubmixOn(boolean on, int address) {
+        IAudioService service = getService();
+        try {
+            service.setRemoteSubmixOn(on, address);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in setRemoteSubmixOn", e);
+        }
+    }
+
+    /**
      * Sets audio routing to the wired headset on or off.
      *
      * @param on set <var>true</var> to route audio to/from wired
@@ -1503,6 +1526,16 @@
 
     /**
      * @hide
+     * Checks whether speech recognition is active
+     * @return true if a recording with source {@link MediaRecorder.AudioSource#VOICE_RECOGNITION}
+     *    is underway.
+     */
+    public boolean isSpeechRecognitionActive() {
+        return AudioSystem.isSourceActive(MediaRecorder.AudioSource.VOICE_RECOGNITION);
+    }
+
+    /**
+     * @hide
      * If the stream is active locally or remotely, adjust its volume according to the enforced
      * priority rules.
      * Note: only AudioManager.STREAM_MUSIC is supported at the moment
@@ -2427,4 +2460,40 @@
             return null;
         }
     }
+
+    /**
+     * Used as a key for {@link #getProperty} to request the native or optimal output sample rate
+     * for this device's primary output stream, in decimal Hz.
+     */
+    public static final String PROPERTY_OUTPUT_SAMPLE_RATE =
+            "android.media.property.OUTPUT_SAMPLE_RATE";
+
+    /**
+     * Used as a key for {@link #getProperty} to request the native or optimal output buffer size
+     * for this device's primary output stream, in decimal PCM frames.
+     */
+    public static final String PROPERTY_OUTPUT_FRAMES_PER_BUFFER =
+            "android.media.property.OUTPUT_FRAMES_PER_BUFFER";
+
+    /**
+     * Returns the value of the property with the specified key.
+     * @param key One of the strings corresponding to a property key: either
+     *            {@link #PROPERTY_OUTPUT_SAMPLE_RATE} or
+     *            {@link #PROPERTY_OUTPUT_FRAMES_PER_BUFFER}
+     * @return A string representing the associated value for that property key,
+     *         or null if there is no value for that key.
+     */
+    public String getProperty(String key) {
+        if (PROPERTY_OUTPUT_SAMPLE_RATE.equals(key)) {
+            int outputSampleRate = AudioSystem.getPrimaryOutputSamplingRate();
+            return outputSampleRate > 0 ? Integer.toString(outputSampleRate) : null;
+        } else if (PROPERTY_OUTPUT_FRAMES_PER_BUFFER.equals(key)) {
+            int outputFramesPerBuffer = AudioSystem.getPrimaryOutputFrameCount();
+            return outputFramesPerBuffer > 0 ? Integer.toString(outputFramesPerBuffer) : null;
+        } else {
+            // null or unknown key
+            return null;
+        }
+    }
+
 }
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 2e153dd..315196e 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -57,11 +57,13 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.os.Vibrator;
 import android.provider.Settings;
 import android.provider.Settings.System;
 import android.speech.RecognizerIntent;
 import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
@@ -143,12 +145,18 @@
     private static final int MSG_REEVALUATE_REMOTE = 17;
     private static final int MSG_RCC_NEW_PLAYBACK_INFO = 18;
     private static final int MSG_RCC_NEW_VOLUME_OBS = 19;
+    private static final int MSG_SET_FORCE_BT_A2DP_USE = 20;
     // start of messages handled under wakelock
     //   these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
     //   and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
-    private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 20;
-    private static final int MSG_SET_A2DP_CONNECTION_STATE = 21;
+    private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 21;
+    private static final int MSG_SET_A2DP_CONNECTION_STATE = 22;
     // end of messages handled under wakelock
+    private static final int MSG_SET_RSX_CONNECTION_STATE = 23; // change remote submix connection
+    private static final int MSG_CHECK_MUSIC_ACTIVE = 24;
+    private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 25;
+    private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 26;
+    private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 27;
 
     // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be
     // persisted
@@ -381,10 +389,12 @@
     // message looper for SoundPool listener
     private Looper mSoundPoolLooper = null;
     // volume applied to sound played with playSoundEffect()
-    private static int SOUND_EFFECT_VOLUME_DB;
-    // getActiveStreamType() will return STREAM_NOTIFICATION during this period after a notification
+    private static int sSoundEffectVolumeDb;
+    // getActiveStreamType() will return:
+    // - STREAM_NOTIFICATION on tablets during this period after a notification stopped
+    // - STREAM_MUSIC on phones during this period after music or talkback/voice search prompt
     // stopped
-    private static final int NOTIFICATION_VOLUME_DELAY_MS = 5000;
+    private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 5000;
     // previous volume adjustment direction received by checkForRingerModeChange()
     private int mPrevVolDirection = AudioManager.ADJUST_SAME;
     // Keyguard manager proxy
@@ -416,6 +426,16 @@
      */
     public final static int STREAM_REMOTE_MUSIC = -200;
 
+    // Devices for which the volume is fixed and VolumePanel slider should be disabled
+    final int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_AUX_DIGITAL |
+            AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
+            AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
+            AudioSystem.DEVICE_OUT_ALL_USB;
+
+    private final boolean mMonitorOrientation;
+
+    private boolean mDockAudioMediaEnabled = true;
+
     ///////////////////////////////////////////////////////////////////////////
     // Construction
     ///////////////////////////////////////////////////////////////////////////
@@ -438,13 +458,27 @@
             "ro.config.vc_call_vol_steps",
            MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]);
 
-        SOUND_EFFECT_VOLUME_DB = context.getResources().getInteger(
+        sSoundEffectVolumeDb = context.getResources().getInteger(
                 com.android.internal.R.integer.config_soundEffectVolumeDb);
 
         mVolumePanel = new VolumePanel(context, this);
         mMode = AudioSystem.MODE_NORMAL;
         mForcedUseForComm = AudioSystem.FORCE_NONE;
+
         createAudioSystemThread();
+
+        boolean cameraSoundForced = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_camera_sound_forced);
+        mCameraSoundForced = new Boolean(cameraSoundForced);
+        sendMsg(mAudioHandler,
+                MSG_SET_FORCE_USE,
+                SENDMSG_QUEUE,
+                AudioSystem.FOR_SYSTEM,
+                cameraSoundForced ?
+                        AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
+                null,
+                0);
+
         readPersistedSettings();
         mSettingsObserver = new SettingsObserver();
         updateStreamVolumeAlias(false /*updateVolumes*/);
@@ -452,6 +486,8 @@
 
         mMediaServerOk = true;
 
+        mSafeMediaVolumeState = new Integer(SAFE_MEDIA_VOLUME_NOT_CONFIGURED);
+
         // Call setRingerModeInt() to apply correct mute
         // state on streams affected by ringer mode.
         mRingerModeMutedStreams = 0;
@@ -469,12 +505,14 @@
         intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
         intentFilter.addAction(Intent.ACTION_SCREEN_ON);
         intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
+        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
 
+        intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
         // Register a configuration change listener only if requested by system properties
         // to monitor orientation changes (off by default)
-        if (SystemProperties.getBoolean("ro.audio.monitorOrientation", false)) {
+        mMonitorOrientation = SystemProperties.getBoolean("ro.audio.monitorOrientation", false);
+        if (mMonitorOrientation) {
             Log.v(TAG, "monitoring device orientation");
-            intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
             // initialize orientation in AudioSystem
             setOrientationForAudioSystem();
         }
@@ -563,6 +601,8 @@
             mStreamStates[i].dump(pw);
             pw.println("");
         }
+        pw.print("\n- mute affected streams = 0x");
+        pw.println(Integer.toHexString(mMuteAffectedStreams));
     }
 
 
@@ -593,11 +633,33 @@
         }
     }
 
+    private void readDockAudioSettings(ContentResolver cr)
+    {
+        mDockAudioMediaEnabled = Settings.Global.getInt(
+                                        cr, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1;
+
+        if (mDockAudioMediaEnabled) {
+            mBecomingNoisyIntentDevices |= AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;
+        } else {
+            mBecomingNoisyIntentDevices &= ~AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;
+        }
+
+        sendMsg(mAudioHandler,
+                MSG_SET_FORCE_USE,
+                SENDMSG_QUEUE,
+                AudioSystem.FOR_DOCK,
+                mDockAudioMediaEnabled ?
+                        AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE,
+                null,
+                0);
+    }
+
     private void readPersistedSettings() {
         final ContentResolver cr = mContentResolver;
 
         int ringerModeFromSettings =
-                System.getInt(cr, System.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
+                Settings.Global.getInt(
+                        cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
         int ringerMode = ringerModeFromSettings;
         // sanity check in case the settings are restored from a device with incompatible
         // ringer modes
@@ -608,42 +670,66 @@
             ringerMode = AudioManager.RINGER_MODE_SILENT;
         }
         if (ringerMode != ringerModeFromSettings) {
-            System.putInt(cr, System.MODE_RINGER, ringerMode);
+            Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode);
         }
         synchronized(mSettingsLock) {
             mRingerMode = ringerMode;
+
+            // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting
+            // are still needed while setVibrateSetting() and getVibrateSetting() are being
+            // deprecated.
+            mVibrateSetting = getValueForVibrateSetting(0,
+                                            AudioManager.VIBRATE_TYPE_NOTIFICATION,
+                                            mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
+                                                            : AudioManager.VIBRATE_SETTING_OFF);
+            mVibrateSetting = getValueForVibrateSetting(mVibrateSetting,
+                                            AudioManager.VIBRATE_TYPE_RINGER,
+                                            mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
+                                                            : AudioManager.VIBRATE_SETTING_OFF);
+
+            // make sure settings for ringer mode are consistent with device type: non voice capable
+            // devices (tablets) include media stream in silent mode whereas phones don't.
+            mRingerModeAffectedStreams = Settings.System.getIntForUser(cr,
+                    Settings.System.MODE_RINGER_STREAMS_AFFECTED,
+                    ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
+                     (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
+                     UserHandle.USER_CURRENT);
+
+            // ringtone, notification and system streams are always affected by ringer mode
+            mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_RING)|
+                                            (1 << AudioSystem.STREAM_NOTIFICATION)|
+                                            (1 << AudioSystem.STREAM_SYSTEM);
+
+            if (mVoiceCapable) {
+                mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
+            } else {
+                mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
+            }
+            synchronized (mCameraSoundForced) {
+                if (mCameraSoundForced) {
+                    mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+                } else {
+                    mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+                }
+            }
+
+            Settings.System.putIntForUser(cr,
+                    Settings.System.MODE_RINGER_STREAMS_AFFECTED,
+                    mRingerModeAffectedStreams,
+                    UserHandle.USER_CURRENT);
+
+            readDockAudioSettings(cr);
         }
 
-        // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting
-        // are still needed while setVibrateSetting() and getVibrateSetting() are being deprecated.
-        mVibrateSetting = getValueForVibrateSetting(0,
-                                        AudioManager.VIBRATE_TYPE_NOTIFICATION,
-                                        mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
-                                                        : AudioManager.VIBRATE_SETTING_OFF);
-        mVibrateSetting = getValueForVibrateSetting(mVibrateSetting,
-                                        AudioManager.VIBRATE_TYPE_RINGER,
-                                        mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
-                                                        : AudioManager.VIBRATE_SETTING_OFF);
-
-        // make sure settings for ringer mode are consistent with device type: non voice capable
-        // devices (tablets) include media stream in silent mode whereas phones don't.
-        mRingerModeAffectedStreams = Settings.System.getInt(cr,
-                Settings.System.MODE_RINGER_STREAMS_AFFECTED,
-                ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
-                 (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)));
-        if (mVoiceCapable) {
-            mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
-        } else {
-            mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
-        }
-        Settings.System.putInt(cr,
-                Settings.System.MODE_RINGER_STREAMS_AFFECTED, mRingerModeAffectedStreams);
-
-        mMuteAffectedStreams = System.getInt(cr,
+        mMuteAffectedStreams = System.getIntForUser(cr,
                 System.MUTE_STREAMS_AFFECTED,
-                ((1 << AudioSystem.STREAM_MUSIC)|(1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_SYSTEM)));
+                ((1 << AudioSystem.STREAM_MUSIC)|
+                 (1 << AudioSystem.STREAM_RING)|
+                 (1 << AudioSystem.STREAM_SYSTEM)),
+                 UserHandle.USER_CURRENT);
 
-        boolean masterMute = System.getInt(cr, System.VOLUME_MASTER_MUTE, 0) == 1;
+        boolean masterMute = System.getIntForUser(cr, System.VOLUME_MASTER_MUTE,
+                                                  0, UserHandle.USER_CURRENT) == 1;
         AudioSystem.setMasterMute(masterMute);
         broadcastMasterMuteStatus(masterMute);
 
@@ -704,7 +790,7 @@
 
         if (streamType == STREAM_REMOTE_MUSIC) {
             // don't play sounds for remote
-            flags &= ~AudioManager.FLAG_PLAY_SOUND;
+            flags &= ~(AudioManager.FLAG_PLAY_SOUND|AudioManager.FLAG_FIXED_VOLUME);
             //if (DEBUG_VOL) Log.i(TAG, "Need to adjust remote volume: calling adjustRemoteVolume()");
             adjustRemoteVolume(AudioSystem.STREAM_MUSIC, direction, flags);
         } else {
@@ -734,58 +820,72 @@
         // convert one UI step (+/-1) into a number of internal units on the stream alias
         int step = rescaleIndex(10, streamType, streamTypeAlias);
 
-        // If either the client forces allowing ringer modes for this adjustment,
-        // or the stream type is one that is affected by ringer modes
-        if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
-                (streamTypeAlias == getMasterStreamType())) {
-            int ringerMode = getRingerMode();
-            // do not vibrate if already in vibrate mode
-            if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
-                flags &= ~AudioManager.FLAG_VIBRATE;
-            }
-            // Check if the ringer mode changes with this volume adjustment. If
-            // it does, it will handle adjusting the volume, so we won't below
-            adjustVolume = checkForRingerModeChange(aliasIndex, direction, step);
-            if ((streamTypeAlias == getMasterStreamType()) &&
-                    (mRingerMode == AudioManager.RINGER_MODE_SILENT)) {
-                streamState.setLastAudibleIndex(0, device);
-            }
+        if ((direction == AudioManager.ADJUST_RAISE) &&
+                !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
+            return;
         }
 
-        // If stream is muted, adjust last audible index only
         int index;
-        final int oldIndex = mStreamStates[streamType].getIndex(device,
-                (mStreamStates[streamType].muteCount() != 0) /* lastAudible */);
+        int oldIndex;
 
-        if (streamState.muteCount() != 0) {
-            if (adjustVolume) {
-                // Post a persist volume msg
-                // no need to persist volume on all streams sharing the same alias
-                streamState.adjustLastAudibleIndex(direction * step, device);
-                sendMsg(mAudioHandler,
-                        MSG_PERSIST_VOLUME,
-                        SENDMSG_QUEUE,
-                        PERSIST_LAST_AUDIBLE,
-                        device,
-                        streamState,
-                        PERSIST_DELAY);
-            }
-            index = mStreamStates[streamType].getIndex(device, true  /* lastAudible */);
+        flags &= ~AudioManager.FLAG_FIXED_VOLUME;
+        if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
+               ((device & mFixedVolumeDevices) != 0)) {
+            flags |= AudioManager.FLAG_FIXED_VOLUME;
+            index = mStreamStates[streamType].getMaxIndex();
+            oldIndex = index;
         } else {
-            if (adjustVolume && streamState.adjustIndex(direction * step, device)) {
-                // Post message to set system volume (it in turn will post a message
-                // to persist). Do not change volume if stream is muted.
-                sendMsg(mAudioHandler,
-                        MSG_SET_DEVICE_VOLUME,
-                        SENDMSG_QUEUE,
-                        device,
-                        0,
-                        streamState,
-                        0);
+            // If either the client forces allowing ringer modes for this adjustment,
+            // or the stream type is one that is affected by ringer modes
+            if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
+                    (streamTypeAlias == getMasterStreamType())) {
+                int ringerMode = getRingerMode();
+                // do not vibrate if already in vibrate mode
+                if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
+                    flags &= ~AudioManager.FLAG_VIBRATE;
+                }
+                // Check if the ringer mode changes with this volume adjustment. If
+                // it does, it will handle adjusting the volume, so we won't below
+                adjustVolume = checkForRingerModeChange(aliasIndex, direction, step);
+                if ((streamTypeAlias == getMasterStreamType()) &&
+                        (mRingerMode == AudioManager.RINGER_MODE_SILENT)) {
+                    streamState.setLastAudibleIndex(0, device);
+                }
             }
-            index = mStreamStates[streamType].getIndex(device, false  /* lastAudible */);
-        }
 
+            // If stream is muted, adjust last audible index only
+            oldIndex = mStreamStates[streamType].getIndex(device,
+                    (mStreamStates[streamType].muteCount() != 0) /* lastAudible */);
+
+            if (streamState.muteCount() != 0) {
+                if (adjustVolume) {
+                    // Post a persist volume msg
+                    // no need to persist volume on all streams sharing the same alias
+                    streamState.adjustLastAudibleIndex(direction * step, device);
+                    sendMsg(mAudioHandler,
+                            MSG_PERSIST_VOLUME,
+                            SENDMSG_QUEUE,
+                            PERSIST_LAST_AUDIBLE,
+                            device,
+                            streamState,
+                            PERSIST_DELAY);
+                }
+                index = mStreamStates[streamType].getIndex(device, true  /* lastAudible */);
+            } else {
+                if (adjustVolume && streamState.adjustIndex(direction * step, device)) {
+                    // Post message to set system volume (it in turn will post a message
+                    // to persist). Do not change volume if stream is muted.
+                    sendMsg(mAudioHandler,
+                            MSG_SET_DEVICE_VOLUME,
+                            SENDMSG_QUEUE,
+                            device,
+                            0,
+                            streamState,
+                            0);
+                }
+                index = mStreamStates[streamType].getIndex(device, false  /* lastAudible */);
+            }
+        }
         sendVolumeUpdate(streamType, oldIndex, index, flags);
     }
 
@@ -811,35 +911,48 @@
         VolumeStreamState streamState = mStreamStates[mStreamVolumeAlias[streamType]];
 
         final int device = getDeviceForStream(streamType);
-        // get last audible index if stream is muted, current index otherwise
-        final int oldIndex = streamState.getIndex(device,
-                                                  (streamState.muteCount() != 0) /* lastAudible */);
+        int oldIndex;
 
-        index = rescaleIndex(index * 10, streamType, mStreamVolumeAlias[streamType]);
+        flags &= ~AudioManager.FLAG_FIXED_VOLUME;
+        if ((mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
+                ((device & mFixedVolumeDevices) != 0)) {
+            flags |= AudioManager.FLAG_FIXED_VOLUME;
+            index = mStreamStates[streamType].getMaxIndex();
+            oldIndex = index;
+        } else {
+            // get last audible index if stream is muted, current index otherwise
+            oldIndex = streamState.getIndex(device,
+                                            (streamState.muteCount() != 0) /* lastAudible */);
 
-        // setting volume on master stream type also controls silent mode
-        if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
-                (mStreamVolumeAlias[streamType] == getMasterStreamType())) {
-            int newRingerMode;
-            if (index == 0) {
-                newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
-                                              : AudioManager.RINGER_MODE_SILENT;
-                setStreamVolumeInt(mStreamVolumeAlias[streamType],
-                                   index,
-                                   device,
-                                   false,
-                                   true);
-            } else {
-                newRingerMode = AudioManager.RINGER_MODE_NORMAL;
+            index = rescaleIndex(index * 10, streamType, mStreamVolumeAlias[streamType]);
+
+            if (!checkSafeMediaVolume(mStreamVolumeAlias[streamType], index, device)) {
+                return;
             }
-            setRingerMode(newRingerMode);
+
+            // setting volume on master stream type also controls silent mode
+            if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
+                    (mStreamVolumeAlias[streamType] == getMasterStreamType())) {
+                int newRingerMode;
+                if (index == 0) {
+                    newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
+                                                  : AudioManager.RINGER_MODE_SILENT;
+                    setStreamVolumeInt(mStreamVolumeAlias[streamType],
+                                       index,
+                                       device,
+                                       false,
+                                       true);
+                } else {
+                    newRingerMode = AudioManager.RINGER_MODE_NORMAL;
+                }
+                setRingerMode(newRingerMode);
+            }
+
+            setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false, true);
+            // get last audible index if stream is muted, current index otherwise
+            index = mStreamStates[streamType].getIndex(device,
+                                    (mStreamStates[streamType].muteCount() != 0) /* lastAudible */);
         }
-
-        setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false, true);
-        // get last audible index if stream is muted, current index otherwise
-        index = mStreamStates[streamType].getIndex(device,
-                                 (mStreamStates[streamType].muteCount() != 0) /* lastAudible */);
-
         sendVolumeUpdate(streamType, oldIndex, index, flags);
     }
 
@@ -929,6 +1042,24 @@
         return delta;
     }
 
+    private void sendBroadcastToAll(Intent intent) {
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void sendStickyBroadcastToAll(Intent intent) {
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
     // UI update and Broadcast Intent
     private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
         if (!mVoiceCapable && (streamType == AudioSystem.STREAM_RING)) {
@@ -937,13 +1068,15 @@
 
         mVolumePanel.postVolumeChanged(streamType, flags);
 
-        oldIndex = (oldIndex + 5) / 10;
-        index = (index + 5) / 10;
-        Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
-        intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType);
-        intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
-        intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
-        mContext.sendBroadcast(intent);
+        if ((flags & AudioManager.FLAG_FIXED_VOLUME) == 0) {
+            oldIndex = (oldIndex + 5) / 10;
+            index = (index + 5) / 10;
+            Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
+            intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType);
+            intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
+            intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
+            sendBroadcastToAll(intent);
+        }
     }
 
     // UI update and Broadcast Intent
@@ -953,7 +1086,7 @@
         Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION);
         intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume);
         intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume);
-        mContext.sendBroadcast(intent);
+        sendBroadcastToAll(intent);
     }
 
     // UI update and Broadcast Intent
@@ -967,9 +1100,7 @@
         intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
-        long origCallerIdentityToken = Binder.clearCallingIdentity();
-        mContext.sendStickyBroadcast(intent);
-        Binder.restoreCallingIdentity(origCallerIdentityToken);
+        sendStickyBroadcastToAll(intent);
     }
 
     /**
@@ -1060,7 +1191,15 @@
     public int getStreamVolume(int streamType) {
         ensureValidStreamType(streamType);
         int device = getDeviceForStream(streamType);
-        return (mStreamStates[streamType].getIndex(device, false  /* lastAudible */) + 5) / 10;
+        int index;
+
+        if ((mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
+                (device & mFixedVolumeDevices) != 0) {
+            index = mStreamStates[streamType].getMaxIndex();
+        } else {
+            index = mStreamStates[streamType].getIndex(device, false  /* lastAudible */);
+        }
+        return (index + 5) / 10;
     }
 
     public int getMasterVolume() {
@@ -1200,8 +1339,8 @@
 
     private void restoreMasterVolume() {
         if (mUseMasterVolume) {
-            float volume = Settings.System.getFloat(mContentResolver,
-                    Settings.System.VOLUME_MASTER, -1.0f);
+            float volume = Settings.System.getFloatForUser(mContentResolver,
+                    Settings.System.VOLUME_MASTER, -1.0f, UserHandle.USER_CURRENT);
             if (volume >= 0.0f) {
                 AudioSystem.setMasterVolume(volume);
             }
@@ -1637,6 +1776,10 @@
 
     /** @see AudioManager#reloadAudioSettings() */
     public void reloadAudioSettings() {
+        readAudioSettings(false /*userSwitch*/);
+    }
+
+    private void readAudioSettings(boolean userSwitch) {
         // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
         readPersistedSettings();
 
@@ -1645,11 +1788,16 @@
         for (int streamType = 0; streamType < numStreamTypes; streamType++) {
             VolumeStreamState streamState = mStreamStates[streamType];
 
+            if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) {
+                continue;
+            }
+
             synchronized (streamState) {
                 streamState.readSettings();
 
                 // unmute stream that was muted but is not affect by mute anymore
-                if (streamState.muteCount() != 0 && !isStreamAffectedByMute(streamType)) {
+                if (streamState.muteCount() != 0 && !isStreamAffectedByMute(streamType) &&
+                        !isStreamMutedByRingerMode(streamType)) {
                     int size = streamState.mDeathHandlers.size();
                     for (int i = 0; i < size; i++) {
                         streamState.mDeathHandlers.get(i).mMuteCount = 1;
@@ -1659,10 +1807,17 @@
             }
         }
 
+        // apply new ringer mode before checking volume for alias streams so that streams
+        // muted by ringer mode have the correct volume
+        setRingerModeInt(getRingerMode(), false);
+
         checkAllAliasStreamVolumes();
 
-        // apply new ringer mode
-        setRingerModeInt(getRingerMode(), false);
+        synchronized (mSafeMediaVolumeState) {
+            if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) {
+                enforceSafeMediaVolume();
+            }
+        }
     }
 
     /** @see AudioManager#setSpeakerphoneOn() */
@@ -1701,7 +1856,13 @@
 
     /** @see AudioManager#setBluetoothA2dpOn() */
     public void setBluetoothA2dpOn(boolean on) {
-        setBluetoothA2dpOnInt(on);
+        synchronized (mBluetoothA2dpEnabledLock) {
+            mBluetoothA2dpEnabled = on;
+            sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE,
+                    AudioSystem.FOR_MEDIA,
+                    mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
+                    null, 0);
+        }
     }
 
     /** @see AudioManager#isBluetoothA2dpOn() */
@@ -1985,7 +2146,7 @@
             newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state);
             newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE,
                     mScoConnectionState);
-            mContext.sendStickyBroadcast(newIntent);
+            sendStickyBroadcastToAll(newIntent);
             mScoConnectionState = state;
         }
     }
@@ -2085,6 +2246,75 @@
         }
     };
 
+    /** see AudioManager.setRemoteSubmixOn(boolean on) */
+    public void setRemoteSubmixOn(boolean on, int address) {
+        sendMsg(mAudioHandler, MSG_SET_RSX_CONNECTION_STATE,
+                SENDMSG_REPLACE /* replace with QUEUE when multiple addresses are supported */,
+                on ? 1 : 0 /*arg1*/,
+                address /*arg2*/,
+                null/*obj*/, 0/*delay*/);
+    }
+
+    private void onSetRsxConnectionState(int available, int address) {
+        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_REMOTE_SUBMIX,
+                available == 1 ?
+                        AudioSystem.DEVICE_STATE_AVAILABLE : AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                String.valueOf(address) /*device_address*/);
+        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX,
+                available == 1 ?
+                        AudioSystem.DEVICE_STATE_AVAILABLE : AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                String.valueOf(address) /*device_address*/);
+    }
+
+    private void onCheckMusicActive() {
+        synchronized (mSafeMediaVolumeState) {
+            if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
+                int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
+
+                if ((device & mSafeMediaVolumeDevices) != 0) {
+                    sendMsg(mAudioHandler,
+                            MSG_CHECK_MUSIC_ACTIVE,
+                            SENDMSG_REPLACE,
+                            0,
+                            0,
+                            null,
+                            MUSIC_ACTIVE_POLL_PERIOD_MS);
+                    int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device,
+                                                                            false /*lastAudible*/);
+                    if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) &&
+                            (index > mSafeMediaVolumeIndex)) {
+                        // Approximate cumulative active music time
+                        mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS;
+                        if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) {
+                            setSafeMediaVolumeEnabled(true);
+                            mMusicActiveMs = 0;
+                            mVolumePanel.postDisplaySafeVolumeWarning();
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private void onConfigureSafeVolume(boolean force) {
+        synchronized (mSafeMediaVolumeState) {
+            int mcc = mContext.getResources().getConfiguration().mcc;
+            if ((mMcc != mcc) || ((mMcc == 0) && force)) {
+                mSafeMediaVolumeIndex = mContext.getResources().getInteger(
+                        com.android.internal.R.integer.config_safe_media_volume_index) * 10;
+                boolean safeMediaVolumeEnabled = mContext.getResources().getBoolean(
+                        com.android.internal.R.bool.config_safe_media_volume_enabled);
+                if (safeMediaVolumeEnabled) {
+                    mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
+                    enforceSafeMediaVolume();
+                } else {
+                    mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
+                }
+                mMcc = mcc;
+            }
+        }
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // Internal methods
     ///////////////////////////////////////////////////////////////////////////
@@ -2217,7 +2447,8 @@
                     if (DEBUG_VOL)
                         Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC");
                     return STREAM_REMOTE_MUSIC;
-                } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) {
+                } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC,
+                            DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) {
                     if (DEBUG_VOL)
                         Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active");
                     return AudioSystem.STREAM_MUSIC;
@@ -2246,9 +2477,9 @@
                     return AudioSystem.STREAM_VOICE_CALL;
                 }
             } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_NOTIFICATION,
-                    NOTIFICATION_VOLUME_DELAY_MS) ||
+                    DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS) ||
                     AudioSystem.isStreamActive(AudioSystem.STREAM_RING,
-                            NOTIFICATION_VOLUME_DELAY_MS)) {
+                            DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) {
                 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
                 return AudioSystem.STREAM_NOTIFICATION;
             } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
@@ -2276,9 +2507,7 @@
         broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode);
         broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
-        long origCallerIdentityToken = Binder.clearCallingIdentity();
-        mContext.sendStickyBroadcast(broadcast);
-        Binder.restoreCallingIdentity(origCallerIdentityToken);
+        sendStickyBroadcastToAll(broadcast);
     }
 
     private void broadcastVibrateSetting(int vibrateType) {
@@ -2287,7 +2516,7 @@
             Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
             broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType);
             broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType));
-            mContext.sendBroadcast(broadcast);
+            sendBroadcastToAll(broadcast);
         }
     }
 
@@ -2397,9 +2626,10 @@
             AudioSystem.initStreamVolume(streamType, 0, mIndexMax);
             mIndexMax *= 10;
 
-            readSettings();
-
+            // mDeathHandlers must be created before calling readSettings()
             mDeathHandlers = new ArrayList<VolumeDeathHandler>();
+
+            readSettings();
         }
 
         public String getSettingNameForDevice(boolean lastAudible, int device) {
@@ -2416,6 +2646,26 @@
         public synchronized void readSettings() {
             int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
 
+            // do not read system stream volume from settings: this stream is always aliased
+            // to another stream type and its volume is never persisted. Values in settings can
+            // only be stale values
+            // on first call to readSettings() at init time, muteCount() is always 0 so we will
+            // always create entries for default device
+            if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
+                    (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
+                int index = 10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType];
+                synchronized (mCameraSoundForced) {
+                    if (mCameraSoundForced) {
+                        index = mIndexMax;
+                    }
+                }
+                if (muteCount() == 0) {
+                    mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
+                }
+                mLastAudibleIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
+                return;
+            }
+
             for (int i = 0; remainingDevices != 0; i++) {
                 int device = (1 << i);
                 if ((device & remainingDevices) == 0) {
@@ -2423,13 +2673,23 @@
                 }
                 remainingDevices &= ~device;
 
+                // ignore settings for fixed volume devices: volume should always be at max
+                if ((mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) &&
+                        ((device & mFixedVolumeDevices) != 0)) {
+                    if (muteCount() == 0) {
+                        mIndex.put(device, mIndexMax);
+                    }
+                    mLastAudibleIndex.put(device, mIndexMax);
+                    continue;
+                }
                 // retrieve current volume for device
                 String name = getSettingNameForDevice(false /* lastAudible */, device);
                 // if no volume stored for current stream and device, use default volume if default
                 // device, continue otherwise
                 int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
                                         AudioManager.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
-                int index = Settings.System.getInt(mContentResolver, name, defaultIndex);
+                int index = Settings.System.getIntForUser(
+                        mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
                 if (index == -1) {
                     continue;
                 }
@@ -2440,15 +2700,13 @@
                 // or default index
                 defaultIndex = (index > 0) ?
                                     index : AudioManager.DEFAULT_STREAM_VOLUME[mStreamType];
-                int lastAudibleIndex = Settings.System.getInt(mContentResolver, name, defaultIndex);
+                int lastAudibleIndex = Settings.System.getIntForUser(
+                        mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
 
                 // a last audible index of 0 should never be stored for ring and notification
                 // streams on phones (voice capable devices).
-                // same for system stream on phones and tablets
-                if ((lastAudibleIndex == 0) &&
-                        ((mVoiceCapable &&
-                                (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_RING)) ||
-                         (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_SYSTEM))) {
+                if ((lastAudibleIndex == 0) && mVoiceCapable &&
+                                (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_RING)) {
                     lastAudibleIndex = AudioManager.DEFAULT_STREAM_VOLUME[mStreamType];
                     // Correct the data base
                     sendMsg(mAudioHandler,
@@ -2462,11 +2720,9 @@
                 mLastAudibleIndex.put(device, getValidIndex(10 * lastAudibleIndex));
                 // the initial index should never be 0 for ring and notification streams on phones
                 // (voice capable devices) if not in silent or vibrate mode.
-                // same for system stream on phones and tablets
                 if ((index == 0) && (mRingerMode == AudioManager.RINGER_MODE_NORMAL) &&
-                        ((mVoiceCapable &&
-                                (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_RING)) ||
-                         (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_SYSTEM))) {
+                        mVoiceCapable &&
+                        (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_RING)) {
                     index = lastAudibleIndex;
                     // Correct the data base
                     sendMsg(mAudioHandler,
@@ -2477,7 +2733,9 @@
                             this,
                             PERSIST_DELAY);
                 }
-                mIndex.put(device, getValidIndex(10 * index));
+                if (muteCount() == 0) {
+                    mIndex.put(device, getValidIndex(10 * index));
+                }
             }
         }
 
@@ -2517,6 +2775,11 @@
         public synchronized boolean setIndex(int index, int device, boolean lastAudible) {
             int oldIndex = getIndex(device, false  /* lastAudible */);
             index = getValidIndex(index);
+            synchronized (mCameraSoundForced) {
+                if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
+                    index = mIndexMax;
+                }
+            }
             mIndex.put(device, getValidIndex(index));
 
             if (oldIndex != index) {
@@ -2611,7 +2874,27 @@
                 int device = ((Integer)entry.getKey()).intValue();
                 int index = ((Integer)entry.getValue()).intValue();
                 index = rescaleIndex(index, srcStream.getStreamType(), mStreamType);
-                setIndex(index, device, lastAudible);
+
+                if (lastAudible) {
+                    setLastAudibleIndex(index, device);
+                } else {
+                    setIndex(index, device, false /* lastAudible */);
+                }
+            }
+        }
+
+        public synchronized void setAllIndexesToMax() {
+            Set set = mIndex.entrySet();
+            Iterator i = set.iterator();
+            while (i.hasNext()) {
+                Map.Entry entry = (Map.Entry)i.next();
+                entry.setValue(mIndexMax);
+            }
+            set = mLastAudibleIndex.entrySet();
+            i = set.iterator();
+            while (i.hasNext()) {
+                Map.Entry entry = (Map.Entry)i.next();
+                entry.setValue(mIndexMax);
             }
         }
 
@@ -2763,6 +3046,8 @@
         }
 
         private void dump(PrintWriter pw) {
+            pw.print("   Mute count: ");
+            pw.println(muteCount());
             pw.print("   Current: ");
             Set set = mIndex.entrySet();
             Iterator i = set.iterator();
@@ -2852,19 +3137,21 @@
                                    int persistType,
                                    int device) {
             if ((persistType & PERSIST_CURRENT) != 0) {
-                System.putInt(mContentResolver,
+                System.putIntForUser(mContentResolver,
                           streamState.getSettingNameForDevice(false /* lastAudible */, device),
-                          (streamState.getIndex(device, false /* lastAudible */) + 5)/ 10);
+                          (streamState.getIndex(device, false /* lastAudible */) + 5)/ 10,
+                          UserHandle.USER_CURRENT);
             }
             if ((persistType & PERSIST_LAST_AUDIBLE) != 0) {
-                System.putInt(mContentResolver,
+                System.putIntForUser(mContentResolver,
                         streamState.getSettingNameForDevice(true /* lastAudible */, device),
-                        (streamState.getIndex(device, true  /* lastAudible */) + 5) / 10);
+                        (streamState.getIndex(device, true  /* lastAudible */) + 5) / 10,
+                        UserHandle.USER_CURRENT);
             }
         }
 
         private void persistRingerMode(int ringerMode) {
-            System.putInt(mContentResolver, System.MODE_RINGER, ringerMode);
+            Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
         }
 
         private void playSoundEffect(int effectType, int volume) {
@@ -2875,7 +3162,7 @@
                 float volFloat;
                 // use default if volume is not specified by caller
                 if (volume < 0) {
-                    volFloat = (float)Math.pow(10, SOUND_EFFECT_VOLUME_DB/20);
+                    volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
                 } else {
                     volFloat = (float) volume / 1000.0f;
                 }
@@ -2914,8 +3201,10 @@
         }
 
         private void onHandlePersistMediaButtonReceiver(ComponentName receiver) {
-            Settings.System.putString(mContentResolver, Settings.System.MEDIA_BUTTON_RECEIVER,
-                    receiver == null ? "" : receiver.flattenToString());
+            Settings.System.putStringForUser(mContentResolver,
+                                             Settings.System.MEDIA_BUTTON_RECEIVER,
+                                             receiver == null ? "" : receiver.flattenToString(),
+                                             UserHandle.USER_CURRENT);
         }
 
         private void cleanupPlayer(MediaPlayer mp) {
@@ -2951,13 +3240,17 @@
                     break;
 
                 case MSG_PERSIST_MASTER_VOLUME:
-                    Settings.System.putFloat(mContentResolver, Settings.System.VOLUME_MASTER,
-                            (float)msg.arg1 / (float)1000.0);
+                    Settings.System.putFloatForUser(mContentResolver,
+                                                    Settings.System.VOLUME_MASTER,
+                                                    (float)msg.arg1 / (float)1000.0,
+                                                    UserHandle.USER_CURRENT);
                     break;
 
                 case MSG_PERSIST_MASTER_VOLUME_MUTE:
-                    Settings.System.putInt(mContentResolver, Settings.System.VOLUME_MASTER_MUTE,
-                            msg.arg1);
+                    Settings.System.putIntForUser(mContentResolver,
+                                                 Settings.System.VOLUME_MASTER_MUTE,
+                                                 msg.arg1,
+                                                 UserHandle.USER_CURRENT);
                     break;
 
                 case MSG_PERSIST_RINGER_MODE:
@@ -3003,6 +3296,8 @@
                     // Restore forced usage for communcations and record
                     AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm);
                     AudioSystem.setForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm);
+                    AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, mCameraSoundForced ?
+                                    AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE);
 
                     // Restore stream volumes
                     int numStreamTypes = AudioSystem.getNumStreamTypes();
@@ -3020,7 +3315,7 @@
                     restoreMasterVolume();
 
                     // Reset device orientation (if monitored for this device)
-                    if (SystemProperties.getBoolean("ro.audio.monitorOrientation", false)) {
+                    if (mMonitorOrientation) {
                         setOrientationForAudioSystem();
                     }
 
@@ -3049,6 +3344,7 @@
                     break;
 
                 case MSG_SET_FORCE_USE:
+                case MSG_SET_FORCE_BT_A2DP_USE:
                     setForceUse(msg.arg1, msg.arg2);
                     break;
 
@@ -3111,6 +3407,23 @@
                     onRegisterVolumeObserverForRcc(msg.arg1 /* rccId */,
                             (IRemoteVolumeObserver)msg.obj /* rvo */);
                     break;
+
+                case MSG_SET_RSX_CONNECTION_STATE:
+                    onSetRsxConnectionState(msg.arg1/*available*/, msg.arg2/*address*/);
+                    break;
+
+                case MSG_CHECK_MUSIC_ACTIVE:
+                    onCheckMusicActive();
+                    break;
+
+                case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
+                    onSendBecomingNoisyIntent();
+                    break;
+
+                case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED:
+                case MSG_CONFIGURE_SAFE_MEDIA_VOLUME:
+                    onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED));
+                    break;
             }
         }
     }
@@ -3121,6 +3434,8 @@
             super(new Handler());
             mContentResolver.registerContentObserver(Settings.System.getUriFor(
                 Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this);
+            mContentResolver.registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
         }
 
         @Override
@@ -3131,15 +3446,23 @@
             //       and mRingerModeAffectedStreams, so will leave this synchronized for now.
             //       mRingerModeMutedStreams and mMuteAffectedStreams are safe (only accessed once).
             synchronized (mSettingsLock) {
-                int ringerModeAffectedStreams = Settings.System.getInt(mContentResolver,
+                int ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
                        Settings.System.MODE_RINGER_STREAMS_AFFECTED,
                        ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
-                       (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)));
+                       (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
+                       UserHandle.USER_CURRENT);
                 if (mVoiceCapable) {
                     ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
                 } else {
                     ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
                 }
+                synchronized (mCameraSoundForced) {
+                    if (mCameraSoundForced) {
+                        ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+                    } else {
+                        ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+                    }
+                }
                 if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
                     /*
                      * Ensure all stream types that should be affected by ringer mode
@@ -3148,6 +3471,7 @@
                     mRingerModeAffectedStreams = ringerModeAffectedStreams;
                     setRingerModeInt(getRingerMode(), false);
                 }
+                readDockAudioSettings(mContentResolver);
             }
         }
     }
@@ -3166,8 +3490,8 @@
                 address);
     }
 
-    private void sendBecomingNoisyIntent() {
-        mContext.sendBroadcast(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
+    private void onSendBecomingNoisyIntent() {
+        sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
     }
 
     // must be called synchronized on mConnectedDevices
@@ -3286,7 +3610,9 @@
     // sent if none of these devices is connected.
     int mBecomingNoisyIntentDevices =
             AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
-            AudioSystem.DEVICE_OUT_ALL_A2DP;
+            AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_AUX_DIGITAL |
+            AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
+            AudioSystem.DEVICE_OUT_ALL_USB;
 
     // must be called before removing the device from mConnectedDevices
     private int checkSendBecomingNoisyIntent(int device, int state) {
@@ -3299,8 +3625,14 @@
                 }
             }
             if (devices == device) {
+                sendMsg(mAudioHandler,
+                        MSG_BROADCAST_AUDIO_BECOMING_NOISY,
+                        SENDMSG_REPLACE,
+                        0,
+                        0,
+                        null,
+                        0);
                 delay = 1000;
-                sendBecomingNoisyIntent();
             }
         }
 
@@ -3356,7 +3688,12 @@
             }
         }
 
-        ActivityManagerNative.broadcastStickyIntent(intent, null);
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
     }
 
     private void onSetWiredDeviceConnectionState(int device, int state, String name)
@@ -3366,12 +3703,26 @@
                     (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) {
                 setBluetoothA2dpOnInt(true);
             }
-            handleDeviceConnection((state == 1), device, "");
-            if ((state != 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
-                    (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) {
-                setBluetoothA2dpOnInt(false);
+            boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0);
+            handleDeviceConnection((state == 1), device, (isUsb ? name : ""));
+            if (state != 0) {
+                if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
+                    (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE)) {
+                    setBluetoothA2dpOnInt(false);
+                }
+                if ((device & mSafeMediaVolumeDevices) != 0) {
+                    sendMsg(mAudioHandler,
+                            MSG_CHECK_MUSIC_ACTIVE,
+                            SENDMSG_REPLACE,
+                            0,
+                            0,
+                            null,
+                            MUSIC_ACTIVE_POLL_PERIOD_MS);
+                }
             }
-            sendDeviceConnectionIntent(device, state, name);
+            if (!isUsb) {
+                sendDeviceConnectionIntent(device, state, name);
+            }
         }
     }
 
@@ -3400,7 +3751,13 @@
                         config = AudioSystem.FORCE_BT_CAR_DOCK;
                         break;
                     case Intent.EXTRA_DOCK_STATE_LE_DESK:
-                        config = AudioSystem.FORCE_ANALOG_DOCK;
+                        synchronized (mSettingsLock) {
+                            if (mDockAudioMediaEnabled) {
+                                config = AudioSystem.FORCE_ANALOG_DOCK;
+                            } else {
+                                config = AudioSystem.FORCE_NONE;
+                            }
+                        }
                         break;
                     case Intent.EXTRA_DOCK_STATE_HE_DESK:
                         config = AudioSystem.FORCE_DIGITAL_DOCK;
@@ -3409,6 +3766,7 @@
                     default:
                         config = AudioSystem.FORCE_NONE;
                 }
+
                 AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config);
             } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
                 state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
@@ -3463,7 +3821,7 @@
                         + (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
                               "ACTION_USB_AUDIO_ACCESSORY_PLUG" : "ACTION_USB_AUDIO_DEVICE_PLUG")
                         + ", state = " + state + ", card: " + alsaCard + ", device: " + alsaDevice);
-                handleDeviceConnection((state == 1), device, params);
+                setWiredDeviceConnectionState(device, state, params);
             } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
                 boolean broadcast = false;
                 int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
@@ -3508,7 +3866,7 @@
                     // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
                     Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
                     newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState);
-                    mContext.sendStickyBroadcast(newIntent);
+                    sendStickyBroadcastToAll(newIntent);
                 }
             } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
                 mBootCompleted = true;
@@ -3525,13 +3883,21 @@
                 Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
                 newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
                         AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
-                mContext.sendStickyBroadcast(newIntent);
+                sendStickyBroadcastToAll(newIntent);
 
                 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
                 if (adapter != null) {
                     adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
                                             BluetoothProfile.A2DP);
                 }
+
+                sendMsg(mAudioHandler,
+                        MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
+                        SENDMSG_REPLACE,
+                        0,
+                        0,
+                        null,
+                        SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
             } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) {
                 if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                     // a package is being removed, not replaced
@@ -3546,6 +3912,27 @@
                 AudioSystem.setParameters("screen_state=off");
             } else if (action.equalsIgnoreCase(Intent.ACTION_CONFIGURATION_CHANGED)) {
                 handleConfigurationChanged(context);
+            } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
+                // attempt to stop music playback for background user
+                sendMsg(mAudioHandler,
+                        MSG_BROADCAST_AUDIO_BECOMING_NOISY,
+                        SENDMSG_REPLACE,
+                        0,
+                        0,
+                        null,
+                        0);
+                // the current audio focus owner is no longer valid
+                discardAudioFocusOwner();
+
+                // load volume settings for new user
+                readAudioSettings(true /*userSwitch*/);
+                // preserve STREAM_MUSIC volume from one user to the next.
+                sendMsg(mAudioHandler,
+                        MSG_SET_ALL_VOLUMES,
+                        SENDMSG_QUEUE,
+                        0,
+                        0,
+                        mStreamStates[AudioSystem.STREAM_MUSIC], 0);
             }
         }
     }
@@ -3581,6 +3968,32 @@
         }
     };
 
+    /**
+     * Discard the current audio focus owner.
+     * Notify top of audio focus stack that it lost focus (regardless of possibility to reassign
+     * focus), remove it from the stack, and clear the remote control display.
+     */
+    private void discardAudioFocusOwner() {
+        synchronized(mAudioFocusLock) {
+            if (!mFocusStack.empty() && (mFocusStack.peek().mFocusDispatcher != null)) {
+                // notify the current focus owner it lost focus after removing it from stack
+                FocusStackEntry focusOwner = mFocusStack.pop();
+                try {
+                    focusOwner.mFocusDispatcher.dispatchAudioFocusChange(
+                            AudioManager.AUDIOFOCUS_LOSS, focusOwner.mClientId);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Failure to signal loss of audio focus due to "+ e);
+                    e.printStackTrace();
+                }
+                focusOwner.unlinkToDeath();
+                // clear RCD
+                synchronized(mRCStack) {
+                    clearRemoteControlDisplay_syncAfRcs();
+                }
+            }
+        }
+    }
+
     private void notifyTopOfAudioFocusStack() {
         // notify the top of the stack it gained focus
         if (!mFocusStack.empty() && (mFocusStack.peek().mFocusDispatcher != null)) {
@@ -3652,9 +4065,12 @@
             Iterator<FocusStackEntry> stackIterator = mFocusStack.iterator();
             while(stackIterator.hasNext()) {
                 FocusStackEntry fse = stackIterator.next();
-                pw.println("     source:" + fse.mSourceRef + " -- client: " + fse.mClientId
+                pw.println("  source:" + fse.mSourceRef
+                        + " -- pack: " + fse.mPackageName
+                        + " -- client: " + fse.mClientId
                         + " -- duration: " + fse.mFocusChangeType
-                        + " -- uid: " + fse.mCallingUid);
+                        + " -- uid: " + fse.mCallingUid
+                        + " -- stream: " + fse.mStreamType);
             }
         }
     }
@@ -3915,8 +4331,13 @@
             mMediaEventWakeLock.acquire();
             keyIntent.putExtra(EXTRA_WAKELOCK_ACQUIRED, WAKELOCK_RELEASE_ON_FINISHED);
         }
-        mContext.sendOrderedBroadcast(keyIntent, null, mKeyEventDone,
-                mAudioHandler, Activity.RESULT_OK, null, null);
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            mContext.sendOrderedBroadcastAsUser(keyIntent, UserHandle.ALL,
+                    null, mKeyEventDone, mAudioHandler, Activity.RESULT_OK, null, null);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
     }
 
     /**
@@ -3949,8 +4370,14 @@
                 if (needWakeLock) {
                     keyIntent.putExtra(EXTRA_WAKELOCK_ACQUIRED, WAKELOCK_RELEASE_ON_FINISHED);
                 }
-                mContext.sendOrderedBroadcast(keyIntent, null, mKeyEventDone,
-                        mAudioHandler, Activity.RESULT_OK, null, null);
+                final long ident = Binder.clearCallingIdentity();
+                try {
+                    mContext.sendOrderedBroadcastAsUser(keyIntent, UserHandle.ALL,
+                            null, mKeyEventDone,
+                            mAudioHandler, Activity.RESULT_OK, null, null);
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
             }
         }
     }
@@ -4014,7 +4441,7 @@
                 startVoiceBasedInteractions(needWakeLock);
                 break;
             case VOICEBUTTON_ACTION_SIMULATE_KEY_PRESS:
-                if (DEBUG_RC) Log.v(TAG, "   send simulated key event");
+                if (DEBUG_RC) Log.v(TAG, "   send simulated key event, wakelock=" + needWakeLock);
                 sendSimulatedMediaButtonEvent(keyEvent, needWakeLock);
                 break;
         }
@@ -4322,6 +4749,7 @@
             while(stackIterator.hasNext()) {
                 RemoteControlStackEntry rcse = stackIterator.next();
                 pw.println("  pi: " + rcse.mMediaIntent +
+                        " -- pack: " + rcse.mCallingPackageName +
                         "  -- ercvr: " + rcse.mReceiverComponent +
                         "  -- client: " + rcse.mRcClient +
                         "  -- uid: " + rcse.mCallingUid +
@@ -4350,7 +4778,7 @@
                         "  -- vol: " + rcse.mPlaybackVolume +
                         "  -- volMax: " + rcse.mPlaybackVolumeMax +
                         "  -- volObs: " + rcse.mRemoteVolumeObs);
-                
+
             }
         }
         synchronized (mMainRemote) {
@@ -4408,8 +4836,8 @@
      * Restore remote control receiver from the system settings.
      */
     private void restoreMediaButtonReceiver() {
-        String receiverName = Settings.System.getString(mContentResolver,
-                Settings.System.MEDIA_BUTTON_RECEIVER);
+        String receiverName = Settings.System.getStringForUser(mContentResolver,
+                Settings.System.MEDIA_BUTTON_RECEIVER, UserHandle.USER_CURRENT);
         if ((null != receiverName) && !receiverName.isEmpty()) {
             ComponentName eventReceiver = ComponentName.unflattenFromString(receiverName);
             // construct a PendingIntent targeted to the restored component name
@@ -4646,17 +5074,40 @@
             clearRemoteControlDisplay_syncAfRcs();
             return;
         }
-        // if the top of the two stacks belong to different packages, there is a mismatch, clear
+
+        // determine which entry in the AudioFocus stack to consider, and compare against the
+        // top of the stack for the media button event receivers : simply using the top of the
+        // stack would make the entry disappear from the RemoteControlDisplay in conditions such as
+        // notifications playing during music playback.
+        // crawl the AudioFocus stack until an entry is found with the following characteristics:
+        // - focus gain on STREAM_MUSIC stream
+        // - non-transient focus gain on a stream other than music
+        FocusStackEntry af = null;
+        Iterator<FocusStackEntry> stackIterator = mFocusStack.iterator();
+        while(stackIterator.hasNext()) {
+            FocusStackEntry fse = (FocusStackEntry)stackIterator.next();
+            if ((fse.mStreamType == AudioManager.STREAM_MUSIC)
+                    || (fse.mFocusChangeType == AudioManager.AUDIOFOCUS_GAIN)) {
+                af = fse;
+                break;
+            }
+        }
+        if (af == null) {
+            clearRemoteControlDisplay_syncAfRcs();
+            return;
+        }
+
+        // if the audio focus and RC owners belong to different packages, there is a mismatch, clear
         if ((mRCStack.peek().mCallingPackageName != null)
-                && (mFocusStack.peek().mPackageName != null)
+                && (af.mPackageName != null)
                 && !(mRCStack.peek().mCallingPackageName.compareTo(
-                        mFocusStack.peek().mPackageName) == 0)) {
+                        af.mPackageName) == 0)) {
             clearRemoteControlDisplay_syncAfRcs();
             return;
         }
         // if the audio focus didn't originate from the same Uid as the one in which the remote
         //   control information will be retrieved, clear
-        if (mRCStack.peek().mCallingUid != mFocusStack.peek().mCallingUid) {
+        if (mRCStack.peek().mCallingUid != af.mCallingUid) {
             clearRemoteControlDisplay_syncAfRcs();
             return;
         }
@@ -5252,10 +5703,62 @@
         try {
             // reading new orientation "safely" (i.e. under try catch) in case anything
             // goes wrong when obtaining resources and configuration
-            int newOrientation = context.getResources().getConfiguration().orientation;
-            if (newOrientation != mDeviceOrientation) {
-                mDeviceOrientation = newOrientation;
-                setOrientationForAudioSystem();
+            Configuration config = context.getResources().getConfiguration();
+            if (mMonitorOrientation) {
+                int newOrientation = config.orientation;
+                if (newOrientation != mDeviceOrientation) {
+                    mDeviceOrientation = newOrientation;
+                    setOrientationForAudioSystem();
+                }
+            }
+            sendMsg(mAudioHandler,
+                    MSG_CONFIGURE_SAFE_MEDIA_VOLUME,
+                    SENDMSG_REPLACE,
+                    0,
+                    0,
+                    null,
+                    0);
+
+            boolean cameraSoundForced = mContext.getResources().getBoolean(
+                    com.android.internal.R.bool.config_camera_sound_forced);
+            synchronized (mSettingsLock) {
+                synchronized (mCameraSoundForced) {
+                    if (cameraSoundForced != mCameraSoundForced) {
+                        mCameraSoundForced = cameraSoundForced;
+
+                        VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
+                        if (cameraSoundForced) {
+                            s.setAllIndexesToMax();
+                            mRingerModeAffectedStreams &=
+                                    ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+                        } else {
+                            s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM],
+                                            false /*lastAudible*/);
+                            s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM],
+                                            true /*lastAudible*/);
+                            mRingerModeAffectedStreams |=
+                                    (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+                        }
+                        // take new state into account for streams muted by ringer mode
+                        setRingerModeInt(getRingerMode(), false);
+
+                        sendMsg(mAudioHandler,
+                                MSG_SET_FORCE_USE,
+                                SENDMSG_QUEUE,
+                                AudioSystem.FOR_SYSTEM,
+                                cameraSoundForced ?
+                                        AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
+                                null,
+                                0);
+
+                        sendMsg(mAudioHandler,
+                                MSG_SET_ALL_VOLUMES,
+                                SENDMSG_QUEUE,
+                                0,
+                                0,
+                                mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
+                    }
+                }
             }
         } catch (Exception e) {
             Log.e(TAG, "Error retrieving device orientation: " + e);
@@ -5290,10 +5793,9 @@
     public void setBluetoothA2dpOnInt(boolean on) {
         synchronized (mBluetoothA2dpEnabledLock) {
             mBluetoothA2dpEnabled = on;
-            sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
-                    AudioSystem.FOR_MEDIA,
-                    mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
-                    null, 0);
+            mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE);
+            AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,
+                    mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP);
         }
     }
 
@@ -5317,6 +5819,154 @@
         }
     }
 
+
+    //==========================================================================================
+    // Safe media volume management.
+    // MUSIC stream volume level is limited when headphones are connected according to safety
+    // regulation. When the user attempts to raise the volume above the limit, a warning is
+    // displayed and the user has to acknowlegde before the volume is actually changed.
+    // The volume index corresponding to the limit is stored in config_safe_media_volume_index
+    // property. Platforms with a different limit must set this property accordingly in their
+    // overlay.
+    //==========================================================================================
+
+    // mSafeMediaVolumeState indicates whether the media volume is limited over headphones.
+    // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected
+    // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or
+    // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it
+    // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume()
+    // (when user opts out).
+    private final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
+    private final int SAFE_MEDIA_VOLUME_DISABLED = 1;
+    private final int SAFE_MEDIA_VOLUME_INACTIVE = 2;
+    private final int SAFE_MEDIA_VOLUME_ACTIVE = 3;
+    private Integer mSafeMediaVolumeState;
+
+    private int mMcc = 0;
+    // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
+    private int mSafeMediaVolumeIndex;
+    // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
+    private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET |
+                                                AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
+    // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
+    // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
+    // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
+    private int mMusicActiveMs;
+    private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
+    private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000;  // 1 minute polling interval
+    private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000;  // 30s after boot completed
+
+    private void setSafeMediaVolumeEnabled(boolean on) {
+        synchronized (mSafeMediaVolumeState) {
+            if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) &&
+                    (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) {
+                if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) {
+                    mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
+                    enforceSafeMediaVolume();
+                } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) {
+                    mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
+                    mMusicActiveMs = 0;
+                    sendMsg(mAudioHandler,
+                            MSG_CHECK_MUSIC_ACTIVE,
+                            SENDMSG_REPLACE,
+                            0,
+                            0,
+                            null,
+                            MUSIC_ACTIVE_POLL_PERIOD_MS);
+                }
+            }
+        }
+    }
+
+    private void enforceSafeMediaVolume() {
+        VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
+        boolean lastAudible = (streamState.muteCount() != 0);
+        int devices = mSafeMediaVolumeDevices;
+        int i = 0;
+
+        while (devices != 0) {
+            int device = 1 << i++;
+            if ((device & devices) == 0) {
+                continue;
+            }
+            int index = streamState.getIndex(device, lastAudible);
+            if (index > mSafeMediaVolumeIndex) {
+                if (lastAudible) {
+                    streamState.setLastAudibleIndex(mSafeMediaVolumeIndex, device);
+                    sendMsg(mAudioHandler,
+                            MSG_PERSIST_VOLUME,
+                            SENDMSG_QUEUE,
+                            PERSIST_LAST_AUDIBLE,
+                            device,
+                            streamState,
+                            PERSIST_DELAY);
+                } else {
+                    streamState.setIndex(mSafeMediaVolumeIndex, device, true);
+                    sendMsg(mAudioHandler,
+                            MSG_SET_DEVICE_VOLUME,
+                            SENDMSG_QUEUE,
+                            device,
+                            0,
+                            streamState,
+                            0);
+                }
+            }
+            devices &= ~device;
+        }
+    }
+
+    private boolean checkSafeMediaVolume(int streamType, int index, int device) {
+        synchronized (mSafeMediaVolumeState) {
+            if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
+                    (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
+                    ((device & mSafeMediaVolumeDevices) != 0) &&
+                    (index > mSafeMediaVolumeIndex)) {
+                mVolumePanel.postDisplaySafeVolumeWarning();
+                return false;
+            }
+            return true;
+        }
+    }
+
+    public void disableSafeMediaVolume() {
+        synchronized (mSafeMediaVolumeState) {
+            setSafeMediaVolumeEnabled(false);
+        }
+    }
+
+
+    //==========================================================================================
+    // Camera shutter sound policy.
+    // config_camera_sound_forced configuration option in config.xml defines if the camera shutter
+    // sound is forced (sound even if the device is in silent mode) or not. This option is false by
+    // default and can be overridden by country specific overlay in values-mccXXX/config.xml.
+    //==========================================================================================
+
+    // cached value of com.android.internal.R.bool.config_camera_sound_forced
+    private Boolean mCameraSoundForced;
+
+    // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound
+    public boolean isCameraSoundForced() {
+        synchronized (mCameraSoundForced) {
+            return mCameraSoundForced;
+        }
+    }
+
+    private static final String[] RINGER_MODE_NAMES = new String[] {
+            "SILENT",
+            "VIBRATE",
+            "NORMAL"
+    };
+
+    private void dumpRingerMode(PrintWriter pw) {
+        pw.println("\nRinger mode: ");
+        pw.println("- mode: "+RINGER_MODE_NAMES[mRingerMode]);
+        pw.print("- ringer mode affected streams = 0x");
+        pw.println(Integer.toHexString(mRingerModeAffectedStreams));
+        pw.print("- ringer mode muted streams = 0x");
+        pw.println(Integer.toHexString(mRingerModeMutedStreams));
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
@@ -5325,6 +5975,7 @@
         dumpRCStack(pw);
         dumpRCCStack(pw);
         dumpStreamStates(pw);
+        dumpRingerMode(pw);
         pw.println("\nAudio routes:");
         pw.print("  mMainType=0x"); pw.println(Integer.toHexString(mCurAudioRoutes.mMainType));
         pw.print("  mBluetoothName="); pw.println(mCurAudioRoutes.mBluetoothName);
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 1ca0df4..dde2979 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -111,6 +111,13 @@
     public static native boolean isStreamActive(int stream, int inPastMs);
 
     /*
+     * Checks whether the specified audio source is active.
+     *
+     * return true if any recorder using this source is currently recording
+     */
+    public static native boolean isSourceActive(int source);
+
+    /*
      * Sets a group generic audio configuration parameters. The use of these parameters
      * are platform dependent, see libaudio
      *
@@ -188,6 +195,13 @@
      * AudioPolicyService methods
      */
 
+    //
+    // audio device definitions: must be kept in sync with values in system/core/audio.h
+    //
+
+    // reserved bits
+    public static final int DEVICE_BIT_IN = 0x80000000;
+    public static final int DEVICE_BIT_DEFAULT = 0x40000000;
     // output devices, be sure to update AudioManager.java also
     public static final int DEVICE_OUT_EARPIECE = 0x1;
     public static final int DEVICE_OUT_SPEAKER = 0x2;
@@ -204,8 +218,10 @@
     public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000;
     public static final int DEVICE_OUT_USB_ACCESSORY = 0x2000;
     public static final int DEVICE_OUT_USB_DEVICE = 0x4000;
+    public static final int DEVICE_OUT_REMOTE_SUBMIX = 0x8000;
 
-    public static final int DEVICE_OUT_DEFAULT = 0x8000;
+    public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT;
+
     public static final int DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE |
                                               DEVICE_OUT_SPEAKER |
                                               DEVICE_OUT_WIRED_HEADSET |
@@ -221,6 +237,7 @@
                                               DEVICE_OUT_DGTL_DOCK_HEADSET |
                                               DEVICE_OUT_USB_ACCESSORY |
                                               DEVICE_OUT_USB_DEVICE |
+                                              DEVICE_OUT_REMOTE_SUBMIX |
                                               DEVICE_OUT_DEFAULT);
     public static final int DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP |
                                                    DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
@@ -232,15 +249,36 @@
                                                   DEVICE_OUT_USB_DEVICE);
 
     // input devices
-    public static final int DEVICE_IN_COMMUNICATION = 0x10000;
-    public static final int DEVICE_IN_AMBIENT = 0x20000;
-    public static final int DEVICE_IN_BUILTIN_MIC1 = 0x40000;
-    public static final int DEVICE_IN_BUILTIN_MIC2 = 0x80000;
-    public static final int DEVICE_IN_MIC_ARRAY = 0x100000;
-    public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x200000;
-    public static final int DEVICE_IN_WIRED_HEADSET = 0x400000;
-    public static final int DEVICE_IN_AUX_DIGITAL = 0x800000;
-    public static final int DEVICE_IN_DEFAULT = 0x80000000;
+    public static final int DEVICE_IN_COMMUNICATION = DEVICE_BIT_IN | 0x1;
+    public static final int DEVICE_IN_AMBIENT = DEVICE_BIT_IN | 0x2;
+    public static final int DEVICE_IN_BUILTIN_MIC = DEVICE_BIT_IN | 0x4;
+    public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET = DEVICE_BIT_IN | 0x8;
+    public static final int DEVICE_IN_WIRED_HEADSET = DEVICE_BIT_IN | 0x10;
+    public static final int DEVICE_IN_AUX_DIGITAL = DEVICE_BIT_IN | 0x20;
+    public static final int DEVICE_IN_VOICE_CALL = DEVICE_BIT_IN | 0x40;
+    public static final int DEVICE_IN_BACK_MIC = DEVICE_BIT_IN | 0x80;
+    public static final int DEVICE_IN_REMOTE_SUBMIX = DEVICE_BIT_IN | 0x100;
+    public static final int DEVICE_IN_ANLG_DOCK_HEADSET = DEVICE_BIT_IN | 0x200;
+    public static final int DEVICE_IN_DGTL_DOCK_HEADSET = DEVICE_BIT_IN | 0x400;
+    public static final int DEVICE_IN_USB_ACCESSORY = DEVICE_BIT_IN | 0x800;
+    public static final int DEVICE_IN_USB_DEVICE = DEVICE_BIT_IN | 0x1000;
+    public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT;
+
+    public static final int DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION |
+                                             DEVICE_IN_AMBIENT |
+                                             DEVICE_IN_BUILTIN_MIC |
+                                             DEVICE_IN_BLUETOOTH_SCO_HEADSET |
+                                             DEVICE_IN_WIRED_HEADSET |
+                                             DEVICE_IN_AUX_DIGITAL |
+                                             DEVICE_IN_VOICE_CALL |
+                                             DEVICE_IN_BACK_MIC |
+                                             DEVICE_IN_REMOTE_SUBMIX |
+                                             DEVICE_IN_ANLG_DOCK_HEADSET |
+                                             DEVICE_IN_DGTL_DOCK_HEADSET |
+                                             DEVICE_IN_USB_ACCESSORY |
+                                             DEVICE_IN_USB_DEVICE |
+                                             DEVICE_IN_DEFAULT);
+    public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET;
 
     // device states, must match AudioSystem::device_connection_state
     public static final int DEVICE_STATE_UNAVAILABLE = 0;
@@ -262,6 +300,7 @@
     public static final String DEVICE_OUT_DGTL_DOCK_HEADSET_NAME = "digital_dock";
     public static final String DEVICE_OUT_USB_ACCESSORY_NAME = "usb_accessory";
     public static final String DEVICE_OUT_USB_DEVICE_NAME = "usb_device";
+    public static final String DEVICE_OUT_REMOTE_SUBMIX_NAME = "remote_submix";
 
     public static String getDeviceName(int device)
     {
@@ -296,7 +335,9 @@
             return DEVICE_OUT_USB_ACCESSORY_NAME;
         case DEVICE_OUT_USB_DEVICE:
             return DEVICE_OUT_USB_DEVICE_NAME;
-        case DEVICE_IN_DEFAULT:
+        case DEVICE_OUT_REMOTE_SUBMIX:
+            return DEVICE_OUT_REMOTE_SUBMIX_NAME;
+        case DEVICE_OUT_DEFAULT:
         default:
             return "";
         }
@@ -319,7 +360,8 @@
     public static final int FORCE_ANALOG_DOCK = 8;
     public static final int FORCE_DIGITAL_DOCK = 9;
     public static final int FORCE_NO_BT_A2DP = 10;
-    private static final int NUM_FORCE_CONFIG = 11;
+    public static final int FORCE_SYSTEM_ENFORCED = 11;
+    private static final int NUM_FORCE_CONFIG = 12;
     public static final int FORCE_DEFAULT = FORCE_NONE;
 
     // usage for setForceUse, must match AudioSystem::force_use
@@ -327,7 +369,8 @@
     public static final int FOR_MEDIA = 1;
     public static final int FOR_RECORD = 2;
     public static final int FOR_DOCK = 3;
-    private static final int NUM_FORCE_USE = 4;
+    public static final int FOR_SYSTEM = 4;
+    private static final int NUM_FORCE_USE = 5;
 
     // usage for AudioRecord.startRecordingSync(), must match AudioSystem::sync_event_t
     public static final int SYNC_EVENT_NONE = 0;
@@ -346,4 +389,9 @@
     public static native int setMasterMute(boolean mute);
     public static native boolean getMasterMute();
     public static native int getDevicesForStream(int stream);
+
+    // helpers for android.media.AudioManager.getProperty(), see description there for meaning
+    public static native int getPrimaryOutputSamplingRate();
+    public static native int getPrimaryOutputFrameCount();
+
 }
diff --git a/media/java/android/media/DataSource.java b/media/java/android/media/DataSource.java
new file mode 100644
index 0000000..347bd5f
--- /dev/null
+++ b/media/java/android/media/DataSource.java
@@ -0,0 +1,43 @@
+/*
+ * 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.media;
+
+import java.io.Closeable;
+
+/**
+ * An abstraction for a media data source, e.g. a file or an http stream
+ * {@hide}
+ */
+public interface DataSource extends Closeable {
+    /**
+     * Reads data from the data source at the requested position
+     *
+     * @param offset where in the source to read
+     * @param buffer the buffer to read the data into
+     * @param size how many bytes to read
+     * @return the number of bytes read, or -1 if there was an error
+     */
+    public int readAt(long offset, byte[] buffer, int size);
+
+    /**
+     * Gets the size of the data source.
+     *
+     * @return size of data source, or -1 if the length is unknown
+     */
+    public long getSize();
+}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 854eb3f..ea99069 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -108,6 +108,8 @@
 
     boolean isBluetoothA2dpOn();
 
+    oneway void setRemoteSubmixOn(boolean on, int address);
+
     int requestAudioFocus(int mainStreamType, int durationHint, IBinder cb, IAudioFocusDispatcher l,
             String clientId, String callingPackageName);
 
@@ -151,4 +153,6 @@
     int setBluetoothA2dpDeviceConnectionState(in BluetoothDevice device, int state);
 
     AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer);
+
+    boolean isCameraSoundForced();
 }
diff --git a/media/java/android/media/IRingtonePlayer.aidl b/media/java/android/media/IRingtonePlayer.aidl
index 44a0333..0872f1d 100644
--- a/media/java/android/media/IRingtonePlayer.aidl
+++ b/media/java/android/media/IRingtonePlayer.aidl
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.net.Uri;
+import android.os.UserHandle;
 
 /**
  * @hide
@@ -28,6 +29,6 @@
     boolean isPlaying(IBinder token);
 
     /** Used for Notification sound playback. */
-    void playAsync(in Uri uri, boolean looping, int streamType);
+    void playAsync(in Uri uri, in UserHandle user, boolean looping, int streamType);
     void stopAsync();
 }
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 687d3a5..749ef12 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -22,6 +22,7 @@
 import android.media.MediaCodec;
 import android.media.MediaFormat;
 import android.net.Uri;
+
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -44,7 +45,7 @@
  * }
  * ByteBuffer inputBuffer = ByteBuffer.allocate(...)
  * while (extractor.readSampleData(inputBuffer, ...) &gt;= 0) {
- *   int trackIndex = extractor.getTrackIndex();
+ *   int trackIndex = extractor.getSampleTrackIndex();
  *   long presentationTimeUs = extractor.getSampleTime();
  *   ...
  *   extractor.advance();
@@ -60,6 +61,12 @@
     }
 
     /**
+     * Sets the DataSource object to be used as the data source for this extractor
+     * {@hide}
+     */
+    public native final void setDataSource(DataSource source);
+
+    /**
      * Sets the data source as a content Uri.
      *
      * @param context the Context to use when resolving the Uri
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index d21ada4..06d43a2 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -325,7 +325,7 @@
         }
         int lastDot = fileName.lastIndexOf('.');
         if (lastDot > 0) {
-            String extension = fileName.substring(lastDot + 1);
+            String extension = fileName.substring(lastDot + 1).toUpperCase();
             Integer value = sFileTypeToFormatMap.get(extension);
             if (value != null) {
                 return value.intValue();
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index aef631f..cc59d02 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -483,5 +483,10 @@
      * of 180 degrees will be retrieved as "-90.0000+180.0000", for instance.
      */
     public static final int METADATA_KEY_LOCATION        = 23;
+    /**
+     * This key retrieves the video rotation angle in degrees, if available.
+     * The video rotation angle may be 0, 90, 180, or 270 degrees.
+     */
+    public static final int METADATA_KEY_VIDEO_ROTATION = 24;
     // Add more here...
 }
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index cd25865b..ef0da3a 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2265,6 +2265,16 @@
      */
     public static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200;
 
+    /** File or network related operation errors. */
+    public static final int MEDIA_ERROR_IO = -1004;
+    /** Bitstream is not conforming to the related coding standard or file spec. */
+    public static final int MEDIA_ERROR_MALFORMED = -1007;
+    /** Bitstream is conforming to the related coding standard or file spec, but
+     * the media framework does not support the feature. */
+    public static final int MEDIA_ERROR_UNSUPPORTED = -1010;
+    /** Some operation takes too long to complete, usually more than 3-5 seconds. */
+    public static final int MEDIA_ERROR_TIMED_OUT = -110;
+
     /**
      * Interface definition of a callback to be invoked when there
      * has been an error during an asynchronous operation (other errors
@@ -2282,7 +2292,13 @@
          * <li>{@link #MEDIA_ERROR_SERVER_DIED}
          * </ul>
          * @param extra an extra code, specific to the error. Typically
-         * implementation dependant.
+         * implementation dependent.
+         * <ul>
+         * <li>{@link #MEDIA_ERROR_IO}
+         * <li>{@link #MEDIA_ERROR_MALFORMED}
+         * <li>{@link #MEDIA_ERROR_UNSUPPORTED}
+         * <li>{@link #MEDIA_ERROR_TIMED_OUT}
+         * </ul>
          * @return True if the method handled the error, false if it didn't.
          * Returning false, or not having an OnErrorListener at all, will
          * cause the OnCompletionListener to be called.
@@ -2319,6 +2335,11 @@
      */
     public static final int MEDIA_INFO_STARTED_AS_NEXT = 2;
 
+    /** The player just pushed the very first video frame for rendering.
+     * @see android.media.MediaPlayer.OnInfoListener
+     */
+    public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3;
+
     /** The video is too complex for the decoder: it can't decode frames fast
      *  enough. Possibly only the audio plays fine at this stage.
      * @see android.media.MediaPlayer.OnInfoListener
@@ -2374,6 +2395,7 @@
          * <ul>
          * <li>{@link #MEDIA_INFO_UNKNOWN}
          * <li>{@link #MEDIA_INFO_VIDEO_TRACK_LAGGING}
+         * <li>{@link #MEDIA_INFO_VIDEO_RENDERING_START}
          * <li>{@link #MEDIA_INFO_BUFFERING_START}
          * <li>{@link #MEDIA_INFO_BUFFERING_END}
          * <li>{@link #MEDIA_INFO_BAD_INTERLEAVING}
@@ -2381,7 +2403,7 @@
          * <li>{@link #MEDIA_INFO_METADATA_UPDATE}
          * </ul>
          * @param extra an extra code, specific to the info. Typically
-         * implementation dependant.
+         * implementation dependent.
          * @return True if the method handled the info, false if it didn't.
          * Returning false, or not having an OnErrorListener at all, will
          * cause the info to be discarded.
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 613354f..48bea52 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -177,6 +177,12 @@
          *  is applied.
          */
         public static final int VOICE_COMMUNICATION = 7;
+
+        /**
+         * @hide
+         * Audio source for remote submix.
+         */
+        public static final int REMOTE_SUBMIX_SOURCE = 8;
     }
 
     /**
@@ -291,7 +297,12 @@
      * Gets the maximum value for audio sources.
      * @see android.media.MediaRecorder.AudioSource
      */
-    public static final int getAudioSourceMax() { return AudioSource.VOICE_COMMUNICATION; }
+    public static final int getAudioSourceMax() {
+        // FIXME disable selection of the remote submxi source selection once test code
+        //       doesn't rely on it
+        return AudioSource.REMOTE_SUBMIX_SOURCE;
+        //return AudioSource.VOICE_COMMUNICATION;
+    }
 
     /**
      * Sets the video source to be used for recording. If this method is not
@@ -720,12 +731,17 @@
     public native int getMaxAmplitude() throws IllegalStateException;
 
     /* Do not change this value without updating its counterpart
-     * in include/media/mediarecorder.h!
+     * in include/media/mediarecorder.h or mediaplayer.h!
      */
     /** Unspecified media recorder error.
      * @see android.media.MediaRecorder.OnErrorListener
      */
     public static final int MEDIA_RECORDER_ERROR_UNKNOWN = 1;
+    /** Media server died. In this case, the application must release the
+     * MediaRecorder object and instantiate a new one.
+     * @see android.media.MediaRecorder.OnErrorListener
+     */
+    public static final int MEDIA_ERROR_SERVER_DIED = 100;
 
     /**
      * Interface definition for a callback to be invoked when an error
@@ -740,6 +756,7 @@
          * @param what    the type of error that has occurred:
          * <ul>
          * <li>{@link #MEDIA_RECORDER_ERROR_UNKNOWN}
+         * <li>{@link #MEDIA_ERROR_SERVER_DIED}
          * </ul>
          * @param extra   an extra code, specific to the error type
          */
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index a256079..2a5a16e 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -22,12 +22,16 @@
 import android.content.IntentFilter;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.WifiDisplay;
+import android.hardware.display.WifiDisplayStatus;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.text.TextUtils;
 import android.util.Log;
+import android.view.Display;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -48,9 +52,10 @@
 public class MediaRouter {
     private static final String TAG = "MediaRouter";
 
-    static class Static {
+    static class Static implements DisplayManager.DisplayListener {
         final Resources mResources;
         final IAudioService mAudioService;
+        final DisplayManager mDisplayService;
         final Handler mHandler;
         final CopyOnWriteArrayList<CallbackInfo> mCallbacks =
                 new CopyOnWriteArrayList<CallbackInfo>();
@@ -60,18 +65,20 @@
 
         final RouteCategory mSystemCategory;
 
-        final AudioRoutesInfo mCurRoutesInfo = new AudioRoutesInfo();
+        final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo();
 
-        RouteInfo mDefaultAudio;
+        RouteInfo mDefaultAudioVideo;
         RouteInfo mBluetoothA2dpRoute;
 
         RouteInfo mSelectedRoute;
 
-        final IAudioRoutesObserver.Stub mRoutesObserver = new IAudioRoutesObserver.Stub() {
+        WifiDisplayStatus mLastKnownWifiDisplayStatus;
+
+        final IAudioRoutesObserver.Stub mAudioRoutesObserver = new IAudioRoutesObserver.Stub() {
             public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
                 mHandler.post(new Runnable() {
                     @Override public void run() {
-                        updateRoutes(newRoutes);
+                        updateAudioRoutes(newRoutes);
                     }
                 });
             }
@@ -84,34 +91,55 @@
             IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
             mAudioService = IAudioService.Stub.asInterface(b);
 
+            mDisplayService = (DisplayManager) appContext.getSystemService(Context.DISPLAY_SERVICE);
+
             mSystemCategory = new RouteCategory(
                     com.android.internal.R.string.default_audio_route_category_name,
-                    ROUTE_TYPE_LIVE_AUDIO, false);
+                    ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO, false);
+            mSystemCategory.mIsSystem = true;
         }
 
         // Called after sStatic is initialized
         void startMonitoringRoutes(Context appContext) {
-            mDefaultAudio = new RouteInfo(mSystemCategory);
-            mDefaultAudio.mNameResId = com.android.internal.R.string.default_audio_route_name;
-            mDefaultAudio.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO;
-            addRoute(mDefaultAudio);
+            mDefaultAudioVideo = new RouteInfo(mSystemCategory);
+            mDefaultAudioVideo.mNameResId = com.android.internal.R.string.default_audio_route_name;
+            mDefaultAudioVideo.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO;
+            mDefaultAudioVideo.mPresentationDisplay = choosePresentationDisplayForRoute(
+                    mDefaultAudioVideo, getAllPresentationDisplays());
+            addRouteStatic(mDefaultAudioVideo);
 
+            // This will select the active wifi display route if there is one.
+            updateWifiDisplayStatus(mDisplayService.getWifiDisplayStatus());
+
+            appContext.registerReceiver(new WifiDisplayStatusChangedReceiver(),
+                    new IntentFilter(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED));
             appContext.registerReceiver(new VolumeChangeReceiver(),
                     new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION));
 
-            AudioRoutesInfo newRoutes = null;
+            mDisplayService.registerDisplayListener(this, mHandler);
+
+            AudioRoutesInfo newAudioRoutes = null;
             try {
-                newRoutes = mAudioService.startWatchingRoutes(mRoutesObserver);
+                newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
             } catch (RemoteException e) {
             }
-            if (newRoutes != null) {
-                updateRoutes(newRoutes);
+            if (newAudioRoutes != null) {
+                // This will select the active BT route if there is one and the current
+                // selected route is the default system route, or if there is no selected
+                // route yet.
+                updateAudioRoutes(newAudioRoutes);
+            }
+
+            // Select the default route if the above didn't sync us up
+            // appropriately with relevant system state.
+            if (mSelectedRoute == null) {
+                selectRouteStatic(mDefaultAudioVideo.getSupportedTypes(), mDefaultAudioVideo);
             }
         }
 
-        void updateRoutes(AudioRoutesInfo newRoutes) {
-            if (newRoutes.mMainType != mCurRoutesInfo.mMainType) {
-                mCurRoutesInfo.mMainType = newRoutes.mMainType;
+        void updateAudioRoutes(AudioRoutesInfo newRoutes) {
+            if (newRoutes.mMainType != mCurAudioRoutesInfo.mMainType) {
+                mCurAudioRoutesInfo.mMainType = newRoutes.mMainType;
                 int name;
                 if ((newRoutes.mMainType&AudioRoutesInfo.MAIN_HEADPHONES) != 0
                         || (newRoutes.mMainType&AudioRoutesInfo.MAIN_HEADSET) != 0) {
@@ -119,14 +147,16 @@
                 } else if ((newRoutes.mMainType&AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
                     name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
                 } else if ((newRoutes.mMainType&AudioRoutesInfo.MAIN_HDMI) != 0) {
-                    name = com.android.internal.R.string.default_audio_route_name_hdmi;
+                    name = com.android.internal.R.string.default_media_route_name_hdmi;
                 } else {
                     name = com.android.internal.R.string.default_audio_route_name;
                 }
-                sStatic.mDefaultAudio.mNameResId = name;
-                dispatchRouteChanged(sStatic.mDefaultAudio);
+                sStatic.mDefaultAudioVideo.mNameResId = name;
+                dispatchRouteChanged(sStatic.mDefaultAudioVideo);
             }
 
+            final int mainType = mCurAudioRoutesInfo.mMainType;
+
             boolean a2dpEnabled;
             try {
                 a2dpEnabled = mAudioService.isBluetoothA2dpOn();
@@ -135,17 +165,17 @@
                 a2dpEnabled = false;
             }
 
-            if (!TextUtils.equals(newRoutes.mBluetoothName, mCurRoutesInfo.mBluetoothName)) {
-                mCurRoutesInfo.mBluetoothName = newRoutes.mBluetoothName;
-                if (mCurRoutesInfo.mBluetoothName != null) {
+            if (!TextUtils.equals(newRoutes.mBluetoothName, mCurAudioRoutesInfo.mBluetoothName)) {
+                mCurAudioRoutesInfo.mBluetoothName = newRoutes.mBluetoothName;
+                if (mCurAudioRoutesInfo.mBluetoothName != null) {
                     if (sStatic.mBluetoothA2dpRoute == null) {
                         final RouteInfo info = new RouteInfo(sStatic.mSystemCategory);
-                        info.mName = mCurRoutesInfo.mBluetoothName;
+                        info.mName = mCurAudioRoutesInfo.mBluetoothName;
                         info.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO;
                         sStatic.mBluetoothA2dpRoute = info;
-                        addRoute(sStatic.mBluetoothA2dpRoute);
+                        addRouteStatic(sStatic.mBluetoothA2dpRoute);
                     } else {
-                        sStatic.mBluetoothA2dpRoute.mName = mCurRoutesInfo.mBluetoothName;
+                        sStatic.mBluetoothA2dpRoute.mName = mCurAudioRoutesInfo.mBluetoothName;
                         dispatchRouteChanged(sStatic.mBluetoothA2dpRoute);
                     }
                 } else if (sStatic.mBluetoothA2dpRoute != null) {
@@ -155,15 +185,48 @@
             }
 
             if (mBluetoothA2dpRoute != null) {
-                if (mCurRoutesInfo.mMainType != AudioRoutesInfo.MAIN_SPEAKER &&
-                        mSelectedRoute == mBluetoothA2dpRoute) {
-                    selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudio);
-                } else if (mCurRoutesInfo.mMainType == AudioRoutesInfo.MAIN_SPEAKER &&
-                        mSelectedRoute == mDefaultAudio && a2dpEnabled) {
+                if (mainType != AudioRoutesInfo.MAIN_SPEAKER &&
+                        mSelectedRoute == mBluetoothA2dpRoute && !a2dpEnabled) {
+                    selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo);
+                } else if ((mSelectedRoute == mDefaultAudioVideo || mSelectedRoute == null) &&
+                        a2dpEnabled) {
                     selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mBluetoothA2dpRoute);
                 }
             }
         }
+
+        @Override
+        public void onDisplayAdded(int displayId) {
+            updatePresentationDisplays(displayId);
+        }
+
+        @Override
+        public void onDisplayChanged(int displayId) {
+            updatePresentationDisplays(displayId);
+        }
+
+        @Override
+        public void onDisplayRemoved(int displayId) {
+            updatePresentationDisplays(displayId);
+        }
+
+        public Display[] getAllPresentationDisplays() {
+            return mDisplayService.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
+        }
+
+        private void updatePresentationDisplays(int changedDisplayId) {
+            final Display[] displays = getAllPresentationDisplays();
+            final int count = mRoutes.size();
+            for (int i = 0; i < count; i++) {
+                final RouteInfo info = mRoutes.get(i);
+                Display display = choosePresentationDisplayForRoute(info, displays);
+                if (display != info.mPresentationDisplay
+                        || (display != null && display.getDisplayId() == changedDisplayId)) {
+                    info.mPresentationDisplay = display;
+                    dispatchRoutePresentationDisplayChanged(info);
+                }
+            }
+        }
     }
 
     static Static sStatic;
@@ -181,6 +244,23 @@
     public static final int ROUTE_TYPE_LIVE_AUDIO = 0x1;
 
     /**
+     * Route type flag for live video.
+     *
+     * <p>A device that supports live video routing will allow a mirrored version
+     * of the device's primary display or a customized
+     * {@link android.app.Presentation Presentation} to be routed to supported destinations.</p>
+     *
+     * <p>Once initiated, display mirroring is transparent to the application.
+     * While remote routing is active the application may use a
+     * {@link android.app.Presentation Presentation} to replace the mirrored view
+     * on the external display with different content.</p>
+     *
+     * @see RouteInfo#getPresentationDisplay()
+     * @see android.app.Presentation
+     */
+    public static final int ROUTE_TYPE_LIVE_VIDEO = 0x2;
+
+    /**
      * Route type flag for application-specific usage.
      *
      * <p>Unlike other media route types, user routes are managed by the application.
@@ -198,6 +278,9 @@
         if ((types & ROUTE_TYPE_LIVE_AUDIO) != 0) {
             result.append("ROUTE_TYPE_LIVE_AUDIO ");
         }
+        if ((types & ROUTE_TYPE_LIVE_VIDEO) != 0) {
+            result.append("ROUTE_TYPE_LIVE_VIDEO ");
+        }
         if ((types & ROUTE_TYPE_USER) != 0) {
             result.append("ROUTE_TYPE_USER ");
         }
@@ -219,7 +302,7 @@
      * @hide for use by framework routing UI
      */
     public RouteInfo getSystemAudioRoute() {
-        return sStatic.mDefaultAudio;
+        return sStatic.mDefaultAudioVideo;
     }
 
     /**
@@ -296,7 +379,8 @@
     }
 
     static void selectRouteStatic(int types, RouteInfo route) {
-        if (sStatic.mSelectedRoute == route) return;
+        final RouteInfo oldRoute = sStatic.mSelectedRoute;
+        if (oldRoute == route) return;
         if ((route.getSupportedTypes() & types) == 0) {
             Log.w(TAG, "selectRoute ignored; cannot select route with supported types " +
                     typesToString(route.getSupportedTypes()) + " into route types " +
@@ -306,7 +390,7 @@
 
         final RouteInfo btRoute = sStatic.mBluetoothA2dpRoute;
         if (btRoute != null && (types & ROUTE_TYPE_LIVE_AUDIO) != 0 &&
-                (route == btRoute || route == sStatic.mDefaultAudio)) {
+                (route == btRoute || route == sStatic.mDefaultAudioVideo)) {
             try {
                 sStatic.mAudioService.setBluetoothA2dpOn(route == btRoute);
             } catch (RemoteException e) {
@@ -314,10 +398,21 @@
             }
         }
 
-        if (sStatic.mSelectedRoute != null) {
+        final WifiDisplay activeDisplay =
+                sStatic.mDisplayService.getWifiDisplayStatus().getActiveDisplay();
+        final boolean oldRouteHasAddress = oldRoute != null && oldRoute.mDeviceAddress != null;
+        final boolean newRouteHasAddress = route != null && route.mDeviceAddress != null;
+        if (activeDisplay != null || oldRouteHasAddress || newRouteHasAddress) {
+            if (newRouteHasAddress && !matchesDeviceAddress(activeDisplay, route)) {
+                sStatic.mDisplayService.connectWifiDisplay(route.mDeviceAddress);
+            } else if (activeDisplay != null && !newRouteHasAddress) {
+                sStatic.mDisplayService.disconnectWifiDisplay();
+            }
+        }
+
+        if (oldRoute != null) {
             // TODO filter types properly
-            dispatchRouteUnselected(types & sStatic.mSelectedRoute.getSupportedTypes(),
-                    sStatic.mSelectedRoute);
+            dispatchRouteUnselected(types & oldRoute.getSupportedTypes(), oldRoute);
         }
         sStatic.mSelectedRoute = route;
         if (route != null) {
@@ -327,6 +422,22 @@
     }
 
     /**
+     * Compare the device address of a display and a route.
+     * Nulls/no device address will match another null/no address.
+     */
+    static boolean matchesDeviceAddress(WifiDisplay display, RouteInfo info) {
+        final boolean routeHasAddress = info != null && info.mDeviceAddress != null;
+        if (display == null && !routeHasAddress) {
+            return true;
+        }
+
+        if (display != null && routeHasAddress) {
+            return display.getDeviceAddress().equals(info.mDeviceAddress);
+        }
+        return false;
+    }
+
+    /**
      * Add an app-specified route for media to the MediaRouter.
      * App-specified route definitions are created using {@link #createUserRoute(RouteCategory)}
      *
@@ -335,22 +446,21 @@
      * @see #removeUserRoute(UserRouteInfo)
      */
     public void addUserRoute(UserRouteInfo info) {
-        addRoute(info);
+        addRouteStatic(info);
     }
 
     /**
      * @hide Framework use only
      */
     public void addRouteInt(RouteInfo info) {
-        addRoute(info);
+        addRouteStatic(info);
     }
 
-    static void addRoute(RouteInfo info) {
+    static void addRouteStatic(RouteInfo info) {
         final RouteCategory cat = info.getCategory();
         if (!sStatic.mCategories.contains(cat)) {
             sStatic.mCategories.add(cat);
         }
-        final boolean onlyRoute = sStatic.mRoutes.isEmpty();
         if (cat.isGroupable() && !(info instanceof RouteGroup)) {
             // Enforce that any added route in a groupable category must be in a group.
             final RouteGroup group = new RouteGroup(info.getCategory());
@@ -364,10 +474,6 @@
             sStatic.mRoutes.add(info);
             dispatchRouteAdded(info);
         }
-
-        if (onlyRoute) {
-            selectRouteStatic(info.getSupportedTypes(), info);
-        }
     }
 
     /**
@@ -419,7 +525,7 @@
             if (info == sStatic.mSelectedRoute) {
                 // Removing the currently selected route? Select the default before we remove it.
                 // TODO: Be smarter about the route types here; this selects for all valid.
-                selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_USER, sStatic.mDefaultAudio);
+                selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_USER, sStatic.mDefaultAudioVideo);
             }
             if (!found) {
                 sStatic.mCategories.remove(removingCat);
@@ -444,7 +550,8 @@
             if (info == sStatic.mSelectedRoute) {
                 // Removing the currently selected route? Select the default before we remove it.
                 // TODO: Be smarter about the route types here; this selects for all valid.
-                selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_USER, sStatic.mDefaultAudio);
+                selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO | ROUTE_TYPE_USER,
+                        sStatic.mDefaultAudioVideo);
             }
             if (!found) {
                 sStatic.mCategories.remove(removingCat);
@@ -606,25 +713,194 @@
         }
     }
 
+    static void dispatchRoutePresentationDisplayChanged(RouteInfo info) {
+        for (CallbackInfo cbi : sStatic.mCallbacks) {
+            if ((cbi.type & info.mSupportedTypes) != 0) {
+                cbi.cb.onRoutePresentationDisplayChanged(cbi.router, info);
+            }
+        }
+    }
+
     static void systemVolumeChanged(int newValue) {
         final RouteInfo selectedRoute = sStatic.mSelectedRoute;
         if (selectedRoute == null) return;
 
         if (selectedRoute == sStatic.mBluetoothA2dpRoute ||
-                selectedRoute == sStatic.mDefaultAudio) {
+                selectedRoute == sStatic.mDefaultAudioVideo) {
             dispatchRouteVolumeChanged(selectedRoute);
         } else if (sStatic.mBluetoothA2dpRoute != null) {
             try {
                 dispatchRouteVolumeChanged(sStatic.mAudioService.isBluetoothA2dpOn() ?
-                        sStatic.mBluetoothA2dpRoute : sStatic.mDefaultAudio);
+                        sStatic.mBluetoothA2dpRoute : sStatic.mDefaultAudioVideo);
             } catch (RemoteException e) {
                 Log.e(TAG, "Error checking Bluetooth A2DP state to report volume change", e);
             }
         } else {
-            dispatchRouteVolumeChanged(sStatic.mDefaultAudio);
+            dispatchRouteVolumeChanged(sStatic.mDefaultAudioVideo);
         }
     }
 
+    static void updateWifiDisplayStatus(WifiDisplayStatus newStatus) {
+        final WifiDisplayStatus oldStatus = sStatic.mLastKnownWifiDisplayStatus;
+
+        // TODO Naive implementation. Make this smarter later.
+        boolean wantScan = false;
+        boolean blockScan = false;
+        WifiDisplay[] oldDisplays = oldStatus != null ?
+                oldStatus.getRememberedDisplays() : new WifiDisplay[0];
+        WifiDisplay[] newDisplays = newStatus.getRememberedDisplays();
+        WifiDisplay[] availableDisplays = newStatus.getAvailableDisplays();
+        WifiDisplay activeDisplay = newStatus.getActiveDisplay();
+
+        for (int i = 0; i < newDisplays.length; i++) {
+            final WifiDisplay d = newDisplays[i];
+            final WifiDisplay oldRemembered = findMatchingDisplay(d, oldDisplays);
+            if (oldRemembered == null) {
+                addRouteStatic(makeWifiDisplayRoute(d,
+                        findMatchingDisplay(d, availableDisplays) != null));
+                wantScan = true;
+            } else {
+                final boolean available = findMatchingDisplay(d, availableDisplays) != null;
+                final RouteInfo route = findWifiDisplayRoute(d);
+                updateWifiDisplayRoute(route, d, available, newStatus);
+            }
+            if (d.equals(activeDisplay)) {
+                final RouteInfo activeRoute = findWifiDisplayRoute(d);
+                if (activeRoute != null) {
+                    selectRouteStatic(activeRoute.getSupportedTypes(), activeRoute);
+
+                    // Don't scan if we're already connected to a wifi display,
+                    // the scanning process can cause a hiccup with some configurations.
+                    blockScan = true;
+                }
+            }
+        }
+        for (int i = 0; i < oldDisplays.length; i++) {
+            final WifiDisplay d = oldDisplays[i];
+            final WifiDisplay newDisplay = findMatchingDisplay(d, newDisplays);
+            if (newDisplay == null) {
+                removeRoute(findWifiDisplayRoute(d));
+            }
+        }
+
+        if (wantScan && !blockScan) {
+            sStatic.mDisplayService.scanWifiDisplays();
+        }
+
+        sStatic.mLastKnownWifiDisplayStatus = newStatus;
+    }
+
+    static RouteInfo makeWifiDisplayRoute(WifiDisplay display, boolean available) {
+        final RouteInfo newRoute = new RouteInfo(sStatic.mSystemCategory);
+        newRoute.mDeviceAddress = display.getDeviceAddress();
+        newRoute.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO;
+        newRoute.mVolumeHandling = RouteInfo.PLAYBACK_VOLUME_FIXED;
+        newRoute.mPlaybackType = RouteInfo.PLAYBACK_TYPE_REMOTE;
+
+        newRoute.setStatusCode(available ?
+                RouteInfo.STATUS_AVAILABLE : RouteInfo.STATUS_CONNECTING);
+        newRoute.mEnabled = available;
+
+        newRoute.mName = display.getFriendlyDisplayName();
+
+        newRoute.mPresentationDisplay = choosePresentationDisplayForRoute(newRoute,
+                sStatic.getAllPresentationDisplays());
+        return newRoute;
+    }
+
+    private static void updateWifiDisplayRoute(RouteInfo route, WifiDisplay display,
+            boolean available, WifiDisplayStatus wifiDisplayStatus) {
+        final boolean isScanning =
+                wifiDisplayStatus.getScanState() == WifiDisplayStatus.SCAN_STATE_SCANNING;
+
+        boolean changed = false;
+        int newStatus = RouteInfo.STATUS_NONE;
+
+        if (available) {
+            newStatus = isScanning ? RouteInfo.STATUS_SCANNING : RouteInfo.STATUS_AVAILABLE;
+        } else {
+            newStatus = RouteInfo.STATUS_NOT_AVAILABLE;
+        }
+
+        if (display.equals(wifiDisplayStatus.getActiveDisplay())) {
+            final int activeState = wifiDisplayStatus.getActiveDisplayState();
+            switch (activeState) {
+                case WifiDisplayStatus.DISPLAY_STATE_CONNECTED:
+                    newStatus = RouteInfo.STATUS_NONE;
+                    break;
+                case WifiDisplayStatus.DISPLAY_STATE_CONNECTING:
+                    newStatus = RouteInfo.STATUS_CONNECTING;
+                    break;
+                case WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED:
+                    Log.e(TAG, "Active display is not connected!");
+                    break;
+            }
+        }
+
+        final String newName = display.getFriendlyDisplayName();
+        if (!route.getName().equals(newName)) {
+            route.mName = newName;
+            changed = true;
+        }
+
+        changed |= route.mEnabled != available;
+        route.mEnabled = available;
+
+        changed |= route.setStatusCode(newStatus);
+
+        if (changed) {
+            dispatchRouteChanged(route);
+        }
+
+        if (!available && route == sStatic.mSelectedRoute) {
+            // Oops, no longer available. Reselect the default.
+            final RouteInfo defaultRoute = sStatic.mDefaultAudioVideo;
+            selectRouteStatic(defaultRoute.getSupportedTypes(), defaultRoute);
+        }
+    }
+
+    private static WifiDisplay findMatchingDisplay(WifiDisplay d, WifiDisplay[] displays) {
+        for (int i = 0; i < displays.length; i++) {
+            final WifiDisplay other = displays[i];
+            if (d.getDeviceAddress().equals(other.getDeviceAddress())) {
+                return other;
+            }
+        }
+        return null;
+    }
+
+    private static RouteInfo findWifiDisplayRoute(WifiDisplay d) {
+        final int count = sStatic.mRoutes.size();
+        for (int i = 0; i < count; i++) {
+            final RouteInfo info = sStatic.mRoutes.get(i);
+            if (d.getDeviceAddress().equals(info.mDeviceAddress)) {
+                return info;
+            }
+        }
+        return null;
+    }
+
+    private static Display choosePresentationDisplayForRoute(RouteInfo route, Display[] displays) {
+        if ((route.mSupportedTypes & ROUTE_TYPE_LIVE_VIDEO) != 0) {
+            if (route.mDeviceAddress != null) {
+                // Find the indicated Wifi display by its address.
+                for (Display display : displays) {
+                    if (display.getType() == Display.TYPE_WIFI
+                            && route.mDeviceAddress.equals(display.getAddress())) {
+                        return display;
+                    }
+                }
+                return null;
+            }
+
+            if (route == sStatic.mDefaultAudioVideo && displays.length > 0) {
+                // Choose the first presentation display from the list.
+                return displays[0];
+            }
+        }
+        return null;
+    }
+
     /**
      * Information about a media route.
      */
@@ -643,6 +919,19 @@
         int mVolumeHandling = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME_HANDLING;
         int mPlaybackStream = AudioManager.STREAM_MUSIC;
         VolumeCallbackInfo mVcb;
+        Display mPresentationDisplay;
+
+        String mDeviceAddress;
+        boolean mEnabled = true;
+
+        // A predetermined connection status that can override mStatus
+        private int mStatusCode;
+
+        /** @hide */ public static final int STATUS_NONE = 0;
+        /** @hide */ public static final int STATUS_SCANNING = 1;
+        /** @hide */ public static final int STATUS_CONNECTING = 2;
+        /** @hide */ public static final int STATUS_AVAILABLE = 3;
+        /** @hide */ public static final int STATUS_NOT_AVAILABLE = 4;
 
         private Object mTag;
 
@@ -711,6 +1000,41 @@
         }
 
         /**
+         * Set this route's status by predetermined status code. If the caller
+         * should dispatch a route changed event this call will return true;
+         */
+        boolean setStatusCode(int statusCode) {
+            if (statusCode != mStatusCode) {
+                mStatusCode = statusCode;
+                int resId = 0;
+                switch (statusCode) {
+                    case STATUS_SCANNING:
+                        resId = com.android.internal.R.string.media_route_status_scanning;
+                        break;
+                    case STATUS_CONNECTING:
+                        resId = com.android.internal.R.string.media_route_status_connecting;
+                        break;
+                    case STATUS_AVAILABLE:
+                        resId = com.android.internal.R.string.media_route_status_available;
+                        break;
+                    case STATUS_NOT_AVAILABLE:
+                        resId = com.android.internal.R.string.media_route_status_not_available;
+                        break;
+                }
+                mStatus = resId != 0 ? sStatic.mResources.getText(resId) : null;
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * @hide
+         */
+        public int getStatusCode() {
+            return mStatusCode;
+        }
+
+        /**
          * @return A media type flag set describing which types this route supports.
          */
         public int getSupportedTypes() {
@@ -866,6 +1190,45 @@
             return mVolumeHandling;
         }
 
+        /**
+         * Gets the {@link Display} that should be used by the application to show
+         * a {@link android.app.Presentation} on an external display when this route is selected.
+         * Depending on the route, this may only be valid if the route is currently
+         * selected.
+         * <p>
+         * The preferred presentation display may change independently of the route
+         * being selected or unselected.  For example, the presentation display
+         * of the default system route may change when an external HDMI display is connected
+         * or disconnected even though the route itself has not changed.
+         * </p><p>
+         * This method may return null if there is no external display associated with
+         * the route or if the display is not ready to show UI yet.
+         * </p><p>
+         * The application should listen for changes to the presentation display
+         * using the {@link Callback#onRoutePresentationDisplayChanged} callback and
+         * show or dismiss its {@link android.app.Presentation} accordingly when the display
+         * becomes available or is removed.
+         * </p><p>
+         * This method only makes sense for {@link #ROUTE_TYPE_LIVE_VIDEO live video} routes.
+         * </p>
+         *
+         * @return The preferred presentation display to use when this route is
+         * selected or null if none.
+         *
+         * @see #ROUTE_TYPE_LIVE_VIDEO
+         * @see android.app.Presentation
+         */
+        public Display getPresentationDisplay() {
+            return mPresentationDisplay;
+        }
+
+        /**
+         * @return true if this route is enabled and may be selected
+         */
+        public boolean isEnabled() {
+            return mEnabled;
+        }
+
         void setStatusInt(CharSequence status) {
             if (!status.equals(mStatus)) {
                 mStatus = status;
@@ -881,7 +1244,6 @@
                 sStatic.mHandler.post(new Runnable() {
                     @Override
                     public void run() {
-                      //Log.d(TAG, "dispatchRemoteVolumeUpdate dir=" + direction + " val=" + value);
                         if (mVcb != null) {
                             if (direction != 0) {
                                 mVcb.vcb.onVolumeUpdateRequest(mVcb.route, direction);
@@ -901,9 +1263,11 @@
         @Override
         public String toString() {
             String supportedTypes = typesToString(getSupportedTypes());
-            return getClass().getSimpleName() + "{ name=" + getName() + ", status=" + getStatus() +
-                    " category=" + getCategory() +
-                    " supportedTypes=" + supportedTypes + "}";
+            return getClass().getSimpleName() + "{ name=" + getName() +
+                    ", status=" + getStatus() +
+                    ", category=" + getCategory() +
+                    ", supportedTypes=" + supportedTypes +
+                    ", presentationDisplay=" + mPresentationDisplay + "}";
         }
     }
 
@@ -1400,6 +1764,7 @@
         int mNameResId;
         int mTypes;
         final boolean mGroupable;
+        boolean mIsSystem;
 
         RouteCategory(CharSequence name, int types, boolean groupable) {
             mName = name;
@@ -1486,6 +1851,14 @@
             return mGroupable;
         }
 
+        /**
+         * @return true if this is the category reserved for system routes.
+         * @hide
+         */
+        public boolean isSystem() {
+            return mIsSystem;
+        }
+
         public String toString() {
             return "RouteCategory{ name=" + mName + " types=" + typesToString(mTypes) +
                     " groupable=" + mGroupable + " }";
@@ -1589,6 +1962,21 @@
          * @param info The route with altered volume
          */
         public abstract void onRouteVolumeChanged(MediaRouter router, RouteInfo info);
+
+        /**
+         * Called when a route's presentation display changes.
+         * <p>
+         * This method is called whenever the route's presentation display becomes
+         * available, is removes or has changes to some of its properties (such as its size).
+         * </p>
+         *
+         * @param router the MediaRouter reporting the event
+         * @param info The route whose presentation display changed
+         *
+         * @see RouteInfo#getPresentationDisplay()
+         */
+        public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo info) {
+        }
     }
 
     /**
@@ -1671,7 +2059,6 @@
     }
 
     static class VolumeChangeReceiver extends BroadcastReceiver {
-
         @Override
         public void onReceive(Context context, Intent intent) {
             if (intent.getAction().equals(AudioManager.VOLUME_CHANGED_ACTION)) {
@@ -1689,6 +2076,15 @@
                 }
             }
         }
+    }
 
+    static class WifiDisplayStatusChangedReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED)) {
+                updateWifiDisplayStatus((WifiDisplayStatus) intent.getParcelableExtra(
+                        DisplayManager.EXTRA_WIFI_DISPLAY_STATUS));
+            }
+        }
     }
 }
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index fd37bcf..88cf4ac 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -314,6 +314,7 @@
     private int mMtpObjectHandle;
 
     private final String mExternalStoragePath;
+    private final boolean mExternalIsEmulated;
 
     /** whether to use bulk inserts or individual inserts for each item */
     private static final boolean ENABLE_BULK_INSERTS = true;
@@ -392,6 +393,7 @@
         setDefaultRingtoneFileNames();
 
         mExternalStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath();
+        mExternalIsEmulated = Environment.isExternalStorageEmulated();
         //mClient.testGenreNameConverter();
     }
 
@@ -543,13 +545,28 @@
                         boolean music = (lowpath.indexOf(MUSIC_DIR) > 0) ||
                             (!ringtones && !notifications && !alarms && !podcasts);
 
+                        boolean isaudio = MediaFile.isAudioFileType(mFileType);
+                        boolean isvideo = MediaFile.isVideoFileType(mFileType);
+                        boolean isimage = MediaFile.isImageFileType(mFileType);
+
+                        if (isaudio || isvideo || isimage) {
+                            if (mExternalIsEmulated && path.startsWith(mExternalStoragePath)) {
+                                // try to rewrite the path to bypass the sd card fuse layer
+                                String directPath = Environment.getMediaStorageDirectory() +
+                                        path.substring(mExternalStoragePath.length());
+                                File f = new File(directPath);
+                                if (f.exists()) {
+                                    path = directPath;
+                                }
+                            }
+                        }
+
                         // we only extract metadata for audio and video files
-                        if (MediaFile.isAudioFileType(mFileType)
-                                || MediaFile.isVideoFileType(mFileType)) {
+                        if (isaudio || isvideo) {
                             processFile(path, mimeType, this);
                         }
 
-                        if (MediaFile.isImageFileType(mFileType)) {
+                        if (isimage) {
                             processImageFile(path);
                         }
 
@@ -972,7 +989,6 @@
                     }
                     values.put(FileColumns.MEDIA_TYPE, mediaType);
                 }
-
                 mMediaProvider.update(result, values, null, null);
             }
 
@@ -1448,24 +1464,42 @@
     }
 
     FileEntry makeEntryFor(String path) {
-        String key = path;
         String where;
         String[] selectionArgs;
-        if (mCaseInsensitivePaths) {
-            // the 'like' makes it use the index, the 'lower()' makes it correct
-            // when the path contains sqlite wildcard characters
-            where = "_data LIKE ?1 AND lower(_data)=lower(?1)";
-            selectionArgs = new String[] { path };
-        } else {
-            where = Files.FileColumns.DATA + "=?";
-            selectionArgs = new String[] { path };
-        }
 
         Cursor c = null;
         try {
+            boolean hasWildCards = path.contains("_") || path.contains("%");
+
+            if (hasWildCards || !mCaseInsensitivePaths) {
+                // if there are wildcard characters in the path, the "like" match
+                // will be slow, and it's worth trying an "=" comparison
+                // first, since in most cases the case will match.
+                // Also, we shouldn't do a "like" match on case-sensitive filesystems
+                where = Files.FileColumns.DATA + "=?";
+                selectionArgs = new String[] { path };
+            } else {
+                // if there are no wildcard characters in the path, then the "like"
+                // match will be just as fast as the "=" case, because of the index
+                where = "_data LIKE ?1 AND lower(_data)=lower(?1)";
+                selectionArgs = new String[] { path };
+            }
             c = mMediaProvider.query(mFilesUri, FILES_PRESCAN_PROJECTION,
                     where, selectionArgs, null, null);
-            if (c.moveToNext()) {
+            if (!c.moveToFirst() && hasWildCards && mCaseInsensitivePaths) {
+                // Try again with case-insensitive match. This will be slower, especially
+                // if the path contains wildcard characters.
+                // The 'like' makes it use the index, the 'lower()' makes it correct
+                // when the path contains sqlite wildcard characters,
+                where = "_data LIKE ?1 AND lower(_data)=lower(?1)";
+                selectionArgs = new String[] { path };
+                c.close();
+                c = mMediaProvider.query(mFilesUri, FILES_PRESCAN_PROJECTION,
+                        where, selectionArgs, null, null);
+                // TODO update the path in the db with the correct case so the fast
+                // path works next time?
+            }
+            if (c.moveToFirst()) {
                 long rowId = c.getLong(FILES_PRESCAN_ID_COLUMN_INDEX);
                 int format = c.getInt(FILES_PRESCAN_FORMAT_COLUMN_INDEX);
                 long lastModified = c.getLong(FILES_PRESCAN_DATE_MODIFIED_COLUMN_INDEX);
diff --git a/media/java/android/media/RemoteDisplay.java b/media/java/android/media/RemoteDisplay.java
new file mode 100644
index 0000000..b463d26
--- /dev/null
+++ b/media/java/android/media/RemoteDisplay.java
@@ -0,0 +1,153 @@
+/*
+ * 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.media;
+
+import dalvik.system.CloseGuard;
+
+import android.os.Handler;
+import android.view.Surface;
+
+/**
+ * Listens for Wifi remote display connections managed by the media server.
+ *
+ * @hide
+ */
+public final class RemoteDisplay {
+    /* these constants must be kept in sync with IRemoteDisplayClient.h */
+
+    public static final int DISPLAY_FLAG_SECURE = 1 << 0;
+
+    public static final int DISPLAY_ERROR_UNKOWN = 1;
+    public static final int DISPLAY_ERROR_CONNECTION_DROPPED = 2;
+
+    private final CloseGuard mGuard = CloseGuard.get();
+    private final Listener mListener;
+    private final Handler mHandler;
+
+    private int mPtr;
+
+    private native int nativeListen(String iface);
+    private native void nativeDispose(int ptr);
+
+    private RemoteDisplay(Listener listener, Handler handler) {
+        mListener = listener;
+        mHandler = handler;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            dispose(true);
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * Starts listening for displays to be connected on the specified interface.
+     *
+     * @param iface The interface address and port in the form "x.x.x.x:y".
+     * @param listener The listener to invoke when displays are connected or disconnected.
+     * @param handler The handler on which to invoke the listener.
+     */
+    public static RemoteDisplay listen(String iface, Listener listener, Handler handler) {
+        if (iface == null) {
+            throw new IllegalArgumentException("iface must not be null");
+        }
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+        if (handler == null) {
+            throw new IllegalArgumentException("handler must not be null");
+        }
+
+        RemoteDisplay display = new RemoteDisplay(listener, handler);
+        display.startListening(iface);
+        return display;
+    }
+
+    /**
+     * Disconnects the remote display and stops listening for new connections.
+     */
+    public void dispose() {
+        dispose(false);
+    }
+
+    private void dispose(boolean finalized) {
+        if (mPtr != 0) {
+            if (mGuard != null) {
+                if (finalized) {
+                    mGuard.warnIfOpen();
+                } else {
+                    mGuard.close();
+                }
+            }
+
+            nativeDispose(mPtr);
+            mPtr = 0;
+        }
+    }
+
+    private void startListening(String iface) {
+        mPtr = nativeListen(iface);
+        if (mPtr == 0) {
+            throw new IllegalStateException("Could not start listening for "
+                    + "remote display connection on \"" + iface + "\"");
+        }
+        mGuard.open("dispose");
+    }
+
+    // Called from native.
+    private void notifyDisplayConnected(final Surface surface,
+            final int width, final int height, final int flags) {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mListener.onDisplayConnected(surface, width, height, flags);
+            }
+        });
+    }
+
+    // Called from native.
+    private void notifyDisplayDisconnected() {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mListener.onDisplayDisconnected();
+            }
+        });
+    }
+
+    // Called from native.
+    private void notifyDisplayError(final int error) {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mListener.onDisplayError(error);
+            }
+        });
+    }
+
+    /**
+     * Listener invoked when the remote display connection changes state.
+     */
+    public interface Listener {
+        void onDisplayConnected(Surface surface, int width, int height, int flags);
+        void onDisplayDisconnected();
+        void onDisplayError(int error);
+    }
+}
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index 23f7b55..f190eb9 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -225,8 +225,9 @@
                 mLocalPlayer.start();
             }
         } else if (mAllowRemote) {
+            final Uri canonicalUri = mUri.getCanonicalUri();
             try {
-                mRemotePlayer.play(mRemoteToken, mUri, mStreamType);
+                mRemotePlayer.play(mRemoteToken, canonicalUri, mStreamType);
             } catch (RemoteException e) {
                 Log.w(TAG, "Problem playing ringtone: " + e);
             }
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index 4756078..f4fccbe 100644
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -3831,6 +3831,7 @@
                         outWidth, outHeight, Bitmap.Config.ARGB_8888);
 
                 // Copy int[] to IntBuffer
+                decBuffer.rewind();
                 decBuffer.put(decArray, 0, thumbnailSize);
                 decBuffer.rewind();
 
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index a0325dd..487585e 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -84,11 +84,10 @@
             Files.FileColumns._ID, // 0
             Files.FileColumns.DATA, // 1
     };
-    private static final String[] PATH_SIZE_FORMAT_PROJECTION = new String[] {
+    private static final String[] PATH_FORMAT_PROJECTION = new String[] {
             Files.FileColumns._ID, // 0
             Files.FileColumns.DATA, // 1
-            Files.FileColumns.SIZE, // 2
-            Files.FileColumns.FORMAT, // 3
+            Files.FileColumns.FORMAT, // 2
     };
     private static final String[] OBJECT_INFO_PROJECTION = new String[] {
             Files.FileColumns._ID, // 0
@@ -96,15 +95,14 @@
             Files.FileColumns.FORMAT, // 2
             Files.FileColumns.PARENT, // 3
             Files.FileColumns.DATA, // 4
-            Files.FileColumns.SIZE, // 5
-            Files.FileColumns.DATE_MODIFIED, // 6
+            Files.FileColumns.DATE_MODIFIED, // 5
     };
     private static final String ID_WHERE = Files.FileColumns._ID + "=?";
     private static final String PATH_WHERE = Files.FileColumns.DATA + "=?";
 
     private static final String STORAGE_WHERE = Files.FileColumns.STORAGE_ID + "=?";
-    private static final String FORMAT_WHERE = Files.FileColumns.PARENT + "=?";
-    private static final String PARENT_WHERE = Files.FileColumns.FORMAT + "=?";
+    private static final String FORMAT_WHERE = Files.FileColumns.FORMAT + "=?";
+    private static final String PARENT_WHERE = Files.FileColumns.PARENT + "=?";
     private static final String STORAGE_FORMAT_WHERE = STORAGE_WHERE + " AND "
                                             + Files.FileColumns.FORMAT + "=?";
     private static final String STORAGE_PARENT_WHERE = STORAGE_WHERE + " AND "
@@ -835,7 +833,7 @@
     }
 
     private boolean getObjectInfo(int handle, int[] outStorageFormatParent,
-                        char[] outName, long[] outSizeModified) {
+                        char[] outName, long[] outModified) {
         Cursor c = null;
         try {
             c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION,
@@ -856,8 +854,7 @@
                 path.getChars(start, end, outName, 0);
                 outName[end - start] = 0;
 
-                outSizeModified[0] = c.getLong(5);
-                outSizeModified[1] = c.getLong(6);
+                outModified[0] = c.getLong(5);
                 return true;
             }
         } catch (RemoteException e) {
@@ -881,14 +878,16 @@
         }
         Cursor c = null;
         try {
-            c = mMediaProvider.query(mObjectsUri, PATH_SIZE_FORMAT_PROJECTION,
+            c = mMediaProvider.query(mObjectsUri, PATH_FORMAT_PROJECTION,
                             ID_WHERE, new String[] {  Integer.toString(handle) }, null, null);
             if (c != null && c.moveToNext()) {
                 String path = c.getString(1);
                 path.getChars(0, path.length(), outFilePath, 0);
                 outFilePath[path.length()] = 0;
-                outFileLengthFormat[0] = c.getLong(2);
-                outFileLengthFormat[1] = c.getLong(3);
+                // File transfers from device to host will likely fail if the size is incorrect.
+                // So to be safe, use the actual file size here.
+                outFileLengthFormat[0] = new File(path).length();
+                outFileLengthFormat[1] = c.getLong(2);
                 return MtpConstants.RESPONSE_OK;
             } else {
                 return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
@@ -910,13 +909,13 @@
 
         Cursor c = null;
         try {
-            c = mMediaProvider.query(mObjectsUri, PATH_SIZE_FORMAT_PROJECTION,
+            c = mMediaProvider.query(mObjectsUri, PATH_FORMAT_PROJECTION,
                             ID_WHERE, new String[] {  Integer.toString(handle) }, null, null);
             if (c != null && c.moveToNext()) {
                 // don't convert to media path here, since we will be matching
                 // against paths in the database matching /data/media
                 path = c.getString(1);
-                format = c.getInt(3);
+                format = c.getInt(2);
             } else {
                 return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
             }
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 4941ae5..f91c9a0 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -370,7 +370,7 @@
 
     sp<ISurfaceTexture> surfaceTexture;
     if (jsurface != NULL) {
-        sp<Surface> surface(Surface_getSurface(env, jsurface));
+        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
         if (surface != NULL) {
             surfaceTexture = surface->getSurfaceTexture();
         } else {
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 351ff04..23949fa 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -44,6 +44,72 @@
 
 static fields_t gFields;
 
+class JavaDataSourceBridge : public DataSource {
+    jmethodID mReadMethod;
+    jmethodID mGetSizeMethod;
+    jmethodID mCloseMethod;
+    jobject   mDataSource;
+ public:
+    JavaDataSourceBridge(JNIEnv *env, jobject source) {
+        mDataSource = env->NewGlobalRef(source);
+
+        jclass datasourceclass = env->GetObjectClass(mDataSource);
+        CHECK(datasourceclass != NULL);
+
+        mReadMethod = env->GetMethodID(datasourceclass, "readAt", "(J[BI)I");
+        CHECK(mReadMethod != NULL);
+
+        mGetSizeMethod = env->GetMethodID(datasourceclass, "getSize", "()J");
+        CHECK(mGetSizeMethod != NULL);
+
+        mCloseMethod = env->GetMethodID(datasourceclass, "close", "()V");
+        CHECK(mCloseMethod != NULL);
+    }
+
+    ~JavaDataSourceBridge() {
+        JNIEnv *env = AndroidRuntime::getJNIEnv();
+        env->CallVoidMethod(mDataSource, mCloseMethod);
+        env->DeleteGlobalRef(mDataSource);
+    }
+
+    virtual status_t initCheck() const {
+        return OK;
+    }
+
+    virtual ssize_t readAt(off64_t offset, void* buffer, size_t size) {
+        JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+        // XXX could optimize this by reusing the same array
+        jbyteArray byteArrayObj = env->NewByteArray(size);
+        env->DeleteLocalRef(env->GetObjectClass(mDataSource));
+        env->DeleteLocalRef(env->GetObjectClass(byteArrayObj));
+        ssize_t numread = env->CallIntMethod(mDataSource, mReadMethod, offset, byteArrayObj, size);
+        env->GetByteArrayRegion(byteArrayObj, 0, size, (jbyte*) buffer);
+        env->DeleteLocalRef(byteArrayObj);
+        if (env->ExceptionCheck()) {
+            ALOGW("Exception occurred while reading %d at %lld", size, offset);
+            LOGW_EX(env);
+            env->ExceptionClear();
+            return -1;
+        }
+        return numread;
+    }
+
+    virtual status_t getSize(off64_t *size) {
+        JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+        CHECK(size != NULL);
+
+        int64_t len = env->CallLongMethod(mDataSource, mGetSizeMethod);
+        if (len < 0) {
+            *size = ERROR_UNSUPPORTED;
+        } else {
+            *size = len;
+        }
+        return OK;
+    }
+};
+
 ////////////////////////////////////////////////////////////////////////////////
 
 JMediaExtractor::JMediaExtractor(JNIEnv *env, jobject thiz)
@@ -76,6 +142,10 @@
     return mImpl->setDataSource(fd, offset, size);
 }
 
+status_t JMediaExtractor::setDataSource(const sp<DataSource> &datasource) {
+    return mImpl->setDataSource(datasource);
+}
+
 size_t JMediaExtractor::countTracks() const {
     return mImpl->countTracks();
 }
@@ -625,6 +695,33 @@
     }
 }
 
+static void android_media_MediaExtractor_setDataSourceCallback(
+        JNIEnv *env, jobject thiz,
+        jobject callbackObj) {
+    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
+
+    if (extractor == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+
+    if (callbackObj == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+
+    sp<JavaDataSourceBridge> bridge = new JavaDataSourceBridge(env, callbackObj);
+    status_t err = extractor->setDataSource(bridge);
+
+    if (err != OK) {
+        jniThrowException(
+                env,
+                "java/io/IOException",
+                "Failed to instantiate extractor.");
+        return;
+    }
+}
+
 static jlong android_media_MediaExtractor_getCachedDurationUs(
         JNIEnv *env, jobject thiz) {
     sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
@@ -713,6 +810,9 @@
     { "setDataSource", "(Ljava/io/FileDescriptor;JJ)V",
       (void *)android_media_MediaExtractor_setDataSourceFd },
 
+    { "setDataSource", "(Landroid/media/DataSource;)V",
+      (void *)android_media_MediaExtractor_setDataSourceCallback },
+
     { "getCachedDuration", "()J",
       (void *)android_media_MediaExtractor_getCachedDurationUs },
 
diff --git a/media/jni/android_media_MediaExtractor.h b/media/jni/android_media_MediaExtractor.h
index 2d4627e..03900db 100644
--- a/media/jni/android_media_MediaExtractor.h
+++ b/media/jni/android_media_MediaExtractor.h
@@ -19,6 +19,7 @@
 
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/MediaSource.h>
+#include <media/stagefright/DataSource.h>
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
@@ -39,6 +40,7 @@
             const KeyedVector<String8, String8> *headers);
 
     status_t setDataSource(int fd, off64_t offset, off64_t size);
+    status_t setDataSource(const sp<DataSource> &source);
 
     size_t countTracks() const;
     status_t getTrackFormat(size_t index, jobject *format) const;
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index c2a6889..ad536f2 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -271,9 +271,14 @@
 
     sp<ISurfaceTexture> new_st;
     if (jsurface) {
-        sp<Surface> surface(Surface_getSurface(env, jsurface));
+        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
         if (surface != NULL) {
             new_st = surface->getSurfaceTexture();
+            if (new_st == NULL) {
+                jniThrowException(env, "java/lang/IllegalArgumentException",
+                    "The surface does not have a binding SurfaceTexture!");
+                return;
+            }
             new_st->incStrong(thiz);
         } else {
             jniThrowException(env, "java/lang/IllegalArgumentException",
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 99e543b..bc65de5 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -751,13 +751,22 @@
 
 MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
                                             MtpObjectInfo& info) {
-    char    date[20];
+    char            date[20];
+    MtpString       path;
+    int64_t         length;
+    MtpObjectFormat format;
+
+    MtpResponseCode result = getObjectFilePath(handle, path, length, format);
+    if (result != MTP_RESPONSE_OK) {
+        return result;
+    }
+    info.mCompressedSize = (length > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)length);
 
     JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jboolean result = env->CallBooleanMethod(mDatabase, method_getObjectInfo,
-                (jint)handle, mIntBuffer, mStringBuffer, mLongBuffer);
-    if (!result)
+    if (!env->CallBooleanMethod(mDatabase, method_getObjectInfo,
+                (jint)handle, mIntBuffer, mStringBuffer, mLongBuffer)) {
         return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+    }
 
     jint* intValues = env->GetIntArrayElements(mIntBuffer, 0);
     info.mStorageID = intValues[0];
@@ -766,9 +775,7 @@
     env->ReleaseIntArrayElements(mIntBuffer, intValues, 0);
 
     jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
-    uint64_t size = longValues[0];
-    info.mCompressedSize = (size > 0xFFFFFFFFLL ? 0xFFFFFFFF : size);
-    info.mDateModified = longValues[1];
+    info.mDateModified = longValues[0];
     env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
 
 //    info.mAssociationType = (format == MTP_FORMAT_ASSOCIATION ?
@@ -783,28 +790,23 @@
 
     // read EXIF data for thumbnail information
     if (info.mFormat == MTP_FORMAT_EXIF_JPEG || info.mFormat == MTP_FORMAT_JFIF) {
-        MtpString path;
-        int64_t length;
-        MtpObjectFormat format;
-        if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK) {
-            ResetJpgfile();
-             // Start with an empty image information structure.
-            memset(&ImageInfo, 0, sizeof(ImageInfo));
-            ImageInfo.FlashUsed = -1;
-            ImageInfo.MeteringMode = -1;
-            ImageInfo.Whitebalance = -1;
-            strncpy(ImageInfo.FileName, (const char *)path, PATH_MAX);
-            if (ReadJpegFile((const char*)path, READ_METADATA)) {
-                Section_t* section = FindSection(M_EXIF);
-                if (section) {
-                    info.mThumbCompressedSize = ImageInfo.ThumbnailSize;
-                    info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
-                    info.mImagePixWidth = ImageInfo.Width;
-                    info.mImagePixHeight = ImageInfo.Height;
-                }
+        ResetJpgfile();
+         // Start with an empty image information structure.
+        memset(&ImageInfo, 0, sizeof(ImageInfo));
+        ImageInfo.FlashUsed = -1;
+        ImageInfo.MeteringMode = -1;
+        ImageInfo.Whitebalance = -1;
+        strncpy(ImageInfo.FileName, (const char *)path, PATH_MAX);
+        if (ReadJpegFile((const char*)path, READ_METADATA)) {
+            Section_t* section = FindSection(M_EXIF);
+            if (section) {
+                info.mThumbCompressedSize = ImageInfo.ThumbnailSize;
+                info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
+                info.mImagePixWidth = ImageInfo.Width;
+                info.mImagePixHeight = ImageInfo.Height;
             }
-            DiscardData();
         }
+        DiscardData();
     }
 
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
diff --git a/media/mca/effect/java/android/media/effect/effects/BackDropperEffect.java b/media/mca/effect/java/android/media/effect/effects/BackDropperEffect.java
index d5c7aaa..f977e60 100644
--- a/media/mca/effect/java/android/media/effect/effects/BackDropperEffect.java
+++ b/media/mca/effect/java/android/media/effect/effects/BackDropperEffect.java
@@ -91,6 +91,9 @@
         if (parameterKey.equals("source")) {
             Filter background = mGraph.getFilter("background");
             background.setInputValue("sourceUrl", value);
+        } else if (parameterKey.equals("context")) {
+            Filter background = mGraph.getFilter("background");
+            background.setInputValue("context", value);
         }
     }
 
diff --git a/media/mca/filterpacks/java/android/filterpacks/imageproc/RedEyeFilter.java b/media/mca/filterpacks/java/android/filterpacks/imageproc/RedEyeFilter.java
index 3450ef1..8618804 100644
--- a/media/mca/filterpacks/java/android/filterpacks/imageproc/RedEyeFilter.java
+++ b/media/mca/filterpacks/java/android/filterpacks/imageproc/RedEyeFilter.java
@@ -72,9 +72,7 @@
             "void main() {\n" +
             "  vec4 color = texture2D(tex_sampler_0, v_texcoord);\n" +
             "  vec4 mask = texture2D(tex_sampler_1, v_texcoord);\n" +
-            "  gl_FragColor = vec4(mask.a, mask.a, mask.a, 1.0) * intensity + color * (1.0 - intensity);\n" +
             "  if (mask.a > 0.0) {\n" +
-            "    gl_FragColor.r = 0.0;\n" +
             "    float green_blue = color.g + color.b;\n" +
             "    float red_intensity = color.r / green_blue;\n" +
             "    if (red_intensity > intensity) {\n" +
@@ -105,8 +103,8 @@
                 ShaderProgram shaderProgram = new ShaderProgram(context, mRedEyeShader);
                 shaderProgram.setMaximumTileSize(mTileSize);
                 mProgram = shaderProgram;
+                mProgram.setHostValue("intensity", DEFAULT_RED_INTENSITY);
                 break;
-
             default:
                 throw new RuntimeException("Filter RedEye does not support frames of " +
                     "target " + target + "!");
@@ -180,8 +178,6 @@
     }
 
     private void updateProgramParams() {
-        mProgram.setHostValue("intensity", DEFAULT_RED_INTENSITY);
-
         if ( mCenters.length % 2 == 1) {
             throw new RuntimeException("The size of center array must be even.");
         }
diff --git a/media/mca/filterpacks/java/android/filterpacks/videosrc/MediaSource.java b/media/mca/filterpacks/java/android/filterpacks/videosrc/MediaSource.java
index 9c40cec..0be6c62 100644
--- a/media/mca/filterpacks/java/android/filterpacks/videosrc/MediaSource.java
+++ b/media/mca/filterpacks/java/android/filterpacks/videosrc/MediaSource.java
@@ -35,6 +35,7 @@
 import android.filterfw.format.ImageFormat;
 import android.graphics.SurfaceTexture;
 import android.media.MediaPlayer;
+import android.net.Uri;
 import android.os.ConditionVariable;
 import android.opengl.Matrix;
 import android.view.Surface;
@@ -64,6 +65,12 @@
     @GenerateFieldPort(name = "sourceAsset", hasDefault = true)
     private AssetFileDescriptor mSourceAsset = null;
 
+    /** The context for the MediaPlayer to resolve the sourceUrl.
+     * Make sure this is set before the sourceUrl to avoid unexpected result.
+     * If the sourceUrl is not a content URI, it is OK to keep this as null. */
+    @GenerateFieldPort(name = "context", hasDefault = true)
+    private Context mContext = null;
+
     /** Whether the media source is a URL or an asset file descriptor. Defaults
      * to false.
      */
@@ -459,7 +466,11 @@
         try {
             if (useUrl) {
                 if (mLogVerbose) Log.v(TAG, "Setting MediaPlayer source to URI " + mSourceUrl);
-                mMediaPlayer.setDataSource(mSourceUrl);
+                if (mContext == null) {
+                    mMediaPlayer.setDataSource(mSourceUrl);
+                } else {
+                    mMediaPlayer.setDataSource(mContext, Uri.parse(mSourceUrl.toString()));
+                }
             } else {
                 if (mLogVerbose) Log.v(TAG, "Setting MediaPlayer source to asset " + mSourceAsset);
                 mMediaPlayer.setDataSource(mSourceAsset.getFileDescriptor(), mSourceAsset.getStartOffset(), mSourceAsset.getLength());
diff --git a/media/tests/EffectsTest/Android.mk b/media/tests/EffectsTest/Android.mk
new file mode 100755
index 0000000..25b4fe4
--- /dev/null
+++ b/media/tests/EffectsTest/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := EffectsTest
+
+include $(BUILD_PACKAGE)
diff --git a/media/tests/EffectsTest/AndroidManifest.xml b/media/tests/EffectsTest/AndroidManifest.xml
new file mode 100755
index 0000000..9b59891
--- /dev/null
+++ b/media/tests/EffectsTest/AndroidManifest.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.effectstest">
+
+   <uses-permission android:name="android.permission.RECORD_AUDIO" />
+   <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+
+   <application>
+        <activity android:label="@string/app_name"
+                android:name="EffectsTest">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+
+        <activity android:label="@string/envreverb_test_name"
+                android:name="EnvReverbTest">
+        </activity>
+
+        <activity android:label="@string/presetrvb_test_name"
+                android:name="PresetReverbTest">
+        </activity>
+
+        <activity android:label="@string/equalizer_test_name"
+                android:name="EqualizerTest">
+        </activity>
+
+        <activity android:label="@string/virtualizer_test_name"
+                android:name="VirtualizerTest">
+        </activity>
+
+        <activity android:label="@string/bassboost_test_name"
+                android:name="BassBoostTest">
+        </activity>
+
+        <activity android:label="@string/visualizer_test_name"
+                android:name="VisualizerTest">
+        </activity>
+
+    </application>
+</manifest>
diff --git a/media/tests/EffectsTest/res/drawable/icon.png b/media/tests/EffectsTest/res/drawable/icon.png
new file mode 100755
index 0000000..64e3601
--- /dev/null
+++ b/media/tests/EffectsTest/res/drawable/icon.png
Binary files differ
diff --git a/media/tests/EffectsTest/res/drawable/stop.png b/media/tests/EffectsTest/res/drawable/stop.png
new file mode 100755
index 0000000..83f012c
--- /dev/null
+++ b/media/tests/EffectsTest/res/drawable/stop.png
Binary files differ
diff --git a/media/tests/EffectsTest/res/layout/bassboosttest.xml b/media/tests/EffectsTest/res/layout/bassboosttest.xml
new file mode 100755
index 0000000..ac912c8
--- /dev/null
+++ b/media/tests/EffectsTest/res/layout/bassboosttest.xml
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical">
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/bbReleaseLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/bbReleaseText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="1.0"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/effect_release"
+            style="@android:style/TextAppearance.Medium" />
+
+        <ToggleButton android:id="@+id/bbReleaseButton"
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent"
+            android:layout_gravity="center_vertical|right"
+            android:layout_weight="0.0" />
+
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/bbControlLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/bbControlText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="1.0"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/effect_control"
+            style="@android:style/TextAppearance.Medium" />
+
+        <ToggleButton android:id="@+id/bassboostOnOff"
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent"
+            android:layout_gravity="center_vertical|right"
+            android:layout_weight="0.0" />
+
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/SessionFrame"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/sessionText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="0.5"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/session"
+            style="@android:style/TextAppearance.Medium" />
+
+        <EditText android:id="@+id/sessionEdit"
+            android:singleLine="true"
+            android:numeric="integer"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="0.5"
+            android:layout_gravity="center_vertical|right" />
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content" >
+
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/bbStrengthName"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/stength_name" />
+
+                <LinearLayout android:id="@+id/bbStrengthDesc"
+                    android:orientation="horizontal"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginTop="10dip"
+                    android:layout_marginRight="30dip"
+                    android:layout_marginBottom="10dip" >
+
+                    <TextView android:id="@+id/bbStrengthMin"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1"
+                        android:layout_gravity="left"
+                        android:gravity="left"/>
+                    <TextView android:id="@+id/bbStrengthMax"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1"
+                        android:layout_gravity="right"
+                        android:gravity="right"/>
+                </LinearLayout>
+
+                <SeekBar android:id="@+id/bbStrengthSeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/bbStrengthValue"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+        </LinearLayout>
+
+    </ScrollView>
+
+</LinearLayout>
diff --git a/media/tests/EffectsTest/res/layout/effectstest.xml b/media/tests/EffectsTest/res/layout/effectstest.xml
new file mode 100755
index 0000000..9af4eb6
--- /dev/null
+++ b/media/tests/EffectsTest/res/layout/effectstest.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical">
+
+    <Button android:id="@+id/env_reverb_actvity"
+        android:layout_width="fill_parent" android:layout_height="wrap_content"
+        android:text="@string/envreverb_test_name">
+    </Button>
+
+    <Button android:id="@+id/preset_reverb_actvity"
+        android:layout_width="fill_parent" android:layout_height="wrap_content"
+        android:text="@string/presetrvb_test_name">
+    </Button>
+
+    <Button android:id="@+id/equalizer_actvity"
+        android:layout_width="fill_parent" android:layout_height="wrap_content"
+        android:text="@string/equalizer_test_name">
+    </Button>
+
+    <Button android:id="@+id/virtualizer_actvity"
+        android:layout_width="fill_parent" android:layout_height="wrap_content"
+        android:text="@string/virtualizer_test_name">
+    </Button>
+
+    <Button android:id="@+id/bassboost_actvity"
+        android:layout_width="fill_parent" android:layout_height="wrap_content"
+        android:text="@string/bassboost_test_name">
+    </Button>
+
+    <Button android:id="@+id/visualizer_actvity"
+        android:layout_width="fill_parent" android:layout_height="wrap_content"
+        android:text="@string/visualizer_test_name">
+    </Button>
+
+    <ListView android:id="@+id/effect_list"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:drawSelectorOnTop="false"/>
+
+
+</LinearLayout>
diff --git a/media/tests/EffectsTest/res/layout/envreverbtest.xml b/media/tests/EffectsTest/res/layout/envreverbtest.xml
new file mode 100755
index 0000000..01c3240
--- /dev/null
+++ b/media/tests/EffectsTest/res/layout/envreverbtest.xml
@@ -0,0 +1,553 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical">
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/rvbReleaseLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/rvbReleaseText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="1.0"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/effect_release"
+            style="@android:style/TextAppearance.Medium" />
+
+        <ToggleButton android:id="@+id/rvbReleaseButton"
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent"
+            android:layout_gravity="center_vertical|right"
+            android:layout_weight="0.0" />
+
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/rvbControlLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/rvbControlText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="1.0"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/effect_control"
+            style="@android:style/TextAppearance.Medium" />
+
+        <ToggleButton android:id="@+id/rvbOnOff"
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent"
+            android:layout_gravity="center_vertical|right"
+            android:layout_weight="0.0" />
+
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/auxFrame"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="3dip"
+        android:layout_marginTop="3dip"
+        android:layout_marginRight="3dip"
+        android:layout_marginBottom="3dip" >
+
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_gravity="left"
+            android:layout_weight="1.0"
+            android:orientation="vertical"
+            android:layout_marginLeft="1dip"
+            android:layout_marginTop="1dip"
+            android:layout_marginRight="1dip"
+            android:layout_marginBottom="1dip"
+            >
+
+            <LinearLayout android:id="@+id/playPauseFrame"
+                android:orientation="horizontal"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="1dip"
+                android:layout_marginTop="1dip"
+                android:layout_marginRight="3dip"
+                android:layout_marginBottom="1dip" >
+
+                <ImageButton android:id="@+id/stop1"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center_vertical|left"
+                    android:layout_weight="0.0"
+                    android:src="@drawable/stop"/>
+
+                 <ImageButton android:id="@+id/playPause1"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center_vertical|center"
+                    android:layout_weight="0.0"
+                    android:src="@android:drawable/ic_media_play"/>
+
+                 <ToggleButton android:id="@+id/attachButton"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center_vertical|right"
+                    android:layout_weight="0.0"
+                    android:textOff="@string/effect_attach_off"
+                    android:textOn="@string/effect_attach_on" />
+             </LinearLayout>
+
+             <TextView android:id="@+id/sessionText"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content" />
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:orientation="vertical"
+            android:layout_gravity="right"
+            android:layout_weight="1.0"
+            android:layout_marginLeft="3dip"
+            android:layout_marginTop="3dip"
+            android:layout_marginRight="1dip"
+            android:layout_marginBottom="3dip"
+            >
+
+            <TextView android:id="@+id/sendLevelText"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/send_level_name" />
+
+            <SeekBar android:id="@+id/sendLevelSeekBar"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:max="100"
+                android:progress="50"
+                android:layout_marginLeft="10dip"
+                android:layout_marginRight="30dip" />
+
+            <TextView android:id="@+id/sendLevelValue"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content" />
+
+        </LinearLayout>
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content" >
+
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/rvbParam1Name"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/rvb_param_1_name" />
+
+                <SeekBar android:id="@+id/rvbParam1SeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/rvbParam1Value"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/rvbParam2Name"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/rvb_param_2_name" />
+
+                <SeekBar android:id="@+id/rvbParam2SeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/rvbParam2Value"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/rvbParam3Name"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/rvb_param_3_name" />
+
+                <SeekBar android:id="@+id/rvbParam3SeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/rvbParam3Value"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/rvbParam4Name"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/rvb_param_4_name" />
+
+                <SeekBar android:id="@+id/rvbParam4SeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/rvbParam4Value"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/rvbParam5Name"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/rvb_param_5_name" />
+
+                <SeekBar android:id="@+id/rvbParam5SeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/rvbParam5Value"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/rvbParam6Name"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/rvb_param_6_name" />
+
+                <SeekBar android:id="@+id/rvbParam6SeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/rvbParam6Value"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/rvbParam7Name"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/rvb_param_7_name" />
+
+                <SeekBar android:id="@+id/rvbParam7SeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/rvbParam7Value"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/rvbParam8Name"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/rvb_param_8_name" />
+
+                <SeekBar android:id="@+id/rvbParam8SeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/rvbParam8Value"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/rvbParam9Name"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/rvb_param_9_name" />
+
+                <SeekBar android:id="@+id/rvbParam9SeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/rvbParam9Value"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/rvbParam10Name"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/rvb_param_10_name" />
+
+                <SeekBar android:id="@+id/rvbParam10SeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/rvbParam10Value"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+        </LinearLayout>
+
+    </ScrollView>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+</LinearLayout>
diff --git a/media/tests/EffectsTest/res/layout/equalizertest.xml b/media/tests/EffectsTest/res/layout/equalizertest.xml
new file mode 100755
index 0000000..5ef035d
--- /dev/null
+++ b/media/tests/EffectsTest/res/layout/equalizertest.xml
@@ -0,0 +1,470 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical">
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/eqReleaseLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/eqReleaseText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="1.0"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/effect_release"
+            style="@android:style/TextAppearance.Medium" />
+
+        <ToggleButton android:id="@+id/eqReleaseButton"
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent"
+            android:layout_gravity="center_vertical|right"
+            android:layout_weight="0.0" />
+
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/eqControlLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/eqControlText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="1.0"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/effect_control"
+            style="@android:style/TextAppearance.Medium" />
+
+        <ToggleButton android:id="@+id/equalizerOnOff"
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent"
+            android:layout_gravity="center_vertical|right"
+            android:layout_weight="0.0" />
+
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/SessionFrame"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/sessionText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="0.5"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/session"
+            style="@android:style/TextAppearance.Medium" />
+
+        <EditText android:id="@+id/sessionEdit"
+            android:singleLine="true"
+            android:numeric="integer"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="0.5"
+            android:layout_gravity="center_vertical|right" />
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content" >
+
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/eqParam1Name"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/eq_param_1_name" />
+
+                <LinearLayout android:id="@+id/eqParam1Desc"
+                    android:orientation="horizontal"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginTop="10dip"
+                    android:layout_marginRight="10dip"
+                    android:layout_marginBottom="10dip" >
+
+                    <TextView android:id="@+id/eqParam1Min"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1.0" />
+                    <TextView android:id="@+id/eqParam1Center"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1.0" />
+                    <TextView android:id="@+id/eqParam1Max"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1.0" />
+                </LinearLayout>
+
+                <SeekBar android:id="@+id/eqParam1SeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/eqParam1Value"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/eqParam2Name"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/eq_param_2_name" />
+
+                <LinearLayout android:id="@+id/eqParam2Desc"
+                    android:orientation="horizontal"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginTop="10dip"
+                    android:layout_marginRight="10dip"
+                    android:layout_marginBottom="10dip" >
+
+                    <TextView android:id="@+id/eqParam2Min"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1.0" />
+                    <TextView android:id="@+id/eqParam2Center"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1.0" />
+                    <TextView android:id="@+id/eqParam2Max"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1.0" />
+
+                </LinearLayout>
+
+                <SeekBar android:id="@+id/eqParam2SeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/eqParam2Value"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/eqParam3Name"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/eq_param_3_name" />
+
+                <LinearLayout android:id="@+id/eqParam3Desc"
+                    android:orientation="horizontal"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginTop="10dip"
+                    android:layout_marginRight="10dip"
+                    android:layout_marginBottom="10dip" >
+
+                    <TextView android:id="@+id/eqParam3Min"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1.0" />
+                    <TextView android:id="@+id/eqParam3Center"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1.0" />
+                    <TextView android:id="@+id/eqParam3Max"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1.0" />
+
+                </LinearLayout>
+
+                <SeekBar android:id="@+id/eqParam3SeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/eqParam3Value"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/eqParam4Name"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/eq_param_4_name" />
+
+                <LinearLayout android:id="@+id/eqParam4Desc"
+                    android:orientation="horizontal"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginTop="10dip"
+                    android:layout_marginRight="10dip"
+                    android:layout_marginBottom="10dip" >
+
+                    <TextView android:id="@+id/eqParam4Min"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1.0" />
+                    <TextView android:id="@+id/eqParam4Center"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1.0" />
+                    <TextView android:id="@+id/eqParam4Max"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1.0" />
+
+                </LinearLayout>
+
+                <SeekBar android:id="@+id/eqParam4SeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/eqParam4Value"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/eqParam5Name"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/eq_param_5_name" />
+
+                <LinearLayout android:id="@+id/eqParam5Desc"
+                    android:orientation="horizontal"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginTop="10dip"
+                    android:layout_marginRight="10dip"
+                    android:layout_marginBottom="10dip" >
+
+                    <TextView android:id="@+id/eqParam5Min"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1.0" />
+                    <TextView android:id="@+id/eqParam5Center"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1.0" />
+                    <TextView android:id="@+id/eqParam5Max"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1.0" />
+
+                </LinearLayout>
+
+                <SeekBar android:id="@+id/eqParam5SeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/eqParam5Value"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+
+                        <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/eqParam6Name"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/eq_param_6_name" />
+
+                <SeekBar android:id="@+id/eqParam6SeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/eqParam6Value"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+        </LinearLayout>
+
+    </ScrollView>
+
+</LinearLayout>
diff --git a/media/tests/EffectsTest/res/layout/presetreverbtest.xml b/media/tests/EffectsTest/res/layout/presetreverbtest.xml
new file mode 100755
index 0000000..cd7fbd3a
--- /dev/null
+++ b/media/tests/EffectsTest/res/layout/presetreverbtest.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical">
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/presetrvbReleaseLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/presetrvbReleaseText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="1.0"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/effect_release"
+            style="@android:style/TextAppearance.Medium" />
+
+        <ToggleButton android:id="@+id/presetrvbReleaseButton"
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent"
+            android:layout_gravity="center_vertical|right"
+            android:layout_weight="0.0" />
+
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/presetrvbControlLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/presetrvbControlText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="1.0"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/effect_control"
+            style="@android:style/TextAppearance.Medium" />
+
+        <ToggleButton android:id="@+id/presetrvbOnOff"
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent"
+            android:layout_gravity="center_vertical|right"
+            android:layout_weight="0.0" />
+
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/SessionFrame"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/sessionText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="0.5"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/session"
+            style="@android:style/TextAppearance.Medium" />
+
+        <EditText android:id="@+id/sessionEdit"
+            android:singleLine="true"
+            android:numeric="integer"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="0.5"
+            android:layout_gravity="center_vertical|right" />
+    </LinearLayout>
+
+  <ImageView
+       android:src="@android:drawable/divider_horizontal_dark"
+       android:layout_width="fill_parent"
+       android:layout_height="wrap_content"
+       android:scaleType="fitXY"/>
+
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content" >
+
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center_horizontal"
+            android:orientation="vertical"
+            android:layout_marginLeft="10dip"
+            android:layout_marginTop="10dip"
+            android:layout_marginRight="10dip"
+            android:layout_marginBottom="10dip"
+            >
+
+            <TextView android:id="@+id/presetrvbParam1Name"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/presetrvb_param_1_name" />
+
+            <SeekBar android:id="@+id/presetrvbParam1SeekBar"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:max="100"
+                android:progress="50"
+                android:layout_marginLeft="10dip"
+                android:layout_marginRight="30dip" />
+
+            <TextView android:id="@+id/presetrvbParam1Value"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content" />
+
+        </LinearLayout>
+
+        <ImageView
+             android:src="@android:drawable/divider_horizontal_dark"
+             android:layout_width="fill_parent"
+             android:layout_height="wrap_content"
+             android:scaleType="fitXY"/>
+
+        </LinearLayout>
+
+    </ScrollView>
+
+</LinearLayout>
diff --git a/media/tests/EffectsTest/res/layout/virtualizertest.xml b/media/tests/EffectsTest/res/layout/virtualizertest.xml
new file mode 100755
index 0000000..1fafeab
--- /dev/null
+++ b/media/tests/EffectsTest/res/layout/virtualizertest.xml
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical">
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/virtReleaseLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/virtReleaseText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="1.0"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/effect_release"
+            style="@android:style/TextAppearance.Medium" />
+
+        <ToggleButton android:id="@+id/virtReleaseButton"
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent"
+            android:layout_gravity="center_vertical|right"
+            android:layout_weight="0.0" />
+
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/virtControlLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/virtControlText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="1.0"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/effect_control"
+            style="@android:style/TextAppearance.Medium" />
+
+        <ToggleButton android:id="@+id/virtualizerOnOff"
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent"
+            android:layout_gravity="center_vertical|right"
+            android:layout_weight="0.0" />
+
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/SessionFrame"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/sessionText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="0.5"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/session"
+            style="@android:style/TextAppearance.Medium" />
+
+        <EditText android:id="@+id/sessionEdit"
+            android:singleLine="true"
+            android:numeric="integer"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="0.5"
+            android:layout_gravity="center_vertical|right" />
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content" >
+
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <LinearLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:layout_marginLeft="10dip"
+                android:layout_marginTop="10dip"
+                android:layout_marginRight="10dip"
+                android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/virtStrengthName"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/stength_name" />
+
+                <LinearLayout android:id="@+id/virtStrengthDesc"
+                    android:orientation="horizontal"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginTop="10dip"
+                    android:layout_marginRight="30dip"
+                    android:layout_marginBottom="10dip" >
+
+                    <TextView android:id="@+id/virtStrengthMin"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1"
+                        android:layout_gravity="left"
+                        android:gravity="left"/>
+                    <TextView android:id="@+id/virtStrengthMax"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:layout_weight="1"
+                        android:layout_gravity="right"
+                        android:gravity="right"/>
+                </LinearLayout>
+
+                <SeekBar android:id="@+id/virtStrengthSeekBar"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:max="100"
+                    android:progress="50"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="30dip" />
+
+                <TextView android:id="@+id/virtStrengthValue"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+        </LinearLayout>
+
+    </ScrollView>
+
+</LinearLayout>
diff --git a/media/tests/EffectsTest/res/layout/visualizertest.xml b/media/tests/EffectsTest/res/layout/visualizertest.xml
new file mode 100755
index 0000000..50ac7bb
--- /dev/null
+++ b/media/tests/EffectsTest/res/layout/visualizertest.xml
@@ -0,0 +1,263 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical">
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/visuReleaseLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/visuReleaseText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="1.0"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/effect_release"
+            style="@android:style/TextAppearance.Medium" />
+
+        <ToggleButton android:id="@+id/visuReleaseButton"
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent"
+            android:layout_gravity="center_vertical|right"
+            android:layout_weight="0.0" />
+
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/visuControlLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/visuControlText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="1.0"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/effect_control"
+            style="@android:style/TextAppearance.Medium" />
+
+        <ToggleButton android:id="@+id/visualizerOnOff"
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent"
+            android:layout_gravity="center_vertical|right"
+            android:layout_weight="0.0" />
+
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/SessionFrame"
+          android:orientation="horizontal"
+          android:layout_width="fill_parent"
+          android:layout_height="wrap_content"
+          android:layout_marginLeft="10dip"
+          android:layout_marginTop="10dip"
+          android:layout_marginRight="10dip"
+          android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/sessionText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="0.5"
+            android:layout_gravity="center_vertical|left"
+            android:text="@string/session"
+            style="@android:style/TextAppearance.Medium" />
+
+        <EditText android:id="@+id/sessionEdit"
+            android:singleLine="true"
+            android:numeric="integer"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="0.5"
+            android:layout_gravity="center_vertical|right" />
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <LinearLayout android:id="@+id/visuCallbackLayout"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginBottom="10dip" >
+
+        <TextView android:id="@+id/visuCallbackText"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+          android:layout_weight="1.0"
+          android:layout_gravity="center_vertical|left"
+            android:text="@string/visu_callback"
+            style="@android:style/TextAppearance.Medium" />
+
+        <ToggleButton android:id="@+id/visuCallbackOnOff"
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent"
+          android:layout_gravity="center_vertical|right"
+          android:layout_weight="0.0" />
+
+    </LinearLayout>
+
+    <ImageView
+         android:src="@android:drawable/divider_horizontal_dark"
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:scaleType="fitXY"/>
+
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content" >
+
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center_horizontal"
+            android:orientation="vertical"
+            android:layout_marginLeft="10dip"
+            android:layout_marginTop="10dip"
+            android:layout_marginRight="10dip"
+            android:layout_marginBottom="10dip"
+                >
+
+                <TextView android:id="@+id/waveformName"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/waveform_name" />
+
+          <LinearLayout android:id="@+id/eqParam1Desc"
+              android:orientation="horizontal"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:layout_marginLeft="10dip"
+              android:layout_marginTop="10dip"
+              android:layout_marginRight="10dip"
+              android:layout_marginBottom="10dip" >
+
+            <TextView android:id="@+id/waveformMin"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent"
+                android:layout_weight="1.0" />
+            <TextView android:id="@+id/waveformCenter"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent"
+                android:layout_weight="1.0" />
+            <TextView android:id="@+id/waveformMax"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent"
+                android:layout_weight="1.0" />
+
+          </LinearLayout>
+
+            </LinearLayout>
+
+            <ImageView
+                 android:src="@android:drawable/divider_horizontal_dark"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 android:scaleType="fitXY"/>
+
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center_horizontal"
+            android:orientation="vertical"
+            android:layout_marginLeft="10dip"
+            android:layout_marginTop="10dip"
+            android:layout_marginRight="10dip"
+            android:layout_marginBottom="10dip"
+            >
+
+          <TextView android:id="@+id/fftName"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:text="@string/fft_name" />
+
+          <LinearLayout android:id="@+id/eqParam1Desc"
+              android:orientation="horizontal"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:layout_marginLeft="10dip"
+              android:layout_marginTop="10dip"
+              android:layout_marginRight="10dip"
+              android:layout_marginBottom="10dip" >
+
+            <TextView android:id="@+id/fftMin"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent"
+                android:layout_weight="1.0" />
+            <TextView android:id="@+id/fftCenter"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent"
+                android:layout_weight="1.0" />
+            <TextView android:id="@+id/fftMax"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent"
+                android:layout_weight="1.0" />
+
+          </LinearLayout>
+
+        </LinearLayout>
+
+        <ImageView
+             android:src="@android:drawable/divider_horizontal_dark"
+             android:layout_width="fill_parent"
+             android:layout_height="wrap_content"
+             android:scaleType="fitXY"/>
+
+
+        </LinearLayout>
+
+    </ScrollView>
+
+</LinearLayout>
diff --git a/media/tests/EffectsTest/res/raw/mp3_sample.mp3 b/media/tests/EffectsTest/res/raw/mp3_sample.mp3
new file mode 100644
index 0000000..a9d8635
--- /dev/null
+++ b/media/tests/EffectsTest/res/raw/mp3_sample.mp3
Binary files differ
diff --git a/media/tests/EffectsTest/res/raw/sine440_mo_16b_16k.wav b/media/tests/EffectsTest/res/raw/sine440_mo_16b_16k.wav
new file mode 100644
index 0000000..2538b4d6
--- /dev/null
+++ b/media/tests/EffectsTest/res/raw/sine440_mo_16b_16k.wav
Binary files differ
diff --git a/media/tests/EffectsTest/res/values/strings.xml b/media/tests/EffectsTest/res/values/strings.xml
new file mode 100755
index 0000000..2a85184
--- /dev/null
+++ b/media/tests/EffectsTest/res/values/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">Effects Test</string>
+    <string name="effect_control">Effect State</string>
+    <string name="effect_release">Effect Instantiated</string>
+    <string name="effect_bypass">Bypass</string>
+    <string name="envreverb_test_name">Environmental Reverb Test</string>
+    <string name="rvb_param_1_name">Room Level</string>
+    <string name="rvb_param_2_name">Room HF Level</string>
+    <string name="rvb_param_3_name">Decay Time</string>
+    <string name="rvb_param_4_name">Decay HF Ratio</string>
+    <string name="rvb_param_5_name">Reflections Level</string>
+    <string name="rvb_param_6_name">Reflections Delay</string>
+    <string name="rvb_param_7_name">Reverb Level</string>
+    <string name="rvb_param_8_name">Reverb Delay</string>
+    <string name="rvb_param_9_name">Diffusion</string>
+    <string name="rvb_param_10_name">Density</string>
+    <string name="presetrvb_test_name">Preset Reverb Test</string>
+    <string name="presetrvb_param_1_name">Presets</string>
+    <string name="equalizer_test_name">Equalizer Test</string>
+    <string name="session">Audio Session</string>
+    <string name="eq_param_1_name">Band 1 Level</string>
+    <string name="eq_param_2_name">Band 2 Level</string>
+    <string name="eq_param_3_name">Band 3 Level</string>
+    <string name="eq_param_4_name">Band 4 Level</string>
+    <string name="eq_param_5_name">Band 5 Level</string>
+    <string name="eq_param_6_name">Presets</string>
+    <string name="virtualizer_test_name">Virtualizer Test</string>
+    <string name="stength_name">Strength</string>
+    <string name="bassboost_test_name">Bass Boost Test</string>
+    <string name="visualizer_test_name">Visualizer Test</string>
+    <string name="visu_callback">Callback Mode</string>
+    <string name="waveform_name">PCM capture</string>
+    <string name="fft_name">FFT Capture</string>
+    <string name="effect_attach_off">Attach</string>
+    <string name="effect_attach_on">Detach</string>
+    <string name="send_level_name">Send Level</string>
+</resources>
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java b/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java
new file mode 100755
index 0000000..1a10d64
--- /dev/null
+++ b/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java
@@ -0,0 +1,276 @@
+/*
+ * 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.
+ */
+
+package com.android.effectstest;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.View.OnClickListener;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.EditText;
+import android.widget.SeekBar;
+import android.widget.ToggleButton;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+
+import android.media.audiofx.BassBoost;
+import android.media.audiofx.AudioEffect;
+
+public class BassBoostTest extends Activity implements OnCheckedChangeListener {
+
+    private final static String TAG = "BassBoostTest";
+
+    private static int NUM_PARAMS = 1;
+
+    private EffectParameter mStrength;
+    private BassBoost mBassBoost = null;
+    ToggleButton mOnOffButton;
+    ToggleButton mReleaseButton;
+    EditText mSessionText;
+    static int sSession = 0;
+    EffectListner mEffectListener = new EffectListner();
+    private static HashMap<Integer, BassBoost> sInstances = new HashMap<Integer, BassBoost>(10);
+    String mSettings = "";
+
+    public BassBoostTest() {
+        Log.d(TAG, "contructor");
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        SeekBar seekBar;
+        TextView textView;
+
+        setContentView(R.layout.bassboosttest);
+
+        mSessionText = (EditText) findViewById(R.id.sessionEdit);
+        mSessionText.setOnKeyListener(mSessionKeyListener);
+
+        mSessionText.setText(Integer.toString(sSession));
+
+        mReleaseButton = (ToggleButton)findViewById(R.id.bbReleaseButton);
+        mOnOffButton = (ToggleButton)findViewById(R.id.bassboostOnOff);
+
+        getEffect(sSession);
+
+        if (mBassBoost != null) {
+            mReleaseButton.setOnCheckedChangeListener(this);
+            mOnOffButton.setOnCheckedChangeListener(this);
+
+            textView = (TextView)findViewById(R.id.bbStrengthMin);
+            textView.setText("0");
+            textView = (TextView)findViewById(R.id.bbStrengthMax);
+            textView.setText("1000");
+            seekBar = (SeekBar)findViewById(R.id.bbStrengthSeekBar);
+            textView = (TextView)findViewById(R.id.bbStrengthValue);
+            mStrength = new BassBoostParam(mBassBoost, 0, 1000, seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mStrength);
+            mStrength.setEnabled(mBassBoost.getStrengthSupported());
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+    }
+
+    private View.OnKeyListener mSessionKeyListener
+    = new View.OnKeyListener() {
+        public boolean onKey(View v, int keyCode, KeyEvent event) {
+            Log.d(TAG, "onKey() keyCode: "+keyCode+" event.getAction(): "+event.getAction());
+            if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                switch (keyCode) {
+                    case KeyEvent.KEYCODE_DPAD_CENTER:
+                    case KeyEvent.KEYCODE_ENTER:
+                        try {
+                            sSession = Integer.parseInt(mSessionText.getText().toString());
+                            getEffect(sSession);
+                            if (mBassBoost != null) {
+                                mStrength.setEffect(mBassBoost);
+                                mStrength.setEnabled(mBassBoost.getStrengthSupported());
+                            }
+                        } catch (NumberFormatException e) {
+                            Log.d(TAG, "Invalid session #: "+mSessionText.getText().toString());
+                        }
+                        return true;
+                }
+            }
+            return false;
+        }
+    };
+
+    // OnCheckedChangeListener
+    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+        if (buttonView.getId() == R.id.bassboostOnOff) {
+            if (mBassBoost != null) {
+                mBassBoost.setEnabled(isChecked);
+                mStrength.updateDisplay();
+            }
+        }
+        if (buttonView.getId() == R.id.bbReleaseButton) {
+            if (isChecked) {
+                if (mBassBoost == null) {
+                    getEffect(sSession);
+                    if (mBassBoost != null) {
+                        mStrength.setEffect(mBassBoost);
+                        mStrength.setEnabled(mBassBoost.getStrengthSupported());
+                    }
+                }
+            } else {
+                if (mBassBoost != null) {
+                    mStrength.setEnabled(false);
+                    putEffect(sSession);
+                }
+            }
+        }
+    }
+
+    private class BassBoostParam extends EffectParameter {
+        private BassBoost mBassBoost;
+
+        public BassBoostParam(BassBoost bassboost, int min, int max, SeekBar seekBar, TextView textView) {
+            super (min, max, seekBar, textView, "o/oo");
+
+            mBassBoost = bassboost;
+            updateDisplay();
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+            if (mBassBoost != null) {
+                mBassBoost.setStrength(value.shortValue());
+            }
+        }
+
+        @Override
+        public Integer getParameter() {
+            if (mBassBoost != null) {
+                return new Integer(mBassBoost.getRoundedStrength());
+            }
+            return new Integer(0);
+        }
+
+        @Override
+        public void setEffect(Object effect) {
+            mBassBoost = (BassBoost)effect;
+        }
+    }
+
+    public class EffectListner implements AudioEffect.OnEnableStatusChangeListener,
+        AudioEffect.OnControlStatusChangeListener, AudioEffect.OnParameterChangeListener
+   {
+        public EffectListner() {
+        }
+        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
+            Log.d(TAG,"onEnableStatusChange: "+ enabled);
+        }
+        public void onControlStatusChange(AudioEffect effect, boolean controlGranted) {
+            Log.d(TAG,"onControlStatusChange: "+ controlGranted);
+        }
+        public void onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value) {
+            int p = byteArrayToInt(param, 0);
+            short v = byteArrayToShort(value, 0);
+
+            Log.d(TAG,"onParameterChange, status: "+status+" p: "+p+" v: "+v);
+        }
+
+        private int byteArrayToInt(byte[] valueBuf, int offset) {
+            ByteBuffer converter = ByteBuffer.wrap(valueBuf);
+            converter.order(ByteOrder.nativeOrder());
+            return converter.getInt(offset);
+
+        }
+        private short byteArrayToShort(byte[] valueBuf, int offset) {
+            ByteBuffer converter = ByteBuffer.wrap(valueBuf);
+            converter.order(ByteOrder.nativeOrder());
+            return converter.getShort(offset);
+
+        }
+
+    }
+
+    private void getEffect(int session) {
+        synchronized (sInstances) {
+            if (sInstances.containsKey(session)) {
+                mBassBoost = sInstances.get(session);
+            } else {
+                try{
+                    mBassBoost = new BassBoost(0, session);
+                } catch (IllegalArgumentException e) {
+                    Log.e(TAG,"BassBoost effect not supported");
+                } catch (IllegalStateException e) {
+                    Log.e(TAG,"BassBoost cannot get strength supported");
+                } catch (UnsupportedOperationException e) {
+                    Log.e(TAG,"BassBoost library not loaded");
+                } catch (RuntimeException e) {
+                    Log.e(TAG,"BassBoost effect not found");
+                }
+                sInstances.put(session, mBassBoost);
+            }
+            mReleaseButton.setEnabled(false);
+            mOnOffButton.setEnabled(false);
+
+            if (mBassBoost != null) {
+                if (mSettings != "") {
+                    mBassBoost.setProperties(new BassBoost.Settings(mSettings));
+                }
+                mBassBoost.setEnableStatusListener(mEffectListener);
+                mBassBoost.setControlStatusListener(mEffectListener);
+                mBassBoost.setParameterListener(mEffectListener);
+
+                mReleaseButton.setChecked(true);
+                mReleaseButton.setEnabled(true);
+
+                mOnOffButton.setChecked(mBassBoost.getEnabled());
+                mOnOffButton.setEnabled(true);
+            }
+        }
+    }
+
+    private void putEffect(int session) {
+        mOnOffButton.setChecked(false);
+        mOnOffButton.setEnabled(false);
+        synchronized (sInstances) {
+            if (mBassBoost != null) {
+                mSettings = mBassBoost.getProperties().toString();
+                mBassBoost.release();
+                Log.d(TAG,"BassBoost released");
+                mBassBoost = null;
+                sInstances.remove(session);
+            }
+        }
+    }
+
+}
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EffectParameter.java b/media/tests/EffectsTest/src/com/android/effectstest/EffectParameter.java
new file mode 100755
index 0000000..95077e7
--- /dev/null
+++ b/media/tests/EffectsTest/src/com/android/effectstest/EffectParameter.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+package com.android.effectstest;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.TextView;
+import android.widget.SeekBar;
+
+
+abstract class EffectParameter implements SeekBar.OnSeekBarChangeListener {
+
+    private final static String TAG = "EffectParameter";
+
+    protected int mMin;
+    protected int mMax;
+    protected String mUnit;
+    protected SeekBar mSeekBar;
+    protected TextView mValueText;
+
+    public EffectParameter (int min, int max, SeekBar seekBar, TextView textView, String unit) {
+        mMin = min;
+        mMax = max;
+        mSeekBar = seekBar;
+        mValueText = textView;
+        mUnit = unit;
+        byte[] paramBuf = new byte[4];
+
+        mSeekBar.setMax(max-min);
+    }
+
+    public void displayValue(int value, boolean fromTouch) {
+        String text = Integer.toString(value)+" "+mUnit;
+        mValueText.setText(text);
+        if (!fromTouch) {
+            mSeekBar.setProgress(value - mMin);
+        }
+    }
+
+    public void updateDisplay() {
+        displayValue(getParameter(), false);
+    }
+
+    public abstract void setParameter(Integer value);
+
+    public abstract Integer getParameter();
+
+    public abstract void setEffect(Object effect);
+
+    // SeekBar.OnSeekBarChangeListener
+    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
+
+        if (seekBar != mSeekBar) {
+            Log.e(TAG, "onProgressChanged called with wrong seekBar");
+            return;
+        }
+
+        int value = progress + mMin;
+        if (fromTouch) {
+            setParameter(value);
+        }
+
+        displayValue(getParameter(), fromTouch);
+    }
+
+    public void onStartTrackingTouch(SeekBar seekBar) {
+    }
+
+    public void onStopTrackingTouch(SeekBar seekBar) {
+    }
+
+    public void setEnabled(boolean e) {
+        mSeekBar.setEnabled(e);
+    }
+}
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EffectsTest.java b/media/tests/EffectsTest/src/com/android/effectstest/EffectsTest.java
new file mode 100755
index 0000000..70202463
--- /dev/null
+++ b/media/tests/EffectsTest/src/com/android/effectstest/EffectsTest.java
@@ -0,0 +1,208 @@
+/*
+ * 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.
+ */
+
+package com.android.effectstest;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.View.OnClickListener;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.ListView;
+import android.widget.BaseAdapter;
+import android.widget.LinearLayout;
+import android.media.audiofx.AudioEffect;
+
+import java.util.UUID;
+
+public class EffectsTest extends Activity {
+
+    private final static String TAG = "EffectsTest";
+
+
+    public EffectsTest() {
+        Log.d(TAG, "contructor");
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.effectstest);
+
+        Button button = (Button) findViewById(R.id.env_reverb_actvity);
+        button.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                startActivity(new Intent(EffectsTest.this, EnvReverbTest.class));
+            }
+        });
+
+        button = (Button) findViewById(R.id.preset_reverb_actvity);
+        button.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                startActivity(new Intent(EffectsTest.this, PresetReverbTest.class));
+            }
+        });
+
+        button = (Button) findViewById(R.id.equalizer_actvity);
+        button.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                startActivity(new Intent(EffectsTest.this, EqualizerTest.class));
+            }
+        });
+
+        button = (Button) findViewById(R.id.virtualizer_actvity);
+        button.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                startActivity(new Intent(EffectsTest.this, VirtualizerTest.class));
+            }
+        });
+
+        button = (Button) findViewById(R.id.bassboost_actvity);
+        button.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                startActivity(new Intent(EffectsTest.this, BassBoostTest.class));
+            }
+        });
+
+        button = (Button) findViewById(R.id.visualizer_actvity);
+        button.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                startActivity(new Intent(EffectsTest.this, VisualizerTest.class));
+            }
+        });
+
+        AudioEffect.Descriptor[] descriptors = AudioEffect.queryEffects();
+
+        ListView list = (ListView) findViewById(R.id.effect_list);
+        list.setAdapter(new EffectListAdapter(this, descriptors));
+
+    }
+
+    private class EffectListAdapter extends BaseAdapter {
+
+        private Context mContext;
+
+        AudioEffect.Descriptor[] mDescriptors;
+
+        public EffectListAdapter(Context context, AudioEffect.Descriptor[] descriptors) {
+            Log.d(TAG, "EffectListAdapter contructor");
+            mContext = context;
+            mDescriptors = descriptors;
+            for (int i = 0; i < mDescriptors.length; i++) {
+                Log.d(TAG, "Effect: "+i+" name: "+ mDescriptors[i].name);
+            }
+        }
+
+         public int getCount() {
+            Log.d(TAG, "EffectListAdapter getCount(): "+mDescriptors.length);
+            return mDescriptors.length;
+        }
+
+        public Object getItem(int position) {
+            Log.d(TAG, "EffectListAdapter getItem() at: "+position+" name: "
+                    +mDescriptors[position].name);
+            return mDescriptors[position];
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            EffectView ev;
+            if (convertView == null) {
+                Log.d(TAG, "getView() new EffectView position: " + position);
+                ev = new EffectView(mContext, mDescriptors);
+            } else {
+                Log.d(TAG, "getView() convertView position: " + position);
+                ev = new EffectView(mContext, mDescriptors);
+                //ev = (EffectView) convertView;
+            }
+            ev.set(position);
+            return ev;
+        }
+    }
+
+    private class EffectView extends LinearLayout {
+        private Context mContext;
+        AudioEffect.Descriptor[] mDescriptors;
+
+        public EffectView(Context context, AudioEffect.Descriptor[] descriptors) {
+            super(context);
+
+            mContext = context;
+            mDescriptors = descriptors;
+            this.setOrientation(VERTICAL);
+        }
+
+        public String effectUuidToString(UUID effectType) {
+            if (effectType.equals(AudioEffect.EFFECT_TYPE_VIRTUALIZER)) {
+                return "Virtualizer";
+            } else if (effectType.equals(AudioEffect.EFFECT_TYPE_ENV_REVERB)){
+                return "Reverb";
+            } else if (effectType.equals(AudioEffect.EFFECT_TYPE_PRESET_REVERB)){
+                return "Preset Reverb";
+            } else if (effectType.equals(AudioEffect.EFFECT_TYPE_EQUALIZER)){
+                return "Equalizer";
+            } else if (effectType.equals(AudioEffect.EFFECT_TYPE_BASS_BOOST)){
+                return "Bass Boost";
+            } else if (effectType.equals(AudioEffect.EFFECT_TYPE_AGC)){
+                return "Automatic Gain Control";
+            } else if (effectType.equals(AudioEffect.EFFECT_TYPE_AEC)){
+                return "Acoustic Echo Canceler";
+            } else if (effectType.equals(AudioEffect.EFFECT_TYPE_NS)){
+                return "Noise Suppressor";
+            }
+
+            return effectType.toString();
+        }
+
+        public void set(int position) {
+            TextView tv = new TextView(mContext);
+            tv.setText("Effect "+ position);
+            addView(tv, new LinearLayout.LayoutParams(
+                    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+            tv = new TextView(mContext);
+            tv.setText(" type: "+ effectUuidToString(mDescriptors[position].type));
+            addView(tv, new LinearLayout.LayoutParams(
+                    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+            tv = new TextView(mContext);
+            tv.setText(" uuid: "+ mDescriptors[position].uuid.toString());
+            addView(tv, new LinearLayout.LayoutParams(
+                    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+            tv = new TextView(mContext);
+            tv.setText(" name: "+ mDescriptors[position].name);
+            addView(tv, new LinearLayout.LayoutParams(
+                    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+            tv = new TextView(mContext);
+            tv.setText(" vendor: "+ mDescriptors[position].implementor);
+            addView(tv, new LinearLayout.LayoutParams(
+                    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+            tv = new TextView(mContext);
+            tv.setText(" mode: "+ mDescriptors[position].connectMode);
+            addView(tv, new LinearLayout.LayoutParams(
+                    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+        }
+    }
+
+}
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java b/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java
new file mode 100755
index 0000000..594e844
--- /dev/null
+++ b/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java
@@ -0,0 +1,568 @@
+/*
+ * 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.
+ */
+
+package com.android.effectstest;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.View.OnClickListener;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.SeekBar;
+import android.widget.ToggleButton;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import java.util.HashMap;
+import java.util.Map;
+
+import android.media.audiofx.EnvironmentalReverb;
+import android.media.audiofx.AudioEffect;
+import android.media.AudioManager;
+
+public class EnvReverbTest extends Activity implements OnCheckedChangeListener, SeekBar.OnSeekBarChangeListener {
+
+    private final static String TAG = "EnvReverbTest";
+
+    private static int NUM_PARAMS = 10;
+
+    private EffectParameter[] mParameters = new EffectParameter[NUM_PARAMS];
+    private EnvironmentalReverb mReverb;
+    ToggleButton mOnOffButton;
+    ToggleButton mReleaseButton;
+    ToggleButton mAttachButton;
+    private static HashMap<Integer, EnvironmentalReverb> sInstances = new HashMap<Integer, EnvironmentalReverb>(10);
+    static SimplePlayer sPlayerController = null;
+    SeekBar mSendLevelSeekBar;
+    TextView mSendLevelDisplay;
+    static float sSendLevel = linToExp(50,100);
+    static boolean sAttached = false;
+    String mSettings = "";
+
+    public EnvReverbTest() {
+        Log.d(TAG, "contructor");
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        Log.d(TAG, "onCreate");
+        SeekBar seekBar;
+        TextView textView;
+        ToggleButton button;
+        setContentView(R.layout.envreverbtest);
+
+        ImageView playPause = (ImageView) findViewById(R.id.playPause1);
+        ImageView stop = (ImageView) findViewById(R.id.stop1);
+        textView = (TextView) findViewById(R.id.sessionText);
+        if (sPlayerController == null) {
+            sPlayerController = new SimplePlayer(this, R.id.playPause1, playPause,
+                    R.id.stop1, stop, textView,
+                    R.raw.mp3_sample, AudioManager.STREAM_MUSIC, 0);
+        } else {
+            sPlayerController.set(this, R.id.playPause1, playPause,
+                    R.id.stop1, stop, textView,
+                    AudioManager.STREAM_MUSIC, 0);
+        }
+
+        // send level
+        mSendLevelSeekBar = (SeekBar)findViewById(R.id.sendLevelSeekBar);
+        mSendLevelDisplay = (TextView)findViewById(R.id.sendLevelValue);
+        mSendLevelSeekBar.setMax(100);
+        mSendLevelSeekBar.setOnSeekBarChangeListener(this);
+        mSendLevelSeekBar.setProgress(expToLin(sSendLevel,100));
+        sPlayerController.setAuxEffectSendLevel(sSendLevel);
+
+        mOnOffButton = (ToggleButton)findViewById(R.id.rvbOnOff);
+        mReleaseButton = (ToggleButton)findViewById(R.id.rvbReleaseButton);
+        mAttachButton = (ToggleButton)findViewById(R.id.attachButton);
+
+        getEffect(0);
+
+        if (mReverb != null) {
+            mOnOffButton.setOnCheckedChangeListener(this);
+            mReleaseButton.setOnCheckedChangeListener(this);
+            mAttachButton.setOnCheckedChangeListener(this);
+
+//            button = (ToggleButton)findViewById(R.id.rvbBypass);
+//            button.setChecked(false);
+//            button.setOnCheckedChangeListener(this);
+
+            // Room level
+            seekBar = (SeekBar)findViewById(R.id.rvbParam1SeekBar);
+            textView = (TextView)findViewById(R.id.rvbParam1Value);
+            mParameters[0] = new RoomLevelParam(mReverb, seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[0]);
+
+            // Room HF level
+            seekBar = (SeekBar)findViewById(R.id.rvbParam2SeekBar);
+            textView = (TextView)findViewById(R.id.rvbParam2Value);
+            mParameters[1] = new RoomHFLevelParam(mReverb, seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[1]);
+
+            // Decay time
+            seekBar = (SeekBar)findViewById(R.id.rvbParam3SeekBar);
+            textView = (TextView)findViewById(R.id.rvbParam3Value);
+            mParameters[2] = new DecayTimeParam(mReverb, seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[2]);
+
+            // Decay HF ratio
+            seekBar = (SeekBar)findViewById(R.id.rvbParam4SeekBar);
+            textView = (TextView)findViewById(R.id.rvbParam4Value);
+            mParameters[3] = new DecayHFRatioParam(mReverb, seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[3]);
+
+            // Reflections level
+            seekBar = (SeekBar)findViewById(R.id.rvbParam5SeekBar);
+            textView = (TextView)findViewById(R.id.rvbParam5Value);
+            mParameters[4] = new ReflectionsLevelParam(mReverb, seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[4]);
+
+            // Reflections delay
+            seekBar = (SeekBar)findViewById(R.id.rvbParam6SeekBar);
+            textView = (TextView)findViewById(R.id.rvbParam6Value);
+            mParameters[5] = new ReflectionsDelayParam(mReverb, seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[5]);
+
+            // Reverb level
+            seekBar = (SeekBar)findViewById(R.id.rvbParam7SeekBar);
+            textView = (TextView)findViewById(R.id.rvbParam7Value);
+            mParameters[6] = new ReverbLevelParam(mReverb, seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[6]);
+
+            // Reverb delay
+            seekBar = (SeekBar)findViewById(R.id.rvbParam8SeekBar);
+            textView = (TextView)findViewById(R.id.rvbParam8Value);
+            mParameters[7] = new ReverbDelayParam(mReverb, seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[7]);
+
+            // Diffusion
+            seekBar = (SeekBar)findViewById(R.id.rvbParam9SeekBar);
+            textView = (TextView)findViewById(R.id.rvbParam9Value);
+            mParameters[8] = new DiffusionParam(mReverb, seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[8]);
+
+            // Density
+            seekBar = (SeekBar)findViewById(R.id.rvbParam10SeekBar);
+            textView = (TextView)findViewById(R.id.rvbParam10Value);
+            mParameters[9] = new DensityParam(mReverb, seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[9]);
+        }
+    }
+    @Override
+    public void onResume() {
+        super.onResume();
+        Log.d(TAG, "onResume");
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+    }
+
+    // OnCheckedChangeListener
+    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+        if (buttonView.getId() == R.id.rvbOnOff) {
+            if (mReverb != null) {
+                mReverb.setEnabled(isChecked);
+                Log.d(TAG,"onCheckedChanged: rvbOnOff");
+                for (int i = 0 ; i < mParameters.length; i++) {
+                    mParameters[i].updateDisplay();
+                }
+            }
+        }
+        if (buttonView.getId() == R.id.rvbReleaseButton) {
+            if (isChecked) {
+                if (mReverb == null) {
+                    getEffect(0);
+                    for (int i = 0 ; i < mParameters.length; i++) {
+                        mParameters[i].setEffect(mReverb);
+                        mParameters[i].setEnabled(true);
+                    }
+                }
+            } else {
+                if (mReverb != null) {
+                    for (int i = 0 ; i < mParameters.length; i++) {
+                        mParameters[i].setEnabled(false);
+                    }
+                    putEffect(0);
+                }
+            }
+        }
+//        if (buttonView.getId() == R.id.rvbBypass) {
+//            // REVERB_PARAM_BYPASS parametervalue is 11 in EffectEnvironmentalReverApi.h
+//            if (mReverb != null) {
+//                if (isChecked) {
+//                    mReverb.setParameter((int)11, (int)1);
+//                } else {
+//                    mReverb.setParameter((int)11, (int)0);
+//                }
+//            }
+//        }
+        if (buttonView.getId() == R.id.attachButton) {
+            if (mReverb != null) {
+                if (isChecked) {
+                    sPlayerController.attachAuxEffect(mReverb.getId());
+                    sAttached = true;
+                } else {
+                    sPlayerController.attachAuxEffect(0);
+                    sAttached = false;
+                }
+            }
+        }
+    }
+
+    // SeekBar.OnSeekBarChangeListener
+    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
+
+        if (seekBar != mSendLevelSeekBar) {
+            Log.e(TAG, "onProgressChanged called with wrong seekBar");
+            return;
+        }
+
+        sSendLevel = linToExp(progress,100);
+        if (fromTouch) {
+            sPlayerController.setAuxEffectSendLevel(sSendLevel);
+        }
+        String text = Float.toString(sSendLevel);
+        mSendLevelDisplay.setText(text);
+        if (!fromTouch) {
+            seekBar.setProgress(progress);
+        }
+    }
+
+    static float linToExp(int lin, int range) {
+        if (lin == 0) return 0;
+        return (float)Math.pow((double)10,(double)72*(lin-range)/(20*range));
+    }
+
+    static int expToLin(float exp, int range) {
+        if (exp == 0) return 0;
+        return (int)(20*range*Math.log10((double)exp)/72 + range);
+    }
+
+    public void onStartTrackingTouch(SeekBar seekBar) {
+    }
+
+    public void onStopTrackingTouch(SeekBar seekBar) {
+    }
+
+    private class EnvReverbParam extends EffectParameter {
+        private EnvironmentalReverb mReverb;
+
+        public EnvReverbParam(EnvironmentalReverb reverb, int min, int max, SeekBar seekBar, TextView textView, String unit) {
+            super (min, max, seekBar, textView, unit);
+            mReverb = reverb;
+            updateDisplay();
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+        }
+
+        @Override
+        public Integer getParameter() {
+            return new Integer(0);
+        }
+
+        @Override
+        public void setEffect(Object reverb) {
+            mReverb = (EnvironmentalReverb)reverb;
+        }
+    }
+
+    private class RoomLevelParam extends EnvReverbParam {
+
+        public RoomLevelParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
+            super (reverb, -9600, 0, seekBar, textView, "mB");
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+            if (mReverb != null) {
+                mReverb.setRoomLevel(value.shortValue());
+            }
+        }
+
+        @Override
+        public Integer getParameter() {
+            if (mReverb != null) {
+                return new Integer(mReverb.getRoomLevel());
+            }
+            return new Integer(0);
+        }
+    }
+
+    private class RoomHFLevelParam extends EnvReverbParam {
+
+        public RoomHFLevelParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
+            super (reverb, -4000, 0, seekBar, textView, "mB");
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+            if (mReverb != null) {
+                mReverb.setRoomHFLevel(value.shortValue());
+            }
+        }
+
+        @Override
+        public Integer getParameter() {
+            if (mReverb != null) {
+                return new Integer(mReverb.getRoomHFLevel());
+            }
+            return new Integer(0);
+        }
+    }
+
+    private class DecayTimeParam extends EnvReverbParam {
+
+        public DecayTimeParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
+            super (reverb, 200, 4000, seekBar, textView, "ms");
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+            if (mReverb != null) {
+                mReverb.setDecayTime(value.intValue());
+            }
+        }
+
+        @Override
+        public Integer getParameter() {
+            if (mReverb != null) {
+                return mReverb.getDecayTime();
+            }
+            return new Integer(0);
+        }
+    }
+
+    private class DecayHFRatioParam extends EnvReverbParam {
+
+        public DecayHFRatioParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
+            super (reverb, 100, 1000, seekBar, textView, "permilles");
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+            if (mReverb != null) {
+                mReverb.setDecayHFRatio(value.shortValue());
+            }
+        }
+
+        @Override
+        public Integer getParameter() {
+            if (mReverb != null) {
+                return new Integer(mReverb.getDecayHFRatio());
+            }
+            return new Integer(0);
+        }
+    }
+
+    private class ReflectionsLevelParam extends EnvReverbParam {
+
+        public ReflectionsLevelParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
+            super (reverb, -9600, 0, seekBar, textView, "mB");
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+            if (mReverb != null) {
+                mReverb.setReflectionsLevel(value.shortValue());
+            }
+        }
+
+        @Override
+        public Integer getParameter() {
+            if (mReverb != null) {
+                return new Integer(mReverb.getReflectionsLevel());
+            }
+            return new Integer(0);
+        }
+    }
+
+    private class ReflectionsDelayParam extends EnvReverbParam {
+
+        public ReflectionsDelayParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
+            super (reverb, 0, 65, seekBar, textView, "ms");
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+            if (mReverb != null) {
+                mReverb.setReflectionsDelay(value.intValue());
+            }
+        }
+
+        @Override
+        public Integer getParameter() {
+            if (mReverb != null) {
+                return mReverb.getReflectionsDelay();
+            }
+            return new Integer(0);
+        }
+    }
+
+    private class ReverbLevelParam extends EnvReverbParam {
+
+        public ReverbLevelParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
+            super (reverb, -9600, 2000, seekBar, textView, "mB");
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+            if (mReverb != null) {
+                mReverb.setReverbLevel(value.shortValue());
+            }
+        }
+
+        @Override
+        public Integer getParameter() {
+            if (mReverb != null) {
+                return new Integer(mReverb.getReverbLevel());
+            }
+            return new Integer(0);
+        }
+    }
+
+    private class ReverbDelayParam extends EnvReverbParam {
+
+        public ReverbDelayParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
+            super (reverb, 0, 65, seekBar, textView, "ms");
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+            if (mReverb != null) {
+                mReverb.setReverbDelay(value.intValue());
+            }
+        }
+
+        @Override
+        public Integer getParameter() {
+            if (mReverb != null) {
+                return mReverb.getReverbDelay();
+            }
+            return new Integer(0);
+        }
+    }
+
+    private class DiffusionParam extends EnvReverbParam {
+
+        public DiffusionParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
+            super (reverb, 0, 1000, seekBar, textView, "permilles");
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+            if (mReverb != null) {
+                mReverb.setDiffusion(value.shortValue());
+            }
+        }
+
+        @Override
+        public Integer getParameter() {
+            if (mReverb != null) {
+                return new Integer(mReverb.getDiffusion());
+            }
+            return new Integer(0);
+        }
+    }
+
+    private class DensityParam extends EnvReverbParam {
+
+        public DensityParam(EnvironmentalReverb reverb, SeekBar seekBar, TextView textView) {
+            super (reverb, 0, 1000, seekBar, textView, "permilles");
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+            if (mReverb != null) {
+                mReverb.setDensity(value.shortValue());
+            }
+        }
+
+        @Override
+        public Integer getParameter() {
+            if (mReverb != null) {
+                return new Integer(mReverb.getDensity());
+            }
+            return new Integer(0);
+        }
+    }
+
+    private void getEffect(int session) {
+        synchronized (sInstances) {
+            if (sInstances.containsKey(session)) {
+                mReverb = sInstances.get(session);
+            } else {
+                try{
+                    mReverb = new EnvironmentalReverb(0, session);
+                } catch (IllegalArgumentException e) {
+                    Log.e(TAG,"Reverb effect not supported");
+                } catch (UnsupportedOperationException e) {
+                    Log.e(TAG,"Reverb library not loaded");
+                } catch (RuntimeException e) {
+                    Log.e(TAG,"Reverb effect not found");
+                }
+                Log.d(TAG, "new reverb: "+mReverb);
+                sInstances.put(session, mReverb);
+            }
+        }
+        mReleaseButton.setEnabled(false);
+        mOnOffButton.setEnabled(false);
+        mAttachButton.setEnabled(false);
+        if (mReverb != null) {
+            if (mSettings != "") {
+                mReverb.setProperties(new EnvironmentalReverb.Settings(mSettings));
+            }
+            mReleaseButton.setChecked(true);
+            mReleaseButton.setEnabled(true);
+            mOnOffButton.setChecked(mReverb.getEnabled());
+            mOnOffButton.setEnabled(true);
+            mAttachButton.setChecked(false);
+            mAttachButton.setEnabled(true);
+            if (sAttached) {
+                mAttachButton.setChecked(true);
+                sPlayerController.attachAuxEffect(mReverb.getId());
+            }
+        }
+    }
+
+    private void putEffect(int session) {
+        mOnOffButton.setChecked(false);
+        mOnOffButton.setEnabled(false);
+        mAttachButton.setChecked(false);
+        mAttachButton.setEnabled(false);
+        synchronized (sInstances) {
+            if (mReverb != null) {
+                mSettings = mReverb.getProperties().toString();
+                mReverb.release();
+                Log.d(TAG,"Reverb released, settings: "+mSettings);
+                mReverb = null;
+                sInstances.remove(session);
+            }
+        }
+    }
+}
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java b/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java
new file mode 100755
index 0000000..f30a26f
--- /dev/null
+++ b/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java
@@ -0,0 +1,407 @@
+/*
+ * 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.
+ */
+
+package com.android.effectstest;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.View.OnClickListener;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.EditText;
+import android.widget.SeekBar;
+import android.widget.ToggleButton;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+
+
+import android.media.audiofx.Equalizer;
+import android.media.audiofx.AudioEffect;
+
+public class EqualizerTest extends Activity implements OnCheckedChangeListener {
+
+    private final static String TAG = "EqualizerTest";
+
+    private static int NUM_BANDS = 5;
+    private static int NUM_PARAMS = NUM_BANDS + 1;
+
+    private EffectParameter[] mParameters = new EffectParameter[NUM_PARAMS];
+    private Equalizer mEqualizer;
+    ToggleButton mOnOffButton;
+    ToggleButton mReleaseButton;
+    EditText mSessionText;
+    static int sSession = 0;
+    EffectListner mEffectListener = new EffectListner();
+    private static HashMap<Integer, Equalizer> sInstances = new HashMap<Integer, Equalizer>(10);
+    String mSettings = "";
+
+    public EqualizerTest() {
+        Log.d(TAG, "contructor");
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        SeekBar seekBar;
+        TextView textView;
+
+        setContentView(R.layout.equalizertest);
+
+        mSessionText = (EditText) findViewById(R.id.sessionEdit);
+        mSessionText.setOnKeyListener(mSessionKeyListener);
+
+        mSessionText.setText(Integer.toString(sSession));
+
+        mReleaseButton = (ToggleButton)findViewById(R.id.eqReleaseButton);
+        mOnOffButton = (ToggleButton)findViewById(R.id.equalizerOnOff);
+
+        getEffect(sSession);
+
+        if (mEqualizer != null) {
+            mReleaseButton.setOnCheckedChangeListener(this);
+            mOnOffButton.setOnCheckedChangeListener(this);
+
+            short[] bandLevelRange = mEqualizer.getBandLevelRange();
+            int centerFreq;
+            int []freqRange;
+
+            // Band 1 level
+            centerFreq = mEqualizer.getCenterFreq((short)0);
+            freqRange = mEqualizer.getBandFreqRange((short)0);
+            displayFreq(R.id.eqParam1Center, centerFreq);
+            displayFreq(R.id.eqParam1Min, freqRange[0]);
+            displayFreq(R.id.eqParam1Max, freqRange[1]);
+            seekBar = (SeekBar)findViewById(R.id.eqParam1SeekBar);
+            textView = (TextView)findViewById(R.id.eqParam1Value);
+            mParameters[0] = new BandLevelParam(mEqualizer, 0, bandLevelRange[0], bandLevelRange[1], seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[0]);
+
+            // Band 2 level
+            centerFreq = mEqualizer.getCenterFreq((short)1);
+            freqRange = mEqualizer.getBandFreqRange((short)1);
+            displayFreq(R.id.eqParam2Center, centerFreq);
+            displayFreq(R.id.eqParam2Min, freqRange[0]);
+            displayFreq(R.id.eqParam2Max, freqRange[1]);
+            seekBar = (SeekBar)findViewById(R.id.eqParam2SeekBar);
+            textView = (TextView)findViewById(R.id.eqParam2Value);
+            mParameters[1] = new BandLevelParam(mEqualizer, 1, bandLevelRange[0], bandLevelRange[1], seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[1]);
+
+            // Band 3 level
+            centerFreq = mEqualizer.getCenterFreq((short)2);
+            freqRange = mEqualizer.getBandFreqRange((short)2);
+            displayFreq(R.id.eqParam3Center, centerFreq);
+            displayFreq(R.id.eqParam3Min, freqRange[0]);
+            displayFreq(R.id.eqParam3Max, freqRange[1]);
+            seekBar = (SeekBar)findViewById(R.id.eqParam3SeekBar);
+            textView = (TextView)findViewById(R.id.eqParam3Value);
+            mParameters[2] = new BandLevelParam(mEqualizer, 2, bandLevelRange[0], bandLevelRange[1], seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[2]);
+
+            // Band 4 level
+            centerFreq = mEqualizer.getCenterFreq((short)3);
+            freqRange = mEqualizer.getBandFreqRange((short)3);
+            displayFreq(R.id.eqParam4Center, centerFreq);
+            displayFreq(R.id.eqParam4Min, freqRange[0]);
+            displayFreq(R.id.eqParam4Max, freqRange[1]);
+            seekBar = (SeekBar)findViewById(R.id.eqParam4SeekBar);
+            textView = (TextView)findViewById(R.id.eqParam4Value);
+            mParameters[3] = new BandLevelParam(mEqualizer, 3, bandLevelRange[0], bandLevelRange[1], seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[3]);
+
+            // Band 5 level
+            centerFreq = mEqualizer.getCenterFreq((short)4);
+            freqRange = mEqualizer.getBandFreqRange((short)4);
+            displayFreq(R.id.eqParam5Center, centerFreq);
+            displayFreq(R.id.eqParam5Min, freqRange[0]);
+            displayFreq(R.id.eqParam5Max, freqRange[1]);
+            seekBar = (SeekBar)findViewById(R.id.eqParam5SeekBar);
+            textView = (TextView)findViewById(R.id.eqParam5Value);
+            mParameters[4] = new BandLevelParam(mEqualizer, 4, bandLevelRange[0], bandLevelRange[1], seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[4]);
+
+            // Presets
+            short numPresets = mEqualizer.getNumberOfPresets();
+            seekBar = (SeekBar)findViewById(R.id.eqParam6SeekBar);
+            textView = (TextView)findViewById(R.id.eqParam6Value);
+            mParameters[5] = new PresetParam(mEqualizer, (short)0, (short)(numPresets-1), seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[5]);
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+    }
+
+    private View.OnKeyListener mSessionKeyListener
+    = new View.OnKeyListener() {
+        public boolean onKey(View v, int keyCode, KeyEvent event) {
+            if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                switch (keyCode) {
+                    case KeyEvent.KEYCODE_DPAD_CENTER:
+                    case KeyEvent.KEYCODE_ENTER:
+                        try {
+                            sSession = Integer.parseInt(mSessionText.getText().toString());
+                            getEffect(sSession);
+                            if (mEqualizer != null) {
+                                for (int i = 0 ; i < mParameters.length; i++) {
+                                    mParameters[i].setEffect(mEqualizer);
+                                    mParameters[i].setEnabled(true);
+                                }
+                            }
+                        } catch (NumberFormatException e) {
+                            Log.d(TAG, "Invalid session #: "+mSessionText.getText().toString());
+                        }
+
+                        return true;
+                }
+            }
+            return false;
+        }
+    };
+
+    // OnCheckedChangeListener
+    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+        if (buttonView.getId() == R.id.equalizerOnOff) {
+            if (mEqualizer != null) {
+                mEqualizer.setEnabled(isChecked);
+                updateBands();
+            }
+        }
+        if (buttonView.getId() == R.id.eqReleaseButton) {
+            if (isChecked) {
+                if (mEqualizer == null) {
+                    getEffect(sSession);
+                    if (mEqualizer != null) {
+                        for (int i = 0 ; i < mParameters.length; i++) {
+                            mParameters[i].setEffect(mEqualizer);
+                            mParameters[i].setEnabled(true);
+                        }
+                    }
+                }
+            } else {
+                if (mEqualizer != null) {
+                    for (int i = 0 ; i < mParameters.length; i++) {
+                        mParameters[i].setEnabled(false);
+                    }
+                    putEffect(sSession);
+                }
+            }
+        }
+    }
+
+    protected void updateBands() {
+        for (int i = 0 ; i < NUM_BANDS; i++) {
+            mParameters[i].updateDisplay();
+        }
+    }
+
+    private void displayFreq(int viewId, int freq) {
+        TextView textView = (TextView)findViewById(viewId);
+        String text = Integer.toString(freq/1000)+" Hz";
+        textView.setText(text);
+    }
+
+    private class EqualizerParam extends EffectParameter {
+        private Equalizer mEqualizer;
+
+        public EqualizerParam(Equalizer equalizer, int min, int max, SeekBar seekBar, TextView textView, String unit) {
+            super (min, max, seekBar, textView, unit);
+
+            mEqualizer = equalizer;
+            updateDisplay();
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+        }
+
+        @Override
+        public Integer getParameter() {
+            return new Integer(0);
+        }
+
+        @Override
+        public void setEffect(Object eq) {
+            mEqualizer = (Equalizer)eq;
+        }
+    }
+
+    private class BandLevelParam extends EqualizerParam {
+        private int mBand;
+
+        public BandLevelParam(Equalizer equalizer, int band, short min, short max, SeekBar seekBar, TextView textView) {
+            super (equalizer, min, max, seekBar, textView, "mB");
+
+            mBand = band;
+            mEqualizer = equalizer;
+            updateDisplay();
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+            if (mEqualizer != null) {
+                mEqualizer.setBandLevel((short)mBand, value.shortValue());
+            }
+        }
+
+        @Override
+        public Integer getParameter() {
+            if (mEqualizer != null) {
+                return new Integer(mEqualizer.getBandLevel((short)mBand));
+            }
+            return new Integer(0);
+        }
+    }
+
+    private class PresetParam extends EqualizerParam {
+
+        public PresetParam(Equalizer equalizer, short min, short max, SeekBar seekBar, TextView textView) {
+            super (equalizer, min, max, seekBar, textView, "");
+
+            mEqualizer = equalizer;
+            updateDisplay();
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+            if (mEqualizer != null) {
+                mEqualizer.usePreset(value.shortValue());
+            }
+        }
+
+        @Override
+        public Integer getParameter() {
+            if (mEqualizer != null) {
+                return new Integer(mEqualizer.getCurrentPreset());
+            }
+            return new Integer(0);
+        }
+
+        @Override
+        public void displayValue(int value, boolean fromTouch) {
+            String text = mEqualizer.getPresetName((short)value);
+            mValueText.setText(text);
+            if (!fromTouch) {
+                mSeekBar.setProgress(value - mMin);
+            } else {
+                updateBands();
+            }
+        }
+    }
+
+    public class EffectListner implements AudioEffect.OnEnableStatusChangeListener,
+    AudioEffect.OnControlStatusChangeListener,
+    Equalizer.OnParameterChangeListener
+   {
+        public EffectListner() {
+        }
+        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
+            Log.d(TAG,"onEnableStatusChange: "+ enabled);
+        }
+        public void onControlStatusChange(AudioEffect effect, boolean controlGranted) {
+            Log.d(TAG,"onControlStatusChange: "+ controlGranted);
+        }
+
+        public void onParameterChange(Equalizer effect, int status, int param1, int param2, int value) {
+            Log.d(TAG,"onParameterChange EQ, status: "+status+" p1: "+param1+" p2: "+param2+" v: "+value);
+        }
+
+        private int byteArrayToInt(byte[] valueBuf, int offset) {
+            ByteBuffer converter = ByteBuffer.wrap(valueBuf);
+            converter.order(ByteOrder.nativeOrder());
+            return converter.getInt(offset);
+
+        }
+        private short byteArrayToShort(byte[] valueBuf, int offset) {
+            ByteBuffer converter = ByteBuffer.wrap(valueBuf);
+            converter.order(ByteOrder.nativeOrder());
+            return converter.getShort(offset);
+
+        }
+    }
+
+    private void getEffect(int session) {
+        synchronized (sInstances) {
+            if (sInstances.containsKey(session)) {
+                mEqualizer = sInstances.get(session);
+            } else {
+                try{
+                    mEqualizer = new Equalizer(0, session);
+                } catch (IllegalArgumentException e) {
+                    Log.e(TAG,"Equalizer effect not supported");
+                } catch (UnsupportedOperationException e) {
+                    Log.e(TAG,"Equalizer library not loaded");
+                } catch (IllegalStateException e) {
+                    Log.e(TAG,"Equalizer cannot get presets");
+                } catch (RuntimeException e) {
+                    Log.e(TAG,"Equalizer effect not found");
+                }
+                sInstances.put(session, mEqualizer);
+            }
+        }
+        mReleaseButton.setEnabled(false);
+        mOnOffButton.setEnabled(false);
+        if (mEqualizer != null) {
+            if (mSettings != "") {
+                Log.d(TAG,"Equalizer settings: "+mSettings);
+                mEqualizer.setProperties(new Equalizer.Settings(mSettings));
+            }
+
+            mEqualizer.setEnableStatusListener(mEffectListener);
+            mEqualizer.setControlStatusListener(mEffectListener);
+            mEqualizer.setParameterListener(mEffectListener);
+
+            mReleaseButton.setChecked(true);
+            mReleaseButton.setEnabled(true);
+
+            mOnOffButton.setChecked(mEqualizer.getEnabled());
+            mOnOffButton.setEnabled(true);
+        }
+    }
+
+    private void putEffect(int session) {
+//        mOnOffButton.setChecked(false);
+        mOnOffButton.setEnabled(false);
+        synchronized (sInstances) {
+            if (mEqualizer != null) {
+                mSettings = mEqualizer.getProperties().toString();
+                mEqualizer.release();
+                Log.d(TAG,"Equalizer released, settings: "+mSettings);
+                mEqualizer = null;
+                sInstances.remove(session);
+            }
+        }
+    }
+}
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/PresetReverbTest.java b/media/tests/EffectsTest/src/com/android/effectstest/PresetReverbTest.java
new file mode 100755
index 0000000..91d7948
--- /dev/null
+++ b/media/tests/EffectsTest/src/com/android/effectstest/PresetReverbTest.java
@@ -0,0 +1,298 @@
+/*
+ * 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.
+ */
+
+package com.android.effectstest;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.View.OnClickListener;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.EditText;
+import android.widget.SeekBar;
+import android.widget.ToggleButton;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+
+import android.media.audiofx.PresetReverb;
+import android.media.audiofx.AudioEffect;
+
+public class PresetReverbTest extends Activity implements OnCheckedChangeListener {
+
+    private final static String TAG = "PresetReverbTest";
+
+    private static int NUM_PARAMS = 1;
+
+    private EffectParameter[] mParameters = new EffectParameter[NUM_PARAMS];
+    private PresetReverb mPresetReverb;
+    ToggleButton mOnOffButton;
+    ToggleButton mReleaseButton;
+    EditText mSessionText;
+    static int sSession = 0;
+    EffectListner mEffectListener = new EffectListner();
+    private static HashMap<Integer, PresetReverb> sInstances = new HashMap<Integer, PresetReverb>(10);
+    String mSettings = "";
+
+    public PresetReverbTest() {
+        Log.d(TAG, "contructor");
+    }
+
+    private static String[] sPresetNames = {
+        "NONE",         //PresetReverb.PRESET_NONE
+        "SMALLROOM",    //PresetReverb.PRESET_SMALLROOM
+        "MEDIUMROOM",   //PresetReverb.PRESET_MEDIUMROOM
+        "LARGEROOM",    //PresetReverb.PRESET_LARGEROOM
+        "MEDIUMHALL",   //PresetReverb.PRESET_MEDIUMHALL
+        "LARGEHALL",    //PresetReverb.PRESET_LARGEHALL
+        "PLATE",        //PresetReverb.PRESET_PLATE
+    };
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        setContentView(R.layout.presetreverbtest);
+
+        mSessionText = (EditText) findViewById(R.id.sessionEdit);
+        mSessionText.setOnKeyListener(mSessionKeyListener);
+
+        mSessionText.setText(Integer.toString(sSession));
+
+        mReleaseButton = (ToggleButton)findViewById(R.id.presetrvbReleaseButton);
+        mOnOffButton = (ToggleButton)findViewById(R.id.presetrvbOnOff);
+
+        getEffect(sSession);
+
+        if (mPresetReverb != null) {
+            mReleaseButton.setOnCheckedChangeListener(this);
+            mOnOffButton.setOnCheckedChangeListener(this);
+            // Presets
+            SeekBar seekBar = (SeekBar)findViewById(R.id.presetrvbParam1SeekBar);
+            TextView textView = (TextView)findViewById(R.id.presetrvbParam1Value);
+            mParameters[0] = new PresetParam(mPresetReverb, (short)0, (short)(sPresetNames.length - 1), seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mParameters[0]);
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+    }
+
+    private View.OnKeyListener mSessionKeyListener
+    = new View.OnKeyListener() {
+        public boolean onKey(View v, int keyCode, KeyEvent event) {
+            if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                switch (keyCode) {
+                    case KeyEvent.KEYCODE_DPAD_CENTER:
+                    case KeyEvent.KEYCODE_ENTER:
+                        try {
+                            sSession = Integer.parseInt(mSessionText.getText().toString());
+                            getEffect(sSession);
+                            if (mPresetReverb != null) {
+                                for (int i = 0 ; i < mParameters.length; i++) {
+                                    mParameters[i].setEffect(mPresetReverb);
+                                    mParameters[i].setEnabled(true);
+                                    mParameters[i].updateDisplay();
+                                }
+                            }
+                        } catch (NumberFormatException e) {
+                            Log.d(TAG, "Invalid session #: "+mSessionText.getText().toString());
+                        }
+
+                        return true;
+                }
+            }
+            return false;
+        }
+    };
+
+    // OnCheckedChangeListener
+    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+        if (buttonView.getId() == R.id.presetrvbOnOff) {
+            if (mPresetReverb != null) {
+                mPresetReverb.setEnabled(isChecked);
+                updateParams();
+            }
+        }
+        if (buttonView.getId() == R.id.presetrvbReleaseButton) {
+            if (isChecked) {
+                if (mPresetReverb == null) {
+                    getEffect(sSession);
+                    if (mPresetReverb != null) {
+                        for (int i = 0 ; i < mParameters.length; i++) {
+                            mParameters[i].setEffect(mPresetReverb);
+                            mParameters[i].setEnabled(true);
+                            mParameters[i].updateDisplay();
+                        }
+                    }
+                }
+            } else {
+                if (mPresetReverb != null) {
+                    for (int i = 0 ; i < mParameters.length; i++) {
+                        mParameters[i].setEnabled(false);
+                    }
+                    putEffect(sSession);
+                }
+            }
+        }
+    }
+
+    private class PresetParam extends EffectParameter {
+        private PresetReverb mPresetReverb;
+
+        public PresetParam(PresetReverb presetrvb, short min, short max, SeekBar seekBar, TextView textView) {
+            super (min, max, seekBar, textView, "");
+
+            mPresetReverb = presetrvb;
+            updateDisplay();
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+            if (mPresetReverb != null) {
+                mPresetReverb.setPreset(value.shortValue());
+            }
+        }
+
+        @Override
+        public Integer getParameter() {
+            if (mPresetReverb != null) {
+                return new Integer(mPresetReverb.getPreset());
+            }
+            return new Integer(0);
+        }
+
+        @Override
+        public void displayValue(int value, boolean fromTouch) {
+            mValueText.setText(sPresetNames[value]);
+            if (!fromTouch) {
+                mSeekBar.setProgress(value - mMin);
+            } else {
+                updateParams();
+            }
+        }
+
+        @Override
+        public void setEffect(Object presetrvb) {
+            mPresetReverb = (PresetReverb)presetrvb;
+        }
+
+    }
+
+    protected void updateParams() {
+        for (int i = 0 ; i < mParameters.length; i++) {
+            mParameters[i].updateDisplay();
+        }
+    }
+
+    public class EffectListner implements AudioEffect.OnEnableStatusChangeListener,
+    AudioEffect.OnControlStatusChangeListener,
+    PresetReverb.OnParameterChangeListener
+   {
+        public EffectListner() {
+        }
+        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
+            Log.d(TAG,"onEnableStatusChange: "+ enabled);
+        }
+        public void onControlStatusChange(AudioEffect effect, boolean controlGranted) {
+            Log.d(TAG,"onControlStatusChange: "+ controlGranted);
+        }
+
+        public void onParameterChange(PresetReverb effect, int status, int param, short value) {
+            Log.d(TAG,"onParameterChange, status: "+status+" p: "+param+" v: "+value);
+        }
+
+        private int byteArrayToInt(byte[] valueBuf, int offset) {
+            ByteBuffer converter = ByteBuffer.wrap(valueBuf);
+            converter.order(ByteOrder.nativeOrder());
+            return converter.getInt(offset);
+
+        }
+        private short byteArrayToShort(byte[] valueBuf, int offset) {
+            ByteBuffer converter = ByteBuffer.wrap(valueBuf);
+            converter.order(ByteOrder.nativeOrder());
+            return converter.getShort(offset);
+
+        }
+    }
+
+    private void getEffect(int session) {
+        synchronized (sInstances) {
+            if (sInstances.containsKey(session)) {
+                mPresetReverb = sInstances.get(session);
+            } else {
+                try{
+                    mPresetReverb = new PresetReverb(0, session);
+                } catch (IllegalArgumentException e) {
+                    Log.e(TAG,"PresetReverb effect not supported");
+                } catch (UnsupportedOperationException e) {
+                    Log.e(TAG,"PresetReverb library not loaded");
+                } catch (RuntimeException e) {
+                    Log.e(TAG,"PresetReverb effect not found");
+                }
+                sInstances.put(session, mPresetReverb);
+            }
+        }
+        mReleaseButton.setEnabled(false);
+        mOnOffButton.setEnabled(false);
+
+        if (mPresetReverb != null) {
+            if (mSettings != "") {
+                mPresetReverb.setProperties(new PresetReverb.Settings(mSettings));
+            }
+            mPresetReverb.setEnableStatusListener(mEffectListener);
+            mPresetReverb.setControlStatusListener(mEffectListener);
+            mPresetReverb.setParameterListener(mEffectListener);
+
+            mReleaseButton.setChecked(true);
+            mReleaseButton.setEnabled(true);
+
+            mOnOffButton.setChecked(mPresetReverb.getEnabled());
+            mOnOffButton.setEnabled(true);
+        }
+    }
+
+    private void putEffect(int session) {
+        mOnOffButton.setChecked(false);
+        mOnOffButton.setEnabled(false);
+        synchronized (sInstances) {
+            if (mPresetReverb != null) {
+                mSettings = mPresetReverb.getProperties().toString();
+                mPresetReverb.release();
+                Log.d(TAG,"PresetReverb released");
+                mPresetReverb = null;
+                sInstances.remove(session);
+            }
+        }
+    }
+}
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/SimplePlayer.java b/media/tests/EffectsTest/src/com/android/effectstest/SimplePlayer.java
new file mode 100644
index 0000000..119a604
--- /dev/null
+++ b/media/tests/EffectsTest/src/com/android/effectstest/SimplePlayer.java
@@ -0,0 +1,197 @@
+/*
+ * 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.
+ */
+
+package com.android.effectstest;
+
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.View.OnClickListener;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.EditText;
+import android.widget.SeekBar;
+import android.widget.ToggleButton;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class SimplePlayer implements OnClickListener {
+
+    private final static String TAG = "SimplePlayer";
+
+    int mPlayPauseButtonId;
+    int mStopButtonId;
+    Context mContext;
+    ImageView mPlayPauseButton;
+    int mPlayImageResource;
+    int mPauseImageResource;
+    String mFileName;
+    int mFileResId;
+    MediaPlayer mMediaPlayer;
+    int mStreamType;
+    int mSession;
+    float mSendLevel = (float)0.5;
+    int mEffectId = 0;
+    TextView mSessionText;
+
+    SimplePlayer(Context context, int playPausebuttonId, ImageView playPausebutton,
+                int stopButtonId, ImageView stopButton, TextView sessionText, String fileName, int stream, int session)
+    {
+        set(context, playPausebuttonId, playPausebutton, stopButtonId, stopButton, sessionText, stream, session);
+        mFileName = fileName;
+    }
+
+    SimplePlayer(Context context, int playPausebuttonId, ImageView playPausebutton,
+            int stopButtonId, ImageView stopButton, TextView sessionText, int fileResId, int stream, int session) {
+        set(context, playPausebuttonId, playPausebutton, stopButtonId, stopButton, sessionText, stream, session);
+        mFileResId = fileResId;
+        mFileName = "";
+    }
+
+    public void set(Context context, int playPausebuttonId, ImageView playPausebutton,
+            int stopButtonId, ImageView stopButton, TextView sessionText, int stream, int session) {
+        mContext = context;
+        mPlayPauseButtonId = playPausebuttonId;
+        mStopButtonId = stopButtonId;
+        mPlayPauseButton = (ImageButton) playPausebutton;
+        ImageButton stop = (ImageButton) stopButton;
+
+        mPlayPauseButton.setOnClickListener(this);
+        mPlayPauseButton.requestFocus();
+        stop.setOnClickListener(this);
+
+        mPlayImageResource = android.R.drawable.ic_media_play;
+        mPauseImageResource = android.R.drawable.ic_media_pause;
+        mStreamType = stream;
+        mSession = session;
+        mSessionText = sessionText;
+    }
+
+
+    public void onClick(View v) {
+        if (v.getId() == mPlayPauseButtonId) {
+            playOrPause();
+        } else if (v.getId() == mStopButtonId) {
+            stop();
+        }
+    }
+
+    public void playOrPause() {
+        if (mMediaPlayer == null || !mMediaPlayer.isPlaying()){
+              if (mMediaPlayer == null) {
+                  try {
+                      mMediaPlayer = new MediaPlayer();
+                      if (mSession != 0) {
+                          mMediaPlayer.setAudioSessionId(mSession);
+                          Log.d(TAG, "mMediaPlayer.setAudioSessionId(): "+ mSession);
+                      }
+
+                      if (mFileName.equals("")) {
+                          Log.d(TAG, "Playing from resource");
+                          AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(mFileResId);
+                          mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+                          afd.close();
+                      } else {
+                          Log.d(TAG, "Playing file: "+mFileName);
+                          mMediaPlayer.setDataSource(mFileName);
+                      }
+                      mMediaPlayer.setAudioStreamType(mStreamType);
+                      mMediaPlayer.prepare();
+                      mMediaPlayer.setLooping(true);
+                  } catch (IOException ex) {
+                      Log.e(TAG, "mMediaPlayercreate failed:", ex);
+                      mMediaPlayer = null;
+                  } catch (IllegalArgumentException ex) {
+                      Log.e(TAG, "mMediaPlayercreate failed:", ex);
+                      mMediaPlayer = null;
+                  } catch (SecurityException ex) {
+                      Log.e(TAG, "mMediaPlayercreate failed:", ex);
+                      mMediaPlayer = null;
+                  }
+
+                  if (mMediaPlayer != null) {
+                      mMediaPlayer.setAuxEffectSendLevel(mSendLevel);
+                      mMediaPlayer.attachAuxEffect(mEffectId);
+                      mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+                          public void onCompletion(MediaPlayer mp) {
+                              updatePlayPauseButton();
+                          }
+                      });
+                      mSessionText.setText("Session: "+Integer.toString(mMediaPlayer.getAudioSessionId()));
+                  }
+              }
+              if (mMediaPlayer != null) {
+                  mMediaPlayer.start();
+              }
+          } else {
+              mMediaPlayer.pause();
+          }
+          updatePlayPauseButton();
+    }
+
+    public void stop() {
+      if (mMediaPlayer != null) {
+          mMediaPlayer.stop();
+          mMediaPlayer.release();
+          mMediaPlayer = null;
+      }
+      updatePlayPauseButton();
+    }
+
+    public boolean isPlaying() {
+        if (mMediaPlayer != null) {
+            return mMediaPlayer.isPlaying();
+        } else {
+            return false;
+        }
+    }
+
+    public void updatePlayPauseButton() {
+        mPlayPauseButton.setImageResource(isPlaying() ? mPauseImageResource : mPlayImageResource);
+    }
+
+    public void attachAuxEffect(int effectId) {
+        mEffectId = effectId;
+        if (mMediaPlayer != null) {
+            Log.d(TAG,"attach effect: "+effectId);
+            mMediaPlayer.attachAuxEffect(effectId);
+        }
+    }
+    public void setAuxEffectSendLevel(float level) {
+        mSendLevel = level;
+        if (mMediaPlayer != null) {
+            mMediaPlayer.setAuxEffectSendLevel(level);
+        }
+    }
+
+    public void setContext(Context context) {
+        mContext = context;
+    }
+}
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java b/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java
new file mode 100755
index 0000000..bb32e6f
--- /dev/null
+++ b/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java
@@ -0,0 +1,271 @@
+/*
+ * 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.
+ */
+
+package com.android.effectstest;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.View.OnClickListener;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.EditText;
+import android.widget.SeekBar;
+import android.widget.ToggleButton;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+
+import android.media.audiofx.Virtualizer;
+import android.media.audiofx.AudioEffect;
+
+public class VirtualizerTest extends Activity implements OnCheckedChangeListener {
+
+    private final static String TAG = "VirtualizerTest";
+
+    private static int NUM_PARAMS = 1;
+
+    private EffectParameter mStrength;
+    private Virtualizer mVirtualizer;
+    ToggleButton mOnOffButton;
+    ToggleButton mReleaseButton;
+    EditText mSessionText;
+    static int sSession = 0;
+    EffectListner mEffectListener = new EffectListner();
+    private static HashMap<Integer, Virtualizer> sInstances = new HashMap<Integer, Virtualizer>(10);
+    String mSettings = "";
+
+    public VirtualizerTest() {
+        Log.d(TAG, "contructor");
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        SeekBar seekBar;
+        TextView textView;
+
+        setContentView(R.layout.virtualizertest);
+
+        mSessionText = (EditText) findViewById(R.id.sessionEdit);
+        mSessionText.setOnKeyListener(mSessionKeyListener);
+        mSessionText.setText(Integer.toString(sSession));
+
+        mReleaseButton = (ToggleButton)findViewById(R.id.virtReleaseButton);
+        mOnOffButton = (ToggleButton)findViewById(R.id.virtualizerOnOff);
+
+        getEffect(sSession);
+
+        if (mVirtualizer != null) {
+            mReleaseButton.setOnCheckedChangeListener(this);
+            mOnOffButton.setOnCheckedChangeListener(this);
+            textView = (TextView)findViewById(R.id.virtStrengthMin);
+            textView.setText("0");
+            textView = (TextView)findViewById(R.id.virtStrengthMax);
+            textView.setText("1000");
+            seekBar = (SeekBar)findViewById(R.id.virtStrengthSeekBar);
+            textView = (TextView)findViewById(R.id.virtStrengthValue);
+            mStrength = new VirtualizerParam(mVirtualizer, 0, 1000, seekBar, textView);
+            seekBar.setOnSeekBarChangeListener(mStrength);
+            mStrength.setEnabled(mVirtualizer.getStrengthSupported());
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+    }
+
+    private View.OnKeyListener mSessionKeyListener
+    = new View.OnKeyListener() {
+        public boolean onKey(View v, int keyCode, KeyEvent event) {
+            if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                switch (keyCode) {
+                    case KeyEvent.KEYCODE_DPAD_CENTER:
+                    case KeyEvent.KEYCODE_ENTER:
+                        try {
+                            sSession = Integer.parseInt(mSessionText.getText().toString());
+                            getEffect(sSession);
+                            if (mVirtualizer != null) {
+                                mStrength.setEffect(mVirtualizer);
+                                mStrength.setEnabled(mVirtualizer.getStrengthSupported());
+                            }
+                        } catch (NumberFormatException e) {
+                            Log.d(TAG, "Invalid session #: "+mSessionText.getText().toString());
+                        }
+                        return true;
+                }
+            }
+            return false;
+        }
+    };
+
+    // OnCheckedChangeListener
+    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+        if (buttonView.getId() == R.id.virtualizerOnOff) {
+            if (mVirtualizer != null) {
+                mVirtualizer.setEnabled(isChecked);
+                mStrength.updateDisplay();
+            }
+        }
+        if (buttonView.getId() == R.id.virtReleaseButton) {
+            if (isChecked) {
+                if (mVirtualizer == null) {
+                    getEffect(sSession);
+                    if (mVirtualizer != null) {
+                        mStrength.setEffect(mVirtualizer);
+                        mStrength.setEnabled(mVirtualizer.getStrengthSupported());
+                    }
+                }
+            } else {
+                if (mVirtualizer != null) {
+                    mStrength.setEnabled(false);
+                    putEffect(sSession);
+                }
+            }
+        }
+    }
+
+    private class VirtualizerParam extends EffectParameter {
+        private Virtualizer mVirtualizer;
+
+        public VirtualizerParam(Virtualizer virtualizer, int min, int max, SeekBar seekBar, TextView textView) {
+            super (min, max, seekBar, textView, "o/oo");
+
+            mVirtualizer = virtualizer;
+            updateDisplay();
+        }
+
+        @Override
+        public void setParameter(Integer value) {
+            if (mVirtualizer != null) {
+                mVirtualizer.setStrength(value.shortValue());
+            }
+        }
+
+        @Override
+        public Integer getParameter() {
+            if (mVirtualizer != null) {
+                return new Integer(mVirtualizer.getRoundedStrength());
+            }
+            return new Integer(0);
+        }
+
+        @Override
+        public void setEffect(Object effect) {
+            mVirtualizer = (Virtualizer)effect;
+        }
+    }
+
+    public class EffectListner implements AudioEffect.OnEnableStatusChangeListener,
+        AudioEffect.OnControlStatusChangeListener, AudioEffect.OnParameterChangeListener
+   {
+        public EffectListner() {
+        }
+        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
+            Log.d(TAG,"onEnableStatusChange: "+ enabled);
+        }
+        public void onControlStatusChange(AudioEffect effect, boolean controlGranted) {
+            Log.d(TAG,"onControlStatusChange: "+ controlGranted);
+        }
+        public void onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value) {
+            int p = byteArrayToInt(param, 0);
+            short v = byteArrayToShort(value, 0);
+
+            Log.d(TAG,"onParameterChange, status: "+status+" p: "+p+" v: "+v);
+        }
+
+        private int byteArrayToInt(byte[] valueBuf, int offset) {
+            ByteBuffer converter = ByteBuffer.wrap(valueBuf);
+            converter.order(ByteOrder.nativeOrder());
+            return converter.getInt(offset);
+
+        }
+        private short byteArrayToShort(byte[] valueBuf, int offset) {
+            ByteBuffer converter = ByteBuffer.wrap(valueBuf);
+            converter.order(ByteOrder.nativeOrder());
+            return converter.getShort(offset);
+
+        }
+    }
+
+    private void getEffect(int session) {
+        synchronized (sInstances) {
+            if (sInstances.containsKey(session)) {
+                mVirtualizer = sInstances.get(session);
+            } else {
+                try{
+                    mVirtualizer = new Virtualizer(0, session);
+                } catch (IllegalArgumentException e) {
+                    Log.e(TAG,"Virtualizer effect not supported");
+                } catch (IllegalStateException e) {
+                    Log.e(TAG,"Virtualizer cannot get strength supported");
+                } catch (UnsupportedOperationException e) {
+                    Log.e(TAG,"Virtualizer library not loaded");
+                } catch (RuntimeException e) {
+                    Log.e(TAG,"Virtualizer effect not found");
+                }
+                sInstances.put(session, mVirtualizer);
+            }
+        }
+        mReleaseButton.setEnabled(false);
+        mOnOffButton.setEnabled(false);
+
+        if (mVirtualizer != null) {
+            if (mSettings != "") {
+                mVirtualizer.setProperties(new Virtualizer.Settings(mSettings));
+            }
+            mVirtualizer.setEnableStatusListener(mEffectListener);
+            mVirtualizer.setControlStatusListener(mEffectListener);
+            mVirtualizer.setParameterListener(mEffectListener);
+
+            mReleaseButton.setChecked(true);
+            mReleaseButton.setEnabled(true);
+
+            mOnOffButton.setChecked(mVirtualizer.getEnabled());
+            mOnOffButton.setEnabled(true);
+        }
+    }
+
+    private void putEffect(int session) {
+        mOnOffButton.setChecked(false);
+        mOnOffButton.setEnabled(false);
+        synchronized (sInstances) {
+            if (mVirtualizer != null) {
+                mSettings = mVirtualizer.getProperties().toString();
+                mVirtualizer.release();
+                Log.d(TAG,"Virtualizer released");
+                mVirtualizer = null;
+                sInstances.remove(session);
+            }
+        }
+    }
+}
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java b/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java
new file mode 100755
index 0000000..60583e0
--- /dev/null
+++ b/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java
@@ -0,0 +1,296 @@
+/*
+ * 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.
+ */
+
+package com.android.effectstest;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.media.audiofx.Visualizer;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.ToggleButton;
+import android.widget.SeekBar;
+
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+
+public class VisualizerTest extends Activity implements OnCheckedChangeListener {
+
+    private final static String TAG = "Visualizer Test";
+
+    private Visualizer mVisualizer;
+    ToggleButton mOnOffButton;
+    ToggleButton mReleaseButton;
+    boolean mEnabled;
+    EditText mSessionText;
+    static int sSession = 0;
+    int mCaptureSize;
+    ToggleButton mCallbackButton;
+    boolean mCallbackOn;
+    VisualizerListener mVisualizerListener;
+    private static HashMap<Integer, Visualizer> sInstances = new HashMap<Integer, Visualizer>(10);
+    private VisualizerTestHandler mVisualizerTestHandler = null;
+
+    public VisualizerTest() {
+        Log.d(TAG, "contructor");
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        TextView textView;
+
+        setContentView(R.layout.visualizertest);
+
+        mSessionText = (EditText) findViewById(R.id.sessionEdit);
+        mSessionText.setOnKeyListener(mSessionKeyListener);
+        mSessionText.setText(Integer.toString(sSession));
+
+        mReleaseButton = (ToggleButton)findViewById(R.id.visuReleaseButton);
+        mOnOffButton = (ToggleButton)findViewById(R.id.visualizerOnOff);
+        mCallbackButton = (ToggleButton)findViewById(R.id.visuCallbackOnOff);
+        mCallbackOn = false;
+        mCallbackButton.setChecked(mCallbackOn);
+
+        mVisualizerTestHandler = new VisualizerTestHandler();
+        mVisualizerListener = new VisualizerListener();
+
+        getEffect(sSession);
+
+        if (mVisualizer != null) {
+            mReleaseButton.setOnCheckedChangeListener(this);
+            mOnOffButton.setOnCheckedChangeListener(this);
+            mCallbackButton.setOnCheckedChangeListener(this);
+        }
+    }
+
+    private static final int MSG_START_CAPTURE = 0;
+    private static final int MSG_STOP_CAPTURE = 1;
+    private static final int MSG_NEW_CAPTURE = 2;
+    private static final int CAPTURE_PERIOD_MS = 100;
+
+    private class VisualizerTestHandler extends Handler {
+        boolean mActive = false;
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+            case MSG_START_CAPTURE:
+                if (!mActive) {
+                    Log.d(TAG, "Start capture");
+                    mActive = true;
+                    sendMessageDelayed(obtainMessage(MSG_NEW_CAPTURE, 0, 0, null), CAPTURE_PERIOD_MS);
+                }
+                break;
+            case MSG_STOP_CAPTURE:
+                if (mActive) {
+                    Log.d(TAG, "Stop capture");
+                    mActive = false;
+                }
+                break;
+            case MSG_NEW_CAPTURE:
+                if (mActive && mVisualizer != null) {
+                    if (mCaptureSize > 0) {
+                        byte[] data = new byte[mCaptureSize];
+                        if (mVisualizer.getWaveForm(data) == Visualizer.SUCCESS) {
+                            int len = data.length < mCaptureSize ? data.length : mCaptureSize;
+                            displayVal(R.id.waveformMin, data[0]);
+                            displayVal(R.id.waveformMax, data[len-1]);
+                            displayVal(R.id.waveformCenter, data[len/2]);
+                        };
+                        if (mVisualizer.getFft(data) == Visualizer.SUCCESS) {
+                            int len = data.length < mCaptureSize ? data.length : mCaptureSize;
+                            displayVal(R.id.fftMin, data[0]);
+                            displayVal(R.id.fftMax, data[len-1]);
+                            displayVal(R.id.fftCenter, data[len/2]);
+                        };
+                    }
+                    sendMessageDelayed(obtainMessage(MSG_NEW_CAPTURE, 0, 0, null), CAPTURE_PERIOD_MS);
+                }
+                break;
+            }
+        }
+    }
+
+    private class VisualizerListener implements Visualizer.OnDataCaptureListener {
+
+        public VisualizerListener() {
+        }
+        public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform, int samplingRate) {
+            if (visualizer == mVisualizer) {
+                if (waveform.length > 0) {
+                    Log.d(TAG, "onWaveFormDataCapture(): "+waveform[0]+" smp rate: "+samplingRate/1000);
+                    displayVal(R.id.waveformMin, waveform[0]);
+                    displayVal(R.id.waveformMax, waveform[waveform.length - 1]);
+                    displayVal(R.id.waveformCenter, waveform[waveform.length/2]);
+                }
+            }
+        }
+        public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) {
+            if (visualizer == mVisualizer) {
+                if (fft.length > 0) {
+                    Log.d(TAG, "onFftDataCapture(): "+fft[0]);
+                    displayVal(R.id.fftMin, fft[0]);
+                    displayVal(R.id.fftMax, fft[fft.length - 1]);
+                    displayVal(R.id.fftCenter, fft[fft.length/2]);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+    }
+
+    private View.OnKeyListener mSessionKeyListener
+    = new View.OnKeyListener() {
+        public boolean onKey(View v, int keyCode, KeyEvent event) {
+            if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                switch (keyCode) {
+                    case KeyEvent.KEYCODE_DPAD_CENTER:
+                    case KeyEvent.KEYCODE_ENTER:
+                        try {
+                            sSession = Integer.parseInt(mSessionText.getText().toString());
+                            getEffect(sSession);
+                        } catch (NumberFormatException e) {
+                            Log.d(TAG, "Invalid session #: "+mSessionText.getText().toString());
+                        }
+
+                        return true;
+                }
+            }
+            return false;
+        }
+    };
+
+    // OnCheckedChangeListener
+    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+        if (buttonView.getId() == R.id.visualizerOnOff) {
+            if (mVisualizer != null) {
+                mEnabled = isChecked;
+                mCallbackButton.setEnabled(!mEnabled);
+                if (mCallbackOn && mEnabled) {
+                    mVisualizer.setDataCaptureListener(mVisualizerListener,
+                            10000,
+                            true,
+                            true);
+                }
+                mVisualizer.setEnabled(mEnabled);
+                if (mCallbackOn) {
+                    if (!mEnabled) {
+                        mVisualizer.setDataCaptureListener(null,
+                                10000,
+                                false,
+                                false);
+                    }
+                } else {
+                    int msg = isChecked ? MSG_START_CAPTURE : MSG_STOP_CAPTURE;
+                    mVisualizerTestHandler.sendMessage(
+                            mVisualizerTestHandler.obtainMessage(msg, 0, 0, null));
+                }
+            }
+        }
+        if (buttonView.getId() == R.id.visuReleaseButton) {
+            if (isChecked) {
+                if (mVisualizer == null) {
+                    getEffect(sSession);
+                }
+            } else {
+                if (mVisualizer != null) {
+                    putEffect(sSession);
+                }
+            }
+        }
+        if (buttonView.getId() == R.id.visuCallbackOnOff) {
+            mCallbackOn = isChecked;
+        }
+    }
+
+    private void displayVal(int viewId, int val) {
+        TextView textView = (TextView)findViewById(viewId);
+        String text = Integer.toString(val);
+        textView.setText(text);
+    }
+
+
+    private void getEffect(int session) {
+        synchronized (sInstances) {
+            if (sInstances.containsKey(session)) {
+                mVisualizer = sInstances.get(session);
+            } else {
+                try{
+                    mVisualizer = new Visualizer(session);
+                } catch (UnsupportedOperationException e) {
+                    Log.e(TAG,"Visualizer library not loaded");
+                    throw (new RuntimeException("Cannot initialize effect"));
+                } catch (RuntimeException e) {
+                    throw e;
+                }
+                sInstances.put(session, mVisualizer);
+            }
+        }
+        mReleaseButton.setEnabled(false);
+        mOnOffButton.setEnabled(false);
+        if (mVisualizer != null) {
+            mCaptureSize = mVisualizer.getCaptureSize();
+
+            mReleaseButton.setChecked(true);
+            mReleaseButton.setEnabled(true);
+
+            mEnabled = mVisualizer.getEnabled();
+            mOnOffButton.setChecked(mEnabled);
+            mOnOffButton.setEnabled(true);
+
+            mCallbackButton.setEnabled(!mEnabled);
+        }
+    }
+
+    private void putEffect(int session) {
+        mOnOffButton.setChecked(false);
+        mOnOffButton.setEnabled(false);
+        synchronized (sInstances) {
+            if (mVisualizer != null) {
+                mVisualizer.release();
+                Log.d(TAG,"Visualizer released");
+                mVisualizer = null;
+                sInstances.remove(session);
+            }
+        }
+    }
+
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
index a6cf355..3d5905d 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
@@ -38,7 +38,7 @@
 public class MediaFrameworkPerfTestRunner extends InstrumentationTestRunner {
 
     public static boolean mGetNativeHeapDump = false;
-
+    public static boolean mGetProcmem = false;
 
     @Override
     public TestSuite getAllTests() {
@@ -61,6 +61,12 @@
         if (get_heap_dump != null) {
             mGetNativeHeapDump = true;
         }
+
+        String get_procmem = (String) icicle.get("get_procmem");
+        if (get_procmem != null) {
+            mGetProcmem = true;
+        }
+
     }
 }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
index e7f98de..ed9bb97 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
@@ -98,7 +98,9 @@
         mWakeLock.acquire();
     }
 
-    public void onStop(Bundle icicle) {
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
         mWakeLock.release();
     }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
index ccb0638..1c60401 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
@@ -1,12 +1,12 @@
 /*
  * 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
@@ -53,7 +53,7 @@
 import com.android.mediaframeworktest.MediaProfileReader;
 
 /**
- * Junit / Instrumentation - performance measurement for media player and 
+ * Junit / Instrumentation - performance measurement for media player and
  * recorder
  *
  * FIXME:
@@ -100,6 +100,7 @@
         super("com.android.mediaframeworktest", MediaFrameworkTest.class);
     }
 
+    @Override
     protected void setUp() throws Exception {
         super.setUp();
         //Insert a 2 second before launching the test activity. This is
@@ -109,18 +110,25 @@
         if (MediaFrameworkPerfTestRunner.mGetNativeHeapDump)
             MediaTestUtil.getNativeHeapDump(this.getName() + "_before");
 
-        mProcMemWriter = new BufferedWriter(new FileWriter
-                (new File(MEDIA_PROCMEM_OUTPUT), true));
-        mProcMemWriter.write(this.getName() + "\n");
+        if (MediaFrameworkPerfTestRunner.mGetProcmem) {
+            mProcMemWriter = new BufferedWriter(new FileWriter
+                    (new File(MEDIA_PROCMEM_OUTPUT), true));
+            mProcMemWriter.write(this.getName() + "\n");
+        }
         mMemWriter = new BufferedWriter(new FileWriter
                 (new File(MEDIA_MEMORY_OUTPUT), true));
-
+        mMemWriter.write(this.getName() + "\n");
     }
 
+    @Override
     protected void tearDown() throws Exception {
         if (MediaFrameworkPerfTestRunner.mGetNativeHeapDump)
             MediaTestUtil.getNativeHeapDump(this.getName() + "_after");
-        mProcMemWriter.close();
+
+        if (MediaFrameworkPerfTestRunner.mGetProcmem) {
+            mProcMemWriter.close();
+        }
+        mMemWriter.write("\n");
         mMemWriter.close();
         super.tearDown();
     }
@@ -157,6 +165,7 @@
     }
 
     private final class RawPreviewCallback implements PreviewCallback {
+        @Override
         public void onPreviewFrame(byte[] rawData, Camera camera) {
             mPreviewDone.open();
         }
@@ -285,19 +294,21 @@
         }
     }
 
-    public void writeProcmemInfo() throws Exception{
-        String cmd = "procmem " + getMediaserverPid();
-        Process p = Runtime.getRuntime().exec(cmd);
+    public void writeProcmemInfo() throws Exception {
+        if (MediaFrameworkPerfTestRunner.mGetProcmem) {
+            String cmd = "procmem " + getMediaserverPid();
+            Process p = Runtime.getRuntime().exec(cmd);
 
-        InputStream inStream = p.getInputStream();
-        InputStreamReader inReader = new InputStreamReader(inStream);
-        BufferedReader inBuffer = new BufferedReader(inReader);
-        String s;
-        while ((s = inBuffer.readLine()) != null) {
-              mProcMemWriter.write(s);
-              mProcMemWriter.write("\n");
+            InputStream inStream = p.getInputStream();
+            InputStreamReader inReader = new InputStreamReader(inStream);
+            BufferedReader inBuffer = new BufferedReader(inReader);
+            String s;
+            while ((s = inBuffer.readLine()) != null) {
+                mProcMemWriter.write(s);
+                mProcMemWriter.write("\n");
+            }
+            mProcMemWriter.write("\n\n");
         }
-        mProcMemWriter.write("\n\n");
     }
 
     public String captureMediaserverInfo() {
@@ -368,13 +379,11 @@
         boolean memoryResult = false;
 
         mStartPid = getMediaserverPid();
-        mMemWriter.write("H263 Video Playback Only\n");
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             mediaStressPlayback(MediaNames.VIDEO_HIGHRES_H263);
             getMemoryWriteToLog(i);
             writeProcmemInfo();
         }
-        mMemWriter.write("\n");
         memoryResult = validateMemoryResult(mStartPid, mStartMemory, DECODER_LIMIT);
         assertTrue("H263 playback memory test", memoryResult);
     }
@@ -385,13 +394,11 @@
         boolean memoryResult = false;
 
         mStartPid = getMediaserverPid();
-        mMemWriter.write("H264 Video Playback only\n");
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             mediaStressPlayback(MediaNames.VIDEO_H264_AMR);
             getMemoryWriteToLog(i);
             writeProcmemInfo();
         }
-        mMemWriter.write("\n");
         memoryResult = validateMemoryResult(mStartPid, mStartMemory, DECODER_LIMIT);
         assertTrue("H264 playback memory test", memoryResult);
     }
@@ -402,7 +409,6 @@
         boolean memoryResult = false;
 
         mStartPid = getMediaserverPid();
-        mMemWriter.write("H263 video record only\n");
         int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H263);
         assertTrue("H263 video recording frame rate", frameRate != -1);
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
@@ -411,7 +417,6 @@
             getMemoryWriteToLog(i);
             writeProcmemInfo();
         }
-        mMemWriter.write("\n");
         memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
         assertTrue("H263 record only memory test", memoryResult);
     }
@@ -422,7 +427,6 @@
         boolean memoryResult = false;
 
         mStartPid = getMediaserverPid();
-        mMemWriter.write("MPEG4 video record only\n");
         int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.MPEG_4_SP);
         assertTrue("MPEG4 video recording frame rate", frameRate != -1);
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
@@ -431,7 +435,6 @@
             getMemoryWriteToLog(i);
             writeProcmemInfo();
         }
-        mMemWriter.write("\n");
         memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
         assertTrue("mpeg4 record only memory test", memoryResult);
     }
@@ -445,14 +448,12 @@
         mStartPid = getMediaserverPid();
         int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H263);
         assertTrue("H263 video recording frame rate", frameRate != -1);
-        mMemWriter.write("Audio and h263 video record\n");
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             assertTrue(stressVideoRecord(frameRate, 352, 288, MediaRecorder.VideoEncoder.H263,
                     MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, false));
             getMemoryWriteToLog(i);
             writeProcmemInfo();
         }
-        mMemWriter.write("\n");
         memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
         assertTrue("H263 audio video record memory test", memoryResult);
     }
@@ -463,13 +464,11 @@
         boolean memoryResult = false;
 
         mStartPid = getMediaserverPid();
-        mMemWriter.write("Audio record only\n");
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             stressAudioRecord(MediaNames.RECORDER_OUTPUT);
             getMemoryWriteToLog(i);
             writeProcmemInfo();
         }
-        mMemWriter.write("\n");
         memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
         assertTrue("audio record only memory test", memoryResult);
     }
@@ -480,13 +479,11 @@
         boolean memoryResult = false;
 
         mStartPid = getMediaserverPid();
-        mMemWriter.write("Camera Preview Only\n");
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             stressCameraPreview();
             getMemoryWriteToLog(i);
             writeProcmemInfo();
         }
-        mMemWriter.write("\n");
         memoryResult = validateMemoryResult(mStartPid, mStartMemory, CAMERA_LIMIT);
         assertTrue("camera preview memory test", memoryResult);
     }
diff --git a/media/tests/contents/media_api/music/sine_200+1000Hz_44K_mo.wav b/media/tests/contents/media_api/music/sine_200+1000Hz_44K_mo.wav
old mode 100755
new mode 100644
index 312b6fb..24c2a0d
--- a/media/tests/contents/media_api/music/sine_200+1000Hz_44K_mo.wav
+++ b/media/tests/contents/media_api/music/sine_200+1000Hz_44K_mo.wav
Binary files differ
diff --git a/native/android/configuration.cpp b/native/android/configuration.cpp
index 7eb51dd..74cf80e 100644
--- a/native/android/configuration.cpp
+++ b/native/android/configuration.cpp
@@ -123,6 +123,11 @@
     return config->smallestScreenWidthDp;
 }
 
+int32_t AConfiguration_getLayoutDirection(AConfiguration* config) {
+    return (config->screenLayout&ResTable_config::MASK_LAYOUTDIR)
+            >> ResTable_config::SHIFT_LAYOUTDIR;
+}
+
 // ----------------------------------------------------------------------
 
 void AConfiguration_setMcc(AConfiguration* config, int32_t mcc) {
@@ -210,6 +215,11 @@
     config->smallestScreenWidthDp = value;
 }
 
+void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value) {
+    config->screenLayout = (config->screenLayout&~ResTable_config::MASK_LAYOUTDIR)
+            | ((value<<ResTable_config::SHIFT_LAYOUTDIR)&ResTable_config::MASK_LAYOUTDIR);
+}
+
 // ----------------------------------------------------------------------
 
 int32_t AConfiguration_diff(AConfiguration* config1, AConfiguration* config2) {
diff --git a/native/android/native_window.cpp b/native/android/native_window.cpp
index 99c0fd3..ca0c9028 100644
--- a/native/android/native_window.cpp
+++ b/native/android/native_window.cpp
@@ -25,7 +25,7 @@
 using namespace android;
 
 ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface) {
-    sp<ANativeWindow> win = android_Surface_getNativeWindow(env, surface);
+    sp<ANativeWindow> win = android_view_Surface_getNativeWindow(env, surface);
     if (win != NULL) {
         win->incStrong((void*)ANativeWindow_acquire);
     }
diff --git a/native/android/storage_manager.cpp b/native/android/storage_manager.cpp
index f2f36b62..399f1ff 100644
--- a/native/android/storage_manager.cpp
+++ b/native/android/storage_manager.cpp
@@ -125,11 +125,20 @@
         }
     }
 
-    void mountObb(const char* filename, const char* key, AStorageManager_obbCallbackFunc func, void* data) {
+    void mountObb(const char* rawPath, const char* key, AStorageManager_obbCallbackFunc func,
+            void* data) {
+        // Resolve path before sending to MountService
+        char canonicalPath[PATH_MAX];
+        if (realpath(rawPath, canonicalPath) == NULL) {
+            ALOGE("mountObb failed to resolve path %s: %s", rawPath, strerror(errno));
+            return;
+        }
+
         ObbCallback* cb = registerObbCallback(func, data);
-        String16 filename16(filename);
+        String16 rawPath16(rawPath);
+        String16 canonicalPath16(canonicalPath);
         String16 key16(key);
-        mMountService->mountObb(filename16, key16, mObbActionListener, cb->nonce);
+        mMountService->mountObb(rawPath16, canonicalPath16, key16, mObbActionListener, cb->nonce);
     }
 
     void unmountObb(const char* filename, const bool force, AStorageManager_obbCallbackFunc func, void* data) {
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
index 9c87c22..ffed804 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
@@ -234,4 +234,21 @@
             attemptDeadServiceRecovery(e);
         }
     }
+
+    /**
+     * Returns the name of this adapter's driver.
+     *
+     * <p>Different NFC adapters may use different drivers.  This value is
+     * informational and should not be parsed.
+     *
+     * @return the driver name, or empty string if unknown
+     */
+    public String getDriverName() {
+        try {
+            return sService.getDriverName(mPackageName);
+        } catch (RemoteException e) {
+            attemptDeadServiceRecovery(e);
+            return "";
+        }
+    }
 }
diff --git a/opengl/java/android/opengl/EGL14.java b/opengl/java/android/opengl/EGL14.java
new file mode 100644
index 0000000..cd53c17
--- /dev/null
+++ b/opengl/java/android/opengl/EGL14.java
@@ -0,0 +1,448 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+// This source file is automatically generated
+
+package android.opengl;
+
+import android.graphics.SurfaceTexture;
+import android.view.Surface;
+import android.view.SurfaceView;
+import android.view.SurfaceHolder;
+
+/**
+ * EGL 1.4
+ *
+ */
+public class EGL14 {
+
+public static final int EGL_DEFAULT_DISPLAY            = 0;
+public static EGLContext EGL_NO_CONTEXT                = null;
+public static EGLDisplay EGL_NO_DISPLAY                = null;
+public static EGLSurface EGL_NO_SURFACE                = null;
+
+public static final int EGL_FALSE                          = 0;
+public static final int EGL_TRUE                           = 1;
+public static final int EGL_SUCCESS                        = 0x3000;
+public static final int EGL_NOT_INITIALIZED                = 0x3001;
+public static final int EGL_BAD_ACCESS                     = 0x3002;
+public static final int EGL_BAD_ALLOC                      = 0x3003;
+public static final int EGL_BAD_ATTRIBUTE                  = 0x3004;
+public static final int EGL_BAD_CONFIG                     = 0x3005;
+public static final int EGL_BAD_CONTEXT                    = 0x3006;
+public static final int EGL_BAD_CURRENT_SURFACE            = 0x3007;
+public static final int EGL_BAD_DISPLAY                    = 0x3008;
+public static final int EGL_BAD_MATCH                      = 0x3009;
+public static final int EGL_BAD_NATIVE_PIXMAP              = 0x300A;
+public static final int EGL_BAD_NATIVE_WINDOW              = 0x300B;
+public static final int EGL_BAD_PARAMETER                  = 0x300C;
+public static final int EGL_BAD_SURFACE                    = 0x300D;
+public static final int EGL_CONTEXT_LOST                   = 0x300E;
+public static final int EGL_BUFFER_SIZE                    = 0x3020;
+public static final int EGL_ALPHA_SIZE                     = 0x3021;
+public static final int EGL_BLUE_SIZE                      = 0x3022;
+public static final int EGL_GREEN_SIZE                     = 0x3023;
+public static final int EGL_RED_SIZE                       = 0x3024;
+public static final int EGL_DEPTH_SIZE                     = 0x3025;
+public static final int EGL_STENCIL_SIZE                   = 0x3026;
+public static final int EGL_CONFIG_CAVEAT                  = 0x3027;
+public static final int EGL_CONFIG_ID                      = 0x3028;
+public static final int EGL_LEVEL                          = 0x3029;
+public static final int EGL_MAX_PBUFFER_HEIGHT             = 0x302A;
+public static final int EGL_MAX_PBUFFER_PIXELS             = 0x302B;
+public static final int EGL_MAX_PBUFFER_WIDTH              = 0x302C;
+public static final int EGL_NATIVE_RENDERABLE              = 0x302D;
+public static final int EGL_NATIVE_VISUAL_ID               = 0x302E;
+public static final int EGL_NATIVE_VISUAL_TYPE             = 0x302F;
+public static final int EGL_SAMPLES                        = 0x3031;
+public static final int EGL_SAMPLE_BUFFERS                 = 0x3032;
+public static final int EGL_SURFACE_TYPE                   = 0x3033;
+public static final int EGL_TRANSPARENT_TYPE               = 0x3034;
+public static final int EGL_TRANSPARENT_BLUE_VALUE         = 0x3035;
+public static final int EGL_TRANSPARENT_GREEN_VALUE        = 0x3036;
+public static final int EGL_TRANSPARENT_RED_VALUE          = 0x3037;
+public static final int EGL_NONE                           = 0x3038;
+public static final int EGL_BIND_TO_TEXTURE_RGB            = 0x3039;
+public static final int EGL_BIND_TO_TEXTURE_RGBA           = 0x303A;
+public static final int EGL_MIN_SWAP_INTERVAL              = 0x303B;
+public static final int EGL_MAX_SWAP_INTERVAL              = 0x303C;
+public static final int EGL_LUMINANCE_SIZE                 = 0x303D;
+public static final int EGL_ALPHA_MASK_SIZE                = 0x303E;
+public static final int EGL_COLOR_BUFFER_TYPE              = 0x303F;
+public static final int EGL_RENDERABLE_TYPE                = 0x3040;
+public static final int EGL_MATCH_NATIVE_PIXMAP            = 0x3041;
+public static final int EGL_CONFORMANT                     = 0x3042;
+public static final int EGL_SLOW_CONFIG                    = 0x3050;
+public static final int EGL_NON_CONFORMANT_CONFIG          = 0x3051;
+public static final int EGL_TRANSPARENT_RGB                = 0x3052;
+public static final int EGL_RGB_BUFFER                     = 0x308E;
+public static final int EGL_LUMINANCE_BUFFER               = 0x308F;
+public static final int EGL_NO_TEXTURE                     = 0x305C;
+public static final int EGL_TEXTURE_RGB                    = 0x305D;
+public static final int EGL_TEXTURE_RGBA                   = 0x305E;
+public static final int EGL_TEXTURE_2D                     = 0x305F;
+public static final int EGL_PBUFFER_BIT                    = 0x0001;
+public static final int EGL_PIXMAP_BIT                     = 0x0002;
+public static final int EGL_WINDOW_BIT                     = 0x0004;
+public static final int EGL_VG_COLORSPACE_LINEAR_BIT       = 0x0020;
+public static final int EGL_VG_ALPHA_FORMAT_PRE_BIT        = 0x0040;
+public static final int EGL_MULTISAMPLE_RESOLVE_BOX_BIT    = 0x0200;
+public static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT    = 0x0400;
+public static final int EGL_OPENGL_ES_BIT                  = 0x0001;
+public static final int EGL_OPENVG_BIT                     = 0x0002;
+public static final int EGL_OPENGL_ES2_BIT                 = 0x0004;
+public static final int EGL_OPENGL_BIT                     = 0x0008;
+public static final int EGL_VENDOR                         = 0x3053;
+public static final int EGL_VERSION                        = 0x3054;
+public static final int EGL_EXTENSIONS                     = 0x3055;
+public static final int EGL_CLIENT_APIS                    = 0x308D;
+public static final int EGL_HEIGHT                         = 0x3056;
+public static final int EGL_WIDTH                          = 0x3057;
+public static final int EGL_LARGEST_PBUFFER                = 0x3058;
+public static final int EGL_TEXTURE_FORMAT                 = 0x3080;
+public static final int EGL_TEXTURE_TARGET                 = 0x3081;
+public static final int EGL_MIPMAP_TEXTURE                 = 0x3082;
+public static final int EGL_MIPMAP_LEVEL                   = 0x3083;
+public static final int EGL_RENDER_BUFFER                  = 0x3086;
+public static final int EGL_VG_COLORSPACE                  = 0x3087;
+public static final int EGL_VG_ALPHA_FORMAT                = 0x3088;
+public static final int EGL_HORIZONTAL_RESOLUTION          = 0x3090;
+public static final int EGL_VERTICAL_RESOLUTION            = 0x3091;
+public static final int EGL_PIXEL_ASPECT_RATIO             = 0x3092;
+public static final int EGL_SWAP_BEHAVIOR                  = 0x3093;
+public static final int EGL_MULTISAMPLE_RESOLVE            = 0x3099;
+public static final int EGL_BACK_BUFFER                    = 0x3084;
+public static final int EGL_SINGLE_BUFFER                  = 0x3085;
+public static final int EGL_VG_COLORSPACE_sRGB             = 0x3089;
+public static final int EGL_VG_COLORSPACE_LINEAR           = 0x308A;
+public static final int EGL_VG_ALPHA_FORMAT_NONPRE         = 0x308B;
+public static final int EGL_VG_ALPHA_FORMAT_PRE            = 0x308C;
+public static final int EGL_DISPLAY_SCALING                = 10000;
+public static final int EGL_BUFFER_PRESERVED               = 0x3094;
+public static final int EGL_BUFFER_DESTROYED               = 0x3095;
+public static final int EGL_OPENVG_IMAGE                   = 0x3096;
+public static final int EGL_CONTEXT_CLIENT_TYPE            = 0x3097;
+public static final int EGL_CONTEXT_CLIENT_VERSION         = 0x3098;
+public static final int EGL_MULTISAMPLE_RESOLVE_DEFAULT    = 0x309A;
+public static final int EGL_MULTISAMPLE_RESOLVE_BOX        = 0x309B;
+public static final int EGL_OPENGL_ES_API                  = 0x30A0;
+public static final int EGL_OPENVG_API                     = 0x30A1;
+public static final int EGL_OPENGL_API                     = 0x30A2;
+public static final int EGL_DRAW                           = 0x3059;
+public static final int EGL_READ                           = 0x305A;
+public static final int EGL_CORE_NATIVE_ENGINE             = 0x305B;
+
+    native private static void _nativeClassInit();
+    static {
+        _nativeClassInit();
+    }
+    // C function EGLint eglGetError ( void )
+
+    public static native int eglGetError(
+    );
+
+    // C function EGLDisplay eglGetDisplay ( EGLNativeDisplayType display_id )
+
+    public static native EGLDisplay eglGetDisplay(
+        int display_id
+    );
+
+    // C function EGLBoolean eglInitialize ( EGLDisplay dpy, EGLint *major, EGLint *minor )
+
+    public static native boolean eglInitialize(
+        EGLDisplay dpy,
+        int[] major,
+        int majorOffset,
+        int[] minor,
+        int minorOffset
+    );
+
+    // C function EGLBoolean eglTerminate ( EGLDisplay dpy )
+
+    public static native boolean eglTerminate(
+        EGLDisplay dpy
+    );
+
+    // C function const char * eglQueryString ( EGLDisplay dpy, EGLint name )
+
+    public static native String eglQueryString(
+        EGLDisplay dpy,
+        int name
+    );
+    // C function EGLBoolean eglGetConfigs ( EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config )
+
+    public static native boolean eglGetConfigs(
+        EGLDisplay dpy,
+        EGLConfig[] configs,
+        int configsOffset,
+        int config_size,
+        int[] num_config,
+        int num_configOffset
+    );
+
+    // C function EGLBoolean eglChooseConfig ( EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config )
+
+    public static native boolean eglChooseConfig(
+        EGLDisplay dpy,
+        int[] attrib_list,
+        int attrib_listOffset,
+        EGLConfig[] configs,
+        int configsOffset,
+        int config_size,
+        int[] num_config,
+        int num_configOffset
+    );
+
+    // C function EGLBoolean eglGetConfigAttrib ( EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value )
+
+    public static native boolean eglGetConfigAttrib(
+        EGLDisplay dpy,
+        EGLConfig config,
+        int attribute,
+        int[] value,
+        int offset
+    );
+
+    // C function EGLSurface eglCreateWindowSurface ( EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list )
+
+    private static native EGLSurface _eglCreateWindowSurface(
+        EGLDisplay dpy,
+        EGLConfig config,
+        Object win,
+        int[] attrib_list,
+        int offset
+    );
+
+    private static native EGLSurface _eglCreateWindowSurfaceTexture(
+        EGLDisplay dpy,
+        EGLConfig config,
+        Object win,
+        int[] attrib_list,
+        int offset
+    );
+
+    public static EGLSurface eglCreateWindowSurface(EGLDisplay dpy,
+        EGLConfig config,
+        Object win,
+        int[] attrib_list,
+        int offset
+    ){
+        Surface sur = null;
+        if (win instanceof SurfaceView) {
+            SurfaceView surfaceView = (SurfaceView)win;
+            sur = surfaceView.getHolder().getSurface();
+        } else if (win instanceof SurfaceHolder) {
+            SurfaceHolder holder = (SurfaceHolder)win;
+            sur = holder.getSurface();
+        } else if (win instanceof Surface) {
+            sur = (Surface) win;
+        }
+
+        EGLSurface surface;
+        if (sur != null) {
+            surface = _eglCreateWindowSurface(dpy, config, sur, attrib_list, offset);
+        } else if (win instanceof SurfaceTexture) {
+            surface = _eglCreateWindowSurfaceTexture(dpy, config,
+                    win, attrib_list, offset);
+        } else {
+            throw new java.lang.UnsupportedOperationException(
+                "eglCreateWindowSurface() can only be called with an instance of " +
+                "Surface, SurfaceView, SurfaceTexture or SurfaceHolder at the moment, " +
+                "this will be fixed later.");
+        }
+
+        return surface;
+    }
+    // C function EGLSurface eglCreatePbufferSurface ( EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list )
+
+    public static native EGLSurface eglCreatePbufferSurface(
+        EGLDisplay dpy,
+        EGLConfig config,
+        int[] attrib_list,
+        int offset
+    );
+
+    // C function EGLSurface eglCreatePixmapSurface ( EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list )
+
+    public static native EGLSurface eglCreatePixmapSurface(
+        EGLDisplay dpy,
+        EGLConfig config,
+        int pixmap,
+        int[] attrib_list,
+        int offset
+    );
+
+    // C function EGLBoolean eglDestroySurface ( EGLDisplay dpy, EGLSurface surface )
+
+    public static native boolean eglDestroySurface(
+        EGLDisplay dpy,
+        EGLSurface surface
+    );
+
+    // C function EGLBoolean eglQuerySurface ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value )
+
+    public static native boolean eglQuerySurface(
+        EGLDisplay dpy,
+        EGLSurface surface,
+        int attribute,
+        int[] value,
+        int offset
+    );
+
+    // C function EGLBoolean eglBindAPI ( EGLenum api )
+
+    public static native boolean eglBindAPI(
+        int api
+    );
+
+    // C function EGLenum eglQueryAPI ( void )
+
+    public static native int eglQueryAPI(
+    );
+
+    // C function EGLBoolean eglWaitClient ( void )
+
+    public static native boolean eglWaitClient(
+    );
+
+    // C function EGLBoolean eglReleaseThread ( void )
+
+    public static native boolean eglReleaseThread(
+    );
+
+    // C function EGLSurface eglCreatePbufferFromClientBuffer ( EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list )
+
+    public static native EGLSurface eglCreatePbufferFromClientBuffer(
+        EGLDisplay dpy,
+        int buftype,
+        int buffer,
+        EGLConfig config,
+        int[] attrib_list,
+        int offset
+    );
+
+    // C function EGLBoolean eglSurfaceAttrib ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value )
+
+    public static native boolean eglSurfaceAttrib(
+        EGLDisplay dpy,
+        EGLSurface surface,
+        int attribute,
+        int value
+    );
+
+    // C function EGLBoolean eglBindTexImage ( EGLDisplay dpy, EGLSurface surface, EGLint buffer )
+
+    public static native boolean eglBindTexImage(
+        EGLDisplay dpy,
+        EGLSurface surface,
+        int buffer
+    );
+
+    // C function EGLBoolean eglReleaseTexImage ( EGLDisplay dpy, EGLSurface surface, EGLint buffer )
+
+    public static native boolean eglReleaseTexImage(
+        EGLDisplay dpy,
+        EGLSurface surface,
+        int buffer
+    );
+
+    // C function EGLBoolean eglSwapInterval ( EGLDisplay dpy, EGLint interval )
+
+    public static native boolean eglSwapInterval(
+        EGLDisplay dpy,
+        int interval
+    );
+
+    // C function EGLContext eglCreateContext ( EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list )
+
+    public static native EGLContext eglCreateContext(
+        EGLDisplay dpy,
+        EGLConfig config,
+        EGLContext share_context,
+        int[] attrib_list,
+        int offset
+    );
+
+    // C function EGLBoolean eglDestroyContext ( EGLDisplay dpy, EGLContext ctx )
+
+    public static native boolean eglDestroyContext(
+        EGLDisplay dpy,
+        EGLContext ctx
+    );
+
+    // C function EGLBoolean eglMakeCurrent ( EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx )
+
+    public static native boolean eglMakeCurrent(
+        EGLDisplay dpy,
+        EGLSurface draw,
+        EGLSurface read,
+        EGLContext ctx
+    );
+
+    // C function EGLContext eglGetCurrentContext ( void )
+
+    public static native EGLContext eglGetCurrentContext(
+    );
+
+    // C function EGLSurface eglGetCurrentSurface ( EGLint readdraw )
+
+    public static native EGLSurface eglGetCurrentSurface(
+        int readdraw
+    );
+
+    // C function EGLDisplay eglGetCurrentDisplay ( void )
+
+    public static native EGLDisplay eglGetCurrentDisplay(
+    );
+
+    // C function EGLBoolean eglQueryContext ( EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value )
+
+    public static native boolean eglQueryContext(
+        EGLDisplay dpy,
+        EGLContext ctx,
+        int attribute,
+        int[] value,
+        int offset
+    );
+
+    // C function EGLBoolean eglWaitGL ( void )
+
+    public static native boolean eglWaitGL(
+    );
+
+    // C function EGLBoolean eglWaitNative ( EGLint engine )
+
+    public static native boolean eglWaitNative(
+        int engine
+    );
+
+    // C function EGLBoolean eglSwapBuffers ( EGLDisplay dpy, EGLSurface surface )
+
+    public static native boolean eglSwapBuffers(
+        EGLDisplay dpy,
+        EGLSurface surface
+    );
+
+    // C function EGLBoolean eglCopyBuffers ( EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target )
+
+    public static native boolean eglCopyBuffers(
+        EGLDisplay dpy,
+        EGLSurface surface,
+        int target
+    );
+
+}
diff --git a/opengl/java/android/opengl/EGLConfig.java b/opengl/java/android/opengl/EGLConfig.java
new file mode 100644
index 0000000..d457c9f
--- /dev/null
+++ b/opengl/java/android/opengl/EGLConfig.java
@@ -0,0 +1,37 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.opengl;
+
+/**
+ * Wrapper class for native EGLConfig objects.
+ *
+ */
+public class EGLConfig extends EGLObjectHandle {
+    private EGLConfig(int handle) {
+        super(handle);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        EGLConfig that = (EGLConfig) o;
+        return getHandle() == that.getHandle();
+    }
+}
diff --git a/opengl/java/android/opengl/EGLContext.java b/opengl/java/android/opengl/EGLContext.java
new file mode 100644
index 0000000..41b8ef1
--- /dev/null
+++ b/opengl/java/android/opengl/EGLContext.java
@@ -0,0 +1,37 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.opengl;
+
+/**
+ * Wrapper class for native EGLContext objects.
+ *
+ */
+public class EGLContext extends EGLObjectHandle {
+    private EGLContext(int handle) {
+        super(handle);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        EGLContext that = (EGLContext) o;
+        return getHandle() == that.getHandle();
+    }
+}
diff --git a/opengl/java/android/opengl/EGLDisplay.java b/opengl/java/android/opengl/EGLDisplay.java
new file mode 100644
index 0000000..17d1a64
--- /dev/null
+++ b/opengl/java/android/opengl/EGLDisplay.java
@@ -0,0 +1,37 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.opengl;
+
+/**
+ * Wrapper class for native EGLDisplay objects.
+ *
+ */
+public class EGLDisplay extends EGLObjectHandle {
+    private EGLDisplay(int handle) {
+        super(handle);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        EGLDisplay that = (EGLDisplay) o;
+        return getHandle() == that.getHandle();
+    }
+}
diff --git a/opengl/java/android/opengl/EGLObjectHandle.java b/opengl/java/android/opengl/EGLObjectHandle.java
new file mode 100644
index 0000000..d2710de
--- /dev/null
+++ b/opengl/java/android/opengl/EGLObjectHandle.java
@@ -0,0 +1,47 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.opengl;
+
+/**
+ * Base class for wrapped EGL objects.
+ *
+ */
+public abstract class EGLObjectHandle {
+    private final int mHandle;
+
+    protected EGLObjectHandle(int handle) {
+        mHandle = handle;
+    }
+
+    /**
+     * Returns the native handle of the wrapped EGL object. This handle can be
+     * cast to the corresponding native type on the native side.
+     *
+     * For example, EGLDisplay dpy = (EGLDisplay)handle;
+     *
+     * @return the native handle of the wrapped EGL object.
+     */
+    public int getHandle() {
+        return mHandle;
+    }
+
+    @Override
+    public int hashCode() {
+        return getHandle();
+    }
+}
diff --git a/opengl/java/android/opengl/EGLSurface.java b/opengl/java/android/opengl/EGLSurface.java
new file mode 100644
index 0000000..65bec4f
--- /dev/null
+++ b/opengl/java/android/opengl/EGLSurface.java
@@ -0,0 +1,37 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.opengl;
+
+/**
+ * Wrapper class for native EGLSurface objects.
+ *
+ */
+public class EGLSurface extends EGLObjectHandle {
+    private EGLSurface(int handle) {
+        super(handle);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        EGLSurface that = (EGLSurface) o;
+        return getHandle() == that.getHandle();
+    }
+}
diff --git a/opengl/java/android/opengl/GLES20.java b/opengl/java/android/opengl/GLES20.java
index 635f811..2eeae62 100644
--- a/opengl/java/android/opengl/GLES20.java
+++ b/opengl/java/android/opengl/GLES20.java
@@ -829,6 +829,25 @@
         byte name
     );
 
+    // C function void glGetActiveAttrib ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name )
+
+    public static native String glGetActiveAttrib(
+        int program,
+        int index,
+        int[] size,
+        int sizeOffset,
+        int[] type,
+        int typeOffset
+    );
+
+    // C function void glGetActiveAttrib ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name )
+
+    public static native String glGetActiveAttrib(
+        int program,
+        int index,
+        java.nio.IntBuffer size,
+        java.nio.IntBuffer type
+    );
     // C function void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name )
 
     public static native void glGetActiveUniform(
@@ -856,7 +875,25 @@
         java.nio.IntBuffer type,
         byte name
     );
+    // C function void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name )
 
+    public static native String glGetActiveUniform(
+        int program,
+        int index,
+        int[] size,
+        int sizeOffset,
+        int[] type,
+        int typeOffset
+    );
+
+    // C function void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name )
+
+    public static native String glGetActiveUniform(
+        int program,
+        int index,
+        java.nio.IntBuffer size,
+        java.nio.IntBuffer type
+    );
     // C function void glGetAttachedShaders ( GLuint program, GLsizei maxcount, GLsizei *count, GLuint *shaders )
 
     public static native void glGetAttachedShaders(
@@ -1105,6 +1142,11 @@
         byte source
     );
 
+    // C function void glGetShaderSource ( GLuint shader, GLsizei bufsize, GLsizei *length, char *source )
+
+    public static native String glGetShaderSource(
+        int shader
+    );
 /*
  * Copyright (C) 2009 The Android Open Source Project
  *
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 8acbae3..54dcaaa 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -83,7 +83,7 @@
  * </ul>
  * <p>
  * <h4>Specifying the android.view.Surface</h4>
- * By default GLSurfaceView will create a PixelFormat.RGB_565 format surface. If a translucent
+ * By default GLSurfaceView will create a PixelFormat.RGB_888 format surface. If a translucent
  * surface is required, call getHolder().setFormat(PixelFormat.TRANSLUCENT).
  * The exact format of a TRANSLUCENT surface is device dependent, but it will be
  * a 32-bit-per-pixel surface with 8 bits per component.
@@ -94,7 +94,7 @@
  * well as how many bits are allocated to each channel. Therefore, the first thing
  * GLSurfaceView has to do when starting to render is choose what EGLConfig to use.
  * <p>
- * By default GLSurfaceView chooses a EGLConfig that has an RGB_565 pixel format,
+ * By default GLSurfaceView chooses a EGLConfig that has an RGB_888 pixel format,
  * with at least a 16-bit depth buffer and no stencil.
  * <p>
  * If you would prefer a different EGLConfig
@@ -414,7 +414,7 @@
      * is called.
      * <p>
      * If no setEGLConfigChooser method is called, then by default the
-     * view will choose an RGB_565 surface with a depth buffer depth of
+     * view will choose an RGB_888 surface with a depth buffer depth of
      * at least 16 bits.
      *
      * @param needDepth
@@ -432,7 +432,7 @@
      * is called.
      * <p>
      * If no setEGLConfigChooser method is called, then by default the
-     * view will choose an RGB_565 surface with a depth buffer depth of
+     * view will choose an RGB_888 surface with a depth buffer depth of
      * at least 16 bits.
      *
      */
@@ -968,13 +968,13 @@
         }
 
     /**
-     * This class will choose a RGB_565 surface with
+     * This class will choose a RGB_888 surface with
      * or without a depth buffer.
      *
      */
     private class SimpleEGLConfigChooser extends ComponentSizeChooser {
         public SimpleEGLConfigChooser(boolean withDepthBuffer) {
-            super(5, 6, 5, 0, withDepthBuffer ? 16 : 0, 0);
+            super(8, 8, 8, 0, withDepthBuffer ? 16 : 0, 0);
         }
     }
 
diff --git a/opengl/java/android/opengl/Matrix.java b/opengl/java/android/opengl/Matrix.java
index 7c72ae4..72128ac 100644
--- a/opengl/java/android/opengl/Matrix.java
+++ b/opengl/java/android/opengl/Matrix.java
@@ -312,7 +312,6 @@
      * @param near
      * @param far
      */
-
     public static void frustumM(float[] m, int offset,
             float left, float right, float bottom, float top,
             float near, float far) {
@@ -336,7 +335,7 @@
         final float r_depth  = 1.0f / (near - far);
         final float x = 2.0f * (near * r_width);
         final float y = 2.0f * (near * r_height);
-        final float A = 2.0f * ((right + left) * r_width);
+        final float A = (right + left) * r_width;
         final float B = (top + bottom) * r_height;
         final float C = (far + near) * r_depth;
         final float D = 2.0f * (far * near * r_depth);
diff --git a/opengl/java/com/google/android/gles_jni/EGLImpl.java b/opengl/java/com/google/android/gles_jni/EGLImpl.java
index 6992019..64a54c2 100644
--- a/opengl/java/com/google/android/gles_jni/EGLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLImpl.java
@@ -83,6 +83,8 @@
         } else if (native_window instanceof SurfaceHolder) {
             SurfaceHolder holder = (SurfaceHolder)native_window;
             sur = holder.getSurface();
+        } else if (native_window instanceof Surface) {
+            sur = (Surface) native_window;
         }
 
         int eglSurfaceId;
@@ -94,8 +96,7 @@
         } else {
             throw new java.lang.UnsupportedOperationException(
                 "eglCreateWindowSurface() can only be called with an instance of " +
-                "SurfaceView, SurfaceHolder or SurfaceTexture at the moment, " + 
-                "this will be fixed later.");
+                "Surface, SurfaceView, SurfaceHolder or SurfaceTexture at the moment.");
         }
 
         if (eglSurfaceId == 0) {
diff --git a/opengl/java/com/google/android/gles_jni/GLImpl.java b/opengl/java/com/google/android/gles_jni/GLImpl.java
index 07f9e91..6b23be9 100644
--- a/opengl/java/com/google/android/gles_jni/GLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/GLImpl.java
@@ -23,7 +23,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.os.Build;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.Log;
 
 import java.nio.Buffer;
@@ -68,7 +68,7 @@
         int version = 0;
         IPackageManager pm = AppGlobals.getPackageManager();
         try {
-            ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0, UserId.myUserId());
+            ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0, UserHandle.myUserId());
             if (applicationInfo != null) {
                 version = applicationInfo.targetSdkVersion;
             }
diff --git a/packages/BackupRestoreConfirmation/res/values-fa/strings.xml b/packages/BackupRestoreConfirmation/res/values-fa/strings.xml
index d202d74..6da7d4a 100644
--- a/packages/BackupRestoreConfirmation/res/values-fa/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-fa/strings.xml
@@ -18,16 +18,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="backup_confirm_title" msgid="827563724209303345">"پشتیبان‌گیری کامل"</string>
     <string name="restore_confirm_title" msgid="5469365809567486602">"بازیابی کامل"</string>
-    <string name="backup_confirm_text" msgid="1878021282758896593">"درخواست پشتیبان گیری کامل از تمام داده‌ها به یک رایانه دسک‌تاپ متصل داده شده است. آیا می‌خواهید این عمل انجام شود؟"\n\n"اگر شما درخواست تهیه نسخه پشتیبان را نداده‌اید، اجازه‌ ادامه عملیات را ندهید."</string>
-    <string name="allow_backup_button_label" msgid="4217228747769644068">"از داده‌های من نسخه پشتیبان تهیه شود"</string>
-    <string name="deny_backup_button_label" msgid="6009119115581097708">"نسخه پشتیبان تهیه نشود"</string>
-    <string name="restore_confirm_text" msgid="7499866728030461776">"بازیابی کامل تمام داده‌ها از یک رایانه دسک تاپ متصل درخواست شده است. آیا می خواهید این اجازه را بدهید؟"\n\n"اگر خود شما درخواست بازیابی نداده‌اید، اجازه ادامه این عملیات را ندهید. با این کار همه داده‌هایی که اکنون روی دستگاه است جایگزین می‌شود!"</string>
+    <string name="backup_confirm_text" msgid="1878021282758896593">"درخواست پشتیبان گیری کامل از تمام داده‌ها به یک رایانه دسک‌تاپ متصل داده شده است. آیا می‌خواهید این عمل انجام شود؟"\n\n"اگر شما درخواست تهیه نسخهٔ پشتیبان را نداده‌اید، اجازه‌ ادامه عملیات را ندهید."</string>
+    <string name="allow_backup_button_label" msgid="4217228747769644068">"از داده‌های من نسخهٔ پشتیبان تهیه شود"</string>
+    <string name="deny_backup_button_label" msgid="6009119115581097708">"نسخهٔ پشتیبان تهیه نشود"</string>
+    <string name="restore_confirm_text" msgid="7499866728030461776">"بازیابی کامل تمام داده‌ها از یک رایانه دسک تاپ متصل درخواست شده است. آیا می‌خواهید این اجازه را بدهید؟"\n\n"اگر خود شما درخواست بازیابی نداده‌اید، اجازه ادامه این عملیات را ندهید. با این کار همه داده‌هایی که اکنون روی دستگاه است جایگزین می‌شود!"</string>
     <string name="allow_restore_button_label" msgid="3081286752277127827">"بازیابی داده‌های من"</string>
     <string name="deny_restore_button_label" msgid="1724367334453104378">"بازیابی نشود"</string>
-    <string name="current_password_text" msgid="8268189555578298067">"لطفاً گذرواژه نسخه پشتیبان فعلی خود را در زیر وارد کنید:"</string>
+    <string name="current_password_text" msgid="8268189555578298067">"لطفاً گذرواژه نسخهٔ پشتیبان فعلی خود را در زیر وارد کنید:"</string>
     <string name="device_encryption_restore_text" msgid="1570864916855208992">"لطفاً گذرواژه رمزگذاری دستگاه خود را در زیر وارد کنید."</string>
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"لطفاً گذرواژه رمزگذاری دستگاه خود را در زیر وارد کنید. این برای رمزگذاری بایگانی پشتیبان نیز مورد استفاده قرار می‌گیرد."</string>
-    <string name="backup_enc_password_text" msgid="4981585714795233099">"لطفاً یک گذرواژه برای رمزگذاری داده‌های کامل نسخه پشتیبانی وارد کنید. اگر این خالی بماند، گذرواژه فعلی نسخه پشتیبان مورد استفاده قرار خواهد گرفت:"</string>
+    <string name="backup_enc_password_text" msgid="4981585714795233099">"لطفاً یک گذرواژه برای رمزگذاری داده‌های کامل نسخهٔ پشتیبانی وارد کنید. اگر این خالی بماند، گذرواژه فعلی نسخهٔ پشتیبان مورد استفاده قرار خواهد گرفت:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"اگر می‌خواهید تمام نسخه پشتیبانی داده را رمزدار کنید، یک گذرواژه در زیر وارد کنید:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"اگر داده بازیابی شده رمزگذاری شده است، لطفاً گذرواژه را در زیر وارد کنید:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"شروع پشتیبان‌گیری..."</string>
diff --git a/packages/DefaultContainerService/AndroidManifest.xml b/packages/DefaultContainerService/AndroidManifest.xml
index 319eb8d..3dcd232 100755
--- a/packages/DefaultContainerService/AndroidManifest.xml
+++ b/packages/DefaultContainerService/AndroidManifest.xml
@@ -8,6 +8,7 @@
     <uses-permission android:name="android.permission.ASEC_MOUNT_UNMOUNT"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
+    <uses-permission android:name="android.permission.ACCESS_ALL_EXTERNAL_STORAGE" />
 
     <application android:label="@string/service_name"
                  android:allowBackup="false">
diff --git a/packages/DefaultContainerService/res/values-ca/strings.xml b/packages/DefaultContainerService/res/values-ca/strings.xml
index 3af2c55..e19c72c 100644
--- a/packages/DefaultContainerService/res/values-ca/strings.xml
+++ b/packages/DefaultContainerService/res/values-ca/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"Assistent d\'accés a paquets"</string>
+    <string name="service_name" msgid="4841491635055379553">"Assist. d\'accés a paquets"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-es-rUS/strings.xml b/packages/DefaultContainerService/res/values-es-rUS/strings.xml
index 670c2c5..19fd655 100644
--- a/packages/DefaultContainerService/res/values-es-rUS/strings.xml
+++ b/packages/DefaultContainerService/res/values-es-rUS/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"Asist. p/acceder al paq."</string>
+    <string name="service_name" msgid="4841491635055379553">"Asist. acceso al paquete"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-lt/strings.xml b/packages/DefaultContainerService/res/values-lt/strings.xml
index df5ffef..3faf8cc 100644
--- a/packages/DefaultContainerService/res/values-lt/strings.xml
+++ b/packages/DefaultContainerService/res/values-lt/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"Prieig. prie paketo pagalb. priem."</string>
+    <string name="service_name" msgid="4841491635055379553">"Pak. pagalb. prm. prieiga"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-nl/strings.xml b/packages/DefaultContainerService/res/values-nl/strings.xml
index 9ece040..2501099 100644
--- a/packages/DefaultContainerService/res/values-nl/strings.xml
+++ b/packages/DefaultContainerService/res/values-nl/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"Helper voor pakkettoegang"</string>
+    <string name="service_name" msgid="4841491635055379553">"Helper pakkettoegang"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-uk/strings.xml b/packages/DefaultContainerService/res/values-uk/strings.xml
index 216d715..1226bd4 100644
--- a/packages/DefaultContainerService/res/values-uk/strings.xml
+++ b/packages/DefaultContainerService/res/values-uk/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
+    <string name="service_name" msgid="4841491635055379553">"Майстер доступу до пакетів"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-vi/strings.xml b/packages/DefaultContainerService/res/values-vi/strings.xml
index 63f1199..885946c 100644
--- a/packages/DefaultContainerService/res/values-vi/strings.xml
+++ b/packages/DefaultContainerService/res/values-vi/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"Trình t.giúp truy cập gói"</string>
+    <string name="service_name" msgid="4841491635055379553">"Trình trợ giúp truy cập gói"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-zh-rCN/strings.xml b/packages/DefaultContainerService/res/values-zh-rCN/strings.xml
index 65928b1..cb117a2 100644
--- a/packages/DefaultContainerService/res/values-zh-rCN/strings.xml
+++ b/packages/DefaultContainerService/res/values-zh-rCN/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"软件包访问帮助程序"</string>
+    <string name="service_name" msgid="4841491635055379553">"应用包访问权限帮助程序"</string>
 </resources>
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index a28b8a4..cf56cba 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -26,6 +26,7 @@
 import android.content.pm.ContainerEncryptionParams;
 import android.content.pm.IPackageManager;
 import android.content.pm.LimitedLengthInputStream;
+import android.content.pm.PackageCleanItem;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInfoLite;
 import android.content.pm.PackageManager;
@@ -34,6 +35,7 @@
 import android.content.res.ObbScanner;
 import android.net.Uri;
 import android.os.Environment;
+import android.os.Environment.UserEnvironment;
 import android.os.FileUtils;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
@@ -181,6 +183,7 @@
             }
 
             ret.packageName = pkg.packageName;
+            ret.versionCode = pkg.versionCode;
             ret.installLocation = pkg.installLocation;
             ret.verifiers = pkg.verifiers;
 
@@ -256,6 +259,21 @@
                 eraseFiles(directory);
             }
         }
+
+        @Override
+        public long calculateInstalledSize(String packagePath, boolean isForwardLocked)
+                throws RemoteException {
+            final File packageFile = new File(packagePath);
+            try {
+                return calculateContainerSize(packageFile, isForwardLocked) * 1024 * 1024;
+            } catch (IOException e) {
+                /*
+                 * Okay, something failed, so let's just estimate it to be 2x
+                 * the file size. Note this will be 0 if the file doesn't exist.
+                 */
+                return packageFile.length() * 2;
+            }
+        }
     };
 
     public DefaultContainerService() {
@@ -266,14 +284,17 @@
     @Override
     protected void onHandleIntent(Intent intent) {
         if (PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE.equals(intent.getAction())) {
-            IPackageManager pm = IPackageManager.Stub.asInterface(
+            final IPackageManager pm = IPackageManager.Stub.asInterface(
                     ServiceManager.getService("package"));
-            String pkg = null;
+            PackageCleanItem item = null;
             try {
-                while ((pkg=pm.nextPackageToClean(pkg)) != null) {
-                    eraseFiles(Environment.getExternalStorageAppDataDirectory(pkg));
-                    eraseFiles(Environment.getExternalStorageAppMediaDirectory(pkg));
-                    eraseFiles(Environment.getExternalStorageAppObbDirectory(pkg));
+                while ((item = pm.nextPackageToClean(item)) != null) {
+                    final UserEnvironment userEnv = new UserEnvironment(item.userId);
+                    eraseFiles(userEnv.getExternalStorageAppDataDirectory(item.packageName));
+                    eraseFiles(userEnv.getExternalStorageAppMediaDirectory(item.packageName));
+                    if (item.andCode) {
+                        eraseFiles(userEnv.getExternalStorageAppObbDirectory(item.packageName));
+                    }
                 }
             } catch (RemoteException e) {
             }
@@ -666,9 +687,9 @@
             }
 
             // Pick user preference
-            int installPreference = Settings.System.getInt(getApplicationContext()
+            int installPreference = Settings.Global.getInt(getApplicationContext()
                     .getContentResolver(),
-                    Settings.Secure.DEFAULT_INSTALL_LOCATION,
+                    Settings.Global.DEFAULT_INSTALL_LOCATION,
                     PackageHelper.APP_INSTALL_AUTO);
             if (installPreference == PackageHelper.APP_INSTALL_INTERNAL) {
                 prefer = PREFER_INTERNAL;
diff --git a/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java b/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java
index 436e579..f11b499 100644
--- a/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java
+++ b/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java
@@ -119,7 +119,7 @@
                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
-        if (ActivityManager.isHighEndGfx(display)) {
+        if (ActivityManager.isHighEndGfx()) {
             lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
         }
         lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
diff --git a/packages/FusedLocation/Android.mk b/packages/FusedLocation/Android.mk
new file mode 100644
index 0000000..a81b9f1
--- /dev/null
+++ b/packages/FusedLocation/Android.mk
@@ -0,0 +1,28 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := com.android.location.provider
+
+LOCAL_PACKAGE_NAME := FusedLocation
+LOCAL_CERTIFICATE := platform
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/packages/FusedLocation/AndroidManifest.xml b/packages/FusedLocation/AndroidManifest.xml
new file mode 100644
index 0000000..779428e
--- /dev/null
+++ b/packages/FusedLocation/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2012 Google Inc.
+ *
+ * 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.location.fused"
+        coreApp="true">
+
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.INSTALL_LOCATION_PROVIDER" />
+
+    <application
+            android:label="@string/app_label">
+
+        <uses-library android:name="com.android.location.provider" />
+
+        <!-- Fused Location Service that LocationManagerService binds to.
+             LocationManagerService will bind to the service with the highest
+             version. -->
+        <service android:name="com.android.location.fused.FusedLocationService"
+                 android:exported="true"
+                 android:permission="android.permission.WRITE_SECURE_SETTINGS" >
+           <intent-filter>
+               <action android:name="com.android.location.service.FusedLocationProvider" />
+           </intent-filter>
+           <meta-data android:name="serviceVersion" android:value="0" />
+        </service>
+    </application>
+</manifest>
diff --git a/packages/FusedLocation/MODULE_LICENSE_APACHE2 b/packages/FusedLocation/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/packages/FusedLocation/MODULE_LICENSE_APACHE2
diff --git a/packages/FusedLocation/NOTICE b/packages/FusedLocation/NOTICE
new file mode 100644
index 0000000..33ff961
--- /dev/null
+++ b/packages/FusedLocation/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/packages/FusedLocation/res/values/strings.xml b/packages/FusedLocation/res/values/strings.xml
new file mode 100644
index 0000000..5b78e39
--- /dev/null
+++ b/packages/FusedLocation/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Name of the application. [CHAR LIMIT=35] -->
+    <string name="app_label">Fused Location</string>
+</resources>
diff --git a/packages/FusedLocation/src/com/android/location/fused/FusedLocationProvider.java b/packages/FusedLocation/src/com/android/location/fused/FusedLocationProvider.java
new file mode 100644
index 0000000..7918882
--- /dev/null
+++ b/packages/FusedLocation/src/com/android/location/fused/FusedLocationProvider.java
@@ -0,0 +1,118 @@
+/*
+ * 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.location.fused;
+
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+import com.android.location.provider.LocationProviderBase;
+import com.android.location.provider.ProviderPropertiesUnbundled;
+import com.android.location.provider.ProviderRequestUnbundled;
+
+import android.content.Context;
+import android.location.Criteria;
+import android.location.LocationProvider;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.WorkSource;
+
+public class FusedLocationProvider extends LocationProviderBase implements FusionEngine.Callback {
+    private static final String TAG = "FusedLocationProvider";
+
+    private static ProviderPropertiesUnbundled PROPERTIES = ProviderPropertiesUnbundled.create(
+            false, false, false, false, true, true, true, Criteria.POWER_LOW,
+            Criteria.ACCURACY_FINE);
+
+    private static final int MSG_ENABLE = 1;
+    private static final int MSG_DISABLE = 2;
+    private static final int MSG_SET_REQUEST = 3;
+
+    private final Context mContext;
+    private final FusionEngine mEngine;
+
+    private static class RequestWrapper {
+        public ProviderRequestUnbundled request;
+        public WorkSource source;
+        public RequestWrapper(ProviderRequestUnbundled request, WorkSource source) {
+            this.request = request;
+            this.source = source;
+        }
+    }
+
+    public FusedLocationProvider(Context context) {
+        super(TAG, PROPERTIES);
+        mContext = context;
+        mEngine = new FusionEngine(context, Looper.myLooper());
+    }
+
+    /**
+     * For serializing requests to mEngine.
+     */
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_ENABLE:
+                    mEngine.init(FusedLocationProvider.this);
+                    break;
+                case MSG_DISABLE:
+                    mEngine.deinit();
+                    break;
+                case MSG_SET_REQUEST:
+                    {
+                        RequestWrapper wrapper = (RequestWrapper) msg.obj;
+                        mEngine.setRequest(wrapper.request, wrapper.source);
+                        break;
+                    }
+            }
+        }
+    };
+
+    @Override
+    public void onEnable() {
+        mHandler.sendEmptyMessage(MSG_ENABLE);
+    }
+
+    @Override
+    public void onDisable() {
+        mHandler.sendEmptyMessage(MSG_DISABLE);
+    }
+
+    @Override
+    public void onSetRequest(ProviderRequestUnbundled request, WorkSource source) {
+        mHandler.obtainMessage(MSG_SET_REQUEST, new RequestWrapper(request, source)).sendToTarget();
+    }
+
+    @Override
+    public void onDump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        // perform synchronously
+        mEngine.dump(fd, pw, args);
+    }
+
+    @Override
+    public int onGetStatus(Bundle extras) {
+        return LocationProvider.AVAILABLE;
+    }
+
+    @Override
+    public long onGetStatusUpdateTime() {
+        return 0;
+    }
+}
diff --git a/packages/FusedLocation/src/com/android/location/fused/FusedLocationService.java b/packages/FusedLocation/src/com/android/location/fused/FusedLocationService.java
new file mode 100644
index 0000000..509c010
--- /dev/null
+++ b/packages/FusedLocation/src/com/android/location/fused/FusedLocationService.java
@@ -0,0 +1,50 @@
+/*
+ * 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.location.fused;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class FusedLocationService extends Service {
+    private FusedLocationProvider mProvider;
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        if (mProvider == null) {
+            mProvider = new FusedLocationProvider(getApplicationContext());
+        }
+        return mProvider.getBinder();
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        // make sure to stop performing work
+        if (mProvider != null) {
+            mProvider.onDisable();
+        }
+      return false;
+    }
+
+    @Override
+    public void onDestroy() {
+        mProvider = null;
+    }
+}
diff --git a/packages/FusedLocation/src/com/android/location/fused/FusionEngine.java b/packages/FusedLocation/src/com/android/location/fused/FusionEngine.java
new file mode 100644
index 0000000..f137373
--- /dev/null
+++ b/packages/FusedLocation/src/com/android/location/fused/FusionEngine.java
@@ -0,0 +1,299 @@
+/*
+ * 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.location.fused;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.HashMap;
+
+import com.android.location.provider.LocationProviderBase;
+import com.android.location.provider.LocationRequestUnbundled;
+import com.android.location.provider.ProviderRequestUnbundled;
+
+import android.content.Context;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.Bundle;
+import android.os.Looper;
+import android.os.Parcelable;
+import android.os.SystemClock;
+import android.os.WorkSource;
+import android.util.Log;
+
+public class FusionEngine implements LocationListener {
+    public interface Callback {
+        public void reportLocation(Location location);
+    }
+
+    private static final String TAG = "FusedLocation";
+    private static final String NETWORK = LocationManager.NETWORK_PROVIDER;
+    private static final String GPS = LocationManager.GPS_PROVIDER;
+    private static final String FUSED = LocationProviderBase.FUSED_PROVIDER;
+
+    public static final long SWITCH_ON_FRESHNESS_CLIFF_NS = 11 * 1000000000; // 11 seconds
+
+    private final Context mContext;
+    private final LocationManager mLocationManager;
+    private final Looper mLooper;
+
+    // all fields are only used on mLooper thread. except for in dump() which is not thread-safe
+    private Callback mCallback;
+    private Location mFusedLocation;
+    private Location mGpsLocation;
+    private Location mNetworkLocation;
+
+    private boolean mEnabled;
+    private ProviderRequestUnbundled mRequest;
+
+    private final HashMap<String, ProviderStats> mStats = new HashMap<String, ProviderStats>();
+
+    public FusionEngine(Context context, Looper looper) {
+        mContext = context;
+        mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
+        mNetworkLocation = new Location("");
+        mNetworkLocation.setAccuracy(Float.MAX_VALUE);
+        mGpsLocation = new Location("");
+        mGpsLocation.setAccuracy(Float.MAX_VALUE);
+        mLooper = looper;
+
+        mStats.put(GPS, new ProviderStats());
+        mStats.get(GPS).available = mLocationManager.isProviderEnabled(GPS);
+        mStats.put(NETWORK, new ProviderStats());
+        mStats.get(NETWORK).available = mLocationManager.isProviderEnabled(NETWORK);
+
+    }
+
+    public void init(Callback callback) {
+        Log.i(TAG, "engine started (" + mContext.getPackageName() + ")");
+        mCallback = callback;
+    }
+
+    /**
+     * Called to stop doing any work, and release all resources
+     * This can happen when a better fusion engine is installed
+     * in a different package, and this one is no longer needed.
+     * Called on mLooper thread
+     */
+    public void deinit() {
+        mRequest = null;
+        disable();
+        Log.i(TAG, "engine stopped (" + mContext.getPackageName() + ")");
+    }
+
+    /** Called on mLooper thread */
+    public void enable() {
+        mEnabled = true;
+        updateRequirements();
+    }
+
+    /** Called on mLooper thread */
+    public void disable() {
+        mEnabled = false;
+        updateRequirements();
+    }
+
+    /** Called on mLooper thread */
+    public void setRequest(ProviderRequestUnbundled request, WorkSource source) {
+        mRequest = request;
+        mEnabled = request.getReportLocation();
+        updateRequirements();
+    }
+
+    private static class ProviderStats {
+        public boolean available;
+        public boolean requested;
+        public long requestTime;
+        public long minTime;
+        @Override
+        public String toString() {
+            StringBuilder s = new StringBuilder();
+            s.append(available ? "AVAILABLE" : "UNAVAILABLE");
+            s.append(requested ? " REQUESTED" : " ---");
+            return s.toString();
+        }
+    }
+
+    private void enableProvider(String name, long minTime) {
+        ProviderStats stats = mStats.get(name);
+
+        if (!stats.requested) {
+            stats.requestTime = SystemClock.elapsedRealtime();
+            stats.requested = true;
+            stats.minTime = minTime;
+            mLocationManager.requestLocationUpdates(name, minTime, 0, this, mLooper);
+        } else if (stats.minTime != minTime) {
+            stats.minTime = minTime;
+            mLocationManager.requestLocationUpdates(name, minTime, 0, this, mLooper);
+        }
+    }
+
+    private void disableProvider(String name) {
+        ProviderStats stats = mStats.get(name);
+
+        if (stats.requested) {
+            stats.requested = false;
+            mLocationManager.removeUpdates(this);  //TODO GLOBAL
+        }
+    }
+
+    private void updateRequirements() {
+        if (mEnabled == false || mRequest == null) {
+            mRequest = null;
+            disableProvider(NETWORK);
+            disableProvider(GPS);
+            return;
+        }
+
+        long networkInterval = Long.MAX_VALUE;
+        long gpsInterval = Long.MAX_VALUE;
+        for (LocationRequestUnbundled request : mRequest.getLocationRequests()) {
+            switch (request.getQuality()) {
+                case LocationRequestUnbundled.ACCURACY_FINE:
+                case LocationRequestUnbundled.POWER_HIGH:
+                    if (request.getInterval() < gpsInterval) {
+                        gpsInterval = request.getInterval();
+                    }
+                    if (request.getInterval() < networkInterval) {
+                        networkInterval = request.getInterval();
+                    }
+                    break;
+                case LocationRequestUnbundled.ACCURACY_BLOCK:
+                case LocationRequestUnbundled.ACCURACY_CITY:
+                case LocationRequestUnbundled.POWER_LOW:
+                    if (request.getInterval() < networkInterval) {
+                        networkInterval = request.getInterval();
+                    }
+                    break;
+            }
+        }
+
+        if (gpsInterval < Long.MAX_VALUE) {
+            enableProvider(GPS, gpsInterval);
+        } else {
+            disableProvider(GPS);
+        }
+        if (networkInterval < Long.MAX_VALUE) {
+            enableProvider(NETWORK, networkInterval);
+        } else {
+            disableProvider(NETWORK);
+        }
+    }
+
+    /**
+     * Test whether one location (a) is better to use than another (b).
+     */
+    private static boolean isBetterThan(Location locationA, Location locationB) {
+      if (locationA == null) {
+        return false;
+      }
+      if (locationB == null) {
+        return true;
+      }
+      // A provider is better if the reading is sufficiently newer.  Heading
+      // underground can cause GPS to stop reporting fixes.  In this case it's
+      // appropriate to revert to cell, even when its accuracy is less.
+      if (locationA.getElapsedRealtimeNanos() > locationB.getElapsedRealtimeNanos() + SWITCH_ON_FRESHNESS_CLIFF_NS) {
+        return true;
+      }
+
+      // A provider is better if it has better accuracy.  Assuming both readings
+      // are fresh (and by that accurate), choose the one with the smaller
+      // accuracy circle.
+      if (!locationA.hasAccuracy()) {
+        return false;
+      }
+      if (!locationB.hasAccuracy()) {
+        return true;
+      }
+      return locationA.getAccuracy() < locationB.getAccuracy();
+    }
+
+    private void updateFusedLocation() {
+        // may the best location win!
+        if (isBetterThan(mGpsLocation, mNetworkLocation)) {
+            mFusedLocation = new Location(mGpsLocation);
+        } else {
+            mFusedLocation = new Location(mNetworkLocation);
+        }
+        mFusedLocation.setProvider(FUSED);
+        if (mNetworkLocation != null) {
+            // copy NO_GPS_LOCATION extra from mNetworkLocation into mFusedLocation
+            Bundle srcExtras = mNetworkLocation.getExtras();
+            if (srcExtras != null) {
+                Parcelable srcParcelable =
+                        srcExtras.getParcelable(LocationProviderBase.EXTRA_NO_GPS_LOCATION);
+                if (srcParcelable instanceof Location) {
+                    Bundle dstExtras = mFusedLocation.getExtras();
+                    if (dstExtras == null) {
+                        dstExtras = new Bundle();
+                        mFusedLocation.setExtras(dstExtras);
+                    }
+                    dstExtras.putParcelable(LocationProviderBase.EXTRA_NO_GPS_LOCATION,
+                            (Location) srcParcelable);
+                }
+            }
+        }
+
+        mCallback.reportLocation(mFusedLocation);
+    }
+
+    /** Called on mLooper thread */
+    @Override
+    public void onLocationChanged(Location location) {
+        if (GPS.equals(location.getProvider())) {
+            mGpsLocation = location;
+            updateFusedLocation();
+        } else if (NETWORK.equals(location.getProvider())) {
+            mNetworkLocation = location;
+            updateFusedLocation();
+        }
+    }
+
+    /** Called on mLooper thread */
+    @Override
+    public void onStatusChanged(String provider, int status, Bundle extras) {  }
+
+    /** Called on mLooper thread */
+    @Override
+    public void onProviderEnabled(String provider) {
+        ProviderStats stats = mStats.get(provider);
+        if (stats == null) return;
+
+        stats.available = true;
+    }
+
+    /** Called on mLooper thread */
+    @Override
+    public void onProviderDisabled(String provider) {
+        ProviderStats stats = mStats.get(provider);
+        if (stats == null) return;
+
+        stats.available = false;
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        StringBuilder s = new StringBuilder();
+        s.append("mEnabled=" + mEnabled).append(' ').append(mRequest).append('\n');
+        s.append("fused=").append(mFusedLocation).append('\n');
+        s.append(String.format("gps %s\n", mGpsLocation));
+        s.append("    ").append(mStats.get(GPS)).append('\n');
+        s.append(String.format("net %s\n", mNetworkLocation));
+        s.append("    ").append(mStats.get(NETWORK)).append('\n');
+        pw.append(s);
+    }
+}
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index 0719426..ab2feb9 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -14,6 +14,7 @@
 
         <provider android:name="SettingsProvider" android:authorities="settings"
                   android:multiprocess="false"
+                  android:exported="true"
                   android:writePermission="android.permission.WRITE_SETTINGS"
                   android:initOrder="100" />
     </application>
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 2c9a6fe..94e2286 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -34,7 +34,9 @@
     <bool name="def_haptic_feedback">true</bool>
 
     <bool name="def_bluetooth_on">false</bool>
+    <bool name="def_wifi_display_on">false</bool>
     <bool name="def_install_non_market_apps">false</bool>
+    <bool name="def_package_verifier_enable">true</bool>
     <!-- Comma-separated list of location providers.
          Network location is off by default because it requires
          user opt-in via Setup Wizard or Settings.
@@ -46,8 +48,8 @@
     <bool name="def_netstats_enabled">true</bool>
     <bool name="def_usb_mass_storage_enabled">true</bool>
     <bool name="def_wifi_on">false</bool>
-    <!-- 0 == default, 1 == never while plugged, 2 == never -->
-    <integer name="def_wifi_sleep_policy">0</integer>
+    <!-- 0 == never, 1 == only when plugged in, 2 == always -->
+    <integer name="def_wifi_sleep_policy">2</integer>
     <bool name="def_networks_available_notification_on">true</bool>
 
     <bool name="def_backup_enabled">false</bool>
@@ -128,6 +130,15 @@
     <!-- Default for Settings.Secure.TOUCH_EXPLORATION_ENABLED -->
     <bool name="def_touch_exploration_enabled">false</bool>
 
+    <!-- Default value for Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE -->
+    <fraction name="def_accessibility_display_magnification_scale">200%</fraction>
+
+    <!-- Default value for Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED -->
+    <bool name="def_accessibility_display_magnification_enabled">false</bool>
+
+    <!-- Default value for Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE -->
+    <bool name="def_accessibility_display_magnification_auto_update">true</bool>
+
     <!-- Default for Settings.System.USER_ROTATION -->
     <integer name="def_user_rotation">0</integer>
 
@@ -153,4 +164,7 @@
     <!-- Number of retries for connecting to DHCP.
          Value here is the same as WifiStateMachine.DEFAULT_MAX_DHCP_RETRIES -->
     <integer name="def_max_dhcp_retries">9</integer>
+
+    <!-- Default for Settings.Secure.USER_SETUP_COMPLETE -->
+    <bool name="def_user_setup_complete">false</bool>
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 7430f57..b649b43 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -30,15 +30,17 @@
 import android.media.AudioManager;
 import android.media.AudioService;
 import android.net.ConnectivityManager;
+import android.os.Environment;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.provider.Settings;
+import android.provider.Settings.Global;
 import android.provider.Settings.Secure;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.internal.content.PackageHelper;
-import com.android.internal.telephony.BaseCommands;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.RILConstants;
@@ -49,6 +51,7 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import java.io.File;
 import java.io.IOException;
 import java.util.HashSet;
 import java.util.List;
@@ -65,15 +68,21 @@
     // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
     // is properly propagated through your change.  Not doing so will result in a loss of user
     // settings.
-    private static final int DATABASE_VERSION = 80;
+    private static final int DATABASE_VERSION = 94;
 
     private Context mContext;
+    private int mUserHandle;
 
     private static final HashSet<String> mValidTables = new HashSet<String>();
 
+    private static final String TABLE_SYSTEM = "system";
+    private static final String TABLE_SECURE = "secure";
+    private static final String TABLE_GLOBAL = "global";
+
     static {
-        mValidTables.add("system");
-        mValidTables.add("secure");
+        mValidTables.add(TABLE_SYSTEM);
+        mValidTables.add(TABLE_SECURE);
+        mValidTables.add(TABLE_GLOBAL);
         mValidTables.add("bluetooth_devices");
         mValidTables.add("bookmarks");
 
@@ -83,9 +92,23 @@
         mValidTables.add("old_favorites");
     }
 
-    public DatabaseHelper(Context context) {
-        super(context, DATABASE_NAME, null, DATABASE_VERSION);
+    static String dbNameForUser(final int userHandle) {
+        // The owner gets the unadorned db name;
+        if (userHandle == UserHandle.USER_OWNER) {
+            return DATABASE_NAME;
+        } else {
+            // Place the database in the user-specific data tree so that it's
+            // cleaned up automatically when the user is deleted.
+            File databaseFile = new File(
+                    Environment.getUserSystemDirectory(userHandle), DATABASE_NAME);
+            return databaseFile.getPath();
+        }
+    }
+
+    public DatabaseHelper(Context context, int userHandle) {
+        super(context, dbNameForUser(userHandle), null, DATABASE_VERSION);
         mContext = context;
+        mUserHandle = userHandle;
         setWriteAheadLoggingEnabled(true);
     }
 
@@ -102,6 +125,15 @@
         db.execSQL("CREATE INDEX secureIndex1 ON secure (name);");
     }
 
+    private void createGlobalTable(SQLiteDatabase db) {
+        db.execSQL("CREATE TABLE global (" +
+                "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
+                "name TEXT UNIQUE ON CONFLICT REPLACE," +
+                "value TEXT" +
+                ");");
+        db.execSQL("CREATE INDEX globalIndex1 ON global (name);");
+    }
+
     @Override
     public void onCreate(SQLiteDatabase db) {
         db.execSQL("CREATE TABLE system (" +
@@ -113,6 +145,11 @@
 
         createSecureTable(db);
 
+        // Only create the global table for the singleton 'owner' user
+        if (mUserHandle == UserHandle.USER_OWNER) {
+            createGlobalTable(db);
+        }
+
         db.execSQL("CREATE TABLE bluetooth_devices (" +
                     "_id INTEGER PRIMARY KEY," +
                     "name TEXT," +
@@ -272,7 +309,7 @@
                     Settings.Secure.WIFI_WATCHDOG_PING_DELAY_MS,
                     Settings.Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS,
                 };
-            moveFromSystemToSecure(db, settingsToMove);
+            moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_SECURE, settingsToMove, false);
             upgradeVersion = 28;
         }
 
@@ -436,7 +473,7 @@
                 String value =
                         mContext.getResources().getBoolean(R.bool.assisted_gps_enabled) ? "1" : "0";
                 db.execSQL("INSERT OR IGNORE INTO secure(name,value) values('" +
-                        Settings.Secure.ASSISTED_GPS_ENABLED + "','" + value + "');");
+                        Settings.Global.ASSISTED_GPS_ENABLED + "','" + value + "');");
                 db.setTransactionSuccessful();
             } finally {
                 db.endTransaction();
@@ -638,7 +675,7 @@
                    "lockscreen.lockedoutpermanently",
                    "lockscreen.password_salt"
            };
-           moveFromSystemToSecure(db, settingsToMove);
+           moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_SECURE, settingsToMove, false);
            upgradeVersion = 52;
        }
 
@@ -685,17 +722,17 @@
         if (upgradeVersion == 55) {
             /* Move the install location settings. */
             String[] settingsToMove = {
-                    Secure.SET_INSTALL_LOCATION,
-                    Secure.DEFAULT_INSTALL_LOCATION
+                    Global.SET_INSTALL_LOCATION,
+                    Global.DEFAULT_INSTALL_LOCATION
             };
-            moveFromSystemToSecure(db, settingsToMove);
+            moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_SECURE, settingsToMove, false);
             db.beginTransaction();
             SQLiteStatement stmt = null;
             try {
                 stmt = db.compileStatement("INSERT INTO system(name,value)"
                         + " VALUES(?,?);");
-                loadSetting(stmt, Secure.SET_INSTALL_LOCATION, 0);
-                loadSetting(stmt, Secure.DEFAULT_INSTALL_LOCATION,
+                loadSetting(stmt, Global.SET_INSTALL_LOCATION, 0);
+                loadSetting(stmt, Global.DEFAULT_INSTALL_LOCATION,
                         PackageHelper.APP_INSTALL_AUTO);
                 db.setTransactionSuccessful();
              } finally {
@@ -1014,7 +1051,7 @@
             SQLiteStatement stmt = null;
             Cursor c = null;
             try {
-                c = db.query("secure", new String[] {"_id", "value"},
+                c = db.query(TABLE_SECURE, new String[] {"_id", "value"},
                         "name='lockscreen.disabled'",
                         null, null, null, null);
                 // only set default if it has not yet been set
@@ -1090,14 +1127,14 @@
             // toggle touch exploration. Note that the user has already manually
             // enabled the services and touch exploration which means the she has
             // given consent to have these services work in touch exploration mode.
-            final boolean accessibilityEnabled = getIntValueFromTable(db, "secure",
+            final boolean accessibilityEnabled = getIntValueFromTable(db, TABLE_SECURE,
                     Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
-            final boolean touchExplorationEnabled = getIntValueFromTable(db, "secure",
+            final boolean touchExplorationEnabled = getIntValueFromTable(db, TABLE_SECURE,
                     Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1;
             if (accessibilityEnabled && touchExplorationEnabled) {
-                String enabledServices = getStringValueFromTable(db, "secure",
+                String enabledServices = getStringValueFromTable(db, TABLE_SECURE,
                         Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "");
-                String touchExplorationGrantedServices = getStringValueFromTable(db, "secure",
+                String touchExplorationGrantedServices = getStringValueFromTable(db, TABLE_SECURE,
                         Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, "");
                 if (TextUtils.isEmpty(touchExplorationGrantedServices)
                         && !TextUtils.isEmpty(enabledServices)) {
@@ -1119,11 +1156,351 @@
             upgradeVersion = 80;
         }
 
+        // vvv Jelly Bean MR1 changes begin here vvv
+
+        if (upgradeVersion == 80) {
+            // update screensaver settings
+            db.beginTransaction();
+            SQLiteStatement stmt = null;
+            try {
+                stmt = db.compileStatement("INSERT OR REPLACE INTO secure(name,value)"
+                        + " VALUES(?,?);");
+                loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ENABLED,
+                        com.android.internal.R.bool.config_dreamsEnabledByDefault);
+                loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
+                        com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
+                loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
+                        com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
+                loadStringSetting(stmt, Settings.Secure.SCREENSAVER_COMPONENTS,
+                        com.android.internal.R.string.config_dreamsDefaultComponent);
+                loadStringSetting(stmt, Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
+                        com.android.internal.R.string.config_dreamsDefaultComponent);
+
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+                if (stmt != null) stmt.close();
+            }
+            upgradeVersion = 81;
+        }
+
+        if (upgradeVersion == 81) {
+            // Add package verification setting
+            db.beginTransaction();
+            SQLiteStatement stmt = null;
+            try {
+                stmt = db.compileStatement("INSERT OR REPLACE INTO secure(name,value)"
+                        + " VALUES(?,?);");
+                loadBooleanSetting(stmt, Settings.Global.PACKAGE_VERIFIER_ENABLE,
+                        R.bool.def_package_verifier_enable);
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+                if (stmt != null) stmt.close();
+            }
+            upgradeVersion = 82;
+        }
+
+        if (upgradeVersion == 82) {
+            // Move to per-user settings dbs
+            if (mUserHandle == UserHandle.USER_OWNER) {
+
+                db.beginTransaction();
+                SQLiteStatement stmt = null;
+                try {
+                    // Migrate now-global settings. Note that this happens before
+                    // new users can be created.
+                    createGlobalTable(db);
+                    String[] settingsToMove = hashsetToStringArray(SettingsProvider.sSystemGlobalKeys);
+                    moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, settingsToMove, false);
+                    settingsToMove = hashsetToStringArray(SettingsProvider.sSecureGlobalKeys);
+                    moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, false);
+
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                    if (stmt != null) stmt.close();
+                }
+            }
+            upgradeVersion = 83;
+        }
+
+        if (upgradeVersion == 83) {
+            // 1. Setting whether screen magnification is enabled.
+            // 2. Setting for screen magnification scale.
+            // 3. Setting for screen magnification auto update.
+            db.beginTransaction();
+            SQLiteStatement stmt = null;
+            try {
+                stmt = db.compileStatement("INSERT INTO secure(name,value) VALUES(?,?);");
+                loadBooleanSetting(stmt,
+                        Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
+                        R.bool.def_accessibility_display_magnification_enabled);
+                stmt.close();
+                stmt = db.compileStatement("INSERT INTO secure(name,value) VALUES(?,?);");
+                loadFractionSetting(stmt, Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+                        R.fraction.def_accessibility_display_magnification_scale, 1);
+                stmt.close();
+                stmt = db.compileStatement("INSERT INTO secure(name,value) VALUES(?,?);");
+                loadBooleanSetting(stmt,
+                        Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE,
+                        R.bool.def_accessibility_display_magnification_auto_update);
+
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+                if (stmt != null) stmt.close();
+            }
+            upgradeVersion = 84;
+        }
+
+        if (upgradeVersion == 84) {
+            if (mUserHandle == UserHandle.USER_OWNER) {
+                db.beginTransaction();
+                SQLiteStatement stmt = null;
+                try {
+                    // Patch up the slightly-wrong key migration from 82 -> 83 for those
+                    // devices that missed it, ignoring if the move is redundant
+                    String[] settingsToMove = {
+                            Settings.Secure.ADB_ENABLED,
+                            Settings.Secure.BLUETOOTH_ON,
+                            Settings.Secure.DATA_ROAMING,
+                            Settings.Secure.DEVICE_PROVISIONED,
+                            Settings.Secure.INSTALL_NON_MARKET_APPS,
+                            Settings.Secure.USB_MASS_STORAGE_ENABLED
+                    };
+                    moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true);
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                    if (stmt != null) stmt.close();
+                }
+            }
+            upgradeVersion = 85;
+        }
+
+        if (upgradeVersion == 85) {
+            if (mUserHandle == UserHandle.USER_OWNER) {
+                db.beginTransaction();
+                try {
+                    // Fix up the migration, ignoring already-migrated elements, to snap up to
+                    // date with new changes to the set of global versus system/secure settings
+                    String[] settingsToMove = { Settings.System.STAY_ON_WHILE_PLUGGED_IN };
+                    moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, settingsToMove, true);
+
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+            upgradeVersion = 86;
+        }
+
+        if (upgradeVersion == 86) {
+            if (mUserHandle == UserHandle.USER_OWNER) {
+                db.beginTransaction();
+                try {
+                    String[] settingsToMove = {
+                            Settings.Global.PACKAGE_VERIFIER_ENABLE,
+                            Settings.Global.PACKAGE_VERIFIER_TIMEOUT,
+                            Settings.Global.PACKAGE_VERIFIER_DEFAULT_RESPONSE
+                    };
+                    moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true);
+
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+            upgradeVersion = 87;
+        }
+
+        if (upgradeVersion == 87) {
+            if (mUserHandle == UserHandle.USER_OWNER) {
+                db.beginTransaction();
+                try {
+                    String[] settingsToMove = {
+                            Settings.Global.DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS,
+                            Settings.Global.DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS,
+                            Settings.Global.GPRS_REGISTER_CHECK_PERIOD_MS
+                    };
+                    moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true);
+
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+            upgradeVersion = 88;
+        }
+
+        if (upgradeVersion == 88) {
+            if (mUserHandle == UserHandle.USER_OWNER) {
+                db.beginTransaction();
+                try {
+                    String[] settingsToMove = {
+                            Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD,
+                            Settings.Global.BATTERY_DISCHARGE_THRESHOLD,
+                            Settings.Global.SEND_ACTION_APP_ERROR,
+                            Settings.Global.DROPBOX_AGE_SECONDS,
+                            Settings.Global.DROPBOX_MAX_FILES,
+                            Settings.Global.DROPBOX_QUOTA_KB,
+                            Settings.Global.DROPBOX_QUOTA_PERCENT,
+                            Settings.Global.DROPBOX_RESERVE_PERCENT,
+                            Settings.Global.DROPBOX_TAG_PREFIX,
+                            Settings.Global.ERROR_LOGCAT_PREFIX,
+                            Settings.Global.SYS_FREE_STORAGE_LOG_INTERVAL,
+                            Settings.Global.DISK_FREE_CHANGE_REPORTING_THRESHOLD,
+                            Settings.Global.SYS_STORAGE_THRESHOLD_PERCENTAGE,
+                            Settings.Global.SYS_STORAGE_THRESHOLD_MAX_BYTES,
+                            Settings.Global.SYS_STORAGE_FULL_THRESHOLD_BYTES,
+                            Settings.Global.SYNC_MAX_RETRY_DELAY_IN_SECONDS,
+                            Settings.Global.CONNECTIVITY_CHANGE_DELAY,
+                            Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED,
+                            Settings.Global.CAPTIVE_PORTAL_SERVER,
+                            Settings.Global.NSD_ON,
+                            Settings.Global.SET_INSTALL_LOCATION,
+                            Settings.Global.DEFAULT_INSTALL_LOCATION,
+                            Settings.Global.INET_CONDITION_DEBOUNCE_UP_DELAY,
+                            Settings.Global.INET_CONDITION_DEBOUNCE_DOWN_DELAY,
+                            Settings.Global.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT,
+                            Settings.Global.HTTP_PROXY,
+                            Settings.Global.GLOBAL_HTTP_PROXY_HOST,
+                            Settings.Global.GLOBAL_HTTP_PROXY_PORT,
+                            Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
+                            Settings.Global.SET_GLOBAL_HTTP_PROXY,
+                            Settings.Global.DEFAULT_DNS_SERVER,
+                    };
+                    moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true);
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+            upgradeVersion = 89;
+        }
+
+        if (upgradeVersion == 89) {
+            if (mUserHandle == UserHandle.USER_OWNER) {
+                db.beginTransaction();
+                try {
+                    String[] prefixesToMove = {
+                            Settings.Global.BLUETOOTH_HEADSET_PRIORITY_PREFIX,
+                            Settings.Global.BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX,
+                            Settings.Global.BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX,
+                    };
+
+                    movePrefixedSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, prefixesToMove);
+
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+            upgradeVersion = 90;
+        }
+
+        if (upgradeVersion == 90) {
+            if (mUserHandle == UserHandle.USER_OWNER) {
+                db.beginTransaction();
+                try {
+                    String[] systemToGlobal = {
+                            Settings.Global.WINDOW_ANIMATION_SCALE,
+                            Settings.Global.TRANSITION_ANIMATION_SCALE,
+                            Settings.Global.ANIMATOR_DURATION_SCALE,
+                            Settings.Global.FANCY_IME_ANIMATIONS,
+                            Settings.Global.COMPATIBILITY_MODE,
+                            Settings.Global.EMERGENCY_TONE,
+                            Settings.Global.CALL_AUTO_RETRY,
+                            Settings.Global.DEBUG_APP,
+                            Settings.Global.WAIT_FOR_DEBUGGER,
+                            Settings.Global.SHOW_PROCESSES,
+                            Settings.Global.ALWAYS_FINISH_ACTIVITIES,
+                    };
+                    String[] secureToGlobal = {
+                            Settings.Global.PREFERRED_NETWORK_MODE,
+                            Settings.Global.PREFERRED_CDMA_SUBSCRIPTION,
+                    };
+
+                    moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, systemToGlobal, true);
+                    moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, secureToGlobal, true);
+
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+            upgradeVersion = 91;
+        }
+
+        if (upgradeVersion == 91) {
+            if (mUserHandle == UserHandle.USER_OWNER) {
+                db.beginTransaction();
+                try {
+                    // Move ringer mode from system to global settings
+                    String[] settingsToMove = { Settings.Global.MODE_RINGER };
+                    moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, settingsToMove, true);
+
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+            upgradeVersion = 92;
+        }
+
+        if (upgradeVersion == 92) {
+            SQLiteStatement stmt = null;
+            try {
+                stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
+                        + " VALUES(?,?);");
+                if (mUserHandle == UserHandle.USER_OWNER) {
+                    // consider existing primary users to have made it through user setup
+                    // if the globally-scoped device-provisioned bit is set
+                    // (indicating they already made it through setup as primary)
+                    int deviceProvisioned = getIntValueFromTable(db, TABLE_GLOBAL,
+                            Settings.Global.DEVICE_PROVISIONED, 0);
+                    loadSetting(stmt, Settings.Secure.USER_SETUP_COMPLETE,
+                            deviceProvisioned);
+                } else {
+                    // otherwise use the default
+                    loadBooleanSetting(stmt, Settings.Secure.USER_SETUP_COMPLETE,
+                            R.bool.def_user_setup_complete);
+                }
+            } finally {
+                if (stmt != null) stmt.close();
+            }
+            upgradeVersion = 93;
+        }
+
+        if (upgradeVersion == 93) {
+            // Redo this step, since somehow it didn't work the first time for some users
+            if (mUserHandle == UserHandle.USER_OWNER) {
+                db.beginTransaction();
+                SQLiteStatement stmt = null;
+                try {
+                    // Migrate now-global settings
+                    String[] settingsToMove = hashsetToStringArray(SettingsProvider.sSystemGlobalKeys);
+                    moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, settingsToMove, true);
+                    settingsToMove = hashsetToStringArray(SettingsProvider.sSecureGlobalKeys);
+                    moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true);
+
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                    if (stmt != null) stmt.close();
+                }
+            }
+            upgradeVersion = 94;
+        }
+
         // *** Remember to update DATABASE_VERSION above!
 
         if (upgradeVersion != currentVersion) {
             Log.w(TAG, "Got stuck trying to upgrade from version " + upgradeVersion
                     + ", must wipe the settings provider");
+            db.execSQL("DROP TABLE IF EXISTS global");
+            db.execSQL("DROP TABLE IF EXISTS globalIndex1");
             db.execSQL("DROP TABLE IF EXISTS system");
             db.execSQL("DROP INDEX IF EXISTS systemIndex1");
             db.execSQL("DROP TABLE IF EXISTS secure");
@@ -1144,18 +1521,25 @@
         }
     }
 
-    private void moveFromSystemToSecure(SQLiteDatabase db, String [] settingsToMove) {
-        // Copy settings values from 'system' to 'secure' and delete them from 'system'
+    private String[] hashsetToStringArray(HashSet<String> set) {
+        String[] array = new String[set.size()];
+        return set.toArray(array);
+    }
+
+    private void moveSettingsToNewTable(SQLiteDatabase db,
+            String sourceTable, String destTable,
+            String[] settingsToMove, boolean doIgnore) {
+        // Copy settings values from the source table to the dest, and remove from the source
         SQLiteStatement insertStmt = null;
         SQLiteStatement deleteStmt = null;
 
         db.beginTransaction();
         try {
-            insertStmt =
-                db.compileStatement("INSERT INTO secure (name,value) SELECT name,value FROM "
-                    + "system WHERE name=?");
-            deleteStmt = db.compileStatement("DELETE FROM system WHERE name=?");
-
+            insertStmt = db.compileStatement("INSERT "
+                    + (doIgnore ? " OR IGNORE " : "")
+                    + " INTO " + destTable + " (name,value) SELECT name,value FROM "
+                    + sourceTable + " WHERE name=?");
+            deleteStmt = db.compileStatement("DELETE FROM " + sourceTable + " WHERE name=?");
 
             for (String setting : settingsToMove) {
                 insertStmt.bindString(1, setting);
@@ -1176,8 +1560,46 @@
         }
     }
 
+    /**
+     * Move any settings with the given prefixes from the source table to the
+     * destination table.
+     */
+    private void movePrefixedSettingsToNewTable(
+            SQLiteDatabase db, String sourceTable, String destTable, String[] prefixesToMove) {
+        SQLiteStatement insertStmt = null;
+        SQLiteStatement deleteStmt = null;
+
+        db.beginTransaction();
+        try {
+            insertStmt = db.compileStatement("INSERT INTO " + destTable
+                    + " (name,value) SELECT name,value FROM " + sourceTable
+                    + " WHERE substr(name,0,?)=?");
+            deleteStmt = db.compileStatement(
+                    "DELETE FROM " + sourceTable + " WHERE substr(name,0,?)=?");
+
+            for (String prefix : prefixesToMove) {
+                insertStmt.bindLong(1, prefix.length() + 1);
+                insertStmt.bindString(2, prefix);
+                insertStmt.execute();
+
+                deleteStmt.bindLong(1, prefix.length() + 1);
+                deleteStmt.bindString(2, prefix);
+                deleteStmt.execute();
+            }
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+            if (insertStmt != null) {
+                insertStmt.close();
+            }
+            if (deleteStmt != null) {
+                deleteStmt.close();
+            }
+        }
+    }
+
     private void upgradeLockPatternLocation(SQLiteDatabase db) {
-        Cursor c = db.query("system", new String[] {"_id", "value"}, "name='lock_pattern'",
+        Cursor c = db.query(TABLE_SYSTEM, new String[] {"_id", "value"}, "name='lock_pattern'",
                 null, null, null, null);
         if (c.getCount() > 0) {
             c.moveToFirst();
@@ -1194,7 +1616,7 @@
                 }
             }
             c.close();
-            db.delete("system", "name='lock_pattern'", null);
+            db.delete(TABLE_SYSTEM, "name='lock_pattern'", null);
         } else {
             c.close();
         }
@@ -1202,7 +1624,7 @@
 
     private void upgradeScreenTimeoutFromNever(SQLiteDatabase db) {
         // See if the timeout is -1 (for "Never").
-        Cursor c = db.query("system", new String[] { "_id", "value" }, "name=? AND value=?",
+        Cursor c = db.query(TABLE_SYSTEM, new String[] { "_id", "value" }, "name=? AND value=?",
                 new String[] { Settings.System.SCREEN_OFF_TIMEOUT, "-1" },
                 null, null, null);
 
@@ -1396,9 +1818,6 @@
                     Settings.System.VOLUME_BLUETOOTH_SCO,
                     AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_BLUETOOTH_SCO]);
 
-            loadSetting(stmt, Settings.System.MODE_RINGER,
-                    AudioManager.RINGER_MODE_NORMAL);
-
             // By default:
             // - ringtones, notification, system and music streams are affected by ringer mode
             // on non voice capable devices (tablets)
@@ -1471,6 +1890,10 @@
     private void loadSettings(SQLiteDatabase db) {
         loadSystemSettings(db);
         loadSecureSettings(db);
+        // The global table only exists for the 'owner' user
+        if (mUserHandle == UserHandle.USER_OWNER) {
+            loadGlobalSettings(db);
+        }
     }
 
     private void loadSystemSettings(SQLiteDatabase db) {
@@ -1481,19 +1904,9 @@
 
             loadBooleanSetting(stmt, Settings.System.DIM_SCREEN,
                     R.bool.def_dim_screen);
-            loadSetting(stmt, Settings.System.STAY_ON_WHILE_PLUGGED_IN,
-                    ("1".equals(SystemProperties.get("ro.kernel.qemu")) ||
-                        mContext.getResources().getBoolean(R.bool.def_stay_on_while_plugged_in))
-                     ? 1 : 0);
             loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
                     R.integer.def_screen_off_timeout);
 
-            // Set default cdma emergency tone
-            loadSetting(stmt, Settings.System.EMERGENCY_TONE, 0);
-
-            // Set default cdma call auto retry
-            loadSetting(stmt, Settings.System.CALL_AUTO_RETRY, 0);
-
             // Set default cdma DTMF type
             loadSetting(stmt, Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, 0);
 
@@ -1503,21 +1916,6 @@
             // Set default tty mode
             loadSetting(stmt, Settings.System.TTY_MODE, 0);
 
-            loadBooleanSetting(stmt, Settings.System.AIRPLANE_MODE_ON,
-                    R.bool.def_airplane_mode_on);
-
-            loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_RADIOS,
-                    R.string.def_airplane_mode_radios);
-
-            loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
-                    R.string.airplane_mode_toggleable_radios);
-
-            loadBooleanSetting(stmt, Settings.System.AUTO_TIME,
-                    R.bool.def_auto_time); // Sync time to NITZ
-
-            loadBooleanSetting(stmt, Settings.System.AUTO_TIME_ZONE,
-                    R.bool.def_auto_time_zone); // Sync timezone to NITZ
-
             loadIntegerSetting(stmt, Settings.System.SCREEN_BRIGHTNESS,
                     R.integer.def_screen_brightness);
 
@@ -1533,27 +1931,17 @@
 
             loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
                     R.bool.def_notification_pulse);
-            loadSetting(stmt, Settings.Secure.SET_INSTALL_LOCATION, 0);
-            loadSetting(stmt, Settings.Secure.DEFAULT_INSTALL_LOCATION,
-                    PackageHelper.APP_INSTALL_AUTO);
 
             loadUISoundEffectsSettings(stmt);
 
             loadIntegerSetting(stmt, Settings.System.POINTER_SPEED,
                     R.integer.def_pointer_speed);
-
-            loadIntegerSetting(stmt, Settings.System.WIFI_SLEEP_POLICY,
-                    R.integer.def_wifi_sleep_policy);
         } finally {
             if (stmt != null) stmt.close();
         }
     }
 
     private void loadUISoundEffectsSettings(SQLiteStatement stmt) {
-        loadIntegerSetting(stmt, Settings.System.POWER_SOUNDS_ENABLED,
-            R.integer.def_power_sounds_enabled);
-        loadStringSetting(stmt, Settings.System.LOW_BATTERY_SOUND,
-            R.string.def_low_battery_sound);
         loadBooleanSetting(stmt, Settings.System.DTMF_TONE_WHEN_DIALING,
                 R.bool.def_dtmf_tones_enabled);
         loadBooleanSetting(stmt, Settings.System.SOUND_EFFECTS_ENABLED,
@@ -1561,23 +1949,8 @@
         loadBooleanSetting(stmt, Settings.System.HAPTIC_FEEDBACK_ENABLED,
                 R.bool.def_haptic_feedback);
 
-        loadIntegerSetting(stmt, Settings.System.DOCK_SOUNDS_ENABLED,
-            R.integer.def_dock_sounds_enabled);
-        loadStringSetting(stmt, Settings.System.DESK_DOCK_SOUND,
-            R.string.def_desk_dock_sound);
-        loadStringSetting(stmt, Settings.System.DESK_UNDOCK_SOUND,
-            R.string.def_desk_undock_sound);
-        loadStringSetting(stmt, Settings.System.CAR_DOCK_SOUND,
-            R.string.def_car_dock_sound);
-        loadStringSetting(stmt, Settings.System.CAR_UNDOCK_SOUND,
-            R.string.def_car_undock_sound);
-
         loadIntegerSetting(stmt, Settings.System.LOCKSCREEN_SOUNDS_ENABLED,
             R.integer.def_lockscreen_sounds_enabled);
-        loadStringSetting(stmt, Settings.System.LOCK_SOUND,
-            R.string.def_lock_sound);
-        loadStringSetting(stmt, Settings.System.UNLOCK_SOUND,
-            R.string.def_unlock_sound);
     }
 
     private void loadDefaultAnimationSettings(SQLiteStatement stmt) {
@@ -1598,60 +1971,14 @@
             stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
                     + " VALUES(?,?);");
 
-            loadBooleanSetting(stmt, Settings.Secure.BLUETOOTH_ON,
-                    R.bool.def_bluetooth_on);
-
-            // Data roaming default, based on build
-            loadSetting(stmt, Settings.Secure.DATA_ROAMING,
-                    "true".equalsIgnoreCase(
-                            SystemProperties.get("ro.com.android.dataroaming",
-                                    "false")) ? 1 : 0);
-
-            // Mobile Data default, based on build
-            loadSetting(stmt, Settings.Secure.MOBILE_DATA,
-                    "true".equalsIgnoreCase(
-                            SystemProperties.get("ro.com.android.mobiledata",
-                                    "true")) ? 1 : 0);
-
-            loadBooleanSetting(stmt, Settings.Secure.INSTALL_NON_MARKET_APPS,
-                    R.bool.def_install_non_market_apps);
-
             loadStringSetting(stmt, Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
                     R.string.def_location_providers_allowed);
 
-            loadBooleanSetting(stmt, Settings.Secure.ASSISTED_GPS_ENABLED,
-                    R.bool.assisted_gps_enabled);
-
-            loadIntegerSetting(stmt, Settings.Secure.NETWORK_PREFERENCE,
-                    R.integer.def_network_preference);
-
-            loadBooleanSetting(stmt, Settings.Secure.USB_MASS_STORAGE_ENABLED,
-                    R.bool.def_usb_mass_storage_enabled);
-
-            loadBooleanSetting(stmt, Settings.Secure.WIFI_ON,
-                    R.bool.def_wifi_on);
-            loadBooleanSetting(stmt, Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
-                    R.bool.def_networks_available_notification_on);
-
             String wifiWatchList = SystemProperties.get("ro.com.android.wifi-watchlist");
             if (!TextUtils.isEmpty(wifiWatchList)) {
                 loadSetting(stmt, Settings.Secure.WIFI_WATCHDOG_WATCH_LIST, wifiWatchList);
             }
 
-            // Set the preferred network mode to 0 = Global, CDMA default
-            int type;
-            if (TelephonyManager.getLteOnCdmaModeStatic() == PhoneConstants.LTE_ON_CDMA_TRUE) {
-                type = Phone.NT_MODE_GLOBAL;
-            } else {
-                type = SystemProperties.getInt("ro.telephony.default_network",
-                        RILConstants.PREFERRED_NETWORK_MODE);
-            }
-            loadSetting(stmt, Settings.Secure.PREFERRED_NETWORK_MODE, type);
-
-            // Enable or disable Cell Broadcast SMS
-            loadSetting(stmt, Settings.Secure.CDMA_CELL_BROADCAST_SMS,
-                    RILConstants.CDMA_CELL_BROADCAST_SMS_DISABLED);
-
             // Don't do this.  The SystemServer will initialize ADB_ENABLED from a
             // persistent system property instead.
             //loadSetting(stmt, Settings.Secure.ADB_ENABLED, 0);
@@ -1680,20 +2007,6 @@
             loadStringSetting(stmt, Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS,
                     R.string.def_accessibility_web_content_key_bindings);
 
-            final int maxBytes = mContext.getResources().getInteger(
-                    R.integer.def_download_manager_max_bytes_over_mobile);
-            if (maxBytes > 0) {
-                loadSetting(stmt, Settings.Secure.DOWNLOAD_MAX_BYTES_OVER_MOBILE,
-                        Integer.toString(maxBytes));
-            }
-
-            final int recommendedMaxBytes = mContext.getResources().getInteger(
-                    R.integer.def_download_manager_recommended_max_bytes_over_mobile);
-            if (recommendedMaxBytes > 0) {
-                loadSetting(stmt, Settings.Secure.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE,
-                        Integer.toString(recommendedMaxBytes));
-            }
-
             loadIntegerSetting(stmt, Settings.Secure.LONG_PRESS_TIMEOUT,
                     R.integer.def_long_press_timeout_millis);
 
@@ -1706,17 +2019,36 @@
             loadStringSetting(stmt, Settings.Secure.ACCESSIBILITY_SCREEN_READER_URL,
                     R.string.def_accessibility_screen_reader_url);
 
-            loadBooleanSetting(stmt, Settings.System.LOCKSCREEN_DISABLED,
-                    R.bool.def_lockscreen_disabled);
+            if (SystemProperties.getBoolean("ro.lockscreen.disable.default", false) == true) {
+                loadSetting(stmt, Settings.System.LOCKSCREEN_DISABLED, "1");
+            } else {
+                loadBooleanSetting(stmt, Settings.System.LOCKSCREEN_DISABLED,
+                        R.bool.def_lockscreen_disabled);
+            }
 
-            loadBooleanSetting(stmt, Settings.Secure.DEVICE_PROVISIONED,
-                    R.bool.def_device_provisioned);
+            loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ENABLED,
+                    com.android.internal.R.bool.config_dreamsEnabledByDefault);
+            loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
+                    com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
+            loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
+                    com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
+            loadStringSetting(stmt, Settings.Secure.SCREENSAVER_COMPONENTS,
+                    com.android.internal.R.string.config_dreamsDefaultComponent);
+            loadStringSetting(stmt, Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
+                    com.android.internal.R.string.config_dreamsDefaultComponent);
 
-            loadBooleanSetting(stmt, Settings.Secure.NETSTATS_ENABLED,
-                    R.bool.def_netstats_enabled);
+            loadBooleanSetting(stmt, Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
+                    R.bool.def_accessibility_display_magnification_enabled);
 
-            loadIntegerSetting(stmt, Settings.Secure.WIFI_MAX_DHCP_RETRY_COUNT,
-                    R.integer.def_max_dhcp_retries);
+            loadFractionSetting(stmt, Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+                    R.fraction.def_accessibility_display_magnification_scale, 1);
+
+            loadBooleanSetting(stmt,
+                    Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE,
+                    R.bool.def_accessibility_display_magnification_auto_update);
+
+            loadBooleanSetting(stmt, Settings.Secure.USER_SETUP_COMPLETE,
+                    R.bool.def_user_setup_complete);
         } finally {
             if (stmt != null) stmt.close();
         }
@@ -1730,6 +2062,151 @@
                 R.string.def_backup_transport);
     }
 
+    private void loadGlobalSettings(SQLiteDatabase db) {
+        SQLiteStatement stmt = null;
+        try {
+            stmt = db.compileStatement("INSERT OR IGNORE INTO global(name,value)"
+                    + " VALUES(?,?);");
+
+            // --- Previously in 'system'
+            loadBooleanSetting(stmt, Settings.Global.AIRPLANE_MODE_ON,
+                    R.bool.def_airplane_mode_on);
+
+            loadStringSetting(stmt, Settings.Global.AIRPLANE_MODE_RADIOS,
+                    R.string.def_airplane_mode_radios);
+
+            loadStringSetting(stmt, Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
+                    R.string.airplane_mode_toggleable_radios);
+
+            loadBooleanSetting(stmt, Settings.Global.ASSISTED_GPS_ENABLED,
+                    R.bool.assisted_gps_enabled);
+
+            loadBooleanSetting(stmt, Settings.Global.AUTO_TIME,
+                    R.bool.def_auto_time); // Sync time to NITZ
+
+            loadBooleanSetting(stmt, Settings.Global.AUTO_TIME_ZONE,
+                    R.bool.def_auto_time_zone); // Sync timezone to NITZ
+
+            loadSetting(stmt, Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
+                    ("1".equals(SystemProperties.get("ro.kernel.qemu")) ||
+                        mContext.getResources().getBoolean(R.bool.def_stay_on_while_plugged_in))
+                     ? 1 : 0);
+
+            loadIntegerSetting(stmt, Settings.Global.WIFI_SLEEP_POLICY,
+                    R.integer.def_wifi_sleep_policy);
+
+            loadSetting(stmt, Settings.Global.MODE_RINGER,
+                    AudioManager.RINGER_MODE_NORMAL);
+
+            // --- Previously in 'secure'
+            loadBooleanSetting(stmt, Settings.Global.PACKAGE_VERIFIER_ENABLE,
+                    R.bool.def_package_verifier_enable);
+
+            loadBooleanSetting(stmt, Settings.Global.WIFI_ON,
+                    R.bool.def_wifi_on);
+
+            loadBooleanSetting(stmt, Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
+                    R.bool.def_networks_available_notification_on);
+
+            loadBooleanSetting(stmt, Settings.Global.BLUETOOTH_ON,
+                    R.bool.def_bluetooth_on);
+
+            // Enable or disable Cell Broadcast SMS
+            loadSetting(stmt, Settings.Global.CDMA_CELL_BROADCAST_SMS,
+                    RILConstants.CDMA_CELL_BROADCAST_SMS_DISABLED);
+
+            // Data roaming default, based on build
+            loadSetting(stmt, Settings.Global.DATA_ROAMING,
+                    "true".equalsIgnoreCase(
+                            SystemProperties.get("ro.com.android.dataroaming",
+                                    "false")) ? 1 : 0);
+
+            loadBooleanSetting(stmt, Settings.Global.DEVICE_PROVISIONED,
+                    R.bool.def_device_provisioned);
+
+            final int maxBytes = mContext.getResources().getInteger(
+                    R.integer.def_download_manager_max_bytes_over_mobile);
+            if (maxBytes > 0) {
+                loadSetting(stmt, Settings.Global.DOWNLOAD_MAX_BYTES_OVER_MOBILE,
+                        Integer.toString(maxBytes));
+            }
+
+            final int recommendedMaxBytes = mContext.getResources().getInteger(
+                    R.integer.def_download_manager_recommended_max_bytes_over_mobile);
+            if (recommendedMaxBytes > 0) {
+                loadSetting(stmt, Settings.Global.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE,
+                        Integer.toString(recommendedMaxBytes));
+            }
+
+            // Mobile Data default, based on build
+            loadSetting(stmt, Settings.Global.MOBILE_DATA,
+                    "true".equalsIgnoreCase(
+                            SystemProperties.get("ro.com.android.mobiledata",
+                                    "true")) ? 1 : 0);
+
+            loadBooleanSetting(stmt, Settings.Global.NETSTATS_ENABLED,
+                    R.bool.def_netstats_enabled);
+
+            loadBooleanSetting(stmt, Settings.Global.INSTALL_NON_MARKET_APPS,
+                    R.bool.def_install_non_market_apps);
+
+            loadIntegerSetting(stmt, Settings.Global.NETWORK_PREFERENCE,
+                    R.integer.def_network_preference);
+
+            loadBooleanSetting(stmt, Settings.Global.USB_MASS_STORAGE_ENABLED,
+                    R.bool.def_usb_mass_storage_enabled);
+
+            loadIntegerSetting(stmt, Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
+                    R.integer.def_max_dhcp_retries);
+
+            loadBooleanSetting(stmt, Settings.Global.WIFI_DISPLAY_ON,
+                    R.bool.def_wifi_display_on);
+
+            loadStringSetting(stmt, Settings.Global.LOCK_SOUND,
+                    R.string.def_lock_sound);
+            loadStringSetting(stmt, Settings.Global.UNLOCK_SOUND,
+                    R.string.def_unlock_sound);
+            loadIntegerSetting(stmt, Settings.Global.POWER_SOUNDS_ENABLED,
+                    R.integer.def_power_sounds_enabled);
+            loadStringSetting(stmt, Settings.Global.LOW_BATTERY_SOUND,
+                    R.string.def_low_battery_sound);
+            loadIntegerSetting(stmt, Settings.Global.DOCK_SOUNDS_ENABLED,
+                    R.integer.def_dock_sounds_enabled);
+            loadStringSetting(stmt, Settings.Global.DESK_DOCK_SOUND,
+                    R.string.def_desk_dock_sound);
+            loadStringSetting(stmt, Settings.Global.DESK_UNDOCK_SOUND,
+                    R.string.def_desk_undock_sound);
+            loadStringSetting(stmt, Settings.Global.CAR_DOCK_SOUND,
+                    R.string.def_car_dock_sound);
+            loadStringSetting(stmt, Settings.Global.CAR_UNDOCK_SOUND,
+                    R.string.def_car_undock_sound);
+
+            loadSetting(stmt, Settings.Global.SET_INSTALL_LOCATION, 0);
+            loadSetting(stmt, Settings.Global.DEFAULT_INSTALL_LOCATION,
+                    PackageHelper.APP_INSTALL_AUTO);
+
+            // Set default cdma emergency tone
+            loadSetting(stmt, Settings.Global.EMERGENCY_TONE, 0);
+
+            // Set default cdma call auto retry
+            loadSetting(stmt, Settings.Global.CALL_AUTO_RETRY, 0);
+
+            // Set the preferred network mode to 0 = Global, CDMA default
+            int type;
+            if (TelephonyManager.getLteOnCdmaModeStatic() == PhoneConstants.LTE_ON_CDMA_TRUE) {
+                type = Phone.NT_MODE_GLOBAL;
+            } else {
+                type = SystemProperties.getInt("ro.telephony.default_network",
+                        RILConstants.PREFERRED_NETWORK_MODE);
+            }
+            loadSetting(stmt, Settings.Global.PREFERRED_NETWORK_MODE, type);
+
+            // --- New global settings start here
+        } finally {
+            if (stmt != null) stmt.close();
+        }
+    }
+
     private void loadSetting(SQLiteStatement stmt, String key, Object value) {
         stmt.bindString(1, key);
         stmt.bindString(2, value.toString());
@@ -1756,7 +2233,7 @@
     }
 
     private int getIntValueFromSystem(SQLiteDatabase db, String name, int defaultValue) {
-        return getIntValueFromTable(db, "system", name, defaultValue);
+        return getIntValueFromTable(db, TABLE_SYSTEM, name, defaultValue);
     }
 
     private int getIntValueFromTable(SQLiteDatabase db, String table, String name,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 0165977..0b85e70 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -26,6 +26,7 @@
 import android.net.Uri;
 import android.net.wifi.WifiManager;
 import android.os.FileUtils;
+import android.os.Handler;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.provider.Settings;
@@ -46,7 +47,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.io.Reader;
 import java.io.Writer;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -64,25 +64,35 @@
 
     private static final String KEY_SYSTEM = "system";
     private static final String KEY_SECURE = "secure";
+    private static final String KEY_GLOBAL = "global";
     private static final String KEY_LOCALE = "locale";
 
-    //Version 2 adds STATE_WIFI_CONFIG
-    private static final int STATE_VERSION_1       = 1;
-    private static final int STATE_VERSION_1_SIZE  = 4;
-
     // Versioning of the state file.  Increment this version
     // number any time the set of state items is altered.
-    private static final int STATE_VERSION = 2;
+    private static final int STATE_VERSION = 3;
 
+    // Slots in the checksum array.  Never insert new items in the middle
+    // of this array; new slots must be appended.
     private static final int STATE_SYSTEM          = 0;
     private static final int STATE_SECURE          = 1;
     private static final int STATE_LOCALE          = 2;
     private static final int STATE_WIFI_SUPPLICANT = 3;
     private static final int STATE_WIFI_CONFIG     = 4;
-    private static final int STATE_SIZE            = 5; // The number of state items
+    private static final int STATE_GLOBAL          = 5;
+
+    private static final int STATE_SIZE            = 6; // The current number of state items
+
+    // Number of entries in the checksum array at various version numbers
+    private static final int STATE_SIZES[] = {
+        0,
+        4,              // version 1
+        5,              // version 2 added STATE_WIFI_CONFIG
+        STATE_SIZE      // version 3 added STATE_GLOBAL
+    };
 
     // Versioning of the 'full backup' format
-    private static final int FULL_BACKUP_VERSION = 1;
+    private static final int FULL_BACKUP_VERSION = 2;
+    private static final int FULL_BACKUP_ADDED_GLOBAL = 2;  // added the "global" entry
 
     private static final int INTEGER_BYTE_COUNT = Integer.SIZE / Byte.SIZE;
 
@@ -112,10 +122,16 @@
     // stored in the full-backup tarfile as well, so should not be changed.
     private static final String STAGE_FILE = "flattened-data";
 
+    // Delay in milliseconds between the restore operation and when we will bounce
+    // wifi in order to rewrite the supplicant config etc.
+    private static final long WIFI_BOUNCE_DELAY_MILLIS = 60 * 1000; // one minute
+
     private SettingsHelper mSettingsHelper;
     private WifiManager mWfm;
     private static String mWifiConfigFile;
 
+    WifiRestoreRunnable mWifiRestore = null;
+
     // Class for capturing a network definition from the wifi supplicant config file
     static class Network {
         String ssid = "";  // equals() and hashCode() need these to be non-null
@@ -257,6 +273,7 @@
 
         byte[] systemSettingsData = getSystemSettings();
         byte[] secureSettingsData = getSecureSettings();
+        byte[] globalSettingsData = getGlobalSettings();
         byte[] locale = mSettingsHelper.getLocaleData();
         byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
         byte[] wifiConfigData = getFileData(mWifiConfigFile);
@@ -267,6 +284,8 @@
             writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data);
         stateChecksums[STATE_SECURE] =
             writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data);
+        stateChecksums[STATE_GLOBAL] =
+            writeIfChanged(stateChecksums[STATE_GLOBAL], KEY_GLOBAL, globalSettingsData, data);
         stateChecksums[STATE_LOCALE] =
             writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data);
         stateChecksums[STATE_WIFI_SUPPLICANT] =
@@ -279,44 +298,111 @@
         writeNewChecksums(stateChecksums, newState);
     }
 
+    class WifiRestoreRunnable implements Runnable {
+        private byte[] restoredSupplicantData;
+        private byte[] restoredWifiConfigFile;
+
+        void incorporateWifiSupplicant(BackupDataInput data) {
+            restoredSupplicantData = new byte[data.getDataSize()];
+            if (restoredSupplicantData.length <= 0) return;
+            try {
+                data.readEntityData(restoredSupplicantData, 0, data.getDataSize());
+            } catch (IOException e) {
+                Log.w(TAG, "Unable to read supplicant data");
+                restoredSupplicantData = null;
+            }
+        }
+
+        void incorporateWifiConfigFile(BackupDataInput data) {
+            restoredWifiConfigFile = new byte[data.getDataSize()];
+            if (restoredWifiConfigFile.length <= 0) return;
+            try {
+                data.readEntityData(restoredWifiConfigFile, 0, data.getDataSize());
+            } catch (IOException e) {
+                Log.w(TAG, "Unable to read config file");
+                restoredWifiConfigFile = null;
+            }
+        }
+
+        @Override
+        public void run() {
+            if (restoredSupplicantData != null || restoredWifiConfigFile != null) {
+                if (DEBUG_BACKUP) {
+                    Log.v(TAG, "Starting deferred restore of wifi data");
+                }
+                final int retainedWifiState = enableWifi(false);
+                if (restoredSupplicantData != null) {
+                    restoreWifiSupplicant(FILE_WIFI_SUPPLICANT,
+                            restoredSupplicantData, restoredSupplicantData.length);
+                    FileUtils.setPermissions(FILE_WIFI_SUPPLICANT,
+                            FileUtils.S_IRUSR | FileUtils.S_IWUSR |
+                            FileUtils.S_IRGRP | FileUtils.S_IWGRP,
+                            Process.myUid(), Process.WIFI_UID);
+                }
+                if (restoredWifiConfigFile != null) {
+                    restoreFileData(mWifiConfigFile,
+                            restoredWifiConfigFile, restoredWifiConfigFile.length);
+                }
+                // restore the previous WIFI state.
+                enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED ||
+                        retainedWifiState == WifiManager.WIFI_STATE_ENABLING);
+            }
+        }
+    }
+
+    // Instantiate the wifi-config restore runnable, scheduling it for execution
+    // a minute hence
+    void initWifiRestoreIfNecessary() {
+        if (mWifiRestore == null) {
+            mWifiRestore = new WifiRestoreRunnable();
+        }
+    }
+
     @Override
     public void onRestore(BackupDataInput data, int appVersionCode,
             ParcelFileDescriptor newState) throws IOException {
 
+        HashSet<String> movedToGlobal = new HashSet<String>();
+        Settings.System.getMovedKeys(movedToGlobal);
+        Settings.Secure.getMovedKeys(movedToGlobal);
+
         while (data.readNextHeader()) {
             final String key = data.getKey();
             final int size = data.getDataSize();
             if (KEY_SYSTEM.equals(key)) {
-                restoreSettings(data, Settings.System.CONTENT_URI);
+                restoreSettings(data, Settings.System.CONTENT_URI, movedToGlobal);
                 mSettingsHelper.applyAudioSettings();
             } else if (KEY_SECURE.equals(key)) {
-                restoreSettings(data, Settings.Secure.CONTENT_URI);
+                restoreSettings(data, Settings.Secure.CONTENT_URI, movedToGlobal);
+            } else if (KEY_GLOBAL.equals(key)) {
+                restoreSettings(data, Settings.Global.CONTENT_URI, null);
             } else if (KEY_WIFI_SUPPLICANT.equals(key)) {
-                int retainedWifiState = enableWifi(false);
-                restoreWifiSupplicant(FILE_WIFI_SUPPLICANT, data);
-                FileUtils.setPermissions(FILE_WIFI_SUPPLICANT,
-                        FileUtils.S_IRUSR | FileUtils.S_IWUSR |
-                        FileUtils.S_IRGRP | FileUtils.S_IWGRP,
-                        Process.myUid(), Process.WIFI_UID);
-                // retain the previous WIFI state.
-                enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED ||
-                        retainedWifiState == WifiManager.WIFI_STATE_ENABLING);
+                initWifiRestoreIfNecessary();
+                mWifiRestore.incorporateWifiSupplicant(data);
             } else if (KEY_LOCALE.equals(key)) {
                 byte[] localeData = new byte[size];
                 data.readEntityData(localeData, 0, size);
                 mSettingsHelper.setLocaleData(localeData, size);
             } else if (KEY_WIFI_CONFIG.equals(key)) {
-                restoreFileData(mWifiConfigFile, data);
+                initWifiRestoreIfNecessary();
+                mWifiRestore.incorporateWifiConfigFile(data);
              } else {
                 data.skipEntityData();
             }
         }
+
+        // If we have wifi data to restore, post a runnable to perform the
+        // bounce-and-update operation a little ways in the future.
+        if (mWifiRestore != null) {
+            new Handler(getMainLooper()).postDelayed(mWifiRestore, WIFI_BOUNCE_DELAY_MILLIS);
+        }
     }
 
     @Override
     public void onFullBackup(FullBackupDataOutput data)  throws IOException {
         byte[] systemSettingsData = getSystemSettings();
         byte[] secureSettingsData = getSecureSettings();
+        byte[] globalSettingsData = getGlobalSettings();
         byte[] locale = mSettingsHelper.getLocaleData();
         byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
         byte[] wifiConfigData = getFileData(mWifiConfigFile);
@@ -339,6 +425,9 @@
             if (DEBUG_BACKUP) Log.d(TAG, secureSettingsData.length + " bytes of secure settings data");
             out.writeInt(secureSettingsData.length);
             out.write(secureSettingsData);
+            if (DEBUG_BACKUP) Log.d(TAG, globalSettingsData.length + " bytes of global settings data");
+            out.writeInt(globalSettingsData.length);
+            out.write(globalSettingsData);
             if (DEBUG_BACKUP) Log.d(TAG, locale.length + " bytes of locale data");
             out.writeInt(locale.length);
             out.write(locale);
@@ -371,20 +460,35 @@
 
         int version = in.readInt();
         if (DEBUG_BACKUP) Log.d(TAG, "Flattened data version " + version);
-        if (version == FULL_BACKUP_VERSION) {
+        if (version <= FULL_BACKUP_VERSION) {
+            // Generate the moved-to-global lookup table
+            HashSet<String> movedToGlobal = new HashSet<String>();
+            Settings.System.getMovedKeys(movedToGlobal);
+            Settings.Secure.getMovedKeys(movedToGlobal);
+
             // system settings data first
             int nBytes = in.readInt();
             if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of settings data");
             byte[] buffer = new byte[nBytes];
             in.readFully(buffer, 0, nBytes);
-            restoreSettings(buffer, nBytes, Settings.System.CONTENT_URI);
+            restoreSettings(buffer, nBytes, Settings.System.CONTENT_URI, movedToGlobal);
 
             // secure settings
             nBytes = in.readInt();
             if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of secure settings data");
             if (nBytes > buffer.length) buffer = new byte[nBytes];
             in.readFully(buffer, 0, nBytes);
-            restoreSettings(buffer, nBytes, Settings.Secure.CONTENT_URI);
+            restoreSettings(buffer, nBytes, Settings.Secure.CONTENT_URI, movedToGlobal);
+
+            // Global only if sufficiently new
+            if (version >= FULL_BACKUP_ADDED_GLOBAL) {
+                nBytes = in.readInt();
+                if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of global settings data");
+                if (nBytes > buffer.length) buffer = new byte[nBytes];
+                in.readFully(buffer, 0, nBytes);
+                movedToGlobal.clear();  // no redirection; this *is* the global namespace
+                restoreSettings(buffer, nBytes, Settings.Global.CONTENT_URI, movedToGlobal);
+            }
 
             // locale
             nBytes = in.readInt();
@@ -430,14 +534,8 @@
 
         try {
             int stateVersion = dataInput.readInt();
-            if (stateVersion == STATE_VERSION_1) {
-                for (int i = 0; i < STATE_VERSION_1_SIZE; i++) {
-                    stateChecksums[i] = dataInput.readLong();
-                }
-            } else if (stateVersion == STATE_VERSION) {
-                for (int i = 0; i < STATE_SIZE; i++) {
-                    stateChecksums[i] = dataInput.readLong();
-                }
+            for (int i = 0; i < STATE_SIZES[stateVersion]; i++) {
+                stateChecksums[i] = dataInput.readLong();
             }
         } catch (EOFException eof) {
             // With the default 0 checksum we'll wind up forcing a backup of
@@ -496,7 +594,18 @@
         }
     }
 
-    private void restoreSettings(BackupDataInput data, Uri contentUri) {
+    private byte[] getGlobalSettings() {
+        Cursor cursor = getContentResolver().query(Settings.Global.CONTENT_URI, PROJECTION, null,
+                null, null);
+        try {
+            return extractRelevantValues(cursor, Settings.Global.SETTINGS_TO_BACKUP);
+        } finally {
+            cursor.close();
+        }
+    }
+
+    private void restoreSettings(BackupDataInput data, Uri contentUri,
+            HashSet<String> movedToGlobal) {
         byte[] settings = new byte[data.getDataSize()];
         try {
             data.readEntityData(settings, 0, settings.length);
@@ -504,20 +613,23 @@
             Log.e(TAG, "Couldn't read entity data");
             return;
         }
-        restoreSettings(settings, settings.length, contentUri);
+        restoreSettings(settings, settings.length, contentUri, movedToGlobal);
     }
 
-    private void restoreSettings(byte[] settings, int bytes, Uri contentUri) {
+    private void restoreSettings(byte[] settings, int bytes, Uri contentUri,
+            HashSet<String> movedToGlobal) {
         if (DEBUG) {
             Log.i(TAG, "restoreSettings: " + contentUri);
         }
 
-        // Figure out the white list.
+        // Figure out the white list and redirects to the global table.
         String[] whitelist = null;
         if (contentUri.equals(Settings.Secure.CONTENT_URI)) {
             whitelist = Settings.Secure.SETTINGS_TO_BACKUP;
         } else if (contentUri.equals(Settings.System.CONTENT_URI)) {
             whitelist = Settings.System.SETTINGS_TO_BACKUP;
+        } else if (contentUri.equals(Settings.Global.CONTENT_URI)) {
+            whitelist = Settings.Global.SETTINGS_TO_BACKUP;
         } else {
             throw new IllegalArgumentException("Unknown URI: " + contentUri);
         }
@@ -556,15 +668,20 @@
                 continue;
             }
 
+            final Uri destination = (movedToGlobal != null && movedToGlobal.contains(key))
+                    ? Settings.Global.CONTENT_URI
+                    : contentUri;
+
+            // The helper doesn't care what namespace the keys are in
             if (settingsHelper.restoreValue(key, value)) {
                 contentValues.clear();
                 contentValues.put(Settings.NameValueTable.NAME, key);
                 contentValues.put(Settings.NameValueTable.VALUE, value);
-                getContentResolver().insert(contentUri, contentValues);
+                getContentResolver().insert(destination, contentValues);
             }
 
             if (DEBUG) {
-                Log.d(TAG, "Restored setting: " + key + "=" + value);
+                Log.d(TAG, "Restored setting: " + destination + " : "+ key + "=" + value);
             }
         }
     }
@@ -675,17 +792,6 @@
 
     }
 
-    private void restoreFileData(String filename, BackupDataInput data) {
-        byte[] bytes = new byte[data.getDataSize()];
-        if (bytes.length <= 0) return;
-        try {
-            data.readEntityData(bytes, 0, data.getDataSize());
-            restoreFileData(filename, bytes, bytes.length);
-        } catch (IOException e) {
-            Log.w(TAG, "Unable to read file data for " + filename);
-        }
-    }
-
     private void restoreFileData(String filename, byte[] bytes, int size) {
         try {
             File file = new File(filename);
@@ -738,17 +844,6 @@
         }
     }
 
-    private void restoreWifiSupplicant(String filename, BackupDataInput data) {
-        byte[] bytes = new byte[data.getDataSize()];
-        if (bytes.length <= 0) return;
-        try {
-            data.readEntityData(bytes, 0, data.getDataSize());
-            restoreWifiSupplicant(filename, bytes, bytes.length);
-        } catch (IOException e) {
-            Log.w(TAG, "Unable to read supplicant data");
-        }
-    }
-
     private void restoreWifiSupplicant(String filename, byte[] bytes, int size) {
         try {
             WifiNetworkSettings supplicantImage = new WifiNetworkSettings();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 18e7faa..621e662 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -20,11 +20,8 @@
 
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
-import android.app.backup.BackupDataInput;
 import android.app.backup.IBackupManager;
-import android.content.ContentResolver;
 import android.content.Context;
-import android.content.IContentService;
 import android.content.res.Configuration;
 import android.location.LocationManager;
 import android.media.AudioManager;
@@ -33,23 +30,15 @@
 import android.os.ServiceManager;
 import android.provider.Settings;
 import android.text.TextUtils;
-import android.util.Log;
 
 public class SettingsHelper {
-    private static final String TAG = "SettingsHelper";
-
     private Context mContext;
     private AudioManager mAudioManager;
-    private IContentService mContentService;
-    private IPowerManager mPowerManager;
 
     public SettingsHelper(Context context) {
         mContext = context;
         mAudioManager = (AudioManager) context
                 .getSystemService(Context.AUDIO_SERVICE);
-        mContentService = ContentResolver.getContentService();
-        mPowerManager = IPowerManager.Stub.asInterface(
-                ServiceManager.getService("power"));
     }
 
     /**
@@ -71,10 +60,31 @@
             return false;
         } else if (Settings.Secure.BACKUP_AUTO_RESTORE.equals(name)) {
             setAutoRestore(Integer.parseInt(value) == 1);
+        } else if (isAlreadyConfiguredCriticalAccessibilitySetting(name)) {
+            return false;
         }
         return true;
     }
 
+    private boolean isAlreadyConfiguredCriticalAccessibilitySetting(String name) {
+        // These are the critical accessibility settings that are required for a
+        // blind user to be able to interact with the device. If these settings are
+        // already configured, we will not overwrite them. If they are already set,
+        // it means that the user has performed a global gesture to enable accessibility
+        // and definitely needs these features working after the restore.
+        if (Settings.Secure.ACCESSIBILITY_ENABLED.equals(name)
+                || Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION.equals(name)
+                || Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD.equals(name)
+                || Settings.Secure.TOUCH_EXPLORATION_ENABLED.equals(name)) {
+            return Settings.Secure.getInt(mContext.getContentResolver(), name, 0) != 0;
+        } else if (Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES.equals(name)
+                || Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(name)) {
+            return !TextUtils.isEmpty(Settings.Secure.getString(
+                    mContext.getContentResolver(), name));
+        }
+        return false;
+    }
+
     private void setAutoRestore(boolean enabled) {
         try {
             IBackupManager bm = IBackupManager.Stub.asInterface(
@@ -109,7 +119,7 @@
             IPowerManager power = IPowerManager.Stub.asInterface(
                     ServiceManager.getService("power"));
             if (power != null) {
-                power.setBacklightBrightness(brightness);
+                power.setTemporaryScreenBrightnessSettingOverride(brightness);
             }
         } catch (RemoteException doe) {
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 1fa3695..8086bbc 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -18,53 +18,74 @@
 
 import java.io.FileNotFoundException;
 import java.security.SecureRandom;
+import java.util.HashSet;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import android.app.ActivityManager;
 import android.app.backup.BackupManager;
+import android.content.BroadcastReceiver;
 import android.content.ContentProvider;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.res.AssetFileDescriptor;
+import android.database.AbstractCursor;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteException;
 import android.database.sqlite.SQLiteQueryBuilder;
 import android.media.RingtoneManager;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.FileObserver;
 import android.os.ParcelFileDescriptor;
 import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.DrmStore;
 import android.provider.MediaStore;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.LruCache;
+import android.util.Slog;
+import android.util.SparseArray;
 
 public class SettingsProvider extends ContentProvider {
     private static final String TAG = "SettingsProvider";
     private static final boolean LOCAL_LOGV = false;
 
+    private static final String TABLE_SYSTEM = "system";
+    private static final String TABLE_SECURE = "secure";
+    private static final String TABLE_GLOBAL = "global";
     private static final String TABLE_FAVORITES = "favorites";
     private static final String TABLE_OLD_FAVORITES = "old_favorites";
 
     private static final String[] COLUMN_VALUE = new String[] { "value" };
 
-    // Cache for settings, access-ordered for acting as LRU.
+    // Caches for each user's settings, access-ordered for acting as LRU.
     // Guarded by themselves.
     private static final int MAX_CACHE_ENTRIES = 200;
-    private static final SettingsCache sSystemCache = new SettingsCache("system");
-    private static final SettingsCache sSecureCache = new SettingsCache("secure");
+    private static final SparseArray<SettingsCache> sSystemCaches
+            = new SparseArray<SettingsCache>();
+    private static final SparseArray<SettingsCache> sSecureCaches
+            = new SparseArray<SettingsCache>();
+    private static final SettingsCache sGlobalCache = new SettingsCache(TABLE_GLOBAL);
 
     // The count of how many known (handled by SettingsProvider)
-    // database mutations are currently being handled.  Used by
-    // sFileObserver to not reload the database when it's ourselves
+    // database mutations are currently being handled for this user.
+    // Used by file observers to not reload the database when it's ourselves
     // modifying it.
-    private static final AtomicInteger sKnownMutationsInFlight = new AtomicInteger(0);
+    private static final SparseArray<AtomicInteger> sKnownMutationsInFlight
+            = new SparseArray<AtomicInteger>();
+
+    // Each defined user has their own settings
+    protected final SparseArray<DatabaseHelper> mOpenHelpers = new SparseArray<DatabaseHelper>();
 
     // Over this size we don't reject loading or saving settings but
     // we do consider them broken/malicious and don't keep them in
@@ -77,10 +98,32 @@
     // want to cache the existence of a key, but not store its value.
     private static final Bundle TOO_LARGE_TO_CACHE_MARKER = Bundle.forPair("_dummy", null);
 
-    protected DatabaseHelper mOpenHelper;
+    private UserManager mUserManager;
     private BackupManager mBackupManager;
 
     /**
+     * Settings which need to be treated as global/shared in multi-user environments.
+     */
+    static final HashSet<String> sSecureGlobalKeys;
+    static final HashSet<String> sSystemGlobalKeys;
+    static {
+        // Keys (name column) from the 'secure' table that are now in the owner user's 'global'
+        // table, shared across all users
+        // These must match Settings.Secure.MOVED_TO_GLOBAL
+        sSecureGlobalKeys = new HashSet<String>();
+        Settings.Secure.getMovedKeys(sSecureGlobalKeys);
+
+        // Keys from the 'system' table now moved to 'global'
+        // These must match Settings.System.MOVED_TO_GLOBAL
+        sSystemGlobalKeys = new HashSet<String>();
+        Settings.System.getNonLegacyMovedKeys(sSystemGlobalKeys);
+    }
+
+    private boolean settingMovedToGlobal(final String name) {
+        return sSecureGlobalKeys.contains(name) || sSystemGlobalKeys.contains(name);
+    }
+
+    /**
      * Decode a content URL into the table, projection, and arguments
      * used to access the corresponding database rows.
      */
@@ -92,6 +135,7 @@
         /** Operate on existing rows. */
         SqlArguments(Uri url, String where, String[] args) {
             if (url.getPathSegments().size() == 1) {
+                // of the form content://settings/secure, arbitrary where clause
                 this.table = url.getPathSegments().get(0);
                 if (!DatabaseHelper.isValidTable(this.table)) {
                     throw new IllegalArgumentException("Bad root path: " + this.table);
@@ -103,14 +147,24 @@
             } else if (!TextUtils.isEmpty(where)) {
                 throw new UnsupportedOperationException("WHERE clause not supported: " + url);
             } else {
+                // of the form content://settings/secure/element_name, no where clause
                 this.table = url.getPathSegments().get(0);
                 if (!DatabaseHelper.isValidTable(this.table)) {
                     throw new IllegalArgumentException("Bad root path: " + this.table);
                 }
-                if ("system".equals(this.table) || "secure".equals(this.table)) {
+                if (TABLE_SYSTEM.equals(this.table) || TABLE_SECURE.equals(this.table) ||
+                    TABLE_GLOBAL.equals(this.table)) {
                     this.where = Settings.NameValueTable.NAME + "=?";
-                    this.args = new String[] { url.getPathSegments().get(1) };
+                    final String name = url.getPathSegments().get(1);
+                    this.args = new String[] { name };
+                    // Rewrite the table for known-migrated names
+                    if (TABLE_SYSTEM.equals(this.table) || TABLE_SECURE.equals(this.table)) {
+                        if (sSecureGlobalKeys.contains(name) || sSystemGlobalKeys.contains(name)) {
+                            this.table = TABLE_GLOBAL;
+                        }
+                    }
                 } else {
+                    // of the form content://bookmarks/19
                     this.where = "_id=" + ContentUris.parseId(url);
                     this.args = null;
                 }
@@ -144,7 +198,9 @@
             throw new IllegalArgumentException("Invalid URI: " + tableUri);
         }
         String table = tableUri.getPathSegments().get(0);
-        if ("system".equals(table) || "secure".equals(table)) {
+        if (TABLE_SYSTEM.equals(table) ||
+                TABLE_SECURE.equals(table) ||
+                TABLE_GLOBAL.equals(table)) {
             String name = values.getAsString(Settings.NameValueTable.NAME);
             return Uri.withAppendedPath(tableUri, name);
         } else {
@@ -159,19 +215,23 @@
      * contract class uses these to provide client-side caches.)
      * @param uri to send notifications for
      */
-    private void sendNotify(Uri uri) {
+    private void sendNotify(Uri uri, int userHandle) {
         // Update the system property *first*, so if someone is listening for
         // a notification and then using the contract class to get their data,
         // the system property will be updated and they'll get the new data.
 
         boolean backedUpDataChanged = false;
         String property = null, table = uri.getPathSegments().get(0);
-        if (table.equals("system")) {
+        final boolean isGlobal = table.equals(TABLE_GLOBAL);
+        if (table.equals(TABLE_SYSTEM)) {
             property = Settings.System.SYS_PROP_SETTING_VERSION;
             backedUpDataChanged = true;
-        } else if (table.equals("secure")) {
+        } else if (table.equals(TABLE_SECURE)) {
             property = Settings.Secure.SYS_PROP_SETTING_VERSION;
             backedUpDataChanged = true;
+        } else if (isGlobal) {
+            property = Settings.Global.SYS_PROP_SETTING_VERSION;    // this one is global
+            backedUpDataChanged = true;
         }
 
         if (property != null) {
@@ -188,8 +248,14 @@
 
         String notify = uri.getQueryParameter("notify");
         if (notify == null || "true".equals(notify)) {
-            getContext().getContentResolver().notifyChange(uri, null);
-            if (LOCAL_LOGV) Log.v(TAG, "notifying: " + uri);
+            final int notifyTarget = isGlobal ? UserHandle.USER_ALL : userHandle;
+            final long oldId = Binder.clearCallingIdentity();
+            try {
+                getContext().getContentResolver().notifyChange(uri, null, true, notifyTarget);
+            } finally {
+                Binder.restoreCallingIdentity(oldId);
+            }
+            if (LOCAL_LOGV) Log.v(TAG, "notifying for " + notifyTarget + ": " + uri);
         } else {
             if (LOCAL_LOGV) Log.v(TAG, "notification suppressed: " + uri);
         }
@@ -201,7 +267,7 @@
      * @throws SecurityException if the caller is forbidden to write.
      */
     private void checkWritePermissions(SqlArguments args) {
-        if ("secure".equals(args.table) &&
+        if ((TABLE_SECURE.equals(args.table) || TABLE_GLOBAL.equals(args.table)) &&
             getContext().checkCallingOrSelfPermission(
                     android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
             PackageManager.PERMISSION_GRANTED) {
@@ -218,70 +284,155 @@
     // normally the exclusive owner of the database.  But we keep this
     // enabled all the time to minimize development-vs-user
     // differences in testing.
-    private static SettingsFileObserver sObserverInstance;
+    private static SparseArray<SettingsFileObserver> sObserverInstances
+            = new SparseArray<SettingsFileObserver>();
     private class SettingsFileObserver extends FileObserver {
         private final AtomicBoolean mIsDirty = new AtomicBoolean(false);
+        private final int mUserHandle;
         private final String mPath;
 
-        public SettingsFileObserver(String path) {
+        public SettingsFileObserver(int userHandle, String path) {
             super(path, FileObserver.CLOSE_WRITE |
                   FileObserver.CREATE | FileObserver.DELETE |
                   FileObserver.MOVED_TO | FileObserver.MODIFY);
+            mUserHandle = userHandle;
             mPath = path;
         }
 
         public void onEvent(int event, String path) {
-            int modsInFlight = sKnownMutationsInFlight.get();
+            int modsInFlight = sKnownMutationsInFlight.get(mUserHandle).get();
             if (modsInFlight > 0) {
                 // our own modification.
                 return;
             }
-            Log.d(TAG, "external modification to " + mPath + "; event=" + event);
+            Log.d(TAG, "User " + mUserHandle + " external modification to " + mPath
+                    + "; event=" + event);
             if (!mIsDirty.compareAndSet(false, true)) {
                 // already handled. (we get a few update events
                 // during an sqlite write)
                 return;
             }
-            Log.d(TAG, "updating our caches for " + mPath);
-            fullyPopulateCaches();
+            Log.d(TAG, "User " + mUserHandle + " updating our caches for " + mPath);
+            fullyPopulateCaches(mUserHandle);
             mIsDirty.set(false);
         }
     }
 
     @Override
     public boolean onCreate() {
-        mOpenHelper = new DatabaseHelper(getContext());
         mBackupManager = new BackupManager(getContext());
+        mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
 
-        if (!ensureAndroidIdIsSet()) {
-            return false;
-        }
+        establishDbTracking(UserHandle.USER_OWNER);
 
-        // Watch for external modifications to the database file,
-        // keeping our cache in sync.
-        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
-        sObserverInstance = new SettingsFileObserver(db.getPath());
-        sObserverInstance.startWatching();
-        startAsyncCachePopulation();
+        IntentFilter userFilter = new IntentFilter();
+        userFilter.addAction(Intent.ACTION_USER_REMOVED);
+        getContext().registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (intent.getAction().equals(Intent.ACTION_USER_REMOVED)) {
+                    final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+                            UserHandle.USER_OWNER);
+                    if (userHandle != UserHandle.USER_OWNER) {
+                        onUserRemoved(userHandle);
+                    }
+                }
+            }
+        }, userFilter);
         return true;
     }
 
-    private void startAsyncCachePopulation() {
-        new Thread("populate-settings-caches") {
-            public void run() {
-                fullyPopulateCaches();
+    void onUserRemoved(int userHandle) {
+        synchronized (this) {
+            // the db file itself will be deleted automatically, but we need to tear down
+            // our caches and other internal bookkeeping.
+            FileObserver observer = sObserverInstances.get(userHandle);
+            if (observer != null) {
+                observer.stopWatching();
+                sObserverInstances.delete(userHandle);
             }
-        }.start();
+
+            mOpenHelpers.delete(userHandle);
+            sSystemCaches.delete(userHandle);
+            sSecureCaches.delete(userHandle);
+            sKnownMutationsInFlight.delete(userHandle);
+        }
     }
 
-    private void fullyPopulateCaches() {
-        fullyPopulateCache("secure", sSecureCache);
-        fullyPopulateCache("system", sSystemCache);
+    private void establishDbTracking(int userHandle) {
+        if (LOCAL_LOGV) {
+            Slog.i(TAG, "Installing settings db helper and caches for user " + userHandle);
+        }
+
+        DatabaseHelper dbhelper;
+
+        synchronized (this) {
+            dbhelper = mOpenHelpers.get(userHandle);
+            if (dbhelper == null) {
+                dbhelper = new DatabaseHelper(getContext(), userHandle);
+                mOpenHelpers.append(userHandle, dbhelper);
+
+                sSystemCaches.append(userHandle, new SettingsCache(TABLE_SYSTEM));
+                sSecureCaches.append(userHandle, new SettingsCache(TABLE_SECURE));
+                sKnownMutationsInFlight.append(userHandle, new AtomicInteger(0));
+            }
+        }
+
+        // Initialization of the db *outside* the locks.  It's possible that racing
+        // threads might wind up here, the second having read the cache entries
+        // written by the first, but that's benign: the SQLite helper implementation
+        // manages concurrency itself, and it's important that we not run the db
+        // initialization with any of our own locks held, so we're fine.
+        SQLiteDatabase db = dbhelper.getWritableDatabase();
+
+        // Watch for external modifications to the database files,
+        // keeping our caches in sync.  We synchronize the observer set
+        // separately, and of course it has to run after the db file
+        // itself was set up by the DatabaseHelper.
+        synchronized (sObserverInstances) {
+            if (sObserverInstances.get(userHandle) == null) {
+                SettingsFileObserver observer = new SettingsFileObserver(userHandle, db.getPath());
+                sObserverInstances.append(userHandle, observer);
+                observer.startWatching();
+            }
+        }
+
+        ensureAndroidIdIsSet(userHandle);
+
+        startAsyncCachePopulation(userHandle);
+    }
+
+    class CachePrefetchThread extends Thread {
+        private int mUserHandle;
+
+        CachePrefetchThread(int userHandle) {
+            super("populate-settings-caches");
+            mUserHandle = userHandle;
+        }
+
+        @Override
+        public void run() {
+            fullyPopulateCaches(mUserHandle);
+        }
+    }
+
+    private void startAsyncCachePopulation(int userHandle) {
+        new CachePrefetchThread(userHandle).start();
+    }
+
+    private void fullyPopulateCaches(final int userHandle) {
+        DatabaseHelper dbHelper = mOpenHelpers.get(userHandle);
+        // Only populate the globals cache once, for the owning user
+        if (userHandle == UserHandle.USER_OWNER) {
+            fullyPopulateCache(dbHelper, TABLE_GLOBAL, sGlobalCache);
+        }
+        fullyPopulateCache(dbHelper, TABLE_SECURE, sSecureCaches.get(userHandle));
+        fullyPopulateCache(dbHelper, TABLE_SYSTEM, sSystemCaches.get(userHandle));
     }
 
     // Slurp all values (if sane in number & size) into cache.
-    private void fullyPopulateCache(String table, SettingsCache cache) {
-        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+    private void fullyPopulateCache(DatabaseHelper dbHelper, String table, SettingsCache cache) {
+        SQLiteDatabase db = dbHelper.getReadableDatabase();
         Cursor c = db.query(
             table,
             new String[] { Settings.NameValueTable.NAME, Settings.NameValueTable.VALUE },
@@ -312,24 +463,27 @@
         }
     }
 
-    private boolean ensureAndroidIdIsSet() {
-        final Cursor c = query(Settings.Secure.CONTENT_URI,
+    private boolean ensureAndroidIdIsSet(int userHandle) {
+        final Cursor c = queryForUser(Settings.Secure.CONTENT_URI,
                 new String[] { Settings.NameValueTable.VALUE },
                 Settings.NameValueTable.NAME + "=?",
-                new String[] { Settings.Secure.ANDROID_ID }, null);
+                new String[] { Settings.Secure.ANDROID_ID }, null,
+                userHandle);
         try {
             final String value = c.moveToNext() ? c.getString(0) : null;
             if (value == null) {
                 final SecureRandom random = new SecureRandom();
                 final String newAndroidIdValue = Long.toHexString(random.nextLong());
-                Log.d(TAG, "Generated and saved new ANDROID_ID [" + newAndroidIdValue + "]");
                 final ContentValues values = new ContentValues();
                 values.put(Settings.NameValueTable.NAME, Settings.Secure.ANDROID_ID);
                 values.put(Settings.NameValueTable.VALUE, newAndroidIdValue);
-                final Uri uri = insert(Settings.Secure.CONTENT_URI, values);
+                final Uri uri = insertForUser(Settings.Secure.CONTENT_URI, values, userHandle);
                 if (uri == null) {
+                    Slog.e(TAG, "Unable to generate new ANDROID_ID for user " + userHandle);
                     return false;
                 }
+                Slog.d(TAG, "Generated and saved new ANDROID_ID [" + newAndroidIdValue
+                        + "] for user " + userHandle);
             }
             return true;
         } finally {
@@ -337,23 +491,130 @@
         }
     }
 
+    // Lazy-initialize the settings caches for non-primary users
+    private SettingsCache getOrConstructCache(int callingUser, SparseArray<SettingsCache> which) {
+        getOrEstablishDatabase(callingUser); // ignore return value; we don't need it
+        return which.get(callingUser);
+    }
+
+    // Lazy initialize the database helper and caches for this user, if necessary
+    private DatabaseHelper getOrEstablishDatabase(int callingUser) {
+        long oldId = Binder.clearCallingIdentity();
+        try {
+            DatabaseHelper dbHelper = mOpenHelpers.get(callingUser);
+            if (null == dbHelper) {
+                establishDbTracking(callingUser);
+                dbHelper = mOpenHelpers.get(callingUser);
+            }
+            return dbHelper;
+        } finally {
+            Binder.restoreCallingIdentity(oldId);
+        }
+    }
+
+    public SettingsCache cacheForTable(final int callingUser, String tableName) {
+        if (TABLE_SYSTEM.equals(tableName)) {
+            return getOrConstructCache(callingUser, sSystemCaches);
+        }
+        if (TABLE_SECURE.equals(tableName)) {
+            return getOrConstructCache(callingUser, sSecureCaches);
+        }
+        if (TABLE_GLOBAL.equals(tableName)) {
+            return sGlobalCache;
+        }
+        return null;
+    }
+
+    /**
+     * Used for wiping a whole cache on deletes when we're not
+     * sure what exactly was deleted or changed.
+     */
+    public void invalidateCache(final int callingUser, String tableName) {
+        SettingsCache cache = cacheForTable(callingUser, tableName);
+        if (cache == null) {
+            return;
+        }
+        synchronized (cache) {
+            cache.evictAll();
+            cache.mCacheFullyMatchesDisk = false;
+        }
+    }
+
     /**
      * Fast path that avoids the use of chatty remoted Cursors.
      */
     @Override
     public Bundle call(String method, String request, Bundle args) {
+        int callingUser = UserHandle.getCallingUserId();
+        if (args != null) {
+            int reqUser = args.getInt(Settings.CALL_METHOD_USER_KEY, callingUser);
+            if (reqUser != callingUser) {
+                callingUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+                        Binder.getCallingUid(), reqUser, false, true,
+                        "get/set setting for user", null);
+                if (LOCAL_LOGV) Slog.v(TAG, "   access setting for user " + callingUser);
+            }
+        }
+
+        // Note: we assume that get/put operations for moved-to-global names have already
+        // been directed to the new location on the caller side (otherwise we'd fix them
+        // up here).
+        DatabaseHelper dbHelper;
+        SettingsCache cache;
+
+        // Get methods
         if (Settings.CALL_METHOD_GET_SYSTEM.equals(method)) {
-            return lookupValue("system", sSystemCache, request);
+            if (LOCAL_LOGV) Slog.v(TAG, "call(system:" + request + ") for " + callingUser);
+            dbHelper = getOrEstablishDatabase(callingUser);
+            cache = sSystemCaches.get(callingUser);
+            return lookupValue(dbHelper, TABLE_SYSTEM, cache, request);
         }
         if (Settings.CALL_METHOD_GET_SECURE.equals(method)) {
-            return lookupValue("secure", sSecureCache, request);
+            if (LOCAL_LOGV) Slog.v(TAG, "call(secure:" + request + ") for " + callingUser);
+            dbHelper = getOrEstablishDatabase(callingUser);
+            cache = sSecureCaches.get(callingUser);
+            return lookupValue(dbHelper, TABLE_SECURE, cache, request);
         }
+        if (Settings.CALL_METHOD_GET_GLOBAL.equals(method)) {
+            if (LOCAL_LOGV) Slog.v(TAG, "call(global:" + request + ") for " + callingUser);
+            // fast path: owner db & cache are immutable after onCreate() so we need not
+            // guard on the attempt to look them up
+            return lookupValue(getOrEstablishDatabase(UserHandle.USER_OWNER), TABLE_GLOBAL,
+                    sGlobalCache, request);
+        }
+
+        // Put methods - new value is in the args bundle under the key named by
+        // the Settings.NameValueTable.VALUE static.
+        final String newValue = (args == null)
+        ? null : args.getString(Settings.NameValueTable.VALUE);
+
+        final ContentValues values = new ContentValues();
+        values.put(Settings.NameValueTable.NAME, request);
+        values.put(Settings.NameValueTable.VALUE, newValue);
+        if (Settings.CALL_METHOD_PUT_SYSTEM.equals(method)) {
+            if (LOCAL_LOGV) Slog.v(TAG, "call_put(system:" + request + "=" + newValue + ") for " + callingUser);
+            insertForUser(Settings.System.CONTENT_URI, values, callingUser);
+        } else if (Settings.CALL_METHOD_PUT_SECURE.equals(method)) {
+            if (LOCAL_LOGV) Slog.v(TAG, "call_put(secure:" + request + "=" + newValue + ") for " + callingUser);
+            insertForUser(Settings.Secure.CONTENT_URI, values, callingUser);
+        } else if (Settings.CALL_METHOD_PUT_GLOBAL.equals(method)) {
+            if (LOCAL_LOGV) Slog.v(TAG, "call_put(global:" + request + "=" + newValue + ") for " + callingUser);
+            insertForUser(Settings.Global.CONTENT_URI, values, callingUser);
+        } else {
+            Slog.w(TAG, "call() with invalid method: " + method);
+        }
+
         return null;
     }
 
     // Looks up value 'key' in 'table' and returns either a single-pair Bundle,
     // possibly with a null value, or null on failure.
-    private Bundle lookupValue(String table, SettingsCache cache, String key) {
+    private Bundle lookupValue(DatabaseHelper dbHelper, String table,
+            final SettingsCache cache, String key) {
+        if (cache == null) {
+           Slog.e(TAG, "cache is null for user " + UserHandle.getCallingUserId() + " : key=" + key);
+           return null;
+        }
         synchronized (cache) {
             Bundle value = cache.get(key);
             if (value != null) {
@@ -372,7 +633,7 @@
             }
         }
 
-        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+        SQLiteDatabase db = dbHelper.getReadableDatabase();
         Cursor cursor = null;
         try {
             cursor = db.query(table, COLUMN_VALUE, "name=?", new String[]{key},
@@ -393,8 +654,17 @@
 
     @Override
     public Cursor query(Uri url, String[] select, String where, String[] whereArgs, String sort) {
+        return queryForUser(url, select, where, whereArgs, sort, UserHandle.getCallingUserId());
+    }
+
+    private Cursor queryForUser(Uri url, String[] select, String where, String[] whereArgs,
+            String sort, int forUser) {
+        if (LOCAL_LOGV) Slog.v(TAG, "query(" + url + ") for user " + forUser);
         SqlArguments args = new SqlArguments(url, where, whereArgs);
-        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+        DatabaseHelper dbH;
+        dbH = getOrEstablishDatabase(
+                TABLE_GLOBAL.equals(args.table) ? UserHandle.USER_OWNER : forUser);
+        SQLiteDatabase db = dbH.getReadableDatabase();
 
         // The favorites table was moved from this provider to a provider inside Home
         // Home still need to query this table to upgrade from pre-cupcake builds
@@ -419,7 +689,16 @@
         qb.setTables(args.table);
 
         Cursor ret = qb.query(db, select, args.where, args.args, null, null, sort);
-        ret.setNotificationUri(getContext().getContentResolver(), url);
+        // the default Cursor interface does not support per-user observation
+        try {
+            AbstractCursor c = (AbstractCursor) ret;
+            c.setNotificationUri(getContext().getContentResolver(), url, forUser);
+        } catch (ClassCastException e) {
+            // details of the concrete Cursor implementation have changed and this code has
+            // not been updated to match -- complain and fail hard.
+            Log.wtf(TAG, "Incompatible cursor derivation!");
+            throw e;
+        }
         return ret;
     }
 
@@ -437,15 +716,20 @@
 
     @Override
     public int bulkInsert(Uri uri, ContentValues[] values) {
+        final int callingUser = UserHandle.getCallingUserId();
+        if (LOCAL_LOGV) Slog.v(TAG, "bulkInsert() for user " + callingUser);
         SqlArguments args = new SqlArguments(uri);
         if (TABLE_FAVORITES.equals(args.table)) {
             return 0;
         }
         checkWritePermissions(args);
-        SettingsCache cache = SettingsCache.forTable(args.table);
+        SettingsCache cache = cacheForTable(callingUser, args.table);
 
-        sKnownMutationsInFlight.incrementAndGet();
-        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        final AtomicInteger mutationCount = sKnownMutationsInFlight.get(callingUser);
+        mutationCount.incrementAndGet();
+        DatabaseHelper dbH = getOrEstablishDatabase(
+                TABLE_GLOBAL.equals(args.table) ? UserHandle.USER_OWNER : callingUser);
+        SQLiteDatabase db = dbH.getWritableDatabase();
         db.beginTransaction();
         try {
             int numValues = values.length;
@@ -457,10 +741,10 @@
             db.setTransactionSuccessful();
         } finally {
             db.endTransaction();
-            sKnownMutationsInFlight.decrementAndGet();
+            mutationCount.decrementAndGet();
         }
 
-        sendNotify(uri);
+        sendNotify(uri, callingUser);
         return values.length;
     }
 
@@ -538,11 +822,26 @@
 
     @Override
     public Uri insert(Uri url, ContentValues initialValues) {
+        return insertForUser(url, initialValues, UserHandle.getCallingUserId());
+    }
+
+    // Settings.put*ForUser() always winds up here, so this is where we apply
+    // policy around permission to write settings for other users.
+    private Uri insertForUser(Uri url, ContentValues initialValues, int desiredUserHandle) {
+        final int callingUser = UserHandle.getCallingUserId();
+        if (callingUser != desiredUserHandle) {
+            getContext().enforceCallingOrSelfPermission(
+                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    "Not permitted to access settings for other users");
+        }
+
+        if (LOCAL_LOGV) Slog.v(TAG, "insert(" + url + ") for user " + desiredUserHandle
+                + " by " + callingUser);
+
         SqlArguments args = new SqlArguments(url);
         if (TABLE_FAVORITES.equals(args.table)) {
             return null;
         }
-        checkWritePermissions(args);
 
         // Special case LOCATION_PROVIDERS_ALLOWED.
         // Support enabling/disabling a single provider (using "+" or "-" prefix)
@@ -551,66 +850,106 @@
             if (!parseProviderList(url, initialValues)) return null;
         }
 
-        SettingsCache cache = SettingsCache.forTable(args.table);
+        // If this is an insert() of a key that has been migrated to the global store,
+        // redirect the operation to that store
+        if (name != null) {
+            if (sSecureGlobalKeys.contains(name) || sSystemGlobalKeys.contains(name)) {
+                if (!TABLE_GLOBAL.equals(args.table)) {
+                    if (LOCAL_LOGV) Slog.i(TAG, "Rewrite of insert() of now-global key " + name);
+                }
+                args.table = TABLE_GLOBAL;  // next condition will rewrite the user handle
+            }
+        }
+
+        // Check write permissions only after determining which table the insert will touch
+        checkWritePermissions(args);
+
+        // The global table is stored under the owner, always
+        if (TABLE_GLOBAL.equals(args.table)) {
+            desiredUserHandle = UserHandle.USER_OWNER;
+        }
+
+        SettingsCache cache = cacheForTable(desiredUserHandle, args.table);
         String value = initialValues.getAsString(Settings.NameValueTable.VALUE);
         if (SettingsCache.isRedundantSetValue(cache, name, value)) {
             return Uri.withAppendedPath(url, name);
         }
 
-        sKnownMutationsInFlight.incrementAndGet();
-        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        final AtomicInteger mutationCount = sKnownMutationsInFlight.get(desiredUserHandle);
+        mutationCount.incrementAndGet();
+        DatabaseHelper dbH = getOrEstablishDatabase(desiredUserHandle);
+        SQLiteDatabase db = dbH.getWritableDatabase();
         final long rowId = db.insert(args.table, null, initialValues);
-        sKnownMutationsInFlight.decrementAndGet();
+        mutationCount.decrementAndGet();
         if (rowId <= 0) return null;
 
         SettingsCache.populate(cache, initialValues);  // before we notify
 
-        if (LOCAL_LOGV) Log.v(TAG, args.table + " <- " + initialValues);
+        if (LOCAL_LOGV) Log.v(TAG, args.table + " <- " + initialValues
+                + " for user " + desiredUserHandle);
+        // Note that we use the original url here, not the potentially-rewritten table name
         url = getUriFor(url, initialValues, rowId);
-        sendNotify(url);
+        sendNotify(url, desiredUserHandle);
         return url;
     }
 
     @Override
     public int delete(Uri url, String where, String[] whereArgs) {
+        int callingUser = UserHandle.getCallingUserId();
+        if (LOCAL_LOGV) Slog.v(TAG, "delete() for user " + callingUser);
         SqlArguments args = new SqlArguments(url, where, whereArgs);
         if (TABLE_FAVORITES.equals(args.table)) {
             return 0;
         } else if (TABLE_OLD_FAVORITES.equals(args.table)) {
             args.table = TABLE_FAVORITES;
+        } else if (TABLE_GLOBAL.equals(args.table)) {
+            callingUser = UserHandle.USER_OWNER;
         }
         checkWritePermissions(args);
 
-        sKnownMutationsInFlight.incrementAndGet();
-        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        final AtomicInteger mutationCount = sKnownMutationsInFlight.get(callingUser);
+        mutationCount.incrementAndGet();
+        DatabaseHelper dbH = getOrEstablishDatabase(callingUser);
+        SQLiteDatabase db = dbH.getWritableDatabase();
         int count = db.delete(args.table, args.where, args.args);
-        sKnownMutationsInFlight.decrementAndGet();
+        mutationCount.decrementAndGet();
         if (count > 0) {
-            SettingsCache.invalidate(args.table);  // before we notify
-            sendNotify(url);
+            invalidateCache(callingUser, args.table);  // before we notify
+            sendNotify(url, callingUser);
         }
-        startAsyncCachePopulation();
+        startAsyncCachePopulation(callingUser);
         if (LOCAL_LOGV) Log.v(TAG, args.table + ": " + count + " row(s) deleted");
         return count;
     }
 
     @Override
     public int update(Uri url, ContentValues initialValues, String where, String[] whereArgs) {
+        // NOTE: update() is never called by the front-end Settings API, and updates that
+        // wind up affecting rows in Secure that are globally shared will not have the
+        // intended effect (the update will be invisible to the rest of the system).
+        // This should have no practical effect, since writes to the Secure db can only
+        // be done by system code, and that code should be using the correct API up front.
+        int callingUser = UserHandle.getCallingUserId();
+        if (LOCAL_LOGV) Slog.v(TAG, "update() for user " + callingUser);
         SqlArguments args = new SqlArguments(url, where, whereArgs);
         if (TABLE_FAVORITES.equals(args.table)) {
             return 0;
+        } else if (TABLE_GLOBAL.equals(args.table)) {
+            callingUser = UserHandle.USER_OWNER;
         }
         checkWritePermissions(args);
 
-        sKnownMutationsInFlight.incrementAndGet();
-        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        final AtomicInteger mutationCount = sKnownMutationsInFlight.get(callingUser);
+        mutationCount.incrementAndGet();
+        DatabaseHelper dbH = getOrEstablishDatabase(callingUser);
+        SQLiteDatabase db = dbH.getWritableDatabase();
         int count = db.update(args.table, initialValues, args.where, args.args);
-        sKnownMutationsInFlight.decrementAndGet();
+        mutationCount.decrementAndGet();
         if (count > 0) {
-            SettingsCache.invalidate(args.table);  // before we notify
-            sendNotify(url);
+            invalidateCache(callingUser, args.table);  // before we notify
+            sendNotify(url, callingUser);
         }
-        startAsyncCachePopulation();
+        startAsyncCachePopulation(callingUser);
         if (LOCAL_LOGV) Log.v(TAG, args.table + ": " + count + " row(s) <- " + initialValues);
         return count;
     }
@@ -772,16 +1111,6 @@
             return bundle;
         }
 
-        public static SettingsCache forTable(String tableName) {
-            if ("system".equals(tableName)) {
-                return SettingsProvider.sSystemCache;
-            }
-            if ("secure".equals(tableName)) {
-                return SettingsProvider.sSecureCache;
-            }
-            return null;
-        }
-
         /**
          * Populates a key in a given (possibly-null) cache.
          */
@@ -809,21 +1138,6 @@
         }
 
         /**
-         * Used for wiping a whole cache on deletes when we're not
-         * sure what exactly was deleted or changed.
-         */
-        public static void invalidate(String tableName) {
-            SettingsCache cache = SettingsCache.forTable(tableName);
-            if (cache == null) {
-                return;
-            }
-            synchronized (cache) {
-                cache.evictAll();
-                cache.mCacheFullyMatchesDisk = false;
-            }
-        }
-
-        /**
          * For suppressing duplicate/redundant settings inserts early,
          * checking our cache first (but without faulting it in),
          * before going to sqlite with the mutation.
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 10849f6..cfe70dc 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -1,10 +1,12 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
         package="com.android.systemui"
         coreApp="true">
 
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.ACCESS_ALL_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
 
     <uses-permission android:name="android.permission.INJECT_EVENTS" />
@@ -15,6 +17,12 @@
     <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
     <uses-permission android:name="android.permission.REMOTE_AUDIO_PLAYBACK" />
 
+    <uses-permission android:name="android.permission.MANAGE_USERS" />
+    <uses-permission android:name="android.permission.READ_PROFILE" />
+    <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+
     <!-- Networking and telephony -->
     <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
@@ -40,6 +48,7 @@
     <uses-permission android:name="android.permission.STOP_APP_SWITCHES" />
     <uses-permission android:name="android.permission.SET_SCREEN_COMPATIBILITY" />
     <uses-permission android:name="android.permission.START_ANY_ACTIVITY" />
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
 
     <!-- WindowManager -->
     <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
@@ -49,6 +58,10 @@
     <uses-permission android:name="android.permission.SET_ORIENTATION" />
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
 
+    <!-- DreamManager -->
+    <uses-permission android:name="android.permission.READ_DREAM_STATE" />
+    <uses-permission android:name="android.permission.WRITE_DREAM_STATE" />
+
     <application
         android:persistent="true"
         android:allowClearUserData="false"
@@ -78,7 +91,7 @@
                 android:permission="android.permission.BIND_WALLPAPER"
                 android:exported="true" />
 
-        <receiver android:name=".BootReceiver" >
+        <receiver android:name=".BootReceiver" androidprv:primaryUserOnly="true">
             <intent-filter>
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
             </intent-filter>
@@ -93,6 +106,26 @@
                 android:excludeFromRecents="true">
         </activity>
 
+        <activity android:name=".recent.RecentsActivity"
+                android:label="@string/accessibility_desc_recent_apps"
+                android:theme="@style/RecentsStyle"
+                android:excludeFromRecents="true"
+                android:launchMode="singleInstance"
+                android:exported="true">
+          <intent-filter>
+            <action android:name="com.android.systemui.TOGGLE_RECENTS" />
+          </intent-filter>
+        </activity>
+
+        <receiver
+            android:name=".recent.RecentsPreloadReceiver"
+            android:exported="false">
+            <intent-filter>
+                <action android:name="com.android.systemui.recent.action.PRELOAD" />
+                <action android:name="com.android.systemui.recent.action.CANCEL_PRELOAD" />
+            </intent-filter>
+        </receiver>
+
         <!-- started from UsbDeviceSettingsManager -->
         <activity android:name=".usb.UsbConfirmActivity"
             android:exported="true"
@@ -129,6 +162,14 @@
             android:excludeFromRecents="true">
         </activity>
 
+        <!-- started from UsbDebuggingManager -->
+        <activity android:name=".usb.UsbDebuggingActivity"
+            android:permission="android.permission.MANAGE_USB"
+            android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+            android:finishOnCloseSystemDialogs="true"
+            android:excludeFromRecents="true">
+        </activity>
+
         <!-- started from NetworkPolicyManagerService -->
         <activity
             android:name=".net.NetworkOverLimitActivity"
@@ -145,7 +186,7 @@
             android:name=".BeanBag"
             android:exported="true"
             android:label="BeanBag"
-            android:icon="@drawable/redbeandroid"
+            android:icon="@drawable/redbean2"
             android:theme="@android:style/Theme.Wallpaper.NoTitleBar.Fullscreen"
             android:hardwareAccelerated="true"
             android:launchMode="singleInstance"
@@ -157,5 +198,38 @@
 <!--            <category android:name="android.intent.category.LAUNCHER" />-->
             </intent-filter>
         </activity>
+
+        <!-- Beans in space -->
+        <service
+            android:name=".BeanBagDream"
+            android:exported="true"
+            android:label="@string/jelly_bean_dream_name"
+            android:enabled="false"
+            >
+            <intent-filter>
+                <action android:name="android.service.dreams.DreamService" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </service>
+
+        <activity android:name=".Somnambulator"
+            android:label="@string/start_dreams"
+            android:icon="@mipmap/ic_launcher_dreams"
+            android:theme="@android:style/Theme.Wallpaper.NoTitleBar"
+            android:exported="true"
+            android:excludeFromRecents="true"
+            >
+            <!--
+            <intent-filter>
+                <action android:name="android.intent.action.CREATE_SHORTCUT" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            -->
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.DESK_DOCK" />
+            </intent-filter>
+        </activity>
     </application>
 </manifest>
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index fe5b983..c886eea 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -13,3 +13,5 @@
   public void setGlowAlpha(float);
   public void setGlowScale(float);
 }
+
+-keep class com.android.systemui.statusbar.tv.TvStatusBar
diff --git a/packages/SystemUI/res/anim/recent_app_enter.xml b/packages/SystemUI/res/anim/recent_app_enter.xml
deleted file mode 100644
index 4947eee..0000000
--- a/packages/SystemUI/res/anim/recent_app_enter.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-
-<!-- Special window zoom animation: this is the element that enters the screen,
-     it starts at 200% and scales down.  Goes with zoom_exit.xml. -->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@android:anim/decelerate_interpolator">
-    <scale android:fromXScale="0.25" android:toXScale="1.0"
-           android:fromYScale="0.25" android:toYScale="1.0"
-           android:pivotX="0%p" android:pivotY="0%p"
-           android:duration="500" />
-    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-            android:duration="500"/>
-</set>
diff --git a/packages/SystemUI/res/anim/recent_app_leave.xml b/packages/SystemUI/res/anim/recent_app_leave.xml
deleted file mode 100644
index 3d83988..0000000
--- a/packages/SystemUI/res/anim/recent_app_leave.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-
-<!-- Special window zoom animation: this is the element that enters the screen,
-     it starts at 200% and scales down.  Goes with zoom_exit.xml. -->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@android:anim/decelerate_interpolator">
-    <scale android:fromXScale="1.0" android:toXScale="0.25"
-           android:fromYScale="1.0" android:toYScale="0.25"
-           android:pivotX="0%p" android:pivotY="0%p"
-           android:duration="500" />
-    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-            android:duration="500"/>
-</set>
diff --git a/packages/SystemUI/res/anim/recents_launch_from_launcher_enter.xml b/packages/SystemUI/res/anim/recents_launch_from_launcher_enter.xml
new file mode 100644
index 0000000..1135bc0
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_launch_from_launcher_enter.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+     android:shareInterpolator="false"
+     android:zAdjustment="normal">
+  <!--scale android:fromXScale="2.0" android:toXScale="1.0"
+         android:fromYScale="2.0" android:toYScale="1.0"
+         android:interpolator="@android:interpolator/decelerate_cubic"
+         android:fillEnabled="true"
+         android:fillBefore="true" android:fillAfter="true"
+         android:pivotX="50%p" android:pivotY="50%p"
+         android:duration="250" /-->
+</set>
diff --git a/packages/SystemUI/res/anim/recents_launch_from_launcher_exit.xml b/packages/SystemUI/res/anim/recents_launch_from_launcher_exit.xml
new file mode 100644
index 0000000..fa28cf4
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_launch_from_launcher_exit.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+     android:shareInterpolator="false"
+     android:zAdjustment="top">
+  <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+         android:fillEnabled="true"
+         android:fillBefore="true" android:fillAfter="true"
+         android:interpolator="@android:interpolator/decelerate_cubic"
+         android:duration="250"/>
+</set>
diff --git a/packages/SystemUI/res/anim/recents_return_to_launcher_enter.xml b/packages/SystemUI/res/anim/recents_return_to_launcher_enter.xml
new file mode 100644
index 0000000..efa9019
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_return_to_launcher_enter.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+     android:shareInterpolator="false"
+     android:zAdjustment="normal">
+  <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+         android:interpolator="@android:interpolator/decelerate_cubic"
+         android:duration="250"/>
+</set>
diff --git a/packages/SystemUI/res/anim/recents_return_to_launcher_exit.xml b/packages/SystemUI/res/anim/recents_return_to_launcher_exit.xml
new file mode 100644
index 0000000..e95e667
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_return_to_launcher_exit.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+     android:shareInterpolator="false"
+     android:zAdjustment="normal">
+  <!--scale android:fromXScale="1.0" android:toXScale="2.0"
+         android:fromYScale="1.0" android:toYScale="2.0"
+         android:interpolator="@android:interpolator/decelerate_cubic"
+         android:pivotX="50%p" android:pivotY="50%p"
+         android:duration="250" /-->
+  <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+         android:interpolator="@android:interpolator/decelerate_cubic"
+         android:duration="250"/>
+</set>
diff --git a/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_enter.xml b/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_enter.xml
new file mode 100644
index 0000000..121daae
--- /dev/null
+++ b/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_enter.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+     android:shareInterpolator="false"
+     android:zAdjustment="normal">
+  <!--scale android:fromXScale="2.0" android:toXScale="1.0"
+         android:fromYScale="2.0" android:toYScale="1.0"
+         android:interpolator="@android:interpolator/decelerate_cubic"
+         android:fillEnabled="true"
+         android:fillBefore="true" android:fillAfter="true"
+         android:pivotX="50%p" android:pivotY="50%p"
+         android:duration="250" /-->
+  <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+         android:fillEnabled="true"
+         android:fillBefore="true" android:fillAfter="true"
+         android:interpolator="@android:interpolator/decelerate_cubic"
+         android:duration="250"/>
+</set>
diff --git a/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_exit.xml b/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_exit.xml
new file mode 100644
index 0000000..fa28cf4
--- /dev/null
+++ b/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_exit.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+     android:shareInterpolator="false"
+     android:zAdjustment="top">
+  <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+         android:fillEnabled="true"
+         android:fillBefore="true" android:fillAfter="true"
+         android:interpolator="@android:interpolator/decelerate_cubic"
+         android:duration="250"/>
+</set>
diff --git a/packages/SystemUI/res/drawable-hdpi/arrow_dashed.png b/packages/SystemUI/res/drawable-hdpi/arrow_dashed.png
new file mode 100644
index 0000000..a8075d5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/arrow_dashed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_cling_normal.9.png b/packages/SystemUI/res/drawable-hdpi/btn_cling_normal.9.png
new file mode 100644
index 0000000..aea8beb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/btn_cling_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_cling_pressed.9.png b/packages/SystemUI/res/drawable-hdpi/btn_cling_pressed.9.png
new file mode 100644
index 0000000..ebefd20
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/btn_cling_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notifications_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notifications_normal.png
new file mode 100644
index 0000000..62afe76
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notifications_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_normal.png
index a54761f..ead184d 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_normal.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_pressed.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_pressed.png
index f3f336c..203e232 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_pressed.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png
new file mode 100644
index 0000000..ca56ad4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_open_pressed.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_open_pressed.png
new file mode 100644
index 0000000..1a14231
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_open_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png
index 3ed7418..4436359 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_pressed.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_pressed.png
index 5e20eea..c86710d 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_pressed.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_settings_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_settings_normal.png
new file mode 100644
index 0000000..3ed7418
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_settings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_settings_pressed.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_settings_pressed.png
new file mode 100644
index 0000000..5e20eea
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_settings_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_off.png
new file mode 100644
index 0000000..ab66137
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_on.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_on.png
new file mode 100644
index 0000000..e058bcd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_alarm_on.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_alarm_on.png
new file mode 100644
index 0000000..e214c00
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_alarm_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_auto_rotate.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_auto_rotate.png
new file mode 100644
index 0000000..8d45fc5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_auto_rotate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_0.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_0.png
new file mode 100644
index 0000000..6fd7910
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_100.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_100.png
new file mode 100644
index 0000000..f3632f3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_15.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_15.png
new file mode 100644
index 0000000..228f59a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_28.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_28.png
new file mode 100644
index 0000000..dc8510d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_43.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_43.png
new file mode 100644
index 0000000..77abaaa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_57.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_57.png
new file mode 100644
index 0000000..403bfbc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_71.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_71.png
new file mode 100644
index 0000000..c0ff12c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_85.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_85.png
new file mode 100644
index 0000000..18e8864
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_orange.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_orange.png
new file mode 100644
index 0000000..29a853d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_orange.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_red.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_red.png
new file mode 100644
index 0000000..988aa12
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_red.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_white.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_white.png
new file mode 100644
index 0000000..64c0d82
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_white.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bolt.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bolt.png
new file mode 100644
index 0000000..f7dca8b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bolt.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_0.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_0.png
new file mode 100644
index 0000000..9ab1d8f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_100.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_100.png
new file mode 100644
index 0000000..64db815
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_15.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_15.png
new file mode 100644
index 0000000..3965162
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_28.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_28.png
new file mode 100644
index 0000000..4b14d62
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_43.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_43.png
new file mode 100644
index 0000000..3f51ba5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_57.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_57.png
new file mode 100644
index 0000000..aecf7e6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_71.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_71.png
new file mode 100644
index 0000000..524bf73
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_85.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_85.png
new file mode 100644
index 0000000..80325c7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_unknown.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_unknown.png
new file mode 100644
index 0000000..ceaa03b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_not_connected.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_not_connected.png
new file mode 100644
index 0000000..8fb71ba
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_not_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_off.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_off.png
new file mode 100644
index 0000000..ac76535
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_on.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_on.png
new file mode 100644
index 0000000..090d235
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_off.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_off.png
new file mode 100644
index 0000000..841b7d9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_on.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_on.png
new file mode 100644
index 0000000..bb58171
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_circle.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_circle.png
new file mode 100644
index 0000000..f724ea5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_circle.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_hour.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_hour.png
new file mode 100644
index 0000000..ca73621
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_hour.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_minute.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_minute.png
new file mode 100644
index 0000000..8ee38ee
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_minute.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_default_user.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_default_user.png
new file mode 100644
index 0000000..03c450c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_default_user.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_ime.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_ime.png
new file mode 100644
index 0000000..e20a061
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_location.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_location.png
new file mode 100644
index 0000000..7e67171
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_location.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_remote_display.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_remote_display.png
new file mode 100644
index 0000000..a7bc3c5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_remote_display.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_remote_display_connected.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_remote_display_connected.png
new file mode 100644
index 0000000..012a4e8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_remote_display_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_rotation_locked.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_rotation_locked.png
new file mode 100644
index 0000000..1a7618d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_rotation_locked.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_settings.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_settings.png
new file mode 100644
index 0000000..cac7192
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_0.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_0.png
new file mode 100644
index 0000000..39fff41
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_1.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_1.png
new file mode 100644
index 0000000..f9ecb02
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_1x.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_1x.png
new file mode 100644
index 0000000..c7cfa21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_2.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_2.png
new file mode 100644
index 0000000..2268801
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_3.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_3.png
new file mode 100644
index 0000000..16ecb6a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_3g.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_3g.png
new file mode 100644
index 0000000..fb01687
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_4.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_4.png
new file mode 100644
index 0000000..fbbf225
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_4g.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_4g.png
new file mode 100644
index 0000000..c151a64
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_e.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_e.png
new file mode 100644
index 0000000..47e9ad5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_0.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_0.png
new file mode 100644
index 0000000..97d84a9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_1.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_1.png
new file mode 100644
index 0000000..544dcf9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_1x.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_1x.png
new file mode 100644
index 0000000..5ca9892
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_2.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_2.png
new file mode 100644
index 0000000..7f050f8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_3.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_3.png
new file mode 100644
index 0000000..be1ed56
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_3g.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_3g.png
new file mode 100644
index 0000000..5eab3c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_4.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_4.png
new file mode 100644
index 0000000..502787b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_4g.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_4g.png
new file mode 100644
index 0000000..777f8fc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_e.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_e.png
new file mode 100644
index 0000000..e436ed8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_g.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_g.png
new file mode 100644
index 0000000..304c278
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_h.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_h.png
new file mode 100644
index 0000000..26687ca
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_r.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_r.png
new file mode 100644
index 0000000..b0449e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_r.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_g.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_g.png
new file mode 100644
index 0000000..2f622c2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_h.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_h.png
new file mode 100644
index 0000000..f5f76c2c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_in.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_in.png
new file mode 100644
index 0000000..a9dc907
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_inout.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_inout.png
new file mode 100644
index 0000000..89d2939
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_no_network.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_no_network.png
new file mode 100644
index 0000000..3ed973b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_no_network.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_no_signal.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_no_signal.png
new file mode 100644
index 0000000..0fb96d9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_no_signal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_out.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_out.png
new file mode 100644
index 0000000..d8993f8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_r.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_r.png
new file mode 100644
index 0000000..b78f4742
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_r.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_usb_device.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_usb_device.png
new file mode 100644
index 0000000..13ee0a5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_usb_device.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_0.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_0.png
new file mode 100644
index 0000000..7e7d068
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_1.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_1.png
new file mode 100644
index 0000000..b720720
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_2.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_2.png
new file mode 100644
index 0000000..1a4c6d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_3.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_3.png
new file mode 100644
index 0000000..96cd8ab
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_4.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_4.png
new file mode 100644
index 0000000..54bab4d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_full_1.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_full_1.png
new file mode 100644
index 0000000..0a31297
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_full_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_full_2.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_full_2.png
new file mode 100644
index 0000000..3e712ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_full_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_full_3.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_full_3.png
new file mode 100644
index 0000000..565ae54
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_full_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_full_4.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_full_4.png
new file mode 100644
index 0000000..2c30f8e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_full_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_in.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_in.png
new file mode 100644
index 0000000..a9dc907
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_inout.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_inout.png
new file mode 100644
index 0000000..89d2939
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_no_network.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_no_network.png
new file mode 100644
index 0000000..6e4276f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_no_network.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_not_connected.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_not_connected.png
new file mode 100644
index 0000000..6095942
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_not_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_out.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_out.png
new file mode 100644
index 0000000..d8993f8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/notification_header_bg.9.png b/packages/SystemUI/res/drawable-hdpi/notification_header_bg.9.png
deleted file mode 100644
index 7444889..0000000
--- a/packages/SystemUI/res/drawable-hdpi/notification_header_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/search_light.png b/packages/SystemUI/res/drawable-hdpi/search_light.png
new file mode 100644
index 0000000..c8b5a2e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/search_light.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_close_off.9.png b/packages/SystemUI/res/drawable-hdpi/status_bar_close_off.9.png
index bc6462b..0c301ab 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_close_off.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_close_off.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
index f4e28ae..ec0424a 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/arrow_dashed.png b/packages/SystemUI/res/drawable-mdpi/arrow_dashed.png
new file mode 100644
index 0000000..c17c668d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/arrow_dashed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_cling_normal.9.png b/packages/SystemUI/res/drawable-mdpi/btn_cling_normal.9.png
new file mode 100644
index 0000000..43a407e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/btn_cling_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_cling_pressed.9.png b/packages/SystemUI/res/drawable-mdpi/btn_cling_pressed.9.png
new file mode 100644
index 0000000..bf0c8cb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/btn_cling_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notifications_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notifications_normal.png
new file mode 100644
index 0000000..62afe76
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notifications_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_normal.png
index b44b527..5dacccb 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_normal.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_pressed.png
index 94c8165..f1f6b00 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png
new file mode 100644
index 0000000..f04aab1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_open_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_open_pressed.png
new file mode 100644
index 0000000..549c5efd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_open_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png
index 44cfc5b..09d2c55 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_pressed.png
index 0c3fdcd..322d1a7 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_settings_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_settings_normal.png
new file mode 100644
index 0000000..44cfc5b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_settings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_settings_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_settings_pressed.png
new file mode 100644
index 0000000..0c3fdcd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_settings_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_airplane_off.png
new file mode 100644
index 0000000..2d0c479
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_airplane_on.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_airplane_on.png
new file mode 100644
index 0000000..6a2906e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_airplane_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_alarm_on.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_alarm_on.png
new file mode 100644
index 0000000..d6590e2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_alarm_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_auto_rotate.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_auto_rotate.png
new file mode 100644
index 0000000..46beb62
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_auto_rotate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_0.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_0.png
new file mode 100644
index 0000000..c581919
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_100.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_100.png
new file mode 100644
index 0000000..2f330f7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_15.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_15.png
new file mode 100644
index 0000000..2a1637c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_28.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_28.png
new file mode 100644
index 0000000..8457c2b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_43.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_43.png
new file mode 100644
index 0000000..f72fe4a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_57.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_57.png
new file mode 100644
index 0000000..10e3275
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_71.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_71.png
new file mode 100644
index 0000000..ca1613c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_85.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_85.png
new file mode 100644
index 0000000..2bfe20d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_orange.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_orange.png
new file mode 100644
index 0000000..41fc2e9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_orange.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_red.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_red.png
new file mode 100644
index 0000000..414be9d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_red.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_white.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_white.png
new file mode 100644
index 0000000..398a08b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_white.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bolt.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bolt.png
new file mode 100644
index 0000000..b01d7d0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bolt.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_0.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_0.png
new file mode 100644
index 0000000..b917281
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_100.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_100.png
new file mode 100644
index 0000000..480f579
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_15.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_15.png
new file mode 100644
index 0000000..cee2a44
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_28.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_28.png
new file mode 100644
index 0000000..f2056db
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_43.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_43.png
new file mode 100644
index 0000000..697d4ec
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_57.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_57.png
new file mode 100644
index 0000000..9c53dd4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_71.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_71.png
new file mode 100644
index 0000000..c967999
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_85.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_85.png
new file mode 100644
index 0000000..8df8234
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_unknown.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_unknown.png
new file mode 100644
index 0000000..c3a4ab4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_not_connected.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_not_connected.png
new file mode 100644
index 0000000..d0ce4f6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_not_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_off.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_off.png
new file mode 100644
index 0000000..2116449
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_on.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_on.png
new file mode 100644
index 0000000..1cc6e62
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_off.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_off.png
new file mode 100644
index 0000000..df5987c9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_on.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_on.png
new file mode 100644
index 0000000..753e9f7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_circle.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_circle.png
new file mode 100644
index 0000000..27904f2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_circle.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_hour.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_hour.png
new file mode 100644
index 0000000..f7f8c42
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_hour.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_minute.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_minute.png
new file mode 100644
index 0000000..fb17e5ab
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_minute.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_default_user.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_default_user.png
new file mode 100644
index 0000000..d90bdd3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_default_user.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_ime.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_ime.png
new file mode 100644
index 0000000..3263c55
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_location.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_location.png
new file mode 100644
index 0000000..79f1f470
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_location.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_remote_display.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_remote_display.png
new file mode 100644
index 0000000..1ff9cbc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_remote_display.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_remote_display_connected.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_remote_display_connected.png
new file mode 100644
index 0000000..0ec78c03
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_remote_display_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_rotation_locked.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_rotation_locked.png
new file mode 100644
index 0000000..b70df3d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_rotation_locked.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_settings.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_settings.png
new file mode 100644
index 0000000..673d2e0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_0.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_0.png
new file mode 100644
index 0000000..d46fced
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_1.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_1.png
new file mode 100644
index 0000000..ef5179f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_1x.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_1x.png
new file mode 100644
index 0000000..53dc47d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_2.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_2.png
new file mode 100644
index 0000000..359f445
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_3.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_3.png
new file mode 100644
index 0000000..7ebebcd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_3g.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_3g.png
new file mode 100644
index 0000000..88cf8b6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_4.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_4.png
new file mode 100644
index 0000000..db72661
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_4g.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_4g.png
new file mode 100644
index 0000000..6022a6a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_e.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_e.png
new file mode 100644
index 0000000..e493d3b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_0.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_0.png
new file mode 100644
index 0000000..6668846f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_1.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_1.png
new file mode 100644
index 0000000..5c8dc82
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_1x.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_1x.png
new file mode 100644
index 0000000..01560e8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_2.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_2.png
new file mode 100644
index 0000000..3082ff0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_3.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_3.png
new file mode 100644
index 0000000..7966be8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_3g.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_3g.png
new file mode 100644
index 0000000..a78c4d6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_4.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_4.png
new file mode 100644
index 0000000..dce07ae
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_4g.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_4g.png
new file mode 100644
index 0000000..82bcb79
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_e.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_e.png
new file mode 100644
index 0000000..828a728
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_g.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_g.png
new file mode 100644
index 0000000..f1a8017
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_h.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_h.png
new file mode 100644
index 0000000..9077d56
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_r.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_r.png
new file mode 100644
index 0000000..d298624
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_r.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_g.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_g.png
new file mode 100644
index 0000000..cb52c98
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_h.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_h.png
new file mode 100644
index 0000000..14550d5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_in.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_in.png
new file mode 100644
index 0000000..4dd6401
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_inout.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_inout.png
new file mode 100644
index 0000000..07ebd9c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_no_network.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_no_network.png
new file mode 100644
index 0000000..cf2cc52
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_no_network.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_no_signal.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_no_signal.png
new file mode 100644
index 0000000..dcd2dbd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_no_signal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_out.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_out.png
new file mode 100644
index 0000000..d8eda87
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_r.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_r.png
new file mode 100644
index 0000000..d26beb5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_r.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_usb_device.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_usb_device.png
new file mode 100644
index 0000000..6ac70fa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_usb_device.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_0.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_0.png
new file mode 100644
index 0000000..9ab044d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_1.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_1.png
new file mode 100644
index 0000000..1de33ba
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_2.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_2.png
new file mode 100644
index 0000000..34c916d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_3.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_3.png
new file mode 100644
index 0000000..2f7a885
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_4.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_4.png
new file mode 100644
index 0000000..f11cc08
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_full_1.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_full_1.png
new file mode 100644
index 0000000..e78ab6b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_full_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_full_2.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_full_2.png
new file mode 100644
index 0000000..1b025f26
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_full_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_full_3.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_full_3.png
new file mode 100644
index 0000000..3036c86
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_full_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_full_4.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_full_4.png
new file mode 100644
index 0000000..de000eb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_full_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_in.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_in.png
new file mode 100644
index 0000000..4dd6401
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_inout.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_inout.png
new file mode 100644
index 0000000..07ebd9c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_no_network.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_no_network.png
new file mode 100644
index 0000000..72da3e8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_no_network.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_not_connected.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_not_connected.png
new file mode 100644
index 0000000..f606a60
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_not_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_out.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_out.png
new file mode 100644
index 0000000..d8eda87
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notification_header_bg.9.png b/packages/SystemUI/res/drawable-mdpi/notification_header_bg.9.png
deleted file mode 100644
index 5002f97..0000000
--- a/packages/SystemUI/res/drawable-mdpi/notification_header_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/search_light.png b/packages/SystemUI/res/drawable-mdpi/search_light.png
new file mode 100644
index 0000000..4b5b2a4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/search_light.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_close_off.9.png b/packages/SystemUI/res/drawable-mdpi/status_bar_close_off.9.png
index 4f5bba5..5c577cb 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_close_off.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_close_off.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
index ef7afb8..7efb502 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/bugdroid.png b/packages/SystemUI/res/drawable-nodpi/bugdroid.png
new file mode 100644
index 0000000..b90675c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/bugdroid.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/qs_coming_soon.png b/packages/SystemUI/res/drawable-nodpi/qs_coming_soon.png
new file mode 100644
index 0000000..47c89b1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/qs_coming_soon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp/status_bar_recents_background.xml b/packages/SystemUI/res/drawable-sw600dp/status_bar_recents_background.xml
deleted file mode 100644
index 363efeb..0000000
--- a/packages/SystemUI/res/drawable-sw600dp/status_bar_recents_background.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright 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.
- */
--->
-<color xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="#e6000000"
-/>
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_alarm.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_alarm.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_0.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_100.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_100.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_15.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_15.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_28.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_28.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_43.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_43.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_57.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_57.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_71.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_71.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_85.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_85.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim0.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim100.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim100.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim15.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim15.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim28.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim28.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim43.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim43.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim57.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim57.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim71.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim71.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim85.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_battery_charge_anim85.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_bluetooth.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_bluetooth.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_bluetooth_connected.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_bluetooth_connected.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_1x.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_1x.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_3g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_3g.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_4g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_4g.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_e.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_e.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_g.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_h.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_h.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_roam.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_connected_roam.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_1x.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_1x.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_3g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_3g.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_4g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_4g.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_e.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_e.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_g.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_h.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_data_fully_connected_h.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_0.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_0_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_0_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_1.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_1.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_1_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_1_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_2.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_2.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_2_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_2_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_3.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_3.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_3_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_3_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_4.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_4.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_4_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_4_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_flightmode.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_flightmode.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_in.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_in.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_inout.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_inout.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_null.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_null.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_out.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_signal_out.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_in.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_in.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_inout.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_inout.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_out.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_out.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_0.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_1.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_1.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_1_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_1_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_2.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_2.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_2_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_2_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_3.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_3.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_3_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_3_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_4.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_4.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_4_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_4_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_null.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/stat_sys_wifi_signal_null.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/sysbar_notification_panel_bg.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-hdpi/notification_panel_bg.9.png
rename to packages/SystemUI/res/drawable-sw720dp-hdpi/sysbar_notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_alarm.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_alarm.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_0.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_100.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_100.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_15.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_15.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_28.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_28.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_43.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_43.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_57.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_57.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_71.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_71.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_85.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_85.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim0.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim100.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim100.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim15.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim15.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim28.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim28.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim43.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim43.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim57.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim57.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim71.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim71.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim85.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_battery_charge_anim85.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_bluetooth.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_bluetooth.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_bluetooth_connected.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_bluetooth_connected.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_1x.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_1x.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_3g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_3g.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_4g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_4g.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_e.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_e.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_g.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_h.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_h.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_roam.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_connected_roam.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_1x.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_1x.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_3g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_3g.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_4g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_4g.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_e.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_e.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_g.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_h.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_data_fully_connected_h.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_0.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_0_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_0_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_1.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_1.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_1_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_1_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_2.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_2.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_2_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_2_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_3.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_3.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_3_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_3_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_4.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_4.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_4_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_4_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_flightmode.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_flightmode.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_in.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_in.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_inout.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_inout.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_null.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_null.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_out.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_signal_out.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_in.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_in.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_inout.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_inout.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_out.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_out.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_0.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_1.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_1.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_1_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_1_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_2.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_2.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_2_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_2_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_3.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_3.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_3_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_3_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_4.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_4.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_4_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_4_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_null.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/stat_sys_wifi_signal_null.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/sysbar_notification_panel_bg.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-mdpi/notification_panel_bg.9.png
rename to packages/SystemUI/res/drawable-sw720dp-mdpi/sysbar_notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-tvdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-tvdpi/sysbar_notification_panel_bg.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-tvdpi/notification_panel_bg.9.png
rename to packages/SystemUI/res/drawable-sw720dp-tvdpi/sysbar_notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_alarm.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_alarm.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_0.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_100.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_100.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_15.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_15.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_28.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_28.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_43.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_43.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_57.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_57.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_71.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_71.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_85.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_85.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim0.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim100.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim100.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim15.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim15.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim28.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim28.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim43.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim43.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim57.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim57.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim71.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim71.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim85.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_battery_charge_anim85.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_bluetooth.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_bluetooth.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_bluetooth_connected.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_bluetooth_connected.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_1x.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_1x.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_3g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_3g.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_4g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_4g.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_e.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_e.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_g.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_h.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_h.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_roam.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_connected_roam.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_1x.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_1x.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_3g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_3g.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_4g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_4g.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_e.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_e.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_g.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_g.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_h.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_data_fully_connected_h.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_0.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_0_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_0_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_1.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_1.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_1_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_1_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_2.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_2.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_2_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_2_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_3.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_3.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_3_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_3_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_4.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_4.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_4_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_4_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_flightmode.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_flightmode.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_in.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_in.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_inout.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_inout.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_null.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_null.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_out.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_signal_out.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_in.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_in.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_inout.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_inout.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_out.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_out.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_0.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_0.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_1.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_1.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_1_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_1_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_2.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_2.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_2_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_2_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_3.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_3.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_3_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_3_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_4.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_4.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_4_fully.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_4_fully.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_null.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/stat_sys_wifi_signal_null.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/sysbar_notification_panel_bg.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-sw720dp-xhdpi/notification_panel_bg.9.png
rename to packages/SystemUI/res/drawable-sw720dp-xhdpi/sysbar_notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/arrow_dashed.png b/packages/SystemUI/res/drawable-xhdpi/arrow_dashed.png
new file mode 100644
index 0000000..c26ed9c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/arrow_dashed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/btn_cling_normal.9.png b/packages/SystemUI/res/drawable-xhdpi/btn_cling_normal.9.png
new file mode 100644
index 0000000..35511d6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/btn_cling_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/btn_cling_pressed.9.png b/packages/SystemUI/res/drawable-xhdpi/btn_cling_pressed.9.png
new file mode 100644
index 0000000..a38b40f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/btn_cling_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notifications_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notifications_normal.png
new file mode 100644
index 0000000..983302c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notifications_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_normal.png
index 870beb4..c882e9a 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_normal.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_pressed.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_pressed.png
index 94a4646..992b50d 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_pressed.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png
new file mode 100644
index 0000000..56386f8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_pressed.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_pressed.png
new file mode 100644
index 0000000..501c777
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png
index 80fdb79..2d445279 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_pressed.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_pressed.png
index ac7c1a7..ddf2c7a 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_pressed.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_settings_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_settings_normal.png
new file mode 100644
index 0000000..80fdb79
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_settings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_settings_pressed.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_settings_pressed.png
new file mode 100644
index 0000000..ac7c1a7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_settings_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_off.png
new file mode 100644
index 0000000..9a4239b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_on.png
new file mode 100644
index 0000000..0af4f3d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_alarm_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_alarm_on.png
new file mode 100644
index 0000000..07e749a9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_alarm_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_auto_rotate.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_auto_rotate.png
new file mode 100644
index 0000000..f9ab581
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_auto_rotate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_0.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_0.png
new file mode 100644
index 0000000..2b592cc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_100.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_100.png
new file mode 100644
index 0000000..2c56c9b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_15.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_15.png
new file mode 100644
index 0000000..9895f71
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_28.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_28.png
new file mode 100644
index 0000000..323fa8b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_43.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_43.png
new file mode 100644
index 0000000..98eea99
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_57.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_57.png
new file mode 100644
index 0000000..64555c0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_71.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_71.png
new file mode 100644
index 0000000..ad8b15f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_85.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_85.png
new file mode 100644
index 0000000..071b79b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_orange.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_orange.png
new file mode 100644
index 0000000..28ec7a8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_orange.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_red.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_red.png
new file mode 100644
index 0000000..432b496
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_red.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_white.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_white.png
new file mode 100644
index 0000000..9ed63f3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_white.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bolt.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bolt.png
new file mode 100644
index 0000000..0c5594d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bolt.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_0.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_0.png
new file mode 100644
index 0000000..1ecedca
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_100.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_100.png
new file mode 100644
index 0000000..234bb63
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_15.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_15.png
new file mode 100644
index 0000000..e3c6920
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_28.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_28.png
new file mode 100644
index 0000000..3dfbe4c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_43.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_43.png
new file mode 100644
index 0000000..3f493f1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_57.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_57.png
new file mode 100644
index 0000000..0cce725
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_71.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_71.png
new file mode 100644
index 0000000..f6fff00
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_85.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_85.png
new file mode 100644
index 0000000..35ef746
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_unknown.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_unknown.png
new file mode 100644
index 0000000..f5fbbfb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_not_connected.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_not_connected.png
new file mode 100644
index 0000000..e312f8e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_not_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_off.png
new file mode 100644
index 0000000..44cd31b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_on.png
new file mode 100644
index 0000000..62a518a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_off.png
new file mode 100644
index 0000000..653fa3f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_on.png
new file mode 100644
index 0000000..4ed4a9e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_circle.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_circle.png
new file mode 100644
index 0000000..c7864ba
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_circle.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_hour.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_hour.png
new file mode 100644
index 0000000..02c4a05
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_hour.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_minute.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_minute.png
new file mode 100644
index 0000000..aa6be72
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_minute.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_default_user.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_default_user.png
new file mode 100644
index 0000000..fd9b677
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_default_user.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_ime.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_ime.png
new file mode 100644
index 0000000..7eabd10
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_location.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_location.png
new file mode 100644
index 0000000..b2033df
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_location.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_remote_display.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_remote_display.png
new file mode 100644
index 0000000..88ea017
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_remote_display.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_remote_display_connected.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_remote_display_connected.png
new file mode 100644
index 0000000..7573636
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_remote_display_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_rotation_locked.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_rotation_locked.png
new file mode 100644
index 0000000..0098df49
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_rotation_locked.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_settings.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_settings.png
new file mode 100644
index 0000000..2d3638c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_0.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_0.png
new file mode 100644
index 0000000..7419be9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_1.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_1.png
new file mode 100644
index 0000000..471e1fa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_1x.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_1x.png
new file mode 100644
index 0000000..cb1eb0f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_2.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_2.png
new file mode 100644
index 0000000..4311330
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_3.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_3.png
new file mode 100644
index 0000000..637e079
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_3g.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_3g.png
new file mode 100644
index 0000000..8fdd7ff
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_4.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_4.png
new file mode 100644
index 0000000..8fca5f2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_4g.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_4g.png
new file mode 100644
index 0000000..125e33d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_e.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_e.png
new file mode 100644
index 0000000..acf4752e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_0.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_0.png
new file mode 100644
index 0000000..25a5c53
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_1.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_1.png
new file mode 100644
index 0000000..1cbe239
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_1x.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_1x.png
new file mode 100644
index 0000000..9507162
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_2.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_2.png
new file mode 100644
index 0000000..deb8c87
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_3.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_3.png
new file mode 100644
index 0000000..7186579
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_3g.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_3g.png
new file mode 100644
index 0000000..1aa2393
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_4.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_4.png
new file mode 100644
index 0000000..adafb2ca
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_4g.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_4g.png
new file mode 100644
index 0000000..0083754
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_e.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_e.png
new file mode 100644
index 0000000..67e2e11
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_g.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_g.png
new file mode 100644
index 0000000..f47c63e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_h.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_h.png
new file mode 100644
index 0000000..2421050
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_r.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_r.png
new file mode 100644
index 0000000..cb4782e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_r.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_g.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_g.png
new file mode 100644
index 0000000..fd5fb17
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_h.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_h.png
new file mode 100644
index 0000000..c63bbfa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_in.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_in.png
new file mode 100644
index 0000000..a0d588d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_inout.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_inout.png
new file mode 100644
index 0000000..341716d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_no_network.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_no_network.png
new file mode 100644
index 0000000..7f2be8c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_no_network.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_no_signal.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_no_signal.png
new file mode 100644
index 0000000..15169b9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_no_signal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_out.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_out.png
new file mode 100644
index 0000000..b2ad34d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_r.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_r.png
new file mode 100644
index 0000000..89680ce
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_r.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_usb_device.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_usb_device.png
new file mode 100644
index 0000000..780a511
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_usb_device.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_0.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_0.png
new file mode 100644
index 0000000..42fdbe8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_1.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_1.png
new file mode 100644
index 0000000..eefe7ed
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_2.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_2.png
new file mode 100644
index 0000000..a2caca2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_3.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_3.png
new file mode 100644
index 0000000..08c1abd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_4.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_4.png
new file mode 100644
index 0000000..8af72e51
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_full_1.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_full_1.png
new file mode 100644
index 0000000..7d9f032
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_full_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_full_2.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_full_2.png
new file mode 100644
index 0000000..896eacc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_full_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_full_3.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_full_3.png
new file mode 100644
index 0000000..0224da1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_full_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_full_4.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_full_4.png
new file mode 100644
index 0000000..fe28671
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_full_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_in.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_in.png
new file mode 100644
index 0000000..a0d588d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_inout.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_inout.png
new file mode 100644
index 0000000..341716d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_no_network.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_no_network.png
new file mode 100644
index 0000000..4c6f1ff
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_no_network.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_not_connected.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_not_connected.png
new file mode 100644
index 0000000..a6dd06a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_not_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_out.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_out.png
new file mode 100644
index 0000000..b2ad34d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/notification_header_bg.9.png b/packages/SystemUI/res/drawable-xhdpi/notification_header_bg.9.png
deleted file mode 100644
index 15008d2..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/notification_header_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/search_light.png b/packages/SystemUI/res/drawable-xhdpi/search_light.png
new file mode 100644
index 0000000..3aa890f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/search_light.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/status_bar_close_off.9.png b/packages/SystemUI/res/drawable-xhdpi/status_bar_close_off.9.png
index e243e50..98d0cfb 100644
--- a/packages/SystemUI/res/drawable-xhdpi/status_bar_close_off.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/status_bar_close_off.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png
index cdad949..17f4169 100644
--- a/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/cling_button_bg.xml b/packages/SystemUI/res/drawable/cling_button_bg.xml
new file mode 100644
index 0000000..d175f53
--- /dev/null
+++ b/packages/SystemUI/res/drawable/cling_button_bg.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true" android:drawable="@drawable/btn_cling_pressed" />
+    <item android:drawable="@drawable/btn_cling_normal" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_notifications.xml b/packages/SystemUI/res/drawable/ic_notifications.xml
new file mode 100644
index 0000000..97a7623
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_notifications.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true"
+         android:drawable="@drawable/ic_notify_open_normal" />
+    <item
+         android:drawable="@drawable/ic_notify_open_normal" />
+</selector>
+
diff --git a/packages/SystemUI/res/drawable/ic_notify_button_bg.xml b/packages/SystemUI/res/drawable/ic_notify_button_bg.xml
new file mode 100644
index 0000000..85f1ea2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_notify_button_bg.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true"  android:drawable="@*android:drawable/list_selector_pressed_holo_dark" />
+    <item                               android:drawable="@*android:drawable/list_selector_disabled_holo_dark" />
+</selector>
diff --git a/packages/SystemUI/res/drawable/ic_notify_clear.xml b/packages/SystemUI/res/drawable/ic_notify_clear.xml
index 9c432b2..2163198 100644
--- a/packages/SystemUI/res/drawable/ic_notify_clear.xml
+++ b/packages/SystemUI/res/drawable/ic_notify_clear.xml
@@ -16,6 +16,6 @@
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_pressed="true"
-        android:drawable="@drawable/ic_notify_clear_pressed" />
+        android:drawable="@drawable/ic_notify_clear_normal" />
     <item android:drawable="@drawable/ic_notify_clear_normal" />
 </selector>
diff --git a/packages/SystemUI/res/drawable/ic_notify_quicksettings.xml b/packages/SystemUI/res/drawable/ic_notify_quicksettings.xml
index d8ea524..7cf3175 100644
--- a/packages/SystemUI/res/drawable/ic_notify_quicksettings.xml
+++ b/packages/SystemUI/res/drawable/ic_notify_quicksettings.xml
@@ -16,7 +16,7 @@
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_pressed="true"
-         android:drawable="@drawable/ic_notify_quicksettings_pressed" />
+         android:drawable="@drawable/ic_notify_quicksettings_normal" />
     <item
          android:drawable="@drawable/ic_notify_quicksettings_normal" />
 </selector>
diff --git a/packages/SystemUI/res/drawable/ic_notify_settings.xml b/packages/SystemUI/res/drawable/ic_notify_settings.xml
new file mode 100644
index 0000000..9303ca4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_notify_settings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true"
+         android:drawable="@drawable/ic_notify_settings_normal" />
+    <item
+         android:drawable="@drawable/ic_notify_settings_normal" />
+</selector>
+
diff --git a/packages/SystemUI/res/drawable/ic_qs_battery.xml b/packages/SystemUI/res/drawable/ic_qs_battery.xml
new file mode 100644
index 0000000..4e2a2658
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_battery.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<clip
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/stat_sys_battery_100"
+    android:clipOrientation="vertical"
+    android:gravity="bottom" />
diff --git a/packages/SystemUI/res/drawable/navbar_search_handle.xml b/packages/SystemUI/res/drawable/navbar_search_handle.xml
deleted file mode 100644
index e40fa2c..0000000
--- a/packages/SystemUI/res/drawable/navbar_search_handle.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item
-        android:state_enabled="true"
-        android:state_active="false"
-        android:state_focused="false"
-        android:drawable="@*android:drawable/ic_lockscreen_handle_pressed" />
-
-    <item
-        android:state_enabled="true"
-        android:state_active="true"
-        android:state_focused="false"
-        android:drawable="@*android:drawable/ic_lockscreen_handle_pressed" />
-
-</selector>
diff --git a/packages/SystemUI/res/drawable/qs_sys_battery.xml b/packages/SystemUI/res/drawable/qs_sys_battery.xml
new file mode 100644
index 0000000..dd36aa5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_sys_battery.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<level-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:maxLevel="4" android:drawable="@drawable/ic_qs_battery_0" />
+    <item android:maxLevel="15" android:drawable="@drawable/ic_qs_battery_15" />
+    <item android:maxLevel="35" android:drawable="@drawable/ic_qs_battery_28" />
+    <item android:maxLevel="49" android:drawable="@drawable/ic_qs_battery_43" />
+    <item android:maxLevel="60" android:drawable="@drawable/ic_qs_battery_57" />
+    <item android:maxLevel="75" android:drawable="@drawable/ic_qs_battery_71" />
+    <item android:maxLevel="90" android:drawable="@drawable/ic_qs_battery_85" />
+    <item android:maxLevel="100" android:drawable="@drawable/ic_qs_battery_100" />
+</level-list>
diff --git a/packages/SystemUI/res/drawable/qs_sys_battery_charging.xml b/packages/SystemUI/res/drawable/qs_sys_battery_charging.xml
new file mode 100644
index 0000000..cee5081
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_sys_battery_charging.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<level-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:maxLevel="4" android:drawable="@drawable/ic_qs_battery_charge_0" />
+    <item android:maxLevel="15" android:drawable="@drawable/ic_qs_battery_charge_15" />
+    <item android:maxLevel="35" android:drawable="@drawable/ic_qs_battery_charge_28" />
+    <item android:maxLevel="49" android:drawable="@drawable/ic_qs_battery_charge_43" />
+    <item android:maxLevel="60" android:drawable="@drawable/ic_qs_battery_charge_57" />
+    <item android:maxLevel="75" android:drawable="@drawable/ic_qs_battery_charge_71" />
+    <item android:maxLevel="90" android:drawable="@drawable/ic_qs_battery_charge_85" />
+    <item android:maxLevel="100" android:drawable="@drawable/ic_qs_battery_charge_100" />
+</level-list>
diff --git a/packages/SystemUI/res/drawable/qs_tile_background.xml b/packages/SystemUI/res/drawable/qs_tile_background.xml
new file mode 100644
index 0000000..96891c1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_tile_background.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+	<color android:color="#212121" />
+    </item>
+    <item>
+        <color android:color="#161616" />
+    </item>
+</selector>
diff --git a/packages/SystemUI/res/drawable/recents_thumbnail_fg.xml b/packages/SystemUI/res/drawable/recents_thumbnail_fg.xml
index d683af9..c209055 100644
--- a/packages/SystemUI/res/drawable/recents_thumbnail_fg.xml
+++ b/packages/SystemUI/res/drawable/recents_thumbnail_fg.xml
@@ -16,5 +16,5 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:drawable="@drawable/recents_thumbnail_bg_press" android:state_selected="true" />
     <item android:drawable="@drawable/recents_thumbnail_bg_press" android:state_pressed="true" />
-    <item android:drawable="@*android:color/transparent"/>
+    <item android:drawable="@drawable/recents_thumbnail_no_press"/>
 </selector>
diff --git a/packages/SystemUI/res/drawable/recents_thumbnail_no_press.xml b/packages/SystemUI/res/drawable/recents_thumbnail_no_press.xml
new file mode 100644
index 0000000..be07b2c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/recents_thumbnail_no_press.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<color xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="#00000000" />
diff --git a/packages/SystemUI/res/drawable/status_bar_recents_background.xml b/packages/SystemUI/res/drawable/status_bar_recents_background.xml
index 7831db0..ea0b75c 100644
--- a/packages/SystemUI/res/drawable/status_bar_recents_background.xml
+++ b/packages/SystemUI/res/drawable/status_bar_recents_background.xml
@@ -18,8 +18,8 @@
 -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android">
     <gradient name="status_bar_recents_background"
-        android:startColor="#e6000000"
-        android:endColor="#c0000000"
+        android:startColor="#E0000000"
+        android:endColor="#99000000"
         android:angle="@integer/status_bar_recents_bg_gradient_degrees"
         />
 </shape>
diff --git a/packages/SystemUI/res/layout-land/status_bar_help.xml b/packages/SystemUI/res/layout-land/status_bar_help.xml
new file mode 100644
index 0000000..5a635ae
--- /dev/null
+++ b/packages/SystemUI/res/layout-land/status_bar_help.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is the combined status bar / notification panel window. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/status_bar_cling"
+    android:paddingLeft="40dp"
+    android:paddingRight="40dp"
+    android:background="#DD000000"
+    android:focusable="true"
+    android:orientation="horizontal" 
+    android:gravity="top|left"
+    >
+
+    <ImageView
+        android:layout_width="wrap_content"
+        android:layout_weight="0"
+        android:layout_height="wrap_content"
+        android:layout_marginRight="50dp"
+        android:gravity="center"
+        android:src="@drawable/arrow_dashed"
+        tools:ignore="ContentDescription" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:layout_marginTop="40dp"
+        >
+        <TextView
+            style="@style/ClingTitleText"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/status_bar_help_title" />
+
+        <TextView
+            style="@style/ClingText"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="30dp"
+            android:text="@string/status_bar_help_text" />
+
+        <Button
+            android:id="@+id/ok"
+            style="@style/ClingButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingLeft="50dp"
+            android:paddingRight="50dp"
+            android:text="@android:string/ok" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
index 715ccba..10e313e 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
@@ -23,13 +23,17 @@
     android:layout_height="match_parent"
     android:layout_width="wrap_content"
     android:paddingLeft="@dimen/status_bar_recents_item_padding"
-    android:paddingRight="@dimen/status_bar_recents_item_padding">
+    android:paddingRight="@dimen/status_bar_recents_item_padding"
+    android:importantForAccessibility="no"
+    android:clipChildren="false">
 
     <RelativeLayout android:id="@+id/recent_item"
         android:layout_gravity="center_vertical"
         android:layout_height="wrap_content"
         android:layout_width="wrap_content"
-        android:paddingTop="@*android:dimen/status_bar_height">
+        android:paddingTop="@*android:dimen/status_bar_height"
+        android:clipChildren="false"
+        android:clipToPadding="false">
 
         <FrameLayout android:id="@+id/app_thumbnail"
             android:layout_width="wrap_content"
@@ -75,6 +79,7 @@
             android:singleLine="true"
             android:ellipsize="marquee"
             android:textColor="@color/status_bar_recents_app_label_color"
+            android:importantForAccessibility="no"
         />
 
         <TextView android:id="@+id/app_description"
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
index 00e3e27..8fdde92b 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
@@ -26,11 +26,6 @@
     android:layout_width="match_parent"
     systemui:recentItemLayout="@layout/status_bar_recent_item"
     >
-    <View
-        android:id="@+id/recents_transition_background"
-        android:layout_height="match_parent"
-        android:layout_width="match_parent"
-        android:visibility="invisible" />
     <FrameLayout
         android:id="@+id/recents_bg_protect"
         android:background="@drawable/status_bar_recents_background"
@@ -40,32 +35,18 @@
         android:clipToPadding="false"
         android:clipChildren="false">
 
-        <ImageView
-            android:id="@+id/recents_transition_placeholder_icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:visibility="invisible" />
-
         <com.android.systemui.recent.RecentsHorizontalScrollView android:id="@+id/recents_container"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin"
-            android:divider="@null"
-            android:stackFromBottom="true"
             android:fadingEdge="horizontal"
             android:scrollbars="none"
-            android:fadingEdgeLength="@dimen/status_bar_recents_scroll_fading_edge_length"
-            android:layout_gravity="bottom|right"
-            android:orientation="horizontal"
-            android:clipToPadding="false"
-            android:clipChildren="false">
+            android:layout_gravity="right"
+            android:fadingEdgeLength="@dimen/status_bar_recents_scroll_fading_edge_length">
 
             <LinearLayout android:id="@+id/recents_linear_layout"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
-                android:orientation="horizontal"
-                android:clipToPadding="false"
-                android:clipChildren="false">
+                android:orientation="horizontal">
             </LinearLayout>
 
         </com.android.systemui.recent.RecentsHorizontalScrollView>
diff --git a/packages/SystemUI/res/layout-land/status_bar_search_panel.xml b/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
index c8a120d4..f56b03b 100644
--- a/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
@@ -49,7 +49,6 @@
                 prvandroid:targetDrawables="@array/navbar_search_targets"
                 prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
                 prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
-                prvandroid:handleDrawable="@drawable/navbar_search_handle"
                 prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
                 prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
                 prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
deleted file mode 100644
index ca72530..0000000
--- a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
+++ /dev/null
@@ -1,103 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* apps/common/assets/default/default/skins/StatusBar.xml
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_height="wrap_content"
-    android:layout_width="match_parent"
-    android:paddingTop="@dimen/status_bar_recents_item_padding"
-    android:paddingBottom="@dimen/status_bar_recents_item_padding">
-
-    <RelativeLayout android:id="@+id/recent_item"
-        android:layout_gravity="center_horizontal"
-        android:layout_height="wrap_content"
-        android:layout_width="wrap_content">
-
-        <TextView android:id="@+id/app_label"
-            android:layout_width="@dimen/status_bar_recents_app_label_width"
-            android:layout_height="wrap_content"
-            android:textSize="@dimen/status_bar_recents_app_label_text_size"
-            android:fadingEdge="horizontal"
-            android:fadingEdgeLength="@dimen/status_bar_recents_text_fading_edge_length"
-            android:scrollHorizontally="true"
-            android:layout_alignParentLeft="true"
-            android:layout_alignTop="@id/app_icon"
-            android:paddingTop="2dp"
-            android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin"
-            android:singleLine="true"
-            android:ellipsize="marquee"
-            android:textColor="@color/status_bar_recents_app_label_color"
-        />
-        <FrameLayout android:id="@+id/app_thumbnail"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentTop="true"
-            android:layout_toRightOf="@id/app_label"
-            android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
-            android:background="@drawable/recents_thumbnail_bg"
-            android:foreground="@drawable/recents_thumbnail_fg"
-            android:visibility="invisible">
-            <ImageView android:id="@+id/app_thumbnail_image"
-                android:layout_width="@dimen/status_bar_recents_thumbnail_width"
-                android:layout_height="@dimen/status_bar_recents_thumbnail_height"
-            />
-        </FrameLayout>
-        <View android:id="@+id/recents_callout_line"
-            android:layout_width="@dimen/status_bar_recents_app_label_width"
-            android:layout_height="1dip"
-            android:layout_alignParentLeft="true"
-            android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin"
-            android:layout_toLeftOf="@id/app_thumbnail"
-            android:layout_below="@id/app_label"
-            android:layout_marginRight="3dip"
-            android:layout_marginTop="3dip"
-            android:background="@drawable/recents_callout_line"
-        />
-
-        <ImageView android:id="@+id/app_icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/app_label"
-            android:layout_marginLeft="@dimen/status_bar_recents_app_icon_left_margin"
-            android:layout_marginTop="@dimen/status_bar_recents_app_icon_top_margin"
-            android:maxWidth="@dimen/status_bar_recents_app_icon_max_width"
-            android:maxHeight="@dimen/status_bar_recents_app_icon_max_height"
-            android:scaleType="centerInside"
-            android:adjustViewBounds="true"
-            android:visibility="invisible"
-        />
-
-        <TextView android:id="@+id/app_description"
-            android:layout_width="@dimen/status_bar_recents_app_label_width"
-            android:layout_height="wrap_content"
-            android:textSize="@dimen/status_bar_recents_app_description_text_size"
-            android:fadingEdge="horizontal"
-            android:fadingEdgeLength="@dimen/status_bar_recents_text_fading_edge_length"
-            android:scrollHorizontally="true"
-            android:layout_alignParentLeft="true"
-            android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin"
-            android:layout_below="@id/recents_callout_line"
-            android:layout_marginTop="3dip"
-            android:singleLine="true"
-            android:ellipsize="marquee"
-        />
-
-    </RelativeLayout>
-</FrameLayout>
diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
deleted file mode 100644
index a7e5db1..0000000
--- a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* apps/common/assets/default/default/skins/StatusBar.xml
-**
-** Copyright 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.
-*/
--->
-
-<com.android.systemui.recent.RecentsPanelView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
-    android:id="@+id/recents_root"
-    android:layout_height="match_parent"
-    android:layout_width="match_parent"
-    systemui:recentItemLayout="@layout/status_bar_recent_item"
-    >
-    <View
-        android:id="@+id/recents_transition_background"
-        android:layout_height="match_parent"
-        android:layout_width="match_parent"
-        android:visibility="invisible" />
-    <FrameLayout
-        android:id="@+id/recents_bg_protect"
-        android:background="@drawable/status_bar_recents_background"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_alignParentBottom="true">
-
-        <ImageView
-            android:id="@+id/recents_transition_placeholder_icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:visibility="invisible" />
-
-        <com.android.systemui.recent.RecentsVerticalScrollView
-            android:id="@+id/recents_container"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginRight="0dp"
-            android:divider="@null"
-            android:stackFromBottom="true"
-            android:fadingEdge="vertical"
-            android:scrollbars="none"
-            android:fadingEdgeLength="@dimen/status_bar_recents_scroll_fading_edge_length"
-            android:layout_gravity="bottom|left"
-            android:clipToPadding="false"
-            android:clipChildren="false">
-
-            <LinearLayout android:id="@+id/recents_linear_layout"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical"
-                android:clipToPadding="false"
-                android:clipChildren="false">
-            </LinearLayout>
-
-        </com.android.systemui.recent.RecentsVerticalScrollView>
-
-    </FrameLayout>
-
-    <include layout="@layout/status_bar_no_recent_apps"
-        android:id="@+id/recents_no_apps"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:visibility="invisible" />
-
-</com.android.systemui.recent.RecentsPanelView>
diff --git a/packages/SystemUI/res/layout-port/status_bar_search_panel.xml b/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
deleted file mode 100644
index 1e4bb57..0000000
--- a/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* apps/common/assets/default/default/skins/StatusBar.xml
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<com.android.systemui.SearchPanelView
-    xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android"
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/search_panel_container"
-    android:layout_height="match_parent"
-    android:layout_width="match_parent"
-    android:paddingBottom="0dip">
-
-    <RelativeLayout
-        android:id="@+id/search_bg_protect"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginBottom="0dip">
-
-        <RelativeLayout
-            android:id="@+id/search_panel_container"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_alignParentBottom="true">
-
-            <com.android.internal.widget.multiwaveview.GlowPadView
-                android:id="@+id/glow_pad_view"
-                android:orientation="horizontal"
-                android:layout_width="match_parent"
-                android:layout_height="@dimen/navbar_search_panel_height"
-                android:layout_alignParentBottom="true"
-                android:gravity="top"
-
-                prvandroid:targetDrawables="@array/navbar_search_targets"
-                prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
-                prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
-                prvandroid:handleDrawable="@drawable/navbar_search_handle"
-                prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
-                prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
-                prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
-                prvandroid:snapMargin="@dimen/navbar_search_snap_margin"
-                prvandroid:feedbackCount="0"
-                prvandroid:vibrationDuration="@integer/config_vibration_duration"
-                prvandroid:alwaysTrackFinger="true"
-                prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius"
-                prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot"
-               />
-
-        </RelativeLayout>
-
-    </RelativeLayout>
-
-</com.android.systemui.SearchPanelView>
diff --git a/packages/SystemUI/res/layout-sw600dp/carrier_label.xml b/packages/SystemUI/res/layout-sw600dp/carrier_label.xml
new file mode 100644
index 0000000..b33caf8
--- /dev/null
+++ b/packages/SystemUI/res/layout-sw600dp/carrier_label.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<Space
+    xmlns:android="http://schemas.android.com/apk/res/android"    
+    android:visibility="gone"
+    />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
index 67e13eb..2669c7e 100644
--- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
@@ -141,10 +141,25 @@
                 />
         </LinearLayout>
 
+        <ImageView
+            android:layout_width="128dp"
+            android:id="@+id/search_light"
+            android:layout_height="match_parent"
+            android:layout_gravity="center_horizontal"
+            android:src="@drawable/search_light"
+            android:scaleType="center"
+            android:visibility="gone"
+            />
+
         <com.android.systemui.statusbar.policy.DeadZone
             android:id="@+id/deadzone"
-            android:layout_height="@dimen/navigation_bar_deadzone_size"
+            android:layout_height="match_parent"
             android:layout_width="match_parent"
+            systemui:minSize="@dimen/navigation_bar_deadzone_size"
+            systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
+            systemui:holdTime="@integer/navigation_bar_deadzone_hold"
+            systemui:decayTime="@integer/navigation_bar_deadzone_decay"
+            systemui:orientation="horizontal"
             android:layout_gravity="top"
             />
     </FrameLayout>
@@ -267,10 +282,25 @@
                 />
         </LinearLayout>
 
+        <ImageView
+            android:layout_width="162dp"
+            android:id="@+id/search_light"
+            android:layout_height="match_parent"
+            android:layout_gravity="center_horizontal"
+            android:src="@drawable/search_light"
+            android:scaleType="center"
+            android:visibility="gone"
+            />
+
         <com.android.systemui.statusbar.policy.DeadZone
             android:id="@+id/deadzone"
-            android:layout_height="@dimen/navigation_bar_deadzone_size"
+            android:layout_height="match_parent"
             android:layout_width="match_parent"
+            systemui:minSize="@dimen/navigation_bar_deadzone_size"
+            systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
+            systemui:holdTime="@integer/navigation_bar_deadzone_hold"
+            systemui:decayTime="@integer/navigation_bar_deadzone_decay"
+            systemui:orientation="vertical"
             android:layout_gravity="top"
             />
     </FrameLayout>
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml
index 3b6c52e..1fa67bd 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml
@@ -35,7 +35,6 @@
         prvandroid:targetDrawables="@array/navbar_search_targets"
         prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
         prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
-        prvandroid:handleDrawable="@drawable/navbar_search_handle"
         prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
         prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
         prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
diff --git a/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml b/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml
index c478334..b68632a 100644
--- a/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml
@@ -31,10 +31,22 @@
         android:layout_height="@*android:dimen/status_bar_height"
         />
 
-    <include layout="@layout/status_bar_expanded"
-        android:layout_width="@dimen/notification_panel_width"
-        android:layout_height="0dp"
-        android:layout_gravity="center_horizontal|top"
-        />
 
+    <com.android.systemui.statusbar.phone.PanelHolder
+        android:id="@+id/panel_holder"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_marginTop="@*android:dimen/status_bar_height"
+        >
+        <include layout="@layout/status_bar_expanded"
+            android:layout_width="@dimen/notification_panel_width"
+            android:layout_height="wrap_content"
+            android:layout_gravity="left|top"
+            />
+        <include layout="@layout/quick_settings"
+            android:layout_width="@dimen/notification_panel_width"
+            android:layout_height="wrap_content"
+            android:layout_gravity="right|top"
+            />
+    </com.android.systemui.statusbar.phone.PanelHolder>
 </com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml b/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml
deleted file mode 100644
index 8c2360e..0000000
--- a/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* apps/common/assets/default/default/skins/StatusBar.xml
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<com.android.systemui.SearchPanelView
-    xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android"
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/search_panel_container"
-    android:layout_height="match_parent"
-    android:layout_width="match_parent">
-
-    <com.android.internal.widget.multiwaveview.GlowPadView
-        android:id="@+id/glow_pad_view"
-        android:layout_width="wrap_content"
-        android:layout_height="@dimen/navbar_search_panel_height"
-        android:layout_gravity="left|bottom"
-        android:gravity="top|right"
-        android:layout_marginLeft="-150dip"
-
-        prvandroid:targetDrawables="@array/navbar_search_targets"
-        prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
-        prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
-        prvandroid:handleDrawable="@drawable/navbar_search_handle"
-        prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
-        prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
-        prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
-        prvandroid:snapMargin="@dimen/navbar_search_snap_margin"
-        prvandroid:feedbackCount="0"
-        prvandroid:vibrationDuration="@integer/config_vibration_duration"
-        prvandroid:alwaysTrackFinger="true"
-        prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius"
-        prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot"/>
-
-</com.android.systemui.SearchPanelView>
diff --git a/packages/SystemUI/res/layout/carrier_label.xml b/packages/SystemUI/res/layout/carrier_label.xml
new file mode 100644
index 0000000..41a1fff
--- /dev/null
+++ b/packages/SystemUI/res/layout/carrier_label.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"    
+    android:id="@+id/carrier_label"
+    android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Network"
+    android:layout_height="@dimen/carrier_label_height"
+    android:layout_width="match_parent"
+    android:layout_gravity="bottom"
+    android:layout_marginBottom="@dimen/close_handle_height"
+    android:gravity="center"
+    android:visibility="invisible"
+    />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/flip_settings.xml b/packages/SystemUI/res/layout/flip_settings.xml
new file mode 100644
index 0000000..1b8898c5
--- /dev/null
+++ b/packages/SystemUI/res/layout/flip_settings.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<com.android.systemui.statusbar.phone.QuickSettingsScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginBottom="@dimen/close_handle_underlap"
+    android:overScrollMode="ifContentScrolls"
+    >
+    <com.android.systemui.statusbar.phone.QuickSettingsContainerView
+        android:id="@+id/quick_settings_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:animateLayoutChanges="true"
+        android:columnCount="@integer/quick_settings_num_columns"
+        />
+</com.android.systemui.statusbar.phone.QuickSettingsScrollView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index d41040d..440a4e1 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -145,10 +145,25 @@
                 />
         </LinearLayout>
 
+        <ImageView
+            android:layout_width="80dp"
+            android:id="@+id/search_light"
+            android:layout_height="match_parent"
+            android:layout_gravity="center_horizontal"
+            android:src="@drawable/search_light"
+            android:scaleType="center"
+            android:visibility="gone"
+            />
+
         <com.android.systemui.statusbar.policy.DeadZone
             android:id="@+id/deadzone"
-            android:layout_height="@dimen/navigation_bar_deadzone_size"
+            android:layout_height="match_parent"
             android:layout_width="match_parent"
+            systemui:minSize="@dimen/navigation_bar_deadzone_size"
+            systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
+            systemui:holdTime="@integer/navigation_bar_deadzone_hold"
+            systemui:decayTime="@integer/navigation_bar_deadzone_decay"
+            systemui:orientation="horizontal"
             android:layout_gravity="top"
             />
     </FrameLayout>
@@ -274,11 +289,26 @@
                 />
         </LinearLayout>
 
+        <ImageView
+            android:id="@+id/search_light"
+            android:layout_height="80dp"
+            android:layout_width="match_parent"
+            android:layout_gravity="center_vertical"
+            android:src="@drawable/search_light"
+            android:scaleType="center"
+            android:visibility="gone"
+            />
+
         <com.android.systemui.statusbar.policy.DeadZone
             android:id="@+id/deadzone"
-            android:layout_width="@dimen/navigation_bar_deadzone_size"
             android:layout_height="match_parent"
-            android:layout_gravity="left"
+            android:layout_width="match_parent"
+            systemui:minSize="@dimen/navigation_bar_deadzone_size"
+            systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
+            systemui:holdTime="@integer/navigation_bar_deadzone_hold"
+            systemui:decayTime="@integer/navigation_bar_deadzone_decay"
+            systemui:orientation="vertical"
+            android:layout_gravity="top"
             />
     </FrameLayout>
 
diff --git a/packages/SystemUI/res/layout/quick_settings.xml b/packages/SystemUI/res/layout/quick_settings.xml
new file mode 100644
index 0000000..75082ba
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<com.android.systemui.statusbar.phone.SettingsPanelView 
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:id="@+id/settings_panel"
+    android:background="@drawable/notification_panel_bg"
+    >
+    <!-- TODO: Put into ScrollView -->
+    <com.android.systemui.statusbar.phone.QuickSettingsScrollView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="@dimen/close_handle_underlap"
+        android:overScrollMode="ifContentScrolls"
+        >
+        <com.android.systemui.statusbar.phone.QuickSettingsContainerView
+            android:id="@+id/quick_settings_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:animateLayoutChanges="true"
+            android:columnCount="@integer/quick_settings_num_columns"
+            />
+    </com.android.systemui.statusbar.phone.QuickSettingsScrollView>
+
+    <View
+        android:id="@+id/handle"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/close_handle_height"
+        android:background="@drawable/status_bar_close"
+        android:visibility="invisible"
+        />
+
+</com.android.systemui.statusbar.phone.SettingsPanelView >
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
new file mode 100644
index 0000000..f7b1d78
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout 
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    style="@style/BrightnessDialogContainer">
+
+    <ImageView
+        android:id="@+id/brightness_icon"
+	    android:layout_width="wrap_content"
+	    android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:paddingRight="10dp"
+        android:src="@drawable/ic_qs_brightness_auto_off"
+        />
+    <com.android.systemui.statusbar.policy.ToggleSlider
+        android:id="@+id/brightness_slider"
+        android:layout_width="0dp"
+        android:layout_height="40dp"
+        android:layout_weight="1"
+        android:layout_marginRight="2dp"
+        android:layout_gravity="center_vertical"
+        systemui:text="@string/status_bar_settings_auto_brightness_label"
+        />
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_settings_tile.xml b/packages/SystemUI/res/layout/quick_settings_tile.xml
new file mode 100644
index 0000000..911f6a2
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<com.android.systemui.statusbar.phone.QuickSettingsTileView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="@dimen/quick_settings_cell_height"
+    android:background="@drawable/qs_tile_background" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_airplane.xml b/packages/SystemUI/res/layout/quick_settings_tile_airplane.xml
new file mode 100644
index 0000000..ac87496
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_airplane.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/TextAppearance.QuickSettings.TileView"
+    android:id="@+id/airplane_mode_textview"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center"
+    />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_alarm.xml b/packages/SystemUI/res/layout/quick_settings_tile_alarm.xml
new file mode 100644
index 0000000..0327bee
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_alarm.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/TextAppearance.QuickSettings.TileView"
+    android:id="@+id/alarm_textview"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center"
+    android:drawableTop="@drawable/ic_qs_alarm_on"
+    />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_battery.xml b/packages/SystemUI/res/layout/quick_settings_tile_battery.xml
new file mode 100644
index 0000000..446b24c
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_battery.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:orientation="vertical">
+    <ImageView
+        android:id="@+id/battery_image"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:paddingBottom="10dp"
+        />
+    <TextView
+        style="@style/TextAppearance.QuickSettings.TileView"
+        android:id="@+id/battery_textview"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:gravity="center"
+        />
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_bluetooth.xml b/packages/SystemUI/res/layout/quick_settings_tile_bluetooth.xml
new file mode 100644
index 0000000..2f3a9c6
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_bluetooth.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/TextAppearance.QuickSettings.TileView"
+    android:id="@+id/bluetooth_textview"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center"
+    />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_brightness.xml b/packages/SystemUI/res/layout/quick_settings_tile_brightness.xml
new file mode 100644
index 0000000..5b3ce1f
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_brightness.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/TextAppearance.QuickSettings.TileView"
+    android:id="@+id/brightness_textview"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center"
+    android:drawableTop="@drawable/ic_qs_brightness_auto_off"
+    />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_bugreport.xml b/packages/SystemUI/res/layout/quick_settings_tile_bugreport.xml
new file mode 100644
index 0000000..0b6a614
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_bugreport.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/TextAppearance.QuickSettings.TileView"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center"
+    android:drawableTop="@*android:drawable/stat_sys_adb"
+    android:text="@*android:string/bugreport_title"
+    />
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_ime.xml b/packages/SystemUI/res/layout/quick_settings_tile_ime.xml
new file mode 100644
index 0000000..e92acd5
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_ime.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/TextAppearance.QuickSettings.TileView"
+    android:id="@+id/ime_textview"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center"
+    android:drawableTop="@drawable/ic_qs_ime"
+    android:text="@string/quick_settings_ime_label"
+    />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_location.xml b/packages/SystemUI/res/layout/quick_settings_tile_location.xml
new file mode 100644
index 0000000..0accb38
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_location.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/TextAppearance.QuickSettings.TileView"
+    android:id="@+id/location_textview"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center"
+    android:drawableTop="@drawable/ic_qs_location"
+    android:text="@string/quick_settings_location_label"
+    />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_media.xml b/packages/SystemUI/res/layout/quick_settings_tile_media.xml
new file mode 100644
index 0000000..7217de3
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_media.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/TextAppearance.QuickSettings.TileView"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:gravity="center"
+    android:text="@string/quick_settings_media_device_label"
+    android:singleLine="true"
+    />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_rotation_lock.xml b/packages/SystemUI/res/layout/quick_settings_tile_rotation_lock.xml
new file mode 100644
index 0000000..6aecaea
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_rotation_lock.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/TextAppearance.QuickSettings.TileView"
+    android:id="@+id/rotation_lock_textview"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center"
+    />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_rssi.xml b/packages/SystemUI/res/layout/quick_settings_tile_rssi.xml
new file mode 100644
index 0000000..febd8a8
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_rssi.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:orientation="vertical">
+    <FrameLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center">
+        <ImageView
+            android:id="@+id/rssi_image"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:paddingBottom="10dp"
+            />
+        <ImageView
+            android:id="@+id/rssi_overlay_image"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:paddingBottom="10dp"
+            />
+    </FrameLayout>
+    <TextView
+        style="@style/TextAppearance.QuickSettings.TileView"
+        android:id="@+id/rssi_textview"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:gravity="center"
+        android:text="@string/quick_settings_rssi_label"
+        />
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_settings.xml b/packages/SystemUI/res/layout/quick_settings_tile_settings.xml
new file mode 100644
index 0000000..d155935
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_settings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/TextAppearance.QuickSettings.TileView"
+    android:id="@+id/settings_tileview"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center"
+    android:drawableTop="@drawable/ic_qs_settings"
+    />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_time.xml b/packages/SystemUI/res/layout/quick_settings_tile_time.xml
new file mode 100644
index 0000000..910e1f6
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_time.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:orientation="vertical">
+    <AnalogClock
+        android:id="@+id/analog_clock"
+        android:layout_width="32dp"
+        android:layout_height="32dp"
+        android:layout_gravity="center"
+        android:layout_marginBottom="10dp"
+        android:dial="@drawable/ic_qs_clock_circle"
+        android:hand_hour="@drawable/ic_qs_clock_hour"
+        android:hand_minute="@drawable/ic_qs_clock_minute"
+        />
+    <com.android.systemui.statusbar.policy.DateView
+        android:textAppearance="@style/TextAppearance.QuickSettings.TileView"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:gravity="center"
+        />
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_user.xml b/packages/SystemUI/res/layout/quick_settings_tile_user.xml
new file mode 100644
index 0000000..878f500
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_user.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <ImageView
+        android:id="@+id/user_imageview"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:src="@drawable/ic_qs_default_user"
+        android:scaleType="centerCrop"
+        />
+    <TextView
+        style="@style/TextAppearance.QuickSettings.TileView"
+        android:id="@+id/user_textview"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal|bottom"
+        android:gravity="center"
+        android:text="@string/quick_settings_user_label"
+        android:background="#CC000000"
+        />
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_wifi.xml b/packages/SystemUI/res/layout/quick_settings_tile_wifi.xml
new file mode 100644
index 0000000..67d6c23
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_wifi.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/TextAppearance.QuickSettings.TileView"
+    android:id="@+id/wifi_textview"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center"
+    android:text="@string/quick_settings_wifi_label"
+    />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_wifi_display.xml b/packages/SystemUI/res/layout/quick_settings_tile_wifi_display.xml
new file mode 100644
index 0000000..2d7e441
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_wifi_display.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/TextAppearance.QuickSettings.TileView"
+    android:id="@+id/wifi_display_textview"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center"
+    android:drawableTop="@drawable/ic_qs_remote_display"
+    android:text="@string/quick_settings_wifi_display_label"
+    />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 6ed5fb7..bf20e9d 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -35,13 +35,13 @@
         android:layout_width="@dimen/status_bar_icon_size"
         android:layout_height="match_parent"
         android:paddingLeft="6dip"
-		android:paddingBottom="2dip"
+        android:paddingBottom="2dip"
         android:src="@drawable/ic_sysbar_lights_out_dot_small"
         android:scaleType="center"
         android:visibility="gone"
         />
 
-    <LinearLayout android:id="@+id/icons"
+    <LinearLayout android:id="@+id/status_bar_contents"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:paddingLeft="6dip"
@@ -50,7 +50,7 @@
         >
 
         <LinearLayout
-			android:id="@+id/notification_icon_area"
+            android:id="@+id/notification_icon_area"
             android:layout_width="0dip"
             android:layout_height="match_parent"
             android:layout_weight="1"
@@ -71,42 +71,48 @@
                 android:orientation="horizontal"/>  
         </LinearLayout>
 
-        <LinearLayout android:id="@+id/statusIcons"
+        <LinearLayout android:id="@+id/system_icon_area"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:gravity="center_vertical"
-            android:orientation="horizontal"/>    
+            android:orientation="horizontal">
 
-        <LinearLayout
-            android:id="@+id/signal_battery_cluster"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:paddingLeft="2dp"
-            android:orientation="horizontal"
-            android:gravity="center"
-            >
-            <include layout="@layout/signal_cluster_view" 
-                android:id="@+id/signal_cluster"
+            <LinearLayout android:id="@+id/statusIcons"
                 android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                />
-            <ImageView
-                android:id="@+id/battery"
-                android:layout_height="wrap_content"
+                android:layout_height="match_parent"
+                android:gravity="center_vertical"
+                android:orientation="horizontal"/>    
+    
+            <LinearLayout
+                android:id="@+id/signal_battery_cluster"
                 android:layout_width="wrap_content"
-                android:paddingLeft="4dip"
+                android:layout_height="match_parent"
+                android:paddingLeft="2dp"
+                android:orientation="horizontal"
+                android:gravity="center"
+                >
+                <include layout="@layout/signal_cluster_view" 
+                    android:id="@+id/signal_cluster"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    />
+                <ImageView
+                    android:id="@+id/battery"
+                    android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:paddingLeft="4dip"
+                    />
+            </LinearLayout>
+    
+            <com.android.systemui.statusbar.policy.Clock
+                android:id="@+id/clock"
+                android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:singleLine="true"
+                android:paddingLeft="6dip"
+                android:gravity="center_vertical|left"
                 />
         </LinearLayout>
-
-        <com.android.systemui.statusbar.policy.Clock
-            android:id="@+id/clock"
-            android:textAppearance="@style/TextAppearance.StatusBar.Clock"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:singleLine="true"
-            android:paddingLeft="6dip"
-            android:gravity="center_vertical|left"
-            />
     </LinearLayout>
         
     <LinearLayout android:id="@+id/ticker"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 17dbcac..b71025e 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -18,33 +18,39 @@
 */
 -->
 
-<FrameLayout 
+<com.android.systemui.statusbar.phone.NotificationPanelView 
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
     android:id="@+id/notification_panel"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
+    android:layout_width="0dp"
+    android:layout_height="wrap_content"
     android:background="@drawable/notification_panel_bg"
     android:paddingTop="@dimen/notification_panel_padding_top"
     android:layout_marginLeft="@dimen/notification_panel_margin_left"
     >
 
-    <TextView
-        android:id="@+id/carrier_label"
-        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Network"
+    <View
+        android:id="@+id/handle"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/close_handle_height"
+        android:background="@drawable/status_bar_close"
+        android:visibility="invisible"
+        />
+
+    <include
+        layout="@layout/carrier_label"
         android:layout_height="@dimen/carrier_label_height"
         android:layout_width="match_parent"
-        android:layout_gravity="bottom"
         android:layout_marginBottom="@dimen/close_handle_height"
-        android:gravity="center"
-        android:visibility="invisible"
+        android:layout_gravity="bottom"
         />
 
     <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
+        android:layout_height="wrap_content"
         android:layout_marginBottom="@dimen/close_handle_underlap"
         android:orientation="vertical"
+        android:animateLayoutChanges="false"
         >
 
         <include layout="@layout/status_bar_expanded_header"
@@ -57,40 +63,35 @@
             android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Network.EmergencyOnly"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:paddingBottom="4dp"
+            android:padding="4dp"
             android:gravity="center"
             android:visibility="gone"
             />
 
-        <ScrollView
-            android:id="@+id/scroll"
+        <FrameLayout
             android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:fadingEdge="none"
-            android:overScrollMode="ifContentScrolls"
+            android:layout_height="wrap_content"
             >
-            <com.android.systemui.statusbar.policy.NotificationRowLayout
-                android:id="@+id/latestItems"
+            <ViewStub android:id="@+id/flip_settings_stub"
+                android:layout="@layout/flip_settings"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                systemui:rowHeight="@dimen/notification_row_min_height"
                 />
-        </ScrollView>
+    
+            <ScrollView
+                android:id="@+id/scroll"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:fadingEdge="none"
+                android:overScrollMode="ifContentScrolls"
+                >
+                <com.android.systemui.statusbar.policy.NotificationRowLayout
+                    android:id="@+id/latestItems"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    systemui:rowHeight="@dimen/notification_row_min_height"
+                    />
+            </ScrollView>
+        </FrameLayout>
     </LinearLayout>
-
-    <com.android.systemui.statusbar.phone.CloseDragHandle android:id="@+id/close"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/close_handle_height"
-        android:layout_gravity="bottom"
-        android:orientation="vertical"
-        >
-        <ImageView
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/close_handle_height"
-            android:layout_gravity="bottom"
-            android:scaleType="fitXY"
-            android:src="@drawable/status_bar_close"
-            />
-
-    </com.android.systemui.statusbar.phone.CloseDragHandle>
-</FrameLayout><!-- end of sliding panel -->
+</com.android.systemui.statusbar.phone.NotificationPanelView><!-- end of sliding panel -->
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 7f598b6..556210e 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -18,46 +18,42 @@
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    android:id="@+id/header"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
+    android:layout_height="@dimen/notification_panel_header_height"
     android:background="@drawable/notification_header_bg"
     android:orientation="horizontal"
     android:gravity="center_vertical"
     android:baselineAligned="false"
     >
-    <com.android.systemui.statusbar.policy.Clock
-        android:id="@+id/clock"
+    <RelativeLayout
+        android:id="@+id/datetime"
         android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginLeft="8dp"
-        android:singleLine="true"
-        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
-        />
+        android:layout_height="match_parent"
+        android:paddingLeft="8dp"
+        android:paddingRight="8dp"
+        android:background="@drawable/ic_notify_button_bg"
+        android:enabled="false"
+        >
+        <com.android.systemui.statusbar.policy.Clock
+            android:id="@+id/clock"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="8dp"
+            android:singleLine="true"
+            android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
+            android:layout_centerVertical="true"
+            />
 
-    <com.android.systemui.statusbar.policy.DateView android:id="@+id/date"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginLeft="8dp"
-        android:layout_marginRight="8dp"
-        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
-        />
-
-    <com.android.systemui.statusbar.RotationToggle android:id="@+id/rotation_lock_button"
-        android:layout_width="32dp"
-        android:layout_height="32dp"
-        android:layout_margin="8dp"
-        android:button="@drawable/ic_notify_rotation"
-        android:contentDescription="@string/accessibility_rotation_lock_off"
-        android:clickable="true"
-        />
-
-    <ImageView android:id="@+id/settings_button"
-        android:layout_width="48dp"
-        android:layout_height="48dp"
-        android:scaleType="center"
-        android:src="@drawable/ic_notify_quicksettings"
-        android:contentDescription="@string/accessibility_settings_button"
-        />
+        <com.android.systemui.statusbar.policy.DateView android:id="@+id/date"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
+            android:layout_toRightOf="@id/clock"
+            android:layout_alignBaseline="@id/clock"
+            />
+    </RelativeLayout>
 
     <Space
         android:layout_width="0dp"
@@ -65,11 +61,49 @@
         android:layout_weight="1"
         />
 
+    <TextView
+        android:id="@+id/header_debug_info"
+        android:visibility="invisible"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:fontFamily="sans-serif-condensed"
+        android:textSize="11dp"
+        android:textStyle="bold"
+        android:textColor="#00A040"
+        android:padding="2dp"
+        />
+
     <ImageView android:id="@+id/clear_all_button"
-        android:layout_width="48dp"
-        android:layout_height="48dp"
+        android:layout_width="50dp"
+        android:layout_height="50dp"
         android:scaleType="center"
         android:src="@drawable/ic_notify_clear"
+        android:background="@drawable/ic_notify_button_bg"
         android:contentDescription="@string/accessibility_clear_all"
-        />            
-</LinearLayout>
\ No newline at end of file
+        />     
+
+    <FrameLayout android:id="@+id/settings_button_holder"
+        android:layout_width="50dp"
+        android:layout_height="50dp"
+        android:layout_marginLeft="12dp"
+        >
+        <ImageView android:id="@+id/settings_button"
+            android:layout_width="50dp"
+            android:layout_height="50dp"
+            android:scaleType="center"
+            android:src="@drawable/ic_notify_settings"
+            android:background="@drawable/ic_notify_button_bg"
+            android:contentDescription="@string/accessibility_desc_quick_settings"
+            />
+        <ImageView android:id="@+id/notification_button"
+            android:layout_width="50dp"
+            android:layout_height="50dp"
+            android:scaleType="center"
+            android:src="@drawable/ic_notifications"
+            android:background="@drawable/ic_notify_button_bg"
+            android:visibility="gone"
+            android:contentDescription="@string/accessibility_notifications_button"
+            />
+    </FrameLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_help.xml b/packages/SystemUI/res/layout/status_bar_help.xml
new file mode 100644
index 0000000..41bde4b
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_help.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is the combined status bar / notification panel window. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/status_bar_cling"
+    android:paddingLeft="40dp"
+    android:paddingRight="40dp"
+    android:background="#DD000000"
+    android:focusable="true"
+    android:orientation="vertical" 
+    android:gravity="top|left"
+    >
+
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="50dp"
+        android:gravity="center"
+        android:src="@drawable/arrow_dashed"
+        tools:ignore="ContentDescription" />
+
+    <TextView
+        style="@style/ClingTitleText"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/status_bar_help_title" />
+
+    <TextView
+        style="@style/ClingText"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="30dp"
+        android:text="@string/status_bar_help_text" />
+
+    <Button
+        android:id="@+id/ok"
+        style="@style/ClingButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingLeft="50dp"
+        android:paddingRight="50dp"
+        android:text="@android:string/ok" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index dd70166..3dcdae8 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -49,4 +49,17 @@
         android:background="@drawable/bottom_divider_glow"
         />
 
+    <TextView
+        android:id="@+id/debug_info"
+        android:visibility="invisible"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom|right"
+        android:fontFamily="sans-serif-condensed"
+        android:textSize="9dp"
+        android:textStyle="bold"
+        android:textColor="#00A040"
+        android:padding="2dp"
+        />
+
 </FrameLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_recent_item.xml b/packages/SystemUI/res/layout/status_bar_recent_item.xml
new file mode 100644
index 0000000..e2b5723
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_recent_item.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:paddingTop="@dimen/status_bar_recents_item_padding"
+    android:paddingBottom="@dimen/status_bar_recents_item_padding"
+    android:clipChildren="false"
+    android:importantForAccessibility="no">
+
+    <RelativeLayout android:id="@+id/recent_item"
+        android:layout_gravity="center_horizontal"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:clipChildren="false">
+
+        <TextView android:id="@+id/app_label"
+            android:layout_width="@dimen/status_bar_recents_app_label_width"
+            android:layout_height="wrap_content"
+            android:textSize="@dimen/status_bar_recents_app_label_text_size"
+            android:fadingEdge="horizontal"
+            android:fadingEdgeLength="@dimen/status_bar_recents_text_fading_edge_length"
+            android:scrollHorizontally="true"
+            android:layout_alignParentLeft="true"
+            android:layout_alignTop="@+id/app_icon"
+            android:paddingTop="2dp"
+            android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:textColor="@color/status_bar_recents_app_label_color"
+            android:importantForAccessibility="no"
+        />
+        <FrameLayout android:id="@+id/app_thumbnail"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentTop="true"
+            android:layout_toRightOf="@id/app_label"
+            android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
+            android:background="@drawable/recents_thumbnail_bg"
+            android:foreground="@drawable/recents_thumbnail_fg"
+            android:visibility="invisible">
+            <ImageView android:id="@+id/app_thumbnail_image"
+                android:layout_width="@dimen/status_bar_recents_thumbnail_width"
+                android:layout_height="@dimen/status_bar_recents_thumbnail_height"
+            />
+        </FrameLayout>
+        <View android:id="@+id/recents_callout_line"
+            android:layout_width="@dimen/status_bar_recents_app_label_width"
+            android:layout_height="1dip"
+            android:layout_alignParentLeft="true"
+            android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin"
+            android:layout_toLeftOf="@id/app_thumbnail"
+            android:layout_below="@id/app_label"
+            android:layout_marginRight="3dip"
+            android:layout_marginTop="3dip"
+            android:background="@drawable/recents_callout_line"
+        />
+
+        <ImageView android:id="@id/app_icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_toRightOf="@id/app_label"
+            android:layout_marginLeft="@dimen/status_bar_recents_app_icon_left_margin"
+            android:layout_marginTop="@dimen/status_bar_recents_app_icon_top_margin"
+            android:maxWidth="@dimen/status_bar_recents_app_icon_max_width"
+            android:maxHeight="@dimen/status_bar_recents_app_icon_max_height"
+            android:scaleType="centerInside"
+            android:adjustViewBounds="true"
+            android:visibility="invisible"
+        />
+
+        <TextView android:id="@+id/app_description"
+            android:layout_width="@dimen/status_bar_recents_app_label_width"
+            android:layout_height="wrap_content"
+            android:textSize="@dimen/status_bar_recents_app_description_text_size"
+            android:fadingEdge="horizontal"
+            android:fadingEdgeLength="@dimen/status_bar_recents_text_fading_edge_length"
+            android:scrollHorizontally="true"
+            android:layout_alignParentLeft="true"
+            android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin"
+            android:layout_below="@id/recents_callout_line"
+            android:layout_marginTop="3dip"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+        />
+
+    </RelativeLayout>
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_recent_panel.xml b/packages/SystemUI/res/layout/status_bar_recent_panel.xml
new file mode 100644
index 0000000..7335f86
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_recent_panel.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 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.
+*/
+-->
+
+<com.android.systemui.recent.RecentsPanelView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    android:id="@+id/recents_root"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    systemui:recentItemLayout="@layout/status_bar_recent_item"
+    >
+    <FrameLayout
+        android:id="@+id/recents_bg_protect"
+        android:background="@drawable/status_bar_recents_background"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_alignParentBottom="true">
+
+        <com.android.systemui.recent.RecentsVerticalScrollView
+            android:id="@+id/recents_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="0dp"
+            android:divider="@null"
+            android:stackFromBottom="true"
+            android:fadingEdge="vertical"
+            android:scrollbars="none"
+            android:fadingEdgeLength="@dimen/status_bar_recents_scroll_fading_edge_length"
+            android:layout_gravity="bottom|left"
+            android:clipToPadding="false"
+            android:clipChildren="false">
+
+            <LinearLayout android:id="@+id/recents_linear_layout"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:clipToPadding="false"
+                android:clipChildren="false">
+            </LinearLayout>
+
+        </com.android.systemui.recent.RecentsVerticalScrollView>
+
+    </FrameLayout>
+
+    <include layout="@layout/status_bar_no_recent_apps"
+        android:id="@+id/recents_no_apps"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="invisible" />
+
+</com.android.systemui.recent.RecentsPanelView>
diff --git a/packages/SystemUI/res/layout/status_bar_search_panel.xml b/packages/SystemUI/res/layout/status_bar_search_panel.xml
new file mode 100644
index 0000000..b871bef
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_search_panel.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<com.android.systemui.SearchPanelView
+    xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/search_panel_container"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:paddingBottom="0dip">
+
+    <RelativeLayout
+        android:id="@+id/search_bg_protect"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_marginBottom="0dip">
+
+        <RelativeLayout
+            android:id="@+id/search_panel_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true">
+
+            <com.android.internal.widget.multiwaveview.GlowPadView
+                android:id="@+id/glow_pad_view"
+                android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/navbar_search_panel_height"
+                android:layout_alignParentBottom="true"
+                android:gravity="top"
+
+                prvandroid:targetDrawables="@array/navbar_search_targets"
+                prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
+                prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
+                prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
+                prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
+                prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
+                prvandroid:snapMargin="@dimen/navbar_search_snap_margin"
+                prvandroid:feedbackCount="0"
+                prvandroid:vibrationDuration="@integer/config_vibration_duration"
+                prvandroid:alwaysTrackFinger="true"
+                prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius"
+                prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot"
+               />
+
+        </RelativeLayout>
+
+    </RelativeLayout>
+
+</com.android.systemui.SearchPanelView>
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 5bf1a58..2b56618 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -32,9 +32,20 @@
         android:layout_height="@*android:dimen/status_bar_height"
         />
 
-    <include layout="@layout/status_bar_expanded"
+    <com.android.systemui.statusbar.phone.PanelHolder
+        android:id="@+id/panel_holder"
         android:layout_width="match_parent"
-        android:layout_height="0dp"
-        />
+        android:layout_height="match_parent"
+        >
+        <include layout="@layout/status_bar_expanded"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            />
+        <ViewStub android:id="@+id/quick_settings_stub"
+            android:layout="@layout/quick_settings"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            />
+    </com.android.systemui.statusbar.phone.PanelHolder>
 
 </com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/layout/system_bar_notification_panel.xml b/packages/SystemUI/res/layout/system_bar_notification_panel.xml
index 48a188b..315639e 100644
--- a/packages/SystemUI/res/layout/system_bar_notification_panel.xml
+++ b/packages/SystemUI/res/layout/system_bar_notification_panel.xml
@@ -57,6 +57,7 @@
             android:id="@+id/notification_scroller"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
+            android:overScrollMode="ifContentScrolls"
             android:layout_weight="1"
             >
             <com.android.systemui.statusbar.policy.NotificationRowLayout
diff --git a/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml b/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml
index 480d979..59544f4 100644
--- a/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml
+++ b/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml
@@ -85,7 +85,7 @@
             </FrameLayout>
             <TextView
                 android:id="@+id/mobile_text"
-                style="@style/StatusBarNotificationText"
+                style="@style/SystemBarNotificationText"
                 android:layout_gravity="left|center_vertical"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
@@ -121,7 +121,7 @@
             </FrameLayout>
             <TextView
                 android:id="@+id/wifi_text"
-                style="@style/StatusBarNotificationText"
+                style="@style/SystemBarNotificationText"
                 android:layout_gravity="left|center_vertical"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
@@ -144,7 +144,7 @@
 
             <TextView
                 android:id="@+id/battery_text"
-                style="@style/StatusBarNotificationText"
+                style="@style/SystemBarNotificationText"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="left|center_vertical"
@@ -170,7 +170,7 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:src="@drawable/ic_sysbar_quicksettings"
-                    android:contentDescription="@string/accessibility_settings_button"
+                    android:contentDescription="@string/accessibility_desc_quick_settings"
                     />
 
                 <ImageView
@@ -202,7 +202,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:singleLine="true"
-            android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
+            android:textAppearance="@style/TextAppearance.SystemBar.Expanded.Clock"
             />
     
         <com.android.systemui.statusbar.policy.DateView
@@ -211,7 +211,7 @@
             android:layout_height="wrap_content"
             android:layout_marginLeft="8dp"
             android:layout_marginRight="8dp"
-            android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
+            android:textAppearance="@style/TextAppearance.SystemBar.Expanded.Date"
             />
 
         <Space
diff --git a/packages/SystemUI/res/layout/system_bar_recent_item.xml b/packages/SystemUI/res/layout/system_bar_recent_item.xml
index 7d639ec..b5f7da7 100644
--- a/packages/SystemUI/res/layout/system_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout/system_bar_recent_item.xml
@@ -37,6 +37,7 @@
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textColor="@color/status_bar_recents_app_label_color"
+        android:importantForAccessibility="no"
     />
 
     <FrameLayout android:id="@+id/app_thumbnail"
diff --git a/packages/SystemUI/res/layout/system_bar_recent_panel.xml b/packages/SystemUI/res/layout/system_bar_recent_panel.xml
index 127551d..3951bba 100644
--- a/packages/SystemUI/res/layout/system_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout/system_bar_recent_panel.xml
@@ -28,11 +28,6 @@
     android:clipChildren="false"
     systemui:recentItemLayout="@layout/system_bar_recent_item"
     >
-    <View
-        android:id="@+id/recents_transition_background"
-        android:layout_height="match_parent"
-        android:layout_width="match_parent"
-        android:visibility="invisible" />
     <FrameLayout
         android:id="@+id/recents_bg_protect"
         android:background="@drawable/recents_bg_protect_tile"
@@ -42,11 +37,6 @@
         android:layout_marginBottom="@*android:dimen/system_bar_height"
         android:clipToPadding="false"
         android:clipChildren="false">
-        <ImageView
-            android:id="@+id/recents_transition_placeholder_icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:visibility="invisible" />
 
         <com.android.systemui.recent.RecentsVerticalScrollView android:id="@+id/recents_container"
             android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/system_bar_settings_view.xml b/packages/SystemUI/res/layout/system_bar_settings_view.xml
index e1b2a54..d07e45d 100644
--- a/packages/SystemUI/res/layout/system_bar_settings_view.xml
+++ b/packages/SystemUI/res/layout/system_bar_settings_view.xml
@@ -26,16 +26,16 @@
     <!-- Airplane mode -->
     <LinearLayout
             android:id="@+id/airplane"
-            style="@style/StatusBarPanelSettingsRow"
+            style="@style/SystemBarPanelSettingsRow"
             >
         <ImageView
                 android:id="@+id/airplane_icon"
-                style="@style/StatusBarPanelSettingsIcon"
+                style="@style/SystemBarPanelSettingsIcon"
                 android:src="@drawable/ic_sysbar_airplane_on"
                 />
         <TextView
                 android:id="@+id/airplane_label"
-                style="@style/StatusBarPanelSettingsContents"
+                style="@style/SystemBarPanelSettingsContents"
                 android:text="@string/status_bar_settings_airplane"
                 />
         <Switch
@@ -46,39 +46,39 @@
                 android:layout_marginRight="5dp"
                 />
     </LinearLayout>
-    <View style="@style/StatusBarPanelSettingsPanelSeparator" />
+    <View style="@style/SystemBarPanelSettingsPanelSeparator" />
 
     <!-- Network -->
     <LinearLayout
             android:id="@+id/network"
-            style="@style/StatusBarPanelSettingsRow"
+            style="@style/SystemBarPanelSettingsRow"
             >
         <ImageView
                 android:id="@+id/network_icon"
-                style="@style/StatusBarPanelSettingsIcon"
+                style="@style/SystemBarPanelSettingsIcon"
                 android:src="@drawable/ic_sysbar_wifi_on"
                 />
         <TextView
                 android:id="@+id/network_label"
-                style="@style/StatusBarPanelSettingsContents"
+                style="@style/SystemBarPanelSettingsContents"
                 android:text="@string/status_bar_settings_wifi_button"
                 />
     </LinearLayout>
-    <View style="@style/StatusBarPanelSettingsPanelSeparator" />
+    <View style="@style/SystemBarPanelSettingsPanelSeparator" />
 
     <!-- Rotation lock -->
     <LinearLayout
             android:id="@+id/rotate"
-            style="@style/StatusBarPanelSettingsRow"
+            style="@style/SystemBarPanelSettingsRow"
             >
         <ImageView
                 android:id="@+id/rotate_icon"
-                style="@style/StatusBarPanelSettingsIcon"
+                style="@style/SystemBarPanelSettingsIcon"
                 android:src="@drawable/ic_sysbar_rotate_on"
                 />
         <TextView
                 android:id="@+id/rotate_label"
-                style="@style/StatusBarPanelSettingsContents"
+                style="@style/SystemBarPanelSettingsContents"
                 android:text="@string/status_bar_settings_auto_rotation"
                 />
         <Switch
@@ -91,13 +91,13 @@
     </LinearLayout>
     <View
             android:id="@+id/rotate_separator"
-            style="@style/StatusBarPanelSettingsPanelSeparator" />
+            style="@style/SystemBarPanelSettingsPanelSeparator" />
 
     <!-- Brightness -->
-    <LinearLayout style="@style/StatusBarPanelSettingsRow" >
+    <LinearLayout style="@style/SystemBarPanelSettingsRow" >
         <ImageView
                 android:id="@+id/brightness_icon"
-                style="@style/StatusBarPanelSettingsIcon"
+                style="@style/SystemBarPanelSettingsIcon"
                 android:src="@drawable/ic_sysbar_brightness"
                 />
         <com.android.systemui.statusbar.policy.ToggleSlider
@@ -109,20 +109,20 @@
                 systemui:text="@string/status_bar_settings_auto_brightness_label"
                 />
     </LinearLayout>
-    <View style="@style/StatusBarPanelSettingsPanelSeparator" />
+    <View style="@style/SystemBarPanelSettingsPanelSeparator" />
 
     <!-- Notifications / Do not disturb -->
     <LinearLayout
             android:id="@+id/do_not_disturb"
-            style="@style/StatusBarPanelSettingsRow"
+            style="@style/SystemBarPanelSettingsRow"
             >
         <ImageView
                 android:id="@+id/do_not_disturb_icon"
-                style="@style/StatusBarPanelSettingsIcon"
+                style="@style/SystemBarPanelSettingsIcon"
                 android:src="@drawable/ic_notification_open"
                 />
         <TextView
-                style="@style/StatusBarPanelSettingsContents"
+                style="@style/SystemBarPanelSettingsContents"
                 android:text="@string/status_bar_settings_notifications"
                 />
         <Switch
@@ -133,25 +133,25 @@
                 android:layout_marginRight="5dp"
                 />
     </LinearLayout>
-    <View style="@style/StatusBarPanelSettingsPanelSeparator" />
+    <View style="@style/SystemBarPanelSettingsPanelSeparator" />
 
     <!-- Link to settings -->
     <LinearLayout
             android:id="@+id/settings"
-            style="@style/StatusBarPanelSettingsRow"
+            style="@style/SystemBarPanelSettingsRow"
             >
 
         <ImageView
                 android:id="@+id/settings"
-                style="@style/StatusBarPanelSettingsIcon"
+                style="@style/SystemBarPanelSettingsIcon"
                 android:src="@drawable/ic_sysbar_quicksettings"
                 />
         <TextView
-                style="@style/StatusBarPanelSettingsContents"
+                style="@style/SystemBarPanelSettingsContents"
                 android:text="@string/status_bar_settings_settings_button"
                 />
     </LinearLayout>
-    <View style="@style/StatusBarPanelSettingsPanelSeparator" />
+    <View style="@style/SystemBarPanelSettingsPanelSeparator" />
 
 </com.android.systemui.statusbar.tablet.SettingsView>
 
diff --git a/packages/SystemUI/res/layout/universe.xml b/packages/SystemUI/res/layout/universe.xml
new file mode 100644
index 0000000..6102d2e
--- /dev/null
+++ b/packages/SystemUI/res/layout/universe.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent" android:layout_height="match_parent">
+    <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true" android:layout_alignParentTop="true"
+        android:src="@drawable/bugdroid" android:scaleType="center" />
+
+    <Button android:id="@+id/close"
+        android:layout_width="wrap_content" android:layout_height="wrap_content"
+        android:layout_alignParentTop="true" android:layout_alignParentRight="true"
+        android:text="@string/close_universe" />
+
+    <TextView android:id="@+id/title"
+        android:layout_width="match_parent" android:layout_height="wrap_content"
+        android:layout_below="@id/close" android:layout_centerHorizontal="true"
+        android:paddingBottom="16dp"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:gravity="center" />
+
+    <ImageView android:id="@+id/bottom"
+        android:layout_width="wrap_content" android:layout_height="wrap_content"
+        android:layout_below="@id/title" android:layout_centerHorizontal="true"
+        android:layout_marginTop="16dp" />
+</RelativeLayout>
diff --git a/packages/SystemUI/res/mipmap-hdpi/ic_daydreams.png b/packages/SystemUI/res/mipmap-hdpi/ic_daydreams.png
new file mode 100644
index 0000000..4779a09
--- /dev/null
+++ b/packages/SystemUI/res/mipmap-hdpi/ic_daydreams.png
Binary files differ
diff --git a/packages/SystemUI/res/mipmap-hdpi/ic_launcher_dreams.png b/packages/SystemUI/res/mipmap-hdpi/ic_launcher_dreams.png
new file mode 100644
index 0000000..37185f3
--- /dev/null
+++ b/packages/SystemUI/res/mipmap-hdpi/ic_launcher_dreams.png
Binary files differ
diff --git a/packages/SystemUI/res/mipmap-mdpi/ic_daydreams.png b/packages/SystemUI/res/mipmap-mdpi/ic_daydreams.png
new file mode 100644
index 0000000..b3a634d
--- /dev/null
+++ b/packages/SystemUI/res/mipmap-mdpi/ic_daydreams.png
Binary files differ
diff --git a/packages/SystemUI/res/mipmap-mdpi/ic_launcher_dreams.png b/packages/SystemUI/res/mipmap-mdpi/ic_launcher_dreams.png
new file mode 100644
index 0000000..1993b0d
--- /dev/null
+++ b/packages/SystemUI/res/mipmap-mdpi/ic_launcher_dreams.png
Binary files differ
diff --git a/packages/SystemUI/res/mipmap-xhdpi/ic_daydreams.png b/packages/SystemUI/res/mipmap-xhdpi/ic_daydreams.png
new file mode 100644
index 0000000..50b1f50
--- /dev/null
+++ b/packages/SystemUI/res/mipmap-xhdpi/ic_daydreams.png
Binary files differ
diff --git a/packages/SystemUI/res/mipmap-xhdpi/ic_launcher_dreams.png b/packages/SystemUI/res/mipmap-xhdpi/ic_launcher_dreams.png
new file mode 100644
index 0000000..c92b681
--- /dev/null
+++ b/packages/SystemUI/res/mipmap-xhdpi/ic_launcher_dreams.png
Binary files differ
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index a24a4d7..89a8dd7 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Sien"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gebruik by verstek vir hierdie USB-toestel"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gebruik by verstek vir hierdie USB-toebehoorsel"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Laat USB-ontfouting toe?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Die rekenaar se RSA-sleutel-vingerafdruk is:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Laat altyd toe van hierdie rekenaar af"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoem om skerm te vul"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Strek om skerm te vul"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Versoenbaarheidszoem"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Data, twee stawe."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Data, drie stawe."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Datasein vol."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Geen Wi-Fi nie."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi een strepie."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi twee strepies."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi drie strepies."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Wi-Fi-sein vol."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi af."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi is ontkoppel."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi een staaf."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi twee stawe."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi drie stawe."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wi-Fi-sein vol."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Geen WiMAX nie."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX een strepie."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX twee strepies."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX drie strepies."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX-sein vol."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Geen sein nie."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Nie gekoppel nie."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Geen stawe."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Een staaf."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Twee stawe."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Drie stawe."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Sein vol."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Aan."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Af"</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Gekoppel."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Swerwing"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Geen SIM nie."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Luitoestel-vibreer."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Luitoestel stil."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> verwerp."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Kennisgewing is toegemaak."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Kennisgewingskerm."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Vinnige instellings."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Onlangse programme."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Gebruiker <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobiele <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Battery <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Vliegtuigmodus <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Wekker gestel vir <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G-data gedeaktiveer"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G data gedeaktiveer"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobieldata gedeaktiveer"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Soek vir GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Ligging deur GPS gestel"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Verwyder alle kennisgewings."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktiveer sluimerskerm"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Programinligting"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Maak toe"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Kennisgewings af"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Tik hier om kennisgewings weer aan te skakel."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Die skerm sal outomaties draai."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skerm is in landskapsoriëntasie gesluit."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skerm is in portretoriëntasie gesluit."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Sluimer"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Vliegtuigmodus"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Laai, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Gelaai"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> toestelle)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth af"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Helderheid"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Outoroteer"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotasie gesluit"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Invoermetode"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Ligging in gebruik"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Mediatoestel"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Net noodoproepe"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Instellings"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Tyd"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Ek"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nie gekoppel nie"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Geen netwerk nie"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi af"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi-skerm"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Draadlose aansig"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Helderheid"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OUTO"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Kennisgewings verskyn hier"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Verkry enige tyd toegang tot hulle deur af te sleep."\n"Sleep weer af vir stelselkontroles."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 7c2956c..da77625 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -26,7 +26,7 @@
     <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_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>
@@ -56,8 +56,11 @@
     <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>
-    <string name="always_use_accessory" msgid="1210954576979621596">"ለዚህ USB  ተቀጥላ በነባሪነት ተጠቀም"</string>
+    <string name="always_use_device" msgid="1450287437017315906">"ለእዚህ USB  መሣሪያ በነባሪነት ተጠቀም"</string>
+    <string name="always_use_accessory" msgid="1210954576979621596">"ለእዚህ USB  ተቀጥላ በነባሪነት ተጠቀም"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"የUSB ማረሚያ ይፈቀድ?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"የኮምፒውተሩ RSA ቁልፍ ጣት አሻራ ይሄ ነው፦"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"ሁልጊዜ ከዚህ ኮምፒውተር ፍቀድ"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"ማያ እንዲሞላ አጉላ"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ማያ ለመሙለት ሳብ"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"የተኳኋኝነት አጉላ"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"የውሂብ ሁለት አሞሌዎች።"</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"የውሂብ ሦስት አሞሌዎች።"</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"የውሂብ አመልካች ሙሉ ነው።"</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"ምንም የWi-Fi የለም::"</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi አንድ አሞሌ::"</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi ሁለት አሞሌዎች::"</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi ሶስት አሞሌዎች::"</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"የWiFi  አመልካች ሙሉ ነው።"</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi ጠፍቷል።"</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"የWifi ግንኙነት ተቋርጧል።"</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"አንድ የWiFi አሞሌ።"</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"ሁለት የWiFi አሞሌዎች።"</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"ሦስት የWiFi አሞሌዎች።"</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"የWiFi ምልክት ሙሉ ነው።"</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"ምንም WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX አንድ አሞሌ።"</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX ሁለት አሞሌዎች።"</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX ሦስት አሞሌዎች።"</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX አመልካች ሙሉ ነው።"</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"ምንም ምልክት የለም።"</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"አልተገናኘም።"</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"ዜሮ አሞሌዎች።"</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"አንድ አሞሌ።"</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"ሁለት አሞሌዎች።"</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"ሶስት አሞሌዎች።"</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"ምልክት ሙሉ ነው።"</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"በርቷል።"</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"ጠፍቷል።"</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"ተገናኝቷል።"</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"ውሂብን በማዛወር ላይ"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"ምንም SIM የለም።"</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"የስልክ ጥሪ ይንዘር።"</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"የስልክ ጥሪ ፀጥታ።"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ተሰናብቷል::"</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"ማሳወቂያ ተወግዷል።"</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"የማሳወቂያ ጥላ።"</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"ፈጣን ቅንብሮች።"</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"የቅርብ ጊዜ መተግበሪያዎች።"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"ተጠቃሚ <xliff:g id="USER">%s</xliff:g>።"</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>። <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"ተንቀሳቃሽ ስልክ <xliff:g id="SIGNAL">%1$s</xliff:g>። <xliff:g id="TYPE">%2$s</xliff:g>። <xliff:g id="NETWORK">%3$s</xliff:g>።"</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"ባትሪ <xliff:g id="STATE">%s</xliff:g>።"</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"የአውሮፕላን ሁነታ <xliff:g id="STATE">%s</xliff:g>።"</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"ብሉቱዝ <xliff:g id="STATE">%s</xliff:g>።"</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"ማንቂያ ለ<xliff:g id="TIME">%s</xliff:g> ተዋቅሯል።"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G ውሂብ ቦዝኗል"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G ውሂብ ቦዝኗል"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"የተንቀሳቃሽ ውሂብ ቦዝኗል"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"ለGPS በመፈለግ ላይ"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"በ GPS የተዘጋጀ ሥፍራ"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"ሁሉንም ማሳወቂያዎች አጽዳ"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">" ገፁማያ ማቆያ አንቃ"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"የመተግበሪያ መረጃ"</string>
+    <string name="close_universe" msgid="3736513750241754348">"ዝጋ"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"ማሳወቂያዎች ጠፍተዋል"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"ማስታወቅያዎችን መልሶ ለማብራት እዚህ ጋር መታ አድርግ።"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ማያ ገጽ በራስ ሰር ይዞራል።"</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"ማያ ገጽ በወርድ ገፅ አቀማመጥ ተቆልፏል።"</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"ማያ ገጽ በቁም ገፅ አቀማመጥ ተቆልፏል።"</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"የቀን ህልም"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"ኤተርኔት"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"የአውሮፕላን ሁነታ"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"ባትሪ በመሙላት ላይ፣ <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"ባትሪ ሞልቷል።"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ብሉቱዝ"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ብሉቱዝ (<xliff:g id="NUMBER">%d</xliff:g> መሣሪያዎች)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ብሉቱዝ ጠፍቷል"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"ብሩህነት"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"ራስ-አዙር"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"አዙሪት ተቆልፏል"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"የግቤት ዘዴ"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"በስራ ላይ ያለው አካባቢ"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"የሚዲያ መሣሪያ"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"የአደጋ ጊዜ ጥሪዎች ብቻ"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"ቅንብሮች"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"ሰዓት"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"እኔ"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"አልተገናኘም"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ምንም አውታረ መረብ የለም"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ጠፍቷል"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"የWi-Fi ማሳያ"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"ገመድ አልባ ማሳያ"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"ብሩህነት"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ራስ-ሰር"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"ማሳወቂያዎች እዚህ ላይ ይታያሉ"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"ወደ ታች በማንሸራተት በማንኛውም ጊዜ ይድረሱባቸው።"\n"Swipe የስርዓት መቆጣጠሪያዎችን ለማምጣት እንደገና ወደ ታች ያንሸራትቱ።"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index b2c9ab0..c40e26d 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"عرض"</string>
     <string name="always_use_device" msgid="1450287437017315906">"الاستخدام بشكل افتراضي لجهاز USB هذا"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"الاستخدام بشكل افتراضي لملحق USB هذا"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"هل تريد السماح بتصحيح أخطاء USB؟"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"الملف المرجعي الرئيسي لـ RSA في هذا الكمبيوتر هو:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"السماح دائمًا من هذا الكمبيوتر"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"تكبير/تصغير لملء الشاشة"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"توسيع بملء الشاشة"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"تكبير/تصغير التوافق"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"إشارة البيانات تتكون من شريطين."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"إشارة البيانات تتكون من ثلاثة أشرطة."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"إشارة البيانات كاملة."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"ليس هناك اتصال Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"شريط واحد لـ Wi-Fi."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"شريطان لـ Wi-Fi."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"ثلاثة أشرطة لـ Wi-Fi."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"إشارة WiFi كاملة."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"تم إيقاف Wifi."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"تم قطع اتصال Wifi."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"إشارة WiFi تتكون من شريط واحد."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"إشارة WiFi تتكون من شريطين."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"إشارة WiFi تتكون من ثلاثة أشرطة."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"إشارة WiFi كاملة."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"ليس هناك WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"شريط WiMAX واحد."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"شريطا WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"أشرطة WiMAX الثلاثة."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"إشارة WiMAX كاملة."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"ليست هناك إشارة."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"غير متصل."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"ليست هناك أشرطة."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"شريط واحد."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"شريطان."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"ثلاثة أشرطة."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"الإشارة كاملة."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"تم التشغيل."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"تم الإيقاف."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"متصل."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1‎ X‎"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"شبكة الجيل الثالث"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"شبكة 3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"شبكة الجيل الرابع"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"تجوال"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"ليست هناك بطاقة SIM."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"رنين مع الاهتزاز."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"رنين صامت."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"تمت إزالة <xliff:g id="APP">%s</xliff:g>."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"تم تجاهل الإشعار."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"مركز الإشعارات."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"الإعدادات السريعة."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"التطبيقات الحديثة"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"المستخدم <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"الجوال <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"البطارية <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"وضع الطائرة <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"البلوتوث <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"تم ضبط المنبه على <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"تم تعطيل بيانات شبكات الجيل الثاني والجيل الثالث"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"تم تعطيل بيانات شبكة الجيل الرابع"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"تم تعطيل بيانات الجوال"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"جارٍ البحث عن GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"تم تعيين الموقع بواسطة GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"محو جميع الإشعارات."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"تنشيط شاشة التوقف"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"معلومات التطبيق"</string>
+    <string name="close_universe" msgid="3736513750241754348">"إغلاق"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"التنبيهات معطّلة"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"انقر هنا لإعادة تشغيل الإشعارات."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"سيتم تدوير الشاشة تلقائيًا."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"تم تأمين الشاشة في الاتجاه الأفقي."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"تم تأمين الشاشة في الاتجاه العمودي."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"حلم اليقظة"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"وضع الطائرة"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"جارٍ الشحن، <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"تم الشحن"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"بلوتوث"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"بلوتوث (<xliff:g id="NUMBER">%d</xliff:g> من الأجهزة)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"إيقاف البلوتوث"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"السطوع"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"تدوير تلقائي"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"تم قفل التدوير"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"أسلوب الإدخال"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"الموقع المستخدم"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"جهاز الوسائط"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"مكالمات الطوارئ فقط"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"الإعدادات"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"الوقت"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"أنا"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"ليست متصلة"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"لا تتوفر شبكة"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"إيقاف Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"عرض Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"عرض شاشة لاسلكي"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"السطوع"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"تلقائي"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"تظهر الإشعارات هنا"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"يمكنك الدخول إليها في أي وقت بالتمرير السريع إلى أسفل."\n"يمكنك التمرير السريع إلى أسفل مرة أخرى للوصول إلى عناصر تحكم النظام."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index c4af8d8..c66e912 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Прагляд"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Выкарыстоўваць налады па змаўчанні для дадзенай USB-прылады"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Выкарыстоўваць налады па змаўчанні для дадзенай USB-прылады"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Дазволіць адладку USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Адбiтак ключа RSA на гэтым камп\'ютары:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Заўсёды дазваляць з гэтага камп\'ютара"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Павял. на ўвесь экран"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Расцягн. на ўвесь экран"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Маштабаванне для сумяшчальнасцi"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"2 планкі дадзеных."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"3 планкі дадзеных."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Поўны сігнал перадачы дадзеных."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Wi-Fi адсутнiчае."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi, адзiн слупок."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi, два слупкi."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi, тры слупкi."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Поўны сігнал Wi-Fi."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi выключаны."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi адключаны."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Адзiн слупок Wi-Fi."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Два слупкi Wi-Fi."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Тры слупкi Wi-Fi."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Поўны сігнал Wi-Fi."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Няма сiгналу WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Адзiн слупок сiгналу WiMAX."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Два слупкi сiгналу WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Тры слупкi сiгналу WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Моцны сiгнал WiMAX."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Няма сігналу."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Няма падключэння."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Няма."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Адзiн слупок."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Два слупкi."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Тры слупкi."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Сігнал поўны."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Уключана."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Адключана."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Падключана."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Роўмінг"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Няма SIM-карты."</string>
@@ -129,6 +146,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Выклік з вібрацыяй."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Маўклівы выклік."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> выдалены."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Апавяшчэнне прапушчана."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Цень апавяшчэння.."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Хуткія налады."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Апошнія прыкладанні."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Карыстальнік: <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Мабiльны сiгнал: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Акумулятар: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Рэжым палёту: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Наладжаны будзiльнiк: <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Дадзеныя 2G-3G адключаныя"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Дадзеныя 4G адключаныя"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Мабільная перадача дадзеных адключаная"</string>
@@ -140,11 +168,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Пошук GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Месца задана праз GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Выдалiць усе апавяшчэннi."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Актывацыя экраннай застаўкі"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Інфармацыя пра прыкладанне"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Закрыць"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Паведамленні адключаны"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Націсніце тут, каб зноў уключыць апавяшчэнні."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Экран паварочваецца аўтаматычна."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Экран заблакiраваны ў альбомнай арыентацыі."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Экран заблакiраваны ў партрэтнай арыентацыі."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Мроi"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Рэжым палёту"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Зарадка, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Зараджана"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (прылады: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth выключаны"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Яркасць"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Аўтапаварот"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Паварот забаронены"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Метад уводу"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Месцазнаходжанне выкарыстоўваецца"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Мультымедыйная прылада"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Толькі экстраныя выклікі"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Налады"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Час"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Я"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Няма падключэння"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Няма сеткi"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi адключаны"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Дысплей Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Бесправадны дысплей"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Яркасць"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АЎТА"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Апавяшчэнні з\'яўляюцца тут"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Атрымлівайце доступ да іх у любы час, праводзячы пальцам уніз."\n"Правядзіце пальцам уніз яшчэ раз, каб атрымаць доступ да сродкаў кіравання сістэмай."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index a4a0e78..e3f7dc1 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Преглед"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Използване по подразб. за това USB устройство"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Използване по подразб. за този аксесоар за USB"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Да се разреши ли отстраняването на грешки през USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Отпечатъкът на RSA ключа на компютъра е:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Винаги да се разрешава от този компютър"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Мащаб – запълва екрана"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Разпъване – запълва екрана"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Промяна на мащаба за съвместимост"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Данните са с две чертички."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Данните са с три чертички."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Сигналът за данни е пълен."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Няма Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi е с една чертичка."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi е с две чертички."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi е с три чертички."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Сигналът за WiFi е пълен."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi е изключен."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Няма връзка с Wi-Fi."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi е с една чертичка."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi е с две чертички."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi е с три чертички."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Сигналът за Wi-Fi е пълен."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Няма WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX е с една чертичка."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX е с две чертички."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX е с три чертички."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Сигналът за WiMAX е пълен."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Няма сигнал."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Няма връзка."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Нула чертички."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Една чертичка."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Две чертички."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Три чертички."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Сигналът е пълен."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Вкл."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Изкл."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Има връзка."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Роуминг"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Няма SIM карта."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Вибрира при звънене."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Звънът е заглушен."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Приложението <xliff:g id="APP">%s</xliff:g> е отхвърлено."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Известието е отхвърлено."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Падащ панел с известия."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Бързи настройки."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Скорошни приложения."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Потребител: <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Мобилно устройство: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Батерия: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Самолетен режим: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Будилникът е навит за <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G данните са деактивирани"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G данните са деактивирани"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Мобилните данни са деактивирани"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Търси се GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Местоположението е зададено от GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Изчистване на всички известия."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Активиране на скрийнсейвъра"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Информация за приложението"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Затваряне"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Известията са изключени"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Докоснете тук, за да включите отново известията."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екранът ще се завърта автоматично."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Екранът е заключен в хоризонтална ориентация."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Екранът е заключен във вертикална ориентация."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Мечта"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Самолетен режим"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Зарежда се, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Заредена"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> устройства)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth е изключен"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Яркост"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Автоматична ориентация"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Ориентацията е заключена"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Метод на въвеждане"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Използвано местоположение"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Мултимедийно устройство"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"Индикатор за силата на получения сигнал (RSSI)"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Само спешни обаждания"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Настройки"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Време"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Аз"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Няма връзка"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Няма мрежа"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi е изключен"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Дисплей през Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Безжичен дисплей"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Яркост"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТ."</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Известията се показват тук"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Осъществявайте достъп до тях по всяко време, като прекарате пръст надолу."\n"Направете го отново за системните контроли."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 5a2c9cd..8c2dd8e 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -44,9 +44,9 @@
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mode d\'avió"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Gira pantalla automàticament"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"Silen."</string>
-    <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
+    <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificacions"</string>
-    <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth sense fil"</string>
+    <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth ancorat"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configura els mètodes d\'entrada"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclat físic"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"Vols permetre que l\'aplicació <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi al dispositiu USB?"</string>
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Mostra"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utilitza de manera predet. per al dispositiu USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utilitza de manera predet. per a l\'accessori USB"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Vols permetre la depuració USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"L\'empremta digital de la clau de l\'RSA de l\'equip és:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Dóna sempre permís des d\'aquest equip"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom per omplir pantalla"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Estira per omplir pant."</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilitat"</string>
@@ -97,25 +100,39 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Senyal de dades: dues barres."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Senyal de dades: tres barres."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Senyal de dades: complet."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"No hi ha Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Una barra de Wi-Fi."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Dues barres de Wi-Fi."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Tres barres de Wi-Fi."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Senyal Wi-Fi: complet."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi desactivada."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi desconnectada."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Senyal Wi-Fi: una barra."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Senyal Wi-Fi: dues barres."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Senyal Wi-Fi: tres barres."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Senyal Wi-Fi: complet."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Sense WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Una barra de WiMAX."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Dues barres de WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Tres barres de WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Senyal de WiMAX plena."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Sense senyal."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Sense connexió."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Cap barra."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Una barra."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Dues barres."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Tres barres."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Senyal complet."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Activat."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Desactivat."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Connectat."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Itinerància"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Vora"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"No hi ha cap targeta SIM."</string>
-    <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Connexió Bluetooth mitjançant dispositiu portàtil"</string>
+    <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Ancoratge de Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Mode d\'avió."</string>
     <!-- String.format failed for translation -->
     <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
@@ -129,6 +146,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Mode vibració."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Mode silenci."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"S\'ha omès <xliff:g id="APP">%s</xliff:g>."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificació omesa."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Capa de notificació."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Configuració ràpida."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Aplicacions recents."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Usuari <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mòbil <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Bateria <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Mode d\'avió <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarma establerta a les <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Dades 2G-3G desactivades"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Dades 4G desactivades"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Dades mòbils desactivades"</string>
@@ -140,11 +168,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"S\'està cercant un GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"S\'ha establert la ubicació per GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Esborra totes les notificacions."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activa el protector de pantalla"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informació de l\'aplicació"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Tanca"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notificacions desactivades"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Pica aquí per tornar a activar les notificacions."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girarà automàticament."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"La pantalla està bloquejada en orientació horitzontal."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"La pantalla està bloquejada en orientació vertical."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Estalvi de pantalla"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode d\'avió"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"S\'està carregant, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Carregada"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositius)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desactivat"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brillantor"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Rotació automàtica"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotació bloquejada"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Mètode d\'entrada"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Ubicació en ús"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Dispositiu multimèdia"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Només trucades d\'emergència"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Configuració"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Hora"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Jo"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Desconnectat"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No hi ha cap xarxa"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desconnectada"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Pantalla Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Pantalla sense fil"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brillantor"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÀTICA"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Les notificacions apareixen aquí"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Accedeix-hi en qualsevol moment: només has de fer lliscar el dit cap avall."\n"Torna a fer lliscar el dit cap avall per fer que es mostrin els controls del sistema."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 2d1f644..a623612 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Zobrazit"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Pro toto zařízení USB použít jako výchozí"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Pro toto periferní zařízení USB použít jako výchozí"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Povolit ladění USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Digitální otisk RSA počítače je:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Vždy povolit z tohoto počítače"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Přiblížit na celou obrazovku"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Na celou obrazovku"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Úprava velikosti z důvodu kompatibility"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Dvě čárky signálu datové sítě."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Tři čárky signálu datové sítě."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Plný signál datové sítě."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Žádná síť Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi – jedna čárka."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi – dvě čárky."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi – tři čárky."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Plný signál sítě Wi-Fi."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Síť Wi-Fi je vypnuta."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Síť Wi-Fi odpojena."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Jedna čárka signálu sítě Wi-Fi."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Dvě čárky signálu sítě Wi-Fi."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Tři čárky signálu sítě Wi-Fi."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Plný signál sítě Wi-Fi."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Žádný signál sítě WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Jedna čárka signálu sítě WiMAX."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Dvě čárky signálu sítě WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Tři čárky signálu sítě WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Plný signál sítě WiMAX."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Není signál."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Nepřipojeno."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Žádná čárka."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Jedna čárka."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Dvě čárky."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Tři čárky."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Plný signál."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Zapnuto."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Vypnuto."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Připojeno."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Žádná SIM karta."</string>
@@ -129,6 +146,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Vibrační vyzvánění."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Tiché vyzvánění."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikace <xliff:g id="APP">%s</xliff:g> byla odebrána."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Oznámení je zavřeno."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Panel oznámení."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Rychlé nastavení."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Naposledy použité aplikace"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Uživatel <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobil: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Baterie: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Režim V letadle: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Budík je nastaven na <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Datové přenosy 2G a 3G jsou zakázány"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Datové přenosy 4G jsou zakázány"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobilní data jsou zakázána"</string>
@@ -140,11 +168,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Vyhledávání satelitů GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Poloha nastavena pomocí systému GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazat všechna oznámení."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivovat spořič obrazovky"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informace o aplikaci"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Zavřít"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Oznámení jsou vypnuta"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Chcete-li oznámení znovu zapnout, klepněte sem."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Obrazovka se automaticky otočí."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Obrazovka je uzamčena v orientaci na šířku."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Obrazovka je uzamčena v orientaci na výšku."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Spořič obrazovky"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Režim V letadle"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Nabíjení, <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Nabito"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> zařízení)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Rozhraní Bluetooth je vypnuto"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Jas"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Automatické otáčení"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Otáčení je uzamčeno"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Metoda zadávání dat"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Používaná poloha"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Mediální zařízení"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Pouze tísňová volání"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Nastavení"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Doba"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Já"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nepřipojeno"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Žádná síť"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi vypnuta"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Displej přes Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Bezdrátový displej"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Jas"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATICKY"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Zde se zobrazují oznámení"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Můžete je kdykoli zobrazit tím, že přejedete prstem dolů."\n"Přejedete-li prstem dolů ještě jednou, zobrazí se ovládací prvky systému."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 01068ec..7f7a51c 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Vis"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Brug som standard til denne USB-enhed"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Brug som standard til dette USB-tilbehør"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Vil du tillade USB-fejlretning?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Fingeraftrykket for computerens RSA-nøgle er:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Tillad altid fra denne computer"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom til fuld skærm"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Stræk til fuld skærm"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitetszoom"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Data to bjælker."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Data tre bjælker."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Datasignal fuldt."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Intet Wi-Fi-signal."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi har en bjælke."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi har to bjælker."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi har tre bjælker."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Wi-Fi-signal fuldt."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi slået fra."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi er afbrudt."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi én bjælke."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi to bjælker."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi tre bjælker."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wi-Fi fuldt signal."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Ingen WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX en bjælke."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX to bjælker."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX tre bjælker."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX-signal er fuldt."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Intet signal."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Ikke tilsluttet."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Nul bjælker."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Én bjælke."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"To bjælker."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Tre bjælker."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Fuldt signal."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Til."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Fra."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Forbundet."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Intet SIM-kort."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Ringervibration."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Lydløs."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> er annulleret."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Underretningen er annulleret."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Underretningspanel."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Hurtige indstillinger."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Seneste apps"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Bruger <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobil <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batteri <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Flytilstand <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarmen er indstillet til <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G-data er deaktiveret"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G-data er deaktiveret"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobildata er deaktiveret"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Søger efter GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Placeringen er angivet ved hjælp af GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ryd alle meddelelser."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivér pauseskærm"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Oplysninger om appen"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Luk"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Underretninger slået fra"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Tryk her for at slå underretninger til igen."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skærmen roterer automatisk."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skærmen er nu låst i liggende retning."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skærmen er nu låst i stående retning."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Dagdrøm"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flytilstand"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Oplader, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Opladet"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> enheder)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth slået fra"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Lysstyrke"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Automatisk rotation"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotation er låst"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Inputmetode"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Placering i brug"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Medieenhed"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Kun nødopkald"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Indstillinger"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Tid"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Mig"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ikke forbundet"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Intet netværk"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi slået fra"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Display"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Trådløs skærm"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Lysstyrke"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Underretninger vises her"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Få adgang til dem når som helst ved at stryge ned."\n"Stryg ned igen for at komme til systemindstillingerne."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 011d3a3..2b226b6 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Anzeigen"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Standardmäßig für dieses USB-Gerät verwenden"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Standardmäßig für dieses USB-Zubehör verwenden"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"USB-Debugging zulassen?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Der Fingerabdruck des RSA-Schlüssels für diesen Computer lautet: "\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Von diesem Computer immer zulassen"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom auf Bildschirmgröße"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Auf Bildschirmgröße anpassen"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitätszoom"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Datensignal - zwei Balken"</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Datensignal - drei Balken"</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Volle Datensignalstärke"</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Kein WLAN"</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"WLAN, ein Balken"</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"WLAN, zwei Balken"</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"WLAN, drei Balken"</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Volle WLAN-Signalstärke"</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"WLAN: aus"</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"WLAN getrennt"</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"WLAN: ein Balken"</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"WLAN: zwei Balken"</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"WLAN: drei Balken"</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Volle WLAN-Signalstärke"</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Kein WiMAX"</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX - ein Balken"</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX - zwei Balken"</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX - drei Balken"</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Volle WiMAX-Signalstärke"</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Kein Signal"</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Nicht verbunden"</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Kein Balken"</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Ein Balken"</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Zwei Balken"</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Drei Balken"</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Volle Signalstärke"</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"An"</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Aus"</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Verbunden"</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"WLAN"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Keine SIM-Karte"</string>
@@ -129,9 +146,20 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Klingeltonmodus \"Vibration\""</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Klingelton lautlos"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> entfernt"</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Benachrichtigung geschlossen"</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Benachrichtigungsleiste"</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Schnelleinstellungen"</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Kürzlich geöffnete Apps"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Nutzer: <xliff:g id="USER">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>, <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobilfunkverbindung: <xliff:g id="SIGNAL">%1$s</xliff:g>, <xliff:g id="TYPE">%2$s</xliff:g>, <xliff:g id="NETWORK">%3$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Akku: <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Flugmodus: <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Wecker gestellt für <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-/3G-Daten deaktiviert"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G-Daten deaktiviert"</string>
-    <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobile Daten deaktiviert"</string>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobilfunk Daten deaktiviert"</string>
     <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"Daten deaktiviert"</string>
     <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"Sie haben die angegebenen Grenze für den Datenverbrauch erreicht."\n\n"Wenn Sie die Datennutzung erneut aktivieren, berechnet Ihr Mobilfunkanbieter unter Umständen zusätzliche Gebühren."</string>
     <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"Daten erneut aktivieren"</string>
@@ -140,11 +168,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS wird gesucht"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Standort durch GPS festgelegt"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Alle Benachrichtigungen löschen"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Bildschirmschoner aktivieren"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"App-Details"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Schließen"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Benachrichtigungen aus"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Tippen Sie hier, um die Benachrichtigungen wieder zu aktivieren."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Bildschirm wird automatisch gedreht."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Bildschirm bleibt im Querformat."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Bildschirm bleibt im Hochformat."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flugmodus"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Lädt, <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Aufgeladen"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Geräte)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth aus"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Helligkeit"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Autom. drehen"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Drehung gesperrt"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Eingabemethode"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Verwendeter Standort"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Mediengerät"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Nur Notrufe"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Einstellungen"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Uhrzeit"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Ich"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"WLAN"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nicht verbunden"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Kein Netz"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"WLAN aus"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"WLAN-Display"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Kabellose Übertragung"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Helligkeit"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Benachrichtigungen erscheinen hier"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Greifen Sie jederzeit auf sie zu, indem Sie nach unten wischen."\n"Wischen Sie für Systemeinstellungen erneut nach unten."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 0b87777..abe6082 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Προβολή"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Χρήση από προεπιλογή για αυτή τη συσκευή USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Χρήση από προεπιλογή για αυτό το εξάρτημα USB"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Να επιτρέπεται ο εντοπισμός σφαλμάτων USB;"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Το μοναδικό χαρακτηριστικό του κλειδιού RSA είναι:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Να επιτρέπεται πάντα από αυτόν τον υπολογιστή"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Ζουμ σε πλήρη οθόνη"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Προβoλή σε πλήρη οθ."</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Ζουμ για συμβατότητα"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Δύο γραμμές δεδομένων."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Τρεις γραμμές δεδομένων."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Πλήρες σήμα δεδομένων."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Δεν υπάρχει σήμα Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Μία γραμμή Wi-Fi."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Δύο γραμμές Wi-Fi."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Τρεις γραμμές Wi-Fi."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Πλήρες σήμα WiFi."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi ανενεργό."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Το Wifi έχει αποσυνδεθεί."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Μία γραμμή WiFi."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Δύο γραμμές WiFi."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Τρεις γραμμές WiFi."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Πλήρες σήμα WiFi."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Δεν υπάρχει σήμα WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Σήμα WiMAX μία γραμμή."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Σήμα WiMAX δύο γραμμές."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Σήμα WiMAX τρεις γραμμές."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Πλήρες σήμα WiMAX."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Δεν υπάρχει σήμα."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Δεν έχει συνδεθεί."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Μηδέν γραμμές."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Μία γραμμή."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Δύο γραμμές."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Τρεις γραμμές."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Πλήρες σήμα."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Ενεργό."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Ανενεργό."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Έχει συνδεθεί."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Περιαγωγή"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Δεν υπάρχει SIM."</string>
@@ -129,6 +146,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Δόνηση ειδοποίησης ήχου."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Ειδοποίηση ήχου στο αθόρυβο."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Απορρίφθηκαν <xliff:g id="APP">%s</xliff:g>."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Η ειδοποίηση έχει απορριφθεί."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Πλαίσιο σκίασης ειδοποιήσεων."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Γρήγορες ρυθμίσεις."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Πρόσφατες εφαρμογές"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Χρήστης <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Κινητό <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Μπαταρία <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Λειτουργία πτήσης <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Το ξυπνητήρι έχει οριστεί στις <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Τα δεδομένα 2G-3G απενεργοποιήθηκαν"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Τα δεδομένα 4G απενεργοποιήθηκαν"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Τα δεδομένα κινητής τηλεφωνίας απενεργοποιήθηκαν"</string>
@@ -140,11 +168,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Αναζήτηση για GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Ρύθμιση τοποθεσίας με GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Εκκαθάριση όλων των ειδοποιήσεων."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ενεργοποίηση προφύλαξης οθόνης"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Πληροφορίες εφαρμογής"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Κλείσιμο"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Ειδοποιήσεις ανενεργές"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Πατήστε εδώ για να ενεργοποιήσετε ξανά τις ειδοποιήσεις."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Θα γίνεται αυτόματη περιστροφή της οθόνης."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Η οθόνη έχει κλειδωθεί σε οριζόντιο προσανατολισμό."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Η οθόνη έχει κλειδωθεί σε κατακόρυφο προσανατολισμό."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Λειτουργία πτήσης"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Φόρτιση, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Χρεώθηκε"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> συσκευές)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Απενεργοποιημένο Bluetooth"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Φωτεινότητα"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Αυτόματη περιστροφή"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Η περιστροφή είναι κλειδωμένη"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Μέθοδος εισαγωγής"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Τοποθεσία σε χρήση"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Συσκευή μέσων"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Μόνο κλήσεις έκτακτης ανάγκης"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Ρυθμίσεις"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Ώρα"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Εγώ"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Μη συνδεδεμένο"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Κανένα δίκτυο"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ανενεργό"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Οθόνη Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Ασύρματη οθόνη"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Φωτεινότητα"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ΑΥΤΟΜΑΤΗ"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Οι ειδοποιήσεις εμφανίζονται εδώ"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Μεταβείτε σε αυτές ανά πάσα στιγμή σύροντας προς τα κάτω."\n"Σύρετε ξανά προς τα κάτω για τα στοιχεία ελέγχου συστήματος."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index f02d09ca..890e05e 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"View"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Use by default for this USB device"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Use by default for this USB accessory"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Allow USB debugging?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"The computer\'s RSA key fingerprint is:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Always allow from this computer"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Stretch to fill screen"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Compatibility zoom"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Data two bars."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Data three bars."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Data signal full."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"No Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi one bar."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi two bars."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi three bars."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Wi-Fi signal full."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi off."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wifi disconnected."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wifi one bar."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wifi two bars."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wifi three bars."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wifi signal full."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"No WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX one bar."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX two bars."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX three bars."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX signal full."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"No signal."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Not connected."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Zero bars."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"One bar."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Two bars."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Three bars."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Signal full."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"On."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Off."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Connected."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"No SIM."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Ringer vibrate."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Ringer silent."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> dismissed."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification dismissed."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Notification shade."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Quick settings."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Recent apps"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"User <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobile <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Battery <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Aeroplane Mode <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm set for <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G data disabled"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G data disabled"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobile data disabled"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Searching for GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Location set by GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Clear all notifications."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activate screen saver"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"App info"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Close"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notifications off"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Tap here to turn notifications back on."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Screen will rotate automatically."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Screen is locked in landscape orientation."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Screen is locked in portrait orientation."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Aeroplane mode"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Charging, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Charged"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Devices)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Off"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brightness"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Auto Rotate"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotation Locked"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Input Method"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Location in use"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Media device"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Emergency Calls Only"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Settings"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Time"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Me"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Not Connected"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No Network"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Off"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Display"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Wireless Display"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brightness"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Notifications appear here"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Access them any time by swiping down."\n"Swipe down again for system controls."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index be2bf6e..d619de1 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Ver"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Se usa de forma predeterminada para este dispositivo USB."</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Se usa de forma predeterminada para este accesorio USB."</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"¿Permitir depuración de USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"La huella digital de tu clave RSA es:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Permitir siempre desde esta computadora"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para ocupar la pantalla"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Estirar p/ ocupar la pantalla"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilidad"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Dos barras de datos"</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Tres barras de datos"</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Señal de datos completa"</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Sin conexión Wi-Fi"</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Una barra de señal Wi-Fi"</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Dos barras de señal Wi-Fi"</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Tres barras de señal Wi-Fi"</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Señal de Wi-Fi completa"</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi desactivado"</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi desconectado"</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Una barra de Wi-Fi"</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Dos barras de Wi-Fi"</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Tres barras de Wi-Fi"</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Señal de Wi-Fi excelente"</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Sin conexión WiMAX"</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Una barra de WiMAX"</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Dos barras de WiMAX"</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Tres barras de WiMAX"</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Señal de WiMAX al máximo"</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Sin señal"</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"No conectado"</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Cero barras"</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Una barra"</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Dos barras"</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Tres barras"</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Señal excelente"</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Activado"</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Desactivado"</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Conectado"</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"No hay tarjeta SIM."</string>
@@ -129,6 +146,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Timbre en vibración"</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Timbre en silencio"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartada."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación ignorada"</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Pantalla de notificaciones"</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Configuración rápida"</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Aplicaciones recientes"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Usuario <xliff:g id="USER">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Móvil <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batería <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modo de avión <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarma: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Datos de 2G-3G inhabilitados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Datos de 4G inhabilitados"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Se inhabilitaron los datos móviles"</string>
@@ -140,11 +168,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Buscando GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"La ubicación se estableció por GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Eliminar todas las notificaciones"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activar el protector de pantalla"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Información de la aplicación"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Cerrar"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notificaciones desactivadas"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Toca aquí para volver a activar las notificaciones."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girará automáticamente."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"La pantalla está bloqueada en modo horizontal."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"La pantalla está bloqueada en modo vertical."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Activar protector"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo de avión"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Cargada"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desactivado"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brillo"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Girar automáticamente"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotación bloqueada"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Método de introducción"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Ubicación en uso"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Dispositivo multimedia"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Solo emergencia"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Configuración"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Hora"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Yo"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Sin conexión"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Sin red"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desactivada"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Pantalla Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Pantalla inalámbrica"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brillo"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÁTICO"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Las notificaciones aparecen aquí."</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Desliza el dedo hacia abajo para acceder al contenido."\n"Vuelve a deslizar el dedo hacia abajo para acceder a los controles del sistema."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index afbceff..19de9b6 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Ver"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Usar de forma predeterminada para este dispositivo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Usar de forma predeterminada para este accesorio USB"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"¿Permitir depuración USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"La huella digital de tu clave RSA es:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Permitir siempre desde este ordenador"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para ajustar"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Expandir para ajustar"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilidad"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Dos barras de datos"</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Tres barras de datos"</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Señal de datos al máximo"</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Sin conexión Wi-Fi"</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Una barra de Wi-Fi"</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Dos barras de Wi-Fi"</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Tres barras de Wi-Fi"</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Señal de Wi-Fi al máximo"</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi desactivado"</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi desconectado"</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Una barra de Wi-Fi"</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Dos barras de Wi-Fi"</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Tres barras de Wi-Fi"</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Señal de Wi-Fi al máximo"</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Sin conexión WiMAX"</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Una barra de WiMAX"</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Dos barras de WiMAX"</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Tres barras de WiMAX"</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Señal de WiMAX al máximo"</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"No hay señal"</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Sin conexión"</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Ninguna barra"</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Una barra"</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Dos barras"</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Tres barras"</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Señal al máximo"</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Activado"</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Desactivado"</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Conectado"</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5 G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Itinerancia"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Tipo Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Sin tarjeta SIM"</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Modo vibración"</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Modo silencio"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Se ha eliminado <xliff:g id="APP">%s</xliff:g>."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación ignorada"</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Pantalla de notificaciones"</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Ajustes rápidos"</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Aplicaciones recientes"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Usuario <xliff:g id="USER">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Móvil <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batería <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modo avión <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"La alarma sonará a la(s) <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Datos 2G-3G inhabilitados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Datos 4G inhabilitados"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Datos móviles inhabilitados"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Buscando GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Ubicación definida por GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Borrar todas las notificaciones"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activar salvapantallas"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Información de la aplicación"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Cerrar"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notificaciones desactivadas"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Toca aquí para volver a activar las notificaciones."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girará automáticamente."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"La pantalla está bloqueada en modo horizontal."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"La pantalla está bloqueada en modo vertical."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Salvapantallas"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo avión"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Cargada"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desactivado"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brillo"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Girar automáticamente"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotación bloqueada"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Método de entrada"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Ubicación en uso"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Dispositivo multimedia"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Solo llamadas de emergencia"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Ajustes"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Hora"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Yo"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"No conectado"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No hay red."</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desactivado"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Pantalla Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Pantalla inalámbrica"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brillo"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Las notificaciones aparecen aquí"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Desliza el dedo hacia abajo para acceder al contenido."\n"Vuelve a deslizar el dedo hacia abajo para acceder a los controles del sistema."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 318ed04..5339006 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Kuva"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Kasuta vaikimisi selle USB-seadme jaoks"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Vaikimisi kasuta seda USB-lisaseadet"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Kas luban USB silumise?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Arvuti RSA-võtme sõrmejälg:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Luba alati sellest arvutist"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Suumi ekraani täitmiseks"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Venita ekraani täitmiseks"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Sobivussuum"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Andmeside: kaks pulka."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Andmeside: kolm pulka."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Andmesignaal on tugev."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"WiFi puudub."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"WiFi signaal: üks post."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"WiFi signaal: kaks posti."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"WiFi signaal: kolm posti."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"WiFi-signaal on tugev."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi on väljas."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wifi-ühendus on katkestatud."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"WiFi: üks pulk."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"WiFi: kaks pulka."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"WiFi: kolm pulka."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"WiFi-signaal on tugev."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"WiMAX-i pole."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX-i on üks riba."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX-i on kaks riba."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX-i on kolm riba."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX-i signaal on tugev."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Signaal puudub."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Ühendus puudub."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Null pulka."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Üks pulk."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Kaks pulka."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Kolm pulka."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Signaal on tugev."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Sees."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Väljas."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Ühendatud."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Rändlus"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Serv"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"WiFi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM-kaarti pole."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Vibreeriv kõlisti."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Vaikne kõlisti."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Loobusite rakendusest <xliff:g id="APP">%s</xliff:g>."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Märguandest on loobutud."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Märguande vari."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Kiirseaded."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Hiljutised rakendused"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Kasutaja <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobiili <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Aku: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Lennukirežiim: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Määratud äratus: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G–3G andmeside keelatud"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G andmeside keelatud"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobiilne andmeside keelatud"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS-i otsimine"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS-i määratud asukoht"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Kustuta kõik teatised."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktiveeri ekraanisäästja"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Rakenduse teave"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Sule"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Teatised väljas"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Teatiste uuesti sisselülitamiseks puudutage siin."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekraani pööramine toimub automaatselt."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ekraan on lukustatud horisontaalsuunas."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ekraan on lukustatud vertikaalsuunas."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Unistus"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Lennurežiim"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Laadimine, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Laetud"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> seadet)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth on väljas"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Heledus"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Automaatne pööramine"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Pööramine lukus"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Sisestusmeetod"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Kasutatav asukoht"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Meediaseade"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Ainult hädaabikõned"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Seaded"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Aeg"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Mina"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"WiFi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ühendus puudub"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Võrku pole"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"WiFi-ühendus on väljas"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"WiFi-ekraan"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Juhtmeta ekraaniühendus"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Heledus"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMAATNE"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Märguanded ilmuvad siia"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Juurdepääs igal ajal sõrmega alla pühkides."\n"Süsteemi juhtnuppude jaoks pühkige uuesti alla."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 104ab038..aa80148 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -22,7 +22,7 @@
     <string name="app_label" msgid="7164937344850004466">"رابط کاربر سیستم"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"پاک کردن"</string>
     <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_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>
@@ -33,35 +33,38 @@
   </plurals>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"اعلانی موجود نیست"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"در حال انجام"</string>
-    <string name="status_bar_latest_events_title" msgid="6594767438577593172">"اعلان ها"</string>
+    <string name="status_bar_latest_events_title" msgid="6594767438577593172">"اعلان‌ها"</string>
     <string name="battery_low_title" msgid="2783104807551211639">"شارژر را متصل کنید"</string>
     <string name="battery_low_subtitle" msgid="1752040062087829196">"باتری در حال کم شدن است."</string>
     <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> باقیمانده است"</string>
-    <string name="invalid_charger" msgid="4549105996740522523">"شارژ USB پشتیبانی نمی شود."\n"فقط از شارژر ارائه شده استفاده کنید."</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"شارژ USB پشتیبانی نمی‌شود."\n"فقط از شارژر ارائه شده استفاده کنید."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"استفاده از باتری"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"تنظیمات"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"حالت هواپیما"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"چرخش خودکار صفحه"</string>
-    <string name="status_bar_settings_mute_label" msgid="554682549917429396">"بیصدا"</string>
+    <string name="status_bar_settings_mute_label" msgid="554682549917429396">"بی‌صدا"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"خودکار"</string>
-    <string name="status_bar_settings_notifications" msgid="397146176280905137">"اعلان ها"</string>
+    <string name="status_bar_settings_notifications" msgid="397146176280905137">"اعلان‌ها"</string>
     <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="7551903084416057810">"صفحه کلید فیزیکی"</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="status_bar_use_physical_keyboard" msgid="7551903084416057810">"صفحه‌کلید فیزیکی"</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>
-    <string name="always_use_accessory" msgid="1210954576979621596">"استفاده به صورت پیش فرض برای این دستگاه USB"</string>
+    <string name="always_use_device" msgid="1450287437017315906">"استفاده به صورت پیش‌فرض برای این دستگاه USB"</string>
+    <string name="always_use_accessory" msgid="1210954576979621596">"استفاده به صورت پیش‌فرض برای این دستگاه USB"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"اجازه به اشکال‌زدایی USB؟"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"اثر انگشت کلید RSA رایانه: "\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"همیشه از این رایانه انجام شود"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"بزرگنمایی برای پر کردن صفحه"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"گسترده کردن برای پر کردن صفحه"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"بزرگنمایی سازگاری"</string>
-    <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>
@@ -69,9 +72,9 @@
     <string name="screenshot_saved_text" msgid="1152839647677558815">"برای مشاهده تصویر صفحه خود، لمس کنید."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"تصویر صفحه گرفته نشد."</string>
     <string name="screenshot_failed_text" msgid="8134011269572415402">"تصویر صفحه ذخیره نشد. ممکن است دستگاه ذخیره‌ در حال استفاده باشد."</string>
-    <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="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 File Transfer را برای Mac نصب کنید"</string>
     <string name="accessibility_back" msgid="567011538994429120">"برگشت"</string>
     <string name="accessibility_home" msgid="8217216074895377641">"صفحهٔ اصلی"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"دو نوار برای داده."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"سه نوار برای داده."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"قدرت سیگنال داده کامل است."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Wi-Fi موجود نیست."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi یک نوار دارد."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi دو نوار دارد."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi سه نوار دارد."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"قدرت سیگنال WiFi کامل است."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi خاموش."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi قطع‌شد."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"یک نوار برای Wifi."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"دو نوار برای Wifi."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"سه نوار برای Wifi."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"قدرت سیگنال Wifi کامل است."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"WiMAX وجود ندارد."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX دارای یک نوار است."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX دارای دو نوار است."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX دارای سه نوار است."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"قدرت سیگنال WiMAX کامل است."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"فاقد سیگنال."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"متصل نیست."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"بدون میله."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"یک میله."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"دو میله."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"سه میله."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"سیگنال کامل."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"روشن."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"خاموش."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"متصل."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"رومینگ"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"بدون سیم کارت."</string>
@@ -125,8 +142,19 @@
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"دستیابی به GPS."</string>
     <string name="accessibility_tty_enabled" msgid="4613200365379426561">"TeleTypewriter فعال شد."</string>
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"زنگ لرزشی."</string>
-    <string name="accessibility_ringer_silent" msgid="9061243307939135383">"زنگ بیصدا."</string>
+    <string name="accessibility_ringer_silent" msgid="9061243307939135383">"زنگ بی‌صدا."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> نادیده گرفته شد."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"اعلان ردشد."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"مجموعه اعلان."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"تنظیمات سریع."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"برنامه‌های اخیر"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"کاربر <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"تلفن همراه <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"باتری <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"حالت هواپیما <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"بلوتوث <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"هشدار برای <xliff:g id="TIME">%s</xliff:g> تنظیم شد."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"داده 2G-3G غیرفعال شد"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"داده 4G غیر فعال شد"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"داده‌های تلفن همراه غیرفعال است"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"جستجو برای GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"مکان تنظیم شده توسط GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"پاک کردن تمام اعلان‌ها"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"فعال کردن محافظ صفحهٔ نمایش"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"اطلاعات برنامه"</string>
+    <string name="close_universe" msgid="3736513750241754348">"بستن"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"اعلان‌ها خاموش"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"برای روشن کردن مجدد اعلان‌ها، اینجا را ضربه بزنید."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"صفحه به صورت خودکار می‌چرخد."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"صفحه اکنون در جهت افقی قفل است."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"صفحه اکنون در جهت عمودی قفل است."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"رویاپردازی"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"اترنت"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"حالت هواپیما"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"در حال شارژ، <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"شارژ شد"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"بلوتوث"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"بلوتوث ( <xliff:g id="NUMBER">%d</xliff:g> دستگاه)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"بلوتوث خاموش"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"روشنایی"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"چرخش خودکار"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"چرخش قفل شد"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"روش ورودی"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"موقعیت مکانی در حال استفاده"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"دستگاه رسانه"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"فقط تماس‌های اضطراری"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"تنظیمات"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"زمان"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"من"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"متصل نیست"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"شبکه‌ای موجود نیست"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi خاموش است"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Display"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"نمایش بدون سیم"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"روشنایی"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"خودکار"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"اعلان‌ها در اینجا نمایش داده می‌شوند"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"با کشیدن انگشت به طرف پایین به آنها دسترسی پیدا کنید."\n"برای کنترل‌های سیستم دوباره انگشت خود را به سمت پایین بکشید."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index a4229b4..3bd709c 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Näytä"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Käytä oletuksena tällä USB-laitteella"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Käytä oletuksena tällä USB-lisälaitteella"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Sallitaanko USB-vianetsintä?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Tietokoneen RSA-avaintunnistetiedosto on:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Salli aina tällä tietokoneella"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoomaa koko näyttöön"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Venytä koko näyttöön"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Yhteensopivuuszoomaus"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Datasignaali - kaksi palkkia."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Datasignaali - kolme palkkia"</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Vahva kuuluvuus."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Ei wifi-yhteyttä."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wifi-signaali: yksi palkki."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wifi-signaali: kaksi palkkia."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wifi-signaali: kolme palkkia."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Vahva wifi-signaali."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi pois käytöstä."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Ei wifi-yhteyttä."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wifi-signaali – yksi palkki."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wifi-signaali – kaksi palkkia."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wifi-signaali – kolme palkkia."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Vahva wifi-signaali."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Ei WiMAX-yhteyttä."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX: yksi palkki."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX: kaksi palkkia."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX: kolme palkkia."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Vahva WiMAX-signaali."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Ei signaalia."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Ei yhteyttä."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Nolla palkkia."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Yksi palkki."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Kaksi palkkia."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Kolme palkkia."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Vahva signaali."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Käytössä."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Pois käytöstä."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Yhdistetty."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wifi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Ei SIM-korttia."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Soittoääni: värinä."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Soittoääni: äänetön."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> hylättiin."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ilmoitus hylätty."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Ilmoitusalue."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Pika-asetukset."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Viimeaikaiset sovellukset"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Käyttäjä: <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobiiliverkkoyhteys: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Akku: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Lentokonetila <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Hälytys asetettu, aika: <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G-tiedonsiirto pois käytöstä"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G-tiedonsiirto pois käytöstä"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobiilitiedonsiirto pois käytöstä"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Haetaan GPS-yhteyttä"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Sijainti määritetty GPS:n avulla"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Tyhjennä kaikki ilmoitukset."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ota näytönsäästäjä käyttöön"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Sovelluksen tiedot"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Sulje"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Ilmoitukset pois käytöstä"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Ota ilmoitukset uudelleen käyttöön napauttamalla tätä."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ruutu kääntyy automaattisesti."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ruutu on lukittu vaakasuuntaan."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ruutu on lukittu pystysuuntaan."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Unelmat"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Lentokonetila"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Ladataan (<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>)"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Täynnä"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> laitetta)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth pois käytöstä"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Kirkkaus"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Automaattinen kääntö"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Kääntö lukittu"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Syöttötapa"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Sijainti käytössä"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Medialaite"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Vain hätäpuhelut"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Asetukset"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Aika"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Minä"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wifi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ei yhteyttä"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ei verkkoa"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wifi-yhteys pois käytöstä"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wifi-näyttö"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Langaton näyttö"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Kirkkaus"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Ilmoitukset näkyvät tässä"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Näet ilmoitukset liu\'uttamalla sormea alas ruudulla."\n"Voit palauttaa järjestelmän ohjaimet näkyviin liu\'uttamalla sormea alas uudelleen."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 30b3539..babbcce 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Afficher"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utiliser par défaut pour ce périphérique USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utiliser par défaut pour cet accessoire USB"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Autoriser le débogage USB ?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Empreinte numérique de la clé RSA de l\'ordinateur : "\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Toujours autoriser sur cet ordinateur"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoomer pour remplir l\'écran"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Étirer pour remplir l\'écran"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilité"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Signal moyen"</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Signal bon"</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Signal excellent"</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Aucun signal Wi-Fi"</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Signal Wi-Fi très faible"</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Signal Wi-Fi faible"</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Signal Wi-Fi bon"</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Signal Wi-Fi excellent"</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi désactivé"</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi déconnecté"</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Signal Wi-Fi faible"</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Signal Wi-Fi moyen"</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Signal Wi-Fi bon"</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Signal Wi-Fi excellent"</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Aucun signal WiMAX"</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Signal WiMAX : faible"</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Signal WiMAX : moyen"</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Signal WiMAX : bon"</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Signal WiMAX : excellent"</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Aucun signal"</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Non connecté"</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Aucun signal"</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Signal faible"</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Moyen"</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Bon"</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Signal excellent"</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Activé"</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Désactivé"</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Connecté"</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1x"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3G+"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Itinérance"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Aucune carte SIM"</string>
@@ -129,22 +146,63 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Sonnerie en mode vibreur"</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Sonnerie en mode silencieux"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Application \"<xliff:g id="APP">%s</xliff:g>\" ignorée."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification masquée"</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Volet des notifications"</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Paramètres rapides"</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Applications récentes"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Utilisateur <xliff:g id="USER">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>, <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Signal mobile : <xliff:g id="SIGNAL">%1$s</xliff:g>, <xliff:g id="TYPE">%2$s</xliff:g>, <xliff:g id="NETWORK">%3$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batterie : <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Mode Avion : <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth : <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarme réglée sur <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Données 2G-3G désactivées"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Données 4G désactivées"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Données mobiles désactivées"</string>
     <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"Données désactivées"</string>
     <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"Vous avez atteint le plafond de consommation de données spécifié."\n\n"Si vous utilisez des données supplémentaires, celles-ci pourront être facturées par l\'opérateur."</string>
     <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"Réactiver connexion données"</string>
-    <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Aucune connexion"</string>
+    <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Aucune connexion Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Connecté au Wi-Fi"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Recherche de GPS..."</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Position définie par GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Supprimer toutes les notifications"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activer l\'économiseur d\'écran"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informations sur l\'application"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Fermer"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notifications désactivées"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Appuyez ici pour réactiver les notifications."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"L\'écran pivote automatiquement."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"L\'écran est verrouillé en mode paysage."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"L\'écran est verrouillé en mode portrait."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Écran de veille interactif"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode avion"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"En charge (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Chargée"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> appareils)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth désactivé"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Luminosité"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Rotation auto."</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotation bloquée"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Mode de saisie"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Utilisation des données de localisation"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Appareil multimédia"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Appels d\'urgence uniquement"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Paramètres"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Heure"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Moi"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Non connecté"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Aucun réseau"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi désactivé"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Display"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Affichage sans fil"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Luminosité"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATIQUE"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Les notifications s’affichent ici"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Accédez-y à tout moment en faisant glisser le doigt vers le bas."\n"Répétez l\'opération pour accéder aux commandes du système."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index aae070a..cdcda79 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"देखें"</string>
     <string name="always_use_device" msgid="1450287437017315906">"इस USB उपकरण के लिए डिफ़ॉल्‍ट रूप से उपयोग करें"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"इस USB एसेसरी के लिए डिफ़ॉल्‍ट रूप से उपयोग करें"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"USB डीबगिंग करने दें?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"कंप्यूटर का RSA कुंजी फ़िंगरप्रिंट है:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"इस कंप्यूटर से हमेशा अनुमति दें"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"स्‍क्रीन भरने हेतु ज़ूम करें"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"स्‍क्रीन को भरने के लिए खींचें"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"संगतता ज़ूम"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"डेटा दो बार."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"डेटा तीन बार."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"पूर्ण डेटा सि‍ग्‍नल."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"कोई Wi-Fi नहीं."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi का एक बार."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi के दो बार."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi के तीन बार."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"पूर्ण WiFi सि‍ग्‍नल."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi बंद."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wifi डिस्कनेक्ट है."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"WiFi एक बार."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"WiFi दो बार."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"WiFi तीन बार."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"पूर्ण WiFi सि‍ग्‍नल."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"WiMAX नहीं."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX एक बार."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX दो बार."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX तीन बार."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX सि‍ग्‍नल पूर्ण."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"कोई सिग्नल नहीं."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"कनेक्ट नहीं है."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"शून्य बार."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"एकल बार."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"दो बार."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"तीन बार."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"पूर्ण सिग्नल."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"चालू."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"बंद."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"कनेक्ट है."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"रोमिंग"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"किनारा"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"कोई सिम नहीं."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"रिंगर कंपन."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"रिंगर मौन."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> खा़रिज कर दिया गया."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना खारिज की गई."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"सूचना शेड."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"त्वरित सेटिंग."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"हाल ही के एप्‍लिकेशन."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"उपयोगकर्ता <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"मोबाइल <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"बैटरी <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"हवाई जहाज़ मोड <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"<xliff:g id="TIME">%s</xliff:g> के लिए अलार्म सेट किया गया."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G डेटा अक्षम"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G डेटा अक्षम"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"मोबाइल डेटा अक्षम"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS को खोजा जा रहा है"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS द्वारा सेट किया गया स्‍थान"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"सभी सूचनाएं साफ़ करें."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"स्‍क्रीन सेवर सक्रिय करें"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"एप्‍लिकेशन जानकारी"</string>
+    <string name="close_universe" msgid="3736513750241754348">"बंद करें"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"सूचनाएं बंद"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"सूचनाओं को पुन: चालू करने के लिए यहां टैप करें."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"स्‍क्रीन स्‍वचालित रूप से घूमेगी."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"स्‍क्रीन लैंडस्केप अभिविन्यास में लॉक है."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"स्‍क्रीन पोर्ट्रेट अभिविन्‍यास में लॉक है."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"ईथरनेट"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"हवाई जहाज़ मोड"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"चार्ज हो रही है, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"चार्ज हो गई है"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> उपकरण)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth बंद"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"चमक"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"स्वत: रोटेट"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"रोटेशन लॉक किया गया"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"इनपुट विधि"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"उपयोग हो रहा स्थान"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"मीडिया उपकरण"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"केवल आपातकालीन कॉल"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"सेटिंग"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"समय"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"मुझे"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"कनेक्ट नहीं है"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"कोई नेटवर्क नहीं"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi बंद"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi प्रदर्शन"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"वायरलेस डिस्प्ले"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"चमक"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"स्वत:"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"सूचनाएं यहां दिखाई देती हैं"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"नीचे स्वाइप करके उन तक कभी भी पहुंचें."\n"सिस्टम नियंत्रणों के लिए पुन: नीचे स्वाइप करें."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 4a1f35a..cfa5d54 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Prikaži"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Koristi se prema zadanim postavkama za ovaj USB uređaj"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Koristi se prema zadanim postavkama za ovaj USB pribor"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Omogućiti rješavanje programske pogreške na USB-u?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Otisak prsta RSA ključa računala je: "\n" <xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Uvijek dopusti s ovog računala"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zumiraj i ispuni zaslon"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rastegni i ispuni zaslon"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilno zumiranje"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Podatkovni signal dva stupca."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Podatkovni signal tri stupca."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Podatkovni signal pun."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Nema Wi-Fi signala."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi jedna crtica."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi dvije crtice."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi tri crtice."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"WiFi signal pun."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"WiFi je isključen."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"WiFi je isključen."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"WiFi signal ima jedan stupac."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"WiFi signal ima dva stupca."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"WiFi signal ima tri stupca."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"WiFi signal je pun."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Nema signala WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX s jednim stupcem."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX s dva stupca."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX s tri stupca."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Signal WiMAX potpun je."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Nema signala."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Nije povezano."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Nijedan stupac."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Jedan stupac."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Dva stupca."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Tri stupca."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Signal je pun."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Uključeno."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Isključeno."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Povezano."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Nema SIM kartice."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Vibracija softvera zvona."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Softver zvona utišan."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> odbačena je."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obavijest je odbačena."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Zaslon obavijesti."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Brze postavke."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Nedavne aplikacije."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Korisnik <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobitel <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Baterija – <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Način rada u zrakoplovu <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth – <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Vrijeme alarma: <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Onemogućeni su 2G-3G podaci"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Onemogućeni su 4G podaci"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Onemogućeni su mobilni podaci"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Traženje GPS-a"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokaciju utvrdio GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Brisanje svih obavijesti."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivirajte čuvar zaslona"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informacije o aplikaciji"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Zatvori"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Obavijesti isključene"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Dotaknite ovdje da biste ponovo uključili obavijesti."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Zaslon će se automatski zakrenuti."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Zaslon je zaključan u pejzažnoj orijentaciji."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Zaslon je zaključan u portretnoj orijentaciji."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Sanjarenje"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Način rada u zrakoplovu"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Puni se, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Napunjena"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (broj uređaja: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth isključen"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Svjetlina"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Automatska rotacija"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotacija zaključana"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Način unosa"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Lokacija u uporabi"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Medijski uređaj"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Samo hitni pozivi"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Postavke"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Vrijeme"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Ja"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nije povezano"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nema mreže"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi isključen"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi zaslon"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Bežični prikaz"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Svjetlina"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATSKI"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Obavijesti se prikazuju ovdje"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Pristupite im u bilo kojem trenutku tako da prstom trznete prema dolje. "\n"Ponovo prstom trznite prema dolje za kontrole sustava."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 2ea0f76..27bf2f5 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Megtekintés"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Alapértelmezett használat ehhez az USB-eszközhöz"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Alapértelmezett használat ehhez az USB-kiegészítőhöz"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Engedélyezi az USB hibakeresést?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"A számítógép RSA kulcs ujjlenyomata:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Mindig engedélyezze erről a számítógépről"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Nagyítás a kitöltéshez"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Nyújtás kitöltéshez"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitás -- nagyítás/kicsinyítés"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Adat két sáv."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Adat három sáv."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Adatjel teljes."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Nincs Wi-Fi"</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi -- egy sáv"</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi -- két sáv"</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi -- három sáv"</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Wi-Fi jel teljes."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi kikapcsolva."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Nincs Wi-Fi kapcsolat."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi jel: egy sáv."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi jel: két sáv."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi jel: három sáv."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wi-Fi jel teljes."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Nincs WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX-jel: egy sáv."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX-jel: két sáv."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX-jel: három sáv."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX-jel: teljes."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Nincs jel."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Nincs csatlakozva."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Nincs sáv."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Egy sáv."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Két sáv."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Három sáv."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Teljes jelerősség."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Bekapcsolva."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Kikapcsolva."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Csatlakoztatva."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Barangolás"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Nincs SIM."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Csengő rezeg."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Csengő néma."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> eltávolítva."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Értesítés elvetve."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Értesítési felület."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Gyorsbeállítások."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Legutóbbi alkalmazások"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Felhasználó: <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobil <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Akkumulátor <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Repülős üzemmód <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Ébresztés időpontja: <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G adatforgalom letiltva"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G adatforgalom letiltva"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobil adatforgalom letiltva"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS keresése"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"A GPS beállította a helyet"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Minden értesítés törlése"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Képernyővédő aktiválása"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Alkalmazásinformáció"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Bezárás"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Értesítések kikapcsolva"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Itt érintse meg az értesítések bekapcsolásához."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"A képernyő automatikusan forogni fog."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"A képernyő zárolva van fekvő tájolásban."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"A képernyő zárolva van álló tájolásban."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Álmodozás"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Repülőgép üzemmód"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Töltés (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Feltöltve"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> eszköz)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth kikapcsolva"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Fényerő"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Automatikus forgatás"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Forgatás zárolva"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Beviteli módszer"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Használatban lévő hely"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Médiaeszköz"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Csak segélyhívások"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Beállítások"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Idő"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Én"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nincs kapcsolat"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nincs hálózat"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi kikapcsolva"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi kijelző"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Vezeték nélküli kijelző"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Fényerő"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"automatikus"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Az értesítések itt jelennek meg."</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Bármikor elérheti őket, ha lefelé húzza az ujját."\n"Húzza le az ujját még egyszer a rendszerbeállítások eléréséhez."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index a69fc23..26151dd 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Lihat"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gunakan secara default untuk perangkat USB ini"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gunakan secara default untuk aksesori USB ini"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Izinkan debugging USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Sidik jari kunci RSA komputer adalah:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Selalu izinkan dari komputer ini"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Perbesar utk mengisi layar"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rentangkn utk mngisi layar"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Perbesar/perkecil untuk kompatibilitas"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Data dua batang."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Data tiga batang."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Sinyal data penuh."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Tidak ada Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi satu bilah."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi dua bilah."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi tiga bilah."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Sinyal WiFi penuh."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi tidak aktif."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi tidak tersambung."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi satu baris."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi dua batang.aris"</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi tiga baris."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Sinyal Wi-Fi penuh."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Tidak ada WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX satu batang."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX dua batang."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX tiga batang."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Sinyal WiMAX penuh."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Tidak ada sinyal."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Tidak tersambung."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"0 baris."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Satu garis."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Dua baris."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Tiga baris."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Sinyal penuh."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Aktif."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Nonaktif."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Tersambung."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Tidak ada SIM."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Pendering bergetar."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Pendering senyap."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> disingkirkan."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pemberitahuan disingkirkan."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bayangan pemberitahuan."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Setelan cepat."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Aplikasi terkini."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Pengguna <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Seluler <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Baterai <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Mode Pesawat <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm disetel ke <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Data 2G-3G dinonaktifkan"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Data 4G dinonaktifkan"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Data seluler dinonaktifkan"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Menelusuri GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasi yang disetel oleh GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Menghapus semua pemberitahuan."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktifkan tirai layar"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Info aplikasi"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Tutup"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Pemberitahuan mati"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Ketuk di sini untuk menyalakan pemberitahuan lagi."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Layar akan diputar secara otomatis."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Layar dikunci dalam orientasi lanskap."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Layar dikunci dalam orientasi potret."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Lamunan"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode pesawat"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Mengisi baterai, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Ditagih"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Perangkat)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Mati"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Kecerahan"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Rotasi Otomatis"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotasi Dikunci"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Metode Masukan"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Lokasi penggunaan"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Perangkat media"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Panggilan Darurat Saja"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Setelan"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Waktu"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Saya"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Tidak Tersambung"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Tidak Ada Jaringan"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Mati"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Tampilan Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Layar Nirkabel"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Kecerahan"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OTOMATIS"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Pemberitahuan muncul di sini"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Akses kapan saja dengan menggesek ke bawah."\n"Gesek ke bawah sekali lagi untuk kontrol sistem."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 432d984..812d1ac 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Visualizza"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Usa per impostazione predef. per dispositivo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Usa per impostazione predef. per accessorio USB"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Consentire debug USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Fingerprint della chiave RSA del computer: "\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Consenti sempre da questo computer"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom per riempire schermo"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Estendi per riemp. schermo"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom compatibilità"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Dati: due barre."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Dati: tre barre."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Massimo segnale dati."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Nessuna connessione Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi: una barra."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi: due barre."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi: tre barre."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Massimo segnale Wi-Fi."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi non attivo."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Rete Wi-Fi scollegata."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi: una barra."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi: due barre."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi: tre barre."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Massimo segnale Wi-Fi."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Nessun segnale WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX: una barra."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX: due barre."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX: tre barre."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Massimo segnale WiMAX."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Nessun segnale."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Non connesso."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Nessuna barra."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Una barra."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Due barre."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Tre barre."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Massimo segnale."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Attivo."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Non attivo."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Connesso."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Nessuna SIM presente."</string>
@@ -129,6 +146,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Suoneria vibrazione."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Suoneria silenziosa."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> eliminata."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notifica eliminata."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Area notifiche."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Impostazioni rapide."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Applicazioni recenti."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Utente <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Cellulare: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batteria: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modalità aereo: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Allarme impostato per: <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Dati 2G-3G disattivati"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Dati 4G disattivati"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Dati mobili disattivati"</string>
@@ -140,11 +168,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Ricerca del GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Posizione stabilita dal GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Cancella tutte le notifiche."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Attiva screensaver"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informazioni applicazione"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Chiudi"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notifiche disattivate"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Tocca qui per riattivare le notifiche."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Lo schermo ruoterà automaticamente."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Lo schermo è bloccato in orientamento orizzontale."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Lo schermo è bloccato in orientamento verticale."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modalità aereo"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"In carica (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Carica"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivi)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth spento"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Luminosità"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Rotazione autom."</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotazione bloccata"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Metodo di immissione"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Posizione in uso"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Dispositivo multimediale"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Solo chiamate di emergenza"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Impostazioni"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Ora"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Io"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Non connesso"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nessuna rete"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi disattivato"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Display Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Visualizzazione wireless"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Luminosità"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Le notifiche vengono visualizzate qui"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Puoi accedervi in qualsiasi momento scorrendo verso il basso."\n"Fai scorrere di nuovo verso il basso per visualizzare i controlli del sistema."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index bdc84b6..150375d 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"הצג"</string>
     <string name="always_use_device" msgid="1450287437017315906">"השתמש כברירת מחדל עבור מכשיר USB זה"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"השתמש כברירת מחדל עבור אביזר USB זה"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"האם לאפשר ניקוי באגים ב-USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"טביעת האצבע של מפתח ה-RSA של המחשב היא:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"אפשר תמיד ממחשב זה"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"הגדל תצוגה כדי למלא את המסך"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"מתח כדי למלא את המסך"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"שינוי מרחק מתצוגה לצורך תאימות"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"שני פסים של נתונים."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"שלושה פסים של נתונים."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"אות הנתונים מלא."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"אין Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"פס Wi-Fi אחד."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"שני פסי Wi-Fi."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"שלושה פסי Wi-Fi."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"אות ה-WiFi מלא."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi כבוי."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wifi מנותק."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"פס אחד של Wifi."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"שני פסים של Wifi."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"שלושה פסים של Wifi."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"אות ה-Wifi מלא."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"ללא WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"פס אחד של WiMAX."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"שני פסים של WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"שלושה פסים של WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"אות ה-WiMAX מלא."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"אין אות."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"לא מחובר."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"אפס פסים."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"פס אחד."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"שני פסים."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"שלושה פסים."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"אות מלא."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"פועל."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"כבוי."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"מחובר."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"‎1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"נדידה"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"קצה"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"אין כרטיס SIM."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"צלצול ורטט."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"צלצול שקט."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> נדחה."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"הודעה נדחתה."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"תריס התראות."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"הגדרות מהירות."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"יישומים אחרונים"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"משתמש <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>‏. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"נייד <xliff:g id="SIGNAL">%1$s</xliff:g>.‏ <xliff:g id="TYPE">%2$s</xliff:g>.‏ <xliff:g id="NETWORK">%3$s</xliff:g>.‏"</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"סוללה <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"מצב טיסה <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth ‏<xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"ההתראה נקבעה ל-<xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"נתוני 2G-3G מושבתים"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"נתוני 4G מושבתים"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"נתונים לנייד מושבתים"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"מחפש GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"מיקום מוגדר על ידי GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"נקה את כל ההתראות."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"הפעלת שומר מסך"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"פרטי יישום"</string>
+    <string name="close_universe" msgid="3736513750241754348">"סגור"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"מצב התראות כבוי"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"הקש כאן כדי להפעיל מחדש את ההתראות."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"המסך יסתובב באופן אוטומטי."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"המסך נעול כעת לרוחב."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"המסך נעול כעת לאורך."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"מצב טיסה"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"טוען (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"מלאה"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth ‏(<xliff:g id="NUMBER">%d</xliff:g> מכשירים)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth מופסק"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"בהירות"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"סיבוב אוטומטי"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"סיבוב נעול"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"שיטת קלט"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"מיקום בשימוש"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"מכשיר מדיה"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"שיחות חירום בלבד"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"הגדרות"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"שעה"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"אני"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"לא מחובר"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"אין רשת"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi כבוי"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"תצוגת Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"תצוגת WiFi"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"בהירות"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"אוטומטי"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"הודעות מופיעות כאן"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"גש אליהם בכל עת על ידי החלקה למטה."\n"החלק למטה שוב למעבר למרכז הבקרה של המערכת."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 70ba034..b64d73e 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"表示"</string>
     <string name="always_use_device" msgid="1450287437017315906">"このUSBデバイスにデフォルトで使用する"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"このUSBアクセサリにデフォルトで使用する"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"USBデバッグを許可しますか?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"このパソコンのRSAキーのフィンガープリント:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"このパソコンからのUSBデバッグを常に許可する"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"画面サイズに合わせて拡大"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"画面サイズに合わせて拡大"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"互換ズーム"</string>
@@ -65,7 +68,7 @@
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"スクリーンショットを保存中..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"スクリーンショットを保存しています..."</string>
     <string name="screenshot_saving_text" msgid="2419718443411738818">"スクリーンショットを保存しています。"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"スクリーンショットをキャプチャしました。"</string>
+    <string name="screenshot_saved_title" msgid="6461865960961414961">"スクリーンショットを取得しました。"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"タップしてスクリーンショットを表示します。"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"スクリーンショットをキャプチャできませんでした。"</string>
     <string name="screenshot_failed_text" msgid="8134011269572415402">"スクリーンショットを保存できませんでした。ストレージが使用中の可能性があります。"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"データ信号:レベル2"</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"データ信号:レベル3"</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"データ信号:フル"</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Wi-Fi接続なし"</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi電波: レベル1"</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi電波: レベル2"</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi電波: レベル3"</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Wi-Fi電波:フル"</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi OFF"</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fiが切断されました。"</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fiレベル1"</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fiレベル2"</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fiレベル3"</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wi-Fi電波フル"</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"WiMAX電波状態:圏外"</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX電波状態:レベル1"</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX電波状態:レベル2"</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX電波状態:レベル3"</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX電波状態:フル"</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"圏外です。"</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"接続されていません。"</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"レベル0"</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"レベル1"</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"レベル2"</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"レベル3"</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"電波フル"</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"ON"</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"OFF"</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"接続済みです。"</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"ローミング中"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIMがありません。"</string>
@@ -129,6 +146,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"バイブレーション着信。"</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"マナーモード着信。"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>は削除されました。"</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"通知が削除されました。"</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知シェード"</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"クイック設定"</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"最近使ったアプリです。"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"ユーザー: <xliff:g id="USER">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>、<xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"モバイル: <xliff:g id="SIGNAL">%1$s</xliff:g>、<xliff:g id="TYPE">%2$s</xliff:g>、<xliff:g id="NETWORK">%3$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"電池<xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"機内モード<xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"アラームは<xliff:g id="TIME">%s</xliff:g>に設定されています。"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G~3Gデータが無効になりました"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4Gデータが無効になりました"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"モバイルデータが無効になりました"</string>
@@ -140,11 +168,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPSで検索中"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPSにより現在地が設定されました"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"通知をすべて消去。"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"スクリーンセーバーを有効にする"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"アプリ情報"</string>
+    <string name="close_universe" msgid="3736513750241754348">"閉じる"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"通知OFF"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"通知を再度ONにするにはここをタップします。"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"画面は自動的に回転します。"</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"画面は横向きにロックされています。"</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"画面は縦向きにロックされています。"</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"スクリーンセーバー"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"イーサネット"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"機内モード"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"充電中: <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"充電完了"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth(端末数<xliff:g id="NUMBER">%d</xliff:g>)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth OFF"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"画面の明るさ"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"自動回転"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"画面の向きをロック"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"入力方法"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"使用中のロケーション"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"メディアデバイス"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"緊急通報のみ"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"設定"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"時間"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"このユーザー"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"接続されていません"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ネットワークなし"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi OFF"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fiディスプレイ"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"ワイヤレスディスプレイ"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"画面の明るさ"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"ここに通知が表示されます"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"下にスワイプすると、いつでも通知を表示できます。"\n"システムを管理するにはもう一度下にスワイプしてください。"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index e54b06c..3f7c520 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"보기"</string>
     <string name="always_use_device" msgid="1450287437017315906">"이 USB 기기에 기본값으로 사용"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"이 USB 액세서리에 기본값으로 사용"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"USB 디버깅을 허용하시겠습니까?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"컴퓨터 RSA 키 지문:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"이 컴퓨터에서 항상 허용"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"전체화면 모드로 확대"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"전체화면 모드로 확대"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"호환성 확대/축소"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"데이터 신호 막대가 두 개입니다."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"데이터 신호 막대가 세 개입니다."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"데이터 신호가 강합니다."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Wi-Fi 신호가 없습니다."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi 신호 막대가 한 개입니다."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi 신호 막대가 두 개입니다."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi 신호 막대가 세 개입니다."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"WiFi 신호가 강합니다."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi가 꺼져 있습니다."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi 연결이 끊어졌습니다."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi 신호 막대가 하나입니다."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi 신호 막대가 두 개입니다."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi 신호 막대가 세 개입니다."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wi-Fi 신호가 강합니다."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"WiMAX가 없습니다."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX 신호 막대가 하나입니다."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX 신호 막대가 두 개입니다."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX 신호 막대가 세 개입니다."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX 신호가 강합니다."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"신호가 없습니다."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"연결되지 않았습니다."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"신호 막대가 없습니다."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"신호 막대가 하나입니다."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"신호 막대가 두 개입니다."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"신호 막대가 세 개입니다."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"신호가 강합니다."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"사용"</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"사용 안함"</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"연결됨"</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"로밍"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM이 없습니다."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"벨소리가 진동입니다."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"벨소리가 무음입니다."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>이(가) 제거되었습니다."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"알림이 제거되었습니다."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"알림 세부정보"</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"빠른 설정"</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"최근 앱"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"사용자 <xliff:g id="USER">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"모바일 <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"배터리 <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"비행기 모드가 <xliff:g id="STATE">%s</xliff:g> 상태입니다."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"블루투스 <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"알람이 <xliff:g id="TIME">%s</xliff:g>(으)로 설정되었습니다."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G 데이터 사용중지됨"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G 데이터 사용중지됨"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"모바일 데이터 사용중지됨"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS 검색 중"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS에서 위치 설정"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"모든 알림 지우기"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"스크린 세이버 활성화"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"앱 정보"</string>
+    <string name="close_universe" msgid="3736513750241754348">"닫기"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"알림 사용 안함"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"알림을 다시 사용하려면 여기를 터치하세요."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"화면이 자동으로 회전됩니다."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"화면이 가로 방향으로 잠겨 있습니다."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"화면이 세로 방향으로 잠겨 있습니다."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"화면 보호기"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"이더넷"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"비행기 모드"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"충전 중(<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"충전됨"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"블루투스"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"블루투스(<xliff:g id="NUMBER">%d</xliff:g>개의 기기)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"블루투스 사용 안함"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"밝기"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"자동 회전"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"회전 잠금"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"입력 방법"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"위치 사용 중"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"미디어 기기"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"긴급 통화만 허용"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"설정"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"시간"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"나"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"연결되어 있지 않음"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"네트워크가 연결되지 않음"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi 꺼짐"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi 디스플레이"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"무선 디스플레이"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"밝기"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"자동"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"알림이 여기에 표시됨"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"아래로 스와이프하여 언제든 액세스하세요."\n"한 번 더 아래로 스와이프하면 시스템 관리로 이동합니다."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-land/config.xml b/packages/SystemUI/res/values-land/config.xml
index bbae18d..6476d88 100644
--- a/packages/SystemUI/res/values-land/config.xml
+++ b/packages/SystemUI/res/values-land/config.xml
@@ -23,5 +23,11 @@
     <!-- Whether we're using the tablet-optimized recents interface (we use this
      value at runtime for some things) -->
     <integer name="status_bar_recents_bg_gradient_degrees">90</integer>
+
+    <!-- The number of columns in the QuickSettings -->
+    <integer name="quick_settings_num_columns">6</integer>
+
+    <!-- The number of columns that the top level tiles span in the QuickSettings -->
+    <integer name="quick_settings_user_time_settings_tile_span">2</integer>
 </resources>
 
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index e7c8b1f..ab71371 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -37,4 +37,7 @@
     <!-- Where to place the app icon over the thumbnail -->
     <dimen name="status_bar_recents_app_icon_left_margin">8dp</dimen>
     <dimen name="status_bar_recents_app_icon_top_margin">8dp</dimen>
+
+    <!-- The fixed height of each tile -->
+    <dimen name="quick_settings_cell_height">100dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-land/styles.xml b/packages/SystemUI/res/values-land/styles.xml
new file mode 100644
index 0000000..8919198
--- /dev/null
+++ b/packages/SystemUI/res/values-land/styles.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <style name="BrightnessDialogContainer" parent="@style/BaseBrightnessDialogContainer">
+        <item name="android:layout_width">360dp</item>
+    </style>
+</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 018b5e5..02d0c5b 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Žiūrėti"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Šiam USB įreng. naudoti pagal numat. nustatymus"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Šiam USB priedui naudoti pagal numat. nustatymus"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Leisti USB derinimą?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Šio kompiuterio RSA rakto kontrolinis kodas yra:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Visada leisti iš šio kompiuterio"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Keisti mast., kad atit. ekr."</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Ištempti, kad atit. ekr."</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Suderinamumo mastelio keitimas"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Dvi duomenų juostos."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Trys duomenų juostos."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Stiprus duomenų signalas."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Nėra „Wi-Fi“ ryšio."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Viena „Wi-Fi“ juosta."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Dvi „Wi-Fi“ signalo juostos."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Trys „Wi-Fi“ signalo juostos."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"„Wi-Fi“ signalas stiprus."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"„Wi-Fi“ išjungta."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"„Wi-Fi“ atjungta."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Viena „Wi-Fi“ juosta."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Dvi „Wi-Fi“ juostos."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Trys „Wi-Fi“ juostos."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Stiprus „Wi-Fi“ signalas."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Nėra „WiMAX“ signalo."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Viena „WiMAX“ signalo juosta."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Dvi „WiMAX“ signalo juostos."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Trys „WiMAX“ signalo juostos."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"„WiMAX“ signalas stiprus."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Nėra signalo."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Neprijungta."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Nė vienos juostos."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Viena juosta."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Dvi juostos."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Trys juostos."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Stiprus signalas."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Įjungta."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Išjungta."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Prijungta."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Tarptinklinis ryšys"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Kraštas"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Nėra SIM kortelės."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Vibracija skambinant."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Skambutis tylus."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Atsisakyta programos „<xliff:g id="APP">%s</xliff:g>“."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pranešimo atsisakyta."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Pranešimų gaubtas."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Spartieji nustatymai."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Naujausios programos."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Naudotojas <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobilusis ryšys <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Akumuliatorius <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Lėktuvo režimas <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"„Bluetooth“ <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Signalas nustatytas <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G–3G duomenys neleidžiami"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G duomenys neleidžiami"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobilieji duomenys neleidžiami"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Ieškoma GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS nustatyta vieta"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Išvalyti visus pranešimus."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktyvinti ekrano užsklandą"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Programos informacija"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Uždaryti"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Pranešimai išjungti"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Jei norite vėl įjungti pranešimus, palieskite čia."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekranas bus sukamas automatiškai."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Užrakintas ekranas yra horizontalios orientacijos."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Užrakintas ekranas yra vertikalios orientacijos."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Svajonė"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Eternetas"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Lėktuvo režimas"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Įkraunama, <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Įkrauta"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"„Bluetooth“ (<xliff:g id="NUMBER">%d</xliff:g> įreng.)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"„Bluetooth“ išjungta"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Skaistis"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Automatiškai sukti"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Sukimas užrakintas"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Įvesties metodas"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Naudojama vieta"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Medijos įrenginys"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Tik skambučiai pagalbos numeriu"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Nustatymai"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Laikas"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Aš"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Neprisijungta"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Tinklo nėra"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"„Wi-Fi“ išjungta"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"„Wi-Fi“ pateiktis"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Belaidis rodymas"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Skaistis"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATINIS"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Pranešimai rodomi čia"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Perbraukę žemyn bet kuriuo metu pasieksite pranešimus."\n"Jei norite naudoti sistemos valdiklius, perbraukite žemyn dar kartą."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index e708804..57e70c8 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Skatīt"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Pēc noklusējuma izmantot šai USB ierīcei"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Pēc noklusējuma izmantot šim USB piederumam"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Vai atļaut USB atkļūdošanu?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Datora RSA atslēgas ciparfails: "\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Vienmēr atļaut no šī datora"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Tālumm., lai aizp. ekr."</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Stiepiet, lai aizp. ekr."</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Saderības tālummaiņa"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Dati: divas joslas."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Dati: trīs joslas."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Pilna piekļuve datu signālam."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Nav Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi: viena josla."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi: divas joslas."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi: trīs joslas."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Pilna piekļuve Wi-Fi signālam"</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi izslēgts"</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi savienojums ir pārtraukts."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi: viena josla"</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi: divas joslas"</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi: trīs joslas"</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Pilna piekļuve Wi-Fi signālam"</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Bez WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX viena josla."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX divas joslas."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX trīs joslas."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX signāls pilns."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Nav signāla."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Savienojums nav izveidots."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Nulle joslu"</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Viena josla"</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Divas joslas"</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Trīs joslas"</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Pilna piekļuve signālam"</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Ieslēgts"</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Izslēgts"</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Savienojums ir izveidots."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Viesabonēšana"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Nav SIM kartes."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Zvana signāls — vibrācija."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Zvana signāls — kluss."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Lietotne <xliff:g id="APP">%s</xliff:g> vairs netiek rādīta."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Paziņojums netiek rādīts."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Paziņojumu panelis"</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Ātrie iestatījumi"</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Pēdējās izmantotās lietotnes"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Lietotājs: <xliff:g id="USER">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobilo sakaru tīkls. <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Akumulatora statuss: <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Lidojuma režīma statuss: <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth statuss: <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Signāls ir iestatīts uz: <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G–3G dati atspējoti"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G dati atspējoti"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobilie dati atspējoti"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Notiek GPS meklēšana..."</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS iestatītā atrašanās vieta"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Notīrīt visus paziņojumus"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivizēt ekrānsaudzētāju"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informācija par lietotni"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Aizvērt"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Paziņojumi ir izslēgti"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Pieskarieties šeit, lai atkal ieslēgtu paziņojumus."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekrāns tiks pagriezts automātiski."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ekrāns tagad ir bloķēts ainavas orientācijā."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ekrāns tagad ir bloķēts portreta orientācijā."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Ekrānsaudzētājs"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Tīkls Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Lidojuma režīms"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Notiek uzlāde, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Uzlādēts"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> ierīce(-es))"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth savienojums ir izslēgts."</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Spilgtums"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Automātiska pagriešana"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Pagriešana bloķēta"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Ievades metode"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Izmantotā atrašanās vieta"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Multivides ierīce"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Tikai ārkārtas izsaukumi"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Iestatījumi"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Laiks"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Es"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nav izveidots savienojums"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nav tīkla"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ir izslēgts"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi displejs"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Bezvadu attēlošana"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Spilgtums"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMĀTISKI"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Šeit tiek rādīti paziņojumi"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Piekļūstiet tiem jebkurā laikā, velkot uz leju."\n"Vēlreiz velciet, lai tiktu parādītas sistēmas vadīklas."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 3265cd5..8505377 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Lihat"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gunakan secara lalai untuk peranti USB ini"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gunakan secara lalai untuk aksesori USB ini"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Benarkan penyahpepijatan USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Cap jari kekunci RSA komputer ialah:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Sentiasa benarkan komputer ini"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zum untuk memenuhi skrin"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Regang utk memenuhi skrin"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zum keserasian"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Data dua bar."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Data tiga bar."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Isyarat data penuh."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Tiada Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Satu bar Wi-Fi."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Dua bar Wi-Fi."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Tiga bar Wi-Fi."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Isyarat WiFi penuh."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi dimatikan."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wifi diputuskan sambungannya."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"WiFi satu bar."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"WiFi dua bar."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"WiFi tiga bar."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Isyarat WiFi penuh."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Tiada WiMAX"</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX satu bar."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX dua bar."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX tiga bar."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Isyarat WiMAX penuh."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Tiada isyarat."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Tidak disambungkan."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Tiada bar."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Satu bar."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Dua bar."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Tiga bar."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Isyarat penuh."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Dihidupkan."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Dimatikan."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Disambungkan."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Perayauan"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Tiada SIM."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Pendering bergetar."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Pendering senyap."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ditolak."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pemberitahuan diketepikan."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bidai pemberitahuan."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Tetapan pantas."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Apl terbaru."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Pengguna <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mudah Alih <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Bateri <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Mod Pesawat <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Penggera ditetapkan pada <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Data 2G-3G dilumpuhkan"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Data 4G dilumpuhkan"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Data mudah alih dilumpuhkan"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Mencari GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasi ditetapkan oleh GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Padamkan semua pemberitahuan."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktifkan gambar skrin"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Maklumat apl"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Tutup"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Pemberitahuan dimatikan"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Ketik di sini untuk menghidupkan kembali pemberitahuan."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skrin akan berputar secara automatik."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skrin dikunci dalam orientasi landskap."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skrin dikunci dalam orientasi potret."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Lamun"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mod kapal terbang"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Mengecas, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Sudah dicas"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Peranti)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Dimatikan"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Kecerahan"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Auto Putar"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Putaran Dikunci"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Kaedah Input"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Lokasi sedang digunakan"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Peranti media"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Panggilan Kecemasan Sahaja"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Tetapan"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Masa"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Saya"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Tidak Disambungkan"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Tiada Rangkaian"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Dimatikan"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Paparan Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Paparan Wayarles"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Kecerahan"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Pemberitahuan dipaparkan di sini"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Akses panel pada bila-bila masa dengan meleret ke bawah."\n"Leret ke bawah sekali lagi untuk mendapatkan kawalan sistem."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index a1ee469..e607632 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Vis"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Bruk som standard for denne USB-enheten"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Bruk som standard for dette USB-tilbehøret"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Vil du tillate USB-feilsøking?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Datamaskinens nøkkelfingeravtrykk for RSA er:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Tillat alltid fra denne datamaskinen"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom for å fylle skjermen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Strekk for å fylle skjerm"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitets-zooming"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Data – to stolper."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Data – tre stolper."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Datasignal er fullt."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Ingen Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Dekningssignal for Wi-Fi med én stolpe."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Dekningssignal for Wi-Fi med to stolper."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Dekningssignal for Wi-Fi med tre stolper."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Wi-Fi-signal er fullt."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi er av."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi er frakoblet."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi – én stolpe."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi – to stolper."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi – tre stolper."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wi-Fi-signal er ved full styrke."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Ingen WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX – én stolpe."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX – to stolper."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX – tre stolper."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Fullt WiMAX-signal."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Ikke noe signal."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Ikke tilkoblet."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Ingen stolper."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"En stolpe."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"To stolper."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Tre stolper."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Full signalstyrke."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"På."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Av."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Tilkoblet."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Datastreifing"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Uten SIM."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Vibreringsmodus."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Stille modus."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> avvist."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Varselet ble skjult."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Varselskygge."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Hurtiginnstillinger."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Nylige apper."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Bruker: <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobil – <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batteri – <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Flymodus – <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth – <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarmen ble stilt for <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G-data er deaktivert"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G-data er deaktivert"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobildata er deaktivert"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Søker etter GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Posisjon angitt av GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Fjern alle varslinger."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktiver skjermbeskytter"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Info om app"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Lukk"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Varsler er deaktivert"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Trykk her for å aktivere varsler på nytt."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skjermen roterer automatisk."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skjermen er låst i liggende retning."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skjermen er låst i stående retning."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Dagdrøm"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flymodus"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Lader: <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Oppladet"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> enheter)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth er slått av"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Lysstyrke"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Automatisk rotasjon"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotasjon er låst"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Inndatametode"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Posisjon i bruk"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Medieenhet"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Bare nødanrop"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Innstillinger"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Tidspunkt"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Meg"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ikke tilkoblet"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ingen nettverk"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi er av"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi-skjerm"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Trådløs skjerm"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Lysstyrke"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Varslene vises her"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Bruk dem når som helst ved å sveipe nedover."\n"Sveip nedover igjen for å gå til systemkontrollene."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 936e0958..c055aec 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Weergeven"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Standaard gebruiken voor dit USB-apparaat"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Standaard gebruiken voor dit USB-accessoire"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"USB-foutopsporing toestaan?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"De vingerafdruk voor de RSA-sleutel van de computer is:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Altijd toestaan vanaf deze computer"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom om scherm te vullen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rek uit v. schermvulling"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Compatibiliteitszoom"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Gegevens: twee streepjes."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Gegevens: drie streepjes."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Gegevenssignaal is op volle sterkte."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Geen wifi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wifi: één streepje."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wifi: twee streepjes."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wifi: drie streepjes."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Wi-Fi-signaal is op volledige sterkte."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi: uitgeschakeld."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wifi-verbinding verbroken."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wifi: één streepje."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wifi: twee streepjes."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wifi: drie streepjes."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wifi-signaal is op volledige sterkte."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Geen WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX: één streepje."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX: twee streepjes."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX: drie streepjes."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX-signaal  is op volle sterkte."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Geen signaal."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Niet verbonden."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Geen streepjes."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Eén streepje."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Twee streepjes."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Drie streepjes."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Signaal is op volledige sterkte."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Ingeschakeld."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Uitgeschakeld."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Verbonden."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wifi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Geen simkaart."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Belsoftware trilt."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Belsoftware stil."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> verwijderd."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Melding verwijderd."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Meldingenpaneel."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Snelle instellingen."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Recente apps."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Gebruiker: <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobiel <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Accu: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Vliegmodus: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm is ingesteld op <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-/3G-gegevens uitgeschakeld"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G-gegevens uitgeschakeld"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobiele gegevens uitgeschakeld"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Zoeken naar GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Locatie bepaald met GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Alle meldingen wissen."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Schermbeveiliging inschakelen"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"App-info"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Sluiten"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Meldingen uit"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Tik hier om meldingen weer in te schakelen."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Scherm wordt automatisch geroteerd."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Het scherm is nu vergrendeld in liggende stand."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Het scherm is nu vergrendeld in staande stand."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Dagdroom"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Vliegmodus"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Opladen, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Opgeladen"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> apparaten)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth uit"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Helderheid"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Automatische rotatie"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotatie vergrendeld"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Invoermethode"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Locatie in gebruik"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Media-apparaat"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Alleen noodoproepen"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Instellingen"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Tijd"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Ik"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wifi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Niet verbonden"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Geen netwerk"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wifi uit"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wifi-weergave"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Draadloze display"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Helderheid"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATISCH"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Meldingen worden hier weergegeven"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"U kunt de meldingen op elk gewenst moment openen door met uw vinger omlaag te vegen."\n"Veeg nogmaals met uw vinger omlaag om de systeembesturingselementen weer te geven."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index b4a77a2..c454bb1 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Wyświetl"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Używaj domyślnie dla tego urządzenia USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Używaj domyślnie dla tego akcesorium USB"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Zezwalać na debugowanie USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Odcisk cyfrowy klucza RSA komputera to:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Zawsze zezwalaj z tego komputera"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Powiększ, aby wypełnić ekran"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rozciągnij, aby wypełnić ekran"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Powiększenie w trybie zgodności"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Dane: dwa paski."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Dane: trzy paski."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Dane: pełna moc sygnału."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Brak sieci Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi jeden pasek."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi dwa paski."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi trzy paski."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Sieć Wi-Fi: pełna moc sygnału."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi wyłączone."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi rozłączone."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi: jeden pasek."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi: dwa paski."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi: trzy paski."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wi-Fi: pełna moc sygnału."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"WiMAX: brak"</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX: jeden pasek"</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX: dwa paski"</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX: trzy paski"</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX: pełna moc sygnału"</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Brak sygnału."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Nie połączono."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Zero pasków."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Jeden pasek."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Dwa paski."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Trzy paski."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Pełna moc sygnału."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Wł."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Wył."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Połączono."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Brak karty SIM."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Dzwonek z wibracjami."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Dzwonek wyciszony."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>: zamknięto."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Zamknięto powiadomienie."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Obszar powiadomień."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Szybkie ustawienia."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Ostatnii używane aplikacje."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Użytkownik: <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Sieć komórkowa: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Bateria: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Tryb samolotowy: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm ustawiony na <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Wyłączono transmisję danych 2G/3G"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Wyłączono transmisję danych 4G"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Wyłączono komórkową transmisję danych"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Wyszukiwanie sygnału GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokalizacja ustawiona według GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Usuń wszystkie powiadomienia."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Włącz wygaszacz ekranu."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"O aplikacji"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Zamknij"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Powiadomienia wyłączone"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Kliknij tutaj, by przywrócić powiadomienia."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran zostanie obrócony automatycznie."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ekran jest zablokowany w orientacji poziomej."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ekran jest zablokowany w orientacji pionowej."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Wygaszacz ekranu"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Tryb samolotowy"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Ładowanie (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Naładowana"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (urządzenia: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth wył."</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Jasność"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Autoobracanie"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Obracanie jest zablokowane"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Metoda wprowadzania"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Lokalizacja w użyciu"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Urządzenie multimedialne"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Tylko połączenia alarmowe"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Ustawienia"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Godzina"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Ja"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Brak połączenia"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Brak sieci"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wyłącz Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wyświetlacz Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Wyświetlacz bezprzewodowy"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Jasność"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATYCZNA"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Tutaj pokazują się powiadomienia"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Możesz je otworzyć w dowolnej chwili, przesuwając w dół."\n"Przesuń jeszcze raz w dół, by otworzyć ustawienia systemowe."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-port/config.xml b/packages/SystemUI/res/values-port/config.xml
deleted file mode 100644
index bbae18d..0000000
--- a/packages/SystemUI/res/values-port/config.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
-     for different hardware and product builds. -->
-<resources>
-    <!-- Whether we're using the tablet-optimized recents interface (we use this
-     value at runtime for some things) -->
-    <integer name="status_bar_recents_bg_gradient_degrees">90</integer>
-</resources>
-
diff --git a/packages/SystemUI/res/values-port/dimens.xml b/packages/SystemUI/res/values-port/dimens.xml
deleted file mode 100644
index de7b836..0000000
--- a/packages/SystemUI/res/values-port/dimens.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (c) 2006, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
--->
-<resources>
-    <!-- Recent Applications parameters -->
-    <!-- How far the thumbnail for a recent app appears from left edge -->
-    <dimen name="status_bar_recents_thumbnail_left_margin">20dp</dimen>
-    <!-- Padding for text descriptions -->
-    <dimen name="status_bar_recents_text_description_padding">8dp</dimen>
-    <!-- Width of application label text -->
-    <dimen name="status_bar_recents_app_label_width">88dip</dimen>
-    <!-- Left margin of application label text -->
-    <dimen name="status_bar_recents_app_label_left_margin">0dip</dimen>
-    <!-- Margin between recents container and glow on the right -->
-    <dimen name="status_bar_recents_right_glow_margin">100dip</dimen>
-    <!-- Padding between recents items -->
-    <dimen name="status_bar_recents_item_padding">0dip</dimen>
-    <!-- Where to place the app icon over the thumbnail -->
-    <dimen name="status_bar_recents_app_icon_left_margin">0dp</dimen>
-    <dimen name="status_bar_recents_app_icon_top_margin">8dp</dimen>
-</resources>
diff --git a/packages/SystemUI/res/values-port/strings.xml b/packages/SystemUI/res/values-port/strings.xml
deleted file mode 100644
index 67364a4..0000000
--- a/packages/SystemUI/res/values-port/strings.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * 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.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index d08c529..1b8370b 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Ver"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utilizar por predefinição para este aparelho USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utilizar por predefinição para este acessório USB"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Permitir depuração USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"A impressão digital da chave RSA do computador é:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Permitir sempre a partir deste computador"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para preencher o ecrã"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Esticar p. caber em ec. int."</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilidade"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Duas barras de dados."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Três barras de dados."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Sinal de dados completo."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Sem Wi-Fi"</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Uma barra de Wi-Fi."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Duas barras de Wi-Fi."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Três barras de Wi-Fi."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Sinal Wi-Fi completo."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi desativado."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi desligado."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Uma barra de Wi-Fi."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Duas barras de Wi-Fi."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Três barras de Wi-Fi."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Sinal Wi-Fi completo."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Sem WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Uma barra de WiMAX."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Duas barras de WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Três barras de WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Sinal WiMAX completo."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Sem sinal."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Sem ligação."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Zero barras."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Uma barra."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Duas barras."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Três barras."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Sinal completo."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Ativado."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Desativado."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Ligado."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Sem SIM."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Campainha em vibração."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Campainha em silêncio."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ignorado."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação ignorada."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Painel de notificações."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Definições rápidas."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Aplicações recentes"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Utilizador <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Dispositivo Móvel <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Bateria <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modo de Avião <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarme definido para <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Os dados 2G-3G estão desativados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Os dados 4G estão desativados"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Os dados móveis estão desativados"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"A procurar GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Localização definida por GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ativar proteção de ecrã"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informações da aplicação"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Fechar"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notificações desativadas"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Toque aqui para voltar a ativar as notificações."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"O ecrã será rodado automaticamente."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"O ecrã está bloqueado na orientação horizontal."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"O ecrã está bloqueado na orientação vertical."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo de avião"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"A carregar, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Carregada"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Dispositivos)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desat."</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brilho"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Rodar automat."</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotação Bloqueada"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Método de Introdução"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Localização em utilização"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Dispositivo multimédia"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Apenas Chamadas de Emergência"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Definições"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Hora"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Eu"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Não Ligado"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Sem Rede"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Desligado"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Visualização Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Display Sem Fios"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brilho"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÁTICO"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"As notificações são apresentadas aqui"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Pode aceder em qualquer altura, deslizando rapidamente para baixo com o dedo."\n"Deslize novamente para baixo para aceder aos controlos do sistema."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 596ceec..a14ee38 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Visualizar"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Usar por padrão para este dispositivo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Usar por padrão para este acessório USB"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Permitir a depuração USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"A impressão digital da chave RSA deste computador é:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Sempre permitir a partir deste computador"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom p/ preencher a tela"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Ampliar p/ preencher tela"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom em modo de compatibilidade"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Duas barras de sinal de dados."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Três barras do sinal de dados."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Sinal de dados cheio."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Nenhum sinal Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Uma barra de Wi-Fi."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Duas barras de Wi-Fi."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Três barras de Wi-Fi."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Sinal do Wi-Fi cheio."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi desligado."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi desconectado."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Uma barra de sinal Wi-Fi."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Duas barras de sinal Wi-Fi."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Três barras de sinal Wi-Fi."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Sinal Wi-Fi cheio."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Sem WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Uma barra do WiMAX."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Duas barras do WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Três barras do WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Sinal WiMAX completo."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Sem sinal."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Sem conexão."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Nenhuma barra."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Uma barra."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Duas barras."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Três barras."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Sinal cheio."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Ligado."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Desligado."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Conectado."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Sem SIM."</string>
@@ -129,6 +146,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Vibração da campainha."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Campainha silenciosa."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartado."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação dispensada."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Aba de notificações."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Configurações rápidas."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Aplicativos recentes."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Usuário <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Celular <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Bateria <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modo para avião <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarme definido para <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Dados 2G e 3G desativados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Dados 4G desativados"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Dados móveis desativados"</string>
@@ -140,11 +168,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Buscando GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Local definido por GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ativar proteção de tela"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informações do aplicativo"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Fechar"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notificações desativadas"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Toque aqui para ativar as notificações novamente."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"A tela girará automaticamente."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"A tela está bloqueada na orientação paisagem."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"A tela está bloqueada na orientação retrato."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo para avião"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Carregando, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Carregado"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desativado"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brilho"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Girar automat."</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotação bloqueada"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Método de entrada"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Local em uso"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Dispositivo de mídia"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Somente chamadas de emergência"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Configurações"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Hora"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Eu"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Não conectado"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Sem rede"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desligado"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Display"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Display sem fio"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brilho"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"As notificações aparecem aqui"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Acesse a qualquer momento deslizando para baixo."\n"Deslize para baixo novamente para acessar os controles do sistema."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 16e5719..606160b 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -86,6 +86,12 @@
     <skip />
     <!-- no translation found for always_use_accessory (1210954576979621596) -->
     <skip />
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <!-- no translation found for compat_mode_on (6623839244840638213) -->
     <skip />
     <!-- no translation found for compat_mode_off (4434467572461327898) -->
@@ -164,15 +170,17 @@
     <skip />
     <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
     <skip />
-    <!-- no translation found for accessibility_no_wifi (7455607460517331976) -->
+    <!-- no translation found for accessibility_wifi_off (3177380296697933627) -->
     <skip />
-    <!-- no translation found for accessibility_wifi_one_bar (6854947280074467207) -->
+    <!-- no translation found for accessibility_no_wifi (1425476551827924474) -->
     <skip />
-    <!-- no translation found for accessibility_wifi_two_bars (3344340012058984348) -->
+    <!-- no translation found for accessibility_wifi_one_bar (7735893178010724377) -->
     <skip />
-    <!-- no translation found for accessibility_wifi_three_bars (928322805193265041) -->
+    <!-- no translation found for accessibility_wifi_two_bars (4994274250497262434) -->
     <skip />
-    <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+    <!-- no translation found for accessibility_wifi_three_bars (3495755044276588384) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (6853561303586480376) -->
     <skip />
     <!-- no translation found for accessibility_no_wimax (4329180129727630368) -->
     <skip />
@@ -184,8 +192,32 @@
     <skip />
     <!-- no translation found for accessibility_wimax_signal_full (2768089986795579558) -->
     <skip />
+    <!-- no translation found for accessibility_no_signal (7064645320782585167) -->
+    <skip />
+    <!-- no translation found for accessibility_not_connected (6395326276213402883) -->
+    <skip />
+    <!-- no translation found for accessibility_zero_bars (3806060224467027887) -->
+    <skip />
+    <!-- no translation found for accessibility_one_bar (1685730113192081895) -->
+    <skip />
+    <!-- no translation found for accessibility_two_bars (6437363648385206679) -->
+    <skip />
+    <!-- no translation found for accessibility_three_bars (2648241415119396648) -->
+    <skip />
+    <!-- no translation found for accessibility_signal_full (9122922886519676839) -->
+    <skip />
+    <!-- no translation found for accessibility_desc_on (2385254693624345265) -->
+    <skip />
+    <!-- no translation found for accessibility_desc_off (6475508157786853157) -->
+    <skip />
+    <!-- no translation found for accessibility_desc_connected (8366256693719499665) -->
+    <skip />
     <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
     <skip />
+    <!-- no translation found for accessibility_data_connection_1x (994133468120244018) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_hspa (2032328855462645198) -->
+    <skip />
     <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
     <skip />
     <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
@@ -194,6 +226,8 @@
     <skip />
     <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
     <skip />
+    <!-- no translation found for accessibility_data_connection_roaming (5977362333466556094) -->
+    <skip />
     <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
     <skip />
     <!-- no translation found for accessibility_data_connection_wifi (2324496756590645221) -->
@@ -224,6 +258,28 @@
     <skip />
     <!-- no translation found for accessibility_recents_item_dismissed (6803574935084867070) -->
     <skip />
+    <!-- no translation found for accessibility_notification_dismissed (854211387186306927) -->
+    <skip />
+    <!-- no translation found for accessibility_desc_notification_shade (4690274844447504208) -->
+    <skip />
+    <!-- no translation found for accessibility_desc_quick_settings (6186378411582437046) -->
+    <skip />
+    <!-- no translation found for accessibility_desc_recent_apps (9014032916410590027) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_user (1104846699869476855) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_wifi (6099781031669728709) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_mobile (4876806564086241341) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_battery (1480931583381408972) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_airplane (4196876722090224753) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_bluetooth (5749054971341882340) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_alarm (3959908972897295660) -->
+    <skip />
     <!-- no translation found for data_usage_disabled_dialog_3g_title (5257833881698644687) -->
     <skip />
     <!-- no translation found for data_usage_disabled_dialog_4g_title (4789143363492682629) -->
@@ -246,10 +302,10 @@
     <skip />
     <!-- no translation found for accessibility_clear_all (5235938559247164925) -->
     <skip />
-    <!-- no translation found for dreams_dock_launcher (3541196417659166245) -->
-    <skip />
     <!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
     <skip />
+    <!-- no translation found for close_universe (3736513750241754348) -->
+    <skip />
     <!-- no translation found for notifications_off_title (8936620513608443224) -->
     <skip />
     <!-- no translation found for notifications_off_text (2529001315769385273) -->
@@ -260,4 +316,64 @@
     <skip />
     <!-- no translation found for accessibility_rotation_lock_on_portrait (5809367521644012115) -->
     <skip />
+    <!-- no translation found for jelly_bean_dream_name (5992026543636816792) -->
+    <skip />
+    <!-- no translation found for start_dreams (7219575858348719790) -->
+    <skip />
+    <!-- no translation found for ethernet_label (7967563676324087464) -->
+    <skip />
+    <!-- no translation found for quick_settings_airplane_mode_label (5510520633448831350) -->
+    <skip />
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- no translation found for quick_settings_battery_charged_label (8865413079414246081) -->
+    <skip />
+    <!-- no translation found for quick_settings_bluetooth_label (6304190285170721401) -->
+    <skip />
+    <!-- no translation found for quick_settings_bluetooth_multiple_devices_label (3912245565613684735) -->
+    <skip />
+    <!-- no translation found for quick_settings_bluetooth_off_label (8159652146149219937) -->
+    <skip />
+    <!-- no translation found for quick_settings_brightness_label (6968372297018755815) -->
+    <skip />
+    <!-- no translation found for quick_settings_rotation_unlocked_label (336054930362580584) -->
+    <skip />
+    <!-- no translation found for quick_settings_rotation_locked_label (8058646447242565486) -->
+    <skip />
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <!-- no translation found for quick_settings_location_label (3292451598267467545) -->
+    <skip />
+    <!-- no translation found for quick_settings_media_device_label (1302906836372603762) -->
+    <skip />
+    <!-- no translation found for quick_settings_rssi_label (7725671335550695589) -->
+    <skip />
+    <!-- no translation found for quick_settings_rssi_emergency_only (2713774041672886750) -->
+    <skip />
+    <!-- no translation found for quick_settings_settings_label (5326556592578065401) -->
+    <skip />
+    <!-- no translation found for quick_settings_time_label (4635969182239736408) -->
+    <skip />
+    <!-- no translation found for quick_settings_user_label (5238995632130897840) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_label (9135344704899546041) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_not_connected (7171904845345573431) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_off_label (7558778100843885864) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_label (6893592964463624333) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_no_connection_label (2355298740765736918) -->
+    <skip />
+    <!-- no translation found for quick_settings_brightness_dialog_title (8599674057673605368) -->
+    <skip />
+    <!-- no translation found for quick_settings_brightness_dialog_auto_brightness_label (5064982743784071218) -->
+    <skip />
+    <!-- no translation found for status_bar_help_title (1199237744086469217) -->
+    <skip />
+    <!-- no translation found for status_bar_help_text (7874607155052076323) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 87eec9f..4618559 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Afişaţi"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utilizaţi în mod prestabilit pt. acest dispoz. USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utiliz. în mod prestabilit pt. acest accesoriu USB"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Permiteţi depanarea USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Amprenta digitală din cheia RSA a computerului este:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Permiteţi întotdeauna de pe acest computer"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom pt. a umple ecranul"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Înt. pt. a umple ecranul"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilitate"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Semnal pentru date: două bare."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Semnal pentru date: trei bare."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Semnal pentru date: complet."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Nu există conexiune Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi o bară."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi două bare."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi trei bare."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Semnal Wi-Fi: complet."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi dezactivat."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi deconectat."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Semnal Wi-Fi: o bară."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Semnal Wi-Fi: două bare."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Semnal Wi-Fi: trei bare."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Semnal Wi-Fi: complet."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Fără WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX o bară."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX două bare."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX trei bare."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX semnal complet."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Fără semnal."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Neconectat."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Nicio bară."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"O bară."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Două bare."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Trei bare."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Semnal complet."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Activat."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Dezactivat."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Conectat."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Niciun card SIM."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Vibrare sonerie."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Sonerie silenţioasă."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> a fost eliminată."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificarea a fost închisă."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Fereastră pentru notificări."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Setări rapide."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Aplicaţii recente"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Utilizatorul <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Semnal mobil: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Baterie <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Mod Avion <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarmă setată pentru <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Datele 2G-3G au fost dezactivate"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Datele 4G au fost dezactivate"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Datele mobile au fost dezactivate"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Se caută GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Locaţie setată prin GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ştergeţi toate notificările."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Activaţi screensaverul"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informaţii despre aplicaţie"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Închideţi"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Notificările sunt dezactivate"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Apăsaţi aici pentru a reactiva notificările."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ecranul se va roti în mod automat."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ecranul este blocat în orientarea de tip peisaj."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ecranul este blocat în orientarea de tip portret."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mod Avion"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Se încarcă, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Încărcată"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispozitive)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth dezactivat"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Luminozitate"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Rotire automată"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotire blocată"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Metodă de introducere"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Locaţie în uz"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Dispozitiv media"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Numai apeluri de urgenţă"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Setări"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Ora"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Eu"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Neconectat"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nicio reţea"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi deconectat"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Afişaj Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Ecran wireless"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Luminozitate"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMAT"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Notificările se afişează aici"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Accesaţi-le oricând glisând în jos."\n"Glisaţi în jos din nou pentru comenzile sistemului."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 7a7d08f..28fe0d2 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -25,7 +25,7 @@
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Показать уведомления"</string>
     <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Удаление из списка"</string>
     <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"О приложении"</string>
-    <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"Нет данных"</string>
+    <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"В последнее время вы не запускали приложения."</string>
     <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Закрыть недавние приложения"</string>
   <plurals name="status_bar_accessibility_recent_apps">
     <item quantity="one" msgid="5854176083865845541">"Недавних приложений: 1"</item>
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Просмотр"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Использовать по умолчанию для этого USB-устройства"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Использовать по умолчанию для этого USB-аксессуара"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Отладка по USB"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Цифровой отпечаток ключа RSA:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Всегда разрешать отладку с этого компьютера"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Подогнать по размерам экрана"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Растянуть на весь экран"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Масштаб и совместимость"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Сигнал передачи данных: два деления."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Сигнал передачи данных: три деления."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Надежный сигнал передачи данных."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Отсутствует подключение к Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi: одно деление."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi: два деления."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi: три деления."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Надежный сигнал Wi-Fi."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi выключен"</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi выключен"</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi: одно деление"</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi: два деления"</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi: три деления"</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wi-Fi: надежный сигнал"</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Нет сигнала WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Сигнал WiMAX: одно деление."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Сигнал WiMAX: два деления."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Сигнал WiMAX: три деления."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Надежный сигнал WiMAX."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Нет сигнала"</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Не подключено"</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Нет сигнала"</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"одно деление"</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"два деления"</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"три деления"</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"надежный сигнал"</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"ВКЛ"</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"ВЫКЛ"</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Подключено"</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Роуминг"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM-карта отсутствует."</string>
@@ -129,22 +146,65 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Вибровызов."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Беззвучный режим."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" удалено из списка."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Уведомление закрыто"</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Панель уведомлений"</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Быстрые настройки"</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Недавние приложения"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Пользователь <xliff:g id="USER">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="NETWORK">%2$s</xliff:g>: <xliff:g id="SIGNAL">%1$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Мобильная сеть: <xliff:g id="NETWORK">%3$s</xliff:g> (<xliff:g id="TYPE">%2$s</xliff:g>, <xliff:g id="SIGNAL">%1$s</xliff:g>)"</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Батарея: <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Режим полета <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Будильник установлен на <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Передача данных по каналам 2G и 3G отключена"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Передача данных по каналу 4G отключена"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Моб. Интернет отключен"</string>
     <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"Передача данных отключена"</string>
     <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"Достигнут лимит трафика."\n\n"При восстановлении подключения оператор может взимать плату за передачу данных."</string>
     <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"Восстановить подключение"</string>
-    <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Нет подключения к Интернету"</string>
+    <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Нет интернет-подключения"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi подключено"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Поиск GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Координаты по GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Удалить все уведомления"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Активация заставки экрана"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"О приложении"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Закрыть"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Уведомления отключены"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Нажмите здесь, чтобы снова включить уведомления."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Экран будет поворачиваться автоматически."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Выбрана только альбомная ориентация экрана."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Выбрана только книжная ориентация экрана."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Заставка"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Режим полета"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for quick_settings_battery_charged_label (8865413079414246081) -->
+    <skip />
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g>)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth выкл."</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Яркость"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Автоповорот"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Автоповорот выкл."</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Способ ввода"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Геосервис вкл."</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Режим медиа"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Экстр. вызов"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Настройки"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Время"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Вы"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Нет соединения"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Нет сети"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi выкл."</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Проектор Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Беспроводной проектор"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Яркость"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТОНАСТРОЙКА"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Это панель уведомлений"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Ее можно открыть, пролистнув экран вниз."\n"Чтобы открыть настройки, проведите пальцем вниз ещё раз."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 8e64487..c5143dd 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Zobraziť"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Pre toto zariadenie USB použiť ako predvolené"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Pre toto periférne zar. USB použiť ako predvolené"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Povoliť ladenie USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Digitálny odtlačok RSA počítača je:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Vždy povoliť z tohto počítača"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Priblížiť na celú obrazovku"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Na celú obrazovku"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Úprava veľkosti z dôvodu kompatibility"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Dve čiarky signálu dátovej siete."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Tri čiarky signálu dátovej siete."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Plný signál dátovej siete."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Žiadna sieť Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Jedna čiarka signálu Wi-Fi."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Dve čiarky signálu Wi-Fi."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Tri čiarky signálu Wi-Fi."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Plný signál siete Wi-Fi."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Sieť Wi-Fi je vypnutá."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Sieť Wi-Fi je odpojená."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Jedna čiarka signálu siete Wi-Fi."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Dve čiarky signálu siete Wi-Fi."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Tri čiarky signálu siete Wi-Fi."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Plný signál siete Wi-Fi."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Žiadna sieť WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Jeden stĺpec signálu siete WiMAX."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Dva stĺpce signálu siete WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Tri stĺpce signálu siete WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Plný signál siete WiMAX."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Žiadny signál."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Nepripojené."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Žiadna čiarka."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Jedna čiarka."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Dve čiarky."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Tri čiarky."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Plný signál."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Zapnuté."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Vypnuté."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Pripojené."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Žiadna karta SIM."</string>
@@ -129,6 +146,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Vibračné zvonenie."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Tiché zvonenie."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikácia <xliff:g id="APP">%s</xliff:g> bola zrušená."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Upozornenie bolo zrušené."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Panel upozornení."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Rýchle nastavenia."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Nedávne aplikácie"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Používateľ: <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobil: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batéria: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Režim V lietadle: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Budík nastavený na <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Dátové prenosy 2G a 3G sú zakázané"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Dátové prenosy 4G sú zakázané"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobilné dátové prenosy sú zakázané"</string>
@@ -140,11 +168,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Vyhľadávanie satelitov GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Poloha nastavená pomocou GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazať všetky upozornenia."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivovať šetrič obrazovky"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informácie o aplikácii"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Zavrieť"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Upozornenia sú vypnuté"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Klepnutím sem upozornenia znova povolíte."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Obrazovka sa automaticky otočí."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Obrazovka je uzamknutá v orientácii na šírku."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Obrazovka je uzamknutá v orientácii na výšku."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Šetrič obrazovky"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Režim V lietadle"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Nabíjanie, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Nabité"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Rozhranie Bluetooth (počet zariadení: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Rozhranie Bluetooth je vypnuté"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Jas"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Automatické otáčanie"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Otáčanie uzamknuté"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Metóda vstupu"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Používaná poloha"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Mediálne zariadenie"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Len tiesňové volania"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Nastavenia"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Čas"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Ja"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nepripojené"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Žiadna sieť"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Sieť Wi-Fi je vypnutá"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Obrazovka Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Bezdrôtový displej"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Jas"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATICKY"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Tu sa zobrazujú upozornenia"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Môžete ich kedykoľvek zobraziť tak, že posuniete prstom nadol."\n"Ak posuniete prstom nadol ešte raz, zobrazia sa ovládacie prvky systému."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 1fa3b21..48f0893 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Prikaži"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Privzeto uporabi za to napravo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Privzeto uporabi za ta dodatek USB"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Ali dovolite odpravljanje težav prek USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Računalnikov prstni odtis ključa RSA je:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Vedno dovoli iz tega računalnika"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Povečava čez cel zaslon"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Raztegnitev čez zaslon"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Razširitev združljivosti"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Podatki z dvema črticama."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Podatki s tremi črticami."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Podatkovni signal poln."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Ni signala Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Ena vrstica signala Wi-Fi."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Dve črtici signala Wi-Fi."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Tri črtice signala Wi-Fi."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Signal Wi-Fi poln."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi je izklopljen."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Povezava Wi-Fi je prekinjena."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi z eno črtico."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi z dvema črticama."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi s tremi črticami."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Poln signal Wi-Fi."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Ni signala WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Signal WiMAX: ena črtica."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Signal WiMAX: dve črtici."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Signal WiMAX: tri črtice."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Poln signal WiMAX."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Ni signala."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Ni povezan."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Nič črtic."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Ena črtica."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Dve črtici."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Tri črtice."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Poln signal."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Vklopljen."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Izklopljen."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Povezan."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Gostovanje"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Ni kartice SIM."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Zvonjenje z vibriranjem."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Zvonjenje izklopljeno."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Program <xliff:g id="APP">%s</xliff:g> je bil odstranjen."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obvestilo je bilo odstranjeno."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Zaslon z obvestili."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Hitre nastavitve."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Nedavne aplikacije."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Uporabnik: <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobilni telefon: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Baterija: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Letalski način: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm je nastavljen na <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Podatki 2G-3G so onemogočeni"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Podatki 4G so onemogočeni"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobilni podatki so onemogočeni"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Iskanje GPS-a"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokacija nastavljena z GPS-om"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Izbriši vsa obvestila."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Vklop ohranjevalnika zaslona"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Podatki o aplikaciji"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Zapri"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Obvestila so izklopljena"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Dotaknite se tukaj, da ponovno vklopite obvestila."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Zaslon se bo samodejno zasukal."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Zaslon je zaklenjen v ležeči usmerjenosti."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Zaslon je zaklenjen v pokončni usmerjenosti."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Sanjarjenje"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Način za letalo"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Polnjenje, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Napolnjeno"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (št. naprav: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth izklopljen"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Svetlost"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Samodejno vrtenje"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Zaklenjeno vrtenje"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Način vnosa"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Mesto uporabe"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Predstavnostna naprava"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Le klici v sili"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Nastavitve"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Čas"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Jaz"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Povezava ni vzpostavljena"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ni omrežja"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi izklopljen"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Zaslon Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Prikaz brezžičnih naprav"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Svetlost"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"SAMODEJNO"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Obvestila so prikazana tukaj"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Do njih lahko kadar koli dostopate tako, da povlečete navzdol."\n"Za prikaz sistemskih kontrolnikov znova povlecite navzdol."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index fd41e02..42ab38a1 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Прикажи"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Користи подразумевано за овај USB уређај"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Користи подразумевано за овај USB додатак"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Желите ли да дозволите отклањање USB грешака?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Дигитални отисак RSA кључа овог рачунара је:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Увек дозволи са овог рачунара"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Зумирај на целом екрану"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Развуци на цео екран"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Компатибилно зумирање"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Сигнал за податке од две црте."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Сигнал за податке од три црте."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Сигнал за податке је најјачи."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Нема Wi-Fi сигнала."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi сигнал има једну црту."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi сигнал има две црте."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi сигнал има три црте."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"WiFi сигнал је најјачи."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi је искључен."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi веза је прекинута."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi сигнал од једне црте."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi сигнал од две црте."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi сигнал од три црте."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wi-Fi сигнал је најјачи."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Нема WiMAX сигнала."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX сигнал има једну црту."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX сигнал има две црте."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX сигнал има три црте."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX сигнал је најјачи."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Нема сигнала."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Није повезано."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Ниједна црта."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Једна црта."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Две црте."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Три црте."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Сигнал је најјачи."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Укључено."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Искључено."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Повезано је."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Роминг"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Нема SIM картице."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Вибрација звона."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Нечујно звоно."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Апликација <xliff:g id="APP">%s</xliff:g> је одбачена."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Обавештење је одбачено."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Прозор са обавештењима."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Брза подешавања."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Недавне апликације."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Корисник: <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Мобилна мрежа: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Батерија: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Режим рада у авиону: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Аларм је подешен за <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G–3G подаци су онемогућени"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G подаци су онемогућени"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Подаци мобилне мреже су онемогућени"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Тражи се GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Локацију је подесио GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Обриши сва обавештења."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Активирање чувара екрана"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Информације о апликацији"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Затвори"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Обавештења су искључена"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Додирните овде да бисте поново укључили обавештења."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екран ће се аутоматски ротирати."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Екран је закључан у хоризонталном положају."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Екран је закључан у вертикалном положају."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Сањарење"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Етернет"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Режим рада у авиону"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Пуњење, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Напуњено"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> уређаја)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth искључен"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Осветљеност"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Аутоматско ротирање"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Ротирање је закључано"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Метод уноса"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Локација која се користи"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Медијски уређај"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Само хитни позиви"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Подешавања"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Време"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Ја"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Веза није успостављена"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Нема мреже"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi је искључен"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi екран"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Бежични екран"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Осветљеност"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АУТОМАТСКА"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Обавештења се појављују овде"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Приступите им у било ком тренутку листањем надоле."\n"Поново листајте надоле да би се приказале системске контроле."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index afbe0fb..7bf9d4c 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Visa"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Använd som standard för den här USB-enheten"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Använd som standard för det här USB-tillbehöret"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Ska USB-felsökning tillåtas?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Fingeravtrycket för datorns RSA-nyckel är:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Tillåt alltid på den här datorn"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zooma för att fylla skärm"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Dra för att fylla skärmen"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom i kompatibilitetsläge"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Data: två staplar."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Data: tre staplar."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Datasignalen är full."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Inget Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi: en stapel."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi: två staplar."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi: tre staplar."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Wi-Fi-signalen är full."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi är inaktiverat."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Ingen Wi-Fi-anslutning."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi: en stapel."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi: två staplar."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi: tre staplar."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Full signalstyrka för Wi-Fi."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Ingen WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX: en stapel."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX: två staplar."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX: tre staplar."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX-signalen är full."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Ingen signal."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Inte ansluten."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Inga staplar."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Ett fält."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Två staplar."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Tre staplar."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Full signalstyrka."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Aktiverad."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Inaktiverad."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Ansluten."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Inget SIM-kort."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Vibrerande ringsignal."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Tyst ringsignal."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> togs bort permanent."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Meddelandet ignorerades."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Meddelandepanel."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Snabbinställningar."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Senaste apparna"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Användare <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobil <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batteri <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Flygplansläge <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarmet ringer <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Data via 2G-3G har inaktiverats"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Data via 4G har inaktiverats"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobildata har inaktiverats"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Sökning efter GPS pågår"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Platsen har identifierats av GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ta bort alla meddelanden."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Aktivera skärmsläckare"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Info om appen"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Stäng"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Meddelanden inaktiverade"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Knacka lätt här om du vill aktivera meddelanden igen."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skärmen roteras automatiskt."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Bildskärmens riktning är nu låst i liggande format."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Bildskärmens riktning är nu låst i stående format."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Dagdröm"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flygplansläge"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Laddar, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Laddat"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> enheter)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Inaktivera Bluetooth"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Ljusstyrka"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Rotera automatiskt"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotationen har låsts"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Inmatningsmetod"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Plats som används"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Medieenhet"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Endast nödsamtal"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Inställningar"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Tid"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Jag"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ej ansluten"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Inget nätverk"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi är inaktiverat"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi visas"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Trådlös visning"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Ljusstyrka"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Meddelanden visas här"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Du kommer åt dem när som helst genom att dra nedåt."\n"Dra nedåt igen om du vill visa systemkontroller."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 8f22b81c..3e4af20 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -26,7 +26,7 @@
     <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Ondoa kwenye orodha"</string>
     <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Taarifa za programu-matumizi"</string>
     <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"Hakuna programu za sasa"</string>
-    <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Ondosha prog za hivi karibuni"</string>
+    <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Ondosha programu za hivi karibuni"</string>
     <!-- String.format failed for translation -->
     <!-- no translation found for status_bar_accessibility_recent_apps:other (1040784359794890744) -->
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Hakuna arifa"</string>
@@ -51,22 +51,25 @@
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Ruhusu programu <xliff:g id="APPLICATION">%1$s</xliff:g> kufikia kifaa cha ziada cha USB?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Je, ungetaka kufungua  <xliff:g id="ACTIVITY">%1$s</xliff:g>wakati kifaa cha USB kimeunganishwa?"</string>
     <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"Je, ungetaka kufungua  <xliff:g id="ACTIVITY">%1$s</xliff:g>wakati kifaa cha USB kimeunganishwa?"</string>
-    <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Hakuna programu zilizosakinishwa zinazofanya kazi na kifaa hiki cha USB. Jifunze zaidi kuhusu kifaa hiki kwenye <xliff:g id="URL">%1$s</xliff:g>"</string>
+    <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Hakuna programu zilizosakinishwa zinazofanya kazi na kifaa hiki cha USB. Pata maelezo zaidi kuhusu kifaa hiki kwenye <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Kifaa cha Usb"</string>
     <string name="label_view" msgid="6304565553218192990">"Ona"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Kwa kifaa hiki cha USB tumia chaguo-msingi"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Tumia kama chaguo-msingi ya kifuasi hiki cha USB"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Ruhusu utatuaji wa USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Alama ya kidole ya kitufe cha RSA ya kompyuta ni:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Ruhusu kutoka kwenye kompyuta hii kila wakati"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Kuza ili kujaza skrini"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Tanua ili kujaza skrini"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kukuza kwa Utangamanifu"</string>
     <string name="compat_mode_help_body" msgid="4946726776359270040">"Wakati programu ilibuniwa kwa skrini ndogo, kidhibiti cha kukuza kitaonekana kwa saa."</string>
-    <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Inahifadhi picha kiwamba..."</string>
-    <string name="screenshot_saving_title" msgid="8242282144535555697">"Inahifadhi picha kiwamba..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Picha kiwamba inahifadhiwa"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Picha kiwamba imenaswa."</string>
-    <string name="screenshot_saved_text" msgid="1152839647677558815">"Gusa ili kuona picha kiwamba yako"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Haikuweza kunasa picha kiwamba"</string>
-    <string name="screenshot_failed_text" msgid="8134011269572415402">"Haikuweza kuhifadhi picha kiwamba. Hifadhi inaweza kuwa inatumika."</string>
+    <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Inahifadhi picha ya skrini..."</string>
+    <string name="screenshot_saving_title" msgid="8242282144535555697">"Inahifadhi picha ya skrini..."</string>
+    <string name="screenshot_saving_text" msgid="2419718443411738818">"Picha ya skrini inahifadhiwa"</string>
+    <string name="screenshot_saved_title" msgid="6461865960961414961">"Picha ya skrini imenaswa."</string>
+    <string name="screenshot_saved_text" msgid="1152839647677558815">"Gusa ili kuona picha yako ya skrini."</string>
+    <string name="screenshot_failed_title" msgid="705781116746922771">"Haikuweza kunasa picha ya skrini"</string>
+    <string name="screenshot_failed_text" msgid="8134011269572415402">"Haikuweza kuhifadhi picha ya skrini. Huenda hifadhi inatumika."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Machaguo ya uhamisho wa faili la USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Angika kama kichezeshi cha midia (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Angika kama kamera (PTP)"</string>
@@ -95,21 +98,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Miamba miwili ya data."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Fito tatu za habari."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Ishara ya data imejaa."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Hakuna Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Mwambaa mmoja wa Wi-Fi."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Miambaa miwili ya Wi-Fi."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Miamba tatu ya Wi-Fi."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Ishara ya Mtandao hewa imejaa"</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi imezimwa."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wifi haijaunganishwa."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Kipima mtandao kimoja cha Wifi."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Vipima mtandao viwili vya Wifi."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Vipima mtandao vitatu vya Wifi."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Nguvu kamili ya mtandao wa Wifi."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Hakuna WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Pau moja ya WiMAX."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Pau mbili za WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Pau tatu za WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Ishara ya WiMAX imejaa."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Hakuna mtandao"</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Haijaunganishwa."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Vipima mtandao sufuri."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Kipima mtandao kimoja."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Vipima mtandao mbili."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Vipima mtandao vitatu."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Nguvu kamili ya mtandao."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Imewashwa."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Imezimwa."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Imeunganishwa."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Inatumia data nje mtandao wako"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Ukingo"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Hakuna SIM."</string>
@@ -119,12 +136,23 @@
     <string name="accessibility_settings_button" msgid="799583911231893380">"Mipangilio ya mfumo."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Arifa."</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Futa arifa"</string>
-    <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPRS imewezeshwa."</string>
-    <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPRS inamiliki."</string>
+    <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS imewashwa."</string>
+    <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Kupata GPS."</string>
     <string name="accessibility_tty_enabled" msgid="4613200365379426561">"Kichapishaji cha Tele kimewezeshwa."</string>
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Mtetemo wa mlio"</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Mlio wa simu uko kimya."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> imeondolewa."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Arifa imetupwa."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Kivuli cha arifa."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Mipangilio ya haraka."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Programu za hivi karibuni."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Mtumiaji <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Simu <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Betri <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Hali ya Ndege <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Kengele imewekwa <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Data ya 2G-3G imelemazwa"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Data ya 4G imelemazwa"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Data ya kifaa cha mkononi imelemazwa"</string>
@@ -136,11 +164,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Inatafuta GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Mahali pamewekwa na GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Futa arifa zote."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Amilisha hifadhi ya skrini"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Taarifa ya programu"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Funga"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Arifa zimelemazwa"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Gonga hapa ili kuwezesha tena arifa."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skrini itazunguka kiotomatiki."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skrini imefungwa sasa katika uelekezo wa mandhari."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skrini imefungwa katika uelekeo wa picha."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Hali Tulivu"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modi ya ndege"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Inachaji, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Imechajiwa"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (Vifaa <xliff:g id="NUMBER">%d</xliff:g>)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Imezimwa"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Ung\'avu"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Zungusha Otomatiki"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Mzunguko Umefungwa"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Mbinu ya uingizaji"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Eneo linalotumika"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Kifaa cha midia"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Simu za Dharura Pekee"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Mipangilio"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Muda"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Mimi"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Haijaunganishwa"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Hakuna Mtandao"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Imezimwa"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Onyesho la Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Uonyeshaji Pasiwaya"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Ung\'avu"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"KIOTOMATIKI"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Arifa zitaonekana hapa"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Wafikie wakati wowote kwa kupapasa chini."\n"Papasa chini tena kupata vidhibiti vya mfumo."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw380dp/dimens.xml b/packages/SystemUI/res/values-sw380dp/dimens.xml
new file mode 100644
index 0000000..b39e94c
--- /dev/null
+++ b/packages/SystemUI/res/values-sw380dp/dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+*/
+-->
+<resources>
+    <!-- The fixed height of each tile -->
+    <dimen name="quick_settings_cell_height">124dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
index afa0b20..c6c0719 100644
--- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
@@ -19,8 +19,4 @@
     <!-- Layout parameters for the notification panel -->
 	<dimen name="notification_panel_margin_bottom">0dp</dimen>
     <dimen name="notification_panel_margin_left">32dp</dimen>
-
-    <!-- Gravity for the notification panel -->
-    <!-- 0x33 = left|top -->
-    <integer name="notification_panel_layout_gravity">0x33</integer>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
new file mode 100644
index 0000000..48a02ab
--- /dev/null
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources>
+    <!-- Enable quick settings on tablets -->
+    <bool name="config_hasSettingsPanel">true</bool>
+
+    <!-- The number of columns in the QuickSettings -->
+    <integer name="quick_settings_num_columns">3</integer>
+
+    <!-- The number of columns that the top level tiles span in the QuickSettings -->
+    <integer name="quick_settings_user_time_settings_tile_span">1</integer>
+
+    <!-- Whether rotation lock shows up in quick settings or not -->
+    <bool name="quick_settings_show_rotation_lock">true</bool>
+
+    <!-- Enable the "flip settings" panel -->
+    <bool name="config_hasFlipSettingsPanel">false</bool>
+</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 2b5248f..fc80f5c 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -21,11 +21,12 @@
 
     <!-- Layout parameters for the notification panel -->
     <dimen name="notification_panel_margin_bottom">192dp</dimen>
-    <dimen name="notification_panel_margin_left">0dp</dimen>
+    <dimen name="notification_panel_margin_left">16dp</dimen>
 
-    <!-- Gravity for the notification panel -->
-    <!-- 0x33 = center_horizontal|top -->
-    <integer name="notification_panel_layout_gravity">0x31</integer>
+    <!-- Gravity for the notification & quick settings panels -->
+    <!-- 0x33 = left|top ; 0x35 = right|top -->
+    <integer name="notification_panel_layout_gravity">0x33</integer>
+    <integer name="settings_panel_layout_gravity">0x35</integer>
 
     <!-- Diameter of outer shape drawable shown in navbar search-->
     <dimen name="navbar_search_outerring_diameter">430dip</dimen>
@@ -39,4 +40,15 @@
     <!-- Size of application thumbnail -->
     <dimen name="status_bar_recents_thumbnail_width">200dp</dimen>
     <dimen name="status_bar_recents_thumbnail_height">177dp</dimen>
+
+    <!-- On tablet-sized devices, we allocate the rightmost third(ish) of the draggable status bar
+         to quick settings. -->
+    <item type="dimen" name="settings_panel_dragzone_fraction">35%</item>
+
+    <!-- Minimum fraction of the screen that should be taken up by the notification panel. -->
+    <item type="dimen" name="notification_panel_min_height_frac">40%</item>
+
+    <!-- How far to slide the panel out when you touch it -->
+    <!-- On tablets this is just the close_handle_height -->
+    <dimen name="peek_height">@dimen/close_handle_height</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/styles.xml b/packages/SystemUI/res/values-sw600dp/styles.xml
new file mode 100644
index 0000000..b7becac
--- /dev/null
+++ b/packages/SystemUI/res/values-sw600dp/styles.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <style name="BrightnessDialogContainer" parent="@style/BaseBrightnessDialogContainer">
+        <item name="android:layout_width">480dp</item>
+    </style>
+</resources>
diff --git a/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
deleted file mode 100644
index 74b266d..0000000
--- a/packages/SystemUI/res/values-sw720dp-port/dimens.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * 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.
-*/
--->
-<resources>
-    <!-- gap on either side of status bar notification icons -->
-    <dimen name="status_bar_icon_padding">2dp</dimen>
-</resources>
-
diff --git a/packages/SystemUI/res/values-sw720dp/config.xml b/packages/SystemUI/res/values-sw720dp/config.xml
index 8af700a..bf01a8d 100644
--- a/packages/SystemUI/res/values-sw720dp/config.xml
+++ b/packages/SystemUI/res/values-sw720dp/config.xml
@@ -20,7 +20,7 @@
 <!-- These resources are around just to allow their values to be customized
      for different hardware and product builds. -->
 <resources>
-    <integer name="config_maxNotificationIcons">5</integer>
+    <integer name="status_bar_config_maxNotificationIcons">5</integer>
 
     <!-- Whether we're using the tablet-optimized recents interface (we use this
      value at runtime for some things) -->
@@ -29,5 +29,8 @@
     <!-- Whether recents thumbnails should stretch in both x and y to fill their
      ImageView -->
     <bool name="config_recents_thumbnail_image_fits_to_xy">true</bool>
+
+    <!-- Min alpha % that recent items will fade to while being dismissed -->
+    <integer name="config_recent_item_min_alpha">0</integer>
 </resources>
 
diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml
index 36cbabf..e42855c 100644
--- a/packages/SystemUI/res/values-sw720dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp/dimens.xml
@@ -17,16 +17,16 @@
 -->
 <resources>
     <!-- size at which Notification icons will be drawn in the status bar -->
-    <dimen name="status_bar_icon_drawing_size">24dip</dimen>
+    <dimen name="system_bar_icon_drawing_size">24dip</dimen>
 
     <!-- opacity at which Notification icons will be drawn in the status bar -->
-    <item type="dimen" name="status_bar_icon_drawing_alpha">100%</item>
+    <item type="dimen" name="system_bar_icon_drawing_alpha">100%</item>
 
     <!-- The width of the view containing non-menu status bar icons -->
-    <dimen name="navigation_key_width">80dip</dimen>
+    <dimen name="system_bar_navigation_key_width">80dip</dimen>
 
     <!-- The width of the view containing the menu status bar icon -->
-    <dimen name="navigation_menu_key_width">80dip</dimen>
+    <dimen name="system_bar_navigation_menu_key_width">80dip</dimen>
 
     <!-- ======================================== -->
     <!-- The following resources were recently moved from sw600dp; there may
@@ -39,7 +39,7 @@
     <!-- Status bar panel bottom offset (height of status bar - overlap) -->
     <dimen name="status_bar_panel_bottom_offset">36dp</dimen>
     <!-- gap on either side of status bar notification icons -->
-    <dimen name="status_bar_icon_padding">8dp</dimen>
+    <dimen name="status_bar_icon_padding">1dp</dimen>
     <!-- The width of the notification panel window -->
     <dimen name="notification_panel_width">512dp</dimen>
     <!-- The minimum height of the notification panel window -->
@@ -75,8 +75,6 @@
     <dimen name="status_bar_recents_text_fading_edge_length">20dip</dimen>
     <!-- Size of fading edge for scrolling -->
     <dimen name="status_bar_recents_scroll_fading_edge_length">10dip</dimen>
-    <!-- Margin between recents container and glow on the right -->
-    <dimen name="status_bar_recents_right_glow_margin">100dip</dimen>
 
     <!-- Where to place the app icon over the thumbnail -->
     <dimen name="status_bar_recents_app_icon_left_margin">0dp</dimen>
diff --git a/packages/SystemUI/res/values-sw720dp/styles.xml b/packages/SystemUI/res/values-sw720dp/styles.xml
index 684258a..e0b1774 100644
--- a/packages/SystemUI/res/values-sw720dp/styles.xml
+++ b/packages/SystemUI/res/values-sw720dp/styles.xml
@@ -16,12 +16,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <style name="StatusBarNotificationText">
+    <style name="SystemBarNotificationText">
         <item name="android:textSize">16sp</item>
         <item name="android:textColor">#ff999999</item>
     </style>
 
-    <style name="StatusBarPanelSettingsRow">
+    <style name="SystemBarPanelSettingsRow">
         <item name="android:paddingRight">16dp</item>
         <item name="android:layout_height">64dp</item>
         <item name="android:layout_width">match_parent</item>
@@ -29,13 +29,13 @@
         <item name="android:background">?android:attr/listChoiceBackgroundIndicator</item>
     </style>
 
-    <style name="StatusBarPanelSettingsIcon">
+    <style name="SystemBarPanelSettingsIcon">
         <item name="android:layout_height">match_parent</item>
         <item name="android:layout_width">64dp</item>
         <item name="android:scaleType">center</item>
     </style>
 
-    <style name="StatusBarPanelSettingsContents">
+    <style name="SystemBarPanelSettingsContents">
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_width">0dp</item>
         <item name="android:layout_weight">1</item>
@@ -44,27 +44,27 @@
         <item name="android:textSize">18sp</item>
     </style>
 
-    <style name="StatusBarPanelSettingsPanelSeparator">
+    <style name="SystemBarPanelSettingsPanelSeparator">
         <item name="android:layout_marginRight">0dp</item>
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">1dp</item>
         <item name="android:background">@android:drawable/divider_horizontal_dark</item>
     </style>
 
-    <style name="TextAppearance.StatusBar.Clock" parent="@*android:style/TextAppearance.StatusBar.Icon">
+    <style name="TextAppearance.SystemBar.Clock" parent="@*android:style/TextAppearance.StatusBar.Icon">
         <item name="android:textSize">30dp</item>
         <item name="android:textStyle">normal</item>
         <item name="android:textColor">@android:color/holo_blue_light</item>
     </style>
 
-    <style name="TextAppearance.StatusBar.Expanded.Clock">
+    <style name="TextAppearance.SystemBar.Expanded.Clock" parent="@style/TextAppearance.StatusBar.Expanded.Clock">
         <item name="android:textSize">48dp</item>
         <item name="android:fontFamily">sans-serif-light</item>
         <item name="android:textStyle">normal</item>
         <item name="android:textColor">#ffffff</item>
     </style>
 
-    <style name="TextAppearance.StatusBar.Expanded.Date">
+    <style name="TextAppearance.SystemBar.Expanded.Date" parent="@style/TextAppearance.StatusBar.Expanded.Date">
         <item name="android:textSize">14dp</item>
         <item name="android:textStyle">normal</item>
         <item name="android:textColor">#666666</item>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 70f0b9b..dadebae 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"ดู"</string>
     <string name="always_use_device" msgid="1450287437017315906">"ใช้ค่าเริ่มต้นสำหรับอุปกรณ์ USB นี้"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"ใช้ค่าเริ่มต้นสำหรับอุปกรณ์เสริม USB นี้"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"อนุญาตให้แก้ไขข้อบกพร่อง USB หรือไม่"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"ลายนิ้วมือหลัก RSA ของคอมพิวเตอร์คือ:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"อนุญาตจากคอมพิวเตอร์เครื่องนี้เสมอ"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"ขยายจนเต็มหน้าจอ"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ยืดจนเต็มหน้าจอ"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"ความเข้ากันได้ของการย่อ/ขยาย"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"สัญญาณข้อมูลสองขีด"</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"สัญญาณข้อมูลสามขีด"</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"สัญญาณข้อมูลเต็ม"</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"ไม่มีสัญญาณ WiFi"</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"สัญญาณ WiFi หนึ่งขีด"</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"สัญญาณ WiFi สองขีด"</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"สัญญาณ WiFi สามขีด"</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"สัญญาณ WiFi เต็ม"</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"WiFi ปิดอยู่"</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"ไม่ได้เชื่อมต่อ WiFi"</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"สัญญาณ WiFi หนึ่งขีด"</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"สัญญาณ WiFi สองขีด"</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"สัญญาณ WiFi สามขีด"</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"สัญญาณ WiFi เต็ม"</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"ไม่มีสัญญาณ WiMAX"</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"สัญญาณ WiMAX หนึ่งขีด"</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"สัญญาณ WiMAX สองขีด"</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"สัญญาณ WiMAX สามขีด"</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"สัญญาณ WiMAX เต็ม"</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"ไม่มีสัญญาณ"</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"ไม่ได้เชื่อมต่อ"</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"ศูนย์ขีด"</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"หนึ่งขีด"</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"สองขีด"</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"สามขีด"</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"สัญญาณเต็ม"</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"เปิดอยู่"</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"ปิดอยู่"</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"เชื่อมต่อแล้ว"</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"โรมมิ่ง"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"WiFi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"ไม่มีซิมการ์ด"</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"เสียงเรียกเข้าแบบสั่น"</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"เสียงเรียกเข้าแบบปิดเสียง"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ถูกนำออกไปแล้ว"</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"ปิดการแจ้งเตือนแล้ว"</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"หน้าต่างแจ้งเตือน"</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"การตั้งค่าด่วน"</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"แอปพลิเคชันล่าสุด"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"ผู้ใช้ <xliff:g id="USER">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g> <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"มือถือ <xliff:g id="SIGNAL">%1$s</xliff:g> <xliff:g id="TYPE">%2$s</xliff:g> <xliff:g id="NETWORK">%3$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"แบตเตอรี่ <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"โหมดใช้งานบนเครื่องบิน <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"บลูทูธ <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"ตั้งเวลาปลุกไว้ที่ <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"ปิดใช้งานข้อมูล 2G-3G แล้ว"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"ปิดใช้งานข้อมูล 4G แล้ว"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"ปิดใช้งานข้อมูลมือถือแล้ว"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"กำลังค้นหา GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"ตำแหน่งที่กำหนดโดย GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"ล้างการแจ้งเตือนทั้งหมด"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"เปิดโปรแกรมรักษาหน้าจอ"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"ข้อมูลแอป"</string>
+    <string name="close_universe" msgid="3736513750241754348">"ปิด"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"การแจ้งเตือนปิดอยู่"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"แตะที่นี่เพื่อเปิดการแจ้งเตือนอีกครั้ง"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"หน้าจอจะหมุนโดยอัตโนมัติ"</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"ขณะนี้หน้าจอถูกล็อกให้วางในแนวนอน"</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"ขณะนี้หน้าจอถูกล็อกให้วางในแนวตั้ง"</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"อีเทอร์เน็ต"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"โหมดใช้งานบนเครื่องบิน"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"กำลังชาร์จ, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"ชาร์จแล้ว"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"บลูทูธ"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"บลูทูธ (<xliff:g id="NUMBER">%d</xliff:g> อุปกรณ์)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ปิดบลูทูธ"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"ความสว่าง"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"หมุนอัตโนมัติ"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"ล็อกการหมุนแล้ว"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"วิธีป้อนข้อมูล"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"สถานที่ที่ใช้งาน"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"อุปกรณ์สื่อ"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"โทรฉุกเฉินเท่านั้น"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"การตั้งค่า"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"เวลา"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"ฉัน"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"WiFi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"ไม่ได้เชื่อมต่อ"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ไม่มีเครือข่าย"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"ปิด WiFi"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"การแสดงผล WiFi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"จอแสดงผลไร้สาย"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"ความสว่าง"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"อัตโนมัติ"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"การแจ้งเตือนจะแสดงขึ้นที่นี่"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"เข้าถึงได้ทุกเมื่อด้วยการกวาดนิ้วลง"\n"กวาดนิ้วลงอีกครั้งสำหรับการควบคุมระบบ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index e1c4185..48dca2d 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Tingnan"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gamitin bilang default para sa USB device"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gamitin bilang default sa USB accessory na ito"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Payagan ang pag-debug ng USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Ang RSA key fingerprint ng computer ay:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Palaging payagan mula sa computer na ito"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"I-zoom upang punan screen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"I-stretch upang mapuno screen"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom sa pagiging Tugma"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Data na dalawang bar."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Data na tatlong bar."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Puno ang signal ng data."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Walang Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Isang bar ang Wi-Fi."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Dalawang bar ang Wi-Fi."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Tatlong bar ang Wi-Fi."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Puno ang signal ng WiFi."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Naka-off ang Wifi."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Nakadiskonekta ang Wifi."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"May isang bar ang WiFi."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"May dalawang bar ang Wifi."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"May tatlong bar ang Wifi."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Puno ang signal ng WiFi."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Walang WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX na isang bar."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX na dalawang bar."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX na tatlong bar."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Puno ang signal ng WiMAX."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Walang signal."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Hindi nakakonekta."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Walang mga bar."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Isang bar."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Dalawang bar."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Tatlong bar."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Puno ang signal."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Naka-on."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Naka-off."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Nakakonekta."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Walang SIM."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Pag-vibrate ng ringer."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Naka-silent ang ringer."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Hindi pinansin ang <xliff:g id="APP">%s</xliff:g>."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Na-dismiss ang notification."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Notification shade."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Mga mabilisang setting."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Kamakailang apps."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"User na si <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobile <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"<xliff:g id="STATE">%s</xliff:g> ng baterya."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"<xliff:g id="STATE">%s</xliff:g> ng Airplane Mode."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"<xliff:g id="STATE">%s</xliff:g> ng Bluetooth."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm set para sa <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Di pinapagana ang 2G-3G na data"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Hindi pinapagana ang 4G na data"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Hindi pinapagana ang data ng mobile"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Naghahanap ng GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasyong itinatakda ng GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"I-clear ang lahat ng notification."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"I-activate ang screen saver"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Impormasyon ng app"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Isara"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Naka-off ang mga notification"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Tumapik dito upang muling i-on ang mga notification."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Awtomatikong iikot ang screen."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Naka-lock ang screen sa pahigang oryentasyon."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Naka-lock ang screen sa patayong oryentasyon."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Airplane mode"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Nagcha-charge, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Na-charge"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> (na) Device)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Naka-off ang Bluetooth"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brightness"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"I-auto Rotate"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Naka-lock ang Pag-rotate"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Pamamaraan ng Pag-input"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Lokasyong ginagamit"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Device ng media"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Mga Pang-emergency na Tawag Lamang"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Mga Setting"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Oras"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Ako"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Hindi Nakakonekta"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Walang Network"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Naka-off ang Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Display ng Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Wireless Display"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brightness"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Dito lumalabas ang mga notification"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"I-access ang mga ito anumang oras sa pamamagitan ng pag-swipe pababa."\n"Muling mag-swipe pababa para sa mga kontrol ng system."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 9bf8f76..5d64286 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Görüntüle"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Bu USB cihazı için varsayılan olarak kullan"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Bu USB aksesuar için varsayılan olarak kullan"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"USB hata ayıklamasına izin verilsin mi?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Bilgisayarın RSA anahtarı parmak izi:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Bu bilgisayardan her zaman izin ver"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Yakınlaştır (ekranı kaplasın)"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Genişlet (ekran kapansın)"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Uyumluluk yakınlaştırması"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Veri sinyali iki çubuk."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Veri sinyali üç çubuk."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Veri sinyali tam."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Kablosuz yok."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Kablosuz gücü tek çubukta."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Kablosuz sinyal gücü iki çubuk."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Kablosuz sinyal gücü üç çubuk."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Kablosuz sinyali tam."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Kablosuz kapalı."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Kablosuz bağlantı kesildi."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Kablosuz sinyali bir çubuk."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Kablosuz sinyali iki çubuk."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Kablosuz sinyali üç çubuk."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Kablosuz sinyali tam."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"WiMAX yok."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX tek çubuk."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX iki çubuk."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX üç çubuk."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX sinyali tam."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Sinyal yok."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Bağlanmadı."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Sıfır çubuk."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Tek çubuk."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"İki çubuk."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Üç çubuk."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Sinyal tam."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Açık."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Kapalı."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Bağlandı."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Dolaşımda"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Kablosuz"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM kart yok."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Telefon zili titreşim."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Telefon zili sessiz."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> kaldırıldı."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Bildirim kapatıldı."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bildirim gölgesi."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Hızlı ayarlar."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Son uygulamalar."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Kullanıcı: <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobil <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Pil <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Uçak Modu <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm saati: <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G verileri devre dışı bırakıldı"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G verileri devre dışı"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobil veriler devre dışı"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS aranıyor"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Konum GPS ile belirlendi"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Tüm bildirimleri temizle"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Ekran koruyucuyu etkinleştir"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Uygulama bilgileri"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Kapat"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Bildirimler kapalı"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Bildirimleri tekrar açmak için buraya hafifçe vurun."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran otomatik olarak dönecektir."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ekran yatay yönde kilitlendi."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ekran dikey yönde kilitlendi."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Hafif uyku"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Uçak modu"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Şarj oluyor, <xliff:g id="PERCENT">%%</xliff:g><xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Şarj oldu"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Cihaz)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Kapalı"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Parlaklık"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Otomatik Döndür"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Dönme Kilitlendi"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Giriş Yöntemi"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Kullanılan konum"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Medya cihazı"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Yalnızca Acil Çağrılar İçin"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Ayarlar"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Saat"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Ben"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Kablosuz"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Bağlı Değil"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ağ yok"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Kablosuz Kapalı"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Kablosuz Ekran"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Kablosuz Ekran"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Parlaklık"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OTOMATİK"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Bildirimler burada görünür"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Aşağıya hızlıca kaydırarak bunlara istediğiniz zaman erişebilirsiniz."\n"Sistem denetimleri için tekrar hızlıca aşağı kaydırın."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 165baae..7750e77 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Переглянути"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Використовувати за умовчанням для пристрою USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Використовувати за умовчанням для аксесуара USB"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Дозволити налагодження USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Цифровий відбиток ключа RSA комп’ютера:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Завжди дозволяти з цього комп’ютера"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Масштабув. на весь екран"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Розтягнути на весь екран"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Масштабування для сумісності"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Дві смужки сигналу даних."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Три смужки сигналу даних."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Максимальний сигнал даних."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Відсутнє з’єднання з Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Одна смужка сигналу Wi-Fi."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Дві смужки сигналу Wi-Fi."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Три смужки сигналу Wi-Fi."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Максимальний сигнал Wi-Fi."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"WiFi вимкнено."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"WiFi від’єднано."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Одна смужка сигналу WiFi."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Дві смужки сигналу WiFi."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Три смужки сигналу WiFi."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Максимальний сигнал Wi-Fi."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Немає сигналу WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Одна смужка сигналу WiMAX."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Дві смужки сигналу WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Три смужки сигналу WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Максимальний сигнал WiMAX."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Немає сигналу."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Не з’єднано."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Нуль смужок сигналу."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Одна смужка сигналу."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Дві смужки сигналу."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Три смужки сигналу."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Максимальний сигнал."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Увімкнено."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Вимкнено."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Під’єднано."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Роумінг"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Немає SIM-карти."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Дзвінок на вібросигналі."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Дзвінок беззвучний."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Програму <xliff:g id="APP">%s</xliff:g> закрито."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Сповіщення відхилено."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Панель сповіщень."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Швидке налаштування."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Нещодавні програми."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Користувач <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>, <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Мобільне передавання даних: <xliff:g id="SIGNAL">%1$s</xliff:g>, <xliff:g id="TYPE">%2$s</xliff:g>, <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Акумулятор: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Режим польоту: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Сигнал установлено на <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Дані 2G–3G вимкнено"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Дані 4G вимкнено"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Мобільне передавання даних вимкнено"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Виконується пошук GPS-сигналу"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Місцезнаходження встановлено за допомогою GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Очистити всі сповіщення."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Активувати заставку"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Інформація про програму"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Закрити"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Сповіщення вимкнено"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Торкніться тут, щоб знову ввімкнути сповіщення."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екран обертатиметься автоматично."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Екран заблоковано в альбомній орієнтації."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Екран заблоковано в книжковій орієнтації."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Заставка"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Режим польоту"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Заряджається, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Заряджено"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (пристроїв: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth вимкнено"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Яскравість"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Обертати автоматично"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Обертання заблоковано"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Метод введення"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Поточне місцезнаходження"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Носій"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Лише екстрені виклики"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Налаштування"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Час"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Я"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Не під’єднано."</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Немає мережі"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi вимкнено"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Відображення Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Бездротове відображення"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Яскравість"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТО"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Сповіщення з’являються тут"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Отримуйте до них доступ будь-коли, провівши пальцем униз."\n"Знову проведіть униз, щоб відкрити елементи керування системи."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index eef2c83..6b8f319 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Xem"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Sử dụng theo mặc định cho thiết bị USB này"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Sử dụng theo mặc định cho phụ kiện USB này"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Cho phép gỡ lỗi USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Tệp tham chiếu khóa RSA của máy tính là:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Luôn cho phép từ máy tính này"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"T.phóng để lấp đầy m.hình"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Giãn ra để lấp đầy m.hình"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Thu phóng tương thích"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Tín hiệu dữ liệu hai vạch."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Tín hiệu dữ liệu ba vạch."</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Tín hiệu dữ liệu đầy đủ."</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Không có Wi-Fi."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi một vạch."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi hai vạch."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi ba vạch."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"Tín hiệu WiFi đầy đủ."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Đã tắt Wifi."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Đã ngắt kết nối Wifi."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Tín hiệu Wifi một vạch."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Tín hiệu Wifi hai vạch."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Tín hiệu Wifi ba vạch."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Tín hiệu Wifi đầy đủ."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Không có WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX một vạch."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX hai vạch."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX ba vạch."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Tín hiệu WiMAX đầy đủ."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Không có tín hiệu nào."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Chưa được kết nối."</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"0 vạch."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Một vạch."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Hai vạch."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Ba vạch."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Tín hiệu đầy đủ."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Bật."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Tắt."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Đã kết nối."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Chuyển vùng"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Cạnh"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Không có SIM nào."</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Chuông rung."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Chuông im lặng."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> đã bị loại bỏ."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Đã loại bỏ thông báo."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bóng thông báo."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Cài đặt nhanh."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Ứng dụng gần đây."</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Người dùng <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Di động <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Pin <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Chế độ trên máy bay <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Báo thức được đặt cho <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Đã tắt dữ liệu 2G-3G"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Đã tắt dữ liệu 4G"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Dữ liệu di động bị vô hiệu hóa"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Đang tìm kiếm GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Vị trí đặt bởi GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Xóa tất cả thông báo."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Kích hoạt trình bảo vệ màn hình"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Thông tin về ứng dụng"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Đóng"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Tắt thông báo"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Chạm vào đây để bật lại thông báo."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Màn hình sẽ xoay tự động."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Màn hình hiện bị khóa theo hướng ngang."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Màn hình hiện bị khóa theo hướng dọc."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Chế độ ngủ"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Chế độ trên máy bay"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Đang sạc, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Đã sạc"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> thiết bị)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Đã tắt Bluetooth"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Độ sáng"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Tự động xoay"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Khóa xoay"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Phương thức nhập"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Vị trí đang được sử dụng"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Thiết bị phương tiện"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Chỉ cuộc gọi khẩn cấp"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Cài đặt"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Thời gian"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Tôi"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Chưa được kết nối"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Không có mạng nào"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Tắt Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Hiển thị Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Hiển thị không dây"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Độ sáng"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"TỰ ĐỘNG"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Thông báo xuất hiện tại đây"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Truy cập vào chúng bất kỳ lúc nào bằng cách vuốt xuống."\n"Vuốt lại xuống để hiển thị các điều khiển hệ thống."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index ca29738..33d1f6d6d 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"查看"</string>
     <string name="always_use_device" msgid="1450287437017315906">"默认情况下用于该 USB 设备"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"默认情况下用于该 USB 配件"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"允许 USB 调试吗?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"这台计算机的 RSA 密钥指纹如下:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"一律允许使用这台计算机进行调试"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"缩放以填满屏幕"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"拉伸以填满屏幕"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"兼容性缩放"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"数据信号强度为两格。"</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"数据信号强度为三格。"</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"数据信号满格。"</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"没有 Wi-Fi 信号。"</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi 信号强度为 1 格。"</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi 信号强度为 2 格。"</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi 信号强度为 3 格。"</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"WiFi 信号满格。"</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"已关闭 Wi-Fi。"</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi 连接已断开。"</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi 信号强度为一格。"</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi 信号强度为两格。"</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi 信号强度为三格。"</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wi-Fi 信号满格。"</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"无 WiMAX 信号。"</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX 信号强度为一格。"</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX 信号强度为两格。"</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX 信号强度为三格。"</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX 信号满格。"</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"无信号。"</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"未连接。"</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"信号强度为零格。"</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"信号强度为一格。"</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"信号强度为两格。"</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"信号强度为三格。"</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"信号满格。"</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"打开。"</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"关闭。"</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"已连接。"</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"漫游中"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"无 SIM 卡。"</string>
@@ -129,6 +146,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"振铃器振动。"</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"振铃器静音。"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"已删除<xliff:g id="APP">%s</xliff:g>"</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"已关闭通知。"</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知栏。"</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"快速设置。"</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"最近使用的应用。"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"用户:<xliff:g id="USER">%s</xliff:g>。"</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>,<xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"移动数据连接:<xliff:g id="SIGNAL">%1$s</xliff:g>,<xliff:g id="TYPE">%2$s</xliff:g>,<xliff:g id="NETWORK">%3$s</xliff:g>。"</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"电池电量:<xliff:g id="STATE">%s</xliff:g>。"</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"飞行模式:<xliff:g id="STATE">%s</xliff:g>。"</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"蓝牙:<xliff:g id="STATE">%s</xliff:g>。"</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"闹钟已设置为:<xliff:g id="TIME">%s</xliff:g>。"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G 数据网络已停用"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G 数据网络已停用"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"移动数据已停用"</string>
@@ -140,11 +168,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"正在搜索 GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"已通过 GPS 确定位置"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"激活屏幕保护程序"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"应用信息"</string>
+    <string name="close_universe" msgid="3736513750241754348">"关闭"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"通知功能已停用"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"点按此处可重新启用通知功能。"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"屏幕会自动旋转。"</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"屏幕锁定为横向模式。"</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"屏幕锁定为纵向模式。"</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"果冻豆大乱舞"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"互动屏保"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"以太网"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"飞行模式"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"正在充电:<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"充电完成"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"蓝牙"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"蓝牙(<xliff:g id="NUMBER">%d</xliff:g> 台设备)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"蓝牙已关闭"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"亮度"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"自动旋转"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"屏幕方向已锁定"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"输入法"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"位置信息"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"媒体设备"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"只能拨打紧急呼救电话"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"设置"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"时间"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"我"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"未连接"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"无网络"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi 已关闭"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi 显示设备"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"无线显示"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"亮度"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自动"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"通知会显示在这里"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"向下滑动可随时查看通知。"\n"再次向下滑动可使用系统控制功能。"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 8fa4af9..b96b8bc 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -58,12 +58,15 @@
     <string name="label_view" msgid="6304565553218192990">"查看"</string>
     <string name="always_use_device" msgid="1450287437017315906">"預設用於這個 USB 裝置"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"預設用於這個 USB 配件"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"允許 USB 偵錯嗎?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"這台電腦的 RSA 金鑰指紋如下:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"一律允許透過這台電腦進行"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"放大為全螢幕"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"放大為全螢幕"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"相容性縮放"</string>
     <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_ticker" msgid="7403652894056693515">"正在儲存螢幕擷取畫面…"</string>
+    <string name="screenshot_saving_title" msgid="8242282144535555697">"正在儲存螢幕擷取畫面…"</string>
     <string name="screenshot_saving_text" msgid="2419718443411738818">"正在儲存螢幕擷取畫面。"</string>
     <string name="screenshot_saved_title" msgid="6461865960961414961">"已拍攝螢幕擷取畫面。"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"輕觸即可查看螢幕擷取畫面。"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"數據網路訊號強度兩格。"</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"數據網路訊號強度三格。"</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"數據網路訊號滿格。"</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"未偵測到 Wi-Fi 訊號。"</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"Wi-Fi 訊號一格。"</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"Wi-Fi 訊號兩格。"</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"Wi-Fi 訊號三格。"</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"WiFi 訊號滿格。"</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"已關閉 WiFi。"</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"WiFi 連線已中斷。"</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"WiFi 訊號強度一格。"</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"WiFi 訊號強度兩格。"</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"WiFi 訊號強度三格。"</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"WiFi 訊號滿格。"</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"沒有 WiMAX 訊號。"</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX 訊號一格。"</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX 訊號兩格。"</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX 訊號三格。"</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX 訊號滿格。"</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"沒有訊號。"</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"尚未連線。"</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"訊號強度零格。"</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"訊號強度一格。"</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"訊號強度兩格。"</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"訊號強度三格。"</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"訊號滿格。"</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"開啟。"</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"關閉。"</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"已連線。"</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"漫遊中"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"沒有 SIM 卡。"</string>
@@ -129,6 +146,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"鈴聲震動。"</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"鈴聲靜音。"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"「<xliff:g id="APP">%s</xliff:g>」已關閉。"</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"已關閉通知。"</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知欄。"</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"快速設定。"</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"最近使用的應用程式。"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"使用者:<xliff:g id="USER">%s</xliff:g>。"</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>,<xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"行動數據連線:<xliff:g id="SIGNAL">%1$s</xliff:g>,<xliff:g id="TYPE">%2$s</xliff:g>,<xliff:g id="NETWORK">%3$s</xliff:g>。"</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"電池電量:<xliff:g id="STATE">%s</xliff:g>。"</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"飛航模式:<xliff:g id="STATE">%s</xliff:g>。"</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"藍牙:<xliff:g id="STATE">%s</xliff:g>。"</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"鬧鐘已設定為:<xliff:g id="TIME">%s</xliff:g>。"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"已停用 2G-3G 數據"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"已停用 4G 數據"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"已停用行動數據"</string>
@@ -140,11 +168,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"正在搜尋 GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS 已定位"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"啟用螢幕保護程式"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"應用程式資訊"</string>
+    <string name="close_universe" msgid="3736513750241754348">"關閉"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"關閉通知"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"輕按這裡即可重新開啟通知。"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"螢幕會自動旋轉。"</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"螢幕已鎖定為橫向模式。"</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"螢幕已鎖定為垂直模式。"</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"休眠模式"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"乙太網路"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"飛航模式"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"充電中 (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"充電完成"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"藍牙"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"藍牙 (<xliff:g id="NUMBER">%d</xliff:g> 個裝置)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"關閉藍牙"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"亮度"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"自動旋轉"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"已鎖定螢幕旋轉功能"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"輸入法"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"使用位置"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"媒體裝置"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"僅可撥打緊急電話"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"設定"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"時間"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"我"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"WiFi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"未連線"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"沒有網路"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"關閉 WiFi"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"WiFi 顯示裝置"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"無線螢幕分享"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"亮度"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"系統會在這裡顯示通知"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"向下滑動即可隨時存取通知。"\n"再次向下滑動即可使用系統控制項。"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 4f3e787..3b772be 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Buka"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Sebenzisa ngokuzenzakalelayo yale divayisi ye-USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Sebenzisa ngokuzenzakalelayo kule-accessory ye-USB"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Vumela ukulungisa iphutha le-USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Izigxivizo zeminwe zokhiye we-RSA wekhompyutha ngu:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Hlala uvumela njalo kusuka kule khompyutha"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Sondeza ukugcwalisa isikrini"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Nweba ukugcwalisa isikrini"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Ukuhambelana Kokusondeza"</string>
@@ -97,21 +100,35 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Amabha amabili edatha"</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Amabha amathathu edatha"</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Igcwele i-signal yedatha"</string>
-    <string name="accessibility_no_wifi" msgid="7455607460517331976">"Alukho uxhumano lwe-Wi-Fi"</string>
-    <string name="accessibility_wifi_one_bar" msgid="6854947280074467207">"I-Wi-Fi umugqaa owodwa."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3344340012058984348">"I-Wi-Fi imigqaa emibili."</string>
-    <string name="accessibility_wifi_three_bars" msgid="928322805193265041">"I-Wi-Fi imigqaa emithathu."</string>
-    <string name="accessibility_wifi_signal_full" msgid="1275764416228473932">"i-signal ye-WiFi igcwele"</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"I-Wifi ivaliwe."</string>
+    <string name="accessibility_no_wifi" msgid="1425476551827924474">"I-Wifi ayixhunywanga."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Ibha elilodwa le-WiFi."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Amabha amabili we-WiFi."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Amabha amathathu we-WiFi."</string>
+    <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Isiginali ye-WiFi igcwele."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Ayikho i-WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Ibha eyodwa ye-WiMAX."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Amabha amabili we-WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Amabha amathathu we-WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Isiginali ye-WiMAX egcwele."</string>
+    <string name="accessibility_no_signal" msgid="7064645320782585167">"Ayikho isignali."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Akuxhunyiwe"</string>
+    <string name="accessibility_zero_bars" msgid="3806060224467027887">"Amabha ayiqanda."</string>
+    <string name="accessibility_one_bar" msgid="1685730113192081895">"Ibha elilodwa."</string>
+    <string name="accessibility_two_bars" msgid="6437363648385206679">"Amabha amabili."</string>
+    <string name="accessibility_three_bars" msgid="2648241415119396648">"Amabha amathathu."</string>
+    <string name="accessibility_signal_full" msgid="9122922886519676839">"Isiginali egcwele."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"Vula."</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"Vala."</string>
+    <string name="accessibility_desc_connected" msgid="8366256693719499665">"Ixhunyiwe."</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+    <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+    <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"I-HSPA"</string>
     <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
     <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
     <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+    <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Iyazulazula"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Ekucupheleni"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"I-Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Ayikho i-SIM"</string>
@@ -127,6 +144,17 @@
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Ukudlidliza kweringa."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Isikhali sithulile."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ivaliwe."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Isaziso sichithiwe."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Umthunzi wesaziso."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Izilingiselelo ezisheshayo."</string>
+    <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Izinhlelo zokusebenza zakamuva"</string>
+    <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Umsebenzisi <xliff:g id="USER">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Iselula <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Ibhethri <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Imodi yendiza <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"I-Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"I-alamu isethiwe ngo-<xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"idatha ye-2G-3G ivimbelwe"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Idatha ye-4G ivimbelwe"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Idatha yefoni ivimbelwe"</string>
@@ -138,11 +166,41 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Isesha i-GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Indawo ihlelwe i-GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Susa zonke izaziso."</string>
-    <string name="dreams_dock_launcher" msgid="3541196417659166245">"Yenza ukuthi iskrini seyiva sisebenze"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Ulwazi lohlelo lokusebenza"</string>
+    <string name="close_universe" msgid="3736513750241754348">"Vala"</string>
     <string name="notifications_off_title" msgid="8936620513608443224">"Izaziso zivaliwe"</string>
     <string name="notifications_off_text" msgid="2529001315769385273">"Thepha lapha ukuvula futhi izaziso."</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Isikrini sizophenduka ngokuzenzakalela."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Isikrini sikhiyelwe ngomumo we-landscape."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Isikrini sikhiyelwe ngomumo we-portrait."</string>
+    <string name="jelly_bean_dream_name" msgid="5992026543636816792">"I-BeanFlinger"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Ukuphupha emini"</string>
+    <string name="ethernet_label" msgid="7967563676324087464">"I-Ethernet"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Isimo sendiza"</string>
+    <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Iyashaja <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Kushajiwe"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"I-Bluetooth"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"I-Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> amadivayisi)"</string>
+    <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"I-Bluetooth ivaliwe"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Ukugqama"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Ukuphendula ngokuzenzakalela"</string>
+    <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Ukuphendula kukhiyiwe"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Indlela yokungenayo"</string>
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Indawo iyasetshenziswa"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Idivayisi yemidiya"</string>
+    <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Amakholi aphuthumayo kuphela"</string>
+    <string name="quick_settings_settings_label" msgid="5326556592578065401">"Izilungiselelo"</string>
+    <string name="quick_settings_time_label" msgid="4635969182239736408">"Isikhathi"</string>
+    <string name="quick_settings_user_label" msgid="5238995632130897840">"Mina"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"I-Wi-Fi"</string>
+    <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Akuxhunyiwe"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ayikho inethiwekhi"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"I-Wi-Fi icimile"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Ukuboniswa kwe-Wi-"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Ukubonisa okungenazintambo"</string>
+    <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Ukugqama"</string>
+    <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OKUZENZAKALELAYO"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"Izaziso zivela lapha"</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Kufinyelele noma kunini ngokuswayiphela phansi."\n"Swayiphela phansi futhi ngezilawuli zesistimu."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-port/arrays.xml b/packages/SystemUI/res/values/arrays.xml
similarity index 100%
rename from packages/SystemUI/res/values-port/arrays.xml
rename to packages/SystemUI/res/values/arrays.xml
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 48fb21f..047570f 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -35,5 +35,17 @@
     <declare-styleable name="RecentsPanelView">
         <attr name="recentItemLayout" format="reference" />
     </declare-styleable>
+    <declare-styleable name="DeadZone">
+        <attr name="minSize" format="dimension" />
+        <attr name="maxSize" format="dimension" />
+        <attr name="holdTime" format="integer" />
+        <attr name="decayTime" format="integer" />
+        <attr name="orientation" />
+    </declare-styleable>
+
+    <attr name="orientation">
+        <enum name="horizontal" value="0" />
+        <enum name="vertical" value="1" />
+    </attr>
 </resources>
 
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 9bbfc91..acb192d 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -28,9 +28,11 @@
     <drawable name="recents_callout_line">#99ffffff</drawable>
     <drawable name="notification_item_background_legacy_color">#ffaaaaaa</drawable>
     <drawable name="intruder_bg_pressed">#ff33B5E5</drawable>
+    <drawable name="notification_header_bg">#FF000000</drawable>
 
     <!-- ==================== system bar only ==================== -->
     <drawable name="system_bar_background">#ff000000</drawable>
     <!-- the darkening filter applied to notifications -->
     <drawable name="notification_icon_area_smoke">#aa000000</drawable>
+    <color name="notification_panel_scrim_color">#B0000000</color>
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index fd5ef4e..a27630d 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -66,7 +66,41 @@
     <!-- Vibration duration for MultiWaveView used in SearchPanelView -->
     <integer translatable="false" name="config_search_panel_view_vibration_duration">20</integer>
 
-    <!-- The length of the vibration when the notificaiotn pops open. -->
+    <!-- The length of the vibration when the notification pops open. -->
+    <integer name="one_finger_pop_duration_ms">10</integer>
+
+    <!-- Whether we're using the tablet-optimized recents interface (we use this
+     value at runtime for some things) -->
+    <integer name="status_bar_recents_bg_gradient_degrees">90</integer>
+
+    <!-- decay duration (from size_max -> size), in ms -->
+    <integer name="navigation_bar_deadzone_hold">333</integer>
+    <integer name="navigation_bar_deadzone_decay">333</integer>
+    
+    <bool name="config_dead_zone_flash">false</bool>
+
+    <!-- Min alpha % that recent items will fade to while being dismissed -->
+    <integer name="config_recent_item_min_alpha">3</integer>
+
+    <!-- The number of columns in the QuickSettings -->
+    <integer name="quick_settings_num_columns">3</integer>
+
+    <!-- The number of columns that the top level tiles span in the QuickSettings -->
+    <integer name="quick_settings_user_time_settings_tile_span">1</integer>
+
+    <!-- Whether rotation lock shows up in quick settings or not -->
+    <bool name="quick_settings_show_rotation_lock">false</bool>
+
+    <!-- Timeouts for brightness dialog to disappear -->
+    <integer name="quick_settings_brightness_dialog_short_timeout">2000</integer>
+    <integer name="quick_settings_brightness_dialog_long_timeout">4000</integer>
+
     <integer name="blinds_pop_duration_ms">10</integer>
+
+    <!-- Disable the separate quick settings panel -->
+    <bool name="config_hasSettingsPanel">true</bool>
+
+    <!-- Enable the "flip settings" panel -->
+    <bool name="config_hasFlipSettingsPanel">true</bool>
 </resources>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c6fd66a..ed08115 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -28,6 +28,7 @@
     <!-- Size of application thumbnail -->
     <dimen name="status_bar_recents_thumbnail_width">164dp</dimen>
     <dimen name="status_bar_recents_thumbnail_height">145dp</dimen>
+    <dimen name="status_bar_recents_thumbnail_bg_padding">4dp</dimen>
 
     <!-- Size of application label text -->
     <dimen name="status_bar_recents_app_label_text_size">14dip</dimen>
@@ -39,6 +40,24 @@
     <dimen name="status_bar_recents_scroll_fading_edge_length">10dip</dimen>
     <!-- Margin between recents container and glow on the right -->
     <dimen name="status_bar_recents_right_glow_margin">100dip</dimen>
+    <!-- How far the thumbnail for a recent app appears from left edge -->
+    <dimen name="status_bar_recents_thumbnail_left_margin">20dp</dimen>
+    <!-- Padding for text descriptions -->
+    <dimen name="status_bar_recents_text_description_padding">8dp</dimen>
+    <!-- Width of application label text -->
+    <dimen name="status_bar_recents_app_label_width">88dip</dimen>
+    <!-- Left margin of application label text -->
+    <dimen name="status_bar_recents_app_label_left_margin">0dip</dimen>
+    <!-- Padding between recents items -->
+    <dimen name="status_bar_recents_item_padding">0dip</dimen>
+    <!-- When recents first appears, how far the icon and label of the primary activity
+         travel -->
+    <dimen name="status_bar_recents_app_icon_translate_distance">35dip</dimen>
+
+    <!-- Where to place the app icon over the thumbnail -->
+    <dimen name="status_bar_recents_app_icon_left_margin">0dp</dimen>
+    <dimen name="status_bar_recents_app_icon_top_margin">8dp</dimen>
+
     <!-- Amount to offset bottom of notification peek window from top of status bar. -->
     <dimen name="peek_window_y_offset">-12dp</dimen>
 
@@ -48,6 +67,8 @@
     <!-- thickness (height) of the dead zone at the top of the navigation bar,
          reducing false presses on navbar buttons; approx 2mm -->
     <dimen name="navigation_bar_deadzone_size">12dp</dimen>
+    <!-- size of the dead zone when touches have recently occurred elsewhere on screen -->
+    <dimen name="navigation_bar_deadzone_size_max">32dp</dimen>
 
     <!-- Height of notification icons in the status bar -->
     <dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
@@ -82,14 +103,17 @@
     <!-- Initial velocity of the shade when collapsing on its own -->
     <dimen name="self_collapse_velocity">2000dp</dimen>
     <!-- Minimum final velocity of gestures interpreted as expand requests -->
-    <dimen name="fling_expand_min_velocity">200dp</dimen>
+    <dimen name="fling_expand_min_velocity">100dp</dimen>
     <!-- Minimum final velocity of gestures interpreted as collapse requests -->
-    <dimen name="fling_collapse_min_velocity">200dp</dimen>
+    <dimen name="fling_collapse_min_velocity">100dp</dimen>
     <!-- Cap on contribution of x dimension of gesture to overall velocity -->
     <dimen name="fling_gesture_max_x_velocity">200dp</dimen>
     <!-- Cap on overall resulting fling speed (s^-1) -->
     <dimen name="fling_gesture_max_output_velocity">3000dp</dimen>
 
+    <!-- Minimum distance a fling must travel (anti-jitter) -->
+    <dimen name="fling_gesture_min_dist">20dp</dimen>
+
     <!-- Minimum fraction of the display a gesture must travel, at any velocity, to qualify as a
          collapse request -->
     <item type="dimen" name="collapse_min_display_fraction">10%</item>
@@ -126,10 +150,10 @@
     <dimen name="navbar_search_panel_height">230dip</dimen>
 
     <!-- Height of the draggable handle at the bottom of the phone notification panel -->
-    <dimen name="close_handle_height">32dp</dimen>
+    <dimen name="close_handle_height">36dp</dimen>
 
-    <!-- Amount of close_handle that will not overlap the notification list -->
-    <dimen name="close_handle_underlap">18dp</dimen>
+    <!-- Amount of close_handle that will NOT overlap the notification list -->
+    <dimen name="close_handle_underlap">32dp</dimen>
 
     <!-- Height of the notification panel header bar -->
     <dimen name="notification_panel_header_height">48dp</dimen>
@@ -144,16 +168,41 @@
     <dimen name="notification_panel_margin_bottom">0dp</dimen>
     <dimen name="notification_panel_margin_left">0dp</dimen>
 
-    <!-- Gravity for the notification panel -->
+    <!-- Gravity for the notification & quick settings panels -->
     <!-- 0x37 = fill_horizontal|top -->
     <integer name="notification_panel_layout_gravity">0x37</integer>
+    <integer name="settings_panel_layout_gravity">0x37</integer>
+
+    <!-- Fraction of the status bar that, when dragged, will produce the quick settings panel
+         instead of the notification panel. See also @dimen/settings_panel_dragzone_min.
+         If zero, the settings panel will not be directly draggable from the status bar. -->
+    <item type="dimen" name="settings_panel_dragzone_fraction">0%</item>
+
+    <!-- Quick settings dragzone, if used, should be at least this big (may be zero). -->
+    <dimen name="settings_panel_dragzone_min">100dp</dimen>
 
     <!-- Height of the carrier/wifi name label -->
     <dimen name="carrier_label_height">24dp</dimen>
 
-    <!-- The distance you can pull a notificaiton before it pops open -->
+    <!-- The distance you can pull a notification before it pops open -->
+    <dimen name="one_finger_pop_limit">32dp</dimen>
+
+    <!-- The fixed height of each tile -->
+    <dimen name="quick_settings_cell_height">110dp</dimen>
+
+    <!-- The padding between each tile within the QuickSettings layout -->
+    <dimen name="quick_settings_cell_gap">4dp</dimen>
+
+    <!-- Minimum fraction of the screen that should be taken up by the notification panel.
+         Not used at this screen size. -->
+    <item type="dimen" name="notification_panel_min_height_frac">0%</item>
+
     <dimen name="blinds_pop_threshold">32dp</dimen>
 
     <!-- The size of the gesture span needed to activate the "pull" notification expansion -->
     <dimen name="pull_span_min">25dp</dimen>
+
+    <!-- How far to slide the panel out when you touch it -->
+    <!-- For phones, this is close_handle_height + header_height -->
+    <dimen name="peek_height">84dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/donottranslate.xml b/packages/SystemUI/res/values/donottranslate.xml
index 089a54d..41ea6f3 100644
--- a/packages/SystemUI/res/values/donottranslate.xml
+++ b/packages/SystemUI/res/values/donottranslate.xml
@@ -17,10 +17,7 @@
  */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- For formatting day of week and date in DateView.  %1$s is DOW, %2$s is date.
-         We show both (DOW on one line, then the date) but this can be overridden for locales as
-         necessary.
-         -->
-    <string name="status_bar_date_formatter">%1$s\n%2$s</string>
+    <!-- Date format for display: should match the lockscreen in /policy.  -->
+    <string name="abbrev_wday_month_day_no_year">@*android:string/abbrev_wday_month_day_no_year</string>
 
 </resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 4a73200..2cc3446 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -19,4 +19,5 @@
     <item type="id" name="expandable_tag" />
     <item type="id" name="user_expanded_tag" />
     <item type="id" name="user_lock_tag" />
+    <item type="id" name="status_bar_cling_stub" />
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index f18e33e..f3db062 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -154,6 +154,15 @@
     <!-- Checkbox label for USB accessory dialogs.  [CHAR LIMIT=50] -->
     <string name="always_use_accessory">Use by default for this USB accessory</string>
 
+    <!-- Title of confirmation dialog for USB debugging -->
+    <string name="usb_debugging_title">Allow USB debugging?</string>
+
+    <!-- Message of confirmation dialog for USB debugging -->
+    <string name="usb_debugging_message">The computer\'s RSA key fingerprint is:\n<xliff:g id="fingerprint">%1$s</xliff:g></string>
+
+    <!-- Option to always allow USB debugging from the attached computer -->
+    <string name="usb_debugging_always">Always allow from this computer</string>
+
     <!-- Checkbox label for application compatibility mode ON (zooming app to look like it's running
          on a phone).  [CHAR LIMIT=25] -->
     <string name="compat_mode_on">Zoom to fill screen</string>
@@ -247,16 +256,18 @@
     <!-- Content description of the data signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_data_signal_full">Data signal full.</string>
 
+    <!-- Content description of the WIFI signal when WIFI is disabled for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_wifi_off">Wifi off.</string>
     <!-- Content description of the WIFI signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_no_wifi">No Wi-Fi.</string>
+    <string name="accessibility_no_wifi">Wifi disconnected.</string>
     <!-- Content description of the WIFI signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_wifi_one_bar">Wi-Fi one bar.</string>
+    <string name="accessibility_wifi_one_bar">Wifi one bar.</string>
     <!-- Content description of the WIFI signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_wifi_two_bars">Wi-Fi two bars.</string>
+    <string name="accessibility_wifi_two_bars">Wifi two bars.</string>
     <!-- Content description of the WIFI signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_wifi_three_bars">Wi-Fi three bars.</string>
+    <string name="accessibility_wifi_three_bars">Wifi three bars.</string>
     <!-- Content description of the WIFI signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_wifi_signal_full">WiFi signal full.</string>
+    <string name="accessibility_wifi_signal_full">Wifi signal full.</string>
 
     <!-- Content description of the WiMAX signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_no_wimax">No WiMAX.</string>
@@ -269,9 +280,37 @@
     <!-- Content description of the WiMAX signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_wimax_signal_full">WiMAX signal full.</string>
 
+    <!-- Content description of an item with no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_no_signal">No signal.</string>
+    <!-- Content description of an item with no signal and no connection for accessibility (not shown on the screen) [CHAR LIMIT=NONE] -->
+    <string name="accessibility_not_connected">Not connected.</string>
+    <!-- Content description of an item with zero signal bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_zero_bars">Zero bars.</string>
+    <!-- Content description of an item with one signal bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_one_bar">One bar.</string>
+    <!-- Content description of an item with two signal bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_two_bars">Two bars.</string>
+    <!-- Content description of an item with three signal bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_three_bars">Three bars.</string>
+    <!-- Content description of an item with full signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_signal_full">Signal full.</string>
+
+    <!-- Content description of an item that is turned on for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_desc_on">On.</string>
+    <!-- Content description of an item that is turned off for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_desc_off">Off.</string>
+    <!-- Content description of an item that is connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_desc_connected">Connected.</string>
+
     <!-- Content description of the data connection type GPRS for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_data_connection_gprs">GPRS</string>
 
+    <!-- Content description of the data connection type 1x for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_1x">1 X</string>
+
+    <!-- Content description of the data connection type HSPA and its variants for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_hspa">HSPA</string>
+
     <!-- Content description of the data connection type 3G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_data_connection_3g">3G</string>
 
@@ -284,6 +323,9 @@
     <!-- Content description of the data connection type CDMA for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_data_connection_cdma">CDMA</string>
 
+    <!-- Content description of the roaming data connection type for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_roaming">Roaming</string>
+
     <!-- Content description of the data connection type Edge for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_data_connection_edge">Edge</string>
 
@@ -328,6 +370,30 @@
 
     <!-- Content description to tell the user an application has been removed from recents -->
     <string name="accessibility_recents_item_dismissed"><xliff:g id="app" example="Calendar">%s</xliff:g> dismissed.</string>
+    <!-- Content description to tell the user a notification has been removed from the notification shade -->
+    <string name="accessibility_notification_dismissed">Notification dismissed.</string>
+
+    <!-- Content description for the notification shade panel (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_desc_notification_shade">Notification shade.</string>
+    <!-- Content description for the quick settings panel (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_desc_quick_settings">Quick settings.</string>
+    <!-- Content description for the recent apps panel (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_desc_recent_apps">Recent apps.</string>
+
+    <!-- Content description of the user tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_user">User <xliff:g id="user" example="John Doe">%s</xliff:g>.</string>
+    <!-- Content description of the wifi tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_wifi"><xliff:g id="signal" example="Three bars">%1$s</xliff:g>. <xliff:g id="network" example="MyWifiNetwork">%2$s</xliff:g></string>
+    <!-- Content description of the mobile data tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_mobile">Mobile <xliff:g id="signal" example="Three bars">%1$s</xliff:g>. <xliff:g id="type" example="4G">%2$s</xliff:g>. <xliff:g id="network" example="T-Mobile">%3$s</xliff:g>.</string>
+    <!-- Content description of the battery tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_battery">Battery <xliff:g id="state" example="50% charging">%s</xliff:g>.</string>
+    <!-- Content description of the airplane mode tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_airplane">Airplane Mode <xliff:g id="state" example="Off">%s</xliff:g>.</string>
+    <!-- Content description of the bluetooth tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_bluetooth">Bluetooth <xliff:g id="state" example="Off">%s</xliff:g>.</string>
+    <!-- Content description of the alarm tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_alarm">Alarm set for <xliff:g id="time" example="Wed 3:30 PM">%s</xliff:g>.</string>
 
     <!-- Title of dialog shown when 2G-3G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
     <string name="data_usage_disabled_dialog_3g_title">2G-3G data disabled</string>
@@ -363,13 +429,13 @@
     <!-- Content description of the clear button in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_clear_all">Clear all notifications.</string>
 
-    <!-- Description of the desk dock action that invokes the Android Dreams screen saver feature -->
-    <string name="dreams_dock_launcher">Activate screen saver</string>
-
     <!-- Title shown in notification popup for inspecting the responsible
          application -->
     <string name="status_bar_notification_inspect_item_title">App info</string>
 
+    <!-- [CHAR LIMIT=NONE] -->
+    <string name="close_universe">Close</string>
+
     <!-- Title for the pseudo-notification shown when notifications are disabled (do-not-disturb
          mode) -->
     <string name="notifications_off_title">Notifications off</string>
@@ -385,4 +451,69 @@
 
     <!-- Description of the button in the phone-style notification panel that controls auto-rotation, when auto-rotation is off. [CHAR LIMIT=NONE] -->
     <string name="accessibility_rotation_lock_on_portrait">Screen is locked in portrait orientation.</string>
+
+    <!-- Name of the Jelly Bean platlogo screensaver -->
+    <string name="jelly_bean_dream_name">BeanFlinger</string>
+
+    <!-- Name of the launcher shortcut icon that allows dreams to be started immediately [CHAR LIMIT=20] -->
+    <string name="start_dreams">Daydream</string>
+
+    <!-- Textual description of Ethernet connections -->
+    <string name="ethernet_label">Ethernet</string>
+
+    <!-- QuickSettings: Airplane mode [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_airplane_mode_label">Airplane mode</string>
+    <!-- QuickSettings: Battery Charging [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_battery_charging_label">Charging, <xliff:g id="number">%d</xliff:g><xliff:g id="percent">%%</xliff:g></string>
+    <!-- QuickSettings: Battery Charged [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_battery_charged_label">Charged</string>
+    <!-- QuickSettings: Bluetooth [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_bluetooth_label">Bluetooth</string>
+    <!-- QuickSettings: Bluetooth (Multiple) [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_bluetooth_multiple_devices_label">Bluetooth (<xliff:g id="number">%d</xliff:g> Devices)</string>
+    <!-- QuickSettings: Bluetooth (Off) [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_bluetooth_off_label">Bluetooth Off</string>
+    <!-- QuickSettings: Brightness [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_brightness_label">Brightness</string>
+    <!-- QuickSettings: Rotation Unlocked [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_rotation_unlocked_label">Auto Rotate</string>
+    <!-- QuickSettings: Rotation Locked [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_rotation_locked_label">Rotation Locked</string>
+    <!-- QuickSettings: IME [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_ime_label">Input Method</string>
+    <!-- QuickSettings: Location [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_location_label">Location in use</string>
+    <!-- QuickSettings: Media device [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_media_device_label">Media device</string>
+    <!-- QuickSettings: RSSI [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_rssi_label">RSSI</string>
+    <!-- QuickSettings: RSSI (No network) [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_rssi_emergency_only">Emergency Calls Only</string>
+    <!-- QuickSettings: Settings [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_settings_label">Settings</string>
+    <!-- QuickSettings: Time [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_time_label">Time</string>
+    <!-- QuickSettings: User [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_user_label">Me</string>
+    <!-- QuickSettings: Wifi [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_wifi_label">Wi-Fi</string>
+    <!-- QuickSettings: Wifi (Not connected) [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_wifi_not_connected">Not Connected</string>
+    <!-- QuickSettings: Wifi (No network) [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_wifi_no_network">No Network</string>
+    <!-- QuickSettings: Wifi (Off) [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_wifi_off_label">Wi-Fi Off</string>
+    <!-- QuickSettings: Wifi display [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_wifi_display_label">Wi-Fi Display</string>
+    <!-- QuickSettings: Wifi display [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_wifi_display_no_connection_label">Wireless Display</string>
+    <!-- QuickSettings: Brightness dialog title [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_brightness_dialog_title">Brightness</string>
+    <!-- QuickSettings: Brightness dialog auto brightness button [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_brightness_dialog_auto_brightness_label">AUTO</string>
+
+    <!-- Title of help text shown when the notification panel is pulled down for the very first time. [CHAR LIMIT=NONE] -->
+    <string name="status_bar_help_title">Notifications appear here</string>
+    <!-- Body of help text shown when the notification panel is pulled down for the very first time. [CHAR LIMIT=NONE] -->
+    <string name="status_bar_help_text">Access them anytime by swiping down.\nSwipe down again for system controls.</string>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 2564003..1a59d6c 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -16,6 +16,24 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 
+    <style name="RecentsStyle" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
+        <item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item>
+    </style>
+
+    <!-- Animations for a non-full-screen window or activity. -->
+    <style name="Animation.RecentsActivity" parent="@android:style/Animation.Activity">
+        <item name="android:activityOpenEnterAnimation">@anim/recents_launch_from_launcher_enter</item>
+        <item name="android:activityOpenExitAnimation">@anim/recents_launch_from_launcher_exit</item>
+        <item name="android:taskOpenEnterAnimation">@anim/recents_launch_from_launcher_enter</item>
+        <item name="android:taskOpenExitAnimation">@anim/recents_launch_from_launcher_exit</item>
+        <item name="android:taskToFrontEnterAnimation">@anim/recents_launch_from_launcher_enter</item>
+        <item name="android:taskToFrontExitAnimation">@anim/recents_launch_from_launcher_exit</item>
+        <item name="android:wallpaperOpenEnterAnimation">@anim/recents_launch_from_launcher_enter</item>
+        <item name="android:wallpaperOpenExitAnimation">@anim/recents_launch_from_launcher_exit</item>
+        <item name="android:wallpaperIntraOpenEnterAnimation">@anim/wallpaper_recents_launch_from_launcher_enter</item>
+        <item name="android:wallpaperIntraOpenExitAnimation">@anim/wallpaper_recents_launch_from_launcher_exit</item>
+    </style>
+
     <style name="TextAppearance.StatusBar.IntruderAlert"
         parent="@*android:style/TextAppearance.StatusBar">
     </style>
@@ -70,6 +88,46 @@
     <style name="TextAppearance.StatusBar.Expanded.Network.EmergencyOnly">
     </style>
 
+    <style name="TextAppearance" />
+    <style name="TextAppearance.QuickSettings" />
+
+    <style name="TextAppearance.QuickSettings.TileView">
+        <item name="android:paddingLeft">6dp</item>
+        <item name="android:paddingRight">6dp</item>
+        <item name="android:paddingBottom">2dp</item>
+        <item name="android:drawablePadding">12dp</item>
+        <item name="android:textSize">12dp</item>
+        <item name="android:textStyle">normal</item>
+        <item name="android:textColor">#CCCCCC</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:singleLine">true</item>
+        <item name="android:ellipsize">marquee</item>
+        <item name="android:fadingEdge">horizontal</item>
+    </style>
+
+    <style name="TextAppearance.QuickSettings.Clock" parent="@style/TextAppearance.QuickSettings.TileView">
+        <item name="android:textSize">20dp</item>
+        <item name="android:textColor">@android:color/holo_blue_light</item>
+    </style>
+
+    <style name="TextAppearance.QuickSettings.Date" parent="@style/TextAppearance.QuickSettings.TileView">
+        <item name="android:textSize">14dp</item>
+    </style>
+
+    <style name="TextAppearance.QuickSettings.Alarm" parent="@style/TextAppearance.QuickSettings.TileView">
+        <item name="android:textSize">14dp</item>
+        <item name="android:textColor">#ff3a3b39</item>
+    </style>
+
+    <style name="BaseBrightnessDialogContainer">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_marginLeft">8dp</item>
+        <item name="android:layout_marginRight">8dp</item>
+        <item name="android:padding">16dp</item>
+    </style>
+    <style name="BrightnessDialogContainer" parent="@style/BaseBrightnessDialogContainer" />
+
     <style name="Animation" />
 
     <style name="Animation.ShirtPocketPanel">
@@ -97,4 +155,33 @@
         <item name="android:textSize">14dp</item>
     </style>
     
+    <style name="ClingButton">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:paddingTop">10dp</item>
+        <item name="android:paddingBottom">15dp</item>
+        <item name="android:paddingLeft">35dp</item>
+        <item name="android:paddingRight">35dp</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:background">@drawable/cling_button_bg</item>
+    </style>
+    <style name="ClingTitleText">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_marginBottom">5dp</item>
+        <item name="android:textSize">23sp</item>
+        <item name="android:textColor">#49C0EC</item>
+        <item name="android:shadowColor">#000000</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:shadowRadius">2.0</item>
+    </style>
+    <style name="ClingText">
+        <item name="android:textSize">15sp</item>
+        <item name="android:textColor">#FFFFFF</item>
+        <item name="android:shadowColor">#000000</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:shadowRadius">2.0</item>
+        <item name="android:lineSpacingMultiplier">1.1</item>
+    </style>
+
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/BeanBag.java b/packages/SystemUI/src/com/android/systemui/BeanBag.java
index 616d72f..f5a90ca 100644
--- a/packages/SystemUI/src/com/android/systemui/BeanBag.java
+++ b/packages/SystemUI/src/com/android/systemui/BeanBag.java
@@ -24,6 +24,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.Bitmap;
@@ -40,6 +41,7 @@
 import android.graphics.RectF;
 import android.os.Handler;
 import android.os.SystemClock;
+import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.Pair;
@@ -402,6 +404,11 @@
     public void onStart() {
         super.onStart();
 
+        // ACHIEVEMENT UNLOCKED
+        PackageManager pm = getPackageManager();
+        pm.setComponentEnabledSetting(new ComponentName(this, BeanBagDream.class),
+                PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
+
         getWindow().addFlags(
                   WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
                 | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
diff --git a/packages/SystemUI/src/com/android/systemui/BeanBagDream.java b/packages/SystemUI/src/com/android/systemui/BeanBagDream.java
new file mode 100644
index 0000000..39e4727
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/BeanBagDream.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.service.dreams.DreamService;
+
+import com.android.systemui.BeanBag.Board;
+
+public class BeanBagDream extends DreamService {
+
+    private Board mBoard;
+
+    @Override
+    public void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        setInteractive(true);
+        setFullscreen(true);
+        mBoard = new Board(this, null);
+        setContentView(mBoard);
+    }
+
+    @Override
+    public void onDreamingStarted() {
+        super.onDreamingStarted();
+        mBoard.startAnimation();
+    }
+
+    @Override
+    public void onDreamingStopped() {
+        mBoard.stopAnimation();
+        super.onDreamingStopped();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/BootReceiver.java b/packages/SystemUI/src/com/android/systemui/BootReceiver.java
index de005aa..d3ce30d 100644
--- a/packages/SystemUI/src/com/android/systemui/BootReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/BootReceiver.java
@@ -35,7 +35,7 @@
         try {
             // Start the load average overlay, if activated
             ContentResolver res = context.getContentResolver();
-            if (Settings.System.getInt(res, Settings.System.SHOW_PROCESSES, 0) != 0) {
+            if (Settings.Global.getInt(res, Settings.Global.SHOW_PROCESSES, 0) != 0) {
                 Intent loadavg = new Intent(context, com.android.systemui.LoadAverageService.class);
                 context.startService(loadavg);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index dcfd0b3..edfaf49 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -27,13 +27,12 @@
 import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.ScaleGestureDetector;
+import android.view.ScaleGestureDetector.OnScaleGestureListener;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.View.OnClickListener;
 
-import java.util.Stack;
-
 public class ExpandHelper implements Gefingerpoken, OnClickListener {
     public interface Callback {
         View getChildAtRawPosition(float x, float y);
@@ -86,6 +85,8 @@
     private float mInitialTouchFocusY;
     private float mInitialTouchY;
     private float mInitialTouchSpan;
+    private float mLastFocusY;
+    private float mLastSpanY;
     private int mTouchSlop;
     private int mLastMotionY;
     private float mPopLimit;
@@ -108,6 +109,32 @@
 
     private View mScrollView;
 
+    private OnScaleGestureListener mScaleGestureListener 
+            = new ScaleGestureDetector.SimpleOnScaleGestureListener() {
+        @Override
+        public boolean onScaleBegin(ScaleGestureDetector detector) {
+            if (DEBUG_SCALE) Slog.v(TAG, "onscalebegin()");
+            float focusX = detector.getFocusX();
+            float focusY = detector.getFocusY();
+
+            final View underFocus = findView(focusX, focusY);
+            if (underFocus != null) {
+                startExpanding(underFocus, STRETCH);
+            }
+            return mExpanding;
+        }
+
+        @Override
+        public boolean onScale(ScaleGestureDetector detector) {
+            if (DEBUG_SCALE) Slog.v(TAG, "onscale() on " + mCurrView);
+            return true;
+        }
+
+        @Override
+        public void onScaleEnd(ScaleGestureDetector detector) {
+        }
+    };
+
     private class ViewScaler {
         View mView;
 
@@ -199,47 +226,13 @@
         final ViewConfiguration configuration = ViewConfiguration.get(mContext);
         mTouchSlop = configuration.getScaledTouchSlop();
 
-        mSGD = new ScaleGestureDetector(context,
-                                         new ScaleGestureDetector.SimpleOnScaleGestureListener() {
-            @Override
-            public boolean onScaleBegin(ScaleGestureDetector detector) {
-                if (DEBUG_SCALE) Slog.v(TAG, "onscalebegin()");
-                float focusX = detector.getFocusX();
-                float focusY = detector.getFocusY();
-
-                // your fingers have to be somewhat close to the bounds of the view in question
-                mInitialTouchFocusY = focusY;
-                mInitialTouchSpan = Math.abs(detector.getCurrentSpan());
-                if (DEBUG_SCALE) Slog.d(TAG, "got mInitialTouchSpan: (" + mInitialTouchSpan + ")");
-
-                final View underFocus = findView(focusX, focusY);
-                if (underFocus != null) {
-                    startExpanding(underFocus, STRETCH);
-                }
-                return mExpanding;
-            }
-
-            @Override
-            public boolean onScale(ScaleGestureDetector detector) {
-                if (DEBUG_SCALE) Slog.v(TAG, "onscale() on " + mCurrView);
-                updateExpansion();
-                return true;
-            }
-
-            @Override
-            public void onScaleEnd(ScaleGestureDetector detector) {
-                if (DEBUG_SCALE) Slog.v(TAG, "onscaleend()");
-                // I guess we're alone now
-                if (DEBUG_SCALE) Slog.d(TAG, "scale end");
-                finishExpanding(false);
-                clearView();
-            }
-        });
+        mSGD = new ScaleGestureDetector(context, mScaleGestureListener);
     }
 
     private void updateExpansion() {
+        if (DEBUG_SCALE) Slog.v(TAG, "updateExpansion()");
         // are we scaling or dragging?
-        float span = Math.abs(mSGD.getCurrentSpan()) - mInitialTouchSpan;
+        float span = mSGD.getCurrentSpan() - mInitialTouchSpan;
         span *= USE_SPAN ? 1f : 0f;
         float drag = mSGD.getFocusY() - mInitialTouchFocusY;
         drag *= USE_DRAG ? 1f : 0f;
@@ -251,6 +244,8 @@
         mScaler.setHeight(newHeight);
 
         setGlow(calculateGlow(target, newHeight));
+        mLastFocusY = mSGD.getFocusY();
+        mLastSpanY = mSGD.getCurrentSpan();
     }
 
     private float clamp(float target) {
@@ -362,6 +357,13 @@
         mSGD.onTouchEvent(ev);
         final int x = (int) mSGD.getFocusX();
         final int y = (int) mSGD.getFocusY();
+
+        mInitialTouchFocusY = y;
+        mInitialTouchSpan = mSGD.getCurrentSpan();
+        mLastFocusY = mInitialTouchFocusY;
+        mLastSpanY = mInitialTouchSpan;
+        if (DEBUG_SCALE) Slog.d(TAG, "set initial span: " + mInitialTouchSpan);
+
         if (mExpanding) {
             return true;
         } else {
@@ -376,8 +378,6 @@
                 // detect a vertical pulling gesture with fingers somewhat separated
                 if (DEBUG_SCALE) Slog.v(TAG, "got pull gesture (xspan=" + xspan + "px)");
 
-                mInitialTouchFocusY = y;
-
                 final View underFocus = findView(x, y);
                 if (underFocus != null) {
                     startExpanding(underFocus, PULL);
@@ -424,7 +424,7 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        final int action = ev.getAction();
+        final int action = ev.getActionMasked();
         if (DEBUG_SCALE) Slog.d(TAG, "touch: act=" + MotionEvent.actionToString(action) +
                 " expanding=" + mExpanding +
                 (0 != (mExpansionStyle & BLINDS) ? " (blinds)" : "") +
@@ -481,6 +481,14 @@
 
                 break;
             }
+
+            case MotionEvent.ACTION_POINTER_UP:
+            case MotionEvent.ACTION_POINTER_DOWN:
+                if (DEBUG) Slog.d(TAG, "pointer change");
+                mInitialTouchY += mSGD.getFocusY() - mLastFocusY;
+                mInitialTouchSpan += mSGD.getCurrentSpan() - mLastSpanY;
+                break;
+
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_CANCEL:
                 if (DEBUG) Slog.d(TAG, "up/cancel");
@@ -492,8 +500,11 @@
     }
 
     private void startExpanding(View v, int expandType) {
+        mExpansionStyle = expandType;
+        if (mExpanding &&  v == mCurrView) {
+            return;
+        }
         mExpanding = true;
-        mExpansionStyle = expandType; 
         if (DEBUG) Slog.d(TAG, "scale type " + expandType + " beginning on view: " + v);
         mCallback.setUserLockedChild(v, true);
         setView(v);
@@ -515,6 +526,8 @@
     private void finishExpanding(boolean force) {
         if (!mExpanding) return;
 
+        if (DEBUG) Slog.d(TAG, "scale in finishing on view: " + mCurrView);
+
         float currentHeight = mScaler.getHeight();
         float targetHeight = mSmallSize;
         float h = mScaler.getHeight();
@@ -539,6 +552,10 @@
         mExpanding = false;
         mExpansionStyle = NONE;
 
+        if (DEBUG) Slog.d(TAG, "wasClosed is: " + wasClosed);
+        if (DEBUG) Slog.d(TAG, "currentHeight is: " + currentHeight);
+        if (DEBUG) Slog.d(TAG, "mSmallSize is: " + mSmallSize);
+        if (DEBUG) Slog.d(TAG, "targetHeight is: " + targetHeight);
         if (DEBUG) Slog.d(TAG, "scale was finished on view: " + mCurrView);
     }
 
@@ -571,6 +588,17 @@
     }
 
     /**
+     * Use this to abort any pending expansions in progress.
+     */
+    public void cancel() {
+        finishExpanding(true);
+        clearView();
+
+        // reset the gesture detector
+        mSGD = new ScaleGestureDetector(mContext, mScaleGestureListener);
+    }
+
+    /**
      * Triggers haptic feedback.
      */
     private synchronized void vibrate(long duration) {
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index b0a7c4b..9da883a 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -19,6 +19,7 @@
 import android.app.ActivityManager;
 import android.app.WallpaperManager;
 import android.content.BroadcastReceiver;
+import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
@@ -64,6 +65,8 @@
 
     WallpaperManager mWallpaperManager;
 
+    DrawableEngine mEngine;
+
     boolean mIsHwAccelerated;
 
     @Override
@@ -74,20 +77,25 @@
         //noinspection PointlessBooleanExpression,ConstantConditions
         if (FIXED_SIZED_SURFACE && USE_OPENGL) {
             if (!isEmulator()) {
-                WindowManager windowManager =
-                        (WindowManager) getSystemService(Context.WINDOW_SERVICE);
-                Display display = windowManager.getDefaultDisplay();
-                mIsHwAccelerated = ActivityManager.isHighEndGfx(display);
+                mIsHwAccelerated = ActivityManager.isHighEndGfx();
             }
         }
     }
 
+    @Override
+    public void onTrimMemory(int level) {
+        if (mEngine != null) {
+            mEngine.trimMemory(level);
+        }
+    }
+
     private static boolean isEmulator() {
         return "1".equals(SystemProperties.get(PROPERTY_KERNEL_QEMU, "0"));
     }
 
     public Engine onCreateEngine() {
-        return new DrawableEngine();
+        mEngine = new DrawableEngine();
+        return mEngine;
     }
 
     class DrawableEngine extends Engine {
@@ -101,7 +109,8 @@
         private WallpaperObserver mReceiver;
 
         Bitmap mBackground;
-        int mBackgroundWidth = -1, mBackgroundHeight = -1;
+        int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
+        int mLastRotation = -1;
         float mXOffset;
         float mYOffset;
 
@@ -147,7 +156,7 @@
                 }
 
                 synchronized (mLock) {
-                    mBackgroundWidth = mBackgroundHeight = -1;
+                    mLastSurfaceWidth = mLastSurfaceHeight = -1;
                     mBackground = null;
                     mRedrawNeeded = true;
                     drawFrameLocked();
@@ -160,6 +169,18 @@
             setFixedSizeAllowed(true);
         }
 
+        public void trimMemory(int level) {
+            if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW &&
+                    mBackground != null && mIsHwAccelerated) {
+                if (DEBUG) {
+                    Log.d(TAG, "trimMemory");
+                }
+                mBackground.recycle();
+                mBackground = null;
+                mWallpaperManager.forgetLoadedWallpaper();
+            }
+        }
+
         @Override
         public void onCreate(SurfaceHolder surfaceHolder) {
             if (DEBUG) {
@@ -210,7 +231,7 @@
         @Override
         public void onVisibilityChanged(boolean visible) {
             if (DEBUG) {
-                Log.d(TAG, "onVisibilityChanged: visible=" + visible);
+                Log.d(TAG, "onVisibilityChanged: mVisible, visible=" + mVisible + ", " + visible);
             }
 
             synchronized (mLock) {
@@ -261,88 +282,126 @@
             super.onSurfaceChanged(holder, format, width, height);
 
             synchronized (mLock) {
-                mRedrawNeeded = true;
+                drawFrameLocked();
+            }
+        }
+
+        @Override
+        public void onSurfaceDestroyed(SurfaceHolder holder) {
+            super.onSurfaceDestroyed(holder);
+            mLastSurfaceWidth = mLastSurfaceHeight = -1;
+        }
+
+        @Override
+        public void onSurfaceCreated(SurfaceHolder holder) {
+            super.onSurfaceCreated(holder);
+            mLastSurfaceWidth = mLastSurfaceHeight = -1;
+        }
+
+        @Override
+        public void onSurfaceRedrawNeeded(SurfaceHolder holder) {
+            if (DEBUG) {
+                Log.d(TAG, "onSurfaceRedrawNeeded");
+            }
+            super.onSurfaceRedrawNeeded(holder);
+
+            synchronized (mLock) {
                 drawFrameLocked();
             }
         }
 
         void drawFrameLocked() {
-            if (!mVisible) {
-                if (DEBUG) {
-                    Log.d(TAG, "Suppressed drawFrame since wallpaper is not visible.");
-                }
-                return;
-            }
-            if (!mRedrawNeeded && !mOffsetsChanged) {
+            SurfaceHolder sh = getSurfaceHolder();
+            final Rect frame = sh.getSurfaceFrame();
+            final int dw = frame.width();
+            final int dh = frame.height();
+            int newRotation = ((WindowManager) getSystemService(WINDOW_SERVICE)).
+                    getDefaultDisplay().getRotation();
+            boolean surfaceDimensionsChanged = dw != mLastSurfaceWidth || dh != mLastSurfaceHeight;
+
+            boolean redrawNeeded = surfaceDimensionsChanged || newRotation != mLastRotation;
+            if (!redrawNeeded && !mOffsetsChanged) {
                 if (DEBUG) {
                     Log.d(TAG, "Suppressed drawFrame since redraw is not needed "
                             + "and offsets have not changed.");
                 }
                 return;
             }
+            mLastRotation = newRotation;
 
-            // If we don't yet know the size of the wallpaper bitmap,
-            // we need to get it now.
-            boolean updateWallpaper = mBackgroundWidth < 0 || mBackgroundHeight < 0 ;
-
-            // If we somehow got to this point after we have last flushed
-            // the wallpaper, well we really need it to draw again.  So
-            // seems like we need to reload it.  Ouch.
-            updateWallpaper = updateWallpaper || mBackground == null;
-
-            if (updateWallpaper) {
+            // Load bitmap if it is not yet loaded or if it was loaded at a different size
+            if (mBackground == null || surfaceDimensionsChanged) {
+                if (DEBUG) {
+                    Log.d(TAG, "Reloading bitmap: mBackground, bgw, bgh, dw, dh = " +
+                            mBackground + ", " +
+                            ((mBackground == null) ? 0 : mBackground.getWidth()) + ", " +
+                            ((mBackground == null) ? 0 : mBackground.getHeight()) + ", " +
+                            dw + ", " + dh);
+                }
                 updateWallpaperLocked();
+                if (mBackground == null) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Unable to load bitmap");
+                    }
+                    return;
+                }
+                if (DEBUG) {
+                    if (dw != mBackground.getWidth() || dh != mBackground.getHeight()) {
+                        Log.d(TAG, "Surface != bitmap dimensions: surface w/h, bitmap w/h: " +
+                                dw + ", " + dh + ", " + mBackground.getWidth() + ", " +
+                                mBackground.getHeight());
+                    }
+                }
             }
 
-            if (mBackground == null) {
-                // If we somehow got to this point after we have last flushed
-                // the wallpaper, well we really need it to draw again.  So
-                // seems like we need to reload it.  Ouch.
-                updateWallpaperLocked();
-            }
-
-            SurfaceHolder sh = getSurfaceHolder();
-            final Rect frame = sh.getSurfaceFrame();
-            final int dw = frame.width();
-            final int dh = frame.height();
-            final int availw = dw - mBackgroundWidth;
-            final int availh = dh - mBackgroundHeight;
+            final int availw = dw - mBackground.getWidth();
+            final int availh = dh - mBackground.getHeight();
             int xPixels = availw < 0 ? (int)(availw * mXOffset + .5f) : (availw / 2);
             int yPixels = availh < 0 ? (int)(availh * mYOffset + .5f) : (availh / 2);
 
             mOffsetsChanged = false;
-            if (!mRedrawNeeded && xPixels == mLastXTranslation && yPixels == mLastYTranslation) {
+            mRedrawNeeded = false;
+            if (surfaceDimensionsChanged) {
+                mLastSurfaceWidth = dw;
+                mLastSurfaceHeight = dh;
+            }
+            mLastXTranslation = xPixels;
+            mLastYTranslation = yPixels;
+            if (!redrawNeeded && xPixels == mLastXTranslation && yPixels == mLastYTranslation) {
                 if (DEBUG) {
                     Log.d(TAG, "Suppressed drawFrame since the image has not "
                             + "actually moved an integral number of pixels.");
                 }
                 return;
             }
-            mRedrawNeeded = false;
-            mLastXTranslation = xPixels;
-            mLastYTranslation = yPixels;
 
+            if (DEBUG) {
+                Log.d(TAG, "Redrawing wallpaper");
+            }
             if (mIsHwAccelerated) {
                 if (!drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels)) {
                     drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
                 }
             } else {
                 drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
+                if (FIXED_SIZED_SURFACE) {
+                    // If the surface is fixed-size, we should only need to
+                    // draw it once and then we'll let the window manager
+                    // position it appropriately.  As such, we no longer needed
+                    // the loaded bitmap.  Yay!
+                    // hw-accelerated path retains bitmap for faster rotation
+                    mBackground = null;
+                    mWallpaperManager.forgetLoadedWallpaper();
+                }
             }
 
-            if (FIXED_SIZED_SURFACE) {
-                // If the surface is fixed-size, we should only need to
-                // draw it once and then we'll let the window manager
-                // position it appropriately.  As such, we no longer needed
-                // the loaded bitmap.  Yay!
-                mBackground = null;
-                mWallpaperManager.forgetLoadedWallpaper();
-            }
         }
 
-        void updateWallpaperLocked() {
+        private void updateWallpaperLocked() {
             Throwable exception = null;
             try {
+                mWallpaperManager.forgetLoadedWallpaper(); // force reload
+                mBackground = null;
                 mBackground = mWallpaperManager.getBitmap();
             } catch (RuntimeException e) {
                 exception = e;
@@ -363,9 +422,6 @@
                     Log.w(TAG, "Unable reset to default wallpaper!", ex);
                 }
             }
-
-            mBackgroundWidth = mBackground != null ? mBackground.getWidth() : 0;
-            mBackgroundHeight = mBackground != null ? mBackground.getHeight() : 0;
         }
 
         private void drawWallpaperWithCanvas(SurfaceHolder sh, int w, int h, int x, int y) {
@@ -379,7 +435,8 @@
                     c.translate(x, y);
                     if (w < 0 || h < 0) {
                         c.save(Canvas.CLIP_SAVE_FLAG);
-                        c.clipRect(0, 0, mBackgroundWidth, mBackgroundHeight, Op.DIFFERENCE);
+                        c.clipRect(0, 0, mBackground.getWidth(), mBackground.getHeight(),
+                                Op.DIFFERENCE);
                         c.drawColor(0xff000000);
                         c.restore();
                     }
@@ -395,11 +452,10 @@
         private boolean drawWallpaperWithOpenGL(SurfaceHolder sh, int w, int h, int left, int top) {
             if (!initGL(sh)) return false;
 
-            final float right = left + mBackgroundWidth;
-            final float bottom = top + mBackgroundHeight;
+            final float right = left + mBackground.getWidth();
+            final float bottom = top + mBackground.getHeight();
 
             final Rect frame = sh.getSurfaceFrame();
-
             final Matrix4f ortho = new Matrix4f();
             ortho.loadOrtho(0.0f, frame.width(), frame.height(), 0.0f, -1.0f, 1.0f);
 
@@ -407,7 +463,7 @@
 
             final int texture = loadTexture(mBackground);
             final int program = buildProgram(sSimpleVS, sSimpleFS);
-    
+
             final int attribPosition = glGetAttribLocation(program, "position");
             final int attribTexCoords = glGetAttribLocation(program, "texCoords");
             final int uniformTexture = glGetUniformLocation(program, "texture");
@@ -430,7 +486,7 @@
                 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
                 glClear(GL_COLOR_BUFFER_BIT);
             }
-    
+
             // drawQuad
             triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
             glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false,
@@ -441,12 +497,12 @@
                     TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
 
             glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-    
+
             if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
                 throw new RuntimeException("Cannot swap buffers");
             }
             checkEglError();
-    
+
             finishGL();
 
             return true;
@@ -488,8 +544,6 @@
             GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0);
             checkGlError();
 
-            bitmap.recycle();
-    
             return texture;
         }
         
@@ -637,6 +691,7 @@
                     EGL_ALPHA_SIZE, 0,
                     EGL_DEPTH_SIZE, 0,
                     EGL_STENCIL_SIZE, 0,
+                    EGL_CONFIG_CAVEAT, EGL_NONE,
                     EGL_NONE
             };
         }
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
index 475fb6d..daac9ed 100644
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -17,6 +17,7 @@
 package com.android.systemui;
 
 import android.animation.LayoutTransition;
+import android.app.ActivityManagerNative;
 import android.app.ActivityOptions;
 import android.app.SearchManager;
 import android.content.ActivityNotFoundException;
@@ -24,10 +25,14 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.os.Vibrator;
 import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.Slog;
+import android.view.IWindowManager;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
@@ -59,6 +64,7 @@
     private boolean mShowing;
     private View mSearchTargetsContainer;
     private GlowPadView mGlowPadView;
+    private IWindowManager mWm;
 
     public SearchPanelView(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
@@ -67,23 +73,52 @@
     public SearchPanelView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         mContext = context;
+        mWm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
     }
 
     private void startAssistActivity() {
+        if (!mBar.isDeviceProvisioned()) return;
+
         // Close Recent Apps if needed
-        mBar.animateCollapse(CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL);
-        // Launch Assist
-        Intent intent = SearchManager.getAssistIntent(mContext);
-        if (intent == null) return;
+        mBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL);
+        boolean isKeyguardShowing = false;
         try {
-            ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
-                    R.anim.search_launch_enter, R.anim.search_launch_exit,
-                    getHandler(), this);
-            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            mContext.startActivity(intent, opts.toBundle());
-        } catch (ActivityNotFoundException e) {
-            Slog.w(TAG, "Activity not found for " + intent.getAction());
+            isKeyguardShowing = mWm.isKeyguardLocked();
+        } catch (RemoteException e) {
+
+        }
+
+        if (isKeyguardShowing) {
+            // Have keyguard show the bouncer and launch the activity if the user succeeds.
+            try {
+                mWm.showAssistant();
+            } catch (RemoteException e) {
+                // too bad, so sad...
+            }
             onAnimationStarted();
+        } else {
+            // Otherwise, keyguard isn't showing so launch it from here.
+            Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                    .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+            if (intent == null) return;
+
+            try {
+                ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
+            } catch (RemoteException e) {
+                // too bad, so sad...
+            }
+
+            try {
+                ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
+                        R.anim.search_launch_enter, R.anim.search_launch_exit,
+                        getHandler(), this);
+                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                mContext.startActivityAsUser(intent, opts.toBundle(),
+                        new UserHandle(UserHandle.USER_CURRENT));
+            } catch (ActivityNotFoundException e) {
+                Slog.w(TAG, "Activity not found for " + intent.getAction());
+                onAnimationStarted();
+            }
         }
     }
 
@@ -140,7 +175,8 @@
     }
 
     private void maybeSwapSearchIcon() {
-        Intent intent = SearchManager.getAssistIntent(mContext);
+        Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                .getAssistIntent(mContext, UserHandle.USER_CURRENT);
         if (intent != null) {
             ComponentName component = intent.getComponent();
             if (component == null || !mGlowPadView.replaceTargetDrawablesIfPresent(component,
@@ -180,8 +216,8 @@
 
     private void vibrate() {
         Context context = getContext();
-        if (Settings.System.getInt(context.getContentResolver(),
-                Settings.System.HAPTIC_FEEDBACK_ENABLED, 1) != 0) {
+        if (Settings.System.getIntForUser(context.getContentResolver(),
+                Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0) {
             Resources res = context.getResources();
             Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
             vibrator.vibrate(res.getInteger(R.integer.config_search_panel_view_vibration_duration));
@@ -216,7 +252,7 @@
     public void hide(boolean animate) {
         if (mBar != null) {
             // This will indirectly cause show(false, ...) to get called
-            mBar.animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
+            mBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
         } else {
             setVisibility(View.INVISIBLE);
         }
@@ -277,6 +313,7 @@
     }
 
     public boolean isAssistantAvailable() {
-        return SearchManager.getAssistIntent(mContext) != null;
+        return ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                .getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/Somnambulator.java b/packages/SystemUI/src/com/android/systemui/Somnambulator.java
new file mode 100644
index 0000000..0dd6d92
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/Somnambulator.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.service.dreams.Sandman;
+
+/**
+ * A simple activity that launches a dream.
+ * <p>
+ * Note: This Activity is special.  If this class is moved to another package or
+ * renamed, be sure to update the component name in {@link Sandman}.
+ * </p>
+ */
+public class Somnambulator extends Activity {
+    public Somnambulator() {
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+
+        final Intent launchIntent = getIntent();
+        final String action = launchIntent.getAction();
+        if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {
+            Intent shortcutIntent = new Intent(this, Somnambulator.class);
+            shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+                    | Intent.FLAG_ACTIVITY_NEW_TASK);
+            Intent resultIntent = new Intent();
+            resultIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
+                    Intent.ShortcutIconResource.fromContext(this, R.mipmap.ic_launcher_dreams));
+            resultIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
+            resultIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, getString(R.string.start_dreams));
+            setResult(RESULT_OK, resultIntent);
+        } else {
+            boolean docked = launchIntent.hasCategory(Intent.CATEGORY_DESK_DOCK);
+            if (docked) {
+                Sandman.startDreamWhenDockedIfAppropriate(this);
+            } else {
+                Sandman.startDreamByUserRequest(this);
+            }
+        }
+        finish();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 0a57499..427fe91 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -31,6 +31,8 @@
 import android.os.ServiceManager;
 import android.util.Slog;
 import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityManager;
 
 public class SystemUIService extends Service {
     static final String TAG = "SystemUIService";
@@ -66,9 +68,12 @@
 
     @Override
     public void onCreate() {
+        // Tell the accessibility layer that this process will
+        // run as the current user, i.e. run across users.
+        AccessibilityManager.createAsSharedAcrossUsers(this);
+
         // Pick status bar or system bar.
-        IWindowManager wm = IWindowManager.Stub.asInterface(
-                ServiceManager.getService(Context.WINDOW_SERVICE));
+        IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
         try {
             SERVICES[0] = wm.hasSystemNavBar()
                     ? R.string.config_systemBarComponent
diff --git a/packages/SystemUI/src/com/android/systemui/UniverseBackground.java b/packages/SystemUI/src/com/android/systemui/UniverseBackground.java
new file mode 100644
index 0000000..7628754
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/UniverseBackground.java
@@ -0,0 +1,458 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Matrix;
+import android.graphics.PixelFormat;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+import android.view.Choreographer;
+import android.view.Display;
+import android.view.IWindowSession;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewRootImpl;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+import android.view.animation.Transformation;
+import android.widget.FrameLayout;
+
+public class UniverseBackground extends FrameLayout {
+    static final String TAG = "UniverseBackground";
+    static final boolean SPEW = false;
+    static final boolean CHATTY = false;
+
+    final IWindowSession mSession;
+    final View mContent;
+    final View mBottomAnchor;
+
+    final Runnable mAnimationCallback = new Runnable() {
+        @Override
+        public void run() {
+            doAnimation(mChoreographer.getFrameTimeNanos());
+        }
+    };
+
+    // fling gesture tuning parameters, scaled to display density
+    private float mSelfExpandVelocityPx; // classic value: 2000px/s
+    private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
+    private float mFlingExpandMinVelocityPx; // classic value: 200px/s
+    private float mFlingCollapseMinVelocityPx; // classic value: 200px/s
+    private float mCollapseMinDisplayFraction; // classic value: 0.08 (25px/min(320px,480px) on G1)
+    private float mExpandMinDisplayFraction; // classic value: 0.5 (drag open halfway to expand)
+    private float mFlingGestureMaxXVelocityPx; // classic value: 150px/s
+
+    private float mExpandAccelPx; // classic value: 2000px/s/s
+    private float mCollapseAccelPx; // classic value: 2000px/s/s (will be negated to collapse "up")
+
+    static final int STATE_CLOSED = 0;
+    static final int STATE_OPENING = 1;
+    static final int STATE_OPEN = 2;
+    private int mState = STATE_CLOSED;
+
+    private float mDragStartX, mDragStartY;
+    private float mAverageX, mAverageY;
+
+    // position
+    private int[] mPositionTmp = new int[2];
+    private boolean mExpanded;
+    private boolean mExpandedVisible;
+
+    private boolean mTracking;
+    private VelocityTracker mVelocityTracker;
+
+    private Choreographer mChoreographer;
+    private boolean mAnimating;
+    private boolean mClosing; // only valid when mAnimating; indicates the initial acceleration
+    private float mAnimY;
+    private float mAnimVel;
+    private float mAnimAccel;
+    private long mAnimLastTimeNanos;
+    private boolean mAnimatingReveal = false;
+
+    private int mYDelta = 0;
+    private Transformation mUniverseTransform = new Transformation();
+    private final float[] mTmpFloats = new float[9];
+
+    public UniverseBackground(Context context) {
+        super(context);
+        setBackgroundColor(0xff000000);
+        mSession = WindowManagerGlobal.getWindowSession(context.getMainLooper());
+        mContent = View.inflate(context, R.layout.universe, null);
+        addView(mContent);
+        mContent.findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
+            @Override public void onClick(View v) {
+                animateCollapse();
+            }
+        });
+        mBottomAnchor = mContent.findViewById(R.id.bottom);
+        mChoreographer = Choreographer.getInstance();
+        loadDimens();
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        loadDimens();
+    }
+
+    private void loadDimens() {
+        final Resources res = getContext().getResources();
+        mSelfExpandVelocityPx = res.getDimension(R.dimen.self_expand_velocity);
+        mSelfCollapseVelocityPx = res.getDimension(R.dimen.self_collapse_velocity);
+        mFlingExpandMinVelocityPx = res.getDimension(R.dimen.fling_expand_min_velocity);
+        mFlingCollapseMinVelocityPx = res.getDimension(R.dimen.fling_collapse_min_velocity);
+
+        mCollapseMinDisplayFraction = res.getFraction(R.dimen.collapse_min_display_fraction, 1, 1);
+        mExpandMinDisplayFraction = res.getFraction(R.dimen.expand_min_display_fraction, 1, 1);
+
+        mExpandAccelPx = res.getDimension(R.dimen.expand_accel);
+        mCollapseAccelPx = res.getDimension(R.dimen.collapse_accel);
+
+        mFlingGestureMaxXVelocityPx = res.getDimension(R.dimen.fling_gesture_max_x_velocity);
+    }
+
+    private void computeAveragePos(MotionEvent event) {
+        final int num = event.getPointerCount();
+        float x = 0, y = 0;
+        for (int i=0; i<num; i++) {
+            x += event.getX(i);
+            y += event.getY(i);
+        }
+        mAverageX = x / num;
+        mAverageY = y / num;
+    }
+
+    private void sendUniverseTransform() {
+        if (getWindowToken() != null) {
+            mUniverseTransform.getMatrix().getValues(mTmpFloats);
+            try {
+                mSession.setUniverseTransform(getWindowToken(), mUniverseTransform.getAlpha(),
+                        mTmpFloats[Matrix.MTRANS_X], mTmpFloats[Matrix.MTRANS_Y],
+                        mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
+                        mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    public WindowManager.LayoutParams getLayoutParams() {
+        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
+                WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND,
+                    0
+                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+                PixelFormat.OPAQUE);
+        // this will allow the window to run in an overlay on devices that support this
+        if (ActivityManager.isHighEndGfx()) {
+            lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+        }
+        lp.setTitle("UniverseBackground");
+        lp.windowAnimations = 0;
+        return lp;
+    }
+
+    private int getExpandedViewMaxHeight() {
+        return mBottomAnchor.getTop();
+    }
+
+    public void animateCollapse() {
+        animateCollapse(1.0f);
+    }
+
+    public void animateCollapse(float velocityMultiplier) {
+        if (SPEW) {
+            Slog.d(TAG, "animateCollapse(): mExpanded=" + mExpanded
+                    + " mExpandedVisible=" + mExpandedVisible
+                    + " mExpanded=" + mExpanded
+                    + " mAnimating=" + mAnimating
+                    + " mAnimY=" + mAnimY
+                    + " mAnimVel=" + mAnimVel);
+        }
+
+        mState = STATE_CLOSED;
+        if (!mExpandedVisible) {
+            return;
+        }
+
+        int y;
+        if (mAnimating) {
+            y = (int)mAnimY;
+        } else {
+            y = getExpandedViewMaxHeight()-1;
+        }
+        // Let the fling think that we're open so it goes in the right direction
+        // and doesn't try to re-open the windowshade.
+        mExpanded = true;
+        prepareTracking(y, false);
+        performFling(y, -mSelfCollapseVelocityPx*velocityMultiplier, true);
+    }
+
+    private void updateUniverseScale() {
+        if (mYDelta > 0) {
+            int w = getWidth();
+            int h = getHeight();
+            float scale = (h-mYDelta+.5f) / (float)h;
+            mUniverseTransform.getMatrix().setScale(scale, scale, w/2, h);
+            if (CHATTY) Log.i(TAG, "w=" + w + " h=" + h + " scale=" + scale
+                    + ": " + mUniverseTransform);
+            sendUniverseTransform();
+            if (getVisibility() != VISIBLE) {
+                setVisibility(VISIBLE);
+            }
+        } else {
+            if (CHATTY) Log.i(TAG, "mYDelta=" + mYDelta);
+            mUniverseTransform.clear();
+            sendUniverseTransform();
+            if (getVisibility() == VISIBLE) {
+                setVisibility(GONE);
+            }
+        }
+    }
+
+    void resetLastAnimTime() {
+        mAnimLastTimeNanos = System.nanoTime();
+        if (SPEW) {
+            Throwable t = new Throwable();
+            t.fillInStackTrace();
+            Slog.d(TAG, "resetting last anim time=" + mAnimLastTimeNanos, t);
+        }
+    }
+
+    void doAnimation(long frameTimeNanos) {
+        if (mAnimating) {
+            if (SPEW) Slog.d(TAG, "doAnimation dt=" + (frameTimeNanos - mAnimLastTimeNanos));
+            if (SPEW) Slog.d(TAG, "doAnimation before mAnimY=" + mAnimY);
+            incrementAnim(frameTimeNanos);
+            if (SPEW) {
+                Slog.d(TAG, "doAnimation after  mAnimY=" + mAnimY);
+            }
+
+            if (mAnimY >= getExpandedViewMaxHeight()-1 && !mClosing) {
+                if (SPEW) Slog.d(TAG, "Animation completed to expanded state.");
+                mAnimating = false;
+                mYDelta = getExpandedViewMaxHeight();
+                updateUniverseScale();
+                mExpanded = true;
+                mState = STATE_OPEN;
+                return;
+            }
+
+            if (mAnimY <= 0 && mClosing) {
+                if (SPEW) Slog.d(TAG, "Animation completed to collapsed state.");
+                mAnimating = false;
+                mYDelta = 0;
+                updateUniverseScale();
+                mExpanded = false;
+                mState = STATE_CLOSED;
+                return;
+            }
+
+            mYDelta = (int)mAnimY;
+            updateUniverseScale();
+            mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
+                    mAnimationCallback, null);
+        }
+    }
+
+    void stopTracking() {
+        mTracking = false;
+        mVelocityTracker.recycle();
+        mVelocityTracker = null;
+    }
+
+    void incrementAnim(long frameTimeNanos) {
+        final long deltaNanos = Math.max(frameTimeNanos - mAnimLastTimeNanos, 0);
+        final float t = deltaNanos * 0.000000001f;                  // ns -> s
+        final float y = mAnimY;
+        final float v = mAnimVel;                                   // px/s
+        final float a = mAnimAccel;                                 // px/s/s
+        mAnimY = y + (v*t) + (0.5f*a*t*t);                          // px
+        mAnimVel = v + (a*t);                                       // px/s
+        mAnimLastTimeNanos = frameTimeNanos;                        // ns
+        //Slog.d(TAG, "y=" + y + " v=" + v + " a=" + a + " t=" + t + " mAnimY=" + mAnimY
+        //        + " mAnimAccel=" + mAnimAccel);
+    }
+
+    void prepareTracking(int y, boolean opening) {
+        if (CHATTY) {
+            Slog.d(TAG, "panel: beginning to track the user's touch, y=" + y + " opening=" + opening);
+        }
+
+        mTracking = true;
+        mVelocityTracker = VelocityTracker.obtain();
+        if (opening) {
+            mAnimAccel = mExpandAccelPx;
+            mAnimVel = mFlingExpandMinVelocityPx;
+            mAnimY = y;
+            mAnimating = true;
+            mAnimatingReveal = true;
+            resetLastAnimTime();
+            mExpandedVisible = true;
+        }
+        if (mAnimating) {
+            mAnimating = false;
+            mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
+                    mAnimationCallback, null);
+        }
+    }
+
+    void performFling(int y, float vel, boolean always) {
+        if (CHATTY) {
+            Slog.d(TAG, "panel: will fling, y=" + y + " vel=" + vel);
+        }
+
+        mAnimatingReveal = false;
+
+        mAnimY = y;
+        mAnimVel = vel;
+
+        //Slog.d(TAG, "starting with mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel);
+
+        if (mExpanded) {
+            if (!always && (
+                    vel > mFlingCollapseMinVelocityPx
+                    || (y > (getExpandedViewMaxHeight()*(1f-mCollapseMinDisplayFraction)) &&
+                        vel > -mFlingExpandMinVelocityPx))) {
+                // We are expanded, but they didn't move sufficiently to cause
+                // us to retract.  Animate back to the expanded position.
+                mAnimAccel = mExpandAccelPx;
+                if (vel < 0) {
+                    mAnimVel = 0;
+                }
+            }
+            else {
+                // We are expanded and are now going to animate away.
+                mAnimAccel = -mCollapseAccelPx;
+                if (vel > 0) {
+                    mAnimVel = 0;
+                }
+            }
+        } else {
+            if (always || (
+                    vel > mFlingExpandMinVelocityPx
+                    || (y > (getExpandedViewMaxHeight()*(1f-mExpandMinDisplayFraction)) &&
+                        vel > -mFlingCollapseMinVelocityPx))) {
+                // We are collapsed, and they moved enough to allow us to
+                // expand.  Animate in the notifications.
+                mAnimAccel = mExpandAccelPx;
+                if (vel < 0) {
+                    mAnimVel = 0;
+                }
+            }
+            else {
+                // We are collapsed, but they didn't move sufficiently to cause
+                // us to retract.  Animate back to the collapsed position.
+                mAnimAccel = -mCollapseAccelPx;
+                if (vel > 0) {
+                    mAnimVel = 0;
+                }
+            }
+        }
+        //Slog.d(TAG, "mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel
+        //        + " mAnimAccel=" + mAnimAccel);
+
+        resetLastAnimTime();
+        mAnimating = true;
+        mClosing = mAnimAccel < 0;
+        mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
+                mAnimationCallback, null);
+        mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
+                mAnimationCallback, null);
+
+        stopTracking();
+    }
+
+    private void trackMovement(MotionEvent event) {
+        mVelocityTracker.addMovement(event);
+    }
+
+    public boolean consumeEvent(MotionEvent event) {
+        if (mState == STATE_CLOSED) {
+            if (event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
+                // Second finger down, time to start opening!
+                computeAveragePos(event);
+                mDragStartX = mAverageX;
+                mDragStartY = mAverageY;
+                mYDelta = 0;
+                mUniverseTransform.clear();
+                sendUniverseTransform();
+                setVisibility(VISIBLE);
+                mState = STATE_OPENING;
+                prepareTracking((int)mDragStartY, true);
+                mVelocityTracker.clear();
+                trackMovement(event);
+                return true;
+            }
+            return false;
+        }
+
+        if (mState == STATE_OPENING) {
+            if (event.getActionMasked() == MotionEvent.ACTION_UP
+                    || event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
+                mVelocityTracker.computeCurrentVelocity(1000);
+                computeAveragePos(event);
+
+                float yVel = mVelocityTracker.getYVelocity();
+                boolean negative = yVel < 0;
+
+                float xVel = mVelocityTracker.getXVelocity();
+                if (xVel < 0) {
+                    xVel = -xVel;
+                }
+                if (xVel > mFlingGestureMaxXVelocityPx) {
+                    xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
+                }
+
+                float vel = (float)Math.hypot(yVel, xVel);
+                if (negative) {
+                    vel = -vel;
+                }
+
+                if (CHATTY) {
+                    Slog.d(TAG, String.format("gesture: vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f",
+                        mVelocityTracker.getXVelocity(),
+                        mVelocityTracker.getYVelocity(),
+                        xVel, yVel,
+                        vel));
+                }
+
+                performFling((int)mAverageY, vel, false);
+                mState = STATE_OPEN;
+                return true;
+            }
+
+            computeAveragePos(event);
+            mYDelta = (int)(mAverageY - mDragStartY);
+            if (mYDelta > getExpandedViewMaxHeight()) {
+                mYDelta = getExpandedViewMaxHeight();
+            }
+            updateUniverseScale();
+            return true;
+        }
+
+        return false;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index 3502b62..0c6e59c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -17,6 +17,7 @@
 package com.android.systemui.media;
 
 import android.content.Context;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.media.IAudioService;
 import android.media.IRingtonePlayer;
 import android.media.Ringtone;
@@ -26,6 +27,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.Slog;
 
 import com.android.systemui.SystemUI;
@@ -70,9 +72,10 @@
         private final IBinder mToken;
         private final Ringtone mRingtone;
 
-        public Client(IBinder token, Uri uri, int streamType) {
+        public Client(IBinder token, Uri uri, UserHandle user, int streamType) {
             mToken = token;
-            mRingtone = new Ringtone(mContext, false);
+
+            mRingtone = new Ringtone(getContextForUser(user), false);
             mRingtone.setStreamType(streamType);
             mRingtone.setUri(uri);
         }
@@ -90,12 +93,16 @@
     private IRingtonePlayer mCallback = new IRingtonePlayer.Stub() {
         @Override
         public void play(IBinder token, Uri uri, int streamType) throws RemoteException {
-            if (LOGD) Slog.d(TAG, "play(token=" + token + ", uri=" + uri + ")");
+            if (LOGD) {
+                Slog.d(TAG, "play(token=" + token + ", uri=" + uri + ", uid="
+                        + Binder.getCallingUid() + ")");
+            }
             Client client;
             synchronized (mClients) {
                 client = mClients.get(token);
                 if (client == null) {
-                    client = new Client(token, uri, streamType);
+                    final UserHandle user = Binder.getCallingUserHandle();
+                    client = new Client(token, uri, user, streamType);
                     token.linkToDeath(client, 0);
                     mClients.put(token, client);
                 }
@@ -131,12 +138,13 @@
         }
 
         @Override
-        public void playAsync(Uri uri, boolean looping, int streamType) {
-            if (LOGD) Slog.d(TAG, "playAsync(uri=" + uri + ")");
+        public void playAsync(Uri uri, UserHandle user, boolean looping, int streamType) {
+            if (LOGD) Slog.d(TAG, "playAsync(uri=" + uri + ", user=" + user + ")");
             if (Binder.getCallingUid() != Process.SYSTEM_UID) {
                 throw new SecurityException("Async playback only available from system UID.");
             }
-            mAsyncPlayer.play(mContext, uri, looping, streamType);
+
+            mAsyncPlayer.play(getContextForUser(user), uri, looping, streamType);
         }
 
         @Override
@@ -149,6 +157,14 @@
         }
     };
 
+    private Context getContextForUser(UserHandle user) {
+        try {
+            return mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user);
+        } catch (NameNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("Clients:");
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 3c30f5d..ccb711a 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -30,6 +30,7 @@
 import android.net.Uri;
 import android.os.BatteryManager;
 import android.os.Handler;
+import android.os.UserHandle;
 import android.media.AudioManager;
 import android.media.Ringtone;
 import android.media.RingtoneManager;
@@ -207,8 +208,9 @@
             if (intent.resolveActivity(mContext.getPackageManager()) != null) {
                 b.setNegativeButton(R.string.battery_low_why,
                         new DialogInterface.OnClickListener() {
+                    @Override
                     public void onClick(DialogInterface dialog, int which) {
-                        mContext.startActivity(intent);
+                        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
                         dismissLowBatteryWarning();
                     }
                 });
@@ -216,12 +218,15 @@
 
             AlertDialog d = b.create();
             d.setOnDismissListener(new DialogInterface.OnDismissListener() {
+                    @Override
                     public void onDismiss(DialogInterface dialog) {
                         mLowBatteryDialog = null;
                         mBatteryLevelTextView = null;
                     }
                 });
             d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+            d.getWindow().getAttributes().privateFlags |=
+                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
             d.show();
             mLowBatteryDialog = d;
         }
@@ -233,9 +238,9 @@
         }
 
         final ContentResolver cr = mContext.getContentResolver();
-        if (Settings.System.getInt(cr, Settings.System.POWER_SOUNDS_ENABLED, 1) == 1) {
-            final String soundPath = Settings.System.getString(cr,
-                    Settings.System.LOW_BATTERY_SOUND);
+        if (Settings.Global.getInt(cr, Settings.Global.POWER_SOUNDS_ENABLED, 1) == 1) {
+            final String soundPath = Settings.Global.getString(cr,
+                    Settings.Global.LOW_BATTERY_SOUND);
             if (soundPath != null) {
                 final Uri soundUri = Uri.parse("file://" + soundPath);
                 if (soundUri != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
deleted file mode 100644
index 296b640..0000000
--- a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
+++ /dev/null
@@ -1,192 +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.
- */
-
-package com.android.systemui.recent;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.AnimatorSet.Builder;
-import android.animation.ObjectAnimator;
-import android.content.res.Resources;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.util.Slog;
-import android.view.View;
-import android.view.ViewRootImpl;
-
-import com.android.systemui.R;
-
-/* package */ class Choreographer implements Animator.AnimatorListener {
-    // should group this into a multi-property animation
-    private static final int OPEN_DURATION = 136;
-    private static final int CLOSE_DURATION = 230;
-    private static final int SCRIM_DURATION = 400;
-    private static final String TAG = RecentsPanelView.TAG;
-    private static final boolean DEBUG = RecentsPanelView.DEBUG;
-
-    boolean mVisible;
-    int mPanelHeight;
-    RecentsPanelView mRootView;
-    View mScrimView;
-    View mContentView;
-    View mNoRecentAppsView;
-    AnimatorSet mContentAnim;
-    Animator.AnimatorListener mListener;
-
-    // the panel will start to appear this many px from the end
-    final int HYPERSPACE_OFFRAMP = 200;
-
-    public Choreographer(RecentsPanelView root, View scrim, View content,
-            View noRecentApps, Animator.AnimatorListener listener) {
-        mRootView = root;
-        mScrimView = scrim;
-        mContentView = content;
-        mListener = listener;
-        mNoRecentAppsView = noRecentApps;
-    }
-
-    void createAnimation(boolean appearing) {
-        float start, end;
-
-        // 0: on-screen
-        // height: off-screen
-        float y = mContentView.getTranslationY();
-        if (appearing) {
-            // we want to go from near-the-top to the top, unless we're half-open in the right
-            // general vicinity
-            start = (y < HYPERSPACE_OFFRAMP) ? y : HYPERSPACE_OFFRAMP;
-            end = 0;
-        } else {
-            start = y;
-            end = y;
-        }
-
-        Animator posAnim = ObjectAnimator.ofFloat(mContentView, "translationY",
-                start, end);
-        posAnim.setInterpolator(appearing
-                ? new android.view.animation.DecelerateInterpolator(2.5f)
-                : new android.view.animation.AccelerateInterpolator(2.5f));
-        posAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
-
-        Animator fadeAnim = ObjectAnimator.ofFloat(mContentView, "alpha",
-                mContentView.getAlpha(), appearing ? 1.0f : 0.0f);
-        fadeAnim.setInterpolator(appearing
-                ? new android.view.animation.AccelerateInterpolator(1.0f)
-                : new android.view.animation.AccelerateInterpolator(2.5f));
-        fadeAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
-
-        Animator noRecentAppsFadeAnim = null;
-        if (mNoRecentAppsView != null &&  // doesn't exist on large devices
-                mNoRecentAppsView.getVisibility() == View.VISIBLE) {
-            noRecentAppsFadeAnim = ObjectAnimator.ofFloat(mNoRecentAppsView, "alpha",
-                    mContentView.getAlpha(), appearing ? 1.0f : 0.0f);
-            noRecentAppsFadeAnim.setInterpolator(appearing
-                    ? new android.view.animation.AccelerateInterpolator(1.0f)
-                    : new android.view.animation.DecelerateInterpolator(1.0f));
-            noRecentAppsFadeAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
-        }
-
-        mContentAnim = new AnimatorSet();
-        final Builder builder = mContentAnim.play(fadeAnim).with(posAnim);
-
-        if (noRecentAppsFadeAnim != null) {
-            builder.with(noRecentAppsFadeAnim);
-        }
-
-        if (appearing) {
-            Drawable background = mScrimView.getBackground();
-            if (background != null) {
-                Animator bgAnim = ObjectAnimator.ofInt(background,
-                    "alpha", appearing ? 0 : 255, appearing ? 255 : 0);
-                bgAnim.setDuration(appearing ? SCRIM_DURATION : CLOSE_DURATION);
-                builder.with(bgAnim);
-            }
-        } else {
-            final Resources res = mRootView.getResources();
-            boolean isTablet = res.getBoolean(R.bool.config_recents_interface_for_tablets);
-            if (!isTablet) {
-                View recentsTransitionBackground =
-                        mRootView.findViewById(R.id.recents_transition_background);
-                recentsTransitionBackground.setVisibility(View.VISIBLE);
-                Drawable bgDrawable = new ColorDrawable(0xFF000000);
-                recentsTransitionBackground.setBackground(bgDrawable);
-                Animator bgAnim = ObjectAnimator.ofInt(bgDrawable, "alpha", 0, 255);
-                bgAnim.setDuration(CLOSE_DURATION);
-                bgAnim.setInterpolator(new android.view.animation.AccelerateInterpolator(1f));
-                builder.with(bgAnim);
-            }
-        }
-        mContentAnim.addListener(this);
-        if (mListener != null) {
-            mContentAnim.addListener(mListener);
-        }
-    }
-
-    void startAnimation(boolean appearing) {
-        if (DEBUG) Slog.d(TAG, "startAnimation(appearing=" + appearing + ")");
-
-        createAnimation(appearing);
-
-        // isHardwareAccelerated() checks if we're attached to a window and if that
-        // window is HW accelerated-- we were sometimes not attached to a window
-        // and buildLayer was throwing an IllegalStateException
-        if (mContentView.isHardwareAccelerated()) {
-            mContentView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-            mContentView.buildLayer();
-        }
-        mContentAnim.start();
-
-        mVisible = appearing;
-    }
-
-    void jumpTo(boolean appearing) {
-        mContentView.setTranslationY(appearing ? 0 : mPanelHeight);
-        if (mScrimView.getBackground() != null) {
-            mScrimView.getBackground().setAlpha(appearing ? 255 : 0);
-        }
-        View recentsTransitionBackground =
-                mRootView.findViewById(R.id.recents_transition_background);
-        recentsTransitionBackground.setVisibility(View.INVISIBLE);
-        mRootView.requestLayout();
-    }
-
-    public void setPanelHeight(int h) {
-        if (DEBUG) Slog.d(TAG, "panelHeight=" + h);
-        mPanelHeight = h;
-    }
-
-    public void onAnimationCancel(Animator animation) {
-        if (DEBUG) Slog.d(TAG, "onAnimationCancel");
-        // force this to zero so we close the window
-        mVisible = false;
-    }
-
-    public void onAnimationEnd(Animator animation) {
-        if (DEBUG) Slog.d(TAG, "onAnimationEnd");
-        if (!mVisible) {
-            mRootView.hideWindow();
-        }
-        mContentView.setLayerType(View.LAYER_TYPE_NONE, null);
-        mContentView.setAlpha(1f);
-        mContentAnim = null;
-    }
-
-    public void onAnimationRepeat(Animator animation) {
-    }
-
-    public void onAnimationStart(Animator animation) {
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index f5894ea..4338fa0 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -30,7 +30,10 @@
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Process;
+import android.os.UserHandle;
 import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
@@ -41,7 +44,7 @@
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
 
-public class RecentTasksLoader {
+public class RecentTasksLoader implements View.OnTouchListener {
     static final String TAG = "RecentTasksLoader";
     static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
 
@@ -51,17 +54,37 @@
     private Context mContext;
     private RecentsPanelView mRecentsPanel;
 
+    private Object mFirstTaskLock = new Object();
+    private TaskDescription mFirstTask;
+    private boolean mFirstTaskLoaded;
+
     private AsyncTask<Void, ArrayList<TaskDescription>, Void> mTaskLoader;
     private AsyncTask<Void, TaskDescription, Void> mThumbnailLoader;
-    private final Handler mHandler;
+    private Handler mHandler;
 
     private int mIconDpi;
     private Bitmap mDefaultThumbnailBackground;
     private Bitmap mDefaultIconBackground;
-    private int mNumTasksInFirstScreenful;
+    private int mNumTasksInFirstScreenful = Integer.MAX_VALUE;
 
-    public RecentTasksLoader(Context context) {
+    private boolean mFirstScreenful;
+    private ArrayList<TaskDescription> mLoadedTasks;
+
+    private enum State { LOADING, LOADED, CANCELLED };
+    private State mState = State.CANCELLED;
+
+
+    private static RecentTasksLoader sInstance;
+    public static RecentTasksLoader getInstance(Context context) {
+        if (sInstance == null) {
+            sInstance = new RecentTasksLoader(context);
+        }
+        return sInstance;
+    }
+
+    private RecentTasksLoader(Context context) {
         mContext = context;
+        mHandler = new Handler();
 
         final Resources res = context.getResources();
 
@@ -91,18 +114,16 @@
                 Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ARGB_8888);
         Canvas c = new Canvas(mDefaultThumbnailBackground);
         c.drawColor(color);
-
-        // If we're using the cache, begin listening to the activity manager for
-        // updated thumbnails
-        final ActivityManager am = (ActivityManager)
-                mContext.getSystemService(Context.ACTIVITY_SERVICE);
-
-        mHandler = new Handler();
     }
 
-    public void setRecentsPanel(RecentsPanelView recentsPanel) {
-        mRecentsPanel = recentsPanel;
-        mNumTasksInFirstScreenful = mRecentsPanel.numItemsInOneScreenful();
+    public void setRecentsPanel(RecentsPanelView newRecentsPanel, RecentsPanelView caller) {
+        // Only allow clearing mRecentsPanel if the caller is the current recentsPanel
+        if (newRecentsPanel != null || mRecentsPanel == caller) {
+            mRecentsPanel = newRecentsPanel;
+            if (mRecentsPanel != null) {
+                mNumTasksInFirstScreenful = mRecentsPanel.numItemsInOneScreenful();
+            }
+        }
     }
 
     public Bitmap getDefaultThumbnail() {
@@ -113,26 +134,33 @@
         return mDefaultIconBackground;
     }
 
-    // Create an TaskDescription, returning null if the title or icon is null, or if it's the
-    // home activity
+    public ArrayList<TaskDescription> getLoadedTasks() {
+        return mLoadedTasks;
+    }
+
+    public boolean isFirstScreenful() {
+        return mFirstScreenful;
+    }
+
+    private boolean isCurrentHomeActivity(ComponentName component, ActivityInfo homeInfo) {
+        if (homeInfo == null) {
+            final PackageManager pm = mContext.getPackageManager();
+            homeInfo = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME)
+                .resolveActivityInfo(pm, 0);
+        }
+        return homeInfo != null
+            && homeInfo.packageName.equals(component.getPackageName())
+            && homeInfo.name.equals(component.getClassName());
+    }
+
+    // Create an TaskDescription, returning null if the title or icon is null
     TaskDescription createTaskDescription(int taskId, int persistentTaskId, Intent baseIntent,
-            ComponentName origActivity, CharSequence description, ActivityInfo homeInfo) {
+            ComponentName origActivity, CharSequence description) {
         Intent intent = new Intent(baseIntent);
         if (origActivity != null) {
             intent.setComponent(origActivity);
         }
         final PackageManager pm = mContext.getPackageManager();
-        if (homeInfo == null) {
-            homeInfo = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME)
-            .resolveActivityInfo(pm, 0);
-        }
-        // Don't load the current home activity.
-        if (homeInfo != null
-            && homeInfo.packageName.equals(intent.getComponent().getPackageName())
-            && homeInfo.name.equals(intent.getComponent().getClassName())) {
-            return null;
-        }
-
         intent.setFlags((intent.getFlags()&~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
                 | Intent.FLAG_ACTIVITY_NEW_TASK);
         final ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
@@ -161,14 +189,14 @@
         final ActivityManager am = (ActivityManager)
                 mContext.getSystemService(Context.ACTIVITY_SERVICE);
         final PackageManager pm = mContext.getPackageManager();
-        ActivityManager.TaskThumbnails thumbs = am.getTaskThumbnails(td.persistentTaskId);
+        Bitmap thumbnail = am.getTaskTopThumbnail(td.persistentTaskId);
         Drawable icon = getFullResIcon(td.resolveInfo, pm);
 
         if (DEBUG) Log.v(TAG, "Loaded bitmap for task "
-                + td + ": " + thumbs.mainThumbnail);
+                + td + ": " + thumbnail);
         synchronized (td) {
-            if (thumbs != null && thumbs.mainThumbnail != null) {
-                td.setThumbnail(thumbs.mainThumbnail);
+            if (thumbnail != null) {
+                td.setThumbnail(thumbnail);
             } else {
                 td.setThumbnail(mDefaultThumbnailBackground);
             }
@@ -209,7 +237,51 @@
         return getFullResDefaultActivityIcon();
     }
 
-    public void cancelLoadingThumbnailsAndIcons() {
+    Runnable mPreloadTasksRunnable = new Runnable() {
+            public void run() {
+                loadTasksInBackground();
+            }
+        };
+
+    // additional optimization when we have software system buttons - start loading the recent
+    // tasks on touch down
+    @Override
+    public boolean onTouch(View v, MotionEvent ev) {
+        int action = ev.getAction() & MotionEvent.ACTION_MASK;
+        if (action == MotionEvent.ACTION_DOWN) {
+            preloadRecentTasksList();
+        } else if (action == MotionEvent.ACTION_CANCEL) {
+            cancelPreloadingRecentTasksList();
+        } else if (action == MotionEvent.ACTION_UP) {
+            // Remove the preloader if we haven't called it yet
+            mHandler.removeCallbacks(mPreloadTasksRunnable);
+            if (!v.isPressed()) {
+                cancelLoadingThumbnailsAndIcons();
+            }
+
+        }
+        return false;
+    }
+
+    public void preloadRecentTasksList() {
+        mHandler.post(mPreloadTasksRunnable);
+    }
+
+    public void cancelPreloadingRecentTasksList() {
+        cancelLoadingThumbnailsAndIcons();
+        mHandler.removeCallbacks(mPreloadTasksRunnable);
+    }
+
+    public void cancelLoadingThumbnailsAndIcons(RecentsPanelView caller) {
+        // Only oblige this request if it comes from the current RecentsPanel
+        // (eg when you rotate, the old RecentsPanel request should be ignored)
+        if (mRecentsPanel == caller) {
+            cancelLoadingThumbnailsAndIcons();
+        }
+    }
+
+
+    private void cancelLoadingThumbnailsAndIcons() {
         if (mTaskLoader != null) {
             mTaskLoader.cancel(false);
             mTaskLoader = null;
@@ -218,15 +290,122 @@
             mThumbnailLoader.cancel(false);
             mThumbnailLoader = null;
         }
+        mLoadedTasks = null;
+        if (mRecentsPanel != null) {
+            mRecentsPanel.onTaskLoadingCancelled();
+        }
+        mFirstScreenful = false;
+        mState = State.CANCELLED;
+    }
+
+    private void clearFirstTask() {
+        synchronized (mFirstTaskLock) {
+            mFirstTask = null;
+            mFirstTaskLoaded = false;
+        }
+    }
+
+    public void preloadFirstTask() {
+        Thread bgLoad = new Thread() {
+            public void run() {
+                TaskDescription first = loadFirstTask();
+                synchronized(mFirstTaskLock) {
+                    if (mCancelPreloadingFirstTask) {
+                        clearFirstTask();
+                    } else {
+                        mFirstTask = first;
+                        mFirstTaskLoaded = true;
+                    }
+                    mPreloadingFirstTask = false;
+                }
+            }
+        };
+        synchronized(mFirstTaskLock) {
+            if (!mPreloadingFirstTask) {
+                clearFirstTask();
+                mPreloadingFirstTask = true;
+                bgLoad.start();
+            }
+        }
+    }
+
+    public void cancelPreloadingFirstTask() {
+        synchronized(mFirstTaskLock) {
+            if (mPreloadingFirstTask) {
+                mCancelPreloadingFirstTask = true;
+            } else {
+                clearFirstTask();
+            }
+        }
+    }
+
+    boolean mPreloadingFirstTask;
+    boolean mCancelPreloadingFirstTask;
+    public TaskDescription getFirstTask() {
+        while(true) {
+            synchronized(mFirstTaskLock) {
+                if (mFirstTaskLoaded) {
+                    return mFirstTask;
+                } else if (!mFirstTaskLoaded && !mPreloadingFirstTask) {
+                    mFirstTask = loadFirstTask();
+                    mFirstTaskLoaded = true;
+                    return mFirstTask;
+                }
+            }
+            try {
+                Thread.sleep(3);
+            } catch (InterruptedException e) {
+            }
+        }
+    }
+
+    public TaskDescription loadFirstTask() {
+        final ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+
+        final List<ActivityManager.RecentTaskInfo> recentTasks = am.getRecentTasksForUser(
+                1, ActivityManager.RECENT_IGNORE_UNAVAILABLE, UserHandle.CURRENT.getIdentifier());
+        TaskDescription item = null;
+        if (recentTasks.size() > 0) {
+            ActivityManager.RecentTaskInfo recentInfo = recentTasks.get(0);
+
+            Intent intent = new Intent(recentInfo.baseIntent);
+            if (recentInfo.origActivity != null) {
+                intent.setComponent(recentInfo.origActivity);
+            }
+
+            // Don't load the current home activity.
+            if (isCurrentHomeActivity(intent.getComponent(), null)) {
+                return null;
+            }
+
+            // Don't load ourselves
+            if (intent.getComponent().getPackageName().equals(mContext.getPackageName())) {
+                return null;
+            }
+
+            item = createTaskDescription(recentInfo.id,
+                    recentInfo.persistentId, recentInfo.baseIntent,
+                    recentInfo.origActivity, recentInfo.description);
+            if (item != null) {
+                loadThumbnailAndIcon(item);
+            }
+            return item;
+        }
+        return null;
     }
 
     public void loadTasksInBackground() {
-        // cancel all previous loading of tasks and thumbnails
-        cancelLoadingThumbnailsAndIcons();
+        loadTasksInBackground(false);
+    }
+    public void loadTasksInBackground(final boolean zeroeth) {
+        if (mState != State.CANCELLED) {
+            return;
+        }
+        mState = State.LOADING;
+        mFirstScreenful = true;
+
         final LinkedBlockingQueue<TaskDescription> tasksWaitingForThumbnails =
                 new LinkedBlockingQueue<TaskDescription>();
-        final ArrayList<TaskDescription> taskDescriptionsWaitingToLoad =
-                new ArrayList<TaskDescription>();
         mTaskLoader = new AsyncTask<Void, ArrayList<TaskDescription>, Void>() {
             @Override
             protected void onProgressUpdate(ArrayList<TaskDescription>... values) {
@@ -234,7 +413,14 @@
                     ArrayList<TaskDescription> newTasks = values[0];
                     // do a callback to RecentsPanelView to let it know we have more values
                     // how do we let it know we're all done? just always call back twice
-                    mRecentsPanel.onTasksLoaded(newTasks);
+                    if (mRecentsPanel != null) {
+                        mRecentsPanel.onTasksLoaded(newTasks, mFirstScreenful);
+                    }
+                    if (mLoadedTasks == null) {
+                        mLoadedTasks = new ArrayList<TaskDescription>();
+                    }
+                    mLoadedTasks.addAll(newTasks);
+                    mFirstScreenful = false;
                 }
             }
             @Override
@@ -257,15 +443,31 @@
                 ArrayList<TaskDescription> tasks = new ArrayList<TaskDescription>();
 
                 // skip the first task - assume it's either the home screen or the current activity.
-                final int first = 1;
+                final int first = 0;
                 for (int i = first, index = 0; i < numTasks && (index < MAX_TASKS); ++i) {
                     if (isCancelled()) {
                         break;
                     }
                     final ActivityManager.RecentTaskInfo recentInfo = recentTasks.get(i);
+
+                    Intent intent = new Intent(recentInfo.baseIntent);
+                    if (recentInfo.origActivity != null) {
+                        intent.setComponent(recentInfo.origActivity);
+                    }
+
+                    // Don't load the current home activity.
+                    if (isCurrentHomeActivity(intent.getComponent(), homeInfo)) {
+                        continue;
+                    }
+
+                    // Don't load ourselves
+                    if (intent.getComponent().getPackageName().equals(mContext.getPackageName())) {
+                        continue;
+                    }
+
                     TaskDescription item = createTaskDescription(recentInfo.id,
                             recentInfo.persistentId, recentInfo.baseIntent,
-                            recentInfo.origActivity, recentInfo.description, homeInfo);
+                            recentInfo.origActivity, recentInfo.description);
 
                     if (item != null) {
                         while (true) {
@@ -320,7 +522,13 @@
             protected void onProgressUpdate(TaskDescription... values) {
                 if (!isCancelled()) {
                     TaskDescription td = values[0];
-                    mRecentsPanel.onTaskThumbnailLoaded(td);
+                    if (td.isNull()) { // end sentinel
+                        mState = State.LOADED;
+                    } else {
+                        if (mRecentsPanel != null) {
+                            mRecentsPanel.onTaskThumbnailLoaded(td);
+                        }
+                    }
                 }
             }
             @Override
@@ -339,13 +547,13 @@
                         } catch (InterruptedException e) {
                         }
                     }
-                    if (td.isNull()) {
+                    if (td.isNull()) { // end sentinel
+                        publishProgress(td);
                         break;
                     }
                     loadThumbnailAndIcon(td);
-                    synchronized(td) {
-                        publishProgress(td);
-                    }
+
+                    publishProgress(td);
                 }
 
                 Process.setThreadPriority(origPri);
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
new file mode 100644
index 0000000..676326a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recent;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.WallpaperManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.tablet.StatusBarPanel;
+
+import java.util.List;
+
+public class RecentsActivity extends Activity {
+    public static final String TOGGLE_RECENTS_INTENT = "com.android.systemui.recent.action.TOGGLE_RECENTS";
+    public static final String PRELOAD_INTENT = "com.android.systemui.recent.action.PRELOAD";
+    public static final String CANCEL_PRELOAD_INTENT = "com.android.systemui.recent.CANCEL_PRELOAD";
+    public static final String CLOSE_RECENTS_INTENT = "com.android.systemui.recent.action.CLOSE";
+    public static final String WINDOW_ANIMATION_START_INTENT = "com.android.systemui.recent.action.WINDOW_ANIMATION_START";
+    public static final String PRELOAD_PERMISSION = "com.android.systemui.recent.permission.PRELOAD";
+    public static final String WAITING_FOR_WINDOW_ANIMATION_PARAM = "com.android.systemui.recent.WAITING_FOR_WINDOW_ANIMATION";
+    private static final String WAS_SHOWING = "was_showing";
+
+    private RecentsPanelView mRecentsPanel;
+    private IntentFilter mIntentFilter;
+    private boolean mShowing;
+    private boolean mForeground;
+
+    private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (CLOSE_RECENTS_INTENT.equals(intent.getAction())) {
+                if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
+                    if (mShowing && !mForeground) {
+                        // Captures the case right before we transition to another activity
+                        mRecentsPanel.show(false);
+                    }
+                }
+            } else if (WINDOW_ANIMATION_START_INTENT.equals(intent.getAction())) {
+                if (mRecentsPanel != null) {
+                    mRecentsPanel.onWindowAnimationStart();
+                }
+            }
+        }
+    };
+
+    public class TouchOutsideListener implements View.OnTouchListener {
+        private StatusBarPanel mPanel;
+
+        public TouchOutsideListener(StatusBarPanel panel) {
+            mPanel = panel;
+        }
+
+        public boolean onTouch(View v, MotionEvent ev) {
+            final int action = ev.getAction();
+            if (action == MotionEvent.ACTION_OUTSIDE
+                    || (action == MotionEvent.ACTION_DOWN
+                    && !mPanel.isInContentArea((int) ev.getX(), (int) ev.getY()))) {
+                dismissAndGoHome();
+                return true;
+            }
+            return false;
+        }
+    }
+
+    @Override
+    public void onPause() {
+        overridePendingTransition(
+                R.anim.recents_return_to_launcher_enter,
+                R.anim.recents_return_to_launcher_exit);
+        mForeground = false;
+        super.onPause();
+    }
+
+    @Override
+    public void onStop() {
+        mShowing = false;
+        if (mRecentsPanel != null) {
+            mRecentsPanel.onUiHidden();
+        }
+        super.onStop();
+    }
+
+    private void updateWallpaperVisibility(boolean visible) {
+        int wpflags = visible ? WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER : 0;
+        int curflags = getWindow().getAttributes().flags
+                & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+        if (wpflags != curflags) {
+            getWindow().setFlags(wpflags, WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER);
+        }
+    }
+
+    public static boolean forceOpaqueBackground(Context context) {
+        return WallpaperManager.getInstance(context).getWallpaperInfo() != null;
+    }
+
+    @Override
+    public void onStart() {
+        // Hide wallpaper if it's not a static image
+        if (forceOpaqueBackground(this)) {
+            updateWallpaperVisibility(false);
+        } else {
+            updateWallpaperVisibility(true);
+        }
+        mShowing = true;
+        if (mRecentsPanel != null) {
+            mRecentsPanel.refreshViews();
+        }
+        super.onStart();
+    }
+
+    @Override
+    public void onResume() {
+        mForeground = true;
+        super.onResume();
+    }
+
+    @Override
+    public void onBackPressed() {
+        dismissAndGoBack();
+    }
+
+    public void dismissAndGoHome() {
+        if (mRecentsPanel != null) {
+            Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
+            homeIntent.addCategory(Intent.CATEGORY_HOME);
+            homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+            startActivityAsUser(homeIntent, new UserHandle(UserHandle.USER_CURRENT));
+            mRecentsPanel.show(false);
+        }
+    }
+
+    public void dismissAndGoBack() {
+        if (mRecentsPanel != null) {
+            final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+
+            final List<ActivityManager.RecentTaskInfo> recentTasks =
+                    am.getRecentTasks(2,
+                            ActivityManager.RECENT_WITH_EXCLUDED |
+                            ActivityManager.RECENT_IGNORE_UNAVAILABLE);
+            if (recentTasks.size() > 1 &&
+                    mRecentsPanel.simulateClick(recentTasks.get(1).persistentId)) {
+                // recents panel will take care of calling show(false) through simulateClick
+                return;
+            }
+            mRecentsPanel.show(false);
+        }
+        finish();
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        setContentView(R.layout.status_bar_recent_panel);
+        mRecentsPanel = (RecentsPanelView) findViewById(R.id.recents_root);
+        mRecentsPanel.setOnTouchListener(new TouchOutsideListener(mRecentsPanel));
+
+        final RecentTasksLoader recentTasksLoader = RecentTasksLoader.getInstance(this);
+        recentTasksLoader.setRecentsPanel(mRecentsPanel, mRecentsPanel);
+        mRecentsPanel.setMinSwipeAlpha(
+                getResources().getInteger(R.integer.config_recent_item_min_alpha) / 100f);
+
+        if (savedInstanceState == null ||
+                savedInstanceState.getBoolean(WAS_SHOWING)) {
+            handleIntent(getIntent(), (savedInstanceState == null));
+        }
+        mIntentFilter = new IntentFilter();
+        mIntentFilter.addAction(CLOSE_RECENTS_INTENT);
+        mIntentFilter.addAction(WINDOW_ANIMATION_START_INTENT);
+        registerReceiver(mIntentReceiver, mIntentFilter);
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        outState.putBoolean(WAS_SHOWING, mRecentsPanel.isShowing());
+    }
+
+    @Override
+    protected void onDestroy() {
+        RecentTasksLoader.getInstance(this).setRecentsPanel(null, mRecentsPanel);
+        unregisterReceiver(mIntentReceiver);
+        super.onDestroy();
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        handleIntent(intent, true);
+    }
+
+    private void handleIntent(Intent intent, boolean checkWaitingForAnimationParam) {
+        super.onNewIntent(intent);
+
+        if (TOGGLE_RECENTS_INTENT.equals(intent.getAction())) {
+            if (mRecentsPanel != null) {
+                if (mRecentsPanel.isShowing()) {
+                    dismissAndGoBack();
+                } else {
+                    final RecentTasksLoader recentTasksLoader = RecentTasksLoader.getInstance(this);
+                    boolean waitingForWindowAnimation = checkWaitingForAnimationParam &&
+                            intent.getBooleanExtra(WAITING_FOR_WINDOW_ANIMATION_PARAM, false);
+                    mRecentsPanel.show(true, recentTasksLoader.getLoadedTasks(),
+                            recentTasksLoader.isFirstScreenful(), waitingForWindowAnimation);
+                }
+            }
+        }
+    }
+
+    boolean isForeground() {
+        return mForeground;
+    }
+
+    boolean isActivityShowing() {
+         return mShowing;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
index f85007e..6cb7dec 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
@@ -27,10 +27,6 @@
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.View.MeasureSpec;
-import android.view.View.OnClickListener;
-import android.view.View.OnLongClickListener;
-import android.view.View.OnTouchListener;
 import android.view.ViewConfiguration;
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
@@ -80,6 +76,17 @@
         }
     }
 
+    public View findViewForTask(int persistentTaskId) {
+        for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
+            View v = mLinearLayout.getChildAt(i);
+            RecentsPanelView.ViewHolder holder = (RecentsPanelView.ViewHolder) v.getTag();
+            if (holder.taskDescription.persistentTaskId == persistentTaskId) {
+                return v;
+            }
+        }
+        return null;
+    }
+
     private void update() {
         for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
             View v = mLinearLayout.getChildAt(i);
@@ -149,19 +156,19 @@
         }
         setLayoutTransition(transitioner);
 
-        // Scroll to end after layout.
-        final ViewTreeObserver observer = getViewTreeObserver();
+        // Scroll to end after initial layout.
 
         final OnGlobalLayoutListener updateScroll = new OnGlobalLayoutListener() {
                 public void onGlobalLayout() {
                     mLastScrollPosition = scrollPositionOfMostRecent();
                     scrollTo(mLastScrollPosition, 0);
+                    final ViewTreeObserver observer = getViewTreeObserver();
                     if (observer.isAlive()) {
                         observer.removeOnGlobalLayoutListener(this);
                     }
                 }
             };
-        observer.addOnGlobalLayoutListener(updateScroll);
+        getViewTreeObserver().addOnGlobalLayoutListener(updateScroll);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 0bdf84a..cd3bc42 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -18,9 +18,11 @@
 
 import android.animation.Animator;
 import android.animation.LayoutTransition;
+import android.animation.TimeInterpolator;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.ActivityOptions;
+import android.app.TaskStackBuilder;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -28,27 +30,24 @@
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Matrix;
-import android.graphics.Rect;
 import android.graphics.Shader.TileMode;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.RemoteException;
-import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.view.Display;
-import android.view.KeyEvent;
-import android.view.IWindowManager;
 import android.view.LayoutInflater;
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.BaseAdapter;
@@ -60,7 +59,6 @@
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.BaseStatusBar;
-import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.tablet.StatusBarPanel;
 import com.android.systemui.statusbar.tablet.TabletStatusBar;
@@ -68,11 +66,9 @@
 import java.util.ArrayList;
 
 public class RecentsPanelView extends FrameLayout implements OnItemClickListener, RecentsCallback,
-        StatusBarPanel, Animator.AnimatorListener, View.OnTouchListener {
+        StatusBarPanel, Animator.AnimatorListener {
     static final String TAG = "RecentsPanelView";
     static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
-    private Context mContext;
-    private BaseStatusBar mBar;
     private PopupMenu mPopup;
     private View mRecentsScrim;
     private View mRecentsNoApps;
@@ -81,36 +77,24 @@
 
     private boolean mShowing;
     private boolean mWaitingToShow;
-    private boolean mWaitingToShowAnimated;
-    private boolean mReadyToShow;
     private int mNumItemsWaitingForThumbnailsAndIcons;
-    private Choreographer mChoreo;
-    OnRecentsPanelVisibilityChangedListener mVisibilityChangedListener;
-
-    ImageView mPlaceholderThumbnail;
-    View mTransitionBg;
-    boolean mHideRecentsAfterThumbnailScaleUpStarted;
+    private ViewHolder mItemToAnimateInWhenWindowAnimationIsFinished;
+    private boolean mWaitingForWindowAnimation;
 
     private RecentTasksLoader mRecentTasksLoader;
     private ArrayList<TaskDescription> mRecentTaskDescriptions;
-    private Runnable mPreloadTasksRunnable;
-    private boolean mRecentTasksDirty = true;
     private TaskDescriptionAdapter mListAdapter;
     private int mThumbnailWidth;
     private boolean mFitThumbnailToXY;
     private int mRecentItemLayoutId;
-    private boolean mFirstScreenful = true;
     private boolean mHighEndGfx;
 
-    public static interface OnRecentsPanelVisibilityChangedListener {
-        public void onRecentsPanelVisibilityChanged(boolean visible);
-    }
-
     public static interface RecentsScrollView {
         public int numItemsInOneScreenful();
         public void setAdapter(TaskDescriptionAdapter adapter);
         public void setCallback(RecentsCallback callback);
         public void setMinSwipeAlpha(float minAlpha);
+        public View findViewForTask(int persistentTaskId);
     }
 
     private final class OnLongClickDelegate implements View.OnLongClickListener {
@@ -130,6 +114,7 @@
         ImageView iconView;
         TextView labelView;
         TextView descriptionView;
+        View calloutLine;
         TaskDescription taskDescription;
         boolean loadedThumbnailAndIcon;
     }
@@ -161,14 +146,11 @@
                     (ImageView) convertView.findViewById(R.id.app_thumbnail_image);
             // If we set the default thumbnail now, we avoid an onLayout when we update
             // the thumbnail later (if they both have the same dimensions)
-            if (mRecentTasksLoader != null) {
-                updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false);
-            }
+            updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false);
             holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon);
-            if (mRecentTasksLoader != null) {
-                holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon());
-            }
+            holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon());
             holder.labelView = (TextView) convertView.findViewById(R.id.app_label);
+            holder.calloutLine = convertView.findViewById(R.id.recents_callout_line);
             holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description);
 
             convertView.setTag(holder);
@@ -178,13 +160,6 @@
         public View getView(int position, View convertView, ViewGroup parent) {
             if (convertView == null) {
                 convertView = createView(parent);
-                if (convertView.getParent() != null) {
-                    throw new RuntimeException("Recycled child has parent");
-                }
-            } else {
-                if (convertView.getParent() != null) {
-                    throw new RuntimeException("Recycled child has parent");
-                }
             }
             ViewHolder holder = (ViewHolder) convertView.getTag();
 
@@ -201,6 +176,38 @@
                 updateIcon(holder, td.getIcon(), true, false);
                 mNumItemsWaitingForThumbnailsAndIcons--;
             }
+            if (index == 0) {
+                if (mWaitingForWindowAnimation) {
+                    if (mItemToAnimateInWhenWindowAnimationIsFinished != null) {
+                        holder.iconView.setAlpha(1f);
+                        holder.iconView.setTranslationX(0f);
+                        holder.iconView.setTranslationY(0f);
+                        holder.labelView.setAlpha(1f);
+                        holder.labelView.setTranslationX(0f);
+                        holder.labelView.setTranslationY(0f);
+                        if (holder.calloutLine != null) {
+                            holder.calloutLine.setAlpha(1f);
+                            holder.calloutLine.setTranslationX(0f);
+                            holder.calloutLine.setTranslationY(0f);
+                        }
+                    }
+                    mItemToAnimateInWhenWindowAnimationIsFinished = holder;
+                    final int translation = -getResources().getDimensionPixelSize(
+                            R.dimen.status_bar_recents_app_icon_translate_distance);
+                    final Configuration config = getResources().getConfiguration();
+                    if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
+                        holder.iconView.setAlpha(0f);
+                        holder.iconView.setTranslationX(translation);
+                        holder.labelView.setAlpha(0f);
+                        holder.labelView.setTranslationX(translation);
+                        holder.calloutLine.setAlpha(0f);
+                        holder.calloutLine.setTranslationX(translation);
+                    } else {
+                        holder.iconView.setAlpha(0f);
+                        holder.iconView.setTranslationY(translation);
+                    }
+                }
+            }
 
             holder.thumbnailView.setTag(td);
             holder.thumbnailView.setOnLongClickListener(new OnLongClickDelegate(convertView));
@@ -218,6 +225,17 @@
             holder.thumbnailView.setTag(null);
             holder.thumbnailView.setOnLongClickListener(null);
             holder.thumbnailView.setVisibility(INVISIBLE);
+            holder.iconView.setAlpha(1f);
+            holder.iconView.setTranslationX(0f);
+            holder.iconView.setTranslationY(0f);
+            holder.labelView.setAlpha(1f);
+            holder.labelView.setTranslationX(0f);
+            holder.labelView.setTranslationY(0f);
+            if (holder.calloutLine != null) {
+                holder.calloutLine.setAlpha(1f);
+                holder.calloutLine.setTranslationX(0f);
+                holder.calloutLine.setTranslationY(0f);
+            }
             holder.taskDescription = null;
             holder.loadedThumbnailAndIcon = false;
         }
@@ -229,13 +247,13 @@
 
     public RecentsPanelView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
-        mContext = context;
         updateValuesFromResources();
 
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RecentsPanelView,
                 defStyle, 0);
 
         mRecentItemLayoutId = a.getResourceId(R.styleable.RecentsPanelView_recentItemLayout, 0);
+        mRecentTasksLoader = RecentTasksLoader.getInstance(context);
         a.recycle();
     }
 
@@ -249,15 +267,6 @@
         }
     }
 
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_BACK && !event.isCanceled()) {
-            show(false, false);
-            return true;
-        }
-        return super.onKeyUp(keyCode, event);
-    }
-
     private boolean pointInside(int x, int y, View v) {
         final int l = v.getLeft();
         final int r = v.getRight();
@@ -277,22 +286,27 @@
         }
     }
 
-    public void show(boolean show, boolean animate) {
+    public void show(boolean show) {
+        show(show, null, false, false);
+    }
+
+    public void show(boolean show, ArrayList<TaskDescription> recentTaskDescriptions,
+            boolean firstScreenful, boolean waitingForWindowAnimation) {
+        mWaitingForWindowAnimation = waitingForWindowAnimation;
         if (show) {
-            refreshRecentTasksList(null, true);
             mWaitingToShow = true;
-            mWaitingToShowAnimated = animate;
+            refreshRecentTasksList(recentTaskDescriptions, firstScreenful);
             showIfReady();
         } else {
-            show(show, animate, null, false);
+            showImpl(false);
         }
     }
 
     private void showIfReady() {
-        // mWaitingToShow = there was a touch up on the recents button
-        // mReadyToShow = we've created views for the first screenful of items
-        if (mWaitingToShow && mReadyToShow) { // && mNumItemsWaitingForThumbnailsAndIcons <= 0
-            show(true, mWaitingToShowAnimated, null, false);
+        // mWaitingToShow => there was a touch up on the recents button
+        // mRecentTaskDescriptions != null => we've created views for the first screenful of items
+        if (mWaitingToShow && mRecentTaskDescriptions != null) {
+            showImpl(true);
         }
     }
 
@@ -305,79 +319,44 @@
         }
     }
 
-    public void show(boolean show, boolean animate,
-            ArrayList<TaskDescription> recentTaskDescriptions, boolean firstScreenful) {
+    private void showImpl(boolean show) {
         sendCloseSystemWindows(mContext, BaseStatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS);
 
+        mShowing = show;
+
         if (show) {
-            // Need to update list of recent apps before we set visibility so this view's
-            // content description is updated before it gets focus for TalkBack mode
-            refreshRecentTasksList(recentTaskDescriptions, firstScreenful);
+            // if there are no apps, bring up a "No recent apps" message
+            boolean noApps = mRecentTaskDescriptions != null
+                    && (mRecentTaskDescriptions.size() == 0);
+            mRecentsNoApps.setAlpha(1f);
+            mRecentsNoApps.setVisibility(noApps ? View.VISIBLE : View.INVISIBLE);
 
-            // if there are no apps, either bring up a "No recent apps" message, or just
-            // quit early
-            boolean noApps = !mFirstScreenful && (mRecentTaskDescriptions.size() == 0);
-            if (mRecentsNoApps != null) {
-                mRecentsNoApps.setAlpha(1f);
-                mRecentsNoApps.setVisibility(noApps ? View.VISIBLE : View.INVISIBLE);
-            } else {
-                if (noApps) {
-                   if (DEBUG) Log.v(TAG, "Nothing to show");
-                    // Need to set recent tasks to dirty so that next time we load, we
-                    // refresh the list of tasks
-                    mRecentTasksLoader.cancelLoadingThumbnailsAndIcons();
-                    mRecentTasksDirty = true;
-
-                    mWaitingToShow = false;
-                    mReadyToShow = false;
-                    return;
-                }
-            }
-        } else {
-            // Need to set recent tasks to dirty so that next time we load, we
-            // refresh the list of tasks
-            mRecentTasksLoader.cancelLoadingThumbnailsAndIcons();
-            mRecentTasksDirty = true;
-            mWaitingToShow = false;
-            mReadyToShow = false;
-        }
-        if (animate) {
-            if (mShowing != show) {
-                mShowing = show;
-                if (show) {
-                    setVisibility(View.VISIBLE);
-                }
-                mChoreo.startAnimation(show);
-            }
-        } else {
-            mShowing = show;
-            setVisibility(show ? View.VISIBLE : View.GONE);
-            mChoreo.jumpTo(show);
             onAnimationEnd(null);
-        }
-        if (show) {
             setFocusable(true);
             setFocusableInTouchMode(true);
             requestFocus();
         } else {
+            mWaitingToShow = false;
+            // call onAnimationEnd() and clearRecentTasksList() in onUiHidden()
             if (mPopup != null) {
                 mPopup.dismiss();
             }
         }
     }
 
-    public void dismiss() {
-        hide(true);
+    public void onUiHidden() {
+        if (!mShowing && mRecentTaskDescriptions != null) {
+            onAnimationEnd(null);
+            clearRecentTasksList();
+        }
     }
 
-    public void hide(boolean animate) {
-        if (!animate) {
-            setVisibility(View.GONE);
-        }
-        if (mBar != null) {
-            // This will indirectly cause show(false, ...) to get called
-            mBar.animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
-        }
+    public void dismiss() {
+        ((RecentsActivity) mContext).dismissAndGoHome();
+    }
+
+    public void dismissAndGoBack() {
+        ((RecentsActivity) mContext).dismissAndGoBack();
     }
 
     public void onAnimationCancel(Animator animation) {
@@ -390,7 +369,6 @@
             createCustomAnimations(transitioner);
         } else {
             ((ViewGroup)mRecentsContainer).setLayoutTransition(null);
-            clearRecentTasksList();
         }
     }
 
@@ -400,16 +378,6 @@
     public void onAnimationStart(Animator animation) {
     }
 
-    /**
-     * We need to be aligned at the bottom.  LinearLayout can't do this, so instead,
-     * let LinearLayout do all the hard work, and then shift everything down to the bottom.
-     */
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        super.onLayout(changed, l, t, r, b);
-        mChoreo.setPanelHeight(mRecentsContainer.getHeight());
-    }
-
     @Override
     public boolean dispatchHoverEvent(MotionEvent event) {
         // Ignore hover events outside of this panel bounds since such events
@@ -431,11 +399,6 @@
         return mShowing;
     }
 
-    public void setBar(BaseStatusBar bar) {
-        mBar = bar;
-
-    }
-
     public void setStatusBarView(View statusBarView) {
         if (mStatusBarTouchProxy != null) {
             mStatusBarTouchProxy.setStatusBar(statusBarView);
@@ -446,18 +409,6 @@
         mRecentTasksLoader = loader;
     }
 
-    public void setOnVisibilityChangedListener(OnRecentsPanelVisibilityChangedListener l) {
-        mVisibilityChangedListener = l;
-
-    }
-
-    public void setVisibility(int visibility) {
-        if (mVisibilityChangedListener != null) {
-            mVisibilityChangedListener.onRecentsPanelVisibilityChanged(visibility == VISIBLE);
-        }
-        super.setVisibility(visibility);
-    }
-
     public void updateValuesFromResources() {
         final Resources res = mContext.getResources();
         mThumbnailWidth = Math.round(res.getDimension(R.dimen.status_bar_recents_thumbnail_width));
@@ -468,7 +419,6 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         mRecentsContainer = (ViewGroup) findViewById(R.id.recents_container);
         mStatusBarTouchProxy = (StatusBarTouchProxy) findViewById(R.id.status_bar_touch_proxy);
         mListAdapter = new TaskDescriptionAdapter(mContext);
@@ -483,12 +433,9 @@
 
         mRecentsScrim = findViewById(R.id.recents_bg_protect);
         mRecentsNoApps = findViewById(R.id.recents_no_apps);
-        mChoreo = new Choreographer(this, mRecentsScrim, mRecentsContainer, mRecentsNoApps, this);
 
         if (mRecentsScrim != null) {
-            Display d = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
-                .getDefaultDisplay();
-            mHighEndGfx = ActivityManager.isHighEndGfx(d);
+            mHighEndGfx = ActivityManager.isHighEndGfx();
             if (!mHighEndGfx) {
                 mRecentsScrim.setBackground(null);
             } else if (mRecentsScrim.getBackground() instanceof BitmapDrawable) {
@@ -496,18 +443,6 @@
                 ((BitmapDrawable) mRecentsScrim.getBackground()).setTileModeY(TileMode.REPEAT);
             }
         }
-
-        mPreloadTasksRunnable = new Runnable() {
-            public void run() {
-                // If we set our visibility to INVISIBLE here, we avoid an extra call to
-                // onLayout later when we become visible (because onLayout is always called
-                // when going from GONE)
-                if (!mShowing) {
-                    setVisibility(INVISIBLE);
-                    refreshRecentTasksList();
-                }
-            }
-        };
     }
 
     public void setMinSwipeAlpha(float minAlpha) {
@@ -597,103 +532,86 @@
                     }
                 }
             }
-            }
+        }
         showIfReady();
     }
 
-    // additional optimization when we have software system buttons - start loading the recent
-    // tasks on touch down
-    @Override
-    public boolean onTouch(View v, MotionEvent ev) {
-        if (!mShowing) {
-            int action = ev.getAction() & MotionEvent.ACTION_MASK;
-            if (action == MotionEvent.ACTION_DOWN) {
-                post(mPreloadTasksRunnable);
-            } else if (action == MotionEvent.ACTION_CANCEL) {
-                setVisibility(GONE);
-                clearRecentTasksList();
-                // Remove the preloader if we haven't called it yet
-                removeCallbacks(mPreloadTasksRunnable);
-            } else if (action == MotionEvent.ACTION_UP) {
-                // Remove the preloader if we haven't called it yet
-                removeCallbacks(mPreloadTasksRunnable);
-                if (!v.isPressed()) {
-                    setVisibility(GONE);
-                    clearRecentTasksList();
+    public void onWindowAnimationStart() {
+        if (mItemToAnimateInWhenWindowAnimationIsFinished != null) {
+            final int startDelay = 150;
+            final int duration = 250;
+            final ViewHolder holder = mItemToAnimateInWhenWindowAnimationIsFinished;
+            final TimeInterpolator cubic = new DecelerateInterpolator(1.5f);
+            for (View v :
+                new View[] { holder.iconView, holder.labelView, holder.calloutLine }) {
+                if (v != null) {
+                    v.animate().translationX(0).translationY(0).alpha(1f).setStartDelay(startDelay)
+                            .setDuration(duration).setInterpolator(cubic);
                 }
             }
-        }
-        return false;
-    }
-
-    public void preloadRecentTasksList() {
-        if (!mShowing) {
-            mPreloadTasksRunnable.run();
+            mItemToAnimateInWhenWindowAnimationIsFinished = null;
+            mWaitingForWindowAnimation = false;
         }
     }
 
     public void clearRecentTasksList() {
         // Clear memory used by screenshots
-        if (!mShowing && mRecentTaskDescriptions != null) {
-            mRecentTasksLoader.cancelLoadingThumbnailsAndIcons();
-            mRecentTaskDescriptions.clear();
-            mListAdapter.notifyDataSetInvalidated();
-            mRecentTasksDirty = true;
+        if (mRecentTaskDescriptions != null) {
+            mRecentTasksLoader.cancelLoadingThumbnailsAndIcons(this);
+            onTaskLoadingCancelled();
         }
     }
 
+    public void onTaskLoadingCancelled() {
+        // Gets called by RecentTasksLoader when it's cancelled
+        if (mRecentTaskDescriptions != null) {
+            mRecentTaskDescriptions = null;
+            mListAdapter.notifyDataSetInvalidated();
+        }
+    }
+
+    public void refreshViews() {
+        mListAdapter.notifyDataSetInvalidated();
+        updateUiElements();
+        showIfReady();
+    }
+
     public void refreshRecentTasksList() {
         refreshRecentTasksList(null, false);
     }
 
     private void refreshRecentTasksList(
             ArrayList<TaskDescription> recentTasksList, boolean firstScreenful) {
-        if (mRecentTasksDirty) {
-            if (recentTasksList != null) {
-                mFirstScreenful = true;
-                onTasksLoaded(recentTasksList);
-            } else {
-                mFirstScreenful = true;
-                mRecentTasksLoader.loadTasksInBackground();
-            }
-            mRecentTasksDirty = false;
+        if (mRecentTaskDescriptions == null && recentTasksList != null) {
+            onTasksLoaded(recentTasksList, firstScreenful);
+        } else {
+            mRecentTasksLoader.loadTasksInBackground();
         }
     }
 
-    public void onTasksLoaded(ArrayList<TaskDescription> tasks) {
-        if (!mFirstScreenful && tasks.size() == 0) {
-            return;
-        }
-        mNumItemsWaitingForThumbnailsAndIcons = mFirstScreenful 
-                ? tasks.size() : mRecentTaskDescriptions == null 
+    public void onTasksLoaded(ArrayList<TaskDescription> tasks, boolean firstScreenful) {
+        mNumItemsWaitingForThumbnailsAndIcons = firstScreenful
+                ? tasks.size() : mRecentTaskDescriptions == null
                         ? 0 : mRecentTaskDescriptions.size();
         if (mRecentTaskDescriptions == null) {
             mRecentTaskDescriptions = new ArrayList<TaskDescription>(tasks);
         } else {
             mRecentTaskDescriptions.addAll(tasks);
         }
-        mListAdapter.notifyDataSetInvalidated();
-        updateUiElements(getResources().getConfiguration());
-        mReadyToShow = true;
-        mFirstScreenful = false;
-        showIfReady();
+        if (((RecentsActivity) mContext).isActivityShowing()) {
+            refreshViews();
+        }
     }
 
-    public ArrayList<TaskDescription> getRecentTasksList() {
-        return mRecentTaskDescriptions;
-    }
-
-    public boolean getFirstScreenful() {
-        return mFirstScreenful;
-    }
-
-    private void updateUiElements(Configuration config) {
-        final int items = mRecentTaskDescriptions.size();
+    private void updateUiElements() {
+        final int items = mRecentTaskDescriptions != null
+                ? mRecentTaskDescriptions.size() : 0;
 
         mRecentsContainer.setVisibility(items > 0 ? View.VISIBLE : View.GONE);
 
         // Set description for accessibility
-        int numRecentApps = mRecentTaskDescriptions.size();
+        int numRecentApps = mRecentTaskDescriptions != null
+                ? mRecentTaskDescriptions.size() : 0;
         String recentAppsAccessibilityDescription;
         if (numRecentApps == 0) {
             recentAppsAccessibilityDescription =
@@ -705,8 +623,19 @@
         setContentDescription(recentAppsAccessibilityDescription);
     }
 
+    public boolean simulateClick(int persistentTaskId) {
+        if (mRecentsContainer instanceof RecentsScrollView){
+            RecentsScrollView scrollView
+                = (RecentsScrollView) mRecentsContainer;
+            View v = scrollView.findViewForTask(persistentTaskId);
+            if (v != null) {
+                handleOnClick(v);
+                return true;
+            }
+        }
+        return false;
+    }
 
-    boolean mThumbnailScaleUpStarted;
     public void handleOnClick(View view) {
         ViewHolder holder = (ViewHolder)view.getTag();
         TaskDescription ad = holder.taskDescription;
@@ -723,89 +652,30 @@
             bm = holder.thumbnailViewImage.getDrawingCache();
             usingDrawingCache = true;
         }
+        Bundle opts = (bm == null) ?
+                null :
+                ActivityOptions.makeThumbnailScaleUpAnimation(
+                        holder.thumbnailViewImage, bm, 0, 0, null).toBundle();
 
-        if (mPlaceholderThumbnail == null) {
-            mPlaceholderThumbnail =
-                    (ImageView) findViewById(R.id.recents_transition_placeholder_icon);
-        }
-        if (mTransitionBg == null) {
-            mTransitionBg = (View) findViewById(R.id.recents_transition_background);
-
-            IWindowManager wm = IWindowManager.Stub.asInterface(
-                    ServiceManager.getService(Context.WINDOW_SERVICE));
-            try {
-                if (!wm.hasSystemNavBar()) {
-                    FrameLayout.LayoutParams lp =
-                            (FrameLayout.LayoutParams) mTransitionBg.getLayoutParams();
-                    int statusBarHeight = getResources().
-                            getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
-                    lp.setMargins(0, statusBarHeight, 0, 0);
-                    mTransitionBg.setLayoutParams(lp);
-                }
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failing checking whether status bar is visible", e);
-            }
-        }
-
-        final ImageView placeholderThumbnail = mPlaceholderThumbnail;
-        mHideRecentsAfterThumbnailScaleUpStarted = false;
-        placeholderThumbnail.setVisibility(VISIBLE);
-        if (!usingDrawingCache) {
-            placeholderThumbnail.setImageBitmap(bm);
-        } else {
-            Bitmap b2 = bm.copy(bm.getConfig(), true);
-            placeholderThumbnail.setImageBitmap(b2);
-        }
-        Rect r = new Rect();
-        holder.thumbnailViewImage.getGlobalVisibleRect(r);
-
-        placeholderThumbnail.setTranslationX(r.left);
-        placeholderThumbnail.setTranslationY(r.top);
-
-        show(false, true);
-
-        mThumbnailScaleUpStarted = false;
-        ActivityOptions opts = ActivityOptions.makeDelayedThumbnailScaleUpAnimation(
-                holder.thumbnailViewImage, bm, 0, 0,
-                new ActivityOptions.OnAnimationStartedListener() {
-                    @Override public void onAnimationStarted() {
-                        mThumbnailScaleUpStarted = true;
-                        if (!mHighEndGfx) {
-                            mPlaceholderThumbnail.setVisibility(INVISIBLE);
-                        }
-                        if (mHideRecentsAfterThumbnailScaleUpStarted) {
-                            hideWindow();
-                        }
-                    }
-                });
+        show(false);
         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,
-                    opts.toBundle());
+                    opts);
         } 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, opts.toBundle());
+            context.startActivityAsUser(intent, opts,
+                    new UserHandle(UserHandle.USER_CURRENT));
         }
         if (usingDrawingCache) {
             holder.thumbnailViewImage.setDrawingCacheEnabled(false);
         }
     }
 
-    public void hideWindow() {
-        if (!mThumbnailScaleUpStarted) {
-            mHideRecentsAfterThumbnailScaleUpStarted = true;
-        } else {
-            setVisibility(GONE);
-            mTransitionBg.setVisibility(INVISIBLE);
-            mPlaceholderThumbnail.setVisibility(INVISIBLE);
-            mHideRecentsAfterThumbnailScaleUpStarted = false;
-        }
-    }
-
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
         handleOnClick(view);
     }
@@ -824,7 +694,7 @@
         // mListAdapter.notifyDataSetChanged();
 
         if (mRecentTaskDescriptions.size() == 0) {
-            hide(false);
+            dismissAndGoBack();
         }
 
         // Currently, either direction means the same thing, so ignore direction and remove
@@ -845,8 +715,9 @@
     private void startApplicationDetailsActivity(String packageName) {
         Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                 Uri.fromParts("package", packageName, null));
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        getContext().startActivity(intent);
+        intent.setComponent(intent.resolveActivity(mContext.getPackageManager()));
+        TaskStackBuilder.create(getContext())
+                .addNextIntentWithParentStack(intent).startActivities();
     }
 
     public boolean onInterceptTouchEvent(MotionEvent ev) {
@@ -873,7 +744,7 @@
                     if (viewHolder != null) {
                         final TaskDescription ad = viewHolder.taskDescription;
                         startApplicationDetailsActivity(ad.packageName);
-                        mBar.animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
+                        show(false);
                     } else {
                         throw new IllegalStateException("Oops, no tag on view " + selectedView);
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPreloadReceiver.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPreloadReceiver.java
new file mode 100644
index 0000000..eb5892007
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPreloadReceiver.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recent;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class RecentsPreloadReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (RecentsActivity.PRELOAD_INTENT.equals(intent.getAction())) {
+            RecentTasksLoader.getInstance(context).preloadRecentTasksList();
+        } else if (RecentsActivity.CANCEL_PRELOAD_INTENT.equals(intent.getAction())){
+            RecentTasksLoader.getInstance(context).cancelPreloadingRecentTasksList();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java
index 9bc54cb..71cc1e4 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.recent;
 
-import android.animation.LayoutTransition;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
@@ -24,11 +23,9 @@
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Shader;
-import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewConfiguration;
-import android.view.ViewGroup;
 import android.widget.LinearLayout;
 
 import com.android.systemui.R;
@@ -37,13 +34,10 @@
     public static final boolean OPTIMIZE_SW_RENDERED_RECENTS = true;
     public static final boolean USE_DARK_FADE_IN_HW_ACCELERATED_MODE = true;
     private View mScrollView;
-    private RecentsCallback mCallback;
 
     private int mFadingEdgeLength;
-    private Context mContext;
     private boolean mIsVertical;
     private boolean mSoftwareRendered = false;
-    private boolean mAttachedToWindow = false;
 
     public static RecentsScrollViewPerformanceHelper create(Context context,
             AttributeSet attrs, View scrollView, boolean isVertical) {
@@ -59,7 +53,6 @@
     public RecentsScrollViewPerformanceHelper(Context context,
             AttributeSet attrs, View scrollView, boolean isVertical) {
         mScrollView = scrollView;
-        mContext = context;
         TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View);
         mFadingEdgeLength = a.getDimensionPixelSize(android.R.styleable.View_fadingEdgeLength,
                 ViewConfiguration.get(context).getScaledFadingEdgeLength());
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
index e802985..47b0113 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -27,10 +27,6 @@
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.View.MeasureSpec;
-import android.view.View.OnClickListener;
-import android.view.View.OnLongClickListener;
-import android.view.View.OnTouchListener;
 import android.view.ViewConfiguration;
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
@@ -81,6 +77,17 @@
         }
     }
 
+    public View findViewForTask(int persistentTaskId) {
+        for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
+            View v = mLinearLayout.getChildAt(i);
+            RecentsPanelView.ViewHolder holder = (RecentsPanelView.ViewHolder) v.getTag();
+            if (holder.taskDescription.persistentTaskId == persistentTaskId) {
+                return v;
+            }
+        }
+        return null;
+    }
+
     private void update() {
         for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
             View v = mLinearLayout.getChildAt(i);
@@ -150,25 +157,26 @@
             appTitle.setContentDescription(" ");
             appTitle.setOnTouchListener(noOpListener);
             final View calloutLine = view.findViewById(R.id.recents_callout_line);
-            calloutLine.setOnTouchListener(noOpListener);
+            if (calloutLine != null) {
+                calloutLine.setOnTouchListener(noOpListener);
+            }
 
             mLinearLayout.addView(view);
         }
         setLayoutTransition(transitioner);
 
-        // Scroll to end after layout.
-        final ViewTreeObserver observer = getViewTreeObserver();
-
+        // Scroll to end after initial layout.
         final OnGlobalLayoutListener updateScroll = new OnGlobalLayoutListener() {
                 public void onGlobalLayout() {
                     mLastScrollPosition = scrollPositionOfMostRecent();
                     scrollTo(0, mLastScrollPosition);
+                    final ViewTreeObserver observer = getViewTreeObserver();
                     if (observer.isAlive()) {
                         observer.removeOnGlobalLayoutListener(this);
                     }
                 }
             };
-        observer.addOnGlobalLayoutListener(updateScroll);
+        getViewTreeObserver().addOnGlobalLayoutListener(updateScroll);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 9448bbf..f25ac0d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -38,7 +38,6 @@
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.PointF;
-import android.graphics.RectF;
 import android.media.MediaActionSound;
 import android.net.Uri;
 import android.os.AsyncTask;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 8d7734e0..fe33b02 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (C) 2010 The Android Open Source Project
  *
@@ -16,17 +17,38 @@
 
 package com.android.systemui.statusbar;
 
-import java.util.ArrayList;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.statusbar.StatusBarIconList;
+import com.android.internal.statusbar.StatusBarNotification;
+import com.android.internal.widget.SizeAdaptiveLayout;
+import com.android.systemui.R;
+import com.android.systemui.SearchPanelView;
+import com.android.systemui.SystemUI;
+import com.android.systemui.recent.RecentTasksLoader;
+import com.android.systemui.recent.RecentsActivity;
+import com.android.systemui.recent.TaskDescription;
+import com.android.systemui.statusbar.policy.NotificationRowLayout;
+import com.android.systemui.statusbar.tablet.StatusBarPanel;
 
+import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
+import android.app.ActivityOptions;
 import android.app.KeyguardManager;
-import android.app.Notification;
 import android.app.PendingIntent;
+import android.app.TaskStackBuilder;
+import android.content.ActivityNotFoundException;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.database.ContentObserver;
+import android.graphics.Bitmap;
+import android.graphics.Paint;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Build;
@@ -35,8 +57,10 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.Slog;
 import android.view.Display;
@@ -48,35 +72,22 @@
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+import android.view.WindowManagerGlobal;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
-import android.widget.RemoteViews;
 import android.widget.PopupMenu;
+import android.widget.RemoteViews;
+import android.widget.TextView;
 
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.statusbar.StatusBarIcon;
-import com.android.internal.statusbar.StatusBarIconList;
-import com.android.internal.statusbar.StatusBarNotification;
-import com.android.internal.widget.SizeAdaptiveLayout;
-import com.android.systemui.SearchPanelView;
-import com.android.systemui.SystemUI;
-import com.android.systemui.recent.RecentsPanelView;
-import com.android.systemui.recent.RecentTasksLoader;
-import com.android.systemui.recent.TaskDescription;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.NotificationData.Entry;
-import com.android.systemui.statusbar.policy.NotificationRowLayout;
-import com.android.systemui.statusbar.tablet.StatusBarPanel;
-
-import com.android.systemui.R;
+import java.util.ArrayList;
 
 public abstract class BaseStatusBar extends SystemUI implements
-    CommandQueue.Callbacks, RecentsPanelView.OnRecentsPanelVisibilityChangedListener {
-    static final String TAG = "StatusBar";
-    private static final boolean DEBUG = false;
+        CommandQueue.Callbacks {
+    public static final String TAG = "StatusBar";
+    public static final boolean DEBUG = false;
+    public static final boolean MULTIUSER_DEBUG = false;
 
-    protected static final int MSG_OPEN_RECENTS_PANEL = 1020;
+    protected static final int MSG_TOGGLE_RECENTS_PANEL = 1020;
     protected static final int MSG_CLOSE_RECENTS_PANEL = 1021;
     protected static final int MSG_PRELOAD_RECENT_APPS = 1022;
     protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
@@ -109,12 +120,10 @@
     // Search panel
     protected SearchPanelView mSearchPanelView;
 
-    // Recent apps
-    protected RecentsPanelView mRecentsPanel;
-    protected RecentTasksLoader mRecentTasksLoader;
-
     protected PopupMenu mNotificationBlamePopup;
 
+    protected int mCurrentUserId = 0;
+
     // UI-specific methods
 
     /**
@@ -123,31 +132,25 @@
      */
     protected abstract void createAndAddWindows();
 
+    protected WindowManager mWindowManager;
+    protected IWindowManager mWindowManagerService;
     protected Display mDisplay;
-    private IWindowManager mWindowManager;
+
     private boolean mDeviceProvisioned = false;
 
-    public IWindowManager getWindowManager() {
-        return mWindowManager;
-    }
-
-    public Display getDisplay() {
-        return mDisplay;
-    }
-
     public IStatusBarService getStatusBarService() {
         return mBarService;
     }
 
-    protected boolean isDeviceProvisioned() {
+    public boolean isDeviceProvisioned() {
         return mDeviceProvisioned;
     }
 
     private ContentObserver mProvisioningObserver = new ContentObserver(new Handler()) {
         @Override
         public void onChange(boolean selfChange) {
-            final boolean provisioned = 0 != Settings.Secure.getInt(
-                    mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0);
+            final boolean provisioned = 0 != Settings.Global.getInt(
+                    mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0);
             if (provisioned != mDeviceProvisioned) {
                 mDeviceProvisioned = provisioned;
                 updateNotificationIcons();
@@ -158,6 +161,9 @@
     private RemoteViews.OnClickHandler mOnClickHandler = new RemoteViews.OnClickHandler() {
         @Override
         public boolean onClickHandler(View view, PendingIntent pendingIntent, Intent fillInIntent) {
+            if (DEBUG) {
+                Slog.v(TAG, "Notification click handler invoked for intent: " + pendingIntent);
+            }
             final boolean isActivity = pendingIntent.isActivity();
             if (isActivity) {
                 try {
@@ -177,7 +183,7 @@
 
             if (isActivity && handled) {
                 // close the shade if it was open
-                animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
+                animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
                 visibilityChanged(false);
             }
             return handled;
@@ -185,17 +191,15 @@
     };
 
     public void start() {
-        mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
-                .getDefaultDisplay();
+        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
+        mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
+        mDisplay = mWindowManager.getDefaultDisplay();
 
         mProvisioningObserver.onChange(false); // set up
         mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.DEVICE_PROVISIONED), true,
+                Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), true,
                 mProvisioningObserver);
 
-        mWindowManager = IWindowManager.Stub.asInterface(
-                ServiceManager.getService(Context.WINDOW_SERVICE));
-
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
 
@@ -255,6 +259,36 @@
                    switches[3]
                    ));
         }
+
+        mCurrentUserId = ActivityManager.getCurrentUser();
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_USER_SWITCHED);
+        mContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                String action = intent.getAction();
+                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                    mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+                    if (true) Slog.v(TAG, "userId " + mCurrentUserId + " is in the house");
+                    userSwitched(mCurrentUserId);
+                }
+            }}, filter);
+    }
+
+    public void userSwitched(int newUserId) {
+        // should be overridden
+    }
+
+    public boolean notificationIsForCurrentUser(StatusBarNotification n) {
+        final int thisUserId = mCurrentUserId;
+        final int notificationUserId = n.getUserId();
+        if (DEBUG && MULTIUSER_DEBUG) {
+            Slog.v(TAG, String.format("%s: current userid: %d, notification userid: %d",
+                    n, thisUserId, notificationUserId));
+        }
+        return notificationUserId == UserHandle.USER_ALL
+                || thisUserId == notificationUserId;
     }
 
     protected View updateNotificationVetoButton(View row, StatusBarNotification n) {
@@ -265,8 +299,12 @@
             final int _id = n.id;
             vetoButton.setOnClickListener(new View.OnClickListener() {
                     public void onClick(View v) {
+                        // Accessibility feedback
+                        v.announceForAccessibility(
+                                mContext.getString(R.string.accessibility_notification_dismissed));
                         try {
                             mBarService.onNotificationClear(_pkg, _tag, _id);
+
                         } catch (RemoteException ex) {
                             // system process is dead if we're here.
                         }
@@ -276,6 +314,7 @@
         } else {
             vetoButton.setVisibility(View.GONE);
         }
+        vetoButton.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
         return vetoButton;
     }
 
@@ -301,8 +340,9 @@
     private void startApplicationDetailsActivity(String packageName) {
         Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                 Uri.fromParts("package", packageName, null));
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mContext.startActivity(intent);
+        intent.setComponent(intent.resolveActivity(mContext.getPackageManager()));
+        TaskStackBuilder.create(mContext).addNextIntentWithParentStack(intent).startActivities(
+                null, UserHandle.CURRENT);
     }
 
     protected View.OnLongClickListener getNotificationLongClicker() {
@@ -320,7 +360,7 @@
                     public boolean onMenuItemClick(MenuItem item) {
                         if (item.getItemId() == R.id.notification_inspect_item) {
                             startApplicationDetailsActivity(packageNameF);
-                            animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
+                            animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
                         } else {
                             return false;
                         }
@@ -347,8 +387,7 @@
 
     @Override
     public void toggleRecentApps() {
-        int msg = (mRecentsPanel.getVisibility() == View.VISIBLE)
-            ? MSG_CLOSE_RECENTS_PANEL : MSG_OPEN_RECENTS_PANEL;
+        int msg = MSG_TOGGLE_RECENTS_PANEL;
         mHandler.removeMessages(msg);
         mHandler.sendEmptyMessage(msg);
     }
@@ -381,57 +420,19 @@
         mHandler.sendEmptyMessage(msg);
     }
 
-    @Override
-    public void onRecentsPanelVisibilityChanged(boolean visible) {
-    }
-
     protected abstract WindowManager.LayoutParams getRecentsLayoutParams(
             LayoutParams layoutParams);
 
     protected abstract WindowManager.LayoutParams getSearchLayoutParams(
             LayoutParams layoutParams);
 
-    protected void updateRecentsPanel(int recentsResId) {
-        // Recents Panel
-        boolean visible = false;
-        ArrayList<TaskDescription> recentTasksList = null;
-        boolean firstScreenful = false;
-        if (mRecentsPanel != null) {
-            visible = mRecentsPanel.isShowing();
-            WindowManagerImpl.getDefault().removeView(mRecentsPanel);
-            if (visible) {
-                recentTasksList = mRecentsPanel.getRecentTasksList();
-                firstScreenful = mRecentsPanel.getFirstScreenful();
-            }
-        }
-
-        // Provide RecentsPanelView with a temporary parent to allow layout params to work.
-        LinearLayout tmpRoot = new LinearLayout(mContext);
-        mRecentsPanel = (RecentsPanelView) LayoutInflater.from(mContext).inflate(
-                recentsResId, tmpRoot, false);
-        mRecentsPanel.setRecentTasksLoader(mRecentTasksLoader);
-        mRecentTasksLoader.setRecentsPanel(mRecentsPanel);
-        mRecentsPanel.setOnTouchListener(
-                 new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL, mRecentsPanel));
-        mRecentsPanel.setVisibility(View.GONE);
-
-
-        WindowManager.LayoutParams lp = getRecentsLayoutParams(mRecentsPanel.getLayoutParams());
-
-        WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
-        mRecentsPanel.setBar(this);
-        if (visible) {
-            mRecentsPanel.show(true, false, recentTasksList, firstScreenful);
-        }
-
-    }
 
     protected void updateSearchPanel() {
         // Search Panel
         boolean visible = false;
         if (mSearchPanelView != null) {
             visible = mSearchPanelView.isShowing();
-            WindowManagerImpl.getDefault().removeView(mSearchPanelView);
+            mWindowManager.removeView(mSearchPanelView);
         }
 
         // Provide SearchPanel with a temporary parent to allow layout params to work.
@@ -444,7 +445,7 @@
 
         WindowManager.LayoutParams lp = getSearchLayoutParams(mSearchPanelView.getLayoutParams());
 
-        WindowManagerImpl.getDefault().addView(mSearchPanelView, lp);
+        mWindowManager.addView(mSearchPanelView, lp);
         mSearchPanelView.setBar(this);
         if (visible) {
             mSearchPanelView.show(true, false);
@@ -464,28 +465,197 @@
         }
     }
 
+    protected abstract View getStatusBarView();
+
+    protected void toggleRecentsActivity() {
+        try {
+
+            TaskDescription firstTask = RecentTasksLoader.getInstance(mContext).getFirstTask();
+
+            Intent intent = new Intent(RecentsActivity.TOGGLE_RECENTS_INTENT);
+            intent.setClassName("com.android.systemui",
+                    "com.android.systemui.recent.RecentsActivity");
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+
+            if (firstTask == null) {
+                if (RecentsActivity.forceOpaqueBackground(mContext)) {
+                    ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
+                            R.anim.recents_launch_from_launcher_enter,
+                            R.anim.recents_launch_from_launcher_exit);
+                    mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
+                            UserHandle.USER_CURRENT));
+                } else {
+                    // The correct window animation will be applied via the activity's style
+                    mContext.startActivityAsUser(intent, new UserHandle(
+                            UserHandle.USER_CURRENT));
+                }
+
+            } else {
+                Bitmap first = firstTask.getThumbnail();
+                final Resources res = mContext.getResources();
+
+                float thumbWidth = res
+                        .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_width);
+                float thumbHeight = res
+                        .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_height);
+                if (first == null) {
+                    throw new RuntimeException("Recents thumbnail is null");
+                }
+                if (first.getWidth() != thumbWidth || first.getHeight() != thumbHeight) {
+                    first = Bitmap.createScaledBitmap(first, (int) thumbWidth, (int) thumbHeight,
+                            true);
+                    if (first == null) {
+                        throw new RuntimeException("Recents thumbnail is null");
+                    }
+                }
+
+
+                DisplayMetrics dm = new DisplayMetrics();
+                mDisplay.getMetrics(dm);
+                // calculate it here, but consider moving it elsewhere
+                // first, determine which orientation you're in.
+                // todo: move the system_bar layouts to sw600dp ?
+                final Configuration config = res.getConfiguration();
+                int x, y;
+
+                if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
+                    float appLabelLeftMargin = res
+                            .getDimensionPixelSize(R.dimen.status_bar_recents_app_label_left_margin);
+                    float appLabelWidth = res
+                            .getDimensionPixelSize(R.dimen.status_bar_recents_app_label_width);
+                    float thumbLeftMargin = res
+                            .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_left_margin);
+                    float thumbBgPadding = res
+                            .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_bg_padding);
+
+                    float width = appLabelLeftMargin +
+                            +appLabelWidth
+                            + thumbLeftMargin
+                            + thumbWidth
+                            + 2 * thumbBgPadding;
+
+                    x = (int) ((dm.widthPixels - width) / 2f + appLabelLeftMargin + appLabelWidth
+                            + thumbBgPadding + thumbLeftMargin);
+                    y = (int) (dm.heightPixels
+                            - res.getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_height) - thumbBgPadding);
+                } else { // if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+                    float thumbTopMargin = res
+                            .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_top_margin);
+                    float thumbBgPadding = res
+                            .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_bg_padding);
+                    float textPadding = res
+                            .getDimensionPixelSize(R.dimen.status_bar_recents_text_description_padding);
+                    float labelTextSize = res
+                            .getDimensionPixelSize(R.dimen.status_bar_recents_app_label_text_size);
+                    Paint p = new Paint();
+                    p.setTextSize(labelTextSize);
+                    float labelTextHeight = p.getFontMetricsInt().bottom
+                            - p.getFontMetricsInt().top;
+                    float descriptionTextSize = res
+                            .getDimensionPixelSize(R.dimen.status_bar_recents_app_description_text_size);
+                    p.setTextSize(descriptionTextSize);
+                    float descriptionTextHeight = p.getFontMetricsInt().bottom
+                            - p.getFontMetricsInt().top;
+
+                    float statusBarHeight = res
+                            .getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+                    float recentsItemTopPadding = statusBarHeight;
+
+                    float height = thumbTopMargin
+                            + thumbHeight
+                            + 2 * thumbBgPadding + textPadding + labelTextHeight
+                            + recentsItemTopPadding + textPadding + descriptionTextHeight;
+                    float recentsItemRightPadding = res
+                            .getDimensionPixelSize(R.dimen.status_bar_recents_item_padding);
+                    float recentsScrollViewRightPadding = res
+                            .getDimensionPixelSize(R.dimen.status_bar_recents_right_glow_margin);
+                    x = (int) (dm.widthPixels - res
+                            .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_width)
+                            - thumbBgPadding - recentsItemRightPadding - recentsScrollViewRightPadding);
+                    y = (int) ((dm.heightPixels - statusBarHeight - height) / 2f + thumbTopMargin
+                            + recentsItemTopPadding + thumbBgPadding + statusBarHeight);
+                }
+
+                ActivityOptions opts = ActivityOptions.makeThumbnailScaleDownAnimation(
+                        getStatusBarView(),
+                        first, x, y,
+                        new ActivityOptions.OnAnimationStartedListener() {
+                            public void onAnimationStarted() {
+                                Intent intent = new Intent(RecentsActivity.WINDOW_ANIMATION_START_INTENT);
+                                intent.setPackage("com.android.systemui");
+                                mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+                            }
+                        });
+                intent.putExtra(RecentsActivity.WAITING_FOR_WINDOW_ANIMATION_PARAM, true);
+                mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
+                        UserHandle.USER_CURRENT));
+            }
+            return;
+        } catch (ActivityNotFoundException e) {
+            Log.e(TAG, "Failed to launch RecentAppsIntent", e);
+        }
+    }
+
+    protected View.OnTouchListener mRecentsPreloadOnTouchListener = new View.OnTouchListener() {
+        // additional optimization when we have software system buttons - start loading the recent
+        // tasks on touch down
+        @Override
+        public boolean onTouch(View v, MotionEvent event) {
+            int action = event.getAction() & MotionEvent.ACTION_MASK;
+            if (action == MotionEvent.ACTION_DOWN) {
+                preloadRecentTasksList();
+            } else if (action == MotionEvent.ACTION_CANCEL) {
+                cancelPreloadingRecentTasksList();
+            } else if (action == MotionEvent.ACTION_UP) {
+                if (!v.isPressed()) {
+                    cancelPreloadingRecentTasksList();
+                }
+
+            }
+            return false;
+        }
+    };
+
+    protected void preloadRecentTasksList() {
+        if (DEBUG) Slog.d(TAG, "preloading recents");
+        Intent intent = new Intent(RecentsActivity.PRELOAD_INTENT);
+        intent.setClassName("com.android.systemui",
+                "com.android.systemui.recent.RecentsPreloadReceiver");
+        mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+
+        RecentTasksLoader.getInstance(mContext).preloadFirstTask();
+    }
+
+    protected void cancelPreloadingRecentTasksList() {
+        if (DEBUG) Slog.d(TAG, "cancel preloading recents");
+        Intent intent = new Intent(RecentsActivity.CANCEL_PRELOAD_INTENT);
+        intent.setClassName("com.android.systemui",
+                "com.android.systemui.recent.RecentsPreloadReceiver");
+        mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+
+        RecentTasksLoader.getInstance(mContext).cancelPreloadingFirstTask();
+    }
+
     protected class H extends Handler {
         public void handleMessage(Message m) {
+            Intent intent;
             switch (m.what) {
-             case MSG_OPEN_RECENTS_PANEL:
-                  if (DEBUG) Slog.d(TAG, "opening recents panel");
-                  if (mRecentsPanel != null) {
-                      mRecentsPanel.show(true, false);
-                  }
-                  break;
+             case MSG_TOGGLE_RECENTS_PANEL:
+                 if (DEBUG) Slog.d(TAG, "toggle recents panel");
+                 toggleRecentsActivity();
+                 break;
              case MSG_CLOSE_RECENTS_PANEL:
-                  if (DEBUG) Slog.d(TAG, "closing recents panel");
-                  if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
-                      mRecentsPanel.show(false, false);
-                  }
-                  break;
+                 if (DEBUG) Slog.d(TAG, "closing recents panel");
+                 intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT);
+                 intent.setPackage("com.android.systemui");
+                 mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+                 break;
              case MSG_PRELOAD_RECENT_APPS:
-                  if (DEBUG) Slog.d(TAG, "preloading recents");
-                  mRecentsPanel.preloadRecentTasksList();
+                  preloadRecentTasksList();
                   break;
              case MSG_CANCEL_PRELOAD_RECENT_APPS:
-                  if (DEBUG) Slog.d(TAG, "cancel preloading recents");
-                  mRecentsPanel.clearRecentTasksList();
+                  cancelPreloadingRecentTasksList();
                   break;
              case MSG_OPEN_SEARCH_PANEL:
                  if (DEBUG) Slog.d(TAG, "opening search panel");
@@ -529,8 +699,6 @@
     }
 
     protected  boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) {
-        int rowHeight =
-                mContext.getResources().getDimensionPixelSize(R.dimen.notification_row_min_height);
         int minHeight =
                 mContext.getResources().getDimensionPixelSize(R.dimen.notification_min_height);
         int maxHeight =
@@ -575,7 +743,6 @@
         // TODO(cwren) normalize variable names with those in updateNotification
         View expandedOneU = null;
         View expandedLarge = null;
-        Exception exception = null;
         try {
             expandedOneU = oneU.apply(mContext, adaptive, mOnClickHandler);
             if (large != null) {
@@ -607,6 +774,14 @@
         applyLegacyRowBackground(sbn, content);
 
         row.setTag(R.id.expandable_tag, Boolean.valueOf(large != null));
+
+        if (MULTIUSER_DEBUG) {
+            TextView debug = (TextView) row.findViewById(R.id.debug_info);
+            if (debug != null) {
+                debug.setVisibility(View.VISIBLE);
+                debug.setText("U " + entry.notification.getUserId());
+            }
+        }
         entry.row = row;
         entry.content = content;
         entry.expanded = expandedOneU;
@@ -670,7 +845,7 @@
             }
 
             // close the shade if it was open
-            animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
+            animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
             visibilityChanged(false);
 
             // If this click was on the intruder alert, hide that instead
@@ -737,6 +912,7 @@
         iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
 
         final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
+                    notification.user,
                     notification.notification.icon,
                     notification.notification.iconLevel,
                     notification.notification.number,
@@ -889,6 +1065,7 @@
                 }
                 // Update the icon.
                 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
+                        notification.user,
                         notification.notification.icon, notification.notification.iconLevel,
                         notification.notification.number,
                         notification.notification.tickerText);
@@ -923,8 +1100,12 @@
         // swipe-dismissable)
         updateNotificationVetoButton(oldEntry.row, notification);
 
+        // Is this for you?
+        boolean isForCurrentUser = notificationIsForCurrentUser(notification);
+        if (DEBUG) Slog.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
+
         // Restart the ticker if it's still running
-        if (updateTicker) {
+        if (updateTicker && isForCurrentUser) {
             haltTicker();
             tick(key, notification, false);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index a00d95a..752bb0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -33,38 +33,29 @@
  * are coalesced, note that they are all idempotent.
  */
 public class CommandQueue extends IStatusBar.Stub {
-    private static final String TAG = "StatusBar.CommandQueue";
-
     private static final int INDEX_MASK = 0xffff;
     private static final int MSG_SHIFT  = 16;
     private static final int MSG_MASK   = 0xffff << MSG_SHIFT;
 
-
-    private static final int MSG_ICON                   = 1 << MSG_SHIFT;
     private static final int OP_SET_ICON    = 1;
     private static final int OP_REMOVE_ICON = 2;
 
-    private static final int MSG_ADD_NOTIFICATION       = 2 << MSG_SHIFT;
-    private static final int MSG_UPDATE_NOTIFICATION    = 3 << MSG_SHIFT;
-    private static final int MSG_REMOVE_NOTIFICATION    = 4 << MSG_SHIFT;
-
-    private static final int MSG_DISABLE                = 5 << MSG_SHIFT;
-
-    private static final int MSG_SET_VISIBILITY         = 6 << MSG_SHIFT;
-    private static final int OP_EXPAND      = 1;
-    private static final int OP_COLLAPSE    = 2;
-
-    private static final int MSG_SET_SYSTEMUI_VISIBILITY          = 7 << MSG_SHIFT;
-
-    private static final int MSG_TOP_APP_WINDOW_CHANGED = 8 << MSG_SHIFT;
-    private static final int MSG_SHOW_IME_BUTTON        = 9 << MSG_SHIFT;
-    private static final int MSG_SET_HARD_KEYBOARD_STATUS = 10 << MSG_SHIFT;
-
-    private static final int MSG_TOGGLE_RECENT_APPS       = 11 << MSG_SHIFT;
-    private static final int MSG_PRELOAD_RECENT_APPS      = 12 << MSG_SHIFT;
-    private static final int MSG_CANCEL_PRELOAD_RECENT_APPS       = 13 << MSG_SHIFT;
-
-    private static final int MSG_SET_NAVIGATION_ICON_HINTS = 14 << MSG_SHIFT;
+    private static final int MSG_ICON                       = 1 << MSG_SHIFT;
+    private static final int MSG_ADD_NOTIFICATION           = 2 << MSG_SHIFT;
+    private static final int MSG_UPDATE_NOTIFICATION        = 3 << MSG_SHIFT;
+    private static final int MSG_REMOVE_NOTIFICATION        = 4 << MSG_SHIFT;
+    private static final int MSG_DISABLE                    = 5 << MSG_SHIFT;
+    private static final int MSG_EXPAND_NOTIFICATIONS       = 6 << MSG_SHIFT;
+    private static final int MSG_COLLAPSE_PANELS            = 7 << MSG_SHIFT;
+    private static final int MSG_EXPAND_SETTINGS            = 8 << MSG_SHIFT;
+    private static final int MSG_SET_SYSTEMUI_VISIBILITY    = 9 << MSG_SHIFT;
+    private static final int MSG_TOP_APP_WINDOW_CHANGED     = 10 << MSG_SHIFT;
+    private static final int MSG_SHOW_IME_BUTTON            = 11 << MSG_SHIFT;
+    private static final int MSG_SET_HARD_KEYBOARD_STATUS   = 12 << MSG_SHIFT;
+    private static final int MSG_TOGGLE_RECENT_APPS         = 13 << MSG_SHIFT;
+    private static final int MSG_PRELOAD_RECENT_APPS        = 14 << MSG_SHIFT;
+    private static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 15 << MSG_SHIFT;
+    private static final int MSG_SET_NAVIGATION_ICON_HINTS  = 16 << MSG_SHIFT;
 
     public static final int FLAG_EXCLUDE_NONE = 0;
     public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -94,8 +85,9 @@
         public void updateNotification(IBinder key, StatusBarNotification notification);
         public void removeNotification(IBinder key);
         public void disable(int state);
-        public void animateExpand();
-        public void animateCollapse(int flags);
+        public void animateExpandNotificationsPanel();
+        public void animateCollapsePanels(int flags);
+        public void animateExpandSettingsPanel();
         public void setSystemUiVisibility(int vis, int mask);
         public void topAppWindowChanged(boolean visible);
         public void setImeWindowStatus(IBinder token, int vis, int backDisposition);
@@ -160,21 +152,24 @@
         }
     }
 
-    public void animateExpand() {
+    public void animateExpandNotificationsPanel() {
         synchronized (mList) {
-            mHandler.removeMessages(MSG_SET_VISIBILITY);
-            mHandler.obtainMessage(MSG_SET_VISIBILITY, OP_EXPAND, 0, null).sendToTarget();
+            mHandler.removeMessages(MSG_EXPAND_NOTIFICATIONS);
+            mHandler.sendEmptyMessage(MSG_EXPAND_NOTIFICATIONS);
         }
     }
 
-    public void animateCollapse() {
-        animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
+    public void animateCollapsePanels() {
+        synchronized (mList) {
+            mHandler.removeMessages(MSG_COLLAPSE_PANELS);
+            mHandler.sendEmptyMessage(MSG_COLLAPSE_PANELS);
+        }
     }
 
-    public void animateCollapse(int flags) {
+    public void animateExpandSettingsPanel() {
         synchronized (mList) {
-            mHandler.removeMessages(MSG_SET_VISIBILITY);
-            mHandler.obtainMessage(MSG_SET_VISIBILITY, OP_COLLAPSE, flags, null).sendToTarget();
+            mHandler.removeMessages(MSG_EXPAND_SETTINGS);
+            mHandler.sendEmptyMessage(MSG_EXPAND_SETTINGS);
         }
     }
 
@@ -284,12 +279,14 @@
                 case MSG_DISABLE:
                     mCallbacks.disable(msg.arg1);
                     break;
-                case MSG_SET_VISIBILITY:
-                    if (msg.arg1 == OP_EXPAND) {
-                        mCallbacks.animateExpand();
-                    } else {
-                        mCallbacks.animateCollapse(msg.arg2);
-                    }
+                case MSG_EXPAND_NOTIFICATIONS:
+                    mCallbacks.animateExpandNotificationsPanel();
+                    break;
+                case MSG_COLLAPSE_PANELS:
+                    mCallbacks.animateCollapsePanels(0);
+                    break;
+                case MSG_EXPAND_SETTINGS:
+                    mCallbacks.animateExpandSettingsPanel();
                     break;
                 case MSG_SET_SYSTEMUI_VISIBILITY:
                     mCallbacks.setSystemUiVisibility(msg.arg1, msg.arg2);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
index 4f33e23..3ac1bcf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
@@ -49,7 +49,7 @@
 
     public boolean onInterceptTouchEvent(MotionEvent event) {
         if (mSourceView == null || mDelegateView == null
-                || mBar.shouldDisableNavbarGestures() || mBar.inKeyguardRestrictedInputMode()) {
+                || mBar.shouldDisableNavbarGestures()) {
             return false;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java b/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
new file mode 100755
index 0000000..0f894a1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import java.io.BufferedWriter;
+import java.io.FileDescriptor;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.LinkedList;
+
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.view.MotionEvent;
+
+/**
+ * Convenience class for capturing gestures for later analysis.
+ */
+public class GestureRecorder {
+    public static final boolean DEBUG = true; // for now
+    public static final String TAG = GestureRecorder.class.getSimpleName();
+
+    public class Gesture {
+        public abstract class Record {
+            long time;
+            public abstract String toJson();
+        }
+        public class MotionEventRecord extends Record {
+            public MotionEvent event;
+            public MotionEventRecord(long when, MotionEvent event) {
+                this.time = when;
+                this.event = event.copy();
+            }
+            String actionName(int action) {
+                switch (action) {
+                    case MotionEvent.ACTION_DOWN:
+                        return "down";
+                    case MotionEvent.ACTION_UP:
+                        return "up";
+                    case MotionEvent.ACTION_MOVE:
+                        return "move";
+                    case MotionEvent.ACTION_CANCEL:
+                        return "cancel";
+                    default:
+                        return String.valueOf(action);
+                }
+            }
+            public String toJson() {
+                return String.format(
+                        ("{\"type\":\"motion\", \"time\":%d, \"action\":\"%s\", "
+                            + "\"x\":%.2f, \"y\":%.2f, \"s\":%.2f, \"p\":%.2f}"),
+                        this.time,
+                        actionName(this.event.getAction()),
+                        this.event.getRawX(),
+                        this.event.getRawY(),
+                        this.event.getSize(),
+                        this.event.getPressure()
+                        );
+            }
+        }
+        public class TagRecord extends Record {
+            public String tag, info;
+            public TagRecord(long when, String tag, String info) {
+                this.time = when;
+                this.tag = tag;
+                this.info = info;
+            }
+            public String toJson() {
+                return String.format("{\"type\":\"tag\", \"time\":%d, \"tag\":\"%s\", \"info\":\"%s\"}",
+                        this.time,
+                        this.tag,
+                        this.info
+                        );
+            }
+        }
+        private LinkedList<Record> mRecords = new LinkedList<Record>();
+        private HashSet<String> mTags = new HashSet<String>();
+        long mDownTime = -1;
+        boolean mComplete = false;
+
+        public void add(MotionEvent ev) {
+            mRecords.add(new MotionEventRecord(ev.getEventTime(), ev));
+            if (mDownTime < 0) {
+                mDownTime = ev.getDownTime();
+            } else {
+                if (mDownTime != ev.getDownTime()) {
+                    Slog.w(TAG, "Assertion failure in GestureRecorder: event downTime ("
+                            +ev.getDownTime()+") does not match gesture downTime ("+mDownTime+")");
+                }
+            }
+            switch (ev.getActionMasked()) {
+                case MotionEvent.ACTION_UP:
+                case MotionEvent.ACTION_CANCEL:
+                    mComplete = true;
+            }
+        }
+        public void tag(long when, String tag, String info) {
+            mRecords.add(new TagRecord(when, tag, info));
+            mTags.add(tag);
+        }
+        public boolean isComplete() {
+            return mComplete;
+        }
+        public String toJson() {
+            StringBuilder sb = new StringBuilder();
+            boolean first = true;
+            sb.append("[");
+            for (Record r : mRecords) {
+                if (!first) sb.append(", ");
+                first = false;
+                sb.append(r.toJson());
+            }
+            sb.append("]");
+            return sb.toString();
+        }
+    }
+
+    // -=-=-=-=-=-=-=-=-=-=-=-
+
+    static final long SAVE_DELAY = 5000; // ms
+    static final int SAVE_MESSAGE = 6351;
+
+    private LinkedList<Gesture> mGestures;
+    private Gesture mCurrentGesture;
+    private int mLastSaveLen = -1;
+    private String mLogfile;
+
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            if (msg.what == SAVE_MESSAGE) {
+                save();
+            }
+        }
+    };
+
+    public GestureRecorder(String filename) {
+        mLogfile = filename;
+        mGestures = new LinkedList<Gesture>();
+        mCurrentGesture = null;
+    }
+
+    public void add(MotionEvent ev) {
+        synchronized (mGestures) {
+            if (mCurrentGesture == null || mCurrentGesture.isComplete()) {
+                mCurrentGesture = new Gesture();
+                mGestures.add(mCurrentGesture);
+            }
+            mCurrentGesture.add(ev);
+        }
+        saveLater();
+    }
+
+    public void tag(long when, String tag, String info) {
+        synchronized (mGestures) {
+            if (mCurrentGesture == null) {
+                mCurrentGesture = new Gesture();
+                mGestures.add(mCurrentGesture);
+            }
+            mCurrentGesture.tag(when, tag, info);
+        }
+        saveLater();
+    }
+
+    public void tag(long when, String tag) {
+        tag(when, tag, null);
+    }
+
+    public void tag(String tag) {
+        tag(SystemClock.uptimeMillis(), tag, null);
+    }
+
+    public void tag(String tag, String info) {
+        tag(SystemClock.uptimeMillis(), tag, info);
+    }
+
+    /**
+     * Generates a JSON string capturing all completed gestures.
+     * Not threadsafe; call with a lock.
+     */
+    public String toJsonLocked() {
+        StringBuilder sb = new StringBuilder();
+        boolean first = true;
+        sb.append("[");
+        int count = 0;
+        for (Gesture g : mGestures) {
+            if (!g.isComplete()) continue;
+            if (!first) sb.append("," );
+            first = false;
+            sb.append(g.toJson());
+            count++;
+        }
+        mLastSaveLen = count;
+        sb.append("]");
+        return sb.toString();
+    }
+
+    public String toJson() {
+        String s;
+        synchronized (mGestures) {
+            s = toJsonLocked();
+        }
+        return s;
+    }
+
+    public void saveLater() {
+        mHandler.removeMessages(SAVE_MESSAGE);
+        mHandler.sendEmptyMessageDelayed(SAVE_MESSAGE, SAVE_DELAY);
+    }
+
+    public void save() {
+        synchronized (mGestures) {
+            try {
+                BufferedWriter w = new BufferedWriter(new FileWriter(mLogfile, /*append=*/ true));
+                w.append(toJsonLocked() + "\n");
+                w.close();
+                mGestures.clear();
+                // If we have a pending gesture, push it back
+                if (mCurrentGesture != null && !mCurrentGesture.isComplete()) {
+                    mGestures.add(mCurrentGesture);
+                }
+                if (DEBUG) {
+                    Slog.v(TAG, String.format("Wrote %d complete gestures to %s", mLastSaveLen, mLogfile));
+                }
+            } catch (IOException e) {
+                Slog.e(TAG, String.format("Couldn't write gestures to %s", mLogfile), e);
+                mLastSaveLen = -1;
+            }
+        }
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        save();
+        if (mLastSaveLen >= 0) {
+            pw.println(String.valueOf(mLastSaveLen) + " gestures written to " + mLogfile);
+        } else {
+            pw.println("error writing gestures");
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RotationToggle.java b/packages/SystemUI/src/com/android/systemui/statusbar/RotationToggle.java
index 5dd45a4..735ee25 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RotationToggle.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RotationToggle.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package com.android.systemui.statusbar;
 
 import android.content.Context;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 6a9e838..dbc55c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -24,6 +24,7 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Slog;
@@ -165,7 +166,12 @@
 
         if (icon.iconPackage != null) {
             try {
-                r = context.getPackageManager().getResourcesForApplication(icon.iconPackage);
+                int userId = icon.user.getIdentifier();
+                if (userId == UserHandle.USER_ALL) {
+                    userId = UserHandle.USER_OWNER;
+                }
+                r = context.getPackageManager()
+                        .getResourcesForApplicationAsUser(icon.iconPackage, userId);
             } catch (PackageManager.NameNotFoundException ex) {
                 Slog.e(TAG, "Icon package not found: " + icon.iconPackage);
                 return null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CloseDragHandle.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CloseDragHandle.java
index ba64282..ee01489 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CloseDragHandle.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CloseDragHandle.java
@@ -36,7 +36,9 @@
      */
     @Override
     public boolean onTouchEvent(MotionEvent event) {
-        if (event.getAction() != MotionEvent.ACTION_DOWN) {
+        if (event.getAction() == MotionEvent.ACTION_DOWN) {
+            setPressed(true);
+        } else {
             mService.interceptTouchEvent(event);
         }
         return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 00d6d6f..5eeef93 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -18,12 +18,12 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
+import android.animation.LayoutTransition;
 import android.app.StatusBarManager;
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.Point;
 import android.graphics.Rect;
-import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.Message;
@@ -33,33 +33,31 @@
 import android.view.animation.AccelerateInterpolator;
 import android.view.Display;
 import android.view.MotionEvent;
-import android.view.VelocityTracker;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.Surface;
-import android.view.Window;
+import android.view.ViewGroup;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.lang.StringBuilder;
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.DelegateViewHelper;
+import com.android.systemui.statusbar.policy.DeadZone;
 
 public class NavigationBarView extends LinearLayout {
     final static boolean DEBUG = false;
     final static String TAG = "PhoneStatusBar/NavigationBarView";
 
-    final static boolean DEBUG_DEADZONE = false;
-
     final static boolean NAVBAR_ALWAYS_AT_RIGHT = true;
 
+    // slippery nav bar when everything is disabled, e.g. during setup
+    final static boolean SLIPPERY_WHEN_DISABLED= true;
+
     final static boolean ANIMATE_HIDE_TRANSITION = false; // turned off because it introduces unsightly delay when videos goes to full screen
 
     protected IStatusBarService mBarService;
@@ -69,6 +67,7 @@
 
     int mBarSize;
     boolean mVertical;
+    boolean mScreenOn;
 
     boolean mHidden, mLowProfile, mShowMenu;
     int mDisabledFlags = 0;
@@ -77,6 +76,7 @@
     private Drawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
     
     private DelegateViewHelper mDelegateHelper;
+    private DeadZone mDeadZone;
 
     // workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288)
     final static boolean WORKAROUND_INVALID_LAYOUT = true;
@@ -115,10 +115,14 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
-        if (mDelegateHelper != null) {
-            mDelegateHelper.onInterceptTouchEvent(event);
+        if (mDeadZone != null && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
+            mDeadZone.poke(event);
         }
-        return true;
+        if (mDelegateHelper != null) {
+            boolean ret = mDelegateHelper.onInterceptTouchEvent(event);
+            if (ret) return true;
+        }
+        return super.onTouchEvent(event);
     }
 
     @Override
@@ -144,6 +148,11 @@
         return mCurrentView.findViewById(R.id.home);
     }
 
+    // for when home is disabled, but search isn't
+    public View getSearchLight() {
+        return mCurrentView.findViewById(R.id.search_light);
+    }
+
     public NavigationBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
@@ -166,6 +175,11 @@
         mBackAltLandIcon = res.getDrawable(R.drawable.ic_sysbar_back_ime);
     }
 
+    public void notifyScreenOn(boolean screenOn) {
+        mScreenOn = screenOn;
+        setDisabledFlags(mDisabledFlags, true);
+    }
+
     View.OnTouchListener mLightsOutListener = new View.OnTouchListener() {
         @Override
         public boolean onTouch(View v, MotionEvent ev) {
@@ -210,6 +224,8 @@
             (0 != (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT))
                 ? (mVertical ? mBackAltLandIcon : mBackAltIcon)
                 : (mVertical ? mBackLandIcon : mBackIcon));
+
+        setDisabledFlags(mDisabledFlags, true);
     }
 
     public void setDisabledFlags(int disabledFlags) {
@@ -223,13 +239,29 @@
 
         final boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
         final boolean disableRecent = ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
-        final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0);
+        final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0)
+                && ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) == 0);
+        final boolean disableSearch = ((disabledFlags & View.STATUS_BAR_DISABLE_SEARCH) != 0);
 
-        setSlippery(disableHome && disableRecent && disableBack);
+        if (SLIPPERY_WHEN_DISABLED) {
+            setSlippery(disableHome && disableRecent && disableBack && disableSearch);
+        }
+
+        if (!mScreenOn && mCurrentView != null) {
+            ViewGroup navButtons = (ViewGroup) mCurrentView.findViewById(R.id.nav_buttons);
+            LayoutTransition lt = navButtons == null ? null : navButtons.getLayoutTransition();
+            if (lt != null) {
+                lt.disableTransitionType(
+                        LayoutTransition.CHANGE_APPEARING | LayoutTransition.CHANGE_DISAPPEARING |
+                        LayoutTransition.APPEARING | LayoutTransition.DISAPPEARING);
+            }
+        }
 
         getBackButton()   .setVisibility(disableBack       ? View.INVISIBLE : View.VISIBLE);
         getHomeButton()   .setVisibility(disableHome       ? View.INVISIBLE : View.VISIBLE);
         getRecentsButton().setVisibility(disableRecent     ? View.INVISIBLE : View.VISIBLE);
+
+        getSearchLight().setVisibility((disableHome && !disableSearch) ? View.VISIBLE : View.GONE);
     }
 
     public void setSlippery(boolean newSlippery) {
@@ -243,7 +275,8 @@
             } else {
                 return;
             }
-            WindowManagerImpl.getDefault().updateViewLayout(this, lp);
+            WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
+            wm.updateViewLayout(this, lp);
         }
     }
 
@@ -340,15 +373,13 @@
         mCurrentView = mRotatedViews[rot];
         mCurrentView.setVisibility(View.VISIBLE);
 
+        mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
+
         // force the low profile & disabled states into compliance
         setLowProfile(mLowProfile, false, true /* force */);
         setDisabledFlags(mDisabledFlags, true /* force */);
         setMenuVisibility(mShowMenu, true /* force */);
 
-        if (DEBUG_DEADZONE) {
-            mCurrentView.findViewById(R.id.deadzone).setBackgroundColor(0x808080FF);
-        }
-
         if (DEBUG) {
             Slog.d(TAG, "reorient(): rot=" + mDisplay.getRotation());
         }
@@ -431,13 +462,14 @@
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("NavigationBarView {");
         final Rect r = new Rect();
+        final Point size = new Point();
+        mDisplay.getRealSize(size);
 
         pw.println(String.format("      this: " + PhoneStatusBar.viewInfo(this)
                         + " " + visibilityToString(getVisibility())));
 
         getWindowVisibleDisplayFrame(r);
-        final boolean offscreen = r.right > mDisplay.getRawWidth()
-            || r.bottom > mDisplay.getRawHeight();
+        final boolean offscreen = r.right > size.x || r.bottom > size.y;
         pw.println("      window: " 
                 + r.toShortString()
                 + " " + visibilityToString(getWindowVisibility())
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
new file mode 100644
index 0000000..248a516
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Slog;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.GestureRecorder;
+
+public class NotificationPanelView extends PanelView {
+
+    Drawable mHandleBar;
+    float mHandleBarHeight;
+    View mHandleView;
+    int mFingers;
+    PhoneStatusBar mStatusBar;
+    boolean mOkToFlip;
+
+    public NotificationPanelView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public void setStatusBar(PhoneStatusBar bar) {
+        mStatusBar = bar;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        Resources resources = getContext().getResources();
+        mHandleBar = resources.getDrawable(R.drawable.status_bar_close);
+        mHandleBarHeight = resources.getDimension(R.dimen.close_handle_height);
+        mHandleView = findViewById(R.id.handle);
+
+        setContentDescription(resources.getString(R.string.accessibility_desc_notification_shade));
+    }
+
+    @Override
+    public void fling(float vel, boolean always) {
+        GestureRecorder gr = ((PhoneStatusBarView) mBar).mBar.getGestureRecorder();
+        if (gr != null) {
+            gr.tag(
+                "fling " + ((vel > 0) ? "open" : "closed"),
+                "notifications,v=" + vel);
+        }
+        super.fling(vel, always);
+    }
+
+    // We draw the handle ourselves so that it's always glued to the bottom of the window.
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        if (changed) {
+            final int pl = getPaddingLeft();
+            final int pr = getPaddingRight();
+            mHandleBar.setBounds(pl, 0, getWidth() - pr, (int) mHandleBarHeight);
+        }
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        super.draw(canvas);
+        final int off = (int) (getHeight() - mHandleBarHeight - getPaddingBottom());
+        canvas.translate(0, off);
+        mHandleBar.setState(mHandleView.getDrawableState());
+        mHandleBar.draw(canvas);
+        canvas.translate(0, -off);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (PhoneStatusBar.SETTINGS_DRAG_SHORTCUT && mStatusBar.mHasFlipSettings) {
+            switch (event.getActionMasked()) {
+                case MotionEvent.ACTION_DOWN:
+                    mOkToFlip = getExpandedHeight() == 0;
+                    break;
+                case MotionEvent.ACTION_POINTER_DOWN:
+                    if (mOkToFlip) {
+                        float miny = event.getY(0);
+                        float maxy = miny;
+                        for (int i=1; i<event.getPointerCount(); i++) {
+                            final float y = event.getY(i);
+                            if (y < miny) miny = y;
+                            if (y > maxy) maxy = y;
+                        }
+                        if (maxy - miny < mHandleBarHeight) {
+                            if (getMeasuredHeight() < mHandleBarHeight) {
+                                mStatusBar.switchToSettings();
+                            } else {
+                                mStatusBar.flipToSettings();
+                            }
+                            mOkToFlip = false;
+                        }
+                    }
+                    break;
+            }
+        }
+        return mHandleView.dispatchTouchEvent(event);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
new file mode 100644
index 0000000..4b07b00
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import java.util.ArrayList;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Slog;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.FrameLayout;
+
+public class PanelBar extends FrameLayout {
+    public static final boolean DEBUG = false;
+    public static final String TAG = PanelBar.class.getSimpleName();
+    public static final void LOG(String fmt, Object... args) {
+        if (!DEBUG) return;
+        Slog.v(TAG, String.format(fmt, args));
+    }
+
+    public static final int STATE_CLOSED = 0;
+    public static final int STATE_OPENING = 1;
+    public static final int STATE_OPEN = 2;
+
+    PanelHolder mPanelHolder;
+    ArrayList<PanelView> mPanels = new ArrayList<PanelView>();
+    PanelView mTouchingPanel;
+    private int mState = STATE_CLOSED;
+    private boolean mTracking;
+
+    float mPanelExpandedFractionSum;
+
+    public void go(int state) {
+        if (DEBUG) LOG("go state: %d -> %d", mState, state);
+        mState = state;
+    }
+
+    public PanelBar(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+    }
+
+    public void addPanel(PanelView pv) {
+        mPanels.add(pv);
+        pv.setBar(this);
+    }
+
+    public void setPanelHolder(PanelHolder ph) {
+        if (ph == null) {
+            Slog.e(TAG, "setPanelHolder: null PanelHolder", new Throwable());
+            return;
+        }
+        ph.setBar(this);
+        mPanelHolder = ph;
+        final int N = ph.getChildCount();
+        for (int i=0; i<N; i++) {
+            final View v = ph.getChildAt(i);
+            if (v != null && v instanceof PanelView) {
+                addPanel((PanelView) v);
+            }
+        }
+    }
+
+    public float getBarHeight() {
+        return getMeasuredHeight();
+    }
+
+    public PanelView selectPanelForTouch(MotionEvent touch) {
+        final int N = mPanels.size();
+        return mPanels.get((int)(N * touch.getX() / getMeasuredWidth()));
+    }
+
+    public boolean panelsEnabled() {
+        return true;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        // Allow subclasses to implement enable/disable semantics
+        if (!panelsEnabled()) return false;
+
+        // figure out which panel needs to be talked to here
+        if (event.getAction() == MotionEvent.ACTION_DOWN) {
+            final PanelView panel = selectPanelForTouch(event);
+            if (panel == null) {
+                // panel is not there, so we'll eat the gesture
+                if (DEBUG) LOG("PanelBar.onTouch: no panel for x=%d, bailing", event.getX());
+                mTouchingPanel = null;
+                return true;
+            }
+            boolean enabled = panel.isEnabled();
+            if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel,
+                    (enabled ? "" : " (disabled)"));
+            if (!enabled) {
+                // panel is disabled, so we'll eat the gesture
+                mTouchingPanel = null;
+                return true;
+            }
+            startOpeningPanel(panel);
+        }
+        final boolean result = mTouchingPanel != null
+                ? mTouchingPanel.onTouchEvent(event)
+                : true;
+        return result;
+    }
+
+    // called from PanelView when self-expanding, too
+    public void startOpeningPanel(PanelView panel) {
+        if (DEBUG) LOG("startOpeningPanel: " + panel);
+        mTouchingPanel = panel;
+        mPanelHolder.setSelectedPanel(mTouchingPanel);
+        for (PanelView pv : mPanels) {
+            if (pv != panel) {
+                pv.collapse();
+            }
+        }
+    }
+
+    public void panelExpansionChanged(PanelView panel, float frac) {
+        boolean fullyClosed = true;
+        PanelView fullyOpenedPanel = null;
+        if (DEBUG) LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName());
+        mPanelExpandedFractionSum = 0f;
+        for (PanelView pv : mPanels) {
+            final boolean visible = pv.getVisibility() == View.VISIBLE;
+            // adjust any other panels that may be partially visible
+            if (pv.getExpandedHeight() > 0f) {
+                if (mState == STATE_CLOSED) {
+                    go(STATE_OPENING);
+                    onPanelPeeked();
+                }
+                fullyClosed = false;
+                final float thisFrac = pv.getExpandedFraction();
+                mPanelExpandedFractionSum += (visible ? thisFrac : 0);
+                if (DEBUG) LOG("panelExpansionChanged:  -> %s: f=%.1f", pv.getName(), thisFrac);
+                if (panel == pv) {
+                    if (thisFrac == 1f) fullyOpenedPanel = panel;
+                }
+            }
+            if (pv.getExpandedHeight() > 0f) {
+                if (!visible) pv.setVisibility(View.VISIBLE);
+            } else {
+                if (visible) pv.setVisibility(View.GONE);
+            }
+        }
+        mPanelExpandedFractionSum /= mPanels.size();
+        if (fullyOpenedPanel != null && !mTracking) {
+            go(STATE_OPEN);
+            onPanelFullyOpened(fullyOpenedPanel);
+        } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) {
+            go(STATE_CLOSED);
+            onAllPanelsCollapsed();
+        }
+
+        if (DEBUG) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState,
+                (fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":"");
+    }
+
+    public void collapseAllPanels(boolean animate) {
+        boolean waiting = false;
+        for (PanelView pv : mPanels) {
+            if (animate && !pv.isFullyCollapsed()) {
+                pv.collapse();
+                waiting = true;
+            } else {
+                pv.setExpandedFraction(0); // just in case
+                pv.setVisibility(View.GONE);
+            }
+        }
+        if (DEBUG) LOG("collapseAllPanels: animate=%s waiting=%s", animate, waiting);
+        if (!waiting && mState != STATE_CLOSED) {
+            // it's possible that nothing animated, so we replicate the termination 
+            // conditions of panelExpansionChanged here
+            go(STATE_CLOSED);
+            onAllPanelsCollapsed();
+        }
+    }
+
+    public void onPanelPeeked() {
+        if (DEBUG) LOG("onPanelPeeked");
+    }
+
+    public void onAllPanelsCollapsed() {
+        if (DEBUG) LOG("onAllPanelsCollapsed");
+    }
+
+    public void onPanelFullyOpened(PanelView openPanel) {
+        if (DEBUG) LOG("onPanelFullyOpened");
+    }
+
+    public void onTrackingStarted(PanelView panel) {
+        mTracking = true;
+        if (DEBUG && panel != mTouchingPanel) {
+            LOG("shouldn't happen: onTrackingStarted(%s) != mTouchingPanel(%s)",
+                    panel, mTouchingPanel);
+        }
+    }
+
+    public void onTrackingStopped(PanelView panel) {
+        mTracking = false;
+        panelExpansionChanged(panel, panel.getExpandedFraction());
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHolder.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHolder.java
new file mode 100644
index 0000000..8a54347
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHolder.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.FrameLayout;
+
+public class PanelHolder extends FrameLayout {
+
+    private int mSelectedPanelIndex = -1;
+    private PanelBar mBar;
+
+    public PanelHolder(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setChildrenDrawingOrderEnabled(true);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        setChildrenDrawingOrderEnabled(true);
+    }
+
+    public int getPanelIndex(PanelView pv) {
+        final int N = getChildCount();
+        for (int i=0; i<N; i++) {
+            final PanelView v = (PanelView) getChildAt(i);
+            if (pv == v) return i;
+        }
+        return -1;
+    }
+
+    public void setSelectedPanel(PanelView pv) {
+        mSelectedPanelIndex = getPanelIndex(pv);
+    }
+
+    @Override
+    protected int getChildDrawingOrder(int childCount, int i) {
+        if (mSelectedPanelIndex == -1) {
+            return i;
+        } else {
+            if (i == childCount - 1) {
+                return mSelectedPanelIndex;
+            } else if (i >= mSelectedPanelIndex) {
+                return i + 1;
+            } else {
+                return i;
+            }
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                PanelBar.LOG("PanelHolder got touch in open air, closing panels");
+                mBar.collapseAllPanels(true);
+                break;
+        }
+        return false;
+    }
+
+    public void setBar(PanelBar panelBar) {
+        mBar = panelBar;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
new file mode 100644
index 0000000..7035006
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -0,0 +1,507 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.animation.ObjectAnimator;
+import android.animation.TimeAnimator;
+import android.animation.TimeAnimator.TimeListener;
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.util.Slog;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.systemui.R;
+
+public class PanelView extends FrameLayout {
+    public static final boolean DEBUG = PanelBar.DEBUG;
+    public static final String TAG = PanelView.class.getSimpleName();
+    public final void LOG(String fmt, Object... args) {
+        if (!DEBUG) return;
+        Slog.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
+    }
+
+    public static final boolean BRAKES = false;
+    private boolean mRubberbandingEnabled = true;
+
+    private float mSelfExpandVelocityPx; // classic value: 2000px/s
+    private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
+    private float mFlingExpandMinVelocityPx; // classic value: 200px/s
+    private float mFlingCollapseMinVelocityPx; // classic value: 200px/s
+    private float mCollapseMinDisplayFraction; // classic value: 0.08 (25px/min(320px,480px) on G1)
+    private float mExpandMinDisplayFraction; // classic value: 0.5 (drag open halfway to expand)
+    private float mFlingGestureMaxXVelocityPx; // classic value: 150px/s
+
+    private float mFlingGestureMinDistPx;
+
+    private float mExpandAccelPx; // classic value: 2000px/s/s
+    private float mCollapseAccelPx; // classic value: 2000px/s/s (will be negated to collapse "up")
+
+    private float mFlingGestureMaxOutputVelocityPx; // how fast can it really go? (should be a little
+                                                    // faster than mSelfCollapseVelocityPx)
+
+    private float mCollapseBrakingDistancePx = 200; // XXX Resource
+    private float mExpandBrakingDistancePx = 150; // XXX Resource
+    private float mBrakingSpeedPx = 150; // XXX Resource
+
+    private View mHandleView;
+    private float mPeekHeight;
+    private float mTouchOffset;
+    private float mExpandedFraction = 0;
+    private float mExpandedHeight = 0;
+    private boolean mJustPeeked;
+    private boolean mClosing;
+    private boolean mRubberbanding;
+    private boolean mTracking;
+
+    private TimeAnimator mTimeAnimator;
+    private ObjectAnimator mPeekAnimator;
+    private VelocityTracker mVelocityTracker;
+
+    private int[] mAbsPos = new int[2];
+    PanelBar mBar;
+
+    private final TimeListener mAnimationCallback = new TimeListener() {
+        @Override
+        public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
+            animationTick(deltaTime);
+        }
+    };
+
+    private final Runnable mStopAnimator = new Runnable() {
+        @Override
+        public void run() {
+            if (mTimeAnimator != null && mTimeAnimator.isStarted()) {
+                mTimeAnimator.end();
+                mRubberbanding = false;
+                mClosing = false;
+            }
+        }
+    };
+
+    private float mVel, mAccel;
+    private int mFullHeight = 0;
+    private String mViewName;
+    protected float mInitialTouchY;
+    protected float mFinalTouchY;
+
+    public void setRubberbandingEnabled(boolean enable) {
+        mRubberbandingEnabled = enable;
+    }
+
+    private void runPeekAnimation() {
+        if (DEBUG) LOG("peek to height=%.1f", mPeekHeight);
+        if (mTimeAnimator.isStarted()) {
+            return;
+        }
+        if (mPeekAnimator == null) {
+            mPeekAnimator = ObjectAnimator.ofFloat(this, 
+                    "expandedHeight", mPeekHeight)
+                .setDuration(250);
+        }
+        mPeekAnimator.start();
+    }
+
+    private void animationTick(long dtms) {
+        if (!mTimeAnimator.isStarted()) {
+            // XXX HAX to work around bug in TimeAnimator.end() not resetting its last time
+            mTimeAnimator = new TimeAnimator();
+            mTimeAnimator.setTimeListener(mAnimationCallback);
+
+            if (mPeekAnimator != null) mPeekAnimator.cancel();
+
+            mTimeAnimator.start();
+
+            mRubberbanding = mRubberbandingEnabled // is it enabled at all?
+                    && mExpandedHeight > getFullHeight() // are we past the end?
+                    && mVel >= -mFlingGestureMinDistPx; // was this not possibly a "close" gesture?
+            if (mRubberbanding) {
+                mClosing = true;
+            } else if (mVel == 0) {
+                // if the panel is less than halfway open, close it
+                mClosing = (mFinalTouchY / getFullHeight()) < 0.5f;
+            } else {
+                mClosing = mExpandedHeight > 0 && mVel < 0;
+            }
+        } else if (dtms > 0) {
+            final float dt = dtms * 0.001f;                  // ms -> s
+            if (DEBUG) LOG("tick: v=%.2fpx/s dt=%.4fs", mVel, dt);
+            if (DEBUG) LOG("tick: before: h=%d", (int) mExpandedHeight);
+
+            final float fh = getFullHeight();
+            boolean braking = false;
+            if (BRAKES) {
+                if (mClosing) {
+                    braking = mExpandedHeight <= mCollapseBrakingDistancePx;
+                    mAccel = braking ? 10*mCollapseAccelPx : -mCollapseAccelPx;
+                } else {
+                    braking = mExpandedHeight >= (fh-mExpandBrakingDistancePx);
+                    mAccel = braking ? 10*-mExpandAccelPx : mExpandAccelPx;
+                }
+            } else {
+                mAccel = mClosing ? -mCollapseAccelPx : mExpandAccelPx;
+            }
+
+            mVel += mAccel * dt;
+
+            if (braking) {
+                if (mClosing && mVel > -mBrakingSpeedPx) {
+                    mVel = -mBrakingSpeedPx;
+                } else if (!mClosing && mVel < mBrakingSpeedPx) {
+                    mVel = mBrakingSpeedPx;
+                }
+            } else {
+                if (mClosing && mVel > -mFlingCollapseMinVelocityPx) {
+                    mVel = -mFlingCollapseMinVelocityPx;
+                } else if (!mClosing && mVel > mFlingGestureMaxOutputVelocityPx) {
+                    mVel = mFlingGestureMaxOutputVelocityPx;
+                }
+            }
+
+            float h = mExpandedHeight + mVel * dt;
+
+            if (mRubberbanding && h < fh) {
+                h = fh;
+            }
+
+            if (DEBUG) LOG("tick: new h=%d closing=%s", (int) h, mClosing?"true":"false");
+
+            setExpandedHeightInternal(h);
+
+            mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
+
+            if (mVel == 0
+                    || (mClosing && mExpandedHeight == 0)
+                    || ((mRubberbanding || !mClosing) && mExpandedHeight == fh)) {
+                post(mStopAnimator);
+            }
+        }
+    }
+
+    public PanelView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        mTimeAnimator = new TimeAnimator();
+        mTimeAnimator.setTimeListener(mAnimationCallback);
+    }
+
+    private void loadDimens() {
+        final Resources res = getContext().getResources();
+
+        mSelfExpandVelocityPx = res.getDimension(R.dimen.self_expand_velocity);
+        mSelfCollapseVelocityPx = res.getDimension(R.dimen.self_collapse_velocity);
+        mFlingExpandMinVelocityPx = res.getDimension(R.dimen.fling_expand_min_velocity);
+        mFlingCollapseMinVelocityPx = res.getDimension(R.dimen.fling_collapse_min_velocity);
+
+        mFlingGestureMinDistPx = res.getDimension(R.dimen.fling_gesture_min_dist);
+
+        mCollapseMinDisplayFraction = res.getFraction(R.dimen.collapse_min_display_fraction, 1, 1);
+        mExpandMinDisplayFraction = res.getFraction(R.dimen.expand_min_display_fraction, 1, 1);
+
+        mExpandAccelPx = res.getDimension(R.dimen.expand_accel);
+        mCollapseAccelPx = res.getDimension(R.dimen.collapse_accel);
+
+        mFlingGestureMaxXVelocityPx = res.getDimension(R.dimen.fling_gesture_max_x_velocity);
+
+        mFlingGestureMaxOutputVelocityPx = res.getDimension(R.dimen.fling_gesture_max_output_velocity);
+
+        mPeekHeight = res.getDimension(R.dimen.peek_height) 
+            + getPaddingBottom() // our window might have a dropshadow
+            - (mHandleView == null ? 0 : mHandleView.getPaddingTop()); // the handle might have a topshadow
+    }
+
+    private void trackMovement(MotionEvent event) {
+        // Add movement to velocity tracker using raw screen X and Y coordinates instead
+        // of window coordinates because the window frame may be moving at the same time.
+        float deltaX = event.getRawX() - event.getX();
+        float deltaY = event.getRawY() - event.getY();
+        event.offsetLocation(deltaX, deltaY);
+        if (mVelocityTracker != null) mVelocityTracker.addMovement(event);
+        event.offsetLocation(-deltaX, -deltaY);
+    }
+
+    // Pass all touches along to the handle, allowing the user to drag the panel closed from its interior
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        return mHandleView.dispatchTouchEvent(event);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mHandleView = findViewById(R.id.handle);
+
+        loadDimens();
+
+        if (DEBUG) LOG("handle view: " + mHandleView);
+        if (mHandleView != null) {
+            mHandleView.setOnTouchListener(new View.OnTouchListener() {
+                @Override
+                public boolean onTouch(View v, MotionEvent event) {
+                    final float y = event.getY();
+                    final float rawY = event.getRawY();
+                    if (DEBUG) LOG("handle.onTouch: a=%s y=%.1f rawY=%.1f off=%.1f",
+                            MotionEvent.actionToString(event.getAction()),
+                            y, rawY, mTouchOffset);
+                    PanelView.this.getLocationOnScreen(mAbsPos);
+
+                    switch (event.getAction()) {
+                        case MotionEvent.ACTION_DOWN:
+                            mTracking = true;
+                            mHandleView.setPressed(true);
+                            postInvalidate(); // catch the press state change
+                            mInitialTouchY = y;
+                            mVelocityTracker = VelocityTracker.obtain();
+                            trackMovement(event);
+                            mTimeAnimator.cancel(); // end any outstanding animations
+                            mBar.onTrackingStarted(PanelView.this);
+                            mTouchOffset = (rawY - mAbsPos[1]) - PanelView.this.getExpandedHeight();
+                            if (mExpandedHeight == 0) {
+                                mJustPeeked = true;
+                                runPeekAnimation();
+                            }
+                            break;
+
+                        case MotionEvent.ACTION_MOVE:
+                            final float h = rawY - mAbsPos[1] - mTouchOffset;
+                            if (h > mPeekHeight) {
+                                if (mPeekAnimator != null && mPeekAnimator.isRunning()) {
+                                    mPeekAnimator.cancel();
+                                }
+                                mJustPeeked = false;
+                            }
+                            if (!mJustPeeked) {
+                                PanelView.this.setExpandedHeightInternal(h);
+                                mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
+                            }
+
+                            trackMovement(event);
+                            break;
+
+                        case MotionEvent.ACTION_UP:
+                        case MotionEvent.ACTION_CANCEL:
+                            mFinalTouchY = y;
+                            mTracking = false;
+                            mHandleView.setPressed(false);
+                            postInvalidate(); // catch the press state change
+                            mBar.onTrackingStopped(PanelView.this);
+                            trackMovement(event);
+
+                            float vel = 0, yVel = 0, xVel = 0;
+                            boolean negative = false;
+
+                            if (mVelocityTracker != null) {
+                                // the velocitytracker might be null if we got a bad input stream
+                                mVelocityTracker.computeCurrentVelocity(1000);
+
+                                yVel = mVelocityTracker.getYVelocity();
+                                negative = yVel < 0;
+
+                                xVel = mVelocityTracker.getXVelocity();
+                                if (xVel < 0) {
+                                    xVel = -xVel;
+                                }
+                                if (xVel > mFlingGestureMaxXVelocityPx) {
+                                    xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
+                                }
+
+                                vel = (float)Math.hypot(yVel, xVel);
+                                if (vel > mFlingGestureMaxOutputVelocityPx) {
+                                    vel = mFlingGestureMaxOutputVelocityPx;
+                                }
+
+                                mVelocityTracker.recycle();
+                                mVelocityTracker = null;
+                            }
+
+                            // if you've barely moved your finger, we treat the velocity as 0
+                            // preventing spurious flings due to touch screen jitter
+                            final float deltaY = Math.abs(mFinalTouchY - mInitialTouchY);
+                            if (deltaY < mFlingGestureMinDistPx
+                                    || vel < mFlingExpandMinVelocityPx
+                                    ) {
+                                vel = 0;
+                            }
+
+                            if (negative) {
+                                vel = -vel;
+                            }
+
+                            if (DEBUG) LOG("gesture: dy=%f vel=(%f,%f) vlinear=%f",
+                                    deltaY,
+                                    xVel, yVel,
+                                    vel);
+
+                            fling(vel, true);
+
+                            break;
+                    }
+                    return true;
+                }});
+        }
+    }
+
+    public void fling(float vel, boolean always) {
+        if (DEBUG) LOG("fling: vel=%.3f, this=%s", vel, this);
+        mVel = vel;
+
+        if (always||mVel != 0) {
+            animationTick(0); // begin the animation
+        }
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mViewName = getResources().getResourceName(getId());
+    }
+
+    public String getName() {
+        return mViewName;
+    }
+
+    @Override
+    protected void onViewAdded(View child) {
+        if (DEBUG) LOG("onViewAdded: " + child);
+    }
+
+    public View getHandle() {
+        return mHandleView;
+    }
+
+    // Rubberbands the panel to hold its contents.
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+        if (DEBUG) LOG("onMeasure(%d, %d) -> (%d, %d)",
+                widthMeasureSpec, heightMeasureSpec, getMeasuredWidth(), getMeasuredHeight());
+
+        // Did one of our children change size?
+        int newHeight = getMeasuredHeight();
+        if (newHeight != mFullHeight) {
+            mFullHeight = newHeight;
+            // If the user isn't actively poking us, let's rubberband to the content
+            if (!mTracking && !mRubberbanding && !mTimeAnimator.isStarted()
+                    && mExpandedHeight > 0 && mExpandedHeight != mFullHeight) {
+                mExpandedHeight = mFullHeight;
+            }
+        }
+        heightMeasureSpec = MeasureSpec.makeMeasureSpec(
+                    (int) mExpandedHeight, MeasureSpec.AT_MOST); // MeasureSpec.getMode(heightMeasureSpec));
+        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
+    }
+
+
+    public void setExpandedHeight(float height) {
+        if (DEBUG) LOG("setExpandedHeight(%.1f)", height);
+        mRubberbanding = false;
+        if (mTimeAnimator.isRunning()) {
+            post(mStopAnimator);
+        }
+        setExpandedHeightInternal(height);
+        mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
+    }
+
+    @Override
+    protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
+        if (DEBUG) LOG("onLayout: changed=%s, bottom=%d eh=%d fh=%d", changed?"T":"f", bottom, (int)mExpandedHeight, mFullHeight);
+        super.onLayout(changed, left, top, right, bottom);
+    }
+
+    public void setExpandedHeightInternal(float h) {
+        float fh = getFullHeight();
+        if (fh == 0) {
+            // Hmm, full height hasn't been computed yet
+        }
+
+        if (h < 0) h = 0;
+        if (!(mRubberbandingEnabled && (mTracking || mRubberbanding)) && h > fh) h = fh;
+        mExpandedHeight = h;
+
+        if (DEBUG) LOG("setExpansion: height=%.1f fh=%.1f tracking=%s rubber=%s", h, fh, mTracking?"T":"f", mRubberbanding?"T":"f");
+
+        requestLayout();
+//        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
+//        lp.height = (int) mExpandedHeight;
+//        setLayoutParams(lp);
+
+        mExpandedFraction = Math.min(1f, (fh == 0) ? 0 : h / fh);
+    }
+
+    private float getFullHeight() {
+        if (mFullHeight <= 0) {
+            if (DEBUG) LOG("Forcing measure() since fullHeight=" + mFullHeight);
+            measure(MeasureSpec.makeMeasureSpec(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY));
+        }
+        return mFullHeight;
+    }
+
+    public void setExpandedFraction(float frac) {
+        setExpandedHeight(getFullHeight() * frac);
+    }
+
+    public float getExpandedHeight() {
+        return mExpandedHeight;
+    }
+
+    public float getExpandedFraction() {
+        return mExpandedFraction;
+    }
+
+    public boolean isFullyExpanded() {
+        return mExpandedHeight >= getFullHeight();
+    }
+
+    public boolean isFullyCollapsed() {
+        return mExpandedHeight <= 0;
+    }
+
+    public boolean isCollapsing() {
+        return mClosing;
+    }
+
+    public void setBar(PanelBar panelBar) {
+        mBar = panelBar;
+    }
+
+    public void collapse() {
+        // TODO: abort animation or ongoing touch
+        if (DEBUG) LOG("collapse: " + this);
+        if (!isFullyCollapsed()) {
+            mTimeAnimator.cancel();
+            mClosing = true;
+            // collapse() should never be a rubberband, even if an animation is already running
+            mRubberbanding = false;
+            fling(-mSelfCollapseVelocityPx, /*always=*/ true);
+        }
+    }
+
+    public void expand() {
+        if (DEBUG) LOG("expand: " + this);
+        if (isFullyCollapsed()) {
+            mBar.startOpeningPanel(this);
+            fling(mSelfExpandVelocityPx, /*always=*/ true);
+        } else if (DEBUG) {
+            if (DEBUG) LOG("skipping expansion: is expanded");
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 2f22cae..7371ce2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -17,14 +17,12 @@
 package com.android.systemui.statusbar.phone;
 
 import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
-import android.app.Dialog;
-import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
@@ -32,37 +30,40 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.res.Configuration;
+import android.content.SharedPreferences;
 import android.content.res.Resources;
+import android.database.ContentObserver;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.PixelFormat;
+import android.graphics.Point;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.NinePatchDrawable;
 import android.inputmethodservice.InputMethodService;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.provider.Settings;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.Slog;
-import android.view.Choreographer;
 import android.view.Display;
 import android.view.Gravity;
-import android.view.IWindowManager;
-import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
+import android.view.ViewPropertyAnimator;
+import android.view.ViewStub;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
@@ -72,24 +73,26 @@
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
 import android.widget.TextView;
+
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarNotification;
 import com.android.systemui.R;
-import com.android.systemui.recent.RecentTasksLoader;
 import com.android.systemui.statusbar.BaseStatusBar;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.NotificationData.Entry;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.RotationToggle;
 import com.android.systemui.statusbar.SignalClusterView;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.DateView;
 import com.android.systemui.statusbar.policy.IntruderAlertView;
 import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.OnSizeChangedListener;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NotificationRowLayout;
+import com.android.systemui.statusbar.policy.OnSizeChangedListener;
+import com.android.systemui.statusbar.policy.Prefs;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -97,9 +100,16 @@
 
 public class PhoneStatusBar extends BaseStatusBar {
     static final String TAG = "PhoneStatusBar";
-    public static final boolean DEBUG = false;
+    public static final boolean DEBUG = BaseStatusBar.DEBUG;
     public static final boolean SPEW = DEBUG;
     public static final boolean DUMPTRUCK = true; // extra dumpsys info
+    public static final boolean DEBUG_GESTURES = false;
+
+    public static final boolean DEBUG_CLINGS = false;
+
+    public static final boolean ENABLE_NOTIFICATION_PANEL_CLING = false;
+
+    public static final boolean SETTINGS_DRAG_SHORTCUT = true;
 
     // additional instrumentation for testing purposes; intended to be left on during development
     public static final boolean CHATTY = DEBUG;
@@ -107,11 +117,9 @@
     public static final String ACTION_STATUSBAR_START
             = "com.android.internal.policy.statusbar.START";
 
-    private static final boolean DIM_BEHIND_EXPANDED_PANEL = true;
-    private static final boolean SHOW_CARRIER_LABEL = true;
-
     private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
-    private static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
+    private static final int MSG_CLOSE_PANELS = 1001;
+    private static final int MSG_OPEN_SETTINGS_PANEL = 1002;
     // 1020-1030 reserved for BaseStatusBar
 
     // will likely move to a resource or other tunable param at some point
@@ -140,6 +148,7 @@
     PhoneStatusBarPolicy mIconPolicy;
 
     // These are no longer handled by the policy, because we need custom strategies for them
+    BluetoothController mBluetoothController;
     BatteryController mBatteryController;
     LocationController mLocationController;
     NetworkController mNetworkController;
@@ -148,8 +157,9 @@
     int mIconSize = -1;
     int mIconHPadding = -1;
     Display mDisplay;
+    Point mCurrentDisplaySize = new Point();
 
-    IWindowManager mWindowManager;
+    IDreamManager mDreamManager;
 
     StatusBarWindowView mStatusBarWindow;
     PhoneStatusBarView mStatusBarView;
@@ -157,40 +167,54 @@
     int mPixelFormat;
     Object mQueueLock = new Object();
 
-    // icons
-    LinearLayout mIcons;
-    IconMerger mNotificationIcons;
-    View mMoreIcon;
+    // viewgroup containing the normal contents of the statusbar
+    LinearLayout mStatusBarContents;
+    
+    // right-hand icons
+    LinearLayout mSystemIconArea;
+    
+    // left-hand icons 
     LinearLayout mStatusIcons;
+    // the icons themselves
+    IconMerger mNotificationIcons;
+    // [+>
+    View mMoreIcon;
 
     // expanded notifications
-    View mNotificationPanel; // the sliding/resizing panel within the notification window
+    NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
     ScrollView mScrollView;
     View mExpandedContents;
-    int mNotificationPanelMarginBottomPx, mNotificationPanelMarginLeftPx;
-    final Rect mNotificationPanelBackgroundPadding = new Rect();
     int mNotificationPanelGravity;
-    int mNotificationPanelMinHeight;
+    int mNotificationPanelMarginBottomPx, mNotificationPanelMarginPx;
+    float mNotificationPanelMinHeightFrac;
     boolean mNotificationPanelIsFullScreenWidth;
+    TextView mNotificationPanelDebugText;
+
+    // settings
+    QuickSettings mQS;
+    boolean mHasSettingsPanel, mHasFlipSettings;
+    SettingsPanelView mSettingsPanel;
+    View mFlipSettingsView;
+    QuickSettingsContainerView mSettingsContainer;
+    int mSettingsPanelGravity;
 
     // top bar
+    View mNotificationPanelHeader;
+    View mDateTimeView; 
     View mClearButton;
-    View mSettingsButton;
-    RotationToggle mRotationButton;
+    ImageView mSettingsButton, mNotificationButton;
 
     // carrier/wifi label
     private TextView mCarrierLabel;
     private boolean mCarrierLabelVisible = false;
     private int mCarrierLabelHeight;
     private TextView mEmergencyCallLabel;
+    private int mNotificationHeaderHeight;
 
-    // drag bar
-    CloseDragHandle mCloseView;
-    private int mCloseViewHeight;
+    private boolean mShowCarrierInPanel = false;
 
     // position
     int[] mPositionTmp = new int[2];
-    boolean mExpanded;
     boolean mExpandedVisible;
 
     // the date view
@@ -215,7 +239,11 @@
     boolean mTracking;
     VelocityTracker mVelocityTracker;
 
-    Choreographer mChoreographer;
+    // help screen
+    private boolean mClingShown;
+    private ViewGroup mCling;
+    private boolean mSuppressStatusBarDrags; // while a cling is up, briefly deaden the bar to give things time to settle
+
     boolean mAnimating;
     boolean mClosing; // only valid when mAnimating; indicates the initial acceleration
     float mAnimY;
@@ -229,8 +257,8 @@
     int[] mAbsPos = new int[2];
     Runnable mPostCollapseCleanup = null;
 
-    private AnimatorSet mLightsOutAnimation;
-    private AnimatorSet mLightsOnAnimation;
+    private Animator mLightsOutAnimation;
+    private Animator mLightsOnAnimation;
 
     // for disabling the status bar
     int mDisabled = 0;
@@ -240,78 +268,57 @@
 
     DisplayMetrics mDisplayMetrics = new DisplayMetrics();
 
+    // XXX: gesture research
+    private final GestureRecorder mGestureRec = DEBUG_GESTURES
+        ? new GestureRecorder("/sdcard/statusbar_gestures.dat") 
+        : null;
+
     private int mNavigationIconHints = 0;
     private final Animator.AnimatorListener mMakeIconsInvisible = new AnimatorListenerAdapter() {
         @Override
         public void onAnimationEnd(Animator animation) {
             // double-check to avoid races
-            if (mIcons.getAlpha() == 0) {
-                Slog.d(TAG, "makeIconsInvisible");
-                mIcons.setVisibility(View.INVISIBLE);
+            if (mStatusBarContents.getAlpha() == 0) {
+                if (DEBUG) Slog.d(TAG, "makeIconsInvisible");
+                mStatusBarContents.setVisibility(View.INVISIBLE);
             }
         }
     };
 
-    private final Runnable mStartRevealAnimation = new Runnable() {
+    // ensure quick settings is disabled until the current user makes it through the setup wizard
+    private boolean mUserSetup = false;
+    private ContentObserver mUserSetupObserver = new ContentObserver(new Handler()) {
         @Override
-        public void run() {
-            mAnimAccel = mExpandAccelPx;
-            mAnimVel = mFlingExpandMinVelocityPx;
-            mAnimY = getStatusBarHeight();
-            updateExpandedViewPos((int)mAnimY);
-
-            mAnimating = true;
-            mAnimatingReveal = true;
-            resetLastAnimTime();
-            mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
-                mAnimationCallback, null);
-            mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
-                mRevealAnimationCallback, null);
-            mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
-                mRevealAnimationCallback, null);
-        }
-    };
-
-    private final Runnable mPerformSelfExpandFling = new Runnable() {
-        @Override
-        public void run() {
-            performFling(0, mSelfExpandVelocityPx, true);
-        }
-    };
-
-    private final Runnable mPerformFling = new Runnable() {
-        @Override
-        public void run() {
-            performFling(mFlingY + mViewDelta, mFlingVelocity, false);
-        }
-    };
-
-    private class ExpandedDialog extends Dialog {
-        ExpandedDialog(Context context) {
-            super(context, com.android.internal.R.style.Theme_Translucent_NoTitleBar);
-        }
-
-        @Override
-        public boolean dispatchKeyEvent(KeyEvent event) {
-            boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
-            switch (event.getKeyCode()) {
-            case KeyEvent.KEYCODE_BACK:
-                if (!down) {
-                    animateCollapse();
-                }
-                return true;
+        public void onChange(boolean selfChange) {
+            final boolean userSetup = 0 != Settings.Secure.getIntForUser(
+                    mContext.getContentResolver(),
+                    Settings.Secure.USER_SETUP_COMPLETE,
+                    0 /*default */,
+                    mCurrentUserId);
+            if (MULTIUSER_DEBUG) Slog.d(TAG, String.format("User setup changed: " +
+                    "selfChange=%s userSetup=%s mUserSetup=%s",
+                    selfChange, userSetup, mUserSetup));
+            if (mSettingsButton != null && !mHasSettingsPanel) {
+                mSettingsButton.setVisibility(userSetup ? View.VISIBLE : View.INVISIBLE);
             }
-            return super.dispatchKeyEvent(event);
+            if (mSettingsPanel != null) {
+                mSettingsPanel.setEnabled(userSetup);
+            }
+            if (userSetup != mUserSetup) {
+                mUserSetup = userSetup;
+                if (!mUserSetup && mStatusBarView != null)
+                    animateCollapseQuickSettings();
+            }
         }
-    }
+    };
 
     @Override
     public void start() {
         mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
                 .getDefaultDisplay();
 
-        mWindowManager = IWindowManager.Stub.asInterface(
-                ServiceManager.getService(Context.WINDOW_SERVICE));
+        mDreamManager = IDreamManager.Stub.asInterface(
+                ServiceManager.checkService(DreamService.DREAM_SERVICE));
 
         super.start(); // calls createAndAddWindows()
 
@@ -338,37 +345,40 @@
 
         mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
                 R.layout.super_status_bar, null);
-        if (DEBUG) {
-            mStatusBarWindow.setBackgroundColor(0x6000FF80);
-        }
         mStatusBarWindow.mService = this;
         mStatusBarWindow.setOnTouchListener(new View.OnTouchListener() {
             @Override
             public boolean onTouch(View v, MotionEvent event) {
                 if (event.getAction() == MotionEvent.ACTION_DOWN) {
-                    if (mExpanded && !mAnimating) {
-                        animateCollapse();
+                    if (mExpandedVisible && !mAnimating) {
+                        animateCollapsePanels();
                     }
                 }
                 return mStatusBarWindow.onTouchEvent(event);
             }});
 
         mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
-        mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel);
-        // don't allow clicks on the panel to pass through to the background where they will cause the panel to close
-        mNotificationPanel.setOnTouchListener(new View.OnTouchListener() {
-            @Override
-            public boolean onTouch(View v, MotionEvent event) {
-                return true;
-            }
-        });
+        mStatusBarView.setBar(this);
+        
+
+        PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder);
+        mStatusBarView.setPanelHolder(holder);
+
+        mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(R.id.notification_panel);
+        mNotificationPanel.setStatusBar(this);
         mNotificationPanelIsFullScreenWidth =
             (mNotificationPanel.getLayoutParams().width == ViewGroup.LayoutParams.MATCH_PARENT);
-        mNotificationPanel.setSystemUiVisibility(
-                  View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER
-                | (mNotificationPanelIsFullScreenWidth ? 0 : View.STATUS_BAR_DISABLE_SYSTEM_INFO));
 
-        if (!ActivityManager.isHighEndGfx(mDisplay)) {
+        // make the header non-responsive to clicks
+        mNotificationPanel.findViewById(R.id.header).setOnTouchListener(
+                new View.OnTouchListener() {
+                    @Override
+                    public boolean onTouch(View v, MotionEvent event) {
+                        return true; // e eats everything
+                    }
+                });
+
+        if (!ActivityManager.isHighEndGfx()) {
             mStatusBarWindow.setBackground(null);
             mNotificationPanel.setBackground(new FastColorDrawable(context.getResources().getColor(
                     R.color.notification_panel_solid_background)));
@@ -378,15 +388,15 @@
             mIntruderAlertView.setVisibility(View.GONE);
             mIntruderAlertView.setBar(this);
         }
+        if (MULTIUSER_DEBUG) {
+            mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(R.id.header_debug_info);
+            mNotificationPanelDebugText.setVisibility(View.VISIBLE);
+        }
 
         updateShowSearchHoldoff();
 
-        mStatusBarView.mService = this;
-
-        mChoreographer = Choreographer.getInstance();
-
         try {
-            boolean showNav = mWindowManager.hasNavigationBar();
+            boolean showNav = mWindowManagerService.hasNavigationBar();
             if (DEBUG) Slog.v(TAG, "hasNavigationBar=" + showNav);
             if (showNav) {
                 mNavigationBarView =
@@ -401,10 +411,12 @@
 
         // figure out which pixel-format to use for the status bar.
         mPixelFormat = PixelFormat.OPAQUE;
+
+        mSystemIconArea = (LinearLayout) mStatusBarView.findViewById(R.id.system_icon_area);
         mStatusIcons = (LinearLayout)mStatusBarView.findViewById(R.id.statusIcons);
         mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons);
         mNotificationIcons.setOverflowIndicator(mMoreIcon);
-        mIcons = (LinearLayout)mStatusBarView.findViewById(R.id.icons);
+        mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents);
         mTickerView = mStatusBarView.findViewById(R.id.ticker);
 
         mPile = (NotificationRowLayout)mStatusBarWindow.findViewById(R.id.latestItems);
@@ -412,28 +424,67 @@
         mPile.setLongPressListener(getNotificationLongClicker());
         mExpandedContents = mPile; // was: expanded.findViewById(R.id.notificationLinearLayout);
 
+        mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header);
+
         mClearButton = mStatusBarWindow.findViewById(R.id.clear_all_button);
         mClearButton.setOnClickListener(mClearButtonListener);
         mClearButton.setAlpha(0f);
         mClearButton.setVisibility(View.INVISIBLE);
         mClearButton.setEnabled(false);
         mDateView = (DateView)mStatusBarWindow.findViewById(R.id.date);
-        mSettingsButton = mStatusBarWindow.findViewById(R.id.settings_button);
-        mSettingsButton.setOnClickListener(mSettingsButtonListener);
-        mRotationButton = (RotationToggle) mStatusBarWindow.findViewById(R.id.rotation_lock_button);
-        
+
+        mHasSettingsPanel = res.getBoolean(R.bool.config_hasSettingsPanel);
+        mHasFlipSettings = res.getBoolean(R.bool.config_hasFlipSettingsPanel);
+
+        mDateTimeView = mNotificationPanelHeader.findViewById(R.id.datetime);
+        if (mHasFlipSettings) {
+            mDateTimeView.setOnClickListener(mClockClickListener);
+            mDateTimeView.setEnabled(true);
+        }
+
+        mSettingsButton = (ImageView) mStatusBarWindow.findViewById(R.id.settings_button);
+        if (mSettingsButton != null) {
+            mSettingsButton.setOnClickListener(mSettingsButtonListener);
+            if (mHasSettingsPanel) {
+                if (mStatusBarView.hasFullWidthNotifications()) {
+                    // the settings panel is hiding behind this button
+                    mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
+                    mSettingsButton.setVisibility(View.VISIBLE);
+                } else {
+                    // there is a settings panel, but it's on the other side of the (large) screen
+                    final View buttonHolder = mStatusBarWindow.findViewById(
+                            R.id.settings_button_holder);
+                    if (buttonHolder != null) {
+                        buttonHolder.setVisibility(View.GONE);
+                    }
+                }
+            } else {
+                // no settings panel, go straight to settings
+                mSettingsButton.setVisibility(View.VISIBLE);
+                mSettingsButton.setImageResource(R.drawable.ic_notify_settings);
+            }
+        }
+        if (mHasFlipSettings) {
+            mNotificationButton = (ImageView) mStatusBarWindow.findViewById(R.id.notification_button);
+            if (mNotificationButton != null) {
+                mNotificationButton.setOnClickListener(mNotificationButtonListener);
+            }
+        }
+
         mScrollView = (ScrollView)mStatusBarWindow.findViewById(R.id.scroll);
         mScrollView.setVerticalScrollBarEnabled(false); // less drawing during pulldowns
+        if (!mNotificationPanelIsFullScreenWidth) {
+            mScrollView.setSystemUiVisibility(
+                    View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER |
+                    View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS |
+                    View.STATUS_BAR_DISABLE_CLOCK);
+        }
 
         mTicker = new MyTicker(context, mStatusBarView);
 
         TickerView tickerView = (TickerView)mStatusBarView.findViewById(R.id.tickerText);
         tickerView.mTicker = mTicker;
 
-        mCloseView = (CloseDragHandle)mStatusBarWindow.findViewById(R.id.close);
-        mCloseView.mService = this;
-        mCloseViewHeight = res.getDimensionPixelSize(R.dimen.close_handle_height);
-
         mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
 
         // set the inital view visibility
@@ -444,15 +495,19 @@
         mBatteryController = new BatteryController(mContext);
         mBatteryController.addIconView((ImageView)mStatusBarView.findViewById(R.id.battery));
         mNetworkController = new NetworkController(mContext);
+        mBluetoothController = new BluetoothController(mContext);
         final SignalClusterView signalCluster =
                 (SignalClusterView)mStatusBarView.findViewById(R.id.signal_cluster);
 
+
         mNetworkController.addSignalCluster(signalCluster);
         signalCluster.setNetworkController(mNetworkController);
 
         mEmergencyCallLabel = (TextView)mStatusBarWindow.findViewById(R.id.emergency_calls_only);
         if (mEmergencyCallLabel != null) {
             mNetworkController.addEmergencyLabelView(mEmergencyCallLabel);
+            mEmergencyCallLabel.setOnClickListener(new View.OnClickListener() {
+                public void onClick(View v) { }});
             mEmergencyCallLabel.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
                 @Override
                 public void onLayoutChange(View v, int left, int top, int right, int bottom,
@@ -461,8 +516,10 @@
                 }});
         }
 
-        if (SHOW_CARRIER_LABEL) {
-            mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label);
+        mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label);
+        mShowCarrierInPanel = (mCarrierLabel != null);
+        if (DEBUG) Slog.v(TAG, "carrierlabel=" + mCarrierLabel + " show=" + mShowCarrierInPanel);
+        if (mShowCarrierInPanel) {
             mCarrierLabel.setVisibility(mCarrierLabelVisible ? View.VISIBLE : View.INVISIBLE);
 
             // for mobile devices, we always show mobile connection info here (SPN/PLMN)
@@ -482,22 +539,86 @@
             });
         }
 
+        // Quick Settings (where available, some restrictions apply)
+        if (mHasSettingsPanel) {
+            // first, figure out where quick settings should be inflated
+            final View settings_stub;
+            if (mHasFlipSettings) {
+                // a version of quick settings that flips around behind the notifications
+                settings_stub = mStatusBarWindow.findViewById(R.id.flip_settings_stub);
+                if (settings_stub != null) {
+                    mFlipSettingsView = ((ViewStub)settings_stub).inflate();
+                    mFlipSettingsView.setVisibility(View.GONE);
+                    mFlipSettingsView.setVerticalScrollBarEnabled(false);
+                }
+            } else {
+                // full quick settings panel
+                settings_stub = mStatusBarWindow.findViewById(R.id.quick_settings_stub);
+                if (settings_stub != null) {
+                    mSettingsPanel = (SettingsPanelView) ((ViewStub)settings_stub).inflate();
+                } else {
+                    mSettingsPanel = (SettingsPanelView) mStatusBarWindow.findViewById(R.id.settings_panel);
+                }
+
+                if (mSettingsPanel != null) {
+                    if (!ActivityManager.isHighEndGfx()) {
+                        mSettingsPanel.setBackground(new FastColorDrawable(context.getResources().getColor(
+                                R.color.notification_panel_solid_background)));
+                    }
+                }
+            }
+
+            // wherever you find it, Quick Settings needs a container to survive
+            mSettingsContainer = (QuickSettingsContainerView)
+                    mStatusBarWindow.findViewById(R.id.quick_settings_container);
+            if (mSettingsContainer != null) {
+                mQS = new QuickSettings(mContext, mSettingsContainer);
+                if (!mNotificationPanelIsFullScreenWidth) {
+                    mSettingsContainer.setSystemUiVisibility(
+                            View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER
+                            | View.STATUS_BAR_DISABLE_SYSTEM_INFO);
+                }
+                if (mSettingsPanel != null) {
+                    mSettingsPanel.setQuickSettings(mQS);
+                }
+                mQS.setService(this);
+                mQS.setBar(mStatusBarView);
+                mQS.setup(mNetworkController, mBluetoothController, mBatteryController,
+                        mLocationController);
+            } else {
+                mQS = null; // fly away, be free
+            }
+        }
+
+        mClingShown = ! (DEBUG_CLINGS 
+            || !Prefs.read(mContext).getBoolean(Prefs.SHOWN_QUICK_SETTINGS_HELP, false));
+
+        if (!ENABLE_NOTIFICATION_PANEL_CLING || ActivityManager.isRunningInTestHarness()) {
+            mClingShown = true;
+        }
+
 //        final ImageView wimaxRSSI =
 //                (ImageView)sb.findViewById(R.id.wimax_signal);
 //        if (wimaxRSSI != null) {
 //            mNetworkController.addWimaxIconView(wimaxRSSI);
 //        }
-        // Recents Panel
-        mRecentTasksLoader = new RecentTasksLoader(context);
-        updateRecentsPanel();
 
         // receive broadcasts
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
         filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
         filter.addAction(Intent.ACTION_SCREEN_OFF);
+        filter.addAction(Intent.ACTION_SCREEN_ON);
         context.registerReceiver(mBroadcastReceiver, filter);
 
+        // listen for USER_SETUP_COMPLETE setting (per-user)
+        resetUserSetupObserver();
+
+        return mStatusBarView;
+    }
+
+    @Override
+    protected View getStatusBarView() {
         return mStatusBarView;
     }
 
@@ -512,7 +633,7 @@
                 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
                 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
-        if (ActivityManager.isHighEndGfx(mDisplay)) {
+        if (ActivityManager.isHighEndGfx()) {
             lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
         } else {
             lp.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
@@ -537,7 +658,7 @@
                 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
                 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
-        if (ActivityManager.isHighEndGfx(mDisplay)) {
+        if (ActivityManager.isHighEndGfx()) {
             lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
         }
         lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
@@ -549,17 +670,6 @@
         return lp;
     }
 
-    protected void updateRecentsPanel() {
-        super.updateRecentsPanel(R.layout.status_bar_recent_panel);
-        // Make .03 alpha the minimum so you always see the item a bit-- slightly below
-        // .03, the item disappears entirely (as if alpha = 0) and that discontinuity looks
-        // a bit jarring
-        mRecentsPanel.setMinSwipeAlpha(0.03f);
-        if (mNavigationBarView != null) {
-            mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPanel);
-        }
-    }
-
     @Override
     protected void updateSearchPanel() {
         super.updateSearchPanel();
@@ -570,10 +680,15 @@
     @Override
     public void showSearchPanel() {
         super.showSearchPanel();
+        mHandler.removeCallbacks(mShowSearchPanel);
+
+        // we want to freeze the sysui state wherever it is
+        mSearchPanelView.setSystemUiVisibility(mSystemUiVisibility);
+
         WindowManager.LayoutParams lp =
             (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
         lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-        WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp);
+        mWindowManager.updateViewLayout(mNavigationBarView, lp);
     }
 
     @Override
@@ -582,7 +697,7 @@
         WindowManager.LayoutParams lp =
             (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
         lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-        WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp);
+        mWindowManager.updateViewLayout(mNavigationBarView, lp);
     }
 
     protected int getStatusBarGravity() {
@@ -598,10 +713,6 @@
         return mNaturalBarHeight;
     }
 
-    private int getCloseViewHeight() {
-        return mCloseViewHeight;
-    }
-
     private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
         public void onClick(View v) {
             toggleRecentApps();
@@ -612,6 +723,7 @@
     private Runnable mShowSearchPanel = new Runnable() {
         public void run() {
             showSearchPanel();
+            awakenDreams();
         }
     };
 
@@ -619,7 +731,7 @@
         public boolean onTouch(View v, MotionEvent event) {
             switch(event.getAction()) {
             case MotionEvent.ACTION_DOWN:
-                if (!shouldDisableNavbarGestures() && !inKeyguardRestrictedInputMode()) {
+                if (!shouldDisableNavbarGestures()) {
                     mHandler.removeCallbacks(mShowSearchPanel);
                     mHandler.postDelayed(mShowSearchPanel, mShowSearchHoldoff);
                 }
@@ -628,18 +740,30 @@
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_CANCEL:
                 mHandler.removeCallbacks(mShowSearchPanel);
+                awakenDreams();
             break;
         }
         return false;
         }
     };
 
+    private void awakenDreams() {
+        if (mDreamManager != null) {
+            try {
+                mDreamManager.awaken();
+            } catch (RemoteException e) {
+                // fine, stay asleep then
+            }
+        }
+    }
+
     private void prepareNavigationBarView() {
         mNavigationBarView.reorient();
 
         mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
-        mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPanel);
+        mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPreloadOnTouchListener);
         mNavigationBarView.getHomeButton().setOnTouchListener(mHomeSearchActionListener);
+        mNavigationBarView.getSearchLight().setOnTouchListener(mHomeSearchActionListener);
         updateSearchPanel();
     }
 
@@ -650,8 +774,7 @@
 
         prepareNavigationBarView();
 
-        WindowManagerImpl.getDefault().addView(
-                mNavigationBarView, getNavigationBarLayoutParams());
+        mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
     }
 
     private void repositionNavigationBar() {
@@ -659,8 +782,12 @@
 
         prepareNavigationBarView();
 
-        WindowManagerImpl.getDefault().updateViewLayout(
-                mNavigationBarView, getNavigationBarLayoutParams());
+        mWindowManager.updateViewLayout(mNavigationBarView, getNavigationBarLayoutParams());
+    }
+
+    private void notifyNavigationBarScreenOn(boolean screenOn) {
+        if (mNavigationBarView == null) return;
+        mNavigationBarView.notifyScreenOn(screenOn);
     }
 
     private WindowManager.LayoutParams getNavigationBarLayoutParams() {
@@ -671,10 +798,11 @@
                     | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                     | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                     | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                     | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.OPAQUE);
         // this will allow the navbar to run in an overlay on devices that support this
-        if (ActivityManager.isHighEndGfx(mDisplay)) {
+        if (ActivityManager.isHighEndGfx()) {
             lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
         }
 
@@ -684,8 +812,6 @@
     }
 
     private void addIntruderView() {
-        final int height = getStatusBarHeight();
-
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.WRAP_CONTENT,
@@ -703,7 +829,7 @@
         lp.packageName = mContext.getPackageName();
         lp.windowAnimations = R.style.Animation_StatusBar_IntruderAlert;
 
-        WindowManagerImpl.getDefault().addView(mIntruderAlertView, lp);
+        mWindowManager.addView(mIntruderAlertView, lp);
     }
 
     public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
@@ -728,7 +854,7 @@
     }
 
     public void addNotification(IBinder key, StatusBarNotification notification) {
-        /* if (DEBUG) */ Slog.d(TAG, "addNotification score=" + notification.score);
+        if (DEBUG) Slog.d(TAG, "addNotification score=" + notification.score);
         StatusBarIconView iconView = addNotificationViews(key, notification);
         if (iconView == null) return;
 
@@ -778,8 +904,12 @@
          */
 
         if (notification.notification.fullScreenIntent != null) {
+            // Stop screensaver if the notification has a full-screen intent.
+            // (like an incoming phone call)
+            awakenDreams();
+
             // not immersive & a full-screen alert should be shown
-            Slog.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
+            if (DEBUG) Slog.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
             try {
                 notification.notification.fullScreenIntent.send();
             } catch (PendingIntent.CanceledException e) {
@@ -814,19 +944,13 @@
             }
 
             if (CLOSE_PANEL_WHEN_EMPTIED && mNotificationData.size() == 0 && !mAnimating) {
-                animateCollapse();
+                animateCollapsePanels();
             }
         }
 
         setAreThereNotifications();
     }
 
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        updateRecentsPanel();
-        updateShowSearchHoldoff();
-    }
-
     private void updateShowSearchHoldoff() {
         mShowSearchHoldoff = mContext.getResources().getInteger(
             R.integer.config_show_search_delay);
@@ -843,9 +967,9 @@
         // If the device hasn't been through Setup, we only show system notifications
         for (int i=0; i<N; i++) {
             Entry ent = mNotificationData.get(N-i-1);
-            if (provisioned || showNotificationEvenIfUnprovisioned(ent.notification)) {
-                toShow.add(ent.row);
-            }
+            if (!(provisioned || showNotificationEvenIfUnprovisioned(ent.notification))) continue;
+            if (!notificationIsForCurrentUser(ent.notification)) continue;
+            toShow.add(ent.row);
         }
 
         ArrayList<View> toRemove = new ArrayList<View>();
@@ -867,13 +991,9 @@
             }
         }
 
-        mSettingsButton.setEnabled(isDeviceProvisioned());
-    }
-
-    private void reloadAllNotificationIcons() {
-        if (mNotificationIcons == null) return;
-        mNotificationIcons.removeAllViews();
-        updateNotificationIcons();
+        if (mSettingsButton != null) {
+            mSettingsButton.setEnabled(isDeviceProvisioned());
+        }
     }
 
     @Override
@@ -897,10 +1017,10 @@
         // If the device hasn't been through Setup, we only show system notifications
         for (int i=0; i<N; i++) {
             Entry ent = mNotificationData.get(N-i-1);
-            if ((provisioned && ent.notification.score >= HIDE_ICONS_BELOW_SCORE)
-                    || showNotificationEvenIfUnprovisioned(ent.notification)) {
-                toShow.add(ent.icon);
-            }
+            if (!((provisioned && ent.notification.score >= HIDE_ICONS_BELOW_SCORE)
+                    || showNotificationEvenIfUnprovisioned(ent.notification))) continue;
+            if (!notificationIsForCurrentUser(ent.notification)) continue;
+            toShow.add(ent.icon);
         }
 
         ArrayList<View> toRemove = new ArrayList<View>();
@@ -924,7 +1044,7 @@
     }
 
     protected void updateCarrierLabelVisibility(boolean force) {
-        if (!SHOW_CARRIER_LABEL) return;
+        if (!mShowCarrierInPanel) return;
         // The idea here is to only show the carrier label when there is enough room to see it, 
         // i.e. when there aren't enough notifications to fill the panel.
         if (DEBUG) {
@@ -935,7 +1055,8 @@
         final boolean emergencyCallsShownElsewhere = mEmergencyCallLabel != null;
         final boolean makeVisible =
             !(emergencyCallsShownElsewhere && mNetworkController.isEmergencyOnly())
-            && mPile.getHeight() < (mScrollView.getHeight() - mCarrierLabelHeight);
+            && mPile.getHeight() < (mNotificationPanel.getHeight() - mCarrierLabelHeight - mNotificationHeaderHeight)
+            && mScrollView.getVisibility() == View.VISIBLE;
         
         if (force || mCarrierLabelVisible != makeVisible) {
             mCarrierLabelVisible = makeVisible;
@@ -975,7 +1096,13 @@
                     + " any=" + any + " clearable=" + clearable);
         }
 
-        if (mClearButton.isShown()) {
+        if (mHasFlipSettings 
+                && mFlipSettingsView != null 
+                && mFlipSettingsView.getVisibility() == View.VISIBLE
+                && mScrollView.getVisibility() != View.VISIBLE) {
+            // the flip settings panel is unequivocally showing; we should not be shown
+            mClearButton.setVisibility(View.INVISIBLE);
+        } else if (mClearButton.isShown()) {
             if (clearable != (mClearButton.getAlpha() == 1.0f)) {
                 ObjectAnimator clearAnimation = ObjectAnimator.ofFloat(
                         mClearButton, "alpha", clearable ? 1.0f : 0.0f).setDuration(250);
@@ -1066,26 +1193,24 @@
         flagdbg.append(((diff  & StatusBarManager.DISABLE_RECENT) != 0) ? "* " : " ");
         flagdbg.append(((state & StatusBarManager.DISABLE_CLOCK) != 0) ? "CLOCK" : "clock");
         flagdbg.append(((diff  & StatusBarManager.DISABLE_CLOCK) != 0) ? "* " : " ");
+        flagdbg.append(((state & StatusBarManager.DISABLE_SEARCH) != 0) ? "SEARCH" : "search");
+        flagdbg.append(((diff  & StatusBarManager.DISABLE_SEARCH) != 0) ? "* " : " ");
         flagdbg.append(">");
         Slog.d(TAG, flagdbg.toString());
 
         if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
-            mIcons.animate().cancel();
+            mSystemIconArea.animate().cancel();
             if ((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
-                if (mTicking) {
-                    mTicker.halt();
-                }
-                mIcons.animate()
+                mSystemIconArea.animate()
                     .alpha(0f)
                     .translationY(mNaturalBarHeight*0.5f)
-                    //.setStartDelay(100)
                     .setDuration(175)
                     .setInterpolator(new DecelerateInterpolator(1.5f))
                     .setListener(mMakeIconsInvisible)
                     .start();
             } else {
-                mIcons.setVisibility(View.VISIBLE);
-                mIcons.animate()
+                mSystemIconArea.setVisibility(View.VISIBLE);
+                mSystemIconArea.animate()
                     .alpha(1f)
                     .translationY(0)
                     .setStartDelay(0)
@@ -1101,13 +1226,14 @@
         }
         if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
             if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
-                animateCollapse();
+                animateCollapsePanels();
             }
         }
 
         if ((diff & (StatusBarManager.DISABLE_HOME
                         | StatusBarManager.DISABLE_RECENT
-                        | StatusBarManager.DISABLE_BACK)) != 0) {
+                        | StatusBarManager.DISABLE_BACK
+                        | StatusBarManager.DISABLE_SEARCH)) != 0) {
             // the nav bar will take care of these
             if (mNavigationBarView != null) mNavigationBarView.setDisabledFlags(state);
 
@@ -1121,18 +1247,29 @@
         if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
             if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
                 if (mTicking) {
-                    mTicker.halt();
-                } else {
-                    setNotificationIconVisibility(false, com.android.internal.R.anim.fade_out);
+                    haltTicker();
                 }
+
+                mNotificationIcons.animate()
+                    .alpha(0f)
+                    .translationY(mNaturalBarHeight*0.5f)
+                    .setDuration(175)
+                    .setInterpolator(new DecelerateInterpolator(1.5f))
+                    .setListener(mMakeIconsInvisible)
+                    .start();
             } else {
-                if (!mExpandedVisible) {
-                    setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
-                }
+                mNotificationIcons.setVisibility(View.VISIBLE);
+                mNotificationIcons.animate()
+                    .alpha(1f)
+                    .translationY(0)
+                    .setStartDelay(0)
+                    .setInterpolator(new DecelerateInterpolator(1.5f))
+                    .setDuration(175)
+                    .start();
             }
         } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
             if (mTicking && (state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
-                mTicker.halt();
+                haltTicker();
             }
         }
     }
@@ -1150,10 +1287,13 @@
             super.handleMessage(m);
             switch (m.what) {
                 case MSG_OPEN_NOTIFICATION_PANEL:
-                    animateExpand();
+                    animateExpandNotificationsPanel();
                     break;
-                case MSG_CLOSE_NOTIFICATION_PANEL:
-                    animateCollapse();
+                case MSG_OPEN_SETTINGS_PANEL:
+                    animateExpandSettingsPanel();
+                    break;
+                case MSG_CLOSE_PANELS:
+                    animateCollapsePanels();
                     break;
                 case MSG_SHOW_INTRUDER:
                     setIntruderAlertVisibility(true);
@@ -1166,19 +1306,9 @@
         }
     }
 
-    final Runnable mAnimationCallback = new Runnable() {
-        @Override
-        public void run() {
-            doAnimation(mChoreographer.getFrameTimeNanos());
-        }
-    };
-
-    final Runnable mRevealAnimationCallback = new Runnable() {
-        @Override
-        public void run() {
-            doRevealAnimation(mChoreographer.getFrameTimeNanos());
-        }
-    };
+    public Handler getHandler() {
+        return mHandler;
+    }
 
     View.OnFocusChangeListener mFocusChangeListener = new View.OnFocusChangeListener() {
         public void onFocusChange(View v, boolean hasFocus) {
@@ -1188,7 +1318,7 @@
         }
     };
 
-    private void makeExpandedVisible(boolean revealAfterDraw) {
+    void makeExpandedVisible(boolean revealAfterDraw) {
         if (SPEW) Slog.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible);
         if (mExpandedVisible) {
             return;
@@ -1209,44 +1339,25 @@
         lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
         lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
-        final WindowManager wm = WindowManagerImpl.getDefault();
-        wm.updateViewLayout(mStatusBarWindow, lp);
+        mWindowManager.updateViewLayout(mStatusBarWindow, lp);
 
         // Updating the window layout will force an expensive traversal/redraw.
         // Kick off the reveal animation after this is complete to avoid animation latency.
         if (revealAfterDraw) {
-            mHandler.post(mStartRevealAnimation);
+//            mHandler.post(mStartRevealAnimation);
         }
 
         visibilityChanged(true);
     }
 
-    public void animateExpand() {
-        if (SPEW) Slog.d(TAG, "Animate expand: expanded=" + mExpanded);
-        if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
-            return ;
-        }
-        if (mExpanded) {
-            return;
-        }
-
-        prepareTracking(0, true);
-        mHandler.post(mPerformSelfExpandFling);
+    public void animateCollapsePanels() {
+        animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
     }
 
-    public void animateCollapse() {
-        animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
-    }
-
-    public void animateCollapse(int flags) {
-        animateCollapse(flags, 1.0f);
-    }
-
-    public void animateCollapse(int flags, float velocityMultiplier) {
+    public void animateCollapsePanels(int flags) {
         if (SPEW) {
-            Slog.d(TAG, "animateCollapse(): mExpanded=" + mExpanded
+            Slog.d(TAG, "animateCollapse():"
                     + " mExpandedVisible=" + mExpandedVisible
-                    + " mExpanded=" + mExpanded
                     + " mAnimating=" + mAnimating
                     + " mAnimatingReveal=" + mAnimatingReveal
                     + " mAnimY=" + mAnimY
@@ -1264,49 +1375,231 @@
             mHandler.sendEmptyMessage(MSG_CLOSE_SEARCH_PANEL);
         }
 
-        if (!mExpandedVisible) {
-            return;
-        }
-
-        int y;
-        if (mAnimating || mAnimatingReveal) {
-            y = (int)mAnimY;
-        } else {
-            y = getExpandedViewMaxHeight()-1;
-        }
-        // Let the fling think that we're open so it goes in the right direction
-        // and doesn't try to re-open the windowshade.
-        mExpanded = true;
-        prepareTracking(y, false);
-        performFling(y, -mSelfCollapseVelocityPx*velocityMultiplier, true);
+        mStatusBarWindow.cancelExpandHelper();
+        mStatusBarView.collapseAllPanels(true);
     }
 
-    void performExpand() {
-        if (SPEW) Slog.d(TAG, "performExpand: mExpanded=" + mExpanded);
+    public ViewPropertyAnimator setVisibilityWhenDone(
+            final ViewPropertyAnimator a, final View v, final int vis) {
+        a.setListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                v.setVisibility(vis);
+                a.setListener(null); // oneshot
+            }
+        });
+        return a;
+    }
+
+    public Animator setVisibilityWhenDone(
+            final Animator a, final View v, final int vis) {
+        a.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                v.setVisibility(vis);
+            }
+        });
+        return a;
+    }
+
+    public Animator interpolator(TimeInterpolator ti, Animator a) {
+        a.setInterpolator(ti);
+        return a;
+    }
+
+    public Animator startDelay(int d, Animator a) {
+        a.setStartDelay(d);
+        return a;
+    }
+    
+    public Animator start(Animator a) {
+        a.start();
+        return a;
+    }
+
+    final TimeInterpolator mAccelerateInterpolator = new AccelerateInterpolator();
+    final TimeInterpolator mDecelerateInterpolator = new DecelerateInterpolator();
+    final int FLIP_DURATION_OUT = 125;
+    final int FLIP_DURATION_IN = 225;
+    final int FLIP_DURATION = (FLIP_DURATION_IN + FLIP_DURATION_OUT);
+
+    Animator mScrollViewAnim, mFlipSettingsViewAnim, mNotificationButtonAnim,
+        mSettingsButtonAnim, mClearButtonAnim;
+
+    @Override
+    public void animateExpandNotificationsPanel() {
+        if (SPEW) Slog.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
         if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
             return ;
         }
-        if (mExpanded) {
-            return;
-        }
 
-        mExpanded = true;
-        makeExpandedVisible(false);
-        updateExpandedViewPos(EXPANDED_FULL_OPEN);
+        mNotificationPanel.expand();
+        if (mHasFlipSettings && mScrollView.getVisibility() != View.VISIBLE) {
+            flipToNotifications();
+        }
 
         if (false) postStartTracing();
     }
 
-    void performCollapse() {
-        if (SPEW) Slog.d(TAG, "performCollapse: mExpanded=" + mExpanded
+    public void flipToNotifications() {
+        if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
+        if (mScrollViewAnim != null) mScrollViewAnim.cancel();
+        if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
+        if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
+        if (mClearButtonAnim != null) mClearButtonAnim.cancel();
+
+        mScrollView.setVisibility(View.VISIBLE);
+        mScrollViewAnim = start(
+            startDelay(FLIP_DURATION_OUT,
+                interpolator(mDecelerateInterpolator,
+                    ObjectAnimator.ofFloat(mScrollView, View.SCALE_X, 0f, 1f)
+                        .setDuration(FLIP_DURATION_IN)
+                    )));
+        mFlipSettingsViewAnim = start(
+            setVisibilityWhenDone(
+                interpolator(mAccelerateInterpolator,
+                        ObjectAnimator.ofFloat(mFlipSettingsView, View.SCALE_X, 1f, 0f)
+                        )
+                    .setDuration(FLIP_DURATION_OUT),
+                mFlipSettingsView, View.INVISIBLE));
+        mNotificationButtonAnim = start(
+            setVisibilityWhenDone(
+                ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 0f)
+                    .setDuration(FLIP_DURATION),
+                mNotificationButton, View.INVISIBLE));
+        mSettingsButton.setVisibility(View.VISIBLE);
+        mSettingsButtonAnim = start(
+            ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 1f)
+                .setDuration(FLIP_DURATION));
+        mClearButton.setVisibility(View.VISIBLE);
+        mClearButton.setAlpha(0f);
+        setAreThereNotifications(); // this will show/hide the button as necessary
+        mNotificationPanel.postDelayed(new Runnable() {
+            public void run() {
+                updateCarrierLabelVisibility(false);
+            }
+        }, FLIP_DURATION - 150);
+    }
+
+    @Override
+    public void animateExpandSettingsPanel() {
+        if (SPEW) Slog.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
+        if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
+            return;
+        }
+
+        if (mHasFlipSettings) {
+            mNotificationPanel.expand();
+            if (mFlipSettingsView.getVisibility() != View.VISIBLE) {
+                flipToSettings();
+            }
+        } else if (mSettingsPanel != null) {
+            mSettingsPanel.expand();
+        }
+
+        if (false) postStartTracing();
+    }
+
+    public void switchToSettings() {
+        mFlipSettingsView.setScaleX(1f);
+        mFlipSettingsView.setVisibility(View.VISIBLE);
+        mSettingsButton.setVisibility(View.GONE);
+        mScrollView.setVisibility(View.GONE);
+        mScrollView.setScaleX(0f);
+        mNotificationButton.setVisibility(View.VISIBLE);
+        mNotificationButton.setAlpha(1f);
+        mClearButton.setVisibility(View.GONE);
+    }
+
+    public void flipToSettings() {
+        if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
+        if (mScrollViewAnim != null) mScrollViewAnim.cancel();
+        if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
+        if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
+        if (mClearButtonAnim != null) mClearButtonAnim.cancel();
+
+        mFlipSettingsView.setVisibility(View.VISIBLE);
+        mFlipSettingsView.setScaleX(0f);
+        mFlipSettingsViewAnim = start(
+            startDelay(FLIP_DURATION_OUT,
+                interpolator(mDecelerateInterpolator,
+                    ObjectAnimator.ofFloat(mFlipSettingsView, View.SCALE_X, 0f, 1f)
+                        .setDuration(FLIP_DURATION_IN)
+                    )));
+        mScrollViewAnim = start(
+            setVisibilityWhenDone(
+                interpolator(mAccelerateInterpolator,
+                        ObjectAnimator.ofFloat(mScrollView, View.SCALE_X, 1f, 0f)
+                        )
+                    .setDuration(FLIP_DURATION_OUT), 
+                mScrollView, View.INVISIBLE));
+        mSettingsButtonAnim = start(
+            setVisibilityWhenDone(
+                ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f)
+                    .setDuration(FLIP_DURATION),
+                    mScrollView, View.INVISIBLE));
+        mNotificationButton.setVisibility(View.VISIBLE);
+        mNotificationButtonAnim = start(
+            ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f)
+                .setDuration(FLIP_DURATION));
+        mClearButtonAnim = start(
+            setVisibilityWhenDone(
+                ObjectAnimator.ofFloat(mClearButton, View.ALPHA, 0f)
+                .setDuration(FLIP_DURATION),
+                mClearButton, View.INVISIBLE));
+        mNotificationPanel.postDelayed(new Runnable() {
+            public void run() {
+                updateCarrierLabelVisibility(false);
+            }
+        }, FLIP_DURATION - 150);
+    }
+
+    public void flipPanels() {
+        if (mHasFlipSettings) {
+            if (mFlipSettingsView.getVisibility() != View.VISIBLE) {
+                flipToSettings();
+            } else {
+                flipToNotifications();
+            }
+        }
+    }
+
+    public void animateCollapseQuickSettings() {
+        mStatusBarView.collapseAllPanels(true);
+    }
+
+    void makeExpandedInvisibleSoon() {
+        mHandler.postDelayed(new Runnable() { public void run() { makeExpandedInvisible(); }}, 50);
+    }
+
+    void makeExpandedInvisible() {
+        if (SPEW) Slog.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible
                 + " mExpandedVisible=" + mExpandedVisible);
 
         if (!mExpandedVisible) {
             return;
         }
 
-        // Ensure the panel is fully collapsed (just in case; bug 6765842)
-        updateExpandedViewPos(0);
+        // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
+        mStatusBarView.collapseAllPanels(/*animate=*/ false);
+
+        if (mHasFlipSettings) {
+            // reset things to their proper state
+            if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
+            if (mScrollViewAnim != null) mScrollViewAnim.cancel();
+            if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
+            if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
+            if (mClearButtonAnim != null) mClearButtonAnim.cancel();
+
+            mScrollView.setScaleX(1f);
+            mScrollView.setVisibility(View.VISIBLE);
+            mSettingsButton.setAlpha(1f);
+            mSettingsButton.setVisibility(View.VISIBLE);
+            mNotificationPanel.setVisibility(View.GONE);
+            mFlipSettingsView.setVisibility(View.GONE);
+            mNotificationButton.setVisibility(View.GONE);
+            setAreThereNotifications(); // show the clear button
+        }
 
         mExpandedVisible = false;
         mPile.setLayoutTransitionsEnabled(false);
@@ -1319,18 +1612,12 @@
         lp.height = getStatusBarHeight();
         lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
         lp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-        final WindowManager wm = WindowManagerImpl.getDefault();
-        wm.updateViewLayout(mStatusBarWindow, lp);
+        mWindowManager.updateViewLayout(mStatusBarWindow, lp);
 
         if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
             setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
         }
 
-        if (!mExpanded) {
-            return;
-        }
-        mExpanded = false;
-
         // Close any "App info" popups that might have snuck on-screen
         dismissPopups();
 
@@ -1340,67 +1627,6 @@
         }
     }
 
-    void resetLastAnimTime() {
-        mAnimLastTimeNanos = System.nanoTime();
-        if (SPEW) {
-            Throwable t = new Throwable();
-            t.fillInStackTrace();
-            Slog.d(TAG, "resetting last anim time=" + mAnimLastTimeNanos, t);
-        }
-    }
-
-    void doAnimation(long frameTimeNanos) {
-        if (mAnimating) {
-            if (SPEW) Slog.d(TAG, "doAnimation dt=" + (frameTimeNanos - mAnimLastTimeNanos));
-            if (SPEW) Slog.d(TAG, "doAnimation before mAnimY=" + mAnimY);
-            incrementAnim(frameTimeNanos);
-            if (SPEW) {
-                Slog.d(TAG, "doAnimation after  mAnimY=" + mAnimY);
-                Slog.d(TAG, "doAnimation expandedViewMax=" + getExpandedViewMaxHeight());
-            }
-
-            if (mAnimY >= getExpandedViewMaxHeight()-1 && !mClosing) {
-                if (SPEW) Slog.d(TAG, "Animation completed to expanded state.");
-                mAnimating = false;
-                updateExpandedViewPos(EXPANDED_FULL_OPEN);
-                performExpand();
-                return;
-            }
-
-            if (mAnimY == 0 && mAnimAccel == 0 && mClosing) {
-                if (SPEW) Slog.d(TAG, "Animation completed to collapsed state.");
-                mAnimating = false;
-                performCollapse();
-                return;
-            }
-
-            if (mAnimY < getStatusBarHeight() && mClosing) {
-                // Draw one more frame with the bar positioned at the top of the screen
-                // before ending the animation so that the user sees the bar in
-                // its final position.  The call to performCollapse() causes a window
-                // relayout which takes time and might cause the animation to skip
-                // on the very last frame before the bar disappears if we did it now.
-                mAnimY = 0;
-                mAnimAccel = 0;
-                mAnimVel = 0;
-            }
-
-            updateExpandedViewPos((int)mAnimY);
-            mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
-                    mAnimationCallback, null);
-        }
-    }
-
-    void stopTracking() {
-        if (!mTracking)
-            return;
-        mTracking = false;
-        setPileLayers(View.LAYER_TYPE_NONE);
-        mVelocityTracker.recycle();
-        mVelocityTracker = null;
-        mCloseView.setPressed(false);
-    }
-
     /**
      * Enables or disables layers on the children of the notifications pile.
      * 
@@ -1448,129 +1674,64 @@
         }
     }
 
-    void incrementAnim(long frameTimeNanos) {
-        final long deltaNanos = Math.max(frameTimeNanos - mAnimLastTimeNanos, 0);
-        final float t = deltaNanos * 0.000000001f;                  // ns -> s
-        final float y = mAnimY;
-        final float v = mAnimVel;                                   // px/s
-        final float a = mAnimAccel;                                 // px/s/s
-        mAnimY = y + (v*t) + (0.5f*a*t*t);                          // px
-        mAnimVel = v + (a*t);                                       // px/s
-        mAnimLastTimeNanos = frameTimeNanos;                        // ns
-        //Slog.d(TAG, "y=" + y + " v=" + v + " a=" + a + " t=" + t + " mAnimY=" + mAnimY
-        //        + " mAnimAccel=" + mAnimAccel);
+    public boolean isClinging() {
+        return mCling != null && mCling.getVisibility() == View.VISIBLE;
     }
 
-    void doRevealAnimation(long frameTimeNanos) {
-        if (SPEW) {
-            Slog.d(TAG, "doRevealAnimation: dt=" + (frameTimeNanos - mAnimLastTimeNanos));
-        }
-        final int h = mNotificationPanelMinHeight;
-        if (mAnimatingReveal && mAnimating && mAnimY < h) {
-            incrementAnim(frameTimeNanos);
-            if (mAnimY >= h) {
-                mAnimY = h;
-                updateExpandedViewPos((int)mAnimY);
-            } else {
-                updateExpandedViewPos((int)mAnimY);
-                mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
-                        mRevealAnimationCallback, null);
-            }
+    public void hideCling() {
+        if (isClinging()) {
+            mCling.animate().alpha(0f).setDuration(250).start();
+            mCling.setVisibility(View.GONE);
+            mSuppressStatusBarDrags = false;
         }
     }
 
-    void prepareTracking(int y, boolean opening) {
-        if (CHATTY) {
-            Slog.d(TAG, "panel: beginning to track the user's touch, y=" + y + " opening=" + opening);
+    public void showCling() {
+        // lazily inflate this to accommodate orientation change
+        final ViewStub stub = (ViewStub) mStatusBarWindow.findViewById(R.id.status_bar_cling_stub);
+        if (stub == null) {
+            mClingShown = true;
+            return; // no clings on this device
         }
 
-        mCloseView.setPressed(true);
+        mSuppressStatusBarDrags = true;
 
-        mTracking = true;
-        setPileLayers(View.LAYER_TYPE_HARDWARE);
-        mVelocityTracker = VelocityTracker.obtain();
-        if (opening) {
-            makeExpandedVisible(true);
-        } else {
-            // it's open, close it?
-            if (mAnimating) {
-                mAnimating = false;
-                mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
-                        mAnimationCallback, null);
+        mHandler.postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                mCling = (ViewGroup) stub.inflate();
+
+                mCling.setOnTouchListener(new View.OnTouchListener() {
+                    @Override
+                    public boolean onTouch(View v, MotionEvent event) {
+                        return true; // e eats everything
+                    }});
+                mCling.findViewById(R.id.ok).setOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        hideCling();
+                    }});
+
+                mCling.setAlpha(0f);
+                mCling.setVisibility(View.VISIBLE);
+                mCling.animate().alpha(1f);
+
+                mClingShown = true;
+                SharedPreferences.Editor editor = Prefs.edit(mContext);
+                editor.putBoolean(Prefs.SHOWN_QUICK_SETTINGS_HELP, true);
+                editor.apply();
+
+                makeExpandedVisible(true); // enforce visibility in case the shade is still animating closed
+                animateExpandNotificationsPanel();
+
+                mSuppressStatusBarDrags = false;
             }
-            updateExpandedViewPos(y + mViewDelta);
-        }
+        }, 500);
+
+        animateExpandNotificationsPanel();
     }
 
-    void performFling(int y, float vel, boolean always) {
-        if (CHATTY) {
-            Slog.d(TAG, "panel: will fling, y=" + y + " vel=" + vel + " mExpanded=" + mExpanded);
-        }
-
-        mAnimatingReveal = false;
-
-        mAnimY = y;
-        mAnimVel = vel;
-
-        //Slog.d(TAG, "starting with mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel);
-
-        if (mExpanded) {
-            if (!always && (
-                    vel > mFlingCollapseMinVelocityPx
-                    || (y > (getExpandedViewMaxHeight()*(1f-mCollapseMinDisplayFraction)) &&
-                        vel > -mFlingExpandMinVelocityPx))) {
-                // We are expanded, but they didn't move sufficiently to cause
-                // us to retract.  Animate back to the expanded position.
-                mAnimAccel = mExpandAccelPx;
-                if (vel < 0) {
-                    mAnimVel = 0;
-                }
-            }
-            else {
-                // We are expanded and are now going to animate away.
-                mAnimAccel = -mCollapseAccelPx;
-                if (vel > 0) {
-                    mAnimVel = 0;
-                }
-            }
-        } else {
-            if (always || (
-                    vel > mFlingExpandMinVelocityPx
-                    || (y > (getExpandedViewMaxHeight()*(1f-mExpandMinDisplayFraction)) &&
-                        vel > -mFlingCollapseMinVelocityPx))) {
-                // We are collapsed, and they moved enough to allow us to
-                // expand.  Animate in the notifications.
-                mAnimAccel = mExpandAccelPx;
-                if (vel < 0) {
-                    mAnimVel = 0;
-                }
-            }
-            else {
-                // We are collapsed, but they didn't move sufficiently to cause
-                // us to retract.  Animate back to the collapsed position.
-                mAnimAccel = -mCollapseAccelPx;
-                if (vel > 0) {
-                    mAnimVel = 0;
-                }
-            }
-        }
-        //Slog.d(TAG, "mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel
-        //        + " mAnimAccel=" + mAnimAccel);
-
-        resetLastAnimTime();
-        mAnimating = true;
-        mClosing = mAnimAccel < 0;
-
-        mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
-                mAnimationCallback, null);
-        mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
-                mRevealAnimationCallback, null);
-        mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
-                mAnimationCallback, null);
-        stopTracking();
-    }
-
-    boolean interceptTouchEvent(MotionEvent event) {
+    public boolean interceptTouchEvent(MotionEvent event) {
         if (SPEW) {
             Slog.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled="
                 + mDisabled + " mTracking=" + mTracking);
@@ -1583,105 +1744,30 @@
             }
         }
 
-        if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
-            return false;
+        if (DEBUG_GESTURES) {
+            mGestureRec.add(event);
         }
 
-        final int action = event.getAction();
-        final int statusBarSize = getStatusBarHeight();
-        final int hitSize = statusBarSize*2;
-        final int y = (int)event.getRawY();
-        if (action == MotionEvent.ACTION_DOWN) {
-            if (!areLightsOn()) {
-                setLightsOn(true);
-            }
-
-            if (!mExpanded) {
-                mViewDelta = statusBarSize - y;
-            } else {
-                mCloseView.getLocationOnScreen(mAbsPos);
-                mViewDelta = mAbsPos[1]
-                           + getCloseViewHeight() // XXX: not closeViewHeight, but paddingBottom from the 9patch
-                           + mNotificationPanelBackgroundPadding.top
-                           + mNotificationPanelBackgroundPadding.bottom
-                           - y;
-            }
-            if ((!mExpanded && y < hitSize) ||
-                    // @@ add taps outside the panel if it's not full-screen
-                    (mExpanded && y > (getExpandedViewMaxHeight()-hitSize))) {
-                // We drop events at the edge of the screen to make the windowshade come
-                // down by accident less, especially when pushing open a device with a keyboard
-                // that rotates (like g1 and droid)
-                int x = (int)event.getRawX();
-                final int edgeBorder = mEdgeBorder;
-                if (x >= edgeBorder && x < mDisplayMetrics.widthPixels - edgeBorder) {
-                    prepareTracking(y, !mExpanded);// opening if we're not already fully visible
-                    trackMovement(event);
-                }
-            }
-        } else if (mTracking) {
-            trackMovement(event);
-            if (action == MotionEvent.ACTION_MOVE) {
-                if (mAnimatingReveal && (y + mViewDelta) < mNotificationPanelMinHeight) {
-                    // nothing
-                } else  {
-                    mAnimatingReveal = false;
-                    updateExpandedViewPos(y + mViewDelta);
-                }
-            } else if (action == MotionEvent.ACTION_UP
-                    || action == MotionEvent.ACTION_CANCEL) {
-                mVelocityTracker.computeCurrentVelocity(1000);
-
-                float yVel = mVelocityTracker.getYVelocity();
-                boolean negative = yVel < 0;
-
-                float xVel = mVelocityTracker.getXVelocity();
-                if (xVel < 0) {
-                    xVel = -xVel;
-                }
-                if (xVel > mFlingGestureMaxXVelocityPx) {
-                    xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
-                }
-
-                float vel = (float)Math.hypot(yVel, xVel);
-                if (vel > mFlingGestureMaxOutputVelocityPx) {
-                    vel = mFlingGestureMaxOutputVelocityPx;
-                }
-                if (negative) {
-                    vel = -vel;
-                }
-
-                if (CHATTY) {
-                    Slog.d(TAG, String.format("gesture: vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f",
-                        mVelocityTracker.getXVelocity(),
-                        mVelocityTracker.getYVelocity(),
-                        xVel, yVel,
-                        vel));
-                }
-
-                if (mTrackingPosition == mNotificationPanelMinHeight) {
-                    // start the fling from the tracking position, ignore y and view delta
-                    mFlingY = mTrackingPosition;
-                    mViewDelta = 0;
-                } else {
-                    mFlingY = y;
-                }
-                mFlingVelocity = vel;
-                mHandler.post(mPerformFling);
-            }
-
+        // Cling (first-run help) handling.
+        // The cling is supposed to show the first time you drag, or even tap, the status bar.
+        // It should show the notification panel, then fade in after half a second, giving you 
+        // an explanation of what just happened, as well as teach you how to access quick
+        // settings (another drag). The user can dismiss the cling by clicking OK or by 
+        // dragging quick settings into view.
+        final int act = event.getActionMasked();
+        if (mSuppressStatusBarDrags) {
+            return true;
+        } else if (act == MotionEvent.ACTION_UP && !mClingShown) {
+            showCling();
+        } else {
+            hideCling();
         }
+
         return false;
     }
 
-    private void trackMovement(MotionEvent event) {
-        // Add movement to velocity tracker using raw screen X and Y coordinates instead
-        // of window coordinates because the window frame may be moving at the same time.
-        float deltaX = event.getRawX() - event.getX();
-        float deltaY = event.getRawY() - event.getY();
-        event.offsetLocation(deltaX, deltaY);
-        mVelocityTracker.addMovement(event);
-        event.offsetLocation(-deltaX, -deltaY);
+    public GestureRecorder getGestureRecorder() {
+        return mGestureRec;
     }
 
     @Override // CommandQueue
@@ -1707,9 +1793,9 @@
             if (0 != (diff & View.SYSTEM_UI_FLAG_LOW_PROFILE)) {
                 final boolean lightsOut = (0 != (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE));
                 if (lightsOut) {
-                    animateCollapse();
+                    animateCollapsePanels();
                     if (mTicking) {
-                        mTicker.halt();
+                        haltTicker();
                     }
                 }
 
@@ -1732,25 +1818,28 @@
             final View battery = mStatusBarView.findViewById(R.id.battery);
             final View clock = mStatusBarView.findViewById(R.id.clock);
 
-            mLightsOutAnimation = new AnimatorSet();
-            mLightsOutAnimation.playTogether(
+            final AnimatorSet lightsOutAnim = new AnimatorSet();
+            lightsOutAnim.playTogether(
                     ObjectAnimator.ofFloat(notifications, View.ALPHA, 0),
                     ObjectAnimator.ofFloat(systemIcons, View.ALPHA, 0),
                     ObjectAnimator.ofFloat(signal, View.ALPHA, 0),
                     ObjectAnimator.ofFloat(battery, View.ALPHA, 0.5f),
                     ObjectAnimator.ofFloat(clock, View.ALPHA, 0.5f)
                 );
-            mLightsOutAnimation.setDuration(750);
+            lightsOutAnim.setDuration(750);
 
-            mLightsOnAnimation = new AnimatorSet();
-            mLightsOnAnimation.playTogether(
+            final AnimatorSet lightsOnAnim = new AnimatorSet();
+            lightsOnAnim.playTogether(
                     ObjectAnimator.ofFloat(notifications, View.ALPHA, 1),
                     ObjectAnimator.ofFloat(systemIcons, View.ALPHA, 1),
                     ObjectAnimator.ofFloat(signal, View.ALPHA, 1),
                     ObjectAnimator.ofFloat(battery, View.ALPHA, 1),
                     ObjectAnimator.ofFloat(clock, View.ALPHA, 1)
                 );
-            mLightsOnAnimation.setDuration(250);
+            lightsOnAnim.setDuration(250);
+
+            mLightsOutAnimation = lightsOutAnim;
+            mLightsOnAnimation = lightsOnAnim;
         }
 
         mLightsOutAnimation.cancel();
@@ -1777,7 +1866,7 @@
 
     private void notifyUiVisibilityChanged() {
         try {
-            mWindowManager.statusBarVisibilityChanged(mSystemUiVisibility);
+            mWindowManagerService.statusBarVisibilityChanged(mSystemUiVisibility);
         } catch (RemoteException ex) {
         }
     }
@@ -1802,68 +1891,11 @@
         mCommandQueue.setNavigationIconHints(
                 altBack ? (mNavigationIconHints | StatusBarManager.NAVIGATION_HINT_BACK_ALT)
                         : (mNavigationIconHints & ~StatusBarManager.NAVIGATION_HINT_BACK_ALT));
+        if (mQS != null) mQS.setImeWindowStatus(vis > 0);
     }
 
     @Override
-    public void setHardKeyboardStatus(boolean available, boolean enabled) { }
-
-    private class NotificationClicker implements View.OnClickListener {
-        private PendingIntent mIntent;
-        private String mPkg;
-        private String mTag;
-        private int mId;
-
-        NotificationClicker(PendingIntent intent, String pkg, String tag, int id) {
-            mIntent = intent;
-            mPkg = pkg;
-            mTag = tag;
-            mId = id;
-        }
-
-        public void onClick(View v) {
-            try {
-                // The intent we are sending is for the application, which
-                // won't have permission to immediately start an activity after
-                // the user switches to home.  We know it is safe to do at this
-                // point, so make sure new activity switches are now allowed.
-                ActivityManagerNative.getDefault().resumeAppSwitches();
-                // Also, notifications can be launched from the lock screen,
-                // so dismiss the lock screen when the activity starts.
-                ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
-            } catch (RemoteException e) {
-            }
-
-            if (mIntent != null) {
-                int[] pos = new int[2];
-                v.getLocationOnScreen(pos);
-                Intent overlay = new Intent();
-                overlay.setSourceBounds(
-                        new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight()));
-                try {
-                    mIntent.send(mContext, 0, overlay);
-                } catch (PendingIntent.CanceledException e) {
-                    // the stack trace isn't very helpful here.  Just log the exception message.
-                    Slog.w(TAG, "Sending contentIntent failed: " + e);
-                }
-
-                KeyguardManager kgm =
-                    (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
-                if (kgm != null) kgm.exitKeyguardSecurely(null);
-            }
-
-            try {
-                mBarService.onNotificationClick(mPkg, mTag, mId);
-            } catch (RemoteException ex) {
-                // system process is dead if we're here.
-            }
-
-            // close the shade if it was open
-            animateCollapse();
-
-            // If this click was on the intruder alert, hide that instead
-            mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
-        }
-    }
+    public void setHardKeyboardStatus(boolean available, boolean enabled) {}
 
     @Override
     protected void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
@@ -1873,6 +1905,9 @@
         // no ticking in Setup
         if (!isDeviceProvisioned()) return;
 
+        // not for you
+        if (!notificationIsForCurrentUser(n)) return;
+
         // Show the ticker if one is requested. Also don't do this
         // until status bar window is attached to the window manager,
         // because...  well, what's the point otherwise?  And trying to
@@ -1893,27 +1928,26 @@
         @Override
         public void tickerStarting() {
             mTicking = true;
-            mIcons.setVisibility(View.GONE);
+            mStatusBarContents.setVisibility(View.GONE);
             mTickerView.setVisibility(View.VISIBLE);
             mTickerView.startAnimation(loadAnim(com.android.internal.R.anim.push_up_in, null));
-            mIcons.startAnimation(loadAnim(com.android.internal.R.anim.push_up_out, null));
+            mStatusBarContents.startAnimation(loadAnim(com.android.internal.R.anim.push_up_out, null));
         }
 
         @Override
         public void tickerDone() {
-            mIcons.setVisibility(View.VISIBLE);
+            mStatusBarContents.setVisibility(View.VISIBLE);
             mTickerView.setVisibility(View.GONE);
-            mIcons.startAnimation(loadAnim(com.android.internal.R.anim.push_down_in, null));
+            mStatusBarContents.startAnimation(loadAnim(com.android.internal.R.anim.push_down_in, null));
             mTickerView.startAnimation(loadAnim(com.android.internal.R.anim.push_down_out,
                         mTickingDoneListener));
         }
 
         public void tickerHalting() {
-            mIcons.setVisibility(View.VISIBLE);
+            mStatusBarContents.setVisibility(View.VISIBLE);
             mTickerView.setVisibility(View.GONE);
-            mIcons.startAnimation(loadAnim(com.android.internal.R.anim.fade_in, null));
-            mTickerView.startAnimation(loadAnim(com.android.internal.R.anim.fade_out,
-                        mTickingDoneListener));
+            mStatusBarContents.startAnimation(loadAnim(com.android.internal.R.anim.fade_in, null));
+            // we do not animate the ticker away at this point, just get rid of it (b/6992707)
         }
     }
 
@@ -1943,8 +1977,7 @@
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         synchronized (mQueueLock) {
             pw.println("Current Status Bar state:");
-            pw.println("  mExpanded=" + mExpanded
-                    + ", mExpandedVisible=" + mExpandedVisible
+            pw.println("  mExpandedVisible=" + mExpandedVisible
                     + ", mTrackingPosition=" + mTrackingPosition);
             pw.println("  mTicking=" + mTicking);
             pw.println("  mTracking=" + mTracking);
@@ -1960,7 +1993,6 @@
                     + " mViewDelta=" + mViewDelta);
             pw.println("  mDisplayMetrics=" + mDisplayMetrics);
             pw.println("  mPile: " + viewInfo(mPile));
-            pw.println("  mCloseView: " + viewInfo(mCloseView));
             pw.println("  mTickerView: " + viewInfo(mTickerView));
             pw.println("  mScrollView: " + viewInfo(mScrollView)
                     + " scroll " + mScrollView.getScrollX() + "," + mScrollView.getScrollY());
@@ -2009,6 +2041,11 @@
             }
         }
 
+        if (DEBUG_GESTURES) {
+            pw.print("  status bar gestures: ");
+            mGestureRec.dump(fd, pw, args);
+        }
+
         mNetworkController.dump(fd, pw, args);
     }
 
@@ -2040,7 +2077,7 @@
         lp.packageName = mContext.getPackageName();
 
         makeStatusBarView();
-        WindowManagerImpl.getDefault().addView(mStatusBarWindow, lp);
+        mWindowManager.addView(mStatusBarWindow, lp);
     }
 
     void setNotificationIconVisibility(boolean visible, int anim) {
@@ -2066,128 +2103,38 @@
     }
 
     @Override
-    protected void updateExpandedViewPos(int expandedPosition) {
-        if (SPEW) {
-            Slog.d(TAG, "updateExpandedViewPos: expandedPosition=" + expandedPosition
-                    //+ " mTrackingParams.y=" + ((mTrackingParams == null) ? "?" : mTrackingParams.y)
-                    + " mTracking=" + mTracking
-                    + " mTrackingPosition=" + mTrackingPosition
-                    + " mExpandedVisible=" + mExpandedVisible
-                    + " mAnimating=" + mAnimating
-                    + " mAnimatingReveal=" + mAnimatingReveal
-                    + " mClosing=" + mClosing
-                    + " gravity=" + mNotificationPanelGravity);
-        }
-        int panelh = 0;
-        final int disph = getExpandedViewMaxHeight();
+    public void updateExpandedViewPos(int thingy) {
+        if (DEBUG) Slog.v(TAG, "updateExpandedViewPos");
 
-        // If the expanded view is not visible, make sure they're still off screen.
-        // Maybe the view was resized.
-        if (!mExpandedVisible) {
-            if (SPEW) Slog.d(TAG, "updateExpandedViewPos: view not visible, bailing");
-            updateExpandedInvisiblePosition();
-            return;
-        }
-
-        // tracking view...
-        int pos;
-        if (expandedPosition == EXPANDED_FULL_OPEN) {
-            panelh = disph;
-        }
-        else if (expandedPosition == EXPANDED_LEAVE_ALONE) {
-            panelh = mTrackingPosition;
-        }
-        else {
-            if (expandedPosition <= disph) {
-                panelh = expandedPosition;
-            } else {
-                panelh = disph;
-            }
-        }
-
-        // catch orientation changes and other peculiar cases
-        if (panelh > 0 &&
-                ((panelh > disph) ||
-                 (panelh < disph && !mTracking && !mAnimating))) {
-            if (SPEW) Slog.d(TAG, "updateExpandedViewPos: orientation change?");
-            panelh = disph;
-        } else if (panelh < 0) {
-            panelh = 0;
-        }
-
-        if (SPEW) Slog.d(TAG, "updateExpandedViewPos: adjusting size to panelh=" + panelh);
-
-        if (panelh == mTrackingPosition) {
-            if (SPEW) Slog.d(TAG, "updateExpandedViewPos: panelh == mTrackingPosition, bailing");
-            return;
-        }
-
-        mTrackingPosition = panelh;
+        // on larger devices, the notification panel is propped open a bit
+        mNotificationPanel.setMinimumHeight(
+                (int)(mNotificationPanelMinHeightFrac * mCurrentDisplaySize.y));
 
         FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mNotificationPanel.getLayoutParams();
-        lp.height = panelh;
         lp.gravity = mNotificationPanelGravity;
-        lp.leftMargin = mNotificationPanelMarginLeftPx;
-        if (SPEW) {
-            Slog.v(TAG, "updated cropView height=" + panelh + " grav=" + lp.gravity);
-        }
+        lp.leftMargin = mNotificationPanelMarginPx;
         mNotificationPanel.setLayoutParams(lp);
 
-        final int barh = getCloseViewHeight() + getStatusBarHeight();
-        final float frac = saturate((float)(panelh - barh) / (disph - barh));
-
-        if (DIM_BEHIND_EXPANDED_PANEL && ActivityManager.isHighEndGfx(mDisplay)) {
-            // woo, special effects
-            final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2.2f))));
-            final int color = ((int)(0xB0 * k)) << 24;
-            mStatusBarWindow.setBackgroundColor(color);
+        if (mSettingsPanel != null) {
+            lp = (FrameLayout.LayoutParams) mSettingsPanel.getLayoutParams();
+            lp.gravity = mSettingsPanelGravity;
+            lp.rightMargin = mNotificationPanelMarginPx;
+            mSettingsPanel.setLayoutParams(lp);
         }
-        
+
         updateCarrierLabelVisibility(false);
     }
 
+    // called by makeStatusbar and also by PhoneStatusBarView
     void updateDisplaySize() {
         mDisplay.getMetrics(mDisplayMetrics);
-    }
-
-    void performDisableActions(int net) {
-        int old = mDisabled;
-        int diff = net ^ old;
-        mDisabled = net;
-
-        // act accordingly
-        if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
-            if ((net & StatusBarManager.DISABLE_EXPAND) != 0) {
-                Slog.d(TAG, "DISABLE_EXPAND: yes");
-                animateCollapse();
-            }
-        }
-        if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
-            if ((net & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
-                Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
-                if (mTicking) {
-                    mNotificationIcons.setVisibility(View.INVISIBLE);
-                    mTicker.halt();
-                } else {
-                    setNotificationIconVisibility(false, com.android.internal.R.anim.fade_out);
-                }
-            } else {
-                Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: no");
-                if (!mExpandedVisible) {
-                    setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
-                }
-            }
-        } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
-            if (mTicking && (net & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
-                mTicker.halt();
-            }
+        if (DEBUG_GESTURES) {
+            mGestureRec.tag("display", 
+                    String.format("%dx%d", mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
         }
     }
 
     private View.OnClickListener mClearButtonListener = new View.OnClickListener() {
-        final int mini(int a, int b) {
-            return (b>a?a:b);
-        }
         public void onClick(View v) {
             synchronized (mNotificationData) {
                 // animate-swipe all dismissable notifications, then animate the shade closed
@@ -2204,7 +2151,7 @@
                     }
                 }
                 if (snapshot.isEmpty()) {
-                    animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
+                    animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
                     return;
                 }
                 new Thread(new Runnable() {
@@ -2224,6 +2171,9 @@
                         mPostCollapseCleanup = new Runnable() {
                             @Override
                             public void run() {
+                                if (DEBUG) {
+                                    Slog.v(TAG, "running post-collapse cleanup");
+                                }
                                 try {
                                     mPile.setViewRemoval(true);
                                     mBarService.onClearAllNotifications();
@@ -2252,7 +2202,7 @@
                         mHandler.postDelayed(new Runnable() {
                             @Override
                             public void run() {
-                                animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
+                                animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
                             }
                         }, totalDelay + 225);
                     }
@@ -2261,24 +2211,45 @@
         }
     };
 
+    public void startActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned) {
+        if (onlyProvisioned && !isDeviceProvisioned()) return;
+        try {
+            // Dismiss the lock screen when Settings starts.
+            ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
+        } catch (RemoteException e) {
+        }
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+        animateCollapsePanels();
+    }
+
     private View.OnClickListener mSettingsButtonListener = new View.OnClickListener() {
         public void onClick(View v) {
-            // We take this as a good indicator that Setup is running and we shouldn't
-            // allow you to go somewhere else
-            if (!isDeviceProvisioned()) return;
-            try {
-                // Dismiss the lock screen when Settings starts.
-                ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
-            } catch (RemoteException e) {
+            if (mHasSettingsPanel) {
+                animateExpandSettingsPanel();
+            } else {
+                startActivityDismissingKeyguard(
+                        new Intent(android.provider.Settings.ACTION_SETTINGS), true);
             }
-            v.getContext().startActivity(new Intent(Settings.ACTION_SETTINGS)
-                    .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
-            animateCollapse();
+        }
+    };
+
+    private View.OnClickListener mClockClickListener = new View.OnClickListener() {
+        public void onClick(View v) {
+            startActivityDismissingKeyguard(
+                    new Intent(Intent.ACTION_QUICK_CLOCK), true); // have fun, everyone
+        }
+    };
+
+    private View.OnClickListener mNotificationButtonListener = new View.OnClickListener() {
+        public void onClick(View v) {
+            animateExpandNotificationsPanel();
         }
     };
 
     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         public void onReceive(Context context, Intent intent) {
+            if (DEBUG) Slog.v(TAG, "onReceive: " + intent);
             String action = intent.getAction();
             if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
                 int flags = CommandQueue.FLAG_EXCLUDE_NONE;
@@ -2288,20 +2259,49 @@
                         flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL;
                     }
                 }
-                animateCollapse(flags);
+                animateCollapsePanels(flags);
             }
             else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                 // no waiting!
-                performCollapse();
+                makeExpandedInvisible();
+                notifyNavigationBarScreenOn(false);
             }
             else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
+                if (DEBUG) {
+                    Slog.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
+                }
+                mDisplay.getSize(mCurrentDisplaySize);
+
                 updateResources();
                 repositionNavigationBar();
                 updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
+                updateShowSearchHoldoff();
+            }
+            else if (Intent.ACTION_SCREEN_ON.equals(action)) {
+                // work around problem where mDisplay.getRotation() is not stable while screen is off (bug 7086018)
+                repositionNavigationBar();
+                notifyNavigationBarScreenOn(true);
             }
         }
     };
 
+    @Override
+    public void userSwitched(int newUserId) {
+        if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId);
+        animateCollapsePanels();
+        updateNotificationIcons();
+        resetUserSetupObserver();
+    }
+
+    private void resetUserSetupObserver() {
+        mContext.getContentResolver().unregisterContentObserver(mUserSetupObserver);
+        mUserSetupObserver.onChange(false);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), true,
+                mUserSetupObserver,
+                mCurrentUserId);
+    }
+
     private void setIntruderAlertVisibility(boolean vis) {
         if (!ENABLE_INTRUDERS) return;
         if (DEBUG) {
@@ -2337,6 +2337,10 @@
         if (mClearButton instanceof TextView) {
             ((TextView)mClearButton).setText(context.getText(R.string.status_bar_clear_all_button));
         }
+
+        // Update the QuickSettings container
+        if (mQS != null) mQS.updateResources();
+
         loadDimens();
     }
 
@@ -2377,34 +2381,28 @@
 
         mNotificationPanelMarginBottomPx
             = (int) res.getDimension(R.dimen.notification_panel_margin_bottom);
-        mNotificationPanelMarginLeftPx
+        mNotificationPanelMarginPx
             = (int) res.getDimension(R.dimen.notification_panel_margin_left);
         mNotificationPanelGravity = res.getInteger(R.integer.notification_panel_layout_gravity);
         if (mNotificationPanelGravity <= 0) {
-            mNotificationPanelGravity = Gravity.CENTER_VERTICAL | Gravity.TOP;
+            mNotificationPanelGravity = Gravity.LEFT | Gravity.TOP;
         }
-        getNinePatchPadding(res.getDrawable(R.drawable.notification_panel_bg), mNotificationPanelBackgroundPadding);
-        final int notificationPanelDecorationHeight =
-              res.getDimensionPixelSize(R.dimen.notification_panel_padding_top)
-            + res.getDimensionPixelSize(R.dimen.notification_panel_header_height)
-            + mNotificationPanelBackgroundPadding.top
-            + mNotificationPanelBackgroundPadding.bottom;
-        mNotificationPanelMinHeight = 
-              notificationPanelDecorationHeight 
-            + res.getDimensionPixelSize(R.dimen.close_handle_underlap);
+        mSettingsPanelGravity = res.getInteger(R.integer.settings_panel_layout_gravity);
+        if (mSettingsPanelGravity <= 0) {
+            mSettingsPanelGravity = Gravity.RIGHT | Gravity.TOP;
+        }
 
         mCarrierLabelHeight = res.getDimensionPixelSize(R.dimen.carrier_label_height);
+        mNotificationHeaderHeight = res.getDimensionPixelSize(R.dimen.notification_panel_header_height);
+
+        mNotificationPanelMinHeightFrac = res.getFraction(R.dimen.notification_panel_min_height_frac, 1, 1);
+        if (mNotificationPanelMinHeightFrac < 0f || mNotificationPanelMinHeightFrac > 1f) {
+            mNotificationPanelMinHeightFrac = 0f;
+        }
 
         if (false) Slog.v(TAG, "updateResources");
     }
 
-    private static void getNinePatchPadding(Drawable d, Rect outPadding) {
-        if (d instanceof NinePatchDrawable) {
-            NinePatchDrawable ninePatch = (NinePatchDrawable) d;
-            ninePatch.getPadding(outPadding);
-        }
-    }
-
     //
     // tracing
     //
@@ -2444,7 +2442,9 @@
 
     @Override
     protected boolean shouldDisableNavbarGestures() {
-        return mExpanded || (mDisabled & StatusBarManager.DISABLE_HOME) != 0;
+        return !isDeviceProvisioned()
+                || mExpandedVisible
+                || (mDisabled & StatusBarManager.DISABLE_SEARCH) != 0;
     }
 
     private static class FastColorDrawable extends Drawable {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index a9cc62a4d6..af6a149 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -16,151 +16,76 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.app.ActivityManager;
+import android.app.StatusBarManager;
 import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.os.SystemClock;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
 import android.util.AttributeSet;
-import android.view.KeyEvent;
+import android.util.Slog;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
 import android.view.accessibility.AccessibilityEvent;
-import android.widget.FrameLayout;
-
 import com.android.systemui.R;
-import com.android.systemui.statusbar.BaseStatusBar;
-import com.android.systemui.statusbar.policy.FixedSizeDrawable;
 
-public class PhoneStatusBarView extends FrameLayout {
+public class PhoneStatusBarView extends PanelBar {
     private static final String TAG = "PhoneStatusBarView";
+    private static final boolean DEBUG = PhoneStatusBar.DEBUG;
 
-    static final int DIM_ANIM_TIME = 400;
-    
-    PhoneStatusBar mService;
-    boolean mTracking;
-    int mStartX, mStartY;
-    ViewGroup mNotificationIcons;
-    ViewGroup mStatusIcons;
-    
-    boolean mNightMode = false;
-    int mStartAlpha = 0, mEndAlpha = 0;
-    long mEndTime = 0;
+    PhoneStatusBar mBar;
+    int mScrimColor;
+    float mSettingsPanelDragzoneFrac;
+    float mSettingsPanelDragzoneMin;
 
-    Rect mButtonBounds = new Rect();
-    boolean mCapturingEvents = true;
+    boolean mFullWidthNotifications;
+    PanelView mFadingPanel = null;
+    PanelView mLastFullyOpenedPanel = null;
+    PanelView mNotificationPanel, mSettingsPanel;
+    private boolean mShouldFade;
 
     public PhoneStatusBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
+
+        Resources res = getContext().getResources();
+        mScrimColor = res.getColor(R.color.notification_panel_scrim_color);
+        mSettingsPanelDragzoneMin = res.getDimension(R.dimen.settings_panel_dragzone_min);
+        try {
+            mSettingsPanelDragzoneFrac = res.getFraction(R.dimen.settings_panel_dragzone_fraction, 1, 1);
+        } catch (NotFoundException ex) {
+            mSettingsPanelDragzoneFrac = 0f;
+        }
+        mFullWidthNotifications = mSettingsPanelDragzoneFrac <= 0f;
+    }
+
+    public void setBar(PhoneStatusBar bar) {
+        mBar = bar;
+    }
+
+    public boolean hasFullWidthNotifications() {
+        return mFullWidthNotifications;
     }
 
     @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mNotificationIcons = (ViewGroup)findViewById(R.id.notificationIcons);
-        mStatusIcons = (ViewGroup)findViewById(R.id.statusIcons);
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        //mService.onBarViewAttached();
-    }
-    
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        mService.updateDisplaySize();
-        boolean nightMode = (newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK)
-                == Configuration.UI_MODE_NIGHT_YES;
-        if (mNightMode != nightMode) {
-            mNightMode = nightMode;
-            mStartAlpha = getCurAlpha();
-            mEndAlpha = mNightMode ? 0x80 : 0x00;
-            mEndTime = SystemClock.uptimeMillis() + DIM_ANIM_TIME;
-            invalidate();
+    public void onAttachedToWindow() {
+        for (PanelView pv : mPanels) {
+            pv.setRubberbandingEnabled(!mFullWidthNotifications);
         }
     }
 
-    int getCurAlpha() {
-        long time = SystemClock.uptimeMillis();
-        if (time > mEndTime) {
-            return mEndAlpha;
-        }
-        return mEndAlpha
-                - (int)(((mEndAlpha-mStartAlpha) * (mEndTime-time) / DIM_ANIM_TIME));
-    }
-    
     @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        super.onSizeChanged(w, h, oldw, oldh);
-        mService.updateExpandedViewPos(BaseStatusBar.EXPANDED_LEAVE_ALONE);
+    public void addPanel(PanelView pv) {
+        super.addPanel(pv);
+        if (pv.getId() == R.id.notification_panel) {
+            mNotificationPanel = pv;
+        } else if (pv.getId() == R.id.settings_panel){
+            mSettingsPanel = pv;
+        }
+        pv.setRubberbandingEnabled(!mFullWidthNotifications);
     }
 
     @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        super.onLayout(changed, l, t, r, b);
-    }
-
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        super.dispatchDraw(canvas);
-        int alpha = getCurAlpha();
-        if (alpha != 0) {
-            canvas.drawARGB(alpha, 0, 0, 0);
-        }
-        if (alpha != mEndAlpha) {
-            invalidate();
-        }
-    }
-
-    /**
-     * Gets the left position of v in this view.  Throws if v is not
-     * a child of this.
-     */
-    private int getViewOffset(View v) {
-        int offset = 0;
-        while (v != this) {
-            offset += v.getLeft();
-            ViewParent p = v.getParent();
-            if (v instanceof View) {
-                v = (View)p;
-            } else {
-                throw new RuntimeException(v + " is not a child of " + this);
-            }
-        }
-        return offset;
-    }
-
-    /**
-     * Ensure that, if there is no target under us to receive the touch,
-     * that we process it ourself.  This makes sure that onInterceptTouchEvent()
-     * is always called for the entire gesture.
-     */
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (!mCapturingEvents) {
-            return false;
-        }
-        if (event.getAction() != MotionEvent.ACTION_DOWN) {
-            mService.interceptTouchEvent(event);
-        }
-        return true;
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent event) {
-        if (event.getAction() == MotionEvent.ACTION_DOWN) {
-            if (mButtonBounds.contains((int)event.getX(), (int)event.getY())) {
-                mCapturingEvents = false;
-                return false;
-            }
-        }
-        mCapturingEvents = true;
-        return mService.interceptTouchEvent(event)
-                ? true : super.onInterceptTouchEvent(event);
+    public boolean panelsEnabled() {
+        return ((mBar.mDisabled & StatusBarManager.DISABLE_EXPAND) == 0);
     }
 
     @Override
@@ -177,4 +102,124 @@
         }
         return false;
     }
+
+    @Override
+    public PanelView selectPanelForTouch(MotionEvent touch) {
+        final float x = touch.getX();
+
+        if (mFullWidthNotifications) {
+            // No double swiping. If either panel is open, nothing else can be pulled down.
+            return ((mSettingsPanel == null ? 0 : mSettingsPanel.getExpandedHeight()) 
+                        + mNotificationPanel.getExpandedHeight() > 0) 
+                    ? null 
+                    : mNotificationPanel;
+        }
+
+        // We split the status bar into thirds: the left 2/3 are for notifications, and the
+        // right 1/3 for quick settings. If you pull the status bar down a second time you'll
+        // toggle panels no matter where you pull it down.
+
+        final float w = getMeasuredWidth();
+        float region = (w * mSettingsPanelDragzoneFrac);
+
+        if (DEBUG) {
+            Slog.v(TAG, String.format(
+                "w=%.1f frac=%.3f region=%.1f min=%.1f x=%.1f w-x=%.1f",
+                w, mSettingsPanelDragzoneFrac, region, mSettingsPanelDragzoneMin, x, (w-x)));
+        }
+
+        if (region < mSettingsPanelDragzoneMin) region = mSettingsPanelDragzoneMin;
+
+        return (w - x < region) ? mSettingsPanel : mNotificationPanel;
+    }
+
+    @Override
+    public void onPanelPeeked() {
+        super.onPanelPeeked();
+        mBar.makeExpandedVisible(true);
+    }
+
+    @Override
+    public void startOpeningPanel(PanelView panel) {
+        super.startOpeningPanel(panel);
+        // we only want to start fading if this is the "first" or "last" panel,
+        // which is kind of tricky to determine
+        mShouldFade = (mFadingPanel == null || mFadingPanel.isFullyExpanded());
+        if (DEBUG) {
+            Slog.v(TAG, "start opening: " + panel + " shouldfade=" + mShouldFade);
+        }
+        mFadingPanel = panel;
+    }
+
+    @Override
+    public void onAllPanelsCollapsed() {
+        super.onAllPanelsCollapsed();
+        // give animations time to settle
+        mBar.makeExpandedInvisibleSoon();
+        mFadingPanel = null;
+        mLastFullyOpenedPanel = null;
+    }
+
+    @Override
+    public void onPanelFullyOpened(PanelView openPanel) {
+        super.onPanelFullyOpened(openPanel);
+        if (openPanel != mLastFullyOpenedPanel) {
+            openPanel.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+        }
+        mFadingPanel = openPanel;
+        mLastFullyOpenedPanel = openPanel;
+        mShouldFade = true; // now you own the fade, mister
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        return mBar.interceptTouchEvent(event) || super.onTouchEvent(event);
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent event) {
+        return mBar.interceptTouchEvent(event) || super.onInterceptTouchEvent(event);
+    }
+
+    @Override
+    public void panelExpansionChanged(PanelView panel, float frac) {
+        super.panelExpansionChanged(panel, frac);
+
+        if (DEBUG) {
+            Slog.v(TAG, "panelExpansionChanged: f=" + frac);
+        }
+
+        if (panel == mFadingPanel && mScrimColor != 0 && ActivityManager.isHighEndGfx()) {
+            if (mShouldFade) {
+                frac = mPanelExpandedFractionSum; // don't judge me
+                // let's start this 20% of the way down the screen
+                frac = frac * 1.2f - 0.2f;
+                if (frac <= 0) {
+                    mBar.mStatusBarWindow.setBackgroundColor(0);
+                } else {
+                    // woo, special effects
+                    final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
+                    // attenuate background color alpha by k
+                    final int color = (int) ((mScrimColor >>> 24) * k) << 24 | (mScrimColor & 0xFFFFFF);
+                    mBar.mStatusBarWindow.setBackgroundColor(color);
+                }
+            }
+        }
+
+        // fade out the panel as it gets buried into the status bar to avoid overdrawing the
+        // status bar on the last frame of a close animation
+        final int H = mBar.getStatusBarHeight();
+        final float ph = panel.getExpandedHeight() + panel.getPaddingBottom();
+        float alpha = 1f;
+        if (ph < 2*H) {
+            if (ph < H) alpha = 0f;
+            else alpha = (ph - H) / H;
+            alpha = alpha * alpha; // get there faster
+        }
+        if (panel.getAlpha() != alpha) {
+            panel.setAlpha(alpha);
+        }
+
+        mBar.updateCarrierLabelVisibility(false);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
new file mode 100644
index 0000000..cc9c601
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -0,0 +1,897 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import com.android.internal.view.RotationPolicy;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.R;
+
+import com.android.systemui.statusbar.phone.QuickSettingsModel.BluetoothState;
+import com.android.systemui.statusbar.phone.QuickSettingsModel.RSSIState;
+import com.android.systemui.statusbar.phone.QuickSettingsModel.State;
+import com.android.systemui.statusbar.phone.QuickSettingsModel.UserState;
+import com.android.systemui.statusbar.phone.QuickSettingsModel.WifiState;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BluetoothController;
+import com.android.systemui.statusbar.policy.BrightnessController;
+import com.android.systemui.statusbar.policy.LocationController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.ToggleSlider;
+
+import android.app.ActivityManagerNative;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.PendingIntent;
+import android.bluetooth.BluetoothAdapter;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.CursorLoader;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LevelListDrawable;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.WifiDisplayStatus;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.Profile;
+import android.provider.Settings;
+import android.util.Log;
+import android.util.Pair;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+
+
+/**
+ *
+ */
+class QuickSettings {
+    private static final String TAG = "QuickSettings";
+    public static final boolean SHOW_IME_TILE = false;
+
+    private Context mContext;
+    private PanelBar mBar;
+    private QuickSettingsModel mModel;
+    private ViewGroup mContainerView;
+
+    private DisplayManager mDisplayManager;
+    private WifiDisplayStatus mWifiDisplayStatus;
+    private PhoneStatusBar mStatusBarService;
+    private BluetoothState mBluetoothState;
+
+    private BrightnessController mBrightnessController;
+    private BluetoothController mBluetoothController;
+
+    private Dialog mBrightnessDialog;
+    private int mBrightnessDialogShortTimeout;
+    private int mBrightnessDialogLongTimeout;
+
+    private AsyncTask<Void, Void, Pair<String, Drawable>> mUserInfoTask;
+
+    private LevelListDrawable mBatteryLevels;
+    private LevelListDrawable mChargingBatteryLevels;
+
+    boolean mTilesSetUp = false;
+
+    private Handler mHandler;
+
+    // The set of QuickSettingsTiles that have dynamic spans (and need to be updated on
+    // configuration change)
+    private final ArrayList<QuickSettingsTileView> mDynamicSpannedTiles =
+            new ArrayList<QuickSettingsTileView>();
+
+    private final RotationPolicy.RotationPolicyListener mRotationPolicyListener =
+            new RotationPolicy.RotationPolicyListener() {
+        @Override
+        public void onChange() {
+            mModel.onRotationLockChanged();
+        }
+    };
+
+    public QuickSettings(Context context, QuickSettingsContainerView container) {
+        mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
+        mContext = context;
+        mContainerView = container;
+        mModel = new QuickSettingsModel(context);
+        mWifiDisplayStatus = new WifiDisplayStatus();
+        mBluetoothState = new QuickSettingsModel.BluetoothState();
+        mHandler = new Handler();
+
+        Resources r = mContext.getResources();
+        mBatteryLevels = (LevelListDrawable) r.getDrawable(R.drawable.qs_sys_battery);
+        mChargingBatteryLevels =
+                (LevelListDrawable) r.getDrawable(R.drawable.qs_sys_battery_charging);
+        mBrightnessDialogLongTimeout =
+                r.getInteger(R.integer.quick_settings_brightness_dialog_long_timeout);
+        mBrightnessDialogShortTimeout =
+                r.getInteger(R.integer.quick_settings_brightness_dialog_short_timeout);
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
+        filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
+        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+        filter.addAction(Intent.ACTION_USER_SWITCHED);
+        mContext.registerReceiver(mReceiver, filter);
+
+        IntentFilter profileFilter = new IntentFilter();
+        profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED);
+        profileFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
+        mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter,
+                null, null);
+    }
+
+    void setBar(PanelBar bar) {
+        mBar = bar;
+    }
+
+    public void setService(PhoneStatusBar phoneStatusBar) {
+        mStatusBarService = phoneStatusBar;
+    }
+
+    public PhoneStatusBar getService() {
+        return mStatusBarService;
+    }
+
+    public void setImeWindowStatus(boolean visible) {
+        mModel.onImeWindowStatusChanged(visible);
+    }
+
+    void setup(NetworkController networkController, BluetoothController bluetoothController,
+            BatteryController batteryController, LocationController locationController) {
+        mBluetoothController = bluetoothController;
+
+        setupQuickSettings();
+        updateWifiDisplayStatus();
+        updateResources();
+
+        networkController.addNetworkSignalChangedCallback(mModel);
+        bluetoothController.addStateChangedCallback(mModel);
+        batteryController.addStateChangedCallback(mModel);
+        locationController.addStateChangedCallback(mModel);
+        RotationPolicy.registerRotationPolicyListener(mContext, mRotationPolicyListener,
+                UserHandle.USER_ALL);
+    }
+
+    private void queryForUserInformation() {
+        Context currentUserContext = null;
+        UserInfo userInfo = null;
+        try {
+            userInfo = ActivityManagerNative.getDefault().getCurrentUser();
+            currentUserContext = mContext.createPackageContextAsUser("android", 0,
+                    new UserHandle(userInfo.id));
+        } catch (NameNotFoundException e) {
+            Log.e(TAG, "Couldn't create user context", e);
+            throw new RuntimeException(e);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Couldn't get user info", e);
+        }
+        final int userId = userInfo.id;
+        final String userName = userInfo.name;
+
+        final Context context = currentUserContext;
+        mUserInfoTask = new AsyncTask<Void, Void, Pair<String, Drawable>>() {
+            @Override
+            protected Pair<String, Drawable> doInBackground(Void... params) {
+                final UserManager um =
+                        (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+
+                // Fall back to the UserManager nickname if we can't read the name from the local
+                // profile below.
+                String name = userName;
+                Drawable avatar = null;
+                Bitmap rawAvatar = um.getUserIcon(userId);
+                if (rawAvatar != null) {
+                    avatar = new BitmapDrawable(mContext.getResources(), rawAvatar);
+                } else {
+                    avatar = mContext.getResources().getDrawable(R.drawable.ic_qs_default_user);
+                }
+
+                // If it's a single-user device, get the profile name, since the nickname is not
+                // usually valid
+                if (um.getUsers().size() <= 1) {
+                    // Try and read the display name from the local profile
+                    final Cursor cursor = context.getContentResolver().query(
+                            Profile.CONTENT_URI, new String[] {Phone._ID, Phone.DISPLAY_NAME},
+                            null, null, null);
+                    if (cursor != null) {
+                        try {
+                            if (cursor.moveToFirst()) {
+                                name = cursor.getString(cursor.getColumnIndex(Phone.DISPLAY_NAME));
+                            }
+                        } finally {
+                            cursor.close();
+                        }
+                    }
+                }
+                return new Pair<String, Drawable>(name, avatar);
+            }
+
+            @Override
+            protected void onPostExecute(Pair<String, Drawable> result) {
+                super.onPostExecute(result);
+                mModel.setUserTileInfo(result.first, result.second);
+                mUserInfoTask = null;
+            }
+        };
+        mUserInfoTask.execute();
+    }
+
+    private void setupQuickSettings() {
+        // Setup the tiles that we are going to be showing (including the temporary ones)
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+
+        addUserTiles(mContainerView, inflater);
+        addSystemTiles(mContainerView, inflater);
+        addTemporaryTiles(mContainerView, inflater);
+
+        queryForUserInformation();
+        mTilesSetUp = true;
+    }
+
+    private void startSettingsActivity(String action) {
+        Intent intent = new Intent(action);
+        startSettingsActivity(intent);
+    }
+
+    private void startSettingsActivity(Intent intent) {
+        startSettingsActivity(intent, true);
+    }
+
+    private void startSettingsActivity(Intent intent, boolean onlyProvisioned) {
+        if (onlyProvisioned && !getService().isDeviceProvisioned()) return;
+        try {
+            // Dismiss the lock screen when Settings starts.
+            ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
+        } catch (RemoteException e) {
+        }
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+        getService().animateCollapsePanels();
+    }
+
+    private void addUserTiles(ViewGroup parent, LayoutInflater inflater) {
+        QuickSettingsTileView userTile = (QuickSettingsTileView)
+                inflater.inflate(R.layout.quick_settings_tile, parent, false);
+        userTile.setContent(R.layout.quick_settings_tile_user, inflater);
+        userTile.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mBar.collapseAllPanels(true);
+                final UserManager um =
+                        (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+                if (um.getUsers(true).size() > 1) {
+                    try {
+                        WindowManagerGlobal.getWindowManagerService().lockNow(
+                                LockPatternUtils.USER_SWITCH_LOCK_OPTIONS);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Couldn't show user switcher", e);
+                    }
+                } else {
+                    Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
+                            mContext, v, ContactsContract.Profile.CONTENT_URI,
+                            ContactsContract.QuickContact.MODE_LARGE, null);
+                    mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+                }
+            }
+        });
+        mModel.addUserTile(userTile, new QuickSettingsModel.RefreshCallback() {
+            @Override
+            public void refreshView(QuickSettingsTileView view, State state) {
+                UserState us = (UserState) state;
+                ImageView iv = (ImageView) view.findViewById(R.id.user_imageview);
+                TextView tv = (TextView) view.findViewById(R.id.user_textview);
+                tv.setText(state.label);
+                iv.setImageDrawable(us.avatar);
+                view.setContentDescription(mContext.getString(
+                        R.string.accessibility_quick_settings_user, state.label));
+            }
+        });
+        parent.addView(userTile);
+        mDynamicSpannedTiles.add(userTile);
+
+        // Brightness
+        QuickSettingsTileView brightnessTile = (QuickSettingsTileView)
+                inflater.inflate(R.layout.quick_settings_tile, parent, false);
+        brightnessTile.setContent(R.layout.quick_settings_tile_brightness, inflater);
+        brightnessTile.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mBar.collapseAllPanels(true);
+                showBrightnessDialog();
+            }
+        });
+        mModel.addBrightnessTile(brightnessTile, new QuickSettingsModel.RefreshCallback() {
+            @Override
+            public void refreshView(QuickSettingsTileView view, State state) {
+                TextView tv = (TextView) view.findViewById(R.id.brightness_textview);
+                tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
+                tv.setText(state.label);
+                dismissBrightnessDialog(mBrightnessDialogShortTimeout);
+            }
+        });
+        parent.addView(brightnessTile);
+        mDynamicSpannedTiles.add(brightnessTile);
+
+        // Time tile
+        /*
+        QuickSettingsTileView timeTile = (QuickSettingsTileView)
+                inflater.inflate(R.layout.quick_settings_tile, parent, false);
+        timeTile.setContent(R.layout.quick_settings_tile_time, inflater);
+        timeTile.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // Quick. Clock. Quick. Clock. Quick. Clock.
+                startSettingsActivity(Intent.ACTION_QUICK_CLOCK);
+            }
+        });
+        mModel.addTimeTile(timeTile, new QuickSettingsModel.RefreshCallback() {
+            @Override
+            public void refreshView(QuickSettingsTileView view, State alarmState) {}
+        });
+        parent.addView(timeTile);
+        mDynamicSpannedTiles.add(timeTile);
+        */
+
+        // Settings tile
+        QuickSettingsTileView settingsTile = (QuickSettingsTileView)
+                inflater.inflate(R.layout.quick_settings_tile, parent, false);
+        settingsTile.setContent(R.layout.quick_settings_tile_settings, inflater);
+        settingsTile.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                startSettingsActivity(android.provider.Settings.ACTION_SETTINGS);
+            }
+        });
+        mModel.addSettingsTile(settingsTile, new QuickSettingsModel.RefreshCallback() {
+            @Override
+            public void refreshView(QuickSettingsTileView view, State state) {
+                TextView tv = (TextView) view.findViewById(R.id.settings_tileview);
+                tv.setText(state.label);
+            }
+        });
+        parent.addView(settingsTile);
+        mDynamicSpannedTiles.add(settingsTile);
+    }
+
+    private void addSystemTiles(ViewGroup parent, LayoutInflater inflater) {
+        // Wi-fi
+        QuickSettingsTileView wifiTile = (QuickSettingsTileView)
+                inflater.inflate(R.layout.quick_settings_tile, parent, false);
+        wifiTile.setContent(R.layout.quick_settings_tile_wifi, inflater);
+        wifiTile.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                startSettingsActivity(android.provider.Settings.ACTION_WIFI_SETTINGS);
+            }
+        });
+        mModel.addWifiTile(wifiTile, new QuickSettingsModel.RefreshCallback() {
+            @Override
+            public void refreshView(QuickSettingsTileView view, State state) {
+                WifiState wifiState = (WifiState) state;
+                TextView tv = (TextView) view.findViewById(R.id.wifi_textview);
+                tv.setCompoundDrawablesWithIntrinsicBounds(0, wifiState.iconId, 0, 0);
+                tv.setText(wifiState.label);
+                view.setContentDescription(mContext.getString(
+                        R.string.accessibility_quick_settings_wifi,
+                        wifiState.signalContentDescription,
+                        (wifiState.connected) ? wifiState.label : ""));
+            }
+        });
+        parent.addView(wifiTile);
+
+        if (mModel.deviceSupportsTelephony()) {
+            // RSSI
+            QuickSettingsTileView rssiTile = (QuickSettingsTileView)
+                    inflater.inflate(R.layout.quick_settings_tile, parent, false);
+            rssiTile.setContent(R.layout.quick_settings_tile_rssi, inflater);
+            rssiTile.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    Intent intent = new Intent();
+                    intent.setComponent(new ComponentName(
+                            "com.android.settings",
+                            "com.android.settings.Settings$DataUsageSummaryActivity"));
+                    startSettingsActivity(intent);
+                }
+            });
+            mModel.addRSSITile(rssiTile, new QuickSettingsModel.RefreshCallback() {
+                @Override
+                public void refreshView(QuickSettingsTileView view, State state) {
+                    RSSIState rssiState = (RSSIState) state;
+                    ImageView iv = (ImageView) view.findViewById(R.id.rssi_image);
+                    ImageView iov = (ImageView) view.findViewById(R.id.rssi_overlay_image);
+                    TextView tv = (TextView) view.findViewById(R.id.rssi_textview);
+                    iv.setImageResource(rssiState.signalIconId);
+
+                    if (rssiState.dataTypeIconId > 0) {
+                        iov.setImageResource(rssiState.dataTypeIconId);
+                    } else {
+                        iov.setImageDrawable(null);
+                    }
+                    tv.setText(state.label);
+                    view.setContentDescription(mContext.getResources().getString(
+                            R.string.accessibility_quick_settings_mobile,
+                            rssiState.signalContentDescription, rssiState.dataContentDescription,
+                            state.label));
+                }
+            });
+            parent.addView(rssiTile);
+        }
+
+        // Rotation Lock
+        if (mContext.getResources().getBoolean(R.bool.quick_settings_show_rotation_lock)) {
+            QuickSettingsTileView rotationLockTile = (QuickSettingsTileView)
+                    inflater.inflate(R.layout.quick_settings_tile, parent, false);
+            rotationLockTile.setContent(R.layout.quick_settings_tile_rotation_lock, inflater);
+            rotationLockTile.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    boolean locked = RotationPolicy.isRotationLocked(mContext);
+                    RotationPolicy.setRotationLock(mContext, !locked);
+                }
+            });
+            mModel.addRotationLockTile(rotationLockTile, new QuickSettingsModel.RefreshCallback() {
+                @Override
+                public void refreshView(QuickSettingsTileView view, State state) {
+                    TextView tv = (TextView) view.findViewById(R.id.rotation_lock_textview);
+                    tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
+                    tv.setText(state.label);
+                }
+            });
+            parent.addView(rotationLockTile);
+        }
+
+        // Battery
+        QuickSettingsTileView batteryTile = (QuickSettingsTileView)
+                inflater.inflate(R.layout.quick_settings_tile, parent, false);
+        batteryTile.setContent(R.layout.quick_settings_tile_battery, inflater);
+        batteryTile.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                startSettingsActivity(Intent.ACTION_POWER_USAGE_SUMMARY);
+            }
+        });
+        mModel.addBatteryTile(batteryTile, new QuickSettingsModel.RefreshCallback() {
+            @Override
+            public void refreshView(QuickSettingsTileView view, State state) {
+                QuickSettingsModel.BatteryState batteryState =
+                        (QuickSettingsModel.BatteryState) state;
+                TextView tv = (TextView) view.findViewById(R.id.battery_textview);
+                ImageView iv = (ImageView) view.findViewById(R.id.battery_image);
+                Drawable d = batteryState.pluggedIn
+                        ? mChargingBatteryLevels
+                        : mBatteryLevels;
+                String t;
+                if (batteryState.batteryLevel == 100) {
+                    t = mContext.getString(R.string.quick_settings_battery_charged_label);
+                } else {
+                    t = batteryState.pluggedIn
+                        ? mContext.getString(R.string.quick_settings_battery_charging_label,
+                                batteryState.batteryLevel)
+                        : mContext.getString(R.string.status_bar_settings_battery_meter_format,
+                                batteryState.batteryLevel);
+                }
+                iv.setImageDrawable(d);
+                iv.setImageLevel(batteryState.batteryLevel);
+                tv.setText(t);
+                view.setContentDescription(
+                        mContext.getString(R.string.accessibility_quick_settings_battery, t));
+            }
+        });
+        parent.addView(batteryTile);
+
+        // Airplane Mode
+        QuickSettingsTileView airplaneTile = (QuickSettingsTileView)
+                inflater.inflate(R.layout.quick_settings_tile, parent, false);
+        airplaneTile.setContent(R.layout.quick_settings_tile_airplane, inflater);
+        mModel.addAirplaneModeTile(airplaneTile, new QuickSettingsModel.RefreshCallback() {
+            @Override
+            public void refreshView(QuickSettingsTileView view, State state) {
+                TextView tv = (TextView) view.findViewById(R.id.airplane_mode_textview);
+                tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
+
+                String airplaneState = mContext.getString(
+                        (state.enabled) ? R.string.accessibility_desc_on
+                                : R.string.accessibility_desc_off);
+                view.setContentDescription(
+                        mContext.getString(R.string.accessibility_quick_settings_airplane, airplaneState));
+                tv.setText(state.label);
+            }
+        });
+        parent.addView(airplaneTile);
+
+        // Bluetooth
+        if (mModel.deviceSupportsBluetooth()) {
+            QuickSettingsTileView bluetoothTile = (QuickSettingsTileView)
+                    inflater.inflate(R.layout.quick_settings_tile, parent, false);
+            bluetoothTile.setContent(R.layout.quick_settings_tile_bluetooth, inflater);
+            bluetoothTile.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    startSettingsActivity(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS);
+                }
+            });
+            mModel.addBluetoothTile(bluetoothTile, new QuickSettingsModel.RefreshCallback() {
+                @Override
+                public void refreshView(QuickSettingsTileView view, State state) {
+                    BluetoothState bluetoothState = (BluetoothState) state;
+                    TextView tv = (TextView) view.findViewById(R.id.bluetooth_textview);
+                    tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
+
+                    Resources r = mContext.getResources();
+                    String label = state.label;
+                    /*
+                    //TODO: Show connected bluetooth device label
+                    Set<BluetoothDevice> btDevices =
+                            mBluetoothController.getBondedBluetoothDevices();
+                    if (btDevices.size() == 1) {
+                        // Show the name of the bluetooth device you are connected to
+                        label = btDevices.iterator().next().getName();
+                    } else if (btDevices.size() > 1) {
+                        // Show a generic label about the number of bluetooth devices
+                        label = r.getString(R.string.quick_settings_bluetooth_multiple_devices_label,
+                                btDevices.size());
+                    }
+                    */
+                    view.setContentDescription(mContext.getString(
+                            R.string.accessibility_quick_settings_bluetooth,
+                            bluetoothState.stateContentDescription));
+                    tv.setText(label);
+                }
+            });
+            parent.addView(bluetoothTile);
+        }
+
+    }
+
+    private void addTemporaryTiles(final ViewGroup parent, final LayoutInflater inflater) {
+        // Alarm tile
+        QuickSettingsTileView alarmTile = (QuickSettingsTileView)
+                inflater.inflate(R.layout.quick_settings_tile, parent, false);
+        alarmTile.setContent(R.layout.quick_settings_tile_alarm, inflater);
+        alarmTile.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // TODO: Jump into the alarm application
+                Intent intent = new Intent();
+                intent.setComponent(new ComponentName(
+                        "com.google.android.deskclock",
+                        "com.android.deskclock.AlarmClock"));
+                startSettingsActivity(intent);
+            }
+        });
+        mModel.addAlarmTile(alarmTile, new QuickSettingsModel.RefreshCallback() {
+            @Override
+            public void refreshView(QuickSettingsTileView view, State alarmState) {
+                TextView tv = (TextView) view.findViewById(R.id.alarm_textview);
+                tv.setText(alarmState.label);
+                view.setVisibility(alarmState.enabled ? View.VISIBLE : View.GONE);
+                view.setContentDescription(mContext.getString(
+                        R.string.accessibility_quick_settings_alarm, alarmState.label));
+            }
+        });
+        parent.addView(alarmTile);
+
+        // Location
+        QuickSettingsTileView locationTile = (QuickSettingsTileView)
+                inflater.inflate(R.layout.quick_settings_tile, parent, false);
+        locationTile.setContent(R.layout.quick_settings_tile_location, inflater);
+        locationTile.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                startSettingsActivity(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+            }
+        });
+        mModel.addLocationTile(locationTile, new QuickSettingsModel.RefreshCallback() {
+            @Override
+            public void refreshView(QuickSettingsTileView view, State state) {
+                TextView tv = (TextView) view.findViewById(R.id.location_textview);
+                tv.setText(state.label);
+                view.setVisibility(state.enabled ? View.VISIBLE : View.GONE);
+            }
+        });
+        parent.addView(locationTile);
+
+        // Wifi Display
+        QuickSettingsTileView wifiDisplayTile = (QuickSettingsTileView)
+                inflater.inflate(R.layout.quick_settings_tile, parent, false);
+        wifiDisplayTile.setContent(R.layout.quick_settings_tile_wifi_display, inflater);
+        wifiDisplayTile.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                startSettingsActivity(android.provider.Settings.ACTION_WIFI_DISPLAY_SETTINGS);
+            }
+        });
+        mModel.addWifiDisplayTile(wifiDisplayTile, new QuickSettingsModel.RefreshCallback() {
+            @Override
+            public void refreshView(QuickSettingsTileView view, State state) {
+                TextView tv = (TextView) view.findViewById(R.id.wifi_display_textview);
+                tv.setText(state.label);
+                tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
+                view.setVisibility(state.enabled ? View.VISIBLE : View.GONE);
+            }
+        });
+        parent.addView(wifiDisplayTile);
+
+        if (SHOW_IME_TILE) {
+            // IME
+            QuickSettingsTileView imeTile = (QuickSettingsTileView)
+                    inflater.inflate(R.layout.quick_settings_tile, parent, false);
+            imeTile.setContent(R.layout.quick_settings_tile_ime, inflater);
+            imeTile.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    try {
+                        mBar.collapseAllPanels(true);
+                        Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
+                        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+                        pendingIntent.send();
+                    } catch (Exception e) {}
+                }
+            });
+            mModel.addImeTile(imeTile, new QuickSettingsModel.RefreshCallback() {
+                @Override
+                public void refreshView(QuickSettingsTileView view, State state) {
+                    TextView tv = (TextView) view.findViewById(R.id.ime_textview);
+                    if (state.label != null) {
+                        tv.setText(state.label);
+                    }
+                    view.setVisibility(state.enabled ? View.VISIBLE : View.GONE);
+                }
+            });
+            parent.addView(imeTile);
+        }
+
+        // Bug reports
+        QuickSettingsTileView bugreportTile = (QuickSettingsTileView)
+                inflater.inflate(R.layout.quick_settings_tile, parent, false);
+        bugreportTile.setContent(R.layout.quick_settings_tile_bugreport, inflater);
+        bugreportTile.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mBar.collapseAllPanels(true);
+                showBugreportDialog();
+            }
+        });
+        mModel.addBugreportTile(bugreportTile, new QuickSettingsModel.RefreshCallback() {
+            @Override
+            public void refreshView(QuickSettingsTileView view, State state) {
+                view.setVisibility(state.enabled ? View.VISIBLE : View.GONE);
+            }
+        });
+        parent.addView(bugreportTile);
+        /*
+        QuickSettingsTileView mediaTile = (QuickSettingsTileView)
+                inflater.inflate(R.layout.quick_settings_tile, parent, false);
+        mediaTile.setContent(R.layout.quick_settings_tile_media, inflater);
+        parent.addView(mediaTile);
+        QuickSettingsTileView imeTile = (QuickSettingsTileView)
+                inflater.inflate(R.layout.quick_settings_tile, parent, false);
+        imeTile.setContent(R.layout.quick_settings_tile_ime, inflater);
+        imeTile.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                parent.removeViewAt(0);
+            }
+        });
+        parent.addView(imeTile);
+        */
+    }
+
+    void updateResources() {
+        Resources r = mContext.getResources();
+
+        // Update the model
+        mModel.updateResources();
+
+        // Update the User, Time, and Settings tiles spans, and reset everything else
+        int span = r.getInteger(R.integer.quick_settings_user_time_settings_tile_span);
+        for (QuickSettingsTileView v : mDynamicSpannedTiles) {
+            v.setColumnSpan(span);
+        }
+        ((QuickSettingsContainerView)mContainerView).updateResources();
+        mContainerView.requestLayout();
+
+        // Reset the dialog
+        boolean isBrightnessDialogVisible = false;
+        if (mBrightnessDialog != null) {
+            removeAllBrightnessDialogCallbacks();
+
+            isBrightnessDialogVisible = mBrightnessDialog.isShowing();
+            mBrightnessDialog.dismiss();
+        }
+        mBrightnessDialog = null;
+        if (isBrightnessDialogVisible) {
+            showBrightnessDialog();
+        }
+    }
+
+    private void removeAllBrightnessDialogCallbacks() {
+        mHandler.removeCallbacks(mDismissBrightnessDialogRunnable);
+    }
+
+    private Runnable mDismissBrightnessDialogRunnable = new Runnable() {
+        public void run() {
+            if (mBrightnessDialog != null && mBrightnessDialog.isShowing()) {
+                mBrightnessDialog.dismiss();
+            }
+            removeAllBrightnessDialogCallbacks();
+        };
+    };
+
+    private void showBrightnessDialog() {
+        if (mBrightnessDialog == null) {
+            mBrightnessDialog = new Dialog(mContext);
+            mBrightnessDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+            mBrightnessDialog.setContentView(R.layout.quick_settings_brightness_dialog);
+            mBrightnessDialog.setCanceledOnTouchOutside(true);
+
+            mBrightnessController = new BrightnessController(mContext,
+                    (ImageView) mBrightnessDialog.findViewById(R.id.brightness_icon),
+                    (ToggleSlider) mBrightnessDialog.findViewById(R.id.brightness_slider));
+            mBrightnessController.addStateChangedCallback(mModel);
+            mBrightnessDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+                @Override
+                public void onDismiss(DialogInterface dialog) {
+                    mBrightnessController = null;
+                }
+            });
+
+            mBrightnessDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+            mBrightnessDialog.getWindow().getAttributes().privateFlags |=
+                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+            mBrightnessDialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+        }
+        if (!mBrightnessDialog.isShowing()) {
+            try {
+                WindowManagerGlobal.getWindowManagerService().dismissKeyguard();
+            } catch (RemoteException e) {
+            }
+            mBrightnessDialog.show();
+            dismissBrightnessDialog(mBrightnessDialogLongTimeout);
+        }
+    }
+
+    private void dismissBrightnessDialog(int timeout) {
+        removeAllBrightnessDialogCallbacks();
+        if (mBrightnessDialog != null) {
+            mHandler.postDelayed(mDismissBrightnessDialogRunnable, timeout);
+        }
+    }
+
+    private void showBugreportDialog() {
+        final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
+        builder.setPositiveButton(com.android.internal.R.string.report, new OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                if (which == DialogInterface.BUTTON_POSITIVE) {
+                    // Add a little delay before executing, to give the
+                    // dialog a chance to go away before it takes a
+                    // screenshot.
+                    mHandler.postDelayed(new Runnable() {
+                        @Override public void run() {
+                            try {
+                                ActivityManagerNative.getDefault()
+                                        .requestBugReport();
+                            } catch (RemoteException e) {
+                            }
+                        }
+                    }, 500);
+                }
+            }
+        });
+        builder.setMessage(com.android.internal.R.string.bugreport_message);
+        builder.setTitle(com.android.internal.R.string.bugreport_title);
+        builder.setCancelable(true);
+        final Dialog dialog = builder.create();
+        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        try {
+            WindowManagerGlobal.getWindowManagerService().dismissKeyguard();
+        } catch (RemoteException e) {
+        }
+        dialog.show();
+    }
+
+    private void updateWifiDisplayStatus() {
+        mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus();
+        applyWifiDisplayStatus();
+    }
+
+    private void applyWifiDisplayStatus() {
+        mModel.onWifiDisplayStateChanged(mWifiDisplayStatus);
+    }
+
+    private void applyBluetoothStatus() {
+        mModel.onBluetoothStateChange(mBluetoothState);
+    }
+
+    void reloadUserInfo() {
+        if (mUserInfoTask != null) {
+            mUserInfoTask.cancel(false);
+            mUserInfoTask = null;
+        }
+        if (mTilesSetUp) {
+            queryForUserInformation();
+        }
+    }
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            if (DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED.equals(action)) {
+                WifiDisplayStatus status = (WifiDisplayStatus)intent.getParcelableExtra(
+                        DisplayManager.EXTRA_WIFI_DISPLAY_STATUS);
+                mWifiDisplayStatus = status;
+                applyWifiDisplayStatus();
+            } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
+                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
+                        BluetoothAdapter.ERROR);
+                mBluetoothState.enabled = (state == BluetoothAdapter.STATE_ON);
+                applyBluetoothStatus();
+            } else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
+                int status = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
+                        BluetoothAdapter.STATE_DISCONNECTED);
+                mBluetoothState.connected = (status == BluetoothAdapter.STATE_CONNECTED);
+                applyBluetoothStatus();
+            } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                reloadUserInfo();
+            }
+        }
+    };
+
+    private final BroadcastReceiver mProfileReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            if (ContactsContract.Intents.ACTION_PROFILE_CHANGED.equals(action) ||
+                    Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
+                try {
+                    final int userId = ActivityManagerNative.getDefault().getCurrentUser().id;
+                    if (getSendingUserId() == userId) {
+                        reloadUserInfo();
+                    }
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Couldn't get current user id for profile change", e);
+                }
+            }
+
+        }
+    };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java
new file mode 100644
index 0000000..4e8339e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.animation.LayoutTransition;
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.systemui.R;
+
+/**
+ *
+ */
+class QuickSettingsContainerView extends FrameLayout {
+
+    // The number of columns in the QuickSettings grid
+    private int mNumColumns;
+
+    // The gap between tiles in the QuickSettings grid
+    private float mCellGap;
+
+    public QuickSettingsContainerView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        updateResources();
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        // TODO: Setup the layout transitions
+        LayoutTransition transitions = getLayoutTransition();
+    }
+
+    void updateResources() {
+        Resources r = getContext().getResources();
+        mCellGap = r.getDimension(R.dimen.quick_settings_cell_gap);
+        mNumColumns = r.getInteger(R.integer.quick_settings_num_columns);
+        requestLayout();
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // Calculate the cell width dynamically
+        int width = MeasureSpec.getSize(widthMeasureSpec);
+        int height = MeasureSpec.getSize(heightMeasureSpec);
+        int availableWidth = (int) (width - getPaddingLeft() - getPaddingRight() -
+                (mNumColumns - 1) * mCellGap);
+        float cellWidth = (float) Math.ceil(((float) availableWidth) / mNumColumns);
+
+        // Update each of the children's widths accordingly to the cell width
+        int N = getChildCount();
+        int cellHeight = 0;
+        int cursor = 0;
+        for (int i = 0; i < N; ++i) {
+            // Update the child's width
+            QuickSettingsTileView v = (QuickSettingsTileView) getChildAt(i);
+            if (v.getVisibility() != View.GONE) {
+                ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
+                int colSpan = v.getColumnSpan();
+                lp.width = (int) ((colSpan * cellWidth) + (colSpan - 1) * mCellGap);
+
+                // Measure the child
+                int newWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
+                int newHeightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
+                v.measure(newWidthSpec, newHeightSpec);
+
+                // Save the cell height
+                if (cellHeight <= 0) {
+                    cellHeight = v.getMeasuredHeight();
+                }
+                cursor += colSpan;
+            }
+        }
+
+        // Set the measured dimensions.  We always fill the tray width, but wrap to the height of
+        // all the tiles.
+        int numRows = (int) Math.ceil((float) cursor / mNumColumns);
+        int newHeight = (int) ((numRows * cellHeight) + ((numRows - 1) * mCellGap)) +
+                getPaddingTop() + getPaddingBottom();
+        setMeasuredDimension(width, newHeight);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        int N = getChildCount();
+        int x = getPaddingLeft();
+        int y = getPaddingTop();
+        int cursor = 0;
+        for (int i = 0; i < N; ++i) {
+            QuickSettingsTileView v = (QuickSettingsTileView) getChildAt(i);
+            ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) v.getLayoutParams();
+            if (v.getVisibility() != GONE) {
+                int col = cursor % mNumColumns;
+                int colSpan = v.getColumnSpan();
+                int row = (int) (cursor / mNumColumns);
+
+                // Push the item to the next row if it can't fit on this one
+                if ((col + colSpan) > mNumColumns) {
+                    x = getPaddingLeft();
+                    y += lp.height + mCellGap;
+                    row++;
+                }
+
+                // Layout the container
+                v.layout(x, y, x + lp.width, y + lp.height);
+
+                // Offset the position by the cell gap or reset the position and cursor when we
+                // reach the end of the row
+                cursor += v.getColumnSpan();
+                if (cursor < (((row + 1) * mNumColumns))) {
+                    x += lp.width + mCellGap;
+                } else {
+                    x = getPaddingLeft();
+                    y += lp.height + mCellGap;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
new file mode 100644
index 0000000..4513dcb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -0,0 +1,702 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.app.ActivityManager;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothAdapter.BluetoothStateChangeCallback;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.graphics.drawable.Drawable;
+import android.hardware.display.WifiDisplayStatus;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.internal.view.RotationPolicy;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
+import com.android.systemui.statusbar.policy.BrightnessController.BrightnessStateChangeCallback;
+import com.android.systemui.statusbar.policy.CurrentUserTracker;
+import com.android.systemui.statusbar.policy.LocationController.LocationGpsStateChangeCallback;
+import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
+
+import java.util.List;
+
+
+class QuickSettingsModel implements BluetoothStateChangeCallback,
+        NetworkSignalChangedCallback,
+        BatteryStateChangeCallback,
+        LocationGpsStateChangeCallback,
+        BrightnessStateChangeCallback {
+
+    // Sett InputMethoManagerService
+    private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
+
+    /** Represents the state of a given attribute. */
+    static class State {
+        int iconId;
+        String label;
+        boolean enabled = false;
+    }
+    static class BatteryState extends State {
+        int batteryLevel;
+        boolean pluggedIn;
+    }
+    static class RSSIState extends State {
+        int signalIconId;
+        String signalContentDescription;
+        int dataTypeIconId;
+        String dataContentDescription;
+    }
+    static class WifiState extends State {
+        String signalContentDescription;
+        boolean connected;
+    }
+    static class UserState extends State {
+        Drawable avatar;
+    }
+    static class BrightnessState extends State {
+        boolean autoBrightness;
+    }
+    public static class BluetoothState extends State {
+        boolean connected = false;
+        String stateContentDescription;
+    }
+
+    /** The callback to update a given tile. */
+    interface RefreshCallback {
+        public void refreshView(QuickSettingsTileView view, State state);
+    }
+
+    /** Broadcast receive to determine if there is an alarm set. */
+    private BroadcastReceiver mAlarmIntentReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (action.equals(Intent.ACTION_ALARM_CHANGED)) {
+                onAlarmChanged(intent);
+                onNextAlarmChanged();
+            }
+        }
+    };
+
+    /** ContentObserver to determine the next alarm */
+    private class NextAlarmObserver extends ContentObserver {
+        public NextAlarmObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override public void onChange(boolean selfChange) {
+            onNextAlarmChanged();
+        }
+
+        public void startObserving() {
+            final ContentResolver cr = mContext.getContentResolver();
+            cr.registerContentObserver(
+                    Settings.System.getUriFor(Settings.System.NEXT_ALARM_FORMATTED), false, this);
+        }
+    }
+
+    /** ContentObserver to watch adb */
+    private class BugreportObserver extends ContentObserver {
+        public BugreportObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override public void onChange(boolean selfChange) {
+            onBugreportChanged();
+        }
+
+        public void startObserving() {
+            final ContentResolver cr = mContext.getContentResolver();
+            cr.registerContentObserver(
+                    Settings.Secure.getUriFor(Settings.Secure.BUGREPORT_IN_POWER_MENU), false, this);
+        }
+    }
+
+    /** ContentObserver to watch brightness **/
+    private class BrightnessObserver extends ContentObserver {
+        public BrightnessObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            onBrightnessLevelChanged();
+        }
+
+        public void startObserving() {
+            final ContentResolver cr = mContext.getContentResolver();
+            cr.unregisterContentObserver(this);
+            cr.registerContentObserver(
+                    Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE),
+                    false, this, mUserTracker.getCurrentUserId());
+            cr.registerContentObserver(
+                    Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS),
+                    false, this, mUserTracker.getCurrentUserId());
+        }
+    }
+
+    private final Context mContext;
+    private final Handler mHandler;
+    private final CurrentUserTracker mUserTracker;
+    private final NextAlarmObserver mNextAlarmObserver;
+    private final BugreportObserver mBugreportObserver;
+    private final BrightnessObserver mBrightnessObserver;
+
+    private QuickSettingsTileView mUserTile;
+    private RefreshCallback mUserCallback;
+    private UserState mUserState = new UserState();
+
+    private QuickSettingsTileView mTimeTile;
+    private RefreshCallback mTimeCallback;
+    private State mTimeState = new State();
+
+    private QuickSettingsTileView mAlarmTile;
+    private RefreshCallback mAlarmCallback;
+    private State mAlarmState = new State();
+
+    private QuickSettingsTileView mAirplaneModeTile;
+    private RefreshCallback mAirplaneModeCallback;
+    private State mAirplaneModeState = new State();
+
+    private QuickSettingsTileView mWifiTile;
+    private RefreshCallback mWifiCallback;
+    private WifiState mWifiState = new WifiState();
+
+    private QuickSettingsTileView mWifiDisplayTile;
+    private RefreshCallback mWifiDisplayCallback;
+    private State mWifiDisplayState = new State();
+
+    private QuickSettingsTileView mRSSITile;
+    private RefreshCallback mRSSICallback;
+    private RSSIState mRSSIState = new RSSIState();
+
+    private QuickSettingsTileView mBluetoothTile;
+    private RefreshCallback mBluetoothCallback;
+    private BluetoothState mBluetoothState = new BluetoothState();
+
+    private QuickSettingsTileView mBatteryTile;
+    private RefreshCallback mBatteryCallback;
+    private BatteryState mBatteryState = new BatteryState();
+
+    private QuickSettingsTileView mLocationTile;
+    private RefreshCallback mLocationCallback;
+    private State mLocationState = new State();
+
+    private QuickSettingsTileView mImeTile;
+    private RefreshCallback mImeCallback = null;
+    private State mImeState = new State();
+
+    private QuickSettingsTileView mRotationLockTile;
+    private RefreshCallback mRotationLockCallback;
+    private State mRotationLockState = new State();
+
+    private QuickSettingsTileView mBrightnessTile;
+    private RefreshCallback mBrightnessCallback;
+    private BrightnessState mBrightnessState = new BrightnessState();
+
+    private QuickSettingsTileView mBugreportTile;
+    private RefreshCallback mBugreportCallback;
+    private State mBugreportState = new State();
+
+    private QuickSettingsTileView mSettingsTile;
+    private RefreshCallback mSettingsCallback;
+    private State mSettingsState = new State();
+
+    public QuickSettingsModel(Context context) {
+        mContext = context;
+        mHandler = new Handler();
+        mUserTracker = new CurrentUserTracker(mContext) {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                super.onReceive(context, intent);
+                onUserSwitched();
+            }
+        };
+
+        mNextAlarmObserver = new NextAlarmObserver(mHandler);
+        mNextAlarmObserver.startObserving();
+        mBugreportObserver = new BugreportObserver(mHandler);
+        mBugreportObserver.startObserving();
+        mBrightnessObserver = new BrightnessObserver(mHandler);
+        mBrightnessObserver.startObserving();
+
+        IntentFilter alarmIntentFilter = new IntentFilter();
+        alarmIntentFilter.addAction(Intent.ACTION_ALARM_CHANGED);
+        context.registerReceiver(mAlarmIntentReceiver, alarmIntentFilter);
+    }
+
+    void updateResources() {
+        refreshSettingsTile();
+        refreshBatteryTile();
+        refreshBluetoothTile();
+        refreshBrightnessTile();
+        refreshRotationLockTile();
+    }
+
+    // Settings
+    void addSettingsTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mSettingsTile = view;
+        mSettingsCallback = cb;
+        refreshSettingsTile();
+    }
+    void refreshSettingsTile() {
+        Resources r = mContext.getResources();
+        mSettingsState.label = r.getString(R.string.quick_settings_settings_label);
+        mSettingsCallback.refreshView(mSettingsTile, mSettingsState);
+    }
+
+    // User
+    void addUserTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mUserTile = view;
+        mUserCallback = cb;
+        mUserCallback.refreshView(mUserTile, mUserState);
+    }
+    void setUserTileInfo(String name, Drawable avatar) {
+        mUserState.label = name;
+        mUserState.avatar = avatar;
+        mUserCallback.refreshView(mUserTile, mUserState);
+    }
+
+    // Time
+    void addTimeTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mTimeTile = view;
+        mTimeCallback = cb;
+        mTimeCallback.refreshView(view, mTimeState);
+    }
+
+    // Alarm
+    void addAlarmTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mAlarmTile = view;
+        mAlarmCallback = cb;
+        mAlarmCallback.refreshView(view, mAlarmState);
+    }
+    void onAlarmChanged(Intent intent) {
+        mAlarmState.enabled = intent.getBooleanExtra("alarmSet", false);
+        mAlarmCallback.refreshView(mAlarmTile, mAlarmState);
+    }
+    void onNextAlarmChanged() {
+        mAlarmState.label = Settings.System.getString(mContext.getContentResolver(),
+                Settings.System.NEXT_ALARM_FORMATTED);
+        mAlarmCallback.refreshView(mAlarmTile, mAlarmState);
+    }
+
+    // Airplane Mode
+    void addAirplaneModeTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mAirplaneModeTile = view;
+        mAirplaneModeTile.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mAirplaneModeState.enabled) {
+                    setAirplaneModeState(false);
+                } else {
+                    setAirplaneModeState(true);
+                }
+            }
+        });
+        mAirplaneModeCallback = cb;
+        int airplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, 0);
+        onAirplaneModeChanged(airplaneMode != 0);
+    }
+    private void setAirplaneModeState(boolean enabled) {
+        // TODO: Sets the view to be "awaiting" if not already awaiting
+
+        // Change the system setting
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON,
+                                enabled ? 1 : 0);
+
+        // Post the intent
+        Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+        intent.putExtra("state", enabled);
+        mContext.sendBroadcast(intent);
+    }
+    // NetworkSignalChanged callback
+    @Override
+    public void onAirplaneModeChanged(boolean enabled) {
+        // TODO: If view is in awaiting state, disable
+        Resources r = mContext.getResources();
+        mAirplaneModeState.enabled = enabled;
+        mAirplaneModeState.iconId = (enabled ?
+                R.drawable.ic_qs_airplane_on :
+                R.drawable.ic_qs_airplane_off);
+        mAirplaneModeState.label = r.getString(R.string.quick_settings_airplane_mode_label);
+        mAirplaneModeCallback.refreshView(mAirplaneModeTile, mAirplaneModeState);
+    }
+
+    // Wifi
+    void addWifiTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mWifiTile = view;
+        mWifiCallback = cb;
+        mWifiCallback.refreshView(mWifiTile, mWifiState);
+    }
+    // Remove the double quotes that the SSID may contain
+    public static String removeDoubleQuotes(String string) {
+        if (string == null) return null;
+        final int length = string.length();
+        if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
+            return string.substring(1, length - 1);
+        }
+        return string;
+    }
+    // Remove the period from the network name
+    public static String removeTrailingPeriod(String string) {
+        if (string == null) return null;
+        final int length = string.length();
+        if (string.endsWith(".")) {
+            string.substring(0, length - 1);
+        }
+        return string;
+    }
+    // NetworkSignalChanged callback
+    @Override
+    public void onWifiSignalChanged(boolean enabled, int wifiSignalIconId,
+            String wifiSignalContentDescription, String enabledDesc) {
+        // TODO: If view is in awaiting state, disable
+        Resources r = mContext.getResources();
+
+        boolean wifiConnected = enabled && (wifiSignalIconId > 0) && (enabledDesc != null);
+        boolean wifiNotConnected = (wifiSignalIconId > 0) && (enabledDesc == null);
+        mWifiState.enabled = enabled;
+        mWifiState.connected = wifiConnected;
+        if (wifiConnected) {
+            mWifiState.iconId = wifiSignalIconId;
+            mWifiState.label = removeDoubleQuotes(enabledDesc);
+            mWifiState.signalContentDescription = wifiSignalContentDescription;
+        } else if (wifiNotConnected) {
+            mWifiState.iconId = R.drawable.ic_qs_wifi_0;
+            mWifiState.label = r.getString(R.string.quick_settings_wifi_label);
+            mWifiState.signalContentDescription = r.getString(R.string.accessibility_no_wifi);
+        } else {
+            mWifiState.iconId = R.drawable.ic_qs_wifi_no_network;
+            mWifiState.label = r.getString(R.string.quick_settings_wifi_off_label);
+            mWifiState.signalContentDescription = r.getString(R.string.accessibility_wifi_off);
+        }
+        mWifiCallback.refreshView(mWifiTile, mWifiState);
+    }
+
+    // RSSI
+    void addRSSITile(QuickSettingsTileView view, RefreshCallback cb) {
+        mRSSITile = view;
+        mRSSICallback = cb;
+        mRSSICallback.refreshView(mRSSITile, mRSSIState);
+    }
+    boolean deviceSupportsTelephony() {
+        PackageManager pm = mContext.getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
+    }
+    // NetworkSignalChanged callback
+    @Override
+    public void onMobileDataSignalChanged(
+            boolean enabled, int mobileSignalIconId, String signalContentDescription,
+            int dataTypeIconId, String dataContentDescription, String enabledDesc) {
+        if (deviceSupportsTelephony()) {
+            // TODO: If view is in awaiting state, disable
+            Resources r = mContext.getResources();
+            mRSSIState.signalIconId = enabled && (mobileSignalIconId > 0)
+                    ? mobileSignalIconId
+                    : R.drawable.ic_qs_signal_no_signal;
+            mRSSIState.signalContentDescription = enabled && (mobileSignalIconId > 0)
+                    ? signalContentDescription
+                    : r.getString(R.string.accessibility_no_signal);
+            mRSSIState.dataTypeIconId = enabled && (dataTypeIconId > 0) && !mWifiState.enabled
+                    ? dataTypeIconId
+                    : 0;
+            mRSSIState.dataContentDescription = enabled && (dataTypeIconId > 0) && !mWifiState.enabled
+                    ? dataContentDescription
+                    : r.getString(R.string.accessibility_no_data);
+            mRSSIState.label = enabled
+                    ? removeTrailingPeriod(enabledDesc)
+                    : r.getString(R.string.quick_settings_rssi_emergency_only);
+            mRSSICallback.refreshView(mRSSITile, mRSSIState);
+        }
+    }
+
+    // Bluetooth
+    void addBluetoothTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mBluetoothTile = view;
+        mBluetoothCallback = cb;
+
+        final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        mBluetoothState.enabled = adapter.isEnabled();
+        mBluetoothState.connected =
+                (adapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED);
+        onBluetoothStateChange(mBluetoothState);
+    }
+    boolean deviceSupportsBluetooth() {
+        return (BluetoothAdapter.getDefaultAdapter() != null);
+    }
+    // BluetoothController callback
+    @Override
+    public void onBluetoothStateChange(boolean on) {
+        mBluetoothState.enabled = on;
+        onBluetoothStateChange(mBluetoothState);
+    }
+    public void onBluetoothStateChange(BluetoothState bluetoothStateIn) {
+        // TODO: If view is in awaiting state, disable
+        Resources r = mContext.getResources();
+        mBluetoothState.enabled = bluetoothStateIn.enabled;
+        mBluetoothState.connected = bluetoothStateIn.connected;
+        if (mBluetoothState.enabled) {
+            if (mBluetoothState.connected) {
+                mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_on;
+                mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_connected);
+            } else {
+                mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_not_connected;
+                mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_on);
+            }
+            mBluetoothState.label = r.getString(R.string.quick_settings_bluetooth_label);
+        } else {
+            mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_off;
+            mBluetoothState.label = r.getString(R.string.quick_settings_bluetooth_off_label);
+            mBluetoothState.stateContentDescription = r.getString(R.string.accessibility_desc_off);
+        }
+        mBluetoothCallback.refreshView(mBluetoothTile, mBluetoothState);
+    }
+    void refreshBluetoothTile() {
+        if (mBluetoothTile != null) {
+            onBluetoothStateChange(mBluetoothState.enabled);
+        }
+    }
+
+    // Battery
+    void addBatteryTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mBatteryTile = view;
+        mBatteryCallback = cb;
+        mBatteryCallback.refreshView(mBatteryTile, mBatteryState);
+    }
+    // BatteryController callback
+    @Override
+    public void onBatteryLevelChanged(int level, boolean pluggedIn) {
+        mBatteryState.batteryLevel = level;
+        mBatteryState.pluggedIn = pluggedIn;
+        mBatteryCallback.refreshView(mBatteryTile, mBatteryState);
+    }
+    void refreshBatteryTile() {
+        mBatteryCallback.refreshView(mBatteryTile, mBatteryState);
+    }
+
+    // Location
+    void addLocationTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mLocationTile = view;
+        mLocationCallback = cb;
+        mLocationCallback.refreshView(mLocationTile, mLocationState);
+    }
+    // LocationController callback
+    @Override
+    public void onLocationGpsStateChanged(boolean inUse, String description) {
+        mLocationState.enabled = inUse;
+        mLocationState.label = description;
+        mLocationCallback.refreshView(mLocationTile, mLocationState);
+    }
+
+    // Bug report
+    void addBugreportTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mBugreportTile = view;
+        mBugreportCallback = cb;
+        onBugreportChanged();
+    }
+    // SettingsObserver callback
+    public void onBugreportChanged() {
+        final ContentResolver cr = mContext.getContentResolver();
+        boolean enabled = false;
+        try {
+            enabled = (Settings.Secure.getInt(cr, Settings.Secure.BUGREPORT_IN_POWER_MENU) != 0);
+        } catch (SettingNotFoundException e) {
+        }
+
+        mBugreportState.enabled = enabled;
+        mBugreportCallback.refreshView(mBugreportTile, mBugreportState);
+    }
+
+    // Wifi Display
+    void addWifiDisplayTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mWifiDisplayTile = view;
+        mWifiDisplayCallback = cb;
+    }
+    public void onWifiDisplayStateChanged(WifiDisplayStatus status) {
+        mWifiDisplayState.enabled =
+                (status.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON);
+        if (status.getActiveDisplay() != null) {
+            mWifiDisplayState.label = status.getActiveDisplay().getFriendlyDisplayName();
+            mWifiDisplayState.iconId = R.drawable.ic_qs_remote_display_connected;
+        } else {
+            mWifiDisplayState.label = mContext.getString(
+                    R.string.quick_settings_wifi_display_no_connection_label);
+            mWifiDisplayState.iconId = R.drawable.ic_qs_remote_display;
+        }
+        mWifiDisplayCallback.refreshView(mWifiDisplayTile, mWifiDisplayState);
+
+    }
+
+    // IME
+    void addImeTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mImeTile = view;
+        mImeCallback = cb;
+        mImeCallback.refreshView(mImeTile, mImeState);
+    }
+    /* This implementation is taken from
+       InputMethodManagerService.needsToShowImeSwitchOngoingNotification(). */
+    private boolean needsToShowImeSwitchOngoingNotification(InputMethodManager imm) {
+        List<InputMethodInfo> imis = imm.getEnabledInputMethodList();
+        final int N = imis.size();
+        if (N > 2) return true;
+        if (N < 1) return false;
+        int nonAuxCount = 0;
+        int auxCount = 0;
+        InputMethodSubtype nonAuxSubtype = null;
+        InputMethodSubtype auxSubtype = null;
+        for(int i = 0; i < N; ++i) {
+            final InputMethodInfo imi = imis.get(i);
+            final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(imi,
+                    true);
+            final int subtypeCount = subtypes.size();
+            if (subtypeCount == 0) {
+                ++nonAuxCount;
+            } else {
+                for (int j = 0; j < subtypeCount; ++j) {
+                    final InputMethodSubtype subtype = subtypes.get(j);
+                    if (!subtype.isAuxiliary()) {
+                        ++nonAuxCount;
+                        nonAuxSubtype = subtype;
+                    } else {
+                        ++auxCount;
+                        auxSubtype = subtype;
+                    }
+                }
+            }
+        }
+        if (nonAuxCount > 1 || auxCount > 1) {
+            return true;
+        } else if (nonAuxCount == 1 && auxCount == 1) {
+            if (nonAuxSubtype != null && auxSubtype != null
+                    && (nonAuxSubtype.getLocale().equals(auxSubtype.getLocale())
+                            || auxSubtype.overridesImplicitlyEnabledSubtype()
+                            || nonAuxSubtype.overridesImplicitlyEnabledSubtype())
+                    && nonAuxSubtype.containsExtraValueKey(TAG_TRY_SUPPRESSING_IME_SWITCHER)) {
+                return false;
+            }
+            return true;
+        }
+        return false;
+    }
+    void onImeWindowStatusChanged(boolean visible) {
+        InputMethodManager imm =
+                (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+        List<InputMethodInfo> imis = imm.getInputMethodList();
+
+        mImeState.enabled = (visible && needsToShowImeSwitchOngoingNotification(imm));
+        mImeState.label = getCurrentInputMethodName(mContext, mContext.getContentResolver(),
+                imm, imis, mContext.getPackageManager());
+        if (mImeCallback != null) {
+            mImeCallback.refreshView(mImeTile, mImeState);
+        }
+    }
+    private static String getCurrentInputMethodName(Context context, ContentResolver resolver,
+            InputMethodManager imm, List<InputMethodInfo> imis, PackageManager pm) {
+        if (resolver == null || imis == null) return null;
+        final String currentInputMethodId = Settings.Secure.getString(resolver,
+                Settings.Secure.DEFAULT_INPUT_METHOD);
+        if (TextUtils.isEmpty(currentInputMethodId)) return null;
+        for (InputMethodInfo imi : imis) {
+            if (currentInputMethodId.equals(imi.getId())) {
+                final InputMethodSubtype subtype = imm.getCurrentInputMethodSubtype();
+                final CharSequence summary = subtype != null
+                        ? subtype.getDisplayName(context, imi.getPackageName(),
+                                imi.getServiceInfo().applicationInfo)
+                        : context.getString(R.string.quick_settings_ime_label);
+                return summary.toString();
+            }
+        }
+        return null;
+    }
+
+    // Rotation lock
+    void addRotationLockTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mRotationLockTile = view;
+        mRotationLockCallback = cb;
+        onRotationLockChanged();
+    }
+    void onRotationLockChanged() {
+        boolean locked = RotationPolicy.isRotationLocked(mContext);
+        mRotationLockState.enabled = locked;
+        mRotationLockState.iconId = locked
+                ? R.drawable.ic_qs_rotation_locked
+                : R.drawable.ic_qs_auto_rotate;
+        mRotationLockState.label = locked
+                ? mContext.getString(R.string.quick_settings_rotation_locked_label)
+                : mContext.getString(R.string.quick_settings_rotation_unlocked_label);
+
+        // may be called before addRotationLockTile due to RotationPolicyListener in QuickSettings
+        if (mRotationLockTile != null && mRotationLockCallback != null) {
+            mRotationLockCallback.refreshView(mRotationLockTile, mRotationLockState);
+        }
+    }
+    void refreshRotationLockTile() {
+        if (mRotationLockTile != null) {
+            onRotationLockChanged();
+        }
+    }
+
+    // Brightness
+    void addBrightnessTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mBrightnessTile = view;
+        mBrightnessCallback = cb;
+        onBrightnessLevelChanged();
+    }
+    @Override
+    public void onBrightnessLevelChanged() {
+        Resources r = mContext.getResources();
+        int mode = Settings.System.getIntForUser(mContext.getContentResolver(),
+                Settings.System.SCREEN_BRIGHTNESS_MODE,
+                Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
+                mUserTracker.getCurrentUserId());
+        mBrightnessState.autoBrightness =
+                (mode == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
+        mBrightnessState.iconId = mBrightnessState.autoBrightness
+                ? R.drawable.ic_qs_brightness_auto_on
+                : R.drawable.ic_qs_brightness_auto_off;
+        mBrightnessState.label = r.getString(R.string.quick_settings_brightness_label);
+        mBrightnessCallback.refreshView(mBrightnessTile, mBrightnessState);
+    }
+    void refreshBrightnessTile() {
+        onBrightnessLevelChanged();
+    }
+
+    // User switch: need to update visuals of all tiles known to have per-user state
+    void onUserSwitched() {
+        mBrightnessObserver.startObserving();
+        onRotationLockChanged();
+        onBrightnessLevelChanged();
+        onNextAlarmChanged();
+        onBugreportChanged();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsScrollView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsScrollView.java
new file mode 100644
index 0000000..8a2f8d6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsScrollView.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.ScrollView;
+
+public class QuickSettingsScrollView extends ScrollView {
+
+    public QuickSettingsScrollView(Context context) {
+        super(context);
+    }
+
+    public QuickSettingsScrollView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public QuickSettingsScrollView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    // Y U NO PROTECTED
+    private int getScrollRange() {
+        int scrollRange = 0;
+        if (getChildCount() > 0) {
+            View child = getChildAt(0);
+            scrollRange = Math.max(0,
+                    child.getHeight() - (getHeight() - mPaddingBottom - mPaddingTop));
+        }
+        return scrollRange;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        final int range = getScrollRange();
+        if (range == 0) {
+            return false;
+        }
+
+        return super.onTouchEvent(ev);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsTileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsTileView.java
new file mode 100644
index 0000000..8f5cde6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsTileView.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.widget.FrameLayout;
+
+/**
+ *
+ */
+class QuickSettingsTileView extends FrameLayout {
+
+    private int mColSpan;
+    private int mRowSpan;
+    private int mCellWidth;
+
+    public QuickSettingsTileView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        mColSpan = 1;
+        mRowSpan = 1;
+    }
+
+    void setColumnSpan(int span) {
+        mColSpan = span;
+    }
+
+    int getColumnSpan() {
+        return mColSpan;
+    }
+
+    void setContent(int layoutId, LayoutInflater inflater) {
+        inflater.inflate(layoutId, this);
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
new file mode 100644
index 0000000..a58eb22
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.animation.LayoutTransition;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.BaseStatusBar;
+import com.android.systemui.statusbar.GestureRecorder;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BluetoothController;
+import com.android.systemui.statusbar.policy.LocationController;
+import com.android.systemui.statusbar.policy.NetworkController;
+
+public class SettingsPanelView extends PanelView {
+
+    private QuickSettings mQS;
+    private QuickSettingsContainerView mQSContainer;
+
+    Drawable mHandleBar;
+    float mHandleBarHeight;
+    View mHandleView;
+
+    public SettingsPanelView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mQSContainer = (QuickSettingsContainerView) findViewById(R.id.quick_settings_container);
+
+        Resources resources = getContext().getResources();
+        mHandleBar = resources.getDrawable(R.drawable.status_bar_close);
+        mHandleBarHeight = resources.getDimension(R.dimen.close_handle_height);
+        mHandleView = findViewById(R.id.handle);
+
+        setContentDescription(resources.getString(R.string.accessibility_desc_quick_settings));
+    }
+    
+    public void setQuickSettings(QuickSettings qs) {
+        mQS = qs;
+    }
+
+    @Override
+    public void setBar(PanelBar panelBar) {
+        super.setBar(panelBar);
+
+        if (mQS != null) {
+            mQS.setBar(panelBar);
+        }
+    }
+
+    public void setImeWindowStatus(boolean visible) {
+        if (mQS != null) {
+            mQS.setImeWindowStatus(visible);
+        }
+    }
+
+    public void setup(NetworkController networkController, BluetoothController bluetoothController,
+            BatteryController batteryController, LocationController locationController) {
+        if (mQS != null) {
+            mQS.setup(networkController, bluetoothController, batteryController,
+                    locationController);
+        }
+    }
+
+    void updateResources() {
+        if (mQS != null) {
+            mQS.updateResources();
+        }
+        if (mQSContainer != null) {
+            mQSContainer.updateResources();
+        }
+        requestLayout();
+    }
+
+    @Override
+    public void fling(float vel, boolean always) {
+        GestureRecorder gr = ((PhoneStatusBarView) mBar).mBar.getGestureRecorder();
+        if (gr != null) {
+            gr.tag(
+                "fling " + ((vel > 0) ? "open" : "closed"),
+                "settings,v=" + vel);
+        }
+        super.fling(vel, always);
+    }
+
+    public void setService(PhoneStatusBar phoneStatusBar) {
+        if (mQS != null) {
+            mQS.setService(phoneStatusBar);
+        }
+    }
+
+    // We draw the handle ourselves so that it's always glued to the bottom of the window.
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        if (changed) {
+            final int pl = getPaddingLeft();
+            final int pr = getPaddingRight();
+            mHandleBar.setBounds(pl, 0, getWidth() - pr, (int) mHandleBarHeight);
+        }
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        super.draw(canvas);
+        final int off = (int) (getHeight() - mHandleBarHeight - getPaddingBottom());
+        canvas.translate(0, off);
+        mHandleBar.setState(mHandleView.getDrawableState());
+        mHandleBar.draw(canvas);
+        canvas.translate(0, -off);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 2628631..f526f0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -17,43 +17,52 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
+import android.view.View;
 import android.widget.FrameLayout;
 import android.widget.ScrollView;
 import android.widget.TextSwitcher;
 
 import com.android.systemui.ExpandHelper;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.policy.NotificationRowLayout;
 
 
 public class StatusBarWindowView extends FrameLayout
 {
-    private static final String TAG = "StatusBarWindowView";
+    public static final String TAG = "StatusBarWindowView";
+    public static final boolean DEBUG = BaseStatusBar.DEBUG;
 
     private ExpandHelper mExpandHelper;
     private NotificationRowLayout latestItems;
+    private NotificationPanelView mNotificationPanel;
+    private ScrollView mScrollView;
 
     PhoneStatusBar mService;
 
     public StatusBarWindowView(Context context, AttributeSet attrs) {
         super(context, attrs);
         setMotionEventSplittingEnabled(false);
+        setWillNotDraw(!DEBUG);
     }
 
     @Override
     protected void onAttachedToWindow () {
         super.onAttachedToWindow();
         latestItems = (NotificationRowLayout) findViewById(R.id.latestItems);
-        ScrollView scroller = (ScrollView) findViewById(R.id.scroll);
+        mScrollView = (ScrollView) findViewById(R.id.scroll);
+        mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);
         int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_min_height);
         int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height);
         mExpandHelper = new ExpandHelper(mContext, latestItems, minHeight, maxHeight);
         mExpandHelper.setEventSource(this);
-        mExpandHelper.setScrollView(scroller);
+        mExpandHelper.setScrollView(mScrollView);
     }
 
     @Override
@@ -62,7 +71,7 @@
         switch (event.getKeyCode()) {
         case KeyEvent.KEYCODE_BACK:
             if (!down) {
-                mService.animateCollapse();
+                mService.animateCollapsePanels();
             }
             return true;
         }
@@ -71,22 +80,50 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        MotionEvent cancellation = MotionEvent.obtain(ev);
-        cancellation.setAction(MotionEvent.ACTION_CANCEL);
-
-        boolean intercept = mExpandHelper.onInterceptTouchEvent(ev) ||
-                super.onInterceptTouchEvent(ev);
+        boolean intercept = false;
+        if (mNotificationPanel.isFullyExpanded() && mScrollView.getVisibility() == View.VISIBLE) {
+            intercept = mExpandHelper.onInterceptTouchEvent(ev);
+        }
+        if (!intercept) {
+            super.onInterceptTouchEvent(ev);
+        }
         if (intercept) {
+            MotionEvent cancellation = MotionEvent.obtain(ev);
+            cancellation.setAction(MotionEvent.ACTION_CANCEL);
             latestItems.onInterceptTouchEvent(cancellation);
+            cancellation.recycle();
         }
         return intercept;
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        boolean handled = mExpandHelper.onTouchEvent(ev) ||
-                super.onTouchEvent(ev);
+        boolean handled = false;
+        if (mNotificationPanel.isFullyExpanded()) {
+            handled = mExpandHelper.onTouchEvent(ev);
+        }
+        if (!handled) {
+            handled = super.onTouchEvent(ev);
+        }
         return handled;
     }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        if (DEBUG) {
+            Paint pt = new Paint();
+            pt.setColor(0x80FFFF00);
+            pt.setStrokeWidth(12.0f);
+            pt.setStyle(Paint.Style.STROKE);
+            canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), pt);
+        }
+    }
+
+    public void cancelExpandHelper() {
+        if (mExpandHelper != null) {
+            mExpandHelper.cancel();
+        }
+    }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
index f5ceed0..ecc70d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
@@ -53,6 +53,16 @@
     private TextSwitcher mTextSwitcher;
     private float mIconScale;
 
+    public static boolean isGraphicOrEmoji(char c) {
+        int gc = Character.getType(c);
+        return     gc != Character.CONTROL
+                && gc != Character.FORMAT
+                && gc != Character.UNASSIGNED
+                && gc != Character.LINE_SEPARATOR
+                && gc != Character.PARAGRAPH_SEPARATOR
+                && gc != Character.SPACE_SEPARATOR;
+    }
+
     private final class Segment {
         StatusBarNotification notification;
         Drawable icon;
@@ -68,7 +78,7 @@
         }
 
         CharSequence rtrim(CharSequence substr, int start, int end) {
-            while (end > start && !TextUtils.isGraphic(substr.charAt(end-1))) {
+            while (end > start && !isGraphicOrEmoji(substr.charAt(end-1))) {
                 end--;
             }
             if (end > start) {
@@ -101,7 +111,7 @@
             this.first = false;
             int index = this.next;
             final int len = this.text.length();
-            while (index < len && !TextUtils.isGraphic(this.text.charAt(index))) {
+            while (index < len && !isGraphicOrEmoji(this.text.charAt(index))) {
                 index++;
             }
             if (index >= len) {
@@ -136,7 +146,7 @@
             this.text = text;
             int index = 0;
             final int len = text.length();
-            while (index < len && !TextUtils.isGraphic(text.charAt(index))) {
+            while (index < len && !isGraphicOrEmoji(text.charAt(index))) {
                 index++;
             }
             this.current = index;
@@ -192,9 +202,10 @@
         }
 
         final Drawable icon = StatusBarIconView.getIcon(mContext,
-                new StatusBarIcon(n.pkg, n.notification.icon, n.notification.iconLevel, 0,
+                new StatusBarIcon(n.pkg, n.user, n.notification.icon, n.notification.iconLevel, 0,
                         n.notification.tickerText));
-        final Segment newSegment = new Segment(n, icon, n.notification.tickerText);
+        final CharSequence text = n.notification.tickerText;
+        final Segment newSegment = new Segment(n, icon, text);
 
         // If there's already a notification schedule for this package and id, remove it.
         for (int i=0; i<mSegments.size(); i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
index f45426b..7ac2a98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
@@ -10,7 +10,6 @@
 public class AccessibilityContentDescriptions {
 
     private AccessibilityContentDescriptions() {}
-    
     static final int[] PHONE_SIGNAL_STRENGTH = {
         R.string.accessibility_no_phone,
         R.string.accessibility_phone_one_bar,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
index 0d2538d..3c8276d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
@@ -24,6 +24,7 @@
 import android.os.AsyncTask;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Slog;
 import android.widget.CompoundButton;
@@ -73,7 +74,7 @@
 
     private boolean getAirplaneMode() {
         ContentResolver cr = mContext.getContentResolver();
-        return 0 != Settings.System.getInt(cr, Settings.System.AIRPLANE_MODE_ON, 0);
+        return 0 != Settings.Global.getInt(cr, Settings.Global.AIRPLANE_MODE_ON, 0);
     }
 
     // TODO: Fix this racy API by adding something better to TelephonyManager or
@@ -81,14 +82,14 @@
     private void unsafe(final boolean enabled) {
         AsyncTask.execute(new Runnable() {
                 public void run() {
-                    Settings.System.putInt(
+                    Settings.Global.putInt(
                             mContext.getContentResolver(),
-                            Settings.System.AIRPLANE_MODE_ON,
+                            Settings.Global.AIRPLANE_MODE_ON,
                             enabled ? 1 : 0);
                     Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
                     intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
                     intent.putExtra("state", enabled);
-                    mContext.sendBroadcast(intent);
+                    mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
                 }
             });
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java
index 109395c..7d58032 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java
@@ -19,6 +19,7 @@
 import com.android.internal.view.RotationPolicy;
 
 import android.content.Context;
+import android.os.UserHandle;
 import android.widget.CompoundButton;
 
 public final class AutoRotateController implements CompoundButton.OnCheckedChangeListener {
@@ -44,7 +45,8 @@
 
         mCheckbox.setOnCheckedChangeListener(this);
 
-        RotationPolicy.registerRotationPolicyListener(context, mRotationPolicyListener);
+        RotationPolicy.registerRotationPolicyListener(context, mRotationPolicyListener,
+                UserHandle.USER_ALL);
         updateState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index ff418c4..7f9bcac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -18,6 +18,7 @@
 
 import java.util.ArrayList;
 
+import android.bluetooth.BluetoothAdapter.BluetoothStateChangeCallback;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -36,6 +37,13 @@
     private ArrayList<ImageView> mIconViews = new ArrayList<ImageView>();
     private ArrayList<TextView> mLabelViews = new ArrayList<TextView>();
 
+    private ArrayList<BatteryStateChangeCallback> mChangeCallbacks =
+            new ArrayList<BatteryStateChangeCallback>();
+
+    public interface BatteryStateChangeCallback {
+        public void onBatteryLevelChanged(int level, boolean pluggedIn);
+    }
+
     public BatteryController(Context context) {
         mContext = context;
 
@@ -52,6 +60,10 @@
         mLabelViews.add(v);
     }
 
+    public void addStateChangedCallback(BatteryStateChangeCallback cb) {
+        mChangeCallbacks.add(cb);
+    }
+
     public void onReceive(Context context, Intent intent) {
         final String action = intent.getAction();
         if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
@@ -73,6 +85,10 @@
                 v.setText(mContext.getString(R.string.status_bar_settings_battery_meter_format,
                         level));
             }
+
+            for (BatteryStateChangeCallback cb : mChangeCallbacks) {
+                cb.onBatteryLevelChanged(level, plugged);
+            }
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
index 603808e..fece57e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
@@ -16,9 +16,9 @@
 
 package com.android.systemui.statusbar.policy;
 
-import java.util.ArrayList;
-
 import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothAdapter.BluetoothStateChangeCallback;
+import android.bluetooth.BluetoothDevice;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -28,6 +28,10 @@
 
 import com.android.systemui.R;
 
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
 public class BluetoothController extends BroadcastReceiver {
     private static final String TAG = "StatusBar.BluetoothController";
 
@@ -38,12 +42,18 @@
     private int mContentDescriptionId = 0;
     private boolean mEnabled = false;
 
+    private Set<BluetoothDevice> mBondedDevices = new HashSet<BluetoothDevice>();
+
+    private ArrayList<BluetoothStateChangeCallback> mChangeCallbacks =
+            new ArrayList<BluetoothStateChangeCallback>();
+
     public BluetoothController(Context context) {
         mContext = context;
 
         IntentFilter filter = new IntentFilter();
         filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
         filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
+        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
         context.registerReceiver(this, filter);
 
         final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -52,12 +62,21 @@
             handleConnectionStateChange(adapter.getConnectionState());
         }
         refreshViews();
+        updateBondedBluetoothDevices();
     }
 
     public void addIconView(ImageView v) {
         mIconViews.add(v);
     }
 
+    public void addStateChangedCallback(BluetoothStateChangeCallback cb) {
+        mChangeCallbacks.add(cb);
+    }
+
+    public Set<BluetoothDevice> getBondedBluetoothDevices() {
+        return mBondedDevices;
+    }
+
     @Override
     public void onReceive(Context context, Intent intent) {
         final String action = intent.getAction();
@@ -69,8 +88,27 @@
             handleConnectionStateChange(
                     intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
                         BluetoothAdapter.STATE_DISCONNECTED));
+        } else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
+            // Fall through and update bonded devices and refresh view
         }
         refreshViews();
+        updateBondedBluetoothDevices();
+    }
+
+    private void updateBondedBluetoothDevices() {
+        mBondedDevices.clear();
+
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        if (adapter != null) {
+            Set<BluetoothDevice> devices = adapter.getBondedDevices();
+            if (devices != null) {
+                for (BluetoothDevice device : devices) {
+                    if (device.getBondState() != BluetoothDevice.BOND_NONE) {
+                        mBondedDevices.add(device);
+                    }
+                }
+            }
+        }
     }
 
     public void handleAdapterStateChange(int adapterState) {
@@ -98,5 +136,8 @@
                     ? null
                     : mContext.getString(mContentDescriptionId));
         }
+        for (BluetoothStateChangeCallback cb : mChangeCallbacks) {
+            cb.onBluetoothStateChange(mEnabled);
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java
index 3ba36af..e18b28a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.os.AsyncTask;
 import android.os.IPowerManager;
+import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.provider.Settings;
@@ -27,79 +28,126 @@
 import android.util.Slog;
 import android.view.IWindowManager;
 import android.widget.CompoundButton;
+import android.widget.ImageView;
+
+import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
+
+import java.util.ArrayList;
 
 public class BrightnessController implements ToggleSlider.Listener {
     private static final String TAG = "StatusBar.BrightnessController";
 
-    private static final int MINIMUM_BACKLIGHT = android.os.PowerManager.BRIGHTNESS_DIM;
-    private static final int MAXIMUM_BACKLIGHT = android.os.PowerManager.BRIGHTNESS_ON;
+    private final int mMinimumBacklight;
+    private final int mMaximumBacklight;
 
-    private Context mContext;
-    private ToggleSlider mControl;
-    private IPowerManager mPower;
+    private final Context mContext;
+    private final ImageView mIcon;
+    private final ToggleSlider mControl;
+    private final boolean mAutomaticAvailable;
+    private final IPowerManager mPower;
+    private final CurrentUserTracker mUserTracker;
 
-    public BrightnessController(Context context, ToggleSlider control) {
+    private ArrayList<BrightnessStateChangeCallback> mChangeCallbacks =
+            new ArrayList<BrightnessStateChangeCallback>();
+
+    public interface BrightnessStateChangeCallback {
+        public void onBrightnessLevelChanged();
+    }
+
+    public BrightnessController(Context context, ImageView icon, ToggleSlider control) {
         mContext = context;
+        mIcon = icon;
         mControl = control;
+        mUserTracker = new CurrentUserTracker(mContext);
 
-        boolean automaticAvailable = context.getResources().getBoolean(
+        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        mMinimumBacklight = pm.getMinimumScreenBrightnessSetting();
+        mMaximumBacklight = pm.getMaximumScreenBrightnessSetting();
+
+        mAutomaticAvailable = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_automatic_brightness_available);
         mPower = IPowerManager.Stub.asInterface(ServiceManager.getService("power"));
 
-        if (automaticAvailable) {
+        control.setOnChangedListener(this);
+    }
+
+    public void addStateChangedCallback(BrightnessStateChangeCallback cb) {
+        mChangeCallbacks.add(cb);
+    }
+
+    @Override
+    public void onInit(ToggleSlider control) {
+        if (mAutomaticAvailable) {
             int automatic;
             try {
-                automatic = Settings.System.getInt(mContext.getContentResolver(),
-                        Settings.System.SCREEN_BRIGHTNESS_MODE);
+                automatic = Settings.System.getIntForUser(mContext.getContentResolver(),
+                        Settings.System.SCREEN_BRIGHTNESS_MODE,
+                        mUserTracker.getCurrentUserId());
             } catch (SettingNotFoundException snfe) {
                 automatic = 0;
             }
             control.setChecked(automatic != 0);
+            updateIcon(automatic != 0);
         } else {
             control.setChecked(false);
+            updateIcon(false /*automatic*/);
             //control.hideToggle();
         }
         
         int value;
         try {
-            value = Settings.System.getInt(mContext.getContentResolver(), 
-                    Settings.System.SCREEN_BRIGHTNESS);
+            value = Settings.System.getIntForUser(mContext.getContentResolver(),
+                    Settings.System.SCREEN_BRIGHTNESS,
+                    mUserTracker.getCurrentUserId());
         } catch (SettingNotFoundException ex) {
-            value = MAXIMUM_BACKLIGHT;
+            value = mMaximumBacklight;
         }
 
-        control.setMax(MAXIMUM_BACKLIGHT - MINIMUM_BACKLIGHT);
-        control.setValue(value - MINIMUM_BACKLIGHT);
-
-        control.setOnChangedListener(this);
+        control.setMax(mMaximumBacklight - mMinimumBacklight);
+        control.setValue(value - mMinimumBacklight);
     }
 
     public void onChanged(ToggleSlider view, boolean tracking, boolean automatic, int value) {
         setMode(automatic ? Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC
                 : Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
+        updateIcon(automatic);
         if (!automatic) {
-            final int val = value + MINIMUM_BACKLIGHT;
+            final int val = value + mMinimumBacklight;
             setBrightness(val);
             if (!tracking) {
                 AsyncTask.execute(new Runnable() {
                         public void run() {
-                            Settings.System.putInt(mContext.getContentResolver(), 
-                                    Settings.System.SCREEN_BRIGHTNESS, val);
+                            Settings.System.putIntForUser(mContext.getContentResolver(),
+                                    Settings.System.SCREEN_BRIGHTNESS, val,
+                                    mUserTracker.getCurrentUserId());
                         }
                     });
             }
         }
+
+        for (BrightnessStateChangeCallback cb : mChangeCallbacks) {
+            cb.onBrightnessLevelChanged();
+        }
     }
 
     private void setMode(int mode) {
-        Settings.System.putInt(mContext.getContentResolver(),
-                Settings.System.SCREEN_BRIGHTNESS_MODE, mode);
+        Settings.System.putIntForUser(mContext.getContentResolver(),
+                Settings.System.SCREEN_BRIGHTNESS_MODE, mode,
+                mUserTracker.getCurrentUserId());
     }
     
     private void setBrightness(int brightness) {
         try {
-            mPower.setBacklightBrightness(brightness);
+            mPower.setTemporaryScreenBrightnessSettingOverride(brightness);
         } catch (RemoteException ex) {
         }        
     }
+
+    private void updateIcon(boolean automatic) {
+        if (mIcon != null) {
+            mIcon.setImageResource(automatic ?
+                    com.android.systemui.R.drawable.ic_qs_brightness_auto_on :
+                    com.android.systemui.R.drawable.ic_qs_brightness_auto_off);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index 69872df..ffc18c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -34,6 +34,7 @@
 import android.text.style.RelativeSizeSpan;
 import android.text.style.StyleSpan;
 import android.util.AttributeSet;
+import android.util.Slog;
 import android.view.View;
 import android.widget.TextView;
 
@@ -173,7 +174,6 @@
                         + "a" + MAGIC2 + format.substring(b + 1);
                 }
             }
-
             mClockFormat = sdf = new SimpleDateFormat(format);
             mClockFormatString = format;
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CurrentUserTracker.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CurrentUserTracker.java
new file mode 100644
index 0000000..225ebc1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CurrentUserTracker.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+public class CurrentUserTracker extends BroadcastReceiver {
+
+    private int mCurrentUserId;
+
+    public CurrentUserTracker(Context context) {
+        IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
+        context.registerReceiver(this, filter);
+        mCurrentUserId = ActivityManager.getCurrentUser();
+    }
+
+    public int getCurrentUserId() {
+        return mCurrentUserId;
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
+            mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index c19550b..1d6b3d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -30,7 +30,7 @@
 
 import java.util.Date;
 
-public final class DateView extends TextView {
+public class DateView extends TextView {
     private static final String TAG = "DateView";
 
     private boolean mAttachedToWindow;
@@ -86,12 +86,9 @@
         return 0;
     }
 
-    private final void updateClock() {
-        final Context context = getContext();
-        Date now = new Date();
-        CharSequence dow = DateFormat.format("EEEE", now);
-        CharSequence date = DateFormat.getLongDateFormat(context).format(now);
-        setText(context.getString(R.string.status_bar_date_formatter, dow, date));
+    protected void updateClock() {
+        final String dateFormat = getContext().getString(R.string.abbrev_wday_month_day_no_year);
+        setText(DateFormat.format(dateFormat, new Date()));
     }
 
     private boolean isVisible() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
index 19fbe96..e5ef5fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
@@ -16,26 +16,150 @@
 
 package com.android.systemui.statusbar.policy;
 
+import android.animation.ObjectAnimator;
 import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.os.SystemClock;
 import android.util.AttributeSet;
+import android.util.Slog;
 import android.view.MotionEvent;
 import android.view.View;
 
 import com.android.systemui.R;
 
 public class DeadZone extends View {
+    public static final String TAG = "DeadZone";
+
+    public static final boolean DEBUG = false;
+    public static final int HORIZONTAL = 0;
+    public static final int VERTICAL = 1;
+
+    private static final boolean CHATTY = true; // print to logcat when we eat a click
+
+    private boolean mShouldFlash;
+    private float mFlashFrac = 0f;
+
+    private int mSizeMax;
+    private int mSizeMin;
+    // Upon activity elsewhere in the UI, the dead zone will hold steady for
+    // mHold ms, then move back over the course of mDecay ms
+    private int mHold, mDecay;
+    private boolean mVertical;
+    private long mLastPokeTime;
+
+    private final Runnable mDebugFlash = new Runnable() {
+        @Override
+        public void run() {
+            ObjectAnimator.ofFloat(DeadZone.this, "flash", 1f, 0f).setDuration(150).start();
+        }
+    };
+
     public DeadZone(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
     }
 
     public DeadZone(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs);
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DeadZone,
+                defStyle, 0);
+
+        mHold = a.getInteger(R.styleable.DeadZone_holdTime, 0);
+        mDecay = a.getInteger(R.styleable.DeadZone_decayTime, 0);
+
+        mSizeMin = a.getDimensionPixelSize(R.styleable.DeadZone_minSize, 0);
+        mSizeMax = a.getDimensionPixelSize(R.styleable.DeadZone_maxSize, 0);
+
+        int index = a.getInt(R.styleable.DeadZone_orientation, -1);
+        mVertical = (index == VERTICAL);
+
+        if (DEBUG)
+            Slog.v(TAG, this + " size=[" + mSizeMin + "-" + mSizeMax + "] hold=" + mHold
+                    + (mVertical ? " vertical" : " horizontal"));
+
+        setFlashOnTouchCapture(context.getResources().getBoolean(R.bool.config_dead_zone_flash));
     }
 
-    // I made you a touch event
+    static float lerp(float a, float b, float f) {
+        return (b - a) * f + a;
+    }
+
+    private float getSize(long now) {
+        if (mSizeMax == 0)
+            return 0;
+        long dt = (now - mLastPokeTime);
+        if (dt > mHold + mDecay)
+            return mSizeMin;
+        if (dt < mHold)
+            return mSizeMax;
+        return (int) lerp(mSizeMax, mSizeMin, (float) (dt - mHold) / mDecay);
+    }
+
+    public void setFlashOnTouchCapture(boolean dbg) {
+        mShouldFlash = dbg;
+        mFlashFrac = 0f;
+        postInvalidate();
+    }
+
+    // I made you a touch event...
     @Override
-    public boolean onTouchEvent (MotionEvent event) {
-        return true; // but I eated it
+    public boolean onTouchEvent(MotionEvent event) {
+        if (DEBUG) {
+            Slog.v(TAG, this + " onTouch: " + MotionEvent.actionToString(event.getAction()));
+        }
+
+        final int action = event.getAction();
+        if (action == MotionEvent.ACTION_OUTSIDE) {
+            poke(event);
+        } else if (action == MotionEvent.ACTION_DOWN) {
+            if (DEBUG) {
+                Slog.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY());
+            }
+            int size = (int) getSize(event.getEventTime());
+            if ((mVertical && event.getX() < size) || event.getY() < size) {
+                if (CHATTY) {
+                    Slog.v(TAG, "consuming errant click: (" + event.getX() + "," + event.getY() + ")");
+                }
+                if (mShouldFlash) {
+                    post(mDebugFlash);
+                    postInvalidate();
+                }
+                return true; // ...but I eated it
+            }
+        }
+        return false;
+    }
+
+    public void poke(MotionEvent event) {
+        mLastPokeTime = event.getEventTime();
+        if (DEBUG)
+            Slog.v(TAG, "poked! size=" + getSize(mLastPokeTime));
+        postInvalidate();
+    }
+
+    public void setFlash(float f) {
+        mFlashFrac = f;
+        postInvalidate();
+    }
+
+    public float getFlash() {
+        return mFlashFrac;
+    }
+
+    @Override
+    public void onDraw(Canvas can) {
+        if (!mShouldFlash || mFlashFrac <= 0f) {
+            return;
+        }
+
+        final int size = (int) getSize(SystemClock.uptimeMillis());
+        can.clipRect(0, 0, mVertical ? size : can.getWidth(), mVertical ? can.getHeight() : size);
+        final float frac = DEBUG ? (mFlashFrac - 0.5f) + 0.5f : mFlashFrac;
+        can.drawARGB((int) (frac * 0xFF), 0xDD, 0xEE, 0xAA);
+
+        if (DEBUG && size > mSizeMin)
+            // crazy aggressive redrawing here, for debugging only
+            postInvalidateDelayed(100);
     }
 }
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
index a60bba7..776cf36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
@@ -26,6 +26,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.location.LocationManager;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Slog;
 import android.view.View;
@@ -36,6 +37,7 @@
 import com.android.internal.statusbar.StatusBarNotification;
 
 import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
 
 public class LocationController extends BroadcastReceiver {
     private static final String TAG = "StatusBar.LocationController";
@@ -46,6 +48,13 @@
 
     private INotificationManager mNotificationService;
 
+    private ArrayList<LocationGpsStateChangeCallback> mChangeCallbacks =
+            new ArrayList<LocationGpsStateChangeCallback>();
+
+    public interface LocationGpsStateChangeCallback {
+        public void onLocationGpsStateChanged(boolean inUse, String description);
+    }
+
     public LocationController(Context context) {
         mContext = context;
 
@@ -59,6 +68,10 @@
         mNotificationService = nm.getService();
     }
 
+    public void addStateChangedCallback(LocationGpsStateChangeCallback cb) {
+        mChangeCallbacks.add(cb);
+    }
+
     @Override
     public void onReceive(Context context, Intent intent) {
         final String action = intent.getAction();
@@ -87,11 +100,14 @@
             if (visible) {
                 Intent gpsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                 gpsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, gpsIntent, 0);
+
+                PendingIntent pendingIntent = PendingIntent.getActivityAsUser(context, 0,
+                        gpsIntent, 0, null, UserHandle.CURRENT);
+                String text = mContext.getText(textResId).toString();
 
                 Notification n = new Notification.Builder(mContext)
                     .setSmallIcon(iconId)
-                    .setContentTitle(mContext.getText(textResId))
+                    .setContentTitle(text)
                     .setOngoing(true)
                     .setContentIntent(pendingIntent)
                     .getNotification();
@@ -108,11 +124,20 @@
                         null, 
                         GPS_NOTIFICATION_ID, 
                         n,
-                        idOut);
+                        idOut,
+                        UserHandle.USER_ALL);
+
+                for (LocationGpsStateChangeCallback cb : mChangeCallbacks) {
+                    cb.onLocationGpsStateChanged(true, text);
+                }
             } else {
-                mNotificationService.cancelNotification(
-                        mContext.getPackageName(),
-                        GPS_NOTIFICATION_ID);
+                mNotificationService.cancelNotificationWithTag(
+                        mContext.getPackageName(), null,
+                        GPS_NOTIFICATION_ID, UserHandle.USER_ALL);
+
+                for (LocationGpsStateChangeCallback cb : mChangeCallbacks) {
+                    cb.onLocationGpsStateChanged(false, null);
+                }
             }
         } catch (android.os.RemoteException ex) {
             // well, it was worth a shot
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index d94c6b2..bbb90c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -16,11 +16,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -37,9 +32,7 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
-import android.os.SystemProperties;
 import android.provider.Settings;
-import android.provider.Telephony;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
@@ -50,15 +43,18 @@
 import android.widget.TextView;
 
 import com.android.internal.app.IBatteryStats;
-import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.cdma.EriInfo;
-import com.android.server.am.BatteryStatsService;
 import com.android.internal.util.AsyncChannel;
-
+import com.android.server.am.BatteryStatsService;
 import com.android.systemui.R;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
 public class NetworkController extends BroadcastReceiver {
     // debug
     static final String TAG = "StatusBar.NetworkController";
@@ -81,9 +77,11 @@
     String mNetworkNameDefault;
     String mNetworkNameSeparator;
     int mPhoneSignalIconId;
+    int mQSPhoneSignalIconId;
     int mDataDirectionIconId; // data + data direction on phones
     int mDataSignalIconId;
     int mDataTypeIconId;
+    int mQSDataTypeIconId;
     int mAirplaneIconId;
     boolean mDataActive;
     int mMobileActivityIconId; // overlay arrows for data direction
@@ -105,6 +103,7 @@
     int mWifiRssi, mWifiLevel;
     String mWifiSsid;
     int mWifiIconId = 0;
+    int mQSWifiIconId = 0;
     int mWifiActivityIconId = 0; // overlay arrows for wifi direction
     int mWifiActivity = WifiManager.DATA_ACTIVITY_NONE;
 
@@ -148,6 +147,8 @@
     ArrayList<TextView> mWifiLabelViews = new ArrayList<TextView>();
     ArrayList<TextView> mEmergencyLabelViews = new ArrayList<TextView>();
     ArrayList<SignalCluster> mSignalClusters = new ArrayList<SignalCluster>();
+    ArrayList<NetworkSignalChangedCallback> mSignalsChangedCallbacks =
+            new ArrayList<NetworkSignalChangedCallback>();
     int mLastPhoneSignalIconId = -1;
     int mLastDataDirectionIconId = -1;
     int mLastDataDirectionOverlayIconId = -1;
@@ -172,6 +173,15 @@
         void setIsAirplaneMode(boolean is, int airplaneIcon);
     }
 
+    public interface NetworkSignalChangedCallback {
+        void onWifiSignalChanged(boolean enabled, int wifiSignalIconId,
+                String wifitSignalContentDescriptionId, String description);
+        void onMobileDataSignalChanged(boolean enabled, int mobileSignalIconId,
+                String mobileSignalContentDescriptionId, int dataTypeIconId,
+                String dataTypeContentDescriptionId, String description);
+        void onAirplaneModeChanged(boolean enabled);
+    }
+
     /**
      * Construct this controller object and register for updates.
      */
@@ -299,6 +309,11 @@
         refreshSignalCluster(cluster);
     }
 
+    public void addNetworkSignalChangedCallback(NetworkSignalChangedCallback cb) {
+        mSignalsChangedCallbacks.add(cb);
+        notifySignalsChangedCallbacks(cb);
+    }
+
     public void refreshSignalCluster(SignalCluster cluster) {
         cluster.setWifiIndicators(
                 // only show wifi in the cluster if connected or if wifi-only
@@ -329,6 +344,33 @@
         cluster.setIsAirplaneMode(mAirplaneMode, mAirplaneIconId);
     }
 
+    void notifySignalsChangedCallbacks(NetworkSignalChangedCallback cb) {
+        // only show wifi in the cluster if connected or if wifi-only
+        boolean wifiEnabled = mWifiEnabled && (mWifiConnected || !mHasMobileDataFeature);
+        String wifiDesc = wifiEnabled ?
+                mWifiSsid : null;
+        cb.onWifiSignalChanged(wifiEnabled, mQSWifiIconId, mContentDescriptionWifi, wifiDesc);
+
+        if (isEmergencyOnly()) {
+            cb.onMobileDataSignalChanged(false, mQSPhoneSignalIconId,
+                    mContentDescriptionPhoneSignal, mQSDataTypeIconId, mContentDescriptionDataType,
+                    null);
+        } else {
+            if (mIsWimaxEnabled && mWimaxConnected) {
+                // Wimax is special
+                cb.onMobileDataSignalChanged(true, mQSPhoneSignalIconId,
+                        mContentDescriptionPhoneSignal, mQSDataTypeIconId,
+                        mContentDescriptionDataType, mNetworkName);
+            } else {
+                // Normal mobile data
+                cb.onMobileDataSignalChanged(mHasMobileDataFeature, mQSPhoneSignalIconId,
+                        mContentDescriptionPhoneSignal, mQSDataTypeIconId,
+                        mContentDescriptionDataType, mNetworkName);
+            }
+        }
+        cb.onAirplaneModeChanged(mAirplaneMode);
+    }
+
     public void setStackedMode(boolean stacked) {
         mDataAndWifiStacked = true;
     }
@@ -475,19 +517,21 @@
     }
 
     private void updateAirplaneMode() {
-        mAirplaneMode = (Settings.System.getInt(mContext.getContentResolver(),
-            Settings.System.AIRPLANE_MODE_ON, 0) == 1);
+        mAirplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),
+            Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
     }
 
     private final void updateTelephonySignalStrength() {
         if (!hasService()) {
             if (CHATTY) Slog.d(TAG, "updateTelephonySignalStrength: !hasService()");
             mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
+            mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal;
             mDataSignalIconId = R.drawable.stat_sys_signal_null;
         } else {
             if (mSignalStrength == null) {
                 if (CHATTY) Slog.d(TAG, "updateTelephonySignalStrength: mSignalStrength == null");
                 mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
+                mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal;
                 mDataSignalIconId = R.drawable.stat_sys_signal_null;
                 mContentDescriptionPhoneSignal = mContext.getString(
                         AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]);
@@ -518,6 +562,8 @@
                     }
                 }
                 mPhoneSignalIconId = iconList[iconLevel];
+                mQSPhoneSignalIconId =
+                        TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[mInetCondition][iconLevel];
                 mContentDescriptionPhoneSignal = mContext.getString(
                         AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[iconLevel]);
                 mDataSignalIconId = TelephonyIcons.DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel];
@@ -530,6 +576,7 @@
             // wimax is a special 4g network not handled by telephony
             mDataIconList = TelephonyIcons.DATA_4G[mInetCondition];
             mDataTypeIconId = R.drawable.stat_sys_data_connected_4g;
+            mQSDataTypeIconId = R.drawable.ic_qs_signal_4g;
             mContentDescriptionDataType = mContext.getString(
                     R.string.accessibility_data_connection_4g);
         } else {
@@ -538,6 +585,7 @@
                     if (!mShowAtLeastThreeGees) {
                         mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
                         mDataTypeIconId = 0;
+                        mQSDataTypeIconId = 0;
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_gprs);
                         break;
@@ -548,6 +596,7 @@
                     if (!mShowAtLeastThreeGees) {
                         mDataIconList = TelephonyIcons.DATA_E[mInetCondition];
                         mDataTypeIconId = R.drawable.stat_sys_data_connected_e;
+                        mQSDataTypeIconId = R.drawable.ic_qs_signal_e;
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_edge);
                         break;
@@ -557,6 +606,7 @@
                 case TelephonyManager.NETWORK_TYPE_UMTS:
                     mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
                     mDataTypeIconId = R.drawable.stat_sys_data_connected_3g;
+                    mQSDataTypeIconId = R.drawable.ic_qs_signal_3g;
                     mContentDescriptionDataType = mContext.getString(
                             R.string.accessibility_data_connection_3g);
                     break;
@@ -567,11 +617,13 @@
                     if (mHspaDataDistinguishable) {
                         mDataIconList = TelephonyIcons.DATA_H[mInetCondition];
                         mDataTypeIconId = R.drawable.stat_sys_data_connected_h;
+                        mQSDataTypeIconId = R.drawable.ic_qs_signal_h;
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_3_5g);
                     } else {
                         mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
                         mDataTypeIconId = R.drawable.stat_sys_data_connected_3g;
+                        mQSDataTypeIconId = R.drawable.ic_qs_signal_3g;
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_3g);
                     }
@@ -581,6 +633,7 @@
                         // display 1xRTT for IS95A/B
                         mDataIconList = TelephonyIcons.DATA_1X[mInetCondition];
                         mDataTypeIconId = R.drawable.stat_sys_data_connected_1x;
+                        mQSDataTypeIconId = R.drawable.ic_qs_signal_1x;
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_cdma);
                         break;
@@ -591,6 +644,7 @@
                     if (!mShowAtLeastThreeGees) {
                         mDataIconList = TelephonyIcons.DATA_1X[mInetCondition];
                         mDataTypeIconId = R.drawable.stat_sys_data_connected_1x;
+                        mQSDataTypeIconId = R.drawable.ic_qs_signal_1x;
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_cdma);
                         break;
@@ -603,12 +657,14 @@
                 case TelephonyManager.NETWORK_TYPE_EHRPD:
                     mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
                     mDataTypeIconId = R.drawable.stat_sys_data_connected_3g;
+                    mQSDataTypeIconId = R.drawable.ic_qs_signal_3g;
                     mContentDescriptionDataType = mContext.getString(
                             R.string.accessibility_data_connection_3g);
                     break;
                 case TelephonyManager.NETWORK_TYPE_LTE:
                     mDataIconList = TelephonyIcons.DATA_4G[mInetCondition];
                     mDataTypeIconId = R.drawable.stat_sys_data_connected_4g;
+                    mQSDataTypeIconId = R.drawable.ic_qs_signal_4g;
                     mContentDescriptionDataType = mContext.getString(
                             R.string.accessibility_data_connection_4g);
                     break;
@@ -616,11 +672,13 @@
                     if (!mShowAtLeastThreeGees) {
                         mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
                         mDataTypeIconId = R.drawable.stat_sys_data_connected_g;
+                        mQSDataTypeIconId = R.drawable.ic_qs_signal_g;
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_gprs);
                     } else {
                         mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
                         mDataTypeIconId = R.drawable.stat_sys_data_connected_3g;
+                        mQSDataTypeIconId = R.drawable.ic_qs_signal_3g;
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_3g);
                     }
@@ -631,9 +689,11 @@
         if (isCdma()) {
             if (isCdmaEri()) {
                 mDataTypeIconId = R.drawable.stat_sys_data_connected_roam;
+                mQSDataTypeIconId = R.drawable.ic_qs_signal_r;
             }
         } else if (mPhone.isNetworkRoaming()) {
                 mDataTypeIconId = R.drawable.stat_sys_data_connected_roam;
+                mQSDataTypeIconId = R.drawable.ic_qs_signal_r;
         }
     }
 
@@ -810,13 +870,16 @@
     private void updateWifiIcons() {
         if (mWifiConnected) {
             mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel];
+            mQSWifiIconId = WifiIcons.QS_WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel];
             mContentDescriptionWifi = mContext.getString(
                     AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH[mWifiLevel]);
         } else {
             if (mDataAndWifiStacked) {
                 mWifiIconId = 0;
+                mQSWifiIconId = 0;
             } else {
                 mWifiIconId = mWifiEnabled ? R.drawable.stat_sys_wifi_signal_null : 0;
+                mQSWifiIconId = mWifiEnabled ? R.drawable.ic_qs_wifi_no_network : 0;
             }
             mContentDescriptionWifi = mContext.getString(R.string.accessibility_no_wifi);
         }
@@ -941,13 +1004,14 @@
 
         if (!mHasMobileDataFeature) {
             mDataSignalIconId = mPhoneSignalIconId = 0;
+            mQSPhoneSignalIconId = 0;
             mobileLabel = "";
         } else {
             // We want to show the carrier name if in service and either:
             //   - We are connected to mobile data, or
             //   - We are not connected to mobile data, as long as the *reason* packets are not
             //     being routed over that link is that we have better connectivity via wifi.
-            // If data is disconnected for some other reason but wifi (or ethernet/bluetooth) 
+            // If data is disconnected for some other reason but wifi (or ethernet/bluetooth)
             // is connected, we show nothing.
             // Otherwise (nothing connected) we show "No internet connection".
 
@@ -1039,8 +1103,7 @@
 
         final boolean ethernetConnected = (mConnectedNetworkType == ConnectivityManager.TYPE_ETHERNET);
         if (ethernetConnected) {
-            // TODO: icons and strings for Ethernet connectivity
-            combinedLabel = mConnectedNetworkTypeName;
+            combinedLabel = context.getString(R.string.ethernet_label);
         }
 
         if (mAirplaneMode &&
@@ -1051,7 +1114,8 @@
             mContentDescriptionPhoneSignal = mContext.getString(
                     R.string.accessibility_airplane_mode);
             mAirplaneIconId = R.drawable.stat_sys_signal_flightmode;
-            mPhoneSignalIconId = mDataSignalIconId = mDataTypeIconId = 0;
+            mPhoneSignalIconId = mDataSignalIconId = mDataTypeIconId = mQSDataTypeIconId = 0;
+            mQSPhoneSignalIconId = 0;
 
             // combined values from connected wifi take precedence over airplane mode
             if (mWifiConnected) {
@@ -1080,12 +1144,15 @@
                 ? mContentDescriptionDataType : mContentDescriptionWifi;
 
             mDataTypeIconId = 0;
+            mQSDataTypeIconId = 0;
             if (isCdma()) {
                 if (isCdmaEri()) {
                     mDataTypeIconId = R.drawable.stat_sys_data_connected_roam;
+                    mQSDataTypeIconId = R.drawable.ic_qs_signal_r;
                 }
             } else if (mPhone.isNetworkRoaming()) {
                 mDataTypeIconId = R.drawable.stat_sys_data_connected_roam;
+                mQSDataTypeIconId = R.drawable.ic_qs_signal_r;
             }
         }
 
@@ -1106,10 +1173,13 @@
                     + " mAirplaneMode=" + mAirplaneMode
                     + " mDataActivity=" + mDataActivity
                     + " mPhoneSignalIconId=0x" + Integer.toHexString(mPhoneSignalIconId)
+                    + " mQSPhoneSignalIconId=0x" + Integer.toHexString(mQSPhoneSignalIconId)
                     + " mDataDirectionIconId=0x" + Integer.toHexString(mDataDirectionIconId)
                     + " mDataSignalIconId=0x" + Integer.toHexString(mDataSignalIconId)
                     + " mDataTypeIconId=0x" + Integer.toHexString(mDataTypeIconId)
+                    + " mQSDataTypeIconId=0x" + Integer.toHexString(mQSDataTypeIconId)
                     + " mWifiIconId=0x" + Integer.toHexString(mWifiIconId)
+                    + " mQSWifiIconId=0x" + Integer.toHexString(mQSWifiIconId)
                     + " mBluetoothTetherIconId=0x" + Integer.toHexString(mBluetoothTetherIconId));
         }
 
@@ -1124,6 +1194,9 @@
             for (SignalCluster cluster : mSignalClusters) {
                 refreshSignalCluster(cluster);
             }
+            for (NetworkSignalChangedCallback cb : mSignalsChangedCallbacks) {
+                notifySignalsChangedCallbacks(cb);
+            }
         }
 
         if (mLastAirplaneMode != mAirplaneMode) {
@@ -1283,7 +1356,7 @@
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("NetworkController state:");
-        pw.println(String.format("  %s network type %d (%s)", 
+        pw.println(String.format("  %s network type %d (%s)",
                 mConnected?"CONNECTED":"DISCONNECTED",
                 mConnectedNetworkType, mConnectedNetworkTypeName));
         pw.println("  - telephony ------");
@@ -1320,6 +1393,9 @@
         pw.print("  mPhoneSignalIconId=0x");
         pw.print(Integer.toHexString(mPhoneSignalIconId));
         pw.print("/");
+        pw.print("  mQSPhoneSignalIconId=0x");
+        pw.print(Integer.toHexString(mQSPhoneSignalIconId));
+        pw.print("/");
         pw.println(getResourceName(mPhoneSignalIconId));
         pw.print("  mDataDirectionIconId=");
         pw.print(Integer.toHexString(mDataDirectionIconId));
@@ -1333,6 +1409,10 @@
         pw.print(Integer.toHexString(mDataTypeIconId));
         pw.print("/");
         pw.println(getResourceName(mDataTypeIconId));
+        pw.print("  mQSDataTypeIconId=");
+        pw.print(Integer.toHexString(mQSDataTypeIconId));
+        pw.print("/");
+        pw.println(getResourceName(mQSDataTypeIconId));
 
         pw.println("  - wifi ------");
         pw.print("  mWifiEnabled=");
@@ -1347,6 +1427,8 @@
         pw.println(mWifiSsid);
         pw.println(String.format("  mWifiIconId=0x%08x/%s",
                     mWifiIconId, getResourceName(mWifiIconId)));
+        pw.println(String.format("  mQSWifiIconId=0x%08x/%s",
+                    mQSWifiIconId, getResourceName(mQSWifiIconId)));
         pw.print("  mWifiActivity=");
         pw.println(mWifiActivity);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
index 83e8c96..5d2198e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
@@ -27,6 +27,7 @@
     public static final boolean DO_NOT_DISTURB_DEFAULT = false;
 
     public static final String SHOWN_COMPAT_MODE_HELP = "shown_compat_mode_help";
+    public static final String SHOWN_QUICK_SETTINGS_HELP = "shown_quick_settings_help";
 
     public static SharedPreferences read(Context context) {
         return context.getSharedPreferences(Prefs.SHARED_PREFS_NAME, Context.MODE_PRIVATE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 959e06d..3b953a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -35,6 +35,19 @@
           R.drawable.stat_sys_signal_4_fully }
     };
 
+    static final int[][] QS_TELEPHONY_SIGNAL_STRENGTH = {
+        { R.drawable.ic_qs_signal_0,
+          R.drawable.ic_qs_signal_1,
+          R.drawable.ic_qs_signal_2,
+          R.drawable.ic_qs_signal_3,
+          R.drawable.ic_qs_signal_4 },
+        { R.drawable.ic_qs_signal_full_0,
+          R.drawable.ic_qs_signal_full_1,
+          R.drawable.ic_qs_signal_full_2,
+          R.drawable.ic_qs_signal_full_3,
+          R.drawable.ic_qs_signal_full_4 }
+    };
+
     static final int[][] TELEPHONY_SIGNAL_STRENGTH_ROAMING = {
         { R.drawable.stat_sys_signal_0,
           R.drawable.stat_sys_signal_1,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ToggleSlider.java
index fe2ec69..39f8fcc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ToggleSlider.java
@@ -36,6 +36,7 @@
     private static final String TAG = "StatusBar.ToggleSlider";
 
     public interface Listener {
+        public void onInit(ToggleSlider v);
         public void onChanged(ToggleSlider v, boolean tracking, boolean checked, int value);
     }
 
@@ -75,6 +76,14 @@
         a.recycle();
     }
 
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        if (mListener != null) {
+            mListener.onInit(this);
+        }
+    }
+
     public void onCheckedChanged(CompoundButton toggle, boolean checked) {
         Drawable thumb;
         Drawable slider;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/VolumeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/VolumeController.java
index 43cb85e..6fee4323 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/VolumeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/VolumeController.java
@@ -51,11 +51,15 @@
 
         mMute = mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL;
         mVolume = mAudioManager.getStreamVolume(STREAM);
+
+        control.setOnChangedListener(this);
+    }
+
+    @Override
+    public void onInit(ToggleSlider control) {
         control.setMax(mAudioManager.getStreamMaxVolume(STREAM));
         control.setValue(mVolume);
         control.setChecked(mMute);
-
-        control.setOnChangedListener(this);
     }
 
     public void onChanged(ToggleSlider view, boolean tracking, boolean mute, int level) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
index 8d72eba..8cc0338 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
@@ -32,5 +32,18 @@
               R.drawable.stat_sys_wifi_signal_4_fully }
         };
 
+    static final int[][] QS_WIFI_SIGNAL_STRENGTH = {
+            { R.drawable.ic_qs_wifi_0,
+              R.drawable.ic_qs_wifi_1,
+              R.drawable.ic_qs_wifi_2,
+              R.drawable.ic_qs_wifi_3,
+              R.drawable.ic_qs_wifi_4 },
+            { R.drawable.ic_qs_wifi_0,
+              R.drawable.ic_qs_wifi_full_1,
+              R.drawable.ic_qs_wifi_full_2,
+              R.drawable.ic_qs_wifi_full_3,
+              R.drawable.ic_qs_wifi_full_4 }
+        };
+
     static final int WIFI_LEVEL_COUNT = WIFI_SIGNAL_STRENGTH[0].length;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index c1ea50d..b431287 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -204,14 +204,14 @@
             // We exclusively handle the back key by hiding this panel.
             case KeyEvent.KEYCODE_BACK: {
                 if (event.getAction() == KeyEvent.ACTION_UP) {
-                    mBar.animateCollapse();
+                    mBar.animateCollapsePanels();
                 }
                 return true;
             }
             // We react to the home key but let the system handle it.
             case KeyEvent.KEYCODE_HOME: {
                 if (event.getAction() == KeyEvent.ACTION_UP) {
-                    mBar.animateCollapse();
+                    mBar.animateCollapsePanels();
                 }
             } break;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
index 537ff66..f71842e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
@@ -19,6 +19,7 @@
 import android.app.StatusBarManager;
 import android.content.Context;
 import android.content.Intent;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.Slog;
@@ -77,6 +78,7 @@
                 });
 
         mBrightness = new BrightnessController(context,
+                (ImageView)findViewById(R.id.brightness_icon),
                 (ToggleSlider)findViewById(R.id.brightness));
         mDoNotDisturb = new DoNotDisturbController(context,
                 (CompoundButton)findViewById(R.id.do_not_disturb_checkbox));
@@ -111,15 +113,16 @@
     private void onClickNetwork() {
         getContext().startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)
                 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
-        getStatusBarManager().collapse();
+        getStatusBarManager().collapsePanels();
     }
 
     // Settings
     // ----------------------------
     private void onClickSettings() {
-        getContext().startActivity(new Intent(Settings.ACTION_SETTINGS)
-                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
-        getStatusBarManager().collapse();
+        getContext().startActivityAsUser(new Intent(Settings.ACTION_SETTINGS)
+                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
+                new UserHandle(UserHandle.USER_CURRENT));
+        getStatusBarManager().collapsePanels();
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
index ddb43b8..2924cc9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
@@ -34,7 +34,6 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.TextView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index f947369..86c247a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -38,12 +38,10 @@
 import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.text.TextUtils;
 import android.util.Slog;
 import android.view.Display;
 import android.view.Gravity;
-import android.view.IWindowManager;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.SoundEffectConstants;
@@ -53,26 +51,22 @@
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
-import android.widget.RemoteViews;
 import android.widget.ScrollView;
 import android.widget.TextView;
 
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarNotification;
 import com.android.systemui.R;
-import com.android.systemui.recent.RecentTasksLoader;
-import com.android.systemui.recent.RecentsPanelView;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.DoNotDisturb;
 import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.NotificationData.Entry;
 import com.android.systemui.statusbar.SignalClusterView;
 import com.android.systemui.statusbar.StatusBarIconView;
-import com.android.systemui.statusbar.NotificationData.Entry;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.CompatModeButton;
@@ -86,8 +80,7 @@
 import java.util.ArrayList;
 
 public class TabletStatusBar extends BaseStatusBar implements
-        InputMethodsPanel.OnHardKeyboardEnabledChangeListener,
-        RecentsPanelView.OnRecentsPanelVisibilityChangedListener {
+        InputMethodsPanel.OnHardKeyboardEnabledChangeListener {
     public static final boolean DEBUG = false;
     public static final boolean DEBUG_COMPAT_HELP = false;
     public static final String TAG = "TabletStatusBar";
@@ -125,8 +118,6 @@
     int mMenuNavIconWidth = -1;
     private int mMaxNotificationIcons = 5;
 
-    IWindowManager mWindowManager;
-
     TabletStatusBarView mStatusBarView;
     View mNotificationArea;
     View mNotificationTrigger;
@@ -232,10 +223,7 @@
                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                     | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                     | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
-                // We use a pixel format of RGB565 for the status bar to save memory bandwidth and
-                // to ensure that the layer can be handled by HWComposer.  On some devices the
-                // HWComposer is unable to handle SW-rendered RGBX_8888 layers.
-                PixelFormat.RGB_565);
+                PixelFormat.OPAQUE);
 
         // We explicitly leave FLAG_HARDWARE_ACCELERATED out of the flags.  The status bar occupies
         // very little screen real-estate and is updated fairly frequently.  By using CPU rendering
@@ -245,7 +233,7 @@
         lp.gravity = getStatusBarGravity();
         lp.setTitle("SystemBar");
         lp.packageName = mContext.getPackageName();
-        WindowManagerImpl.getDefault().addView(sb, lp);
+        mWindowManager.addView(sb, lp);
     }
 
     protected void addPanelWindows() {
@@ -310,11 +298,7 @@
         lp.windowAnimations = com.android.internal.R.style.Animation; // == no animation
 //        lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
 
-        WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
-
-        // Recents Panel
-        mRecentTasksLoader = new RecentTasksLoader(context);
-        updateRecentsPanel();
+        mWindowManager.addView(mNotificationPanel, lp);
 
         // Search Panel
         mStatusBarView.setBar(this);
@@ -342,7 +326,7 @@
         lp.setTitle("InputMethodsPanel");
         lp.windowAnimations = R.style.Animation_RecentPanel;
 
-        WindowManagerImpl.getDefault().addView(mInputMethodsPanel, lp);
+        mWindowManager.addView(mInputMethodsPanel, lp);
 
         // Compatibility mode selector panel
         mCompatModePanel = (CompatModePanel) View.inflate(context,
@@ -365,9 +349,9 @@
         lp.setTitle("CompatModePanel");
         lp.windowAnimations = android.R.style.Animation_Dialog;
 
-        WindowManagerImpl.getDefault().addView(mCompatModePanel, lp);
+        mWindowManager.addView(mCompatModePanel, lp);
 
-        mRecentButton.setOnTouchListener(mRecentsPanel);
+        mRecentButton.setOnTouchListener(mRecentsPreloadOnTouchListener);
 
         mPile = (NotificationRowLayout)mNotificationPanel.findViewById(R.id.content);
         mPile.removeAllViews();
@@ -384,7 +368,7 @@
 
     private int getNotificationPanelHeight() {
         final Resources res = mContext.getResources();
-        final Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
+        final Display d = mWindowManager.getDefaultDisplay();
         final Point size = new Point();
         d.getRealSize(size);
         return Math.max(res.getDimensionPixelSize(R.dimen.notification_panel_min_height), size.y);
@@ -399,9 +383,7 @@
     protected void onConfigurationChanged(Configuration newConfig) {
         loadDimens();
         mNotificationPanelParams.height = getNotificationPanelHeight();
-        WindowManagerImpl.getDefault().updateViewLayout(mNotificationPanel,
-                mNotificationPanelParams);
-        mRecentsPanel.updateValuesFromResources();
+        mWindowManager.updateViewLayout(mNotificationPanel, mNotificationPanelParams);
         mShowSearchHoldoff = mContext.getResources().getInteger(
                 R.integer.config_show_search_delay);
         updateSearchPanel();
@@ -453,6 +435,7 @@
         }
     }
 
+    @Override
     public View getStatusBarView() {
         return mStatusBarView;
     }
@@ -460,9 +443,6 @@
     protected View makeStatusBarView() {
         final Context context = mContext;
 
-        mWindowManager = IWindowManager.Stub.asInterface(
-                ServiceManager.getService(Context.WINDOW_SERVICE));
-
         loadDimens();
 
         final TabletStatusBarView sb = (TabletStatusBarView)View.inflate(
@@ -474,7 +454,7 @@
         try {
             // Sanity-check that someone hasn't set up the config wrong and asked for a navigation
             // bar on a tablet that has only the system bar
-            if (mWindowManager.hasNavigationBar()) {
+            if (mWindowManagerService.hasNavigationBar()) {
                 Slog.e(TAG, "Tablet device cannot show navigation bar and system bar");
             }
         } catch (RemoteException ex) {
@@ -495,8 +475,7 @@
         // where the icons go
         mIconLayout = (NotificationIconArea.IconLayout) sb.findViewById(R.id.icons);
 
-        ViewConfiguration vc = ViewConfiguration.get(context);
-        mNotificationPeekTapDuration = vc.getTapTimeout();
+        mNotificationPeekTapDuration = ViewConfiguration.getTapTimeout();
         mNotificationFlingVelocity = 300; // px/s
 
         mTicker = new TabletTicker(this);
@@ -653,7 +632,7 @@
                         | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
                         | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
-        if (ActivityManager.isHighEndGfx(mDisplay)) {
+        if (ActivityManager.isHighEndGfx()) {
             lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
         } else {
             lp.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
@@ -668,11 +647,6 @@
         return lp;
     }
 
-    protected void updateRecentsPanel() {
-        super.updateRecentsPanel(R.layout.system_bar_recent_panel);
-        mRecentsPanel.setStatusBarView(mStatusBarView);
-    }
-
     @Override
     protected void updateSearchPanel() {
         super.updateSearchPanel();
@@ -686,7 +660,7 @@
         WindowManager.LayoutParams lp =
             (android.view.WindowManager.LayoutParams) mStatusBarView.getLayoutParams();
         lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-        WindowManagerImpl.getDefault().updateViewLayout(mStatusBarView, lp);
+        mWindowManager.updateViewLayout(mStatusBarView, lp);
     }
 
     @Override
@@ -695,7 +669,7 @@
         WindowManager.LayoutParams lp =
             (android.view.WindowManager.LayoutParams) mStatusBarView.getLayoutParams();
         lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-        WindowManagerImpl.getDefault().updateViewLayout(mStatusBarView, lp);
+        mWindowManager.updateViewLayout(mStatusBarView, lp);
     }
 
     public int getStatusBarHeight() {
@@ -717,8 +691,7 @@
         }
         if (lp.height != height) {
             lp.height = height;
-            final WindowManager wm = WindowManagerImpl.getDefault();
-            wm.updateViewLayout(mStatusBarView, lp);
+            mWindowManager.updateViewLayout(mStatusBarView, lp);
         }
     }
 
@@ -765,7 +738,7 @@
                                         SharedPreferences.Editor editor = Prefs.edit(mContext);
                                         editor.putBoolean(Prefs.DO_NOT_DISTURB_PREF, false);
                                         editor.apply();
-                                        animateCollapse();
+                                        animateCollapsePanels();
                                         visibilityChanged(false);
                                     }
                                 });
@@ -846,7 +819,7 @@
                     break;
                 case MSG_HIDE_CHROME:
                     if (DEBUG) Slog.d(TAG, "showing shadows (lights out)");
-                    animateCollapse();
+                    animateCollapsePanels();
                     visibilityChanged(false);
                     mBarContents.setVisibility(View.GONE);
                     mShadow.setVisibility(View.VISIBLE);
@@ -932,7 +905,7 @@
         if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
             if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
                 Slog.i(TAG, "DISABLE_EXPAND: yes");
-                animateCollapse();
+                animateCollapsePanels();
                 visibilityChanged(false);
             }
         }
@@ -1013,16 +986,16 @@
         mFeedbackIconArea.setVisibility(View.VISIBLE);
     }
 
-    public void animateExpand() {
+    public void animateExpandNotificationsPanel() {
         mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
         mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
     }
 
-    public void animateCollapse() {
-        animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
+    public void animateCollapsePanels() {
+        animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
     }
 
-    public void animateCollapse(int flags) {
+    public void animateCollapsePanels(int flags) {
         if ((flags & CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL) == 0) {
             mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PANEL);
             mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PANEL);
@@ -1046,6 +1019,11 @@
 
     }
 
+    @Override
+    public void animateExpandSettingsPanel() {
+        // TODO: Implement when TabletStatusBar begins to be used.
+    }
+
     @Override // CommandQueue
     public void setNavigationIconHints(int hints) {
         if (hints == mNavigationIconHints) return;
@@ -1073,7 +1051,7 @@
 
     private void notifyUiVisibilityChanged() {
         try {
-            mWindowManager.statusBarVisibilityChanged(mSystemUiVisibility);
+            mWindowManagerService.statusBarVisibilityChanged(mSystemUiVisibility);
         } catch (RemoteException ex) {
         }
     }
@@ -1165,12 +1143,12 @@
                 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
         lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
 
-        WindowManagerImpl.getDefault().addView(mCompatibilityHelpDialog, lp);
+        mWindowManager.addView(mCompatibilityHelpDialog, lp);
     }
 
     private void hideCompatibilityHelp() {
         if (mCompatibilityHelpDialog != null) {
-            WindowManagerImpl.getDefault().removeView(mCompatibilityHelpDialog);
+            mWindowManager.removeView(mCompatibilityHelpDialog);
             mCompatibilityHelpDialog = null;
         }
     }
@@ -1196,14 +1174,6 @@
     }
 
     @Override
-    public void onRecentsPanelVisibilityChanged(boolean visible) {
-        boolean altBack = visible || mAltBackButtonEnabledForIme;
-        mCommandQueue.setNavigationIconHints(
-                altBack ? (mNavigationIconHints | StatusBarManager.NAVIGATION_HINT_BACK_ALT)
-                        : (mNavigationIconHints & ~StatusBarManager.NAVIGATION_HINT_BACK_ALT));
-    }
-
-    @Override
     public void setHardKeyboardStatus(boolean available, boolean enabled) {
         if (DEBUG) {
             Slog.d(TAG, "Set hard keyboard status: available=" + available
@@ -1254,10 +1224,7 @@
     public void onClickRecentButton() {
         if (DEBUG) Slog.d(TAG, "clicked recent apps; disabled=" + mDisabled);
         if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
-            int msg = (mRecentsPanel.getVisibility() == View.VISIBLE)
-                ? MSG_CLOSE_RECENTS_PANEL : MSG_OPEN_RECENTS_PANEL;
-            mHandler.removeMessages(msg);
-            mHandler.sendEmptyMessage(msg);
+            toggleRecentApps();
         }
     }
 
@@ -1294,7 +1261,7 @@
                 mNotificationArea.postDelayed(mHiliteOnR, 100);
             } else {
                 mNotificationArea.removeCallbacks(mHiliteOnR);
-                mNotificationArea.setBackgroundDrawable(null);
+                mNotificationArea.setBackground(null);
             }
         }
 
@@ -1325,7 +1292,7 @@
                         mVT.computeCurrentVelocity(1000); // pixels per second
                         // require a little more oomph once we're already in peekaboo mode
                         if (mVT.getYVelocity() < -mNotificationFlingVelocity) {
-                            animateExpand();
+                            animateExpandNotificationsPanel();
                             visibilityChanged(true);
                             hilite(false);
                             mVT.recycle();
@@ -1343,7 +1310,7 @@
                          && Math.abs(event.getY() - mInitialTouchY) < (mTouchSlop / 3)
                          // dragging off the bottom doesn't count
                          && (int)event.getY() < v.getBottom()) {
-                            animateExpand();
+                            animateExpandNotificationsPanel();
                             visibilityChanged(true);
                             v.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
                             v.playSoundEffect(SoundEffectConstants.CLICK);
@@ -1368,106 +1335,6 @@
                 NOTIFICATION_PEEK_FADE_DELAY);
     }
 
-    private class NotificationIconTouchListener implements View.OnTouchListener {
-        VelocityTracker mVT;
-        int mPeekIndex;
-        float mInitialTouchX, mInitialTouchY;
-        int mTouchSlop;
-
-        public NotificationIconTouchListener() {
-            mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
-        }
-
-        public boolean onTouch(View v, MotionEvent event) {
-            boolean peeking = mNotificationPeekWindow.getVisibility() != View.GONE;
-            boolean panelShowing = mNotificationPanel.isShowing();
-            if (panelShowing) return false;
-
-            int numIcons = mIconLayout.getChildCount();
-            int newPeekIndex = (int)(event.getX() * numIcons / mIconLayout.getWidth());
-            if (newPeekIndex > numIcons - 1) newPeekIndex = numIcons - 1;
-            else if (newPeekIndex < 0) newPeekIndex = 0;
-
-            final int action = event.getAction();
-            switch (action) {
-                case MotionEvent.ACTION_DOWN:
-                    mVT = VelocityTracker.obtain();
-                    mInitialTouchX = event.getX();
-                    mInitialTouchY = event.getY();
-                    mPeekIndex = -1;
-
-                    // fall through
-                case MotionEvent.ACTION_OUTSIDE:
-                case MotionEvent.ACTION_MOVE:
-                    // peek and switch icons if necessary
-
-                    if (newPeekIndex != mPeekIndex) {
-                        mPeekIndex = newPeekIndex;
-
-                        if (DEBUG) Slog.d(TAG, "will peek at notification #" + mPeekIndex);
-                        Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
-                        peekMsg.arg1 = mPeekIndex;
-
-                        mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
-
-                        if (peeking) {
-                            // no delay if we're scrubbing left-right
-                            mHandler.sendMessage(peekMsg);
-                        } else {
-                            // wait for fling
-                            mHandler.sendMessageDelayed(peekMsg, NOTIFICATION_PEEK_HOLD_THRESH);
-                        }
-                    }
-
-                    // check for fling
-                    if (mVT != null) {
-                        mVT.addMovement(event);
-                        mVT.computeCurrentVelocity(1000); // pixels per second
-                        // require a little more oomph once we're already in peekaboo mode
-                        if (!panelShowing && (
-                               (peeking && mVT.getYVelocity() < -mNotificationFlingVelocity*3)
-                            || (mVT.getYVelocity() < -mNotificationFlingVelocity))) {
-                            mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
-                            mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
-                            mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
-                            mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
-                        }
-                    }
-                    return true;
-                case MotionEvent.ACTION_UP:
-                case MotionEvent.ACTION_CANCEL:
-                    mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
-                    if (!peeking) {
-                        if (action == MotionEvent.ACTION_UP
-                                // was this a sloppy tap?
-                                && Math.abs(event.getX() - mInitialTouchX) < mTouchSlop
-                                && Math.abs(event.getY() - mInitialTouchY) < (mTouchSlop / 3)
-                                // dragging off the bottom doesn't count
-                                && (int)event.getY() < v.getBottom()) {
-                            Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
-                            peekMsg.arg1 = mPeekIndex;
-                            mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
-                            mHandler.sendMessage(peekMsg);
-
-                            v.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
-                            v.playSoundEffect(SoundEffectConstants.CLICK);
-
-                            peeking = true; // not technically true yet, but the next line will run
-                        }
-                    }
-
-                    if (peeking) {
-                        resetNotificationPeekFadeTimer();
-                    }
-
-                    mVT.recycle();
-                    mVT = null;
-                    return true;
-            }
-            return false;
-        }
-    }
-
     private void reloadAllNotificationIcons() {
         if (mIconLayout == null) return;
         mIconLayout.removeAllViews();
@@ -1504,9 +1371,8 @@
                 iconView.setPadding(mIconHPadding, 0, mIconHPadding, 0);
 
                 mNotificationDNDDummyEntry = new NotificationData.Entry(
-                        null,
-                        new StatusBarNotification("", 0, "", 0, 0, Notification.PRIORITY_MAX, dndNotification),
-                        iconView);
+                        null, new StatusBarNotification("", 0, "", 0, 0, Notification.PRIORITY_MAX,
+                                dndNotification, android.os.Process.myUserHandle()), iconView);
 
                 mIconLayout.addView(iconView, params);
             }
@@ -1609,9 +1475,9 @@
         if (!(bgd instanceof LayerDrawable)) return;
 
         LayerDrawable d = (LayerDrawable) bgd;
-        v.setBackgroundDrawable(null);
+        v.setBackground(null);
         d.setOpacity(PixelFormat.TRANSLUCENT);
-        v.setBackgroundDrawable(d);
+        v.setBackground(d);
     }
 
     public void clearAll() {
@@ -1620,7 +1486,7 @@
         } catch (RemoteException ex) {
             // system process is dead if we're here.
         }
-        animateCollapse();
+        animateCollapsePanels();
         visibilityChanged(false);
     }
 
@@ -1636,15 +1502,7 @@
                         flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL;
                     }
                 }
-                if (Intent.ACTION_SCREEN_OFF.equals(action)) {
-                    // If we're turning the screen off, we want to hide the
-                    // recents panel with no animation
-                    // TODO: hide other things, like the notification tray,
-                    // with no animation as well
-                    mRecentsPanel.show(false, false);
-                    flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL;
-                }
-                animateCollapse(flags);
+                animateCollapsePanels(flags);
             }
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
index d4ebe6d..ea97941 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
@@ -35,7 +35,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.FrameLayout;
@@ -62,7 +61,8 @@
 
     private static final int ADVANCE_DELAY = 5000; // 5 seconds
 
-    private Context mContext;
+    private final Context mContext;
+    private final WindowManager mWindowManager;
 
     private ViewGroup mWindow;
     private IBinder mCurrentKey;
@@ -83,6 +83,7 @@
     public TabletTicker(TabletStatusBar bar) {
         mBar = bar;
         mContext = bar.getContext();
+        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
         final Resources res = mContext.getResources();
         mLargeIconHeight = res.getDimensionPixelSize(
                 android.R.dimen.notification_large_icon_height);
@@ -178,7 +179,7 @@
             if (mCurrentView != null) {
                 if (mWindow == null) {
                     mWindow = makeWindow();
-                    WindowManagerImpl.getDefault().addView(mWindow, mWindow.getLayoutParams());
+                    mWindowManager.addView(mWindow, mWindow.getLayoutParams());
                 }
 
                 mWindow.addView(mCurrentView);
@@ -242,7 +243,7 @@
     public void endTransition(LayoutTransition transition, ViewGroup container,
             View view, int transitionType) {
         if (mWindowShouldClose) {
-            WindowManagerImpl.getDefault().removeView(mWindow);
+            mWindowManager.removeView(mWindow);
             mWindow = null;
             mWindowShouldClose = false;
             mBar.doneTicking();
@@ -287,7 +288,8 @@
         } else if (n.tickerText != null) {
             group = (ViewGroup)inflater.inflate(R.layout.system_bar_ticker_compat, mWindow, false);
             final Drawable icon = StatusBarIconView.getIcon(mContext,
-                    new StatusBarIcon(notification.pkg, n.icon, n.iconLevel, 0, n.tickerText));
+                    new StatusBarIcon(notification.pkg, notification.user, n.icon, n.iconLevel, 0,
+                            n.tickerText));
             ImageView iv = (ImageView)group.findViewById(iconId);
             iv.setImageDrawable(icon);
             iv.setVisibility(View.VISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
new file mode 100644
index 0000000..519d3c1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.tv;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.statusbar.StatusBarNotification;
+import com.android.systemui.statusbar.BaseStatusBar;
+
+import android.os.IBinder;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.view.WindowManager;
+
+/*
+ * Status bar implementation for "large screen" products that mostly present no on-screen nav
+ */
+
+public class TvStatusBar extends BaseStatusBar {
+
+    @Override
+    public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
+    }
+
+    @Override
+    public void updateIcon(String slot, int index, int viewIndex, StatusBarIcon old,
+            StatusBarIcon icon) {
+    }
+
+    @Override
+    public void removeIcon(String slot, int index, int viewIndex) {
+    }
+
+    @Override
+    public void addNotification(IBinder key, StatusBarNotification notification) {
+    }
+
+    @Override
+    public void updateNotification(IBinder key, StatusBarNotification notification) {
+    }
+
+    @Override
+    public void removeNotification(IBinder key) {
+    }
+
+    @Override
+    public void disable(int state) {
+    }
+
+    @Override
+    public void animateExpandNotificationsPanel() {
+    }
+
+    @Override
+    public void animateCollapsePanels(int flags) {
+    }
+
+    @Override
+    public void setSystemUiVisibility(int vis, int mask) {
+    }
+
+    @Override
+    public void topAppWindowChanged(boolean visible) {
+    }
+
+    @Override
+    public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
+    }
+
+    @Override
+    public void setHardKeyboardStatus(boolean available, boolean enabled) {
+    }
+
+    @Override
+    public void toggleRecentApps() {
+    }
+
+    @Override // CommandQueue
+    public void setNavigationIconHints(int hints) {
+    }
+
+    @Override
+    protected void createAndAddWindows() {
+    }
+
+    @Override
+    protected WindowManager.LayoutParams getRecentsLayoutParams(
+            LayoutParams layoutParams) {
+        return null;
+    }
+
+    @Override
+    protected WindowManager.LayoutParams getSearchLayoutParams(
+            LayoutParams layoutParams) {
+        return null;
+    }
+
+    @Override
+    protected void haltTicker() {
+    }
+
+    @Override
+    protected void setAreThereNotifications() {
+    }
+
+    @Override
+    protected void updateNotificationIcons() {
+    }
+
+    @Override
+    protected void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
+    }
+
+    @Override
+    protected void updateExpandedViewPos(int expandedPosition) {
+    }
+
+    @Override
+    protected int getExpandedViewMaxHeight() {
+        return 0;
+    }
+
+    @Override
+    protected boolean shouldDisableNavbarGestures() {
+        return true;
+    }
+
+    public View getStatusBarView() {
+        return null;
+    }
+
+    @Override
+    public void animateExpandSettingsPanel() {
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 7dff549..91fc67a 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -25,6 +25,7 @@
 import android.os.Environment;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.UserHandle;
 import android.os.storage.StorageEventListener;
 import android.os.storage.StorageManager;
 import android.provider.Settings;
@@ -311,13 +312,14 @@
             mUsbStorageNotification.tickerText = title;
             if (pi == null) {
                 Intent intent = new Intent();
-                pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+                pi = PendingIntent.getBroadcastAsUser(mContext, 0, intent, 0,
+                        UserHandle.CURRENT);
             }
 
             mUsbStorageNotification.setLatestEventInfo(mContext, title, message, pi);
-            final boolean adbOn = 1 == Settings.Secure.getInt(
+            final boolean adbOn = 1 == Settings.Global.getInt(
                 mContext.getContentResolver(),
-                Settings.Secure.ADB_ENABLED,
+                Settings.Global.ADB_ENABLED,
                 0);
 
             if (POP_UMS_ACTIVITY_ON_CONNECT && !adbOn) {
@@ -336,9 +338,10 @@
     
         final int notificationId = mUsbStorageNotification.icon;
         if (visible) {
-            notificationManager.notify(notificationId, mUsbStorageNotification);
+            notificationManager.notifyAsUser(null, notificationId, mUsbStorageNotification,
+                    UserHandle.ALL);
         } else {
-            notificationManager.cancel(notificationId);
+            notificationManager.cancelAsUser(null, notificationId, UserHandle.ALL);
         }
     }
 
@@ -398,7 +401,8 @@
             mMediaStorageNotification.tickerText = title;
             if (pi == null) {
                 Intent intent = new Intent();
-                pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+                pi = PendingIntent.getBroadcastAsUser(mContext, 0, intent, 0,
+                        UserHandle.CURRENT);
             }
 
             mMediaStorageNotification.icon = icon;
@@ -407,9 +411,10 @@
     
         final int notificationId = mMediaStorageNotification.icon;
         if (visible) {
-            notificationManager.notify(notificationId, mMediaStorageNotification);
+            notificationManager.notifyAsUser(null, notificationId,
+                    mMediaStorageNotification, UserHandle.ALL);
         } else {
-            notificationManager.cancel(notificationId);
+            notificationManager.cancelAsUser(null, notificationId, UserHandle.ALL);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
index 5007cf4..ff06630 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
@@ -26,6 +26,7 @@
 import android.hardware.usb.UsbAccessory;
 import android.hardware.usb.UsbManager;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.util.Log;
 
 import com.android.internal.app.AlertActivity;
@@ -90,7 +91,7 @@
             intent.addCategory(Intent.CATEGORY_BROWSABLE);
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             try {
-                startActivity(intent);
+                startActivityAsUser(intent, UserHandle.CURRENT);
             } catch (ActivityNotFoundException e) {
                 Log.e(TAG, "startActivity failed for " + mUri);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
index 030a261..3eccccd 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
@@ -16,23 +16,21 @@
 
 package com.android.systemui.usb;
 
-import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.hardware.usb.IUsbManager;
-import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbAccessory;
+import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbManager;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -42,7 +40,6 @@
 
 import com.android.internal.app.AlertActivity;
 import com.android.internal.app.AlertController;
-
 import com.android.systemui.R;
 
 public class UsbConfirmActivity extends AlertActivity
@@ -62,10 +59,10 @@
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
-       Intent intent = getIntent();
-        mDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+        Intent intent = getIntent();
+        mDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
         mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
-        mResolveInfo = (ResolveInfo)intent.getParcelableExtra("rinfo");
+        mResolveInfo = (ResolveInfo) intent.getParcelableExtra("rinfo");
 
         PackageManager packageManager = getPackageManager();
         String appName = mResolveInfo.loadLabel(packageManager).toString();
@@ -117,7 +114,8 @@
             try {
                 IBinder b = ServiceManager.getService(USB_SERVICE);
                 IUsbManager service = IUsbManager.Stub.asInterface(b);
-                int uid = mResolveInfo.activityInfo.applicationInfo.uid;
+                final int uid = mResolveInfo.activityInfo.applicationInfo.uid;
+                final int userId = UserHandle.myUserId();
                 boolean alwaysUse = mAlwaysUse.isChecked();
                 Intent intent = null;
 
@@ -129,9 +127,10 @@
                     service.grantDevicePermission(mDevice, uid);
                     // set or clear default setting
                     if (alwaysUse) {
-                        service.setDevicePackage(mDevice, mResolveInfo.activityInfo.packageName);
+                        service.setDevicePackage(
+                                mDevice, mResolveInfo.activityInfo.packageName, userId);
                     } else {
-                        service.setDevicePackage(mDevice, null);
+                        service.setDevicePackage(mDevice, null, userId);
                     }
                 } else if (mAccessory != null) {
                     intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
@@ -141,10 +140,10 @@
                     service.grantAccessoryPermission(mAccessory, uid);
                     // set or clear default setting
                     if (alwaysUse) {
-                        service.setAccessoryPackage(mAccessory,
-                                mResolveInfo.activityInfo.packageName);
+                        service.setAccessoryPackage(
+                                mAccessory, mResolveInfo.activityInfo.packageName, userId);
                     } else {
-                        service.setAccessoryPackage(mAccessory, null);
+                        service.setAccessoryPackage(mAccessory, null, userId);
                     }
                 }
 
@@ -152,7 +151,7 @@
                 intent.setComponent(
                     new ComponentName(mResolveInfo.activityInfo.packageName,
                             mResolveInfo.activityInfo.name));
-                startActivity(intent);
+                startActivityAsUser(intent, new UserHandle(userId));
             } catch (Exception e) {
                 Log.e(TAG, "Unable to start activity", e);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
new file mode 100644
index 0000000..9146ccd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.usb;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Typeface;
+import android.hardware.usb.IUsbManager;
+import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbManager;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.internal.app.AlertActivity;
+import com.android.internal.app.AlertController;
+
+import com.android.systemui.R;
+
+public class UsbDebuggingActivity extends AlertActivity
+                                  implements DialogInterface.OnClickListener {
+    private static final String TAG = "UsbDebuggingActivity";
+
+    private CheckBox mAlwaysAllow;
+    private UsbDisconnectedReceiver mDisconnectedReceiver;
+    private String mKey;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mDisconnectedReceiver = new UsbDisconnectedReceiver(this);
+        Intent intent = getIntent();
+        String fingerprints = intent.getStringExtra("fingerprints");
+        mKey = intent.getStringExtra("key");
+
+        if (fingerprints == null || mKey == null) {
+            finish();
+            return;
+        }
+
+        final AlertController.AlertParams ap = mAlertParams;
+        ap.mTitle = getString(R.string.usb_debugging_title);
+        ap.mIconId = com.android.internal.R.drawable.ic_dialog_usb;
+        ap.mMessage = getString(R.string.usb_debugging_message, fingerprints);
+        ap.mPositiveButtonText = getString(android.R.string.ok);
+        ap.mNegativeButtonText = getString(android.R.string.cancel);
+        ap.mPositiveButtonListener = this;
+        ap.mNegativeButtonListener = this;
+
+        // add "always allow" checkbox
+        LayoutInflater inflater = LayoutInflater.from(ap.mContext);
+        View checkbox = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
+        mAlwaysAllow = (CheckBox)checkbox.findViewById(com.android.internal.R.id.alwaysUse);
+        mAlwaysAllow.setText(getString(R.string.usb_debugging_always));
+        ap.mView = checkbox;
+
+        setupAlert();
+    }
+
+    private class UsbDisconnectedReceiver extends BroadcastReceiver {
+        private final Activity mActivity;
+        public UsbDisconnectedReceiver(Activity activity) {
+            mActivity = activity;
+        }
+
+        @Override
+        public void onReceive(Context content, Intent intent) {
+            String action = intent.getAction();
+            if (!UsbManager.ACTION_USB_STATE.equals(action)) {
+                return;
+            }
+            boolean connected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
+            if (!connected) {
+                mActivity.finish();
+            }
+        }
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_STATE);
+        registerReceiver(mDisconnectedReceiver, filter);
+    }
+
+    @Override
+    protected void onStop() {
+        if (mDisconnectedReceiver != null) {
+            unregisterReceiver(mDisconnectedReceiver);
+        }
+        super.onStop();
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        boolean allow = (which == AlertDialog.BUTTON_POSITIVE);
+        boolean alwaysAllow = allow && mAlwaysAllow.isChecked();
+        try {
+            IBinder b = ServiceManager.getService(USB_SERVICE);
+            IUsbManager service = IUsbManager.Stub.asInterface(b);
+            if (allow) {
+                service.allowUsbDebugging(alwaysAllow, mKey);
+            } else {
+                service.denyUsbDebugging();
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Unable to notify Usb service", e);
+        }
+        finish();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
index c384f50..6e88d0d 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
@@ -32,6 +32,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -67,7 +68,7 @@
         mDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
         mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
         mPendingIntent = (PendingIntent)intent.getParcelableExtra(Intent.EXTRA_INTENT);
-        mUid = intent.getIntExtra("uid", 0);
+        mUid = intent.getIntExtra(Intent.EXTRA_UID, -1);
         mPackageName = intent.getStringExtra("package");
 
         PackageManager packageManager = getPackageManager();
@@ -128,7 +129,8 @@
                 if (mPermissionGranted) {
                     service.grantDevicePermission(mDevice, mUid);
                     if (mAlwaysUse.isChecked()) {
-                        service.setDevicePackage(mDevice, mPackageName);
+                        final int userId = UserHandle.getUserId(mUid);
+                        service.setDevicePackage(mDevice, mPackageName, userId);
                     }
                 }
             }
@@ -137,7 +139,8 @@
                 if (mPermissionGranted) {
                     service.grantAccessoryPermission(mAccessory, mUid);
                     if (mAlwaysUse.isChecked()) {
-                        service.setAccessoryPackage(mAccessory, mPackageName);
+                        final int userId = UserHandle.getUserId(mUid);
+                        service.setAccessoryPackage(mAccessory, mPackageName, userId);
                     }
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
index f61ecb1..9928f7f 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.usb;
 
-import com.android.internal.app.ResolverActivity;
-
 import android.content.ActivityNotFoundException;
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
@@ -30,9 +28,11 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.Log;
 import android.widget.CheckBox;
 
+import com.android.internal.app.ResolverActivity;
 import com.android.systemui.R;
 
 import java.util.ArrayList;
@@ -92,34 +92,36 @@
         super.onDestroy();
     }
 
+    @Override
     protected void onIntentSelected(ResolveInfo ri, Intent intent, boolean alwaysCheck) {
         try {
             IBinder b = ServiceManager.getService(USB_SERVICE);
             IUsbManager service = IUsbManager.Stub.asInterface(b);
-            int uid = ri.activityInfo.applicationInfo.uid;
+            final int uid = ri.activityInfo.applicationInfo.uid;
+            final int userId = UserHandle.myUserId();
 
             if (mDevice != null) {
                 // grant permission for the device
                 service.grantDevicePermission(mDevice, uid);
                 // set or clear default setting
                 if (alwaysCheck) {
-                    service.setDevicePackage(mDevice, ri.activityInfo.packageName);
+                    service.setDevicePackage(mDevice, ri.activityInfo.packageName, userId);
                 } else {
-                    service.setDevicePackage(mDevice, null);
+                    service.setDevicePackage(mDevice, null, userId);
                 }
             } else if (mAccessory != null) {
                 // grant permission for the accessory
                 service.grantAccessoryPermission(mAccessory, uid);
                 // set or clear default setting
                 if (alwaysCheck) {
-                    service.setAccessoryPackage(mAccessory, ri.activityInfo.packageName);
+                    service.setAccessoryPackage(mAccessory, ri.activityInfo.packageName, userId);
                 } else {
-                    service.setAccessoryPackage(mAccessory, null);
+                    service.setAccessoryPackage(mAccessory, null, userId);
                 }
             }
 
             try {
-                startActivity(intent);
+                startActivityAsUser(intent, new UserHandle(userId));
             } catch (ActivityNotFoundException e) {
                 Log.e(TAG, "startActivity failed", e);
             }
diff --git a/packages/VpnDialogs/res/values-fa/strings.xml b/packages/VpnDialogs/res/values-fa/strings.xml
index 7bd5590..ec163af 100644
--- a/packages/VpnDialogs/res/values-fa/strings.xml
+++ b/packages/VpnDialogs/res/values-fa/strings.xml
@@ -17,7 +17,7 @@
 <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="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>
diff --git a/packages/VpnDialogs/res/values-in/strings.xml b/packages/VpnDialogs/res/values-in/strings.xml
index c9710e5..2848f83 100644
--- a/packages/VpnDialogs/res/values-in/strings.xml
+++ b/packages/VpnDialogs/res/values-in/strings.xml
@@ -17,7 +17,7 @@
 <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> mencoba membuat sambungan VPN."</string>
-    <string name="warning" msgid="5470743576660160079">"Dengan melanjutkan, Anda memberikan izin kepada aplikasi untuk mencegat semua lalu lintas jaringan. "<b>"JANGAN memberi izin kecuali Anda mempercayai aplikasi ini."</b>" Jika tidak, data Anda berisiko disusupi oleh perangkat lunak jahat."</string>
+    <string name="warning" msgid="5470743576660160079">"Dengan melanjutkan, Anda memberikan izin kepada aplikasi untuk mencegat semua lalu lintas jaringan. "<b>"JANGAN memberi izin kecuali Anda mempercayai aplikasi ini."</b>" Jika tidak, data Anda berisiko disusupi oleh perangkat lunak perusak."</string>
     <string name="accept" msgid="2889226408765810173">"Saya mempercayai aplikasi ini."</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN tersambung"</string>
     <string name="configure" msgid="4905518375574791375">"Konfigurasikan"</string>
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
index 9999adb..96de1b9 100644
--- a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
@@ -79,7 +79,7 @@
             mDataReceived = (TextView) view.findViewById(R.id.data_received);
             mDataRowsHidden = true;
 
-            if (mConfig.user.equals(VpnConfig.LEGACY_VPN)) {
+            if (mConfig.legacy) {
                 mAlertParams.mIconId = android.R.drawable.ic_dialog_info;
                 mAlertParams.mTitle = getText(R.string.legacy_title);
             } else {
@@ -123,7 +123,11 @@
             if (which == DialogInterface.BUTTON_POSITIVE) {
                 mConfig.configureIntent.send();
             } else if (which == DialogInterface.BUTTON_NEUTRAL) {
-                mService.prepareVpn(mConfig.user, VpnConfig.LEGACY_VPN);
+                if (mConfig.legacy) {
+                    mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN);
+                } else {
+                    mService.prepareVpn(mConfig.user, VpnConfig.LEGACY_VPN);
+                }
             }
         } catch (Exception e) {
             Log.e(TAG, "onClick", e);
diff --git a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
deleted file mode 100644
index a4baeed..0000000
--- a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
+++ /dev/null
@@ -1,317 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import com.android.internal.R;
-import com.android.internal.widget.LockPatternUtils;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.accounts.OperationCanceledException;
-import android.accounts.AccountManagerFuture;
-import android.accounts.AuthenticatorException;
-import android.accounts.AccountManagerCallback;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.text.Editable;
-import android.text.InputFilter;
-import android.text.LoginFilter;
-import android.text.TextWatcher;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-import android.app.Dialog;
-import android.app.ProgressDialog;
-import android.os.Bundle;
-
-import java.io.IOException;
-
-/**
- * When the user forgets their password a bunch of times, we fall back on their
- * account's login/password to unlock the phone (and reset their lock pattern).
- */
-public class AccountUnlockScreen extends RelativeLayout implements KeyguardScreen,
-        View.OnClickListener, TextWatcher {
-    private static final String LOCK_PATTERN_PACKAGE = "com.android.settings";
-    private static final String LOCK_PATTERN_CLASS = LOCK_PATTERN_PACKAGE + ".ChooseLockGeneric";
-
-    /**
-     * The amount of millis to stay awake once this screen detects activity
-     */
-    private static final int AWAKE_POKE_MILLIS = 30000;
-
-    private KeyguardScreenCallback mCallback;
-    private LockPatternUtils mLockPatternUtils;
-    private KeyguardUpdateMonitor mUpdateMonitor;
-
-    private TextView mTopHeader;
-    private TextView mInstructions;
-    private EditText mLogin;
-    private EditText mPassword;
-    private Button mOk;
-
-    /**
-     * Shown while making asynchronous check of password.
-     */
-    private ProgressDialog mCheckingDialog;
-    private KeyguardStatusViewManager mKeyguardStatusViewManager;
-
-    /**
-     * AccountUnlockScreen constructor.
-     * @param configuration
-     * @param updateMonitor
-     */
-    public AccountUnlockScreen(Context context, Configuration configuration,
-            KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback,
-            LockPatternUtils lockPatternUtils) {
-        super(context);
-        mCallback = callback;
-        mLockPatternUtils = lockPatternUtils;
-
-        LayoutInflater.from(context).inflate(
-                R.layout.keyguard_screen_glogin_unlock, this, true);
-
-        mTopHeader = (TextView) findViewById(R.id.topHeader);
-        mTopHeader.setText(mLockPatternUtils.isPermanentlyLocked() ?
-                R.string.lockscreen_glogin_too_many_attempts :
-                R.string.lockscreen_glogin_forgot_pattern);
-
-        mInstructions = (TextView) findViewById(R.id.instructions);
-
-        mLogin = (EditText) findViewById(R.id.login);
-        mLogin.setFilters(new InputFilter[] { new LoginFilter.UsernameFilterGeneric() } );
-        mLogin.addTextChangedListener(this);
-
-        mPassword = (EditText) findViewById(R.id.password);
-        mPassword.addTextChangedListener(this);
-
-        mOk = (Button) findViewById(R.id.ok);
-        mOk.setOnClickListener(this);
-
-        mUpdateMonitor = updateMonitor;
-
-        mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor,
-                lockPatternUtils, callback, true);
-    }
-
-    public void afterTextChanged(Editable s) {
-    }
-
-    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-    }
-
-    public void onTextChanged(CharSequence s, int start, int before, int count) {
-        mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
-    }
-
-    @Override
-    protected boolean onRequestFocusInDescendants(int direction,
-            Rect previouslyFocusedRect) {
-        // send focus to the login field
-        return mLogin.requestFocus(direction, previouslyFocusedRect);
-    }
-
-    /** {@inheritDoc} */
-    public boolean needsInput() {
-        return true;
-    }
-
-    /** {@inheritDoc} */
-    public void onPause() {
-        mKeyguardStatusViewManager.onPause();
-    }
-
-    /** {@inheritDoc} */
-    public void onResume() {
-        // start fresh
-        mLogin.setText("");
-        mPassword.setText("");
-        mLogin.requestFocus();
-        mKeyguardStatusViewManager.onResume();
-    }
-
-    /** {@inheritDoc} */
-    public void cleanUp() {
-        if (mCheckingDialog != null) {
-            mCheckingDialog.hide();
-        }
-        mUpdateMonitor.removeCallback(this); // this must be first
-        mCallback = null;
-        mLockPatternUtils = null;
-        mUpdateMonitor = null;
-    }
-
-    /** {@inheritDoc} */
-    public void onClick(View v) {
-        mCallback.pokeWakelock();
-        if (v == mOk) {
-            asyncCheckPassword();
-        }
-    }
-
-    private void postOnCheckPasswordResult(final boolean success) {
-        // ensure this runs on UI thread
-        mLogin.post(new Runnable() {
-            public void run() {
-                if (success) {
-                    // clear out forgotten password
-                    mLockPatternUtils.setPermanentlyLocked(false);
-                    mLockPatternUtils.setLockPatternEnabled(false);
-                    mLockPatternUtils.saveLockPattern(null);
-
-                    // launch the 'choose lock pattern' activity so
-                    // the user can pick a new one if they want to
-                    Intent intent = new Intent();
-                    intent.setClassName(LOCK_PATTERN_PACKAGE, LOCK_PATTERN_CLASS);
-                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                    mContext.startActivity(intent);
-                    mCallback.reportSuccessfulUnlockAttempt();
-
-                    // close the keyguard
-                    mCallback.keyguardDone(true);
-                } else {
-                    mInstructions.setText(R.string.lockscreen_glogin_invalid_input);
-                    mPassword.setText("");
-                    mCallback.reportFailedUnlockAttempt();
-                }
-            }
-        });
-    }
-
-    @Override
-    public boolean dispatchKeyEvent(KeyEvent event) {
-        if (event.getAction() == KeyEvent.ACTION_DOWN
-                && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
-            if (mLockPatternUtils.isPermanentlyLocked()) {
-                mCallback.goToLockScreen();
-            } else {
-                mCallback.forgotPattern(false);
-            }
-            return true;
-        }
-        return super.dispatchKeyEvent(event);
-    }
-
-    /**
-     * Given the string the user entered in the 'username' field, find
-     * the stored account that they probably intended.  Prefer, in order:
-     *
-     *   - an exact match for what was typed, or
-     *   - a case-insensitive match for what was typed, or
-     *   - if they didn't include a domain, an exact match of the username, or
-     *   - if they didn't include a domain, a case-insensitive
-     *     match of the username.
-     *
-     * If there is a tie for the best match, choose neither --
-     * the user needs to be more specific.
-     *
-     * @return an account name from the database, or null if we can't
-     * find a single best match.
-     */
-    private Account findIntendedAccount(String username) {
-        Account[] accounts = AccountManager.get(mContext).getAccountsByType("com.google");
-
-        // Try to figure out which account they meant if they
-        // typed only the username (and not the domain), or got
-        // the case wrong.
-
-        Account bestAccount = null;
-        int bestScore = 0;
-        for (Account a: accounts) {
-            int score = 0;
-            if (username.equals(a.name)) {
-                score = 4;
-            } else if (username.equalsIgnoreCase(a.name)) {
-                score = 3;
-            } else if (username.indexOf('@') < 0) {
-                int i = a.name.indexOf('@');
-                if (i >= 0) {
-                    String aUsername = a.name.substring(0, i);
-                    if (username.equals(aUsername)) {
-                        score = 2;
-                    } else if (username.equalsIgnoreCase(aUsername)) {
-                        score = 1;
-                    }
-                }
-            }
-            if (score > bestScore) {
-                bestAccount = a;
-                bestScore = score;
-            } else if (score == bestScore) {
-                bestAccount = null;
-            }
-        }
-        return bestAccount;
-    }
-
-    private void asyncCheckPassword() {
-        mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
-        final String login = mLogin.getText().toString();
-        final String password = mPassword.getText().toString();
-        Account account = findIntendedAccount(login);
-        if (account == null) {
-            postOnCheckPasswordResult(false);
-            return;
-        }
-        getProgressDialog().show();
-        Bundle options = new Bundle();
-        options.putString(AccountManager.KEY_PASSWORD, password);
-        AccountManager.get(mContext).confirmCredentials(account, options, null /* activity */,
-                new AccountManagerCallback<Bundle>() {
-            public void run(AccountManagerFuture<Bundle> future) {
-                try {
-                    mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
-                    final Bundle result = future.getResult();
-                    final boolean verified = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
-                    postOnCheckPasswordResult(verified);
-                } catch (OperationCanceledException e) {
-                    postOnCheckPasswordResult(false);
-                } catch (IOException e) {
-                    postOnCheckPasswordResult(false);
-                } catch (AuthenticatorException e) {
-                    postOnCheckPasswordResult(false);
-                } finally {
-                    mLogin.post(new Runnable() {
-                        public void run() {
-                            getProgressDialog().hide();
-                        }
-                    });
-                }
-            }
-        }, null /* handler */);
-    }
-
-    private Dialog getProgressDialog() {
-        if (mCheckingDialog == null) {
-            mCheckingDialog = new ProgressDialog(mContext);
-            mCheckingDialog.setMessage(
-                    mContext.getString(R.string.lockscreen_glogin_checking_password));
-            mCheckingDialog.setIndeterminate(true);
-            mCheckingDialog.setCancelable(false);
-            mCheckingDialog.getWindow().setType(
-                    WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
-        }
-        return mCheckingDialog;
-    }
-}
diff --git a/policy/src/com/android/internal/policy/impl/BiometricSensorUnlock.java b/policy/src/com/android/internal/policy/impl/BiometricSensorUnlock.java
deleted file mode 100644
index f476f82..0000000
--- a/policy/src/com/android/internal/policy/impl/BiometricSensorUnlock.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.internal.policy.impl;
-
-import android.view.View;
-
-interface BiometricSensorUnlock {
-    /**
-     * Initializes the view provided for the biometric unlock UI to work within.  The provided area
-     * completely covers the backup unlock mechanism.
-     * @param biometricUnlockView View provided for the biometric unlock UI.
-     */
-    public void initializeView(View biometricUnlockView);
-
-    /**
-     * Indicates whether the biometric unlock is running.  Before
-     * {@link BiometricSensorUnlock#start} is called, isRunning() returns false.  After a successful
-     * call to {@link BiometricSensorUnlock#start}, isRunning() returns true until the biometric
-     * unlock completes, {@link BiometricSensorUnlock#stop} has been called, or an error has
-     * forced the biometric unlock to stop.
-     * @return whether the biometric unlock is currently running.
-     */
-    public boolean isRunning();
-
-    /**
-     * Covers the backup unlock mechanism by showing the contents of the view initialized in
-     * {@link BiometricSensorUnlock#initializeView(View)}.  The view should disappear after the
-     * specified timeout.  If the timeout is 0, the interface shows until another event, such as
-     * calling {@link BiometricSensorUnlock#hide()}, causes it to disappear.  Called on the UI
-     * thread.
-     * @param timeoutMilliseconds Amount of time in milliseconds to display the view before
-     * disappearing.  A value of 0 means the view should remain visible.
-     */
-    public void show(long timeoutMilliseconds);
-
-    /**
-     * Uncovers the backup unlock mechanism by hiding the contents of the view initialized in
-     * {@link BiometricSensorUnlock#initializeView(View)}.
-     */
-    public void hide();
-
-    /**
-     * Binds to the biometric unlock service and starts the unlock procedure.  Called on the UI
-     * thread.
-     * @return false if it can't be started or the backup should be used.
-     */
-    public boolean start();
-
-    /**
-     * Stops the biometric unlock procedure and unbinds from the service.  Called on the UI thread.
-     * @return whether the biometric unlock was running when called.
-     */
-    public boolean stop();
-
-    /**
-     * Cleans up any resources used by the biometric unlock.
-     */
-    public void cleanUp();
-
-    /**
-     * Gets the Device Policy Manager quality of the biometric unlock sensor
-     * (e.g., PASSWORD_QUALITY_BIOMETRIC_WEAK).
-     * @return biometric unlock sensor quality, as defined by Device Policy Manager.
-     */
-    public int getQuality();
-}
diff --git a/policy/src/com/android/internal/policy/impl/EnableAccessibilityController.java b/policy/src/com/android/internal/policy/impl/EnableAccessibilityController.java
new file mode 100644
index 0000000..71b0d53
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/EnableAccessibilityController.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ *
+ * 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.internal.policy.impl;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.ServiceInfo;
+import android.media.AudioManager;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.speech.tts.TextToSpeech;
+import android.util.MathUtils;
+import android.view.IWindowManager;
+import android.view.MotionEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.IAccessibilityManager;
+
+import com.android.internal.R;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class EnableAccessibilityController {
+
+    private static final int SPEAK_WARNING_DELAY_MILLIS = 2000;
+    private static final int ENABLE_ACCESSIBILITY_DELAY_MILLIS = 6000;
+
+    public static final int MESSAGE_SPEAK_WARNING = 1;
+    public static final int MESSAGE_SPEAK_ENABLE_CANCELED = 2;
+    public static final int MESSAGE_ENABLE_ACCESSIBILITY = 3;
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message message) {
+            switch (message.what) {
+                case MESSAGE_SPEAK_WARNING: {
+                    String text = mContext.getString(R.string.continue_to_enable_accessibility);
+                    mTts.speak(text, TextToSpeech.QUEUE_FLUSH, null);
+                } break;
+                case MESSAGE_SPEAK_ENABLE_CANCELED: {
+                    String text = mContext.getString(R.string.enable_accessibility_canceled);
+                    mTts.speak(text, TextToSpeech.QUEUE_FLUSH, null);
+                } break;
+                case MESSAGE_ENABLE_ACCESSIBILITY: {
+                    enableAccessibility();
+                    mTone.play();
+                    mTts.speak(mContext.getString(R.string.accessibility_enabled),
+                            TextToSpeech.QUEUE_FLUSH, null);
+                } break;
+            }
+        }
+    };
+
+    private final IWindowManager mWindowManager = IWindowManager.Stub.asInterface(
+            ServiceManager.getService("window"));
+
+    private final IAccessibilityManager mAccessibilityManager = IAccessibilityManager
+            .Stub.asInterface(ServiceManager.getService("accessibility"));
+
+
+    private final Context mContext;
+    private final UserManager mUserManager;
+    private final TextToSpeech mTts;
+    private final Ringtone mTone;
+
+    private final float mTouchSlop;
+
+    private boolean mDestroyed;
+    private boolean mCanceled;
+
+    private float mFirstPointerDownX;
+    private float mFirstPointerDownY;
+    private float mSecondPointerDownX;
+    private float mSecondPointerDownY;
+
+    public EnableAccessibilityController(Context context) {
+        mContext = context;
+        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        mTts = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
+            @Override
+            public void onInit(int status) {
+                if (mDestroyed) {
+                    mTts.shutdown();
+                }
+            }
+        });
+        mTone = RingtoneManager.getRingtone(context, Settings.System.DEFAULT_NOTIFICATION_URI);
+        mTone.setStreamType(AudioManager.STREAM_MUSIC);
+        mTouchSlop = context.getResources().getDimensionPixelSize(
+                R.dimen.accessibility_touch_slop);
+    }
+
+    public static boolean canEnableAccessibilityViaGesture(Context context) {
+        AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(context);
+        // Accessibility is enabled and there is an enabled speaking
+        // accessibility service, then we have nothing to do.
+        if (accessibilityManager.isEnabled()
+                && !accessibilityManager.getEnabledAccessibilityServiceList(
+                        AccessibilityServiceInfo.FEEDBACK_SPOKEN).isEmpty()) {
+            return false;
+        }
+        // If the global gesture is enabled and there is a speaking service
+        // installed we are good to go, otherwise there is nothing to do.
+        return Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1
+                && !getInstalledSpeakingAccessibilityServices(context).isEmpty();
+    }
+
+    private static List<AccessibilityServiceInfo> getInstalledSpeakingAccessibilityServices(
+            Context context) {
+        List<AccessibilityServiceInfo> services = new ArrayList<AccessibilityServiceInfo>();
+        services.addAll(AccessibilityManager.getInstance(context)
+                .getInstalledAccessibilityServiceList());
+        Iterator<AccessibilityServiceInfo> iterator = services.iterator();
+        while (iterator.hasNext()) {
+            AccessibilityServiceInfo service = iterator.next();
+            if ((service.feedbackType & AccessibilityServiceInfo.FEEDBACK_SPOKEN) == 0) {
+                iterator.remove();
+            }
+        }
+        return services;
+    }
+
+    public void onDestroy() {
+        mDestroyed = true;
+    }
+
+    public boolean onInterceptTouchEvent(MotionEvent event) {
+        if (event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN
+                && event.getPointerCount() == 2) {
+            mFirstPointerDownX = event.getX(0);
+            mFirstPointerDownY = event.getY(0);
+            mSecondPointerDownX = event.getX(1);
+            mSecondPointerDownY = event.getY(1);
+            mHandler.sendEmptyMessageDelayed(MESSAGE_SPEAK_WARNING,
+                    SPEAK_WARNING_DELAY_MILLIS);
+            mHandler.sendEmptyMessageDelayed(MESSAGE_ENABLE_ACCESSIBILITY,
+                   ENABLE_ACCESSIBILITY_DELAY_MILLIS);
+            return true;
+        }
+        return false;
+    }
+
+    public boolean onTouchEvent(MotionEvent event) {
+        final int pointerCount = event.getPointerCount();
+        final int action = event.getActionMasked();
+        if (mCanceled) {
+            if (action == MotionEvent.ACTION_UP) {
+                mCanceled = false;
+            }
+            return true;
+        }
+        switch (action) {
+            case MotionEvent.ACTION_POINTER_DOWN: {
+                if (pointerCount > 2) {
+                    cancel();
+                }
+            } break;
+            case MotionEvent.ACTION_MOVE: {
+                final float firstPointerMove = MathUtils.dist(event.getX(0),
+                        event.getY(0), mFirstPointerDownX, mFirstPointerDownY);
+                if (Math.abs(firstPointerMove) > mTouchSlop) {
+                    cancel();
+                }
+                final float secondPointerMove = MathUtils.dist(event.getX(1),
+                        event.getY(1), mSecondPointerDownX, mSecondPointerDownY);
+                if (Math.abs(secondPointerMove) > mTouchSlop) {
+                    cancel();
+                }
+            } break;
+            case MotionEvent.ACTION_POINTER_UP:
+            case MotionEvent.ACTION_CANCEL: {
+                cancel();
+            } break;
+        }
+        return true;
+    }
+
+    private void cancel() {
+        mCanceled = true;
+        if (mHandler.hasMessages(MESSAGE_SPEAK_WARNING)) {
+            mHandler.removeMessages(MESSAGE_SPEAK_WARNING);
+        } else if (mHandler.hasMessages(MESSAGE_ENABLE_ACCESSIBILITY)) {
+            mHandler.sendEmptyMessage(MESSAGE_SPEAK_ENABLE_CANCELED);
+        }
+        mHandler.removeMessages(MESSAGE_ENABLE_ACCESSIBILITY);
+    }
+
+    private void enableAccessibility() {
+        List<AccessibilityServiceInfo> services = getInstalledSpeakingAccessibilityServices(
+                mContext);
+        if (services.isEmpty()) {
+            return;
+        }
+        boolean keyguardLocked = false;
+        try {
+            keyguardLocked = mWindowManager.isKeyguardLocked();
+        } catch (RemoteException re) {
+            /* ignore */
+        }
+
+        final boolean hasMoreThanOneUser = mUserManager.getUsers().size() > 1;
+
+        AccessibilityServiceInfo service = services.get(0);
+        boolean enableTouchExploration = (service.flags
+                & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
+        // Try to find a service supporting explore by touch.
+        if (!enableTouchExploration) {
+            final int serviceCount = services.size();
+            for (int i = 1; i < serviceCount; i++) {
+                AccessibilityServiceInfo candidate = services.get(i);
+                if ((candidate.flags & AccessibilityServiceInfo
+                        .FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0) {
+                    enableTouchExploration = true;
+                    service = candidate;
+                    break;
+                }
+            }
+        }
+
+        ServiceInfo serviceInfo = service.getResolveInfo().serviceInfo;
+        ComponentName componentName = new ComponentName(serviceInfo.packageName, serviceInfo.name);
+        if (!keyguardLocked || !hasMoreThanOneUser) {
+            final int userId = ActivityManager.getCurrentUser();
+            String enabledServiceString = componentName.flattenToString();
+            ContentResolver resolver = mContext.getContentResolver();
+            // Enable one speaking accessibility service.
+            Settings.Secure.putStringForUser(resolver,
+                    Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                    enabledServiceString, userId);
+            // Allow the services we just enabled to toggle touch exploration.
+            Settings.Secure.putStringForUser(resolver,
+                    Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+                    enabledServiceString, userId);
+            // Enable touch exploration.
+            if (enableTouchExploration) {
+                Settings.Secure.putIntForUser(resolver, Settings.Secure.TOUCH_EXPLORATION_ENABLED,
+                        1, userId);
+            }
+            // Enable accessibility script injection (AndroidVox) for web content.
+            Settings.Secure.putIntForUser(resolver, Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION,
+                    1, userId);
+            // Turn on accessibility mode last.
+            Settings.Secure.putIntForUser(resolver, Settings.Secure.ACCESSIBILITY_ENABLED,
+                    1, userId);
+        } else if (keyguardLocked) {
+            try {
+                mAccessibilityManager.temporaryEnableAccessibilityStateUntilKeyguardRemoved(
+                        componentName, enableTouchExploration);
+            } catch (RemoteException re) {
+                /* ignore */
+            }
+        }
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/FaceUnlock.java
deleted file mode 100644
index fda3c9d..0000000
--- a/policy/src/com/android/internal/policy/impl/FaceUnlock.java
+++ /dev/null
@@ -1,554 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import com.android.internal.R;
-import com.android.internal.policy.IFaceLockCallback;
-import com.android.internal.policy.IFaceLockInterface;
-import com.android.internal.widget.LockPatternUtils;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-import android.view.View;
-
-public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
-
-    private static final boolean DEBUG = false;
-    private static final String TAG = "FULLockscreen";
-
-    private final Context mContext;
-    private final LockPatternUtils mLockPatternUtils;
-    private final KeyguardUpdateMonitor mUpdateMonitor;
-
-    // TODO: is mServiceRunning needed or can we just use mIsRunning or check if mService is null?
-    private boolean mServiceRunning = false;
-    // TODO: now that the code has been restructure to do almost all operations from a handler, this
-    // lock may no longer be necessary.
-    private final Object mServiceRunningLock = new Object();
-    private IFaceLockInterface mService;
-    private boolean mBoundToService = false;
-    private View mFaceUnlockView;
-
-    private Handler mHandler;
-    private final int MSG_SHOW_FACE_UNLOCK_VIEW = 0;
-    private final int MSG_HIDE_FACE_UNLOCK_VIEW = 1;
-    private final int MSG_SERVICE_CONNECTED = 2;
-    private final int MSG_SERVICE_DISCONNECTED = 3;
-    private final int MSG_UNLOCK = 4;
-    private final int MSG_CANCEL = 5;
-    private final int MSG_REPORT_FAILED_ATTEMPT = 6;
-    private final int MSG_EXPOSE_FALLBACK = 7;
-    private final int MSG_POKE_WAKELOCK = 8;
-
-    // TODO: This was added for the purpose of adhering to what the biometric interface expects
-    // the isRunning() function to return.  However, it is probably not necessary to have both
-    // mRunning and mServiceRunning.  I'd just rather wait to change that logic.
-    private volatile boolean mIsRunning = false;
-
-    // Long enough to stay visible while the service starts
-    // Short enough to not have to wait long for backup if service fails to start or crashes
-    // The service can take a couple of seconds to start on the first try after boot
-    private final int SERVICE_STARTUP_VIEW_TIMEOUT = 3000;
-
-    // So the user has a consistent amount of time when brought to the backup method from Face
-    // Unlock
-    private final int BACKUP_LOCK_TIMEOUT = 5000;
-
-    KeyguardScreenCallback mKeyguardScreenCallback;
-
-    /**
-     * Stores some of the structures that Face Unlock will need to access and creates the handler
-     * will be used to execute messages on the UI thread.
-     */
-    public FaceUnlock(Context context, KeyguardUpdateMonitor updateMonitor,
-            LockPatternUtils lockPatternUtils, KeyguardScreenCallback keyguardScreenCallback) {
-        mContext = context;
-        mUpdateMonitor = updateMonitor;
-        mLockPatternUtils = lockPatternUtils;
-        mKeyguardScreenCallback = keyguardScreenCallback;
-        mHandler = new Handler(this);
-    }
-
-    /**
-     * Stores and displays the view that Face Unlock is allowed to draw within.
-     * TODO: since the layout object will eventually be shared by multiple biometric unlock
-     * methods, we will have to add our other views (background, cancel button) here.
-     */
-    public void initializeView(View biometricUnlockView) {
-        Log.d(TAG, "initializeView()");
-        mFaceUnlockView = biometricUnlockView;
-    }
-
-    /**
-     * Indicates whether Face Unlock is currently running.
-     */
-    public boolean isRunning() {
-        return mIsRunning;
-    }
-
-    /**
-     * Sets the Face Unlock view to visible, hiding it after the specified amount of time.  If
-     * timeoutMillis is 0, no hide is performed.  Called on the UI thread.
-     */
-    public void show(long timeoutMillis) {
-        if (DEBUG) Log.d(TAG, "show()");
-        if (mHandler.getLooper() != Looper.myLooper()) {
-            Log.e(TAG, "show() called off of the UI thread");
-        }
-
-        removeDisplayMessages();
-        if (mFaceUnlockView != null) {
-            mFaceUnlockView.setVisibility(View.VISIBLE);
-        }
-        if (timeoutMillis > 0) {
-            mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACE_UNLOCK_VIEW, timeoutMillis);
-        }
-    }
-
-    /**
-     * Hides the Face Unlock view.
-     */
-    public void hide() {
-        if (DEBUG) Log.d(TAG, "hide()");
-        // Remove messages to prevent a delayed show message from undo-ing the hide
-        removeDisplayMessages();
-        mHandler.sendEmptyMessage(MSG_HIDE_FACE_UNLOCK_VIEW);
-    }
-
-    /**
-     * Binds to the Face Unlock service.  Face Unlock will be started when the bind completes.  The
-     * Face Unlock view is displayed to hide the backup lock while the service is starting up.
-     * Called on the UI thread.
-     */
-    public boolean start() {
-        if (DEBUG) Log.d(TAG, "start()");
-        if (mHandler.getLooper() != Looper.myLooper()) {
-            Log.e(TAG, "start() called off of the UI thread");
-        }
-
-        if (mIsRunning) {
-            Log.w(TAG, "start() called when already running");
-        }
-
-        // Show Face Unlock view, but only for a little bit so lockpattern will become visible if
-        // Face Unlock fails to start or crashes
-        // This must show before bind to guarantee that Face Unlock has a place to display
-        show(SERVICE_STARTUP_VIEW_TIMEOUT);
-        if (!mBoundToService) {
-            Log.d(TAG, "Binding to Face Unlock service");
-            mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
-                    mConnection,
-                    Context.BIND_AUTO_CREATE,
-                    mLockPatternUtils.getCurrentUser());
-            mBoundToService = true;
-        } else {
-            Log.w(TAG, "Attempt to bind to Face Unlock when already bound");
-        }
-
-        mIsRunning = true;
-        return true;
-    }
-
-    /**
-     * Stops Face Unlock and unbinds from the service.  Called on the UI thread.
-     */
-    public boolean stop() {
-        if (DEBUG) Log.d(TAG, "stop()");
-        if (mHandler.getLooper() != Looper.myLooper()) {
-            Log.e(TAG, "stop() called off of the UI thread");
-        }
-
-        boolean mWasRunning = mIsRunning;
-        stopUi();
-
-        if (mBoundToService) {
-            if (mService != null) {
-                try {
-                    mService.unregisterCallback(mFaceUnlockCallback);
-                } catch (RemoteException e) {
-                    // Not much we can do
-                }
-            }
-            Log.d(TAG, "Unbinding from Face Unlock service");
-            mContext.unbindService(mConnection);
-            mBoundToService = false;
-        } else {
-            // This is usually not an error when this happens.  Sometimes we will tell it to
-            // unbind multiple times because it's called from both onWindowFocusChanged and
-            // onDetachedFromWindow.
-            if (DEBUG) Log.d(TAG, "Attempt to unbind from Face Unlock when not bound");
-        }
-        mIsRunning = false;
-        return mWasRunning;
-    }
-
-    /**
-     * Frees up resources used by Face Unlock and stops it if it is still running.
-     */
-    public void cleanUp() {
-        if (DEBUG) Log.d(TAG, "cleanUp()");
-        if (mService != null) {
-            try {
-                mService.unregisterCallback(mFaceUnlockCallback);
-            } catch (RemoteException e) {
-                // Not much we can do
-            }
-            stopUi();
-            mService = null;
-        }
-    }
-
-    /**
-     * Returns the Device Policy Manager quality for Face Unlock, which is BIOMETRIC_WEAK.
-     */
-    public int getQuality() {
-        return DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
-    }
-
-    /**
-     * Handles messages such that everything happens on the UI thread in a deterministic order.
-     * Calls from the Face Unlock service come from binder threads.  Calls from lockscreen typically
-     * come from the UI thread.  This makes sure there are no race conditions between those calls.
-     */
-    @Override
-    public boolean handleMessage(Message msg) {
-        switch (msg.what) {
-            case MSG_SHOW_FACE_UNLOCK_VIEW:
-                handleShowFaceUnlockView();
-                break;
-            case MSG_HIDE_FACE_UNLOCK_VIEW:
-                handleHideFaceUnlockView();
-                break;
-            case MSG_SERVICE_CONNECTED:
-                handleServiceConnected();
-                break;
-            case MSG_SERVICE_DISCONNECTED:
-                handleServiceDisconnected();
-                break;
-            case MSG_UNLOCK:
-                handleUnlock();
-                break;
-            case MSG_CANCEL:
-                handleCancel();
-                break;
-            case MSG_REPORT_FAILED_ATTEMPT:
-                handleReportFailedAttempt();
-                break;
-            case MSG_EXPOSE_FALLBACK:
-                handleExposeFallback();
-                break;
-            case MSG_POKE_WAKELOCK:
-                handlePokeWakelock(msg.arg1);
-                break;
-            default:
-                Log.e(TAG, "Unhandled message");
-                return false;
-        }
-        return true;
-    }
-
-    /**
-     * Sets the Face Unlock view to visible, thus covering the backup lock.
-     */
-    void handleShowFaceUnlockView() {
-        if (DEBUG) Log.d(TAG, "handleShowFaceUnlockView()");
-        if (mFaceUnlockView != null) {
-            mFaceUnlockView.setVisibility(View.VISIBLE);
-        } else {
-            Log.e(TAG, "mFaceUnlockView is null in handleShowFaceUnlockView()");
-        }
-    }
-
-    /**
-     * Sets the Face Unlock view to invisible, thus exposing the backup lock.
-     */
-    void handleHideFaceUnlockView() {
-        if (DEBUG) Log.d(TAG, "handleHideFaceUnlockView()");
-        if (mFaceUnlockView != null) {
-            mFaceUnlockView.setVisibility(View.INVISIBLE);
-        } else {
-            Log.e(TAG, "mFaceUnlockView is null in handleHideFaceUnlockView()");
-        }
-    }
-
-    /**
-     * Tells the service to start its UI via an AIDL interface.  Called when the
-     * onServiceConnected() callback is received.
-     */
-    void handleServiceConnected() {
-        Log.d(TAG, "handleServiceConnected()");
-
-        // It is possible that an unbind has occurred in the time between the bind and when this
-        // function is reached.  If an unbind has already occurred, proceeding on to call startUi()
-        // can result in a fatal error.  Note that the onServiceConnected() callback is
-        // asynchronous, so this possibility would still exist if we executed this directly in
-        // onServiceConnected() rather than using a handler.
-        if (!mBoundToService) {
-            Log.d(TAG, "Dropping startUi() in handleServiceConnected() because no longer bound");
-            return;
-        }
-
-        try {
-            mService.registerCallback(mFaceUnlockCallback);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Caught exception connecting to Face Unlock: " + e.toString());
-            mService = null;
-            mBoundToService = false;
-            mIsRunning = false;
-            return;
-        }
-
-        if (mFaceUnlockView != null) {
-            IBinder windowToken = mFaceUnlockView.getWindowToken();
-            if (windowToken != null) {
-                // When switching between portrait and landscape view while Face Unlock is running,
-                // the screen will eventually go dark unless we poke the wakelock when Face Unlock
-                // is restarted.
-                mKeyguardScreenCallback.pokeWakelock();
-
-                int[] position;
-                position = new int[2];
-                mFaceUnlockView.getLocationInWindow(position);
-                startUi(windowToken, position[0], position[1], mFaceUnlockView.getWidth(),
-                        mFaceUnlockView.getHeight());
-            } else {
-                Log.e(TAG, "windowToken is null in handleServiceConnected()");
-            }
-        }
-    }
-
-    /**
-     * Called when the onServiceDisconnected() callback is received.  This should not happen during
-     * normal operation.  It indicates an error has occurred.
-     */
-    void handleServiceDisconnected() {
-        Log.e(TAG, "handleServiceDisconnected()");
-        // TODO: this lock may no longer be needed now that everything is being called from a
-        // handler
-        synchronized (mServiceRunningLock) {
-            mService = null;
-            mServiceRunning = false;
-        }
-        mBoundToService = false;
-        mIsRunning = false;
-    }
-
-    /**
-     * Stops the Face Unlock service and tells the device to grant access to the user.  Shows the
-     * Face Unlock view to keep the backup lock covered while the device unlocks.
-     */
-    void handleUnlock() {
-        if (DEBUG) Log.d(TAG, "handleUnlock()");
-        removeDisplayMessages();
-        if (mFaceUnlockView != null) {
-            mFaceUnlockView.setVisibility(View.VISIBLE);
-        } else {
-            Log.e(TAG, "mFaceUnlockView is null in handleUnlock()");
-        }
-        stop();
-        mKeyguardScreenCallback.keyguardDone(true);
-        mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
-    }
-
-    /**
-     * Stops the Face Unlock service and exposes the backup lock.
-     */
-    void handleCancel() {
-        if (DEBUG) Log.d(TAG, "handleCancel()");
-        if (mFaceUnlockView != null) {
-            mFaceUnlockView.setVisibility(View.INVISIBLE);
-        } else {
-            Log.e(TAG, "mFaceUnlockView is null in handleCancel()");
-        }
-        stop();
-        mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
-    }
-
-    /**
-     * Increments the number of failed Face Unlock attempts.
-     */
-    void handleReportFailedAttempt() {
-        if (DEBUG) Log.d(TAG, "handleReportFailedAttempt()");
-        mUpdateMonitor.reportFailedBiometricUnlockAttempt();
-    }
-
-    /**
-     * Hides the Face Unlock view to expose the backup lock.  Called when the Face Unlock service UI
-     * is started, indicating there is no need to continue displaying the underlying view because
-     * the service UI is now covering the backup lock.
-     */
-    void handleExposeFallback() {
-        if (DEBUG) Log.d(TAG, "handleExposeFallback()");
-        if (mFaceUnlockView != null) {
-            mFaceUnlockView.setVisibility(View.INVISIBLE);
-        } else {
-            Log.e(TAG, "mFaceUnlockView is null in handleExposeFallback()");
-        }
-    }
-
-    /**
-     * Pokes the wakelock to keep the screen alive and active for a specific amount of time.
-     */
-    void handlePokeWakelock(int millis) {
-        mKeyguardScreenCallback.pokeWakelock(millis);
-    }
-
-    /**
-     * Removes show and hide messages from the message queue.  Called to prevent delayed show/hide
-     * messages from undoing a new message.
-     */
-    private void removeDisplayMessages() {
-        mHandler.removeMessages(MSG_SHOW_FACE_UNLOCK_VIEW);
-        mHandler.removeMessages(MSG_HIDE_FACE_UNLOCK_VIEW);
-    }
-
-    /**
-     * Implements service connection methods.
-     */
-    private ServiceConnection mConnection = new ServiceConnection() {
-        /**
-         * Called when the Face Unlock service connects after calling bind().
-         */
-        @Override
-        public void onServiceConnected(ComponentName className, IBinder iservice) {
-            Log.d(TAG, "Connected to Face Unlock service");
-            mService = IFaceLockInterface.Stub.asInterface(iservice);
-            mHandler.sendEmptyMessage(MSG_SERVICE_CONNECTED);
-        }
-
-        /**
-         * Called if the Face Unlock service unexpectedly disconnects.  This indicates an error.
-         */
-        @Override
-        public void onServiceDisconnected(ComponentName className) {
-            Log.e(TAG, "Unexpected disconnect from Face Unlock service");
-            mHandler.sendEmptyMessage(MSG_SERVICE_DISCONNECTED);
-        }
-    };
-
-    /**
-     * Tells the Face Unlock service to start displaying its UI and start processing.
-     */
-    private void startUi(IBinder windowToken, int x, int y, int w, int h) {
-        if (DEBUG) Log.d(TAG, "startUi()");
-        synchronized (mServiceRunningLock) {
-            if (!mServiceRunning) {
-                Log.d(TAG, "Starting Face Unlock");
-                try {
-                    mService.startUi(windowToken, x, y, w, h,
-                            mLockPatternUtils.isBiometricWeakLivelinessEnabled());
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Caught exception starting Face Unlock: " + e.toString());
-                    return;
-                }
-                mServiceRunning = true;
-            } else {
-                Log.w(TAG, "startUi() attempted while running");
-            }
-        }
-    }
-
-    /**
-     * Tells the Face Unlock service to stop displaying its UI and stop processing.
-     */
-    private void stopUi() {
-        if (DEBUG) Log.d(TAG, "stopUi()");
-        // Note that attempting to stop Face Unlock when it's not running is not an issue.
-        // Face Unlock can return, which stops it and then we try to stop it when the
-        // screen is turned off.  That's why we check.
-        synchronized (mServiceRunningLock) {
-            if (mServiceRunning) {
-                Log.d(TAG, "Stopping Face Unlock");
-                try {
-                    mService.stopUi();
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Caught exception stopping Face Unlock: " + e.toString());
-                }
-                mServiceRunning = false;
-            } else {
-                // This is usually not an error when this happens.  Sometimes we will tell it to
-                // stop multiple times because it's called from both onWindowFocusChanged and
-                // onDetachedFromWindow.
-                if (DEBUG) Log.d(TAG, "stopUi() attempted while not running");
-            }
-        }
-    }
-
-    /**
-     * Implements the AIDL biometric unlock service callback interface.
-     */
-    private final IFaceLockCallback mFaceUnlockCallback = new IFaceLockCallback.Stub() {
-        /**
-         * Called when Face Unlock wants to grant access to the user.
-         */
-        @Override
-        public void unlock() {
-            if (DEBUG) Log.d(TAG, "unlock()");
-            mHandler.sendEmptyMessage(MSG_UNLOCK);
-        }
-
-        /**
-         * Called when Face Unlock wants to go to the backup.
-         */
-        @Override
-        public void cancel() {
-            if (DEBUG) Log.d(TAG, "cancel()");
-            mHandler.sendEmptyMessage(MSG_CANCEL);
-        }
-
-        /**
-         * Called when Face Unlock wants to increment the number of failed attempts.
-         */
-        @Override
-        public void reportFailedAttempt() {
-            if (DEBUG) Log.d(TAG, "reportFailedAttempt()");
-            mHandler.sendEmptyMessage(MSG_REPORT_FAILED_ATTEMPT);
-        }
-
-        /**
-         * Called when the Face Unlock service starts displaying the UI, indicating that the backup
-         * unlock can be exposed because the Face Unlock service is now covering the backup with its
-         * UI.
-         **/
-        @Override
-        public void exposeFallback() {
-            if (DEBUG) Log.d(TAG, "exposeFallback()");
-            mHandler.sendEmptyMessage(MSG_EXPOSE_FALLBACK);
-        }
-
-        /**
-         * Called when Face Unlock wants to keep the screen alive and active for a specific amount
-         * of time.
-         */
-        public void pokeWakelock(int millis) {
-            if (DEBUG) Log.d(TAG, "pokeWakelock() for " + millis + "ms");
-            Message message = mHandler.obtainMessage(MSG_POKE_WAKELOCK, millis, -1);
-            mHandler.sendMessage(message);
-        }
-
-    };
-}
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index fc187ce..d1f8ef1 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -16,12 +16,15 @@
 
 package com.android.internal.policy.impl;
 
+import com.android.internal.app.AlertController;
+import com.android.internal.app.AlertController.AlertParams;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.R;
 
 import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
+import android.app.Dialog;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -29,29 +32,41 @@
 import android.content.IntentFilter;
 import android.content.pm.UserInfo;
 import android.database.ContentObserver;
+import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
+import android.os.Bundle;
 import android.os.Handler;
-import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.os.Vibrator;
 import android.provider.Settings;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.util.Log;
-import android.view.IWindowManager;
+import android.util.TypedValue;
+import android.view.InputDevice;
+import android.view.KeyEvent;
 import android.view.LayoutInflater;
+import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.view.WindowManagerPolicy.WindowManagerFuncs;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
 import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+import android.widget.ListView;
 import android.widget.TextView;
 
 import java.util.ArrayList;
@@ -71,9 +86,10 @@
     private final Context mContext;
     private final WindowManagerFuncs mWindowManagerFuncs;
     private final AudioManager mAudioManager;
+    private final IDreamManager mDreamManager;
 
     private ArrayList<Action> mItems;
-    private AlertDialog mDialog;
+    private GlobalActionsDialog mDialog;
 
     private Action mSilentModeAction;
     private ToggleAction mAirplaneModeOn;
@@ -87,8 +103,6 @@
     private boolean mHasTelephony;
     private boolean mHasVibrator;
 
-    private IWindowManager mIWindowManager;
-
     /**
      * @param context everything needs a context :(
      */
@@ -96,6 +110,8 @@
         mContext = context;
         mWindowManagerFuncs = windowManagerFuncs;
         mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        mDreamManager = IDreamManager.Stub.asInterface(
+                ServiceManager.getService(DreamService.DREAM_SERVICE));
 
         // receive broadcasts
         IntentFilter filter = new IntentFilter();
@@ -112,7 +128,7 @@
                 context.getSystemService(Context.CONNECTIVITY_SERVICE);
         mHasTelephony = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
         mContext.getContentResolver().registerContentObserver(
-                Settings.System.getUriFor(Settings.System.AIRPLANE_MODE_ON), true,
+                Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
                 mAirplaneModeObserver);
         Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
         mHasVibrator = vibrator != null && vibrator.hasVibrator();
@@ -135,10 +151,26 @@
         }
     }
 
+    private void awakenIfNecessary() {
+        if (mDreamManager != null) {
+            try {
+                if (mDreamManager.isDreaming()) {
+                    mDreamManager.awaken();
+                }
+            } catch (RemoteException e) {
+                // we tried
+            }
+        }
+    }
+
     private void handleShow() {
+        awakenIfNecessary();
         mDialog = createDialog();
         prepareDialog();
 
+        WindowManager.LayoutParams attrs = mDialog.getWindow().getAttributes();
+        attrs.setTitle("GlobalActions");
+        mDialog.getWindow().setAttributes(attrs);
         mDialog.show();
         mDialog.getWindow().getDecorView().setSystemUiVisibility(View.STATUS_BAR_DISABLE_EXPAND);
     }
@@ -147,7 +179,7 @@
      * Create the global actions dialog.
      * @return A new dialog.
      */
-    private AlertDialog createDialog() {
+    private GlobalActionsDialog createDialog() {
         // Simple toggle style if there's no vibrator, otherwise use a tri-state
         if (!mHasVibrator) {
             mSilentModeAction = new SilentModeToggleAction();
@@ -207,11 +239,11 @@
 
                 public void onPress() {
                     // shutdown by making sure radio and power are handled accordingly.
-                    mWindowManagerFuncs.shutdown();
+                    mWindowManagerFuncs.shutdown(true);
                 }
 
                 public boolean onLongPress() {
-                    mWindowManagerFuncs.rebootSafeMode();
+                    mWindowManagerFuncs.rebootSafeMode(true);
                     return true;
                 }
 
@@ -227,12 +259,95 @@
         // next: airplane mode
         mItems.add(mAirplaneModeOn);
 
+        // next: bug report, if enabled
+        if (Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.BUGREPORT_IN_POWER_MENU, 0) != 0) {
+            mItems.add(
+                new SinglePressAction(com.android.internal.R.drawable.stat_sys_adb,
+                        R.string.global_action_bug_report) {
+
+                    public void onPress() {
+                        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
+                        builder.setTitle(com.android.internal.R.string.bugreport_title);
+                        builder.setMessage(com.android.internal.R.string.bugreport_message);
+                        builder.setNegativeButton(com.android.internal.R.string.cancel, null);
+                        builder.setPositiveButton(com.android.internal.R.string.report,
+                                new DialogInterface.OnClickListener() {
+                                    @Override
+                                    public void onClick(DialogInterface dialog, int which) {
+                                        // Add a little delay before executing, to give the
+                                        // dialog a chance to go away before it takes a
+                                        // screenshot.
+                                        mHandler.postDelayed(new Runnable() {
+                                            @Override public void run() {
+                                                try {
+                                                    ActivityManagerNative.getDefault()
+                                                            .requestBugReport();
+                                                } catch (RemoteException e) {
+                                                }
+                                            }
+                                        }, 500);
+                                    }
+                                });
+                        AlertDialog dialog = builder.create();
+                        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+                        dialog.show();
+                    }
+
+                    public boolean onLongPress() {
+                        return false;
+                    }
+
+                    public boolean showDuringKeyguard() {
+                        return true;
+                    }
+
+                    public boolean showBeforeProvisioning() {
+                        return false;
+                    }
+                });
+        }
+
         // last: silent mode
         if (SHOW_SILENT_TOGGLE) {
             mItems.add(mSilentModeAction);
         }
 
-        List<UserInfo> users = mContext.getPackageManager().getUsers();
+        // one more thing: optionally add a list of users to switch to
+        if (SystemProperties.getBoolean("fw.power_user_switcher", false)) {
+            addUsersToMenu(mItems);
+        }
+
+        mAdapter = new MyAdapter();
+
+        AlertParams params = new AlertParams(mContext);
+        params.mAdapter = mAdapter;
+        params.mOnClickListener = this;
+        params.mForceInverseBackground = true;
+
+        GlobalActionsDialog dialog = new GlobalActionsDialog(mContext, params);
+        dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
+
+        dialog.getListView().setItemsCanFocus(true);
+        dialog.getListView().setLongClickable(true);
+        dialog.getListView().setOnItemLongClickListener(
+                new AdapterView.OnItemLongClickListener() {
+                    @Override
+                    public boolean onItemLongClick(AdapterView<?> parent, View view, int position,
+                            long id) {
+                        return mAdapter.getItem(position).onLongPress();
+                    }
+        });
+        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+
+        dialog.setOnDismissListener(this);
+
+        return dialog;
+    }
+
+    private void addUsersToMenu(ArrayList<Action> items) {
+        List<UserInfo> users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
+                .getUsers();
         if (users.size() > 1) {
             UserInfo currentUser;
             try {
@@ -243,14 +358,15 @@
             for (final UserInfo user : users) {
                 boolean isCurrentUser = currentUser == null
                         ? user.id == 0 : (currentUser.id == user.id);
+                Drawable icon = user.iconPath != null ? Drawable.createFromPath(user.iconPath)
+                        : null;
                 SinglePressAction switchToUser = new SinglePressAction(
-                        com.android.internal.R.drawable.ic_menu_cc,
+                        com.android.internal.R.drawable.ic_menu_cc, icon,
                         (user.name != null ? user.name : "Primary")
                         + (isCurrentUser ? " \u2714" : "")) {
                     public void onPress() {
                         try {
                             ActivityManagerNative.getDefault().switchUser(user.id);
-                            getWindowManager().lockNow();
                         } catch (RemoteException re) {
                             Log.e(TAG, "Couldn't switch user " + re);
                         }
@@ -264,44 +380,16 @@
                         return false;
                     }
                 };
-                mItems.add(switchToUser);
+                items.add(switchToUser);
             }
         }
-
-        mAdapter = new MyAdapter();
-
-        final AlertDialog.Builder ab = new AlertDialog.Builder(mContext);
-
-        ab.setAdapter(mAdapter, this)
-                .setInverseBackgroundForced(true);
-
-        final AlertDialog dialog = ab.create();
-        dialog.getListView().setItemsCanFocus(true);
-        dialog.getListView().setLongClickable(true);
-        dialog.getListView().setOnItemLongClickListener(
-                new AdapterView.OnItemLongClickListener() {
-                    @Override
-                    public boolean onItemLongClick(AdapterView<?> parent, View view, int position,
-                            long id) {
-                        return mAdapter.getItem(position).onLongPress();
-                    }
-        });
-        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
-
-        dialog.setOnDismissListener(this);
-
-        return dialog;
     }
 
     private void prepareDialog() {
         refreshSilentMode();
         mAirplaneModeOn.updateState(mAirplaneState);
         mAdapter.notifyDataSetChanged();
-        if (mKeyguardShowing) {
-            mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
-        } else {
-            mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
-        }
+        mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
         if (SHOW_SILENT_TOGGLE) {
             IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
             mContext.registerReceiver(mRingerModeReceiver, filter);
@@ -439,6 +527,7 @@
      */
     private static abstract class SinglePressAction implements Action {
         private final int mIconResId;
+        private final Drawable mIcon;
         private final int mMessageResId;
         private final CharSequence mMessage;
 
@@ -446,13 +535,23 @@
             mIconResId = iconResId;
             mMessageResId = messageResId;
             mMessage = null;
+            mIcon = null;
+        }
+
+        protected SinglePressAction(int iconResId, Drawable icon, CharSequence message) {
+            mIconResId = iconResId;
+            mMessageResId = 0;
+            mMessage = message;
+            mIcon = icon;
         }
 
         protected SinglePressAction(int iconResId, CharSequence message) {
             mIconResId = iconResId;
             mMessageResId = 0;
             mMessage = message;
+            mIcon = null;
         }
+
         public boolean isEnabled() {
             return true;
         }
@@ -471,8 +570,12 @@
             TextView messageView = (TextView) v.findViewById(R.id.message);
 
             v.findViewById(R.id.status).setVisibility(View.GONE);
-
-            icon.setImageDrawable(context.getResources().getDrawable(mIconResId));
+            if (mIcon != null) {
+                icon.setImageDrawable(mIcon);
+                icon.setScaleType(ScaleType.CENTER_CROP);
+            } else if (mIconResId != 0) {
+                icon.setImageDrawable(context.getResources().getDrawable(mIconResId));
+            }
             if (mMessage != null) {
                 messageView.setText(mMessage);
             } else {
@@ -784,9 +887,9 @@
         // Let the service state callbacks handle the state.
         if (mHasTelephony) return;
 
-        boolean airplaneModeOn = Settings.System.getInt(
+        boolean airplaneModeOn = Settings.Global.getInt(
                 mContext.getContentResolver(),
-                Settings.System.AIRPLANE_MODE_ON,
+                Settings.Global.AIRPLANE_MODE_ON,
                 0) == 1;
         mAirplaneState = airplaneModeOn ? ToggleAction.State.On : ToggleAction.State.Off;
         mAirplaneModeOn.updateState(mAirplaneState);
@@ -796,24 +899,133 @@
      * Change the airplane mode system setting
      */
     private void changeAirplaneModeSystemSetting(boolean on) {
-        Settings.System.putInt(
+        Settings.Global.putInt(
                 mContext.getContentResolver(),
-                Settings.System.AIRPLANE_MODE_ON,
+                Settings.Global.AIRPLANE_MODE_ON,
                 on ? 1 : 0);
         Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
         intent.putExtra("state", on);
-        mContext.sendBroadcast(intent);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
         if (!mHasTelephony) {
             mAirplaneState = on ? ToggleAction.State.On : ToggleAction.State.Off;
         }
     }
 
-    private IWindowManager getWindowManager() {
-        if (mIWindowManager == null) {
-            IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE);
-            mIWindowManager = IWindowManager.Stub.asInterface(b);
+    private static final class GlobalActionsDialog extends Dialog implements DialogInterface {
+        private final Context mContext;
+        private final int mWindowTouchSlop;
+        private final AlertController mAlert;
+
+        private EnableAccessibilityController mEnableAccessibilityController;
+
+        private boolean mIntercepted;
+        private boolean mCancelOnUp;
+
+        public GlobalActionsDialog(Context context, AlertParams params) {
+            super(context, getDialogTheme(context));
+            mContext = context;
+            mAlert = new AlertController(mContext, this, getWindow());
+            mWindowTouchSlop = ViewConfiguration.get(context).getScaledWindowTouchSlop();
+            params.apply(mAlert);
         }
-        return mIWindowManager;
+
+        private static int getDialogTheme(Context context) {
+            TypedValue outValue = new TypedValue();
+            context.getTheme().resolveAttribute(com.android.internal.R.attr.alertDialogTheme,
+                    outValue, true);
+            return outValue.resourceId;
+        }
+
+        @Override
+        protected void onStart() {
+            // If global accessibility gesture can be performed, we will take care
+            // of dismissing the dialog on touch outside. This is because the dialog
+            // is dismissed on the first down while the global gesture is a long press
+            // with two fingers anywhere on the screen.
+            if (EnableAccessibilityController.canEnableAccessibilityViaGesture(mContext)) {
+                mEnableAccessibilityController = new EnableAccessibilityController(mContext);
+                super.setCanceledOnTouchOutside(false);
+            } else {
+                mEnableAccessibilityController = null;
+                super.setCanceledOnTouchOutside(true);
+            }
+            super.onStart();
+        }
+
+        @Override
+        protected void onStop() {
+            if (mEnableAccessibilityController != null) {
+                mEnableAccessibilityController.onDestroy();
+            }
+            super.onStop();
+        }
+
+        @Override
+        public boolean dispatchTouchEvent(MotionEvent event) {
+            if (mEnableAccessibilityController != null) {
+                final int action = event.getActionMasked();
+                if (action == MotionEvent.ACTION_DOWN) {
+                    View decor = getWindow().getDecorView();
+                    final int eventX = (int) event.getX();
+                    final int eventY = (int) event.getY();
+                    if (eventX < -mWindowTouchSlop
+                            || eventY < -mWindowTouchSlop
+                            || eventX >= decor.getWidth() + mWindowTouchSlop
+                            || eventY >= decor.getHeight() + mWindowTouchSlop) {
+                        mCancelOnUp = true;
+                    }
+                }
+                try {
+                    if (!mIntercepted) {
+                        mIntercepted = mEnableAccessibilityController.onInterceptTouchEvent(event);
+                        if (mIntercepted) {
+                            final long now = SystemClock.uptimeMillis();
+                            event = MotionEvent.obtain(now, now,
+                                    MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
+                            event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+                            mCancelOnUp = true;
+                        }
+                    } else {
+                        return mEnableAccessibilityController.onTouchEvent(event);
+                    }
+                } finally {
+                    if (action == MotionEvent.ACTION_UP) {
+                        if (mCancelOnUp) {
+                            cancel();
+                        }
+                        mCancelOnUp = false;
+                        mIntercepted = false;
+                    }
+                }
+            }
+            return super.dispatchTouchEvent(event);
+        }
+
+        public ListView getListView() {
+            return mAlert.getListView();
+        }
+
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            mAlert.installContent();
+        }
+
+        @Override
+        public boolean onKeyDown(int keyCode, KeyEvent event) {
+            if (mAlert.onKeyDown(keyCode, event)) {
+                return true;
+            }
+            return super.onKeyDown(keyCode, event);
+        }
+
+        @Override
+        public boolean onKeyUp(int keyCode, KeyEvent event) {
+            if (mAlert.onKeyUp(keyCode, event)) {
+                return true;
+            }
+            return super.onKeyUp(keyCode, event);
+        }
     }
 }
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardScreen.java b/policy/src/com/android/internal/policy/impl/KeyguardScreen.java
deleted file mode 100644
index bbb6875..0000000
--- a/policy/src/com/android/internal/policy/impl/KeyguardScreen.java
+++ /dev/null
@@ -1,45 +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.
- */
-
-package com.android.internal.policy.impl;
-
-/**
- * Common interface of each {@link android.view.View} that is a screen of
- * {@link LockPatternKeyguardView}.
- */
-public interface KeyguardScreen {
-
-    /**
-     * Return true if your view needs input, so should allow the soft
-     * keyboard to be displayed.
-     */
-    boolean needsInput();
-    
-    /**
-     * This screen is no longer in front of the user.
-     */
-    void onPause();
-
-    /**
-     * This screen is going to be in front of the user.
-     */
-    void onResume();
-
-    /**
-     * This view is going away; a hook to do cleanup.
-     */
-    void cleanUp();
-}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardScreenCallback.java b/policy/src/com/android/internal/policy/impl/KeyguardScreenCallback.java
deleted file mode 100644
index a843603..0000000
--- a/policy/src/com/android/internal/policy/impl/KeyguardScreenCallback.java
+++ /dev/null
@@ -1,82 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import android.content.res.Configuration;
-
-/**
- * Within a keyguard, there may be several screens that need a callback
- * to the host keyguard view.
- */
-public interface KeyguardScreenCallback extends KeyguardViewCallback {
-
-    /**
-     * Transition to the lock screen.
-     */
-    void goToLockScreen();
-
-    /**
-     * Transition to the unlock screen.
-     */
-    void goToUnlockScreen();
-
-    /**
-     * The user reported that they forgot their pattern (or not, when they want to back out of the
-     * forgot pattern screen).
-     *
-     * @param isForgotten True if the user hit the forgot pattern, false if they want to back out
-     *        of the account screen.
-     */
-    void forgotPattern(boolean isForgotten);
-
-    /**
-     * @return Whether the keyguard requires some sort of PIN.
-     */
-    boolean isSecure();
-
-    /**
-     * @return Whether we are in a mode where we only want to verify the
-     *   user can get past the keyguard.
-     */
-    boolean isVerifyUnlockOnly();
-
-    /**
-     * Stay on me, but recreate me (so I can use a different layout).
-     */
-    void recreateMe(Configuration config);
-
-    /**
-     * Take action to send an emergency call.
-     */
-    void takeEmergencyCallAction();
-
-    /**
-     * Report that the user had a failed attempt to unlock with password or pattern.
-     */
-    void reportFailedUnlockAttempt();
-
-    /**
-     * Report that the user successfully entered their password or pattern.
-     */
-    void reportSuccessfulUnlockAttempt();
-
-    /**
-     * Report whether we there's another way to unlock the device.
-     * @return true
-     */
-    boolean doesFallbackUnlockScreenExist();
-}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
deleted file mode 100644
index c1fd515..0000000
--- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
+++ /dev/null
@@ -1,696 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import com.android.internal.R;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.widget.DigitalClock;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.TransportControlView;
-import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl;
-import com.android.internal.policy.impl.KeyguardUpdateMonitor.SimStateCallback;
-
-import java.util.ArrayList;
-import java.util.Date;
-
-import libcore.util.MutableInt;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.text.format.DateFormat;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.TextView;
-
-/***
- * Manages a number of views inside of LockScreen layouts. See below for a list of widgets
- *
- */
-class KeyguardStatusViewManager implements OnClickListener {
-    private static final boolean DEBUG = false;
-    private static final String TAG = "KeyguardStatusView";
-
-    public static final int LOCK_ICON = 0; // R.drawable.ic_lock_idle_lock;
-    public static final int ALARM_ICON = R.drawable.ic_lock_idle_alarm;
-    public static final int CHARGING_ICON = 0; //R.drawable.ic_lock_idle_charging;
-    public static final int BATTERY_LOW_ICON = 0; //R.drawable.ic_lock_idle_low_battery;
-    private static final long INSTRUCTION_RESET_DELAY = 2000; // time until instruction text resets
-
-    private static final int INSTRUCTION_TEXT = 10;
-    private static final int CARRIER_TEXT = 11;
-    private static final int CARRIER_HELP_TEXT = 12;
-    private static final int HELP_MESSAGE_TEXT = 13;
-    private static final int OWNER_INFO = 14;
-    private static final int BATTERY_INFO = 15;
-
-    private StatusMode mStatus;
-    private String mDateFormatString;
-    private TransientTextManager mTransientTextManager;
-
-    // Views that this class controls.
-    // NOTE: These may be null in some LockScreen screens and should protect from NPE
-    private TextView mCarrierView;
-    private TextView mDateView;
-    private TextView mStatus1View;
-    private TextView mOwnerInfoView;
-    private TextView mAlarmStatusView;
-    private TransportControlView mTransportView;
-
-    // Top-level container view for above views
-    private View mContainer;
-
-    // are we showing battery information?
-    private boolean mShowingBatteryInfo = false;
-
-    // last known plugged in state
-    private boolean mPluggedIn = false;
-
-    // last known battery level
-    private int mBatteryLevel = 100;
-
-    // last known SIM state
-    protected IccCardConstants.State mSimState;
-
-    private LockPatternUtils mLockPatternUtils;
-    private KeyguardUpdateMonitor mUpdateMonitor;
-    private Button mEmergencyCallButton;
-    private boolean mEmergencyButtonEnabledBecauseSimLocked;
-
-    // Shadowed text values
-    private CharSequence mCarrierText;
-    private CharSequence mCarrierHelpText;
-    private String mHelpMessageText;
-    private String mInstructionText;
-    private CharSequence mOwnerInfoText;
-    private boolean mShowingStatus;
-    private KeyguardScreenCallback mCallback;
-    private final boolean mEmergencyCallButtonEnabledInScreen;
-    private CharSequence mPlmn;
-    private CharSequence mSpn;
-    protected int mPhoneState;
-    private DigitalClock mDigitalClock;
-
-    private class TransientTextManager {
-        private TextView mTextView;
-        private class Data {
-            final int icon;
-            final CharSequence text;
-            Data(CharSequence t, int i) {
-                text = t;
-                icon = i;
-            }
-        };
-        private ArrayList<Data> mMessages = new ArrayList<Data>(5);
-
-        TransientTextManager(TextView textView) {
-            mTextView = textView;
-        }
-
-        /* Show given message with icon for up to duration ms. Newer messages override older ones.
-         * The most recent message with the longest duration is shown as messages expire until
-         * nothing is left, in which case the text/icon is defined by a call to
-         * getAltTextMessage() */
-        void post(final CharSequence message, final int icon, long duration) {
-            if (mTextView == null) {
-                return;
-            }
-            mTextView.setText(message);
-            mTextView.setCompoundDrawablesWithIntrinsicBounds(icon, 0, 0, 0);
-            final Data data = new Data(message, icon);
-            mContainer.postDelayed(new Runnable() {
-                public void run() {
-                    mMessages.remove(data);
-                    int last = mMessages.size() - 1;
-                    final CharSequence lastText;
-                    final int lastIcon;
-                    if (last > 0) {
-                        final Data oldData = mMessages.get(last);
-                        lastText = oldData.text;
-                        lastIcon = oldData.icon;
-                    } else {
-                        final MutableInt tmpIcon = new MutableInt(0);
-                        lastText = getAltTextMessage(tmpIcon);
-                        lastIcon = tmpIcon.value;
-                    }
-                    mTextView.setText(lastText);
-                    mTextView.setCompoundDrawablesWithIntrinsicBounds(lastIcon, 0, 0, 0);
-                }
-            }, duration);
-        }
-    };
-
-    /**
-     *
-     * @param view the containing view of all widgets
-     * @param updateMonitor the update monitor to use
-     * @param lockPatternUtils lock pattern util object
-     * @param callback used to invoke emergency dialer
-     * @param emergencyButtonEnabledInScreen whether emergency button is enabled by default
-     */
-    public KeyguardStatusViewManager(View view, KeyguardUpdateMonitor updateMonitor,
-                LockPatternUtils lockPatternUtils, KeyguardScreenCallback callback,
-                boolean emergencyButtonEnabledInScreen) {
-        if (DEBUG) Log.v(TAG, "KeyguardStatusViewManager()");
-        mContainer = view;
-        mDateFormatString = getContext().getString(R.string.abbrev_wday_month_day_no_year);
-        mLockPatternUtils = lockPatternUtils;
-        mUpdateMonitor = updateMonitor;
-        mCallback = callback;
-
-        mCarrierView = (TextView) findViewById(R.id.carrier);
-        mDateView = (TextView) findViewById(R.id.date);
-        mStatus1View = (TextView) findViewById(R.id.status1);
-        mAlarmStatusView = (TextView) findViewById(R.id.alarm_status);
-        mOwnerInfoView = (TextView) findViewById(R.id.propertyOf);
-        mTransportView = (TransportControlView) findViewById(R.id.transport);
-        mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
-        mEmergencyCallButtonEnabledInScreen = emergencyButtonEnabledInScreen;
-        mDigitalClock = (DigitalClock) findViewById(R.id.time);
-
-        // Hide transport control view until we know we need to show it.
-        if (mTransportView != null) {
-            mTransportView.setVisibility(View.GONE);
-        }
-
-        if (mEmergencyCallButton != null) {
-            mEmergencyCallButton.setText(R.string.lockscreen_emergency_call);
-            mEmergencyCallButton.setOnClickListener(this);
-            mEmergencyCallButton.setFocusable(false); // touch only!
-        }
-
-        mTransientTextManager = new TransientTextManager(mCarrierView);
-
-        mUpdateMonitor.registerInfoCallback(mInfoCallback);
-        mUpdateMonitor.registerSimStateCallback(mSimStateCallback);
-
-        resetStatusInfo();
-        refreshDate();
-        updateOwnerInfo();
-
-        // Required to get Marquee to work.
-        final View scrollableViews[] = { mCarrierView, mDateView, mStatus1View, mOwnerInfoView,
-                mAlarmStatusView };
-        for (View v : scrollableViews) {
-            if (v != null) {
-                v.setSelected(true);
-            }
-        }
-    }
-
-    private boolean inWidgetMode() {
-        return mTransportView != null && mTransportView.getVisibility() == View.VISIBLE;
-    }
-
-    void setInstructionText(String string) {
-        mInstructionText = string;
-        update(INSTRUCTION_TEXT, string);
-    }
-
-    void setCarrierText(CharSequence string) {
-        mCarrierText = string;
-        update(CARRIER_TEXT, string);
-    }
-
-    void setOwnerInfo(CharSequence string) {
-        mOwnerInfoText = string;
-        update(OWNER_INFO, string);
-    }
-
-    /**
-     * Sets the carrier help text message, if view is present. Carrier help text messages are
-     * typically for help dealing with SIMS and connectivity.
-     *
-     * @param resId resource id of the message
-     */
-    public void setCarrierHelpText(int resId) {
-        mCarrierHelpText = getText(resId);
-        update(CARRIER_HELP_TEXT, mCarrierHelpText);
-    }
-
-    private CharSequence getText(int resId) {
-        return resId == 0 ? null : getContext().getText(resId);
-    }
-
-    /**
-     * Unlock help message.  This is typically for help with unlock widgets, e.g. "wrong password"
-     * or "try again."
-     *
-     * @param textResId
-     * @param lockIcon
-     */
-    public void setHelpMessage(int textResId, int lockIcon) {
-        final CharSequence tmp = getText(textResId);
-        mHelpMessageText = tmp == null ? null : tmp.toString();
-        update(HELP_MESSAGE_TEXT, mHelpMessageText);
-    }
-
-    private void update(int what, CharSequence string) {
-        if (inWidgetMode()) {
-            if (DEBUG) Log.v(TAG, "inWidgetMode() is true");
-            // Use Transient text for messages shown while widget is shown.
-            switch (what) {
-                case INSTRUCTION_TEXT:
-                case CARRIER_HELP_TEXT:
-                case HELP_MESSAGE_TEXT:
-                case BATTERY_INFO:
-                    mTransientTextManager.post(string, 0, INSTRUCTION_RESET_DELAY);
-                    break;
-
-                case OWNER_INFO:
-                case CARRIER_TEXT:
-                default:
-                    if (DEBUG) Log.w(TAG, "Not showing message id " + what + ", str=" + string);
-            }
-        } else {
-            updateStatusLines(mShowingStatus);
-        }
-    }
-
-    public void onPause() {
-        if (DEBUG) Log.v(TAG, "onPause()");
-        mUpdateMonitor.removeCallback(mInfoCallback);
-        mUpdateMonitor.removeCallback(mSimStateCallback);
-    }
-
-    /** {@inheritDoc} */
-    public void onResume() {
-        if (DEBUG) Log.v(TAG, "onResume()");
-
-        // First update the clock, if present.
-        if (mDigitalClock != null) {
-            mDigitalClock.updateTime();
-        }
-
-        mUpdateMonitor.registerInfoCallback(mInfoCallback);
-        mUpdateMonitor.registerSimStateCallback(mSimStateCallback);
-        resetStatusInfo();
-        // Issue the biometric unlock failure message in a centralized place
-        // TODO: we either need to make the Face Unlock multiple failures string a more general
-        // 'biometric unlock' or have each biometric unlock handle this on their own.
-        if (mUpdateMonitor.getMaxBiometricUnlockAttemptsReached()) {
-            setInstructionText(getContext().getString(R.string.faceunlock_multiple_failures));
-        }
-    }
-
-    void resetStatusInfo() {
-        mInstructionText = null;
-        mShowingBatteryInfo = mUpdateMonitor.shouldShowBatteryInfo();
-        mPluggedIn = mUpdateMonitor.isDevicePluggedIn();
-        mBatteryLevel = mUpdateMonitor.getBatteryLevel();
-        updateStatusLines(true);
-    }
-
-    /**
-     * Update the status lines based on these rules:
-     * AlarmStatus: Alarm state always gets it's own line.
-     * Status1 is shared between help, battery status and generic unlock instructions,
-     * prioritized in that order.
-     * @param showStatusLines status lines are shown if true
-     */
-    void updateStatusLines(boolean showStatusLines) {
-        if (DEBUG) Log.v(TAG, "updateStatusLines(" + showStatusLines + ")");
-        mShowingStatus = showStatusLines;
-        updateAlarmInfo();
-        updateOwnerInfo();
-        updateStatus1();
-        updateCarrierText();
-    }
-
-    private void updateAlarmInfo() {
-        if (mAlarmStatusView != null) {
-            String nextAlarm = mLockPatternUtils.getNextAlarm();
-            boolean showAlarm = mShowingStatus && !TextUtils.isEmpty(nextAlarm);
-            mAlarmStatusView.setText(nextAlarm);
-            mAlarmStatusView.setCompoundDrawablesWithIntrinsicBounds(ALARM_ICON, 0, 0, 0);
-            mAlarmStatusView.setVisibility(showAlarm ? View.VISIBLE : View.GONE);
-        }
-    }
-
-    private void updateOwnerInfo() {
-        final ContentResolver res = getContext().getContentResolver();
-        final boolean ownerInfoEnabled = Settings.Secure.getInt(res,
-                Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 1) != 0;
-        mOwnerInfoText = ownerInfoEnabled ?
-                Settings.Secure.getString(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO) : null;
-        if (mOwnerInfoView != null) {
-            mOwnerInfoView.setText(mOwnerInfoText);
-            mOwnerInfoView.setVisibility(TextUtils.isEmpty(mOwnerInfoText) ? View.GONE:View.VISIBLE);
-        }
-    }
-
-    private void updateStatus1() {
-        if (mStatus1View != null) {
-            MutableInt icon = new MutableInt(0);
-            CharSequence string = getPriorityTextMessage(icon);
-            mStatus1View.setText(string);
-            mStatus1View.setCompoundDrawablesWithIntrinsicBounds(icon.value, 0, 0, 0);
-            mStatus1View.setVisibility(mShowingStatus ? View.VISIBLE : View.INVISIBLE);
-        }
-    }
-
-    private void updateCarrierText() {
-        if (!inWidgetMode() && mCarrierView != null) {
-            mCarrierView.setText(mCarrierText);
-        }
-    }
-
-    private CharSequence getAltTextMessage(MutableInt icon) {
-        // If we have replaced the status area with a single widget, then this code
-        // prioritizes what to show in that space when all transient messages are gone.
-        CharSequence string = null;
-        if (mShowingBatteryInfo) {
-            // Battery status
-            if (mPluggedIn) {
-                // Charging or charged
-                if (mUpdateMonitor.isDeviceCharged()) {
-                    string = getContext().getString(R.string.lockscreen_charged);
-                } else {
-                    string = getContext().getString(R.string.lockscreen_plugged_in, mBatteryLevel);
-                }
-                icon.value = CHARGING_ICON;
-            } else if (mBatteryLevel < KeyguardUpdateMonitor.LOW_BATTERY_THRESHOLD) {
-                // Battery is low
-                string = getContext().getString(R.string.lockscreen_low_battery);
-                icon.value = BATTERY_LOW_ICON;
-            }
-        } else {
-            string = mCarrierText;
-        }
-        return string;
-    }
-
-    private CharSequence getPriorityTextMessage(MutableInt icon) {
-        CharSequence string = null;
-        if (!TextUtils.isEmpty(mInstructionText)) {
-            // Instructions only
-            string = mInstructionText;
-            icon.value = LOCK_ICON;
-        } else if (mShowingBatteryInfo) {
-            // Battery status
-            if (mPluggedIn) {
-                // Charging or charged
-                if (mUpdateMonitor.isDeviceCharged()) {
-                    string = getContext().getString(R.string.lockscreen_charged);
-                } else {
-                    string = getContext().getString(R.string.lockscreen_plugged_in, mBatteryLevel);
-                }
-                icon.value = CHARGING_ICON;
-            } else if (mBatteryLevel < KeyguardUpdateMonitor.LOW_BATTERY_THRESHOLD) {
-                // Battery is low
-                string = getContext().getString(R.string.lockscreen_low_battery);
-                icon.value = BATTERY_LOW_ICON;
-            }
-        } else if (!inWidgetMode() && mOwnerInfoView == null && mOwnerInfoText != null) {
-            // OwnerInfo shows in status if we don't have a dedicated widget
-            string = mOwnerInfoText;
-        }
-        return string;
-    }
-
-    void refreshDate() {
-        if (mDateView != null) {
-            mDateView.setText(DateFormat.format(mDateFormatString, new Date()));
-        }
-    }
-
-    /**
-     * Determine the current status of the lock screen given the sim state and other stuff.
-     */
-    public StatusMode getStatusForIccState(IccCardConstants.State simState) {
-        // Since reading the SIM may take a while, we assume it is present until told otherwise.
-        if (simState == null) {
-            return StatusMode.Normal;
-        }
-
-        final boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned()
-                && (simState == IccCardConstants.State.ABSENT ||
-                        simState == IccCardConstants.State.PERM_DISABLED));
-
-        // Assume we're NETWORK_LOCKED if not provisioned
-        simState = missingAndNotProvisioned ? IccCardConstants.State.NETWORK_LOCKED : simState;
-        switch (simState) {
-            case ABSENT:
-                return StatusMode.SimMissing;
-            case NETWORK_LOCKED:
-                return StatusMode.SimMissingLocked;
-            case NOT_READY:
-                return StatusMode.SimMissing;
-            case PIN_REQUIRED:
-                return StatusMode.SimLocked;
-            case PUK_REQUIRED:
-                return StatusMode.SimPukLocked;
-            case READY:
-                return StatusMode.Normal;
-            case PERM_DISABLED:
-                return StatusMode.SimPermDisabled;
-            case UNKNOWN:
-                return StatusMode.SimMissing;
-        }
-        return StatusMode.SimMissing;
-    }
-
-    private Context getContext() {
-        return mContainer.getContext();
-    }
-
-    /**
-     * Update carrier text, carrier help and emergency button to match the current status based
-     * on SIM state.
-     *
-     * @param simState
-     */
-    private void updateCarrierStateWithSimStatus(IccCardConstants.State simState) {
-        if (DEBUG) Log.d(TAG, "updateCarrierTextWithSimStatus(), simState = " + simState);
-
-        CharSequence carrierText = null;
-        int carrierHelpTextId = 0;
-        mEmergencyButtonEnabledBecauseSimLocked = false;
-        mStatus = getStatusForIccState(simState);
-        mSimState = simState;
-        switch (mStatus) {
-            case Normal:
-                carrierText = makeCarierString(mPlmn, mSpn);
-                break;
-
-            case NetworkLocked:
-                carrierText = makeCarrierStringOnEmergencyCapable(
-                        getContext().getText(R.string.lockscreen_network_locked_message),
-                        mPlmn);
-                carrierHelpTextId = R.string.lockscreen_instructions_when_pattern_disabled;
-                break;
-
-            case SimMissing:
-                // Shows "No SIM card | Emergency calls only" on devices that are voice-capable.
-                // This depends on mPlmn containing the text "Emergency calls only" when the radio
-                // has some connectivity. Otherwise, it should be null or empty and just show
-                // "No SIM card"
-                carrierText =  makeCarrierStringOnEmergencyCapable(
-                        getContext().getText(R.string.lockscreen_missing_sim_message_short),
-                        mPlmn);
-                carrierHelpTextId = R.string.lockscreen_missing_sim_instructions_long;
-                break;
-
-            case SimPermDisabled:
-                carrierText = getContext().getText(
-                        R.string.lockscreen_permanent_disabled_sim_message_short);
-                carrierHelpTextId = R.string.lockscreen_permanent_disabled_sim_instructions;
-                mEmergencyButtonEnabledBecauseSimLocked = true;
-                break;
-
-            case SimMissingLocked:
-                carrierText =  makeCarrierStringOnEmergencyCapable(
-                        getContext().getText(R.string.lockscreen_missing_sim_message_short),
-                        mPlmn);
-                carrierHelpTextId = R.string.lockscreen_missing_sim_instructions;
-                mEmergencyButtonEnabledBecauseSimLocked = true;
-                break;
-
-            case SimLocked:
-                carrierText = makeCarrierStringOnEmergencyCapable(
-                        getContext().getText(R.string.lockscreen_sim_locked_message),
-                        mPlmn);
-                mEmergencyButtonEnabledBecauseSimLocked = true;
-                break;
-
-            case SimPukLocked:
-                carrierText = makeCarrierStringOnEmergencyCapable(
-                        getContext().getText(R.string.lockscreen_sim_puk_locked_message),
-                        mPlmn);
-                if (!mLockPatternUtils.isPukUnlockScreenEnable()) {
-                    // This means we're showing the PUK unlock screen
-                    mEmergencyButtonEnabledBecauseSimLocked = true;
-                }
-                break;
-        }
-
-        setCarrierText(carrierText);
-        setCarrierHelpText(carrierHelpTextId);
-        updateEmergencyCallButtonState(mPhoneState);
-    }
-
-
-    /*
-     * Add emergencyCallMessage to carrier string only if phone supports emergency calls.
-     */
-    private CharSequence makeCarrierStringOnEmergencyCapable(
-            CharSequence simMessage, CharSequence emergencyCallMessage) {
-        if (mLockPatternUtils.isEmergencyCallCapable()) {
-            return makeCarierString(simMessage, emergencyCallMessage);
-        }
-        return simMessage;
-    }
-
-    private View findViewById(int id) {
-        return mContainer.findViewById(id);
-    }
-
-    /**
-     * The status of this lock screen. Primarily used for widgets on LockScreen.
-     */
-    enum StatusMode {
-        /**
-         * Normal case (sim card present, it's not locked)
-         */
-        Normal(true),
-
-        /**
-         * The sim card is 'network locked'.
-         */
-        NetworkLocked(true),
-
-        /**
-         * The sim card is missing.
-         */
-        SimMissing(false),
-
-        /**
-         * The sim card is missing, and this is the device isn't provisioned, so we don't let
-         * them get past the screen.
-         */
-        SimMissingLocked(false),
-
-        /**
-         * The sim card is PUK locked, meaning they've entered the wrong sim unlock code too many
-         * times.
-         */
-        SimPukLocked(false),
-
-        /**
-         * The sim card is locked.
-         */
-        SimLocked(true),
-
-        /**
-         * The sim card is permanently disabled due to puk unlock failure
-         */
-        SimPermDisabled(false);
-
-        private final boolean mShowStatusLines;
-
-        StatusMode(boolean mShowStatusLines) {
-            this.mShowStatusLines = mShowStatusLines;
-        }
-
-        /**
-         * @return Whether the status lines (battery level and / or next alarm) are shown while
-         *         in this state.  Mostly dictated by whether this is room for them.
-         */
-        public boolean shouldShowStatusLines() {
-            return mShowStatusLines;
-        }
-    }
-
-    private void updateEmergencyCallButtonState(int phoneState) {
-        if (mEmergencyCallButton != null) {
-            boolean enabledBecauseSimLocked =
-                    mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked()
-                    && mEmergencyButtonEnabledBecauseSimLocked;
-            boolean shown = mEmergencyCallButtonEnabledInScreen || enabledBecauseSimLocked;
-            mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton,
-                    phoneState, shown);
-        }
-    }
-
-    private InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() {
-
-        @Override
-        public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
-                int batteryLevel) {
-            mShowingBatteryInfo = showBatteryInfo;
-            mPluggedIn = pluggedIn;
-            mBatteryLevel = batteryLevel;
-            final MutableInt tmpIcon = new MutableInt(0);
-            update(BATTERY_INFO, getAltTextMessage(tmpIcon));
-        }
-
-        @Override
-        public void onTimeChanged() {
-            refreshDate();
-        }
-
-        @Override
-        public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
-            mPlmn = plmn;
-            mSpn = spn;
-            updateCarrierStateWithSimStatus(mSimState);
-        }
-
-        @Override
-        public void onPhoneStateChanged(int phoneState) {
-            mPhoneState = phoneState;
-            updateEmergencyCallButtonState(phoneState);
-        }
-
-    };
-
-    private SimStateCallback mSimStateCallback = new SimStateCallback() {
-
-        public void onSimStateChanged(IccCardConstants.State simState) {
-            updateCarrierStateWithSimStatus(simState);
-        }
-    };
-
-    public void onClick(View v) {
-        if (v == mEmergencyCallButton) {
-            mCallback.takeEmergencyCallAction();
-        }
-    }
-
-    /**
-     * Performs concentenation of PLMN/SPN
-     * @param plmn
-     * @param spn
-     * @return
-     */
-    private static CharSequence makeCarierString(CharSequence plmn, CharSequence spn) {
-        final boolean plmnValid = !TextUtils.isEmpty(plmn);
-        final boolean spnValid = !TextUtils.isEmpty(spn);
-        if (plmnValid && spnValid) {
-            return plmn + "|" + spn;
-        } else if (plmnValid) {
-            return plmn;
-        } else if (spnValid) {
-            return spn;
-        } else {
-            return "";
-        }
-    }
-}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
deleted file mode 100644
index 5cd0349..0000000
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ /dev/null
@@ -1,725 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.database.ContentObserver;
-import static android.os.BatteryManager.BATTERY_STATUS_FULL;
-import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
-import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
-import static android.os.BatteryManager.EXTRA_STATUS;
-import static android.os.BatteryManager.EXTRA_PLUGGED;
-import static android.os.BatteryManager.EXTRA_LEVEL;
-import static android.os.BatteryManager.EXTRA_HEALTH;
-import android.media.AudioManager;
-import android.os.BatteryManager;
-import android.os.Handler;
-import android.os.Message;
-import android.provider.Settings;
-
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.TelephonyIntents;
-
-import android.telephony.TelephonyManager;
-import android.util.Log;
-import com.android.internal.R;
-import com.google.android.collect.Lists;
-
-import java.util.ArrayList;
-
-/**
- * Watches for updates that may be interesting to the keyguard, and provides
- * the up to date information as well as a registration for callbacks that care
- * to be updated.
- *
- * Note: under time crunch, this has been extended to include some stuff that
- * doesn't really belong here.  see {@link #handleBatteryUpdate} where it shutdowns
- * the device, and {@link #getFailedAttempts()}, {@link #reportFailedAttempt()}
- * and {@link #clearFailedAttempts()}.  Maybe we should rename this 'KeyguardContext'...
- */
-public class KeyguardUpdateMonitor {
-
-    static private final String TAG = "KeyguardUpdateMonitor";
-    static private final boolean DEBUG = false;
-
-    /* package */ static final int LOW_BATTERY_THRESHOLD = 20;
-
-    private final Context mContext;
-
-    private IccCardConstants.State mSimState = IccCardConstants.State.READY;
-
-    private boolean mDeviceProvisioned;
-
-    private BatteryStatus mBatteryStatus;
-
-    private CharSequence mTelephonyPlmn;
-    private CharSequence mTelephonySpn;
-
-    private int mFailedAttempts = 0;
-    private int mFailedBiometricUnlockAttempts = 0;
-    private static final int FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 3;
-
-    private boolean mClockVisible;
-
-    private Handler mHandler;
-
-    private ArrayList<InfoCallback> mInfoCallbacks = Lists.newArrayList();
-    private ArrayList<SimStateCallback> mSimStateCallbacks = Lists.newArrayList();
-    private ContentObserver mContentObserver;
-    private int mRingMode;
-    private int mPhoneState;
-
-    // messages for the handler
-    private static final int MSG_TIME_UPDATE = 301;
-    private static final int MSG_BATTERY_UPDATE = 302;
-    private static final int MSG_CARRIER_INFO_UPDATE = 303;
-    private static final int MSG_SIM_STATE_CHANGE = 304;
-    private static final int MSG_RINGER_MODE_CHANGED = 305;
-    private static final int MSG_PHONE_STATE_CHANGED = 306;
-    private static final int MSG_CLOCK_VISIBILITY_CHANGED = 307;
-    private static final int MSG_DEVICE_PROVISIONED = 308;
-    protected static final int MSG_DPM_STATE_CHANGED = 309;
-    protected static final int MSG_USER_CHANGED = 310;
-
-    protected static final boolean DEBUG_SIM_STATES = DEBUG || false;
-
-    /**
-     * When we receive a
-     * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
-     * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange},
-     * we need a single object to pass to the handler.  This class helps decode
-     * the intent and provide a {@link SimCard.State} result.
-     */
-    private static class SimArgs {
-        public final IccCardConstants.State simState;
-
-        SimArgs(IccCardConstants.State state) {
-            simState = state;
-        }
-
-        static SimArgs fromIntent(Intent intent) {
-            IccCardConstants.State state;
-            if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
-                throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
-            }
-            String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
-            if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
-                final String absentReason = intent
-                    .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
-
-                if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
-                        absentReason)) {
-                    state = IccCardConstants.State.PERM_DISABLED;
-                } else {
-                    state = IccCardConstants.State.ABSENT;
-                }
-            } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
-                state = IccCardConstants.State.READY;
-            } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
-                final String lockedReason = intent
-                        .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
-                if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
-                    state = IccCardConstants.State.PIN_REQUIRED;
-                } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
-                    state = IccCardConstants.State.PUK_REQUIRED;
-                } else {
-                    state = IccCardConstants.State.UNKNOWN;
-                }
-            } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
-                state = IccCardConstants.State.NETWORK_LOCKED;
-            } else {
-                state = IccCardConstants.State.UNKNOWN;
-            }
-            return new SimArgs(state);
-        }
-
-        public String toString() {
-            return simState.toString();
-        }
-    }
-
-    private static class BatteryStatus {
-        public final int status;
-        public final int level;
-        public final int plugged;
-        public final int health;
-        public BatteryStatus(int status, int level, int plugged, int health) {
-            this.status = status;
-            this.level = level;
-            this.plugged = plugged;
-            this.health = health;
-        }
-
-    }
-
-    public KeyguardUpdateMonitor(Context context) {
-        mContext = context;
-
-        mHandler = new Handler() {
-            @Override
-            public void handleMessage(Message msg) {
-                switch (msg.what) {
-                    case MSG_TIME_UPDATE:
-                        handleTimeUpdate();
-                        break;
-                    case MSG_BATTERY_UPDATE:
-                        handleBatteryUpdate((BatteryStatus) msg.obj);
-                        break;
-                    case MSG_CARRIER_INFO_UPDATE:
-                        handleCarrierInfoUpdate();
-                        break;
-                    case MSG_SIM_STATE_CHANGE:
-                        handleSimStateChange((SimArgs) msg.obj);
-                        break;
-                    case MSG_RINGER_MODE_CHANGED:
-                        handleRingerModeChange(msg.arg1);
-                        break;
-                    case MSG_PHONE_STATE_CHANGED:
-                        handlePhoneStateChanged((String)msg.obj);
-                        break;
-                    case MSG_CLOCK_VISIBILITY_CHANGED:
-                        handleClockVisibilityChanged();
-                        break;
-                    case MSG_DEVICE_PROVISIONED:
-                        handleDeviceProvisioned();
-                        break;
-                    case MSG_DPM_STATE_CHANGED:
-                        handleDevicePolicyManagerStateChanged();
-                        break;
-                    case MSG_USER_CHANGED:
-                        handleUserChanged(msg.arg1);
-                        break;
-                }
-            }
-        };
-
-        mDeviceProvisioned = Settings.Secure.getInt(
-                mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
-
-        // Since device can't be un-provisioned, we only need to register a content observer
-        // to update mDeviceProvisioned when we are...
-        if (!mDeviceProvisioned) {
-            mContentObserver = new ContentObserver(mHandler) {
-                @Override
-                public void onChange(boolean selfChange) {
-                    super.onChange(selfChange);
-                    mDeviceProvisioned = Settings.Secure.getInt(mContext.getContentResolver(),
-                        Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
-                    if (mDeviceProvisioned) {
-                        mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
-                    }
-                    if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
-                }
-            };
-
-            mContext.getContentResolver().registerContentObserver(
-                    Settings.Secure.getUriFor(Settings.Secure.DEVICE_PROVISIONED),
-                    false, mContentObserver);
-
-            // prevent a race condition between where we check the flag and where we register the
-            // observer by grabbing the value once again...
-            boolean provisioned = Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
-            if (provisioned != mDeviceProvisioned) {
-                mDeviceProvisioned = provisioned;
-                if (mDeviceProvisioned) {
-                    mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
-                }
-            }
-        }
-
-        // take a guess to start
-        mSimState = IccCardConstants.State.READY;
-        mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0);
-
-        mTelephonyPlmn = getDefaultPlmn();
-
-        // setup receiver
-        final IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_TIME_TICK);
-        filter.addAction(Intent.ACTION_TIME_CHANGED);
-        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
-        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
-        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
-        filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
-        filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
-        filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
-        filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
-        filter.addAction(Intent.ACTION_USER_SWITCHED);
-        filter.addAction(Intent.ACTION_USER_REMOVED);
-        context.registerReceiver(new BroadcastReceiver() {
-
-            public void onReceive(Context context, Intent intent) {
-                final String action = intent.getAction();
-                if (DEBUG) Log.d(TAG, "received broadcast " + action);
-
-                if (Intent.ACTION_TIME_TICK.equals(action)
-                        || Intent.ACTION_TIME_CHANGED.equals(action)
-                        || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
-                    mHandler.sendMessage(mHandler.obtainMessage(MSG_TIME_UPDATE));
-                } else if (TelephonyIntents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
-                    mTelephonyPlmn = getTelephonyPlmnFrom(intent);
-                    mTelephonySpn = getTelephonySpnFrom(intent);
-                    mHandler.sendMessage(mHandler.obtainMessage(MSG_CARRIER_INFO_UPDATE));
-                } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
-                    final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
-                    final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
-                    final int level = intent.getIntExtra(EXTRA_LEVEL, 0);
-                    final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
-                    final Message msg = mHandler.obtainMessage(
-                            MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health));
-                    mHandler.sendMessage(msg);
-                } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
-                    if (DEBUG_SIM_STATES) {
-                        Log.v(TAG, "action " + action + " state" +
-                            intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE));
-                    }
-                    mHandler.sendMessage(mHandler.obtainMessage(
-                            MSG_SIM_STATE_CHANGE, SimArgs.fromIntent(intent)));
-                } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
-                    mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
-                            intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
-                } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
-                    String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
-                    mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
-                } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
-                        .equals(action)) {
-                    mHandler.sendMessage(mHandler.obtainMessage(MSG_DPM_STATE_CHANGED));
-                } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
-                    mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_CHANGED,
-                            intent.getIntExtra(Intent.EXTRA_USERID, 0), 0));
-                }
-            }
-        }, filter);
-    }
-
-    protected void handleDevicePolicyManagerStateChanged() {
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onDevicePolicyManagerStateChanged();
-        }
-    }
-
-    protected void handleUserChanged(int userId) {
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onUserChanged(userId);
-        }
-    }
-
-    protected void handleDeviceProvisioned() {
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onDeviceProvisioned();
-        }
-        if (mContentObserver != null) {
-            // We don't need the observer anymore...
-            mContext.getContentResolver().unregisterContentObserver(mContentObserver);
-            mContentObserver = null;
-        }
-    }
-
-    protected void handlePhoneStateChanged(String newState) {
-        if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
-        if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
-            mPhoneState = TelephonyManager.CALL_STATE_IDLE;
-        } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
-            mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
-        } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
-            mPhoneState = TelephonyManager.CALL_STATE_RINGING;
-        }
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onPhoneStateChanged(mPhoneState);
-        }
-    }
-
-    protected void handleRingerModeChange(int mode) {
-        if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
-        mRingMode = mode;
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onRingerModeChanged(mode);
-        }
-    }
-
-    /**
-     * Handle {@link #MSG_TIME_UPDATE}
-     */
-    private void handleTimeUpdate() {
-        if (DEBUG) Log.d(TAG, "handleTimeUpdate");
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onTimeChanged();
-        }
-    }
-
-    /**
-     * Handle {@link #MSG_BATTERY_UPDATE}
-     */
-    private void handleBatteryUpdate(BatteryStatus batteryStatus) {
-        if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
-        final boolean batteryUpdateInteresting =
-                isBatteryUpdateInteresting(mBatteryStatus, batteryStatus);
-        mBatteryStatus = batteryStatus;
-        if (batteryUpdateInteresting) {
-            for (int i = 0; i < mInfoCallbacks.size(); i++) {
-                // TODO: pass BatteryStatus object to onRefreshBatteryInfo() instead...
-                mInfoCallbacks.get(i).onRefreshBatteryInfo(
-                    shouldShowBatteryInfo(),isPluggedIn(batteryStatus), batteryStatus.level);
-            }
-        }
-    }
-
-    /**
-     * Handle {@link #MSG_CARRIER_INFO_UPDATE}
-     */
-    private void handleCarrierInfoUpdate() {
-        if (DEBUG) Log.d(TAG, "handleCarrierInfoUpdate: plmn = " + mTelephonyPlmn
-            + ", spn = " + mTelephonySpn);
-
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
-        }
-    }
-
-    /**
-     * Handle {@link #MSG_SIM_STATE_CHANGE}
-     */
-    private void handleSimStateChange(SimArgs simArgs) {
-        final IccCardConstants.State state = simArgs.simState;
-
-        if (DEBUG) {
-            Log.d(TAG, "handleSimStateChange: intentValue = " + simArgs + " "
-                    + "state resolved to " + state.toString());
-        }
-
-        if (state != IccCardConstants.State.UNKNOWN && state != mSimState) {
-            mSimState = state;
-            for (int i = 0; i < mSimStateCallbacks.size(); i++) {
-                mSimStateCallbacks.get(i).onSimStateChanged(state);
-            }
-        }
-    }
-
-    private void handleClockVisibilityChanged() {
-        if (DEBUG) Log.d(TAG, "handleClockVisibilityChanged()");
-        for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onClockVisibilityChanged();
-        }
-    }
-
-    /**
-     * @param pluggedIn state from {@link android.os.BatteryManager#EXTRA_PLUGGED}
-     * @return Whether the device is considered "plugged in."
-     */
-    private static boolean isPluggedIn(BatteryStatus status) {
-        return status.plugged == BatteryManager.BATTERY_PLUGGED_AC
-                || status.plugged == BatteryManager.BATTERY_PLUGGED_USB;
-    }
-
-    private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
-        final boolean nowPluggedIn = isPluggedIn(current);
-        final boolean wasPluggedIn = isPluggedIn(old);
-        final boolean stateChangedWhilePluggedIn =
-            wasPluggedIn == true && nowPluggedIn == true
-            && (old.status != current.status);
-
-        // change in plug state is always interesting
-        if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
-            return true;
-        }
-
-        // change in battery level while plugged in
-        if (nowPluggedIn && old.level != current.level) {
-            return true;
-        }
-
-        // change where battery needs charging
-        if (!nowPluggedIn && isBatteryLow(current) && current.level != old.level) {
-            return true;
-        }
-        return false;
-    }
-
-    private static boolean isBatteryLow(BatteryStatus status) {
-        return status.level < LOW_BATTERY_THRESHOLD;
-    }
-
-    /**
-     * @param intent The intent with action {@link TelephonyIntents#SPN_STRINGS_UPDATED_ACTION}
-     * @return The string to use for the plmn, or null if it should not be shown.
-     */
-    private CharSequence getTelephonyPlmnFrom(Intent intent) {
-        if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false)) {
-            final String plmn = intent.getStringExtra(TelephonyIntents.EXTRA_PLMN);
-            if (plmn != null) {
-                return plmn;
-            } else {
-                return getDefaultPlmn();
-            }
-        }
-        return null;
-    }
-
-    /**
-     * @return The default plmn (no service)
-     */
-    private CharSequence getDefaultPlmn() {
-        return mContext.getResources().getText(
-                        R.string.lockscreen_carrier_default);
-    }
-
-    /**
-     * @param intent The intent with action {@link Telephony.Intents#SPN_STRINGS_UPDATED_ACTION}
-     * @return The string to use for the plmn, or null if it should not be shown.
-     */
-    private CharSequence getTelephonySpnFrom(Intent intent) {
-        if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false)) {
-            final String spn = intent.getStringExtra(TelephonyIntents.EXTRA_SPN);
-            if (spn != null) {
-                return spn;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Remove the given observer from being registered from any of the kinds
-     * of callbacks.
-     * @param observer The observer to remove (an instance of {@link ConfigurationChangeCallback},
-     *   {@link InfoCallback} or {@link SimStateCallback}
-     */
-    public void removeCallback(Object observer) {
-        mInfoCallbacks.remove(observer);
-        mSimStateCallbacks.remove(observer);
-    }
-
-    /**
-     * Callback for general information relevant to lock screen.
-     */
-    interface InfoCallback {
-        void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel);
-        void onTimeChanged();
-
-        /**
-         * @param plmn The operator name of the registered network.  May be null if it shouldn't
-         *   be displayed.
-         * @param spn The service provider name.  May be null if it shouldn't be displayed.
-         */
-        void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn);
-
-        /**
-         * Called when the ringer mode changes.
-         * @param state the current ringer state, as defined in
-         * {@link AudioManager#RINGER_MODE_CHANGED_ACTION}
-         */
-        void onRingerModeChanged(int state);
-
-        /**
-         * Called when the phone state changes. String will be one of:
-         * {@link TelephonyManager#EXTRA_STATE_IDLE}
-         * {@link TelephonyManager@EXTRA_STATE_RINGING}
-         * {@link TelephonyManager#EXTRA_STATE_OFFHOOK
-         */
-        void onPhoneStateChanged(int phoneState);
-
-        /**
-         * Called when visibility of lockscreen clock changes, such as when
-         * obscured by a widget.
-         */
-        void onClockVisibilityChanged();
-
-        /**
-         * Called when the device becomes provisioned
-         */
-        void onDeviceProvisioned();
-
-        /**
-         * Called when the device policy changes.
-         * See {@link DevicePolicyManager#ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED}
-         */
-        void onDevicePolicyManagerStateChanged();
-
-        /**
-         * Called when the user changes.
-         */
-        void onUserChanged(int userId);
-    }
-
-    // Simple class that allows methods to easily be overwritten
-    public static class InfoCallbackImpl implements InfoCallback {
-        public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
-                int batteryLevel) {
-        }
-
-        public void onTimeChanged() {
-        }
-
-        public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
-        }
-
-        public void onRingerModeChanged(int state) {
-        }
-
-        public void onPhoneStateChanged(int phoneState) {
-        }
-
-        public void onClockVisibilityChanged() {
-        }
-
-        public void onDeviceProvisioned() {
-        }
-
-        public void onDevicePolicyManagerStateChanged() {
-        }
-
-        public void onUserChanged(int userId) {
-        }
-    }
-
-    /**
-     * Callback to notify of sim state change.
-     */
-    interface SimStateCallback {
-        void onSimStateChanged(IccCardConstants.State simState);
-    }
-
-    /**
-     * Register to receive notifications about general keyguard information
-     * (see {@link InfoCallback}.
-     * @param callback The callback.
-     */
-    public void registerInfoCallback(InfoCallback callback) {
-        if (!mInfoCallbacks.contains(callback)) {
-            mInfoCallbacks.add(callback);
-            // Notify listener of the current state
-            callback.onRefreshBatteryInfo(shouldShowBatteryInfo(),isPluggedIn(mBatteryStatus),
-                    mBatteryStatus.level);
-            callback.onTimeChanged();
-            callback.onRingerModeChanged(mRingMode);
-            callback.onPhoneStateChanged(mPhoneState);
-            callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
-            callback.onClockVisibilityChanged();
-        } else {
-            if (DEBUG) Log.e(TAG, "Object tried to add another INFO callback",
-                    new Exception("Whoops"));
-        }
-    }
-
-    /**
-     * Register to be notified of sim state changes.
-     * @param callback The callback.
-     */
-    public void registerSimStateCallback(SimStateCallback callback) {
-        if (!mSimStateCallbacks.contains(callback)) {
-            mSimStateCallbacks.add(callback);
-            // Notify listener of the current state
-            callback.onSimStateChanged(mSimState);
-        } else {
-            if (DEBUG) Log.e(TAG, "Object tried to add another SIM callback",
-                    new Exception("Whoops"));
-        }
-    }
-
-    public void reportClockVisible(boolean visible) {
-        mClockVisible = visible;
-        mHandler.obtainMessage(MSG_CLOCK_VISIBILITY_CHANGED).sendToTarget();
-    }
-
-    public IccCardConstants.State getSimState() {
-        return mSimState;
-    }
-
-    /**
-     * Report that the user successfully entered the SIM PIN or PUK/SIM PIN so we
-     * have the information earlier than waiting for the intent
-     * broadcast from the telephony code.
-     *
-     * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
-     * through mHandler, this *must* be called from the UI thread.
-     */
-    public void reportSimUnlocked() {
-        handleSimStateChange(new SimArgs(IccCardConstants.State.READY));
-    }
-
-    public boolean isDevicePluggedIn() {
-        return isPluggedIn(mBatteryStatus);
-    }
-
-    public boolean isDeviceCharged() {
-        return mBatteryStatus.status == BATTERY_STATUS_FULL
-                || mBatteryStatus.level >= 100; // in case particular device doesn't flag it
-    }
-
-    public int getBatteryLevel() {
-        return mBatteryStatus.level;
-    }
-
-    public boolean shouldShowBatteryInfo() {
-        return isPluggedIn(mBatteryStatus) || isBatteryLow(mBatteryStatus);
-    }
-
-    public CharSequence getTelephonyPlmn() {
-        return mTelephonyPlmn;
-    }
-
-    public CharSequence getTelephonySpn() {
-        return mTelephonySpn;
-    }
-
-    /**
-     * @return Whether the device is provisioned (whether they have gone through
-     *   the setup wizard)
-     */
-    public boolean isDeviceProvisioned() {
-        return mDeviceProvisioned;
-    }
-
-    public int getFailedAttempts() {
-        return mFailedAttempts;
-    }
-
-    public void clearFailedAttempts() {
-        mFailedAttempts = 0;
-        mFailedBiometricUnlockAttempts = 0;
-    }
-
-    public void reportFailedAttempt() {
-        mFailedAttempts++;
-    }
-
-    public boolean isClockVisible() {
-        return mClockVisible;
-    }
-
-    public int getPhoneState() {
-        return mPhoneState;
-    }
-
-    public void reportFailedBiometricUnlockAttempt() {
-        mFailedBiometricUnlockAttempts++;
-    }
-
-    public boolean getMaxBiometricUnlockAttemptsReached() {
-        return mFailedBiometricUnlockAttempts >= FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP;
-    }
-
-    public boolean isSimLocked() {
-        return mSimState == IccCardConstants.State.PIN_REQUIRED
-            || mSimState == IccCardConstants.State.PUK_REQUIRED
-            || mSimState == IccCardConstants.State.PERM_DISABLED;
-    }
-}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
deleted file mode 100644
index 29a5573..0000000
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
+++ /dev/null
@@ -1,270 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
-import android.media.AudioManager;
-import android.media.IAudioService;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.telephony.TelephonyManager;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.Gravity;
-import android.widget.FrameLayout;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.Slog;
-
-/**
- * Base class for keyguard views.  {@link #reset} is where you should
- * reset the state of your view.  Use the {@link KeyguardViewCallback} via
- * {@link #getCallback()} to send information back (such as poking the wake lock,
- * or finishing the keyguard).
- *
- * Handles intercepting of media keys that still work when the keyguard is
- * showing.
- */
-public abstract class KeyguardViewBase extends FrameLayout {
-
-    private static final int BACKGROUND_COLOR = 0x70000000;
-    private KeyguardViewCallback mCallback;
-    private AudioManager mAudioManager;
-    private TelephonyManager mTelephonyManager = null;
-    // Whether the volume keys should be handled by keyguard. If true, then
-    // they will be handled here for specific media types such as music, otherwise
-    // the audio service will bring up the volume dialog.
-    private static final boolean KEYGUARD_MANAGES_VOLUME = true;
-
-    // This is a faster way to draw the background on devices without hardware acceleration
-    Drawable mBackgroundDrawable = new Drawable() {
-        @Override
-        public void draw(Canvas canvas) {
-            canvas.drawColor(BACKGROUND_COLOR, PorterDuff.Mode.SRC);
-        }
-
-        @Override
-        public void setAlpha(int alpha) {
-        }
-
-        @Override
-        public void setColorFilter(ColorFilter cf) {
-        }
-
-        @Override
-        public int getOpacity() {
-            return PixelFormat.TRANSLUCENT;
-        }
-    };
-
-    public KeyguardViewBase(Context context, KeyguardViewCallback callback) {
-        super(context);
-        mCallback = callback;
-        resetBackground();
-    }
-
-    public void resetBackground() {
-        setBackgroundDrawable(mBackgroundDrawable);
-    }
-
-    public KeyguardViewCallback getCallback() {
-        return mCallback;
-    }
-
-    /**
-     * Called when you need to reset the state of your view.
-     */
-    abstract public void reset();
-
-    /**
-     * Called when the screen turned off.
-     */
-    abstract public void onScreenTurnedOff();
-
-    /**
-     * Called when the screen turned on.
-     */
-    abstract public void onScreenTurnedOn();
-
-    /**
-     * Called when the view needs to be shown.
-     */
-    abstract public void show();
-
-    /**
-     * Called when a key has woken the device to give us a chance to adjust our
-     * state according the the key.  We are responsible for waking the device
-     * (by poking the wake lock) once we are ready.
-     *
-     * The 'Tq' suffix is per the documentation in {@link android.view.WindowManagerPolicy}.
-     * Be sure not to take any action that takes a long time; any significant
-     * action should be posted to a handler.
-     *
-     * @param keyCode The wake key, which may be relevant for configuring the
-     *   keyguard.  May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking for a reason
-     *   other than a key press.
-     */
-    abstract public void wakeWhenReadyTq(int keyCode);
-
-    /**
-     * Verify that the user can get past the keyguard securely.  This is called,
-     * for example, when the phone disables the keyguard but then wants to launch
-     * something else that requires secure access.
-     *
-     * The result will be propogated back via {@link KeyguardViewCallback#keyguardDone(boolean)}
-     */
-    abstract public void verifyUnlock();
-
-    /**
-     * Called before this view is being removed.
-     */
-    abstract public void cleanUp();
-
-    @Override
-    public boolean dispatchKeyEvent(KeyEvent event) {
-        if (shouldEventKeepScreenOnWhileKeyguardShowing(event)) {
-            mCallback.pokeWakelock();
-        }
-
-        if (interceptMediaKey(event)) {
-            return true;
-        }
-        return super.dispatchKeyEvent(event);
-    }
-
-    private boolean shouldEventKeepScreenOnWhileKeyguardShowing(KeyEvent event) {
-        if (event.getAction() != KeyEvent.ACTION_DOWN) {
-            return false;
-        }
-        switch (event.getKeyCode()) {
-            case KeyEvent.KEYCODE_DPAD_DOWN:
-            case KeyEvent.KEYCODE_DPAD_LEFT:
-            case KeyEvent.KEYCODE_DPAD_RIGHT:
-            case KeyEvent.KEYCODE_DPAD_UP:
-                return false;
-            default:
-                return true;
-        }
-    }
-
-    /**
-     * Allows the media keys to work when the keyguard is showing.
-     * The media keys should be of no interest to the actual keyguard view(s),
-     * so intercepting them here should not be of any harm.
-     * @param event The key event
-     * @return whether the event was consumed as a media key.
-     */
-    private boolean interceptMediaKey(KeyEvent event) {
-        final int keyCode = event.getKeyCode();
-        if (event.getAction() == KeyEvent.ACTION_DOWN) {
-            switch (keyCode) {
-                case KeyEvent.KEYCODE_MEDIA_PLAY:
-                case KeyEvent.KEYCODE_MEDIA_PAUSE:
-                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
-                    /* Suppress PLAY/PAUSE toggle when phone is ringing or
-                     * in-call to avoid music playback */
-                    if (mTelephonyManager == null) {
-                        mTelephonyManager = (TelephonyManager) getContext().getSystemService(
-                                Context.TELEPHONY_SERVICE);
-                    }
-                    if (mTelephonyManager != null &&
-                            mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
-                        return true;  // suppress key event
-                    }
-                case KeyEvent.KEYCODE_MUTE:
-                case KeyEvent.KEYCODE_HEADSETHOOK:
-                case KeyEvent.KEYCODE_MEDIA_STOP:
-                case KeyEvent.KEYCODE_MEDIA_NEXT:
-                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
-                case KeyEvent.KEYCODE_MEDIA_REWIND:
-                case KeyEvent.KEYCODE_MEDIA_RECORD:
-                case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
-                    handleMediaKeyEvent(event);
-                    return true;
-                }
-
-                case KeyEvent.KEYCODE_VOLUME_UP:
-                case KeyEvent.KEYCODE_VOLUME_DOWN:
-                case KeyEvent.KEYCODE_VOLUME_MUTE: {
-                    if (KEYGUARD_MANAGES_VOLUME) {
-                        synchronized (this) {
-                            if (mAudioManager == null) {
-                                mAudioManager = (AudioManager) getContext().getSystemService(
-                                        Context.AUDIO_SERVICE);
-                            }
-                        }
-                        // Volume buttons should only function for music (local or remote).
-                        // TODO: Actually handle MUTE.
-                        mAudioManager.adjustLocalOrRemoteStreamVolume(
-                                AudioManager.STREAM_MUSIC,
-                                keyCode == KeyEvent.KEYCODE_VOLUME_UP
-                                        ? AudioManager.ADJUST_RAISE
-                                        : AudioManager.ADJUST_LOWER);
-                        // Don't execute default volume behavior
-                        return true;
-                    } else {
-                        return false;
-                    }
-                }
-            }
-        } else if (event.getAction() == KeyEvent.ACTION_UP) {
-            switch (keyCode) {
-                case KeyEvent.KEYCODE_MUTE:
-                case KeyEvent.KEYCODE_HEADSETHOOK:
-                case KeyEvent.KEYCODE_MEDIA_PLAY:
-                case KeyEvent.KEYCODE_MEDIA_PAUSE:
-                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
-                case KeyEvent.KEYCODE_MEDIA_STOP:
-                case KeyEvent.KEYCODE_MEDIA_NEXT:
-                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
-                case KeyEvent.KEYCODE_MEDIA_REWIND:
-                case KeyEvent.KEYCODE_MEDIA_RECORD:
-                case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
-                    handleMediaKeyEvent(event);
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    void handleMediaKeyEvent(KeyEvent keyEvent) {
-        IAudioService audioService = IAudioService.Stub.asInterface(
-                ServiceManager.checkService(Context.AUDIO_SERVICE));
-        if (audioService != null) {
-            try {
-                audioService.dispatchMediaKeyEvent(keyEvent);
-            } catch (RemoteException e) {
-                Log.e("KeyguardViewBase", "dispatchMediaKeyEvent threw exception " + e);
-            }
-        } else {
-            Slog.w("KeyguardViewBase", "Unable to find IAudioService for media key event");
-        }
-    }
-
-    @Override
-    public void dispatchSystemUiVisibilityChanged(int visibility) {
-        super.dispatchSystemUiVisibilityChanged(visibility);
-        setSystemUiVisibility(STATUS_BAR_DISABLE_BACK);
-    }
-}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewCallback.java b/policy/src/com/android/internal/policy/impl/KeyguardViewCallback.java
deleted file mode 100644
index b376d65..0000000
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewCallback.java
+++ /dev/null
@@ -1,49 +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.
- */
-
-package com.android.internal.policy.impl;
-
-/**
- * The callback used by the keyguard view to tell the {@link KeyguardViewMediator} 
- * various things.
- */
-public interface KeyguardViewCallback {
-
-    /**
-     * Request the wakelock to be poked for the default amount of time.
-     */
-    void pokeWakelock();
-
-    /**
-     * Request the wakelock to be poked for a specific amount of time.
-     * @param millis The amount of time in millis.
-     */
-    void pokeWakelock(int millis);
-
-    /**
-     * Report that the keyguard is done.
-     * @param authenticated Whether the user securely got past the keyguard.
-     *   the only reason for this to be false is if the keyguard was instructed
-     *   to appear temporarily to verify the user is supposed to get past the
-     *   keyguard, and the user fails to do so.
-     */
-    void keyguardDone(boolean authenticated);
-
-    /**
-     * Report that the keyguard is done drawing.
-     */
-    void keyguardDoneDrawing();
-}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
deleted file mode 100644
index fb6ff24..0000000
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ /dev/null
@@ -1,311 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import com.android.internal.R;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.res.Resources;
-import android.graphics.PixelFormat;
-import android.graphics.Canvas;
-import android.os.IBinder;
-import android.os.SystemProperties;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewManager;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-
-import android.graphics.Color;
-
-/**
- * Manages creating, showing, hiding and resetting the keyguard.  Calls back
- * via {@link com.android.internal.policy.impl.KeyguardViewCallback} to poke
- * the wake lock and report that the keyguard is done, which is in turn,
- * reported to this class by the current {@link KeyguardViewBase}.
- */
-public class KeyguardViewManager implements KeyguardWindowController {
-    private final static boolean DEBUG = false;
-    private static String TAG = "KeyguardViewManager";
-
-    private final Context mContext;
-    private final ViewManager mViewManager;
-    private final KeyguardViewCallback mCallback;
-    private final KeyguardViewProperties mKeyguardViewProperties;
-
-    private final KeyguardUpdateMonitor mUpdateMonitor;
-
-    private WindowManager.LayoutParams mWindowLayoutParams;
-    private boolean mNeedsInput = false;
-
-    private FrameLayout mKeyguardHost;
-    private KeyguardViewBase mKeyguardView;
-
-    private boolean mScreenOn = false;
-
-    public interface ShowListener {
-        void onShown(IBinder windowToken);
-    };
-
-    /**
-     * @param context Used to create views.
-     * @param viewManager Keyguard will be attached to this.
-     * @param callback Used to notify of changes.
-     */
-    public KeyguardViewManager(Context context, ViewManager viewManager,
-            KeyguardViewCallback callback, KeyguardViewProperties keyguardViewProperties,
-            KeyguardUpdateMonitor updateMonitor) {
-        mContext = context;
-        mViewManager = viewManager;
-        mCallback = callback;
-        mKeyguardViewProperties = keyguardViewProperties;
-
-        mUpdateMonitor = updateMonitor;
-    }
-
-    /**
-     * Helper class to host the keyguard view.
-     */
-    private static class KeyguardViewHost extends FrameLayout {
-        private final KeyguardViewCallback mCallback;
-
-        private KeyguardViewHost(Context context, KeyguardViewCallback callback) {
-            super(context);
-            mCallback = callback;
-        }
-
-        @Override
-        protected void dispatchDraw(Canvas canvas) {
-            super.dispatchDraw(canvas);
-            mCallback.keyguardDoneDrawing();
-        }
-    }
-
-    /**
-     * Show the keyguard.  Will handle creating and attaching to the view manager
-     * lazily.
-     */
-    public synchronized void show() {
-        if (DEBUG) Log.d(TAG, "show(); mKeyguardView==" + mKeyguardView);
-
-        Resources res = mContext.getResources();
-        boolean enableScreenRotation =
-                SystemProperties.getBoolean("lockscreen.rot_override",false)
-                || res.getBoolean(R.bool.config_enableLockScreenRotation);
-        if (mKeyguardHost == null) {
-            if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");
-
-            mKeyguardHost = new KeyguardViewHost(mContext, mCallback);
-
-            final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
-            int flags = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
-                    | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER
-                    | WindowManager.LayoutParams.FLAG_SLIPPERY
-                    /*| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                    | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR*/ ;
-            if (!mNeedsInput) {
-                flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-            }
-            if (ActivityManager.isHighEndGfx(((WindowManager)mContext.getSystemService(
-                    Context.WINDOW_SERVICE)).getDefaultDisplay())) {
-                flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-            }
-            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                    stretch, stretch, WindowManager.LayoutParams.TYPE_KEYGUARD,
-                    flags, PixelFormat.TRANSLUCENT);
-            lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
-            lp.windowAnimations = com.android.internal.R.style.Animation_LockScreen;
-            if (ActivityManager.isHighEndGfx(((WindowManager)mContext.getSystemService(
-                    Context.WINDOW_SERVICE)).getDefaultDisplay())) {
-                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-                lp.privateFlags |=
-                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
-            }
-            lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
-            lp.setTitle("Keyguard");
-            mWindowLayoutParams = lp;
-
-            mViewManager.addView(mKeyguardHost, lp);
-        }
-
-        if (enableScreenRotation) {
-            if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen On!");
-            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
-        } else {
-            if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen Off!");
-            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
-        }
-
-        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-
-        if (mKeyguardView == null) {
-            if (DEBUG) Log.d(TAG, "keyguard view is null, creating it...");
-            mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mCallback,
-                    mUpdateMonitor, this);
-            mKeyguardView.setId(R.id.lock_screen);
-
-            final ViewGroup.LayoutParams lp = new FrameLayout.LayoutParams(
-                    ViewGroup.LayoutParams.MATCH_PARENT,
-                    ViewGroup.LayoutParams.MATCH_PARENT);
-
-            mKeyguardHost.addView(mKeyguardView, lp);
-
-            if (mScreenOn) {
-                mKeyguardView.show();
-            }
-        }
-
-        // Disable aspects of the system/status/navigation bars that are not appropriate or
-        // useful for the lockscreen but can be re-shown by dialogs or SHOW_WHEN_LOCKED activities.
-        // Other disabled bits are handled by the KeyguardViewMediator talking directly to the
-        // status bar service.
-        int visFlags =
-                ( View.STATUS_BAR_DISABLE_BACK
-                | View.STATUS_BAR_DISABLE_HOME
-                );
-        Log.v(TAG, "KGVM: Set visibility on " + mKeyguardHost + " to " + visFlags);
-        mKeyguardHost.setSystemUiVisibility(visFlags);
-
-        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-        mKeyguardHost.setVisibility(View.VISIBLE);
-        mKeyguardView.requestFocus();
-    }
-
-    public void setNeedsInput(boolean needsInput) {
-        mNeedsInput = needsInput;
-        if (mWindowLayoutParams != null) {
-            if (needsInput) {
-                mWindowLayoutParams.flags &=
-                    ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-            } else {
-                mWindowLayoutParams.flags |=
-                    WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-            }
-            mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-        }
-    }
-
-    /**
-     * Reset the state of the view.
-     */
-    public synchronized void reset() {
-        if (DEBUG) Log.d(TAG, "reset()");
-        if (mKeyguardView != null) {
-            mKeyguardView.reset();
-        }
-    }
-
-    public synchronized void onScreenTurnedOff() {
-        if (DEBUG) Log.d(TAG, "onScreenTurnedOff()");
-        mScreenOn = false;
-        if (mKeyguardView != null) {
-            mKeyguardView.onScreenTurnedOff();
-        }
-    }
-
-    public synchronized void onScreenTurnedOn(
-            final KeyguardViewManager.ShowListener showListener) {
-        if (DEBUG) Log.d(TAG, "onScreenTurnedOn()");
-        mScreenOn = true;
-        if (mKeyguardView != null) {
-            mKeyguardView.onScreenTurnedOn();
-
-            // Caller should wait for this window to be shown before turning
-            // on the screen.
-            if (mKeyguardHost.getVisibility() == View.VISIBLE) {
-                // Keyguard may be in the process of being shown, but not yet
-                // updated with the window manager...  give it a chance to do so.
-                mKeyguardHost.post(new Runnable() {
-                    @Override public void run() {
-                        if (mKeyguardHost.getVisibility() == View.VISIBLE) {
-                            showListener.onShown(mKeyguardHost.getWindowToken());
-                        } else {
-                            showListener.onShown(null);
-                        }
-                    }
-                });
-            } else {
-                showListener.onShown(null);
-            }
-        } else {
-            showListener.onShown(null);
-        }
-    }
-
-    public synchronized void verifyUnlock() {
-        if (DEBUG) Log.d(TAG, "verifyUnlock()");
-        show();
-        mKeyguardView.verifyUnlock();
-    }
-
-    /**
-     * A key has woken the device.  We use this to potentially adjust the state
-     * of the lock screen based on the key.
-     *
-     * The 'Tq' suffix is per the documentation in {@link android.view.WindowManagerPolicy}.
-     * Be sure not to take any action that takes a long time; any significant
-     * action should be posted to a handler.
-     *
-     * @param keyCode The wake key.  May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking
-     * for a reason other than a key press.
-     */
-    public boolean wakeWhenReadyTq(int keyCode) {
-        if (DEBUG) Log.d(TAG, "wakeWhenReady(" + keyCode + ")");
-        if (mKeyguardView != null) {
-            mKeyguardView.wakeWhenReadyTq(keyCode);
-            return true;
-        } else {
-            Log.w(TAG, "mKeyguardView is null in wakeWhenReadyTq");
-            return false;
-        }
-    }
-
-    /**
-     * Hides the keyguard view
-     */
-    public synchronized void hide() {
-        if (DEBUG) Log.d(TAG, "hide()");
-
-        if (mKeyguardHost != null) {
-            mKeyguardHost.setVisibility(View.GONE);
-            // Don't do this right away, so we can let the view continue to animate
-            // as it goes away.
-            if (mKeyguardView != null) {
-                final KeyguardViewBase lastView = mKeyguardView;
-                mKeyguardView = null;
-                mKeyguardHost.postDelayed(new Runnable() {
-                    public void run() {
-                        synchronized (KeyguardViewManager.this) {
-                            lastView.cleanUp();
-                            mKeyguardHost.removeView(lastView);
-                        }
-                    }
-                }, 500);
-            }
-        }
-    }
-
-    /**
-     * @return Whether the keyguard is showing
-     */
-    public synchronized boolean isShowing() {
-        return (mKeyguardHost != null && mKeyguardHost.getVisibility() == View.VISIBLE);
-    }
-}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
deleted file mode 100644
index 5fa6dbf..0000000
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ /dev/null
@@ -1,1334 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-
-import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.widget.LockPatternUtils;
-
-import android.app.ActivityManagerNative;
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.app.StatusBarManager;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.media.AudioManager;
-import android.media.SoundPool;
-import android.os.Handler;
-import android.os.LocalPowerManager;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.telephony.TelephonyManager;
-import android.util.EventLog;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.WindowManagerImpl;
-import android.view.WindowManagerPolicy;
-
-
-/**
- * Mediates requests related to the keyguard.  This includes queries about the
- * state of the keyguard, power management events that effect whether the keyguard
- * should be shown or reset, callbacks to the phone window manager to notify
- * it of when the keyguard is showing, and events from the keyguard view itself
- * stating that the keyguard was succesfully unlocked.
- *
- * Note that the keyguard view is shown when the screen is off (as appropriate)
- * so that once the screen comes on, it will be ready immediately.
- *
- * Example queries about the keyguard:
- * - is {movement, key} one that should wake the keygaurd?
- * - is the keyguard showing?
- * - are input events restricted due to the state of the keyguard?
- *
- * Callbacks to the phone window manager:
- * - the keyguard is showing
- *
- * Example external events that translate to keyguard view changes:
- * - screen turned off -> reset the keyguard, and show it so it will be ready
- *   next time the screen turns on
- * - keyboard is slid open -> if the keyguard is not secure, hide it
- *
- * Events from the keyguard view:
- * - user succesfully unlocked keyguard -> hide keyguard view, and no longer
- *   restrict input events.
- *
- * Note: in addition to normal power managment events that effect the state of
- * whether the keyguard should be showing, external apps and services may request
- * that the keyguard be disabled via {@link #setKeyguardEnabled(boolean)}.  When
- * false, this will override all other conditions for turning on the keyguard.
- *
- * Threading and synchronization:
- * This class is created by the initialization routine of the {@link WindowManagerPolicy},
- * and runs on its thread.  The keyguard UI is created from that thread in the
- * constructor of this class.  The apis may be called from other threads, including the
- * {@link com.android.server.input.InputManagerService}'s and {@link android.view.WindowManager}'s.
- * Therefore, methods on this class are synchronized, and any action that is pointed
- * directly to the keyguard UI is posted to a {@link Handler} to ensure it is taken on the UI
- * thread of the keyguard.
- */
-public class KeyguardViewMediator implements KeyguardViewCallback,
-        KeyguardUpdateMonitor.SimStateCallback {
-    private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
-    private final static boolean DEBUG = false;
-    private final static boolean DBG_WAKE = false;
-
-    private final static String TAG = "KeyguardViewMediator";
-
-    private static final String DELAYED_KEYGUARD_ACTION =
-        "com.android.internal.policy.impl.PhoneWindowManager.DELAYED_KEYGUARD";
-
-    // used for handler messages
-    private static final int TIMEOUT = 1;
-    private static final int SHOW = 2;
-    private static final int HIDE = 3;
-    private static final int RESET = 4;
-    private static final int VERIFY_UNLOCK = 5;
-    private static final int NOTIFY_SCREEN_OFF = 6;
-    private static final int NOTIFY_SCREEN_ON = 7;
-    private static final int WAKE_WHEN_READY = 8;
-    private static final int KEYGUARD_DONE = 9;
-    private static final int KEYGUARD_DONE_DRAWING = 10;
-    private static final int KEYGUARD_DONE_AUTHENTICATING = 11;
-    private static final int SET_HIDDEN = 12;
-    private static final int KEYGUARD_TIMEOUT = 13;
-
-    /**
-     * The default amount of time we stay awake (used for all key input)
-     */
-    protected static final int AWAKE_INTERVAL_DEFAULT_MS = 10000;
-
-    /**
-     * How long to wait after the screen turns off due to timeout before
-     * turning on the keyguard (i.e, the user has this much time to turn
-     * the screen back on without having to face the keyguard).
-     */
-    private static final int KEYGUARD_LOCK_AFTER_DELAY_DEFAULT = 5000;
-
-    /**
-     * How long we'll wait for the {@link KeyguardViewCallback#keyguardDoneDrawing()}
-     * callback before unblocking a call to {@link #setKeyguardEnabled(boolean)}
-     * that is reenabling the keyguard.
-     */
-    private static final int KEYGUARD_DONE_DRAWING_TIMEOUT_MS = 2000;
-
-    /**
-     * Allow the user to expand the status bar when the keyguard is engaged
-     * (without a pattern or password).
-     */
-    private static final boolean ENABLE_INSECURE_STATUS_BAR_EXPAND = true;
-
-    /** The stream type that the lock sounds are tied to. */
-    private int mMasterStreamType;
-
-    private Context mContext;
-    private AlarmManager mAlarmManager;
-    private AudioManager mAudioManager;
-    private StatusBarManager mStatusBarManager;
-    private boolean mShowLockIcon;
-    private boolean mShowingLockIcon;
-
-    private boolean mSystemReady;
-
-    // Whether the next call to playSounds() should be skipped.  Defaults to
-    // true because the first lock (on boot) should be silent.
-    private boolean mSuppressNextLockSound = true;
-
-
-    /** Low level access to the power manager for enableUserActivity.  Having this
-     * requires that we run in the system process.  */
-    LocalPowerManager mRealPowerManager;
-
-    /** High level access to the power manager for WakeLocks */
-    private PowerManager mPM;
-
-    /**
-     * Used to keep the device awake while the keyguard is showing, i.e for
-     * calls to {@link #pokeWakelock()}
-     */
-    private PowerManager.WakeLock mWakeLock;
-
-    /**
-     * Used to keep the device awake while to ensure the keyguard finishes opening before
-     * we sleep.
-     */
-    private PowerManager.WakeLock mShowKeyguardWakeLock;
-
-    /**
-     * Does not turn on screen, held while a call to {@link KeyguardViewManager#wakeWhenReadyTq(int)}
-     * is called to make sure the device doesn't sleep before it has a chance to poke
-     * the wake lock.
-     * @see #wakeWhenReadyLocked(int)
-     */
-    private PowerManager.WakeLock mWakeAndHandOff;
-
-    private KeyguardViewManager mKeyguardViewManager;
-
-    // these are protected by synchronized (this)
-
-    /**
-     * External apps (like the phone app) can tell us to disable the keygaurd.
-     */
-    private boolean mExternallyEnabled = true;
-
-    /**
-     * Remember if an external call to {@link #setKeyguardEnabled} with value
-     * false caused us to hide the keyguard, so that we need to reshow it once
-     * the keygaurd is reenabled with another call with value true.
-     */
-    private boolean mNeedToReshowWhenReenabled = false;
-
-    // cached value of whether we are showing (need to know this to quickly
-    // answer whether the input should be restricted)
-    private boolean mShowing = false;
-
-    // true if the keyguard is hidden by another window
-    private boolean mHidden = false;
-
-    /**
-     * Helps remember whether the screen has turned on since the last time
-     * it turned off due to timeout. see {@link #onScreenTurnedOff(int)}
-     */
-    private int mDelayedShowingSequence;
-
-    private int mWakelockSequence;
-
-    private PhoneWindowManager mCallback;
-
-    /**
-     * If the user has disabled the keyguard, then requests to exit, this is
-     * how we'll ultimately let them know whether it was successful.  We use this
-     * var being non-null as an indicator that there is an in progress request.
-     */
-    private WindowManagerPolicy.OnKeyguardExitResult mExitSecureCallback;
-
-    // the properties of the keyguard
-    private KeyguardViewProperties mKeyguardViewProperties;
-
-    private KeyguardUpdateMonitor mUpdateMonitor;
-
-    private boolean mScreenOn;
-
-    // last known state of the cellular connection
-    private String mPhoneState = TelephonyManager.EXTRA_STATE_IDLE;
-
-    /**
-     * we send this intent when the keyguard is dismissed.
-     */
-    private Intent mUserPresentIntent;
-
-    /**
-     * {@link #setKeyguardEnabled} waits on this condition when it reenables
-     * the keyguard.
-     */
-    private boolean mWaitingUntilKeyguardVisible = false;
-    private LockPatternUtils mLockPatternUtils;
-
-    private SoundPool mLockSounds;
-    private int mLockSoundId;
-    private int mUnlockSoundId;
-    private int mLockSoundStreamId;
-
-    /**
-     * The volume applied to the lock/unlock sounds.
-     */
-    private final float mLockSoundVolume;
-
-    InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() {
-
-        @Override
-        public void onClockVisibilityChanged() {
-            adjustStatusBarLocked();
-        }
-
-        @Override
-        public void onDeviceProvisioned() {
-            mContext.sendBroadcast(mUserPresentIntent);
-        }
-
-    };
-
-    public KeyguardViewMediator(Context context, PhoneWindowManager callback,
-            LocalPowerManager powerManager) {
-        mContext = context;
-
-        mRealPowerManager = powerManager;
-        mPM = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = mPM.newWakeLock(
-                PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
-                "keyguard");
-        mWakeLock.setReferenceCounted(false);
-        mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
-        mShowKeyguardWakeLock.setReferenceCounted(false);
-
-        mWakeAndHandOff = mPM.newWakeLock(
-                PowerManager.PARTIAL_WAKE_LOCK,
-                "keyguardWakeAndHandOff");
-        mWakeAndHandOff.setReferenceCounted(false);
-
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(DELAYED_KEYGUARD_ACTION);
-        filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
-        context.registerReceiver(mBroadCastReceiver, filter);
-        mAlarmManager = (AlarmManager) context
-                .getSystemService(Context.ALARM_SERVICE);
-        mCallback = callback;
-
-        mUpdateMonitor = new KeyguardUpdateMonitor(context);
-
-        mUpdateMonitor.registerInfoCallback(mInfoCallback);
-
-        mUpdateMonitor.registerSimStateCallback(this);
-
-        mLockPatternUtils = new LockPatternUtils(mContext);
-        mKeyguardViewProperties
-                = new LockPatternKeyguardViewProperties(mLockPatternUtils, mUpdateMonitor);
-
-        mKeyguardViewManager = new KeyguardViewManager(
-                context, WindowManagerImpl.getDefault(), this,
-                mKeyguardViewProperties, mUpdateMonitor);
-
-        mUserPresentIntent = new Intent(Intent.ACTION_USER_PRESENT);
-        mUserPresentIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
-                | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-
-        final ContentResolver cr = mContext.getContentResolver();
-        mShowLockIcon = (Settings.System.getInt(cr, "show_status_bar_lock", 0) == 1);
-
-        mScreenOn = mPM.isScreenOn();
-
-        mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0);
-        String soundPath = Settings.System.getString(cr, Settings.System.LOCK_SOUND);
-        if (soundPath != null) {
-            mLockSoundId = mLockSounds.load(soundPath, 1);
-        }
-        if (soundPath == null || mLockSoundId == 0) {
-            if (DEBUG) Log.d(TAG, "failed to load sound from " + soundPath);
-        }
-        soundPath = Settings.System.getString(cr, Settings.System.UNLOCK_SOUND);
-        if (soundPath != null) {
-            mUnlockSoundId = mLockSounds.load(soundPath, 1);
-        }
-        if (soundPath == null || mUnlockSoundId == 0) {
-            if (DEBUG) Log.d(TAG, "failed to load sound from " + soundPath);
-        }
-        int lockSoundDefaultAttenuation = context.getResources().getInteger(
-                com.android.internal.R.integer.config_lockSoundVolumeDb);
-        mLockSoundVolume = (float)Math.pow(10, lockSoundDefaultAttenuation/20);
-        IntentFilter userFilter = new IntentFilter();
-        userFilter.addAction(Intent.ACTION_USER_SWITCHED);
-        userFilter.addAction(Intent.ACTION_USER_REMOVED);
-        mContext.registerReceiver(mUserChangeReceiver, userFilter);
-    }
-
-    /**
-     * Let us know that the system is ready after startup.
-     */
-    public void onSystemReady() {
-        synchronized (this) {
-            if (DEBUG) Log.d(TAG, "onSystemReady");
-            mSystemReady = true;
-            doKeyguardLocked();
-        }
-    }
-
-    /**
-     * Called to let us know the screen was turned off.
-     * @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER},
-     *   {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
-     *   {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
-     */
-    public void onScreenTurnedOff(int why) {
-        synchronized (this) {
-            mScreenOn = false;
-            if (DEBUG) Log.d(TAG, "onScreenTurnedOff(" + why + ")");
-
-            // Lock immediately based on setting if secure (user has a pin/pattern/password).
-            // This also "locks" the device when not secure to provide easy access to the
-            // camera while preventing unwanted input.
-            final boolean lockImmediately =
-                mLockPatternUtils.getPowerButtonInstantlyLocks() || !mLockPatternUtils.isSecure();
-
-            if (mExitSecureCallback != null) {
-                if (DEBUG) Log.d(TAG, "pending exit secure callback cancelled");
-                mExitSecureCallback.onKeyguardExitResult(false);
-                mExitSecureCallback = null;
-                if (!mExternallyEnabled) {
-                    hideLocked();
-                }
-            } else if (mShowing) {
-                notifyScreenOffLocked();
-                resetStateLocked();
-            } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT
-                   || (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)) {
-                // if the screen turned off because of timeout or the user hit the power button
-                // and we don't need to lock immediately, set an alarm
-                // to enable it a little bit later (i.e, give the user a chance
-                // to turn the screen back on within a certain window without
-                // having to unlock the screen)
-                final ContentResolver cr = mContext.getContentResolver();
-
-                // From DisplaySettings
-                long displayTimeout = Settings.System.getInt(cr, SCREEN_OFF_TIMEOUT,
-                        KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT);
-
-                // From SecuritySettings
-                final long lockAfterTimeout = Settings.Secure.getInt(cr,
-                        Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
-                        KEYGUARD_LOCK_AFTER_DELAY_DEFAULT);
-
-                // From DevicePolicyAdmin
-                final long policyTimeout = mLockPatternUtils.getDevicePolicyManager()
-                        .getMaximumTimeToLock(null);
-
-                long timeout;
-                if (policyTimeout > 0) {
-                    // policy in effect. Make sure we don't go beyond policy limit.
-                    displayTimeout = Math.max(displayTimeout, 0); // ignore negative values
-                    timeout = Math.min(policyTimeout - displayTimeout, lockAfterTimeout);
-                } else {
-                    timeout = lockAfterTimeout;
-                }
-
-                if (timeout <= 0) {
-                    // Lock now
-                    mSuppressNextLockSound = true;
-                    doKeyguardLocked();
-                } else {
-                    // Lock in the future
-                    long when = SystemClock.elapsedRealtime() + timeout;
-                    Intent intent = new Intent(DELAYED_KEYGUARD_ACTION);
-                    intent.putExtra("seq", mDelayedShowingSequence);
-                    PendingIntent sender = PendingIntent.getBroadcast(mContext,
-                            0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
-                    mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, sender);
-                    if (DEBUG) Log.d(TAG, "setting alarm to turn off keyguard, seq = "
-                                     + mDelayedShowingSequence);
-                }
-            } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
-                // Do not enable the keyguard if the prox sensor forced the screen off.
-            } else {
-                doKeyguardLocked();
-            }
-        }
-    }
-
-    /**
-     * Let's us know the screen was turned on.
-     */
-    public void onScreenTurnedOn(KeyguardViewManager.ShowListener showListener) {
-        synchronized (this) {
-            mScreenOn = true;
-            mDelayedShowingSequence++;
-            if (DEBUG) Log.d(TAG, "onScreenTurnedOn, seq = " + mDelayedShowingSequence);
-            if (showListener != null) {
-                notifyScreenOnLocked(showListener);
-            }
-        }
-    }
-
-    /**
-     * Same semantics as {@link WindowManagerPolicy#enableKeyguard}; provide
-     * a way for external stuff to override normal keyguard behavior.  For instance
-     * the phone app disables the keyguard when it receives incoming calls.
-     */
-    public void setKeyguardEnabled(boolean enabled) {
-        synchronized (this) {
-            if (DEBUG) Log.d(TAG, "setKeyguardEnabled(" + enabled + ")");
-
-
-            mExternallyEnabled = enabled;
-
-            if (!enabled && mShowing) {
-                if (mExitSecureCallback != null) {
-                    if (DEBUG) Log.d(TAG, "in process of verifyUnlock request, ignoring");
-                    // we're in the process of handling a request to verify the user
-                    // can get past the keyguard. ignore extraneous requests to disable / reenable
-                    return;
-                }
-
-                // hiding keyguard that is showing, remember to reshow later
-                if (DEBUG) Log.d(TAG, "remembering to reshow, hiding keyguard, "
-                        + "disabling status bar expansion");
-                mNeedToReshowWhenReenabled = true;
-                hideLocked();
-            } else if (enabled && mNeedToReshowWhenReenabled) {
-                // reenabled after previously hidden, reshow
-                if (DEBUG) Log.d(TAG, "previously hidden, reshowing, reenabling "
-                        + "status bar expansion");
-                mNeedToReshowWhenReenabled = false;
-
-                if (mExitSecureCallback != null) {
-                    if (DEBUG) Log.d(TAG, "onKeyguardExitResult(false), resetting");
-                    mExitSecureCallback.onKeyguardExitResult(false);
-                    mExitSecureCallback = null;
-                    resetStateLocked();
-                } else {
-                    showLocked();
-
-                    // block until we know the keygaurd is done drawing (and post a message
-                    // to unblock us after a timeout so we don't risk blocking too long
-                    // and causing an ANR).
-                    mWaitingUntilKeyguardVisible = true;
-                    mHandler.sendEmptyMessageDelayed(KEYGUARD_DONE_DRAWING, KEYGUARD_DONE_DRAWING_TIMEOUT_MS);
-                    if (DEBUG) Log.d(TAG, "waiting until mWaitingUntilKeyguardVisible is false");
-                    while (mWaitingUntilKeyguardVisible) {
-                        try {
-                            wait();
-                        } catch (InterruptedException e) {
-                            Thread.currentThread().interrupt();
-                        }
-                    }
-                    if (DEBUG) Log.d(TAG, "done waiting for mWaitingUntilKeyguardVisible");
-                }
-            }
-        }
-    }
-
-    /**
-     * @see android.app.KeyguardManager#exitKeyguardSecurely
-     */
-    public void verifyUnlock(WindowManagerPolicy.OnKeyguardExitResult callback) {
-        synchronized (this) {
-            if (DEBUG) Log.d(TAG, "verifyUnlock");
-            if (!mUpdateMonitor.isDeviceProvisioned()) {
-                // don't allow this api when the device isn't provisioned
-                if (DEBUG) Log.d(TAG, "ignoring because device isn't provisioned");
-                callback.onKeyguardExitResult(false);
-            } else if (mExternallyEnabled) {
-                // this only applies when the user has externally disabled the
-                // keyguard.  this is unexpected and means the user is not
-                // using the api properly.
-                Log.w(TAG, "verifyUnlock called when not externally disabled");
-                callback.onKeyguardExitResult(false);
-            } else if (mExitSecureCallback != null) {
-                // already in progress with someone else
-                callback.onKeyguardExitResult(false);
-            } else {
-                mExitSecureCallback = callback;
-                verifyUnlockLocked();
-            }
-        }
-    }
-
-    /**
-     * Is the keyguard currently showing?
-     */
-    public boolean isShowing() {
-        return mShowing;
-    }
-
-    /**
-     * Is the keyguard currently showing and not being force hidden?
-     */
-    public boolean isShowingAndNotHidden() {
-        return mShowing && !mHidden;
-    }
-
-    /**
-     * Notify us when the keyguard is hidden by another window
-     */
-    public void setHidden(boolean isHidden) {
-        if (DEBUG) Log.d(TAG, "setHidden " + isHidden);
-        mHandler.removeMessages(SET_HIDDEN);
-        Message msg = mHandler.obtainMessage(SET_HIDDEN, (isHidden ? 1 : 0), 0);
-        mHandler.sendMessage(msg);
-    }
-
-    /**
-     * Handles SET_HIDDEN message sent by setHidden()
-     */
-    private void handleSetHidden(boolean isHidden) {
-        synchronized (KeyguardViewMediator.this) {
-            if (mHidden != isHidden) {
-                mHidden = isHidden;
-                updateActivityLockScreenState();
-                adjustUserActivityLocked();
-                adjustStatusBarLocked();
-            }
-        }
-    }
-
-    /**
-     * Used by PhoneWindowManager to enable the keyguard due to a user activity timeout.
-     * This must be safe to call from any thread and with any window manager locks held.
-     */
-    public void doKeyguardTimeout() {
-        mHandler.removeMessages(KEYGUARD_TIMEOUT);
-        Message msg = mHandler.obtainMessage(KEYGUARD_TIMEOUT);
-        mHandler.sendMessage(msg);
-    }
-
-    /**
-     * Given the state of the keyguard, is the input restricted?
-     * Input is restricted when the keyguard is showing, or when the keyguard
-     * was suppressed by an app that disabled the keyguard or we haven't been provisioned yet.
-     */
-    public boolean isInputRestricted() {
-        return mShowing || mNeedToReshowWhenReenabled || !mUpdateMonitor.isDeviceProvisioned();
-    }
-
-    /**
-     * Enable the keyguard if the settings are appropriate.  Return true if all
-     * work that will happen is done; returns false if the caller can wait for
-     * the keyguard to be shown.
-     */
-    private void doKeyguardLocked() {
-        // if another app is disabling us, don't show
-        if (!mExternallyEnabled) {
-            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
-
-            // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
-            // for an occasional ugly flicker in this situation:
-            // 1) receive a call with the screen on (no keyguard) or make a call
-            // 2) screen times out
-            // 3) user hits key to turn screen back on
-            // instead, we reenable the keyguard when we know the screen is off and the call
-            // ends (see the broadcast receiver below)
-            // TODO: clean this up when we have better support at the window manager level
-            // for apps that wish to be on top of the keyguard
-            return;
-        }
-
-        // if the keyguard is already showing, don't bother
-        if (mKeyguardViewManager.isShowing()) {
-            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
-            return;
-        }
-
-        // if the setup wizard hasn't run yet, don't show
-        final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim",
-                false);
-        final boolean provisioned = mUpdateMonitor.isDeviceProvisioned();
-        final IccCardConstants.State state = mUpdateMonitor.getSimState();
-        final boolean lockedOrMissing = state.isPinLocked()
-                || ((state == IccCardConstants.State.ABSENT
-                || state == IccCardConstants.State.PERM_DISABLED)
-                && requireSim);
-
-        if (!lockedOrMissing && !provisioned) {
-            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
-                    + " and the sim is not locked or missing");
-            return;
-        }
-
-        if (mLockPatternUtils.isLockScreenDisabled() && !lockedOrMissing) {
-            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
-            return;
-        }
-
-        if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
-        showLocked();
-    }
-
-    /**
-     * Send message to keyguard telling it to reset its state.
-     * @see #handleReset()
-     */
-    private void resetStateLocked() {
-        if (DEBUG) Log.d(TAG, "resetStateLocked");
-        Message msg = mHandler.obtainMessage(RESET);
-        mHandler.sendMessage(msg);
-    }
-
-    /**
-     * Send message to keyguard telling it to verify unlock
-     * @see #handleVerifyUnlock()
-     */
-    private void verifyUnlockLocked() {
-        if (DEBUG) Log.d(TAG, "verifyUnlockLocked");
-        mHandler.sendEmptyMessage(VERIFY_UNLOCK);
-    }
-
-
-    /**
-     * Send a message to keyguard telling it the screen just turned on.
-     * @see #onScreenTurnedOff(int)
-     * @see #handleNotifyScreenOff
-     */
-    private void notifyScreenOffLocked() {
-        if (DEBUG) Log.d(TAG, "notifyScreenOffLocked");
-        mHandler.sendEmptyMessage(NOTIFY_SCREEN_OFF);
-    }
-
-    /**
-     * Send a message to keyguard telling it the screen just turned on.
-     * @see #onScreenTurnedOn()
-     * @see #handleNotifyScreenOn
-     */
-    private void notifyScreenOnLocked(KeyguardViewManager.ShowListener showListener) {
-        if (DEBUG) Log.d(TAG, "notifyScreenOnLocked");
-        Message msg = mHandler.obtainMessage(NOTIFY_SCREEN_ON, showListener);
-        mHandler.sendMessage(msg);
-    }
-
-    /**
-     * Send message to keyguard telling it about a wake key so it can adjust
-     * its state accordingly and then poke the wake lock when it is ready.
-     * @param keyCode The wake key.
-     * @see #handleWakeWhenReady
-     * @see #onWakeKeyWhenKeyguardShowingTq(int)
-     */
-    private void wakeWhenReadyLocked(int keyCode) {
-        if (DBG_WAKE) Log.d(TAG, "wakeWhenReadyLocked(" + keyCode + ")");
-
-        /**
-         * acquire the handoff lock that will keep the cpu running.  this will
-         * be released once the keyguard has set itself up and poked the other wakelock
-         * in {@link #handleWakeWhenReady(int)}
-         */
-        mWakeAndHandOff.acquire();
-
-        Message msg = mHandler.obtainMessage(WAKE_WHEN_READY, keyCode, 0);
-        mHandler.sendMessage(msg);
-    }
-
-    /**
-     * Send message to keyguard telling it to show itself
-     * @see #handleShow()
-     */
-    private void showLocked() {
-        if (DEBUG) Log.d(TAG, "showLocked");
-        // ensure we stay awake until we are finished displaying the keyguard
-        mShowKeyguardWakeLock.acquire();
-        Message msg = mHandler.obtainMessage(SHOW);
-        mHandler.sendMessage(msg);
-    }
-
-    /**
-     * Send message to keyguard telling it to hide itself
-     * @see #handleHide()
-     */
-    private void hideLocked() {
-        if (DEBUG) Log.d(TAG, "hideLocked");
-        Message msg = mHandler.obtainMessage(HIDE);
-        mHandler.sendMessage(msg);
-    }
-
-    /** {@inheritDoc} */
-    public void onSimStateChanged(IccCardConstants.State simState) {
-        if (DEBUG) Log.d(TAG, "onSimStateChanged: " + simState);
-
-        switch (simState) {
-            case ABSENT:
-                // only force lock screen in case of missing sim if user hasn't
-                // gone through setup wizard
-                synchronized (this) {
-                    if (!mUpdateMonitor.isDeviceProvisioned()) {
-                        if (!isShowing()) {
-                            if (DEBUG) Log.d(TAG, "ICC_ABSENT isn't showing,"
-                                    + " we need to show the keyguard since the "
-                                    + "device isn't provisioned yet.");
-                            doKeyguardLocked();
-                        } else {
-                            resetStateLocked();
-                        }
-                    }
-                }
-                break;
-            case PIN_REQUIRED:
-            case PUK_REQUIRED:
-                synchronized (this) {
-                    if (!isShowing()) {
-                        if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't showing, "
-                                + "we need to show keyguard so user can enter their sim pin");
-                        doKeyguardLocked();
-                    } else {
-                        resetStateLocked();
-                    }
-                }
-                break;
-            case PERM_DISABLED:
-                synchronized (this) {
-                    if (!isShowing()) {
-                        if (DEBUG) Log.d(TAG, "PERM_DISABLED and "
-                              + "keygaurd isn't showing.");
-                        doKeyguardLocked();
-                    } else {
-                        if (DEBUG) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
-                              + "show permanently disabled message in lockscreen.");
-                        resetStateLocked();
-                    }
-                }
-                break;
-            case READY:
-                synchronized (this) {
-                    if (isShowing()) {
-                        resetStateLocked();
-                    }
-                }
-                break;
-        }
-    }
-
-    public boolean isSecure() {
-        return mKeyguardViewProperties.isSecure();
-    }
-
-    private void onUserSwitched(int userId) {
-        mLockPatternUtils.setCurrentUser(userId);
-        synchronized (KeyguardViewMediator.this) {
-            resetStateLocked();
-        }
-    }
-
-    private void onUserRemoved(int userId) {
-        mLockPatternUtils.removeUser(userId);
-    }
-
-    private BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
-                onUserSwitched(intent.getIntExtra(Intent.EXTRA_USERID, 0));
-            } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
-                onUserRemoved(intent.getIntExtra(Intent.EXTRA_USERID, 0));
-            }
-        }
-    };
-
-    private BroadcastReceiver mBroadCastReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            final String action = intent.getAction();
-            if (action.equals(DELAYED_KEYGUARD_ACTION)) {
-
-                int sequence = intent.getIntExtra("seq", 0);
-
-                if (DEBUG) Log.d(TAG, "received DELAYED_KEYGUARD_ACTION with seq = "
-                        + sequence + ", mDelayedShowingSequence = " + mDelayedShowingSequence);
-
-                synchronized (KeyguardViewMediator.this) {
-                    if (mDelayedShowingSequence == sequence) {
-                        // Don't play lockscreen SFX if the screen went off due to
-                        // timeout.
-                        mSuppressNextLockSound = true;
-
-                        doKeyguardLocked();
-                    }
-                }
-            } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
-                mPhoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
-
-                synchronized (KeyguardViewMediator.this) {
-                    if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)  // call ending
-                            && !mScreenOn                           // screen off
-                            && mExternallyEnabled) {                // not disabled by any app
-
-                        // note: this is a way to gracefully reenable the keyguard when the call
-                        // ends and the screen is off without always reenabling the keyguard
-                        // each time the screen turns off while in call (and having an occasional ugly
-                        // flicker while turning back on the screen and disabling the keyguard again).
-                        if (DEBUG) Log.d(TAG, "screen is off and call ended, let's make sure the "
-                                + "keyguard is showing");
-                        doKeyguardLocked();
-                    }
-                }
-            }
-        }
-    };
-
-
-    /**
-     * When a key is received when the screen is off and the keyguard is showing,
-     * we need to decide whether to actually turn on the screen, and if so, tell
-     * the keyguard to prepare itself and poke the wake lock when it is ready.
-     *
-     * The 'Tq' suffix is per the documentation in {@link WindowManagerPolicy}.
-     * Be sure not to take any action that takes a long time; any significant
-     * action should be posted to a handler.
-     *
-     * @param keyCode The keycode of the key that woke the device
-     * @param isDocked True if the device is in the dock
-     * @return Whether we poked the wake lock (and turned the screen on)
-     */
-    public boolean onWakeKeyWhenKeyguardShowingTq(int keyCode, boolean isDocked) {
-        if (DEBUG) Log.d(TAG, "onWakeKeyWhenKeyguardShowing(" + keyCode + ")");
-
-        if (isWakeKeyWhenKeyguardShowing(keyCode, isDocked)) {
-            // give the keyguard view manager a chance to adjust the state of the
-            // keyguard based on the key that woke the device before poking
-            // the wake lock
-            wakeWhenReadyLocked(keyCode);
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * When the keyguard is showing we ignore some keys that might otherwise typically
-     * be considered wake keys.  We filter them out here.
-     *
-     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
-     * is always considered a wake key.
-     */
-    private boolean isWakeKeyWhenKeyguardShowing(int keyCode, boolean isDocked) {
-        switch (keyCode) {
-            // ignore volume keys unless docked
-            case KeyEvent.KEYCODE_VOLUME_UP:
-            case KeyEvent.KEYCODE_VOLUME_DOWN:
-            case KeyEvent.KEYCODE_VOLUME_MUTE:
-                return isDocked;
-
-            // ignore media and camera keys
-            case KeyEvent.KEYCODE_MUTE:
-            case KeyEvent.KEYCODE_HEADSETHOOK:
-            case KeyEvent.KEYCODE_MEDIA_PLAY:
-            case KeyEvent.KEYCODE_MEDIA_PAUSE:
-            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
-            case KeyEvent.KEYCODE_MEDIA_STOP:
-            case KeyEvent.KEYCODE_MEDIA_NEXT:
-            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
-            case KeyEvent.KEYCODE_MEDIA_REWIND:
-            case KeyEvent.KEYCODE_MEDIA_RECORD:
-            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
-            case KeyEvent.KEYCODE_CAMERA:
-                return false;
-        }
-        return true;
-    }
-
-    /**
-     * When a wake motion such as an external mouse movement is received when the screen
-     * is off and the keyguard is showing, we need to decide whether to actually turn
-     * on the screen, and if so, tell the keyguard to prepare itself and poke the wake
-     * lock when it is ready.
-     *
-     * The 'Tq' suffix is per the documentation in {@link WindowManagerPolicy}.
-     * Be sure not to take any action that takes a long time; any significant
-     * action should be posted to a handler.
-     *
-     * @return Whether we poked the wake lock (and turned the screen on)
-     */
-    public boolean onWakeMotionWhenKeyguardShowingTq() {
-        if (DEBUG) Log.d(TAG, "onWakeMotionWhenKeyguardShowing()");
-
-        // give the keyguard view manager a chance to adjust the state of the
-        // keyguard based on the key that woke the device before poking
-        // the wake lock
-        wakeWhenReadyLocked(KeyEvent.KEYCODE_UNKNOWN);
-        return true;
-    }
-
-    /**
-     * Callbacks from {@link KeyguardViewManager}.
-     */
-
-    /** {@inheritDoc} */
-    public void pokeWakelock() {
-        pokeWakelock(AWAKE_INTERVAL_DEFAULT_MS);
-    }
-
-    /** {@inheritDoc} */
-    public void pokeWakelock(int holdMs) {
-        synchronized (this) {
-            if (DBG_WAKE) Log.d(TAG, "pokeWakelock(" + holdMs + ")");
-            mWakeLock.acquire();
-            mHandler.removeMessages(TIMEOUT);
-            mWakelockSequence++;
-            Message msg = mHandler.obtainMessage(TIMEOUT, mWakelockSequence, 0);
-            mHandler.sendMessageDelayed(msg, holdMs);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @see #handleKeyguardDone
-     */
-    public void keyguardDone(boolean authenticated) {
-        keyguardDone(authenticated, true);
-    }
-
-    public void keyguardDone(boolean authenticated, boolean wakeup) {
-        synchronized (this) {
-            EventLog.writeEvent(70000, 2);
-            if (DEBUG) Log.d(TAG, "keyguardDone(" + authenticated + ")");
-            Message msg = mHandler.obtainMessage(KEYGUARD_DONE);
-            msg.arg1 = wakeup ? 1 : 0;
-            mHandler.sendMessage(msg);
-
-            if (authenticated) {
-                mUpdateMonitor.clearFailedAttempts();
-            }
-
-            if (mExitSecureCallback != null) {
-                mExitSecureCallback.onKeyguardExitResult(authenticated);
-                mExitSecureCallback = null;
-
-                if (authenticated) {
-                    // after succesfully exiting securely, no need to reshow
-                    // the keyguard when they've released the lock
-                    mExternallyEnabled = true;
-                    mNeedToReshowWhenReenabled = false;
-                }
-            }
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @see #handleKeyguardDoneDrawing
-     */
-    public void keyguardDoneDrawing() {
-        mHandler.sendEmptyMessage(KEYGUARD_DONE_DRAWING);
-    }
-
-    /**
-     * This handler will be associated with the policy thread, which will also
-     * be the UI thread of the keyguard.  Since the apis of the policy, and therefore
-     * this class, can be called by other threads, any action that directly
-     * interacts with the keyguard ui should be posted to this handler, rather
-     * than called directly.
-     */
-    private Handler mHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case TIMEOUT:
-                    handleTimeout(msg.arg1);
-                    return ;
-                case SHOW:
-                    handleShow();
-                    return ;
-                case HIDE:
-                    handleHide();
-                    return ;
-                case RESET:
-                    handleReset();
-                    return ;
-                case VERIFY_UNLOCK:
-                    handleVerifyUnlock();
-                    return;
-                case NOTIFY_SCREEN_OFF:
-                    handleNotifyScreenOff();
-                    return;
-                case NOTIFY_SCREEN_ON:
-                    handleNotifyScreenOn((KeyguardViewManager.ShowListener)msg.obj);
-                    return;
-                case WAKE_WHEN_READY:
-                    handleWakeWhenReady(msg.arg1);
-                    return;
-                case KEYGUARD_DONE:
-                    handleKeyguardDone(msg.arg1 != 0);
-                    return;
-                case KEYGUARD_DONE_DRAWING:
-                    handleKeyguardDoneDrawing();
-                    return;
-                case KEYGUARD_DONE_AUTHENTICATING:
-                    keyguardDone(true);
-                    return;
-                case SET_HIDDEN:
-                    handleSetHidden(msg.arg1 != 0);
-                    break;
-                case KEYGUARD_TIMEOUT:
-                    synchronized (KeyguardViewMediator.this) {
-                        doKeyguardLocked();
-                    }
-                    break;
-            }
-        }
-    };
-
-    /**
-     * @see #keyguardDone
-     * @see #KEYGUARD_DONE
-     */
-    private void handleKeyguardDone(boolean wakeup) {
-        if (DEBUG) Log.d(TAG, "handleKeyguardDone");
-        handleHide();
-        if (wakeup) {
-            mPM.userActivity(SystemClock.uptimeMillis(), true);
-        }
-        mWakeLock.release();
-        mContext.sendBroadcast(mUserPresentIntent);
-    }
-
-    /**
-     * @see #keyguardDoneDrawing
-     * @see #KEYGUARD_DONE_DRAWING
-     */
-    private void handleKeyguardDoneDrawing() {
-        synchronized(this) {
-            if (false) Log.d(TAG, "handleKeyguardDoneDrawing");
-            if (mWaitingUntilKeyguardVisible) {
-                if (DEBUG) Log.d(TAG, "handleKeyguardDoneDrawing: notifying mWaitingUntilKeyguardVisible");
-                mWaitingUntilKeyguardVisible = false;
-                notifyAll();
-
-                // there will usually be two of these sent, one as a timeout, and one
-                // as a result of the callback, so remove any remaining messages from
-                // the queue
-                mHandler.removeMessages(KEYGUARD_DONE_DRAWING);
-            }
-        }
-    }
-
-    /**
-     * Handles the message sent by {@link #pokeWakelock}
-     * @param seq used to determine if anything has changed since the message
-     *   was sent.
-     * @see #TIMEOUT
-     */
-    private void handleTimeout(int seq) {
-        synchronized (KeyguardViewMediator.this) {
-            if (DEBUG) Log.d(TAG, "handleTimeout");
-            if (seq == mWakelockSequence) {
-                mWakeLock.release();
-            }
-        }
-    }
-
-    private void playSounds(boolean locked) {
-        // User feedback for keyguard.
-
-        if (mSuppressNextLockSound) {
-            mSuppressNextLockSound = false;
-            return;
-        }
-
-        final ContentResolver cr = mContext.getContentResolver();
-        if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) {
-            final int whichSound = locked
-                ? mLockSoundId
-                : mUnlockSoundId;
-            mLockSounds.stop(mLockSoundStreamId);
-            // Init mAudioManager
-            if (mAudioManager == null) {
-                mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-                if (mAudioManager == null) return;
-                mMasterStreamType = mAudioManager.getMasterStreamType();
-            }
-            // If the stream is muted, don't play the sound
-            if (mAudioManager.isStreamMute(mMasterStreamType)) return;
-
-            mLockSoundStreamId = mLockSounds.play(whichSound,
-                    mLockSoundVolume, mLockSoundVolume, 1/*priortiy*/, 0/*loop*/, 1.0f/*rate*/);
-        }
-    }
-
-    private void updateActivityLockScreenState() {
-        try {
-            ActivityManagerNative.getDefault().setLockScreenShown(
-                    mShowing && !mHidden);
-        } catch (RemoteException e) {
-        }
-    }
-
-    /**
-     * Handle message sent by {@link #showLocked}.
-     * @see #SHOW
-     */
-    private void handleShow() {
-        synchronized (KeyguardViewMediator.this) {
-            if (DEBUG) Log.d(TAG, "handleShow");
-            if (!mSystemReady) return;
-
-            mKeyguardViewManager.show();
-            mShowing = true;
-            updateActivityLockScreenState();
-            adjustUserActivityLocked();
-            adjustStatusBarLocked();
-            try {
-                ActivityManagerNative.getDefault().closeSystemDialogs("lock");
-            } catch (RemoteException e) {
-            }
-
-            // Do this at the end to not slow down display of the keyguard.
-            playSounds(true);
-
-            mShowKeyguardWakeLock.release();
-        }
-    }
-
-    /**
-     * Handle message sent by {@link #hideLocked()}
-     * @see #HIDE
-     */
-    private void handleHide() {
-        synchronized (KeyguardViewMediator.this) {
-            if (DEBUG) Log.d(TAG, "handleHide");
-            if (mWakeAndHandOff.isHeld()) {
-                Log.w(TAG, "attempt to hide the keyguard while waking, ignored");
-                return;
-            }
-
-            // only play "unlock" noises if not on a call (since the incall UI
-            // disables the keyguard)
-            if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) {
-                playSounds(false);
-            }
-
-            mKeyguardViewManager.hide();
-            mShowing = false;
-            updateActivityLockScreenState();
-            adjustUserActivityLocked();
-            adjustStatusBarLocked();
-        }
-    }
-
-    private void adjustUserActivityLocked() {
-        // disable user activity if we are shown and not hidden
-        if (DEBUG) Log.d(TAG, "adjustUserActivityLocked mShowing: " + mShowing + " mHidden: " + mHidden);
-        boolean enabled = !mShowing || mHidden;
-        mRealPowerManager.enableUserActivity(enabled);
-        if (!enabled && mScreenOn) {
-            // reinstate our short screen timeout policy
-            pokeWakelock();
-        }
-    }
-
-    private void adjustStatusBarLocked() {
-        if (mStatusBarManager == null) {
-            mStatusBarManager = (StatusBarManager)
-                    mContext.getSystemService(Context.STATUS_BAR_SERVICE);
-        }
-        if (mStatusBarManager == null) {
-            Log.w(TAG, "Could not get status bar manager");
-        } else {
-            if (mShowLockIcon) {
-                // Give feedback to user when secure keyguard is active and engaged
-                if (mShowing && isSecure()) {
-                    if (!mShowingLockIcon) {
-                        String contentDescription = mContext.getString(
-                                com.android.internal.R.string.status_bar_device_locked);
-                        mStatusBarManager.setIcon("secure",
-                                com.android.internal.R.drawable.stat_sys_secure, 0,
-                                contentDescription);
-                        mShowingLockIcon = true;
-                    }
-                } else {
-                    if (mShowingLockIcon) {
-                        mStatusBarManager.removeIcon("secure");
-                        mShowingLockIcon = false;
-                    }
-                }
-            }
-
-            // Disable aspects of the system/status/navigation bars that must not be re-enabled by
-            // windows that appear on top, ever
-            int flags = StatusBarManager.DISABLE_NONE;
-            if (mShowing) {
-                // disable navigation status bar components (home, recents) if lock screen is up
-                flags |= StatusBarManager.DISABLE_RECENT;
-                if (isSecure() || !ENABLE_INSECURE_STATUS_BAR_EXPAND) {
-                    // showing secure lockscreen; disable expanding.
-                    flags |= StatusBarManager.DISABLE_EXPAND;
-                }
-                if (isSecure()) {
-                    // showing secure lockscreen; disable ticker.
-                    flags |= StatusBarManager.DISABLE_NOTIFICATION_TICKER;
-                }
-            }
-
-            if (DEBUG) {
-                Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mHidden=" + mHidden
-                        + " isSecure=" + isSecure() + " --> flags=0x" + Integer.toHexString(flags));
-            }
-
-            mStatusBarManager.disable(flags);
-        }
-    }
-
-    /**
-     * Handle message sent by {@link #wakeWhenReadyLocked(int)}
-     * @param keyCode The key that woke the device.
-     * @see #WAKE_WHEN_READY
-     */
-    private void handleWakeWhenReady(int keyCode) {
-        synchronized (KeyguardViewMediator.this) {
-            if (DBG_WAKE) Log.d(TAG, "handleWakeWhenReady(" + keyCode + ")");
-
-            // this should result in a call to 'poke wakelock' which will set a timeout
-            // on releasing the wakelock
-            if (!mKeyguardViewManager.wakeWhenReadyTq(keyCode)) {
-                // poke wakelock ourselves if keyguard is no longer active
-                Log.w(TAG, "mKeyguardViewManager.wakeWhenReadyTq did not poke wake lock, so poke it ourselves");
-                pokeWakelock();
-            }
-
-            /**
-             * Now that the keyguard is ready and has poked the wake lock, we can
-             * release the handoff wakelock
-             */
-            mWakeAndHandOff.release();
-
-            if (!mWakeLock.isHeld()) {
-                Log.w(TAG, "mWakeLock not held in mKeyguardViewManager.wakeWhenReadyTq");
-            }
-        }
-    }
-
-    /**
-     * Handle message sent by {@link #resetStateLocked()}
-     * @see #RESET
-     */
-    private void handleReset() {
-        synchronized (KeyguardViewMediator.this) {
-            if (DEBUG) Log.d(TAG, "handleReset");
-            mKeyguardViewManager.reset();
-        }
-    }
-
-    /**
-     * Handle message sent by {@link #verifyUnlock}
-     * @see #RESET
-     */
-    private void handleVerifyUnlock() {
-        synchronized (KeyguardViewMediator.this) {
-            if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
-            mKeyguardViewManager.verifyUnlock();
-            mShowing = true;
-            updateActivityLockScreenState();
-        }
-    }
-
-    /**
-     * Handle message sent by {@link #notifyScreenOffLocked()}
-     * @see #NOTIFY_SCREEN_OFF
-     */
-    private void handleNotifyScreenOff() {
-        synchronized (KeyguardViewMediator.this) {
-            if (DEBUG) Log.d(TAG, "handleNotifyScreenOff");
-            mKeyguardViewManager.onScreenTurnedOff();
-        }
-    }
-
-    /**
-     * Handle message sent by {@link #notifyScreenOnLocked()}
-     * @see #NOTIFY_SCREEN_ON
-     */
-    private void handleNotifyScreenOn(KeyguardViewManager.ShowListener showListener) {
-        synchronized (KeyguardViewMediator.this) {
-            if (DEBUG) Log.d(TAG, "handleNotifyScreenOn");
-            mKeyguardViewManager.onScreenTurnedOn(showListener);
-        }
-    }
-
-}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewProperties.java b/policy/src/com/android/internal/policy/impl/KeyguardViewProperties.java
deleted file mode 100644
index 51b7f1e..0000000
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewProperties.java
+++ /dev/null
@@ -1,47 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import android.content.Context;
-
-/**
- * Defines operations necessary for showing a keyguard, including how to create
- * it, and various properties that are useful to be able to query independant
- * of whether the keyguard instance is around or not.
- */
-public interface KeyguardViewProperties {
-
-    /**
-     * Create a keyguard view.
-     * @param context the context to use when creating the view.
-     * @param callback keyguard callback object for pokewakelock(), etc.
-     * @param updateMonitor configuration may be based on this.
-     * @param controller for talking back with the containing window.
-     * @return the view.
-     */
-    KeyguardViewBase createKeyguardView(Context context,
-            KeyguardViewCallback mCallback, KeyguardUpdateMonitor updateMonitor,
-            KeyguardWindowController controller);
-
-    /**
-     * Would the keyguard be secure right now?
-     * @return Whether the keyguard is currently secure, meaning it will block
-     *   the user from getting past it until the user enters some sort of PIN.
-     */
-    boolean isSecure();
-
-}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardWindowController.java b/policy/src/com/android/internal/policy/impl/KeyguardWindowController.java
deleted file mode 100644
index 4ad48fb..0000000
--- a/policy/src/com/android/internal/policy/impl/KeyguardWindowController.java
+++ /dev/null
@@ -1,29 +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.
- */
-
-package com.android.internal.policy.impl;
-
-/**
- * Interface passed to the keyguard view, for it to call up to control
- * its containing window.
- */
-public interface KeyguardWindowController {
-    /**
-     * Control whether the window needs input -- that is if it has
-     * text fields and thus should allow input method interaction.
-     */
-    void setNeedsInput(boolean needsInput);
-}
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
deleted file mode 100644
index 041211c..0000000
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ /dev/null
@@ -1,1227 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import com.android.internal.R;
-import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallback;
-import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl;
-import com.android.internal.policy.impl.LockPatternKeyguardView.UnlockMode;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.LockScreenWidgetCallback;
-import com.android.internal.widget.LockScreenWidgetInterface;
-import com.android.internal.widget.TransportControlView;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.accounts.AccountManagerCallback;
-import android.accounts.AccountManagerFuture;
-import android.accounts.AuthenticatorException;
-import android.accounts.OperationCanceledException;
-import android.app.AlertDialog;
-import android.app.admin.DevicePolicyManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.PixelFormat;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.os.PowerManager;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Slog;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.WindowManager;
-import android.view.accessibility.AccessibilityManager;
-
-import java.io.IOException;
-
-
-/**
- * The host view for all of the screens of the pattern unlock screen.  There are
- * two {@link Mode}s of operation, lock and unlock.  This will show the appropriate
- * screen, and listen for callbacks via
- * {@link com.android.internal.policy.impl.KeyguardScreenCallback}
- * from the current screen.
- *
- * This view, in turn, communicates back to
- * {@link com.android.internal.policy.impl.KeyguardViewManager}
- * via its {@link com.android.internal.policy.impl.KeyguardViewCallback}, as appropriate.
- */
-public class LockPatternKeyguardView extends KeyguardViewBase {
-
-    private static final int TRANSPORT_USERACTIVITY_TIMEOUT = 10000;
-
-    static final boolean DEBUG_CONFIGURATION = false;
-
-    // time after launching EmergencyDialer before the screen goes blank.
-    private static final int EMERGENCY_CALL_TIMEOUT = 10000;
-
-    // intent action for launching emergency dialer activity.
-    static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
-
-    private static final boolean DEBUG = false;
-    private static final String TAG = "LockPatternKeyguardView";
-
-    private final KeyguardUpdateMonitor mUpdateMonitor;
-    private final KeyguardWindowController mWindowController;
-
-    private View mLockScreen;
-    private View mUnlockScreen;
-
-    private boolean mScreenOn;
-    private boolean mWindowFocused = false;
-    private boolean mEnableFallback = false; // assume no fallback UI until we know better
-
-    private boolean mShowLockBeforeUnlock = false;
-
-    // Interface to a biometric sensor that can optionally be used to unlock the device
-    private BiometricSensorUnlock mBiometricUnlock;
-    private final Object mBiometricUnlockStartupLock = new Object();
-    // Long enough to stay visible while dialer comes up
-    // Short enough to not be visible if the user goes back immediately
-    private final int BIOMETRIC_AREA_EMERGENCY_DIALER_TIMEOUT = 1000;
-
-    private boolean mRequiresSim;
-    // True if the biometric unlock should not be displayed.  For example, if there is an overlay on
-    // lockscreen or the user is plugging in / unplugging the device.
-    private boolean mSuppressBiometricUnlock;
-    //True if a dialog is currently displaying on top of this window
-    //Unlike other overlays, this does not close with a power button cycle
-    private boolean mHasDialog = false;
-    //True if this device is currently plugged in
-    private boolean mPluggedIn;
-    // True the first time lockscreen is showing after boot
-    private static boolean sIsFirstAppearanceAfterBoot = true;
-
-    // The music control widget
-    private TransportControlView mTransportControlView;
-
-    private Parcelable mSavedState;
-
-    /**
-     * Either a lock screen (an informational keyguard screen), or an unlock
-     * screen (a means for unlocking the device) is shown at any given time.
-     */
-    enum Mode {
-        LockScreen,
-        UnlockScreen
-    }
-
-    /**
-     * The different types screens available for {@link Mode#UnlockScreen}.
-     * @see com.android.internal.policy.impl.LockPatternKeyguardView#getUnlockMode()
-     */
-    enum UnlockMode {
-
-        /**
-         * Unlock by drawing a pattern.
-         */
-        Pattern,
-
-        /**
-         * Unlock by entering a sim pin.
-         */
-        SimPin,
-
-        /**
-         * Unlock by entering a sim puk.
-         */
-        SimPuk,
-
-        /**
-         * Unlock by entering an account's login and password.
-         */
-        Account,
-
-        /**
-         * Unlock by entering a password or PIN
-         */
-        Password,
-
-        /**
-         * Unknown (uninitialized) value
-         */
-        Unknown
-    }
-
-    /**
-     * The current mode.
-     */
-    private Mode mMode = Mode.LockScreen;
-
-    /**
-     * Keeps track of what mode the current unlock screen is (cached from most recent computation in
-     * {@link #getUnlockMode}).
-     */
-    private UnlockMode mUnlockScreenMode = UnlockMode.Unknown;
-
-    private boolean mForgotPattern;
-
-    /**
-     * If true, it means we are in the process of verifying that the user
-     * can get past the lock screen per {@link #verifyUnlock()}
-     */
-    private boolean mIsVerifyUnlockOnly = false;
-
-    /**
-     * Used to lookup the state of the lock pattern
-     */
-    private final LockPatternUtils mLockPatternUtils;
-
-    /**
-     * The current configuration.
-     */
-    private Configuration mConfiguration;
-
-    private Runnable mRecreateRunnable = new Runnable() {
-        public void run() {
-            Mode mode = mMode;
-            // If we were previously in a locked state but now it's Unknown, it means the phone
-            // was previously locked because of SIM state and has since been resolved. This
-            // bit of code checks this condition and dismisses keyguard.
-            boolean dismissAfterCreation = false;
-            if (mode == Mode.UnlockScreen && getUnlockMode() == UnlockMode.Unknown) {
-                if (DEBUG) Log.v(TAG, "Switch to Mode.LockScreen because SIM unlocked");
-                mode = Mode.LockScreen;
-                dismissAfterCreation = true;
-            }
-            updateScreen(mode, true);
-            restoreWidgetState();
-            if (dismissAfterCreation) {
-                mKeyguardScreenCallback.keyguardDone(false);
-            }
-        }
-    };
-
-    private LockScreenWidgetCallback mWidgetCallback = new LockScreenWidgetCallback() {
-        public void userActivity(View self) {
-            mKeyguardScreenCallback.pokeWakelock(TRANSPORT_USERACTIVITY_TIMEOUT);
-        }
-
-        public void requestShow(View view) {
-            if (DEBUG) Log.v(TAG, "View " + view + " requested show transports");
-            view.setVisibility(View.VISIBLE);
-
-            // TODO: examine all widgets to derive clock status
-            mUpdateMonitor.reportClockVisible(false);
-
-            // If there's not a bg protection view containing the transport, then show a black
-            // background. Otherwise, allow the normal background to show.
-            if (findViewById(R.id.transport_bg_protect) == null) {
-                // TODO: We should disable the wallpaper instead
-                setBackgroundColor(0xff000000);
-            } else {
-                resetBackground();
-            }
-        }
-
-        public void requestHide(View view) {
-            if (DEBUG) Log.v(TAG, "View " + view + " requested hide transports");
-            view.setVisibility(View.GONE);
-
-            // TODO: examine all widgets to derive clock status
-            mUpdateMonitor.reportClockVisible(true);
-            resetBackground();
-        }
-
-        public boolean isVisible(View self) {
-            // TODO: this should be up to the lockscreen to determine if the view
-            // is currently showing. The idea is it can be used for the widget to
-            // avoid doing work if it's not visible. For now just returns the view's
-            // actual visibility.
-            return self.getVisibility() == View.VISIBLE;
-        }
-    };
-
-    /**
-     * @return Whether we are stuck on the lock screen because the sim is
-     *   missing.
-     */
-    private boolean stuckOnLockScreenBecauseSimMissing() {
-        return mRequiresSim
-                && (!mUpdateMonitor.isDeviceProvisioned())
-                && (mUpdateMonitor.getSimState() == IccCardConstants.State.ABSENT ||
-                    mUpdateMonitor.getSimState() == IccCardConstants.State.PERM_DISABLED);
-    }
-
-    /**
-     * The current {@link KeyguardScreen} will use this to communicate back to us.
-     */
-    KeyguardScreenCallback mKeyguardScreenCallback = new KeyguardScreenCallback() {
-
-        public void goToLockScreen() {
-            mForgotPattern = false;
-            if (mIsVerifyUnlockOnly) {
-                // navigating away from unlock screen during verify mode means
-                // we are done and the user failed to authenticate.
-                mIsVerifyUnlockOnly = false;
-                getCallback().keyguardDone(false);
-            } else {
-                updateScreen(Mode.LockScreen, false);
-            }
-        }
-
-        public void goToUnlockScreen() {
-            final IccCardConstants.State simState = mUpdateMonitor.getSimState();
-            if (stuckOnLockScreenBecauseSimMissing()
-                     || (simState == IccCardConstants.State.PUK_REQUIRED
-                         && !mLockPatternUtils.isPukUnlockScreenEnable())){
-                // stuck on lock screen when sim missing or
-                // puk'd but puk unlock screen is disabled
-                return;
-            }
-            if (!isSecure()) {
-                getCallback().keyguardDone(true);
-            } else {
-                updateScreen(Mode.UnlockScreen, false);
-            }
-        }
-
-        public void forgotPattern(boolean isForgotten) {
-            if (mEnableFallback) {
-                mForgotPattern = isForgotten;
-                updateScreen(Mode.UnlockScreen, false);
-            }
-        }
-
-        public boolean isSecure() {
-            return LockPatternKeyguardView.this.isSecure();
-        }
-
-        public boolean isVerifyUnlockOnly() {
-            return mIsVerifyUnlockOnly;
-        }
-
-        public void recreateMe(Configuration config) {
-            if (DEBUG) Log.v(TAG, "recreateMe()");
-            removeCallbacks(mRecreateRunnable);
-            post(mRecreateRunnable);
-        }
-
-        public void takeEmergencyCallAction() {
-            mSuppressBiometricUnlock = true;
-
-            if (mBiometricUnlock != null) {
-                if (mBiometricUnlock.isRunning()) {
-                    // Continue covering backup lock until dialer comes up or call is resumed
-                    mBiometricUnlock.show(BIOMETRIC_AREA_EMERGENCY_DIALER_TIMEOUT);
-                }
-
-                // We must ensure the biometric unlock is stopped when emergency call is pressed
-                mBiometricUnlock.stop();
-            }
-
-            pokeWakelock(EMERGENCY_CALL_TIMEOUT);
-            if (TelephonyManager.getDefault().getCallState()
-                    == TelephonyManager.CALL_STATE_OFFHOOK) {
-                mLockPatternUtils.resumeCall();
-            } else {
-                Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
-                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-                getContext().startActivity(intent);
-            }
-        }
-
-        public void pokeWakelock() {
-            getCallback().pokeWakelock();
-        }
-
-        public void pokeWakelock(int millis) {
-            getCallback().pokeWakelock(millis);
-        }
-
-        public void keyguardDone(boolean authenticated) {
-            getCallback().keyguardDone(authenticated);
-            mSavedState = null; // clear state so we re-establish when locked again
-        }
-
-        public void keyguardDoneDrawing() {
-            // irrelevant to keyguard screen, they shouldn't be calling this
-        }
-
-        public void reportFailedUnlockAttempt() {
-            mUpdateMonitor.reportFailedAttempt();
-            final int failedAttempts = mUpdateMonitor.getFailedAttempts();
-            if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts +
-                " (enableFallback=" + mEnableFallback + ")");
-
-            final boolean usingPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality()
-                    == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
-
-            final int failedAttemptsBeforeWipe = mLockPatternUtils.getDevicePolicyManager()
-                    .getMaximumFailedPasswordsForWipe(null);
-
-            final int failedAttemptWarning = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
-                    - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
-
-            final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ?
-                    (failedAttemptsBeforeWipe - failedAttempts)
-                    : Integer.MAX_VALUE; // because DPM returns 0 if no restriction
-
-            if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {
-                // If we reach this code, it means the user has installed a DevicePolicyManager
-                // that requests device wipe after N attempts.  Once we get below the grace
-                // period, we'll post this dialog every time as a clear warning until the
-                // bombshell hits and the device is wiped.
-                if (remainingBeforeWipe > 0) {
-                    showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe);
-                } else {
-                    // Too many attempts. The device will be wiped shortly.
-                    Slog.i(TAG, "Too many unlock attempts; device will be wiped!");
-                    showWipeDialog(failedAttempts);
-                }
-            } else {
-                boolean showTimeout =
-                    (failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0;
-                if (usingPattern && mEnableFallback) {
-                    if (failedAttempts == failedAttemptWarning) {
-                        showAlmostAtAccountLoginDialog();
-                        showTimeout = false; // don't show both dialogs
-                    } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
-                        mLockPatternUtils.setPermanentlyLocked(true);
-                        updateScreen(mMode, false);
-                        // don't show timeout dialog because we show account unlock screen next
-                        showTimeout = false;
-                    }
-                }
-                if (showTimeout) {
-                    showTimeoutDialog();
-                }
-            }
-            mLockPatternUtils.reportFailedPasswordAttempt();
-        }
-
-        public boolean doesFallbackUnlockScreenExist() {
-            return mEnableFallback;
-        }
-
-        public void reportSuccessfulUnlockAttempt() {
-            mLockPatternUtils.reportSuccessfulPasswordAttempt();
-        }
-    };
-
-    /**
-     * @param context Used to inflate, and create views.
-     * @param callback Keyguard callback object for pokewakelock(), etc.
-     * @param updateMonitor Knows the state of the world, and passed along to each
-     *   screen so they can use the knowledge, and also register for callbacks
-     *   on dynamic information.
-     * @param lockPatternUtils Used to look up state of lock pattern.
-     */
-    public LockPatternKeyguardView(
-            Context context, KeyguardViewCallback callback, KeyguardUpdateMonitor updateMonitor,
-            LockPatternUtils lockPatternUtils, KeyguardWindowController controller) {
-        super(context, callback);
-
-        mConfiguration = context.getResources().getConfiguration();
-        mEnableFallback = false;
-        mRequiresSim = TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim"));
-        mUpdateMonitor = updateMonitor;
-        mLockPatternUtils = lockPatternUtils;
-        mWindowController = controller;
-        mSuppressBiometricUnlock = sIsFirstAppearanceAfterBoot;
-        sIsFirstAppearanceAfterBoot = false;
-        mPluggedIn = mUpdateMonitor.isDevicePluggedIn();
-        mScreenOn = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)).isScreenOn();
-        mUpdateMonitor.registerInfoCallback(mInfoCallback);
-
-        /**
-         * We'll get key events the current screen doesn't use. see
-         * {@link KeyguardViewBase#onKeyDown(int, android.view.KeyEvent)}
-         */
-        setFocusableInTouchMode(true);
-        setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
-
-        updateScreen(getInitialMode(), false);
-        maybeEnableFallback(context);
-    }
-
-    private class AccountAnalyzer implements AccountManagerCallback<Bundle> {
-        private final AccountManager mAccountManager;
-        private final Account[] mAccounts;
-        private int mAccountIndex;
-
-        private AccountAnalyzer(AccountManager accountManager) {
-            mAccountManager = accountManager;
-            mAccounts = accountManager.getAccountsByType("com.google");
-        }
-
-        private void next() {
-            // if we are ready to enable the fallback or if we depleted the list of accounts
-            // then finish and get out
-            if (mEnableFallback || mAccountIndex >= mAccounts.length) {
-                if (mUnlockScreen == null) {
-                    if (DEBUG) Log.w(TAG, "no unlock screen when trying to enable fallback");
-                } else if (mUnlockScreen instanceof PatternUnlockScreen) {
-                    ((PatternUnlockScreen)mUnlockScreen).setEnableFallback(mEnableFallback);
-                }
-                return;
-            }
-
-            // lookup the confirmCredentials intent for the current account
-            mAccountManager.confirmCredentials(mAccounts[mAccountIndex], null, null, this, null);
-        }
-
-        public void start() {
-            mEnableFallback = false;
-            mAccountIndex = 0;
-            next();
-        }
-
-        public void run(AccountManagerFuture<Bundle> future) {
-            try {
-                Bundle result = future.getResult();
-                if (result.getParcelable(AccountManager.KEY_INTENT) != null) {
-                    mEnableFallback = true;
-                }
-            } catch (OperationCanceledException e) {
-                // just skip the account if we are unable to query it
-            } catch (IOException e) {
-                // just skip the account if we are unable to query it
-            } catch (AuthenticatorException e) {
-                // just skip the account if we are unable to query it
-            } finally {
-                mAccountIndex++;
-                next();
-            }
-        }
-    }
-
-    private void maybeEnableFallback(Context context) {
-        // Ask the account manager if we have an account that can be used as a
-        // fallback in case the user forgets his pattern.
-        AccountAnalyzer accountAnalyzer = new AccountAnalyzer(AccountManager.get(context));
-        accountAnalyzer.start();
-    }
-
-
-    // TODO:
-    // This overloaded method was added to workaround a race condition in the framework between
-    // notification for orientation changed, layout() and switching resources.  This code attempts
-    // to avoid drawing the incorrect layout while things are in transition.  The method can just
-    // be removed once the race condition is fixed. See bugs 2262578 and 2292713.
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        if (DEBUG) Log.v(TAG, "*** dispatchDraw() time: " + SystemClock.elapsedRealtime());
-        super.dispatchDraw(canvas);
-    }
-
-    @Override
-    public void reset() {
-        mIsVerifyUnlockOnly = false;
-        mForgotPattern = false;
-        if (DEBUG) Log.v(TAG, "reset()");
-        post(mRecreateRunnable);
-    }
-
-    @Override
-    public void onScreenTurnedOff() {
-        if (DEBUG) Log.d(TAG, "screen off");
-        mScreenOn = false;
-        mForgotPattern = false;
-
-        // Emulate activity life-cycle for both lock and unlock screen.
-        if (mLockScreen != null) {
-            ((KeyguardScreen) mLockScreen).onPause();
-        }
-        if (mUnlockScreen != null) {
-            ((KeyguardScreen) mUnlockScreen).onPause();
-        }
-
-        saveWidgetState();
-
-        if (mBiometricUnlock != null) {
-            // The biometric unlock must stop when screen turns off.
-            mBiometricUnlock.stop();
-        }
-    }
-
-    @Override
-    public void onScreenTurnedOn() {
-        if (DEBUG) Log.d(TAG, "screen on");
-        boolean startBiometricUnlock = false;
-        // Start the biometric unlock if and only if the screen is both on and focused
-        synchronized(mBiometricUnlockStartupLock) {
-            mScreenOn = true;
-            startBiometricUnlock = mWindowFocused;
-        }
-
-        show();
-
-        restoreWidgetState();
-
-        if (mBiometricUnlock != null && startBiometricUnlock) {
-            maybeStartBiometricUnlock();
-        }
-    }
-
-    private void saveWidgetState() {
-        if (mTransportControlView != null) {
-            if (DEBUG) Log.v(TAG, "Saving widget state");
-            mSavedState = mTransportControlView.onSaveInstanceState();
-        }
-    }
-
-    private void restoreWidgetState() {
-        if (mTransportControlView != null) {
-            if (DEBUG) Log.v(TAG, "Restoring widget state");
-            if (mSavedState != null) {
-                mTransportControlView.onRestoreInstanceState(mSavedState);
-            }
-        }
-    }
-
-    /**
-     * Stop the biometric unlock if something covers this window (such as an alarm)
-     * Start the biometric unlock if the lockscreen window just came into focus and the screen is on
-     */
-    @Override
-    public void onWindowFocusChanged (boolean hasWindowFocus) {
-        if (DEBUG) Log.d(TAG, hasWindowFocus ? "focused" : "unfocused");
-
-        boolean startBiometricUnlock = false;
-        // Start the biometric unlock if and only if the screen is both on and focused
-        synchronized(mBiometricUnlockStartupLock) {
-            if (mScreenOn && !mWindowFocused) startBiometricUnlock = hasWindowFocus;
-            mWindowFocused = hasWindowFocus;
-        }
-        if (!hasWindowFocus) {
-            if (mBiometricUnlock != null) {
-                mSuppressBiometricUnlock = true;
-                mBiometricUnlock.stop();
-                mBiometricUnlock.hide();
-            }
-        } else {
-            mHasDialog = false;
-            if (mBiometricUnlock != null && startBiometricUnlock) {
-                maybeStartBiometricUnlock();
-            }
-        }
-    }
-
-    @Override
-    public void show() {
-        // Emulate activity life-cycle for both lock and unlock screen.
-        if (mLockScreen != null) {
-            ((KeyguardScreen) mLockScreen).onResume();
-        }
-        if (mUnlockScreen != null) {
-            ((KeyguardScreen) mUnlockScreen).onResume();
-        }
-
-        if (mBiometricUnlock != null && mSuppressBiometricUnlock) {
-            mBiometricUnlock.hide();
-        }
-    }
-
-    private void recreateLockScreen() {
-        if (mLockScreen != null) {
-            ((KeyguardScreen) mLockScreen).onPause();
-            ((KeyguardScreen) mLockScreen).cleanUp();
-            removeView(mLockScreen);
-        }
-
-        mLockScreen = createLockScreen();
-        mLockScreen.setVisibility(View.INVISIBLE);
-        addView(mLockScreen);
-    }
-
-    private void recreateUnlockScreen(UnlockMode unlockMode) {
-        if (mUnlockScreen != null) {
-            ((KeyguardScreen) mUnlockScreen).onPause();
-            ((KeyguardScreen) mUnlockScreen).cleanUp();
-            removeView(mUnlockScreen);
-        }
-
-        mUnlockScreen = createUnlockScreenFor(unlockMode);
-        mUnlockScreen.setVisibility(View.INVISIBLE);
-        addView(mUnlockScreen);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        mUpdateMonitor.removeCallback(mInfoCallback);
-
-        removeCallbacks(mRecreateRunnable);
-
-        if (mBiometricUnlock != null) {
-            // When view is hidden, we need to stop the biometric unlock
-            // e.g., when device becomes unlocked
-            mBiometricUnlock.stop();
-        }
-
-        super.onDetachedFromWindow();
-    }
-
-    protected void onConfigurationChanged(Configuration newConfig) {
-        Resources resources = getResources();
-        mShowLockBeforeUnlock = resources.getBoolean(R.bool.config_enableLockBeforeUnlockScreen);
-        mConfiguration = newConfig;
-        if (DEBUG_CONFIGURATION) Log.v(TAG, "**** re-creating lock screen since config changed");
-        saveWidgetState();
-        removeCallbacks(mRecreateRunnable);
-        if (DEBUG) Log.v(TAG, "recreating lockscreen because config changed");
-        post(mRecreateRunnable);
-    }
-
-    InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() {
-
-        @Override
-        public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
-                int batteryLevel) {
-            // When someone plugs in or unplugs the device, we hide the biometric sensor area and
-            // suppress its startup for the next onScreenTurnedOn().  Since plugging/unplugging
-            // causes the screen to turn on, the biometric unlock would start if it wasn't
-            // suppressed.
-            //
-            // However, if the biometric unlock is already running, we do not want to interrupt it.
-            if (mBiometricUnlock != null && mPluggedIn != pluggedIn
-                    && !mBiometricUnlock.isRunning()) {
-                mBiometricUnlock.stop();
-                mBiometricUnlock.hide();
-                mSuppressBiometricUnlock = true;
-            }
-            mPluggedIn = pluggedIn;
-        }
-
-        @Override
-        public void onClockVisibilityChanged() {
-            int visFlags = (getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_CLOCK)
-                    | (mUpdateMonitor.isClockVisible() ? View.STATUS_BAR_DISABLE_CLOCK : 0);
-            Log.v(TAG, "Set visibility on " + this + " to " + visFlags);
-            setSystemUiVisibility(visFlags);
-        }
-
-        // We need to stop the biometric unlock when a phone call comes in
-        @Override
-        public void onPhoneStateChanged(int phoneState) {
-            if (DEBUG) Log.d(TAG, "phone state: " + phoneState);
-            if (mBiometricUnlock != null && phoneState == TelephonyManager.CALL_STATE_RINGING) {
-                mSuppressBiometricUnlock = true;
-                mBiometricUnlock.stop();
-                mBiometricUnlock.hide();
-            }
-        }
-
-        @Override
-        public void onUserChanged(int userId) {
-            if (mBiometricUnlock != null) {
-                mBiometricUnlock.stop();
-            }
-            mLockPatternUtils.setCurrentUser(userId);
-            updateScreen(getInitialMode(), true);
-        }
-    };
-
-    @Override
-    protected boolean dispatchHoverEvent(MotionEvent event) {
-        // Do not let the screen to get locked while the user is disabled and touch
-        // exploring. A blind user will need significantly more time to find and
-        // interact with the lock screen views.
-        AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(mContext);
-        if (accessibilityManager.isEnabled() && accessibilityManager.isTouchExplorationEnabled()) {
-            getCallback().pokeWakelock();
-        }
-        return super.dispatchHoverEvent(event);
-    }
-
-    @Override
-    public void wakeWhenReadyTq(int keyCode) {
-        if (DEBUG) Log.d(TAG, "onWakeKey");
-        if (keyCode == KeyEvent.KEYCODE_MENU && isSecure() && (mMode == Mode.LockScreen)
-                && (mUpdateMonitor.getSimState() != IccCardConstants.State.PUK_REQUIRED)) {
-            if (DEBUG) Log.d(TAG, "switching screens to unlock screen because wake key was MENU");
-            updateScreen(Mode.UnlockScreen, false);
-            getCallback().pokeWakelock();
-        } else {
-            if (DEBUG) Log.d(TAG, "poking wake lock immediately");
-            getCallback().pokeWakelock();
-        }
-    }
-
-    @Override
-    public void verifyUnlock() {
-        if (!isSecure()) {
-            // non-secure keyguard screens are successfull by default
-            getCallback().keyguardDone(true);
-        } else if (mUnlockScreenMode != UnlockMode.Pattern
-                && mUnlockScreenMode != UnlockMode.Password) {
-            // can only verify unlock when in pattern/password mode
-            getCallback().keyguardDone(false);
-        } else {
-            // otherwise, go to the unlock screen, see if they can verify it
-            mIsVerifyUnlockOnly = true;
-            updateScreen(Mode.UnlockScreen, false);
-        }
-    }
-
-    @Override
-    public void cleanUp() {
-        if (mLockScreen != null) {
-            ((KeyguardScreen) mLockScreen).onPause();
-            ((KeyguardScreen) mLockScreen).cleanUp();
-            this.removeView(mLockScreen);
-            mLockScreen = null;
-        }
-        if (mUnlockScreen != null) {
-            ((KeyguardScreen) mUnlockScreen).onPause();
-            ((KeyguardScreen) mUnlockScreen).cleanUp();
-            this.removeView(mUnlockScreen);
-            mUnlockScreen = null;
-        }
-        mUpdateMonitor.removeCallback(this);
-        if (mBiometricUnlock != null) {
-            mBiometricUnlock.cleanUp();
-        }
-    }
-
-    private boolean isSecure() {
-        UnlockMode unlockMode = getUnlockMode();
-        boolean secure = false;
-        switch (unlockMode) {
-            case Pattern:
-                secure = mLockPatternUtils.isLockPatternEnabled();
-                break;
-            case SimPin:
-                secure = mUpdateMonitor.getSimState() == IccCardConstants.State.PIN_REQUIRED;
-                break;
-            case SimPuk:
-                secure = mUpdateMonitor.getSimState() == IccCardConstants.State.PUK_REQUIRED;
-                break;
-            case Account:
-                secure = true;
-                break;
-            case Password:
-                secure = mLockPatternUtils.isLockPasswordEnabled();
-                break;
-            case Unknown:
-                // This means no security is set up
-                break;
-            default:
-                throw new IllegalStateException("unknown unlock mode " + unlockMode);
-        }
-        return secure;
-    }
-
-    private void updateScreen(Mode mode, boolean force) {
-
-        if (DEBUG_CONFIGURATION) Log.v(TAG, "**** UPDATE SCREEN: mode=" + mode
-                + " last mode=" + mMode + ", force = " + force, new RuntimeException());
-
-        mMode = mode;
-
-        // Re-create the lock screen if necessary
-        if (mode == Mode.LockScreen || mShowLockBeforeUnlock) {
-            if (force || mLockScreen == null) {
-                recreateLockScreen();
-            }
-        }
-
-        // Re-create the unlock screen if necessary.
-        final UnlockMode unlockMode = getUnlockMode();
-        if (mode == Mode.UnlockScreen && unlockMode != UnlockMode.Unknown) {
-            if (force || mUnlockScreen == null || unlockMode != mUnlockScreenMode) {
-                recreateUnlockScreen(unlockMode);
-            }
-        }
-
-        // visibleScreen should never be null
-        final View goneScreen = (mode == Mode.LockScreen) ? mUnlockScreen : mLockScreen;
-        final View visibleScreen = (mode == Mode.LockScreen) ? mLockScreen : mUnlockScreen;
-
-        // do this before changing visibility so focus isn't requested before the input
-        // flag is set
-        mWindowController.setNeedsInput(((KeyguardScreen)visibleScreen).needsInput());
-
-        if (DEBUG_CONFIGURATION) {
-            Log.v(TAG, "Gone=" + goneScreen);
-            Log.v(TAG, "Visible=" + visibleScreen);
-        }
-
-        if (mScreenOn) {
-            if (goneScreen != null && goneScreen.getVisibility() == View.VISIBLE) {
-                ((KeyguardScreen) goneScreen).onPause();
-            }
-            if (visibleScreen.getVisibility() != View.VISIBLE) {
-                ((KeyguardScreen) visibleScreen).onResume();
-            }
-        }
-
-        if (goneScreen != null) {
-            goneScreen.setVisibility(View.GONE);
-        }
-        visibleScreen.setVisibility(View.VISIBLE);
-        requestLayout();
-
-        if (!visibleScreen.requestFocus()) {
-            throw new IllegalStateException("keyguard screen must be able to take "
-                    + "focus when shown " + visibleScreen.getClass().getCanonicalName());
-        }
-    }
-
-    View createLockScreen() {
-        View lockView = new LockScreen(
-                mContext,
-                mConfiguration,
-                mLockPatternUtils,
-                mUpdateMonitor,
-                mKeyguardScreenCallback);
-        initializeTransportControlView(lockView);
-        return lockView;
-    }
-
-    View createUnlockScreenFor(UnlockMode unlockMode) {
-        View unlockView = null;
-
-        if (DEBUG) Log.d(TAG,
-                "createUnlockScreenFor(" + unlockMode + "): mEnableFallback=" + mEnableFallback);
-
-        if (unlockMode == UnlockMode.Pattern) {
-            PatternUnlockScreen view = new PatternUnlockScreen(
-                    mContext,
-                    mConfiguration,
-                    mLockPatternUtils,
-                    mUpdateMonitor,
-                    mKeyguardScreenCallback,
-                    mUpdateMonitor.getFailedAttempts());
-            view.setEnableFallback(mEnableFallback);
-            unlockView = view;
-        } else if (unlockMode == UnlockMode.SimPuk) {
-            unlockView = new SimPukUnlockScreen(
-                    mContext,
-                    mConfiguration,
-                    mUpdateMonitor,
-                    mKeyguardScreenCallback,
-                    mLockPatternUtils);
-        } else if (unlockMode == UnlockMode.SimPin) {
-            unlockView = new SimUnlockScreen(
-                    mContext,
-                    mConfiguration,
-                    mUpdateMonitor,
-                    mKeyguardScreenCallback,
-                    mLockPatternUtils);
-        } else if (unlockMode == UnlockMode.Account) {
-            try {
-                unlockView = new AccountUnlockScreen(
-                        mContext,
-                        mConfiguration,
-                        mUpdateMonitor,
-                        mKeyguardScreenCallback,
-                        mLockPatternUtils);
-            } catch (IllegalStateException e) {
-                Log.i(TAG, "Couldn't instantiate AccountUnlockScreen"
-                      + " (IAccountsService isn't available)");
-                // TODO: Need a more general way to provide a
-                // platform-specific fallback UI here.
-                // For now, if we can't display the account login
-                // unlock UI, just bring back the regular "Pattern" unlock mode.
-
-                // (We do this by simply returning a regular UnlockScreen
-                // here.  This means that the user will still see the
-                // regular pattern unlock UI, regardless of the value of
-                // mUnlockScreenMode or whether or not we're in the
-                // "permanently locked" state.)
-                return createUnlockScreenFor(UnlockMode.Pattern);
-            }
-        } else if (unlockMode == UnlockMode.Password) {
-            unlockView = new PasswordUnlockScreen(
-                    mContext,
-                    mConfiguration,
-                    mLockPatternUtils,
-                    mUpdateMonitor,
-                    mKeyguardScreenCallback);
-        } else {
-            throw new IllegalArgumentException("unknown unlock mode " + unlockMode);
-        }
-        initializeTransportControlView(unlockView);
-        initializeBiometricUnlockView(unlockView);
-
-        mUnlockScreenMode = unlockMode;
-        return unlockView;
-    }
-
-    private void initializeTransportControlView(View view) {
-        mTransportControlView = (TransportControlView) view.findViewById(R.id.transport);
-        if (mTransportControlView == null) {
-            if (DEBUG) Log.w(TAG, "Couldn't find transport control widget");
-        } else {
-            mUpdateMonitor.reportClockVisible(true);
-            mTransportControlView.setVisibility(View.GONE); // hide until it requests being shown.
-            mTransportControlView.setCallback(mWidgetCallback);
-        }
-    }
-
-    /**
-     * This returns false if there is any condition that indicates that the biometric unlock should
-     * not be used before the next time the unlock screen is recreated.  In other words, if this
-     * returns false there is no need to even construct the biometric unlock.
-     */
-    private boolean useBiometricUnlock() {
-        final UnlockMode unlockMode = getUnlockMode();
-        final boolean backupIsTimedOut = (mUpdateMonitor.getFailedAttempts() >=
-                LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
-        return (mLockPatternUtils.usingBiometricWeak() &&
-                mLockPatternUtils.isBiometricWeakInstalled() &&
-                !mUpdateMonitor.getMaxBiometricUnlockAttemptsReached() &&
-                !backupIsTimedOut &&
-                (unlockMode == UnlockMode.Pattern || unlockMode == UnlockMode.Password));
-    }
-
-    private void initializeBiometricUnlockView(View view) {
-        boolean restartBiometricUnlock = false;
-
-        if (mBiometricUnlock != null) {
-            restartBiometricUnlock = mBiometricUnlock.stop();
-        }
-
-        // Prevents biometric unlock from coming up immediately after a phone call or if there
-        // is a dialog on top of lockscreen. It is only updated if the screen is off because if the
-        // screen is on it's either because of an orientation change, or when it first boots.
-        // In both those cases, we don't want to override the current value of
-        // mSuppressBiometricUnlock and instead want to use the previous value.
-        if (!mScreenOn) {
-            mSuppressBiometricUnlock =
-                    mUpdateMonitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE
-                    || mHasDialog;
-        }
-
-        // If the biometric unlock is not being used, we don't bother constructing it.  Then we can
-        // simply check if it is null when deciding whether we should make calls to it.
-        mBiometricUnlock = null;
-        if (useBiometricUnlock()) {
-            // TODO: make faceLockAreaView a more general biometricUnlockView
-            // We will need to add our Face Unlock specific child views programmatically in
-            // initializeView rather than having them in the XML files.
-            View biometricUnlockView = view.findViewById(R.id.faceLockAreaView);
-            if (biometricUnlockView != null) {
-                mBiometricUnlock = new FaceUnlock(mContext, mUpdateMonitor, mLockPatternUtils,
-                        mKeyguardScreenCallback);
-                mBiometricUnlock.initializeView(biometricUnlockView);
-
-                // If this is being called because the screen turned off, we want to cover the
-                // backup lock so it is covered when the screen turns back on.
-                if (!mScreenOn) mBiometricUnlock.show(0);
-            } else {
-                Log.w(TAG, "Couldn't find biometric unlock view");
-            }
-        }
-
-        if (mBiometricUnlock != null && restartBiometricUnlock) {
-            maybeStartBiometricUnlock();
-        }
-    }
-
-    /**
-     * Given the current state of things, what should be the initial mode of
-     * the lock screen (lock or unlock).
-     */
-    private Mode getInitialMode() {
-        final IccCardConstants.State simState = mUpdateMonitor.getSimState();
-        if (stuckOnLockScreenBecauseSimMissing() ||
-                (simState == IccCardConstants.State.PUK_REQUIRED &&
-                        !mLockPatternUtils.isPukUnlockScreenEnable())) {
-            return Mode.LockScreen;
-        } else {
-            if (!isSecure() || mShowLockBeforeUnlock) {
-                return Mode.LockScreen;
-            } else {
-                return Mode.UnlockScreen;
-            }
-        }
-    }
-
-    /**
-     * Given the current state of things, what should the unlock screen be?
-     */
-    private UnlockMode getUnlockMode() {
-        final IccCardConstants.State simState = mUpdateMonitor.getSimState();
-        UnlockMode currentMode;
-        if (simState == IccCardConstants.State.PIN_REQUIRED) {
-            currentMode = UnlockMode.SimPin;
-        } else if (simState == IccCardConstants.State.PUK_REQUIRED) {
-            currentMode = UnlockMode.SimPuk;
-        } else {
-            final int mode = mLockPatternUtils.getKeyguardStoredPasswordQuality();
-            switch (mode) {
-                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
-                case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
-                case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
-                case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
-                    currentMode = UnlockMode.Password;
-                    break;
-                case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
-                case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
-                    if (mLockPatternUtils.isLockPatternEnabled()) {
-                        // "forgot pattern" button is only available in the pattern mode...
-                        if (mForgotPattern || mLockPatternUtils.isPermanentlyLocked()) {
-                            currentMode = UnlockMode.Account;
-                        } else {
-                            currentMode = UnlockMode.Pattern;
-                        }
-                    } else {
-                        currentMode = UnlockMode.Unknown;
-                    }
-                    break;
-                default:
-                   throw new IllegalStateException("Unknown unlock mode:" + mode);
-            }
-        }
-        return currentMode;
-    }
-
-    private void showDialog(String title, String message) {
-        mHasDialog = true;
-        final AlertDialog dialog = new AlertDialog.Builder(mContext)
-            .setTitle(title)
-            .setMessage(message)
-            .setNeutralButton(R.string.ok, null)
-            .create();
-        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
-        dialog.show();
-    }
-
-    private void showTimeoutDialog() {
-        int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
-        int messageId = R.string.lockscreen_too_many_failed_attempts_dialog_message;
-        if (getUnlockMode() == UnlockMode.Password) {
-            if(mLockPatternUtils.getKeyguardStoredPasswordQuality() ==
-                DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {
-                messageId = R.string.lockscreen_too_many_failed_pin_attempts_dialog_message;
-            } else {
-                messageId = R.string.lockscreen_too_many_failed_password_attempts_dialog_message;
-            }
-        }
-        String message = mContext.getString(messageId, mUpdateMonitor.getFailedAttempts(),
-                timeoutInSeconds);
-
-        showDialog(null, message);
-    }
-
-    private void showAlmostAtAccountLoginDialog() {
-        final int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
-        final int count = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
-                - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
-        String message = mContext.getString(R.string.lockscreen_failed_attempts_almost_glogin,
-                count, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, timeoutInSeconds);
-        showDialog(null, message);
-    }
-
-    private void showAlmostAtWipeDialog(int attempts, int remaining) {
-        int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
-        String message = mContext.getString(
-                R.string.lockscreen_failed_attempts_almost_at_wipe, attempts, remaining);
-        showDialog(null, message);
-    }
-
-    private void showWipeDialog(int attempts) {
-        String message = mContext.getString(
-                R.string.lockscreen_failed_attempts_now_wiping, attempts);
-        showDialog(null, message);
-    }
-
-    /**
-     * Used to put wallpaper on the background of the lock screen.  Centers it
-     * Horizontally and pins the bottom (assuming that the lock screen is aligned
-     * with the bottom, so the wallpaper should extend above the top into the
-     * status bar).
-     */
-    static private class FastBitmapDrawable extends Drawable {
-        private Bitmap mBitmap;
-        private int mOpacity;
-
-        private FastBitmapDrawable(Bitmap bitmap) {
-            mBitmap = bitmap;
-            mOpacity = mBitmap.hasAlpha() ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
-        }
-
-        @Override
-        public void draw(Canvas canvas) {
-            canvas.drawBitmap(
-                    mBitmap,
-                    (getBounds().width() - mBitmap.getWidth()) / 2,
-                    (getBounds().height() - mBitmap.getHeight()),
-                    null);
-        }
-
-        @Override
-        public int getOpacity() {
-            return mOpacity;
-        }
-
-        @Override
-        public void setAlpha(int alpha) {
-        }
-
-        @Override
-        public void setColorFilter(ColorFilter cf) {
-        }
-
-        @Override
-        public int getIntrinsicWidth() {
-            return mBitmap.getWidth();
-        }
-
-        @Override
-        public int getIntrinsicHeight() {
-            return mBitmap.getHeight();
-        }
-
-        @Override
-        public int getMinimumWidth() {
-            return mBitmap.getWidth();
-        }
-
-        @Override
-        public int getMinimumHeight() {
-            return mBitmap.getHeight();
-        }
-    }
-
-    /**
-     * Starts the biometric unlock if it should be started based on a number of factors including
-     * the mSuppressBiometricUnlock flag.  If it should not be started, it hides the biometric
-     * unlock area.
-     */
-    private void maybeStartBiometricUnlock() {
-        if (mBiometricUnlock != null) {
-            final boolean backupIsTimedOut = (mUpdateMonitor.getFailedAttempts() >=
-                    LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
-            if (!mSuppressBiometricUnlock
-                    && mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
-                    && !mUpdateMonitor.getMaxBiometricUnlockAttemptsReached()
-                    && !backupIsTimedOut) {
-                mBiometricUnlock.start();
-            } else {
-                mBiometricUnlock.hide();
-            }
-        }
-    }
-}
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java
deleted file mode 100644
index 6d3c20a6..0000000
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java
+++ /dev/null
@@ -1,65 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import com.android.internal.widget.LockPatternUtils;
-
-import android.content.Context;
-import com.android.internal.telephony.IccCardConstants;
-
-/**
- * Knows how to create a lock pattern keyguard view, and answer questions about
- * it (even if it hasn't been created, per the interface specs).
- */
-public class LockPatternKeyguardViewProperties implements KeyguardViewProperties {
-
-    private final LockPatternUtils mLockPatternUtils;
-    private final KeyguardUpdateMonitor mUpdateMonitor;
-
-    /**
-     * @param lockPatternUtils Used to know whether the pattern enabled, and passed
-     *   onto the keygaurd view when it is created.
-     * @param updateMonitor Used to know whether the sim pin is enabled, and passed
-     *   onto the keyguard view when it is created.
-     */
-    public LockPatternKeyguardViewProperties(LockPatternUtils lockPatternUtils,
-            KeyguardUpdateMonitor updateMonitor) {
-        mLockPatternUtils = lockPatternUtils;
-        mUpdateMonitor = updateMonitor;
-    }
-
-    public KeyguardViewBase createKeyguardView(Context context,
-            KeyguardViewCallback callback,
-            KeyguardUpdateMonitor updateMonitor,
-            KeyguardWindowController controller) {
-        return new LockPatternKeyguardView(context, callback, updateMonitor,
-                mLockPatternUtils, controller);
-    }
-
-    public boolean isSecure() {
-        return mLockPatternUtils.isSecure() || isSimPinSecure();
-    }
-
-    private boolean isSimPinSecure() {
-        final IccCardConstants.State simState = mUpdateMonitor.getSimState();
-        return (simState == IccCardConstants.State.PIN_REQUIRED
-                || simState == IccCardConstants.State.PUK_REQUIRED
-                || simState == IccCardConstants.State.ABSENT
-                || simState == IccCardConstants.State.PERM_DISABLED);
-    }
-
-}
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
deleted file mode 100644
index 26078ec..0000000
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ /dev/null
@@ -1,616 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import com.android.internal.R;
-import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl;
-import com.android.internal.policy.impl.KeyguardUpdateMonitor.SimStateCallback;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.SlidingTab;
-import com.android.internal.widget.WaveView;
-import com.android.internal.widget.multiwaveview.GlowPadView;
-
-import android.app.ActivityManager;
-import android.app.ActivityManagerNative;
-import android.app.SearchManager;
-import android.content.ActivityNotFoundException;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.os.Vibrator;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.*;
-import android.util.Log;
-import android.util.Slog;
-import android.media.AudioManager;
-import android.os.RemoteException;
-import android.provider.MediaStore;
-
-import java.io.File;
-
-/**
- * The screen within {@link LockPatternKeyguardView} that shows general
- * information about the device depending on its state, and how to get
- * past it, as applicable.
- */
-class LockScreen extends LinearLayout implements KeyguardScreen {
-
-    private static final int ON_RESUME_PING_DELAY = 500; // delay first ping until the screen is on
-    private static final boolean DBG = false;
-    private static final String TAG = "LockScreen";
-    private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
-    private static final int WAIT_FOR_ANIMATION_TIMEOUT = 0;
-    private static final int STAY_ON_WHILE_GRABBED_TIMEOUT = 30000;
-    private static final String ASSIST_ICON_METADATA_NAME =
-            "com.android.systemui.action_assist_icon";
-
-    private LockPatternUtils mLockPatternUtils;
-    private KeyguardUpdateMonitor mUpdateMonitor;
-    private KeyguardScreenCallback mCallback;
-
-    // set to 'true' to show the ring/silence target when camera isn't available
-    private boolean mEnableRingSilenceFallback = false;
-
-    // current configuration state of keyboard and display
-    private int mCreationOrientation;
-
-    private boolean mSilentMode;
-    private AudioManager mAudioManager;
-    private boolean mEnableMenuKeyInLockScreen;
-
-    private KeyguardStatusViewManager mStatusViewManager;
-    private UnlockWidgetCommonMethods mUnlockWidgetMethods;
-    private View mUnlockWidget;
-    private boolean mCameraDisabled;
-    private boolean mSearchDisabled;
-    // Is there a vibrator
-    private final boolean mHasVibrator;
-
-    InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() {
-
-        @Override
-        public void onRingerModeChanged(int state) {
-            boolean silent = AudioManager.RINGER_MODE_NORMAL != state;
-            if (silent != mSilentMode) {
-                mSilentMode = silent;
-                mUnlockWidgetMethods.updateResources();
-            }
-        }
-
-        @Override
-        public void onDevicePolicyManagerStateChanged() {
-            updateTargets();
-        }
-
-    };
-
-    SimStateCallback mSimStateCallback = new SimStateCallback() {
-        public void onSimStateChanged(IccCardConstants.State simState) {
-            updateTargets();
-        }
-    };
-
-    private interface UnlockWidgetCommonMethods {
-        // Update resources based on phone state
-        public void updateResources();
-
-        // Get the view associated with this widget
-        public View getView();
-
-        // Reset the view
-        public void reset(boolean animate);
-
-        // Animate the widget if it supports ping()
-        public void ping();
-
-        // Enable or disable a target. ResourceId is the id of the *drawable* associated with the
-        // target.
-        public void setEnabled(int resourceId, boolean enabled);
-
-        // Get the target position for the given resource. Returns -1 if not found.
-        public int getTargetPosition(int resourceId);
-
-        // Clean up when this widget is going away
-        public void cleanUp();
-    }
-
-    class SlidingTabMethods implements SlidingTab.OnTriggerListener, UnlockWidgetCommonMethods {
-        private final SlidingTab mSlidingTab;
-
-        SlidingTabMethods(SlidingTab slidingTab) {
-            mSlidingTab = slidingTab;
-        }
-
-        public void updateResources() {
-            boolean vibe = mSilentMode
-                && (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);
-
-            mSlidingTab.setRightTabResources(
-                    mSilentMode ? ( vibe ? R.drawable.ic_jog_dial_vibrate_on
-                                         : R.drawable.ic_jog_dial_sound_off )
-                                : R.drawable.ic_jog_dial_sound_on,
-                    mSilentMode ? R.drawable.jog_tab_target_yellow
-                                : R.drawable.jog_tab_target_gray,
-                    mSilentMode ? R.drawable.jog_tab_bar_right_sound_on
-                                : R.drawable.jog_tab_bar_right_sound_off,
-                    mSilentMode ? R.drawable.jog_tab_right_sound_on
-                                : R.drawable.jog_tab_right_sound_off);
-        }
-
-        /** {@inheritDoc} */
-        public void onTrigger(View v, int whichHandle) {
-            if (whichHandle == SlidingTab.OnTriggerListener.LEFT_HANDLE) {
-                mCallback.goToUnlockScreen();
-            } else if (whichHandle == SlidingTab.OnTriggerListener.RIGHT_HANDLE) {
-                toggleRingMode();
-                mCallback.pokeWakelock();
-            }
-        }
-
-        /** {@inheritDoc} */
-        public void onGrabbedStateChange(View v, int grabbedState) {
-            if (grabbedState == SlidingTab.OnTriggerListener.RIGHT_HANDLE) {
-                mSilentMode = isSilentMode();
-                mSlidingTab.setRightHintText(mSilentMode ? R.string.lockscreen_sound_on_label
-                        : R.string.lockscreen_sound_off_label);
-            }
-            // Don't poke the wake lock when returning to a state where the handle is
-            // not grabbed since that can happen when the system (instead of the user)
-            // cancels the grab.
-            if (grabbedState != SlidingTab.OnTriggerListener.NO_HANDLE) {
-                mCallback.pokeWakelock();
-            }
-        }
-
-        public View getView() {
-            return mSlidingTab;
-        }
-
-        public void reset(boolean animate) {
-            mSlidingTab.reset(animate);
-        }
-
-        public void ping() {
-        }
-
-        public void setEnabled(int resourceId, boolean enabled) {
-            // Not used
-        }
-
-        public int getTargetPosition(int resourceId) {
-            return -1; // Not supported
-        }
-
-        public void cleanUp() {
-            mSlidingTab.setOnTriggerListener(null);
-        }
-    }
-
-    class WaveViewMethods implements WaveView.OnTriggerListener, UnlockWidgetCommonMethods {
-
-        private final WaveView mWaveView;
-
-        WaveViewMethods(WaveView waveView) {
-            mWaveView = waveView;
-        }
-        /** {@inheritDoc} */
-        public void onTrigger(View v, int whichHandle) {
-            if (whichHandle == WaveView.OnTriggerListener.CENTER_HANDLE) {
-                requestUnlockScreen();
-            }
-        }
-
-        /** {@inheritDoc} */
-        public void onGrabbedStateChange(View v, int grabbedState) {
-            // Don't poke the wake lock when returning to a state where the handle is
-            // not grabbed since that can happen when the system (instead of the user)
-            // cancels the grab.
-            if (grabbedState == WaveView.OnTriggerListener.CENTER_HANDLE) {
-                mCallback.pokeWakelock(STAY_ON_WHILE_GRABBED_TIMEOUT);
-            }
-        }
-
-        public void updateResources() {
-        }
-
-        public View getView() {
-            return mWaveView;
-        }
-        public void reset(boolean animate) {
-            mWaveView.reset();
-        }
-        public void ping() {
-        }
-        public void setEnabled(int resourceId, boolean enabled) {
-            // Not used
-        }
-        public int getTargetPosition(int resourceId) {
-            return -1; // Not supported
-        }
-        public void cleanUp() {
-            mWaveView.setOnTriggerListener(null);
-        }
-    }
-
-    class GlowPadViewMethods implements GlowPadView.OnTriggerListener,
-            UnlockWidgetCommonMethods {
-        private final GlowPadView mGlowPadView;
-
-        GlowPadViewMethods(GlowPadView glowPadView) {
-            mGlowPadView = glowPadView;
-        }
-
-        public boolean isTargetPresent(int resId) {
-            return mGlowPadView.getTargetPosition(resId) != -1;
-        }
-
-        public void updateResources() {
-            int resId;
-            if (mCameraDisabled && mEnableRingSilenceFallback) {
-                // Fall back to showing ring/silence if camera is disabled...
-                resId = mSilentMode ? R.array.lockscreen_targets_when_silent
-                    : R.array.lockscreen_targets_when_soundon;
-            } else {
-                resId = R.array.lockscreen_targets_with_camera;
-            }
-            if (mGlowPadView.getTargetResourceId() != resId) {
-                mGlowPadView.setTargetResources(resId);
-            }
-
-            // Update the search icon with drawable from the search .apk
-            if (!mSearchDisabled) {
-                Intent intent = SearchManager.getAssistIntent(mContext);
-                if (intent != null) {
-                    // XXX Hack. We need to substitute the icon here but haven't formalized
-                    // the public API. The "_google" metadata will be going away, so
-                    // DON'T USE IT!
-                    ComponentName component = intent.getComponent();
-                    boolean replaced = mGlowPadView.replaceTargetDrawablesIfPresent(component,
-                            ASSIST_ICON_METADATA_NAME + "_google",
-                            com.android.internal.R.drawable.ic_action_assist_generic);
-
-                    if (!replaced && !mGlowPadView.replaceTargetDrawablesIfPresent(component,
-                                ASSIST_ICON_METADATA_NAME,
-                                com.android.internal.R.drawable.ic_action_assist_generic)) {
-                            Slog.w(TAG, "Couldn't grab icon from package " + component);
-                    }
-                }
-            }
-
-            setEnabled(com.android.internal.R.drawable.ic_lockscreen_camera, !mCameraDisabled);
-            setEnabled(com.android.internal.R.drawable.ic_action_assist_generic, !mSearchDisabled);
-        }
-
-        public void onGrabbed(View v, int handle) {
-
-        }
-
-        public void onReleased(View v, int handle) {
-
-        }
-
-        public void onTrigger(View v, int target) {
-            final int resId = mGlowPadView.getResourceIdForTarget(target);
-            switch (resId) {
-                case com.android.internal.R.drawable.ic_action_assist_generic:
-                    Intent assistIntent = SearchManager.getAssistIntent(mContext);
-                    if (assistIntent != null) {
-                        launchActivity(assistIntent);
-                    } else {
-                        Log.w(TAG, "Failed to get intent for assist activity");
-                    }
-                    mCallback.pokeWakelock();
-                    break;
-
-                case com.android.internal.R.drawable.ic_lockscreen_camera:
-                    launchActivity(new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA));
-                    mCallback.pokeWakelock();
-                    break;
-
-                case com.android.internal.R.drawable.ic_lockscreen_silent:
-                    toggleRingMode();
-                    mCallback.pokeWakelock();
-                break;
-
-                case com.android.internal.R.drawable.ic_lockscreen_unlock_phantom:
-                case com.android.internal.R.drawable.ic_lockscreen_unlock:
-                    mCallback.goToUnlockScreen();
-                break;
-            }
-        }
-
-        private void launchActivity(Intent intent) {
-            intent.setFlags(
-                    Intent.FLAG_ACTIVITY_NEW_TASK
-                    | Intent.FLAG_ACTIVITY_SINGLE_TOP
-                    | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-            try {
-                ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
-            } catch (RemoteException e) {
-                Log.w(TAG, "can't dismiss keyguard on launch");
-            }
-            try {
-                mContext.startActivity(intent);
-            } catch (ActivityNotFoundException e) {
-                Log.w(TAG, "Activity not found for intent + " + intent.getAction());
-            }
-        }
-
-        public void onGrabbedStateChange(View v, int handle) {
-            // Don't poke the wake lock when returning to a state where the handle is
-            // not grabbed since that can happen when the system (instead of the user)
-            // cancels the grab.
-            if (handle != GlowPadView.OnTriggerListener.NO_HANDLE) {
-                mCallback.pokeWakelock();
-            }
-        }
-
-        public View getView() {
-            return mGlowPadView;
-        }
-
-        public void reset(boolean animate) {
-            mGlowPadView.reset(animate);
-        }
-
-        public void ping() {
-            mGlowPadView.ping();
-        }
-
-        public void setEnabled(int resourceId, boolean enabled) {
-            mGlowPadView.setEnableTarget(resourceId, enabled);
-        }
-
-        public int getTargetPosition(int resourceId) {
-            return mGlowPadView.getTargetPosition(resourceId);
-        }
-
-        public void cleanUp() {
-            mGlowPadView.setOnTriggerListener(null);
-        }
-
-        public void onFinishFinalAnimation() {
-
-        }
-    }
-
-    private void requestUnlockScreen() {
-        // Delay hiding lock screen long enough for animation to finish
-        postDelayed(new Runnable() {
-            public void run() {
-                mCallback.goToUnlockScreen();
-            }
-        }, WAIT_FOR_ANIMATION_TIMEOUT);
-    }
-
-    private void toggleRingMode() {
-        // toggle silent mode
-        mSilentMode = !mSilentMode;
-        if (mSilentMode) {
-            mAudioManager.setRingerMode(mHasVibrator
-                ? AudioManager.RINGER_MODE_VIBRATE
-                : AudioManager.RINGER_MODE_SILENT);
-        } else {
-            mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
-        }
-    }
-
-    /**
-     * In general, we enable unlocking the insecure key guard with the menu key. However, there are
-     * some cases where we wish to disable it, notably when the menu button placement or technology
-     * is prone to false positives.
-     *
-     * @return true if the menu key should be enabled
-     */
-    private boolean shouldEnableMenuKey() {
-        final Resources res = getResources();
-        final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
-        final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
-        final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
-        return !configDisabled || isTestHarness || fileOverride;
-    }
-
-    /**
-     * @param context Used to setup the view.
-     * @param configuration The current configuration. Used to use when selecting layout, etc.
-     * @param lockPatternUtils Used to know the state of the lock pattern settings.
-     * @param updateMonitor Used to register for updates on various keyguard related
-     *    state, and query the initial state at setup.
-     * @param callback Used to communicate back to the host keyguard view.
-     */
-    LockScreen(Context context, Configuration configuration, LockPatternUtils lockPatternUtils,
-            KeyguardUpdateMonitor updateMonitor,
-            KeyguardScreenCallback callback) {
-        super(context);
-        mLockPatternUtils = lockPatternUtils;
-        mUpdateMonitor = updateMonitor;
-        mCallback = callback;
-        mEnableMenuKeyInLockScreen = shouldEnableMenuKey();
-        mCreationOrientation = configuration.orientation;
-
-        if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
-            Log.v(TAG, "***** CREATING LOCK SCREEN", new RuntimeException());
-            Log.v(TAG, "Cur orient=" + mCreationOrientation
-                    + " res orient=" + context.getResources().getConfiguration().orientation);
-        }
-
-        final LayoutInflater inflater = LayoutInflater.from(context);
-        if (DBG) Log.v(TAG, "Creation orientation = " + mCreationOrientation);
-        if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {
-            inflater.inflate(R.layout.keyguard_screen_tab_unlock, this, true);
-        } else {
-            inflater.inflate(R.layout.keyguard_screen_tab_unlock_land, this, true);
-        }
-
-        mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, mLockPatternUtils,
-                mCallback, false);
-
-        setFocusable(true);
-        setFocusableInTouchMode(true);
-        setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
-
-        Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
-        mHasVibrator = vibrator == null ? false : vibrator.hasVibrator();
-        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-        mSilentMode = isSilentMode();
-        mUnlockWidget = findViewById(R.id.unlock_widget);
-        mUnlockWidgetMethods = createUnlockMethods(mUnlockWidget);
-
-        if (DBG) Log.v(TAG, "*** LockScreen accel is "
-                + (mUnlockWidget.isHardwareAccelerated() ? "on":"off"));
-    }
-
-    private UnlockWidgetCommonMethods createUnlockMethods(View unlockWidget) {
-        if (unlockWidget instanceof SlidingTab) {
-            SlidingTab slidingTabView = (SlidingTab) unlockWidget;
-            slidingTabView.setHoldAfterTrigger(true, false);
-            slidingTabView.setLeftHintText(R.string.lockscreen_unlock_label);
-            slidingTabView.setLeftTabResources(
-                    R.drawable.ic_jog_dial_unlock,
-                    R.drawable.jog_tab_target_green,
-                    R.drawable.jog_tab_bar_left_unlock,
-                    R.drawable.jog_tab_left_unlock);
-            SlidingTabMethods slidingTabMethods = new SlidingTabMethods(slidingTabView);
-            slidingTabView.setOnTriggerListener(slidingTabMethods);
-            return slidingTabMethods;
-        } else if (unlockWidget instanceof WaveView) {
-            WaveView waveView = (WaveView) unlockWidget;
-            WaveViewMethods waveViewMethods = new WaveViewMethods(waveView);
-            waveView.setOnTriggerListener(waveViewMethods);
-            return waveViewMethods;
-        } else if (unlockWidget instanceof GlowPadView) {
-            GlowPadView glowPadView = (GlowPadView) unlockWidget;
-            GlowPadViewMethods glowPadViewMethods = new GlowPadViewMethods(glowPadView);
-            glowPadView.setOnTriggerListener(glowPadViewMethods);
-            return glowPadViewMethods;
-        } else {
-            throw new IllegalStateException("Unrecognized unlock widget: " + unlockWidget);
-        }
-    }
-
-    private void updateTargets() {
-        boolean disabledByAdmin = mLockPatternUtils.getDevicePolicyManager()
-                .getCameraDisabled(null);
-        boolean disabledBySimState = mUpdateMonitor.isSimLocked();
-        boolean cameraTargetPresent = (mUnlockWidgetMethods instanceof GlowPadViewMethods)
-                ? ((GlowPadViewMethods) mUnlockWidgetMethods)
-                        .isTargetPresent(com.android.internal.R.drawable.ic_lockscreen_camera)
-                        : false;
-        boolean searchTargetPresent = (mUnlockWidgetMethods instanceof GlowPadViewMethods)
-                ? ((GlowPadViewMethods) mUnlockWidgetMethods)
-                        .isTargetPresent(com.android.internal.R.drawable.ic_action_assist_generic)
-                        : false;
-
-        if (disabledByAdmin) {
-            Log.v(TAG, "Camera disabled by Device Policy");
-        } else if (disabledBySimState) {
-            Log.v(TAG, "Camera disabled by Sim State");
-        }
-        boolean searchActionAvailable = SearchManager.getAssistIntent(mContext) != null;
-        mCameraDisabled = disabledByAdmin || disabledBySimState || !cameraTargetPresent;
-        mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent;
-        mUnlockWidgetMethods.updateResources();
-    }
-
-    private boolean isSilentMode() {
-        return mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL;
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_MENU && mEnableMenuKeyInLockScreen) {
-            mCallback.goToUnlockScreen();
-        }
-        return false;
-    }
-
-    void updateConfiguration() {
-        Configuration newConfig = getResources().getConfiguration();
-        if (newConfig.orientation != mCreationOrientation) {
-            mCallback.recreateMe(newConfig);
-        }
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
-            Log.v(TAG, "***** LOCK ATTACHED TO WINDOW");
-            Log.v(TAG, "Cur orient=" + mCreationOrientation
-                    + ", new config=" + getResources().getConfiguration());
-        }
-        updateConfiguration();
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
-            Log.w(TAG, "***** LOCK CONFIG CHANGING", new RuntimeException());
-            Log.v(TAG, "Cur orient=" + mCreationOrientation
-                    + ", new config=" + newConfig);
-        }
-        updateConfiguration();
-    }
-
-    /** {@inheritDoc} */
-    public boolean needsInput() {
-        return false;
-    }
-
-    /** {@inheritDoc} */
-    public void onPause() {
-        mUpdateMonitor.removeCallback(mInfoCallback);
-        mUpdateMonitor.removeCallback(mSimStateCallback);
-        mStatusViewManager.onPause();
-        mUnlockWidgetMethods.reset(false);
-    }
-
-    private final Runnable mOnResumePing = new Runnable() {
-        public void run() {
-            mUnlockWidgetMethods.ping();
-        }
-    };
-
-    /** {@inheritDoc} */
-    public void onResume() {
-        // We don't want to show the camera target if SIM state prevents us from
-        // launching the camera. So watch for SIM changes...
-        mUpdateMonitor.registerSimStateCallback(mSimStateCallback);
-        mUpdateMonitor.registerInfoCallback(mInfoCallback);
-
-        mStatusViewManager.onResume();
-        postDelayed(mOnResumePing, ON_RESUME_PING_DELAY);
-    }
-
-    /** {@inheritDoc} */
-    public void cleanUp() {
-        mUpdateMonitor.removeCallback(mInfoCallback); // this must be first
-        mUpdateMonitor.removeCallback(mSimStateCallback);
-        mUnlockWidgetMethods.cleanUp();
-        mLockPatternUtils = null;
-        mUpdateMonitor = null;
-        mCallback = null;
-    }
-}
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
deleted file mode 100644
index 203f9db..0000000
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ /dev/null
@@ -1,383 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import java.util.List;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.PasswordEntryKeyboardView;
-
-import android.os.CountDownTimer;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.security.KeyStore;
-import android.text.Editable;
-import android.text.InputType;
-import android.text.TextWatcher;
-import android.text.method.DigitsKeyListener;
-import android.text.method.TextKeyListener;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.Space;
-import android.widget.TextView;
-import android.widget.TextView.OnEditorActionListener;
-
-import com.android.internal.R;
-import com.android.internal.widget.PasswordEntryKeyboardHelper;
-
-/**
- * Displays a dialer-like interface or alphanumeric (latin-1) key entry for the user to enter
- * an unlock password
- */
-public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen,
-        OnEditorActionListener {
-
-    private static final String TAG = "PasswordUnlockScreen";
-    private final KeyguardUpdateMonitor mUpdateMonitor;
-    private final KeyguardScreenCallback mCallback;
-
-    private final boolean mIsAlpha;
-
-    private final EditText mPasswordEntry;
-    private final LockPatternUtils mLockPatternUtils;
-    private final PasswordEntryKeyboardView mKeyboardView;
-    private final PasswordEntryKeyboardHelper mKeyboardHelper;
-
-    private final int mCreationOrientation;
-    private final int mCreationHardKeyboardHidden;
-
-    private final KeyguardStatusViewManager mStatusViewManager;
-    private final boolean mUseSystemIME = true; // TODO: Make configurable
-    private boolean mResuming; // used to prevent poking the wakelock during onResume()
-
-    // To avoid accidental lockout due to events while the device in in the pocket, ignore
-    // any passwords with length less than or equal to this length.
-    private static final int MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT = 3;
-
-    public PasswordUnlockScreen(Context context, Configuration configuration,
-            LockPatternUtils lockPatternUtils, KeyguardUpdateMonitor updateMonitor,
-            KeyguardScreenCallback callback) {
-        super(context);
-
-        mCreationHardKeyboardHidden = configuration.hardKeyboardHidden;
-        mCreationOrientation = configuration.orientation;
-        mUpdateMonitor = updateMonitor;
-        mCallback = callback;
-        mLockPatternUtils = lockPatternUtils;
-
-        LayoutInflater layoutInflater = LayoutInflater.from(context);
-        if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {
-            layoutInflater.inflate(R.layout.keyguard_screen_password_portrait, this, true);
-        } else {
-            layoutInflater.inflate(R.layout.keyguard_screen_password_landscape, this, true);
-        }
-
-        mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, mLockPatternUtils,
-                mCallback, true);
-
-        final int quality = lockPatternUtils.getKeyguardStoredPasswordQuality();
-        mIsAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == quality
-                || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == quality
-                || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == quality;
-
-        mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
-        mPasswordEntry = (EditText) findViewById(R.id.passwordEntry);
-        mPasswordEntry.setOnEditorActionListener(this);
-
-        mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this, false);
-        mKeyboardHelper.setEnableHaptics(mLockPatternUtils.isTactileFeedbackEnabled());
-        boolean imeOrDeleteButtonVisible = false;
-        if (mIsAlpha) {
-            // We always use the system IME for alpha keyboard, so hide lockscreen's soft keyboard
-            mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA);
-            mKeyboardView.setVisibility(View.GONE);
-        } else {
-            // Use lockscreen's numeric keyboard if the physical keyboard isn't showing
-            mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
-            mKeyboardView.setVisibility(mCreationHardKeyboardHidden
-                    == Configuration.HARDKEYBOARDHIDDEN_NO ? View.INVISIBLE : View.VISIBLE);
-
-            // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
-            // not a separate view
-            View pinDelete = findViewById(R.id.pinDel);
-            if (pinDelete != null) {
-                pinDelete.setVisibility(View.VISIBLE);
-                imeOrDeleteButtonVisible = true;
-                pinDelete.setOnClickListener(new OnClickListener() {
-                    @Override
-                    public void onClick(View v) {
-                        mKeyboardHelper.handleBackspace();
-                    }
-                });
-            }
-        }
-
-        mPasswordEntry.requestFocus();
-
-        // This allows keyboards with overlapping qwerty/numeric keys to choose just numeric keys.
-        if (mIsAlpha) {
-            mPasswordEntry.setKeyListener(TextKeyListener.getInstance());
-            mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT
-                    | InputType.TYPE_TEXT_VARIATION_PASSWORD);
-            //mStatusViewManager.setHelpMessage(R.string.keyguard_password_enter_password_code,
-                    //KeyguardStatusViewManager.LOCK_ICON);
-        } else {
-            mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
-            mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
-                    | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
-            //mStatusViewManager.setHelpMessage(R.string.keyguard_password_enter_pin_code,
-                    //KeyguardStatusViewManager.LOCK_ICON);
-        }
-
-        // Poke the wakelock any time the text is selected or modified
-        mPasswordEntry.setOnClickListener(new OnClickListener() {
-            public void onClick(View v) {
-                mCallback.pokeWakelock();
-            }
-        });
-        mPasswordEntry.addTextChangedListener(new TextWatcher() {
-            public void onTextChanged(CharSequence s, int start, int before, int count) {
-            }
-
-            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-            }
-
-            public void afterTextChanged(Editable s) {
-                if (!mResuming) {
-                    mCallback.pokeWakelock();
-                }
-            }
-        });
-
-        // If there's more than one IME, enable the IME switcher button
-        View switchImeButton = findViewById(R.id.switch_ime_button);
-        final InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
-                Context.INPUT_METHOD_SERVICE);
-        if (mIsAlpha && switchImeButton != null && hasMultipleEnabledIMEsOrSubtypes(imm, false)) {
-            switchImeButton.setVisibility(View.VISIBLE);
-            imeOrDeleteButtonVisible = true;
-            switchImeButton.setOnClickListener(new OnClickListener() {
-                public void onClick(View v) {
-                    mCallback.pokeWakelock(); // Leave the screen on a bit longer
-                    imm.showInputMethodPicker();
-                }
-            });
-        }
-
-        // If no icon is visible, reset the left margin on the password field so the text is
-        // still centered.
-        if (!imeOrDeleteButtonVisible) {
-            android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams();
-            if (params instanceof MarginLayoutParams) {
-                ((MarginLayoutParams)params).leftMargin = 0;
-                mPasswordEntry.setLayoutParams(params);
-            }
-        }
-    }
-
-    /**
-     * Method adapted from com.android.inputmethod.latin.Utils
-     *
-     * @param imm The input method manager
-     * @param shouldIncludeAuxiliarySubtypes
-     * @return true if we have multiple IMEs to choose from
-     */
-    private boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManager imm,
-            final boolean shouldIncludeAuxiliarySubtypes) {
-        final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList();
-
-        // Number of the filtered IMEs
-        int filteredImisCount = 0;
-
-        for (InputMethodInfo imi : enabledImis) {
-            // We can return true immediately after we find two or more filtered IMEs.
-            if (filteredImisCount > 1) return true;
-            final List<InputMethodSubtype> subtypes =
-                    imm.getEnabledInputMethodSubtypeList(imi, true);
-            // IMEs that have no subtypes should be counted.
-            if (subtypes.isEmpty()) {
-                ++filteredImisCount;
-                continue;
-            }
-
-            int auxCount = 0;
-            for (InputMethodSubtype subtype : subtypes) {
-                if (subtype.isAuxiliary()) {
-                    ++auxCount;
-                }
-            }
-            final int nonAuxCount = subtypes.size() - auxCount;
-
-            // IMEs that have one or more non-auxiliary subtypes should be counted.
-            // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary
-            // subtypes should be counted as well.
-            if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) {
-                ++filteredImisCount;
-                continue;
-            }
-        }
-
-        return filteredImisCount > 1
-        // imm.getEnabledInputMethodSubtypeList(null, false) will return the current IME's enabled
-        // input method subtype (The current IME should be LatinIME.)
-                || imm.getEnabledInputMethodSubtypeList(null, false).size() > 1;
-    }
-
-    @Override
-    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
-        // send focus to the password field
-        return mPasswordEntry.requestFocus(direction, previouslyFocusedRect);
-    }
-
-    /** {@inheritDoc} */
-    public boolean needsInput() {
-        return mUseSystemIME && mIsAlpha;
-    }
-
-    /** {@inheritDoc} */
-    public void onPause() {
-        mStatusViewManager.onPause();
-    }
-
-    /** {@inheritDoc} */
-    public void onResume() {
-        mResuming = true;
-        // reset status
-        mStatusViewManager.onResume();
-
-        // start fresh
-        mPasswordEntry.setText("");
-        mPasswordEntry.requestFocus();
-
-        // if the user is currently locked out, enforce it.
-        long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
-        if (deadline != 0) {
-            handleAttemptLockout(deadline);
-        }
-        mResuming = false;
-    }
-
-    /** {@inheritDoc} */
-    public void cleanUp() {
-        mUpdateMonitor.removeCallback(this);
-    }
-
-    private void verifyPasswordAndUnlock() {
-        String entry = mPasswordEntry.getText().toString();
-        if (mLockPatternUtils.checkPassword(entry)) {
-            mCallback.keyguardDone(true);
-            mCallback.reportSuccessfulUnlockAttempt();
-            mStatusViewManager.setInstructionText(null);
-            KeyStore.getInstance().password(entry);
-        } else if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) {
-            // to avoid accidental lockout, only count attempts that are long enough to be a
-            // real password. This may require some tweaking.
-            mCallback.reportFailedUnlockAttempt();
-            if (0 == (mUpdateMonitor.getFailedAttempts()
-                    % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
-                long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
-                handleAttemptLockout(deadline);
-            }
-            mStatusViewManager.setInstructionText(
-                    mContext.getString(R.string.lockscreen_password_wrong));
-        } else if (entry.length() > 0) {
-            mStatusViewManager.setInstructionText(
-                    mContext.getString(R.string.lockscreen_password_wrong));
-        }
-        mPasswordEntry.setText("");
-    }
-
-    // Prevent user from using the PIN/Password entry until scheduled deadline.
-    private void handleAttemptLockout(long elapsedRealtimeDeadline) {
-        mPasswordEntry.setEnabled(false);
-        mKeyboardView.setEnabled(false);
-        long elapsedRealtime = SystemClock.elapsedRealtime();
-        new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
-
-            @Override
-            public void onTick(long millisUntilFinished) {
-                int secondsRemaining = (int) (millisUntilFinished / 1000);
-                String instructions = getContext().getString(
-                        R.string.lockscreen_too_many_failed_attempts_countdown,
-                        secondsRemaining);
-                mStatusViewManager.setInstructionText(instructions);
-            }
-
-            @Override
-            public void onFinish() {
-                mPasswordEntry.setEnabled(true);
-                mKeyboardView.setEnabled(true);
-                mStatusViewManager.resetStatusInfo();
-            }
-        }.start();
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        mCallback.pokeWakelock();
-        return false;
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        Configuration config = getResources().getConfiguration();
-        if (config.orientation != mCreationOrientation
-                || config.hardKeyboardHidden != mCreationHardKeyboardHidden) {
-            mCallback.recreateMe(config);
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        if (newConfig.orientation != mCreationOrientation
-                || newConfig.hardKeyboardHidden != mCreationHardKeyboardHidden) {
-            mCallback.recreateMe(newConfig);
-        }
-    }
-
-    public void onKeyboardChange(boolean isKeyboardOpen) {
-        // Don't show the soft keyboard when the real keyboard is open
-        mKeyboardView.setVisibility(isKeyboardOpen ? View.INVISIBLE : View.VISIBLE);
-    }
-
-    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
-        // Check if this was the result of hitting the enter key
-        if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE
-                || actionId == EditorInfo.IME_ACTION_NEXT) {
-            verifyPasswordAndUnlock();
-            return true;
-        }
-        return false;
-    }
-}
diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
deleted file mode 100644
index 9a6d2cc..0000000
--- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
+++ /dev/null
@@ -1,416 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.os.CountDownTimer;
-import android.os.SystemClock;
-import android.security.KeyStore;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.MotionEvent;
-import android.widget.Button;
-import android.util.Log;
-import com.android.internal.R;
-import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.LockPatternView;
-import com.android.internal.widget.LockPatternView.Cell;
-
-import java.util.List;
-
-/**
- * This is the screen that shows the 9 circle unlock widget and instructs
- * the user how to unlock their device, or make an emergency call.
- */
-class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient
-        implements KeyguardScreen {
-
-    private static final boolean DEBUG = false;
-    private static final String TAG = "UnlockScreen";
-
-    // how long before we clear the wrong pattern
-    private static final int PATTERN_CLEAR_TIMEOUT_MS = 2000;
-
-    // how long we stay awake after each key beyond MIN_PATTERN_BEFORE_POKE_WAKELOCK
-    private static final int UNLOCK_PATTERN_WAKE_INTERVAL_MS = 7000;
-
-    // how long we stay awake after the user hits the first dot.
-    private static final int UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS = 2000;
-
-    // how many cells the user has to cross before we poke the wakelock
-    private static final int MIN_PATTERN_BEFORE_POKE_WAKELOCK = 2;
-
-    private int mFailedPatternAttemptsSinceLastTimeout = 0;
-    private int mTotalFailedPatternAttempts = 0;
-    private CountDownTimer mCountdownTimer = null;
-
-    private LockPatternUtils mLockPatternUtils;
-    private KeyguardUpdateMonitor mUpdateMonitor;
-    private KeyguardScreenCallback mCallback;
-
-    /**
-     * whether there is a fallback option available when the pattern is forgotten.
-     */
-    private boolean mEnableFallback;
-
-    private KeyguardStatusViewManager mKeyguardStatusViewManager;
-    private LockPatternView mLockPatternView;
-
-    /**
-     * Keeps track of the last time we poked the wake lock during dispatching
-     * of the touch event, initalized to something gauranteed to make us
-     * poke it when the user starts drawing the pattern.
-     * @see #dispatchTouchEvent(android.view.MotionEvent)
-     */
-    private long mLastPokeTime = -UNLOCK_PATTERN_WAKE_INTERVAL_MS;
-
-    /**
-     * Useful for clearing out the wrong pattern after a delay
-     */
-    private Runnable mCancelPatternRunnable = new Runnable() {
-        public void run() {
-            mLockPatternView.clearPattern();
-        }
-    };
-
-    private final OnClickListener mForgotPatternClick = new OnClickListener() {
-        public void onClick(View v) {
-            mCallback.forgotPattern(true);
-        }
-    };
-
-    private Button mForgotPatternButton;
-    private int mCreationOrientation;
-
-    enum FooterMode {
-        Normal,
-        ForgotLockPattern,
-        VerifyUnlocked
-    }
-
-    private void hideForgotPatternButton() {
-        mForgotPatternButton.setVisibility(View.GONE);
-    }
-
-    private void showForgotPatternButton() {
-        mForgotPatternButton.setVisibility(View.VISIBLE);
-    }
-
-    private void updateFooter(FooterMode mode) {
-        switch (mode) {
-            case Normal:
-                if (DEBUG) Log.d(TAG, "mode normal");
-                hideForgotPatternButton();
-                break;
-            case ForgotLockPattern:
-                if (DEBUG) Log.d(TAG, "mode ForgotLockPattern");
-                showForgotPatternButton();
-                break;
-            case VerifyUnlocked:
-                if (DEBUG) Log.d(TAG, "mode VerifyUnlocked");
-                hideForgotPatternButton();
-        }
-    }
-
-    /**
-     * @param context The context.
-     * @param configuration
-     * @param lockPatternUtils Used to lookup lock pattern settings.
-     * @param updateMonitor Used to lookup state affecting keyguard.
-     * @param callback Used to notify the manager when we're done, etc.
-     * @param totalFailedAttempts The current number of failed attempts.
-     * @param enableFallback True if a backup unlock option is available when the user has forgotten
-     *        their pattern (e.g they have a google account so we can show them the account based
-     *        backup option).
-     */
-    PatternUnlockScreen(Context context,
-                 Configuration configuration, LockPatternUtils lockPatternUtils,
-                 KeyguardUpdateMonitor updateMonitor,
-                 KeyguardScreenCallback callback,
-                 int totalFailedAttempts) {
-        super(context);
-        mLockPatternUtils = lockPatternUtils;
-        mUpdateMonitor = updateMonitor;
-        mCallback = callback;
-        mTotalFailedPatternAttempts = totalFailedAttempts;
-        mFailedPatternAttemptsSinceLastTimeout =
-            totalFailedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
-
-        if (DEBUG) Log.d(TAG,
-            "UnlockScreen() ctor: totalFailedAttempts="
-                 + totalFailedAttempts + ", mFailedPat...="
-                 + mFailedPatternAttemptsSinceLastTimeout
-                 );
-
-        mCreationOrientation = configuration.orientation;
-
-        LayoutInflater inflater = LayoutInflater.from(context);
-
-        if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {
-            Log.d(TAG, "portrait mode");
-            inflater.inflate(R.layout.keyguard_screen_unlock_portrait, this, true);
-        } else {
-            Log.d(TAG, "landscape mode");
-            inflater.inflate(R.layout.keyguard_screen_unlock_landscape, this, true);
-        }
-
-        mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor,
-                mLockPatternUtils, mCallback, true);
-
-        mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
-
-        mForgotPatternButton = (Button) findViewById(R.id.forgotPatternButton);
-        mForgotPatternButton.setText(R.string.lockscreen_forgot_pattern_button_text);
-        mForgotPatternButton.setOnClickListener(mForgotPatternClick);
-
-        // make it so unhandled touch events within the unlock screen go to the
-        // lock pattern view.
-        setDefaultTouchRecepient(mLockPatternView);
-
-        mLockPatternView.setSaveEnabled(false);
-        mLockPatternView.setFocusable(false);
-        mLockPatternView.setOnPatternListener(new UnlockPatternListener());
-
-        // stealth mode will be the same for the life of this screen
-        mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled());
-
-        // vibrate mode will be the same for the life of this screen
-        mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
-
-        // assume normal footer mode for now
-        updateFooter(FooterMode.Normal);
-
-        setFocusableInTouchMode(true);
-    }
-
-    public void setEnableFallback(boolean state) {
-        if (DEBUG) Log.d(TAG, "setEnableFallback(" + state + ")");
-        mEnableFallback = state;
-    }
-
-    @Override
-    public boolean dispatchTouchEvent(MotionEvent ev) {
-        // as long as the user is entering a pattern (i.e sending a touch
-        // event that was handled by this screen), keep poking the
-        // wake lock so that the screen will stay on.
-        final boolean result = super.dispatchTouchEvent(ev);
-        if (result &&
-                ((SystemClock.elapsedRealtime() - mLastPokeTime)
-                        >  (UNLOCK_PATTERN_WAKE_INTERVAL_MS - 100))) {
-            mLastPokeTime = SystemClock.elapsedRealtime();
-        }
-        return result;
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
-            Log.v(TAG, "***** PATTERN ATTACHED TO WINDOW");
-            Log.v(TAG, "Cur orient=" + mCreationOrientation
-                    + ", new config=" + getResources().getConfiguration());
-        }
-        if (getResources().getConfiguration().orientation != mCreationOrientation) {
-            mCallback.recreateMe(getResources().getConfiguration());
-        }
-    }
-
-
-    /** {@inheritDoc} */
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
-            Log.v(TAG, "***** PATTERN CONFIGURATION CHANGED");
-            Log.v(TAG, "Cur orient=" + mCreationOrientation
-                    + ", new config=" + getResources().getConfiguration());
-        }
-        if (newConfig.orientation != mCreationOrientation) {
-            mCallback.recreateMe(newConfig);
-        }
-    }
-
-    /** {@inheritDoc} */
-    public void onKeyboardChange(boolean isKeyboardOpen) {}
-
-    /** {@inheritDoc} */
-    public boolean needsInput() {
-        return false;
-    }
-
-    /** {@inheritDoc} */
-    public void onPause() {
-        if (mCountdownTimer != null) {
-            mCountdownTimer.cancel();
-            mCountdownTimer = null;
-        }
-        mKeyguardStatusViewManager.onPause();
-    }
-
-    /** {@inheritDoc} */
-    public void onResume() {
-        // reset status
-        mKeyguardStatusViewManager.onResume();
-
-        // reset lock pattern
-        mLockPatternView.enableInput();
-        mLockPatternView.setEnabled(true);
-        mLockPatternView.clearPattern();
-
-        // show "forgot pattern?" button if we have an alternate authentication method
-        if (mCallback.doesFallbackUnlockScreenExist()) {
-            showForgotPatternButton();
-        } else {
-            hideForgotPatternButton();
-        }
-
-        // if the user is currently locked out, enforce it.
-        long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
-        if (deadline != 0) {
-            handleAttemptLockout(deadline);
-        }
-
-        // the footer depends on how many total attempts the user has failed
-        if (mCallback.isVerifyUnlockOnly()) {
-            updateFooter(FooterMode.VerifyUnlocked);
-        } else if (mEnableFallback &&
-                (mTotalFailedPatternAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
-            updateFooter(FooterMode.ForgotLockPattern);
-        } else {
-            updateFooter(FooterMode.Normal);
-        }
-
-    }
-
-    /** {@inheritDoc} */
-    public void cleanUp() {
-        if (DEBUG) Log.v(TAG, "Cleanup() called on " + this);
-        mUpdateMonitor.removeCallback(this);
-        mLockPatternUtils = null;
-        mUpdateMonitor = null;
-        mCallback = null;
-        mLockPatternView.setOnPatternListener(null);
-    }
-
-    @Override
-    public void onWindowFocusChanged(boolean hasWindowFocus) {
-        super.onWindowFocusChanged(hasWindowFocus);
-        if (hasWindowFocus) {
-            // when timeout dialog closes we want to update our state
-            onResume();
-        }
-    }
-
-    private class UnlockPatternListener
-            implements LockPatternView.OnPatternListener {
-
-        public void onPatternStart() {
-            mLockPatternView.removeCallbacks(mCancelPatternRunnable);
-        }
-
-        public void onPatternCleared() {
-        }
-
-        public void onPatternCellAdded(List<Cell> pattern) {
-            // To guard against accidental poking of the wakelock, look for
-            // the user actually trying to draw a pattern of some minimal length.
-            if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
-                mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
-            } else {
-                // Give just a little extra time if they hit one of the first few dots
-                mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS);
-            }
-        }
-
-        public void onPatternDetected(List<LockPatternView.Cell> pattern) {
-            if (mLockPatternUtils.checkPattern(pattern)) {
-                mLockPatternView
-                        .setDisplayMode(LockPatternView.DisplayMode.Correct);
-                mKeyguardStatusViewManager.setInstructionText("");
-                mKeyguardStatusViewManager.updateStatusLines(true);
-                mCallback.keyguardDone(true);
-                mCallback.reportSuccessfulUnlockAttempt();
-                KeyStore.getInstance().password(LockPatternUtils.patternToString(pattern));
-            } else {
-                boolean reportFailedAttempt = false;
-                if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
-                    mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
-                }
-                mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
-                if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
-                    mTotalFailedPatternAttempts++;
-                    mFailedPatternAttemptsSinceLastTimeout++;
-                    reportFailedAttempt = true;
-                }
-                if (mFailedPatternAttemptsSinceLastTimeout
-                        >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
-                    long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
-                    handleAttemptLockout(deadline);
-                } else {
-                    // TODO mUnlockIcon.setVisibility(View.VISIBLE);
-                    mKeyguardStatusViewManager.setInstructionText(
-                            getContext().getString(R.string.lockscreen_pattern_wrong));
-                    mKeyguardStatusViewManager.updateStatusLines(true);
-                    mLockPatternView.postDelayed(
-                            mCancelPatternRunnable,
-                            PATTERN_CLEAR_TIMEOUT_MS);
-                }
-
-                // Because the following can result in cleanUp() being called on this screen,
-                // member variables reset in cleanUp() shouldn't be accessed after this call.
-                if (reportFailedAttempt) {
-                    mCallback.reportFailedUnlockAttempt();
-                }
-            }
-        }
-    }
-
-    private void handleAttemptLockout(long elapsedRealtimeDeadline) {
-        mLockPatternView.clearPattern();
-        mLockPatternView.setEnabled(false);
-        long elapsedRealtime = SystemClock.elapsedRealtime();
-        mCountdownTimer = new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
-
-            @Override
-            public void onTick(long millisUntilFinished) {
-                int secondsRemaining = (int) (millisUntilFinished / 1000);
-                mKeyguardStatusViewManager.setInstructionText(getContext().getString(
-                        R.string.lockscreen_too_many_failed_attempts_countdown,
-                        secondsRemaining));
-                mKeyguardStatusViewManager.updateStatusLines(true);
-            }
-
-            @Override
-            public void onFinish() {
-                mLockPatternView.setEnabled(true);
-                mKeyguardStatusViewManager.setInstructionText(getContext().getString(
-                        R.string.lockscreen_pattern_instructions));
-                mKeyguardStatusViewManager.updateStatusLines(true);
-                // TODO mUnlockIcon.setVisibility(View.VISIBLE);
-                mFailedPatternAttemptsSinceLastTimeout = 0;
-                if (mEnableFallback) {
-                    updateFooter(FooterMode.ForgotLockPattern);
-                } else {
-                    updateFooter(FooterMode.Normal);
-                }
-            }
-        }.start();
-    }
-
-}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneFallbackEventHandler.java b/policy/src/com/android/internal/policy/impl/PhoneFallbackEventHandler.java
index b88d84b..b72bb2b 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneFallbackEventHandler.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneFallbackEventHandler.java
@@ -26,8 +26,8 @@
 import android.media.IAudioService;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.telephony.TelephonyManager;
-import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
 import android.view.View;
@@ -142,7 +142,8 @@
                     // Broadcast an intent that the Camera button was longpressed
                     Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null);
                     intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
-                    mContext.sendOrderedBroadcast(intent, null);
+                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF,
+                            null, null, null, 0, null, null);
                 }
                 return true;
             }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 0aa3018..41d67bc 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -192,6 +192,20 @@
 
     private int mUiOptions = 0;
 
+    private boolean mInvalidatePanelMenuPosted;
+    private int mInvalidatePanelMenuFeatures;
+    private final Runnable mInvalidatePanelMenuRunnable = new Runnable() {
+        @Override public void run() {
+            for (int i = 0; i <= FEATURE_MAX; i++) {
+                if ((mInvalidatePanelMenuFeatures & 1 << i) != 0) {
+                    doInvalidatePanelMenu(i);
+                }
+            }
+            mInvalidatePanelMenuPosted = false;
+            mInvalidatePanelMenuFeatures = 0;
+        }
+    };
+
     static class WindowManagerHolder {
         static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService("window"));
@@ -613,8 +627,7 @@
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 width, WRAP_CONTENT,
                 st.x, st.y, WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG,
-                WindowManager.LayoutParams.FLAG_DITHER
-                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
                 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 st.decorView.mDefaultOpacity);
 
@@ -723,6 +736,15 @@
 
     @Override
     public void invalidatePanelMenu(int featureId) {
+        mInvalidatePanelMenuFeatures |= 1 << featureId;
+
+        if (!mInvalidatePanelMenuPosted && mDecor != null) {
+            mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
+            mInvalidatePanelMenuPosted = true;
+        }
+    }
+
+    void doInvalidatePanelMenu(int featureId) {
         PanelFeatureState st = getPanelState(featureId, true);
         Bundle savedActionViewStates = null;
         if (st.menu != null) {
@@ -971,7 +993,11 @@
             if (!mActionBar.isOverflowMenuShowing() || !toggleMenuMode) {
                 if (cb != null && !isDestroyed() && mActionBar.getVisibility() == View.VISIBLE) {
                     final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
-                    if (cb.onPreparePanel(FEATURE_OPTIONS_PANEL, st.createdPanelView, st.menu)) {
+
+                    // If we don't have a menu or we're waiting for a full content refresh,
+                    // forget it. This is a lingering event that no longer matters.
+                    if (st.menu != null && !st.refreshMenuContent &&
+                            cb.onPreparePanel(FEATURE_OPTIONS_PANEL, st.createdPanelView, st.menu)) {
                         cb.onMenuOpened(FEATURE_ACTION_BAR, st.menu);
                         mActionBar.showOverflowMenu();
                     }
@@ -2841,6 +2867,9 @@
             mDecor = generateDecor();
             mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
             mDecor.setIsRootNamespace(true);
+            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
+                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
+            }
         }
         if (mContentParent == null) {
             mContentParent = generateLayout(mDecor);
@@ -2850,6 +2879,7 @@
 
             mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
             if (mTitleView != null) {
+                mTitleView.setLayoutDirection(mDecor.getLayoutDirection());
                 if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
                     View titleContainer = findViewById(com.android.internal.R.id.title_container);
                     if (titleContainer != null) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 25da642..d9c07f8 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -17,7 +17,6 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
-import android.app.IUiModeManager;
 import android.app.ProgressDialog;
 import android.app.SearchManager;
 import android.app.UiModeManager;
@@ -40,12 +39,13 @@
 import android.graphics.Rect;
 import android.media.AudioManager;
 import android.media.IAudioService;
-import android.os.BatteryManager;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
 import android.os.Bundle;
+import android.os.FactoryTest;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
-import android.os.LocalPowerManager;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
@@ -55,16 +55,18 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UEventObserver;
+import android.os.UserHandle;
 import android.os.Vibrator;
 import android.provider.Settings;
 
 import com.android.internal.R;
 import com.android.internal.policy.PolicyManager;
+import com.android.internal.policy.impl.keyguard.KeyguardViewManager;
+import com.android.internal.policy.impl.keyguard.KeyguardViewMediator;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.widget.PointerLocationView;
 
-import android.service.dreams.IDreamManager;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
@@ -82,6 +84,7 @@
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
+import android.view.WindowManagerGlobal;
 import android.view.WindowOrientationListener;
 import android.view.Surface;
 import android.view.View;
@@ -97,6 +100,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
@@ -104,15 +108,19 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
 import static android.view.WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER;
 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
 import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
+import static android.view.WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
@@ -125,13 +133,13 @@
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
+import static android.view.WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND;
 import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
-import android.view.WindowManagerImpl;
 import android.view.WindowManagerPolicy;
 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
@@ -163,17 +171,10 @@
     static final boolean SHOW_STARTING_ANIMATIONS = true;
     static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
 
-    // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
-    // No longer recommended for desk docks; still useful in car docks.
-    static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true;
-    static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
-
-    // Should screen savers use their own timeout, or the SCREEN_OFF_TIMEOUT?
-    static final boolean SEPARATE_TIMEOUT_FOR_SCREEN_SAVER = false;
-
     static final int LONG_PRESS_POWER_NOTHING = 0;
     static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
     static final int LONG_PRESS_POWER_SHUT_OFF = 2;
+    static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
 
     // These need to match the documentation/constant in
     // core/res/res/values/config.xml
@@ -181,56 +182,11 @@
     static final int LONG_PRESS_HOME_RECENT_DIALOG = 1;
     static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 2;
 
-    // wallpaper is at the bottom, though the window manager may move it.
-    static final int WALLPAPER_LAYER = 2;
-    static final int APPLICATION_LAYER = 2;
-    static final int PHONE_LAYER = 3;
-    static final int SEARCH_BAR_LAYER = 4;
-    static final int SYSTEM_DIALOG_LAYER = 5;
-    // toasts and the plugged-in battery thing
-    static final int TOAST_LAYER = 6;
-    // SIM errors and unlock.  Not sure if this really should be in a high layer.
-    static final int PRIORITY_PHONE_LAYER = 7;
-    // like the ANR / app crashed dialogs
-    static final int SYSTEM_ALERT_LAYER = 8;
-    // on-screen keyboards and other such input method user interfaces go here.
-    static final int INPUT_METHOD_LAYER = 9;
-    // on-screen keyboards and other such input method user interfaces go here.
-    static final int INPUT_METHOD_DIALOG_LAYER = 10;
-    // the keyguard; nothing on top of these can take focus, since they are
-    // responsible for power management when displayed.
-    static final int KEYGUARD_LAYER = 11;
-    static final int KEYGUARD_DIALOG_LAYER = 12;
-    // used for Dreams (screensavers with TYPE_DREAM windows)
-    static final int SCREENSAVER_LAYER = 13; 
-    static final int STATUS_BAR_SUB_PANEL_LAYER = 14;
-    static final int STATUS_BAR_LAYER = 15;
-    static final int STATUS_BAR_PANEL_LAYER = 16;
-    // the on-screen volume indicator and controller shown when the user
-    // changes the device volume
-    static final int VOLUME_OVERLAY_LAYER = 17;
-    // things in here CAN NOT take focus, but are shown on top of everything else.
-    static final int SYSTEM_OVERLAY_LAYER = 18;
-    // the navigation bar, if available, shows atop most things
-    static final int NAVIGATION_BAR_LAYER = 19;
-    // some panels (e.g. search) need to show on top of the navigation bar
-    static final int NAVIGATION_BAR_PANEL_LAYER = 20;
-    // system-level error dialogs
-    static final int SYSTEM_ERROR_LAYER = 21;
-    // the drag layer: input for drag-and-drop is associated with this window,
-    // which sits above all other focusable windows
-    static final int DRAG_LAYER = 22;
-    static final int SECURE_SYSTEM_OVERLAY_LAYER = 23;
-    static final int BOOT_PROGRESS_LAYER = 24;
-    // the (mouse) pointer layer
-    static final int POINTER_LAYER = 25;
-    static final int HIDDEN_NAV_CONSUMER_LAYER = 26;
-
     static final int APPLICATION_MEDIA_SUBLAYER = -2;
     static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
     static final int APPLICATION_PANEL_SUBLAYER = 1;
     static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
-    
+
     static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
     static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
     static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
@@ -277,7 +233,7 @@
     Context mContext;
     IWindowManager mWindowManager;
     WindowManagerFuncs mWindowManagerFuncs;
-    LocalPowerManager mPowerManager;
+    PowerManager mPowerManager;
     IStatusBarService mStatusBarService;
     final Object mServiceAquireLock = new Object();
     Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
@@ -285,7 +241,7 @@
 
     // Vibrator pattern for haptic feedback of a long press.
     long[] mLongPressVibePattern;
-    
+
     // Vibrator pattern for haptic feedback of virtual key press.
     long[] mVirtualKeyVibePattern;
     
@@ -338,14 +294,12 @@
     boolean mSystemReady;
     boolean mSystemBooted;
     boolean mHdmiPlugged;
-    int mExternalDisplayWidth;
-    int mExternalDisplayHeight;
-    int mUiMode;
     int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
     int mLidOpenRotation;
     int mCarDockRotation;
     int mDeskDockRotation;
     int mHdmiRotation;
+    boolean mHdmiRotationLock;
 
     int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
     int mUserRotation = Surface.ROTATION_0;
@@ -456,8 +410,22 @@
     WindowState mTopFullscreenOpaqueWindowState;
     boolean mTopIsFullscreen;
     boolean mForceStatusBar;
+    boolean mForceStatusBarFromKeyguard;
     boolean mHideLockScreen;
-    boolean mDismissKeyguard;
+
+    // States of keyguard dismiss.
+    private static final int DISMISS_KEYGUARD_NONE = 0; // Keyguard not being dismissed.
+    private static final int DISMISS_KEYGUARD_START = 1; // Keyguard needs to be dismissed.
+    private static final int DISMISS_KEYGUARD_CONTINUE = 2; // Keyguard has been dismissed.
+    int mDismissKeyguard = DISMISS_KEYGUARD_NONE;
+
+    /** The window that is currently dismissing the keyguard. Dismissing the keyguard must only
+     * be done once per window. */
+    private WindowState mWinDismissingKeyguard;
+
+    boolean mShowingLockscreen;
+    boolean mShowingDream;
+    boolean mDreamingLockscreen;
     boolean mHomePressed;
     boolean mHomeLongPressed;
     Intent mHomeIntent;
@@ -472,13 +440,6 @@
     int mLockScreenTimeout;
     boolean mLockScreenTimerActive;
 
-    // visual screen saver support
-    boolean mScreenSaverFeatureAvailable;
-    int mScreenSaverTimeout = 0;
-    boolean mScreenSaverEnabledByUser = false;
-    boolean mScreenSaverMayRun = true; // false if a wakelock is held
-    boolean mPluggedIn;
-
     // Behavior of ENDCALL Button.  (See Settings.System.END_BUTTON_BEHAVIOR.)
     int mEndcallBehavior;
 
@@ -499,6 +460,8 @@
     // 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;
+    // Increase the chord delay when taking a screenshot from the keyguard
+    private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f;
     private boolean mScreenshotChordEnabled;
     private boolean mVolumeDownKeyTriggered;
     private long mVolumeDownKeyTime;
@@ -507,6 +470,7 @@
     private boolean mPowerKeyTriggered;
     private long mPowerKeyTime;
 
+    SettingsObserver mSettingsObserver;
     ShortcutManager mShortcutManager;
     PowerManager.WakeLock mBroadcastWakeLock;
     boolean mHavePendingMediaKeyRepeatWithWakeLock;
@@ -553,29 +517,32 @@
         }
 
         void observe() {
+            // Observe all users' changes
             ContentResolver resolver = mContext.getContentResolver();
             resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.System.END_BUTTON_BEHAVIOR), false, this);
+                    Settings.System.END_BUTTON_BEHAVIOR), false, this,
+                    UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this);
+                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this,
+                    UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.System.ACCELEROMETER_ROTATION), false, this);
+                    Settings.System.ACCELEROMETER_ROTATION), false, this,
+                    UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.System.USER_ROTATION), false, this);
+                    Settings.System.USER_ROTATION), false, this,
+                    UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.System.SCREEN_OFF_TIMEOUT), false, this);
+                    Settings.System.SCREEN_OFF_TIMEOUT), false, this,
+                    UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.System.POINTER_LOCATION), false, this);
+                    Settings.System.POINTER_LOCATION), false, this,
+                    UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
+                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
+                    UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.System.getUriFor(
-                    "fancy_rotation_anim"), false, this);
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.SCREENSAVER_ENABLED), false, this);
-            if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) {
-                resolver.registerContentObserver(Settings.Secure.getUriFor(
-                        "screensaver_timeout"), false, this);
-            } // otherwise SCREEN_OFF_TIMEOUT will do nicely
+                    "fancy_rotation_anim"), false, this,
+                    UserHandle.USER_ALL);
             updateSettings();
         }
 
@@ -717,37 +684,55 @@
                 mVolumeDownKeyConsumedByScreenshotChord = true;
                 cancelPendingPowerKeyAction();
 
-                mHandler.postDelayed(mScreenshotChordLongPress,
-                        ViewConfiguration.getGlobalActionKeyTimeout());
+                mHandler.postDelayed(mScreenshotChordLongPress, getScreenshotChordLongPressDelay());
             }
         }
     }
 
+    private long getScreenshotChordLongPressDelay() {
+        if (mKeyguardMediator.isShowing()) {
+            // Double the time it takes to take a screenshot from the keyguard
+            return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER *
+                    ViewConfiguration.getGlobalActionKeyTimeout());
+        } else {
+            return ViewConfiguration.getGlobalActionKeyTimeout();
+        }
+    }
+
     private void cancelPendingScreenshotChordAction() {
         mHandler.removeCallbacks(mScreenshotChordLongPress);
     }
 
     private final Runnable mPowerLongPress = new Runnable() {
+        @Override
         public void run() {
             // The context isn't read
             if (mLongPressOnPowerBehavior < 0) {
                 mLongPressOnPowerBehavior = mContext.getResources().getInteger(
                         com.android.internal.R.integer.config_longPressOnPowerBehavior);
             }
-            switch (mLongPressOnPowerBehavior) {
+            int resolvedBehavior = mLongPressOnPowerBehavior;
+            if (FactoryTest.isLongPressOnPowerOffEnabled()) {
+                resolvedBehavior = LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
+            }
+
+            switch (resolvedBehavior) {
             case LONG_PRESS_POWER_NOTHING:
                 break;
             case LONG_PRESS_POWER_GLOBAL_ACTIONS:
                 mPowerKeyHandled = true;
-                performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+                if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
+                    performAuditoryFeedbackForAccessibilityIfNeed();
+                }
                 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
                 showGlobalActionsDialog();
                 break;
             case LONG_PRESS_POWER_SHUT_OFF:
+            case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
                 mPowerKeyHandled = true;
                 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
                 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
-                mWindowManagerFuncs.shutdown();
+                mWindowManagerFuncs.shutdown(resolvedBehavior == LONG_PRESS_POWER_SHUT_OFF);
                 break;
             }
         }
@@ -768,13 +753,13 @@
         if (keyguardShowing) {
             // since it took two seconds of long press to bring this up,
             // poke the wake lock so they have some time to see the dialog.
-            mKeyguardMediator.pokeWakelock();
+            mKeyguardMediator.userActivity();
         }
     }
 
     boolean isDeviceProvisioned() {
-        return Settings.Secure.getInt(
-                mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
+        return Settings.Global.getInt(
+                mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
     }
 
     private void handleLongPressOnHome() {
@@ -861,28 +846,24 @@
 
     /** {@inheritDoc} */
     public void init(Context context, IWindowManager windowManager,
-            WindowManagerFuncs windowManagerFuncs,
-            LocalPowerManager powerManager) {
+            WindowManagerFuncs windowManagerFuncs) {
         mContext = context;
         mWindowManager = windowManager;
         mWindowManagerFuncs = windowManagerFuncs;
-        mPowerManager = powerManager;
         mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
         if (!mHeadless) {
             // don't create KeyguardViewMediator if headless
-            mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
+            mKeyguardMediator = new KeyguardViewMediator(context, null);
         }
         mHandler = new PolicyHandler();
         mOrientationListener = new MyOrientationListener(mContext);
         try {
             mOrientationListener.setCurrentRotation(windowManager.getRotation());
         } catch (RemoteException ex) { }
-        SettingsObserver settingsObserver = new SettingsObserver(mHandler);
-        settingsObserver.observe();
+        mSettingsObserver = new SettingsObserver(mHandler);
+        mSettingsObserver.observe();
         mShortcutManager = new ShortcutManager(context, mHandler);
         mShortcutManager.observe();
-        mUiMode = context.getResources().getInteger(
-                com.android.internal.R.integer.config_defaultUiModeType);
         mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
         mHomeIntent.addCategory(Intent.CATEGORY_HOME);
         mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
@@ -896,8 +877,8 @@
         mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
 
-        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
-        mBroadcastWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                 "PhoneWindowManager.mBroadcastWakeLock");
         mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
         mLidOpenRotation = readRotation(
@@ -930,13 +911,15 @@
                     Intent.EXTRA_DOCK_STATE_UNDOCKED);
         }
 
-        // watch the plug to know whether to trigger the screen saver
+        // register for dream-related broadcasts
         filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
-        intent = context.registerReceiver(mPowerReceiver, filter);
-        if (intent != null) {
-            mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
-        }
+        filter.addAction(Intent.ACTION_DREAMING_STARTED);
+        filter.addAction(Intent.ACTION_DREAMING_STOPPED);
+        context.registerReceiver(mDreamReceiver, filter);
+
+        // register for multiuser-relevant broadcasts
+        filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
+        context.registerReceiver(mMultiuserReceiver, filter);
 
         mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
         mLongPressVibePattern = getLongIntArray(mContext.getResources(),
@@ -964,7 +947,7 @@
         }
     }
 
-    public void setInitialDisplaySize(Display display, int width, int height) {
+    public void setInitialDisplaySize(Display display, int width, int height, int density) {
         mDisplay = display;
 
         int shortSize, longSize;
@@ -996,9 +979,6 @@
             }
         }
 
-        mExternalDisplayWidth = mDisplay.getRawExternalWidth();
-        mExternalDisplayHeight = mDisplay.getRawExternalHeight();
-
         mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_height);
 
@@ -1021,22 +1001,16 @@
                         com.android.internal.R.dimen.navigation_bar_width);
 
         // SystemUI (status bar) layout policy
-        int shortSizeDp = shortSize
-                * DisplayMetrics.DENSITY_DEFAULT
-                / DisplayMetrics.DENSITY_DEVICE;
+        int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
 
         if (shortSizeDp < 600) {
             // 0-599dp: "phone" UI with a separate status & navigation bar
             mHasSystemNavBar = false;
             mNavigationBarCanMove = true;
         } else if (shortSizeDp < 720) {
-            // 600-719dp: "phone" UI with modifications for larger screens
+            // 600+dp: "phone" UI with modifications for larger screens
             mHasSystemNavBar = false;
             mNavigationBarCanMove = false;
-        } else {
-            // 720dp: "tablet" UI with a single combined status & navigation bar
-            mHasSystemNavBar = true;
-            mNavigationBarCanMove = false;
         }
 
         if (!mHasSystemNavBar) {
@@ -1057,12 +1031,9 @@
             // The system bar is always at the bottom.  If you are watching
             // a video in landscape, we don't need to hide it if we can still
             // show a 16:9 aspect ratio with it.
-            int longSizeDp = longSize
-                    * DisplayMetrics.DENSITY_DEFAULT
-                    / DisplayMetrics.DENSITY_DEVICE;
+            int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
             int barHeightDp = mNavigationBarHeightForRotation[mLandscapeRotation]
-                    * DisplayMetrics.DENSITY_DEFAULT
-                    / DisplayMetrics.DENSITY_DEVICE;
+                    * DisplayMetrics.DENSITY_DEFAULT / density;
             int aspect = ((shortSizeDp-barHeightDp) * 16) / longSizeDp;
             // We have computed the aspect ratio with the bar height taken
             // out to be 16:aspect.  If this is less than 9, then hiding
@@ -1077,33 +1048,39 @@
             mCanHideNavigationBar = false;
         }
 
+        // For demo purposes, allow the rotation of the HDMI display to be controlled.
+        // By default, HDMI locks rotation to landscape.
         if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
             mHdmiRotation = mPortraitRotation;
         } else {
             mHdmiRotation = mLandscapeRotation;
         }
+        mHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", true);
     }
 
     public void updateSettings() {
         ContentResolver resolver = mContext.getContentResolver();
         boolean updateRotation = false;
         synchronized (mLock) {
-            mEndcallBehavior = Settings.System.getInt(resolver,
+            mEndcallBehavior = Settings.System.getIntForUser(resolver,
                     Settings.System.END_BUTTON_BEHAVIOR,
-                    Settings.System.END_BUTTON_BEHAVIOR_DEFAULT);
-            mIncallPowerBehavior = Settings.Secure.getInt(resolver,
+                    Settings.System.END_BUTTON_BEHAVIOR_DEFAULT,
+                    UserHandle.USER_CURRENT);
+            mIncallPowerBehavior = Settings.Secure.getIntForUser(resolver,
                     Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
-                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT);
+                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT,
+                    UserHandle.USER_CURRENT);
 
             // Configure rotation lock.
-            int userRotation = Settings.System.getInt(resolver,
-                    Settings.System.USER_ROTATION, Surface.ROTATION_0);
+            int userRotation = Settings.System.getIntForUser(resolver,
+                    Settings.System.USER_ROTATION, Surface.ROTATION_0,
+                    UserHandle.USER_CURRENT);
             if (mUserRotation != userRotation) {
                 mUserRotation = userRotation;
                 updateRotation = true;
             }
-            int userRotationMode = Settings.System.getInt(resolver,
-                    Settings.System.ACCELEROMETER_ROTATION, 0) != 0 ?
+            int userRotationMode = Settings.System.getIntForUser(resolver,
+                    Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
                             WindowManagerPolicy.USER_ROTATION_FREE :
                                     WindowManagerPolicy.USER_ROTATION_LOCKED;
             if (mUserRotationMode != userRotationMode) {
@@ -1113,8 +1090,8 @@
             }
 
             if (mSystemReady) {
-                int pointerLocation = Settings.System.getInt(resolver,
-                        Settings.System.POINTER_LOCATION, 0);
+                int pointerLocation = Settings.System.getIntForUser(resolver,
+                        Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
                 if (mPointerLocationMode != pointerLocation) {
                     mPointerLocationMode = pointerLocation;
                     mHandler.sendEmptyMessage(pointerLocation != 0 ?
@@ -1122,35 +1099,15 @@
                 }
             }
             // use screen off timeout setting as the timeout for the lockscreen
-            mLockScreenTimeout = Settings.System.getInt(resolver,
-                    Settings.System.SCREEN_OFF_TIMEOUT, 0);
-            String imId = Settings.Secure.getString(resolver,
-                    Settings.Secure.DEFAULT_INPUT_METHOD);
+            mLockScreenTimeout = Settings.System.getIntForUser(resolver,
+                    Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT);
+            String imId = Settings.Secure.getStringForUser(resolver,
+                    Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT);
             boolean hasSoftInput = imId != null && imId.length() > 0;
             if (mHasSoftInput != hasSoftInput) {
                 mHasSoftInput = hasSoftInput;
                 updateRotation = true;
             }
-
-            // dreams
-            mScreenSaverFeatureAvailable = mContext.getResources().getBoolean(
-                    com.android.internal.R.bool.config_enableDreams);
-            
-            mScreenSaverEnabledByUser = 0 != Settings.Secure.getInt(resolver,
-                    Settings.Secure.SCREENSAVER_ENABLED, 1);
-
-            if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) {
-                mScreenSaverTimeout = Settings.Secure.getInt(resolver,
-                        "screensaver_timeout", 0);
-            } else {
-                mScreenSaverTimeout = Settings.System.getInt(resolver,
-                        Settings.System.SCREEN_OFF_TIMEOUT, 0);
-                if (mScreenSaverTimeout > 0) {
-                    // We actually want to activate the screensaver just before the
-                    // power manager's screen timeout
-                    mScreenSaverTimeout -= 5000;
-                }
-            }
         }
         if (updateRotation) {
             updateRotation(true);
@@ -1170,6 +1127,11 @@
                     | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                     | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                     | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+            if (ActivityManager.isHighEndGfx()) {
+                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+                lp.privateFlags |=
+                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
+            }
             lp.format = PixelFormat.TRANSLUCENT;
             lp.setTitle("PointerLocation");
             WindowManager wm = (WindowManager)
@@ -1224,12 +1186,13 @@
     }
 
     /** {@inheritDoc} */
+    @Override
     public int checkAddPermission(WindowManager.LayoutParams attrs) {
         int type = attrs.type;
         
         if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
                 || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
-            return WindowManagerImpl.ADD_OKAY;
+            return WindowManagerGlobal.ADD_OKAY;
         }
         String permission = null;
         switch (type) {
@@ -1256,12 +1219,60 @@
         if (permission != null) {
             if (mContext.checkCallingOrSelfPermission(permission)
                     != PackageManager.PERMISSION_GRANTED) {
-                return WindowManagerImpl.ADD_PERMISSION_DENIED;
+                return WindowManagerGlobal.ADD_PERMISSION_DENIED;
             }
         }
-        return WindowManagerImpl.ADD_OKAY;
+        return WindowManagerGlobal.ADD_OKAY;
     }
-    
+
+    @Override
+    public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) {
+
+        // If this switch statement is modified, modify the comment in the declarations of
+        // the type in {@link WindowManager.LayoutParams} as well.
+        switch (attrs.type) {
+            default:
+                // These are the windows that by default are shown only to the user that created
+                // them. If this needs to be overridden, set
+                // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in
+                // {@link WindowManager.LayoutParams}. Note that permission
+                // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well.
+                if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) {
+                    return true;
+                }
+                break;
+
+            // These are the windows that by default are shown to all users. However, to
+            // protect against spoofing, check permissions below.
+            case TYPE_APPLICATION_STARTING:
+            case TYPE_BOOT_PROGRESS:
+            case TYPE_DISPLAY_OVERLAY:
+            case TYPE_HIDDEN_NAV_CONSUMER:
+            case TYPE_KEYGUARD:
+            case TYPE_KEYGUARD_DIALOG:
+            case TYPE_MAGNIFICATION_OVERLAY:
+            case TYPE_NAVIGATION_BAR:
+            case TYPE_NAVIGATION_BAR_PANEL:
+            case TYPE_PHONE:
+            case TYPE_POINTER:
+            case TYPE_PRIORITY_PHONE:
+            case TYPE_RECENTS_OVERLAY:
+            case TYPE_SEARCH_BAR:
+            case TYPE_STATUS_BAR:
+            case TYPE_STATUS_BAR_PANEL:
+            case TYPE_STATUS_BAR_SUB_PANEL:
+            case TYPE_SYSTEM_DIALOG:
+            case TYPE_UNIVERSE_BACKGROUND:
+            case TYPE_VOLUME_OVERLAY:
+                break;
+        }
+
+        // Check if third party app has set window to system window type.
+        return mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.INTERNAL_SYSTEM_WINDOW)
+                        != PackageManager.PERMISSION_GRANTED;
+    }
+
     public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
         switch (attrs.type) {
             case TYPE_SYSTEM_OVERLAY:
@@ -1321,62 +1332,90 @@
     /** {@inheritDoc} */
     public int windowTypeToLayerLw(int type) {
         if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
-            return APPLICATION_LAYER;
+            return 2;
         }
         switch (type) {
-        case TYPE_STATUS_BAR:
-            return STATUS_BAR_LAYER;
-        case TYPE_STATUS_BAR_PANEL:
-            return STATUS_BAR_PANEL_LAYER;
-        case TYPE_STATUS_BAR_SUB_PANEL:
-            return STATUS_BAR_SUB_PANEL_LAYER;
-        case TYPE_SYSTEM_DIALOG:
-            return SYSTEM_DIALOG_LAYER;
-        case TYPE_SEARCH_BAR:
-            return SEARCH_BAR_LAYER;
-        case TYPE_PHONE:
-            return PHONE_LAYER;
-        case TYPE_KEYGUARD:
-            return KEYGUARD_LAYER;
-        case TYPE_KEYGUARD_DIALOG:
-            return KEYGUARD_DIALOG_LAYER;
-        case TYPE_SYSTEM_ALERT:
-            return SYSTEM_ALERT_LAYER;
-        case TYPE_SYSTEM_ERROR:
-            return SYSTEM_ERROR_LAYER;
-        case TYPE_INPUT_METHOD:
-            return INPUT_METHOD_LAYER;
-        case TYPE_INPUT_METHOD_DIALOG:
-            return INPUT_METHOD_DIALOG_LAYER;
-        case TYPE_VOLUME_OVERLAY:
-            return VOLUME_OVERLAY_LAYER;
-        case TYPE_SYSTEM_OVERLAY:
-            return SYSTEM_OVERLAY_LAYER;
-        case TYPE_SECURE_SYSTEM_OVERLAY:
-            return SECURE_SYSTEM_OVERLAY_LAYER;
-        case TYPE_PRIORITY_PHONE:
-            return PRIORITY_PHONE_LAYER;
-        case TYPE_TOAST:
-            return TOAST_LAYER;
+        case TYPE_UNIVERSE_BACKGROUND:
+            return 1;
         case TYPE_WALLPAPER:
-            return WALLPAPER_LAYER;
-        case TYPE_DRAG:
-            return DRAG_LAYER;
-        case TYPE_POINTER:
-            return POINTER_LAYER;
-        case TYPE_NAVIGATION_BAR:
-            return NAVIGATION_BAR_LAYER;
-        case TYPE_NAVIGATION_BAR_PANEL:
-            return NAVIGATION_BAR_PANEL_LAYER;
-        case TYPE_BOOT_PROGRESS:
-            return BOOT_PROGRESS_LAYER;
-        case TYPE_HIDDEN_NAV_CONSUMER:
-            return HIDDEN_NAV_CONSUMER_LAYER;
+            // wallpaper is at the bottom, though the window manager may move it.
+            return 2;
+        case TYPE_PHONE:
+            return 3;
+        case TYPE_SEARCH_BAR:
+            return 4;
+        case TYPE_RECENTS_OVERLAY:
+        case TYPE_SYSTEM_DIALOG:
+            return 5;
+        case TYPE_TOAST:
+            // toasts and the plugged-in battery thing
+            return 6;
+        case TYPE_PRIORITY_PHONE:
+            // SIM errors and unlock.  Not sure if this really should be in a high layer.
+            return 7;
         case TYPE_DREAM:
-            return SCREENSAVER_LAYER;
+            // used for Dreams (screensavers with TYPE_DREAM windows)
+            return 8;
+        case TYPE_SYSTEM_ALERT:
+            // like the ANR / app crashed dialogs
+            return 9;
+        case TYPE_INPUT_METHOD:
+            // on-screen keyboards and other such input method user interfaces go here.
+            return 10;
+        case TYPE_INPUT_METHOD_DIALOG:
+            // on-screen keyboards and other such input method user interfaces go here.
+            return 11;
+        case TYPE_KEYGUARD:
+            // the keyguard; nothing on top of these can take focus, since they are
+            // responsible for power management when displayed.
+            return 12;
+        case TYPE_KEYGUARD_DIALOG:
+            return 13;
+        case TYPE_STATUS_BAR_SUB_PANEL:
+            return 14;
+        case TYPE_STATUS_BAR:
+            return 15;
+        case TYPE_STATUS_BAR_PANEL:
+            return 16;
+        case TYPE_VOLUME_OVERLAY:
+            // the on-screen volume indicator and controller shown when the user
+            // changes the device volume
+            return 17;
+        case TYPE_SYSTEM_OVERLAY:
+            // the on-screen volume indicator and controller shown when the user
+            // changes the device volume
+            return 18;
+        case TYPE_NAVIGATION_BAR:
+            // the navigation bar, if available, shows atop most things
+            return 19;
+        case TYPE_NAVIGATION_BAR_PANEL:
+            // some panels (e.g. search) need to show on top of the navigation bar
+            return 20;
+        case TYPE_SYSTEM_ERROR:
+            // system-level error dialogs
+            return 21;
+        case TYPE_MAGNIFICATION_OVERLAY:
+            // used to highlight the magnified portion of a display
+            return 22;
+        case TYPE_DISPLAY_OVERLAY:
+            // used to simulate secondary display devices
+            return 23;
+        case TYPE_DRAG:
+            // the drag layer: input for drag-and-drop is associated with this window,
+            // which sits above all other focusable windows
+            return 24;
+        case TYPE_SECURE_SYSTEM_OVERLAY:
+            return 25;
+        case TYPE_BOOT_PROGRESS:
+            return 26;
+        case TYPE_POINTER:
+            // the (mouse) pointer layer
+            return 27;
+        case TYPE_HIDDEN_NAV_CONSUMER:
+            return 28;
         }
         Log.e(TAG, "Unknown window type: " + type);
-        return APPLICATION_LAYER;
+        return 2;
     }
 
     /** {@inheritDoc} */
@@ -1397,7 +1436,11 @@
     }
 
     public int getMaxWallpaperLayer() {
-        return STATUS_BAR_LAYER;
+        return windowTypeToLayerLw(TYPE_STATUS_BAR);
+    }
+
+    public int getAboveUniverseLayer() {
+        return windowTypeToLayerLw(TYPE_SYSTEM_ERROR);
     }
 
     public boolean hasSystemNavBar() {
@@ -1446,14 +1489,24 @@
         return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation);
     }
 
+    @Override
     public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
         return attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD;
     }
-    
+
+    @Override
     public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
-        return attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR
-                && attrs.type != WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
-                && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER;
+        switch (attrs.type) {
+            case TYPE_STATUS_BAR:
+            case TYPE_NAVIGATION_BAR:
+            case TYPE_WALLPAPER:
+            case TYPE_DREAM:
+            case TYPE_UNIVERSE_BACKGROUND:
+            case TYPE_KEYGUARD:
+                return false;
+            default:
+                return true;
+        }
     }
 
     /** {@inheritDoc} */
@@ -1524,6 +1577,7 @@
                     com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
             params.privateFlags |=
                     WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
+            params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
             params.setTitle("Starting " + packageName);
 
             WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
@@ -1549,7 +1603,7 @@
             // Only return the view if it was successfully added to the
             // window manager... which we can tell by it having a parent.
             return view.getParent() != null ? view : null;
-        } catch (WindowManagerImpl.BadTokenException e) {
+        } catch (WindowManager.BadTokenException e) {
             // ignore
             Log.w(TAG, appToken + " already running, starting window not displayed");
         } catch (RuntimeException e) {
@@ -1588,7 +1642,8 @@
      * @param win The window to be added
      * @param attrs Information about the window to be added
      * 
-     * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons, WindowManagerImpl.ADD_MULTIPLE_SINGLETON
+     * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons,
+     * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
      */
     public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
         switch (attrs.type) {
@@ -1598,7 +1653,7 @@
                         "PhoneWindowManager");
                 if (mStatusBar != null) {
                     if (mStatusBar.isAlive()) {
-                        return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
+                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
                     }
                 }
                 mStatusBar = win;
@@ -1609,7 +1664,7 @@
                         "PhoneWindowManager");
                 if (mNavigationBar != null) {
                     if (mNavigationBar.isAlive()) {
-                        return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
+                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
                     }
                 }
                 mNavigationBar = win;
@@ -1632,12 +1687,12 @@
                 break;
             case TYPE_KEYGUARD:
                 if (mKeyguard != null) {
-                    return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
+                    return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
                 }
                 mKeyguard = win;
                 break;
         }
-        return WindowManagerImpl.ADD_OKAY;
+        return WindowManagerGlobal.ADD_OKAY;
     }
 
     /** {@inheritDoc} */
@@ -1683,6 +1738,13 @@
                 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
                 return com.android.internal.R.anim.app_starting_exit;
             }
+        } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
+                && transit == TRANSIT_ENTER) {
+            // Special case: we are animating in a dream, while the keyguard
+            // is shown.  We don't want an animation on the dream, because
+            // we need it shown immediately with the keyguard animating away
+            // to reveal it.
+            return -1;
         }
 
         return 0;
@@ -1767,15 +1829,17 @@
                 mHomePressed = false;
                 mHomeLongPressed = false;
                 if (!homeWasLongPressed) {
-                    try {
-                        IStatusBarService statusbar = getStatusBarService();
-                        if (statusbar != null) {
-                            statusbar.cancelPreloadRecentApps();
+                    if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
+                        try {
+                            IStatusBarService statusbar = getStatusBarService();
+                            if (statusbar != null) {
+                                statusbar.cancelPreloadRecentApps();
+                            }
+                        } catch (RemoteException e) {
+                            Slog.e(TAG, "RemoteException when showing recent apps", e);
+                            // re-acquire status bar service next time it is needed.
+                            mStatusBarService = null;
                         }
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "RemoteException when showing recent apps", e);
-                        // re-acquire status bar service next time it is needed.
-                        mStatusBarService = null;
                     }
 
                     mHomePressed = false;
@@ -1852,22 +1916,23 @@
             if (down && repeatCount == 0) {
                 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
                     Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
-                    mContext.sendOrderedBroadcast(intent, null);
+                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
+                            null, null, null, 0, null, null);
                     return -1;
                 } else if (SHOW_PROCESSES_ON_ALT_MENU &&
                         (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
                     Intent service = new Intent();
                     service.setClassName(mContext, "com.android.server.LoadAverageService");
                     ContentResolver res = mContext.getContentResolver();
-                    boolean shown = Settings.System.getInt(
-                            res, Settings.System.SHOW_PROCESSES, 0) != 0;
+                    boolean shown = Settings.Global.getInt(
+                            res, Settings.Global.SHOW_PROCESSES, 0) != 0;
                     if (!shown) {
                         mContext.startService(service);
                     } else {
                         mContext.stopService(service);
                     }
-                    Settings.System.putInt(
-                            res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1);
+                    Settings.Global.putInt(
+                            res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1);
                     return -1;
                 }
             }
@@ -2114,7 +2179,7 @@
             if (searchManager != null) {
                 searchManager.stopSearch();
             }
-            mContext.startActivity(intent);
+            mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
         } catch (ActivityNotFoundException e) {
             Slog.w(TAG, "No activity to handle assist long press action.", e);
         }
@@ -2122,13 +2187,14 @@
 
     private void launchAssistAction() {
         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
-        Intent intent = SearchManager.getAssistIntent(mContext);
+        Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                .getAssistIntent(mContext, UserHandle.USER_CURRENT);
         if (intent != null) {
             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                     | Intent.FLAG_ACTIVITY_SINGLE_TOP
                     | Intent.FLAG_ACTIVITY_CLEAR_TOP);
             try {
-                mContext.startActivity(intent);
+                mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
             } catch (ActivityNotFoundException e) {
                 Slog.w(TAG, "No activity to handle assist action.", e);
             }
@@ -2269,6 +2335,7 @@
                 & ~mForceClearedSystemUiFlags;
     }
 
+    @Override
     public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) {
         final int fl = attrs.flags;
         final int systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility);
@@ -2309,7 +2376,9 @@
     }
 
     /** {@inheritDoc} */
-    public void beginLayoutLw(int displayWidth, int displayHeight, int displayRotation) {
+    @Override
+    public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
+                              int displayRotation) {
         mUnrestrictedScreenLeft = mUnrestrictedScreenTop = 0;
         mUnrestrictedScreenWidth = displayWidth;
         mUnrestrictedScreenHeight = displayHeight;
@@ -2336,151 +2405,138 @@
         pf.right = df.right = vf.right = mDockRight;
         pf.bottom = df.bottom = vf.bottom = mDockBottom;
 
-        // For purposes of putting out fake window up to steal focus, we will
-        // drive nav being hidden only by whether it is requested.
-        boolean navVisible = (mLastSystemUiFlags&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
+        if (isDefaultDisplay) {
+            // For purposes of putting out fake window up to steal focus, we will
+            // drive nav being hidden only by whether it is requested.
+            boolean navVisible = (mLastSystemUiFlags&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
 
-        // When the navigation bar isn't visible, we put up a fake
-        // input window to catch all touch events.  This way we can
-        // detect when the user presses anywhere to bring back the nav
-        // bar and ensure the application doesn't see the event.
-        if (navVisible) {
-            if (mHideNavFakeWindow != null) {
-                mHideNavFakeWindow.dismiss();
-                mHideNavFakeWindow = null;
+            // When the navigation bar isn't visible, we put up a fake
+            // input window to catch all touch events.  This way we can
+            // detect when the user presses anywhere to bring back the nav
+            // bar and ensure the application doesn't see the event.
+            if (navVisible) {
+                if (mHideNavFakeWindow != null) {
+                    mHideNavFakeWindow.dismiss();
+                    mHideNavFakeWindow = null;
+                }
+            } else if (mHideNavFakeWindow == null) {
+                mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow(
+                        mHandler.getLooper(), mHideNavInputEventReceiverFactory,
+                        "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER,
+                        0, false, false, true);
             }
-        } else if (mHideNavFakeWindow == null) {
-            mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow(
-                    mHandler.getLooper(), mHideNavInputEventReceiverFactory,
-                    "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER,
-                    0, false, false, true);
-        }
 
-        // For purposes of positioning and showing the nav bar, if we have
-        // decided that it can't be hidden (because of the screen aspect ratio),
-        // then take that into account.
-        navVisible |= !mCanHideNavigationBar;
+            // For purposes of positioning and showing the nav bar, if we have
+            // decided that it can't be hidden (because of the screen aspect ratio),
+            // then take that into account.
+            navVisible |= !mCanHideNavigationBar;
 
-        if (mNavigationBar != null) {
-            // Force the navigation bar to its appropriate place and
-            // size.  We need to do this directly, instead of relying on
-            // it to bubble up from the nav bar, because this needs to
-            // change atomically with screen rotations.
-            mNavigationBarOnBottom = (!mNavigationBarCanMove || displayWidth < displayHeight);
-            if (mNavigationBarOnBottom) {
-                // It's a system nav bar or a portrait screen; nav bar goes on bottom.
-                int top = displayHeight - mNavigationBarHeightForRotation[displayRotation];
-                if (mHdmiPlugged) {
-                    // Move the nav bar up if the external display is the same aspect ratio
-                    // but shorter.  This avoids clipping on the external display.
-                    boolean sameAspect = mExternalDisplayHeight > 0 && displayHeight > 0
-                        && ((float) mExternalDisplayWidth / mExternalDisplayHeight > 1)
-                        == ((float) displayWidth / displayHeight > 1);
-                    if (sameAspect && top > mExternalDisplayHeight) {
-                        top = mExternalDisplayHeight;
+            if (mNavigationBar != null) {
+                // Force the navigation bar to its appropriate place and
+                // size.  We need to do this directly, instead of relying on
+                // it to bubble up from the nav bar, because this needs to
+                // change atomically with screen rotations.
+                mNavigationBarOnBottom = (!mNavigationBarCanMove || displayWidth < displayHeight);
+                if (mNavigationBarOnBottom) {
+                    // It's a system nav bar or a portrait screen; nav bar goes on bottom.
+                    int top = displayHeight - mNavigationBarHeightForRotation[displayRotation];
+                    mTmpNavigationFrame.set(0, top, displayWidth, displayHeight);
+                    mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
+                    if (navVisible) {
+                        mNavigationBar.showLw(true);
+                        mDockBottom = mTmpNavigationFrame.top;
+                        mRestrictedScreenHeight = mDockBottom - mDockTop;
+                    } else {
+                        // We currently want to hide the navigation UI.
+                        mNavigationBar.hideLw(true);
+                    }
+                    if (navVisible && !mNavigationBar.isAnimatingLw()) {
+                        // If the nav bar is currently requested to be visible,
+                        // and not in the process of animating on or off, then
+                        // we can tell the app that it is covered by it.
+                        mSystemBottom = mTmpNavigationFrame.top;
+                    }
+                } else {
+                    // Landscape screen; nav bar goes to the right.
+                    int left = displayWidth - mNavigationBarWidthForRotation[displayRotation];
+                    mTmpNavigationFrame.set(left, 0, displayWidth, displayHeight);
+                    mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
+                    if (navVisible) {
+                        mNavigationBar.showLw(true);
+                        mDockRight = mTmpNavigationFrame.left;
+                        mRestrictedScreenWidth = mDockRight - mDockLeft;
+                    } else {
+                        // We currently want to hide the navigation UI.
+                        mNavigationBar.hideLw(true);
+                    }
+                    if (navVisible && !mNavigationBar.isAnimatingLw()) {
+                        // If the nav bar is currently requested to be visible,
+                        // and not in the process of animating on or off, then
+                        // we can tell the app that it is covered by it.
+                        mSystemRight = mTmpNavigationFrame.left;
                     }
                 }
-                mTmpNavigationFrame.set(0, top, displayWidth, displayHeight);
-                mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
-                if (navVisible) {
-                    mNavigationBar.showLw(true);
-                    mDockBottom = mTmpNavigationFrame.top;
-                    mRestrictedScreenHeight = mDockBottom - mDockTop;
-                } else {
-                    // We currently want to hide the navigation UI.
-                    mNavigationBar.hideLw(true);
-                }
-                if (navVisible && !mNavigationBar.isAnimatingLw()) {
-                    // If the nav bar is currently requested to be visible,
-                    // and not in the process of animating on or off, then
-                    // we can tell the app that it is covered by it.
-                    mSystemBottom = mTmpNavigationFrame.top;
-                }
-            } else {
-                // Landscape screen; nav bar goes to the right.
-                int left = displayWidth - mNavigationBarWidthForRotation[displayRotation];
-                if (mHdmiPlugged) {
-                    if (left > mExternalDisplayWidth) {
-                        left = mExternalDisplayWidth;
-                    }
-                }
-                mTmpNavigationFrame.set(left, 0, displayWidth, displayHeight);
-                mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
-                if (navVisible) {
-                    mNavigationBar.showLw(true);
-                    mDockRight = mTmpNavigationFrame.left;
-                    mRestrictedScreenWidth = mDockRight - mDockLeft;
-                } else {
-                    // We currently want to hide the navigation UI.
-                    mNavigationBar.hideLw(true);
-                }
-                if (navVisible && !mNavigationBar.isAnimatingLw()) {
-                    // If the nav bar is currently requested to be visible,
-                    // and not in the process of animating on or off, then
-                    // we can tell the app that it is covered by it.
-                    mSystemRight = mTmpNavigationFrame.left;
-                }
-            }
-            // Make sure the content and current rectangles are updated to
-            // account for the restrictions from the navigation bar.
-            mContentTop = mCurTop = mDockTop;
-            mContentBottom = mCurBottom = mDockBottom;
-            mContentLeft = mCurLeft = mDockLeft;
-            mContentRight = mCurRight = mDockRight;
-            mStatusBarLayer = mNavigationBar.getSurfaceLayer();
-            // And compute the final frame.
-            mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
-                    mTmpNavigationFrame, mTmpNavigationFrame);
-            if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
-        }
-        if (DEBUG_LAYOUT) Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
-                mDockLeft, mDockTop, mDockRight, mDockBottom));
-
-        // decide where the status bar goes ahead of time
-        if (mStatusBar != null) {
-            // apply any navigation bar insets
-            pf.left = df.left = mUnrestrictedScreenLeft;
-            pf.top = df.top = mUnrestrictedScreenTop;
-            pf.right = df.right = mUnrestrictedScreenWidth - mUnrestrictedScreenLeft;
-            pf.bottom = df.bottom = mUnrestrictedScreenHeight - mUnrestrictedScreenTop;
-            vf.left = mStableLeft;
-            vf.top = mStableTop;
-            vf.right = mStableRight;
-            vf.bottom = mStableBottom;
-
-            mStatusBarLayer = mStatusBar.getSurfaceLayer();
-
-            // Let the status bar determine its size.
-            mStatusBar.computeFrameLw(pf, df, vf, vf);
-
-            // For layout, the status bar is always at the top with our fixed height.
-            mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
-
-            // If the status bar is hidden, we don't want to cause
-            // windows behind it to scroll.
-            if (mStatusBar.isVisibleLw()) {
-                // Status bar may go away, so the screen area it occupies
-                // is available to apps but just covering them when the
-                // status bar is visible.
-                mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
-                
+                // Make sure the content and current rectangles are updated to
+                // account for the restrictions from the navigation bar.
                 mContentTop = mCurTop = mDockTop;
                 mContentBottom = mCurBottom = mDockBottom;
                 mContentLeft = mCurLeft = mDockLeft;
                 mContentRight = mCurRight = mDockRight;
-
-                if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: " +
-                    String.format(
-                        "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
-                        mDockLeft, mDockTop, mDockRight, mDockBottom,
-                        mContentLeft, mContentTop, mContentRight, mContentBottom,
-                        mCurLeft, mCurTop, mCurRight, mCurBottom));
+                mStatusBarLayer = mNavigationBar.getSurfaceLayer();
+                // And compute the final frame.
+                mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
+                        mTmpNavigationFrame, mTmpNavigationFrame);
+                if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
             }
-            if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()) {
-                // If the status bar is currently requested to be visible,
-                // and not in the process of animating on or off, then
-                // we can tell the app that it is covered by it.
-                mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
+            if (DEBUG_LAYOUT) Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
+                    mDockLeft, mDockTop, mDockRight, mDockBottom));
+
+            // decide where the status bar goes ahead of time
+            if (mStatusBar != null) {
+                // apply any navigation bar insets
+                pf.left = df.left = mUnrestrictedScreenLeft;
+                pf.top = df.top = mUnrestrictedScreenTop;
+                pf.right = df.right = mUnrestrictedScreenWidth - mUnrestrictedScreenLeft;
+                pf.bottom = df.bottom = mUnrestrictedScreenHeight - mUnrestrictedScreenTop;
+                vf.left = mStableLeft;
+                vf.top = mStableTop;
+                vf.right = mStableRight;
+                vf.bottom = mStableBottom;
+
+                mStatusBarLayer = mStatusBar.getSurfaceLayer();
+
+                // Let the status bar determine its size.
+                mStatusBar.computeFrameLw(pf, df, vf, vf);
+
+                // For layout, the status bar is always at the top with our fixed height.
+                mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
+
+                // If the status bar is hidden, we don't want to cause
+                // windows behind it to scroll.
+                if (mStatusBar.isVisibleLw()) {
+                    // Status bar may go away, so the screen area it occupies
+                    // is available to apps but just covering them when the
+                    // status bar is visible.
+                    mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
+
+                    mContentTop = mCurTop = mDockTop;
+                    mContentBottom = mCurBottom = mDockBottom;
+                    mContentLeft = mCurLeft = mDockLeft;
+                    mContentRight = mCurRight = mDockRight;
+
+                    if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: " +
+                        String.format(
+                            "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
+                            mDockLeft, mDockTop, mDockRight, mDockBottom,
+                            mContentLeft, mContentTop, mContentRight, mContentBottom,
+                            mCurLeft, mCurTop, mCurRight, mCurBottom));
+                }
+                if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()) {
+                    // If the status bar is currently requested to be visible,
+                    // and not in the process of animating on or off, then
+                    // we can tell the app that it is covered by it.
+                    mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
+                }
             }
         }
     }
@@ -2563,13 +2619,15 @@
     }
 
     /** {@inheritDoc} */
+    @Override
     public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs,
             WindowState attached) {
         // we've already done the status bar
         if (win == mStatusBar || win == mNavigationBar) {
             return;
         }
-        final boolean needsToOffsetInputMethodTarget =
+        final boolean isDefaultDisplay = win.isDefaultDisplay();
+        final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
                 (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
         if (needsToOffsetInputMethodTarget) {
             if (DEBUG_LAYOUT) {
@@ -2586,11 +2644,27 @@
         final Rect df = mTmpDisplayFrame;
         final Rect cf = mTmpContentFrame;
         final Rect vf = mTmpVisibleFrame;
-        
-        final boolean hasNavBar = (mHasNavigationBar 
+
+        final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
                 && mNavigationBar != null && mNavigationBar.isVisibleLw());
 
-        if (attrs.type == TYPE_INPUT_METHOD) {
+        final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
+
+        if (!isDefaultDisplay) {
+            if (attached != null) {
+                // If this window is attached to another, our display
+                // frame is the same as the one we are attached to.
+                setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, cf, vf);
+            } else {
+                // Give the window full screen.
+                pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
+                pf.top = df.top = cf.top = mUnrestrictedScreenTop;
+                pf.right = df.right = cf.right
+                        = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
+                pf.bottom = df.bottom = cf.bottom
+                        = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
+            }
+        } else  if (attrs.type == TYPE_INPUT_METHOD) {
             pf.left = df.left = cf.left = vf.left = mDockLeft;
             pf.top = df.top = cf.top = vf.top = mDockTop;
             pf.right = df.right = cf.right = vf.right = mDockRight;
@@ -2599,8 +2673,6 @@
             attrs.gravity = Gravity.BOTTOM;
             mDockLayer = win.getSurfaceLayer();
         } else {
-            final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
-
             if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
                     == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)
                     && (sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
@@ -2614,7 +2686,7 @@
                 if (attached != null) {
                     // If this window is attached to another, our display
                     // frame is the same as the one we are attached to.
-                    setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf);
+                    setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, cf, vf);
                 } else {
                     if (attrs.type == TYPE_STATUS_BAR_PANEL
                             || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
@@ -2657,6 +2729,7 @@
                         pf.right = df.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
                         pf.bottom = df.bottom = mRestrictedScreenTop+mRestrictedScreenHeight;
                     }
+
                     if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
                         cf.left = mDockLeft;
                         cf.top = mDockTop;
@@ -2668,6 +2741,7 @@
                         cf.right = mContentRight;
                         cf.bottom = mContentBottom;
                     }
+
                     applyStableConstraints(sysUiFl, fl, cf);
                     if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
                         vf.left = mCurLeft;
@@ -2720,7 +2794,8 @@
                     pf.top = df.top = mUnrestrictedScreenTop;
                     pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
                     pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
-                } else if (attrs.type == TYPE_BOOT_PROGRESS) {
+                } else if (attrs.type == TYPE_BOOT_PROGRESS
+                        || attrs.type == TYPE_UNIVERSE_BACKGROUND) {
                     // Boot progress screen always covers entire display.
                     pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
                     pf.top = df.top = cf.top = mUnrestrictedScreenTop;
@@ -2750,7 +2825,9 @@
                     pf.bottom = df.bottom = cf.bottom
                             = mRestrictedScreenTop+mRestrictedScreenHeight;
                 }
+
                 applyStableConstraints(sysUiFl, fl, cf);
+
                 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
                     vf.left = mCurLeft;
                     vf.top = mCurTop;
@@ -2807,7 +2884,7 @@
                 }
             }
         }
-        
+
         if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0) {
             df.left = df.top = cf.left = cf.top = vf.left = vf.top = -10000;
             df.right = df.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
@@ -2819,12 +2896,13 @@
                 + String.format(" flags=0x%08x", fl)
                 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
                 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString());
-        
+
         win.computeFrameLw(pf, df, cf, vf);
-        
+
         // Dock windows carve out the bottom of the screen, so normal windows
         // can't appear underneath them.
-        if (attrs.type == TYPE_INPUT_METHOD && !win.getGivenInsetsPendingLw()) {
+        if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleOrBehindKeyguardLw()
+                && !win.getGivenInsetsPendingLw()) {
             setLastInputMethodWindowLw(null, null);
             offsetInputMethodWindowLw(win);
         }
@@ -2853,39 +2931,66 @@
     }
 
     /** {@inheritDoc} */
-    public void beginAnimationLw(int displayWidth, int displayHeight) {
+    @Override
+    public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
         mTopFullscreenOpaqueWindowState = null;
         mForceStatusBar = false;
+        mForceStatusBarFromKeyguard = false;
         
         mHideLockScreen = false;
         mAllowLockscreenWhenOn = false;
-        mDismissKeyguard = false;
+        mDismissKeyguard = DISMISS_KEYGUARD_NONE;
+        mShowingLockscreen = false;
+        mShowingDream = false;
     }
 
     /** {@inheritDoc} */
-    public void animatingWindowLw(WindowState win,
+    @Override
+    public void applyPostLayoutPolicyLw(WindowState win,
                                 WindowManager.LayoutParams attrs) {
         if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
                 + win.isVisibleOrBehindKeyguardLw());
         if (mTopFullscreenOpaqueWindowState == null &&
                 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
             if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
-                mForceStatusBar = true;
+                if (attrs.type == TYPE_KEYGUARD) {
+                    mForceStatusBarFromKeyguard = true;
+                } else {
+                    mForceStatusBar = true;
+                }
             }
-            if (attrs.type >= FIRST_APPLICATION_WINDOW
-                    && attrs.type <= LAST_APPLICATION_WINDOW
+            if (attrs.type == TYPE_KEYGUARD) {
+                mShowingLockscreen = true;
+            }
+            boolean applyWindow = attrs.type >= FIRST_APPLICATION_WINDOW
+                    && attrs.type <= LAST_APPLICATION_WINDOW;
+            if (attrs.type == TYPE_DREAM) {
+                // If the lockscreen was showing when the dream started then wait
+                // for the dream to draw before hiding the lockscreen.
+                if (!mDreamingLockscreen
+                        || (win.isVisibleLw() && win.hasDrawnLw())) {
+                    mShowingDream = true;
+                    applyWindow = true;
+                }
+            }
+            if (applyWindow
                     && attrs.x == 0 && attrs.y == 0
                     && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
                     && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
                 if (DEBUG_LAYOUT) Log.v(TAG, "Fullscreen window: " + win);
                 mTopFullscreenOpaqueWindowState = win;
                 if ((attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
-                    if (localLOGV) Log.v(TAG, "Setting mHideLockScreen to true by win " + win);
+                    if (DEBUG_LAYOUT) Log.v(TAG, "Setting mHideLockScreen to true by win " + win);
                     mHideLockScreen = true;
+                    mForceStatusBarFromKeyguard = false;
                 }
-                if ((attrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
-                    if (localLOGV) Log.v(TAG, "Setting mDismissKeyguard to true by win " + win);
-                    mDismissKeyguard = true;
+                if ((attrs.flags & FLAG_DISMISS_KEYGUARD) != 0
+                        && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
+                    if (DEBUG_LAYOUT) Log.v(TAG, "Setting mDismissKeyguard to true by win " + win);
+                    mDismissKeyguard = mWinDismissingKeyguard == win ?
+                            DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
+                    mWinDismissingKeyguard = win;
+                    mForceStatusBarFromKeyguard = false;
                 }
                 if ((attrs.flags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
                     mAllowLockscreenWhenOn = true;
@@ -2895,7 +3000,8 @@
     }
 
     /** {@inheritDoc} */
-    public int finishAnimationLw() {
+    @Override
+    public int finishPostLayoutPolicyLw() {
         int changes = 0;
         boolean topIsFullscreen = false;
 
@@ -2903,10 +3009,19 @@
                 ? mTopFullscreenOpaqueWindowState.getAttrs()
                 : null;
 
+        // If we are not currently showing a dream then remember the current
+        // lockscreen state.  We will use this to determine whether the dream
+        // started while the lockscreen was showing and remember this state
+        // while the dream is showing.
+        if (!mShowingDream) {
+            mDreamingLockscreen = mShowingLockscreen;
+        }
+
         if (mStatusBar != null) {
             if (DEBUG_LAYOUT) Log.i(TAG, "force=" + mForceStatusBar
+                    + " forcefkg=" + mForceStatusBarFromKeyguard
                     + " top=" + mTopFullscreenOpaqueWindowState);
-            if (mForceStatusBar) {
+            if (mForceStatusBar || mForceStatusBarFromKeyguard) {
                 if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar: forced");
                 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
             } else if (mTopFullscreenOpaqueWindowState != null) {
@@ -2927,11 +3042,13 @@
                     if (mStatusBar.hideLw(true)) {
                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
 
-                        mHandler.post(new Runnable() { public void run() {
+                        mHandler.post(new Runnable() {
+                            @Override
+                            public void run() {
                             try {
                                 IStatusBarService statusbar = getStatusBarService();
                                 if (statusbar != null) {
-                                    statusbar.collapse();
+                                    statusbar.collapsePanels();
                                 }
                             } catch (RemoteException ex) {
                                 // re-acquire status bar service next time it is needed.
@@ -2950,11 +3067,12 @@
 
         mTopIsFullscreen = topIsFullscreen;
 
-        // Hide the key guard if a visible window explicitly specifies that it wants to be displayed
-        // when the screen is locked
+        // Hide the key guard if a visible window explicitly specifies that it wants to be
+        // displayed when the screen is locked.
         if (mKeyguard != null) {
-            if (localLOGV) Log.v(TAG, "finishAnimationLw::mHideKeyguard="+mHideLockScreen);
-            if (mDismissKeyguard && !mKeyguardMediator.isSecure()) {
+            if (localLOGV) Log.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
+                    + mHideLockScreen);
+            if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardMediator.isSecure()) {
                 if (mKeyguard.hideLw(true)) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT
                             | FINISH_LAYOUT_REDO_CONFIG
@@ -2962,6 +3080,7 @@
                 }
                 if (mKeyguardMediator.isShowing()) {
                     mHandler.post(new Runnable() {
+                        @Override
                         public void run() {
                             mKeyguardMediator.keyguardDone(false, false);
                         }
@@ -2974,7 +3093,25 @@
                             | FINISH_LAYOUT_REDO_WALLPAPER;
                 }
                 mKeyguardMediator.setHidden(true);
+            } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) {
+                // This is the case of keyguard isSecure() and not mHideLockScreen.
+                if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
+                    // Only launch the next keyguard unlock window once per window.
+                    if (mKeyguard.showLw(true)) {
+                        changes |= FINISH_LAYOUT_REDO_LAYOUT
+                                | FINISH_LAYOUT_REDO_CONFIG
+                                | FINISH_LAYOUT_REDO_WALLPAPER;
+                    }
+                    mKeyguardMediator.setHidden(false);
+                    mHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            mKeyguardMediator.dismiss();
+                        }
+                    });
+                }
             } else {
+                mWinDismissingKeyguard = null;
                 if (mKeyguard.showLw(true)) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT
                             | FINISH_LAYOUT_REDO_CONFIG
@@ -3031,30 +3168,23 @@
 
         if (lidOpen) {
             if (keyguardIsShowingTq()) {
-                mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(
-                        KeyEvent.KEYCODE_POWER, mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
+                mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(KeyEvent.KEYCODE_POWER);
             } else {
-                mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
-                        LocalPowerManager.BUTTON_EVENT);
+                mPowerManager.wakeUp(SystemClock.uptimeMillis());
             }
         } else if (!mLidControlsSleep) {
-            mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
-                    LocalPowerManager.OTHER_EVENT);
+            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
         }
     }
 
     void setHdmiPlugged(boolean plugged) {
         if (mHdmiPlugged != plugged) {
             mHdmiPlugged = plugged;
-            if (plugged && mDisplay != null) {
-                mExternalDisplayWidth = mDisplay.getRawExternalWidth();
-                mExternalDisplayHeight = mDisplay.getRawExternalHeight();
-            }
             updateRotation(true, true);
             Intent intent = new Intent(ACTION_HDMI_PLUGGED);
             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
             intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
-            mContext.sendStickyBroadcast(intent);
+            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
         }
     }
 
@@ -3192,7 +3322,8 @@
                 @Override
                 public void onServiceDisconnected(ComponentName name) {}
             };
-            if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
+            if (mContext.bindService(
+                    intent, conn, Context.BIND_AUTO_CREATE, UserHandle.USER_CURRENT)) {
                 mScreenshotConnection = conn;
                 mHandler.postDelayed(mScreenshotTimeout, 10000);
             }
@@ -3202,6 +3333,11 @@
     /** {@inheritDoc} */
     @Override
     public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
+        if (!mSystemBooted) {
+            // If we have not yet booted, don't let key events do anything.
+            return 0;
+        }
+
         final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
         final boolean canceled = event.isCanceled();
         final int keyCode = event.getKeyCode();
@@ -3217,14 +3353,17 @@
                                                 mKeyguardMediator.isShowingAndNotHidden() :
                                                 mKeyguardMediator.isShowing()));
 
-        if (!mSystemBooted) {
-            // If we have not yet booted, don't let key events do anything.
-            return 0;
+        if (keyCode == KeyEvent.KEYCODE_POWER) {
+            policyFlags |= WindowManagerPolicy.FLAG_WAKE;
         }
+        final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE
+                | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
 
         if (DEBUG_INPUT) {
             Log.d(TAG, "interceptKeyTq keycode=" + keyCode
-                  + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive);
+                    + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive
+                    + " policyFlags=" + Integer.toHexString(policyFlags)
+                    + " isWakeKey=" + isWakeKey);
         }
 
         if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
@@ -3232,12 +3371,6 @@
             performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
         }
 
-        if (keyCode == KeyEvent.KEYCODE_POWER) {
-            policyFlags |= WindowManagerPolicy.FLAG_WAKE;
-        }
-        final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE
-                | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
-
         // Basic policy based on screen state and keyguard.
         // FIXME: This policy isn't quite correct.  We shouldn't care whether the screen
         //        is on or off, really.  We should care about whether the device is in an
@@ -3254,14 +3387,13 @@
             // When the screen is off and the key is not injected, determine whether
             // to wake the device but don't pass the key to the application.
             result = 0;
-            if (down && isWakeKey) {
+            if (down && isWakeKey && isWakeKeyWhenScreenOff(keyCode)) {
                 if (keyguardActive) {
-                    // If the keyguard is showing, let it decide what to do with the wake key.
-                    mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode,
-                            mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
+                    // If the keyguard is showing, let it wake the device when ready.
+                    mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode);
                 } else {
                     // Otherwise, wake the device ourselves.
-                    result |= ACTION_POKE_USER_ACTIVITY;
+                    result |= ACTION_WAKE_UP;
                 }
             }
         }
@@ -3366,7 +3498,7 @@
                         }
                         if ((mEndcallBehavior
                                 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
-                            result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
+                            result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP;
                         }
                     }
                 }
@@ -3408,7 +3540,7 @@
                     mPowerKeyTriggered = false;
                     cancelPendingScreenshotChordAction();
                     if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
-                        result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
+                        result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP;
                     }
                     mPendingPowerKeyUpCanceled = false;
                 }
@@ -3480,6 +3612,40 @@
         return result;
     }
 
+    /**
+     * When the screen is off we ignore some keys that might otherwise typically
+     * be considered wake keys.  We filter them out here.
+     *
+     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
+     * is always considered a wake key.
+     */
+    private boolean isWakeKeyWhenScreenOff(int keyCode) {
+        switch (keyCode) {
+            // ignore volume keys unless docked
+            case KeyEvent.KEYCODE_VOLUME_UP:
+            case KeyEvent.KEYCODE_VOLUME_DOWN:
+            case KeyEvent.KEYCODE_VOLUME_MUTE:
+                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
+
+            // ignore media and camera keys
+            case KeyEvent.KEYCODE_MUTE:
+            case KeyEvent.KEYCODE_HEADSETHOOK:
+            case KeyEvent.KEYCODE_MEDIA_PLAY:
+            case KeyEvent.KEYCODE_MEDIA_PAUSE:
+            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+            case KeyEvent.KEYCODE_MEDIA_STOP:
+            case KeyEvent.KEYCODE_MEDIA_NEXT:
+            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+            case KeyEvent.KEYCODE_MEDIA_REWIND:
+            case KeyEvent.KEYCODE_MEDIA_RECORD:
+            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
+            case KeyEvent.KEYCODE_CAMERA:
+                return false;
+        }
+        return true;
+    }
+
+
     /** {@inheritDoc} */
     @Override
     public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
@@ -3493,7 +3659,7 @@
                 mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
             } else {
                 // Otherwise, wake the device ourselves.
-                result |= ACTION_POKE_USER_ACTIVITY;
+                result |= ACTION_WAKE_UP;
             }
         }
         return result;
@@ -3560,29 +3726,41 @@
             if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
                 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
                         Intent.EXTRA_DOCK_STATE_UNDOCKED);
-            } else {
-                try {
-                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
-                            ServiceManager.getService(Context.UI_MODE_SERVICE));
-                    mUiMode = uiModeService.getCurrentModeType();
-                } catch (RemoteException e) {
-                }
             }
             updateRotation(true);
             updateOrientationListenerLp();
         }
     };
 
-    BroadcastReceiver mPowerReceiver = new BroadcastReceiver() {
+    BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
+        @Override
         public void onReceive(Context context, Intent intent) {
-            if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
-                mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
-                if (localLOGV) Log.v(TAG, "BATTERY_CHANGED: " + intent + " plugged=" + mPluggedIn);
+            if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
+                if (mKeyguardMediator != null) {
+                    mKeyguardMediator.onDreamingStarted();
+                }
+            } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
+                if (mKeyguardMediator != null) {
+                    mKeyguardMediator.onDreamingStopped();
+                }
             }
         }
     };
 
-    /** {@inheritDoc} */
+    BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
+                // tickle the settings observer: this first ensures that we're
+                // observing the relevant settings for the newly-active user,
+                // and then updates our own bookkeeping based on the now-
+                // current user.
+                mSettingsObserver.onChange(false);
+            }
+        }
+    };
+
+    @Override
     public void screenTurnedOff(int why) {
         EventLog.writeEvent(70000, 0);
         synchronized (mLock) {
@@ -3598,7 +3776,7 @@
         }
     }
 
-    /** {@inheritDoc} */
+    @Override
     public void screenTurningOn(final ScreenOnListener screenOnListener) {
         EventLog.writeEvent(70000, 1);
         if (false) {
@@ -3606,64 +3784,83 @@
             here.fillInStackTrace();
             Slog.i(TAG, "Screen turning on...", here);
         }
-        if (screenOnListener != null) {
-            if (mKeyguardMediator != null) {
-                try {
-                    mWindowManager.setEventDispatching(true);
-                } catch (RemoteException unhandled) {
-                }
-                mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() {
-                    @Override public void onShown(IBinder windowToken) {
-                        if (windowToken != null) {
-                            try {
-                                mWindowManager.waitForWindowDrawn(windowToken,
-                                        new IRemoteCallback.Stub() {
-                                    @Override public void sendResult(Bundle data) {
-                                        Slog.i(TAG, "Lock screen displayed!");
-                                        screenOnListener.onScreenOn();
-                                        synchronized (mLock) {
-                                            mScreenOnFully = true;
-                                        }
-                                    }
-                                });
-                            } catch (RemoteException e) {
-                            }
-                        } else {
-                            Slog.i(TAG, "No lock screen!");
-                            screenOnListener.onScreenOn();
-                            synchronized (mLock) {
-                                mScreenOnFully = true;
-                            }
-                        }
-                    }
-                });
-            }
-        } else {
-            if (mKeyguardMediator != null) {
-                // Must set mScreenOn = true.
-                mKeyguardMediator.onScreenTurnedOn(null);
-            }
-            synchronized (mLock) {
-                mScreenOnFully = true;
-            }
-        }
+
         synchronized (mLock) {
             mScreenOnEarly = true;
             updateOrientationListenerLp();
             updateLockScreenTimeout();
         }
+
+        waitForKeyguard(screenOnListener);
     }
 
-    /** {@inheritDoc} */
+    private void waitForKeyguard(final ScreenOnListener screenOnListener) {
+        if (mKeyguardMediator != null) {
+            if (screenOnListener != null) {
+                mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() {
+                    @Override
+                    public void onShown(IBinder windowToken) {
+                        waitForKeyguardWindowDrawn(windowToken, screenOnListener);
+                    }
+                });
+                return;
+            } else {
+                mKeyguardMediator.onScreenTurnedOn(null);
+            }
+        } else {
+            Slog.i(TAG, "No keyguard mediator!");
+        }
+        finishScreenTurningOn(screenOnListener);
+    }
+
+    private void waitForKeyguardWindowDrawn(IBinder windowToken,
+            final ScreenOnListener screenOnListener) {
+        if (windowToken != null) {
+            try {
+                if (mWindowManager.waitForWindowDrawn(
+                        windowToken, new IRemoteCallback.Stub() {
+                    @Override
+                    public void sendResult(Bundle data) {
+                        Slog.i(TAG, "Lock screen displayed!");
+                        finishScreenTurningOn(screenOnListener);
+                    }
+                })) {
+                    return;
+                }
+            } catch (RemoteException ex) {
+                // Can't happen in system process.
+            }
+        }
+
+        Slog.i(TAG, "No lock screen!");
+        finishScreenTurningOn(screenOnListener);
+    }
+
+    private void finishScreenTurningOn(ScreenOnListener screenOnListener) {
+        synchronized (mLock) {
+            mScreenOnFully = true;
+        }
+
+        try {
+            mWindowManager.setEventDispatching(true);
+        } catch (RemoteException unhandled) {
+        }
+
+        if (screenOnListener != null) {
+            screenOnListener.onScreenOn();
+        }
+    }
+
+    @Override
     public boolean isScreenOnEarly() {
         return mScreenOnEarly;
     }
-    
-    /** {@inheritDoc} */
+
+    @Override
     public boolean isScreenOnFully() {
         return mScreenOnFully;
     }
-    
+
     /** {@inheritDoc} */
     public void enableKeyguard(boolean enabled) {
         if (mKeyguardMediator != null) {
@@ -3702,14 +3899,18 @@
     }
 
     public void dismissKeyguardLw() {
-        if (!mKeyguardMediator.isSecure()) {
-            if (mKeyguardMediator.isShowing()) {
-                mHandler.post(new Runnable() {
-                    public void run() {
+        if (mKeyguardMediator.isShowing()) {
+            mHandler.post(new Runnable() {
+                public void run() {
+                    if (mKeyguardMediator.isDismissable()) {
+                        // Can we just finish the keyguard straight away?
                         mKeyguardMediator.keyguardDone(false, true);
+                    } else {
+                        // ask the keyguard to prompt the user to authenticate if necessary
+                        mKeyguardMediator.dismiss();
                     }
-                });
-            }
+                }
+            });
         }
     }
 
@@ -3767,7 +3968,7 @@
                 // enable 180 degree rotation while docked.
                 preferredRotation = mDeskDockEnablesAccelerometer
                         ? sensorRotation : mDeskDockRotation;
-            } else if (mHdmiPlugged) {
+            } else if (mHdmiPlugged && mHdmiRotationLock) {
                 // Ignore sensor when plugged into HDMI.
                 // Note that the dock orientation overrides the HDMI orientation.
                 preferredRotation = mHdmiRotation;
@@ -3905,16 +4106,19 @@
 
         // mUserRotationMode and mUserRotation will be assigned by the content observer
         if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
-            Settings.System.putInt(res,
+            Settings.System.putIntForUser(res,
                     Settings.System.USER_ROTATION,
-                    rot);
-            Settings.System.putInt(res,
+                    rot,
+                    UserHandle.USER_CURRENT);
+            Settings.System.putIntForUser(res,
                     Settings.System.ACCELEROMETER_ROTATION,
-                    0);
+                    0,
+                    UserHandle.USER_CURRENT);
         } else {
-            Settings.System.putInt(res,
+            Settings.System.putIntForUser(res,
                     Settings.System.ACCELEROMETER_ROTATION,
-                    1);
+                    1,
+                    UserHandle.USER_CURRENT);
         }
     }
 
@@ -4046,75 +4250,36 @@
         }
     }
 
-    private IDreamManager getDreamManager() {
-        if (!mScreenSaverFeatureAvailable) {
-            return null;
-        }
-        
-        IDreamManager sandman = IDreamManager.Stub.asInterface(
-                ServiceManager.checkService("dreams"));
-        if (sandman == null) {
-            Log.w(TAG, "Unable to find IDreamManager");
-        }
-        return sandman;
-    }
+    class ScreenLockTimeout implements Runnable {
+        Bundle options;
 
-    @Override
-    public boolean isScreenSaverEnabled() {
-        return (mScreenSaverFeatureAvailable && mScreenSaverEnabledByUser
-                && mScreenSaverMayRun && mScreenOnEarly && mPluggedIn);
-    }
-
-    @Override
-    public boolean startScreenSaver() {
-        synchronized (mLock) {
-            if (isScreenSaverEnabled()) {
-                IDreamManager dm = getDreamManager();
-                if (dm == null) return false;
-                
-                try {
-                    if (localLOGV) Log.v(TAG, "startScreenSaver: entering dreamland...");
-
-                    dm.dream();
-                    return true;
-                } catch (RemoteException ex) {
-                    // too bad, so sad, oh mom, oh dad
-                }
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public void stopScreenSaver() {
-        synchronized (mLock) {
-            IDreamManager dm = getDreamManager();
-            if (dm == null) return;
-            
-            try {
-                if (localLOGV) Log.v(TAG, "startScreenSaver: awakening...");
-                
-                dm.awaken();
-            } catch (RemoteException ex) {
-            }
-        }
-    }
-
-    Runnable mScreenLockTimeout = new Runnable() {
+        @Override
         public void run() {
             synchronized (this) {
                 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
                 if (mKeyguardMediator != null) {
-                    mKeyguardMediator.doKeyguardTimeout();
+                    mKeyguardMediator.doKeyguardTimeout(options);
                 }
                 mLockScreenTimerActive = false;
+                options = null;
             }
         }
-    };
 
-    public void lockNow() {
+        public void setLockOptions(Bundle options) {
+            this.options = options;
+        }
+    }
+
+    ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
+
+    public void lockNow(Bundle options) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
         mHandler.removeCallbacks(mScreenLockTimeout);
+        if (options != null) {
+            // In case multiple calls are made to lockNow, we don't wipe out the options
+            // until the runnable actually executes.
+            mScreenLockTimeout.setLockOptions(options);
+        }
         mHandler.post(mScreenLockTimeout);
     }
 
@@ -4143,8 +4308,6 @@
     }
 
     private void applyLidSwitchState() {
-        mPowerManager.setKeyboardVisibility(isBuiltInKeyboardVisible());
-
         if (mLidState == LID_CLOSED && mLidControlsSleep) {
             mPowerManager.goToSleep(SystemClock.uptimeMillis());
         }
@@ -4168,64 +4331,9 @@
         }
     }
 
-    /**
-     * Return an Intent to launch the currently active dock app as home.  Returns
-     * null if the standard home should be launched, which is the case if any of the following is
-     * true:
-     * <ul>
-     *  <li>The device is not in either car mode or desk mode
-     *  <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false
-     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
-     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
-     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
-     * </ul>
-     * @return
-     */
-    Intent createHomeDockIntent() {
-        Intent intent = null;
-        
-        // What home does is based on the mode, not the dock state.  That
-        // is, when in car mode you should be taken to car home regardless
-        // of whether we are actually in a car dock.
-        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
-            if (ENABLE_CAR_DOCK_HOME_CAPTURE) {
-                intent = mCarDockIntent;
-            }
-        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
-            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
-                intent = mDeskDockIntent;
-            }
-        }
-
-        if (intent == null) {
-            return null;
-        }
-        
-        ActivityInfo ai = intent.resolveActivityInfo(
-                mContext.getPackageManager(), PackageManager.GET_META_DATA);
-        if (ai == null) {
-            return null;
-        }
-        
-        if (ai.metaData != null && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
-            intent = new Intent(intent);
-            intent.setClassName(ai.packageName, ai.name);
-            return intent;
-        }
-        
-        return null;
-    }
-    
     void startDockOrHome() {
-        Intent dock = createHomeDockIntent();
-        if (dock != null) {
-            try {
-                mContext.startActivity(dock);
-                return;
-            } catch (ActivityNotFoundException e) {
-            }
-        }
-        mContext.startActivity(mHomeIntent);
+        // We don't have dock home anymore. Home is home. If you lived here, you'd be home by now.
+        mContext.startActivityAsUser(mHomeIntent, UserHandle.CURRENT);
     }
     
     /**
@@ -4251,25 +4359,13 @@
                 } else {
                     ActivityManagerNative.getDefault().stopAppSwitches();
                     sendCloseSystemWindows();
-                    Intent dock = createHomeDockIntent();
-                    if (dock != null) {
-                        int result = ActivityManagerNative.getDefault()
-                                .startActivity(null, dock,
-                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
-                                        null, null, 0,
-                                        ActivityManager.START_FLAG_ONLY_IF_NEEDED,
-                                        null, null, null);
-                        if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
-                            return false;
-                        }
-                    }
                 }
                 int result = ActivityManagerNative.getDefault()
-                        .startActivity(null, mHomeIntent,
+                        .startActivityAsUser(null, mHomeIntent,
                                 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
                                 null, null, 0,
                                 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
-                                null, null, null);
+                                null, null, null, UserHandle.USER_CURRENT);
                 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
                     return false;
                 }
@@ -4289,9 +4385,31 @@
         }
     }
 
+    private void performAuditoryFeedbackForAccessibilityIfNeed() {
+        if (!isGlobalAccessibilityGestureEnabled()) {
+            return;
+        }
+        AudioManager audioManager = (AudioManager) mContext.getSystemService(
+                Context.AUDIO_SERVICE);
+        if (audioManager.isSilentMode()) {
+            return;
+        }
+        Ringtone ringTone = RingtoneManager.getRingtone(mContext,
+                Settings.System.DEFAULT_NOTIFICATION_URI);
+        ringTone.setStreamType(AudioManager.STREAM_MUSIC);
+        ringTone.play();
+    }
+    private boolean isGlobalAccessibilityGestureEnabled() {
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1;
+    }
+
     public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
-        final boolean hapticsDisabled = Settings.System.getInt(mContext.getContentResolver(),
-                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0;
+        if (!mVibrator.hasVibrator()) {
+            return false;
+        }
+        final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
+                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
         if (!always && (hapticsDisabled || mKeyguardMediator.isShowingAndNotHidden())) {
             return false;
         }
@@ -4324,41 +4442,34 @@
         }
         return true;
     }
-    
-    public void screenOnStartedLw() {
-        // The window manager has just grabbed a wake lock. This is our cue to disable the screen
-        // saver.
-        synchronized (mLock) {
-            mScreenSaverMayRun = false;
-        }
+
+    @Override
+    public void keepScreenOnStartedLw() {
     }
 
-    public void screenOnStoppedLw() {
-        if (mPowerManager.isScreenOn()) {
-            if (mKeyguardMediator != null && !mKeyguardMediator.isShowingAndNotHidden()) {
-                long curTime = SystemClock.uptimeMillis();
-                mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
-            }
-
-            synchronized (mLock) {
-                // even if the keyguard is up, now that all the wakelocks have been released, we
-                // should re-enable the screen saver
-                mScreenSaverMayRun = true;
-            }
+    @Override
+    public void keepScreenOnStoppedLw() {
+        if (mKeyguardMediator != null && !mKeyguardMediator.isShowingAndNotHidden()) {
+            long curTime = SystemClock.uptimeMillis();
+            mPowerManager.userActivity(curTime, false);
         }
     }
 
-    public boolean allowKeyRepeat() {
-        // disable key repeat when screen is off
-        return mScreenOnEarly;
-    }
-
     private int updateSystemUiVisibilityLw() {
         // If there is no window focused, there will be nobody to handle the events
         // anyway, so just hang on in whatever state we're in until things settle down.
         if (mFocusedWindow == null) {
             return 0;
         }
+        if (mFocusedWindow.getAttrs().type == TYPE_KEYGUARD && mHideLockScreen == true) {
+            // We are updating at a point where the keyguard has gotten
+            // focus, but we were last in a state where the top window is
+            // hiding it.  This is probably because the keyguard as been
+            // shown while the top window was displayed, so we want to ignore
+            // it here because this is just a very transient change and it
+            // will quickly lose focus once it correctly gets hidden.
+            return 0;
+        }
         final int visibility = mFocusedWindow.getSystemUiVisibility()
                 & ~mResettingSystemUiFlags
                 & ~mForceClearedSystemUiFlags;
@@ -4400,6 +4511,40 @@
         mLastInputMethodTargetWindow = target;
     }
 
+    @Override
+    public boolean canMagnifyWindowLw(WindowManager.LayoutParams attrs) {
+        switch (attrs.type) {
+            case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
+            case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
+            case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
+            case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void setCurrentUserLw(int newUserId) {
+        if (mKeyguardMediator != null) {
+            mKeyguardMediator.setCurrentUser(newUserId);
+        }
+        if (mStatusBarService != null) {
+            try {
+                mStatusBarService.setCurrentUser(newUserId);
+            } catch (RemoteException e) {
+                // oh well
+            }
+        }
+        setLastInputMethodWindowLw(null, null);
+    }
+
+    @Override
+    public void showAssistant() {
+        mKeyguardMediator.showAssistant();
+    }
+
+    @Override
     public void dump(String prefix, PrintWriter pw, String[] args) {
         pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
                 pw.print(" mSystemReady="); pw.print(mSystemReady);
@@ -4420,8 +4565,7 @@
             pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
                     pw.println(mLastFocusNeedsMenu);
         }
-        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
-                pw.print(" mDockMode="); pw.print(mDockMode);
+        pw.print(prefix); pw.print("mDockMode="); pw.print(mDockMode);
                 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
                 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
         pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
@@ -4476,12 +4620,52 @@
                 pw.print(","); pw.print(mDockBottom); pw.println(")");
         pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
                 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
-        pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
-                pw.println(mTopFullscreenOpaqueWindowState);
+        pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen);
+                pw.print(" mShowingDream="); pw.print(mShowingDream);
+                pw.print(" mDreamingLockscreen="); pw.println(mDreamingLockscreen);
+        if (mLastInputMethodWindow != null) {
+            pw.print(prefix); pw.print("mLastInputMethodWindow=");
+                    pw.println(mLastInputMethodWindow);
+        }
+        if (mLastInputMethodTargetWindow != null) {
+            pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
+                    pw.println(mLastInputMethodTargetWindow);
+        }
+        if (mStatusBar != null) {
+            pw.print(prefix); pw.print("mStatusBar=");
+                    pw.println(mStatusBar);
+        }
+        if (mNavigationBar != null) {
+            pw.print(prefix); pw.print("mNavigationBar=");
+                    pw.println(mNavigationBar);
+        }
+        if (mKeyguard != null) {
+            pw.print(prefix); pw.print("mKeyguard=");
+                    pw.println(mKeyguard);
+        }
+        if (mFocusedWindow != null) {
+            pw.print(prefix); pw.print("mFocusedWindow=");
+                    pw.println(mFocusedWindow);
+        }
+        if (mFocusedApp != null) {
+            pw.print(prefix); pw.print("mFocusedApp=");
+                    pw.println(mFocusedApp);
+        }
+        if (mWinDismissingKeyguard != null) {
+            pw.print(prefix); pw.print("mWinDismissingKeyguard=");
+                    pw.println(mWinDismissingKeyguard);
+        }
+        if (mTopFullscreenOpaqueWindowState != null) {
+            pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
+                    pw.println(mTopFullscreenOpaqueWindowState);
+        }
         pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
-                pw.print(" mForceStatusBar="); pw.print(mForceStatusBar);
                 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
+        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
+                pw.print(" mForceStatusBarFromKeyguard=");
+                pw.println(mForceStatusBarFromKeyguard);
         pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
+                pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard);
                 pw.print(" mHomePressed="); pw.println(mHomePressed);
         pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
                 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
@@ -4493,5 +4677,7 @@
                 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
         pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
                 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
+        pw.print(prefix); pw.print("mHdmiRotation="); pw.print(mHdmiRotation);
+                pw.print(" mHdmiRotationLock="); pw.println(mHdmiRotationLock);
     }
 }
diff --git a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
index b9903dd..2f0d7d6 100644
--- a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
+++ b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
@@ -94,7 +94,7 @@
 
         Window window = getWindow();
         window.requestFeature(Window.FEATURE_NO_TITLE);
-        window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
+        window.setType(WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY);
         window.setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
         window.setTitle("Recents");
diff --git a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
deleted file mode 100644
index 3b2a473..0000000
--- a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
+++ /dev/null
@@ -1,422 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import android.app.Dialog;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-
-import com.android.internal.telephony.ITelephony;
-import com.android.internal.widget.LockPatternUtils;
-
-import android.text.Editable;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.Button;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-import com.android.internal.R;
-
-/**
- * Displays a dialer like interface to unlock the SIM PUK.
- */
-public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen,
-        View.OnClickListener, View.OnFocusChangeListener {
-
-    private static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
-
-    private final KeyguardUpdateMonitor mUpdateMonitor;
-    private final KeyguardScreenCallback mCallback;
-    private KeyguardStatusViewManager mKeyguardStatusViewManager;
-
-    private TextView mHeaderText;
-    private TextView mPukText;
-    private TextView mPinText;
-    private TextView mFocusedEntry;
-
-    private View mOkButton;
-    private View mDelPukButton;
-    private View mDelPinButton;
-
-    private ProgressDialog mSimUnlockProgressDialog = null;
-
-    private LockPatternUtils mLockPatternUtils;
-
-    private int mCreationOrientation;
-
-    private int mKeyboardHidden;
-
-    private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
-
-    public SimPukUnlockScreen(Context context, Configuration configuration,
-            KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback,
-            LockPatternUtils lockpatternutils) {
-        super(context);
-        mUpdateMonitor = updateMonitor;
-        mCallback = callback;;
-
-        mCreationOrientation = configuration.orientation;
-        mKeyboardHidden = configuration.hardKeyboardHidden;
-        mLockPatternUtils = lockpatternutils;
-
-        LayoutInflater inflater = LayoutInflater.from(context);
-        if (mKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
-            inflater.inflate(
-                    R.layout.keyguard_screen_sim_puk_landscape, this, true);
-        } else {
-            inflater.inflate(
-                    R.layout.keyguard_screen_sim_puk_portrait, this, true);
-            new TouchInput();
-        }
-
-        mHeaderText = (TextView) findViewById(R.id.headerText);
-
-        mPukText = (TextView) findViewById(R.id.pukDisplay);
-        mPinText = (TextView) findViewById(R.id.pinDisplay);
-        mDelPukButton = findViewById(R.id.pukDel);
-        mDelPinButton = findViewById(R.id.pinDel);
-        mOkButton = findViewById(R.id.ok);
-
-        mDelPinButton.setOnClickListener(this);
-        mDelPukButton.setOnClickListener(this);
-        mOkButton.setOnClickListener(this);
-
-        mHeaderText.setText(R.string.keyguard_password_enter_puk_code);
-        // To make marquee work
-        mHeaderText.setSelected(true);
-
-        mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor,
-                lockpatternutils, callback, true);
-
-        mPinText.setFocusableInTouchMode(true);
-        mPinText.setOnFocusChangeListener(this);
-        mPukText.setFocusableInTouchMode(true);
-        mPukText.setOnFocusChangeListener(this);
-    }
-
-    /** {@inheritDoc} */
-    public boolean needsInput() {
-        return false;
-    }
-
-    /** {@inheritDoc} */
-    public void onPause() {
-        mKeyguardStatusViewManager.onPause();
-    }
-
-    /** {@inheritDoc} */
-    public void onResume() {
-        // start fresh
-        mHeaderText.setText(R.string.keyguard_password_enter_puk_code);
-        mKeyguardStatusViewManager.onResume();
-    }
-
-    /** {@inheritDoc} */
-    public void cleanUp() {
-        // dismiss the dialog.
-        if (mSimUnlockProgressDialog != null) {
-            mSimUnlockProgressDialog.dismiss();
-            mSimUnlockProgressDialog = null;
-        }
-        mUpdateMonitor.removeCallback(this);
-    }
-
-
-    /**
-     * Since the IPC can block, we want to run the request in a separate thread
-     * with a callback.
-     */
-    private abstract class CheckSimPuk extends Thread {
-
-        private final String mPin, mPuk;
-
-        protected CheckSimPuk(String puk, String pin) {
-            mPuk = puk;
-            mPin = pin;
-        }
-
-        abstract void onSimLockChangedResponse(boolean success);
-
-        @Override
-        public void run() {
-            try {
-                final boolean result = ITelephony.Stub.asInterface(ServiceManager
-                        .checkService("phone")).supplyPuk(mPuk, mPin);
-
-                post(new Runnable() {
-                    public void run() {
-                        onSimLockChangedResponse(result);
-                    }
-                });
-            } catch (RemoteException e) {
-                post(new Runnable() {
-                    public void run() {
-                        onSimLockChangedResponse(false);
-                    }
-                });
-            }
-        }
-    }
-
-    public void onClick(View v) {
-        if (v == mDelPukButton) {
-            if (mFocusedEntry != mPukText)
-                mPukText.requestFocus();
-            final Editable digits = mPukText.getEditableText();
-            final int len = digits.length();
-            if (len > 0) {
-                digits.delete(len-1, len);
-            }
-        } else if (v == mDelPinButton) {
-            if (mFocusedEntry != mPinText)
-                mPinText.requestFocus();
-            final Editable digits = mPinText.getEditableText();
-            final int len = digits.length();
-            if (len > 0) {
-                digits.delete(len-1, len);
-            }
-        } else if (v == mOkButton) {
-            checkPuk();
-        }
-        mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS);
-
-    }
-
-    @Override
-    public void onFocusChange(View v, boolean hasFocus) {
-        if (hasFocus)
-            mFocusedEntry = (TextView)v;
-    }
-
-    private Dialog getSimUnlockProgressDialog() {
-        if (mSimUnlockProgressDialog == null) {
-            mSimUnlockProgressDialog = new ProgressDialog(mContext);
-            mSimUnlockProgressDialog.setMessage(
-                    mContext.getString(R.string.lockscreen_sim_unlock_progress_dialog_message));
-            mSimUnlockProgressDialog.setIndeterminate(true);
-            mSimUnlockProgressDialog.setCancelable(false);
-            mSimUnlockProgressDialog.getWindow().setType(
-                    WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
-        }
-        return mSimUnlockProgressDialog;
-    }
-
-    private void checkPuk() {
-        // make sure that the puk is at least 8 digits long.
-        if (mPukText.getText().length() < 8) {
-            // otherwise, display a message to the user, and don't submit.
-            mHeaderText.setText(R.string.invalidPuk);
-            mPukText.setText("");
-            return;
-        }
-
-        if (mPinText.getText().length() < 4
-                || mPinText.getText().length() > 8) {
-            // otherwise, display a message to the user, and don't submit.
-            mHeaderText.setText(R.string.invalidPin);
-            mPinText.setText("");
-            return;
-        }
-
-        getSimUnlockProgressDialog().show();
-
-        new CheckSimPuk(mPukText.getText().toString(),
-                mPinText.getText().toString()) {
-            void onSimLockChangedResponse(final boolean success) {
-                mPinText.post(new Runnable() {
-                    public void run() {
-                        if (mSimUnlockProgressDialog != null) {
-                            mSimUnlockProgressDialog.hide();
-                        }
-                        if (success) {
-                            // before closing the keyguard, report back that
-                            // the sim is unlocked so it knows right away
-                            mUpdateMonitor.reportSimUnlocked();
-                            mCallback.goToUnlockScreen();
-                        } else {
-                            mHeaderText.setText(R.string.badPuk);
-                            mPukText.setText("");
-                            mPinText.setText("");
-                        }
-                    }
-                });
-            }
-        }.start();
-    }
-
-
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_BACK) {
-            mCallback.goToLockScreen();
-            return true;
-        }
-        final char match = event.getMatch(DIGITS);
-        if (match != 0) {
-            reportDigit(match - '0');
-            return true;
-        }
-        if (keyCode == KeyEvent.KEYCODE_DEL) {
-            mFocusedEntry.onKeyDown(keyCode, event);
-            final Editable digits = mFocusedEntry.getEditableText();
-            final int len = digits.length();
-            if (len > 0) {
-                digits.delete(len-1, len);
-            }
-            mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS);
-            return true;
-        }
-
-        if (keyCode == KeyEvent.KEYCODE_ENTER) {
-            checkPuk();
-            return true;
-        }
-
-        return false;
-    }
-
-    private void reportDigit(int digit) {
-        mFocusedEntry.append(Integer.toString(digit));
-    }
-
-    void updateConfiguration() {
-        Configuration newConfig = getResources().getConfiguration();
-        if (newConfig.orientation != mCreationOrientation) {
-            mCallback.recreateMe(newConfig);
-        } else if (newConfig.hardKeyboardHidden != mKeyboardHidden) {
-            mKeyboardHidden = newConfig.hardKeyboardHidden;
-        }
-
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        updateConfiguration();
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        updateConfiguration();
-    }
-
-    /**
-     * Helper class to handle input from touch dialer.  Only relevant when
-     * the keyboard is shut.
-     */
-    private class TouchInput implements View.OnClickListener {
-        private TextView mZero;
-        private TextView mOne;
-        private TextView mTwo;
-        private TextView mThree;
-        private TextView mFour;
-        private TextView mFive;
-        private TextView mSix;
-        private TextView mSeven;
-        private TextView mEight;
-        private TextView mNine;
-        private TextView mCancelButton;
-
-        private TouchInput() {
-            mZero = (TextView) findViewById(R.id.zero);
-            mOne = (TextView) findViewById(R.id.one);
-            mTwo = (TextView) findViewById(R.id.two);
-            mThree = (TextView) findViewById(R.id.three);
-            mFour = (TextView) findViewById(R.id.four);
-            mFive = (TextView) findViewById(R.id.five);
-            mSix = (TextView) findViewById(R.id.six);
-            mSeven = (TextView) findViewById(R.id.seven);
-            mEight = (TextView) findViewById(R.id.eight);
-            mNine = (TextView) findViewById(R.id.nine);
-            mCancelButton = (TextView) findViewById(R.id.cancel);
-
-            mZero.setText("0");
-            mOne.setText("1");
-            mTwo.setText("2");
-            mThree.setText("3");
-            mFour.setText("4");
-            mFive.setText("5");
-            mSix.setText("6");
-            mSeven.setText("7");
-            mEight.setText("8");
-            mNine.setText("9");
-
-            mZero.setOnClickListener(this);
-            mOne.setOnClickListener(this);
-            mTwo.setOnClickListener(this);
-            mThree.setOnClickListener(this);
-            mFour.setOnClickListener(this);
-            mFive.setOnClickListener(this);
-            mSix.setOnClickListener(this);
-            mSeven.setOnClickListener(this);
-            mEight.setOnClickListener(this);
-            mNine.setOnClickListener(this);
-            mCancelButton.setOnClickListener(this);
-        }
-
-
-        public void onClick(View v) {
-            if (v == mCancelButton) {
-                // clear the PIN/PUK entry fields if the user cancels
-                mPinText.setText("");
-                mPukText.setText("");
-                mCallback.goToLockScreen();
-                return;
-            }
-
-            final int digit = checkDigit(v);
-            if (digit >= 0) {
-                mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS);
-                reportDigit(digit);
-            }
-        }
-
-        private int checkDigit(View v) {
-            int digit = -1;
-            if (v == mZero) {
-                digit = 0;
-            } else if (v == mOne) {
-                digit = 1;
-            } else if (v == mTwo) {
-                digit = 2;
-            } else if (v == mThree) {
-                digit = 3;
-            } else if (v == mFour) {
-                digit = 4;
-            } else if (v == mFive) {
-                digit = 5;
-            } else if (v == mSix) {
-                digit = 6;
-            } else if (v == mSeven) {
-                digit = 7;
-            } else if (v == mEight) {
-                digit = 8;
-            } else if (v == mNine) {
-                digit = 9;
-            }
-            return digit;
-        }
-    }
-
-}
diff --git a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
deleted file mode 100644
index 80407f5..0000000
--- a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
+++ /dev/null
@@ -1,396 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import android.app.Dialog;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-
-import com.android.internal.telephony.ITelephony;
-import com.android.internal.widget.LockPatternUtils;
-
-import android.text.Editable;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.Button;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-import com.android.internal.R;
-
-/**
- * Displays a dialer like interface to unlock the SIM PIN.
- */
-public class SimUnlockScreen extends LinearLayout implements KeyguardScreen, View.OnClickListener {
-
-    private static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
-
-    private final KeyguardUpdateMonitor mUpdateMonitor;
-    private final KeyguardScreenCallback mCallback;
-
-    private TextView mHeaderText;
-    private TextView mPinText;
-
-    private TextView mOkButton;
-
-    private View mBackSpaceButton;
-
-    private final int[] mEnteredPin = {0, 0, 0, 0, 0, 0, 0, 0};
-    private int mEnteredDigits = 0;
-
-    private ProgressDialog mSimUnlockProgressDialog = null;
-
-    private LockPatternUtils mLockPatternUtils;
-
-    private int mCreationOrientation;
-
-    private int mKeyboardHidden;
-
-    private KeyguardStatusViewManager mKeyguardStatusViewManager;
-
-    private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
-
-    public SimUnlockScreen(Context context, Configuration configuration,
-            KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback,
-            LockPatternUtils lockpatternutils) {
-        super(context);
-        mUpdateMonitor = updateMonitor;
-        mCallback = callback;
-
-        mCreationOrientation = configuration.orientation;
-        mKeyboardHidden = configuration.hardKeyboardHidden;
-        mLockPatternUtils = lockpatternutils;
-
-        LayoutInflater inflater = LayoutInflater.from(context);
-        if (mKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
-            inflater.inflate(R.layout.keyguard_screen_sim_pin_landscape, this, true);
-        } else {
-            inflater.inflate(R.layout.keyguard_screen_sim_pin_portrait, this, true);
-            new TouchInput();
-        }
-
-        mHeaderText = (TextView) findViewById(R.id.headerText);
-        mPinText = (TextView) findViewById(R.id.pinDisplay);
-        mBackSpaceButton = findViewById(R.id.backspace);
-        mBackSpaceButton.setOnClickListener(this);
-
-        mOkButton = (TextView) findViewById(R.id.ok);
-
-        mHeaderText.setText(R.string.keyguard_password_enter_pin_code);
-        mPinText.setFocusable(false);
-
-        mOkButton.setOnClickListener(this);
-
-        mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor,
-                lockpatternutils, callback, false);
-
-        setFocusableInTouchMode(true);
-    }
-
-    /** {@inheritDoc} */
-    public boolean needsInput() {
-        return true;
-    }
-
-    /** {@inheritDoc} */
-    public void onPause() {
-        mKeyguardStatusViewManager.onPause();
-    }
-
-    /** {@inheritDoc} */
-    public void onResume() {
-        // start fresh
-        mHeaderText.setText(R.string.keyguard_password_enter_pin_code);
-
-        // make sure that the number of entered digits is consistent when we
-        // erase the SIM unlock code, including orientation changes.
-        mPinText.setText("");
-        mEnteredDigits = 0;
-
-        mKeyguardStatusViewManager.onResume();
-    }
-
-    /** {@inheritDoc} */
-    public void cleanUp() {
-        // dismiss the dialog.
-        if (mSimUnlockProgressDialog != null) {
-            mSimUnlockProgressDialog.dismiss();
-            mSimUnlockProgressDialog = null;
-        }
-        mUpdateMonitor.removeCallback(this);
-    }
-
-
-    /**
-     * Since the IPC can block, we want to run the request in a separate thread
-     * with a callback.
-     */
-    private abstract class CheckSimPin extends Thread {
-
-        private final String mPin;
-
-        protected CheckSimPin(String pin) {
-            mPin = pin;
-        }
-
-        abstract void onSimLockChangedResponse(boolean success);
-
-        @Override
-        public void run() {
-            try {
-                final boolean result = ITelephony.Stub.asInterface(ServiceManager
-                        .checkService("phone")).supplyPin(mPin);
-                post(new Runnable() {
-                    public void run() {
-                        onSimLockChangedResponse(result);
-                    }
-                });
-            } catch (RemoteException e) {
-                post(new Runnable() {
-                    public void run() {
-                        onSimLockChangedResponse(false);
-                    }
-                });
-            }
-        }
-    }
-
-    public void onClick(View v) {
-        if (v == mBackSpaceButton) {
-            final Editable digits = mPinText.getEditableText();
-            final int len = digits.length();
-            if (len > 0) {
-                digits.delete(len-1, len);
-                mEnteredDigits--;
-            }
-            mCallback.pokeWakelock();
-        } else if (v == mOkButton) {
-            checkPin();
-        }
-    }
-
-    private Dialog getSimUnlockProgressDialog() {
-        if (mSimUnlockProgressDialog == null) {
-            mSimUnlockProgressDialog = new ProgressDialog(mContext);
-            mSimUnlockProgressDialog.setMessage(
-                    mContext.getString(R.string.lockscreen_sim_unlock_progress_dialog_message));
-            mSimUnlockProgressDialog.setIndeterminate(true);
-            mSimUnlockProgressDialog.setCancelable(false);
-            mSimUnlockProgressDialog.getWindow().setType(
-                    WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
-        }
-        return mSimUnlockProgressDialog;
-    }
-
-    private void checkPin() {
-
-        // make sure that the pin is at least 4 digits long.
-        if (mEnteredDigits < 4) {
-            // otherwise, display a message to the user, and don't submit.
-            mHeaderText.setText(R.string.invalidPin);
-            mPinText.setText("");
-            mEnteredDigits = 0;
-            mCallback.pokeWakelock();
-            return;
-        }
-        getSimUnlockProgressDialog().show();
-
-        new CheckSimPin(mPinText.getText().toString()) {
-            void onSimLockChangedResponse(final boolean success) {
-                mPinText.post(new Runnable() {
-                    public void run() {
-                        if (mSimUnlockProgressDialog != null) {
-                            mSimUnlockProgressDialog.hide();
-                        }
-                        if (success) {
-                            // before closing the keyguard, report back that
-                            // the sim is unlocked so it knows right away
-                            mUpdateMonitor.reportSimUnlocked();
-                            mCallback.goToUnlockScreen();
-                        } else {
-                            mHeaderText.setText(R.string.keyguard_password_wrong_pin_code);
-                            mPinText.setText("");
-                            mEnteredDigits = 0;
-                        }
-                        mCallback.pokeWakelock();
-                    }
-                });
-            }
-        }.start();
-    }
-
-
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_BACK) {
-            mCallback.goToLockScreen();
-            return true;
-        }
-
-        final char match = event.getMatch(DIGITS);
-        if (match != 0) {
-            reportDigit(match - '0');
-            return true;
-        }
-        if (keyCode == KeyEvent.KEYCODE_DEL) {
-            if (mEnteredDigits > 0) {
-                mPinText.onKeyDown(keyCode, event);
-                mEnteredDigits--;
-            }
-            return true;
-        }
-
-        if (keyCode == KeyEvent.KEYCODE_ENTER) {
-            checkPin();
-            return true;
-        }
-
-        return false;
-    }
-
-    private void reportDigit(int digit) {
-        if (mEnteredDigits == 0) {
-            mPinText.setText("");
-        }
-        if (mEnteredDigits == 8) {
-            return;
-        }
-        mPinText.append(Integer.toString(digit));
-        mEnteredPin[mEnteredDigits++] = digit;
-    }
-
-    void updateConfiguration() {
-        Configuration newConfig = getResources().getConfiguration();
-        if (newConfig.orientation != mCreationOrientation) {
-            mCallback.recreateMe(newConfig);
-        } else if (newConfig.hardKeyboardHidden != mKeyboardHidden) {
-            mKeyboardHidden = newConfig.hardKeyboardHidden;
-        }
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        updateConfiguration();
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        updateConfiguration();
-    }
-
-    /**
-     * Helper class to handle input from touch dialer.  Only relevant when
-     * the keyboard is shut.
-     */
-    private class TouchInput implements View.OnClickListener {
-        private TextView mZero;
-        private TextView mOne;
-        private TextView mTwo;
-        private TextView mThree;
-        private TextView mFour;
-        private TextView mFive;
-        private TextView mSix;
-        private TextView mSeven;
-        private TextView mEight;
-        private TextView mNine;
-        private TextView mCancelButton;
-
-        private TouchInput() {
-            mZero = (TextView) findViewById(R.id.zero);
-            mOne = (TextView) findViewById(R.id.one);
-            mTwo = (TextView) findViewById(R.id.two);
-            mThree = (TextView) findViewById(R.id.three);
-            mFour = (TextView) findViewById(R.id.four);
-            mFive = (TextView) findViewById(R.id.five);
-            mSix = (TextView) findViewById(R.id.six);
-            mSeven = (TextView) findViewById(R.id.seven);
-            mEight = (TextView) findViewById(R.id.eight);
-            mNine = (TextView) findViewById(R.id.nine);
-            mCancelButton = (TextView) findViewById(R.id.cancel);
-
-            mZero.setText("0");
-            mOne.setText("1");
-            mTwo.setText("2");
-            mThree.setText("3");
-            mFour.setText("4");
-            mFive.setText("5");
-            mSix.setText("6");
-            mSeven.setText("7");
-            mEight.setText("8");
-            mNine.setText("9");
-
-            mZero.setOnClickListener(this);
-            mOne.setOnClickListener(this);
-            mTwo.setOnClickListener(this);
-            mThree.setOnClickListener(this);
-            mFour.setOnClickListener(this);
-            mFive.setOnClickListener(this);
-            mSix.setOnClickListener(this);
-            mSeven.setOnClickListener(this);
-            mEight.setOnClickListener(this);
-            mNine.setOnClickListener(this);
-            mCancelButton.setOnClickListener(this);
-        }
-
-
-        public void onClick(View v) {
-            if (v == mCancelButton) {
-                mPinText.setText(""); // clear the PIN entry field if the user cancels
-                mCallback.goToLockScreen();
-                return;
-            }
-
-            final int digit = checkDigit(v);
-            if (digit >= 0) {
-                mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS);
-                reportDigit(digit);
-            }
-        }
-
-        private int checkDigit(View v) {
-            int digit = -1;
-            if (v == mZero) {
-                digit = 0;
-            } else if (v == mOne) {
-                digit = 1;
-            } else if (v == mTwo) {
-                digit = 2;
-            } else if (v == mThree) {
-                digit = 3;
-            } else if (v == mFour) {
-                digit = 4;
-            } else if (v == mFive) {
-                digit = 5;
-            } else if (v == mSix) {
-                digit = 6;
-            } else if (v == mSeven) {
-                digit = 7;
-            } else if (v == mEight) {
-                digit = 8;
-            } else if (v == mNine) {
-                digit = 9;
-            }
-            return digit;
-        }
-    }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/BiometricSensorUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard/BiometricSensorUnlock.java
new file mode 100644
index 0000000..e65a716f
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/BiometricSensorUnlock.java
@@ -0,0 +1,68 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.view.View;
+
+interface BiometricSensorUnlock {
+    /**
+     * Initializes the view provided for the biometric unlock UI to work within.  The provided area
+     * completely covers the backup unlock mechanism.
+     * @param biometricUnlockView View provided for the biometric unlock UI.
+     */
+    public void initializeView(View biometricUnlockView);
+
+    /**
+     * Indicates whether the biometric unlock is running.  Before
+     * {@link BiometricSensorUnlock#start} is called, isRunning() returns false.  After a successful
+     * call to {@link BiometricSensorUnlock#start}, isRunning() returns true until the biometric
+     * unlock completes, {@link BiometricSensorUnlock#stop} has been called, or an error has
+     * forced the biometric unlock to stop.
+     * @return whether the biometric unlock is currently running.
+     */
+    public boolean isRunning();
+
+    /**
+     * Stops and removes the biometric unlock and shows the backup unlock
+     */
+    public void stopAndShowBackup();
+
+    /**
+     * Binds to the biometric unlock service and starts the unlock procedure.  Called on the UI
+     * thread.
+     * @return false if it can't be started or the backup should be used.
+     */
+    public boolean start();
+
+    /**
+     * Stops the biometric unlock procedure and unbinds from the service.  Called on the UI thread.
+     * @return whether the biometric unlock was running when called.
+     */
+    public boolean stop();
+
+    /**
+     * Cleans up any resources used by the biometric unlock.
+     */
+    public void cleanUp();
+
+    /**
+     * Gets the Device Policy Manager quality of the biometric unlock sensor
+     * (e.g., PASSWORD_QUALITY_BIOMETRIC_WEAK).
+     * @return biometric unlock sensor quality, as defined by Device Policy Manager.
+     */
+    public int getQuality();
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
new file mode 100644
index 0000000..dbd9999
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
@@ -0,0 +1,450 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Point;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+
+import com.android.internal.R;
+import com.android.internal.policy.impl.keyguard.KeyguardActivityLauncher.CameraWidgetInfo;
+
+public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnClickListener {
+    private static final String TAG = CameraWidgetFrame.class.getSimpleName();
+    private static final boolean DEBUG = KeyguardHostView.DEBUG;
+    private static final int WIDGET_ANIMATION_DURATION = 250; // ms
+    private static final int WIDGET_WAIT_DURATION = 650; // ms
+    private static final int RECOVERY_DELAY = 1000; // ms
+
+    interface Callbacks {
+        void onLaunchingCamera();
+        void onCameraLaunchedSuccessfully();
+        void onCameraLaunchedUnsuccessfully();
+    }
+
+    private final Handler mHandler = new Handler();
+    private final KeyguardActivityLauncher mActivityLauncher;
+    private final Callbacks mCallbacks;
+    private final WindowManager mWindowManager;
+    private final Point mRenderedSize = new Point();
+    private final int[] mScreenLocation = new int[2];
+
+    private View mWidgetView;
+    private long mLaunchCameraStart;
+    private boolean mActive;
+    private boolean mTransitioning;
+    private boolean mRecovering;
+    private boolean mDown;
+
+    private final Runnable mTransitionToCameraRunnable = new Runnable() {
+        @Override
+        public void run() {
+            transitionToCamera();
+        }};
+
+    private final Runnable mTransitionToCameraEndAction = new Runnable() {
+        @Override
+        public void run() {
+            if (!mTransitioning)
+                return;
+            Handler worker =  getWorkerHandler() != null ? getWorkerHandler() : mHandler;
+            mLaunchCameraStart = SystemClock.uptimeMillis();
+            if (DEBUG) Log.d(TAG, "Launching camera at " + mLaunchCameraStart);
+            mActivityLauncher.launchCamera(worker, mSecureCameraActivityStartedRunnable);
+        }};
+
+    private final Runnable mRecoverRunnable = new Runnable() {
+        @Override
+        public void run() {
+            recover();
+        }};
+
+    private final Runnable mRecoverEndAction = new Runnable() {
+        @Override
+        public void run() {
+            if (!mRecovering)
+                return;
+            mCallbacks.onCameraLaunchedUnsuccessfully();
+            reset();
+        }};
+
+    private final Runnable mRenderRunnable = new Runnable() {
+        @Override
+        public void run() {
+            render();
+        }};
+
+    private final Runnable mSecureCameraActivityStartedRunnable = new Runnable() {
+        @Override
+        public void run() {
+            onSecureCameraActivityStarted();
+        }
+    };
+
+    private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
+        private boolean mShowing;
+        void onKeyguardVisibilityChanged(boolean showing) {
+            if (mShowing == showing)
+                return;
+            mShowing = showing;
+            CameraWidgetFrame.this.onKeyguardVisibilityChanged(mShowing);
+        };
+    };
+
+    private CameraWidgetFrame(Context context, Callbacks callbacks,
+            KeyguardActivityLauncher activityLauncher) {
+        super(context);
+        mCallbacks = callbacks;
+        mActivityLauncher = activityLauncher;
+        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        KeyguardUpdateMonitor.getInstance(context).registerCallback(mCallback);
+        if (DEBUG) Log.d(TAG, "new CameraWidgetFrame instance " + instanceId());
+    }
+
+    public static CameraWidgetFrame create(Context context, Callbacks callbacks,
+            KeyguardActivityLauncher launcher) {
+        if (context == null || callbacks == null || launcher == null)
+            return null;
+
+        CameraWidgetInfo widgetInfo = launcher.getCameraWidgetInfo();
+        if (widgetInfo == null)
+            return null;
+        View widgetView = widgetInfo.layoutId > 0 ?
+                inflateWidgetView(context, widgetInfo) :
+                inflateGenericWidgetView(context);
+        if (widgetView == null)
+            return null;
+
+        ImageView preview = new ImageView(context);
+        preview.setLayoutParams(new FrameLayout.LayoutParams(
+                FrameLayout.LayoutParams.MATCH_PARENT,
+                FrameLayout.LayoutParams.MATCH_PARENT));
+        preview.setScaleType(ScaleType.FIT_CENTER);
+        preview.setContentDescription(preview.getContext().getString(
+                R.string.keyguard_accessibility_camera));
+        CameraWidgetFrame cameraWidgetFrame = new CameraWidgetFrame(context, callbacks, launcher);
+        cameraWidgetFrame.addView(preview);
+        cameraWidgetFrame.mWidgetView = widgetView;
+        preview.setOnClickListener(cameraWidgetFrame);
+        return cameraWidgetFrame;
+    }
+
+    private static View inflateWidgetView(Context context, CameraWidgetInfo widgetInfo) {
+        if (DEBUG) Log.d(TAG, "inflateWidgetView: " + widgetInfo.contextPackage);
+        View widgetView = null;
+        Exception exception = null;
+        try {
+            Context cameraContext = context.createPackageContext(
+                    widgetInfo.contextPackage, Context.CONTEXT_RESTRICTED);
+            LayoutInflater cameraInflater = (LayoutInflater)
+                    cameraContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            cameraInflater = cameraInflater.cloneInContext(cameraContext);
+            widgetView = cameraInflater.inflate(widgetInfo.layoutId, null, false);
+        } catch (NameNotFoundException e) {
+            exception = e;
+        } catch (RuntimeException e) {
+            exception = e;
+        }
+        if (exception != null) {
+            Log.w(TAG, "Error creating camera widget view", exception);
+        }
+        return widgetView;
+    }
+
+    private static View inflateGenericWidgetView(Context context) {
+        if (DEBUG) Log.d(TAG, "inflateGenericWidgetView");
+        ImageView iv = new ImageView(context);
+        iv.setImageResource(com.android.internal.R.drawable.ic_lockscreen_camera);
+        iv.setScaleType(ScaleType.CENTER);
+        iv.setBackgroundColor(Color.argb(127, 0, 0, 0));
+        return iv;
+    }
+
+    public void render() {
+        final Throwable[] thrown = new Throwable[1];
+        final Bitmap[] offscreen = new Bitmap[1];
+        try {
+            final int width = getRootView().getWidth();
+            final int height = getRootView().getHeight();
+            if (mRenderedSize.x == width && mRenderedSize.y == height) {
+                if (DEBUG) Log.d(TAG, String.format("Already rendered at size=%sx%s",
+                        width, height));
+                return;
+            }
+            if (width == 0 || height == 0) {
+                return;
+            }
+            final long start = SystemClock.uptimeMillis();
+            offscreen[0] = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+            final Canvas c = new Canvas(offscreen[0]);
+            mWidgetView.measure(
+                    MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+            mWidgetView.layout(0, 0, width, height);
+            mWidgetView.draw(c);
+
+            final long end = SystemClock.uptimeMillis();
+            if (DEBUG) Log.d(TAG, String.format(
+                    "Rendered camera widget in %sms size=%sx%s instance=%s at %s",
+                    end - start,
+                    width, height,
+                    instanceId(),
+                    end));
+            mRenderedSize.set(width, height);
+        } catch (Throwable t) {
+            thrown[0] = t;
+        }
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                if (thrown[0] == null) {
+                    try {
+                        ((ImageView) getChildAt(0)).setImageBitmap(offscreen[0]);
+                    } catch (Throwable t) {
+                        thrown[0] = t;
+                    }
+                }
+                if (thrown[0] == null)
+                    return;
+
+                Log.w(TAG, "Error rendering camera widget", thrown[0]);
+                try {
+                    removeAllViews();
+                    final View genericView = inflateGenericWidgetView(mContext);
+                    addView(genericView);
+                } catch (Throwable t) {
+                    Log.w(TAG, "Error inflating generic camera widget", t);
+                }
+            }});
+    }
+
+    private void transitionToCamera() {
+        if (mTransitioning || mDown) return;
+
+        mTransitioning = true;
+
+        final View child = getChildAt(0);
+        final View root = getRootView();
+
+        final int startWidth = child.getWidth();
+        final int startHeight = child.getHeight();
+
+        final int finishWidth = root.getWidth();
+        final int finishHeight = root.getHeight();
+
+        final float scaleX = (float) finishWidth / startWidth;
+        final float scaleY = (float) finishHeight / startHeight;
+        final float scale = Math.round( Math.max(scaleX, scaleY) * 100) / 100f;
+
+        final int[] loc = new int[2];
+        root.getLocationInWindow(loc);
+        final int finishCenter = loc[1] + finishHeight / 2;
+
+        child.getLocationInWindow(loc);
+        final int startCenter = loc[1] + startHeight / 2;
+
+        if (DEBUG) Log.d(TAG, String.format("Transitioning to camera. " +
+                "(start=%sx%s, finish=%sx%s, scale=%s,%s, startCenter=%s, finishCenter=%s)",
+                startWidth, startHeight,
+                finishWidth, finishHeight,
+                scaleX, scaleY,
+                startCenter, finishCenter));
+
+        enableWindowExitAnimation(false);
+        animate()
+            .scaleX(scale)
+            .scaleY(scale)
+            .translationY(finishCenter - startCenter)
+            .setDuration(WIDGET_ANIMATION_DURATION)
+            .withEndAction(mTransitionToCameraEndAction)
+            .start();
+
+        mCallbacks.onLaunchingCamera();
+    }
+
+    private void recover() {
+        if (DEBUG) Log.d(TAG, "recovering at " + SystemClock.uptimeMillis());
+        mRecovering = true;
+        animate()
+            .scaleX(1)
+            .scaleY(1)
+            .translationY(0)
+            .setDuration(WIDGET_ANIMATION_DURATION)
+            .withEndAction(mRecoverEndAction)
+            .start();
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (DEBUG) Log.d(TAG, "clicked");
+        if (mTransitioning) return;
+        if (mActive) {
+            cancelTransitionToCamera();
+            transitionToCamera();
+        }
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        if (DEBUG) Log.d(TAG, "onDetachedFromWindow: instance " + instanceId()
+                + " at " + SystemClock.uptimeMillis());
+        super.onDetachedFromWindow();
+        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mCallback);
+        cancelTransitionToCamera();
+        mHandler.removeCallbacks(mRecoverRunnable);
+    }
+
+    @Override
+    public void onActive(boolean isActive) {
+        mActive = isActive;
+        if (mActive) {
+            rescheduleTransitionToCamera();
+        } else {
+            reset();
+        }
+    }
+
+    @Override
+    public boolean onUserInteraction(MotionEvent event) {
+        if (mTransitioning) {
+            if (DEBUG) Log.d(TAG, "onUserInteraction eaten: mTransitioning");
+            return true;
+        }
+
+        getLocationOnScreen(mScreenLocation);
+        int rawBottom = mScreenLocation[1] + getHeight();
+        if (event.getRawY() > rawBottom) {
+            if (DEBUG) Log.d(TAG, "onUserInteraction eaten: below widget");
+            return true;
+        }
+
+        int action = event.getAction();
+        mDown = action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE;
+        if (mActive) {
+            rescheduleTransitionToCamera();
+        }
+        if (DEBUG) Log.d(TAG, "onUserInteraction observed, not eaten");
+        return false;
+    }
+
+    @Override
+    protected void onFocusLost() {
+        if (DEBUG) Log.d(TAG, "onFocusLost at " + SystemClock.uptimeMillis());
+        cancelTransitionToCamera();
+        super.onFocusLost();
+    }
+
+    public void onScreenTurnedOff() {
+        if (DEBUG) Log.d(TAG, "onScreenTurnedOff");
+        reset();
+    }
+
+    private void rescheduleTransitionToCamera() {
+        if (DEBUG) Log.d(TAG, "rescheduleTransitionToCamera at " + SystemClock.uptimeMillis());
+        mHandler.removeCallbacks(mTransitionToCameraRunnable);
+        mHandler.postDelayed(mTransitionToCameraRunnable, WIDGET_WAIT_DURATION);
+    }
+
+    private void cancelTransitionToCamera() {
+        if (DEBUG) Log.d(TAG, "cancelTransitionToCamera at " + SystemClock.uptimeMillis());
+        mHandler.removeCallbacks(mTransitionToCameraRunnable);
+    }
+
+    private void onCameraLaunched() {
+        mCallbacks.onCameraLaunchedSuccessfully();
+        reset();
+    }
+
+    private void reset() {
+        if (DEBUG) Log.d(TAG, "reset at " + SystemClock.uptimeMillis());
+        mLaunchCameraStart = 0;
+        mTransitioning = false;
+        mRecovering = false;
+        mDown = false;
+        cancelTransitionToCamera();
+        mHandler.removeCallbacks(mRecoverRunnable);
+        animate().cancel();
+        setScaleX(1);
+        setScaleY(1);
+        setTranslationY(0);
+        enableWindowExitAnimation(true);
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        if (DEBUG) Log.d(TAG, String.format("onSizeChanged new=%sx%s old=%sx%s at %s",
+                w, h, oldw, oldh, SystemClock.uptimeMillis()));
+        final Handler worker =  getWorkerHandler();
+        (worker != null ? worker : mHandler).post(mRenderRunnable);
+        super.onSizeChanged(w, h, oldw, oldh);
+    }
+
+    private void enableWindowExitAnimation(boolean isEnabled) {
+        View root = getRootView();
+        ViewGroup.LayoutParams lp = root.getLayoutParams();
+        if (!(lp instanceof WindowManager.LayoutParams))
+            return;
+        WindowManager.LayoutParams wlp = (WindowManager.LayoutParams) lp;
+        int newWindowAnimations = isEnabled ? com.android.internal.R.style.Animation_LockScreen : 0;
+        if (newWindowAnimations != wlp.windowAnimations) {
+            if (DEBUG) Log.d(TAG, "setting windowAnimations to: " + newWindowAnimations
+                    + " at " + SystemClock.uptimeMillis());
+            wlp.windowAnimations = newWindowAnimations;
+            mWindowManager.updateViewLayout(root, wlp);
+        }
+    }
+
+    private void onKeyguardVisibilityChanged(boolean showing) {
+        if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged " + showing
+                + " at " + SystemClock.uptimeMillis());
+        if (mTransitioning && !showing) {
+          mTransitioning = false;
+          mRecovering = false;
+          mHandler.removeCallbacks(mRecoverRunnable);
+          if (mLaunchCameraStart > 0) {
+              long launchTime = SystemClock.uptimeMillis() - mLaunchCameraStart;
+              if (DEBUG) Log.d(TAG, String.format("Camera took %sms to launch", launchTime));
+              mLaunchCameraStart = 0;
+              onCameraLaunched();
+          }
+        }
+    }
+
+    private void onSecureCameraActivityStarted() {
+        if (DEBUG) Log.d(TAG, "onSecureCameraActivityStarted at " + SystemClock.uptimeMillis());
+        mHandler.postDelayed(mRecoverRunnable, RECOVERY_DELAY);
+    }
+
+    private String instanceId() {
+        return Integer.toHexString(hashCode());
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/CarrierText.java b/policy/src/com/android/internal/policy/impl/keyguard/CarrierText.java
new file mode 100644
index 0000000..a38e86d
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/CarrierText.java
@@ -0,0 +1,258 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import com.android.internal.R;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.IccCardConstants.State;
+import com.android.internal.widget.LockPatternUtils;
+
+public class CarrierText extends TextView {
+    private static CharSequence mSeparator;
+
+    private LockPatternUtils mLockPatternUtils;
+
+    private KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
+        private CharSequence mPlmn;
+        private CharSequence mSpn;
+        private State mSimState;
+
+        @Override
+        public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
+            mPlmn = plmn;
+            mSpn = spn;
+            updateCarrierText(mSimState, mPlmn, mSpn);
+        }
+
+        @Override
+        public void onSimStateChanged(IccCardConstants.State simState) {
+            mSimState = simState;
+            updateCarrierText(mSimState, mPlmn, mSpn);
+        }
+    };
+    /**
+     * The status of this lock screen. Primarily used for widgets on LockScreen.
+     */
+    private static enum StatusMode {
+        Normal, // Normal case (sim card present, it's not locked)
+        NetworkLocked, // SIM card is 'network locked'.
+        SimMissing, // SIM card is missing.
+        SimMissingLocked, // SIM card is missing, and device isn't provisioned; don't allow access
+        SimPukLocked, // SIM card is PUK locked because SIM entered wrong too many times
+        SimLocked, // SIM card is currently locked
+        SimPermDisabled, // SIM card is permanently disabled due to PUK unlock failure
+        SimNotReady; // SIM is not ready yet. May never be on devices w/o a SIM.
+    }
+
+    public CarrierText(Context context) {
+        this(context, null);
+    }
+
+    public CarrierText(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mLockPatternUtils = new LockPatternUtils(mContext);
+    }
+
+    protected void updateCarrierText(State simState, CharSequence plmn, CharSequence spn) {
+        CharSequence text = getCarrierTextForSimState(simState, plmn, spn);
+        if (KeyguardViewManager.USE_UPPER_CASE) {
+            setText(text != null ? text.toString().toUpperCase() : null);
+        } else {
+            setText(text);
+        }
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mSeparator = getResources().getString(R.string.kg_text_message_separator);
+        setSelected(true); // Allow marquee to work.
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mCallback);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mCallback);
+    }
+
+    /**
+     * Top-level function for creating carrier text. Makes text based on simState, PLMN
+     * and SPN as well as device capabilities, such as being emergency call capable.
+     *
+     * @param simState
+     * @param plmn
+     * @param spn
+     * @return
+     */
+    private CharSequence getCarrierTextForSimState(IccCardConstants.State simState,
+            CharSequence plmn, CharSequence spn) {
+        CharSequence carrierText = null;
+        StatusMode status = getStatusForIccState(simState);
+        switch (status) {
+            case Normal:
+                carrierText = concatenate(plmn, spn);
+                break;
+
+            case SimNotReady:
+                carrierText = null; // nothing to display yet.
+                break;
+
+            case NetworkLocked:
+                carrierText = makeCarrierStringOnEmergencyCapable(
+                        mContext.getText(R.string.lockscreen_network_locked_message), plmn);
+                break;
+
+            case SimMissing:
+                // Shows "No SIM card | Emergency calls only" on devices that are voice-capable.
+                // This depends on mPlmn containing the text "Emergency calls only" when the radio
+                // has some connectivity. Otherwise, it should be null or empty and just show
+                // "No SIM card"
+                carrierText =  makeCarrierStringOnEmergencyCapable(
+                        getContext().getText(R.string.lockscreen_missing_sim_message_short),
+                        plmn);
+                break;
+
+            case SimPermDisabled:
+                carrierText = getContext().getText(
+                        R.string.lockscreen_permanent_disabled_sim_message_short);
+                break;
+
+            case SimMissingLocked:
+                carrierText =  makeCarrierStringOnEmergencyCapable(
+                        getContext().getText(R.string.lockscreen_missing_sim_message_short),
+                        plmn);
+                break;
+
+            case SimLocked:
+                carrierText = makeCarrierStringOnEmergencyCapable(
+                        getContext().getText(R.string.lockscreen_sim_locked_message),
+                        plmn);
+                break;
+
+            case SimPukLocked:
+                carrierText = makeCarrierStringOnEmergencyCapable(
+                        getContext().getText(R.string.lockscreen_sim_puk_locked_message),
+                        plmn);
+                break;
+        }
+
+        return carrierText;
+    }
+
+    /*
+     * Add emergencyCallMessage to carrier string only if phone supports emergency calls.
+     */
+    private CharSequence makeCarrierStringOnEmergencyCapable(
+            CharSequence simMessage, CharSequence emergencyCallMessage) {
+        if (mLockPatternUtils.isEmergencyCallCapable()) {
+            return concatenate(simMessage, emergencyCallMessage);
+        }
+        return simMessage;
+    }
+
+    /**
+     * Determine the current status of the lock screen given the SIM state and other stuff.
+     */
+    private StatusMode getStatusForIccState(IccCardConstants.State simState) {
+        // Since reading the SIM may take a while, we assume it is present until told otherwise.
+        if (simState == null) {
+            return StatusMode.Normal;
+        }
+
+        final boolean missingAndNotProvisioned =
+                !KeyguardUpdateMonitor.getInstance(mContext).isDeviceProvisioned()
+                && (simState == IccCardConstants.State.ABSENT ||
+                        simState == IccCardConstants.State.PERM_DISABLED);
+
+        // Assume we're NETWORK_LOCKED if not provisioned
+        simState = missingAndNotProvisioned ? IccCardConstants.State.NETWORK_LOCKED : simState;
+        switch (simState) {
+            case ABSENT:
+                return StatusMode.SimMissing;
+            case NETWORK_LOCKED:
+                return StatusMode.SimMissingLocked;
+            case NOT_READY:
+                return StatusMode.SimNotReady;
+            case PIN_REQUIRED:
+                return StatusMode.SimLocked;
+            case PUK_REQUIRED:
+                return StatusMode.SimPukLocked;
+            case READY:
+                return StatusMode.Normal;
+            case PERM_DISABLED:
+                return StatusMode.SimPermDisabled;
+            case UNKNOWN:
+                return StatusMode.SimMissing;
+        }
+        return StatusMode.SimMissing;
+    }
+
+    private static CharSequence concatenate(CharSequence plmn, CharSequence spn) {
+        final boolean plmnValid = !TextUtils.isEmpty(plmn);
+        final boolean spnValid = !TextUtils.isEmpty(spn);
+        if (plmnValid && spnValid) {
+            return new StringBuilder().append(plmn).append(mSeparator).append(spn).toString();
+        } else if (plmnValid) {
+            return plmn;
+        } else if (spnValid) {
+            return spn;
+        } else {
+            return "";
+        }
+    }
+
+    private CharSequence getCarrierHelpTextForSimState(IccCardConstants.State simState,
+            String plmn, String spn) {
+        int carrierHelpTextId = 0;
+        StatusMode status = getStatusForIccState(simState);
+        switch (status) {
+            case NetworkLocked:
+                carrierHelpTextId = R.string.lockscreen_instructions_when_pattern_disabled;
+                break;
+
+            case SimMissing:
+                carrierHelpTextId = R.string.lockscreen_missing_sim_instructions_long;
+                break;
+
+            case SimPermDisabled:
+                carrierHelpTextId = R.string.lockscreen_permanent_disabled_sim_instructions;
+                break;
+
+            case SimMissingLocked:
+                carrierHelpTextId = R.string.lockscreen_missing_sim_instructions;
+                break;
+
+            case Normal:
+            case SimLocked:
+            case SimPukLocked:
+                break;
+        }
+
+        return mContext.getText(carrierHelpTextId);
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/ChallengeLayout.java b/policy/src/com/android/internal/policy/impl/keyguard/ChallengeLayout.java
new file mode 100644
index 0000000..8ece559
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/ChallengeLayout.java
@@ -0,0 +1,97 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+/**
+ * Interface implemented by ViewGroup-derived layouts that implement
+ * special logic for presenting security challenges to the user.
+ */
+public interface ChallengeLayout {
+    /**
+     * @return true if the security challenge area of this layout is currently visible
+     */
+    boolean isChallengeShowing();
+
+    /**
+     * @return true if the challenge area significantly overlaps other content
+     */
+    boolean isChallengeOverlapping();
+
+    /**
+     * Show or hide the challenge layout.
+     *
+     * If you want to show the challenge layout in bouncer mode where applicable,
+     * use {@link #showBouncer()} instead.
+     *
+     * @param b true to show, false to hide
+     */
+    void showChallenge(boolean b);
+
+    /**
+     * Show the bouncer challenge. This may block access to other child views.
+     */
+    void showBouncer();
+
+    /**
+     * Hide the bouncer challenge if it is currently showing.
+     * This may restore previously blocked access to other child views.
+     */
+    void hideBouncer();
+
+    /**
+     * Returns true if the challenge is currently in bouncer mode,
+     * potentially blocking access to other child views.
+     */
+    boolean isBouncing();
+
+    /**
+     * Returns the duration of the bounce animation.
+     */
+    int getBouncerAnimationDuration();
+
+    /**
+     * Set a listener that will respond to changes in bouncer state.
+     *
+     * @param listener listener to register
+     */
+    void setOnBouncerStateChangedListener(OnBouncerStateChangedListener listener);
+
+    /**
+     * Listener interface that reports changes in bouncer state.
+     * The bouncer is
+     */
+    public interface OnBouncerStateChangedListener {
+        /**
+         * Called when the bouncer state changes.
+         * The bouncer is activated when the user must pass a security challenge
+         * to proceed with the requested action.
+         *
+         * <p>This differs from simply showing or hiding the security challenge
+         * as the bouncer will prevent interaction with other elements of the UI.
+         * If the user attempts to escape from the bouncer, it will be dismissed,
+         * this method will be called with false as the parameter, and the action
+         * should be canceled. If the security component reports a successful
+         * authentication and the containing code calls hideBouncer() as a result,
+         * this method will also be called with a false parameter. It is up to the
+         * caller of hideBouncer to be ready for this.</p>
+         *
+         * @param bouncerActive true if the bouncer is now active,
+         *                      false if the bouncer was dismissed.
+         */
+        public void onBouncerStateChanged(boolean bouncerActive);
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/CheckLongPressHelper.java b/policy/src/com/android/internal/policy/impl/keyguard/CheckLongPressHelper.java
new file mode 100644
index 0000000..4825e23
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/CheckLongPressHelper.java
@@ -0,0 +1,82 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+
+public class CheckLongPressHelper {
+    private View mView;
+    private boolean mHasPerformedLongPress;
+    private CheckForLongPress mPendingCheckForLongPress;
+    private float mDownX, mDownY;
+    private int mLongPressTimeout;
+    private int mScaledTouchSlop;
+
+    class CheckForLongPress implements Runnable {
+        public void run() {
+            if ((mView.getParent() != null) && mView.hasWindowFocus()
+                    && !mHasPerformedLongPress) {
+                if (mView.performLongClick()) {
+                    mView.setPressed(false);
+                    mHasPerformedLongPress = true;
+                }
+            }
+        }
+    }
+
+    public CheckLongPressHelper(View v) {
+        mScaledTouchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop();
+        mLongPressTimeout = ViewConfiguration.getLongPressTimeout();
+        mView = v;
+    }
+
+    public void postCheckForLongPress(MotionEvent ev) {
+        mDownX = ev.getX();
+        mDownY = ev.getY();
+        mHasPerformedLongPress = false;
+
+        if (mPendingCheckForLongPress == null) {
+            mPendingCheckForLongPress = new CheckForLongPress();
+        }
+        mView.postDelayed(mPendingCheckForLongPress, mLongPressTimeout);
+    }
+
+    public void onMove(MotionEvent ev) {
+        float x = ev.getX();
+        float y = ev.getY();
+        boolean xMoved = Math.abs(mDownX - x) > mScaledTouchSlop;
+        boolean yMoved = Math.abs(mDownY - y) > mScaledTouchSlop;
+
+        if (xMoved || yMoved) {
+            cancelLongPress();
+        }
+    }
+
+    public void cancelLongPress() {
+        mHasPerformedLongPress = false;
+        if (mPendingCheckForLongPress != null) {
+            mView.removeCallbacks(mPendingCheckForLongPress);
+            mPendingCheckForLongPress = null;
+        }
+    }
+
+    public boolean hasPerformedLongPress() {
+        return mHasPerformedLongPress;
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/ClockView.java b/policy/src/com/android/internal/policy/impl/keyguard/ClockView.java
new file mode 100644
index 0000000..6c701c7
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/ClockView.java
@@ -0,0 +1,224 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.graphics.Typeface;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.format.DateFormat;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import java.lang.ref.WeakReference;
+import java.text.DateFormatSymbols;
+import java.util.Calendar;
+import com.android.internal.R;
+
+/**
+ * Displays the time
+ */
+public class ClockView extends RelativeLayout {
+    private static final String ANDROID_CLOCK_FONT_FILE = "/system/fonts/AndroidClock.ttf";
+    private final static String M12 = "h:mm";
+    private final static String M24 = "kk:mm";
+
+    private Calendar mCalendar;
+    private String mFormat;
+    private TextView mTimeView;
+    private AmPm mAmPm;
+    private ContentObserver mFormatChangeObserver;
+    private int mAttached = 0; // for debugging - tells us whether attach/detach is unbalanced
+
+    /* called by system on minute ticks */
+    private final Handler mHandler = new Handler();
+    private BroadcastReceiver mIntentReceiver;
+
+    private static class TimeChangedReceiver extends BroadcastReceiver {
+        private WeakReference<ClockView> mClock;
+        private Context mContext;
+
+        public TimeChangedReceiver(ClockView clock) {
+            mClock = new WeakReference<ClockView>(clock);
+            mContext = clock.getContext();
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // Post a runnable to avoid blocking the broadcast.
+            final boolean timezoneChanged =
+                    intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED);
+            final ClockView clock = mClock.get();
+            if (clock != null) {
+                clock.mHandler.post(new Runnable() {
+                    public void run() {
+                        if (timezoneChanged) {
+                            clock.mCalendar = Calendar.getInstance();
+                        }
+                        clock.updateTime();
+                    }
+                });
+            } else {
+                try {
+                    mContext.unregisterReceiver(this);
+                } catch (RuntimeException e) {
+                    // Shouldn't happen
+                }
+            }
+        }
+    };
+
+    static class AmPm {
+        private TextView mAmPmTextView;
+        private String mAmString, mPmString;
+
+        AmPm(View parent, Typeface tf) {
+            // No longer used, uncomment if we decide to use AM/PM indicator again
+            // mAmPmTextView = (TextView) parent.findViewById(R.id.am_pm);
+            if (mAmPmTextView != null && tf != null) {
+                mAmPmTextView.setTypeface(tf);
+            }
+
+            String[] ampm = new DateFormatSymbols().getAmPmStrings();
+            mAmString = ampm[0];
+            mPmString = ampm[1];
+        }
+
+        void setShowAmPm(boolean show) {
+            if (mAmPmTextView != null) {
+                mAmPmTextView.setVisibility(show ? View.VISIBLE : View.GONE);
+            }
+        }
+
+        void setIsMorning(boolean isMorning) {
+            if (mAmPmTextView != null) {
+                mAmPmTextView.setText(isMorning ? mAmString : mPmString);
+            }
+        }
+    }
+
+    private static class FormatChangeObserver extends ContentObserver {
+        private WeakReference<ClockView> mClock;
+        private Context mContext;
+        public FormatChangeObserver(ClockView clock) {
+            super(new Handler());
+            mClock = new WeakReference<ClockView>(clock);
+            mContext = clock.getContext();
+        }
+        @Override
+        public void onChange(boolean selfChange) {
+            ClockView digitalClock = mClock.get();
+            if (digitalClock != null) {
+                digitalClock.setDateFormat();
+                digitalClock.updateTime();
+            } else {
+                try {
+                    mContext.getContentResolver().unregisterContentObserver(this);
+                } catch (RuntimeException e) {
+                    // Shouldn't happen
+                }
+            }
+        }
+    }
+
+    public ClockView(Context context) {
+        this(context, null);
+    }
+
+    public ClockView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mTimeView = (TextView) findViewById(R.id.clock_text);
+        mTimeView.setTypeface(Typeface.createFromFile(ANDROID_CLOCK_FONT_FILE));
+        mAmPm = new AmPm(this, null);
+        mCalendar = Calendar.getInstance();
+        setDateFormat();
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+
+        mAttached++;
+
+        /* monitor time ticks, time changed, timezone */
+        if (mIntentReceiver == null) {
+            mIntentReceiver = new TimeChangedReceiver(this);
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(Intent.ACTION_TIME_TICK);
+            filter.addAction(Intent.ACTION_TIME_CHANGED);
+            filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+            mContext.registerReceiverAsUser(mIntentReceiver, UserHandle.OWNER, filter, null, null );
+        }
+
+        /* monitor 12/24-hour display preference */
+        if (mFormatChangeObserver == null) {
+            mFormatChangeObserver = new FormatChangeObserver(this);
+            mContext.getContentResolver().registerContentObserver(
+                    Settings.System.CONTENT_URI, true, mFormatChangeObserver);
+        }
+
+        updateTime();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+
+        mAttached--;
+
+        if (mIntentReceiver != null) {
+            mContext.unregisterReceiver(mIntentReceiver);
+        }
+        if (mFormatChangeObserver != null) {
+            mContext.getContentResolver().unregisterContentObserver(
+                    mFormatChangeObserver);
+        }
+
+        mFormatChangeObserver = null;
+        mIntentReceiver = null;
+    }
+
+    void updateTime(Calendar c) {
+        mCalendar = c;
+        updateTime();
+    }
+
+    public void updateTime() {
+        mCalendar.setTimeInMillis(System.currentTimeMillis());
+
+        CharSequence newTime = DateFormat.format(mFormat, mCalendar);
+        mTimeView.setText(newTime);
+        mAmPm.setIsMorning(mCalendar.get(Calendar.AM_PM) == 0);
+    }
+
+    private void setDateFormat() {
+        mFormat = android.text.format.DateFormat.is24HourFormat(getContext()) ? M24 : M12;
+        mAmPm.setShowAmPm(mFormat.equals(M12));
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/EmergencyButton.java b/policy/src/com/android/internal/policy/impl/keyguard/EmergencyButton.java
new file mode 100644
index 0000000..cd7324c
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/EmergencyButton.java
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.telephony.TelephonyManager;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Button;
+
+import com.android.internal.telephony.IccCardConstants.State;
+import com.android.internal.widget.LockPatternUtils;
+
+/**
+ * This class implements a smart emergency button that updates itself based
+ * on telephony state.  When the phone is idle, it is an emergency call button.
+ * When there's a call in progress, it presents an appropriate message and
+ * allows the user to return to the call.
+ */
+public class EmergencyButton extends Button {
+
+    private static final int EMERGENCY_CALL_TIMEOUT = 10000; // screen timeout after starting e.d.
+    private static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
+
+    KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
+
+        @Override
+        public void onSimStateChanged(State simState) {
+            int phoneState = KeyguardUpdateMonitor.getInstance(mContext).getPhoneState();
+            updateEmergencyCallButton(simState, phoneState);
+        }
+
+        void onPhoneStateChanged(int phoneState) {
+            State simState = KeyguardUpdateMonitor.getInstance(mContext).getSimState();
+            updateEmergencyCallButton(simState, phoneState);
+        };
+    };
+    private LockPatternUtils mLockPatternUtils;
+    private PowerManager mPowerManager;
+
+    public EmergencyButton(Context context) {
+        this(context, null);
+    }
+
+    public EmergencyButton(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mInfoCallback);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mInfoCallback);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mLockPatternUtils = new LockPatternUtils(mContext);
+        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                takeEmergencyCallAction();
+            }
+        });
+        int phoneState = KeyguardUpdateMonitor.getInstance(mContext).getPhoneState();
+        State simState = KeyguardUpdateMonitor.getInstance(mContext).getSimState();
+        updateEmergencyCallButton(simState, phoneState);
+    }
+
+    /**
+     * Shows the emergency dialer or returns the user to the existing call.
+     */
+    public void takeEmergencyCallAction() {
+        // TODO: implement a shorter timeout once new PowerManager API is ready.
+        // should be the equivalent to the old userActivity(EMERGENCY_CALL_TIMEOUT)
+        mPowerManager.userActivity(SystemClock.uptimeMillis(), true);
+        if (TelephonyManager.getDefault().getCallState()
+                == TelephonyManager.CALL_STATE_OFFHOOK) {
+            mLockPatternUtils.resumeCall();
+        } else {
+            Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+            getContext().startActivity(intent);
+        }
+    }
+
+    private void updateEmergencyCallButton(State simState, int phoneState) {
+        boolean enabled = false;
+        if (phoneState == TelephonyManager.CALL_STATE_OFFHOOK) {
+            enabled = true; // always show "return to call" if phone is off-hook
+        } else if (mLockPatternUtils.isEmergencyCallCapable()) {
+            boolean simLocked = KeyguardUpdateMonitor.getInstance(mContext).isSimLocked();
+            if (simLocked) {
+                // Some countries can't handle emergency calls while SIM is locked.
+                enabled = mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked();
+            } else {
+                // True if we need to show a secure screen (pin/pattern/SIM pin/SIM puk);
+                // hides emergency button on "Slide" screen if device is not secure.
+                enabled = mLockPatternUtils.isSecure();
+            }
+        }
+        mLockPatternUtils.updateEmergencyCallButtonState(this, phoneState, enabled,
+                KeyguardViewManager.USE_UPPER_CASE, false);
+    }
+
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
new file mode 100644
index 0000000..259f1e4
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
@@ -0,0 +1,453 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import com.android.internal.policy.IFaceLockCallback;
+import com.android.internal.policy.IFaceLockInterface;
+import com.android.internal.widget.LockPatternUtils;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.View;
+
+public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
+
+    private static final boolean DEBUG = false;
+    private static final String TAG = "FULLockscreen";
+
+    private final Context mContext;
+    private final LockPatternUtils mLockPatternUtils;
+
+    // TODO: is mServiceRunning needed or can we just use mIsRunning or check if mService is null?
+    private boolean mServiceRunning = false;
+    // TODO: now that the code has been restructure to do almost all operations from a handler, this
+    // lock may no longer be necessary.
+    private final Object mServiceRunningLock = new Object();
+    private IFaceLockInterface mService;
+    private boolean mBoundToService = false;
+    private View mFaceUnlockView;
+
+    private Handler mHandler;
+    private final int MSG_SERVICE_CONNECTED = 0;
+    private final int MSG_SERVICE_DISCONNECTED = 1;
+    private final int MSG_UNLOCK = 2;
+    private final int MSG_CANCEL = 3;
+    private final int MSG_REPORT_FAILED_ATTEMPT = 4;
+    private final int MSG_POKE_WAKELOCK = 5;
+
+    // TODO: This was added for the purpose of adhering to what the biometric interface expects
+    // the isRunning() function to return.  However, it is probably not necessary to have both
+    // mRunning and mServiceRunning.  I'd just rather wait to change that logic.
+    private volatile boolean mIsRunning = false;
+
+    // So the user has a consistent amount of time when brought to the backup method from Face
+    // Unlock
+    private final int BACKUP_LOCK_TIMEOUT = 5000;
+
+    KeyguardSecurityCallback mKeyguardScreenCallback;
+
+    /**
+     * Stores some of the structures that Face Unlock will need to access and creates the handler
+     * will be used to execute messages on the UI thread.
+     */
+    public FaceUnlock(Context context) {
+        mContext = context;
+        mLockPatternUtils = new LockPatternUtils(context);
+        mHandler = new Handler(this);
+    }
+
+    public void setKeyguardCallback(KeyguardSecurityCallback keyguardScreenCallback) {
+        mKeyguardScreenCallback = keyguardScreenCallback;
+    }
+
+    /**
+     * Stores and displays the view that Face Unlock is allowed to draw within.
+     * TODO: since the layout object will eventually be shared by multiple biometric unlock
+     * methods, we will have to add our other views (background, cancel button) here.
+     */
+    public void initializeView(View biometricUnlockView) {
+        Log.d(TAG, "initializeView()");
+        mFaceUnlockView = biometricUnlockView;
+    }
+
+    /**
+     * Indicates whether Face Unlock is currently running.
+     */
+    public boolean isRunning() {
+        return mIsRunning;
+    }
+
+    /**
+     * Dismisses face unlock and goes to the backup lock
+     */
+    public void stopAndShowBackup() {
+        if (DEBUG) Log.d(TAG, "stopAndShowBackup()");
+        mHandler.sendEmptyMessage(MSG_CANCEL);
+    }
+
+    /**
+     * Binds to the Face Unlock service.  Face Unlock will be started when the bind completes.  The
+     * Face Unlock view is displayed to hide the backup lock while the service is starting up.
+     * Called on the UI thread.
+     */
+    public boolean start() {
+        if (DEBUG) Log.d(TAG, "start()");
+        if (mHandler.getLooper() != Looper.myLooper()) {
+            Log.e(TAG, "start() called off of the UI thread");
+        }
+
+        if (mIsRunning) {
+            Log.w(TAG, "start() called when already running");
+        }
+
+        if (!mBoundToService) {
+            Log.d(TAG, "Binding to Face Unlock service for user="
+                    + mLockPatternUtils.getCurrentUser());
+            mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
+                    mConnection,
+                    Context.BIND_AUTO_CREATE,
+                    mLockPatternUtils.getCurrentUser());
+            mBoundToService = true;
+        } else {
+            Log.w(TAG, "Attempt to bind to Face Unlock when already bound");
+        }
+
+        mIsRunning = true;
+        return true;
+    }
+
+    /**
+     * Stops Face Unlock and unbinds from the service.  Called on the UI thread.
+     */
+    public boolean stop() {
+        if (DEBUG) Log.d(TAG, "stop()");
+        if (mHandler.getLooper() != Looper.myLooper()) {
+            Log.e(TAG, "stop() called from non-UI thread");
+        }
+
+        // Clearing any old service connected messages.
+        mHandler.removeMessages(MSG_SERVICE_CONNECTED);
+
+        boolean mWasRunning = mIsRunning;
+
+        stopUi();
+
+        if (mBoundToService) {
+            if (mService != null) {
+                try {
+                    mService.unregisterCallback(mFaceUnlockCallback);
+                } catch (RemoteException e) {
+                    // Not much we can do
+                }
+            }
+            Log.d(TAG, "Unbinding from Face Unlock service");
+            mContext.unbindService(mConnection);
+            mBoundToService = false;
+        } else {
+            // This is usually not an error when this happens.  Sometimes we will tell it to
+            // unbind multiple times because it's called from both onWindowFocusChanged and
+            // onDetachedFromWindow.
+            if (DEBUG) Log.d(TAG, "Attempt to unbind from Face Unlock when not bound");
+        }
+        mIsRunning = false;
+        return mWasRunning;
+    }
+
+    /**
+     * Frees up resources used by Face Unlock and stops it if it is still running.
+     */
+    public void cleanUp() {
+        if (DEBUG) Log.d(TAG, "cleanUp()");
+        if (mService != null) {
+            try {
+                mService.unregisterCallback(mFaceUnlockCallback);
+            } catch (RemoteException e) {
+                // Not much we can do
+            }
+            stopUi();
+            mService = null;
+        }
+    }
+
+    /**
+     * Returns the Device Policy Manager quality for Face Unlock, which is BIOMETRIC_WEAK.
+     */
+    public int getQuality() {
+        return DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
+    }
+
+    /**
+     * Handles messages such that everything happens on the UI thread in a deterministic order.
+     * Calls from the Face Unlock service come from binder threads.  Calls from lockscreen typically
+     * come from the UI thread.  This makes sure there are no race conditions between those calls.
+     */
+    public boolean handleMessage(Message msg) {
+        switch (msg.what) {
+            case MSG_SERVICE_CONNECTED:
+                handleServiceConnected();
+                break;
+            case MSG_SERVICE_DISCONNECTED:
+                handleServiceDisconnected();
+                break;
+            case MSG_UNLOCK:
+                handleUnlock();
+                break;
+            case MSG_CANCEL:
+                handleCancel();
+                break;
+            case MSG_REPORT_FAILED_ATTEMPT:
+                handleReportFailedAttempt();
+                break;
+            case MSG_POKE_WAKELOCK:
+                handlePokeWakelock(msg.arg1);
+                break;
+            default:
+                Log.e(TAG, "Unhandled message");
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Tells the service to start its UI via an AIDL interface.  Called when the
+     * onServiceConnected() callback is received.
+     */
+    void handleServiceConnected() {
+        Log.d(TAG, "handleServiceConnected()");
+
+        // It is possible that an unbind has occurred in the time between the bind and when this
+        // function is reached.  If an unbind has already occurred, proceeding on to call startUi()
+        // can result in a fatal error.  Note that the onServiceConnected() callback is
+        // asynchronous, so this possibility would still exist if we executed this directly in
+        // onServiceConnected() rather than using a handler.
+        if (!mBoundToService) {
+            Log.d(TAG, "Dropping startUi() in handleServiceConnected() because no longer bound");
+            return;
+        }
+
+        try {
+            mService.registerCallback(mFaceUnlockCallback);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Caught exception connecting to Face Unlock: " + e.toString());
+            mService = null;
+            mBoundToService = false;
+            mIsRunning = false;
+            return;
+        }
+
+        if (mFaceUnlockView != null) {
+            IBinder windowToken = mFaceUnlockView.getWindowToken();
+            if (windowToken != null) {
+                // When switching between portrait and landscape view while Face Unlock is running,
+                // the screen will eventually go dark unless we poke the wakelock when Face Unlock
+                // is restarted.
+                mKeyguardScreenCallback.userActivity(0);
+
+                int[] position;
+                position = new int[2];
+                mFaceUnlockView.getLocationInWindow(position);
+                startUi(windowToken, position[0], position[1], mFaceUnlockView.getWidth(),
+                        mFaceUnlockView.getHeight());
+            } else {
+                Log.e(TAG, "windowToken is null in handleServiceConnected()");
+            }
+        }
+    }
+
+    /**
+     * Called when the onServiceDisconnected() callback is received.  This should not happen during
+     * normal operation.  It indicates an error has occurred.
+     */
+    void handleServiceDisconnected() {
+        Log.e(TAG, "handleServiceDisconnected()");
+        // TODO: this lock may no longer be needed now that everything is being called from a
+        // handler
+        synchronized (mServiceRunningLock) {
+            mService = null;
+            mServiceRunning = false;
+        }
+        mBoundToService = false;
+        mIsRunning = false;
+    }
+
+    /**
+     * Stops the Face Unlock service and tells the device to grant access to the user.
+     */
+    void handleUnlock() {
+        if (DEBUG) Log.d(TAG, "handleUnlock()");
+        stop();
+        mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
+        mKeyguardScreenCallback.dismiss(true);
+    }
+
+    /**
+     * Stops the Face Unlock service and goes to the backup lock.
+     */
+    void handleCancel() {
+        if (DEBUG) Log.d(TAG, "handleCancel()");
+        // We are going to the backup method, so we don't want to see Face Unlock again until the
+        // next time the user visits keyguard.
+        KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(false);
+
+        mKeyguardScreenCallback.showBackupSecurity();
+        stop();
+        mKeyguardScreenCallback.userActivity(BACKUP_LOCK_TIMEOUT);
+    }
+
+    /**
+     * Increments the number of failed Face Unlock attempts.
+     */
+    void handleReportFailedAttempt() {
+        if (DEBUG) Log.d(TAG, "handleReportFailedAttempt()");
+        // We are going to the backup method, so we don't want to see Face Unlock again until the
+        // next time the user visits keyguard.
+        KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(false);
+
+        mKeyguardScreenCallback.reportFailedUnlockAttempt();
+    }
+
+    /**
+     * If the screen is on, pokes the wakelock to keep the screen alive and active for a specific
+     * amount of time.
+     */
+    void handlePokeWakelock(int millis) {
+      PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+      if (powerManager.isScreenOn()) {
+        mKeyguardScreenCallback.userActivity(millis);
+      }
+    }
+
+    /**
+     * Implements service connection methods.
+     */
+    private ServiceConnection mConnection = new ServiceConnection() {
+        /**
+         * Called when the Face Unlock service connects after calling bind().
+         */
+        public void onServiceConnected(ComponentName className, IBinder iservice) {
+            Log.d(TAG, "Connected to Face Unlock service");
+            mService = IFaceLockInterface.Stub.asInterface(iservice);
+            mHandler.sendEmptyMessage(MSG_SERVICE_CONNECTED);
+        }
+
+        /**
+         * Called if the Face Unlock service unexpectedly disconnects.  This indicates an error.
+         */
+        public void onServiceDisconnected(ComponentName className) {
+            Log.e(TAG, "Unexpected disconnect from Face Unlock service");
+            mHandler.sendEmptyMessage(MSG_SERVICE_DISCONNECTED);
+        }
+    };
+
+    /**
+     * Tells the Face Unlock service to start displaying its UI and start processing.
+     */
+    private void startUi(IBinder windowToken, int x, int y, int w, int h) {
+        if (DEBUG) Log.d(TAG, "startUi()");
+        synchronized (mServiceRunningLock) {
+            if (!mServiceRunning) {
+                Log.d(TAG, "Starting Face Unlock");
+                try {
+                    mService.startUi(windowToken, x, y, w, h,
+                            mLockPatternUtils.isBiometricWeakLivelinessEnabled());
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Caught exception starting Face Unlock: " + e.toString());
+                    return;
+                }
+                mServiceRunning = true;
+            } else {
+                Log.w(TAG, "startUi() attempted while running");
+            }
+        }
+    }
+
+    /**
+     * Tells the Face Unlock service to stop displaying its UI and stop processing.
+     */
+    private void stopUi() {
+        if (DEBUG) Log.d(TAG, "stopUi()");
+        // Note that attempting to stop Face Unlock when it's not running is not an issue.
+        // Face Unlock can return, which stops it and then we try to stop it when the
+        // screen is turned off.  That's why we check.
+        synchronized (mServiceRunningLock) {
+            if (mServiceRunning) {
+                Log.d(TAG, "Stopping Face Unlock");
+                try {
+                    mService.stopUi();
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Caught exception stopping Face Unlock: " + e.toString());
+                }
+                mServiceRunning = false;
+            } else {
+                // This is usually not an error when this happens.  Sometimes we will tell it to
+                // stop multiple times because it's called from both onWindowFocusChanged and
+                // onDetachedFromWindow.
+                if (DEBUG) Log.d(TAG, "stopUi() attempted while not running");
+            }
+        }
+    }
+
+    /**
+     * Implements the AIDL biometric unlock service callback interface.
+     */
+    private final IFaceLockCallback mFaceUnlockCallback = new IFaceLockCallback.Stub() {
+        /**
+         * Called when Face Unlock wants to grant access to the user.
+         */
+        public void unlock() {
+            if (DEBUG) Log.d(TAG, "unlock()");
+            mHandler.sendEmptyMessage(MSG_UNLOCK);
+        }
+
+        /**
+         * Called when Face Unlock wants to go to the backup.
+         */
+        public void cancel() {
+            if (DEBUG) Log.d(TAG, "cancel()");
+            mHandler.sendEmptyMessage(MSG_CANCEL);
+        }
+
+        /**
+         * Called when Face Unlock wants to increment the number of failed attempts.
+         */
+        public void reportFailedAttempt() {
+            if (DEBUG) Log.d(TAG, "reportFailedAttempt()");
+            mHandler.sendEmptyMessage(MSG_REPORT_FAILED_ATTEMPT);
+        }
+
+        /**
+         * Called when Face Unlock wants to keep the screen alive and active for a specific amount
+         * of time.
+         */
+        public void pokeWakelock(int millis) {
+            if (DEBUG) Log.d(TAG, "pokeWakelock() for " + millis + "ms");
+            Message message = mHandler.obtainMessage(MSG_POKE_WAKELOCK, millis, -1);
+            mHandler.sendMessage(message);
+        }
+
+    };
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java
new file mode 100644
index 0000000..cc520dc
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java
@@ -0,0 +1,263 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.CountDownTimer;
+import android.os.SystemClock;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.view.HapticFeedbackConstants;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.inputmethod.EditorInfo;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+import com.android.internal.R;
+import com.android.internal.widget.LockPatternUtils;
+
+/**
+ * Base class for PIN and password unlock screens.
+ */
+public abstract class KeyguardAbsKeyInputView extends LinearLayout
+        implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
+    protected KeyguardSecurityCallback mCallback;
+    protected TextView mPasswordEntry;
+    protected LockPatternUtils mLockPatternUtils;
+    protected SecurityMessageDisplay mSecurityMessageDisplay;
+    protected View mEcaView;
+    private Drawable mBouncerFrame;
+    protected boolean mEnableHaptics;
+
+    // To avoid accidental lockout due to events while the device in in the pocket, ignore
+    // any passwords with length less than or equal to this length.
+    protected static final int MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT = 3;
+
+    public KeyguardAbsKeyInputView(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardAbsKeyInputView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public void setKeyguardCallback(KeyguardSecurityCallback callback) {
+        mCallback = callback;
+    }
+
+    public void setLockPatternUtils(LockPatternUtils utils) {
+        mLockPatternUtils = utils;
+        mEnableHaptics = mLockPatternUtils.isTactileFeedbackEnabled();
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        if (hasWindowFocus) {
+            reset();
+        }
+    }
+
+    public void reset() {
+        // start fresh
+        mPasswordEntry.setText("");
+        mPasswordEntry.requestFocus();
+
+        // if the user is currently locked out, enforce it.
+        long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
+        if (deadline != 0) {
+            handleAttemptLockout(deadline);
+        } else {
+            resetState();
+        }
+    }
+
+    protected abstract int getPasswordTextViewId();
+    protected abstract void resetState();
+
+    @Override
+    protected void onFinishInflate() {
+        mLockPatternUtils = new LockPatternUtils(mContext);
+
+        mPasswordEntry = (TextView) findViewById(getPasswordTextViewId());
+        mPasswordEntry.setOnEditorActionListener(this);
+        mPasswordEntry.addTextChangedListener(this);
+
+        // Set selected property on so the view can send accessibility events.
+        mPasswordEntry.setSelected(true);
+
+        // Poke the wakelock any time the text is selected or modified
+        mPasswordEntry.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                mCallback.userActivity(0); // TODO: customize timeout for text?
+            }
+        });
+
+        mPasswordEntry.addTextChangedListener(new TextWatcher() {
+            public void onTextChanged(CharSequence s, int start, int before, int count) {
+            }
+
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+            }
+
+            public void afterTextChanged(Editable s) {
+                if (mCallback != null) {
+                    mCallback.userActivity(0);
+                }
+            }
+        });
+        mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
+        mEcaView = findViewById(R.id.keyguard_selector_fade_container);
+        View bouncerFrameView = findViewById(R.id.keyguard_bouncer_frame);
+        if (bouncerFrameView != null) {
+            mBouncerFrame = bouncerFrameView.getBackground();
+        }
+    }
+
+    @Override
+    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
+        // send focus to the password field
+        return mPasswordEntry.requestFocus(direction, previouslyFocusedRect);
+    }
+
+    /*
+     * Override this if you have a different string for "wrong password"
+     *
+     * Note that PIN/PUK have their own implementation of verifyPasswordAndUnlock and so don't need this
+     */
+    protected int getWrongPasswordStringId() {
+        return R.string.kg_wrong_password;
+    }
+
+    protected void verifyPasswordAndUnlock() {
+        String entry = mPasswordEntry.getText().toString();
+        if (mLockPatternUtils.checkPassword(entry)) {
+            mCallback.reportSuccessfulUnlockAttempt();
+            mCallback.dismiss(true);
+        } else if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) {
+            // to avoid accidental lockout, only count attempts that are long enough to be a
+            // real password. This may require some tweaking.
+            mCallback.reportFailedUnlockAttempt();
+            if (0 == (mCallback.getFailedAttempts()
+                    % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
+                long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
+                handleAttemptLockout(deadline);
+            }
+            mSecurityMessageDisplay.setMessage(getWrongPasswordStringId(), true);
+        }
+        mPasswordEntry.setText("");
+    }
+
+    // Prevent user from using the PIN/Password entry until scheduled deadline.
+    protected void handleAttemptLockout(long elapsedRealtimeDeadline) {
+        mPasswordEntry.setEnabled(false);
+        long elapsedRealtime = SystemClock.elapsedRealtime();
+        new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
+
+            @Override
+            public void onTick(long millisUntilFinished) {
+                int secondsRemaining = (int) (millisUntilFinished / 1000);
+                mSecurityMessageDisplay.setMessage(
+                        R.string.kg_too_many_failed_attempts_countdown, true, secondsRemaining);
+            }
+
+            @Override
+            public void onFinish() {
+                mSecurityMessageDisplay.setMessage("", false);
+                resetState();
+            }
+        }.start();
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        mCallback.userActivity(0);
+        return false;
+    }
+
+    @Override
+    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+        // Check if this was the result of hitting the enter key
+        if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE
+                || actionId == EditorInfo.IME_ACTION_NEXT) {
+            verifyPasswordAndUnlock();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean needsInput() {
+        return false;
+    }
+
+    @Override
+    public void onPause() {
+
+    }
+
+    @Override
+    public void onResume(int reason) {
+        reset();
+    }
+
+    @Override
+    public KeyguardSecurityCallback getCallback() {
+        return mCallback;
+    }
+
+    @Override
+    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+        if (mCallback != null) {
+            mCallback.userActivity(KeyguardViewManager.DIGIT_PRESS_WAKE_MILLIS);
+        }
+    }
+
+    @Override
+    public void onTextChanged(CharSequence s, int start, int before, int count) {
+    }
+
+    @Override
+    public void afterTextChanged(Editable s) {
+    }
+
+    // Cause a VIRTUAL_KEY vibration
+    public void doHapticKeyClick() {
+        if (mEnableHaptics) {
+            performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
+                    HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING
+                    | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
+        }
+    }
+
+    @Override
+    public void showBouncer(int duration) {
+        KeyguardSecurityViewHelper.
+                showBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
+    }
+
+    @Override
+    public void hideBouncer(int duration) {
+        KeyguardSecurityViewHelper.
+                hideBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
+    }
+}
+
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
new file mode 100644
index 0000000..e0e7128
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
@@ -0,0 +1,333 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerCallback;
+import android.accounts.AccountManagerFuture;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.text.Editable;
+import android.text.InputFilter;
+import android.text.LoginFilter;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.R;
+
+import java.io.IOException;
+
+/**
+ * When the user forgets their password a bunch of times, we fall back on their
+ * account's login/password to unlock the phone (and reset their lock pattern).
+ */
+public class KeyguardAccountView extends LinearLayout implements KeyguardSecurityView,
+        View.OnClickListener, TextWatcher {
+    private static final int AWAKE_POKE_MILLIS = 30000;
+    private static final String LOCK_PATTERN_PACKAGE = "com.android.settings";
+    private static final String LOCK_PATTERN_CLASS = LOCK_PATTERN_PACKAGE + ".ChooseLockGeneric";
+
+    private KeyguardSecurityCallback mCallback;
+    private LockPatternUtils mLockPatternUtils;
+    private EditText mLogin;
+    private EditText mPassword;
+    private Button mOk;
+    public boolean mEnableFallback;
+    private SecurityMessageDisplay mSecurityMessageDisplay;
+
+    /**
+     * Shown while making asynchronous check of password.
+     */
+    private ProgressDialog mCheckingDialog;
+
+    public KeyguardAccountView(Context context) {
+        this(context, null, 0);
+    }
+
+    public KeyguardAccountView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public KeyguardAccountView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mLockPatternUtils = new LockPatternUtils(getContext());
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mLogin = (EditText) findViewById(R.id.login);
+        mLogin.setFilters(new InputFilter[] { new LoginFilter.UsernameFilterGeneric() } );
+        mLogin.addTextChangedListener(this);
+
+        mPassword = (EditText) findViewById(R.id.password);
+        mPassword.addTextChangedListener(this);
+
+        mOk = (Button) findViewById(R.id.ok);
+        mOk.setOnClickListener(this);
+
+        mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
+        reset();
+    }
+
+    public void setKeyguardCallback(KeyguardSecurityCallback callback) {
+        mCallback = callback;
+    }
+
+    public void setLockPatternUtils(LockPatternUtils utils) {
+        mLockPatternUtils = utils;
+    }
+
+    public KeyguardSecurityCallback getCallback() {
+        return mCallback;
+    }
+
+
+    public void afterTextChanged(Editable s) {
+    }
+
+    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+    }
+
+    public void onTextChanged(CharSequence s, int start, int before, int count) {
+        if (mCallback != null) {
+            mCallback.userActivity(AWAKE_POKE_MILLIS);
+        }
+    }
+
+    @Override
+    protected boolean onRequestFocusInDescendants(int direction,
+            Rect previouslyFocusedRect) {
+        // send focus to the login field
+        return mLogin.requestFocus(direction, previouslyFocusedRect);
+    }
+
+    public boolean needsInput() {
+        return true;
+    }
+
+    public void reset() {
+        // start fresh
+        mLogin.setText("");
+        mPassword.setText("");
+        mLogin.requestFocus();
+        boolean permLocked = mLockPatternUtils.isPermanentlyLocked();
+        mSecurityMessageDisplay.setMessage(permLocked ? R.string.kg_login_too_many_attempts :
+            R.string.kg_login_instructions, permLocked ? true : false);
+    }
+
+    /** {@inheritDoc} */
+    public void cleanUp() {
+        if (mCheckingDialog != null) {
+            mCheckingDialog.hide();
+        }
+        mCallback = null;
+        mLockPatternUtils = null;
+    }
+
+    public void onClick(View v) {
+        mCallback.userActivity(0);
+        if (v == mOk) {
+            asyncCheckPassword();
+        }
+    }
+
+    private void postOnCheckPasswordResult(final boolean success) {
+        // ensure this runs on UI thread
+        mLogin.post(new Runnable() {
+            public void run() {
+                if (success) {
+                    // clear out forgotten password
+                    mLockPatternUtils.setPermanentlyLocked(false);
+                    mLockPatternUtils.setLockPatternEnabled(false);
+                    mLockPatternUtils.saveLockPattern(null);
+
+                    // launch the 'choose lock pattern' activity so
+                    // the user can pick a new one if they want to
+                    Intent intent = new Intent();
+                    intent.setClassName(LOCK_PATTERN_PACKAGE, LOCK_PATTERN_CLASS);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                    mContext.startActivityAsUser(intent,
+                            new UserHandle(mLockPatternUtils.getCurrentUser()));
+                    mCallback.reportSuccessfulUnlockAttempt();
+
+                    // dismiss keyguard
+                    mCallback.dismiss(true);
+                } else {
+                    mSecurityMessageDisplay.setMessage(R.string.kg_login_invalid_input, true);
+                    mPassword.setText("");
+                    mCallback.reportFailedUnlockAttempt();
+                }
+            }
+        });
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if (event.getAction() == KeyEvent.ACTION_DOWN
+                && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+            if (mLockPatternUtils.isPermanentlyLocked()) {
+                mCallback.dismiss(false);
+            } else {
+                // TODO: mCallback.forgotPattern(false);
+            }
+            return true;
+        }
+        return super.dispatchKeyEvent(event);
+    }
+
+    /**
+     * Given the string the user entered in the 'username' field, find
+     * the stored account that they probably intended.  Prefer, in order:
+     *
+     *   - an exact match for what was typed, or
+     *   - a case-insensitive match for what was typed, or
+     *   - if they didn't include a domain, an exact match of the username, or
+     *   - if they didn't include a domain, a case-insensitive
+     *     match of the username.
+     *
+     * If there is a tie for the best match, choose neither --
+     * the user needs to be more specific.
+     *
+     * @return an account name from the database, or null if we can't
+     * find a single best match.
+     */
+    private Account findIntendedAccount(String username) {
+        Account[] accounts = AccountManager.get(mContext).getAccountsByTypeAsUser("com.google",
+                new UserHandle(mLockPatternUtils.getCurrentUser()));
+
+        // Try to figure out which account they meant if they
+        // typed only the username (and not the domain), or got
+        // the case wrong.
+
+        Account bestAccount = null;
+        int bestScore = 0;
+        for (Account a: accounts) {
+            int score = 0;
+            if (username.equals(a.name)) {
+                score = 4;
+            } else if (username.equalsIgnoreCase(a.name)) {
+                score = 3;
+            } else if (username.indexOf('@') < 0) {
+                int i = a.name.indexOf('@');
+                if (i >= 0) {
+                    String aUsername = a.name.substring(0, i);
+                    if (username.equals(aUsername)) {
+                        score = 2;
+                    } else if (username.equalsIgnoreCase(aUsername)) {
+                        score = 1;
+                    }
+                }
+            }
+            if (score > bestScore) {
+                bestAccount = a;
+                bestScore = score;
+            } else if (score == bestScore) {
+                bestAccount = null;
+            }
+        }
+        return bestAccount;
+    }
+
+    private void asyncCheckPassword() {
+        mCallback.userActivity(AWAKE_POKE_MILLIS);
+        final String login = mLogin.getText().toString();
+        final String password = mPassword.getText().toString();
+        Account account = findIntendedAccount(login);
+        if (account == null) {
+            postOnCheckPasswordResult(false);
+            return;
+        }
+        getProgressDialog().show();
+        Bundle options = new Bundle();
+        options.putString(AccountManager.KEY_PASSWORD, password);
+        AccountManager.get(mContext).confirmCredentialsAsUser(account, options, null /* activity */,
+                new AccountManagerCallback<Bundle>() {
+            public void run(AccountManagerFuture<Bundle> future) {
+                try {
+                    mCallback.userActivity(AWAKE_POKE_MILLIS);
+                    final Bundle result = future.getResult();
+                    final boolean verified = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
+                    postOnCheckPasswordResult(verified);
+                } catch (OperationCanceledException e) {
+                    postOnCheckPasswordResult(false);
+                } catch (IOException e) {
+                    postOnCheckPasswordResult(false);
+                } catch (AuthenticatorException e) {
+                    postOnCheckPasswordResult(false);
+                } finally {
+                    mLogin.post(new Runnable() {
+                        public void run() {
+                            getProgressDialog().hide();
+                        }
+                    });
+                }
+            }
+        }, null /* handler */, new UserHandle(mLockPatternUtils.getCurrentUser()));
+    }
+
+    private Dialog getProgressDialog() {
+        if (mCheckingDialog == null) {
+            mCheckingDialog = new ProgressDialog(mContext);
+            mCheckingDialog.setMessage(
+                    mContext.getString(R.string.kg_login_checking_password));
+            mCheckingDialog.setIndeterminate(true);
+            mCheckingDialog.setCancelable(false);
+            mCheckingDialog.getWindow().setType(
+                    WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+        }
+        return mCheckingDialog;
+    }
+
+    @Override
+    public void onPause() {
+
+    }
+
+    @Override
+    public void onResume(int reason) {
+        reset();
+    }
+
+    @Override
+    public void showUsabilityHint() {
+    }
+
+    @Override
+    public void showBouncer(int duration) {
+    }
+
+    @Override
+    public void hideBouncer(int duration) {
+    }
+}
+
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java
new file mode 100644
index 0000000..4c19caa
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java
@@ -0,0 +1,272 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.app.ActivityManagerNative;
+import android.app.ActivityOptions;
+import android.app.IActivityManager.WaitResult;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.MediaStore;
+import android.util.Log;
+import android.view.WindowManager;
+
+import com.android.internal.policy.impl.keyguard.KeyguardHostView.OnDismissAction;
+import com.android.internal.widget.LockPatternUtils;
+
+import java.util.List;
+
+public abstract class KeyguardActivityLauncher {
+    private static final String TAG = KeyguardActivityLauncher.class.getSimpleName();
+    private static final boolean DEBUG = KeyguardHostView.DEBUG;
+    private static final String META_DATA_KEYGUARD_LAYOUT = "com.android.keyguard.layout";
+    private static final Intent SECURE_CAMERA_INTENT =
+            new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
+                    .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+    private static final Intent INSECURE_CAMERA_INTENT =
+            new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
+
+    abstract Context getContext();
+
+    abstract KeyguardSecurityCallback getCallback();
+
+    abstract LockPatternUtils getLockPatternUtils();
+
+    public static class CameraWidgetInfo {
+        public String contextPackage;
+        public int layoutId;
+    }
+
+    public CameraWidgetInfo getCameraWidgetInfo() {
+        CameraWidgetInfo info = new CameraWidgetInfo();
+        Intent intent = getCameraIntent();
+        PackageManager packageManager = getContext().getPackageManager();
+        final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
+                intent, PackageManager.MATCH_DEFAULT_ONLY, getLockPatternUtils().getCurrentUser());
+        if (appList.size() == 0) {
+            if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): Nothing found");
+            return null;
+        }
+        ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
+                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
+                getLockPatternUtils().getCurrentUser());
+        if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): resolved: " + resolved);
+        if (wouldLaunchResolverActivity(resolved, appList)) {
+            if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): Would launch resolver");
+            return info;
+        }
+        if (resolved == null || resolved.activityInfo == null) {
+            return null;
+        }
+        if (resolved.activityInfo.metaData == null || resolved.activityInfo.metaData.isEmpty()) {
+            if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): no metadata found");
+            return info;
+        }
+        int layoutId = resolved.activityInfo.metaData.getInt(META_DATA_KEYGUARD_LAYOUT);
+        if (layoutId == 0) {
+            if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): no layout specified");
+            return info;
+        }
+        info.contextPackage = resolved.activityInfo.packageName;
+        info.layoutId = layoutId;
+        return info;
+    }
+
+    public void launchCamera(Handler worker, Runnable onSecureCameraStarted) {
+        LockPatternUtils lockPatternUtils = getLockPatternUtils();
+        if (lockPatternUtils.isSecure()) {
+            // Launch the secure version of the camera
+            if (wouldLaunchResolverActivity(SECURE_CAMERA_INTENT)) {
+                // TODO: Show disambiguation dialog instead.
+                // For now, we'll treat this like launching any other app from secure keyguard.
+                // When they do, user sees the system's ResolverActivity which lets them choose
+                // which secure camera to use.
+                launchActivity(SECURE_CAMERA_INTENT, false, false, null, null);
+            } else {
+                launchActivity(SECURE_CAMERA_INTENT, true, false, worker, onSecureCameraStarted);
+            }
+        } else {
+            // Launch the normal camera
+            launchActivity(INSECURE_CAMERA_INTENT, false, false, null, null);
+        }
+    }
+
+    public void launchWidgetPicker(int appWidgetId) {
+        Intent pickIntent = new Intent(AppWidgetManager.ACTION_KEYGUARD_APPWIDGET_PICK);
+
+        pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+        pickIntent.putExtra(AppWidgetManager.EXTRA_CUSTOM_SORT, false);
+        pickIntent.putExtra(AppWidgetManager.EXTRA_CATEGORY_FILTER,
+                AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
+
+        Bundle options = new Bundle();
+        options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
+                AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
+        pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
+        pickIntent.addFlags(
+                Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_SINGLE_TOP
+                | Intent.FLAG_ACTIVITY_CLEAR_TOP
+                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+
+        launchActivity(pickIntent, false, false, null, null);
+    }
+
+    /**
+     * Launches the said intent for the current foreground user.
+     *
+     * @param intent
+     * @param showsWhileLocked true if the activity can be run on top of keyguard.
+     *   See {@link WindowManager#FLAG_SHOW_WHEN_LOCKED}
+     * @param useDefaultAnimations true if default transitions should be used, else suppressed.
+     * @param worker if supplied along with onStarted, used to launch the blocking activity call.
+     * @param onStarted if supplied along with worker, called after activity is started.
+     */
+    public void launchActivity(final Intent intent,
+            boolean showsWhileLocked,
+            boolean useDefaultAnimations,
+            final Handler worker,
+            final Runnable onStarted) {
+
+        final Context context = getContext();
+        final Bundle animation = useDefaultAnimations ? null
+                : ActivityOptions.makeCustomAnimation(context, 0, 0).toBundle();
+        launchActivityWithAnimation(intent, showsWhileLocked, animation, worker, onStarted);
+    }
+
+    public void launchActivityWithAnimation(final Intent intent,
+            boolean showsWhileLocked,
+            final Bundle animation,
+            final Handler worker,
+            final Runnable onStarted) {
+
+        LockPatternUtils lockPatternUtils = getLockPatternUtils();
+        intent.addFlags(
+                Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_SINGLE_TOP
+                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        boolean isSecure = lockPatternUtils.isSecure();
+        if (!isSecure || showsWhileLocked) {
+            if (!isSecure) {
+                dismissKeyguardOnNextActivity();
+            }
+            try {
+                if (DEBUG) Log.d(TAG, String.format("Starting activity for intent %s at %s",
+                        intent, SystemClock.uptimeMillis()));
+                startActivityForCurrentUser(intent, animation, worker, onStarted);
+            } catch (ActivityNotFoundException e) {
+                Log.w(TAG, "Activity not found for intent + " + intent.getAction());
+            }
+        } else {
+            // Create a runnable to start the activity and ask the user to enter their
+            // credentials.
+            KeyguardSecurityCallback callback = getCallback();
+            callback.setOnDismissAction(new OnDismissAction() {
+                @Override
+                public boolean onDismiss() {
+                    dismissKeyguardOnNextActivity();
+                    startActivityForCurrentUser(intent, animation, worker, onStarted);
+                    return true;
+                }
+            });
+            callback.dismiss(false);
+        }
+    }
+
+    private void dismissKeyguardOnNextActivity() {
+        try {
+            ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
+        } catch (RemoteException e) {
+            Log.w(TAG, "can't dismiss keyguard on launch");
+        }
+    }
+
+    private void startActivityForCurrentUser(final Intent intent, final Bundle options,
+            Handler worker, final Runnable onStarted) {
+        final UserHandle user = new UserHandle(UserHandle.USER_CURRENT);
+        if (worker == null || onStarted == null) {
+            getContext().startActivityAsUser(intent, options, user);
+            return;
+        }
+        // if worker + onStarted are supplied, run blocking activity launch call in the background
+        worker.post(new Runnable(){
+            @Override
+            public void run() {
+                try {
+                    WaitResult result = ActivityManagerNative.getDefault().startActivityAndWait(
+                            null /*caller*/,
+                            intent,
+                            intent.resolveTypeIfNeeded(getContext().getContentResolver()),
+                            null /*resultTo*/,
+                            null /*resultWho*/,
+                            0 /*requestCode*/,
+                            Intent.FLAG_ACTIVITY_NEW_TASK,
+                            null /*profileFile*/,
+                            null /*profileFd*/,
+                            options,
+                            user.getIdentifier());
+                    if (DEBUG) Log.d(TAG, String.format("waitResult[%s,%s,%s,%s] at %s",
+                            result.result, result.thisTime, result.totalTime, result.who,
+                            SystemClock.uptimeMillis()));
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Error starting activity", e);
+                    return;
+                }
+                try {
+                    onStarted.run();
+                } catch (Throwable t) {
+                    Log.w(TAG, "Error running onStarted callback", t);
+                }
+            }});
+    }
+
+    private Intent getCameraIntent() {
+        return getLockPatternUtils().isSecure() ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
+    }
+
+    private boolean wouldLaunchResolverActivity(Intent intent) {
+        PackageManager packageManager = getContext().getPackageManager();
+        ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
+                PackageManager.MATCH_DEFAULT_ONLY, getLockPatternUtils().getCurrentUser());
+        List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
+                intent, PackageManager.MATCH_DEFAULT_ONLY, getLockPatternUtils().getCurrentUser());
+        return wouldLaunchResolverActivity(resolved, appList);
+    }
+
+    private boolean wouldLaunchResolverActivity(ResolveInfo resolved, List<ResolveInfo> appList) {
+        // If the list contains the above resolved activity, then it can't be
+        // ResolverActivity itself.
+        for (int i = 0; i < appList.size(); i++) {
+            ResolveInfo tmp = appList.get(i);
+            if (tmp.activityInfo.name.equals(resolved.activityInfo.name)
+                    && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardCircleFramedDrawable.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardCircleFramedDrawable.java
new file mode 100644
index 0000000..29124c4
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardCircleFramedDrawable.java
@@ -0,0 +1,161 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+
+import android.util.Log;
+
+class KeyguardCircleFramedDrawable extends Drawable {
+
+    private final Bitmap mBitmap;
+    private final int mSize;
+    private final Paint mPaint;
+    private final float mShadowRadius;
+    private final float mStrokeWidth;
+    private final int mFrameColor;
+    private final int mHighlightColor;
+    private final int mFrameShadowColor;
+
+    private float mScale;
+    private Path mFramePath;
+    private Rect mSrcRect;
+    private RectF mDstRect;
+    private RectF mFrameRect;
+    private boolean mPressed;
+
+    public KeyguardCircleFramedDrawable(Bitmap bitmap, int size,
+            int frameColor, float strokeWidth,
+            int frameShadowColor, float shadowRadius,
+            int highlightColor) {
+        super();
+        mSize = size;
+        mShadowRadius = shadowRadius;
+        mFrameColor = frameColor;
+        mFrameShadowColor = frameShadowColor;
+        mStrokeWidth = strokeWidth;
+        mHighlightColor = highlightColor;
+
+        mBitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888);
+        final Canvas canvas = new Canvas(mBitmap);
+
+        final int width = bitmap.getWidth();
+        final int height = bitmap.getHeight();
+        final int square = Math.min(width, height);
+
+        final Rect cropRect = new Rect((width - square) / 2, (height - square) / 2, square, square);
+        final RectF circleRect = new RectF(0f, 0f, mSize, mSize);
+        circleRect.inset(mStrokeWidth / 2f, mStrokeWidth / 2f);
+        circleRect.inset(mShadowRadius, mShadowRadius);
+
+        final Path fillPath = new Path();
+        fillPath.addArc(circleRect, 0f, 360f);
+
+        canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+
+        // opaque circle matte
+        mPaint = new Paint();
+        mPaint.setAntiAlias(true);
+        mPaint.setColor(Color.BLACK);
+        mPaint.setStyle(Paint.Style.FILL);
+        canvas.drawPath(fillPath, mPaint);
+
+        // mask in the icon where the bitmap is opaque
+        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
+        canvas.drawBitmap(bitmap, cropRect, circleRect, mPaint);
+
+        // prepare paint for frame drawing
+        mPaint.setXfermode(null);
+
+        mScale = 1f;
+
+        mSrcRect = new Rect(0, 0, mSize, mSize);
+        mDstRect = new RectF(0, 0, mSize, mSize);
+        mFrameRect = new RectF(mDstRect);
+        mFramePath = new Path();
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        // clear background
+        final float outside = Math.min(canvas.getWidth(), canvas.getHeight());
+        final float inside = mScale * outside;
+        final float pad = (outside - inside) / 2f;
+
+        mDstRect.set(pad, pad, outside - pad, outside - pad);
+        canvas.drawBitmap(mBitmap, mSrcRect, mDstRect, null);
+
+        mFrameRect.set(mDstRect);
+        mFrameRect.inset(mStrokeWidth / 2f, mStrokeWidth / 2f);
+        mFrameRect.inset(mShadowRadius, mShadowRadius);
+
+        mFramePath.reset();
+        mFramePath.addArc(mFrameRect, 0f, 360f);
+
+        // white frame
+        if (mPressed) {
+            mPaint.setStyle(Paint.Style.FILL);
+            mPaint.setColor(Color.argb((int) (0.33f * 255),
+                            Color.red(mHighlightColor),
+                            Color.green(mHighlightColor),
+                            Color.blue(mHighlightColor)));
+            canvas.drawPath(mFramePath, mPaint);
+        }
+        mPaint.setStrokeWidth(mStrokeWidth);
+        mPaint.setStyle(Paint.Style.STROKE);
+        mPaint.setColor(mPressed ? mHighlightColor : mFrameColor);
+        mPaint.setShadowLayer(mShadowRadius, 0f, 0f, mFrameShadowColor);
+        canvas.drawPath(mFramePath, mPaint);
+    }
+
+    public void setScale(float scale) {
+        Log.i("KFD", "scale: " + scale);
+        mScale = scale;
+    }
+
+    public float getScale() {
+        return mScale;
+    }
+
+    public void setPressed(boolean pressed) {
+        mPressed = pressed;
+    }
+
+    @Override
+    public int getOpacity() {
+        return PixelFormat.TRANSLUCENT;
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter cf) {
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
new file mode 100644
index 0000000..de3354a
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
@@ -0,0 +1,245 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.os.PowerManager;
+import android.telephony.TelephonyManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+
+import com.android.internal.R;
+
+import com.android.internal.widget.LockPatternUtils;
+
+public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecurityView {
+
+    private static final String TAG = "FULKeyguardFaceUnlockView";
+    private static final boolean DEBUG = false;
+    private KeyguardSecurityCallback mKeyguardSecurityCallback;
+    private LockPatternUtils mLockPatternUtils;
+    private BiometricSensorUnlock mBiometricUnlock;
+    private View mFaceUnlockAreaView;
+    private ImageButton mCancelButton;
+    private SecurityMessageDisplay mSecurityMessageDisplay;
+    private View mEcaView;
+    private Drawable mBouncerFrame;
+
+    private boolean mIsShowing = false;
+    private final Object mIsShowingLock = new Object();
+
+    public KeyguardFaceUnlockView(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardFaceUnlockView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        initializeBiometricUnlockView();
+
+        mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
+        mEcaView = findViewById(R.id.keyguard_selector_fade_container);
+        View bouncerFrameView = findViewById(R.id.keyguard_bouncer_frame);
+        if (bouncerFrameView != null) {
+            mBouncerFrame = bouncerFrameView.getBackground();
+        }
+    }
+
+    @Override
+    public void setKeyguardCallback(KeyguardSecurityCallback callback) {
+        mKeyguardSecurityCallback = callback;
+        // TODO: formalize this in the interface or factor it out
+        ((FaceUnlock)mBiometricUnlock).setKeyguardCallback(callback);
+    }
+
+    @Override
+    public void setLockPatternUtils(LockPatternUtils utils) {
+        mLockPatternUtils = utils;
+    }
+
+    @Override
+    public void reset() {
+
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        if (DEBUG) Log.d(TAG, "onDetachedFromWindow()");
+        if (mBiometricUnlock != null) {
+            mBiometricUnlock.stop();
+        }
+        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateCallback);
+    }
+
+    @Override
+    public void onPause() {
+        if (DEBUG) Log.d(TAG, "onPause()");
+        if (mBiometricUnlock != null) {
+            mBiometricUnlock.stop();
+        }
+        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateCallback);
+    }
+
+    @Override
+    public void onResume(int reason) {
+        if (DEBUG) Log.d(TAG, "onResume()");
+        mIsShowing = KeyguardUpdateMonitor.getInstance(mContext).isKeyguardVisible();
+        maybeStartBiometricUnlock();
+        KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateCallback);
+    }
+
+    @Override
+    public boolean needsInput() {
+        return false;
+    }
+
+    @Override
+    public KeyguardSecurityCallback getCallback() {
+        return mKeyguardSecurityCallback;
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
+        mBiometricUnlock.initializeView(mFaceUnlockAreaView);
+    }
+
+    private void initializeBiometricUnlockView() {
+        if (DEBUG) Log.d(TAG, "initializeBiometricUnlockView()");
+        mFaceUnlockAreaView = findViewById(R.id.face_unlock_area_view);
+        if (mFaceUnlockAreaView != null) {
+            mBiometricUnlock = new FaceUnlock(mContext);
+
+            mCancelButton = (ImageButton) findViewById(R.id.face_unlock_cancel_button);
+            mCancelButton.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    mBiometricUnlock.stopAndShowBackup();
+                }
+            });
+        } else {
+            Log.w(TAG, "Couldn't find biometric unlock view");
+        }
+    }
+
+    /**
+     * Starts the biometric unlock if it should be started based on a number of factors.  If it
+     * should not be started, it either goes to the back up, or remains showing to prepare for
+     * it being started later.
+     */
+    private void maybeStartBiometricUnlock() {
+        if (DEBUG) Log.d(TAG, "maybeStartBiometricUnlock()");
+        if (mBiometricUnlock != null) {
+            KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
+            final boolean backupIsTimedOut = (
+                    monitor.getFailedUnlockAttempts() >=
+                    LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
+            PowerManager powerManager = (PowerManager) mContext.getSystemService(
+                    Context.POWER_SERVICE);
+
+            boolean isShowing;
+            synchronized(mIsShowingLock) {
+                isShowing = mIsShowing;
+            }
+
+            // Don't start it if the screen is off or if it's not showing, but keep this view up
+            // because we want it here and ready for when the screen turns on or when it does start
+            // showing.
+            if (!powerManager.isScreenOn() || !isShowing) {
+                mBiometricUnlock.stop(); // It shouldn't be running but calling this can't hurt.
+                return;
+            }
+
+            // TODO: Some of these conditions are handled in KeyguardSecurityModel and may not be
+            // necessary here.
+            if (monitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
+                    && !monitor.getMaxBiometricUnlockAttemptsReached()
+                    && !backupIsTimedOut) {
+                mBiometricUnlock.start();
+            } else {
+                mBiometricUnlock.stopAndShowBackup();
+            }
+        }
+    }
+
+    KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
+        // We need to stop the biometric unlock when a phone call comes in
+        @Override
+        public void onPhoneStateChanged(int phoneState) {
+            if (DEBUG) Log.d(TAG, "onPhoneStateChanged(" + phoneState + ")");
+            if (phoneState == TelephonyManager.CALL_STATE_RINGING) {
+                if (mBiometricUnlock != null) {
+                    mBiometricUnlock.stopAndShowBackup();
+                }
+            }
+        }
+
+        @Override
+        public void onUserSwitched(int userId) {
+            if (DEBUG) Log.d(TAG, "onUserSwitched(" + userId + ")");
+            if (mBiometricUnlock != null) {
+                mBiometricUnlock.stop();
+            }
+            // No longer required; static value set by KeyguardViewMediator
+            // mLockPatternUtils.setCurrentUser(userId);
+        }
+
+        @Override
+        public void onKeyguardVisibilityChanged(boolean showing) {
+            if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")");
+            boolean wasShowing = false;
+            synchronized(mIsShowingLock) {
+                wasShowing = mIsShowing;
+                mIsShowing = showing;
+            }
+            PowerManager powerManager = (PowerManager) mContext.getSystemService(
+                    Context.POWER_SERVICE);
+            if (mBiometricUnlock != null) {
+                if (!showing && wasShowing) {
+                    mBiometricUnlock.stop();
+                } else if (showing && powerManager.isScreenOn() && !wasShowing) {
+                    maybeStartBiometricUnlock();
+                }
+            }
+        }
+    };
+
+    @Override
+    public void showUsabilityHint() {
+    }
+
+    @Override
+    public void showBouncer(int duration) {
+        KeyguardSecurityViewHelper.
+                showBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
+    }
+
+    @Override
+    public void hideBouncer(int duration) {
+        KeyguardSecurityViewHelper.
+                hideBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
+    }
+
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardGlowStripView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardGlowStripView.java
new file mode 100644
index 0000000..e1c95f0
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardGlowStripView.java
@@ -0,0 +1,139 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
+import android.widget.LinearLayout;
+
+import com.android.internal.R;
+
+/**
+ * A layout which animates a strip of horizontal, pulsing dots on request. This is used
+ * to indicate the presence of pages to the left / right.
+ */
+public class KeyguardGlowStripView extends LinearLayout {
+    private static final int DURATION = 500;
+
+    private static final float SLIDING_WINDOW_SIZE = 0.4f;
+    private int mDotStripTop;
+    private int mHorizontalDotGap;
+
+    private int mDotSize;
+    private int mNumDots;
+    private Drawable mDotDrawable;
+    private boolean mLeftToRight = true;
+
+    private float mAnimationProgress = 0f;
+    private boolean mDrawDots = false;
+    private ValueAnimator mAnimator;
+    private Interpolator mDotAlphaInterpolator = new DecelerateInterpolator(0.5f);
+
+    public KeyguardGlowStripView(Context context) {
+        this(context, null, 0);
+    }
+
+    public KeyguardGlowStripView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public KeyguardGlowStripView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.KeyguardGlowStripView);
+        mDotSize = a.getDimensionPixelSize(R.styleable.KeyguardGlowStripView_dotSize, mDotSize);
+        mNumDots = a.getInt(R.styleable.KeyguardGlowStripView_numDots, mNumDots);
+        mDotDrawable = a.getDrawable(R.styleable.KeyguardGlowStripView_glowDot);
+        mLeftToRight = a.getBoolean(R.styleable.KeyguardGlowStripView_leftToRight, mLeftToRight);
+    }
+
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        int availableWidth = w - getPaddingLeft() - getPaddingRight();
+        mHorizontalDotGap = (availableWidth - mDotSize * mNumDots) /  (mNumDots - 1);
+        mDotStripTop = getPaddingTop();
+        invalidate();
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+
+        if (!mDrawDots) return;
+
+        int xOffset = getPaddingLeft();
+        mDotDrawable.setBounds(0, 0, mDotSize, mDotSize);
+
+        for (int i = 0; i < mNumDots; i++) {
+            // We fudge the relative position to provide a fade in of the first dot and a fade
+            // out of the final dot.
+            float relativeDotPosition = SLIDING_WINDOW_SIZE / 2 + ((1.0f * i) / (mNumDots - 1)) *
+                    (1 - SLIDING_WINDOW_SIZE);
+            float distance = Math.abs(relativeDotPosition - mAnimationProgress);
+            float alpha = Math.max(0, 1 - distance / (SLIDING_WINDOW_SIZE / 2));
+
+            alpha = mDotAlphaInterpolator.getInterpolation(alpha);
+
+            canvas.save();
+            canvas.translate(xOffset, mDotStripTop);
+            mDotDrawable.setAlpha((int) (alpha * 255));
+            mDotDrawable.draw(canvas);
+            canvas.restore();
+            xOffset += mDotSize + mHorizontalDotGap;
+        }
+    }
+
+    public void makeEmGo() {
+        if (mAnimator != null) {
+            mAnimator.cancel();
+        }
+        float from = mLeftToRight ? 0f : 1f;
+        float to = mLeftToRight ? 1f : 0f;
+        mAnimator = ValueAnimator.ofFloat(from, to);
+        mAnimator.setDuration(DURATION);
+        mAnimator.setInterpolator(new LinearInterpolator());
+        mAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mDrawDots = false;
+                // make sure we draw one frame at the end with everything gone.
+                invalidate();
+            }
+
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mDrawDots = true;
+            }
+        });
+        mAnimator.addUpdateListener(new AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                mAnimationProgress = (Float) animation.getAnimatedValue();
+                invalidate();
+            }
+        });
+        mAnimator.start();
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
new file mode 100644
index 0000000..de19bd5
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -0,0 +1,1515 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.app.AlertDialog;
+import android.app.SearchManager;
+import android.app.admin.DevicePolicyManager;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.os.Looper;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Slog;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.animation.AnimationUtils;
+import android.widget.RemoteViews.OnClickHandler;
+
+import com.android.internal.R;
+import com.android.internal.policy.impl.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.internal.widget.LockPatternUtils;
+
+import java.io.File;
+import java.util.List;
+
+public class KeyguardHostView extends KeyguardViewBase {
+    private static final String TAG = "KeyguardHostView";
+
+    // Use this to debug all of keyguard
+    public static boolean DEBUG = KeyguardViewMediator.DEBUG;
+
+    // Found in KeyguardAppWidgetPickActivity.java
+    static final int APPWIDGET_HOST_ID = 0x4B455947;
+
+    private final int MAX_WIDGETS = 5;
+
+    private AppWidgetHost mAppWidgetHost;
+    private AppWidgetManager mAppWidgetManager;
+    private KeyguardWidgetPager mAppWidgetContainer;
+    private KeyguardSecurityViewFlipper mSecurityViewContainer;
+    private KeyguardSelectorView mKeyguardSelectorView;
+    private KeyguardTransportControlView mTransportControl;
+    private boolean mIsVerifyUnlockOnly;
+    private boolean mEnableFallback; // TODO: This should get the value from KeyguardPatternView
+    private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid;
+    private int mAppWidgetToShow;
+
+    private boolean mCheckAppWidgetConsistencyOnBootCompleted = false;
+
+    protected OnDismissAction mDismissAction;
+
+    protected int mFailedAttempts;
+    private LockPatternUtils mLockPatternUtils;
+
+    private KeyguardSecurityModel mSecurityModel;
+    private KeyguardViewStateManager mViewStateManager;
+
+    boolean mPersitentStickyWidgetLoaded = false;
+
+    private Rect mTempRect = new Rect();
+
+    private int mDisabledFeatures;
+
+    private boolean mCameraDisabled;
+
+    private boolean mSafeModeEnabled;
+
+    /*package*/ interface TransportCallback {
+        void onListenerDetached();
+        void onListenerAttached();
+        void onPlayStateChanged();
+    }
+
+    /*package*/ interface UserSwitcherCallback {
+        void hideSecurityView(int duration);
+        void showSecurityView();
+        void showUnlockHint();
+        void userActivity();
+    }
+
+    /*package*/ interface OnDismissAction {
+        /* returns true if the dismiss should be deferred */
+        boolean onDismiss();
+    }
+
+    public KeyguardHostView(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardHostView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mLockPatternUtils = new LockPatternUtils(context);
+        mAppWidgetHost = new AppWidgetHost(
+                context, APPWIDGET_HOST_ID, mOnClickHandler, Looper.myLooper());
+        mAppWidgetManager = AppWidgetManager.getInstance(mContext);
+        mSecurityModel = new KeyguardSecurityModel(context);
+
+        mViewStateManager = new KeyguardViewStateManager(this);
+
+        DevicePolicyManager dpm =
+            (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+        if (dpm != null) {
+            mDisabledFeatures = getDisabledFeatures(dpm);
+            mCameraDisabled = dpm.getCameraDisabled(null);
+        }
+
+        mSafeModeEnabled = LockPatternUtils.isSafeModeEnabled();
+
+        if (mSafeModeEnabled) {
+            Log.v(TAG, "Keyguard widgets disabled by safe mode");
+        }
+        if ((mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL) != 0) {
+            Log.v(TAG, "Keyguard widgets disabled by DPM");
+        }
+        if ((mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0) {
+            Log.v(TAG, "Keyguard secure camera disabled by DPM");
+        }
+    }
+
+    private KeyguardUpdateMonitorCallback mUpdateMonitorCallbacks =
+            new KeyguardUpdateMonitorCallback() {
+        @Override
+        public void onBootCompleted() {
+            if (mCheckAppWidgetConsistencyOnBootCompleted) {
+                checkAppWidgetConsistency();
+                mSwitchPageRunnable.run();
+                mCheckAppWidgetConsistencyOnBootCompleted = false;
+            }
+        }
+    };
+
+    private SlidingChallengeLayout mSlidingChallengeLayout;
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        boolean result = super.onTouchEvent(ev);
+        mTempRect.set(0, 0, 0, 0);
+        offsetRectIntoDescendantCoords(mSecurityViewContainer, mTempRect);
+        ev.offsetLocation(mTempRect.left, mTempRect.top);
+        result = mSecurityViewContainer.dispatchTouchEvent(ev) || result;
+        ev.offsetLocation(-mTempRect.left, -mTempRect.top);
+        return result;
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+        if (mViewMediatorCallback != null) {
+            mViewMediatorCallback.keyguardDoneDrawing();
+        }
+    }
+
+    private int getWidgetPosition(int id) {
+        final int children = mAppWidgetContainer.getChildCount();
+        for (int i = 0; i < children; i++) {
+            if (mAppWidgetContainer.getWidgetPageAt(i).getContent().getId() == id) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        // Grab instances of and make any necessary changes to the main layouts. Create
+        // view state manager and wire up necessary listeners / callbacks.
+        View deleteDropTarget = findViewById(R.id.keyguard_widget_pager_delete_target);
+        mAppWidgetContainer = (KeyguardWidgetPager) findViewById(R.id.app_widget_container);
+        mAppWidgetContainer.setVisibility(VISIBLE);
+        mAppWidgetContainer.setCallbacks(mWidgetCallbacks);
+        mAppWidgetContainer.setDeleteDropTarget(deleteDropTarget);
+        mAppWidgetContainer.setMinScale(0.5f);
+
+        mSlidingChallengeLayout = (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
+        if (mSlidingChallengeLayout != null) {
+            mSlidingChallengeLayout.setOnChallengeScrolledListener(mViewStateManager);
+        }
+        mAppWidgetContainer.setViewStateManager(mViewStateManager);
+        mAppWidgetContainer.setLockPatternUtils(mLockPatternUtils);
+
+        ChallengeLayout challenge = mSlidingChallengeLayout != null ? mSlidingChallengeLayout :
+            (ChallengeLayout) findViewById(R.id.multi_pane_challenge);
+        challenge.setOnBouncerStateChangedListener(mViewStateManager);
+        mAppWidgetContainer.setBouncerAnimationDuration(challenge.getBouncerAnimationDuration());
+        mViewStateManager.setPagedView(mAppWidgetContainer);
+        mViewStateManager.setChallengeLayout(challenge);
+        mSecurityViewContainer = (KeyguardSecurityViewFlipper) findViewById(R.id.view_flipper);
+        mKeyguardSelectorView = (KeyguardSelectorView) findViewById(R.id.keyguard_selector_view);
+        mViewStateManager.setSecurityViewContainer(mSecurityViewContainer);
+
+        if (!(mContext instanceof Activity)) {
+            setSystemUiVisibility(getSystemUiVisibility() | View.STATUS_BAR_DISABLE_BACK);
+        }
+
+        addDefaultWidgets();
+
+        addWidgetsFromSettings();
+        if (numWidgets() >= MAX_WIDGETS) {
+            setAddWidgetEnabled(false);
+        }
+        checkAppWidgetConsistency();
+        mSwitchPageRunnable.run();
+        // This needs to be called after the pages are all added.
+        mViewStateManager.showUsabilityHints();
+
+        showPrimarySecurityScreen(false);
+        updateSecurityViews();
+    }
+
+    private int getDisabledFeatures(DevicePolicyManager dpm) {
+        int disabledFeatures = DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
+        if (dpm != null) {
+            final int currentUser = mLockPatternUtils.getCurrentUser();
+            disabledFeatures = dpm.getKeyguardDisabledFeatures(null, currentUser);
+        }
+        return disabledFeatures;
+    }
+
+    private boolean widgetsDisabledByDpm() {
+        return (mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL) != 0;
+    }
+
+    private boolean cameraDisabledByDpm() {
+        return mCameraDisabled
+                || (mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0;
+    }
+
+    private void updateSecurityViews() {
+        int children = mSecurityViewContainer.getChildCount();
+        for (int i = 0; i < children; i++) {
+            updateSecurityView(mSecurityViewContainer.getChildAt(i));
+        }
+    }
+
+    private void updateSecurityView(View view) {
+        if (view instanceof KeyguardSecurityView) {
+            KeyguardSecurityView ksv = (KeyguardSecurityView) view;
+            ksv.setKeyguardCallback(mCallback);
+            ksv.setLockPatternUtils(mLockPatternUtils);
+            if (mViewStateManager.isBouncing()) {
+                ksv.showBouncer(0);
+            } else {
+                ksv.hideBouncer(0);
+            }
+        } else {
+            Log.w(TAG, "View " + view + " is not a KeyguardSecurityView");
+        }
+    }
+
+    void setLockPatternUtils(LockPatternUtils utils) {
+        mSecurityModel.setLockPatternUtils(utils);
+        mLockPatternUtils = utils;
+        updateSecurityViews();
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mAppWidgetHost.startListening();
+        KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallbacks);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mAppWidgetHost.stopListening();
+        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallbacks);
+    }
+
+    private AppWidgetHost getAppWidgetHost() {
+        return mAppWidgetHost;
+    }
+
+    void addWidget(AppWidgetHostView view, int pageIndex) {
+        mAppWidgetContainer.addWidget(view, pageIndex);
+    }
+
+    private KeyguardWidgetPager.Callbacks mWidgetCallbacks
+            = new KeyguardWidgetPager.Callbacks() {
+        @Override
+        public void userActivity() {
+            KeyguardHostView.this.userActivity();
+        }
+
+        @Override
+        public void onUserActivityTimeoutChanged() {
+            KeyguardHostView.this.onUserActivityTimeoutChanged();
+        }
+
+        @Override
+        public void onAddView(View v) {
+            if (numWidgets() >= MAX_WIDGETS) {
+                setAddWidgetEnabled(false);
+            }
+        };
+
+        @Override
+        public void onRemoveView(View v) {
+            if (numWidgets() < MAX_WIDGETS) {
+                setAddWidgetEnabled(true);
+            }
+        }
+    };
+
+    public void userActivity() {
+        if (mViewMediatorCallback != null) {
+            mViewMediatorCallback.userActivity();
+        }
+    }
+
+    public void onUserActivityTimeoutChanged() {
+        if (mViewMediatorCallback != null) {
+            mViewMediatorCallback.onUserActivityTimeoutChanged();
+        }
+    }
+
+    @Override
+    public long getUserActivityTimeout() {
+        // Currently only considering user activity timeouts needed by widgets.
+        // Could also take into account longer timeouts for certain security views.
+        if (mAppWidgetContainer != null) {
+            return mAppWidgetContainer.getUserActivityTimeout();
+        }
+        return -1;
+    }
+
+    private KeyguardSecurityCallback mCallback = new KeyguardSecurityCallback() {
+
+        public void userActivity(long timeout) {
+            if (mViewMediatorCallback != null) {
+                mViewMediatorCallback.userActivity(timeout);
+            }
+        }
+
+        public void dismiss(boolean authenticated) {
+            showNextSecurityScreenOrFinish(authenticated);
+        }
+
+        public boolean isVerifyUnlockOnly() {
+            return mIsVerifyUnlockOnly;
+        }
+
+        public void reportSuccessfulUnlockAttempt() {
+            KeyguardUpdateMonitor.getInstance(mContext).clearFailedUnlockAttempts();
+            mLockPatternUtils.reportSuccessfulPasswordAttempt();
+        }
+
+        public void reportFailedUnlockAttempt() {
+            if (mCurrentSecuritySelection == SecurityMode.Biometric) {
+                KeyguardUpdateMonitor.getInstance(mContext).reportFailedBiometricUnlockAttempt();
+            } else {
+                KeyguardHostView.this.reportFailedUnlockAttempt();
+            }
+        }
+
+        public int getFailedAttempts() {
+            return KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts();
+        }
+
+        @Override
+        public void showBackupSecurity() {
+            KeyguardHostView.this.showBackupSecurityScreen();
+        }
+
+        @Override
+        public void setOnDismissAction(OnDismissAction action) {
+            KeyguardHostView.this.setOnDismissAction(action);
+        }
+
+    };
+
+    private void showDialog(String title, String message) {
+        final AlertDialog dialog = new AlertDialog.Builder(mContext)
+            .setTitle(title)
+            .setMessage(message)
+            .setNeutralButton(com.android.internal.R.string.ok, null)
+            .create();
+        if (!(mContext instanceof Activity)) {
+            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+        }
+        dialog.show();
+    }
+
+    private void showTimeoutDialog() {
+        int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
+        int messageId = 0;
+
+        switch (mSecurityModel.getSecurityMode()) {
+            case Pattern:
+                messageId = R.string.kg_too_many_failed_pattern_attempts_dialog_message;
+                break;
+            case PIN:
+                messageId = R.string.kg_too_many_failed_pin_attempts_dialog_message;
+                break;
+            case Password:
+                messageId = R.string.kg_too_many_failed_password_attempts_dialog_message;
+                break;
+        }
+
+        if (messageId != 0) {
+            final String message = mContext.getString(messageId,
+                    KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts(),
+                    timeoutInSeconds);
+            showDialog(null, message);
+        }
+    }
+
+    private void showAlmostAtWipeDialog(int attempts, int remaining) {
+        int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
+        String message = mContext.getString(R.string.kg_failed_attempts_almost_at_wipe,
+                attempts, remaining);
+        showDialog(null, message);
+    }
+
+    private void showWipeDialog(int attempts) {
+        String message = mContext.getString(R.string.kg_failed_attempts_now_wiping, attempts);
+        showDialog(null, message);
+    }
+
+    private void showAlmostAtAccountLoginDialog() {
+        final int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
+        final int count = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
+                - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
+        String message = mContext.getString(R.string.kg_failed_attempts_almost_at_login,
+                count, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, timeoutInSeconds);
+        showDialog(null, message);
+    }
+
+    private void reportFailedUnlockAttempt() {
+        final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
+        final int failedAttempts = monitor.getFailedUnlockAttempts() + 1; // +1 for this time
+
+        if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts);
+
+        SecurityMode mode = mSecurityModel.getSecurityMode();
+        final boolean usingPattern = mode == KeyguardSecurityModel.SecurityMode.Pattern;
+
+        final int failedAttemptsBeforeWipe = mLockPatternUtils.getDevicePolicyManager()
+                .getMaximumFailedPasswordsForWipe(null, mLockPatternUtils.getCurrentUser());
+
+        final int failedAttemptWarning = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
+                - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
+
+        final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ?
+                (failedAttemptsBeforeWipe - failedAttempts)
+                : Integer.MAX_VALUE; // because DPM returns 0 if no restriction
+
+        boolean showTimeout = false;
+        if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {
+            // If we reach this code, it means the user has installed a DevicePolicyManager
+            // that requests device wipe after N attempts.  Once we get below the grace
+            // period, we'll post this dialog every time as a clear warning until the
+            // bombshell hits and the device is wiped.
+            if (remainingBeforeWipe > 0) {
+                showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe);
+            } else {
+                // Too many attempts. The device will be wiped shortly.
+                Slog.i(TAG, "Too many unlock attempts; device will be wiped!");
+                showWipeDialog(failedAttempts);
+            }
+        } else {
+            showTimeout =
+                (failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0;
+            if (usingPattern && mEnableFallback) {
+                if (failedAttempts == failedAttemptWarning) {
+                    showAlmostAtAccountLoginDialog();
+                    showTimeout = false; // don't show both dialogs
+                } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
+                    mLockPatternUtils.setPermanentlyLocked(true);
+                    showSecurityScreen(SecurityMode.Account);
+                    // don't show timeout dialog because we show account unlock screen next
+                    showTimeout = false;
+                }
+            }
+        }
+        monitor.reportFailedUnlockAttempt();
+        mLockPatternUtils.reportFailedPasswordAttempt();
+        if (showTimeout) {
+            showTimeoutDialog();
+        }
+    }
+
+    /**
+     * Shows the primary security screen for the user. This will be either the multi-selector
+     * or the user's security method.
+     * @param turningOff true if the device is being turned off
+     */
+    void showPrimarySecurityScreen(boolean turningOff) {
+        SecurityMode securityMode = mSecurityModel.getSecurityMode();
+        if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
+        if (!turningOff &&
+                KeyguardUpdateMonitor.getInstance(mContext).isAlternateUnlockEnabled()) {
+            // If we're not turning off, then allow biometric alternate.
+            // We'll reload it when the device comes back on.
+            securityMode = mSecurityModel.getAlternateFor(securityMode);
+        }
+        showSecurityScreen(securityMode);
+    }
+
+    /**
+     * Shows the backup security screen for the current security mode.  This could be used for
+     * password recovery screens but is currently only used for pattern unlock to show the
+     * account unlock screen and biometric unlock to show the user's normal unlock.
+     */
+    private void showBackupSecurityScreen() {
+        if (DEBUG) Log.d(TAG, "showBackupSecurity()");
+        SecurityMode backup = mSecurityModel.getBackupSecurityMode(mCurrentSecuritySelection);
+        showSecurityScreen(backup);
+    }
+
+    public boolean showNextSecurityScreenIfPresent() {
+        SecurityMode securityMode = mSecurityModel.getSecurityMode();
+        // Allow an alternate, such as biometric unlock
+        securityMode = mSecurityModel.getAlternateFor(securityMode);
+        if (SecurityMode.None == securityMode) {
+            return false;
+        } else {
+            showSecurityScreen(securityMode); // switch to the alternate security view
+            return true;
+        }
+    }
+
+    private void showNextSecurityScreenOrFinish(boolean authenticated) {
+        if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
+        boolean finish = false;
+        if (SecurityMode.None == mCurrentSecuritySelection) {
+            SecurityMode securityMode = mSecurityModel.getSecurityMode();
+            // Allow an alternate, such as biometric unlock
+            securityMode = mSecurityModel.getAlternateFor(securityMode);
+            if (SecurityMode.None == securityMode) {
+                finish = true; // no security required
+            } else {
+                showSecurityScreen(securityMode); // switch to the alternate security view
+            }
+        } else if (authenticated) {
+            switch (mCurrentSecuritySelection) {
+                case Pattern:
+                case Password:
+                case PIN:
+                case Account:
+                case Biometric:
+                    finish = true;
+                    break;
+
+                case SimPin:
+                case SimPuk:
+                    // Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
+                    SecurityMode securityMode = mSecurityModel.getSecurityMode();
+                    if (securityMode != SecurityMode.None) {
+                        showSecurityScreen(securityMode);
+                    } else {
+                        finish = true;
+                    }
+                    break;
+
+                default:
+                    Log.v(TAG, "Bad security screen " + mCurrentSecuritySelection + ", fail safe");
+                    showPrimarySecurityScreen(false);
+                    break;
+            }
+        } else {
+            showPrimarySecurityScreen(false);
+        }
+        if (finish) {
+            // If the alternate unlock was suppressed, it can now be safely
+            // enabled because the user has left keyguard.
+            KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
+
+            // If there's a pending runnable because the user interacted with a widget
+            // and we're leaving keyguard, then run it.
+            boolean deferKeyguardDone = false;
+            if (mDismissAction != null) {
+                deferKeyguardDone = mDismissAction.onDismiss();
+                mDismissAction = null;
+            }
+            if (mViewMediatorCallback != null) {
+                if (deferKeyguardDone) {
+                    mViewMediatorCallback.keyguardDonePending();
+                } else {
+                    mViewMediatorCallback.keyguardDone(true);
+                }
+            }
+        } else {
+            mViewStateManager.showBouncer(true);
+        }
+    }
+
+    private OnClickHandler mOnClickHandler = new OnClickHandler() {
+        @Override
+        public boolean onClickHandler(final View view,
+                final android.app.PendingIntent pendingIntent,
+                final Intent fillInIntent) {
+            if (pendingIntent.isActivity()) {
+                setOnDismissAction(new OnDismissAction() {
+                    public boolean onDismiss() {
+                        try {
+                              // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
+                              Context context = view.getContext();
+                              ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(view,
+                                      0, 0,
+                                      view.getMeasuredWidth(), view.getMeasuredHeight());
+                              context.startIntentSender(
+                                      pendingIntent.getIntentSender(), fillInIntent,
+                                      Intent.FLAG_ACTIVITY_NEW_TASK,
+                                      Intent.FLAG_ACTIVITY_NEW_TASK, 0, opts.toBundle());
+                        } catch (IntentSender.SendIntentException e) {
+                            android.util.Log.e(TAG, "Cannot send pending intent: ", e);
+                        } catch (Exception e) {
+                            android.util.Log.e(TAG, "Cannot send pending intent due to " +
+                                    "unknown exception: ", e);
+                        }
+                        return false;
+                    }
+                });
+
+                if (mViewStateManager.isChallengeShowing()) {
+                    mViewStateManager.showBouncer(true);
+                } else {
+                    mCallback.dismiss(false);
+                }
+                return true;
+            } else {
+                return super.onClickHandler(view, pendingIntent, fillInIntent);
+            }
+        };
+    };
+
+    // Used to ignore callbacks from methods that are no longer current (e.g. face unlock).
+    // This avoids unwanted asynchronous events from messing with the state.
+    private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {
+
+        @Override
+        public void userActivity(long timeout) {
+        }
+
+        @Override
+        public void showBackupSecurity() {
+        }
+
+        @Override
+        public void setOnDismissAction(OnDismissAction action) {
+        }
+
+        @Override
+        public void reportSuccessfulUnlockAttempt() {
+        }
+
+        @Override
+        public void reportFailedUnlockAttempt() {
+        }
+
+        @Override
+        public boolean isVerifyUnlockOnly() {
+            return false;
+        }
+
+        @Override
+        public int getFailedAttempts() {
+            return 0;
+        }
+
+        @Override
+        public void dismiss(boolean securityVerified) {
+        }
+    };
+
+    protected boolean mShowSecurityWhenReturn;
+
+    @Override
+    public void reset() {
+        mIsVerifyUnlockOnly = false;
+        mAppWidgetContainer.setCurrentPage(getWidgetPosition(R.id.keyguard_status_view));
+    }
+
+    /**
+     * Sets an action to perform when keyguard is dismissed.
+     * @param action
+     */
+    protected void setOnDismissAction(OnDismissAction action) {
+        mDismissAction = action;
+    }
+
+    private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
+        final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
+        KeyguardSecurityView view = null;
+        final int children = mSecurityViewContainer.getChildCount();
+        for (int child = 0; child < children; child++) {
+            if (mSecurityViewContainer.getChildAt(child).getId() == securityViewIdForMode) {
+                view = ((KeyguardSecurityView)mSecurityViewContainer.getChildAt(child));
+                break;
+            }
+        }
+        int layoutId = getLayoutIdFor(securityMode);
+        if (view == null && layoutId != 0) {
+            final LayoutInflater inflater = LayoutInflater.from(mContext);
+            if (DEBUG) Log.v(TAG, "inflating id = " + layoutId);
+            View v = inflater.inflate(layoutId, mSecurityViewContainer, false);
+            mSecurityViewContainer.addView(v);
+            updateSecurityView(v);
+            view = (KeyguardSecurityView)v;
+        }
+
+        if (view instanceof KeyguardSelectorView) {
+            KeyguardSelectorView selectorView = (KeyguardSelectorView) view;
+            View carrierText = selectorView.findViewById(R.id.keyguard_selector_fade_container);
+            selectorView.setCarrierArea(carrierText);
+        }
+
+        return view;
+    }
+
+    /**
+     * Switches to the given security view unless it's already being shown, in which case
+     * this is a no-op.
+     *
+     * @param securityMode
+     */
+    private void showSecurityScreen(SecurityMode securityMode) {
+        if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")");
+
+        if (securityMode == mCurrentSecuritySelection) return;
+
+        KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
+        KeyguardSecurityView newView = getSecurityView(securityMode);
+
+        // Enter full screen mode if we're in SIM or Account screen
+        boolean fullScreenEnabled = getResources().getBoolean(
+                com.android.internal.R.bool.kg_sim_puk_account_full_screen);
+        boolean isSimOrAccount = securityMode == SecurityMode.SimPin
+                || securityMode == SecurityMode.SimPuk
+                || securityMode == SecurityMode.Account;
+        mAppWidgetContainer.setVisibility(
+                isSimOrAccount && fullScreenEnabled ? View.GONE : View.VISIBLE);
+
+        if (mSlidingChallengeLayout != null) {
+            mSlidingChallengeLayout.setChallengeInteractive(!fullScreenEnabled);
+        }
+
+        // Emulate Activity life cycle
+        if (oldView != null) {
+            oldView.onPause();
+            oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view
+        }
+        newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
+        newView.setKeyguardCallback(mCallback);
+
+        final boolean needsInput = newView.needsInput();
+        if (mViewMediatorCallback != null) {
+            mViewMediatorCallback.setNeedsInput(needsInput);
+        }
+
+        // Find and show this child.
+        final int childCount = mSecurityViewContainer.getChildCount();
+
+        mSecurityViewContainer.setInAnimation(
+                AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_fade_in));
+        mSecurityViewContainer.setOutAnimation(
+                AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_fade_out));
+        final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
+        for (int i = 0; i < childCount; i++) {
+            if (mSecurityViewContainer.getChildAt(i).getId() == securityViewIdForMode) {
+                mSecurityViewContainer.setDisplayedChild(i);
+                break;
+            }
+        }
+
+        if (securityMode == SecurityMode.None) {
+            // Discard current runnable if we're switching back to the selector view
+            setOnDismissAction(null);
+        }
+        mCurrentSecuritySelection = securityMode;
+    }
+
+    @Override
+    public void onScreenTurnedOn() {
+        if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
+        showPrimarySecurityScreen(false);
+        getSecurityView(mCurrentSecuritySelection).onResume(KeyguardSecurityView.SCREEN_ON);
+
+        // This is a an attempt to fix bug 7137389 where the device comes back on but the entire
+        // layout is blank but forcing a layout causes it to reappear (e.g. with with
+        // hierarchyviewer).
+        requestLayout();
+
+        if (mViewStateManager != null) {
+            mViewStateManager.showUsabilityHints();
+        }
+    }
+
+    @Override
+    public void onScreenTurnedOff() {
+        if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
+                Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
+        // Once the screen turns off, we no longer consider this to be first boot and we want the
+        // biometric unlock to start next time keyguard is shown.
+        KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
+        // We use mAppWidgetToShow to show a particular widget after you add it-- once the screen
+        // turns off we reset that behavior
+        clearAppWidgetToShow();
+        checkAppWidgetConsistency();
+        showPrimarySecurityScreen(true);
+        getSecurityView(mCurrentSecuritySelection).onPause();
+        CameraWidgetFrame cameraPage = findCameraPage();
+        if (cameraPage != null) {
+            cameraPage.onScreenTurnedOff();
+        }
+    }
+
+    public void clearAppWidgetToShow() {
+        mAppWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
+    }
+
+    @Override
+    public void show() {
+        if (DEBUG) Log.d(TAG, "show()");
+        showPrimarySecurityScreen(false);
+    }
+
+    private boolean isSecure() {
+        SecurityMode mode = mSecurityModel.getSecurityMode();
+        switch (mode) {
+            case Pattern:
+                return mLockPatternUtils.isLockPatternEnabled();
+            case Password:
+            case PIN:
+                return mLockPatternUtils.isLockPasswordEnabled();
+            case SimPin:
+            case SimPuk:
+            case Account:
+                return true;
+            case None:
+                return false;
+            default:
+                throw new IllegalStateException("Unknown security mode " + mode);
+        }
+    }
+
+    @Override
+    public void wakeWhenReadyTq(int keyCode) {
+        if (DEBUG) Log.d(TAG, "onWakeKey");
+        if (keyCode == KeyEvent.KEYCODE_MENU && isSecure()) {
+            if (DEBUG) Log.d(TAG, "switching screens to unlock screen because wake key was MENU");
+            showSecurityScreen(SecurityMode.None);
+        } else {
+            if (DEBUG) Log.d(TAG, "poking wake lock immediately");
+        }
+        if (mViewMediatorCallback != null) {
+            mViewMediatorCallback.wakeUp();
+        }
+    }
+
+    @Override
+    public void verifyUnlock() {
+        SecurityMode securityMode = mSecurityModel.getSecurityMode();
+        if (securityMode == KeyguardSecurityModel.SecurityMode.None) {
+            if (mViewMediatorCallback != null) {
+                mViewMediatorCallback.keyguardDone(true);
+            }
+        } else if (securityMode != KeyguardSecurityModel.SecurityMode.Pattern
+                && securityMode != KeyguardSecurityModel.SecurityMode.PIN
+                && securityMode != KeyguardSecurityModel.SecurityMode.Password) {
+            // can only verify unlock when in pattern/password mode
+            if (mViewMediatorCallback != null) {
+                mViewMediatorCallback.keyguardDone(false);
+            }
+        } else {
+            // otherwise, go to the unlock screen, see if they can verify it
+            mIsVerifyUnlockOnly = true;
+            showSecurityScreen(securityMode);
+        }
+    }
+
+    private int getSecurityViewIdForMode(SecurityMode securityMode) {
+        switch (securityMode) {
+            case None: return R.id.keyguard_selector_view;
+            case Pattern: return R.id.keyguard_pattern_view;
+            case PIN: return R.id.keyguard_pin_view;
+            case Password: return R.id.keyguard_password_view;
+            case Biometric: return R.id.keyguard_face_unlock_view;
+            case Account: return R.id.keyguard_account_view;
+            case SimPin: return R.id.keyguard_sim_pin_view;
+            case SimPuk: return R.id.keyguard_sim_puk_view;
+        }
+        return 0;
+    }
+
+    private int getLayoutIdFor(SecurityMode securityMode) {
+        switch (securityMode) {
+            case None: return R.layout.keyguard_selector_view;
+            case Pattern: return R.layout.keyguard_pattern_view;
+            case PIN: return R.layout.keyguard_pin_view;
+            case Password: return R.layout.keyguard_password_view;
+            case Biometric: return R.layout.keyguard_face_unlock_view;
+            case Account: return R.layout.keyguard_account_view;
+            case SimPin: return R.layout.keyguard_sim_pin_view;
+            case SimPuk: return R.layout.keyguard_sim_puk_view;
+            default:
+                return 0;
+        }
+    }
+
+    private boolean addWidget(int appId, int pageIndex, boolean updateDbIfFailed) {
+        AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appId);
+        if (appWidgetInfo != null) {
+            AppWidgetHostView view = getAppWidgetHost().createView(mContext, appId, appWidgetInfo);
+            addWidget(view, pageIndex);
+            return true;
+        } else {
+            if (updateDbIfFailed) {
+                Log.w(TAG, "AppWidgetInfo for app widget id " + appId + " was null, deleting");
+                mAppWidgetHost.deleteAppWidgetId(appId);
+                mLockPatternUtils.removeAppWidget(appId);
+            }
+            return false;
+        }
+    }
+
+    private final CameraWidgetFrame.Callbacks mCameraWidgetCallbacks =
+        new CameraWidgetFrame.Callbacks() {
+            @Override
+            public void onLaunchingCamera() {
+                setSliderHandleAlpha(0);
+            }
+
+            @Override
+            public void onCameraLaunchedSuccessfully() {
+                if (mAppWidgetContainer.isCameraPage(mAppWidgetContainer.getCurrentPage())) {
+                    mAppWidgetContainer.scrollLeft();
+                }
+                setSliderHandleAlpha(1);
+                mShowSecurityWhenReturn = true;
+            }
+
+            @Override
+            public void onCameraLaunchedUnsuccessfully() {
+                setSliderHandleAlpha(1);
+            }
+
+            private void setSliderHandleAlpha(float alpha) {
+                SlidingChallengeLayout slider =
+                        (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
+                if (slider != null) {
+                    slider.setHandleAlpha(alpha);
+                }
+            }
+        };
+
+    private final KeyguardActivityLauncher mActivityLauncher = new KeyguardActivityLauncher() {
+        @Override
+        Context getContext() {
+            return mContext;
+        }
+
+        @Override
+        KeyguardSecurityCallback getCallback() {
+            return mCallback;
+        }
+
+        @Override
+        LockPatternUtils getLockPatternUtils() {
+            return mLockPatternUtils;
+        }
+    };
+
+    private int numWidgets() {
+        final int childCount = mAppWidgetContainer.getChildCount();
+        int widgetCount = 0;
+        for (int i = 0; i < childCount; i++) {
+            if (mAppWidgetContainer.isWidgetPage(i)) {
+                widgetCount++;
+            }
+        }
+        return widgetCount;
+    }
+
+
+    private void setAddWidgetEnabled(boolean clickable) {
+        View addWidget = mAppWidgetContainer.findViewById(R.id.keyguard_add_widget);
+        if (addWidget != null) {
+            View addWidgetButton = addWidget.findViewById(R.id.keyguard_add_widget_view);
+            addWidgetButton.setEnabled(clickable);
+        }
+    }
+
+    private void addDefaultWidgets() {
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        inflater.inflate(R.layout.keyguard_transport_control_view, this, true);
+
+        if (!mSafeModeEnabled && !widgetsDisabledByDpm()) {
+            View addWidget = inflater.inflate(R.layout.keyguard_add_widget, this, false);
+            mAppWidgetContainer.addWidget(addWidget, 0);
+            View addWidgetButton = addWidget.findViewById(R.id.keyguard_add_widget_view);
+            addWidgetButton.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    // Pass in an invalid widget id... the picker will allocate an ID for us
+                    mActivityLauncher.launchWidgetPicker(AppWidgetManager.INVALID_APPWIDGET_ID);
+                }
+            });
+        }
+
+        // We currently disable cameras in safe mode because we support loading 3rd party
+        // cameras we can't trust.  TODO: plumb safe mode into camera creation code and only
+        // inflate system-provided camera?
+        if (!mSafeModeEnabled && !cameraDisabledByDpm()
+                && mContext.getResources().getBoolean(R.bool.kg_enable_camera_default_widget)) {
+            View cameraWidget =
+                    CameraWidgetFrame.create(mContext, mCameraWidgetCallbacks, mActivityLauncher);
+            if (cameraWidget != null) {
+                mAppWidgetContainer.addWidget(cameraWidget);
+            }
+        }
+
+        enableUserSelectorIfNecessary();
+        initializeTransportControl();
+    }
+
+    private boolean removeTransportFromWidgetPager() {
+        int page = getWidgetPosition(R.id.keyguard_transport_control);
+        if (page != -1) {
+            mAppWidgetContainer.removeWidget(mTransportControl);
+
+            // XXX keep view attached so we still get show/hide events from AudioManager
+            KeyguardHostView.this.addView(mTransportControl);
+            mTransportControl.setVisibility(View.GONE);
+            mViewStateManager.setTransportState(KeyguardViewStateManager.TRANSPORT_GONE);
+            return true;
+        }
+        return false;
+    }
+
+    private void addTransportToWidgetPager() {
+        if (getWidgetPosition(R.id.keyguard_transport_control) == -1) {
+            KeyguardHostView.this.removeView(mTransportControl);
+            // insert to left of camera if it exists, otherwise after right-most widget
+            int lastWidget = mAppWidgetContainer.getChildCount() - 1;
+            int position = 0; // handle no widget case
+            if (lastWidget >= 0) {
+                position = mAppWidgetContainer.isCameraPage(lastWidget) ?
+                        lastWidget : lastWidget + 1;
+            }
+            mAppWidgetContainer.addWidget(mTransportControl, position);
+            mTransportControl.setVisibility(View.VISIBLE);
+        }
+    }
+
+    private void initializeTransportControl() {
+        mTransportControl =
+            (KeyguardTransportControlView) findViewById(R.id.keyguard_transport_control);
+        mTransportControl.setVisibility(View.GONE);
+
+        // This code manages showing/hiding the transport control. We keep it around and only
+        // add it to the hierarchy if it needs to be present.
+        if (mTransportControl != null) {
+            mTransportControl.setKeyguardCallback(new TransportCallback() {
+                @Override
+                public void onListenerDetached() {
+                    if (removeTransportFromWidgetPager()) {
+                        mTransportControl.post(mSwitchPageRunnable);
+                    }
+                }
+
+                @Override
+                public void onListenerAttached() {
+                    // Transport will be added when playstate changes...
+                    mTransportControl.post(mSwitchPageRunnable);
+                }
+
+                @Override
+                public void onPlayStateChanged() {
+                    mTransportControl.post(mSwitchPageRunnable);
+                }
+            });
+        }
+    }
+
+    private int getInsertPageIndex() {
+        View addWidget = mAppWidgetContainer.findViewById(R.id.keyguard_add_widget);
+        int insertionIndex = mAppWidgetContainer.indexOfChild(addWidget);
+        if (insertionIndex < 0) {
+            insertionIndex = 0; // no add widget page found
+        } else {
+            insertionIndex++; // place after add widget
+        }
+        return insertionIndex;
+    }
+
+    private void addDefaultStatusWidget(int index) {
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        View statusWidget = inflater.inflate(R.layout.keyguard_status_view, null, true);
+        mAppWidgetContainer.addWidget(statusWidget, index);
+    }
+
+    private void addWidgetsFromSettings() {
+        if (mSafeModeEnabled || widgetsDisabledByDpm()) {
+            return;
+        }
+
+        int insertionIndex = getInsertPageIndex();
+
+        // Add user-selected widget
+        final int[] widgets = mLockPatternUtils.getAppWidgets();
+
+        if (widgets == null) {
+            Log.d(TAG, "Problem reading widgets");
+        } else {
+            for (int i = widgets.length -1; i >= 0; i--) {
+                if (widgets[i] == LockPatternUtils.ID_DEFAULT_STATUS_WIDGET) {
+                    addDefaultStatusWidget(insertionIndex);
+                } else {
+                    // We add the widgets from left to right, starting after the first page after
+                    // the add page. We count down, since the order will be persisted from right
+                    // to left, starting after camera.
+                    addWidget(widgets[i], insertionIndex, true);
+                }
+            }
+        }
+    }
+
+    private int allocateIdForDefaultAppWidget() {
+        int appWidgetId;
+        Resources res = getContext().getResources();
+        ComponentName defaultAppWidget = new ComponentName(
+                res.getString(R.string.widget_default_package_name),
+                res.getString(R.string.widget_default_class_name));
+
+        // Note: we don't support configuring the widget
+        appWidgetId = mAppWidgetHost.allocateAppWidgetId();
+
+        try {
+            mAppWidgetManager.bindAppWidgetId(appWidgetId, defaultAppWidget);
+
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "Error when trying to bind default AppWidget: " + e);
+            mAppWidgetHost.deleteAppWidgetId(appWidgetId);
+            appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
+        }
+        return appWidgetId;
+    }
+    public void checkAppWidgetConsistency() {
+        // Since this method may bind a widget (which we can't do until boot completed) we
+        // may have to defer it until after boot complete.
+        if (!KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
+            mCheckAppWidgetConsistencyOnBootCompleted = true;
+            return;
+        }
+        final int childCount = mAppWidgetContainer.getChildCount();
+        boolean widgetPageExists = false;
+        for (int i = 0; i < childCount; i++) {
+            if (mAppWidgetContainer.isWidgetPage(i)) {
+                widgetPageExists = true;
+                break;
+            }
+        }
+        if (!widgetPageExists) {
+            final int insertPageIndex = getInsertPageIndex();
+
+            final boolean userAddedWidgetsEnabled = !widgetsDisabledByDpm();
+            boolean addedDefaultAppWidget = false;
+
+            if (!mSafeModeEnabled) {
+                if (userAddedWidgetsEnabled) {
+                    int appWidgetId = allocateIdForDefaultAppWidget();
+                    if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
+                        addedDefaultAppWidget = addWidget(appWidgetId, insertPageIndex, true);
+                    }
+                } else {
+                    // note: even if widgetsDisabledByDpm() returns true, we still bind/create
+                    // the default appwidget if possible
+                    int appWidgetId = mLockPatternUtils.getFallbackAppWidgetId();
+                    if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
+                        appWidgetId = allocateIdForDefaultAppWidget();
+                        if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
+                            mLockPatternUtils.writeFallbackAppWidgetId(appWidgetId);
+                        }
+                    }
+                    if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
+                        addedDefaultAppWidget = addWidget(appWidgetId, insertPageIndex, false);
+                        if (!addedDefaultAppWidget) {
+                            mAppWidgetHost.deleteAppWidgetId(appWidgetId);
+                            mLockPatternUtils.writeFallbackAppWidgetId(
+                                    AppWidgetManager.INVALID_APPWIDGET_ID);
+                        }
+                    }
+                }
+            }
+
+            // Use the built-in status/clock view if we can't inflate the default widget
+            if (!addedDefaultAppWidget) {
+                addDefaultStatusWidget(insertPageIndex);
+            }
+
+            // trigger DB updates only if user-added widgets are enabled
+            if (!mSafeModeEnabled && userAddedWidgetsEnabled) {
+                mAppWidgetContainer.onAddView(
+                        mAppWidgetContainer.getChildAt(insertPageIndex), insertPageIndex);
+            }
+        }
+    }
+
+    Runnable mSwitchPageRunnable = new Runnable() {
+        @Override
+        public void run() {
+           showAppropriateWidgetPage();
+        }
+    };
+
+    static class SavedState extends BaseSavedState {
+        int transportState;
+        int appWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
+
+        SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        private SavedState(Parcel in) {
+            super(in);
+            this.transportState = in.readInt();
+            this.appWidgetToShow = in.readInt();
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            super.writeToParcel(out, flags);
+            out.writeInt(this.transportState);
+            out.writeInt(this.appWidgetToShow);
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR
+                = new Parcelable.Creator<SavedState>() {
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+
+    @Override
+    public Parcelable onSaveInstanceState() {
+        if (DEBUG) Log.d(TAG, "onSaveInstanceState");
+        Parcelable superState = super.onSaveInstanceState();
+        SavedState ss = new SavedState(superState);
+        ss.transportState = mViewStateManager.getTransportState();
+        ss.appWidgetToShow = mAppWidgetToShow;
+        return ss;
+    }
+
+    @Override
+    public void onRestoreInstanceState(Parcelable state) {
+        if (DEBUG) Log.d(TAG, "onRestoreInstanceState");
+        if (!(state instanceof SavedState)) {
+            super.onRestoreInstanceState(state);
+            return;
+        }
+        SavedState ss = (SavedState) state;
+        super.onRestoreInstanceState(ss.getSuperState());
+        mViewStateManager.setTransportState(ss.transportState);
+        mAppWidgetToShow = ss.appWidgetToShow;
+        post(mSwitchPageRunnable);
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        super.onWindowFocusChanged(hasWindowFocus);
+        if (DEBUG) Log.d(TAG, "Window is " + (hasWindowFocus ? "focused" : "unfocused"));
+        if (hasWindowFocus && mShowSecurityWhenReturn) {
+            SlidingChallengeLayout slider =
+                (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
+            if (slider != null) {
+                slider.setHandleAlpha(1);
+                slider.showChallenge(true);
+            }
+            mShowSecurityWhenReturn = false;
+        }
+    }
+
+    private void showAppropriateWidgetPage() {
+        int state = mViewStateManager.getTransportState();
+        boolean isMusicPlaying = mTransportControl.isMusicPlaying()
+                || state == KeyguardViewStateManager.TRANSPORT_VISIBLE;
+        if (isMusicPlaying) {
+            mViewStateManager.setTransportState(KeyguardViewStateManager.TRANSPORT_VISIBLE);
+            addTransportToWidgetPager();
+        } else if (state == KeyguardViewStateManager.TRANSPORT_VISIBLE) {
+            mViewStateManager.setTransportState(KeyguardViewStateManager.TRANSPORT_INVISIBLE);
+        }
+        int pageToShow = getAppropriateWidgetPage(isMusicPlaying);
+        mAppWidgetContainer.setCurrentPage(pageToShow);
+    }
+
+    private CameraWidgetFrame findCameraPage() {
+        for (int i = mAppWidgetContainer.getChildCount() - 1; i >= 0; i--) {
+            if (mAppWidgetContainer.isCameraPage(i)) {
+                return (CameraWidgetFrame) mAppWidgetContainer.getChildAt(i);
+            }
+        }
+        return null;
+    }
+
+    boolean isMusicPage(int pageIndex) {
+        return pageIndex >= 0 && pageIndex == getWidgetPosition(R.id.keyguard_transport_control);
+    }
+
+    private int getAppropriateWidgetPage(boolean isMusicPlaying) {
+        // assumes at least one widget (besides camera + add)
+        if (mAppWidgetToShow != AppWidgetManager.INVALID_APPWIDGET_ID) {
+            final int childCount = mAppWidgetContainer.getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                if (mAppWidgetContainer.getWidgetPageAt(i).getContentAppWidgetId()
+                        == mAppWidgetToShow) {
+                    return i;
+                }
+            }
+            mAppWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
+        }
+        // if music playing, show transport
+        if (isMusicPlaying) {
+            if (DEBUG) Log.d(TAG, "Music playing, show transport");
+            return mAppWidgetContainer.getWidgetPageIndex(mTransportControl);
+        }
+
+        // else show the right-most widget (except for camera)
+        int rightMost = mAppWidgetContainer.getChildCount() - 1;
+        if (mAppWidgetContainer.isCameraPage(rightMost)) {
+            rightMost--;
+        }
+        if (DEBUG) Log.d(TAG, "Show right-most page " + rightMost);
+        return rightMost;
+    }
+
+    private void enableUserSelectorIfNecessary() {
+        if (!UserManager.supportsMultipleUsers()) {
+            return; // device doesn't support multi-user mode
+        }
+        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        if (um == null) {
+            Throwable t = new Throwable();
+            t.fillInStackTrace();
+            Log.e(TAG, "user service is null.", t);
+            return;
+        }
+
+        // if there are multiple users, we need to enable to multi-user switcher
+        final List<UserInfo> users = um.getUsers(true);
+        if (users == null) {
+            Throwable t = new Throwable();
+            t.fillInStackTrace();
+            Log.e(TAG, "list of users is null.", t);
+            return;
+        }
+
+        final View multiUserView = findViewById(R.id.keyguard_user_selector);
+        if (multiUserView == null) {
+            Throwable t = new Throwable();
+            t.fillInStackTrace();
+            Log.e(TAG, "can't find user_selector in layout.", t);
+            return;
+        }
+
+        if (users.size() > 1) {
+            if (multiUserView instanceof KeyguardMultiUserSelectorView) {
+                KeyguardMultiUserSelectorView multiUser =
+                        (KeyguardMultiUserSelectorView) multiUserView;
+                multiUser.setVisibility(View.VISIBLE);
+                multiUser.addUsers(users);
+                UserSwitcherCallback callback = new UserSwitcherCallback() {
+                    @Override
+                    public void hideSecurityView(int duration) {
+                        mSecurityViewContainer.animate().alpha(0).setDuration(duration);
+                    }
+
+                    @Override
+                    public void showSecurityView() {
+                        mSecurityViewContainer.setAlpha(1.0f);
+                    }
+
+                    @Override
+                    public void showUnlockHint() {
+                        if (mKeyguardSelectorView != null) {
+                            mKeyguardSelectorView.showUsabilityHint();
+                        }
+                    }
+
+                    @Override
+                    public void userActivity() {
+                        if (mViewMediatorCallback != null) {
+                            mViewMediatorCallback.userActivity();
+                        }
+                    }
+                };
+                multiUser.setCallback(callback);
+            } else {
+                Throwable t = new Throwable();
+                t.fillInStackTrace();
+                if (multiUserView == null) {
+                    Log.e(TAG, "could not find the user_selector.", t);
+                } else {
+                    Log.e(TAG, "user_selector is the wrong type.", t);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void cleanUp() {
+
+    }
+
+    /**
+     * In general, we enable unlocking the insecure keyguard with the menu key. However, there are
+     * some cases where we wish to disable it, notably when the menu button placement or technology
+     * is prone to false positives.
+     *
+     * @return true if the menu key should be enabled
+     */
+    private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
+    private boolean shouldEnableMenuKey() {
+        final Resources res = getResources();
+        final boolean configDisabled = res.getBoolean(
+                com.android.internal.R.bool.config_disableMenuKeyInLockScreen);
+        final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
+        final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
+        return !configDisabled || isTestHarness || fileOverride;
+    }
+
+
+
+    public void goToUserSwitcher() {
+        mAppWidgetContainer.setCurrentPage(getWidgetPosition(R.id.keyguard_multi_user_selector));
+    }
+
+    public void goToWidget(int appWidgetId) {
+        mAppWidgetToShow = appWidgetId;
+        mSwitchPageRunnable.run();
+    }
+
+    public boolean handleMenuKey() {
+        // The following enables the MENU key to work for testing automation
+        if (shouldEnableMenuKey()) {
+            showNextSecurityScreenOrFinish(false);
+            return true;
+        }
+        return false;
+    }
+
+    public boolean handleBackKey() {
+        if (mCurrentSecuritySelection != SecurityMode.None) {
+            mCallback.dismiss(false);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     *  Dismisses the keyguard by going to the next screen or making it gone.
+     */
+    public void dismiss() {
+        showNextSecurityScreenOrFinish(false);
+    }
+
+    public void showAssistant() {
+        final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+          .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+
+        if (intent == null) return;
+
+        final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
+                R.anim.keyguard_action_assist_enter, R.anim.keyguard_action_assist_exit,
+                getHandler(), null);
+
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        mActivityLauncher.launchActivityWithAnimation(
+                intent, false, opts.toBundle(), null, null);
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardLinearLayout.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardLinearLayout.java
new file mode 100644
index 0000000..0fc54cd
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardLinearLayout.java
@@ -0,0 +1,46 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+
+/**
+ * A layout that arranges its children into a special type of grid.
+ */
+public class KeyguardLinearLayout extends LinearLayout {
+    int mTopChild = 0;
+
+    public KeyguardLinearLayout(Context context) {
+        this(context, null, 0);
+    }
+
+    public KeyguardLinearLayout(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public KeyguardLinearLayout(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public void setTopChild(View child) {
+        int top = indexOfChild(child);
+        mTopChild = top;
+        invalidate();
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java
new file mode 100644
index 0000000..ee5c4a6
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java
@@ -0,0 +1,272 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TextView;
+
+import libcore.util.MutableInt;
+
+import com.android.internal.R;
+
+/***
+ * Manages a number of views inside of the given layout. See below for a list of widgets.
+ */
+class KeyguardMessageArea extends TextView {
+    static final int CHARGING_ICON = 0; //R.drawable.ic_lock_idle_charging;
+    static final int BATTERY_LOW_ICON = 0; //R.drawable.ic_lock_idle_low_battery;
+
+    static final int SECURITY_MESSAGE_DURATION = 5000;
+    protected static final int FADE_DURATION = 750;
+
+    // are we showing battery information?
+    boolean mShowingBatteryInfo = false;
+
+    // is the bouncer up?
+    boolean mShowingBouncer = false;
+
+    // last known plugged in state
+    boolean mPluggedIn = false;
+
+    // last known battery level
+    int mBatteryLevel = 100;
+
+    KeyguardUpdateMonitor mUpdateMonitor;
+
+    // Timeout before we reset the message to show charging/owner info
+    long mTimeout = SECURITY_MESSAGE_DURATION;
+
+    // Shadowed text values
+    protected boolean mBatteryCharged;
+    protected boolean mBatteryIsLow;
+
+    private Handler mHandler;
+
+    CharSequence mMessage;
+    boolean mShowingMessage;
+    Runnable mClearMessageRunnable = new Runnable() {
+        @Override
+        public void run() {
+            mMessage = null;
+            mShowingMessage = false;
+            if (mShowingBouncer) {
+                hideMessage(FADE_DURATION, true);
+            } else {
+                update();
+            }
+        }
+    };
+
+    public static class Helper implements SecurityMessageDisplay {
+        KeyguardMessageArea mMessageArea;
+        Helper(View v) {
+            mMessageArea = (KeyguardMessageArea) v.findViewById(R.id.keyguard_message_area);
+            if (mMessageArea == null) {
+                throw new RuntimeException("Can't find keyguard_message_area in " + v.getClass());
+            }
+        }
+
+        public void setMessage(CharSequence msg, boolean important) {
+            if (!TextUtils.isEmpty(msg) && important) {
+                mMessageArea.mMessage = msg;
+                mMessageArea.securityMessageChanged();
+            }
+        }
+
+        public void setMessage(int resId, boolean important) {
+            if (resId != 0 && important) {
+                mMessageArea.mMessage = mMessageArea.getContext().getResources().getText(resId);
+                mMessageArea.securityMessageChanged();
+            }
+        }
+
+        public void setMessage(int resId, boolean important, Object... formatArgs) {
+            if (resId != 0 && important) {
+                mMessageArea.mMessage = mMessageArea.getContext().getString(resId, formatArgs);
+                mMessageArea.securityMessageChanged();
+            }
+        }
+
+        @Override
+        public void showBouncer(int duration) {
+            mMessageArea.hideMessage(duration, false);
+            mMessageArea.mShowingBouncer = true;
+        }
+
+        @Override
+        public void hideBouncer(int duration) {
+            mMessageArea.showMessage(duration);
+            mMessageArea.mShowingBouncer = false;
+        }
+
+        @Override
+        public void setTimeout(int timeoutMs) {
+            mMessageArea.mTimeout = timeoutMs;
+        }
+    }
+
+    private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
+        @Override
+        public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) {
+            mShowingBatteryInfo = status.isPluggedIn() || status.isBatteryLow();
+            mPluggedIn = status.isPluggedIn();
+            mBatteryLevel = status.level;
+            mBatteryCharged = status.isCharged();
+            mBatteryIsLow = status.isBatteryLow();
+            update();
+        }
+    };
+
+    private CharSequence mSeparator;
+
+    public KeyguardMessageArea(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardMessageArea(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        // This is required to ensure marquee works
+        setSelected(true);
+
+        // Registering this callback immediately updates the battery state, among other things.
+        mUpdateMonitor = KeyguardUpdateMonitor.getInstance(getContext());
+        mUpdateMonitor.registerCallback(mInfoCallback);
+        mHandler = new Handler(Looper.myLooper());
+
+        mSeparator = getResources().getString(R.string.kg_text_message_separator);
+
+        update();
+    }
+
+    public void securityMessageChanged() {
+        setAlpha(1f);
+        mShowingMessage = true;
+        update();
+        mHandler.removeCallbacks(mClearMessageRunnable);
+        if (mTimeout > 0) {
+            mHandler.postDelayed(mClearMessageRunnable, mTimeout);
+        }
+        announceForAccessibility(getText());
+    }
+
+    /**
+     * Update the status lines based on these rules:
+     * AlarmStatus: Alarm state always gets it's own line.
+     * Status1 is shared between help, battery status and generic unlock instructions,
+     * prioritized in that order.
+     * @param showStatusLines status lines are shown if true
+     */
+    void update() {
+        MutableInt icon = new MutableInt(0);
+        CharSequence status = concat(getChargeInfo(icon), getOwnerInfo(), getCurrentMessage());
+        setCompoundDrawablesWithIntrinsicBounds(icon.value, 0, 0, 0);
+        setText(status);
+    }
+
+    private CharSequence concat(CharSequence... args) {
+        StringBuilder b = new StringBuilder();
+        if (!TextUtils.isEmpty(args[0])) {
+            b.append(args[0]);
+        }
+        for (int i = 1; i < args.length; i++) {
+            CharSequence text = args[i];
+            if (!TextUtils.isEmpty(text)) {
+                if (b.length() > 0) {
+                    b.append(mSeparator);
+                }
+                b.append(text);
+            }
+        }
+        return b.toString();
+    }
+
+    CharSequence getCurrentMessage() {
+        return mShowingMessage ? mMessage : null;
+    }
+
+    String getOwnerInfo() {
+        ContentResolver res = getContext().getContentResolver();
+        final boolean ownerInfoEnabled = Settings.Secure.getIntForUser(res,
+                Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
+        return ownerInfoEnabled && !mShowingMessage ?
+                Settings.Secure.getStringForUser(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO,
+                        UserHandle.USER_CURRENT) : null;
+    }
+
+    private CharSequence getChargeInfo(MutableInt icon) {
+        CharSequence string = null;
+        if (mShowingBatteryInfo && !mShowingMessage) {
+            // Battery status
+            if (mPluggedIn) {
+                // Charging, charged or waiting to charge.
+                string = getContext().getString(mBatteryCharged ?
+                        com.android.internal.R.string.lockscreen_charged
+                        :com.android.internal.R.string.lockscreen_plugged_in, mBatteryLevel);
+                icon.value = CHARGING_ICON;
+            } else if (mBatteryIsLow) {
+                // Battery is low
+                string = getContext().getString(
+                        com.android.internal.R.string.lockscreen_low_battery);
+                icon.value = BATTERY_LOW_ICON;
+            }
+        }
+        return string;
+    }
+
+    private void hideMessage(int duration, boolean thenUpdate) {
+        if (duration > 0) {
+            Animator anim = ObjectAnimator.ofFloat(this, "alpha", 0f);
+            anim.setDuration(duration);
+            if (thenUpdate) {
+                anim.addListener(new AnimatorListenerAdapter() {
+                        @Override
+                            public void onAnimationEnd(Animator animation) {
+                            update();
+                        }
+                });
+            }
+            anim.start();
+        } else {
+            setAlpha(0f);
+            if (thenUpdate) {
+                update();
+            }
+        }
+    }
+
+    private void showMessage(int duration) {
+        if (duration > 0) {
+            Animator anim = ObjectAnimator.ofFloat(this, "alpha", 1f);
+            anim.setDuration(duration);
+            anim.start();
+        } else {
+            setAlpha(1f);
+        }
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserAvatar.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserAvatar.java
new file mode 100644
index 0000000..7bf2bf9
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserAvatar.java
@@ -0,0 +1,225 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.internal.R;
+
+class KeyguardMultiUserAvatar extends FrameLayout {
+    private static final String TAG = KeyguardMultiUserAvatar.class.getSimpleName();
+    private static final boolean DEBUG = KeyguardHostView.DEBUG;
+
+    private ImageView mUserImage;
+    private TextView mUserName;
+    private UserInfo mUserInfo;
+    private static final float ACTIVE_ALPHA = 1.0f;
+    private static final float INACTIVE_ALPHA = 1.0f;
+    private static final float ACTIVE_SCALE = 1.5f;
+    private static final float ACTIVE_TEXT_ALPHA = 0f;
+    private static final float INACTIVE_TEXT_ALPHA = 0.5f;
+    private static final int SWITCH_ANIMATION_DURATION = 150;
+
+    private final float mActiveAlpha;
+    private final float mActiveScale;
+    private final float mActiveTextAlpha;
+    private final float mInactiveAlpha;
+    private final float mInactiveTextAlpha;
+    private final float mShadowRadius;
+    private final float mStroke;
+    private final float mIconSize;
+    private final int mFrameColor;
+    private final int mFrameShadowColor;
+    private final int mTextColor;
+    private final int mHighlightColor;
+
+    private boolean mTouched;
+
+    private boolean mActive;
+    private boolean mInit = true;
+    private KeyguardMultiUserSelectorView mUserSelector;
+    private KeyguardCircleFramedDrawable mFramed;
+
+    public static KeyguardMultiUserAvatar fromXml(int resId, Context context,
+            KeyguardMultiUserSelectorView userSelector, UserInfo info) {
+        KeyguardMultiUserAvatar icon = (KeyguardMultiUserAvatar)
+                LayoutInflater.from(context).inflate(resId, userSelector, false);
+
+        icon.init(info, userSelector);
+        return icon;
+    }
+
+    public KeyguardMultiUserAvatar(Context context) {
+        this(context, null, 0);
+    }
+
+    public KeyguardMultiUserAvatar(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public KeyguardMultiUserAvatar(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        Resources res = mContext.getResources();
+        mTextColor = res.getColor(R.color.keyguard_avatar_nick_color);
+        mIconSize = res.getDimension(R.dimen.keyguard_avatar_size);
+        mStroke = res.getDimension(R.dimen.keyguard_avatar_frame_stroke_width);
+        mShadowRadius = res.getDimension(R.dimen.keyguard_avatar_frame_shadow_radius);
+        mFrameColor = res.getColor(R.color.keyguard_avatar_frame_color);
+        mFrameShadowColor = res.getColor(R.color.keyguard_avatar_frame_shadow_color);
+        mHighlightColor = res.getColor(R.color.keyguard_avatar_frame_pressed_color);
+        mActiveTextAlpha = ACTIVE_TEXT_ALPHA;
+        mInactiveTextAlpha = INACTIVE_TEXT_ALPHA;
+        mActiveScale = ACTIVE_SCALE;
+        mActiveAlpha = ACTIVE_ALPHA;
+        mInactiveAlpha = INACTIVE_ALPHA;
+
+        mTouched = false;
+
+        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+    }
+
+    protected String rewriteIconPath(String path) {
+        if (!this.getClass().getName().contains("internal")) {
+            return path.replace("system", "data");
+        }
+        return path;
+    }
+
+    public void init(UserInfo user, KeyguardMultiUserSelectorView userSelector) {
+        mUserInfo = user;
+        mUserSelector = userSelector;
+
+        mUserImage = (ImageView) findViewById(R.id.keyguard_user_avatar);
+        mUserName = (TextView) findViewById(R.id.keyguard_user_name);
+
+        Bitmap icon = null; 
+        try {
+            icon = BitmapFactory.decodeFile(rewriteIconPath(user.iconPath));
+        } catch (Exception e) {
+            if (DEBUG) Log.d(TAG, "failed to open profile icon " + user.iconPath, e);
+        }
+
+        if (icon == null) {
+            icon = BitmapFactory.decodeResource(mContext.getResources(),
+                    com.android.internal.R.drawable.ic_contact_picture);
+        }
+
+        mFramed = new KeyguardCircleFramedDrawable(icon, (int) mIconSize, mFrameColor, mStroke,
+                mFrameShadowColor, mShadowRadius, mHighlightColor);
+        mUserImage.setImageDrawable(mFramed);
+        mUserName.setText(mUserInfo.name);
+        setOnClickListener(mUserSelector);
+        mInit = false;
+    }
+
+    public void setActive(boolean active, boolean animate, final Runnable onComplete) {
+        if (mActive != active || mInit) {
+            mActive = active;
+
+            if (active) {
+                KeyguardLinearLayout parent = (KeyguardLinearLayout) getParent();
+                parent.setTopChild(this);
+                // TODO: Create an appropriate asset when string changes are possible.
+                setContentDescription(mUserName.getText()
+                        + ". " + mContext.getString(R.string.user_switched, ""));
+            } else {
+                setContentDescription(mUserName.getText());
+            }
+        }
+        updateVisualsForActive(mActive, animate, SWITCH_ANIMATION_DURATION, onComplete);
+    }
+
+    void updateVisualsForActive(boolean active, boolean animate, int duration,
+            final Runnable onComplete) {
+        final float finalAlpha = active ? mActiveAlpha : mInactiveAlpha;
+        final float initAlpha = active ? mInactiveAlpha : mActiveAlpha;
+        final float finalScale = active ? 1f : 1f / mActiveScale;
+        final float initScale = mFramed.getScale();
+        final int finalTextAlpha = active ? (int) (mActiveTextAlpha * 255) :
+                (int) (mInactiveTextAlpha * 255);
+        final int initTextAlpha = active ? (int) (mInactiveTextAlpha * 255) :
+                (int) (mActiveTextAlpha * 255);
+        int textColor = mTextColor;
+        mUserName.setTextColor(textColor);
+
+        if (animate && mTouched) {
+            ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
+            va.addUpdateListener(new AnimatorUpdateListener() {
+                @Override
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    float r = animation.getAnimatedFraction();
+                    float scale = (1 - r) * initScale + r * finalScale;
+                    float alpha = (1 - r) * initAlpha + r * finalAlpha;
+                    int textAlpha = (int) ((1 - r) * initTextAlpha + r * finalTextAlpha);
+                    mFramed.setScale(scale);
+                    mUserImage.setAlpha(alpha);
+                    mUserName.setTextColor(Color.argb(textAlpha, 255, 255, 255));
+                    mUserImage.invalidate();
+                }
+            });
+            va.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    if (onComplete != null) {
+                        onComplete.run();
+                    }
+                }
+            });
+            va.setDuration(duration);
+            va.start();
+        } else {
+            mFramed.setScale(finalScale);
+            mUserImage.setAlpha(finalAlpha);
+            mUserName.setTextColor(Color.argb(finalTextAlpha, 255, 255, 255));
+            if (onComplete != null) {
+                post(onComplete);
+            }
+        }
+
+        mTouched = true;
+    }
+
+    @Override
+    public void setPressed(boolean pressed) {
+        if (!pressed || isClickable()) {
+            super.setPressed(pressed);
+            mFramed.setPressed(pressed);
+            mUserImage.invalidate();
+        }
+    }
+
+    public UserInfo getUserInfo() {
+        return mUserInfo;
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserSelectorView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserSelectorView.java
new file mode 100644
index 0000000..728e87c
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserSelectorView.java
@@ -0,0 +1,159 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.RemoteException;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.internal.R;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+
+public class KeyguardMultiUserSelectorView extends FrameLayout implements View.OnClickListener {
+    private static final String TAG = "KeyguardMultiUserSelectorView";
+
+    private ViewGroup mUsersGrid;
+    private KeyguardMultiUserAvatar mActiveUserAvatar;
+    private KeyguardHostView.UserSwitcherCallback mCallback;
+    private static final int FADE_OUT_ANIMATION_DURATION = 100;
+
+    public KeyguardMultiUserSelectorView(Context context) {
+        this(context, null, 0);
+    }
+
+    public KeyguardMultiUserSelectorView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public KeyguardMultiUserSelectorView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    protected void onFinishInflate () {
+        mUsersGrid = (ViewGroup) findViewById(R.id.keyguard_users_grid);
+        mUsersGrid.removeAllViews();
+        setClipChildren(false);
+        setClipToPadding(false);
+
+    }
+
+    public void setCallback(KeyguardHostView.UserSwitcherCallback callback) {
+        mCallback = callback;
+    }
+
+    public void addUsers(Collection<UserInfo> userList) {
+        UserInfo activeUser;
+        try {
+            activeUser = ActivityManagerNative.getDefault().getCurrentUser();
+        } catch (RemoteException re) {
+            activeUser = null;
+        }
+
+        ArrayList<UserInfo> users = new ArrayList<UserInfo>(userList);
+        Collections.sort(users, mOrderAddedComparator);
+
+        for (UserInfo user: users) {
+            KeyguardMultiUserAvatar uv = createAndAddUser(user);
+            if (user.id == activeUser.id) {
+                mActiveUserAvatar = uv;
+                mActiveUserAvatar.setActive(true, false, null);
+            } else {
+                uv.setActive(false, false, null);
+            }
+        }
+    }
+
+    Comparator<UserInfo> mOrderAddedComparator = new Comparator<UserInfo>() {
+        @Override
+        public int compare(UserInfo lhs, UserInfo rhs) {
+            return (lhs.serialNumber - rhs.serialNumber);
+        }
+    };
+
+    private KeyguardMultiUserAvatar createAndAddUser(UserInfo user) {
+        KeyguardMultiUserAvatar uv = KeyguardMultiUserAvatar.fromXml(
+                R.layout.keyguard_multi_user_avatar, mContext, this, user);
+        mUsersGrid.addView(uv);
+        return uv;
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent event) {
+        if(event.getActionMasked() != MotionEvent.ACTION_CANCEL && mCallback != null) {
+            mCallback.userActivity();
+        }
+        return false;
+    }
+
+    private void setAllClickable(boolean clickable)
+    {
+        for(int i = 0; i < mUsersGrid.getChildCount(); i++) {
+            View v = mUsersGrid.getChildAt(i);
+            v.setClickable(clickable);
+            v.setPressed(false);
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (!(v instanceof KeyguardMultiUserAvatar)) return;
+        final KeyguardMultiUserAvatar avatar = (KeyguardMultiUserAvatar) v;
+        if (avatar.isClickable()) { // catch race conditions
+            if (mActiveUserAvatar == avatar) {
+                // If they click the currently active user, show the unlock hint
+                mCallback.showUnlockHint();
+                return;
+            } else {
+                // Reset the previously active user to appear inactive
+                mCallback.hideSecurityView(FADE_OUT_ANIMATION_DURATION);
+                setAllClickable(false);
+                mActiveUserAvatar.setActive(false, true, new Runnable() {
+                    @Override
+                    public void run() {
+                        mActiveUserAvatar = avatar;
+                        mActiveUserAvatar.setActive(true, true, new Runnable() {
+                            @Override
+                            public void run() {
+                                if (this.getClass().getName().contains("internal")) {
+                                    try {
+                                        ActivityManagerNative.getDefault()
+                                                .switchUser(avatar.getUserInfo().id);
+                                    } catch (RemoteException re) {
+                                        Log.e(TAG, "Couldn't switch user " + re);
+                                    }
+                                } else {
+                                    setAllClickable(true);
+                                }
+                            }
+                        });
+                    }
+                });
+            }
+        }
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java
new file mode 100644
index 0000000..fa80352
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java
@@ -0,0 +1,120 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.text.method.DigitsKeyListener;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TextView.OnEditorActionListener;
+
+import com.android.internal.R;
+
+/**
+ * Displays a PIN pad for unlocking.
+ */
+public class KeyguardPINView extends KeyguardAbsKeyInputView
+        implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
+
+    public KeyguardPINView(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardPINView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    protected void resetState() {
+        if (KeyguardUpdateMonitor.getInstance(mContext).getMaxBiometricUnlockAttemptsReached()) {
+            mSecurityMessageDisplay.setMessage(R.string.faceunlock_multiple_failures, true);
+        } else {
+            mSecurityMessageDisplay.setMessage(R.string.kg_pin_instructions, false);
+        }
+        mPasswordEntry.setEnabled(true);
+    }
+
+    @Override
+    protected int getPasswordTextViewId() {
+        return R.id.pinEntry;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        final View ok = findViewById(R.id.key_enter);
+        if (ok != null) {
+            ok.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    doHapticKeyClick();
+                    if (mPasswordEntry.isEnabled()) {
+                        verifyPasswordAndUnlock();
+                    }
+                }
+            });
+            ok.setOnHoverListener(new LiftToActivateListener(getContext()));
+        }
+
+        // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
+        // not a separate view
+        View pinDelete = findViewById(R.id.delete_button);
+        if (pinDelete != null) {
+            pinDelete.setVisibility(View.VISIBLE);
+            pinDelete.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    // check for time-based lockouts
+                    if (mPasswordEntry.isEnabled()) {
+                        CharSequence str = mPasswordEntry.getText();
+                        if (str.length() > 0) {
+                            mPasswordEntry.setText(str.subSequence(0, str.length()-1));
+                        }
+                    }
+                    doHapticKeyClick();
+                }
+            });
+            pinDelete.setOnLongClickListener(new View.OnLongClickListener() {
+                public boolean onLongClick(View v) {
+                    // check for time-based lockouts
+                    if (mPasswordEntry.isEnabled()) {
+                        mPasswordEntry.setText("");
+                    }
+                    doHapticKeyClick();
+                    return true;
+                }
+            });
+        }
+
+        mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
+        mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
+                | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
+
+        mPasswordEntry.requestFocus();
+    }
+
+    @Override
+    public void showUsabilityHint() {
+    }
+
+    @Override
+    public int getWrongPasswordStringId() {
+        return R.string.kg_wrong_pin;
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java
new file mode 100644
index 0000000..d52c993
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java
@@ -0,0 +1,208 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.text.method.DigitsKeyListener;
+import android.text.method.TextKeyListener;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+import android.widget.TextView.OnEditorActionListener;
+
+import com.android.internal.R;
+import com.android.internal.widget.PasswordEntryKeyboardHelper;
+import com.android.internal.widget.PasswordEntryKeyboardView;
+
+import java.util.List;
+/**
+ * Displays an alphanumeric (latin-1) key entry for the user to enter
+ * an unlock password
+ */
+
+public class KeyguardPasswordView extends KeyguardAbsKeyInputView
+        implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
+
+    private final boolean mShowImeAtScreenOn;
+
+    InputMethodManager mImm;
+
+    public KeyguardPasswordView(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardPasswordView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mShowImeAtScreenOn = context.getResources().
+                getBoolean(R.bool.kg_show_ime_at_screen_on);
+    }
+
+    protected void resetState() {
+        mSecurityMessageDisplay.setMessage(R.string.kg_password_instructions, false);
+        mPasswordEntry.setEnabled(true);
+    }
+
+    @Override
+    protected int getPasswordTextViewId() {
+        return R.id.passwordEntry;
+    }
+
+    @Override
+    public boolean needsInput() {
+        return true;
+    }
+
+    @Override
+    public void onResume(int reason) {
+        super.onResume(reason);
+        mPasswordEntry.requestFocus();
+        if (reason != KeyguardSecurityView.SCREEN_ON || mShowImeAtScreenOn) {
+            mImm.showSoftInput(mPasswordEntry, InputMethodManager.SHOW_IMPLICIT);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        mImm.hideSoftInputFromWindow(getWindowToken(), 0);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        boolean imeOrDeleteButtonVisible = false;
+
+        mImm = (InputMethodManager) getContext().getSystemService(
+                Context.INPUT_METHOD_SERVICE);
+
+        mPasswordEntry.setKeyListener(TextKeyListener.getInstance());
+        mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT
+                | InputType.TYPE_TEXT_VARIATION_PASSWORD);
+
+        // Poke the wakelock any time the text is selected or modified
+        mPasswordEntry.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                mCallback.userActivity(0); // TODO: customize timeout for text?
+            }
+        });
+
+        mPasswordEntry.addTextChangedListener(new TextWatcher() {
+            public void onTextChanged(CharSequence s, int start, int before, int count) {
+            }
+
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+            }
+
+            public void afterTextChanged(Editable s) {
+                if (mCallback != null) {
+                    mCallback.userActivity(0);
+                }
+            }
+        });
+
+        mPasswordEntry.requestFocus();
+
+        // If there's more than one IME, enable the IME switcher button
+        View switchImeButton = findViewById(R.id.switch_ime_button);
+        if (switchImeButton != null && hasMultipleEnabledIMEsOrSubtypes(mImm, false)) {
+            switchImeButton.setVisibility(View.VISIBLE);
+            imeOrDeleteButtonVisible = true;
+            switchImeButton.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    mCallback.userActivity(0); // Leave the screen on a bit longer
+                    mImm.showInputMethodPicker();
+                }
+            });
+        }
+
+        // If no icon is visible, reset the start margin on the password field so the text is
+        // still centered.
+        if (!imeOrDeleteButtonVisible) {
+            android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams();
+            if (params instanceof MarginLayoutParams) {
+                final MarginLayoutParams mlp = (MarginLayoutParams) params;
+                mlp.setMarginStart(0);
+                mPasswordEntry.setLayoutParams(params);
+            }
+        }
+    }
+
+    /**
+     * Method adapted from com.android.inputmethod.latin.Utils
+     *
+     * @param imm The input method manager
+     * @param shouldIncludeAuxiliarySubtypes
+     * @return true if we have multiple IMEs to choose from
+     */
+    private boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManager imm,
+            final boolean shouldIncludeAuxiliarySubtypes) {
+        final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList();
+
+        // Number of the filtered IMEs
+        int filteredImisCount = 0;
+
+        for (InputMethodInfo imi : enabledImis) {
+            // We can return true immediately after we find two or more filtered IMEs.
+            if (filteredImisCount > 1) return true;
+            final List<InputMethodSubtype> subtypes =
+                    imm.getEnabledInputMethodSubtypeList(imi, true);
+            // IMEs that have no subtypes should be counted.
+            if (subtypes.isEmpty()) {
+                ++filteredImisCount;
+                continue;
+            }
+
+            int auxCount = 0;
+            for (InputMethodSubtype subtype : subtypes) {
+                if (subtype.isAuxiliary()) {
+                    ++auxCount;
+                }
+            }
+            final int nonAuxCount = subtypes.size() - auxCount;
+
+            // IMEs that have one or more non-auxiliary subtypes should be counted.
+            // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary
+            // subtypes should be counted as well.
+            if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) {
+                ++filteredImisCount;
+                continue;
+            }
+        }
+
+        return filteredImisCount > 1
+        // imm.getEnabledInputMethodSubtypeList(null, false) will return the current IME's enabled
+        // input method subtype (The current IME should be LatinIME.)
+                || imm.getEnabledInputMethodSubtypeList(null, false).size() > 1;
+    }
+
+    @Override
+    public void showUsabilityHint() {
+    }
+
+    @Override
+    public int getWrongPasswordStringId() {
+        return R.string.kg_wrong_password;
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java
new file mode 100644
index 0000000..e114b78
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java
@@ -0,0 +1,412 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerCallback;
+import android.accounts.AccountManagerFuture;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
+import android.content.Context;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.CountDownTimer;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+import com.android.internal.R;
+
+import java.io.IOException;
+import java.util.List;
+
+public class KeyguardPatternView extends LinearLayout implements KeyguardSecurityView {
+
+    private static final String TAG = "SecurityPatternView";
+    private static final boolean DEBUG = false;
+
+    // how long before we clear the wrong pattern
+    private static final int PATTERN_CLEAR_TIMEOUT_MS = 2000;
+
+    // how long we stay awake after each key beyond MIN_PATTERN_BEFORE_POKE_WAKELOCK
+    private static final int UNLOCK_PATTERN_WAKE_INTERVAL_MS = 7000;
+
+    // how long we stay awake after the user hits the first dot.
+    private static final int UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS = 2000;
+
+    // how many cells the user has to cross before we poke the wakelock
+    private static final int MIN_PATTERN_BEFORE_POKE_WAKELOCK = 2;
+
+    private int mFailedPatternAttemptsSinceLastTimeout = 0;
+    private int mTotalFailedPatternAttempts = 0;
+    private CountDownTimer mCountdownTimer = null;
+    private LockPatternUtils mLockPatternUtils;
+    private LockPatternView mLockPatternView;
+    private Button mForgotPatternButton;
+    private KeyguardSecurityCallback mCallback;
+    private boolean mEnableFallback;
+
+    /**
+     * Keeps track of the last time we poked the wake lock during dispatching of the touch event.
+     * Initialized to something guaranteed to make us poke the wakelock when the user starts
+     * drawing the pattern.
+     * @see #dispatchTouchEvent(android.view.MotionEvent)
+     */
+    private long mLastPokeTime = -UNLOCK_PATTERN_WAKE_INTERVAL_MS;
+
+    /**
+     * Useful for clearing out the wrong pattern after a delay
+     */
+    private Runnable mCancelPatternRunnable = new Runnable() {
+        public void run() {
+            mLockPatternView.clearPattern();
+        }
+    };
+    private Rect mTempRect = new Rect();
+    private SecurityMessageDisplay mSecurityMessageDisplay;
+    private View mEcaView;
+    private Drawable mBouncerFrame;
+
+    enum FooterMode {
+        Normal,
+        ForgotLockPattern,
+        VerifyUnlocked
+    }
+
+    public KeyguardPatternView(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardPatternView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public void setKeyguardCallback(KeyguardSecurityCallback callback) {
+        mCallback = callback;
+    }
+
+    public void setLockPatternUtils(LockPatternUtils utils) {
+        mLockPatternUtils = utils;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mLockPatternUtils = mLockPatternUtils == null
+                ? new LockPatternUtils(mContext) : mLockPatternUtils;
+
+        mLockPatternView = (LockPatternView) findViewById(R.id.lockPatternView);
+        mLockPatternView.setSaveEnabled(false);
+        mLockPatternView.setFocusable(false);
+        mLockPatternView.setOnPatternListener(new UnlockPatternListener());
+
+        // stealth mode will be the same for the life of this screen
+        mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled());
+
+        // vibrate mode will be the same for the life of this screen
+        mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
+
+        mForgotPatternButton = (Button) findViewById(R.id.forgot_password_button);
+        // note: some configurations don't have an emergency call area
+        if (mForgotPatternButton != null) {
+            mForgotPatternButton.setText(R.string.kg_forgot_pattern_button_text);
+            mForgotPatternButton.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    mCallback.showBackupSecurity();
+                }
+            });
+        }
+
+        setFocusableInTouchMode(true);
+
+        maybeEnableFallback(mContext);
+        mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
+        mEcaView = findViewById(R.id.keyguard_selector_fade_container);
+        View bouncerFrameView = findViewById(R.id.keyguard_bouncer_frame);
+        if (bouncerFrameView != null) {
+            mBouncerFrame = bouncerFrameView.getBackground();
+        }
+    }
+
+    private void updateFooter(FooterMode mode) {
+        if (mForgotPatternButton == null) return; // no ECA? no footer
+
+        switch (mode) {
+            case Normal:
+                if (DEBUG) Log.d(TAG, "mode normal");
+                mForgotPatternButton.setVisibility(View.GONE);
+                break;
+            case ForgotLockPattern:
+                if (DEBUG) Log.d(TAG, "mode ForgotLockPattern");
+                mForgotPatternButton.setVisibility(View.VISIBLE);
+                break;
+            case VerifyUnlocked:
+                if (DEBUG) Log.d(TAG, "mode VerifyUnlocked");
+                mForgotPatternButton.setVisibility(View.GONE);
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        boolean result = super.onTouchEvent(ev);
+        // as long as the user is entering a pattern (i.e sending a touch event that was handled
+        // by this screen), keep poking the wake lock so that the screen will stay on.
+        final long elapsed = SystemClock.elapsedRealtime() - mLastPokeTime;
+        if (result && (elapsed > (UNLOCK_PATTERN_WAKE_INTERVAL_MS - 100))) {
+            mLastPokeTime = SystemClock.elapsedRealtime();
+        }
+        mTempRect.set(0, 0, 0, 0);
+        offsetRectIntoDescendantCoords(mLockPatternView, mTempRect);
+        ev.offsetLocation(mTempRect.left, mTempRect.top);
+        result = mLockPatternView.dispatchTouchEvent(ev) || result;
+        ev.offsetLocation(-mTempRect.left, -mTempRect.top);
+        return result;
+    }
+
+    public void reset() {
+        // reset lock pattern
+        mLockPatternView.enableInput();
+        mLockPatternView.setEnabled(true);
+        mLockPatternView.clearPattern();
+
+        // if the user is currently locked out, enforce it.
+        long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
+        if (deadline != 0) {
+            handleAttemptLockout(deadline);
+        } else {
+            displayDefaultSecurityMessage();
+        }
+
+        // the footer depends on how many total attempts the user has failed
+        if (mCallback.isVerifyUnlockOnly()) {
+            updateFooter(FooterMode.VerifyUnlocked);
+        } else if (mEnableFallback &&
+                (mTotalFailedPatternAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
+            updateFooter(FooterMode.ForgotLockPattern);
+        } else {
+            updateFooter(FooterMode.Normal);
+        }
+
+    }
+
+    private void displayDefaultSecurityMessage() {
+        if (KeyguardUpdateMonitor.getInstance(mContext).getMaxBiometricUnlockAttemptsReached()) {
+            mSecurityMessageDisplay.setMessage(R.string.faceunlock_multiple_failures, true);
+        } else {
+            mSecurityMessageDisplay.setMessage(R.string.kg_pattern_instructions, false);
+        }
+    }
+
+    @Override
+    public void showUsabilityHint() {
+    }
+
+    /** TODO: hook this up */
+    public void cleanUp() {
+        if (DEBUG) Log.v(TAG, "Cleanup() called on " + this);
+        mLockPatternUtils = null;
+        mLockPatternView.setOnPatternListener(null);
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        super.onWindowFocusChanged(hasWindowFocus);
+        if (hasWindowFocus) {
+            // when timeout dialog closes we want to update our state
+            reset();
+        }
+    }
+
+    private class UnlockPatternListener implements LockPatternView.OnPatternListener {
+
+        public void onPatternStart() {
+            mLockPatternView.removeCallbacks(mCancelPatternRunnable);
+        }
+
+        public void onPatternCleared() {
+        }
+
+        public void onPatternCellAdded(List<LockPatternView.Cell> pattern) {
+            // To guard against accidental poking of the wakelock, look for
+            // the user actually trying to draw a pattern of some minimal length.
+            if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
+                mCallback.userActivity(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
+            } else {
+                // Give just a little extra time if they hit one of the first few dots
+                mCallback.userActivity(UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS);
+            }
+        }
+
+        public void onPatternDetected(List<LockPatternView.Cell> pattern) {
+            if (mLockPatternUtils.checkPattern(pattern)) {
+                mCallback.reportSuccessfulUnlockAttempt();
+                mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
+                mTotalFailedPatternAttempts = 0;
+                mCallback.dismiss(true);
+            } else {
+                if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
+                    mCallback.userActivity(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
+                }
+                mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
+                if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
+                    mTotalFailedPatternAttempts++;
+                    mFailedPatternAttemptsSinceLastTimeout++;
+                    mCallback.reportFailedUnlockAttempt();
+                }
+                if (mFailedPatternAttemptsSinceLastTimeout
+                        >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
+                    long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
+                    handleAttemptLockout(deadline);
+                } else {
+                    mSecurityMessageDisplay.setMessage(R.string.kg_wrong_pattern, true);
+                    mLockPatternView.postDelayed(mCancelPatternRunnable, PATTERN_CLEAR_TIMEOUT_MS);
+                }
+            }
+        }
+    }
+
+    private void maybeEnableFallback(Context context) {
+        // Ask the account manager if we have an account that can be used as a
+        // fallback in case the user forgets his pattern.
+        AccountAnalyzer accountAnalyzer = new AccountAnalyzer(AccountManager.get(context));
+        accountAnalyzer.start();
+    }
+
+    private class AccountAnalyzer implements AccountManagerCallback<Bundle> {
+        private final AccountManager mAccountManager;
+        private final Account[] mAccounts;
+        private int mAccountIndex;
+
+        private AccountAnalyzer(AccountManager accountManager) {
+            mAccountManager = accountManager;
+            mAccounts = accountManager.getAccountsByTypeAsUser("com.google",
+                    new UserHandle(mLockPatternUtils.getCurrentUser()));
+        }
+
+        private void next() {
+            // if we are ready to enable the fallback or if we depleted the list of accounts
+            // then finish and get out
+            if (mEnableFallback || mAccountIndex >= mAccounts.length) {
+                return;
+            }
+
+            // lookup the confirmCredentials intent for the current account
+            mAccountManager.confirmCredentialsAsUser(mAccounts[mAccountIndex], null, null, this,
+                    null, new UserHandle(mLockPatternUtils.getCurrentUser()));
+        }
+
+        public void start() {
+            mEnableFallback = false;
+            mAccountIndex = 0;
+            next();
+        }
+
+        public void run(AccountManagerFuture<Bundle> future) {
+            try {
+                Bundle result = future.getResult();
+                if (result.getParcelable(AccountManager.KEY_INTENT) != null) {
+                    mEnableFallback = true;
+                }
+            } catch (OperationCanceledException e) {
+                // just skip the account if we are unable to query it
+            } catch (IOException e) {
+                // just skip the account if we are unable to query it
+            } catch (AuthenticatorException e) {
+                // just skip the account if we are unable to query it
+            } finally {
+                mAccountIndex++;
+                next();
+            }
+        }
+    }
+
+    private void handleAttemptLockout(long elapsedRealtimeDeadline) {
+        mLockPatternView.clearPattern();
+        mLockPatternView.setEnabled(false);
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        if (mEnableFallback) {
+            updateFooter(FooterMode.ForgotLockPattern);
+        }
+
+        mCountdownTimer = new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
+
+            @Override
+            public void onTick(long millisUntilFinished) {
+                final int secondsRemaining = (int) (millisUntilFinished / 1000);
+                mSecurityMessageDisplay.setMessage(
+                        R.string.kg_too_many_failed_attempts_countdown, true, secondsRemaining);
+            }
+
+            @Override
+            public void onFinish() {
+                mLockPatternView.setEnabled(true);
+                displayDefaultSecurityMessage();
+                // TODO mUnlockIcon.setVisibility(View.VISIBLE);
+                mFailedPatternAttemptsSinceLastTimeout = 0;
+                if (mEnableFallback) {
+                    updateFooter(FooterMode.ForgotLockPattern);
+                } else {
+                    updateFooter(FooterMode.Normal);
+                }
+            }
+
+        }.start();
+    }
+
+    @Override
+    public boolean needsInput() {
+        return false;
+    }
+
+    @Override
+    public void onPause() {
+        if (mCountdownTimer != null) {
+            mCountdownTimer.cancel();
+            mCountdownTimer = null;
+        }
+    }
+
+    @Override
+    public void onResume(int reason) {
+        reset();
+    }
+
+    @Override
+    public KeyguardSecurityCallback getCallback() {
+        return mCallback;
+    }
+
+    @Override
+    public void showBouncer(int duration) {
+        KeyguardSecurityViewHelper.
+                showBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
+    }
+
+    @Override
+    public void hideBouncer(int duration) {
+        KeyguardSecurityViewHelper.
+                hideBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityCallback.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityCallback.java
new file mode 100644
index 0000000..7e6c108
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityCallback.java
@@ -0,0 +1,68 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import com.android.internal.policy.impl.keyguard.KeyguardHostView.OnDismissAction;
+
+public interface KeyguardSecurityCallback {
+
+    /**
+     * Dismiss the given security screen.
+     * @param securityVerified true if the user correctly entered credentials for the given screen.
+     */
+    void dismiss(boolean securityVerified);
+
+    /**
+     * Manually report user activity to keep the device awake. If timeout is 0,
+     * uses user-defined timeout.
+     * @param timeout
+     */
+    void userActivity(long timeout);
+
+    /**
+     * Checks if keyguard is in "verify credentials" mode.
+     * @return true if user has been asked to verify security.
+     */
+    boolean isVerifyUnlockOnly();
+
+    /**
+     * Call when user correctly enters their credentials
+     */
+    void reportSuccessfulUnlockAttempt();
+
+    /**
+     * Call when the user incorrectly enters their credentials
+     */
+    void reportFailedUnlockAttempt();
+
+    /**
+     * Gets the number of attempts thus far as reported by {@link #reportFailedUnlockAttempt()}
+     * @return number of failed attempts
+     */
+    int getFailedAttempts();
+
+    /**
+     * Shows the backup security for the current method.  If none available, this call is a no-op.
+     */
+    void showBackupSecurity();
+
+    /**
+     * Sets an action to perform after the user successfully enters their credentials.
+     * @param action
+     */
+    void setOnDismissAction(OnDismissAction action);
+
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityContainer.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityContainer.java
new file mode 100644
index 0000000..375a96a
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityContainer.java
@@ -0,0 +1,47 @@
+package com.android.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.internal.R;
+
+public class KeyguardSecurityContainer extends FrameLayout {
+    public KeyguardSecurityContainer(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public KeyguardSecurityContainer(Context context) {
+        this(null, null, 0);
+    }
+
+    public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    KeyguardSecurityViewFlipper getFlipper() {
+        for (int i = 0; i < getChildCount(); i++) {
+            View child = getChildAt(i);
+            if (child instanceof KeyguardSecurityViewFlipper) {
+                return (KeyguardSecurityViewFlipper) child;
+            }
+        }
+        return null;
+    }
+
+    public void showBouncer(int duration) {
+        KeyguardSecurityViewFlipper flipper = getFlipper();
+        if (flipper != null) {
+            flipper.showBouncer(duration);
+        }
+    }
+
+    public void hideBouncer(int duration) {
+        KeyguardSecurityViewFlipper flipper = getFlipper();
+        if (flipper != null) {
+            flipper.hideBouncer(duration);
+        }
+    }
+}
+
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java
new file mode 100644
index 0000000..7a69586
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java
@@ -0,0 +1,147 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.widget.LockPatternUtils;
+
+public class KeyguardSecurityModel {
+    /**
+     * The different types of security available for {@link Mode#UnlockScreen}.
+     * @see com.android.internal.policy.impl.LockPatternKeyguardView#getUnlockMode()
+     */
+    enum SecurityMode {
+        Invalid, // NULL state
+        None, // No security enabled
+        Pattern, // Unlock by drawing a pattern.
+        Password, // Unlock by entering an alphanumeric password
+        PIN, // Strictly numeric password
+        Biometric, // Unlock with a biometric key (e.g. finger print or face unlock)
+        Account, // Unlock by entering an account's login and password.
+        SimPin, // Unlock by entering a sim pin.
+        SimPuk // Unlock by entering a sim puk
+    }
+
+    private Context mContext;
+    private LockPatternUtils mLockPatternUtils;
+
+    KeyguardSecurityModel(Context context) {
+        mContext = context;
+        mLockPatternUtils = new LockPatternUtils(context);
+    }
+
+    void setLockPatternUtils(LockPatternUtils utils) {
+        mLockPatternUtils = utils;
+    }
+
+    /**
+     * Returns true if biometric unlock is installed and selected.  If this returns false there is
+     * no need to even construct the biometric unlock.
+     */
+    boolean isBiometricUnlockEnabled() {
+        return mLockPatternUtils.usingBiometricWeak()
+                && mLockPatternUtils.isBiometricWeakInstalled();
+    }
+
+    /**
+     * Returns true if a condition is currently suppressing the biometric unlock.  If this returns
+     * true there is no need to even construct the biometric unlock.
+     */
+    private boolean isBiometricUnlockSuppressed() {
+        KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
+        final boolean backupIsTimedOut = monitor.getFailedUnlockAttempts() >=
+                LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
+        return monitor.getMaxBiometricUnlockAttemptsReached() || backupIsTimedOut
+                || !monitor.isAlternateUnlockEnabled()
+                || monitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE;
+    }
+
+    SecurityMode getSecurityMode() {
+        KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+        final IccCardConstants.State simState = updateMonitor.getSimState();
+        SecurityMode mode = SecurityMode.None;
+        if (simState == IccCardConstants.State.PIN_REQUIRED) {
+            mode = SecurityMode.SimPin;
+        } else if (simState == IccCardConstants.State.PUK_REQUIRED
+                && mLockPatternUtils.isPukUnlockScreenEnable()) {
+            mode = SecurityMode.SimPuk;
+        } else {
+            final int security = mLockPatternUtils.getKeyguardStoredPasswordQuality();
+            switch (security) {
+                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+                    mode = mLockPatternUtils.isLockPasswordEnabled() ?
+                            SecurityMode.PIN : SecurityMode.None;
+                    break;
+                case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
+                case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+                case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
+                    mode = mLockPatternUtils.isLockPasswordEnabled() ?
+                            SecurityMode.Password : SecurityMode.None;
+                    break;
+
+                case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+                case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
+                    if (mLockPatternUtils.isLockPatternEnabled()) {
+                        mode = mLockPatternUtils.isPermanentlyLocked() ?
+                            SecurityMode.Account : SecurityMode.Pattern;
+                    }
+                    break;
+
+                default:
+                    throw new IllegalStateException("Unknown unlock mode:" + mode);
+            }
+        }
+        return mode;
+    }
+
+    /**
+     * Some unlock methods can have an alternate, such as biometric unlocks (e.g. face unlock).
+     * This function decides if an alternate unlock is available and returns it. Otherwise,
+     * returns @param mode.
+     *
+     * @param mode the mode we want the alternate for
+     * @return alternate or the given mode
+     */
+    SecurityMode getAlternateFor(SecurityMode mode) {
+        if (isBiometricUnlockEnabled() && !isBiometricUnlockSuppressed()
+                && (mode == SecurityMode.Password
+                        || mode == SecurityMode.PIN
+                        || mode == SecurityMode.Pattern)) {
+            return SecurityMode.Biometric;
+        }
+        return mode; // no alternate, return what was given
+    }
+
+    /**
+     * Some unlock methods can have a backup which gives the user another way to get into
+     * the device. This is currently only supported for Biometric and Pattern unlock.
+     *
+     * @return backup method or current security mode
+     */
+    SecurityMode getBackupSecurityMode(SecurityMode mode) {
+        switch(mode) {
+            case Biometric:
+                return getSecurityMode();
+            case Pattern:
+                return SecurityMode.Account;
+        }
+        return mode; // no backup, return current security mode
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityView.java
new file mode 100644
index 0000000..a3ac39c
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityView.java
@@ -0,0 +1,87 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import com.android.internal.widget.LockPatternUtils;
+
+public interface KeyguardSecurityView {
+    static public final int SCREEN_ON = 1;
+    static public final int VIEW_REVEALED = 2;
+
+    /**
+     * Interface back to keyguard to tell it when security
+     * @param callback
+     */
+    void setKeyguardCallback(KeyguardSecurityCallback callback);
+
+    /**
+     * Set {@link LockPatternUtils} object. Useful for providing a mock interface.
+     * @param utils
+     */
+    void setLockPatternUtils(LockPatternUtils utils);
+
+    /**
+     * Reset the view and prepare to take input. This should do things like clearing the
+     * password or pattern and clear error messages.
+     */
+    void reset();
+
+    /**
+     * Emulate activity life cycle within the view. When called, the view should clean up
+     * and prepare to be removed.
+     */
+    void onPause();
+
+    /**
+     * Emulate activity life cycle within this view.  When called, the view should prepare itself
+     * to be shown.
+     * @param reason the root cause of the event.
+     */
+    void onResume(int reason);
+
+    /**
+     * Inquire whether this view requires IME (keyboard) interaction.
+     *
+     * @return true if IME interaction is required.
+     */
+    boolean needsInput();
+
+    /**
+     * Get {@link KeyguardSecurityCallback} for the given object
+     * @return KeyguardSecurityCallback
+     */
+    KeyguardSecurityCallback getCallback();
+
+    /**
+     * Instruct the view to show usability hints, if any.
+     *
+     */
+    void showUsabilityHint();
+
+    /**
+     * Place the security view into bouncer mode.
+     * Animate transisiton if duration is non-zero.
+     * @param duration millisends for the transisiton animation.
+     */
+    void showBouncer(int duration);
+
+    /**
+     * Place the security view into non-bouncer mode.
+     * Animate transisiton if duration is non-zero.
+     * @param duration millisends for the transisiton animation.
+     */
+    void hideBouncer(int duration);
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewFlipper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewFlipper.java
new file mode 100644
index 0000000..aa31b00
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewFlipper.java
@@ -0,0 +1,279 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import com.android.internal.R;
+import com.android.internal.widget.LockPatternUtils;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewDebug;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.ViewFlipper;
+
+/**
+ * Subclass of the current view flipper that allows us to overload dispatchTouchEvent() so
+ * we can emulate {@link WindowManager.LayoutParams#FLAG_SLIPPERY} within a view hierarchy.
+ *
+ */
+public class KeyguardSecurityViewFlipper extends ViewFlipper implements KeyguardSecurityView {
+    private static final String TAG = "KeyguardSecurityViewFlipper";
+    private static final boolean DEBUG = false;
+
+    private Rect mTempRect = new Rect();
+
+    public KeyguardSecurityViewFlipper(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardSecurityViewFlipper(Context context, AttributeSet attr) {
+        super(context, attr);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        boolean result = super.onTouchEvent(ev);
+        mTempRect.set(0, 0, 0, 0);
+        for (int i = 0; i < getChildCount(); i++) {
+            View child = getChildAt(i);
+            if (child.getVisibility() == View.VISIBLE) {
+                offsetRectIntoDescendantCoords(child, mTempRect);
+                ev.offsetLocation(mTempRect.left, mTempRect.top);
+                result = child.dispatchTouchEvent(ev) || result;
+                ev.offsetLocation(-mTempRect.left, -mTempRect.top);
+            }
+        }
+        return result;
+    }
+
+    KeyguardSecurityView getSecurityView() {
+        View child = getChildAt(getDisplayedChild());
+        if (child instanceof KeyguardSecurityView) {
+            return (KeyguardSecurityView) child;
+        }
+        return null;
+    }
+
+    @Override
+    public void setKeyguardCallback(KeyguardSecurityCallback callback) {
+        KeyguardSecurityView ksv = getSecurityView();
+        if (ksv != null) {
+            ksv.setKeyguardCallback(callback);
+        }
+    }
+
+    @Override
+    public void setLockPatternUtils(LockPatternUtils utils) {
+        KeyguardSecurityView ksv = getSecurityView();
+        if (ksv != null) {
+            ksv.setLockPatternUtils(utils);
+        }
+    }
+
+    @Override
+    public void reset() {
+        KeyguardSecurityView ksv = getSecurityView();
+        if (ksv != null) {
+            ksv.reset();
+        }
+    }
+
+    @Override
+    public void onPause() {
+        KeyguardSecurityView ksv = getSecurityView();
+        if (ksv != null) {
+            ksv.onPause();
+        }
+    }
+
+    @Override
+    public void onResume(int reason) {
+        KeyguardSecurityView ksv = getSecurityView();
+        if (ksv != null) {
+            ksv.onResume(reason);
+        }
+    }
+
+    @Override
+    public boolean needsInput() {
+        KeyguardSecurityView ksv = getSecurityView();
+        return (ksv != null) ? ksv.needsInput() : false;
+    }
+
+    @Override
+    public KeyguardSecurityCallback getCallback() {
+        KeyguardSecurityView ksv = getSecurityView();
+        return (ksv != null) ? ksv.getCallback() : null;
+    }
+
+    @Override
+    public void showUsabilityHint() {
+        KeyguardSecurityView ksv = getSecurityView();
+        if (ksv != null) {
+            ksv.showUsabilityHint();
+        }
+    }
+
+    @Override
+    public void showBouncer(int duration) {
+        KeyguardSecurityView active = getSecurityView();
+        for (int i = 0; i < getChildCount(); i++) {
+            View child = getChildAt(i);
+            if (child instanceof KeyguardSecurityView) {
+                KeyguardSecurityView ksv = (KeyguardSecurityView) child;
+                ksv.showBouncer(ksv == active ? duration : 0);
+            }
+        }
+    }
+
+    @Override
+    public void hideBouncer(int duration) {
+        KeyguardSecurityView active = getSecurityView();
+        for (int i = 0; i < getChildCount(); i++) {
+            View child = getChildAt(i);
+            if (child instanceof KeyguardSecurityView) {
+                KeyguardSecurityView ksv = (KeyguardSecurityView) child;
+                ksv.hideBouncer(ksv == active ? duration : 0);
+            }
+        }
+    }
+
+    @Override
+    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+        return p instanceof LayoutParams;
+    }
+
+    @Override
+    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+        return p instanceof LayoutParams ? new LayoutParams((LayoutParams) p) : new LayoutParams(p);
+    }
+
+    @Override
+    public LayoutParams generateLayoutParams(AttributeSet attrs) {
+        return new LayoutParams(getContext(), attrs);
+    }
+
+    @Override
+    protected void onMeasure(int widthSpec, int heightSpec) {
+        final int widthMode = MeasureSpec.getMode(widthSpec);
+        final int heightMode = MeasureSpec.getMode(heightSpec);
+        if (DEBUG && widthMode != MeasureSpec.AT_MOST) {
+            Log.w(TAG, "onMeasure: widthSpec " + MeasureSpec.toString(widthSpec) +
+                    " should be AT_MOST");
+        }
+        if (DEBUG && heightMode != MeasureSpec.AT_MOST) {
+            Log.w(TAG, "onMeasure: heightSpec " + MeasureSpec.toString(heightSpec) +
+                    " should be AT_MOST");
+        }
+
+        final int widthSize = MeasureSpec.getSize(widthSpec);
+        final int heightSize = MeasureSpec.getSize(heightSpec);
+        int maxWidth = widthSize;
+        int maxHeight = heightSize;
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+            if (lp.maxWidth > 0 && lp.maxWidth < maxWidth) {
+                maxWidth = lp.maxWidth;
+            }
+            if (lp.maxHeight > 0 && lp.maxHeight < maxHeight) {
+                maxHeight = lp.maxHeight;
+            }
+        }
+
+        final int wPadding = getPaddingLeft() + getPaddingRight();
+        final int hPadding = getPaddingTop() + getPaddingBottom();
+        maxWidth -= wPadding;
+        maxHeight -= hPadding;
+
+        int width = widthMode == MeasureSpec.EXACTLY ? widthSize : 0;
+        int height = heightMode == MeasureSpec.EXACTLY ? heightSize : 0;
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+            final int childWidthSpec = makeChildMeasureSpec(maxWidth, lp.width);
+            final int childHeightSpec = makeChildMeasureSpec(maxHeight, lp.height);
+
+            child.measure(childWidthSpec, childHeightSpec);
+
+            width = Math.max(width, Math.min(child.getMeasuredWidth(), widthSize - wPadding));
+            height = Math.max(height, Math.min(child.getMeasuredHeight(), heightSize - hPadding));
+        }
+        setMeasuredDimension(width + wPadding, height + hPadding);
+    }
+
+    private int makeChildMeasureSpec(int maxSize, int childDimen) {
+        final int mode;
+        final int size;
+        switch (childDimen) {
+            case LayoutParams.WRAP_CONTENT:
+                mode = MeasureSpec.AT_MOST;
+                size = maxSize;
+                break;
+            case LayoutParams.MATCH_PARENT:
+                mode = MeasureSpec.EXACTLY;
+                size = maxSize;
+                break;
+            default:
+                mode = MeasureSpec.EXACTLY;
+                size = Math.min(maxSize, childDimen);
+                break;
+        }
+        return MeasureSpec.makeMeasureSpec(size, mode);
+    }
+
+    public static class LayoutParams extends FrameLayout.LayoutParams {
+        @ViewDebug.ExportedProperty(category = "layout")
+        public int maxWidth;
+
+        @ViewDebug.ExportedProperty(category = "layout")
+        public int maxHeight;
+
+        public LayoutParams(ViewGroup.LayoutParams other) {
+            super(other);
+        }
+
+        public LayoutParams(LayoutParams other) {
+            super(other);
+
+            maxWidth = other.maxWidth;
+            maxHeight = other.maxHeight;
+        }
+
+        public LayoutParams(Context c, AttributeSet attrs) {
+            super(c, attrs);
+
+            final TypedArray a = c.obtainStyledAttributes(attrs,
+                    R.styleable.KeyguardSecurityViewFlipper_Layout, 0, 0);
+            maxWidth = a.getDimensionPixelSize(
+                    R.styleable.KeyguardSecurityViewFlipper_Layout_layout_maxWidth, 0);
+            maxHeight = a.getDimensionPixelSize(
+                    R.styleable.KeyguardSecurityViewFlipper_Layout_layout_maxHeight, 0);
+            a.recycle();
+        }
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewHelper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewHelper.java
new file mode 100644
index 0000000..3d59f8d
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewHelper.java
@@ -0,0 +1,94 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+
+/**
+ * Some common functions that are useful for KeyguardSecurityViews.
+ */
+public class KeyguardSecurityViewHelper {
+
+    public static void showBouncer(SecurityMessageDisplay securityMessageDisplay,
+            final View ecaView, Drawable bouncerFrame, int duration) {
+        if (securityMessageDisplay != null) {
+            securityMessageDisplay.showBouncer(duration);
+        }
+        if (ecaView != null) {
+            if (duration > 0) {
+                Animator anim = ObjectAnimator.ofFloat(ecaView, "alpha", 0f);
+                anim.setDuration(duration);
+                anim.addListener(new AnimatorListenerAdapter() {
+                    private boolean mCanceled;
+                    @Override
+                    public void onAnimationCancel(Animator animation) {
+                        // Fail safe and show the emergency button in onAnimationEnd()
+                        mCanceled = true;
+                        ecaView.setAlpha(1f);
+                    }
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        ecaView.setVisibility(mCanceled ? View.VISIBLE : View.INVISIBLE);
+                    }
+                });
+                anim.start();
+            } else {
+                ecaView.setAlpha(0f);
+                ecaView.setVisibility(View.INVISIBLE);
+            }
+        }
+        if (bouncerFrame != null) {
+            if (duration > 0) {
+                Animator anim = ObjectAnimator.ofInt(bouncerFrame, "alpha", 0, 255);
+                anim.setDuration(duration);
+                anim.start();
+            } else {
+                bouncerFrame.setAlpha(255);
+            }
+        }
+    }
+
+    public static void hideBouncer(SecurityMessageDisplay securityMessageDisplay,
+            View ecaView, Drawable bouncerFrame, int duration) {
+        if (securityMessageDisplay != null) {
+            securityMessageDisplay.hideBouncer(duration);
+        }
+        if (ecaView != null) {
+            ecaView.setVisibility(View.VISIBLE);
+            if (duration > 0) {
+                Animator anim = ObjectAnimator.ofFloat(ecaView, "alpha", 1f);
+                anim.setDuration(duration);
+                anim.start();
+            } else {
+                ecaView.setAlpha(1f);
+            }
+        }
+        if (bouncerFrame != null) {
+            if (duration > 0) {
+                Animator anim = ObjectAnimator.ofInt(bouncerFrame, "alpha", 255, 0);
+                anim.setDuration(duration);
+                anim.start();
+            } else {
+                bouncerFrame.setAlpha(0);
+            }
+        }
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
new file mode 100644
index 0000000..76cbbd5
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
@@ -0,0 +1,288 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.animation.ObjectAnimator;
+import android.app.SearchManager;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Slog;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import com.android.internal.telephony.IccCardConstants.State;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.multiwaveview.GlowPadView;
+import com.android.internal.widget.multiwaveview.GlowPadView.OnTriggerListener;
+import com.android.internal.R;
+
+public class KeyguardSelectorView extends LinearLayout implements KeyguardSecurityView {
+    private static final boolean DEBUG = KeyguardHostView.DEBUG;
+    private static final String TAG = "SecuritySelectorView";
+    private static final String ASSIST_ICON_METADATA_NAME =
+        "com.android.systemui.action_assist_icon";
+
+    private KeyguardSecurityCallback mCallback;
+    private GlowPadView mGlowPadView;
+    private ObjectAnimator mAnim;
+    private View mFadeView;
+    private boolean mIsBouncing;
+    private boolean mCameraDisabled;
+    private boolean mSearchDisabled;
+    private LockPatternUtils mLockPatternUtils;
+    private SecurityMessageDisplay mSecurityMessageDisplay;
+    private Drawable mBouncerFrame;
+
+    OnTriggerListener mOnTriggerListener = new OnTriggerListener() {
+
+        public void onTrigger(View v, int target) {
+            final int resId = mGlowPadView.getResourceIdForTarget(target);
+            switch (resId) {
+                case com.android.internal.R.drawable.ic_action_assist_generic:
+                    Intent assistIntent =
+                            ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                            .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+                    if (assistIntent != null) {
+                        mActivityLauncher.launchActivity(assistIntent, false, true, null, null);
+                    } else {
+                        Log.w(TAG, "Failed to get intent for assist activity");
+                    }
+                    mCallback.userActivity(0);
+                    break;
+
+                case com.android.internal.R.drawable.ic_lockscreen_camera:
+                    mActivityLauncher.launchCamera(null, null);
+                    mCallback.userActivity(0);
+                    break;
+
+                case com.android.internal.R.drawable.ic_lockscreen_unlock_phantom:
+                case com.android.internal.R.drawable.ic_lockscreen_unlock:
+                    mCallback.userActivity(0);
+                    mCallback.dismiss(false);
+                break;
+            }
+        }
+
+        public void onReleased(View v, int handle) {
+            if (!mIsBouncing) {
+                doTransition(mFadeView, 1.0f);
+            }
+        }
+
+        public void onGrabbed(View v, int handle) {
+            mCallback.userActivity(0);
+            doTransition(mFadeView, 0.0f);
+        }
+
+        public void onGrabbedStateChange(View v, int handle) {
+
+        }
+
+        public void onFinishFinalAnimation() {
+
+        }
+
+    };
+
+    KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
+
+        @Override
+        public void onDevicePolicyManagerStateChanged() {
+            updateTargets();
+        }
+
+        @Override
+        public void onSimStateChanged(State simState) {
+            updateTargets();
+        }
+    };
+
+    private final KeyguardActivityLauncher mActivityLauncher = new KeyguardActivityLauncher() {
+
+        @Override
+        KeyguardSecurityCallback getCallback() {
+            return mCallback;
+        }
+
+        @Override
+        LockPatternUtils getLockPatternUtils() {
+            return mLockPatternUtils;
+        }
+
+        @Override
+        Context getContext() {
+            return mContext;
+        }};
+
+    public KeyguardSelectorView(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardSelectorView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mLockPatternUtils = new LockPatternUtils(getContext());
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mGlowPadView = (GlowPadView) findViewById(R.id.glow_pad_view);
+        mGlowPadView.setOnTriggerListener(mOnTriggerListener);
+        updateTargets();
+
+        mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
+        View bouncerFrameView = findViewById(R.id.keyguard_selector_view_frame);
+        mBouncerFrame = bouncerFrameView.getBackground();
+    }
+
+    public void setCarrierArea(View carrierArea) {
+        mFadeView = carrierArea;
+    }
+
+    public boolean isTargetPresent(int resId) {
+        return mGlowPadView.getTargetPosition(resId) != -1;
+    }
+
+    @Override
+    public void showUsabilityHint() {
+        mGlowPadView.ping();
+    }
+
+    private void updateTargets() {
+        int currentUserHandle = mLockPatternUtils.getCurrentUser();
+        DevicePolicyManager dpm = mLockPatternUtils.getDevicePolicyManager();
+        int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, currentUserHandle);
+        boolean secureCameraDisabled = mLockPatternUtils.isSecure()
+                && (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0;
+        boolean cameraDisabledByAdmin = dpm.getCameraDisabled(null, currentUserHandle)
+                || secureCameraDisabled;
+        final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(getContext());
+        boolean disabledBySimState = monitor.isSimLocked();
+        boolean cameraTargetPresent =
+            isTargetPresent(com.android.internal.R.drawable.ic_lockscreen_camera);
+        boolean searchTargetPresent =
+            isTargetPresent(com.android.internal.R.drawable.ic_action_assist_generic);
+
+        if (cameraDisabledByAdmin) {
+            Log.v(TAG, "Camera disabled by Device Policy");
+        } else if (disabledBySimState) {
+            Log.v(TAG, "Camera disabled by Sim State");
+        }
+        boolean currentUserSetup = 0 != Settings.Secure.getIntForUser(
+                mContext.getContentResolver(),
+                Settings.Secure.USER_SETUP_COMPLETE,
+                0 /*default */,
+                currentUserHandle);
+        boolean searchActionAvailable =
+                ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                .getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
+        mCameraDisabled = cameraDisabledByAdmin || disabledBySimState || !cameraTargetPresent
+                || !currentUserSetup;
+        mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent
+                || !currentUserSetup;
+        updateResources();
+    }
+
+    public void updateResources() {
+        // Update the search icon with drawable from the search .apk
+        if (!mSearchDisabled) {
+            Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                    .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+            if (intent != null) {
+                // XXX Hack. We need to substitute the icon here but haven't formalized
+                // the public API. The "_google" metadata will be going away, so
+                // DON'T USE IT!
+                ComponentName component = intent.getComponent();
+                boolean replaced = mGlowPadView.replaceTargetDrawablesIfPresent(component,
+                        ASSIST_ICON_METADATA_NAME + "_google",
+                        com.android.internal.R.drawable.ic_action_assist_generic);
+
+                if (!replaced && !mGlowPadView.replaceTargetDrawablesIfPresent(component,
+                            ASSIST_ICON_METADATA_NAME,
+                            com.android.internal.R.drawable.ic_action_assist_generic)) {
+                        Slog.w(TAG, "Couldn't grab icon from package " + component);
+                }
+            }
+        }
+
+        mGlowPadView.setEnableTarget(com.android.internal.R.drawable
+                .ic_lockscreen_camera, !mCameraDisabled);
+        mGlowPadView.setEnableTarget(com.android.internal.R.drawable
+                .ic_action_assist_generic, !mSearchDisabled);
+    }
+
+    void doTransition(View view, float to) {
+        if (mAnim != null) {
+            mAnim.cancel();
+        }
+        mAnim = ObjectAnimator.ofFloat(view, "alpha", to);
+        mAnim.start();
+    }
+
+    public void setKeyguardCallback(KeyguardSecurityCallback callback) {
+        mCallback = callback;
+    }
+
+    public void setLockPatternUtils(LockPatternUtils utils) {
+        mLockPatternUtils = utils;
+    }
+
+    @Override
+    public void reset() {
+        mGlowPadView.reset(false);
+    }
+
+    @Override
+    public boolean needsInput() {
+        return false;
+    }
+
+    @Override
+    public void onPause() {
+        KeyguardUpdateMonitor.getInstance(getContext()).removeCallback(mInfoCallback);
+    }
+
+    @Override
+    public void onResume(int reason) {
+        KeyguardUpdateMonitor.getInstance(getContext()).registerCallback(mInfoCallback);
+    }
+
+    @Override
+    public KeyguardSecurityCallback getCallback() {
+        return mCallback;
+    }
+
+    @Override
+    public void showBouncer(int duration) {
+        mIsBouncing = true;
+        KeyguardSecurityViewHelper.
+                showBouncer(mSecurityMessageDisplay, mFadeView, mBouncerFrame, duration);
+    }
+
+    @Override
+    public void hideBouncer(int duration) {
+        mIsBouncing = false;
+        KeyguardSecurityViewHelper.
+                hideBouncer(mSecurityMessageDisplay, mFadeView, mBouncerFrame, duration);
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java
new file mode 100644
index 0000000..ab364ee
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java
@@ -0,0 +1,213 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import com.android.internal.telephony.ITelephony;
+
+import android.content.Context;
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.text.method.DigitsKeyListener;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.TextView.OnEditorActionListener;
+
+import com.android.internal.R;
+
+/**
+ * Displays a PIN pad for unlocking.
+ */
+public class KeyguardSimPinView extends KeyguardAbsKeyInputView
+        implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
+
+    private ProgressDialog mSimUnlockProgressDialog = null;
+    private volatile boolean mSimCheckInProgress;
+
+    public KeyguardSimPinView(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardSimPinView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public void resetState() {
+        mSecurityMessageDisplay.setMessage(R.string.kg_sim_pin_instructions, true);
+        mPasswordEntry.setEnabled(true);
+    }
+
+    @Override
+    protected int getPasswordTextViewId() {
+        return R.id.pinEntry;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        final View ok = findViewById(R.id.key_enter);
+        if (ok != null) {
+            ok.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    doHapticKeyClick();
+                    verifyPasswordAndUnlock();
+                }
+            });
+        }
+
+        // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
+        // not a separate view
+        View pinDelete = findViewById(R.id.delete_button);
+        if (pinDelete != null) {
+            pinDelete.setVisibility(View.VISIBLE);
+            pinDelete.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    CharSequence str = mPasswordEntry.getText();
+                    if (str.length() > 0) {
+                        mPasswordEntry.setText(str.subSequence(0, str.length()-1));
+                    }
+                    doHapticKeyClick();
+                }
+            });
+            pinDelete.setOnLongClickListener(new View.OnLongClickListener() {
+                public boolean onLongClick(View v) {
+                    mPasswordEntry.setText("");
+                    doHapticKeyClick();
+                    return true;
+                }
+            });
+        }
+
+        mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
+        mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
+                | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
+
+        mPasswordEntry.requestFocus();
+    }
+
+    @Override
+    public void showUsabilityHint() {
+    }
+
+    @Override
+    public void onPause() {
+        // dismiss the dialog.
+        if (mSimUnlockProgressDialog != null) {
+            mSimUnlockProgressDialog.dismiss();
+            mSimUnlockProgressDialog = null;
+        }
+    }
+
+    /**
+     * Since the IPC can block, we want to run the request in a separate thread
+     * with a callback.
+     */
+    private abstract class CheckSimPin extends Thread {
+        private final String mPin;
+
+        protected CheckSimPin(String pin) {
+            mPin = pin;
+        }
+
+        abstract void onSimCheckResponse(boolean success);
+
+        @Override
+        public void run() {
+            try {
+                final boolean result = ITelephony.Stub.asInterface(ServiceManager
+                        .checkService("phone")).supplyPin(mPin);
+                post(new Runnable() {
+                    public void run() {
+                        onSimCheckResponse(result);
+                    }
+                });
+            } catch (RemoteException e) {
+                post(new Runnable() {
+                    public void run() {
+                        onSimCheckResponse(false);
+                    }
+                });
+            }
+        }
+    }
+
+    private Dialog getSimUnlockProgressDialog() {
+        if (mSimUnlockProgressDialog == null) {
+            mSimUnlockProgressDialog = new ProgressDialog(mContext);
+            mSimUnlockProgressDialog.setMessage(
+                    mContext.getString(R.string.kg_sim_unlock_progress_dialog_message));
+            mSimUnlockProgressDialog.setIndeterminate(true);
+            mSimUnlockProgressDialog.setCancelable(false);
+            if (!(mContext instanceof Activity)) {
+                mSimUnlockProgressDialog.getWindow().setType(
+                        WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+            }
+        }
+        return mSimUnlockProgressDialog;
+    }
+
+    @Override
+    protected void verifyPasswordAndUnlock() {
+        String entry = mPasswordEntry.getText().toString();
+        
+        if (entry.length() < 4) {
+            // otherwise, display a message to the user, and don't submit.
+            mSecurityMessageDisplay.setMessage(R.string.kg_invalid_sim_pin_hint, true);
+            mPasswordEntry.setText("");
+            mCallback.userActivity(0);
+            return;
+        }
+
+        getSimUnlockProgressDialog().show();
+
+        if (!mSimCheckInProgress) {
+            mSimCheckInProgress = true; // there should be only one
+            new CheckSimPin(mPasswordEntry.getText().toString()) {
+                void onSimCheckResponse(final boolean success) {
+                    post(new Runnable() {
+                        public void run() {
+                            if (mSimUnlockProgressDialog != null) {
+                                mSimUnlockProgressDialog.hide();
+                            }
+                            if (success) {
+                                // before closing the keyguard, report back that the sim is unlocked
+                                // so it knows right away.
+                                KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked();
+                                mCallback.dismiss(true);
+                            } else {
+                                mSecurityMessageDisplay.setMessage
+                                    (R.string.kg_password_wrong_pin_code, true);
+                                mPasswordEntry.setText("");
+                            }
+                            mCallback.userActivity(0);
+                            mSimCheckInProgress = false;
+                        }
+                    });
+                }
+            }.start();
+        }
+    }
+}
+
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java
new file mode 100644
index 0000000..e5b4b73
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java
@@ -0,0 +1,282 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.text.method.DigitsKeyListener;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.TextView.OnEditorActionListener;
+
+import com.android.internal.telephony.ITelephony;
+
+import com.android.internal.R;
+
+/**
+ * Displays a PIN pad for entering a PUK (Pin Unlock Kode) provided by a carrier.
+ */
+public class KeyguardSimPukView extends KeyguardAbsKeyInputView
+        implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
+
+    private ProgressDialog mSimUnlockProgressDialog = null;
+    private volatile boolean mCheckInProgress;
+    private String mPukText;
+    private String mPinText;
+    private StateMachine mStateMachine = new StateMachine();
+
+    private class StateMachine {
+        final int ENTER_PUK = 0;
+        final int ENTER_PIN = 1;
+        final int CONFIRM_PIN = 2;
+        final int DONE = 3;
+        private int state = ENTER_PUK;
+
+        public void next() {
+            int msg = 0;
+            if (state == ENTER_PUK) {
+                if (checkPuk()) {
+                    state = ENTER_PIN;
+                    msg = R.string.kg_puk_enter_pin_hint;
+                } else {
+                    msg = R.string.kg_invalid_sim_puk_hint;
+                }
+            } else if (state == ENTER_PIN) {
+                if (checkPin()) {
+                    state = CONFIRM_PIN;
+                    msg = R.string.kg_enter_confirm_pin_hint;
+                } else {
+                    msg = R.string.kg_invalid_sim_pin_hint;
+                }
+            } else if (state == CONFIRM_PIN) {
+                if (confirmPin()) {
+                    state = DONE;
+                    msg =
+                        com.android.internal.R.string.lockscreen_sim_unlock_progress_dialog_message;
+                    updateSim();
+                } else {
+                    state = ENTER_PIN; // try again?
+                    msg = R.string.kg_invalid_confirm_pin_hint;
+                }
+            }
+            mPasswordEntry.setText(null);
+            if (msg != 0) {
+                mSecurityMessageDisplay.setMessage(msg, true);
+            }
+        }
+
+        void reset() {
+            mPinText="";
+            mPukText="";
+            state = ENTER_PUK;
+            mSecurityMessageDisplay.setMessage(R.string.kg_puk_enter_puk_hint, true);
+            mPasswordEntry.requestFocus();
+        }
+    }
+
+    public KeyguardSimPukView(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardSimPukView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public void resetState() {
+        mStateMachine.reset();
+        mPasswordEntry.setEnabled(true);
+    }
+
+    @Override
+    protected int getPasswordTextViewId() {
+        return R.id.pinEntry;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        final View ok = findViewById(R.id.key_enter);
+        if (ok != null) {
+            ok.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    doHapticKeyClick();
+                    verifyPasswordAndUnlock();
+                }
+            });
+        }
+
+        // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
+        // not a separate view
+        View pinDelete = findViewById(R.id.delete_button);
+        if (pinDelete != null) {
+            pinDelete.setVisibility(View.VISIBLE);
+            pinDelete.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    CharSequence str = mPasswordEntry.getText();
+                    if (str.length() > 0) {
+                        mPasswordEntry.setText(str.subSequence(0, str.length()-1));
+                    }
+                    doHapticKeyClick();
+                }
+            });
+            pinDelete.setOnLongClickListener(new View.OnLongClickListener() {
+                public boolean onLongClick(View v) {
+                    mPasswordEntry.setText("");
+                    doHapticKeyClick();
+                    return true;
+                }
+            });
+        }
+
+        mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
+        mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
+                | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
+
+        mPasswordEntry.requestFocus();
+
+        mSecurityMessageDisplay.setTimeout(0); // don't show ownerinfo/charging status by default
+    }
+
+    @Override
+    public void showUsabilityHint() {
+    }
+
+    @Override
+    public void onPause() {
+        // dismiss the dialog.
+        if (mSimUnlockProgressDialog != null) {
+            mSimUnlockProgressDialog.dismiss();
+            mSimUnlockProgressDialog = null;
+        }
+    }
+
+    /**
+     * Since the IPC can block, we want to run the request in a separate thread
+     * with a callback.
+     */
+    private abstract class CheckSimPuk extends Thread {
+
+        private final String mPin, mPuk;
+
+        protected CheckSimPuk(String puk, String pin) {
+            mPuk = puk;
+            mPin = pin;
+        }
+
+        abstract void onSimLockChangedResponse(boolean success);
+
+        @Override
+        public void run() {
+            try {
+                final boolean result = ITelephony.Stub.asInterface(ServiceManager
+                        .checkService("phone")).supplyPuk(mPuk, mPin);
+
+                post(new Runnable() {
+                    public void run() {
+                        onSimLockChangedResponse(result);
+                    }
+                });
+            } catch (RemoteException e) {
+                post(new Runnable() {
+                    public void run() {
+                        onSimLockChangedResponse(false);
+                    }
+                });
+            }
+        }
+    }
+
+    private Dialog getSimUnlockProgressDialog() {
+        if (mSimUnlockProgressDialog == null) {
+            mSimUnlockProgressDialog = new ProgressDialog(mContext);
+            mSimUnlockProgressDialog.setMessage(
+                    mContext.getString(R.string.kg_sim_unlock_progress_dialog_message));
+            mSimUnlockProgressDialog.setIndeterminate(true);
+            mSimUnlockProgressDialog.setCancelable(false);
+            if (!(mContext instanceof Activity)) {
+                mSimUnlockProgressDialog.getWindow().setType(
+                        WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+            }
+        }
+        return mSimUnlockProgressDialog;
+    }
+
+    private boolean checkPuk() {
+        // make sure the puk is at least 8 digits long.
+        if (mPasswordEntry.getText().length() >= 8) {
+            mPukText = mPasswordEntry.getText().toString();
+            return true;
+        }
+        return false;
+    }
+
+    private boolean checkPin() {
+        // make sure the PIN is between 4 and 8 digits
+        int length = mPasswordEntry.getText().length();
+        if (length >= 4 && length <= 8) {
+            mPinText = mPasswordEntry.getText().toString();
+            return true;
+        }
+        return false;
+    }
+
+    public boolean confirmPin() {
+        return mPinText.equals(mPasswordEntry.getText().toString());
+    }
+
+    private void updateSim() {
+        getSimUnlockProgressDialog().show();
+
+        if (!mCheckInProgress) {
+            mCheckInProgress = true;
+            new CheckSimPuk(mPukText, mPinText) {
+                void onSimLockChangedResponse(final boolean success) {
+                    post(new Runnable() {
+                        public void run() {
+                            if (mSimUnlockProgressDialog != null) {
+                                mSimUnlockProgressDialog.hide();
+                            }
+                            if (success) {
+                                mCallback.dismiss(true);
+                            } else {
+                                mStateMachine.reset();
+                                mSecurityMessageDisplay.setMessage(R.string.kg_invalid_puk, true);
+                            }
+                            mCheckInProgress = false;
+                        }
+                    });
+                }
+            }.start();
+        }
+    }
+
+    @Override
+    protected void verifyPasswordAndUnlock() {
+        mStateMachine.next();
+    }
+}
+
+
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java
new file mode 100644
index 0000000..35b8509
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java
@@ -0,0 +1,151 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Typeface;
+import android.text.TextUtils;
+import android.text.format.DateFormat;
+import android.util.AttributeSet;
+import android.util.Slog;
+import android.view.View;
+import android.widget.GridLayout;
+import android.widget.TextView;
+
+import com.android.internal.R;
+import com.android.internal.widget.LockPatternUtils;
+
+import java.util.Date;
+
+public class KeyguardStatusView extends GridLayout {
+    private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
+    private static final String TAG = "KeyguardStatusView";
+
+    public static final int LOCK_ICON = 0; // R.drawable.ic_lock_idle_lock;
+    public static final int ALARM_ICON = com.android.internal.R.drawable.ic_lock_idle_alarm;
+    public static final int CHARGING_ICON = 0; //R.drawable.ic_lock_idle_charging;
+    public static final int BATTERY_LOW_ICON = 0; //R.drawable.ic_lock_idle_low_battery;
+
+    private CharSequence mDateFormatString;
+    private LockPatternUtils mLockPatternUtils;
+
+    private TextView mDateView;
+    private TextView mAlarmStatusView;
+    private ClockView mClockView;
+
+    private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
+
+        @Override
+        public void onTimeChanged() {
+            refresh();
+        }
+
+        @Override
+        void onKeyguardVisibilityChanged(boolean showing) {
+            if (showing) {
+                if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
+                refresh();
+            }
+        };
+    };
+
+    public KeyguardStatusView(Context context) {
+        this(context, null, 0);
+    }
+
+    public KeyguardStatusView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public KeyguardStatusView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        Resources res = getContext().getResources();
+        mDateFormatString =
+                res.getText(com.android.internal.R.string.abbrev_wday_month_day_no_year);
+        mDateView = (TextView) findViewById(R.id.date);
+        mAlarmStatusView = (TextView) findViewById(R.id.alarm_status);
+        mClockView = (ClockView) findViewById(R.id.clock_view);
+        mLockPatternUtils = new LockPatternUtils(getContext());
+
+        // Use custom font in mDateView
+        mDateView.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD);
+
+        // Required to get Marquee to work.
+        final View marqueeViews[] = { mDateView, mAlarmStatusView };
+        for (int i = 0; i < marqueeViews.length; i++) {
+            View v = marqueeViews[i];
+            if (v == null) {
+                throw new RuntimeException("Can't find widget at index " + i);
+            }
+            v.setSelected(true);
+        }
+        refresh();
+    }
+
+    protected void refresh() {
+        mClockView.updateTime();
+        refreshDate();
+        refreshAlarmStatus(); // might as well
+    }
+
+    void refreshAlarmStatus() {
+        // Update Alarm status
+        String nextAlarm = mLockPatternUtils.getNextAlarm();
+        if (!TextUtils.isEmpty(nextAlarm)) {
+            maybeSetUpperCaseText(mAlarmStatusView, nextAlarm);
+            mAlarmStatusView.setCompoundDrawablesWithIntrinsicBounds(ALARM_ICON, 0, 0, 0);
+            mAlarmStatusView.setVisibility(View.VISIBLE);
+        } else {
+            mAlarmStatusView.setVisibility(View.GONE);
+        }
+    }
+
+    void refreshDate() {
+        maybeSetUpperCaseText(mDateView, DateFormat.format(mDateFormatString, new Date()));
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mInfoCallback);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mInfoCallback);
+    }
+
+    public int getAppWidgetId() {
+        return LockPatternUtils.ID_DEFAULT_STATUS_WIDGET;
+    }
+
+    private void maybeSetUpperCaseText(TextView textView, CharSequence text) {
+        if (KeyguardViewManager.USE_UPPER_CASE
+                && textView.getId() != R.id.owner_info) { // currently only required for date view
+            textView.setText(text != null ? text.toString().toUpperCase() : null);
+        } else {
+            textView.setText(text);
+        }
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java
new file mode 100644
index 0000000..d284602
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java
@@ -0,0 +1,520 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard;
+
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.media.AudioManager;
+import android.media.IRemoteControlDisplay;
+import android.media.MediaMetadataRetriever;
+import android.media.RemoteControlClient;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.text.Spannable;
+import android.text.TextUtils;
+import android.text.style.ForegroundColorSpan;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.internal.R;
+
+import java.lang.ref.WeakReference;
+/**
+ * This is the widget responsible for showing music controls in keyguard.
+ */
+public class KeyguardTransportControlView extends FrameLayout implements OnClickListener {
+
+    private static final int MSG_UPDATE_STATE = 100;
+    private static final int MSG_SET_METADATA = 101;
+    private static final int MSG_SET_TRANSPORT_CONTROLS = 102;
+    private static final int MSG_SET_ARTWORK = 103;
+    private static final int MSG_SET_GENERATION_ID = 104;
+    private static final int DISPLAY_TIMEOUT_MS = 5000; // 5s
+    protected static final boolean DEBUG = false;
+    protected static final String TAG = "TransportControlView";
+
+    private ImageView mAlbumArt;
+    private TextView mTrackTitle;
+    private ImageView mBtnPrev;
+    private ImageView mBtnPlay;
+    private ImageView mBtnNext;
+    private int mClientGeneration;
+    private Metadata mMetadata = new Metadata();
+    private boolean mAttached;
+    private PendingIntent mClientIntent;
+    private int mTransportControlFlags;
+    private int mCurrentPlayState;
+    private AudioManager mAudioManager;
+    private IRemoteControlDisplayWeak mIRCD;
+    private boolean mMusicClientPresent = true;
+
+    /**
+     * The metadata which should be populated into the view once we've been attached
+     */
+    private Bundle mPopulateMetadataWhenAttached = null;
+
+    // This handler is required to ensure messages from IRCD are handled in sequence and on
+    // the UI thread.
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+            case MSG_UPDATE_STATE:
+                if (mClientGeneration == msg.arg1) updatePlayPauseState(msg.arg2);
+                break;
+
+            case MSG_SET_METADATA:
+                if (mClientGeneration == msg.arg1) updateMetadata((Bundle) msg.obj);
+                break;
+
+            case MSG_SET_TRANSPORT_CONTROLS:
+                if (mClientGeneration == msg.arg1) updateTransportControls(msg.arg2);
+                break;
+
+            case MSG_SET_ARTWORK:
+                if (mClientGeneration == msg.arg1) {
+                    if (mMetadata.bitmap != null) {
+                        mMetadata.bitmap.recycle();
+                    }
+                    mMetadata.bitmap = (Bitmap) msg.obj;
+                    mAlbumArt.setImageBitmap(mMetadata.bitmap);
+                }
+                break;
+
+            case MSG_SET_GENERATION_ID:
+                if (msg.arg2 != 0) {
+                    // This means nobody is currently registered. Hide the view.
+                    onListenerDetached();
+                } else {
+                    onListenerAttached();
+                }
+                if (DEBUG) Log.v(TAG, "New genId = " + msg.arg1 + ", clearing = " + msg.arg2);
+                mClientGeneration = msg.arg1;
+                mClientIntent = (PendingIntent) msg.obj;
+                break;
+
+            }
+        }
+    };
+    private KeyguardHostView.TransportCallback mTransportCallback;
+
+    /**
+     * This class is required to have weak linkage to the current TransportControlView
+     * because the remote process can hold a strong reference to this binder object and
+     * we can't predict when it will be GC'd in the remote process. Without this code, it
+     * would allow a heavyweight object to be held on this side of the binder when there's
+     * no requirement to run a GC on the other side.
+     */
+    private static class IRemoteControlDisplayWeak extends IRemoteControlDisplay.Stub {
+        private WeakReference<Handler> mLocalHandler;
+
+        IRemoteControlDisplayWeak(Handler handler) {
+            mLocalHandler = new WeakReference<Handler>(handler);
+        }
+
+        public void setPlaybackState(int generationId, int state, long stateChangeTimeMs) {
+            Handler handler = mLocalHandler.get();
+            if (handler != null) {
+                handler.obtainMessage(MSG_UPDATE_STATE, generationId, state).sendToTarget();
+            }
+        }
+
+        public void setMetadata(int generationId, Bundle metadata) {
+            Handler handler = mLocalHandler.get();
+            if (handler != null) {
+                handler.obtainMessage(MSG_SET_METADATA, generationId, 0, metadata).sendToTarget();
+            }
+        }
+
+        public void setTransportControlFlags(int generationId, int flags) {
+            Handler handler = mLocalHandler.get();
+            if (handler != null) {
+                handler.obtainMessage(MSG_SET_TRANSPORT_CONTROLS, generationId, flags)
+                        .sendToTarget();
+            }
+        }
+
+        public void setArtwork(int generationId, Bitmap bitmap) {
+            Handler handler = mLocalHandler.get();
+            if (handler != null) {
+                handler.obtainMessage(MSG_SET_ARTWORK, generationId, 0, bitmap).sendToTarget();
+            }
+        }
+
+        public void setAllMetadata(int generationId, Bundle metadata, Bitmap bitmap) {
+            Handler handler = mLocalHandler.get();
+            if (handler != null) {
+                handler.obtainMessage(MSG_SET_METADATA, generationId, 0, metadata).sendToTarget();
+                handler.obtainMessage(MSG_SET_ARTWORK, generationId, 0, bitmap).sendToTarget();
+            }
+        }
+
+        public void setCurrentClientId(int clientGeneration, PendingIntent mediaIntent,
+                boolean clearing) throws RemoteException {
+            Handler handler = mLocalHandler.get();
+            if (handler != null) {
+                handler.obtainMessage(MSG_SET_GENERATION_ID,
+                    clientGeneration, (clearing ? 1 : 0), mediaIntent).sendToTarget();
+            }
+        }
+    };
+
+    public KeyguardTransportControlView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        Log.v(TAG, "Create TCV " + this);
+        mAudioManager = new AudioManager(mContext);
+        mCurrentPlayState = RemoteControlClient.PLAYSTATE_NONE; // until we get a callback
+        mIRCD = new IRemoteControlDisplayWeak(mHandler);
+    }
+
+    protected void onListenerDetached() {
+        mMusicClientPresent = false;
+        if (DEBUG) Log.v(TAG, "onListenerDetached()");
+        if (mTransportCallback != null) {
+            mTransportCallback.onListenerDetached();
+        } else {
+            Log.w(TAG, "onListenerDetached: no callback");
+        }
+    }
+
+    private void onListenerAttached() {
+        mMusicClientPresent = true;
+        if (DEBUG) Log.v(TAG, "onListenerAttached()");
+        if (mTransportCallback != null) {
+            mTransportCallback.onListenerAttached();
+        } else {
+            Log.w(TAG, "onListenerAttached(): no callback");
+        }
+    }
+
+    private void updateTransportControls(int transportControlFlags) {
+        mTransportControlFlags = transportControlFlags;
+    }
+
+    @Override
+    public void onFinishInflate() {
+        super.onFinishInflate();
+        mTrackTitle = (TextView) findViewById(R.id.title);
+        mTrackTitle.setSelected(true); // enable marquee
+        mAlbumArt = (ImageView) findViewById(R.id.albumart);
+        mBtnPrev = (ImageView) findViewById(R.id.btn_prev);
+        mBtnPlay = (ImageView) findViewById(R.id.btn_play);
+        mBtnNext = (ImageView) findViewById(R.id.btn_next);
+        final View buttons[] = { mBtnPrev, mBtnPlay, mBtnNext };
+        for (View view : buttons) {
+            view.setOnClickListener(this);
+        }
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        if (DEBUG) Log.v(TAG, "onAttachToWindow()");
+        if (mPopulateMetadataWhenAttached != null) {
+            updateMetadata(mPopulateMetadataWhenAttached);
+            mPopulateMetadataWhenAttached = null;
+        }
+        if (!mAttached) {
+            if (DEBUG) Log.v(TAG, "Registering TCV " + this);
+            mAudioManager.registerRemoteControlDisplay(mIRCD);
+        }
+        mAttached = true;
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        if (DEBUG) Log.v(TAG, "onDetachFromWindow()");
+        super.onDetachedFromWindow();
+        if (mAttached) {
+            if (DEBUG) Log.v(TAG, "Unregistering TCV " + this);
+            mAudioManager.unregisterRemoteControlDisplay(mIRCD);
+        }
+        mAttached = false;
+    }
+
+    class Metadata {
+        private String artist;
+        private String trackTitle;
+        private String albumTitle;
+        private Bitmap bitmap;
+
+        public String toString() {
+            return "Metadata[artist=" + artist + " trackTitle=" + trackTitle + " albumTitle=" + albumTitle + "]";
+        }
+    }
+
+    private String getMdString(Bundle data, int id) {
+        return data.getString(Integer.toString(id));
+    }
+
+    private void updateMetadata(Bundle data) {
+        if (mAttached) {
+            mMetadata.artist = getMdString(data, MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST);
+            mMetadata.trackTitle = getMdString(data, MediaMetadataRetriever.METADATA_KEY_TITLE);
+            mMetadata.albumTitle = getMdString(data, MediaMetadataRetriever.METADATA_KEY_ALBUM);
+            populateMetadata();
+        } else {
+            mPopulateMetadataWhenAttached = data;
+        }
+    }
+
+    /**
+     * Populates the given metadata into the view
+     */
+    private void populateMetadata() {
+        StringBuilder sb = new StringBuilder();
+        int trackTitleLength = 0;
+        if (!TextUtils.isEmpty(mMetadata.trackTitle)) {
+            sb.append(mMetadata.trackTitle);
+            trackTitleLength = mMetadata.trackTitle.length();
+        }
+        if (!TextUtils.isEmpty(mMetadata.artist)) {
+            if (sb.length() != 0) {
+                sb.append(" - ");
+            }
+            sb.append(mMetadata.artist);
+        }
+        if (!TextUtils.isEmpty(mMetadata.albumTitle)) {
+            if (sb.length() != 0) {
+                sb.append(" - ");
+            }
+            sb.append(mMetadata.albumTitle);
+        }
+        mTrackTitle.setText(sb.toString(), TextView.BufferType.SPANNABLE);
+        Spannable str = (Spannable) mTrackTitle.getText();
+        if (trackTitleLength != 0) {
+            str.setSpan(new ForegroundColorSpan(0xffffffff), 0, trackTitleLength,
+                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            trackTitleLength++;
+        }
+        if (sb.length() > trackTitleLength) {
+            str.setSpan(new ForegroundColorSpan(0x7fffffff), trackTitleLength, sb.length(),
+                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+        }
+
+        mAlbumArt.setImageBitmap(mMetadata.bitmap);
+        final int flags = mTransportControlFlags;
+        setVisibilityBasedOnFlag(mBtnPrev, flags, RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS);
+        setVisibilityBasedOnFlag(mBtnNext, flags, RemoteControlClient.FLAG_KEY_MEDIA_NEXT);
+        setVisibilityBasedOnFlag(mBtnPlay, flags,
+                RemoteControlClient.FLAG_KEY_MEDIA_PLAY
+                | RemoteControlClient.FLAG_KEY_MEDIA_PAUSE
+                | RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE
+                | RemoteControlClient.FLAG_KEY_MEDIA_STOP);
+
+        updatePlayPauseState(mCurrentPlayState);
+    }
+
+    public boolean isMusicPlaying() {
+       return mCurrentPlayState == RemoteControlClient.PLAYSTATE_PLAYING
+               || mCurrentPlayState == RemoteControlClient.PLAYSTATE_BUFFERING;
+    }
+
+    private static void setVisibilityBasedOnFlag(View view, int flags, int flag) {
+        if ((flags & flag) != 0) {
+            view.setVisibility(View.VISIBLE);
+        } else {
+            view.setVisibility(View.GONE);
+        }
+    }
+
+    private void updatePlayPauseState(int state) {
+        if (DEBUG) Log.v(TAG,
+                "updatePlayPauseState(), old=" + mCurrentPlayState + ", state=" + state);
+        if (state == mCurrentPlayState) {
+            return;
+        }
+        final int imageResId;
+        final int imageDescId;
+        switch (state) {
+            case RemoteControlClient.PLAYSTATE_ERROR:
+                imageResId = com.android.internal.R.drawable.stat_sys_warning;
+                // TODO use more specific image description string for warning, but here the "play"
+                //      message is still valid because this button triggers a play command.
+                imageDescId = com.android.internal.R.string.lockscreen_transport_play_description;
+                break;
+
+            case RemoteControlClient.PLAYSTATE_PLAYING:
+                imageResId = com.android.internal.R.drawable.ic_media_pause;
+                imageDescId = com.android.internal.R.string.lockscreen_transport_pause_description;
+                break;
+
+            case RemoteControlClient.PLAYSTATE_BUFFERING:
+                imageResId = com.android.internal.R.drawable.ic_media_stop;
+                imageDescId = com.android.internal.R.string.lockscreen_transport_stop_description;
+                break;
+
+            case RemoteControlClient.PLAYSTATE_PAUSED:
+            default:
+                imageResId = com.android.internal.R.drawable.ic_media_play;
+                imageDescId = com.android.internal.R.string.lockscreen_transport_play_description;
+                break;
+        }
+        mBtnPlay.setImageResource(imageResId);
+        mBtnPlay.setContentDescription(getResources().getString(imageDescId));
+        mCurrentPlayState = state;
+        mTransportCallback.onPlayStateChanged();
+    }
+
+    static class SavedState extends BaseSavedState {
+        boolean clientPresent;
+
+        SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        private SavedState(Parcel in) {
+            super(in);
+            this.clientPresent = in.readInt() != 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            super.writeToParcel(out, flags);
+            out.writeInt(this.clientPresent ? 1 : 0);
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR
+                = new Parcelable.Creator<SavedState>() {
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+
+    @Override
+    public Parcelable onSaveInstanceState() {
+        Parcelable superState = super.onSaveInstanceState();
+        SavedState ss = new SavedState(superState);
+        ss.clientPresent = mMusicClientPresent;
+        return ss;
+    }
+
+    @Override
+    public void onRestoreInstanceState(Parcelable state) {
+        if (!(state instanceof SavedState)) {
+            super.onRestoreInstanceState(state);
+            return;
+        }
+        SavedState ss = (SavedState) state;
+        super.onRestoreInstanceState(ss.getSuperState());
+        if (ss.clientPresent) {
+            if (DEBUG) Log.v(TAG, "Reattaching client because it was attached");
+            onListenerAttached();
+        }
+    }
+
+    public void onClick(View v) {
+        int keyCode = -1;
+        if (v == mBtnPrev) {
+            keyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS;
+        } else if (v == mBtnNext) {
+            keyCode = KeyEvent.KEYCODE_MEDIA_NEXT;
+        } else if (v == mBtnPlay) {
+            keyCode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
+
+        }
+        if (keyCode != -1) {
+            sendMediaButtonClick(keyCode);
+        }
+    }
+
+    private void sendMediaButtonClick(int keyCode) {
+        if (mClientIntent == null) {
+            // Shouldn't be possible because this view should be hidden in this case.
+            Log.e(TAG, "sendMediaButtonClick(): No client is currently registered");
+            return;
+        }
+        // use the registered PendingIntent that will be processed by the registered
+        //    media button event receiver, which is the component of mClientIntent
+        KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
+        Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+        intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
+        try {
+            mClientIntent.send(getContext(), 0, intent);
+        } catch (CanceledException e) {
+            Log.e(TAG, "Error sending intent for media button down: "+e);
+            e.printStackTrace();
+        }
+
+        keyEvent = new KeyEvent(KeyEvent.ACTION_UP, keyCode);
+        intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+        intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
+        try {
+            mClientIntent.send(getContext(), 0, intent);
+        } catch (CanceledException e) {
+            Log.e(TAG, "Error sending intent for media button up: "+e);
+            e.printStackTrace();
+        }
+    }
+
+    public boolean providesClock() {
+        return false;
+    }
+
+    private boolean wasPlayingRecently(int state, long stateChangeTimeMs) {
+        switch (state) {
+            case RemoteControlClient.PLAYSTATE_PLAYING:
+            case RemoteControlClient.PLAYSTATE_FAST_FORWARDING:
+            case RemoteControlClient.PLAYSTATE_REWINDING:
+            case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS:
+            case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS:
+            case RemoteControlClient.PLAYSTATE_BUFFERING:
+                // actively playing or about to play
+                return true;
+            case RemoteControlClient.PLAYSTATE_NONE:
+                return false;
+            case RemoteControlClient.PLAYSTATE_STOPPED:
+            case RemoteControlClient.PLAYSTATE_PAUSED:
+            case RemoteControlClient.PLAYSTATE_ERROR:
+                // we have stopped playing, check how long ago
+                if (DEBUG) {
+                    if ((SystemClock.elapsedRealtime() - stateChangeTimeMs) < DISPLAY_TIMEOUT_MS) {
+                        Log.v(TAG, "wasPlayingRecently: time < TIMEOUT was playing recently");
+                    } else {
+                        Log.v(TAG, "wasPlayingRecently: time > TIMEOUT");
+                    }
+                }
+                return ((SystemClock.elapsedRealtime() - stateChangeTimeMs) < DISPLAY_TIMEOUT_MS);
+            default:
+                Log.e(TAG, "Unknown playback state " + state + " in wasPlayingRecently()");
+                return false;
+        }
+    }
+
+    public void setKeyguardCallback(KeyguardHostView.TransportCallback transportCallback) {
+        mTransportCallback = transportCallback;
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
new file mode 100644
index 0000000..1968ecd
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
@@ -0,0 +1,821 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard;
+
+import android.app.ActivityManagerNative;
+import android.app.IUserSwitchObserver;
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import static android.os.BatteryManager.BATTERY_STATUS_FULL;
+import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
+import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
+import static android.os.BatteryManager.EXTRA_STATUS;
+import static android.os.BatteryManager.EXTRA_PLUGGED;
+import static android.os.BatteryManager.EXTRA_LEVEL;
+import static android.os.BatteryManager.EXTRA_HEALTH;
+import android.media.AudioManager;
+import android.os.BatteryManager;
+import android.os.Handler;
+import android.os.IRemoteCallback;
+import android.os.Message;
+import android.os.RemoteException;
+import android.provider.Settings;
+
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.TelephonyIntents;
+
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import com.android.internal.R;
+import com.google.android.collect.Lists;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+
+/**
+ * Watches for updates that may be interesting to the keyguard, and provides
+ * the up to date information as well as a registration for callbacks that care
+ * to be updated.
+ *
+ * Note: under time crunch, this has been extended to include some stuff that
+ * doesn't really belong here.  see {@link #handleBatteryUpdate} where it shutdowns
+ * the device, and {@link #getFailedUnlockAttempts()}, {@link #reportFailedAttempt()}
+ * and {@link #clearFailedUnlockAttempts()}.  Maybe we should rename this 'KeyguardContext'...
+ */
+public class KeyguardUpdateMonitor {
+
+    private static final String TAG = "KeyguardUpdateMonitor";
+    private static final boolean DEBUG = false;
+    private static final boolean DEBUG_SIM_STATES = DEBUG || false;
+    private static final int FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 3;
+    private static final int LOW_BATTERY_THRESHOLD = 20;
+
+    // Callback messages
+    private static final int MSG_TIME_UPDATE = 301;
+    private static final int MSG_BATTERY_UPDATE = 302;
+    private static final int MSG_CARRIER_INFO_UPDATE = 303;
+    private static final int MSG_SIM_STATE_CHANGE = 304;
+    private static final int MSG_RINGER_MODE_CHANGED = 305;
+    private static final int MSG_PHONE_STATE_CHANGED = 306;
+    private static final int MSG_CLOCK_VISIBILITY_CHANGED = 307;
+    private static final int MSG_DEVICE_PROVISIONED = 308;
+    private static final int MSG_DPM_STATE_CHANGED = 309;
+    private static final int MSG_USER_SWITCHED = 310;
+    private static final int MSG_USER_REMOVED = 311;
+    private static final int MSG_KEYGUARD_VISIBILITY_CHANGED = 312;
+    protected static final int MSG_BOOT_COMPLETED = 313;
+
+
+    private static KeyguardUpdateMonitor sInstance;
+
+    private final Context mContext;
+
+    // Telephony state
+    private IccCardConstants.State mSimState = IccCardConstants.State.READY;
+    private CharSequence mTelephonyPlmn;
+    private CharSequence mTelephonySpn;
+    private int mRingMode;
+    private int mPhoneState;
+    private boolean mKeyguardIsVisible;
+    private boolean mBootCompleted;
+
+    // Device provisioning state
+    private boolean mDeviceProvisioned;
+
+    // Battery status
+    private BatteryStatus mBatteryStatus;
+
+    // Password attempts
+    private int mFailedAttempts = 0;
+    private int mFailedBiometricUnlockAttempts = 0;
+
+    private boolean mAlternateUnlockEnabled;
+
+    private boolean mClockVisible;
+
+    private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
+            mCallbacks = Lists.newArrayList();
+    private ContentObserver mContentObserver;
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_TIME_UPDATE:
+                    handleTimeUpdate();
+                    break;
+                case MSG_BATTERY_UPDATE:
+                    handleBatteryUpdate((BatteryStatus) msg.obj);
+                    break;
+                case MSG_CARRIER_INFO_UPDATE:
+                    handleCarrierInfoUpdate();
+                    break;
+                case MSG_SIM_STATE_CHANGE:
+                    handleSimStateChange((SimArgs) msg.obj);
+                    break;
+                case MSG_RINGER_MODE_CHANGED:
+                    handleRingerModeChange(msg.arg1);
+                    break;
+                case MSG_PHONE_STATE_CHANGED:
+                    handlePhoneStateChanged((String)msg.obj);
+                    break;
+                case MSG_CLOCK_VISIBILITY_CHANGED:
+                    handleClockVisibilityChanged();
+                    break;
+                case MSG_DEVICE_PROVISIONED:
+                    handleDeviceProvisioned();
+                    break;
+                case MSG_DPM_STATE_CHANGED:
+                    handleDevicePolicyManagerStateChanged();
+                    break;
+                case MSG_USER_SWITCHED:
+                    handleUserSwitched(msg.arg1, (IRemoteCallback)msg.obj);
+                    break;
+                case MSG_USER_REMOVED:
+                    handleUserRemoved(msg.arg1);
+                    break;
+                case MSG_KEYGUARD_VISIBILITY_CHANGED:
+                    handleKeyguardVisibilityChanged(msg.arg1);
+                    break;
+                case MSG_BOOT_COMPLETED:
+                    handleBootCompleted();
+                    break;
+
+            }
+        }
+    };
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            if (DEBUG) Log.d(TAG, "received broadcast " + action);
+
+            if (Intent.ACTION_TIME_TICK.equals(action)
+                    || Intent.ACTION_TIME_CHANGED.equals(action)
+                    || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_TIME_UPDATE));
+            } else if (TelephonyIntents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
+                mTelephonyPlmn = getTelephonyPlmnFrom(intent);
+                mTelephonySpn = getTelephonySpnFrom(intent);
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_CARRIER_INFO_UPDATE));
+            } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
+                final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
+                final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
+                final int level = intent.getIntExtra(EXTRA_LEVEL, 0);
+                final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
+                final Message msg = mHandler.obtainMessage(
+                        MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health));
+                mHandler.sendMessage(msg);
+            } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
+                if (DEBUG_SIM_STATES) {
+                    Log.v(TAG, "action " + action + " state" +
+                        intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE));
+                }
+                mHandler.sendMessage(mHandler.obtainMessage(
+                        MSG_SIM_STATE_CHANGE, SimArgs.fromIntent(intent)));
+            } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
+                        intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
+            } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
+                String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
+            } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
+                    .equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_DPM_STATE_CHANGED));
+            } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_REMOVED,
+                       intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
+            } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_BOOT_COMPLETED));
+            }
+        }
+    };
+
+    /**
+     * When we receive a
+     * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
+     * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange},
+     * we need a single object to pass to the handler.  This class helps decode
+     * the intent and provide a {@link SimCard.State} result.
+     */
+    private static class SimArgs {
+        public final IccCardConstants.State simState;
+
+        SimArgs(IccCardConstants.State state) {
+            simState = state;
+        }
+
+        static SimArgs fromIntent(Intent intent) {
+            IccCardConstants.State state;
+            if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
+                throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
+            }
+            String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
+            if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
+                final String absentReason = intent
+                    .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
+
+                if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
+                        absentReason)) {
+                    state = IccCardConstants.State.PERM_DISABLED;
+                } else {
+                    state = IccCardConstants.State.ABSENT;
+                }
+            } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
+                state = IccCardConstants.State.READY;
+            } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+                final String lockedReason = intent
+                        .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
+                if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
+                    state = IccCardConstants.State.PIN_REQUIRED;
+                } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
+                    state = IccCardConstants.State.PUK_REQUIRED;
+                } else {
+                    state = IccCardConstants.State.UNKNOWN;
+                }
+            } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
+                state = IccCardConstants.State.NETWORK_LOCKED;
+            } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)
+                        || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
+                // This is required because telephony doesn't return to "READY" after
+                // these state transitions. See bug 7197471.
+                state = IccCardConstants.State.READY;
+            } else {
+                state = IccCardConstants.State.UNKNOWN;
+            }
+            return new SimArgs(state);
+        }
+
+        public String toString() {
+            return simState.toString();
+        }
+    }
+
+    /* package */ static class BatteryStatus {
+        public final int status;
+        public final int level;
+        public final int plugged;
+        public final int health;
+        public BatteryStatus(int status, int level, int plugged, int health) {
+            this.status = status;
+            this.level = level;
+            this.plugged = plugged;
+            this.health = health;
+        }
+
+        /**
+         * Determine whether the device is plugged in (USB, power, or wireless).
+         * @return true if the device is plugged in.
+         */
+        boolean isPluggedIn() {
+            return plugged == BatteryManager.BATTERY_PLUGGED_AC
+                    || plugged == BatteryManager.BATTERY_PLUGGED_USB
+                    || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
+        }
+
+        /**
+         * Whether or not the device is charged. Note that some devices never return 100% for
+         * battery level, so this allows either battery level or status to determine if the
+         * battery is charged.
+         * @return true if the device is charged
+         */
+        public boolean isCharged() {
+            return status == BATTERY_STATUS_FULL || level >= 100;
+        }
+
+        /**
+         * Whether battery is low and needs to be charged.
+         * @return true if battery is low
+         */
+        public boolean isBatteryLow() {
+            return level < LOW_BATTERY_THRESHOLD;
+        }
+
+    }
+
+    public static KeyguardUpdateMonitor getInstance(Context context) {
+        if (sInstance == null) {
+            sInstance = new KeyguardUpdateMonitor(context);
+        }
+        return sInstance;
+    }
+
+    private KeyguardUpdateMonitor(Context context) {
+        mContext = context;
+
+        mDeviceProvisioned = Settings.Global.getInt(
+                mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+
+        // Since device can't be un-provisioned, we only need to register a content observer
+        // to update mDeviceProvisioned when we are...
+        if (!mDeviceProvisioned) {
+            watchForDeviceProvisioning();
+        }
+
+        // Take a guess at initial SIM state, battery status and PLMN until we get an update
+        mSimState = IccCardConstants.State.NOT_READY;
+        mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0);
+        mTelephonyPlmn = getDefaultPlmn();
+
+        // Watch for interesting updates
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_TIME_TICK);
+        filter.addAction(Intent.ACTION_TIME_CHANGED);
+        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
+        filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
+        filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
+        filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+        filter.addAction(Intent.ACTION_USER_REMOVED);
+        context.registerReceiver(mBroadcastReceiver, filter);
+
+        final IntentFilter bootCompleteFilter = new IntentFilter();
+        bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
+        context.registerReceiver(mBroadcastReceiver, bootCompleteFilter);
+
+        try {
+            ActivityManagerNative.getDefault().registerUserSwitchObserver(
+                    new IUserSwitchObserver.Stub() {
+                        @Override
+                        public void onUserSwitching(int newUserId, IRemoteCallback reply) {
+                            mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED,
+                                    newUserId, 0, reply));
+                        }
+                        @Override
+                        public void onUserSwitchComplete(int newUserId) throws RemoteException {
+                        }
+                    });
+        } catch (RemoteException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+    }
+
+    private void watchForDeviceProvisioning() {
+        mContentObserver = new ContentObserver(mHandler) {
+            @Override
+            public void onChange(boolean selfChange) {
+                super.onChange(selfChange);
+                mDeviceProvisioned = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+                if (mDeviceProvisioned) {
+                    mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
+                }
+                if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
+            }
+        };
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
+                false, mContentObserver);
+
+        // prevent a race condition between where we check the flag and where we register the
+        // observer by grabbing the value once again...
+        boolean provisioned = Settings.Global.getInt(mContext.getContentResolver(),
+            Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+        if (provisioned != mDeviceProvisioned) {
+            mDeviceProvisioned = provisioned;
+            if (mDeviceProvisioned) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
+            }
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_DPM_STATE_CHANGED}
+     */
+    protected void handleDevicePolicyManagerStateChanged() {
+        for (int i = mCallbacks.size() - 1; i >= 0; i--) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onDevicePolicyManagerStateChanged();
+            }
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_USER_SWITCHED}
+     */
+    protected void handleUserSwitched(int userId, IRemoteCallback reply) {
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onUserSwitched(userId);
+            }
+        }
+        setAlternateUnlockEnabled(false);
+        try {
+            reply.sendResult(null);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_BOOT_COMPLETED}
+     */
+    protected void handleBootCompleted() {
+        mBootCompleted = true;
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onBootCompleted();
+            }
+        }
+    }
+
+    /**
+     * We need to store this state in the KeyguardUpdateMonitor since this class will not be 
+     * destroyed.
+     */
+    public boolean hasBootCompleted() {
+        return mBootCompleted;
+    }
+
+    /**
+     * Handle {@link #MSG_USER_SWITCHED}
+     */
+    protected void handleUserRemoved(int userId) {
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onUserRemoved(userId);
+            }
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_DEVICE_PROVISIONED}
+     */
+    protected void handleDeviceProvisioned() {
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onDeviceProvisioned();
+            }
+        }
+        if (mContentObserver != null) {
+            // We don't need the observer anymore...
+            mContext.getContentResolver().unregisterContentObserver(mContentObserver);
+            mContentObserver = null;
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_PHONE_STATE_CHANGED}
+     */
+    protected void handlePhoneStateChanged(String newState) {
+        if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
+        if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
+            mPhoneState = TelephonyManager.CALL_STATE_IDLE;
+        } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
+            mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
+        } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
+            mPhoneState = TelephonyManager.CALL_STATE_RINGING;
+        }
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onPhoneStateChanged(mPhoneState);
+            }
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_RINGER_MODE_CHANGED}
+     */
+    protected void handleRingerModeChange(int mode) {
+        if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
+        mRingMode = mode;
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onRingerModeChanged(mode);
+            }
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_TIME_UPDATE}
+     */
+    private void handleTimeUpdate() {
+        if (DEBUG) Log.d(TAG, "handleTimeUpdate");
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onTimeChanged();
+            }
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_BATTERY_UPDATE}
+     */
+    private void handleBatteryUpdate(BatteryStatus status) {
+        if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
+        final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
+        mBatteryStatus = status;
+        if (batteryUpdateInteresting) {
+            for (int i = 0; i < mCallbacks.size(); i++) {
+                KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+                if (cb != null) {
+                    cb.onRefreshBatteryInfo(status);
+                }
+            }
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_CARRIER_INFO_UPDATE}
+     */
+    private void handleCarrierInfoUpdate() {
+        if (DEBUG) Log.d(TAG, "handleCarrierInfoUpdate: plmn = " + mTelephonyPlmn
+            + ", spn = " + mTelephonySpn);
+
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
+            }
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_SIM_STATE_CHANGE}
+     */
+    private void handleSimStateChange(SimArgs simArgs) {
+        final IccCardConstants.State state = simArgs.simState;
+
+        if (DEBUG) {
+            Log.d(TAG, "handleSimStateChange: intentValue = " + simArgs + " "
+                    + "state resolved to " + state.toString());
+        }
+
+        if (state != IccCardConstants.State.UNKNOWN && state != mSimState) {
+            mSimState = state;
+            for (int i = 0; i < mCallbacks.size(); i++) {
+                KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+                if (cb != null) {
+                    cb.onSimStateChanged(state);
+                }
+            }
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_CLOCK_VISIBILITY_CHANGED}
+     */
+    private void handleClockVisibilityChanged() {
+        if (DEBUG) Log.d(TAG, "handleClockVisibilityChanged()");
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onClockVisibilityChanged();
+            }
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED}
+     */
+    private void handleKeyguardVisibilityChanged(int showing) {
+        if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")");
+        boolean isShowing = (showing == 1);
+        mKeyguardIsVisible = isShowing;
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onKeyguardVisibilityChanged(isShowing);
+            }
+        }
+    }
+
+    public boolean isKeyguardVisible() {
+        return mKeyguardIsVisible;
+    }
+
+    private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
+        final boolean nowPluggedIn = current.isPluggedIn();
+        final boolean wasPluggedIn = old.isPluggedIn();
+        final boolean stateChangedWhilePluggedIn =
+            wasPluggedIn == true && nowPluggedIn == true
+            && (old.status != current.status);
+
+        // change in plug state is always interesting
+        if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
+            return true;
+        }
+
+        // change in battery level while plugged in
+        if (nowPluggedIn && old.level != current.level) {
+            return true;
+        }
+
+        // change where battery needs charging
+        if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * @param intent The intent with action {@link TelephonyIntents#SPN_STRINGS_UPDATED_ACTION}
+     * @return The string to use for the plmn, or null if it should not be shown.
+     */
+    private CharSequence getTelephonyPlmnFrom(Intent intent) {
+        if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false)) {
+            final String plmn = intent.getStringExtra(TelephonyIntents.EXTRA_PLMN);
+            return (plmn != null) ? plmn : getDefaultPlmn();
+        }
+        return null;
+    }
+
+    /**
+     * @return The default plmn (no service)
+     */
+    private CharSequence getDefaultPlmn() {
+        return mContext.getResources().getText(R.string.lockscreen_carrier_default);
+    }
+
+    /**
+     * @param intent The intent with action {@link Telephony.Intents#SPN_STRINGS_UPDATED_ACTION}
+     * @return The string to use for the plmn, or null if it should not be shown.
+     */
+    private CharSequence getTelephonySpnFrom(Intent intent) {
+        if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false)) {
+            final String spn = intent.getStringExtra(TelephonyIntents.EXTRA_SPN);
+            if (spn != null) {
+                return spn;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Remove the given observer's callback.
+     *
+     * @param callback The callback to remove
+     */
+    public void removeCallback(KeyguardUpdateMonitorCallback callback) {
+        if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback);
+        for (int i = mCallbacks.size() - 1; i >= 0; i--) {
+            if (mCallbacks.get(i).get() == callback) {
+                mCallbacks.remove(i);
+            }
+        }
+    }
+
+    /**
+     * Register to receive notifications about general keyguard information
+     * (see {@link InfoCallback}.
+     * @param callback The callback to register
+     */
+    public void registerCallback(KeyguardUpdateMonitorCallback callback) {
+        if (DEBUG) Log.v(TAG, "*** register callback for " + callback);
+        // Prevent adding duplicate callbacks
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            if (mCallbacks.get(i).get() == callback) {
+                if (DEBUG) Log.e(TAG, "Object tried to add another callback",
+                        new Exception("Called by"));
+                return;
+            }
+        }
+        mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback));
+        removeCallback(null); // remove unused references
+        sendUpdates(callback);
+    }
+
+    private void sendUpdates(KeyguardUpdateMonitorCallback callback) {
+        // Notify listener of the current state
+        callback.onRefreshBatteryInfo(mBatteryStatus);
+        callback.onTimeChanged();
+        callback.onRingerModeChanged(mRingMode);
+        callback.onPhoneStateChanged(mPhoneState);
+        callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
+        callback.onClockVisibilityChanged();
+        callback.onSimStateChanged(mSimState);
+    }
+
+    public void sendKeyguardVisibilityChanged(boolean showing) {
+        if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")");
+        Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED);
+        message.arg1 = showing ? 1 : 0;
+        message.sendToTarget();
+    }
+
+    public void reportClockVisible(boolean visible) {
+        mClockVisible = visible;
+        mHandler.obtainMessage(MSG_CLOCK_VISIBILITY_CHANGED).sendToTarget();
+    }
+
+    public IccCardConstants.State getSimState() {
+        return mSimState;
+    }
+
+    /**
+     * Report that the user successfully entered the SIM PIN or PUK/SIM PIN so we
+     * have the information earlier than waiting for the intent
+     * broadcast from the telephony code.
+     *
+     * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
+     * through mHandler, this *must* be called from the UI thread.
+     */
+    public void reportSimUnlocked() {
+        handleSimStateChange(new SimArgs(IccCardConstants.State.READY));
+    }
+
+    public CharSequence getTelephonyPlmn() {
+        return mTelephonyPlmn;
+    }
+
+    public CharSequence getTelephonySpn() {
+        return mTelephonySpn;
+    }
+
+    /**
+     * @return Whether the device is provisioned (whether they have gone through
+     *   the setup wizard)
+     */
+    public boolean isDeviceProvisioned() {
+        return mDeviceProvisioned;
+    }
+
+    public int getFailedUnlockAttempts() {
+        return mFailedAttempts;
+    }
+
+    public void clearFailedUnlockAttempts() {
+        mFailedAttempts = 0;
+        mFailedBiometricUnlockAttempts = 0;
+    }
+
+    public void reportFailedUnlockAttempt() {
+        mFailedAttempts++;
+    }
+
+    public boolean isClockVisible() {
+        return mClockVisible;
+    }
+
+    public int getPhoneState() {
+        return mPhoneState;
+    }
+
+    public void reportFailedBiometricUnlockAttempt() {
+        mFailedBiometricUnlockAttempts++;
+    }
+
+    public boolean getMaxBiometricUnlockAttemptsReached() {
+        return mFailedBiometricUnlockAttempts >= FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP;
+    }
+
+    public boolean isAlternateUnlockEnabled() {
+        return mAlternateUnlockEnabled;
+    }
+
+    public void setAlternateUnlockEnabled(boolean enabled) {
+        mAlternateUnlockEnabled = enabled;
+    }
+
+    public boolean isSimLocked() {
+        return isSimLocked(mSimState);
+    }
+
+    public static boolean isSimLocked(IccCardConstants.State state) {
+        return state == IccCardConstants.State.PIN_REQUIRED
+        || state == IccCardConstants.State.PUK_REQUIRED
+        || state == IccCardConstants.State.PERM_DISABLED;
+    }
+
+    public boolean isSimPinSecure() {
+        return isSimPinSecure(mSimState);
+    }
+
+    public static boolean isSimPinSecure(IccCardConstants.State state) {
+        final IccCardConstants.State simState = state;
+        return (simState == IccCardConstants.State.PIN_REQUIRED
+                || simState == IccCardConstants.State.PUK_REQUIRED
+                || simState == IccCardConstants.State.PERM_DISABLED);
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java
new file mode 100644
index 0000000..1ba1388
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java
@@ -0,0 +1,110 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.app.admin.DevicePolicyManager;
+import android.media.AudioManager;
+
+import com.android.internal.telephony.IccCardConstants;
+
+/**
+ * Callback for general information relevant to lock screen.
+ */
+class KeyguardUpdateMonitorCallback {
+    /**
+     * Called when the battery status changes, e.g. when plugged in or unplugged, charge
+     * level, etc. changes.
+     *
+     * @param status current battery status
+     */
+    void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) { }
+
+    /**
+     * Called once per minute or when the time changes.
+     */
+    void onTimeChanged() { }
+
+    /**
+     * Called when the carrier PLMN or SPN changes.
+     *
+     * @param plmn The operator name of the registered network.  May be null if it shouldn't
+     *   be displayed.
+     * @param spn The service provider name.  May be null if it shouldn't be displayed.
+     */
+    void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { }
+
+    /**
+     * Called when the ringer mode changes.
+     * @param state the current ringer state, as defined in
+     * {@link AudioManager#RINGER_MODE_CHANGED_ACTION}
+     */
+    void onRingerModeChanged(int state) { }
+
+    /**
+     * Called when the phone state changes. String will be one of:
+     * {@link TelephonyManager#EXTRA_STATE_IDLE}
+     * {@link TelephonyManager@EXTRA_STATE_RINGING}
+     * {@link TelephonyManager#EXTRA_STATE_OFFHOOK
+     */
+    void onPhoneStateChanged(int phoneState) { }
+
+    /**
+     * Called when the visibility of the keyguard changes.
+     * @param showing Indicates if the keyguard is now visible.
+     */
+    void onKeyguardVisibilityChanged(boolean showing) { }
+
+    /**
+     * Called when visibility of lockscreen clock changes, such as when
+     * obscured by a widget.
+     */
+    void onClockVisibilityChanged() { }
+
+    /**
+     * Called when the device becomes provisioned
+     */
+    void onDeviceProvisioned() { }
+
+    /**
+     * Called when the device policy changes.
+     * See {@link DevicePolicyManager#ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED}
+     */
+    void onDevicePolicyManagerStateChanged() { }
+
+    /**
+     * Called when the user changes.
+     */
+    void onUserSwitched(int userId) { }
+
+    /**
+     * Called when the SIM state changes.
+     * @param simState
+     */
+    void onSimStateChanged(IccCardConstants.State simState) { }
+
+    /**
+     * Called when a user is removed.
+     */
+    void onUserRemoved(int userId) { }
+
+    /**
+     * Called when boot completed.
+     *
+     * Note, this callback will only be received if boot complete occurs after registering with
+     * KeyguardUpdateMonitor.
+     */
+    void onBootCompleted() { }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewBase.java
new file mode 100644
index 0000000..6fcacd3
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewBase.java
@@ -0,0 +1,264 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.media.AudioManager;
+import android.media.IAudioService;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.telephony.TelephonyManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Slog;
+import android.view.KeyEvent;
+import android.widget.FrameLayout;
+
+/**
+ * Base class for keyguard view.  {@link #reset} is where you should
+ * reset the state of your view.  Use the {@link KeyguardViewCallback} via
+ * {@link #getCallback()} to send information back (such as poking the wake lock,
+ * or finishing the keyguard).
+ *
+ * Handles intercepting of media keys that still work when the keyguard is
+ * showing.
+ */
+public abstract class KeyguardViewBase extends FrameLayout {
+
+    private static final int BACKGROUND_COLOR = 0x70000000;
+    private AudioManager mAudioManager;
+    private TelephonyManager mTelephonyManager = null;
+    protected KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
+
+    // Whether the volume keys should be handled by keyguard. If true, then
+    // they will be handled here for specific media types such as music, otherwise
+    // the audio service will bring up the volume dialog.
+    private static final boolean KEYGUARD_MANAGES_VOLUME = true;
+
+    // This is a faster way to draw the background on devices without hardware acceleration
+    private static final Drawable mBackgroundDrawable = new Drawable() {
+        @Override
+        public void draw(Canvas canvas) {
+            canvas.drawColor(BACKGROUND_COLOR, PorterDuff.Mode.SRC);
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {
+        }
+
+        @Override
+        public int getOpacity() {
+            return PixelFormat.TRANSLUCENT;
+        }
+    };
+
+    public KeyguardViewBase(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardViewBase(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        resetBackground();
+    }
+
+    public void resetBackground() {
+        setBackground(mBackgroundDrawable);
+    }
+
+    /**
+     * Called when you need to reset the state of your view.
+     */
+    abstract public void reset();
+
+    /**
+     * Called when the screen turned off.
+     */
+    abstract public void onScreenTurnedOff();
+
+    /**
+     * Called when the screen turned on.
+     */
+    abstract public void onScreenTurnedOn();
+
+    /**
+     * Called when the view needs to be shown.
+     */
+    abstract public void show();
+
+    /**
+     * Called when a key has woken the device to give us a chance to adjust our
+     * state according the the key.  We are responsible for waking the device
+     * (by poking the wake lock) once we are ready.
+     *
+     * The 'Tq' suffix is per the documentation in {@link android.view.WindowManagerPolicy}.
+     * Be sure not to take any action that takes a long time; any significant
+     * action should be posted to a handler.
+     *
+     * @param keyCode The wake key, which may be relevant for configuring the
+     *   keyguard.  May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking for a reason
+     *   other than a key press.
+     */
+    abstract public void wakeWhenReadyTq(int keyCode);
+
+    /**
+     * Verify that the user can get past the keyguard securely.  This is called,
+     * for example, when the phone disables the keyguard but then wants to launch
+     * something else that requires secure access.
+     *
+     * The result will be propogated back via {@link KeyguardViewCallback#keyguardDone(boolean)}
+     */
+    abstract public void verifyUnlock();
+
+    /**
+     * Called before this view is being removed.
+     */
+    abstract public void cleanUp();
+
+    /**
+     * Gets the desired user activity timeout in milliseconds, or -1 if the
+     * default should be used.
+     */
+    abstract public long getUserActivityTimeout();
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if (interceptMediaKey(event)) {
+            return true;
+        }
+        return super.dispatchKeyEvent(event);
+    }
+
+    /**
+     * Allows the media keys to work when the keyguard is showing.
+     * The media keys should be of no interest to the actual keyguard view(s),
+     * so intercepting them here should not be of any harm.
+     * @param event The key event
+     * @return whether the event was consumed as a media key.
+     */
+    private boolean interceptMediaKey(KeyEvent event) {
+        final int keyCode = event.getKeyCode();
+        if (event.getAction() == KeyEvent.ACTION_DOWN) {
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_MEDIA_PLAY:
+                case KeyEvent.KEYCODE_MEDIA_PAUSE:
+                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+                    /* Suppress PLAY/PAUSE toggle when phone is ringing or
+                     * in-call to avoid music playback */
+                    if (mTelephonyManager == null) {
+                        mTelephonyManager = (TelephonyManager) getContext().getSystemService(
+                                Context.TELEPHONY_SERVICE);
+                    }
+                    if (mTelephonyManager != null &&
+                            mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
+                        return true;  // suppress key event
+                    }
+                case KeyEvent.KEYCODE_MUTE:
+                case KeyEvent.KEYCODE_HEADSETHOOK:
+                case KeyEvent.KEYCODE_MEDIA_STOP:
+                case KeyEvent.KEYCODE_MEDIA_NEXT:
+                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+                case KeyEvent.KEYCODE_MEDIA_REWIND:
+                case KeyEvent.KEYCODE_MEDIA_RECORD:
+                case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
+                    handleMediaKeyEvent(event);
+                    return true;
+                }
+
+                case KeyEvent.KEYCODE_VOLUME_UP:
+                case KeyEvent.KEYCODE_VOLUME_DOWN:
+                case KeyEvent.KEYCODE_VOLUME_MUTE: {
+                    if (KEYGUARD_MANAGES_VOLUME) {
+                        synchronized (this) {
+                            if (mAudioManager == null) {
+                                mAudioManager = (AudioManager) getContext().getSystemService(
+                                        Context.AUDIO_SERVICE);
+                            }
+                        }
+                        // Volume buttons should only function for music (local or remote).
+                        // TODO: Actually handle MUTE.
+                        mAudioManager.adjustLocalOrRemoteStreamVolume(
+                                AudioManager.STREAM_MUSIC,
+                                keyCode == KeyEvent.KEYCODE_VOLUME_UP
+                                        ? AudioManager.ADJUST_RAISE
+                                        : AudioManager.ADJUST_LOWER);
+                        // Don't execute default volume behavior
+                        return true;
+                    } else {
+                        return false;
+                    }
+                }
+            }
+        } else if (event.getAction() == KeyEvent.ACTION_UP) {
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_MUTE:
+                case KeyEvent.KEYCODE_HEADSETHOOK:
+                case KeyEvent.KEYCODE_MEDIA_PLAY:
+                case KeyEvent.KEYCODE_MEDIA_PAUSE:
+                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+                case KeyEvent.KEYCODE_MEDIA_STOP:
+                case KeyEvent.KEYCODE_MEDIA_NEXT:
+                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+                case KeyEvent.KEYCODE_MEDIA_REWIND:
+                case KeyEvent.KEYCODE_MEDIA_RECORD:
+                case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
+                    handleMediaKeyEvent(event);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    void handleMediaKeyEvent(KeyEvent keyEvent) {
+        IAudioService audioService = IAudioService.Stub.asInterface(
+                ServiceManager.checkService(Context.AUDIO_SERVICE));
+        if (audioService != null) {
+            try {
+                audioService.dispatchMediaKeyEvent(keyEvent);
+            } catch (RemoteException e) {
+                Log.e("KeyguardViewBase", "dispatchMediaKeyEvent threw exception " + e);
+            }
+        } else {
+            Slog.w("KeyguardViewBase", "Unable to find IAudioService for media key event");
+        }
+    }
+
+    @Override
+    public void dispatchSystemUiVisibilityChanged(int visibility) {
+        super.dispatchSystemUiVisibilityChanged(visibility);
+
+        if (!(mContext instanceof Activity)) {
+            setSystemUiVisibility(STATUS_BAR_DISABLE_BACK);
+        }
+    }
+
+    public void setViewMediatorCallback(
+            KeyguardViewMediator.ViewMediatorCallback viewMediatorCallback) {
+        mViewMediatorCallback = viewMediatorCallback;
+    }
+
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
new file mode 100644
index 0000000..76ba811
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
@@ -0,0 +1,434 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.appwidget.AppWidgetManager;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Parcelable;
+import android.os.SystemProperties;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewManager;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+
+import com.android.internal.R;
+import com.android.internal.widget.LockPatternUtils;
+
+/**
+ * Manages creating, showing, hiding and resetting the keyguard.  Calls back
+ * via {@link KeyguardViewMediator.ViewMediatorCallback} to poke
+ * the wake lock and report that the keyguard is done, which is in turn,
+ * reported to this class by the current {@link KeyguardViewBase}.
+ */
+public class KeyguardViewManager {
+    private final static boolean DEBUG = KeyguardViewMediator.DEBUG;
+    private static String TAG = "KeyguardViewManager";
+    public static boolean USE_UPPER_CASE = true;
+
+    // Timeout used for keypresses
+    static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
+
+    private final Context mContext;
+    private final ViewManager mViewManager;
+    private final KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
+
+    private WindowManager.LayoutParams mWindowLayoutParams;
+    private boolean mNeedsInput = false;
+
+    private FrameLayout mKeyguardHost;
+    private KeyguardHostView mKeyguardView;
+
+    private boolean mScreenOn = false;
+    private LockPatternUtils mLockPatternUtils;
+
+    public interface ShowListener {
+        void onShown(IBinder windowToken);
+    };
+
+    /**
+     * @param context Used to create views.
+     * @param viewManager Keyguard will be attached to this.
+     * @param callback Used to notify of changes.
+     * @param lockPatternUtils
+     */
+    public KeyguardViewManager(Context context, ViewManager viewManager,
+            KeyguardViewMediator.ViewMediatorCallback callback,
+            LockPatternUtils lockPatternUtils) {
+        mContext = context;
+        mViewManager = viewManager;
+        mViewMediatorCallback = callback;
+        mLockPatternUtils = lockPatternUtils;
+    }
+
+    /**
+     * Show the keyguard.  Will handle creating and attaching to the view manager
+     * lazily.
+     */
+    public synchronized void show(Bundle options) {
+        if (DEBUG) Log.d(TAG, "show(); mKeyguardView==" + mKeyguardView);
+
+        boolean enableScreenRotation = shouldEnableScreenRotation();
+
+        maybeCreateKeyguardLocked(enableScreenRotation, false, options);
+        maybeEnableScreenRotation(enableScreenRotation);
+
+        // Disable common aspects of the system/status/navigation bars that are not appropriate or
+        // useful on any keyguard screen but can be re-shown by dialogs or SHOW_WHEN_LOCKED
+        // activities. Other disabled bits are handled by the KeyguardViewMediator talking
+        // directly to the status bar service.
+        final int visFlags = View.STATUS_BAR_DISABLE_HOME;
+        if (DEBUG) Log.v(TAG, "show:setSystemUiVisibility(" + Integer.toHexString(visFlags)+")");
+        mKeyguardHost.setSystemUiVisibility(visFlags);
+
+        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
+        mKeyguardHost.setVisibility(View.VISIBLE);
+        mKeyguardView.show();
+        mKeyguardView.requestFocus();
+    }
+
+    private boolean shouldEnableScreenRotation() {
+        Resources res = mContext.getResources();
+        return SystemProperties.getBoolean("lockscreen.rot_override",false)
+                || res.getBoolean(com.android.internal.R.bool.config_enableLockScreenRotation);
+    }
+
+    class ViewManagerHost extends FrameLayout {
+        public ViewManagerHost(Context context) {
+            super(context);
+            setFitsSystemWindows(true);
+        }
+
+        @Override
+        protected void onConfigurationChanged(Configuration newConfig) {
+            super.onConfigurationChanged(newConfig);
+            if (mKeyguardHost.getVisibility() == View.VISIBLE) {
+                // only propagate configuration messages if we're currently showing
+                maybeCreateKeyguardLocked(shouldEnableScreenRotation(), true, null);
+            } else {
+                if (DEBUG) Log.v(TAG, "onConfigurationChanged: view not visible");
+            }
+        }
+
+        @Override
+        public boolean dispatchKeyEvent(KeyEvent event) {
+            if (event.getAction() == KeyEvent.ACTION_DOWN && mKeyguardView != null) {
+                int keyCode = event.getKeyCode();
+                if (keyCode == KeyEvent.KEYCODE_BACK && mKeyguardView.handleBackKey()) {
+                    return true;
+                } else if (keyCode == KeyEvent.KEYCODE_MENU && mKeyguardView.handleMenuKey()) {
+                    return true;
+                }
+            }
+            return super.dispatchKeyEvent(event);
+        }
+    }
+
+    SparseArray<Parcelable> mStateContainer = new SparseArray<Parcelable>();
+
+    private void maybeCreateKeyguardLocked(boolean enableScreenRotation, boolean force,
+            Bundle options) {
+        final boolean isActivity = (mContext instanceof Activity); // for test activity
+
+        if (mKeyguardHost != null) {
+            mKeyguardHost.saveHierarchyState(mStateContainer);
+        }
+
+        if (mKeyguardHost == null) {
+            if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");
+
+            mKeyguardHost = new ViewManagerHost(mContext);
+
+            int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                    | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
+                    | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
+                    | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+
+            if (!mNeedsInput) {
+                flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+            }
+            if (ActivityManager.isHighEndGfx()) {
+                flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+            }
+
+            final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
+            final int type = isActivity ? WindowManager.LayoutParams.TYPE_APPLICATION
+                    : WindowManager.LayoutParams.TYPE_KEYGUARD;
+            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                    stretch, stretch, type, flags, PixelFormat.TRANSLUCENT);
+            lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+            lp.windowAnimations = com.android.internal.R.style.Animation_LockScreen;
+            if (ActivityManager.isHighEndGfx()) {
+                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+                lp.privateFlags |=
+                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
+            }
+            lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
+            if (isActivity) {
+                lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+            }
+            lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
+            lp.setTitle(isActivity ? "KeyguardMock" : "Keyguard");
+            mWindowLayoutParams = lp;
+            mViewManager.addView(mKeyguardHost, lp);
+        }
+
+        if (force || mKeyguardView == null) {
+            inflateKeyguardView(options);
+        }
+        updateUserActivityTimeoutInWindowLayoutParams();
+        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
+
+        mKeyguardHost.restoreHierarchyState(mStateContainer);
+    }
+
+    private void inflateKeyguardView(Bundle options) {
+        View v = mKeyguardHost.findViewById(R.id.keyguard_host_view);
+        if (v != null) {
+            mKeyguardHost.removeView(v);
+        }
+        // TODO: Remove once b/7094175 is fixed
+        if (false) Slog.d(TAG, "inflateKeyguardView: b/7094175 mContext.config="
+                + mContext.getResources().getConfiguration());
+        final LayoutInflater inflater = LayoutInflater.from(mContext);
+        View view = inflater.inflate(R.layout.keyguard_host_view, mKeyguardHost, true);
+        mKeyguardView = (KeyguardHostView) view.findViewById(R.id.keyguard_host_view);
+        mKeyguardView.setLockPatternUtils(mLockPatternUtils);
+        mKeyguardView.setViewMediatorCallback(mViewMediatorCallback);
+
+        // HACK
+        // The keyguard view will have set up window flags in onFinishInflate before we set
+        // the view mediator callback. Make sure it knows the correct IME state.
+        if (mViewMediatorCallback != null) {
+            KeyguardPasswordView kpv = (KeyguardPasswordView) mKeyguardView.findViewById(
+                    R.id.keyguard_password_view);
+
+            if (kpv != null) {
+                mViewMediatorCallback.setNeedsInput(kpv.needsInput());
+            }
+        }
+
+        if (options != null) {
+            if (options.getBoolean(LockPatternUtils.KEYGUARD_SHOW_USER_SWITCHER)) {
+                mKeyguardView.goToUserSwitcher();
+            }
+            if (options.getBoolean(LockPatternUtils.KEYGUARD_SHOW_SECURITY_CHALLENGE)) {
+                mKeyguardView.showNextSecurityScreenIfPresent();
+            }
+            int widgetToShow = options.getInt(LockPatternUtils.KEYGUARD_SHOW_APPWIDGET,
+                    AppWidgetManager.INVALID_APPWIDGET_ID);
+            if (widgetToShow != AppWidgetManager.INVALID_APPWIDGET_ID) {
+                mKeyguardView.goToWidget(widgetToShow);
+            }
+        }
+    }
+
+    public void updateUserActivityTimeout() {
+        updateUserActivityTimeoutInWindowLayoutParams();
+        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
+    }
+
+    private void updateUserActivityTimeoutInWindowLayoutParams() {
+        // Use the user activity timeout requested by the keyguard view, if any.
+        if (mKeyguardView != null) {
+            long timeout = mKeyguardView.getUserActivityTimeout();
+            if (timeout >= 0) {
+                mWindowLayoutParams.userActivityTimeout = timeout;
+                return;
+            }
+        }
+
+        // Otherwise, use the default timeout.
+        mWindowLayoutParams.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
+    }
+
+    private void maybeEnableScreenRotation(boolean enableScreenRotation) {
+        // TODO: move this outside
+        if (enableScreenRotation) {
+            if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen On!");
+            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
+        } else {
+            if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen Off!");
+            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+        }
+        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
+    }
+
+    public void setNeedsInput(boolean needsInput) {
+        mNeedsInput = needsInput;
+        if (mWindowLayoutParams != null) {
+            if (needsInput) {
+                mWindowLayoutParams.flags &=
+                    ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+            } else {
+                mWindowLayoutParams.flags |=
+                    WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+            }
+
+            try {
+                mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
+            } catch (java.lang.IllegalArgumentException e) {
+                // TODO: Ensure this method isn't called on views that are changing...
+                Log.w(TAG,"Can't update input method on " + mKeyguardHost + " window not attached");
+            }
+        }
+    }
+
+    /**
+     * Reset the state of the view.
+     */
+    public synchronized void reset(Bundle options) {
+        if (DEBUG) Log.d(TAG, "reset()");
+        // User might have switched, check if we need to go back to keyguard
+        // TODO: It's preferable to stay and show the correct lockscreen or unlock if none
+        maybeCreateKeyguardLocked(shouldEnableScreenRotation(), true, options);
+    }
+
+    public synchronized void onScreenTurnedOff() {
+        if (DEBUG) Log.d(TAG, "onScreenTurnedOff()");
+        mScreenOn = false;
+        if (mKeyguardView != null) {
+            mKeyguardView.onScreenTurnedOff();
+        }
+    }
+
+    public synchronized void onScreenTurnedOn(
+            final KeyguardViewManager.ShowListener showListener) {
+        if (DEBUG) Log.d(TAG, "onScreenTurnedOn()");
+        mScreenOn = true;
+        if (mKeyguardView != null) {
+            mKeyguardView.onScreenTurnedOn();
+
+            // Caller should wait for this window to be shown before turning
+            // on the screen.
+            if (showListener != null) {
+                if (mKeyguardHost.getVisibility() == View.VISIBLE) {
+                    // Keyguard may be in the process of being shown, but not yet
+                    // updated with the window manager...  give it a chance to do so.
+                    mKeyguardHost.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            if (mKeyguardHost.getVisibility() == View.VISIBLE) {
+                                showListener.onShown(mKeyguardHost.getWindowToken());
+                            } else {
+                                showListener.onShown(null);
+                            }
+                        }
+                    });
+                } else {
+                    showListener.onShown(null);
+                }
+            }
+        } else if (showListener != null) {
+            showListener.onShown(null);
+        }
+    }
+
+    public synchronized void verifyUnlock() {
+        if (DEBUG) Log.d(TAG, "verifyUnlock()");
+        show(null);
+        mKeyguardView.verifyUnlock();
+    }
+
+    /**
+     * A key has woken the device.  We use this to potentially adjust the state
+     * of the lock screen based on the key.
+     *
+     * The 'Tq' suffix is per the documentation in {@link android.view.WindowManagerPolicy}.
+     * Be sure not to take any action that takes a long time; any significant
+     * action should be posted to a handler.
+     *
+     * @param keyCode The wake key.  May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking
+     * for a reason other than a key press.
+     */
+    public boolean wakeWhenReadyTq(int keyCode) {
+        if (DEBUG) Log.d(TAG, "wakeWhenReady(" + keyCode + ")");
+        if (mKeyguardView != null) {
+            mKeyguardView.wakeWhenReadyTq(keyCode);
+            return true;
+        }
+        Log.w(TAG, "mKeyguardView is null in wakeWhenReadyTq");
+        return false;
+    }
+
+    /**
+     * Hides the keyguard view
+     */
+    public synchronized void hide() {
+        if (DEBUG) Log.d(TAG, "hide()");
+
+        if (mKeyguardHost != null) {
+            mKeyguardHost.setVisibility(View.GONE);
+
+            // We really only want to preserve keyguard state for configuration changes. Hence
+            // we should clear state of widgets (e.g. Music) when we hide keyguard so it can
+            // start with a fresh state when we return.
+            mStateContainer.clear();
+
+            // Don't do this right away, so we can let the view continue to animate
+            // as it goes away.
+            if (mKeyguardView != null) {
+                final KeyguardViewBase lastView = mKeyguardView;
+                mKeyguardView = null;
+                mKeyguardHost.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        synchronized (KeyguardViewManager.this) {
+                            lastView.cleanUp();
+                            mKeyguardHost.removeView(lastView);
+                        }
+                    }
+                }, 500);
+            }
+        }
+    }
+
+    /**
+     * Dismisses the keyguard by going to the next screen or making it gone.
+     */
+    public synchronized void dismiss() {
+        if (mScreenOn) {
+            mKeyguardView.dismiss();
+        }
+    }
+
+    /**
+     * @return Whether the keyguard is showing
+     */
+    public synchronized boolean isShowing() {
+        return (mKeyguardHost != null && mKeyguardHost.getVisibility() == View.VISIBLE);
+    }
+
+    public void showAssistant() {
+        if (mKeyguardView != null) {
+            mKeyguardView.showAssistant();
+        }
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
new file mode 100644
index 0000000..df4c661
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
@@ -0,0 +1,1413 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard;
+
+import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+
+import android.app.Activity;
+import android.app.ActivityManagerNative;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.app.StatusBarManager;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.media.AudioManager;
+import android.media.SoundPool;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.util.EventLog;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.widget.LockPatternUtils;
+
+
+/**
+ * Mediates requests related to the keyguard.  This includes queries about the
+ * state of the keyguard, power management events that effect whether the keyguard
+ * should be shown or reset, callbacks to the phone window manager to notify
+ * it of when the keyguard is showing, and events from the keyguard view itself
+ * stating that the keyguard was succesfully unlocked.
+ *
+ * Note that the keyguard view is shown when the screen is off (as appropriate)
+ * so that once the screen comes on, it will be ready immediately.
+ *
+ * Example queries about the keyguard:
+ * - is {movement, key} one that should wake the keygaurd?
+ * - is the keyguard showing?
+ * - are input events restricted due to the state of the keyguard?
+ *
+ * Callbacks to the phone window manager:
+ * - the keyguard is showing
+ *
+ * Example external events that translate to keyguard view changes:
+ * - screen turned off -> reset the keyguard, and show it so it will be ready
+ *   next time the screen turns on
+ * - keyboard is slid open -> if the keyguard is not secure, hide it
+ *
+ * Events from the keyguard view:
+ * - user succesfully unlocked keyguard -> hide keyguard view, and no longer
+ *   restrict input events.
+ *
+ * Note: in addition to normal power managment events that effect the state of
+ * whether the keyguard should be showing, external apps and services may request
+ * that the keyguard be disabled via {@link #setKeyguardEnabled(boolean)}.  When
+ * false, this will override all other conditions for turning on the keyguard.
+ *
+ * Threading and synchronization:
+ * This class is created by the initialization routine of the {@link WindowManagerPolicy},
+ * and runs on its thread.  The keyguard UI is created from that thread in the
+ * constructor of this class.  The apis may be called from other threads, including the
+ * {@link com.android.server.input.InputManagerService}'s and {@link android.view.WindowManager}'s.
+ * Therefore, methods on this class are synchronized, and any action that is pointed
+ * directly to the keyguard UI is posted to a {@link Handler} to ensure it is taken on the UI
+ * thread of the keyguard.
+ */
+public class KeyguardViewMediator {
+    private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
+    final static boolean DEBUG = false;
+    private final static boolean DBG_WAKE = false;
+
+    private final static String TAG = "KeyguardViewMediator";
+
+    private static final String DELAYED_KEYGUARD_ACTION =
+        "com.android.internal.policy.impl.PhoneWindowManager.DELAYED_KEYGUARD";
+
+    // used for handler messages
+    private static final int SHOW = 2;
+    private static final int HIDE = 3;
+    private static final int RESET = 4;
+    private static final int VERIFY_UNLOCK = 5;
+    private static final int NOTIFY_SCREEN_OFF = 6;
+    private static final int NOTIFY_SCREEN_ON = 7;
+    private static final int WAKE_WHEN_READY = 8;
+    private static final int KEYGUARD_DONE = 9;
+    private static final int KEYGUARD_DONE_DRAWING = 10;
+    private static final int KEYGUARD_DONE_AUTHENTICATING = 11;
+    private static final int SET_HIDDEN = 12;
+    private static final int KEYGUARD_TIMEOUT = 13;
+    private static final int SHOW_ASSISTANT = 14;
+
+    /**
+     * The default amount of time we stay awake (used for all key input)
+     */
+    protected static final int AWAKE_INTERVAL_DEFAULT_MS = 10000;
+
+    /**
+     * How long to wait after the screen turns off due to timeout before
+     * turning on the keyguard (i.e, the user has this much time to turn
+     * the screen back on without having to face the keyguard).
+     */
+    private static final int KEYGUARD_LOCK_AFTER_DELAY_DEFAULT = 5000;
+
+    /**
+     * How long we'll wait for the {@link ViewMediatorCallback#keyguardDoneDrawing()}
+     * callback before unblocking a call to {@link #setKeyguardEnabled(boolean)}
+     * that is reenabling the keyguard.
+     */
+    private static final int KEYGUARD_DONE_DRAWING_TIMEOUT_MS = 2000;
+
+    /**
+     * Allow the user to expand the status bar when the keyguard is engaged
+     * (without a pattern or password).
+     */
+    private static final boolean ENABLE_INSECURE_STATUS_BAR_EXPAND = true;
+
+    /** The stream type that the lock sounds are tied to. */
+    private int mMasterStreamType;
+
+    private Context mContext;
+    private AlarmManager mAlarmManager;
+    private AudioManager mAudioManager;
+    private StatusBarManager mStatusBarManager;
+    private boolean mShowLockIcon;
+    private boolean mShowingLockIcon;
+
+    private boolean mSystemReady;
+
+    // Whether the next call to playSounds() should be skipped.  Defaults to
+    // true because the first lock (on boot) should be silent.
+    private boolean mSuppressNextLockSound = true;
+
+
+    /** High level access to the power manager for WakeLocks */
+    private PowerManager mPM;
+
+    /** UserManager for querying number of users */
+    private UserManager mUserManager;
+
+    /**
+     * Used to keep the device awake while to ensure the keyguard finishes opening before
+     * we sleep.
+     */
+    private PowerManager.WakeLock mShowKeyguardWakeLock;
+
+    /**
+     * Does not turn on screen, held while a call to {@link KeyguardViewManager#wakeWhenReadyTq(int)}
+     * is called to make sure the device doesn't sleep before it has a chance to poke
+     * the wake lock.
+     * @see #wakeWhenReady(int)
+     */
+    private PowerManager.WakeLock mWakeAndHandOff;
+
+    private KeyguardViewManager mKeyguardViewManager;
+
+    // these are protected by synchronized (this)
+
+    /**
+     * External apps (like the phone app) can tell us to disable the keygaurd.
+     */
+    private boolean mExternallyEnabled = true;
+
+    /**
+     * Remember if an external call to {@link #setKeyguardEnabled} with value
+     * false caused us to hide the keyguard, so that we need to reshow it once
+     * the keygaurd is reenabled with another call with value true.
+     */
+    private boolean mNeedToReshowWhenReenabled = false;
+
+    // cached value of whether we are showing (need to know this to quickly
+    // answer whether the input should be restricted)
+    private boolean mShowing = false;
+
+    // true if the keyguard is hidden by another window
+    private boolean mHidden = false;
+
+    /**
+     * Helps remember whether the screen has turned on since the last time
+     * it turned off due to timeout. see {@link #onScreenTurnedOff(int)}
+     */
+    private int mDelayedShowingSequence;
+
+    /**
+     * If the user has disabled the keyguard, then requests to exit, this is
+     * how we'll ultimately let them know whether it was successful.  We use this
+     * var being non-null as an indicator that there is an in progress request.
+     */
+    private WindowManagerPolicy.OnKeyguardExitResult mExitSecureCallback;
+
+    // the properties of the keyguard
+
+    private KeyguardUpdateMonitor mUpdateMonitor;
+
+    private boolean mScreenOn;
+
+    // last known state of the cellular connection
+    private String mPhoneState = TelephonyManager.EXTRA_STATE_IDLE;
+
+    /**
+     * we send this intent when the keyguard is dismissed.
+     */
+    private Intent mUserPresentIntent;
+
+    /**
+     * {@link #setKeyguardEnabled} waits on this condition when it reenables
+     * the keyguard.
+     */
+    private boolean mWaitingUntilKeyguardVisible = false;
+    private LockPatternUtils mLockPatternUtils;
+    private boolean mKeyguardDonePending = false;
+
+    private SoundPool mLockSounds;
+    private int mLockSoundId;
+    private int mUnlockSoundId;
+    private int mLockSoundStreamId;
+
+    /**
+     * The volume applied to the lock/unlock sounds.
+     */
+    private final float mLockSoundVolume;
+
+    /**
+     * The callback used by the keyguard view to tell the {@link KeyguardViewMediator}
+     * various things.
+     */
+    public interface ViewMediatorCallback {
+
+        /**
+         * Wake the device immediately.
+         */
+        void wakeUp();
+
+        /**
+         * Reports user activity and requests that the screen stay on.
+         */
+        void userActivity();
+
+        /**
+         * Reports user activity and requests that the screen stay on for at least
+         * the specified amount of time.
+         * @param millis The amount of time in millis.  This value is currently ignored.
+         */
+        void userActivity(long millis);
+
+        /**
+         * Report that the keyguard is done.
+         * @param authenticated Whether the user securely got past the keyguard.
+         *   the only reason for this to be false is if the keyguard was instructed
+         *   to appear temporarily to verify the user is supposed to get past the
+         *   keyguard, and the user fails to do so.
+         */
+        void keyguardDone(boolean authenticated);
+
+        /**
+         * Report that the keyguard is done drawing.
+         */
+        void keyguardDoneDrawing();
+
+        /**
+         * Tell ViewMediator that the current view needs IME input
+         * @param needsInput
+         */
+        void setNeedsInput(boolean needsInput);
+
+        /**
+         * Tell view mediator that the keyguard view's desired user activity timeout
+         * has changed and needs to be reapplied to the window.
+         */
+        void onUserActivityTimeoutChanged();
+
+        /**
+         * Report that the keyguard is dismissable, pending the next keyguardDone call.
+         */
+        void keyguardDonePending();
+    }
+
+    KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
+
+        @Override
+        public void onUserSwitched(int userId) {
+            // Note that the mLockPatternUtils user has already been updated from setCurrentUser.
+            // We need to force a reset of the views, since lockNow (called by
+            // ActivityManagerService) will not reconstruct the keyguard if it is already showing.
+            synchronized (KeyguardViewMediator.this) {
+                Bundle options = new Bundle();
+                options.putBoolean(LockPatternUtils.KEYGUARD_SHOW_USER_SWITCHER, true);
+                options.putBoolean(LockPatternUtils.KEYGUARD_SHOW_SECURITY_CHALLENGE, true);
+                resetStateLocked(options);
+                adjustStatusBarLocked();
+                // Disable face unlock when the user switches.
+                KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(false);
+            }
+        }
+
+        @Override
+        public void onUserRemoved(int userId) {
+            mLockPatternUtils.removeUser(userId);
+        }
+
+        @Override
+        void onPhoneStateChanged(int phoneState) {
+            synchronized (KeyguardViewMediator.this) {
+                if (TelephonyManager.CALL_STATE_IDLE == phoneState  // call ending
+                        && !mScreenOn                           // screen off
+                        && mExternallyEnabled) {                // not disabled by any app
+
+                    // note: this is a way to gracefully reenable the keyguard when the call
+                    // ends and the screen is off without always reenabling the keyguard
+                    // each time the screen turns off while in call (and having an occasional ugly
+                    // flicker while turning back on the screen and disabling the keyguard again).
+                    if (DEBUG) Log.d(TAG, "screen is off and call ended, let's make sure the "
+                            + "keyguard is showing");
+                    doKeyguardLocked();
+                }
+            }
+        };
+
+        @Override
+        public void onClockVisibilityChanged() {
+            adjustStatusBarLocked();
+        }
+
+        @Override
+        public void onDeviceProvisioned() {
+            sendUserPresentBroadcast();
+        }
+
+        @Override
+        public void onSimStateChanged(IccCardConstants.State simState) {
+            if (DEBUG) Log.d(TAG, "onSimStateChanged: " + simState);
+
+            switch (simState) {
+                case NOT_READY:
+                case ABSENT:
+                    // only force lock screen in case of missing sim if user hasn't
+                    // gone through setup wizard
+                    synchronized (this) {
+                        if (!mUpdateMonitor.isDeviceProvisioned()) {
+                            if (!isShowing()) {
+                                if (DEBUG) Log.d(TAG, "ICC_ABSENT isn't showing,"
+                                        + " we need to show the keyguard since the "
+                                        + "device isn't provisioned yet.");
+                                doKeyguardLocked();
+                            } else {
+                                resetStateLocked(null);
+                            }
+                        }
+                    }
+                    break;
+                case PIN_REQUIRED:
+                case PUK_REQUIRED:
+                    synchronized (this) {
+                        if (!isShowing()) {
+                            if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't "
+                                    + "showing; need to show keyguard so user can enter sim pin");
+                            doKeyguardLocked();
+                        } else {
+                            resetStateLocked(null);
+                        }
+                    }
+                    break;
+                case PERM_DISABLED:
+                    synchronized (this) {
+                        if (!isShowing()) {
+                            if (DEBUG) Log.d(TAG, "PERM_DISABLED and "
+                                  + "keygaurd isn't showing.");
+                            doKeyguardLocked();
+                        } else {
+                            if (DEBUG) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
+                                  + "show permanently disabled message in lockscreen.");
+                            resetStateLocked(null);
+                        }
+                    }
+                    break;
+                case READY:
+                    synchronized (this) {
+                        if (isShowing()) {
+                            resetStateLocked(null);
+                        }
+                    }
+                    break;
+            }
+        }
+
+    };
+
+    ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() {
+        public void wakeUp() {
+            KeyguardViewMediator.this.wakeUp();
+        }
+
+        public void userActivity() {
+            KeyguardViewMediator.this.userActivity();
+        }
+
+        public void userActivity(long holdMs) {
+            KeyguardViewMediator.this.userActivity(holdMs);
+        }
+
+        public void keyguardDone(boolean authenticated) {
+            KeyguardViewMediator.this.keyguardDone(authenticated, true);
+        }
+
+        public void keyguardDoneDrawing() {
+            mHandler.sendEmptyMessage(KEYGUARD_DONE_DRAWING);
+        }
+
+        @Override
+        public void setNeedsInput(boolean needsInput) {
+            mKeyguardViewManager.setNeedsInput(needsInput);
+        }
+
+        @Override
+        public void onUserActivityTimeoutChanged() {
+            mKeyguardViewManager.updateUserActivityTimeout();
+        }
+
+        @Override
+        public void keyguardDonePending() {
+            mKeyguardDonePending = true;
+        }
+    };
+
+    public void wakeUp() {
+        mPM.wakeUp(SystemClock.uptimeMillis());
+    }
+
+    public void userActivity() {
+        userActivity(AWAKE_INTERVAL_DEFAULT_MS);
+    }
+
+    public void userActivity(long holdMs) {
+        // We ignore the hold time.  Eventually we should remove it.
+        // Instead, the keyguard window has an explicit user activity timeout set on it.
+        mPM.userActivity(SystemClock.uptimeMillis(), false);
+    }
+
+    /**
+     * Construct a KeyguardViewMediator
+     * @param context
+     * @param lockPatternUtils optional mock interface for LockPatternUtils
+     */
+    public KeyguardViewMediator(Context context, LockPatternUtils lockPatternUtils) {
+        mContext = context;
+        mPM = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
+        mShowKeyguardWakeLock.setReferenceCounted(false);
+
+        mWakeAndHandOff = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "keyguardWakeAndHandOff");
+        mWakeAndHandOff.setReferenceCounted(false);
+
+        mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION));
+
+        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+
+        mUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
+
+        mLockPatternUtils = lockPatternUtils != null
+                ? lockPatternUtils : new LockPatternUtils(mContext);
+        mLockPatternUtils.setCurrentUser(UserHandle.USER_OWNER);
+
+        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+
+        mKeyguardViewManager = new KeyguardViewManager(context, wm, mViewMediatorCallback,
+                mLockPatternUtils);
+
+        mUserPresentIntent = new Intent(Intent.ACTION_USER_PRESENT);
+        mUserPresentIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
+                | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+
+        final ContentResolver cr = mContext.getContentResolver();
+        mShowLockIcon = (Settings.System.getInt(cr, "show_status_bar_lock", 0) == 1);
+
+        mScreenOn = mPM.isScreenOn();
+
+        mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0);
+        String soundPath = Settings.Global.getString(cr, Settings.Global.LOCK_SOUND);
+        if (soundPath != null) {
+            mLockSoundId = mLockSounds.load(soundPath, 1);
+        }
+        if (soundPath == null || mLockSoundId == 0) {
+            Log.w(TAG, "failed to load lock sound from " + soundPath);
+        }
+        soundPath = Settings.Global.getString(cr, Settings.Global.UNLOCK_SOUND);
+        if (soundPath != null) {
+            mUnlockSoundId = mLockSounds.load(soundPath, 1);
+        }
+        if (soundPath == null || mUnlockSoundId == 0) {
+            Log.w(TAG, "failed to load unlock sound from " + soundPath);
+        }
+        int lockSoundDefaultAttenuation = context.getResources().getInteger(
+                com.android.internal.R.integer.config_lockSoundVolumeDb);
+        mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20);
+    }
+
+    /**
+     * Let us know that the system is ready after startup.
+     */
+    public void onSystemReady() {
+        synchronized (this) {
+            if (DEBUG) Log.d(TAG, "onSystemReady");
+            mSystemReady = true;
+            mUpdateMonitor.registerCallback(mUpdateCallback);
+
+            // Suppress biometric unlock right after boot until things have settled if it is the
+            // selected security method, otherwise unsuppress it.  It must be unsuppressed if it is
+            // not the selected security method for the following reason:  if the user starts
+            // without a screen lock selected, the biometric unlock would be suppressed the first
+            // time they try to use it.
+            //
+            // Note that the biometric unlock will still not show if it is not the selected method.
+            // Calling setAlternateUnlockEnabled(true) simply says don't suppress it if it is the
+            // selected method.
+            if (mLockPatternUtils.usingBiometricWeak()
+                    && mLockPatternUtils.isBiometricWeakInstalled()) {
+                if (DEBUG) Log.d(TAG, "suppressing biometric unlock during boot");
+                mUpdateMonitor.setAlternateUnlockEnabled(false);
+            } else {
+                mUpdateMonitor.setAlternateUnlockEnabled(true);
+            }
+
+            doKeyguardLocked();
+        }
+        // Most services aren't available until the system reaches the ready state, so we
+        // send it here when the device first boots.
+        maybeSendUserPresentBroadcast();
+    }
+
+    /**
+     * Called to let us know the screen was turned off.
+     * @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER},
+     *   {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
+     *   {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
+     */
+    public void onScreenTurnedOff(int why) {
+        synchronized (this) {
+            mScreenOn = false;
+            if (DEBUG) Log.d(TAG, "onScreenTurnedOff(" + why + ")");
+
+            mKeyguardDonePending = false;
+
+            // Lock immediately based on setting if secure (user has a pin/pattern/password).
+            // This also "locks" the device when not secure to provide easy access to the
+            // camera while preventing unwanted input.
+            final boolean lockImmediately =
+                mLockPatternUtils.getPowerButtonInstantlyLocks() || !mLockPatternUtils.isSecure();
+
+            if (mExitSecureCallback != null) {
+                if (DEBUG) Log.d(TAG, "pending exit secure callback cancelled");
+                mExitSecureCallback.onKeyguardExitResult(false);
+                mExitSecureCallback = null;
+                if (!mExternallyEnabled) {
+                    hideLocked();
+                }
+            } else if (mShowing) {
+                notifyScreenOffLocked();
+                resetStateLocked(null);
+            } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT
+                   || (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)) {
+                doKeyguardLaterLocked();
+            } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
+                // Do not enable the keyguard if the prox sensor forced the screen off.
+            } else {
+                doKeyguardLocked();
+            }
+        }
+    }
+
+    private void doKeyguardLaterLocked() {
+        // if the screen turned off because of timeout or the user hit the power button
+        // and we don't need to lock immediately, set an alarm
+        // to enable it a little bit later (i.e, give the user a chance
+        // to turn the screen back on within a certain window without
+        // having to unlock the screen)
+        final ContentResolver cr = mContext.getContentResolver();
+
+        // From DisplaySettings
+        long displayTimeout = Settings.System.getInt(cr, SCREEN_OFF_TIMEOUT,
+                KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT);
+
+        // From SecuritySettings
+        final long lockAfterTimeout = Settings.Secure.getInt(cr,
+                Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
+                KEYGUARD_LOCK_AFTER_DELAY_DEFAULT);
+
+        // From DevicePolicyAdmin
+        final long policyTimeout = mLockPatternUtils.getDevicePolicyManager()
+                .getMaximumTimeToLock(null, mLockPatternUtils.getCurrentUser());
+
+        long timeout;
+        if (policyTimeout > 0) {
+            // policy in effect. Make sure we don't go beyond policy limit.
+            displayTimeout = Math.max(displayTimeout, 0); // ignore negative values
+            timeout = Math.min(policyTimeout - displayTimeout, lockAfterTimeout);
+        } else {
+            timeout = lockAfterTimeout;
+        }
+
+        if (timeout <= 0) {
+            // Lock now
+            mSuppressNextLockSound = true;
+            doKeyguardLocked();
+        } else {
+            // Lock in the future
+            long when = SystemClock.elapsedRealtime() + timeout;
+            Intent intent = new Intent(DELAYED_KEYGUARD_ACTION);
+            intent.putExtra("seq", mDelayedShowingSequence);
+            PendingIntent sender = PendingIntent.getBroadcast(mContext,
+                    0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, sender);
+            if (DEBUG) Log.d(TAG, "setting alarm to turn off keyguard, seq = "
+                             + mDelayedShowingSequence);
+        }
+    }
+
+    private void cancelDoKeyguardLaterLocked() {
+        mDelayedShowingSequence++;
+    }
+
+    /**
+     * Let's us know the screen was turned on.
+     */
+    public void onScreenTurnedOn(KeyguardViewManager.ShowListener showListener) {
+        synchronized (this) {
+            mScreenOn = true;
+            cancelDoKeyguardLaterLocked();
+            if (DEBUG) Log.d(TAG, "onScreenTurnedOn, seq = " + mDelayedShowingSequence);
+            if (showListener != null) {
+                notifyScreenOnLocked(showListener);
+            }
+        }
+        maybeSendUserPresentBroadcast();
+    }
+
+    private void maybeSendUserPresentBroadcast() {
+        if (mSystemReady && mLockPatternUtils.isLockScreenDisabled()
+                && mUserManager.getUsers(true).size() == 1) {
+            // Lock screen is disabled because the user has set the preference to "None".
+            // In this case, send out ACTION_USER_PRESENT here instead of in
+            // handleKeyguardDone()
+            sendUserPresentBroadcast();
+        }
+    }
+
+    /**
+     * A dream started.  We should lock after the usual screen-off lock timeout but only
+     * if there is a secure lock pattern.
+     */
+    public void onDreamingStarted() {
+        synchronized (this) {
+            if (mScreenOn && mLockPatternUtils.isSecure()) {
+                doKeyguardLaterLocked();
+            }
+        }
+    }
+
+    /**
+     * A dream stopped.
+     */
+    public void onDreamingStopped() {
+        synchronized (this) {
+            if (mScreenOn) {
+                cancelDoKeyguardLaterLocked();
+            }
+        }
+    }
+
+    /**
+     * Same semantics as {@link WindowManagerPolicy#enableKeyguard}; provide
+     * a way for external stuff to override normal keyguard behavior.  For instance
+     * the phone app disables the keyguard when it receives incoming calls.
+     */
+    public void setKeyguardEnabled(boolean enabled) {
+        synchronized (this) {
+            if (DEBUG) Log.d(TAG, "setKeyguardEnabled(" + enabled + ")");
+
+            mExternallyEnabled = enabled;
+
+            if (!enabled && mShowing) {
+                if (mExitSecureCallback != null) {
+                    if (DEBUG) Log.d(TAG, "in process of verifyUnlock request, ignoring");
+                    // we're in the process of handling a request to verify the user
+                    // can get past the keyguard. ignore extraneous requests to disable / reenable
+                    return;
+                }
+
+                // hiding keyguard that is showing, remember to reshow later
+                if (DEBUG) Log.d(TAG, "remembering to reshow, hiding keyguard, "
+                        + "disabling status bar expansion");
+                mNeedToReshowWhenReenabled = true;
+                hideLocked();
+            } else if (enabled && mNeedToReshowWhenReenabled) {
+                // reenabled after previously hidden, reshow
+                if (DEBUG) Log.d(TAG, "previously hidden, reshowing, reenabling "
+                        + "status bar expansion");
+                mNeedToReshowWhenReenabled = false;
+
+                if (mExitSecureCallback != null) {
+                    if (DEBUG) Log.d(TAG, "onKeyguardExitResult(false), resetting");
+                    mExitSecureCallback.onKeyguardExitResult(false);
+                    mExitSecureCallback = null;
+                    resetStateLocked(null);
+                } else {
+                    showLocked(null);
+
+                    // block until we know the keygaurd is done drawing (and post a message
+                    // to unblock us after a timeout so we don't risk blocking too long
+                    // and causing an ANR).
+                    mWaitingUntilKeyguardVisible = true;
+                    mHandler.sendEmptyMessageDelayed(KEYGUARD_DONE_DRAWING, KEYGUARD_DONE_DRAWING_TIMEOUT_MS);
+                    if (DEBUG) Log.d(TAG, "waiting until mWaitingUntilKeyguardVisible is false");
+                    while (mWaitingUntilKeyguardVisible) {
+                        try {
+                            wait();
+                        } catch (InterruptedException e) {
+                            Thread.currentThread().interrupt();
+                        }
+                    }
+                    if (DEBUG) Log.d(TAG, "done waiting for mWaitingUntilKeyguardVisible");
+                }
+            }
+        }
+    }
+
+    /**
+     * @see android.app.KeyguardManager#exitKeyguardSecurely
+     */
+    public void verifyUnlock(WindowManagerPolicy.OnKeyguardExitResult callback) {
+        synchronized (this) {
+            if (DEBUG) Log.d(TAG, "verifyUnlock");
+            if (!mUpdateMonitor.isDeviceProvisioned()) {
+                // don't allow this api when the device isn't provisioned
+                if (DEBUG) Log.d(TAG, "ignoring because device isn't provisioned");
+                callback.onKeyguardExitResult(false);
+            } else if (mExternallyEnabled) {
+                // this only applies when the user has externally disabled the
+                // keyguard.  this is unexpected and means the user is not
+                // using the api properly.
+                Log.w(TAG, "verifyUnlock called when not externally disabled");
+                callback.onKeyguardExitResult(false);
+            } else if (mExitSecureCallback != null) {
+                // already in progress with someone else
+                callback.onKeyguardExitResult(false);
+            } else {
+                mExitSecureCallback = callback;
+                verifyUnlockLocked();
+            }
+        }
+    }
+
+    /**
+     * Is the keyguard currently showing?
+     */
+    public boolean isShowing() {
+        return mShowing;
+    }
+
+    /**
+     * Is the keyguard currently showing and not being force hidden?
+     */
+    public boolean isShowingAndNotHidden() {
+        return mShowing && !mHidden;
+    }
+
+    /**
+     * Notify us when the keyguard is hidden by another window
+     */
+    public void setHidden(boolean isHidden) {
+        if (DEBUG) Log.d(TAG, "setHidden " + isHidden);
+        mUpdateMonitor.sendKeyguardVisibilityChanged(!isHidden);
+        mHandler.removeMessages(SET_HIDDEN);
+        Message msg = mHandler.obtainMessage(SET_HIDDEN, (isHidden ? 1 : 0), 0);
+        mHandler.sendMessage(msg);
+    }
+
+    /**
+     * Handles SET_HIDDEN message sent by setHidden()
+     */
+    private void handleSetHidden(boolean isHidden) {
+        synchronized (KeyguardViewMediator.this) {
+            if (mHidden != isHidden) {
+                mHidden = isHidden;
+                updateActivityLockScreenState();
+                adjustStatusBarLocked();
+            }
+        }
+    }
+
+    /**
+     * Used by PhoneWindowManager to enable the keyguard due to a user activity timeout.
+     * This must be safe to call from any thread and with any window manager locks held.
+     */
+    public void doKeyguardTimeout(Bundle options) {
+        mHandler.removeMessages(KEYGUARD_TIMEOUT);
+        Message msg = mHandler.obtainMessage(KEYGUARD_TIMEOUT, options);
+        mHandler.sendMessage(msg);
+    }
+
+    /**
+     * Given the state of the keyguard, is the input restricted?
+     * Input is restricted when the keyguard is showing, or when the keyguard
+     * was suppressed by an app that disabled the keyguard or we haven't been provisioned yet.
+     */
+    public boolean isInputRestricted() {
+        return mShowing || mNeedToReshowWhenReenabled || !mUpdateMonitor.isDeviceProvisioned();
+    }
+
+    private void doKeyguardLocked() {
+        doKeyguardLocked(null);
+    }
+
+    /**
+     * Enable the keyguard if the settings are appropriate.
+     */
+    private void doKeyguardLocked(Bundle options) {
+        // if another app is disabling us, don't show
+        if (!mExternallyEnabled) {
+            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
+
+            // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
+            // for an occasional ugly flicker in this situation:
+            // 1) receive a call with the screen on (no keyguard) or make a call
+            // 2) screen times out
+            // 3) user hits key to turn screen back on
+            // instead, we reenable the keyguard when we know the screen is off and the call
+            // ends (see the broadcast receiver below)
+            // TODO: clean this up when we have better support at the window manager level
+            // for apps that wish to be on top of the keyguard
+            return;
+        }
+
+        // if the keyguard is already showing, don't bother
+        if (mKeyguardViewManager.isShowing()) {
+            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
+            return;
+        }
+
+        // if the setup wizard hasn't run yet, don't show
+        final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim",
+                false);
+        final boolean provisioned = mUpdateMonitor.isDeviceProvisioned();
+        final IccCardConstants.State state = mUpdateMonitor.getSimState();
+        final boolean lockedOrMissing = state.isPinLocked()
+                || ((state == IccCardConstants.State.ABSENT
+                || state == IccCardConstants.State.PERM_DISABLED)
+                && requireSim);
+
+        if (!lockedOrMissing && !provisioned) {
+            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
+                    + " and the sim is not locked or missing");
+            return;
+        }
+
+        if (mUserManager.getUsers(true).size() < 2
+                && mLockPatternUtils.isLockScreenDisabled() && !lockedOrMissing) {
+            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
+            return;
+        }
+
+        if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
+        showLocked(options);
+    }
+
+    /**
+     * Dismiss the keyguard through the security layers.
+     */
+    public void dismiss() {
+        if (mShowing && !mHidden) {
+            mKeyguardViewManager.dismiss();
+        }
+    }
+
+    /**
+     * Send message to keyguard telling it to reset its state.
+     * @param options options about how to show the keyguard
+     * @see #handleReset()
+     */
+    private void resetStateLocked(Bundle options) {
+        if (DEBUG) Log.d(TAG, "resetStateLocked");
+        Message msg = mHandler.obtainMessage(RESET, options);
+        mHandler.sendMessage(msg);
+    }
+
+    /**
+     * Send message to keyguard telling it to verify unlock
+     * @see #handleVerifyUnlock()
+     */
+    private void verifyUnlockLocked() {
+        if (DEBUG) Log.d(TAG, "verifyUnlockLocked");
+        mHandler.sendEmptyMessage(VERIFY_UNLOCK);
+    }
+
+
+    /**
+     * Send a message to keyguard telling it the screen just turned on.
+     * @see #onScreenTurnedOff(int)
+     * @see #handleNotifyScreenOff
+     */
+    private void notifyScreenOffLocked() {
+        if (DEBUG) Log.d(TAG, "notifyScreenOffLocked");
+        mHandler.sendEmptyMessage(NOTIFY_SCREEN_OFF);
+    }
+
+    /**
+     * Send a message to keyguard telling it the screen just turned on.
+     * @see #onScreenTurnedOn()
+     * @see #handleNotifyScreenOn
+     */
+    private void notifyScreenOnLocked(KeyguardViewManager.ShowListener showListener) {
+        if (DEBUG) Log.d(TAG, "notifyScreenOnLocked");
+        Message msg = mHandler.obtainMessage(NOTIFY_SCREEN_ON, showListener);
+        mHandler.sendMessage(msg);
+    }
+
+    /**
+     * Send message to keyguard telling it about a wake key so it can adjust
+     * its state accordingly and then poke the wake lock when it is ready.
+     * @param keyCode The wake key.
+     * @see #handleWakeWhenReady
+     * @see #onWakeKeyWhenKeyguardShowingTq(int)
+     */
+    private void wakeWhenReady(int keyCode) {
+        if (DBG_WAKE) Log.d(TAG, "wakeWhenReady(" + keyCode + ")");
+
+        /**
+         * acquire the handoff lock that will keep the cpu running.  this will
+         * be released once the keyguard has set itself up and poked the other wakelock
+         * in {@link #handleWakeWhenReady(int)}
+         */
+        mWakeAndHandOff.acquire();
+
+        Message msg = mHandler.obtainMessage(WAKE_WHEN_READY, keyCode, 0);
+        mHandler.sendMessage(msg);
+    }
+
+    /**
+     * Send message to keyguard telling it to show itself
+     * @see #handleShow()
+     */
+    private void showLocked(Bundle options) {
+        if (DEBUG) Log.d(TAG, "showLocked");
+        // ensure we stay awake until we are finished displaying the keyguard
+        mShowKeyguardWakeLock.acquire();
+        Message msg = mHandler.obtainMessage(SHOW, options);
+        mHandler.sendMessage(msg);
+    }
+
+    /**
+     * Send message to keyguard telling it to hide itself
+     * @see #handleHide()
+     */
+    private void hideLocked() {
+        if (DEBUG) Log.d(TAG, "hideLocked");
+        Message msg = mHandler.obtainMessage(HIDE);
+        mHandler.sendMessage(msg);
+    }
+
+    public boolean isSecure() {
+        return mLockPatternUtils.isSecure()
+            || KeyguardUpdateMonitor.getInstance(mContext).isSimPinSecure();
+    }
+
+    /**
+     * Update the newUserId. Call while holding WindowManagerService lock.
+     * NOTE: Should only be called by KeyguardViewMediator in response to the user id changing.
+     *
+     * @param newUserId The id of the incoming user.
+     */
+    public void setCurrentUser(int newUserId) {
+        mLockPatternUtils.setCurrentUser(newUserId);
+    }
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (DELAYED_KEYGUARD_ACTION.equals(intent.getAction())) {
+                final int sequence = intent.getIntExtra("seq", 0);
+                if (DEBUG) Log.d(TAG, "received DELAYED_KEYGUARD_ACTION with seq = "
+                        + sequence + ", mDelayedShowingSequence = " + mDelayedShowingSequence);
+                synchronized (KeyguardViewMediator.this) {
+                    if (mDelayedShowingSequence == sequence) {
+                        // Don't play lockscreen SFX if the screen went off due to timeout.
+                        mSuppressNextLockSound = true;
+                        doKeyguardLocked();
+                    }
+                }
+            }
+        }
+    };
+
+    /**
+     * When a key is received when the screen is off and the keyguard is showing,
+     * we need to decide whether to actually turn on the screen, and if so, tell
+     * the keyguard to prepare itself and poke the wake lock when it is ready.
+     *
+     * The 'Tq' suffix is per the documentation in {@link WindowManagerPolicy}.
+     * Be sure not to take any action that takes a long time; any significant
+     * action should be posted to a handler.
+     *
+     * @param keyCode The keycode of the key that woke the device
+     */
+    public void onWakeKeyWhenKeyguardShowingTq(int keyCode) {
+        if (DEBUG) Log.d(TAG, "onWakeKeyWhenKeyguardShowing(" + keyCode + ")");
+
+        // give the keyguard view manager a chance to adjust the state of the
+        // keyguard based on the key that woke the device before poking
+        // the wake lock
+        wakeWhenReady(keyCode);
+    }
+
+    /**
+     * When a wake motion such as an external mouse movement is received when the screen
+     * is off and the keyguard is showing, we need to decide whether to actually turn
+     * on the screen, and if so, tell the keyguard to prepare itself and poke the wake
+     * lock when it is ready.
+     *
+     * The 'Tq' suffix is per the documentation in {@link WindowManagerPolicy}.
+     * Be sure not to take any action that takes a long time; any significant
+     * action should be posted to a handler.
+     */
+    public void onWakeMotionWhenKeyguardShowingTq() {
+        if (DEBUG) Log.d(TAG, "onWakeMotionWhenKeyguardShowing()");
+
+        // give the keyguard view manager a chance to adjust the state of the
+        // keyguard based on the key that woke the device before poking
+        // the wake lock
+        wakeWhenReady(KeyEvent.KEYCODE_UNKNOWN);
+    }
+
+    public void keyguardDone(boolean authenticated, boolean wakeup) {
+        mKeyguardDonePending = false;
+        synchronized (this) {
+            EventLog.writeEvent(70000, 2);
+            if (DEBUG) Log.d(TAG, "keyguardDone(" + authenticated + ")");
+            Message msg = mHandler.obtainMessage(KEYGUARD_DONE);
+            msg.arg1 = wakeup ? 1 : 0;
+            mHandler.sendMessage(msg);
+
+            if (authenticated) {
+                mUpdateMonitor.clearFailedUnlockAttempts();
+            }
+
+            if (mExitSecureCallback != null) {
+                mExitSecureCallback.onKeyguardExitResult(authenticated);
+                mExitSecureCallback = null;
+
+                if (authenticated) {
+                    // after succesfully exiting securely, no need to reshow
+                    // the keyguard when they've released the lock
+                    mExternallyEnabled = true;
+                    mNeedToReshowWhenReenabled = false;
+                }
+            }
+        }
+    }
+
+    /**
+     * This handler will be associated with the policy thread, which will also
+     * be the UI thread of the keyguard.  Since the apis of the policy, and therefore
+     * this class, can be called by other threads, any action that directly
+     * interacts with the keyguard ui should be posted to this handler, rather
+     * than called directly.
+     */
+    private Handler mHandler = new Handler(Looper.myLooper(), null, true /*async*/) {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case SHOW:
+                    handleShow((Bundle) msg.obj);
+                    return ;
+                case HIDE:
+                    handleHide();
+                    return ;
+                case RESET:
+                    handleReset((Bundle) msg.obj);
+                    return ;
+                case VERIFY_UNLOCK:
+                    handleVerifyUnlock();
+                    return;
+                case NOTIFY_SCREEN_OFF:
+                    handleNotifyScreenOff();
+                    return;
+                case NOTIFY_SCREEN_ON:
+                    handleNotifyScreenOn((KeyguardViewManager.ShowListener)msg.obj);
+                    return;
+                case WAKE_WHEN_READY:
+                    handleWakeWhenReady(msg.arg1);
+                    return;
+                case KEYGUARD_DONE:
+                    handleKeyguardDone(msg.arg1 != 0);
+                    return;
+                case KEYGUARD_DONE_DRAWING:
+                    handleKeyguardDoneDrawing();
+                    return;
+                case KEYGUARD_DONE_AUTHENTICATING:
+                    keyguardDone(true, true);
+                    return;
+                case SET_HIDDEN:
+                    handleSetHidden(msg.arg1 != 0);
+                    break;
+                case KEYGUARD_TIMEOUT:
+                    synchronized (KeyguardViewMediator.this) {
+                        doKeyguardLocked((Bundle) msg.obj);
+                    }
+                    break;
+                case SHOW_ASSISTANT:
+                    handleShowAssistant();
+                    break;
+            }
+        }
+    };
+
+    /**
+     * @see #keyguardDone
+     * @see #KEYGUARD_DONE
+     */
+    private void handleKeyguardDone(boolean wakeup) {
+        if (DEBUG) Log.d(TAG, "handleKeyguardDone");
+        handleHide();
+        if (wakeup) {
+            wakeUp();
+        }
+
+        sendUserPresentBroadcast();
+    }
+
+    private void sendUserPresentBroadcast() {
+        if (!(mContext instanceof Activity)) {
+            final UserHandle currentUser = new UserHandle(mLockPatternUtils.getCurrentUser());
+            mContext.sendBroadcastAsUser(mUserPresentIntent, currentUser);
+        }
+    }
+
+    /**
+     * @see #keyguardDoneDrawing
+     * @see #KEYGUARD_DONE_DRAWING
+     */
+    private void handleKeyguardDoneDrawing() {
+        synchronized(this) {
+            if (false) Log.d(TAG, "handleKeyguardDoneDrawing");
+            if (mWaitingUntilKeyguardVisible) {
+                if (DEBUG) Log.d(TAG, "handleKeyguardDoneDrawing: notifying mWaitingUntilKeyguardVisible");
+                mWaitingUntilKeyguardVisible = false;
+                notifyAll();
+
+                // there will usually be two of these sent, one as a timeout, and one
+                // as a result of the callback, so remove any remaining messages from
+                // the queue
+                mHandler.removeMessages(KEYGUARD_DONE_DRAWING);
+            }
+        }
+    }
+
+    private void playSounds(boolean locked) {
+        // User feedback for keyguard.
+
+        if (mSuppressNextLockSound) {
+            mSuppressNextLockSound = false;
+            return;
+        }
+
+        final ContentResolver cr = mContext.getContentResolver();
+        if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) {
+            final int whichSound = locked
+                ? mLockSoundId
+                : mUnlockSoundId;
+            mLockSounds.stop(mLockSoundStreamId);
+            // Init mAudioManager
+            if (mAudioManager == null) {
+                mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+                if (mAudioManager == null) return;
+                mMasterStreamType = mAudioManager.getMasterStreamType();
+            }
+            // If the stream is muted, don't play the sound
+            if (mAudioManager.isStreamMute(mMasterStreamType)) return;
+
+            mLockSoundStreamId = mLockSounds.play(whichSound,
+                    mLockSoundVolume, mLockSoundVolume, 1/*priortiy*/, 0/*loop*/, 1.0f/*rate*/);
+        }
+    }
+
+    private void updateActivityLockScreenState() {
+        try {
+            ActivityManagerNative.getDefault().setLockScreenShown(
+                    mShowing && !mHidden);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Handle message sent by {@link #showLocked}.
+     * @see #SHOW
+     */
+    private void handleShow(Bundle options) {
+        synchronized (KeyguardViewMediator.this) {
+            if (DEBUG) Log.d(TAG, "handleShow");
+            if (!mSystemReady) return;
+
+            mKeyguardViewManager.show(options);
+            mShowing = true;
+            mKeyguardDonePending = false;
+            updateActivityLockScreenState();
+            adjustStatusBarLocked();
+            userActivity();
+            try {
+                ActivityManagerNative.getDefault().closeSystemDialogs("lock");
+            } catch (RemoteException e) {
+            }
+
+            // Do this at the end to not slow down display of the keyguard.
+            playSounds(true);
+
+            mShowKeyguardWakeLock.release();
+        }
+    }
+
+    /**
+     * Handle message sent by {@link #hideLocked()}
+     * @see #HIDE
+     */
+    private void handleHide() {
+        synchronized (KeyguardViewMediator.this) {
+            if (DEBUG) Log.d(TAG, "handleHide");
+            if (mWakeAndHandOff.isHeld()) {
+                Log.w(TAG, "attempt to hide the keyguard while waking, ignored");
+                return;
+            }
+
+            // only play "unlock" noises if not on a call (since the incall UI
+            // disables the keyguard)
+            if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) {
+                playSounds(false);
+            }
+
+            mKeyguardViewManager.hide();
+            mShowing = false;
+            mKeyguardDonePending = false;
+            updateActivityLockScreenState();
+            adjustStatusBarLocked();
+        }
+    }
+
+    private void adjustStatusBarLocked() {
+        if (mStatusBarManager == null) {
+            mStatusBarManager = (StatusBarManager)
+                    mContext.getSystemService(Context.STATUS_BAR_SERVICE);
+        }
+        if (mStatusBarManager == null) {
+            Log.w(TAG, "Could not get status bar manager");
+        } else {
+            if (mShowLockIcon) {
+                // Give feedback to user when secure keyguard is active and engaged
+                if (mShowing && isSecure()) {
+                    if (!mShowingLockIcon) {
+                        String contentDescription = mContext.getString(
+                                com.android.internal.R.string.status_bar_device_locked);
+                        mStatusBarManager.setIcon("secure",
+                                com.android.internal.R.drawable.stat_sys_secure, 0,
+                                contentDescription);
+                        mShowingLockIcon = true;
+                    }
+                } else {
+                    if (mShowingLockIcon) {
+                        mStatusBarManager.removeIcon("secure");
+                        mShowingLockIcon = false;
+                    }
+                }
+            }
+
+            // Disable aspects of the system/status/navigation bars that must not be re-enabled by
+            // windows that appear on top, ever
+            int flags = StatusBarManager.DISABLE_NONE;
+            if (mShowing) {
+                // Permanently disable components not available when keyguard is enabled
+                // (like recents). Temporary enable/disable (e.g. the "back" button) are
+                // done in KeyguardHostView.
+                flags |= StatusBarManager.DISABLE_RECENT;
+                if (isSecure() || !ENABLE_INSECURE_STATUS_BAR_EXPAND) {
+                    // showing secure lockscreen; disable expanding.
+                    flags |= StatusBarManager.DISABLE_EXPAND;
+                }
+                if (isSecure()) {
+                    // showing secure lockscreen; disable ticker.
+                    flags |= StatusBarManager.DISABLE_NOTIFICATION_TICKER;
+                }
+            }
+
+            if (DEBUG) {
+                Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mHidden=" + mHidden
+                        + " isSecure=" + isSecure() + " --> flags=0x" + Integer.toHexString(flags));
+            }
+
+            if (!(mContext instanceof Activity)) {
+                mStatusBarManager.disable(flags);
+            }
+        }
+    }
+
+    /**
+     * Handle message sent by {@link #wakeWhenReady(int)}
+     * @param keyCode The key that woke the device.
+     * @see #WAKE_WHEN_READY
+     */
+    private void handleWakeWhenReady(int keyCode) {
+        synchronized (KeyguardViewMediator.this) {
+            if (DBG_WAKE) Log.d(TAG, "handleWakeWhenReady(" + keyCode + ")");
+
+            // this should result in a call to 'poke wakelock' which will set a timeout
+            // on releasing the wakelock
+            if (!mKeyguardViewManager.wakeWhenReadyTq(keyCode)) {
+                // poke wakelock ourselves if keyguard is no longer active
+                Log.w(TAG, "mKeyguardViewManager.wakeWhenReadyTq did not poke wake lock, so poke it ourselves");
+                userActivity();
+            }
+
+            /**
+             * Now that the keyguard is ready and has poked the wake lock, we can
+             * release the handoff wakelock
+             */
+            mWakeAndHandOff.release();
+        }
+    }
+
+    /**
+     * Handle message sent by {@link #resetStateLocked(Bundle)}
+     * @see #RESET
+     */
+    private void handleReset(Bundle options) {
+        synchronized (KeyguardViewMediator.this) {
+            if (DEBUG) Log.d(TAG, "handleReset");
+            mKeyguardViewManager.reset(options);
+        }
+    }
+
+    /**
+     * Handle message sent by {@link #verifyUnlock}
+     * @see #VERIFY_UNLOCK
+     */
+    private void handleVerifyUnlock() {
+        synchronized (KeyguardViewMediator.this) {
+            if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
+            mKeyguardViewManager.verifyUnlock();
+            mShowing = true;
+            updateActivityLockScreenState();
+        }
+    }
+
+    /**
+     * Handle message sent by {@link #notifyScreenOffLocked()}
+     * @see #NOTIFY_SCREEN_OFF
+     */
+    private void handleNotifyScreenOff() {
+        synchronized (KeyguardViewMediator.this) {
+            if (DEBUG) Log.d(TAG, "handleNotifyScreenOff");
+            mKeyguardViewManager.onScreenTurnedOff();
+        }
+    }
+
+    /**
+     * Handle message sent by {@link #notifyScreenOnLocked()}
+     * @see #NOTIFY_SCREEN_ON
+     */
+    private void handleNotifyScreenOn(KeyguardViewManager.ShowListener showListener) {
+        synchronized (KeyguardViewMediator.this) {
+            if (DEBUG) Log.d(TAG, "handleNotifyScreenOn");
+            mKeyguardViewManager.onScreenTurnedOn(showListener);
+        }
+    }
+
+    public boolean isDismissable() {
+        return mKeyguardDonePending || !isSecure();
+    }
+
+    public void showAssistant() {
+        Message msg = mHandler.obtainMessage(SHOW_ASSISTANT);
+        mHandler.sendMessage(msg);
+    }
+
+    public void handleShowAssistant() {
+        mKeyguardViewManager.showAssistant();
+    }
+
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java
new file mode 100644
index 0000000..0a166e1
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java
@@ -0,0 +1,333 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.appwidget.AppWidgetManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.view.View;
+
+public class KeyguardViewStateManager implements
+        SlidingChallengeLayout.OnChallengeScrolledListener,
+        ChallengeLayout.OnBouncerStateChangedListener {
+
+    private KeyguardWidgetPager mKeyguardWidgetPager;
+    private ChallengeLayout mChallengeLayout;
+    private KeyguardHostView mKeyguardHostView;
+    private int[] mTmpPoint = new int[2];
+    private int[] mTmpLoc = new int[2];
+
+    private KeyguardSecurityView mKeyguardSecurityContainer;
+    private static final int SCREEN_ON_HINT_DURATION = 1000;
+    private static final int SCREEN_ON_RING_HINT_DELAY = 300;
+    Handler mMainQueue = new Handler(Looper.myLooper());
+
+    // transport control states
+    static final int TRANSPORT_GONE = 0;
+    static final int TRANSPORT_INVISIBLE = 1;
+    static final int TRANSPORT_VISIBLE = 2;
+
+    private int mTransportState = TRANSPORT_GONE;
+
+    int mLastScrollState = SlidingChallengeLayout.SCROLL_STATE_IDLE;
+
+    // Paged view state
+    private int mPageListeningToSlider = -1;
+    private int mCurrentPage = -1;
+    private int mPageIndexOnPageBeginMoving = -1;
+
+    int mChallengeTop = 0;
+
+    public KeyguardViewStateManager(KeyguardHostView hostView) {
+        mKeyguardHostView = hostView;
+    }
+
+    public void setPagedView(KeyguardWidgetPager pagedView) {
+        mKeyguardWidgetPager = pagedView;
+        updateEdgeSwiping();
+    }
+
+    public void setChallengeLayout(ChallengeLayout layout) {
+        mChallengeLayout = layout;
+        updateEdgeSwiping();
+    }
+
+    private void updateEdgeSwiping() {
+        if (mChallengeLayout != null && mKeyguardWidgetPager != null) {
+            if (mChallengeLayout.isChallengeOverlapping()) {
+                mKeyguardWidgetPager.setOnlyAllowEdgeSwipes(true);
+            } else {
+                mKeyguardWidgetPager.setOnlyAllowEdgeSwipes(false);
+            }
+        }
+    }
+
+    public boolean isChallengeShowing() {
+        if (mChallengeLayout != null) {
+            return mChallengeLayout.isChallengeShowing();
+        }
+        return false;
+    }
+
+    public boolean isChallengeOverlapping() {
+        if (mChallengeLayout != null) {
+            return mChallengeLayout.isChallengeOverlapping();
+        }
+        return false;
+    }
+
+    public void setSecurityViewContainer(KeyguardSecurityView container) {
+        mKeyguardSecurityContainer = container;
+    }
+
+    public void showBouncer(boolean show) {
+        mChallengeLayout.showBouncer();
+    }
+
+    public boolean isBouncing() {
+        return mChallengeLayout.isBouncing();
+    }
+
+    public void fadeOutSecurity(int duration) {
+        ((View) mKeyguardSecurityContainer).animate().alpha(0).setDuration(duration);
+    }
+
+    public void fadeInSecurity(int duration) {
+        ((View) mKeyguardSecurityContainer).animate().alpha(1f).setDuration(duration);
+    }
+
+    public void onPageBeginMoving() {
+        if (mChallengeLayout.isChallengeOverlapping() &&
+                mChallengeLayout instanceof SlidingChallengeLayout) {
+            SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
+            scl.fadeOutChallenge();
+            mPageIndexOnPageBeginMoving = mKeyguardWidgetPager.getCurrentPage();
+        }
+        // We use mAppWidgetToShow to show a particular widget after you add it--
+        // once the user swipes a page we clear that behavior
+        if (mKeyguardHostView != null) {
+            mKeyguardHostView.clearAppWidgetToShow();
+            mKeyguardHostView.setOnDismissAction(null);
+        }
+        if (mHideHintsRunnable != null) {
+            mMainQueue.removeCallbacks(mHideHintsRunnable);
+            mHideHintsRunnable = null;
+        }
+    }
+
+    public void onPageEndMoving() {
+        mPageIndexOnPageBeginMoving = -1;
+    }
+
+    public void onPageSwitching(View newPage, int newPageIndex) {
+        if (mKeyguardWidgetPager != null && mChallengeLayout instanceof SlidingChallengeLayout) {
+            boolean isCameraPage = newPage instanceof CameraWidgetFrame;
+            ((SlidingChallengeLayout) mChallengeLayout).setChallengeInteractive(!isCameraPage);
+        }
+
+        // If the page we're settling to is the same as we started on, and the action of
+        // moving the page hid the security, we restore it immediately.
+        if (mPageIndexOnPageBeginMoving == mKeyguardWidgetPager.getNextPage() &&
+                mChallengeLayout instanceof SlidingChallengeLayout) {
+            SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
+            scl.fadeInChallenge();
+            mKeyguardWidgetPager.setWidgetToResetOnPageFadeOut(-1);
+        }
+        mPageIndexOnPageBeginMoving = -1;
+    }
+
+    public void onPageSwitched(View newPage, int newPageIndex) {
+        // Reset the previous page size and ensure the current page is sized appropriately.
+        // We only modify the page state if it is not currently under control by the slider.
+        // This prevents conflicts.
+
+        // If the page hasn't switched, don't bother with any of this
+        if (mCurrentPage == newPageIndex) return;
+
+        if (mKeyguardWidgetPager != null && mChallengeLayout != null) {
+            KeyguardWidgetFrame prevPage = mKeyguardWidgetPager.getWidgetPageAt(mCurrentPage);
+            if (prevPage != null && mCurrentPage != mPageListeningToSlider && mCurrentPage
+                    != mKeyguardWidgetPager.getWidgetToResetOnPageFadeOut()) {
+                prevPage.resetSize();
+            }
+
+            KeyguardWidgetFrame newCurPage = mKeyguardWidgetPager.getWidgetPageAt(newPageIndex);
+            boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
+            if (challengeOverlapping && !newCurPage.isSmall()
+                    && mPageListeningToSlider != newPageIndex) {
+                newCurPage.shrinkWidget();
+            }
+        }
+
+        mCurrentPage = newPageIndex;
+    }
+
+    private int getChallengeTopRelativeToFrame(KeyguardWidgetFrame frame, int top) {
+        mTmpPoint[0] = 0;
+        mTmpPoint[1] = top;
+        mapPoint((View) mChallengeLayout, frame, mTmpPoint);
+        return mTmpPoint[1];
+    }
+
+    /**
+     * Simple method to map a point from one view's coordinates to another's. Note: this method
+     * doesn't account for transforms, so if the views will be transformed, this should not be used.
+     *
+     * @param fromView The view to which the point is relative
+     * @param toView The view into which the point should be mapped
+     * @param pt The point
+     */
+    private void mapPoint(View fromView, View toView, int pt[]) {
+        fromView.getLocationInWindow(mTmpLoc);
+
+        int x = mTmpLoc[0];
+        int y = mTmpLoc[1];
+
+        toView.getLocationInWindow(mTmpLoc);
+        int vX = mTmpLoc[0];
+        int vY = mTmpLoc[1];
+
+        pt[0] += x - vX;
+        pt[1] += y - vY;
+    }
+
+    private void userActivity() {
+        if (mKeyguardHostView != null) {
+            mKeyguardHostView.onUserActivityTimeoutChanged();
+            mKeyguardHostView.userActivity();
+        }
+    }
+
+    @Override
+    public void onScrollStateChanged(int scrollState) {
+        if (mKeyguardWidgetPager == null || mChallengeLayout == null) return;
+
+        boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
+
+        if (scrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
+            KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
+            if (frame == null) return;
+
+            if (!challengeOverlapping) {
+                if (!mKeyguardWidgetPager.isPageMoving()) {
+                    frame.resetSize();
+                    userActivity();
+                } else {
+                    mKeyguardWidgetPager.setWidgetToResetOnPageFadeOut(mPageListeningToSlider);
+                }
+            }
+            if (frame.isSmall()) {
+                // This is to make sure that if the scroller animation gets cut off midway
+                // that the frame doesn't stay in a partial down position.
+                frame.setFrameHeight(frame.getSmallFrameHeight());
+            }
+            if (scrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
+                frame.hideFrame(this);
+            }
+            updateEdgeSwiping();
+
+            if (mChallengeLayout.isChallengeShowing()) {
+                mKeyguardSecurityContainer.onResume(KeyguardSecurityView.VIEW_REVEALED);
+            } else {
+                mKeyguardSecurityContainer.onPause();
+            }
+            mPageListeningToSlider = -1;
+        } else if (mLastScrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
+            // Whether dragging or settling, if the last state was idle, we use this signal
+            // to update the current page who will receive events from the sliding challenge.
+            // We resize the frame as appropriate.
+            mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
+            KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
+            if (frame == null) return;
+
+            // Skip showing the frame and shrinking the widget if we are
+            if (!mChallengeLayout.isBouncing()) {
+                if (scrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
+                    frame.showFrame(this);
+                }
+
+                // As soon as the security begins sliding, the widget becomes small (if it wasn't
+                // small to begin with).
+                if (!frame.isSmall()) {
+                    // We need to fetch the final page, in case the pages are in motion.
+                    mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
+                    frame.shrinkWidget(false);
+                }
+            } else {
+                if (!frame.isSmall()) {
+                    // We need to fetch the final page, in case the pages are in motion.
+                    mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
+                }
+            }
+
+            // View is on the move.  Pause the security view until it completes.
+            mKeyguardSecurityContainer.onPause();
+        }
+        mLastScrollState = scrollState;
+    }
+
+    @Override
+    public void onScrollPositionChanged(float scrollPosition, int challengeTop) {
+        mChallengeTop = challengeTop;
+        KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
+        if (frame != null && mLastScrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
+            frame.adjustFrame(getChallengeTopRelativeToFrame(frame, mChallengeTop));
+        }
+    }
+
+    private Runnable mHideHintsRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (mKeyguardWidgetPager != null) {
+                mKeyguardWidgetPager.hideOutlinesAndSidePages();
+            }
+        }
+    };
+
+    public void showUsabilityHints() {
+        mMainQueue.postDelayed( new Runnable() {
+            @Override
+            public void run() {
+                mKeyguardSecurityContainer.showUsabilityHint();
+            }
+        } , SCREEN_ON_RING_HINT_DELAY);
+        mKeyguardWidgetPager.showInitialPageHints();
+        if (mHideHintsRunnable != null) {
+            mMainQueue.postDelayed(mHideHintsRunnable, SCREEN_ON_HINT_DURATION);
+        }
+    }
+
+    public void setTransportState(int state) {
+        mTransportState = state;
+    }
+
+    public int getTransportState() {
+        return mTransportState;
+    }
+
+    // ChallengeLayout.OnBouncerStateChangedListener
+    @Override
+    public void onBouncerStateChanged(boolean bouncerActive) {
+        if (bouncerActive) {
+            mKeyguardWidgetPager.zoomOutToBouncer();
+        } else {
+            mKeyguardWidgetPager.zoomInFromBouncer();
+            if (mKeyguardHostView != null) {
+                mKeyguardHostView.setOnDismissAction(null);
+            }
+        }
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java
new file mode 100644
index 0000000..debf765
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java
@@ -0,0 +1,270 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+
+import java.util.ArrayList;
+
+import com.android.internal.R;
+
+public class KeyguardWidgetCarousel extends KeyguardWidgetPager {
+
+    private float mAdjacentPagesAngle;
+    private static float MAX_SCROLL_PROGRESS = 1.3f;
+    private static float CAMERA_DISTANCE = 10000;
+    protected AnimatorSet mChildrenTransformsAnimator;
+    float[] mTmpTransform = new float[3];
+
+    public KeyguardWidgetCarousel(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public KeyguardWidgetCarousel(Context context) {
+        this(context, null, 0);
+    }
+
+    public KeyguardWidgetCarousel(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mAdjacentPagesAngle = context.getResources().getInteger(R.integer.kg_carousel_angle);
+    }
+
+    protected float getMaxScrollProgress() {
+        return MAX_SCROLL_PROGRESS;
+    }
+
+    public float getAlphaForPage(int screenCenter, int index) {
+        View child = getChildAt(index);
+        if (child == null) return 0f;
+
+        float scrollProgress = getScrollProgress(screenCenter, child, index);
+        if (!isOverScrollChild(index, scrollProgress)) {
+            scrollProgress = getBoundedScrollProgress(screenCenter, child, index);
+            float alpha = 1.0f - 1.0f * Math.abs(scrollProgress / MAX_SCROLL_PROGRESS);
+            return alpha;
+        } else {
+            return 1.0f;
+        }
+    }
+
+    private void updatePageAlphaValues(int screenCenter) {
+        if (mChildrenOutlineFadeAnimation != null) {
+            mChildrenOutlineFadeAnimation.cancel();
+            mChildrenOutlineFadeAnimation = null;
+        }
+        if (!isReordering(false)) {
+            for (int i = 0; i < getChildCount(); i++) {
+                KeyguardWidgetFrame child = getWidgetPageAt(i);
+                if (child != null) {
+                    child.setBackgroundAlpha(getOutlineAlphaForPage(screenCenter, i));
+                    child.setContentAlpha(getAlphaForPage(screenCenter, i));
+                }
+            }
+        }
+    }
+
+    public void showInitialPageHints() {
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            KeyguardWidgetFrame child = getWidgetPageAt(i);
+            if (i >= mCurrentPage - 1 && i <= mCurrentPage + 1) {
+                child.fadeFrame(this, true, KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER,
+                        CHILDREN_OUTLINE_FADE_IN_DURATION);
+            }
+        }
+    }
+
+    @Override
+    protected void screenScrolled(int screenCenter) {
+        mScreenCenter = screenCenter;
+        updatePageAlphaValues(screenCenter);
+        if (isReordering(false)) return;
+        for (int i = 0; i < getChildCount(); i++) {
+            KeyguardWidgetFrame v = getWidgetPageAt(i);
+            float scrollProgress = getScrollProgress(screenCenter, v, i);
+            float boundedProgress = getBoundedScrollProgress(screenCenter, v, i);
+            if (v == mDragView || v == null) continue;
+            v.setCameraDistance(CAMERA_DISTANCE);
+
+            if (isOverScrollChild(i, scrollProgress)) {
+                v.setRotationY(- OVERSCROLL_MAX_ROTATION * scrollProgress);
+                v.setOverScrollAmount(Math.abs(scrollProgress), scrollProgress < 0);
+            } else {
+                int width = v.getMeasuredWidth();
+                float pivotX = (width / 2f) + boundedProgress * (width / 2f);
+                float pivotY = v.getMeasuredHeight() / 2;
+                float rotationY = - mAdjacentPagesAngle * boundedProgress;
+                v.setPivotX(pivotX);
+                v.setPivotY(pivotY);
+                v.setRotationY(rotationY);
+                v.setOverScrollAmount(0f, false);
+            }
+            float alpha = v.getAlpha();
+            // If the view has 0 alpha, we set it to be invisible so as to prevent
+            // it from accepting touches
+            if (alpha == 0) {
+                v.setVisibility(INVISIBLE);
+            } else if (v.getVisibility() != VISIBLE) {
+                v.setVisibility(VISIBLE);
+            }
+        }
+    }
+
+    void animatePagesToNeutral() {
+        if (mChildrenTransformsAnimator != null) {
+            mChildrenTransformsAnimator.cancel();
+            mChildrenTransformsAnimator = null;
+        }
+
+        int count = getChildCount();
+        PropertyValuesHolder alpha;
+        PropertyValuesHolder outlineAlpha;
+        PropertyValuesHolder rotationY;
+        ArrayList<Animator> anims = new ArrayList<Animator>();
+
+        for (int i = 0; i < count; i++) {
+            KeyguardWidgetFrame child = getWidgetPageAt(i);
+            boolean inVisibleRange = (i >= mCurrentPage - 1 && i <= mCurrentPage + 1);
+            if (!inVisibleRange) {
+                child.setRotationY(0f);
+            }
+            alpha = PropertyValuesHolder.ofFloat("contentAlpha", 1.0f);
+            outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha",
+                    KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER);
+            rotationY = PropertyValuesHolder.ofFloat("rotationY", 0f);
+            ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha, rotationY);
+            child.setVisibility(VISIBLE);
+            if (!inVisibleRange) {
+                a.setInterpolator(mSlowFadeInterpolator);
+            }
+            anims.add(a);
+        }
+
+        int duration = REORDERING_ZOOM_IN_OUT_DURATION;
+        mChildrenTransformsAnimator = new AnimatorSet();
+        mChildrenTransformsAnimator.playTogether(anims);
+
+        mChildrenTransformsAnimator.setDuration(duration);
+        mChildrenTransformsAnimator.start();
+    }
+
+    private void getTransformForPage(int screenCenter, int index, float[] transform) {
+        View child = getChildAt(index);
+        float boundedProgress = getBoundedScrollProgress(screenCenter, child, index);
+        float rotationY = - mAdjacentPagesAngle * boundedProgress;
+        int width = child.getMeasuredWidth();
+        float pivotX = (width / 2f) + boundedProgress * (width / 2f);
+        float pivotY = child.getMeasuredHeight() / 2;
+
+        transform[0] = pivotX;
+        transform[1] = pivotY;
+        transform[2] = rotationY;
+    }
+
+    Interpolator mFastFadeInterpolator = new Interpolator() {
+        Interpolator mInternal = new DecelerateInterpolator(1.5f);
+        float mFactor = 2.5f;
+        @Override
+        public float getInterpolation(float input) {
+            return mInternal.getInterpolation(Math.min(mFactor * input, 1f));
+        }
+    };
+
+    Interpolator mSlowFadeInterpolator = new Interpolator() {
+        Interpolator mInternal = new AccelerateInterpolator(1.5f);
+        float mFactor = 1.3f;
+        @Override
+        public float getInterpolation(float input) {
+            input -= (1 - 1 / mFactor);
+            input = mFactor * Math.max(input, 0f);
+            return mInternal.getInterpolation(input);
+        }
+    };
+
+    void animatePagesToCarousel() {
+        if (mChildrenTransformsAnimator != null) {
+            mChildrenTransformsAnimator.cancel();
+            mChildrenTransformsAnimator = null;
+        }
+
+        int count = getChildCount();
+        PropertyValuesHolder alpha;
+        PropertyValuesHolder outlineAlpha;
+        PropertyValuesHolder rotationY;
+        PropertyValuesHolder pivotX;
+        PropertyValuesHolder pivotY;
+        ArrayList<Animator> anims = new ArrayList<Animator>();
+
+        for (int i = 0; i < count; i++) {
+            KeyguardWidgetFrame child = getWidgetPageAt(i);
+            float finalAlpha = getAlphaForPage(mScreenCenter, i);
+            float finalOutlineAlpha = getOutlineAlphaForPage(mScreenCenter, i);
+            getTransformForPage(mScreenCenter, i, mTmpTransform);
+
+            boolean inVisibleRange = (i >= mCurrentPage - 1 && i <= mCurrentPage + 1);
+
+            ObjectAnimator a;
+            alpha = PropertyValuesHolder.ofFloat("contentAlpha", finalAlpha);
+            outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", finalOutlineAlpha);
+            pivotX = PropertyValuesHolder.ofFloat("pivotX", mTmpTransform[0]);
+            pivotY = PropertyValuesHolder.ofFloat("pivotY", mTmpTransform[1]);
+            rotationY = PropertyValuesHolder.ofFloat("rotationY", mTmpTransform[2]);
+
+            if (inVisibleRange) {
+                // for the central pages we animate into a rotated state
+                a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha,
+                        pivotX, pivotY, rotationY);
+            } else {
+                a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha);
+                a.setInterpolator(mFastFadeInterpolator);
+            }
+            anims.add(a);
+        }
+
+        int duration = REORDERING_ZOOM_IN_OUT_DURATION;
+        mChildrenTransformsAnimator = new AnimatorSet();
+        mChildrenTransformsAnimator.playTogether(anims);
+
+        mChildrenTransformsAnimator.setDuration(duration);
+        mChildrenTransformsAnimator.start();
+    }
+
+    protected void reorderStarting() {
+        mViewStateManager.fadeOutSecurity(REORDERING_ZOOM_IN_OUT_DURATION);
+        animatePagesToNeutral();
+    }
+
+    protected boolean zoomIn(final Runnable onCompleteRunnable) {
+        animatePagesToCarousel();
+        return super.zoomIn(onCompleteRunnable);
+    }
+
+    @Override
+    protected void onEndReordering() {
+        super.onEndReordering();
+        mViewStateManager.fadeInSecurity(REORDERING_ZOOM_IN_OUT_DURATION);
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
new file mode 100644
index 0000000..3c79206
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
@@ -0,0 +1,522 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetManager;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.Shader;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.internal.R;
+
+public class KeyguardWidgetFrame extends FrameLayout {
+    private final static PorterDuffXfermode sAddBlendMode =
+            new PorterDuffXfermode(PorterDuff.Mode.ADD);
+
+    static final float OUTLINE_ALPHA_MULTIPLIER = 0.6f;
+    static final int HOVER_OVER_DELETE_DROP_TARGET_OVERLAY_COLOR = 0x99FF0000;
+
+    // Temporarily disable this for the time being until we know why the gfx is messing up
+    static final boolean ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY = true;
+
+    private int mGradientColor;
+    private LinearGradient mForegroundGradient;
+    private LinearGradient mLeftToRightGradient;
+    private LinearGradient mRightToLeftGradient;
+    private Paint mGradientPaint = new Paint();
+    boolean mLeftToRight = true;
+
+    private float mOverScrollAmount = 0f;
+    private final Rect mForegroundRect = new Rect();
+    private int mForegroundAlpha = 0;
+    private CheckLongPressHelper mLongPressHelper;
+    private Animator mFrameFade;
+    private boolean mIsSmall = false;
+    private Handler mWorkerHandler;
+
+    private float mBackgroundAlpha;
+    private float mContentAlpha;
+    private float mBackgroundAlphaMultiplier = 1.0f;
+    private Drawable mBackgroundDrawable;
+    private Rect mBackgroundRect = new Rect();
+
+    // These variables are all needed in order to size things properly before we're actually
+    // measured.
+    private int mSmallWidgetHeight;
+    private int mSmallFrameHeight;
+    private boolean mWidgetLockedSmall = false;
+    private int mMaxChallengeTop = -1;
+    private int mFrameStrokeAdjustment;
+    private boolean mPerformAppWidgetSizeUpdateOnBootComplete;
+
+    // This will hold the width value before we've actually been measured
+    private int mFrameHeight;
+
+    private boolean mIsHoveringOverDeleteDropTarget;
+
+    // Multiple callers may try and adjust the alpha of the frame. When a caller shows
+    // the outlines, we give that caller control, and nobody else can fade them out.
+    // This prevents animation conflicts.
+    private Object mBgAlphaController;
+
+    public KeyguardWidgetFrame(Context context) {
+        this(context, null, 0);
+    }
+
+    public KeyguardWidgetFrame(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public KeyguardWidgetFrame(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        mLongPressHelper = new CheckLongPressHelper(this);
+
+        Resources res = context.getResources();
+        // TODO: this padding should really correspond to the padding embedded in the background
+        // drawable (ie. outlines).
+        float density = res.getDisplayMetrics().density;
+        int padding = (int) (res.getDisplayMetrics().density * 8);
+        setPadding(padding, padding, padding, padding);
+
+        mFrameStrokeAdjustment = 2 + (int) (2 * density);
+
+        // This will be overriden on phones based on the current security mode, however on tablets
+        // we need to specify a height.
+        mSmallWidgetHeight =
+                res.getDimensionPixelSize(com.android.internal.R.dimen.kg_small_widget_height);
+        mBackgroundDrawable = res.getDrawable(R.drawable.kg_widget_bg_padded);
+        mGradientColor = res.getColor(com.android.internal.R.color.kg_widget_pager_gradient);
+        mGradientPaint.setXfermode(sAddBlendMode);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        cancelLongPress();
+        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallbacks);
+
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallbacks);
+    }
+
+    private KeyguardUpdateMonitorCallback mUpdateMonitorCallbacks =
+            new KeyguardUpdateMonitorCallback() {
+        @Override
+        public void onBootCompleted() {
+            if (mPerformAppWidgetSizeUpdateOnBootComplete) {
+                performAppWidgetSizeCallbacksIfNecessary();
+                mPerformAppWidgetSizeUpdateOnBootComplete = false;
+            }
+        }
+    };
+
+    void setIsHoveringOverDeleteDropTarget(boolean isHovering) {
+        if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
+            if (mIsHoveringOverDeleteDropTarget != isHovering) {
+                mIsHoveringOverDeleteDropTarget = isHovering;
+                invalidate();
+            }
+        }
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        // Watch for longpress events at this level to make sure
+        // users can always pick up this widget
+        switch (ev.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                mLongPressHelper.postCheckForLongPress(ev);
+                break;
+            case MotionEvent.ACTION_MOVE:
+                mLongPressHelper.onMove(ev);
+                break;
+            case MotionEvent.ACTION_POINTER_DOWN:
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                mLongPressHelper.cancelLongPress();
+                break;
+        }
+
+        // Otherwise continue letting touch events fall through to children
+        return false;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        // Watch for longpress events at this level to make sure
+        // users can always pick up this widget
+        switch (ev.getAction()) {
+            case MotionEvent.ACTION_MOVE:
+                mLongPressHelper.onMove(ev);
+                break;
+            case MotionEvent.ACTION_POINTER_DOWN:
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                mLongPressHelper.cancelLongPress();
+                break;
+        }
+
+        // We return true here to ensure that we will get cancel / up signal
+        // even if none of our children have requested touch.
+        return true;
+    }
+
+    @Override
+    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+        super.requestDisallowInterceptTouchEvent(disallowIntercept);
+        cancelLongPress();
+    }
+
+    @Override
+    public void cancelLongPress() {
+        super.cancelLongPress();
+        mLongPressHelper.cancelLongPress();
+    }
+
+
+    private void drawGradientOverlay(Canvas c) {
+        mGradientPaint.setShader(mForegroundGradient);
+        mGradientPaint.setAlpha(mForegroundAlpha);
+        c.drawRect(mForegroundRect, mGradientPaint);
+    }
+
+    private void drawHoveringOverDeleteOverlay(Canvas c) {
+        if (mIsHoveringOverDeleteDropTarget) {
+            c.drawColor(HOVER_OVER_DELETE_DROP_TARGET_OVERLAY_COLOR);
+        }
+    }
+
+    protected void drawBg(Canvas canvas) {
+        if (mBackgroundAlpha > 0.0f) {
+            Drawable bg = mBackgroundDrawable;
+
+            bg.setAlpha((int) (mBackgroundAlpha * mBackgroundAlphaMultiplier * 255));
+            bg.setBounds(mBackgroundRect);
+            bg.draw(canvas);
+        }
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
+            canvas.save();
+        }
+        drawBg(canvas);
+        super.dispatchDraw(canvas);
+        drawGradientOverlay(canvas);
+        if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
+            drawHoveringOverDeleteOverlay(canvas);
+            canvas.restore();
+        }
+    }
+
+    /**
+     * Because this view has fading outlines, it is essential that we enable hardware
+     * layers on the content (child) so that updating the alpha of the outlines doesn't
+     * result in the content layer being recreated.
+     */
+    public void enableHardwareLayersForContent() {
+        View widget = getContent();
+        if (widget != null) {
+            widget.setLayerType(LAYER_TYPE_HARDWARE, null);
+        }
+    }
+
+    /**
+     * Because this view has fading outlines, it is essential that we enable hardware
+     * layers on the content (child) so that updating the alpha of the outlines doesn't
+     * result in the content layer being recreated.
+     */
+    public void disableHardwareLayersForContent() {
+        View widget = getContent();
+        if (widget != null) {
+            widget.setLayerType(LAYER_TYPE_NONE, null);
+        }
+    }
+
+    public void enableHardwareLayers() {
+        setLayerType(LAYER_TYPE_HARDWARE, null);
+    }
+
+    public void disableHardwareLayers() {
+        setLayerType(LAYER_TYPE_NONE, null);
+    }
+
+    public View getContent() {
+        return getChildAt(0);
+    }
+
+    public int getContentAppWidgetId() {
+        View content = getContent();
+        if (content instanceof AppWidgetHostView) {
+            return ((AppWidgetHostView) content).getAppWidgetId();
+        } else if (content instanceof KeyguardStatusView) {
+            return ((KeyguardStatusView) content).getAppWidgetId();
+        } else {
+            return AppWidgetManager.INVALID_APPWIDGET_ID;
+        }
+    }
+
+    public float getBackgroundAlpha() {
+        return mBackgroundAlpha;
+    }
+
+    public void setBackgroundAlphaMultiplier(float multiplier) {
+        if (Float.compare(mBackgroundAlphaMultiplier, multiplier) != 0) {
+            mBackgroundAlphaMultiplier = multiplier;
+            invalidate();
+        }
+    }
+
+    public float getBackgroundAlphaMultiplier() {
+        return mBackgroundAlphaMultiplier;
+    }
+
+    public void setBackgroundAlpha(float alpha) {
+        if (Float.compare(mBackgroundAlpha, alpha) != 0) {
+            mBackgroundAlpha = alpha;
+            invalidate();
+        }
+    }
+
+    public float getContentAlpha() {
+        return mContentAlpha;
+    }
+
+    public void setContentAlpha(float alpha) {
+        mContentAlpha = alpha;
+        View content = getContent();
+        if (content != null) {
+            content.setAlpha(alpha);
+        }
+    }
+
+    /**
+     * Depending on whether the security is up, the widget size needs to change
+     * 
+     * @param height The height of the widget, -1 for full height
+     */
+    private void setWidgetHeight(int height) {
+        boolean needLayout = false;
+        View widget = getContent();
+        if (widget != null) {
+            LayoutParams lp = (LayoutParams) widget.getLayoutParams();
+            if (lp.height != height) {
+                needLayout = true;
+                lp.height = height;
+            }
+        }
+        if (needLayout) {
+            requestLayout();
+        }
+    }
+
+    public void setMaxChallengeTop(int top) {
+        boolean dirty = mMaxChallengeTop != top;
+        mMaxChallengeTop = top;
+        mSmallWidgetHeight = top - getPaddingTop();
+        mSmallFrameHeight = top + getPaddingBottom();
+        if (dirty && mIsSmall) {
+            setWidgetHeight(mSmallWidgetHeight);
+            setFrameHeight(mSmallFrameHeight);
+        } else if (dirty && mWidgetLockedSmall) {
+            setWidgetHeight(mSmallWidgetHeight);
+        }
+    }
+
+    public boolean isSmall() {
+        return mIsSmall;
+    }
+
+    public void adjustFrame(int challengeTop) {
+        int frameHeight = challengeTop + getPaddingBottom();
+        setFrameHeight(frameHeight);
+    }
+
+    public void shrinkWidget(boolean alsoShrinkFrame) {
+        mIsSmall = true;
+        setWidgetHeight(mSmallWidgetHeight);
+
+        if (alsoShrinkFrame) {
+            setFrameHeight(mSmallFrameHeight);
+        }
+    }
+
+    public int getSmallFrameHeight() {
+        return mSmallFrameHeight;
+    }
+
+    public void shrinkWidget() {
+        shrinkWidget(true);
+    }
+
+    public void setWidgetLockedSmall(boolean locked) {
+        if (locked) {
+            setWidgetHeight(mSmallWidgetHeight);
+        }
+        mWidgetLockedSmall = locked;
+    }
+
+    public void resetSize() {
+        mIsSmall = false;
+        if (!mWidgetLockedSmall) {
+            setWidgetHeight(LayoutParams.MATCH_PARENT);
+        }
+        setFrameHeight(getMeasuredHeight());
+    }
+
+    public void setFrameHeight(int height) {
+        mFrameHeight = height;
+        mBackgroundRect.set(0, 0, getMeasuredWidth(), Math.min(mFrameHeight, getMeasuredHeight()));
+        mForegroundRect.set(mFrameStrokeAdjustment, mFrameStrokeAdjustment,getMeasuredWidth() -
+                mFrameStrokeAdjustment, Math.min(getMeasuredHeight(), mFrameHeight) -
+                mFrameStrokeAdjustment);
+        updateGradient();
+        invalidate();
+    }
+
+    public void hideFrame(Object caller) {
+        fadeFrame(caller, false, 0f, KeyguardWidgetPager.CHILDREN_OUTLINE_FADE_OUT_DURATION);
+    }
+
+    public void showFrame(Object caller) {
+        fadeFrame(caller, true, OUTLINE_ALPHA_MULTIPLIER,
+                KeyguardWidgetPager.CHILDREN_OUTLINE_FADE_IN_DURATION);
+    }
+
+    public void fadeFrame(Object caller, boolean takeControl, float alpha, int duration) {
+        if (takeControl) {
+            mBgAlphaController = caller;
+        }
+
+        if (mBgAlphaController != caller) return;
+
+        if (mFrameFade != null) {
+            mFrameFade.cancel();
+            mFrameFade = null;
+        }
+        PropertyValuesHolder bgAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", alpha);
+        mFrameFade = ObjectAnimator.ofPropertyValuesHolder(this, bgAlpha);
+        mFrameFade.setDuration(duration);
+        mFrameFade.start();
+    }
+
+    private void updateGradient() {
+        float x0 = mLeftToRight ? 0 : mForegroundRect.width();
+        float x1 = mLeftToRight ? mForegroundRect.width(): 0;
+        mLeftToRightGradient = new LinearGradient(x0, 0f, x1, 0f,
+                mGradientColor, 0, Shader.TileMode.CLAMP);
+        mRightToLeftGradient = new LinearGradient(x1, 0f, x0, 0f,
+                mGradientColor, 0, Shader.TileMode.CLAMP);
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+
+        if (!mIsSmall) {
+            mFrameHeight = h;
+        }
+
+        // mFrameStrokeAdjustment is a cludge to prevent the overlay from drawing outside the
+        // rounded rect background.
+        mForegroundRect.set(mFrameStrokeAdjustment, mFrameStrokeAdjustment,
+                w - mFrameStrokeAdjustment, Math.min(h, mFrameHeight) - mFrameStrokeAdjustment);
+
+        mBackgroundRect.set(0, 0, getMeasuredWidth(), Math.min(h, mFrameHeight));
+        updateGradient();
+        invalidate();
+    }
+
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        performAppWidgetSizeCallbacksIfNecessary();
+    }
+
+    private void performAppWidgetSizeCallbacksIfNecessary() {
+        View content = getContent();
+        if (!(content instanceof AppWidgetHostView)) return;
+
+        if (!KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
+            mPerformAppWidgetSizeUpdateOnBootComplete = true;
+            return;
+        }
+
+        // TODO: there's no reason to force the AppWidgetHostView to catch duplicate size calls.
+        // We can do that even more cheaply here. It's not an issue right now since we're in the
+        // system process and hence no binder calls.
+        AppWidgetHostView awhv = (AppWidgetHostView) content;
+        float density = getResources().getDisplayMetrics().density;
+
+        int width = (int) (content.getMeasuredWidth() / density);
+        int height = (int) (content.getMeasuredHeight() / density);
+        awhv.updateAppWidgetSize(null, width, height, width, height, true);
+    }
+
+    void setOverScrollAmount(float r, boolean left) {
+        if (Float.compare(mOverScrollAmount, r) != 0) {
+            mOverScrollAmount = r;
+            mForegroundGradient = left ? mLeftToRightGradient : mRightToLeftGradient;
+            mForegroundAlpha = (int) Math.round((0.5f * r * 255));
+
+            // We bump up the alpha of the outline to hide the fact that the overlay is drawing
+            // over the rounded part of the frame.
+            float bgAlpha = Math.min(OUTLINE_ALPHA_MULTIPLIER + r * (1 - OUTLINE_ALPHA_MULTIPLIER),
+                    1f);
+            setBackgroundAlpha(bgAlpha);
+            invalidate();
+        }
+    }
+
+    public void onActive(boolean isActive) {
+        // hook for subclasses
+    }
+
+    public boolean onUserInteraction(MotionEvent event) {
+        // hook for subclasses
+        return false;
+    }
+
+    public void setWorkerHandler(Handler workerHandler) {
+        mWorkerHandler = workerHandler;
+    }
+
+    public Handler getWorkerHandler() {
+        return mWorkerHandler;
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
new file mode 100644
index 0000000..25e2781
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
@@ -0,0 +1,819 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.TimeInterpolator;
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.Context;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.util.AttributeSet;
+import android.util.Slog;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnLongClickListener;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.FrameLayout;
+
+import com.android.internal.widget.LockPatternUtils;
+
+import java.util.ArrayList;
+
+public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwitchListener,
+        OnLongClickListener, ChallengeLayout.OnBouncerStateChangedListener {
+
+    ZInterpolator mZInterpolator = new ZInterpolator(0.5f);
+    private static float CAMERA_DISTANCE = 10000;
+    protected static float OVERSCROLL_MAX_ROTATION = 30;
+    private static final boolean PERFORM_OVERSCROLL_ROTATION = true;
+
+    protected KeyguardViewStateManager mViewStateManager;
+    private LockPatternUtils mLockPatternUtils;
+
+    // Related to the fading in / out background outlines
+    public static final int CHILDREN_OUTLINE_FADE_OUT_DURATION = 375;
+    public static final int CHILDREN_OUTLINE_FADE_IN_DURATION = 100;
+    protected AnimatorSet mChildrenOutlineFadeAnimation;
+    protected int mScreenCenter;
+    private boolean mHasMeasure = false;
+    boolean showHintsAfterLayout = false;
+
+    private static final long CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT = 30000;
+    private static final String TAG = "KeyguardWidgetPager";
+    private boolean mCenterSmallWidgetsVertically;
+
+    private int mPage = 0;
+    private Callbacks mCallbacks;
+
+    private int mWidgetToResetAfterFadeOut;
+
+    // Bouncer
+    private int mBouncerZoomInOutDuration = 250;
+    private float BOUNCER_SCALE_FACTOR = 0.67f;
+
+    // Background worker thread: used here for persistence, also made available to widget frames
+    private final HandlerThread mBackgroundWorkerThread;
+    private final Handler mBackgroundWorkerHandler;
+
+    public KeyguardWidgetPager(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public KeyguardWidgetPager(Context context) {
+        this(null, null, 0);
+    }
+
+    public KeyguardWidgetPager(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
+            setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+        }
+
+        setPageSwitchListener(this);
+
+        mBackgroundWorkerThread = new HandlerThread("KeyguardWidgetPager Worker");
+        mBackgroundWorkerThread.start();
+        mBackgroundWorkerHandler = new Handler(mBackgroundWorkerThread.getLooper());
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+
+        // Clean up the worker thread
+        mBackgroundWorkerThread.quit();
+    }
+
+    public void setViewStateManager(KeyguardViewStateManager viewStateManager) {
+        mViewStateManager = viewStateManager;
+    }
+
+    public void setLockPatternUtils(LockPatternUtils l) {
+        mLockPatternUtils = l;
+    }
+
+    @Override
+    public void onPageSwitching(View newPage, int newPageIndex) {
+        if (mViewStateManager != null) {
+            mViewStateManager.onPageSwitching(newPage, newPageIndex);
+        }
+    }
+
+    @Override
+    public void onPageSwitched(View newPage, int newPageIndex) {
+        boolean showingStatusWidget = false;
+        if (newPage instanceof ViewGroup) {
+            ViewGroup vg = (ViewGroup) newPage;
+            if (vg.getChildAt(0) instanceof KeyguardStatusView) {
+                showingStatusWidget = true;
+            }
+        }
+
+        // Disable the status bar clock if we're showing the default status widget
+        if (showingStatusWidget) {
+            setSystemUiVisibility(getSystemUiVisibility() | View.STATUS_BAR_DISABLE_CLOCK);
+        } else {
+            setSystemUiVisibility(getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_CLOCK);
+        }
+
+        // Extend the display timeout if the user switches pages
+        if (mPage != newPageIndex) {
+            int oldPageIndex = mPage;
+            mPage = newPageIndex;
+            userActivity();
+            KeyguardWidgetFrame oldWidgetPage = getWidgetPageAt(oldPageIndex);
+            if (oldWidgetPage != null) {
+                oldWidgetPage.onActive(false);
+            }
+            KeyguardWidgetFrame newWidgetPage = getWidgetPageAt(newPageIndex);
+            if (newWidgetPage != null) {
+                newWidgetPage.onActive(true);
+                newWidgetPage.requestAccessibilityFocus();
+            }
+            if (mParent != null && AccessibilityManager.getInstance(mContext).isEnabled()) {
+                AccessibilityEvent event = AccessibilityEvent.obtain(
+                        AccessibilityEvent.TYPE_VIEW_SCROLLED);
+                onInitializeAccessibilityEvent(event);
+                onPopulateAccessibilityEvent(event);
+                mParent.requestSendAccessibilityEvent(this, event);
+            }
+        }
+        if (mViewStateManager != null) {
+            mViewStateManager.onPageSwitched(newPage, newPageIndex);
+        }
+    }
+
+    @Override
+    public void sendAccessibilityEvent(int eventType) {
+        if (eventType != AccessibilityEvent.TYPE_VIEW_SCROLLED || isPageMoving()) {
+            super.sendAccessibilityEvent(eventType);
+        }
+    }
+
+    private void updateWidgetFramesImportantForAccessibility() {
+        final int pageCount = getPageCount();
+        for (int i = 0; i < pageCount; i++) {
+            KeyguardWidgetFrame frame = getWidgetPageAt(i);
+            updateWidgetFrameImportantForAccessibility(frame);
+        }
+    }
+
+    private void updateWidgetFrameImportantForAccessibility(KeyguardWidgetFrame frame) {
+        if (frame.getContentAlpha() <= 0) {
+            frame.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+        } else {
+            frame.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+        }
+    }
+
+    private void userActivity() {
+        if (mCallbacks != null) {
+            mCallbacks.onUserActivityTimeoutChanged();
+            mCallbacks.userActivity();
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        return captureUserInteraction(ev) || super.onTouchEvent(ev);
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        return captureUserInteraction(ev) || super.onInterceptTouchEvent(ev);
+    }
+
+    private boolean captureUserInteraction(MotionEvent ev) {
+        KeyguardWidgetFrame currentWidgetPage = getWidgetPageAt(getCurrentPage());
+        return currentWidgetPage != null && currentWidgetPage.onUserInteraction(ev);
+    }
+
+    public void showPagingFeedback() {
+        // Nothing yet.
+    }
+
+    public long getUserActivityTimeout() {
+        View page = getPageAt(mPage);
+        if (page instanceof ViewGroup) {
+            ViewGroup vg = (ViewGroup) page;
+            View view = vg.getChildAt(0);
+            if (!(view instanceof KeyguardStatusView)
+                    && !(view instanceof KeyguardMultiUserSelectorView)) {
+                return CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT;
+            }
+        }
+        return -1;
+    }
+
+    public void setCallbacks(Callbacks callbacks) {
+        mCallbacks = callbacks;
+    }
+
+    public interface Callbacks {
+        public void userActivity();
+        public void onUserActivityTimeoutChanged();
+        public void onAddView(View v);
+        public void onRemoveView(View v);
+    }
+
+    public void addWidget(View widget) {
+        addWidget(widget, -1);
+    }
+
+
+    public void onRemoveView(View v) {
+        final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId();
+        if (mCallbacks != null) {
+            mCallbacks.onRemoveView(v);
+        }
+        mBackgroundWorkerHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mLockPatternUtils.removeAppWidget(appWidgetId);
+            }
+        });
+    }
+
+    public void onAddView(View v, final int index) {
+        final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId();
+        final int[] pagesRange = new int[mTempVisiblePagesRange.length];
+        getVisiblePages(pagesRange);
+        boundByReorderablePages(true, pagesRange);
+        if (mCallbacks != null) {
+            mCallbacks.onAddView(v);
+        }
+        // Subtract from the index to take into account pages before the reorderable
+        // pages (e.g. the "add widget" page)
+        mBackgroundWorkerHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mLockPatternUtils.addAppWidget(appWidgetId, index - pagesRange[0]);
+            }
+        });
+    }
+
+    /*
+     * We wrap widgets in a special frame which handles drawing the over scroll foreground.
+     */
+    public void addWidget(View widget, int pageIndex) {
+        KeyguardWidgetFrame frame;
+        // All views contained herein should be wrapped in a KeyguardWidgetFrame
+        if (!(widget instanceof KeyguardWidgetFrame)) {
+            frame = new KeyguardWidgetFrame(getContext());
+            FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+                    LayoutParams.MATCH_PARENT);
+            lp.gravity = Gravity.TOP;
+
+            // The framework adds a default padding to AppWidgetHostView. We don't need this padding
+            // for the Keyguard, so we override it to be 0.
+            widget.setPadding(0,  0, 0, 0);
+            frame.addView(widget, lp);
+
+            // We set whether or not this widget supports vertical resizing.
+            if (widget instanceof AppWidgetHostView) {
+                AppWidgetHostView awhv = (AppWidgetHostView) widget;
+                AppWidgetProviderInfo info = awhv.getAppWidgetInfo();
+                if ((info.resizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0) {
+                    frame.setWidgetLockedSmall(false);
+                } else {
+                    // Lock the widget to be small.
+                    frame.setWidgetLockedSmall(true);
+                    if (mCenterSmallWidgetsVertically) {
+                        lp.gravity = Gravity.CENTER;
+                    }
+                }
+            }
+        } else {
+            frame = (KeyguardWidgetFrame) widget;
+        }
+
+        ViewGroup.LayoutParams pageLp = new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+        frame.setOnLongClickListener(this);
+        frame.setWorkerHandler(mBackgroundWorkerHandler);
+
+        if (pageIndex == -1) {
+            addView(frame, pageLp);
+        } else {
+            addView(frame, pageIndex, pageLp);
+        }
+
+        // Update the frame content description.
+        View content = (widget == frame) ?  frame.getContent() : widget;
+        if (content != null) {
+            String contentDescription = mContext.getString(
+                com.android.internal.R.string.keyguard_accessibility_widget,
+                content.getContentDescription());
+            frame.setContentDescription(contentDescription);
+        }
+        updateWidgetFrameImportantForAccessibility(frame);
+    }
+
+    /**
+     * Use addWidget() instead.
+     * @deprecated
+     */
+    @Override
+    public void addView(View child, int index) {
+        enforceKeyguardWidgetFrame(child);
+        super.addView(child, index);
+    }
+
+    /**
+     * Use addWidget() instead.
+     * @deprecated
+     */
+    @Override
+    public void addView(View child, int width, int height) {
+        enforceKeyguardWidgetFrame(child);
+        super.addView(child, width, height);
+    }
+
+    /**
+     * Use addWidget() instead.
+     * @deprecated
+     */
+    @Override
+    public void addView(View child, LayoutParams params) {
+        enforceKeyguardWidgetFrame(child);
+        super.addView(child, params);
+    }
+
+    /**
+     * Use addWidget() instead.
+     * @deprecated
+     */
+    @Override
+    public void addView(View child, int index, LayoutParams params) {
+        enforceKeyguardWidgetFrame(child);
+        super.addView(child, index, params);
+    }
+
+    private void enforceKeyguardWidgetFrame(View child) {
+        if (!(child instanceof KeyguardWidgetFrame)) {
+            throw new IllegalArgumentException(
+                    "KeyguardWidgetPager children must be KeyguardWidgetFrames");
+        }
+    }
+
+    public KeyguardWidgetFrame getWidgetPageAt(int index) {
+        // This is always a valid cast as we've guarded the ability to
+        return (KeyguardWidgetFrame) getChildAt(index);
+    }
+
+    protected void onUnhandledTap(MotionEvent ev) {
+        showPagingFeedback();
+    }
+
+    @Override
+    protected void onPageBeginMoving() {
+        if (mViewStateManager != null) {
+            mViewStateManager.onPageBeginMoving();
+        }
+        if (!isReordering(false)) {
+            showOutlinesAndSidePages();
+        }
+        userActivity();
+    }
+
+    @Override
+    protected void onPageEndMoving() {
+        if (mViewStateManager != null) {
+            mViewStateManager.onPageEndMoving();
+        }
+
+        // In the reordering case, the pages will be faded appropriately on completion
+        // of the zoom in animation.
+        if (!isReordering(false)) {
+            hideOutlinesAndSidePages();
+        }
+    }
+
+    protected void enablePageContentLayers() {
+        int children = getChildCount();
+        for (int i = 0; i < children; i++) {
+            getWidgetPageAt(i).enableHardwareLayersForContent();
+        }
+    }
+
+    protected void disablePageContentLayers() {
+        int children = getChildCount();
+        for (int i = 0; i < children; i++) {
+            getWidgetPageAt(i).disableHardwareLayersForContent();
+        }
+    }
+
+    /*
+     * This interpolator emulates the rate at which the perceived scale of an object changes
+     * as its distance from a camera increases. When this interpolator is applied to a scale
+     * animation on a view, it evokes the sense that the object is shrinking due to moving away
+     * from the camera.
+     */
+    static class ZInterpolator implements TimeInterpolator {
+        private float focalLength;
+
+        public ZInterpolator(float foc) {
+            focalLength = foc;
+        }
+
+        public float getInterpolation(float input) {
+            return (1.0f - focalLength / (focalLength + input)) /
+                (1.0f - focalLength / (focalLength + 1.0f));
+        }
+    }
+
+    @Override
+    protected void overScroll(float amount) {
+        acceleratedOverScroll(amount);
+    }
+
+    float backgroundAlphaInterpolator(float r) {
+        return Math.min(1f, r);
+    }
+
+    private void updatePageAlphaValues(int screenCenter) {
+    }
+
+    public float getAlphaForPage(int screenCenter, int index) {
+        return 1f;
+    }
+
+    public float getOutlineAlphaForPage(int screenCenter, int index) {
+        return getAlphaForPage(screenCenter, index) * KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER;
+    }
+
+    protected boolean isOverScrollChild(int index, float scrollProgress) {
+        boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
+        return (isInOverscroll && (index == 0 && scrollProgress < 0 ||
+                index == getChildCount() - 1 && scrollProgress > 0));
+    }
+
+    @Override
+    protected void screenScrolled(int screenCenter) {
+        mScreenCenter = screenCenter;
+        updatePageAlphaValues(screenCenter);
+        for (int i = 0; i < getChildCount(); i++) {
+            KeyguardWidgetFrame v = getWidgetPageAt(i);
+            if (v == mDragView) continue;
+            if (v != null) {
+                float scrollProgress = getScrollProgress(screenCenter, v, i);
+
+                v.setCameraDistance(mDensity * CAMERA_DISTANCE);
+
+                if (isOverScrollChild(i, scrollProgress) && PERFORM_OVERSCROLL_ROTATION) {
+                    float pivotX = v.getMeasuredWidth() / 2;
+                    float pivotY = v.getMeasuredHeight() / 2;
+                    v.setPivotX(pivotX);
+                    v.setPivotY(pivotY);
+                    v.setRotationY(- OVERSCROLL_MAX_ROTATION * scrollProgress);
+                    v.setOverScrollAmount(Math.abs(scrollProgress), scrollProgress < 0);
+                } else {
+                    v.setRotationY(0f);
+                    v.setOverScrollAmount(0, false);
+                }
+
+                float alpha = v.getAlpha();
+                // If the view has 0 alpha, we set it to be invisible so as to prevent
+                // it from accepting touches
+                if (alpha == 0) {
+                    v.setVisibility(INVISIBLE);
+                } else if (v.getVisibility() != VISIBLE) {
+                    v.setVisibility(VISIBLE);
+                }
+            }
+        }
+    }
+
+    public boolean isWidgetPage(int pageIndex) {
+        if (pageIndex < 0 || pageIndex >= getChildCount()) {
+            return false;
+        }
+        View v = getChildAt(pageIndex);
+        if (v != null && v instanceof KeyguardWidgetFrame) {
+            KeyguardWidgetFrame kwf = (KeyguardWidgetFrame) v;
+            return kwf.getContentAppWidgetId() != AppWidgetManager.INVALID_APPWIDGET_ID;
+        }
+        return false;
+    }
+
+    /**
+     * Returns the bounded set of pages that are re-orderable.  The range is fully inclusive.
+     */
+    @Override
+    void boundByReorderablePages(boolean isReordering, int[] range) {
+        if (isReordering) {
+            // Remove non-widget pages from the range
+            while (range[1] >= range[0] && !isWidgetPage(range[1])) {
+                range[1]--;
+            }
+            while (range[0] <= range[1] && !isWidgetPage(range[0])) {
+                range[0]++;
+            }
+        }
+    }
+
+    protected void reorderStarting() {
+        showOutlinesAndSidePages();
+    }
+
+    @Override
+    protected void onStartReordering() {
+        super.onStartReordering();
+        enablePageContentLayers();
+        reorderStarting();
+    }
+
+    @Override
+    protected void onEndReordering() {
+        super.onEndReordering();
+        hideOutlinesAndSidePages();
+    }
+
+    void showOutlinesAndSidePages() {
+        animateOutlinesAndSidePages(true);
+    }
+
+    void hideOutlinesAndSidePages() {
+        animateOutlinesAndSidePages(false);
+    }
+
+    public void showInitialPageHints() {
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            KeyguardWidgetFrame child = getWidgetPageAt(i);
+            if (i != mCurrentPage) {
+                child.fadeFrame(this, true, KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER,
+                        CHILDREN_OUTLINE_FADE_IN_DURATION);
+                child.setContentAlpha(0f);
+            } else {
+                child.setBackgroundAlpha(0f);
+                child.setContentAlpha(1f);
+            }
+        }
+    }
+
+    public void showSidePageHints() {
+        animateOutlinesAndSidePages(true, -1);
+    }
+
+    @Override
+    void setCurrentPage(int currentPage) {
+        super.setCurrentPage(currentPage);
+        updateWidgetFramesImportantForAccessibility();
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mHasMeasure = false;
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+    }
+
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int maxChallengeTop = -1;
+        View parent = (View) getParent();
+        boolean challengeShowing = false;
+        // Widget pages need to know where the top of the sliding challenge is so that they
+        // now how big the widget should be when the challenge is up. We compute it here and
+        // then propagate it to each of our children.
+        if (parent.getParent() instanceof SlidingChallengeLayout) {
+            SlidingChallengeLayout scl = (SlidingChallengeLayout) parent.getParent();
+            int top = scl.getMaxChallengeTop();
+
+            // This is a bit evil, but we need to map a coordinate relative to the SCL into a
+            // coordinate relative to our children, hence we subtract the top padding.s
+            maxChallengeTop = top - getPaddingTop();
+            challengeShowing = scl.isChallengeShowing();
+
+            int count = getChildCount();
+            for (int i = 0; i < count; i++) {
+                KeyguardWidgetFrame frame = getWidgetPageAt(i);
+                frame.setMaxChallengeTop(maxChallengeTop);
+                // On the very first measure pass, if the challenge is showing, we need to make sure
+                // that the widget on the current page is small.
+                if (challengeShowing && i == mCurrentPage && !mHasMeasure) {
+                    frame.shrinkWidget();
+                }
+            }
+        }
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        mHasMeasure = true;
+    }
+
+    void animateOutlinesAndSidePages(final boolean show) {
+        animateOutlinesAndSidePages(show, -1);
+    }
+
+    public void setWidgetToResetOnPageFadeOut(int widget) {
+        mWidgetToResetAfterFadeOut = widget;
+    }
+
+    public int getWidgetToResetOnPageFadeOut() {
+        return mWidgetToResetAfterFadeOut;
+    }
+
+    void animateOutlinesAndSidePages(final boolean show, int duration) {
+        if (mChildrenOutlineFadeAnimation != null) {
+            mChildrenOutlineFadeAnimation.cancel();
+            mChildrenOutlineFadeAnimation = null;
+        }
+        int count = getChildCount();
+        PropertyValuesHolder alpha;
+        ArrayList<Animator> anims = new ArrayList<Animator>();
+
+        if (duration == -1) {
+            duration = show ? CHILDREN_OUTLINE_FADE_IN_DURATION :
+                CHILDREN_OUTLINE_FADE_OUT_DURATION;
+        }
+
+        int curPage = getNextPage();
+        for (int i = 0; i < count; i++) {
+            float finalContentAlpha;
+            if (show) {
+                finalContentAlpha = getAlphaForPage(mScreenCenter, i);
+            } else if (!show && i == curPage) {
+                finalContentAlpha = 1f;
+            } else {
+                finalContentAlpha = 0f;
+            }
+            KeyguardWidgetFrame child = getWidgetPageAt(i);
+
+            alpha = PropertyValuesHolder.ofFloat("contentAlpha", finalContentAlpha);
+            ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha);
+            anims.add(a);
+
+            float finalOutlineAlpha = show ? getOutlineAlphaForPage(mScreenCenter, i) : 0f;
+            child.fadeFrame(this, show, finalOutlineAlpha, duration);
+        }
+
+        mChildrenOutlineFadeAnimation = new AnimatorSet();
+        mChildrenOutlineFadeAnimation.playTogether(anims);
+
+        mChildrenOutlineFadeAnimation.setDuration(duration);
+        mChildrenOutlineFadeAnimation.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                if (show) {
+                    enablePageContentLayers();
+                }
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (!show) {
+                    disablePageContentLayers();
+                    KeyguardWidgetFrame frame = getWidgetPageAt(mWidgetToResetAfterFadeOut);
+                    if (frame != null && !(frame == getWidgetPageAt(mCurrentPage) &&
+                            mViewStateManager.isChallengeOverlapping())) {
+                        frame.resetSize();
+                    }
+                    mWidgetToResetAfterFadeOut = -1;
+                }
+                updateWidgetFramesImportantForAccessibility();
+            }
+        });
+        mChildrenOutlineFadeAnimation.start();
+    }
+
+    @Override
+    public boolean onLongClick(View v) {
+        // Disallow long pressing to reorder if the challenge is showing
+        boolean isChallengeOverlapping = mViewStateManager.isChallengeShowing() &&
+                mViewStateManager.isChallengeOverlapping();
+        if (!isChallengeOverlapping && startReordering()) {
+            return true;
+        }
+        return false;
+    }
+
+    public void removeWidget(View view) {
+        if (view instanceof KeyguardWidgetFrame) {
+            removeView(view);
+        } else {
+            // Assume view was wrapped by a KeyguardWidgetFrame in KeyguardWidgetPager#addWidget().
+            // This supports legacy hard-coded "widgets" like KeyguardTransportControlView.
+            int pos = getWidgetPageIndex(view);
+            if (pos != -1) {
+                KeyguardWidgetFrame frame = (KeyguardWidgetFrame) getChildAt(pos);
+                frame.removeView(view);
+                removeView(frame);
+            } else {
+                Slog.w(TAG, "removeWidget() can't find:" + view);
+            }
+        }
+    }
+
+    public int getWidgetPageIndex(View view) {
+        if (view instanceof KeyguardWidgetFrame) {
+            return indexOfChild(view);
+        } else {
+            // View was wrapped by a KeyguardWidgetFrame by KeyguardWidgetPager#addWidget()
+            return indexOfChild((KeyguardWidgetFrame)view.getParent());
+        }
+    }
+
+    @Override
+    protected void setPageHoveringOverDeleteDropTarget(int viewIndex, boolean isHovering) {
+        KeyguardWidgetFrame child = getWidgetPageAt(viewIndex);
+        child.setIsHoveringOverDeleteDropTarget(isHovering);
+    }
+
+    // ChallengeLayout.OnBouncerStateChangedListener
+    @Override
+    public void onBouncerStateChanged(boolean bouncerActive) {
+        if (bouncerActive) {
+            zoomOutToBouncer();
+        } else {
+            zoomInFromBouncer();
+        }
+    }
+
+    void setBouncerAnimationDuration(int duration) {
+        mBouncerZoomInOutDuration = duration;
+    }
+
+    // Zoom in after the bouncer is dismissed
+    void zoomInFromBouncer() {
+        if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) {
+            mZoomInOutAnim.cancel();
+        }
+        final View currentPage = getPageAt(getCurrentPage());
+        if (currentPage.getScaleX() < 1f || currentPage.getScaleY() < 1f) {
+            mZoomInOutAnim = new AnimatorSet();
+            mZoomInOutAnim.playTogether(
+                    ObjectAnimator.ofFloat(currentPage, "scaleX", 1f),
+                    ObjectAnimator.ofFloat(currentPage , "scaleY", 1f));
+            mZoomInOutAnim.setDuration(mBouncerZoomInOutDuration);
+            mZoomInOutAnim.setInterpolator(new DecelerateInterpolator(1.5f));
+            mZoomInOutAnim.start();
+        }
+    }
+
+    // Zoom out after the bouncer is initiated
+    void zoomOutToBouncer() {
+        if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) {
+            mZoomInOutAnim.cancel();
+        }
+        int curPage = getCurrentPage();
+        View currentPage = getPageAt(curPage);
+        if (shouldSetTopAlignedPivotForWidget(curPage)) {
+            currentPage.setPivotY(0);
+            // Note: we are working around the issue that setting the x-pivot to the same value as it
+            //       was does not actually work.
+            currentPage.setPivotX(0);
+            currentPage.setPivotX(currentPage.getMeasuredWidth() / 2);
+        }
+        if (!(currentPage.getScaleX() < 1f || currentPage.getScaleY() < 1f)) {
+            mZoomInOutAnim = new AnimatorSet();
+            mZoomInOutAnim.playTogether(
+                    ObjectAnimator.ofFloat(currentPage, "scaleX", BOUNCER_SCALE_FACTOR),
+                    ObjectAnimator.ofFloat(currentPage, "scaleY", BOUNCER_SCALE_FACTOR));
+            mZoomInOutAnim.setDuration(mBouncerZoomInOutDuration);
+            mZoomInOutAnim.setInterpolator(new DecelerateInterpolator(1.5f));
+            mZoomInOutAnim.start();
+        }
+    }
+
+    boolean isAddPage(int pageIndex) {
+        View v = getChildAt(pageIndex);
+        return v != null && v.getId() == com.android.internal.R.id.keyguard_add_widget;
+    }
+
+    boolean isCameraPage(int pageIndex) {
+        View v = getChildAt(pageIndex);
+        return v != null && v instanceof CameraWidgetFrame;
+    }
+
+    @Override
+    protected boolean shouldSetTopAlignedPivotForWidget(int childIndex) {
+        return !isCameraPage(childIndex) && super.shouldSetTopAlignedPivotForWidget(childIndex);
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/LiftToActivateListener.java b/policy/src/com/android/internal/policy/impl/keyguard/LiftToActivateListener.java
new file mode 100644
index 0000000..818108c
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/LiftToActivateListener.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2013 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.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.accessibility.AccessibilityManager;
+
+/**
+ * Hover listener that implements lift-to-activate interaction for
+ * accessibility. May be added to multiple views.
+ */
+class LiftToActivateListener implements View.OnHoverListener {
+    /** Manager used to query accessibility enabled state. */
+    private final AccessibilityManager mAccessibilityManager;
+
+    private boolean mCachedClickableState;
+
+    public LiftToActivateListener(Context context) {
+        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
+                Context.ACCESSIBILITY_SERVICE);
+    }
+
+    @Override
+    public boolean onHover(View v, MotionEvent event) {
+        // When touch exploration is turned on, lifting a finger while
+        // inside the view bounds should perform a click action.
+        if (mAccessibilityManager.isEnabled()
+                && mAccessibilityManager.isTouchExplorationEnabled()) {
+            switch (event.getActionMasked()) {
+                case MotionEvent.ACTION_HOVER_ENTER:
+                    // Lift-to-type temporarily disables double-tap
+                    // activation by setting the view as not clickable.
+                    mCachedClickableState = v.isClickable();
+                    v.setClickable(false);
+                    break;
+                case MotionEvent.ACTION_HOVER_EXIT:
+                    final int x = (int) event.getX();
+                    final int y = (int) event.getY();
+                    if ((x > v.getPaddingLeft()) && (y > v.getPaddingTop())
+                            && (x < v.getWidth() - v.getPaddingRight())
+                            && (y < v.getHeight() - v.getPaddingBottom())) {
+                        v.performClick();
+                    }
+                    v.setClickable(mCachedClickableState);
+                    break;
+            }
+        }
+
+        // Pass the event to View.onHoverEvent() to handle accessibility.
+        v.onHoverEvent(event);
+
+        // Consume the event so it doesn't fall through to other views.
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/MultiPaneChallengeLayout.java b/policy/src/com/android/internal/policy/impl/keyguard/MultiPaneChallengeLayout.java
new file mode 100644
index 0000000..0ca46c3
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/MultiPaneChallengeLayout.java
@@ -0,0 +1,566 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import com.android.internal.R;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayout {
+    private static final String TAG = "MultiPaneChallengeLayout";
+
+    final int mOrientation;
+    private boolean mIsBouncing;
+
+    public static final int HORIZONTAL = LinearLayout.HORIZONTAL;
+    public static final int VERTICAL = LinearLayout.VERTICAL;
+    public static final int ANIMATE_BOUNCE_DURATION = 350;
+
+    private KeyguardSecurityContainer mChallengeView;
+    private View mUserSwitcherView;
+    private View mScrimView;
+    private OnBouncerStateChangedListener mBouncerListener;
+
+    private final Rect mTempRect = new Rect();
+    private final Rect mZeroPadding = new Rect();
+
+    private final DisplayMetrics mDisplayMetrics;
+
+    private final OnClickListener mScrimClickListener = new OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            hideBouncer();
+        }
+    };
+
+    public MultiPaneChallengeLayout(Context context) {
+        this(context, null);
+    }
+
+    public MultiPaneChallengeLayout(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public MultiPaneChallengeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+        final TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.MultiPaneChallengeLayout, defStyleAttr, 0);
+        mOrientation = a.getInt(R.styleable.MultiPaneChallengeLayout_orientation,
+                HORIZONTAL);
+        a.recycle();
+
+        final Resources res = getResources();
+        mDisplayMetrics = res.getDisplayMetrics();
+
+        setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_STABLE);
+    }
+
+    @Override
+    public boolean isChallengeShowing() {
+        return true;
+    }
+
+    @Override
+    public boolean isChallengeOverlapping() {
+        return false;
+    }
+
+    @Override
+    public void showChallenge(boolean b) {
+    }
+
+    @Override
+    public int getBouncerAnimationDuration() {
+        return ANIMATE_BOUNCE_DURATION;
+    }
+
+    @Override
+    public void showBouncer() {
+        if (mIsBouncing) return;
+        mIsBouncing = true;
+        if (mScrimView != null) {
+            if (mChallengeView != null) {
+                mChallengeView.showBouncer(ANIMATE_BOUNCE_DURATION);
+            }
+
+            Animator anim = ObjectAnimator.ofFloat(mScrimView, "alpha", 1f);
+            anim.setDuration(ANIMATE_BOUNCE_DURATION);
+            anim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationStart(Animator animation) {
+                    mScrimView.setVisibility(VISIBLE);
+                }
+            });
+            anim.start();
+        }
+        if (mBouncerListener != null) {
+            mBouncerListener.onBouncerStateChanged(true);
+        }
+    }
+
+    @Override
+    public void hideBouncer() {
+        if (!mIsBouncing) return;
+        mIsBouncing = false;
+        if (mScrimView != null) {
+            if (mChallengeView != null) {
+                mChallengeView.hideBouncer(ANIMATE_BOUNCE_DURATION);
+            }
+
+            Animator anim = ObjectAnimator.ofFloat(mScrimView, "alpha", 0f);
+            anim.setDuration(ANIMATE_BOUNCE_DURATION);
+            anim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    mScrimView.setVisibility(INVISIBLE);
+                }
+            });
+            anim.start();
+        }
+        if (mBouncerListener != null) {
+            mBouncerListener.onBouncerStateChanged(false);
+        }
+    }
+
+    @Override
+    public boolean isBouncing() {
+        return mIsBouncing;
+    }
+
+    @Override
+    public void setOnBouncerStateChangedListener(OnBouncerStateChangedListener listener) {
+        mBouncerListener = listener;
+    }
+
+    @Override
+    public void requestChildFocus(View child, View focused) {
+        if (mIsBouncing && child != mChallengeView) {
+            // Clear out of the bouncer if the user tries to move focus outside of
+            // the security challenge view.
+            hideBouncer();
+        }
+        super.requestChildFocus(child, focused);
+    }
+
+    void setScrimView(View scrim) {
+        if (mScrimView != null) {
+            mScrimView.setOnClickListener(null);
+        }
+        mScrimView = scrim;
+        mScrimView.setAlpha(mIsBouncing ? 1.0f : 0.0f);
+        mScrimView.setVisibility(mIsBouncing ? VISIBLE : INVISIBLE);
+        mScrimView.setFocusable(true);
+        mScrimView.setOnClickListener(mScrimClickListener);
+    }
+
+    private int getVirtualHeight(LayoutParams lp, int height, int heightUsed) {
+        int virtualHeight = height;
+        final View root = getRootView();
+        if (root != null) {
+            // This calculation is super dodgy and relies on several assumptions.
+            // Specifically that the root of the window will be padded in for insets
+            // and that the window is LAYOUT_IN_SCREEN.
+            virtualHeight = mDisplayMetrics.heightPixels - root.getPaddingTop();
+        }
+        if (lp.childType == LayoutParams.CHILD_TYPE_WIDGET ||
+                lp.childType == LayoutParams.CHILD_TYPE_USER_SWITCHER) {
+            // Always measure the widget pager/user switcher as if there were no IME insets
+            // on the window. We want to avoid resizing widgets when possible as it can
+            // be ugly/expensive. This lets us simply clip them instead.
+            return virtualHeight - heightUsed;
+        } else if (lp.childType == LayoutParams.CHILD_TYPE_PAGE_DELETE_DROP_TARGET) {
+            return height;
+        }
+        return Math.min(virtualHeight - heightUsed, height);
+    }
+
+    @Override
+    protected void onMeasure(final int widthSpec, final int heightSpec) {
+        if (MeasureSpec.getMode(widthSpec) != MeasureSpec.EXACTLY ||
+                MeasureSpec.getMode(heightSpec) != MeasureSpec.EXACTLY) {
+            throw new IllegalArgumentException(
+                    "MultiPaneChallengeLayout must be measured with an exact size");
+        }
+
+        final int width = MeasureSpec.getSize(widthSpec);
+        final int height = MeasureSpec.getSize(heightSpec);
+        setMeasuredDimension(width, height);
+
+        int widthUsed = 0;
+        int heightUsed = 0;
+
+        // First pass. Find the challenge view and measure the user switcher,
+        // which consumes space in the layout.
+        mChallengeView = null;
+        mUserSwitcherView = null;
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+            if (lp.childType == LayoutParams.CHILD_TYPE_CHALLENGE) {
+                if (mChallengeView != null) {
+                    throw new IllegalStateException(
+                            "There may only be one child of type challenge");
+                }
+                if (!(child instanceof KeyguardSecurityContainer)) {
+                    throw new IllegalArgumentException(
+                            "Challenge must be a KeyguardSecurityContainer");
+                }
+                mChallengeView = (KeyguardSecurityContainer) child;
+            } else if (lp.childType == LayoutParams.CHILD_TYPE_USER_SWITCHER) {
+                if (mUserSwitcherView != null) {
+                    throw new IllegalStateException(
+                            "There may only be one child of type userSwitcher");
+                }
+                mUserSwitcherView = child;
+
+                if (child.getVisibility() == GONE) continue;
+
+                int adjustedWidthSpec = widthSpec;
+                int adjustedHeightSpec = heightSpec;
+                if (lp.maxWidth >= 0) {
+                    adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
+                            Math.min(lp.maxWidth, width), MeasureSpec.EXACTLY);
+                }
+                if (lp.maxHeight >= 0) {
+                    adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
+                            Math.min(lp.maxHeight, height), MeasureSpec.EXACTLY);
+                }
+                // measureChildWithMargins will resolve layout direction for the LayoutParams
+                measureChildWithMargins(child, adjustedWidthSpec, 0, adjustedHeightSpec, 0);
+
+                // Only subtract out space from one dimension. Favor vertical.
+                // Offset by 1.5x to add some balance along the other edge.
+                if (Gravity.isVertical(lp.gravity)) {
+                    heightUsed += child.getMeasuredHeight() * 1.5f;
+                } else if (Gravity.isHorizontal(lp.gravity)) {
+                    widthUsed += child.getMeasuredWidth() * 1.5f;
+                }
+            } else if (lp.childType == LayoutParams.CHILD_TYPE_SCRIM) {
+                setScrimView(child);
+                child.measure(widthSpec, heightSpec);
+            }
+        }
+
+        // Second pass. Measure everything that's left.
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+            if (lp.childType == LayoutParams.CHILD_TYPE_USER_SWITCHER ||
+                    lp.childType == LayoutParams.CHILD_TYPE_SCRIM ||
+                    child.getVisibility() == GONE) {
+                // Don't need to measure GONE children, and the user switcher was already measured.
+                continue;
+            }
+
+            final int virtualHeight = getVirtualHeight(lp, height, heightUsed);
+
+            int adjustedWidthSpec;
+            int adjustedHeightSpec;
+            if (lp.centerWithinArea > 0) {
+                if (mOrientation == HORIZONTAL) {
+                    adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
+                            (int) ((width - widthUsed) * lp.centerWithinArea + 0.5f),
+                            MeasureSpec.EXACTLY);
+                    adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
+                            virtualHeight, MeasureSpec.EXACTLY);
+                } else {
+                    adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
+                            width - widthUsed, MeasureSpec.EXACTLY);
+                    adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
+                            (int) (virtualHeight * lp.centerWithinArea + 0.5f),
+                            MeasureSpec.EXACTLY);
+                }
+            } else {
+                adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
+                        width - widthUsed, MeasureSpec.EXACTLY);
+                adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
+                        virtualHeight, MeasureSpec.EXACTLY);
+            }
+            if (lp.maxWidth >= 0) {
+                adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
+                        Math.min(lp.maxWidth, MeasureSpec.getSize(adjustedWidthSpec)),
+                        MeasureSpec.EXACTLY);
+            }
+            if (lp.maxHeight >= 0) {
+                adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
+                        Math.min(lp.maxHeight, MeasureSpec.getSize(adjustedHeightSpec)),
+                        MeasureSpec.EXACTLY);
+            }
+
+            measureChildWithMargins(child, adjustedWidthSpec, 0, adjustedHeightSpec, 0);
+        }
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        final Rect padding = mTempRect;
+        padding.left = getPaddingLeft();
+        padding.top = getPaddingTop();
+        padding.right = getPaddingRight();
+        padding.bottom = getPaddingBottom();
+        final int width = r - l;
+        final int height = b - t;
+
+        // Reserve extra space in layout for the user switcher by modifying
+        // local padding during this layout pass
+        if (mUserSwitcherView != null && mUserSwitcherView.getVisibility() != GONE) {
+            layoutWithGravity(width, height, mUserSwitcherView, padding, true);
+        }
+
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+            // We did the user switcher above if we have one.
+            if (child == mUserSwitcherView || child.getVisibility() == GONE) continue;
+
+            if (child == mScrimView) {
+                child.layout(0, 0, width, height);
+                continue;
+            } else if (lp.childType == LayoutParams.CHILD_TYPE_PAGE_DELETE_DROP_TARGET) {
+                layoutWithGravity(width, height, child, mZeroPadding, false);
+                continue;
+            }
+
+            layoutWithGravity(width, height, child, padding, false);
+        }
+    }
+
+    private void layoutWithGravity(int width, int height, View child, Rect padding,
+            boolean adjustPadding) {
+        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+        final int heightUsed = padding.top + padding.bottom - getPaddingTop() - getPaddingBottom();
+        height = getVirtualHeight(lp, height, heightUsed);
+
+        final int gravity = Gravity.getAbsoluteGravity(lp.gravity, getLayoutDirection());
+
+        final boolean fixedLayoutSize = lp.centerWithinArea > 0;
+        final boolean fixedLayoutHorizontal = fixedLayoutSize && mOrientation == HORIZONTAL;
+        final boolean fixedLayoutVertical = fixedLayoutSize && mOrientation == VERTICAL;
+
+        final int adjustedWidth;
+        final int adjustedHeight;
+        if (fixedLayoutHorizontal) {
+            final int paddedWidth = width - padding.left - padding.right;
+            adjustedWidth = (int) (paddedWidth * lp.centerWithinArea + 0.5f);
+            adjustedHeight = height;
+        } else if (fixedLayoutVertical) {
+            final int paddedHeight = height - getPaddingTop() - getPaddingBottom();
+            adjustedWidth = width;
+            adjustedHeight = (int) (paddedHeight * lp.centerWithinArea + 0.5f);
+        } else {
+            adjustedWidth = width;
+            adjustedHeight = height;
+        }
+
+        final boolean isVertical = Gravity.isVertical(gravity);
+        final boolean isHorizontal = Gravity.isHorizontal(gravity);
+        final int childWidth = child.getMeasuredWidth();
+        final int childHeight = child.getMeasuredHeight();
+
+        int left = padding.left;
+        int top = padding.top;
+        int right = left + childWidth;
+        int bottom = top + childHeight;
+        switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
+            case Gravity.TOP:
+                top = fixedLayoutVertical ?
+                        padding.top + (adjustedHeight - childHeight) / 2 : padding.top;
+                bottom = top + childHeight;
+                if (adjustPadding && isVertical) {
+                    padding.top = bottom;
+                    padding.bottom += childHeight / 2;
+                }
+                break;
+            case Gravity.BOTTOM:
+                bottom = fixedLayoutVertical
+                        ? padding.top + height - (adjustedHeight - childHeight) / 2
+                        : padding.top + height;
+                top = bottom - childHeight;
+                if (adjustPadding && isVertical) {
+                    padding.bottom = height - top;
+                    padding.top += childHeight / 2;
+                }
+                break;
+            case Gravity.CENTER_VERTICAL:
+                top = padding.top + (height - childHeight) / 2;
+                bottom = top + childHeight;
+                break;
+        }
+        switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+            case Gravity.LEFT:
+                left = fixedLayoutHorizontal ?
+                        padding.left + (adjustedWidth - childWidth) / 2 : padding.left;
+                right = left + childWidth;
+                if (adjustPadding && isHorizontal && !isVertical) {
+                    padding.left = right;
+                    padding.right += childWidth / 2;
+                }
+                break;
+            case Gravity.RIGHT:
+                right = fixedLayoutHorizontal
+                        ? width - padding.right - (adjustedWidth - childWidth) / 2
+                        : width - padding.right;
+                left = right - childWidth;
+                if (adjustPadding && isHorizontal && !isVertical) {
+                    padding.right = width - left;
+                    padding.left += childWidth / 2;
+                }
+                break;
+            case Gravity.CENTER_HORIZONTAL:
+                final int paddedWidth = width - padding.left - padding.right;
+                left = (paddedWidth - childWidth) / 2;
+                right = left + childWidth;
+                break;
+        }
+        child.layout(left, top, right, bottom);
+    }
+
+    @Override
+    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
+        return new LayoutParams(getContext(), attrs, this);
+    }
+
+    @Override
+    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+        return p instanceof LayoutParams ? new LayoutParams((LayoutParams) p) :
+                p instanceof MarginLayoutParams ? new LayoutParams((MarginLayoutParams) p) :
+                new LayoutParams(p);
+    }
+
+    @Override
+    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
+        return new LayoutParams();
+    }
+
+    @Override
+    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+        return p instanceof LayoutParams;
+    }
+
+    public static class LayoutParams extends MarginLayoutParams {
+
+        public float centerWithinArea = 0;
+
+        public int childType = 0;
+
+        public static final int CHILD_TYPE_NONE = 0;
+        public static final int CHILD_TYPE_WIDGET = 1;
+        public static final int CHILD_TYPE_CHALLENGE = 2;
+        public static final int CHILD_TYPE_USER_SWITCHER = 3;
+        public static final int CHILD_TYPE_SCRIM = 4;
+        public static final int CHILD_TYPE_PAGE_DELETE_DROP_TARGET = 7;
+
+        public int gravity = Gravity.NO_GRAVITY;
+
+        public int maxWidth = -1;
+        public int maxHeight = -1;
+
+        public LayoutParams() {
+            this(WRAP_CONTENT, WRAP_CONTENT);
+        }
+
+        LayoutParams(Context c, AttributeSet attrs, MultiPaneChallengeLayout parent) {
+            super(c, attrs);
+
+            final TypedArray a = c.obtainStyledAttributes(attrs,
+                    R.styleable.MultiPaneChallengeLayout_Layout);
+
+            centerWithinArea = a.getFloat(
+                    R.styleable.MultiPaneChallengeLayout_Layout_layout_centerWithinArea, 0);
+            childType = a.getInt(R.styleable.MultiPaneChallengeLayout_Layout_layout_childType,
+                    CHILD_TYPE_NONE);
+            gravity = a.getInt(R.styleable.MultiPaneChallengeLayout_Layout_layout_gravity,
+                    Gravity.NO_GRAVITY);
+            maxWidth = a.getDimensionPixelSize(
+                    R.styleable.MultiPaneChallengeLayout_Layout_layout_maxWidth, -1);
+            maxHeight = a.getDimensionPixelSize(
+                    R.styleable.MultiPaneChallengeLayout_Layout_layout_maxHeight, -1);
+
+            // Default gravity settings based on type and parent orientation
+            if (gravity == Gravity.NO_GRAVITY) {
+                if (parent.mOrientation == HORIZONTAL) {
+                    switch (childType) {
+                        case CHILD_TYPE_WIDGET:
+                            gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
+                            break;
+                        case CHILD_TYPE_CHALLENGE:
+                            gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL;
+                            break;
+                        case CHILD_TYPE_USER_SWITCHER:
+                            gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
+                            break;
+                    }
+                } else {
+                    switch (childType) {
+                        case CHILD_TYPE_WIDGET:
+                            gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
+                            break;
+                        case CHILD_TYPE_CHALLENGE:
+                            gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
+                            break;
+                        case CHILD_TYPE_USER_SWITCHER:
+                            gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
+                            break;
+                    }
+                }
+            }
+
+            a.recycle();
+        }
+
+        public LayoutParams(int width, int height) {
+            super(width, height);
+        }
+
+        public LayoutParams(ViewGroup.LayoutParams source) {
+            super(source);
+        }
+
+        public LayoutParams(MarginLayoutParams source) {
+            super(source);
+        }
+
+        public LayoutParams(LayoutParams source) {
+            this((MarginLayoutParams) source);
+
+            centerWithinArea = source.centerWithinArea;
+            childType = source.childType;
+            gravity = source.gravity;
+            maxWidth = source.maxWidth;
+            maxHeight = source.maxHeight;
+        }
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/NumPadKey.java b/policy/src/com/android/internal/policy/impl/keyguard/NumPadKey.java
new file mode 100644
index 0000000..a0038bc
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/NumPadKey.java
@@ -0,0 +1,128 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.text.SpannableStringBuilder;
+import android.text.style.TextAppearanceSpan;
+import android.util.AttributeSet;
+import android.view.HapticFeedbackConstants;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.android.internal.R;
+import com.android.internal.widget.LockPatternUtils;
+
+public class NumPadKey extends Button {
+    // list of "ABC", etc per digit, starting with '0'
+    static String sKlondike[];
+
+    int mDigit = -1;
+    int mTextViewResId;
+    TextView mTextView = null;
+    boolean mEnableHaptics;
+
+    private View.OnClickListener mListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View thisView) {
+            if (mTextView == null) {
+                if (mTextViewResId > 0) {
+                    final View v = NumPadKey.this.getRootView().findViewById(mTextViewResId);
+                    if (v != null && v instanceof TextView) {
+                        mTextView = (TextView) v;
+                    }
+                }
+            }
+            // check for time-based lockouts
+            if (mTextView != null && mTextView.isEnabled()) {
+                mTextView.append(String.valueOf(mDigit));
+            }
+            doHapticKeyClick();
+        }
+    };
+
+    public NumPadKey(Context context) {
+        this(context, null);
+    }
+
+    public NumPadKey(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public NumPadKey(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NumPadKey);
+        mDigit = a.getInt(R.styleable.NumPadKey_digit, mDigit);
+        setTextViewResId(a.getResourceId(R.styleable.NumPadKey_textView, 0));
+
+        setOnClickListener(mListener);
+        setOnHoverListener(new LiftToActivateListener(context));
+        setAccessibilityDelegate(new ObscureSpeechDelegate(context));
+
+        mEnableHaptics = new LockPatternUtils(context).isTactileFeedbackEnabled();
+
+        SpannableStringBuilder builder = new SpannableStringBuilder();
+        builder.append(String.valueOf(mDigit));
+        if (mDigit >= 0) {
+            if (sKlondike == null) {
+                sKlondike = context.getResources().getStringArray(
+                        R.array.lockscreen_num_pad_klondike);
+            }
+            if (sKlondike != null && sKlondike.length > mDigit) {
+                final String extra = sKlondike[mDigit];
+                final int extraLen = extra.length();
+                if (extraLen > 0) {
+                    builder.append(" ");
+                    builder.append(extra);
+                    builder.setSpan(
+                        new TextAppearanceSpan(context, R.style.TextAppearance_NumPadKey_Klondike),
+                        builder.length()-extraLen, builder.length(), 0);
+                }
+            }
+        }
+        setText(builder);
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+
+        // Reset the "announced headset" flag when detached.
+        ObscureSpeechDelegate.sAnnouncedHeadset = false;
+    }
+
+    public void setTextView(TextView tv) {
+        mTextView = tv;
+    }
+
+    public void setTextViewResId(int resId) {
+        mTextView = null;
+        mTextViewResId = resId;
+    }
+
+    // Cause a VIRTUAL_KEY vibration
+    public void doHapticKeyClick() {
+        if (mEnableHaptics) {
+            performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
+                    HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING
+                    | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
+        }
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/ObscureSpeechDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/ObscureSpeechDelegate.java
new file mode 100644
index 0000000..af043ab
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/ObscureSpeechDelegate.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2013 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.internal.policy.impl.keyguard;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.media.AudioManager;
+import android.provider.Settings;
+import android.view.View;
+import android.view.View.AccessibilityDelegate;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import com.android.internal.R;
+
+/**
+ * Accessibility delegate that obscures speech for a view when the user has
+ * not turned on the "speak passwords" preference and is not listening
+ * through headphones.
+ */
+class ObscureSpeechDelegate extends AccessibilityDelegate {
+    /** Whether any client has announced the "headset" notification. */
+    static boolean sAnnouncedHeadset = false;
+
+    private final ContentResolver mContentResolver;
+    private final AudioManager mAudioManager;
+
+    public ObscureSpeechDelegate(Context context) {
+        mContentResolver = context.getContentResolver();
+        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+    }
+
+    @Override
+    public void sendAccessibilityEvent(View host, int eventType) {
+        super.sendAccessibilityEvent(host, eventType);
+
+        // Play the "headset required" announcement the first time the user
+        // places accessibility focus on a key.
+        if ((eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED)
+                && !sAnnouncedHeadset && shouldObscureSpeech()) {
+            sAnnouncedHeadset = true;
+            host.announceForAccessibility(host.getContext().getString(
+                    R.string.keyboard_headset_required_to_hear_password));
+        }
+    }
+
+    @Override
+    public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
+        super.onPopulateAccessibilityEvent(host, event);
+
+        if ((event.getEventType() != AccessibilityEvent.TYPE_ANNOUNCEMENT)
+                && shouldObscureSpeech()) {
+            event.getText().clear();
+            event.setContentDescription(host.getContext().getString(
+                    R.string.keyboard_password_character_no_headset));
+        }
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(host, info);
+
+        if (shouldObscureSpeech()) {
+            final Context ctx = host.getContext();
+            info.setText(null);
+            info.setContentDescription(
+                    ctx.getString(R.string.keyboard_password_character_no_headset));
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private boolean shouldObscureSpeech() {
+        // The user can optionally force speaking passwords.
+        if (Settings.Secure.getInt(mContentResolver,
+                Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0) != 0) {
+            return false;
+        }
+
+        // Always speak if the user is listening through headphones.
+        if (mAudioManager.isWiredHeadsetOn() || mAudioManager.isBluetoothA2dpOn()) {
+            return false;
+        }
+
+        // Don't speak since this key is used to type a password.
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
new file mode 100644
index 0000000..3900ab4
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
@@ -0,0 +1,2555 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.InputDevice;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
+import android.widget.Scroller;
+
+import com.android.internal.R;
+
+import java.util.ArrayList;
+
+/**
+ * An abstraction of the original Workspace which supports browsing through a
+ * sequential list of "pages"
+ */
+public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarchyChangeListener {
+    private static final String TAG = "WidgetPagedView";
+    private static final boolean DEBUG = false;
+    protected static final int INVALID_PAGE = -1;
+
+    // the min drag distance for a fling to register, to prevent random page shifts
+    private static final int MIN_LENGTH_FOR_FLING = 25;
+
+    protected static final int PAGE_SNAP_ANIMATION_DURATION = 750;
+    protected static final int SLOW_PAGE_SNAP_ANIMATION_DURATION = 950;
+    protected static final float NANOTIME_DIV = 1000000000.0f;
+
+    private static final float OVERSCROLL_ACCELERATE_FACTOR = 2;
+    private static final float OVERSCROLL_DAMP_FACTOR = 0.14f;
+
+    private static final float RETURN_TO_ORIGINAL_PAGE_THRESHOLD = 0.33f;
+    // The page is moved more than halfway, automatically move to the next page on touch up.
+    private static final float SIGNIFICANT_MOVE_THRESHOLD = 0.4f;
+
+    // The following constants need to be scaled based on density. The scaled versions will be
+    // assigned to the corresponding member variables below.
+    private static final int FLING_THRESHOLD_VELOCITY = 500;
+    private static final int MIN_SNAP_VELOCITY = 1500;
+    private static final int MIN_FLING_VELOCITY = 250;
+
+    // We are disabling touch interaction of the widget region for factory ROM. 
+    private static final boolean DISABLE_TOUCH_INTERACTION = false;
+    private static final boolean DISABLE_TOUCH_SIDE_PAGES = true;
+    private static final boolean DISABLE_FLING_TO_DELETE = false;
+
+    static final int AUTOMATIC_PAGE_SPACING = -1;
+
+    protected int mFlingThresholdVelocity;
+    protected int mMinFlingVelocity;
+    protected int mMinSnapVelocity;
+
+    protected float mDensity;
+    protected float mSmoothingTime;
+    protected float mTouchX;
+
+    protected boolean mFirstLayout = true;
+
+    protected int mCurrentPage;
+    protected int mChildCountOnLastMeasure;
+
+    protected int mNextPage = INVALID_PAGE;
+    protected int mMaxScrollX;
+    protected Scroller mScroller;
+    private VelocityTracker mVelocityTracker;
+
+    private float mParentDownMotionX;
+    private float mParentDownMotionY;
+    private float mDownMotionX;
+    private float mDownMotionY;
+    private float mDownScrollX;
+    protected float mLastMotionX;
+    protected float mLastMotionXRemainder;
+    protected float mLastMotionY;
+    protected float mTotalMotionX;
+    private int mLastScreenCenter = -1;
+    private int[] mChildOffsets;
+    private int[] mChildRelativeOffsets;
+    private int[] mChildOffsetsWithLayoutScale;
+
+    protected final static int TOUCH_STATE_REST = 0;
+    protected final static int TOUCH_STATE_SCROLLING = 1;
+    protected final static int TOUCH_STATE_PREV_PAGE = 2;
+    protected final static int TOUCH_STATE_NEXT_PAGE = 3;
+    protected final static int TOUCH_STATE_REORDERING = 4;
+
+    protected final static float ALPHA_QUANTIZE_LEVEL = 0.0001f;
+
+    protected int mTouchState = TOUCH_STATE_REST;
+    protected boolean mForceScreenScrolled = false;
+
+    protected OnLongClickListener mLongClickListener;
+
+    protected int mTouchSlop;
+    private int mPagingTouchSlop;
+    private int mMaximumVelocity;
+    private int mMinimumWidth;
+    protected int mPageSpacing;
+    protected int mCellCountX = 0;
+    protected int mCellCountY = 0;
+    protected boolean mAllowOverScroll = true;
+    protected int mUnboundedScrollX;
+    protected int[] mTempVisiblePagesRange = new int[2];
+    protected boolean mForceDrawAllChildrenNextFrame;
+
+    // mOverScrollX is equal to getScrollX() when we're within the normal scroll range. Otherwise
+    // it is equal to the scaled overscroll position. We use a separate value so as to prevent
+    // the screens from continuing to translate beyond the normal bounds.
+    protected int mOverScrollX;
+
+    // parameter that adjusts the layout to be optimized for pages with that scale factor
+    protected float mLayoutScale = 1.0f;
+
+    protected static final int INVALID_POINTER = -1;
+
+    protected int mActivePointerId = INVALID_POINTER;
+
+    private PageSwitchListener mPageSwitchListener;
+
+    protected ArrayList<Boolean> mDirtyPageContent;
+
+    // If true, syncPages and syncPageItems will be called to refresh pages
+    protected boolean mContentIsRefreshable = true;
+
+    // If true, modify alpha of neighboring pages as user scrolls left/right
+    protected boolean mFadeInAdjacentScreens = false;
+
+    // It true, use a different slop parameter (pagingTouchSlop = 2 * touchSlop) for deciding
+    // to switch to a new page
+    protected boolean mUsePagingTouchSlop = true;
+
+    // If true, the subclass should directly update scrollX itself in its computeScroll method
+    // (SmoothPagedView does this)
+    protected boolean mDeferScrollUpdate = false;
+
+    protected boolean mIsPageMoving = false;
+
+    // All syncs and layout passes are deferred until data is ready.
+    protected boolean mIsDataReady = true;
+
+    // Scrolling indicator
+    private ValueAnimator mScrollIndicatorAnimator;
+    private View mScrollIndicator;
+    private int mScrollIndicatorPaddingLeft;
+    private int mScrollIndicatorPaddingRight;
+    private boolean mShouldShowScrollIndicator = false;
+    private boolean mShouldShowScrollIndicatorImmediately = false;
+    protected static final int sScrollIndicatorFadeInDuration = 150;
+    protected static final int sScrollIndicatorFadeOutDuration = 650;
+    protected static final int sScrollIndicatorFlashDuration = 650;
+
+    // The viewport whether the pages are to be contained (the actual view may be larger than the
+    // viewport)
+    private Rect mViewport = new Rect();
+
+    // Reordering
+    // We use the min scale to determine how much to expand the actually PagedView measured
+    // dimensions such that when we are zoomed out, the view is not clipped
+    private int REORDERING_DROP_REPOSITION_DURATION = 200;
+    protected int REORDERING_REORDER_REPOSITION_DURATION = 300;
+    protected int REORDERING_ZOOM_IN_OUT_DURATION = 250;
+    private int REORDERING_SIDE_PAGE_HOVER_TIMEOUT = 300;
+    private float REORDERING_SIDE_PAGE_BUFFER_PERCENTAGE = 0.1f;
+    private long REORDERING_DELETE_DROP_TARGET_FADE_DURATION = 150;
+    private float mMinScale = 1f;
+    protected View mDragView;
+    protected AnimatorSet mZoomInOutAnim;
+    private Runnable mSidePageHoverRunnable;
+    private int mSidePageHoverIndex = -1;
+    // This variable's scope is only for the duration of startReordering() and endReordering()
+    private boolean mReorderingStarted = false;
+    // This variable's scope is for the duration of startReordering() and after the zoomIn()
+    // animation after endReordering()
+    private boolean mIsReordering;
+    // The runnable that settles the page after snapToPage and animateDragViewToOriginalPosition
+    private int NUM_ANIMATIONS_RUNNING_BEFORE_ZOOM_OUT = 2;
+    private int mPostReorderingPreZoomInRemainingAnimationCount;
+    private Runnable mPostReorderingPreZoomInRunnable;
+
+    // Edge swiping
+    private boolean mOnlyAllowEdgeSwipes = false;
+    private boolean mDownEventOnEdge = false;
+    private int mEdgeSwipeRegionSize = 0;
+
+    // Convenience/caching
+    private Matrix mTmpInvMatrix = new Matrix();
+    private float[] mTmpPoint = new float[2];
+    private Rect mTmpRect = new Rect();
+    private Rect mAltTmpRect = new Rect();
+
+    // Fling to delete
+    private int FLING_TO_DELETE_FADE_OUT_DURATION = 350;
+    private float FLING_TO_DELETE_FRICTION = 0.035f;
+    // The degrees specifies how much deviation from the up vector to still consider a fling "up"
+    private float FLING_TO_DELETE_MAX_FLING_DEGREES = 65f;
+    protected int mFlingToDeleteThresholdVelocity = -1400;
+    // Drag to delete
+    private boolean mDeferringForDelete = false;
+    private int DELETE_SLIDE_IN_SIDE_PAGE_DURATION = 250;
+    private int DRAG_TO_DELETE_FADE_OUT_DURATION = 350;
+
+    // Drop to delete
+    private View mDeleteDropTarget;
+
+    // Bouncer
+    private boolean mTopAlignPageWhenShrinkingForBouncer = false;
+
+    public interface PageSwitchListener {
+        void onPageSwitching(View newPage, int newPageIndex);
+        void onPageSwitched(View newPage, int newPageIndex);
+    }
+
+    public PagedView(Context context) {
+        this(context, null);
+    }
+
+    public PagedView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public PagedView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.PagedView, defStyle, 0);
+        setPageSpacing(a.getDimensionPixelSize(R.styleable.PagedView_pageSpacing, 0));
+        mScrollIndicatorPaddingLeft =
+            a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingLeft, 0);
+        mScrollIndicatorPaddingRight =
+                a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingRight, 0);
+        a.recycle();
+
+        Resources r = getResources();
+        mEdgeSwipeRegionSize = r.getDimensionPixelSize(R.dimen.kg_edge_swipe_region_size);
+        mTopAlignPageWhenShrinkingForBouncer =
+                r.getBoolean(R.bool.kg_top_align_page_shrink_on_bouncer_visible);
+
+        setHapticFeedbackEnabled(false);
+        init();
+    }
+
+    /**
+     * Initializes various states for this workspace.
+     */
+    protected void init() {
+        mDirtyPageContent = new ArrayList<Boolean>();
+        mDirtyPageContent.ensureCapacity(32);
+        mScroller = new Scroller(getContext(), new ScrollInterpolator());
+        mCurrentPage = 0;
+
+        final ViewConfiguration configuration = ViewConfiguration.get(getContext());
+        mTouchSlop = configuration.getScaledTouchSlop();
+        mPagingTouchSlop = configuration.getScaledPagingTouchSlop();
+        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
+        mDensity = getResources().getDisplayMetrics().density;
+
+        // Scale the fling-to-delete threshold by the density
+        mFlingToDeleteThresholdVelocity =
+                (int) (mFlingToDeleteThresholdVelocity * mDensity);
+
+        mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * mDensity);
+        mMinFlingVelocity = (int) (MIN_FLING_VELOCITY * mDensity);
+        mMinSnapVelocity = (int) (MIN_SNAP_VELOCITY * mDensity);
+        setOnHierarchyChangeListener(this);
+    }
+
+    void setDeleteDropTarget(View v) {
+        mDeleteDropTarget = v;
+    }
+
+    // Convenience methods to map points from self to parent and vice versa
+    float[] mapPointFromViewToParent(View v, float x, float y) {
+        mTmpPoint[0] = x;
+        mTmpPoint[1] = y;
+        v.getMatrix().mapPoints(mTmpPoint);
+        mTmpPoint[0] += v.getLeft();
+        mTmpPoint[1] += v.getTop();
+        return mTmpPoint;
+    }
+    float[] mapPointFromParentToView(View v, float x, float y) {
+        mTmpPoint[0] = x - v.getLeft();
+        mTmpPoint[1] = y - v.getTop();
+        v.getMatrix().invert(mTmpInvMatrix);
+        mTmpInvMatrix.mapPoints(mTmpPoint);
+        return mTmpPoint;
+    }
+
+    void updateDragViewTranslationDuringDrag() {
+        float x = mLastMotionX - mDownMotionX + getScrollX() - mDownScrollX;
+        float y = mLastMotionY - mDownMotionY;
+        mDragView.setTranslationX(x);
+        mDragView.setTranslationY(y);
+
+        if (DEBUG) Log.d(TAG, "PagedView.updateDragViewTranslationDuringDrag(): " + x + ", " + y);
+    }
+
+    public void setMinScale(float f) {
+        mMinScale = f;
+        requestLayout();
+    }
+
+    @Override
+    public void setScaleX(float scaleX) {
+        super.setScaleX(scaleX);
+        if (isReordering(true)) {
+            float[] p = mapPointFromParentToView(this, mParentDownMotionX, mParentDownMotionY);
+            mLastMotionX = p[0];
+            mLastMotionY = p[1];
+            updateDragViewTranslationDuringDrag();
+        }
+    }
+
+    // Convenience methods to get the actual width/height of the PagedView (since it is measured
+    // to be larger to account for the minimum possible scale)
+    int getViewportWidth() {
+        return mViewport.width();
+    }
+    int getViewportHeight() {
+        return mViewport.height();
+    }
+
+    // Convenience methods to get the offset ASSUMING that we are centering the pages in the
+    // PagedView both horizontally and vertically
+    int getViewportOffsetX() {
+        return (getMeasuredWidth() - getViewportWidth()) / 2;
+    }
+    int getViewportOffsetY() {
+        return (getMeasuredHeight() - getViewportHeight()) / 2;
+    }
+
+    public void setPageSwitchListener(PageSwitchListener pageSwitchListener) {
+        mPageSwitchListener = pageSwitchListener;
+        if (mPageSwitchListener != null) {
+            mPageSwitchListener.onPageSwitched(getPageAt(mCurrentPage), mCurrentPage);
+        }
+    }
+
+    /**
+     * Called by subclasses to mark that data is ready, and that we can begin loading and laying
+     * out pages.
+     */
+    protected void setDataIsReady() {
+        mIsDataReady = true;
+    }
+
+    protected boolean isDataReady() {
+        return mIsDataReady;
+    }
+
+    /**
+     * Returns the index of the currently displayed page.
+     *
+     * @return The index of the currently displayed page.
+     */
+    int getCurrentPage() {
+        return mCurrentPage;
+    }
+
+    int getNextPage() {
+        return (mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage;
+    }
+
+    int getPageCount() {
+        return getChildCount();
+    }
+
+    View getPageAt(int index) {
+        return getChildAt(index);
+    }
+
+    protected int indexToPage(int index) {
+        return index;
+    }
+
+    /**
+     * Updates the scroll of the current page immediately to its final scroll position.  We use this
+     * in CustomizePagedView to allow tabs to share the same PagedView while resetting the scroll of
+     * the previous tab page.
+     */
+    protected void updateCurrentPageScroll() {
+        int offset = getChildOffset(mCurrentPage);
+        int relOffset = getRelativeChildOffset(mCurrentPage);
+        int newX = offset - relOffset;
+        scrollTo(newX, 0);
+        mScroller.setFinalX(newX);
+        mScroller.forceFinished(true);
+    }
+
+    /**
+     * Sets the current page.
+     */
+    void setCurrentPage(int currentPage) {
+        notifyPageSwitching(currentPage);
+        if (!mScroller.isFinished()) {
+            mScroller.abortAnimation();
+        }
+        // don't introduce any checks like mCurrentPage == currentPage here-- if we change the
+        // the default
+        if (getChildCount() == 0) {
+            return;
+        }
+
+        mForceScreenScrolled = true;
+        mCurrentPage = Math.max(0, Math.min(currentPage, getPageCount() - 1));
+        updateCurrentPageScroll();
+        updateScrollingIndicator();
+        notifyPageSwitched();
+        invalidate();
+    }
+
+    public void setOnlyAllowEdgeSwipes(boolean enable) {
+        mOnlyAllowEdgeSwipes = enable;
+    }
+
+    protected void notifyPageSwitching(int whichPage) {
+        if (mPageSwitchListener != null) {
+            mPageSwitchListener.onPageSwitching(getPageAt(whichPage), whichPage);
+        }
+    }
+
+    protected void notifyPageSwitched() {
+        if (mPageSwitchListener != null) {
+            mPageSwitchListener.onPageSwitched(getPageAt(mCurrentPage), mCurrentPage);
+        }
+    }
+
+    protected void pageBeginMoving() {
+        if (!mIsPageMoving) {
+            mIsPageMoving = true;
+            onPageBeginMoving();
+        }
+    }
+
+    protected void pageEndMoving() {
+        if (mIsPageMoving) {
+            mIsPageMoving = false;
+            onPageEndMoving();
+        }
+    }
+
+    protected boolean isPageMoving() {
+        return mIsPageMoving;
+    }
+
+    // a method that subclasses can override to add behavior
+    protected void onPageBeginMoving() {
+    }
+
+    // a method that subclasses can override to add behavior
+    protected void onPageEndMoving() {
+    }
+
+    /**
+     * Registers the specified listener on each page contained in this workspace.
+     *
+     * @param l The listener used to respond to long clicks.
+     */
+    @Override
+    public void setOnLongClickListener(OnLongClickListener l) {
+        mLongClickListener = l;
+        final int count = getPageCount();
+        for (int i = 0; i < count; i++) {
+            getPageAt(i).setOnLongClickListener(l);
+        }
+    }
+
+    @Override
+    public void scrollBy(int x, int y) {
+        scrollTo(mUnboundedScrollX + x, getScrollY() + y);
+    }
+
+    @Override
+    public void scrollTo(int x, int y) {
+        mUnboundedScrollX = x;
+
+        if (x < 0) {
+            super.scrollTo(0, y);
+            if (mAllowOverScroll) {
+                overScroll(x);
+            }
+        } else if (x > mMaxScrollX) {
+            super.scrollTo(mMaxScrollX, y);
+            if (mAllowOverScroll) {
+                overScroll(x - mMaxScrollX);
+            }
+        } else {
+            mOverScrollX = x;
+            super.scrollTo(x, y);
+        }
+
+        mTouchX = x;
+        mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
+
+        // Update the last motion events when scrolling
+        if (isReordering(true)) {
+            float[] p = mapPointFromParentToView(this, mParentDownMotionX, mParentDownMotionY);
+            mLastMotionX = p[0];
+            mLastMotionY = p[1];
+            updateDragViewTranslationDuringDrag();
+        }
+    }
+
+    // we moved this functionality to a helper function so SmoothPagedView can reuse it
+    protected boolean computeScrollHelper() {
+        if (mScroller.computeScrollOffset()) {
+            // Don't bother scrolling if the page does not need to be moved
+            if (getScrollX() != mScroller.getCurrX()
+                || getScrollY() != mScroller.getCurrY()
+                || mOverScrollX != mScroller.getCurrX()) {
+                scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
+            }
+            invalidate();
+            return true;
+        } else if (mNextPage != INVALID_PAGE) {
+            mCurrentPage = Math.max(0, Math.min(mNextPage, getPageCount() - 1));
+            mNextPage = INVALID_PAGE;
+            notifyPageSwitched();
+
+            // We don't want to trigger a page end moving unless the page has settled
+            // and the user has stopped scrolling
+            if (mTouchState == TOUCH_STATE_REST) {
+                pageEndMoving();
+            }
+
+            onPostReorderingAnimationCompleted();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void computeScroll() {
+        computeScrollHelper();
+    }
+
+    protected boolean shouldSetTopAlignedPivotForWidget(int childIndex) {
+        return mTopAlignPageWhenShrinkingForBouncer;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (!mIsDataReady || getChildCount() == 0) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+            return;
+        }
+
+        // We measure the dimensions of the PagedView to be larger than the pages so that when we
+        // zoom out (and scale down), the view is still contained in the parent
+        View parent = (View) getParent();
+        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+        // NOTE: We multiply by 1.5f to account for the fact that depending on the offset of the
+        // viewport, we can be at most one and a half screens offset once we scale down
+        DisplayMetrics dm = getResources().getDisplayMetrics();
+        int maxSize = Math.max(dm.widthPixels, dm.heightPixels);
+        int parentWidthSize = (int) (1.5f * maxSize);
+        int parentHeightSize = maxSize;
+        int scaledWidthSize = (int) (parentWidthSize / mMinScale);
+        int scaledHeightSize = (int) (parentHeightSize / mMinScale);
+        mViewport.set(0, 0, widthSize, heightSize);
+
+        if (widthMode == MeasureSpec.UNSPECIFIED || heightMode == MeasureSpec.UNSPECIFIED) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+            return;
+        }
+
+        // Return early if we aren't given a proper dimension
+        if (widthSize <= 0 || heightSize <= 0) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+            return;
+        }
+
+        /* Allow the height to be set as WRAP_CONTENT. This allows the particular case
+         * of the All apps view on XLarge displays to not take up more space then it needs. Width
+         * is still not allowed to be set as WRAP_CONTENT since many parts of the code expect
+         * each page to have the same width.
+         */
+        final int verticalPadding = getPaddingTop() + getPaddingBottom();
+        final int horizontalPadding = getPaddingLeft() + getPaddingRight();
+
+        // The children are given the same width and height as the workspace
+        // unless they were set to WRAP_CONTENT
+        if (DEBUG) Log.d(TAG, "PagedView.onMeasure(): " + widthSize + ", " + heightSize);
+        if (DEBUG) Log.d(TAG, "PagedView.scaledSize: " + scaledWidthSize + ", " + scaledHeightSize);
+        if (DEBUG) Log.d(TAG, "PagedView.parentSize: " + parentWidthSize + ", " + parentHeightSize);
+        if (DEBUG) Log.d(TAG, "PagedView.horizontalPadding: " + horizontalPadding);
+        if (DEBUG) Log.d(TAG, "PagedView.verticalPadding: " + verticalPadding);
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            // disallowing padding in paged view (just pass 0)
+            final View child = getPageAt(i);
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+            int childWidthMode;
+            if (lp.width == LayoutParams.WRAP_CONTENT) {
+                childWidthMode = MeasureSpec.AT_MOST;
+            } else {
+                childWidthMode = MeasureSpec.EXACTLY;
+            }
+
+            int childHeightMode;
+            if (lp.height == LayoutParams.WRAP_CONTENT) {
+                childHeightMode = MeasureSpec.AT_MOST;
+            } else {
+                childHeightMode = MeasureSpec.EXACTLY;
+            }
+
+            final int childWidthMeasureSpec =
+                MeasureSpec.makeMeasureSpec(widthSize - horizontalPadding, childWidthMode);
+            final int childHeightMeasureSpec =
+                MeasureSpec.makeMeasureSpec(heightSize - verticalPadding, childHeightMode);
+
+            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+        }
+        setMeasuredDimension(scaledWidthSize, scaledHeightSize);
+
+        // We can't call getChildOffset/getRelativeChildOffset until we set the measured dimensions.
+        // We also wait until we set the measured dimensions before flushing the cache as well, to
+        // ensure that the cache is filled with good values.
+        invalidateCachedOffsets();
+
+        if (mChildCountOnLastMeasure != getChildCount() && !mDeferringForDelete) {
+            setCurrentPage(mCurrentPage);
+        }
+        mChildCountOnLastMeasure = getChildCount();
+
+        if (childCount > 0) {
+            if (DEBUG) Log.d(TAG, "getRelativeChildOffset(): " + getViewportWidth() + ", "
+                    + getChildWidth(0));
+
+            // Calculate the variable page spacing if necessary
+            if (mPageSpacing == AUTOMATIC_PAGE_SPACING) {
+                // The gap between pages in the PagedView should be equal to the gap from the page
+                // to the edge of the screen (so it is not visible in the current screen).  To
+                // account for unequal padding on each side of the paged view, we take the maximum
+                // of the left/right gap and use that as the gap between each page.
+                int offset = getRelativeChildOffset(0);
+                int spacing = Math.max(offset, widthSize - offset -
+                        getChildAt(0).getMeasuredWidth());
+                setPageSpacing(spacing);
+            }
+        }
+
+        updateScrollingIndicatorPosition();
+
+        if (childCount > 0) {
+            mMaxScrollX = getChildOffset(childCount - 1) - getRelativeChildOffset(childCount - 1);
+        } else {
+            mMaxScrollX = 0;
+        }
+    }
+
+    public void setPageSpacing(int pageSpacing) {
+        mPageSpacing = pageSpacing;
+        invalidateCachedOffsets();
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        if (!mIsDataReady || getChildCount() == 0) {
+            return;
+        }
+
+        if (DEBUG) Log.d(TAG, "PagedView.onLayout()");
+        final int childCount = getChildCount();
+
+        int offsetX = getViewportOffsetX();
+        int offsetY = getViewportOffsetY();
+
+        // Update the viewport offsets
+        mViewport.offset(offsetX,  offsetY);
+
+        int childLeft = offsetX + getRelativeChildOffset(0);
+        for (int i = 0; i < childCount; i++) {
+            final View child = getPageAt(i);
+            int childTop = offsetY + getPaddingTop();
+            if (child.getVisibility() != View.GONE) {
+                final int childWidth = getScaledMeasuredWidth(child);
+                final int childHeight = child.getMeasuredHeight();
+
+                if (DEBUG) Log.d(TAG, "\tlayout-child" + i + ": " + childLeft + ", " + childTop);
+                child.layout(childLeft, childTop,
+                        childLeft + child.getMeasuredWidth(), childTop + childHeight);
+                childLeft += childWidth + mPageSpacing;
+            }
+        }
+
+        if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) {
+            setHorizontalScrollBarEnabled(false);
+            updateCurrentPageScroll();
+            setHorizontalScrollBarEnabled(true);
+            mFirstLayout = false;
+        }
+    }
+
+    protected void screenScrolled(int screenCenter) {
+    }
+
+    @Override
+    public void onChildViewAdded(View parent, View child) {
+        // This ensures that when children are added, they get the correct transforms / alphas
+        // in accordance with any scroll effects.
+        mForceScreenScrolled = true;
+        invalidate();
+        invalidateCachedOffsets();
+    }
+
+    @Override
+    public void onChildViewRemoved(View parent, View child) {
+        mForceScreenScrolled = true;
+    }
+
+    protected void invalidateCachedOffsets() {
+        int count = getChildCount();
+        if (count == 0) {
+            mChildOffsets = null;
+            mChildRelativeOffsets = null;
+            mChildOffsetsWithLayoutScale = null;
+            return;
+        }
+
+        mChildOffsets = new int[count];
+        mChildRelativeOffsets = new int[count];
+        mChildOffsetsWithLayoutScale = new int[count];
+        for (int i = 0; i < count; i++) {
+            mChildOffsets[i] = -1;
+            mChildRelativeOffsets[i] = -1;
+            mChildOffsetsWithLayoutScale[i] = -1;
+        }
+    }
+
+    protected int getChildOffset(int index) {
+        if (index < 0 || index > getChildCount() - 1) return 0;
+
+        int[] childOffsets = Float.compare(mLayoutScale, 1f) == 0 ?
+                mChildOffsets : mChildOffsetsWithLayoutScale;
+
+        if (childOffsets != null && childOffsets[index] != -1) {
+            return childOffsets[index];
+        } else {
+            if (getChildCount() == 0)
+                return 0;
+
+            int offset = getRelativeChildOffset(0);
+            for (int i = 0; i < index; ++i) {
+                offset += getScaledMeasuredWidth(getPageAt(i)) + mPageSpacing;
+            }
+            if (childOffsets != null) {
+                childOffsets[index] = offset;
+            }
+            return offset;
+        }
+    }
+
+    protected int getRelativeChildOffset(int index) {
+        if (index < 0 || index > getChildCount() - 1) return 0;
+
+        if (mChildRelativeOffsets != null && mChildRelativeOffsets[index] != -1) {
+            return mChildRelativeOffsets[index];
+        } else {
+            final int padding = getPaddingLeft() + getPaddingRight();
+            final int offset = getPaddingLeft() +
+                    (getViewportWidth() - padding - getChildWidth(index)) / 2;
+            if (mChildRelativeOffsets != null) {
+                mChildRelativeOffsets[index] = offset;
+            }
+            return offset;
+        }
+    }
+
+    protected int getScaledMeasuredWidth(View child) {
+        // This functions are called enough times that it actually makes a difference in the
+        // profiler -- so just inline the max() here
+        final int measuredWidth = child.getMeasuredWidth();
+        final int minWidth = mMinimumWidth;
+        final int maxWidth = (minWidth > measuredWidth) ? minWidth : measuredWidth;
+        return (int) (maxWidth * mLayoutScale + 0.5f);
+    }
+
+    void boundByReorderablePages(boolean isReordering, int[] range) {
+        // Do nothing
+    }
+
+    // TODO: Fix this
+    protected void getVisiblePages(int[] range) {
+        range[0] = 0;
+        range[1] = getPageCount() - 1;
+
+        /*
+        final int pageCount = getChildCount();
+
+        if (pageCount > 0) {
+            final int screenWidth = getViewportWidth();
+            int leftScreen = 0;
+            int rightScreen = 0;
+            int offsetX = getViewportOffsetX() + getScrollX();
+            View currPage = getPageAt(leftScreen);
+            while (leftScreen < pageCount - 1 &&
+                    currPage.getX() + currPage.getWidth() -
+                    currPage.getPaddingRight() < offsetX) {
+                leftScreen++;
+                currPage = getPageAt(leftScreen);
+            }
+            rightScreen = leftScreen;
+            currPage = getPageAt(rightScreen + 1);
+            while (rightScreen < pageCount - 1 &&
+                    currPage.getX() - currPage.getPaddingLeft() < offsetX + screenWidth) {
+                rightScreen++;
+                currPage = getPageAt(rightScreen + 1);
+            }
+
+            // TEMP: this is a hacky way to ensure that animations to new pages are not clipped
+            // because we don't draw them while scrolling?
+            range[0] = Math.max(0, leftScreen - 1);
+            range[1] = Math.min(rightScreen + 1, getChildCount() - 1);
+        } else {
+            range[0] = -1;
+            range[1] = -1;
+        }
+        */
+    }
+
+    protected boolean shouldDrawChild(View child) {
+        return child.getAlpha() > 0;
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        int halfScreenSize = getViewportWidth() / 2;
+        // mOverScrollX is equal to getScrollX() when we're within the normal scroll range.
+        // Otherwise it is equal to the scaled overscroll position.
+        int screenCenter = mOverScrollX + halfScreenSize;
+
+        if (screenCenter != mLastScreenCenter || mForceScreenScrolled) {
+            // set mForceScreenScrolled before calling screenScrolled so that screenScrolled can
+            // set it for the next frame
+            mForceScreenScrolled = false;
+            screenScrolled(screenCenter);
+            mLastScreenCenter = screenCenter;
+        }
+
+        // Find out which screens are visible; as an optimization we only call draw on them
+        final int pageCount = getChildCount();
+        if (pageCount > 0) {
+            getVisiblePages(mTempVisiblePagesRange);
+            final int leftScreen = mTempVisiblePagesRange[0];
+            final int rightScreen = mTempVisiblePagesRange[1];
+            if (leftScreen != -1 && rightScreen != -1) {
+                final long drawingTime = getDrawingTime();
+                // Clip to the bounds
+                canvas.save();
+                canvas.clipRect(getScrollX(), getScrollY(), getScrollX() + getRight() - getLeft(),
+                        getScrollY() + getBottom() - getTop());
+
+                // Draw all the children, leaving the drag view for last
+                for (int i = pageCount - 1; i >= 0; i--) {
+                    final View v = getPageAt(i);
+                    if (v == mDragView) continue;
+                    if (mForceDrawAllChildrenNextFrame ||
+                               (leftScreen <= i && i <= rightScreen && shouldDrawChild(v))) {
+                        drawChild(canvas, v, drawingTime);
+                    }
+                }
+                // Draw the drag view on top (if there is one)
+                if (mDragView != null) {
+                    drawChild(canvas, mDragView, drawingTime);
+                }
+
+                mForceDrawAllChildrenNextFrame = false;
+                canvas.restore();
+            }
+        }
+    }
+
+    @Override
+    public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
+        int page = indexToPage(indexOfChild(child));
+        if (page != mCurrentPage || !mScroller.isFinished()) {
+            snapToPage(page);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
+        int focusablePage;
+        if (mNextPage != INVALID_PAGE) {
+            focusablePage = mNextPage;
+        } else {
+            focusablePage = mCurrentPage;
+        }
+        View v = getPageAt(focusablePage);
+        if (v != null) {
+            return v.requestFocus(direction, previouslyFocusedRect);
+        }
+        return false;
+    }
+
+    @Override
+    public boolean dispatchUnhandledMove(View focused, int direction) {
+        if (direction == View.FOCUS_LEFT) {
+            if (getCurrentPage() > 0) {
+                snapToPage(getCurrentPage() - 1);
+                return true;
+            }
+        } else if (direction == View.FOCUS_RIGHT) {
+            if (getCurrentPage() < getPageCount() - 1) {
+                snapToPage(getCurrentPage() + 1);
+                return true;
+            }
+        }
+        return super.dispatchUnhandledMove(focused, direction);
+    }
+
+    @Override
+    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
+        if (mCurrentPage >= 0 && mCurrentPage < getPageCount()) {
+            getPageAt(mCurrentPage).addFocusables(views, direction, focusableMode);
+        }
+        if (direction == View.FOCUS_LEFT) {
+            if (mCurrentPage > 0) {
+                getPageAt(mCurrentPage - 1).addFocusables(views, direction, focusableMode);
+            }
+        } else if (direction == View.FOCUS_RIGHT){
+            if (mCurrentPage < getPageCount() - 1) {
+                getPageAt(mCurrentPage + 1).addFocusables(views, direction, focusableMode);
+            }
+        }
+    }
+
+    /**
+     * If one of our descendant views decides that it could be focused now, only
+     * pass that along if it's on the current page.
+     *
+     * This happens when live folders requery, and if they're off page, they
+     * end up calling requestFocus, which pulls it on page.
+     */
+    @Override
+    public void focusableViewAvailable(View focused) {
+        View current = getPageAt(mCurrentPage);
+        View v = focused;
+        while (true) {
+            if (v == current) {
+                super.focusableViewAvailable(focused);
+                return;
+            }
+            if (v == this) {
+                return;
+            }
+            ViewParent parent = v.getParent();
+            if (parent instanceof View) {
+                v = (View)v.getParent();
+            } else {
+                return;
+            }
+        }
+    }
+
+    /**
+     * Return true if a tap at (x, y) should trigger a flip to the previous page.
+     */
+    protected boolean hitsPreviousPage(float x, float y) {
+        return (x < getViewportOffsetX() + getRelativeChildOffset(mCurrentPage) - mPageSpacing);
+    }
+
+    /**
+     * Return true if a tap at (x, y) should trigger a flip to the next page.
+     */
+    protected boolean hitsNextPage(float x, float y) {
+        return  (x > (getViewportOffsetX() + getViewportWidth() - getRelativeChildOffset(mCurrentPage) + mPageSpacing));
+    }
+
+    /** Returns whether x and y originated within the buffered/unbuffered viewport */
+    private boolean isTouchPointInViewport(int x, int y, boolean buffer) {
+        if (buffer) {
+            mTmpRect.set(mViewport.left - mViewport.width() / 2, mViewport.top,
+                    mViewport.right + mViewport.width() / 2, mViewport.bottom);
+            return mTmpRect.contains(x, y);
+        } else {
+            return mViewport.contains(x, y);
+        }
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (DISABLE_TOUCH_INTERACTION) {
+            return false;
+        }
+
+        /*
+         * This method JUST determines whether we want to intercept the motion.
+         * If we return true, onTouchEvent will be called and we do the actual
+         * scrolling there.
+         */
+        acquireVelocityTrackerAndAddMovement(ev);
+
+        // Skip touch handling if there are no pages to swipe
+        if (getChildCount() <= 0) return super.onInterceptTouchEvent(ev);
+
+        /*
+         * Shortcut the most recurring case: the user is in the dragging
+         * state and he is moving his finger.  We want to intercept this
+         * motion.
+         */
+        final int action = ev.getAction();
+        if ((action == MotionEvent.ACTION_MOVE) &&
+                (mTouchState == TOUCH_STATE_SCROLLING)) {
+            return true;
+        }
+
+        switch (action & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_MOVE: {
+                /*
+                 * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
+                 * whether the user has moved far enough from his original down touch.
+                 */
+                if (mActivePointerId != INVALID_POINTER) {
+                    determineScrollingStart(ev);
+                    break;
+                }
+                // if mActivePointerId is INVALID_POINTER, then we must have missed an ACTION_DOWN
+                // event. in that case, treat the first occurence of a move event as a ACTION_DOWN
+                // i.e. fall through to the next case (don't break)
+                // (We sometimes miss ACTION_DOWN events in Workspace because it ignores all events
+                // while it's small- this was causing a crash before we checked for INVALID_POINTER)
+            }
+
+            case MotionEvent.ACTION_DOWN: {
+                final float x = ev.getX();
+                final float y = ev.getY();
+                // Remember location of down touch
+                mDownMotionX = x;
+                mDownMotionY = y;
+                mDownScrollX = getScrollX();
+                mLastMotionX = x;
+                mLastMotionY = y;
+                float[] p = mapPointFromViewToParent(this, x, y);
+                mParentDownMotionX = p[0];
+                mParentDownMotionY = p[1];
+                mLastMotionXRemainder = 0;
+                mTotalMotionX = 0;
+                mActivePointerId = ev.getPointerId(0);
+
+                // Determine if the down event is within the threshold to be an edge swipe
+                int leftEdgeBoundary = getViewportOffsetX() + mEdgeSwipeRegionSize;
+                int rightEdgeBoundary = getMeasuredWidth() - getViewportOffsetX() - mEdgeSwipeRegionSize;
+                if ((mDownMotionX <= leftEdgeBoundary || mDownMotionX >= rightEdgeBoundary)) {
+                    mDownEventOnEdge = true;
+                }
+
+                /*
+                 * If being flinged and user touches the screen, initiate drag;
+                 * otherwise don't.  mScroller.isFinished should be false when
+                 * being flinged.
+                 */
+                final int xDist = Math.abs(mScroller.getFinalX() - mScroller.getCurrX());
+                final boolean finishedScrolling = (mScroller.isFinished() || xDist < mTouchSlop);
+                if (finishedScrolling) {
+                    mTouchState = TOUCH_STATE_REST;
+                    mScroller.abortAnimation();
+                } else {
+                    if (isTouchPointInViewport((int) mDownMotionX, (int) mDownMotionY, true)) {
+                        mTouchState = TOUCH_STATE_SCROLLING;
+                    } else {
+                        mTouchState = TOUCH_STATE_REST;
+                    }
+                }
+
+                // check if this can be the beginning of a tap on the side of the pages
+                // to scroll the current page
+                if (!DISABLE_TOUCH_SIDE_PAGES) {
+                    if (mTouchState != TOUCH_STATE_PREV_PAGE && mTouchState != TOUCH_STATE_NEXT_PAGE) {
+                        if (getChildCount() > 0) {
+                            if (hitsPreviousPage(x, y)) {
+                                mTouchState = TOUCH_STATE_PREV_PAGE;
+                            } else if (hitsNextPage(x, y)) {
+                                mTouchState = TOUCH_STATE_NEXT_PAGE;
+                            }
+                        }
+                    }
+                }
+                break;
+            }
+
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                resetTouchState();
+                // Just intercept the touch event on up if we tap outside the strict viewport
+                if (!isTouchPointInViewport((int) mLastMotionX, (int) mLastMotionY, false)) {
+                    return true;
+                }
+                break;
+
+            case MotionEvent.ACTION_POINTER_UP:
+                onSecondaryPointerUp(ev);
+                releaseVelocityTracker();
+                break;
+        }
+
+        /*
+         * The only time we want to intercept motion events is if we are in the
+         * drag mode.
+         */
+        return mTouchState != TOUCH_STATE_REST;
+    }
+
+    protected void determineScrollingStart(MotionEvent ev) {
+        determineScrollingStart(ev, 1.0f);
+    }
+
+    /*
+     * Determines if we should change the touch state to start scrolling after the
+     * user moves their touch point too far.
+     */
+    protected void determineScrollingStart(MotionEvent ev, float touchSlopScale) {
+        // Disallow scrolling if we don't have a valid pointer index
+        final int pointerIndex = ev.findPointerIndex(mActivePointerId);
+        if (pointerIndex == -1) return;
+
+        // Disallow scrolling if we started the gesture from outside the viewport
+        final float x = ev.getX(pointerIndex);
+        final float y = ev.getY(pointerIndex);
+        if (!isTouchPointInViewport((int) x, (int) y, true)) return;
+
+        // If we're only allowing edge swipes, we break out early if the down event wasn't
+        // at the edge.
+        if (mOnlyAllowEdgeSwipes && !mDownEventOnEdge) return;
+
+        final int xDiff = (int) Math.abs(x - mLastMotionX);
+        final int yDiff = (int) Math.abs(y - mLastMotionY);
+
+        final int touchSlop = Math.round(touchSlopScale * mTouchSlop);
+        boolean xPaged = xDiff > mPagingTouchSlop;
+        boolean xMoved = xDiff > touchSlop;
+        boolean yMoved = yDiff > touchSlop;
+
+        if (xMoved || xPaged || yMoved) {
+            if (mUsePagingTouchSlop ? xPaged : xMoved) {
+                // Scroll if the user moved far enough along the X axis
+                mTouchState = TOUCH_STATE_SCROLLING;
+                mTotalMotionX += Math.abs(mLastMotionX - x);
+                mLastMotionX = x;
+                mLastMotionXRemainder = 0;
+                mTouchX = getViewportOffsetX() + getScrollX();
+                mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
+                pageBeginMoving();
+            }
+        }
+    }
+
+    protected float getMaxScrollProgress() {
+        return 1.0f;
+    }
+
+    protected float getBoundedScrollProgress(int screenCenter, View v, int page) {
+        final int halfScreenSize = getViewportWidth() / 2;
+
+        screenCenter = Math.min(mScrollX + halfScreenSize, screenCenter);
+        screenCenter = Math.max(halfScreenSize,  screenCenter);
+
+        return getScrollProgress(screenCenter, v, page);
+    }
+
+    protected float getScrollProgress(int screenCenter, View v, int page) {
+        final int halfScreenSize = getViewportWidth() / 2;
+
+        int totalDistance = getScaledMeasuredWidth(v) + mPageSpacing;
+        int delta = screenCenter - (getChildOffset(page) -
+                getRelativeChildOffset(page) + halfScreenSize);
+
+        float scrollProgress = delta / (totalDistance * 1.0f);
+        scrollProgress = Math.min(scrollProgress, getMaxScrollProgress());
+        scrollProgress = Math.max(scrollProgress, - getMaxScrollProgress());
+        return scrollProgress;
+    }
+
+    // This curve determines how the effect of scrolling over the limits of the page dimishes
+    // as the user pulls further and further from the bounds
+    private float overScrollInfluenceCurve(float f) {
+        f -= 1.0f;
+        return f * f * f + 1.0f;
+    }
+
+    protected void acceleratedOverScroll(float amount) {
+        int screenSize = getViewportWidth();
+
+        // We want to reach the max over scroll effect when the user has
+        // over scrolled half the size of the screen
+        float f = OVERSCROLL_ACCELERATE_FACTOR * (amount / screenSize);
+
+        if (f == 0) return;
+
+        // Clamp this factor, f, to -1 < f < 1
+        if (Math.abs(f) >= 1) {
+            f /= Math.abs(f);
+        }
+
+        int overScrollAmount = (int) Math.round(f * screenSize);
+        if (amount < 0) {
+            mOverScrollX = overScrollAmount;
+            super.scrollTo(0, getScrollY());
+        } else {
+            mOverScrollX = mMaxScrollX + overScrollAmount;
+            super.scrollTo(mMaxScrollX, getScrollY());
+        }
+        invalidate();
+    }
+
+    protected void dampedOverScroll(float amount) {
+        int screenSize = getViewportWidth();
+
+        float f = (amount / screenSize);
+
+        if (f == 0) return;
+        f = f / (Math.abs(f)) * (overScrollInfluenceCurve(Math.abs(f)));
+
+        // Clamp this factor, f, to -1 < f < 1
+        if (Math.abs(f) >= 1) {
+            f /= Math.abs(f);
+        }
+
+        int overScrollAmount = (int) Math.round(OVERSCROLL_DAMP_FACTOR * f * screenSize);
+        if (amount < 0) {
+            mOverScrollX = overScrollAmount;
+            super.scrollTo(0, getScrollY());
+        } else {
+            mOverScrollX = mMaxScrollX + overScrollAmount;
+            super.scrollTo(mMaxScrollX, getScrollY());
+        }
+        invalidate();
+    }
+
+    protected void overScroll(float amount) {
+        dampedOverScroll(amount);
+    }
+
+    protected float maxOverScroll() {
+        // Using the formula in overScroll, assuming that f = 1.0 (which it should generally not
+        // exceed). Used to find out how much extra wallpaper we need for the over scroll effect
+        float f = 1.0f;
+        f = f / (Math.abs(f)) * (overScrollInfluenceCurve(Math.abs(f)));
+        return OVERSCROLL_DAMP_FACTOR * f;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        if (DISABLE_TOUCH_INTERACTION) {
+            return false;
+        }
+
+        // Skip touch handling if there are no pages to swipe
+        if (getChildCount() <= 0) return super.onTouchEvent(ev);
+
+        acquireVelocityTrackerAndAddMovement(ev);
+
+        final int action = ev.getAction();
+
+        switch (action & MotionEvent.ACTION_MASK) {
+        case MotionEvent.ACTION_DOWN:
+            /*
+             * If being flinged and user touches, stop the fling. isFinished
+             * will be false if being flinged.
+             */
+            if (!mScroller.isFinished()) {
+                mScroller.abortAnimation();
+            }
+
+            // Remember where the motion event started
+            mDownMotionX = mLastMotionX = ev.getX();
+            mDownMotionY = mLastMotionY = ev.getY();
+            mDownScrollX = getScrollX();
+            float[] p = mapPointFromViewToParent(this, mLastMotionX, mLastMotionY);
+            mParentDownMotionX = p[0];
+            mParentDownMotionY = p[1];
+            mLastMotionXRemainder = 0;
+            mTotalMotionX = 0;
+            mActivePointerId = ev.getPointerId(0);
+
+            // Determine if the down event is within the threshold to be an edge swipe
+            int leftEdgeBoundary = getViewportOffsetX() + mEdgeSwipeRegionSize;
+            int rightEdgeBoundary = getMeasuredWidth() - getViewportOffsetX() - mEdgeSwipeRegionSize;
+            if ((mDownMotionX <= leftEdgeBoundary || mDownMotionX >= rightEdgeBoundary)) {
+                mDownEventOnEdge = true;
+            }
+
+            if (mTouchState == TOUCH_STATE_SCROLLING) {
+                pageBeginMoving();
+            }
+            break;
+
+        case MotionEvent.ACTION_MOVE:
+            if (mTouchState == TOUCH_STATE_SCROLLING) {
+                // Scroll to follow the motion event
+                final int pointerIndex = ev.findPointerIndex(mActivePointerId);
+                final float x = ev.getX(pointerIndex);
+                final float deltaX = mLastMotionX + mLastMotionXRemainder - x;
+
+                mTotalMotionX += Math.abs(deltaX);
+
+                // Only scroll and update mLastMotionX if we have moved some discrete amount.  We
+                // keep the remainder because we are actually testing if we've moved from the last
+                // scrolled position (which is discrete).
+                if (Math.abs(deltaX) >= 1.0f) {
+                    mTouchX += deltaX;
+                    mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
+                    if (!mDeferScrollUpdate) {
+                        scrollBy((int) deltaX, 0);
+                        if (DEBUG) Log.d(TAG, "onTouchEvent().Scrolling: " + deltaX);
+                    } else {
+                        invalidate();
+                    }
+                    mLastMotionX = x;
+                    mLastMotionXRemainder = deltaX - (int) deltaX;
+                } else {
+                    awakenScrollBars();
+                }
+            } else if (mTouchState == TOUCH_STATE_REORDERING) {
+                // Update the last motion position
+                mLastMotionX = ev.getX();
+                mLastMotionY = ev.getY();
+
+                // Update the parent down so that our zoom animations take this new movement into
+                // account
+                float[] pt = mapPointFromViewToParent(this, mLastMotionX, mLastMotionY);
+                mParentDownMotionX = pt[0];
+                mParentDownMotionY = pt[1];
+                updateDragViewTranslationDuringDrag();
+
+                // Find the closest page to the touch point
+                final int dragViewIndex = indexOfChild(mDragView);
+                int bufferSize = (int) (REORDERING_SIDE_PAGE_BUFFER_PERCENTAGE *
+                    getViewportWidth());
+                int leftBufferEdge = (int) (mapPointFromViewToParent(this, mViewport.left, 0)[0]
+                        + bufferSize);
+                int rightBufferEdge = (int) (mapPointFromViewToParent(this, mViewport.right, 0)[0]
+                        - bufferSize);
+
+                // Change the drag view if we are hovering over the drop target
+                boolean isHoveringOverDelete = isHoveringOverDeleteDropTarget(
+                        (int) mParentDownMotionX, (int) mParentDownMotionY);
+                setPageHoveringOverDeleteDropTarget(dragViewIndex, isHoveringOverDelete);
+
+                if (DEBUG) Log.d(TAG, "leftBufferEdge: " + leftBufferEdge);
+                if (DEBUG) Log.d(TAG, "rightBufferEdge: " + rightBufferEdge);
+                if (DEBUG) Log.d(TAG, "mLastMotionX: " + mLastMotionX);
+                if (DEBUG) Log.d(TAG, "mLastMotionY: " + mLastMotionY);
+                if (DEBUG) Log.d(TAG, "mParentDownMotionX: " + mParentDownMotionX);
+                if (DEBUG) Log.d(TAG, "mParentDownMotionY: " + mParentDownMotionY);
+
+                float parentX = mParentDownMotionX;
+                int pageIndexToSnapTo = -1;
+                if (parentX < leftBufferEdge && dragViewIndex > 0) {
+                    pageIndexToSnapTo = dragViewIndex - 1;
+                } else if (parentX > rightBufferEdge && dragViewIndex < getChildCount() - 1) {
+                    pageIndexToSnapTo = dragViewIndex + 1;
+                }
+
+                final int pageUnderPointIndex = pageIndexToSnapTo;
+                if (pageUnderPointIndex > -1 && !isHoveringOverDelete) {
+                    mTempVisiblePagesRange[0] = 0;
+                    mTempVisiblePagesRange[1] = getPageCount() - 1;
+                    boundByReorderablePages(true, mTempVisiblePagesRange);
+                    if (mTempVisiblePagesRange[0] <= pageUnderPointIndex &&
+                            pageUnderPointIndex <= mTempVisiblePagesRange[1] &&
+                            pageUnderPointIndex != mSidePageHoverIndex && mScroller.isFinished()) {
+                        mSidePageHoverIndex = pageUnderPointIndex;
+                        mSidePageHoverRunnable = new Runnable() {
+                            @Override
+                            public void run() {
+                                // Update the down scroll position to account for the fact that the
+                                // current page is moved
+                                mDownScrollX = getChildOffset(pageUnderPointIndex)
+                                        - getRelativeChildOffset(pageUnderPointIndex);
+
+                                // Setup the scroll to the correct page before we swap the views
+                                snapToPage(pageUnderPointIndex);
+
+                                // For each of the pages between the paged view and the drag view,
+                                // animate them from the previous position to the new position in
+                                // the layout (as a result of the drag view moving in the layout)
+                                int shiftDelta = (dragViewIndex < pageUnderPointIndex) ? -1 : 1;
+                                int lowerIndex = (dragViewIndex < pageUnderPointIndex) ?
+                                        dragViewIndex + 1 : pageUnderPointIndex;
+                                int upperIndex = (dragViewIndex > pageUnderPointIndex) ?
+                                        dragViewIndex - 1 : pageUnderPointIndex;
+                                for (int i = lowerIndex; i <= upperIndex; ++i) {
+                                    View v = getChildAt(i);
+                                    // dragViewIndex < pageUnderPointIndex, so after we remove the
+                                    // drag view all subsequent views to pageUnderPointIndex will
+                                    // shift down.
+                                    int oldX = getViewportOffsetX() + getChildOffset(i);
+                                    int newX = getViewportOffsetX() + getChildOffset(i + shiftDelta);
+
+                                    // Animate the view translation from its old position to its new
+                                    // position
+                                    AnimatorSet anim = (AnimatorSet) v.getTag();
+                                    if (anim != null) {
+                                        anim.cancel();
+                                    }
+
+                                    v.setTranslationX(oldX - newX);
+                                    anim = new AnimatorSet();
+                                    anim.setDuration(REORDERING_REORDER_REPOSITION_DURATION);
+                                    anim.playTogether(
+                                            ObjectAnimator.ofFloat(v, "translationX", 0f));
+                                    anim.start();
+                                    v.setTag(anim);
+                                }
+
+                                removeView(mDragView);
+                                onRemoveView(mDragView);
+                                addView(mDragView, pageUnderPointIndex);
+                                onAddView(mDragView, pageUnderPointIndex);
+                                mSidePageHoverIndex = -1;
+                            }
+                        };
+                        postDelayed(mSidePageHoverRunnable, REORDERING_SIDE_PAGE_HOVER_TIMEOUT);
+                    }
+                } else {
+                    removeCallbacks(mSidePageHoverRunnable);
+                    mSidePageHoverIndex = -1;
+                }
+            } else {
+                determineScrollingStart(ev);
+            }
+            break;
+
+        case MotionEvent.ACTION_UP:
+            if (mTouchState == TOUCH_STATE_SCROLLING) {
+                final int activePointerId = mActivePointerId;
+                final int pointerIndex = ev.findPointerIndex(activePointerId);
+                final float x = ev.getX(pointerIndex);
+                final VelocityTracker velocityTracker = mVelocityTracker;
+                velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+                int velocityX = (int) velocityTracker.getXVelocity(activePointerId);
+                final int deltaX = (int) (x - mDownMotionX);
+                final int pageWidth = getScaledMeasuredWidth(getPageAt(mCurrentPage));
+                boolean isSignificantMove = Math.abs(deltaX) > pageWidth *
+                        SIGNIFICANT_MOVE_THRESHOLD;
+
+                mTotalMotionX += Math.abs(mLastMotionX + mLastMotionXRemainder - x);
+
+                boolean isFling = mTotalMotionX > MIN_LENGTH_FOR_FLING &&
+                        Math.abs(velocityX) > mFlingThresholdVelocity;
+
+                // In the case that the page is moved far to one direction and then is flung
+                // in the opposite direction, we use a threshold to determine whether we should
+                // just return to the starting page, or if we should skip one further.
+                boolean returnToOriginalPage = false;
+                if (Math.abs(deltaX) > pageWidth * RETURN_TO_ORIGINAL_PAGE_THRESHOLD &&
+                        Math.signum(velocityX) != Math.signum(deltaX) && isFling) {
+                    returnToOriginalPage = true;
+                }
+
+                int finalPage;
+                // We give flings precedence over large moves, which is why we short-circuit our
+                // test for a large move if a fling has been registered. That is, a large
+                // move to the left and fling to the right will register as a fling to the right.
+                if (((isSignificantMove && deltaX > 0 && !isFling) ||
+                        (isFling && velocityX > 0)) && mCurrentPage > 0) {
+                    finalPage = returnToOriginalPage ? mCurrentPage : mCurrentPage - 1;
+                    snapToPageWithVelocity(finalPage, velocityX);
+                } else if (((isSignificantMove && deltaX < 0 && !isFling) ||
+                        (isFling && velocityX < 0)) &&
+                        mCurrentPage < getChildCount() - 1) {
+                    finalPage = returnToOriginalPage ? mCurrentPage : mCurrentPage + 1;
+                    snapToPageWithVelocity(finalPage, velocityX);
+                } else {
+                    snapToDestination();
+                }
+            } else if (mTouchState == TOUCH_STATE_PREV_PAGE) {
+                // at this point we have not moved beyond the touch slop
+                // (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so
+                // we can just page
+                int nextPage = Math.max(0, mCurrentPage - 1);
+                if (nextPage != mCurrentPage) {
+                    snapToPage(nextPage);
+                } else {
+                    snapToDestination();
+                }
+            } else if (mTouchState == TOUCH_STATE_NEXT_PAGE) {
+                // at this point we have not moved beyond the touch slop
+                // (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so
+                // we can just page
+                int nextPage = Math.min(getChildCount() - 1, mCurrentPage + 1);
+                if (nextPage != mCurrentPage) {
+                    snapToPage(nextPage);
+                } else {
+                    snapToDestination();
+                }
+            } else if (mTouchState == TOUCH_STATE_REORDERING) {
+                // Update the last motion position
+                mLastMotionX = ev.getX();
+                mLastMotionY = ev.getY();
+
+                // Update the parent down so that our zoom animations take this new movement into
+                // account
+                float[] pt = mapPointFromViewToParent(this, mLastMotionX, mLastMotionY);
+                mParentDownMotionX = pt[0];
+                mParentDownMotionY = pt[1];
+                updateDragViewTranslationDuringDrag();
+                boolean handledFling = false;
+                if (!DISABLE_FLING_TO_DELETE) {
+                    // Check the velocity and see if we are flinging-to-delete
+                    PointF flingToDeleteVector = isFlingingToDelete();
+                    if (flingToDeleteVector != null) {
+                        onFlingToDelete(flingToDeleteVector);
+                        handledFling = true;
+                    }
+                }
+                if (!handledFling && isHoveringOverDeleteDropTarget((int) mParentDownMotionX,
+                        (int) mParentDownMotionY)) {
+                    onDropToDelete();
+                }
+            } else {
+                onUnhandledTap(ev);
+            }
+
+            // Remove the callback to wait for the side page hover timeout
+            removeCallbacks(mSidePageHoverRunnable);
+            // End any intermediate reordering states
+            resetTouchState();
+            break;
+
+        case MotionEvent.ACTION_CANCEL:
+            if (mTouchState == TOUCH_STATE_SCROLLING) {
+                snapToDestination();
+            }
+            resetTouchState();
+            break;
+
+        case MotionEvent.ACTION_POINTER_UP:
+            onSecondaryPointerUp(ev);
+            break;
+        }
+
+        return true;
+    }
+
+    //public abstract void onFlingToDelete(View v);
+    public abstract void onRemoveView(View v);
+    public abstract void onAddView(View v, int index);
+
+    private void resetTouchState() {
+        releaseVelocityTracker();
+        endReordering();
+        mTouchState = TOUCH_STATE_REST;
+        mActivePointerId = INVALID_POINTER;
+        mDownEventOnEdge = false;
+    }
+
+    protected void onUnhandledTap(MotionEvent ev) {}
+
+    @Override
+    public boolean onGenericMotionEvent(MotionEvent event) {
+        if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+            switch (event.getAction()) {
+                case MotionEvent.ACTION_SCROLL: {
+                    // Handle mouse (or ext. device) by shifting the page depending on the scroll
+                    final float vscroll;
+                    final float hscroll;
+                    if ((event.getMetaState() & KeyEvent.META_SHIFT_ON) != 0) {
+                        vscroll = 0;
+                        hscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+                    } else {
+                        vscroll = -event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+                        hscroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
+                    }
+                    if (hscroll != 0 || vscroll != 0) {
+                        if (hscroll > 0 || vscroll > 0) {
+                            scrollRight();
+                        } else {
+                            scrollLeft();
+                        }
+                        return true;
+                    }
+                }
+            }
+        }
+        return super.onGenericMotionEvent(event);
+    }
+
+    private void acquireVelocityTrackerAndAddMovement(MotionEvent ev) {
+        if (mVelocityTracker == null) {
+            mVelocityTracker = VelocityTracker.obtain();
+        }
+        mVelocityTracker.addMovement(ev);
+    }
+
+    private void releaseVelocityTracker() {
+        if (mVelocityTracker != null) {
+            mVelocityTracker.recycle();
+            mVelocityTracker = null;
+        }
+    }
+
+    private void onSecondaryPointerUp(MotionEvent ev) {
+        final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
+                MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+        final int pointerId = ev.getPointerId(pointerIndex);
+        if (pointerId == mActivePointerId) {
+            // This was our active pointer going up. Choose a new
+            // active pointer and adjust accordingly.
+            // TODO: Make this decision more intelligent.
+            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
+            mLastMotionX = mDownMotionX = ev.getX(newPointerIndex);
+            mLastMotionY = ev.getY(newPointerIndex);
+            mLastMotionXRemainder = 0;
+            mActivePointerId = ev.getPointerId(newPointerIndex);
+            if (mVelocityTracker != null) {
+                mVelocityTracker.clear();
+            }
+        }
+    }
+
+    @Override
+    public void requestChildFocus(View child, View focused) {
+        super.requestChildFocus(child, focused);
+        int page = indexToPage(indexOfChild(child));
+        if (page >= 0 && page != getCurrentPage() && !isInTouchMode()) {
+            snapToPage(page);
+        }
+    }
+
+    protected int getChildIndexForRelativeOffset(int relativeOffset) {
+        final int childCount = getChildCount();
+        int left;
+        int right;
+        for (int i = 0; i < childCount; ++i) {
+            left = getRelativeChildOffset(i);
+            right = (left + getScaledMeasuredWidth(getPageAt(i)));
+            if (left <= relativeOffset && relativeOffset <= right) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    protected int getChildWidth(int index) {
+        // This functions are called enough times that it actually makes a difference in the
+        // profiler -- so just inline the max() here
+        final int measuredWidth = getPageAt(index).getMeasuredWidth();
+        final int minWidth = mMinimumWidth;
+        return (minWidth > measuredWidth) ? minWidth : measuredWidth;
+    }
+
+    int getPageNearestToPoint(float x) {
+        int index = 0;
+        for (int i = 0; i < getChildCount(); ++i) {
+            if (x < getChildAt(i).getRight() - getScrollX()) {
+                return index;
+            } else {
+                index++;
+            }
+        }
+        return Math.min(index, getChildCount() - 1);
+    }
+
+    int getPageNearestToCenterOfScreen() {
+        int minDistanceFromScreenCenter = Integer.MAX_VALUE;
+        int minDistanceFromScreenCenterIndex = -1;
+        int screenCenter = getViewportOffsetX() + getScrollX() + (getViewportWidth() / 2);
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; ++i) {
+            View layout = (View) getPageAt(i);
+            int childWidth = getScaledMeasuredWidth(layout);
+            int halfChildWidth = (childWidth / 2);
+            int childCenter = getViewportOffsetX() + getChildOffset(i) + halfChildWidth;
+            int distanceFromScreenCenter = Math.abs(childCenter - screenCenter);
+            if (distanceFromScreenCenter < minDistanceFromScreenCenter) {
+                minDistanceFromScreenCenter = distanceFromScreenCenter;
+                minDistanceFromScreenCenterIndex = i;
+            }
+        }
+        return minDistanceFromScreenCenterIndex;
+    }
+
+    protected void snapToDestination() {
+        snapToPage(getPageNearestToCenterOfScreen(), PAGE_SNAP_ANIMATION_DURATION);
+    }
+
+    private static class ScrollInterpolator implements Interpolator {
+        public ScrollInterpolator() {
+        }
+
+        public float getInterpolation(float t) {
+            t -= 1.0f;
+            return t*t*t*t*t + 1;
+        }
+    }
+
+    // We want the duration of the page snap animation to be influenced by the distance that
+    // the screen has to travel, however, we don't want this duration to be effected in a
+    // purely linear fashion. Instead, we use this method to moderate the effect that the distance
+    // of travel has on the overall snap duration.
+    float distanceInfluenceForSnapDuration(float f) {
+        f -= 0.5f; // center the values about 0.
+        f *= 0.3f * Math.PI / 2.0f;
+        return (float) Math.sin(f);
+    }
+
+    protected void snapToPageWithVelocity(int whichPage, int velocity) {
+        whichPage = Math.max(0, Math.min(whichPage, getChildCount() - 1));
+        int halfScreenSize = getViewportWidth() / 2;
+
+        if (DEBUG) Log.d(TAG, "snapToPage.getChildOffset(): " + getChildOffset(whichPage));
+        if (DEBUG) Log.d(TAG, "snapToPageWithVelocity.getRelativeChildOffset(): "
+                + getViewportWidth() + ", " + getChildWidth(whichPage));
+        final int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
+        int delta = newX - mUnboundedScrollX;
+        int duration = 0;
+
+        if (Math.abs(velocity) < mMinFlingVelocity) {
+            // If the velocity is low enough, then treat this more as an automatic page advance
+            // as opposed to an apparent physical response to flinging
+            snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
+            return;
+        }
+
+        // Here we compute a "distance" that will be used in the computation of the overall
+        // snap duration. This is a function of the actual distance that needs to be traveled;
+        // we keep this value close to half screen size in order to reduce the variance in snap
+        // duration as a function of the distance the page needs to travel.
+        float distanceRatio = Math.min(1f, 1.0f * Math.abs(delta) / (2 * halfScreenSize));
+        float distance = halfScreenSize + halfScreenSize *
+                distanceInfluenceForSnapDuration(distanceRatio);
+
+        velocity = Math.abs(velocity);
+        velocity = Math.max(mMinSnapVelocity, velocity);
+
+        // we want the page's snap velocity to approximately match the velocity at which the
+        // user flings, so we scale the duration by a value near to the derivative of the scroll
+        // interpolator at zero, ie. 5. We use 4 to make it a little slower.
+        duration = 4 * Math.round(1000 * Math.abs(distance / velocity));
+
+        snapToPage(whichPage, delta, duration);
+    }
+
+    protected void snapToPage(int whichPage) {
+        snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
+    }
+    protected void snapToPageImmediately(int whichPage) {
+        snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION, true);
+    }
+
+    protected void snapToPage(int whichPage, int duration) {
+        snapToPage(whichPage, duration, false);
+    }
+    protected void snapToPage(int whichPage, int duration, boolean immediate) {
+        whichPage = Math.max(0, Math.min(whichPage, getPageCount() - 1));
+
+        if (DEBUG) Log.d(TAG, "snapToPage.getChildOffset(): " + getChildOffset(whichPage));
+        if (DEBUG) Log.d(TAG, "snapToPage.getRelativeChildOffset(): " + getViewportWidth() + ", "
+                + getChildWidth(whichPage));
+        int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
+        final int sX = mUnboundedScrollX;
+        final int delta = newX - sX;
+        snapToPage(whichPage, delta, duration, immediate);
+    }
+
+    protected void snapToPage(int whichPage, int delta, int duration) {
+        snapToPage(whichPage, delta, duration, false);
+    }
+    protected void snapToPage(int whichPage, int delta, int duration, boolean immediate) {
+        mNextPage = whichPage;
+        notifyPageSwitching(whichPage);
+        View focusedChild = getFocusedChild();
+        if (focusedChild != null && whichPage != mCurrentPage &&
+                focusedChild == getPageAt(mCurrentPage)) {
+            focusedChild.clearFocus();
+        }
+
+        pageBeginMoving();
+        awakenScrollBars(duration);
+        if (immediate) {
+            duration = 0;
+        } else if (duration == 0) {
+            duration = Math.abs(delta);
+        }
+
+        if (!mScroller.isFinished()) mScroller.abortAnimation();
+        mScroller.startScroll(mUnboundedScrollX, 0, delta, 0, duration);
+
+        notifyPageSwitched();
+
+        // Trigger a compute() to finish switching pages if necessary
+        if (immediate) {
+            computeScroll();
+        }
+
+        mForceScreenScrolled = true;
+        invalidate();
+    }
+
+    public void scrollLeft() {
+        if (mScroller.isFinished()) {
+            if (mCurrentPage > 0) snapToPage(mCurrentPage - 1);
+        } else {
+            if (mNextPage > 0) snapToPage(mNextPage - 1);
+        }
+    }
+
+    public void scrollRight() {
+        if (mScroller.isFinished()) {
+            if (mCurrentPage < getChildCount() -1) snapToPage(mCurrentPage + 1);
+        } else {
+            if (mNextPage < getChildCount() -1) snapToPage(mNextPage + 1);
+        }
+    }
+
+    public int getPageForView(View v) {
+        int result = -1;
+        if (v != null) {
+            ViewParent vp = v.getParent();
+            int count = getChildCount();
+            for (int i = 0; i < count; i++) {
+                if (vp == getPageAt(i)) {
+                    return i;
+                }
+            }
+        }
+        return result;
+    }
+
+    public static class SavedState extends BaseSavedState {
+        int currentPage = -1;
+
+        SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        private SavedState(Parcel in) {
+            super(in);
+            currentPage = in.readInt();
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            super.writeToParcel(out, flags);
+            out.writeInt(currentPage);
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+
+    protected View getScrollingIndicator() {
+        return null;
+    }
+
+    protected boolean isScrollingIndicatorEnabled() {
+        return false;
+    }
+
+    Runnable hideScrollingIndicatorRunnable = new Runnable() {
+        @Override
+        public void run() {
+            hideScrollingIndicator(false);
+        }
+    };
+
+    protected void flashScrollingIndicator(boolean animated) {
+        removeCallbacks(hideScrollingIndicatorRunnable);
+        showScrollingIndicator(!animated);
+        postDelayed(hideScrollingIndicatorRunnable, sScrollIndicatorFlashDuration);
+    }
+
+    protected void showScrollingIndicator(boolean immediately) {
+        mShouldShowScrollIndicator = true;
+        mShouldShowScrollIndicatorImmediately = true;
+        if (getChildCount() <= 1) return;
+        if (!isScrollingIndicatorEnabled()) return;
+
+        mShouldShowScrollIndicator = false;
+        getScrollingIndicator();
+        if (mScrollIndicator != null) {
+            // Fade the indicator in
+            updateScrollingIndicatorPosition();
+            mScrollIndicator.setVisibility(View.VISIBLE);
+            cancelScrollingIndicatorAnimations();
+            if (immediately) {
+                mScrollIndicator.setAlpha(1f);
+            } else {
+                mScrollIndicatorAnimator = ObjectAnimator.ofFloat(mScrollIndicator, "alpha", 1f);
+                mScrollIndicatorAnimator.setDuration(sScrollIndicatorFadeInDuration);
+                mScrollIndicatorAnimator.start();
+            }
+        }
+    }
+
+    protected void cancelScrollingIndicatorAnimations() {
+        if (mScrollIndicatorAnimator != null) {
+            mScrollIndicatorAnimator.cancel();
+        }
+    }
+
+    protected void hideScrollingIndicator(boolean immediately) {
+        if (getChildCount() <= 1) return;
+        if (!isScrollingIndicatorEnabled()) return;
+
+        getScrollingIndicator();
+        if (mScrollIndicator != null) {
+            // Fade the indicator out
+            updateScrollingIndicatorPosition();
+            cancelScrollingIndicatorAnimations();
+            if (immediately) {
+                mScrollIndicator.setVisibility(View.INVISIBLE);
+                mScrollIndicator.setAlpha(0f);
+            } else {
+                mScrollIndicatorAnimator = ObjectAnimator.ofFloat(mScrollIndicator, "alpha", 0f);
+                mScrollIndicatorAnimator.setDuration(sScrollIndicatorFadeOutDuration);
+                mScrollIndicatorAnimator.addListener(new AnimatorListenerAdapter() {
+                    private boolean cancelled = false;
+                    @Override
+                    public void onAnimationCancel(android.animation.Animator animation) {
+                        cancelled = true;
+                    }
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        if (!cancelled) {
+                            mScrollIndicator.setVisibility(View.INVISIBLE);
+                        }
+                    }
+                });
+                mScrollIndicatorAnimator.start();
+            }
+        }
+    }
+
+    /**
+     * To be overridden by subclasses to determine whether the scroll indicator should stretch to
+     * fill its space on the track or not.
+     */
+    protected boolean hasElasticScrollIndicator() {
+        return true;
+    }
+
+    private void updateScrollingIndicator() {
+        if (getChildCount() <= 1) return;
+        if (!isScrollingIndicatorEnabled()) return;
+
+        getScrollingIndicator();
+        if (mScrollIndicator != null) {
+            updateScrollingIndicatorPosition();
+        }
+        if (mShouldShowScrollIndicator) {
+            showScrollingIndicator(mShouldShowScrollIndicatorImmediately);
+        }
+    }
+
+    private void updateScrollingIndicatorPosition() {
+        if (!isScrollingIndicatorEnabled()) return;
+        if (mScrollIndicator == null) return;
+        int numPages = getChildCount();
+        int pageWidth = getViewportWidth();
+        int lastChildIndex = Math.max(0, getChildCount() - 1);
+        int maxScrollX = getChildOffset(lastChildIndex) - getRelativeChildOffset(lastChildIndex);
+        int trackWidth = pageWidth - mScrollIndicatorPaddingLeft - mScrollIndicatorPaddingRight;
+        int indicatorWidth = mScrollIndicator.getMeasuredWidth() -
+                mScrollIndicator.getPaddingLeft() - mScrollIndicator.getPaddingRight();
+
+        float offset = Math.max(0f, Math.min(1f, (float) getScrollX() / maxScrollX));
+        int indicatorSpace = trackWidth / numPages;
+        int indicatorPos = (int) (offset * (trackWidth - indicatorSpace)) + mScrollIndicatorPaddingLeft;
+        if (hasElasticScrollIndicator()) {
+            if (mScrollIndicator.getMeasuredWidth() != indicatorSpace) {
+                mScrollIndicator.getLayoutParams().width = indicatorSpace;
+                mScrollIndicator.requestLayout();
+            }
+        } else {
+            int indicatorCenterOffset = indicatorSpace / 2 - indicatorWidth / 2;
+            indicatorPos += indicatorCenterOffset;
+        }
+        mScrollIndicator.setTranslationX(indicatorPos);
+    }
+
+    // Animate the drag view back to the original position
+    void animateDragViewToOriginalPosition() {
+        if (mDragView != null) {
+            AnimatorSet anim = new AnimatorSet();
+            anim.setDuration(REORDERING_DROP_REPOSITION_DURATION);
+            anim.playTogether(
+                    ObjectAnimator.ofFloat(mDragView, "translationX", 0f),
+                    ObjectAnimator.ofFloat(mDragView, "translationY", 0f));
+            anim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    onPostReorderingAnimationCompleted();
+                }
+            });
+            anim.start();
+        }
+    }
+
+    // "Zooms out" the PagedView to reveal more side pages
+    protected boolean zoomOut() {
+        if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) {
+            mZoomInOutAnim.cancel();
+        }
+
+        if (!(getScaleX() < 1f || getScaleY() < 1f)) {
+            mZoomInOutAnim = new AnimatorSet();
+            mZoomInOutAnim.setDuration(REORDERING_ZOOM_IN_OUT_DURATION);
+            mZoomInOutAnim.playTogether(
+                    ObjectAnimator.ofFloat(this, "scaleX", mMinScale),
+                    ObjectAnimator.ofFloat(this, "scaleY", mMinScale));
+            mZoomInOutAnim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationStart(Animator animation) {
+                    // Show the delete drop target
+                    if (mDeleteDropTarget != null) {
+                        mDeleteDropTarget.setVisibility(View.VISIBLE);
+                        mDeleteDropTarget.animate().alpha(1f)
+                            .setDuration(REORDERING_DELETE_DROP_TARGET_FADE_DURATION)
+                            .setListener(new AnimatorListenerAdapter() {
+                                @Override
+                                public void onAnimationStart(Animator animation) {
+                                    mDeleteDropTarget.setAlpha(0f);
+                                }
+                            });
+                    }
+                }
+            });
+            mZoomInOutAnim.start();
+            return true;
+        }
+        return false;
+    }
+
+    protected void onStartReordering() {
+        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+            announceForAccessibility(mContext.getString(
+                    R.string.keyguard_accessibility_widget_reorder_start));
+        }
+
+        // Set the touch state to reordering (allows snapping to pages, dragging a child, etc.)
+        mTouchState = TOUCH_STATE_REORDERING;
+        mIsReordering = true;
+
+        // Mark all the non-widget pages as invisible
+        getVisiblePages(mTempVisiblePagesRange);
+        boundByReorderablePages(true, mTempVisiblePagesRange);
+        for (int i = 0; i < getPageCount(); ++i) {
+            if (i < mTempVisiblePagesRange[0] || i > mTempVisiblePagesRange[1]) {
+                getPageAt(i).setAlpha(0f);
+            }
+        }
+
+        // We must invalidate to trigger a redraw to update the layers such that the drag view
+        // is always drawn on top
+        invalidate();
+    }
+
+    private void onPostReorderingAnimationCompleted() {
+        // Trigger the callback when reordering has settled
+        --mPostReorderingPreZoomInRemainingAnimationCount;
+        if (mPostReorderingPreZoomInRunnable != null &&
+                mPostReorderingPreZoomInRemainingAnimationCount == 0) {
+            mPostReorderingPreZoomInRunnable.run();
+            mPostReorderingPreZoomInRunnable = null;
+        }
+    }
+
+    protected void onEndReordering() {
+        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+            announceForAccessibility(mContext.getString(
+                    R.string.keyguard_accessibility_widget_reorder_end));
+        }
+        mIsReordering = false;
+
+        // Mark all the non-widget pages as visible again
+        getVisiblePages(mTempVisiblePagesRange);
+        boundByReorderablePages(true, mTempVisiblePagesRange);
+        for (int i = 0; i < getPageCount(); ++i) {
+            if (i < mTempVisiblePagesRange[0] || i > mTempVisiblePagesRange[1]) {
+                getPageAt(i).setAlpha(1f);
+            }
+        }
+    }
+
+    public boolean startReordering() {
+        int dragViewIndex = getPageNearestToCenterOfScreen();
+        mTempVisiblePagesRange[0] = 0;
+        mTempVisiblePagesRange[1] = getPageCount() - 1;
+        boundByReorderablePages(true, mTempVisiblePagesRange);
+        mReorderingStarted = true;
+
+        // Check if we are within the reordering range
+        if (mTempVisiblePagesRange[0] <= dragViewIndex &&
+                dragViewIndex <= mTempVisiblePagesRange[1]) {
+            if (zoomOut()) {
+                // Find the drag view under the pointer
+                mDragView = getChildAt(dragViewIndex);
+
+                onStartReordering();
+            }
+            return true;
+        }
+        return false;
+    }
+
+    boolean isReordering(boolean testTouchState) {
+        boolean state = mIsReordering;
+        if (testTouchState) {
+            state &= (mTouchState == TOUCH_STATE_REORDERING);
+        }
+        return state;
+    }
+    void endReordering() {
+        // For simplicity, we call endReordering sometimes even if reordering was never started.
+        // In that case, we don't want to do anything.
+        if (!mReorderingStarted) return;
+        mReorderingStarted = false;
+
+        // If we haven't flung-to-delete the current child, then we just animate the drag view
+        // back into position
+        final Runnable onCompleteRunnable = new Runnable() {
+            @Override
+            public void run() {
+                onEndReordering();
+            }
+        };
+        if (!mDeferringForDelete) {
+            mPostReorderingPreZoomInRunnable = new Runnable() {
+                public void run() {
+                    zoomIn(onCompleteRunnable);
+                };
+            };
+
+            mPostReorderingPreZoomInRemainingAnimationCount =
+                    NUM_ANIMATIONS_RUNNING_BEFORE_ZOOM_OUT;
+            // Snap to the current page
+            snapToPage(indexOfChild(mDragView), 0);
+            // Animate the drag view back to the front position
+            animateDragViewToOriginalPosition();
+        } else {
+            // Handled in post-delete-animation-callbacks
+        }
+    }
+
+    // "Zooms in" the PagedView to highlight the current page
+    protected boolean zoomIn(final Runnable onCompleteRunnable) {
+        if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) {
+            mZoomInOutAnim.cancel();
+        }
+        if (getScaleX() < 1f || getScaleY() < 1f) {
+            mZoomInOutAnim = new AnimatorSet();
+            mZoomInOutAnim.setDuration(REORDERING_ZOOM_IN_OUT_DURATION);
+            mZoomInOutAnim.playTogether(
+                    ObjectAnimator.ofFloat(this, "scaleX", 1f),
+                    ObjectAnimator.ofFloat(this, "scaleY", 1f));
+            mZoomInOutAnim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationStart(Animator animation) {
+                    // Hide the delete drop target
+                    if (mDeleteDropTarget != null) {
+                        mDeleteDropTarget.animate().alpha(0f)
+                            .setDuration(REORDERING_DELETE_DROP_TARGET_FADE_DURATION)
+                            .setListener(new AnimatorListenerAdapter() {
+                                @Override
+                                public void onAnimationEnd(Animator animation) {
+                                    mDeleteDropTarget.setVisibility(View.GONE);
+                                }
+                            });
+                    }
+                }
+                @Override
+                public void onAnimationCancel(Animator animation) {
+                    mDragView = null;
+                }
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    mDragView = null;
+                    if (onCompleteRunnable != null) {
+                        onCompleteRunnable.run();
+                    }
+                }
+            });
+            mZoomInOutAnim.start();
+            return true;
+        } else {
+            if (onCompleteRunnable != null) {
+                onCompleteRunnable.run();
+            }
+        }
+        return false;
+    }
+
+    /*
+     * Flinging to delete - IN PROGRESS
+     */
+    private PointF isFlingingToDelete() {
+        ViewConfiguration config = ViewConfiguration.get(getContext());
+        mVelocityTracker.computeCurrentVelocity(1000, config.getScaledMaximumFlingVelocity());
+
+        if (mVelocityTracker.getYVelocity() < mFlingToDeleteThresholdVelocity) {
+            // Do a quick dot product test to ensure that we are flinging upwards
+            PointF vel = new PointF(mVelocityTracker.getXVelocity(),
+                    mVelocityTracker.getYVelocity());
+            PointF upVec = new PointF(0f, -1f);
+            float theta = (float) Math.acos(((vel.x * upVec.x) + (vel.y * upVec.y)) /
+                    (vel.length() * upVec.length()));
+            if (theta <= Math.toRadians(FLING_TO_DELETE_MAX_FLING_DEGREES)) {
+                return vel;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Creates an animation from the current drag view along its current velocity vector.
+     * For this animation, the alpha runs for a fixed duration and we update the position
+     * progressively.
+     */
+    private static class FlingAlongVectorAnimatorUpdateListener implements AnimatorUpdateListener {
+        private View mDragView;
+        private PointF mVelocity;
+        private Rect mFrom;
+        private long mPrevTime;
+        private float mFriction;
+
+        private final TimeInterpolator mAlphaInterpolator = new DecelerateInterpolator(0.75f);
+
+        public FlingAlongVectorAnimatorUpdateListener(View dragView, PointF vel, Rect from,
+                long startTime, float friction) {
+            mDragView = dragView;
+            mVelocity = vel;
+            mFrom = from;
+            mPrevTime = startTime;
+            mFriction = 1f - (mDragView.getResources().getDisplayMetrics().density * friction);
+        }
+
+        @Override
+        public void onAnimationUpdate(ValueAnimator animation) {
+            float t = ((Float) animation.getAnimatedValue()).floatValue();
+            long curTime = AnimationUtils.currentAnimationTimeMillis();
+
+            mFrom.left += (mVelocity.x * (curTime - mPrevTime) / 1000f);
+            mFrom.top += (mVelocity.y * (curTime - mPrevTime) / 1000f);
+
+            mDragView.setTranslationX(mFrom.left);
+            mDragView.setTranslationY(mFrom.top);
+            mDragView.setAlpha(1f - mAlphaInterpolator.getInterpolation(t));
+
+            mVelocity.x *= mFriction;
+            mVelocity.y *= mFriction;
+            mPrevTime = curTime;
+        }
+    };
+
+    private Runnable createPostDeleteAnimationRunnable(final View dragView) {
+        return new Runnable() {
+            @Override
+            public void run() {
+                int dragViewIndex = indexOfChild(dragView);
+
+                // For each of the pages around the drag view, animate them from the previous
+                // position to the new position in the layout (as a result of the drag view moving
+                // in the layout)
+                // NOTE: We can make an assumption here because we have side-bound pages that we
+                //       will always have pages to animate in from the left
+                getVisiblePages(mTempVisiblePagesRange);
+                boundByReorderablePages(true, mTempVisiblePagesRange);
+                boolean isLastWidgetPage = (mTempVisiblePagesRange[0] == mTempVisiblePagesRange[1]);
+                boolean slideFromLeft = (isLastWidgetPage ||
+                        dragViewIndex > mTempVisiblePagesRange[0]);
+
+                // Setup the scroll to the correct page before we swap the views
+                if (slideFromLeft) {
+                    snapToPageImmediately(dragViewIndex - 1);
+                }
+
+                int firstIndex = (isLastWidgetPage ? 0 : mTempVisiblePagesRange[0]);
+                int lastIndex = Math.min(mTempVisiblePagesRange[1], getPageCount() - 1);
+                int lowerIndex = (slideFromLeft ? firstIndex : dragViewIndex + 1 );
+                int upperIndex = (slideFromLeft ? dragViewIndex - 1 : lastIndex);
+                ArrayList<Animator> animations = new ArrayList<Animator>();
+                for (int i = lowerIndex; i <= upperIndex; ++i) {
+                    View v = getChildAt(i);
+                    // dragViewIndex < pageUnderPointIndex, so after we remove the
+                    // drag view all subsequent views to pageUnderPointIndex will
+                    // shift down.
+                    int oldX = 0;
+                    int newX = 0;
+                    if (slideFromLeft) {
+                        if (i == 0) {
+                            // Simulate the page being offscreen with the page spacing
+                            oldX = getViewportOffsetX() + getChildOffset(i) - getChildWidth(i)
+                                    - mPageSpacing;
+                        } else {
+                            oldX = getViewportOffsetX() + getChildOffset(i - 1);
+                        }
+                        newX = getViewportOffsetX() + getChildOffset(i);
+                    } else {
+                        oldX = getChildOffset(i) - getChildOffset(i - 1);
+                        newX = 0;
+                    }
+
+                    // Animate the view translation from its old position to its new
+                    // position
+                    AnimatorSet anim = (AnimatorSet) v.getTag();
+                    if (anim != null) {
+                        anim.cancel();
+                    }
+
+                    // Note: Hacky, but we want to skip any optimizations to not draw completely
+                    // hidden views
+                    v.setAlpha(Math.max(v.getAlpha(), 0.01f));
+                    v.setTranslationX(oldX - newX);
+                    anim = new AnimatorSet();
+                    anim.playTogether(
+                            ObjectAnimator.ofFloat(v, "translationX", 0f),
+                            ObjectAnimator.ofFloat(v, "alpha", 1f));
+                    animations.add(anim);
+                    v.setTag(anim);
+                }
+
+                AnimatorSet slideAnimations = new AnimatorSet();
+                slideAnimations.playTogether(animations);
+                slideAnimations.setDuration(DELETE_SLIDE_IN_SIDE_PAGE_DURATION);
+                slideAnimations.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        final Runnable onCompleteRunnable = new Runnable() {
+                            @Override
+                            public void run() {
+                                mDeferringForDelete = false;
+                                onEndReordering();
+                            }
+                        };
+                        zoomIn(onCompleteRunnable);
+                    }
+                });
+                slideAnimations.start();
+
+                removeView(dragView);
+                onRemoveView(dragView);
+            }
+        };
+    }
+
+    public void onFlingToDelete(PointF vel) {
+        final long startTime = AnimationUtils.currentAnimationTimeMillis();
+
+        // NOTE: Because it takes time for the first frame of animation to actually be
+        // called and we expect the animation to be a continuation of the fling, we have
+        // to account for the time that has elapsed since the fling finished.  And since
+        // we don't have a startDelay, we will always get call to update when we call
+        // start() (which we want to ignore).
+        final TimeInterpolator tInterpolator = new TimeInterpolator() {
+            private int mCount = -1;
+            private long mStartTime;
+            private float mOffset;
+            /* Anonymous inner class ctor */ {
+                mStartTime = startTime;
+            }
+
+            @Override
+            public float getInterpolation(float t) {
+                if (mCount < 0) {
+                    mCount++;
+                } else if (mCount == 0) {
+                    mOffset = Math.min(0.5f, (float) (AnimationUtils.currentAnimationTimeMillis() -
+                            mStartTime) / FLING_TO_DELETE_FADE_OUT_DURATION);
+                    mCount++;
+                }
+                return Math.min(1f, mOffset + t);
+            }
+        };
+
+        final Rect from = new Rect();
+        final View dragView = mDragView;
+        from.left = (int) dragView.getTranslationX();
+        from.top = (int) dragView.getTranslationY();
+        AnimatorUpdateListener updateCb = new FlingAlongVectorAnimatorUpdateListener(dragView, vel,
+                from, startTime, FLING_TO_DELETE_FRICTION);
+
+        final Runnable onAnimationEndRunnable = createPostDeleteAnimationRunnable(dragView);
+
+        // Create and start the animation
+        ValueAnimator mDropAnim = new ValueAnimator();
+        mDropAnim.setInterpolator(tInterpolator);
+        mDropAnim.setDuration(FLING_TO_DELETE_FADE_OUT_DURATION);
+        mDropAnim.setFloatValues(0f, 1f);
+        mDropAnim.addUpdateListener(updateCb);
+        mDropAnim.addListener(new AnimatorListenerAdapter() {
+            public void onAnimationEnd(Animator animation) {
+                onAnimationEndRunnable.run();
+            }
+        });
+        mDropAnim.start();
+        mDeferringForDelete = true;
+    }
+
+    /* Drag to delete */
+    private boolean isHoveringOverDeleteDropTarget(int x, int y) {
+        if (mDeleteDropTarget != null) {
+            mAltTmpRect.set(0, 0, 0, 0);
+            View parent = (View) mDeleteDropTarget.getParent();
+            if (parent != null) {
+                parent.getGlobalVisibleRect(mAltTmpRect);
+            }
+            mDeleteDropTarget.getGlobalVisibleRect(mTmpRect);
+            mTmpRect.offset(-mAltTmpRect.left, -mAltTmpRect.top);
+            return mTmpRect.contains(x, y);
+        }
+        return false;
+    }
+
+    protected void setPageHoveringOverDeleteDropTarget(int viewIndex, boolean isHovering) {}
+
+    private void onDropToDelete() {
+        final View dragView = mDragView;
+
+        final float toScale = 0f;
+        final float toAlpha = 0f;
+
+        // Create and start the complex animation
+        ArrayList<Animator> animations = new ArrayList<Animator>();
+        AnimatorSet motionAnim = new AnimatorSet();
+        motionAnim.setInterpolator(new DecelerateInterpolator(2));
+        motionAnim.playTogether(
+                ObjectAnimator.ofFloat(dragView, "scaleX", toScale),
+                ObjectAnimator.ofFloat(dragView, "scaleY", toScale));
+        animations.add(motionAnim);
+
+        AnimatorSet alphaAnim = new AnimatorSet();
+        alphaAnim.setInterpolator(new LinearInterpolator());
+        alphaAnim.playTogether(
+                ObjectAnimator.ofFloat(dragView, "alpha", toAlpha));
+        animations.add(alphaAnim);
+
+        final Runnable onAnimationEndRunnable = createPostDeleteAnimationRunnable(dragView);
+
+        AnimatorSet anim = new AnimatorSet();
+        anim.playTogether(animations);
+        anim.setDuration(DRAG_TO_DELETE_FADE_OUT_DURATION);
+        anim.addListener(new AnimatorListenerAdapter() {
+            public void onAnimationEnd(Animator animation) {
+                onAnimationEndRunnable.run();
+            }
+        });
+        anim.start();
+
+        mDeferringForDelete = true;
+    }
+
+    /* Accessibility */
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setScrollable(getPageCount() > 1);
+        if (getCurrentPage() < getPageCount() - 1) {
+            info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+        }
+        if (getCurrentPage() > 0) {
+            info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+        }
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setScrollable(true);
+        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+            event.setFromIndex(mCurrentPage);
+            event.setToIndex(mCurrentPage);
+            event.setItemCount(getChildCount());
+        }
+    }
+
+    @Override
+    public boolean performAccessibilityAction(int action, Bundle arguments) {
+        if (super.performAccessibilityAction(action, arguments)) {
+            return true;
+        }
+        switch (action) {
+            case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+                if (getCurrentPage() < getPageCount() - 1) {
+                    scrollRight();
+                    return true;
+                }
+            } break;
+            case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+                if (getCurrentPage() > 0) {
+                    scrollLeft();
+                    return true;
+                }
+            } break;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onHoverEvent(android.view.MotionEvent event) {
+        return true;
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/SecurityMessageDisplay.java b/policy/src/com/android/internal/policy/impl/keyguard/SecurityMessageDisplay.java
new file mode 100644
index 0000000..7760279
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/SecurityMessageDisplay.java
@@ -0,0 +1,31 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+public interface SecurityMessageDisplay {
+    public void setMessage(CharSequence msg, boolean important);
+
+    public void setMessage(int resId, boolean important);
+
+    public void setMessage(int resId, boolean important, Object... formatArgs);
+
+    public void setTimeout(int timeout_ms);
+
+    public void showBouncer(int animationDuration);
+
+    public void hideBouncer(int animationDuration);
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java b/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
new file mode 100644
index 0000000..073225f
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
@@ -0,0 +1,1244 @@
+/*
+ * 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.internal.policy.impl.keyguard;
+
+import com.android.internal.R;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.FloatProperty;
+import android.util.Log;
+import android.util.Property;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
+import android.view.animation.Interpolator;
+import android.widget.Scroller;
+
+/**
+ * This layout handles interaction with the sliding security challenge views
+ * that overlay/resize other keyguard contents.
+ */
+public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout {
+    private static final String TAG = "SlidingChallengeLayout";
+    private static final boolean DEBUG = false;
+
+    // The drag handle is measured in dp above & below the top edge of the
+    // challenge view; these parameters change based on whether the challenge 
+    // is open or closed.
+    private static final int DRAG_HANDLE_CLOSED_ABOVE = 8; // dp
+    private static final int DRAG_HANDLE_CLOSED_BELOW = 0; // dp
+    private static final int DRAG_HANDLE_OPEN_ABOVE = 8; // dp
+    private static final int DRAG_HANDLE_OPEN_BELOW = 0; // dp
+
+    private static final int HANDLE_ANIMATE_DURATION = 250; // ms
+
+    // Drawn to show the drag handle in closed state; crossfades to the challenge view
+    // when challenge is fully visible
+    private boolean mEdgeCaptured;
+
+    private DisplayMetrics mDisplayMetrics;
+
+    // Initialized during measurement from child layoutparams
+    private View mExpandChallengeView;
+    private KeyguardSecurityContainer mChallengeView;
+    private View mScrimView;
+    private View mWidgetsView;
+
+    // Range: 0 (fully hidden) to 1 (fully visible)
+    private float mChallengeOffset = 1.f;
+    private boolean mChallengeShowing = true;
+    private boolean mChallengeShowingTargetState = true;
+    private boolean mWasChallengeShowing = true;
+    private boolean mIsBouncing = false;
+
+    private final Scroller mScroller;
+    private ObjectAnimator mFader;
+    private int mScrollState;
+    private OnChallengeScrolledListener mScrollListener;
+    private OnBouncerStateChangedListener mBouncerListener;
+
+    public static final int SCROLL_STATE_IDLE = 0;
+    public static final int SCROLL_STATE_DRAGGING = 1;
+    public static final int SCROLL_STATE_SETTLING = 2;
+    public static final int SCROLL_STATE_FADING = 3;
+
+    private static final int CHALLENGE_FADE_OUT_DURATION = 100;
+    private static final int CHALLENGE_FADE_IN_DURATION = 160;
+
+    private static final int MAX_SETTLE_DURATION = 600; // ms
+
+    // ID of the pointer in charge of a current drag
+    private int mActivePointerId = INVALID_POINTER;
+    private static final int INVALID_POINTER = -1;
+
+    // True if the user is currently dragging the slider
+    private boolean mDragging;
+    // True if the user may not drag until a new gesture begins
+    private boolean mBlockDrag;
+
+    private VelocityTracker mVelocityTracker;
+    private int mMinVelocity;
+    private int mMaxVelocity;
+    private float mGestureStartX, mGestureStartY; // where did you first touch the screen?
+    private int mGestureStartChallengeBottom; // where was the challenge at that time?
+
+    private int mDragHandleClosedBelow; // handle hitrect extension into the challenge view
+    private int mDragHandleClosedAbove; // extend the handle's hitrect this far above the line
+    private int mDragHandleOpenBelow; // handle hitrect extension into the challenge view
+    private int mDragHandleOpenAbove; // extend the handle's hitrect this far above the line
+
+    private int mDragHandleEdgeSlop;
+    private int mChallengeBottomBound; // Number of pixels from the top of the challenge view
+                                       // that should remain on-screen
+
+    private int mTouchSlop;
+    private int mTouchSlopSquare;
+
+    float mHandleAlpha;
+    float mFrameAlpha;
+    float mFrameAnimationTarget = Float.MIN_VALUE;
+    private ObjectAnimator mHandleAnimation;
+    private ObjectAnimator mFrameAnimation;
+
+    private boolean mHasGlowpad;
+
+    // We have an internal and external version, and we and them together.
+    private boolean mChallengeInteractiveExternal = true;
+    private boolean mChallengeInteractiveInternal = true;
+
+    static final Property<SlidingChallengeLayout, Float> HANDLE_ALPHA =
+            new FloatProperty<SlidingChallengeLayout>("handleAlpha") {
+        @Override
+        public void setValue(SlidingChallengeLayout view, float value) {
+            view.mHandleAlpha = value;
+            view.invalidate();
+        }
+
+        @Override
+        public Float get(SlidingChallengeLayout view) {
+            return view.mHandleAlpha;
+        }
+    };
+
+    // True if at least one layout pass has happened since the view was attached.
+    private boolean mHasLayout;
+
+    private static final Interpolator sMotionInterpolator = new Interpolator() {
+        public float getInterpolation(float t) {
+            t -= 1.0f;
+            return t * t * t * t * t + 1.0f;
+        }
+    };
+
+    private static final Interpolator sHandleFadeInterpolator = new Interpolator() {
+        public float getInterpolation(float t) {
+            return t * t;
+        }
+    };
+
+    private final Runnable mEndScrollRunnable = new Runnable () {
+        public void run() {
+            completeChallengeScroll();
+        }
+    };
+
+    private final OnClickListener mScrimClickListener = new OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            hideBouncer();
+        }
+    };
+
+    private final OnClickListener mExpandChallengeClickListener = new OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            if (!isChallengeShowing()) {
+                showChallenge(true);
+            }
+        }
+    };
+
+    /**
+     * Listener interface that reports changes in scroll state of the challenge area.
+     */
+    public interface OnChallengeScrolledListener {
+        /**
+         * The scroll state itself changed.
+         *
+         * <p>scrollState will be one of the following:</p>
+         *
+         * <ul>
+         * <li><code>SCROLL_STATE_IDLE</code> - The challenge area is stationary.</li>
+         * <li><code>SCROLL_STATE_DRAGGING</code> - The user is actively dragging
+         * the challenge area.</li>
+         * <li><code>SCROLL_STATE_SETTLING</code> - The challenge area is animating
+         * into place.</li>
+         * </ul>
+         *
+         * <p>Do not perform expensive operations (e.g. layout)
+         * while the scroll state is not <code>SCROLL_STATE_IDLE</code>.</p>
+         *
+         * @param scrollState The new scroll state of the challenge area.
+         */
+        public void onScrollStateChanged(int scrollState);
+
+        /**
+         * The precise position of the challenge area has changed.
+         *
+         * <p>NOTE: It is NOT safe to modify layout or call any View methods that may
+         * result in a requestLayout anywhere in your view hierarchy as a result of this call.
+         * It may be called during drawing.</p>
+         *
+         * @param scrollPosition New relative position of the challenge area.
+         *                       1.f = fully visible/ready to be interacted with.
+         *                       0.f = fully invisible/inaccessible to the user.
+         * @param challengeTop Position of the top edge of the challenge view in px in the
+         *                     SlidingChallengeLayout's coordinate system.
+         */
+        public void onScrollPositionChanged(float scrollPosition, int challengeTop);
+    }
+
+    public SlidingChallengeLayout(Context context) {
+        this(context, null);
+    }
+
+    public SlidingChallengeLayout(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public SlidingChallengeLayout(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        mScroller = new Scroller(context, sMotionInterpolator);
+
+        final ViewConfiguration vc = ViewConfiguration.get(context);
+        mMinVelocity = vc.getScaledMinimumFlingVelocity();
+        mMaxVelocity = vc.getScaledMaximumFlingVelocity();
+
+        final Resources res = getResources();
+        mDragHandleEdgeSlop = res.getDimensionPixelSize(R.dimen.kg_edge_swipe_region_size);
+
+        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+        mTouchSlopSquare = mTouchSlop * mTouchSlop;
+
+        mDisplayMetrics = res.getDisplayMetrics();
+        final float density = mDisplayMetrics.density;
+
+        // top half of the lock icon, plus another 25% to be sure
+        mDragHandleClosedAbove = (int) (DRAG_HANDLE_CLOSED_ABOVE * density + 0.5f);
+        mDragHandleClosedBelow = (int) (DRAG_HANDLE_CLOSED_BELOW * density + 0.5f);
+        mDragHandleOpenAbove = (int) (DRAG_HANDLE_OPEN_ABOVE * density + 0.5f);
+        mDragHandleOpenBelow = (int) (DRAG_HANDLE_OPEN_BELOW * density + 0.5f);
+
+        // how much space to account for in the handle when closed
+        mChallengeBottomBound = res.getDimensionPixelSize(R.dimen.kg_widget_pager_bottom_padding);
+
+        setWillNotDraw(false);
+        setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_STABLE);
+    }
+
+    public void setHandleAlpha(float alpha) {
+        if (mExpandChallengeView != null) {
+            mExpandChallengeView.setAlpha(alpha);
+        }
+    }
+
+    public void setChallengeInteractive(boolean interactive) {
+        mChallengeInteractiveExternal = interactive;
+        if (mExpandChallengeView != null) {
+            mExpandChallengeView.setEnabled(interactive);
+        }
+    }
+
+    void animateHandle(boolean visible) {
+        if (mHandleAnimation != null) {
+            mHandleAnimation.cancel();
+            mHandleAnimation = null;
+        }
+        final float targetAlpha = visible ? 1.f : 0.f;
+        if (targetAlpha == mHandleAlpha) {
+            return;
+        }
+        mHandleAnimation = ObjectAnimator.ofFloat(this, HANDLE_ALPHA, targetAlpha);
+        mHandleAnimation.setInterpolator(sHandleFadeInterpolator);
+        mHandleAnimation.setDuration(HANDLE_ANIMATE_DURATION);
+        mHandleAnimation.start();
+    }
+
+    private void sendInitialListenerUpdates() {
+        if (mScrollListener != null) {
+            int challengeTop = mChallengeView != null ? mChallengeView.getTop() : 0;
+            mScrollListener.onScrollPositionChanged(mChallengeOffset, challengeTop);
+            mScrollListener.onScrollStateChanged(mScrollState);
+        }
+    }
+
+    public void setOnChallengeScrolledListener(OnChallengeScrolledListener listener) {
+        mScrollListener = listener;
+        if (mHasLayout) {
+            sendInitialListenerUpdates();
+        }
+    }
+
+    public void setOnBouncerStateChangedListener(OnBouncerStateChangedListener listener) {
+        mBouncerListener = listener;
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+        super.onAttachedToWindow();
+
+        mHasLayout = false;
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+
+        removeCallbacks(mEndScrollRunnable);
+        mHasLayout = false;
+    }
+
+    @Override
+    public void requestChildFocus(View child, View focused) {
+        if (mIsBouncing && child != mChallengeView) {
+            // Clear out of the bouncer if the user tries to move focus outside of
+            // the security challenge view.
+            hideBouncer();
+        }
+        super.requestChildFocus(child, focused);
+    }
+
+    // We want the duration of the page snap animation to be influenced by the distance that
+    // the screen has to travel, however, we don't want this duration to be effected in a
+    // purely linear fashion. Instead, we use this method to moderate the effect that the distance
+    // of travel has on the overall snap duration.
+    float distanceInfluenceForSnapDuration(float f) {
+        f -= 0.5f; // center the values about 0.
+        f *= 0.3f * Math.PI / 2.0f;
+        return (float) Math.sin(f);
+    }
+
+    void setScrollState(int state) {
+        if (mScrollState != state) {
+            mScrollState = state;
+
+            animateHandle(state == SCROLL_STATE_IDLE && !mChallengeShowing);
+            if (mScrollListener != null) {
+                mScrollListener.onScrollStateChanged(state);
+            }
+        }
+    }
+
+    void completeChallengeScroll() {
+        setChallengeShowing(mChallengeShowingTargetState);
+        mChallengeOffset = mChallengeShowing ? 1.f : 0.f;
+        setScrollState(SCROLL_STATE_IDLE);
+        mChallengeInteractiveInternal = true;
+        mChallengeView.setLayerType(LAYER_TYPE_NONE, null);
+    }
+
+    void setScrimView(View scrim) {
+        if (mScrimView != null) {
+            mScrimView.setOnClickListener(null);
+        }
+        mScrimView = scrim;
+        mScrimView.setVisibility(mIsBouncing ? VISIBLE : GONE);
+        mScrimView.setFocusable(true);
+        mScrimView.setOnClickListener(mScrimClickListener);
+    }
+
+    /**
+     * Animate the bottom edge of the challenge view to the given position.
+     *
+     * @param y desired final position for the bottom edge of the challenge view in px
+     * @param velocity velocity in
+     */
+    void animateChallengeTo(int y, int velocity) {
+        if (mChallengeView == null) {
+            // Nothing to do.
+            return;
+        }
+
+        cancelTransitionsInProgress();
+
+        mChallengeInteractiveInternal = false;
+        mChallengeView.setLayerType(LAYER_TYPE_HARDWARE, null);
+        final int sy = mChallengeView.getBottom();
+        final int dy = y - sy;
+        if (dy == 0) {
+            completeChallengeScroll();
+            return;
+        }
+
+        setScrollState(SCROLL_STATE_SETTLING);
+
+        final int childHeight = mChallengeView.getHeight();
+        final int halfHeight = childHeight / 2;
+        final float distanceRatio = Math.min(1f, 1.0f * Math.abs(dy) / childHeight);
+        final float distance = halfHeight + halfHeight *
+                distanceInfluenceForSnapDuration(distanceRatio);
+
+        int duration = 0;
+        velocity = Math.abs(velocity);
+        if (velocity > 0) {
+            duration = 4 * Math.round(1000 * Math.abs(distance / velocity));
+        } else {
+            final float childDelta = (float) Math.abs(dy) / childHeight;
+            duration = (int) ((childDelta + 1) * 100);
+        }
+        duration = Math.min(duration, MAX_SETTLE_DURATION);
+
+        mScroller.startScroll(0, sy, 0, dy, duration);
+        postInvalidateOnAnimation();
+    }
+
+    private void setChallengeShowing(boolean showChallenge) {
+        if (mChallengeShowing == showChallenge) {
+            return;
+        }
+        mChallengeShowing = showChallenge;
+
+        if (mExpandChallengeView == null || mChallengeView == null) {
+            // These might not be here yet if we haven't been through layout.
+            // If we haven't, the first layout pass will set everything up correctly
+            // based on mChallengeShowing as set above.
+            return;
+        }
+
+        if (mChallengeShowing) {
+            mExpandChallengeView.setVisibility(View.INVISIBLE);
+            mChallengeView.setVisibility(View.VISIBLE);
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                mChallengeView.requestAccessibilityFocus();
+                mChallengeView.announceForAccessibility(mContext.getString(
+                        R.string.keyguard_accessibility_unlock_area_expanded));
+            }
+        } else {
+            mExpandChallengeView.setVisibility(View.VISIBLE);
+            mChallengeView.setVisibility(View.INVISIBLE);
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                mExpandChallengeView.requestAccessibilityFocus();
+                mChallengeView.announceForAccessibility(mContext.getString(
+                        R.string.keyguard_accessibility_unlock_area_collapsed));
+            }
+        }
+    }
+
+    /**
+     * @return true if the challenge is at all visible.
+     */
+    public boolean isChallengeShowing() {
+        return mChallengeShowing;
+    }
+
+    @Override
+    public boolean isChallengeOverlapping() {
+        return mChallengeShowing;
+    }
+
+    @Override
+    public boolean isBouncing() {
+        return mIsBouncing;
+    }
+
+    @Override
+    public int getBouncerAnimationDuration() {
+        return HANDLE_ANIMATE_DURATION;
+    }
+
+    @Override
+    public void showBouncer() {
+        if (mIsBouncing) return;
+        mWasChallengeShowing = mChallengeShowing;
+        mIsBouncing = true;
+        showChallenge(true);
+        if (mScrimView != null) {
+            Animator anim = ObjectAnimator.ofFloat(mScrimView, "alpha", 1f);
+            anim.setDuration(HANDLE_ANIMATE_DURATION);
+            anim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationStart(Animator animation) {
+                    mScrimView.setVisibility(VISIBLE);
+                }
+            });
+            anim.start();
+        }
+        if (mChallengeView != null) {
+            mChallengeView.showBouncer(HANDLE_ANIMATE_DURATION);
+        }
+
+        if (mBouncerListener != null) {
+            mBouncerListener.onBouncerStateChanged(true);
+        }
+    }
+
+    @Override
+    public void hideBouncer() {
+        if (!mIsBouncing) return;
+        if (!mWasChallengeShowing) showChallenge(false);
+        mIsBouncing = false;
+
+        if (mScrimView != null) {
+            Animator anim = ObjectAnimator.ofFloat(mScrimView, "alpha", 0f);
+            anim.setDuration(HANDLE_ANIMATE_DURATION);
+            anim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    mScrimView.setVisibility(GONE);
+                }
+            });
+            anim.start();
+        }
+        if (mChallengeView != null) {
+            mChallengeView.hideBouncer(HANDLE_ANIMATE_DURATION);
+        }
+        if (mBouncerListener != null) {
+            mBouncerListener.onBouncerStateChanged(false);
+        }
+    }
+
+    private int getChallengeMargin(boolean expanded) {
+        return expanded && mHasGlowpad ? 0 : mDragHandleEdgeSlop;
+    }
+
+    private float getChallengeAlpha() {
+        float x = mChallengeOffset - 1;
+        return x * x * x + 1.f;
+    }
+
+    @Override
+    public void requestDisallowInterceptTouchEvent(boolean allowIntercept) {
+        // We'll intercept whoever we feel like! ...as long as it isn't a challenge view.
+        // If there are one or more pointers in the challenge view before we take over
+        // touch events, onInterceptTouchEvent will set mBlockDrag.
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (mVelocityTracker == null) {
+            mVelocityTracker = VelocityTracker.obtain();
+        }
+        mVelocityTracker.addMovement(ev);
+
+        final int action = ev.getActionMasked();
+        switch (action) {
+            case MotionEvent.ACTION_DOWN:
+                mGestureStartX = ev.getX();
+                mGestureStartY = ev.getY();
+                mBlockDrag = false;
+                break;
+
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                resetTouch();
+                break;
+
+            case MotionEvent.ACTION_MOVE:
+                final int count = ev.getPointerCount();
+                for (int i = 0; i < count; i++) {
+                    final float x = ev.getX(i);
+                    final float y = ev.getY(i);
+                    if (!mIsBouncing && mActivePointerId == INVALID_POINTER
+                                && (crossedDragHandle(x, y, mGestureStartY)
+                                || (isInChallengeView(x, y) &&
+                                        mScrollState == SCROLL_STATE_SETTLING))) {
+                        mActivePointerId = ev.getPointerId(i);
+                        mGestureStartX = x;
+                        mGestureStartY = y;
+                        mGestureStartChallengeBottom = getChallengeBottom();
+                        mDragging = true;
+                        mChallengeView.setLayerType(LAYER_TYPE_HARDWARE, null);
+                    } else if (mChallengeShowing && isInChallengeView(x, y)) {
+                        mBlockDrag = true;
+                    }
+                }
+                break;
+        }
+
+        if (mBlockDrag || isChallengeInteractionBlocked()) {
+            mActivePointerId = INVALID_POINTER;
+            mDragging = false;
+        }
+
+        return mDragging;
+    }
+
+    private boolean isChallengeInteractionBlocked() {
+        return !mChallengeInteractiveExternal || !mChallengeInteractiveInternal;
+    }
+
+    private void resetTouch() {
+        mVelocityTracker.recycle();
+        mVelocityTracker = null;
+        mActivePointerId = INVALID_POINTER;
+        mDragging = mBlockDrag = false;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        if (mVelocityTracker == null) {
+            mVelocityTracker = VelocityTracker.obtain();
+        }
+        mVelocityTracker.addMovement(ev);
+
+        final int action = ev.getActionMasked();
+        switch (action) {
+            case MotionEvent.ACTION_DOWN:
+                mBlockDrag = false;
+                mGestureStartX = ev.getX();
+                mGestureStartY = ev.getY();
+                break;
+
+            case MotionEvent.ACTION_CANCEL:
+                if (mDragging && !isChallengeInteractionBlocked()) {
+                    showChallenge(0);
+                }
+                resetTouch();
+                break;
+
+            case MotionEvent.ACTION_POINTER_UP:
+                if (mActivePointerId != ev.getPointerId(ev.getActionIndex())) {
+                    break;
+                }
+            case MotionEvent.ACTION_UP:
+                if (mDragging && !isChallengeInteractionBlocked()) {
+                    mVelocityTracker.computeCurrentVelocity(1000, mMaxVelocity);
+                    showChallenge((int) mVelocityTracker.getYVelocity(mActivePointerId));
+                }
+                resetTouch();
+                break;
+
+            case MotionEvent.ACTION_MOVE:
+                if (!mDragging && !mBlockDrag && !mIsBouncing) {
+                    final int count = ev.getPointerCount();
+                    for (int i = 0; i < count; i++) {
+                        final float x = ev.getX(i);
+                        final float y = ev.getY(i);
+
+                        if ((isInDragHandle(x, y) || crossedDragHandle(x, y, mGestureStartY) ||
+                                (isInChallengeView(x, y) && mScrollState == SCROLL_STATE_SETTLING))
+                                && mActivePointerId == INVALID_POINTER
+                                && !isChallengeInteractionBlocked()) {
+                            mGestureStartX = x;
+                            mGestureStartY = y;
+                            mActivePointerId = ev.getPointerId(i);
+                            mGestureStartChallengeBottom = getChallengeBottom();
+                            mDragging = true;
+                            mChallengeView.setLayerType(LAYER_TYPE_HARDWARE, null);
+                            break;
+                        }
+                    }
+                }
+                // Not an else; this can be set above.
+                if (mDragging) {
+                    // No-op if already in this state, but set it here in case we arrived
+                    // at this point from either intercept or the above.
+                    setScrollState(SCROLL_STATE_DRAGGING);
+
+                    final int index = ev.findPointerIndex(mActivePointerId);
+                    if (index < 0) {
+                        // Oops, bogus state. We lost some touch events somewhere.
+                        // Just drop it with no velocity and let things settle.
+                        resetTouch();
+                        showChallenge(0);
+                        return true;
+                    }
+                    final float y = ev.getY(index);
+                    final float pos = Math.min(y - mGestureStartY,
+                            getLayoutBottom() - mChallengeBottomBound);
+
+                    moveChallengeTo(mGestureStartChallengeBottom + (int) pos);
+                }
+                break;
+        }
+        return true;
+    }
+
+    /**
+     * The lifecycle of touch events is subtle and it's very easy to do something
+     * that will cause bugs that will be nasty to track when overriding this method.
+     * Normally one should always override onInterceptTouchEvent instead.
+     *
+     * To put it another way, don't try this at home.
+     */
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        final int action = ev.getActionMasked();
+        boolean handled = false;
+        if (action == MotionEvent.ACTION_DOWN) {
+            // Defensive programming: if we didn't get the UP or CANCEL, reset anyway.
+            mEdgeCaptured = false;
+        }
+        if (mWidgetsView != null && !mIsBouncing && (mEdgeCaptured || isEdgeSwipeBeginEvent(ev))) {
+            // Normally we would need to do a lot of extra stuff here.
+            // We can only get away with this because we haven't padded in
+            // the widget pager or otherwise transformed it during layout.
+            // We also don't support things like splitting MotionEvents.
+
+            // We set handled to captured even if dispatch is returning false here so that
+            // we don't send a different view a busted or incomplete event stream.
+            handled = mEdgeCaptured |= mWidgetsView.dispatchTouchEvent(ev);
+        }
+
+        if (!handled && !mEdgeCaptured) {
+            handled = super.dispatchTouchEvent(ev);
+        }
+
+        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+            mEdgeCaptured = false;
+        }
+
+        return handled;
+    }
+
+    private boolean isEdgeSwipeBeginEvent(MotionEvent ev) {
+        if (ev.getActionMasked() != MotionEvent.ACTION_DOWN) {
+            return false;
+        }
+
+        final float x = ev.getX();
+        return x < mDragHandleEdgeSlop || x >= getWidth() - mDragHandleEdgeSlop;
+    }
+
+    /**
+     * We only want to add additional vertical space to the drag handle when the panel is fully
+     * closed.
+     */
+    private int getDragHandleSizeAbove() {
+        return isChallengeShowing() ? mDragHandleOpenAbove : mDragHandleClosedAbove;
+    }
+    private int getDragHandleSizeBelow() {
+        return isChallengeShowing() ? mDragHandleOpenBelow : mDragHandleClosedBelow;
+    }
+
+    private boolean isInChallengeView(float x, float y) {
+        return isPointInView(x, y, mChallengeView);
+    }
+
+    private boolean isInDragHandle(float x, float y) {
+        return isPointInView(x, y, mExpandChallengeView);
+    }
+
+    private boolean isPointInView(float x, float y, View view) {
+        if (view == null) {
+            return false;
+        }
+        return x >= view.getLeft() && y >= view.getTop()
+                && x < view.getRight() && y < view.getBottom();
+    }
+
+    private boolean crossedDragHandle(float x, float y, float initialY) {
+
+        final int challengeTop = mChallengeView.getTop();
+        final boolean horizOk = x >= 0 && x < getWidth();
+
+        final boolean vertOk;
+        if (mChallengeShowing) {
+            vertOk = initialY < (challengeTop - getDragHandleSizeAbove()) &&
+                    y > challengeTop + getDragHandleSizeBelow();
+        } else {
+            vertOk = initialY > challengeTop + getDragHandleSizeBelow() &&
+                    y < challengeTop - getDragHandleSizeAbove();
+        }
+        return horizOk && vertOk;
+    }
+
+    private int makeChildMeasureSpec(int maxSize, int childDimen) {
+        final int mode;
+        final int size;
+        switch (childDimen) {
+            case LayoutParams.WRAP_CONTENT:
+                mode = MeasureSpec.AT_MOST;
+                size = maxSize;
+                break;
+            case LayoutParams.MATCH_PARENT:
+                mode = MeasureSpec.EXACTLY;
+                size = maxSize;
+                break;
+            default:
+                mode = MeasureSpec.EXACTLY;
+                size = Math.min(maxSize, childDimen);
+                break;
+        }
+        return MeasureSpec.makeMeasureSpec(size, mode);
+    }
+
+    @Override
+    protected void onMeasure(int widthSpec, int heightSpec) {
+        if (MeasureSpec.getMode(widthSpec) != MeasureSpec.EXACTLY ||
+                MeasureSpec.getMode(heightSpec) != MeasureSpec.EXACTLY) {
+            throw new IllegalArgumentException(
+                    "SlidingChallengeLayout must be measured with an exact size");
+        }
+
+        final int width = MeasureSpec.getSize(widthSpec);
+        final int height = MeasureSpec.getSize(heightSpec);
+        setMeasuredDimension(width, height);
+
+        // Find one and only one challenge view.
+        final View oldChallengeView = mChallengeView;
+        final View oldExpandChallengeView = mChallengeView;
+        mChallengeView = null;
+        mExpandChallengeView = null;
+        final int count = getChildCount();
+
+        // First iteration through the children finds special children and sets any associated
+        // state.
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            if (lp.childType == LayoutParams.CHILD_TYPE_CHALLENGE) {
+                if (mChallengeView != null) {
+                    throw new IllegalStateException(
+                            "There may only be one child with layout_isChallenge=\"true\"");
+                }
+                if (!(child instanceof KeyguardSecurityContainer)) {
+                            throw new IllegalArgumentException(
+                                    "Challenge must be a KeyguardSecurityContainer");
+                }
+                mChallengeView = (KeyguardSecurityContainer) child;
+                if (mChallengeView != oldChallengeView) {
+                    mChallengeView.setVisibility(mChallengeShowing ? VISIBLE : INVISIBLE);
+                }
+                // We're going to play silly games with the frame's background drawable later.
+                if (!mHasLayout) {
+                    // Set up the margin correctly based on our content for the first run.
+                    mHasGlowpad = child.findViewById(R.id.keyguard_selector_view) != null;
+                    lp.leftMargin = lp.rightMargin = getChallengeMargin(true);
+                }
+            } else if (lp.childType == LayoutParams.CHILD_TYPE_EXPAND_CHALLENGE_HANDLE) {
+                if (mExpandChallengeView != null) {
+                    throw new IllegalStateException(
+                            "There may only be one child with layout_childType"
+                            + "=\"expandChallengeHandle\"");
+                }
+                mExpandChallengeView = child;
+                if (mExpandChallengeView != oldExpandChallengeView) {
+                    mExpandChallengeView.setVisibility(mChallengeShowing ? INVISIBLE : VISIBLE);
+                    mExpandChallengeView.setOnClickListener(mExpandChallengeClickListener);
+                }
+            } else if (lp.childType == LayoutParams.CHILD_TYPE_SCRIM) {
+                setScrimView(child);
+            } else if (lp.childType == LayoutParams.CHILD_TYPE_WIDGETS) {
+                mWidgetsView = child;
+            }
+        }
+
+        // We want to measure the challenge view first, since the KeyguardWidgetPager
+        // needs to do things its measure pass that are dependent on the challenge view
+        // having been measured.
+        if (mChallengeView != null && mChallengeView.getVisibility() != View.GONE) {
+            // This one's a little funny. If the IME is present - reported in the form
+            // of insets on the root view - we only give the challenge the space it would
+            // have had if the IME wasn't there in order to keep the rest of the layout stable.
+            // We base this on the layout_maxHeight on the challenge view. If it comes out
+            // negative or zero, either we didn't have a maxHeight or we're totally out of space,
+            // so give up and measure as if this rule weren't there.
+            int challengeHeightSpec = heightSpec;
+            final View root = getRootView();
+            if (root != null) {
+                final LayoutParams lp = (LayoutParams) mChallengeView.getLayoutParams();
+                final int specSize = MeasureSpec.getSize(heightSpec);
+                final int windowHeight = mDisplayMetrics.heightPixels - root.getPaddingTop();
+                final int diff = windowHeight - specSize;
+                final int maxChallengeHeight = lp.maxHeight - diff;
+                if (maxChallengeHeight > 0) {
+                    challengeHeightSpec = makeChildMeasureSpec(maxChallengeHeight, lp.height);
+                }
+            }
+            measureChildWithMargins(mChallengeView, widthSpec, 0, challengeHeightSpec, 0);
+        }
+
+        // Measure the rest of the children
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.getVisibility() == GONE) {
+                continue;
+            }
+            // Don't measure the challenge view twice!
+            if (child == mChallengeView) continue;
+
+            // Measure children. Widget frame measures special, so that we can ignore
+            // insets for the IME.
+            int parentWidthSpec = widthSpec, parentHeightSpec = heightSpec;
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            if (lp.childType == LayoutParams.CHILD_TYPE_WIDGETS) {
+                final View root = getRootView();
+                if (root != null) {
+                    // This calculation is super dodgy and relies on several assumptions.
+                    // Specifically that the root of the window will be padded in for insets
+                    // and that the window is LAYOUT_IN_SCREEN.
+                    final int windowWidth = mDisplayMetrics.widthPixels;
+                    final int windowHeight = mDisplayMetrics.heightPixels - root.getPaddingTop();
+                    parentWidthSpec = MeasureSpec.makeMeasureSpec(
+                            windowWidth, MeasureSpec.EXACTLY);
+                    parentHeightSpec = MeasureSpec.makeMeasureSpec(
+                            windowHeight, MeasureSpec.EXACTLY);
+                }
+            }
+            measureChildWithMargins(child, parentWidthSpec, 0, parentHeightSpec, 0);
+        }
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        final int paddingLeft = getPaddingLeft();
+        final int paddingTop = getPaddingTop();
+        final int paddingRight = getPaddingRight();
+        final int paddingBottom = getPaddingBottom();
+        final int width = r - l;
+        final int height = b - t;
+
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+
+            if (child.getVisibility() == GONE) continue;
+
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+            if (lp.childType == LayoutParams.CHILD_TYPE_CHALLENGE) {
+                // Challenge views pin to the bottom, offset by a portion of their height,
+                // and center horizontally.
+                final int center = (paddingLeft + width - paddingRight) / 2;
+                final int childWidth = child.getMeasuredWidth();
+                final int childHeight = child.getMeasuredHeight();
+                final int left = center - childWidth / 2;
+                final int layoutBottom = height - paddingBottom - lp.bottomMargin;
+                // We use the top of the challenge view to position the handle, so
+                // we never want less than the handle size showing at the bottom.
+                final int bottom = layoutBottom + (int) ((childHeight - mChallengeBottomBound)
+                        * (1 - mChallengeOffset));
+                child.setAlpha(getChallengeAlpha());
+                child.layout(left, bottom - childHeight, left + childWidth, bottom);
+            } else if (lp.childType == LayoutParams.CHILD_TYPE_EXPAND_CHALLENGE_HANDLE) {
+                final int center = (paddingLeft + width - paddingRight) / 2;
+                final int left = center - child.getMeasuredWidth() / 2;
+                final int right = left + child.getMeasuredWidth();
+                final int bottom = height - paddingBottom - lp.bottomMargin;
+                final int top = bottom - child.getMeasuredHeight();
+                child.layout(left, top, right, bottom);
+            } else {
+                // Non-challenge views lay out from the upper left, layered.
+                child.layout(paddingLeft + lp.leftMargin,
+                        paddingTop + lp.topMargin,
+                        paddingLeft + child.getMeasuredWidth(),
+                        paddingTop + child.getMeasuredHeight());
+            }
+        }
+
+        if (!mHasLayout) {
+            mHasLayout = true;
+        }
+    }
+
+    @Override
+    public void draw(Canvas c) {
+        super.draw(c);
+        if (DEBUG) {
+            final Paint debugPaint = new Paint();
+            debugPaint.setColor(0x40FF00CC);
+            // show the isInDragHandle() rect
+            c.drawRect(mDragHandleEdgeSlop,
+                    mChallengeView.getTop() - getDragHandleSizeAbove(),
+                    getWidth() - mDragHandleEdgeSlop,
+                    mChallengeView.getTop() + getDragHandleSizeBelow(),
+                    debugPaint);
+        }
+    }
+
+    public void computeScroll() {
+        super.computeScroll();
+
+        if (!mScroller.isFinished()) {
+            if (mChallengeView == null) {
+                // Can't scroll if the view is missing.
+                Log.e(TAG, "Challenge view missing in computeScroll");
+                mScroller.abortAnimation();
+                return;
+            }
+
+            mScroller.computeScrollOffset();
+            moveChallengeTo(mScroller.getCurrY());
+
+            if (mScroller.isFinished()) {
+                post(mEndScrollRunnable);
+            }
+        }
+    }
+
+    private void cancelTransitionsInProgress() {
+        if (!mScroller.isFinished()) {
+            mScroller.abortAnimation();
+            completeChallengeScroll();
+        }
+        if (mFader != null) {
+            mFader.cancel();
+        }
+    }
+
+    public void fadeInChallenge() {
+        fadeChallenge(true);
+    }
+
+    public void fadeOutChallenge() {
+        fadeChallenge(false);
+    }
+
+    public void fadeChallenge(final boolean show) {
+        if (mChallengeView != null) {
+
+            cancelTransitionsInProgress();
+            float alpha = show ? 1f : 0f;
+            int duration = show ? CHALLENGE_FADE_IN_DURATION : CHALLENGE_FADE_OUT_DURATION;
+            mFader = ObjectAnimator.ofFloat(mChallengeView, "alpha", alpha);
+            mFader.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationStart(Animator animation) {
+                    onFadeStart(show);
+                }
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    onFadeEnd(show);
+                }
+            });
+            mFader.setDuration(duration);
+            mFader.start();
+        }
+    }
+
+    private int getMaxChallengeBottom() {
+        if (mChallengeView == null) return 0;
+        final int layoutBottom = getLayoutBottom();
+        final int challengeHeight = mChallengeView.getMeasuredHeight();
+
+        return (layoutBottom + challengeHeight - mChallengeBottomBound);
+    }
+
+    private int getMinChallengeBottom() {
+        return getLayoutBottom();
+    }
+
+
+    private void onFadeStart(boolean show) {
+        mChallengeInteractiveInternal = false;
+        mChallengeView.setLayerType(LAYER_TYPE_HARDWARE, null);
+
+        if (show) {
+            moveChallengeTo(getMinChallengeBottom());
+        }
+
+        setScrollState(SCROLL_STATE_FADING);
+    }
+
+    private void onFadeEnd(boolean show) {
+        mChallengeInteractiveInternal = true;
+        setChallengeShowing(show);
+
+        if (!show) {
+            moveChallengeTo(getMaxChallengeBottom());
+        }
+
+        mChallengeView.setLayerType(LAYER_TYPE_NONE, null);
+        mFader = null;
+        setScrollState(SCROLL_STATE_IDLE);
+    }
+
+    public int getMaxChallengeTop() {
+        if (mChallengeView == null) return 0;
+
+        final int layoutBottom = getLayoutBottom();
+        final int challengeHeight = mChallengeView.getMeasuredHeight();
+        return layoutBottom - challengeHeight;
+    }
+
+    /**
+     * Move the bottom edge of mChallengeView to a new position and notify the listener
+     * if it represents a change in position. Changes made through this method will
+     * be stable across layout passes. If this method is called before first layout of
+     * this SlidingChallengeLayout it will have no effect.
+     *
+     * @param bottom New bottom edge in px in this SlidingChallengeLayout's coordinate system.
+     * @return true if the challenge view was moved
+     */
+    private boolean moveChallengeTo(int bottom) {
+        if (mChallengeView == null || !mHasLayout) {
+            return false;
+        }
+
+        final int layoutBottom = getLayoutBottom();
+        final int challengeHeight = mChallengeView.getHeight();
+
+        bottom = Math.max(getMinChallengeBottom(),
+                Math.min(bottom, getMaxChallengeBottom()));
+
+        float offset = 1.f - (float) (bottom - layoutBottom) /
+                (challengeHeight - mChallengeBottomBound);
+        mChallengeOffset = offset;
+        if (offset > 0 && !mChallengeShowing) {
+            setChallengeShowing(true);
+        }
+
+        mChallengeView.layout(mChallengeView.getLeft(),
+                bottom - mChallengeView.getHeight(), mChallengeView.getRight(), bottom);
+
+        mChallengeView.setAlpha(getChallengeAlpha());
+        if (mScrollListener != null) {
+            mScrollListener.onScrollPositionChanged(offset, mChallengeView.getTop());
+        }
+        postInvalidateOnAnimation();
+        return true;
+    }
+
+    /**
+     * The bottom edge of this SlidingChallengeLayout's coordinate system; will coincide with
+     * the bottom edge of mChallengeView when the challenge is fully opened.
+     */
+    private int getLayoutBottom() {
+        final int bottomMargin = (mChallengeView == null)
+                ? 0
+                : ((LayoutParams) mChallengeView.getLayoutParams()).bottomMargin;
+        final int layoutBottom = getMeasuredHeight() - getPaddingBottom() - bottomMargin;
+        return layoutBottom;
+    }
+
+    /**
+     * The bottom edge of mChallengeView; essentially, where the sliding challenge 'is'.
+     */
+    private int getChallengeBottom() {
+        if (mChallengeView == null) return 0;
+
+        return mChallengeView.getBottom();
+    }
+
+    /**
+     * Show or hide the challenge view, animating it if necessary.
+     * @param show true to show, false to hide
+     */
+    public void showChallenge(boolean show) {
+        showChallenge(show, 0);
+        if (!show) {
+            // Block any drags in progress so that callers can use this to disable dragging
+            // for other touch interactions.
+            mBlockDrag = true;
+        }
+    }
+
+    private void showChallenge(int velocity) {
+        boolean show = false;
+        if (Math.abs(velocity) > mMinVelocity) {
+            show = velocity < 0;
+        } else {
+            show = mChallengeOffset >= 0.5f;
+        }
+        showChallenge(show, velocity);
+    }
+
+    private void showChallenge(boolean show, int velocity) {
+        if (mChallengeView == null) {
+            setChallengeShowing(false);
+            return;
+        }
+
+        if (mHasLayout) {
+            mChallengeShowingTargetState = show;
+            final int layoutBottom = getLayoutBottom();
+            animateChallengeTo(show ? layoutBottom :
+                    layoutBottom + mChallengeView.getHeight() - mChallengeBottomBound, velocity);
+        }
+    }
+
+    @Override
+    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
+        return new LayoutParams(getContext(), attrs);
+    }
+
+    @Override
+    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+        return p instanceof LayoutParams ? new LayoutParams((LayoutParams) p) :
+                p instanceof MarginLayoutParams ? new LayoutParams((MarginLayoutParams) p) :
+                new LayoutParams(p);
+    }
+
+    @Override
+    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
+        return new LayoutParams();
+    }
+
+    @Override
+    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+        return p instanceof LayoutParams;
+    }
+
+    public static class LayoutParams extends MarginLayoutParams {
+        public int childType = CHILD_TYPE_NONE;
+        public static final int CHILD_TYPE_NONE = 0;
+        public static final int CHILD_TYPE_CHALLENGE = 2;
+        public static final int CHILD_TYPE_SCRIM = 4;
+        public static final int CHILD_TYPE_WIDGETS = 5;
+        public static final int CHILD_TYPE_EXPAND_CHALLENGE_HANDLE = 6;
+
+        public int maxHeight;
+
+        public LayoutParams() {
+            this(MATCH_PARENT, WRAP_CONTENT);
+        }
+
+        public LayoutParams(int width, int height) {
+            super(width, height);
+        }
+
+        public LayoutParams(android.view.ViewGroup.LayoutParams source) {
+            super(source);
+        }
+
+        public LayoutParams(MarginLayoutParams source) {
+            super(source);
+        }
+
+        public LayoutParams(LayoutParams source) {
+            super(source);
+
+            childType = source.childType;
+        }
+
+        public LayoutParams(Context c, AttributeSet attrs) {
+            super(c, attrs);
+
+            final TypedArray a = c.obtainStyledAttributes(attrs,
+                    R.styleable.SlidingChallengeLayout_Layout);
+            childType = a.getInt(R.styleable.SlidingChallengeLayout_Layout_layout_childType,
+                    CHILD_TYPE_NONE);
+            maxHeight = a.getDimensionPixelSize(
+                    R.styleable.SlidingChallengeLayout_Layout_layout_maxHeight, 0);
+            a.recycle();
+        }
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/AccountUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/AccountUnlockScreen.java
new file mode 100644
index 0000000..d6a31b8
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/AccountUnlockScreen.java
@@ -0,0 +1,317 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import com.android.internal.R;
+import com.android.internal.widget.LockPatternUtils;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.OperationCanceledException;
+import android.accounts.AccountManagerFuture;
+import android.accounts.AuthenticatorException;
+import android.accounts.AccountManagerCallback;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.text.Editable;
+import android.text.InputFilter;
+import android.text.LoginFilter;
+import android.text.TextWatcher;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.os.Bundle;
+
+import java.io.IOException;
+
+/**
+ * When the user forgets their password a bunch of times, we fall back on their
+ * account's login/password to unlock the phone (and reset their lock pattern).
+ */
+public class AccountUnlockScreen extends RelativeLayout implements KeyguardScreen,
+        View.OnClickListener, TextWatcher {
+    private static final String LOCK_PATTERN_PACKAGE = "com.android.settings";
+    private static final String LOCK_PATTERN_CLASS = LOCK_PATTERN_PACKAGE + ".ChooseLockGeneric";
+
+    /**
+     * The amount of millis to stay awake once this screen detects activity
+     */
+    private static final int AWAKE_POKE_MILLIS = 30000;
+
+    private KeyguardScreenCallback mCallback;
+    private LockPatternUtils mLockPatternUtils;
+    private KeyguardUpdateMonitor mUpdateMonitor;
+
+    private TextView mTopHeader;
+    private TextView mInstructions;
+    private EditText mLogin;
+    private EditText mPassword;
+    private Button mOk;
+
+    /**
+     * Shown while making asynchronous check of password.
+     */
+    private ProgressDialog mCheckingDialog;
+    private KeyguardStatusViewManager mKeyguardStatusViewManager;
+
+    /**
+     * AccountUnlockScreen constructor.
+     * @param configuration
+     * @param updateMonitor
+     */
+    public AccountUnlockScreen(Context context, Configuration configuration,
+            KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback,
+            LockPatternUtils lockPatternUtils) {
+        super(context);
+        mCallback = callback;
+        mLockPatternUtils = lockPatternUtils;
+
+        LayoutInflater.from(context).inflate(
+                R.layout.keyguard_screen_glogin_unlock, this, true);
+
+        mTopHeader = (TextView) findViewById(R.id.topHeader);
+        mTopHeader.setText(mLockPatternUtils.isPermanentlyLocked() ?
+                R.string.lockscreen_glogin_too_many_attempts :
+                R.string.lockscreen_glogin_forgot_pattern);
+
+        mInstructions = (TextView) findViewById(R.id.instructions);
+
+        mLogin = (EditText) findViewById(R.id.login);
+        mLogin.setFilters(new InputFilter[] { new LoginFilter.UsernameFilterGeneric() } );
+        mLogin.addTextChangedListener(this);
+
+        mPassword = (EditText) findViewById(R.id.password);
+        mPassword.addTextChangedListener(this);
+
+        mOk = (Button) findViewById(R.id.ok);
+        mOk.setOnClickListener(this);
+
+        mUpdateMonitor = updateMonitor;
+
+        mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor,
+                lockPatternUtils, callback, true);
+    }
+
+    public void afterTextChanged(Editable s) {
+    }
+
+    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+    }
+
+    public void onTextChanged(CharSequence s, int start, int before, int count) {
+        mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
+    }
+
+    @Override
+    protected boolean onRequestFocusInDescendants(int direction,
+            Rect previouslyFocusedRect) {
+        // send focus to the login field
+        return mLogin.requestFocus(direction, previouslyFocusedRect);
+    }
+
+    /** {@inheritDoc} */
+    public boolean needsInput() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    public void onPause() {
+        mKeyguardStatusViewManager.onPause();
+    }
+
+    /** {@inheritDoc} */
+    public void onResume() {
+        // start fresh
+        mLogin.setText("");
+        mPassword.setText("");
+        mLogin.requestFocus();
+        mKeyguardStatusViewManager.onResume();
+    }
+
+    /** {@inheritDoc} */
+    public void cleanUp() {
+        if (mCheckingDialog != null) {
+            mCheckingDialog.hide();
+        }
+        mUpdateMonitor.removeCallback(this); // this must be first
+        mCallback = null;
+        mLockPatternUtils = null;
+        mUpdateMonitor = null;
+    }
+
+    /** {@inheritDoc} */
+    public void onClick(View v) {
+        mCallback.pokeWakelock();
+        if (v == mOk) {
+            asyncCheckPassword();
+        }
+    }
+
+    private void postOnCheckPasswordResult(final boolean success) {
+        // ensure this runs on UI thread
+        mLogin.post(new Runnable() {
+            public void run() {
+                if (success) {
+                    // clear out forgotten password
+                    mLockPatternUtils.setPermanentlyLocked(false);
+                    mLockPatternUtils.setLockPatternEnabled(false);
+                    mLockPatternUtils.saveLockPattern(null);
+
+                    // launch the 'choose lock pattern' activity so
+                    // the user can pick a new one if they want to
+                    Intent intent = new Intent();
+                    intent.setClassName(LOCK_PATTERN_PACKAGE, LOCK_PATTERN_CLASS);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                    mContext.startActivity(intent);
+                    mCallback.reportSuccessfulUnlockAttempt();
+
+                    // close the keyguard
+                    mCallback.keyguardDone(true);
+                } else {
+                    mInstructions.setText(R.string.lockscreen_glogin_invalid_input);
+                    mPassword.setText("");
+                    mCallback.reportFailedUnlockAttempt();
+                }
+            }
+        });
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if (event.getAction() == KeyEvent.ACTION_DOWN
+                && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+            if (mLockPatternUtils.isPermanentlyLocked()) {
+                mCallback.goToLockScreen();
+            } else {
+                mCallback.forgotPattern(false);
+            }
+            return true;
+        }
+        return super.dispatchKeyEvent(event);
+    }
+
+    /**
+     * Given the string the user entered in the 'username' field, find
+     * the stored account that they probably intended.  Prefer, in order:
+     *
+     *   - an exact match for what was typed, or
+     *   - a case-insensitive match for what was typed, or
+     *   - if they didn't include a domain, an exact match of the username, or
+     *   - if they didn't include a domain, a case-insensitive
+     *     match of the username.
+     *
+     * If there is a tie for the best match, choose neither --
+     * the user needs to be more specific.
+     *
+     * @return an account name from the database, or null if we can't
+     * find a single best match.
+     */
+    private Account findIntendedAccount(String username) {
+        Account[] accounts = AccountManager.get(mContext).getAccountsByType("com.google");
+
+        // Try to figure out which account they meant if they
+        // typed only the username (and not the domain), or got
+        // the case wrong.
+
+        Account bestAccount = null;
+        int bestScore = 0;
+        for (Account a: accounts) {
+            int score = 0;
+            if (username.equals(a.name)) {
+                score = 4;
+            } else if (username.equalsIgnoreCase(a.name)) {
+                score = 3;
+            } else if (username.indexOf('@') < 0) {
+                int i = a.name.indexOf('@');
+                if (i >= 0) {
+                    String aUsername = a.name.substring(0, i);
+                    if (username.equals(aUsername)) {
+                        score = 2;
+                    } else if (username.equalsIgnoreCase(aUsername)) {
+                        score = 1;
+                    }
+                }
+            }
+            if (score > bestScore) {
+                bestAccount = a;
+                bestScore = score;
+            } else if (score == bestScore) {
+                bestAccount = null;
+            }
+        }
+        return bestAccount;
+    }
+
+    private void asyncCheckPassword() {
+        mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
+        final String login = mLogin.getText().toString();
+        final String password = mPassword.getText().toString();
+        Account account = findIntendedAccount(login);
+        if (account == null) {
+            postOnCheckPasswordResult(false);
+            return;
+        }
+        getProgressDialog().show();
+        Bundle options = new Bundle();
+        options.putString(AccountManager.KEY_PASSWORD, password);
+        AccountManager.get(mContext).confirmCredentials(account, options, null /* activity */,
+                new AccountManagerCallback<Bundle>() {
+            public void run(AccountManagerFuture<Bundle> future) {
+                try {
+                    mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
+                    final Bundle result = future.getResult();
+                    final boolean verified = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
+                    postOnCheckPasswordResult(verified);
+                } catch (OperationCanceledException e) {
+                    postOnCheckPasswordResult(false);
+                } catch (IOException e) {
+                    postOnCheckPasswordResult(false);
+                } catch (AuthenticatorException e) {
+                    postOnCheckPasswordResult(false);
+                } finally {
+                    mLogin.post(new Runnable() {
+                        public void run() {
+                            getProgressDialog().hide();
+                        }
+                    });
+                }
+            }
+        }, null /* handler */);
+    }
+
+    private Dialog getProgressDialog() {
+        if (mCheckingDialog == null) {
+            mCheckingDialog = new ProgressDialog(mContext);
+            mCheckingDialog.setMessage(
+                    mContext.getString(R.string.lockscreen_glogin_checking_password));
+            mCheckingDialog.setIndeterminate(true);
+            mCheckingDialog.setCancelable(false);
+            mCheckingDialog.getWindow().setType(
+                    WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+        }
+        return mCheckingDialog;
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/BiometricSensorUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/BiometricSensorUnlock.java
new file mode 100644
index 0000000..c38525e
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/BiometricSensorUnlock.java
@@ -0,0 +1,80 @@
+/*
+ * 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.internal.policy.impl.keyguard_obsolete;
+
+import android.view.View;
+
+interface BiometricSensorUnlock {
+    /**
+     * Initializes the view provided for the biometric unlock UI to work within.  The provided area
+     * completely covers the backup unlock mechanism.
+     * @param biometricUnlockView View provided for the biometric unlock UI.
+     */
+    public void initializeView(View biometricUnlockView);
+
+    /**
+     * Indicates whether the biometric unlock is running.  Before
+     * {@link BiometricSensorUnlock#start} is called, isRunning() returns false.  After a successful
+     * call to {@link BiometricSensorUnlock#start}, isRunning() returns true until the biometric
+     * unlock completes, {@link BiometricSensorUnlock#stop} has been called, or an error has
+     * forced the biometric unlock to stop.
+     * @return whether the biometric unlock is currently running.
+     */
+    public boolean isRunning();
+
+    /**
+     * Covers the backup unlock mechanism by showing the contents of the view initialized in
+     * {@link BiometricSensorUnlock#initializeView(View)}.  The view should disappear after the
+     * specified timeout.  If the timeout is 0, the interface shows until another event, such as
+     * calling {@link BiometricSensorUnlock#hide()}, causes it to disappear.  Called on the UI
+     * thread.
+     * @param timeoutMilliseconds Amount of time in milliseconds to display the view before
+     * disappearing.  A value of 0 means the view should remain visible.
+     */
+    public void show(long timeoutMilliseconds);
+
+    /**
+     * Uncovers the backup unlock mechanism by hiding the contents of the view initialized in
+     * {@link BiometricSensorUnlock#initializeView(View)}.
+     */
+    public void hide();
+
+    /**
+     * Binds to the biometric unlock service and starts the unlock procedure.  Called on the UI
+     * thread.
+     * @return false if it can't be started or the backup should be used.
+     */
+    public boolean start();
+
+    /**
+     * Stops the biometric unlock procedure and unbinds from the service.  Called on the UI thread.
+     * @return whether the biometric unlock was running when called.
+     */
+    public boolean stop();
+
+    /**
+     * Cleans up any resources used by the biometric unlock.
+     */
+    public void cleanUp();
+
+    /**
+     * Gets the Device Policy Manager quality of the biometric unlock sensor
+     * (e.g., PASSWORD_QUALITY_BIOMETRIC_WEAK).
+     * @return biometric unlock sensor quality, as defined by Device Policy Manager.
+     */
+    public int getQuality();
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/FaceUnlock.java
new file mode 100644
index 0000000..e4768e2
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/FaceUnlock.java
@@ -0,0 +1,554 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import com.android.internal.R;
+import com.android.internal.policy.IFaceLockCallback;
+import com.android.internal.policy.IFaceLockInterface;
+import com.android.internal.widget.LockPatternUtils;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import android.view.View;
+
+public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
+
+    private static final boolean DEBUG = false;
+    private static final String TAG = "FULLockscreen";
+
+    private final Context mContext;
+    private final LockPatternUtils mLockPatternUtils;
+    private final KeyguardUpdateMonitor mUpdateMonitor;
+
+    // TODO: is mServiceRunning needed or can we just use mIsRunning or check if mService is null?
+    private boolean mServiceRunning = false;
+    // TODO: now that the code has been restructure to do almost all operations from a handler, this
+    // lock may no longer be necessary.
+    private final Object mServiceRunningLock = new Object();
+    private IFaceLockInterface mService;
+    private boolean mBoundToService = false;
+    private View mFaceUnlockView;
+
+    private Handler mHandler;
+    private final int MSG_SHOW_FACE_UNLOCK_VIEW = 0;
+    private final int MSG_HIDE_FACE_UNLOCK_VIEW = 1;
+    private final int MSG_SERVICE_CONNECTED = 2;
+    private final int MSG_SERVICE_DISCONNECTED = 3;
+    private final int MSG_UNLOCK = 4;
+    private final int MSG_CANCEL = 5;
+    private final int MSG_REPORT_FAILED_ATTEMPT = 6;
+    //private final int MSG_EXPOSE_FALLBACK = 7;
+    private final int MSG_POKE_WAKELOCK = 8;
+
+    // TODO: This was added for the purpose of adhering to what the biometric interface expects
+    // the isRunning() function to return.  However, it is probably not necessary to have both
+    // mRunning and mServiceRunning.  I'd just rather wait to change that logic.
+    private volatile boolean mIsRunning = false;
+
+    // Long enough to stay visible while the service starts
+    // Short enough to not have to wait long for backup if service fails to start or crashes
+    // The service can take a couple of seconds to start on the first try after boot
+    private final int SERVICE_STARTUP_VIEW_TIMEOUT = 3000;
+
+    // So the user has a consistent amount of time when brought to the backup method from Face
+    // Unlock
+    private final int BACKUP_LOCK_TIMEOUT = 5000;
+
+    KeyguardScreenCallback mKeyguardScreenCallback;
+
+    /**
+     * Stores some of the structures that Face Unlock will need to access and creates the handler
+     * will be used to execute messages on the UI thread.
+     */
+    public FaceUnlock(Context context, KeyguardUpdateMonitor updateMonitor,
+            LockPatternUtils lockPatternUtils, KeyguardScreenCallback keyguardScreenCallback) {
+        mContext = context;
+        mUpdateMonitor = updateMonitor;
+        mLockPatternUtils = lockPatternUtils;
+        mKeyguardScreenCallback = keyguardScreenCallback;
+        mHandler = new Handler(this);
+    }
+
+    /**
+     * Stores and displays the view that Face Unlock is allowed to draw within.
+     * TODO: since the layout object will eventually be shared by multiple biometric unlock
+     * methods, we will have to add our other views (background, cancel button) here.
+     */
+    public void initializeView(View biometricUnlockView) {
+        Log.d(TAG, "initializeView()");
+        mFaceUnlockView = biometricUnlockView;
+    }
+
+    /**
+     * Indicates whether Face Unlock is currently running.
+     */
+    public boolean isRunning() {
+        return mIsRunning;
+    }
+
+    /**
+     * Sets the Face Unlock view to visible, hiding it after the specified amount of time.  If
+     * timeoutMillis is 0, no hide is performed.  Called on the UI thread.
+     */
+    public void show(long timeoutMillis) {
+        if (DEBUG) Log.d(TAG, "show()");
+        if (mHandler.getLooper() != Looper.myLooper()) {
+            Log.e(TAG, "show() called off of the UI thread");
+        }
+
+        removeDisplayMessages();
+        if (mFaceUnlockView != null) {
+            mFaceUnlockView.setVisibility(View.VISIBLE);
+        }
+        if (timeoutMillis > 0) {
+            mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACE_UNLOCK_VIEW, timeoutMillis);
+        }
+    }
+
+    /**
+     * Hides the Face Unlock view.
+     */
+    public void hide() {
+        if (DEBUG) Log.d(TAG, "hide()");
+        // Remove messages to prevent a delayed show message from undo-ing the hide
+        removeDisplayMessages();
+        mHandler.sendEmptyMessage(MSG_HIDE_FACE_UNLOCK_VIEW);
+    }
+
+    /**
+     * Binds to the Face Unlock service.  Face Unlock will be started when the bind completes.  The
+     * Face Unlock view is displayed to hide the backup lock while the service is starting up.
+     * Called on the UI thread.
+     */
+    public boolean start() {
+        if (DEBUG) Log.d(TAG, "start()");
+        if (mHandler.getLooper() != Looper.myLooper()) {
+            Log.e(TAG, "start() called off of the UI thread");
+        }
+
+        if (mIsRunning) {
+            Log.w(TAG, "start() called when already running");
+        }
+
+        // Show Face Unlock view, but only for a little bit so lockpattern will become visible if
+        // Face Unlock fails to start or crashes
+        // This must show before bind to guarantee that Face Unlock has a place to display
+        show(SERVICE_STARTUP_VIEW_TIMEOUT);
+        if (!mBoundToService) {
+            Log.d(TAG, "Binding to Face Unlock service");
+            mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
+                    mConnection,
+                    Context.BIND_AUTO_CREATE,
+                    mLockPatternUtils.getCurrentUser());
+            mBoundToService = true;
+        } else {
+            Log.w(TAG, "Attempt to bind to Face Unlock when already bound");
+        }
+
+        mIsRunning = true;
+        return true;
+    }
+
+    /**
+     * Stops Face Unlock and unbinds from the service.  Called on the UI thread.
+     */
+    public boolean stop() {
+        if (DEBUG) Log.d(TAG, "stop()");
+        if (mHandler.getLooper() != Looper.myLooper()) {
+            Log.e(TAG, "stop() called off of the UI thread");
+        }
+
+        boolean mWasRunning = mIsRunning;
+        stopUi();
+
+        if (mBoundToService) {
+            if (mService != null) {
+                try {
+                    mService.unregisterCallback(mFaceUnlockCallback);
+                } catch (RemoteException e) {
+                    // Not much we can do
+                }
+            }
+            Log.d(TAG, "Unbinding from Face Unlock service");
+            mContext.unbindService(mConnection);
+            mBoundToService = false;
+        } else {
+            // This is usually not an error when this happens.  Sometimes we will tell it to
+            // unbind multiple times because it's called from both onWindowFocusChanged and
+            // onDetachedFromWindow.
+            if (DEBUG) Log.d(TAG, "Attempt to unbind from Face Unlock when not bound");
+        }
+        mIsRunning = false;
+        return mWasRunning;
+    }
+
+    /**
+     * Frees up resources used by Face Unlock and stops it if it is still running.
+     */
+    public void cleanUp() {
+        if (DEBUG) Log.d(TAG, "cleanUp()");
+        if (mService != null) {
+            try {
+                mService.unregisterCallback(mFaceUnlockCallback);
+            } catch (RemoteException e) {
+                // Not much we can do
+            }
+            stopUi();
+            mService = null;
+        }
+    }
+
+    /**
+     * Returns the Device Policy Manager quality for Face Unlock, which is BIOMETRIC_WEAK.
+     */
+    public int getQuality() {
+        return DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
+    }
+
+    /**
+     * Handles messages such that everything happens on the UI thread in a deterministic order.
+     * Calls from the Face Unlock service come from binder threads.  Calls from lockscreen typically
+     * come from the UI thread.  This makes sure there are no race conditions between those calls.
+     */
+    @Override
+    public boolean handleMessage(Message msg) {
+        switch (msg.what) {
+            case MSG_SHOW_FACE_UNLOCK_VIEW:
+                handleShowFaceUnlockView();
+                break;
+            case MSG_HIDE_FACE_UNLOCK_VIEW:
+                handleHideFaceUnlockView();
+                break;
+            case MSG_SERVICE_CONNECTED:
+                handleServiceConnected();
+                break;
+            case MSG_SERVICE_DISCONNECTED:
+                handleServiceDisconnected();
+                break;
+            case MSG_UNLOCK:
+                handleUnlock();
+                break;
+            case MSG_CANCEL:
+                handleCancel();
+                break;
+            case MSG_REPORT_FAILED_ATTEMPT:
+                handleReportFailedAttempt();
+                break;
+                //case MSG_EXPOSE_FALLBACK:
+                //handleExposeFallback();
+                //break;
+            case MSG_POKE_WAKELOCK:
+                handlePokeWakelock(msg.arg1);
+                break;
+            default:
+                Log.e(TAG, "Unhandled message");
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Sets the Face Unlock view to visible, thus covering the backup lock.
+     */
+    void handleShowFaceUnlockView() {
+        if (DEBUG) Log.d(TAG, "handleShowFaceUnlockView()");
+        if (mFaceUnlockView != null) {
+            mFaceUnlockView.setVisibility(View.VISIBLE);
+        } else {
+            Log.e(TAG, "mFaceUnlockView is null in handleShowFaceUnlockView()");
+        }
+    }
+
+    /**
+     * Sets the Face Unlock view to invisible, thus exposing the backup lock.
+     */
+    void handleHideFaceUnlockView() {
+        if (DEBUG) Log.d(TAG, "handleHideFaceUnlockView()");
+        if (mFaceUnlockView != null) {
+            mFaceUnlockView.setVisibility(View.INVISIBLE);
+        } else {
+            Log.e(TAG, "mFaceUnlockView is null in handleHideFaceUnlockView()");
+        }
+    }
+
+    /**
+     * Tells the service to start its UI via an AIDL interface.  Called when the
+     * onServiceConnected() callback is received.
+     */
+    void handleServiceConnected() {
+        Log.d(TAG, "handleServiceConnected()");
+
+        // It is possible that an unbind has occurred in the time between the bind and when this
+        // function is reached.  If an unbind has already occurred, proceeding on to call startUi()
+        // can result in a fatal error.  Note that the onServiceConnected() callback is
+        // asynchronous, so this possibility would still exist if we executed this directly in
+        // onServiceConnected() rather than using a handler.
+        if (!mBoundToService) {
+            Log.d(TAG, "Dropping startUi() in handleServiceConnected() because no longer bound");
+            return;
+        }
+
+        try {
+            mService.registerCallback(mFaceUnlockCallback);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Caught exception connecting to Face Unlock: " + e.toString());
+            mService = null;
+            mBoundToService = false;
+            mIsRunning = false;
+            return;
+        }
+
+        if (mFaceUnlockView != null) {
+            IBinder windowToken = mFaceUnlockView.getWindowToken();
+            if (windowToken != null) {
+                // When switching between portrait and landscape view while Face Unlock is running,
+                // the screen will eventually go dark unless we poke the wakelock when Face Unlock
+                // is restarted.
+                mKeyguardScreenCallback.pokeWakelock();
+
+                int[] position;
+                position = new int[2];
+                mFaceUnlockView.getLocationInWindow(position);
+                startUi(windowToken, position[0], position[1], mFaceUnlockView.getWidth(),
+                        mFaceUnlockView.getHeight());
+            } else {
+                Log.e(TAG, "windowToken is null in handleServiceConnected()");
+            }
+        }
+    }
+
+    /**
+     * Called when the onServiceDisconnected() callback is received.  This should not happen during
+     * normal operation.  It indicates an error has occurred.
+     */
+    void handleServiceDisconnected() {
+        Log.e(TAG, "handleServiceDisconnected()");
+        // TODO: this lock may no longer be needed now that everything is being called from a
+        // handler
+        synchronized (mServiceRunningLock) {
+            mService = null;
+            mServiceRunning = false;
+        }
+        mBoundToService = false;
+        mIsRunning = false;
+    }
+
+    /**
+     * Stops the Face Unlock service and tells the device to grant access to the user.  Shows the
+     * Face Unlock view to keep the backup lock covered while the device unlocks.
+     */
+    void handleUnlock() {
+        if (DEBUG) Log.d(TAG, "handleUnlock()");
+        removeDisplayMessages();
+        if (mFaceUnlockView != null) {
+            mFaceUnlockView.setVisibility(View.VISIBLE);
+        } else {
+            Log.e(TAG, "mFaceUnlockView is null in handleUnlock()");
+        }
+        stop();
+        mKeyguardScreenCallback.keyguardDone(true);
+        mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
+    }
+
+    /**
+     * Stops the Face Unlock service and exposes the backup lock.
+     */
+    void handleCancel() {
+        if (DEBUG) Log.d(TAG, "handleCancel()");
+        if (mFaceUnlockView != null) {
+            mFaceUnlockView.setVisibility(View.INVISIBLE);
+        } else {
+            Log.e(TAG, "mFaceUnlockView is null in handleCancel()");
+        }
+        stop();
+        mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
+    }
+
+    /**
+     * Increments the number of failed Face Unlock attempts.
+     */
+    void handleReportFailedAttempt() {
+        if (DEBUG) Log.d(TAG, "handleReportFailedAttempt()");
+        mUpdateMonitor.reportFailedBiometricUnlockAttempt();
+    }
+
+    /**
+     * Hides the Face Unlock view to expose the backup lock.  Called when the Face Unlock service UI
+     * is started, indicating there is no need to continue displaying the underlying view because
+     * the service UI is now covering the backup lock.
+     */
+    //void handleExposeFallback() {
+    //    if (DEBUG) Log.d(TAG, "handleExposeFallback()");
+    //    if (mFaceUnlockView != null) {
+    //        mFaceUnlockView.setVisibility(View.INVISIBLE);
+    //    } else {
+    //        Log.e(TAG, "mFaceUnlockView is null in handleExposeFallback()");
+    //    }
+    //}
+
+    /**
+     * Pokes the wakelock to keep the screen alive and active for a specific amount of time.
+     */
+    void handlePokeWakelock(int millis) {
+        mKeyguardScreenCallback.pokeWakelock(millis);
+    }
+
+    /**
+     * Removes show and hide messages from the message queue.  Called to prevent delayed show/hide
+     * messages from undoing a new message.
+     */
+    private void removeDisplayMessages() {
+        mHandler.removeMessages(MSG_SHOW_FACE_UNLOCK_VIEW);
+        mHandler.removeMessages(MSG_HIDE_FACE_UNLOCK_VIEW);
+    }
+
+    /**
+     * Implements service connection methods.
+     */
+    private ServiceConnection mConnection = new ServiceConnection() {
+        /**
+         * Called when the Face Unlock service connects after calling bind().
+         */
+        @Override
+        public void onServiceConnected(ComponentName className, IBinder iservice) {
+            Log.d(TAG, "Connected to Face Unlock service");
+            mService = IFaceLockInterface.Stub.asInterface(iservice);
+            mHandler.sendEmptyMessage(MSG_SERVICE_CONNECTED);
+        }
+
+        /**
+         * Called if the Face Unlock service unexpectedly disconnects.  This indicates an error.
+         */
+        @Override
+        public void onServiceDisconnected(ComponentName className) {
+            Log.e(TAG, "Unexpected disconnect from Face Unlock service");
+            mHandler.sendEmptyMessage(MSG_SERVICE_DISCONNECTED);
+        }
+    };
+
+    /**
+     * Tells the Face Unlock service to start displaying its UI and start processing.
+     */
+    private void startUi(IBinder windowToken, int x, int y, int w, int h) {
+        if (DEBUG) Log.d(TAG, "startUi()");
+        synchronized (mServiceRunningLock) {
+            if (!mServiceRunning) {
+                Log.d(TAG, "Starting Face Unlock");
+                try {
+                    mService.startUi(windowToken, x, y, w, h,
+                            mLockPatternUtils.isBiometricWeakLivelinessEnabled());
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Caught exception starting Face Unlock: " + e.toString());
+                    return;
+                }
+                mServiceRunning = true;
+            } else {
+                Log.w(TAG, "startUi() attempted while running");
+            }
+        }
+    }
+
+    /**
+     * Tells the Face Unlock service to stop displaying its UI and stop processing.
+     */
+    private void stopUi() {
+        if (DEBUG) Log.d(TAG, "stopUi()");
+        // Note that attempting to stop Face Unlock when it's not running is not an issue.
+        // Face Unlock can return, which stops it and then we try to stop it when the
+        // screen is turned off.  That's why we check.
+        synchronized (mServiceRunningLock) {
+            if (mServiceRunning) {
+                Log.d(TAG, "Stopping Face Unlock");
+                try {
+                    mService.stopUi();
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Caught exception stopping Face Unlock: " + e.toString());
+                }
+                mServiceRunning = false;
+            } else {
+                // This is usually not an error when this happens.  Sometimes we will tell it to
+                // stop multiple times because it's called from both onWindowFocusChanged and
+                // onDetachedFromWindow.
+                if (DEBUG) Log.d(TAG, "stopUi() attempted while not running");
+            }
+        }
+    }
+
+    /**
+     * Implements the AIDL biometric unlock service callback interface.
+     */
+    private final IFaceLockCallback mFaceUnlockCallback = new IFaceLockCallback.Stub() {
+        /**
+         * Called when Face Unlock wants to grant access to the user.
+         */
+        @Override
+        public void unlock() {
+            if (DEBUG) Log.d(TAG, "unlock()");
+            mHandler.sendEmptyMessage(MSG_UNLOCK);
+        }
+
+        /**
+         * Called when Face Unlock wants to go to the backup.
+         */
+        @Override
+        public void cancel() {
+            if (DEBUG) Log.d(TAG, "cancel()");
+            mHandler.sendEmptyMessage(MSG_CANCEL);
+        }
+
+        /**
+         * Called when Face Unlock wants to increment the number of failed attempts.
+         */
+        @Override
+        public void reportFailedAttempt() {
+            if (DEBUG) Log.d(TAG, "reportFailedAttempt()");
+            mHandler.sendEmptyMessage(MSG_REPORT_FAILED_ATTEMPT);
+        }
+
+        /**
+         * Called when the Face Unlock service starts displaying the UI, indicating that the backup
+         * unlock can be exposed because the Face Unlock service is now covering the backup with its
+         * UI.
+         **/
+        //@Override
+        //public void exposeFallback() {
+        //    if (DEBUG) Log.d(TAG, "exposeFallback()");
+        //    mHandler.sendEmptyMessage(MSG_EXPOSE_FALLBACK);
+        //}
+
+        /**
+         * Called when Face Unlock wants to keep the screen alive and active for a specific amount
+         * of time.
+         */
+        public void pokeWakelock(int millis) {
+            if (DEBUG) Log.d(TAG, "pokeWakelock() for " + millis + "ms");
+            Message message = mHandler.obtainMessage(MSG_POKE_WAKELOCK, millis, -1);
+            mHandler.sendMessage(message);
+        }
+
+    };
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreen.java
new file mode 100644
index 0000000..ba5b7ff
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreen.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+/**
+ * Common interface of each {@link android.view.View} that is a screen of
+ * {@link LockPatternKeyguardView}.
+ */
+public interface KeyguardScreen {
+
+    /**
+     * Return true if your view needs input, so should allow the soft
+     * keyboard to be displayed.
+     */
+    boolean needsInput();
+
+    /**
+     * This screen is no longer in front of the user.
+     */
+    void onPause();
+
+    /**
+     * This screen is going to be in front of the user.
+     */
+    void onResume();
+
+    /**
+     * This view is going away; a hook to do cleanup.
+     */
+    void cleanUp();
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreenCallback.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreenCallback.java
new file mode 100644
index 0000000..be505a1
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreenCallback.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import android.content.res.Configuration;
+
+/**
+ * Within a keyguard, there may be several screens that need a callback
+ * to the host keyguard view.
+ */
+public interface KeyguardScreenCallback extends KeyguardViewCallback {
+
+    /**
+     * Transition to the lock screen.
+     */
+    void goToLockScreen();
+
+    /**
+     * Transition to the unlock screen.
+     */
+    void goToUnlockScreen();
+
+    /**
+     * The user reported that they forgot their pattern (or not, when they want to back out of the
+     * forgot pattern screen).
+     *
+     * @param isForgotten True if the user hit the forgot pattern, false if they want to back out
+     *        of the account screen.
+     */
+    void forgotPattern(boolean isForgotten);
+
+    /**
+     * @return Whether the keyguard requires some sort of PIN.
+     */
+    boolean isSecure();
+
+    /**
+     * @return Whether we are in a mode where we only want to verify the
+     *   user can get past the keyguard.
+     */
+    boolean isVerifyUnlockOnly();
+
+    /**
+     * Stay on me, but recreate me (so I can use a different layout).
+     */
+    void recreateMe(Configuration config);
+
+    /**
+     * Take action to send an emergency call.
+     */
+    void takeEmergencyCallAction();
+
+    /**
+     * Report that the user had a failed attempt to unlock with password or pattern.
+     */
+    void reportFailedUnlockAttempt();
+
+    /**
+     * Report that the user successfully entered their password or pattern.
+     */
+    void reportSuccessfulUnlockAttempt();
+
+    /**
+     * Report whether we there's another way to unlock the device.
+     * @return true
+     */
+    boolean doesFallbackUnlockScreenExist();
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardStatusViewManager.java
new file mode 100644
index 0000000..b6ffde0
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardStatusViewManager.java
@@ -0,0 +1,682 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import com.android.internal.R;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.widget.DigitalClock;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.TransportControlView;
+
+import java.util.ArrayList;
+import java.util.Date;
+
+import libcore.util.MutableInt;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.text.format.DateFormat;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+
+/***
+ * Manages a number of views inside of LockScreen layouts. See below for a list of widgets
+ *
+ */
+class KeyguardStatusViewManager implements OnClickListener {
+    private static final boolean DEBUG = false;
+    private static final String TAG = "KeyguardStatusView";
+
+    public static final int LOCK_ICON = 0; // R.drawable.ic_lock_idle_lock;
+    public static final int ALARM_ICON = R.drawable.ic_lock_idle_alarm;
+    public static final int CHARGING_ICON = 0; //R.drawable.ic_lock_idle_charging;
+    public static final int BATTERY_LOW_ICON = 0; //R.drawable.ic_lock_idle_low_battery;
+    private static final long INSTRUCTION_RESET_DELAY = 2000; // time until instruction text resets
+
+    private static final int INSTRUCTION_TEXT = 10;
+    private static final int CARRIER_TEXT = 11;
+    private static final int CARRIER_HELP_TEXT = 12;
+    private static final int HELP_MESSAGE_TEXT = 13;
+    private static final int OWNER_INFO = 14;
+    private static final int BATTERY_INFO = 15;
+
+    private StatusMode mStatus;
+    private String mDateFormatString;
+    private TransientTextManager mTransientTextManager;
+
+    // Views that this class controls.
+    // NOTE: These may be null in some LockScreen screens and should protect from NPE
+    private TextView mCarrierView;
+    private TextView mDateView;
+    private TextView mStatus1View;
+    private TextView mOwnerInfoView;
+    private TextView mAlarmStatusView;
+    private TransportControlView mTransportView;
+
+    // Top-level container view for above views
+    private View mContainer;
+
+    // are we showing battery information?
+    private boolean mShowingBatteryInfo = false;
+
+    // last known plugged in state
+    private boolean mPluggedIn = false;
+
+    // last known battery level
+    private int mBatteryLevel = 100;
+
+    // last known SIM state
+    protected IccCardConstants.State mSimState;
+
+    private LockPatternUtils mLockPatternUtils;
+    private KeyguardUpdateMonitor mUpdateMonitor;
+    private Button mEmergencyCallButton;
+    private boolean mEmergencyButtonEnabledBecauseSimLocked;
+
+    // Shadowed text values
+    private CharSequence mCarrierText;
+    private CharSequence mCarrierHelpText;
+    private String mHelpMessageText;
+    private String mInstructionText;
+    private CharSequence mOwnerInfoText;
+    private boolean mShowingStatus;
+    private KeyguardScreenCallback mCallback;
+    private final boolean mEmergencyCallButtonEnabledInScreen;
+    private CharSequence mPlmn;
+    private CharSequence mSpn;
+    protected int mPhoneState;
+    private DigitalClock mDigitalClock;
+    protected boolean mBatteryCharged;
+    protected boolean mBatteryIsLow;
+
+    private class TransientTextManager {
+        private TextView mTextView;
+        private class Data {
+            final int icon;
+            final CharSequence text;
+            Data(CharSequence t, int i) {
+                text = t;
+                icon = i;
+            }
+        };
+        private ArrayList<Data> mMessages = new ArrayList<Data>(5);
+
+        TransientTextManager(TextView textView) {
+            mTextView = textView;
+        }
+
+        /* Show given message with icon for up to duration ms. Newer messages override older ones.
+         * The most recent message with the longest duration is shown as messages expire until
+         * nothing is left, in which case the text/icon is defined by a call to
+         * getAltTextMessage() */
+        void post(final CharSequence message, final int icon, long duration) {
+            if (mTextView == null) {
+                return;
+            }
+            mTextView.setText(message);
+            mTextView.setCompoundDrawablesWithIntrinsicBounds(icon, 0, 0, 0);
+            final Data data = new Data(message, icon);
+            mContainer.postDelayed(new Runnable() {
+                public void run() {
+                    mMessages.remove(data);
+                    int last = mMessages.size() - 1;
+                    final CharSequence lastText;
+                    final int lastIcon;
+                    if (last > 0) {
+                        final Data oldData = mMessages.get(last);
+                        lastText = oldData.text;
+                        lastIcon = oldData.icon;
+                    } else {
+                        final MutableInt tmpIcon = new MutableInt(0);
+                        lastText = getAltTextMessage(tmpIcon);
+                        lastIcon = tmpIcon.value;
+                    }
+                    mTextView.setText(lastText);
+                    mTextView.setCompoundDrawablesWithIntrinsicBounds(lastIcon, 0, 0, 0);
+                }
+            }, duration);
+        }
+    };
+
+    /**
+     *
+     * @param view the containing view of all widgets
+     * @param updateMonitor the update monitor to use
+     * @param lockPatternUtils lock pattern util object
+     * @param callback used to invoke emergency dialer
+     * @param emergencyButtonEnabledInScreen whether emergency button is enabled by default
+     */
+    public KeyguardStatusViewManager(View view, KeyguardUpdateMonitor updateMonitor,
+                LockPatternUtils lockPatternUtils, KeyguardScreenCallback callback,
+                boolean emergencyButtonEnabledInScreen) {
+        if (DEBUG) Log.v(TAG, "KeyguardStatusViewManager()");
+        mContainer = view;
+        mDateFormatString = getContext().getString(R.string.abbrev_wday_month_day_no_year);
+        mLockPatternUtils = lockPatternUtils;
+        mUpdateMonitor = updateMonitor;
+        mCallback = callback;
+
+        mCarrierView = (TextView) findViewById(R.id.carrier);
+        mDateView = (TextView) findViewById(R.id.date);
+        mStatus1View = (TextView) findViewById(R.id.status1);
+        mAlarmStatusView = (TextView) findViewById(R.id.alarm_status);
+        mOwnerInfoView = (TextView) findViewById(R.id.owner_info);
+        mTransportView = (TransportControlView) findViewById(R.id.transport);
+        mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
+        mEmergencyCallButtonEnabledInScreen = emergencyButtonEnabledInScreen;
+        mDigitalClock = (DigitalClock) findViewById(R.id.time);
+
+        // Hide transport control view until we know we need to show it.
+        if (mTransportView != null) {
+            mTransportView.setVisibility(View.GONE);
+        }
+
+        if (mEmergencyCallButton != null) {
+            mEmergencyCallButton.setText(R.string.lockscreen_emergency_call);
+            mEmergencyCallButton.setOnClickListener(this);
+            mEmergencyCallButton.setFocusable(false); // touch only!
+        }
+
+        mTransientTextManager = new TransientTextManager(mCarrierView);
+
+        // Registering this callback immediately updates the battery state, among other things.
+        mUpdateMonitor.registerCallback(mInfoCallback);
+
+        resetStatusInfo();
+        refreshDate();
+        updateOwnerInfo();
+
+        // Required to get Marquee to work.
+        final View scrollableViews[] = { mCarrierView, mDateView, mStatus1View, mOwnerInfoView,
+                mAlarmStatusView };
+        for (View v : scrollableViews) {
+            if (v != null) {
+                v.setSelected(true);
+            }
+        }
+    }
+
+    private boolean inWidgetMode() {
+        return mTransportView != null && mTransportView.getVisibility() == View.VISIBLE;
+    }
+
+    void setInstructionText(String string) {
+        mInstructionText = string;
+        update(INSTRUCTION_TEXT, string);
+    }
+
+    void setCarrierText(CharSequence string) {
+        mCarrierText = string;
+        update(CARRIER_TEXT, string);
+    }
+
+    void setOwnerInfo(CharSequence string) {
+        mOwnerInfoText = string;
+        update(OWNER_INFO, string);
+    }
+
+    /**
+     * Sets the carrier help text message, if view is present. Carrier help text messages are
+     * typically for help dealing with SIMS and connectivity.
+     *
+     * @param resId resource id of the message
+     */
+    public void setCarrierHelpText(int resId) {
+        mCarrierHelpText = getText(resId);
+        update(CARRIER_HELP_TEXT, mCarrierHelpText);
+    }
+
+    private CharSequence getText(int resId) {
+        return resId == 0 ? null : getContext().getText(resId);
+    }
+
+    /**
+     * Unlock help message.  This is typically for help with unlock widgets, e.g. "wrong password"
+     * or "try again."
+     *
+     * @param textResId
+     * @param lockIcon
+     */
+    public void setHelpMessage(int textResId, int lockIcon) {
+        final CharSequence tmp = getText(textResId);
+        mHelpMessageText = tmp == null ? null : tmp.toString();
+        update(HELP_MESSAGE_TEXT, mHelpMessageText);
+    }
+
+    private void update(int what, CharSequence string) {
+        if (inWidgetMode()) {
+            if (DEBUG) Log.v(TAG, "inWidgetMode() is true");
+            // Use Transient text for messages shown while widget is shown.
+            switch (what) {
+                case INSTRUCTION_TEXT:
+                case CARRIER_HELP_TEXT:
+                case HELP_MESSAGE_TEXT:
+                case BATTERY_INFO:
+                    mTransientTextManager.post(string, 0, INSTRUCTION_RESET_DELAY);
+                    break;
+
+                case OWNER_INFO:
+                case CARRIER_TEXT:
+                default:
+                    if (DEBUG) Log.w(TAG, "Not showing message id " + what + ", str=" + string);
+            }
+        } else {
+            updateStatusLines(mShowingStatus);
+        }
+    }
+
+    public void onPause() {
+        if (DEBUG) Log.v(TAG, "onPause()");
+        mUpdateMonitor.removeCallback(mInfoCallback);
+    }
+
+    /** {@inheritDoc} */
+    public void onResume() {
+        if (DEBUG) Log.v(TAG, "onResume()");
+
+        // First update the clock, if present.
+        if (mDigitalClock != null) {
+            mDigitalClock.updateTime();
+        }
+
+        mUpdateMonitor.registerCallback(mInfoCallback);
+        resetStatusInfo();
+        // Issue the biometric unlock failure message in a centralized place
+        // TODO: we either need to make the Face Unlock multiple failures string a more general
+        // 'biometric unlock' or have each biometric unlock handle this on their own.
+        if (mUpdateMonitor.getMaxBiometricUnlockAttemptsReached()) {
+            setInstructionText(getContext().getString(R.string.faceunlock_multiple_failures));
+        }
+    }
+
+    void resetStatusInfo() {
+        mInstructionText = null;
+        updateStatusLines(true);
+    }
+
+    /**
+     * Update the status lines based on these rules:
+     * AlarmStatus: Alarm state always gets it's own line.
+     * Status1 is shared between help, battery status and generic unlock instructions,
+     * prioritized in that order.
+     * @param showStatusLines status lines are shown if true
+     */
+    void updateStatusLines(boolean showStatusLines) {
+        if (DEBUG) Log.v(TAG, "updateStatusLines(" + showStatusLines + ")");
+        mShowingStatus = showStatusLines;
+        updateAlarmInfo();
+        updateOwnerInfo();
+        updateStatus1();
+        updateCarrierText();
+    }
+
+    private void updateAlarmInfo() {
+        if (mAlarmStatusView != null) {
+            String nextAlarm = mLockPatternUtils.getNextAlarm();
+            boolean showAlarm = mShowingStatus && !TextUtils.isEmpty(nextAlarm);
+            mAlarmStatusView.setText(nextAlarm);
+            mAlarmStatusView.setCompoundDrawablesWithIntrinsicBounds(ALARM_ICON, 0, 0, 0);
+            mAlarmStatusView.setVisibility(showAlarm ? View.VISIBLE : View.GONE);
+        }
+    }
+
+    private void updateOwnerInfo() {
+        final ContentResolver res = getContext().getContentResolver();
+        final boolean ownerInfoEnabled = Settings.Secure.getInt(res,
+                Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 1) != 0;
+        mOwnerInfoText = ownerInfoEnabled ?
+                Settings.Secure.getString(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO) : null;
+        if (mOwnerInfoView != null) {
+            mOwnerInfoView.setText(mOwnerInfoText);
+            mOwnerInfoView.setVisibility(TextUtils.isEmpty(mOwnerInfoText) ? View.GONE:View.VISIBLE);
+        }
+    }
+
+    private void updateStatus1() {
+        if (mStatus1View != null) {
+            MutableInt icon = new MutableInt(0);
+            CharSequence string = getPriorityTextMessage(icon);
+            mStatus1View.setText(string);
+            mStatus1View.setCompoundDrawablesWithIntrinsicBounds(icon.value, 0, 0, 0);
+            mStatus1View.setVisibility(mShowingStatus ? View.VISIBLE : View.INVISIBLE);
+        }
+    }
+
+    private void updateCarrierText() {
+        if (!inWidgetMode() && mCarrierView != null) {
+            mCarrierView.setText(mCarrierText);
+        }
+    }
+
+    private CharSequence getAltTextMessage(MutableInt icon) {
+        // If we have replaced the status area with a single widget, then this code
+        // prioritizes what to show in that space when all transient messages are gone.
+        CharSequence string = null;
+        if (mShowingBatteryInfo) {
+            // Battery status
+            if (mPluggedIn) {
+                // Charging, charged or waiting to charge.
+                string = getContext().getString(mBatteryCharged ? R.string.lockscreen_charged
+                        :R.string.lockscreen_plugged_in, mBatteryLevel);
+                icon.value = CHARGING_ICON;
+            } else if (mBatteryIsLow) {
+                // Battery is low
+                string = getContext().getString(R.string.lockscreen_low_battery);
+                icon.value = BATTERY_LOW_ICON;
+            }
+        } else {
+            string = mCarrierText;
+        }
+        return string;
+    }
+
+    private CharSequence getPriorityTextMessage(MutableInt icon) {
+        CharSequence string = null;
+        if (!TextUtils.isEmpty(mInstructionText)) {
+            // Instructions only
+            string = mInstructionText;
+            icon.value = LOCK_ICON;
+        } else if (mShowingBatteryInfo) {
+            // Battery status
+            if (mPluggedIn) {
+                // Charging, charged or waiting to charge.
+                string = getContext().getString(mBatteryCharged ? R.string.lockscreen_charged
+                        :R.string.lockscreen_plugged_in, mBatteryLevel);
+                icon.value = CHARGING_ICON;
+            } else if (mBatteryIsLow) {
+                // Battery is low
+                string = getContext().getString(R.string.lockscreen_low_battery);
+                icon.value = BATTERY_LOW_ICON;
+            }
+        } else if (!inWidgetMode() && mOwnerInfoView == null && mOwnerInfoText != null) {
+            // OwnerInfo shows in status if we don't have a dedicated widget
+            string = mOwnerInfoText;
+        }
+        return string;
+    }
+
+    void refreshDate() {
+        if (mDateView != null) {
+            mDateView.setText(DateFormat.format(mDateFormatString, new Date()));
+        }
+    }
+
+    /**
+     * Determine the current status of the lock screen given the sim state and other stuff.
+     */
+    public StatusMode getStatusForIccState(IccCardConstants.State simState) {
+        // Since reading the SIM may take a while, we assume it is present until told otherwise.
+        if (simState == null) {
+            return StatusMode.Normal;
+        }
+
+        final boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned()
+                && (simState == IccCardConstants.State.ABSENT ||
+                        simState == IccCardConstants.State.PERM_DISABLED));
+
+        // Assume we're NETWORK_LOCKED if not provisioned
+        simState = missingAndNotProvisioned ? IccCardConstants.State.NETWORK_LOCKED : simState;
+        switch (simState) {
+            case ABSENT:
+                return StatusMode.SimMissing;
+            case NETWORK_LOCKED:
+                return StatusMode.SimMissingLocked;
+            case NOT_READY:
+                return StatusMode.SimMissing;
+            case PIN_REQUIRED:
+                return StatusMode.SimLocked;
+            case PUK_REQUIRED:
+                return StatusMode.SimPukLocked;
+            case READY:
+                return StatusMode.Normal;
+            case PERM_DISABLED:
+                return StatusMode.SimPermDisabled;
+            case UNKNOWN:
+                return StatusMode.SimMissing;
+        }
+        return StatusMode.SimMissing;
+    }
+
+    private Context getContext() {
+        return mContainer.getContext();
+    }
+
+    /**
+     * Update carrier text, carrier help and emergency button to match the current status based
+     * on SIM state.
+     *
+     * @param simState
+     */
+    private void updateCarrierStateWithSimStatus(IccCardConstants.State simState) {
+        if (DEBUG) Log.d(TAG, "updateCarrierTextWithSimStatus(), simState = " + simState);
+
+        CharSequence carrierText = null;
+        int carrierHelpTextId = 0;
+        mEmergencyButtonEnabledBecauseSimLocked = false;
+        mStatus = getStatusForIccState(simState);
+        mSimState = simState;
+        switch (mStatus) {
+            case Normal:
+                carrierText = makeCarierString(mPlmn, mSpn);
+                break;
+
+            case NetworkLocked:
+                carrierText = makeCarrierStringOnEmergencyCapable(
+                        getContext().getText(R.string.lockscreen_network_locked_message),
+                        mPlmn);
+                carrierHelpTextId = R.string.lockscreen_instructions_when_pattern_disabled;
+                break;
+
+            case SimMissing:
+                // Shows "No SIM card | Emergency calls only" on devices that are voice-capable.
+                // This depends on mPlmn containing the text "Emergency calls only" when the radio
+                // has some connectivity. Otherwise, it should be null or empty and just show
+                // "No SIM card"
+                carrierText =  makeCarrierStringOnEmergencyCapable(
+                        getContext().getText(R.string.lockscreen_missing_sim_message_short),
+                        mPlmn);
+                carrierHelpTextId = R.string.lockscreen_missing_sim_instructions_long;
+                break;
+
+            case SimPermDisabled:
+                carrierText = getContext().getText(
+                        R.string.lockscreen_permanent_disabled_sim_message_short);
+                carrierHelpTextId = R.string.lockscreen_permanent_disabled_sim_instructions;
+                mEmergencyButtonEnabledBecauseSimLocked = true;
+                break;
+
+            case SimMissingLocked:
+                carrierText =  makeCarrierStringOnEmergencyCapable(
+                        getContext().getText(R.string.lockscreen_missing_sim_message_short),
+                        mPlmn);
+                carrierHelpTextId = R.string.lockscreen_missing_sim_instructions;
+                mEmergencyButtonEnabledBecauseSimLocked = true;
+                break;
+
+            case SimLocked:
+                carrierText = makeCarrierStringOnEmergencyCapable(
+                        getContext().getText(R.string.lockscreen_sim_locked_message),
+                        mPlmn);
+                mEmergencyButtonEnabledBecauseSimLocked = true;
+                break;
+
+            case SimPukLocked:
+                carrierText = makeCarrierStringOnEmergencyCapable(
+                        getContext().getText(R.string.lockscreen_sim_puk_locked_message),
+                        mPlmn);
+                if (!mLockPatternUtils.isPukUnlockScreenEnable()) {
+                    // This means we're showing the PUK unlock screen
+                    mEmergencyButtonEnabledBecauseSimLocked = true;
+                }
+                break;
+        }
+
+        setCarrierText(carrierText);
+        setCarrierHelpText(carrierHelpTextId);
+        updateEmergencyCallButtonState(mPhoneState);
+    }
+
+
+    /*
+     * Add emergencyCallMessage to carrier string only if phone supports emergency calls.
+     */
+    private CharSequence makeCarrierStringOnEmergencyCapable(
+            CharSequence simMessage, CharSequence emergencyCallMessage) {
+        if (mLockPatternUtils.isEmergencyCallCapable()) {
+            return makeCarierString(simMessage, emergencyCallMessage);
+        }
+        return simMessage;
+    }
+
+    private View findViewById(int id) {
+        return mContainer.findViewById(id);
+    }
+
+    /**
+     * The status of this lock screen. Primarily used for widgets on LockScreen.
+     */
+    enum StatusMode {
+        /**
+         * Normal case (sim card present, it's not locked)
+         */
+        Normal(true),
+
+        /**
+         * The sim card is 'network locked'.
+         */
+        NetworkLocked(true),
+
+        /**
+         * The sim card is missing.
+         */
+        SimMissing(false),
+
+        /**
+         * The sim card is missing, and this is the device isn't provisioned, so we don't let
+         * them get past the screen.
+         */
+        SimMissingLocked(false),
+
+        /**
+         * The sim card is PUK locked, meaning they've entered the wrong sim unlock code too many
+         * times.
+         */
+        SimPukLocked(false),
+
+        /**
+         * The sim card is locked.
+         */
+        SimLocked(true),
+
+        /**
+         * The sim card is permanently disabled due to puk unlock failure
+         */
+        SimPermDisabled(false);
+
+        private final boolean mShowStatusLines;
+
+        StatusMode(boolean mShowStatusLines) {
+            this.mShowStatusLines = mShowStatusLines;
+        }
+
+        /**
+         * @return Whether the status lines (battery level and / or next alarm) are shown while
+         *         in this state.  Mostly dictated by whether this is room for them.
+         */
+        public boolean shouldShowStatusLines() {
+            return mShowStatusLines;
+        }
+    }
+
+    private void updateEmergencyCallButtonState(int phoneState) {
+        if (mEmergencyCallButton != null) {
+            boolean enabledBecauseSimLocked =
+                    mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked()
+                    && mEmergencyButtonEnabledBecauseSimLocked;
+            boolean shown = mEmergencyCallButtonEnabledInScreen || enabledBecauseSimLocked;
+            mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton,
+                    phoneState, shown);
+        }
+    }
+
+    private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
+
+        public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) {
+            mShowingBatteryInfo = status.isPluggedIn() || status.isBatteryLow();
+            mPluggedIn = status.isPluggedIn();
+            mBatteryLevel = status.level;
+            mBatteryCharged = status.isCharged();
+            mBatteryIsLow = status.isBatteryLow();
+            final MutableInt tmpIcon = new MutableInt(0);
+            update(BATTERY_INFO, getAltTextMessage(tmpIcon));
+        }
+
+        @Override
+        public void onTimeChanged() {
+            refreshDate();
+        }
+
+        @Override
+        public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
+            mPlmn = plmn;
+            mSpn = spn;
+            updateCarrierStateWithSimStatus(mSimState);
+        }
+
+        @Override
+        public void onPhoneStateChanged(int phoneState) {
+            mPhoneState = phoneState;
+            updateEmergencyCallButtonState(phoneState);
+        }
+
+        @Override
+        public void onSimStateChanged(IccCardConstants.State simState) {
+            updateCarrierStateWithSimStatus(simState);
+        }
+    };
+
+    public void onClick(View v) {
+        if (v == mEmergencyCallButton) {
+            mCallback.takeEmergencyCallAction();
+        }
+    }
+
+    /**
+     * Performs concentenation of PLMN/SPN
+     * @param plmn
+     * @param spn
+     * @return
+     */
+    private static CharSequence makeCarierString(CharSequence plmn, CharSequence spn) {
+        final boolean plmnValid = !TextUtils.isEmpty(plmn);
+        final boolean spnValid = !TextUtils.isEmpty(spn);
+        if (plmnValid && spnValid) {
+            return plmn + "|" + spn;
+        } else if (plmnValid) {
+            return plmn;
+        } else if (spnValid) {
+            return spn;
+        } else {
+            return "";
+        }
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardUpdateMonitor.java
new file mode 100644
index 0000000..67dc8a7
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardUpdateMonitor.java
@@ -0,0 +1,642 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import static android.os.BatteryManager.BATTERY_STATUS_FULL;
+import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
+import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
+import static android.os.BatteryManager.EXTRA_STATUS;
+import static android.os.BatteryManager.EXTRA_PLUGGED;
+import static android.os.BatteryManager.EXTRA_LEVEL;
+import static android.os.BatteryManager.EXTRA_HEALTH;
+import android.media.AudioManager;
+import android.os.BatteryManager;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.Settings;
+
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.TelephonyIntents;
+
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import com.android.internal.R;
+import com.google.android.collect.Lists;
+
+import java.util.ArrayList;
+
+/**
+ * Watches for updates that may be interesting to the keyguard, and provides
+ * the up to date information as well as a registration for callbacks that care
+ * to be updated.
+ *
+ * Note: under time crunch, this has been extended to include some stuff that
+ * doesn't really belong here.  see {@link #handleBatteryUpdate} where it shutdowns
+ * the device, and {@link #getFailedAttempts()}, {@link #reportFailedAttempt()}
+ * and {@link #clearFailedAttempts()}.  Maybe we should rename this 'KeyguardContext'...
+ */
+public class KeyguardUpdateMonitor {
+
+    private static final String TAG = "KeyguardUpdateMonitor";
+    private static final boolean DEBUG = false;
+    private static final boolean DEBUG_SIM_STATES = DEBUG || false;
+    private static final int FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 3;
+    private static final int LOW_BATTERY_THRESHOLD = 20;
+
+    // Callback messages
+    private static final int MSG_TIME_UPDATE = 301;
+    private static final int MSG_BATTERY_UPDATE = 302;
+    private static final int MSG_CARRIER_INFO_UPDATE = 303;
+    private static final int MSG_SIM_STATE_CHANGE = 304;
+    private static final int MSG_RINGER_MODE_CHANGED = 305;
+    private static final int MSG_PHONE_STATE_CHANGED = 306;
+    private static final int MSG_CLOCK_VISIBILITY_CHANGED = 307;
+    private static final int MSG_DEVICE_PROVISIONED = 308;
+    protected static final int MSG_DPM_STATE_CHANGED = 309;
+    protected static final int MSG_USER_SWITCHED = 310;
+    protected static final int MSG_USER_REMOVED = 311;
+
+    private final Context mContext;
+
+    // Telephony state
+    private IccCardConstants.State mSimState = IccCardConstants.State.READY;
+    private CharSequence mTelephonyPlmn;
+    private CharSequence mTelephonySpn;
+    private int mRingMode;
+    private int mPhoneState;
+
+    private boolean mDeviceProvisioned;
+
+    private BatteryStatus mBatteryStatus;
+
+    private int mFailedAttempts = 0;
+    private int mFailedBiometricUnlockAttempts = 0;
+
+    private boolean mClockVisible;
+
+    private ArrayList<KeyguardUpdateMonitorCallback> mCallbacks = Lists.newArrayList();
+    private ContentObserver mContentObserver;
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_TIME_UPDATE:
+                    handleTimeUpdate();
+                    break;
+                case MSG_BATTERY_UPDATE:
+                    handleBatteryUpdate((BatteryStatus) msg.obj);
+                    break;
+                case MSG_CARRIER_INFO_UPDATE:
+                    handleCarrierInfoUpdate();
+                    break;
+                case MSG_SIM_STATE_CHANGE:
+                    handleSimStateChange((SimArgs) msg.obj);
+                    break;
+                case MSG_RINGER_MODE_CHANGED:
+                    handleRingerModeChange(msg.arg1);
+                    break;
+                case MSG_PHONE_STATE_CHANGED:
+                    handlePhoneStateChanged((String)msg.obj);
+                    break;
+                case MSG_CLOCK_VISIBILITY_CHANGED:
+                    handleClockVisibilityChanged();
+                    break;
+                case MSG_DEVICE_PROVISIONED:
+                    handleDeviceProvisioned();
+                    break;
+                case MSG_DPM_STATE_CHANGED:
+                    handleDevicePolicyManagerStateChanged();
+                    break;
+                case MSG_USER_SWITCHED:
+                    handleUserSwitched(msg.arg1);
+                    break;
+                case MSG_USER_REMOVED:
+                    handleUserRemoved(msg.arg1);
+                    break;
+            }
+        }
+    };
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            if (DEBUG) Log.d(TAG, "received broadcast " + action);
+
+            if (Intent.ACTION_TIME_TICK.equals(action)
+                    || Intent.ACTION_TIME_CHANGED.equals(action)
+                    || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_TIME_UPDATE));
+            } else if (TelephonyIntents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
+                mTelephonyPlmn = getTelephonyPlmnFrom(intent);
+                mTelephonySpn = getTelephonySpnFrom(intent);
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_CARRIER_INFO_UPDATE));
+            } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
+                final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
+                final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
+                final int level = intent.getIntExtra(EXTRA_LEVEL, 0);
+                final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
+                final Message msg = mHandler.obtainMessage(
+                        MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health));
+                mHandler.sendMessage(msg);
+            } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
+                if (DEBUG_SIM_STATES) {
+                    Log.v(TAG, "action " + action + " state" +
+                        intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE));
+                }
+                mHandler.sendMessage(mHandler.obtainMessage(
+                        MSG_SIM_STATE_CHANGE, SimArgs.fromIntent(intent)));
+            } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
+                        intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
+            } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
+                String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
+            } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
+                    .equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_DPM_STATE_CHANGED));
+            } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED,
+                        intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
+            } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_REMOVED,
+                        intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
+            }
+        }
+    };
+
+    /**
+     * When we receive a
+     * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
+     * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange},
+     * we need a single object to pass to the handler.  This class helps decode
+     * the intent and provide a {@link SimCard.State} result.
+     */
+    private static class SimArgs {
+        public final IccCardConstants.State simState;
+
+        SimArgs(IccCardConstants.State state) {
+            simState = state;
+        }
+
+        static SimArgs fromIntent(Intent intent) {
+            IccCardConstants.State state;
+            if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
+                throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
+            }
+            String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
+            if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
+                final String absentReason = intent
+                    .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
+
+                if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
+                        absentReason)) {
+                    state = IccCardConstants.State.PERM_DISABLED;
+                } else {
+                    state = IccCardConstants.State.ABSENT;
+                }
+            } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
+                state = IccCardConstants.State.READY;
+            } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+                final String lockedReason = intent
+                        .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
+                if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
+                    state = IccCardConstants.State.PIN_REQUIRED;
+                } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
+                    state = IccCardConstants.State.PUK_REQUIRED;
+                } else {
+                    state = IccCardConstants.State.UNKNOWN;
+                }
+            } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
+                state = IccCardConstants.State.NETWORK_LOCKED;
+            } else {
+                state = IccCardConstants.State.UNKNOWN;
+            }
+            return new SimArgs(state);
+        }
+
+        public String toString() {
+            return simState.toString();
+        }
+    }
+
+    /* package */ static class BatteryStatus {
+        public final int status;
+        public final int level;
+        public final int plugged;
+        public final int health;
+        public BatteryStatus(int status, int level, int plugged, int health) {
+            this.status = status;
+            this.level = level;
+            this.plugged = plugged;
+            this.health = health;
+        }
+
+        /**
+         * Determine whether the device is plugged in (USB or power).
+         * @return true if the device is plugged in.
+         */
+        boolean isPluggedIn() {
+            return plugged == BatteryManager.BATTERY_PLUGGED_AC
+                    || plugged == BatteryManager.BATTERY_PLUGGED_USB
+                    || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
+        }
+
+        /**
+         * Whether or not the device is charged. Note that some devices never return 100% for
+         * battery level, so this allows either battery level or status to determine if the
+         * battery is charged.
+         * @return true if the device is charged
+         */
+        public boolean isCharged() {
+            return status == BATTERY_STATUS_FULL || level >= 100;
+        }
+
+        /**
+         * Whether battery is low and needs to be charged.
+         * @return true if battery is low
+         */
+        public boolean isBatteryLow() {
+            return level < LOW_BATTERY_THRESHOLD;
+        }
+
+    }
+
+    public KeyguardUpdateMonitor(Context context) {
+        mContext = context;
+
+        mDeviceProvisioned = Settings.Global.getInt(
+                mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+
+        // Since device can't be un-provisioned, we only need to register a content observer
+        // to update mDeviceProvisioned when we are...
+        if (!mDeviceProvisioned) {
+            watchForDeviceProvisioning();
+        }
+
+        // Take a guess at initial SIM state, battery status and PLMN until we get an update
+        mSimState = IccCardConstants.State.NOT_READY;
+        mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0);
+        mTelephonyPlmn = getDefaultPlmn();
+
+        // Watch for interesting updates
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_TIME_TICK);
+        filter.addAction(Intent.ACTION_TIME_CHANGED);
+        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
+        filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
+        filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
+        filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+        filter.addAction(Intent.ACTION_USER_SWITCHED);
+        filter.addAction(Intent.ACTION_USER_REMOVED);
+        context.registerReceiver(mBroadcastReceiver, filter);
+    }
+
+    private void watchForDeviceProvisioning() {
+        mContentObserver = new ContentObserver(mHandler) {
+            @Override
+            public void onChange(boolean selfChange) {
+                super.onChange(selfChange);
+                mDeviceProvisioned = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+                if (mDeviceProvisioned) {
+                    mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
+                }
+                if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
+            }
+        };
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
+                false, mContentObserver);
+
+        // prevent a race condition between where we check the flag and where we register the
+        // observer by grabbing the value once again...
+        boolean provisioned = Settings.Global.getInt(mContext.getContentResolver(),
+            Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+        if (provisioned != mDeviceProvisioned) {
+            mDeviceProvisioned = provisioned;
+            if (mDeviceProvisioned) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
+            }
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_DPM_STATE_CHANGED}
+     */
+    protected void handleDevicePolicyManagerStateChanged() {
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onDevicePolicyManagerStateChanged();
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_USER_SWITCHED}
+     */
+    protected void handleUserSwitched(int userId) {
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onUserSwitched(userId);
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_USER_SWITCHED}
+     */
+    protected void handleUserRemoved(int userId) {
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onUserRemoved(userId);
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_DEVICE_PROVISIONED}
+     */
+    protected void handleDeviceProvisioned() {
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onDeviceProvisioned();
+        }
+        if (mContentObserver != null) {
+            // We don't need the observer anymore...
+            mContext.getContentResolver().unregisterContentObserver(mContentObserver);
+            mContentObserver = null;
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_PHONE_STATE_CHANGED}
+     */
+    protected void handlePhoneStateChanged(String newState) {
+        if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
+        if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
+            mPhoneState = TelephonyManager.CALL_STATE_IDLE;
+        } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
+            mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
+        } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
+            mPhoneState = TelephonyManager.CALL_STATE_RINGING;
+        }
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onPhoneStateChanged(mPhoneState);
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_RINGER_MODE_CHANGED}
+     */
+    protected void handleRingerModeChange(int mode) {
+        if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
+        mRingMode = mode;
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onRingerModeChanged(mode);
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_TIME_UPDATE}
+     */
+    private void handleTimeUpdate() {
+        if (DEBUG) Log.d(TAG, "handleTimeUpdate");
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onTimeChanged();
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_BATTERY_UPDATE}
+     */
+    private void handleBatteryUpdate(BatteryStatus status) {
+        if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
+        final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
+        mBatteryStatus = status;
+        if (batteryUpdateInteresting) {
+            for (int i = 0; i < mCallbacks.size(); i++) {
+                mCallbacks.get(i).onRefreshBatteryInfo(status);
+            }
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_CARRIER_INFO_UPDATE}
+     */
+    private void handleCarrierInfoUpdate() {
+        if (DEBUG) Log.d(TAG, "handleCarrierInfoUpdate: plmn = " + mTelephonyPlmn
+            + ", spn = " + mTelephonySpn);
+
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_SIM_STATE_CHANGE}
+     */
+    private void handleSimStateChange(SimArgs simArgs) {
+        final IccCardConstants.State state = simArgs.simState;
+
+        if (DEBUG) {
+            Log.d(TAG, "handleSimStateChange: intentValue = " + simArgs + " "
+                    + "state resolved to " + state.toString());
+        }
+
+        if (state != IccCardConstants.State.UNKNOWN && state != mSimState) {
+            mSimState = state;
+            for (int i = 0; i < mCallbacks.size(); i++) {
+                mCallbacks.get(i).onSimStateChanged(state);
+            }
+        }
+    }
+
+    /**
+     * Handle {@link #MSG_CLOCK_VISIBILITY_CHANGED}
+     */
+    private void handleClockVisibilityChanged() {
+        if (DEBUG) Log.d(TAG, "handleClockVisibilityChanged()");
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            mCallbacks.get(i).onClockVisibilityChanged();
+        }
+    }
+
+    private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
+        final boolean nowPluggedIn = current.isPluggedIn();
+        final boolean wasPluggedIn = old.isPluggedIn();
+        final boolean stateChangedWhilePluggedIn =
+            wasPluggedIn == true && nowPluggedIn == true
+            && (old.status != current.status);
+
+        // change in plug state is always interesting
+        if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
+            return true;
+        }
+
+        // change in battery level while plugged in
+        if (nowPluggedIn && old.level != current.level) {
+            return true;
+        }
+
+        // change where battery needs charging
+        if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * @param intent The intent with action {@link TelephonyIntents#SPN_STRINGS_UPDATED_ACTION}
+     * @return The string to use for the plmn, or null if it should not be shown.
+     */
+    private CharSequence getTelephonyPlmnFrom(Intent intent) {
+        if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false)) {
+            final String plmn = intent.getStringExtra(TelephonyIntents.EXTRA_PLMN);
+            return (plmn != null) ? plmn : getDefaultPlmn();
+        }
+        return null;
+    }
+
+    /**
+     * @return The default plmn (no service)
+     */
+    private CharSequence getDefaultPlmn() {
+        return mContext.getResources().getText(R.string.lockscreen_carrier_default);
+    }
+
+    /**
+     * @param intent The intent with action {@link Telephony.Intents#SPN_STRINGS_UPDATED_ACTION}
+     * @return The string to use for the plmn, or null if it should not be shown.
+     */
+    private CharSequence getTelephonySpnFrom(Intent intent) {
+        if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false)) {
+            final String spn = intent.getStringExtra(TelephonyIntents.EXTRA_SPN);
+            if (spn != null) {
+                return spn;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Remove the given observer's callback.
+     *
+     * @param observer The observer to remove
+     */
+    public void removeCallback(Object observer) {
+        mCallbacks.remove(observer);
+    }
+
+    /**
+     * Register to receive notifications about general keyguard information
+     * (see {@link InfoCallback}.
+     * @param callback The callback.
+     */
+    public void registerCallback(KeyguardUpdateMonitorCallback callback) {
+        if (!mCallbacks.contains(callback)) {
+            mCallbacks.add(callback);
+            // Notify listener of the current state
+            callback.onRefreshBatteryInfo(mBatteryStatus);
+            callback.onTimeChanged();
+            callback.onRingerModeChanged(mRingMode);
+            callback.onPhoneStateChanged(mPhoneState);
+            callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
+            callback.onClockVisibilityChanged();
+            callback.onSimStateChanged(mSimState);
+        } else {
+            if (DEBUG) Log.e(TAG, "Object tried to add another callback",
+                    new Exception("Called by"));
+        }
+    }
+
+    public void reportClockVisible(boolean visible) {
+        mClockVisible = visible;
+        mHandler.obtainMessage(MSG_CLOCK_VISIBILITY_CHANGED).sendToTarget();
+    }
+
+    public IccCardConstants.State getSimState() {
+        return mSimState;
+    }
+
+    /**
+     * Report that the user successfully entered the SIM PIN or PUK/SIM PIN so we
+     * have the information earlier than waiting for the intent
+     * broadcast from the telephony code.
+     *
+     * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
+     * through mHandler, this *must* be called from the UI thread.
+     */
+    public void reportSimUnlocked() {
+        handleSimStateChange(new SimArgs(IccCardConstants.State.READY));
+    }
+
+    public CharSequence getTelephonyPlmn() {
+        return mTelephonyPlmn;
+    }
+
+    public CharSequence getTelephonySpn() {
+        return mTelephonySpn;
+    }
+
+    /**
+     * @return Whether the device is provisioned (whether they have gone through
+     *   the setup wizard)
+     */
+    public boolean isDeviceProvisioned() {
+        return mDeviceProvisioned;
+    }
+
+    public int getFailedAttempts() {
+        return mFailedAttempts;
+    }
+
+    public void clearFailedAttempts() {
+        mFailedAttempts = 0;
+        mFailedBiometricUnlockAttempts = 0;
+    }
+
+    public void reportFailedAttempt() {
+        mFailedAttempts++;
+    }
+
+    public boolean isClockVisible() {
+        return mClockVisible;
+    }
+
+    public int getPhoneState() {
+        return mPhoneState;
+    }
+
+    public void reportFailedBiometricUnlockAttempt() {
+        mFailedBiometricUnlockAttempts++;
+    }
+
+    public boolean getMaxBiometricUnlockAttemptsReached() {
+        return mFailedBiometricUnlockAttempts >= FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP;
+    }
+
+    public boolean isSimLocked() {
+        return mSimState == IccCardConstants.State.PIN_REQUIRED
+            || mSimState == IccCardConstants.State.PUK_REQUIRED
+            || mSimState == IccCardConstants.State.PERM_DISABLED;
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardUpdateMonitorCallback.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardUpdateMonitorCallback.java
new file mode 100644
index 0000000..79233e8
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardUpdateMonitorCallback.java
@@ -0,0 +1,96 @@
+/*
+ * 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.internal.policy.impl.keyguard_obsolete;
+
+import android.app.admin.DevicePolicyManager;
+import android.media.AudioManager;
+
+import com.android.internal.telephony.IccCardConstants;
+
+/**
+ * Callback for general information relevant to lock screen.
+ */
+class KeyguardUpdateMonitorCallback {
+    /**
+     * Called when the battery status changes, e.g. when plugged in or unplugged, charge
+     * level, etc. changes.
+     *
+     * @param status current battery status
+     */
+    void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) { }
+
+    /**
+     * Called once per minute or when the time changes.
+     */
+    void onTimeChanged() { }
+
+    /**
+     * Called when the carrier PLMN or SPN changes.
+     *
+     * @param plmn The operator name of the registered network.  May be null if it shouldn't
+     *   be displayed.
+     * @param spn The service provider name.  May be null if it shouldn't be displayed.
+     */
+    void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { }
+
+    /**
+     * Called when the ringer mode changes.
+     * @param state the current ringer state, as defined in
+     * {@link AudioManager#RINGER_MODE_CHANGED_ACTION}
+     */
+    void onRingerModeChanged(int state) { }
+
+    /**
+     * Called when the phone state changes. String will be one of:
+     * {@link TelephonyManager#EXTRA_STATE_IDLE}
+     * {@link TelephonyManager@EXTRA_STATE_RINGING}
+     * {@link TelephonyManager#EXTRA_STATE_OFFHOOK
+     */
+    void onPhoneStateChanged(int phoneState) { }
+
+    /**
+     * Called when visibility of lockscreen clock changes, such as when
+     * obscured by a widget.
+     */
+    void onClockVisibilityChanged() { }
+
+    /**
+     * Called when the device becomes provisioned
+     */
+    void onDeviceProvisioned() { }
+
+    /**
+     * Called when the device policy changes.
+     * See {@link DevicePolicyManager#ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED}
+     */
+    void onDevicePolicyManagerStateChanged() { }
+
+    /**
+     * Called when the user changes.
+     */
+    void onUserSwitched(int userId) { }
+
+    /**
+     * Called when the SIM state changes.
+     * @param simState
+     */
+    void onSimStateChanged(IccCardConstants.State simState) { }
+
+    /**
+     * Called when a user is removed.
+     */
+    void onUserRemoved(int userId) { }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewBase.java
new file mode 100644
index 0000000..f9fe797
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewBase.java
@@ -0,0 +1,270 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.media.AudioManager;
+import android.media.IAudioService;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.telephony.TelephonyManager;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.Gravity;
+import android.widget.FrameLayout;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Slog;
+
+/**
+ * Base class for keyguard views.  {@link #reset} is where you should
+ * reset the state of your view.  Use the {@link KeyguardViewCallback} via
+ * {@link #getCallback()} to send information back (such as poking the wake lock,
+ * or finishing the keyguard).
+ *
+ * Handles intercepting of media keys that still work when the keyguard is
+ * showing.
+ */
+public abstract class KeyguardViewBase extends FrameLayout {
+
+    private static final int BACKGROUND_COLOR = 0x70000000;
+    private KeyguardViewCallback mCallback;
+    private AudioManager mAudioManager;
+    private TelephonyManager mTelephonyManager = null;
+    // Whether the volume keys should be handled by keyguard. If true, then
+    // they will be handled here for specific media types such as music, otherwise
+    // the audio service will bring up the volume dialog.
+    private static final boolean KEYGUARD_MANAGES_VOLUME = true;
+
+    // This is a faster way to draw the background on devices without hardware acceleration
+    Drawable mBackgroundDrawable = new Drawable() {
+        @Override
+        public void draw(Canvas canvas) {
+            canvas.drawColor(BACKGROUND_COLOR, PorterDuff.Mode.SRC);
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {
+        }
+
+        @Override
+        public int getOpacity() {
+            return PixelFormat.TRANSLUCENT;
+        }
+    };
+
+    public KeyguardViewBase(Context context, KeyguardViewCallback callback) {
+        super(context);
+        mCallback = callback;
+        resetBackground();
+    }
+
+    public void resetBackground() {
+        setBackgroundDrawable(mBackgroundDrawable);
+    }
+
+    public KeyguardViewCallback getCallback() {
+        return mCallback;
+    }
+
+    /**
+     * Called when you need to reset the state of your view.
+     */
+    abstract public void reset();
+
+    /**
+     * Called when the screen turned off.
+     */
+    abstract public void onScreenTurnedOff();
+
+    /**
+     * Called when the screen turned on.
+     */
+    abstract public void onScreenTurnedOn();
+
+    /**
+     * Called when the view needs to be shown.
+     */
+    abstract public void show();
+
+    /**
+     * Called when a key has woken the device to give us a chance to adjust our
+     * state according the the key.  We are responsible for waking the device
+     * (by poking the wake lock) once we are ready.
+     *
+     * The 'Tq' suffix is per the documentation in {@link android.view.WindowManagerPolicy}.
+     * Be sure not to take any action that takes a long time; any significant
+     * action should be posted to a handler.
+     *
+     * @param keyCode The wake key, which may be relevant for configuring the
+     *   keyguard.  May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking for a reason
+     *   other than a key press.
+     */
+    abstract public void wakeWhenReadyTq(int keyCode);
+
+    /**
+     * Verify that the user can get past the keyguard securely.  This is called,
+     * for example, when the phone disables the keyguard but then wants to launch
+     * something else that requires secure access.
+     *
+     * The result will be propogated back via {@link KeyguardViewCallback#keyguardDone(boolean)}
+     */
+    abstract public void verifyUnlock();
+
+    /**
+     * Called before this view is being removed.
+     */
+    abstract public void cleanUp();
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if (shouldEventKeepScreenOnWhileKeyguardShowing(event)) {
+            mCallback.pokeWakelock();
+        }
+
+        if (interceptMediaKey(event)) {
+            return true;
+        }
+        return super.dispatchKeyEvent(event);
+    }
+
+    private boolean shouldEventKeepScreenOnWhileKeyguardShowing(KeyEvent event) {
+        if (event.getAction() != KeyEvent.ACTION_DOWN) {
+            return false;
+        }
+        switch (event.getKeyCode()) {
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+            case KeyEvent.KEYCODE_DPAD_UP:
+                return false;
+            default:
+                return true;
+        }
+    }
+
+    /**
+     * Allows the media keys to work when the keyguard is showing.
+     * The media keys should be of no interest to the actual keyguard view(s),
+     * so intercepting them here should not be of any harm.
+     * @param event The key event
+     * @return whether the event was consumed as a media key.
+     */
+    private boolean interceptMediaKey(KeyEvent event) {
+        final int keyCode = event.getKeyCode();
+        if (event.getAction() == KeyEvent.ACTION_DOWN) {
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_MEDIA_PLAY:
+                case KeyEvent.KEYCODE_MEDIA_PAUSE:
+                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+                    /* Suppress PLAY/PAUSE toggle when phone is ringing or
+                     * in-call to avoid music playback */
+                    if (mTelephonyManager == null) {
+                        mTelephonyManager = (TelephonyManager) getContext().getSystemService(
+                                Context.TELEPHONY_SERVICE);
+                    }
+                    if (mTelephonyManager != null &&
+                            mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
+                        return true;  // suppress key event
+                    }
+                case KeyEvent.KEYCODE_MUTE:
+                case KeyEvent.KEYCODE_HEADSETHOOK:
+                case KeyEvent.KEYCODE_MEDIA_STOP:
+                case KeyEvent.KEYCODE_MEDIA_NEXT:
+                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+                case KeyEvent.KEYCODE_MEDIA_REWIND:
+                case KeyEvent.KEYCODE_MEDIA_RECORD:
+                case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
+                    handleMediaKeyEvent(event);
+                    return true;
+                }
+
+                case KeyEvent.KEYCODE_VOLUME_UP:
+                case KeyEvent.KEYCODE_VOLUME_DOWN:
+                case KeyEvent.KEYCODE_VOLUME_MUTE: {
+                    if (KEYGUARD_MANAGES_VOLUME) {
+                        synchronized (this) {
+                            if (mAudioManager == null) {
+                                mAudioManager = (AudioManager) getContext().getSystemService(
+                                        Context.AUDIO_SERVICE);
+                            }
+                        }
+                        // Volume buttons should only function for music (local or remote).
+                        // TODO: Actually handle MUTE.
+                        mAudioManager.adjustLocalOrRemoteStreamVolume(
+                                AudioManager.STREAM_MUSIC,
+                                keyCode == KeyEvent.KEYCODE_VOLUME_UP
+                                        ? AudioManager.ADJUST_RAISE
+                                        : AudioManager.ADJUST_LOWER);
+                        // Don't execute default volume behavior
+                        return true;
+                    } else {
+                        return false;
+                    }
+                }
+            }
+        } else if (event.getAction() == KeyEvent.ACTION_UP) {
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_MUTE:
+                case KeyEvent.KEYCODE_HEADSETHOOK:
+                case KeyEvent.KEYCODE_MEDIA_PLAY:
+                case KeyEvent.KEYCODE_MEDIA_PAUSE:
+                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+                case KeyEvent.KEYCODE_MEDIA_STOP:
+                case KeyEvent.KEYCODE_MEDIA_NEXT:
+                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+                case KeyEvent.KEYCODE_MEDIA_REWIND:
+                case KeyEvent.KEYCODE_MEDIA_RECORD:
+                case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
+                    handleMediaKeyEvent(event);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    void handleMediaKeyEvent(KeyEvent keyEvent) {
+        IAudioService audioService = IAudioService.Stub.asInterface(
+                ServiceManager.checkService(Context.AUDIO_SERVICE));
+        if (audioService != null) {
+            try {
+                audioService.dispatchMediaKeyEvent(keyEvent);
+            } catch (RemoteException e) {
+                Log.e("KeyguardViewBase", "dispatchMediaKeyEvent threw exception " + e);
+            }
+        } else {
+            Slog.w("KeyguardViewBase", "Unable to find IAudioService for media key event");
+        }
+    }
+
+    @Override
+    public void dispatchSystemUiVisibilityChanged(int visibility) {
+        super.dispatchSystemUiVisibilityChanged(visibility);
+        setSystemUiVisibility(STATUS_BAR_DISABLE_BACK);
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewCallback.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewCallback.java
new file mode 100644
index 0000000..4cc0f30
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewCallback.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+/**
+ * The callback used by the keyguard view to tell the {@link KeyguardViewMediator}
+ * various things.
+ */
+public interface KeyguardViewCallback {
+
+    /**
+     * Request the wakelock to be poked for the default amount of time.
+     */
+    void pokeWakelock();
+
+    /**
+     * Request the wakelock to be poked for a specific amount of time.
+     * @param millis The amount of time in millis.
+     */
+    void pokeWakelock(int millis);
+
+    /**
+     * Report that the keyguard is done.
+     * @param authenticated Whether the user securely got past the keyguard.
+     *   the only reason for this to be false is if the keyguard was instructed
+     *   to appear temporarily to verify the user is supposed to get past the
+     *   keyguard, and the user fails to do so.
+     */
+    void keyguardDone(boolean authenticated);
+
+    /**
+     * Report that the keyguard is done drawing.
+     */
+    void keyguardDoneDrawing();
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewManager.java
new file mode 100644
index 0000000..5dbef48
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewManager.java
@@ -0,0 +1,309 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import com.android.internal.R;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.graphics.Canvas;
+import android.os.IBinder;
+import android.os.SystemProperties;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewManager;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+
+import android.graphics.Color;
+
+/**
+ * Manages creating, showing, hiding and resetting the keyguard.  Calls back
+ * via {@link com.android.internal.policy.impl.KeyguardViewCallback} to poke
+ * the wake lock and report that the keyguard is done, which is in turn,
+ * reported to this class by the current {@link KeyguardViewBase}.
+ */
+public class KeyguardViewManager implements KeyguardWindowController {
+    private final static boolean DEBUG = false;
+    private static String TAG = "KeyguardViewManager";
+
+    private final Context mContext;
+    private final ViewManager mViewManager;
+    private final KeyguardViewCallback mCallback;
+    private final KeyguardViewProperties mKeyguardViewProperties;
+
+    private final KeyguardUpdateMonitor mUpdateMonitor;
+
+    private WindowManager.LayoutParams mWindowLayoutParams;
+    private boolean mNeedsInput = false;
+
+    private FrameLayout mKeyguardHost;
+    private KeyguardViewBase mKeyguardView;
+
+    private boolean mScreenOn = false;
+
+    public interface ShowListener {
+        void onShown(IBinder windowToken);
+    };
+
+    /**
+     * @param context Used to create views.
+     * @param viewManager Keyguard will be attached to this.
+     * @param callback Used to notify of changes.
+     */
+    public KeyguardViewManager(Context context, ViewManager viewManager,
+            KeyguardViewCallback callback, KeyguardViewProperties keyguardViewProperties,
+            KeyguardUpdateMonitor updateMonitor) {
+        mContext = context;
+        mViewManager = viewManager;
+        mCallback = callback;
+        mKeyguardViewProperties = keyguardViewProperties;
+
+        mUpdateMonitor = updateMonitor;
+    }
+
+    /**
+     * Helper class to host the keyguard view.
+     */
+    private static class KeyguardViewHost extends FrameLayout {
+        private final KeyguardViewCallback mCallback;
+
+        private KeyguardViewHost(Context context, KeyguardViewCallback callback) {
+            super(context);
+            mCallback = callback;
+        }
+
+        @Override
+        protected void dispatchDraw(Canvas canvas) {
+            super.dispatchDraw(canvas);
+            mCallback.keyguardDoneDrawing();
+        }
+    }
+
+    /**
+     * Show the keyguard.  Will handle creating and attaching to the view manager
+     * lazily.
+     */
+    public synchronized void show() {
+        if (DEBUG) Log.d(TAG, "show(); mKeyguardView==" + mKeyguardView);
+
+        Resources res = mContext.getResources();
+        boolean enableScreenRotation =
+                SystemProperties.getBoolean("lockscreen.rot_override",false)
+                || res.getBoolean(R.bool.config_enableLockScreenRotation);
+        if (mKeyguardHost == null) {
+            if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");
+
+            mKeyguardHost = new KeyguardViewHost(mContext, mCallback);
+
+            final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
+            int flags = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
+                    | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER
+                    | WindowManager.LayoutParams.FLAG_SLIPPERY
+                    /*| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                    | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR*/ ;
+            if (!mNeedsInput) {
+                flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+            }
+            if (ActivityManager.isHighEndGfx()) {
+                flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+            }
+            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                    stretch, stretch, WindowManager.LayoutParams.TYPE_KEYGUARD,
+                    flags, PixelFormat.TRANSLUCENT);
+            lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+            lp.windowAnimations = com.android.internal.R.style.Animation_LockScreen;
+            if (ActivityManager.isHighEndGfx()) {
+                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+                lp.privateFlags |=
+                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
+            }
+            lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
+            lp.setTitle("Keyguard");
+            mWindowLayoutParams = lp;
+
+            mViewManager.addView(mKeyguardHost, lp);
+        }
+
+        if (enableScreenRotation) {
+            if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen On!");
+            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
+        } else {
+            if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen Off!");
+            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+        }
+
+        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
+
+        if (mKeyguardView == null) {
+            if (DEBUG) Log.d(TAG, "keyguard view is null, creating it...");
+            mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mCallback,
+                    mUpdateMonitor, this);
+            mKeyguardView.setId(R.id.lock_screen);
+
+            final ViewGroup.LayoutParams lp = new FrameLayout.LayoutParams(
+                    ViewGroup.LayoutParams.MATCH_PARENT,
+                    ViewGroup.LayoutParams.MATCH_PARENT);
+
+            mKeyguardHost.addView(mKeyguardView, lp);
+
+            if (mScreenOn) {
+                mKeyguardView.show();
+            }
+        }
+
+        // Disable aspects of the system/status/navigation bars that are not appropriate or
+        // useful for the lockscreen but can be re-shown by dialogs or SHOW_WHEN_LOCKED activities.
+        // Other disabled bits are handled by the KeyguardViewMediator talking directly to the
+        // status bar service.
+        int visFlags =
+                ( View.STATUS_BAR_DISABLE_BACK
+                | View.STATUS_BAR_DISABLE_HOME
+                );
+        Log.v(TAG, "KGVM: Set visibility on " + mKeyguardHost + " to " + visFlags);
+        mKeyguardHost.setSystemUiVisibility(visFlags);
+
+        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
+        mKeyguardHost.setVisibility(View.VISIBLE);
+        mKeyguardView.requestFocus();
+    }
+
+    public void setNeedsInput(boolean needsInput) {
+        mNeedsInput = needsInput;
+        if (mWindowLayoutParams != null) {
+            if (needsInput) {
+                mWindowLayoutParams.flags &=
+                    ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+            } else {
+                mWindowLayoutParams.flags |=
+                    WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+            }
+            mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
+        }
+    }
+
+    /**
+     * Reset the state of the view.
+     */
+    public synchronized void reset() {
+        if (DEBUG) Log.d(TAG, "reset()");
+        if (mKeyguardView != null) {
+            mKeyguardView.reset();
+        }
+    }
+
+    public synchronized void onScreenTurnedOff() {
+        if (DEBUG) Log.d(TAG, "onScreenTurnedOff()");
+        mScreenOn = false;
+        if (mKeyguardView != null) {
+            mKeyguardView.onScreenTurnedOff();
+        }
+    }
+
+    public synchronized void onScreenTurnedOn(
+            final KeyguardViewManager.ShowListener showListener) {
+        if (DEBUG) Log.d(TAG, "onScreenTurnedOn()");
+        mScreenOn = true;
+        if (mKeyguardView != null) {
+            mKeyguardView.onScreenTurnedOn();
+
+            // Caller should wait for this window to be shown before turning
+            // on the screen.
+            if (mKeyguardHost.getVisibility() == View.VISIBLE) {
+                // Keyguard may be in the process of being shown, but not yet
+                // updated with the window manager...  give it a chance to do so.
+                mKeyguardHost.post(new Runnable() {
+                    public void run() {
+                        if (mKeyguardHost.getVisibility() == View.VISIBLE) {
+                            showListener.onShown(mKeyguardHost.getWindowToken());
+                        } else {
+                            showListener.onShown(null);
+                        }
+                    }
+                });
+            } else {
+                showListener.onShown(null);
+            }
+        } else {
+            showListener.onShown(null);
+        }
+    }
+
+    public synchronized void verifyUnlock() {
+        if (DEBUG) Log.d(TAG, "verifyUnlock()");
+        show();
+        mKeyguardView.verifyUnlock();
+    }
+
+    /**
+     * A key has woken the device.  We use this to potentially adjust the state
+     * of the lock screen based on the key.
+     *
+     * The 'Tq' suffix is per the documentation in {@link android.view.WindowManagerPolicy}.
+     * Be sure not to take any action that takes a long time; any significant
+     * action should be posted to a handler.
+     *
+     * @param keyCode The wake key.  May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking
+     * for a reason other than a key press.
+     */
+    public boolean wakeWhenReadyTq(int keyCode) {
+        if (DEBUG) Log.d(TAG, "wakeWhenReady(" + keyCode + ")");
+        if (mKeyguardView != null) {
+            mKeyguardView.wakeWhenReadyTq(keyCode);
+            return true;
+        } else {
+            Log.w(TAG, "mKeyguardView is null in wakeWhenReadyTq");
+            return false;
+        }
+    }
+
+    /**
+     * Hides the keyguard view
+     */
+    public synchronized void hide() {
+        if (DEBUG) Log.d(TAG, "hide()");
+
+        if (mKeyguardHost != null) {
+            mKeyguardHost.setVisibility(View.GONE);
+            // Don't do this right away, so we can let the view continue to animate
+            // as it goes away.
+            if (mKeyguardView != null) {
+                final KeyguardViewBase lastView = mKeyguardView;
+                mKeyguardView = null;
+                mKeyguardHost.postDelayed(new Runnable() {
+                    public void run() {
+                        synchronized (KeyguardViewManager.this) {
+                            lastView.cleanUp();
+                            mKeyguardHost.removeView(lastView);
+                        }
+                    }
+                }, 500);
+            }
+        }
+    }
+
+    /**
+     * @return Whether the keyguard is showing
+     */
+    public synchronized boolean isShowing() {
+        return (mKeyguardHost != null && mKeyguardHost.getVisibility() == View.VISIBLE);
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewMediator.java
new file mode 100644
index 0000000..3de1428
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewMediator.java
@@ -0,0 +1,1302 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+
+import com.android.internal.policy.impl.PhoneWindowManager;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.widget.LockPatternUtils;
+
+import android.app.ActivityManagerNative;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.app.StatusBarManager;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.media.AudioManager;
+import android.media.SoundPool;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.util.EventLog;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+
+
+/**
+ * Mediates requests related to the keyguard.  This includes queries about the
+ * state of the keyguard, power management events that effect whether the keyguard
+ * should be shown or reset, callbacks to the phone window manager to notify
+ * it of when the keyguard is showing, and events from the keyguard view itself
+ * stating that the keyguard was succesfully unlocked.
+ *
+ * Note that the keyguard view is shown when the screen is off (as appropriate)
+ * so that once the screen comes on, it will be ready immediately.
+ *
+ * Example queries about the keyguard:
+ * - is {movement, key} one that should wake the keygaurd?
+ * - is the keyguard showing?
+ * - are input events restricted due to the state of the keyguard?
+ *
+ * Callbacks to the phone window manager:
+ * - the keyguard is showing
+ *
+ * Example external events that translate to keyguard view changes:
+ * - screen turned off -> reset the keyguard, and show it so it will be ready
+ *   next time the screen turns on
+ * - keyboard is slid open -> if the keyguard is not secure, hide it
+ *
+ * Events from the keyguard view:
+ * - user succesfully unlocked keyguard -> hide keyguard view, and no longer
+ *   restrict input events.
+ *
+ * Note: in addition to normal power managment events that effect the state of
+ * whether the keyguard should be showing, external apps and services may request
+ * that the keyguard be disabled via {@link #setKeyguardEnabled(boolean)}.  When
+ * false, this will override all other conditions for turning on the keyguard.
+ *
+ * Threading and synchronization:
+ * This class is created by the initialization routine of the {@link WindowManagerPolicy},
+ * and runs on its thread.  The keyguard UI is created from that thread in the
+ * constructor of this class.  The apis may be called from other threads, including the
+ * {@link com.android.server.input.InputManagerService}'s and {@link android.view.WindowManager}'s.
+ * Therefore, methods on this class are synchronized, and any action that is pointed
+ * directly to the keyguard UI is posted to a {@link Handler} to ensure it is taken on the UI
+ * thread of the keyguard.
+ */
+public class KeyguardViewMediator implements KeyguardViewCallback {
+    private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
+    private final static boolean DEBUG = false;
+    private final static boolean DBG_WAKE = false;
+
+    private final static String TAG = "KeyguardViewMediator";
+
+    private static final String DELAYED_KEYGUARD_ACTION =
+        "com.android.internal.policy.impl.PhoneWindowManager.DELAYED_KEYGUARD";
+
+    // used for handler messages
+    private static final int TIMEOUT = 1;
+    private static final int SHOW = 2;
+    private static final int HIDE = 3;
+    private static final int RESET = 4;
+    private static final int VERIFY_UNLOCK = 5;
+    private static final int NOTIFY_SCREEN_OFF = 6;
+    private static final int NOTIFY_SCREEN_ON = 7;
+    private static final int WAKE_WHEN_READY = 8;
+    private static final int KEYGUARD_DONE = 9;
+    private static final int KEYGUARD_DONE_DRAWING = 10;
+    private static final int KEYGUARD_DONE_AUTHENTICATING = 11;
+    private static final int SET_HIDDEN = 12;
+    private static final int KEYGUARD_TIMEOUT = 13;
+
+    /**
+     * The default amount of time we stay awake (used for all key input)
+     */
+    protected static final int AWAKE_INTERVAL_DEFAULT_MS = 10000;
+
+    /**
+     * How long to wait after the screen turns off due to timeout before
+     * turning on the keyguard (i.e, the user has this much time to turn
+     * the screen back on without having to face the keyguard).
+     */
+    private static final int KEYGUARD_LOCK_AFTER_DELAY_DEFAULT = 5000;
+
+    /**
+     * How long we'll wait for the {@link KeyguardViewCallback#keyguardDoneDrawing()}
+     * callback before unblocking a call to {@link #setKeyguardEnabled(boolean)}
+     * that is reenabling the keyguard.
+     */
+    private static final int KEYGUARD_DONE_DRAWING_TIMEOUT_MS = 2000;
+
+    /**
+     * Allow the user to expand the status bar when the keyguard is engaged
+     * (without a pattern or password).
+     */
+    private static final boolean ENABLE_INSECURE_STATUS_BAR_EXPAND = true;
+
+    /** The stream type that the lock sounds are tied to. */
+    private int mMasterStreamType;
+
+    private Context mContext;
+    private AlarmManager mAlarmManager;
+    private AudioManager mAudioManager;
+    private StatusBarManager mStatusBarManager;
+    private boolean mShowLockIcon;
+    private boolean mShowingLockIcon;
+
+    private boolean mSystemReady;
+
+    // Whether the next call to playSounds() should be skipped.  Defaults to
+    // true because the first lock (on boot) should be silent.
+    private boolean mSuppressNextLockSound = true;
+
+
+    /** High level access to the power manager for WakeLocks */
+    private PowerManager mPM;
+
+    /**
+     * Used to keep the device awake while the keyguard is showing, i.e for
+     * calls to {@link #pokeWakelock()}
+     */
+    private PowerManager.WakeLock mWakeLock;
+
+    /**
+     * Used to keep the device awake while to ensure the keyguard finishes opening before
+     * we sleep.
+     */
+    private PowerManager.WakeLock mShowKeyguardWakeLock;
+
+    /**
+     * Does not turn on screen, held while a call to {@link KeyguardViewManager#wakeWhenReadyTq(int)}
+     * is called to make sure the device doesn't sleep before it has a chance to poke
+     * the wake lock.
+     * @see #wakeWhenReadyLocked(int)
+     */
+    private PowerManager.WakeLock mWakeAndHandOff;
+
+    private KeyguardViewManager mKeyguardViewManager;
+
+    // these are protected by synchronized (this)
+
+    /**
+     * External apps (like the phone app) can tell us to disable the keygaurd.
+     */
+    private boolean mExternallyEnabled = true;
+
+    /**
+     * Remember if an external call to {@link #setKeyguardEnabled} with value
+     * false caused us to hide the keyguard, so that we need to reshow it once
+     * the keygaurd is reenabled with another call with value true.
+     */
+    private boolean mNeedToReshowWhenReenabled = false;
+
+    // cached value of whether we are showing (need to know this to quickly
+    // answer whether the input should be restricted)
+    private boolean mShowing = false;
+
+    // true if the keyguard is hidden by another window
+    private boolean mHidden = false;
+
+    /**
+     * Helps remember whether the screen has turned on since the last time
+     * it turned off due to timeout. see {@link #onScreenTurnedOff(int)}
+     */
+    private int mDelayedShowingSequence;
+
+    private int mWakelockSequence;
+
+    private PhoneWindowManager mCallback;
+
+    /**
+     * If the user has disabled the keyguard, then requests to exit, this is
+     * how we'll ultimately let them know whether it was successful.  We use this
+     * var being non-null as an indicator that there is an in progress request.
+     */
+    private WindowManagerPolicy.OnKeyguardExitResult mExitSecureCallback;
+
+    // the properties of the keyguard
+    private KeyguardViewProperties mKeyguardViewProperties;
+
+    private KeyguardUpdateMonitor mUpdateMonitor;
+
+    private boolean mScreenOn;
+
+    // last known state of the cellular connection
+    private String mPhoneState = TelephonyManager.EXTRA_STATE_IDLE;
+
+    /**
+     * we send this intent when the keyguard is dismissed.
+     */
+    private Intent mUserPresentIntent;
+
+    /**
+     * {@link #setKeyguardEnabled} waits on this condition when it reenables
+     * the keyguard.
+     */
+    private boolean mWaitingUntilKeyguardVisible = false;
+    private LockPatternUtils mLockPatternUtils;
+
+    private SoundPool mLockSounds;
+    private int mLockSoundId;
+    private int mUnlockSoundId;
+    private int mLockSoundStreamId;
+
+    /**
+     * The volume applied to the lock/unlock sounds.
+     */
+    private final float mLockSoundVolume;
+
+    KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
+
+        @Override
+        public void onUserSwitched(int userId) {
+            mLockPatternUtils.setCurrentUser(userId);
+            synchronized (KeyguardViewMediator.this) {
+                resetStateLocked();
+            }
+        }
+
+        @Override
+        public void onUserRemoved(int userId) {
+            mLockPatternUtils.removeUser(userId);
+        }
+
+        @Override
+        void onPhoneStateChanged(int phoneState) {
+            synchronized (KeyguardViewMediator.this) {
+                if (TelephonyManager.CALL_STATE_IDLE == phoneState  // call ending
+                        && !mScreenOn                           // screen off
+                        && mExternallyEnabled) {                // not disabled by any app
+
+                    // note: this is a way to gracefully reenable the keyguard when the call
+                    // ends and the screen is off without always reenabling the keyguard
+                    // each time the screen turns off while in call (and having an occasional ugly
+                    // flicker while turning back on the screen and disabling the keyguard again).
+                    if (DEBUG) Log.d(TAG, "screen is off and call ended, let's make sure the "
+                            + "keyguard is showing");
+                    doKeyguardLocked();
+                }
+            }
+        };
+
+        @Override
+        public void onClockVisibilityChanged() {
+            adjustStatusBarLocked();
+        }
+
+        @Override
+        public void onDeviceProvisioned() {
+            mContext.sendBroadcastAsUser(mUserPresentIntent, UserHandle.ALL);
+        }
+
+        @Override
+        public void onSimStateChanged(IccCardConstants.State simState) {
+            if (DEBUG) Log.d(TAG, "onSimStateChanged: " + simState);
+
+            switch (simState) {
+                case NOT_READY:
+                case ABSENT:
+                    // only force lock screen in case of missing sim if user hasn't
+                    // gone through setup wizard
+                    synchronized (this) {
+                        if (!mUpdateMonitor.isDeviceProvisioned()) {
+                            if (!isShowing()) {
+                                if (DEBUG) Log.d(TAG, "ICC_ABSENT isn't showing,"
+                                        + " we need to show the keyguard since the "
+                                        + "device isn't provisioned yet.");
+                                doKeyguardLocked();
+                            } else {
+                                resetStateLocked();
+                            }
+                        }
+                    }
+                    break;
+                case PIN_REQUIRED:
+                case PUK_REQUIRED:
+                    synchronized (this) {
+                        if (!isShowing()) {
+                            if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't "
+                                    + "showing; need to show keyguard so user can enter sim pin");
+                            doKeyguardLocked();
+                        } else {
+                            resetStateLocked();
+                        }
+                    }
+                    break;
+                case PERM_DISABLED:
+                    synchronized (this) {
+                        if (!isShowing()) {
+                            if (DEBUG) Log.d(TAG, "PERM_DISABLED and "
+                                  + "keygaurd isn't showing.");
+                            doKeyguardLocked();
+                        } else {
+                            if (DEBUG) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
+                                  + "show permanently disabled message in lockscreen.");
+                            resetStateLocked();
+                        }
+                    }
+                    break;
+                case READY:
+                    synchronized (this) {
+                        if (isShowing()) {
+                            resetStateLocked();
+                        }
+                    }
+                    break;
+            }
+        }
+
+    };
+
+    public KeyguardViewMediator(Context context, PhoneWindowManager callback) {
+        mContext = context;
+        mCallback = callback;
+        mPM = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = mPM.newWakeLock(
+                PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "keyguard");
+        mWakeLock.setReferenceCounted(false);
+        mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
+        mShowKeyguardWakeLock.setReferenceCounted(false);
+
+        mWakeAndHandOff = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "keyguardWakeAndHandOff");
+        mWakeAndHandOff.setReferenceCounted(false);
+
+        mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION));
+
+        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+
+        mUpdateMonitor = new KeyguardUpdateMonitor(context);
+
+        mLockPatternUtils = new LockPatternUtils(mContext);
+        mKeyguardViewProperties
+                = new LockPatternKeyguardViewProperties(mLockPatternUtils, mUpdateMonitor);
+
+        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+        mKeyguardViewManager = new KeyguardViewManager(
+                context, wm, this, mKeyguardViewProperties, mUpdateMonitor);
+
+        mUserPresentIntent = new Intent(Intent.ACTION_USER_PRESENT);
+        mUserPresentIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
+                | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+
+        final ContentResolver cr = mContext.getContentResolver();
+        mShowLockIcon = (Settings.System.getInt(cr, "show_status_bar_lock", 0) == 1);
+
+        mScreenOn = mPM.isScreenOn();
+
+        mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0);
+        String soundPath = Settings.Global.getString(cr, Settings.Global.LOCK_SOUND);
+        if (soundPath != null) {
+            mLockSoundId = mLockSounds.load(soundPath, 1);
+        }
+        if (soundPath == null || mLockSoundId == 0) {
+            if (DEBUG) Log.d(TAG, "failed to load sound from " + soundPath);
+        }
+        soundPath = Settings.Global.getString(cr, Settings.Global.UNLOCK_SOUND);
+        if (soundPath != null) {
+            mUnlockSoundId = mLockSounds.load(soundPath, 1);
+        }
+        if (soundPath == null || mUnlockSoundId == 0) {
+            if (DEBUG) Log.d(TAG, "failed to load sound from " + soundPath);
+        }
+        int lockSoundDefaultAttenuation = context.getResources().getInteger(
+                com.android.internal.R.integer.config_lockSoundVolumeDb);
+        mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20);
+    }
+
+    /**
+     * Let us know that the system is ready after startup.
+     */
+    public void onSystemReady() {
+        synchronized (this) {
+            if (DEBUG) Log.d(TAG, "onSystemReady");
+            mSystemReady = true;
+            mUpdateMonitor.registerCallback(mUpdateCallback);
+            doKeyguardLocked();
+        }
+    }
+
+    /**
+     * Called to let us know the screen was turned off.
+     * @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER},
+     *   {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
+     *   {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
+     */
+    public void onScreenTurnedOff(int why) {
+        synchronized (this) {
+            mScreenOn = false;
+            if (DEBUG) Log.d(TAG, "onScreenTurnedOff(" + why + ")");
+
+            // Lock immediately based on setting if secure (user has a pin/pattern/password).
+            // This also "locks" the device when not secure to provide easy access to the
+            // camera while preventing unwanted input.
+            final boolean lockImmediately =
+                mLockPatternUtils.getPowerButtonInstantlyLocks() || !mLockPatternUtils.isSecure();
+
+            if (mExitSecureCallback != null) {
+                if (DEBUG) Log.d(TAG, "pending exit secure callback cancelled");
+                mExitSecureCallback.onKeyguardExitResult(false);
+                mExitSecureCallback = null;
+                if (!mExternallyEnabled) {
+                    hideLocked();
+                }
+            } else if (mShowing) {
+                notifyScreenOffLocked();
+                resetStateLocked();
+            } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT
+                   || (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)) {
+                // if the screen turned off because of timeout or the user hit the power button
+                // and we don't need to lock immediately, set an alarm
+                // to enable it a little bit later (i.e, give the user a chance
+                // to turn the screen back on within a certain window without
+                // having to unlock the screen)
+                final ContentResolver cr = mContext.getContentResolver();
+
+                // From DisplaySettings
+                long displayTimeout = Settings.System.getInt(cr, SCREEN_OFF_TIMEOUT,
+                        KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT);
+
+                // From SecuritySettings
+                final long lockAfterTimeout = Settings.Secure.getInt(cr,
+                        Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
+                        KEYGUARD_LOCK_AFTER_DELAY_DEFAULT);
+
+                // From DevicePolicyAdmin
+                final long policyTimeout = mLockPatternUtils.getDevicePolicyManager()
+                        .getMaximumTimeToLock(null);
+
+                long timeout;
+                if (policyTimeout > 0) {
+                    // policy in effect. Make sure we don't go beyond policy limit.
+                    displayTimeout = Math.max(displayTimeout, 0); // ignore negative values
+                    timeout = Math.min(policyTimeout - displayTimeout, lockAfterTimeout);
+                } else {
+                    timeout = lockAfterTimeout;
+                }
+
+                if (timeout <= 0) {
+                    // Lock now
+                    mSuppressNextLockSound = true;
+                    doKeyguardLocked();
+                } else {
+                    // Lock in the future
+                    long when = SystemClock.elapsedRealtime() + timeout;
+                    Intent intent = new Intent(DELAYED_KEYGUARD_ACTION);
+                    intent.putExtra("seq", mDelayedShowingSequence);
+                    PendingIntent sender = PendingIntent.getBroadcast(mContext,
+                            0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+                    mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, sender);
+                    if (DEBUG) Log.d(TAG, "setting alarm to turn off keyguard, seq = "
+                                     + mDelayedShowingSequence);
+                }
+            } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
+                // Do not enable the keyguard if the prox sensor forced the screen off.
+            } else {
+                doKeyguardLocked();
+            }
+        }
+    }
+
+    /**
+     * Let's us know the screen was turned on.
+     */
+    public void onScreenTurnedOn(KeyguardViewManager.ShowListener showListener) {
+        synchronized (this) {
+            mScreenOn = true;
+            mDelayedShowingSequence++;
+            if (DEBUG) Log.d(TAG, "onScreenTurnedOn, seq = " + mDelayedShowingSequence);
+            if (showListener != null) {
+                notifyScreenOnLocked(showListener);
+            }
+        }
+    }
+
+    /**
+     * Same semantics as {@link WindowManagerPolicy#enableKeyguard}; provide
+     * a way for external stuff to override normal keyguard behavior.  For instance
+     * the phone app disables the keyguard when it receives incoming calls.
+     */
+    public void setKeyguardEnabled(boolean enabled) {
+        synchronized (this) {
+            if (DEBUG) Log.d(TAG, "setKeyguardEnabled(" + enabled + ")");
+
+
+            mExternallyEnabled = enabled;
+
+            if (!enabled && mShowing) {
+                if (mExitSecureCallback != null) {
+                    if (DEBUG) Log.d(TAG, "in process of verifyUnlock request, ignoring");
+                    // we're in the process of handling a request to verify the user
+                    // can get past the keyguard. ignore extraneous requests to disable / reenable
+                    return;
+                }
+
+                // hiding keyguard that is showing, remember to reshow later
+                if (DEBUG) Log.d(TAG, "remembering to reshow, hiding keyguard, "
+                        + "disabling status bar expansion");
+                mNeedToReshowWhenReenabled = true;
+                hideLocked();
+            } else if (enabled && mNeedToReshowWhenReenabled) {
+                // reenabled after previously hidden, reshow
+                if (DEBUG) Log.d(TAG, "previously hidden, reshowing, reenabling "
+                        + "status bar expansion");
+                mNeedToReshowWhenReenabled = false;
+
+                if (mExitSecureCallback != null) {
+                    if (DEBUG) Log.d(TAG, "onKeyguardExitResult(false), resetting");
+                    mExitSecureCallback.onKeyguardExitResult(false);
+                    mExitSecureCallback = null;
+                    resetStateLocked();
+                } else {
+                    showLocked();
+
+                    // block until we know the keygaurd is done drawing (and post a message
+                    // to unblock us after a timeout so we don't risk blocking too long
+                    // and causing an ANR).
+                    mWaitingUntilKeyguardVisible = true;
+                    mHandler.sendEmptyMessageDelayed(KEYGUARD_DONE_DRAWING, KEYGUARD_DONE_DRAWING_TIMEOUT_MS);
+                    if (DEBUG) Log.d(TAG, "waiting until mWaitingUntilKeyguardVisible is false");
+                    while (mWaitingUntilKeyguardVisible) {
+                        try {
+                            wait();
+                        } catch (InterruptedException e) {
+                            Thread.currentThread().interrupt();
+                        }
+                    }
+                    if (DEBUG) Log.d(TAG, "done waiting for mWaitingUntilKeyguardVisible");
+                }
+            }
+        }
+    }
+
+    /**
+     * @see android.app.KeyguardManager#exitKeyguardSecurely
+     */
+    public void verifyUnlock(WindowManagerPolicy.OnKeyguardExitResult callback) {
+        synchronized (this) {
+            if (DEBUG) Log.d(TAG, "verifyUnlock");
+            if (!mUpdateMonitor.isDeviceProvisioned()) {
+                // don't allow this api when the device isn't provisioned
+                if (DEBUG) Log.d(TAG, "ignoring because device isn't provisioned");
+                callback.onKeyguardExitResult(false);
+            } else if (mExternallyEnabled) {
+                // this only applies when the user has externally disabled the
+                // keyguard.  this is unexpected and means the user is not
+                // using the api properly.
+                Log.w(TAG, "verifyUnlock called when not externally disabled");
+                callback.onKeyguardExitResult(false);
+            } else if (mExitSecureCallback != null) {
+                // already in progress with someone else
+                callback.onKeyguardExitResult(false);
+            } else {
+                mExitSecureCallback = callback;
+                verifyUnlockLocked();
+            }
+        }
+    }
+
+    /**
+     * Is the keyguard currently showing?
+     */
+    public boolean isShowing() {
+        return mShowing;
+    }
+
+    /**
+     * Is the keyguard currently showing and not being force hidden?
+     */
+    public boolean isShowingAndNotHidden() {
+        return mShowing && !mHidden;
+    }
+
+    /**
+     * Notify us when the keyguard is hidden by another window
+     */
+    public void setHidden(boolean isHidden) {
+        if (DEBUG) Log.d(TAG, "setHidden " + isHidden);
+        mHandler.removeMessages(SET_HIDDEN);
+        Message msg = mHandler.obtainMessage(SET_HIDDEN, (isHidden ? 1 : 0), 0);
+        mHandler.sendMessage(msg);
+    }
+
+    /**
+     * Handles SET_HIDDEN message sent by setHidden()
+     */
+    private void handleSetHidden(boolean isHidden) {
+        synchronized (KeyguardViewMediator.this) {
+            if (mHidden != isHidden) {
+                mHidden = isHidden;
+                updateActivityLockScreenState();
+                adjustUserActivityLocked();
+                adjustStatusBarLocked();
+            }
+        }
+    }
+
+    /**
+     * Used by PhoneWindowManager to enable the keyguard due to a user activity timeout.
+     * This must be safe to call from any thread and with any window manager locks held.
+     */
+    public void doKeyguardTimeout() {
+        mHandler.removeMessages(KEYGUARD_TIMEOUT);
+        Message msg = mHandler.obtainMessage(KEYGUARD_TIMEOUT);
+        mHandler.sendMessage(msg);
+    }
+
+    /**
+     * Given the state of the keyguard, is the input restricted?
+     * Input is restricted when the keyguard is showing, or when the keyguard
+     * was suppressed by an app that disabled the keyguard or we haven't been provisioned yet.
+     */
+    public boolean isInputRestricted() {
+        return mShowing || mNeedToReshowWhenReenabled || !mUpdateMonitor.isDeviceProvisioned();
+    }
+
+    /**
+     * Enable the keyguard if the settings are appropriate.  Return true if all
+     * work that will happen is done; returns false if the caller can wait for
+     * the keyguard to be shown.
+     */
+    private void doKeyguardLocked() {
+        // if another app is disabling us, don't show
+        if (!mExternallyEnabled) {
+            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
+
+            // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
+            // for an occasional ugly flicker in this situation:
+            // 1) receive a call with the screen on (no keyguard) or make a call
+            // 2) screen times out
+            // 3) user hits key to turn screen back on
+            // instead, we reenable the keyguard when we know the screen is off and the call
+            // ends (see the broadcast receiver below)
+            // TODO: clean this up when we have better support at the window manager level
+            // for apps that wish to be on top of the keyguard
+            return;
+        }
+
+        // if the keyguard is already showing, don't bother
+        if (mKeyguardViewManager.isShowing()) {
+            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
+            return;
+        }
+
+        // if the setup wizard hasn't run yet, don't show
+        final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim",
+                false);
+        final boolean provisioned = mUpdateMonitor.isDeviceProvisioned();
+        final IccCardConstants.State state = mUpdateMonitor.getSimState();
+        final boolean lockedOrMissing = state.isPinLocked()
+                || ((state == IccCardConstants.State.ABSENT
+                || state == IccCardConstants.State.PERM_DISABLED)
+                && requireSim);
+
+        if (!lockedOrMissing && !provisioned) {
+            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
+                    + " and the sim is not locked or missing");
+            return;
+        }
+
+        if (mLockPatternUtils.isLockScreenDisabled() && !lockedOrMissing) {
+            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
+            return;
+        }
+
+        if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
+        showLocked();
+    }
+
+    /**
+     * Send message to keyguard telling it to reset its state.
+     * @see #handleReset()
+     */
+    private void resetStateLocked() {
+        if (DEBUG) Log.d(TAG, "resetStateLocked");
+        Message msg = mHandler.obtainMessage(RESET);
+        mHandler.sendMessage(msg);
+    }
+
+    /**
+     * Send message to keyguard telling it to verify unlock
+     * @see #handleVerifyUnlock()
+     */
+    private void verifyUnlockLocked() {
+        if (DEBUG) Log.d(TAG, "verifyUnlockLocked");
+        mHandler.sendEmptyMessage(VERIFY_UNLOCK);
+    }
+
+
+    /**
+     * Send a message to keyguard telling it the screen just turned on.
+     * @see #onScreenTurnedOff(int)
+     * @see #handleNotifyScreenOff
+     */
+    private void notifyScreenOffLocked() {
+        if (DEBUG) Log.d(TAG, "notifyScreenOffLocked");
+        mHandler.sendEmptyMessage(NOTIFY_SCREEN_OFF);
+    }
+
+    /**
+     * Send a message to keyguard telling it the screen just turned on.
+     * @see #onScreenTurnedOn()
+     * @see #handleNotifyScreenOn
+     */
+    private void notifyScreenOnLocked(KeyguardViewManager.ShowListener showListener) {
+        if (DEBUG) Log.d(TAG, "notifyScreenOnLocked");
+        Message msg = mHandler.obtainMessage(NOTIFY_SCREEN_ON, showListener);
+        mHandler.sendMessage(msg);
+    }
+
+    /**
+     * Send message to keyguard telling it about a wake key so it can adjust
+     * its state accordingly and then poke the wake lock when it is ready.
+     * @param keyCode The wake key.
+     * @see #handleWakeWhenReady
+     * @see #onWakeKeyWhenKeyguardShowingTq(int)
+     */
+    private void wakeWhenReadyLocked(int keyCode) {
+        if (DBG_WAKE) Log.d(TAG, "wakeWhenReadyLocked(" + keyCode + ")");
+
+        /**
+         * acquire the handoff lock that will keep the cpu running.  this will
+         * be released once the keyguard has set itself up and poked the other wakelock
+         * in {@link #handleWakeWhenReady(int)}
+         */
+        mWakeAndHandOff.acquire();
+
+        Message msg = mHandler.obtainMessage(WAKE_WHEN_READY, keyCode, 0);
+        mHandler.sendMessage(msg);
+    }
+
+    /**
+     * Send message to keyguard telling it to show itself
+     * @see #handleShow()
+     */
+    private void showLocked() {
+        if (DEBUG) Log.d(TAG, "showLocked");
+        // ensure we stay awake until we are finished displaying the keyguard
+        mShowKeyguardWakeLock.acquire();
+        Message msg = mHandler.obtainMessage(SHOW);
+        mHandler.sendMessage(msg);
+    }
+
+    /**
+     * Send message to keyguard telling it to hide itself
+     * @see #handleHide()
+     */
+    private void hideLocked() {
+        if (DEBUG) Log.d(TAG, "hideLocked");
+        Message msg = mHandler.obtainMessage(HIDE);
+        mHandler.sendMessage(msg);
+    }
+
+    public boolean isSecure() {
+        return mKeyguardViewProperties.isSecure();
+    }
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (DELAYED_KEYGUARD_ACTION.equals(intent.getAction())) {
+                final int sequence = intent.getIntExtra("seq", 0);
+                if (DEBUG) Log.d(TAG, "received DELAYED_KEYGUARD_ACTION with seq = "
+                        + sequence + ", mDelayedShowingSequence = " + mDelayedShowingSequence);
+                synchronized (KeyguardViewMediator.this) {
+                    if (mDelayedShowingSequence == sequence) {
+                        // Don't play lockscreen SFX if the screen went off due to timeout.
+                        mSuppressNextLockSound = true;
+                        doKeyguardLocked();
+                    }
+                }
+            }
+        }
+    };
+
+    /**
+     * When a key is received when the screen is off and the keyguard is showing,
+     * we need to decide whether to actually turn on the screen, and if so, tell
+     * the keyguard to prepare itself and poke the wake lock when it is ready.
+     *
+     * The 'Tq' suffix is per the documentation in {@link WindowManagerPolicy}.
+     * Be sure not to take any action that takes a long time; any significant
+     * action should be posted to a handler.
+     *
+     * @param keyCode The keycode of the key that woke the device
+     * @param isDocked True if the device is in the dock
+     * @return Whether we poked the wake lock (and turned the screen on)
+     */
+    public boolean onWakeKeyWhenKeyguardShowingTq(int keyCode, boolean isDocked) {
+        if (DEBUG) Log.d(TAG, "onWakeKeyWhenKeyguardShowing(" + keyCode + ")");
+
+        if (isWakeKeyWhenKeyguardShowing(keyCode, isDocked)) {
+            // give the keyguard view manager a chance to adjust the state of the
+            // keyguard based on the key that woke the device before poking
+            // the wake lock
+            wakeWhenReadyLocked(keyCode);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * When the keyguard is showing we ignore some keys that might otherwise typically
+     * be considered wake keys.  We filter them out here.
+     *
+     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
+     * is always considered a wake key.
+     */
+    private boolean isWakeKeyWhenKeyguardShowing(int keyCode, boolean isDocked) {
+        switch (keyCode) {
+            // ignore volume keys unless docked
+            case KeyEvent.KEYCODE_VOLUME_UP:
+            case KeyEvent.KEYCODE_VOLUME_DOWN:
+            case KeyEvent.KEYCODE_VOLUME_MUTE:
+                return isDocked;
+
+            // ignore media and camera keys
+            case KeyEvent.KEYCODE_MUTE:
+            case KeyEvent.KEYCODE_HEADSETHOOK:
+            case KeyEvent.KEYCODE_MEDIA_PLAY:
+            case KeyEvent.KEYCODE_MEDIA_PAUSE:
+            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+            case KeyEvent.KEYCODE_MEDIA_STOP:
+            case KeyEvent.KEYCODE_MEDIA_NEXT:
+            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+            case KeyEvent.KEYCODE_MEDIA_REWIND:
+            case KeyEvent.KEYCODE_MEDIA_RECORD:
+            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
+            case KeyEvent.KEYCODE_CAMERA:
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * When a wake motion such as an external mouse movement is received when the screen
+     * is off and the keyguard is showing, we need to decide whether to actually turn
+     * on the screen, and if so, tell the keyguard to prepare itself and poke the wake
+     * lock when it is ready.
+     *
+     * The 'Tq' suffix is per the documentation in {@link WindowManagerPolicy}.
+     * Be sure not to take any action that takes a long time; any significant
+     * action should be posted to a handler.
+     *
+     * @return Whether we poked the wake lock (and turned the screen on)
+     */
+    public boolean onWakeMotionWhenKeyguardShowingTq() {
+        if (DEBUG) Log.d(TAG, "onWakeMotionWhenKeyguardShowing()");
+
+        // give the keyguard view manager a chance to adjust the state of the
+        // keyguard based on the key that woke the device before poking
+        // the wake lock
+        wakeWhenReadyLocked(KeyEvent.KEYCODE_UNKNOWN);
+        return true;
+    }
+
+    /**
+     * Callbacks from {@link KeyguardViewManager}.
+     */
+
+    /** {@inheritDoc} */
+    public void pokeWakelock() {
+        pokeWakelock(AWAKE_INTERVAL_DEFAULT_MS);
+    }
+
+    /** {@inheritDoc} */
+    public void pokeWakelock(int holdMs) {
+        synchronized (this) {
+            if (DBG_WAKE) Log.d(TAG, "pokeWakelock(" + holdMs + ")");
+            mWakeLock.acquire();
+            mHandler.removeMessages(TIMEOUT);
+            mWakelockSequence++;
+            Message msg = mHandler.obtainMessage(TIMEOUT, mWakelockSequence, 0);
+            mHandler.sendMessageDelayed(msg, holdMs);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @see #handleKeyguardDone
+     */
+    public void keyguardDone(boolean authenticated) {
+        keyguardDone(authenticated, true);
+    }
+
+    public void keyguardDone(boolean authenticated, boolean wakeup) {
+        synchronized (this) {
+            EventLog.writeEvent(70000, 2);
+            if (DEBUG) Log.d(TAG, "keyguardDone(" + authenticated + ")");
+            Message msg = mHandler.obtainMessage(KEYGUARD_DONE);
+            msg.arg1 = wakeup ? 1 : 0;
+            mHandler.sendMessage(msg);
+
+            if (authenticated) {
+                mUpdateMonitor.clearFailedAttempts();
+            }
+
+            if (mExitSecureCallback != null) {
+                mExitSecureCallback.onKeyguardExitResult(authenticated);
+                mExitSecureCallback = null;
+
+                if (authenticated) {
+                    // after succesfully exiting securely, no need to reshow
+                    // the keyguard when they've released the lock
+                    mExternallyEnabled = true;
+                    mNeedToReshowWhenReenabled = false;
+                }
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @see #handleKeyguardDoneDrawing
+     */
+    public void keyguardDoneDrawing() {
+        mHandler.sendEmptyMessage(KEYGUARD_DONE_DRAWING);
+    }
+
+    /**
+     * This handler will be associated with the policy thread, which will also
+     * be the UI thread of the keyguard.  Since the apis of the policy, and therefore
+     * this class, can be called by other threads, any action that directly
+     * interacts with the keyguard ui should be posted to this handler, rather
+     * than called directly.
+     */
+    private Handler mHandler = new Handler(true /*async*/) {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case TIMEOUT:
+                    handleTimeout(msg.arg1);
+                    return ;
+                case SHOW:
+                    handleShow();
+                    return ;
+                case HIDE:
+                    handleHide();
+                    return ;
+                case RESET:
+                    handleReset();
+                    return ;
+                case VERIFY_UNLOCK:
+                    handleVerifyUnlock();
+                    return;
+                case NOTIFY_SCREEN_OFF:
+                    handleNotifyScreenOff();
+                    return;
+                case NOTIFY_SCREEN_ON:
+                    handleNotifyScreenOn((KeyguardViewManager.ShowListener)msg.obj);
+                    return;
+                case WAKE_WHEN_READY:
+                    handleWakeWhenReady(msg.arg1);
+                    return;
+                case KEYGUARD_DONE:
+                    handleKeyguardDone(msg.arg1 != 0);
+                    return;
+                case KEYGUARD_DONE_DRAWING:
+                    handleKeyguardDoneDrawing();
+                    return;
+                case KEYGUARD_DONE_AUTHENTICATING:
+                    keyguardDone(true);
+                    return;
+                case SET_HIDDEN:
+                    handleSetHidden(msg.arg1 != 0);
+                    break;
+                case KEYGUARD_TIMEOUT:
+                    synchronized (KeyguardViewMediator.this) {
+                        doKeyguardLocked();
+                    }
+                    break;
+            }
+        }
+    };
+
+    /**
+     * @see #keyguardDone
+     * @see #KEYGUARD_DONE
+     */
+    private void handleKeyguardDone(boolean wakeup) {
+        if (DEBUG) Log.d(TAG, "handleKeyguardDone");
+        handleHide();
+        if (wakeup) {
+            mPM.wakeUp(SystemClock.uptimeMillis());
+        }
+        mWakeLock.release();
+
+        final UserHandle currentUser = new UserHandle(mLockPatternUtils.getCurrentUser());
+        mContext.sendBroadcastAsUser(mUserPresentIntent, currentUser);
+    }
+
+    /**
+     * @see #keyguardDoneDrawing
+     * @see #KEYGUARD_DONE_DRAWING
+     */
+    private void handleKeyguardDoneDrawing() {
+        synchronized(this) {
+            if (false) Log.d(TAG, "handleKeyguardDoneDrawing");
+            if (mWaitingUntilKeyguardVisible) {
+                if (DEBUG) Log.d(TAG, "handleKeyguardDoneDrawing: notifying mWaitingUntilKeyguardVisible");
+                mWaitingUntilKeyguardVisible = false;
+                notifyAll();
+
+                // there will usually be two of these sent, one as a timeout, and one
+                // as a result of the callback, so remove any remaining messages from
+                // the queue
+                mHandler.removeMessages(KEYGUARD_DONE_DRAWING);
+            }
+        }
+    }
+
+    /**
+     * Handles the message sent by {@link #pokeWakelock}
+     * @param seq used to determine if anything has changed since the message
+     *   was sent.
+     * @see #TIMEOUT
+     */
+    private void handleTimeout(int seq) {
+        synchronized (KeyguardViewMediator.this) {
+            if (DEBUG) Log.d(TAG, "handleTimeout");
+            if (seq == mWakelockSequence) {
+                mWakeLock.release();
+            }
+        }
+    }
+
+    private void playSounds(boolean locked) {
+        // User feedback for keyguard.
+
+        if (mSuppressNextLockSound) {
+            mSuppressNextLockSound = false;
+            return;
+        }
+
+        final ContentResolver cr = mContext.getContentResolver();
+        if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) {
+            final int whichSound = locked
+                ? mLockSoundId
+                : mUnlockSoundId;
+            mLockSounds.stop(mLockSoundStreamId);
+            // Init mAudioManager
+            if (mAudioManager == null) {
+                mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+                if (mAudioManager == null) return;
+                mMasterStreamType = mAudioManager.getMasterStreamType();
+            }
+            // If the stream is muted, don't play the sound
+            if (mAudioManager.isStreamMute(mMasterStreamType)) return;
+
+            mLockSoundStreamId = mLockSounds.play(whichSound,
+                    mLockSoundVolume, mLockSoundVolume, 1/*priortiy*/, 0/*loop*/, 1.0f/*rate*/);
+        }
+    }
+
+    private void updateActivityLockScreenState() {
+        try {
+            ActivityManagerNative.getDefault().setLockScreenShown(
+                    mShowing && !mHidden);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Handle message sent by {@link #showLocked}.
+     * @see #SHOW
+     */
+    private void handleShow() {
+        synchronized (KeyguardViewMediator.this) {
+            if (DEBUG) Log.d(TAG, "handleShow");
+            if (!mSystemReady) return;
+
+            mKeyguardViewManager.show();
+            mShowing = true;
+            updateActivityLockScreenState();
+            adjustUserActivityLocked();
+            adjustStatusBarLocked();
+            try {
+                ActivityManagerNative.getDefault().closeSystemDialogs("lock");
+            } catch (RemoteException e) {
+            }
+
+            // Do this at the end to not slow down display of the keyguard.
+            playSounds(true);
+
+            mShowKeyguardWakeLock.release();
+        }
+    }
+
+    /**
+     * Handle message sent by {@link #hideLocked()}
+     * @see #HIDE
+     */
+    private void handleHide() {
+        synchronized (KeyguardViewMediator.this) {
+            if (DEBUG) Log.d(TAG, "handleHide");
+            if (mWakeAndHandOff.isHeld()) {
+                Log.w(TAG, "attempt to hide the keyguard while waking, ignored");
+                return;
+            }
+
+            // only play "unlock" noises if not on a call (since the incall UI
+            // disables the keyguard)
+            if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) {
+                playSounds(false);
+            }
+
+            mKeyguardViewManager.hide();
+            mShowing = false;
+            updateActivityLockScreenState();
+            adjustUserActivityLocked();
+            adjustStatusBarLocked();
+        }
+    }
+
+    private void adjustUserActivityLocked() {
+        // disable user activity if we are shown and not hidden
+        if (DEBUG) Log.d(TAG, "adjustUserActivityLocked mShowing: " + mShowing + " mHidden: " + mHidden);
+        boolean enabled = !mShowing || mHidden;
+        // FIXME: Replace this with a new timeout control mechanism.
+        //mRealPowerManager.enableUserActivity(enabled);
+        if (!enabled && mScreenOn) {
+            // reinstate our short screen timeout policy
+            pokeWakelock();
+        }
+    }
+
+    private void adjustStatusBarLocked() {
+        if (mStatusBarManager == null) {
+            mStatusBarManager = (StatusBarManager)
+                    mContext.getSystemService(Context.STATUS_BAR_SERVICE);
+        }
+        if (mStatusBarManager == null) {
+            Log.w(TAG, "Could not get status bar manager");
+        } else {
+            if (mShowLockIcon) {
+                // Give feedback to user when secure keyguard is active and engaged
+                if (mShowing && isSecure()) {
+                    if (!mShowingLockIcon) {
+                        String contentDescription = mContext.getString(
+                                com.android.internal.R.string.status_bar_device_locked);
+                        mStatusBarManager.setIcon("secure",
+                                com.android.internal.R.drawable.stat_sys_secure, 0,
+                                contentDescription);
+                        mShowingLockIcon = true;
+                    }
+                } else {
+                    if (mShowingLockIcon) {
+                        mStatusBarManager.removeIcon("secure");
+                        mShowingLockIcon = false;
+                    }
+                }
+            }
+
+            // Disable aspects of the system/status/navigation bars that must not be re-enabled by
+            // windows that appear on top, ever
+            int flags = StatusBarManager.DISABLE_NONE;
+            if (mShowing) {
+                // disable navigation status bar components (home, recents) if lock screen is up
+                flags |= StatusBarManager.DISABLE_RECENT;
+                if (isSecure() || !ENABLE_INSECURE_STATUS_BAR_EXPAND) {
+                    // showing secure lockscreen; disable expanding.
+                    flags |= StatusBarManager.DISABLE_EXPAND;
+                }
+                if (isSecure()) {
+                    // showing secure lockscreen; disable ticker.
+                    flags |= StatusBarManager.DISABLE_NOTIFICATION_TICKER;
+                }
+            }
+
+            if (DEBUG) {
+                Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mHidden=" + mHidden
+                        + " isSecure=" + isSecure() + " --> flags=0x" + Integer.toHexString(flags));
+            }
+
+            mStatusBarManager.disable(flags);
+        }
+    }
+
+    /**
+     * Handle message sent by {@link #wakeWhenReadyLocked(int)}
+     * @param keyCode The key that woke the device.
+     * @see #WAKE_WHEN_READY
+     */
+    private void handleWakeWhenReady(int keyCode) {
+        synchronized (KeyguardViewMediator.this) {
+            if (DBG_WAKE) Log.d(TAG, "handleWakeWhenReady(" + keyCode + ")");
+
+            // this should result in a call to 'poke wakelock' which will set a timeout
+            // on releasing the wakelock
+            if (!mKeyguardViewManager.wakeWhenReadyTq(keyCode)) {
+                // poke wakelock ourselves if keyguard is no longer active
+                Log.w(TAG, "mKeyguardViewManager.wakeWhenReadyTq did not poke wake lock, so poke it ourselves");
+                pokeWakelock();
+            }
+
+            /**
+             * Now that the keyguard is ready and has poked the wake lock, we can
+             * release the handoff wakelock
+             */
+            mWakeAndHandOff.release();
+
+            if (!mWakeLock.isHeld()) {
+                Log.w(TAG, "mWakeLock not held in mKeyguardViewManager.wakeWhenReadyTq");
+            }
+        }
+    }
+
+    /**
+     * Handle message sent by {@link #resetStateLocked()}
+     * @see #RESET
+     */
+    private void handleReset() {
+        synchronized (KeyguardViewMediator.this) {
+            if (DEBUG) Log.d(TAG, "handleReset");
+            mKeyguardViewManager.reset();
+        }
+    }
+
+    /**
+     * Handle message sent by {@link #verifyUnlock}
+     * @see #RESET
+     */
+    private void handleVerifyUnlock() {
+        synchronized (KeyguardViewMediator.this) {
+            if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
+            mKeyguardViewManager.verifyUnlock();
+            mShowing = true;
+            updateActivityLockScreenState();
+        }
+    }
+
+    /**
+     * Handle message sent by {@link #notifyScreenOffLocked()}
+     * @see #NOTIFY_SCREEN_OFF
+     */
+    private void handleNotifyScreenOff() {
+        synchronized (KeyguardViewMediator.this) {
+            if (DEBUG) Log.d(TAG, "handleNotifyScreenOff");
+            mKeyguardViewManager.onScreenTurnedOff();
+        }
+    }
+
+    /**
+     * Handle message sent by {@link #notifyScreenOnLocked()}
+     * @see #NOTIFY_SCREEN_ON
+     */
+    private void handleNotifyScreenOn(KeyguardViewManager.ShowListener showListener) {
+        synchronized (KeyguardViewMediator.this) {
+            if (DEBUG) Log.d(TAG, "handleNotifyScreenOn");
+            mKeyguardViewManager.onScreenTurnedOn(showListener);
+        }
+    }
+
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewProperties.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewProperties.java
new file mode 100644
index 0000000..676574d
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewProperties.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import android.content.Context;
+
+/**
+ * Defines operations necessary for showing a keyguard, including how to create
+ * it, and various properties that are useful to be able to query independant
+ * of whether the keyguard instance is around or not.
+ */
+public interface KeyguardViewProperties {
+
+    /**
+     * Create a keyguard view.
+     * @param context the context to use when creating the view.
+     * @param callback keyguard callback object for pokewakelock(), etc.
+     * @param updateMonitor configuration may be based on this.
+     * @param controller for talking back with the containing window.
+     * @return the view.
+     */
+    KeyguardViewBase createKeyguardView(Context context,
+            KeyguardViewCallback mCallback, KeyguardUpdateMonitor updateMonitor,
+            KeyguardWindowController controller);
+
+    /**
+     * Would the keyguard be secure right now?
+     * @return Whether the keyguard is currently secure, meaning it will block
+     *   the user from getting past it until the user enters some sort of PIN.
+     */
+    boolean isSecure();
+
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardWindowController.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardWindowController.java
new file mode 100644
index 0000000..98e3209
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardWindowController.java
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+/**
+ * Interface passed to the keyguard view, for it to call up to control
+ * its containing window.
+ */
+public interface KeyguardWindowController {
+    /**
+     * Control whether the window needs input -- that is if it has
+     * text fields and thus should allow input method interaction.
+     */
+    void setNeedsInput(boolean needsInput);
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardView.java
new file mode 100644
index 0000000..4dc83b6
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardView.java
@@ -0,0 +1,1220 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import com.android.internal.R;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockScreenWidgetCallback;
+import com.android.internal.widget.TransportControlView;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerCallback;
+import android.accounts.AccountManagerFuture;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
+import android.app.AlertDialog;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Slog;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
+
+import java.io.IOException;
+
+
+/**
+ * The host view for all of the screens of the pattern unlock screen.  There are
+ * two {@link Mode}s of operation, lock and unlock.  This will show the appropriate
+ * screen, and listen for callbacks via
+ * {@link com.android.internal.policy.impl.KeyguardScreenCallback}
+ * from the current screen.
+ *
+ * This view, in turn, communicates back to
+ * {@link com.android.internal.policy.impl.KeyguardViewManager}
+ * via its {@link com.android.internal.policy.impl.KeyguardViewCallback}, as appropriate.
+ */
+public class LockPatternKeyguardView extends KeyguardViewBase {
+
+    private static final int TRANSPORT_USERACTIVITY_TIMEOUT = 10000;
+
+    static final boolean DEBUG_CONFIGURATION = false;
+
+    // time after launching EmergencyDialer before the screen goes blank.
+    private static final int EMERGENCY_CALL_TIMEOUT = 10000;
+
+    // intent action for launching emergency dialer activity.
+    static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
+
+    private static final boolean DEBUG = false;
+    private static final String TAG = "LockPatternKeyguardView";
+
+    private final KeyguardUpdateMonitor mUpdateMonitor;
+    private final KeyguardWindowController mWindowController;
+
+    private View mLockScreen;
+    private View mUnlockScreen;
+
+    private boolean mScreenOn;
+    private boolean mWindowFocused = false;
+    private boolean mEnableFallback = false; // assume no fallback UI until we know better
+
+    private boolean mShowLockBeforeUnlock = false;
+
+    // Interface to a biometric sensor that can optionally be used to unlock the device
+    private BiometricSensorUnlock mBiometricUnlock;
+    private final Object mBiometricUnlockStartupLock = new Object();
+    // Long enough to stay visible while dialer comes up
+    // Short enough to not be visible if the user goes back immediately
+    private final int BIOMETRIC_AREA_EMERGENCY_DIALER_TIMEOUT = 1000;
+
+    private boolean mRequiresSim;
+    // True if the biometric unlock should not be displayed.  For example, if there is an overlay on
+    // lockscreen or the user is plugging in / unplugging the device.
+    private boolean mSuppressBiometricUnlock;
+    //True if a dialog is currently displaying on top of this window
+    //Unlike other overlays, this does not close with a power button cycle
+    private boolean mHasDialog = false;
+    //True if this device is currently plugged in
+    private boolean mPluggedIn;
+    // True the first time lockscreen is showing after boot
+    private static boolean sIsFirstAppearanceAfterBoot = true;
+
+    // The music control widget
+    private TransportControlView mTransportControlView;
+
+    private Parcelable mSavedState;
+
+    /**
+     * Either a lock screen (an informational keyguard screen), or an unlock
+     * screen (a means for unlocking the device) is shown at any given time.
+     */
+    enum Mode {
+        LockScreen,
+        UnlockScreen
+    }
+
+    /**
+     * The different types screens available for {@link Mode#UnlockScreen}.
+     * @see com.android.internal.policy.impl.LockPatternKeyguardView#getUnlockMode()
+     */
+    enum UnlockMode {
+
+        /**
+         * Unlock by drawing a pattern.
+         */
+        Pattern,
+
+        /**
+         * Unlock by entering a sim pin.
+         */
+        SimPin,
+
+        /**
+         * Unlock by entering a sim puk.
+         */
+        SimPuk,
+
+        /**
+         * Unlock by entering an account's login and password.
+         */
+        Account,
+
+        /**
+         * Unlock by entering a password or PIN
+         */
+        Password,
+
+        /**
+         * Unknown (uninitialized) value
+         */
+        Unknown
+    }
+
+    /**
+     * The current mode.
+     */
+    private Mode mMode = Mode.LockScreen;
+
+    /**
+     * Keeps track of what mode the current unlock screen is (cached from most recent computation in
+     * {@link #getUnlockMode}).
+     */
+    private UnlockMode mUnlockScreenMode = UnlockMode.Unknown;
+
+    private boolean mForgotPattern;
+
+    /**
+     * If true, it means we are in the process of verifying that the user
+     * can get past the lock screen per {@link #verifyUnlock()}
+     */
+    private boolean mIsVerifyUnlockOnly = false;
+
+    /**
+     * Used to lookup the state of the lock pattern
+     */
+    private final LockPatternUtils mLockPatternUtils;
+
+    /**
+     * The current configuration.
+     */
+    private Configuration mConfiguration;
+
+    private Runnable mRecreateRunnable = new Runnable() {
+        public void run() {
+            Mode mode = mMode;
+            // If we were previously in a locked state but now it's Unknown, it means the phone
+            // was previously locked because of SIM state and has since been resolved. This
+            // bit of code checks this condition and dismisses keyguard.
+            boolean dismissAfterCreation = false;
+            if (mode == Mode.UnlockScreen && getUnlockMode() == UnlockMode.Unknown) {
+                if (DEBUG) Log.v(TAG, "Switch to Mode.LockScreen because SIM unlocked");
+                mode = Mode.LockScreen;
+                dismissAfterCreation = true;
+            }
+            updateScreen(mode, true);
+            restoreWidgetState();
+            if (dismissAfterCreation) {
+                mKeyguardScreenCallback.keyguardDone(false);
+            }
+        }
+    };
+
+    private LockScreenWidgetCallback mWidgetCallback = new LockScreenWidgetCallback() {
+        public void userActivity(View self) {
+            mKeyguardScreenCallback.pokeWakelock(TRANSPORT_USERACTIVITY_TIMEOUT);
+        }
+
+        public void requestShow(View view) {
+            if (DEBUG) Log.v(TAG, "View " + view + " requested show transports");
+            view.setVisibility(View.VISIBLE);
+
+            // TODO: examine all widgets to derive clock status
+            mUpdateMonitor.reportClockVisible(false);
+
+            // If there's not a bg protection view containing the transport, then show a black
+            // background. Otherwise, allow the normal background to show.
+            if (findViewById(R.id.transport_bg_protect) == null) {
+                // TODO: We should disable the wallpaper instead
+                setBackgroundColor(0xff000000);
+            } else {
+                resetBackground();
+            }
+        }
+
+        public void requestHide(View view) {
+            if (DEBUG) Log.v(TAG, "View " + view + " requested hide transports");
+            view.setVisibility(View.GONE);
+
+            // TODO: examine all widgets to derive clock status
+            mUpdateMonitor.reportClockVisible(true);
+            resetBackground();
+        }
+
+        public boolean isVisible(View self) {
+            // TODO: this should be up to the lockscreen to determine if the view
+            // is currently showing. The idea is it can be used for the widget to
+            // avoid doing work if it's not visible. For now just returns the view's
+            // actual visibility.
+            return self.getVisibility() == View.VISIBLE;
+        }
+    };
+
+    /**
+     * @return Whether we are stuck on the lock screen because the sim is
+     *   missing.
+     */
+    private boolean stuckOnLockScreenBecauseSimMissing() {
+        return mRequiresSim
+                && (!mUpdateMonitor.isDeviceProvisioned())
+                && (mUpdateMonitor.getSimState() == IccCardConstants.State.ABSENT ||
+                    mUpdateMonitor.getSimState() == IccCardConstants.State.PERM_DISABLED);
+    }
+
+    /**
+     * The current {@link KeyguardScreen} will use this to communicate back to us.
+     */
+    KeyguardScreenCallback mKeyguardScreenCallback = new KeyguardScreenCallback() {
+
+        public void goToLockScreen() {
+            mForgotPattern = false;
+            if (mIsVerifyUnlockOnly) {
+                // navigating away from unlock screen during verify mode means
+                // we are done and the user failed to authenticate.
+                mIsVerifyUnlockOnly = false;
+                getCallback().keyguardDone(false);
+            } else {
+                updateScreen(Mode.LockScreen, false);
+            }
+        }
+
+        public void goToUnlockScreen() {
+            final IccCardConstants.State simState = mUpdateMonitor.getSimState();
+            if (stuckOnLockScreenBecauseSimMissing()
+                     || (simState == IccCardConstants.State.PUK_REQUIRED
+                         && !mLockPatternUtils.isPukUnlockScreenEnable())){
+                // stuck on lock screen when sim missing or
+                // puk'd but puk unlock screen is disabled
+                return;
+            }
+            if (!isSecure()) {
+                getCallback().keyguardDone(true);
+            } else {
+                updateScreen(Mode.UnlockScreen, false);
+            }
+        }
+
+        public void forgotPattern(boolean isForgotten) {
+            if (mEnableFallback) {
+                mForgotPattern = isForgotten;
+                updateScreen(Mode.UnlockScreen, false);
+            }
+        }
+
+        public boolean isSecure() {
+            return LockPatternKeyguardView.this.isSecure();
+        }
+
+        public boolean isVerifyUnlockOnly() {
+            return mIsVerifyUnlockOnly;
+        }
+
+        public void recreateMe(Configuration config) {
+            if (DEBUG) Log.v(TAG, "recreateMe()");
+            removeCallbacks(mRecreateRunnable);
+            post(mRecreateRunnable);
+        }
+
+        public void takeEmergencyCallAction() {
+            mSuppressBiometricUnlock = true;
+
+            if (mBiometricUnlock != null) {
+                if (mBiometricUnlock.isRunning()) {
+                    // Continue covering backup lock until dialer comes up or call is resumed
+                    mBiometricUnlock.show(BIOMETRIC_AREA_EMERGENCY_DIALER_TIMEOUT);
+                }
+
+                // We must ensure the biometric unlock is stopped when emergency call is pressed
+                mBiometricUnlock.stop();
+            }
+
+            pokeWakelock(EMERGENCY_CALL_TIMEOUT);
+            if (TelephonyManager.getDefault().getCallState()
+                    == TelephonyManager.CALL_STATE_OFFHOOK) {
+                mLockPatternUtils.resumeCall();
+            } else {
+                Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
+                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+                getContext().startActivity(intent);
+            }
+        }
+
+        public void pokeWakelock() {
+            getCallback().pokeWakelock();
+        }
+
+        public void pokeWakelock(int millis) {
+            getCallback().pokeWakelock(millis);
+        }
+
+        public void keyguardDone(boolean authenticated) {
+            getCallback().keyguardDone(authenticated);
+            mSavedState = null; // clear state so we re-establish when locked again
+        }
+
+        public void keyguardDoneDrawing() {
+            // irrelevant to keyguard screen, they shouldn't be calling this
+        }
+
+        public void reportFailedUnlockAttempt() {
+            mUpdateMonitor.reportFailedAttempt();
+            final int failedAttempts = mUpdateMonitor.getFailedAttempts();
+            if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts +
+                " (enableFallback=" + mEnableFallback + ")");
+
+            final boolean usingPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality()
+                    == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+
+            final int failedAttemptsBeforeWipe = mLockPatternUtils.getDevicePolicyManager()
+                    .getMaximumFailedPasswordsForWipe(null);
+
+            final int failedAttemptWarning = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
+                    - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
+
+            final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ?
+                    (failedAttemptsBeforeWipe - failedAttempts)
+                    : Integer.MAX_VALUE; // because DPM returns 0 if no restriction
+
+            if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {
+                // If we reach this code, it means the user has installed a DevicePolicyManager
+                // that requests device wipe after N attempts.  Once we get below the grace
+                // period, we'll post this dialog every time as a clear warning until the
+                // bombshell hits and the device is wiped.
+                if (remainingBeforeWipe > 0) {
+                    showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe);
+                } else {
+                    // Too many attempts. The device will be wiped shortly.
+                    Slog.i(TAG, "Too many unlock attempts; device will be wiped!");
+                    showWipeDialog(failedAttempts);
+                }
+            } else {
+                boolean showTimeout =
+                    (failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0;
+                if (usingPattern && mEnableFallback) {
+                    if (failedAttempts == failedAttemptWarning) {
+                        showAlmostAtAccountLoginDialog();
+                        showTimeout = false; // don't show both dialogs
+                    } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
+                        mLockPatternUtils.setPermanentlyLocked(true);
+                        updateScreen(mMode, false);
+                        // don't show timeout dialog because we show account unlock screen next
+                        showTimeout = false;
+                    }
+                }
+                if (showTimeout) {
+                    showTimeoutDialog();
+                }
+            }
+            mLockPatternUtils.reportFailedPasswordAttempt();
+        }
+
+        public boolean doesFallbackUnlockScreenExist() {
+            return mEnableFallback;
+        }
+
+        public void reportSuccessfulUnlockAttempt() {
+            mLockPatternUtils.reportSuccessfulPasswordAttempt();
+        }
+    };
+
+    /**
+     * @param context Used to inflate, and create views.
+     * @param callback Keyguard callback object for pokewakelock(), etc.
+     * @param updateMonitor Knows the state of the world, and passed along to each
+     *   screen so they can use the knowledge, and also register for callbacks
+     *   on dynamic information.
+     * @param lockPatternUtils Used to look up state of lock pattern.
+     */
+    public LockPatternKeyguardView(
+            Context context, KeyguardViewCallback callback, KeyguardUpdateMonitor updateMonitor,
+            LockPatternUtils lockPatternUtils, KeyguardWindowController controller) {
+        super(context, callback);
+
+        mConfiguration = context.getResources().getConfiguration();
+        mEnableFallback = false;
+        mRequiresSim = TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim"));
+        mUpdateMonitor = updateMonitor;
+        mLockPatternUtils = lockPatternUtils;
+        mWindowController = controller;
+        mSuppressBiometricUnlock = sIsFirstAppearanceAfterBoot;
+        sIsFirstAppearanceAfterBoot = false;
+        mScreenOn = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)).isScreenOn();
+        mUpdateMonitor.registerCallback(mInfoCallback);
+
+        /**
+         * We'll get key events the current screen doesn't use. see
+         * {@link KeyguardViewBase#onKeyDown(int, android.view.KeyEvent)}
+         */
+        setFocusableInTouchMode(true);
+        setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
+
+        updateScreen(getInitialMode(), false);
+        maybeEnableFallback(context);
+    }
+
+    private class AccountAnalyzer implements AccountManagerCallback<Bundle> {
+        private final AccountManager mAccountManager;
+        private final Account[] mAccounts;
+        private int mAccountIndex;
+
+        private AccountAnalyzer(AccountManager accountManager) {
+            mAccountManager = accountManager;
+            mAccounts = accountManager.getAccountsByType("com.google");
+        }
+
+        private void next() {
+            // if we are ready to enable the fallback or if we depleted the list of accounts
+            // then finish and get out
+            if (mEnableFallback || mAccountIndex >= mAccounts.length) {
+                if (mUnlockScreen == null) {
+                    if (DEBUG) Log.w(TAG, "no unlock screen when trying to enable fallback");
+                } else if (mUnlockScreen instanceof PatternUnlockScreen) {
+                    ((PatternUnlockScreen)mUnlockScreen).setEnableFallback(mEnableFallback);
+                }
+                return;
+            }
+
+            // lookup the confirmCredentials intent for the current account
+            mAccountManager.confirmCredentials(mAccounts[mAccountIndex], null, null, this, null);
+        }
+
+        public void start() {
+            mEnableFallback = false;
+            mAccountIndex = 0;
+            next();
+        }
+
+        public void run(AccountManagerFuture<Bundle> future) {
+            try {
+                Bundle result = future.getResult();
+                if (result.getParcelable(AccountManager.KEY_INTENT) != null) {
+                    mEnableFallback = true;
+                }
+            } catch (OperationCanceledException e) {
+                // just skip the account if we are unable to query it
+            } catch (IOException e) {
+                // just skip the account if we are unable to query it
+            } catch (AuthenticatorException e) {
+                // just skip the account if we are unable to query it
+            } finally {
+                mAccountIndex++;
+                next();
+            }
+        }
+    }
+
+    private void maybeEnableFallback(Context context) {
+        // Ask the account manager if we have an account that can be used as a
+        // fallback in case the user forgets his pattern.
+        AccountAnalyzer accountAnalyzer = new AccountAnalyzer(AccountManager.get(context));
+        accountAnalyzer.start();
+    }
+
+
+    // TODO:
+    // This overloaded method was added to workaround a race condition in the framework between
+    // notification for orientation changed, layout() and switching resources.  This code attempts
+    // to avoid drawing the incorrect layout while things are in transition.  The method can just
+    // be removed once the race condition is fixed. See bugs 2262578 and 2292713.
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        if (DEBUG) Log.v(TAG, "*** dispatchDraw() time: " + SystemClock.elapsedRealtime());
+        super.dispatchDraw(canvas);
+    }
+
+    @Override
+    public void reset() {
+        mIsVerifyUnlockOnly = false;
+        mForgotPattern = false;
+        if (DEBUG) Log.v(TAG, "reset()");
+        post(mRecreateRunnable);
+    }
+
+    @Override
+    public void onScreenTurnedOff() {
+        if (DEBUG) Log.d(TAG, "screen off");
+        mScreenOn = false;
+        mForgotPattern = false;
+
+        // Emulate activity life-cycle for both lock and unlock screen.
+        if (mLockScreen != null) {
+            ((KeyguardScreen) mLockScreen).onPause();
+        }
+        if (mUnlockScreen != null) {
+            ((KeyguardScreen) mUnlockScreen).onPause();
+        }
+
+        saveWidgetState();
+
+        if (mBiometricUnlock != null) {
+            // The biometric unlock must stop when screen turns off.
+            mBiometricUnlock.stop();
+        }
+    }
+
+    @Override
+    public void onScreenTurnedOn() {
+        if (DEBUG) Log.d(TAG, "screen on");
+        boolean startBiometricUnlock = false;
+        // Start the biometric unlock if and only if the screen is both on and focused
+        synchronized(mBiometricUnlockStartupLock) {
+            mScreenOn = true;
+            startBiometricUnlock = mWindowFocused;
+        }
+
+        show();
+
+        restoreWidgetState();
+
+        if (mBiometricUnlock != null && startBiometricUnlock) {
+            maybeStartBiometricUnlock();
+        }
+    }
+
+    private void saveWidgetState() {
+        if (mTransportControlView != null) {
+            if (DEBUG) Log.v(TAG, "Saving widget state");
+            mSavedState = mTransportControlView.onSaveInstanceState();
+        }
+    }
+
+    private void restoreWidgetState() {
+        if (mTransportControlView != null) {
+            if (DEBUG) Log.v(TAG, "Restoring widget state");
+            if (mSavedState != null) {
+                mTransportControlView.onRestoreInstanceState(mSavedState);
+            }
+        }
+    }
+
+    /**
+     * Stop the biometric unlock if something covers this window (such as an alarm)
+     * Start the biometric unlock if the lockscreen window just came into focus and the screen is on
+     */
+    @Override
+    public void onWindowFocusChanged (boolean hasWindowFocus) {
+        if (DEBUG) Log.d(TAG, hasWindowFocus ? "focused" : "unfocused");
+
+        boolean startBiometricUnlock = false;
+        // Start the biometric unlock if and only if the screen is both on and focused
+        synchronized(mBiometricUnlockStartupLock) {
+            if (mScreenOn && !mWindowFocused) startBiometricUnlock = hasWindowFocus;
+            mWindowFocused = hasWindowFocus;
+        }
+        if (!hasWindowFocus) {
+            if (mBiometricUnlock != null) {
+                mSuppressBiometricUnlock = true;
+                mBiometricUnlock.stop();
+                mBiometricUnlock.hide();
+            }
+        } else {
+            mHasDialog = false;
+            if (mBiometricUnlock != null && startBiometricUnlock) {
+                maybeStartBiometricUnlock();
+            }
+        }
+    }
+
+    @Override
+    public void show() {
+        // Emulate activity life-cycle for both lock and unlock screen.
+        if (mLockScreen != null) {
+            ((KeyguardScreen) mLockScreen).onResume();
+        }
+        if (mUnlockScreen != null) {
+            ((KeyguardScreen) mUnlockScreen).onResume();
+        }
+
+        if (mBiometricUnlock != null && mSuppressBiometricUnlock) {
+            mBiometricUnlock.hide();
+        }
+    }
+
+    private void recreateLockScreen() {
+        if (mLockScreen != null) {
+            ((KeyguardScreen) mLockScreen).onPause();
+            ((KeyguardScreen) mLockScreen).cleanUp();
+            removeView(mLockScreen);
+        }
+
+        mLockScreen = createLockScreen();
+        mLockScreen.setVisibility(View.INVISIBLE);
+        addView(mLockScreen);
+    }
+
+    private void recreateUnlockScreen(UnlockMode unlockMode) {
+        if (mUnlockScreen != null) {
+            ((KeyguardScreen) mUnlockScreen).onPause();
+            ((KeyguardScreen) mUnlockScreen).cleanUp();
+            removeView(mUnlockScreen);
+        }
+
+        mUnlockScreen = createUnlockScreenFor(unlockMode);
+        mUnlockScreen.setVisibility(View.INVISIBLE);
+        addView(mUnlockScreen);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        mUpdateMonitor.removeCallback(mInfoCallback);
+
+        removeCallbacks(mRecreateRunnable);
+
+        if (mBiometricUnlock != null) {
+            // When view is hidden, we need to stop the biometric unlock
+            // e.g., when device becomes unlocked
+            mBiometricUnlock.stop();
+        }
+
+        super.onDetachedFromWindow();
+    }
+
+    protected void onConfigurationChanged(Configuration newConfig) {
+        Resources resources = getResources();
+        mShowLockBeforeUnlock = resources.getBoolean(R.bool.config_enableLockBeforeUnlockScreen);
+        mConfiguration = newConfig;
+        if (DEBUG_CONFIGURATION) Log.v(TAG, "**** re-creating lock screen since config changed");
+        saveWidgetState();
+        removeCallbacks(mRecreateRunnable);
+        if (DEBUG) Log.v(TAG, "recreating lockscreen because config changed");
+        post(mRecreateRunnable);
+    }
+
+    KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
+
+        @Override
+        public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) {
+            // When someone plugs in or unplugs the device, we hide the biometric sensor area and
+            // suppress its startup for the next onScreenTurnedOn().  Since plugging/unplugging
+            // causes the screen to turn on, the biometric unlock would start if it wasn't
+            // suppressed.
+            //
+            // However, if the biometric unlock is already running, we do not want to interrupt it.
+            final boolean pluggedIn = status.isPluggedIn();
+            if (mBiometricUnlock != null && mPluggedIn != pluggedIn
+                    && !mBiometricUnlock.isRunning()) {
+                mBiometricUnlock.stop();
+                mBiometricUnlock.hide();
+                mSuppressBiometricUnlock = true;
+            }
+            mPluggedIn = pluggedIn;
+        }
+
+        @Override
+        public void onClockVisibilityChanged() {
+            int visFlags = (getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_CLOCK)
+                    | (mUpdateMonitor.isClockVisible() ? View.STATUS_BAR_DISABLE_CLOCK : 0);
+            Log.v(TAG, "Set visibility on " + this + " to " + visFlags);
+            setSystemUiVisibility(visFlags);
+        }
+
+        // We need to stop the biometric unlock when a phone call comes in
+        @Override
+        public void onPhoneStateChanged(int phoneState) {
+            if (DEBUG) Log.d(TAG, "phone state: " + phoneState);
+            if (mBiometricUnlock != null && phoneState == TelephonyManager.CALL_STATE_RINGING) {
+                mSuppressBiometricUnlock = true;
+                mBiometricUnlock.stop();
+                mBiometricUnlock.hide();
+            }
+        }
+
+        @Override
+        public void onUserSwitched(int userId) {
+            if (mBiometricUnlock != null) {
+                mBiometricUnlock.stop();
+            }
+            mLockPatternUtils.setCurrentUser(userId);
+            updateScreen(getInitialMode(), true);
+        }
+    };
+
+    @Override
+    protected boolean dispatchHoverEvent(MotionEvent event) {
+        // Do not let the screen to get locked while the user is disabled and touch
+        // exploring. A blind user will need significantly more time to find and
+        // interact with the lock screen views.
+        AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(mContext);
+        if (accessibilityManager.isEnabled() && accessibilityManager.isTouchExplorationEnabled()) {
+            getCallback().pokeWakelock();
+        }
+        return super.dispatchHoverEvent(event);
+    }
+
+    @Override
+    public void wakeWhenReadyTq(int keyCode) {
+        if (DEBUG) Log.d(TAG, "onWakeKey");
+        if (keyCode == KeyEvent.KEYCODE_MENU && isSecure() && (mMode == Mode.LockScreen)
+                && (mUpdateMonitor.getSimState() != IccCardConstants.State.PUK_REQUIRED)) {
+            if (DEBUG) Log.d(TAG, "switching screens to unlock screen because wake key was MENU");
+            updateScreen(Mode.UnlockScreen, false);
+            getCallback().pokeWakelock();
+        } else {
+            if (DEBUG) Log.d(TAG, "poking wake lock immediately");
+            getCallback().pokeWakelock();
+        }
+    }
+
+    @Override
+    public void verifyUnlock() {
+        if (!isSecure()) {
+            // non-secure keyguard screens are successfull by default
+            getCallback().keyguardDone(true);
+        } else if (mUnlockScreenMode != UnlockMode.Pattern
+                && mUnlockScreenMode != UnlockMode.Password) {
+            // can only verify unlock when in pattern/password mode
+            getCallback().keyguardDone(false);
+        } else {
+            // otherwise, go to the unlock screen, see if they can verify it
+            mIsVerifyUnlockOnly = true;
+            updateScreen(Mode.UnlockScreen, false);
+        }
+    }
+
+    @Override
+    public void cleanUp() {
+        if (mLockScreen != null) {
+            ((KeyguardScreen) mLockScreen).onPause();
+            ((KeyguardScreen) mLockScreen).cleanUp();
+            this.removeView(mLockScreen);
+            mLockScreen = null;
+        }
+        if (mUnlockScreen != null) {
+            ((KeyguardScreen) mUnlockScreen).onPause();
+            ((KeyguardScreen) mUnlockScreen).cleanUp();
+            this.removeView(mUnlockScreen);
+            mUnlockScreen = null;
+        }
+        mUpdateMonitor.removeCallback(this);
+        if (mBiometricUnlock != null) {
+            mBiometricUnlock.cleanUp();
+        }
+    }
+
+    private boolean isSecure() {
+        UnlockMode unlockMode = getUnlockMode();
+        boolean secure = false;
+        switch (unlockMode) {
+            case Pattern:
+                secure = mLockPatternUtils.isLockPatternEnabled();
+                break;
+            case SimPin:
+                secure = mUpdateMonitor.getSimState() == IccCardConstants.State.PIN_REQUIRED;
+                break;
+            case SimPuk:
+                secure = mUpdateMonitor.getSimState() == IccCardConstants.State.PUK_REQUIRED;
+                break;
+            case Account:
+                secure = true;
+                break;
+            case Password:
+                secure = mLockPatternUtils.isLockPasswordEnabled();
+                break;
+            case Unknown:
+                // This means no security is set up
+                break;
+            default:
+                throw new IllegalStateException("unknown unlock mode " + unlockMode);
+        }
+        return secure;
+    }
+
+    private void updateScreen(Mode mode, boolean force) {
+
+        if (DEBUG_CONFIGURATION) Log.v(TAG, "**** UPDATE SCREEN: mode=" + mode
+                + " last mode=" + mMode + ", force = " + force, new RuntimeException());
+
+        mMode = mode;
+
+        // Re-create the lock screen if necessary
+        if (mode == Mode.LockScreen || mShowLockBeforeUnlock) {
+            if (force || mLockScreen == null) {
+                recreateLockScreen();
+            }
+        }
+
+        // Re-create the unlock screen if necessary.
+        final UnlockMode unlockMode = getUnlockMode();
+        if (mode == Mode.UnlockScreen && unlockMode != UnlockMode.Unknown) {
+            if (force || mUnlockScreen == null || unlockMode != mUnlockScreenMode) {
+                recreateUnlockScreen(unlockMode);
+            }
+        }
+
+        // visibleScreen should never be null
+        final View goneScreen = (mode == Mode.LockScreen) ? mUnlockScreen : mLockScreen;
+        final View visibleScreen = (mode == Mode.LockScreen) ? mLockScreen : mUnlockScreen;
+
+        // do this before changing visibility so focus isn't requested before the input
+        // flag is set
+        mWindowController.setNeedsInput(((KeyguardScreen)visibleScreen).needsInput());
+
+        if (DEBUG_CONFIGURATION) {
+            Log.v(TAG, "Gone=" + goneScreen);
+            Log.v(TAG, "Visible=" + visibleScreen);
+        }
+
+        if (mScreenOn) {
+            if (goneScreen != null && goneScreen.getVisibility() == View.VISIBLE) {
+                ((KeyguardScreen) goneScreen).onPause();
+            }
+            if (visibleScreen.getVisibility() != View.VISIBLE) {
+                ((KeyguardScreen) visibleScreen).onResume();
+            }
+        }
+
+        if (goneScreen != null) {
+            goneScreen.setVisibility(View.GONE);
+        }
+        visibleScreen.setVisibility(View.VISIBLE);
+        requestLayout();
+
+        if (!visibleScreen.requestFocus()) {
+            throw new IllegalStateException("keyguard screen must be able to take "
+                    + "focus when shown " + visibleScreen.getClass().getCanonicalName());
+        }
+    }
+
+    View createLockScreen() {
+        View lockView = new LockScreen(
+                mContext,
+                mConfiguration,
+                mLockPatternUtils,
+                mUpdateMonitor,
+                mKeyguardScreenCallback);
+        initializeTransportControlView(lockView);
+        return lockView;
+    }
+
+    View createUnlockScreenFor(UnlockMode unlockMode) {
+        View unlockView = null;
+
+        if (DEBUG) Log.d(TAG,
+                "createUnlockScreenFor(" + unlockMode + "): mEnableFallback=" + mEnableFallback);
+
+        if (unlockMode == UnlockMode.Pattern) {
+            PatternUnlockScreen view = new PatternUnlockScreen(
+                    mContext,
+                    mConfiguration,
+                    mLockPatternUtils,
+                    mUpdateMonitor,
+                    mKeyguardScreenCallback,
+                    mUpdateMonitor.getFailedAttempts());
+            view.setEnableFallback(mEnableFallback);
+            unlockView = view;
+        } else if (unlockMode == UnlockMode.SimPuk) {
+            unlockView = new SimPukUnlockScreen(
+                    mContext,
+                    mConfiguration,
+                    mUpdateMonitor,
+                    mKeyguardScreenCallback,
+                    mLockPatternUtils);
+        } else if (unlockMode == UnlockMode.SimPin) {
+            unlockView = new SimUnlockScreen(
+                    mContext,
+                    mConfiguration,
+                    mUpdateMonitor,
+                    mKeyguardScreenCallback,
+                    mLockPatternUtils);
+        } else if (unlockMode == UnlockMode.Account) {
+            try {
+                unlockView = new AccountUnlockScreen(
+                        mContext,
+                        mConfiguration,
+                        mUpdateMonitor,
+                        mKeyguardScreenCallback,
+                        mLockPatternUtils);
+            } catch (IllegalStateException e) {
+                Log.i(TAG, "Couldn't instantiate AccountUnlockScreen"
+                      + " (IAccountsService isn't available)");
+                // TODO: Need a more general way to provide a
+                // platform-specific fallback UI here.
+                // For now, if we can't display the account login
+                // unlock UI, just bring back the regular "Pattern" unlock mode.
+
+                // (We do this by simply returning a regular UnlockScreen
+                // here.  This means that the user will still see the
+                // regular pattern unlock UI, regardless of the value of
+                // mUnlockScreenMode or whether or not we're in the
+                // "permanently locked" state.)
+                return createUnlockScreenFor(UnlockMode.Pattern);
+            }
+        } else if (unlockMode == UnlockMode.Password) {
+            unlockView = new PasswordUnlockScreen(
+                    mContext,
+                    mConfiguration,
+                    mLockPatternUtils,
+                    mUpdateMonitor,
+                    mKeyguardScreenCallback);
+        } else {
+            throw new IllegalArgumentException("unknown unlock mode " + unlockMode);
+        }
+        initializeTransportControlView(unlockView);
+        initializeBiometricUnlockView(unlockView);
+
+        mUnlockScreenMode = unlockMode;
+        return unlockView;
+    }
+
+    private void initializeTransportControlView(View view) {
+        mTransportControlView = (TransportControlView) view.findViewById(R.id.transport);
+        if (mTransportControlView == null) {
+            if (DEBUG) Log.w(TAG, "Couldn't find transport control widget");
+        } else {
+            mUpdateMonitor.reportClockVisible(true);
+            mTransportControlView.setVisibility(View.GONE); // hide until it requests being shown.
+            mTransportControlView.setCallback(mWidgetCallback);
+        }
+    }
+
+    /**
+     * This returns false if there is any condition that indicates that the biometric unlock should
+     * not be used before the next time the unlock screen is recreated.  In other words, if this
+     * returns false there is no need to even construct the biometric unlock.
+     */
+    private boolean useBiometricUnlock() {
+        final UnlockMode unlockMode = getUnlockMode();
+        final boolean backupIsTimedOut = (mUpdateMonitor.getFailedAttempts() >=
+                LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
+        return (mLockPatternUtils.usingBiometricWeak() &&
+                mLockPatternUtils.isBiometricWeakInstalled() &&
+                !mUpdateMonitor.getMaxBiometricUnlockAttemptsReached() &&
+                !backupIsTimedOut &&
+                (unlockMode == UnlockMode.Pattern || unlockMode == UnlockMode.Password));
+    }
+
+    private void initializeBiometricUnlockView(View view) {
+        boolean restartBiometricUnlock = false;
+
+        if (mBiometricUnlock != null) {
+            restartBiometricUnlock = mBiometricUnlock.stop();
+        }
+
+        // Prevents biometric unlock from coming up immediately after a phone call or if there
+        // is a dialog on top of lockscreen. It is only updated if the screen is off because if the
+        // screen is on it's either because of an orientation change, or when it first boots.
+        // In both those cases, we don't want to override the current value of
+        // mSuppressBiometricUnlock and instead want to use the previous value.
+        if (!mScreenOn) {
+            mSuppressBiometricUnlock =
+                    mUpdateMonitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE
+                    || mHasDialog;
+        }
+
+        // If the biometric unlock is not being used, we don't bother constructing it.  Then we can
+        // simply check if it is null when deciding whether we should make calls to it.
+        mBiometricUnlock = null;
+        if (useBiometricUnlock()) {
+            // TODO: make faceLockAreaView a more general biometricUnlockView
+            // We will need to add our Face Unlock specific child views programmatically in
+            // initializeView rather than having them in the XML files.
+            View biometricUnlockView = view.findViewById(R.id.face_unlock_area_view);
+            if (biometricUnlockView != null) {
+                mBiometricUnlock = new FaceUnlock(mContext, mUpdateMonitor, mLockPatternUtils,
+                        mKeyguardScreenCallback);
+                mBiometricUnlock.initializeView(biometricUnlockView);
+
+                // If this is being called because the screen turned off, we want to cover the
+                // backup lock so it is covered when the screen turns back on.
+                if (!mScreenOn) mBiometricUnlock.show(0);
+            } else {
+                Log.w(TAG, "Couldn't find biometric unlock view");
+            }
+        }
+
+        if (mBiometricUnlock != null && restartBiometricUnlock) {
+            maybeStartBiometricUnlock();
+        }
+    }
+
+    /**
+     * Given the current state of things, what should be the initial mode of
+     * the lock screen (lock or unlock).
+     */
+    private Mode getInitialMode() {
+        final IccCardConstants.State simState = mUpdateMonitor.getSimState();
+        if (stuckOnLockScreenBecauseSimMissing() ||
+                (simState == IccCardConstants.State.PUK_REQUIRED &&
+                        !mLockPatternUtils.isPukUnlockScreenEnable())) {
+            return Mode.LockScreen;
+        } else {
+            if (!isSecure() || mShowLockBeforeUnlock) {
+                return Mode.LockScreen;
+            } else {
+                return Mode.UnlockScreen;
+            }
+        }
+    }
+
+    /**
+     * Given the current state of things, what should the unlock screen be?
+     */
+    private UnlockMode getUnlockMode() {
+        final IccCardConstants.State simState = mUpdateMonitor.getSimState();
+        UnlockMode currentMode;
+        if (simState == IccCardConstants.State.PIN_REQUIRED) {
+            currentMode = UnlockMode.SimPin;
+        } else if (simState == IccCardConstants.State.PUK_REQUIRED) {
+            currentMode = UnlockMode.SimPuk;
+        } else {
+            final int mode = mLockPatternUtils.getKeyguardStoredPasswordQuality();
+            switch (mode) {
+                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+                case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
+                case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+                case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
+                    currentMode = UnlockMode.Password;
+                    break;
+                case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+                case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
+                    if (mLockPatternUtils.isLockPatternEnabled()) {
+                        // "forgot pattern" button is only available in the pattern mode...
+                        if (mForgotPattern || mLockPatternUtils.isPermanentlyLocked()) {
+                            currentMode = UnlockMode.Account;
+                        } else {
+                            currentMode = UnlockMode.Pattern;
+                        }
+                    } else {
+                        currentMode = UnlockMode.Unknown;
+                    }
+                    break;
+                default:
+                   throw new IllegalStateException("Unknown unlock mode:" + mode);
+            }
+        }
+        return currentMode;
+    }
+
+    private void showDialog(String title, String message) {
+        mHasDialog = true;
+        final AlertDialog dialog = new AlertDialog.Builder(mContext)
+            .setTitle(title)
+            .setMessage(message)
+            .setNeutralButton(R.string.ok, null)
+            .create();
+        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+        dialog.show();
+    }
+
+    private void showTimeoutDialog() {
+        int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
+        int messageId = R.string.lockscreen_too_many_failed_attempts_dialog_message;
+        if (getUnlockMode() == UnlockMode.Password) {
+            if(mLockPatternUtils.getKeyguardStoredPasswordQuality() ==
+                DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {
+                messageId = R.string.lockscreen_too_many_failed_pin_attempts_dialog_message;
+            } else {
+                messageId = R.string.lockscreen_too_many_failed_password_attempts_dialog_message;
+            }
+        }
+        String message = mContext.getString(messageId, mUpdateMonitor.getFailedAttempts(),
+                timeoutInSeconds);
+
+        showDialog(null, message);
+    }
+
+    private void showAlmostAtAccountLoginDialog() {
+        final int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
+        final int count = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
+                - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
+        String message = mContext.getString(R.string.lockscreen_failed_attempts_almost_glogin,
+                count, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, timeoutInSeconds);
+        showDialog(null, message);
+    }
+
+    private void showAlmostAtWipeDialog(int attempts, int remaining) {
+        int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
+        String message = mContext.getString(
+                R.string.lockscreen_failed_attempts_almost_at_wipe, attempts, remaining);
+        showDialog(null, message);
+    }
+
+    private void showWipeDialog(int attempts) {
+        String message = mContext.getString(
+                R.string.lockscreen_failed_attempts_now_wiping, attempts);
+        showDialog(null, message);
+    }
+
+    /**
+     * Used to put wallpaper on the background of the lock screen.  Centers it
+     * Horizontally and pins the bottom (assuming that the lock screen is aligned
+     * with the bottom, so the wallpaper should extend above the top into the
+     * status bar).
+     */
+    static private class FastBitmapDrawable extends Drawable {
+        private Bitmap mBitmap;
+        private int mOpacity;
+
+        private FastBitmapDrawable(Bitmap bitmap) {
+            mBitmap = bitmap;
+            mOpacity = mBitmap.hasAlpha() ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            canvas.drawBitmap(
+                    mBitmap,
+                    (getBounds().width() - mBitmap.getWidth()) / 2,
+                    (getBounds().height() - mBitmap.getHeight()),
+                    null);
+        }
+
+        @Override
+        public int getOpacity() {
+            return mOpacity;
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {
+        }
+
+        @Override
+        public int getIntrinsicWidth() {
+            return mBitmap.getWidth();
+        }
+
+        @Override
+        public int getIntrinsicHeight() {
+            return mBitmap.getHeight();
+        }
+
+        @Override
+        public int getMinimumWidth() {
+            return mBitmap.getWidth();
+        }
+
+        @Override
+        public int getMinimumHeight() {
+            return mBitmap.getHeight();
+        }
+    }
+
+    /**
+     * Starts the biometric unlock if it should be started based on a number of factors including
+     * the mSuppressBiometricUnlock flag.  If it should not be started, it hides the biometric
+     * unlock area.
+     */
+    private void maybeStartBiometricUnlock() {
+        if (mBiometricUnlock != null) {
+            final boolean backupIsTimedOut = (mUpdateMonitor.getFailedAttempts() >=
+                    LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
+            if (!mSuppressBiometricUnlock
+                    && mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
+                    && !mUpdateMonitor.getMaxBiometricUnlockAttemptsReached()
+                    && !backupIsTimedOut) {
+                mBiometricUnlock.start();
+            } else {
+                mBiometricUnlock.hide();
+            }
+        }
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewProperties.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewProperties.java
new file mode 100644
index 0000000..5d9cc8e
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewProperties.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import com.android.internal.widget.LockPatternUtils;
+
+import android.content.Context;
+import com.android.internal.telephony.IccCardConstants;
+
+/**
+ * Knows how to create a lock pattern keyguard view, and answer questions about
+ * it (even if it hasn't been created, per the interface specs).
+ */
+public class LockPatternKeyguardViewProperties implements KeyguardViewProperties {
+
+    private final LockPatternUtils mLockPatternUtils;
+    private final KeyguardUpdateMonitor mUpdateMonitor;
+
+    /**
+     * @param lockPatternUtils Used to know whether the pattern enabled, and passed
+     *   onto the keygaurd view when it is created.
+     * @param updateMonitor Used to know whether the sim pin is enabled, and passed
+     *   onto the keyguard view when it is created.
+     */
+    public LockPatternKeyguardViewProperties(LockPatternUtils lockPatternUtils,
+            KeyguardUpdateMonitor updateMonitor) {
+        mLockPatternUtils = lockPatternUtils;
+        mUpdateMonitor = updateMonitor;
+    }
+
+    public KeyguardViewBase createKeyguardView(Context context,
+            KeyguardViewCallback callback,
+            KeyguardUpdateMonitor updateMonitor,
+            KeyguardWindowController controller) {
+        return new LockPatternKeyguardView(context, callback, updateMonitor,
+                mLockPatternUtils, controller);
+    }
+
+    public boolean isSecure() {
+        return mLockPatternUtils.isSecure() || isSimPinSecure();
+    }
+
+    private boolean isSimPinSecure() {
+        final IccCardConstants.State simState = mUpdateMonitor.getSimState();
+        return (simState == IccCardConstants.State.PIN_REQUIRED
+                || simState == IccCardConstants.State.PUK_REQUIRED
+                || simState == IccCardConstants.State.PERM_DISABLED);
+    }
+
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockScreen.java
new file mode 100644
index 0000000..4e9a1f7
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockScreen.java
@@ -0,0 +1,619 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import com.android.internal.R;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.SlidingTab;
+import com.android.internal.widget.WaveView;
+import com.android.internal.widget.multiwaveview.GlowPadView;
+
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.app.SearchManager;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.UserHandle;
+import android.os.Vibrator;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.*;
+import android.util.Log;
+import android.util.Slog;
+import android.media.AudioManager;
+import android.os.RemoteException;
+import android.provider.MediaStore;
+
+import java.io.File;
+
+/**
+ * The screen within {@link LockPatternKeyguardView} that shows general
+ * information about the device depending on its state, and how to get
+ * past it, as applicable.
+ */
+class LockScreen extends LinearLayout implements KeyguardScreen {
+
+    private static final int ON_RESUME_PING_DELAY = 500; // delay first ping until the screen is on
+    private static final boolean DBG = false;
+    private static final String TAG = "LockScreen";
+    private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
+    private static final int WAIT_FOR_ANIMATION_TIMEOUT = 0;
+    private static final int STAY_ON_WHILE_GRABBED_TIMEOUT = 30000;
+    private static final String ASSIST_ICON_METADATA_NAME =
+            "com.android.systemui.action_assist_icon";
+
+    private LockPatternUtils mLockPatternUtils;
+    private KeyguardUpdateMonitor mUpdateMonitor;
+    private KeyguardScreenCallback mCallback;
+
+    // set to 'true' to show the ring/silence target when camera isn't available
+    private boolean mEnableRingSilenceFallback = false;
+
+    // current configuration state of keyboard and display
+    private int mCreationOrientation;
+
+    private boolean mSilentMode;
+    private AudioManager mAudioManager;
+    private boolean mEnableMenuKeyInLockScreen;
+
+    private KeyguardStatusViewManager mStatusViewManager;
+    private UnlockWidgetCommonMethods mUnlockWidgetMethods;
+    private View mUnlockWidget;
+    private boolean mCameraDisabled;
+    private boolean mSearchDisabled;
+    // Is there a vibrator
+    private final boolean mHasVibrator;
+
+    KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
+
+        @Override
+        public void onRingerModeChanged(int state) {
+            boolean silent = AudioManager.RINGER_MODE_NORMAL != state;
+            if (silent != mSilentMode) {
+                mSilentMode = silent;
+                mUnlockWidgetMethods.updateResources();
+            }
+        }
+
+        @Override
+        public void onDevicePolicyManagerStateChanged() {
+            updateTargets();
+        }
+
+        @Override
+        public void onSimStateChanged(IccCardConstants.State simState) {
+            updateTargets();
+        }
+    };
+
+    private interface UnlockWidgetCommonMethods {
+        // Update resources based on phone state
+        public void updateResources();
+
+        // Get the view associated with this widget
+        public View getView();
+
+        // Reset the view
+        public void reset(boolean animate);
+
+        // Animate the widget if it supports ping()
+        public void ping();
+
+        // Enable or disable a target. ResourceId is the id of the *drawable* associated with the
+        // target.
+        public void setEnabled(int resourceId, boolean enabled);
+
+        // Get the target position for the given resource. Returns -1 if not found.
+        public int getTargetPosition(int resourceId);
+
+        // Clean up when this widget is going away
+        public void cleanUp();
+    }
+
+    class SlidingTabMethods implements SlidingTab.OnTriggerListener, UnlockWidgetCommonMethods {
+        private final SlidingTab mSlidingTab;
+
+        SlidingTabMethods(SlidingTab slidingTab) {
+            mSlidingTab = slidingTab;
+        }
+
+        public void updateResources() {
+            boolean vibe = mSilentMode
+                && (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);
+
+            mSlidingTab.setRightTabResources(
+                    mSilentMode ? ( vibe ? R.drawable.ic_jog_dial_vibrate_on
+                                         : R.drawable.ic_jog_dial_sound_off )
+                                : R.drawable.ic_jog_dial_sound_on,
+                    mSilentMode ? R.drawable.jog_tab_target_yellow
+                                : R.drawable.jog_tab_target_gray,
+                    mSilentMode ? R.drawable.jog_tab_bar_right_sound_on
+                                : R.drawable.jog_tab_bar_right_sound_off,
+                    mSilentMode ? R.drawable.jog_tab_right_sound_on
+                                : R.drawable.jog_tab_right_sound_off);
+        }
+
+        /** {@inheritDoc} */
+        public void onTrigger(View v, int whichHandle) {
+            if (whichHandle == SlidingTab.OnTriggerListener.LEFT_HANDLE) {
+                mCallback.goToUnlockScreen();
+            } else if (whichHandle == SlidingTab.OnTriggerListener.RIGHT_HANDLE) {
+                toggleRingMode();
+                mCallback.pokeWakelock();
+            }
+        }
+
+        /** {@inheritDoc} */
+        public void onGrabbedStateChange(View v, int grabbedState) {
+            if (grabbedState == SlidingTab.OnTriggerListener.RIGHT_HANDLE) {
+                mSilentMode = isSilentMode();
+                mSlidingTab.setRightHintText(mSilentMode ? R.string.lockscreen_sound_on_label
+                        : R.string.lockscreen_sound_off_label);
+            }
+            // Don't poke the wake lock when returning to a state where the handle is
+            // not grabbed since that can happen when the system (instead of the user)
+            // cancels the grab.
+            if (grabbedState != SlidingTab.OnTriggerListener.NO_HANDLE) {
+                mCallback.pokeWakelock();
+            }
+        }
+
+        public View getView() {
+            return mSlidingTab;
+        }
+
+        public void reset(boolean animate) {
+            mSlidingTab.reset(animate);
+        }
+
+        public void ping() {
+        }
+
+        public void setEnabled(int resourceId, boolean enabled) {
+            // Not used
+        }
+
+        public int getTargetPosition(int resourceId) {
+            return -1; // Not supported
+        }
+
+        public void cleanUp() {
+            mSlidingTab.setOnTriggerListener(null);
+        }
+    }
+
+    class WaveViewMethods implements WaveView.OnTriggerListener, UnlockWidgetCommonMethods {
+
+        private final WaveView mWaveView;
+
+        WaveViewMethods(WaveView waveView) {
+            mWaveView = waveView;
+        }
+        /** {@inheritDoc} */
+        public void onTrigger(View v, int whichHandle) {
+            if (whichHandle == WaveView.OnTriggerListener.CENTER_HANDLE) {
+                requestUnlockScreen();
+            }
+        }
+
+        /** {@inheritDoc} */
+        public void onGrabbedStateChange(View v, int grabbedState) {
+            // Don't poke the wake lock when returning to a state where the handle is
+            // not grabbed since that can happen when the system (instead of the user)
+            // cancels the grab.
+            if (grabbedState == WaveView.OnTriggerListener.CENTER_HANDLE) {
+                mCallback.pokeWakelock(STAY_ON_WHILE_GRABBED_TIMEOUT);
+            }
+        }
+
+        public void updateResources() {
+        }
+
+        public View getView() {
+            return mWaveView;
+        }
+        public void reset(boolean animate) {
+            mWaveView.reset();
+        }
+        public void ping() {
+        }
+        public void setEnabled(int resourceId, boolean enabled) {
+            // Not used
+        }
+        public int getTargetPosition(int resourceId) {
+            return -1; // Not supported
+        }
+        public void cleanUp() {
+            mWaveView.setOnTriggerListener(null);
+        }
+    }
+
+    class GlowPadViewMethods implements GlowPadView.OnTriggerListener,
+            UnlockWidgetCommonMethods {
+        private final GlowPadView mGlowPadView;
+
+        GlowPadViewMethods(GlowPadView glowPadView) {
+            mGlowPadView = glowPadView;
+        }
+
+        public boolean isTargetPresent(int resId) {
+            return mGlowPadView.getTargetPosition(resId) != -1;
+        }
+
+        public void updateResources() {
+            int resId;
+            if (mCameraDisabled && mEnableRingSilenceFallback) {
+                // Fall back to showing ring/silence if camera is disabled...
+                resId = mSilentMode ? R.array.lockscreen_targets_when_silent
+                    : R.array.lockscreen_targets_when_soundon;
+            } else {
+                resId = R.array.lockscreen_targets_with_camera;
+            }
+            if (mGlowPadView.getTargetResourceId() != resId) {
+                mGlowPadView.setTargetResources(resId);
+            }
+
+            // Update the search icon with drawable from the search .apk
+            if (!mSearchDisabled) {
+                Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                        .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+                if (intent != null) {
+                    // XXX Hack. We need to substitute the icon here but haven't formalized
+                    // the public API. The "_google" metadata will be going away, so
+                    // DON'T USE IT!
+                    ComponentName component = intent.getComponent();
+                    boolean replaced = mGlowPadView.replaceTargetDrawablesIfPresent(component,
+                            ASSIST_ICON_METADATA_NAME + "_google",
+                            com.android.internal.R.drawable.ic_action_assist_generic);
+
+                    if (!replaced && !mGlowPadView.replaceTargetDrawablesIfPresent(component,
+                                ASSIST_ICON_METADATA_NAME,
+                                com.android.internal.R.drawable.ic_action_assist_generic)) {
+                            Slog.w(TAG, "Couldn't grab icon from package " + component);
+                    }
+                }
+            }
+
+            setEnabled(com.android.internal.R.drawable.ic_lockscreen_camera, !mCameraDisabled);
+            setEnabled(com.android.internal.R.drawable.ic_action_assist_generic, !mSearchDisabled);
+        }
+
+        public void onGrabbed(View v, int handle) {
+
+        }
+
+        public void onReleased(View v, int handle) {
+
+        }
+
+        public void onTrigger(View v, int target) {
+            final int resId = mGlowPadView.getResourceIdForTarget(target);
+            switch (resId) {
+                case com.android.internal.R.drawable.ic_action_assist_generic:
+                    Intent assistIntent =
+                            ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                            .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+                    if (assistIntent != null) {
+                        launchActivity(assistIntent);
+                    } else {
+                        Log.w(TAG, "Failed to get intent for assist activity");
+                    }
+                    mCallback.pokeWakelock();
+                    break;
+
+                case com.android.internal.R.drawable.ic_lockscreen_camera:
+                    launchActivity(new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA));
+                    mCallback.pokeWakelock();
+                    break;
+
+                case com.android.internal.R.drawable.ic_lockscreen_silent:
+                    toggleRingMode();
+                    mCallback.pokeWakelock();
+                break;
+
+                case com.android.internal.R.drawable.ic_lockscreen_unlock_phantom:
+                case com.android.internal.R.drawable.ic_lockscreen_unlock:
+                    mCallback.goToUnlockScreen();
+                break;
+            }
+        }
+
+        /**
+         * Launches the said intent for the current foreground user.
+         * @param intent
+         */
+        private void launchActivity(Intent intent) {
+            intent.setFlags(
+                    Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_SINGLE_TOP
+                    | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+            try {
+                ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
+            } catch (RemoteException e) {
+                Log.w(TAG, "can't dismiss keyguard on launch");
+            }
+            try {
+                mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+            } catch (ActivityNotFoundException e) {
+                Log.w(TAG, "Activity not found for intent + " + intent.getAction());
+            }
+        }
+
+        public void onGrabbedStateChange(View v, int handle) {
+            // Don't poke the wake lock when returning to a state where the handle is
+            // not grabbed since that can happen when the system (instead of the user)
+            // cancels the grab.
+            if (handle != GlowPadView.OnTriggerListener.NO_HANDLE) {
+                mCallback.pokeWakelock();
+            }
+        }
+
+        public View getView() {
+            return mGlowPadView;
+        }
+
+        public void reset(boolean animate) {
+            mGlowPadView.reset(animate);
+        }
+
+        public void ping() {
+            mGlowPadView.ping();
+        }
+
+        public void setEnabled(int resourceId, boolean enabled) {
+            mGlowPadView.setEnableTarget(resourceId, enabled);
+        }
+
+        public int getTargetPosition(int resourceId) {
+            return mGlowPadView.getTargetPosition(resourceId);
+        }
+
+        public void cleanUp() {
+            mGlowPadView.setOnTriggerListener(null);
+        }
+
+        public void onFinishFinalAnimation() {
+
+        }
+    }
+
+    private void requestUnlockScreen() {
+        // Delay hiding lock screen long enough for animation to finish
+        postDelayed(new Runnable() {
+            public void run() {
+                mCallback.goToUnlockScreen();
+            }
+        }, WAIT_FOR_ANIMATION_TIMEOUT);
+    }
+
+    private void toggleRingMode() {
+        // toggle silent mode
+        mSilentMode = !mSilentMode;
+        if (mSilentMode) {
+            mAudioManager.setRingerMode(mHasVibrator
+                ? AudioManager.RINGER_MODE_VIBRATE
+                : AudioManager.RINGER_MODE_SILENT);
+        } else {
+            mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
+        }
+    }
+
+    /**
+     * In general, we enable unlocking the insecure key guard with the menu key. However, there are
+     * some cases where we wish to disable it, notably when the menu button placement or technology
+     * is prone to false positives.
+     *
+     * @return true if the menu key should be enabled
+     */
+    private boolean shouldEnableMenuKey() {
+        final Resources res = getResources();
+        final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
+        final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
+        final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
+        return !configDisabled || isTestHarness || fileOverride;
+    }
+
+    /**
+     * @param context Used to setup the view.
+     * @param configuration The current configuration. Used to use when selecting layout, etc.
+     * @param lockPatternUtils Used to know the state of the lock pattern settings.
+     * @param updateMonitor Used to register for updates on various keyguard related
+     *    state, and query the initial state at setup.
+     * @param callback Used to communicate back to the host keyguard view.
+     */
+    LockScreen(Context context, Configuration configuration, LockPatternUtils lockPatternUtils,
+            KeyguardUpdateMonitor updateMonitor,
+            KeyguardScreenCallback callback) {
+        super(context);
+        mLockPatternUtils = lockPatternUtils;
+        mUpdateMonitor = updateMonitor;
+        mCallback = callback;
+        mEnableMenuKeyInLockScreen = shouldEnableMenuKey();
+        mCreationOrientation = configuration.orientation;
+
+        if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
+            Log.v(TAG, "***** CREATING LOCK SCREEN", new RuntimeException());
+            Log.v(TAG, "Cur orient=" + mCreationOrientation
+                    + " res orient=" + context.getResources().getConfiguration().orientation);
+        }
+
+        final LayoutInflater inflater = LayoutInflater.from(context);
+        if (DBG) Log.v(TAG, "Creation orientation = " + mCreationOrientation);
+        if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {
+            inflater.inflate(R.layout.keyguard_screen_tab_unlock, this, true);
+        } else {
+            inflater.inflate(R.layout.keyguard_screen_tab_unlock_land, this, true);
+        }
+
+        mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, mLockPatternUtils,
+                mCallback, false);
+
+        setFocusable(true);
+        setFocusableInTouchMode(true);
+        setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+
+        Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
+        mHasVibrator = vibrator == null ? false : vibrator.hasVibrator();
+        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        mSilentMode = isSilentMode();
+        mUnlockWidget = findViewById(R.id.unlock_widget);
+        mUnlockWidgetMethods = createUnlockMethods(mUnlockWidget);
+
+        if (DBG) Log.v(TAG, "*** LockScreen accel is "
+                + (mUnlockWidget.isHardwareAccelerated() ? "on":"off"));
+    }
+
+    private UnlockWidgetCommonMethods createUnlockMethods(View unlockWidget) {
+        if (unlockWidget instanceof SlidingTab) {
+            SlidingTab slidingTabView = (SlidingTab) unlockWidget;
+            slidingTabView.setHoldAfterTrigger(true, false);
+            slidingTabView.setLeftHintText(R.string.lockscreen_unlock_label);
+            slidingTabView.setLeftTabResources(
+                    R.drawable.ic_jog_dial_unlock,
+                    R.drawable.jog_tab_target_green,
+                    R.drawable.jog_tab_bar_left_unlock,
+                    R.drawable.jog_tab_left_unlock);
+            SlidingTabMethods slidingTabMethods = new SlidingTabMethods(slidingTabView);
+            slidingTabView.setOnTriggerListener(slidingTabMethods);
+            return slidingTabMethods;
+        } else if (unlockWidget instanceof WaveView) {
+            WaveView waveView = (WaveView) unlockWidget;
+            WaveViewMethods waveViewMethods = new WaveViewMethods(waveView);
+            waveView.setOnTriggerListener(waveViewMethods);
+            return waveViewMethods;
+        } else if (unlockWidget instanceof GlowPadView) {
+            GlowPadView glowPadView = (GlowPadView) unlockWidget;
+            GlowPadViewMethods glowPadViewMethods = new GlowPadViewMethods(glowPadView);
+            glowPadView.setOnTriggerListener(glowPadViewMethods);
+            return glowPadViewMethods;
+        } else {
+            throw new IllegalStateException("Unrecognized unlock widget: " + unlockWidget);
+        }
+    }
+
+    private void updateTargets() {
+        boolean disabledByAdmin = mLockPatternUtils.getDevicePolicyManager()
+                .getCameraDisabled(null);
+        boolean disabledBySimState = mUpdateMonitor.isSimLocked();
+        boolean cameraTargetPresent = (mUnlockWidgetMethods instanceof GlowPadViewMethods)
+                ? ((GlowPadViewMethods) mUnlockWidgetMethods)
+                        .isTargetPresent(com.android.internal.R.drawable.ic_lockscreen_camera)
+                        : false;
+        boolean searchTargetPresent = (mUnlockWidgetMethods instanceof GlowPadViewMethods)
+                ? ((GlowPadViewMethods) mUnlockWidgetMethods)
+                        .isTargetPresent(com.android.internal.R.drawable.ic_action_assist_generic)
+                        : false;
+
+        if (disabledByAdmin) {
+            Log.v(TAG, "Camera disabled by Device Policy");
+        } else if (disabledBySimState) {
+            Log.v(TAG, "Camera disabled by Sim State");
+        }
+        boolean searchActionAvailable =
+                ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                .getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
+        mCameraDisabled = disabledByAdmin || disabledBySimState || !cameraTargetPresent;
+        mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent;
+        mUnlockWidgetMethods.updateResources();
+    }
+
+    private boolean isSilentMode() {
+        return mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL;
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_MENU && mEnableMenuKeyInLockScreen) {
+            mCallback.goToUnlockScreen();
+        }
+        return false;
+    }
+
+    void updateConfiguration() {
+        Configuration newConfig = getResources().getConfiguration();
+        if (newConfig.orientation != mCreationOrientation) {
+            mCallback.recreateMe(newConfig);
+        }
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
+            Log.v(TAG, "***** LOCK ATTACHED TO WINDOW");
+            Log.v(TAG, "Cur orient=" + mCreationOrientation
+                    + ", new config=" + getResources().getConfiguration());
+        }
+        updateConfiguration();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
+            Log.w(TAG, "***** LOCK CONFIG CHANGING", new RuntimeException());
+            Log.v(TAG, "Cur orient=" + mCreationOrientation
+                    + ", new config=" + newConfig);
+        }
+        updateConfiguration();
+    }
+
+    /** {@inheritDoc} */
+    public boolean needsInput() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    public void onPause() {
+        mUpdateMonitor.removeCallback(mInfoCallback);
+        mStatusViewManager.onPause();
+        mUnlockWidgetMethods.reset(false);
+    }
+
+    private final Runnable mOnResumePing = new Runnable() {
+        public void run() {
+            mUnlockWidgetMethods.ping();
+        }
+    };
+
+    /** {@inheritDoc} */
+    public void onResume() {
+        // We don't want to show the camera target if SIM state prevents us from
+        // launching the camera. So watch for SIM changes...
+        mUpdateMonitor.registerCallback(mInfoCallback);
+
+        mStatusViewManager.onResume();
+        postDelayed(mOnResumePing, ON_RESUME_PING_DELAY);
+    }
+
+    /** {@inheritDoc} */
+    public void cleanUp() {
+        mUpdateMonitor.removeCallback(mInfoCallback); // this must be first
+        mUnlockWidgetMethods.cleanUp();
+        mLockPatternUtils = null;
+        mUpdateMonitor = null;
+        mCallback = null;
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/PasswordUnlockScreen.java
new file mode 100644
index 0000000..87a7371
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/PasswordUnlockScreen.java
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import java.util.List;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.PasswordEntryKeyboardView;
+
+import android.os.CountDownTimer;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.security.KeyStore;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.text.method.DigitsKeyListener;
+import android.text.method.TextKeyListener;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.Space;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+import com.android.internal.R;
+import com.android.internal.widget.PasswordEntryKeyboardHelper;
+
+/**
+ * Displays a dialer-like interface or alphanumeric (latin-1) key entry for the user to enter
+ * an unlock password
+ */
+public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen,
+        OnEditorActionListener {
+
+    private static final String TAG = "PasswordUnlockScreen";
+    private final KeyguardUpdateMonitor mUpdateMonitor;
+    private final KeyguardScreenCallback mCallback;
+
+    private final boolean mIsAlpha;
+
+    private final EditText mPasswordEntry;
+    private final LockPatternUtils mLockPatternUtils;
+    private final PasswordEntryKeyboardView mKeyboardView;
+    private final PasswordEntryKeyboardHelper mKeyboardHelper;
+
+    private final int mCreationOrientation;
+    private final int mCreationHardKeyboardHidden;
+
+    private final KeyguardStatusViewManager mStatusViewManager;
+    private final boolean mUseSystemIME = true; // TODO: Make configurable
+    private boolean mResuming; // used to prevent poking the wakelock during onResume()
+
+    // To avoid accidental lockout due to events while the device in in the pocket, ignore
+    // any passwords with length less than or equal to this length.
+    private static final int MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT = 3;
+
+    public PasswordUnlockScreen(Context context, Configuration configuration,
+            LockPatternUtils lockPatternUtils, KeyguardUpdateMonitor updateMonitor,
+            KeyguardScreenCallback callback) {
+        super(context);
+
+        mCreationHardKeyboardHidden = configuration.hardKeyboardHidden;
+        mCreationOrientation = configuration.orientation;
+        mUpdateMonitor = updateMonitor;
+        mCallback = callback;
+        mLockPatternUtils = lockPatternUtils;
+
+        LayoutInflater layoutInflater = LayoutInflater.from(context);
+        if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {
+            layoutInflater.inflate(R.layout.keyguard_screen_password_portrait, this, true);
+        } else {
+            layoutInflater.inflate(R.layout.keyguard_screen_password_landscape, this, true);
+        }
+
+        mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, mLockPatternUtils,
+                mCallback, true);
+
+        final int quality = lockPatternUtils.getKeyguardStoredPasswordQuality();
+        mIsAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == quality
+                || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == quality
+                || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == quality;
+
+        mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
+        mPasswordEntry = (EditText) findViewById(R.id.passwordEntry);
+        mPasswordEntry.setOnEditorActionListener(this);
+
+        mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this, false);
+        mKeyboardHelper.setEnableHaptics(mLockPatternUtils.isTactileFeedbackEnabled());
+        boolean imeOrDeleteButtonVisible = false;
+        if (mIsAlpha) {
+            // We always use the system IME for alpha keyboard, so hide lockscreen's soft keyboard
+            mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA);
+            mKeyboardView.setVisibility(View.GONE);
+        } else {
+            // Use lockscreen's numeric keyboard if the physical keyboard isn't showing
+            mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
+            mKeyboardView.setVisibility(mCreationHardKeyboardHidden
+                    == Configuration.HARDKEYBOARDHIDDEN_NO ? View.INVISIBLE : View.VISIBLE);
+
+            // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
+            // not a separate view
+            View pinDelete = findViewById(R.id.pinDel);
+            if (pinDelete != null) {
+                pinDelete.setVisibility(View.VISIBLE);
+                imeOrDeleteButtonVisible = true;
+                pinDelete.setOnClickListener(new OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        mKeyboardHelper.handleBackspace();
+                    }
+                });
+            }
+        }
+
+        mPasswordEntry.requestFocus();
+
+        // This allows keyboards with overlapping qwerty/numeric keys to choose just numeric keys.
+        if (mIsAlpha) {
+            mPasswordEntry.setKeyListener(TextKeyListener.getInstance());
+            mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT
+                    | InputType.TYPE_TEXT_VARIATION_PASSWORD);
+            //mStatusViewManager.setHelpMessage(R.string.keyguard_password_enter_password_code,
+                    //KeyguardStatusViewManager.LOCK_ICON);
+        } else {
+            mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
+            mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
+                    | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
+            //mStatusViewManager.setHelpMessage(R.string.keyguard_password_enter_pin_code,
+                    //KeyguardStatusViewManager.LOCK_ICON);
+        }
+
+        // Poke the wakelock any time the text is selected or modified
+        mPasswordEntry.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                mCallback.pokeWakelock();
+            }
+        });
+        mPasswordEntry.addTextChangedListener(new TextWatcher() {
+            public void onTextChanged(CharSequence s, int start, int before, int count) {
+            }
+
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+            }
+
+            public void afterTextChanged(Editable s) {
+                if (!mResuming) {
+                    mCallback.pokeWakelock();
+                }
+            }
+        });
+
+        // If there's more than one IME, enable the IME switcher button
+        View switchImeButton = findViewById(R.id.switch_ime_button);
+        final InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
+                Context.INPUT_METHOD_SERVICE);
+        if (mIsAlpha && switchImeButton != null && hasMultipleEnabledIMEsOrSubtypes(imm, false)) {
+            switchImeButton.setVisibility(View.VISIBLE);
+            imeOrDeleteButtonVisible = true;
+            switchImeButton.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    mCallback.pokeWakelock(); // Leave the screen on a bit longer
+                    imm.showInputMethodPicker();
+                }
+            });
+        }
+
+        // If no icon is visible, reset the left margin on the password field so the text is
+        // still centered.
+        if (!imeOrDeleteButtonVisible) {
+            android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams();
+            if (params instanceof MarginLayoutParams) {
+                ((MarginLayoutParams)params).leftMargin = 0;
+                mPasswordEntry.setLayoutParams(params);
+            }
+        }
+    }
+
+    /**
+     * Method adapted from com.android.inputmethod.latin.Utils
+     *
+     * @param imm The input method manager
+     * @param shouldIncludeAuxiliarySubtypes
+     * @return true if we have multiple IMEs to choose from
+     */
+    private boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManager imm,
+            final boolean shouldIncludeAuxiliarySubtypes) {
+        final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList();
+
+        // Number of the filtered IMEs
+        int filteredImisCount = 0;
+
+        for (InputMethodInfo imi : enabledImis) {
+            // We can return true immediately after we find two or more filtered IMEs.
+            if (filteredImisCount > 1) return true;
+            final List<InputMethodSubtype> subtypes =
+                    imm.getEnabledInputMethodSubtypeList(imi, true);
+            // IMEs that have no subtypes should be counted.
+            if (subtypes.isEmpty()) {
+                ++filteredImisCount;
+                continue;
+            }
+
+            int auxCount = 0;
+            for (InputMethodSubtype subtype : subtypes) {
+                if (subtype.isAuxiliary()) {
+                    ++auxCount;
+                }
+            }
+            final int nonAuxCount = subtypes.size() - auxCount;
+
+            // IMEs that have one or more non-auxiliary subtypes should be counted.
+            // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary
+            // subtypes should be counted as well.
+            if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) {
+                ++filteredImisCount;
+                continue;
+            }
+        }
+
+        return filteredImisCount > 1
+        // imm.getEnabledInputMethodSubtypeList(null, false) will return the current IME's enabled
+        // input method subtype (The current IME should be LatinIME.)
+                || imm.getEnabledInputMethodSubtypeList(null, false).size() > 1;
+    }
+
+    @Override
+    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
+        // send focus to the password field
+        return mPasswordEntry.requestFocus(direction, previouslyFocusedRect);
+    }
+
+    /** {@inheritDoc} */
+    public boolean needsInput() {
+        return mUseSystemIME && mIsAlpha;
+    }
+
+    /** {@inheritDoc} */
+    public void onPause() {
+        mStatusViewManager.onPause();
+    }
+
+    /** {@inheritDoc} */
+    public void onResume() {
+        mResuming = true;
+        // reset status
+        mStatusViewManager.onResume();
+
+        // start fresh
+        mPasswordEntry.setText("");
+        mPasswordEntry.requestFocus();
+
+        // if the user is currently locked out, enforce it.
+        long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
+        if (deadline != 0) {
+            handleAttemptLockout(deadline);
+        }
+        mResuming = false;
+    }
+
+    /** {@inheritDoc} */
+    public void cleanUp() {
+        mUpdateMonitor.removeCallback(this);
+    }
+
+    private void verifyPasswordAndUnlock() {
+        String entry = mPasswordEntry.getText().toString();
+        if (mLockPatternUtils.checkPassword(entry)) {
+            mCallback.keyguardDone(true);
+            mCallback.reportSuccessfulUnlockAttempt();
+            mStatusViewManager.setInstructionText(null);
+            KeyStore.getInstance().password(entry);
+        } else if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) {
+            // to avoid accidental lockout, only count attempts that are long enough to be a
+            // real password. This may require some tweaking.
+            mCallback.reportFailedUnlockAttempt();
+            if (0 == (mUpdateMonitor.getFailedAttempts()
+                    % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
+                long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
+                handleAttemptLockout(deadline);
+            }
+            mStatusViewManager.setInstructionText(
+                    mContext.getString(R.string.lockscreen_password_wrong));
+        } else if (entry.length() > 0) {
+            mStatusViewManager.setInstructionText(
+                    mContext.getString(R.string.lockscreen_password_wrong));
+        }
+        mPasswordEntry.setText("");
+    }
+
+    // Prevent user from using the PIN/Password entry until scheduled deadline.
+    private void handleAttemptLockout(long elapsedRealtimeDeadline) {
+        mPasswordEntry.setEnabled(false);
+        mKeyboardView.setEnabled(false);
+        long elapsedRealtime = SystemClock.elapsedRealtime();
+        new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
+
+            @Override
+            public void onTick(long millisUntilFinished) {
+                int secondsRemaining = (int) (millisUntilFinished / 1000);
+                String instructions = getContext().getString(
+                        R.string.lockscreen_too_many_failed_attempts_countdown,
+                        secondsRemaining);
+                mStatusViewManager.setInstructionText(instructions);
+            }
+
+            @Override
+            public void onFinish() {
+                mPasswordEntry.setEnabled(true);
+                mKeyboardView.setEnabled(true);
+                mStatusViewManager.resetStatusInfo();
+            }
+        }.start();
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        mCallback.pokeWakelock();
+        return false;
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        Configuration config = getResources().getConfiguration();
+        if (config.orientation != mCreationOrientation
+                || config.hardKeyboardHidden != mCreationHardKeyboardHidden) {
+            mCallback.recreateMe(config);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        if (newConfig.orientation != mCreationOrientation
+                || newConfig.hardKeyboardHidden != mCreationHardKeyboardHidden) {
+            mCallback.recreateMe(newConfig);
+        }
+    }
+
+    public void onKeyboardChange(boolean isKeyboardOpen) {
+        // Don't show the soft keyboard when the real keyboard is open
+        mKeyboardView.setVisibility(isKeyboardOpen ? View.INVISIBLE : View.VISIBLE);
+    }
+
+    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+        // Check if this was the result of hitting the enter key
+        if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE
+                || actionId == EditorInfo.IME_ACTION_NEXT) {
+            verifyPasswordAndUnlock();
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/PatternUnlockScreen.java
new file mode 100644
index 0000000..6d5706b
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/PatternUnlockScreen.java
@@ -0,0 +1,416 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.CountDownTimer;
+import android.os.SystemClock;
+import android.security.KeyStore;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.MotionEvent;
+import android.widget.Button;
+import android.util.Log;
+import com.android.internal.R;
+import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+import com.android.internal.widget.LockPatternView.Cell;
+
+import java.util.List;
+
+/**
+ * This is the screen that shows the 9 circle unlock widget and instructs
+ * the user how to unlock their device, or make an emergency call.
+ */
+class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient
+        implements KeyguardScreen {
+
+    private static final boolean DEBUG = false;
+    private static final String TAG = "UnlockScreen";
+
+    // how long before we clear the wrong pattern
+    private static final int PATTERN_CLEAR_TIMEOUT_MS = 2000;
+
+    // how long we stay awake after each key beyond MIN_PATTERN_BEFORE_POKE_WAKELOCK
+    private static final int UNLOCK_PATTERN_WAKE_INTERVAL_MS = 7000;
+
+    // how long we stay awake after the user hits the first dot.
+    private static final int UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS = 2000;
+
+    // how many cells the user has to cross before we poke the wakelock
+    private static final int MIN_PATTERN_BEFORE_POKE_WAKELOCK = 2;
+
+    private int mFailedPatternAttemptsSinceLastTimeout = 0;
+    private int mTotalFailedPatternAttempts = 0;
+    private CountDownTimer mCountdownTimer = null;
+
+    private LockPatternUtils mLockPatternUtils;
+    private KeyguardUpdateMonitor mUpdateMonitor;
+    private KeyguardScreenCallback mCallback;
+
+    /**
+     * whether there is a fallback option available when the pattern is forgotten.
+     */
+    private boolean mEnableFallback;
+
+    private KeyguardStatusViewManager mKeyguardStatusViewManager;
+    private LockPatternView mLockPatternView;
+
+    /**
+     * Keeps track of the last time we poked the wake lock during dispatching
+     * of the touch event, initalized to something gauranteed to make us
+     * poke it when the user starts drawing the pattern.
+     * @see #dispatchTouchEvent(android.view.MotionEvent)
+     */
+    private long mLastPokeTime = -UNLOCK_PATTERN_WAKE_INTERVAL_MS;
+
+    /**
+     * Useful for clearing out the wrong pattern after a delay
+     */
+    private Runnable mCancelPatternRunnable = new Runnable() {
+        public void run() {
+            mLockPatternView.clearPattern();
+        }
+    };
+
+    private final OnClickListener mForgotPatternClick = new OnClickListener() {
+        public void onClick(View v) {
+            mCallback.forgotPattern(true);
+        }
+    };
+
+    private Button mForgotPatternButton;
+    private int mCreationOrientation;
+
+    enum FooterMode {
+        Normal,
+        ForgotLockPattern,
+        VerifyUnlocked
+    }
+
+    private void hideForgotPatternButton() {
+        mForgotPatternButton.setVisibility(View.GONE);
+    }
+
+    private void showForgotPatternButton() {
+        mForgotPatternButton.setVisibility(View.VISIBLE);
+    }
+
+    private void updateFooter(FooterMode mode) {
+        switch (mode) {
+            case Normal:
+                if (DEBUG) Log.d(TAG, "mode normal");
+                hideForgotPatternButton();
+                break;
+            case ForgotLockPattern:
+                if (DEBUG) Log.d(TAG, "mode ForgotLockPattern");
+                showForgotPatternButton();
+                break;
+            case VerifyUnlocked:
+                if (DEBUG) Log.d(TAG, "mode VerifyUnlocked");
+                hideForgotPatternButton();
+        }
+    }
+
+    /**
+     * @param context The context.
+     * @param configuration
+     * @param lockPatternUtils Used to lookup lock pattern settings.
+     * @param updateMonitor Used to lookup state affecting keyguard.
+     * @param callback Used to notify the manager when we're done, etc.
+     * @param totalFailedAttempts The current number of failed attempts.
+     * @param enableFallback True if a backup unlock option is available when the user has forgotten
+     *        their pattern (e.g they have a google account so we can show them the account based
+     *        backup option).
+     */
+    PatternUnlockScreen(Context context,
+                 Configuration configuration, LockPatternUtils lockPatternUtils,
+                 KeyguardUpdateMonitor updateMonitor,
+                 KeyguardScreenCallback callback,
+                 int totalFailedAttempts) {
+        super(context);
+        mLockPatternUtils = lockPatternUtils;
+        mUpdateMonitor = updateMonitor;
+        mCallback = callback;
+        mTotalFailedPatternAttempts = totalFailedAttempts;
+        mFailedPatternAttemptsSinceLastTimeout =
+            totalFailedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
+
+        if (DEBUG) Log.d(TAG,
+            "UnlockScreen() ctor: totalFailedAttempts="
+                 + totalFailedAttempts + ", mFailedPat...="
+                 + mFailedPatternAttemptsSinceLastTimeout
+                 );
+
+        mCreationOrientation = configuration.orientation;
+
+        LayoutInflater inflater = LayoutInflater.from(context);
+
+        if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {
+            Log.d(TAG, "portrait mode");
+            inflater.inflate(R.layout.keyguard_screen_unlock_portrait, this, true);
+        } else {
+            Log.d(TAG, "landscape mode");
+            inflater.inflate(R.layout.keyguard_screen_unlock_landscape, this, true);
+        }
+
+        mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor,
+                mLockPatternUtils, mCallback, true);
+
+        mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
+
+        mForgotPatternButton = (Button) findViewById(R.id.forgotPatternButton);
+        mForgotPatternButton.setText(R.string.lockscreen_forgot_pattern_button_text);
+        mForgotPatternButton.setOnClickListener(mForgotPatternClick);
+
+        // make it so unhandled touch events within the unlock screen go to the
+        // lock pattern view.
+        setDefaultTouchRecepient(mLockPatternView);
+
+        mLockPatternView.setSaveEnabled(false);
+        mLockPatternView.setFocusable(false);
+        mLockPatternView.setOnPatternListener(new UnlockPatternListener());
+
+        // stealth mode will be the same for the life of this screen
+        mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled());
+
+        // vibrate mode will be the same for the life of this screen
+        mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
+
+        // assume normal footer mode for now
+        updateFooter(FooterMode.Normal);
+
+        setFocusableInTouchMode(true);
+    }
+
+    public void setEnableFallback(boolean state) {
+        if (DEBUG) Log.d(TAG, "setEnableFallback(" + state + ")");
+        mEnableFallback = state;
+    }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        // as long as the user is entering a pattern (i.e sending a touch
+        // event that was handled by this screen), keep poking the
+        // wake lock so that the screen will stay on.
+        final boolean result = super.dispatchTouchEvent(ev);
+        if (result &&
+                ((SystemClock.elapsedRealtime() - mLastPokeTime)
+                        >  (UNLOCK_PATTERN_WAKE_INTERVAL_MS - 100))) {
+            mLastPokeTime = SystemClock.elapsedRealtime();
+        }
+        return result;
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
+            Log.v(TAG, "***** PATTERN ATTACHED TO WINDOW");
+            Log.v(TAG, "Cur orient=" + mCreationOrientation
+                    + ", new config=" + getResources().getConfiguration());
+        }
+        if (getResources().getConfiguration().orientation != mCreationOrientation) {
+            mCallback.recreateMe(getResources().getConfiguration());
+        }
+    }
+
+
+    /** {@inheritDoc} */
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
+            Log.v(TAG, "***** PATTERN CONFIGURATION CHANGED");
+            Log.v(TAG, "Cur orient=" + mCreationOrientation
+                    + ", new config=" + getResources().getConfiguration());
+        }
+        if (newConfig.orientation != mCreationOrientation) {
+            mCallback.recreateMe(newConfig);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void onKeyboardChange(boolean isKeyboardOpen) {}
+
+    /** {@inheritDoc} */
+    public boolean needsInput() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    public void onPause() {
+        if (mCountdownTimer != null) {
+            mCountdownTimer.cancel();
+            mCountdownTimer = null;
+        }
+        mKeyguardStatusViewManager.onPause();
+    }
+
+    /** {@inheritDoc} */
+    public void onResume() {
+        // reset status
+        mKeyguardStatusViewManager.onResume();
+
+        // reset lock pattern
+        mLockPatternView.enableInput();
+        mLockPatternView.setEnabled(true);
+        mLockPatternView.clearPattern();
+
+        // show "forgot pattern?" button if we have an alternate authentication method
+        if (mCallback.doesFallbackUnlockScreenExist()) {
+            showForgotPatternButton();
+        } else {
+            hideForgotPatternButton();
+        }
+
+        // if the user is currently locked out, enforce it.
+        long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
+        if (deadline != 0) {
+            handleAttemptLockout(deadline);
+        }
+
+        // the footer depends on how many total attempts the user has failed
+        if (mCallback.isVerifyUnlockOnly()) {
+            updateFooter(FooterMode.VerifyUnlocked);
+        } else if (mEnableFallback &&
+                (mTotalFailedPatternAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
+            updateFooter(FooterMode.ForgotLockPattern);
+        } else {
+            updateFooter(FooterMode.Normal);
+        }
+
+    }
+
+    /** {@inheritDoc} */
+    public void cleanUp() {
+        if (DEBUG) Log.v(TAG, "Cleanup() called on " + this);
+        mUpdateMonitor.removeCallback(this);
+        mLockPatternUtils = null;
+        mUpdateMonitor = null;
+        mCallback = null;
+        mLockPatternView.setOnPatternListener(null);
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        super.onWindowFocusChanged(hasWindowFocus);
+        if (hasWindowFocus) {
+            // when timeout dialog closes we want to update our state
+            onResume();
+        }
+    }
+
+    private class UnlockPatternListener
+            implements LockPatternView.OnPatternListener {
+
+        public void onPatternStart() {
+            mLockPatternView.removeCallbacks(mCancelPatternRunnable);
+        }
+
+        public void onPatternCleared() {
+        }
+
+        public void onPatternCellAdded(List<Cell> pattern) {
+            // To guard against accidental poking of the wakelock, look for
+            // the user actually trying to draw a pattern of some minimal length.
+            if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
+                mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
+            } else {
+                // Give just a little extra time if they hit one of the first few dots
+                mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS);
+            }
+        }
+
+        public void onPatternDetected(List<LockPatternView.Cell> pattern) {
+            if (mLockPatternUtils.checkPattern(pattern)) {
+                mLockPatternView
+                        .setDisplayMode(LockPatternView.DisplayMode.Correct);
+                mKeyguardStatusViewManager.setInstructionText("");
+                mKeyguardStatusViewManager.updateStatusLines(true);
+                mCallback.keyguardDone(true);
+                mCallback.reportSuccessfulUnlockAttempt();
+                KeyStore.getInstance().password(LockPatternUtils.patternToString(pattern));
+            } else {
+                boolean reportFailedAttempt = false;
+                if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
+                    mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
+                }
+                mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
+                if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
+                    mTotalFailedPatternAttempts++;
+                    mFailedPatternAttemptsSinceLastTimeout++;
+                    reportFailedAttempt = true;
+                }
+                if (mFailedPatternAttemptsSinceLastTimeout
+                        >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
+                    long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
+                    handleAttemptLockout(deadline);
+                } else {
+                    // TODO mUnlockIcon.setVisibility(View.VISIBLE);
+                    mKeyguardStatusViewManager.setInstructionText(
+                            getContext().getString(R.string.lockscreen_pattern_wrong));
+                    mKeyguardStatusViewManager.updateStatusLines(true);
+                    mLockPatternView.postDelayed(
+                            mCancelPatternRunnable,
+                            PATTERN_CLEAR_TIMEOUT_MS);
+                }
+
+                // Because the following can result in cleanUp() being called on this screen,
+                // member variables reset in cleanUp() shouldn't be accessed after this call.
+                if (reportFailedAttempt) {
+                    mCallback.reportFailedUnlockAttempt();
+                }
+            }
+        }
+    }
+
+    private void handleAttemptLockout(long elapsedRealtimeDeadline) {
+        mLockPatternView.clearPattern();
+        mLockPatternView.setEnabled(false);
+        long elapsedRealtime = SystemClock.elapsedRealtime();
+        mCountdownTimer = new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
+
+            @Override
+            public void onTick(long millisUntilFinished) {
+                int secondsRemaining = (int) (millisUntilFinished / 1000);
+                mKeyguardStatusViewManager.setInstructionText(getContext().getString(
+                        R.string.lockscreen_too_many_failed_attempts_countdown,
+                        secondsRemaining));
+                mKeyguardStatusViewManager.updateStatusLines(true);
+            }
+
+            @Override
+            public void onFinish() {
+                mLockPatternView.setEnabled(true);
+                mKeyguardStatusViewManager.setInstructionText(getContext().getString(
+                        R.string.lockscreen_pattern_instructions));
+                mKeyguardStatusViewManager.updateStatusLines(true);
+                // TODO mUnlockIcon.setVisibility(View.VISIBLE);
+                mFailedPatternAttemptsSinceLastTimeout = 0;
+                if (mEnableFallback) {
+                    updateFooter(FooterMode.ForgotLockPattern);
+                } else {
+                    updateFooter(FooterMode.Normal);
+                }
+            }
+        }.start();
+    }
+
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimPukUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimPukUnlockScreen.java
new file mode 100644
index 0000000..3c1703a
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimPukUnlockScreen.java
@@ -0,0 +1,422 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.telephony.ITelephony;
+import com.android.internal.widget.LockPatternUtils;
+
+import android.text.Editable;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import com.android.internal.R;
+
+/**
+ * Displays a dialer like interface to unlock the SIM PUK.
+ */
+public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen,
+        View.OnClickListener, View.OnFocusChangeListener {
+
+    private static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
+
+    private final KeyguardUpdateMonitor mUpdateMonitor;
+    private final KeyguardScreenCallback mCallback;
+    private KeyguardStatusViewManager mKeyguardStatusViewManager;
+
+    private TextView mHeaderText;
+    private TextView mPukText;
+    private TextView mPinText;
+    private TextView mFocusedEntry;
+
+    private View mOkButton;
+    private View mDelPukButton;
+    private View mDelPinButton;
+
+    private ProgressDialog mSimUnlockProgressDialog = null;
+
+    private LockPatternUtils mLockPatternUtils;
+
+    private int mCreationOrientation;
+
+    private int mKeyboardHidden;
+
+    private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
+
+    public SimPukUnlockScreen(Context context, Configuration configuration,
+            KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback,
+            LockPatternUtils lockpatternutils) {
+        super(context);
+        mUpdateMonitor = updateMonitor;
+        mCallback = callback;;
+
+        mCreationOrientation = configuration.orientation;
+        mKeyboardHidden = configuration.hardKeyboardHidden;
+        mLockPatternUtils = lockpatternutils;
+
+        LayoutInflater inflater = LayoutInflater.from(context);
+        if (mKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
+            inflater.inflate(
+                    R.layout.keyguard_screen_sim_puk_landscape, this, true);
+        } else {
+            inflater.inflate(
+                    R.layout.keyguard_screen_sim_puk_portrait, this, true);
+            new TouchInput();
+        }
+
+        mHeaderText = (TextView) findViewById(R.id.headerText);
+
+        mPukText = (TextView) findViewById(R.id.pukDisplay);
+        mPinText = (TextView) findViewById(R.id.pinDisplay);
+        mDelPukButton = findViewById(R.id.pukDel);
+        mDelPinButton = findViewById(R.id.pinDel);
+        mOkButton = findViewById(R.id.ok);
+
+        mDelPinButton.setOnClickListener(this);
+        mDelPukButton.setOnClickListener(this);
+        mOkButton.setOnClickListener(this);
+
+        mHeaderText.setText(R.string.keyguard_password_enter_puk_code);
+        // To make marquee work
+        mHeaderText.setSelected(true);
+
+        mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor,
+                lockpatternutils, callback, true);
+
+        mPinText.setFocusableInTouchMode(true);
+        mPinText.setOnFocusChangeListener(this);
+        mPukText.setFocusableInTouchMode(true);
+        mPukText.setOnFocusChangeListener(this);
+    }
+
+    /** {@inheritDoc} */
+    public boolean needsInput() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    public void onPause() {
+        mKeyguardStatusViewManager.onPause();
+    }
+
+    /** {@inheritDoc} */
+    public void onResume() {
+        // start fresh
+        mHeaderText.setText(R.string.keyguard_password_enter_puk_code);
+        mKeyguardStatusViewManager.onResume();
+    }
+
+    /** {@inheritDoc} */
+    public void cleanUp() {
+        // dismiss the dialog.
+        if (mSimUnlockProgressDialog != null) {
+            mSimUnlockProgressDialog.dismiss();
+            mSimUnlockProgressDialog = null;
+        }
+        mUpdateMonitor.removeCallback(this);
+    }
+
+
+    /**
+     * Since the IPC can block, we want to run the request in a separate thread
+     * with a callback.
+     */
+    private abstract class CheckSimPuk extends Thread {
+
+        private final String mPin, mPuk;
+
+        protected CheckSimPuk(String puk, String pin) {
+            mPuk = puk;
+            mPin = pin;
+        }
+
+        abstract void onSimLockChangedResponse(boolean success);
+
+        @Override
+        public void run() {
+            try {
+                final boolean result = ITelephony.Stub.asInterface(ServiceManager
+                        .checkService("phone")).supplyPuk(mPuk, mPin);
+
+                post(new Runnable() {
+                    public void run() {
+                        onSimLockChangedResponse(result);
+                    }
+                });
+            } catch (RemoteException e) {
+                post(new Runnable() {
+                    public void run() {
+                        onSimLockChangedResponse(false);
+                    }
+                });
+            }
+        }
+    }
+
+    public void onClick(View v) {
+        if (v == mDelPukButton) {
+            if (mFocusedEntry != mPukText)
+                mPukText.requestFocus();
+            final Editable digits = mPukText.getEditableText();
+            final int len = digits.length();
+            if (len > 0) {
+                digits.delete(len-1, len);
+            }
+        } else if (v == mDelPinButton) {
+            if (mFocusedEntry != mPinText)
+                mPinText.requestFocus();
+            final Editable digits = mPinText.getEditableText();
+            final int len = digits.length();
+            if (len > 0) {
+                digits.delete(len-1, len);
+            }
+        } else if (v == mOkButton) {
+            checkPuk();
+        }
+        mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS);
+
+    }
+
+    @Override
+    public void onFocusChange(View v, boolean hasFocus) {
+        if (hasFocus)
+            mFocusedEntry = (TextView)v;
+    }
+
+    private Dialog getSimUnlockProgressDialog() {
+        if (mSimUnlockProgressDialog == null) {
+            mSimUnlockProgressDialog = new ProgressDialog(mContext);
+            mSimUnlockProgressDialog.setMessage(
+                    mContext.getString(R.string.lockscreen_sim_unlock_progress_dialog_message));
+            mSimUnlockProgressDialog.setIndeterminate(true);
+            mSimUnlockProgressDialog.setCancelable(false);
+            mSimUnlockProgressDialog.getWindow().setType(
+                    WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+        }
+        return mSimUnlockProgressDialog;
+    }
+
+    private void checkPuk() {
+        // make sure that the puk is at least 8 digits long.
+        if (mPukText.getText().length() < 8) {
+            // otherwise, display a message to the user, and don't submit.
+            mHeaderText.setText(R.string.invalidPuk);
+            mPukText.setText("");
+            return;
+        }
+
+        if (mPinText.getText().length() < 4
+                || mPinText.getText().length() > 8) {
+            // otherwise, display a message to the user, and don't submit.
+            mHeaderText.setText(R.string.invalidPin);
+            mPinText.setText("");
+            return;
+        }
+
+        getSimUnlockProgressDialog().show();
+
+        new CheckSimPuk(mPukText.getText().toString(),
+                mPinText.getText().toString()) {
+            void onSimLockChangedResponse(final boolean success) {
+                mPinText.post(new Runnable() {
+                    public void run() {
+                        if (mSimUnlockProgressDialog != null) {
+                            mSimUnlockProgressDialog.hide();
+                        }
+                        if (success) {
+                            // before closing the keyguard, report back that
+                            // the sim is unlocked so it knows right away
+                            mUpdateMonitor.reportSimUnlocked();
+                            mCallback.goToUnlockScreen();
+                        } else {
+                            mHeaderText.setText(R.string.badPuk);
+                            mPukText.setText("");
+                            mPinText.setText("");
+                        }
+                    }
+                });
+            }
+        }.start();
+    }
+
+
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+            mCallback.goToLockScreen();
+            return true;
+        }
+        final char match = event.getMatch(DIGITS);
+        if (match != 0) {
+            reportDigit(match - '0');
+            return true;
+        }
+        if (keyCode == KeyEvent.KEYCODE_DEL) {
+            mFocusedEntry.onKeyDown(keyCode, event);
+            final Editable digits = mFocusedEntry.getEditableText();
+            final int len = digits.length();
+            if (len > 0) {
+                digits.delete(len-1, len);
+            }
+            mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS);
+            return true;
+        }
+
+        if (keyCode == KeyEvent.KEYCODE_ENTER) {
+            checkPuk();
+            return true;
+        }
+
+        return false;
+    }
+
+    private void reportDigit(int digit) {
+        mFocusedEntry.append(Integer.toString(digit));
+    }
+
+    void updateConfiguration() {
+        Configuration newConfig = getResources().getConfiguration();
+        if (newConfig.orientation != mCreationOrientation) {
+            mCallback.recreateMe(newConfig);
+        } else if (newConfig.hardKeyboardHidden != mKeyboardHidden) {
+            mKeyboardHidden = newConfig.hardKeyboardHidden;
+        }
+
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        updateConfiguration();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        updateConfiguration();
+    }
+
+    /**
+     * Helper class to handle input from touch dialer.  Only relevant when
+     * the keyboard is shut.
+     */
+    private class TouchInput implements View.OnClickListener {
+        private TextView mZero;
+        private TextView mOne;
+        private TextView mTwo;
+        private TextView mThree;
+        private TextView mFour;
+        private TextView mFive;
+        private TextView mSix;
+        private TextView mSeven;
+        private TextView mEight;
+        private TextView mNine;
+        private TextView mCancelButton;
+
+        private TouchInput() {
+            mZero = (TextView) findViewById(R.id.zero);
+            mOne = (TextView) findViewById(R.id.one);
+            mTwo = (TextView) findViewById(R.id.two);
+            mThree = (TextView) findViewById(R.id.three);
+            mFour = (TextView) findViewById(R.id.four);
+            mFive = (TextView) findViewById(R.id.five);
+            mSix = (TextView) findViewById(R.id.six);
+            mSeven = (TextView) findViewById(R.id.seven);
+            mEight = (TextView) findViewById(R.id.eight);
+            mNine = (TextView) findViewById(R.id.nine);
+            mCancelButton = (TextView) findViewById(R.id.cancel);
+
+            mZero.setText("0");
+            mOne.setText("1");
+            mTwo.setText("2");
+            mThree.setText("3");
+            mFour.setText("4");
+            mFive.setText("5");
+            mSix.setText("6");
+            mSeven.setText("7");
+            mEight.setText("8");
+            mNine.setText("9");
+
+            mZero.setOnClickListener(this);
+            mOne.setOnClickListener(this);
+            mTwo.setOnClickListener(this);
+            mThree.setOnClickListener(this);
+            mFour.setOnClickListener(this);
+            mFive.setOnClickListener(this);
+            mSix.setOnClickListener(this);
+            mSeven.setOnClickListener(this);
+            mEight.setOnClickListener(this);
+            mNine.setOnClickListener(this);
+            mCancelButton.setOnClickListener(this);
+        }
+
+
+        public void onClick(View v) {
+            if (v == mCancelButton) {
+                // clear the PIN/PUK entry fields if the user cancels
+                mPinText.setText("");
+                mPukText.setText("");
+                mCallback.goToLockScreen();
+                return;
+            }
+
+            final int digit = checkDigit(v);
+            if (digit >= 0) {
+                mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS);
+                reportDigit(digit);
+            }
+        }
+
+        private int checkDigit(View v) {
+            int digit = -1;
+            if (v == mZero) {
+                digit = 0;
+            } else if (v == mOne) {
+                digit = 1;
+            } else if (v == mTwo) {
+                digit = 2;
+            } else if (v == mThree) {
+                digit = 3;
+            } else if (v == mFour) {
+                digit = 4;
+            } else if (v == mFive) {
+                digit = 5;
+            } else if (v == mSix) {
+                digit = 6;
+            } else if (v == mSeven) {
+                digit = 7;
+            } else if (v == mEight) {
+                digit = 8;
+            } else if (v == mNine) {
+                digit = 9;
+            }
+            return digit;
+        }
+    }
+
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimUnlockScreen.java
new file mode 100644
index 0000000..13c040c
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimUnlockScreen.java
@@ -0,0 +1,396 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.telephony.ITelephony;
+import com.android.internal.widget.LockPatternUtils;
+
+import android.text.Editable;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import com.android.internal.R;
+
+/**
+ * Displays a dialer like interface to unlock the SIM PIN.
+ */
+public class SimUnlockScreen extends LinearLayout implements KeyguardScreen, View.OnClickListener {
+
+    private static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
+
+    private final KeyguardUpdateMonitor mUpdateMonitor;
+    private final KeyguardScreenCallback mCallback;
+
+    private TextView mHeaderText;
+    private TextView mPinText;
+
+    private TextView mOkButton;
+
+    private View mBackSpaceButton;
+
+    private final int[] mEnteredPin = {0, 0, 0, 0, 0, 0, 0, 0};
+    private int mEnteredDigits = 0;
+
+    private ProgressDialog mSimUnlockProgressDialog = null;
+
+    private LockPatternUtils mLockPatternUtils;
+
+    private int mCreationOrientation;
+
+    private int mKeyboardHidden;
+
+    private KeyguardStatusViewManager mKeyguardStatusViewManager;
+
+    private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
+
+    public SimUnlockScreen(Context context, Configuration configuration,
+            KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback,
+            LockPatternUtils lockpatternutils) {
+        super(context);
+        mUpdateMonitor = updateMonitor;
+        mCallback = callback;
+
+        mCreationOrientation = configuration.orientation;
+        mKeyboardHidden = configuration.hardKeyboardHidden;
+        mLockPatternUtils = lockpatternutils;
+
+        LayoutInflater inflater = LayoutInflater.from(context);
+        if (mKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
+            inflater.inflate(R.layout.keyguard_screen_sim_pin_landscape, this, true);
+        } else {
+            inflater.inflate(R.layout.keyguard_screen_sim_pin_portrait, this, true);
+            new TouchInput();
+        }
+
+        mHeaderText = (TextView) findViewById(R.id.headerText);
+        mPinText = (TextView) findViewById(R.id.pinDisplay);
+        mBackSpaceButton = findViewById(R.id.backspace);
+        mBackSpaceButton.setOnClickListener(this);
+
+        mOkButton = (TextView) findViewById(R.id.ok);
+
+        mHeaderText.setText(R.string.keyguard_password_enter_pin_code);
+        mPinText.setFocusable(false);
+
+        mOkButton.setOnClickListener(this);
+
+        mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor,
+                lockpatternutils, callback, false);
+
+        setFocusableInTouchMode(true);
+    }
+
+    /** {@inheritDoc} */
+    public boolean needsInput() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    public void onPause() {
+        mKeyguardStatusViewManager.onPause();
+    }
+
+    /** {@inheritDoc} */
+    public void onResume() {
+        // start fresh
+        mHeaderText.setText(R.string.keyguard_password_enter_pin_code);
+
+        // make sure that the number of entered digits is consistent when we
+        // erase the SIM unlock code, including orientation changes.
+        mPinText.setText("");
+        mEnteredDigits = 0;
+
+        mKeyguardStatusViewManager.onResume();
+    }
+
+    /** {@inheritDoc} */
+    public void cleanUp() {
+        // dismiss the dialog.
+        if (mSimUnlockProgressDialog != null) {
+            mSimUnlockProgressDialog.dismiss();
+            mSimUnlockProgressDialog = null;
+        }
+        mUpdateMonitor.removeCallback(this);
+    }
+
+
+    /**
+     * Since the IPC can block, we want to run the request in a separate thread
+     * with a callback.
+     */
+    private abstract class CheckSimPin extends Thread {
+
+        private final String mPin;
+
+        protected CheckSimPin(String pin) {
+            mPin = pin;
+        }
+
+        abstract void onSimLockChangedResponse(boolean success);
+
+        @Override
+        public void run() {
+            try {
+                final boolean result = ITelephony.Stub.asInterface(ServiceManager
+                        .checkService("phone")).supplyPin(mPin);
+                post(new Runnable() {
+                    public void run() {
+                        onSimLockChangedResponse(result);
+                    }
+                });
+            } catch (RemoteException e) {
+                post(new Runnable() {
+                    public void run() {
+                        onSimLockChangedResponse(false);
+                    }
+                });
+            }
+        }
+    }
+
+    public void onClick(View v) {
+        if (v == mBackSpaceButton) {
+            final Editable digits = mPinText.getEditableText();
+            final int len = digits.length();
+            if (len > 0) {
+                digits.delete(len-1, len);
+                mEnteredDigits--;
+            }
+            mCallback.pokeWakelock();
+        } else if (v == mOkButton) {
+            checkPin();
+        }
+    }
+
+    private Dialog getSimUnlockProgressDialog() {
+        if (mSimUnlockProgressDialog == null) {
+            mSimUnlockProgressDialog = new ProgressDialog(mContext);
+            mSimUnlockProgressDialog.setMessage(
+                    mContext.getString(R.string.lockscreen_sim_unlock_progress_dialog_message));
+            mSimUnlockProgressDialog.setIndeterminate(true);
+            mSimUnlockProgressDialog.setCancelable(false);
+            mSimUnlockProgressDialog.getWindow().setType(
+                    WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+        }
+        return mSimUnlockProgressDialog;
+    }
+
+    private void checkPin() {
+
+        // make sure that the pin is at least 4 digits long.
+        if (mEnteredDigits < 4) {
+            // otherwise, display a message to the user, and don't submit.
+            mHeaderText.setText(R.string.invalidPin);
+            mPinText.setText("");
+            mEnteredDigits = 0;
+            mCallback.pokeWakelock();
+            return;
+        }
+        getSimUnlockProgressDialog().show();
+
+        new CheckSimPin(mPinText.getText().toString()) {
+            void onSimLockChangedResponse(final boolean success) {
+                mPinText.post(new Runnable() {
+                    public void run() {
+                        if (mSimUnlockProgressDialog != null) {
+                            mSimUnlockProgressDialog.hide();
+                        }
+                        if (success) {
+                            // before closing the keyguard, report back that
+                            // the sim is unlocked so it knows right away
+                            mUpdateMonitor.reportSimUnlocked();
+                            mCallback.goToUnlockScreen();
+                        } else {
+                            mHeaderText.setText(R.string.keyguard_password_wrong_pin_code);
+                            mPinText.setText("");
+                            mEnteredDigits = 0;
+                        }
+                        mCallback.pokeWakelock();
+                    }
+                });
+            }
+        }.start();
+    }
+
+
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+            mCallback.goToLockScreen();
+            return true;
+        }
+
+        final char match = event.getMatch(DIGITS);
+        if (match != 0) {
+            reportDigit(match - '0');
+            return true;
+        }
+        if (keyCode == KeyEvent.KEYCODE_DEL) {
+            if (mEnteredDigits > 0) {
+                mPinText.onKeyDown(keyCode, event);
+                mEnteredDigits--;
+            }
+            return true;
+        }
+
+        if (keyCode == KeyEvent.KEYCODE_ENTER) {
+            checkPin();
+            return true;
+        }
+
+        return false;
+    }
+
+    private void reportDigit(int digit) {
+        if (mEnteredDigits == 0) {
+            mPinText.setText("");
+        }
+        if (mEnteredDigits == 8) {
+            return;
+        }
+        mPinText.append(Integer.toString(digit));
+        mEnteredPin[mEnteredDigits++] = digit;
+    }
+
+    void updateConfiguration() {
+        Configuration newConfig = getResources().getConfiguration();
+        if (newConfig.orientation != mCreationOrientation) {
+            mCallback.recreateMe(newConfig);
+        } else if (newConfig.hardKeyboardHidden != mKeyboardHidden) {
+            mKeyboardHidden = newConfig.hardKeyboardHidden;
+        }
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        updateConfiguration();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        updateConfiguration();
+    }
+
+    /**
+     * Helper class to handle input from touch dialer.  Only relevant when
+     * the keyboard is shut.
+     */
+    private class TouchInput implements View.OnClickListener {
+        private TextView mZero;
+        private TextView mOne;
+        private TextView mTwo;
+        private TextView mThree;
+        private TextView mFour;
+        private TextView mFive;
+        private TextView mSix;
+        private TextView mSeven;
+        private TextView mEight;
+        private TextView mNine;
+        private TextView mCancelButton;
+
+        private TouchInput() {
+            mZero = (TextView) findViewById(R.id.zero);
+            mOne = (TextView) findViewById(R.id.one);
+            mTwo = (TextView) findViewById(R.id.two);
+            mThree = (TextView) findViewById(R.id.three);
+            mFour = (TextView) findViewById(R.id.four);
+            mFive = (TextView) findViewById(R.id.five);
+            mSix = (TextView) findViewById(R.id.six);
+            mSeven = (TextView) findViewById(R.id.seven);
+            mEight = (TextView) findViewById(R.id.eight);
+            mNine = (TextView) findViewById(R.id.nine);
+            mCancelButton = (TextView) findViewById(R.id.cancel);
+
+            mZero.setText("0");
+            mOne.setText("1");
+            mTwo.setText("2");
+            mThree.setText("3");
+            mFour.setText("4");
+            mFive.setText("5");
+            mSix.setText("6");
+            mSeven.setText("7");
+            mEight.setText("8");
+            mNine.setText("9");
+
+            mZero.setOnClickListener(this);
+            mOne.setOnClickListener(this);
+            mTwo.setOnClickListener(this);
+            mThree.setOnClickListener(this);
+            mFour.setOnClickListener(this);
+            mFive.setOnClickListener(this);
+            mSix.setOnClickListener(this);
+            mSeven.setOnClickListener(this);
+            mEight.setOnClickListener(this);
+            mNine.setOnClickListener(this);
+            mCancelButton.setOnClickListener(this);
+        }
+
+
+        public void onClick(View v) {
+            if (v == mCancelButton) {
+                mPinText.setText(""); // clear the PIN entry field if the user cancels
+                mCallback.goToLockScreen();
+                return;
+            }
+
+            final int digit = checkDigit(v);
+            if (digit >= 0) {
+                mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS);
+                reportDigit(digit);
+            }
+        }
+
+        private int checkDigit(View v) {
+            int digit = -1;
+            if (v == mZero) {
+                digit = 0;
+            } else if (v == mOne) {
+                digit = 1;
+            } else if (v == mTwo) {
+                digit = 2;
+            } else if (v == mThree) {
+                digit = 3;
+            } else if (v == mFour) {
+                digit = 4;
+            } else if (v == mFive) {
+                digit = 5;
+            } else if (v == mSix) {
+                digit = 6;
+            } else if (v == mSeven) {
+                digit = 7;
+            } else if (v == mEight) {
+                digit = 8;
+            } else if (v == mNine) {
+                digit = 9;
+            }
+            return digit;
+        }
+    }
+}
diff --git a/policy/tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java b/policy/tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java
deleted file mode 100644
index 862e683..0000000
--- a/policy/tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java
+++ /dev/null
@@ -1,351 +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.
- */
-
-package com.android.internal.policy.impl;
-
-import android.content.Context;
-import com.android.internal.policy.impl.KeyguardViewCallback;
-import com.android.internal.telephony.IccCardConstants;
-import android.content.res.Configuration;
-import android.test.AndroidTestCase;
-import android.view.View;
-import android.view.KeyEvent;
-import com.android.internal.widget.LockPatternUtils;
-import com.google.android.collect.Lists;
-
-import java.util.List;
-
-/**
- * Tests for {@link com.android.internal.policy.impl.LockPatternKeyguardView},
- * which handles the management of screens while the keyguard is showing.
- */
-public class LockPatternKeyguardViewTest extends AndroidTestCase {
-    private MockUpdateMonitor mUpdateMonitor;
-    private LockPatternUtils mLockPatternUtils;
-    private TestableLockPatternKeyguardView mLPKV;
-    private MockKeyguardCallback mKeyguardViewCallback;
-
-    private static class MockUpdateMonitor extends KeyguardUpdateMonitor {
-
-        public IccCardConstants.State simState = IccCardConstants.State.READY;
-
-        private MockUpdateMonitor(Context context) {
-            super(context);
-        }
-
-        @Override
-        public IccCardConstants.State getSimState() {
-            return simState;
-        }
-    }
-
-    private static class MockLockPatternUtils extends LockPatternUtils {
-        boolean isLockPatternEnabled = true;
-        public boolean isPermanentlyLocked = false;
-
-        public MockLockPatternUtils(Context context) {
-            super(context);
-        }
-
-        @Override
-        public boolean isLockPatternEnabled() {
-            return isLockPatternEnabled;
-        }
-
-        @Override
-        public void setLockPatternEnabled(boolean lockPatternEnabled) {
-            isLockPatternEnabled = lockPatternEnabled;
-        }
-
-        @Override
-        public boolean isPermanentlyLocked() {
-            return isPermanentlyLocked;
-        }
-
-        public void setPermanentlyLocked(boolean permanentlyLocked) {
-            isPermanentlyLocked = permanentlyLocked;
-        }
-    }
-
-    private static class MockKeyguardScreen extends View implements KeyguardScreen {
-
-        private int mOnPauseCount = 0;
-        private int mOnResumeCount = 0;
-        private int mCleanupCount = 0;
-
-        private MockKeyguardScreen(Context context) {
-            super(context);
-            setFocusable(true);
-        }
-
-        /** {@inheritDoc} */
-        public boolean needsInput() {
-            return false;
-        }
-
-        /** {@inheritDoc} */
-        public void onPause() {
-            mOnPauseCount++;
-        }
-
-        /** {@inheritDoc} */
-        public void onResume() {
-            mOnResumeCount++;
-        }
-
-        /** {@inheritDoc} */
-        public void cleanUp() {
-            mCleanupCount++;
-        }
-
-        public int getOnPauseCount() {
-            return mOnPauseCount;
-        }
-
-        public int getOnResumeCount() {
-            return mOnResumeCount;
-        }
-
-        public int getCleanupCount() {
-            return mCleanupCount;
-        }
-    }
-
-    /**
-     * Allows us to inject the lock and unlock views to simulate their behavior
-     * and detect their creation.
-     */
-    private static class TestableLockPatternKeyguardView extends LockPatternKeyguardView {
-        private List<MockKeyguardScreen> mInjectedLockScreens;
-        private List<MockKeyguardScreen> mInjectedUnlockScreens;
-
-
-
-        private TestableLockPatternKeyguardView(Context context, KeyguardViewCallback callback,
-                KeyguardUpdateMonitor updateMonitor,
-                LockPatternUtils lockPatternUtils, KeyguardWindowController controller) {
-            super(context, callback, updateMonitor, lockPatternUtils, controller);
-        }
-
-        @Override
-        View createLockScreen() {
-            final MockKeyguardScreen newView = new MockKeyguardScreen(getContext());
-            if (mInjectedLockScreens == null) mInjectedLockScreens = Lists.newArrayList();
-            mInjectedLockScreens.add(newView);
-            return newView;
-        }
-
-        @Override
-        View createUnlockScreenFor(UnlockMode unlockMode) {
-            final MockKeyguardScreen newView = new MockKeyguardScreen(getContext());
-            if (mInjectedUnlockScreens == null) mInjectedUnlockScreens = Lists.newArrayList();
-            mInjectedUnlockScreens.add(newView);
-            return newView;
-        }
-
-        public List<MockKeyguardScreen> getInjectedLockScreens() {
-            return mInjectedLockScreens;
-        }
-
-        public List<MockKeyguardScreen> getInjectedUnlockScreens() {
-            return mInjectedUnlockScreens;
-        }
-    }
-
-    private static class MockKeyguardCallback implements KeyguardViewCallback {
-
-        private int mPokeWakelockCount = 0;
-        private int mKeyguardDoneCount = 0;
-
-        public void pokeWakelock() {
-            mPokeWakelockCount++;
-        }
-
-        public void pokeWakelock(int millis) {
-            mPokeWakelockCount++;
-        }
-
-        public void keyguardDone(boolean authenticated) {
-            mKeyguardDoneCount++;
-        }
-
-        public void keyguardDoneDrawing() {
-
-        }
-
-        public int getPokeWakelockCount() {
-            return mPokeWakelockCount;
-        }
-
-        public int getKeyguardDoneCount() {
-            return mKeyguardDoneCount;
-        }
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mUpdateMonitor = new MockUpdateMonitor(getContext());
-        mLockPatternUtils = new MockLockPatternUtils(getContext());
-        mKeyguardViewCallback = new MockKeyguardCallback();
-
-        mLPKV = new TestableLockPatternKeyguardView(getContext(), mKeyguardViewCallback,
-                mUpdateMonitor, mLockPatternUtils, new KeyguardWindowController() {
-            public void setNeedsInput(boolean needsInput) {
-            }
-        });
-    }
-
-    public void testStateAfterCreatedWhileScreenOff() {
-
-        assertEquals(1, mLPKV.getInjectedLockScreens().size());
-        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
-
-        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
-        MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
-
-        assertEquals(0, lockScreen.getOnPauseCount());
-        assertEquals(0, lockScreen.getOnResumeCount());
-        assertEquals(0, lockScreen.getCleanupCount());
-
-        assertEquals(0, unlockScreen.getOnPauseCount());
-        assertEquals(0, unlockScreen.getOnResumeCount());
-        assertEquals(0, unlockScreen.getCleanupCount());
-
-        assertEquals(0, mKeyguardViewCallback.getPokeWakelockCount());
-        assertEquals(0, mKeyguardViewCallback.getKeyguardDoneCount());
-    }
-
-    public void testWokenByNonMenuKey() {
-        mLPKV.wakeWhenReadyTq(0);
-
-        // should have poked the wakelock to turn on the screen
-        assertEquals(1, mKeyguardViewCallback.getPokeWakelockCount());
-
-        // shouldn't be any additional views created
-        assertEquals(1, mLPKV.getInjectedLockScreens().size());
-        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
-        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
-        MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
-
-        // lock screen should be only visible one
-        assertEquals(View.VISIBLE, lockScreen.getVisibility());
-        assertEquals(View.GONE, unlockScreen.getVisibility());
-
-        // on resume not called until screen turns on
-        assertEquals(0, lockScreen.getOnPauseCount());
-        assertEquals(0, lockScreen.getOnResumeCount());
-        assertEquals(0, lockScreen.getCleanupCount());
-
-        assertEquals(0, unlockScreen.getOnPauseCount());
-        assertEquals(0, unlockScreen.getOnResumeCount());
-        assertEquals(0, unlockScreen.getCleanupCount());
-
-        // simulate screen turning on
-        mLPKV.onScreenTurnedOn();
-
-        assertEquals(0, lockScreen.getOnPauseCount());
-        assertEquals(1, lockScreen.getOnResumeCount());
-        assertEquals(0, lockScreen.getCleanupCount());
-
-        assertEquals(0, unlockScreen.getOnPauseCount());
-        assertEquals(0, unlockScreen.getOnResumeCount());
-        assertEquals(0, unlockScreen.getCleanupCount());
-    }
-
-    public void testWokenByMenuKeyWhenPatternSet() {
-        assertEquals(true, mLockPatternUtils.isLockPatternEnabled());
-
-        mLPKV.wakeWhenReadyTq(KeyEvent.KEYCODE_MENU);
-
-        // should have poked the wakelock to turn on the screen
-        assertEquals(1, mKeyguardViewCallback.getPokeWakelockCount());
-
-        // shouldn't be any additional views created
-        assertEquals(1, mLPKV.getInjectedLockScreens().size());
-        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
-        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
-        MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
-
-        // unlock screen should be only visible one
-        assertEquals(View.GONE, lockScreen.getVisibility());
-        assertEquals(View.VISIBLE, unlockScreen.getVisibility());
-    }
-
-    public void testScreenRequestsRecreation() {
-        mLPKV.wakeWhenReadyTq(0);
-        mLPKV.onScreenTurnedOn();
-
-        assertEquals(1, mLPKV.getInjectedLockScreens().size());
-        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
-        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
-
-        assertEquals(0, lockScreen.getOnPauseCount());
-        assertEquals(1, lockScreen.getOnResumeCount());
-
-        // simulate screen asking to be recreated
-        mLPKV.mKeyguardScreenCallback.recreateMe(new Configuration());
-
-        // should have been recreated
-        assertEquals(2, mLPKV.getInjectedLockScreens().size());
-        assertEquals(2, mLPKV.getInjectedUnlockScreens().size());
-
-        // both old screens should have been cleaned up
-        assertEquals(1, mLPKV.getInjectedLockScreens().get(0).getCleanupCount());
-        assertEquals(1, mLPKV.getInjectedUnlockScreens().get(0).getCleanupCount());
-
-        // old lock screen should have been paused
-        assertEquals(1, mLPKV.getInjectedLockScreens().get(0).getOnPauseCount());
-        assertEquals(0, mLPKV.getInjectedUnlockScreens().get(0).getOnPauseCount());
-
-        // new lock screen should have been resumed
-        assertEquals(1, mLPKV.getInjectedLockScreens().get(1).getOnResumeCount());
-        assertEquals(0, mLPKV.getInjectedUnlockScreens().get(1).getOnResumeCount());
-    }
-
-    public void testMenuDoesntGoToUnlockScreenOnWakeWhenPukLocked() {
-        // PUK locked
-        mUpdateMonitor.simState = IccCardConstants.State.PUK_REQUIRED;
-
-        // wake by menu
-        mLPKV.wakeWhenReadyTq(KeyEvent.KEYCODE_MENU);
-
-        assertEquals(1, mLPKV.getInjectedLockScreens().size());
-        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
-        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
-        MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
-
-        // lock screen should be only visible one
-        assertEquals(View.VISIBLE, lockScreen.getVisibility());
-        assertEquals(View.GONE, unlockScreen.getVisibility());
-    }
-
-    public void testMenuGoesToLockScreenWhenDeviceNotSecure() {
-        mLockPatternUtils.setLockPatternEnabled(false);
-
-        // wake by menu
-        mLPKV.wakeWhenReadyTq(KeyEvent.KEYCODE_MENU);
-
-        assertEquals(1, mLPKV.getInjectedLockScreens().size());
-        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
-        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
-        MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
-
-        // lock screen should be only visible one
-        assertEquals(View.VISIBLE, lockScreen.getVisibility());
-        assertEquals(View.GONE, unlockScreen.getVisibility());
-    }
-}
diff --git a/policy/tests/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewTest.java b/policy/tests/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewTest.java
new file mode 100644
index 0000000..97c5672
--- /dev/null
+++ b/policy/tests/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewTest.java
@@ -0,0 +1,356 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.policy.impl.keyguard_obsolete;
+
+import android.content.Context;
+
+import com.android.internal.policy.impl.keyguard_obsolete.KeyguardScreen;
+import com.android.internal.policy.impl.keyguard_obsolete.KeyguardUpdateMonitor;
+import com.android.internal.policy.impl.keyguard_obsolete.KeyguardViewCallback;
+import com.android.internal.policy.impl.keyguard_obsolete.KeyguardWindowController;
+import com.android.internal.policy.impl.keyguard_obsolete.LockPatternKeyguardView;
+import com.android.internal.telephony.IccCardConstants;
+import android.content.res.Configuration;
+import android.test.AndroidTestCase;
+import android.view.View;
+import android.view.KeyEvent;
+import com.android.internal.widget.LockPatternUtils;
+import com.google.android.collect.Lists;
+
+import java.util.List;
+
+/**
+ * Tests for {@link com.android.internal.policy.impl.LockPatternKeyguardView},
+ * which handles the management of screens while the keyguard is showing.
+ */
+public class LockPatternKeyguardViewTest extends AndroidTestCase {
+    private MockUpdateMonitor mUpdateMonitor;
+    private LockPatternUtils mLockPatternUtils;
+    private TestableLockPatternKeyguardView mLPKV;
+    private MockKeyguardCallback mKeyguardViewCallback;
+
+    private static class MockUpdateMonitor extends KeyguardUpdateMonitor {
+
+        public IccCardConstants.State simState = IccCardConstants.State.READY;
+
+        private MockUpdateMonitor(Context context) {
+            super(context);
+        }
+
+        @Override
+        public IccCardConstants.State getSimState() {
+            return simState;
+        }
+    }
+
+    private static class MockLockPatternUtils extends LockPatternUtils {
+        boolean isLockPatternEnabled = true;
+        public boolean isPermanentlyLocked = false;
+
+        public MockLockPatternUtils(Context context) {
+            super(context);
+        }
+
+        @Override
+        public boolean isLockPatternEnabled() {
+            return isLockPatternEnabled;
+        }
+
+        @Override
+        public void setLockPatternEnabled(boolean lockPatternEnabled) {
+            isLockPatternEnabled = lockPatternEnabled;
+        }
+
+        @Override
+        public boolean isPermanentlyLocked() {
+            return isPermanentlyLocked;
+        }
+
+        public void setPermanentlyLocked(boolean permanentlyLocked) {
+            isPermanentlyLocked = permanentlyLocked;
+        }
+    }
+
+    private static class MockKeyguardScreen extends View implements KeyguardScreen {
+
+        private int mOnPauseCount = 0;
+        private int mOnResumeCount = 0;
+        private int mCleanupCount = 0;
+
+        private MockKeyguardScreen(Context context) {
+            super(context);
+            setFocusable(true);
+        }
+
+        /** {@inheritDoc} */
+        public boolean needsInput() {
+            return false;
+        }
+
+        /** {@inheritDoc} */
+        public void onPause() {
+            mOnPauseCount++;
+        }
+
+        /** {@inheritDoc} */
+        public void onResume() {
+            mOnResumeCount++;
+        }
+
+        /** {@inheritDoc} */
+        public void cleanUp() {
+            mCleanupCount++;
+        }
+
+        public int getOnPauseCount() {
+            return mOnPauseCount;
+        }
+
+        public int getOnResumeCount() {
+            return mOnResumeCount;
+        }
+
+        public int getCleanupCount() {
+            return mCleanupCount;
+        }
+    }
+
+    /**
+     * Allows us to inject the lock and unlock views to simulate their behavior
+     * and detect their creation.
+     */
+    private static class TestableLockPatternKeyguardView extends LockPatternKeyguardView {
+        private List<MockKeyguardScreen> mInjectedLockScreens;
+        private List<MockKeyguardScreen> mInjectedUnlockScreens;
+
+
+
+        private TestableLockPatternKeyguardView(Context context, KeyguardViewCallback callback,
+                KeyguardUpdateMonitor updateMonitor,
+                LockPatternUtils lockPatternUtils, KeyguardWindowController controller) {
+            super(context, callback, updateMonitor, lockPatternUtils, controller);
+        }
+
+        @Override
+        View createLockScreen() {
+            final MockKeyguardScreen newView = new MockKeyguardScreen(getContext());
+            if (mInjectedLockScreens == null) mInjectedLockScreens = Lists.newArrayList();
+            mInjectedLockScreens.add(newView);
+            return newView;
+        }
+
+        @Override
+        View createUnlockScreenFor(UnlockMode unlockMode) {
+            final MockKeyguardScreen newView = new MockKeyguardScreen(getContext());
+            if (mInjectedUnlockScreens == null) mInjectedUnlockScreens = Lists.newArrayList();
+            mInjectedUnlockScreens.add(newView);
+            return newView;
+        }
+
+        public List<MockKeyguardScreen> getInjectedLockScreens() {
+            return mInjectedLockScreens;
+        }
+
+        public List<MockKeyguardScreen> getInjectedUnlockScreens() {
+            return mInjectedUnlockScreens;
+        }
+    }
+
+    private static class MockKeyguardCallback implements KeyguardViewCallback {
+
+        private int mPokeWakelockCount = 0;
+        private int mKeyguardDoneCount = 0;
+
+        public void pokeWakelock() {
+            mPokeWakelockCount++;
+        }
+
+        public void pokeWakelock(int millis) {
+            mPokeWakelockCount++;
+        }
+
+        public void keyguardDone(boolean authenticated) {
+            mKeyguardDoneCount++;
+        }
+
+        public void keyguardDoneDrawing() {
+
+        }
+
+        public int getPokeWakelockCount() {
+            return mPokeWakelockCount;
+        }
+
+        public int getKeyguardDoneCount() {
+            return mKeyguardDoneCount;
+        }
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mUpdateMonitor = new MockUpdateMonitor(getContext());
+        mLockPatternUtils = new MockLockPatternUtils(getContext());
+        mKeyguardViewCallback = new MockKeyguardCallback();
+
+        mLPKV = new TestableLockPatternKeyguardView(getContext(), mKeyguardViewCallback,
+                mUpdateMonitor, mLockPatternUtils, new KeyguardWindowController() {
+            public void setNeedsInput(boolean needsInput) {
+            }
+        });
+    }
+
+    public void testStateAfterCreatedWhileScreenOff() {
+
+        assertEquals(1, mLPKV.getInjectedLockScreens().size());
+        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
+
+        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
+        MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
+
+        assertEquals(0, lockScreen.getOnPauseCount());
+        assertEquals(0, lockScreen.getOnResumeCount());
+        assertEquals(0, lockScreen.getCleanupCount());
+
+        assertEquals(0, unlockScreen.getOnPauseCount());
+        assertEquals(0, unlockScreen.getOnResumeCount());
+        assertEquals(0, unlockScreen.getCleanupCount());
+
+        assertEquals(0, mKeyguardViewCallback.getPokeWakelockCount());
+        assertEquals(0, mKeyguardViewCallback.getKeyguardDoneCount());
+    }
+
+    public void testWokenByNonMenuKey() {
+        mLPKV.wakeWhenReadyTq(0);
+
+        // should have poked the wakelock to turn on the screen
+        assertEquals(1, mKeyguardViewCallback.getPokeWakelockCount());
+
+        // shouldn't be any additional views created
+        assertEquals(1, mLPKV.getInjectedLockScreens().size());
+        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
+        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
+        MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
+
+        // lock screen should be only visible one
+        assertEquals(View.VISIBLE, lockScreen.getVisibility());
+        assertEquals(View.GONE, unlockScreen.getVisibility());
+
+        // on resume not called until screen turns on
+        assertEquals(0, lockScreen.getOnPauseCount());
+        assertEquals(0, lockScreen.getOnResumeCount());
+        assertEquals(0, lockScreen.getCleanupCount());
+
+        assertEquals(0, unlockScreen.getOnPauseCount());
+        assertEquals(0, unlockScreen.getOnResumeCount());
+        assertEquals(0, unlockScreen.getCleanupCount());
+
+        // simulate screen turning on
+        mLPKV.onScreenTurnedOn();
+
+        assertEquals(0, lockScreen.getOnPauseCount());
+        assertEquals(1, lockScreen.getOnResumeCount());
+        assertEquals(0, lockScreen.getCleanupCount());
+
+        assertEquals(0, unlockScreen.getOnPauseCount());
+        assertEquals(0, unlockScreen.getOnResumeCount());
+        assertEquals(0, unlockScreen.getCleanupCount());
+    }
+
+    public void testWokenByMenuKeyWhenPatternSet() {
+        assertEquals(true, mLockPatternUtils.isLockPatternEnabled());
+
+        mLPKV.wakeWhenReadyTq(KeyEvent.KEYCODE_MENU);
+
+        // should have poked the wakelock to turn on the screen
+        assertEquals(1, mKeyguardViewCallback.getPokeWakelockCount());
+
+        // shouldn't be any additional views created
+        assertEquals(1, mLPKV.getInjectedLockScreens().size());
+        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
+        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
+        MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
+
+        // unlock screen should be only visible one
+        assertEquals(View.GONE, lockScreen.getVisibility());
+        assertEquals(View.VISIBLE, unlockScreen.getVisibility());
+    }
+
+    public void testScreenRequestsRecreation() {
+        mLPKV.wakeWhenReadyTq(0);
+        mLPKV.onScreenTurnedOn();
+
+        assertEquals(1, mLPKV.getInjectedLockScreens().size());
+        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
+        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
+
+        assertEquals(0, lockScreen.getOnPauseCount());
+        assertEquals(1, lockScreen.getOnResumeCount());
+
+        // simulate screen asking to be recreated
+        mLPKV.mKeyguardScreenCallback.recreateMe(new Configuration());
+
+        // should have been recreated
+        assertEquals(2, mLPKV.getInjectedLockScreens().size());
+        assertEquals(2, mLPKV.getInjectedUnlockScreens().size());
+
+        // both old screens should have been cleaned up
+        assertEquals(1, mLPKV.getInjectedLockScreens().get(0).getCleanupCount());
+        assertEquals(1, mLPKV.getInjectedUnlockScreens().get(0).getCleanupCount());
+
+        // old lock screen should have been paused
+        assertEquals(1, mLPKV.getInjectedLockScreens().get(0).getOnPauseCount());
+        assertEquals(0, mLPKV.getInjectedUnlockScreens().get(0).getOnPauseCount());
+
+        // new lock screen should have been resumed
+        assertEquals(1, mLPKV.getInjectedLockScreens().get(1).getOnResumeCount());
+        assertEquals(0, mLPKV.getInjectedUnlockScreens().get(1).getOnResumeCount());
+    }
+
+    public void testMenuDoesntGoToUnlockScreenOnWakeWhenPukLocked() {
+        // PUK locked
+        mUpdateMonitor.simState = IccCardConstants.State.PUK_REQUIRED;
+
+        // wake by menu
+        mLPKV.wakeWhenReadyTq(KeyEvent.KEYCODE_MENU);
+
+        assertEquals(1, mLPKV.getInjectedLockScreens().size());
+        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
+        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
+        MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
+
+        // lock screen should be only visible one
+        assertEquals(View.VISIBLE, lockScreen.getVisibility());
+        assertEquals(View.GONE, unlockScreen.getVisibility());
+    }
+
+    public void testMenuGoesToLockScreenWhenDeviceNotSecure() {
+        mLockPatternUtils.setLockPatternEnabled(false);
+
+        // wake by menu
+        mLPKV.wakeWhenReadyTq(KeyEvent.KEYCODE_MENU);
+
+        assertEquals(1, mLPKV.getInjectedLockScreens().size());
+        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
+        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
+        MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
+
+        // lock screen should be only visible one
+        assertEquals(View.VISIBLE, lockScreen.getVisibility());
+        assertEquals(View.GONE, unlockScreen.getVisibility());
+    }
+}
diff --git a/preloaded-classes b/preloaded-classes
index feddbd6..10c5c9e 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -6,7 +6,8 @@
 android.accounts.Account
 android.accounts.Account$1
 android.accounts.AccountManager
-android.accounts.AccountManager$12
+android.accounts.AccountManager$13
+android.accounts.AccountManager$6
 android.accounts.AccountManager$AmsTask
 android.accounts.AccountManager$AmsTask$1
 android.accounts.AccountManager$AmsTask$Response
@@ -16,6 +17,7 @@
 android.accounts.IAccountManager$Stub$Proxy
 android.accounts.IAccountManagerResponse
 android.accounts.IAccountManagerResponse$Stub
+android.accounts.OnAccountsUpdateListener
 android.animation.Animator
 android.animation.Animator$AnimatorListener
 android.animation.AnimatorInflater
@@ -27,21 +29,25 @@
 android.animation.FloatEvaluator
 android.animation.FloatKeyframeSet
 android.animation.IntEvaluator
+android.animation.IntKeyframeSet
 android.animation.Keyframe
 android.animation.Keyframe$FloatKeyframe
+android.animation.Keyframe$IntKeyframe
 android.animation.KeyframeSet
+android.animation.LayoutTransition
 android.animation.LayoutTransition$TransitionListener
 android.animation.ObjectAnimator
 android.animation.PropertyValuesHolder
 android.animation.PropertyValuesHolder$FloatPropertyValuesHolder
+android.animation.PropertyValuesHolder$IntPropertyValuesHolder
 android.animation.TimeInterpolator
 android.animation.TypeEvaluator
 android.animation.ValueAnimator
-android.animation.ValueAnimator$1
 android.animation.ValueAnimator$AnimationHandler
 android.app.ActionBar
 android.app.ActionBar$LayoutParams
 android.app.Activity
+android.app.Activity$1
 android.app.ActivityManager
 android.app.ActivityManagerNative
 android.app.ActivityManagerNative$1
@@ -55,6 +61,7 @@
 android.app.ActivityThread$BindServiceData
 android.app.ActivityThread$ContextCleanupInfo
 android.app.ActivityThread$CreateServiceData
+android.app.ActivityThread$EventLoggingReporter
 android.app.ActivityThread$GcIdler
 android.app.ActivityThread$H
 android.app.ActivityThread$Idler
@@ -63,6 +70,7 @@
 android.app.ActivityThread$ProviderRefCount
 android.app.ActivityThread$ReceiverData
 android.app.ActivityThread$ResourcesKey
+android.app.ActivityThread$ResultData
 android.app.ActivityThread$ServiceArgsData
 android.app.ActivityThread$StopInfo
 android.app.AlertDialog
@@ -103,7 +111,14 @@
 android.app.ContextImpl$31
 android.app.ContextImpl$32
 android.app.ContextImpl$33
+android.app.ContextImpl$34
+android.app.ContextImpl$35
+android.app.ContextImpl$36
+android.app.ContextImpl$37
+android.app.ContextImpl$38
+android.app.ContextImpl$39
 android.app.ContextImpl$4
+android.app.ContextImpl$40
 android.app.ContextImpl$5
 android.app.ContextImpl$6
 android.app.ContextImpl$7
@@ -117,12 +132,11 @@
 android.app.Dialog$ListenersHandler
 android.app.DialogFragment
 android.app.Fragment
+android.app.FragmentContainer
 android.app.FragmentManager
 android.app.FragmentManager$BackStackEntry
 android.app.FragmentManagerImpl
 android.app.FragmentManagerImpl$1
-android.app.FragmentManagerImpl$2
-android.app.FragmentManagerImpl$3
 android.app.FragmentTransaction
 android.app.IActivityManager
 android.app.IActivityManager$ContentProviderHolder
@@ -158,6 +172,8 @@
 android.app.LoadedApk$ServiceDispatcher$InnerConnection
 android.app.LoadedApk$ServiceDispatcher$RunConnection
 android.app.LoadedApk$WarningContextClassLoader
+android.app.LoaderManager
+android.app.LoaderManagerImpl
 android.app.NativeActivity
 android.app.NotificationManager
 android.app.PendingIntent
@@ -190,6 +206,9 @@
 android.bluetooth.IBluetooth$Stub
 android.bluetooth.IBluetoothA2dp
 android.bluetooth.IBluetoothA2dp$Stub
+android.content.AbstractThreadedSyncAdapter
+android.content.AbstractThreadedSyncAdapter$ISyncAdapterImpl
+undroid.content.AbstractThreadedSyncAdapter$SyncThread
 android.content.BroadcastReceiver
 android.content.BroadcastReceiver$PendingResult
 android.content.ComponentCallbacks
@@ -198,8 +217,10 @@
 android.content.ComponentName$1
 android.content.ContentProvider
 android.content.ContentProvider$Transport
+android.content.ContentProviderClient
 android.content.ContentProviderNative
 android.content.ContentProviderProxy
+android.content.ContentProviderResult
 android.content.ContentResolver
 android.content.ContentResolver$CursorWrapperInner
 android.content.ContentResolver$ParcelFileDescriptorInner
@@ -221,6 +242,11 @@
 android.content.IIntentSender
 android.content.IIntentSender$Stub
 android.content.IIntentSender$Stub$Proxy
+android.content.ISyncAdapter
+android.content.ISyncAdapter$Stub
+android.content.ISyncContext
+android.content.ISyncContext$Stub
+android.content.ISyncContext$Stub$Proxy
 android.content.Intent
 android.content.Intent$1
 android.content.IntentFilter
@@ -229,6 +255,11 @@
 android.content.SharedPreferences
 android.content.SharedPreferences$Editor
 android.content.SharedPreferences$OnSharedPreferenceChangeListener
+android.content.SyncContext
+android.content.SyncResult
+android.content.SyncResult$1
+android.content.SyncStats
+android.content.SyncStats$1
 android.content.UriMatcher
 android.content.pm.ActivityInfo
 android.content.pm.ActivityInfo$1
@@ -248,6 +279,7 @@
 android.content.pm.PackageInfo$1
 android.content.pm.PackageItemInfo
 android.content.pm.PackageManager
+android.content.pm.PackageManager$NameNotFoundException
 android.content.pm.PathPermission
 android.content.pm.PathPermission$1
 android.content.pm.PermissionInfo
@@ -285,6 +317,8 @@
 android.database.AbstractCursor
 android.database.AbstractCursor$SelfContentObserver
 android.database.AbstractWindowedCursor
+android.database.BulkCursorDescriptor
+android.database.BulkCursorDescriptor$1
 android.database.BulkCursorNative
 android.database.BulkCursorProxy
 android.database.BulkCursorToCursorAdaptor
@@ -294,6 +328,7 @@
 android.database.ContentObserver$NotificationRunnable
 android.database.ContentObserver$Transport
 android.database.CrossProcessCursor
+android.database.CrossProcessCursorWrapper
 android.database.Cursor
 android.database.CursorToBulkCursorAdaptor
 android.database.CursorToBulkCursorAdaptor$ContentObserverProxy
@@ -313,19 +348,32 @@
 android.database.Observable
 android.database.sqlite.DatabaseObjectNotClosedException
 android.database.sqlite.SQLiteClosable
+android.database.sqlite.SQLiteConnection
+android.database.sqlite.SQLiteConnection$Operation
+android.database.sqlite.SQLiteConnection$OperationLog
+android.database.sqlite.SQLiteConnection$PreparedStatement
+android.database.sqlite.SQLiteConnection$PreparedStatementCache
+android.database.sqlite.SQLiteConnectionPool
+android.database.sqlite.SQLiteConnectionPool$AcquiredConnectionStatus
 android.database.sqlite.SQLiteCursor
 android.database.sqlite.SQLiteCursorDriver
+android.database.sqlite.SQLiteCustomFunction
 android.database.sqlite.SQLiteDatabase
 android.database.sqlite.SQLiteDatabase$1
+android.database.sqlite.SQLiteDatabaseConfiguration
 android.database.sqlite.SQLiteDatabase$CustomFunction
 android.database.sqlite.SQLiteDebug
 android.database.sqlite.SQLiteDebug$PagerStats
 android.database.sqlite.SQLiteDirectCursorDriver
+android.database.sqlite.SQLiteGlobal
 android.database.sqlite.SQLiteOpenHelper
 android.database.sqlite.SQLiteProgram
 android.database.sqlite.SQLiteQuery
 android.database.sqlite.SQLiteQueryBuilder
+android.database.sqlite.SQLiteSession
+android.database.sqlite.SQLiteSession$Transaction
 android.database.sqlite.SQLiteStatement
+android.database.sqlite.SQLiteStatementInfo
 android.ddm.DdmHandleAppName
 android.ddm.DdmHandleExit
 android.ddm.DdmHandleHeap
@@ -335,6 +383,7 @@
 android.ddm.DdmHandleThread
 android.ddm.DdmRegister
 android.debug.JNITest
+android.drm.DrmManagerClient
 android.emoji.EmojiFactory
 android.graphics.AvoidXfermode
 android.graphics.Bitmap
@@ -361,6 +410,7 @@
 android.graphics.DiscretePathEffect
 android.graphics.DrawFilter
 android.graphics.EmbossMaskFilter
+android.graphics.Insets
 android.graphics.Interpolator
 android.graphics.Interpolator$Result
 android.graphics.LayerRasterizer
@@ -368,6 +418,7 @@
 android.graphics.LinearGradient
 android.graphics.MaskFilter
 android.graphics.Matrix
+android.graphics.Matrix$1
 android.graphics.Matrix$ScaleToFit
 android.graphics.Movie
 android.graphics.NinePatch
@@ -408,6 +459,7 @@
 android.graphics.Shader$TileMode
 android.graphics.SumPathEffect
 android.graphics.SurfaceTexture
+android.graphics.SurfaceTexture$OnFrameAvailableListener
 android.graphics.SweepGradient
 android.graphics.TableMaskFilter
 android.graphics.TemporaryBuffer
@@ -427,12 +479,11 @@
 android.graphics.drawable.ColorDrawable$ColorState
 android.graphics.drawable.Drawable
 android.graphics.drawable.Drawable$Callback
-android.graphics.drawable.Drawable$Callback2
 android.graphics.drawable.Drawable$ConstantState
 android.graphics.drawable.DrawableContainer
-android.graphics.drawable.DrawableContainer$1
 android.graphics.drawable.DrawableContainer$DrawableContainerState
 android.graphics.drawable.GradientDrawable
+android.graphics.drawable.GradientDrawable$1
 android.graphics.drawable.GradientDrawable$GradientState
 android.graphics.drawable.GradientDrawable$Orientation
 android.graphics.drawable.LayerDrawable
@@ -458,6 +509,23 @@
 android.hardware.Camera$Face
 android.hardware.Camera$Parameters
 android.hardware.SensorManager
+android.hardware.SerialPort
+android.hardware.SystemSensorManager
+android.hardware.display.DisplayManager
+android.hardware.display.DisplayManagerGlobal
+android.hardware.display.DisplayManagerGlobal$DisplayManagerCallback
+android.hardware.display.IDisplayManager
+android.hardware.display.IDisplayManager$Stub
+android.hardware.display.IDisplayManager$Stub$Proxy
+android.hardware.display.IDisplayManagerCallback
+android.hardware.display.IDisplayManagerCallback$Stub
+android.hardware.input.IInputDevicesChangedListener
+android.hardware.input.IInputDevicesChangedListener$Stub
+android.hardware.input.IInputManager
+android.hardware.input.IInputManager$Stub
+android.hardware.input.IInputManager$Stub$Proxy
+android.hardware.input.InputManager
+android.hardware.input.InputManager$InputDevicesChangedListener
 android.hardware.usb.UsbDevice
 android.hardware.usb.UsbDeviceConnection
 android.hardware.usb.UsbRequest
@@ -495,7 +563,10 @@
 android.media.MediaPlayer$OnErrorListener
 android.media.MediaPlayer$OnInfoListener
 android.media.MediaPlayer$OnPreparedListener
+android.media.MediaPlayer$OnSeekCompleteListener
+android.media.MediaRecorder
 android.media.MediaScanner
+android.media.RemoteDisplay
 android.media.ToneGenerator
 android.net.ConnectivityManager
 android.net.Credentials
@@ -534,9 +605,12 @@
 android.net.WebAddress
 android.net.http.AndroidHttpClient
 android.net.http.AndroidHttpClient$1
+android.net.wifi.IWifiManager
+android.net.wifi.IWifiManager$Stub
 android.net.http.AndroidHttpClient$2
 android.net.http.AndroidHttpClient$CurlLogger
 android.net.wifi.WifiNative
+android.opengl.EGL14
 android.nfc.NdefMessage
 android.nfc.NdefRecord
 android.opengl.ETC1
@@ -546,6 +620,7 @@
 android.opengl.GLES11Ext
 android.opengl.GLES20
 android.opengl.GLUtils
+android.opengl.ManagedEGLContext
 android.opengl.Matrix
 android.opengl.Visibility
 android.os.AsyncTask$1
@@ -557,24 +632,27 @@
 android.os.AsyncTask$SerialExecutor$1
 android.os.AsyncTask$Status
 android.os.AsyncTask$WorkerRunnable
-android.os.BatteryStats
 android.os.Binder
 android.os.BinderProxy
 android.os.Build
 android.os.Build$VERSION
 android.os.Bundle
 android.os.Bundle$1
+android.os.CancellationSignal
+android.os.CancellationSignal$OnCancelListener
 android.os.Debug
 android.os.Debug$MemoryInfo
 android.os.Debug$MemoryInfo$1
 android.os.Environment
+android.os.Environment$UserEnvironment
 android.os.FileObserver$ObserverThread
 android.os.FileUtils
-android.os.FileUtils$FileStatus
 android.os.Handler
 android.os.HandlerThread
 android.os.IBinder
 android.os.IBinder$DeathRecipient
+android.os.ICancellationSignal
+android.os.ICancellationSignal$Stub
 android.os.IInterface
 android.os.IPowerManager
 android.os.IPowerManager$Stub
@@ -599,6 +677,8 @@
 android.os.PowerManager$WakeLock
 android.os.PowerManager$WakeLock$1
 android.os.Process
+android.os.RemoteException
+android.os.SELinux
 android.os.ServiceManager
 android.os.ServiceManagerNative
 android.os.ServiceManagerProxy
@@ -629,13 +709,28 @@
 android.os.StrictMode$VmPolicy$Builder
 android.os.SystemClock
 android.os.SystemProperties
+android.os.Trace
+android.os.Trace$1
 android.os.UEventObserver
+android.os.UserHandle
+android.os.UserHandle$1
 android.os.Vibrator
 android.os.storage.IMountService
 android.os.storage.IMountService$Stub
 android.os.storage.IMountService$Stub$Proxy
+android.os.storage.StorageManager
+android.os.storage.StorageVolume
+android.os.storage.StorageVolume$1
+android.preference.GenericInflater$Parent
+android.preference.OnDependencyChangeListener
+android.preference.Preference
 android.preference.PreferenceActivity
+android.preference.PreferenceFragment
+android.preference.PreferenceFragment$OnPreferenceStartFragmentCallback
+android.preference.PreferenceGroup
 android.preference.PreferenceManager
+android.preference.PreferenceManager$OnPreferenceTreeClickListener
+android.preference.PreferenceScreen
 android.provider.BaseColumns
 android.provider.Settings$NameValueCache
 android.provider.Settings$NameValueTable
@@ -674,6 +769,7 @@
 android.text.Selection$END
 android.text.Selection$PositionIterator
 android.text.Selection$START
+android.text.SpanSet
 android.text.SpanWatcher
 android.text.Spannable
 android.text.Spannable$Factory
@@ -691,6 +787,7 @@
 android.text.TextDirectionHeuristics$TextDirectionAlgorithm
 android.text.TextDirectionHeuristics$TextDirectionHeuristicImpl
 android.text.TextDirectionHeuristics$TextDirectionHeuristicInternal
+android.text.TextDirectionHeuristics$TextDirectionHeuristicLocale
 android.text.TextDirectionHeuristics$TriState
 android.text.TextLine
 android.text.TextPaint
@@ -699,6 +796,7 @@
 android.text.TextUtils$EllipsizeCallback
 android.text.TextUtils$TruncateAt
 android.text.TextWatcher
+android.text.format.DateFormat
 android.text.format.Time
 android.text.method.AllCapsTransformationMethod
 android.text.method.ArrowKeyMovementMethod
@@ -707,6 +805,7 @@
 android.text.method.KeyListener
 android.text.method.MetaKeyKeyListener
 android.text.method.MovementMethod
+android.text.method.PasswordTransformationMethod
 android.text.method.QwertyKeyListener
 android.text.method.ReplacementTransformationMethod
 android.text.method.ReplacementTransformationMethod$ReplacementCharSequence
@@ -719,6 +818,9 @@
 android.text.method.WordIterator
 android.text.style.AlignmentSpan
 android.text.style.CharacterStyle
+android.text.style.DynamicDrawableSpan
+android.text.style.EasyEditSpan
+android.text.style.ImageSpan
 android.text.style.LeadingMarginSpan
 android.text.style.LineBackgroundSpan
 android.text.style.LineHeightSpan
@@ -734,6 +836,8 @@
 android.util.AndroidException
 android.util.AndroidRuntimeException
 android.util.AttributeSet
+android.util.Base64
+android.util.Base64$Coder
 android.util.DisplayMetrics
 android.util.EventLog
 android.util.EventLog$Event
@@ -767,11 +871,23 @@
 android.view.AbsSavedState$2
 android.view.ActionMode
 android.view.ActionMode$Callback
+android.view.ActionProvider$SubUiVisibilityListener
+android.view.Choreographer
+android.view.Choreographer$1
+android.view.Choreographer$2
+android.view.Choreographer$CallbackQueue
+android.view.Choreographer$CallbackRecord
+android.view.Choreographer$FrameDisplayEventReceiver
+android.view.Choreographer$FrameHandler
+android.view.CollapsibleActionView
 android.view.CompatibilityInfoHolder
 android.view.ContextMenu
 android.view.ContextMenu$ContextMenuInfo
 android.view.ContextThemeWrapper
 android.view.Display
+android.view.DisplayEventReceiver
+android.view.DisplayInfo
+android.view.DisplayInfo$1
 android.view.DisplayList
 android.view.FallbackEventHandler
 android.view.FocusFinder
@@ -793,7 +909,10 @@
 android.view.HardwareLayer
 android.view.HardwareRenderer
 android.view.HardwareRenderer$Gl20Renderer
+android.view.HardwareRenderer$Gl20Renderer$1
+android.view.HardwareRenderer$Gl20Renderer$Gl20RendererEglContext
 android.view.HardwareRenderer$GlRenderer
+android.view.HardwareRenderer$GlRenderer$FunctorsRunnable
 android.view.HardwareRenderer$HardwareDrawCallbacks
 android.view.IRotationWatcher
 android.view.IRotationWatcher$Stub
@@ -807,6 +926,8 @@
 android.view.IWindowSession$Stub$Proxy
 android.view.InputChannel
 android.view.InputChannel$1
+android.view.InputDevice
+android.view.InputDevice$1
 android.view.InputEvent
 android.view.InputEvent$1
 android.view.InputEventConsistencyVerifier
@@ -815,6 +936,7 @@
 android.view.InputQueue
 android.view.InputQueue$Callback
 android.view.KeyCharacterMap
+android.view.KeyCharacterMap$1
 android.view.KeyCharacterMap$FallbackAction
 android.view.KeyEvent
 android.view.KeyEvent$1
@@ -834,9 +956,11 @@
 android.view.MotionEvent$PointerProperties
 android.view.PointerIcon
 android.view.PointerIcon$1
+android.view.SubMenu
 android.view.Surface
 android.view.Surface$1
 android.view.Surface$CompatibleCanvas
+android.view.Surface$PhysicalDisplayInfo
 android.view.SurfaceHolder
 android.view.SurfaceHolder$Callback
 android.view.SurfaceHolder$Callback2
@@ -848,13 +972,15 @@
 android.view.SurfaceView$4
 android.view.SurfaceView$MyWindow
 android.view.TextureView
+android.view.TouchDelegate
 android.view.VelocityTracker
 android.view.VelocityTracker$1
+android.view.VelocityTracker$Estimator
 android.view.View
 android.view.View$10
 android.view.View$11
 android.view.View$12
-android.view.View$13
+android.view.View$3
 android.view.View$4
 android.view.View$5
 android.view.View$6
@@ -865,7 +991,9 @@
 android.view.View$AttachInfo$Callbacks
 android.view.View$BaseSavedState
 android.view.View$BaseSavedState$1
+android.view.View$CheckForLongPress
 android.view.View$CheckForTap
+android.view.View$ListenerInfo
 android.view.View$MeasureSpec
 android.view.View$OnClickListener
 android.view.View$OnCreateContextMenuListener
@@ -890,15 +1018,24 @@
 android.view.ViewRootImpl
 android.view.ViewRootImpl$2
 android.view.ViewRootImpl$AccessibilityInteractionConnectionManager
+android.view.ViewRootImpl$ConsumeBatchedInputRunnable
 android.view.ViewRootImpl$InputMethodCallback
+android.view.ViewRootImpl$InvalidateOnAnimationRunnable
+android.view.ViewRootImpl$QueuedInputEvent
 android.view.ViewRootImpl$ResizedInfo
 android.view.ViewRootImpl$RunQueue
 android.view.ViewRootImpl$RunQueue$HandlerAction
 android.view.ViewRootImpl$TrackballAxis
+android.view.ViewRootImpl$TraversalRunnable
+android.view.ViewRootImpl$ViewRootHandler
 android.view.ViewRootImpl$W
+android.view.ViewRootImpl$WindowInputEventReceiver
 android.view.ViewStub
 android.view.ViewTreeObserver
+android.view.ViewTreeObserver$CopyOnWriteArray
+android.view.ViewTreeObserver$CopyOnWriteArray$Access
 android.view.ViewTreeObserver$InternalInsetsInfo
+android.view.ViewTreeObserver$OnGlobalFocusChangeListener
 android.view.ViewTreeObserver$OnGlobalLayoutListener
 android.view.ViewTreeObserver$OnPreDrawListener
 android.view.ViewTreeObserver$OnScrollChangedListener
@@ -910,6 +1047,8 @@
 android.view.WindowManager
 android.view.WindowManager$LayoutParams
 android.view.WindowManager$LayoutParams$1
+android.view.WindowManagerGlobal
+android.view.WindowManagerGlobal$1
 android.view.WindowManagerImpl
 android.view.WindowManagerImpl$CompatModeWrapper
 android.view.accessibility.AccessibilityEvent
@@ -918,6 +1057,7 @@
 android.view.accessibility.AccessibilityManager$1
 android.view.accessibility.AccessibilityManager$AccessibilityStateChangeListener
 android.view.accessibility.AccessibilityManager$MyHandler
+android.view.accessibility.AccessibilityNodeInfo
 android.view.accessibility.AccessibilityRecord
 android.view.accessibility.IAccessibilityManager
 android.view.accessibility.IAccessibilityManager$Stub
@@ -928,6 +1068,9 @@
 android.view.animation.AccelerateInterpolator
 android.view.animation.AlphaAnimation
 android.view.animation.Animation
+android.view.animation.Animation$1
+android.view.animation.Animation$2
+android.view.animation.Animation$3
 android.view.animation.AnimationUtils
 android.view.animation.DecelerateInterpolator
 android.view.animation.Interpolator
@@ -943,13 +1086,46 @@
 android.view.inputmethod.InputConnectionWrapper
 android.view.inputmethod.InputMethodManager
 android.view.inputmethod.InputMethodManager$1
+android.view.inputmethod.InputMethodManager$2
 android.view.inputmethod.InputMethodManager$ControlledInputConnectionWrapper
+android.view.inputmethod.InputMethodManager$FinishedEventCallback
 android.view.inputmethod.InputMethodManager$H
+android.view.inputmethod.InputMethodManager$PendingEvent
+android.webkit.BrowserFrame
+android.webkit.CacheManager
+android.webkit.CookieManager
+android.webkit.CookieManagerClassic
+android.webkit.DeviceMotionAndOrientationManager
+android.webkit.GeolocationPermissions
+android.webkit.GeolocationPermissionsClassic
+android.webkit.HTML5Audio
+android.webkit.HTML5VideoViewProxy
+android.webkit.JWebCoreJavaBridge
+android.webkit.JavascriptInterface
 android.webkit.JniUtil
-android.webkit.PluginManager
-android.webkit.WebTextView
+android.webkit.MockGeolocation
+android.webkit.ViewStateSerializer
+android.webkit.WebBackForwardList
+android.webkit.WebBackForwardListClassic
+android.webkit.WebHistoryItem
+android.webkit.WebHistoryItemClassic
+android.webkit.WebIconDatabase
+android.webkit.WebIconDatabaseClassic
+android.webkit.WebSettings
+android.webkit.WebSettingsClassic
+android.webkit.WebSettingsClassic$AutoFillProfile
+android.webkit.WebStorage
+android.webkit.WebStorageClassic
 android.webkit.WebView
+android.webkit.WebViewClassic
+android.webkit.WebViewClassic$Factory
 android.webkit.WebViewCore
+android.webkit.WebViewFactory
+android.webkit.WebViewFactoryProvider
+android.webkit.WebViewFactoryProvider$Statics
+android.webkit.WebViewProvider
+android.webkit.WebViewProvider$ScrollDelegate
+android.webkit.WebViewProvider$ViewDelegate
 android.widget.AbsListView
 android.widget.AbsListView$1
 android.widget.AbsListView$2
@@ -988,14 +1164,18 @@
 android.widget.CompoundButton
 android.widget.CompoundButton$OnCheckedChangeListener
 android.widget.CursorAdapter
+android.widget.CursorAdapter$ChangeObserver
+android.widget.CursorAdapter$MyDataSetObserver
 android.widget.CursorFilter$CursorFilterClient
 android.widget.EdgeEffect
 android.widget.EditText
+android.widget.Editor
 android.widget.Editor$Blink
 android.widget.Editor$EasyEditSpanController
 android.widget.Editor$InputContentType
 android.widget.Editor$InputMethodState
 android.widget.ExpandableListView
+android.widget.ExpandableListView$SavedState
 android.widget.FastScroller
 android.widget.FastScroller$1
 android.widget.FastScroller$ScrollFade
@@ -1029,6 +1209,7 @@
 android.widget.OverScroller$SplineOverScroller
 android.widget.PopupWindow
 android.widget.PopupWindow$1
+android.widget.PopupWindow$OnDismissListener
 android.widget.ProgressBar
 android.widget.ProgressBar$SavedState
 android.widget.ProgressBar$SavedState$1
@@ -1047,6 +1228,18 @@
 android.widget.ScrollView
 android.widget.Scroller
 android.widget.SearchView
+android.widget.SearchView$1
+android.widget.SearchView$10
+android.widget.SearchView$11
+android.widget.SearchView$2
+android.widget.SearchView$3
+android.widget.SearchView$4
+android.widget.SearchView$5
+android.widget.SearchView$6
+android.widget.SearchView$7
+android.widget.SearchView$8
+android.widget.SearchView$9
+android.widget.SearchView$SearchAutoComplete
 android.widget.Spinner
 android.widget.SpinnerAdapter
 android.widget.StackView
@@ -1074,6 +1267,7 @@
 android.widget.TextView$Drawables
 android.widget.TextView$OnEditorActionListener
 android.widget.TextView$SavedState
+android.widget.TextView$SavedState$1
 android.widget.VideoView
 android.widget.ViewAnimator
 com.android.i18n.phonenumbers.AsYouTypeFormatter
@@ -1103,6 +1297,7 @@
 com.android.internal.os.RuntimeInit$Arguments
 com.android.internal.os.RuntimeInit$UncaughtHandler
 com.android.internal.os.SamplingProfilerIntegration
+com.android.internal.os.SomeArgs
 com.android.internal.os.ZygoteConnection
 com.android.internal.os.ZygoteConnection$Arguments
 com.android.internal.os.ZygoteInit
@@ -1113,6 +1308,7 @@
 com.android.internal.policy.impl.PhoneLayoutInflater
 com.android.internal.policy.impl.PhoneWindow
 com.android.internal.policy.impl.PhoneWindow$1
+com.android.internal.policy.impl.PhoneWindow$2
 com.android.internal.policy.impl.PhoneWindow$ActionMenuPresenterCallback
 com.android.internal.policy.impl.PhoneWindow$DecorView
 com.android.internal.policy.impl.PhoneWindow$DialogMenuCallback
@@ -1130,8 +1326,10 @@
 com.android.internal.telephony.PhoneConstants$State
 com.android.internal.util.ArrayUtils
 com.android.internal.util.FastXmlSerializer
+com.android.internal.util.MemInfoReader
 com.android.internal.util.Preconditions
 com.android.internal.util.XmlUtils
+com.android.internal.view.ActionBarPolicy
 com.android.internal.view.BaseIWindow
 com.android.internal.view.IInputConnectionWrapper
 com.android.internal.view.IInputConnectionWrapper$MyHandler
@@ -1157,6 +1355,8 @@
 com.android.internal.view.menu.ActionMenuPresenter
 com.android.internal.view.menu.ActionMenuPresenter$OverflowMenuButton
 com.android.internal.view.menu.ActionMenuPresenter$PopupPresenterCallback
+com.android.internal.view.menu.ActionMenuPresenter$SavedState
+com.android.internal.view.menu.ActionMenuPresenter$SavedState$1
 com.android.internal.view.menu.ActionMenuView
 com.android.internal.view.menu.ActionMenuView$ActionMenuChildView
 com.android.internal.view.menu.ActionMenuView$LayoutParams
@@ -1173,6 +1373,7 @@
 com.android.internal.widget.AbsActionBarView$VisibilityAnimListener
 com.android.internal.widget.ActionBarContainer
 com.android.internal.widget.ActionBarContextView
+com.android.internal.widget.ActionBarOverlayLayout
 com.android.internal.widget.ActionBarView
 com.android.internal.widget.ActionBarView$1
 com.android.internal.widget.ActionBarView$2
@@ -1183,7 +1384,11 @@
 com.android.internal.widget.ActionBarView$SavedState$1
 com.android.internal.widget.DialogTitle
 com.android.internal.widget.EditableInputConnection
+com.android.internal.widget.ILockSettings
+com.android.internal.widget.ILockSettings$Stub
+com.android.internal.widget.ILockSettings$Stub$Proxy
 com.android.internal.widget.ScrollingTabContainerView
+com.android.org.bouncycastle.asn1.ASN1Boolean
 com.android.org.bouncycastle.asn1.ASN1Choice
 com.android.org.bouncycastle.asn1.ASN1Encodable
 com.android.org.bouncycastle.asn1.ASN1EncodableVector
@@ -1194,37 +1399,36 @@
 com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier
 com.android.org.bouncycastle.asn1.ASN1OctetString
 com.android.org.bouncycastle.asn1.ASN1OctetStringParser
+com.android.org.bouncycastle.asn1.ASN1Primitive
 com.android.org.bouncycastle.asn1.ASN1Sequence
 com.android.org.bouncycastle.asn1.ASN1Set
 com.android.org.bouncycastle.asn1.ASN1StreamParser
 com.android.org.bouncycastle.asn1.ASN1String
 com.android.org.bouncycastle.asn1.ASN1TaggedObject
 com.android.org.bouncycastle.asn1.ASN1TaggedObjectParser
+com.android.org.bouncycastle.asn1.BERTags
 com.android.org.bouncycastle.asn1.DERBitString
 com.android.org.bouncycastle.asn1.DERBoolean
-com.android.org.bouncycastle.asn1.DEREncodable
-com.android.org.bouncycastle.asn1.DEREncodableVector
 com.android.org.bouncycastle.asn1.DERFactory
 com.android.org.bouncycastle.asn1.DERIA5String
 com.android.org.bouncycastle.asn1.DERInteger
 com.android.org.bouncycastle.asn1.DERNull
-com.android.org.bouncycastle.asn1.DERObject
 com.android.org.bouncycastle.asn1.DERObjectIdentifier
 com.android.org.bouncycastle.asn1.DEROctetString
-com.android.org.bouncycastle.asn1.DEROutputStream
 com.android.org.bouncycastle.asn1.DERPrintableString
 com.android.org.bouncycastle.asn1.DERSequence
 com.android.org.bouncycastle.asn1.DERSet
-com.android.org.bouncycastle.asn1.DERString
 com.android.org.bouncycastle.asn1.DERT61String
 com.android.org.bouncycastle.asn1.DERTaggedObject
-com.android.org.bouncycastle.asn1.DERTags
 com.android.org.bouncycastle.asn1.DERUniversalString
+com.android.org.bouncycastle.asn1.DLSequence
+com.android.org.bouncycastle.asn1.DLSet
 com.android.org.bouncycastle.asn1.DefiniteLengthInputStream
 com.android.org.bouncycastle.asn1.InMemoryRepresentable
 com.android.org.bouncycastle.asn1.IndefiniteLengthInputStream
 com.android.org.bouncycastle.asn1.LimitedInputStream
 com.android.org.bouncycastle.asn1.OIDTokenizer
+com.android.org.bouncycastle.asn1.StreamUtil
 com.android.org.bouncycastle.asn1.bc.BCObjectIdentifiers
 com.android.org.bouncycastle.asn1.iana.IANAObjectIdentifiers
 com.android.org.bouncycastle.asn1.nist.NISTObjectIdentifiers
@@ -1232,52 +1436,89 @@
 com.android.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers
 com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier
 com.android.org.bouncycastle.asn1.x509.BasicConstraints
-com.android.org.bouncycastle.asn1.x509.DigestInfo
 com.android.org.bouncycastle.asn1.x509.GeneralName
 com.android.org.bouncycastle.asn1.x509.GeneralNames
-com.android.org.bouncycastle.asn1.x509.RSAPublicKeyStructure
 com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
+com.android.org.bouncycastle.asn1.x509.X509Extension
 com.android.org.bouncycastle.asn1.x509.X509Extensions
 com.android.org.bouncycastle.asn1.x509.X509Name
 com.android.org.bouncycastle.asn1.x509.X509ObjectIdentifiers
 com.android.org.bouncycastle.asn1.x9.X9ObjectIdentifiers
-com.android.org.bouncycastle.crypto.AsymmetricBlockCipher
+com.android.org.bouncycastle.crypto.BlockCipher
+com.android.org.bouncycastle.crypto.BufferedBlockCipher
 com.android.org.bouncycastle.crypto.CipherParameters
 com.android.org.bouncycastle.crypto.Digest
 com.android.org.bouncycastle.crypto.ExtendedDigest
-com.android.org.bouncycastle.crypto.digests.GeneralDigest
-com.android.org.bouncycastle.crypto.digests.SHA1Digest
-com.android.org.bouncycastle.crypto.encodings.PKCS1Encoding
-com.android.org.bouncycastle.crypto.encodings.PKCS1Encoding$1
-com.android.org.bouncycastle.crypto.engines.RSABlindedEngine
-com.android.org.bouncycastle.crypto.engines.RSACoreEngine
-com.android.org.bouncycastle.crypto.params.AsymmetricKeyParameter
+com.android.org.bouncycastle.crypto.digests.OpenSSLDigest
+com.android.org.bouncycastle.crypto.digests.OpenSSLDigest$SHA1
+com.android.org.bouncycastle.crypto.engines.AESFastEngine
+com.android.org.bouncycastle.crypto.paddings.BlockCipherPadding
+com.android.org.bouncycastle.crypto.paddings.PKCS7Padding
+com.android.org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher
+com.android.org.bouncycastle.crypto.params.KeyParameter
 com.android.org.bouncycastle.crypto.params.ParametersWithRandom
-com.android.org.bouncycastle.crypto.params.RSAKeyParameters
-com.android.org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters
-com.android.org.bouncycastle.crypto.util.Pack
+com.android.org.bouncycastle.jcajce.provider.asymmetric.DH$Mappings
+com.android.org.bouncycastle.jcajce.provider.asymmetric.DSA$Mappings
+com.android.org.bouncycastle.jcajce.provider.asymmetric.EC$Mappings
+com.android.org.bouncycastle.jcajce.provider.asymmetric.RSA$Mappings
+com.android.org.bouncycastle.jcajce.provider.asymmetric.X509$Mappings
+com.android.org.bouncycastle.jcajce.provider.asymmetric.dsa.DSAUtil
+com.android.org.bouncycastle.jcajce.provider.asymmetric.dsa.KeyFactorySpi
+com.android.org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi
+com.android.org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi$EC
+com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.KeyFactorySpi
+com.android.org.bouncycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi
+com.android.org.bouncycastle.jcajce.provider.config.ConfigurableProvider
+com.android.org.bouncycastle.jcajce.provider.config.ProviderConfiguration
+com.android.org.bouncycastle.jcajce.provider.config.ProviderConfigurationPermission
+com.android.org.bouncycastle.jcajce.provider.digest.DigestAlgorithmProvider
+com.android.org.bouncycastle.jcajce.provider.digest.MD5
+com.android.org.bouncycastle.jcajce.provider.digest.MD5$Mappings
+com.android.org.bouncycastle.jcajce.provider.digest.SHA1
+com.android.org.bouncycastle.jcajce.provider.digest.SHA1$Mappings
+com.android.org.bouncycastle.jcajce.provider.digest.SHA256
+com.android.org.bouncycastle.jcajce.provider.digest.SHA256$Mappings
+com.android.org.bouncycastle.jcajce.provider.digest.SHA384
+com.android.org.bouncycastle.jcajce.provider.digest.SHA384$Mappings
+com.android.org.bouncycastle.jcajce.provider.digest.SHA512
+com.android.org.bouncycastle.jcajce.provider.digest.SHA512$Mappings
+com.android.org.bouncycastle.jcajce.provider.symmetric.AES
+com.android.org.bouncycastle.jcajce.provider.symmetric.AES$ECB
+com.android.org.bouncycastle.jcajce.provider.symmetric.AES$Mappings
+com.android.org.bouncycastle.jcajce.provider.symmetric.ARC4
+com.android.org.bouncycastle.jcajce.provider.symmetric.ARC4$Mappings
+com.android.org.bouncycastle.jcajce.provider.symmetric.Blowfish
+com.android.org.bouncycastle.jcajce.provider.symmetric.Blowfish$Mappings
+com.android.org.bouncycastle.jcajce.provider.symmetric.DES
+com.android.org.bouncycastle.jcajce.provider.symmetric.DES$Mappings
+com.android.org.bouncycastle.jcajce.provider.symmetric.DESede
+com.android.org.bouncycastle.jcajce.provider.symmetric.DESede$Mappings
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$BufferedGenericBlockCipher
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$GenericBlockCipher
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseWrapCipher
+com.android.org.bouncycastle.jcajce.provider.symmetric.util.PBE
+com.android.org.bouncycastle.jcajce.provider.util.AlgorithmProvider
+com.android.org.bouncycastle.jcajce.provider.util.AsymmetricAlgorithmProvider
+com.android.org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter
 com.android.org.bouncycastle.jce.interfaces.BCKeyStore
-com.android.org.bouncycastle.jce.interfaces.ConfigurableProvider
 com.android.org.bouncycastle.jce.provider.BouncyCastleProvider
 com.android.org.bouncycastle.jce.provider.BouncyCastleProvider$1
+com.android.org.bouncycastle.jce.provider.BouncyCastleProviderConfiguration
+com.android.org.bouncycastle.jce.provider.CertBlacklist
 com.android.org.bouncycastle.jce.provider.CertPathValidatorUtilities
-com.android.org.bouncycastle.jce.provider.JCERSAPublicKey
-com.android.org.bouncycastle.jce.provider.JDKDigestSignature
-com.android.org.bouncycastle.jce.provider.JDKDigestSignature$SHA1WithRSAEncryption
-com.android.org.bouncycastle.jce.provider.JDKKeyFactory
-com.android.org.bouncycastle.jce.provider.JDKKeyFactory$RSA
 com.android.org.bouncycastle.jce.provider.JDKKeyStore
 com.android.org.bouncycastle.jce.provider.PKIXCRLUtil
 com.android.org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi
 com.android.org.bouncycastle.jce.provider.PKIXNameConstraintValidator
 com.android.org.bouncycastle.jce.provider.PKIXPolicyNode
 com.android.org.bouncycastle.jce.provider.RFC3280CertPathUtilities
-com.android.org.bouncycastle.jce.provider.RSAUtil
-com.android.org.bouncycastle.jce.provider.asymmetric.EC$Mappings
-com.android.org.bouncycastle.jce.provider.symmetric.AES$Mappings
-com.android.org.bouncycastle.jce.provider.symmetric.ARC4$Mappings
-com.android.org.bouncycastle.jce.provider.symmetric.Blowfish$Mappings
-com.android.org.bouncycastle.jce.provider.symmetric.DESede$Mappings
+com.android.org.bouncycastle.util.Arrays
+com.android.org.bouncycastle.util.Strings
+com.android.org.bouncycastle.util.encoders.Encoder
+com.android.org.bouncycastle.util.encoders.Hex
+com.android.org.bouncycastle.util.encoders.HexEncoder
 com.android.org.bouncycastle.util.io.Streams
 com.android.org.bouncycastle.x509.ExtendedPKIXParameters
 com.android.server.NetworkManagementSocketTagger
@@ -1318,6 +1559,7 @@
 java.beans.PropertyChangeEvent
 java.beans.PropertyChangeSupport
 java.io.BufferedInputStream
+java.io.BufferedOutputStream
 java.io.BufferedReader
 java.io.ByteArrayInputStream
 java.io.ByteArrayOutputStream
@@ -1329,6 +1571,7 @@
 java.io.DataOutputStream
 java.io.File
 java.io.FileDescriptor
+java.io.FileFilter
 java.io.FileInputStream
 java.io.FileNotFoundException
 java.io.FileOutputStream
@@ -1503,6 +1746,7 @@
 java.net.URLEncoder
 java.net.URLEncoder$1
 java.net.URLStreamHandler
+java.net.UnknownHostException
 java.nio.BaseByteBuffer
 java.nio.Buffer
 java.nio.ByteBuffer
@@ -1514,6 +1758,7 @@
 java.nio.FileChannelImpl
 java.nio.FileChannelImpl$1
 java.nio.HeapByteBuffer
+java.nio.MemoryBlock
 java.nio.NIOAccess
 java.nio.NioUtils
 java.nio.ReadWriteCharArrayBuffer
@@ -1546,6 +1791,7 @@
 java.security.Key
 java.security.KeyFactory
 java.security.KeyFactorySpi
+java.security.KeyPairGeneratorSpi
 java.security.KeyStore
 java.security.KeyStoreSpi
 java.security.MessageDigest
@@ -1584,6 +1830,7 @@
 java.security.interfaces.DSAPublicKey
 java.security.interfaces.RSAKey
 java.security.interfaces.RSAPublicKey
+java.security.spec.AlgorithmParameterSpec
 java.security.spec.EncodedKeySpec
 java.security.spec.KeySpec
 java.security.spec.RSAPublicKeySpec
@@ -1629,10 +1876,15 @@
 java.util.Collections$EmptyMap
 java.util.Collections$EmptySet
 java.util.Collections$SingletonList
+java.util.Collections$SynchronizedCollection
+java.util.Collections$SynchronizedMap
 java.util.Collections$UnmodifiableCollection
 java.util.Collections$UnmodifiableCollection$1
 java.util.Collections$UnmodifiableList
 java.util.Collections$UnmodifiableMap
+java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet
+java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet$1
+java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableMapEntry
 java.util.Collections$UnmodifiableRandomAccessList
 java.util.Collections$UnmodifiableSet
 java.util.ComparableTimSort
@@ -1675,6 +1927,7 @@
 java.util.LinkedHashMap$LinkedEntry
 java.util.LinkedHashMap$LinkedHashIterator
 java.util.LinkedHashMap$ValueIterator
+java.util.LinkedHashSet
 java.util.LinkedList
 java.util.LinkedList$Link
 java.util.LinkedList$LinkIterator
@@ -1693,6 +1946,7 @@
 java.util.SimpleTimeZone
 java.util.SortedMap
 java.util.SortedSet
+java.util.Stack
 java.util.StringTokenizer
 java.util.TimSort
 java.util.TimeZone
@@ -1714,6 +1968,8 @@
 java.util.Vector
 java.util.Vector$1
 java.util.WeakHashMap
+java.util.WeakHashMap$2
+java.util.WeakHashMap$2$1
 java.util.WeakHashMap$Entry
 java.util.WeakHashMap$Entry$Type
 java.util.WeakHashMap$HashIterator
@@ -1738,6 +1994,7 @@
 java.util.concurrent.Executors$FinalizableDelegatedExecutorService
 java.util.concurrent.Future
 java.util.concurrent.FutureTask
+java.util.concurrent.FutureTask$WaitNode
 java.util.concurrent.FutureTask$Sync
 java.util.concurrent.LinkedBlockingQueue
 java.util.concurrent.LinkedBlockingQueue$Node
@@ -1816,6 +2073,13 @@
 java.util.zip.ZipFile$1
 java.util.zip.ZipFile$RAFStream
 java.util.zip.ZipFile$ZipInflaterInputStream
+javax.crypto.Cipher
+javax.crypto.CipherSpi
+javax.crypto.SecretKey
+javax.crypto.interfaces.PBEKey
+javax.crypto.spec.IvParameterSpec
+javax.crypto.spec.PBEParameterSpec
+javax.crypto.spec.SecretKeySpec
 javax.microedition.khronos.egl.EGL
 javax.microedition.khronos.egl.EGL10
 javax.microedition.khronos.egl.EGLConfig
@@ -1865,6 +2129,9 @@
 libcore.io.BlockGuardOs
 libcore.io.BufferIterator
 libcore.io.ErrnoException
+libcore.io.EventLogger
+libcore.io.EventLogger$DefaultReporter
+libcore.io.EventLogger$Reporter
 libcore.io.ForwardingOs
 libcore.io.GaiException
 libcore.io.HeapBufferIterator
@@ -1888,6 +2155,7 @@
 libcore.io.StructStatFs
 libcore.io.StructTimeval
 libcore.io.StructUtsname
+libcore.math.MathUtils
 libcore.net.MimeUtils
 libcore.net.RawSocket
 libcore.net.UriCodec
@@ -1911,6 +2179,7 @@
 org.apache.commons.logging.LogFactory
 org.apache.commons.logging.impl.Jdk14Logger
 org.apache.commons.logging.impl.WeakHashtable
+org.apache.harmony.crypto.internal.NullCipherSpi
 org.apache.harmony.dalvik.NativeTestTarget
 org.apache.harmony.dalvik.ddmc.Chunk
 org.apache.harmony.dalvik.ddmc.ChunkHandler
@@ -1918,11 +2187,6 @@
 org.apache.harmony.lang.annotation.AnnotationFactory
 org.apache.harmony.lang.annotation.AnnotationMember
 org.apache.harmony.luni.internal.util.TimezoneGetter
-org.apache.harmony.luni.util.TwoKeyHashMap
-org.apache.harmony.luni.util.TwoKeyHashMap$Entry
-org.apache.harmony.luni.util.TwoKeyHashMap$EntryIteratorImpl
-org.apache.harmony.luni.util.TwoKeyHashMap$ValueIteratorImpl
-org.apache.harmony.luni.util.TwoKeyHashMap$ValuesCollectionImpl
 org.apache.harmony.security.asn1.ASN1Any
 org.apache.harmony.security.asn1.ASN1BitString
 org.apache.harmony.security.asn1.ASN1BitString$ASN1NamedBitList
@@ -1977,7 +2241,6 @@
 org.apache.harmony.security.provider.cert.X509CertPathImpl$3
 org.apache.harmony.security.provider.crypto.CryptoProvider
 org.apache.harmony.security.provider.crypto.RandomBitsSupplier
-org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl
 org.apache.harmony.security.provider.crypto.SHA1_Data
 org.apache.harmony.security.utils.AlgNameMapper
 org.apache.harmony.security.utils.ObjectIdentifier
@@ -2027,6 +2290,7 @@
 org.apache.harmony.xnet.provider.jsse.AbstractSessionContext
 org.apache.harmony.xnet.provider.jsse.AbstractSessionContext$1
 org.apache.harmony.xnet.provider.jsse.ByteArray
+org.apache.harmony.xnet.provider.jsse.CertPinManager
 org.apache.harmony.xnet.provider.jsse.ClientSessionContext
 org.apache.harmony.xnet.provider.jsse.ClientSessionContext$HostAndPort
 org.apache.harmony.xnet.provider.jsse.DefaultSSLContextImpl
@@ -2037,24 +2301,38 @@
 org.apache.harmony.xnet.provider.jsse.KeyManagerImpl
 org.apache.harmony.xnet.provider.jsse.NativeCrypto
 org.apache.harmony.xnet.provider.jsse.NativeCrypto$SSLHandshakeCallbacks
+org.apache.harmony.xnet.provider.jsse.OpenSSLCipherRSA
+org.apache.harmony.xnet.provider.jsse.OpenSSLCipherRSA$PKCS1
+org.apache.harmony.xnet.provider.jsse.OpenSSLCipherRSA$Raw
 org.apache.harmony.xnet.provider.jsse.OpenSSLContextImpl
+org.apache.harmony.xnet.provider.jsse.OpenSSLDSAKeyPairGenerator
+org.apache.harmony.xnet.provider.jsse.OpenSSLDSAPublicKey
+org.apache.harmony.xnet.provider.jsse.OpenSSLKey
 org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK
 org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$MD5
 org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA1
+org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA512
 org.apache.harmony.xnet.provider.jsse.OpenSSLProvider
+org.apache.harmony.xnet.provider.jsse.OpenSSLRSAKeyFactory
+org.apache.harmony.xnet.provider.jsse.OpenSSLRSAKeyPairGenerator
+org.apache.harmony.xnet.provider.jsse.OpenSSLRSAPublicKey
+org.apache.harmony.xnet.provider.jsse.OpenSSLRandom
 org.apache.harmony.xnet.provider.jsse.OpenSSLSessionImpl
 org.apache.harmony.xnet.provider.jsse.OpenSSLSignature
+org.apache.harmony.xnet.provider.jsse.OpenSSLSignature$EngineType
 org.apache.harmony.xnet.provider.jsse.OpenSSLSignature$MD5RSA
 org.apache.harmony.xnet.provider.jsse.OpenSSLSignature$SHA1DSA
 org.apache.harmony.xnet.provider.jsse.OpenSSLSignature$SHA1RSA
 org.apache.harmony.xnet.provider.jsse.OpenSSLSignature$SHA256RSA
 org.apache.harmony.xnet.provider.jsse.OpenSSLSignature$SHA384RSA
 org.apache.harmony.xnet.provider.jsse.OpenSSLSignature$SHA512RSA
+org.apache.harmony.xnet.provider.jsse.OpenSSLSignatureRawRSA
 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketFactoryImpl
 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl
 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream
 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLOutputStream
 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImplWrapper
+org.apache.harmony.xnet.provider.jsse.PinListEntry
 org.apache.harmony.xnet.provider.jsse.ProtocolVersion
 org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache
 org.apache.harmony.xnet.provider.jsse.SSLContextImpl
@@ -2277,14 +2555,6 @@
 org.kxml2.io.KXmlParser
 org.kxml2.io.KXmlParser$ValueContext
 org.xml.sax.Attributes
-org.xml.sax.ContentHandler
-org.xml.sax.DTDHandler
-org.xml.sax.EntityResolver
-org.xml.sax.ErrorHandler
-org.xml.sax.InputSource
-org.xml.sax.Locator
-org.xml.sax.XMLReader
-org.xml.sax.helpers.DefaultHandler
 org.xmlpull.v1.XmlPullParser
 org.xmlpull.v1.XmlSerializer
 sun.misc.Unsafe
diff --git a/services/common_time/Android.mk b/services/common_time/Android.mk
index e534d49..0606ab4 100644
--- a/services/common_time/Android.mk
+++ b/services/common_time/Android.mk
@@ -14,7 +14,8 @@
     common_time_server_packets.cpp \
     clock_recovery.cpp \
     common_clock.cpp \
-    main.cpp
+    main.cpp \
+    utils.cpp
 
 # Uncomment to enable vesbose logging and debug service.
 #TIME_SERVICE_DEBUG=true
diff --git a/services/common_time/clock_recovery.cpp b/services/common_time/clock_recovery.cpp
index 6c98d32..3a7c70c 100644
--- a/services/common_time/clock_recovery.cpp
+++ b/services/common_time/clock_recovery.cpp
@@ -53,6 +53,21 @@
 
     local_clock_can_slew_ = local_clock_->initCheck() &&
                            (local_clock_->setLocalSlew(0) == OK);
+    tgt_correction_ = 0;
+    cur_correction_ = 0;
+
+    // Precompute the max rate at which we are allowed to change the VCXO
+    // control.
+    uint64_t N = 0x10000ull * 1000ull;
+    uint64_t D = local_clock_->getLocalFreq() * kMinFullRangeSlewChange_mSec;
+    LinearTransform::reduce(&N, &D);
+    while ((N > INT32_MAX) || (D > UINT32_MAX)) {
+        N >>= 1;
+        D >>= 1;
+        LinearTransform::reduce(&N, &D);
+    }
+    time_to_cur_slew_.a_to_b_numer = static_cast<int32_t>(N);
+    time_to_cur_slew_.a_to_b_denom = static_cast<uint32_t>(D);
 
     reset(true, true);
 
@@ -85,6 +100,9 @@
 const int64_t ClockRecoveryLoop::control_thresh_ = 10000;
 const float ClockRecoveryLoop::COmin = -100.0f;
 const float ClockRecoveryLoop::COmax = 100.0f;
+const uint32_t ClockRecoveryLoop::kMinFullRangeSlewChange_mSec = 300;
+const int ClockRecoveryLoop::kSlewChangeStepPeriod_mSec = 10;
+
 
 void ClockRecoveryLoop::reset(bool position, bool frequency) {
     Mutex::Autolock lock(&lock_);
@@ -144,7 +162,7 @@
     int64_t observed_common;
     int64_t delta;
     float delta_f, dCO;
-    int32_t correction_cur;
+    int32_t tgt_correction;
 
     if (OK != common_clock_->localToCommon(local_time, &observed_common)) {
         // Since we just checked to make certain that this conversion was valid,
@@ -207,6 +225,9 @@
     if (current_point == min_rtt || rtt < control_thresh_) {
         delta_f = delta = nominal_common_time - observed_common;
 
+        last_error_est_valid_ = true;
+        last_error_est_usec_ = delta;
+
         // Compute the error then clamp to the panic threshold.  If we ever
         // exceed this amt of error, its time to panic and reset the system.
         // Given that the error in the measurement of the error could be as
@@ -240,7 +261,6 @@
 
     // Save error terms for later.
     last_delta_f_ = delta_f;
-    last_delta_ = delta;
 
     // Clamp CO to +/- 100ppm.
     if (CO < COmin)
@@ -254,23 +274,20 @@
 
     // Convert PPM to 16-bit int range. Add some guard band (-0.01) so we
     // don't get fp weirdness.
-    correction_cur = CO * 327.66;
+    tgt_correction = CO * 327.66;
 
     // If there was a change in the amt of correction to use, update the
     // system.
-    if (correction_cur_ != correction_cur) {
-        correction_cur_ = correction_cur;
-        applySlew();
-    }
+    setTargetCorrection_l(tgt_correction);
 
-    LOG_TS("clock_loop %lld %f %f %f %d\n", raw_delta, delta_f, CO, CObias, correction_cur);
+    LOG_TS("clock_loop %lld %f %f %f %d\n", raw_delta, delta_f, CO, CObias, tgt_correction);
 
 #ifdef TIME_SERVICE_DEBUG
     diag_thread_->pushDisciplineEvent(
             local_time,
             observed_common,
             nominal_common_time,
-            correction_cur,
+            tgt_correction,
             rtt);
 #endif
 
@@ -280,8 +297,8 @@
 int32_t ClockRecoveryLoop::getLastErrorEstimate() {
     Mutex::Autolock lock(&lock_);
 
-    if (last_delta_valid_)
-        return last_delta_;
+    if (last_error_est_valid_)
+        return last_error_est_usec_;
     else
         return ICommonClock::kErrorEstimateUnknown;
 }
@@ -295,27 +312,112 @@
     }
 
     if (frequency) {
-        last_delta_valid_ = false;
-        last_delta_ = 0;
+        last_error_est_valid_ = false;
+        last_error_est_usec_ = 0;
         last_delta_f_ = 0.0;
-        correction_cur_ = 0x0;
         CO = 0.0f;
         lastCObias = CObias = 0.0f;
-        applySlew();
+        setTargetCorrection_l(0);
+        applySlew_l();
     }
 
     filter_wr_   = 0;
     filter_full_ = false;
 }
 
-void ClockRecoveryLoop::applySlew() {
+void ClockRecoveryLoop::setTargetCorrection_l(int32_t tgt) {
+    // When we make a change to the slew rate, we need to be careful to not
+    // change it too quickly as it can anger some HDMI sinks out there, notably
+    // some Sony panels from the 2010-2011 timeframe.  From experimenting with
+    // some of these sinks, it seems like swinging from one end of the range to
+    // another in less that 190mSec or so can start to cause trouble.  Adding in
+    // a hefty margin, we limit the system to a full range sweep in no less than
+    // 300mSec.
+    if (tgt_correction_ != tgt) {
+        int64_t now = local_clock_->getLocalTime();
+        status_t res;
+
+        tgt_correction_ = tgt;
+
+        // Set up the transformation to figure out what the slew should be at
+        // any given point in time in the future.
+        time_to_cur_slew_.a_zero = now;
+        time_to_cur_slew_.b_zero = cur_correction_;
+
+        // Make sure the sign of the slope is headed in the proper direction.
+        bool needs_increase = (cur_correction_ < tgt_correction_);
+        bool is_increasing  = (time_to_cur_slew_.a_to_b_numer > 0);
+        if (( needs_increase && !is_increasing) ||
+            (!needs_increase &&  is_increasing)) {
+            time_to_cur_slew_.a_to_b_numer = -time_to_cur_slew_.a_to_b_numer;
+        }
+
+        // Finally, figure out when the change will be finished and start the
+        // slew operation.
+        time_to_cur_slew_.doReverseTransform(tgt_correction_,
+                                             &slew_change_end_time_);
+
+        applySlew_l();
+    }
+}
+
+bool ClockRecoveryLoop::applySlew_l() {
+    bool ret = true;
+
+    // If cur == tgt, there is no ongoing sleq rate change and we are already
+    // finished.
+    if (cur_correction_ == tgt_correction_)
+        goto bailout;
+
     if (local_clock_can_slew_) {
-        local_clock_->setLocalSlew(correction_cur_);
+        int64_t now = local_clock_->getLocalTime();
+        int64_t tmp;
+
+        if (now >= slew_change_end_time_) {
+            cur_correction_ = tgt_correction_;
+            next_slew_change_timeout_.setTimeout(-1);
+        } else {
+            time_to_cur_slew_.doForwardTransform(now, &tmp);
+
+            if (tmp > INT16_MAX)
+                cur_correction_ = INT16_MAX;
+            else if (tmp < INT16_MIN)
+                cur_correction_ = INT16_MIN;
+            else
+                cur_correction_ = static_cast<int16_t>(tmp);
+
+            next_slew_change_timeout_.setTimeout(kSlewChangeStepPeriod_mSec);
+            ret = false;
+        }
+
+        local_clock_->setLocalSlew(cur_correction_);
     } else {
+        // Since we are not actually changing the rate of a HW clock, we don't
+        // need to worry to much about changing the slew rate so fast that we
+        // anger any downstream HDMI devices.
+        cur_correction_ = tgt_correction_;
+        next_slew_change_timeout_.setTimeout(-1);
+
         // The SW clock recovery implemented by the common clock class expects
         // values expressed in PPM. CO is in ppm.
         common_clock_->setSlew(local_clock_->getLocalTime(), CO);
     }
+
+bailout:
+    return ret;
+}
+
+int ClockRecoveryLoop::applyRateLimitedSlew() {
+    Mutex::Autolock lock(&lock_);
+
+    int ret = next_slew_change_timeout_.msecTillTimeout();
+    if (!ret) {
+        if (applySlew_l())
+            next_slew_change_timeout_.setTimeout(-1);
+        ret = next_slew_change_timeout_.msecTillTimeout();
+    }
+
+    return ret;
 }
 
 }  // namespace android
diff --git a/services/common_time/clock_recovery.h b/services/common_time/clock_recovery.h
index b7362be..b6c87ff 100644
--- a/services/common_time/clock_recovery.h
+++ b/services/common_time/clock_recovery.h
@@ -26,6 +26,8 @@
 #include "diag_thread.h"
 #endif
 
+#include "utils.h"
+
 namespace android {
 
 class CommonClock;
@@ -42,6 +44,11 @@
                              int64_t data_point_rtt);
     int32_t getLastErrorEstimate();
 
+    // Applies the next step in any ongoing slew change operation.  Returns a
+    // timeout suitable for use with poll/select indicating the number of mSec
+    // until the next change should be applied.
+    int applyRateLimitedSlew();
+
   private:
 
     // Tuned using the "Good Gain" method.
@@ -87,7 +94,8 @@
     static uint32_t findMinRTTNdx(DisciplineDataPoint* data, uint32_t count);
 
     void reset_l(bool position, bool frequency);
-    void applySlew();
+    void setTargetCorrection_l(int32_t tgt);
+    bool applySlew_l();
 
     // The local clock HW abstraction we use as the basis for common time.
     LocalClock* local_clock_;
@@ -100,11 +108,15 @@
 
     // parameters maintained while running and reset during a reset
     // of the frequency correction.
-    bool    last_delta_valid_;
-    int32_t last_delta_;
+    bool    last_error_est_valid_;
+    int32_t last_error_est_usec_;
     float last_delta_f_;
     int32_t integrated_error_;
-    int32_t correction_cur_;
+    int32_t tgt_correction_;
+    int32_t cur_correction_;
+    LinearTransform time_to_cur_slew_;
+    int64_t slew_change_end_time_;
+    Timeout next_slew_change_timeout_;
 
     // Contoller Output.
     float CO;
@@ -128,6 +140,15 @@
     DisciplineDataPoint startup_filter_data_[kStartupFilterSize];
     uint32_t startup_filter_wr_;
 
+    // Minimum number of milliseconds over which we allow a full range change
+    // (from rail to rail) of the VCXO control signal.  This is the rate
+    // limiting factor which keeps us from changing the clock rate so fast that
+    // we get in trouble with certain HDMI sinks.
+    static const uint32_t kMinFullRangeSlewChange_mSec;
+
+    // How much time (in msec) to wait 
+    static const int kSlewChangeStepPeriod_mSec;
+
 #ifdef TIME_SERVICE_DEBUG
     sp<DiagThread> diag_thread_;
 #endif
diff --git a/services/common_time/common_time_server.cpp b/services/common_time/common_time_server.cpp
index 7a4986b..21e706f 100644
--- a/services/common_time/common_time_server.cpp
+++ b/services/common_time/common_time_server.cpp
@@ -53,9 +53,9 @@
 
 namespace android {
 
-const char*    CommonTimeServer::kDefaultMasterElectionAddr = "239.195.128.88";
-const uint16_t CommonTimeServer::kDefaultMasterElectionPort = 8887;
-const uint64_t CommonTimeServer::kDefaultSyncGroupID = 0;
+const char*    CommonTimeServer::kDefaultMasterElectionAddr = "255.255.255.255";
+const uint16_t CommonTimeServer::kDefaultMasterElectionPort = 8886;
+const uint64_t CommonTimeServer::kDefaultSyncGroupID = 1;
 const uint8_t  CommonTimeServer::kDefaultMasterPriority = 1;
 const uint32_t CommonTimeServer::kDefaultMasterAnnounceIntervalMs = 10000;
 const uint32_t CommonTimeServer::kDefaultSyncRequestIntervalMs = 1000;
@@ -107,6 +107,9 @@
     , mTimelineID(ICommonClock::kInvalidTimelineID)
     , mClockSynced(false)
     , mCommonClockHasClients(false)
+    , mStateChangeLog("Recent State Change Events", 30)
+    , mElectionLog("Recent Master Election Traffic", 30)
+    , mBadPktLog("Recent Bad Packet RX Info", 8)
     , mInitial_WhoIsMasterRequestTimeouts(0)
     , mClient_MasterDeviceID(0)
     , mClient_MasterDevicePriority(0)
@@ -202,9 +205,11 @@
     // run the state machine
     while (!exitPending()) {
         struct pollfd pfds[2];
-        int rc;
+        int rc, timeout;
         int eventCnt = 0;
         int64_t wakeupTime;
+        uint32_t t1, t2;
+        bool needHandleTimeout = false;
 
         // We are always interested in our wakeup FD.
         pfds[eventCnt].fd      = mWakeupThreadFD;
@@ -221,10 +226,14 @@
             eventCnt++;
         }
 
+        t1 = static_cast<uint32_t>(mCurTimeout.msecTillTimeout());
+        t2 = static_cast<uint32_t>(mClockRecovery.applyRateLimitedSlew());
+        timeout = static_cast<int>(t1 < t2 ? t1 : t2);
+
         // Note, we were holding mLock when this function was called.  We
         // release it only while we are blocking and hold it at all other times.
         mLock.unlock();
-        rc          = poll(pfds, eventCnt, mCurTimeout.msecTillTimeout());
+        rc          = poll(pfds, eventCnt, timeout);
         wakeupTime  = mLocalClock.getLocalTime();
         mLock.lock();
 
@@ -238,8 +247,11 @@
             return false;
         }
 
-        if (rc == 0)
-            mCurTimeout.setTimeout(kInfiniteTimeout);
+        if (rc == 0) {
+            needHandleTimeout = !mCurTimeout.msecTillTimeout();
+            if (needHandleTimeout)
+                mCurTimeout.setTimeout(kInfiniteTimeout);
+        }
 
         // Were we woken up on purpose?  If so, clear the eventfd with a read.
         if (pfds[0].revents)
@@ -321,10 +333,11 @@
             // we are in any other state (CLIENT, RONIN or WAIT_FOR_ELECTION),
             // then transition to either INITIAL or MASTER depending on whether
             // or not our timeline is valid.
-            ALOGI("Entering networkless mode interface is %s, "
-                 "shouldAutoDisable = %s",
-                 mBindIfaceValid ? "valid" : "invalid",
-                 shouldAutoDisable() ? "true" : "false");
+            mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+                    "Entering networkless mode interface is %s, "
+                    "shouldAutoDisable = %s",
+                    mBindIfaceValid ? "valid" : "invalid",
+                    shouldAutoDisable() ? "true" : "false");
             if ((mState != ICommonClock::STATE_INITIAL) &&
                 (mState != ICommonClock::STATE_MASTER)) {
                 if (mTimelineID == ICommonClock::kInvalidTimelineID)
@@ -336,9 +349,8 @@
             continue;
         }
 
-        // Did we wakeup with no signalled events across all of our FDs?  If so,
-        // we must have hit our timeout.
-        if (rc == 0) {
+        // Time to handle the timeouts?
+        if (needHandleTimeout) {
             if (!handleTimeout())
                 ALOGE("handleTimeout failed");
             continue;
@@ -407,20 +419,23 @@
 
     sockaddrToString(mMasterElectionEP, true, masterElectionEPStr,
                      sizeof(masterElectionEPStr));
-    ALOGI("Building socket :: bind = %s master election = %s",
-         mBindIface.string(), masterElectionEPStr);
+    mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+                        "Building socket :: bind = %s master election = %s",
+                        mBindIface.string(), masterElectionEPStr);
 
     // TODO: add proper support for IPv6.  Right now, we block IPv6 addresses at
     // the configuration interface level.
     if (AF_INET != mMasterElectionEP.ss_family) {
-        ALOGW("TODO: add proper IPv6 support");
+        mStateChangeLog.log(ANDROID_LOG_WARN, LOG_TAG,
+                            "TODO: add proper IPv6 support");
         goto bailout;
     }
 
     // open a UDP socket for the timeline serivce
     mSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
     if (mSocket < 0) {
-        ALOGE("Failed to create socket (errno = %d)", errno);
+        mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+                            "Failed to create socket (errno = %d)", errno);
         goto bailout;
     }
 
@@ -432,8 +447,9 @@
     rc = setsockopt(mSocket, SOL_SOCKET, SO_BINDTODEVICE,
                     (void *)&ifr, sizeof(ifr));
     if (rc) {
-        ALOGE("Failed to bind socket at to interface %s (errno = %d)",
-              ifr.ifr_name, errno);
+        mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+                            "Failed to bind socket at to interface %s "
+                            "(errno = %d)", ifr.ifr_name, errno);
         goto bailout;
     }
 
@@ -451,8 +467,9 @@
               reinterpret_cast<const sockaddr *>(&bindAddr),
               sizeof(bindAddr));
     if (rc) {
-        ALOGE("Failed to bind socket to port %hu (errno = %d)",
-              ntohs(bindAddr.sin_port), errno);
+        mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+                            "Failed to bind socket to port %hu (errno = %d)",
+                            ntohs(bindAddr.sin_port), errno);
         goto bailout;
     }
 
@@ -475,11 +492,23 @@
         rc = setsockopt(mSocket, IPPROTO_IP, IP_MULTICAST_LOOP,
                         &zero, sizeof(zero));
         if (rc == -1) {
-            ALOGE("Failed to disable multicast loopback (errno = %d)", errno);
+            mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+                                "Failed to disable multicast loopback "
+                                "(errno = %d)", errno);
             goto bailout;
         }
     } else
-    if (ntohl(ipv4_addr->sin_addr.s_addr) != 0xFFFFFFFF) {
+    if (ntohl(ipv4_addr->sin_addr.s_addr) == 0xFFFFFFFF) {
+        // If the master election address is the broadcast address, then enable
+        // the broadcast socket option
+        rc = setsockopt(mSocket, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one));
+        if (rc == -1) {
+            mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+                                "Failed to enable broadcast (errno = %d)",
+                                errno);
+            goto bailout;
+        }
+    } else {
         // If the master election address is neither broadcast, nor multicast,
         // then we are misconfigured.  The config API layer should prevent this
         // from ever happening.
@@ -490,7 +519,8 @@
     // the local subnet)
     rc = setsockopt(mSocket, IPPROTO_IP, IP_TTL, &one, sizeof(one));
     if (rc == -1) {
-        ALOGE("Failed to set TTL to %d (errno = %d)", one, errno);
+        mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+                            "Failed to set TTL to %d (errno = %d)", one, errno);
         goto bailout;
     }
 
@@ -552,6 +582,31 @@
            ((devicePrio1 == devicePrio2) && (deviceID1 > deviceID2)));
 }
 
+static void hexDumpToString(const uint8_t* src, size_t src_len,
+                            char* dst, size_t dst_len) {
+    size_t offset = 0;
+    size_t i;
+
+    for (i = 0; (i < src_len) && (offset < dst_len); ++i) {
+        int res;
+        if (0 == (i % 16)) {
+            res = snprintf(dst + offset, dst_len - offset, "\n%04x :", i);
+            if (res < 0)
+                break;
+            offset += res;
+            if (offset >= dst_len)
+                break;
+        }
+
+        res = snprintf(dst + offset, dst_len - offset, " %02x", src[i]);
+        if (res < 0)
+            break;
+        offset += res;
+    }
+
+    dst[dst_len - 1] = 0;
+}
+
 bool CommonTimeServer::handlePacket() {
     uint8_t buf[256];
     struct sockaddr_storage srcAddr;
@@ -562,14 +617,24 @@
             reinterpret_cast<const sockaddr *>(&srcAddr), &srcAddrLen);
 
     if (recvBytes < 0) {
-        ALOGE("%s:%d recvfrom failed", __PRETTY_FUNCTION__, __LINE__);
+        mBadPktLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+                       "recvfrom failed (res %d, errno %d)",
+                       recvBytes, errno);
         return false;
     }
 
     UniversalTimeServicePacket pkt;
-    recvBytes = pkt.deserializePacket(buf, recvBytes, mSyncGroupID);
-    if (recvBytes < 0)
+    if (pkt.deserializePacket(buf, recvBytes, mSyncGroupID) < 0) {
+        char hex[256];
+        char srcEPStr[64];
+
+        hexDumpToString(buf, static_cast<size_t>(recvBytes), hex, sizeof(hex));
+        sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
+
+        mBadPktLog.log("Failed to parse %d byte packet from %s.%s",
+                       recvBytes, srcEPStr, hex);
         return false;
+    }
 
     bool result;
     switch (pkt.packetType) {
@@ -597,8 +662,13 @@
             break;
 
         default: {
-            ALOGD("%s:%d unknown packet type(%d)",
-                    __PRETTY_FUNCTION__, __LINE__, pkt.packetType);
+            char srcEPStr[64];
+            sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
+
+            mBadPktLog.log(ANDROID_LOG_WARN, LOG_TAG,
+                           "unknown packet type (%d) from %s",
+                           pkt.packetType, srcEPStr);
+
             result = false;
         } break;
     }
@@ -682,6 +752,17 @@
 bool CommonTimeServer::handleWhoIsMasterRequest(
         const WhoIsMasterRequestPacket* request,
         const sockaddr_storage& srcAddr) {
+    // Skip our own messages which come back via broadcast loopback.
+    if (request->senderDeviceID == mDeviceID)
+        return true;
+
+    char srcEPStr[64];
+    sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
+    mElectionLog.log("RXed WhoIs master request while in state %s.  "
+                     "src %s reqTID %016llx ourTID %016llx",
+                     stateToString(mState), srcEPStr,
+                     request->timelineID, mTimelineID);
+
     if (mState == ICommonClock::STATE_MASTER) {
         // is this request related to this master's timeline?
         if (request->timelineID != ICommonClock::kInvalidTimelineID &&
@@ -693,6 +774,13 @@
         pkt.deviceID = mDeviceID;
         pkt.devicePriority = effectivePriority();
 
+        mElectionLog.log("TXing WhoIs master resp to %s while in state %s.  "
+                         "ourTID %016llx ourGID %016llx ourDID %016llx "
+                         "ourPrio %u",
+                         srcEPStr, stateToString(mState),
+                         mTimelineID, mSyncGroupID,
+                         pkt.deviceID, pkt.devicePriority);
+
         uint8_t buf[256];
         ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf));
         if (bufSz < 0)
@@ -744,6 +832,21 @@
 bool CommonTimeServer::handleWhoIsMasterResponse(
         const WhoIsMasterResponsePacket* response,
         const sockaddr_storage& srcAddr) {
+    // Skip our own messages which come back via broadcast loopback.
+    if (response->deviceID == mDeviceID)
+        return true;
+
+    char srcEPStr[64];
+    sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
+    mElectionLog.log("RXed WhoIs master response while in state %s.  "
+                     "src %s respTID %016llx respDID %016llx respPrio %u "
+                     "ourTID %016llx",
+                     stateToString(mState), srcEPStr,
+                     response->timelineID,
+                     response->deviceID,
+                     static_cast<uint32_t>(response->devicePriority),
+                     mTimelineID);
+
     if (mState == ICommonClock::STATE_INITIAL || mState == ICommonClock::STATE_RONIN) {
         return becomeClient(srcAddr,
                             response->deviceID,
@@ -900,6 +1003,18 @@
     uint8_t  newDevicePrio = packet->devicePriority;
     uint64_t newTimelineID = packet->timelineID;
 
+    // Skip our own messages which come back via broadcast loopback.
+    if (newDeviceID == mDeviceID)
+        return true;
+
+    char srcEPStr[64];
+    sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
+    mElectionLog.log("RXed master announcement while in state %s.  "
+                     "src %s srcDevID %lld srcPrio %u srcTID %016llx",
+                     stateToString(mState), srcEPStr,
+                     newDeviceID, static_cast<uint32_t>(newDevicePrio),
+                     newTimelineID);
+
     if (mState == ICommonClock::STATE_INITIAL ||
         mState == ICommonClock::STATE_RONIN ||
         mState == ICommonClock::STATE_WAIT_FOR_ELECTION) {
@@ -956,6 +1071,15 @@
     uint8_t buf[256];
     ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf));
     if (bufSz >= 0) {
+        char dstEPStr[64];
+        sockaddrToString(mMasterElectionEP, true, dstEPStr, sizeof(dstEPStr));
+        mElectionLog.log("TXing WhoIs master request to %s while in state %s.  "
+                         "ourTID %016llx ourGID %016llx ourDID %016llx "
+                         "ourPrio %u",
+                         dstEPStr, stateToString(mState),
+                         mTimelineID, mSyncGroupID,
+                         pkt.senderDeviceID, pkt.senderDevicePriority);
+
         ssize_t sendBytes = sendto(
                 mSocket, buf, bufSz, 0,
                 reinterpret_cast<const sockaddr *>(&mMasterElectionEP),
@@ -1032,6 +1156,15 @@
     uint8_t buf[256];
     ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf));
     if (bufSz >= 0) {
+        char dstEPStr[64];
+        sockaddrToString(mMasterElectionEP, true, dstEPStr, sizeof(dstEPStr));
+        mElectionLog.log("TXing Master announcement to %s while in state %s.  "
+                         "ourTID %016llx ourGID %016llx ourDID %016llx "
+                         "ourPrio %u",
+                         dstEPStr, stateToString(mState),
+                         mTimelineID, mSyncGroupID,
+                         pkt.deviceID, pkt.devicePriority);
+
         ssize_t sendBytes = sendto(
                 mSocket, buf, bufSz, 0,
                 reinterpret_cast<const sockaddr *>(&mMasterElectionEP),
@@ -1054,15 +1187,16 @@
     sockaddrToString(masterEP, true, newEPStr, sizeof(newEPStr));
     sockaddrToString(mMasterEP, mMasterEPValid, oldEPStr, sizeof(oldEPStr));
 
-    ALOGI("%s --> CLIENT (%s) :%s"
-         " OldMaster: %02x-%014llx::%016llx::%s"
-         " NewMaster: %02x-%014llx::%016llx::%s",
-         stateToString(mState), cause,
-         (mTimelineID != timelineID) ? " (new timeline)" : "",
-         mClient_MasterDevicePriority, mClient_MasterDeviceID,
-         mTimelineID, oldEPStr,
-         masterDevicePriority, masterDeviceID,
-         timelineID, newEPStr);
+    mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+            "%s --> CLIENT (%s) :%s"
+            " OldMaster: %02x-%014llx::%016llx::%s"
+            " NewMaster: %02x-%014llx::%016llx::%s",
+            stateToString(mState), cause,
+            (mTimelineID != timelineID) ? " (new timeline)" : "",
+            mClient_MasterDevicePriority, mClient_MasterDeviceID,
+            mTimelineID, oldEPStr,
+            masterDevicePriority, masterDeviceID,
+            timelineID, newEPStr);
 
     if (mTimelineID != timelineID) {
         // start following a new timeline
@@ -1115,11 +1249,12 @@
         notifyClockSync();
     }
 
-    ALOGI("%s --> MASTER (%s) : %s timeline %016llx",
-         stateToString(mState), cause,
-         (oldTimelineID == mTimelineID) ? "taking ownership of"
-                                        : "creating new",
-         mTimelineID);
+    mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+            "%s --> MASTER (%s) : %s timeline %016llx",
+            stateToString(mState), cause,
+            (oldTimelineID == mTimelineID) ? "taking ownership of"
+                                           : "creating new",
+            mTimelineID);
 
     memset(&mMasterEP, 0, sizeof(mMasterEP));
     mMasterEPValid = false;
@@ -1148,7 +1283,8 @@
     mMasterEPValid = false;
 
     if (mCommonClock.isValid()) {
-        ALOGI("%s --> RONIN (%s) : lost track of previously valid timeline "
+        mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+             "%s --> RONIN (%s) : lost track of previously valid timeline "
              "%02x-%014llx::%016llx::%s (%d TXed %d RXed %d RXExpired)",
              stateToString(mState), cause,
              mClient_MasterDevicePriority, mClient_MasterDeviceID,
@@ -1161,7 +1297,8 @@
         setState(ICommonClock::STATE_RONIN);
         return sendWhoIsMasterRequest();
     } else {
-        ALOGI("%s --> INITIAL (%s) : never synced timeline "
+        mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+             "%s --> INITIAL (%s) : never synced timeline "
              "%02x-%014llx::%016llx::%s (%d TXed %d RXed %d RXExpired)",
              stateToString(mState), cause,
              mClient_MasterDevicePriority, mClient_MasterDeviceID,
@@ -1175,7 +1312,8 @@
 }
 
 bool CommonTimeServer::becomeWaitForElection(const char* cause) {
-    ALOGI("%s --> WAIT_FOR_ELECTION (%s) : dropping out of election,"
+    mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+         "%s --> WAIT_FOR_ELECTION (%s) : dropping out of election,"
          " waiting %d mSec for completion.",
          stateToString(mState), cause, kWaitForElection_TimeoutMs);
 
@@ -1185,7 +1323,9 @@
 }
 
 bool CommonTimeServer::becomeInitial(const char* cause) {
-    ALOGI("Entering INITIAL (%s), total reset.", cause);
+    mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+                        "Entering INITIAL (%s), total reset.",
+                        cause);
 
     setState(ICommonClock::STATE_INITIAL);
 
@@ -1326,29 +1466,6 @@
     }
 }
 
-void CommonTimeServer::TimeoutHelper::setTimeout(int msec) {
-    mTimeoutValid = (msec >= 0);
-    if (mTimeoutValid)
-        mEndTime = systemTime() +
-                   (static_cast<nsecs_t>(msec) * 1000000);
-}
-
-int CommonTimeServer::TimeoutHelper::msecTillTimeout() {
-    if (!mTimeoutValid)
-        return kInfiniteTimeout;
-
-    nsecs_t now = systemTime();
-    if (now >= mEndTime)
-        return 0;
-
-    uint64_t deltaMsec = (((mEndTime - now) + 999999) / 1000000);
-
-    if (deltaMsec > static_cast<uint64_t>(MAX_INT))
-        return MAX_INT;
-
-    return static_cast<int>(deltaMsec);
-}
-
 bool CommonTimeServer::shouldPanicNotGettingGoodData() {
     if (mClient_FirstSyncTX) {
         int64_t now = mLocalClock.getLocalTime();
diff --git a/services/common_time/common_time_server.h b/services/common_time/common_time_server.h
index 89bca64..6e18050 100644
--- a/services/common_time/common_time_server.h
+++ b/services/common_time/common_time_server.h
@@ -28,6 +28,7 @@
 #include "clock_recovery.h"
 #include "common_clock.h"
 #include "common_time_server_packets.h"
+#include "utils.h"
 
 #define RTT_LOG_SIZE 30
 
@@ -104,18 +105,6 @@
         int64_t rxTimes[RTT_LOG_SIZE];
     };
 
-    class TimeoutHelper {
-      public:
-        TimeoutHelper() : mTimeoutValid(false) { }
-
-        void setTimeout(int msec);
-        int msecTillTimeout();
-
-      private:
-        bool        mTimeoutValid;
-        nsecs_t     mEndTime;
-    };
-
     bool threadLoop();
 
     bool runStateMachine_l();
@@ -194,7 +183,7 @@
     bool shouldPanicNotGettingGoodData();
 
     // Helper to keep track of the state machine's current timeout
-    TimeoutHelper mCurTimeout;
+    Timeout mCurTimeout;
 
     // common clock, local clock abstraction, and clock recovery loop
     CommonClock mCommonClock;
@@ -249,6 +238,11 @@
     // interface AND currently active common clock clients.
     bool mCommonClockHasClients;
 
+    // Internal logs used for dumpsys.
+    LogRing                 mStateChangeLog;
+    LogRing                 mElectionLog;
+    LogRing                 mBadPktLog;
+
     // Configuration info
     struct sockaddr_storage mMasterElectionEP;          // Endpoint over which we conduct master election
     String8                 mBindIface;                 // Endpoint for the service to bind to.
diff --git a/services/common_time/common_time_server_api.cpp b/services/common_time/common_time_server_api.cpp
index fb8c261..e157071 100644
--- a/services/common_time/common_time_server_api.cpp
+++ b/services/common_time/common_time_server_api.cpp
@@ -354,6 +354,9 @@
 
         dump_printf("Active Clients : %u\n", activeClients);
         mClient_PacketRTTLog.dumpLog(fd, mCommonClock);
+        mStateChangeLog.dumpLog(fd);
+        mElectionLog.dumpLog(fd);
+        mBadPktLog.dumpLog(fd);
     }
 
     return NO_ERROR;
diff --git a/services/common_time/utils.cpp b/services/common_time/utils.cpp
new file mode 100644
index 0000000..ed2c77d
--- /dev/null
+++ b/services/common_time/utils.cpp
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "common_time"
+#include <utils/Log.h>
+
+#include "utils.h"
+
+namespace android {
+
+void Timeout::setTimeout(int msec) {
+    if (msec < 0) {
+        mSystemEndTime = 0;
+        return;
+    }
+
+    mSystemEndTime = systemTime() + (static_cast<nsecs_t>(msec) * 1000000);
+}
+
+int Timeout::msecTillTimeout(nsecs_t nowTime) {
+    if (!mSystemEndTime) {
+        return -1;
+    }
+
+    if (mSystemEndTime < nowTime) {
+        return 0;
+    }
+
+    nsecs_t delta = mSystemEndTime - nowTime;
+    delta += 999999;
+    delta /= 1000000;
+    if (delta > 0x7FFFFFFF) {
+        return 0x7FFFFFFF;
+    }
+
+    return static_cast<int>(delta);
+}
+
+LogRing::LogRing(const char* header, size_t entries)
+    : mSize(entries)
+    , mWr(0)
+    , mIsFull(false)
+    , mHeader(header) {
+    mRingBuffer = new Entry[mSize];
+    if (NULL == mRingBuffer)
+        ALOGE("Failed to allocate log ring with %u entries.", mSize);
+}
+
+LogRing::~LogRing() {
+    if (NULL != mRingBuffer)
+        delete[] mRingBuffer;
+}
+
+void LogRing::log(int prio, const char* tag, const char* fmt, ...) {
+    va_list argp;
+    va_start(argp, fmt);
+    internalLog(prio, tag, fmt, argp);
+    va_end(argp);
+}
+
+void LogRing::log(const char* fmt, ...) {
+    va_list argp;
+    va_start(argp, fmt);
+    internalLog(0, NULL, fmt, argp);
+    va_end(argp);
+}
+
+void LogRing::internalLog(int prio,
+                          const char* tag,
+                          const char* fmt,
+                          va_list argp) {
+    if (NULL != mRingBuffer) {
+        Mutex::Autolock lock(&mLock);
+        String8 s(String8::formatV(fmt, argp));
+        Entry* last = NULL;
+
+        if (mIsFull || mWr)
+            last = &(mRingBuffer[(mWr + mSize - 1) % mSize]);
+
+
+        if ((NULL != last) && !last->s.compare(s)) {
+            gettimeofday(&(last->last_ts), NULL);
+            ++last->count;
+        } else {
+            gettimeofday(&mRingBuffer[mWr].first_ts, NULL);
+            mRingBuffer[mWr].last_ts = mRingBuffer[mWr].first_ts;
+            mRingBuffer[mWr].count = 1;
+            mRingBuffer[mWr].s.setTo(s);
+
+            mWr = (mWr + 1) % mSize;
+            if (!mWr)
+                mIsFull = true;
+        }
+    }
+
+    if (NULL != tag)
+        LOG_PRI_VA(prio, tag, fmt, argp);
+}
+
+void LogRing::dumpLog(int fd) {
+    if (NULL == mRingBuffer)
+        return;
+
+    Mutex::Autolock lock(&mLock);
+
+    if (!mWr && !mIsFull)
+        return;
+
+    char buf[1024];
+    int res;
+    size_t start = mIsFull ? mWr : 0;
+    size_t count = mIsFull ? mSize : mWr;
+    static const char* kTimeFmt = "%a %b %d %Y %H:%M:%S";
+
+    res = snprintf(buf, sizeof(buf), "\n%s\n", mHeader);
+    if (res > 0)
+        write(fd, buf, res);
+
+    for (size_t i = 0; i < count; ++i) {
+        struct tm t;
+        char timebuf[64];
+        char repbuf[96];
+        size_t ndx = (start + i) % mSize;
+
+        if (1 != mRingBuffer[ndx].count) {
+            localtime_r(&mRingBuffer[ndx].last_ts.tv_sec, &t);
+            strftime(timebuf, sizeof(timebuf), kTimeFmt, &t);
+            snprintf(repbuf, sizeof(repbuf),
+                    " (repeated %d times, last was %s.%03ld)",
+                     mRingBuffer[ndx].count,
+                     timebuf,
+                     mRingBuffer[ndx].last_ts.tv_usec / 1000);
+            repbuf[sizeof(repbuf) - 1] = 0;
+        } else {
+            repbuf[0] = 0;
+        }
+
+        localtime_r(&mRingBuffer[ndx].first_ts.tv_sec, &t);
+        strftime(timebuf, sizeof(timebuf), kTimeFmt, &t);
+        res = snprintf(buf, sizeof(buf), "[%2d] %s.%03ld :: %s%s\n", 
+                       i, timebuf,
+                       mRingBuffer[ndx].first_ts.tv_usec / 1000,
+                       mRingBuffer[ndx].s.string(),
+                       repbuf);
+
+        if (res > 0)
+            write(fd, buf, res);
+    }
+}
+
+}  // namespace android
diff --git a/services/common_time/utils.h b/services/common_time/utils.h
new file mode 100644
index 0000000..c28cf0a
--- /dev/null
+++ b/services/common_time/utils.h
@@ -0,0 +1,83 @@
+/*
+ * 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 __UTILS_H__
+#define __UTILS_H__
+
+#include <stdint.h>
+#include <unistd.h>
+
+#include <utils/String8.h>
+#include <utils/threads.h>
+#include <utils/Timers.h>
+
+namespace android {
+
+class Timeout {
+  public:
+    Timeout() : mSystemEndTime(0) { }
+
+    // Set a timeout which should occur msec milliseconds from now.
+    // Negative values will cancel any current timeout;
+    void setTimeout(int msec);
+
+    // Return the number of milliseconds until the timeout occurs, or -1 if
+    // no timeout is scheduled.
+    int msecTillTimeout(nsecs_t nowTime);
+    int msecTillTimeout() { return msecTillTimeout(systemTime()); }
+
+  private:
+    // The systemTime() at which the timeout will be complete, or 0 if no
+    // timeout is currently scheduled.
+    nsecs_t mSystemEndTime;
+};
+
+class LogRing {
+  public:
+    LogRing(const char* header, size_t entries);
+    ~LogRing();
+
+    // Send a log message to logcat as well as storing it in the ring buffer.
+    void log(int prio, const char* tag, const char* fmt, ...);
+
+    // Add a log message the ring buffer, do not send the message to logcat.
+    void log(const char* fmt, ...);
+
+    // Dump the log to an fd (dumpsys style)
+    void dumpLog(int fd);
+
+  private:
+    class Entry {
+      public:
+        uint32_t count;
+        struct timeval first_ts;
+        struct timeval last_ts;
+        String8 s;
+    };
+
+    Mutex  mLock;
+    Entry* mRingBuffer;
+    size_t mSize;
+    size_t mWr;
+    bool   mIsFull;
+    const char* mHeader;
+
+    void internalLog(int prio, const char* tag, const char* fmt, va_list va);
+};
+
+}  // namespace android
+
+#endif  // __UTILS_H__
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index f80ac18..1c9520d 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -787,6 +787,40 @@
                         event->when = nsecs_t(iev.time.tv_sec) * 1000000000LL
                                 + nsecs_t(iev.time.tv_usec) * 1000LL;
                         ALOGV("event time %lld, now %lld", event->when, now);
+
+                        // Bug 7291243: Add a guard in case the kernel generates timestamps
+                        // that appear to be far into the future because they were generated
+                        // using the wrong clock source.
+                        //
+                        // This can happen because when the input device is initially opened
+                        // it has a default clock source of CLOCK_REALTIME.  Any input events
+                        // enqueued right after the device is opened will have timestamps
+                        // generated using CLOCK_REALTIME.  We later set the clock source
+                        // to CLOCK_MONOTONIC but it is already too late.
+                        //
+                        // Invalid input event timestamps can result in ANRs, crashes and
+                        // and other issues that are hard to track down.  We must not let them
+                        // propagate through the system.
+                        //
+                        // Log a warning so that we notice the problem and recover gracefully.
+                        if (event->when >= now + 10 * 1000000000LL) {
+                            // Double-check.  Time may have moved on.
+                            nsecs_t time = systemTime(SYSTEM_TIME_MONOTONIC);
+                            if (event->when > time) {
+                                ALOGW("An input event from %s has a timestamp that appears to "
+                                        "have been generated using the wrong clock source "
+                                        "(expected CLOCK_MONOTONIC): "
+                                        "event time %lld, current time %lld, call time %lld.  "
+                                        "Using current time instead.",
+                                        device->path.string(), event->when, time, now);
+                                event->when = time;
+                            } else {
+                                ALOGV("Event time is ok but failed the fast path and required "
+                                        "an extra call to systemTime: "
+                                        "event time %lld, current time %lld, call time %lld.",
+                                        event->when, time, now);
+                            }
+                        }
 #else
                         event->when = now;
 #endif
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index e63da05..0465215 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -166,6 +166,10 @@
     return true;
 }
 
+static bool isMainDisplay(int32_t displayId) {
+    return displayId == ADISPLAY_ID_DEFAULT || displayId == ADISPLAY_ID_NONE;
+}
+
 static void dumpRegion(String8& dump, const SkRegion& region) {
     if (region.isEmpty()) {
         dump.append("<empty>");
@@ -220,10 +224,16 @@
         AutoMutex _l(mLock);
         mDispatcherIsAliveCondition.broadcast();
 
-        dispatchOnceInnerLocked(&nextWakeupTime);
+        // Run a dispatch loop if there are no pending commands.
+        // The dispatch loop might enqueue commands to run afterwards.
+        if (!haveCommandsLocked()) {
+            dispatchOnceInnerLocked(&nextWakeupTime);
+        }
 
+        // Run all pending commands if there are any.
+        // If any commands were run then force the next poll to wake up immediately.
         if (runCommandsLockedInterruptible()) {
-            nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
+            nextWakeupTime = LONG_LONG_MIN;
         }
     } // release lock
 
@@ -423,11 +433,12 @@
                 && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
                 && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY
                 && mInputTargetWaitApplicationHandle != NULL) {
+            int32_t displayId = motionEntry->displayId;
             int32_t x = int32_t(motionEntry->pointerCoords[0].
                     getAxisValue(AMOTION_EVENT_AXIS_X));
             int32_t y = int32_t(motionEntry->pointerCoords[0].
                     getAxisValue(AMOTION_EVENT_AXIS_Y));
-            sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(x, y);
+            sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y);
             if (touchedWindowHandle != NULL
                     && touchedWindowHandle->inputApplicationHandle
                             != mInputTargetWaitApplicationHandle) {
@@ -444,28 +455,31 @@
     return needWake;
 }
 
-sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) {
+sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId,
+        int32_t x, int32_t y) {
     // Traverse windows from front to back to find touched window.
     size_t numWindows = mWindowHandles.size();
     for (size_t i = 0; i < numWindows; i++) {
         sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
         const InputWindowInfo* windowInfo = windowHandle->getInfo();
-        int32_t flags = windowInfo->layoutParamsFlags;
+        if (windowInfo->displayId == displayId) {
+            int32_t flags = windowInfo->layoutParamsFlags;
 
-        if (windowInfo->visible) {
-            if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
-                bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
-                        | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
-                if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
-                    // Found window.
-                    return windowHandle;
+            if (windowInfo->visible) {
+                if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
+                    bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
+                            | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
+                    if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
+                        // Found window.
+                        return windowHandle;
+                    }
                 }
             }
-        }
 
-        if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) {
-            // Error window is on top but not visible, so touch is dropped.
-            return NULL;
+            if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) {
+                // Error window is on top but not visible, so touch is dropped.
+                return NULL;
+            }
         }
     }
     return NULL;
@@ -554,6 +568,10 @@
     return currentTime - entry->eventTime >= STALE_EVENT_TIMEOUT;
 }
 
+bool InputDispatcher::haveCommandsLocked() const {
+    return !mCommandQueue.isEmpty();
+}
+
 bool InputDispatcher::runCommandsLockedInterruptible() {
     if (mCommandQueue.isEmpty()) {
         return false;
@@ -826,7 +844,10 @@
         return true;
     }
 
-    addMonitoringTargetsLocked(inputTargets);
+    // TODO: support sending secondary display events to input monitors
+    if (isMainDisplay(entry->displayId)) {
+        addMonitoringTargetsLocked(inputTargets);
+    }
 
     // Dispatch the motion.
     if (conflictingPointerActions) {
@@ -1117,6 +1138,7 @@
     //
     bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
 
+    int32_t displayId = entry->displayId;
     int32_t action = entry->action;
     int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
 
@@ -1126,9 +1148,10 @@
     sp<InputWindowHandle> newHoverWindowHandle;
 
     bool isSplit = mTouchState.split;
-    bool switchedDevice = mTouchState.deviceId >= 0
+    bool switchedDevice = mTouchState.deviceId >= 0 && mTouchState.displayId >= 0
             && (mTouchState.deviceId != entry->deviceId
-                    || mTouchState.source != entry->source);
+                    || mTouchState.source != entry->source
+                    || mTouchState.displayId != displayId);
     bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
             || maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
             || maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT);
@@ -1152,6 +1175,7 @@
         mTempTouchState.down = down;
         mTempTouchState.deviceId = entry->deviceId;
         mTempTouchState.source = entry->source;
+        mTempTouchState.displayId = displayId;
         isSplit = false;
     } else {
         mTempTouchState.copyFrom(mTouchState);
@@ -1174,8 +1198,11 @@
         for (size_t i = 0; i < numWindows; i++) {
             sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
             const InputWindowInfo* windowInfo = windowHandle->getInfo();
-            int32_t flags = windowInfo->layoutParamsFlags;
+            if (windowInfo->displayId != displayId) {
+                continue; // wrong display
+            }
 
+            int32_t flags = windowInfo->layoutParamsFlags;
             if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) {
                 if (topErrorWindowHandle == NULL) {
                     topErrorWindowHandle = windowHandle;
@@ -1300,7 +1327,8 @@
 
             sp<InputWindowHandle> oldTouchedWindowHandle =
                     mTempTouchState.getFirstForegroundWindowHandle();
-            sp<InputWindowHandle> newTouchedWindowHandle = findTouchedWindowAtLocked(x, y);
+            sp<InputWindowHandle> newTouchedWindowHandle =
+                    findTouchedWindowAtLocked(displayId, x, y);
             if (oldTouchedWindowHandle != newTouchedWindowHandle
                     && newTouchedWindowHandle != NULL) {
 #if DEBUG_FOCUS
@@ -1438,8 +1466,10 @@
         if (foregroundWindowHandle->getInfo()->hasWallpaper) {
             for (size_t i = 0; i < mWindowHandles.size(); i++) {
                 sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
-                if (windowHandle->getInfo()->layoutParamsType
-                        == InputWindowInfo::TYPE_WALLPAPER) {
+                const InputWindowInfo* info = windowHandle->getInfo();
+                if (info->displayId == displayId
+                        && windowHandle->getInfo()->layoutParamsType
+                                == InputWindowInfo::TYPE_WALLPAPER) {
                     mTempTouchState.addOrUpdateWindow(windowHandle,
                             InputTarget::FLAG_WINDOW_IS_OBSCURED
                                     | InputTarget::FLAG_DISPATCH_AS_IS,
@@ -1495,6 +1525,7 @@
                         || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
                     mTouchState.deviceId = entry->deviceId;
                     mTouchState.source = entry->source;
+                    mTouchState.displayId = displayId;
                 }
             } else if (maskedAction == AMOTION_EVENT_ACTION_UP
                     || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
@@ -1610,6 +1641,7 @@
 
 bool InputDispatcher::isWindowObscuredAtPointLocked(
         const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const {
+    int32_t displayId = windowHandle->getInfo()->displayId;
     size_t numWindows = mWindowHandles.size();
     for (size_t i = 0; i < numWindows; i++) {
         sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
@@ -1618,7 +1650,8 @@
         }
 
         const InputWindowInfo* otherInfo = otherHandle->getInfo();
-        if (otherInfo->visible && ! otherInfo->isTrustedOverlay()
+        if (otherInfo->displayId == displayId
+                && otherInfo->visible && !otherInfo->isTrustedOverlay()
                 && otherInfo->frameContainsPoint(x, y)) {
             return true;
         }
@@ -1693,7 +1726,17 @@
 }
 
 void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
-    int32_t eventType = POWER_MANAGER_OTHER_EVENT;
+    if (mFocusedWindowHandle != NULL) {
+        const InputWindowInfo* info = mFocusedWindowHandle->getInfo();
+        if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) {
+#if DEBUG_DISPATCH_CYCLE
+            ALOGD("Not poking user activity: disabled by window '%s'.", info->name.string());
+#endif
+            return;
+        }
+    }
+
+    int32_t eventType = USER_ACTIVITY_EVENT_OTHER;
     switch (eventEntry->type) {
     case EventEntry::TYPE_MOTION: {
         const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
@@ -1702,7 +1745,7 @@
         }
 
         if (MotionEvent::isTouchEvent(motionEntry->source, motionEntry->action)) {
-            eventType = POWER_MANAGER_TOUCH_EVENT;
+            eventType = USER_ACTIVITY_EVENT_TOUCH;
         }
         break;
     }
@@ -1711,7 +1754,7 @@
         if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
             return;
         }
-        eventType = POWER_MANAGER_BUTTON_EVENT;
+        eventType = USER_ACTIVITY_EVENT_BUTTON;
         break;
     }
     }
@@ -1845,7 +1888,7 @@
         }
         if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
                 && !connection->inputState.isHovering(
-                        motionEntry->deviceId, motionEntry->source)) {
+                        motionEntry->deviceId, motionEntry->source, motionEntry->displayId)) {
 #if DEBUG_DISPATCH_CYCLE
         ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter event",
                 connection->getInputChannelName());
@@ -2271,6 +2314,7 @@
             originalMotionEntry->xPrecision,
             originalMotionEntry->yPrecision,
             originalMotionEntry->downTime,
+            originalMotionEntry->displayId,
             splitPointerCount, splitPointerProperties, splitPointerCoords);
 
     if (originalMotionEntry->injectionState) {
@@ -2351,7 +2395,7 @@
     { // acquire lock
         mLock.lock();
 
-        if (mInputFilterEnabled) {
+        if (shouldSendKeyToInputFilterLocked(args)) {
             mLock.unlock();
 
             policyFlags |= POLICY_FLAG_FILTERED;
@@ -2377,6 +2421,10 @@
     }
 }
 
+bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) {
+    return mInputFilterEnabled;
+}
+
 void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
 #if DEBUG_INBOUND_EVENT_DETAILS
     ALOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
@@ -2415,7 +2463,7 @@
     { // acquire lock
         mLock.lock();
 
-        if (mInputFilterEnabled) {
+        if (shouldSendMotionToInputFilterLocked(args)) {
             mLock.unlock();
 
             MotionEvent event;
@@ -2438,6 +2486,7 @@
                 args->deviceId, args->source, policyFlags,
                 args->action, args->flags, args->metaState, args->buttonState,
                 args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
+                args->displayId,
                 args->pointerCount, args->pointerProperties, args->pointerCoords);
 
         needWake = enqueueInboundEventLocked(newEntry);
@@ -2449,17 +2498,22 @@
     }
 }
 
+bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) {
+    // TODO: support sending secondary display events to input filter
+    return mInputFilterEnabled && isMainDisplay(args->displayId);
+}
+
 void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) {
 #if DEBUG_INBOUND_EVENT_DETAILS
-    ALOGD("notifySwitch - eventTime=%lld, policyFlags=0x%x, switchCode=%d, switchValue=%d",
+    ALOGD("notifySwitch - eventTime=%lld, policyFlags=0x%x, switchValues=0x%08x, switchMask=0x%08x",
             args->eventTime, args->policyFlags,
-            args->switchCode, args->switchValue);
+            args->switchValues, args->switchMask);
 #endif
 
     uint32_t policyFlags = args->policyFlags;
     policyFlags |= POLICY_FLAG_TRUSTED;
     mPolicy->notifySwitch(args->eventTime,
-            args->switchCode, args->switchValue, policyFlags);
+            args->switchValues, args->switchMask, policyFlags);
 }
 
 void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
@@ -2532,6 +2586,7 @@
 
     case AINPUT_EVENT_TYPE_MOTION: {
         const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
+        int32_t displayId = ADISPLAY_ID_DEFAULT;
         int32_t action = motionEvent->getAction();
         size_t pointerCount = motionEvent->getPointerCount();
         const PointerProperties* pointerProperties = motionEvent->getPointerProperties();
@@ -2553,8 +2608,8 @@
                 motionEvent->getMetaState(), motionEvent->getButtonState(),
                 motionEvent->getEdgeFlags(),
                 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
-                motionEvent->getDownTime(), uint32_t(pointerCount),
-                pointerProperties, samplePointerCoords);
+                motionEvent->getDownTime(), displayId,
+                uint32_t(pointerCount), pointerProperties, samplePointerCoords);
         lastInjectedEntry = firstInjectedEntry;
         for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
             sampleEventTimes += 1;
@@ -2565,8 +2620,8 @@
                     motionEvent->getMetaState(), motionEvent->getButtonState(),
                     motionEvent->getEdgeFlags(),
                     motionEvent->getXPrecision(), motionEvent->getYPrecision(),
-                    motionEvent->getDownTime(), uint32_t(pointerCount),
-                    pointerProperties, samplePointerCoords);
+                    motionEvent->getDownTime(), displayId,
+                    uint32_t(pointerCount), pointerProperties, samplePointerCoords);
             lastInjectedEntry->next = nextInjectedEntry;
             lastInjectedEntry = nextInjectedEntry;
         }
@@ -2939,6 +2994,12 @@
 #endif
             return true;
         }
+        if (fromWindowHandle->getInfo()->displayId != toWindowHandle->getInfo()->displayId) {
+#if DEBUG_FOCUS
+            ALOGD("Cannot transfer focus because windows are on different displays.");
+#endif
+            return false;
+        }
 
         bool found = false;
         for (size_t i = 0; i < mTouchState.windows.size(); i++) {
@@ -3040,6 +3101,7 @@
     dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
     dump.appendFormat(INDENT "TouchDeviceId: %d\n", mTouchState.deviceId);
     dump.appendFormat(INDENT "TouchSource: 0x%08x\n", mTouchState.source);
+    dump.appendFormat(INDENT "TouchDisplayId: %d\n", mTouchState.displayId);
     if (!mTouchState.windows.isEmpty()) {
         dump.append(INDENT "TouchedWindows:\n");
         for (size_t i = 0; i < mTouchState.windows.size(); i++) {
@@ -3059,11 +3121,12 @@
             const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
             const InputWindowInfo* windowInfo = windowHandle->getInfo();
 
-            dump.appendFormat(INDENT2 "%d: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
+            dump.appendFormat(INDENT2 "%d: name='%s', displayId=%d, "
+                    "paused=%s, hasFocus=%s, hasWallpaper=%s, "
                     "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
                     "frame=[%d,%d][%d,%d], scale=%f, "
                     "touchableRegion=",
-                    i, windowInfo->name.string(),
+                    i, windowInfo->name.string(), windowInfo->displayId,
                     toString(windowInfo->paused),
                     toString(windowInfo->hasFocus),
                     toString(windowInfo->hasWallpaper),
@@ -3194,9 +3257,10 @@
         }
 
         mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
-
-        runCommandsLockedInterruptible();
     } // release lock
+
+    // Wake the looper because some connections have changed.
+    mLooper->wake();
     return OK;
 }
 
@@ -3241,8 +3305,6 @@
     nsecs_t currentTime = now();
     abortBrokenDispatchCycleLocked(currentTime, connection, notify);
 
-    runCommandsLockedInterruptible();
-
     connection->status = Connection::STATUS_ZOMBIE;
     return OK;
 }
@@ -3802,14 +3864,14 @@
         int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
         int32_t metaState, int32_t buttonState,
         int32_t edgeFlags, float xPrecision, float yPrecision,
-        nsecs_t downTime, uint32_t pointerCount,
+        nsecs_t downTime, int32_t displayId, uint32_t pointerCount,
         const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) :
         EventEntry(TYPE_MOTION, eventTime, policyFlags),
         eventTime(eventTime),
         deviceId(deviceId), source(source), action(action), flags(flags),
         metaState(metaState), buttonState(buttonState), edgeFlags(edgeFlags),
         xPrecision(xPrecision), yPrecision(yPrecision),
-        downTime(downTime), pointerCount(pointerCount) {
+        downTime(downTime), displayId(displayId), pointerCount(pointerCount) {
     for (uint32_t i = 0; i < pointerCount; i++) {
         this->pointerProperties[i].copyFrom(pointerProperties[i]);
         this->pointerCoords[i].copyFrom(pointerCoords[i]);
@@ -3820,8 +3882,8 @@
 }
 
 void InputDispatcher::MotionEntry::appendDescription(String8& msg) const {
-    msg.appendFormat("MotionEvent(action=%d, deviceId=%d, source=0x%08x)",
-            action, deviceId, source);
+    msg.appendFormat("MotionEvent(action=%d, deviceId=%d, source=0x%08x, displayId=%d)",
+            action, deviceId, source, displayId);
 }
 
 
@@ -3864,11 +3926,13 @@
     return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
 }
 
-bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source) const {
+bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source,
+        int32_t displayId) const {
     for (size_t i = 0; i < mMotionMementos.size(); i++) {
         const MotionMemento& memento = mMotionMementos.itemAt(i);
         if (memento.deviceId == deviceId
                 && memento.source == source
+                && memento.displayId == displayId
                 && memento.hovering) {
             return true;
         }
@@ -4025,6 +4089,7 @@
         const MotionMemento& memento = mMotionMementos.itemAt(i);
         if (memento.deviceId == entry->deviceId
                 && memento.source == entry->source
+                && memento.displayId == entry->displayId
                 && memento.hovering == hovering) {
             return i;
         }
@@ -4055,6 +4120,7 @@
     memento.xPrecision = entry->xPrecision;
     memento.yPrecision = entry->yPrecision;
     memento.downTime = entry->downTime;
+    memento.displayId = entry->displayId;
     memento.setPointers(entry);
     memento.hovering = hovering;
     memento.policyFlags = entry->policyFlags;
@@ -4090,6 +4156,7 @@
                             : AMOTION_EVENT_ACTION_CANCEL,
                     memento.flags, 0, 0, 0,
                     memento.xPrecision, memento.yPrecision, memento.downTime,
+                    memento.displayId,
                     memento.pointerCount, memento.pointerProperties, memento.pointerCoords));
         }
     }
@@ -4108,7 +4175,8 @@
             for (size_t j = 0; j < other.mMotionMementos.size(); ) {
                 const MotionMemento& otherMemento = other.mMotionMementos.itemAt(j);
                 if (memento.deviceId == otherMemento.deviceId
-                        && memento.source == otherMemento.source) {
+                        && memento.source == otherMemento.source
+                        && memento.displayId == otherMemento.displayId) {
                     other.mMotionMementos.removeAt(j);
                 } else {
                     j += 1;
@@ -4240,7 +4308,7 @@
 // --- InputDispatcher::TouchState ---
 
 InputDispatcher::TouchState::TouchState() :
-    down(false), split(false), deviceId(-1), source(0) {
+    down(false), split(false), deviceId(-1), source(0), displayId(-1) {
 }
 
 InputDispatcher::TouchState::~TouchState() {
@@ -4251,6 +4319,7 @@
     split = false;
     deviceId = -1;
     source = 0;
+    displayId = -1;
     windows.clear();
 }
 
@@ -4259,6 +4328,7 @@
     split = other.split;
     deviceId = other.deviceId;
     source = other.source;
+    displayId = other.displayId;
     windows = other.windows;
 }
 
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index d0824fc..d4f932e 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -248,7 +248,7 @@
     /* Notifies the policy about switch events.
      */
     virtual void notifySwitch(nsecs_t when,
-            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) = 0;
+            uint32_t switchValues, uint32_t switchMask, uint32_t policyFlags) = 0;
 
     /* Poke user activity for an event dispatched to a window. */
     virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) = 0;
@@ -511,15 +511,17 @@
         float xPrecision;
         float yPrecision;
         nsecs_t downTime;
+        int32_t displayId;
         uint32_t pointerCount;
         PointerProperties pointerProperties[MAX_POINTERS];
         PointerCoords pointerCoords[MAX_POINTERS];
 
         MotionEntry(nsecs_t eventTime,
-                int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action,
-                int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+                int32_t deviceId, uint32_t source, uint32_t policyFlags,
+                int32_t action, int32_t flags,
+                int32_t metaState, int32_t buttonState, int32_t edgeFlags,
                 float xPrecision, float yPrecision,
-                nsecs_t downTime, uint32_t pointerCount,
+                nsecs_t downTime, int32_t displayId, uint32_t pointerCount,
                 const PointerProperties* pointerProperties, const PointerCoords* pointerCoords);
         virtual void appendDescription(String8& msg) const;
 
@@ -696,7 +698,7 @@
 
         // Returns true if the specified source is known to have received a hover enter
         // motion event.
-        bool isHovering(int32_t deviceId, uint32_t source) const;
+        bool isHovering(int32_t deviceId, uint32_t source, int32_t displayId) const;
 
         // Records tracking information for a key event that has just been published.
         // Returns true if the event should be delivered, false if it is inconsistent
@@ -752,6 +754,7 @@
             float xPrecision;
             float yPrecision;
             nsecs_t downTime;
+            int32_t displayId;
             uint32_t pointerCount;
             PointerProperties pointerProperties[MAX_POINTERS];
             PointerCoords pointerCoords[MAX_POINTERS];
@@ -867,7 +870,7 @@
     // to transfer focus to a new application.
     EventEntry* mNextUnblockedEvent;
 
-    sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t x, int32_t y);
+    sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y);
 
     // All registered connections mapped by channel file descriptor.
     KeyedVector<int, sp<Connection> > mConnectionsByFd;
@@ -896,9 +899,14 @@
     KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime);
 
     // Deferred command processing.
+    bool haveCommandsLocked() const;
     bool runCommandsLockedInterruptible();
     CommandEntry* postCommandLocked(Command command);
 
+    // Input filter processing.
+    bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args);
+    bool shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args);
+
     // Inbound event processing.
     void drainInboundQueueLocked();
     void releasePendingEventLocked();
@@ -928,6 +936,7 @@
         bool split;
         int32_t deviceId; // id of the device that is currently down, others are rejected
         uint32_t source;  // source of the device that is current down, others are rejected
+        int32_t displayId; // id to the display that currently has a touch, others are rejected
         Vector<TouchedWindow> windows;
 
         TouchState();
diff --git a/services/input/InputListener.cpp b/services/input/InputListener.cpp
index 657a6b9..85bb0ed 100644
--- a/services/input/InputListener.cpp
+++ b/services/input/InputListener.cpp
@@ -69,12 +69,12 @@
 NotifyMotionArgs::NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source,
         uint32_t policyFlags,
         int32_t action, int32_t flags, int32_t metaState, int32_t buttonState,
-        int32_t edgeFlags, uint32_t pointerCount,
+        int32_t edgeFlags, int32_t displayId, uint32_t pointerCount,
         const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
         float xPrecision, float yPrecision, nsecs_t downTime) :
         eventTime(eventTime), deviceId(deviceId), source(source), policyFlags(policyFlags),
         action(action), flags(flags), metaState(metaState), buttonState(buttonState),
-        edgeFlags(edgeFlags), pointerCount(pointerCount),
+        edgeFlags(edgeFlags), displayId(displayId), pointerCount(pointerCount),
         xPrecision(xPrecision), yPrecision(yPrecision), downTime(downTime) {
     for (uint32_t i = 0; i < pointerCount; i++) {
         this->pointerProperties[i].copyFrom(pointerProperties[i]);
@@ -87,7 +87,8 @@
         policyFlags(other.policyFlags),
         action(other.action), flags(other.flags),
         metaState(other.metaState), buttonState(other.buttonState),
-        edgeFlags(other.edgeFlags), pointerCount(other.pointerCount),
+        edgeFlags(other.edgeFlags), displayId(other.displayId),
+        pointerCount(other.pointerCount),
         xPrecision(other.xPrecision), yPrecision(other.yPrecision), downTime(other.downTime) {
     for (uint32_t i = 0; i < pointerCount; i++) {
         pointerProperties[i].copyFrom(other.pointerProperties[i]);
@@ -103,14 +104,14 @@
 // --- NotifySwitchArgs ---
 
 NotifySwitchArgs::NotifySwitchArgs(nsecs_t eventTime, uint32_t policyFlags,
-        int32_t switchCode, int32_t switchValue) :
+        uint32_t switchValues, uint32_t switchMask) :
         eventTime(eventTime), policyFlags(policyFlags),
-        switchCode(switchCode), switchValue(switchValue) {
+        switchValues(switchValues), switchMask(switchMask) {
 }
 
 NotifySwitchArgs::NotifySwitchArgs(const NotifySwitchArgs& other) :
         eventTime(other.eventTime), policyFlags(other.policyFlags),
-        switchCode(other.switchCode), switchValue(other.switchValue) {
+        switchValues(other.switchValues), switchMask(other.switchMask) {
 }
 
 void NotifySwitchArgs::notify(const sp<InputListenerInterface>& listener) const {
diff --git a/services/input/InputListener.h b/services/input/InputListener.h
index b1dc0b8..cd7c25a 100644
--- a/services/input/InputListener.h
+++ b/services/input/InputListener.h
@@ -88,6 +88,7 @@
     int32_t metaState;
     int32_t buttonState;
     int32_t edgeFlags;
+    int32_t displayId;
     uint32_t pointerCount;
     PointerProperties pointerProperties[MAX_POINTERS];
     PointerCoords pointerCoords[MAX_POINTERS];
@@ -99,7 +100,7 @@
 
     NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags,
             int32_t action, int32_t flags, int32_t metaState, int32_t buttonState,
-            int32_t edgeFlags, uint32_t pointerCount,
+            int32_t edgeFlags, int32_t displayId, uint32_t pointerCount,
             const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
             float xPrecision, float yPrecision, nsecs_t downTime);
 
@@ -115,13 +116,13 @@
 struct NotifySwitchArgs : public NotifyArgs {
     nsecs_t eventTime;
     uint32_t policyFlags;
-    int32_t switchCode;
-    int32_t switchValue;
+    uint32_t switchValues;
+    uint32_t switchMask;
 
     inline NotifySwitchArgs() { }
 
     NotifySwitchArgs(nsecs_t eventTime, uint32_t policyFlags,
-            int32_t switchCode, int32_t switchValue);
+            uint32_t switchValues, uint32_t switchMask);
 
     NotifySwitchArgs(const NotifySwitchArgs& other);
 
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index cd6a2ec..bc8df18 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -203,34 +203,18 @@
 
 // --- InputReaderConfiguration ---
 
-bool InputReaderConfiguration::getDisplayInfo(int32_t displayId, bool external,
-        int32_t* width, int32_t* height, int32_t* orientation) const {
-    if (displayId == 0) {
-        const DisplayInfo& info = external ? mExternalDisplay : mInternalDisplay;
-        if (info.width > 0 && info.height > 0) {
-            if (width) {
-                *width = info.width;
-            }
-            if (height) {
-                *height = info.height;
-            }
-            if (orientation) {
-                *orientation = info.orientation;
-            }
-            return true;
-        }
+bool InputReaderConfiguration::getDisplayInfo(bool external, DisplayViewport* outViewport) const {
+    const DisplayViewport& viewport = external ? mExternalDisplay : mInternalDisplay;
+    if (viewport.displayId >= 0) {
+        *outViewport = viewport;
+        return true;
     }
     return false;
 }
 
-void InputReaderConfiguration::setDisplayInfo(int32_t displayId, bool external,
-        int32_t width, int32_t height, int32_t orientation) {
-    if (displayId == 0) {
-        DisplayInfo& info = external ? mExternalDisplay : mInternalDisplay;
-        info.width = width;
-        info.height = height;
-        info.orientation = orientation;
-    }
+void InputReaderConfiguration::setDisplayInfo(bool external, const DisplayViewport& viewport) {
+    DisplayViewport& v = external ? mExternalDisplay : mInternalDisplay;
+    v = viewport;
 }
 
 
@@ -972,8 +956,9 @@
     size_t numMappers = mMappers.size();
     for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
 #if DEBUG_RAW_EVENTS
-        ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x",
-                rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value);
+        ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%lld",
+                rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
+                rawEvent->when);
 #endif
 
         if (mDropUntilNextSync) {
@@ -1816,7 +1801,7 @@
 // --- SwitchInputMapper ---
 
 SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
-        InputMapper(device) {
+        InputMapper(device), mUpdatedSwitchValues(0), mUpdatedSwitchMask(0) {
 }
 
 SwitchInputMapper::~SwitchInputMapper() {
@@ -1829,14 +1814,33 @@
 void SwitchInputMapper::process(const RawEvent* rawEvent) {
     switch (rawEvent->type) {
     case EV_SW:
-        processSwitch(rawEvent->when, rawEvent->code, rawEvent->value);
+        processSwitch(rawEvent->code, rawEvent->value);
         break;
+
+    case EV_SYN:
+        if (rawEvent->code == SYN_REPORT) {
+            sync(rawEvent->when);
+        }
     }
 }
 
-void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
-    NotifySwitchArgs args(when, 0, switchCode, switchValue);
-    getListener()->notifySwitch(&args);
+void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
+    if (switchCode >= 0 && switchCode < 32) {
+        if (switchValue) {
+            mUpdatedSwitchValues |= 1 << switchCode;
+        }
+        mUpdatedSwitchMask |= 1 << switchCode;
+    }
+}
+
+void SwitchInputMapper::sync(nsecs_t when) {
+    if (mUpdatedSwitchMask) {
+        NotifySwitchArgs args(when, 0, mUpdatedSwitchValues, mUpdatedSwitchMask);
+        getListener()->notifySwitch(&args);
+
+        mUpdatedSwitchValues = 0;
+        mUpdatedSwitchMask = 0;
+    }
 }
 
 int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
@@ -2001,9 +2005,11 @@
     }
 
     if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
-        if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
-            if (!config->getDisplayInfo(mParameters.associatedDisplayId,
-                        false /*external*/, NULL, NULL, &mOrientation)) {
+        if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
+            DisplayViewport v;
+            if (config->getDisplayInfo(false /*external*/, &v)) {
+                mOrientation = v.orientation;
+            } else {
                 mOrientation = DISPLAY_ORIENTATION_0;
             }
         } else {
@@ -2017,16 +2023,16 @@
     getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
             mParameters.orientationAware);
 
-    mParameters.associatedDisplayId = -1;
+    mParameters.hasAssociatedDisplay = false;
     if (mParameters.orientationAware) {
-        mParameters.associatedDisplayId = 0;
+        mParameters.hasAssociatedDisplay = true;
     }
 }
 
 void KeyboardInputMapper::dumpParameters(String8& dump) {
     dump.append(INDENT3 "Parameters:\n");
-    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
-            mParameters.associatedDisplayId);
+    dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n",
+            toString(mParameters.hasAssociatedDisplay));
     dump.appendFormat(INDENT4 "OrientationAware: %s\n",
             toString(mParameters.orientationAware));
 }
@@ -2086,7 +2092,7 @@
 
     if (down) {
         // Rotate key codes according to orientation if needed.
-        if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
+        if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
             keyCode = rotateKeyCode(keyCode, mOrientation);
         }
 
@@ -2317,9 +2323,11 @@
     }
 
     if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
-        if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
-            if (!config->getDisplayInfo(mParameters.associatedDisplayId,
-                        false /*external*/, NULL, NULL, &mOrientation)) {
+        if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
+            DisplayViewport v;
+            if (config->getDisplayInfo(false /*external*/, &v)) {
+                mOrientation = v.orientation;
+            } else {
                 mOrientation = DISPLAY_ORIENTATION_0;
             }
         } else {
@@ -2344,16 +2352,16 @@
     getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
             mParameters.orientationAware);
 
-    mParameters.associatedDisplayId = -1;
+    mParameters.hasAssociatedDisplay = false;
     if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) {
-        mParameters.associatedDisplayId = 0;
+        mParameters.hasAssociatedDisplay = true;
     }
 }
 
 void CursorInputMapper::dumpParameters(String8& dump) {
     dump.append(INDENT3 "Parameters:\n");
-    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
-            mParameters.associatedDisplayId);
+    dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n",
+            toString(mParameters.hasAssociatedDisplay));
 
     switch (mParameters.mode) {
     case Parameters::MODE_POINTER:
@@ -2420,7 +2428,7 @@
     bool moved = deltaX != 0 || deltaY != 0;
 
     // Rotate delta according to orientation if needed.
-    if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
+    if (mParameters.orientationAware && mParameters.hasAssociatedDisplay
             && (deltaX != 0.0f || deltaY != 0.0f)) {
         rotateDelta(mOrientation, &deltaX, &deltaY);
     }
@@ -2443,6 +2451,7 @@
 
     mPointerVelocityControl.move(when, &deltaX, &deltaY);
 
+    int32_t displayId;
     if (mPointerController != NULL) {
         if (moved || scrolled || buttonsChanged) {
             mPointerController->setPresentation(
@@ -2463,9 +2472,11 @@
         mPointerController->getPosition(&x, &y);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+        displayId = ADISPLAY_ID_DEFAULT;
     } else {
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
+        displayId = ADISPLAY_ID_NONE;
     }
 
     pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
@@ -2497,7 +2508,8 @@
 
         NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
                 motionEventAction, 0, metaState, currentButtonState, 0,
-                1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
+                displayId, 1, &pointerProperties, &pointerCoords,
+                mXPrecision, mYPrecision, downTime);
         getListener()->notifyMotion(&args);
 
         // Send hover move after UP to tell the application that the mouse is hovering now.
@@ -2506,7 +2518,8 @@
             NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, policyFlags,
                     AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
                     metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
-                    1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
+                    displayId, 1, &pointerProperties, &pointerCoords,
+                    mXPrecision, mYPrecision, downTime);
             getListener()->notifyMotion(&hoverArgs);
         }
 
@@ -2518,7 +2531,8 @@
             NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags,
                     AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState,
                     AMOTION_EVENT_EDGE_FLAG_NONE,
-                    1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
+                    displayId, 1, &pointerProperties, &pointerCoords,
+                    mXPrecision, mYPrecision, downTime);
             getListener()->notifyMotion(&scrollArgs);
         }
     }
@@ -2551,7 +2565,8 @@
 TouchInputMapper::TouchInputMapper(InputDevice* device) :
         InputMapper(device),
         mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
-        mSurfaceOrientation(-1), mSurfaceWidth(-1), mSurfaceHeight(-1) {
+        mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0),
+        mSurfaceOrientation(DISPLAY_ORIENTATION_0) {
 }
 
 TouchInputMapper::~TouchInputMapper() {
@@ -2613,6 +2628,8 @@
     dumpSurface(dump);
 
     dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
+    dump.appendFormat(INDENT4 "XTranslate: %0.3f\n", mXTranslate);
+    dump.appendFormat(INDENT4 "YTranslate: %0.3f\n", mYTranslate);
     dump.appendFormat(INDENT4 "XScale: %0.3f\n", mXScale);
     dump.appendFormat(INDENT4 "YScale: %0.3f\n", mYScale);
     dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mXPrecision);
@@ -2620,7 +2637,6 @@
     dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
     dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
     dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
-    dump.appendFormat(INDENT4 "OrientationCenter: %0.3f\n", mOrientationCenter);
     dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
     dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
     dump.appendFormat(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
@@ -2783,15 +2799,15 @@
     getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
             mParameters.orientationAware);
 
-    mParameters.associatedDisplayId = -1;
+    mParameters.hasAssociatedDisplay = false;
     mParameters.associatedDisplayIsExternal = false;
     if (mParameters.orientationAware
             || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
             || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
+        mParameters.hasAssociatedDisplay = true;
         mParameters.associatedDisplayIsExternal =
                 mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
                         && getDevice()->isExternal();
-        mParameters.associatedDisplayId = 0;
     }
 }
 
@@ -2823,8 +2839,9 @@
         ALOG_ASSERT(false);
     }
 
-    dump.appendFormat(INDENT4 "AssociatedDisplay: id=%d, isExternal=%s\n",
-            mParameters.associatedDisplayId, toString(mParameters.associatedDisplayIsExternal));
+    dump.appendFormat(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s\n",
+            toString(mParameters.hasAssociatedDisplay),
+            toString(mParameters.associatedDisplayIsExternal));
     dump.appendFormat(INDENT4 "OrientationAware: %s\n",
             toString(mParameters.orientationAware));
 }
@@ -2862,7 +2879,7 @@
             mSource |= AINPUT_SOURCE_STYLUS;
         }
     } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
-            && mParameters.associatedDisplayId >= 0) {
+            && mParameters.hasAssociatedDisplay) {
         mSource = AINPUT_SOURCE_TOUCHSCREEN;
         mDeviceMode = DEVICE_MODE_DIRECT;
         if (hasStylus()) {
@@ -2881,32 +2898,93 @@
         return;
     }
 
+    // Raw width and height in the natural orientation.
+    int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
+    int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
+
     // Get associated display dimensions.
-    if (mParameters.associatedDisplayId >= 0) {
-        if (!mConfig.getDisplayInfo(mParameters.associatedDisplayId,
-                mParameters.associatedDisplayIsExternal,
-                &mAssociatedDisplayWidth, &mAssociatedDisplayHeight,
-                &mAssociatedDisplayOrientation)) {
+    bool viewportChanged = false;
+    DisplayViewport newViewport;
+    if (mParameters.hasAssociatedDisplay) {
+        if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, &newViewport)) {
             ALOGI(INDENT "Touch device '%s' could not query the properties of its associated "
-                    "display %d.  The device will be inoperable until the display size "
+                    "display.  The device will be inoperable until the display size "
                     "becomes available.",
-                    getDeviceName().string(), mParameters.associatedDisplayId);
+                    getDeviceName().string());
             mDeviceMode = DEVICE_MODE_DISABLED;
             return;
         }
-    }
-
-    // Configure dimensions.
-    int32_t width, height, orientation;
-    if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
-        width = mAssociatedDisplayWidth;
-        height = mAssociatedDisplayHeight;
-        orientation = mParameters.orientationAware ?
-                mAssociatedDisplayOrientation : DISPLAY_ORIENTATION_0;
     } else {
-        width = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
-        height = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
-        orientation = DISPLAY_ORIENTATION_0;
+        newViewport.setNonDisplayViewport(rawWidth, rawHeight);
+    }
+    if (mViewport != newViewport) {
+        mViewport = newViewport;
+        viewportChanged = true;
+
+        if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
+            // Convert rotated viewport to natural surface coordinates.
+            int32_t naturalLogicalWidth, naturalLogicalHeight;
+            int32_t naturalPhysicalWidth, naturalPhysicalHeight;
+            int32_t naturalPhysicalLeft, naturalPhysicalTop;
+            int32_t naturalDeviceWidth, naturalDeviceHeight;
+            switch (mViewport.orientation) {
+            case DISPLAY_ORIENTATION_90:
+                naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
+                naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
+                naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
+                naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
+                naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
+                naturalPhysicalTop = mViewport.physicalLeft;
+                naturalDeviceWidth = mViewport.deviceHeight;
+                naturalDeviceHeight = mViewport.deviceWidth;
+                break;
+            case DISPLAY_ORIENTATION_180:
+                naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
+                naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
+                naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
+                naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
+                naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight;
+                naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom;
+                naturalDeviceWidth = mViewport.deviceWidth;
+                naturalDeviceHeight = mViewport.deviceHeight;
+                break;
+            case DISPLAY_ORIENTATION_270:
+                naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
+                naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
+                naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
+                naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
+                naturalPhysicalLeft = mViewport.physicalTop;
+                naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
+                naturalDeviceWidth = mViewport.deviceHeight;
+                naturalDeviceHeight = mViewport.deviceWidth;
+                break;
+            case DISPLAY_ORIENTATION_0:
+            default:
+                naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
+                naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
+                naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
+                naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
+                naturalPhysicalLeft = mViewport.physicalLeft;
+                naturalPhysicalTop = mViewport.physicalTop;
+                naturalDeviceWidth = mViewport.deviceWidth;
+                naturalDeviceHeight = mViewport.deviceHeight;
+                break;
+            }
+
+            mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
+            mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
+            mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
+            mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight;
+
+            mSurfaceOrientation = mParameters.orientationAware ?
+                    mViewport.orientation : DISPLAY_ORIENTATION_0;
+        } else {
+            mSurfaceWidth = rawWidth;
+            mSurfaceHeight = rawHeight;
+            mSurfaceLeft = 0;
+            mSurfaceTop = 0;
+            mSurfaceOrientation = DISPLAY_ORIENTATION_0;
+        }
     }
 
     // If moving between pointer modes, need to reset some state.
@@ -2926,22 +3004,17 @@
         mPointerController.clear();
     }
 
-    bool orientationChanged = mSurfaceOrientation != orientation;
-    if (orientationChanged) {
-        mSurfaceOrientation = orientation;
-    }
-
-    bool sizeChanged = mSurfaceWidth != width || mSurfaceHeight != height;
-    if (sizeChanged || deviceModeChanged) {
-        ALOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d, mode is %d",
-                getDeviceId(), getDeviceName().string(), width, height, mDeviceMode);
-
-        mSurfaceWidth = width;
-        mSurfaceHeight = height;
+    if (viewportChanged || deviceModeChanged) {
+        ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
+                "display id %d",
+                getDeviceId(), getDeviceName().string(), mSurfaceWidth, mSurfaceHeight,
+                mSurfaceOrientation, mDeviceMode, mViewport.displayId);
 
         // Configure X and Y factors.
-        mXScale = float(width) / (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1);
-        mYScale = float(height) / (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1);
+        mXScale = float(mSurfaceWidth) / rawWidth;
+        mYScale = float(mSurfaceHeight) / rawHeight;
+        mXTranslate = -mSurfaceLeft;
+        mYTranslate = -mSurfaceTop;
         mXPrecision = 1.0f / mXScale;
         mYPrecision = 1.0f / mYScale;
 
@@ -2958,7 +3031,7 @@
         mGeometricScale = avg(mXScale, mYScale);
 
         // Size of diagonal axis.
-        float diagonalSize = hypotf(width, height);
+        float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight);
 
         // Size factors.
         if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
@@ -3051,7 +3124,6 @@
         }
 
         // Orientation
-        mOrientationCenter = 0;
         mOrientationScale = 0;
         if (mHaveTilt) {
             mOrientedRanges.haveOrientation = true;
@@ -3067,10 +3139,13 @@
             if (mCalibration.orientationCalibration
                     == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
                 if (mRawPointerAxes.orientation.valid) {
-                    mOrientationCenter = avg(mRawPointerAxes.orientation.minValue,
-                            mRawPointerAxes.orientation.maxValue);
-                    mOrientationScale = M_PI / (mRawPointerAxes.orientation.maxValue -
-                            mRawPointerAxes.orientation.minValue);
+                    if (mRawPointerAxes.orientation.maxValue > 0) {
+                        mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
+                    } else if (mRawPointerAxes.orientation.minValue < 0) {
+                        mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue;
+                    } else {
+                        mOrientationScale = 0;
+                    }
                 }
             }
 
@@ -3108,50 +3183,38 @@
             mOrientedRanges.distance.fuzz =
                     mRawPointerAxes.distance.fuzz * mDistanceScale;
         }
-    }
 
-    if (orientationChanged || sizeChanged || deviceModeChanged) {
-        // Compute oriented surface dimensions, precision, scales and ranges.
+        // Compute oriented precision, scales and ranges.
         // Note that the maximum value reported is an inclusive maximum value so it is one
         // unit less than the total width or height of surface.
         switch (mSurfaceOrientation) {
         case DISPLAY_ORIENTATION_90:
         case DISPLAY_ORIENTATION_270:
-            mOrientedSurfaceWidth = mSurfaceHeight;
-            mOrientedSurfaceHeight = mSurfaceWidth;
-
             mOrientedXPrecision = mYPrecision;
             mOrientedYPrecision = mXPrecision;
 
-            mOrientedRanges.x.min = 0;
-            mOrientedRanges.x.max = (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue)
-                    * mYScale;
+            mOrientedRanges.x.min = mYTranslate;
+            mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1;
             mOrientedRanges.x.flat = 0;
             mOrientedRanges.x.fuzz = mYScale;
 
-            mOrientedRanges.y.min = 0;
-            mOrientedRanges.y.max = (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue)
-                    * mXScale;
+            mOrientedRanges.y.min = mXTranslate;
+            mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1;
             mOrientedRanges.y.flat = 0;
             mOrientedRanges.y.fuzz = mXScale;
             break;
 
         default:
-            mOrientedSurfaceWidth = mSurfaceWidth;
-            mOrientedSurfaceHeight = mSurfaceHeight;
-
             mOrientedXPrecision = mXPrecision;
             mOrientedYPrecision = mYPrecision;
 
-            mOrientedRanges.x.min = 0;
-            mOrientedRanges.x.max = (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue)
-                    * mXScale;
+            mOrientedRanges.x.min = mXTranslate;
+            mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1;
             mOrientedRanges.x.flat = 0;
             mOrientedRanges.x.fuzz = mXScale;
 
-            mOrientedRanges.y.min = 0;
-            mOrientedRanges.y.max = (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue)
-                    * mYScale;
+            mOrientedRanges.y.min = mYTranslate;
+            mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1;
             mOrientedRanges.y.flat = 0;
             mOrientedRanges.y.fuzz = mYScale;
             break;
@@ -3159,11 +3222,8 @@
 
         // Compute pointer gesture detection parameters.
         if (mDeviceMode == DEVICE_MODE_POINTER) {
-            int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
-            int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
             float rawDiagonal = hypotf(rawWidth, rawHeight);
-            float displayDiagonal = hypotf(mAssociatedDisplayWidth,
-                    mAssociatedDisplayHeight);
+            float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight);
 
             // Scale movements such that one whole swipe of the touch pad covers a
             // given area relative to the diagonal size of the display when no acceleration
@@ -3198,8 +3258,21 @@
 }
 
 void TouchInputMapper::dumpSurface(String8& dump) {
+    dump.appendFormat(INDENT3 "Viewport: displayId=%d, orientation=%d, "
+            "logicalFrame=[%d, %d, %d, %d], "
+            "physicalFrame=[%d, %d, %d, %d], "
+            "deviceSize=[%d, %d]\n",
+            mViewport.displayId, mViewport.orientation,
+            mViewport.logicalLeft, mViewport.logicalTop,
+            mViewport.logicalRight, mViewport.logicalBottom,
+            mViewport.physicalLeft, mViewport.physicalTop,
+            mViewport.physicalRight, mViewport.physicalBottom,
+            mViewport.deviceWidth, mViewport.deviceHeight);
+
     dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
     dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
+    dump.appendFormat(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
+    dump.appendFormat(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
     dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
 }
 
@@ -3284,6 +3357,8 @@
             out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
         } else if (sizeCalibrationString == "diameter") {
             out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
+        } else if (sizeCalibrationString == "box") {
+            out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX;
         } else if (sizeCalibrationString == "area") {
             out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
         } else if (sizeCalibrationString != "default") {
@@ -3404,6 +3479,9 @@
     case Calibration::SIZE_CALIBRATION_DIAMETER:
         dump.append(INDENT4 "touch.size.calibration: diameter\n");
         break;
+    case Calibration::SIZE_CALIBRATION_BOX:
+        dump.append(INDENT4 "touch.size.calibration: box\n");
+        break;
     case Calibration::SIZE_CALIBRATION_AREA:
         dump.append(INDENT4 "touch.size.calibration: area\n");
         break;
@@ -3954,6 +4032,7 @@
         switch (mCalibration.sizeCalibration) {
         case Calibration::SIZE_CALIBRATION_GEOMETRIC:
         case Calibration::SIZE_CALIBRATION_DIAMETER:
+        case Calibration::SIZE_CALIBRATION_BOX:
         case Calibration::SIZE_CALIBRATION_AREA:
             if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
                 touchMajor = in.touchMajor;
@@ -4050,7 +4129,7 @@
 
             switch (mCalibration.orientationCalibration) {
             case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
-                orientation = (in.orientation - mOrientationCenter) * mOrientationScale;
+                orientation = in.orientation * mOrientationScale;
                 break;
             case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
                 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
@@ -4088,28 +4167,28 @@
         float x, y;
         switch (mSurfaceOrientation) {
         case DISPLAY_ORIENTATION_90:
-            x = float(in.y - mRawPointerAxes.y.minValue) * mYScale;
-            y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale;
+            x = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+            y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate;
             orientation -= M_PI_2;
             if (orientation < - M_PI_2) {
                 orientation += M_PI;
             }
             break;
         case DISPLAY_ORIENTATION_180:
-            x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale;
-            y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale;
+            x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate;
+            y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
             break;
         case DISPLAY_ORIENTATION_270:
-            x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale;
-            y = float(in.x - mRawPointerAxes.x.minValue) * mXScale;
+            x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
+            y = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
             orientation += M_PI_2;
             if (orientation > M_PI_2) {
                 orientation -= M_PI;
             }
             break;
         default:
-            x = float(in.x - mRawPointerAxes.x.minValue) * mXScale;
-            y = float(in.y - mRawPointerAxes.y.minValue) * mYScale;
+            x = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+            y = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
             break;
         }
 
@@ -4365,7 +4444,8 @@
         NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
                 AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
                 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
-                1, &pointerProperties, &pointerCoords, 0, 0, mPointerGesture.downTime);
+                mViewport.displayId, 1, &pointerProperties, &pointerCoords,
+                0, 0, mPointerGesture.downTime);
         getListener()->notifyMotion(&args);
     }
 
@@ -5273,6 +5353,7 @@
         // Send up.
         NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
                  AMOTION_EVENT_ACTION_UP, 0, metaState, mLastButtonState, 0,
+                 mViewport.displayId,
                  1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
                  mOrientedXPrecision, mOrientedYPrecision,
                  mPointerSimple.downTime);
@@ -5285,6 +5366,7 @@
         // Send hover exit.
         NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
                 AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
+                mViewport.displayId,
                 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
                 mOrientedXPrecision, mOrientedYPrecision,
                 mPointerSimple.downTime);
@@ -5299,6 +5381,7 @@
             // Send down.
             NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
                     AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentButtonState, 0,
+                    mViewport.displayId,
                     1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
                     mOrientedXPrecision, mOrientedYPrecision,
                     mPointerSimple.downTime);
@@ -5308,6 +5391,7 @@
         // Send move.
         NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
                 AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentButtonState, 0,
+                mViewport.displayId,
                 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
                 mOrientedXPrecision, mOrientedYPrecision,
                 mPointerSimple.downTime);
@@ -5321,6 +5405,7 @@
             // Send hover enter.
             NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
                     AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
+                    mViewport.displayId,
                     1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
                     mOrientedXPrecision, mOrientedYPrecision,
                     mPointerSimple.downTime);
@@ -5330,6 +5415,7 @@
         // Send hover move.
         NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
                 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
+                mViewport.displayId,
                 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
                 mOrientedXPrecision, mOrientedYPrecision,
                 mPointerSimple.downTime);
@@ -5350,6 +5436,7 @@
 
         NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
                 AMOTION_EVENT_ACTION_SCROLL, 0, metaState, mCurrentButtonState, 0,
+                mViewport.displayId,
                 1, &mPointerSimple.currentProperties, &pointerCoords,
                 mOrientedXPrecision, mOrientedYPrecision,
                 mPointerSimple.downTime);
@@ -5411,7 +5498,8 @@
 
     NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
             action, flags, metaState, buttonState, edgeFlags,
-            pointerCount, pointerProperties, pointerCoords, xPrecision, yPrecision, downTime);
+            mViewport.displayId, pointerCount, pointerProperties, pointerCoords,
+            xPrecision, yPrecision, downTime);
     getListener()->notifyMotion(&args);
 }
 
@@ -6214,7 +6302,7 @@
         }
     }
 
-    // Moving a joystick axis should not wake the devide because joysticks can
+    // Moving a joystick axis should not wake the device because joysticks can
     // be fairly noisy even when not in use.  On the other hand, pushing a gamepad
     // button will likely wake the device.
     // TODO: Use the input device configuration to control this behavior more finely.
@@ -6222,7 +6310,7 @@
 
     NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
             AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
-            1, &pointerProperties, &pointerCoords, 0, 0, 0);
+            ADISPLAY_ID_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, 0);
     getListener()->notifyMotion(&args);
 }
 
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 122a2ab..61b21e2 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -24,7 +24,6 @@
 #include <androidfw/Input.h>
 #include <androidfw/VelocityControl.h>
 #include <androidfw/VelocityTracker.h>
-#include <ui/DisplayInfo.h>
 #include <utils/KeyedVector.h>
 #include <utils/threads.h>
 #include <utils/Timers.h>
@@ -48,6 +47,69 @@
 class InputDevice;
 class InputMapper;
 
+/*
+ * Describes how coordinates are mapped on a physical display.
+ * See com.android.server.display.DisplayViewport.
+ */
+struct DisplayViewport {
+    int32_t displayId; // -1 if invalid
+    int32_t orientation;
+    int32_t logicalLeft;
+    int32_t logicalTop;
+    int32_t logicalRight;
+    int32_t logicalBottom;
+    int32_t physicalLeft;
+    int32_t physicalTop;
+    int32_t physicalRight;
+    int32_t physicalBottom;
+    int32_t deviceWidth;
+    int32_t deviceHeight;
+
+    DisplayViewport() :
+            displayId(ADISPLAY_ID_NONE), orientation(DISPLAY_ORIENTATION_0),
+            logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0),
+            physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0),
+            deviceWidth(0), deviceHeight(0) {
+    }
+
+    bool operator==(const DisplayViewport& other) const {
+        return displayId == other.displayId
+                && orientation == other.orientation
+                && logicalLeft == other.logicalLeft
+                && logicalTop == other.logicalTop
+                && logicalRight == other.logicalRight
+                && logicalBottom == other.logicalBottom
+                && physicalLeft == other.physicalLeft
+                && physicalTop == other.physicalTop
+                && physicalRight == other.physicalRight
+                && physicalBottom == other.physicalBottom
+                && deviceWidth == other.deviceWidth
+                && deviceHeight == other.deviceHeight;
+    }
+
+    bool operator!=(const DisplayViewport& other) const {
+        return !(*this == other);
+    }
+
+    inline bool isValid() const {
+        return displayId >= 0;
+    }
+
+    void setNonDisplayViewport(int32_t width, int32_t height) {
+        displayId = ADISPLAY_ID_NONE;
+        orientation = DISPLAY_ORIENTATION_0;
+        logicalLeft = 0;
+        logicalTop = 0;
+        logicalRight = width;
+        logicalBottom = height;
+        physicalLeft = 0;
+        physicalTop = 0;
+        physicalRight = width;
+        physicalBottom = height;
+        deviceWidth = width;
+        deviceHeight = height;
+    }
+};
 
 /*
  * Input reader configuration.
@@ -180,25 +242,12 @@
             pointerGestureZoomSpeedRatio(0.3f),
             showTouches(false) { }
 
-    bool getDisplayInfo(int32_t displayId, bool external,
-            int32_t* width, int32_t* height, int32_t* orientation) const;
-
-    void setDisplayInfo(int32_t displayId, bool external,
-            int32_t width, int32_t height, int32_t orientation);
+    bool getDisplayInfo(bool external, DisplayViewport* outViewport) const;
+    void setDisplayInfo(bool external, const DisplayViewport& viewport);
 
 private:
-    struct DisplayInfo {
-        int32_t width;
-        int32_t height;
-        int32_t orientation;
-
-        DisplayInfo() :
-            width(-1), height(-1), orientation(DISPLAY_ORIENTATION_0) {
-        }
-    };
-
-    DisplayInfo mInternalDisplay;
-    DisplayInfo mExternalDisplay;
+    DisplayViewport mInternalDisplay;
+    DisplayViewport mExternalDisplay;
 };
 
 
@@ -913,7 +962,11 @@
     virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
 
 private:
-    void processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue);
+    uint32_t mUpdatedSwitchValues;
+    uint32_t mUpdatedSwitchMask;
+
+    void processSwitch(int32_t switchCode, int32_t switchValue);
+    void sync(nsecs_t when);
 };
 
 
@@ -992,7 +1045,7 @@
 
     // Immutable configuration parameters.
     struct Parameters {
-        int32_t associatedDisplayId;
+        bool hasAssociatedDisplay;
         bool orientationAware;
     } mParameters;
 
@@ -1042,7 +1095,7 @@
         };
 
         Mode mode;
-        int32_t associatedDisplayId;
+        bool hasAssociatedDisplay;
         bool orientationAware;
     } mParameters;
 
@@ -1143,7 +1196,7 @@
         };
 
         DeviceType deviceType;
-        int32_t associatedDisplayId;
+        bool hasAssociatedDisplay;
         bool associatedDisplayIsExternal;
         bool orientationAware;
 
@@ -1162,6 +1215,7 @@
             SIZE_CALIBRATION_NONE,
             SIZE_CALIBRATION_GEOMETRIC,
             SIZE_CALIBRATION_DIAMETER,
+            SIZE_CALIBRATION_BOX,
             SIZE_CALIBRATION_AREA,
         };
 
@@ -1271,20 +1325,30 @@
     virtual void syncTouch(nsecs_t when, bool* outHavePointerIds) = 0;
 
 private:
-    // The surface orientation and width and height set by configureSurface().
-    int32_t mSurfaceOrientation;
+    // The current viewport.
+    // The components of the viewport are specified in the display's rotated orientation.
+    DisplayViewport mViewport;
+
+    // The surface orientation, width and height set by configureSurface().
+    // The width and height are derived from the viewport but are specified
+    // in the natural orientation.
+    // The surface origin specifies how the surface coordinates should be translated
+    // to align with the logical display coordinate space.
+    // The orientation may be different from the viewport orientation as it specifies
+    // the rotation of the surface coordinates required to produce the viewport's
+    // requested orientation, so it will depend on whether the device is orientation aware.
     int32_t mSurfaceWidth;
     int32_t mSurfaceHeight;
-
-    // The associated display orientation and width and height set by configureSurface().
-    int32_t mAssociatedDisplayOrientation;
-    int32_t mAssociatedDisplayWidth;
-    int32_t mAssociatedDisplayHeight;
+    int32_t mSurfaceLeft;
+    int32_t mSurfaceTop;
+    int32_t mSurfaceOrientation;
 
     // Translation and scaling factors, orientation-independent.
+    float mXTranslate;
     float mXScale;
     float mXPrecision;
 
+    float mYTranslate;
     float mYScale;
     float mYPrecision;
 
@@ -1294,7 +1358,6 @@
 
     float mSizeScale;
 
-    float mOrientationCenter;
     float mOrientationScale;
 
     float mDistanceScale;
@@ -1346,8 +1409,6 @@
     } mOrientedRanges;
 
     // Oriented dimensions and precision.
-    float mOrientedSurfaceWidth;
-    float mOrientedSurfaceHeight;
     float mOrientedXPrecision;
     float mOrientedYPrecision;
 
diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h
index 824a64b..7bd3af7 100644
--- a/services/input/InputWindow.h
+++ b/services/input/InputWindow.h
@@ -110,6 +110,8 @@
 
     enum {
         INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES = 0x00000001,
+        INPUT_FEATURE_NO_INPUT_CHANNEL = 0x00000002,
+        INPUT_FEATURE_DISABLE_USER_ACTIVITY = 0x00000004,
     };
 
     sp<InputChannel> inputChannel;
@@ -132,6 +134,7 @@
     int32_t ownerPid;
     int32_t ownerUid;
     int32_t inputFeatures;
+    int32_t displayId;
 
     bool touchableRegionContainsPoint(int32_t x, int32_t y) const;
     bool frameContainsPoint(int32_t x, int32_t y) const;
diff --git a/services/input/PointerController.cpp b/services/input/PointerController.cpp
index fc828a6..9af521b 100644
--- a/services/input/PointerController.cpp
+++ b/services/input/PointerController.cpp
@@ -307,9 +307,17 @@
     }
 }
 
-void PointerController::setDisplaySize(int32_t width, int32_t height) {
+void PointerController::setDisplayViewport(int32_t width, int32_t height, int32_t orientation) {
     AutoMutex _l(mLock);
 
+    // Adjust to use the display's unrotated coordinate frame.
+    if (orientation == DISPLAY_ORIENTATION_90
+            || orientation == DISPLAY_ORIENTATION_270) {
+        int32_t temp = height;
+        height = width;
+        width = temp;
+    }
+
     if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
         mLocked.displayWidth = width;
         mLocked.displayHeight = height;
@@ -324,12 +332,7 @@
         }
 
         fadeOutAndReleaseAllSpotsLocked();
-        updatePointerLocked();
     }
-}
-
-void PointerController::setDisplayOrientation(int32_t orientation) {
-    AutoMutex _l(mLock);
 
     if (mLocked.displayOrientation != orientation) {
         // Apply offsets to convert from the pixel top-left corner position to the pixel center.
@@ -380,9 +383,9 @@
         mLocked.pointerX = x - 0.5f;
         mLocked.pointerY = y - 0.5f;
         mLocked.displayOrientation = orientation;
-
-        updatePointerLocked();
     }
+
+    updatePointerLocked();
 }
 
 void PointerController::setPointerIcon(const SpriteIcon& icon) {
diff --git a/services/input/PointerController.h b/services/input/PointerController.h
index 4c307c4..fd68b61 100644
--- a/services/input/PointerController.h
+++ b/services/input/PointerController.h
@@ -170,8 +170,7 @@
             const uint32_t* spotIdToIndex, BitSet32 spotIdBits);
     virtual void clearSpots();
 
-    void setDisplaySize(int32_t width, int32_t height);
-    void setDisplayOrientation(int32_t orientation);
+    void setDisplayViewport(int32_t width, int32_t height, int32_t orientation);
     void setPointerIcon(const SpriteIcon& icon);
     void setInactivityTimeout(InactivityTimeout inactivityTimeout);
 
diff --git a/services/input/SpriteController.cpp b/services/input/SpriteController.cpp
index b15d4c8..1f3d2cf 100644
--- a/services/input/SpriteController.cpp
+++ b/services/input/SpriteController.cpp
@@ -298,7 +298,7 @@
             }
 
             if (becomingVisible) {
-                status = update.state.surfaceControl->show(surfaceLayer);
+                status = update.state.surfaceControl->show();
                 if (status) {
                     ALOGE("Error %d showing sprite surface.", status);
                 } else {
@@ -369,7 +369,8 @@
     ensureSurfaceComposerClient();
 
     sp<SurfaceControl> surfaceControl = mSurfaceComposerClient->createSurface(
-            String8("Sprite"), 0, width, height, PIXEL_FORMAT_RGBA_8888);
+            String8("Sprite"), width, height, PIXEL_FORMAT_RGBA_8888,
+            ISurfaceComposerClient::eHidden);
     if (surfaceControl == NULL || !surfaceControl->isValid()
             || !surfaceControl->getSurface()->isValid()) {
         ALOGE("Error creating sprite surface.");
diff --git a/services/input/tests/InputDispatcher_test.cpp b/services/input/tests/InputDispatcher_test.cpp
index 961566f..ed2b4a5 100644
--- a/services/input/tests/InputDispatcher_test.cpp
+++ b/services/input/tests/InputDispatcher_test.cpp
@@ -86,7 +86,7 @@
     }
 
     virtual void notifySwitch(nsecs_t when,
-            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
+            uint32_t switchValues, uint32_t switchMask, uint32_t policyFlags) {
     }
 
     virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index abda10b..14065d2 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -138,8 +138,23 @@
 
     void setDisplayInfo(int32_t displayId, int32_t width, int32_t height, int32_t orientation) {
         // Set the size of both the internal and external display at the same time.
-        mConfig.setDisplayInfo(displayId, false /*external*/, width, height, orientation);
-        mConfig.setDisplayInfo(displayId, true /*external*/, width, height, orientation);
+        bool isRotated = (orientation == DISPLAY_ORIENTATION_90
+                || orientation == DISPLAY_ORIENTATION_270);
+        DisplayViewport v;
+        v.displayId = displayId;
+        v.orientation = orientation;
+        v.logicalLeft = 0;
+        v.logicalTop = 0;
+        v.logicalRight = isRotated ? height : width;
+        v.logicalBottom = isRotated ? width : height;
+        v.physicalLeft = 0;
+        v.physicalTop = 0;
+        v.physicalRight = isRotated ? height : width;
+        v.physicalBottom = isRotated ? width : height;
+        v.deviceWidth = isRotated ? height : width;
+        v.deviceHeight = isRotated ? width : height;
+        mConfig.setDisplayInfo(false /*external*/, v);
+        mConfig.setDisplayInfo(true /*external*/, v);
     }
 
     void addExcludedDeviceName(const String8& deviceName) {
@@ -474,6 +489,7 @@
                 return OK;
             }
         }
+        outAxisInfo->clear();
         return -1;
     }
 
@@ -1477,12 +1493,16 @@
     addMapperAndConfigure(mapper);
 
     process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_LID, 1);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_JACK_PHYSICAL_INSERT, 1);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_HEADPHONE_INSERT, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
 
     NotifySwitchArgs args;
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySwitchWasCalled(&args));
     ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-    ASSERT_EQ(SW_LID, args.switchCode);
-    ASSERT_EQ(1, args.switchValue);
+    ASSERT_EQ((1 << SW_LID) | (1 << SW_JACK_PHYSICAL_INSERT), args.switchValues);
+    ASSERT_EQ((1 << SW_LID) | (1 << SW_JACK_PHYSICAL_INSERT) | (1 << SW_HEADPHONE_INSERT),
+            args.switchMask);
     ASSERT_EQ(uint32_t(0), args.policyFlags);
 }
 
diff --git a/services/java/Android.mk b/services/java/Android.mk
index e70a6c9..95b28d9 100644
--- a/services/java/Android.mk
+++ b/services/java/Android.mk
@@ -13,9 +13,6 @@
 
 LOCAL_JAVA_LIBRARIES := android.policy telephony-common
 
-LOCAL_NO_EMMA_INSTRUMENT := true
-LOCAL_NO_EMMA_COMPILE := true
-
 include $(BUILD_JAVA_LIBRARY)
 
 include $(BUILD_DROIDDOC)
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 32ac8e1..440f8e1 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -34,6 +34,7 @@
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.os.WorkSource;
 import android.text.TextUtils;
 import android.text.format.Time;
@@ -129,12 +130,14 @@
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
         
-        mTimeTickSender = PendingIntent.getBroadcast(context, 0,
+        mTimeTickSender = PendingIntent.getBroadcastAsUser(context, 0,
                 new Intent(Intent.ACTION_TIME_TICK).addFlags(
-                        Intent.FLAG_RECEIVER_REGISTERED_ONLY), 0);
+                        Intent.FLAG_RECEIVER_REGISTERED_ONLY), 0,
+                        UserHandle.ALL);
         Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
-        mDateChangeSender = PendingIntent.getBroadcast(context, 0, intent, 0);
+        mDateChangeSender = PendingIntent.getBroadcastAsUser(context, 0, intent,
+                Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
         
         // now that we have initied the driver schedule the alarm
         mClockReceiver= new ClockReceiver();
@@ -242,32 +245,39 @@
                 "android.permission.SET_TIME_ZONE",
                 "setTimeZone");
 
-        if (TextUtils.isEmpty(tz)) return;
-        TimeZone zone = TimeZone.getTimeZone(tz);
-        // Prevent reentrant calls from stepping on each other when writing
-        // the time zone property
-        boolean timeZoneWasChanged = false;
-        synchronized (this) {
-            String current = SystemProperties.get(TIMEZONE_PROPERTY);
-            if (current == null || !current.equals(zone.getID())) {
-                if (localLOGV) Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID());
-                timeZoneWasChanged = true; 
-                SystemProperties.set(TIMEZONE_PROPERTY, zone.getID());
-            }
-            
-            // Update the kernel timezone information
-            // Kernel tracks time offsets as 'minutes west of GMT'
-            int gmtOffset = zone.getOffset(System.currentTimeMillis());
-            setKernelTimezone(mDescriptor, -(gmtOffset / 60000));
-        }
+        long oldId = Binder.clearCallingIdentity();
+        try {
+            if (TextUtils.isEmpty(tz)) return;
+            TimeZone zone = TimeZone.getTimeZone(tz);
+            // Prevent reentrant calls from stepping on each other when writing
+            // the time zone property
+            boolean timeZoneWasChanged = false;
+            synchronized (this) {
+                String current = SystemProperties.get(TIMEZONE_PROPERTY);
+                if (current == null || !current.equals(zone.getID())) {
+                    if (localLOGV) {
+                        Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID());
+                    }
+                    timeZoneWasChanged = true;
+                    SystemProperties.set(TIMEZONE_PROPERTY, zone.getID());
+                }
 
-        TimeZone.setDefault(null);
-        
-        if (timeZoneWasChanged) {
-            Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
-            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
-            intent.putExtra("time-zone", zone.getID());
-            mContext.sendBroadcast(intent);
+                // Update the kernel timezone information
+                // Kernel tracks time offsets as 'minutes west of GMT'
+                int gmtOffset = zone.getOffset(System.currentTimeMillis());
+                setKernelTimezone(mDescriptor, -(gmtOffset / 60000));
+            }
+
+            TimeZone.setDefault(null);
+
+            if (timeZoneWasChanged) {
+                Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
+                intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+                intent.putExtra("time-zone", zone.getID());
+                mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(oldId);
         }
     }
     
@@ -303,7 +313,7 @@
             }
         }
     }
-    
+
     public void removeLocked(String packageName) {
         removeLocked(mRtcWakeupAlarms, packageName);
         removeLocked(mRtcAlarms, packageName);
@@ -327,6 +337,29 @@
             }
         }
     }
+
+    public void removeUserLocked(int userHandle) {
+        removeUserLocked(mRtcWakeupAlarms, userHandle);
+        removeUserLocked(mRtcAlarms, userHandle);
+        removeUserLocked(mElapsedRealtimeWakeupAlarms, userHandle);
+        removeUserLocked(mElapsedRealtimeAlarms, userHandle);
+    }
+
+    private void removeUserLocked(ArrayList<Alarm> alarmList, int userHandle) {
+        if (alarmList.size() <= 0) {
+            return;
+        }
+
+        // iterator over the list removing any it where the intent match
+        Iterator<Alarm> it = alarmList.iterator();
+
+        while (it.hasNext()) {
+            Alarm alarm = it.next();
+            if (UserHandle.getUserId(alarm.operation.getCreatorUid()) == userHandle) {
+                it.remove();
+            }
+        }
+    }
     
     public boolean lookForPackageLocked(String packageName) {
         return lookForPackageLocked(mRtcWakeupAlarms, packageName)
@@ -637,7 +670,7 @@
                     Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
                     intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
                             | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-                    mContext.sendBroadcast(intent);
+                    mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
                 }
                 
                 synchronized (mLock) {
@@ -822,6 +855,7 @@
              // Register for events related to sdcard installation.
             IntentFilter sdFilter = new IntentFilter();
             sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+            sdFilter.addAction(Intent.ACTION_USER_STOPPED);
             mContext.registerReceiver(this, sdFilter);
         }
         
@@ -841,6 +875,11 @@
                     return;
                 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
+                    int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+                    if (userHandle >= 0) {
+                        removeUserLocked(userHandle);
+                    }
                 } else {
                     if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
                             && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 38f4554..06d37dc 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -16,33 +16,29 @@
 
 package com.android.server;
 
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.appwidget.AppWidgetManager;
+import android.app.ActivityManagerNative;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.util.Pair;
+import android.os.UserHandle;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.widget.RemoteViews;
 
 import com.android.internal.appwidget.IAppWidgetHost;
 import com.android.internal.appwidget.IAppWidgetService;
-import com.android.internal.widget.IRemoteViewsAdapterConnection;
+import com.android.internal.util.IndentingPrintWriter;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 
@@ -54,85 +50,11 @@
 {
     private static final String TAG = "AppWidgetService";
 
-    /*
-     * When identifying a Host or Provider based on the calling process, use the uid field.
-     * When identifying a Host or Provider based on a package manager broadcast, use the
-     * package given.
-     */
-
-    static class Provider {
-        int uid;
-        AppWidgetProviderInfo info;
-        ArrayList<AppWidgetId> instances = new ArrayList<AppWidgetId>();
-        PendingIntent broadcast;
-        boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
-        
-        int tag;    // for use while saving state (the index)
-    }
-
-    static class Host {
-        int uid;
-        int hostId;
-        String packageName;
-        ArrayList<AppWidgetId> instances = new ArrayList<AppWidgetId>();
-        IAppWidgetHost callbacks;
-        boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
-        
-        int tag;    // for use while saving state (the index)
-    }
-
-    static class AppWidgetId {
-        int appWidgetId;
-        Provider provider;
-        RemoteViews views;
-        Host host;
-    }
-
-    /**
-     * Acts as a proxy between the ServiceConnection and the RemoteViewsAdapterConnection.
-     * This needs to be a static inner class since a reference to the ServiceConnection is held
-     * globally and may lead us to leak AppWidgetService instances (if there were more than one).
-     */
-    static class ServiceConnectionProxy implements ServiceConnection {
-        private final IBinder mConnectionCb;
-
-        ServiceConnectionProxy(Pair<Integer, Intent.FilterComparison> key, IBinder connectionCb) {
-            mConnectionCb = connectionCb;
-        }
-        public void onServiceConnected(ComponentName name, IBinder service) {
-            final IRemoteViewsAdapterConnection cb =
-                IRemoteViewsAdapterConnection.Stub.asInterface(mConnectionCb);
-            try {
-                cb.onServiceConnected(service);
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-        }
-        public void onServiceDisconnected(ComponentName name) {
-            disconnect();
-        }
-        public void disconnect() {
-            final IRemoteViewsAdapterConnection cb =
-                IRemoteViewsAdapterConnection.Stub.asInterface(mConnectionCb);
-            try {
-                cb.onServiceDisconnected();
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-        }
-    }
-
     Context mContext;
     Locale mLocale;
     PackageManager mPackageManager;
-    AlarmManager mAlarmManager;
-    ArrayList<Provider> mInstalledProviders = new ArrayList<Provider>();
-    int mNextAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID + 1;
-    final ArrayList<AppWidgetId> mAppWidgetIds = new ArrayList<AppWidgetId>();
-    ArrayList<Host> mHosts = new ArrayList<Host>();
     boolean mSafeMode;
 
-
     private final SparseArray<AppWidgetServiceImpl> mAppWidgetServices;
 
     AppWidgetService(Context context) {
@@ -150,13 +72,13 @@
         // Register for the boot completed broadcast, so we can send the
         // ENABLE broacasts. If we try to send them now, they time out,
         // because the system isn't ready to handle them yet.
-        mContext.registerReceiver(mBroadcastReceiver,
+        mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
                 new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
 
         // Register for configuration changes so we can update the names
         // of the widgets when the locale changes.
-        mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(
-                Intent.ACTION_CONFIGURATION_CHANGED), null, null);
+        mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
+                new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED), null, null);
 
         // Register for broadcasts about package install, etc., so we can
         // update the provider list.
@@ -165,182 +87,241 @@
         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         filter.addDataScheme("package");
-        mContext.registerReceiver(mBroadcastReceiver, filter);
+        mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
+                filter, null, null);
         // Register for events related to sdcard installation.
         IntentFilter sdFilter = new IntentFilter();
         sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
         sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
-        mContext.registerReceiver(mBroadcastReceiver, sdFilter);
+        mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
+                sdFilter, null, null);
 
         IntentFilter userFilter = new IntentFilter();
         userFilter.addAction(Intent.ACTION_USER_REMOVED);
+        userFilter.addAction(Intent.ACTION_USER_STOPPING);
         mContext.registerReceiver(new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
-                onUserRemoved(intent.getIntExtra(Intent.EXTRA_USERID, -1));
+                if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
+                    onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+                            UserHandle.USER_NULL));
+                } else if (Intent.ACTION_USER_STOPPING.equals(intent.getAction())) {
+                    onUserStopping(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+                            UserHandle.USER_NULL));
+                }
             }
         }, userFilter);
     }
 
+    /**
+     * This returns the user id of the caller, if the caller is not the system process,
+     * otherwise it assumes that the calls are from the lockscreen and hence are meant for the
+     * current user. TODO: Instead, have lockscreen make explicit calls with userId
+     */
+    private int getCallingOrCurrentUserId() {
+        int callingUid = Binder.getCallingUid();
+        // Also check the PID because Settings (power control widget) also runs as System UID
+        if (callingUid == android.os.Process.myUid()
+                && Binder.getCallingPid() == android.os.Process.myPid()) {
+            try {
+                return ActivityManagerNative.getDefault().getCurrentUser().id;
+            } catch (RemoteException re) {
+                return UserHandle.getUserId(callingUid);
+            }
+        } else {
+            return UserHandle.getUserId(callingUid);
+        }
+    }
+
     @Override
     public int allocateAppWidgetId(String packageName, int hostId) throws RemoteException {
-        return getImplForUser().allocateAppWidgetId(packageName, hostId);
+        return getImplForUser(getCallingOrCurrentUserId()).allocateAppWidgetId(
+                packageName, hostId);
     }
     
     @Override
     public void deleteAppWidgetId(int appWidgetId) throws RemoteException {
-        getImplForUser().deleteAppWidgetId(appWidgetId);
+        getImplForUser(getCallingOrCurrentUserId()).deleteAppWidgetId(appWidgetId);
     }
 
     @Override
     public void deleteHost(int hostId) throws RemoteException {
-        getImplForUser().deleteHost(hostId);
+        getImplForUser(getCallingOrCurrentUserId()).deleteHost(hostId);
     }
 
     @Override
     public void deleteAllHosts() throws RemoteException {
-        getImplForUser().deleteAllHosts();
+        getImplForUser(getCallingOrCurrentUserId()).deleteAllHosts();
     }
 
     @Override
-    public void bindAppWidgetId(int appWidgetId, ComponentName provider) throws RemoteException {
-        getImplForUser().bindAppWidgetId(appWidgetId, provider);
+    public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options)
+            throws RemoteException {
+        getImplForUser(getCallingOrCurrentUserId()).bindAppWidgetId(appWidgetId, provider,
+                options);
     }
 
     @Override
     public boolean bindAppWidgetIdIfAllowed(
-            String packageName, int appWidgetId, ComponentName provider) throws RemoteException {
-        return getImplForUser().bindAppWidgetIdIfAllowed(packageName, appWidgetId, provider);
+            String packageName, int appWidgetId, ComponentName provider, Bundle options)
+                    throws RemoteException {
+        return getImplForUser(getCallingOrCurrentUserId()).bindAppWidgetIdIfAllowed(
+                packageName, appWidgetId, provider, options);
     }
 
     @Override
     public boolean hasBindAppWidgetPermission(String packageName) throws RemoteException {
-        return getImplForUser().hasBindAppWidgetPermission(packageName);
+        return getImplForUser(getCallingOrCurrentUserId()).hasBindAppWidgetPermission(
+                packageName);
     }
 
     @Override
     public void setBindAppWidgetPermission(String packageName, boolean permission)
             throws RemoteException {
-        getImplForUser().setBindAppWidgetPermission(packageName, permission);
+        getImplForUser(getCallingOrCurrentUserId()).setBindAppWidgetPermission(
+                packageName, permission);
     }
 
     @Override
     public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection)
             throws RemoteException {
-        getImplForUser().bindRemoteViewsService(appWidgetId, intent, connection);
+        getImplForUser(getCallingOrCurrentUserId()).bindRemoteViewsService(
+                appWidgetId, intent, connection);
     }
 
     @Override
     public int[] startListening(IAppWidgetHost host, String packageName, int hostId,
             List<RemoteViews> updatedViews) throws RemoteException {
-        return getImplForUser().startListening(host, packageName, hostId, updatedViews);
+        return getImplForUser(getCallingOrCurrentUserId()).startListening(host,
+                packageName, hostId, updatedViews);
     }
 
     public void onUserRemoved(int userId) {
-        AppWidgetServiceImpl impl = mAppWidgetServices.get(userId);
         if (userId < 1) return;
+        synchronized (mAppWidgetServices) {
+            AppWidgetServiceImpl impl = mAppWidgetServices.get(userId);
+            mAppWidgetServices.remove(userId);
 
-        if (impl == null) {
-            AppWidgetServiceImpl.getSettingsFile(userId).delete();
-        } else {
-            impl.onUserRemoved();
+            if (impl == null) {
+                AppWidgetServiceImpl.getSettingsFile(userId).delete();
+            } else {
+                impl.onUserRemoved();
+            }
         }
     }
 
-    private AppWidgetServiceImpl getImplForUser() {
-        final int userId = Binder.getOrigCallingUser();
-        AppWidgetServiceImpl service = mAppWidgetServices.get(userId);
-        if (service == null) {
-            Slog.e(TAG, "Unable to find AppWidgetServiceImpl for the current user");
-            // TODO: Verify that it's a valid user
-            service = new AppWidgetServiceImpl(mContext, userId);
-            service.systemReady(mSafeMode);
-            // Assume that BOOT_COMPLETED was received, as this is a non-primary user.
-            service.sendInitialBroadcasts();
-            mAppWidgetServices.append(userId, service);
+    public void onUserStopping(int userId) {
+        if (userId < 1) return;
+        synchronized (mAppWidgetServices) {
+            AppWidgetServiceImpl impl = mAppWidgetServices.get(userId);
+            if (impl != null) {
+                mAppWidgetServices.remove(userId);
+                impl.onUserStopping();
+            }
         }
+    }
 
+    private AppWidgetServiceImpl getImplForUser(int userId) {
+        boolean sendInitial = false;
+        AppWidgetServiceImpl service;
+        synchronized (mAppWidgetServices) {
+            service = mAppWidgetServices.get(userId);
+            if (service == null) {
+                Slog.i(TAG, "Unable to find AppWidgetServiceImpl for user " + userId + ", adding");
+                // TODO: Verify that it's a valid user
+                service = new AppWidgetServiceImpl(mContext, userId);
+                service.systemReady(mSafeMode);
+                // Assume that BOOT_COMPLETED was received, as this is a non-primary user.
+                mAppWidgetServices.append(userId, service);
+                sendInitial = true;
+            }
+        }
+        if (sendInitial) {
+            service.sendInitialBroadcasts();
+        }
         return service;
     }
 
     @Override
     public int[] getAppWidgetIds(ComponentName provider) throws RemoteException {
-        return getImplForUser().getAppWidgetIds(provider);
+        return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetIds(provider);
     }
 
     @Override
     public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) throws RemoteException {
-        return getImplForUser().getAppWidgetInfo(appWidgetId);
+        return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetInfo(appWidgetId);
     }
 
     @Override
     public RemoteViews getAppWidgetViews(int appWidgetId) throws RemoteException {
-        return getImplForUser().getAppWidgetViews(appWidgetId);
+        return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetViews(appWidgetId);
     }
 
     @Override
     public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
-        getImplForUser().updateAppWidgetOptions(appWidgetId, options);
+        getImplForUser(getCallingOrCurrentUserId()).updateAppWidgetOptions(appWidgetId, options);
     }
 
     @Override
     public Bundle getAppWidgetOptions(int appWidgetId) {
-        return getImplForUser().getAppWidgetOptions(appWidgetId);
-    }
-
-    static int[] getAppWidgetIds(Provider p) {
-        int instancesSize = p.instances.size();
-        int appWidgetIds[] = new int[instancesSize];
-        for (int i=0; i<instancesSize; i++) {
-            appWidgetIds[i] = p.instances.get(i).appWidgetId;
-        }
-        return appWidgetIds;
+        return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetOptions(appWidgetId);
     }
 
     @Override
     public List<AppWidgetProviderInfo> getInstalledProviders() throws RemoteException {
-        return getImplForUser().getInstalledProviders();
+        return getImplForUser(getCallingOrCurrentUserId()).getInstalledProviders();
     }
 
     @Override
     public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId)
             throws RemoteException {
-        getImplForUser().notifyAppWidgetViewDataChanged(appWidgetIds, viewId);
+        getImplForUser(getCallingOrCurrentUserId()).notifyAppWidgetViewDataChanged(
+                appWidgetIds, viewId);
     }
 
     @Override
     public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views)
             throws RemoteException {
-        getImplForUser().partiallyUpdateAppWidgetIds(appWidgetIds, views);
+        getImplForUser(getCallingOrCurrentUserId()).partiallyUpdateAppWidgetIds(
+                appWidgetIds, views);
     }
 
     @Override
     public void stopListening(int hostId) throws RemoteException {
-        getImplForUser().stopListening(hostId);
+        getImplForUser(getCallingOrCurrentUserId()).stopListening(hostId);
     }
 
     @Override
     public void unbindRemoteViewsService(int appWidgetId, Intent intent) throws RemoteException {
-        getImplForUser().unbindRemoteViewsService(appWidgetId, intent);
+        getImplForUser(getCallingOrCurrentUserId()).unbindRemoteViewsService(
+                appWidgetId, intent);
     }
 
     @Override
     public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views) throws RemoteException {
-        getImplForUser().updateAppWidgetIds(appWidgetIds, views);
+        getImplForUser(getCallingOrCurrentUserId()).updateAppWidgetIds(appWidgetIds, views);
     }
 
     @Override
     public void updateAppWidgetProvider(ComponentName provider, RemoteViews views)
             throws RemoteException {
-        getImplForUser().updateAppWidgetProvider(provider, views);
+        getImplForUser(getCallingOrCurrentUserId()).updateAppWidgetProvider(provider, views);
     }
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+
         // Dump the state of all the app widget providers
-        for (int i = 0; i < mAppWidgetServices.size(); i++) {
-            AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
-            service.dump(fd, pw, args);
+        synchronized (mAppWidgetServices) {
+            IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
+            for (int i = 0; i < mAppWidgetServices.size(); i++) {
+                pw.println("User: " + mAppWidgetServices.keyAt(i));
+                ipw.increaseIndent();
+                AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
+                service.dump(fd, ipw, args);
+                ipw.decreaseIndent();
+            }
         }
     }
 
@@ -349,16 +330,29 @@
             String action = intent.getAction();
             // Slog.d(TAG, "received " + action);
             if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
-                getImplForUser().sendInitialBroadcasts();
+                int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+                if (userId >= 0) {
+                    getImplForUser(userId).sendInitialBroadcasts();
+                } else {
+                    Slog.w(TAG, "Incorrect user handle supplied in " + intent);
+                }
             } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
                 for (int i = 0; i < mAppWidgetServices.size(); i++) {
                     AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
                     service.onConfigurationChanged();
                 }
             } else {
-                for (int i = 0; i < mAppWidgetServices.size(); i++) {
-                    AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
-                    service.onBroadcastReceived(intent);
+                int sendingUser = getSendingUserId();
+                if (sendingUser == UserHandle.USER_ALL) {
+                    for (int i = 0; i < mAppWidgetServices.size(); i++) {
+                        AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
+                        service.onBroadcastReceived(intent);
+                    }
+                } else {
+                    AppWidgetServiceImpl service = mAppWidgetServices.get(sendingUser);
+                    if (service != null) {
+                        service.onBroadcastReceived(intent);
+                    }
                 }
             }
         }
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index f9c432b..daa82f2 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -36,24 +36,28 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
+import android.graphics.Point;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Environment;
 import android.os.IBinder;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.UserId;
+import android.os.UserHandle;
+import android.util.AtomicFile;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.TypedValue;
 import android.util.Xml;
+import android.view.Display;
 import android.view.WindowManager;
 import android.widget.RemoteViews;
 
 import com.android.internal.appwidget.IAppWidgetHost;
-import com.android.internal.os.AtomicFile;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.widget.IRemoteViewsAdapterConnection;
 import com.android.internal.widget.IRemoteViewsFactory;
@@ -83,6 +87,8 @@
     private static final String SETTINGS_FILENAME = "appwidgets.xml";
     private static final int MIN_UPDATE_PERIOD = 30 * 60 * 1000; // 30 minutes
 
+    private static boolean DBG = false;
+
     /*
      * When identifying a Host or Provider based on the calling process, use the uid field. When
      * identifying a Host or Provider based on a package manager broadcast, use the package given.
@@ -188,11 +194,12 @@
 
     void computeMaximumWidgetBitmapMemory() {
         WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
-        int height = wm.getDefaultDisplay().getRawHeight();
-        int width = wm.getDefaultDisplay().getRawWidth();
+        Display display = wm.getDefaultDisplay();
+        Point size = new Point();
+        display.getRealSize(size);
         // Cap memory usage at 1.5 times the size of the display
         // 1.5 * 4 bytes/pixel * w * h ==> 6 * w * h
-        mMaxWidgetBitmapMemory = 6 * width * height;
+        mMaxWidgetBitmapMemory = 6 * size.x * size.y;
     }
 
     public void systemReady(boolean safeMode) {
@@ -203,18 +210,31 @@
         }
     }
 
+    private void log(String msg) {
+        Slog.i(TAG, "u=" + mUserId + ": " + msg);
+    }
+
     void onConfigurationChanged() {
+        if (DBG) log("Got onConfigurationChanged()");
         Locale revised = Locale.getDefault();
         if (revised == null || mLocale == null || !(revised.equals(mLocale))) {
             mLocale = revised;
 
             synchronized (mAppWidgetIds) {
                 ensureStateLoadedLocked();
-                int N = mInstalledProviders.size();
+                // Note: updateProvidersForPackageLocked() may remove providers, so we must copy the
+                // list of installed providers and skip providers that we don't need to update.
+                // Also note that remove the provider does not clear the Provider component data.
+                ArrayList<Provider> installedProviders =
+                        new ArrayList<Provider>(mInstalledProviders);
+                HashSet<ComponentName> removedProviders = new HashSet<ComponentName>();
+                int N = installedProviders.size();
                 for (int i = N - 1; i >= 0; i--) {
-                    Provider p = mInstalledProviders.get(i);
-                    String pkgName = p.info.provider.getPackageName();
-                    updateProvidersForPackageLocked(pkgName);
+                    Provider p = installedProviders.get(i);
+                    ComponentName cn = p.info.provider;
+                    if (!removedProviders.contains(cn)) {
+                        updateProvidersForPackageLocked(cn.getPackageName(), removedProviders);
+                    }
                 }
                 saveStateLocked();
             }
@@ -222,9 +242,11 @@
     }
 
     void onBroadcastReceived(Intent intent) {
+        if (DBG) log("onBroadcast " + intent);
         final String action = intent.getAction();
         boolean added = false;
         boolean changed = false;
+        boolean providersModified = false;
         String pkgList[] = null;
         if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
             pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
@@ -256,12 +278,12 @@
                         || (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false))) {
                     for (String pkgName : pkgList) {
                         // The package was just upgraded
-                        updateProvidersForPackageLocked(pkgName);
+                        providersModified |= updateProvidersForPackageLocked(pkgName, null);
                     }
                 } else {
                     // The package was just added
                     for (String pkgName : pkgList) {
-                        addProvidersForPackageLocked(pkgName);
+                        providersModified |= addProvidersForPackageLocked(pkgName);
                     }
                 }
                 saveStateLocked();
@@ -274,12 +296,20 @@
                 synchronized (mAppWidgetIds) {
                     ensureStateLoadedLocked();
                     for (String pkgName : pkgList) {
-                        removeProvidersForPackageLocked(pkgName);
+                        providersModified |= removeProvidersForPackageLocked(pkgName);
                         saveStateLocked();
                     }
                 }
             }
         }
+
+        if (providersModified) {
+            // If the set of providers has been modified, notify each active AppWidgetHost
+            synchronized (mAppWidgetIds) {
+                ensureStateLoadedLocked();
+                notifyHostsForProvidersChangedLocked();
+            }
+        }
     }
 
     private void dumpProvider(Provider p, int index, PrintWriter pw) {
@@ -295,6 +325,7 @@
                 pw.print(info.updatePeriodMillis);
                 pw.print(" resizeMode=");
                 pw.print(info.resizeMode);
+                pw.print(info.widgetCategory);
                 pw.print(" autoAdvanceViewId=");
                 pw.print(info.autoAdvanceViewId);
                 pw.print(" initialLayout=#");
@@ -386,7 +417,7 @@
     }
 
     public int allocateAppWidgetId(String packageName, int hostId) {
-        int callingUid = enforceCallingUid(packageName);
+        int callingUid = enforceSystemOrCallingUid(packageName);
         synchronized (mAppWidgetIds) {
             ensureStateLoadedLocked();
             int appWidgetId = mNextAppWidgetId++;
@@ -401,7 +432,8 @@
             mAppWidgetIds.add(id);
 
             saveStateLocked();
-
+            if (DBG) log("Allocating AppWidgetId for " + packageName + " host=" + hostId
+                    + " id=" + appWidgetId);
             return appWidgetId;
         }
     }
@@ -479,7 +511,7 @@
                 Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DELETED);
                 intent.setComponent(p.info.provider);
                 intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id.appWidgetId);
-                mContext.sendBroadcast(intent, mUserId);
+                mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
                 if (p.instances.size() == 0) {
                     // cancel the future updates
                     cancelBroadcasts(p);
@@ -487,13 +519,14 @@
                     // send the broacast saying that the provider is not in use any more
                     intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DISABLED);
                     intent.setComponent(p.info.provider);
-                    mContext.sendBroadcast(intent, mUserId);
+                    mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
                 }
             }
         }
     }
 
     void cancelBroadcasts(Provider p) {
+        if (DBG) log("cancelBroadcasts for " + p);
         if (p.broadcast != null) {
             mAlarmManager.cancel(p.broadcast);
             long token = Binder.clearCallingIdentity();
@@ -506,10 +539,13 @@
         }
     }
 
-    private void bindAppWidgetIdImpl(int appWidgetId, ComponentName provider) {
+    private void bindAppWidgetIdImpl(int appWidgetId, ComponentName provider, Bundle options) {
+        if (DBG) log("bindAppWidgetIdImpl appwid=" + appWidgetId
+                + " provider=" + provider);
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized (mAppWidgetIds) {
+                options = cloneIfLocalBinder(options);
                 ensureStateLoadedLocked();
                 AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
                 if (id == null) {
@@ -529,6 +565,17 @@
                 }
 
                 id.provider = p;
+                if (options == null) {
+                    options = new Bundle();
+                }
+                id.options = options;
+
+                // We need to provide a default value for the widget category if it is not specified
+                if (!options.containsKey(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)) {
+                    options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
+                            AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
+                }
+
                 p.instances.add(id);
                 int instancesSize = p.instances.size();
                 if (instancesSize == 1) {
@@ -551,29 +598,29 @@
         }
     }
 
-    public void bindAppWidgetId(int appWidgetId, ComponentName provider) {
-        mContext.enforceCallingPermission(android.Manifest.permission.BIND_APPWIDGET,
+    public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BIND_APPWIDGET,
             "bindAppWidgetId appWidgetId=" + appWidgetId + " provider=" + provider);
-        bindAppWidgetIdImpl(appWidgetId, provider);
+        bindAppWidgetIdImpl(appWidgetId, provider, options);
     }
 
     public boolean bindAppWidgetIdIfAllowed(
-            String packageName, int appWidgetId, ComponentName provider) {
+            String packageName, int appWidgetId, ComponentName provider, Bundle options) {
         try {
-            mContext.enforceCallingPermission(android.Manifest.permission.BIND_APPWIDGET, null);
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BIND_APPWIDGET, null);
         } catch (SecurityException se) {
             if (!callerHasBindAppWidgetPermission(packageName)) {
                 return false;
             }
         }
-        bindAppWidgetIdImpl(appWidgetId, provider);
+        bindAppWidgetIdImpl(appWidgetId, provider, options);
         return true;
     }
 
     private boolean callerHasBindAppWidgetPermission(String packageName) {
         int callingUid = Binder.getCallingUid();
         try {
-            if (!UserId.isSameApp(callingUid, getUidForPackage(packageName))) {
+            if (!UserHandle.isSameApp(callingUid, getUidForPackage(packageName))) {
                 return false;
             }
         } catch (Exception e) {
@@ -622,13 +669,13 @@
             }
             final ComponentName componentName = intent.getComponent();
             try {
-                final ServiceInfo si = mContext.getPackageManager().getServiceInfo(componentName,
-                        PackageManager.GET_PERMISSIONS);
+                final ServiceInfo si = AppGlobals.getPackageManager().getServiceInfo(componentName,
+                        PackageManager.GET_PERMISSIONS, mUserId);
                 if (!android.Manifest.permission.BIND_REMOTEVIEWS.equals(si.permission)) {
                     throw new SecurityException("Selected service does not require "
                             + android.Manifest.permission.BIND_REMOTEVIEWS + ": " + componentName);
                 }
-            } catch (PackageManager.NameNotFoundException e) {
+            } catch (RemoteException e) {
                 throw new IllegalArgumentException("Unknown component " + componentName);
             }
 
@@ -645,7 +692,7 @@
                 mBoundRemoteViewsServices.remove(key);
             }
 
-            int userId = UserId.getUserId(id.provider.uid);
+            int userId = UserHandle.getUserId(id.provider.uid);
             // Bind to the RemoteViewsService (which will trigger a callback to the
             // RemoteViewsAdapter.onServiceConnected())
             final long token = Binder.clearCallingIdentity();
@@ -736,7 +783,7 @@
             }
         };
 
-        int userId = UserId.getUserId(id.provider.uid);
+        int userId = UserHandle.getUserId(id.provider.uid);
         // Bind to the service and remove the static intent->factory mapping in the
         // RemoteViewsService.
         final long token = Binder.clearCallingIdentity();
@@ -782,19 +829,21 @@
             ensureStateLoadedLocked();
             AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
             if (id != null && id.provider != null && !id.provider.zombie) {
-                return id.provider.info;
+                return cloneIfLocalBinder(id.provider.info);
             }
             return null;
         }
     }
 
     public RemoteViews getAppWidgetViews(int appWidgetId) {
+        if (DBG) log("getAppWidgetViews id=" + appWidgetId);
         synchronized (mAppWidgetIds) {
             ensureStateLoadedLocked();
             AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
             if (id != null) {
-                return id.views;
+                return cloneIfLocalBinder(id.views);
             }
+            if (DBG) log("   couldn't find appwidgetid");
             return null;
         }
     }
@@ -807,7 +856,7 @@
             for (int i = 0; i < N; i++) {
                 Provider p = mInstalledProviders.get(i);
                 if (!p.zombie) {
-                    result.add(p.info);
+                    result.add(cloneIfLocalBinder(p.info));
                 }
             }
             return result;
@@ -818,7 +867,7 @@
         if (appWidgetIds == null) {
             return;
         }
-
+        if (DBG) log("updateAppWidgetIds views: " + views);
         int bitmapMemoryUsage = 0;
         if (views != null) {
             bitmapMemoryUsage = views.estimateMemoryUsage();
@@ -846,21 +895,25 @@
 
     public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
         synchronized (mAppWidgetIds) {
+            options = cloneIfLocalBinder(options);
             ensureStateLoadedLocked();
             AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
 
             if (id == null) {
                 return;
             }
+
             Provider p = id.provider;
-            id.options = options;
+            // Merge the options
+            id.options.putAll(options);
 
             // send the broacast saying that this appWidgetId has been deleted
             Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED);
             intent.setComponent(p.info.provider);
             intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id.appWidgetId);
-            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
-            mContext.sendBroadcast(intent, mUserId);
+            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, id.options);
+            mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
+            saveStateLocked();
         }
     }
 
@@ -869,7 +922,7 @@
             ensureStateLoadedLocked();
             AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
             if (id != null && id.options != null) {
-                return id.options;
+                return cloneIfLocalBinder(id.options);
             } else {
                 return Bundle.EMPTY;
             }
@@ -889,7 +942,10 @@
             ensureStateLoadedLocked();
             for (int i = 0; i < N; i++) {
                 AppWidgetId id = lookupAppWidgetIdLocked(appWidgetIds[i]);
-                updateAppWidgetInstanceLocked(id, views, true);
+                if (id.views != null) {
+                    // Only trigger a partial update for a widget if it has received a full update
+                    updateAppWidgetInstanceLocked(id, views, true);
+                }
             }
         }
     }
@@ -942,9 +998,13 @@
         // drop unbound appWidgetIds (shouldn't be possible under normal circumstances)
         if (id != null && id.provider != null && !id.provider.zombie && !id.host.zombie) {
 
-            // We do not want to save this RemoteViews
-            if (!isPartialUpdate)
+            if (!isPartialUpdate) {
+                // For a full update we replace the RemoteViews completely.
                 id.views = views;
+            } else {
+                // For a partial update, we merge the new RemoteViews with the old.
+                id.views.mergeRemoteViews(views);
+            }
 
             // is anyone listening?
             if (id.host.callbacks != null) {
@@ -1006,7 +1066,7 @@
                             }
                         };
 
-                        int userId = UserId.getUserId(id.provider.uid);
+                        int userId = UserHandle.getUserId(id.provider.uid);
                         // Bind to the service and call onDataSetChanged()
                         final long token = Binder.clearCallingIdentity();
                         try {
@@ -1020,6 +1080,34 @@
         }
     }
 
+    private boolean isLocalBinder() {
+        return Process.myPid() == Binder.getCallingPid();
+    }
+
+    private RemoteViews cloneIfLocalBinder(RemoteViews rv) {
+        if (isLocalBinder() && rv != null) {
+            return rv.clone();
+        }
+        return rv;
+    }
+
+    private AppWidgetProviderInfo cloneIfLocalBinder(AppWidgetProviderInfo info) {
+        if (isLocalBinder() && info != null) {
+            return info.clone();
+        }
+        return info;
+    }
+
+    private Bundle cloneIfLocalBinder(Bundle bundle) {
+        // Note: this is only a shallow copy. For now this will be fine, but it could be problematic
+        // if we start adding objects to the options. Further, it would only be an issue if keyguard
+        // used such options.
+        if (isLocalBinder() && bundle != null) {
+            return (Bundle) bundle.clone();
+        }
+        return bundle;
+    }
+
     public int[] startListening(IAppWidgetHost callbacks, String packageName, int hostId,
             List<RemoteViews> updatedViews) {
         int callingUid = enforceCallingUid(packageName);
@@ -1036,7 +1124,7 @@
             for (int i = 0; i < N; i++) {
                 AppWidgetId id = instances.get(i);
                 updatedIds[i] = id.appWidgetId;
-                updatedViews.add(id.views);
+                updatedViews.add(cloneIfLocalBinder(id.views));
             }
             return updatedIds;
         }
@@ -1185,7 +1273,7 @@
     void sendEnableIntentLocked(Provider p) {
         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_ENABLED);
         intent.setComponent(p.info.provider);
-        mContext.sendBroadcast(intent, mUserId);
+        mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
     }
 
     void sendUpdateIntentLocked(Provider p, int[] appWidgetIds) {
@@ -1193,7 +1281,7 @@
             Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
             intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
             intent.setComponent(p.info.provider);
-            mContext.sendBroadcast(intent, mUserId);
+            mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
         }
     }
 
@@ -1208,8 +1296,8 @@
             intent.setComponent(p.info.provider);
             long token = Binder.clearCallingIdentity();
             try {
-                p.broadcast = PendingIntent.getBroadcast(mContext, 1, intent,
-                        PendingIntent.FLAG_UPDATE_CURRENT);
+                p.broadcast = PendingIntent.getBroadcastAsUser(mContext, 1, intent,
+                        PendingIntent.FLAG_UPDATE_CURRENT, new UserHandle(mUserId));
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -1281,7 +1369,7 @@
             p.uid = activityInfo.applicationInfo.uid;
 
             Resources res = mContext.getPackageManager()
-                    .getResourcesForApplication(activityInfo.applicationInfo);
+                    .getResourcesForApplicationAsUser(activityInfo.packageName, mUserId);
 
             TypedArray sa = res.obtainAttributes(attrs,
                     com.android.internal.R.styleable.AppWidgetProviderInfo);
@@ -1304,6 +1392,8 @@
                     com.android.internal.R.styleable.AppWidgetProviderInfo_updatePeriodMillis, 0);
             info.initialLayout = sa.getResourceId(
                     com.android.internal.R.styleable.AppWidgetProviderInfo_initialLayout, 0);
+            info.initialKeyguardLayout = sa.getResourceId(com.android.internal.R.styleable.
+                    AppWidgetProviderInfo_initialKeyguardLayout, 0);
             String className = sa
                     .getString(com.android.internal.R.styleable.AppWidgetProviderInfo_configure);
             if (className != null) {
@@ -1318,6 +1408,9 @@
             info.resizeMode = sa.getInt(
                     com.android.internal.R.styleable.AppWidgetProviderInfo_resizeMode,
                     AppWidgetProviderInfo.RESIZE_NONE);
+            info.widgetCategory = sa.getInt(
+                    com.android.internal.R.styleable.AppWidgetProviderInfo_widgetCategory,
+                    AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
 
             sa.recycle();
         } catch (Exception e) {
@@ -1346,6 +1439,14 @@
         return pkgInfo.applicationInfo.uid;
     }
 
+    int enforceSystemOrCallingUid(String packageName) throws IllegalArgumentException {
+        int callingUid = Binder.getCallingUid();
+        if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID || callingUid == 0) {
+            return callingUid;
+        }
+        return enforceCallingUid(packageName);
+    }
+
     int enforceCallingUid(String packageName) throws IllegalArgumentException {
         int callingUid = Binder.getCallingUid();
         int packageUid;
@@ -1355,7 +1456,7 @@
             throw new IllegalArgumentException("packageName and uid don't match packageName="
                     + packageName);
         }
-        if (!UserId.isSameApp(callingUid, packageUid)) {
+        if (!UserHandle.isSameApp(callingUid, packageUid)) {
             throw new IllegalArgumentException("packageName and uid don't match packageName="
                     + packageName);
         }
@@ -1455,6 +1556,18 @@
                 if (id.provider != null) {
                     out.attribute(null, "p", Integer.toHexString(id.provider.tag));
                 }
+                if (id.options != null) {
+                    out.attribute(null, "min_width", Integer.toHexString(id.options.getInt(
+                            AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)));
+                    out.attribute(null, "min_height", Integer.toHexString(id.options.getInt(
+                            AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)));
+                    out.attribute(null, "max_width", Integer.toHexString(id.options.getInt(
+                            AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)));
+                    out.attribute(null, "max_height", Integer.toHexString(id.options.getInt(
+                            AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)));
+                    out.attribute(null, "host_category", Integer.toHexString(id.options.getInt(
+                            AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)));
+                }
                 out.endTag(null, "g");
             }
 
@@ -1475,6 +1588,7 @@
         }
     }
 
+    @SuppressWarnings("unused")
     void readStateFromFileLocked(FileInputStream stream) {
         boolean success = false;
         try {
@@ -1494,11 +1608,11 @@
                         String pkg = parser.getAttributeValue(null, "pkg");
                         String cl = parser.getAttributeValue(null, "cl");
 
-                        final PackageManager packageManager = mContext.getPackageManager();
+                        final IPackageManager packageManager = AppGlobals.getPackageManager();
                         try {
-                            packageManager.getReceiverInfo(new ComponentName(pkg, cl), 0);
-                        } catch (PackageManager.NameNotFoundException e) {
-                            String[] pkgs = packageManager
+                            packageManager.getReceiverInfo(new ComponentName(pkg, cl), 0, mUserId);
+                        } catch (RemoteException e) {
+                            String[] pkgs = mContext.getPackageManager()
                                     .currentToCanonicalPackageNames(new String[] { pkg });
                             pkg = pkgs[0];
                         }
@@ -1547,6 +1661,34 @@
                             mNextAppWidgetId = id.appWidgetId + 1;
                         }
 
+                        Bundle options = new Bundle();
+                        String minWidthString = parser.getAttributeValue(null, "min_width");
+                        if (minWidthString != null) {
+                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH,
+                                    Integer.parseInt(minWidthString, 16));
+                        }
+                        String minHeightString = parser.getAttributeValue(null, "min_height");
+                        if (minHeightString != null) {
+                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT,
+                                    Integer.parseInt(minHeightString, 16));
+                        }
+                        String maxWidthString = parser.getAttributeValue(null, "max_width");
+                        if (maxWidthString != null) {
+                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH,
+                                    Integer.parseInt(maxWidthString, 16));
+                        }
+                        String maxHeightString = parser.getAttributeValue(null, "max_height");
+                        if (maxHeightString != null) {
+                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT,
+                                    Integer.parseInt(maxHeightString, 16));
+                        }
+                        String categoryString = parser.getAttributeValue(null, "host_category");
+                        if (categoryString != null) {
+                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
+                                    Integer.parseInt(categoryString, 16));
+                        }
+                        id.options = options;
+
                         String providerString = parser.getAttributeValue(null, "p");
                         if (providerString != null) {
                             // there's no provider if it hasn't been bound yet.
@@ -1613,11 +1755,11 @@
     }
 
     static File getSettingsFile(int userId) {
-        return new File("/data/system/users/" + userId + "/" + SETTINGS_FILENAME);
+        return new File(Environment.getUserSystemDirectory(userId), SETTINGS_FILENAME);
     }
 
     AtomicFile savedStateFile() {
-        File dir = new File("/data/system/users/" + mUserId);
+        File dir = Environment.getUserSystemDirectory(mUserId);
         File settingsFile = getSettingsFile(mUserId);
         if (!settingsFile.exists() && mUserId == 0) {
             if (!dir.exists()) {
@@ -1632,17 +1774,21 @@
         return new AtomicFile(settingsFile);
     }
 
-    void onUserRemoved() {
+    void onUserStopping() {
         // prune the ones we don't want to keep
         int N = mInstalledProviders.size();
         for (int i = N - 1; i >= 0; i--) {
             Provider p = mInstalledProviders.get(i);
             cancelBroadcasts(p);
         }
+    }
+
+    void onUserRemoved() {
         getSettingsFile(mUserId).delete();
     }
 
-    void addProvidersForPackageLocked(String pkgName) {
+    boolean addProvidersForPackageLocked(String pkgName) {
+        boolean providersAdded = false;
         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
         intent.setPackage(pkgName);
         List<ResolveInfo> broadcastReceivers;
@@ -1652,7 +1798,7 @@
                     PackageManager.GET_META_DATA, mUserId);
         } catch (RemoteException re) {
             // Shouldn't happen, local call
-            return;
+            return false;
         }
         final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
         for (int i = 0; i < N; i++) {
@@ -1663,11 +1809,21 @@
             }
             if (pkgName.equals(ai.packageName)) {
                 addProviderLocked(ri);
+                providersAdded = true;
             }
         }
+
+        return providersAdded;
     }
 
-    void updateProvidersForPackageLocked(String pkgName) {
+    /**
+     * Updates all providers with the specified package names, and records any providers that were
+     * pruned.
+     *
+     * @return whether any providers were updated
+     */
+    boolean updateProvidersForPackageLocked(String pkgName, Set<ComponentName> removedProviders) {
+        boolean providersUpdated = false;
         HashSet<String> keep = new HashSet<String>();
         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
         intent.setPackage(pkgName);
@@ -1678,7 +1834,7 @@
                 PackageManager.GET_META_DATA, mUserId);
         } catch (RemoteException re) {
             // Shouldn't happen, local call
-            return;
+            return false;
         }
 
         // add the missing ones and collect which ones to keep
@@ -1695,6 +1851,7 @@
                 if (p == null) {
                     if (addProviderLocked(ri)) {
                         keep.add(ai.name);
+                        providersUpdated = true;
                     }
                 } else {
                     Provider parsed = parseProviderInfoXml(component, ri);
@@ -1729,6 +1886,7 @@
                             }
                             // Now that we've told the host, push out an update.
                             sendUpdateIntentLocked(p, appWidgetIds);
+                            providersUpdated = true;
                         }
                     }
                 }
@@ -1741,17 +1899,25 @@
             Provider p = mInstalledProviders.get(i);
             if (pkgName.equals(p.info.provider.getPackageName())
                     && !keep.contains(p.info.provider.getClassName())) {
+                if (removedProviders != null) {
+                    removedProviders.add(p.info.provider);
+                }
                 removeProviderLocked(i, p);
+                providersUpdated = true;
             }
         }
+
+        return providersUpdated;
     }
 
-    void removeProvidersForPackageLocked(String pkgName) {
+    boolean removeProvidersForPackageLocked(String pkgName) {
+        boolean providersRemoved = false;
         int N = mInstalledProviders.size();
         for (int i = N - 1; i >= 0; i--) {
             Provider p = mInstalledProviders.get(i);
             if (pkgName.equals(p.info.provider.getPackageName())) {
                 removeProviderLocked(i, p);
+                providersRemoved = true;
             }
         }
 
@@ -1766,5 +1932,24 @@
                 deleteHostLocked(host);
             }
         }
+
+        return providersRemoved;
+    }
+
+    void notifyHostsForProvidersChangedLocked() {
+        final int N = mHosts.size();
+        for (int i = N - 1; i >= 0; i--) {
+            Host host = mHosts.get(i);
+            try {
+                if (host.callbacks != null) {
+                    host.callbacks.providersChanged();
+                }
+            } catch (RemoteException ex) {
+                // It failed; remove the callback. No need to prune because
+                // we know that this host is still referenced by this
+                // instance.
+                host.callbacks = null;
+            }
+        }
     }
 }
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 1f3f172b..7ac314b 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -65,7 +65,9 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.os.WorkSource;
+import android.os.Environment.UserEnvironment;
 import android.os.storage.IMountService;
 import android.provider.Settings;
 import android.util.EventLog;
@@ -131,7 +133,7 @@
 
 class BackupManagerService extends IBackupManager.Stub {
     private static final String TAG = "BackupManagerService";
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
     private static final boolean MORE_DEBUG = false;
 
     // Name and current contents version of the full-backup manifest file
@@ -727,14 +729,14 @@
         final ContentResolver resolver = context.getContentResolver();
         boolean areEnabled = Settings.Secure.getInt(resolver,
                 Settings.Secure.BACKUP_ENABLED, 0) != 0;
-        mProvisioned = Settings.Secure.getInt(resolver,
-                Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
+        mProvisioned = Settings.Global.getInt(resolver,
+                Settings.Global.DEVICE_PROVISIONED, 0) != 0;
         mAutoRestore = Settings.Secure.getInt(resolver,
                 Settings.Secure.BACKUP_AUTO_RESTORE, 1) != 0;
 
         mProvisionedObserver = new ProvisionedObserver(mBackupHandler);
         resolver.registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.DEVICE_PROVISIONED),
+                Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
                 false, mProvisionedObserver);
 
         // If Encrypted file systems is enabled or disabled, this call will return the
@@ -834,7 +836,8 @@
             if ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                 if (DEBUG) Slog.v(TAG, "Binding to Google transport");
                 Intent intent = new Intent().setComponent(transportComponent);
-                context.bindService(intent, mGoogleConnection, Context.BIND_AUTO_CREATE);
+                context.bindService(intent, mGoogleConnection, Context.BIND_AUTO_CREATE,
+                        UserHandle.USER_OWNER);
             } else {
                 Slog.w(TAG, "Possible Google transport spoof: ignoring " + info);
             }
@@ -1431,12 +1434,9 @@
                 set.add(pkg.packageName);
                 if (MORE_DEBUG) Slog.v(TAG, "Agent found; added");
 
-                // If we've never seen this app before, schedule a backup for it
-                if (!mEverStoredApps.contains(pkg.packageName)) {
-                    if (DEBUG) Slog.i(TAG, "New app " + pkg.packageName
-                            + " never backed up; scheduling");
-                    dataChangedImpl(pkg.packageName);
-                }
+                // Schedule a backup for it on general principles
+                if (DEBUG) Slog.i(TAG, "Scheduling backup for new app " + pkg.packageName);
+                dataChangedImpl(pkg.packageName);
             }
         }
     }
@@ -1469,9 +1469,12 @@
             // Found it.  Remove this one package from the bookkeeping, and
             // if it's the last participating app under this uid we drop the
             // (now-empty) set as well.
+            // Note that we deliberately leave it 'known' in the "ever backed up"
+            // bookkeeping so that its current-dataset data will be retrieved
+            // if the app is subsequently reinstalled
             if (MORE_DEBUG) Slog.v(TAG, "  removing participant " + packageName);
-            removeEverBackedUp(packageName);
             set.remove(packageName);
+            mPendingBackups.remove(packageName);
         }
     }
 
@@ -1623,6 +1626,7 @@
                         } catch (InterruptedException e) {
                             // just bail
                             if (DEBUG) Slog.w(TAG, "Interrupted: " + e);
+                            mActivityManager.clearPendingBackup();
                             return null;
                         }
                     }
@@ -1630,6 +1634,7 @@
                     // if we timed out with no connect, abort and move on
                     if (mConnecting == true) {
                         Slog.w(TAG, "Timeout waiting for agent " + app);
+                        mActivityManager.clearPendingBackup();
                         return null;
                     }
                     if (DEBUG) Slog.i(TAG, "got agent " + mConnectedAgent);
@@ -1662,8 +1667,7 @@
         synchronized(mClearDataLock) {
             mClearingData = true;
             try {
-                mActivityManager.clearApplicationUserData(packageName, observer,
-                        Binder.getOrigCallingUser());
+                mActivityManager.clearApplicationUserData(packageName, observer, 0);
             } catch (RemoteException e) {
                 // can't happen because the activity manager is in this process
             }
@@ -2735,9 +2739,13 @@
             FullBackup.backupToTar(pkg.packageName, FullBackup.APK_TREE_TOKEN, null,
                     apkDir, appSourceDir, output);
 
+            // TODO: migrate this to SharedStorageBackup, since AID_SYSTEM
+            // doesn't have access to external storage.
+
             // Save associated .obb content if it exists and we did save the apk
             // check for .obb and save those too
-            final File obbDir = Environment.getExternalStorageAppObbDirectory(pkg.packageName);
+            final UserEnvironment userEnv = new UserEnvironment(UserHandle.USER_OWNER);
+            final File obbDir = userEnv.getExternalStorageAppObbDirectory(pkg.packageName);
             if (obbDir != null) {
                 if (MORE_DEBUG) Log.i(TAG, "obb dir: " + obbDir.getAbsolutePath());
                 File[] obbFiles = obbDir.listFiles();
@@ -4424,6 +4432,18 @@
                     return;
                 }
 
+                if (packageInfo.applicationInfo.backupAgentName == null
+                        || "".equals(packageInfo.applicationInfo.backupAgentName)) {
+                    if (DEBUG) {
+                        Slog.i(TAG, "Data exists for package " + packageName
+                                + " but app has no agent; skipping");
+                    }
+                    EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, packageName,
+                            "Package has no agent");
+                    executeNextState(RestoreState.RUNNING_QUEUE);
+                    return;
+                }
+
                 if (metaInfo.versionCode > packageInfo.versionCode) {
                     // Data is from a "newer" version of the app than we have currently
                     // installed.  If the app has not declared that it is prepared to
@@ -4868,6 +4888,18 @@
     // ----- IBackupManager binder interface -----
 
     public void dataChanged(final String packageName) {
+        final int callingUserHandle = UserHandle.getCallingUserId();
+        if (callingUserHandle != UserHandle.USER_OWNER) {
+            // App is running under a non-owner user profile.  For now, we do not back
+            // up data from secondary user profiles.
+            // TODO: backups for all user profiles.
+            if (MORE_DEBUG) {
+                Slog.v(TAG, "dataChanged(" + packageName + ") ignored because it's user "
+                        + callingUserHandle);
+            }
+            return;
+        }
+
         final HashSet<String> targets = dataChangedTargets(packageName);
         if (targets == null) {
             Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
@@ -4950,7 +4982,7 @@
 
     boolean deviceIsProvisioned() {
         final ContentResolver resolver = mContext.getContentResolver();
-        return (Settings.Secure.getInt(resolver, Settings.Secure.DEVICE_PROVISIONED, 0) != 0);
+        return (Settings.Global.getInt(resolver, Settings.Global.DEVICE_PROVISIONED, 0) != 0);
     }
 
     // Run a *full* backup pass for the given package, writing the resulting data stream
@@ -4960,6 +4992,11 @@
             boolean doAllApps, boolean includeSystem, String[] pkgList) {
         mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "fullBackup");
 
+        final int callingUserHandle = UserHandle.getCallingUserId();
+        if (callingUserHandle != UserHandle.USER_OWNER) {
+            throw new IllegalStateException("Backup supported only for the device owner");
+        }
+
         // Validate
         if (!doAllApps) {
             if (!includeShared) {
@@ -5024,6 +5061,11 @@
     public void fullRestore(ParcelFileDescriptor fd) {
         mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "fullRestore");
 
+        final int callingUserHandle = UserHandle.getCallingUserId();
+        if (callingUserHandle != UserHandle.USER_OWNER) {
+            throw new IllegalStateException("Restore supported only for the device owner");
+        }
+
         long oldId = Binder.clearCallingIdentity();
 
         try {
@@ -5398,7 +5440,8 @@
 
         long restoreSet = getAvailableRestoreToken(packageName);
         if (DEBUG) Slog.v(TAG, "restoreAtInstall pkg=" + packageName
-                + " token=" + Integer.toHexString(token));
+                + " token=" + Integer.toHexString(token)
+                + " restoreSet=" + Long.toHexString(restoreSet));
 
         if (mAutoRestore && mProvisioned && restoreSet != 0) {
             // okay, we're going to attempt a restore of this package from this restore set.
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index ab9ae69..dbffa97 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -27,23 +27,23 @@
 import android.os.BatteryManager;
 import android.os.Binder;
 import android.os.FileUtils;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.DropBoxManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UEventObserver;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.EventLog;
 import android.util.Slog;
 
 import java.io.File;
 import java.io.FileDescriptor;
-import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.util.Arrays;
 
 
 /**
@@ -67,13 +67,21 @@
  * <p>&quot;temperature&quot; - int, current battery temperature in tenths of
  * a degree Centigrade</p>
  * <p>&quot;technology&quot; - String, the type of battery installed, e.g. "Li-ion"</p>
+ *
+ * <p>
+ * The battery service may be called by the power manager while holding its locks so
+ * we take care to post all outcalls into the activity manager to a handler.
+ *
+ * FIXME: Ideally the power manager would perform all of its calls into the battery
+ * service asynchronously itself.
+ * </p>
  */
-class BatteryService extends Binder {
+public final class BatteryService extends Binder {
     private static final String TAG = BatteryService.class.getSimpleName();
 
-    private static final boolean LOCAL_LOGV = false;
+    private static final boolean DEBUG = false;
 
-    static final int BATTERY_SCALE = 100;    // battery capacity is a percentage
+    private static final int BATTERY_SCALE = 100;    // battery capacity is a percentage
 
     // Used locally for determining when to make a last ditch effort to log
     // discharge stats before the device dies.
@@ -90,9 +98,14 @@
 
     private final Context mContext;
     private final IBatteryStats mBatteryStats;
+    private final Handler mHandler;
 
+    private final Object mLock = new Object();
+
+    /* Begin native fields: All of these fields are set by native code. */
     private boolean mAcOnline;
     private boolean mUsbOnline;
+    private boolean mWirelessOnline;
     private int mBatteryStatus;
     private int mBatteryHealth;
     private boolean mBatteryPresent;
@@ -101,7 +114,7 @@
     private int mBatteryTemperature;
     private String mBatteryTechnology;
     private boolean mBatteryLevelCritical;
-    private int mInvalidCharger;
+    /* End native fields. */
 
     private int mLastBatteryStatus;
     private int mLastBatteryHealth;
@@ -110,10 +123,13 @@
     private int mLastBatteryVoltage;
     private int mLastBatteryTemperature;
     private boolean mLastBatteryLevelCritical;
+
+    private int mInvalidCharger;
     private int mLastInvalidCharger;
 
     private int mLowBatteryWarningLevel;
     private int mLowBatteryCloseWarningLevel;
+    private int mShutdownBatteryTemperature;
 
     private int mPlugType;
     private int mLastPlugType = -1; // Extra state so we can detect first run
@@ -121,12 +137,17 @@
     private long mDischargeStartTime;
     private int mDischargeStartLevel;
 
+    private boolean mUpdatesStopped;
+
     private Led mLed;
 
     private boolean mSentLowBatteryBroadcast = false;
 
+    private native void native_update();
+
     public BatteryService(Context context, LightsService lights) {
         mContext = context;
+        mHandler = new Handler(true /*async*/);
         mLed = new Led(context, lights);
         mBatteryStats = BatteryStatsService.getService();
 
@@ -136,117 +157,163 @@
                 com.android.internal.R.integer.config_lowBatteryWarningLevel);
         mLowBatteryCloseWarningLevel = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_lowBatteryCloseWarningLevel);
+        mShutdownBatteryTemperature = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_shutdownBatteryTemperature);
 
         mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply");
 
         // watch for invalid charger messages if the invalid_charger switch exists
         if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
-            mInvalidChargerObserver.startObserving("DEVPATH=/devices/virtual/switch/invalid_charger");
+            mInvalidChargerObserver.startObserving(
+                    "DEVPATH=/devices/virtual/switch/invalid_charger");
         }
 
         // set initial status
-        update();
+        synchronized (mLock) {
+            updateLocked();
+        }
     }
 
-    final boolean isPowered() {
-        // assume we are powered if battery state is unknown so the "stay on while plugged in" option will work.
-        return (mAcOnline || mUsbOnline || mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN);
+    void systemReady() {
+        // check our power situation now that it is safe to display the shutdown dialog.
+        synchronized (mLock) {
+            shutdownIfNoPowerLocked();
+            shutdownIfOverTempLocked();
+        }
     }
 
-    final boolean isPowered(int plugTypeSet) {
+    /**
+     * Returns true if the device is plugged into any of the specified plug types.
+     */
+    public boolean isPowered(int plugTypeSet) {
+        synchronized (mLock) {
+            return isPoweredLocked(plugTypeSet);
+        }
+    }
+
+    private boolean isPoweredLocked(int plugTypeSet) {
         // assume we are powered if battery state is unknown so
         // the "stay on while plugged in" option will work.
         if (mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {
             return true;
         }
-        if (plugTypeSet == 0) {
-            return false;
+        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_AC) != 0 && mAcOnline) {
+            return true;
         }
-        int plugTypeBit = 0;
-        if (mAcOnline) {
-            plugTypeBit |= BatteryManager.BATTERY_PLUGGED_AC;
+        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_USB) != 0 && mUsbOnline) {
+            return true;
         }
-        if (mUsbOnline) {
-            plugTypeBit |= BatteryManager.BATTERY_PLUGGED_USB;
+        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0 && mWirelessOnline) {
+            return true;
         }
-        return (plugTypeSet & plugTypeBit) != 0;
+        return false;
     }
 
-    final int getPlugType() {
-        return mPlugType;
-    }
-
-    private UEventObserver mPowerSupplyObserver = new UEventObserver() {
-        @Override
-        public void onUEvent(UEventObserver.UEvent event) {
-            update();
+    /**
+     * Returns the current plug type.
+     */
+    public int getPlugType() {
+        synchronized (mLock) {
+            return mPlugType;
         }
-    };
+    }
 
-    private UEventObserver mInvalidChargerObserver = new UEventObserver() {
-        @Override
-        public void onUEvent(UEventObserver.UEvent event) {
-            int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0;
-            if (mInvalidCharger != invalidCharger) {
-                mInvalidCharger = invalidCharger;
-                update();
-            }
+    /**
+     * Returns battery level as a percentage.
+     */
+    public int getBatteryLevel() {
+        synchronized (mLock) {
+            return mBatteryLevel;
         }
-    };
-
-    // returns battery level as a percentage
-    final int getBatteryLevel() {
-        return mBatteryLevel;
     }
 
-    void systemReady() {
-        // check our power situation now that it is safe to display the shutdown dialog.
-        shutdownIfNoPower();
-        shutdownIfOverTemp();
+    /**
+     * Returns true if battery level is below the first warning threshold.
+     */
+    public boolean isBatteryLow() {
+        synchronized (mLock) {
+            return mBatteryPresent && mBatteryLevel <= mLowBatteryWarningLevel;
+        }
     }
 
-    private final void shutdownIfNoPower() {
+    private void shutdownIfNoPowerLocked() {
         // shut down gracefully if our battery is critically low and we are not powered.
         // wait until the system has booted before attempting to display the shutdown dialog.
-        if (mBatteryLevel == 0 && !isPowered() && ActivityManagerNative.isSystemReady()) {
-            Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
-            intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            mContext.startActivity(intent);
+        if (mBatteryLevel == 0 && !isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    if (ActivityManagerNative.isSystemReady()) {
+                        Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
+                        intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
+                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+                    }
+                }
+            });
         }
     }
 
-    private final void shutdownIfOverTemp() {
-        // shut down gracefully if temperature is too high (> 68.0C)
-        // wait until the system has booted before attempting to display the shutdown dialog.
-        if (mBatteryTemperature > 680 && ActivityManagerNative.isSystemReady()) {
-            Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
-            intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            mContext.startActivity(intent);
+    private void shutdownIfOverTempLocked() {
+        // shut down gracefully if temperature is too high (> 68.0C by default)
+        // wait until the system has booted before attempting to display the
+        // shutdown dialog.
+        if (mBatteryTemperature > mShutdownBatteryTemperature) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    if (ActivityManagerNative.isSystemReady()) {
+                        Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
+                        intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
+                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+                    }
+                }
+            });
         }
     }
 
-    private native void native_update();
+    private void updateLocked() {
+        if (!mUpdatesStopped) {
+            // Update the values of mAcOnline, et. all.
+            native_update();
 
-    private synchronized final void update() {
-        native_update();
-        processValues();
+            // Process the new values.
+            processValuesLocked();
+        }
     }
 
-    private void processValues() {
+    private void processValuesLocked() {
         boolean logOutlier = false;
         long dischargeDuration = 0;
 
-        mBatteryLevelCritical = mBatteryLevel <= mCriticalBatteryLevel;
+        mBatteryLevelCritical = (mBatteryLevel <= mCriticalBatteryLevel);
         if (mAcOnline) {
             mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
         } else if (mUsbOnline) {
             mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
+        } else if (mWirelessOnline) {
+            mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
         } else {
             mPlugType = BATTERY_PLUGGED_NONE;
         }
-        
+
+        if (DEBUG) {
+            Slog.d(TAG, "Processing new values: "
+                    + "mAcOnline=" + mAcOnline
+                    + ", mUsbOnline=" + mUsbOnline
+                    + ", mWirelessOnline=" + mWirelessOnline
+                    + ", mBatteryStatus=" + mBatteryStatus
+                    + ", mBatteryHealth=" + mBatteryHealth
+                    + ", mBatteryPresent=" + mBatteryPresent
+                    + ", mBatteryLevel=" + mBatteryLevel
+                    + ", mBatteryTechnology=" + mBatteryTechnology
+                    + ", mBatteryVoltage=" + mBatteryVoltage
+                    + ", mBatteryTemperature=" + mBatteryTemperature
+                    + ", mBatteryLevelCritical=" + mBatteryLevelCritical
+                    + ", mPlugType=" + mPlugType);
+        }
+
         // Let the battery stats keep track of the current level.
         try {
             mBatteryStats.setBatteryState(mBatteryStatus, mBatteryHealth,
@@ -255,9 +322,9 @@
         } catch (RemoteException e) {
             // Should never happen.
         }
-        
-        shutdownIfNoPower();
-        shutdownIfOverTemp();
+
+        shutdownIfNoPowerLocked();
+        shutdownIfOverTempLocked();
 
         if (mBatteryStatus != mLastBatteryStatus ||
                 mBatteryHealth != mLastBatteryHealth ||
@@ -324,30 +391,52 @@
                     && mBatteryLevel <= mLowBatteryWarningLevel
                     && (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel);
 
-            sendIntent();
+            sendIntentLocked();
 
             // Separate broadcast is sent for power connected / not connected
             // since the standard intent will not wake any applications and some
             // applications may want to have smart behavior based on this.
-            Intent statusIntent = new Intent();
-            statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
             if (mPlugType != 0 && mLastPlugType == 0) {
-                statusIntent.setAction(Intent.ACTION_POWER_CONNECTED);
-                mContext.sendBroadcast(statusIntent);
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);
+                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                        mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
+                    }
+                });
             }
             else if (mPlugType == 0 && mLastPlugType != 0) {
-                statusIntent.setAction(Intent.ACTION_POWER_DISCONNECTED);
-                mContext.sendBroadcast(statusIntent);
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
+                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                        mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
+                    }
+                });
             }
 
             if (sendBatteryLow) {
                 mSentLowBatteryBroadcast = true;
-                statusIntent.setAction(Intent.ACTION_BATTERY_LOW);
-                mContext.sendBroadcast(statusIntent);
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW);
+                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                        mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
+                    }
+                });
             } else if (mSentLowBatteryBroadcast && mLastBatteryLevel >= mLowBatteryCloseWarningLevel) {
                 mSentLowBatteryBroadcast = false;
-                statusIntent.setAction(Intent.ACTION_BATTERY_OKAY);
-                mContext.sendBroadcast(statusIntent);
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);
+                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                        mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
+                    }
+                });
             }
 
             // Update the battery LED
@@ -355,7 +444,7 @@
 
             // This needs to be done after sendIntent() so that we get the lastest battery stats.
             if (logOutlier && dischargeDuration != 0) {
-                logOutlier(dischargeDuration);
+                logOutlierLocked(dischargeDuration);
             }
 
             mLastBatteryStatus = mBatteryStatus;
@@ -370,13 +459,13 @@
         }
     }
 
-    private final void sendIntent() {
+    private void sendIntentLocked() {
         //  Pack up the values and broadcast them to everyone
-        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
+        final Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
 
-        int icon = getIcon(mBatteryLevel);
+        int icon = getIconLocked(mBatteryLevel);
 
         intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryStatus);
         intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryHealth);
@@ -390,21 +479,27 @@
         intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryTechnology);
         intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger);
 
-        if (false) {
-            Slog.d(TAG, "level:" + mBatteryLevel +
-                    " scale:" + BATTERY_SCALE + " status:" + mBatteryStatus +
-                    " health:" + mBatteryHealth +  " present:" + mBatteryPresent +
-                    " voltage: " + mBatteryVoltage +
-                    " temperature: " + mBatteryTemperature +
-                    " technology: " + mBatteryTechnology +
-                    " AC powered:" + mAcOnline + " USB powered:" + mUsbOnline +
-                    " icon:" + icon  + " invalid charger:" + mInvalidCharger);
+        if (DEBUG) {
+            Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED.  level:" + mBatteryLevel +
+                    ", scale:" + BATTERY_SCALE + ", status:" + mBatteryStatus +
+                    ", health:" + mBatteryHealth +  ", present:" + mBatteryPresent +
+                    ", voltage: " + mBatteryVoltage +
+                    ", temperature: " + mBatteryTemperature +
+                    ", technology: " + mBatteryTechnology +
+                    ", AC powered:" + mAcOnline + ", USB powered:" + mUsbOnline +
+                    ", Wireless powered:" + mWirelessOnline +
+                    ", icon:" + icon  + ", invalid charger:" + mInvalidCharger);
         }
 
-        ActivityManagerNative.broadcastStickyIntent(intent, null);
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);
+            }
+        });
     }
 
-    private final void logBatteryStats() {
+    private void logBatteryStatsLocked() {
         IBinder batteryInfoService = ServiceManager.getService(BATTERY_STATS_SERVICE_NAME);
         if (batteryInfoService == null) return;
 
@@ -442,12 +537,12 @@
         }
     }
 
-    private final void logOutlier(long duration) {
+    private void logOutlierLocked(long duration) {
         ContentResolver cr = mContext.getContentResolver();
-        String dischargeThresholdString = Settings.Secure.getString(cr,
-                Settings.Secure.BATTERY_DISCHARGE_THRESHOLD);
-        String durationThresholdString = Settings.Secure.getString(cr,
-                Settings.Secure.BATTERY_DISCHARGE_DURATION_THRESHOLD);
+        String dischargeThresholdString = Settings.Global.getString(cr,
+                Settings.Global.BATTERY_DISCHARGE_THRESHOLD);
+        String durationThresholdString = Settings.Global.getString(cr,
+                Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD);
 
         if (dischargeThresholdString != null && durationThresholdString != null) {
             try {
@@ -456,11 +551,11 @@
                 if (duration <= durationThreshold &&
                         mDischargeStartLevel - mBatteryLevel >= dischargeThreshold) {
                     // If the discharge cycle is bad enough we want to know about it.
-                    logBatteryStats();
+                    logBatteryStatsLocked();
                 }
-                if (LOCAL_LOGV) Slog.v(TAG, "duration threshold: " + durationThreshold +
+                if (DEBUG) Slog.v(TAG, "duration threshold: " + durationThreshold +
                         " discharge threshold: " + dischargeThreshold);
-                if (LOCAL_LOGV) Slog.v(TAG, "duration: " + duration + " discharge: " +
+                if (DEBUG) Slog.v(TAG, "duration: " + duration + " discharge: " +
                         (mDischargeStartLevel - mBatteryLevel));
             } catch (NumberFormatException e) {
                 Slog.e(TAG, "Invalid DischargeThresholds GService string: " +
@@ -470,14 +565,15 @@
         }
     }
 
-    private final int getIcon(int level) {
+    private int getIconLocked(int level) {
         if (mBatteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) {
             return com.android.internal.R.drawable.stat_sys_battery_charge;
         } else if (mBatteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) {
             return com.android.internal.R.drawable.stat_sys_battery;
         } else if (mBatteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING
                 || mBatteryStatus == BatteryManager.BATTERY_STATUS_FULL) {
-            if (isPowered() && mBatteryLevel >= 100) {
+            if (isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)
+                    && mBatteryLevel >= 100) {
                 return com.android.internal.R.drawable.stat_sys_battery_charge;
             } else {
                 return com.android.internal.R.drawable.stat_sys_battery;
@@ -498,11 +594,15 @@
             return;
         }
 
-        if (args == null || args.length == 0 || "-a".equals(args[0])) {
-            synchronized (this) {
+        synchronized (mLock) {
+            if (args == null || args.length == 0 || "-a".equals(args[0])) {
                 pw.println("Current Battery Service state:");
+                if (mUpdatesStopped) {
+                    pw.println("  (UPDATES STOPPED -- use 'reset' to restart)");
+                }
                 pw.println("  AC powered: " + mAcOnline);
                 pw.println("  USB powered: " + mUsbOnline);
+                pw.println("  Wireless powered: " + mWirelessOnline);
                 pw.println("  status: " + mBatteryStatus);
                 pw.println("  health: " + mBatteryHealth);
                 pw.println("  present: " + mBatteryPresent);
@@ -511,10 +611,7 @@
                 pw.println("  voltage:" + mBatteryVoltage);
                 pw.println("  temperature: " + mBatteryTemperature);
                 pw.println("  technology: " + mBatteryTechnology);
-            }
-        } else if (false) {
-            // DO NOT SUBMIT WITH THIS TURNED ON
-            if (args.length == 3 && "set".equals(args[0])) {
+            } else if (args.length == 3 && "set".equals(args[0])) {
                 String key = args[1];
                 String value = args[2];
                 try {
@@ -523,6 +620,8 @@
                         mAcOnline = Integer.parseInt(value) != 0;
                     } else if ("usb".equals(key)) {
                         mUsbOnline = Integer.parseInt(value) != 0;
+                    } else if ("wireless".equals(key)) {
+                        mWirelessOnline = Integer.parseInt(value) != 0;
                     } else if ("status".equals(key)) {
                         mBatteryStatus = Integer.parseInt(value);
                     } else if ("level".equals(key)) {
@@ -530,52 +629,77 @@
                     } else if ("invalid".equals(key)) {
                         mInvalidCharger = Integer.parseInt(value);
                     } else {
+                        pw.println("Unknown set option: " + key);
                         update = false;
                     }
                     if (update) {
-                        processValues();
+                        mUpdatesStopped = true;
+                        processValuesLocked();
                     }
                 } catch (NumberFormatException ex) {
                     pw.println("Bad value: " + value);
                 }
+            } else if (args.length == 1 && "reset".equals(args[0])) {
+                mUpdatesStopped = false;
+                updateLocked();
+            } else {
+                pw.println("Dump current battery state, or:");
+                pw.println("  set ac|usb|wireless|status|level|invalid <value>");
+                pw.println("  reset");
             }
         }
     }
 
-    class Led {
-        private LightsService mLightsService;
-        private LightsService.Light mBatteryLight;
+    private final UEventObserver mPowerSupplyObserver = new UEventObserver() {
+        @Override
+        public void onUEvent(UEventObserver.UEvent event) {
+            synchronized (mLock) {
+                updateLocked();
+            }
+        }
+    };
 
-        private int mBatteryLowARGB;
-        private int mBatteryMediumARGB;
-        private int mBatteryFullARGB;
-        private int mBatteryLedOn;
-        private int mBatteryLedOff;
+    private final UEventObserver mInvalidChargerObserver = new UEventObserver() {
+        @Override
+        public void onUEvent(UEventObserver.UEvent event) {
+            final int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0;
+            synchronized (mLock) {
+                if (mInvalidCharger != invalidCharger) {
+                    mInvalidCharger = invalidCharger;
+                    updateLocked();
+                }
+            }
+        }
+    };
 
-        private boolean mBatteryCharging;
-        private boolean mBatteryLow;
-        private boolean mBatteryFull;
+    private final class Led {
+        private final LightsService.Light mBatteryLight;
 
-        Led(Context context, LightsService lights) {
-            mLightsService = lights;
+        private final int mBatteryLowARGB;
+        private final int mBatteryMediumARGB;
+        private final int mBatteryFullARGB;
+        private final int mBatteryLedOn;
+        private final int mBatteryLedOff;
+
+        public Led(Context context, LightsService lights) {
             mBatteryLight = lights.getLight(LightsService.LIGHT_ID_BATTERY);
 
-            mBatteryLowARGB = mContext.getResources().getInteger(
+            mBatteryLowARGB = context.getResources().getInteger(
                     com.android.internal.R.integer.config_notificationsBatteryLowARGB);
-            mBatteryMediumARGB = mContext.getResources().getInteger(
+            mBatteryMediumARGB = context.getResources().getInteger(
                     com.android.internal.R.integer.config_notificationsBatteryMediumARGB);
-            mBatteryFullARGB = mContext.getResources().getInteger(
+            mBatteryFullARGB = context.getResources().getInteger(
                     com.android.internal.R.integer.config_notificationsBatteryFullARGB);
-            mBatteryLedOn = mContext.getResources().getInteger(
+            mBatteryLedOn = context.getResources().getInteger(
                     com.android.internal.R.integer.config_notificationsBatteryLedOn);
-            mBatteryLedOff = mContext.getResources().getInteger(
+            mBatteryLedOff = context.getResources().getInteger(
                     com.android.internal.R.integer.config_notificationsBatteryLedOff);
         }
 
         /**
          * Synchronize on BatteryService.
          */
-        void updateLightsLocked() {
+        public void updateLightsLocked() {
             final int level = mBatteryLevel;
             final int status = mBatteryStatus;
             if (level < mLowBatteryWarningLevel) {
@@ -603,4 +727,3 @@
         }
     }
 }
-
diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java
new file mode 100755
index 0000000..69ccbc7
--- /dev/null
+++ b/services/java/com/android/server/BluetoothManagerService.java
@@ -0,0 +1,1040 @@
+/*
+ * 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;
+
+import android.app.ActivityManager;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.IBluetooth;
+import android.bluetooth.IBluetoothCallback;
+import android.bluetooth.IBluetoothManager;
+import android.bluetooth.IBluetoothManagerCallback;
+import android.bluetooth.IBluetoothStateChangeCallback;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+import java.util.ArrayList;
+import java.util.List;
+class BluetoothManagerService extends IBluetoothManager.Stub {
+    private static final String TAG = "BluetoothManagerService";
+    private static final boolean DBG = true;
+
+    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
+    private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
+    private static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED";
+    private static final String EXTRA_ACTION="action";
+    private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid";
+    private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address";
+    private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name";
+    private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
+    private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save
+    //Maximum msec to wait for service restart
+    private static final int SERVICE_RESTART_TIME_MS = 200;
+    //Maximum msec to delay MESSAGE_USER_SWITCHED
+    private static final int USER_SWITCHED_TIME_MS = 200;
+
+    private static final int MESSAGE_ENABLE = 1;
+    private static final int MESSAGE_DISABLE = 2;
+    private static final int MESSAGE_REGISTER_ADAPTER = 20;
+    private static final int MESSAGE_UNREGISTER_ADAPTER = 21;
+    private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30;
+    private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31;
+    private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40;
+    private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41;
+    private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42;
+    private static final int MESSAGE_BLUETOOTH_STATE_CHANGE=60;
+    private static final int MESSAGE_TIMEOUT_BIND =100;
+    private static final int MESSAGE_TIMEOUT_UNBIND =101;
+    private static final int MESSAGE_GET_NAME_AND_ADDRESS=200;
+    private static final int MESSAGE_SAVE_NAME_AND_ADDRESS=201;
+    private static final int MESSAGE_USER_SWITCHED = 300;
+    private static final int MAX_SAVE_RETRIES=3;
+
+    private final Context mContext;
+
+    // Locks are not provided for mName and mAddress.
+    // They are accessed in handler or broadcast receiver, same thread context.
+    private String mAddress;
+    private String mName;
+    private final ContentResolver mContentResolver;
+    private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks;
+    private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks;
+    private IBluetooth mBluetooth;
+    private boolean mBinding;
+    private boolean mUnbinding;
+    private boolean mQuietEnable = false;
+    private boolean mEnable;
+    private int mState;
+    private HandlerThread mThread;
+    private final BluetoothHandler mHandler;
+
+    private void registerForAirplaneMode(IntentFilter filter) {
+        final ContentResolver resolver = mContext.getContentResolver();
+        final String airplaneModeRadios = Settings.Global.getString(resolver,
+                Settings.Global.AIRPLANE_MODE_RADIOS);
+        final String toggleableRadios = Settings.Global.getString(resolver,
+                Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
+        boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true :
+                airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH);
+        if (mIsAirplaneSensitive) {
+            filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+        }
+    }
+
+    private final IBluetoothCallback mBluetoothCallback =  new IBluetoothCallback.Stub() {
+        @Override
+        public void onBluetoothStateChange(int prevState, int newState) throws RemoteException  {
+            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState);
+            mHandler.sendMessage(msg);
+        }
+    };
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) {
+                String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME);
+                if (DBG) Log.d(TAG, "Bluetooth Adapter name changed to " + newName);
+                if (newName != null) {
+                    storeNameAndAddress(newName, null);
+                }
+            } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
+                if (isAirplaneModeOn()) {
+                    // disable without persisting the setting
+                    mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE,
+                           0, 0));
+                } else if (isBluetoothPersistedStateOn()) {
+                    // enable without persisting the setting
+                    mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
+                           0, 0));
+                }
+            } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED,
+                       intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
+            }
+        }
+    };
+
+    BluetoothManagerService(Context context) {
+        mThread = new HandlerThread("BluetoothManager");
+        mThread.start();
+        mHandler = new BluetoothHandler(mThread.getLooper());
+
+        mContext = context;
+        mBluetooth = null;
+        mBinding = false;
+        mUnbinding = false;
+        mEnable = false;
+        mState = BluetoothAdapter.STATE_OFF;
+        mAddress = null;
+        mName = null;
+        mContentResolver = context.getContentResolver();
+        mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
+        mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
+        IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
+        filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
+        filter.addAction(Intent.ACTION_USER_SWITCHED);
+        registerForAirplaneMode(filter);
+        mContext.registerReceiver(mReceiver, filter);
+        boolean airplaneModeOn = isAirplaneModeOn();
+        boolean bluetoothOn = isBluetoothPersistedStateOn();
+        loadStoredNameAndAddress();
+        if (DBG) Log.d(TAG, "airplaneModeOn: " + airplaneModeOn + " bluetoothOn: " + bluetoothOn);
+        if (bluetoothOn) {
+            //Enable
+            if (DBG) Log.d(TAG, "Auto-enabling Bluetooth.");
+            enableHelper();
+        }
+
+        if (!isNameAndAddressSet()) {
+            //Sync the Bluetooth name and address from the Bluetooth Adapter
+            if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address...");
+            getNameAndAddress();
+        }
+    }
+
+    /**
+     *  Returns true if airplane mode is currently on
+     */
+    private final boolean isAirplaneModeOn() {
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
+    }
+
+    /**
+     *  Returns true if the Bluetooth saved state is "on"
+     */
+    private final boolean isBluetoothPersistedStateOn() {
+        return Settings.Global.getInt(mContentResolver,
+                Settings.Global.BLUETOOTH_ON, 0) ==1;
+    }
+
+    /**
+     *  Save the Bluetooth on/off state
+     *
+     */
+    private void persistBluetoothSetting(boolean setOn) {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                               Settings.Global.BLUETOOTH_ON,
+                               setOn ? 1 : 0);
+    }
+
+    /**
+     * Returns true if the Bluetooth Adapter's name and address is
+     * locally cached
+     * @return
+     */
+    private boolean isNameAndAddressSet() {
+        return mName !=null && mAddress!= null && mName.length()>0 && mAddress.length()>0;
+    }
+
+    /**
+     * Retrieve the Bluetooth Adapter's name and address and save it in
+     * in the local cache
+     */
+    private void loadStoredNameAndAddress() {
+        if (DBG) Log.d(TAG, "Loading stored name and address");
+        if (mContext.getResources().getBoolean
+            (com.android.internal.R.bool.config_bluetooth_address_validation) &&
+             Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) == 0) {
+            // if the valid flag is not set, don't load the address and name
+            if (DBG) Log.d(TAG, "invalid bluetooth name and address stored");
+            return;
+        }
+        mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME);
+        mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS);
+        if (DBG) Log.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress);
+    }
+
+    /**
+     * Save the Bluetooth name and address in the persistent store.
+     * Only non-null values will be saved.
+     * @param name
+     * @param address
+     */
+    private void storeNameAndAddress(String name, String address) {
+        if (name != null) {
+            Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name);
+            mName = name;
+            if (DBG) Log.d(TAG,"Stored Bluetooth name: " +
+                Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME));
+        }
+
+        if (address != null) {
+            Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address);
+            mAddress=address;
+            if (DBG)  Log.d(TAG,"Stored Bluetoothaddress: " +
+                Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS));
+        }
+
+        if ((name != null) && (address != null)) {
+            Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1);
+        }
+    }
+
+    public IBluetooth registerAdapter(IBluetoothManagerCallback callback){
+        Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER);
+        msg.obj = callback;
+        mHandler.sendMessage(msg);
+        synchronized(mConnection) {
+            return mBluetooth;
+        }
+    }
+
+    public void unregisterAdapter(IBluetoothManagerCallback callback) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+                                                "Need BLUETOOTH permission");
+        Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER);
+        msg.obj = callback;
+        mHandler.sendMessage(msg);
+    }
+
+    public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+                                                "Need BLUETOOTH permission");
+        Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK);
+        msg.obj = callback;
+        mHandler.sendMessage(msg);
+    }
+
+    public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+                                                "Need BLUETOOTH permission");
+        Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK);
+        msg.obj = callback;
+        mHandler.sendMessage(msg);
+    }
+
+    public boolean isEnabled() {
+        if (!checkIfCallerIsForegroundUser()) {
+            Log.w(TAG,"isEnabled(): not allowed for non-active user");
+            return false;
+        }
+
+        synchronized(mConnection) {
+            try {
+                return (mBluetooth != null && mBluetooth.isEnabled());
+            } catch (RemoteException e) {
+                Log.e(TAG, "isEnabled()", e);
+            }
+        }
+        return false;
+    }
+
+    public void getNameAndAddress() {
+        if (DBG) {
+            Log.d(TAG,"getNameAndAddress(): mBluetooth = " + mBluetooth +
+                  " mBinding = " + mBinding);
+        }
+        Message msg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
+        mHandler.sendMessage(msg);
+    }
+    public boolean enableNoAutoConnect()
+    {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH ADMIN permission");
+
+        if (!checkIfCallerIsForegroundUser()) {
+            Log.w(TAG,"enableNoAutoConnect(): not allowed for non-active user");
+            return false;
+        }
+
+        if (DBG) {
+            Log.d(TAG,"enableNoAutoConnect():  mBluetooth =" + mBluetooth +
+                    " mBinding = " + mBinding);
+        }
+        if (Binder.getCallingUid() != Process.NFC_UID) {
+            throw new SecurityException("no permission to enable Bluetooth quietly");
+        }
+        Message msg = mHandler.obtainMessage(MESSAGE_ENABLE);
+        msg.arg1=0; //No persist
+        msg.arg2=1; //Quiet mode
+        mHandler.sendMessage(msg);
+        return true;
+
+    }
+    public boolean enable() {
+        if (!checkIfCallerIsForegroundUser()) {
+            Log.w(TAG,"enable(): not allowed for non-active user");
+            return false;
+        }
+
+        return enableHelper();
+    }
+
+    public boolean disable(boolean persist) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH ADMIN permissicacheNameAndAddresson");
+
+        if (!checkIfCallerIsForegroundUser()) {
+            Log.w(TAG,"disable(): not allowed for non-active user");
+            return false;
+        }
+
+        if (DBG) {
+            Log.d(TAG,"disable(): mBluetooth = " + mBluetooth +
+                " mBinding = " + mBinding);
+        }
+
+        Message msg = mHandler.obtainMessage(MESSAGE_DISABLE);
+        msg.arg1=(persist?1:0);
+        mHandler.sendMessage(msg);
+        return true;
+    }
+
+    public void unbindAndFinish() {
+        if (DBG) {
+            Log.d(TAG,"unbindAndFinish(): " + mBluetooth +
+                " mBinding = " + mBinding);
+        }
+
+        synchronized (mConnection) {
+            if (mUnbinding) return;
+            mUnbinding = true;
+            if (mBluetooth != null) {
+                if (!mConnection.isGetNameAddressOnly()) {
+                    //Unregister callback object
+                    try {
+                        mBluetooth.unregisterCallback(mBluetoothCallback);
+                    } catch (RemoteException re) {
+                        Log.e(TAG, "Unable to unregister BluetoothCallback",re);
+                    }
+                }
+                if (DBG) Log.d(TAG, "Sending unbind request.");
+                mBluetooth = null;
+                //Unbind
+                mContext.unbindService(mConnection);
+                mUnbinding = false;
+                mBinding = false;
+            } else {
+                mUnbinding=false;
+            }
+        }
+    }
+
+    private void sendBluetoothStateCallback(boolean isUp) {
+        int n = mStateChangeCallbacks.beginBroadcast();
+        if (DBG) Log.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers.");
+        for (int i=0; i <n;i++) {
+            try {
+                mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i , e);
+            }
+        }
+        mStateChangeCallbacks.finishBroadcast();
+    }
+
+    /**
+     * Inform BluetoothAdapter instances that Adapter service is up
+     */
+    private void sendBluetoothServiceUpCallback() {
+        if (!mConnection.isGetNameAddressOnly()) {
+            if (DBG) Log.d(TAG,"Calling onBluetoothServiceUp callbacks");
+            int n = mCallbacks.beginBroadcast();
+            Log.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
+            for (int i=0; i <n;i++) {
+                try {
+                    mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
+                }  catch (RemoteException e) {
+                    Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
+                }
+            }
+            mCallbacks.finishBroadcast();
+        }
+    }
+    /**
+     * Inform BluetoothAdapter instances that Adapter service is down
+     */
+    private void sendBluetoothServiceDownCallback() {
+        if (!mConnection.isGetNameAddressOnly()) {
+            if (DBG) Log.d(TAG,"Calling onBluetoothServiceDown callbacks");
+            int n = mCallbacks.beginBroadcast();
+            Log.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers.");
+            for (int i=0; i <n;i++) {
+                try {
+                    mCallbacks.getBroadcastItem(i).onBluetoothServiceDown();
+                }  catch (RemoteException e) {
+                    Log.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
+                }
+            }
+            mCallbacks.finishBroadcast();
+        }
+    }
+    public String getAddress() {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH ADMIN permission");
+
+        if (!checkIfCallerIsForegroundUser()) {
+            Log.w(TAG,"getAddress(): not allowed for non-active user");
+            return mAddress;
+        }
+
+        synchronized(mConnection) {
+            if (mBluetooth != null) {
+                try {
+                    return mBluetooth.getAddress();
+                } catch (RemoteException e) {
+                    Log.e(TAG, "getAddress(): Unable to retrieve address remotely..Returning cached address",e);
+                }
+            }
+        }
+        // mAddress is accessed from outside.
+        // It is alright without a lock. Here, bluetooth is off, no other thread is
+        // changing mAddress
+        return mAddress;
+    }
+
+    public String getName() {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH ADMIN permission");
+
+        if (!checkIfCallerIsForegroundUser()) {
+            Log.w(TAG,"getName(): not allowed for non-active user");
+            return mName;
+        }
+
+        synchronized(mConnection) {
+            if (mBluetooth != null) {
+                try {
+                    return mBluetooth.getName();
+                } catch (RemoteException e) {
+                    Log.e(TAG, "getName(): Unable to retrieve name remotely..Returning cached name",e);
+                }
+            }
+        }
+        // mName is accessed from outside.
+        // It alright without a lock. Here, bluetooth is off, no other thread is
+        // changing mName
+        return mName;
+    }
+
+    private class BluetoothServiceConnection implements ServiceConnection {
+
+        private boolean mGetNameAddressOnly;
+
+        public void setGetNameAddressOnly(boolean getOnly) {
+            mGetNameAddressOnly = getOnly;
+        }
+
+        public boolean isGetNameAddressOnly() {
+            return mGetNameAddressOnly;
+        }
+
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            if (DBG) Log.d(TAG, "BluetoothServiceConnection: connected to AdapterService");
+            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
+            msg.obj = service;
+            mHandler.sendMessage(msg);
+        }
+
+        public void onServiceDisconnected(ComponentName className) {
+            // Called if we unexpected disconnected.
+            if (DBG) Log.d(TAG, "BluetoothServiceConnection: disconnected from AdapterService");
+            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
+            mHandler.sendMessage(msg);
+        }
+    }
+
+    private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
+
+    private class BluetoothHandler extends Handler {
+        public BluetoothHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            if (DBG) Log.d (TAG, "Message: " + msg.what);
+            switch (msg.what) {
+                case MESSAGE_GET_NAME_AND_ADDRESS: {
+                    if (DBG) Log.d(TAG,"MESSAGE_GET_NAME_AND_ADDRESS");
+                    synchronized(mConnection) {
+                        //Start bind request
+                        if ((mBluetooth == null) && (!mBinding)) {
+                            if (DBG) Log.d(TAG, "Binding to service to get name and address");
+                            mConnection.setGetNameAddressOnly(true);
+                            //Start bind timeout and bind
+                            Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
+                            mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
+                            Intent i = new Intent(IBluetooth.class.getName());
+                            if (!mContext.bindService(i, mConnection,
+                                  Context.BIND_AUTO_CREATE, UserHandle.USER_CURRENT)) {
+                                mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
+                                Log.e(TAG, "fail to bind to: " + IBluetooth.class.getName());
+                            } else {
+                                mBinding = true;
+                            }
+                        }
+                        else {
+                            Message saveMsg= mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
+                            saveMsg.arg1 = 0;
+                            if (mBluetooth != null) {
+                                mHandler.sendMessage(saveMsg);
+                            } else {
+                                // if enable is also called to bind the service
+                                // wait for MESSAGE_BLUETOOTH_SERVICE_CONNECTED
+                                mHandler.sendMessageDelayed(saveMsg, TIMEOUT_SAVE_MS);
+                            }
+                        }
+                    }
+                    break;
+                }
+                case MESSAGE_SAVE_NAME_AND_ADDRESS: {
+                    boolean unbind = false;
+                    if (DBG) Log.d(TAG,"MESSAGE_SAVE_NAME_AND_ADDRESS");
+                    synchronized(mConnection) {
+                        if (!mEnable && mBluetooth != null) {
+                            try {
+                                mBluetooth.enable();
+                            } catch (RemoteException e) {
+                                Log.e(TAG,"Unable to call enable()",e);
+                            }
+                        }
+                    }
+                    if (mBluetooth != null) waitForOnOff(true, false);
+                    synchronized(mConnection) {
+                        if (mBluetooth != null) {
+                            String name =  null;
+                            String address = null;
+                            try {
+                                name =  mBluetooth.getName();
+                                address = mBluetooth.getAddress();
+                            } catch (RemoteException re) {
+                                Log.e(TAG,"",re);
+                            }
+
+                            if (name != null && address != null) {
+                                storeNameAndAddress(name,address);
+                                if (mConnection.isGetNameAddressOnly()) {
+                                    unbind = true;
+                                }
+                            } else {
+                                if (msg.arg1 < MAX_SAVE_RETRIES) {
+                                    Message retryMsg = mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
+                                    retryMsg.arg1= 1+msg.arg1;
+                                    if (DBG) Log.d(TAG,"Retrying name/address remote retrieval and save.....Retry count =" + retryMsg.arg1);
+                                    mHandler.sendMessageDelayed(retryMsg, TIMEOUT_SAVE_MS);
+                                } else {
+                                    Log.w(TAG,"Maximum name/address remote retrieval retry exceeded");
+                                    if (mConnection.isGetNameAddressOnly()) {
+                                        unbind = true;
+                                    }
+                                }
+                            }
+                            if (!mEnable) {
+                                try {
+                                    mBluetooth.disable();
+                                } catch (RemoteException e) {
+                                    Log.e(TAG,"Unable to call disable()",e);
+                                }
+                            }
+                        } else {
+                            // rebind service by Request GET NAME AND ADDRESS
+                            // if service is unbinded by disable or
+                            // MESSAGE_BLUETOOTH_SERVICE_CONNECTED is not received
+                            Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
+                            mHandler.sendMessage(getMsg);
+                        }
+                    }
+                    if (!mEnable && mBluetooth != null) waitForOnOff(false, true);
+                    if (unbind) {
+                        unbindAndFinish();
+                    }
+                    break;
+                }
+                case MESSAGE_ENABLE:
+                    if (DBG) {
+                        Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);
+                    }
+                    mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
+                    mEnable = true;
+                    handleEnable(msg.arg1 == 1, msg.arg2 ==1);
+                    break;
+
+                case MESSAGE_DISABLE:
+                    mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
+                    if (mEnable && mBluetooth != null) {
+                        waitForOnOff(true, false);
+                        mEnable = false;
+                        handleDisable(msg.arg1 == 1);
+                        waitForOnOff(false, false);
+                    } else {
+                        mEnable = false;
+                        handleDisable(msg.arg1 == 1);
+                    }
+                    break;
+
+                case MESSAGE_REGISTER_ADAPTER:
+                {
+                    IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
+                    boolean added = mCallbacks.register(callback);
+                    Log.d(TAG,"Added callback: " +  (callback == null? "null": callback)  +":" +added );
+                }
+                    break;
+                case MESSAGE_UNREGISTER_ADAPTER:
+                {
+                    IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
+                    boolean removed = mCallbacks.unregister(callback);
+                    Log.d(TAG,"Removed callback: " +  (callback == null? "null": callback)  +":" + removed);
+                    break;
+                }
+                case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK:
+                {
+                    IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
+                    mStateChangeCallbacks.register(callback);
+                    break;
+                }
+                case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK:
+                {
+                    IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
+                    mStateChangeCallbacks.unregister(callback);
+                    break;
+                }
+                case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
+                {
+                    if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED");
+
+                    //Remove timeout
+                    mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
+
+                    IBinder service = (IBinder) msg.obj;
+                    synchronized(mConnection) {
+                        mBinding = false;
+                        mBluetooth = IBluetooth.Stub.asInterface(service);
+
+                        if (mConnection.isGetNameAddressOnly()) {
+                            //Request GET NAME AND ADDRESS
+                            Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
+                            mHandler.sendMessage(getMsg);
+                            if (!mEnable) return;
+                        }
+
+                        mConnection.setGetNameAddressOnly(false);
+                        //Register callback object
+                        try {
+                            mBluetooth.registerCallback(mBluetoothCallback);
+                        } catch (RemoteException re) {
+                            Log.e(TAG, "Unable to register BluetoothCallback",re);
+                        }
+                        //Inform BluetoothAdapter instances that service is up
+                        sendBluetoothServiceUpCallback();
+
+                        //Do enable request
+                        try {
+                            if (mQuietEnable == false) {
+                                if(!mBluetooth.enable()) {
+                                    Log.e(TAG,"IBluetooth.enable() returned false");
+                                }
+                            }
+                            else
+                            {
+                                if(!mBluetooth.enableNoAutoConnect()) {
+                                    Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
+                                }
+                            }
+                        } catch (RemoteException e) {
+                            Log.e(TAG,"Unable to call enable()",e);
+                        }
+                    }
+
+                    if (!mEnable) {
+                        waitForOnOff(true, false);
+                        handleDisable(false);
+                        waitForOnOff(false, false);
+                    }
+                    break;
+                }
+                case MESSAGE_TIMEOUT_BIND: {
+                    Log.e(TAG, "MESSAGE_TIMEOUT_BIND");
+                    synchronized(mConnection) {
+                        mBinding = false;
+                    }
+                    break;
+                }
+                case MESSAGE_BLUETOOTH_STATE_CHANGE:
+                {
+                    int prevState = msg.arg1;
+                    int newState = msg.arg2;
+                    if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState=" + newState);
+                    mState = newState;
+                    bluetoothStateChangeHandler(prevState, newState);
+                    break;
+                }
+                case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED:
+                {
+                    Log.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED");
+                    synchronized(mConnection) {
+                        // if service is unbinded already, do nothing and return
+                        if (mBluetooth == null) return;
+                        mBluetooth = null;
+                    }
+
+                    if (mEnable) {
+                        mEnable = false;
+                        // Send a Bluetooth Restart message
+                        Message restartMsg = mHandler.obtainMessage(
+                            MESSAGE_RESTART_BLUETOOTH_SERVICE);
+                        mHandler.sendMessageDelayed(restartMsg,
+                            SERVICE_RESTART_TIME_MS);
+                    }
+
+                    if (!mConnection.isGetNameAddressOnly()) {
+                        sendBluetoothServiceDownCallback();
+
+                        // Send BT state broadcast to update
+                        // the BT icon correctly
+                        bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
+                                                    BluetoothAdapter.STATE_TURNING_OFF);
+                        mState = BluetoothAdapter.STATE_OFF;
+                    }
+                    break;
+                }
+                case MESSAGE_RESTART_BLUETOOTH_SERVICE:
+                {
+                    Log.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE:"
+                        +" Restart IBluetooth service");
+                    /* Enable without persisting the setting as
+                     it doesnt change when IBluetooth
+                     service restarts */
+                    mEnable = true;
+                    handleEnable(false, mQuietEnable);
+                    break;
+                }
+
+                case MESSAGE_TIMEOUT_UNBIND:
+                {
+                    Log.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
+                    synchronized(mConnection) {
+                        mUnbinding = false;
+                    }
+                    break;
+                }
+
+                case MESSAGE_USER_SWITCHED:
+                {
+                    if (DBG) {
+                        Log.d(TAG, "MESSAGE_USER_SWITCHED");
+                    }
+                    mHandler.removeMessages(MESSAGE_USER_SWITCHED);
+                    /* disable and enable BT when detect a user switch */
+                    if (mEnable && mBluetooth != null) {
+                        synchronized (mConnection) {
+                            if (mBluetooth != null) {
+                                //Unregister callback object
+                                try {
+                                    mBluetooth.unregisterCallback(mBluetoothCallback);
+                                } catch (RemoteException re) {
+                                    Log.e(TAG, "Unable to unregister",re);
+                                }
+                            }
+                        }
+                        mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
+
+                        waitForOnOff(true, false);
+
+                        bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
+
+                        // disable
+                        handleDisable(false);
+
+                        waitForOnOff(false, true);
+
+                        bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
+                                                    BluetoothAdapter.STATE_OFF);
+                        mState = BluetoothAdapter.STATE_OFF;
+                        sendBluetoothServiceDownCallback();
+                        synchronized (mConnection) {
+                            if (mBluetooth != null) {
+                                mBluetooth = null;
+                                //Unbind
+                                mContext.unbindService(mConnection);
+                            }
+                        }
+                        SystemClock.sleep(100);
+
+                        // enable
+                        handleEnable(false, mQuietEnable);
+		    } else if (mBinding || mBluetooth != null) {
+                        Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
+                        userMsg.arg2 = 1 + msg.arg2;
+                        // if user is switched when service is being binding
+                        // delay sending MESSAGE_USER_SWITCHED
+                        mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS);
+                        if (DBG) {
+                            Log.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2);
+                        }
+		    }
+                    break;
+                }
+            }
+        }
+    }
+
+    private void handleEnable(boolean persist, boolean quietMode) {
+        if (persist) {
+            persistBluetoothSetting(true);
+        }
+
+        mQuietEnable = quietMode;
+
+        synchronized(mConnection) {
+            if ((mBluetooth == null) && (!mBinding)) {
+                //Start bind timeout and bind
+                Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
+                mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
+                mConnection.setGetNameAddressOnly(false);
+                Intent i = new Intent(IBluetooth.class.getName());
+                if (!mContext.bindService(i, mConnection,Context.BIND_AUTO_CREATE,
+                                          UserHandle.USER_CURRENT)) {
+                    mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
+                    Log.e(TAG, "Fail to bind to: " + IBluetooth.class.getName());
+                } else {
+                    mBinding = true;
+                }
+            } else if (mBluetooth != null) {
+                if (mConnection.isGetNameAddressOnly()) {
+                    // if GetNameAddressOnly is set, we can clear this flag,
+                    // so the service won't be unbind
+                    // after name and address are saved
+                    mConnection.setGetNameAddressOnly(false);
+                    //Register callback object
+                    try {
+                        mBluetooth.registerCallback(mBluetoothCallback);
+                    } catch (RemoteException re) {
+                        Log.e(TAG, "Unable to register BluetoothCallback",re);
+                    }
+                    //Inform BluetoothAdapter instances that service is up
+                    sendBluetoothServiceUpCallback();
+                }
+
+                //Enable bluetooth
+                try {
+                    if (!mQuietEnable) {
+                        if(!mBluetooth.enable()) {
+                            Log.e(TAG,"IBluetooth.enable() returned false");
+                        }
+                    }
+                    else {
+                        if(!mBluetooth.enableNoAutoConnect()) {
+                            Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
+                        }
+                    }
+                } catch (RemoteException e) {
+                    Log.e(TAG,"Unable to call enable()",e);
+                }
+            }
+        }
+    }
+
+    private void handleDisable(boolean persist) {
+        if (persist) {
+            persistBluetoothSetting(false);
+        }
+
+        synchronized(mConnection) {
+            // don't need to disable if GetNameAddressOnly is set,
+            // service will be unbinded after Name and Address are saved
+            if ((mBluetooth != null) && (!mConnection.isGetNameAddressOnly())) {
+                if (DBG) Log.d(TAG,"Sending off request.");
+
+                try {
+                    if(!mBluetooth.disable()) {
+                        Log.e(TAG,"IBluetooth.disable() returned false");
+                    }
+                } catch (RemoteException e) {
+                    Log.e(TAG,"Unable to call disable()",e);
+                }
+            }
+        }
+    }
+
+    private boolean checkIfCallerIsForegroundUser() {
+        int foregroundUser;
+        int callingUser = UserHandle.getCallingUserId();
+        long callingIdentity = Binder.clearCallingIdentity();
+        boolean valid = false;
+        try {
+            foregroundUser = ActivityManager.getCurrentUser();
+            valid = (callingUser == foregroundUser);
+            if (DBG) {
+                Log.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid
+                    + " callingUser=" + callingUser
+                    + " foregroundUser=" + foregroundUser);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingIdentity);
+        }
+        return valid;
+    }
+
+    private boolean enableHelper() {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH ADMIN permission");
+        if (DBG) {
+            Log.d(TAG,"enable():  mBluetooth =" + mBluetooth +
+                    " mBinding = " + mBinding);
+        }
+
+        Message msg = mHandler.obtainMessage(MESSAGE_ENABLE);
+        msg.arg1=1; //persist
+        msg.arg2=0; //No Quiet Mode
+        mHandler.sendMessage(msg);
+        return true;
+    }
+
+    private void bluetoothStateChangeHandler(int prevState, int newState) {
+        if (prevState != newState) {
+            //Notify all proxy objects first of adapter state change
+            if (newState == BluetoothAdapter.STATE_ON || newState == BluetoothAdapter.STATE_OFF) {
+                boolean isUp = (newState==BluetoothAdapter.STATE_ON);
+                sendBluetoothStateCallback(isUp);
+
+                //If Bluetooth is off, send service down event to proxy objects, and unbind
+                if (!isUp) {
+                    //Only unbind with mEnable flag not set
+                    //For race condition: disable and enable back-to-back
+                    //Avoid unbind right after enable due to callback from disable
+                    if ((!mEnable) && (mBluetooth != null)) {
+                        sendBluetoothServiceDownCallback();
+                        unbindAndFinish();
+                    }
+                }
+            }
+
+            //Send broadcast message to everyone else
+            Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
+            intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
+            intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+            if (DBG) Log.d(TAG,"Bluetooth State Change Intent: " + prevState + " -> " + newState);
+            mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+                    BLUETOOTH_PERM);
+        }
+    }
+
+    /**
+     *  if on is true, wait for state become ON
+     *  if off is true, wait for state become OFF
+     *  if both on and off are false, wait for state not ON
+     */
+    private boolean waitForOnOff(boolean on, boolean off) {
+        int i = 0;
+        while (i < 10) {
+            synchronized(mConnection) {
+                try {
+                    if (mBluetooth == null) break;
+                    if (on) {
+                        if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true;
+                    } else if (off) {
+                        if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true;
+		    } else {
+                        if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true;
+		    }
+                } catch (RemoteException e) {
+                    Log.e(TAG, "getState()", e);
+                    break;
+                }
+            }
+            if (on || off) {
+                SystemClock.sleep(300);
+	    } else {
+                SystemClock.sleep(50);
+	    }
+            i++;
+        }
+        Log.e(TAG,"waitForOnOff time out");
+        return false;
+    }
+}
diff --git a/services/java/com/android/server/BootReceiver.java b/services/java/com/android/server/BootReceiver.java
index 22874e6..7e1de5a 100644
--- a/services/java/com/android/server/BootReceiver.java
+++ b/services/java/com/android/server/BootReceiver.java
@@ -88,6 +88,8 @@
         final String headers = new StringBuilder(512)
             .append("Build: ").append(Build.FINGERPRINT).append("\n")
             .append("Hardware: ").append(Build.BOARD).append("\n")
+            .append("Revision: ")
+            .append(SystemProperties.get("ro.revision", "")).append("\n")
             .append("Bootloader: ").append(Build.BOOTLOADER).append("\n")
             .append("Radio: ").append(Build.RADIO).append("\n")
             .append("Kernel: ")
diff --git a/services/java/com/android/server/ClipboardService.java b/services/java/com/android/server/ClipboardService.java
index 8a6a550..74ec6e2 100644
--- a/services/java/com/android/server/ClipboardService.java
+++ b/services/java/com/android/server/ClipboardService.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
 import android.app.IActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.ClipData;
@@ -26,6 +27,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -36,7 +38,7 @@
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -96,7 +98,7 @@
             public void onReceive(Context context, Intent intent) {
                 String action = intent.getAction();
                 if (Intent.ACTION_USER_REMOVED.equals(action)) {
-                    removeClipboard(intent.getIntExtra(Intent.EXTRA_USERID, 0));
+                    removeClipboard(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
                 }
             }
         }, userFilter);
@@ -115,12 +117,11 @@
     }
 
     private PerUserClipboard getClipboard() {
-        return getClipboard(UserId.getCallingUserId());
+        return getClipboard(UserHandle.getCallingUserId());
     }
 
     private PerUserClipboard getClipboard(int userId) {
         synchronized (mClipboards) {
-            Slog.i(TAG, "Got clipboard for user=" + userId);
             PerUserClipboard puc = mClipboards.get(userId);
             if (puc == null) {
                 puc = new PerUserClipboard(userId);
@@ -255,15 +256,22 @@
     }
 
     private final void addActiveOwnerLocked(int uid, String pkg) {
-        PackageInfo pi;
+        final IPackageManager pm = AppGlobals.getPackageManager();
+        final int targetUserHandle = UserHandle.getCallingUserId();
+        final long oldIdentity = Binder.clearCallingIdentity();
         try {
-            pi = mPm.getPackageInfo(pkg, 0);
-            if (!UserId.isSameApp(pi.applicationInfo.uid, uid)) {
+            PackageInfo pi = pm.getPackageInfo(pkg, 0, targetUserHandle);
+            if (pi == null) {
+                throw new IllegalArgumentException("Unknown package " + pkg);
+            }
+            if (!UserHandle.isSameApp(pi.applicationInfo.uid, uid)) {
                 throw new SecurityException("Calling uid " + uid
                         + " does not own package " + pkg);
             }
-        } catch (NameNotFoundException e) {
-            throw new IllegalArgumentException("Unknown package " + pkg, e);
+        } catch (RemoteException e) {
+            // Can't happen; the package manager is in the same process
+        } finally {
+            Binder.restoreCallingIdentity(oldIdentity);
         }
         PerUserClipboard clipboard = getClipboard();
         if (clipboard.primaryClip != null && !clipboard.activePermissionOwners.contains(pkg)) {
diff --git a/services/java/com/android/server/CommonTimeManagementService.java b/services/java/com/android/server/CommonTimeManagementService.java
index 9a25d2e..c316733 100644
--- a/services/java/com/android/server/CommonTimeManagementService.java
+++ b/services/java/com/android/server/CommonTimeManagementService.java
@@ -120,6 +120,8 @@
             reevaluateServiceState();
         }
         public void limitReached(String limitName, String iface) { }
+
+        public void interfaceClassDataActivityChanged(String label, boolean active) {}
     };
 
     private BroadcastReceiver mConnectivityMangerObserver = new BroadcastReceiver() {
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 86ada40..ad1dfb2 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -16,25 +16,39 @@
 
 package com.android.server;
 
+import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
 import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
+import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
+import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
+import static android.net.ConnectivityManager.TYPE_DUMMY;
+import static android.net.ConnectivityManager.TYPE_ETHERNET;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.ConnectivityManager.TYPE_WIMAX;
+import static android.net.ConnectivityManager.getNetworkTypeName;
 import static android.net.ConnectivityManager.isNetworkTypeValid;
 import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
 
+import android.app.Activity;
 import android.bluetooth.BluetoothTetheringDataTracker;
+import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.database.ContentObserver;
+import android.net.CaptivePortalTracker;
 import android.net.ConnectivityManager;
 import android.net.DummyDataStateTracker;
 import android.net.EthernetDataTracker;
 import android.net.IConnectivityManager;
+import android.net.INetworkManagementEventObserver;
 import android.net.INetworkPolicyListener;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
@@ -64,11 +78,15 @@
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.provider.Settings;
+import android.security.Credentials;
+import android.security.KeyStore;
 import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.Slog;
@@ -76,21 +94,24 @@
 
 import com.android.internal.net.LegacyVpnInfo;
 import com.android.internal.net.VpnConfig;
+import com.android.internal.net.VpnProfile;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.am.BatteryStatsService;
 import com.android.server.connectivity.Tethering;
 import com.android.server.connectivity.Vpn;
+import com.android.server.net.BaseNetworkObserver;
+import com.android.server.net.LockdownVpnTracker;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Sets;
+
 import dalvik.system.DexClassLoader;
+
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.InvocationTargetException;
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
@@ -106,13 +127,15 @@
  * @hide
  */
 public class ConnectivityService extends IConnectivityManager.Stub {
+    private static final String TAG = "ConnectivityService";
 
     private static final boolean DBG = true;
     private static final boolean VDBG = false;
-    private static final String TAG = "ConnectivityService";
 
     private static final boolean LOGD_RULES = false;
 
+    // TODO: create better separation between radio types and network types
+
     // how long to wait before switching back to a radio's default network
     private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
     // system property that can override the above value
@@ -126,7 +149,13 @@
     private Tethering mTethering;
     private boolean mTetheringConfigValid = false;
 
+    private KeyStore mKeyStore;
+
     private Vpn mVpn;
+    private VpnCallback mVpnCallback = new VpnCallback();
+
+    private boolean mLockdownEnabled;
+    private LockdownVpnTracker mLockdownTracker;
 
     /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */
     private Object mRulesLock = new Object();
@@ -142,6 +171,9 @@
      */
     private NetworkStateTracker mNetTrackers[];
 
+    /* Handles captive portal check on a network */
+    private CaptivePortalTracker mCaptivePortalTracker;
+
     /**
      * The link properties that define the current links
      */
@@ -186,95 +218,83 @@
     private static final boolean TO_DEFAULT_TABLE = true;
     private static final boolean TO_SECONDARY_TABLE = false;
 
-    // Share the event space with NetworkStateTracker (which can't see this
-    // internal class but sends us events).  If you change these, change
-    // NetworkStateTracker.java too.
-    private static final int MIN_NETWORK_STATE_TRACKER_EVENT = 1;
-    private static final int MAX_NETWORK_STATE_TRACKER_EVENT = 100;
-
     /**
      * used internally as a delayed event to make us switch back to the
      * default network
      */
-    private static final int EVENT_RESTORE_DEFAULT_NETWORK =
-            MAX_NETWORK_STATE_TRACKER_EVENT + 1;
+    private static final int EVENT_RESTORE_DEFAULT_NETWORK = 1;
 
     /**
      * used internally to change our mobile data enabled flag
      */
-    private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED =
-            MAX_NETWORK_STATE_TRACKER_EVENT + 2;
+    private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED = 2;
 
     /**
      * used internally to change our network preference setting
      * arg1 = networkType to prefer
      */
-    private static final int EVENT_SET_NETWORK_PREFERENCE =
-            MAX_NETWORK_STATE_TRACKER_EVENT + 3;
+    private static final int EVENT_SET_NETWORK_PREFERENCE = 3;
 
     /**
      * used internally to synchronize inet condition reports
      * arg1 = networkType
      * arg2 = condition (0 bad, 100 good)
      */
-    private static final int EVENT_INET_CONDITION_CHANGE =
-            MAX_NETWORK_STATE_TRACKER_EVENT + 4;
+    private static final int EVENT_INET_CONDITION_CHANGE = 4;
 
     /**
      * used internally to mark the end of inet condition hold periods
      * arg1 = networkType
      */
-    private static final int EVENT_INET_CONDITION_HOLD_END =
-            MAX_NETWORK_STATE_TRACKER_EVENT + 5;
+    private static final int EVENT_INET_CONDITION_HOLD_END = 5;
 
     /**
      * used internally to set enable/disable cellular data
      * arg1 = ENBALED or DISABLED
      */
-    private static final int EVENT_SET_MOBILE_DATA =
-            MAX_NETWORK_STATE_TRACKER_EVENT + 7;
+    private static final int EVENT_SET_MOBILE_DATA = 7;
 
     /**
      * used internally to clear a wakelock when transitioning
      * from one net to another
      */
-    private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK =
-            MAX_NETWORK_STATE_TRACKER_EVENT + 8;
+    private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK = 8;
 
     /**
      * used internally to reload global proxy settings
      */
-    private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY =
-            MAX_NETWORK_STATE_TRACKER_EVENT + 9;
+    private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = 9;
 
     /**
      * used internally to set external dependency met/unmet
      * arg1 = ENABLED (met) or DISABLED (unmet)
      * arg2 = NetworkType
      */
-    private static final int EVENT_SET_DEPENDENCY_MET =
-            MAX_NETWORK_STATE_TRACKER_EVENT + 10;
+    private static final int EVENT_SET_DEPENDENCY_MET = 10;
 
     /**
      * used internally to restore DNS properties back to the
      * default network
      */
-    private static final int EVENT_RESTORE_DNS =
-            MAX_NETWORK_STATE_TRACKER_EVENT + 11;
+    private static final int EVENT_RESTORE_DNS = 11;
 
     /**
      * used internally to send a sticky broadcast delayed.
      */
-    private static final int EVENT_SEND_STICKY_BROADCAST_INTENT =
-            MAX_NETWORK_STATE_TRACKER_EVENT + 12;
+    private static final int EVENT_SEND_STICKY_BROADCAST_INTENT = 12;
 
     /**
      * Used internally to
      * {@link NetworkStateTracker#setPolicyDataEnable(boolean)}.
      */
-    private static final int EVENT_SET_POLICY_DATA_ENABLE = MAX_NETWORK_STATE_TRACKER_EVENT + 13;
+    private static final int EVENT_SET_POLICY_DATA_ENABLE = 13;
 
-    private Handler mHandler;
+    private static final int EVENT_VPN_STATE_CHANGED = 14;
+
+    /** Handler used for internal events. */
+    private InternalHandler mHandler;
+    /** Handler used for incoming {@link NetworkStateTracker} events. */
+    private NetworkStateTrackerHandler mTrackerHandler;
 
     // list of DeathRecipients used to make sure features are turned off when
     // a process dies
@@ -328,11 +348,24 @@
 
     public ConnectivityService(Context context, INetworkManagementService netd,
             INetworkStatsService statsService, INetworkPolicyManager policyManager) {
+        // Currently, omitting a NetworkFactory will create one internally
+        // TODO: create here when we have cleaner WiMAX support
+        this(context, netd, statsService, policyManager, null);
+    }
+
+    public ConnectivityService(Context context, INetworkManagementService netManager,
+            INetworkStatsService statsService, INetworkPolicyManager policyManager,
+            NetworkFactory netFactory) {
         if (DBG) log("ConnectivityService starting up");
 
         HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
         handlerThread.start();
-        mHandler = new MyHandler(handlerThread.getLooper());
+        mHandler = new InternalHandler(handlerThread.getLooper());
+        mTrackerHandler = new NetworkStateTrackerHandler(handlerThread.getLooper());
+
+        if (netFactory == null) {
+            netFactory = new DefaultNetworkFactory(context, mTrackerHandler);
+        }
 
         // setup our unique device name
         if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) {
@@ -345,8 +378,8 @@
         }
 
         // read our default dns server ip
-        String dns = Settings.Secure.getString(context.getContentResolver(),
-                Settings.Secure.DEFAULT_DNS_SERVER);
+        String dns = Settings.Global.getString(context.getContentResolver(),
+                Settings.Global.DEFAULT_DNS_SERVER);
         if (dns == null || dns.length() == 0) {
             dns = context.getResources().getString(
                     com.android.internal.R.string.config_default_dns_server);
@@ -358,8 +391,9 @@
         }
 
         mContext = checkNotNull(context, "missing Context");
-        mNetd = checkNotNull(netd, "missing INetworkManagementService");
+        mNetd = checkNotNull(netManager, "missing INetworkManagementService");
         mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
+        mKeyStore = KeyStore.getInstance();
 
         try {
             mPolicyManager.registerListener(mPolicyListener);
@@ -472,69 +506,38 @@
 
         mTestMode = SystemProperties.get("cm.test.mode").equals("true")
                 && SystemProperties.get("ro.build.type").equals("eng");
-        /*
-         * Create the network state trackers for Wi-Fi and mobile
-         * data. Maybe this could be done with a factory class,
-         * but it's not clear that it's worth it, given that
-         * the number of different network types is not going
-         * to change very often.
-         */
-        for (int netType : mPriorityList) {
-            switch (mNetConfigs[netType].radio) {
-            case ConnectivityManager.TYPE_WIFI:
-                mNetTrackers[netType] = new WifiStateTracker(netType,
-                        mNetConfigs[netType].name);
-                mNetTrackers[netType].startMonitoring(context, mHandler);
-               break;
-            case ConnectivityManager.TYPE_MOBILE:
-                mNetTrackers[netType] = new MobileDataStateTracker(netType,
-                        mNetConfigs[netType].name);
-                mNetTrackers[netType].startMonitoring(context, mHandler);
-                break;
-            case ConnectivityManager.TYPE_DUMMY:
-                mNetTrackers[netType] = new DummyDataStateTracker(netType,
-                        mNetConfigs[netType].name);
-                mNetTrackers[netType].startMonitoring(context, mHandler);
-                break;
-            case ConnectivityManager.TYPE_BLUETOOTH:
-                mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance();
-                mNetTrackers[netType].startMonitoring(context, mHandler);
-                break;
-            case ConnectivityManager.TYPE_WIMAX:
-                mNetTrackers[netType] = makeWimaxStateTracker();
-                if (mNetTrackers[netType]!= null) {
-                    mNetTrackers[netType].startMonitoring(context, mHandler);
-                }
-                break;
-            case ConnectivityManager.TYPE_ETHERNET:
-                mNetTrackers[netType] = EthernetDataTracker.getInstance();
-                mNetTrackers[netType].startMonitoring(context, mHandler);
-                break;
-            default:
-                loge("Trying to create a DataStateTracker for an unknown radio type " +
-                        mNetConfigs[netType].radio);
+
+        // Create and start trackers for hard-coded networks
+        for (int targetNetworkType : mPriorityList) {
+            final NetworkConfig config = mNetConfigs[targetNetworkType];
+            final NetworkStateTracker tracker;
+            try {
+                tracker = netFactory.createTracker(targetNetworkType, config);
+                mNetTrackers[targetNetworkType] = tracker;
+            } catch (IllegalArgumentException e) {
+                Slog.e(TAG, "Problem creating " + getNetworkTypeName(targetNetworkType)
+                        + " tracker: " + e);
                 continue;
             }
-            mCurrentLinkProperties[netType] = null;
-            if (mNetTrackers[netType] != null && mNetConfigs[netType].isDefault()) {
-                mNetTrackers[netType].reconnect();
+
+            tracker.startMonitoring(context, mTrackerHandler);
+            if (config.isDefault()) {
+                tracker.reconnect();
             }
         }
 
-        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
-        INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b);
-
-        mTethering = new Tethering(mContext, nmService, statsService, this, mHandler.getLooper());
+        mTethering = new Tethering(mContext, mNetd, statsService, this, mHandler.getLooper());
         mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 ||
                                   mTethering.getTetherableWifiRegexs().length != 0 ||
                                   mTethering.getTetherableBluetoothRegexs().length != 0) &&
                                  mTethering.getUpstreamIfaceTypes().length != 0);
 
-        mVpn = new Vpn(mContext, new VpnCallback());
+        mVpn = new Vpn(mContext, mVpnCallback, mNetd);
+        mVpn.startMonitoring(mContext, mTrackerHandler);
 
         try {
-            nmService.registerObserver(mTethering);
-            nmService.registerObserver(mVpn);
+            mNetd.registerObserver(mTethering);
+            mNetd.registerObserver(mDataActivityObserver);
         } catch (RemoteException e) {
             loge("Error registering observer :" + e);
         }
@@ -546,10 +549,58 @@
         mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
         mSettingsObserver.observe(mContext);
 
+        mCaptivePortalTracker = CaptivePortalTracker.makeCaptivePortalTracker(mContext, this);
         loadGlobalProxy();
     }
-private NetworkStateTracker makeWimaxStateTracker() {
-        //Initialize Wimax
+
+    /**
+     * Factory that creates {@link NetworkStateTracker} instances using given
+     * {@link NetworkConfig}.
+     */
+    public interface NetworkFactory {
+        public NetworkStateTracker createTracker(int targetNetworkType, NetworkConfig config);
+    }
+
+    private static class DefaultNetworkFactory implements NetworkFactory {
+        private final Context mContext;
+        private final Handler mTrackerHandler;
+
+        public DefaultNetworkFactory(Context context, Handler trackerHandler) {
+            mContext = context;
+            mTrackerHandler = trackerHandler;
+        }
+
+        @Override
+        public NetworkStateTracker createTracker(int targetNetworkType, NetworkConfig config) {
+            switch (config.radio) {
+                case TYPE_WIFI:
+                    return new WifiStateTracker(targetNetworkType, config.name);
+                case TYPE_MOBILE:
+                    return new MobileDataStateTracker(targetNetworkType, config.name);
+                case TYPE_DUMMY:
+                    return new DummyDataStateTracker(targetNetworkType, config.name);
+                case TYPE_BLUETOOTH:
+                    return BluetoothTetheringDataTracker.getInstance();
+                case TYPE_WIMAX:
+                    return makeWimaxStateTracker(mContext, mTrackerHandler);
+                case TYPE_ETHERNET:
+                    return EthernetDataTracker.getInstance();
+                default:
+                    throw new IllegalArgumentException(
+                            "Trying to create a NetworkStateTracker for an unknown radio type: "
+                            + config.radio);
+            }
+        }
+    }
+
+    /**
+     * Loads external WiMAX library and registers as system service, returning a
+     * {@link NetworkStateTracker} for WiMAX. Caller is still responsible for
+     * invoking {@link NetworkStateTracker#startMonitoring(Context, Handler)}.
+     */
+    private static NetworkStateTracker makeWimaxStateTracker(
+            Context context, Handler trackerHandler) {
+        // Initialize Wimax
         DexClassLoader wimaxClassLoader;
         Class wimaxStateTrackerClass = null;
         Class wimaxServiceClass = null;
@@ -562,25 +613,25 @@
 
         NetworkStateTracker wimaxStateTracker = null;
 
-        boolean isWimaxEnabled = mContext.getResources().getBoolean(
+        boolean isWimaxEnabled = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_wimaxEnabled);
 
         if (isWimaxEnabled) {
             try {
-                wimaxJarLocation = mContext.getResources().getString(
+                wimaxJarLocation = context.getResources().getString(
                         com.android.internal.R.string.config_wimaxServiceJarLocation);
-                wimaxLibLocation = mContext.getResources().getString(
+                wimaxLibLocation = context.getResources().getString(
                         com.android.internal.R.string.config_wimaxNativeLibLocation);
-                wimaxManagerClassName = mContext.getResources().getString(
+                wimaxManagerClassName = context.getResources().getString(
                         com.android.internal.R.string.config_wimaxManagerClassname);
-                wimaxServiceClassName = mContext.getResources().getString(
+                wimaxServiceClassName = context.getResources().getString(
                         com.android.internal.R.string.config_wimaxServiceClassname);
-                wimaxStateTrackerClassName = mContext.getResources().getString(
+                wimaxStateTrackerClassName = context.getResources().getString(
                         com.android.internal.R.string.config_wimaxStateTrackerClassname);
 
-                log("wimaxJarLocation: " + wimaxJarLocation);
+                if (DBG) log("wimaxJarLocation: " + wimaxJarLocation);
                 wimaxClassLoader =  new DexClassLoader(wimaxJarLocation,
-                        new ContextWrapper(mContext).getCacheDir().getAbsolutePath(),
+                        new ContextWrapper(context).getCacheDir().getAbsolutePath(),
                         wimaxLibLocation, ClassLoader.getSystemClassLoader());
 
                 try {
@@ -597,17 +648,17 @@
             }
 
             try {
-                log("Starting Wimax Service... ");
+                if (DBG) log("Starting Wimax Service... ");
 
                 Constructor wmxStTrkrConst = wimaxStateTrackerClass.getConstructor
                         (new Class[] {Context.class, Handler.class});
-                wimaxStateTracker = (NetworkStateTracker)wmxStTrkrConst.newInstance(mContext,
-                        mHandler);
+                wimaxStateTracker = (NetworkStateTracker) wmxStTrkrConst.newInstance(
+                        context, trackerHandler);
 
                 Constructor wmxSrvConst = wimaxServiceClass.getDeclaredConstructor
                         (new Class[] {Context.class, wimaxStateTrackerClass});
                 wmxSrvConst.setAccessible(true);
-                IBinder svcInvoker = (IBinder)wmxSrvConst.newInstance(mContext, wimaxStateTracker);
+                IBinder svcInvoker = (IBinder)wmxSrvConst.newInstance(context, wimaxStateTracker);
                 wmxSrvConst.setAccessible(false);
 
                 ServiceManager.addService(WimaxManagerConstants.WIMAX_SERVICE, svcInvoker);
@@ -623,6 +674,7 @@
 
         return wimaxStateTracker;
     }
+
     /**
      * Sets the preferred network.
      * @param preference the new preference
@@ -630,7 +682,8 @@
     public void setNetworkPreference(int preference) {
         enforceChangePermission();
 
-        mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0));
+        mHandler.sendMessage(
+                mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0));
     }
 
     public int getNetworkPreference() {
@@ -648,7 +701,7 @@
                 mNetConfigs[preference].isDefault()) {
             if (mNetworkPreference != preference) {
                 final ContentResolver cr = mContext.getContentResolver();
-                Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE, preference);
+                Settings.Global.putInt(cr, Settings.Global.NETWORK_PREFERENCE, preference);
                 synchronized(this) {
                     mNetworkPreference = preference;
                 }
@@ -662,17 +715,17 @@
 
         /** Check system properties for the default value then use secure settings value, if any. */
         int defaultDelay = SystemProperties.getInt(
-                "conn." + Settings.Secure.CONNECTIVITY_CHANGE_DELAY,
-                Settings.Secure.CONNECTIVITY_CHANGE_DELAY_DEFAULT);
-        return Settings.Secure.getInt(cr, Settings.Secure.CONNECTIVITY_CHANGE_DELAY,
+                "conn." + Settings.Global.CONNECTIVITY_CHANGE_DELAY,
+                ConnectivityManager.CONNECTIVITY_CHANGE_DELAY_DEFAULT);
+        return Settings.Global.getInt(cr, Settings.Global.CONNECTIVITY_CHANGE_DELAY,
                 defaultDelay);
     }
 
     private int getPersistedNetworkPreference() {
         final ContentResolver cr = mContext.getContentResolver();
 
-        final int networkPrefSetting = Settings.Secure
-                .getInt(cr, Settings.Secure.NETWORK_PREFERENCE, -1);
+        final int networkPrefSetting = Settings.Global
+                .getInt(cr, Settings.Global.NETWORK_PREFERENCE, -1);
         if (networkPrefSetting != -1) {
             return networkPrefSetting;
         }
@@ -749,6 +802,9 @@
             info = new NetworkInfo(info);
             info.setDetailedState(DetailedState.BLOCKED, null, null);
         }
+        if (mLockdownTracker != null) {
+            info = mLockdownTracker.augmentNetworkInfo(info);
+        }
         return info;
     }
 
@@ -766,6 +822,17 @@
         return getNetworkInfo(mActiveDefaultNetwork, uid);
     }
 
+    public NetworkInfo getActiveNetworkInfoUnfiltered() {
+        enforceAccessPermission();
+        if (isNetworkTypeValid(mActiveDefaultNetwork)) {
+            final NetworkStateTracker tracker = mNetTrackers[mActiveDefaultNetwork];
+            if (tracker != null) {
+                return tracker.getNetworkInfo();
+            }
+        }
+        return null;
+    }
+
     @Override
     public NetworkInfo getActiveNetworkInfoForUid(int uid) {
         enforceConnectivityInternalPermission();
@@ -923,6 +990,14 @@
         return tracker != null && tracker.setRadio(turnOn);
     }
 
+    private INetworkManagementEventObserver mDataActivityObserver = new BaseNetworkObserver() {
+        @Override
+        public void interfaceClassDataActivityChanged(String label, boolean active) {
+            int deviceType = Integer.parseInt(label);
+            sendDataActivityBroadcast(deviceType, active);
+        }
+    };
+
     /**
      * Used to notice when the calling process dies so we can self-expire
      *
@@ -1017,6 +1092,12 @@
             // TODO - move this into individual networktrackers
             int usedNetworkType = convertFeatureToNetworkType(networkType, feature);
 
+            if (mLockdownEnabled) {
+                // Since carrier APNs usually aren't available from VPN
+                // endpoint, mark them as unavailable.
+                return PhoneConstants.APN_TYPE_NOT_AVAILABLE;
+            }
+
             if (mProtectedNetworks.contains(usedNetworkType)) {
                 enforceConnectivityInternalPermission();
             }
@@ -1291,8 +1372,10 @@
             return false;
         }
         NetworkStateTracker tracker = mNetTrackers[networkType];
+        DetailedState netState = tracker.getNetworkInfo().getDetailedState();
 
-        if (tracker == null || !tracker.getNetworkInfo().isConnected() ||
+        if (tracker == null || (netState != DetailedState.CONNECTED &&
+                netState != DetailedState.CAPTIVE_PORTAL_CHECK) ||
                 tracker.isTeardownRequested()) {
             if (VDBG) {
                 log("requestRouteToHostAddress on down network " +
@@ -1426,8 +1509,8 @@
         //       which is where we store the value and maybe make this
         //       asynchronous.
         enforceAccessPermission();
-        boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.MOBILE_DATA, 1) == 1;
+        boolean retVal = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.MOBILE_DATA, 1) == 1;
         if (VDBG) log("getMobileDataEnabled returning " + retVal);
         return retVal;
     }
@@ -1591,6 +1674,10 @@
         int prevNetType = info.getType();
 
         mNetTrackers[prevNetType].setTeardownRequested(false);
+
+        // Remove idletimer previously setup in {@code handleConnect}
+        removeDataActivityTracking(prevNetType);
+
         /*
          * If the disconnected network is not the active one, then don't report
          * this as a loss of connectivity. What probably happened is that we're
@@ -1609,7 +1696,8 @@
         }
 
         Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
-        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
+        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, new NetworkInfo(info));
+        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
         if (info.isFailover()) {
             intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
             info.setFailover(false);
@@ -1719,7 +1807,7 @@
         }
     }
 
-    private void sendConnectedBroadcast(NetworkInfo info) {
+    public void sendConnectedBroadcast(NetworkInfo info) {
         sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE);
         sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
     }
@@ -1734,8 +1822,13 @@
     }
 
     private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
+        if (mLockdownTracker != null) {
+            info = mLockdownTracker.augmentNetworkInfo(info);
+        }
+
         Intent intent = new Intent(bcastType);
-        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
+        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, new NetworkInfo(info));
+        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
         if (info.isFailover()) {
             intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
             info.setFailover(false);
@@ -1759,6 +1852,19 @@
         sendStickyBroadcastDelayed(makeGeneralIntent(info, bcastType), delayMs);
     }
 
+    private void sendDataActivityBroadcast(int deviceType, boolean active) {
+        Intent intent = new Intent(ConnectivityManager.ACTION_DATA_ACTIVITY_CHANGE);
+        intent.putExtra(ConnectivityManager.EXTRA_DEVICE_TYPE, deviceType);
+        intent.putExtra(ConnectivityManager.EXTRA_IS_ACTIVE, active);
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL,
+                    RECEIVE_DATA_ACTIVITY_CHANGE, null, null, 0, null, null);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
     /**
      * Called when an attempt to fail over to another network has failed.
      * @param info the {@link NetworkInfo} for the failed network
@@ -1778,7 +1884,8 @@
         loge("Attempt to connect to " + info.getTypeName() + " failed" + reasonText);
 
         Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
-        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
+        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, new NetworkInfo(info));
+        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
         if (getActiveNetworkInfo() == null) {
             intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
         }
@@ -1829,7 +1936,12 @@
                 log("sendStickyBroadcast: action=" + intent.getAction());
             }
 
-            mContext.sendStickyBroadcast(intent);
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
         }
     }
 
@@ -1850,37 +1962,55 @@
         synchronized(this) {
             mSystemReady = true;
             if (mInitialBroadcast != null) {
-                mContext.sendStickyBroadcast(mInitialBroadcast);
+                mContext.sendStickyBroadcastAsUser(mInitialBroadcast, UserHandle.ALL);
                 mInitialBroadcast = null;
             }
         }
         // load the global proxy at startup
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
+
+        // Try bringing up tracker, but if KeyStore isn't ready yet, wait
+        // for user to unlock device.
+        if (!updateLockdownVpn()) {
+            final IntentFilter filter = new IntentFilter(Intent.ACTION_USER_PRESENT);
+            mContext.registerReceiver(mUserPresentReceiver, filter);
+        }
+    }
+
+    private BroadcastReceiver mUserPresentReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // Try creating lockdown tracker, since user present usually means
+            // unlocked keystore.
+            if (updateLockdownVpn()) {
+                mContext.unregisterReceiver(this);
+            }
+        }
+    };
+
+    private boolean isNewNetTypePreferredOverCurrentNetType(int type) {
+        if ((type != mNetworkPreference &&
+                    mNetConfigs[mActiveDefaultNetwork].priority >
+                    mNetConfigs[type].priority) ||
+                mNetworkPreference == mActiveDefaultNetwork) return false;
+        return true;
     }
 
     private void handleConnect(NetworkInfo info) {
-        final int type = info.getType();
+        final int newNetType = info.getType();
+
+        setupDataActivityTracking(newNetType);
 
         // snapshot isFailover, because sendConnectedBroadcast() resets it
         boolean isFailover = info.isFailover();
-        final NetworkStateTracker thisNet = mNetTrackers[type];
+        final NetworkStateTracker thisNet = mNetTrackers[newNetType];
+        final String thisIface = thisNet.getLinkProperties().getInterfaceName();
 
         // if this is a default net and other default is running
         // kill the one not preferred
-        if (mNetConfigs[type].isDefault()) {
-            if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
-                if ((type != mNetworkPreference &&
-                        mNetConfigs[mActiveDefaultNetwork].priority >
-                        mNetConfigs[type].priority) ||
-                        mNetworkPreference == mActiveDefaultNetwork) {
-                        // don't accept this one
-                        if (VDBG) {
-                            log("Not broadcasting CONNECT_ACTION " +
-                                "to torn down network " + info.getTypeName());
-                        }
-                        teardown(thisNet);
-                        return;
-                } else {
+        if (mNetConfigs[newNetType].isDefault()) {
+            if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != newNetType) {
+                if (isNewNetTypePreferredOverCurrentNetType(newNetType)) {
                     // tear down the other
                     NetworkStateTracker otherNet =
                             mNetTrackers[mActiveDefaultNetwork];
@@ -1893,6 +2023,14 @@
                         teardown(thisNet);
                         return;
                     }
+                } else {
+                       // don't accept this one
+                        if (VDBG) {
+                            log("Not broadcasting CONNECT_ACTION " +
+                                "to torn down network " + info.getTypeName());
+                        }
+                        teardown(thisNet);
+                        return;
                 }
             }
             synchronized (ConnectivityService.this) {
@@ -1906,7 +2044,7 @@
                             1000);
                 }
             }
-            mActiveDefaultNetwork = type;
+            mActiveDefaultNetwork = newNetType;
             // this will cause us to come up initially as unconnected and switching
             // to connected after our normal pause unless somebody reports us as reall
             // disconnected
@@ -1918,20 +2056,97 @@
         }
         thisNet.setTeardownRequested(false);
         updateNetworkSettings(thisNet);
-        handleConnectivityChange(type, false);
+        handleConnectivityChange(newNetType, false);
         sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
 
         // notify battery stats service about this network
-        final String iface = thisNet.getLinkProperties().getInterfaceName();
-        if (iface != null) {
+        if (thisIface != null) {
             try {
-                BatteryStatsService.getService().noteNetworkInterfaceType(iface, type);
+                BatteryStatsService.getService().noteNetworkInterfaceType(thisIface, newNetType);
             } catch (RemoteException e) {
                 // ignored; service lives in system_server
             }
         }
     }
 
+    private void handleCaptivePortalTrackerCheck(NetworkInfo info) {
+        if (DBG) log("Captive portal check " + info);
+        int type = info.getType();
+        final NetworkStateTracker thisNet = mNetTrackers[type];
+        if (mNetConfigs[type].isDefault()) {
+            if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
+                if (isNewNetTypePreferredOverCurrentNetType(type)) {
+                    if (DBG) log("Captive check on " + info.getTypeName());
+                    mCaptivePortalTracker.detectCaptivePortal(new NetworkInfo(info));
+                    return;
+                } else {
+                    if (DBG) log("Tear down low priority net " + info.getTypeName());
+                    teardown(thisNet);
+                    return;
+                }
+            }
+        }
+
+        thisNet.captivePortalCheckComplete();
+    }
+
+    /** @hide */
+    public void captivePortalCheckComplete(NetworkInfo info) {
+        mNetTrackers[info.getType()].captivePortalCheckComplete();
+    }
+
+    /**
+     * Setup data activity tracking for the given network interface.
+     *
+     * Every {@code setupDataActivityTracking} should be paired with a
+     * {@link removeDataActivityTracking} for cleanup.
+     */
+    private void setupDataActivityTracking(int type) {
+        final NetworkStateTracker thisNet = mNetTrackers[type];
+        final String iface = thisNet.getLinkProperties().getInterfaceName();
+
+        final int timeout;
+
+        if (ConnectivityManager.isNetworkTypeMobile(type)) {
+            timeout = Settings.Global.getInt(mContext.getContentResolver(),
+                                             Settings.Global.DATA_ACTIVITY_TIMEOUT_MOBILE,
+                                             0);
+            // Canonicalize mobile network type
+            type = ConnectivityManager.TYPE_MOBILE;
+        } else if (ConnectivityManager.TYPE_WIFI == type) {
+            timeout = Settings.Global.getInt(mContext.getContentResolver(),
+                                             Settings.Global.DATA_ACTIVITY_TIMEOUT_WIFI,
+                                             0);
+        } else {
+            // do not track any other networks
+            timeout = 0;
+        }
+
+        if (timeout > 0 && iface != null) {
+            try {
+                mNetd.addIdleTimer(iface, timeout, Integer.toString(type));
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    /**
+     * Remove data activity tracking when network disconnects.
+     */
+    private void removeDataActivityTracking(int type) {
+        final NetworkStateTracker net = mNetTrackers[type];
+        final String iface = net.getLinkProperties().getInterfaceName();
+
+        if (iface != null && (ConnectivityManager.isNetworkTypeMobile(type) ||
+                              ConnectivityManager.TYPE_WIFI == type)) {
+            try {
+                // the call fails silently if no idletimer setup for this interface
+                mNetd.removeIdleTimer(iface);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
     /**
      * After a change in the connectivity state of a network. We're mainly
      * concerned with making sure that the list of DNS servers is set up
@@ -2136,9 +2351,9 @@
      */
    public void updateNetworkSettings(NetworkStateTracker nt) {
         String key = nt.getTcpBufferSizesPropName();
-        String bufferSizes = SystemProperties.get(key);
+        String bufferSizes = key == null ? null : SystemProperties.get(key);
 
-        if (bufferSizes.length() == 0) {
+        if (TextUtils.isEmpty(bufferSizes)) {
             if (VDBG) log(key + " not found in system properties. Using defaults");
 
             // Setting to default values so we won't be stuck to previous values
@@ -2264,7 +2479,12 @@
          * Connectivity events can happen before boot has completed ...
          */
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        mContext.sendBroadcast(intent);
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
     }
 
     // Caller must grab mDnsLock.
@@ -2374,7 +2594,8 @@
     }
 
     @Override
-    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
         if (mContext.checkCallingOrSelfPermission(
                 android.Manifest.permission.DUMP)
                 != PackageManager.PERMISSION_GRANTED) {
@@ -2383,20 +2604,28 @@
                     Binder.getCallingUid());
             return;
         }
+
+        // TODO: add locking to get atomic snapshot
         pw.println();
-        for (NetworkStateTracker nst : mNetTrackers) {
+        for (int i = 0; i < mNetTrackers.length; i++) {
+            final NetworkStateTracker nst = mNetTrackers[i];
             if (nst != null) {
+                pw.println("NetworkStateTracker for " + getNetworkTypeName(i) + ":");
+                pw.increaseIndent();
                 if (nst.getNetworkInfo().isConnected()) {
                     pw.println("Active network: " + nst.getNetworkInfo().
                             getTypeName());
                 }
                 pw.println(nst.getNetworkInfo());
+                pw.println(nst.getLinkProperties());
                 pw.println(nst);
                 pw.println();
+                pw.decreaseIndent();
             }
         }
 
         pw.println("Network Requester Pids:");
+        pw.increaseIndent();
         for (int net : mPriorityList) {
             String pidString = net + ": ";
             for (Object pid : mNetRequestersPids[net]) {
@@ -2405,12 +2634,15 @@
             pw.println(pidString);
         }
         pw.println();
+        pw.decreaseIndent();
 
         pw.println("FeatureUsers:");
+        pw.increaseIndent();
         for (Object requester : mFeatureUsers) {
             pw.println(requester.toString());
         }
         pw.println();
+        pw.decreaseIndent();
 
         synchronized (this) {
             pw.println("NetworkTranstionWakeLock is currently " +
@@ -2424,15 +2656,17 @@
         if (mInetLog != null) {
             pw.println();
             pw.println("Inet condition reports:");
+            pw.increaseIndent();
             for(int i = 0; i < mInetLog.size(); i++) {
                 pw.println(mInetLog.get(i));
             }
+            pw.decreaseIndent();
         }
     }
 
     // must be stateless - things change under us.
-    private class MyHandler extends Handler {
-        public MyHandler(Looper looper) {
+    private class NetworkStateTrackerHandler extends Handler {
+        public NetworkStateTrackerHandler(Looper looper) {
             super(looper);
         }
 
@@ -2468,6 +2702,9 @@
                     if (info.getDetailedState() ==
                             NetworkInfo.DetailedState.FAILED) {
                         handleConnectionFailure(info);
+                    } else if (info.getDetailedState() ==
+                            DetailedState.CAPTIVE_PORTAL_CHECK) {
+                        handleCaptivePortalTrackerCheck(info);
                     } else if (state == NetworkInfo.State.DISCONNECTED) {
                         handleDisconnect(info);
                     } else if (state == NetworkInfo.State.SUSPENDED) {
@@ -2482,6 +2719,9 @@
                     } else if (state == NetworkInfo.State.CONNECTED) {
                         handleConnect(info);
                     }
+                    if (mLockdownTracker != null) {
+                        mLockdownTracker.onNetworkInfoChanged(info);
+                    }
                     break;
                 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
                     info = (NetworkInfo) msg.obj;
@@ -2495,6 +2735,19 @@
                     type = info.getType();
                     updateNetworkSettings(mNetTrackers[type]);
                     break;
+            }
+        }
+    }
+
+    private class InternalHandler extends Handler {
+        public InternalHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            NetworkInfo info;
+            switch (msg.what) {
                 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
                     String causedBy = null;
                     synchronized (ConnectivityService.this) {
@@ -2566,6 +2819,13 @@
                     final int networkType = msg.arg1;
                     final boolean enabled = msg.arg2 == ENABLED;
                     handleSetPolicyDataEnable(networkType, enabled);
+                    break;
+                }
+                case EVENT_VPN_STATE_CHANGED: {
+                    if (mLockdownTracker != null) {
+                        mLockdownTracker.onVpnStateChanged((NetworkInfo) msg.obj);
+                    }
+                    break;
                 }
             }
         }
@@ -2670,8 +2930,8 @@
     public boolean isTetheringSupported() {
         enforceTetherAccessPermission();
         int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
-        boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0);
+        boolean tetherEnabledInSettings = (Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.TETHER_SUPPORTED, defaultVal) != 0);
         return tetherEnabledInSettings && mTetheringConfigValid;
     }
 
@@ -2737,11 +2997,11 @@
             if (VDBG) log("handleInetConditionChange: starting a change hold");
             // setup a new hold to debounce this
             if (mDefaultInetCondition > 50) {
-                delay = Settings.Secure.getInt(mContext.getContentResolver(),
-                        Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
+                delay = Settings.Global.getInt(mContext.getContentResolver(),
+                        Settings.Global.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
             } else {
-                delay = Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
+                delay = Settings.Global.getInt(mContext.getContentResolver(),
+                        Settings.Global.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
             }
             mInetConditionChangeInFlight = true;
             mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END,
@@ -2810,9 +3070,9 @@
                 mGlobalProxy = null;
             }
             ContentResolver res = mContext.getContentResolver();
-            Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, host);
-            Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, port);
-            Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
+            Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, host);
+            Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, port);
+            Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
                     exclList);
         }
 
@@ -2824,10 +3084,10 @@
 
     private void loadGlobalProxy() {
         ContentResolver res = mContext.getContentResolver();
-        String host = Settings.Secure.getString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST);
-        int port = Settings.Secure.getInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, 0);
-        String exclList = Settings.Secure.getString(res,
-                Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
+        String host = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST);
+        int port = Settings.Global.getInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, 0);
+        String exclList = Settings.Global.getString(res,
+                Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
         if (!TextUtils.isEmpty(host)) {
             ProxyProperties proxyProperties = new ProxyProperties(host, port, exclList);
             synchronized (mGlobalProxyLock) {
@@ -2858,8 +3118,8 @@
     }
 
     private void handleDeprecatedGlobalHttpProxy() {
-        String proxy = Settings.Secure.getString(mContext.getContentResolver(),
-                Settings.Secure.HTTP_PROXY);
+        String proxy = Settings.Global.getString(mContext.getContentResolver(),
+                Settings.Global.HTTP_PROXY);
         if (!TextUtils.isEmpty(proxy)) {
             String data[] = proxy.split(":");
             String proxyHost =  data[0];
@@ -2883,7 +3143,12 @@
         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
             Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
-        mContext.sendStickyBroadcast(intent);
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
     }
 
     private static class SettingsObserver extends ContentObserver {
@@ -2897,8 +3162,8 @@
 
         void observe(Context context) {
             ContentResolver resolver = context.getContentResolver();
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.HTTP_PROXY), false, this);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.HTTP_PROXY), false, this);
         }
 
         @Override
@@ -2907,11 +3172,11 @@
         }
     }
 
-    private void log(String s) {
+    private static void log(String s) {
         Slog.d(TAG, s);
     }
 
-    private void loge(String s) {
+    private static void loge(String s) {
         Slog.e(TAG, s);
     }
 
@@ -2964,6 +3229,7 @@
      */
     @Override
     public boolean protectVpn(ParcelFileDescriptor socket) {
+        throwIfLockdownEnabled();
         try {
             int type = mActiveDefaultNetwork;
             if (ConnectivityManager.isNetworkTypeValid(type)) {
@@ -2990,6 +3256,7 @@
      */
     @Override
     public boolean prepareVpn(String oldPackage, String newPackage) {
+        throwIfLockdownEnabled();
         return mVpn.prepare(oldPackage, newPackage);
     }
 
@@ -3002,18 +3269,22 @@
      */
     @Override
     public ParcelFileDescriptor establishVpn(VpnConfig config) {
+        throwIfLockdownEnabled();
         return mVpn.establish(config);
     }
 
     /**
-     * Start legacy VPN and return an intent to VpnDialogs. This method is
-     * used by VpnSettings and not available in ConnectivityManager.
-     * Permissions are checked in Vpn class.
-     * @hide
+     * Start legacy VPN, controlling native daemons as needed. Creates a
+     * secondary thread to perform connection work, returning quickly.
      */
     @Override
-    public void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) {
-        mVpn.startLegacyVpn(config, racoon, mtpd);
+    public void startLegacyVpn(VpnProfile profile) {
+        throwIfLockdownEnabled();
+        final LinkProperties egress = getActiveLinkProperties();
+        if (egress == null) {
+            throw new IllegalStateException("Missing active network connection");
+        }
+        mVpn.startLegacyVpn(profile, mKeyStore, egress);
     }
 
     /**
@@ -3024,6 +3295,7 @@
      */
     @Override
     public LegacyVpnInfo getLegacyVpnInfo() {
+        throwIfLockdownEnabled();
         return mVpn.getLegacyVpnInfo();
     }
 
@@ -3038,10 +3310,13 @@
      * be done whenever a better abstraction is developed.
      */
     public class VpnCallback {
-
         private VpnCallback() {
         }
 
+        public void onStateChanged(NetworkInfo info) {
+            mHandler.obtainMessage(EVENT_VPN_STATE_CHANGED, info).sendToTarget();
+        }
+
         public void override(List<String> dnsServers, List<String> searchDomains) {
             if (dnsServers == null) {
                 restore();
@@ -3108,4 +3383,65 @@
             }
         }
     }
+
+    @Override
+    public boolean updateLockdownVpn() {
+        enforceSystemUid();
+
+        // Tear down existing lockdown if profile was removed
+        mLockdownEnabled = LockdownVpnTracker.isEnabled();
+        if (mLockdownEnabled) {
+            if (mKeyStore.state() != KeyStore.State.UNLOCKED) {
+                Slog.w(TAG, "KeyStore locked; unable to create LockdownTracker");
+                return false;
+            }
+
+            final String profileName = new String(mKeyStore.get(Credentials.LOCKDOWN_VPN));
+            final VpnProfile profile = VpnProfile.decode(
+                    profileName, mKeyStore.get(Credentials.VPN + profileName));
+            setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, mVpn, profile));
+        } else {
+            setLockdownTracker(null);
+        }
+
+        return true;
+    }
+
+    /**
+     * Internally set new {@link LockdownVpnTracker}, shutting down any existing
+     * {@link LockdownVpnTracker}. Can be {@code null} to disable lockdown.
+     */
+    private void setLockdownTracker(LockdownVpnTracker tracker) {
+        // Shutdown any existing tracker
+        final LockdownVpnTracker existing = mLockdownTracker;
+        mLockdownTracker = null;
+        if (existing != null) {
+            existing.shutdown();
+        }
+
+        try {
+            if (tracker != null) {
+                mNetd.setFirewallEnabled(true);
+                mLockdownTracker = tracker;
+                mLockdownTracker.init();
+            } else {
+                mNetd.setFirewallEnabled(false);
+            }
+        } catch (RemoteException e) {
+            // ignored; NMS lives inside system_server
+        }
+    }
+
+    private void throwIfLockdownEnabled() {
+        if (mLockdownEnabled) {
+            throw new IllegalStateException("Unavailable in lockdown mode");
+        }
+    }
+
+    private static void enforceSystemUid() {
+        final int uid = Binder.getCallingUid();
+        if (uid != Process.SYSTEM_UID) {
+            throw new SecurityException("Only available to AID_SYSTEM");
+        }
+    }
 }
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index ea19d6e..a5e26a8 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -16,7 +16,6 @@
 
 package com.android.server;
 
-import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.storage.ExternalStorageFormatter;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.JournaledFile;
@@ -28,7 +27,9 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import android.app.Activity;
+import android.app.ActivityManagerNative;
 import android.app.AlarmManager;
+import android.app.AppGlobals;
 import android.app.PendingIntent;
 import android.app.admin.DeviceAdminInfo;
 import android.app.admin.DeviceAdminReceiver;
@@ -40,25 +41,31 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IPowerManager;
 import android.os.PowerManager;
+import android.os.Process;
 import android.os.RecoverySystem;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.util.PrintWriterPrinter;
 import android.util.Printer;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.Xml;
 import android.view.IWindowManager;
 import android.view.WindowManagerPolicy;
@@ -81,56 +88,86 @@
  * Implementation of the device policy APIs.
  */
 public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
+    private static final String DEVICE_POLICIES_XML = "device_policies.xml";
+
     private static final String TAG = "DevicePolicyManagerService";
 
     private static final int REQUEST_EXPIRE_PASSWORD = 5571;
 
-    private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * 86400 * 1000; // 5 days, in ms
+    private static final long MS_PER_DAY = 86400 * 1000;
+
+    private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * MS_PER_DAY; // 5 days, in ms
 
     protected static final String ACTION_EXPIRED_PASSWORD_NOTIFICATION
             = "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION";
 
-    private static final long MS_PER_DAY = 86400 * 1000;
+    private static final boolean DBG = false;
 
     final Context mContext;
-    final MyPackageMonitor mMonitor;
     final PowerManager.WakeLock mWakeLock;
 
     IPowerManager mIPowerManager;
     IWindowManager mIWindowManager;
 
-    int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
-    int mActivePasswordLength = 0;
-    int mActivePasswordUpperCase = 0;
-    int mActivePasswordLowerCase = 0;
-    int mActivePasswordLetters = 0;
-    int mActivePasswordNumeric = 0;
-    int mActivePasswordSymbols = 0;
-    int mActivePasswordNonLetter = 0;
-    int mFailedPasswordAttempts = 0;
+    public static class DevicePolicyData {
+        int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+        int mActivePasswordLength = 0;
+        int mActivePasswordUpperCase = 0;
+        int mActivePasswordLowerCase = 0;
+        int mActivePasswordLetters = 0;
+        int mActivePasswordNumeric = 0;
+        int mActivePasswordSymbols = 0;
+        int mActivePasswordNonLetter = 0;
+        int mFailedPasswordAttempts = 0;
 
-    int mPasswordOwner = -1;
+        int mUserHandle;;
+        int mPasswordOwner = -1;
+        long mLastMaximumTimeToLock = -1;
+
+        final HashMap<ComponentName, ActiveAdmin> mAdminMap
+                = new HashMap<ComponentName, ActiveAdmin>();
+        final ArrayList<ActiveAdmin> mAdminList
+                = new ArrayList<ActiveAdmin>();
+
+        public DevicePolicyData(int userHandle) {
+            mUserHandle = userHandle;
+        }
+    }
+
+    final SparseArray<DevicePolicyData> mUserData = new SparseArray<DevicePolicyData>();
+
     Handler mHandler = new Handler();
 
-    long mLastMaximumTimeToLock = -1;
-
-    final HashMap<ComponentName, ActiveAdmin> mAdminMap
-            = new HashMap<ComponentName, ActiveAdmin>();
-    final ArrayList<ActiveAdmin> mAdminList
-            = new ArrayList<ActiveAdmin>();
-
     BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
+            final String action = intent.getAction();
+            final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+                    getSendingUserId());
             if (Intent.ACTION_BOOT_COMPLETED.equals(action)
                     || ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) {
-                Slog.v(TAG, "Sending password expiration notifications for action " + action);
+                Slog.v(TAG, "Sending password expiration notifications for action " + action
+                        + " for user " + userHandle);
                 mHandler.post(new Runnable() {
                     public void run() {
-                        handlePasswordExpirationNotification();
+                        handlePasswordExpirationNotification(getUserData(userHandle));
                     }
                 });
+            } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+                removeUserData(userHandle);
+            } else if (Intent.ACTION_USER_STARTED.equals(action)
+                    || Intent.ACTION_PACKAGE_CHANGED.equals(action)
+                    || Intent.ACTION_PACKAGE_REMOVED.equals(action)
+                    || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
+
+                if (Intent.ACTION_USER_STARTED.equals(action)) {
+                    // Reset the policy data
+                    synchronized (DevicePolicyManagerService.this) {
+                        mUserData.remove(userHandle);
+                    }
+                }
+
+                handlePackagesChanged(userHandle);
             }
         }
     };
@@ -176,6 +213,9 @@
         static final long DEF_PASSWORD_EXPIRATION_DATE = 0;
         long passwordExpirationDate = DEF_PASSWORD_EXPIRATION_DATE;
 
+        static final int DEF_KEYGUARD_FEATURES_DISABLED = 0; // none
+        int disabledKeyguardFeatures = DEF_KEYGUARD_FEATURES_DISABLED;
+
         boolean encryptionRequested = false;
         boolean disableCamera = false;
 
@@ -190,6 +230,10 @@
 
         int getUid() { return info.getActivityInfo().applicationInfo.uid; }
 
+        public UserHandle getUserHandle() {
+            return new UserHandle(UserHandle.getUserId(info.getActivityInfo().applicationInfo.uid));
+        }
+
         void writeToXml(XmlSerializer out)
                 throws IllegalArgumentException, IllegalStateException, IOException {
             out.startTag(null, "policies");
@@ -285,6 +329,11 @@
                 out.attribute(null, "value", Boolean.toString(disableCamera));
                 out.endTag(null, "disable-camera");
             }
+            if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) {
+                out.startTag(null, "disable-keyguard-features");
+                out.attribute(null, "value", Integer.toString(disabledKeyguardFeatures));
+                out.endTag(null, "disable-keyguard-features");
+            }
         }
 
         void readFromXml(XmlPullParser parser)
@@ -353,6 +402,9 @@
                 } else if ("disable-camera".equals(tag)) {
                     disableCamera = Boolean.parseBoolean(
                             parser.getAttributeValue(null, "value"));
+                } else if ("disable-keyguard-features".equals(tag)) {
+                    disabledKeyguardFeatures = Integer.parseInt(
+                            parser.getAttributeValue(null, "value"));
                 } else {
                     Slog.w(TAG, "Unknown admin tag: " + tag);
                 }
@@ -409,42 +461,33 @@
                     pw.println(encryptionRequested);
             pw.print(prefix); pw.print("disableCamera=");
                     pw.println(disableCamera);
+            pw.print(prefix); pw.print("disabledKeyguardFeatures=");
+                    pw.println(disabledKeyguardFeatures);
         }
     }
 
-    class MyPackageMonitor extends PackageMonitor {
-        @Override
-        public void onSomePackagesChanged() {
-            synchronized (DevicePolicyManagerService.this) {
-                boolean removed = false;
-                for (int i=mAdminList.size()-1; i>=0; i--) {
-                    ActiveAdmin aa = mAdminList.get(i);
-                    int change = isPackageDisappearing(aa.info.getPackageName());
-                    if (change == PACKAGE_PERMANENT_CHANGE
-                            || change == PACKAGE_TEMPORARY_CHANGE) {
-                        Slog.w(TAG, "Admin unexpectedly uninstalled: "
-                                + aa.info.getComponent());
-                        removed = true;
-                        mAdminList.remove(i);
-                    } else if (isPackageModified(aa.info.getPackageName())) {
-                        try {
-                            mContext.getPackageManager().getReceiverInfo(
-                                    aa.info.getComponent(), 0);
-                        } catch (NameNotFoundException e) {
-                            Slog.w(TAG, "Admin package change removed component: "
-                                    + aa.info.getComponent());
-                            removed = true;
-                            mAdminList.remove(i);
-                        }
-                    }
+    private void handlePackagesChanged(int userHandle) {
+        boolean removed = false;
+        Slog.d(TAG, "Handling package changes for user " + userHandle);
+        DevicePolicyData policy = getUserData(userHandle);
+        IPackageManager pm = AppGlobals.getPackageManager();
+        for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
+            ActiveAdmin aa = policy.mAdminList.get(i);
+            try {
+                if (pm.getPackageInfo(aa.info.getPackageName(), 0, userHandle) == null
+                        || pm.getReceiverInfo(aa.info.getComponent(), 0, userHandle) == null) {
+                    removed = true;
+                    policy.mAdminList.remove(i);
                 }
-                if (removed) {
-                    validatePasswordOwnerLocked();
-                    syncDeviceCapabilitiesLocked();
-                    saveSettingsLocked();
-                }
+            } catch (RemoteException re) {
+                // Shouldn't happen
             }
         }
+        if (removed) {
+            validatePasswordOwnerLocked(policy);
+            syncDeviceCapabilitiesLocked(policy);
+            saveSettingsLocked(policy.mUserHandle);
+        }
     }
 
     /**
@@ -452,22 +495,62 @@
      */
     public DevicePolicyManagerService(Context context) {
         mContext = context;
-        mMonitor = new MyPackageMonitor();
-        mMonitor.register(context, null, true);
         mWakeLock = ((PowerManager)context.getSystemService(Context.POWER_SERVICE))
                 .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM");
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_BOOT_COMPLETED);
         filter.addAction(ACTION_EXPIRED_PASSWORD_NOTIFICATION);
-        context.registerReceiver(mReceiver, filter);
+        filter.addAction(Intent.ACTION_USER_REMOVED);
+        filter.addAction(Intent.ACTION_USER_STARTED);
+        context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
+        filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+        filter.addDataScheme("package");
+        context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
+    }
+
+    /**
+     * Creates and loads the policy data from xml.
+     * @param userHandle the user for whom to load the policy data
+     * @return
+     */
+    DevicePolicyData getUserData(int userHandle) {
+        synchronized (this) {
+            DevicePolicyData policy = mUserData.get(userHandle);
+            if (policy == null) {
+                policy = new DevicePolicyData(userHandle);
+                mUserData.append(userHandle, policy);
+                loadSettingsLocked(policy, userHandle);
+            }
+            return policy;
+        }
+    }
+
+    void removeUserData(int userHandle) {
+        synchronized (this) {
+            if (userHandle == UserHandle.USER_OWNER) {
+                Slog.w(TAG, "Tried to remove device policy file for user 0! Ignoring.");
+                return;
+            }
+            DevicePolicyData policy = mUserData.get(userHandle);
+            if (policy != null) {
+                mUserData.remove(userHandle);
+            }
+            File policyFile = new File(Environment.getUserSystemDirectory(userHandle),
+                    DEVICE_POLICIES_XML);
+            policyFile.delete();
+            Slog.i(TAG, "Removed device policy file " + policyFile.getAbsolutePath());
+        }
     }
 
     /**
      * Set an alarm for an upcoming event - expiration warning, expiration, or post-expiration
      * reminders.  Clears alarm if no expirations are configured.
      */
-    protected void setExpirationAlarmCheckLocked(Context context) {
-        final long expiration = getPasswordExpirationLocked(null);
+    protected void setExpirationAlarmCheckLocked(Context context, DevicePolicyData policy) {
+        final long expiration = getPasswordExpirationLocked(null, policy.mUserHandle);
         final long now = System.currentTimeMillis();
         final long timeToExpire = expiration - now;
         final long alarmTime;
@@ -490,9 +573,10 @@
         long token = Binder.clearCallingIdentity();
         try {
             AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
-            PendingIntent pi = PendingIntent.getBroadcast(context, REQUEST_EXPIRE_PASSWORD,
+            PendingIntent pi = PendingIntent.getBroadcastAsUser(context, REQUEST_EXPIRE_PASSWORD,
                     new Intent(ACTION_EXPIRED_PASSWORD_NOTIFICATION),
-                    PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
+                    PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT,
+                    new UserHandle(policy.mUserHandle));
             am.cancel(pi);
             if (alarmTime != 0) {
                 am.set(AlarmManager.RTC, alarmTime, pi);
@@ -518,8 +602,8 @@
         return mIWindowManager;
     }
 
-    ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who) {
-        ActiveAdmin admin = mAdminMap.get(who);
+    ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who, int userHandle) {
+        ActiveAdmin admin = getUserData(userHandle).mAdminMap.get(who);
         if (admin != null
                 && who.getPackageName().equals(admin.info.getActivityInfo().packageName)
                 && who.getClassName().equals(admin.info.getActivityInfo().name)) {
@@ -531,8 +615,10 @@
     ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
             throws SecurityException {
         final int callingUid = Binder.getCallingUid();
+        final int userHandle = UserHandle.getUserId(callingUid);
+        final DevicePolicyData policy = getUserData(userHandle);
         if (who != null) {
-            ActiveAdmin admin = mAdminMap.get(who);
+            ActiveAdmin admin = policy.mAdminMap.get(who);
             if (admin == null) {
                 throw new SecurityException("No active admin " + who);
             }
@@ -547,9 +633,9 @@
             }
             return admin;
         } else {
-            final int N = mAdminList.size();
+            final int N = policy.mAdminList.size();
             for (int i=0; i<N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) {
                     return admin;
                 }
@@ -570,18 +656,19 @@
             intent.putExtra("expiration", admin.passwordExpirationDate);
         }
         if (result != null) {
-            mContext.sendOrderedBroadcast(intent, null, result, mHandler,
-                    Activity.RESULT_OK, null, null);
+            mContext.sendOrderedBroadcastAsUser(intent, admin.getUserHandle(),
+                    null, result, mHandler, Activity.RESULT_OK, null, null);
         } else {
-            mContext.sendBroadcast(intent);
+            mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);
         }
     }
 
-    void sendAdminCommandLocked(String action, int reqPolicy) {
-        final int N = mAdminList.size();
-        if (N > 0) {
-            for (int i=0; i<N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+    void sendAdminCommandLocked(String action, int reqPolicy, int userHandle) {
+        final DevicePolicyData policy = getUserData(userHandle);
+        final int count = policy.mAdminList.size();
+        if (count > 0) {
+            for (int i = 0; i < count; i++) {
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (admin.info.usesPolicy(reqPolicy)) {
                     sendAdminCommandLocked(admin, action);
                 }
@@ -589,8 +676,8 @@
         }
     }
 
-    void removeActiveAdminLocked(final ComponentName adminReceiver) {
-        final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
+    void removeActiveAdminLocked(final ComponentName adminReceiver, int userHandle) {
+        final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
         if (admin != null) {
             sendAdminCommandLocked(admin,
                     DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED,
@@ -598,28 +685,31 @@
                         @Override
                         public void onReceive(Context context, Intent intent) {
                             synchronized (DevicePolicyManagerService.this) {
+                                int userHandle = admin.getUserHandle().getIdentifier();
+                                DevicePolicyData policy = getUserData(userHandle);
                                 boolean doProxyCleanup = admin.info.usesPolicy(
                                         DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
-                                mAdminList.remove(admin);
-                                mAdminMap.remove(adminReceiver);
-                                validatePasswordOwnerLocked();
-                                syncDeviceCapabilitiesLocked();
+                                policy.mAdminList.remove(admin);
+                                policy.mAdminMap.remove(adminReceiver);
+                                validatePasswordOwnerLocked(policy);
+                                syncDeviceCapabilitiesLocked(policy);
                                 if (doProxyCleanup) {
-                                    resetGlobalProxyLocked();
+                                    resetGlobalProxyLocked(getUserData(userHandle));
                                 }
-                                saveSettingsLocked();
-                                updateMaximumTimeToLockLocked();
+                                saveSettingsLocked(userHandle);
+                                updateMaximumTimeToLockLocked(policy);
                             }
                         }
             });
         }
     }
 
-    public DeviceAdminInfo findAdmin(ComponentName adminName) {
+    public DeviceAdminInfo findAdmin(ComponentName adminName, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         Intent resolveIntent = new Intent();
         resolveIntent.setComponent(adminName);
         List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceivers(
-                resolveIntent, PackageManager.GET_META_DATA);
+                resolveIntent, PackageManager.GET_META_DATA, userHandle);
         if (infos == null || infos.size() <= 0) {
             throw new IllegalArgumentException("Unknown admin: " + adminName);
         }
@@ -627,21 +717,25 @@
         try {
             return new DeviceAdminInfo(mContext, infos.get(0));
         } catch (XmlPullParserException e) {
-            Slog.w(TAG, "Bad device admin requested: " + adminName, e);
+            Slog.w(TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName, e);
             return null;
         } catch (IOException e) {
-            Slog.w(TAG, "Bad device admin requested: " + adminName, e);
+            Slog.w(TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName, e);
             return null;
         }
     }
 
-    private static JournaledFile makeJournaledFile() {
-        final String base = "/data/system/device_policies.xml";
+    private static JournaledFile makeJournaledFile(int userHandle) {
+        final String base = userHandle == 0
+                ? "/data/system/" + DEVICE_POLICIES_XML
+                : new File(Environment.getUserSystemDirectory(userHandle), DEVICE_POLICIES_XML)
+                        .getAbsolutePath();
         return new JournaledFile(new File(base), new File(base + ".tmp"));
     }
 
-    private void saveSettingsLocked() {
-        JournaledFile journal = makeJournaledFile();
+    private void saveSettingsLocked(int userHandle) {
+        DevicePolicyData policy = getUserData(userHandle);
+        JournaledFile journal = makeJournaledFile(userHandle);
         FileOutputStream stream = null;
         try {
             stream = new FileOutputStream(journal.chooseForWrite(), false);
@@ -651,9 +745,9 @@
 
             out.startTag(null, "policies");
 
-            final int N = mAdminList.size();
+            final int N = policy.mAdminList.size();
             for (int i=0; i<N; i++) {
-                ActiveAdmin ap = mAdminList.get(i);
+                ActiveAdmin ap = policy.mAdminList.get(i);
                 if (ap != null) {
                     out.startTag(null, "admin");
                     out.attribute(null, "name", ap.info.getComponent().flattenToString());
@@ -662,32 +756,32 @@
                 }
             }
 
-            if (mPasswordOwner >= 0) {
+            if (policy.mPasswordOwner >= 0) {
                 out.startTag(null, "password-owner");
-                out.attribute(null, "value", Integer.toString(mPasswordOwner));
+                out.attribute(null, "value", Integer.toString(policy.mPasswordOwner));
                 out.endTag(null, "password-owner");
             }
 
-            if (mFailedPasswordAttempts != 0) {
+            if (policy.mFailedPasswordAttempts != 0) {
                 out.startTag(null, "failed-password-attempts");
-                out.attribute(null, "value", Integer.toString(mFailedPasswordAttempts));
+                out.attribute(null, "value", Integer.toString(policy.mFailedPasswordAttempts));
                 out.endTag(null, "failed-password-attempts");
             }
 
-            if (mActivePasswordQuality != 0 || mActivePasswordLength != 0
-                    || mActivePasswordUpperCase != 0 || mActivePasswordLowerCase != 0
-                    || mActivePasswordLetters != 0 || mActivePasswordNumeric != 0
-                    || mActivePasswordSymbols != 0 || mActivePasswordNonLetter != 0) {
+            if (policy.mActivePasswordQuality != 0 || policy.mActivePasswordLength != 0
+                    || policy.mActivePasswordUpperCase != 0 || policy.mActivePasswordLowerCase != 0
+                    || policy.mActivePasswordLetters != 0 || policy.mActivePasswordNumeric != 0
+                    || policy.mActivePasswordSymbols != 0 || policy.mActivePasswordNonLetter != 0) {
                 out.startTag(null, "active-password");
-                out.attribute(null, "quality", Integer.toString(mActivePasswordQuality));
-                out.attribute(null, "length", Integer.toString(mActivePasswordLength));
-                out.attribute(null, "uppercase", Integer.toString(mActivePasswordUpperCase));
-                out.attribute(null, "lowercase", Integer.toString(mActivePasswordLowerCase));
-                out.attribute(null, "letters", Integer.toString(mActivePasswordLetters));
+                out.attribute(null, "quality", Integer.toString(policy.mActivePasswordQuality));
+                out.attribute(null, "length", Integer.toString(policy.mActivePasswordLength));
+                out.attribute(null, "uppercase", Integer.toString(policy.mActivePasswordUpperCase));
+                out.attribute(null, "lowercase", Integer.toString(policy.mActivePasswordLowerCase));
+                out.attribute(null, "letters", Integer.toString(policy.mActivePasswordLetters));
                 out.attribute(null, "numeric", Integer
-                        .toString(mActivePasswordNumeric));
-                out.attribute(null, "symbols", Integer.toString(mActivePasswordSymbols));
-                out.attribute(null, "nonletter", Integer.toString(mActivePasswordNonLetter));
+                        .toString(policy.mActivePasswordNumeric));
+                out.attribute(null, "symbols", Integer.toString(policy.mActivePasswordSymbols));
+                out.attribute(null, "nonletter", Integer.toString(policy.mActivePasswordNonLetter));
                 out.endTag(null, "active-password");
             }
 
@@ -696,7 +790,7 @@
             out.endDocument();
             stream.close();
             journal.commit();
-            sendChangedNotification();
+            sendChangedNotification(userHandle);
         } catch (IOException e) {
             try {
                 if (stream != null) {
@@ -709,14 +803,19 @@
         }
     }
 
-    private void sendChangedNotification() {
+    private void sendChangedNotification(int userHandle) {
         Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
         intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-        mContext.sendBroadcast(intent);
+        long ident = Binder.clearCallingIdentity();
+        try {
+            mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle));
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
     }
 
-    private void loadSettingsLocked() {
-        JournaledFile journal = makeJournaledFile();
+    private void loadSettingsLocked(DevicePolicyData policy, int userHandle) {
+        JournaledFile journal = makeJournaledFile(userHandle);
         FileInputStream stream = null;
         File file = journal.chooseForRead();
         try {
@@ -745,40 +844,46 @@
                     String name = parser.getAttributeValue(null, "name");
                     try {
                         DeviceAdminInfo dai = findAdmin(
-                                ComponentName.unflattenFromString(name));
+                                ComponentName.unflattenFromString(name), userHandle);
+                        if (DBG && (UserHandle.getUserId(dai.getActivityInfo().applicationInfo.uid)
+                                != userHandle)) {
+                            Slog.w(TAG, "findAdmin returned an incorrect uid "
+                                    + dai.getActivityInfo().applicationInfo.uid + " for user "
+                                    + userHandle);
+                        }
                         if (dai != null) {
                             ActiveAdmin ap = new ActiveAdmin(dai);
                             ap.readFromXml(parser);
-                            mAdminMap.put(ap.info.getComponent(), ap);
-                            mAdminList.add(ap);
+                            policy.mAdminMap.put(ap.info.getComponent(), ap);
+                            policy.mAdminList.add(ap);
                         }
                     } catch (RuntimeException e) {
                         Slog.w(TAG, "Failed loading admin " + name, e);
                     }
                 } else if ("failed-password-attempts".equals(tag)) {
-                    mFailedPasswordAttempts = Integer.parseInt(
+                    policy.mFailedPasswordAttempts = Integer.parseInt(
                             parser.getAttributeValue(null, "value"));
                     XmlUtils.skipCurrentTag(parser);
                 } else if ("password-owner".equals(tag)) {
-                    mPasswordOwner = Integer.parseInt(
+                    policy.mPasswordOwner = Integer.parseInt(
                             parser.getAttributeValue(null, "value"));
                     XmlUtils.skipCurrentTag(parser);
                 } else if ("active-password".equals(tag)) {
-                    mActivePasswordQuality = Integer.parseInt(
+                    policy.mActivePasswordQuality = Integer.parseInt(
                             parser.getAttributeValue(null, "quality"));
-                    mActivePasswordLength = Integer.parseInt(
+                    policy.mActivePasswordLength = Integer.parseInt(
                             parser.getAttributeValue(null, "length"));
-                    mActivePasswordUpperCase = Integer.parseInt(
+                    policy.mActivePasswordUpperCase = Integer.parseInt(
                             parser.getAttributeValue(null, "uppercase"));
-                    mActivePasswordLowerCase = Integer.parseInt(
+                    policy.mActivePasswordLowerCase = Integer.parseInt(
                             parser.getAttributeValue(null, "lowercase"));
-                    mActivePasswordLetters = Integer.parseInt(
+                    policy.mActivePasswordLetters = Integer.parseInt(
                             parser.getAttributeValue(null, "letters"));
-                    mActivePasswordNumeric = Integer.parseInt(
+                    policy.mActivePasswordNumeric = Integer.parseInt(
                             parser.getAttributeValue(null, "numeric"));
-                    mActivePasswordSymbols = Integer.parseInt(
+                    policy.mActivePasswordSymbols = Integer.parseInt(
                             parser.getAttributeValue(null, "symbols"));
-                    mActivePasswordNonLetter = Integer.parseInt(
+                    policy.mActivePasswordNonLetter = Integer.parseInt(
                             parser.getAttributeValue(null, "nonletter"));
                     XmlUtils.skipCurrentTag(parser);
                 } else {
@@ -812,24 +917,24 @@
         // a sanity check in case the two get out of sync; this should
         // never normally happen.
         LockPatternUtils utils = new LockPatternUtils(mContext);
-        if (utils.getActivePasswordQuality() < mActivePasswordQuality) {
+        if (utils.getActivePasswordQuality() < policy.mActivePasswordQuality) {
             Slog.w(TAG, "Active password quality 0x"
-                    + Integer.toHexString(mActivePasswordQuality)
+                    + Integer.toHexString(policy.mActivePasswordQuality)
                     + " does not match actual quality 0x"
                     + Integer.toHexString(utils.getActivePasswordQuality()));
-            mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
-            mActivePasswordLength = 0;
-            mActivePasswordUpperCase = 0;
-            mActivePasswordLowerCase = 0;
-            mActivePasswordLetters = 0;
-            mActivePasswordNumeric = 0;
-            mActivePasswordSymbols = 0;
-            mActivePasswordNonLetter = 0;
+            policy.mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+            policy.mActivePasswordLength = 0;
+            policy.mActivePasswordUpperCase = 0;
+            policy.mActivePasswordLowerCase = 0;
+            policy.mActivePasswordLetters = 0;
+            policy.mActivePasswordNumeric = 0;
+            policy.mActivePasswordSymbols = 0;
+            policy.mActivePasswordNonLetter = 0;
         }
 
-        validatePasswordOwnerLocked();
-        syncDeviceCapabilitiesLocked();
-        updateMaximumTimeToLockLocked();
+        validatePasswordOwnerLocked(policy);
+        syncDeviceCapabilitiesLocked(policy);
+        updateMaximumTimeToLockLocked(policy);
     }
 
     static void validateQualityConstant(int quality) {
@@ -847,19 +952,19 @@
                 + Integer.toHexString(quality));
     }
 
-    void validatePasswordOwnerLocked() {
-        if (mPasswordOwner >= 0) {
+    void validatePasswordOwnerLocked(DevicePolicyData policy) {
+        if (policy.mPasswordOwner >= 0) {
             boolean haveOwner = false;
-            for (int i=mAdminList.size()-1; i>=0; i--) {
-                if (mAdminList.get(i).getUid() == mPasswordOwner) {
+            for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
+                if (policy.mAdminList.get(i).getUid() == policy.mPasswordOwner) {
                     haveOwner = true;
                     break;
                 }
             }
             if (!haveOwner) {
-                Slog.w(TAG, "Previous password owner " + mPasswordOwner
+                Slog.w(TAG, "Previous password owner " + policy.mPasswordOwner
                         + " no longer active; disabling");
-                mPasswordOwner = -1;
+                policy.mPasswordOwner = -1;
             }
         }
     }
@@ -868,11 +973,11 @@
      * Pushes down policy information to the system for any policies related to general device
      * capabilities that need to be enforced by lower level services (e.g. Camera services).
      */
-    void syncDeviceCapabilitiesLocked() {
+    void syncDeviceCapabilitiesLocked(DevicePolicyData policy) {
         // Ensure the status of the camera is synced down to the system. Interested native services
         // should monitor this value and act accordingly.
         boolean systemState = SystemProperties.getBoolean(SYSTEM_PROP_DISABLE_CAMERA, false);
-        boolean cameraDisabled = getCameraDisabled(null);
+        boolean cameraDisabled = getCameraDisabled(null, policy.mUserHandle);
         if (cameraDisabled != systemState) {
             long token = Binder.clearCallingIdentity();
             try {
@@ -888,19 +993,19 @@
 
     public void systemReady() {
         synchronized (this) {
-            loadSettingsLocked();
+            loadSettingsLocked(getUserData(UserHandle.USER_OWNER), UserHandle.USER_OWNER);
         }
     }
 
-    private void handlePasswordExpirationNotification() {
+    private void handlePasswordExpirationNotification(DevicePolicyData policy) {
         synchronized (this) {
             final long now = System.currentTimeMillis();
-            final int N = mAdminList.size();
+            final int N = policy.mAdminList.size();
             if (N <= 0) {
                 return;
             }
             for (int i=0; i < N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)
                         && admin.passwordExpirationTimeout > 0L
                         && admin.passwordExpirationDate > 0L
@@ -908,7 +1013,7 @@
                     sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING);
                 }
             }
-            setExpirationAlarmCheckLocked(mContext);
+            setExpirationAlarmCheckLocked(mContext, policy);
         }
     }
 
@@ -916,27 +1021,29 @@
      * @param adminReceiver The admin to add
      * @param refreshing true = update an active admin, no error
      */
-    public void setActiveAdmin(ComponentName adminReceiver, boolean refreshing) {
+    public void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
+        enforceCrossUserPermission(userHandle);
 
-        DeviceAdminInfo info = findAdmin(adminReceiver);
+        DevicePolicyData policy = getUserData(userHandle);
+        DeviceAdminInfo info = findAdmin(adminReceiver, userHandle);
         if (info == null) {
             throw new IllegalArgumentException("Bad admin: " + adminReceiver);
         }
         synchronized (this) {
             long ident = Binder.clearCallingIdentity();
             try {
-                if (!refreshing && getActiveAdminUncheckedLocked(adminReceiver) != null) {
+                if (!refreshing && getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null) {
                     throw new IllegalArgumentException("Admin is already added");
                 }
                 ActiveAdmin newAdmin = new ActiveAdmin(info);
-                mAdminMap.put(adminReceiver, newAdmin);
+                policy.mAdminMap.put(adminReceiver, newAdmin);
                 int replaceIndex = -1;
                 if (refreshing) {
-                    final int N = mAdminList.size();
+                    final int N = policy.mAdminList.size();
                     for (int i=0; i < N; i++) {
-                        ActiveAdmin oldAdmin = mAdminList.get(i);
+                        ActiveAdmin oldAdmin = policy.mAdminList.get(i);
                         if (oldAdmin.info.getComponent().equals(adminReceiver)) {
                             replaceIndex = i;
                             break;
@@ -944,11 +1051,11 @@
                     }
                 }
                 if (replaceIndex == -1) {
-                    mAdminList.add(newAdmin);
+                    policy.mAdminList.add(newAdmin);
                 } else {
-                    mAdminList.set(replaceIndex, newAdmin);
+                    policy.mAdminList.set(replaceIndex, newAdmin);
                 }
-                saveSettingsLocked();
+                saveSettingsLocked(userHandle);
                 sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED);
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -956,15 +1063,17 @@
         }
     }
 
-    public boolean isAdminActive(ComponentName adminReceiver) {
+    public boolean isAdminActive(ComponentName adminReceiver, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
-            return getActiveAdminUncheckedLocked(adminReceiver) != null;
+            return getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null;
         }
     }
 
-    public boolean hasGrantedPolicy(ComponentName adminReceiver, int policyId) {
+    public boolean hasGrantedPolicy(ComponentName adminReceiver, int policyId, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
-            ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver);
+            ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
             if (administrator == null) {
                 throw new SecurityException("No active admin " + adminReceiver);
             }
@@ -972,25 +1081,29 @@
         }
     }
 
-    public List<ComponentName> getActiveAdmins() {
+    public List<ComponentName> getActiveAdmins(int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
-            final int N = mAdminList.size();
+            DevicePolicyData policy = getUserData(userHandle);
+            final int N = policy.mAdminList.size();
             if (N <= 0) {
                 return null;
             }
             ArrayList<ComponentName> res = new ArrayList<ComponentName>(N);
             for (int i=0; i<N; i++) {
-                res.add(mAdminList.get(i).info.getComponent());
+                res.add(policy.mAdminList.get(i).info.getComponent());
             }
             return res;
         }
     }
 
-    public boolean packageHasActiveAdmins(String packageName) {
+    public boolean packageHasActiveAdmins(String packageName, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
-            final int N = mAdminList.size();
+            DevicePolicyData policy = getUserData(userHandle);
+            final int N = policy.mAdminList.size();
             for (int i=0; i<N; i++) {
-                if (mAdminList.get(i).info.getPackageName().equals(packageName)) {
+                if (policy.mAdminList.get(i).info.getPackageName().equals(packageName)) {
                     return true;
                 }
             }
@@ -998,9 +1111,10 @@
         }
     }
 
-    public void removeActiveAdmin(ComponentName adminReceiver) {
+    public void removeActiveAdmin(ComponentName adminReceiver, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
-            ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
+            ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
             if (admin == null) {
                 return;
             }
@@ -1010,15 +1124,16 @@
             }
             long ident = Binder.clearCallingIdentity();
             try {
-                removeActiveAdminLocked(adminReceiver);
+                removeActiveAdminLocked(adminReceiver, userHandle);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
         }
     }
 
-    public void setPasswordQuality(ComponentName who, int quality) {
+    public void setPasswordQuality(ComponentName who, int quality, int userHandle) {
         validateQualityConstant(quality);
+        enforceCrossUserPermission(userHandle);
 
         synchronized (this) {
             if (who == null) {
@@ -1028,23 +1143,25 @@
                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
             if (ap.passwordQuality != quality) {
                 ap.passwordQuality = quality;
-                saveSettingsLocked();
+                saveSettingsLocked(userHandle);
             }
         }
     }
 
-    public int getPasswordQuality(ComponentName who) {
+    public int getPasswordQuality(ComponentName who, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+            DevicePolicyData policy = getUserData(userHandle);
 
             if (who != null) {
-                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+                ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
                 return admin != null ? admin.passwordQuality : mode;
             }
 
-            final int N = mAdminList.size();
+            final int N = policy.mAdminList.size();
             for  (int i=0; i<N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (mode < admin.passwordQuality) {
                     mode = admin.passwordQuality;
                 }
@@ -1053,7 +1170,8 @@
         }
     }
 
-    public void setPasswordMinimumLength(ComponentName who, int length) {
+    public void setPasswordMinimumLength(ComponentName who, int length, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -1062,23 +1180,25 @@
                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
             if (ap.minimumPasswordLength != length) {
                 ap.minimumPasswordLength = length;
-                saveSettingsLocked();
+                saveSettingsLocked(userHandle);
             }
         }
     }
 
-    public int getPasswordMinimumLength(ComponentName who) {
+    public int getPasswordMinimumLength(ComponentName who, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
+            DevicePolicyData policy = getUserData(userHandle);
             int length = 0;
 
             if (who != null) {
-                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+                ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
                 return admin != null ? admin.minimumPasswordLength : length;
             }
 
-            final int N = mAdminList.size();
+            final int N = policy.mAdminList.size();
             for  (int i=0; i<N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (length < admin.minimumPasswordLength) {
                     length = admin.minimumPasswordLength;
                 }
@@ -1087,7 +1207,8 @@
         }
     }
 
-    public void setPasswordHistoryLength(ComponentName who, int length) {
+    public void setPasswordHistoryLength(ComponentName who, int length, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -1096,23 +1217,25 @@
                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
             if (ap.passwordHistoryLength != length) {
                 ap.passwordHistoryLength = length;
-                saveSettingsLocked();
+                saveSettingsLocked(userHandle);
             }
         }
     }
 
-    public int getPasswordHistoryLength(ComponentName who) {
+    public int getPasswordHistoryLength(ComponentName who, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
+            DevicePolicyData policy = getUserData(userHandle);
             int length = 0;
 
             if (who != null) {
-                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+                ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
                 return admin != null ? admin.passwordHistoryLength : length;
             }
 
-            final int N = mAdminList.size();
+            final int N = policy.mAdminList.size();
             for (int i = 0; i < N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (length < admin.passwordHistoryLength) {
                     length = admin.passwordHistoryLength;
                 }
@@ -1121,7 +1244,8 @@
         }
     }
 
-    public void setPasswordExpirationTimeout(ComponentName who, long timeout) {
+    public void setPasswordExpirationTimeout(ComponentName who, long timeout, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -1140,8 +1264,9 @@
                         + DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)
                         .format(new Date(expiration)));
             }
-            saveSettingsLocked();
-            setExpirationAlarmCheckLocked(mContext); // in case this is the first one
+            saveSettingsLocked(userHandle);
+            // in case this is the first one
+            setExpirationAlarmCheckLocked(mContext, getUserData(userHandle));
         }
     }
 
@@ -1149,17 +1274,19 @@
      * Return a single admin's expiration cycle time, or the min of all cycle times.
      * Returns 0 if not configured.
      */
-    public long getPasswordExpirationTimeout(ComponentName who) {
+    public long getPasswordExpirationTimeout(ComponentName who, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             if (who != null) {
-                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+                ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
                 return admin != null ? admin.passwordExpirationTimeout : 0L;
             }
 
             long timeout = 0L;
-            final int N = mAdminList.size();
+            DevicePolicyData policy = getUserData(userHandle);
+            final int N = policy.mAdminList.size();
             for (int i = 0; i < N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (timeout == 0L || (admin.passwordExpirationTimeout != 0L
                         && timeout > admin.passwordExpirationTimeout)) {
                     timeout = admin.passwordExpirationTimeout;
@@ -1173,16 +1300,17 @@
      * Return a single admin's expiration date/time, or the min (soonest) for all admins.
      * Returns 0 if not configured.
      */
-    private long getPasswordExpirationLocked(ComponentName who) {
+    private long getPasswordExpirationLocked(ComponentName who, int userHandle) {
         if (who != null) {
-            ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+            ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
             return admin != null ? admin.passwordExpirationDate : 0L;
         }
 
         long timeout = 0L;
-        final int N = mAdminList.size();
+        DevicePolicyData policy = getUserData(userHandle);
+        final int N = policy.mAdminList.size();
         for (int i = 0; i < N; i++) {
-            ActiveAdmin admin = mAdminList.get(i);
+            ActiveAdmin admin = policy.mAdminList.get(i);
             if (timeout == 0L || (admin.passwordExpirationDate != 0
                     && timeout > admin.passwordExpirationDate)) {
                 timeout = admin.passwordExpirationDate;
@@ -1191,13 +1319,15 @@
         return timeout;
     }
 
-    public long getPasswordExpiration(ComponentName who) {
+    public long getPasswordExpiration(ComponentName who, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
-            return getPasswordExpirationLocked(who);
+            return getPasswordExpirationLocked(who, userHandle);
         }
     }
 
-    public void setPasswordMinimumUpperCase(ComponentName who, int length) {
+    public void setPasswordMinimumUpperCase(ComponentName who, int length, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -1206,23 +1336,25 @@
                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
             if (ap.minimumPasswordUpperCase != length) {
                 ap.minimumPasswordUpperCase = length;
-                saveSettingsLocked();
+                saveSettingsLocked(userHandle);
             }
         }
     }
 
-    public int getPasswordMinimumUpperCase(ComponentName who) {
+    public int getPasswordMinimumUpperCase(ComponentName who, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             int length = 0;
 
             if (who != null) {
-                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+                ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
                 return admin != null ? admin.minimumPasswordUpperCase : length;
             }
 
-            final int N = mAdminList.size();
+            DevicePolicyData policy = getUserData(userHandle);
+            final int N = policy.mAdminList.size();
             for (int i=0; i<N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (length < admin.minimumPasswordUpperCase) {
                     length = admin.minimumPasswordUpperCase;
                 }
@@ -1231,7 +1363,8 @@
         }
     }
 
-    public void setPasswordMinimumLowerCase(ComponentName who, int length) {
+    public void setPasswordMinimumLowerCase(ComponentName who, int length, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -1240,23 +1373,25 @@
                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
             if (ap.minimumPasswordLowerCase != length) {
                 ap.minimumPasswordLowerCase = length;
-                saveSettingsLocked();
+                saveSettingsLocked(userHandle);
             }
         }
     }
 
-    public int getPasswordMinimumLowerCase(ComponentName who) {
+    public int getPasswordMinimumLowerCase(ComponentName who, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             int length = 0;
 
             if (who != null) {
-                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+                ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
                 return admin != null ? admin.minimumPasswordLowerCase : length;
             }
 
-            final int N = mAdminList.size();
+            DevicePolicyData policy = getUserData(userHandle);
+            final int N = policy.mAdminList.size();
             for (int i=0; i<N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (length < admin.minimumPasswordLowerCase) {
                     length = admin.minimumPasswordLowerCase;
                 }
@@ -1265,7 +1400,8 @@
         }
     }
 
-    public void setPasswordMinimumLetters(ComponentName who, int length) {
+    public void setPasswordMinimumLetters(ComponentName who, int length, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -1274,23 +1410,25 @@
                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
             if (ap.minimumPasswordLetters != length) {
                 ap.minimumPasswordLetters = length;
-                saveSettingsLocked();
+                saveSettingsLocked(userHandle);
             }
         }
     }
 
-    public int getPasswordMinimumLetters(ComponentName who) {
+    public int getPasswordMinimumLetters(ComponentName who, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             int length = 0;
 
             if (who != null) {
-                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+                ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
                 return admin != null ? admin.minimumPasswordLetters : length;
             }
 
-            final int N = mAdminList.size();
+            DevicePolicyData policy = getUserData(userHandle);
+            final int N = policy.mAdminList.size();
             for (int i=0; i<N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (length < admin.minimumPasswordLetters) {
                     length = admin.minimumPasswordLetters;
                 }
@@ -1299,7 +1437,8 @@
         }
     }
 
-    public void setPasswordMinimumNumeric(ComponentName who, int length) {
+    public void setPasswordMinimumNumeric(ComponentName who, int length, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -1308,23 +1447,25 @@
                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
             if (ap.minimumPasswordNumeric != length) {
                 ap.minimumPasswordNumeric = length;
-                saveSettingsLocked();
+                saveSettingsLocked(userHandle);
             }
         }
     }
 
-    public int getPasswordMinimumNumeric(ComponentName who) {
+    public int getPasswordMinimumNumeric(ComponentName who, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             int length = 0;
 
             if (who != null) {
-                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+                ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
                 return admin != null ? admin.minimumPasswordNumeric : length;
             }
 
-            final int N = mAdminList.size();
+            DevicePolicyData policy = getUserData(userHandle);
+            final int N = policy.mAdminList.size();
             for (int i = 0; i < N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (length < admin.minimumPasswordNumeric) {
                     length = admin.minimumPasswordNumeric;
                 }
@@ -1333,7 +1474,8 @@
         }
     }
 
-    public void setPasswordMinimumSymbols(ComponentName who, int length) {
+    public void setPasswordMinimumSymbols(ComponentName who, int length, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -1342,23 +1484,25 @@
                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
             if (ap.minimumPasswordSymbols != length) {
                 ap.minimumPasswordSymbols = length;
-                saveSettingsLocked();
+                saveSettingsLocked(userHandle);
             }
         }
     }
 
-    public int getPasswordMinimumSymbols(ComponentName who) {
+    public int getPasswordMinimumSymbols(ComponentName who, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             int length = 0;
 
             if (who != null) {
-                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+                ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
                 return admin != null ? admin.minimumPasswordSymbols : length;
             }
 
-            final int N = mAdminList.size();
+            DevicePolicyData policy = getUserData(userHandle);
+            final int N = policy.mAdminList.size();
             for  (int i=0; i<N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (length < admin.minimumPasswordSymbols) {
                     length = admin.minimumPasswordSymbols;
                 }
@@ -1367,7 +1511,8 @@
         }
     }
 
-    public void setPasswordMinimumNonLetter(ComponentName who, int length) {
+    public void setPasswordMinimumNonLetter(ComponentName who, int length, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -1376,23 +1521,25 @@
                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
             if (ap.minimumPasswordNonLetter != length) {
                 ap.minimumPasswordNonLetter = length;
-                saveSettingsLocked();
+                saveSettingsLocked(userHandle);
             }
         }
     }
 
-    public int getPasswordMinimumNonLetter(ComponentName who) {
+    public int getPasswordMinimumNonLetter(ComponentName who, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             int length = 0;
 
             if (who != null) {
-                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+                ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
                 return admin != null ? admin.minimumPasswordNonLetter : length;
             }
 
-            final int N = mAdminList.size();
+            DevicePolicyData policy = getUserData(userHandle);
+            final int N = policy.mAdminList.size();
             for (int i=0; i<N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (length < admin.minimumPasswordNonLetter) {
                     length = admin.minimumPasswordNonLetter;
                 }
@@ -1401,39 +1548,43 @@
         }
     }
 
-    public boolean isActivePasswordSufficient() {
+    public boolean isActivePasswordSufficient(int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
+            DevicePolicyData policy = getUserData(userHandle);
             // This API can only be called by an active device admin,
             // so try to retrieve it to check that the caller is one.
             getActiveAdminForCallerLocked(null,
                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
-            if (mActivePasswordQuality < getPasswordQuality(null)
-                    || mActivePasswordLength < getPasswordMinimumLength(null)) {
+            if (policy.mActivePasswordQuality < getPasswordQuality(null, userHandle)
+                    || policy.mActivePasswordLength < getPasswordMinimumLength(null, userHandle)) {
                 return false;
             }
-            if(mActivePasswordQuality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
+            if (policy.mActivePasswordQuality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
                 return true;
             }
-            return mActivePasswordUpperCase >= getPasswordMinimumUpperCase(null)
-                    && mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null)
-                    && mActivePasswordLetters >= getPasswordMinimumLetters(null)
-                    && mActivePasswordNumeric >= getPasswordMinimumNumeric(null)
-                    && mActivePasswordSymbols >= getPasswordMinimumSymbols(null)
-                    && mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null);
+            return policy.mActivePasswordUpperCase >= getPasswordMinimumUpperCase(null, userHandle)
+                    && policy.mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null, userHandle)
+                    && policy.mActivePasswordLetters >= getPasswordMinimumLetters(null, userHandle)
+                    && policy.mActivePasswordNumeric >= getPasswordMinimumNumeric(null, userHandle)
+                    && policy.mActivePasswordSymbols >= getPasswordMinimumSymbols(null, userHandle)
+                    && policy.mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null, userHandle);
         }
     }
 
-    public int getCurrentFailedPasswordAttempts() {
+    public int getCurrentFailedPasswordAttempts(int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             // This API can only be called by an active device admin,
             // so try to retrieve it to check that the caller is one.
             getActiveAdminForCallerLocked(null,
                     DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
-            return mFailedPasswordAttempts;
+            return getUserData(userHandle).mFailedPasswordAttempts;
         }
     }
 
-    public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) {
+    public void setMaximumFailedPasswordsForWipe(ComponentName who, int num, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             // This API can only be called by an active device admin,
             // so try to retrieve it to check that the caller is one.
@@ -1443,23 +1594,25 @@
                     DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
             if (ap.maximumFailedPasswordsForWipe != num) {
                 ap.maximumFailedPasswordsForWipe = num;
-                saveSettingsLocked();
+                saveSettingsLocked(userHandle);
             }
         }
     }
 
-    public int getMaximumFailedPasswordsForWipe(ComponentName who) {
+    public int getMaximumFailedPasswordsForWipe(ComponentName who, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
+            DevicePolicyData policy = getUserData(userHandle);
             int count = 0;
 
             if (who != null) {
-                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+                ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
                 return admin != null ? admin.maximumFailedPasswordsForWipe : count;
             }
 
-            final int N = mAdminList.size();
+            final int N = policy.mAdminList.size();
             for  (int i=0; i<N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (count == 0) {
                     count = admin.maximumFailedPasswordsForWipe;
                 } else if (admin.maximumFailedPasswordsForWipe != 0
@@ -1471,14 +1624,15 @@
         }
     }
 
-    public boolean resetPassword(String password, int flags) {
+    public boolean resetPassword(String password, int flags, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         int quality;
         synchronized (this) {
             // This API can only be called by an active device admin,
             // so try to retrieve it to check that the caller is one.
             getActiveAdminForCallerLocked(null,
                     DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
-            quality = getPasswordQuality(null);
+            quality = getPasswordQuality(null, userHandle);
             if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
                 int realQuality = LockPatternUtils.computePasswordQuality(password);
                 if (realQuality < quality
@@ -1491,7 +1645,7 @@
                 }
                 quality = Math.max(realQuality, quality);
             }
-            int length = getPasswordMinimumLength(null);
+            int length = getPasswordMinimumLength(null, userHandle);
             if (password.length() < length) {
                 Slog.w(TAG, "resetPassword: password length " + password.length()
                         + " does not meet required length " + length);
@@ -1520,13 +1674,13 @@
                         nonletter++;
                     }
                 }
-                int neededLetters = getPasswordMinimumLetters(null);
+                int neededLetters = getPasswordMinimumLetters(null, userHandle);
                 if(letters < neededLetters) {
                     Slog.w(TAG, "resetPassword: number of letters " + letters
                             + " does not meet required number of letters " + neededLetters);
                     return false;
                 }
-                int neededNumbers = getPasswordMinimumNumeric(null);
+                int neededNumbers = getPasswordMinimumNumeric(null, userHandle);
                 if (numbers < neededNumbers) {
                     Slog
                             .w(TAG, "resetPassword: number of numerical digits " + numbers
@@ -1534,27 +1688,27 @@
                                     + neededNumbers);
                     return false;
                 }
-                int neededLowerCase = getPasswordMinimumLowerCase(null);
+                int neededLowerCase = getPasswordMinimumLowerCase(null, userHandle);
                 if (lowercase < neededLowerCase) {
                     Slog.w(TAG, "resetPassword: number of lowercase letters " + lowercase
                             + " does not meet required number of lowercase letters "
                             + neededLowerCase);
                     return false;
                 }
-                int neededUpperCase = getPasswordMinimumUpperCase(null);
+                int neededUpperCase = getPasswordMinimumUpperCase(null, userHandle);
                 if (uppercase < neededUpperCase) {
                     Slog.w(TAG, "resetPassword: number of uppercase letters " + uppercase
                             + " does not meet required number of uppercase letters "
                             + neededUpperCase);
                     return false;
                 }
-                int neededSymbols = getPasswordMinimumSymbols(null);
+                int neededSymbols = getPasswordMinimumSymbols(null, userHandle);
                 if (symbols < neededSymbols) {
                     Slog.w(TAG, "resetPassword: number of special symbols " + symbols
                             + " does not meet required number of special symbols " + neededSymbols);
                     return false;
                 }
-                int neededNonLetter = getPasswordMinimumNonLetter(null);
+                int neededNonLetter = getPasswordMinimumNonLetter(null, userHandle);
                 if (nonletter < neededNonLetter) {
                     Slog.w(TAG, "resetPassword: number of non-letter characters " + nonletter
                             + " does not meet required number of non-letter characters "
@@ -1565,7 +1719,8 @@
         }
 
         int callingUid = Binder.getCallingUid();
-        if (mPasswordOwner >= 0 && mPasswordOwner != callingUid) {
+        DevicePolicyData policy = getUserData(userHandle);
+        if (policy.mPasswordOwner >= 0 && policy.mPasswordOwner != callingUid) {
             Slog.w(TAG, "resetPassword: already set by another uid and not entered by user");
             return false;
         }
@@ -1575,13 +1730,13 @@
         long ident = Binder.clearCallingIdentity();
         try {
             LockPatternUtils utils = new LockPatternUtils(mContext);
-            utils.saveLockPassword(password, quality);
+            utils.saveLockPassword(password, quality, false, userHandle);
             synchronized (this) {
                 int newOwner = (flags&DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY)
                         != 0 ? callingUid : -1;
-                if (mPasswordOwner != newOwner) {
-                    mPasswordOwner = newOwner;
-                    saveSettingsLocked();
+                if (policy.mPasswordOwner != newOwner) {
+                    policy.mPasswordOwner = newOwner;
+                    saveSettingsLocked(userHandle);
                 }
             }
         } finally {
@@ -1591,7 +1746,8 @@
         return true;
     }
 
-    public void setMaximumTimeToLock(ComponentName who, long timeMs) {
+    public void setMaximumTimeToLock(ComponentName who, long timeMs, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -1600,15 +1756,15 @@
                     DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
             if (ap.maximumTimeToUnlock != timeMs) {
                 ap.maximumTimeToUnlock = timeMs;
-                saveSettingsLocked();
-                updateMaximumTimeToLockLocked();
+                saveSettingsLocked(userHandle);
+                updateMaximumTimeToLockLocked(getUserData(userHandle));
             }
         }
     }
 
-    void updateMaximumTimeToLockLocked() {
-        long timeMs = getMaximumTimeToLock(null);
-        if (mLastMaximumTimeToLock == timeMs) {
+    void updateMaximumTimeToLockLocked(DevicePolicyData policy) {
+        long timeMs = getMaximumTimeToLock(null, policy.mUserHandle);
+        if (policy.mLastMaximumTimeToLock == timeMs) {
             return;
         }
 
@@ -1619,14 +1775,14 @@
             } else {
                 // Make sure KEEP_SCREEN_ON is disabled, since that
                 // would allow bypassing of the maximum time to lock.
-                Settings.System.putInt(mContext.getContentResolver(),
-                        Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0);
+                Settings.Global.putInt(mContext.getContentResolver(),
+                        Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
             }
 
-            mLastMaximumTimeToLock = timeMs;
+            policy.mLastMaximumTimeToLock = timeMs;
 
             try {
-                getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
+                getIPowerManager().setMaximumScreenOffTimeoutFromDeviceAdmin((int)timeMs);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Failure talking with power manager", e);
             }
@@ -1635,18 +1791,20 @@
         }
     }
 
-    public long getMaximumTimeToLock(ComponentName who) {
+    public long getMaximumTimeToLock(ComponentName who, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             long time = 0;
 
             if (who != null) {
-                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+                ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
                 return admin != null ? admin.maximumTimeToUnlock : time;
             }
 
-            final int N = mAdminList.size();
+            DevicePolicyData policy = getUserData(userHandle);
+            final int N = policy.mAdminList.size();
             for  (int i=0; i<N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (time == 0) {
                     time = admin.maximumTimeToUnlock;
                 } else if (admin.maximumTimeToUnlock != 0
@@ -1664,17 +1822,21 @@
             // so try to retrieve it to check that the caller is one.
             getActiveAdminForCallerLocked(null,
                     DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
-            long ident = Binder.clearCallingIdentity();
-            try {
-                // Power off the display
-                mIPowerManager.goToSleepWithReason(SystemClock.uptimeMillis(),
-                        WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN);
-                // Ensure the device is locked
-                getWindowManager().lockNow();
-            } catch (RemoteException e) {
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
+            lockNowUnchecked();
+        }
+    }
+
+    private void lockNowUnchecked() {
+        long ident = Binder.clearCallingIdentity();
+        try {
+            // Power off the display
+            getIPowerManager().goToSleep(SystemClock.uptimeMillis(),
+                    PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN);
+            // Ensure the device is locked
+            getWindowManager().lockNow(null);
+        } catch (RemoteException e) {
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
@@ -1704,7 +1866,8 @@
         }
     }
 
-    public void wipeData(int flags) {
+    public void wipeData(int flags, final int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             // This API can only be called by an active device admin,
             // so try to retrieve it to check that the caller is one.
@@ -1712,19 +1875,35 @@
                     DeviceAdminInfo.USES_POLICY_WIPE_DATA);
             long ident = Binder.clearCallingIdentity();
             try {
-                wipeDataLocked(flags);
+                if (userHandle == UserHandle.USER_OWNER) {
+                    wipeDataLocked(flags);
+                } else {
+                    lockNowUnchecked();
+                    mHandler.post(new Runnable() {
+                        public void run() {
+                            try {
+                                ActivityManagerNative.getDefault().switchUser(0);
+                                ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
+                                        .removeUser(userHandle);
+                            } catch (RemoteException re) {
+                                // Shouldn't happen
+                            }
+                        }
+                    });
+                }
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
         }
     }
 
-    public void getRemoveWarning(ComponentName comp, final RemoteCallback result) {
+    public void getRemoveWarning(ComponentName comp, final RemoteCallback result, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
 
         synchronized (this) {
-            ActiveAdmin admin = getActiveAdminUncheckedLocked(comp);
+            ActiveAdmin admin = getActiveAdminUncheckedLocked(comp, userHandle);
             if (admin == null) {
                 try {
                     result.sendResult(null);
@@ -1734,7 +1913,8 @@
             }
             Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED);
             intent.setComponent(admin.info.getComponent());
-            mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
+            mContext.sendOrderedBroadcastAsUser(intent, new UserHandle(userHandle),
+                    null, new BroadcastReceiver() {
                 @Override
                 public void onReceive(Context context, Intent intent) {
                     try {
@@ -1747,34 +1927,36 @@
     }
 
     public void setActivePasswordState(int quality, int length, int letters, int uppercase,
-            int lowercase, int numbers, int symbols, int nonletter) {
+            int lowercase, int numbers, int symbols, int nonletter, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
+        DevicePolicyData p = getUserData(userHandle);
 
         validateQualityConstant(quality);
 
         synchronized (this) {
-            if (mActivePasswordQuality != quality || mActivePasswordLength != length
-                    || mFailedPasswordAttempts != 0 || mActivePasswordLetters != letters
-                    || mActivePasswordUpperCase != uppercase
-                    || mActivePasswordLowerCase != lowercase || mActivePasswordNumeric != numbers
-                    || mActivePasswordSymbols != symbols || mActivePasswordNonLetter != nonletter) {
+            if (p.mActivePasswordQuality != quality || p.mActivePasswordLength != length
+                    || p.mFailedPasswordAttempts != 0 || p.mActivePasswordLetters != letters
+                    || p.mActivePasswordUpperCase != uppercase
+                    || p.mActivePasswordLowerCase != lowercase || p.mActivePasswordNumeric != numbers
+                    || p.mActivePasswordSymbols != symbols || p.mActivePasswordNonLetter != nonletter) {
                 long ident = Binder.clearCallingIdentity();
                 try {
-                    mActivePasswordQuality = quality;
-                    mActivePasswordLength = length;
-                    mActivePasswordLetters = letters;
-                    mActivePasswordLowerCase = lowercase;
-                    mActivePasswordUpperCase = uppercase;
-                    mActivePasswordNumeric = numbers;
-                    mActivePasswordSymbols = symbols;
-                    mActivePasswordNonLetter = nonletter;
-                    mFailedPasswordAttempts = 0;
-                    saveSettingsLocked();
-                    updatePasswordExpirationsLocked();
-                    setExpirationAlarmCheckLocked(mContext);
+                    p.mActivePasswordQuality = quality;
+                    p.mActivePasswordLength = length;
+                    p.mActivePasswordLetters = letters;
+                    p.mActivePasswordLowerCase = lowercase;
+                    p.mActivePasswordUpperCase = uppercase;
+                    p.mActivePasswordNumeric = numbers;
+                    p.mActivePasswordSymbols = symbols;
+                    p.mActivePasswordNonLetter = nonletter;
+                    p.mFailedPasswordAttempts = 0;
+                    saveSettingsLocked(userHandle);
+                    updatePasswordExpirationsLocked(userHandle);
+                    setExpirationAlarmCheckLocked(mContext, p);
                     sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
-                            DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
+                            DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, userHandle);
                 } finally {
                     Binder.restoreCallingIdentity(ident);
                 }
@@ -1785,55 +1967,60 @@
     /**
      * Called any time the device password is updated.  Resets all password expiration clocks.
      */
-    private void updatePasswordExpirationsLocked() {
-        final int N = mAdminList.size();
+    private void updatePasswordExpirationsLocked(int userHandle) {
+        DevicePolicyData policy = getUserData(userHandle);
+        final int N = policy.mAdminList.size();
         if (N > 0) {
             for (int i=0; i<N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) {
                     long timeout = admin.passwordExpirationTimeout;
                     long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L;
                     admin.passwordExpirationDate = expiration;
                 }
             }
-            saveSettingsLocked();
+            saveSettingsLocked(userHandle);
         }
     }
 
-    public void reportFailedPasswordAttempt() {
+    public void reportFailedPasswordAttempt(int userHandle) {
+        enforceCrossUserPermission(userHandle);
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
 
         synchronized (this) {
+            DevicePolicyData policy = getUserData(userHandle);
             long ident = Binder.clearCallingIdentity();
             try {
-                mFailedPasswordAttempts++;
-                saveSettingsLocked();
-                int max = getMaximumFailedPasswordsForWipe(null);
-                if (max > 0 && mFailedPasswordAttempts >= max) {
+                policy.mFailedPasswordAttempts++;
+                saveSettingsLocked(userHandle);
+                int max = getMaximumFailedPasswordsForWipe(null, userHandle);
+                if (max > 0 && policy.mFailedPasswordAttempts >= max) {
                     wipeDataLocked(0);
                 }
                 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
-                        DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
+                        DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
         }
     }
 
-    public void reportSuccessfulPasswordAttempt() {
+    public void reportSuccessfulPasswordAttempt(int userHandle) {
+        enforceCrossUserPermission(userHandle);
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
 
         synchronized (this) {
-            if (mFailedPasswordAttempts != 0 || mPasswordOwner >= 0) {
+            DevicePolicyData policy = getUserData(userHandle);
+            if (policy.mFailedPasswordAttempts != 0 || policy.mPasswordOwner >= 0) {
                 long ident = Binder.clearCallingIdentity();
                 try {
-                    mFailedPasswordAttempts = 0;
-                    mPasswordOwner = -1;
-                    saveSettingsLocked();
+                    policy.mFailedPasswordAttempts = 0;
+                    policy.mPasswordOwner = -1;
+                    saveSettingsLocked(userHandle);
                     sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
-                            DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
+                            DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
                 } finally {
                     Binder.restoreCallingIdentity(ident);
                 }
@@ -1842,26 +2029,36 @@
     }
 
     public ComponentName setGlobalProxy(ComponentName who, String proxySpec,
-            String exclusionList) {
+            String exclusionList, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized(this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
             }
 
+            // Only check if owner has set global proxy. We don't allow other users to set it.
+            DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
                     DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
 
             // Scan through active admins and find if anyone has already
             // set the global proxy.
-            Set<ComponentName> compSet = mAdminMap.keySet();
+            Set<ComponentName> compSet = policy.mAdminMap.keySet();
             for  (ComponentName component : compSet) {
-                ActiveAdmin ap = mAdminMap.get(component);
+                ActiveAdmin ap = policy.mAdminMap.get(component);
                 if ((ap.specifiesGlobalProxy) && (!component.equals(who))) {
                     // Another admin already sets the global proxy
                     // Return it to the caller.
                     return component;
                 }
             }
+
+            // If the user is not the owner, don't set the global proxy. Fail silently.
+            if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
+                Slog.w(TAG, "Only the owner is allowed to set the global proxy. User "
+                        + userHandle + " is not permitted.");
+                return null;
+            }
             if (proxySpec == null) {
                 admin.specifiesGlobalProxy = false;
                 admin.globalProxySpec = null;
@@ -1876,19 +2073,21 @@
             // Reset the global proxy accordingly
             // Do this using system permissions, as apps cannot write to secure settings
             long origId = Binder.clearCallingIdentity();
-            resetGlobalProxyLocked();
+            resetGlobalProxyLocked(policy);
             Binder.restoreCallingIdentity(origId);
             return null;
         }
     }
 
-    public ComponentName getGlobalProxyAdmin() {
+    public ComponentName getGlobalProxyAdmin(int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized(this) {
+            DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
             // Scan through active admins and find if anyone has already
             // set the global proxy.
-            final int N = mAdminList.size();
+            final int N = policy.mAdminList.size();
             for (int i = 0; i < N; i++) {
-                ActiveAdmin ap = mAdminList.get(i);
+                ActiveAdmin ap = policy.mAdminList.get(i);
                 if (ap.specifiesGlobalProxy) {
                     // Device admin sets the global proxy
                     // Return it to the caller.
@@ -1900,10 +2099,10 @@
         return null;
     }
 
-    private void resetGlobalProxyLocked() {
-        final int N = mAdminList.size();
+    private void resetGlobalProxyLocked(DevicePolicyData policy) {
+        final int N = policy.mAdminList.size();
         for (int i = 0; i < N; i++) {
-            ActiveAdmin ap = mAdminList.get(i);
+            ActiveAdmin ap = policy.mAdminList.get(i);
             if (ap.specifiesGlobalProxy) {
                 saveGlobalProxyLocked(ap.globalProxySpec, ap.globalProxyExclusionList);
                 return;
@@ -1931,9 +2130,9 @@
         }
         exclusionList = exclusionList.trim();
         ContentResolver res = mContext.getContentResolver();
-        Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, data[0]);
-        Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, proxyPort);
-        Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
+        Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, data[0]);
+        Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, proxyPort);
+        Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
                 exclusionList);
     }
 
@@ -1941,12 +2140,21 @@
      * Set the storage encryption request for a single admin.  Returns the new total request
      * status (for all admins).
      */
-    public int setStorageEncryption(ComponentName who, boolean encrypt) {
+    public int setStorageEncryption(ComponentName who, boolean encrypt, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             // Check for permissions
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
             }
+            // Only owner can set storage encryption
+            if (userHandle != UserHandle.USER_OWNER
+                    || UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
+                Slog.w(TAG, "Only owner is allowed to set storage encryption. User "
+                        + UserHandle.getCallingUserId() + " is not permitted.");
+                return 0;
+            }
+
             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
                     DeviceAdminInfo.USES_ENCRYPTED_STORAGE);
 
@@ -1958,14 +2166,15 @@
             // (1) Record the value for the admin so it's sticky
             if (ap.encryptionRequested != encrypt) {
                 ap.encryptionRequested = encrypt;
-                saveSettingsLocked();
+                saveSettingsLocked(userHandle);
             }
 
+            DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
             // (2) Compute "max" for all admins
             boolean newRequested = false;
-            final int N = mAdminList.size();
+            final int N = policy.mAdminList.size();
             for (int i = 0; i < N; i++) {
-                newRequested |= mAdminList.get(i).encryptionRequested;
+                newRequested |= policy.mAdminList.get(i).encryptionRequested;
             }
 
             // Notify OS of new request
@@ -1982,20 +2191,22 @@
      * Get the current storage encryption request status for a given admin, or aggregate of all
      * active admins.
      */
-    public boolean getStorageEncryption(ComponentName who) {
+    public boolean getStorageEncryption(ComponentName who, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             // Check for permissions if a particular caller is specified
             if (who != null) {
                 // When checking for a single caller, status is based on caller's request
-                ActiveAdmin ap = getActiveAdminUncheckedLocked(who);
+                ActiveAdmin ap = getActiveAdminUncheckedLocked(who, userHandle);
                 return ap != null ? ap.encryptionRequested : false;
             }
 
             // If no particular caller is specified, return the aggregate set of requests.
             // This is short circuited by returning true on the first hit.
-            final int N = mAdminList.size();
+            DevicePolicyData policy = getUserData(userHandle);
+            final int N = policy.mAdminList.size();
             for (int i = 0; i < N; i++) {
-                if (mAdminList.get(i).encryptionRequested) {
+                if (policy.mAdminList.get(i).encryptionRequested) {
                     return true;
                 }
             }
@@ -2006,7 +2217,8 @@
     /**
      * Get the current encryption status of the device.
      */
-    public int getStorageEncryptionStatus() {
+    public int getStorageEncryptionStatus(int userHandle) {
+        enforceCrossUserPermission(userHandle);
         return getEncryptionStatus();
     }
 
@@ -2053,7 +2265,8 @@
     /**
      * Disables all device cameras according to the specified admin.
      */
-    public void setCameraDisabled(ComponentName who, boolean disabled) {
+    public void setCameraDisabled(ComponentName who, boolean disabled, int userHandle) {
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -2062,9 +2275,9 @@
                     DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA);
             if (ap.disableCamera != disabled) {
                 ap.disableCamera = disabled;
-                saveSettingsLocked();
+                saveSettingsLocked(userHandle);
             }
-            syncDeviceCapabilitiesLocked();
+            syncDeviceCapabilitiesLocked(getUserData(userHandle));
         }
     }
 
@@ -2072,17 +2285,18 @@
      * Gets whether or not all device cameras are disabled for a given admin, or disabled for any
      * active admins.
      */
-    public boolean getCameraDisabled(ComponentName who) {
+    public boolean getCameraDisabled(ComponentName who, int userHandle) {
         synchronized (this) {
             if (who != null) {
-                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+                ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
                 return (admin != null) ? admin.disableCamera : false;
             }
 
+            DevicePolicyData policy = getUserData(userHandle);
             // Determine whether or not the device camera is disabled for any active admins.
-            final int N = mAdminList.size();
+            final int N = policy.mAdminList.size();
             for (int i = 0; i < N; i++) {
-                ActiveAdmin admin = mAdminList.get(i);
+                ActiveAdmin admin = policy.mAdminList.get(i);
                 if (admin.disableCamera) {
                     return true;
                 }
@@ -2091,6 +2305,62 @@
         }
     }
 
+    /**
+     * Selectively disable keyguard features.
+     */
+    public void setKeyguardDisabledFeatures(ComponentName who, int which, int userHandle) {
+        enforceCrossUserPermission(userHandle);
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
+            if (ap.disabledKeyguardFeatures != which) {
+                ap.disabledKeyguardFeatures = which;
+                saveSettingsLocked(userHandle);
+            }
+            syncDeviceCapabilitiesLocked(getUserData(userHandle));
+        }
+    }
+
+    /**
+     * Gets the disabled state for features in keyguard for the given admin,
+     * or the aggregate of all active admins if who is null.
+     */
+    public int getKeyguardDisabledFeatures(ComponentName who, int userHandle) {
+        enforceCrossUserPermission(userHandle);
+        synchronized (this) {
+            if (who != null) {
+                ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
+                return (admin != null) ? admin.disabledKeyguardFeatures : 0;
+            }
+
+            // Determine which keyguard features are disabled for any active admins.
+            DevicePolicyData policy = getUserData(userHandle);
+            final int N = policy.mAdminList.size();
+            int which = 0;
+            for (int i = 0; i < N; i++) {
+                ActiveAdmin admin = policy.mAdminList.get(i);
+                which |= admin.disabledKeyguardFeatures;
+            }
+            return which;
+        }
+    }
+
+    private void enforceCrossUserPermission(int userHandle) {
+        if (userHandle < 0) {
+            throw new IllegalArgumentException("Invalid userId " + userHandle);
+        }
+        final int callingUid = Binder.getCallingUid();
+        if (userHandle == UserHandle.getUserId(callingUid)) return;
+        if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "Must be system or have"
+                    + " INTERACT_ACROSS_USERS_FULL permission");
+        }
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
@@ -2107,19 +2377,23 @@
         synchronized (this) {
             p.println("Current Device Policy Manager state:");
 
-            p.println("  Enabled Device Admins:");
-            final int N = mAdminList.size();
-            for (int i=0; i<N; i++) {
-                ActiveAdmin ap = mAdminList.get(i);
-                if (ap != null) {
-                    pw.print("  "); pw.print(ap.info.getComponent().flattenToShortString());
-                            pw.println(":");
-                    ap.dump("    ", pw);
+            int userCount = mUserData.size();
+            for (int u = 0; u < userCount; u++) {
+                DevicePolicyData policy = getUserData(mUserData.keyAt(u));
+                p.println("  Enabled Device Admins (User " + policy.mUserHandle + "):");
+                final int N = policy.mAdminList.size();
+                for (int i=0; i<N; i++) {
+                    ActiveAdmin ap = policy.mAdminList.get(i);
+                    if (ap != null) {
+                        pw.print("  "); pw.print(ap.info.getComponent().flattenToShortString());
+                                pw.println(":");
+                        ap.dump("    ", pw);
+                    }
                 }
-            }
 
-            pw.println(" ");
-            pw.print("  mPasswordOwner="); pw.println(mPasswordOwner);
+                pw.println(" ");
+                pw.print("  mPasswordOwner="); pw.println(policy.mPasswordOwner);
+            }
         }
     }
 }
diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java
index 0ed5189..94a087a 100644
--- a/services/java/com/android/server/DeviceStorageMonitorService.java
+++ b/services/java/com/android/server/DeviceStorageMonitorService.java
@@ -16,6 +16,9 @@
 
 package com.android.server;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -24,6 +27,7 @@
 import android.content.Intent;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.FileObserver;
@@ -35,9 +39,12 @@
 import android.os.StatFs;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.provider.Settings;
+import android.text.format.Formatter;
 import android.util.EventLog;
 import android.util.Slog;
+import android.util.TimeUtils;
 
 /**
  * This class implements a service to monitor the amount of disk
@@ -71,6 +78,7 @@
     private static final long DEFAULT_CHECK_INTERVAL = MONITOR_INTERVAL*60*1000;
     private static final int DEFAULT_FULL_THRESHOLD_BYTES = 1024*1024; // 1MB
     private long mFreeMem;  // on /data
+    private long mFreeMemAfterLastCacheClear;  // on /data
     private long mLastReportedFreeMem;
     private long mLastReportedFreeMemTime;
     private boolean mLowMemFlag=false;
@@ -95,7 +103,19 @@
     private final CacheFileDeletedObserver mCacheFileDeletedObserver;
     private static final int _TRUE = 1;
     private static final int _FALSE = 0;
+    // This is the raw threshold that has been set at which we consider
+    // storage to be low.
     private long mMemLowThreshold;
+    // This is the threshold at which we start trying to flush caches
+    // to get below the low threshold limit.  It is less than the low
+    // threshold; we will allow storage to get a bit beyond the limit
+    // before flushing and checking if we are actually low.
+    private long mMemCacheStartTrimThreshold;
+    // This is the threshold that we try to get to when deleting cache
+    // files.  This is greater than the low threshold so that we will flush
+    // more files than absolutely needed, to reduce the frequency that
+    // flushing takes place.
+    private long mMemCacheTrimToThreshold;
     private int mMemFullThreshold;
 
     /**
@@ -143,8 +163,8 @@
             mFreeMem = Long.parseLong(debugFreeMem);
         }
         // Read the log interval from secure settings
-        long freeMemLogInterval = Settings.Secure.getLong(mContentResolver,
-                Settings.Secure.SYS_FREE_STORAGE_LOG_INTERVAL,
+        long freeMemLogInterval = Settings.Global.getLong(mContentResolver,
+                Settings.Global.SYS_FREE_STORAGE_LOG_INTERVAL,
                 DEFAULT_FREE_STORAGE_LOG_INTERVAL_IN_MINUTES)*60*1000;
         //log the amount of free memory in event log
         long currTime = SystemClock.elapsedRealtime();
@@ -170,8 +190,8 @@
                                 mFreeMem, mFreeSystem, mFreeCache);
         }
         // Read the reporting threshold from secure settings
-        long threshold = Settings.Secure.getLong(mContentResolver,
-                Settings.Secure.DISK_FREE_CHANGE_REPORTING_THRESHOLD,
+        long threshold = Settings.Global.getLong(mContentResolver,
+                Settings.Global.DISK_FREE_CHANGE_REPORTING_THRESHOLD,
                 DEFAULT_DISK_FREE_CHANGE_REPORTING_THRESHOLD);
         // If mFree changed significantly log the new value
         long delta = mFreeMem - mLastReportedFreeMem;
@@ -190,7 +210,7 @@
         try {
             if (localLOGV) Slog.i(TAG, "Clearing cache");
             IPackageManager.Stub.asInterface(ServiceManager.getService("package")).
-                    freeStorageAndNotify(mMemLowThreshold, mClearCacheObserver);
+                    freeStorageAndNotify(mMemCacheTrimToThreshold, mClearCacheObserver);
         } catch (RemoteException e) {
             Slog.w(TAG, "Failed to get handle for PackageManger Exception: "+e);
             mClearingCache = false;
@@ -216,24 +236,42 @@
 
             //post intent to NotificationManager to display icon if necessary
             if (mFreeMem < mMemLowThreshold) {
-                if (!mLowMemFlag) {
-                    if (checkCache) {
-                        // See if clearing cache helps
-                        // Note that clearing cache is asynchronous and so we do a
-                        // memory check again once the cache has been cleared.
-                        mThreadStartTime = System.currentTimeMillis();
-                        mClearSucceeded = false;
-                        clearCache();
-                    } else {
+                if (checkCache) {
+                    // We are allowed to clear cache files at this point to
+                    // try to get down below the limit, because this is not
+                    // the initial call after a cache clear has been attempted.
+                    // In this case we will try a cache clear if our free
+                    // space has gone below the cache clear limit.
+                    if (mFreeMem < mMemCacheStartTrimThreshold) {
+                        // We only clear the cache if the free storage has changed
+                        // a significant amount since the last time.
+                        if ((mFreeMemAfterLastCacheClear-mFreeMem)
+                                >= ((mMemLowThreshold-mMemCacheStartTrimThreshold)/4)) {
+                            // See if clearing cache helps
+                            // Note that clearing cache is asynchronous and so we do a
+                            // memory check again once the cache has been cleared.
+                            mThreadStartTime = System.currentTimeMillis();
+                            mClearSucceeded = false;
+                            clearCache();
+                        }
+                    }
+                } else {
+                    // This is a call from after clearing the cache.  Note
+                    // the amount of free storage at this point.
+                    mFreeMemAfterLastCacheClear = mFreeMem;
+                    if (!mLowMemFlag) {
+                        // We tried to clear the cache, but that didn't get us
+                        // below the low storage limit.  Tell the user.
                         Slog.i(TAG, "Running low on memory. Sending notification");
                         sendNotification();
                         mLowMemFlag = true;
+                    } else {
+                        if (localLOGV) Slog.v(TAG, "Running low on memory " +
+                                "notification already sent. do nothing");
                     }
-                } else {
-                    if (localLOGV) Slog.v(TAG, "Running low on memory " +
-                            "notification already sent. do nothing");
                 }
             } else {
+                mFreeMemAfterLastCacheClear = mFreeMem;
                 if (mLowMemFlag) {
                     Slog.i(TAG, "Memory available. Cancelling notification");
                     cancelNotification();
@@ -271,15 +309,15 @@
      * any way
      */
     private long getMemThreshold() {
-        long value = Settings.Secure.getInt(
+        long value = Settings.Global.getInt(
                               mContentResolver,
-                              Settings.Secure.SYS_STORAGE_THRESHOLD_PERCENTAGE,
+                              Settings.Global.SYS_STORAGE_THRESHOLD_PERCENTAGE,
                               DEFAULT_THRESHOLD_PERCENTAGE);
         if(localLOGV) Slog.v(TAG, "Threshold Percentage="+value);
-        value *= mTotalMemory;
-        long maxValue = Settings.Secure.getInt(
+        value = (value*mTotalMemory)/100;
+        long maxValue = Settings.Global.getInt(
                 mContentResolver,
-                Settings.Secure.SYS_STORAGE_THRESHOLD_MAX_BYTES,
+                Settings.Global.SYS_STORAGE_THRESHOLD_MAX_BYTES,
                 DEFAULT_THRESHOLD_MAX_BYTES);
         //evaluate threshold value
         return value < maxValue ? value : maxValue;
@@ -291,9 +329,9 @@
      * any way
      */
     private int getMemFullThreshold() {
-        int value = Settings.Secure.getInt(
+        int value = Settings.Global.getInt(
                               mContentResolver,
-                              Settings.Secure.SYS_STORAGE_FULL_THRESHOLD_BYTES,
+                              Settings.Global.SYS_STORAGE_FULL_THRESHOLD_BYTES,
                               DEFAULT_FULL_THRESHOLD_BYTES);
         if(localLOGV) Slog.v(TAG, "Full Threshold Bytes="+value);
         return value;
@@ -312,8 +350,8 @@
         mSystemFileStats = new StatFs(SYSTEM_PATH);
         mCacheFileStats = new StatFs(CACHE_PATH);
         //initialize total storage on device
-        mTotalMemory = ((long)mDataFileStats.getBlockCount() *
-                        mDataFileStats.getBlockSize())/100L;
+        mTotalMemory = (long)mDataFileStats.getBlockCount() *
+                        mDataFileStats.getBlockSize();
         mStorageLowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_LOW);
         mStorageLowIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         mStorageOkIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK);
@@ -325,6 +363,10 @@
         // cache storage thresholds
         mMemLowThreshold = getMemThreshold();
         mMemFullThreshold = getMemFullThreshold();
+        mMemCacheStartTrimThreshold = ((mMemLowThreshold*3)+mMemFullThreshold)/4;
+        mMemCacheTrimToThreshold = mMemLowThreshold
+                + ((mMemLowThreshold-mMemCacheStartTrimThreshold)*2);
+        mFreeMemAfterLastCacheClear = mTotalMemory;
         checkMemory(true);
 
         mCacheFileDeletedObserver = new CacheFileDeletedObserver();
@@ -354,14 +396,16 @@
                 com.android.internal.R.string.low_internal_storage_view_title);
         CharSequence details = mContext.getText(
                 com.android.internal.R.string.low_internal_storage_view_text);
-        PendingIntent intent = PendingIntent.getActivity(mContext, 0,  lowMemIntent, 0);
+        PendingIntent intent = PendingIntent.getActivityAsUser(mContext, 0,  lowMemIntent, 0,
+                null, UserHandle.CURRENT);
         Notification notification = new Notification();
         notification.icon = com.android.internal.R.drawable.stat_notify_disk_full;
         notification.tickerText = title;
         notification.flags |= Notification.FLAG_NO_CLEAR;
         notification.setLatestEventInfo(mContext, title, details, intent);
-        mNotificationMgr.notify(LOW_MEMORY_NOTIFICATION_ID, notification);
-        mContext.sendStickyBroadcast(mStorageLowIntent);
+        mNotificationMgr.notifyAsUser(null, LOW_MEMORY_NOTIFICATION_ID, notification,
+                UserHandle.ALL);
+        mContext.sendStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL);
     }
 
     /**
@@ -373,10 +417,10 @@
                 (NotificationManager)mContext.getSystemService(
                         Context.NOTIFICATION_SERVICE);
         //cancel notification since memory has been freed
-        mNotificationMgr.cancel(LOW_MEMORY_NOTIFICATION_ID);
+        mNotificationMgr.cancelAsUser(null, LOW_MEMORY_NOTIFICATION_ID, UserHandle.ALL);
 
-        mContext.removeStickyBroadcast(mStorageLowIntent);
-        mContext.sendBroadcast(mStorageOkIntent);
+        mContext.removeStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL);
+        mContext.sendBroadcastAsUser(mStorageOkIntent, UserHandle.ALL);
     }
 
     /**
@@ -384,7 +428,7 @@
      */
     private final void sendFullNotification() {
         if(localLOGV) Slog.i(TAG, "Sending memory full notification");
-        mContext.sendStickyBroadcast(mStorageFullIntent);
+        mContext.sendStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL);
     }
 
     /**
@@ -392,8 +436,8 @@
      */
     private final void cancelFullNotification() {
         if(localLOGV) Slog.i(TAG, "Canceling memory full notification");
-        mContext.removeStickyBroadcast(mStorageFullIntent);
-        mContext.sendBroadcast(mStorageNotFullIntent);
+        mContext.removeStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL);
+        mContext.sendBroadcastAsUser(mStorageNotFullIntent, UserHandle.ALL);
     }
 
     public void updateMemory() {
@@ -435,4 +479,40 @@
             EventLogTags.writeCacheFileDeleted(path);
         }
     }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+
+            pw.println("Permission Denial: can't dump " + SERVICE + " from from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid());
+            return;
+        }
+
+        pw.println("Current DeviceStorageMonitor state:");
+        pw.print("  mFreeMem="); pw.print(Formatter.formatFileSize(mContext, mFreeMem));
+                pw.print(" mTotalMemory=");
+                pw.println(Formatter.formatFileSize(mContext, mTotalMemory));
+        pw.print("  mFreeMemAfterLastCacheClear=");
+                pw.println(Formatter.formatFileSize(mContext, mFreeMemAfterLastCacheClear));
+        pw.print("  mLastReportedFreeMem=");
+                pw.print(Formatter.formatFileSize(mContext, mLastReportedFreeMem));
+                pw.print(" mLastReportedFreeMemTime=");
+                TimeUtils.formatDuration(mLastReportedFreeMemTime, SystemClock.elapsedRealtime(), pw);
+                pw.println();
+        pw.print("  mLowMemFlag="); pw.print(mLowMemFlag);
+                pw.print(" mMemFullFlag="); pw.println(mMemFullFlag);
+        pw.print("  mClearSucceeded="); pw.print(mClearSucceeded);
+                pw.print(" mClearingCache="); pw.println(mClearingCache);
+        pw.print("  mMemLowThreshold=");
+                pw.print(Formatter.formatFileSize(mContext, mMemLowThreshold));
+                pw.print(" mMemFullThreshold=");
+                pw.println(Formatter.formatFileSize(mContext, mMemFullThreshold));
+        pw.print("  mMemCacheStartTrimThreshold=");
+                pw.print(Formatter.formatFileSize(mContext, mMemCacheStartTrimThreshold));
+                pw.print(" mMemCacheTrimToThreshold=");
+                pw.println(Formatter.formatFileSize(mContext, mMemCacheTrimToThreshold));
+    }
 }
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 64789d3..4a8bf72 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -16,8 +16,6 @@
 
 package com.android.server;
 
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -27,10 +25,11 @@
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Message;
+import android.os.PowerManager;
 import android.os.SystemClock;
 import android.os.UEventObserver;
+import android.os.UserHandle;
 import android.provider.Settings;
-import android.server.BluetoothService;
 import android.util.Log;
 import android.util.Slog;
 
@@ -40,14 +39,15 @@
 /**
  * <p>DockObserver monitors for a docking station.
  */
-class DockObserver extends UEventObserver {
+final class DockObserver extends UEventObserver {
     private static final String TAG = DockObserver.class.getSimpleName();
-    private static final boolean LOG = false;
 
     private static final String DOCK_UEVENT_MATCH = "DEVPATH=/devices/virtual/switch/dock";
     private static final String DOCK_STATE_PATH = "/sys/class/switch/dock/state";
 
-    private static final int MSG_DOCK_STATE = 0;
+    private static final int MSG_DOCK_STATE_CHANGED = 0;
+
+    private final Object mLock = new Object();
 
     private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
     private int mPreviousDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
@@ -55,14 +55,16 @@
     private boolean mSystemReady;
 
     private final Context mContext;
+    private final PowerManager mPowerManager;
+    private final PowerManager.WakeLock mWakeLock;
 
-    private PowerManagerService mPowerManager;
-
-    public DockObserver(Context context, PowerManagerService pm) {
+    public DockObserver(Context context) {
         mContext = context;
-        mPowerManager = pm;
-        init();  // set initial status
 
+        mPowerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+
+        init();  // set initial status
         startObserving(DOCK_UEVENT_MATCH);
     }
 
@@ -72,24 +74,17 @@
             Slog.v(TAG, "Dock UEVENT: " + event.toString());
         }
 
-        synchronized (this) {
+        synchronized (mLock) {
             try {
                 int newState = Integer.parseInt(event.get("SWITCH_STATE"));
                 if (newState != mDockState) {
                     mPreviousDockState = mDockState;
                     mDockState = newState;
                     if (mSystemReady) {
-                        // Don't force screen on when undocking from the desk dock.
-                        // The change in power state will do this anyway.
-                        // FIXME - we should be configurable.
-                        if ((mPreviousDockState != Intent.EXTRA_DOCK_STATE_DESK
-                                && mPreviousDockState != Intent.EXTRA_DOCK_STATE_LE_DESK
-                                && mPreviousDockState != Intent.EXTRA_DOCK_STATE_HE_DESK) ||
-                                mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
-                            mPowerManager.userActivityWithForce(SystemClock.uptimeMillis(),
-                                    false, true);
-                        }
-                        update();
+                        // Wake up immediately when docked or undocked.
+                        mPowerManager.wakeUp(SystemClock.uptimeMillis());
+
+                        updateLocked();
                     }
                 }
             } catch (NumberFormatException e) {
@@ -98,102 +93,112 @@
         }
     }
 
-    private final void init() {
-        char[] buffer = new char[1024];
-
-        try {
-            FileReader file = new FileReader(DOCK_STATE_PATH);
-            int len = file.read(buffer, 0, 1024);
-            file.close();
-            mPreviousDockState = mDockState = Integer.valueOf((new String(buffer, 0, len)).trim());
-        } catch (FileNotFoundException e) {
-            Slog.w(TAG, "This kernel does not have dock station support");
-        } catch (Exception e) {
-            Slog.e(TAG, "" , e);
+    private void init() {
+        synchronized (mLock) {
+            try {
+                char[] buffer = new char[1024];
+                FileReader file = new FileReader(DOCK_STATE_PATH);
+                try {
+                    int len = file.read(buffer, 0, 1024);
+                    mDockState = Integer.valueOf((new String(buffer, 0, len)).trim());
+                    mPreviousDockState = mDockState;
+                } finally {
+                    file.close();
+                }
+            } catch (FileNotFoundException e) {
+                Slog.w(TAG, "This kernel does not have dock station support");
+            } catch (Exception e) {
+                Slog.e(TAG, "" , e);
+            }
         }
     }
 
     void systemReady() {
-        synchronized (this) {
+        synchronized (mLock) {
             // don't bother broadcasting undocked here
             if (mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
-                update();
+                updateLocked();
             }
             mSystemReady = true;
         }
     }
 
-    private final void update() {
-        mHandler.sendEmptyMessage(MSG_DOCK_STATE);
+    private void updateLocked() {
+        mWakeLock.acquire();
+        mHandler.sendEmptyMessage(MSG_DOCK_STATE_CHANGED);
     }
 
-    private final Handler mHandler = new Handler() {
+    private void handleDockStateChange() {
+        synchronized (mLock) {
+            Slog.i(TAG, "Dock state changed: " + mDockState);
+
+            // Skip the dock intent if not yet provisioned.
+            final ContentResolver cr = mContext.getContentResolver();
+            if (Settings.Global.getInt(cr,
+                    Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
+                Slog.i(TAG, "Device not provisioned, skipping dock broadcast");
+                return;
+            }
+
+            // Pack up the values and broadcast them to everyone
+            Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
+            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+            intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
+
+            // Play a sound to provide feedback to confirm dock connection.
+            // Particularly useful for flaky contact pins...
+            if (Settings.Global.getInt(cr,
+                    Settings.Global.DOCK_SOUNDS_ENABLED, 1) == 1) {
+                String whichSound = null;
+                if (mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
+                    if ((mPreviousDockState == Intent.EXTRA_DOCK_STATE_DESK) ||
+                        (mPreviousDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
+                        (mPreviousDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) {
+                        whichSound = Settings.Global.DESK_UNDOCK_SOUND;
+                    } else if (mPreviousDockState == Intent.EXTRA_DOCK_STATE_CAR) {
+                        whichSound = Settings.Global.CAR_UNDOCK_SOUND;
+                    }
+                } else {
+                    if ((mDockState == Intent.EXTRA_DOCK_STATE_DESK) ||
+                        (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
+                        (mDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) {
+                        whichSound = Settings.Global.DESK_DOCK_SOUND;
+                    } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
+                        whichSound = Settings.Global.CAR_DOCK_SOUND;
+                    }
+                }
+
+                if (whichSound != null) {
+                    final String soundPath = Settings.Global.getString(cr, whichSound);
+                    if (soundPath != null) {
+                        final Uri soundUri = Uri.parse("file://" + soundPath);
+                        if (soundUri != null) {
+                            final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
+                            if (sfx != null) {
+                                sfx.setStreamType(AudioManager.STREAM_SYSTEM);
+                                sfx.play();
+                            }
+                        }
+                    }
+                }
+            }
+
+            // Send the dock event intent.
+            // There are many components in the system watching for this so as to
+            // adjust audio routing, screen orientation, etc.
+            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+
+            // Release the wake lock that was acquired when the message was posted.
+            mWakeLock.release();
+        }
+    }
+
+    private final Handler mHandler = new Handler(true /*async*/) {
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                case MSG_DOCK_STATE:
-                    synchronized (this) {
-                        Slog.i(TAG, "Dock state changed: " + mDockState);
-
-                        final ContentResolver cr = mContext.getContentResolver();
-
-                        if (Settings.Secure.getInt(cr,
-                                Settings.Secure.DEVICE_PROVISIONED, 0) == 0) {
-                            Slog.i(TAG, "Device not provisioned, skipping dock broadcast");
-                            return;
-                        }
-                        // Pack up the values and broadcast them to everyone
-                        Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
-                        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
-                        intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
-
-                        // Check if this is Bluetooth Dock
-                        String address = BluetoothService.readDockBluetoothAddress();
-                        if (address != null)
-                            intent.putExtra(BluetoothDevice.EXTRA_DEVICE,
-                                    BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address));
-
-                        // User feedback to confirm dock connection. Particularly
-                        // useful for flaky contact pins...
-                        if (Settings.System.getInt(cr,
-                                Settings.System.DOCK_SOUNDS_ENABLED, 1) == 1)
-                        {
-                            String whichSound = null;
-                            if (mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
-                                if ((mPreviousDockState == Intent.EXTRA_DOCK_STATE_DESK) ||
-                                    (mPreviousDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
-                                    (mPreviousDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) {
-                                    whichSound = Settings.System.DESK_UNDOCK_SOUND;
-                                } else if (mPreviousDockState == Intent.EXTRA_DOCK_STATE_CAR) {
-                                    whichSound = Settings.System.CAR_UNDOCK_SOUND;
-                                }
-                            } else {
-                                if ((mDockState == Intent.EXTRA_DOCK_STATE_DESK) ||
-                                    (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
-                                    (mDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) {
-                                    whichSound = Settings.System.DESK_DOCK_SOUND;
-                                } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
-                                    whichSound = Settings.System.CAR_DOCK_SOUND;
-                                }
-                            }
-
-                            if (whichSound != null) {
-                                final String soundPath = Settings.System.getString(cr, whichSound);
-                                if (soundPath != null) {
-                                    final Uri soundUri = Uri.parse("file://" + soundPath);
-                                    if (soundUri != null) {
-                                        final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
-                                        if (sfx != null) {
-                                            sfx.setStreamType(AudioManager.STREAM_SYSTEM);
-                                            sfx.play();
-                                        }
-                                    }
-                                }
-                            }
-                        }
-
-                        mContext.sendStickyBroadcast(intent);
-                    }
+                case MSG_DOCK_STATE_CHANGED:
+                    handleDockStateChange();
                     break;
             }
         }
diff --git a/services/java/com/android/server/DropBoxManagerService.java b/services/java/com/android/server/DropBoxManagerService.java
index 932cba1..5008270 100644
--- a/services/java/com/android/server/DropBoxManagerService.java
+++ b/services/java/com/android/server/DropBoxManagerService.java
@@ -31,6 +31,7 @@
 import android.os.Message;
 import android.os.StatFs;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.format.Time;
 import android.util.Slog;
@@ -145,7 +146,7 @@
         context.registerReceiver(mReceiver, filter);
 
         mContentResolver.registerContentObserver(
-            Settings.Secure.CONTENT_URI, true,
+            Settings.Global.CONTENT_URI, true,
             new ContentObserver(new Handler()) {
                 @Override
                 public void onChange(boolean selfChange) {
@@ -157,7 +158,8 @@
             @Override
             public void handleMessage(Message msg) {
                 if (msg.what == MSG_SEND_BROADCAST) {
-                    mContext.sendBroadcast((Intent)msg.obj, android.Manifest.permission.READ_LOGS);
+                    mContext.sendBroadcastAsUser((Intent)msg.obj, UserHandle.OWNER,
+                            android.Manifest.permission.READ_LOGS);
                 }
             }
         };
@@ -263,8 +265,8 @@
     }
 
     public boolean isTagEnabled(String tag) {
-        return !"disabled".equals(Settings.Secure.getString(
-                mContentResolver, Settings.Secure.DROPBOX_TAG_PREFIX + tag));
+        return !"disabled".equals(Settings.Global.getString(
+                mContentResolver, Settings.Global.DROPBOX_TAG_PREFIX + tag));
     }
 
     public synchronized DropBoxManager.Entry getNextEntry(String tag, long millis) {
@@ -686,10 +688,10 @@
     private synchronized long trimToFit() {
         // Expunge aged items (including tombstones marking deleted data).
 
-        int ageSeconds = Settings.Secure.getInt(mContentResolver,
-                Settings.Secure.DROPBOX_AGE_SECONDS, DEFAULT_AGE_SECONDS);
-        int maxFiles = Settings.Secure.getInt(mContentResolver,
-                Settings.Secure.DROPBOX_MAX_FILES, DEFAULT_MAX_FILES);
+        int ageSeconds = Settings.Global.getInt(mContentResolver,
+                Settings.Global.DROPBOX_AGE_SECONDS, DEFAULT_AGE_SECONDS);
+        int maxFiles = Settings.Global.getInt(mContentResolver,
+                Settings.Global.DROPBOX_MAX_FILES, DEFAULT_MAX_FILES);
         long cutoffMillis = System.currentTimeMillis() - ageSeconds * 1000;
         while (!mAllFiles.contents.isEmpty()) {
             EntryFile entry = mAllFiles.contents.first();
@@ -708,12 +710,12 @@
 
         long uptimeMillis = SystemClock.uptimeMillis();
         if (uptimeMillis > mCachedQuotaUptimeMillis + QUOTA_RESCAN_MILLIS) {
-            int quotaPercent = Settings.Secure.getInt(mContentResolver,
-                    Settings.Secure.DROPBOX_QUOTA_PERCENT, DEFAULT_QUOTA_PERCENT);
-            int reservePercent = Settings.Secure.getInt(mContentResolver,
-                    Settings.Secure.DROPBOX_RESERVE_PERCENT, DEFAULT_RESERVE_PERCENT);
-            int quotaKb = Settings.Secure.getInt(mContentResolver,
-                    Settings.Secure.DROPBOX_QUOTA_KB, DEFAULT_QUOTA_KB);
+            int quotaPercent = Settings.Global.getInt(mContentResolver,
+                    Settings.Global.DROPBOX_QUOTA_PERCENT, DEFAULT_QUOTA_PERCENT);
+            int reservePercent = Settings.Global.getInt(mContentResolver,
+                    Settings.Global.DROPBOX_RESERVE_PERCENT, DEFAULT_RESERVE_PERCENT);
+            int quotaKb = Settings.Global.getInt(mContentResolver,
+                    Settings.Global.DROPBOX_QUOTA_KB, DEFAULT_QUOTA_KB);
 
             mStatFs.restat(mDropBoxDir.getPath());
             int available = mStatFs.getAvailableBlocks();
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 41f7335..0fe66fc 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -52,12 +52,12 @@
 # NotificationManagerService.java
 # ---------------------------
 # when a NotificationManager.notify is called
-2750 notification_enqueue (pkg|3),(id|1|5),(tag|3),(notification|3)
+2750 notification_enqueue (pkg|3),(id|1|5),(tag|3),(userid|1|5),(notification|3)
 # when someone tries to cancel a notification, the notification manager sometimes
 # calls this with flags too
-2751 notification_cancel (pkg|3),(id|1|5),(tag|3),(required_flags|1),(forbidden_flags|1)
+2751 notification_cancel (pkg|3),(id|1|5),(tag|3),(userid|1|5),(required_flags|1),(forbidden_flags|1)
 # when someone tries to cancel all of the notifications for a particular package
-2752 notification_cancel_all (pkg|3),(required_flags|1),(forbidden_flags|1)
+2752 notification_cancel_all (pkg|3),(userid|1|5),(required_flags|1),(forbidden_flags|1)
 
 
 # ---------------------------
@@ -114,6 +114,8 @@
 # Package Manager ready:
 3100 boot_progress_pms_ready (time|2|3)
 # + check activity_launch_time for Home app
+# Value of "unknown sources" setting at app install time
+3110 unknown_sources_enabled (value|1)
 
 
 # ---------------------------
@@ -146,3 +148,16 @@
 # ---------------------------
 51100 netstats_mobile_sample (dev_rx_bytes|2|2),(dev_tx_bytes|2|2),(dev_rx_pkts|2|1),(dev_tx_pkts|2|1),(xt_rx_bytes|2|2),(xt_tx_bytes|2|2),(xt_rx_pkts|2|1),(xt_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1),(trusted_time|2|3)
 51101 netstats_wifi_sample (dev_rx_bytes|2|2),(dev_tx_bytes|2|2),(dev_rx_pkts|2|1),(dev_tx_pkts|2|1),(xt_rx_bytes|2|2),(xt_tx_bytes|2|2),(xt_rx_pkts|2|1),(xt_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1),(trusted_time|2|3)
+
+
+# ---------------------------
+# LockdownVpnTracker.java
+# ---------------------------
+51200 lockdown_vpn_connecting (egress_net|1)
+51201 lockdown_vpn_connected (egress_net|1)
+51202 lockdown_vpn_error (egress_net|1)
+
+# ---------------------------
+# ConfigUpdateInstallReceiver.java
+# ---------------------------
+51300 config_install_failed (dir|3)
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index fdb278d..c9ff595 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -16,8 +16,8 @@
 package com.android.server;
 
 import com.android.internal.content.PackageMonitor;
-import com.android.internal.os.AtomicFile;
 import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.SomeArgs;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethod;
@@ -34,7 +34,9 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
 import android.app.AlertDialog;
+import android.app.IUserSwitchObserver;
 import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -49,6 +51,7 @@
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
@@ -63,17 +66,21 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IInterface;
+import android.os.IRemoteCallback;
 import android.os.Message;
+import android.os.Process;
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.provider.Settings.SettingNotFoundException;
 import android.text.TextUtils;
 import android.text.style.SuggestionSpan;
+import android.util.AtomicFile;
 import android.util.EventLog;
 import android.util.LruCache;
 import android.util.Pair;
@@ -164,8 +171,8 @@
     final SettingsObserver mSettingsObserver;
     final IWindowManager mIWindowManager;
     final HandlerCaller mCaller;
-    private final InputMethodFileManager mFileManager;
-    private final InputMethodAndSubtypeListManager mImListManager;
+    private InputMethodFileManager mFileManager;
+    private InputMethodAndSubtypeListManager mImListManager;
     private final HardKeyboardListener mHardKeyboardListener;
     private final WindowManagerService mWindowManagerService;
 
@@ -377,6 +384,8 @@
     private InputMethodInfo[] mIms;
     private int[] mSubtypeIds;
     private Locale mLastSystemLocale;
+    private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
+    private final IPackageManager mIPackageManager;
 
     class SettingsObserver extends ContentObserver {
         SettingsObserver(Handler handler) {
@@ -397,37 +406,55 @@
         }
     }
 
-    class ScreenOnOffReceiver extends android.content.BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
-                mScreenOn = true;
-                refreshImeWindowVisibilityLocked();
-            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
-                mScreenOn = false;
-                setImeWindowVisibilityStatusHiddenLocked();
-            } else if (intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
-                hideInputMethodMenu();
-                return;
-            } else {
-                Slog.w(TAG, "Unexpected intent " + intent);
-            }
-
+    class ImmsBroadcastReceiver extends android.content.BroadcastReceiver {
+        private void updateActive() {
             // Inform the current client of the change in active status
             if (mCurClient != null && mCurClient.client != null) {
                 executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
                         MSG_SET_ACTIVE, mScreenOn ? 1 : 0, mCurClient));
             }
         }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            if (Intent.ACTION_SCREEN_ON.equals(action)) {
+                mScreenOn = true;
+                refreshImeWindowVisibilityLocked();
+                updateActive();
+                return;
+            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
+                mScreenOn = false;
+                setImeWindowVisibilityStatusHiddenLocked();
+                updateActive();
+                return;
+            } else if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
+                hideInputMethodMenu();
+                // No need to updateActive
+                return;
+            } else {
+                Slog.w(TAG, "Unexpected intent " + intent);
+            }
+        }
     }
 
     class MyPackageMonitor extends PackageMonitor {
-        
+        private boolean isChangingPackagesOfCurrentUser() {
+            final int userId = getChangingUserId();
+            final boolean retval = userId == mSettings.getCurrentUserId();
+            if (DEBUG) {
+                Slog.d(TAG, "--- ignore this call back from a background user: " + userId);
+            }
+            return retval;
+        }
+
         @Override
         public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
+            if (!isChangingPackagesOfCurrentUser()) {
+                return false;
+            }
             synchronized (mMethodMap) {
-                String curInputMethodId = Settings.Secure.getString(mContext
-                        .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
+                String curInputMethodId = mSettings.getSelectedInputMethod();
                 final int N = mMethodList.size();
                 if (curInputMethodId != null) {
                     for (int i=0; i<N; i++) {
@@ -452,10 +479,12 @@
 
         @Override
         public void onSomePackagesChanged() {
+            if (!isChangingPackagesOfCurrentUser()) {
+                return;
+            }
             synchronized (mMethodMap) {
                 InputMethodInfo curIm = null;
-                String curInputMethodId = Settings.Secure.getString(mContext
-                        .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
+                String curInputMethodId = mSettings.getSelectedInputMethod();
                 final int N = mMethodList.size();
                 if (curInputMethodId != null) {
                     for (int i=0; i<N; i++) {
@@ -488,9 +517,9 @@
                             || change == PACKAGE_PERMANENT_CHANGE) {
                         ServiceInfo si = null;
                         try {
-                            si = mContext.getPackageManager().getServiceInfo(
-                                    curIm.getComponent(), 0);
-                        } catch (PackageManager.NameNotFoundException ex) {
+                            si = mIPackageManager.getServiceInfo(
+                                    curIm.getComponent(), 0, mSettings.getCurrentUserId());
+                        } catch (RemoteException ex) {
                         }
                         if (si == null) {
                             // Uh oh, current input method is no longer around!
@@ -564,6 +593,7 @@
     }
 
     public InputMethodManagerService(Context context, WindowManagerService windowManager) {
+        mIPackageManager = AppGlobals.getPackageManager();
         mContext = context;
         mRes = context.getResources();
         mHandler = new Handler(this);
@@ -595,28 +625,48 @@
 
         mShowOngoingImeSwitcherForPhones = false;
 
-        synchronized (mMethodMap) {
-            mFileManager = new InputMethodFileManager(mMethodMap);
-        }
-        mImListManager = new InputMethodAndSubtypeListManager(context, this);
-
-        (new MyPackageMonitor()).register(mContext, null, true);
-
-        IntentFilter screenOnOffFilt = new IntentFilter();
-        screenOnOffFilt.addAction(Intent.ACTION_SCREEN_ON);
-        screenOnOffFilt.addAction(Intent.ACTION_SCREEN_OFF);
-        screenOnOffFilt.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
-        mContext.registerReceiver(new ScreenOnOffReceiver(), screenOnOffFilt);
+        final IntentFilter broadcastFilter = new IntentFilter();
+        broadcastFilter.addAction(Intent.ACTION_SCREEN_ON);
+        broadcastFilter.addAction(Intent.ACTION_SCREEN_OFF);
+        broadcastFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+        mContext.registerReceiver(new ImmsBroadcastReceiver(), broadcastFilter);
 
         mNotificationShown = false;
+        int userId = 0;
+        try {
+            ActivityManagerNative.getDefault().registerUserSwitchObserver(
+                    new IUserSwitchObserver.Stub() {
+                        @Override
+                        public void onUserSwitching(int newUserId, IRemoteCallback reply) {
+                            synchronized(mMethodMap) {
+                                switchUserLocked(newUserId);
+                            }
+                            if (reply != null) {
+                                try {
+                                    reply.sendResult(null);
+                                } catch (RemoteException e) {
+                                }
+                            }
+                        }
+
+                        @Override
+                        public void onUserSwitchComplete(int newUserId) throws RemoteException {
+                        }
+                    });
+            userId = ActivityManagerNative.getDefault().getCurrentUser().id;
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
+        }
+        mMyPackageMonitor.register(mContext, null, true);
 
         // mSettings should be created before buildInputMethodListLocked
         mSettings = new InputMethodSettings(
-                mRes, context.getContentResolver(), mMethodMap, mMethodList);
+                mRes, context.getContentResolver(), mMethodMap, mMethodList, userId);
+        mFileManager = new InputMethodFileManager(mMethodMap, userId);
+        mImListManager = new InputMethodAndSubtypeListManager(context, this);
 
         // Just checking if defaultImiId is empty or not
-        final String defaultImiId = Settings.Secure.getString(
-                mContext.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
+        final String defaultImiId = mSettings.getSelectedInputMethod();
         mImeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
 
         buildInputMethodListLocked(mMethodList, mMethodMap);
@@ -645,24 +695,6 @@
                 }, filter);
     }
 
-    private void checkCurrentLocaleChangedLocked() {
-        if (!mSystemReady) {
-            // not system ready
-            return;
-        }
-        final Locale newLocale = mRes.getConfiguration().locale;
-        if (newLocale != null && !newLocale.equals(mLastSystemLocale)) {
-            if (DEBUG) {
-                Slog.i(TAG, "Locale has been changed to " + newLocale);
-            }
-            buildInputMethodListLocked(mMethodList, mMethodMap);
-            // Reset the current ime to the proper one
-            resetDefaultImeLocked(mContext);
-            updateFromSettingsLocked();
-            mLastSystemLocale = newLocale;
-        }
-    }
-
     private void resetDefaultImeLocked(Context context) {
         // Do not reset the default (current) IME when it is a 3rd-party IME
         if (mCurMethodId != null && !isSystemIme(mMethodMap.get(mCurMethodId))) {
@@ -687,6 +719,59 @@
         }
     }
 
+    private void resetAllInternalStateLocked(boolean updateOnlyWhenLocaleChanged) {
+        if (!mSystemReady) {
+            // not system ready
+            return;
+        }
+        final Locale newLocale = mRes.getConfiguration().locale;
+        if (!updateOnlyWhenLocaleChanged
+                || (newLocale != null && !newLocale.equals(mLastSystemLocale))) {
+            if (!updateOnlyWhenLocaleChanged) {
+                hideCurrentInputLocked(0, null);
+                mCurMethodId = null;
+                unbindCurrentMethodLocked(true, false);
+            }
+            if (DEBUG) {
+                Slog.i(TAG, "Locale has been changed to " + newLocale);
+            }
+            // InputMethodAndSubtypeListManager should be reset when the locale is changed.
+            mImListManager = new InputMethodAndSubtypeListManager(mContext, this);
+            buildInputMethodListLocked(mMethodList, mMethodMap);
+            if (!updateOnlyWhenLocaleChanged) {
+                final String selectedImiId = mSettings.getSelectedInputMethod();
+                if (TextUtils.isEmpty(selectedImiId)) {
+                    // This is the first time of the user switch and
+                    // set the current ime to the proper one.
+                    resetDefaultImeLocked(mContext);
+                }
+            } else {
+                // If the locale is changed, needs to reset the default ime
+                resetDefaultImeLocked(mContext);
+            }
+            updateFromSettingsLocked();
+            mLastSystemLocale = newLocale;
+            if (!updateOnlyWhenLocaleChanged) {
+                try {
+                    startInputInnerLocked();
+                } catch (RuntimeException e) {
+                    Slog.w(TAG, "Unexpected exception", e);
+                }
+            }
+        }
+    }
+
+    private void checkCurrentLocaleChangedLocked() {
+        resetAllInternalStateLocked(true);
+    }
+
+    private void switchUserLocked(int newUserId) {
+        mSettings.setCurrentUserId(newUserId);
+        // InputMethodFileManager should be reset when the user is changed
+        mFileManager = new InputMethodFileManager(mMethodMap, newUserId);
+        resetAllInternalStateLocked(false);
+    }
+
     private boolean isValidSystemDefaultIme(InputMethodInfo imi, Context context) {
         if (!mSystemReady) {
             return false;
@@ -747,10 +832,13 @@
 
     public void systemReady(StatusBarManagerService statusBar) {
         synchronized (mMethodMap) {
+            if (DEBUG) {
+                Slog.d(TAG, "--- systemReady");
+            }
             if (!mSystemReady) {
                 mSystemReady = true;
-                mKeyguardManager = (KeyguardManager)
-                        mContext.getSystemService(Context.KEYGUARD_SERVICE);
+                mKeyguardManager =
+                        (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
                 mNotificationManager = (NotificationManager)
                         mContext.getSystemService(Context.NOTIFICATION_SERVICE);
                 mStatusBar = statusBar;
@@ -801,8 +889,56 @@
         setImeWindowStatus(mCurToken, mImeWindowVis, mBackDisposition);
     }
 
+    // ---------------------------------------------------------------------------------------
+    // Check whether or not this is a valid IPC. Assumes an IPC is valid when either
+    // 1) it comes from the system process
+    // 2) the calling process' user id is identical to the current user id IMMS thinks.
+    private boolean calledFromValidUser() {
+        final int uid = Binder.getCallingUid();
+        final int userId = UserHandle.getUserId(uid);
+        if (DEBUG) {
+            Slog.d(TAG, "--- calledFromForegroundUserOrSystemProcess ? "
+                    + "calling uid = " + uid + " system uid = " + Process.SYSTEM_UID
+                    + " calling userId = " + userId + ", foreground user id = "
+                    + mSettings.getCurrentUserId() + ", calling pid = " + Binder.getCallingPid());
+        }
+        if (uid == Process.SYSTEM_UID || userId == mSettings.getCurrentUserId()) {
+            return true;
+        }
+
+        // Caveat: A process which has INTERACT_ACROSS_USERS_FULL gets results for the
+        // foreground user, not for the user of that process. Accordingly InputMethodManagerService
+        // must not manage background users' states in any functions.
+        // Note that privacy-sensitive IPCs, such as setInputMethod, are still securely guarded
+        // by a token.
+        if (mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+                        == PackageManager.PERMISSION_GRANTED) {
+            if (DEBUG) {
+                Slog.d(TAG, "--- Access granted because the calling process has "
+                        + "the INTERACT_ACROSS_USERS_FULL permission");
+            }
+            return true;
+        }
+        Slog.w(TAG, "--- IPC called from background users. Ignore. \n" + getStackTrace());
+        return false;
+    }
+
+    private boolean bindCurrentInputMethodService(
+            Intent service, ServiceConnection conn, int flags) {
+        if (service == null || conn == null) {
+            Slog.e(TAG, "--- bind failed: service = " + service + ", conn = " + conn);
+            return false;
+        }
+        return mContext.bindService(service, conn, flags, mSettings.getCurrentUserId());
+    }
+
     @Override
     public List<InputMethodInfo> getInputMethodList() {
+        // TODO: Make this work even for non-current users?
+        if (!calledFromValidUser()) {
+            return Collections.emptyList();
+        }
         synchronized (mMethodMap) {
             return new ArrayList<InputMethodInfo>(mMethodList);
         }
@@ -810,6 +946,10 @@
 
     @Override
     public List<InputMethodInfo> getEnabledInputMethodList() {
+        // TODO: Make this work even for non-current users?
+        if (!calledFromValidUser()) {
+            return Collections.emptyList();
+        }
         synchronized (mMethodMap) {
             return mSettings.getEnabledInputMethodListLocked();
         }
@@ -819,7 +959,7 @@
             getExplicitlyOrImplicitlyEnabledInputMethodsAndSubtypeListLocked() {
         HashMap<InputMethodInfo, List<InputMethodSubtype>> enabledInputMethodAndSubtypes =
                 new HashMap<InputMethodInfo, List<InputMethodSubtype>>();
-        for (InputMethodInfo imi: getEnabledInputMethodList()) {
+        for (InputMethodInfo imi: mSettings.getEnabledInputMethodListLocked()) {
             enabledInputMethodAndSubtypes.put(
                     imi, getEnabledInputMethodSubtypeListLocked(imi, true));
         }
@@ -842,6 +982,10 @@
     @Override
     public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi,
             boolean allowsImplicitlySelectedSubtypes) {
+        // TODO: Make this work even for non-current users?
+        if (!calledFromValidUser()) {
+            return Collections.emptyList();
+        }
         synchronized (mMethodMap) {
             return getEnabledInputMethodSubtypeListLocked(imi, allowsImplicitlySelectedSubtypes);
         }
@@ -850,6 +994,9 @@
     @Override
     public void addClient(IInputMethodClient client,
             IInputContext inputContext, int uid, int pid) {
+        if (!calledFromValidUser()) {
+            return;
+        }
         synchronized (mMethodMap) {
             mClients.put(client.asBinder(), new ClientState(client,
                     inputContext, uid, pid));
@@ -858,6 +1005,9 @@
 
     @Override
     public void removeClient(IInputMethodClient client) {
+        if (!calledFromValidUser()) {
+            return;
+        }
         synchronized (mMethodMap) {
             mClients.remove(client.asBinder());
         }
@@ -1051,7 +1201,7 @@
             throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
         }
 
-        unbindCurrentMethodLocked(false);
+        unbindCurrentMethodLocked(false, true);
 
         mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
         mCurIntent.setComponent(info.getComponent());
@@ -1059,7 +1209,7 @@
                 com.android.internal.R.string.input_method_binding_label);
         mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
                 mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
-        if (mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE
+        if (bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
                 | Context.BIND_NOT_VISIBLE)) {
             mLastBindTime = SystemClock.uptimeMillis();
             mHaveConnection = true;
@@ -1083,6 +1233,9 @@
     @Override
     public InputBindResult startInput(IInputMethodClient client,
             IInputContext inputContext, EditorInfo attribute, int controlFlags) {
+        if (!calledFromValidUser()) {
+            return null;
+        }
         synchronized (mMethodMap) {
             final long ident = Binder.clearCallingIdentity();
             try {
@@ -1104,7 +1257,7 @@
                 mCurMethod = IInputMethod.Stub.asInterface(service);
                 if (mCurToken == null) {
                     Slog.w(TAG, "Service connected without a token!");
-                    unbindCurrentMethodLocked(false);
+                    unbindCurrentMethodLocked(false, false);
                     return;
                 }
                 if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
@@ -1139,7 +1292,7 @@
         }
     }
 
-    void unbindCurrentMethodLocked(boolean reportToClient) {
+    void unbindCurrentMethodLocked(boolean reportToClient, boolean savePosition) {
         if (mVisibleBound) {
             mContext.unbindService(mVisibleConnection);
             mVisibleBound = false;
@@ -1153,7 +1306,7 @@
         if (mCurToken != null) {
             try {
                 if (DEBUG) Slog.v(TAG, "Removing window token: " + mCurToken);
-                if ((mImeWindowVis & InputMethodService.IME_ACTIVE) != 0) {
+                if ((mImeWindowVis & InputMethodService.IME_ACTIVE) != 0 && savePosition) {
                     // The current IME is shown. Hence an IME switch (transition) is happening.
                     mWindowManagerService.saveLastInputMethodWindowForTransition();
                 }
@@ -1241,10 +1394,12 @@
                     if (DEBUG) Slog.d(TAG, "show a small icon for the input method");
                     CharSequence contentDescription = null;
                     try {
-                        PackageManager packageManager = mContext.getPackageManager();
+                        // Use PackageManager to load label
+                        final PackageManager packageManager = mContext.getPackageManager();
                         contentDescription = packageManager.getApplicationLabel(
-                                packageManager.getApplicationInfo(packageName, 0));
-                    } catch (NameNotFoundException nnfe) {
+                                mIPackageManager.getApplicationInfo(packageName, 0,
+                                        mSettings.getCurrentUserId()));
+                    } catch (RemoteException e) {
                         /* ignore */
                     }
                     if (mStatusBar != null) {
@@ -1308,13 +1463,14 @@
         }
     }
 
+    // Caution! This method is called in this class. Handle multi-user carefully
     @SuppressWarnings("deprecation")
     @Override
     public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
-        int uid = Binder.getCallingUid();
-        long ident = Binder.clearCallingIdentity();
+        final long ident = Binder.clearCallingIdentity();
         try {
             if (token == null || mCurToken != token) {
+                int uid = Binder.getCallingUid();
                 Slog.w(TAG, "Ignoring setImeWindowStatus of uid " + uid + " token: " + token);
                 return;
             }
@@ -1328,6 +1484,7 @@
                 final boolean iconVisibility = (vis & InputMethodService.IME_ACTIVE) != 0;
                 final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
                 if (imi != null && iconVisibility && needsToShowImeSwitchOngoingNotification()) {
+                    // Used to load label
                     final PackageManager pm = mContext.getPackageManager();
                     final CharSequence title = mRes.getText(
                             com.android.internal.R.string.select_input_method);
@@ -1342,15 +1499,22 @@
                     mImeSwitcherNotification.setLatestEventInfo(
                             mContext, title, summary, mImeSwitchPendingIntent);
                     if (mNotificationManager != null) {
-                        mNotificationManager.notify(
+                        if (DEBUG) {
+                            Slog.d(TAG, "--- show notification: label =  " + imiLabel
+                                    + ", summary = " + summary);
+                        }
+                        mNotificationManager.notifyAsUser(null,
                                 com.android.internal.R.string.select_input_method,
-                                mImeSwitcherNotification);
+                                mImeSwitcherNotification, UserHandle.ALL);
                         mNotificationShown = true;
                     }
                 } else {
                     if (mNotificationShown && mNotificationManager != null) {
-                        mNotificationManager.cancel(
-                                com.android.internal.R.string.select_input_method);
+                        if (DEBUG) {
+                            Slog.d(TAG, "--- hide notification");
+                        }
+                        mNotificationManager.cancelAsUser(null,
+                                com.android.internal.R.string.select_input_method, UserHandle.ALL);
                         mNotificationShown = false;
                     }
                 }
@@ -1362,6 +1526,9 @@
 
     @Override
     public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
+        if (!calledFromValidUser()) {
+            return;
+        }
         synchronized (mMethodMap) {
             final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
             for (int i = 0; i < spans.length; ++i) {
@@ -1376,6 +1543,9 @@
 
     @Override
     public boolean notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
+        if (!calledFromValidUser()) {
+            return false;
+        }
         synchronized (mMethodMap) {
             final InputMethodInfo targetImi = mSecureSuggestionSpans.get(span);
             // TODO: Do not send the intent if the process of the targetImi is already dead.
@@ -1391,7 +1561,12 @@
                 intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_BEFORE, originalString);
                 intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_AFTER, suggestions[index]);
                 intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_HASHCODE, span.hashCode());
-                mContext.sendBroadcast(intent);
+                final long ident = Binder.clearCallingIdentity();
+                try {
+                    mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
                 return true;
             }
         }
@@ -1403,12 +1578,10 @@
         // ENABLED_INPUT_METHODS is taking care of keeping them correctly in
         // sync, so we will never have a DEFAULT_INPUT_METHOD that is not
         // enabled.
-        String id = Settings.Secure.getString(mContext.getContentResolver(),
-                Settings.Secure.DEFAULT_INPUT_METHOD);
+        String id = mSettings.getSelectedInputMethod();
         // There is no input method selected, try to choose new applicable input method.
         if (TextUtils.isEmpty(id) && chooseNewDefaultIMELocked()) {
-            id = Settings.Secure.getString(mContext.getContentResolver(),
-                    Settings.Secure.DEFAULT_INPUT_METHOD);
+            id = mSettings.getSelectedInputMethod();
         }
         if (!TextUtils.isEmpty(id)) {
             try {
@@ -1416,13 +1589,13 @@
             } catch (IllegalArgumentException e) {
                 Slog.w(TAG, "Unknown input method from prefs: " + id, e);
                 mCurMethodId = null;
-                unbindCurrentMethodLocked(true);
+                unbindCurrentMethodLocked(true, false);
             }
             mShortcutInputMethodsAndSubtypes.clear();
         } else {
             // There is no longer an input method set, so stop any current one.
             mCurMethodId = null;
-            unbindCurrentMethodLocked(true);
+            unbindCurrentMethodLocked(true, false);
         }
     }
 
@@ -1445,7 +1618,7 @@
             } else {
                 // If subtype is null, try to find the most applicable one from
                 // getCurrentInputMethodSubtype.
-                newSubtype = getCurrentInputMethodSubtype();
+                newSubtype = getCurrentInputMethodSubtypeLocked();
             }
             if (newSubtype == null || oldSubtype == null) {
                 Slog.w(TAG, "Illegal subtype state: old subtype = " + oldSubtype
@@ -1481,7 +1654,7 @@
                 Intent intent = new Intent(Intent.ACTION_INPUT_METHOD_CHANGED);
                 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
                 intent.putExtra("input_method_id", id);
-                mContext.sendBroadcast(intent);
+                mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
             }
             unbindCurrentClientLocked();
         } finally {
@@ -1492,6 +1665,9 @@
     @Override
     public boolean showSoftInput(IInputMethodClient client, int flags,
             ResultReceiver resultReceiver) {
+        if (!calledFromValidUser()) {
+            return false;
+        }
         int uid = Binder.getCallingUid();
         long ident = Binder.clearCallingIdentity();
         try {
@@ -1540,7 +1716,8 @@
                     resultReceiver));
             mInputShown = true;
             if (mHaveConnection && !mVisibleBound) {
-                mContext.bindService(mCurIntent, mVisibleConnection, Context.BIND_AUTO_CREATE);
+                bindCurrentInputMethodService(
+                        mCurIntent, mVisibleConnection, Context.BIND_AUTO_CREATE);
                 mVisibleBound = true;
             }
             res = true;
@@ -1554,8 +1731,13 @@
                     SystemClock.uptimeMillis()-mLastBindTime,1);
             Slog.w(TAG, "Force disconnect/connect to the IME in showCurrentInputLocked()");
             mContext.unbindService(this);
-            mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE
+            bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
                     | Context.BIND_NOT_VISIBLE);
+        } else {
+            if (DEBUG) {
+                Slog.d(TAG, "Can't show input: connection = " + mHaveConnection + ", time = "
+                        + ((mLastBindTime+TIME_TO_RECONNECT) - SystemClock.uptimeMillis()));
+            }
         }
 
         return res;
@@ -1564,6 +1746,9 @@
     @Override
     public boolean hideSoftInput(IInputMethodClient client, int flags,
             ResultReceiver resultReceiver) {
+        if (!calledFromValidUser()) {
+            return false;
+        }
         int uid = Binder.getCallingUid();
         long ident = Binder.clearCallingIdentity();
         try {
@@ -1629,6 +1814,9 @@
     public InputBindResult windowGainedFocus(IInputMethodClient client, IBinder windowToken,
             int controlFlags, int softInputMode, int windowFlags,
             EditorInfo attribute, IInputContext inputContext) {
+        if (!calledFromValidUser()) {
+            return null;
+        }
         InputBindResult res = null;
         long ident = Binder.clearCallingIdentity();
         try {
@@ -1660,7 +1848,7 @@
 
                 if (mCurFocusedWindow == windowToken) {
                     Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client
-                            + " attribute=" + attribute);
+                            + " attribute=" + attribute + ", token = " + windowToken);
                     if (attribute != null) {
                         return startInputUncheckedLocked(cs, inputContext, attribute,
                                 controlFlags);
@@ -1769,6 +1957,9 @@
 
     @Override
     public void showInputMethodPickerFromClient(IInputMethodClient client) {
+        if (!calledFromValidUser()) {
+            return;
+        }
         synchronized (mMethodMap) {
             if (mCurClient == null || client == null
                     || mCurClient.client.asBinder() != client.asBinder()) {
@@ -1784,11 +1975,17 @@
 
     @Override
     public void setInputMethod(IBinder token, String id) {
+        if (!calledFromValidUser()) {
+            return;
+        }
         setInputMethodWithSubtypeId(token, id, NOT_A_SUBTYPE_ID);
     }
 
     @Override
     public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
+        if (!calledFromValidUser()) {
+            return;
+        }
         synchronized (mMethodMap) {
             if (subtype != null) {
                 setInputMethodWithSubtypeId(token, id, getSubtypeIdFromHashCode(
@@ -1802,6 +1999,9 @@
     @Override
     public void showInputMethodAndSubtypeEnablerFromClient(
             IInputMethodClient client, String inputMethodId) {
+        if (!calledFromValidUser()) {
+            return;
+        }
         synchronized (mMethodMap) {
             if (mCurClient == null || client == null
                 || mCurClient.client.asBinder() != client.asBinder()) {
@@ -1814,6 +2014,9 @@
 
     @Override
     public boolean switchToLastInputMethod(IBinder token) {
+        if (!calledFromValidUser()) {
+            return false;
+        }
         synchronized (mMethodMap) {
             final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
             final InputMethodInfo lastImi;
@@ -1881,6 +2084,9 @@
 
     @Override
     public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) {
+        if (!calledFromValidUser()) {
+            return false;
+        }
         synchronized (mMethodMap) {
             final ImeSubtypeListItem nextSubtype = mImListManager.getNextInputMethod(
                     onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype);
@@ -1894,6 +2100,9 @@
 
     @Override
     public InputMethodSubtype getLastInputMethodSubtype() {
+        if (!calledFromValidUser()) {
+            return null;
+        }
         synchronized (mMethodMap) {
             final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
             // TODO: Handle the case of the last IME with no subtypes
@@ -1916,14 +2125,22 @@
 
     @Override
     public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
+        if (!calledFromValidUser()) {
+            return;
+        }
         // By this IPC call, only a process which shares the same uid with the IME can add
         // additional input method subtypes to the IME.
         if (TextUtils.isEmpty(imiId) || subtypes == null || subtypes.length == 0) return;
         synchronized (mMethodMap) {
             final InputMethodInfo imi = mMethodMap.get(imiId);
             if (imi == null) return;
-            final PackageManager pm = mContext.getPackageManager();
-            final String[] packageInfos = pm.getPackagesForUid(Binder.getCallingUid());
+            final String[] packageInfos;
+            try {
+                packageInfos = mIPackageManager.getPackagesForUid(Binder.getCallingUid());
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to get package infos");
+                return;
+            }
             if (packageInfos != null) {
                 final int packageNum = packageInfos.length;
                 for (int i = 0; i < packageNum; ++i) {
@@ -1970,6 +2187,9 @@
 
     @Override
     public void hideMySoftInput(IBinder token, int flags) {
+        if (!calledFromValidUser()) {
+            return;
+        }
         synchronized (mMethodMap) {
             if (token == null || mCurToken != token) {
                 if (DEBUG) Slog.w(TAG, "Ignoring hideInputMethod of uid "
@@ -1987,6 +2207,9 @@
 
     @Override
     public void showMySoftInput(IBinder token, int flags) {
+        if (!calledFromValidUser()) {
+            return;
+        }
         synchronized (mMethodMap) {
             if (token == null || mCurToken != token) {
                 Slog.w(TAG, "Ignoring showMySoftInput of uid "
@@ -2024,7 +2247,7 @@
 
     @Override
     public boolean handleMessage(Message msg) {
-        HandlerCaller.SomeArgs args;
+        SomeArgs args;
         switch (msg.what) {
             case MSG_SHOW_IM_PICKER:
                 showInputMethodMenu();
@@ -2035,8 +2258,9 @@
                 return true;
 
             case MSG_SHOW_IM_SUBTYPE_ENABLER:
-                args = (HandlerCaller.SomeArgs)msg.obj;
+                args = (SomeArgs)msg.obj;
                 showInputMethodAndSubtypeEnabler((String)args.arg1);
+                args.recycle();
                 return true;
 
             case MSG_SHOW_IM_CONFIG:
@@ -2053,48 +2277,53 @@
                 }
                 return true;
             case MSG_BIND_INPUT:
-                args = (HandlerCaller.SomeArgs)msg.obj;
+                args = (SomeArgs)msg.obj;
                 try {
                     ((IInputMethod)args.arg1).bindInput((InputBinding)args.arg2);
                 } catch (RemoteException e) {
                 }
+                args.recycle();
                 return true;
             case MSG_SHOW_SOFT_INPUT:
-                args = (HandlerCaller.SomeArgs)msg.obj;
+                args = (SomeArgs)msg.obj;
                 try {
                     ((IInputMethod)args.arg1).showSoftInput(msg.arg1,
                             (ResultReceiver)args.arg2);
                 } catch (RemoteException e) {
                 }
+                args.recycle();
                 return true;
             case MSG_HIDE_SOFT_INPUT:
-                args = (HandlerCaller.SomeArgs)msg.obj;
+                args = (SomeArgs)msg.obj;
                 try {
                     ((IInputMethod)args.arg1).hideSoftInput(0,
                             (ResultReceiver)args.arg2);
                 } catch (RemoteException e) {
                 }
+                args.recycle();
                 return true;
             case MSG_ATTACH_TOKEN:
-                args = (HandlerCaller.SomeArgs)msg.obj;
+                args = (SomeArgs)msg.obj;
                 try {
                     if (DEBUG) Slog.v(TAG, "Sending attach of token: " + args.arg2);
                     ((IInputMethod)args.arg1).attachToken((IBinder)args.arg2);
                 } catch (RemoteException e) {
                 }
+                args.recycle();
                 return true;
             case MSG_CREATE_SESSION:
-                args = (HandlerCaller.SomeArgs)msg.obj;
+                args = (SomeArgs)msg.obj;
                 try {
                     ((IInputMethod)args.arg1).createSession(
                             (IInputMethodCallback)args.arg2);
                 } catch (RemoteException e) {
                 }
+                args.recycle();
                 return true;
             // ---------------------------------------------------------
 
             case MSG_START_INPUT:
-                args = (HandlerCaller.SomeArgs)msg.obj;
+                args = (SomeArgs)msg.obj;
                 try {
                     SessionState session = (SessionState)args.arg1;
                     setEnabledSessionInMainThread(session);
@@ -2102,9 +2331,10 @@
                             (EditorInfo)args.arg3);
                 } catch (RemoteException e) {
                 }
+                args.recycle();
                 return true;
             case MSG_RESTART_INPUT:
-                args = (HandlerCaller.SomeArgs)msg.obj;
+                args = (SomeArgs)msg.obj;
                 try {
                     SessionState session = (SessionState)args.arg1;
                     setEnabledSessionInMainThread(session);
@@ -2112,6 +2342,7 @@
                             (EditorInfo)args.arg3);
                 } catch (RemoteException e) {
                 }
+                args.recycle();
                 return true;
 
             // ---------------------------------------------------------
@@ -2124,13 +2355,14 @@
                 }
                 return true;
             case MSG_BIND_METHOD:
-                args = (HandlerCaller.SomeArgs)msg.obj;
+                args = (SomeArgs)msg.obj;
                 try {
                     ((IInputMethodClient)args.arg1).onBindMethod(
                             (InputBindResult)args.arg2);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Client died receiving input method " + args.arg2);
                 }
+                args.recycle();
                 return true;
             case MSG_SET_ACTIVE:
                 try {
@@ -2214,19 +2446,22 @@
 
     void buildInputMethodListLocked(ArrayList<InputMethodInfo> list,
             HashMap<String, InputMethodInfo> map) {
+        if (DEBUG) {
+            Slog.d(TAG, "--- re-buildInputMethodList " + ", \n ------ \n" + getStackTrace());
+        }
         list.clear();
         map.clear();
 
-        PackageManager pm = mContext.getPackageManager();
+        // Use for queryIntentServicesAsUser
+        final PackageManager pm = mContext.getPackageManager();
         final Configuration config = mRes.getConfiguration();
         final boolean haveHardKeyboard = config.keyboard == Configuration.KEYBOARD_QWERTY;
-        String disabledSysImes = Settings.Secure.getString(mContext.getContentResolver(),
-                Secure.DISABLED_SYSTEM_INPUT_METHODS);
+        String disabledSysImes = mSettings.getDisabledSystemInputMethods();
         if (disabledSysImes == null) disabledSysImes = "";
 
-        List<ResolveInfo> services = pm.queryIntentServices(
+        final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
                 new Intent(InputMethod.SERVICE_INTERFACE),
-                PackageManager.GET_META_DATA);
+                PackageManager.GET_META_DATA, mSettings.getCurrentUserId());
 
         final HashMap<String, List<InputMethodSubtype>> additionalSubtypes =
                 mFileManager.getAllAdditionalInputMethodSubtypes();
@@ -2269,8 +2504,7 @@
             }
         }
 
-        final String defaultImiId = Settings.Secure.getString(mContext
-                .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
+        final String defaultImiId = mSettings.getSelectedInputMethod();
         if (!TextUtils.isEmpty(defaultImiId)) {
             if (!map.containsKey(defaultImiId)) {
                 Slog.w(TAG, "Default IME is uninstalled. Choose new default IME.");
@@ -2302,7 +2536,7 @@
         if (!TextUtils.isEmpty(inputMethodId)) {
             intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, inputMethodId);
         }
-        mContext.startActivity(intent);
+        mContext.startActivityAsUser(intent, null, UserHandle.CURRENT);
     }
 
     private void showConfigureInputMethods() {
@@ -2310,7 +2544,7 @@
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-        mContext.startActivity(intent);
+        mContext.startActivityAsUser(intent, null, UserHandle.CURRENT);
     }
 
     private boolean isScreenLocked() {
@@ -2321,11 +2555,9 @@
         if (DEBUG) Slog.v(TAG, "Show switching menu");
 
         final Context context = mContext;
-        final PackageManager pm = context.getPackageManager();
         final boolean isScreenLocked = isScreenLocked();
 
-        final String lastInputMethodId = Settings.Secure.getString(context
-                .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
+        final String lastInputMethodId = mSettings.getSelectedInputMethod();
         int lastInputMethodSubtypeId = getSelectedInputMethodSubtypeId(lastInputMethodId);
         if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId);
 
@@ -2343,7 +2575,7 @@
                             showSubtypes, mInputShown, isScreenLocked);
 
             if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) {
-                final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtype();
+                final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtypeLocked();
                 if (currentSubtype != null) {
                     final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
                     lastInputMethodSubtypeId =
@@ -2446,6 +2678,8 @@
             mSwitchingDialog.setCanceledOnTouchOutside(true);
             mSwitchingDialog.getWindow().setType(
                     WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
+            mSwitchingDialog.getWindow().getAttributes().privateFlags |=
+                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
             mSwitchingDialog.getWindow().getAttributes().setTitle("Select input method");
             mSwitchingDialog.show();
         }
@@ -2572,6 +2806,10 @@
 
     @Override
     public boolean setInputMethodEnabled(String id, boolean enabled) {
+        // TODO: Make this work even for non-current users?
+        if (!calledFromValidUser()) {
+            return false;
+        }
         synchronized (mMethodMap) {
             if (mContext.checkCallingOrSelfPermission(
                     android.Manifest.permission.WRITE_SECURE_SETTINGS)
@@ -2616,8 +2854,7 @@
             if (mSettings.buildAndPutEnabledInputMethodsStrRemovingIdLocked(
                     builder, enabledInputMethodsList, id)) {
                 // Disabled input method is currently selected, switch to another one.
-                String selId = Settings.Secure.getString(mContext.getContentResolver(),
-                        Settings.Secure.DEFAULT_INPUT_METHOD);
+                final String selId = mSettings.getSelectedInputMethod();
                 if (id.equals(selId) && !chooseNewDefaultIMELocked()) {
                     Slog.i(TAG, "Can't find new IME, unsetting the current input method.");
                     resetSelectedInputMethodAndSubtypeLocked("");
@@ -2664,7 +2901,7 @@
             } else {
                 mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
                 // If the subtype is not specified, choose the most applicable one
-                mCurrentSubtype = getCurrentInputMethodSubtype();
+                mCurrentSubtype = getCurrentInputMethodSubtypeLocked();
             }
         }
 
@@ -2706,14 +2943,8 @@
         if (imi == null) {
             return NOT_A_SUBTYPE_ID;
         }
-        int subtypeId;
-        try {
-            subtypeId = Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE);
-        } catch (SettingNotFoundException e) {
-            return NOT_A_SUBTYPE_ID;
-        }
-        return getSubtypeIdFromHashCode(imi, subtypeId);
+        final int subtypeHashCode = mSettings.getSelectedInputMethodSubtypeHashCode();
+        return getSubtypeIdFromHashCode(imi, subtypeHashCode);
     }
 
     private static boolean isValidSubtypeId(InputMethodInfo imi, int subtypeHashCode) {
@@ -2876,7 +3107,7 @@
             }
             InputMethodSubtype subtype = null;
             final List<InputMethodSubtype> enabledSubtypes =
-                    getEnabledInputMethodSubtypeList(imi, true);
+                    getEnabledInputMethodSubtypeListLocked(imi, true);
             // 1. Search by the current subtype's locale from enabledSubtypes.
             if (mCurrentSubtype != null) {
                 subtype = findLastResortApplicableSubtypeLocked(
@@ -2945,49 +3176,53 @@
      */
     @Override
     public InputMethodSubtype getCurrentInputMethodSubtype() {
+        // TODO: Make this work even for non-current users?
+        if (!calledFromValidUser()) {
+            return null;
+        }
+        synchronized (mMethodMap) {
+            return getCurrentInputMethodSubtypeLocked();
+        }
+    }
+
+    private InputMethodSubtype getCurrentInputMethodSubtypeLocked() {
         if (mCurMethodId == null) {
             return null;
         }
-        boolean subtypeIsSelected = false;
-        try {
-            subtypeIsSelected = Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE) != NOT_A_SUBTYPE_ID;
-        } catch (SettingNotFoundException e) {
+        final boolean subtypeIsSelected =
+                mSettings.getSelectedInputMethodSubtypeHashCode() != NOT_A_SUBTYPE_ID;
+        final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
+        if (imi == null || imi.getSubtypeCount() == 0) {
+            return null;
         }
-        synchronized (mMethodMap) {
-            final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
-            if (imi == null || imi.getSubtypeCount() == 0) {
-                return null;
-            }
-            if (!subtypeIsSelected || mCurrentSubtype == null
-                    || !isValidSubtypeId(imi, mCurrentSubtype.hashCode())) {
-                int subtypeId = getSelectedInputMethodSubtypeId(mCurMethodId);
-                if (subtypeId == NOT_A_SUBTYPE_ID) {
-                    // If there are no selected subtypes, the framework will try to find
-                    // the most applicable subtype from explicitly or implicitly enabled
-                    // subtypes.
-                    List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypes =
-                            getEnabledInputMethodSubtypeList(imi, true);
-                    // If there is only one explicitly or implicitly enabled subtype,
-                    // just returns it.
-                    if (explicitlyOrImplicitlyEnabledSubtypes.size() == 1) {
-                        mCurrentSubtype = explicitlyOrImplicitlyEnabledSubtypes.get(0);
-                    } else if (explicitlyOrImplicitlyEnabledSubtypes.size() > 1) {
+        if (!subtypeIsSelected || mCurrentSubtype == null
+                || !isValidSubtypeId(imi, mCurrentSubtype.hashCode())) {
+            int subtypeId = getSelectedInputMethodSubtypeId(mCurMethodId);
+            if (subtypeId == NOT_A_SUBTYPE_ID) {
+                // If there are no selected subtypes, the framework will try to find
+                // the most applicable subtype from explicitly or implicitly enabled
+                // subtypes.
+                List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypes =
+                        getEnabledInputMethodSubtypeListLocked(imi, true);
+                // If there is only one explicitly or implicitly enabled subtype,
+                // just returns it.
+                if (explicitlyOrImplicitlyEnabledSubtypes.size() == 1) {
+                    mCurrentSubtype = explicitlyOrImplicitlyEnabledSubtypes.get(0);
+                } else if (explicitlyOrImplicitlyEnabledSubtypes.size() > 1) {
+                    mCurrentSubtype = findLastResortApplicableSubtypeLocked(
+                            mRes, explicitlyOrImplicitlyEnabledSubtypes,
+                            SUBTYPE_MODE_KEYBOARD, null, true);
+                    if (mCurrentSubtype == null) {
                         mCurrentSubtype = findLastResortApplicableSubtypeLocked(
-                                mRes, explicitlyOrImplicitlyEnabledSubtypes,
-                                SUBTYPE_MODE_KEYBOARD, null, true);
-                        if (mCurrentSubtype == null) {
-                            mCurrentSubtype = findLastResortApplicableSubtypeLocked(
-                                    mRes, explicitlyOrImplicitlyEnabledSubtypes, null, null,
-                                    true);
-                        }
+                                mRes, explicitlyOrImplicitlyEnabledSubtypes, null, null,
+                                true);
                     }
-                } else {
-                    mCurrentSubtype = getSubtypes(imi).get(subtypeId);
                 }
+            } else {
+                mCurrentSubtype = getSubtypes(imi).get(subtypeId);
             }
-            return mCurrentSubtype;
         }
+        return mCurrentSubtype;
     }
 
     private void addShortcutInputMethodAndSubtypes(InputMethodInfo imi,
@@ -3032,6 +3267,10 @@
 
     @Override
     public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
+        // TODO: Make this work even for non-current users?
+        if (!calledFromValidUser()) {
+            return false;
+        }
         synchronized (mMethodMap) {
             if (subtype != null && mCurMethodId != null) {
                 InputMethodInfo imi = mMethodMap.get(mCurMethodId);
@@ -3047,6 +3286,7 @@
 
     private static class InputMethodAndSubtypeListManager {
         private final Context mContext;
+        // Used to load label
         private final PackageManager mPm;
         private final InputMethodManagerService mImms;
         private final String mSystemLocaleStr;
@@ -3183,6 +3423,7 @@
         private final ArrayList<InputMethodInfo> mMethodList;
 
         private String mEnabledInputMethodsStrCache;
+        private int mCurrentUserId;
 
         private static void buildEnabledInputMethodsSettingString(
                 StringBuilder builder, Pair<String, ArrayList<String>> pair) {
@@ -3198,13 +3439,24 @@
 
         public InputMethodSettings(
                 Resources res, ContentResolver resolver,
-                HashMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList) {
+                HashMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList,
+                int userId) {
+            setCurrentUserId(userId);
             mRes = res;
             mResolver = resolver;
             mMethodMap = methodMap;
             mMethodList = methodList;
         }
 
+        public void setCurrentUserId(int userId) {
+            if (DEBUG) {
+                Slog.d(TAG, "--- Swtich the current user from " + mCurrentUserId + " to "
+                        + userId + ", new ime = " + getSelectedInputMethod());
+            }
+            // IMMS settings are kept per user, so keep track of current user
+            mCurrentUserId = userId;
+        }
+
         public List<InputMethodInfo> getEnabledInputMethodListLocked() {
             return createEnabledInputMethodListLocked(
                     getEnabledInputMethodsAndSubtypeListLocked());
@@ -3353,15 +3605,20 @@
         }
 
         private void putEnabledInputMethodsStr(String str) {
-            Settings.Secure.putString(mResolver, Settings.Secure.ENABLED_INPUT_METHODS, str);
+            Settings.Secure.putStringForUser(
+                    mResolver, Settings.Secure.ENABLED_INPUT_METHODS, str, mCurrentUserId);
             mEnabledInputMethodsStrCache = str;
+            if (DEBUG) {
+                Slog.d(TAG, "putEnabledInputMethodStr: " + str);
+            }
         }
 
         private String getEnabledInputMethodsStr() {
-            mEnabledInputMethodsStrCache = Settings.Secure.getString(
-                    mResolver, Settings.Secure.ENABLED_INPUT_METHODS);
+            mEnabledInputMethodsStrCache = Settings.Secure.getStringForUser(
+                    mResolver, Settings.Secure.ENABLED_INPUT_METHODS, mCurrentUserId);
             if (DEBUG) {
-                Slog.d(TAG, "getEnabledInputMethodsStr: " + mEnabledInputMethodsStrCache);
+                Slog.d(TAG, "getEnabledInputMethodsStr: " + mEnabledInputMethodsStrCache
+                        + ", " + mCurrentUserId);
             }
             return mEnabledInputMethodsStrCache;
         }
@@ -3416,8 +3673,8 @@
             if (DEBUG) {
                 Slog.d(TAG, "putSubtypeHistoryStr: " + str);
             }
-            Settings.Secure.putString(
-                    mResolver, Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, str);
+            Settings.Secure.putStringForUser(
+                    mResolver, Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, str, mCurrentUserId);
         }
 
         public Pair<String, String> getLastInputMethodAndSubtypeLocked() {
@@ -3536,23 +3793,61 @@
 
         private String getSubtypeHistoryStr() {
             if (DEBUG) {
-                Slog.d(TAG, "getSubtypeHistoryStr: " + Settings.Secure.getString(
-                        mResolver, Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY));
+                Slog.d(TAG, "getSubtypeHistoryStr: " + Settings.Secure.getStringForUser(
+                        mResolver, Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, mCurrentUserId));
             }
-            return Settings.Secure.getString(
-                    mResolver, Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY);
+            return Settings.Secure.getStringForUser(
+                    mResolver, Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, mCurrentUserId);
         }
 
         public void putSelectedInputMethod(String imeId) {
-            Settings.Secure.putString(mResolver, Settings.Secure.DEFAULT_INPUT_METHOD, imeId);
+            if (DEBUG) {
+                Slog.d(TAG, "putSelectedInputMethodStr: " + imeId + ", "
+                        + mCurrentUserId);
+            }
+            Settings.Secure.putStringForUser(
+                    mResolver, Settings.Secure.DEFAULT_INPUT_METHOD, imeId, mCurrentUserId);
         }
 
         public void putSelectedSubtype(int subtypeId) {
-            Settings.Secure.putInt(
-                    mResolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, subtypeId);
+            if (DEBUG) {
+                Slog.d(TAG, "putSelectedInputMethodSubtypeStr: " + subtypeId + ", "
+                        + mCurrentUserId);
+            }
+            Settings.Secure.putIntForUser(mResolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE,
+                    subtypeId, mCurrentUserId);
+        }
+
+        public String getDisabledSystemInputMethods() {
+            return Settings.Secure.getStringForUser(
+                    mResolver, Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS, mCurrentUserId);
+        }
+
+        public String getSelectedInputMethod() {
+            if (DEBUG) {
+                Slog.d(TAG, "getSelectedInputMethodStr: " + Settings.Secure.getStringForUser(
+                        mResolver, Settings.Secure.DEFAULT_INPUT_METHOD, mCurrentUserId)
+                        + ", " + mCurrentUserId);
+            }
+            return Settings.Secure.getStringForUser(
+                    mResolver, Settings.Secure.DEFAULT_INPUT_METHOD, mCurrentUserId);
+        }
+
+        public int getSelectedInputMethodSubtypeHashCode() {
+            try {
+                return Settings.Secure.getIntForUser(
+                        mResolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, mCurrentUserId);
+            } catch (SettingNotFoundException e) {
+                return NOT_A_SUBTYPE_ID;
+            }
+        }
+
+        public int getCurrentUserId() {
+            return mCurrentUserId;
         }
     }
 
+    // TODO: Cache the state for each user and reset when the cached user is removed.
     private static class InputMethodFileManager {
         private static final String SYSTEM_PATH = "system";
         private static final String INPUT_METHOD_PATH = "inputmethod";
@@ -3569,14 +3864,16 @@
         private static final String ATTR_IS_AUXILIARY = "isAuxiliary";
         private final AtomicFile mAdditionalInputMethodSubtypeFile;
         private final HashMap<String, InputMethodInfo> mMethodMap;
-        private final HashMap<String, List<InputMethodSubtype>> mSubtypesMap =
+        private final HashMap<String, List<InputMethodSubtype>> mAdditionalSubtypesMap =
                 new HashMap<String, List<InputMethodSubtype>>();
-        public InputMethodFileManager(HashMap<String, InputMethodInfo> methodMap) {
+        public InputMethodFileManager(HashMap<String, InputMethodInfo> methodMap, int userId) {
             if (methodMap == null) {
                 throw new NullPointerException("methodMap is null");
             }
             mMethodMap = methodMap;
-            final File systemDir = new File(Environment.getDataDirectory(), SYSTEM_PATH);
+            final File systemDir = userId == UserHandle.USER_OWNER
+                    ? new File(Environment.getDataDirectory(), SYSTEM_PATH)
+                    : Environment.getUserSystemDirectory(userId);
             final File inputMethodDir = new File(systemDir, INPUT_METHOD_PATH);
             if (!inputMethodDir.mkdirs()) {
                 Slog.w(TAG, "Couldn't create dir.: " + inputMethodDir.getAbsolutePath());
@@ -3585,18 +3882,19 @@
             mAdditionalInputMethodSubtypeFile = new AtomicFile(subtypeFile);
             if (!subtypeFile.exists()) {
                 // If "subtypes.xml" doesn't exist, create a blank file.
-                writeAdditionalInputMethodSubtypes(mSubtypesMap, mAdditionalInputMethodSubtypeFile,
-                        methodMap);
+                writeAdditionalInputMethodSubtypes(
+                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, methodMap);
             } else {
-                readAdditionalInputMethodSubtypes(mSubtypesMap, mAdditionalInputMethodSubtypeFile);
+                readAdditionalInputMethodSubtypes(
+                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile);
             }
         }
 
         private void deleteAllInputMethodSubtypes(String imiId) {
             synchronized (mMethodMap) {
-                mSubtypesMap.remove(imiId);
-                writeAdditionalInputMethodSubtypes(mSubtypesMap, mAdditionalInputMethodSubtypeFile,
-                        mMethodMap);
+                mAdditionalSubtypesMap.remove(imiId);
+                writeAdditionalInputMethodSubtypes(
+                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, mMethodMap);
             }
         }
 
@@ -3609,17 +3907,20 @@
                     final InputMethodSubtype subtype = additionalSubtypes[i];
                     if (!subtypes.contains(subtype)) {
                         subtypes.add(subtype);
+                    } else {
+                        Slog.w(TAG, "Duplicated subtype definition found: "
+                                + subtype.getLocale() + ", " + subtype.getMode());
                     }
                 }
-                mSubtypesMap.put(imi.getId(), subtypes);
-                writeAdditionalInputMethodSubtypes(mSubtypesMap, mAdditionalInputMethodSubtypeFile,
-                        mMethodMap);
+                mAdditionalSubtypesMap.put(imi.getId(), subtypes);
+                writeAdditionalInputMethodSubtypes(
+                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, mMethodMap);
             }
         }
 
         public HashMap<String, List<InputMethodSubtype>> getAllAdditionalInputMethodSubtypes() {
             synchronized (mMethodMap) {
-                return mSubtypesMap;
+                return mAdditionalSubtypesMap;
             }
         }
 
@@ -3748,6 +4049,20 @@
     }
 
     // ----------------------------------------------------------------------
+    // Utilities for debug
+    private static String getStackTrace() {
+        final StringBuilder sb = new StringBuilder();
+        try {
+            throw new RuntimeException();
+        } catch (RuntimeException e) {
+            final StackTraceElement[] frames = e.getStackTrace();
+            // Start at 1 because the first frame is here and we don't care about it
+            for (int j = 1; j < frames.length; ++j) {
+                sb.append(frames[j].toString() + "\n");
+            }
+        }
+        return sb.toString();
+    }
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java
index f7e841e..9b19008 100644
--- a/services/java/com/android/server/IntentResolver.java
+++ b/services/java/com/android/server/IntentResolver.java
@@ -34,6 +34,7 @@
 import android.util.Slog;
 import android.util.LogPrinter;
 import android.util.Printer;
+import android.util.StringBuilderPrinter;
 
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -45,6 +46,7 @@
     final private static String TAG = "IntentResolver";
     final private static boolean DEBUG = false;
     final private static boolean localLOGV = DEBUG || false;
+    final private static boolean VALIDATE = false;
 
     public void addFilter(F f) {
         if (localLOGV) {
@@ -65,11 +67,21 @@
             register_intent_filter(f, f.actionsIterator(),
                     mTypedActionToFilter, "      TypedAction: ");
         }
+
+        if (VALIDATE) {
+            mOldResolver.addFilter(f);
+            verifyDataStructures(f);
+        }
     }
 
     public void removeFilter(F f) {
         removeFilterInternal(f);
         mFilters.remove(f);
+
+        if (VALIDATE) {
+            mOldResolver.removeFilter(f);
+            verifyDataStructures(f);
+        }
     }
 
     void removeFilterInternal(F f) {
@@ -93,18 +105,18 @@
     }
 
     boolean dumpMap(PrintWriter out, String titlePrefix, String title,
-            String prefix, Map<String, ArrayList<F>> map, String packageName,
+            String prefix, Map<String, F[]> map, String packageName,
             boolean printFilter) {
         String eprefix = prefix + "  ";
         String fprefix = prefix + "    ";
         boolean printedSomething = false;
         Printer printer = null;
-        for (Map.Entry<String, ArrayList<F>> e : map.entrySet()) {
-            ArrayList<F> a = e.getValue();
-            final int N = a.size();
+        for (Map.Entry<String, F[]> e : map.entrySet()) {
+            F[] a = e.getValue();
+            final int N = a.length;
             boolean printedHeader = false;
-            for (int i=0; i<N; i++) {
-                F filter = a.get(i);
+            F filter;
+            for (int i=0; i<N && (filter=a[i]) != null; i++) {
                 if (packageName != null && !packageName.equals(packageForFilter(filter))) {
                     continue;
                 }
@@ -201,7 +213,7 @@
     }
 
     public List<R> queryIntentFromList(Intent intent, String resolvedType, 
-            boolean defaultOnly, ArrayList<ArrayList<F>> listCut, int userId) {
+            boolean defaultOnly, ArrayList<F[]> listCut, int userId) {
         ArrayList<R> resultList = new ArrayList<R>();
 
         final boolean debug = localLOGV ||
@@ -231,10 +243,10 @@
             TAG, "Resolving type " + resolvedType + " scheme " + scheme
             + " of intent " + intent);
 
-        ArrayList<F> firstTypeCut = null;
-        ArrayList<F> secondTypeCut = null;
-        ArrayList<F> thirdTypeCut = null;
-        ArrayList<F> schemeCut = null;
+        F[] firstTypeCut = null;
+        F[] secondTypeCut = null;
+        F[] thirdTypeCut = null;
+        F[] schemeCut = null;
 
         // If the intent includes a MIME type, then we want to collect all of
         // the filters that match that MIME type.
@@ -307,6 +319,16 @@
         }
         sortResults(finalList);
 
+        if (VALIDATE) {
+            List<R> oldList = mOldResolver.queryIntent(intent, resolvedType, defaultOnly, userId);
+            if (oldList.size() != finalList.size()) {
+                ValidationFailure here = new ValidationFailure();
+                here.fillInStackTrace();
+                Log.wtf(TAG, "Query result " + intent + " size is " + finalList.size()
+                        + "; old implementation is " + oldList.size(), here);
+            }
+        }
+
         if (debug) {
             Slog.v(TAG, "Final result list:");
             for (R r : finalList) {
@@ -340,7 +362,9 @@
      * they are to be delivered to.
      */
     protected abstract String packageForFilter(F filter);
-    
+
+    protected abstract F[] newArray(int size);
+
     @SuppressWarnings("unchecked")
     protected R newResult(F filter, int match, int userId) {
         return (R)filter;
@@ -355,6 +379,29 @@
         out.print(prefix); out.println(filter);
     }
 
+    private final void addFilter(HashMap<String, F[]> map, String name, F filter) {
+        F[] array = map.get(name);
+        if (array == null) {
+            array = newArray(2);
+            map.put(name,  array);
+            array[0] = filter;
+        } else {
+            final int N = array.length;
+            int i = N;
+            while (i > 0 && array[i-1] == null) {
+                i--;
+            }
+            if (i < N) {
+                array[i] = filter;
+            } else {
+                F[] newa = newArray((N*3)/2);
+                System.arraycopy(array, 0, newa, 0, N);
+                newa[N] = filter;
+                map.put(name, newa);
+            }
+        }
+    }
+
     private final int register_mime_types(F filter, String prefix) {
         final Iterator<String> i = filter.typesIterator();
         if (i == null) {
@@ -374,30 +421,12 @@
                 name = name + "/*";
             }
 
-            ArrayList<F> array = mTypeToFilter.get(name);
-            if (array == null) {
-                //Slog.v(TAG, "Creating new array for " + name);
-                array = new ArrayList<F>();
-                mTypeToFilter.put(name, array);
-            }
-            array.add(filter);
+            addFilter(mTypeToFilter, name, filter);
 
             if (slashpos > 0) {
-                array = mBaseTypeToFilter.get(baseName);
-                if (array == null) {
-                    //Slog.v(TAG, "Creating new array for " + name);
-                    array = new ArrayList<F>();
-                    mBaseTypeToFilter.put(baseName, array);
-                }
-                array.add(filter);
+                addFilter(mBaseTypeToFilter, baseName, filter);
             } else {
-                array = mWildTypeToFilter.get(baseName);
-                if (array == null) {
-                    //Slog.v(TAG, "Creating new array for " + name);
-                    array = new ArrayList<F>();
-                    mWildTypeToFilter.put(baseName, array);
-                }
-                array.add(filter);
+                addFilter(mWildTypeToFilter, baseName, filter);
             }
         }
 
@@ -423,25 +452,19 @@
                 name = name + "/*";
             }
 
-            if (!remove_all_objects(mTypeToFilter.get(name), filter)) {
-                mTypeToFilter.remove(name);
-            }
+            remove_all_objects(mTypeToFilter, name, filter);
 
             if (slashpos > 0) {
-                if (!remove_all_objects(mBaseTypeToFilter.get(baseName), filter)) {
-                    mBaseTypeToFilter.remove(baseName);
-                }
+                remove_all_objects(mBaseTypeToFilter, baseName, filter);
             } else {
-                if (!remove_all_objects(mWildTypeToFilter.get(baseName), filter)) {
-                    mWildTypeToFilter.remove(baseName);
-                }
+                remove_all_objects(mWildTypeToFilter, baseName, filter);
             }
         }
         return num;
     }
 
     private final int register_intent_filter(F filter, Iterator<String> i,
-            HashMap<String, ArrayList<F>> dest, String prefix) {
+            HashMap<String, F[]> dest, String prefix) {
         if (i == null) {
             return 0;
         }
@@ -451,19 +474,13 @@
             String name = i.next();
             num++;
             if (localLOGV) Slog.v(TAG, prefix + name);
-            ArrayList<F> array = dest.get(name);
-            if (array == null) {
-                //Slog.v(TAG, "Creating new array for " + name);
-                array = new ArrayList<F>();
-                dest.put(name, array);
-            }
-            array.add(filter);
+            addFilter(dest, name, filter);
         }
         return num;
     }
 
     private final int unregister_intent_filter(F filter, Iterator<String> i,
-            HashMap<String, ArrayList<F>> dest, String prefix) {
+            HashMap<String, F[]> dest, String prefix) {
         if (i == null) {
             return 0;
         }
@@ -473,26 +490,37 @@
             String name = i.next();
             num++;
             if (localLOGV) Slog.v(TAG, prefix + name);
-            if (!remove_all_objects(dest.get(name), filter)) {
-                dest.remove(name);
-            }
+            remove_all_objects(dest, name, filter);
         }
         return num;
     }
 
-    private final boolean remove_all_objects(List<F> list, Object object) {
-        if (list != null) {
-            int N = list.size();
-            for (int idx=0; idx<N; idx++) {
-                if (list.get(idx) == object) {
-                    list.remove(idx);
-                    idx--;
-                    N--;
+    private final void remove_all_objects(HashMap<String, F[]> map, String name,
+            Object object) {
+        F[] array = map.get(name);
+        if (array != null) {
+            int LAST = array.length-1;
+            while (LAST >= 0 && array[LAST] == null) {
+                LAST--;
+            }
+            for (int idx=LAST; idx>=0; idx--) {
+                if (array[idx] == object) {
+                    final int remain = LAST - idx;
+                    if (remain > 0) {
+                        System.arraycopy(array, idx+1, array, idx, remain);
+                    }
+                    array[LAST] = null;
+                    LAST--;
                 }
             }
-            return N > 0;
+            if (LAST < 0) {
+                map.remove(name);
+            } else if (LAST < (array.length/2)) {
+                F[] newa = newArray(LAST+2);
+                System.arraycopy(array, 0, newa, 0, LAST+1);
+                map.put(name, newa);
+            }
         }
-        return false;
     }
 
     private static FastImmutableArraySet<String> getFastIntentCategories(Intent intent) {
@@ -505,18 +533,18 @@
 
     private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
             boolean debug, boolean defaultOnly,
-            String resolvedType, String scheme, List<F> src, List<R> dest, int userId) {
+            String resolvedType, String scheme, F[] src, List<R> dest, int userId) {
         final String action = intent.getAction();
         final Uri data = intent.getData();
         final String packageName = intent.getPackage();
 
         final boolean excludingStopped = intent.isExcludingStopped();
 
-        final int N = src != null ? src.size() : 0;
+        final int N = src != null ? src.length : 0;
         boolean hasNonDefaults = false;
         int i;
-        for (i=0; i<N; i++) {
-            F filter = src.get(i);
+        F filter;
+        for (i=0; i<N && (filter=src[i]) != null; i++) {
             int match;
             if (debug) Slog.v(TAG, "Matching against filter " + filter);
 
@@ -585,6 +613,120 @@
         }
     };
 
+    static class ValidationFailure extends RuntimeException {
+    }
+
+    private void verifyDataStructures(IntentFilter src) {
+        compareMaps(src, "mTypeToFilter", mTypeToFilter, mOldResolver.mTypeToFilter);
+        compareMaps(src, "mBaseTypeToFilter", mBaseTypeToFilter, mOldResolver.mBaseTypeToFilter);
+        compareMaps(src, "mWildTypeToFilter", mWildTypeToFilter, mOldResolver.mWildTypeToFilter);
+        compareMaps(src, "mSchemeToFilter", mSchemeToFilter, mOldResolver.mSchemeToFilter);
+        compareMaps(src, "mActionToFilter", mActionToFilter, mOldResolver.mActionToFilter);
+        compareMaps(src, "mTypedActionToFilter", mTypedActionToFilter, mOldResolver.mTypedActionToFilter);
+    }
+
+    private void compareMaps(IntentFilter src, String name, HashMap<String, F[]> cur,
+            HashMap<String, ArrayList<F>> old) {
+        if (cur.size() != old.size()) {
+            StringBuilder missing = new StringBuilder(128);
+            for (Map.Entry<String, ArrayList<F>> e : old.entrySet()) {
+                final F[] curArray = cur.get(e.getKey());
+                if (curArray == null) {
+                    if (missing.length() > 0) {
+                        missing.append(' ');
+                    }
+                    missing.append(e.getKey());
+                }
+            }
+            StringBuilder extra = new StringBuilder(128);
+            for (Map.Entry<String, F[]> e : cur.entrySet()) {
+                if (old.get(e.getKey()) == null) {
+                    if (extra.length() > 0) {
+                        extra.append(' ');
+                    }
+                    extra.append(e.getKey());
+                }
+            }
+            StringBuilder srcStr = new StringBuilder(1024);
+            StringBuilderPrinter printer = new StringBuilderPrinter(srcStr);
+            src.dump(printer, "");
+            ValidationFailure here = new ValidationFailure();
+            here.fillInStackTrace();
+            Log.wtf(TAG, "New map " + name + " size is " + cur.size()
+                    + "; old implementation is " + old.size()
+                    + "; missing: " + missing.toString()
+                    + "; extra: " + extra.toString()
+                    + "; src: " + srcStr.toString(), here);
+            return;
+        }
+        for (Map.Entry<String, ArrayList<F>> e : old.entrySet()) {
+            final F[] curArray = cur.get(e.getKey());
+            int curLen = curArray != null ? curArray.length : 0;
+            if (curLen == 0) {
+                ValidationFailure here = new ValidationFailure();
+                here.fillInStackTrace();
+                Log.wtf(TAG, "New map " + name + " doesn't contain expected key "
+                        + e.getKey() + " (array=" + curArray + ")");
+                return;
+            }
+            while (curLen > 0 && curArray[curLen-1] == null) {
+                curLen--;
+            }
+            final ArrayList<F> oldArray = e.getValue();
+            final int oldLen = oldArray.size();
+            if (curLen != oldLen) {
+                ValidationFailure here = new ValidationFailure();
+                here.fillInStackTrace();
+                Log.wtf(TAG, "New map " + name + " entry " + e.getKey() + " size is "
+                        + curLen + "; old implementation is " + oldLen, here);
+                return;
+            }
+            for (int i=0; i<oldLen; i++) {
+                F f = oldArray.get(i);
+                boolean found = false;
+                for (int j=0; j<curLen; j++) {
+                    if (curArray[j] == f) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {
+                    ValidationFailure here = new ValidationFailure();
+                    here.fillInStackTrace();
+                    Log.wtf(TAG, "New map " + name + " entry + " + e.getKey()
+                            + " doesn't contain expected filter " + f, here);
+                }
+            }
+            for (int i=0; i<curLen; i++) {
+                if (curArray[i] == null) {
+                    ValidationFailure here = new ValidationFailure();
+                    here.fillInStackTrace();
+                    Log.wtf(TAG, "New map " + name + " entry + " + e.getKey()
+                            + " has unexpected null at " + i + "; array: " + curArray, here);
+                    break;
+                }
+            }
+        }
+    }
+
+    private final IntentResolverOld<F, R> mOldResolver = new IntentResolverOld<F, R>() {
+        @Override protected String packageForFilter(F filter) {
+            return IntentResolver.this.packageForFilter(filter);
+        }
+        @Override protected boolean allowFilterResult(F filter, List<R> dest) {
+            return IntentResolver.this.allowFilterResult(filter, dest);
+        }
+        @Override protected boolean isFilterStopped(F filter, int userId) {
+            return IntentResolver.this.isFilterStopped(filter, userId);
+        }
+        @Override protected R newResult(F filter, int match, int userId) {
+            return IntentResolver.this.newResult(filter, match, userId);
+        }
+        @Override protected void sortResults(List<R> results) {
+            IntentResolver.this.sortResults(results);
+        }
+    };
+
     /**
      * All filters that have been registered.
      */
@@ -594,16 +736,14 @@
      * All of the MIME types that have been registered, such as "image/jpeg",
      * "image/*", or "{@literal *}/*".
      */
-    private final HashMap<String, ArrayList<F>> mTypeToFilter
-            = new HashMap<String, ArrayList<F>>();
+    private final HashMap<String, F[]> mTypeToFilter = new HashMap<String, F[]>();
 
     /**
      * The base names of all of all fully qualified MIME types that have been
      * registered, such as "image" or "*".  Wild card MIME types such as
      * "image/*" will not be here.
      */
-    private final HashMap<String, ArrayList<F>> mBaseTypeToFilter
-            = new HashMap<String, ArrayList<F>>();
+    private final HashMap<String, F[]> mBaseTypeToFilter = new HashMap<String, F[]>();
 
     /**
      * The base names of all of the MIME types with a sub-type wildcard that
@@ -612,26 +752,21 @@
      * included here.  This also includes the "*" for the "{@literal *}/*"
      * MIME type.
      */
-    private final HashMap<String, ArrayList<F>> mWildTypeToFilter
-            = new HashMap<String, ArrayList<F>>();
+    private final HashMap<String, F[]> mWildTypeToFilter = new HashMap<String, F[]>();
 
     /**
      * All of the URI schemes (such as http) that have been registered.
      */
-    private final HashMap<String, ArrayList<F>> mSchemeToFilter
-            = new HashMap<String, ArrayList<F>>();
+    private final HashMap<String, F[]> mSchemeToFilter = new HashMap<String, F[]>();
 
     /**
      * All of the actions that have been registered, but only those that did
      * not specify data.
      */
-    private final HashMap<String, ArrayList<F>> mActionToFilter
-            = new HashMap<String, ArrayList<F>>();
+    private final HashMap<String, F[]> mActionToFilter = new HashMap<String, F[]>();
 
     /**
      * All of the actions that have been registered and specified a MIME type.
      */
-    private final HashMap<String, ArrayList<F>> mTypedActionToFilter
-            = new HashMap<String, ArrayList<F>>();
+    private final HashMap<String, F[]> mTypedActionToFilter = new HashMap<String, F[]>();
 }
-
diff --git a/services/java/com/android/server/IntentResolverOld.java b/services/java/com/android/server/IntentResolverOld.java
new file mode 100644
index 0000000..4dd77ce
--- /dev/null
+++ b/services/java/com/android/server/IntentResolverOld.java
@@ -0,0 +1,638 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import android.net.Uri;
+import android.util.FastImmutableArraySet;
+import android.util.Log;
+import android.util.PrintWriterPrinter;
+import android.util.Slog;
+import android.util.LogPrinter;
+import android.util.Printer;
+
+import android.content.Intent;
+import android.content.IntentFilter;
+
+/**
+ * Temporary for verification of new implementation.
+ * {@hide}
+ */
+public abstract class IntentResolverOld<F extends IntentFilter, R extends Object> {
+    final private static String TAG = "IntentResolver";
+    final private static boolean DEBUG = false;
+    final private static boolean localLOGV = DEBUG || false;
+
+    public void addFilter(F f) {
+        if (localLOGV) {
+            Slog.v(TAG, "Adding filter: " + f);
+            f.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), "      ");
+            Slog.v(TAG, "    Building Lookup Maps:");
+        }
+
+        mFilters.add(f);
+        int numS = register_intent_filter(f, f.schemesIterator(),
+                mSchemeToFilter, "      Scheme: ");
+        int numT = register_mime_types(f, "      Type: ");
+        if (numS == 0 && numT == 0) {
+            register_intent_filter(f, f.actionsIterator(),
+                    mActionToFilter, "      Action: ");
+        }
+        if (numT != 0) {
+            register_intent_filter(f, f.actionsIterator(),
+                    mTypedActionToFilter, "      TypedAction: ");
+        }
+    }
+
+    public void removeFilter(F f) {
+        removeFilterInternal(f);
+        mFilters.remove(f);
+    }
+
+    void removeFilterInternal(F f) {
+        if (localLOGV) {
+            Slog.v(TAG, "Removing filter: " + f);
+            f.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), "      ");
+            Slog.v(TAG, "    Cleaning Lookup Maps:");
+        }
+
+        int numS = unregister_intent_filter(f, f.schemesIterator(),
+                mSchemeToFilter, "      Scheme: ");
+        int numT = unregister_mime_types(f, "      Type: ");
+        if (numS == 0 && numT == 0) {
+            unregister_intent_filter(f, f.actionsIterator(),
+                    mActionToFilter, "      Action: ");
+        }
+        if (numT != 0) {
+            unregister_intent_filter(f, f.actionsIterator(),
+                    mTypedActionToFilter, "      TypedAction: ");
+        }
+    }
+
+    boolean dumpMap(PrintWriter out, String titlePrefix, String title,
+            String prefix, Map<String, ArrayList<F>> map, String packageName,
+            boolean printFilter) {
+        String eprefix = prefix + "  ";
+        String fprefix = prefix + "    ";
+        boolean printedSomething = false;
+        Printer printer = null;
+        for (Map.Entry<String, ArrayList<F>> e : map.entrySet()) {
+            ArrayList<F> a = e.getValue();
+            final int N = a.size();
+            boolean printedHeader = false;
+            for (int i=0; i<N; i++) {
+                F filter = a.get(i);
+                if (packageName != null && !packageName.equals(packageForFilter(filter))) {
+                    continue;
+                }
+                if (title != null) {
+                    out.print(titlePrefix); out.println(title);
+                    title = null;
+                }
+                if (!printedHeader) {
+                    out.print(eprefix); out.print(e.getKey()); out.println(":");
+                    printedHeader = true;
+                }
+                printedSomething = true;
+                dumpFilter(out, fprefix, filter);
+                if (printFilter) {
+                    if (printer == null) {
+                        printer = new PrintWriterPrinter(out);
+                    }
+                    filter.dump(printer, fprefix + "  ");
+                }
+            }
+        }
+        return printedSomething;
+    }
+
+    public boolean dump(PrintWriter out, String title, String prefix, String packageName,
+            boolean printFilter) {
+        String innerPrefix = prefix + "  ";
+        String sepPrefix = "\n" + prefix;
+        String curPrefix = title + "\n" + prefix;
+        if (dumpMap(out, curPrefix, "Full MIME Types:", innerPrefix,
+                mTypeToFilter, packageName, printFilter)) {
+            curPrefix = sepPrefix;
+        }
+        if (dumpMap(out, curPrefix, "Base MIME Types:", innerPrefix,
+                mBaseTypeToFilter, packageName, printFilter)) {
+            curPrefix = sepPrefix;
+        }
+        if (dumpMap(out, curPrefix, "Wild MIME Types:", innerPrefix,
+                mWildTypeToFilter, packageName, printFilter)) {
+            curPrefix = sepPrefix;
+        }
+        if (dumpMap(out, curPrefix, "Schemes:", innerPrefix,
+                mSchemeToFilter, packageName, printFilter)) {
+            curPrefix = sepPrefix;
+        }
+        if (dumpMap(out, curPrefix, "Non-Data Actions:", innerPrefix,
+                mActionToFilter, packageName, printFilter)) {
+            curPrefix = sepPrefix;
+        }
+        if (dumpMap(out, curPrefix, "MIME Typed Actions:", innerPrefix,
+                mTypedActionToFilter, packageName, printFilter)) {
+            curPrefix = sepPrefix;
+        }
+        return curPrefix == sepPrefix;
+    }
+
+    private class IteratorWrapper implements Iterator<F> {
+        private final Iterator<F> mI;
+        private F mCur;
+
+        IteratorWrapper(Iterator<F> it) {
+            mI = it;
+        }
+
+        public boolean hasNext() {
+            return mI.hasNext();
+        }
+
+        public F next() {
+            return (mCur = mI.next());
+        }
+
+        public void remove() {
+            if (mCur != null) {
+                removeFilterInternal(mCur);
+            }
+            mI.remove();
+        }
+
+    }
+
+    /**
+     * Returns an iterator allowing filters to be removed.
+     */
+    public Iterator<F> filterIterator() {
+        return new IteratorWrapper(mFilters.iterator());
+    }
+
+    /**
+     * Returns a read-only set of the filters.
+     */
+    public Set<F> filterSet() {
+        return Collections.unmodifiableSet(mFilters);
+    }
+
+    public List<R> queryIntentFromList(Intent intent, String resolvedType, 
+            boolean defaultOnly, ArrayList<ArrayList<F>> listCut, int userId) {
+        ArrayList<R> resultList = new ArrayList<R>();
+
+        final boolean debug = localLOGV ||
+                ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
+
+        FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
+        final String scheme = intent.getScheme();
+        int N = listCut.size();
+        for (int i = 0; i < N; ++i) {
+            buildResolveList(intent, categories, debug, defaultOnly,
+                    resolvedType, scheme, listCut.get(i), resultList, userId);
+        }
+        sortResults(resultList);
+        return resultList;
+    }
+
+    public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
+            int userId) {
+        String scheme = intent.getScheme();
+
+        ArrayList<R> finalList = new ArrayList<R>();
+
+        final boolean debug = localLOGV ||
+                ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
+
+        if (debug) Slog.v(
+            TAG, "Resolving type " + resolvedType + " scheme " + scheme
+            + " of intent " + intent);
+
+        ArrayList<F> firstTypeCut = null;
+        ArrayList<F> secondTypeCut = null;
+        ArrayList<F> thirdTypeCut = null;
+        ArrayList<F> schemeCut = null;
+
+        // If the intent includes a MIME type, then we want to collect all of
+        // the filters that match that MIME type.
+        if (resolvedType != null) {
+            int slashpos = resolvedType.indexOf('/');
+            if (slashpos > 0) {
+                final String baseType = resolvedType.substring(0, slashpos);
+                if (!baseType.equals("*")) {
+                    if (resolvedType.length() != slashpos+2
+                            || resolvedType.charAt(slashpos+1) != '*') {
+                        // Not a wild card, so we can just look for all filters that
+                        // completely match or wildcards whose base type matches.
+                        firstTypeCut = mTypeToFilter.get(resolvedType);
+                        if (debug) Slog.v(TAG, "First type cut: " + firstTypeCut);
+                        secondTypeCut = mWildTypeToFilter.get(baseType);
+                        if (debug) Slog.v(TAG, "Second type cut: " + secondTypeCut);
+                    } else {
+                        // We can match anything with our base type.
+                        firstTypeCut = mBaseTypeToFilter.get(baseType);
+                        if (debug) Slog.v(TAG, "First type cut: " + firstTypeCut);
+                        secondTypeCut = mWildTypeToFilter.get(baseType);
+                        if (debug) Slog.v(TAG, "Second type cut: " + secondTypeCut);
+                    }
+                    // Any */* types always apply, but we only need to do this
+                    // if the intent type was not already */*.
+                    thirdTypeCut = mWildTypeToFilter.get("*");
+                    if (debug) Slog.v(TAG, "Third type cut: " + thirdTypeCut);
+                } else if (intent.getAction() != null) {
+                    // The intent specified any type ({@literal *}/*).  This
+                    // can be a whole heck of a lot of things, so as a first
+                    // cut let's use the action instead.
+                    firstTypeCut = mTypedActionToFilter.get(intent.getAction());
+                    if (debug) Slog.v(TAG, "Typed Action list: " + firstTypeCut);
+                }
+            }
+        }
+
+        // If the intent includes a data URI, then we want to collect all of
+        // the filters that match its scheme (we will further refine matches
+        // on the authority and path by directly matching each resulting filter).
+        if (scheme != null) {
+            schemeCut = mSchemeToFilter.get(scheme);
+            if (debug) Slog.v(TAG, "Scheme list: " + schemeCut);
+        }
+
+        // If the intent does not specify any data -- either a MIME type or
+        // a URI -- then we will only be looking for matches against empty
+        // data.
+        if (resolvedType == null && scheme == null && intent.getAction() != null) {
+            firstTypeCut = mActionToFilter.get(intent.getAction());
+            if (debug) Slog.v(TAG, "Action list: " + firstTypeCut);
+        }
+
+        FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
+        if (firstTypeCut != null) {
+            buildResolveList(intent, categories, debug, defaultOnly,
+                    resolvedType, scheme, firstTypeCut, finalList, userId);
+        }
+        if (secondTypeCut != null) {
+            buildResolveList(intent, categories, debug, defaultOnly,
+                    resolvedType, scheme, secondTypeCut, finalList, userId);
+        }
+        if (thirdTypeCut != null) {
+            buildResolveList(intent, categories, debug, defaultOnly,
+                    resolvedType, scheme, thirdTypeCut, finalList, userId);
+        }
+        if (schemeCut != null) {
+            buildResolveList(intent, categories, debug, defaultOnly,
+                    resolvedType, scheme, schemeCut, finalList, userId);
+        }
+        sortResults(finalList);
+
+        if (debug) {
+            Slog.v(TAG, "Final result list:");
+            for (R r : finalList) {
+                Slog.v(TAG, "  " + r);
+            }
+        }
+        return finalList;
+    }
+
+    /**
+     * Control whether the given filter is allowed to go into the result
+     * list.  Mainly intended to prevent adding multiple filters for the
+     * same target object.
+     */
+    protected boolean allowFilterResult(F filter, List<R> dest) {
+        return true;
+    }
+
+    /**
+     * Returns whether the object associated with the given filter is
+     * "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, int userId) {
+        return false;
+    }
+
+    /**
+     * Return the package that owns this filter.  This must be implemented to
+     * provide correct filtering of Intents that have specified a package name
+     * they are to be delivered to.
+     */
+    protected abstract String packageForFilter(F filter);
+    
+    @SuppressWarnings("unchecked")
+    protected R newResult(F filter, int match, int userId) {
+        return (R)filter;
+    }
+
+    @SuppressWarnings("unchecked")
+    protected void sortResults(List<R> results) {
+        Collections.sort(results, mResolvePrioritySorter);
+    }
+
+    protected void dumpFilter(PrintWriter out, String prefix, F filter) {
+        out.print(prefix); out.println(filter);
+    }
+
+    private final int register_mime_types(F filter, String prefix) {
+        final Iterator<String> i = filter.typesIterator();
+        if (i == null) {
+            return 0;
+        }
+
+        int num = 0;
+        while (i.hasNext()) {
+            String name = i.next();
+            num++;
+            if (localLOGV) Slog.v(TAG, prefix + name);
+            String baseName = name;
+            final int slashpos = name.indexOf('/');
+            if (slashpos > 0) {
+                baseName = name.substring(0, slashpos).intern();
+            } else {
+                name = name + "/*";
+            }
+
+            ArrayList<F> array = mTypeToFilter.get(name);
+            if (array == null) {
+                //Slog.v(TAG, "Creating new array for " + name);
+                array = new ArrayList<F>();
+                mTypeToFilter.put(name, array);
+            }
+            array.add(filter);
+
+            if (slashpos > 0) {
+                array = mBaseTypeToFilter.get(baseName);
+                if (array == null) {
+                    //Slog.v(TAG, "Creating new array for " + name);
+                    array = new ArrayList<F>();
+                    mBaseTypeToFilter.put(baseName, array);
+                }
+                array.add(filter);
+            } else {
+                array = mWildTypeToFilter.get(baseName);
+                if (array == null) {
+                    //Slog.v(TAG, "Creating new array for " + name);
+                    array = new ArrayList<F>();
+                    mWildTypeToFilter.put(baseName, array);
+                }
+                array.add(filter);
+            }
+        }
+
+        return num;
+    }
+
+    private final int unregister_mime_types(F filter, String prefix) {
+        final Iterator<String> i = filter.typesIterator();
+        if (i == null) {
+            return 0;
+        }
+
+        int num = 0;
+        while (i.hasNext()) {
+            String name = i.next();
+            num++;
+            if (localLOGV) Slog.v(TAG, prefix + name);
+            String baseName = name;
+            final int slashpos = name.indexOf('/');
+            if (slashpos > 0) {
+                baseName = name.substring(0, slashpos).intern();
+            } else {
+                name = name + "/*";
+            }
+
+            if (!remove_all_objects(mTypeToFilter.get(name), filter)) {
+                mTypeToFilter.remove(name);
+            }
+
+            if (slashpos > 0) {
+                if (!remove_all_objects(mBaseTypeToFilter.get(baseName), filter)) {
+                    mBaseTypeToFilter.remove(baseName);
+                }
+            } else {
+                if (!remove_all_objects(mWildTypeToFilter.get(baseName), filter)) {
+                    mWildTypeToFilter.remove(baseName);
+                }
+            }
+        }
+        return num;
+    }
+
+    private final int register_intent_filter(F filter, Iterator<String> i,
+            HashMap<String, ArrayList<F>> dest, String prefix) {
+        if (i == null) {
+            return 0;
+        }
+
+        int num = 0;
+        while (i.hasNext()) {
+            String name = i.next();
+            num++;
+            if (localLOGV) Slog.v(TAG, prefix + name);
+            ArrayList<F> array = dest.get(name);
+            if (array == null) {
+                //Slog.v(TAG, "Creating new array for " + name);
+                array = new ArrayList<F>();
+                dest.put(name, array);
+            }
+            array.add(filter);
+        }
+        return num;
+    }
+
+    private final int unregister_intent_filter(F filter, Iterator<String> i,
+            HashMap<String, ArrayList<F>> dest, String prefix) {
+        if (i == null) {
+            return 0;
+        }
+
+        int num = 0;
+        while (i.hasNext()) {
+            String name = i.next();
+            num++;
+            if (localLOGV) Slog.v(TAG, prefix + name);
+            if (!remove_all_objects(dest.get(name), filter)) {
+                dest.remove(name);
+            }
+        }
+        return num;
+    }
+
+    private final boolean remove_all_objects(List<F> list, Object object) {
+        if (list != null) {
+            int N = list.size();
+            for (int idx=0; idx<N; idx++) {
+                if (list.get(idx) == object) {
+                    list.remove(idx);
+                    idx--;
+                    N--;
+                }
+            }
+            return N > 0;
+        }
+        return false;
+    }
+
+    private static FastImmutableArraySet<String> getFastIntentCategories(Intent intent) {
+        final Set<String> categories = intent.getCategories();
+        if (categories == null) {
+            return null;
+        }
+        return new FastImmutableArraySet<String>(categories.toArray(new String[categories.size()]));
+    }
+
+    private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
+            boolean debug, boolean defaultOnly,
+            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();
+
+        final boolean excludingStopped = intent.isExcludingStopped();
+
+        final int N = src != null ? src.size() : 0;
+        boolean hasNonDefaults = false;
+        int i;
+        for (i=0; i<N; i++) {
+            F filter = src.get(i);
+            int match;
+            if (debug) Slog.v(TAG, "Matching against filter " + filter);
+
+            if (excludingStopped && isFilterStopped(filter, userId)) {
+                if (debug) {
+                    Slog.v(TAG, "  Filter's target is stopped; skipping");
+                }
+                continue;
+            }
+
+            // Is delivery being limited to filters owned by a particular package?
+            if (packageName != null && !packageName.equals(packageForFilter(filter))) {
+                if (debug) {
+                    Slog.v(TAG, "  Filter is not from package " + packageName + "; skipping");
+                }
+                continue;
+            }
+
+            // Do we already have this one?
+            if (!allowFilterResult(filter, dest)) {
+                if (debug) {
+                    Slog.v(TAG, "  Filter's target already added");
+                }
+                continue;
+            }
+
+            match = filter.match(action, resolvedType, scheme, data, categories, TAG);
+            if (match >= 0) {
+                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, userId);
+                    if (oneResult != null) {
+                        dest.add(oneResult);
+                    }
+                } else {
+                    hasNonDefaults = true;
+                }
+            } else {
+                if (debug) {
+                    String reason;
+                    switch (match) {
+                        case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;
+                        case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;
+                        case IntentFilter.NO_MATCH_DATA: reason = "data"; break;
+                        case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;
+                        default: reason = "unknown reason"; break;
+                    }
+                    Slog.v(TAG, "  Filter did not match: " + reason);
+                }
+            }
+        }
+
+        if (dest.size() == 0 && hasNonDefaults) {
+            Slog.w(TAG, "resolveIntent failed: found match, but none with Intent.CATEGORY_DEFAULT");
+        }
+    }
+
+    // Sorts a List of IntentFilter objects into descending priority order.
+    @SuppressWarnings("rawtypes")
+    private static final Comparator mResolvePrioritySorter = new Comparator() {
+        public int compare(Object o1, Object o2) {
+            final int q1 = ((IntentFilter) o1).getPriority();
+            final int q2 = ((IntentFilter) o2).getPriority();
+            return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0);
+        }
+    };
+
+    /**
+     * All filters that have been registered.
+     */
+    final HashSet<F> mFilters = new HashSet<F>();
+
+    /**
+     * All of the MIME types that have been registered, such as "image/jpeg",
+     * "image/*", or "{@literal *}/*".
+     */
+    final HashMap<String, ArrayList<F>> mTypeToFilter
+            = new HashMap<String, ArrayList<F>>();
+
+    /**
+     * The base names of all of all fully qualified MIME types that have been
+     * registered, such as "image" or "*".  Wild card MIME types such as
+     * "image/*" will not be here.
+     */
+    final HashMap<String, ArrayList<F>> mBaseTypeToFilter
+            = new HashMap<String, ArrayList<F>>();
+
+    /**
+     * The base names of all of the MIME types with a sub-type wildcard that
+     * have been registered.  For example, a filter with "image/*" will be
+     * included here as "image" but one with "image/jpeg" will not be
+     * included here.  This also includes the "*" for the "{@literal *}/*"
+     * MIME type.
+     */
+    final HashMap<String, ArrayList<F>> mWildTypeToFilter
+            = new HashMap<String, ArrayList<F>>();
+
+    /**
+     * All of the URI schemes (such as http) that have been registered.
+     */
+    final HashMap<String, ArrayList<F>> mSchemeToFilter
+            = new HashMap<String, ArrayList<F>>();
+
+    /**
+     * All of the actions that have been registered, but only those that did
+     * not specify data.
+     */
+    final HashMap<String, ArrayList<F>> mActionToFilter
+            = new HashMap<String, ArrayList<F>>();
+
+    /**
+     * All of the actions that have been registered and specified a MIME type.
+     */
+    final HashMap<String, ArrayList<F>> mTypedActionToFilter
+            = new HashMap<String, ArrayList<F>>();
+}
+
diff --git a/services/java/com/android/server/LightsService.java b/services/java/com/android/server/LightsService.java
index 1e95f3e..89bfcac 100644
--- a/services/java/com/android/server/LightsService.java
+++ b/services/java/com/android/server/LightsService.java
@@ -31,29 +31,29 @@
     private static final String TAG = "LightsService";
     private static final boolean DEBUG = false;
 
-    static final int LIGHT_ID_BACKLIGHT = 0;
-    static final int LIGHT_ID_KEYBOARD = 1;
-    static final int LIGHT_ID_BUTTONS = 2;
-    static final int LIGHT_ID_BATTERY = 3;
-    static final int LIGHT_ID_NOTIFICATIONS = 4;
-    static final int LIGHT_ID_ATTENTION = 5;
-    static final int LIGHT_ID_BLUETOOTH = 6;
-    static final int LIGHT_ID_WIFI = 7;
-    static final int LIGHT_ID_COUNT = 8;
+    public static final int LIGHT_ID_BACKLIGHT = 0;
+    public static final int LIGHT_ID_KEYBOARD = 1;
+    public static final int LIGHT_ID_BUTTONS = 2;
+    public static final int LIGHT_ID_BATTERY = 3;
+    public static final int LIGHT_ID_NOTIFICATIONS = 4;
+    public static final int LIGHT_ID_ATTENTION = 5;
+    public static final int LIGHT_ID_BLUETOOTH = 6;
+    public static final int LIGHT_ID_WIFI = 7;
+    public static final int LIGHT_ID_COUNT = 8;
 
-    static final int LIGHT_FLASH_NONE = 0;
-    static final int LIGHT_FLASH_TIMED = 1;
-    static final int LIGHT_FLASH_HARDWARE = 2;
+    public static final int LIGHT_FLASH_NONE = 0;
+    public static final int LIGHT_FLASH_TIMED = 1;
+    public static final int LIGHT_FLASH_HARDWARE = 2;
 
     /**
      * Light brightness is managed by a user setting.
      */
-    static final int BRIGHTNESS_MODE_USER = 0;
+    public static final int BRIGHTNESS_MODE_USER = 0;
 
     /**
      * Light brightness is managed by a light sensor.
      */
-    static final int BRIGHTNESS_MODE_SENSOR = 1;
+    public static final int BRIGHTNESS_MODE_SENSOR = 1;
 
     private final Light mLights[] = new Light[LIGHT_ID_COUNT];
 
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 8c1581c..89fa6d0 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -16,27 +16,24 @@
 
 package com.android.server;
 
-import android.app.Activity;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentQueryMap;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
 import android.content.pm.Signature;
 import android.content.res.Resources;
 import android.database.ContentObserver;
-import android.database.Cursor;
 import android.location.Address;
 import android.location.Criteria;
 import android.location.GeocoderParams;
+import android.location.Geofence;
 import android.location.IGpsStatusListener;
 import android.location.IGpsStatusProvider;
 import android.location.ILocationListener;
@@ -45,9 +42,7 @@
 import android.location.Location;
 import android.location.LocationManager;
 import android.location.LocationProvider;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.net.Uri;
+import android.location.LocationRequest;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -57,17 +52,21 @@
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.util.Log;
 import android.util.Slog;
-import android.util.PrintWriterPrinter;
 
 import com.android.internal.content.PackageMonitor;
-import com.android.internal.location.GpsNetInitiatedHandler;
-
+import com.android.internal.location.ProviderProperties;
+import com.android.internal.location.ProviderRequest;
 import com.android.server.location.GeocoderProxy;
+import com.android.server.location.GeofenceManager;
 import com.android.server.location.GpsLocationProvider;
+import com.android.server.location.LocationBlacklist;
+import com.android.server.location.LocationFudger;
 import com.android.server.location.LocationProviderInterface;
 import com.android.server.location.LocationProviderProxy;
 import com.android.server.location.MockProvider;
@@ -76,169 +75,380 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.Observable;
-import java.util.Observer;
 import java.util.Set;
 
 /**
  * The service class that manages LocationProviders and issues location
  * updates and alerts.
- *
- * {@hide}
  */
 public class LocationManagerService extends ILocationManager.Stub implements Runnable {
     private static final String TAG = "LocationManagerService";
-    private static final boolean LOCAL_LOGV = false;
+    public static final boolean D = false;
 
-    // The last time a location was written, by provider name.
-    private HashMap<String,Long> mLastWriteTime = new HashMap<String,Long>();
+    private static final String WAKELOCK_KEY = TAG;
+    private static final String THREAD_NAME = TAG;
 
-    private static final String ACCESS_FINE_LOCATION =
-        android.Manifest.permission.ACCESS_FINE_LOCATION;
-    private static final String ACCESS_COARSE_LOCATION =
-        android.Manifest.permission.ACCESS_COARSE_LOCATION;
+    // Location resolution level: no location data whatsoever
+    private static final int RESOLUTION_LEVEL_NONE = 0;
+    // Location resolution level: coarse location data only
+    private static final int RESOLUTION_LEVEL_COARSE = 1;
+    // Location resolution level: fine location data
+    private static final int RESOLUTION_LEVEL_FINE = 2;
+
     private static final String ACCESS_MOCK_LOCATION =
-        android.Manifest.permission.ACCESS_MOCK_LOCATION;
+            android.Manifest.permission.ACCESS_MOCK_LOCATION;
     private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
-        android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
+            android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
     private static final String INSTALL_LOCATION_PROVIDER =
-        android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
+            android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
 
-    private static final String BLACKLIST_CONFIG_NAME = "locationPackagePrefixBlacklist";
-    private static final String WHITELIST_CONFIG_NAME = "locationPackagePrefixWhitelist";
+    private static final String NETWORK_LOCATION_SERVICE_ACTION =
+            "com.android.location.service.v2.NetworkLocationProvider";
+    private static final String FUSED_LOCATION_SERVICE_ACTION =
+            "com.android.location.service.FusedLocationProvider";
+
+    private static final int MSG_LOCATION_CHANGED = 1;
 
     // Location Providers may sometimes deliver location updates
     // slightly faster that requested - provide grace period so
     // we don't unnecessarily filter events that are otherwise on
     // time
-    private static final int MAX_PROVIDER_SCHEDULING_JITTER = 100;
+    private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
 
+    private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
+
+    private final Context mContext;
+
+    // used internally for synchronization
+    private final Object mLock = new Object();
+
+    // --- fields below are final after init() ---
+    private LocationFudger mLocationFudger;
+    private GeofenceManager mGeofenceManager;
+    private PowerManager.WakeLock mWakeLock;
+    private PackageManager mPackageManager;
+    private GeocoderProxy mGeocodeProvider;
+    private IGpsStatusProvider mGpsStatusProvider;
+    private INetInitiatedListener mNetInitiatedListener;
+    private LocationWorkerHandler mLocationHandler;
+    private PassiveProvider mPassiveProvider;  // track passive provider for special cases
+    private LocationBlacklist mBlacklist;
+
+    // --- fields below are protected by mWakeLock ---
+    private int mPendingBroadcasts;
+
+    // --- fields below are protected by mLock ---
     // Set of providers that are explicitly enabled
     private final Set<String> mEnabledProviders = new HashSet<String>();
 
     // Set of providers that are explicitly disabled
     private final Set<String> mDisabledProviders = new HashSet<String>();
 
-    // Locations, status values, and extras for mock providers
-    private final HashMap<String,MockProvider> mMockProviders = new HashMap<String,MockProvider>();
+    // Mock (test) providers
+    private final HashMap<String, MockProvider> mMockProviders =
+            new HashMap<String, MockProvider>();
 
-    private static boolean sProvidersLoaded = false;
-
-    private final Context mContext;
-    private PackageManager mPackageManager;  // final after initialize()
-    private String mNetworkLocationProviderPackageName;  // only used on handler thread
-    private String mGeocodeProviderPackageName;  // only used on handler thread
-    private GeocoderProxy mGeocodeProvider;
-    private IGpsStatusProvider mGpsStatusProvider;
-    private INetInitiatedListener mNetInitiatedListener;
-    private LocationWorkerHandler mLocationHandler;
-
-    // Cache the real providers for use in addTestProvider() and removeTestProvider()
-     LocationProviderProxy mNetworkLocationProvider;
-     LocationProviderInterface mGpsLocationProvider;
-
-    // Handler messages
-    private static final int MESSAGE_LOCATION_CHANGED = 1;
-    private static final int MESSAGE_PACKAGE_UPDATED = 2;
-
-    // wakelock variables
-    private final static String WAKELOCK_KEY = "LocationManagerService";
-    private PowerManager.WakeLock mWakeLock = null;
-    private int mPendingBroadcasts;
-    
-    /**
-     * List of all receivers.
-     */
+    // all receivers
     private final HashMap<Object, Receiver> mReceivers = new HashMap<Object, Receiver>();
 
-
-    /**
-     * List of location providers.
-     */
+    // currently installed providers (with mocks replacing real providers)
     private final ArrayList<LocationProviderInterface> mProviders =
-        new ArrayList<LocationProviderInterface>();
-    private final HashMap<String, LocationProviderInterface> mProvidersByName
-        = new HashMap<String, LocationProviderInterface>();
+            new ArrayList<LocationProviderInterface>();
+
+    // real providers, saved here when mocked out
+    private final HashMap<String, LocationProviderInterface> mRealProviders =
+            new HashMap<String, LocationProviderInterface>();
+
+    // mapping from provider name to provider
+    private final HashMap<String, LocationProviderInterface> mProvidersByName =
+            new HashMap<String, LocationProviderInterface>();
+
+    // mapping from provider name to all its UpdateRecords
+    private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
+            new HashMap<String, ArrayList<UpdateRecord>>();
+
+    // mapping from provider name to last known location
+    private final HashMap<String, Location> mLastLocation = new HashMap<String, Location>();
+
+    // all providers that operate over proxy, for authorizing incoming location
+    private final ArrayList<LocationProviderProxy> mProxyProviders =
+            new ArrayList<LocationProviderProxy>();
+
+    // current active user on the device - other users are denied location data
+    private int mCurrentUserId = UserHandle.USER_OWNER;
+
+    public LocationManagerService(Context context) {
+        super();
+        mContext = context;
+
+        if (D) Log.d(TAG, "Constructed");
+
+        // most startup is deferred until systemReady()
+    }
+
+    public void systemReady() {
+        Thread thread = new Thread(null, this, THREAD_NAME);
+        thread.start();
+    }
+
+    @Override
+    public void run() {
+        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+        Looper.prepare();
+        mLocationHandler = new LocationWorkerHandler();
+        init();
+        Looper.loop();
+    }
+
+    private void init() {
+        if (D) Log.d(TAG, "init()");
+
+        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
+        mPackageManager = mContext.getPackageManager();
+
+        mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
+        mBlacklist.init();
+        mLocationFudger = new LocationFudger(mContext, mLocationHandler);
+
+        synchronized (mLock) {
+            loadProvidersLocked();
+        }
+
+        mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
+
+        // listen for settings changes
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
+                new ContentObserver(mLocationHandler) {
+           @Override
+            public void onChange(boolean selfChange) {
+               synchronized (mLock) {
+                   updateProvidersLocked();
+               }
+            }
+        }, UserHandle.USER_ALL);
+        mPackageMonitor.register(mContext, Looper.myLooper(), true);
+
+        // listen for user change
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
+
+        mContext.registerReceiverAsUser(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                String action = intent.getAction();
+                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                    switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+                }
+            }
+        }, UserHandle.ALL, intentFilter, null, null);
+
+        updateProvidersLocked();
+    }
+
+    private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
+        PackageManager pm = mContext.getPackageManager();
+        String systemPackageName = mContext.getPackageName();
+        ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
+
+        List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
+                new Intent(FUSED_LOCATION_SERVICE_ACTION),
+                PackageManager.GET_META_DATA, mCurrentUserId);
+        for (ResolveInfo rInfo : rInfos) {
+            String packageName = rInfo.serviceInfo.packageName;
+
+            // Check that the signature is in the list of supported sigs. If it's not in
+            // this list the standard provider binding logic won't bind to it.
+            try {
+                PackageInfo pInfo;
+                pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
+                if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
+                    Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
+                            ", but has wrong signature, ignoring");
+                    continue;
+                }
+            } catch (NameNotFoundException e) {
+                Log.e(TAG, "missing package: " + packageName);
+                continue;
+            }
+
+            // Get the version info
+            if (rInfo.serviceInfo.metaData == null) {
+                Log.w(TAG, "Found fused provider without metadata: " + packageName);
+                continue;
+            }
+
+            int version = rInfo.serviceInfo.metaData.getInt(
+                    ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
+            if (version == 0) {
+                // This should be the fallback fused location provider.
+
+                // Make sure it's in the system partition.
+                if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+                    if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
+                    continue;
+                }
+
+                // Check that the fallback is signed the same as the OS
+                // as a proxy for coreApp="true"
+                if (pm.checkSignatures(systemPackageName, packageName)
+                        != PackageManager.SIGNATURE_MATCH) {
+                    if (D) Log.d(TAG, "Fallback candidate not signed the same as system: "
+                            + packageName);
+                    continue;
+                }
+
+                // Found a valid fallback.
+                if (D) Log.d(TAG, "Found fallback provider: " + packageName);
+                return;
+            } else {
+                if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
+            }
+        }
+
+        throw new IllegalStateException("Unable to find a fused location provider that is in the "
+                + "system partition with version 0 and signed with the platform certificate. "
+                + "Such a package is needed to provide a default fused location provider in the "
+                + "event that no other fused location provider has been installed or is currently "
+                + "available. For example, coreOnly boot mode when decrypting the data "
+                + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
+    }
+
+    private void loadProvidersLocked() {
+        // create a passive location provider, which is always enabled
+        PassiveProvider passiveProvider = new PassiveProvider(this);
+        addProviderLocked(passiveProvider);
+        mEnabledProviders.add(passiveProvider.getName());
+        mPassiveProvider = passiveProvider;
+
+        if (GpsLocationProvider.isSupported()) {
+            // Create a gps location provider
+            GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
+            mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
+            mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
+            addProviderLocked(gpsProvider);
+            mRealProviders.put(LocationManager.GPS_PROVIDER, gpsProvider);
+        }
+
+        /*
+        Load package name(s) containing location provider support.
+        These packages can contain services implementing location providers:
+        Geocoder Provider, Network Location Provider, and
+        Fused Location Provider. They will each be searched for
+        service components implementing these providers.
+        The location framework also has support for installation
+        of new location providers at run-time. The new package does not
+        have to be explicitly listed here, however it must have a signature
+        that matches the signature of at least one package on this list.
+        */
+        Resources resources = mContext.getResources();
+        ArrayList<String> providerPackageNames = new ArrayList<String>();
+        String[] pkgs = resources.getStringArray(
+                com.android.internal.R.array.config_locationProviderPackageNames);
+        if (D) Log.d(TAG, "certificates for location providers pulled from: " +
+                Arrays.toString(pkgs));
+        if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
+
+        ensureFallbackFusedProviderPresentLocked(providerPackageNames);
+
+        // bind to network provider
+        LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
+                mContext,
+                LocationManager.NETWORK_PROVIDER,
+                NETWORK_LOCATION_SERVICE_ACTION,
+                providerPackageNames, mLocationHandler, mCurrentUserId);
+        if (networkProvider != null) {
+            mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
+            mProxyProviders.add(networkProvider);
+            addProviderLocked(networkProvider);
+        } else {
+            Slog.w(TAG,  "no network location provider found");
+        }
+
+        // bind to fused provider
+        LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
+                mContext,
+                LocationManager.FUSED_PROVIDER,
+                FUSED_LOCATION_SERVICE_ACTION,
+                providerPackageNames, mLocationHandler, mCurrentUserId);
+        if (fusedLocationProvider != null) {
+            addProviderLocked(fusedLocationProvider);
+            mProxyProviders.add(fusedLocationProvider);
+            mEnabledProviders.add(fusedLocationProvider.getName());
+            mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
+        } else {
+            Slog.e(TAG, "no fused location provider found",
+                    new IllegalStateException("Location service needs a fused location provider"));
+        }
+
+        // bind to geocoder provider
+        mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames,
+                mCurrentUserId);
+        if (mGeocodeProvider == null) {
+            Slog.e(TAG,  "no geocoder provider found");
+        }
+    }
 
     /**
-     * Object used internally for synchronization
+     * Called when the device's active user changes.
+     * @param userId the new active user's UserId
      */
-    private final Object mLock = new Object();
-
-    /**
-     * Mapping from provider name to all its UpdateRecords
-     */
-    private final HashMap<String,ArrayList<UpdateRecord>> mRecordsByProvider =
-        new HashMap<String,ArrayList<UpdateRecord>>();
-
-    /**
-     * Temporary filled in when computing min time for a provider.  Access is
-     * protected by global lock mLock.
-     */
-    private final WorkSource mTmpWorkSource = new WorkSource();
-
-    // Proximity listeners
-    private Receiver mProximityReceiver = null;
-    private ILocationListener mProximityListener = null;
-    private HashMap<PendingIntent,ProximityAlert> mProximityAlerts =
-        new HashMap<PendingIntent,ProximityAlert>();
-    private HashSet<ProximityAlert> mProximitiesEntered =
-        new HashSet<ProximityAlert>();
-
-    // Last known location for each provider
-    private HashMap<String,Location> mLastKnownLocation =
-        new HashMap<String,Location>();
-
-    private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
-
-    // for prefix blacklist
-    private String[] mWhitelist = new String[0];
-    private String[] mBlacklist = new String[0];
-
-    // for Settings change notification
-    private ContentQueryMap mSettings;
+    private void switchUser(int userId) {
+        mBlacklist.switchUser(userId);
+        synchronized (mLock) {
+            mLastLocation.clear();
+            for (LocationProviderInterface p : mProviders) {
+                updateProviderListenersLocked(p.getName(), false, mCurrentUserId);
+                p.switchUser(userId);
+            }
+            mCurrentUserId = userId;
+            updateProvidersLocked();
+        }
+    }
 
     /**
      * A wrapper class holding either an ILocationListener or a PendingIntent to receive
      * location updates.
      */
     private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
+        final int mUid;  // uid of receiver
+        final int mPid;  // pid of receiver
+        final String mPackageName;  // package name of receiver
+        final int mAllowedResolutionLevel;  // resolution level allowed to receiver
+
         final ILocationListener mListener;
         final PendingIntent mPendingIntent;
         final Object mKey;
+
         final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
-        final String mPackageName;
 
         int mPendingBroadcasts;
-        String mRequiredPermissions;
 
-        Receiver(ILocationListener listener, String packageName) {
+        Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
+                String packageName) {
             mListener = listener;
-            mPendingIntent = null;
-            mKey = listener.asBinder();
-            mPackageName = packageName;
-        }
-
-        Receiver(PendingIntent intent, String packageName) {
             mPendingIntent = intent;
-            mListener = null;
-            mKey = intent;
+            if (listener != null) {
+                mKey = listener.asBinder();
+            } else {
+                mKey = intent;
+            }
+            mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
+            mUid = uid;
+            mPid = pid;
             mPackageName = packageName;
         }
 
         @Override
         public boolean equals(Object otherObj) {
             if (otherObj instanceof Receiver) {
-                return mKey.equals(
-                        ((Receiver)otherObj).mKey);
+                return mKey.equals(((Receiver)otherObj).mKey);
             }
             return false;
         }
@@ -250,18 +460,19 @@
 
         @Override
         public String toString() {
-            String result;
+            StringBuilder s = new StringBuilder();
+            s.append("Reciever[");
+            s.append(Integer.toHexString(System.identityHashCode(this)));
             if (mListener != null) {
-                result = "Receiver{"
-                        + Integer.toHexString(System.identityHashCode(this))
-                        + " Listener " + mKey + "}";
+                s.append(" listener");
             } else {
-                result = "Receiver{"
-                        + Integer.toHexString(System.identityHashCode(this))
-                        + " Intent " + mKey + "}";
+                s.append(" intent");
             }
-            result += "mUpdateRecords: " + mUpdateRecords;
-            return result;
+            for (String p : mUpdateRecords.keySet()) {
+                s.append(" ").append(mUpdateRecords.get(p).toString());
+            }
+            s.append("]");
+            return s.toString();
         }
 
         public boolean isListener() {
@@ -279,13 +490,6 @@
             throw new IllegalStateException("Request for non-existent listener");
         }
 
-        public PendingIntent getPendingIntent() {
-            if (mPendingIntent != null) {
-                return mPendingIntent;
-            }
-            throw new IllegalStateException("Request for non-existent intent");
-        }
-
         public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
             if (mListener != null) {
                 try {
@@ -293,11 +497,9 @@
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
                         mListener.onStatusChanged(provider, status, extras);
-                        if (mListener != mProximityListener) {
-                            // call this after broadcasting so we do not increment
-                            // if we throw an exeption.
-                            incrementPendingBroadcastsLocked();
-                        }
+                        // call this after broadcasting so we do not increment
+                        // if we throw an exeption.
+                        incrementPendingBroadcastsLocked();
                     }
                 } catch (RemoteException e) {
                     return false;
@@ -311,7 +513,7 @@
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
                         mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
-                                mRequiredPermissions);
+                                getResolutionPermission(mAllowedResolutionLevel));
                         // call this after broadcasting so we do not increment
                         // if we throw an exeption.
                         incrementPendingBroadcastsLocked();
@@ -330,11 +532,9 @@
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
                         mListener.onLocationChanged(location);
-                        if (mListener != mProximityListener) {
-                            // call this after broadcasting so we do not increment
-                            // if we throw an exeption.
-                            incrementPendingBroadcastsLocked();
-                        }
+                        // call this after broadcasting so we do not increment
+                        // if we throw an exeption.
+                        incrementPendingBroadcastsLocked();
                     }
                 } catch (RemoteException e) {
                     return false;
@@ -347,7 +547,7 @@
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
                         mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
-                                mRequiredPermissions);
+                                getResolutionPermission(mAllowedResolutionLevel));
                         // call this after broadcasting so we do not increment
                         // if we throw an exeption.
                         incrementPendingBroadcastsLocked();
@@ -370,11 +570,9 @@
                         } else {
                             mListener.onProviderDisabled(provider);
                         }
-                        if (mListener != mProximityListener) {
-                            // call this after broadcasting so we do not increment
-                            // if we throw an exeption.
-                            incrementPendingBroadcastsLocked();
-                        }
+                        // call this after broadcasting so we do not increment
+                        // if we throw an exeption.
+                        incrementPendingBroadcastsLocked();
                     }
                 } catch (RemoteException e) {
                     return false;
@@ -387,7 +585,7 @@
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
                         mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
-                                mRequiredPermissions);
+                                getResolutionPermission(mAllowedResolutionLevel));
                         // call this after broadcasting so we do not increment
                         // if we throw an exeption.
                         incrementPendingBroadcastsLocked();
@@ -401,9 +599,8 @@
 
         @Override
         public void binderDied() {
-            if (LOCAL_LOGV) {
-                Slog.v(TAG, "Location listener died");
-            }
+            if (D) Log.d(TAG, "Location listener died");
+
             synchronized (mLock) {
                 removeUpdatesLocked(this);
             }
@@ -415,6 +612,7 @@
             }
         }
 
+        @Override
         public void onSendFinished(PendingIntent pendingIntent, Intent intent,
                 int resultCode, String resultData, Bundle resultExtras) {
             synchronized (this) {
@@ -437,6 +635,7 @@
         }
     }
 
+    @Override
     public void locationCallbackFinished(ILocationListener listener) {
         //Do not use getReceiver here as that will add the ILocationListener to
         //the receiver list if it is not found.  If it is not found then the
@@ -454,200 +653,22 @@
         }
     }
 
-    private final class SettingsObserver implements Observer {
-        public void update(Observable o, Object arg) {
-            synchronized (mLock) {
-                updateProvidersLocked();
-            }
-        }
-    }
-
-    private void addProvider(LocationProviderInterface provider) {
+    private void addProviderLocked(LocationProviderInterface provider) {
         mProviders.add(provider);
         mProvidersByName.put(provider.getName(), provider);
     }
 
-    private void removeProvider(LocationProviderInterface provider) {
+    private void removeProviderLocked(LocationProviderInterface provider) {
+        provider.disable();
         mProviders.remove(provider);
         mProvidersByName.remove(provider.getName());
     }
 
-    private void loadProviders() {
-        synchronized (mLock) {
-            if (sProvidersLoaded) {
-                return;
-            }
 
-            // Load providers
-            loadProvidersLocked();
-            sProvidersLoaded = true;
+    private boolean isAllowedBySettingsLocked(String provider, int userId) {
+        if (userId != mCurrentUserId) {
+            return false;
         }
-    }
-
-    private void loadProvidersLocked() {
-        try {
-            _loadProvidersLocked();
-        } catch (Exception e) {
-            Slog.e(TAG, "Exception loading providers:", e);
-        }
-    }
-
-    private void _loadProvidersLocked() {
-        // Attempt to load "real" providers first
-        if (GpsLocationProvider.isSupported()) {
-            // Create a gps location provider
-            GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
-            mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
-            mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
-            addProvider(gpsProvider);
-            mGpsLocationProvider = gpsProvider;
-        }
-
-        // create a passive location provider, which is always enabled
-        PassiveProvider passiveProvider = new PassiveProvider(this);
-        addProvider(passiveProvider);
-        mEnabledProviders.add(passiveProvider.getName());
-
-        // initialize external network location and geocoder services.
-        // The initial value of mNetworkLocationProviderPackageName and
-        // mGeocodeProviderPackageName is just used to determine what
-        // signatures future mNetworkLocationProviderPackageName and
-        // mGeocodeProviderPackageName packages must have. So alternate
-        // providers can be installed under a different package name
-        // so long as they have the same signature as the original
-        // provider packages.
-        if (mNetworkLocationProviderPackageName != null) {
-            String packageName = findBestPackage(LocationProviderProxy.SERVICE_ACTION,
-                    mNetworkLocationProviderPackageName);
-            if (packageName != null) {
-                mNetworkLocationProvider = new LocationProviderProxy(mContext,
-                        LocationManager.NETWORK_PROVIDER,
-                        packageName, mLocationHandler);
-                mNetworkLocationProviderPackageName = packageName;
-                addProvider(mNetworkLocationProvider);
-            }
-        }
-        if (mGeocodeProviderPackageName != null) {
-            String packageName = findBestPackage(GeocoderProxy.SERVICE_ACTION,
-                    mGeocodeProviderPackageName);
-            if (packageName != null) {
-                mGeocodeProvider = new GeocoderProxy(mContext, packageName);
-                mGeocodeProviderPackageName = packageName;
-            }
-        }
-
-        updateProvidersLocked();
-    }
-
-    /**
-     * Pick the best (network location provider or geocode provider) package.
-     * The best package:
-     * - implements serviceIntentName
-     * - has signatures that match that of sigPackageName
-     * - has the highest version value in a meta-data field in the service component
-     */
-    String findBestPackage(String serviceIntentName, String sigPackageName) {
-        Intent intent = new Intent(serviceIntentName);
-        List<ResolveInfo> infos = mPackageManager.queryIntentServices(intent,
-                PackageManager.GET_META_DATA);
-        if (infos == null) return null;
-
-        int bestVersion = Integer.MIN_VALUE;
-        String bestPackage = null;
-        for (ResolveInfo info : infos) {
-            String packageName = info.serviceInfo.packageName;
-            // check signature
-            if (mPackageManager.checkSignatures(packageName, sigPackageName) !=
-                    PackageManager.SIGNATURE_MATCH) {
-                Slog.w(TAG, packageName + " implements " + serviceIntentName +
-                       " but its signatures don't match those in " + sigPackageName +
-                       ", ignoring");
-                continue;
-            }
-            // read version
-            int version = 0;
-            if (info.serviceInfo.metaData != null) {
-                version = info.serviceInfo.metaData.getInt("version", 0);
-            }
-            if (LOCAL_LOGV) Slog.v(TAG, packageName + " implements " + serviceIntentName +
-                    " with version " + version);
-            if (version > bestVersion) {
-                bestVersion = version;
-                bestPackage = packageName;
-            }
-        }
-
-        return bestPackage;
-    }
-
-    /**
-     * @param context the context that the LocationManagerService runs in
-     */
-    public LocationManagerService(Context context) {
-        super();
-        mContext = context;
-        Resources resources = context.getResources();
-
-        mNetworkLocationProviderPackageName = resources.getString(
-                com.android.internal.R.string.config_networkLocationProviderPackageName);
-        mGeocodeProviderPackageName = resources.getString(
-                com.android.internal.R.string.config_geocodeProviderPackageName);
-
-        mPackageMonitor.register(context, null, true);
-
-        if (LOCAL_LOGV) {
-            Slog.v(TAG, "Constructed LocationManager Service");
-        }
-    }
-
-    void systemReady() {
-        // we defer starting up the service until the system is ready 
-        Thread thread = new Thread(null, this, "LocationManagerService");
-        thread.start();
-    }
-
-    private void initialize() {
-        // Create a wake lock, needs to be done before calling loadProviders() below
-        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
-        mPackageManager = mContext.getPackageManager();
-
-        // Load providers
-        loadProviders();
-        loadBlacklist();
-
-        // Register for Network (Wifi or Mobile) updates
-        IntentFilter intentFilter = new IntentFilter();
-        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
-        // Register for Package Manager updates
-        intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-        intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
-        intentFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
-        mContext.registerReceiver(mBroadcastReceiver, intentFilter);
-        IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
-        mContext.registerReceiver(mBroadcastReceiver, sdFilter);
-
-        // listen for settings changes
-        ContentResolver resolver = mContext.getContentResolver();
-        Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI, null,
-                "(" + Settings.System.NAME + "=?)",
-                new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
-                null);
-        mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler);
-        SettingsObserver settingsObserver = new SettingsObserver();
-        mSettings.addObserver(settingsObserver);
-    }
-
-    public void run()
-    {
-        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-        Looper.prepare();
-        mLocationHandler = new LocationWorkerHandler();
-        initialize();
-        Looper.loop();
-    }
-
-    private boolean isAllowedBySettingsLocked(String provider) {
         if (mEnabledProviders.contains(provider)) {
             return true;
         }
@@ -657,320 +678,235 @@
         // Use system settings
         ContentResolver resolver = mContext.getContentResolver();
 
-        return Settings.Secure.isLocationProviderEnabled(resolver, provider);
+        return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId);
     }
 
-    private String checkPermissionsSafe(String provider, String lastPermission) {
-        if (LocationManager.GPS_PROVIDER.equals(provider)
-                 || LocationManager.PASSIVE_PROVIDER.equals(provider)) {
-            if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Provider " + provider
-                        + " requires ACCESS_FINE_LOCATION permission");
-            }
-            return ACCESS_FINE_LOCATION;
-        }
-
-        // Assume any other provider requires the coarse or fine permission.
-        if (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
-                == PackageManager.PERMISSION_GRANTED) {
-            return ACCESS_FINE_LOCATION.equals(lastPermission)
-                    ? lastPermission : ACCESS_COARSE_LOCATION;
-        }
-        if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
-                == PackageManager.PERMISSION_GRANTED) {
-            return ACCESS_FINE_LOCATION;
-        }
-
-        throw new SecurityException("Provider " + provider
-                + " requires ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission");
-    }
-
-    private boolean isAllowedProviderSafe(String provider) {
-        if ((LocationManager.GPS_PROVIDER.equals(provider)
-                || LocationManager.PASSIVE_PROVIDER.equals(provider))
-            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
-                != PackageManager.PERMISSION_GRANTED)) {
-            return false;
-        }
-        if (LocationManager.NETWORK_PROVIDER.equals(provider)
-            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
-                != PackageManager.PERMISSION_GRANTED)
-            && (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
-                != PackageManager.PERMISSION_GRANTED)) {
-            return false;
-        }
-
-        return true;
-    }
-
-    public List<String> getAllProviders() {
-        try {
-            synchronized (mLock) {
-                return _getAllProvidersLocked();
-            }
-        } catch (SecurityException se) {
-            throw se;
-        } catch (Exception e) {
-            Slog.e(TAG, "getAllProviders got exception:", e);
-            return null;
+    /**
+     * Returns the permission string associated with the specified resolution level.
+     *
+     * @param resolutionLevel the resolution level
+     * @return the permission string
+     */
+    private String getResolutionPermission(int resolutionLevel) {
+        switch (resolutionLevel) {
+            case RESOLUTION_LEVEL_FINE:
+                return android.Manifest.permission.ACCESS_FINE_LOCATION;
+            case RESOLUTION_LEVEL_COARSE:
+                return android.Manifest.permission.ACCESS_COARSE_LOCATION;
+            default:
+                return null;
         }
     }
 
-    private List<String> _getAllProvidersLocked() {
-        if (LOCAL_LOGV) {
-            Slog.v(TAG, "getAllProviders");
-        }
-        ArrayList<String> out = new ArrayList<String>(mProviders.size());
-        for (int i = mProviders.size() - 1; i >= 0; i--) {
-            LocationProviderInterface p = mProviders.get(i);
-            out.add(p.getName());
-        }
-        return out;
-    }
-
-    public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
-        try {
-            synchronized (mLock) {
-                return _getProvidersLocked(criteria, enabledOnly);
-            }
-        } catch (SecurityException se) {
-            throw se;
-        } catch (Exception e) {
-            Slog.e(TAG, "getProviders got exception:", e);
-            return null;
+    /**
+     * Returns the resolution level allowed to the given PID/UID pair.
+     *
+     * @param pid the PID
+     * @param uid the UID
+     * @return resolution level allowed to the pid/uid pair
+     */
+    private int getAllowedResolutionLevel(int pid, int uid) {
+        if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
+                pid, uid) == PackageManager.PERMISSION_GRANTED) {
+            return RESOLUTION_LEVEL_FINE;
+        } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
+                pid, uid) == PackageManager.PERMISSION_GRANTED) {
+            return RESOLUTION_LEVEL_COARSE;
+        } else {
+            return RESOLUTION_LEVEL_NONE;
         }
     }
 
-    private List<String> _getProvidersLocked(Criteria criteria, boolean enabledOnly) {
-        if (LOCAL_LOGV) {
-            Slog.v(TAG, "getProviders");
+    /**
+     * Returns the resolution level allowed to the caller
+     *
+     * @return resolution level allowed to caller
+     */
+    private int getCallerAllowedResolutionLevel() {
+        return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
+    }
+
+    /**
+     * Throw SecurityException if specified resolution level is insufficient to use geofences.
+     *
+     * @param allowedResolutionLevel resolution level allowed to caller
+     */
+    private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
+        if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
+            throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
         }
-        ArrayList<String> out = new ArrayList<String>(mProviders.size());
-        for (int i = mProviders.size() - 1; i >= 0; i--) {
-            LocationProviderInterface p = mProviders.get(i);
-            String name = p.getName();
-            if (isAllowedProviderSafe(name)) {
-                if (enabledOnly && !isAllowedBySettingsLocked(name)) {
-                    continue;
+    }
+
+    /**
+     * Return the minimum resolution level required to use the specified location provider.
+     *
+     * @param provider the name of the location provider
+     * @return minimum resolution level required for provider
+     */
+    private int getMinimumResolutionLevelForProviderUse(String provider) {
+        if (LocationManager.GPS_PROVIDER.equals(provider) ||
+                LocationManager.PASSIVE_PROVIDER.equals(provider)) {
+            // gps and passive providers require FINE permission
+            return RESOLUTION_LEVEL_FINE;
+        } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
+                LocationManager.FUSED_PROVIDER.equals(provider)) {
+            // network and fused providers are ok with COARSE or FINE
+            return RESOLUTION_LEVEL_COARSE;
+        } else {
+            // mock providers
+            LocationProviderInterface lp = mMockProviders.get(provider);
+            if (lp != null) {
+                ProviderProperties properties = lp.getProperties();
+                if (properties != null) {
+                    if (properties.mRequiresSatellite) {
+                        // provider requiring satellites require FINE permission
+                        return RESOLUTION_LEVEL_FINE;
+                    } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
+                        // provider requiring network and or cell require COARSE or FINE
+                        return RESOLUTION_LEVEL_COARSE;
+                    }
                 }
-                if (criteria != null && !p.meetsCriteria(criteria)) {
+            }
+        }
+        return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
+    }
+
+    /**
+     * Throw SecurityException if specified resolution level is insufficient to use the named
+     * location provider.
+     *
+     * @param allowedResolutionLevel resolution level allowed to caller
+     * @param providerName the name of the location provider
+     */
+    private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
+            String providerName) {
+        int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
+        if (allowedResolutionLevel < requiredResolutionLevel) {
+            switch (requiredResolutionLevel) {
+                case RESOLUTION_LEVEL_FINE:
+                    throw new SecurityException("\"" + providerName + "\" location provider " +
+                            "requires ACCESS_FINE_LOCATION permission.");
+                case RESOLUTION_LEVEL_COARSE:
+                    throw new SecurityException("\"" + providerName + "\" location provider " +
+                            "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
+                default:
+                    throw new SecurityException("Insufficient permission for \"" + providerName +
+                            "\" location provider.");
+            }
+        }
+    }
+
+    /**
+     * Returns all providers by name, including passive, but excluding
+     * fused, also including ones that are not permitted to
+     * be accessed by the calling activity or are currently disabled.
+     */
+    @Override
+    public List<String> getAllProviders() {
+        ArrayList<String> out;
+        synchronized (mLock) {
+            out = new ArrayList<String>(mProviders.size());
+            for (LocationProviderInterface provider : mProviders) {
+                String name = provider.getName();
+                if (LocationManager.FUSED_PROVIDER.equals(name)) {
                     continue;
                 }
                 out.add(name);
             }
         }
+
+        if (D) Log.d(TAG, "getAllProviders()=" + out);
         return out;
     }
 
     /**
-     * Returns the next looser power requirement, in the sequence:
-     *
-     * POWER_LOW -> POWER_MEDIUM -> POWER_HIGH -> NO_REQUIREMENT
+     * Return all providers by name, that match criteria and are optionally
+     * enabled.
+     * Can return passive provider, but never returns fused provider.
      */
-    private int nextPower(int power) {
-        switch (power) {
-        case Criteria.POWER_LOW:
-            return Criteria.POWER_MEDIUM;
-        case Criteria.POWER_MEDIUM:
-            return Criteria.POWER_HIGH;
-        case Criteria.POWER_HIGH:
-            return Criteria.NO_REQUIREMENT;
-        case Criteria.NO_REQUIREMENT:
-        default:
-            return Criteria.NO_REQUIREMENT;
-        }
-    }
-
-    /**
-     * Returns the next looser accuracy requirement, in the sequence:
-     *
-     * ACCURACY_FINE -> ACCURACY_APPROXIMATE-> NO_REQUIREMENT
-     */
-    private int nextAccuracy(int accuracy) {
-        if (accuracy == Criteria.ACCURACY_FINE) {
-            return Criteria.ACCURACY_COARSE;
-        } else {
-            return Criteria.NO_REQUIREMENT;
-        }
-    }
-
-    private class LpPowerComparator implements Comparator<LocationProviderInterface> {
-        public int compare(LocationProviderInterface l1, LocationProviderInterface l2) {
-            // Smaller is better
-            return (l1.getPowerRequirement() - l2.getPowerRequirement());
-         }
-
-         public boolean equals(LocationProviderInterface l1, LocationProviderInterface l2) {
-             return (l1.getPowerRequirement() == l2.getPowerRequirement());
-         }
-    }
-
-    private class LpAccuracyComparator implements Comparator<LocationProviderInterface> {
-        public int compare(LocationProviderInterface l1, LocationProviderInterface l2) {
-            // Smaller is better
-            return (l1.getAccuracy() - l2.getAccuracy());
-         }
-
-         public boolean equals(LocationProviderInterface l1, LocationProviderInterface l2) {
-             return (l1.getAccuracy() == l2.getAccuracy());
-         }
-    }
-
-    private class LpCapabilityComparator implements Comparator<LocationProviderInterface> {
-
-        private static final int ALTITUDE_SCORE = 4;
-        private static final int BEARING_SCORE = 4;
-        private static final int SPEED_SCORE = 4;
-
-        private int score(LocationProviderInterface p) {
-            return (p.supportsAltitude() ? ALTITUDE_SCORE : 0) +
-                (p.supportsBearing() ? BEARING_SCORE : 0) +
-                (p.supportsSpeed() ? SPEED_SCORE : 0);
-        }
-
-        public int compare(LocationProviderInterface l1, LocationProviderInterface l2) {
-            return (score(l2) - score(l1)); // Bigger is better
-         }
-
-         public boolean equals(LocationProviderInterface l1, LocationProviderInterface l2) {
-             return (score(l1) == score(l2));
-         }
-    }
-
-    private LocationProviderInterface best(List<String> providerNames) {
-        ArrayList<LocationProviderInterface> providers;
-        synchronized (mLock) {
-            providers = new ArrayList<LocationProviderInterface>(providerNames.size());
-            for (String name : providerNames) {
-                providers.add(mProvidersByName.get(name));
+    @Override
+    public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
+        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
+        ArrayList<String> out;
+        int callingUserId = UserHandle.getCallingUserId();
+        long identity = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                out = new ArrayList<String>(mProviders.size());
+                for (LocationProviderInterface provider : mProviders) {
+                    String name = provider.getName();
+                    if (LocationManager.FUSED_PROVIDER.equals(name)) {
+                        continue;
+                    }
+                    if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
+                        if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) {
+                            continue;
+                        }
+                        if (criteria != null && !LocationProvider.propertiesMeetCriteria(
+                                name, provider.getProperties(), criteria)) {
+                            continue;
+                        }
+                        out.add(name);
+                    }
+                }
             }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
 
-        if (providers.size() < 2) {
-            return providers.get(0);
-        }
-
-        // First, sort by power requirement
-        Collections.sort(providers, new LpPowerComparator());
-        int power = providers.get(0).getPowerRequirement();
-        if (power < providers.get(1).getPowerRequirement()) {
-            return providers.get(0);
-        }
-
-        int idx, size;
-
-        ArrayList<LocationProviderInterface> tmp = new ArrayList<LocationProviderInterface>();
-        idx = 0;
-        size = providers.size();
-        while ((idx < size) && (providers.get(idx).getPowerRequirement() == power)) {
-            tmp.add(providers.get(idx));
-            idx++;
-        }
-
-        // Next, sort by accuracy
-        Collections.sort(tmp, new LpAccuracyComparator());
-        int acc = tmp.get(0).getAccuracy();
-        if (acc < tmp.get(1).getAccuracy()) {
-            return tmp.get(0);
-        }
-
-        ArrayList<LocationProviderInterface> tmp2 = new ArrayList<LocationProviderInterface>();
-        idx = 0;
-        size = tmp.size();
-        while ((idx < size) && (tmp.get(idx).getAccuracy() == acc)) {
-            tmp2.add(tmp.get(idx));
-            idx++;
-        }
-
-        // Finally, sort by capability "score"
-        Collections.sort(tmp2, new LpCapabilityComparator());
-        return tmp2.get(0);
+        if (D) Log.d(TAG, "getProviders()=" + out);
+        return out;
     }
 
     /**
-     * Returns the name of the provider that best meets the given criteria. Only providers
-     * that are permitted to be accessed by the calling activity will be
-     * returned.  If several providers meet the criteria, the one with the best
-     * accuracy is returned.  If no provider meets the criteria,
-     * the criteria are loosened in the following sequence:
-     *
-     * <ul>
-     * <li> power requirement
-     * <li> accuracy
-     * <li> bearing
-     * <li> speed
-     * <li> altitude
-     * </ul>
-     *
-     * <p> Note that the requirement on monetary cost is not removed
-     * in this process.
-     *
-     * @param criteria the criteria that need to be matched
-     * @param enabledOnly if true then only a provider that is currently enabled is returned
-     * @return name of the provider that best matches the requirements
+     * Return the name of the best provider given a Criteria object.
+     * This method has been deprecated from the public API,
+     * and the whole LocationProvider (including #meetsCriteria)
+     * has been deprecated as well. So this method now uses
+     * some simplified logic.
      */
+    @Override
     public String getBestProvider(Criteria criteria, boolean enabledOnly) {
-        List<String> goodProviders = getProviders(criteria, enabledOnly);
-        if (!goodProviders.isEmpty()) {
-            return best(goodProviders).getName();
+        String result = null;
+
+        List<String> providers = getProviders(criteria, enabledOnly);
+        if (!providers.isEmpty()) {
+            result = pickBest(providers);
+            if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
+            return result;
+        }
+        providers = getProviders(null, enabledOnly);
+        if (!providers.isEmpty()) {
+            result = pickBest(providers);
+            if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
+            return result;
         }
 
-        // Make a copy of the criteria that we can modify
-        criteria = new Criteria(criteria);
-
-        // Loosen power requirement
-        int power = criteria.getPowerRequirement();
-        while (goodProviders.isEmpty() && (power != Criteria.NO_REQUIREMENT)) {
-            power = nextPower(power);
-            criteria.setPowerRequirement(power);
-            goodProviders = getProviders(criteria, enabledOnly);
-        }
-        if (!goodProviders.isEmpty()) {
-            return best(goodProviders).getName();
-        }
-
-        // Loosen accuracy requirement
-        int accuracy = criteria.getAccuracy();
-        while (goodProviders.isEmpty() && (accuracy != Criteria.NO_REQUIREMENT)) {
-            accuracy = nextAccuracy(accuracy);
-            criteria.setAccuracy(accuracy);
-            goodProviders = getProviders(criteria, enabledOnly);
-        }
-        if (!goodProviders.isEmpty()) {
-            return best(goodProviders).getName();
-        }
-
-        // Remove bearing requirement
-        criteria.setBearingRequired(false);
-        goodProviders = getProviders(criteria, enabledOnly);
-        if (!goodProviders.isEmpty()) {
-            return best(goodProviders).getName();
-        }
-
-        // Remove speed requirement
-        criteria.setSpeedRequired(false);
-        goodProviders = getProviders(criteria, enabledOnly);
-        if (!goodProviders.isEmpty()) {
-            return best(goodProviders).getName();
-        }
-
-        // Remove altitude requirement
-        criteria.setAltitudeRequired(false);
-        goodProviders = getProviders(criteria, enabledOnly);
-        if (!goodProviders.isEmpty()) {
-            return best(goodProviders).getName();
-        }
-
+        if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
         return null;
     }
 
+    private String pickBest(List<String> providers) {
+        if (providers.contains(LocationManager.GPS_PROVIDER)) {
+            return LocationManager.GPS_PROVIDER;
+        } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
+            return LocationManager.NETWORK_PROVIDER;
+        } else {
+            return providers.get(0);
+        }
+    }
+
+    @Override
     public boolean providerMeetsCriteria(String provider, Criteria criteria) {
         LocationProviderInterface p = mProvidersByName.get(provider);
         if (p == null) {
             throw new IllegalArgumentException("provider=" + provider);
         }
-        return p.meetsCriteria(criteria);
+
+        boolean result = LocationProvider.propertiesMeetCriteria(
+                p.getName(), p.getProperties(), criteria);
+        if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
+        return result;
     }
 
     private void updateProvidersLocked() {
@@ -979,108 +915,119 @@
             LocationProviderInterface p = mProviders.get(i);
             boolean isEnabled = p.isEnabled();
             String name = p.getName();
-            boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
+            boolean shouldBeEnabled = isAllowedBySettingsLocked(name, mCurrentUserId);
             if (isEnabled && !shouldBeEnabled) {
-                updateProviderListenersLocked(name, false);
+                updateProviderListenersLocked(name, false, mCurrentUserId);
                 changesMade = true;
             } else if (!isEnabled && shouldBeEnabled) {
-                updateProviderListenersLocked(name, true);
+                updateProviderListenersLocked(name, true, mCurrentUserId);
                 changesMade = true;
             }
         }
         if (changesMade) {
-            mContext.sendBroadcast(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION));
+            mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
+                    UserHandle.ALL);
         }
     }
 
-    private void updateProviderListenersLocked(String provider, boolean enabled) {
+    private void updateProviderListenersLocked(String provider, boolean enabled, int userId) {
         int listeners = 0;
 
         LocationProviderInterface p = mProvidersByName.get(provider);
-        if (p == null) {
-            return;
-        }
+        if (p == null) return;
 
         ArrayList<Receiver> deadReceivers = null;
-        
+
         ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
         if (records != null) {
             final int N = records.size();
-            for (int i=0; i<N; i++) {
+            for (int i = 0; i < N; i++) {
                 UpdateRecord record = records.get(i);
-                // Sends a notification message to the receiver
-                if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
-                    if (deadReceivers == null) {
-                        deadReceivers = new ArrayList<Receiver>();
+                if (UserHandle.getUserId(record.mReceiver.mUid) == userId) {
+                    // Sends a notification message to the receiver
+                    if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
+                        if (deadReceivers == null) {
+                            deadReceivers = new ArrayList<Receiver>();
+                        }
+                        deadReceivers.add(record.mReceiver);
                     }
-                    deadReceivers.add(record.mReceiver);
+                    listeners++;
                 }
-                listeners++;
             }
         }
 
         if (deadReceivers != null) {
-            for (int i=deadReceivers.size()-1; i>=0; i--) {
+            for (int i = deadReceivers.size() - 1; i >= 0; i--) {
                 removeUpdatesLocked(deadReceivers.get(i));
             }
         }
-        
+
         if (enabled) {
             p.enable();
             if (listeners > 0) {
-                p.setMinTime(getMinTimeLocked(provider), mTmpWorkSource);
-                p.enableLocationTracking(true);
+                applyRequirementsLocked(provider);
             }
         } else {
-            p.enableLocationTracking(false);
             p.disable();
         }
     }
 
-    private long getMinTimeLocked(String provider) {
-        long minTime = Long.MAX_VALUE;
+    private void applyRequirementsLocked(String provider) {
+        LocationProviderInterface p = mProvidersByName.get(provider);
+        if (p == null) return;
+
         ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
-        mTmpWorkSource.clear();
+        WorkSource worksource = new WorkSource();
+        ProviderRequest providerRequest = new ProviderRequest();
+
         if (records != null) {
-            for (int i=records.size()-1; i>=0; i--) {
-                UpdateRecord ur = records.get(i);
-                long curTime = ur.mMinTime;
-                if (curTime < minTime) {
-                    minTime = curTime;
+            for (UpdateRecord record : records) {
+                if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
+                    LocationRequest locationRequest = record.mRequest;
+                    providerRequest.locationRequests.add(locationRequest);
+                    if (locationRequest.getInterval() < providerRequest.interval) {
+                        providerRequest.reportLocation = true;
+                        providerRequest.interval = locationRequest.getInterval();
+                    }
                 }
             }
-            long inclTime = (minTime*3)/2;
-            for (int i=records.size()-1; i>=0; i--) {
-                UpdateRecord ur = records.get(i);
-                if (ur.mMinTime <= inclTime) {
-                    mTmpWorkSource.add(ur.mUid);
+
+            if (providerRequest.reportLocation) {
+                // calculate who to blame for power
+                // This is somewhat arbitrary. We pick a threshold interval
+                // that is slightly higher that the minimum interval, and
+                // spread the blame across all applications with a request
+                // under that threshold.
+                long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
+                for (UpdateRecord record : records) {
+                    if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
+                        LocationRequest locationRequest = record.mRequest;
+                        if (locationRequest.getInterval() <= thresholdInterval) {
+                            worksource.add(record.mReceiver.mUid);
+                        }
+                    }
                 }
             }
         }
-        return minTime;
+
+        if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
+        p.setRequest(providerRequest, worksource);
     }
 
     private class UpdateRecord {
         final String mProvider;
+        final LocationRequest mRequest;
         final Receiver mReceiver;
-        final long mMinTime;
-        final float mMinDistance;
-        final boolean mSingleShot;
-        final int mUid;
         Location mLastFixBroadcast;
         long mLastStatusBroadcast;
 
         /**
          * Note: must be constructed with lock held.
          */
-        UpdateRecord(String provider, long minTime, float minDistance, boolean singleShot,
-            Receiver receiver, int uid) {
+        UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
             mProvider = provider;
+            mRequest = request;
             mReceiver = receiver;
-            mMinTime = minTime;
-            mMinDistance = minDistance;
-            mSingleShot = singleShot;
-            mUid = uid;
 
             ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
             if (records == null) {
@@ -1096,45 +1043,49 @@
          * Method to be called when a record will no longer be used.  Calling this multiple times
          * must have the same effect as calling it once.
          */
-        void disposeLocked() {
-            ArrayList<UpdateRecord> records = mRecordsByProvider.get(this.mProvider);
-            if (records != null) {
-                records.remove(this);
+        void disposeLocked(boolean removeReceiver) {
+            // remove from mRecordsByProvider
+            ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
+            if (globalRecords != null) {
+                globalRecords.remove(this);
+            }
+
+            if (!removeReceiver) return;  // the caller will handle the rest
+
+            // remove from Receiver#mUpdateRecords
+            HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
+            if (receiverRecords != null) {
+                receiverRecords.remove(this.mProvider);
+
+                // and also remove the Receiver if it has no more update records
+                if (removeReceiver && receiverRecords.size() == 0) {
+                    removeUpdatesLocked(mReceiver);
+                }
             }
         }
 
         @Override
         public String toString() {
-            return "UpdateRecord{"
-                    + Integer.toHexString(System.identityHashCode(this))
-                    + " mProvider: " + mProvider + " mUid: " + mUid + "}";
-        }
-
-        void dump(PrintWriter pw, String prefix) {
-            pw.println(prefix + this);
-            pw.println(prefix + "mProvider=" + mProvider + " mReceiver=" + mReceiver);
-            pw.println(prefix + "mMinTime=" + mMinTime + " mMinDistance=" + mMinDistance);
-            pw.println(prefix + "mSingleShot=" + mSingleShot);
-            pw.println(prefix + "mUid=" + mUid);
-            pw.println(prefix + "mLastFixBroadcast:");
-            if (mLastFixBroadcast != null) {
-                mLastFixBroadcast.dump(new PrintWriterPrinter(pw), prefix + "  ");
-            }
-            pw.println(prefix + "mLastStatusBroadcast=" + mLastStatusBroadcast);
+            StringBuilder s = new StringBuilder();
+            s.append("UpdateRecord[");
+            s.append(mProvider);
+            s.append(' ').append(mReceiver.mPackageName).append('(');
+            s.append(mReceiver.mUid).append(')');
+            s.append(' ').append(mRequest);
+            s.append(']');
+            return s.toString();
         }
     }
 
-    private Receiver getReceiver(ILocationListener listener, String packageName) {
+    private Receiver getReceiver(ILocationListener listener, int pid, int uid, String packageName) {
         IBinder binder = listener.asBinder();
         Receiver receiver = mReceivers.get(binder);
         if (receiver == null) {
-            receiver = new Receiver(listener, packageName);
+            receiver = new Receiver(listener, null, pid, uid, packageName);
             mReceivers.put(binder, receiver);
 
             try {
-                if (receiver.isListener()) {
-                    receiver.getListener().asBinder().linkToDeath(receiver, 0);
-                }
+                receiver.getListener().asBinder().linkToDeath(receiver, 0);
             } catch (RemoteException e) {
                 Slog.e(TAG, "linkToDeath failed:", e);
                 return null;
@@ -1143,259 +1094,301 @@
         return receiver;
     }
 
-    private Receiver getReceiver(PendingIntent intent, String packageName) {
+    private Receiver getReceiver(PendingIntent intent, int pid, int uid, String packageName) {
         Receiver receiver = mReceivers.get(intent);
         if (receiver == null) {
-            receiver = new Receiver(intent, packageName);
+            receiver = new Receiver(null, intent, pid, uid, packageName);
             mReceivers.put(intent, receiver);
         }
         return receiver;
     }
 
-    private boolean providerHasListener(String provider, int uid, Receiver excludedReceiver) {
-        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
-        if (records != null) {
-            for (int i = records.size() - 1; i >= 0; i--) {
-                UpdateRecord record = records.get(i);
-                if (record.mUid == uid && record.mReceiver != excludedReceiver) {
-                    return true;
-                }
-           }
-        }
-        for (ProximityAlert alert : mProximityAlerts.values()) {
-            if (alert.mUid == uid) {
-                return true;
+    /**
+     * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
+     * and consistency requirements.
+     *
+     * @param request the LocationRequest from which to create a sanitized version
+     * @param shouldBeCoarse whether the sanitized version should be held to coarse resolution
+     * constraints
+     * @param fastestCoarseIntervalMS minimum interval allowed for coarse resolution
+     * @return a version of request that meets the given resolution and consistency requirements
+     * @hide
+     */
+    private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) {
+        LocationRequest sanitizedRequest = new LocationRequest(request);
+        if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
+            switch (sanitizedRequest.getQuality()) {
+                case LocationRequest.ACCURACY_FINE:
+                    sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
+                    break;
+                case LocationRequest.POWER_HIGH:
+                    sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
+                    break;
+            }
+            // throttle
+            if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
+                sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
+            }
+            if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
+                sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
             }
         }
-        return false;
+        // make getFastestInterval() the minimum of interval and fastest interval
+        if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
+            request.setFastestInterval(request.getInterval());
+        }
+        return sanitizedRequest;
     }
 
-    public void requestLocationUpdates(String provider, Criteria criteria,
-        long minTime, float minDistance, boolean singleShot, ILocationListener listener,
-        String packageName) {
-        checkPackageName(Binder.getCallingUid(), packageName);
-        if (criteria != null) {
-            // FIXME - should we consider using multiple providers simultaneously
-            // rather than only the best one?
-            // Should we do anything different for single shot fixes?
-            provider = getBestProvider(criteria, true);
-            if (provider == null) {
-                throw new IllegalArgumentException("no providers found for criteria");
-            }
+    private void checkPackageName(String packageName) {
+        if (packageName == null) {
+            throw new SecurityException("invalid package name: " + packageName);
         }
-        try {
-            synchronized (mLock) {
-                requestLocationUpdatesLocked(provider, minTime, minDistance, singleShot,
-                        getReceiver(listener, packageName));
-            }
-        } catch (SecurityException se) {
-            throw se;
-        } catch (IllegalArgumentException iae) {
-            throw iae;
-        } catch (Exception e) {
-            Slog.e(TAG, "requestUpdates got exception:", e);
+        int uid = Binder.getCallingUid();
+        String[] packages = mPackageManager.getPackagesForUid(uid);
+        if (packages == null) {
+            throw new SecurityException("invalid UID " + uid);
+        }
+        for (String pkg : packages) {
+            if (packageName.equals(pkg)) return;
+        }
+        throw new SecurityException("invalid package name: " + packageName);
+    }
+
+    private void checkPendingIntent(PendingIntent intent) {
+        if (intent == null) {
+            throw new IllegalArgumentException("invalid pending intent: " + intent);
         }
     }
 
-    void validatePendingIntent(PendingIntent intent) {
-        if (intent.isTargetedToPackage()) {
-            return;
-        }
-        Slog.i(TAG, "Given Intent does not require a specific package: "
-                + intent);
-        // XXX we should really throw a security exception, if the caller's
-        // targetSdkVersion is high enough.
-        //throw new SecurityException("Given Intent does not require a specific package: "
-        //        + intent);
-    }
-
-    public void requestLocationUpdatesPI(String provider, Criteria criteria,
-            long minTime, float minDistance, boolean singleShot, PendingIntent intent,
-            String packageName) {
-        checkPackageName(Binder.getCallingUid(), packageName);
-        validatePendingIntent(intent);
-        if (criteria != null) {
-            // FIXME - should we consider using multiple providers simultaneously
-            // rather than only the best one?
-            // Should we do anything different for single shot fixes?
-            provider = getBestProvider(criteria, true);
-            if (provider == null) {
-                throw new IllegalArgumentException("no providers found for criteria");
-            }
-        }
-        try {
-            synchronized (mLock) {
-                requestLocationUpdatesLocked(provider, minTime, minDistance, singleShot,
-                        getReceiver(intent, packageName));
-            }
-        } catch (SecurityException se) {
-            throw se;
-        } catch (IllegalArgumentException iae) {
-            throw iae;
-        } catch (Exception e) {
-            Slog.e(TAG, "requestUpdates got exception:", e);
+    private Receiver checkListenerOrIntent(ILocationListener listener, PendingIntent intent,
+            int pid, int uid, String packageName) {
+        if (intent == null && listener == null) {
+            throw new IllegalArgumentException("need eiter listener or intent");
+        } else if (intent != null && listener != null) {
+            throw new IllegalArgumentException("cannot register both listener and intent");
+        } else if (intent != null) {
+            checkPendingIntent(intent);
+            return getReceiver(intent, pid, uid, packageName);
+        } else {
+            return getReceiver(listener, pid, uid, packageName);
         }
     }
 
-    private void requestLocationUpdatesLocked(String provider, long minTime, float minDistance,
-            boolean singleShot, Receiver receiver) {
+    @Override
+    public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
+            PendingIntent intent, String packageName) {
+        if (request == null) request = DEFAULT_LOCATION_REQUEST;
+        checkPackageName(packageName);
+        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
+        checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
+                request.getProvider());
+        LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
 
-        LocationProviderInterface p = mProvidersByName.get(provider);
-        if (p == null) {
-            throw new IllegalArgumentException("requested provider " + provider +
-                    " doesn't exisit");
-        }
-        receiver.mRequiredPermissions = checkPermissionsSafe(provider,
-                receiver.mRequiredPermissions);
+        final int pid = Binder.getCallingPid();
+        final int uid = Binder.getCallingUid();
+        Receiver recevier = checkListenerOrIntent(listener, intent, pid, uid, packageName);
 
-        // so wakelock calls will succeed
-        final int callingPid = Binder.getCallingPid();
-        final int callingUid = Binder.getCallingUid();
-        boolean newUid = !providerHasListener(provider, callingUid, null);
+        // providers may use public location API's, need to clear identity
         long identity = Binder.clearCallingIdentity();
         try {
-            UpdateRecord r = new UpdateRecord(provider, minTime, minDistance, singleShot,
-                    receiver, callingUid);
-            UpdateRecord oldRecord = receiver.mUpdateRecords.put(provider, r);
-            if (oldRecord != null) {
-                oldRecord.disposeLocked();
-            }
-
-            if (newUid) {
-                p.addListener(callingUid);
-            }
-
-            boolean isProviderEnabled = isAllowedBySettingsLocked(provider);
-            if (isProviderEnabled) {
-                long minTimeForProvider = getMinTimeLocked(provider);
-                Slog.i(TAG, "request " + provider + " (pid " + callingPid + ") " + minTime +
-                        " " + minTimeForProvider + (singleShot ? " (singleshot)" : ""));
-                p.setMinTime(minTimeForProvider, mTmpWorkSource);
-                // try requesting single shot if singleShot is true, and fall back to
-                // regular location tracking if requestSingleShotFix() is not supported
-                if (!singleShot || !p.requestSingleShotFix()) {
-                    p.enableLocationTracking(true);
-                }
-            } else {
-                // Notify the listener that updates are currently disabled
-                receiver.callProviderEnabledLocked(provider, false);
-            }
-            if (LOCAL_LOGV) {
-                Slog.v(TAG, "_requestLocationUpdates: provider = " + provider + " listener = " + receiver);
+            synchronized (mLock) {
+                requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
             }
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
     }
 
-    public void removeUpdates(ILocationListener listener, String packageName) {
-        try {
-            synchronized (mLock) {
-                removeUpdatesLocked(getReceiver(listener, packageName));
-            }
-        } catch (SecurityException se) {
-            throw se;
-        } catch (IllegalArgumentException iae) {
-            throw iae;
-        } catch (Exception e) {
-            Slog.e(TAG, "removeUpdates got exception:", e);
+    private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
+            int pid, int uid, String packageName) {
+        // Figure out the provider. Either its explicitly request (legacy use cases), or
+        // use the fused provider
+        if (request == null) request = DEFAULT_LOCATION_REQUEST;
+        String name = request.getProvider();
+        if (name == null) {
+            throw new IllegalArgumentException("provider name must not be null");
+        }
+        LocationProviderInterface provider = mProvidersByName.get(name);
+        if (provider == null) {
+            throw new IllegalArgumentException("provider doesn't exisit: " + provider);
+        }
+
+        if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
+                + " " + name + " " + request + " from " + packageName + "(" + uid + ")");
+
+        UpdateRecord record = new UpdateRecord(name, request, receiver);
+        UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
+        if (oldRecord != null) {
+            oldRecord.disposeLocked(false);
+        }
+
+        boolean isProviderEnabled = isAllowedBySettingsLocked(name, UserHandle.getUserId(uid));
+        if (isProviderEnabled) {
+            applyRequirementsLocked(name);
+        } else {
+            // Notify the listener that updates are currently disabled
+            receiver.callProviderEnabledLocked(name, false);
         }
     }
 
-    public void removeUpdatesPI(PendingIntent intent, String packageName) {
+    @Override
+    public void removeUpdates(ILocationListener listener, PendingIntent intent,
+            String packageName) {
+        checkPackageName(packageName);
+
+        final int pid = Binder.getCallingPid();
+        final int uid = Binder.getCallingUid();
+        Receiver receiver = checkListenerOrIntent(listener, intent, pid, uid, packageName);
+
+        // providers may use public location API's, need to clear identity
+        long identity = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                removeUpdatesLocked(getReceiver(intent, packageName));
+                removeUpdatesLocked(receiver);
             }
-        } catch (SecurityException se) {
-            throw se;
-        } catch (IllegalArgumentException iae) {
-            throw iae;
-        } catch (Exception e) {
-            Slog.e(TAG, "removeUpdates got exception:", e);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
     }
 
     private void removeUpdatesLocked(Receiver receiver) {
-        if (LOCAL_LOGV) {
-            Slog.v(TAG, "_removeUpdates: listener = " + receiver);
+        if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
+
+        if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
+            receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
+            synchronized (receiver) {
+                if (receiver.mPendingBroadcasts > 0) {
+                    decrementPendingBroadcasts();
+                    receiver.mPendingBroadcasts = 0;
+                }
+            }
         }
 
-        // so wakelock calls will succeed
-        final int callingPid = Binder.getCallingPid();
-        final int callingUid = Binder.getCallingUid();
+        // Record which providers were associated with this listener
+        HashSet<String> providers = new HashSet<String>();
+        HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
+        if (oldRecords != null) {
+            // Call dispose() on the obsolete update records.
+            for (UpdateRecord record : oldRecords.values()) {
+                record.disposeLocked(false);
+            }
+            // Accumulate providers
+            providers.addAll(oldRecords.keySet());
+        }
+
+        // update provider
+        for (String provider : providers) {
+            // If provider is already disabled, don't need to do anything
+            if (!isAllowedBySettingsLocked(provider, mCurrentUserId)) {
+                continue;
+            }
+
+            applyRequirementsLocked(provider);
+        }
+    }
+
+    @Override
+    public Location getLastLocation(LocationRequest request, String packageName) {
+        if (D) Log.d(TAG, "getLastLocation: " + request);
+        if (request == null) request = DEFAULT_LOCATION_REQUEST;
+        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
+        checkPackageName(packageName);
+        checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
+                request.getProvider());
+        // no need to sanitize this request, as only the provider name is used
+
         long identity = Binder.clearCallingIdentity();
         try {
-            if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
-                receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
-                synchronized(receiver) {
-                    if(receiver.mPendingBroadcasts > 0) {
-                        decrementPendingBroadcasts();
-                        receiver.mPendingBroadcasts = 0;
-                    }
-                }
+            if (mBlacklist.isBlacklisted(packageName)) {
+                if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
+                        packageName);
+                return null;
             }
 
-            // Record which providers were associated with this listener
-            HashSet<String> providers = new HashSet<String>();
-            HashMap<String,UpdateRecord> oldRecords = receiver.mUpdateRecords;
-            if (oldRecords != null) {
-                // Call dispose() on the obsolete update records.
-                for (UpdateRecord record : oldRecords.values()) {
-                    if (!providerHasListener(record.mProvider, callingUid, receiver)) {
-                        LocationProviderInterface p = mProvidersByName.get(record.mProvider);
-                        if (p != null) {
-                            p.removeListener(callingUid);
-                        }
+            synchronized (mLock) {
+                // Figure out the provider. Either its explicitly request (deprecated API's),
+                // or use the fused provider
+                String name = request.getProvider();
+                if (name == null) name = LocationManager.FUSED_PROVIDER;
+                LocationProviderInterface provider = mProvidersByName.get(name);
+                if (provider == null) return null;
+
+                if (!isAllowedBySettingsLocked(name, mCurrentUserId)) return null;
+
+                Location location = mLastLocation.get(name);
+                if (location == null) {
+                    return null;
+                }
+                if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
+                    Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
+                    if (noGPSLocation != null) {
+                        return mLocationFudger.getOrCreate(noGPSLocation);
                     }
-                    record.disposeLocked();
-                }
-                // Accumulate providers
-                providers.addAll(oldRecords.keySet());
-            }
-
-            // See if the providers associated with this listener have any
-            // other listeners; if one does, inform it of the new smallest minTime
-            // value; if one does not, disable location tracking for it
-            for (String provider : providers) {
-                // If provider is already disabled, don't need to do anything
-                if (!isAllowedBySettingsLocked(provider)) {
-                    continue;
-                }
-
-                boolean hasOtherListener = false;
-                ArrayList<UpdateRecord> recordsForProvider = mRecordsByProvider.get(provider);
-                if (recordsForProvider != null && recordsForProvider.size() > 0) {
-                    hasOtherListener = true;
-                }
-
-                LocationProviderInterface p = mProvidersByName.get(provider);
-                if (p != null) {
-                    if (hasOtherListener) {
-                        long minTime = getMinTimeLocked(provider);
-                        Slog.i(TAG, "remove " + provider + " (pid " + callingPid +
-                                "), next minTime = " + minTime);
-                        p.setMinTime(minTime, mTmpWorkSource);
-                    } else {
-                        Slog.i(TAG, "remove " + provider + " (pid " + callingPid +
-                                "), disabled");
-                        p.enableLocationTracking(false);
-                    }
+                } else {
+                    return location;
                 }
             }
+            return null;
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
     }
 
+    @Override
+    public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
+            String packageName) {
+        if (request == null) request = DEFAULT_LOCATION_REQUEST;
+        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
+        checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
+        checkPendingIntent(intent);
+        checkPackageName(packageName);
+        checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
+                request.getProvider());
+        LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
+
+        if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
+
+        // geo-fence manager uses the public location API, need to clear identity
+        int uid = Binder.getCallingUid();
+        if (UserHandle.getUserId(uid) != UserHandle.USER_OWNER) {
+            // temporary measure until geofences work for secondary users
+            Log.w(TAG, "proximity alerts are currently available only to the primary user");
+            return;
+        }
+        long identity = Binder.clearCallingIdentity();
+        try {
+            mGeofenceManager.addFence(sanitizedRequest, geofence, intent, uid, packageName);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
+        checkResolutionLevelIsSufficientForGeofenceUse(getCallerAllowedResolutionLevel());
+        checkPendingIntent(intent);
+        checkPackageName(packageName);
+
+        if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
+
+        // geo-fence manager uses the public location API, need to clear identity
+        long identity = Binder.clearCallingIdentity();
+        try {
+            mGeofenceManager.removeFence(geofence, intent);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+
+    @Override
     public boolean addGpsStatusListener(IGpsStatusListener listener) {
         if (mGpsStatusProvider == null) {
             return false;
         }
-        if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) !=
-                PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
-        }
+        checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
+                LocationManager.GPS_PROVIDER);
 
         try {
             mGpsStatusProvider.addGpsStatusListener(listener);
@@ -1406,6 +1399,7 @@
         return true;
     }
 
+    @Override
     public void removeGpsStatusListener(IGpsStatusListener listener) {
         synchronized (mLock) {
             try {
@@ -1416,14 +1410,15 @@
         }
     }
 
+    @Override
     public boolean sendExtraCommand(String provider, String command, Bundle extras) {
         if (provider == null) {
             // throw NullPointerException to remain compatible with previous implementation
             throw new NullPointerException();
         }
+        checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
+                provider);
 
-        // first check for permission to the provider
-        checkPermissionsSafe(provider, null);
         // and check for ACCESS_LOCATION_EXTRA_COMMANDS
         if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
                 != PackageManager.PERMISSION_GRANTED)) {
@@ -1432,465 +1427,194 @@
 
         synchronized (mLock) {
             LocationProviderInterface p = mProvidersByName.get(provider);
-            if (p == null) {
-                return false;
-            }
-    
+            if (p == null) return false;
+
             return p.sendExtraCommand(command, extras);
         }
     }
 
-    public boolean sendNiResponse(int notifId, int userResponse)
-    {
+    @Override
+    public boolean sendNiResponse(int notifId, int userResponse) {
         if (Binder.getCallingUid() != Process.myUid()) {
             throw new SecurityException(
                     "calling sendNiResponse from outside of the system is not allowed");
         }
         try {
             return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
-        }
-        catch (RemoteException e)
-        {
+        } catch (RemoteException e) {
             Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
             return false;
         }
     }
 
-    class ProximityAlert {
-        final int  mUid;
-        final double mLatitude;
-        final double mLongitude;
-        final float mRadius;
-        final long mExpiration;
-        final PendingIntent mIntent;
-        final Location mLocation;
-        final String mPackageName;
-
-        public ProximityAlert(int uid, double latitude, double longitude,
-            float radius, long expiration, PendingIntent intent, String packageName) {
-            mUid = uid;
-            mLatitude = latitude;
-            mLongitude = longitude;
-            mRadius = radius;
-            mExpiration = expiration;
-            mIntent = intent;
-            mPackageName = packageName;
-
-            mLocation = new Location("");
-            mLocation.setLatitude(latitude);
-            mLocation.setLongitude(longitude);
-        }
-
-        long getExpiration() {
-            return mExpiration;
-        }
-
-        PendingIntent getIntent() {
-            return mIntent;
-        }
-
-        boolean isInProximity(double latitude, double longitude, float accuracy) {
-            Location loc = new Location("");
-            loc.setLatitude(latitude);
-            loc.setLongitude(longitude);
-
-            double radius = loc.distanceTo(mLocation);
-            return radius <= Math.max(mRadius,accuracy);
-        }
-        
-        @Override
-        public String toString() {
-            return "ProximityAlert{"
-                    + Integer.toHexString(System.identityHashCode(this))
-                    + " uid " + mUid + mIntent + "}";
-        }
-        
-        void dump(PrintWriter pw, String prefix) {
-            pw.println(prefix + this);
-            pw.println(prefix + "mLatitude=" + mLatitude + " mLongitude=" + mLongitude);
-            pw.println(prefix + "mRadius=" + mRadius + " mExpiration=" + mExpiration);
-            pw.println(prefix + "mIntent=" + mIntent);
-            pw.println(prefix + "mLocation:");
-            mLocation.dump(new PrintWriterPrinter(pw), prefix + "  ");
-        }
-    }
-
-    // Listener for receiving locations to trigger proximity alerts
-    class ProximityListener extends ILocationListener.Stub implements PendingIntent.OnFinished {
-
-        boolean isGpsAvailable = false;
-
-        // Note: this is called with the lock held.
-        public void onLocationChanged(Location loc) {
-
-            // If Gps is available, then ignore updates from NetworkLocationProvider
-            if (loc.getProvider().equals(LocationManager.GPS_PROVIDER)) {
-                isGpsAvailable = true;
-            }
-            if (isGpsAvailable && loc.getProvider().equals(LocationManager.NETWORK_PROVIDER)) {
-                return;
-            }
-
-            // Process proximity alerts
-            long now = System.currentTimeMillis();
-            double latitude = loc.getLatitude();
-            double longitude = loc.getLongitude();
-            float accuracy = loc.getAccuracy();
-            ArrayList<PendingIntent> intentsToRemove = null;
-
-            for (ProximityAlert alert : mProximityAlerts.values()) {
-                PendingIntent intent = alert.getIntent();
-                long expiration = alert.getExpiration();
-
-                if (inBlacklist(alert.mPackageName)) {
-                    continue;
-                }
-
-                if ((expiration == -1) || (now <= expiration)) {
-                    boolean entered = mProximitiesEntered.contains(alert);
-                    boolean inProximity =
-                        alert.isInProximity(latitude, longitude, accuracy);
-                    if (!entered && inProximity) {
-                        if (LOCAL_LOGV) {
-                            Slog.v(TAG, "Entered alert");
-                        }
-                        mProximitiesEntered.add(alert);
-                        Intent enteredIntent = new Intent();
-                        enteredIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, true);
-                        try {
-                            synchronized (this) {
-                                // synchronize to ensure incrementPendingBroadcasts()
-                                // is called before decrementPendingBroadcasts()
-                                intent.send(mContext, 0, enteredIntent, this, mLocationHandler,
-                                        ACCESS_FINE_LOCATION);
-                                // call this after broadcasting so we do not increment
-                                // if we throw an exeption.
-                                incrementPendingBroadcasts();
-                            }
-                        } catch (PendingIntent.CanceledException e) {
-                            if (LOCAL_LOGV) {
-                                Slog.v(TAG, "Canceled proximity alert: " + alert, e);
-                            }
-                            if (intentsToRemove == null) {
-                                intentsToRemove = new ArrayList<PendingIntent>();
-                            }
-                            intentsToRemove.add(intent);
-                        }
-                    } else if (entered && !inProximity) {
-                        if (LOCAL_LOGV) {
-                            Slog.v(TAG, "Exited alert");
-                        }
-                        mProximitiesEntered.remove(alert);
-                        Intent exitedIntent = new Intent();
-                        exitedIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);
-                        try {
-                            synchronized (this) {
-                                // synchronize to ensure incrementPendingBroadcasts()
-                                // is called before decrementPendingBroadcasts()
-                                intent.send(mContext, 0, exitedIntent, this, mLocationHandler,
-                                        ACCESS_FINE_LOCATION);
-                                // call this after broadcasting so we do not increment
-                                // if we throw an exeption.
-                                incrementPendingBroadcasts();
-                            }
-                        } catch (PendingIntent.CanceledException e) {
-                            if (LOCAL_LOGV) {
-                                Slog.v(TAG, "Canceled proximity alert: " + alert, e);
-                            }
-                            if (intentsToRemove == null) {
-                                intentsToRemove = new ArrayList<PendingIntent>();
-                            }
-                            intentsToRemove.add(intent);
-                        }
-                    }
-                } else {
-                    // Mark alert for expiration
-                    if (LOCAL_LOGV) {
-                        Slog.v(TAG, "Expiring proximity alert: " + alert);
-                    }
-                    if (intentsToRemove == null) {
-                        intentsToRemove = new ArrayList<PendingIntent>();
-                    }
-                    intentsToRemove.add(alert.getIntent());
-                }
-            }
-
-            // Remove expired alerts
-            if (intentsToRemove != null) {
-                for (PendingIntent i : intentsToRemove) {
-                    ProximityAlert alert = mProximityAlerts.get(i);
-                    mProximitiesEntered.remove(alert);
-                    removeProximityAlertLocked(i);
-                }
-            }
-        }
-
-        // Note: this is called with the lock held.
-        public void onProviderDisabled(String provider) {
-            if (provider.equals(LocationManager.GPS_PROVIDER)) {
-                isGpsAvailable = false;
-            }
-        }
-
-        // Note: this is called with the lock held.
-        public void onProviderEnabled(String provider) {
-            // ignore
-        }
-
-        // Note: this is called with the lock held.
-        public void onStatusChanged(String provider, int status, Bundle extras) {
-            if ((provider.equals(LocationManager.GPS_PROVIDER)) &&
-                (status != LocationProvider.AVAILABLE)) {
-                isGpsAvailable = false;
-            }
-        }
-
-        public void onSendFinished(PendingIntent pendingIntent, Intent intent,
-                int resultCode, String resultData, Bundle resultExtras) {
-            // synchronize to ensure incrementPendingBroadcasts()
-            // is called before decrementPendingBroadcasts()
-            synchronized (this) {
-                decrementPendingBroadcasts();
-            }
-        }
-    }
-
-    public void addProximityAlert(double latitude, double longitude,
-        float radius, long expiration, PendingIntent intent, String packageName) {
-        validatePendingIntent(intent);
-        try {
-            synchronized (mLock) {
-                addProximityAlertLocked(latitude, longitude, radius, expiration, intent,
-                        packageName);
-            }
-        } catch (SecurityException se) {
-            throw se;
-        } catch (IllegalArgumentException iae) {
-            throw iae;
-        } catch (Exception e) {
-            Slog.e(TAG, "addProximityAlert got exception:", e);
-        }
-    }
-
-    private void addProximityAlertLocked(double latitude, double longitude,
-        float radius, long expiration, PendingIntent intent, String packageName) {
-        if (LOCAL_LOGV) {
-            Slog.v(TAG, "addProximityAlert: latitude = " + latitude +
-                    ", longitude = " + longitude +
-                    ", expiration = " + expiration +
-                    ", intent = " + intent);
-        }
-
-        checkPackageName(Binder.getCallingUid(), packageName);
-
-        // Require ability to access all providers for now
-        if (!isAllowedProviderSafe(LocationManager.GPS_PROVIDER) ||
-            !isAllowedProviderSafe(LocationManager.NETWORK_PROVIDER)) {
-            throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
-        }
-
-        if (expiration != -1) {
-            expiration += System.currentTimeMillis();
-        }
-        ProximityAlert alert = new ProximityAlert(Binder.getCallingUid(),
-                latitude, longitude, radius, expiration, intent, packageName);
-        mProximityAlerts.put(intent, alert);
-
-        if (mProximityReceiver == null) {
-            mProximityListener = new ProximityListener();
-            mProximityReceiver = new Receiver(mProximityListener, packageName);
-
-            for (int i = mProviders.size() - 1; i >= 0; i--) {
-                LocationProviderInterface provider = mProviders.get(i);
-                requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f,
-                        false, mProximityReceiver);
-            }
-        }
-    }
-
-    public void removeProximityAlert(PendingIntent intent) {
-        try {
-            synchronized (mLock) {
-               removeProximityAlertLocked(intent);
-            }
-        } catch (SecurityException se) {
-            throw se;
-        } catch (IllegalArgumentException iae) {
-            throw iae;
-        } catch (Exception e) {
-            Slog.e(TAG, "removeProximityAlert got exception:", e);
-        }
-    }
-
-    private void removeProximityAlertLocked(PendingIntent intent) {
-        if (LOCAL_LOGV) {
-            Slog.v(TAG, "removeProximityAlert: intent = " + intent);
-        }
-
-        mProximityAlerts.remove(intent);
-        if (mProximityAlerts.size() == 0) {
-            if (mProximityReceiver != null) {
-                removeUpdatesLocked(mProximityReceiver);
-            }
-            mProximityReceiver = null;
-            mProximityListener = null;
-        }
-     }
-
     /**
      * @return null if the provider does not exist
      * @throws SecurityException if the provider is not allowed to be
      * accessed by the caller
      */
-    public Bundle getProviderInfo(String provider) {
-        try {
-            synchronized (mLock) {
-                return _getProviderInfoLocked(provider);
-            }
-        } catch (SecurityException se) {
-            throw se;
-        } catch (IllegalArgumentException iae) {
-            throw iae;
-        } catch (Exception e) {
-            Slog.e(TAG, "_getProviderInfo got exception:", e);
-            return null;
-        }
-    }
-
-    private Bundle _getProviderInfoLocked(String provider) {
-        LocationProviderInterface p = mProvidersByName.get(provider);
-        if (p == null) {
-            return null;
+    @Override
+    public ProviderProperties getProviderProperties(String provider) {
+        if (mProvidersByName.get(provider) == null) {
+          return null;
         }
 
-        checkPermissionsSafe(provider, null);
+        checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
+                provider);
 
-        Bundle b = new Bundle();
-        b.putBoolean("network", p.requiresNetwork());
-        b.putBoolean("satellite", p.requiresSatellite());
-        b.putBoolean("cell", p.requiresCell());
-        b.putBoolean("cost", p.hasMonetaryCost());
-        b.putBoolean("altitude", p.supportsAltitude());
-        b.putBoolean("speed", p.supportsSpeed());
-        b.putBoolean("bearing", p.supportsBearing());
-        b.putInt("power", p.getPowerRequirement());
-        b.putInt("accuracy", p.getAccuracy());
+        LocationProviderInterface p;
+        synchronized (mLock) {
+            p = mProvidersByName.get(provider);
+        }
 
-        return b;
+        if (p == null) return null;
+        return p.getProperties();
     }
 
+    @Override
     public boolean isProviderEnabled(String provider) {
+        checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
+                provider);
+        if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
+
+        long identity = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                return _isProviderEnabledLocked(provider);
+                LocationProviderInterface p = mProvidersByName.get(provider);
+                if (p == null) return false;
+
+                return isAllowedBySettingsLocked(provider, mCurrentUserId);
             }
-        } catch (SecurityException se) {
-            throw se;
-        } catch (Exception e) {
-            Slog.e(TAG, "isProviderEnabled got exception:", e);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    private void checkCallerIsProvider() {
+        if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
+                == PackageManager.PERMISSION_GRANTED) {
+            return;
+        }
+
+        // Previously we only used the INSTALL_LOCATION_PROVIDER
+        // check. But that is system or signature
+        // protection level which is not flexible enough for
+        // providers installed oustide the system image. So
+        // also allow providers with a UID matching the
+        // currently bound package name
+
+        int uid = Binder.getCallingUid();
+
+        if (mGeocodeProvider != null) {
+            if (doesPackageHaveUid(uid, mGeocodeProvider.getConnectedPackageName())) return;
+        }
+        for (LocationProviderProxy proxy : mProxyProviders) {
+            if (doesPackageHaveUid(uid, proxy.getConnectedPackageName())) return;
+        }
+        throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
+                "or UID of a currently bound location provider");
+    }
+
+    private boolean doesPackageHaveUid(int uid, String packageName) {
+        if (packageName == null) {
             return false;
         }
+        try {
+            ApplicationInfo appInfo = mPackageManager.getApplicationInfo(packageName, 0);
+            if (appInfo.uid != uid) {
+                return false;
+            }
+        } catch (NameNotFoundException e) {
+            return false;
+        }
+        return true;
     }
 
+    @Override
     public void reportLocation(Location location, boolean passive) {
-        if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
+        checkCallerIsProvider();
+
+        if (!location.isComplete()) {
+            Log.w(TAG, "Dropping incomplete location: " + location);
+            return;
         }
 
-        mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location);
-        Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location);
+        mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
+        Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
         m.arg1 = (passive ? 1 : 0);
         mLocationHandler.sendMessageAtFrontOfQueue(m);
     }
 
-    private boolean _isProviderEnabledLocked(String provider) {
-        checkPermissionsSafe(provider, null);
 
-        LocationProviderInterface p = mProvidersByName.get(provider);
-        if (p == null) {
-            return false;
-        }
-        return isAllowedBySettingsLocked(provider);
-    }
-
-    public Location getLastKnownLocation(String provider, String packageName) {
-        if (LOCAL_LOGV) {
-            Slog.v(TAG, "getLastKnownLocation: " + provider);
-        }
-        try {
-            synchronized (mLock) {
-                return _getLastKnownLocationLocked(provider, packageName);
-            }
-        } catch (SecurityException se) {
-            throw se;
-        } catch (Exception e) {
-            Slog.e(TAG, "getLastKnownLocation got exception:", e);
-            return null;
-        }
-    }
-
-    private Location _getLastKnownLocationLocked(String provider, String packageName) {
-        checkPermissionsSafe(provider, null);
-        checkPackageName(Binder.getCallingUid(), packageName);
-
-        LocationProviderInterface p = mProvidersByName.get(provider);
-        if (p == null) {
-            return null;
-        }
-
-        if (!isAllowedBySettingsLocked(provider)) {
-            return null;
-        }
-
-        if (inBlacklist(packageName)) {
-            return null;
-        }
-
-        return mLastKnownLocation.get(provider);
-    }
-
-    private static boolean shouldBroadcastSafe(Location loc, Location lastLoc, UpdateRecord record) {
+    private static boolean shouldBroadcastSafe(
+            Location loc, Location lastLoc, UpdateRecord record, long now) {
         // Always broadcast the first update
         if (lastLoc == null) {
             return true;
         }
 
         // Check whether sufficient time has passed
-        long minTime = record.mMinTime;
-        if (loc.getTime() - lastLoc.getTime() < minTime - MAX_PROVIDER_SCHEDULING_JITTER) {
+        long minTime = record.mRequest.getFastestInterval();
+        long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos()) / 1000000L;
+        if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
             return false;
         }
 
         // Check whether sufficient distance has been traveled
-        double minDistance = record.mMinDistance;
+        double minDistance = record.mRequest.getSmallestDisplacement();
         if (minDistance > 0.0) {
             if (loc.distanceTo(lastLoc) <= minDistance) {
                 return false;
             }
         }
 
+        // Check whether sufficient number of udpates is left
+        if (record.mRequest.getNumUpdates() <= 0) {
+            return false;
+        }
+
+        // Check whether the expiry date has passed
+        if (record.mRequest.getExpireAt() < now) {
+            return false;
+        }
+
         return true;
     }
 
     private void handleLocationChangedLocked(Location location, boolean passive) {
+        if (D) Log.d(TAG, "incoming location: " + location);
+
+        long now = SystemClock.elapsedRealtime();
         String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
-        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
-        if (records == null || records.size() == 0) {
-            return;
-        }
 
+        // Skip if the provider is unknown.
         LocationProviderInterface p = mProvidersByName.get(provider);
-        if (p == null) {
-            return;
-        }
+        if (p == null) return;
 
-        // Update last known location for provider
-        Location lastLocation = mLastKnownLocation.get(provider);
+        // Update last known locations
+        Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
+        Location lastNoGPSLocation = null;
+        Location lastLocation = mLastLocation.get(provider);
         if (lastLocation == null) {
-            mLastKnownLocation.put(provider, new Location(location));
+            lastLocation = new Location(provider);
+            mLastLocation.put(provider, lastLocation);
         } else {
-            lastLocation.set(location);
+            lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
+            if (noGPSLocation == null && lastNoGPSLocation != null) {
+                // New location has no no-GPS location: adopt last no-GPS location. This is set
+                // directly into location because we do not want to notify COARSE clients.
+                location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
+            }
+        }
+        lastLocation.set(location);
+
+        // Skip if there are no UpdateRecords for this provider.
+        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
+        if (records == null || records.size() == 0) return;
+
+        // Fetch coarse location
+        Location coarseLocation = null;
+        if (noGPSLocation != null && !noGPSLocation.equals(lastNoGPSLocation)) {
+            coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
         }
 
         // Fetch latest status update time
@@ -1901,35 +1625,55 @@
         int status = p.getStatus(extras);
 
         ArrayList<Receiver> deadReceivers = null;
-        
+        ArrayList<UpdateRecord> deadUpdateRecords = null;
+
         // Broadcast location or status to all listeners
-        final int N = records.size();
-        for (int i=0; i<N; i++) {
-            UpdateRecord r = records.get(i);
+        for (UpdateRecord r : records) {
             Receiver receiver = r.mReceiver;
             boolean receiverDead = false;
 
-            if (inBlacklist(receiver.mPackageName)) {
+            int receiverUserId = UserHandle.getUserId(receiver.mUid);
+            if (receiverUserId != mCurrentUserId) {
+                if (D) {
+                    Log.d(TAG, "skipping loc update for background user " + receiverUserId +
+                            " (current user: " + mCurrentUserId + ", app: " +
+                            receiver.mPackageName + ")");
+                }
                 continue;
             }
 
-            Location lastLoc = r.mLastFixBroadcast;
-            if ((lastLoc == null) || shouldBroadcastSafe(location, lastLoc, r)) {
-                if (lastLoc == null) {
-                    lastLoc = new Location(location);
-                    r.mLastFixBroadcast = lastLoc;
-                } else {
-                    lastLoc.set(location);
-                }
-                if (!receiver.callLocationChangedLocked(location)) {
-                    Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
-                    receiverDead = true;
+            if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
+                if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
+                        receiver.mPackageName);
+                continue;
+            }
+
+            Location notifyLocation = null;
+            if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
+                notifyLocation = coarseLocation;  // use coarse location
+            } else {
+                notifyLocation = lastLocation;  // use fine location
+            }
+            if (notifyLocation != null) {
+                Location lastLoc = r.mLastFixBroadcast;
+                if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
+                    if (lastLoc == null) {
+                        lastLoc = new Location(notifyLocation);
+                        r.mLastFixBroadcast = lastLoc;
+                    } else {
+                        lastLoc.set(notifyLocation);
+                    }
+                    if (!receiver.callLocationChangedLocked(notifyLocation)) {
+                        Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
+                        receiverDead = true;
+                    }
+                    r.mRequest.decrementNumUpdates();
                 }
             }
 
             long prevStatusUpdateTime = r.mLastStatusBroadcast;
             if ((newStatusUpdateTime > prevStatusUpdateTime) &&
-                (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
+                    (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
 
                 r.mLastStatusBroadcast = newStatusUpdateTime;
                 if (!receiver.callStatusChangedLocked(provider, status, extras)) {
@@ -1938,8 +1682,15 @@
                 }
             }
 
-            // remove receiver if it is dead or we just processed a single shot request
-            if (receiverDead || r.mSingleShot) {
+            // track expired records
+            if (r.mRequest.getNumUpdates() <= 0 || r.mRequest.getExpireAt() < now) {
+                if (deadUpdateRecords == null) {
+                    deadUpdateRecords = new ArrayList<UpdateRecord>();
+                }
+                deadUpdateRecords.add(r);
+            }
+            // track dead receivers
+            if (receiverDead) {
                 if (deadReceivers == null) {
                     deadReceivers = new ArrayList<Receiver>();
                 }
@@ -1948,182 +1699,69 @@
                 }
             }
         }
-        
+
+        // remove dead records and receivers outside the loop
         if (deadReceivers != null) {
-            for (int i=deadReceivers.size()-1; i>=0; i--) {
-                removeUpdatesLocked(deadReceivers.get(i));
+            for (Receiver receiver : deadReceivers) {
+                removeUpdatesLocked(receiver);
+            }
+        }
+        if (deadUpdateRecords != null) {
+            for (UpdateRecord r : deadUpdateRecords) {
+                r.disposeLocked(true);
             }
         }
     }
 
     private class LocationWorkerHandler extends Handler {
-
         @Override
         public void handleMessage(Message msg) {
-            try {
-                if (msg.what == MESSAGE_LOCATION_CHANGED) {
-                    // log("LocationWorkerHandler: MESSAGE_LOCATION_CHANGED!");
-
-                    synchronized (mLock) {
-                        Location location = (Location) msg.obj;
-                        String provider = location.getProvider();
-                        boolean passive = (msg.arg1 == 1);
-
-                        if (!passive) {
-                            // notify other providers of the new location
-                            for (int i = mProviders.size() - 1; i >= 0; i--) {
-                                LocationProviderInterface p = mProviders.get(i);
-                                if (!provider.equals(p.getName())) {
-                                    p.updateLocation(location);
-                                }
-                            }
-                        }
-
-                        if (isAllowedBySettingsLocked(provider)) {
-                            handleLocationChangedLocked(location, passive);
-                        }
-                    }
-                } else if (msg.what == MESSAGE_PACKAGE_UPDATED) {
-                    String packageName = (String) msg.obj;
-
-                    // reconnect to external providers if there is a better package
-                    if (mNetworkLocationProviderPackageName != null &&
-                            mPackageManager.resolveService(
-                            new Intent(LocationProviderProxy.SERVICE_ACTION)
-                            .setPackage(packageName), 0) != null) {
-                        // package implements service, perform full check
-                        String bestPackage = findBestPackage(
-                                LocationProviderProxy.SERVICE_ACTION,
-                                mNetworkLocationProviderPackageName);
-                        if (packageName.equals(bestPackage)) {
-                            mNetworkLocationProvider.reconnect(bestPackage);
-                            mNetworkLocationProviderPackageName = packageName;
-                        }
-                    }
-                    if (mGeocodeProviderPackageName != null &&
-                            mPackageManager.resolveService(
-                            new Intent(GeocoderProxy.SERVICE_ACTION)
-                            .setPackage(packageName), 0) != null) {
-                        // package implements service, perform full check
-                        String bestPackage = findBestPackage(
-                                GeocoderProxy.SERVICE_ACTION,
-                                mGeocodeProviderPackageName);
-                        if (packageName.equals(bestPackage)) {
-                            mGeocodeProvider.reconnect(bestPackage);
-                            mGeocodeProviderPackageName = packageName;
-                        }
-                    }
-                }
-            } catch (Exception e) {
-                // Log, don't crash!
-                Slog.e(TAG, "Exception in LocationWorkerHandler.handleMessage:", e);
+            switch (msg.what) {
+                case MSG_LOCATION_CHANGED:
+                    handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
+                    break;
             }
         }
     }
 
-    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            boolean queryRestart = action.equals(Intent.ACTION_QUERY_PACKAGE_RESTART);
-            if (queryRestart
-                    || action.equals(Intent.ACTION_PACKAGE_REMOVED)
-                    || action.equals(Intent.ACTION_PACKAGE_RESTARTED)
-                    || action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
-                synchronized (mLock) {
-                    int uidList[] = null;
-                    if (action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
-                        uidList = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
-                    } else {
-                        uidList = new int[]{intent.getIntExtra(Intent.EXTRA_UID, -1)};
-                    }
-                    if (uidList == null || uidList.length == 0) {
-                        return;
-                    }
-                    for (int uid : uidList) {
-                        if (uid >= 0) {
-                            ArrayList<Receiver> removedRecs = null;
-                            for (ArrayList<UpdateRecord> i : mRecordsByProvider.values()) {
-                                for (int j=i.size()-1; j>=0; j--) {
-                                    UpdateRecord ur = i.get(j);
-                                    if (ur.mReceiver.isPendingIntent() && ur.mUid == uid) {
-                                        if (queryRestart) {
-                                            setResultCode(Activity.RESULT_OK);
-                                            return;
-                                        }
-                                        if (removedRecs == null) {
-                                            removedRecs = new ArrayList<Receiver>();
-                                        }
-                                        if (!removedRecs.contains(ur.mReceiver)) {
-                                            removedRecs.add(ur.mReceiver);
-                                        }
-                                    }
-                                }
-                            }
-                            ArrayList<ProximityAlert> removedAlerts = null;
-                            for (ProximityAlert i : mProximityAlerts.values()) {
-                                if (i.mUid == uid) {
-                                    if (queryRestart) {
-                                        setResultCode(Activity.RESULT_OK);
-                                        return;
-                                    }
-                                    if (removedAlerts == null) {
-                                        removedAlerts = new ArrayList<ProximityAlert>();
-                                    }
-                                    if (!removedAlerts.contains(i)) {
-                                        removedAlerts.add(i);
-                                    }
-                                }
-                            }
-                            if (removedRecs != null) {
-                                for (int i=removedRecs.size()-1; i>=0; i--) {
-                                    removeUpdatesLocked(removedRecs.get(i));
-                                }
-                            }
-                            if (removedAlerts != null) {
-                                for (int i=removedAlerts.size()-1; i>=0; i--) {
-                                    removeProximityAlertLocked(removedAlerts.get(i).mIntent);
-                                }
-                            }
-                        }
-                    }
-                }
-            } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
-                boolean noConnectivity =
-                    intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
-                if (!noConnectivity) {
-                    mNetworkState = LocationProvider.AVAILABLE;
-                } else {
-                    mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
-                }
+    private void handleLocationChanged(Location location, boolean passive) {
+        String provider = location.getProvider();
 
-                final ConnectivityManager connManager = (ConnectivityManager) context
-                        .getSystemService(Context.CONNECTIVITY_SERVICE);
-                final NetworkInfo info = connManager.getActiveNetworkInfo();
+        if (!passive) {
+            // notify passive provider of the new location
+            mPassiveProvider.updateLocation(location);
+        }
 
-                // Notify location providers of current network state
-                synchronized (mLock) {
-                    for (int i = mProviders.size() - 1; i >= 0; i--) {
-                        LocationProviderInterface provider = mProviders.get(i);
-                        if (provider.requiresNetwork()) {
-                            provider.updateNetworkState(mNetworkState, info);
-                        }
-                    }
-                }
+        synchronized (mLock) {
+            if (isAllowedBySettingsLocked(provider, mCurrentUserId)) {
+                handleLocationChangedLocked(location, passive);
             }
         }
-    };
+    }
 
     private final PackageMonitor mPackageMonitor = new PackageMonitor() {
         @Override
-        public void onPackageUpdateFinished(String packageName, int uid) {
-            // Called by main thread; divert work to LocationWorker.
-            Message.obtain(mLocationHandler, MESSAGE_PACKAGE_UPDATED, packageName).sendToTarget();
-        }
-        @Override
-        public void onPackageAdded(String packageName, int uid) {
-            // Called by main thread; divert work to LocationWorker.
-            Message.obtain(mLocationHandler, MESSAGE_PACKAGE_UPDATED, packageName).sendToTarget();
+        public void onPackageDisappeared(String packageName, int reason) {
+            // remove all receivers associated with this package name
+            synchronized (mLock) {
+                ArrayList<Receiver> deadReceivers = null;
+
+                for (Receiver receiver : mReceivers.values()) {
+                    if (receiver.mPackageName.equals(packageName)) {
+                        if (deadReceivers == null) {
+                            deadReceivers = new ArrayList<Receiver>();
+                        }
+                        deadReceivers.add(receiver);
+                    }
+                }
+
+                // perform removal outside of mReceivers loop
+                if (deadReceivers != null) {
+                    for (Receiver receiver : deadReceivers) {
+                        removeUpdatesLocked(receiver);
+                    }
+                }
+            }
         }
     };
 
@@ -2166,10 +1804,12 @@
 
     // Geocoder
 
+    @Override
     public boolean geocoderIsPresent() {
         return mGeocodeProvider != null;
     }
 
+    @Override
     public String getFromLocation(double latitude, double longitude, int maxResults,
             GeocoderParams params, List<Address> addrs) {
         if (mGeocodeProvider != null) {
@@ -2180,6 +1820,7 @@
     }
 
 
+    @Override
     public String getFromLocationName(String locationName,
             double lowerLeftLatitude, double lowerLeftLongitude,
             double upperRightLatitude, double upperRightLongitude, int maxResults,
@@ -2205,12 +1846,11 @@
         if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
             PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
-        }            
+        }
     }
 
-    public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite,
-        boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
-        boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
+    @Override
+    public void addTestProvider(String name, ProviderProperties properties) {
         checkMockPermissionsSafe();
 
         if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
@@ -2219,30 +1859,28 @@
 
         long identity = Binder.clearCallingIdentity();
         synchronized (mLock) {
-            MockProvider provider = new MockProvider(name, this,
-                requiresNetwork, requiresSatellite,
-                requiresCell, hasMonetaryCost, supportsAltitude,
-                supportsSpeed, supportsBearing, powerRequirement, accuracy);
+            MockProvider provider = new MockProvider(name, this, properties);
             // remove the real provider if we are replacing GPS or network provider
             if (LocationManager.GPS_PROVIDER.equals(name)
-                    || LocationManager.NETWORK_PROVIDER.equals(name)) {
+                    || LocationManager.NETWORK_PROVIDER.equals(name)
+                    || LocationManager.FUSED_PROVIDER.equals(name)) {
                 LocationProviderInterface p = mProvidersByName.get(name);
                 if (p != null) {
-                    p.enableLocationTracking(false);
-                    removeProvider(p);
+                    removeProviderLocked(p);
                 }
             }
             if (mProvidersByName.get(name) != null) {
                 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
             }
-            addProvider(provider);
+            addProviderLocked(provider);
             mMockProviders.put(name, provider);
-            mLastKnownLocation.put(name, null);
+            mLastLocation.put(name, null);
             updateProvidersLocked();
         }
         Binder.restoreCallingIdentity(identity);
     }
 
+    @Override
     public void removeTestProvider(String provider) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2251,22 +1889,21 @@
                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
             }
             long identity = Binder.clearCallingIdentity();
-            removeProvider(mProvidersByName.get(provider));
+            removeProviderLocked(mProvidersByName.get(provider));
             mMockProviders.remove(mockProvider);
-            // reinstall real provider if we were mocking GPS or network provider
-            if (LocationManager.GPS_PROVIDER.equals(provider) &&
-                    mGpsLocationProvider != null) {
-                addProvider(mGpsLocationProvider);
-            } else if (LocationManager.NETWORK_PROVIDER.equals(provider) &&
-                    mNetworkLocationProvider != null) {
-                addProvider(mNetworkLocationProvider);
+
+            // reinstate real provider if available
+            LocationProviderInterface realProvider = mRealProviders.get(provider);
+            if (realProvider != null) {
+                addProviderLocked(realProvider);
             }
-            mLastKnownLocation.put(provider, null);
+            mLastLocation.put(provider, null);
             updateProvidersLocked();
             Binder.restoreCallingIdentity(identity);
         }
     }
 
+    @Override
     public void setTestProviderLocation(String provider, Location loc) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2281,6 +1918,7 @@
         }
     }
 
+    @Override
     public void clearTestProviderLocation(String provider) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2292,6 +1930,7 @@
         }
     }
 
+    @Override
     public void setTestProviderEnabled(String provider, boolean enabled) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2314,6 +1953,7 @@
         }
     }
 
+    @Override
     public void clearTestProviderEnabled(String provider) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2329,6 +1969,7 @@
         }
     }
 
+    @Override
     public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2340,6 +1981,7 @@
         }
     }
 
+    @Override
     public void clearTestProviderStatus(String provider) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2351,119 +1993,13 @@
         }
     }
 
-    public class BlacklistObserver extends ContentObserver {
-        public BlacklistObserver(Handler handler) {
-            super(handler);
-        }
-        @Override
-        public void onChange(boolean selfChange) {
-            reloadBlacklist();
-        }
-    }
-
-    private void loadBlacklist() {
-        // Register for changes
-        BlacklistObserver observer = new BlacklistObserver(mLocationHandler);
-        mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
-                BLACKLIST_CONFIG_NAME), false, observer);
-        mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
-                WHITELIST_CONFIG_NAME), false, observer);
-        reloadBlacklist();
-    }
-
-    private void reloadBlacklist() {
-        String blacklist[] = getStringArray(BLACKLIST_CONFIG_NAME);
-        String whitelist[] = getStringArray(WHITELIST_CONFIG_NAME);
-        synchronized (mLock) {
-            mWhitelist = whitelist;
-            Slog.i(TAG, "whitelist: " + arrayToString(mWhitelist));
-            mBlacklist = blacklist;
-            Slog.i(TAG, "blacklist: " + arrayToString(mBlacklist));
-        }
-    }
-
-    private static String arrayToString(String[] array) {
-        StringBuilder s = new StringBuilder();
-        s.append('[');
-        boolean first = true;
-        for (String a : array) {
-            if (!first) s.append(',');
-            first = false;
-            s.append(a);
-        }
-        s.append(']');
-        return s.toString();
-    }
-
-    private String[] getStringArray(String key) {
-        String flatString = Settings.Secure.getString(mContext.getContentResolver(), key);
-        if (flatString == null) {
-            return new String[0];
-        }
-        String[] splitStrings = flatString.split(",");
-        ArrayList<String> result = new ArrayList<String>();
-        for (String pkg : splitStrings) {
-            pkg = pkg.trim();
-            if (pkg.isEmpty()) {
-                continue;
-            }
-            result.add(pkg);
-        }
-        return result.toArray(new String[result.size()]);
-    }
-
-    /**
-     * Return true if in blacklist, and not in whitelist.
-     */
-    private boolean inBlacklist(String packageName) {
-        synchronized (mLock) {
-            for (String black : mBlacklist) {
-                if (packageName.startsWith(black)) {
-                    if (inWhitelist(packageName)) {
-                        continue;
-                    } else {
-                        if (LOCAL_LOGV) Log.d(TAG, "dropping location (blacklisted): "
-                                + packageName + " matches " + black);
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Return true if any of packages are in whitelist
-     */
-    private boolean inWhitelist(String pkg) {
-        synchronized (mLock) {
-            for (String white : mWhitelist) {
-                if (pkg.startsWith(white)) return true;
-            }
-        }
-        return false;
-    }
-
-    private void checkPackageName(int uid, String packageName) {
-        if (packageName == null) {
-            throw new SecurityException("packageName cannot be null");
-        }
-        String[] packages = mPackageManager.getPackagesForUid(uid);
-        if (packages == null) {
-            throw new SecurityException("invalid UID " + uid);
-        }
-        for (String pkg : packages) {
-            if (packageName.equals(pkg)) return;
-        }
-        throw new SecurityException("invalid package name");
-    }
-
     private void log(String log) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Slog.d(TAG, log);
         }
     }
-    
+
+    @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                 != PackageManager.PERMISSION_GRANTED) {
@@ -2472,83 +2008,65 @@
                     + ", uid=" + Binder.getCallingUid());
             return;
         }
-        
+
         synchronized (mLock) {
             pw.println("Current Location Manager state:");
-            pw.println("  sProvidersLoaded=" + sProvidersLoaded);
-            pw.println("  Listeners:");
-            int N = mReceivers.size();
-            for (int i=0; i<N; i++) {
-                pw.println("    " + mReceivers.get(i));
-            }
             pw.println("  Location Listeners:");
-            for (Receiver i : mReceivers.values()) {
-                pw.println("    " + i + ":");
-                for (Map.Entry<String,UpdateRecord> j : i.mUpdateRecords.entrySet()) {
-                    pw.println("      " + j.getKey() + ":");
-                    j.getValue().dump(pw, "        ");
-                }
+            for (Receiver receiver : mReceivers.values()) {
+                pw.println("    " + receiver);
             }
-            pw.println("  Package blacklist:" + arrayToString(mBlacklist));
-            pw.println("  Package whitelist:" + arrayToString(mWhitelist));
             pw.println("  Records by Provider:");
-            for (Map.Entry<String, ArrayList<UpdateRecord>> i
-                    : mRecordsByProvider.entrySet()) {
-                pw.println("    " + i.getKey() + ":");
-                for (UpdateRecord j : i.getValue()) {
-                    pw.println("      " + j + ":");
-                    j.dump(pw, "        ");
+            for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
+                pw.println("    " + entry.getKey() + ":");
+                for (UpdateRecord record : entry.getValue()) {
+                    pw.println("      " + record);
                 }
             }
             pw.println("  Last Known Locations:");
-            for (Map.Entry<String, Location> i
-                    : mLastKnownLocation.entrySet()) {
-                pw.println("    " + i.getKey() + ":");
-                i.getValue().dump(new PrintWriterPrinter(pw), "      ");
+            for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
+                String provider = entry.getKey();
+                Location location = entry.getValue();
+                pw.println("    " + provider + ": " + location);
             }
-            if (mProximityAlerts.size() > 0) {
-                pw.println("  Proximity Alerts:");
-                for (Map.Entry<PendingIntent, ProximityAlert> i
-                        : mProximityAlerts.entrySet()) {
-                    pw.println("    " + i.getKey() + ":");
-                    i.getValue().dump(pw, "      ");
-                }
-            }
-            if (mProximitiesEntered.size() > 0) {
-                pw.println("  Proximities Entered:");
-                for (ProximityAlert i : mProximitiesEntered) {
-                    pw.println("    " + i + ":");
-                    i.dump(pw, "      ");
-                }
-            }
-            pw.println("  mProximityReceiver=" + mProximityReceiver);
-            pw.println("  mProximityListener=" + mProximityListener);
+
+            mGeofenceManager.dump(pw);
+
             if (mEnabledProviders.size() > 0) {
                 pw.println("  Enabled Providers:");
                 for (String i : mEnabledProviders) {
                     pw.println("    " + i);
                 }
-                
+
             }
             if (mDisabledProviders.size() > 0) {
                 pw.println("  Disabled Providers:");
                 for (String i : mDisabledProviders) {
                     pw.println("    " + i);
                 }
-                
             }
+            pw.append("  ");
+            mBlacklist.dump(pw);
             if (mMockProviders.size() > 0) {
                 pw.println("  Mock Providers:");
                 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
                     i.getValue().dump(pw, "      ");
                 }
             }
+
+            pw.append("  fudger: ");
+            mLocationFudger.dump(fd, pw,  args);
+
+            if (args.length > 0 && "short".equals(args[0])) {
+                return;
+            }
             for (LocationProviderInterface provider: mProviders) {
-                String state = provider.getInternalState();
-                if (state != null) {
-                    pw.println(provider.getName() + " Internal State:");
-                    pw.write(state);
+                pw.print(provider.getName() + " Internal State");
+                if (provider instanceof LocationProviderProxy) {
+                    LocationProviderProxy proxy = (LocationProviderProxy) provider;
+                    pw.print(" (" + proxy.getConnectedPackageName() + ")");
                 }
+                pw.println(":");
+                provider.dump(fd, pw, args);
             }
         }
     }
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 04267a3..c512bc1 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -16,11 +16,7 @@
 
 package com.android.server;
 
-import com.android.internal.app.IMediaContainerService;
-import com.android.internal.util.XmlUtils;
-import com.android.server.am.ActivityManagerService;
-import com.android.server.pm.PackageManagerService;
-import com.android.server.NativeDaemonConnector.Command;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
 import android.Manifest;
 import android.content.BroadcastReceiver;
@@ -30,6 +26,7 @@
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
 import android.content.res.ObbInfo;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -38,17 +35,16 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Environment;
+import android.os.Environment.UserEnvironment;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.os.storage.IMountService;
 import android.os.storage.IMountServiceListener;
 import android.os.storage.IMountShutdownObserver;
@@ -61,9 +57,19 @@
 import android.util.Slog;
 import android.util.Xml;
 
-import org.xmlpull.v1.XmlPullParser;
+import com.android.internal.app.IMediaContainerService;
+import com.android.internal.util.Preconditions;
+import com.android.internal.util.XmlUtils;
+import com.android.server.NativeDaemonConnector.Command;
+import com.android.server.am.ActivityManagerService;
+import com.android.server.pm.PackageManagerService;
+import com.android.server.pm.UserManagerService;
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
+
 import org.xmlpull.v1.XmlPullParserException;
 
+import java.io.File;
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -81,7 +87,6 @@
 import java.util.Map.Entry;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
-import java.util.Set;
 
 import javax.crypto.SecretKey;
 import javax.crypto.SecretKeyFactory;
@@ -96,9 +101,11 @@
 class MountService extends IMountService.Stub
         implements INativeDaemonConnectorCallbacks, Watchdog.Monitor {
 
-    private static final boolean LOCAL_LOGD = false;
-    private static final boolean DEBUG_UNMOUNT = false;
-    private static final boolean DEBUG_EVENTS = false;
+    // TODO: listen for user creation/deletion
+
+    private static final boolean LOCAL_LOGD = true;
+    private static final boolean DEBUG_UNMOUNT = true;
+    private static final boolean DEBUG_EVENTS = true;
     private static final boolean DEBUG_OBB = false;
 
     // Disable this since it messes up long-running cryptfs operations.
@@ -166,25 +173,34 @@
         public static final int VolumeBadRemoval               = 632;
     }
 
-    private Context                               mContext;
-    private NativeDaemonConnector                 mConnector;
-    private final ArrayList<StorageVolume>        mVolumes = new ArrayList<StorageVolume>();
-    private StorageVolume                         mPrimaryVolume;
-    private final HashMap<String, String>         mVolumeStates = new HashMap<String, String>();
-    private final HashMap<String, StorageVolume>  mVolumeMap = new HashMap<String, StorageVolume>();
-    private String                                mExternalStoragePath;
+    private Context mContext;
+    private NativeDaemonConnector mConnector;
+
+    private final Object mVolumesLock = new Object();
+
+    /** When defined, base template for user-specific {@link StorageVolume}. */
+    private StorageVolume mEmulatedTemplate;
+
+    // @GuardedBy("mVolumesLock")
+    private final ArrayList<StorageVolume> mVolumes = Lists.newArrayList();
+    /** Map from path to {@link StorageVolume} */
+    // @GuardedBy("mVolumesLock")
+    private final HashMap<String, StorageVolume> mVolumesByPath = Maps.newHashMap();
+    /** Map from path to state */
+    // @GuardedBy("mVolumesLock")
+    private final HashMap<String, String> mVolumeStates = Maps.newHashMap();
+
+    private volatile boolean mSystemReady = false;
+
     private PackageManagerService                 mPms;
     private boolean                               mUmsEnabling;
     private boolean                               mUmsAvailable = false;
     // Used as a lock for methods that register/unregister listeners.
     final private ArrayList<MountServiceBinderListener> mListeners =
             new ArrayList<MountServiceBinderListener>();
-    private boolean                               mBooted = false;
     private CountDownLatch                        mConnectedSignal = new CountDownLatch(1);
     private CountDownLatch                        mAsecsScanned = new CountDownLatch(1);
     private boolean                               mSendUmsConnectedOnBoot = false;
-    // true if we should fake MEDIA_MOUNTED state for external storage
-    private boolean                               mEmulateExternalStorage = false;
 
     /**
      * Private hash of currently mounted secure containers.
@@ -209,22 +225,31 @@
      * OBBs.
      */
     final private Map<IBinder, List<ObbState>> mObbMounts = new HashMap<IBinder, List<ObbState>>();
+
+    /** Map from raw paths to {@link ObbState}. */
     final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
 
     class ObbState implements IBinder.DeathRecipient {
-        public ObbState(String filename, int callerUid, IObbActionListener token, int nonce)
-                throws RemoteException {
-            this.filename = filename;
-            this.callerUid = callerUid;
+        public ObbState(String rawPath, String canonicalPath, int callingUid,
+                IObbActionListener token, int nonce) {
+            this.rawPath = rawPath;
+            this.canonicalPath = canonicalPath.toString();
+
+            final int userId = UserHandle.getUserId(callingUid);
+            this.ownerPath = buildObbPath(canonicalPath, userId, false);
+            this.voldPath = buildObbPath(canonicalPath, userId, true);
+
+            this.ownerGid = UserHandle.getSharedAppGid(callingUid);
             this.token = token;
             this.nonce = nonce;
         }
 
-        // OBB source filename
-        String filename;
+        final String rawPath;
+        final String canonicalPath;
+        final String ownerPath;
+        final String voldPath;
 
-        // Binder.callingUid()
-        final public int callerUid;
+        final int ownerGid;
 
         // Token of remote Binder caller
         final IObbActionListener token;
@@ -253,12 +278,13 @@
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder("ObbState{");
-            sb.append("filename=");
-            sb.append(filename);
-            sb.append(",token=");
-            sb.append(token.toString());
-            sb.append(",callerUid=");
-            sb.append(callerUid);
+            sb.append("rawPath=").append(rawPath);
+            sb.append(",canonicalPath=").append(canonicalPath);
+            sb.append(",ownerPath=").append(ownerPath);
+            sb.append(",voldPath=").append(voldPath);
+            sb.append(",ownerGid=").append(ownerGid);
+            sb.append(",token=").append(token);
+            sb.append(",binder=").append(getBinder());
             sb.append('}');
             return sb.toString();
         }
@@ -303,6 +329,8 @@
     private static final int H_UNMOUNT_PM_UPDATE = 1;
     private static final int H_UNMOUNT_PM_DONE = 2;
     private static final int H_UNMOUNT_MS = 3;
+    private static final int H_SYSTEM_READY = 4;
+
     private static final int RETRY_UNMOUNT_DELAY = 30; // in ms
     private static final int MAX_UNMOUNT_RETRIES = 4;
 
@@ -437,17 +465,26 @@
                     }
                     break;
                 }
-                case H_UNMOUNT_MS : {
+                case H_UNMOUNT_MS: {
                     if (DEBUG_UNMOUNT) Slog.i(TAG, "H_UNMOUNT_MS");
                     UnmountCallBack ucb = (UnmountCallBack) msg.obj;
                     ucb.handleFinished();
                     break;
                 }
+                case H_SYSTEM_READY: {
+                    try {
+                        handleSystemReady();
+                    } catch (Exception ex) {
+                        Slog.e(TAG, "Boot-time mount exception", ex);
+                    }
+                    break;
+                }
             }
         }
     };
-    final private HandlerThread mHandlerThread;
-    final private Handler mHandler;
+
+    private final HandlerThread mHandlerThread;
+    private final Handler mHandler;
 
     void waitForAsecScan() {
         waitForLatch(mAsecsScanned);
@@ -476,90 +513,91 @@
         }
     }
 
-    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+    private void handleSystemReady() {
+        // Snapshot current volume states since it's not safe to call into vold
+        // while holding locks.
+        final HashMap<String, String> snapshot;
+        synchronized (mVolumesLock) {
+            snapshot = new HashMap<String, String>(mVolumeStates);
+        }
+
+        for (Map.Entry<String, String> entry : snapshot.entrySet()) {
+            final String path = entry.getKey();
+            final String state = entry.getValue();
+
+            if (state.equals(Environment.MEDIA_UNMOUNTED)) {
+                int rc = doMountVolume(path);
+                if (rc != StorageResultCode.OperationSucceeded) {
+                    Slog.e(TAG, String.format("Boot-time mount failed (%d)",
+                            rc));
+                }
+            } else if (state.equals(Environment.MEDIA_SHARED)) {
+                /*
+                 * Bootstrap UMS enabled state since vold indicates
+                 * the volume is shared (runtime restart while ums enabled)
+                 */
+                notifyVolumeStateChange(null, path, VolumeState.NoMedia,
+                        VolumeState.Shared);
+            }
+        }
+
+        // Push mounted state for all emulated storage
+        synchronized (mVolumesLock) {
+            for (StorageVolume volume : mVolumes) {
+                if (volume.isEmulated()) {
+                    updatePublicVolumeState(volume, Environment.MEDIA_MOUNTED);
+                }
+            }
+        }
+
+        /*
+         * If UMS was connected on boot, send the connected event
+         * now that we're up.
+         */
+        if (mSendUmsConnectedOnBoot) {
+            sendUmsIntent(true);
+            mSendUmsConnectedOnBoot = false;
+        }
+    }
+
+    private final BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
+            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+            if (userId == -1) return;
+            final UserHandle user = new UserHandle(userId);
 
-            if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
-                mBooted = true;
-
-                /*
-                 * In the simulator, we need to broadcast a volume mounted event
-                 * to make the media scanner run.
-                 */
-                if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
-                    notifyVolumeStateChange(null, "/sdcard", VolumeState.NoMedia,
-                            VolumeState.Mounted);
-                    return;
+            final String action = intent.getAction();
+            if (Intent.ACTION_USER_ADDED.equals(action)) {
+                synchronized (mVolumesLock) {
+                    createEmulatedVolumeForUserLocked(user);
                 }
-                new Thread() {
-                    @Override
-                    public void run() {
-                        try {
-                            // it is not safe to call vold with mVolumeStates locked
-                            // so we make a copy of the paths and states and process them
-                            // outside the lock
-                            String[] paths;
-                            String[] states;
-                            int count;
-                            synchronized (mVolumeStates) {
-                                Set<String> keys = mVolumeStates.keySet();
-                                count = keys.size();
-                                paths = keys.toArray(new String[count]);
-                                states = new String[count];
-                                for (int i = 0; i < count; i++) {
-                                    states[i] = mVolumeStates.get(paths[i]);
-                                }
-                            }
 
-                            for (int i = 0; i < count; i++) {
-                                String path = paths[i];
-                                String state = states[i];
-
-                                if (state.equals(Environment.MEDIA_UNMOUNTED)) {
-                                    int rc = doMountVolume(path);
-                                    if (rc != StorageResultCode.OperationSucceeded) {
-                                        Slog.e(TAG, String.format("Boot-time mount failed (%d)",
-                                                rc));
-                                    }
-                                } else if (state.equals(Environment.MEDIA_SHARED)) {
-                                    /*
-                                     * Bootstrap UMS enabled state since vold indicates
-                                     * the volume is shared (runtime restart while ums enabled)
-                                     */
-                                    notifyVolumeStateChange(null, path, VolumeState.NoMedia,
-                                            VolumeState.Shared);
-                                }
-                            }
-
-                            /* notify external storage has mounted to trigger media scanner */
-                            if (mEmulateExternalStorage) {
-                                notifyVolumeStateChange(null,
-                                        Environment.getExternalStorageDirectory().getPath(),
-                                        VolumeState.NoMedia, VolumeState.Mounted);
-                            }
-
-                            /*
-                             * If UMS was connected on boot, send the connected event
-                             * now that we're up.
-                             */
-                            if (mSendUmsConnectedOnBoot) {
-                                sendUmsIntent(true);
-                                mSendUmsConnectedOnBoot = false;
-                            }
-                        } catch (Exception ex) {
-                            Slog.e(TAG, "Boot-time mount exception", ex);
+            } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+                synchronized (mVolumesLock) {
+                    final List<StorageVolume> toRemove = Lists.newArrayList();
+                    for (StorageVolume volume : mVolumes) {
+                        if (user.equals(volume.getOwner())) {
+                            toRemove.add(volume);
                         }
                     }
-                }.start();
-            } else if (action.equals(UsbManager.ACTION_USB_STATE)) {
-                boolean available = (intent.getBooleanExtra(UsbManager.USB_CONNECTED, false) &&
-                        intent.getBooleanExtra(UsbManager.USB_FUNCTION_MASS_STORAGE, false));
-                notifyShareAvailabilityChange(available);
+                    for (StorageVolume volume : toRemove) {
+                        removeVolumeLocked(volume);
+                    }
+                }
             }
         }
     };
+
+    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            boolean available = (intent.getBooleanExtra(UsbManager.USB_CONNECTED, false) &&
+                    intent.getBooleanExtra(UsbManager.USB_FUNCTION_MASS_STORAGE, false));
+            notifyShareAvailabilityChange(available);
+        }
+    };
+
     private final class MountServiceBinderListener implements IBinder.DeathRecipient {
         final IMountServiceListener mListener;
 
@@ -590,11 +628,13 @@
         }
     }
 
-    private void updatePublicVolumeState(String path, String state) {
-        String oldState;
-        synchronized(mVolumeStates) {
+    private void updatePublicVolumeState(StorageVolume volume, String state) {
+        final String path = volume.getPath();
+        final String oldState;
+        synchronized (mVolumesLock) {
             oldState = mVolumeStates.put(path, state);
         }
+
         if (state.equals(oldState)) {
             Slog.w(TAG, String.format("Duplicate state transition (%s -> %s) for %s",
                     state, state, path));
@@ -603,24 +643,24 @@
 
         Slog.d(TAG, "volume state changed for " + path + " (" + oldState + " -> " + state + ")");
 
-        if (path.equals(mExternalStoragePath)) {
-            // Update state on PackageManager, but only of real events
-            if (!mEmulateExternalStorage) {
-                if (Environment.MEDIA_UNMOUNTED.equals(state)) {
-                    mPms.updateExternalMediaStatus(false, false);
+        // Tell PackageManager about changes to primary volume state, but only
+        // when not emulated.
+        if (volume.isPrimary() && !volume.isEmulated()) {
+            if (Environment.MEDIA_UNMOUNTED.equals(state)) {
+                mPms.updateExternalMediaStatus(false, false);
 
-                    /*
-                     * Some OBBs might have been unmounted when this volume was
-                     * unmounted, so send a message to the handler to let it know to
-                     * remove those from the list of mounted OBBS.
-                     */
-                    mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
-                            OBB_FLUSH_MOUNT_STATE, path));
-                } else if (Environment.MEDIA_MOUNTED.equals(state)) {
-                    mPms.updateExternalMediaStatus(true, false);
-                }
+                /*
+                 * Some OBBs might have been unmounted when this volume was
+                 * unmounted, so send a message to the handler to let it know to
+                 * remove those from the list of mounted OBBS.
+                 */
+                mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
+                        OBB_FLUSH_MOUNT_STATE, path));
+            } else if (Environment.MEDIA_MOUNTED.equals(state)) {
+                mPms.updateExternalMediaStatus(true, false);
             }
         }
+
         synchronized (mListeners) {
             for (int i = mListeners.size() -1; i >= 0; i--) {
                 MountServiceBinderListener bl = mListeners.get(i);
@@ -637,7 +677,6 @@
     }
 
     /**
-     *
      * Callback from NativeDaemonConnector
      */
     public void onDaemonConnected() {
@@ -661,6 +700,11 @@
                         String path = tok[1];
                         String state = Environment.MEDIA_REMOVED;
 
+                        final StorageVolume volume;
+                        synchronized (mVolumesLock) {
+                            volume = mVolumesByPath.get(path);
+                        }
+
                         int st = Integer.parseInt(tok[2]);
                         if (st == VolumeState.NoMedia) {
                             state = Environment.MEDIA_REMOVED;
@@ -678,12 +722,15 @@
 
                         if (state != null) {
                             if (DEBUG_EVENTS) Slog.i(TAG, "Updating valid state " + state);
-                            updatePublicVolumeState(path, state);
+                            updatePublicVolumeState(volume, state);
                         }
                     }
                 } catch (Exception e) {
                     Slog.e(TAG, "Error processing initial volume state", e);
-                    updatePublicVolumeState(mExternalStoragePath, Environment.MEDIA_REMOVED);
+                    final StorageVolume primary = getPrimaryPhysicalVolume();
+                    if (primary != null) {
+                        updatePublicVolumeState(primary, Environment.MEDIA_REMOVED);
+                    }
                 }
 
                 /*
@@ -749,6 +796,13 @@
                 Slog.e(TAG, "Failed to parse major/minor", ex);
             }
 
+            final StorageVolume volume;
+            final String state;
+            synchronized (mVolumesLock) {
+                volume = mVolumesByPath.get(path);
+                state = mVolumeStates.get(path);
+            }
+
             if (code == VoldResponseCode.VolumeDiskInserted) {
                 new Thread() {
                     @Override
@@ -772,27 +826,27 @@
                 }
                 /* Send the media unmounted event first */
                 if (DEBUG_EVENTS) Slog.i(TAG, "Sending unmounted event first");
-                updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
-                sendStorageIntent(Environment.MEDIA_UNMOUNTED, path);
+                updatePublicVolumeState(volume, Environment.MEDIA_UNMOUNTED);
+                sendStorageIntent(Environment.MEDIA_UNMOUNTED, volume, UserHandle.ALL);
 
                 if (DEBUG_EVENTS) Slog.i(TAG, "Sending media removed");
-                updatePublicVolumeState(path, Environment.MEDIA_REMOVED);
+                updatePublicVolumeState(volume, Environment.MEDIA_REMOVED);
                 action = Intent.ACTION_MEDIA_REMOVED;
             } else if (code == VoldResponseCode.VolumeBadRemoval) {
                 if (DEBUG_EVENTS) Slog.i(TAG, "Sending unmounted event first");
                 /* Send the media unmounted event first */
-                updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
+                updatePublicVolumeState(volume, Environment.MEDIA_UNMOUNTED);
                 action = Intent.ACTION_MEDIA_UNMOUNTED;
 
                 if (DEBUG_EVENTS) Slog.i(TAG, "Sending media bad removal");
-                updatePublicVolumeState(path, Environment.MEDIA_BAD_REMOVAL);
+                updatePublicVolumeState(volume, Environment.MEDIA_BAD_REMOVAL);
                 action = Intent.ACTION_MEDIA_BAD_REMOVAL;
             } else {
                 Slog.e(TAG, String.format("Unknown code {%d}", code));
             }
 
             if (action != null) {
-                sendStorageIntent(action, path);
+                sendStorageIntent(action, volume, UserHandle.ALL);
             }
         } else {
             return false;
@@ -802,14 +856,20 @@
     }
 
     private void notifyVolumeStateChange(String label, String path, int oldState, int newState) {
-        String vs = getVolumeState(path);
-        if (DEBUG_EVENTS) Slog.i(TAG, "notifyVolumeStateChanged::" + vs);
+        final StorageVolume volume;
+        final String state;
+        synchronized (mVolumesLock) {
+            volume = mVolumesByPath.get(path);
+            state = getVolumeState(path);
+        }
+
+        if (DEBUG_EVENTS) Slog.i(TAG, "notifyVolumeStateChange::" + state);
 
         String action = null;
 
         if (oldState == VolumeState.Shared && newState != oldState) {
             if (LOCAL_LOGD) Slog.d(TAG, "Sending ACTION_MEDIA_UNSHARED intent");
-            sendStorageIntent(Intent.ACTION_MEDIA_UNSHARED,  path);
+            sendStorageIntent(Intent.ACTION_MEDIA_UNSHARED, volume, UserHandle.ALL);
         }
 
         if (newState == VolumeState.Init) {
@@ -820,22 +880,22 @@
              * Don't notify if we're in BAD_REMOVAL, NOFS, UNMOUNTABLE, or
              * if we're in the process of enabling UMS
              */
-            if (!vs.equals(
-                    Environment.MEDIA_BAD_REMOVAL) && !vs.equals(
-                            Environment.MEDIA_NOFS) && !vs.equals(
+            if (!state.equals(
+                    Environment.MEDIA_BAD_REMOVAL) && !state.equals(
+                            Environment.MEDIA_NOFS) && !state.equals(
                                     Environment.MEDIA_UNMOUNTABLE) && !getUmsEnabling()) {
                 if (DEBUG_EVENTS) Slog.i(TAG, "updating volume state for media bad removal nofs and unmountable");
-                updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
+                updatePublicVolumeState(volume, Environment.MEDIA_UNMOUNTED);
                 action = Intent.ACTION_MEDIA_UNMOUNTED;
             }
         } else if (newState == VolumeState.Pending) {
         } else if (newState == VolumeState.Checking) {
             if (DEBUG_EVENTS) Slog.i(TAG, "updating volume state checking");
-            updatePublicVolumeState(path, Environment.MEDIA_CHECKING);
+            updatePublicVolumeState(volume, Environment.MEDIA_CHECKING);
             action = Intent.ACTION_MEDIA_CHECKING;
         } else if (newState == VolumeState.Mounted) {
             if (DEBUG_EVENTS) Slog.i(TAG, "updating volume state mounted");
-            updatePublicVolumeState(path, Environment.MEDIA_MOUNTED);
+            updatePublicVolumeState(volume, Environment.MEDIA_MOUNTED);
             action = Intent.ACTION_MEDIA_MOUNTED;
         } else if (newState == VolumeState.Unmounting) {
             action = Intent.ACTION_MEDIA_EJECT;
@@ -843,11 +903,11 @@
         } else if (newState == VolumeState.Shared) {
             if (DEBUG_EVENTS) Slog.i(TAG, "Updating volume state media mounted");
             /* Send the media unmounted event first */
-            updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
-            sendStorageIntent(Intent.ACTION_MEDIA_UNMOUNTED, path);
+            updatePublicVolumeState(volume, Environment.MEDIA_UNMOUNTED);
+            sendStorageIntent(Intent.ACTION_MEDIA_UNMOUNTED, volume, UserHandle.ALL);
 
             if (DEBUG_EVENTS) Slog.i(TAG, "Updating media shared");
-            updatePublicVolumeState(path, Environment.MEDIA_SHARED);
+            updatePublicVolumeState(volume, Environment.MEDIA_SHARED);
             action = Intent.ACTION_MEDIA_SHARED;
             if (LOCAL_LOGD) Slog.d(TAG, "Sending ACTION_MEDIA_SHARED intent");
         } else if (newState == VolumeState.SharedMnt) {
@@ -858,13 +918,18 @@
         }
 
         if (action != null) {
-            sendStorageIntent(action, path);
+            sendStorageIntent(action, volume, UserHandle.ALL);
         }
     }
 
     private int doMountVolume(String path) {
         int rc = StorageResultCode.OperationSucceeded;
 
+        final StorageVolume volume;
+        synchronized (mVolumesLock) {
+            volume = mVolumesByPath.get(path);
+        }
+
         if (DEBUG_EVENTS) Slog.i(TAG, "doMountVolume: Mouting " + path);
         try {
             mConnector.execute("volume", "mount", path);
@@ -884,7 +949,7 @@
                 /*
                  * Media is blank or does not contain a supported filesystem
                  */
-                updatePublicVolumeState(path, Environment.MEDIA_NOFS);
+                updatePublicVolumeState(volume, Environment.MEDIA_NOFS);
                 action = Intent.ACTION_MEDIA_NOFS;
                 rc = StorageResultCode.OperationFailedMediaBlank;
             } else if (code == VoldResponseCode.OpFailedMediaCorrupt) {
@@ -892,7 +957,7 @@
                 /*
                  * Volume consistency check failed
                  */
-                updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTABLE);
+                updatePublicVolumeState(volume, Environment.MEDIA_UNMOUNTABLE);
                 action = Intent.ACTION_MEDIA_UNMOUNTABLE;
                 rc = StorageResultCode.OperationFailedMediaCorrupt;
             } else {
@@ -903,7 +968,7 @@
              * Send broadcast intent (if required for the failure)
              */
             if (action != null) {
-                sendStorageIntent(action, path);
+                sendStorageIntent(action, volume, UserHandle.ALL);
             }
         }
 
@@ -1011,14 +1076,16 @@
             }
         }
 
-        if (mBooted == true) {
+        if (mSystemReady == true) {
             sendUmsIntent(avail);
         } else {
             mSendUmsConnectedOnBoot = avail;
         }
 
-        final String path = Environment.getExternalStorageDirectory().getPath();
-        if (avail == false && getVolumeState(path).equals(Environment.MEDIA_SHARED)) {
+        final StorageVolume primary = getPrimaryPhysicalVolume();
+        if (avail == false && primary != null
+                && Environment.MEDIA_SHARED.equals(getVolumeState(primary.getPath()))) {
+            final String path = primary.getPath();
             /*
              * USB mass storage disconnected while enabled
              */
@@ -1042,17 +1109,17 @@
         }
     }
 
-    private void sendStorageIntent(String action, String path) {
-        Intent intent = new Intent(action, Uri.parse("file://" + path));
-        // add StorageVolume extra
-        intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, mVolumeMap.get(path));
-        Slog.d(TAG, "sendStorageIntent " + intent);
-        mContext.sendBroadcast(intent);
+    private void sendStorageIntent(String action, StorageVolume volume, UserHandle user) {
+        final Intent intent = new Intent(action, Uri.parse("file://" + volume.getPath()));
+        intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, volume);
+        Slog.d(TAG, "sendStorageIntent " + intent + " to " + user);
+        mContext.sendBroadcastAsUser(intent, user);
     }
 
     private void sendUmsIntent(boolean c) {
-        mContext.sendBroadcast(
-                new Intent((c ? Intent.ACTION_UMS_CONNECTED : Intent.ACTION_UMS_DISCONNECTED)));
+        mContext.sendBroadcastAsUser(
+                new Intent((c ? Intent.ACTION_UMS_CONNECTED : Intent.ACTION_UMS_DISCONNECTED)),
+                UserHandle.ALL);
     }
 
     private void validatePermission(String perm) {
@@ -1065,7 +1132,10 @@
     private static final String TAG_STORAGE_LIST = "StorageList";
     private static final String TAG_STORAGE = "storage";
 
-    private void readStorageList() {
+    private void readStorageListLocked() {
+        mVolumes.clear();
+        mVolumeStates.clear();
+
         Resources resources = mContext.getResources();
 
         int id = com.android.internal.R.xml.storage_list;
@@ -1084,7 +1154,7 @@
                     TypedArray a = resources.obtainAttributes(attrs,
                             com.android.internal.R.styleable.Storage);
 
-                    CharSequence path = a.getText(
+                    String path = a.getString(
                             com.android.internal.R.styleable.Storage_mountPoint);
                     int descriptionId = a.getResourceId(
                             com.android.internal.R.styleable.Storage_storageDescription, -1);
@@ -1109,28 +1179,29 @@
                             " emulated: " + emulated +  " mtpReserve: " + mtpReserve +
                             " allowMassStorage: " + allowMassStorage +
                             " maxFileSize: " + maxFileSize);
-                    if (path == null || description == null) {
-                        Slog.e(TAG, "path or description is null in readStorageList");
+
+                    if (emulated) {
+                        // For devices with emulated storage, we create separate
+                        // volumes for each known user.
+                        mEmulatedTemplate = new StorageVolume(null, descriptionId, true, false,
+                                true, mtpReserve, false, maxFileSize, null);
+
+                        final UserManagerService userManager = UserManagerService.getInstance();
+                        for (UserInfo user : userManager.getUsers(false)) {
+                            createEmulatedVolumeForUserLocked(user.getUserHandle());
+                        }
+
                     } else {
-                        String pathString = path.toString();
-                        StorageVolume volume = new StorageVolume(pathString,
-                                descriptionId, removable, emulated,
-                                mtpReserve, allowMassStorage, maxFileSize);
-                        if (primary) {
-                            if (mPrimaryVolume == null) {
-                                mPrimaryVolume = volume;
-                            } else {
-                                Slog.e(TAG, "multiple primary volumes in storage list");
-                            }
-                        }
-                        if (mPrimaryVolume == volume) {
-                            // primay volume must be first
-                            mVolumes.add(0, volume);
+                        if (path == null || description == null) {
+                            Slog.e(TAG, "Missing storage path or description in readStorageList");
                         } else {
-                            mVolumes.add(volume);
+                            final StorageVolume volume = new StorageVolume(new File(path),
+                                    descriptionId, primary, removable, emulated, mtpReserve,
+                                    allowMassStorage, maxFileSize, null);
+                            addVolumeLocked(volume);
                         }
-                        mVolumeMap.put(pathString, volume);
                     }
+
                     a.recycle();
                 }
             }
@@ -1139,48 +1210,101 @@
         } catch (IOException e) {
             throw new RuntimeException(e);
         } finally {
-            // compute storage ID for each volume
-            int length = mVolumes.size();
-            for (int i = 0; i < length; i++) {
-                mVolumes.get(i).setStorageId(i);
+            // Compute storage ID for each physical volume; emulated storage is
+            // always 0 when defined.
+            int index = isExternalStorageEmulated() ? 1 : 0;
+            for (StorageVolume volume : mVolumes) {
+                if (!volume.isEmulated()) {
+                    volume.setStorageId(index++);
+                }
             }
             parser.close();
         }
     }
 
     /**
+     * Create and add new {@link StorageVolume} for given {@link UserHandle}
+     * using {@link #mEmulatedTemplate} as template.
+     */
+    private void createEmulatedVolumeForUserLocked(UserHandle user) {
+        if (mEmulatedTemplate == null) {
+            throw new IllegalStateException("Missing emulated volume multi-user template");
+        }
+
+        final UserEnvironment userEnv = new UserEnvironment(user.getIdentifier());
+        final File path = userEnv.getExternalStorageDirectory();
+        final StorageVolume volume = StorageVolume.fromTemplate(mEmulatedTemplate, path, user);
+        volume.setStorageId(0);
+        addVolumeLocked(volume);
+
+        if (mSystemReady) {
+            updatePublicVolumeState(volume, Environment.MEDIA_MOUNTED);
+        } else {
+            // Place stub status for early callers to find
+            mVolumeStates.put(volume.getPath(), Environment.MEDIA_MOUNTED);
+        }
+    }
+
+    private void addVolumeLocked(StorageVolume volume) {
+        Slog.d(TAG, "addVolumeLocked() " + volume);
+        mVolumes.add(volume);
+        final StorageVolume existing = mVolumesByPath.put(volume.getPath(), volume);
+        if (existing != null) {
+            throw new IllegalStateException(
+                    "Volume at " + volume.getPath() + " already exists: " + existing);
+        }
+    }
+
+    private void removeVolumeLocked(StorageVolume volume) {
+        Slog.d(TAG, "removeVolumeLocked() " + volume);
+        mVolumes.remove(volume);
+        mVolumesByPath.remove(volume.getPath());
+        mVolumeStates.remove(volume.getPath());
+    }
+
+    private StorageVolume getPrimaryPhysicalVolume() {
+        synchronized (mVolumesLock) {
+            for (StorageVolume volume : mVolumes) {
+                if (volume.isPrimary() && !volume.isEmulated()) {
+                    return volume;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
      * Constructs a new MountService instance
      *
      * @param context  Binder context for this service
      */
     public MountService(Context context) {
         mContext = context;
-        readStorageList();
 
-        if (mPrimaryVolume != null) {
-            mExternalStoragePath = mPrimaryVolume.getPath();
-            mEmulateExternalStorage = mPrimaryVolume.isEmulated();
-            if (mEmulateExternalStorage) {
-                Slog.d(TAG, "using emulated external storage");
-                mVolumeStates.put(mExternalStoragePath, Environment.MEDIA_MOUNTED);
-            }
+        synchronized (mVolumesLock) {
+            readStorageListLocked();
         }
 
         // XXX: This will go away soon in favor of IMountServiceObserver
         mPms = (PackageManagerService) ServiceManager.getService("package");
 
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_BOOT_COMPLETED);
-        // don't bother monitoring USB if mass storage is not supported on our primary volume
-        if (mPrimaryVolume != null && mPrimaryVolume.allowMassStorage()) {
-            filter.addAction(UsbManager.ACTION_USB_STATE);
-        }
-        mContext.registerReceiver(mBroadcastReceiver, filter, null, null);
-
         mHandlerThread = new HandlerThread("MountService");
         mHandlerThread.start();
         mHandler = new MountServiceHandler(mHandlerThread.getLooper());
 
+        // Watch for user changes
+        final IntentFilter userFilter = new IntentFilter();
+        userFilter.addAction(Intent.ACTION_USER_ADDED);
+        userFilter.addAction(Intent.ACTION_USER_REMOVED);
+        mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
+
+        // Watch for USB changes on primary volume
+        final StorageVolume primary = getPrimaryPhysicalVolume();
+        if (primary != null && primary.allowMassStorage()) {
+            mContext.registerReceiver(
+                    mUsbReceiver, new IntentFilter(UsbManager.ACTION_USB_STATE), null, mHandler);
+        }
+
         // Add OBB Action Handler to MountService thread.
         mObbActionHandler = new ObbActionHandler(mHandlerThread.getLooper());
 
@@ -1200,6 +1324,11 @@
         }
     }
 
+    public void systemReady() {
+        mSystemReady = true;
+        mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
+    }
+
     /**
      * Exposed API calls below here
      */
@@ -1232,7 +1361,7 @@
         validatePermission(android.Manifest.permission.SHUTDOWN);
 
         Slog.i(TAG, "Shutting down");
-        synchronized (mVolumeStates) {
+        synchronized (mVolumesLock) {
             for (String path : mVolumeStates.keySet()) {
                 String state = mVolumeStates.get(path);
 
@@ -1313,12 +1442,15 @@
         waitForReady();
         validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
 
+        final StorageVolume primary = getPrimaryPhysicalVolume();
+        if (primary == null) return;
+
         // TODO: Add support for multiple share methods
 
         /*
          * If the volume is mounted and we're enabling then unmount it
          */
-        String path = Environment.getExternalStorageDirectory().getPath();
+        String path = primary.getPath();
         String vs = getVolumeState(path);
         String method = "ums";
         if (enable && vs.equals(Environment.MEDIA_MOUNTED)) {
@@ -1348,14 +1480,20 @@
 
     public boolean isUsbMassStorageEnabled() {
         waitForReady();
-        return doGetVolumeShared(Environment.getExternalStorageDirectory().getPath(), "ums");
+
+        final StorageVolume primary = getPrimaryPhysicalVolume();
+        if (primary != null) {
+            return doGetVolumeShared(primary.getPath(), "ums");
+        } else {
+            return false;
+        }
     }
 
     /**
      * @return state of the volume at the specified mount point
      */
     public String getVolumeState(String mountPoint) {
-        synchronized (mVolumeStates) {
+        synchronized (mVolumesLock) {
             String state = mVolumeStates.get(mountPoint);
             if (state == null) {
                 Slog.w(TAG, "getVolumeState(" + mountPoint + "): Unknown volume");
@@ -1370,8 +1508,9 @@
         }
     }
 
+    @Override
     public boolean isExternalStorageEmulated() {
-        return mEmulateExternalStorage;
+        return mEmulatedTemplate != null;
     }
 
     public int mountVolume(String path) {
@@ -1437,8 +1576,17 @@
     }
 
     private void warnOnNotMounted() {
-        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
-            Slog.w(TAG, "getSecureContainerList() called when storage not mounted");
+        final StorageVolume primary = getPrimaryPhysicalVolume();
+        if (primary != null) {
+            boolean mounted = false;
+            try {
+                mounted = Environment.MEDIA_MOUNTED.equals(getVolumeState(primary.getPath()));
+            } catch (IllegalStateException e) {
+            }
+
+            if (!mounted) {
+                Slog.w(TAG, "getSecureContainerList() called when storage not mounted");
+            }
         }
     }
 
@@ -1713,7 +1861,7 @@
             return false;
         }
 
-        final int packageUid = mPms.getPackageUid(packageName, UserId.getUserId(callerUid));
+        final int packageUid = mPms.getPackageUid(packageName, UserHandle.getUserId(callerUid));
 
         if (DEBUG_OBB) {
             Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
@@ -1723,17 +1871,24 @@
         return callerUid == packageUid;
     }
 
-    public String getMountedObbPath(String filename) {
-        if (filename == null) {
-            throw new IllegalArgumentException("filename cannot be null");
-        }
+    public String getMountedObbPath(String rawPath) {
+        Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
 
         waitForReady();
         warnOnNotMounted();
 
+        final ObbState state;
+        synchronized (mObbPathToStateMap) {
+            state = mObbPathToStateMap.get(rawPath);
+        }
+        if (state == null) {
+            Slog.w(TAG, "Failed to find OBB mounted at " + rawPath);
+            return null;
+        }
+
         final NativeDaemonEvent event;
         try {
-            event = mConnector.execute("obb", "path", filename);
+            event = mConnector.execute("obb", "path", state.voldPath);
             event.checkCode(VoldResponseCode.AsecPathResult);
             return event.getMessage();
         } catch (NativeDaemonConnectorException e) {
@@ -1746,48 +1901,52 @@
         }
     }
 
-    public boolean isObbMounted(String filename) {
-        if (filename == null) {
-            throw new IllegalArgumentException("filename cannot be null");
-        }
-
+    @Override
+    public boolean isObbMounted(String rawPath) {
+        Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
         synchronized (mObbMounts) {
-            return mObbPathToStateMap.containsKey(filename);
+            return mObbPathToStateMap.containsKey(rawPath);
         }
     }
 
-    public void mountObb(String filename, String key, IObbActionListener token, int nonce)
-            throws RemoteException {
-        if (filename == null) {
-            throw new IllegalArgumentException("filename cannot be null");
-        }
+    @Override
+    public void mountObb(
+            String rawPath, String canonicalPath, String key, IObbActionListener token, int nonce) {
+        Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
+        Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
+        Preconditions.checkNotNull(token, "token cannot be null");
 
-        if (token == null) {
-            throw new IllegalArgumentException("token cannot be null");
-        }
-
-        final int callerUid = Binder.getCallingUid();
-        final ObbState obbState = new ObbState(filename, callerUid, token, nonce);
-        final ObbAction action = new MountObbAction(obbState, key);
+        final int callingUid = Binder.getCallingUid();
+        final ObbState obbState = new ObbState(rawPath, canonicalPath, callingUid, token, nonce);
+        final ObbAction action = new MountObbAction(obbState, key, callingUid);
         mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
 
         if (DEBUG_OBB)
             Slog.i(TAG, "Send to OBB handler: " + action.toString());
     }
 
-    public void unmountObb(String filename, boolean force, IObbActionListener token, int nonce)
-            throws RemoteException {
-        if (filename == null) {
-            throw new IllegalArgumentException("filename cannot be null");
+    @Override
+    public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
+        Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
+
+        final ObbState existingState;
+        synchronized (mObbPathToStateMap) {
+            existingState = mObbPathToStateMap.get(rawPath);
         }
 
-        final int callerUid = Binder.getCallingUid();
-        final ObbState obbState = new ObbState(filename, callerUid, token, nonce);
-        final ObbAction action = new UnmountObbAction(obbState, force);
-        mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
+        if (existingState != null) {
+            // TODO: separate state object from request data
+            final int callingUid = Binder.getCallingUid();
+            final ObbState newState = new ObbState(
+                    rawPath, existingState.canonicalPath, callingUid, token, nonce);
+            final ObbAction action = new UnmountObbAction(newState, force);
+            mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
 
-        if (DEBUG_OBB)
-            Slog.i(TAG, "Send to OBB handler: " + action.toString());
+            if (DEBUG_OBB)
+                Slog.i(TAG, "Send to OBB handler: " + action.toString());
+        } else {
+            Slog.w(TAG, "Unknown OBB mount at " + rawPath);
+        }
     }
 
     @Override
@@ -1935,14 +2094,23 @@
         }
     }
 
-    public Parcelable[] getVolumeList() {
-        synchronized(mVolumes) {
-            int size = mVolumes.size();
-            Parcelable[] result = new Parcelable[size];
-            for (int i = 0; i < size; i++) {
-                result[i] = mVolumes.get(i);
+    @Override
+    public StorageVolume[] getVolumeList() {
+        final int callingUserId = UserHandle.getCallingUserId();
+        final boolean accessAll = (mContext.checkPermission(
+                android.Manifest.permission.ACCESS_ALL_EXTERNAL_STORAGE,
+                Binder.getCallingPid(), Binder.getCallingUid()) == PERMISSION_GRANTED);
+
+        synchronized (mVolumesLock) {
+            final ArrayList<StorageVolume> filtered = Lists.newArrayList();
+            for (StorageVolume volume : mVolumes) {
+                final UserHandle owner = volume.getOwner();
+                final boolean ownerMatch = owner == null || owner.getIdentifier() == callingUserId;
+                if (accessAll || ownerMatch) {
+                    filtered.add(volume);
+                }
             }
-            return result;
+            return filtered.toArray(new StorageVolume[filtered.size()]);
         }
     }
 
@@ -1955,7 +2123,7 @@
             mObbMounts.put(binder, obbStates);
         } else {
             for (final ObbState o : obbStates) {
-                if (o.filename.equals(obbState.filename)) {
+                if (o.rawPath.equals(obbState.rawPath)) {
                     throw new IllegalStateException("Attempt to add ObbState twice. "
                             + "This indicates an error in the MountService logic.");
                 }
@@ -1979,7 +2147,7 @@
             throw e;
         }
 
-        mObbPathToStateMap.put(obbState.filename, obbState);
+        mObbPathToStateMap.put(obbState.rawPath, obbState);
     }
 
     private void removeObbStateLocked(ObbState obbState) {
@@ -1994,7 +2162,7 @@
             }
         }
 
-        mObbPathToStateMap.remove(obbState.filename);
+        mObbPathToStateMap.remove(obbState.rawPath);
     }
 
     private class ObbActionHandler extends Handler {
@@ -2102,33 +2270,32 @@
                     synchronized (mObbMounts) {
                         final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
 
-                        final Iterator<Entry<String, ObbState>> i =
-                                mObbPathToStateMap.entrySet().iterator();
+                        final Iterator<ObbState> i = mObbPathToStateMap.values().iterator();
                         while (i.hasNext()) {
-                            final Entry<String, ObbState> obbEntry = i.next();
+                            final ObbState state = i.next();
 
                             /*
                              * If this entry's source file is in the volume path
                              * that got unmounted, remove it because it's no
                              * longer valid.
                              */
-                            if (obbEntry.getKey().startsWith(path)) {
-                                obbStatesToRemove.add(obbEntry.getValue());
+                            if (state.canonicalPath.startsWith(path)) {
+                                obbStatesToRemove.add(state);
                             }
                         }
 
                         for (final ObbState obbState : obbStatesToRemove) {
                             if (DEBUG_OBB)
-                                Slog.i(TAG, "Removing state for " + obbState.filename);
+                                Slog.i(TAG, "Removing state for " + obbState.rawPath);
 
                             removeObbStateLocked(obbState);
 
                             try {
-                                obbState.token.onObbResult(obbState.filename, obbState.nonce,
+                                obbState.token.onObbResult(obbState.rawPath, obbState.nonce,
                                         OnObbStateChangeListener.UNMOUNTED);
                             } catch (RemoteException e) {
                                 Slog.i(TAG, "Couldn't send unmount notification for  OBB: "
-                                        + obbState.filename);
+                                        + obbState.rawPath);
                             }
                         }
                     }
@@ -2200,14 +2367,14 @@
         protected ObbInfo getObbInfo() throws IOException {
             ObbInfo obbInfo;
             try {
-                obbInfo = mContainerService.getObbInfo(mObbState.filename);
+                obbInfo = mContainerService.getObbInfo(mObbState.ownerPath);
             } catch (RemoteException e) {
                 Slog.d(TAG, "Couldn't call DefaultContainerService to fetch OBB info for "
-                        + mObbState.filename);
+                        + mObbState.ownerPath);
                 obbInfo = null;
             }
             if (obbInfo == null) {
-                throw new IOException("Couldn't read OBB file: " + mObbState.filename);
+                throw new IOException("Couldn't read OBB file: " + mObbState.ownerPath);
             }
             return obbInfo;
         }
@@ -2218,7 +2385,7 @@
             }
 
             try {
-                mObbState.token.onObbResult(mObbState.filename, mObbState.nonce, status);
+                mObbState.token.onObbResult(mObbState.rawPath, mObbState.nonce, status);
             } catch (RemoteException e) {
                 Slog.w(TAG, "MountServiceListener went away while calling onObbStateChanged");
             }
@@ -2227,10 +2394,12 @@
 
     class MountObbAction extends ObbAction {
         private final String mKey;
+        private final int mCallingUid;
 
-        MountObbAction(ObbState obbState, String key) {
+        MountObbAction(ObbState obbState, String key, int callingUid) {
             super(obbState);
             mKey = key;
+            mCallingUid = callingUid;
         }
 
         @Override
@@ -2240,7 +2409,7 @@
 
             final ObbInfo obbInfo = getObbInfo();
 
-            if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mObbState.callerUid)) {
+            if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mCallingUid)) {
                 Slog.w(TAG, "Denied attempt to mount OBB " + obbInfo.filename
                         + " which is owned by " + obbInfo.packageName);
                 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
@@ -2249,7 +2418,7 @@
 
             final boolean isMounted;
             synchronized (mObbMounts) {
-                isMounted = mObbPathToStateMap.containsKey(obbInfo.filename);
+                isMounted = mObbPathToStateMap.containsKey(mObbState.rawPath);
             }
             if (isMounted) {
                 Slog.w(TAG, "Attempt to mount OBB which is already mounted: " + obbInfo.filename);
@@ -2257,12 +2426,6 @@
                 return;
             }
 
-            /*
-             * The filename passed in might not be the canonical name, so just
-             * set the filename to the canonicalized version.
-             */
-            mObbState.filename = obbInfo.filename;
-
             final String hashedKey;
             if (mKey == null) {
                 hashedKey = "none";
@@ -2289,7 +2452,7 @@
             int rc = StorageResultCode.OperationSucceeded;
             try {
                 mConnector.execute(
-                        "obb", "mount", mObbState.filename, hashedKey, mObbState.callerUid);
+                        "obb", "mount", mObbState.voldPath, hashedKey, mObbState.ownerGid);
             } catch (NativeDaemonConnectorException e) {
                 int code = e.getCode();
                 if (code != VoldResponseCode.OpFailedStorageBusy) {
@@ -2299,7 +2462,7 @@
 
             if (rc == StorageResultCode.OperationSucceeded) {
                 if (DEBUG_OBB)
-                    Slog.d(TAG, "Successfully mounted OBB " + mObbState.filename);
+                    Slog.d(TAG, "Successfully mounted OBB " + mObbState.voldPath);
 
                 synchronized (mObbMounts) {
                     addObbStateLocked(mObbState);
@@ -2322,14 +2485,7 @@
         public String toString() {
             StringBuilder sb = new StringBuilder();
             sb.append("MountObbAction{");
-            sb.append("filename=");
-            sb.append(mObbState.filename);
-            sb.append(",callerUid=");
-            sb.append(mObbState.callerUid);
-            sb.append(",token=");
-            sb.append(mObbState.token != null ? mObbState.token.toString() : "NULL");
-            sb.append(",binder=");
-            sb.append(mObbState.token != null ? mObbState.getBinder().toString() : "null");
+            sb.append(mObbState);
             sb.append('}');
             return sb.toString();
         }
@@ -2350,28 +2506,26 @@
 
             final ObbInfo obbInfo = getObbInfo();
 
-            final ObbState obbState;
+            final ObbState existingState;
             synchronized (mObbMounts) {
-                obbState = mObbPathToStateMap.get(obbInfo.filename);
+                existingState = mObbPathToStateMap.get(mObbState.rawPath);
             }
 
-            if (obbState == null) {
+            if (existingState == null) {
                 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_NOT_MOUNTED);
                 return;
             }
 
-            if (obbState.callerUid != mObbState.callerUid) {
-                Slog.w(TAG, "Permission denied attempting to unmount OBB " + obbInfo.filename
-                        + " (owned by " + obbInfo.packageName + ")");
+            if (existingState.ownerGid != mObbState.ownerGid) {
+                Slog.w(TAG, "Permission denied attempting to unmount OBB " + existingState.rawPath
+                        + " (owned by GID " + existingState.ownerGid + ")");
                 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
                 return;
             }
 
-            mObbState.filename = obbInfo.filename;
-
             int rc = StorageResultCode.OperationSucceeded;
             try {
-                final Command cmd = new Command("obb", "unmount", mObbState.filename);
+                final Command cmd = new Command("obb", "unmount", mObbState.voldPath);
                 if (mForceUnmount) {
                     cmd.appendArg("force");
                 }
@@ -2390,12 +2544,12 @@
 
             if (rc == StorageResultCode.OperationSucceeded) {
                 synchronized (mObbMounts) {
-                    removeObbStateLocked(obbState);
+                    removeObbStateLocked(existingState);
                 }
 
                 sendNewStatusOrIgnore(OnObbStateChangeListener.UNMOUNTED);
             } else {
-                Slog.w(TAG, "Could not mount OBB: " + mObbState.filename);
+                Slog.w(TAG, "Could not unmount OBB: " + existingState);
                 sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT);
             }
         }
@@ -2409,21 +2563,63 @@
         public String toString() {
             StringBuilder sb = new StringBuilder();
             sb.append("UnmountObbAction{");
-            sb.append("filename=");
-            sb.append(mObbState.filename != null ? mObbState.filename : "null");
+            sb.append(mObbState);
             sb.append(",force=");
             sb.append(mForceUnmount);
-            sb.append(",callerUid=");
-            sb.append(mObbState.callerUid);
-            sb.append(",token=");
-            sb.append(mObbState.token != null ? mObbState.token.toString() : "null");
-            sb.append(",binder=");
-            sb.append(mObbState.token != null ? mObbState.getBinder().toString() : "null");
             sb.append('}');
             return sb.toString();
         }
     }
 
+    // @VisibleForTesting
+    public static String buildObbPath(final String canonicalPath, int userId, boolean forVold) {
+        // TODO: allow caller to provide Environment for full testing
+
+        // Only adjust paths when storage is emulated
+        if (!Environment.isExternalStorageEmulated()) {
+            return canonicalPath;
+        }
+
+        String path = canonicalPath.toString();
+
+        // First trim off any external storage prefix
+        final UserEnvironment userEnv = new UserEnvironment(userId);
+
+        // /storage/emulated/0
+        final String externalPath = userEnv.getExternalStorageDirectory().toString();
+        // /storage/emulated_legacy
+        final String legacyExternalPath = Environment.getLegacyExternalStorageDirectory()
+                .toString();
+
+        if (path.startsWith(externalPath)) {
+            path = path.substring(externalPath.length() + 1);
+        } else if (path.startsWith(legacyExternalPath)) {
+            path = path.substring(legacyExternalPath.length() + 1);
+        } else {
+            return canonicalPath;
+        }
+
+        // Handle special OBB paths on emulated storage
+        final String obbPath = "Android/obb";
+        if (path.startsWith(obbPath)) {
+            path = path.substring(obbPath.length() + 1);
+
+            if (forVold) {
+                return new File(Environment.getEmulatedStorageObbSource(), path).toString();
+            } else {
+                final UserEnvironment ownerEnv = new UserEnvironment(UserHandle.USER_OWNER);
+                return new File(ownerEnv.getExternalStorageObbDirectory(), path).toString();
+            }
+        }
+
+        // Handle normal external storage paths
+        if (forVold) {
+            return new File(Environment.getEmulatedStorageSource(userId), path).toString();
+        } else {
+            return new File(userEnv.getExternalStorageDirectory(), path).toString();
+        }
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
@@ -2458,7 +2654,7 @@
 
         pw.println("");
 
-        synchronized (mVolumes) {
+        synchronized (mVolumesLock) {
             pw.println("  mVolumes:");
 
             final int N = mVolumes.size();
diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java
index f71125a..92af9a9 100644
--- a/services/java/com/android/server/NativeDaemonConnector.java
+++ b/services/java/com/android/server/NativeDaemonConnector.java
@@ -35,6 +35,9 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
 import java.util.LinkedList;
 
 /**
@@ -482,102 +485,108 @@
 
     private static class ResponseQueue {
 
-        private static class Response {
+        private static class PendingCmd {
             public int cmdNum;
-            public LinkedList<NativeDaemonEvent> responses = new LinkedList<NativeDaemonEvent>();
+            public BlockingQueue<NativeDaemonEvent> responses =
+                    new ArrayBlockingQueue<NativeDaemonEvent>(10);
             public String request;
-            public Response(int c, String r) {cmdNum = c; request = r;}
+
+            // The availableResponseCount member is used to track when we can remove this
+            // instance from the ResponseQueue.
+            // This is used under the protection of a sync of the mPendingCmds object.
+            // A positive value means we've had more writers retreive this object while
+            // a negative value means we've had more readers.  When we've had an equal number
+            // (it goes to zero) we can remove this object from the mPendingCmds list.
+            // Note that we may have more responses for this command (and more readers
+            // coming), but that would result in a new PendingCmd instance being created
+            // and added with the same cmdNum.
+            // Also note that when this goes to zero it just means a parity of readers and
+            // writers have retrieved this object - not that they are done using it.  The
+            // responses queue may well have more responses yet to be read or may get more
+            // responses added to it.  But all those readers/writers have retreived and
+            // hold references to this instance already so it can be removed from
+            // mPendingCmds queue.
+            public int availableResponseCount;
+            public PendingCmd(int c, String r) {cmdNum = c; request = r;}
         }
 
-        private final LinkedList<Response> mResponses;
+        private final LinkedList<PendingCmd> mPendingCmds;
         private int mMaxCount;
 
         ResponseQueue(int maxCount) {
-            mResponses = new LinkedList<Response>();
+            mPendingCmds = new LinkedList<PendingCmd>();
             mMaxCount = maxCount;
         }
 
         public void add(int cmdNum, NativeDaemonEvent response) {
-            Response found = null;
-            synchronized (mResponses) {
-                for (Response r : mResponses) {
-                    if (r.cmdNum == cmdNum) {
-                        found = r;
+            PendingCmd found = null;
+            synchronized (mPendingCmds) {
+                for (PendingCmd pendingCmd : mPendingCmds) {
+                    if (pendingCmd.cmdNum == cmdNum) {
+                        found = pendingCmd;
                         break;
                     }
                 }
                 if (found == null) {
                     // didn't find it - make sure our queue isn't too big before adding
-                    // another..
-                    while (mResponses.size() >= mMaxCount) {
+                    while (mPendingCmds.size() >= mMaxCount) {
                         Slog.e("NativeDaemonConnector.ResponseQueue",
-                                "more buffered than allowed: " + mResponses.size() +
+                                "more buffered than allowed: " + mPendingCmds.size() +
                                 " >= " + mMaxCount);
                         // let any waiter timeout waiting for this
-                        Response r = mResponses.remove();
+                        PendingCmd pendingCmd = mPendingCmds.remove();
                         Slog.e("NativeDaemonConnector.ResponseQueue",
-                                "Removing request: " + r.request + " (" + r.cmdNum + ")");
+                                "Removing request: " + pendingCmd.request + " (" +
+                                pendingCmd.cmdNum + ")");
                     }
-                    found = new Response(cmdNum, null);
-                    mResponses.add(found);
+                    found = new PendingCmd(cmdNum, null);
+                    mPendingCmds.add(found);
                 }
-                found.responses.add(response);
+                found.availableResponseCount++;
+                // if a matching remove call has already retrieved this we can remove this
+                // instance from our list
+                if (found.availableResponseCount == 0) mPendingCmds.remove(found);
             }
-            synchronized (found) {
-                found.notify();
-            }
+            try {
+                found.responses.put(response);
+            } catch (InterruptedException e) { }
         }
 
         // note that the timeout does not count time in deep sleep.  If you don't want
         // the device to sleep, hold a wakelock
         public NativeDaemonEvent remove(int cmdNum, int timeoutMs, String origCmd) {
-            long endTime = SystemClock.uptimeMillis() + timeoutMs;
-            long nowTime;
-            Response found = null;
-            while (true) {
-                synchronized (mResponses) {
-                    for (Response response : mResponses) {
-                        if (response.cmdNum == cmdNum) {
-                            found = response;
-                            // how many response fragments are left
-                            switch (response.responses.size()) {
-                            case 0:  // haven't got any - must wait
-                                break;
-                            case 1:  // last one - remove this from the master list
-                                mResponses.remove(response); // fall through
-                            default: // take one and move on
-                                response.request = origCmd;
-                                return response.responses.remove();
-                            }
-                        }
-                    }
-                    nowTime = SystemClock.uptimeMillis();
-                    if (endTime <= nowTime) {
-                        Slog.e("NativeDaemonConnector.ResponseQueue",
-                                "Timeout waiting for response");
-                        return null;
-                    }
-                    /* pre-allocate so we have something unique to wait on */
-                    if (found == null) {
-                        found = new Response(cmdNum, origCmd);
-                        mResponses.add(found);
+            PendingCmd found = null;
+            synchronized (mPendingCmds) {
+                for (PendingCmd pendingCmd : mPendingCmds) {
+                    if (pendingCmd.cmdNum == cmdNum) {
+                        found = pendingCmd;
+                        break;
                     }
                 }
-                try {
-                    synchronized (found) {
-                        found.wait(endTime - nowTime);
-                    }
-                } catch (InterruptedException e) {
-                    // loop around to check if we're done or if it's time to stop waiting
+                if (found == null) {
+                    found = new PendingCmd(cmdNum, origCmd);
+                    mPendingCmds.add(found);
                 }
+                found.availableResponseCount--;
+                // if a matching add call has already retrieved this we can remove this
+                // instance from our list
+                if (found.availableResponseCount == 0) mPendingCmds.remove(found);
             }
+            NativeDaemonEvent result = null;
+            try {
+                result = found.responses.poll(timeoutMs, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {}
+            if (result == null) {
+                Slog.e("NativeDaemonConnector.ResponseQueue", "Timeout waiting for response");
+            }
+            return result;
         }
 
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             pw.println("Pending requests:");
-            synchronized (mResponses) {
-                for (Response response : mResponses) {
-                    pw.println("  Cmd " + response.cmdNum + " - " + response.request);
+            synchronized (mPendingCmds) {
+                for (PendingCmd pendingCmd : mPendingCmds) {
+                    pw.println("  Cmd " + pendingCmd.cmdNum + " - " + pendingCmd.request);
                 }
             }
         }
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 11644e3..3ddae3e 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -35,6 +35,7 @@
 import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
 import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
 
+import android.bluetooth.BluetoothTetheringDataTracker;
 import android.content.Context;
 import android.net.INetworkManagementEventObserver;
 import android.net.InterfaceConfiguration;
@@ -44,8 +45,10 @@
 import android.net.RouteInfo;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.os.Binder;
 import android.os.Handler;
 import android.os.INetworkManagementService;
+import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -55,7 +58,9 @@
 import android.util.SparseBooleanArray;
 
 import com.android.internal.net.NetworkStatsFactory;
+import com.android.internal.util.Preconditions;
 import com.android.server.NativeDaemonConnector.Command;
+import com.android.server.net.LockdownVpnTracker;
 import com.google.android.collect.Maps;
 
 import java.io.BufferedReader;
@@ -91,6 +96,9 @@
     private static final String ADD = "add";
     private static final String REMOVE = "remove";
 
+    private static final String ALLOW = "allow";
+    private static final String DENY = "deny";
+
     private static final String DEFAULT = "default";
     private static final String SECONDARY = "secondary";
 
@@ -121,6 +129,7 @@
 
         public static final int InterfaceChange           = 600;
         public static final int BandwidthControl          = 601;
+        public static final int InterfaceClassActivity    = 613;
     }
 
     /**
@@ -151,7 +160,23 @@
     /** Set of UIDs with active reject rules. */
     private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray();
 
+    private Object mIdleTimerLock = new Object();
+    /** Set of interfaces with active idle timers. */
+    private static class IdleTimerParams {
+        public final int timeout;
+        public final String label;
+        public int networkCount;
+
+        IdleTimerParams(int timeout, String label) {
+            this.timeout = timeout;
+            this.label = label;
+            this.networkCount = 1;
+        }
+    }
+    private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap();
+
     private volatile boolean mBandwidthControlEnabled;
+    private volatile boolean mFirewallEnabled;
 
     /**
      * Constructs a new NetworkManagementService instance
@@ -278,6 +303,20 @@
     }
 
     /**
+     * Notify our observers of a change in the data activity state of the interface
+     */
+    private void notifyInterfaceClassActivity(String label, boolean active) {
+        final int length = mObservers.beginBroadcast();
+        for (int i = 0; i < length; i++) {
+            try {
+                mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged(label, active);
+            } catch (RemoteException e) {
+            }
+        }
+        mObservers.finishBroadcast();
+    }
+
+    /**
      * Prepare native daemon once connected, enabling modules and pushing any
      * existing in-memory rules.
      */
@@ -332,6 +371,9 @@
                 }
             }
         }
+
+        // TODO: Push any existing firewall state
+        setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled());
     }
 
     //
@@ -403,6 +445,19 @@
                     throw new IllegalStateException(
                             String.format("Invalid event from daemon (%s)", raw));
                     // break;
+            case NetdResponseCode.InterfaceClassActivity:
+                    /*
+                     * An network interface class state changed (active/idle)
+                     * Format: "NNN IfaceClass <active/idle> <label>"
+                     */
+                    if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) {
+                        throw new IllegalStateException(
+                                String.format("Invalid event from daemon (%s)", raw));
+                    }
+                    boolean isActive = cooked[2].equals("active");
+                    notifyInterfaceClassActivity(cooked[3], isActive);
+                    return true;
+                    // break;
             default: break;
             }
             return false;
@@ -780,6 +835,36 @@
         return event.getMessage().endsWith("started");
     }
 
+    // TODO(BT) Remove
+    public void startReverseTethering(String iface)
+             throws IllegalStateException {
+        if (DBG) Slog.d(TAG, "startReverseTethering in");
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        // cmd is "tether start first_start first_stop second_start second_stop ..."
+        // an odd number of addrs will fail
+        String cmd = "tether start-reverse";
+        cmd += " " + iface;
+        if (DBG) Slog.d(TAG, "startReverseTethering cmd: " + cmd);
+        try {
+            mConnector.doCommand(cmd);
+        } catch (NativeDaemonConnectorException e) {
+            throw new IllegalStateException("Unable to communicate to native daemon");
+        }
+        BluetoothTetheringDataTracker.getInstance().startReverseTether(iface);
+
+    }
+
+    // TODO(BT) Remove
+    public void stopReverseTethering() throws IllegalStateException {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        try {
+            mConnector.doCommand("tether stop-reverse");
+        } catch (NativeDaemonConnectorException e) {
+            throw new IllegalStateException("Unable to communicate to native daemon to stop tether");
+        }
+        BluetoothTetheringDataTracker.getInstance().stopReverseTether();
+    }
+
     @Override
     public void tetherInterface(String iface) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
@@ -923,14 +1008,14 @@
 
     @Override
     public void startAccessPoint(
-            WifiConfiguration wifiConfig, String wlanIface, String softapIface) {
+            WifiConfiguration wifiConfig, String wlanIface) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
             wifiFirmwareReload(wlanIface, "AP");
             if (wifiConfig == null) {
-                mConnector.execute("softap", "set", wlanIface, softapIface);
+                mConnector.execute("softap", "set", wlanIface);
             } else {
-                mConnector.execute("softap", "set", wlanIface, softapIface, wifiConfig.SSID,
+                mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
                         getSecurityType(wifiConfig), wifiConfig.preSharedKey);
             }
             mConnector.execute("softap", "startap");
@@ -966,7 +1051,6 @@
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
             mConnector.execute("softap", "stopap");
-            mConnector.execute("softap", "stop", wlanIface);
             wifiFirmwareReload(wlanIface, "STA");
         } catch (NativeDaemonConnectorException e) {
             throw e.rethrowAsParcelableException();
@@ -974,13 +1058,13 @@
     }
 
     @Override
-    public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface) {
+    public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
             if (wifiConfig == null) {
-                mConnector.execute("softap", "set", wlanIface, softapIface);
+                mConnector.execute("softap", "set", wlanIface);
             } else {
-                mConnector.execute("softap", "set", wlanIface, softapIface, wifiConfig.SSID,
+                mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
                         getSecurityType(wifiConfig), wifiConfig.preSharedKey);
             }
         } catch (NativeDaemonConnectorException e) {
@@ -989,6 +1073,51 @@
     }
 
     @Override
+    public void addIdleTimer(String iface, int timeout, String label) {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+
+        if (DBG) Slog.d(TAG, "Adding idletimer");
+
+        synchronized (mIdleTimerLock) {
+            IdleTimerParams params = mActiveIdleTimers.get(iface);
+            if (params != null) {
+                // the interface already has idletimer, update network count
+                params.networkCount++;
+                return;
+            }
+
+            try {
+                mConnector.execute("idletimer", "add", iface, Integer.toString(timeout), label);
+            } catch (NativeDaemonConnectorException e) {
+                throw e.rethrowAsParcelableException();
+            }
+            mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, label));
+        }
+    }
+
+    @Override
+    public void removeIdleTimer(String iface) {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+
+        if (DBG) Slog.d(TAG, "Removing idletimer");
+
+        synchronized (mIdleTimerLock) {
+            IdleTimerParams params = mActiveIdleTimers.get(iface);
+            if (params == null || --(params.networkCount) > 0) {
+                return;
+            }
+
+            try {
+                mConnector.execute("idletimer", "remove", iface,
+                        Integer.toString(params.timeout), params.label);
+            } catch (NativeDaemonConnectorException e) {
+                throw e.rethrowAsParcelableException();
+            }
+            mActiveIdleTimers.remove(iface);
+        }
+    }
+
+    @Override
     public NetworkStats getNetworkStatsSummaryDev() {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         return mStatsFactory.readNetworkStatsSummaryDev();
@@ -1307,7 +1436,79 @@
         }
     }
 
-    /** {@inheritDoc} */
+    @Override
+    public void setFirewallEnabled(boolean enabled) {
+        enforceSystemUid();
+        try {
+            mConnector.execute("firewall", enabled ? "enable" : "disable");
+            mFirewallEnabled = enabled;
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
+    public boolean isFirewallEnabled() {
+        enforceSystemUid();
+        return mFirewallEnabled;
+    }
+
+    @Override
+    public void setFirewallInterfaceRule(String iface, boolean allow) {
+        enforceSystemUid();
+        Preconditions.checkState(mFirewallEnabled);
+        final String rule = allow ? ALLOW : DENY;
+        try {
+            mConnector.execute("firewall", "set_interface_rule", iface, rule);
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
+    public void setFirewallEgressSourceRule(String addr, boolean allow) {
+        enforceSystemUid();
+        Preconditions.checkState(mFirewallEnabled);
+        final String rule = allow ? ALLOW : DENY;
+        try {
+            mConnector.execute("firewall", "set_egress_source_rule", addr, rule);
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
+    public void setFirewallEgressDestRule(String addr, int port, boolean allow) {
+        enforceSystemUid();
+        Preconditions.checkState(mFirewallEnabled);
+        final String rule = allow ? ALLOW : DENY;
+        try {
+            mConnector.execute("firewall", "set_egress_dest_rule", addr, port, rule);
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
+    public void setFirewallUidRule(int uid, boolean allow) {
+        enforceSystemUid();
+        Preconditions.checkState(mFirewallEnabled);
+        final String rule = allow ? ALLOW : DENY;
+        try {
+            mConnector.execute("firewall", "set_uid_rule", uid, rule);
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    private static void enforceSystemUid() {
+        final int uid = Binder.getCallingUid();
+        if (uid != Process.SYSTEM_UID) {
+            throw new SecurityException("Only available to AID_SYSTEM");
+        }
+    }
+
+    @Override
     public void monitor() {
         if (mConnector != null) {
             mConnector.monitor();
@@ -1338,5 +1539,7 @@
             }
             pw.println("]");
         }
+
+        pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
     }
 }
diff --git a/services/java/com/android/server/NetworkTimeUpdateService.java b/services/java/com/android/server/NetworkTimeUpdateService.java
index 76972bc..790be55 100644
--- a/services/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/java/com/android/server/NetworkTimeUpdateService.java
@@ -215,8 +215,8 @@
      * Checks if the user prefers to automatically set the time.
      */
     private boolean isAutomaticTimeRequested() {
-        return Settings.System.getInt(mContext.getContentResolver(), Settings.System.AUTO_TIME, 0)
-                != 0;
+        return Settings.Global.getInt(
+                mContext.getContentResolver(), Settings.Global.AUTO_TIME, 0) != 0;
     }
 
     /** Receiver for Nitz time events */
@@ -289,7 +289,7 @@
 
         void observe(Context context) {
             ContentResolver resolver = context.getContentResolver();
-            resolver.registerContentObserver(Settings.System.getUriFor(Settings.System.AUTO_TIME),
+            resolver.registerContentObserver(Settings.Global.getUriFor(Settings.Global.AUTO_TIME),
                     false, this);
         }
 
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index f6d3b608..f3a38f0 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -20,7 +20,9 @@
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
+import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
 import android.app.IActivityManager;
 import android.app.INotificationManager;
 import android.app.ITransientNotification;
@@ -48,20 +50,21 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.os.Vibrator;
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import android.util.AtomicFile;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
 import android.util.Xml;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
+import android.widget.RemoteViews;
 import android.widget.Toast;
 
-import com.android.internal.os.AtomicFile;
 import com.android.internal.statusbar.StatusBarNotification;
 import com.android.internal.util.FastXmlSerializer;
 
@@ -314,17 +317,20 @@
         final int id;
         final int uid;
         final int initialPid;
+        final int userId;
         final Notification notification;
         final int score;
         IBinder statusBarKey;
 
-        NotificationRecord(String pkg, String tag, int id, int uid, int initialPid, int score, Notification notification)
+        NotificationRecord(String pkg, String tag, int id, int uid, int initialPid,
+                int userId, int score, Notification notification)
         {
             this.pkg = pkg;
             this.tag = tag;
             this.id = id;
             this.uid = uid;
             this.initialPid = initialPid;
+            this.userId = userId;
             this.score = score;
             this.notification = notification;
         }
@@ -339,7 +345,7 @@
             pw.println(prefix + "  deleteIntent=" + notification.deleteIntent);
             pw.println(prefix + "  tickerText=" + notification.tickerText);
             pw.println(prefix + "  contentView=" + notification.contentView);
-            pw.println(prefix + "  uid=" + uid);
+            pw.println(prefix + "  uid=" + uid + " userId=" + userId);
             pw.println(prefix + "  defaults=0x" + Integer.toHexString(notification.defaults));
             pw.println(prefix + "  flags=0x" + Integer.toHexString(notification.flags));
             pw.println(prefix + "  sound=" + notification.sound);
@@ -426,18 +432,25 @@
         }
 
         public void onClearAll() {
-            cancelAll();
+            // XXX to be totally correct, the caller should tell us which user
+            // this is for.
+            cancelAll(ActivityManager.getCurrentUser());
         }
 
         public void onNotificationClick(String pkg, String tag, int id) {
+            // XXX to be totally correct, the caller should tell us which user
+            // this is for.
             cancelNotification(pkg, tag, id, Notification.FLAG_AUTO_CANCEL,
-                    Notification.FLAG_FOREGROUND_SERVICE, false);
+                    Notification.FLAG_FOREGROUND_SERVICE, false,
+                    ActivityManager.getCurrentUser());
         }
 
         public void onNotificationClear(String pkg, String tag, int id) {
+            // XXX to be totally correct, the caller should tell us which user
+            // this is for.
             cancelNotification(pkg, tag, id, 0,
                 Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
-                true);
+                true, ActivityManager.getCurrentUser());
         }
 
         public void onPanelRevealed() {
@@ -476,7 +489,9 @@
                 int uid, int initialPid, String message) {
             Slog.d(TAG, "onNotification error pkg=" + pkg + " tag=" + tag + " id=" + id
                     + "; will crashApplication(uid=" + uid + ", pid=" + initialPid + ")");
-            cancelNotification(pkg, tag, id, 0, 0, false);
+            // XXX to be totally correct, the caller should tell us which user
+            // this is for.
+            cancelNotification(pkg, tag, id, 0, 0, false, UserHandle.getUserId(uid));
             long ident = Binder.clearCallingIdentity();
             try {
                 ActivityManagerNative.getDefault().crashApplication(uid, initialPid, pkg,
@@ -528,7 +543,8 @@
                 }
                 if (pkgList != null && (pkgList.length > 0)) {
                     for (String pkgName : pkgList) {
-                        cancelAllNotificationsInt(pkgName, 0, 0, !queryRestart);
+                        cancelAllNotificationsInt(pkgName, 0, 0, !queryRestart,
+                                UserHandle.USER_ALL);
                     }
                 }
             } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
@@ -541,6 +557,11 @@
                 mInCall = (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
                         TelephonyManager.EXTRA_STATE_OFFHOOK));
                 updateNotificationPulse();
+            } else if (action.equals(Intent.ACTION_USER_STOPPED)) {
+                int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+                if (userHandle >= 0) {
+                    cancelAllNotificationsInt(null, 0, 0, true, userHandle);
+                }
             } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
                 // turn off LED when user passes through lock screen
                 mNotificationLight.turnOff();
@@ -605,8 +626,8 @@
         // After that, including subsequent boots, init with notifications turned on.
         // This works on the first boot because the setup wizard will toggle this
         // flag at least once and we'll go back to 0 after that.
-        if (0 == Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.DEVICE_PROVISIONED, 0)) {
+        if (0 == Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.DEVICE_PROVISIONED, 0)) {
             mDisabledNotifications = StatusBarManager.DISABLE_NOTIFICATION_ALERTS;
         }
 
@@ -616,6 +637,7 @@
         filter.addAction(Intent.ACTION_SCREEN_OFF);
         filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
         filter.addAction(Intent.ACTION_USER_PRESENT);
+        filter.addAction(Intent.ACTION_USER_STOPPED);
         mContext.registerReceiver(mIntentReceiver, filter);
         IntentFilter pkgFilter = new IntentFilter();
         pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -844,28 +866,21 @@
 
     // Notifications
     // ============================================================================
-    @Deprecated
-    public void enqueueNotification(String pkg, int id, Notification notification, int[] idOut)
-    {
-        enqueueNotificationWithTag(pkg, null /* tag */, id, notification, idOut);
-    }
-
     public void enqueueNotificationWithTag(String pkg, String tag, int id, Notification notification,
-            int[] idOut)
+            int[] idOut, int userId)
     {
         enqueueNotificationInternal(pkg, Binder.getCallingUid(), Binder.getCallingPid(),
-                tag, id, notification, idOut);
+                tag, id, notification, idOut, userId);
     }
     
     private final static int clamp(int x, int low, int high) {
         return (x < low) ? low : ((x > high) ? high : x);
     }
 
-    
     // Not exposed via Binder; for system use only (otherwise malicious apps could spoof the
     // uid/pid of another application)
     public void enqueueNotificationInternal(String pkg, int callingUid, int callingPid,
-            String tag, int id, Notification notification, int[] idOut)
+            String tag, int id, Notification notification, int[] idOut, int userId)
     {
         if (DBG) {
             Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id + " notification=" + notification);
@@ -873,6 +888,10 @@
         checkCallerIsSystemOrSameApp(pkg);
         final boolean isSystemNotification = ("android".equals(pkg));
 
+        userId = ActivityManager.handleIncomingUser(callingPid,
+                callingUid, userId, true, false, "enqueueNotification", pkg);
+        final UserHandle user = new UserHandle(userId);
+
         // Limit the number of notifications that any given package except the android
         // package can enqueue.  Prevents DOS attacks and deals with leaks.
         if (!isSystemNotification) {
@@ -881,7 +900,7 @@
                 final int N = mNotificationList.size();
                 for (int i=0; i<N; i++) {
                     final NotificationRecord r = mNotificationList.get(i);
-                    if (r.pkg.equals(pkg)) {
+                    if (r.pkg.equals(pkg) && r.userId == userId) {
                         count++;
                         if (count >= MAX_PACKAGE_NOTIFICATIONS) {
                             Slog.e(TAG, "Package has already posted " + count
@@ -897,7 +916,7 @@
         //     behalf of the download manager without affecting other apps.
         if (!pkg.equals("com.android.providers.downloads")
                 || Log.isLoggable("DownloadManager", Log.VERBOSE)) {
-            EventLog.writeEvent(EventLogTags.NOTIFICATION_ENQUEUE, pkg, id, tag,
+            EventLog.writeEvent(EventLogTags.NOTIFICATION_ENQUEUE, pkg, id, tag, userId,
                     notification.toString());
         }
 
@@ -947,12 +966,12 @@
 
         synchronized (mNotificationList) {
             NotificationRecord r = new NotificationRecord(pkg, tag, id, 
-                    callingUid, callingPid, 
+                    callingUid, callingPid, userId,
                     score,
                     notification);
             NotificationRecord old = null;
 
-            int index = indexOfNotificationLocked(pkg, tag, id);
+            int index = indexOfNotificationLocked(pkg, tag, id, userId);
             if (index < 0) {
                 mNotificationList.add(r);
             } else {
@@ -972,9 +991,17 @@
                         | Notification.FLAG_NO_CLEAR;
             }
 
+            final int currentUser;
+            final long token = Binder.clearCallingIdentity();
+            try {
+                currentUser = ActivityManager.getCurrentUser();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+
             if (notification.icon != 0) {
-                StatusBarNotification n = new StatusBarNotification(pkg, id, tag,
-                        r.uid, r.initialPid, score, notification);
+                final StatusBarNotification n = new StatusBarNotification(
+                        pkg, id, tag, r.uid, r.initialPid, score, notification, user);
                 if (old != null && old.statusBarKey != null) {
                     r.statusBarKey = old.statusBarKey;
                     long identity = Binder.clearCallingIdentity();
@@ -996,7 +1023,10 @@
                         Binder.restoreCallingIdentity(identity);
                     }
                 }
-                sendAccessibilityEvent(notification, pkg);
+                // Send accessibility events only for the current user.
+                if (currentUser == userId) {
+                    sendAccessibilityEvent(notification, pkg);
+                }
             } else {
                 Slog.e(TAG, "Ignoring notification with icon==0: " + notification);
                 if (old != null && old.statusBarKey != null) {
@@ -1014,6 +1044,8 @@
             if (((mDisabledNotifications & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) == 0)
                     && (!(old != null
                         && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
+                    && (r.userId == UserHandle.USER_ALL ||
+                        (r.userId == userId && r.userId == currentUser))
                     && mSystemReady) {
 
                 final AudioManager audioManager = (AudioManager) mContext
@@ -1037,13 +1069,14 @@
                     }
                     mSoundNotification = r;
                     // do not play notifications if stream volume is 0
-                    // (typically because ringer mode is silent).
-                    if (audioManager.getStreamVolume(audioStreamType) != 0) {
+                    // (typically because ringer mode is silent) or if speech recognition is active.
+                    if ((audioManager.getStreamVolume(audioStreamType) != 0)
+                            && !audioManager.isSpeechRecognitionActive()) {
                         final long identity = Binder.clearCallingIdentity();
                         try {
                             final IRingtonePlayer player = mAudioService.getRingtonePlayer();
                             if (player != null) {
-                                player.playAsync(uri, looping, audioStreamType);
+                                player.playAsync(uri, user, looping, audioStreamType);
                             }
                         } catch (RemoteException e) {
                         } finally {
@@ -1053,8 +1086,17 @@
                 }
 
                 // vibrate
+                // new in 4.2: if there was supposed to be a sound and we're in vibrate mode,
+                // we always vibrate, even if no vibration was specified
+                final boolean convertSoundToVibration =
+                           notification.vibrate == null
+                        && (useDefaultSound || notification.sound != null)
+                        && (audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);
+
                 final boolean useDefaultVibrate =
-                    (notification.defaults & Notification.DEFAULT_VIBRATE) != 0;
+                    (notification.defaults & Notification.DEFAULT_VIBRATE) != 0
+                    || convertSoundToVibration;
+
                 if ((useDefaultVibrate || notification.vibrate != null)
                         && !(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT)) {
                     mVibrateNotification = r;
@@ -1173,12 +1215,12 @@
      * and none of the {@code mustNotHaveFlags}.
      */
     private void cancelNotification(String pkg, String tag, int id, int mustHaveFlags,
-            int mustNotHaveFlags, boolean sendDelete) {
-        EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL, pkg, id, tag,
+            int mustNotHaveFlags, boolean sendDelete, int userId) {
+        EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL, pkg, id, tag, userId,
                 mustHaveFlags, mustNotHaveFlags);
 
         synchronized (mNotificationList) {
-            int index = indexOfNotificationLocked(pkg, tag, id);
+            int index = indexOfNotificationLocked(pkg, tag, id, userId);
             if (index >= 0) {
                 NotificationRecord r = mNotificationList.get(index);
 
@@ -1198,26 +1240,47 @@
     }
 
     /**
+     * Determine whether the userId applies to the notification in question, either because
+     * they match exactly, or one of them is USER_ALL (which is treated as a wildcard).
+     */
+    private boolean notificationMatchesUserId(NotificationRecord r, int userId) {
+        return
+                // looking for USER_ALL notifications? match everything
+                   userId == UserHandle.USER_ALL
+                // a notification sent to USER_ALL matches any query
+                || r.userId == UserHandle.USER_ALL
+                // an exact user match
+                || r.userId == userId;
+    }
+
+    /**
      * Cancels all notifications from a given package that have all of the
      * {@code mustHaveFlags}.
      */
     boolean cancelAllNotificationsInt(String pkg, int mustHaveFlags,
-            int mustNotHaveFlags, boolean doit) {
-        EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL_ALL, pkg, mustHaveFlags,
-                mustNotHaveFlags);
+            int mustNotHaveFlags, boolean doit, int userId) {
+        EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL_ALL, pkg, userId,
+                mustHaveFlags, mustNotHaveFlags);
 
         synchronized (mNotificationList) {
             final int N = mNotificationList.size();
             boolean canceledSomething = false;
             for (int i = N-1; i >= 0; --i) {
                 NotificationRecord r = mNotificationList.get(i);
+                if (!notificationMatchesUserId(r, userId)) {
+                    continue;
+                }
+                // Don't remove notifications to all, if there's no package name specified
+                if (r.userId == UserHandle.USER_ALL && pkg == null) {
+                    continue;
+                }
                 if ((r.notification.flags & mustHaveFlags) != mustHaveFlags) {
                     continue;
                 }
                 if ((r.notification.flags & mustNotHaveFlags) != 0) {
                     continue;
                 }
-                if (!r.pkg.equals(pkg)) {
+                if (pkg != null && !r.pkg.equals(pkg)) {
                     continue;
                 }
                 canceledSomething = true;
@@ -1234,30 +1297,30 @@
         }
     }
 
-    @Deprecated
-    public void cancelNotification(String pkg, int id) {
-        cancelNotificationWithTag(pkg, null /* tag */, id);
-    }
-
-    public void cancelNotificationWithTag(String pkg, String tag, int id) {
+    public void cancelNotificationWithTag(String pkg, String tag, int id, int userId) {
         checkCallerIsSystemOrSameApp(pkg);
+        userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+                Binder.getCallingUid(), userId, true, false, "cancelNotificationWithTag", pkg);
         // Don't allow client applications to cancel foreground service notis.
         cancelNotification(pkg, tag, id, 0,
                 Binder.getCallingUid() == Process.SYSTEM_UID
-                ? 0 : Notification.FLAG_FOREGROUND_SERVICE, false);
+                ? 0 : Notification.FLAG_FOREGROUND_SERVICE, false, userId);
     }
 
-    public void cancelAllNotifications(String pkg) {
+    public void cancelAllNotifications(String pkg, int userId) {
         checkCallerIsSystemOrSameApp(pkg);
 
+        userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+                Binder.getCallingUid(), userId, true, false, "cancelAllNotifications", pkg);
+
         // Calling from user space, don't allow the canceling of actively
         // running foreground services.
-        cancelAllNotificationsInt(pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true);
+        cancelAllNotificationsInt(pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true, userId);
     }
 
     void checkCallerIsSystem() {
         int uid = Binder.getCallingUid();
-        if (uid == Process.SYSTEM_UID || uid == 0) {
+        if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) {
             return;
         }
         throw new SecurityException("Disallowed call for uid " + uid);
@@ -1265,27 +1328,31 @@
 
     void checkCallerIsSystemOrSameApp(String pkg) {
         int uid = Binder.getCallingUid();
-        if (uid == Process.SYSTEM_UID || uid == 0) {
+        if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) {
             return;
         }
         try {
-            ApplicationInfo ai = mContext.getPackageManager().getApplicationInfo(
-                    pkg, 0);
-            if (!UserId.isSameApp(ai.uid, uid)) {
+            ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo(
+                    pkg, 0, UserHandle.getCallingUserId());
+            if (!UserHandle.isSameApp(ai.uid, uid)) {
                 throw new SecurityException("Calling uid " + uid + " gave package"
                         + pkg + " which is owned by uid " + ai.uid);
             }
-        } catch (PackageManager.NameNotFoundException e) {
-            throw new SecurityException("Unknown package " + pkg);
+        } catch (RemoteException re) {
+            throw new SecurityException("Unknown package " + pkg + "\n" + re);
         }
     }
 
-    void cancelAll() {
+    void cancelAll(int userId) {
         synchronized (mNotificationList) {
             final int N = mNotificationList.size();
             for (int i=N-1; i>=0; i--) {
                 NotificationRecord r = mNotificationList.get(i);
 
+                if (!notificationMatchesUserId(r, userId)) {
+                    continue;
+                }
+
                 if ((r.notification.flags & (Notification.FLAG_ONGOING_EVENT
                                 | Notification.FLAG_NO_CLEAR)) == 0) {
                     mNotificationList.remove(i);
@@ -1330,12 +1397,15 @@
     }
 
     // lock on mNotificationList
-    private int indexOfNotificationLocked(String pkg, String tag, int id)
+    private int indexOfNotificationLocked(String pkg, String tag, int id, int userId)
     {
         ArrayList<NotificationRecord> list = mNotificationList;
         final int len = list.size();
         for (int i=0; i<len; i++) {
             NotificationRecord r = list.get(i);
+            if (!notificationMatchesUserId(r, userId) || r.id != id) {
+                continue;
+            }
             if (tag == null) {
                 if (r.tag != null) {
                     continue;
@@ -1345,7 +1415,7 @@
                     continue;
                 }
             }
-            if (r.id == id && r.pkg.equals(pkg)) {
+            if (r.pkg.equals(pkg)) {
                 return i;
             }
         }
diff --git a/services/java/com/android/server/NsdService.java b/services/java/com/android/server/NsdService.java
index 87843d9..1b9742c 100644
--- a/services/java/com/android/server/NsdService.java
+++ b/services/java/com/android/server/NsdService.java
@@ -31,6 +31,7 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.IBinder;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -130,7 +131,7 @@
             };
 
             mContext.getContentResolver().registerContentObserver(
-                    Settings.Secure.getUriFor(Settings.Secure.NSD_ON),
+                    Settings.Global.getUriFor(Settings.Global.NSD_ON),
                     false, contentObserver);
         }
 
@@ -432,7 +433,7 @@
     public void setEnabled(boolean enable) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL,
                 "NsdService");
-        Settings.Secure.putInt(mContentResolver, Settings.Secure.NSD_ON, enable ? 1 : 0);
+        Settings.Global.putInt(mContentResolver, Settings.Global.NSD_ON, enable ? 1 : 0);
         if (enable) {
             mNsdStateMachine.sendMessage(NsdManager.ENABLE);
         } else {
@@ -448,11 +449,11 @@
         } else {
             intent.putExtra(NsdManager.EXTRA_NSD_STATE, NsdManager.NSD_STATE_DISABLED);
         }
-        mContext.sendStickyBroadcast(intent);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private boolean isNsdEnabled() {
-        boolean ret = Settings.Secure.getInt(mContentResolver, Settings.Secure.NSD_ON, 1) == 1;
+        boolean ret = Settings.Global.getInt(mContentResolver, Settings.Global.NSD_ON, 1) == 1;
         if (DBG) Slog.d(TAG, "Network service discovery enabled " + ret);
         return ret;
     }
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
deleted file mode 100644
index 888ec69..0000000
--- a/services/java/com/android/server/PowerManagerService.java
+++ /dev/null
@@ -1,3405 +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.
- */
-
-package com.android.server;
-
-import com.android.internal.app.IBatteryStats;
-import com.android.server.am.BatteryStatsService;
-import com.android.server.pm.ShutdownThread;
-
-import android.app.ActivityManagerNative;
-import android.app.IActivityManager;
-import android.content.BroadcastReceiver;
-import android.content.ContentQueryMap;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.hardware.SystemSensorManager;
-import android.os.BatteryManager;
-import android.os.BatteryStats;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.IPowerManager;
-import android.os.LocalPowerManager;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.WorkSource;
-import android.provider.Settings;
-import android.util.EventLog;
-import android.util.Log;
-import android.util.Slog;
-import android.view.WindowManagerPolicy;
-import static android.view.WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR;
-import static android.provider.Settings.System.DIM_SCREEN;
-import static android.provider.Settings.System.SCREEN_BRIGHTNESS;
-import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE;
-import static android.provider.Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ;
-import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
-import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-import static android.provider.Settings.System.STAY_ON_WHILE_PLUGGED_IN;
-import static android.provider.Settings.System.WINDOW_ANIMATION_SCALE;
-import static android.provider.Settings.System.TRANSITION_ANIMATION_SCALE;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Observable;
-import java.util.Observer;
-
-public class PowerManagerService extends IPowerManager.Stub
-        implements LocalPowerManager, Watchdog.Monitor {
-    private static final int NOMINAL_FRAME_TIME_MS = 1000/60;
-
-    private static final String TAG = "PowerManagerService";
-    static final String PARTIAL_NAME = "PowerManagerService";
-
-    // Wake lock that ensures that the CPU is running.  The screen might not be on.
-    private static final int PARTIAL_WAKE_LOCK_ID = 1;
-
-    // Wake lock that ensures that the screen is on.
-    private static final int FULL_WAKE_LOCK_ID = 2;
-
-    static final boolean DEBUG_SCREEN_ON = false;
-
-    private static final boolean LOG_PARTIAL_WL = false;
-
-    // Indicates whether touch-down cycles should be logged as part of the
-    // LOG_POWER_SCREEN_STATE log events
-    private static final boolean LOG_TOUCH_DOWNS = true;
-
-    private static final int LOCK_MASK = PowerManager.PARTIAL_WAKE_LOCK
-                                        | PowerManager.SCREEN_DIM_WAKE_LOCK
-                                        | PowerManager.SCREEN_BRIGHT_WAKE_LOCK
-                                        | PowerManager.FULL_WAKE_LOCK
-                                        | PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
-
-    //                       time since last state:               time since last event:
-    // The short keylight delay comes from secure settings; this is the default.
-    private static final int SHORT_KEYLIGHT_DELAY_DEFAULT = 6000; // t+6 sec
-    private static final int MEDIUM_KEYLIGHT_DELAY = 15000;       // t+15 sec
-    private static final int LONG_KEYLIGHT_DELAY = 6000;        // t+6 sec
-    private static final int LONG_DIM_TIME = 7000;              // t+N-5 sec
-
-    // How long to wait to debounce light sensor changes in milliseconds
-    private static final int LIGHT_SENSOR_DELAY = 2000;
-
-    // light sensor events rate in microseconds
-    private static final int LIGHT_SENSOR_RATE = 1000000;
-
-    // Expansion of range of light values when applying scale from light
-    // sensor brightness setting, in the [0..255] brightness range.
-    private static final int LIGHT_SENSOR_RANGE_EXPANSION = 20;
-
-    // Scaling factor of the light sensor brightness setting when applying
-    // it to the final brightness.
-    private static final int LIGHT_SENSOR_OFFSET_SCALE = 8;
-
-    // For debouncing the proximity sensor in milliseconds
-    private static final int PROXIMITY_SENSOR_DELAY = 1000;
-
-    // trigger proximity if distance is less than 5 cm
-    private static final float PROXIMITY_THRESHOLD = 5.0f;
-
-    // Cached secure settings; see updateSettingsValues()
-    private int mShortKeylightDelay = SHORT_KEYLIGHT_DELAY_DEFAULT;
-
-    // Default timeout for screen off, if not found in settings database = 15 seconds.
-    private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15000;
-
-    // Screen brightness should always have a value, but just in case...
-    private static final int DEFAULT_SCREEN_BRIGHTNESS = 192;
-
-    // Threshold for BRIGHTNESS_LOW_BATTERY (percentage)
-    // Screen will stay dim if battery level is <= LOW_BATTERY_THRESHOLD
-    private static final int LOW_BATTERY_THRESHOLD = 10;
-
-    // flags for setPowerState
-    private static final int ALL_LIGHTS_OFF         = 0x00000000;
-    private static final int SCREEN_ON_BIT          = 0x00000001;
-    private static final int SCREEN_BRIGHT_BIT      = 0x00000002;
-    private static final int BUTTON_BRIGHT_BIT      = 0x00000004;
-    private static final int KEYBOARD_BRIGHT_BIT    = 0x00000008;
-    private static final int BATTERY_LOW_BIT        = 0x00000010;
-
-    // values for setPowerState
-
-    // SCREEN_OFF == everything off
-    private static final int SCREEN_OFF         = 0x00000000;
-
-    // SCREEN_DIM == screen on, screen backlight dim
-    private static final int SCREEN_DIM         = SCREEN_ON_BIT;
-
-    // SCREEN_BRIGHT == screen on, screen backlight bright
-    private static final int SCREEN_BRIGHT      = SCREEN_ON_BIT | SCREEN_BRIGHT_BIT;
-
-    // SCREEN_BUTTON_BRIGHT == screen on, screen and button backlights bright
-    private static final int SCREEN_BUTTON_BRIGHT  = SCREEN_BRIGHT | BUTTON_BRIGHT_BIT;
-
-    // SCREEN_BUTTON_BRIGHT == screen on, screen, button and keyboard backlights bright
-    private static final int ALL_BRIGHT         = SCREEN_BUTTON_BRIGHT | KEYBOARD_BRIGHT_BIT;
-
-    // used for noChangeLights in setPowerState()
-    private static final int LIGHTS_MASK        = SCREEN_BRIGHT_BIT | BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT;
-
-    // animate screen lights in PowerManager (as opposed to SurfaceFlinger)
-    boolean mAnimateScreenLights = true;
-
-    static final int ANIM_STEPS = 60; // nominal # of frames at 60Hz
-    // Slower animation for autobrightness changes
-    static final int AUTOBRIGHTNESS_ANIM_STEPS = 2 * ANIM_STEPS;
-    // Even slower animation for autodimness changes. Set to max to effectively disable dimming.
-    // Note 100 is used to keep the mWindowScaleAnimation scaling below from overflowing an int.
-    static final int AUTODIMNESS_ANIM_STEPS = Integer.MAX_VALUE / (NOMINAL_FRAME_TIME_MS * 100);
-    // Number of steps when performing a more immediate brightness change.
-    static final int IMMEDIATE_ANIM_STEPS = 4;
-
-    // These magic numbers are the initial state of the LEDs at boot.  Ideally
-    // we should read them from the driver, but our current hardware returns 0
-    // for the initial value.  Oops!
-    static final int INITIAL_SCREEN_BRIGHTNESS = 255;
-    static final int INITIAL_BUTTON_BRIGHTNESS = PowerManager.BRIGHTNESS_OFF;
-    static final int INITIAL_KEYBOARD_BRIGHTNESS = PowerManager.BRIGHTNESS_OFF;
-
-    private final int MY_UID;
-    private final int MY_PID;
-
-    private boolean mDoneBooting = false;
-    private boolean mBootCompleted = false;
-    private boolean mHeadless = false;
-    private int mStayOnConditions = 0;
-    private final int[] mBroadcastQueue = new int[] { -1, -1, -1 };
-    private final int[] mBroadcastWhy = new int[3];
-    private boolean mPreparingForScreenOn = false;
-    private boolean mSkippedScreenOn = false;
-    private boolean mInitialized = false;
-    private int mPartialCount = 0;
-    private int mPowerState;
-    // mScreenOffReason can be WindowManagerPolicy.OFF_BECAUSE_OF_USER,
-    // WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT or WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR
-    private int mScreenOffReason;
-    private int mUserState;
-    private boolean mKeyboardVisible = false;
-    private boolean mUserActivityAllowed = true;
-    private int mProximityWakeLockCount = 0;
-    private boolean mProximitySensorEnabled = false;
-    private boolean mProximitySensorActive = false;
-    private int mProximityPendingValue = -1; // -1 == nothing, 0 == inactive, 1 == active
-    private long mLastProximityEventTime;
-    private int mScreenOffTimeoutSetting;
-    private int mMaximumScreenOffTimeout = Integer.MAX_VALUE;
-    private int mKeylightDelay;
-    private int mDimDelay;
-    private int mScreenOffDelay;
-    private int mWakeLockState;
-    private long mLastEventTime = 0;
-    private long mScreenOffTime;
-    private volatile WindowManagerPolicy mPolicy;
-    private final LockList mLocks = new LockList();
-    private Intent mScreenOffIntent;
-    private Intent mScreenOnIntent;
-    private LightsService mLightsService;
-    private Context mContext;
-    private LightsService.Light mLcdLight;
-    private LightsService.Light mButtonLight;
-    private LightsService.Light mKeyboardLight;
-    private LightsService.Light mAttentionLight;
-    private UnsynchronizedWakeLock mBroadcastWakeLock;
-    private UnsynchronizedWakeLock mStayOnWhilePluggedInScreenDimLock;
-    private UnsynchronizedWakeLock mStayOnWhilePluggedInPartialLock;
-    private UnsynchronizedWakeLock mPreventScreenOnPartialLock;
-    private UnsynchronizedWakeLock mProximityPartialLock;
-    private HandlerThread mHandlerThread;
-    private Handler mScreenOffHandler;
-    private Handler mScreenBrightnessHandler;
-    private Handler mHandler;
-    private final TimeoutTask mTimeoutTask = new TimeoutTask();
-    private ScreenBrightnessAnimator mScreenBrightnessAnimator;
-    private boolean mWaitingForFirstLightSensor = false;
-    private boolean mStillNeedSleepNotification;
-    private boolean mIsPowered = false;
-    private IActivityManager mActivityService;
-    private IBatteryStats mBatteryStats;
-    private BatteryService mBatteryService;
-    private SensorManager mSensorManager;
-    private Sensor mProximitySensor;
-    private Sensor mLightSensor;
-    private boolean mLightSensorEnabled;
-    private float mLightSensorValue = -1;
-    private boolean mProxIgnoredBecauseScreenTurnedOff = false;
-    private int mHighestLightSensorValue = -1;
-    private boolean mLightSensorPendingDecrease = false;
-    private boolean mLightSensorPendingIncrease = false;
-    private float mLightSensorPendingValue = -1;
-    private float mLightSensorAdjustSetting = 0;
-    private int mLightSensorScreenBrightness = -1;
-    private int mLightSensorButtonBrightness = -1;
-    private int mLightSensorKeyboardBrightness = -1;
-    private boolean mDimScreen = true;
-    private boolean mIsDocked = false;
-    private long mNextTimeout;
-    private volatile int mPokey = 0;
-    private volatile boolean mPokeAwakeOnSet = false;
-    private volatile boolean mInitComplete = false;
-    private final HashMap<IBinder,PokeLock> mPokeLocks = new HashMap<IBinder,PokeLock>();
-    // mLastScreenOnTime is the time the screen was last turned on
-    private long mLastScreenOnTime;
-    private boolean mPreventScreenOn;
-    private int mScreenBrightnessSetting = DEFAULT_SCREEN_BRIGHTNESS;
-    private int mScreenBrightnessOverride = -1;
-    private int mButtonBrightnessOverride = -1;
-    private int mScreenBrightnessDim;
-    private boolean mUseSoftwareAutoBrightness;
-    private boolean mAutoBrightessEnabled;
-    private int[] mAutoBrightnessLevels;
-    private int[] mLcdBacklightValues;
-    private int[] mButtonBacklightValues;
-    private int[] mKeyboardBacklightValues;
-    private int mLightSensorWarmupTime;
-    boolean mUnplugTurnsOnScreen;
-    private int mWarningSpewThrottleCount;
-    private long mWarningSpewThrottleTime;
-    private int mAnimationSetting = ANIM_SETTING_OFF;
-    private float mWindowScaleAnimation;
-
-    // Must match with the ISurfaceComposer constants in C++.
-    private static final int ANIM_SETTING_ON = 0x01;
-    private static final int ANIM_SETTING_OFF = 0x10;
-
-    // Used when logging number and duration of touch-down cycles
-    private long mTotalTouchDownTime;
-    private long mLastTouchDown;
-    private int mTouchCycles;
-
-    // could be either static or controllable at runtime
-    private static final boolean mSpew = false;
-    private static final boolean mDebugProximitySensor = (false || mSpew);
-    private static final boolean mDebugLightSensor = (false || mSpew);
-    private static final boolean mDebugLightAnimation = (false || mSpew);
-
-    private native void nativeInit();
-    private native void nativeSetPowerState(boolean screenOn, boolean screenBright);
-    private native void nativeStartSurfaceFlingerAnimation(int mode);
-    private static native void nativeAcquireWakeLock(int lock, String id);
-    private static native void nativeReleaseWakeLock(String id);
-    private static native int nativeSetScreenState(boolean on);
-    private static native void nativeShutdown();
-    private static native void nativeReboot(String reason) throws IOException;
-
-    /*
-    static PrintStream mLog;
-    static {
-        try {
-            mLog = new PrintStream("/data/power.log");
-        }
-        catch (FileNotFoundException e) {
-            android.util.Slog.e(TAG, "Life is hard", e);
-        }
-    }
-    static class Log {
-        static void d(String tag, String s) {
-            mLog.println(s);
-            android.util.Slog.d(tag, s);
-        }
-        static void i(String tag, String s) {
-            mLog.println(s);
-            android.util.Slog.i(tag, s);
-        }
-        static void w(String tag, String s) {
-            mLog.println(s);
-            android.util.Slog.w(tag, s);
-        }
-        static void e(String tag, String s) {
-            mLog.println(s);
-            android.util.Slog.e(tag, s);
-        }
-    }
-    */
-
-    /**
-     * This class works around a deadlock between the lock in PowerManager.WakeLock
-     * and our synchronizing on mLocks.  PowerManager.WakeLock synchronizes on its
-     * mToken object so it can be accessed from any thread, but it calls into here
-     * with its lock held.  This class is essentially a reimplementation of
-     * PowerManager.WakeLock, but without that extra synchronized block, because we'll
-     * only call it with our own locks held.
-     */
-    private class UnsynchronizedWakeLock {
-        int mFlags;
-        String mTag;
-        IBinder mToken;
-        int mCount = 0;
-        boolean mRefCounted;
-        boolean mHeld;
-
-        UnsynchronizedWakeLock(int flags, String tag, boolean refCounted) {
-            mFlags = flags;
-            mTag = tag;
-            mToken = new Binder();
-            mRefCounted = refCounted;
-        }
-
-        public void acquire() {
-            if (!mRefCounted || mCount++ == 0) {
-                long ident = Binder.clearCallingIdentity();
-                try {
-                    PowerManagerService.this.acquireWakeLockLocked(mFlags, mToken,
-                            MY_UID, MY_PID, mTag, null);
-                    mHeld = true;
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
-            }
-        }
-
-        public void release() {
-            if (!mRefCounted || --mCount == 0) {
-                PowerManagerService.this.releaseWakeLockLocked(mToken, 0, false);
-                mHeld = false;
-            }
-            if (mCount < 0) {
-                throw new RuntimeException("WakeLock under-locked " + mTag);
-            }
-        }
-
-        public boolean isHeld()
-        {
-            return mHeld;
-        }
-
-        public String toString() {
-            return "UnsynchronizedWakeLock(mFlags=0x" + Integer.toHexString(mFlags)
-                    + " mCount=" + mCount + " mHeld=" + mHeld + ")";
-        }
-    }
-
-    private final class BatteryReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            synchronized (mLocks) {
-                boolean wasPowered = mIsPowered;
-                mIsPowered = mBatteryService.isPowered();
-
-                if (mIsPowered != wasPowered) {
-                    // update mStayOnWhilePluggedIn wake lock
-                    updateWakeLockLocked();
-
-                    // treat plugging and unplugging the devices as a user activity.
-                    // users find it disconcerting when they unplug the device
-                    // and it shuts off right away.
-                    // to avoid turning on the screen when unplugging, we only trigger
-                    // user activity when screen was already on.
-                    // temporarily set mUserActivityAllowed to true so this will work
-                    // even when the keyguard is on.
-                    // However, you can also set config_unplugTurnsOnScreen to have it
-                    // turn on.  Some devices want this because they don't have a
-                    // charging LED.
-                    synchronized (mLocks) {
-                        if (!wasPowered || (mPowerState & SCREEN_ON_BIT) != 0 ||
-                                mUnplugTurnsOnScreen) {
-                            forceUserActivityLocked();
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private final class BootCompletedReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            bootCompleted();
-        }
-    }
-
-    private final class DockReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
-                    Intent.EXTRA_DOCK_STATE_UNDOCKED);
-            dockStateChanged(state);
-        }
-    }
-
-    /**
-     * Set the setting that determines whether the device stays on when plugged in.
-     * The argument is a bit string, with each bit specifying a power source that,
-     * when the device is connected to that source, causes the device to stay on.
-     * See {@link android.os.BatteryManager} for the list of power sources that
-     * can be specified. Current values include {@link android.os.BatteryManager#BATTERY_PLUGGED_AC}
-     * and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB}
-     * @param val an {@code int} containing the bits that specify which power sources
-     * should cause the device to stay on.
-     */
-    public void setStayOnSetting(int val) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS, null);
-        Settings.System.putInt(mContext.getContentResolver(),
-                Settings.System.STAY_ON_WHILE_PLUGGED_IN, val);
-    }
-
-    public void setMaximumScreenOffTimeount(int timeMs) {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.WRITE_SECURE_SETTINGS, null);
-        synchronized (mLocks) {
-            mMaximumScreenOffTimeout = timeMs;
-            // recalculate everything
-            setScreenOffTimeoutsLocked();
-        }
-    }
-
-    int getStayOnConditionsLocked() {
-        return mMaximumScreenOffTimeout <= 0 || mMaximumScreenOffTimeout == Integer.MAX_VALUE
-                ? mStayOnConditions : 0;
-    }
-
-    private class SettingsObserver implements Observer {
-        private int getInt(String name, int defValue) {
-            ContentValues values = mSettings.getValues(name);
-            Integer iVal = values != null ? values.getAsInteger(Settings.System.VALUE) : null;
-            return iVal != null ? iVal : defValue;
-        }
-
-        private float getFloat(String name, float defValue) {
-            ContentValues values = mSettings.getValues(name);
-            Float fVal = values != null ? values.getAsFloat(Settings.System.VALUE) : null;
-            return fVal != null ? fVal : defValue;
-        }
-
-        public void update(Observable o, Object arg) {
-            synchronized (mLocks) {
-                // STAY_ON_WHILE_PLUGGED_IN, default to when plugged into AC
-                mStayOnConditions = getInt(STAY_ON_WHILE_PLUGGED_IN,
-                        BatteryManager.BATTERY_PLUGGED_AC);
-                updateWakeLockLocked();
-
-                // SCREEN_OFF_TIMEOUT, default to 15 seconds
-                mScreenOffTimeoutSetting = getInt(SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT);
-
-                // DIM_SCREEN
-                //mDimScreen = getInt(DIM_SCREEN) != 0;
-
-                mScreenBrightnessSetting = getInt(SCREEN_BRIGHTNESS, DEFAULT_SCREEN_BRIGHTNESS);
-                mLightSensorAdjustSetting = 0; //getFloat(SCREEN_AUTO_BRIGHTNESS_ADJ, 0);
-
-                // SCREEN_BRIGHTNESS_MODE, default to manual
-                setScreenBrightnessMode(getInt(SCREEN_BRIGHTNESS_MODE,
-                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL));
-
-                // recalculate everything
-                setScreenOffTimeoutsLocked();
-
-                mWindowScaleAnimation = getFloat(WINDOW_ANIMATION_SCALE, 1.0f);
-                final float transitionScale = getFloat(TRANSITION_ANIMATION_SCALE, 1.0f);
-                mAnimationSetting = 0;
-                if (mWindowScaleAnimation > 0.5f) {
-                    mAnimationSetting |= ANIM_SETTING_OFF;
-                }
-                if (transitionScale > 0.5f) {
-                    // Uncomment this if you want the screen-on animation.
-                    // mAnimationSetting |= ANIM_SETTING_ON;
-                }
-            }
-        }
-    }
-
-    PowerManagerService() {
-        // Hack to get our uid...  should have a func for this.
-        long token = Binder.clearCallingIdentity();
-        MY_UID = Process.myUid();
-        MY_PID = Process.myPid();
-        Binder.restoreCallingIdentity(token);
-
-        // assume nothing is on yet
-        mUserState = mPowerState = 0;
-
-        // Add ourself to the Watchdog monitors.
-        Watchdog.getInstance().addMonitor(this);
-
-        nativeInit();
-    }
-
-    private ContentQueryMap mSettings;
-
-    void init(Context context, LightsService lights, IActivityManager activity,
-            BatteryService battery) {
-        mLightsService = lights;
-        mContext = context;
-        mActivityService = activity;
-        mBatteryStats = BatteryStatsService.getService();
-        mBatteryService = battery;
-
-        mLcdLight = lights.getLight(LightsService.LIGHT_ID_BACKLIGHT);
-        mButtonLight = lights.getLight(LightsService.LIGHT_ID_BUTTONS);
-        mKeyboardLight = lights.getLight(LightsService.LIGHT_ID_KEYBOARD);
-        mAttentionLight = lights.getLight(LightsService.LIGHT_ID_ATTENTION);
-        mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
-
-        mInitComplete = false;
-        mScreenBrightnessAnimator = new ScreenBrightnessAnimator("mScreenBrightnessUpdaterThread",
-                Process.THREAD_PRIORITY_DISPLAY);
-        mScreenBrightnessAnimator.start();
-
-        synchronized (mScreenBrightnessAnimator) {
-            while (!mInitComplete) {
-                try {
-                    mScreenBrightnessAnimator.wait();
-                } catch (InterruptedException e) {
-                    // Ignore
-                }
-            }
-        }
-
-        mInitComplete = false;
-        mHandlerThread = new HandlerThread("PowerManagerService") {
-            @Override
-            protected void onLooperPrepared() {
-                super.onLooperPrepared();
-                initInThread();
-            }
-        };
-        mHandlerThread.start();
-
-        synchronized (mHandlerThread) {
-            while (!mInitComplete) {
-                try {
-                    mHandlerThread.wait();
-                } catch (InterruptedException e) {
-                    // Ignore
-                }
-            }
-        }
-
-        synchronized (mLocks) {
-            updateNativePowerStateLocked();
-            // We make sure to start out with the screen on due to user activity.
-            // (They did just boot their device, after all.)
-            forceUserActivityLocked();
-            mInitialized = true;
-        }
-    }
-
-    void initInThread() {
-        mHandler = new Handler();
-
-        mBroadcastWakeLock = new UnsynchronizedWakeLock(
-                                PowerManager.PARTIAL_WAKE_LOCK, "sleep_broadcast", true);
-        mStayOnWhilePluggedInScreenDimLock = new UnsynchronizedWakeLock(
-                                PowerManager.SCREEN_DIM_WAKE_LOCK, "StayOnWhilePluggedIn Screen Dim", false);
-        mStayOnWhilePluggedInPartialLock = new UnsynchronizedWakeLock(
-                                PowerManager.PARTIAL_WAKE_LOCK, "StayOnWhilePluggedIn Partial", false);
-        mPreventScreenOnPartialLock = new UnsynchronizedWakeLock(
-                                PowerManager.PARTIAL_WAKE_LOCK, "PreventScreenOn Partial", false);
-        mProximityPartialLock = new UnsynchronizedWakeLock(
-                                PowerManager.PARTIAL_WAKE_LOCK, "Proximity Partial", false);
-
-        mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
-        mScreenOnIntent.addFlags(
-                Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
-        mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
-        mScreenOffIntent.addFlags(
-                Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
-
-        Resources resources = mContext.getResources();
-
-        mAnimateScreenLights = resources.getBoolean(
-                com.android.internal.R.bool.config_animateScreenLights);
-
-        mUnplugTurnsOnScreen = resources.getBoolean(
-                com.android.internal.R.bool.config_unplugTurnsOnScreen);
-
-        mScreenBrightnessDim = resources.getInteger(
-                com.android.internal.R.integer.config_screenBrightnessDim);
-
-        // read settings for auto-brightness
-        mUseSoftwareAutoBrightness = resources.getBoolean(
-                com.android.internal.R.bool.config_automatic_brightness_available);
-        if (mUseSoftwareAutoBrightness) {
-            mAutoBrightnessLevels = resources.getIntArray(
-                    com.android.internal.R.array.config_autoBrightnessLevels);
-            mLcdBacklightValues = resources.getIntArray(
-                    com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
-            mButtonBacklightValues = resources.getIntArray(
-                    com.android.internal.R.array.config_autoBrightnessButtonBacklightValues);
-            mKeyboardBacklightValues = resources.getIntArray(
-                    com.android.internal.R.array.config_autoBrightnessKeyboardBacklightValues);
-            mLightSensorWarmupTime = resources.getInteger(
-                    com.android.internal.R.integer.config_lightSensorWarmupTime);
-        }
-
-       ContentResolver resolver = mContext.getContentResolver();
-        Cursor settingsCursor = resolver.query(Settings.System.CONTENT_URI, null,
-                "(" + Settings.System.NAME + "=?) or ("
-                        + Settings.System.NAME + "=?) or ("
-                        + Settings.System.NAME + "=?) or ("
-                        + Settings.System.NAME + "=?) or ("
-                        + Settings.System.NAME + "=?) or ("
-                        + Settings.System.NAME + "=?) or ("
-                        + Settings.System.NAME + "=?) or ("
-                        + Settings.System.NAME + "=?)",
-                new String[]{STAY_ON_WHILE_PLUGGED_IN, SCREEN_OFF_TIMEOUT, DIM_SCREEN, SCREEN_BRIGHTNESS,
-                        SCREEN_BRIGHTNESS_MODE, /*SCREEN_AUTO_BRIGHTNESS_ADJ,*/
-                        WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE},
-                null);
-        mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mHandler);
-        SettingsObserver settingsObserver = new SettingsObserver();
-        mSettings.addObserver(settingsObserver);
-
-        // pretend that the settings changed so we will get their initial state
-        settingsObserver.update(mSettings, null);
-
-        // register for the battery changed notifications
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
-        mContext.registerReceiver(new BatteryReceiver(), filter);
-        filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_BOOT_COMPLETED);
-        mContext.registerReceiver(new BootCompletedReceiver(), filter);
-        filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_DOCK_EVENT);
-        mContext.registerReceiver(new DockReceiver(), filter);
-
-        // Listen for secure settings changes
-        mContext.getContentResolver().registerContentObserver(
-            Settings.Secure.CONTENT_URI, true,
-            new ContentObserver(new Handler()) {
-                public void onChange(boolean selfChange) {
-                    updateSettingsValues();
-                }
-            });
-        updateSettingsValues();
-
-        synchronized (mHandlerThread) {
-            mInitComplete = true;
-            mHandlerThread.notifyAll();
-        }
-    }
-
-    /**
-     * Low-level function turn the device off immediately, without trying
-     * to be clean.  Most people should use
-     * {@link com.android.server.pm.internal.app.ShutdownThread} for a clean shutdown.
-     */
-    public static void lowLevelShutdown() {
-        nativeShutdown();
-    }
-
-    /**
-     * Low-level function to reboot the device.
-     *
-     * @param reason code to pass to the kernel (e.g. "recovery"), or null.
-     * @throws IOException if reboot fails for some reason (eg, lack of
-     *         permission)
-     */
-    public static void lowLevelReboot(String reason) throws IOException {
-        nativeReboot(reason);
-    }
-
-    private class WakeLock implements IBinder.DeathRecipient
-    {
-        WakeLock(int f, IBinder b, String t, int u, int p) {
-            super();
-            flags = f;
-            binder = b;
-            tag = t;
-            uid = u == MY_UID ? Process.SYSTEM_UID : u;
-            pid = p;
-            if (u != MY_UID || (
-                    !"KEEP_SCREEN_ON_FLAG".equals(tag)
-                    && !"KeyInputQueue".equals(tag))) {
-                monitorType = (f & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK
-                        ? BatteryStats.WAKE_TYPE_PARTIAL
-                        : BatteryStats.WAKE_TYPE_FULL;
-            } else {
-                monitorType = -1;
-            }
-            try {
-                b.linkToDeath(this, 0);
-            } catch (RemoteException e) {
-                binderDied();
-            }
-        }
-        public void binderDied() {
-            synchronized (mLocks) {
-                releaseWakeLockLocked(this.binder, 0, true);
-            }
-        }
-        final int flags;
-        final IBinder binder;
-        final String tag;
-        final int uid;
-        final int pid;
-        final int monitorType;
-        WorkSource ws;
-        boolean activated = true;
-        int minState;
-    }
-
-    private void updateWakeLockLocked() {
-        final int stayOnConditions = getStayOnConditionsLocked();
-        if (stayOnConditions != 0 && mBatteryService.isPowered(stayOnConditions)) {
-            // keep the device on if we're plugged in and mStayOnWhilePluggedIn is set.
-            mStayOnWhilePluggedInScreenDimLock.acquire();
-            mStayOnWhilePluggedInPartialLock.acquire();
-        } else {
-            mStayOnWhilePluggedInScreenDimLock.release();
-            mStayOnWhilePluggedInPartialLock.release();
-        }
-    }
-
-    private boolean isScreenLock(int flags)
-    {
-        int n = flags & LOCK_MASK;
-        return n == PowerManager.FULL_WAKE_LOCK
-                || n == PowerManager.SCREEN_BRIGHT_WAKE_LOCK
-                || n == PowerManager.SCREEN_DIM_WAKE_LOCK
-                || n == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
-    }
-
-    void enforceWakeSourcePermission(int uid, int pid) {
-        if (uid == Process.myUid()) {
-            return;
-        }
-        mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
-                pid, uid, null);
-    }
-
-    public void acquireWakeLock(int flags, IBinder lock, String tag, WorkSource ws) {
-        int uid = Binder.getCallingUid();
-        int pid = Binder.getCallingPid();
-        if (uid != Process.myUid()) {
-            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
-        }
-        if (ws != null) {
-            enforceWakeSourcePermission(uid, pid);
-        }
-        long ident = Binder.clearCallingIdentity();
-        try {
-            synchronized (mLocks) {
-                acquireWakeLockLocked(flags, lock, uid, pid, tag, ws);
-            }
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
-    void noteStartWakeLocked(WakeLock wl, WorkSource ws) {
-        if (wl.monitorType >= 0) {
-            long origId = Binder.clearCallingIdentity();
-            try {
-                if (ws != null) {
-                    mBatteryStats.noteStartWakelockFromSource(ws, wl.pid, wl.tag,
-                            wl.monitorType);
-                } else {
-                    mBatteryStats.noteStartWakelock(wl.uid, wl.pid, wl.tag, wl.monitorType);
-                }
-            } catch (RemoteException e) {
-                // Ignore
-            } finally {
-                Binder.restoreCallingIdentity(origId);
-            }
-        }
-    }
-
-    void noteStopWakeLocked(WakeLock wl, WorkSource ws) {
-        if (wl.monitorType >= 0) {
-            long origId = Binder.clearCallingIdentity();
-            try {
-                if (ws != null) {
-                    mBatteryStats.noteStopWakelockFromSource(ws, wl.pid, wl.tag,
-                            wl.monitorType);
-                } else {
-                    mBatteryStats.noteStopWakelock(wl.uid, wl.pid, wl.tag, wl.monitorType);
-                }
-            } catch (RemoteException e) {
-                // Ignore
-            } finally {
-                Binder.restoreCallingIdentity(origId);
-            }
-        }
-    }
-
-    public void acquireWakeLockLocked(int flags, IBinder lock, int uid, int pid, String tag,
-            WorkSource ws) {
-        if (mSpew) {
-            Slog.d(TAG, "acquireWakeLock flags=0x" + Integer.toHexString(flags) + " tag=" + tag);
-        }
-
-        if (ws != null && ws.size() == 0) {
-            ws = null;
-        }
-
-        int index = mLocks.getIndex(lock);
-        WakeLock wl;
-        boolean newlock;
-        boolean diffsource;
-        WorkSource oldsource;
-        if (index < 0) {
-            wl = new WakeLock(flags, lock, tag, uid, pid);
-            switch (wl.flags & LOCK_MASK)
-            {
-                case PowerManager.FULL_WAKE_LOCK:
-                    if (mUseSoftwareAutoBrightness) {
-                        wl.minState = SCREEN_BRIGHT;
-                    } else {
-                        wl.minState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
-                    }
-                    break;
-                case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
-                    wl.minState = SCREEN_BRIGHT;
-                    break;
-                case PowerManager.SCREEN_DIM_WAKE_LOCK:
-                    wl.minState = SCREEN_DIM;
-                    break;
-                case PowerManager.PARTIAL_WAKE_LOCK:
-                case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
-                    break;
-                default:
-                    // just log and bail.  we're in the server, so don't
-                    // throw an exception.
-                    Slog.e(TAG, "bad wakelock type for lock '" + tag + "' "
-                            + " flags=" + flags);
-                    return;
-            }
-            mLocks.addLock(wl);
-            if (ws != null) {
-                wl.ws = new WorkSource(ws);
-            }
-            newlock = true;
-            diffsource = false;
-            oldsource = null;
-        } else {
-            wl = mLocks.get(index);
-            newlock = false;
-            oldsource = wl.ws;
-            if (oldsource != null) {
-                if (ws == null) {
-                    wl.ws = null;
-                    diffsource = true;
-                } else {
-                    diffsource = oldsource.diff(ws);
-                }
-            } else if (ws != null) {
-                diffsource = true;
-            } else {
-                diffsource = false;
-            }
-            if (diffsource) {
-                wl.ws = new WorkSource(ws);
-            }
-        }
-        if (isScreenLock(flags)) {
-            // if this causes a wakeup, we reactivate all of the locks and
-            // set it to whatever they want.  otherwise, we modulate that
-            // by the current state so we never turn it more on than
-            // it already is.
-            if ((flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
-                mProximityWakeLockCount++;
-                if (mProximityWakeLockCount == 1) {
-                    enableProximityLockLocked();
-                }
-            } else {
-                if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
-                    int oldWakeLockState = mWakeLockState;
-                    mWakeLockState = mLocks.reactivateScreenLocksLocked();
-
-                    // Disable proximity sensor if if user presses power key while we are in the
-                    // "waiting for proximity sensor to go negative" state.
-                    if ((mWakeLockState & SCREEN_ON_BIT) != 0
-                            && mProximitySensorActive && mProximityWakeLockCount == 0) {
-                        mProximitySensorActive = false;
-                    }
-
-                    if (mSpew) {
-                        Slog.d(TAG, "wakeup here mUserState=0x" + Integer.toHexString(mUserState)
-                                + " mWakeLockState=0x"
-                                + Integer.toHexString(mWakeLockState)
-                                + " previous wakeLockState=0x"
-                                + Integer.toHexString(oldWakeLockState));
-                    }
-                } else {
-                    if (mSpew) {
-                        Slog.d(TAG, "here mUserState=0x" + Integer.toHexString(mUserState)
-                                + " mLocks.gatherState()=0x"
-                                + Integer.toHexString(mLocks.gatherState())
-                                + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState));
-                    }
-                    mWakeLockState = (mUserState | mWakeLockState) & mLocks.gatherState();
-                }
-                setPowerState(mWakeLockState | mUserState);
-            }
-        }
-        else if ((flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
-            if (newlock) {
-                mPartialCount++;
-                if (mPartialCount == 1) {
-                    if (LOG_PARTIAL_WL) EventLog.writeEvent(EventLogTags.POWER_PARTIAL_WAKE_STATE, 1, tag);
-                }
-            }
-            nativeAcquireWakeLock(PARTIAL_WAKE_LOCK_ID, PARTIAL_NAME);
-        }
-
-        if (diffsource) {
-            // If the lock sources have changed, need to first release the
-            // old ones.
-            noteStopWakeLocked(wl, oldsource);
-        }
-        if (newlock || diffsource) {
-            noteStartWakeLocked(wl, ws);
-        }
-    }
-
-    public void updateWakeLockWorkSource(IBinder lock, WorkSource ws) {
-        int uid = Binder.getCallingUid();
-        int pid = Binder.getCallingPid();
-        if (ws != null && ws.size() == 0) {
-            ws = null;
-        }
-        if (ws != null) {
-            enforceWakeSourcePermission(uid, pid);
-        }
-        synchronized (mLocks) {
-            int index = mLocks.getIndex(lock);
-            if (index < 0) {
-                throw new IllegalArgumentException("Wake lock not active");
-            }
-            WakeLock wl = mLocks.get(index);
-            WorkSource oldsource = wl.ws;
-            wl.ws = ws != null ? new WorkSource(ws) : null;
-            noteStopWakeLocked(wl, oldsource);
-            noteStartWakeLocked(wl, ws);
-        }
-    }
-
-    public void releaseWakeLock(IBinder lock, int flags) {
-        int uid = Binder.getCallingUid();
-        if (uid != Process.myUid()) {
-            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
-        }
-
-        synchronized (mLocks) {
-            releaseWakeLockLocked(lock, flags, false);
-        }
-    }
-
-    private void releaseWakeLockLocked(IBinder lock, int flags, boolean death) {
-        WakeLock wl = mLocks.removeLock(lock);
-        if (wl == null) {
-            return;
-        }
-
-        if (mSpew) {
-            Slog.d(TAG, "releaseWakeLock flags=0x"
-                    + Integer.toHexString(wl.flags) + " tag=" + wl.tag);
-        }
-
-        if (isScreenLock(wl.flags)) {
-            if ((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
-                mProximityWakeLockCount--;
-                if (mProximityWakeLockCount == 0) {
-                    if (mProximitySensorActive &&
-                            ((flags & PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE) != 0)) {
-                        // wait for proximity sensor to go negative before disabling sensor
-                        if (mDebugProximitySensor) {
-                            Slog.d(TAG, "waiting for proximity sensor to go negative");
-                        }
-                    } else {
-                        disableProximityLockLocked();
-                    }
-                }
-            } else {
-                mWakeLockState = mLocks.gatherState();
-                // goes in the middle to reduce flicker
-                if ((wl.flags & PowerManager.ON_AFTER_RELEASE) != 0) {
-                    userActivity(SystemClock.uptimeMillis(), -1, false, OTHER_EVENT, false, true);
-                }
-                setPowerState(mWakeLockState | mUserState);
-            }
-        }
-        else if ((wl.flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
-            mPartialCount--;
-            if (mPartialCount == 0) {
-                if (LOG_PARTIAL_WL) EventLog.writeEvent(EventLogTags.POWER_PARTIAL_WAKE_STATE, 0, wl.tag);
-                nativeReleaseWakeLock(PARTIAL_NAME);
-            }
-        }
-        // Unlink the lock from the binder.
-        wl.binder.unlinkToDeath(wl, 0);
-
-        noteStopWakeLocked(wl, wl.ws);
-    }
-
-    private class PokeLock implements IBinder.DeathRecipient
-    {
-        PokeLock(int p, IBinder b, String t) {
-            super();
-            this.pokey = p;
-            this.binder = b;
-            this.tag = t;
-            try {
-                b.linkToDeath(this, 0);
-            } catch (RemoteException e) {
-                binderDied();
-            }
-        }
-        public void binderDied() {
-            setPokeLock(0, this.binder, this.tag);
-        }
-        int pokey;
-        IBinder binder;
-        String tag;
-        boolean awakeOnSet;
-    }
-
-    public void setPokeLock(int pokey, IBinder token, String tag) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-        if (token == null) {
-            Slog.e(TAG, "setPokeLock got null token for tag='" + tag + "'");
-            return;
-        }
-
-        if ((pokey & POKE_LOCK_TIMEOUT_MASK) == POKE_LOCK_TIMEOUT_MASK) {
-            throw new IllegalArgumentException("setPokeLock can't have both POKE_LOCK_SHORT_TIMEOUT"
-                    + " and POKE_LOCK_MEDIUM_TIMEOUT");
-        }
-
-        synchronized (mLocks) {
-            if (pokey != 0) {
-                PokeLock p = mPokeLocks.get(token);
-                int oldPokey = 0;
-                if (p != null) {
-                    oldPokey = p.pokey;
-                    p.pokey = pokey;
-                } else {
-                    p = new PokeLock(pokey, token, tag);
-                    mPokeLocks.put(token, p);
-                }
-                int oldTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
-                int newTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
-                if (((mPowerState & SCREEN_ON_BIT) == 0) && (oldTimeout != newTimeout)) {
-                    p.awakeOnSet = true;
-                }
-            } else {
-                PokeLock rLock = mPokeLocks.remove(token);
-                if (rLock != null) {
-                    token.unlinkToDeath(rLock, 0);
-                }
-            }
-
-            int oldPokey = mPokey;
-            int cumulative = 0;
-            boolean awakeOnSet = false;
-            for (PokeLock p: mPokeLocks.values()) {
-                cumulative |= p.pokey;
-                if (p.awakeOnSet) {
-                    awakeOnSet = true;
-                }
-            }
-            mPokey = cumulative;
-            mPokeAwakeOnSet = awakeOnSet;
-
-            int oldCumulativeTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
-            int newCumulativeTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
-
-            if (oldCumulativeTimeout != newCumulativeTimeout) {
-                setScreenOffTimeoutsLocked();
-                // reset the countdown timer, but use the existing nextState so it doesn't
-                // change anything
-                setTimeoutLocked(SystemClock.uptimeMillis(), mTimeoutTask.nextState);
-            }
-        }
-    }
-
-    private static String lockType(int type)
-    {
-        switch (type)
-        {
-            case PowerManager.FULL_WAKE_LOCK:
-                return "FULL_WAKE_LOCK                ";
-            case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
-                return "SCREEN_BRIGHT_WAKE_LOCK       ";
-            case PowerManager.SCREEN_DIM_WAKE_LOCK:
-                return "SCREEN_DIM_WAKE_LOCK          ";
-            case PowerManager.PARTIAL_WAKE_LOCK:
-                return "PARTIAL_WAKE_LOCK             ";
-            case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
-                return "PROXIMITY_SCREEN_OFF_WAKE_LOCK";
-            default:
-                return "???                           ";
-        }
-    }
-
-    private static String dumpPowerState(int state) {
-        return (((state & KEYBOARD_BRIGHT_BIT) != 0)
-                        ? "KEYBOARD_BRIGHT_BIT " : "")
-                + (((state & SCREEN_BRIGHT_BIT) != 0)
-                        ? "SCREEN_BRIGHT_BIT " : "")
-                + (((state & SCREEN_ON_BIT) != 0)
-                        ? "SCREEN_ON_BIT " : "")
-                + (((state & BUTTON_BRIGHT_BIT) != 0)
-                        ? "BUTTON_BRIGHT_BIT " : "")
-                + (((state & BATTERY_LOW_BIT) != 0)
-                        ? "BATTERY_LOW_BIT " : "");
-    }
-
-    @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump PowerManager from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
-
-        long now = SystemClock.uptimeMillis();
-
-        synchronized (mLocks) {
-            pw.println("Power Manager State:");
-            pw.println("  mIsPowered=" + mIsPowered
-                    + " mPowerState=" + mPowerState
-                    + " mScreenOffTime=" + (SystemClock.elapsedRealtime()-mScreenOffTime)
-                    + " ms");
-            pw.println("  mPartialCount=" + mPartialCount);
-            pw.println("  mWakeLockState=" + dumpPowerState(mWakeLockState));
-            pw.println("  mUserState=" + dumpPowerState(mUserState));
-            pw.println("  mPowerState=" + dumpPowerState(mPowerState));
-            pw.println("  mLocks.gather=" + dumpPowerState(mLocks.gatherState()));
-            pw.println("  mNextTimeout=" + mNextTimeout + " now=" + now
-                    + " " + ((mNextTimeout-now)/1000) + "s from now");
-            pw.println("  mDimScreen=" + mDimScreen
-                    + " mStayOnConditions=" + mStayOnConditions
-                    + " mPreparingForScreenOn=" + mPreparingForScreenOn
-                    + " mSkippedScreenOn=" + mSkippedScreenOn);
-            pw.println("  mScreenOffReason=" + mScreenOffReason
-                    + " mUserState=" + mUserState);
-            pw.println("  mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1]
-                    + ',' + mBroadcastQueue[2] + "}");
-            pw.println("  mBroadcastWhy={" + mBroadcastWhy[0] + ',' + mBroadcastWhy[1]
-                    + ',' + mBroadcastWhy[2] + "}");
-            pw.println("  mPokey=" + mPokey + " mPokeAwakeonSet=" + mPokeAwakeOnSet);
-            pw.println("  mKeyboardVisible=" + mKeyboardVisible
-                    + " mUserActivityAllowed=" + mUserActivityAllowed);
-            pw.println("  mKeylightDelay=" + mKeylightDelay + " mDimDelay=" + mDimDelay
-                    + " mScreenOffDelay=" + mScreenOffDelay);
-            pw.println("  mPreventScreenOn=" + mPreventScreenOn
-                    + "  mScreenBrightnessOverride=" + mScreenBrightnessOverride
-                    + "  mButtonBrightnessOverride=" + mButtonBrightnessOverride);
-            pw.println("  mScreenOffTimeoutSetting=" + mScreenOffTimeoutSetting
-                    + " mMaximumScreenOffTimeout=" + mMaximumScreenOffTimeout);
-            pw.println("  mLastScreenOnTime=" + mLastScreenOnTime);
-            pw.println("  mBroadcastWakeLock=" + mBroadcastWakeLock);
-            pw.println("  mStayOnWhilePluggedInScreenDimLock=" + mStayOnWhilePluggedInScreenDimLock);
-            pw.println("  mStayOnWhilePluggedInPartialLock=" + mStayOnWhilePluggedInPartialLock);
-            pw.println("  mPreventScreenOnPartialLock=" + mPreventScreenOnPartialLock);
-            pw.println("  mProximityPartialLock=" + mProximityPartialLock);
-            pw.println("  mProximityWakeLockCount=" + mProximityWakeLockCount);
-            pw.println("  mProximitySensorEnabled=" + mProximitySensorEnabled);
-            pw.println("  mProximitySensorActive=" + mProximitySensorActive);
-            pw.println("  mProximityPendingValue=" + mProximityPendingValue);
-            pw.println("  mLastProximityEventTime=" + mLastProximityEventTime);
-            pw.println("  mLightSensorEnabled=" + mLightSensorEnabled
-                    + " mLightSensorAdjustSetting=" + mLightSensorAdjustSetting);
-            pw.println("  mLightSensorValue=" + mLightSensorValue
-                    + " mLightSensorPendingValue=" + mLightSensorPendingValue);
-            pw.println("  mHighestLightSensorValue=" + mHighestLightSensorValue
-                    + " mWaitingForFirstLightSensor=" + mWaitingForFirstLightSensor);
-            pw.println("  mLightSensorPendingDecrease=" + mLightSensorPendingDecrease
-                    + " mLightSensorPendingIncrease=" + mLightSensorPendingIncrease);
-            pw.println("  mLightSensorScreenBrightness=" + mLightSensorScreenBrightness
-                    + " mLightSensorButtonBrightness=" + mLightSensorButtonBrightness
-                    + " mLightSensorKeyboardBrightness=" + mLightSensorKeyboardBrightness);
-            pw.println("  mUseSoftwareAutoBrightness=" + mUseSoftwareAutoBrightness);
-            pw.println("  mAutoBrightessEnabled=" + mAutoBrightessEnabled);
-            mScreenBrightnessAnimator.dump(pw, "mScreenBrightnessAnimator: ");
-
-            int N = mLocks.size();
-            pw.println();
-            pw.println("mLocks.size=" + N + ":");
-            for (int i=0; i<N; i++) {
-                WakeLock wl = mLocks.get(i);
-                String type = lockType(wl.flags & LOCK_MASK);
-                String acquireCausesWakeup = "";
-                if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
-                    acquireCausesWakeup = "ACQUIRE_CAUSES_WAKEUP ";
-                }
-                String activated = "";
-                if (wl.activated) {
-                   activated = " activated";
-                }
-                pw.println("  " + type + " '" + wl.tag + "'" + acquireCausesWakeup
-                        + activated + " (minState=" + wl.minState + ", uid=" + wl.uid
-                        + ", pid=" + wl.pid + ")");
-            }
-
-            pw.println();
-            pw.println("mPokeLocks.size=" + mPokeLocks.size() + ":");
-            for (PokeLock p: mPokeLocks.values()) {
-                pw.println("    poke lock '" + p.tag + "':"
-                        + ((p.pokey & POKE_LOCK_IGNORE_TOUCH_EVENTS) != 0
-                                ? " POKE_LOCK_IGNORE_TOUCH_EVENTS" : "")
-                        + ((p.pokey & POKE_LOCK_SHORT_TIMEOUT) != 0
-                                ? " POKE_LOCK_SHORT_TIMEOUT" : "")
-                        + ((p.pokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0
-                                ? " POKE_LOCK_MEDIUM_TIMEOUT" : ""));
-            }
-
-            pw.println();
-        }
-    }
-
-    private void setTimeoutLocked(long now, int nextState) {
-        setTimeoutLocked(now, -1, nextState);
-    }
-
-    // If they gave a timeoutOverride it is the number of seconds
-    // to screen-off.  Figure out where in the countdown cycle we
-    // should jump to.
-    private void setTimeoutLocked(long now, final long originalTimeoutOverride, int nextState) {
-        long timeoutOverride = originalTimeoutOverride;
-        if (mBootCompleted) {
-            synchronized (mLocks) {
-                long when = 0;
-                if (timeoutOverride <= 0) {
-                    switch (nextState)
-                    {
-                        case SCREEN_BRIGHT:
-                            when = now + mKeylightDelay;
-                            break;
-                        case SCREEN_DIM:
-                            if (mDimDelay >= 0) {
-                                when = now + mDimDelay;
-                                break;
-                            } else {
-                                Slog.w(TAG, "mDimDelay=" + mDimDelay + " while trying to dim");
-                            }
-                       case SCREEN_OFF:
-                            synchronized (mLocks) {
-                                when = now + mScreenOffDelay;
-                            }
-                            break;
-                        default:
-                            when = now;
-                            break;
-                    }
-                } else {
-                    override: {
-                        if (timeoutOverride <= mScreenOffDelay) {
-                            when = now + timeoutOverride;
-                            nextState = SCREEN_OFF;
-                            break override;
-                        }
-                        timeoutOverride -= mScreenOffDelay;
-
-                        if (mDimDelay >= 0) {
-                             if (timeoutOverride <= mDimDelay) {
-                                when = now + timeoutOverride;
-                                nextState = SCREEN_DIM;
-                                break override;
-                            }
-                            timeoutOverride -= mDimDelay;
-                        }
-
-                        when = now + timeoutOverride;
-                        nextState = SCREEN_BRIGHT;
-                    }
-                }
-                if (mSpew) {
-                    Slog.d(TAG, "setTimeoutLocked now=" + now
-                            + " timeoutOverride=" + timeoutOverride
-                            + " nextState=" + nextState + " when=" + when);
-                }
-
-                mHandler.removeCallbacks(mTimeoutTask);
-                mTimeoutTask.nextState = nextState;
-                mTimeoutTask.remainingTimeoutOverride = timeoutOverride > 0
-                        ? (originalTimeoutOverride - timeoutOverride)
-                        : -1;
-                mHandler.postAtTime(mTimeoutTask, when);
-                mNextTimeout = when; // for debugging
-            }
-        }
-    }
-
-    private void cancelTimerLocked()
-    {
-        mHandler.removeCallbacks(mTimeoutTask);
-        mTimeoutTask.nextState = -1;
-    }
-
-    private class TimeoutTask implements Runnable
-    {
-        int nextState; // access should be synchronized on mLocks
-        long remainingTimeoutOverride;
-        public void run()
-        {
-            synchronized (mLocks) {
-                if (mSpew) {
-                    Slog.d(TAG, "user activity timeout timed out nextState=" + this.nextState);
-                }
-
-                if (nextState == -1) {
-                    return;
-                }
-
-                mUserState = this.nextState;
-                setPowerState(this.nextState | mWakeLockState);
-
-                long now = SystemClock.uptimeMillis();
-
-                switch (this.nextState)
-                {
-                    case SCREEN_BRIGHT:
-                        if (mDimDelay >= 0) {
-                            setTimeoutLocked(now, remainingTimeoutOverride, SCREEN_DIM);
-                            break;
-                        }
-                    case SCREEN_DIM:
-                        setTimeoutLocked(now, remainingTimeoutOverride, SCREEN_OFF);
-                        break;
-                }
-            }
-        }
-    }
-
-    private void sendNotificationLocked(boolean on, int why) {
-        if (!mInitialized) {
-            // No notifications sent until first initialization is done.
-            // This is so that when we are moving from our initial state
-            // which looks like the screen was off to it being on, we do not
-            // go through the process of waiting for the higher-level user
-            // space to be ready before turning up the display brightness.
-            // (And also do not send needless broadcasts about the screen.)
-            return;
-        }
-
-        if (DEBUG_SCREEN_ON) {
-            RuntimeException here = new RuntimeException("here");
-            here.fillInStackTrace();
-            Slog.i(TAG, "sendNotificationLocked: " + on, here);
-        }
-
-        if (!on) {
-            mStillNeedSleepNotification = false;
-        }
-
-        // Add to the queue.
-        int index = 0;
-        while (mBroadcastQueue[index] != -1) {
-            index++;
-        }
-        mBroadcastQueue[index] = on ? 1 : 0;
-        mBroadcastWhy[index] = why;
-
-        // If we added it position 2, then there is a pair that can be stripped.
-        // If we added it position 1 and we're turning the screen off, we can strip
-        // the pair and do nothing, because the screen is already off, and therefore
-        // keyguard has already been enabled.
-        // However, if we added it at position 1 and we're turning it on, then position
-        // 0 was to turn it off, and we can't strip that, because keyguard needs to come
-        // on, so have to run the queue then.
-        if (index == 2) {
-            // While we're collapsing them, if it's going off, and the new reason
-            // is more significant than the first, then use the new one.
-            if (!on && mBroadcastWhy[0] > why) {
-                mBroadcastWhy[0] = why;
-            }
-            mBroadcastQueue[0] = on ? 1 : 0;
-            mBroadcastQueue[1] = -1;
-            mBroadcastQueue[2] = -1;
-            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
-            mBroadcastWakeLock.release();
-            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
-            mBroadcastWakeLock.release();
-            index = 0;
-        }
-        if (index == 1 && !on) {
-            mBroadcastQueue[0] = -1;
-            mBroadcastQueue[1] = -1;
-            index = -1;
-            // The wake lock was being held, but we're not actually going to do any
-            // broadcasts, so release the wake lock.
-            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
-            mBroadcastWakeLock.release();
-        }
-
-        // The broadcast queue has changed; make sure the screen is on if it
-        // is now possible for it to be.
-        if (mSkippedScreenOn) {
-            updateLightsLocked(mPowerState, SCREEN_ON_BIT);
-        }
-
-        // Now send the message.
-        if (index >= 0) {
-            // Acquire the broadcast wake lock before changing the power
-            // state. It will be release after the broadcast is sent.
-            // We always increment the ref count for each notification in the queue
-            // and always decrement when that notification is handled.
-            mBroadcastWakeLock.acquire();
-            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, mBroadcastWakeLock.mCount);
-            mHandler.post(mNotificationTask);
-        }
-    }
-
-    private WindowManagerPolicy.ScreenOnListener mScreenOnListener =
-            new WindowManagerPolicy.ScreenOnListener() {
-                public void onScreenOn() {
-                    synchronized (mLocks) {
-                        if (mPreparingForScreenOn) {
-                            mPreparingForScreenOn = false;
-                            updateLightsLocked(mPowerState, SCREEN_ON_BIT);
-                            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP,
-                                    4, mBroadcastWakeLock.mCount);
-                            mBroadcastWakeLock.release();
-                        }
-                    }
-                }
-    };
-
-    private Runnable mNotificationTask = new Runnable()
-    {
-        public void run()
-        {
-            while (true) {
-                int value;
-                int why;
-                WindowManagerPolicy policy;
-                synchronized (mLocks) {
-                    value = mBroadcastQueue[0];
-                    why = mBroadcastWhy[0];
-                    for (int i=0; i<2; i++) {
-                        mBroadcastQueue[i] = mBroadcastQueue[i+1];
-                        mBroadcastWhy[i] = mBroadcastWhy[i+1];
-                    }
-                    policy = getPolicyLocked();
-                    if (value == 1 && !mPreparingForScreenOn) {
-                        mPreparingForScreenOn = true;
-                        mBroadcastWakeLock.acquire();
-                        EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND,
-                                mBroadcastWakeLock.mCount);
-                    }
-                }
-                if (value == 1) {
-                    mScreenOnStart = SystemClock.uptimeMillis();
-
-                    policy.screenTurningOn(mScreenOnListener);
-                    try {
-                        ActivityManagerNative.getDefault().wakingUp();
-                    } catch (RemoteException e) {
-                        // ignore it
-                    }
-
-                    if (mSpew) {
-                        Slog.d(TAG, "mBroadcastWakeLock=" + mBroadcastWakeLock);
-                    }
-                    if (mContext != null && ActivityManagerNative.isSystemReady()) {
-                        mContext.sendOrderedBroadcast(mScreenOnIntent, null,
-                                mScreenOnBroadcastDone, mHandler, 0, null, null);
-                    } else {
-                        synchronized (mLocks) {
-                            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2,
-                                    mBroadcastWakeLock.mCount);
-                            mBroadcastWakeLock.release();
-                        }
-                    }
-                }
-                else if (value == 0) {
-                    mScreenOffStart = SystemClock.uptimeMillis();
-
-                    policy.screenTurnedOff(why);
-                    try {
-                        ActivityManagerNative.getDefault().goingToSleep();
-                    } catch (RemoteException e) {
-                        // ignore it.
-                    }
-
-                    if (mContext != null && ActivityManagerNative.isSystemReady()) {
-                        mContext.sendOrderedBroadcast(mScreenOffIntent, null,
-                                mScreenOffBroadcastDone, mHandler, 0, null, null);
-                    } else {
-                        synchronized (mLocks) {
-                            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3,
-                                    mBroadcastWakeLock.mCount);
-                            updateLightsLocked(mPowerState, SCREEN_ON_BIT);
-                            mBroadcastWakeLock.release();
-                        }
-                    }
-                }
-                else {
-                    // If we're in this case, then this handler is running for a previous
-                    // paired transaction.  mBroadcastWakeLock will already have been released.
-                    break;
-                }
-            }
-        }
-    };
-
-    long mScreenOnStart;
-    private BroadcastReceiver mScreenOnBroadcastDone = new BroadcastReceiver() {
-        public void onReceive(Context context, Intent intent) {
-            synchronized (mLocks) {
-                EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
-                        SystemClock.uptimeMillis() - mScreenOnStart, mBroadcastWakeLock.mCount);
-                mBroadcastWakeLock.release();
-            }
-        }
-    };
-
-    long mScreenOffStart;
-    private BroadcastReceiver mScreenOffBroadcastDone = new BroadcastReceiver() {
-        public void onReceive(Context context, Intent intent) {
-            synchronized (mLocks) {
-                EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
-                        SystemClock.uptimeMillis() - mScreenOffStart, mBroadcastWakeLock.mCount);
-                mBroadcastWakeLock.release();
-            }
-        }
-    };
-
-    void logPointerUpEvent() {
-        if (LOG_TOUCH_DOWNS) {
-            mTotalTouchDownTime += SystemClock.elapsedRealtime() - mLastTouchDown;
-            mLastTouchDown = 0;
-        }
-    }
-
-    void logPointerDownEvent() {
-        if (LOG_TOUCH_DOWNS) {
-            // If we are not already timing a down/up sequence
-            if (mLastTouchDown == 0) {
-                mLastTouchDown = SystemClock.elapsedRealtime();
-                mTouchCycles++;
-            }
-        }
-    }
-
-    /**
-     * Prevents the screen from turning on even if it *should* turn on due
-     * to a subsequent full wake lock being acquired.
-     * <p>
-     * This is a temporary hack that allows an activity to "cover up" any
-     * display glitches that happen during the activity's startup
-     * sequence.  (Specifically, this API was added to work around a
-     * cosmetic bug in the "incoming call" sequence, where the lock screen
-     * would flicker briefly before the incoming call UI became visible.)
-     * TODO: There ought to be a more elegant way of doing this,
-     * probably by having the PowerManager and ActivityManager
-     * work together to let apps specify that the screen on/off
-     * state should be synchronized with the Activity lifecycle.
-     * <p>
-     * Note that calling preventScreenOn(true) will NOT turn the screen
-     * off if it's currently on.  (This API only affects *future*
-     * acquisitions of full wake locks.)
-     * But calling preventScreenOn(false) WILL turn the screen on if
-     * it's currently off because of a prior preventScreenOn(true) call.
-     * <p>
-     * Any call to preventScreenOn(true) MUST be followed promptly by a call
-     * to preventScreenOn(false).  In fact, if the preventScreenOn(false)
-     * call doesn't occur within 5 seconds, we'll turn the screen back on
-     * ourselves (and log a warning about it); this prevents a buggy app
-     * from disabling the screen forever.)
-     * <p>
-     * TODO: this feature should really be controlled by a new type of poke
-     * lock (rather than an IPowerManager call).
-     */
-    public void preventScreenOn(boolean prevent) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
-        synchronized (mLocks) {
-            if (prevent) {
-                // First of all, grab a partial wake lock to
-                // make sure the CPU stays on during the entire
-                // preventScreenOn(true) -> preventScreenOn(false) sequence.
-                mPreventScreenOnPartialLock.acquire();
-
-                // Post a forceReenableScreen() call (for 5 seconds in the
-                // future) to make sure the matching preventScreenOn(false) call
-                // has happened by then.
-                mHandler.removeCallbacks(mForceReenableScreenTask);
-                mHandler.postDelayed(mForceReenableScreenTask, 5000);
-
-                // Finally, set the flag that prevents the screen from turning on.
-                // (Below, in setPowerState(), we'll check mPreventScreenOn and
-                // we *won't* call setScreenStateLocked(true) if it's set.)
-                mPreventScreenOn = true;
-            } else {
-                // (Re)enable the screen.
-                mPreventScreenOn = false;
-
-                // We're "undoing" a the prior preventScreenOn(true) call, so we
-                // no longer need the 5-second safeguard.
-                mHandler.removeCallbacks(mForceReenableScreenTask);
-
-                // Forcibly turn on the screen if it's supposed to be on.  (This
-                // handles the case where the screen is currently off because of
-                // a prior preventScreenOn(true) call.)
-                if (!mProximitySensorActive && (mPowerState & SCREEN_ON_BIT) != 0) {
-                    if (mSpew) {
-                        Slog.d(TAG,
-                              "preventScreenOn: turning on after a prior preventScreenOn(true)!");
-                    }
-                    int err = setScreenStateLocked(true);
-                    if (err != 0) {
-                        Slog.w(TAG, "preventScreenOn: error from setScreenStateLocked(): " + err);
-                    }
-                }
-
-                // Release the partial wake lock that we held during the
-                // preventScreenOn(true) -> preventScreenOn(false) sequence.
-                mPreventScreenOnPartialLock.release();
-            }
-        }
-    }
-
-    public void setScreenBrightnessOverride(int brightness) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
-        if (mSpew) Slog.d(TAG, "setScreenBrightnessOverride " + brightness);
-        synchronized (mLocks) {
-            if (mScreenBrightnessOverride != brightness) {
-                mScreenBrightnessOverride = brightness;
-                if (isScreenOn()) {
-                    updateLightsLocked(mPowerState, SCREEN_ON_BIT);
-                }
-            }
-        }
-    }
-
-    public void setButtonBrightnessOverride(int brightness) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
-        if (mSpew) Slog.d(TAG, "setButtonBrightnessOverride " + brightness);
-         synchronized (mLocks) {
-           if (mButtonBrightnessOverride != brightness) {
-                mButtonBrightnessOverride = brightness;
-                if (isScreenOn()) {
-                    updateLightsLocked(mPowerState, BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT);
-                }
-            }
-        }
-    }
-
-    /**
-     * Sanity-check that gets called 5 seconds after any call to
-     * preventScreenOn(true).  This ensures that the original call
-     * is followed promptly by a call to preventScreenOn(false).
-     */
-    private void forceReenableScreen() {
-        // We shouldn't get here at all if mPreventScreenOn is false, since
-        // we should have already removed any existing
-        // mForceReenableScreenTask messages...
-        if (!mPreventScreenOn) {
-            Slog.w(TAG, "forceReenableScreen: mPreventScreenOn is false, nothing to do");
-            return;
-        }
-
-        // Uh oh.  It's been 5 seconds since a call to
-        // preventScreenOn(true) and we haven't re-enabled the screen yet.
-        // This means the app that called preventScreenOn(true) is either
-        // slow (i.e. it took more than 5 seconds to call preventScreenOn(false)),
-        // or buggy (i.e. it forgot to call preventScreenOn(false), or
-        // crashed before doing so.)
-
-        // Log a warning, and forcibly turn the screen back on.
-        Slog.w(TAG, "App called preventScreenOn(true) but didn't promptly reenable the screen! "
-              + "Forcing the screen back on...");
-        preventScreenOn(false);
-    }
-
-    private Runnable mForceReenableScreenTask = new Runnable() {
-            public void run() {
-                forceReenableScreen();
-            }
-        };
-
-    private int setScreenStateLocked(boolean on) {
-        if (DEBUG_SCREEN_ON) {
-            RuntimeException e = new RuntimeException("here");
-            e.fillInStackTrace();
-            Slog.i(TAG, "Set screen state: " + on, e);
-        }
-        if (on) {
-            if (mInitialized && ((mPowerState & SCREEN_ON_BIT) == 0 || mSkippedScreenOn)) {
-                // If we are turning the screen state on, but the screen
-                // light is currently off, then make sure that we set the
-                // light at this point to 0.  This is the case where we are
-                // turning on the screen and waiting for the UI to be drawn
-                // before showing it to the user.  We want the light off
-                // until it is ready to be shown to the user, not it using
-                // whatever the last value it had.
-                // Skip this if the screen is being turned on for the first time
-                // after boot (mInitialized is false).
-                if (DEBUG_SCREEN_ON) {
-                    Slog.i(TAG, "Forcing brightness 0: mPowerState=0x"
-                            + Integer.toHexString(mPowerState)
-                            + " mSkippedScreenOn=" + mSkippedScreenOn);
-                }
-                mScreenBrightnessAnimator.animateTo(PowerManager.BRIGHTNESS_OFF, SCREEN_BRIGHT_BIT, 0);
-            }
-        }
-        int err = nativeSetScreenState(on);
-        if (err == 0) {
-            mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0);
-            if (mUseSoftwareAutoBrightness) {
-                enableLightSensorLocked(on);
-                if (on) {
-                    // If AutoBrightness is enabled, set the brightness immediately after the
-                    // next sensor value is received.
-                    mWaitingForFirstLightSensor = mAutoBrightessEnabled;
-                } else {
-                    // make sure button and key backlights are off too
-                    mButtonLight.turnOff();
-                    mKeyboardLight.turnOff();
-                }
-            }
-        }
-        return err;
-    }
-
-    private void setPowerState(int state)
-    {
-        setPowerState(state, false, WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT);
-    }
-
-    private void setPowerState(int newState, boolean noChangeLights, int reason)
-    {
-        synchronized (mLocks) {
-            int err;
-
-            if (mSpew) {
-                Slog.d(TAG, "setPowerState: mPowerState=0x" + Integer.toHexString(mPowerState)
-                        + " newState=0x" + Integer.toHexString(newState)
-                        + " noChangeLights=" + noChangeLights
-                        + " reason=" + reason);
-            }
-            
-            if (noChangeLights) {
-                newState = (newState & ~LIGHTS_MASK) | (mPowerState & LIGHTS_MASK);
-            }
-            if (mProximitySensorActive) {
-                // don't turn on the screen when the proximity sensor lock is held
-                newState = (newState & ~SCREEN_BRIGHT);
-            }
-
-            if (batteryIsLow()) {
-                newState |= BATTERY_LOW_BIT;
-            } else {
-                newState &= ~BATTERY_LOW_BIT;
-            }
-            if (newState == mPowerState && mInitialized) {
-                return;
-            }
-
-            if (!mBootCompleted && !mUseSoftwareAutoBrightness) {
-                newState |= ALL_BRIGHT;
-            }
-
-            boolean oldScreenOn = (mPowerState & SCREEN_ON_BIT) != 0;
-            boolean newScreenOn = (newState & SCREEN_ON_BIT) != 0;
-
-            if (mSpew) {
-                Slog.d(TAG, "setPowerState: mPowerState=" + mPowerState
-                        + " newState=" + newState + " noChangeLights=" + noChangeLights);
-                Slog.d(TAG, "  oldKeyboardBright=" + ((mPowerState & KEYBOARD_BRIGHT_BIT) != 0)
-                         + " newKeyboardBright=" + ((newState & KEYBOARD_BRIGHT_BIT) != 0));
-                Slog.d(TAG, "  oldScreenBright=" + ((mPowerState & SCREEN_BRIGHT_BIT) != 0)
-                         + " newScreenBright=" + ((newState & SCREEN_BRIGHT_BIT) != 0));
-                Slog.d(TAG, "  oldButtonBright=" + ((mPowerState & BUTTON_BRIGHT_BIT) != 0)
-                         + " newButtonBright=" + ((newState & BUTTON_BRIGHT_BIT) != 0));
-                Slog.d(TAG, "  oldScreenOn=" + oldScreenOn
-                         + " newScreenOn=" + newScreenOn);
-                Slog.d(TAG, "  oldBatteryLow=" + ((mPowerState & BATTERY_LOW_BIT) != 0)
-                         + " newBatteryLow=" + ((newState & BATTERY_LOW_BIT) != 0));
-            }
-
-            final boolean stateChanged = mPowerState != newState;
-
-            if (stateChanged && reason == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT) {
-                if (mPolicy != null && mPolicy.isScreenSaverEnabled()) {
-                    if (mSpew) {
-                        Slog.d(TAG, "setPowerState: running screen saver instead of turning off screen");
-                    }
-                    if (mPolicy.startScreenSaver()) {
-                        // was successful
-                        return;
-                    }
-                }
-            }
-
-
-            if (oldScreenOn != newScreenOn) {
-                if (newScreenOn) {
-                    // When the user presses the power button, we need to always send out the
-                    // notification that it's going to sleep so the keyguard goes on.  But
-                    // we can't do that until the screen fades out, so we don't show the keyguard
-                    // too early.
-                    if (mStillNeedSleepNotification) {
-                        sendNotificationLocked(false, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
-                    }
-
-                    // Turn on the screen UNLESS there was a prior
-                    // preventScreenOn(true) request.  (Note that the lifetime
-                    // of a single preventScreenOn() request is limited to 5
-                    // seconds to prevent a buggy app from disabling the
-                    // screen forever; see forceReenableScreen().)
-                    boolean reallyTurnScreenOn = true;
-                    if (mSpew) {
-                        Slog.d(TAG, "- turning screen on...  mPreventScreenOn = "
-                              + mPreventScreenOn);
-                    }
-
-                    if (mPreventScreenOn) {
-                        if (mSpew) {
-                            Slog.d(TAG, "- PREVENTING screen from really turning on!");
-                        }
-                        reallyTurnScreenOn = false;
-                    }
-                    if (reallyTurnScreenOn) {
-                        err = setScreenStateLocked(true);
-                        long identity = Binder.clearCallingIdentity();
-                        try {
-                            mBatteryStats.noteScreenBrightness(getPreferredBrightness());
-                            mBatteryStats.noteScreenOn();
-                        } catch (RemoteException e) {
-                            Slog.w(TAG, "RemoteException calling noteScreenOn on BatteryStatsService", e);
-                        } finally {
-                            Binder.restoreCallingIdentity(identity);
-                        }
-                    } else {
-                        setScreenStateLocked(false);
-                        // But continue as if we really did turn the screen on...
-                        err = 0;
-                    }
-
-                    mLastTouchDown = 0;
-                    mTotalTouchDownTime = 0;
-                    mTouchCycles = 0;
-                    EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, reason,
-                            mTotalTouchDownTime, mTouchCycles);
-                    if (err == 0) {
-                        sendNotificationLocked(true, -1);
-                        // Update the lights *after* taking care of turning the
-                        // screen on, so we do this after our notifications are
-                        // enqueued and thus will delay turning on the screen light
-                        // until the windows are correctly displayed.
-                        if (stateChanged) {
-                            updateLightsLocked(newState, 0);
-                        }
-                        mPowerState |= SCREEN_ON_BIT;
-                    }
-
-                } else {
-                    // Update the lights *before* taking care of turning the
-                    // screen off, so we can initiate any animations that are desired.
-                    mScreenOffReason = reason;
-                    if (stateChanged) {
-                        updateLightsLocked(newState, 0);
-                    }
-
-                    // cancel light sensor task
-                    mHandler.removeCallbacks(mAutoBrightnessTask);
-                    mLightSensorPendingDecrease = false;
-                    mLightSensorPendingIncrease = false;
-                    mScreenOffTime = SystemClock.elapsedRealtime();
-                    long identity = Binder.clearCallingIdentity();
-                    try {
-                        mBatteryStats.noteScreenOff();
-                    } catch (RemoteException e) {
-                        Slog.w(TAG, "RemoteException calling noteScreenOff on BatteryStatsService", e);
-                    } finally {
-                        Binder.restoreCallingIdentity(identity);
-                    }
-                    mPowerState &= ~SCREEN_ON_BIT;
-                    if (!mScreenBrightnessAnimator.isAnimating()) {
-                        err = screenOffFinishedAnimatingLocked(reason);
-                    } else {
-                        err = 0;
-                        mLastTouchDown = 0;
-                    }
-                }
-            } else if (stateChanged) {
-                // Screen on/off didn't change, but lights may have.
-                updateLightsLocked(newState, 0);
-            }
-
-            mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
-
-            updateNativePowerStateLocked();
-        }
-    }
-
-    private void updateNativePowerStateLocked() {
-        if (!mHeadless) {
-            nativeSetPowerState(
-                    (mPowerState & SCREEN_ON_BIT) != 0,
-                    (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT);
-        }
-    }
-
-    private int screenOffFinishedAnimatingLocked(int reason) {
-        // I don't think we need to check the current state here because all of these
-        // Power.setScreenState and sendNotificationLocked can both handle being
-        // called multiple times in the same state. -joeo
-        EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, reason, mTotalTouchDownTime,
-                mTouchCycles);
-        mLastTouchDown = 0;
-        int err = setScreenStateLocked(false);
-        if (err == 0) {
-            mScreenOffReason = reason;
-            sendNotificationLocked(false, reason);
-        }
-        return err;
-    }
-
-    private boolean batteryIsLow() {
-        return (!mIsPowered &&
-                mBatteryService.getBatteryLevel() <= LOW_BATTERY_THRESHOLD);
-    }
-
-    private boolean shouldDeferScreenOnLocked() {
-        if (mPreparingForScreenOn) {
-            // Currently waiting for confirmation from the policy that it
-            // is okay to turn on the screen.  Don't allow the screen to go
-            // on until that is done.
-            if (DEBUG_SCREEN_ON) Slog.i(TAG,
-                    "updateLights: delaying screen on due to mPreparingForScreenOn");
-            return true;
-        } else {
-            // If there is a screen-on command in the notification queue, we
-            // can't turn the screen on until it has been processed (and we
-            // have set mPreparingForScreenOn) or it has been dropped.
-            for (int i=0; i<mBroadcastQueue.length; i++) {
-                if (mBroadcastQueue[i] == 1) {
-                    if (DEBUG_SCREEN_ON) Slog.i(TAG,
-                            "updateLights: delaying screen on due to notification queue");
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private void updateLightsLocked(int newState, int forceState) {
-        final int oldState = mPowerState;
-
-        // If the screen is not currently on, we will want to delay actually
-        // turning the lights on if we are still getting the UI put up.
-        if ((oldState & SCREEN_ON_BIT) == 0 || mSkippedScreenOn) {
-            // Don't turn screen on until we know we are really ready to.
-            // This is to avoid letting the screen go on before things like the
-            // lock screen have been displayed.
-            if ((mSkippedScreenOn = shouldDeferScreenOnLocked())) {
-                newState &= ~(SCREEN_ON_BIT|SCREEN_BRIGHT_BIT);
-            }
-        }
-
-        if ((newState & SCREEN_ON_BIT) != 0) {
-            // Only turn on the buttons or keyboard if the screen is also on.
-            // We should never see the buttons on but not the screen.
-            newState = applyButtonState(newState);
-            newState = applyKeyboardState(newState);
-        }
-        final int realDifference = (newState ^ oldState);
-        final int difference = realDifference | forceState;
-        if (difference == 0) {
-            return;
-        }
-
-        int offMask = 0;
-        int dimMask = 0;
-        int onMask = 0;
-
-        int preferredBrightness = getPreferredBrightness();
-
-        if ((difference & KEYBOARD_BRIGHT_BIT) != 0) {
-            if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
-                offMask |= KEYBOARD_BRIGHT_BIT;
-            } else {
-                onMask |= KEYBOARD_BRIGHT_BIT;
-            }
-        }
-
-        if ((difference & BUTTON_BRIGHT_BIT) != 0) {
-            if ((newState & BUTTON_BRIGHT_BIT) == 0) {
-                offMask |= BUTTON_BRIGHT_BIT;
-            } else {
-                onMask |= BUTTON_BRIGHT_BIT;
-            }
-        }
-
-        if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
-            int nominalCurrentValue = -1;
-            // If there was an actual difference in the light state, then
-            // figure out the "ideal" current value based on the previous
-            // state.  Otherwise, this is a change due to the brightness
-            // override, so we want to animate from whatever the current
-            // value is.
-            if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
-                switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) {
-                    case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT:
-                        nominalCurrentValue = preferredBrightness;
-                        break;
-                    case SCREEN_ON_BIT:
-                        nominalCurrentValue = mScreenBrightnessDim;
-                        break;
-                    case 0:
-                        nominalCurrentValue = PowerManager.BRIGHTNESS_OFF;
-                        break;
-                    case SCREEN_BRIGHT_BIT:
-                    default:
-                        // not possible
-                        nominalCurrentValue = (int)mScreenBrightnessAnimator.getCurrentBrightness();
-                        break;
-                }
-            }
-            int brightness = preferredBrightness;
-            int steps = ANIM_STEPS;
-            if ((newState & SCREEN_BRIGHT_BIT) == 0) {
-                // dim or turn off backlight, depending on if the screen is on
-                // the scale is because the brightness ramp isn't linear and this biases
-                // it so the later parts take longer.
-                final float scale = 1.5f;
-                float ratio = (((float)mScreenBrightnessDim)/preferredBrightness);
-                if (ratio > 1.0f) ratio = 1.0f;
-                if ((newState & SCREEN_ON_BIT) == 0) {
-                    if ((oldState & SCREEN_BRIGHT_BIT) != 0) {
-                        // was bright
-                        steps = ANIM_STEPS;
-                    } else {
-                        // was dim
-                        steps = (int)(ANIM_STEPS*ratio*scale);
-                    }
-                    brightness = PowerManager.BRIGHTNESS_OFF;
-                } else {
-                    if ((oldState & SCREEN_ON_BIT) != 0) {
-                        // was bright
-                        steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale);
-                    } else {
-                        // was dim
-                        steps = (int)(ANIM_STEPS*ratio);
-                    }
-                    final int stayOnConditions = getStayOnConditionsLocked();
-                    if (stayOnConditions != 0 && mBatteryService.isPowered(stayOnConditions)) {
-                        // If the "stay on while plugged in" option is
-                        // turned on, then the screen will often not
-                        // automatically turn off while plugged in.  To
-                        // still have a sense of when it is inactive, we
-                        // will then count going dim as turning off.
-                        mScreenOffTime = SystemClock.elapsedRealtime();
-                    }
-                    brightness = mScreenBrightnessDim;
-                }
-            }
-            if (mWaitingForFirstLightSensor && (newState & SCREEN_ON_BIT) != 0) {
-                steps = IMMEDIATE_ANIM_STEPS;
-            }
-
-            long identity = Binder.clearCallingIdentity();
-            try {
-                mBatteryStats.noteScreenBrightness(brightness);
-            } catch (RemoteException e) {
-                // Nothing interesting to do.
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-            if (!mSkippedScreenOn) {
-                int dt = steps * NOMINAL_FRAME_TIME_MS;
-                mScreenBrightnessAnimator.animateTo(brightness, SCREEN_BRIGHT_BIT, dt);
-                if (DEBUG_SCREEN_ON) {
-                    RuntimeException e = new RuntimeException("here");
-                    e.fillInStackTrace();
-                    Slog.i(TAG, "Setting screen brightness: " + brightness, e);
-                }
-            }
-        }
-
-        if (mSpew) {
-            Slog.d(TAG, "offMask=0x" + Integer.toHexString(offMask)
-                    + " dimMask=0x" + Integer.toHexString(dimMask)
-                    + " onMask=0x" + Integer.toHexString(onMask)
-                    + " difference=0x" + Integer.toHexString(difference)
-                    + " realDifference=0x" + Integer.toHexString(realDifference)
-                    + " forceState=0x" + Integer.toHexString(forceState)
-                    );
-        }
-
-        if (offMask != 0) {
-            if (mSpew) Slog.i(TAG, "Setting brightess off: " + offMask);
-            setLightBrightness(offMask, PowerManager.BRIGHTNESS_OFF);
-        }
-        if (dimMask != 0) {
-            int brightness = mScreenBrightnessDim;
-            if ((newState & BATTERY_LOW_BIT) != 0 &&
-                    brightness > PowerManager.BRIGHTNESS_LOW_BATTERY) {
-                brightness = PowerManager.BRIGHTNESS_LOW_BATTERY;
-            }
-            if (mSpew) Slog.i(TAG, "Setting brightess dim " + brightness + ": " + dimMask);
-            setLightBrightness(dimMask, brightness);
-        }
-        if (onMask != 0) {
-            int brightness = getPreferredBrightness();
-            if ((newState & BATTERY_LOW_BIT) != 0 &&
-                    brightness > PowerManager.BRIGHTNESS_LOW_BATTERY) {
-                brightness = PowerManager.BRIGHTNESS_LOW_BATTERY;
-            }
-            if (mSpew) Slog.i(TAG, "Setting brightess on " + brightness + ": " + onMask);
-            setLightBrightness(onMask, brightness);
-        }
-    }
-
-    /**
-     * Note: by design this class does not hold mLocks while calling native methods.
-     * Nor should it. Ever.
-     */
-    class ScreenBrightnessAnimator extends HandlerThread {
-        static final int ANIMATE_LIGHTS = 10;
-        static final int ANIMATE_POWER_OFF = 11;
-        volatile int startValue;
-        volatile int endValue;
-        volatile int startSensorValue;
-        volatile int endSensorValue;
-        volatile int currentValue;
-        private int currentMask;
-        private int duration;
-        private long startTimeMillis;
-        private final String prefix;
-
-        public ScreenBrightnessAnimator(String name, int priority) {
-            super(name, priority);
-            prefix = name;
-        }
-
-        @Override
-        protected void onLooperPrepared() {
-            mScreenBrightnessHandler = new Handler() {
-                public void handleMessage(Message msg) {
-                    int brightnessMode = (mAutoBrightessEnabled && !mInitialAnimation
-                            ? LightsService.BRIGHTNESS_MODE_SENSOR
-                            : LightsService.BRIGHTNESS_MODE_USER);
-                    if (msg.what == ANIMATE_LIGHTS) {
-                        final int mask = msg.arg1;
-                        int value = msg.arg2;
-                        long tStart = SystemClock.uptimeMillis();
-                        if ((mask & SCREEN_BRIGHT_BIT) != 0) {
-                            if (mDebugLightAnimation) Slog.v(TAG, "Set brightness: " + value);
-                            mLcdLight.setBrightness(value, brightnessMode);
-                        }
-                        long elapsed = SystemClock.uptimeMillis() - tStart;
-                        if ((mask & BUTTON_BRIGHT_BIT) != 0) {
-                            mButtonLight.setBrightness(value);
-                        }
-                        if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {
-                            mKeyboardLight.setBrightness(value);
-                        }
-
-                        if (elapsed > 100) {
-                            Slog.e(TAG, "Excessive delay setting brightness: " + elapsed
-                                    + "ms, mask=" + mask);
-                        }
-
-                        // Throttle brightness updates to frame refresh rate
-                        int delay = elapsed < NOMINAL_FRAME_TIME_MS ? NOMINAL_FRAME_TIME_MS : 1;
-                        synchronized(this) {
-                            currentValue = value;
-                        }
-                        animateInternal(mask, false, delay);
-                    } else if (msg.what == ANIMATE_POWER_OFF) {
-                        int mode = msg.arg1;
-                        nativeStartSurfaceFlingerAnimation(mode);
-                    }
-                }
-            };
-            synchronized (this) {
-                mInitComplete = true;
-                notifyAll();
-            }
-        }
-
-        private void animateInternal(int mask, boolean turningOff, int delay) {
-            synchronized (this) {
-                if (currentValue != endValue) {
-                    final long now = SystemClock.elapsedRealtime();
-                    final int elapsed = (int) (now - startTimeMillis);
-                    int newValue;
-                    if (elapsed < duration) {
-                        int delta = endValue - startValue;
-                        newValue = startValue + delta * elapsed / duration;
-                        newValue = Math.max(PowerManager.BRIGHTNESS_OFF, newValue);
-                        newValue = Math.min(PowerManager.BRIGHTNESS_ON, newValue);
-                        // Optimization to delay next step until a change will occur.
-                        if (delay > 0 && newValue == currentValue) {
-                            final int timePerStep = duration / Math.abs(delta);
-                            delay = Math.min(duration - elapsed, timePerStep);
-                            newValue += delta < 0 ? -1 : 1;
-                        }
-                        // adjust the peak sensor value until we get to the target sensor value
-                        delta = endSensorValue - startSensorValue;
-                        mHighestLightSensorValue = startSensorValue + delta * elapsed / duration;
-                    } else {
-                        newValue = endValue;
-                        mHighestLightSensorValue = endSensorValue;
-                        if (endValue > 0) {
-                            mInitialAnimation = false;
-                        }
-                    }
-
-                    if (mDebugLightAnimation) {
-                        Slog.v(TAG, "Animating light: " + "start:" + startValue
-                                + ", end:" + endValue + ", elapsed:" + elapsed
-                                + ", duration:" + duration + ", current:" + currentValue
-                                + ", newValue:" + newValue
-                                + ", delay:" + delay
-                                + ", highestSensor:" + mHighestLightSensorValue);
-                    }
-
-                    if (turningOff && !mHeadless && !mAnimateScreenLights) {
-                        int mode = mScreenOffReason == OFF_BECAUSE_OF_PROX_SENSOR
-                                ? 0 : mAnimationSetting;
-                        if (mDebugLightAnimation) {
-                            Slog.v(TAG, "Doing power-off anim, mode=" + mode);
-                        }
-                        mScreenBrightnessHandler.obtainMessage(ANIMATE_POWER_OFF, mode, 0)
-                                .sendToTarget();
-                    }
-                    mScreenBrightnessHandler.removeMessages(
-                            ScreenBrightnessAnimator.ANIMATE_LIGHTS);
-                    Message msg = mScreenBrightnessHandler
-                            .obtainMessage(ANIMATE_LIGHTS, mask, newValue);
-                    mScreenBrightnessHandler.sendMessageDelayed(msg, delay);
-                }
-            }
-        }
-
-        public void dump(PrintWriter pw, String string) {
-            pw.println(string);
-            pw.println("  animating: " + "start:" + startValue + ", end:" + endValue
-                    + ", duration:" + duration + ", current:" + currentValue);
-            pw.println("  startSensorValue:" + startSensorValue
-                    + " endSensorValue:" + endSensorValue);
-            pw.println("  startTimeMillis:" + startTimeMillis
-                    + " now:" + SystemClock.elapsedRealtime());
-            pw.println("  currentMask:" + dumpPowerState(currentMask));
-        }
-
-        public void animateTo(int target, int mask, int animationDuration) {
-            animateTo(target, mHighestLightSensorValue, mask, animationDuration);
-        }
-
-        public void animateTo(int target, int sensorTarget, int mask, int animationDuration) {
-            synchronized(this) {
-                if ((mask & SCREEN_BRIGHT_BIT) == 0) {
-                    // We only animate keyboard and button when passed in with SCREEN_BRIGHT_BIT.
-                    if ((mask & BUTTON_BRIGHT_BIT) != 0) {
-                        mButtonLight.setBrightness(target);
-                    }
-                    if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {
-                        mKeyboardLight.setBrightness(target);
-                    }
-                    return;
-                }
-                if (isAnimating() && (mask ^ currentMask) != 0) {
-                    // current animation is unrelated to new animation, jump to final values
-                    cancelAnimation();
-                }
-                if (mInitialAnimation) {
-                    // jump to final value in one step the first time the brightness is set
-                    animationDuration = 0;
-                    if (target > 0) {
-                        mInitialAnimation = false;
-                    }
-                }
-                startValue = currentValue;
-                endValue = target;
-                startSensorValue = mHighestLightSensorValue;
-                endSensorValue = sensorTarget;
-                currentMask = mask;
-                duration = (int) (mWindowScaleAnimation * animationDuration);
-                startTimeMillis = SystemClock.elapsedRealtime();
-
-                if (mDebugLightAnimation) {
-                    Slog.v(TAG, "animateTo(target=" + target
-                            + ", sensor=" + sensorTarget
-                            + ", mask=" + mask
-                            + ", duration=" + animationDuration +")"
-                            + ", currentValue=" + currentValue
-                            + ", startTime=" + startTimeMillis);
-                }
-
-                if (target != currentValue) {
-                    final boolean doScreenAnim = (mask & (SCREEN_BRIGHT_BIT | SCREEN_ON_BIT)) != 0;
-                    final boolean turningOff = endValue == PowerManager.BRIGHTNESS_OFF;
-                    if (turningOff && doScreenAnim) {
-                        // Cancel all pending animations since we're turning off
-                        mScreenBrightnessHandler.removeCallbacksAndMessages(null);
-                        screenOffFinishedAnimatingLocked(mScreenOffReason);
-                        duration = 200; // TODO: how long should this be?
-                    }
-                    if (doScreenAnim) {
-                        animateInternal(mask, turningOff, 0);
-                    }
-                    // TODO: Handle keyboard light animation when we have devices that support it
-                }
-            }
-        }
-
-        public int getCurrentBrightness() {
-            synchronized (this) {
-                return currentValue;
-            }
-        }
-
-        public boolean isAnimating() {
-            synchronized (this) {
-                return currentValue != endValue;
-            }
-        }
-
-        public void cancelAnimation() {
-            animateTo(endValue, currentMask, 0);
-        }
-    }
-
-    private void setLightBrightness(int mask, int value) {
-        mScreenBrightnessAnimator.animateTo(value, mask, 0);
-    }
-
-    private int getPreferredBrightness() {
-        if (mScreenBrightnessOverride >= 0) {
-            return mScreenBrightnessOverride;
-        } else if (mLightSensorScreenBrightness >= 0 && mUseSoftwareAutoBrightness
-                && mAutoBrightessEnabled) {
-            return mLightSensorScreenBrightness;
-        }
-        final int brightness = mScreenBrightnessSetting;
-         // Don't let applications turn the screen all the way off
-        return Math.max(brightness, mScreenBrightnessDim);
-    }
-
-    private int applyButtonState(int state) {
-        int brightness = -1;
-        if ((state & BATTERY_LOW_BIT) != 0) {
-            // do not override brightness if the battery is low
-            return state;
-        }
-        if (mButtonBrightnessOverride >= 0) {
-            brightness = mButtonBrightnessOverride;
-        } else if (mLightSensorButtonBrightness >= 0 && mUseSoftwareAutoBrightness) {
-            brightness = mLightSensorButtonBrightness;
-        }
-        if (brightness > 0) {
-            return state | BUTTON_BRIGHT_BIT;
-        } else if (brightness == 0) {
-            return state & ~BUTTON_BRIGHT_BIT;
-        } else {
-            return state;
-        }
-    }
-
-    private int applyKeyboardState(int state) {
-        int brightness = -1;
-        if ((state & BATTERY_LOW_BIT) != 0) {
-            // do not override brightness if the battery is low
-            return state;
-        }
-        if (!mKeyboardVisible) {
-            brightness = 0;
-        } else if (mButtonBrightnessOverride >= 0) {
-            brightness = mButtonBrightnessOverride;
-        } else if (mLightSensorKeyboardBrightness >= 0 && mUseSoftwareAutoBrightness) {
-            brightness =  mLightSensorKeyboardBrightness;
-        }
-        if (brightness > 0) {
-            return state | KEYBOARD_BRIGHT_BIT;
-        } else if (brightness == 0) {
-            return state & ~KEYBOARD_BRIGHT_BIT;
-        } else {
-            return state;
-        }
-    }
-
-    public boolean isScreenOn() {
-        synchronized (mLocks) {
-            return (mPowerState & SCREEN_ON_BIT) != 0;
-        }
-    }
-
-    boolean isScreenBright() {
-        synchronized (mLocks) {
-            return (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT;
-        }
-    }
-
-    private boolean isScreenTurningOffLocked() {
-        return (mScreenBrightnessAnimator.isAnimating()
-                && mScreenBrightnessAnimator.endValue == PowerManager.BRIGHTNESS_OFF
-                && (mScreenBrightnessAnimator.currentMask & SCREEN_BRIGHT_BIT) != 0);
-    }
-
-    private boolean shouldLog(long time) {
-        synchronized (mLocks) {
-            if (time > (mWarningSpewThrottleTime + (60*60*1000))) {
-                mWarningSpewThrottleTime = time;
-                mWarningSpewThrottleCount = 0;
-                return true;
-            } else if (mWarningSpewThrottleCount < 30) {
-                mWarningSpewThrottleCount++;
-                return true;
-            } else {
-                return false;
-            }
-        }
-    }
-
-    private void forceUserActivityLocked() {
-        if (isScreenTurningOffLocked()) {
-            // cancel animation so userActivity will succeed
-            mScreenBrightnessAnimator.cancelAnimation();
-        }
-        boolean savedActivityAllowed = mUserActivityAllowed;
-        mUserActivityAllowed = true;
-        userActivity(SystemClock.uptimeMillis(), false);
-        mUserActivityAllowed = savedActivityAllowed;
-    }
-
-    public void userActivityWithForce(long time, boolean noChangeLights, boolean force) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-        userActivity(time, -1, noChangeLights, OTHER_EVENT, force, false);
-    }
-
-    public void userActivity(long time, boolean noChangeLights) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
-                != PackageManager.PERMISSION_GRANTED) {
-            if (shouldLog(time)) {
-                Slog.w(TAG, "Caller does not have DEVICE_POWER permission.  pid="
-                        + Binder.getCallingPid() + " uid=" + Binder.getCallingUid());
-            }
-            return;
-        }
-
-        userActivity(time, -1, noChangeLights, OTHER_EVENT, false, false);
-    }
-
-    public void userActivity(long time, boolean noChangeLights, int eventType) {
-        userActivity(time, -1, noChangeLights, eventType, false, false);
-    }
-
-    public void userActivity(long time, boolean noChangeLights, int eventType, boolean force) {
-        userActivity(time, -1, noChangeLights, eventType, force, false);
-    }
-
-    /*
-     * Reset the user activity timeout to now + timeout.  This overrides whatever else is going
-     * on with user activity.  Don't use this function.
-     */
-    public void clearUserActivityTimeout(long now, long timeout) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-        Slog.i(TAG, "clearUserActivity for " + timeout + "ms from now");
-        userActivity(now, timeout, false, OTHER_EVENT, false, false);
-    }
-
-    private void userActivity(long time, long timeoutOverride, boolean noChangeLights,
-            int eventType, boolean force, boolean ignoreIfScreenOff) {
-
-        if (((mPokey & POKE_LOCK_IGNORE_TOUCH_EVENTS) != 0) && (eventType == TOUCH_EVENT)) {
-            if (false) {
-                Slog.d(TAG, "dropping touch mPokey=0x" + Integer.toHexString(mPokey));
-            }
-            return;
-        }
-
-        synchronized (mLocks) {
-            if (mSpew) {
-                Slog.d(TAG, "userActivity mLastEventTime=" + mLastEventTime + " time=" + time
-                        + " mUserActivityAllowed=" + mUserActivityAllowed
-                        + " mUserState=0x" + Integer.toHexString(mUserState)
-                        + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState)
-                        + " mProximitySensorActive=" + mProximitySensorActive
-                        + " timeoutOverride=" + timeoutOverride
-                        + " force=" + force);
-            }
-            // ignore user activity if we are in the process of turning off the screen
-            if (isScreenTurningOffLocked()) {
-                Slog.d(TAG, "ignoring user activity while turning off screen");
-                return;
-            }
-            // ignore if the caller doesn't want this to allow the screen to turn
-            // on, and the screen is currently off.
-            if (ignoreIfScreenOff && (mPowerState & SCREEN_ON_BIT) == 0) {
-                return;
-            }
-            // Disable proximity sensor if if user presses power key while we are in the
-            // "waiting for proximity sensor to go negative" state.
-            if (mProximitySensorActive && mProximityWakeLockCount == 0) {
-                mProximitySensorActive = false;
-            }
-            if (mLastEventTime <= time || force) {
-                mLastEventTime = time;
-                if ((mUserActivityAllowed && !mProximitySensorActive) || force) {
-                    // Only turn on button backlights if a button was pressed
-                    // and auto brightness is disabled
-                    if (eventType == BUTTON_EVENT && !mUseSoftwareAutoBrightness) {
-                        mUserState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
-                    } else {
-                        // don't clear button/keyboard backlights when the screen is touched.
-                        mUserState |= SCREEN_BRIGHT;
-                    }
-
-                    int uid = Binder.getCallingUid();
-                    long ident = Binder.clearCallingIdentity();
-                    try {
-                        mBatteryStats.noteUserActivity(uid, eventType);
-                    } catch (RemoteException e) {
-                        // Ignore
-                    } finally {
-                        Binder.restoreCallingIdentity(ident);
-                    }
-
-                    mWakeLockState = mLocks.reactivateScreenLocksLocked();
-                    setPowerState(mUserState | mWakeLockState, noChangeLights,
-                            WindowManagerPolicy.OFF_BECAUSE_OF_USER);
-                    setTimeoutLocked(time, timeoutOverride, SCREEN_BRIGHT);
-                }
-            }
-        }
-
-        if (mPolicy != null) {
-            mPolicy.userActivity();
-        }
-    }
-
-    private int getAutoBrightnessValue(int sensorValue, int[] values) {
-        try {
-            int i;
-            for (i = 0; i < mAutoBrightnessLevels.length; i++) {
-                if (sensorValue < mAutoBrightnessLevels[i]) {
-                    break;
-                }
-            }
-            // This is the range of brightness values that we can use.
-            final int minval = values[0];
-            final int maxval = values[mAutoBrightnessLevels.length];
-            // This is the range we will be scaling.  We put some padding
-            // at the low and high end to give the adjustment a little better
-            // impact on the actual observed value.
-            final int range = (maxval-minval) + LIGHT_SENSOR_RANGE_EXPANSION;
-            // This is the desired brightness value from 0.0 to 1.0.
-            float valf = ((values[i]-minval+(LIGHT_SENSOR_RANGE_EXPANSION/2))/(float)range);
-            // Apply a scaling to the value based on the adjustment.
-            if (mLightSensorAdjustSetting > 0 && mLightSensorAdjustSetting <= 1) {
-                float adj = (float)Math.sqrt(1.0f-mLightSensorAdjustSetting);
-                if (adj <= .00001) {
-                    valf = 1;
-                } else {
-                    valf /= adj;
-                }
-            } else if (mLightSensorAdjustSetting < 0 && mLightSensorAdjustSetting >= -1) {
-                float adj = (float)Math.sqrt(1.0f+mLightSensorAdjustSetting);
-                valf *= adj;
-            }
-            // Apply an additional offset to the value based on the adjustment.
-            valf += mLightSensorAdjustSetting/LIGHT_SENSOR_OFFSET_SCALE;
-            // Convert the 0.0-1.0 value back to a brightness integer.
-            int val = (int)((valf*range)+minval) - (LIGHT_SENSOR_RANGE_EXPANSION/2);
-            if (val < minval) val = minval;
-            else if (val > maxval) val = maxval;
-            return val;
-        } catch (Exception e) {
-            // guard against null pointer or index out of bounds errors
-            Slog.e(TAG, "Values array must be non-empty and must be one element longer than "
-                    + "the auto-brightness levels array.  Check config.xml.", e);
-            return 255;
-        }
-    }
-
-    private Runnable mProximityTask = new Runnable() {
-        public void run() {
-            synchronized (mLocks) {
-                if (mProximityPendingValue != -1) {
-                    proximityChangedLocked(mProximityPendingValue == 1);
-                    mProximityPendingValue = -1;
-                }
-                if (mProximityPartialLock.isHeld()) {
-                    mProximityPartialLock.release();
-                }
-            }
-        }
-    };
-
-    private Runnable mAutoBrightnessTask = new Runnable() {
-        public void run() {
-            synchronized (mLocks) {
-                if (mLightSensorPendingDecrease || mLightSensorPendingIncrease) {
-                    int value = (int)mLightSensorPendingValue;
-                    mLightSensorPendingDecrease = false;
-                    mLightSensorPendingIncrease = false;
-                    lightSensorChangedLocked(value, false);
-                }
-            }
-        }
-    };
-
-    /** used to prevent lightsensor changes while turning on. */
-    private boolean mInitialAnimation = true;
-
-    private void dockStateChanged(int state) {
-        synchronized (mLocks) {
-            mIsDocked = (state != Intent.EXTRA_DOCK_STATE_UNDOCKED);
-            if (mIsDocked) {
-                // allow brightness to decrease when docked
-                mHighestLightSensorValue = -1;
-            }
-            if ((mPowerState & SCREEN_ON_BIT) != 0) {
-                // force lights recalculation
-                int value = (int)mLightSensorValue;
-                mLightSensorValue = -1;
-                lightSensorChangedLocked(value, false);
-            }
-        }
-    }
-
-    private void lightSensorChangedLocked(int value, boolean immediate) {
-        if (mDebugLightSensor) {
-            Slog.d(TAG, "lightSensorChangedLocked value=" + value + " immediate=" + immediate);
-        }
-
-        // Don't do anything if the screen is off.
-        if ((mPowerState & SCREEN_ON_BIT) == 0) {
-            if (mDebugLightSensor) {
-                Slog.d(TAG, "dropping lightSensorChangedLocked because screen is off");
-            }
-            return;
-        }
-
-        if (mLightSensorValue != value) {
-            mLightSensorValue = value;
-            if ((mPowerState & BATTERY_LOW_BIT) == 0) {
-                // use maximum light sensor value seen since screen went on for LCD to avoid flicker
-                // we only do this if we are undocked, since lighting should be stable when
-                // stationary in a dock.
-                int lcdValue = getAutoBrightnessValue(value, mLcdBacklightValues);
-                int buttonValue = getAutoBrightnessValue(value, mButtonBacklightValues);
-                int keyboardValue;
-                if (mKeyboardVisible) {
-                    keyboardValue = getAutoBrightnessValue(value, mKeyboardBacklightValues);
-                } else {
-                    keyboardValue = 0;
-                }
-                mLightSensorScreenBrightness = lcdValue;
-                mLightSensorButtonBrightness = buttonValue;
-                mLightSensorKeyboardBrightness = keyboardValue;
-
-                if (mDebugLightSensor) {
-                    Slog.d(TAG, "lcdValue " + lcdValue);
-                    Slog.d(TAG, "buttonValue " + buttonValue);
-                    Slog.d(TAG, "keyboardValue " + keyboardValue);
-                }
-
-                if (mAutoBrightessEnabled && mScreenBrightnessOverride < 0) {
-                    if (!mSkippedScreenOn && !mInitialAnimation) {
-                        final int steps;
-                        if (immediate) {
-                            steps = IMMEDIATE_ANIM_STEPS;
-                        } else {
-                            synchronized (mScreenBrightnessAnimator) {
-                                if (mScreenBrightnessAnimator.currentValue <= lcdValue) {
-                                    steps = AUTOBRIGHTNESS_ANIM_STEPS;
-                                } else {
-                                    steps = AUTODIMNESS_ANIM_STEPS;
-                                }
-                            }
-                        }
-                        mScreenBrightnessAnimator.animateTo(lcdValue, value,
-                                SCREEN_BRIGHT_BIT, steps * NOMINAL_FRAME_TIME_MS);
-                    }
-                }
-                if (mButtonBrightnessOverride < 0) {
-                    mButtonLight.setBrightness(buttonValue);
-                }
-                if (mButtonBrightnessOverride < 0 || !mKeyboardVisible) {
-                    mKeyboardLight.setBrightness(keyboardValue);
-                }
-            }
-        }
-    }
-
-    /**
-     * The user requested that we go to sleep (probably with the power button).
-     * This overrides all wake locks that are held.
-     */
-    public void goToSleep(long time)
-    {
-        goToSleepWithReason(time, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
-    }
-
-    /**
-     * The user requested that we go to sleep (probably with the power button).
-     * This overrides all wake locks that are held.
-     */
-    public void goToSleepWithReason(long time, int reason)
-    {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-        synchronized (mLocks) {
-            goToSleepLocked(time, reason);
-        }
-    }
-
-    /**
-     * Reboot the device immediately, passing 'reason' (may be null)
-     * to the underlying __reboot system call.  Should not return.
-     */
-    public void reboot(String reason)
-    {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
-
-        if (mHandler == null || !ActivityManagerNative.isSystemReady()) {
-            throw new IllegalStateException("Too early to call reboot()");
-        }
-
-        final String finalReason = reason;
-        Runnable runnable = new Runnable() {
-            public void run() {
-                synchronized (this) {
-                    ShutdownThread.reboot(mContext, finalReason, false);
-                }
-
-            }
-        };
-        // ShutdownThread must run on a looper capable of displaying the UI.
-        mHandler.post(runnable);
-
-        // PowerManager.reboot() is documented not to return so just wait for the inevitable.
-        synchronized (runnable) {
-            while (true) {
-                try {
-                    runnable.wait();
-                } catch (InterruptedException e) {
-                }
-            }
-        }
-    }
-
-    /**
-     * Crash the runtime (causing a complete restart of the Android framework).
-     * Requires REBOOT permission.  Mostly for testing.  Should not return.
-     */
-    public void crash(final String message)
-    {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
-        Thread t = new Thread("PowerManagerService.crash()") {
-            public void run() { throw new RuntimeException(message); }
-        };
-        try {
-            t.start();
-            t.join();
-        } catch (InterruptedException e) {
-            Log.wtf(TAG, e);
-        }
-    }
-
-    private void goToSleepLocked(long time, int reason) {
-        if (mSpew) {
-            Exception ex = new Exception();
-            ex.fillInStackTrace();
-            Slog.d(TAG, "goToSleep mLastEventTime=" + mLastEventTime + " time=" + time
-                    + " reason=" + reason, ex);
-        }
-
-        if (mLastEventTime <= time) {
-            mLastEventTime = time;
-            // cancel all of the wake locks
-            mWakeLockState = SCREEN_OFF;
-            int N = mLocks.size();
-            int numCleared = 0;
-            boolean proxLock = false;
-            for (int i=0; i<N; i++) {
-                WakeLock wl = mLocks.get(i);
-                if (isScreenLock(wl.flags)) {
-                    if (((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
-                            && reason == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
-                        proxLock = true;
-                    } else {
-                        mLocks.get(i).activated = false;
-                        numCleared++;
-                    }
-                }
-            }
-            if (!proxLock) {
-                mProxIgnoredBecauseScreenTurnedOff = true;
-                if (mDebugProximitySensor) {
-                    Slog.d(TAG, "setting mProxIgnoredBecauseScreenTurnedOff");
-                }
-            }
-            EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numCleared);
-            mStillNeedSleepNotification = true;
-            mUserState = SCREEN_OFF;
-            setPowerState(SCREEN_OFF, false, reason);
-            cancelTimerLocked();
-        }
-    }
-
-    public long timeSinceScreenOn() {
-        synchronized (mLocks) {
-            if ((mPowerState & SCREEN_ON_BIT) != 0) {
-                return 0;
-            }
-            return SystemClock.elapsedRealtime() - mScreenOffTime;
-        }
-    }
-
-    public void setKeyboardVisibility(boolean visible) {
-        synchronized (mLocks) {
-            if (mSpew) {
-                Slog.d(TAG, "setKeyboardVisibility: " + visible);
-            }
-            if (mKeyboardVisible != visible) {
-                mKeyboardVisible = visible;
-                // don't signal user activity if the screen is off; other code
-                // will take care of turning on due to a true change to the lid
-                // switch and synchronized with the lock screen.
-                if ((mPowerState & SCREEN_ON_BIT) != 0) {
-                    if (mUseSoftwareAutoBrightness) {
-                        // force recompute of backlight values
-                        if (mLightSensorValue >= 0) {
-                            int value = (int)mLightSensorValue;
-                            mLightSensorValue = -1;
-                            lightSensorChangedLocked(value, false);
-                        }
-                    }
-                    userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
-                }
-            }
-        }
-    }
-
-    /**
-     * When the keyguard is up, it manages the power state, and userActivity doesn't do anything.
-     * When disabling user activity we also reset user power state so the keyguard can reset its
-     * short screen timeout when keyguard is unhidden.
-     */
-    public void enableUserActivity(boolean enabled) {
-        if (mSpew) {
-            Slog.d(TAG, "enableUserActivity " + enabled);
-        }
-        synchronized (mLocks) {
-            mUserActivityAllowed = enabled;
-            if (!enabled) {
-                // cancel timeout and clear mUserState so the keyguard can set a short timeout
-                setTimeoutLocked(SystemClock.uptimeMillis(), 0);
-            }
-        }
-    }
-
-    private void setScreenBrightnessMode(int mode) {
-        synchronized (mLocks) {
-            boolean enabled = (mode == SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
-            if (mUseSoftwareAutoBrightness && mAutoBrightessEnabled != enabled) {
-                mAutoBrightessEnabled = enabled;
-                // This will get us a new value
-                enableLightSensorLocked(mAutoBrightessEnabled && isScreenOn());
-            }
-        }
-    }
-
-    /** Sets the screen off timeouts:
-     *      mKeylightDelay
-     *      mDimDelay
-     *      mScreenOffDelay
-     * */
-    private void setScreenOffTimeoutsLocked() {
-        if ((mPokey & POKE_LOCK_SHORT_TIMEOUT) != 0) {
-            mKeylightDelay = mShortKeylightDelay;  // Configurable via secure settings
-            mDimDelay = -1;
-            mScreenOffDelay = 0;
-        } else if ((mPokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0) {
-            mKeylightDelay = MEDIUM_KEYLIGHT_DELAY;
-            mDimDelay = -1;
-            mScreenOffDelay = 0;
-        } else {
-            int totalDelay = mScreenOffTimeoutSetting;
-            if (totalDelay > mMaximumScreenOffTimeout) {
-                totalDelay = mMaximumScreenOffTimeout;
-            }
-            mKeylightDelay = LONG_KEYLIGHT_DELAY;
-            if (totalDelay < 0) {
-                // negative number means stay on as long as possible.
-                mScreenOffDelay = mMaximumScreenOffTimeout;
-            } else if (mKeylightDelay < totalDelay) {
-                // subtract the time that the keylight delay. This will give us the
-                // remainder of the time that we need to sleep to get the accurate
-                // screen off timeout.
-                mScreenOffDelay = totalDelay - mKeylightDelay;
-            } else {
-                mScreenOffDelay = 0;
-            }
-            if (mDimScreen && totalDelay >= (LONG_KEYLIGHT_DELAY + LONG_DIM_TIME)) {
-                mDimDelay = mScreenOffDelay - LONG_DIM_TIME;
-                mScreenOffDelay = LONG_DIM_TIME;
-            } else {
-                mDimDelay = -1;
-            }
-        }
-        if (mSpew) {
-            Slog.d(TAG, "setScreenOffTimeouts mKeylightDelay=" + mKeylightDelay
-                    + " mDimDelay=" + mDimDelay + " mScreenOffDelay=" + mScreenOffDelay
-                    + " mDimScreen=" + mDimScreen);
-        }
-    }
-
-    /**
-     * Refreshes cached secure settings.  Called once on startup, and
-     * on subsequent changes to secure settings.
-     */
-    private void updateSettingsValues() {
-        mShortKeylightDelay = Settings.Secure.getInt(
-                mContext.getContentResolver(),
-                Settings.Secure.SHORT_KEYLIGHT_DELAY_MS,
-                SHORT_KEYLIGHT_DELAY_DEFAULT);
-        // Slog.i(TAG, "updateSettingsValues(): mShortKeylightDelay now " + mShortKeylightDelay);
-    }
-
-    private class LockList extends ArrayList<WakeLock>
-    {
-        void addLock(WakeLock wl)
-        {
-            int index = getIndex(wl.binder);
-            if (index < 0) {
-                this.add(wl);
-            }
-        }
-
-        WakeLock removeLock(IBinder binder)
-        {
-            int index = getIndex(binder);
-            if (index >= 0) {
-                return this.remove(index);
-            } else {
-                return null;
-            }
-        }
-
-        int getIndex(IBinder binder)
-        {
-            int N = this.size();
-            for (int i=0; i<N; i++) {
-                if (this.get(i).binder == binder) {
-                    return i;
-                }
-            }
-            return -1;
-        }
-
-        int gatherState()
-        {
-            int result = 0;
-            int N = this.size();
-            for (int i=0; i<N; i++) {
-                WakeLock wl = this.get(i);
-                if (wl.activated) {
-                    if (isScreenLock(wl.flags)) {
-                        result |= wl.minState;
-                    }
-                }
-            }
-            return result;
-        }
-
-        int reactivateScreenLocksLocked()
-        {
-            int result = 0;
-            int N = this.size();
-            for (int i=0; i<N; i++) {
-                WakeLock wl = this.get(i);
-                if (isScreenLock(wl.flags)) {
-                    wl.activated = true;
-                    result |= wl.minState;
-                }
-            }
-            if (mDebugProximitySensor) {
-                Slog.d(TAG, "reactivateScreenLocksLocked mProxIgnoredBecauseScreenTurnedOff="
-                        + mProxIgnoredBecauseScreenTurnedOff);
-            }
-            mProxIgnoredBecauseScreenTurnedOff = false;
-            return result;
-        }
-    }
-
-    public void setPolicy(WindowManagerPolicy p) {
-        synchronized (mLocks) {
-            mPolicy = p;
-            mLocks.notifyAll();
-        }
-    }
-
-    WindowManagerPolicy getPolicyLocked() {
-        while (mPolicy == null || !mDoneBooting) {
-            try {
-                mLocks.wait();
-            } catch (InterruptedException e) {
-                // Ignore
-            }
-        }
-        return mPolicy;
-    }
-
-    void systemReady() {
-        mSensorManager = new SystemSensorManager(mHandlerThread.getLooper());
-        mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
-        // don't bother with the light sensor if auto brightness is handled in hardware
-        if (mUseSoftwareAutoBrightness) {
-            mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
-        }
-
-        // wait until sensors are enabled before turning on screen.
-        // some devices will not activate the light sensor properly on boot
-        // unless we do this.
-        if (mUseSoftwareAutoBrightness) {
-            // turn the screen on
-            setPowerState(SCREEN_BRIGHT);
-        } else {
-            // turn everything on
-            setPowerState(ALL_BRIGHT);
-        }
-
-        synchronized (mLocks) {
-            Slog.d(TAG, "system ready!");
-            mDoneBooting = true;
-
-            enableLightSensorLocked(mUseSoftwareAutoBrightness && mAutoBrightessEnabled);
-
-            long identity = Binder.clearCallingIdentity();
-            try {
-                mBatteryStats.noteScreenBrightness(getPreferredBrightness());
-                mBatteryStats.noteScreenOn();
-            } catch (RemoteException e) {
-                // Nothing interesting to do.
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        }
-    }
-
-    void bootCompleted() {
-        Slog.d(TAG, "bootCompleted");
-        synchronized (mLocks) {
-            mBootCompleted = true;
-            userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
-            updateWakeLockLocked();
-            mLocks.notifyAll();
-        }
-    }
-
-    // for watchdog
-    public void monitor() {
-        synchronized (mLocks) { }
-    }
-
-    public int getSupportedWakeLockFlags() {
-        int result = PowerManager.PARTIAL_WAKE_LOCK
-                   | PowerManager.FULL_WAKE_LOCK
-                   | PowerManager.SCREEN_DIM_WAKE_LOCK;
-
-        if (mProximitySensor != null) {
-            result |= PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
-        }
-
-        return result;
-    }
-
-    public void setBacklightBrightness(int brightness) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-        // Don't let applications turn the screen all the way off
-        synchronized (mLocks) {
-            brightness = Math.max(brightness, mScreenBrightnessDim);
-            mLcdLight.setBrightness(brightness);
-            mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0);
-            mButtonLight.setBrightness(brightness);
-            long identity = Binder.clearCallingIdentity();
-            try {
-                mBatteryStats.noteScreenBrightness(brightness);
-            } catch (RemoteException e) {
-                Slog.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-            mScreenBrightnessAnimator.animateTo(brightness, SCREEN_BRIGHT_BIT, 0);
-        }
-    }
-
-    public void setAutoBrightnessAdjustment(float adj) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-        synchronized (mLocks) {
-            mLightSensorAdjustSetting = adj;
-            if (mSensorManager != null && mLightSensorEnabled) {
-                // clear calling identity so sensor manager battery stats are accurate
-                long identity = Binder.clearCallingIdentity();
-                try {
-                    // force recompute of backlight values
-                    if (mLightSensorValue >= 0) {
-                        int value = (int)mLightSensorValue;
-                        mLightSensorValue = -1;
-                        handleLightSensorValue(value, true);
-                    }
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-            }
-        }
-    }
-
-    public void setAttentionLight(boolean on, int color) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-        mAttentionLight.setFlashing(color, LightsService.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0);
-    }
-
-    private void enableProximityLockLocked() {
-        if (mDebugProximitySensor) {
-            Slog.d(TAG, "enableProximityLockLocked");
-        }
-        if (!mProximitySensorEnabled) {
-            // clear calling identity so sensor manager battery stats are accurate
-            long identity = Binder.clearCallingIdentity();
-            try {
-                mSensorManager.registerListener(mProximityListener, mProximitySensor,
-                        SensorManager.SENSOR_DELAY_NORMAL);
-                mProximitySensorEnabled = true;
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        }
-    }
-
-    private void disableProximityLockLocked() {
-        if (mDebugProximitySensor) {
-            Slog.d(TAG, "disableProximityLockLocked");
-        }
-        if (mProximitySensorEnabled) {
-            // clear calling identity so sensor manager battery stats are accurate
-            long identity = Binder.clearCallingIdentity();
-            try {
-                mSensorManager.unregisterListener(mProximityListener);
-                mHandler.removeCallbacks(mProximityTask);
-                if (mProximityPartialLock.isHeld()) {
-                    mProximityPartialLock.release();
-                }
-                mProximitySensorEnabled = false;
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-            if (mProximitySensorActive) {
-                mProximitySensorActive = false;
-                if (mDebugProximitySensor) {
-                    Slog.d(TAG, "disableProximityLockLocked mProxIgnoredBecauseScreenTurnedOff="
-                            + mProxIgnoredBecauseScreenTurnedOff);
-                }
-                if (!mProxIgnoredBecauseScreenTurnedOff) {
-                    forceUserActivityLocked();
-                }
-            }
-        }
-    }
-
-    private void proximityChangedLocked(boolean active) {
-        if (mDebugProximitySensor) {
-            Slog.d(TAG, "proximityChangedLocked, active: " + active);
-        }
-        if (!mProximitySensorEnabled) {
-            Slog.d(TAG, "Ignoring proximity change after sensor is disabled");
-            return;
-        }
-        if (active) {
-            if (mDebugProximitySensor) {
-                Slog.d(TAG, "b mProxIgnoredBecauseScreenTurnedOff="
-                        + mProxIgnoredBecauseScreenTurnedOff);
-            }
-            if (!mProxIgnoredBecauseScreenTurnedOff) {
-                goToSleepLocked(SystemClock.uptimeMillis(),
-                        WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR);
-            }
-            mProximitySensorActive = true;
-        } else {
-            // proximity sensor negative events trigger as user activity.
-            // temporarily set mUserActivityAllowed to true so this will work
-            // even when the keyguard is on.
-            mProximitySensorActive = false;
-            if (mDebugProximitySensor) {
-                Slog.d(TAG, "b mProxIgnoredBecauseScreenTurnedOff="
-                        + mProxIgnoredBecauseScreenTurnedOff);
-            }
-            if (!mProxIgnoredBecauseScreenTurnedOff) {
-                forceUserActivityLocked();
-            }
-
-            if (mProximityWakeLockCount == 0) {
-                // disable sensor if we have no listeners left after proximity negative
-                disableProximityLockLocked();
-            }
-        }
-    }
-
-    private void enableLightSensorLocked(boolean enable) {
-        if (mDebugLightSensor) {
-            Slog.d(TAG, "enableLightSensorLocked enable=" + enable
-                    + " mLightSensorEnabled=" + mLightSensorEnabled
-                    + " mAutoBrightessEnabled=" + mAutoBrightessEnabled
-                    + " mWaitingForFirstLightSensor=" + mWaitingForFirstLightSensor);
-        }
-        if (!mAutoBrightessEnabled) {
-            enable = false;
-        }
-        if (mSensorManager != null && mLightSensorEnabled != enable) {
-            mLightSensorEnabled = enable;
-            // clear calling identity so sensor manager battery stats are accurate
-            long identity = Binder.clearCallingIdentity();
-            try {
-                if (enable) {
-                    // reset our highest value when reenabling
-                    mHighestLightSensorValue = -1;
-                    // force recompute of backlight values
-                    final int value = (int)mLightSensorValue;
-                    if (value >= 0) {
-                        mLightSensorValue = -1;
-                        handleLightSensorValue(value, true);
-                    }
-                    mSensorManager.registerListener(mLightListener, mLightSensor,
-                            LIGHT_SENSOR_RATE);
-                } else {
-                    mSensorManager.unregisterListener(mLightListener);
-                    mHandler.removeCallbacks(mAutoBrightnessTask);
-                    mLightSensorPendingDecrease = false;
-                    mLightSensorPendingIncrease = false;
-                }
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        }
-    }
-
-    SensorEventListener mProximityListener = new SensorEventListener() {
-        public void onSensorChanged(SensorEvent event) {
-            long milliseconds = SystemClock.elapsedRealtime();
-            synchronized (mLocks) {
-                float distance = event.values[0];
-                long timeSinceLastEvent = milliseconds - mLastProximityEventTime;
-                mLastProximityEventTime = milliseconds;
-                mHandler.removeCallbacks(mProximityTask);
-                boolean proximityTaskQueued = false;
-
-                // compare against getMaximumRange to support sensors that only return 0 or 1
-                boolean active = (distance >= 0.0 && distance < PROXIMITY_THRESHOLD &&
-                        distance < mProximitySensor.getMaximumRange());
-
-                if (mDebugProximitySensor) {
-                    Slog.d(TAG, "mProximityListener.onSensorChanged active: " + active);
-                }
-                if (timeSinceLastEvent < PROXIMITY_SENSOR_DELAY) {
-                    // enforce delaying atleast PROXIMITY_SENSOR_DELAY before processing
-                    mProximityPendingValue = (active ? 1 : 0);
-                    mHandler.postDelayed(mProximityTask, PROXIMITY_SENSOR_DELAY - timeSinceLastEvent);
-                    proximityTaskQueued = true;
-                } else {
-                    // process the value immediately
-                    mProximityPendingValue = -1;
-                    proximityChangedLocked(active);
-                }
-
-                // update mProximityPartialLock state
-                boolean held = mProximityPartialLock.isHeld();
-                if (!held && proximityTaskQueued) {
-                    // hold wakelock until mProximityTask runs
-                    mProximityPartialLock.acquire();
-                } else if (held && !proximityTaskQueued) {
-                    mProximityPartialLock.release();
-                }
-            }
-        }
-
-        public void onAccuracyChanged(Sensor sensor, int accuracy) {
-            // ignore
-        }
-    };
-
-    private void handleLightSensorValue(int value, boolean immediate) {
-        long milliseconds = SystemClock.elapsedRealtime();
-        if (mLightSensorValue == -1
-                || milliseconds < mLastScreenOnTime + mLightSensorWarmupTime
-                || mWaitingForFirstLightSensor) {
-            // process the value immediately if screen has just turned on
-            mHandler.removeCallbacks(mAutoBrightnessTask);
-            mLightSensorPendingDecrease = false;
-            mLightSensorPendingIncrease = false;
-            lightSensorChangedLocked(value, immediate);
-        } else {
-            if ((value > mLightSensorValue && mLightSensorPendingDecrease) ||
-                    (value < mLightSensorValue && mLightSensorPendingIncrease) ||
-                    (value == mLightSensorValue) ||
-                    (!mLightSensorPendingDecrease && !mLightSensorPendingIncrease)) {
-                // delay processing to debounce the sensor
-                mHandler.removeCallbacks(mAutoBrightnessTask);
-                mLightSensorPendingDecrease = (value < mLightSensorValue);
-                mLightSensorPendingIncrease = (value > mLightSensorValue);
-                if (mLightSensorPendingDecrease || mLightSensorPendingIncrease) {
-                    mLightSensorPendingValue = value;
-                    mHandler.postDelayed(mAutoBrightnessTask, LIGHT_SENSOR_DELAY);
-                }
-            } else {
-                mLightSensorPendingValue = value;
-            }
-        }
-    }
-
-    SensorEventListener mLightListener = new SensorEventListener() {
-        @Override
-        public void onSensorChanged(SensorEvent event) {
-            if (mDebugLightSensor) {
-                Slog.d(TAG, "onSensorChanged: light value: " + event.values[0]);
-            }
-            synchronized (mLocks) {
-                // ignore light sensor while screen is turning off
-                if (isScreenTurningOffLocked()) {
-                    return;
-                }
-                handleLightSensorValue((int)event.values[0], mWaitingForFirstLightSensor);
-                if (mWaitingForFirstLightSensor && !mPreparingForScreenOn) {
-                    if (mDebugLightAnimation) {
-                        Slog.d(TAG, "onSensorChanged: Clearing mWaitingForFirstLightSensor.");
-                    }
-                    mWaitingForFirstLightSensor = false;
-                }
-            }
-        }
-
-        @Override
-        public void onAccuracyChanged(Sensor sensor, int accuracy) {
-            // ignore
-        }
-    };
-}
diff --git a/services/java/com/android/server/RecognitionManagerService.java b/services/java/com/android/server/RecognitionManagerService.java
index 3567cfc..1e0755d 100644
--- a/services/java/com/android/server/RecognitionManagerService.java
+++ b/services/java/com/android/server/RecognitionManagerService.java
@@ -18,13 +18,18 @@
 
 import com.android.internal.content.PackageMonitor;
 
+import android.app.AppGlobals;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Binder;
+import android.os.RemoteException;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.speech.RecognitionService;
 import android.text.TextUtils;
@@ -34,68 +39,82 @@
 
 public class RecognitionManagerService extends Binder {
     final static String TAG = "RecognitionManagerService";
-    
-    final Context mContext;
-    final MyPackageMonitor mMonitor;
-    
+
+    private final Context mContext;
+    private final MyPackageMonitor mMonitor;
+    private final IPackageManager mIPm;
+
+    private static final boolean DEBUG = false;
+
     class MyPackageMonitor extends PackageMonitor {
         public void onSomePackagesChanged() {
-            ComponentName comp = getCurRecognizer();
+            int userHandle = getChangingUserId();
+            if (DEBUG) Slog.i(TAG, "onSomePackagesChanged user=" + userHandle);
+            ComponentName comp = getCurRecognizer(userHandle);
             if (comp == null) {
                 if (anyPackagesAppearing()) {
-                    comp = findAvailRecognizer(null);
+                    comp = findAvailRecognizer(null, userHandle);
                     if (comp != null) {
-                        setCurRecognizer(comp);
+                        setCurRecognizer(comp, userHandle);
                     }
                 }
                 return;
             }
-            
+
             int change = isPackageDisappearing(comp.getPackageName()); 
             if (change == PACKAGE_PERMANENT_CHANGE
                     || change == PACKAGE_TEMPORARY_CHANGE) {
-                setCurRecognizer(findAvailRecognizer(null));
+                setCurRecognizer(findAvailRecognizer(null, userHandle), userHandle);
                 
             } else if (isPackageModified(comp.getPackageName())) {
-                setCurRecognizer(findAvailRecognizer(comp.getPackageName()));
+                setCurRecognizer(findAvailRecognizer(comp.getPackageName(), userHandle),
+                        userHandle);
             }
         }
     }
-    
+
     RecognitionManagerService(Context context) {
         mContext = context;
         mMonitor = new MyPackageMonitor();
-        mMonitor.register(context, null, true);
+        mMonitor.register(context, null, UserHandle.ALL, true);
+        mIPm = AppGlobals.getPackageManager();
+        mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
+                new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
     }
-    
+
     public void systemReady() {
-        ComponentName comp = getCurRecognizer();
+        initForUser(UserHandle.USER_OWNER);
+    }
+
+    private void initForUser(int userHandle) {
+        if (DEBUG) Slog.i(TAG, "initForUser user=" + userHandle);
+        ComponentName comp = getCurRecognizer(userHandle);
         if (comp != null) {
             // See if the current recognizer is no longer available.
             try {
-                mContext.getPackageManager().getServiceInfo(comp, 0);
-            } catch (NameNotFoundException e) {
-                comp = findAvailRecognizer(null);
+                mIPm.getServiceInfo(comp, 0, userHandle);
+            } catch (RemoteException e) {
+                comp = findAvailRecognizer(null, userHandle);
                 if (comp != null) {
-                    setCurRecognizer(comp);
+                    setCurRecognizer(comp, userHandle);
                 }
             }
         } else {
-            comp = findAvailRecognizer(null);
+            comp = findAvailRecognizer(null, userHandle);
             if (comp != null) {
-                setCurRecognizer(comp);
+                setCurRecognizer(comp, userHandle);
             }
         }
     }
-    
-    ComponentName findAvailRecognizer(String prefPackage) {
+
+    ComponentName findAvailRecognizer(String prefPackage, int userHandle) {
         List<ResolveInfo> available =
-                mContext.getPackageManager().queryIntentServices(
-                        new Intent(RecognitionService.SERVICE_INTERFACE), 0);
+                mContext.getPackageManager().queryIntentServicesAsUser(
+                        new Intent(RecognitionService.SERVICE_INTERFACE), 0, userHandle);
         int numAvailable = available.size();
-    
+
         if (numAvailable == 0) {
-            Slog.w(TAG, "no available voice recognition services found");
+            Slog.w(TAG, "no available voice recognition services found for user " + userHandle);
             return null;
         } else {
             if (prefPackage != null) {
@@ -109,25 +128,42 @@
             if (numAvailable > 1) {
                 Slog.w(TAG, "more than one voice recognition service found, picking first");
             }
-    
+
             ServiceInfo serviceInfo = available.get(0).serviceInfo;
             return new ComponentName(serviceInfo.packageName, serviceInfo.name);
         }
     }
-    
-    ComponentName getCurRecognizer() {
-        String curRecognizer = Settings.Secure.getString(
+
+    ComponentName getCurRecognizer(int userHandle) {
+        String curRecognizer = Settings.Secure.getStringForUser(
                 mContext.getContentResolver(),
-                Settings.Secure.VOICE_RECOGNITION_SERVICE);
+                Settings.Secure.VOICE_RECOGNITION_SERVICE, userHandle);
         if (TextUtils.isEmpty(curRecognizer)) {
             return null;
         }
+        if (DEBUG) Slog.i(TAG, "getCurRecognizer curRecognizer=" + curRecognizer
+                + " user=" + userHandle);
         return ComponentName.unflattenFromString(curRecognizer);
     }
-    
-    void setCurRecognizer(ComponentName comp) {
-        Settings.Secure.putString(mContext.getContentResolver(),
+
+    void setCurRecognizer(ComponentName comp, int userHandle) {
+        Settings.Secure.putStringForUser(mContext.getContentResolver(),
                 Settings.Secure.VOICE_RECOGNITION_SERVICE,
-                comp != null ? comp.flattenToShortString() : "");
+                comp != null ? comp.flattenToShortString() : "", userHandle);
+        if (DEBUG) Slog.i(TAG, "setCurRecognizer comp=" + comp
+                + " user=" + userHandle);
     }
+
+    BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (DEBUG) Slog.i(TAG, "received " + action);
+            if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
+                int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+                if (userHandle > 0) {
+                    initForUser(userHandle);
+                }
+            }
+        }
+    };
 }
diff --git a/services/java/com/android/server/SamplingProfilerService.java b/services/java/com/android/server/SamplingProfilerService.java
index 0034d2c..fbf1aa4 100644
--- a/services/java/com/android/server/SamplingProfilerService.java
+++ b/services/java/com/android/server/SamplingProfilerService.java
@@ -90,7 +90,7 @@
     private void registerSettingObserver(Context context) {
         ContentResolver contentResolver = context.getContentResolver();
         contentResolver.registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.SAMPLING_PROFILER_MS),
+                Settings.Global.getUriFor(Settings.Global.SAMPLING_PROFILER_MS),
                 false, new SamplingProfilerSettingsObserver(contentResolver));
     }
 
@@ -111,8 +111,8 @@
         }
         @Override
         public void onChange(boolean selfChange) {
-            Integer samplingProfilerMs = Settings.Secure.getInt(
-                    mContentResolver, Settings.Secure.SAMPLING_PROFILER_MS, 0);
+            Integer samplingProfilerMs = Settings.Global.getInt(
+                    mContentResolver, Settings.Global.SAMPLING_PROFILER_MS, 0);
             // setting this secure property will start or stop sampling profiler,
             // as well as adjust the the time between taking snapshots.
             SystemProperties.set("persist.sys.profiler_ms", samplingProfilerMs.toString());
diff --git a/services/java/com/android/server/ServiceWatcher.java b/services/java/com/android/server/ServiceWatcher.java
new file mode 100644
index 0000000..2e7c6d1
--- /dev/null
+++ b/services/java/com/android/server/ServiceWatcher.java
@@ -0,0 +1,300 @@
+/*
+ * 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;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.content.pm.Signature;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.UserHandle;
+import android.util.Log;
+
+import com.android.internal.content.PackageMonitor;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+/**
+ * Find the best Service, and bind to it.
+ * Handles run-time package changes.
+ */
+public class ServiceWatcher implements ServiceConnection {
+    private static final boolean D = false;
+    public static final String EXTRA_SERVICE_VERSION = "serviceVersion";
+
+    private final String mTag;
+    private final Context mContext;
+    private final PackageManager mPm;
+    private final List<HashSet<Signature>> mSignatureSets;
+    private final String mAction;
+    private final Runnable mNewServiceWork;
+    private final Handler mHandler;
+
+    private Object mLock = new Object();
+
+    // all fields below synchronized on mLock
+    private IBinder mBinder;   // connected service
+    private String mPackageName;  // current best package
+    private int mVersion = Integer.MIN_VALUE;  // current best version
+    private int mCurrentUserId;
+
+    public static ArrayList<HashSet<Signature>> getSignatureSets(Context context,
+            List<String> initialPackageNames) {
+        PackageManager pm = context.getPackageManager();
+        ArrayList<HashSet<Signature>> sigSets = new ArrayList<HashSet<Signature>>();
+        for (int i = 0, size = initialPackageNames.size(); i < size; i++) {
+            String pkg = initialPackageNames.get(i);
+            try {
+                HashSet<Signature> set = new HashSet<Signature>();
+                Signature[] sigs = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES).signatures;
+                set.addAll(Arrays.asList(sigs));
+                sigSets.add(set);
+            } catch (NameNotFoundException e) {
+                Log.w("ServiceWatcher", pkg + " not found");
+            }
+        }
+        return sigSets;
+    }
+
+    public ServiceWatcher(Context context, String logTag, String action,
+            List<String> initialPackageNames, Runnable newServiceWork, Handler handler, int userId) {
+        mContext = context;
+        mTag = logTag;
+        mAction = action;
+        mPm = mContext.getPackageManager();
+        mNewServiceWork = newServiceWork;
+        mHandler = handler;
+        mCurrentUserId = userId;
+
+        mSignatureSets = getSignatureSets(context, initialPackageNames);
+    }
+
+    public boolean start() {
+        synchronized (mLock) {
+            if (!bindBestPackageLocked(null)) return false;
+        }
+
+        mPackageMonitor.register(mContext, null, UserHandle.ALL, true);
+        return true;
+    }
+
+    /**
+     * Searches and binds to the best package, or do nothing
+     * if the best package is already bound.
+     * Only checks the named package, or checks all packages if it
+     * is null.
+     * Return true if a new package was found to bind to.
+     */
+    private boolean bindBestPackageLocked(String justCheckThisPackage) {
+        Intent intent = new Intent(mAction);
+        if (justCheckThisPackage != null) {
+            intent.setPackage(justCheckThisPackage);
+        }
+        List<ResolveInfo> rInfos = mPm.queryIntentServicesAsUser(new Intent(mAction),
+                PackageManager.GET_META_DATA, mCurrentUserId);
+        int bestVersion = Integer.MIN_VALUE;
+        String bestPackage = null;
+        for (ResolveInfo rInfo : rInfos) {
+            String packageName = rInfo.serviceInfo.packageName;
+
+            // check signature
+            try {
+                PackageInfo pInfo;
+                pInfo = mPm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
+                if (!isSignatureMatch(pInfo.signatures)) {
+                    Log.w(mTag, packageName + " resolves service " + mAction +
+                            ", but has wrong signature, ignoring");
+                    continue;
+                }
+            } catch (NameNotFoundException e) {
+                Log.wtf(mTag, e);
+                continue;
+            }
+
+            // check version
+            int version = 0;
+            if (rInfo.serviceInfo.metaData != null) {
+                version = rInfo.serviceInfo.metaData.getInt(EXTRA_SERVICE_VERSION, 0);
+            }
+
+            if (version > mVersion) {
+                bestVersion = version;
+                bestPackage = packageName;
+            }
+        }
+
+        if (D) Log.d(mTag, String.format("bindBestPackage for %s : %s found %d, %s", mAction,
+                (justCheckThisPackage == null ? "" : "(" + justCheckThisPackage + ") "),
+                rInfos.size(),
+                (bestPackage == null ? "no new best package" : "new best packge: " + bestPackage)));
+
+        if (bestPackage != null) {
+            bindToPackageLocked(bestPackage, bestVersion);
+            return true;
+        }
+        return false;
+    }
+
+    private void unbindLocked() {
+        String pkg;
+        pkg = mPackageName;
+        mPackageName = null;
+        mVersion = Integer.MIN_VALUE;
+        if (pkg != null) {
+            if (D) Log.d(mTag, "unbinding " + pkg);
+            mContext.unbindService(this);
+        }
+    }
+
+    private void bindToPackageLocked(String packageName, int version) {
+        unbindLocked();
+        Intent intent = new Intent(mAction);
+        intent.setPackage(packageName);
+        mPackageName = packageName;
+        mVersion = version;
+        if (D) Log.d(mTag, "binding " + packageName + " (version " + version + ")");
+        mContext.bindService(intent, this, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
+                | Context.BIND_ALLOW_OOM_MANAGEMENT | Context.BIND_NOT_VISIBLE, mCurrentUserId);
+    }
+
+    public static boolean isSignatureMatch(Signature[] signatures,
+            List<HashSet<Signature>> sigSets) {
+        if (signatures == null) return false;
+
+        // build hashset of input to test against
+        HashSet<Signature> inputSet = new HashSet<Signature>();
+        for (Signature s : signatures) {
+            inputSet.add(s);
+        }
+
+        // test input against each of the signature sets
+        for (HashSet<Signature> referenceSet : sigSets) {
+            if (referenceSet.equals(inputSet)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isSignatureMatch(Signature[] signatures) {
+        return isSignatureMatch(signatures, mSignatureSets);
+    }
+
+    private final PackageMonitor mPackageMonitor = new PackageMonitor() {
+        /**
+         * Called when package has been reinstalled
+         */
+        @Override
+        public void onPackageUpdateFinished(String packageName, int uid) {
+            synchronized (mLock) {
+                if (packageName.equals(mPackageName)) {
+                    // package updated, make sure to rebind
+                    unbindLocked();
+                }
+                // check the updated package in case it is better
+                bindBestPackageLocked(packageName);
+            }
+        }
+
+        @Override
+        public void onPackageAdded(String packageName, int uid) {
+            synchronized (mLock) {
+                if (packageName.equals(mPackageName)) {
+                    // package updated, make sure to rebind
+                    unbindLocked();
+                }
+                // check the new package is case it is better
+                bindBestPackageLocked(packageName);
+            }
+        }
+
+        @Override
+        public void onPackageRemoved(String packageName, int uid) {
+            synchronized (mLock) {
+                if (packageName.equals(mPackageName)) {
+                    unbindLocked();
+                    // the currently bound package was removed,
+                    // need to search for a new package
+                    bindBestPackageLocked(null);
+                }
+            }
+        }
+    };
+
+    @Override
+    public void onServiceConnected(ComponentName name, IBinder binder) {
+        synchronized (mLock) {
+            String packageName = name.getPackageName();
+            if (packageName.equals(mPackageName)) {
+                if (D) Log.d(mTag, packageName + " connected");
+                mBinder = binder;
+                if (mHandler !=null && mNewServiceWork != null) {
+                    mHandler.post(mNewServiceWork);
+                }
+            } else {
+                Log.w(mTag, "unexpected onServiceConnected: " + packageName);
+            }
+        }
+    }
+
+    @Override
+    public void onServiceDisconnected(ComponentName name) {
+        synchronized (mLock) {
+            String packageName = name.getPackageName();
+            if (D) Log.d(mTag, packageName + " disconnected");
+
+            if (packageName.equals(mPackageName)) {
+                mBinder = null;
+            }
+        }
+    }
+
+    public String getBestPackageName() {
+        synchronized (mLock) {
+            return mPackageName;
+        }
+    }
+
+    public int getBestVersion() {
+        synchronized (mLock) {
+            return mVersion;
+        }
+    }
+
+    public IBinder getBinder() {
+        synchronized (mLock) {
+            return mBinder;
+        }
+    }
+
+    public void switchUser(int userId) {
+        synchronized (mLock) {
+            unbindLocked();
+            mCurrentUserId = userId;
+            bindBestPackageLocked(null);
+        }
+    }
+}
diff --git a/services/java/com/android/server/ShutdownActivity.java b/services/java/com/android/server/ShutdownActivity.java
index d85abe6..be65141 100644
--- a/services/java/com/android/server/ShutdownActivity.java
+++ b/services/java/com/android/server/ShutdownActivity.java
@@ -17,13 +17,16 @@
 package com.android.server;
 
 import android.app.Activity;
-import android.content.BroadcastReceiver;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.IPowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.util.Slog;
 
-import com.android.server.pm.ShutdownThread;
+import com.android.server.power.ShutdownThread;
 
 public class ShutdownActivity extends Activity {
 
@@ -40,15 +43,27 @@
         mConfirm = intent.getBooleanExtra(Intent.EXTRA_KEY_CONFIRM, false);
         Slog.i(TAG, "onCreate(): confirm=" + mConfirm);
 
-        Handler h = new Handler();
-        h.post(new Runnable() {
+        Thread thr = new Thread("ShutdownActivity") {
+            @Override
             public void run() {
-                if (mReboot) {
-                    ShutdownThread.reboot(ShutdownActivity.this, null, mConfirm);
-                } else {
-                    ShutdownThread.shutdown(ShutdownActivity.this, mConfirm);
+                IPowerManager pm = IPowerManager.Stub.asInterface(
+                        ServiceManager.getService(Context.POWER_SERVICE));
+                try {
+                    if (mReboot) {
+                        pm.reboot(mConfirm, null, false);
+                    } else {
+                        pm.shutdown(mConfirm, false);
+                    }
+                } catch (RemoteException e) {
                 }
             }
-        });
+        };
+        thr.start();
+        finish();
+        // Wait for us to tell the power manager to shutdown.
+        try {
+            thr.join();
+        } catch (InterruptedException e) {
+        }
     }
 }
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index 78c0c12..439eebe 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -26,8 +26,8 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.Slog;
-import android.view.View;
 
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.IStatusBarService;
@@ -64,7 +64,7 @@
             = new HashMap<IBinder,StatusBarNotification>();
 
     // for disabling the status bar
-    ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();
+    final ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();
     IBinder mSysUiVisToken = new Binder();
     int mDisabled = 0;
 
@@ -75,15 +75,17 @@
     int mImeWindowVis = 0;
     int mImeBackDisposition;
     IBinder mImeToken = null;
+    int mCurrentUserId;
 
     private class DisableRecord implements IBinder.DeathRecipient {
+        int userId;
         String pkg;
         int what;
         IBinder token;
 
         public void binderDied() {
             Slog.i(TAG, "binder died for pkg=" + pkg);
-            disable(0, token, pkg);
+            disableInternal(userId, 0, token, pkg);
             token.unlinkToDeath(this, 0);
         }
     }
@@ -117,43 +119,58 @@
     // ================================================================================
     // From IStatusBarService
     // ================================================================================
-    public void expand() {
+    public void expandNotificationsPanel() {
         enforceExpandStatusBar();
 
         if (mBar != null) {
             try {
-                mBar.animateExpand();
+                mBar.animateExpandNotificationsPanel();
             } catch (RemoteException ex) {
             }
         }
     }
 
-    public void collapse() {
+    public void collapsePanels() {
         enforceExpandStatusBar();
 
         if (mBar != null) {
             try {
-                mBar.animateCollapse();
+                mBar.animateCollapsePanels();
+            } catch (RemoteException ex) {
+            }
+        }
+    }
+
+    public void expandSettingsPanel() {
+        enforceExpandStatusBar();
+
+        if (mBar != null) {
+            try {
+                mBar.animateExpandSettingsPanel();
             } catch (RemoteException ex) {
             }
         }
     }
 
     public void disable(int what, IBinder token, String pkg) {
+        disableInternal(mCurrentUserId, what, token, pkg);
+    }
+
+    private void disableInternal(int userId, int what, IBinder token, String pkg) {
         enforceStatusBar();
 
         synchronized (mLock) {
-            disableLocked(what, token, pkg);
+            disableLocked(userId, what, token, pkg);
         }
     }
 
-    private void disableLocked(int what, IBinder token, String pkg) {
+    private void disableLocked(int userId, int what, IBinder token, String pkg) {
         // It's important that the the callback and the call to mBar get done
         // in the same order when multiple threads are calling this function
         // so they are paired correctly.  The messages on the handler will be
         // handled in the order they were enqueued, but will be outside the lock.
-        manageDisableListLocked(what, token, pkg);
-        final int net = gatherDisableActionsLocked();
+        manageDisableListLocked(userId, what, token, pkg);
+        final int net = gatherDisableActionsLocked(userId);
         if (net != mDisabled) {
             mDisabled = net;
             mHandler.post(new Runnable() {
@@ -180,7 +197,8 @@
                 throw new SecurityException("invalid status bar icon slot: " + slot);
             }
 
-            StatusBarIcon icon = new StatusBarIcon(iconPackage, iconId, iconLevel, 0,
+            StatusBarIcon icon = new StatusBarIcon(iconPackage, UserHandle.OWNER, iconId,
+                    iconLevel, 0,
                     contentDescription);
             //Slog.d(TAG, "setIcon slot=" + slot + " index=" + index + " icon=" + icon);
             mIcons.setIcon(index, icon);
@@ -300,7 +318,10 @@
 
         synchronized (mLock) {
             updateUiVisibilityLocked(vis, mask);
-            disableLocked(vis & StatusBarManager.DISABLE_MASK, mSysUiVisToken,
+            disableLocked(
+                    mCurrentUserId,
+                    vis & StatusBarManager.DISABLE_MASK,
+                    mSysUiVisToken,
                     "WindowManager.LayoutParams");
         }
     }
@@ -370,6 +391,12 @@
         }
     }
 
+    @Override
+    public void setCurrentUser(int newUserId) {
+        if (SPEW) Slog.d(TAG, "Setting current user to user " + newUserId);
+        mCurrentUserId = newUserId;
+    }
+
     private void enforceStatusBar() {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR,
                 "StatusBarManagerService");
@@ -405,7 +432,7 @@
             }
         }
         synchronized (mLock) {
-            switches[0] = gatherDisableActionsLocked();
+            switches[0] = gatherDisableActionsLocked(mCurrentUserId);
             switches[1] = mSystemUiVisibility;
             switches[2] = mMenuVisible ? 1 : 0;
             switches[3] = mImeWindowVis;
@@ -506,9 +533,10 @@
     // ================================================================================
 
     // lock on mDisableRecords
-    void manageDisableListLocked(int what, IBinder token, String pkg) {
+    void manageDisableListLocked(int userId, int what, IBinder token, String pkg) {
         if (SPEW) {
-            Slog.d(TAG, "manageDisableList what=0x" + Integer.toHexString(what) + " pkg=" + pkg);
+            Slog.d(TAG, "manageDisableList userId=" + userId
+                    + " what=0x" + Integer.toHexString(what) + " pkg=" + pkg);
         }
         // update the list
         final int N = mDisableRecords.size();
@@ -516,7 +544,7 @@
         int i;
         for (i=0; i<N; i++) {
             DisableRecord t = mDisableRecords.get(i);
-            if (t.token == token) {
+            if (t.token == token && t.userId == userId) {
                 tok = t;
                 break;
             }
@@ -529,6 +557,7 @@
         } else {
             if (tok == null) {
                 tok = new DisableRecord();
+                tok.userId = userId;
                 try {
                     token.linkToDeath(tok, 0);
                 }
@@ -544,12 +573,15 @@
     }
 
     // lock on mDisableRecords
-    int gatherDisableActionsLocked() {
+    int gatherDisableActionsLocked(int userId) {
         final int N = mDisableRecords.size();
         // gather the new net flags
         int net = 0;
         for (int i=0; i<N; i++) {
-            net |= mDisableRecords.get(i).what;
+            final DisableRecord rec = mDisableRecords.get(i);
+            if (rec.userId == userId) {
+                net |= rec.what;
+            }
         }
         return net;
     }
@@ -581,13 +613,15 @@
         }
 
         synchronized (mLock) {
+            pw.println("  mDisabled=0x" + Integer.toHexString(mDisabled));
             final int N = mDisableRecords.size();
-            pw.println("  mDisableRecords.size=" + N
-                    + " mDisabled=0x" + Integer.toHexString(mDisabled));
+            pw.println("  mDisableRecords.size=" + N);
             for (int i=0; i<N; i++) {
                 DisableRecord tok = mDisableRecords.get(i);
-                pw.println("    [" + i + "] what=0x" + Integer.toHexString(tok.what)
-                                + " pkg=" + tok.pkg + " token=" + tok.token);
+                pw.println("    [" + i + "] userId=" + tok.userId
+                                + " what=0x" + Integer.toHexString(tok.what)
+                                + " pkg=" + tok.pkg
+                                + " token=" + tok.token);
             }
         }
     }
@@ -597,7 +631,7 @@
             String action = intent.getAction();
             if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
                     || Intent.ACTION_SCREEN_OFF.equals(action)) {
-                collapse();
+                collapsePanels();
             }
             /*
             else if (Telephony.Intents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
diff --git a/services/java/com/android/server/SystemBackupAgent.java b/services/java/com/android/server/SystemBackupAgent.java
index a7a583c..8cf273d 100644
--- a/services/java/com/android/server/SystemBackupAgent.java
+++ b/services/java/com/android/server/SystemBackupAgent.java
@@ -24,8 +24,10 @@
 import android.app.backup.FullBackupDataOutput;
 import android.app.backup.WallpaperBackupHelper;
 import android.content.Context;
+import android.os.Environment;
 import android.os.ParcelFileDescriptor;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.Slog;
 
 
@@ -45,11 +47,13 @@
     private static final String WALLPAPER_INFO_FILENAME = "wallpaper_info.xml";
 
     // TODO: Will need to change if backing up non-primary user's wallpaper
-    private static final String WALLPAPER_IMAGE_DIR = "/data/system/users/0";
+    private static final String WALLPAPER_IMAGE_DIR =
+            Environment.getUserSystemDirectory(UserHandle.USER_OWNER).getAbsolutePath();
     private static final String WALLPAPER_IMAGE = WallpaperBackupHelper.WALLPAPER_IMAGE;
 
     // TODO: Will need to change if backing up non-primary user's wallpaper
-    private static final String WALLPAPER_INFO_DIR = "/data/system/users/0";
+    private static final String WALLPAPER_INFO_DIR =
+            Environment.getUserSystemDirectory(UserHandle.USER_OWNER).getAbsolutePath();
     private static final String WALLPAPER_INFO = WallpaperBackupHelper.WALLPAPER_INFO;
     // Use old keys to keep legacy data compatibility and avoid writing two wallpapers
     private static final String WALLPAPER_IMAGE_KEY = WallpaperBackupHelper.WALLPAPER_IMAGE_KEY;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2676537..894c4d0 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -28,6 +28,8 @@
 import android.content.res.Configuration;
 import android.media.AudioService;
 import android.net.wifi.p2p.WifiP2pService;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.SchedulingPolicyService;
@@ -35,11 +37,9 @@
 import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.provider.Settings;
-import android.server.BluetoothA2dpService;
-import android.server.BluetoothService;
+import android.os.UserHandle;
 import android.server.search.SearchManagerService;
-import android.service.dreams.DreamManagerService;
+import android.service.dreams.DreamService;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
@@ -51,11 +51,17 @@
 import com.android.internal.widget.LockSettingsService;
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.am.ActivityManagerService;
+import com.android.server.am.BatteryStatsService;
+import com.android.server.display.DisplayManagerService;
+import com.android.server.dreams.DreamManagerService;
 import com.android.server.input.InputManagerService;
 import com.android.server.net.NetworkPolicyManagerService;
 import com.android.server.net.NetworkStatsService;
+import com.android.server.pm.Installer;
 import com.android.server.pm.PackageManagerService;
-import com.android.server.pm.ShutdownThread;
+import com.android.server.pm.UserManagerService;
+import com.android.server.power.PowerManagerService;
+import com.android.server.power.ShutdownThread;
 import com.android.server.usb.UsbService;
 import com.android.server.wm.WindowManagerService;
 
@@ -114,13 +120,16 @@
                 : Integer.parseInt(factoryTestStr);
         final boolean headless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
 
+        Installer installer = null;
         AccountManagerService accountManager = null;
         ContentService contentService = null;
         LightsService lights = null;
         PowerManagerService power = null;
+        DisplayManagerService display = null;
         BatteryService battery = null;
         VibratorService vibrator = null;
         AlarmManagerService alarm = null;
+        MountService mountService = null;
         NetworkManagementService networkManagement = null;
         NetworkStatsService networkStats = null;
         NetworkPolicyManagerService networkPolicy = null;
@@ -131,20 +140,73 @@
         IPackageManager pm = null;
         Context context = null;
         WindowManagerService wm = null;
-        BluetoothService bluetooth = null;
-        BluetoothA2dpService bluetoothA2dp = null;
+        BluetoothManagerService bluetooth = null;
         DockObserver dock = null;
         UsbService usb = null;
         SerialService serial = null;
+        TwilightService twilight = null;
         UiModeManagerService uiMode = null;
         RecognitionManagerService recognition = null;
         ThrottleService throttle = null;
         NetworkTimeUpdateService networkTimeUpdater = null;
         CommonTimeManagementService commonTimeMgmtService = null;
         InputManagerService inputManager = null;
+        TelephonyRegistry telephonyRegistry = null;
+
+        // Create a shared handler thread for UI within the system server.
+        // This thread is used by at least the following components:
+        // - WindowManagerPolicy
+        // - KeyguardViewManager
+        // - DisplayManagerService
+        HandlerThread uiHandlerThread = new HandlerThread("UI");
+        uiHandlerThread.start();
+        Handler uiHandler = new Handler(uiHandlerThread.getLooper());
+        uiHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                //Looper.myLooper().setMessageLogging(new LogPrinter(
+                //        Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM));
+                android.os.Process.setThreadPriority(
+                        android.os.Process.THREAD_PRIORITY_FOREGROUND);
+                android.os.Process.setCanSelfBackground(false);
+
+                // For debug builds, log event loop stalls to dropbox for analysis.
+                if (StrictMode.conditionallyEnableDebugLogging()) {
+                    Slog.i(TAG, "Enabled StrictMode logging for UI Looper");
+                }
+            }
+        });
+
+        // Create a handler thread just for the window manager to enjoy.
+        HandlerThread wmHandlerThread = new HandlerThread("WindowManager");
+        wmHandlerThread.start();
+        Handler wmHandler = new Handler(wmHandlerThread.getLooper());
+        wmHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                //Looper.myLooper().setMessageLogging(new LogPrinter(
+                //        android.util.Log.DEBUG, TAG, android.util.Log.LOG_ID_SYSTEM));
+                android.os.Process.setThreadPriority(
+                        android.os.Process.THREAD_PRIORITY_DISPLAY);
+                android.os.Process.setCanSelfBackground(false);
+
+                // For debug builds, log event loop stalls to dropbox for analysis.
+                if (StrictMode.conditionallyEnableDebugLogging()) {
+                    Slog.i(TAG, "Enabled StrictMode logging for WM Looper");
+                }
+            }
+        });
 
         // Critical services...
+        boolean onlyCore = false;
         try {
+            // Wait for installd to finished starting up so that it has a chance to
+            // create critical directories such as /data/user with the appropriate
+            // permissions.  We need this to complete before we initialize other services.
+            Slog.i(TAG, "Waiting for installd to be ready.");
+            installer = new Installer();
+            installer.ping();
+
             Slog.i(TAG, "Entropy Mixer");
             ServiceManager.addService("entropy", new EntropyMixer());
 
@@ -155,8 +217,13 @@
             Slog.i(TAG, "Activity Manager");
             context = ActivityManagerService.main(factoryTest);
 
+            Slog.i(TAG, "Display Manager");
+            display = new DisplayManagerService(context, wmHandler, uiHandler);
+            ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
+
             Slog.i(TAG, "Telephony Registry");
-            ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));
+            telephonyRegistry = new TelephonyRegistry(context);
+            ServiceManager.addService("telephony.registry", telephonyRegistry);
 
             Slog.i(TAG, "Scheduling Policy");
             ServiceManager.addService(Context.SCHEDULING_POLICY_SERVICE,
@@ -164,10 +231,14 @@
 
             AttributeCache.init(context);
 
+            if (!display.waitForDefaultDisplay()) {
+                reportWtf("Timeout waiting for default display to be initialized.",
+                        new Throwable());
+            }
+
             Slog.i(TAG, "Package Manager");
             // Only run "core" apps if we're encrypting the device.
             String cryptState = SystemProperties.get("vold.decrypt");
-            boolean onlyCore = false;
             if (ENCRYPTING_STATE.equals(cryptState)) {
                 Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
                 onlyCore = true;
@@ -176,7 +247,7 @@
                 onlyCore = true;
             }
 
-            pm = PackageManagerService.main(context,
+            pm = PackageManagerService.main(context, installer,
                     factoryTest != SystemServer.FACTORY_TEST_OFF,
                     onlyCore);
             boolean firstBoot = false;
@@ -186,6 +257,11 @@
             }
 
             ActivityManagerService.setSystemProcess();
+            
+            Slog.i(TAG, "User Service");
+            ServiceManager.addService(Context.USER_SERVICE,
+                    UserManagerService.getInstance());
+
 
             mContentResolver = context.getContentResolver();
 
@@ -218,7 +294,8 @@
 
             // only initialize the power service after we have started the
             // lights service, content providers and the battery service.
-            power.init(context, lights, ActivityManagerService.self(), battery);
+            power.init(context, lights, ActivityManagerService.self(), battery,
+                    BatteryStatsService.getService(), display);
 
             Slog.i(TAG, "Alarm Manager");
             alarm = new AlarmManagerService(context);
@@ -228,16 +305,25 @@
             Watchdog.getInstance().init(context, battery, power, alarm,
                     ActivityManagerService.self());
 
+            Slog.i(TAG, "Input Manager");
+            inputManager = new InputManagerService(context, wmHandler);
+
             Slog.i(TAG, "Window Manager");
-            wm = WindowManagerService.main(context, power,
+            wm = WindowManagerService.main(context, power, display, inputManager,
+                    uiHandler, wmHandler,
                     factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
                     !firstBoot, onlyCore);
             ServiceManager.addService(Context.WINDOW_SERVICE, wm);
-            inputManager = wm.getInputManagerService();
             ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
 
             ActivityManagerService.self().setWindowManager(wm);
 
+            inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
+            inputManager.start();
+
+            display.setWindowManager(wm);
+            display.setInputManager(inputManager);
+
             // Skip Bluetooth if we have an emulator kernel
             // TODO: Use a more reliable check to see if this product should
             // support Bluetooth - see bug 988521
@@ -246,23 +332,9 @@
             } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
                 Slog.i(TAG, "No Bluetooth Service (factory test)");
             } else {
-                Slog.i(TAG, "Bluetooth Service");
-                bluetooth = new BluetoothService(context);
-                ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, bluetooth);
-                bluetooth.initAfterRegistration();
-
-                if (!"0".equals(SystemProperties.get("system_init.startaudioservice"))) {
-                    bluetoothA2dp = new BluetoothA2dpService(context, bluetooth);
-                    ServiceManager.addService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE,
-                                              bluetoothA2dp);
-                    bluetooth.initAfterA2dpRegistration();
-                }
-
-                int bluetoothOn = Settings.Secure.getInt(mContentResolver,
-                    Settings.Secure.BLUETOOTH_ON, 0);
-                if (bluetoothOn != 0) {
-                    bluetooth.enable();
-                }
+                Slog.i(TAG, "Bluetooth Manager Service");
+                bluetooth = new BluetoothManagerService(context);
+                ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);
             }
 
         } catch (RuntimeException e) {
@@ -322,7 +394,6 @@
         }
 
         if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
-            MountService mountService = null;
             if (!"0".equals(SystemProperties.get("system_init.startmountservice"))) {
                 try {
                     /*
@@ -555,17 +626,18 @@
             try {
                 Slog.i(TAG, "Dock Observer");
                 // Listen for dock station changes
-                dock = new DockObserver(context, power);
+                dock = new DockObserver(context);
             } catch (Throwable e) {
                 reportWtf("starting DockObserver", e);
             }
 
             try {
-                Slog.i(TAG, "Wired Accessory Observer");
+                Slog.i(TAG, "Wired Accessory Manager");
                 // Listen for wired headset changes
-                new WiredAccessoryObserver(context);
+                inputManager.setWiredAccessoryCallbacks(
+                        new WiredAccessoryManager(context, inputManager));
             } catch (Throwable e) {
-                reportWtf("starting WiredAccessoryObserver", e);
+                reportWtf("starting WiredAccessoryManager", e);
             }
 
             try {
@@ -587,9 +659,16 @@
             }
 
             try {
+                Slog.i(TAG, "Twilight Service");
+                twilight = new TwilightService(context);
+            } catch (Throwable e) {
+                reportWtf("starting TwilightService", e);
+            }
+
+            try {
                 Slog.i(TAG, "UI Mode Manager Service");
                 // Listen for UI mode changes
-                uiMode = new UiModeManagerService(context);
+                uiMode = new UiModeManagerService(context, twilight);
             } catch (Throwable e) {
                 reportWtf("starting UiModeManagerService", e);
             }
@@ -659,12 +738,12 @@
             }
             
             if (context.getResources().getBoolean(
-                    com.android.internal.R.bool.config_enableDreams)) {
+                    com.android.internal.R.bool.config_dreamsSupported)) {
                 try {
                     Slog.i(TAG, "Dreams Service");
                     // Dreams (interactive idle-time views, a/k/a screen savers)
-                    dreamy = new DreamManagerService(context);
-                    ServiceManager.addService("dreams", dreamy);
+                    dreamy = new DreamManagerService(context, wmHandler);
+                    ServiceManager.addService(DreamService.DREAM_SERVICE, dreamy);
                 } catch (Throwable e) {
                     reportWtf("starting DreamManagerService", e);
                 }
@@ -734,15 +813,27 @@
         w.getDefaultDisplay().getMetrics(metrics);
         context.getResources().updateConfiguration(config, metrics);
 
-        power.systemReady();
+        try {
+            power.systemReady(twilight, dreamy);
+        } catch (Throwable e) {
+            reportWtf("making Power Manager Service ready", e);
+        }
+
         try {
             pm.systemReady();
         } catch (Throwable e) {
             reportWtf("making Package Manager Service ready", e);
         }
 
+        try {
+            display.systemReady(safeMode, onlyCore);
+        } catch (Throwable e) {
+            reportWtf("making Display Manager Service ready", e);
+        }
+
         // These are needed to propagate to the runnable below.
         final Context contextF = context;
+        final MountService mountServiceF = mountService;
         final BatteryService batteryF = battery;
         final NetworkManagementService networkManagementF = networkManagement;
         final NetworkStatsService networkStatsF = networkStats;
@@ -751,6 +842,7 @@
         final DockObserver dockF = dock;
         final UsbService usbF = usb;
         final ThrottleService throttleF = throttle;
+        final TwilightService twilightF = twilight;
         final UiModeManagerService uiModeF = uiMode;
         final AppWidgetService appWidgetF = appWidget;
         final WallpaperManagerService wallpaperF = wallpaper;
@@ -764,7 +856,7 @@
         final StatusBarManagerService statusBarF = statusBar;
         final DreamManagerService dreamyF = dreamy;
         final InputManagerService inputManagerF = inputManager;
-        final BluetoothService bluetoothF = bluetooth;
+        final TelephonyRegistry telephonyRegistryF = telephonyRegistry;
 
         // We now tell the activity manager it is okay to run third party
         // code.  It will call back into us once it has gotten to the state
@@ -777,6 +869,11 @@
 
                 if (!headless) startSystemUi(contextF);
                 try {
+                    if (mountServiceF != null) mountServiceF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Mount Service ready", e);
+                }
+                try {
                     if (batteryF != null) batteryF.systemReady();
                 } catch (Throwable e) {
                     reportWtf("making Battery Service ready", e);
@@ -812,6 +909,11 @@
                     reportWtf("making USB Service ready", e);
                 }
                 try {
+                    if (twilightF != null) twilightF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("makin Twilight Service ready", e);
+                }
+                try {
                     if (uiModeF != null) uiModeF.systemReady();
                 } catch (Throwable e) {
                     reportWtf("making UI Mode Service ready", e);
@@ -877,10 +979,16 @@
                     reportWtf("making DreamManagerService ready", e);
                 }
                 try {
-                    if (inputManagerF != null) inputManagerF.systemReady(bluetoothF);
+                    // TODO(BT) Pass parameter to input manager
+                    if (inputManagerF != null) inputManagerF.systemReady();
                 } catch (Throwable e) {
                     reportWtf("making InputManagerService ready", e);
                 }
+                try {
+                    if (telephonyRegistryF != null) telephonyRegistryF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making TelephonyRegistry ready", e);
+                }
             }
         });
 
@@ -898,7 +1006,7 @@
         intent.setComponent(new ComponentName("com.android.systemui",
                     "com.android.systemui.SystemUIService"));
         Slog.d(TAG, "Starting service: " + intent);
-        context.startService(intent);
+        context.startServiceAsUser(intent, UserHandle.OWNER);
     }
 }
 
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index c23a1d9..26684de 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -16,15 +16,21 @@
 
 package com.android.server;
 
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.net.LinkCapabilities;
 import android.net.LinkProperties;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Message;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.telephony.CellLocation;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
@@ -35,15 +41,14 @@
 import android.util.Slog;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.net.NetworkInterface;
 
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.telephony.ITelephonyRegistry;
 import com.android.internal.telephony.IPhoneStateListener;
 import com.android.internal.telephony.DefaultPhoneNotifier;
-import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.TelephonyIntents;
@@ -56,6 +61,7 @@
 class TelephonyRegistry extends ITelephonyRegistry.Stub {
     private static final String TAG = "TelephonyRegistry";
     private static final boolean DBG = false;
+    private static final boolean DBG_LOC = false;
 
     private static class Record {
         String pkgForDebug;
@@ -64,7 +70,15 @@
 
         IPhoneStateListener callback;
 
+        int callerUid;
+
         int events;
+
+        @Override
+        public String toString() {
+            return "{pkgForDebug=" + pkgForDebug + " callerUid=" + callerUid +
+                    " events=" + Integer.toHexString(events) + "}";
+        }
     }
 
     private final Context mContext;
@@ -109,7 +123,7 @@
 
     private int mOtaspMode = ServiceStateTracker.OTASP_UNKNOWN;
 
-    private CellInfo mCellInfo = null;
+    private List<CellInfo> mCellInfo = null;
 
     static final int PHONE_STATE_PERMISSION_MASK =
                 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
@@ -118,6 +132,32 @@
                 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
                 PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR;
 
+    private static final int MSG_USER_SWITCHED = 1;
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_USER_SWITCHED: {
+                    Slog.d(TAG, "MSG_USER_SWITCHED userId=" + msg.arg1);
+                    TelephonyRegistry.this.notifyCellLocation(mCellLocation);
+                    break;
+                }
+            }
+        }
+    };
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED,
+                       intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
+            }
+        }
+    };
+
     // we keep a copy of all of the state so we can send it out when folks
     // register for it
     //
@@ -138,10 +178,24 @@
         mConnectedApns = new ArrayList<String>();
     }
 
+    public void systemReady() {
+        // Watch for interesting updates
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_USER_SWITCHED);
+        filter.addAction(Intent.ACTION_USER_REMOVED);
+        mContext.registerReceiver(mBroadcastReceiver, filter);
+    }
+
+    @Override
     public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
             boolean notifyNow) {
-        // Slog.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" +
-        // Integer.toHexString(events));
+        int callerUid = UserHandle.getCallingUserId();
+        int myUid = UserHandle.myUserId();
+        if (DBG) {
+            Slog.d(TAG, "listen: E pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events)
+                + " myUid=" + myUid
+                + " callerUid=" + callerUid);
+        }
         if (events != 0) {
             /* Checks permission and throws Security exception */
             checkListenerPermission(events);
@@ -162,7 +216,9 @@
                     r.binder = b;
                     r.callback = callback;
                     r.pkgForDebug = pkgForDebug;
+                    r.callerUid = callerUid;
                     mRecords.add(r);
+                    if (DBG) Slog.i(TAG, "listen: add new record=" + r);
                 }
                 int send = events & (events ^ r.events);
                 r.events = events;
@@ -197,8 +253,9 @@
                             remove(r.binder);
                         }
                     }
-                    if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
+                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
                         try {
+                            if (DBG_LOC) Slog.d(TAG, "listen: mCellLocation=" + mCellLocation);
                             r.callback.onCellLocationChanged(new Bundle(mCellLocation));
                         } catch (RemoteException ex) {
                             remove(r.binder);
@@ -240,9 +297,10 @@
                             remove(r.binder);
                         }
                     }
-                    if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
+                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
                         try {
-                            r.callback.onCellInfoChanged(new CellInfo(mCellInfo));
+                            if (DBG_LOC) Slog.d(TAG, "listen: mCellInfo=" + mCellInfo);
+                            r.callback.onCellInfoChanged(mCellInfo);
                         } catch (RemoteException ex) {
                             remove(r.binder);
                         }
@@ -336,7 +394,7 @@
         broadcastSignalStrengthChanged(signalStrength);
     }
 
-    public void notifyCellInfo(CellInfo cellInfo) {
+    public void notifyCellInfo(List<CellInfo> cellInfo) {
         if (!checkNotifyPermission("notifyCellInfo()")) {
             return;
         }
@@ -344,9 +402,12 @@
         synchronized (mRecords) {
             mCellInfo = cellInfo;
             for (Record r : mRecords) {
-                if ((r.events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
+                if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
                     try {
-                        r.callback.onCellInfoChanged(new CellInfo(cellInfo));
+                        if (DBG_LOC) {
+                            Slog.d(TAG, "notifyCellInfo: mCellInfo=" + mCellInfo + " r=" + r);
+                        }
+                        r.callback.onCellInfoChanged(cellInfo);
                     } catch (RemoteException ex) {
                         mRemoveList.add(r.binder);
                     }
@@ -422,7 +483,8 @@
         if (DBG) {
             Slog.i(TAG, "notifyDataConnection: state=" + state + " isDataConnectivityPossible="
                 + isDataConnectivityPossible + " reason='" + reason
-                + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType);
+                + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType
+                + " mRecords.size()=" + mRecords.size() + " mRecords=" + mRecords);
         }
         synchronized (mRecords) {
             boolean modified = false;
@@ -504,8 +566,12 @@
         synchronized (mRecords) {
             mCellLocation = cellLocation;
             for (Record r : mRecords) {
-                if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
+                if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
                     try {
+                        if (DBG_LOC) {
+                            Slog.d(TAG, "notifyCellLocation: mCellLocation=" + mCellLocation
+                                    + " r=" + r);
+                        }
                         r.callback.onCellLocationChanged(new Bundle(cellLocation));
                     } catch (RemoteException ex) {
                         mRemoveList.add(r.binder);
@@ -587,7 +653,7 @@
         Bundle data = new Bundle();
         state.fillInNotifierBundle(data);
         intent.putExtras(data);
-        mContext.sendStickyBroadcast(intent);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void broadcastSignalStrengthChanged(SignalStrength signalStrength) {
@@ -605,7 +671,7 @@
         Bundle data = new Bundle();
         signalStrength.fillInNotifierBundle(data);
         intent.putExtras(data);
-        mContext.sendStickyBroadcast(intent);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void broadcastCallStateChanged(int state, String incomingNumber) {
@@ -628,7 +694,8 @@
         if (!TextUtils.isEmpty(incomingNumber)) {
             intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
         }
-        mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+                android.Manifest.permission.READ_PHONE_STATE);
     }
 
     private void broadcastDataConnectionStateChanged(int state,
@@ -661,14 +728,14 @@
 
         intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
         intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
-        mContext.sendStickyBroadcast(intent);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void broadcastDataConnectionFailed(String reason, String apnType) {
         Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
         intent.putExtra(PhoneConstants.FAILURE_REASON_KEY, reason);
         intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
-        mContext.sendStickyBroadcast(intent);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private boolean checkNotifyPermission(String method) {
@@ -709,4 +776,22 @@
             mRemoveList.clear();
         }
     }
+
+    private boolean validateEventsAndUserLocked(Record r, int events) {
+        int foregroundUser;
+        long callingIdentity = Binder.clearCallingIdentity();
+        boolean valid = false;
+        try {
+            foregroundUser = ActivityManager.getCurrentUser();
+            valid = r.callerUid ==  foregroundUser && (r.events & events) != 0;
+            if (DBG | DBG_LOC) {
+                Slog.d(TAG, "validateEventsAndUserLocked: valid=" + valid
+                        + " r.callerUid=" + r.callerUid + " foregroundUser=" + foregroundUser
+                        + " r.events=" + r.events + " events=" + events);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingIdentity);
+        }
+        return valid;
+    }
 }
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index c74dd00..d0d8428 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -25,17 +25,25 @@
 
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
+import android.app.IUserSwitchObserver;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.IRemoteCallback;
+import android.os.Process;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.textservice.SpellCheckerService;
 import android.text.TextUtils;
@@ -66,6 +74,7 @@
     private final ArrayList<SpellCheckerInfo> mSpellCheckerList = new ArrayList<SpellCheckerInfo>();
     private final HashMap<String, SpellCheckerBindGroup> mSpellCheckerBindGroups =
             new HashMap<String, SpellCheckerBindGroup>();
+    private final TextServicesSettings mSettings;
 
     public void systemReady() {
         if (!mSystemReady) {
@@ -76,11 +85,43 @@
     public TextServicesManagerService(Context context) {
         mSystemReady = false;
         mContext = context;
+        int userId = UserHandle.USER_OWNER;
+        try {
+            ActivityManagerNative.getDefault().registerUserSwitchObserver(
+                    new IUserSwitchObserver.Stub() {
+                        @Override
+                        public void onUserSwitching(int newUserId, IRemoteCallback reply) {
+                            synchronized(mSpellCheckerMap) {
+                                switchUserLocked(newUserId);
+                            }
+                            if (reply != null) {
+                                try {
+                                    reply.sendResult(null);
+                                } catch (RemoteException e) {
+                                }
+                            }
+                        }
+
+                        @Override
+                        public void onUserSwitchComplete(int newUserId) throws RemoteException {
+                        }
+                    });
+            userId = ActivityManagerNative.getDefault().getCurrentUser().id;
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
+        }
         mMonitor = new TextServicesMonitor();
         mMonitor.register(context, null, true);
-        synchronized (mSpellCheckerMap) {
-            buildSpellCheckerMapLocked(context, mSpellCheckerList, mSpellCheckerMap);
-        }
+        mSettings = new TextServicesSettings(context.getContentResolver(), userId);
+
+        // "switchUserLocked" initializes the states for the foreground user
+        switchUserLocked(userId);
+    }
+
+    private void switchUserLocked(int userId) {
+        mSettings.setCurrentUserId(userId);
+        unbindServiceLocked();
+        buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap, mSettings);
         SpellCheckerInfo sci = getCurrentSpellChecker(null);
         if (sci == null) {
             sci = findAvailSpellCheckerLocked(null, null);
@@ -94,10 +135,23 @@
     }
 
     private class TextServicesMonitor extends PackageMonitor {
+        private boolean isChangingPackagesOfCurrentUser() {
+            final int userId = getChangingUserId();
+            final boolean retval = userId == mSettings.getCurrentUserId();
+            if (DBG) {
+                Slog.d(TAG, "--- ignore this call back from a background user: " + userId);
+            }
+            return retval;
+        }
+
         @Override
         public void onSomePackagesChanged() {
+            if (!isChangingPackagesOfCurrentUser()) {
+                return;
+            }
             synchronized (mSpellCheckerMap) {
-                buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap);
+                buildSpellCheckerMapLocked(
+                        mContext, mSpellCheckerList, mSpellCheckerMap, mSettings);
                 // TODO: Update for each locale
                 SpellCheckerInfo sci = getCurrentSpellChecker(null);
                 if (sci == null) return;
@@ -117,12 +171,14 @@
     }
 
     private static void buildSpellCheckerMapLocked(Context context,
-            ArrayList<SpellCheckerInfo> list, HashMap<String, SpellCheckerInfo> map) {
+            ArrayList<SpellCheckerInfo> list, HashMap<String, SpellCheckerInfo> map,
+            TextServicesSettings settings) {
         list.clear();
         map.clear();
         final PackageManager pm = context.getPackageManager();
-        List<ResolveInfo> services = pm.queryIntentServices(
-                new Intent(SpellCheckerService.SERVICE_INTERFACE), PackageManager.GET_META_DATA);
+        final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
+                new Intent(SpellCheckerService.SERVICE_INTERFACE), PackageManager.GET_META_DATA,
+                settings.getCurrentUserId());
         final int N = services.size();
         for (int i = 0; i < N; ++i) {
             final ResolveInfo ri = services.get(i);
@@ -155,6 +211,53 @@
         }
     }
 
+    // ---------------------------------------------------------------------------------------
+    // Check whether or not this is a valid IPC. Assumes an IPC is valid when either
+    // 1) it comes from the system process
+    // 2) the calling process' user id is identical to the current user id TSMS thinks.
+    private boolean calledFromValidUser() {
+        final int uid = Binder.getCallingUid();
+        final int userId = UserHandle.getUserId(uid);
+        if (DBG) {
+            Slog.d(TAG, "--- calledFromForegroundUserOrSystemProcess ? "
+                    + "calling uid = " + uid + " system uid = " + Process.SYSTEM_UID
+                    + " calling userId = " + userId + ", foreground user id = "
+                    + mSettings.getCurrentUserId());
+            try {
+                final String[] packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid);
+                for (int i = 0; i < packageNames.length; ++i) {
+                    if (DBG) {
+                        Slog.d(TAG, "--- process name for "+ uid + " = " + packageNames[i]);
+                    }
+                }
+            } catch (RemoteException e) {
+            }
+        }
+
+        if (uid == Process.SYSTEM_UID || userId == mSettings.getCurrentUserId()) {
+            return true;
+        } else {
+            Slog.w(TAG, "--- IPC called from background users. Ignore. \n" + getStackTrace());
+            return false;
+        }
+    }
+
+    private boolean bindCurrentSpellCheckerService(
+            Intent service, ServiceConnection conn, int flags) {
+        if (service == null || conn == null) {
+            Slog.e(TAG, "--- bind failed: service = " + service + ", conn = " + conn);
+            return false;
+        }
+        return mContext.bindService(service, conn, flags, mSettings.getCurrentUserId());
+    }
+
+    private void unbindServiceLocked() {
+        for (SpellCheckerBindGroup scbg : mSpellCheckerBindGroups.values()) {
+            scbg.removeAll();
+        }
+        mSpellCheckerBindGroups.clear();
+    }
+
     // TODO: find an appropriate spell checker for specified locale
     private SpellCheckerInfo findAvailSpellCheckerLocked(String locale, String prefPackage) {
         final int spellCheckersCount = mSpellCheckerList.size();
@@ -183,10 +286,12 @@
     // checker is saved.
     @Override
     public SpellCheckerInfo getCurrentSpellChecker(String locale) {
+        // TODO: Make this work even for non-current users?
+        if (!calledFromValidUser()) {
+            return null;
+        }
         synchronized (mSpellCheckerMap) {
-            final String curSpellCheckerId =
-                    Settings.Secure.getString(mContext.getContentResolver(),
-                            Settings.Secure.SELECTED_SPELL_CHECKER);
+            final String curSpellCheckerId = mSettings.getSelectedSpellChecker();
             if (DBG) {
                 Slog.w(TAG, "getCurrentSpellChecker: " + curSpellCheckerId);
             }
@@ -202,10 +307,12 @@
     @Override
     public SpellCheckerSubtype getCurrentSpellCheckerSubtype(
             String locale, boolean allowImplicitlySelectedSubtype) {
+        // TODO: Make this work even for non-current users?
+        if (!calledFromValidUser()) {
+            return null;
+        }
         synchronized (mSpellCheckerMap) {
-            final String subtypeHashCodeStr =
-                    Settings.Secure.getString(mContext.getContentResolver(),
-                            Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE);
+            final String subtypeHashCodeStr = mSettings.getSelectedSpellCheckerSubtype();
             if (DBG) {
                 Slog.w(TAG, "getCurrentSpellCheckerSubtype: " + subtypeHashCodeStr);
             }
@@ -280,6 +387,9 @@
     public void getSpellCheckerService(String sciId, String locale,
             ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener,
             Bundle bundle) {
+        if (!calledFromValidUser()) {
+            return;
+        }
         if (!mSystemReady) {
             return;
         }
@@ -346,6 +456,9 @@
 
     @Override
     public boolean isSpellCheckerEnabled() {
+        if (!calledFromValidUser()) {
+            return false;
+        }
         synchronized(mSpellCheckerMap) {
             return isSpellCheckerEnabledLocked();
         }
@@ -365,7 +478,7 @@
         if (DBG) {
             Slog.w(TAG, "bind service: " + info.getId());
         }
-        if (!mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) {
+        if (!bindCurrentSpellCheckerService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) {
             Slog.e(TAG, "Failed to get a spell checker service.");
             return;
         }
@@ -376,6 +489,10 @@
 
     @Override
     public SpellCheckerInfo[] getEnabledSpellCheckers() {
+        // TODO: Make this work even for non-current users?
+        if (!calledFromValidUser()) {
+            return null;
+        }
         if (DBG) {
             Slog.d(TAG, "getEnabledSpellCheckers: " + mSpellCheckerList.size());
             for (int i = 0; i < mSpellCheckerList.size(); ++i) {
@@ -387,6 +504,9 @@
 
     @Override
     public void finishSpellCheckerService(ISpellCheckerSessionListener listener) {
+        if (!calledFromValidUser()) {
+            return;
+        }
         if (DBG) {
             Slog.d(TAG, "FinishSpellCheckerService");
         }
@@ -407,6 +527,9 @@
 
     @Override
     public void setCurrentSpellChecker(String locale, String sciId) {
+        if (!calledFromValidUser()) {
+            return;
+        }
         synchronized(mSpellCheckerMap) {
             if (mContext.checkCallingOrSelfPermission(
                     android.Manifest.permission.WRITE_SECURE_SETTINGS)
@@ -421,6 +544,9 @@
 
     @Override
     public void setCurrentSpellCheckerSubtype(String locale, int hashCode) {
+        if (!calledFromValidUser()) {
+            return;
+        }
         synchronized(mSpellCheckerMap) {
             if (mContext.checkCallingOrSelfPermission(
                     android.Manifest.permission.WRITE_SECURE_SETTINGS)
@@ -435,6 +561,9 @@
 
     @Override
     public void setSpellCheckerEnabled(boolean enabled) {
+        if (!calledFromValidUser()) {
+            return;
+        }
         synchronized(mSpellCheckerMap) {
             if (mContext.checkCallingOrSelfPermission(
                     android.Manifest.permission.WRITE_SECURE_SETTINGS)
@@ -459,8 +588,7 @@
         }
         final long ident = Binder.clearCallingIdentity();
         try {
-            Settings.Secure.putString(mContext.getContentResolver(),
-                    Settings.Secure.SELECTED_SPELL_CHECKER, sciId);
+            mSettings.putSelectedSpellChecker(sciId);
             setCurrentSpellCheckerSubtypeLocked(0);
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -481,8 +609,7 @@
         }
         final long ident = Binder.clearCallingIdentity();
         try {
-            Settings.Secure.putString(mContext.getContentResolver(),
-                    Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(tempHashCode));
+            mSettings.putSelectedSpellCheckerSubtype(tempHashCode);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -494,8 +621,7 @@
         }
         final long ident = Binder.clearCallingIdentity();
         try {
-            Settings.Secure.putInt(mContext.getContentResolver(),
-                    Settings.Secure.SPELL_CHECKER_ENABLED, enabled ? 1 : 0);
+            mSettings.setSpellCheckerEnabled(enabled);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -504,8 +630,7 @@
     private boolean isSpellCheckerEnabledLocked() {
         final long ident = Binder.clearCallingIdentity();
         try {
-            final boolean retval = Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.SPELL_CHECKER_ENABLED, 1) == 1;
+            final boolean retval = mSettings.isSpellCheckerEnabled();
             if (DBG) {
                 Slog.w(TAG, "getSpellCheckerEnabled: " + retval);
             }
@@ -729,14 +854,19 @@
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
             synchronized(mSpellCheckerMap) {
-                if (DBG) {
-                    Slog.w(TAG, "onServiceConnected: " + name);
-                }
-                ISpellCheckerService spellChecker = ISpellCheckerService.Stub.asInterface(service);
-                final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId);
-                if (group != null && this == group.mInternalConnection) {
-                    group.onServiceConnected(spellChecker);
-                }
+                onServiceConnectedInnerLocked(name, service);
+            }
+        }
+
+        private void onServiceConnectedInnerLocked(ComponentName name, IBinder service) {
+            if (DBG) {
+                Slog.w(TAG, "onServiceConnected: " + name);
+            }
+            final ISpellCheckerService spellChecker =
+                    ISpellCheckerService.Stub.asInterface(service);
+            final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId);
+            if (group != null && this == group.mInternalConnection) {
+                group.onServiceConnected(spellChecker);
             }
         }
 
@@ -778,4 +908,73 @@
             mGroup.removeListener(mScListener);
         }
     }
+
+    private static class TextServicesSettings {
+        private final ContentResolver mResolver;
+        private int mCurrentUserId;
+        public TextServicesSettings(ContentResolver resolver, int userId) {
+            mResolver = resolver;
+            mCurrentUserId = userId;
+        }
+
+        public void setCurrentUserId(int userId) {
+            if (DBG) {
+                Slog.d(TAG, "--- Swtich the current user from " + mCurrentUserId + " to "
+                        + userId + ", new ime = " + getSelectedSpellChecker());
+            }
+            // TSMS settings are kept per user, so keep track of current user
+            mCurrentUserId = userId;
+        }
+
+        public int getCurrentUserId() {
+            return mCurrentUserId;
+        }
+
+        public void putSelectedSpellChecker(String sciId) {
+            Settings.Secure.putStringForUser(mResolver,
+                    Settings.Secure.SELECTED_SPELL_CHECKER, sciId, mCurrentUserId);
+        }
+
+        public void putSelectedSpellCheckerSubtype(int hashCode) {
+            Settings.Secure.putStringForUser(mResolver,
+                    Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(hashCode),
+                    mCurrentUserId);
+        }
+
+        public void setSpellCheckerEnabled(boolean enabled) {
+            Settings.Secure.putIntForUser(mResolver,
+                    Settings.Secure.SPELL_CHECKER_ENABLED, enabled ? 1 : 0, mCurrentUserId);
+        }
+
+        public String getSelectedSpellChecker() {
+            return Settings.Secure.getStringForUser(mResolver,
+                    Settings.Secure.SELECTED_SPELL_CHECKER, mCurrentUserId);
+        }
+
+        public String getSelectedSpellCheckerSubtype() {
+            return Settings.Secure.getStringForUser(mResolver,
+                    Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, mCurrentUserId);
+        }
+
+        public boolean isSpellCheckerEnabled() {
+            return Settings.Secure.getIntForUser(mResolver,
+                    Settings.Secure.SPELL_CHECKER_ENABLED, 1, mCurrentUserId) == 1;
+        }
+    }
+
+    // ----------------------------------------------------------------------
+    // Utilities for debug
+    private static String getStackTrace() {
+        final StringBuilder sb = new StringBuilder();
+        try {
+            throw new RuntimeException();
+        } catch (RuntimeException e) {
+            final StackTraceElement[] frames = e.getStackTrace();
+            // Start at 1 because the first frame is here and we don't care about it
+            for (int j = 1; j < frames.length; ++j) {
+                sb.append(frames[j].toString() + "\n");
+            }
+        }
+        return sb.toString();
+    }
 }
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index f35a5af..75eb3c4 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -44,6 +44,7 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -195,6 +196,7 @@
 
         public void interfaceRemoved(String iface) {}
         public void limitReached(String limitName, String iface) {}
+        public void interfaceClassDataActivityChanged(String label, boolean active) {}
     }
 
 
@@ -209,20 +211,20 @@
 
         void register(Context context) {
             ContentResolver resolver = context.getContentResolver();
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.THROTTLE_POLLING_SEC), false, this);
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.THROTTLE_THRESHOLD_BYTES), false, this);
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.THROTTLE_VALUE_KBITSPS), false, this);
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.THROTTLE_RESET_DAY), false, this);
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.THROTTLE_NOTIFICATION_TYPE), false, this);
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.THROTTLE_HELP_URI), false, this);
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.THROTTLE_MAX_NTP_CACHE_AGE_SEC), false, this);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.THROTTLE_POLLING_SEC), false, this);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.THROTTLE_THRESHOLD_BYTES), false, this);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.THROTTLE_VALUE_KBITSPS), false, this);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.THROTTLE_RESET_DAY), false, this);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.THROTTLE_NOTIFICATION_TYPE), false, this);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.THROTTLE_HELP_URI), false, this);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.THROTTLE_MAX_NTP_CACHE_AGE_SEC), false, this);
         }
 
         void unregister(Context context) {
@@ -295,8 +297,8 @@
 
     public String getHelpUri() {
         enforceAccessPermission();
-        return Settings.Secure.getString(mContext.getContentResolver(),
-                    Settings.Secure.THROTTLE_HELP_URI);
+        return Settings.Global.getString(mContext.getContentResolver(),
+                    Settings.Global.THROTTLE_HELP_URI);
     }
 
     // TODO - fetch for the iface
@@ -367,7 +369,7 @@
         }
 
         if (mPollStickyBroadcast != null) {
-            mContext.removeStickyBroadcast(mPollStickyBroadcast);
+            mContext.removeStickyBroadcastAsUser(mPollStickyBroadcast, UserHandle.ALL);
         }
     }
 
@@ -434,18 +436,18 @@
 
             int pollingPeriod = mContext.getResources().getInteger(
                     R.integer.config_datause_polling_period_sec);
-            mPolicyPollPeriodSec = Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.THROTTLE_POLLING_SEC, pollingPeriod);
+            mPolicyPollPeriodSec = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.THROTTLE_POLLING_SEC, pollingPeriod);
 
             // TODO - remove testing stuff?
             long defaultThreshold = mContext.getResources().getInteger(
                     R.integer.config_datause_threshold_bytes);
             int defaultValue = mContext.getResources().getInteger(
                     R.integer.config_datause_throttle_kbitsps);
-            long threshold = Settings.Secure.getLong(mContext.getContentResolver(),
-                    Settings.Secure.THROTTLE_THRESHOLD_BYTES, defaultThreshold);
-            int value = Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.THROTTLE_VALUE_KBITSPS, defaultValue);
+            long threshold = Settings.Global.getLong(mContext.getContentResolver(),
+                    Settings.Global.THROTTLE_THRESHOLD_BYTES, defaultThreshold);
+            int value = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.THROTTLE_VALUE_KBITSPS, defaultValue);
 
             mPolicyThreshold.set(threshold);
             mPolicyThrottleValue.set(value);
@@ -454,14 +456,14 @@
                 mPolicyThreshold.set(TESTING_THRESHOLD);
             }
 
-            mPolicyResetDay = Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.THROTTLE_RESET_DAY, -1);
+            mPolicyResetDay = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.THROTTLE_RESET_DAY, -1);
             if (mPolicyResetDay == -1 ||
                     ((mPolicyResetDay < 1) || (mPolicyResetDay > 28))) {
                 Random g = new Random();
                 mPolicyResetDay = 1 + g.nextInt(28); // 1-28
-                Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.THROTTLE_RESET_DAY, mPolicyResetDay);
+                Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.THROTTLE_RESET_DAY, mPolicyResetDay);
             }
             if (mIface == null) {
                 mPolicyThreshold.set(0);
@@ -469,11 +471,11 @@
 
             int defaultNotificationType = mContext.getResources().getInteger(
                     R.integer.config_datause_notification_type);
-            mPolicyNotificationsAllowedMask = Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.THROTTLE_NOTIFICATION_TYPE, defaultNotificationType);
+            mPolicyNotificationsAllowedMask = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.THROTTLE_NOTIFICATION_TYPE, defaultNotificationType);
 
-            final int maxNtpCacheAgeSec = Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.THROTTLE_MAX_NTP_CACHE_AGE_SEC,
+            final int maxNtpCacheAgeSec = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.THROTTLE_MAX_NTP_CACHE_AGE_SEC,
                     (int) (MAX_NTP_CACHE_AGE / 1000));
             mMaxNtpCacheAge = maxNtpCacheAgeSec * 1000;
 
@@ -493,7 +495,7 @@
             onPollAlarm();
 
             Intent broadcast = new Intent(ThrottleManager.POLICY_CHANGED_ACTION);
-            mContext.sendBroadcast(broadcast);
+            mContext.sendBroadcastAsUser(broadcast, UserHandle.ALL);
         }
 
         private void onPollAlarm() {
@@ -562,7 +564,7 @@
             broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_WRITE, periodTx);
             broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_START, getPeriodStartTime(mIface));
             broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_END, getResetTime(mIface));
-            mContext.sendStickyBroadcast(broadcast);
+            mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
             mPollStickyBroadcast = broadcast;
 
             mAlarmManager.cancel(mPendingPollIntent);
@@ -620,7 +622,7 @@
                     Intent broadcast = new Intent(ThrottleManager.THROTTLE_ACTION);
                     broadcast.putExtra(ThrottleManager.EXTRA_THROTTLE_LEVEL,
                             mPolicyThrottleValue.get());
-                    mContext.sendStickyBroadcast(broadcast);
+                    mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
 
                 } // else already up!
             } else {
@@ -668,7 +670,8 @@
             intent.setClassName("com.android.phone", "com.android.phone.DataUsage");
             intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
 
-            PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
+            PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0,
+                    null, UserHandle.CURRENT);
 
             Resources r = Resources.getSystem();
             CharSequence title = r.getText(titleInt);
@@ -684,7 +687,8 @@
             mThrottlingNotification.tickerText = title;
             mThrottlingNotification.setLatestEventInfo(mContext, title, message, pi);
 
-            mNotificationManager.notify(mThrottlingNotification.icon, mThrottlingNotification);
+            mNotificationManager.notifyAsUser(null, mThrottlingNotification.icon,
+                    mThrottlingNotification, UserHandle.ALL);
         }
 
 
@@ -698,8 +702,9 @@
                 }
                 Intent broadcast = new Intent(ThrottleManager.THROTTLE_ACTION);
                 broadcast.putExtra(ThrottleManager.EXTRA_THROTTLE_LEVEL, -1);
-                mContext.sendStickyBroadcast(broadcast);
-                mNotificationManager.cancel(R.drawable.stat_sys_throttled);
+                mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
+                mNotificationManager.cancelAsUser(null, R.drawable.stat_sys_throttled,
+                        UserHandle.ALL);
                 mWarningNotificationSent = false;
             }
         }
diff --git a/services/java/com/android/server/TwilightService.java b/services/java/com/android/server/TwilightService.java
new file mode 100644
index 0000000..154de1c
--- /dev/null
+++ b/services/java/com/android/server/TwilightService.java
@@ -0,0 +1,572 @@
+/*
+ * 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;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.location.Criteria;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+import android.text.format.DateUtils;
+import android.text.format.Time;
+import android.util.Slog;
+
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+
+import libcore.util.Objects;
+
+/**
+ * Figures out whether it's twilight time based on the user's location.
+ *
+ * Used by the UI mode manager and other components to adjust night mode
+ * effects based on sunrise and sunset.
+ */
+public final class TwilightService {
+    private static final String TAG = "TwilightService";
+
+    private static final boolean DEBUG = false;
+
+    private static final String ACTION_UPDATE_TWILIGHT_STATE =
+            "com.android.server.action.UPDATE_TWILIGHT_STATE";
+
+    private final Context mContext;
+    private final AlarmManager mAlarmManager;
+    private final LocationManager mLocationManager;
+    private final LocationHandler mLocationHandler;
+
+    private final Object mLock = new Object();
+
+    private final ArrayList<TwilightListenerRecord> mListeners =
+            new ArrayList<TwilightListenerRecord>();
+
+    private boolean mSystemReady;
+
+    private TwilightState mTwilightState;
+
+    public TwilightService(Context context) {
+        mContext = context;
+
+        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
+        mLocationManager = (LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE);
+        mLocationHandler = new LocationHandler();
+    }
+
+    void systemReady() {
+        synchronized (mLock) {
+            mSystemReady = true;
+
+            IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+            filter.addAction(Intent.ACTION_TIME_CHANGED);
+            filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+            filter.addAction(ACTION_UPDATE_TWILIGHT_STATE);
+            mContext.registerReceiver(mUpdateLocationReceiver, filter);
+
+            if (!mListeners.isEmpty()) {
+                mLocationHandler.enableLocationUpdates();
+            }
+        }
+    }
+
+    /**
+     * Gets the current twilight state.
+     *
+     * @return The current twilight state, or null if no information is available.
+     */
+    public TwilightState getCurrentState() {
+        synchronized (mLock) {
+            return mTwilightState;
+        }
+    }
+
+    /**
+     * Listens for twilight time.
+     *
+     * @param listener The listener.
+     * @param handler The handler on which to post calls into the listener.
+     */
+    public void registerListener(TwilightListener listener, Handler handler) {
+        synchronized (mLock) {
+            mListeners.add(new TwilightListenerRecord(listener, handler));
+
+            if (mSystemReady && mListeners.size() == 1) {
+                mLocationHandler.enableLocationUpdates();
+            }
+        }
+    }
+
+    private void setTwilightState(TwilightState state) {
+        synchronized (mLock) {
+            if (!Objects.equal(mTwilightState, state)) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Twilight state changed: " + state);
+                }
+
+                mTwilightState = state;
+                int count = mListeners.size();
+                for (int i = 0; i < count; i++) {
+                    mListeners.get(i).post();
+                }
+            }
+        }
+    }
+
+    // The user has moved if the accuracy circles of the two locations don't overlap.
+    private static boolean hasMoved(Location from, Location to) {
+        if (to == null) {
+            return false;
+        }
+
+        if (from == null) {
+            return true;
+        }
+
+        // if new location is older than the current one, the device hasn't moved.
+        if (to.getElapsedRealtimeNanos() < from.getElapsedRealtimeNanos()) {
+            return false;
+        }
+
+        // Get the distance between the two points.
+        float distance = from.distanceTo(to);
+
+        // Get the total accuracy radius for both locations.
+        float totalAccuracy = from.getAccuracy() + to.getAccuracy();
+
+        // If the distance is greater than the combined accuracy of the two
+        // points then they can't overlap and hence the user has moved.
+        return distance >= totalAccuracy;
+    }
+
+    /**
+     * Describes whether it is day or night.
+     * This object is immutable.
+     */
+    public static final class TwilightState {
+        private final boolean mIsNight;
+        private final long mYesterdaySunset;
+        private final long mTodaySunrise;
+        private final long mTodaySunset;
+        private final long mTomorrowSunrise;
+
+        TwilightState(boolean isNight,
+                long yesterdaySunset,
+                long todaySunrise, long todaySunset,
+                long tomorrowSunrise) {
+            mIsNight = isNight;
+            mYesterdaySunset = yesterdaySunset;
+            mTodaySunrise = todaySunrise;
+            mTodaySunset = todaySunset;
+            mTomorrowSunrise = tomorrowSunrise;
+        }
+
+        /**
+         * Returns true if it is currently night time.
+         */
+        public boolean isNight() {
+            return mIsNight;
+        }
+
+        /**
+         * Returns the time of yesterday's sunset in the System.currentTimeMillis() timebase,
+         * or -1 if the sun never sets.
+         */
+        public long getYesterdaySunset() {
+            return mYesterdaySunset;
+        }
+
+        /**
+         * Returns the time of today's sunrise in the System.currentTimeMillis() timebase,
+         * or -1 if the sun never rises.
+         */
+        public long getTodaySunrise() {
+            return mTodaySunrise;
+        }
+
+        /**
+         * Returns the time of today's sunset in the System.currentTimeMillis() timebase,
+         * or -1 if the sun never sets.
+         */
+        public long getTodaySunset() {
+            return mTodaySunset;
+        }
+
+        /**
+         * Returns the time of tomorrow's sunrise in the System.currentTimeMillis() timebase,
+         * or -1 if the sun never rises.
+         */
+        public long getTomorrowSunrise() {
+            return mTomorrowSunrise;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            return o instanceof TwilightState && equals((TwilightState)o);
+        }
+
+        public boolean equals(TwilightState other) {
+            return other != null
+                    && mIsNight == other.mIsNight
+                    && mYesterdaySunset == other.mYesterdaySunset
+                    && mTodaySunrise == other.mTodaySunrise
+                    && mTodaySunset == other.mTodaySunset
+                    && mTomorrowSunrise == other.mTomorrowSunrise;
+        }
+
+        @Override
+        public int hashCode() {
+            return 0; // don't care
+        }
+
+        @Override
+        public String toString() {
+            DateFormat f = DateFormat.getDateTimeInstance();
+            return "{TwilightState: isNight=" + mIsNight
+                    + ", mYesterdaySunset=" + f.format(new Date(mYesterdaySunset))
+                    + ", mTodaySunrise=" + f.format(new Date(mTodaySunrise))
+                    + ", mTodaySunset=" + f.format(new Date(mTodaySunset))
+                    + ", mTomorrowSunrise=" + f.format(new Date(mTomorrowSunrise))
+                    + "}";
+        }
+    }
+
+    /**
+     * Listener for changes in twilight state.
+     */
+    public interface TwilightListener {
+        public void onTwilightStateChanged();
+    }
+
+    private static final class TwilightListenerRecord implements Runnable {
+        private final TwilightListener mListener;
+        private final Handler mHandler;
+
+        public TwilightListenerRecord(TwilightListener listener, Handler handler) {
+            mListener = listener;
+            mHandler = handler;
+        }
+
+        public void post() {
+            mHandler.post(this);
+        }
+
+        @Override
+        public void run() {
+            mListener.onTwilightStateChanged();
+        }
+    }
+
+    private final class LocationHandler extends Handler {
+        private static final int MSG_ENABLE_LOCATION_UPDATES = 1;
+        private static final int MSG_GET_NEW_LOCATION_UPDATE = 2;
+        private static final int MSG_PROCESS_NEW_LOCATION = 3;
+        private static final int MSG_DO_TWILIGHT_UPDATE = 4;
+
+        private static final long LOCATION_UPDATE_MS = 24 * DateUtils.HOUR_IN_MILLIS;
+        private static final long MIN_LOCATION_UPDATE_MS = 30 * DateUtils.MINUTE_IN_MILLIS;
+        private static final float LOCATION_UPDATE_DISTANCE_METER = 1000 * 20;
+        private static final long LOCATION_UPDATE_ENABLE_INTERVAL_MIN = 5000;
+        private static final long LOCATION_UPDATE_ENABLE_INTERVAL_MAX =
+                15 * DateUtils.MINUTE_IN_MILLIS;
+        private static final double FACTOR_GMT_OFFSET_LONGITUDE =
+                1000.0 * 360.0 / DateUtils.DAY_IN_MILLIS;
+
+        private boolean mPassiveListenerEnabled;
+        private boolean mNetworkListenerEnabled;
+        private boolean mDidFirstInit;
+        private long mLastNetworkRegisterTime = -MIN_LOCATION_UPDATE_MS;
+        private long mLastUpdateInterval;
+        private Location mLocation;
+        private final TwilightCalculator mTwilightCalculator = new TwilightCalculator();
+
+        public void processNewLocation(Location location) {
+            Message msg = obtainMessage(MSG_PROCESS_NEW_LOCATION, location);
+            sendMessage(msg);
+        }
+
+        public void enableLocationUpdates() {
+            sendEmptyMessage(MSG_ENABLE_LOCATION_UPDATES);
+        }
+
+        public void requestLocationUpdate() {
+            sendEmptyMessage(MSG_GET_NEW_LOCATION_UPDATE);
+        }
+
+        public void requestTwilightUpdate() {
+            sendEmptyMessage(MSG_DO_TWILIGHT_UPDATE);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_PROCESS_NEW_LOCATION: {
+                    final Location location = (Location)msg.obj;
+                    final boolean hasMoved = hasMoved(mLocation, location);
+                    final boolean hasBetterAccuracy = mLocation == null
+                            || location.getAccuracy() < mLocation.getAccuracy();
+                    if (DEBUG) {
+                        Slog.d(TAG, "Processing new location: " + location
+                               + ", hasMoved=" + hasMoved
+                               + ", hasBetterAccuracy=" + hasBetterAccuracy);
+                    }
+                    if (hasMoved || hasBetterAccuracy) {
+                        setLocation(location);
+                    }
+                    break;
+                }
+
+                case MSG_GET_NEW_LOCATION_UPDATE:
+                    if (!mNetworkListenerEnabled) {
+                        // Don't do anything -- we are still trying to get a
+                        // location.
+                        return;
+                    }
+                    if ((mLastNetworkRegisterTime + MIN_LOCATION_UPDATE_MS) >=
+                            SystemClock.elapsedRealtime()) {
+                        // Don't do anything -- it hasn't been long enough
+                        // since we last requested an update.
+                        return;
+                    }
+
+                    // Unregister the current location monitor, so we can
+                    // register a new one for it to get an immediate update.
+                    mNetworkListenerEnabled = false;
+                    mLocationManager.removeUpdates(mEmptyLocationListener);
+
+                    // Fall through to re-register listener.
+                case MSG_ENABLE_LOCATION_UPDATES:
+                    // enable network provider to receive at least location updates for a given
+                    // distance.
+                    boolean networkLocationEnabled;
+                    try {
+                        networkLocationEnabled =
+                            mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
+                    } catch (Exception e) {
+                        // we may get IllegalArgumentException if network location provider
+                        // does not exist or is not yet installed.
+                        networkLocationEnabled = false;
+                    }
+                    if (!mNetworkListenerEnabled && networkLocationEnabled) {
+                        mNetworkListenerEnabled = true;
+                        mLastNetworkRegisterTime = SystemClock.elapsedRealtime();
+                        mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
+                                LOCATION_UPDATE_MS, 0, mEmptyLocationListener);
+
+                        if (!mDidFirstInit) {
+                            mDidFirstInit = true;
+                            if (mLocation == null) {
+                                retrieveLocation();
+                            }
+                        }
+                    }
+
+                    // enable passive provider to receive updates from location fixes (gps
+                    // and network).
+                    boolean passiveLocationEnabled;
+                    try {
+                        passiveLocationEnabled =
+                            mLocationManager.isProviderEnabled(LocationManager.PASSIVE_PROVIDER);
+                    } catch (Exception e) {
+                        // we may get IllegalArgumentException if passive location provider
+                        // does not exist or is not yet installed.
+                        passiveLocationEnabled = false;
+                    }
+
+                    if (!mPassiveListenerEnabled && passiveLocationEnabled) {
+                        mPassiveListenerEnabled = true;
+                        mLocationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER,
+                                0, LOCATION_UPDATE_DISTANCE_METER , mLocationListener);
+                    }
+
+                    if (!(mNetworkListenerEnabled && mPassiveListenerEnabled)) {
+                        mLastUpdateInterval *= 1.5;
+                        if (mLastUpdateInterval == 0) {
+                            mLastUpdateInterval = LOCATION_UPDATE_ENABLE_INTERVAL_MIN;
+                        } else if (mLastUpdateInterval > LOCATION_UPDATE_ENABLE_INTERVAL_MAX) {
+                            mLastUpdateInterval = LOCATION_UPDATE_ENABLE_INTERVAL_MAX;
+                        }
+                        sendEmptyMessageDelayed(MSG_ENABLE_LOCATION_UPDATES, mLastUpdateInterval);
+                    }
+                    break;
+
+                case MSG_DO_TWILIGHT_UPDATE:
+                    updateTwilightState();
+                    break;
+            }
+        }
+
+        private void retrieveLocation() {
+            Location location = null;
+            final Iterator<String> providers =
+                    mLocationManager.getProviders(new Criteria(), true).iterator();
+            while (providers.hasNext()) {
+                final Location lastKnownLocation =
+                        mLocationManager.getLastKnownLocation(providers.next());
+                // pick the most recent location
+                if (location == null || (lastKnownLocation != null &&
+                        location.getElapsedRealtimeNanos() <
+                        lastKnownLocation.getElapsedRealtimeNanos())) {
+                    location = lastKnownLocation;
+                }
+            }
+
+            // In the case there is no location available (e.g. GPS fix or network location
+            // is not available yet), the longitude of the location is estimated using the timezone,
+            // latitude and accuracy are set to get a good average.
+            if (location == null) {
+                Time currentTime = new Time();
+                currentTime.set(System.currentTimeMillis());
+                double lngOffset = FACTOR_GMT_OFFSET_LONGITUDE *
+                        (currentTime.gmtoff - (currentTime.isDst > 0 ? 3600 : 0));
+                location = new Location("fake");
+                location.setLongitude(lngOffset);
+                location.setLatitude(0);
+                location.setAccuracy(417000.0f);
+                location.setTime(System.currentTimeMillis());
+                location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
+
+                if (DEBUG) {
+                    Slog.d(TAG, "Estimated location from timezone: " + location);
+                }
+            }
+
+            setLocation(location);
+        }
+
+        private void setLocation(Location location) {
+            mLocation = location;
+            updateTwilightState();
+        }
+
+        private void updateTwilightState() {
+            if (mLocation == null) {
+                setTwilightState(null);
+                return;
+            }
+
+            final long now = System.currentTimeMillis();
+
+            // calculate yesterday's twilight
+            mTwilightCalculator.calculateTwilight(now - DateUtils.DAY_IN_MILLIS,
+                    mLocation.getLatitude(), mLocation.getLongitude());
+            final long yesterdaySunset = mTwilightCalculator.mSunset;
+
+            // calculate today's twilight
+            mTwilightCalculator.calculateTwilight(now,
+                    mLocation.getLatitude(), mLocation.getLongitude());
+            final boolean isNight = (mTwilightCalculator.mState == TwilightCalculator.NIGHT);
+            final long todaySunrise = mTwilightCalculator.mSunrise;
+            final long todaySunset = mTwilightCalculator.mSunset;
+
+            // calculate tomorrow's twilight
+            mTwilightCalculator.calculateTwilight(now + DateUtils.DAY_IN_MILLIS,
+                    mLocation.getLatitude(), mLocation.getLongitude());
+            final long tomorrowSunrise = mTwilightCalculator.mSunrise;
+
+            // set twilight state
+            TwilightState state = new TwilightState(isNight, yesterdaySunset,
+                    todaySunrise, todaySunset, tomorrowSunrise);
+            if (DEBUG) {
+                Slog.d(TAG, "Updating twilight state: " + state);
+            }
+            setTwilightState(state);
+
+            // schedule next update
+            long nextUpdate = 0;
+            if (todaySunrise == -1 || todaySunset == -1) {
+                // In the case the day or night never ends the update is scheduled 12 hours later.
+                nextUpdate = now + 12 * DateUtils.HOUR_IN_MILLIS;
+            } else {
+                // add some extra time to be on the safe side.
+                nextUpdate += DateUtils.MINUTE_IN_MILLIS;
+
+                if (now > todaySunset) {
+                    nextUpdate += tomorrowSunrise;
+                } else if (now > todaySunrise) {
+                    nextUpdate += todaySunset;
+                } else {
+                    nextUpdate += todaySunrise;
+                }
+            }
+
+            if (DEBUG) {
+                Slog.d(TAG, "Next update in " + (nextUpdate - now) + " ms");
+            }
+
+            Intent updateIntent = new Intent(ACTION_UPDATE_TWILIGHT_STATE);
+            PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, updateIntent, 0);
+            mAlarmManager.cancel(pendingIntent);
+            mAlarmManager.set(AlarmManager.RTC_WAKEUP, nextUpdate, pendingIntent);
+        }
+    };
+
+    private final BroadcastReceiver mUpdateLocationReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(intent.getAction())
+                    && !intent.getBooleanExtra("state", false)) {
+                // Airplane mode is now off!
+                mLocationHandler.requestLocationUpdate();
+                return;
+            }
+
+            // Time zone has changed or alarm expired.
+            mLocationHandler.requestTwilightUpdate();
+        }
+    };
+
+    // A LocationListener to initialize the network location provider. The location updates
+    // are handled through the passive location provider.
+    private final LocationListener mEmptyLocationListener =  new LocationListener() {
+        public void onLocationChanged(Location location) {
+        }
+
+        public void onProviderDisabled(String provider) {
+        }
+
+        public void onProviderEnabled(String provider) {
+        }
+
+        public void onStatusChanged(String provider, int status, Bundle extras) {
+        }
+    };
+
+    private final LocationListener mLocationListener = new LocationListener() {
+        public void onLocationChanged(Location location) {
+            mLocationHandler.processNewLocation(location);
+        }
+
+        public void onProviderDisabled(String provider) {
+        }
+
+        public void onProviderEnabled(String provider) {
+        }
+
+        public void onStatusChanged(String provider, int status, Bundle extras) {
+        }
+    };
+}
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index d1f92a7..0e456f1 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -17,70 +17,49 @@
 package com.android.server;
 
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
-import android.app.AlarmManager;
 import android.app.IUiModeManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
 import android.app.UiModeManager;
-import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
-import android.location.Criteria;
-import android.location.Location;
-import android.location.LocationListener;
-import android.location.LocationManager;
 import android.os.BatteryManager;
 import android.os.Binder;
-import android.os.Bundle;
 import android.os.Handler;
-import android.os.Message;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemClock;
+import android.os.UserHandle;
 import android.provider.Settings;
-import android.text.format.DateUtils;
-import android.text.format.Time;
+import android.service.dreams.Sandman;
 import android.util.Slog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.Iterator;
 
 import com.android.internal.R;
 import com.android.internal.app.DisableCarModeActivity;
+import com.android.server.TwilightService.TwilightState;
 
-class UiModeManagerService extends IUiModeManager.Stub {
+final class UiModeManagerService extends IUiModeManager.Stub {
     private static final String TAG = UiModeManager.class.getSimpleName();
     private static final boolean LOG = false;
 
-    private static final String KEY_LAST_UPDATE_INTERVAL = "LAST_UPDATE_INTERVAL";
-
     // Enable launching of applications when entering the dock.
     private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true;
     private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true;
 
-    private static final int MSG_UPDATE_TWILIGHT = 0;
-    private static final int MSG_ENABLE_LOCATION_UPDATES = 1;
-    private static final int MSG_GET_NEW_LOCATION_UPDATE = 2;
-
-    private static final long LOCATION_UPDATE_MS = 24 * DateUtils.HOUR_IN_MILLIS;
-    private static final long MIN_LOCATION_UPDATE_MS = 30 * DateUtils.MINUTE_IN_MILLIS;
-    private static final float LOCATION_UPDATE_DISTANCE_METER = 1000 * 20;
-    private static final long LOCATION_UPDATE_ENABLE_INTERVAL_MIN = 5000;
-    private static final long LOCATION_UPDATE_ENABLE_INTERVAL_MAX = 15 * DateUtils.MINUTE_IN_MILLIS;
-    private static final double FACTOR_GMT_OFFSET_LONGITUDE = 1000.0 * 360.0 / DateUtils.DAY_IN_MILLIS;
-
-    private static final String ACTION_UPDATE_NIGHT_MODE = "com.android.server.action.UPDATE_NIGHT_MODE";
-
     private final Context mContext;
+    private final TwilightService mTwilightService;
+    private final Handler mHandler = new Handler();
 
     final Object mLock = new Object();
 
@@ -106,11 +85,9 @@
 
     private NotificationManager mNotificationManager;
 
-    private AlarmManager mAlarmManager;
-
-    private LocationManager mLocationManager;
-    private Location mLocation;
     private StatusBarManager mStatusBarManager;
+
+    private final PowerManager mPowerManager;
     private final PowerManager.WakeLock mWakeLock;
 
     static Intent buildHomeIntent(String category) {
@@ -136,81 +113,10 @@
                 return;
             }
 
-            final int  enableFlags = intent.getIntExtra("enableFlags", 0);
-            final int  disableFlags = intent.getIntExtra("disableFlags", 0);
-
+            final int enableFlags = intent.getIntExtra("enableFlags", 0);
+            final int disableFlags = intent.getIntExtra("disableFlags", 0);
             synchronized (mLock) {
-                // Launch a dock activity
-                String category = null;
-                if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(intent.getAction())) {
-                    // Only launch car home when car mode is enabled and the caller
-                    // has asked us to switch to it.
-                    if (ENABLE_LAUNCH_CAR_DOCK_APP
-                            && (enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
-                        category = Intent.CATEGORY_CAR_DOCK;
-                    }
-                } else if (UiModeManager.ACTION_ENTER_DESK_MODE.equals(intent.getAction())) {
-                    // Only launch car home when desk mode is enabled and the caller
-                    // has asked us to switch to it.  Currently re-using the car
-                    // mode flag since we don't have a formal API for "desk mode".
-                    if (ENABLE_LAUNCH_DESK_DOCK_APP
-                            && (enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
-                        category = Intent.CATEGORY_DESK_DOCK;
-                    }
-                } else {
-                    // Launch the standard home app if requested.
-                    if ((disableFlags&UiModeManager.DISABLE_CAR_MODE_GO_HOME) != 0) {
-                        category = Intent.CATEGORY_HOME;
-                    }
-                }
-
-                if (LOG) {
-                    Slog.v(TAG, String.format(
-                        "Handling broadcast result for action %s: enable=0x%08x disable=0x%08x category=%s",
-                        intent.getAction(), enableFlags, disableFlags, category));
-                }
-
-                if (category != null) {
-                    // This is the new activity that will serve as home while
-                    // we are in care mode.
-                    Intent homeIntent = buildHomeIntent(category);
-
-                    // Now we are going to be careful about switching the
-                    // configuration and starting the activity -- we need to
-                    // do this in a specific order under control of the
-                    // activity manager, to do it cleanly.  So compute the
-                    // new config, but don't set it yet, and let the
-                    // activity manager take care of both the start and config
-                    // change.
-                    Configuration newConfig = null;
-                    if (mHoldingConfiguration) {
-                        mHoldingConfiguration = false;
-                        updateConfigurationLocked(false);
-                        newConfig = mConfiguration;
-                    }
-                    try {
-                        ActivityManagerNative.getDefault().startActivityWithConfig(
-                                null, homeIntent, null, null, null, 0, 0,
-                                newConfig, null);
-                        mHoldingConfiguration = false;
-                    } catch (RemoteException e) {
-                        Slog.w(TAG, e.getCause());
-                    }
-                }
-
-                if (mHoldingConfiguration) {
-                    mHoldingConfiguration = false;
-                    updateConfigurationLocked(true);
-                }
-            }
-        }
-    };
-
-    private final BroadcastReceiver mTwilightUpdateReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (isDoingNightMode() && mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
-                mHandler.sendEmptyMessage(MSG_UPDATE_TWILIGHT);
+                updateAfterBroadcastLocked(intent.getAction(), enableFlags, disableFlags);
             }
         }
     };
@@ -236,116 +142,27 @@
         }
     };
 
-    private final BroadcastReceiver mUpdateLocationReceiver = new BroadcastReceiver() {
+    private final TwilightService.TwilightListener mTwilightListener =
+            new TwilightService.TwilightListener() {
         @Override
-        public void onReceive(Context context, Intent intent) {
-            if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(intent.getAction())) {
-                if (!intent.getBooleanExtra("state", false)) {
-                    // Airplane mode is now off!
-                    mHandler.sendEmptyMessage(MSG_GET_NEW_LOCATION_UPDATE);
-                }
-            } else {
-                // Time zone has changed!
-                mHandler.sendEmptyMessage(MSG_GET_NEW_LOCATION_UPDATE);
-            }
+        public void onTwilightStateChanged() {
+            updateTwilight();
         }
     };
 
-    // A LocationListener to initialize the network location provider. The location updates
-    // are handled through the passive location provider.
-    private final LocationListener mEmptyLocationListener =  new LocationListener() {
-        public void onLocationChanged(Location location) {
-        }
-
-        public void onProviderDisabled(String provider) {
-        }
-
-        public void onProviderEnabled(String provider) {
-        }
-
-        public void onStatusChanged(String provider, int status, Bundle extras) {
-        }
-    };
-
-    private final LocationListener mLocationListener = new LocationListener() {
-
-        public void onLocationChanged(Location location) {
-            final boolean hasMoved = hasMoved(location);
-            final boolean hasBetterAccuracy = mLocation == null
-                    || location.getAccuracy() < mLocation.getAccuracy();
-            if (hasMoved || hasBetterAccuracy) {
-                synchronized (mLock) {
-                    mLocation = location;
-                    if (hasMoved && isDoingNightMode()
-                            && mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
-                        mHandler.sendEmptyMessage(MSG_UPDATE_TWILIGHT);
-                    }
-                }
-            }
-        }
-
-        public void onProviderDisabled(String provider) {
-        }
-
-        public void onProviderEnabled(String provider) {
-        }
-
-        public void onStatusChanged(String provider, int status, Bundle extras) {
-        }
-
-        /*
-         * The user has moved if the accuracy circles of the two locations
-         * don't overlap.
-         */
-        private boolean hasMoved(Location location) {
-            if (location == null) {
-                return false;
-            }
-            if (mLocation == null) {
-                return true;
-            }
-
-            /* if new location is older than the current one, the devices hasn't
-             * moved.
-             */
-            if (location.getTime() < mLocation.getTime()) {
-                return false;
-            }
-
-            /* Get the distance between the two points */
-            float distance = mLocation.distanceTo(location);
-
-            /* Get the total accuracy radius for both locations */
-            float totalAccuracy = mLocation.getAccuracy() + location.getAccuracy();
-
-            /* If the distance is greater than the combined accuracy of the two
-             * points then they can't overlap and hence the user has moved.
-             */
-            return distance >= totalAccuracy;
-        }
-    };
-
-    public UiModeManagerService(Context context) {
+    public UiModeManagerService(Context context, TwilightService twilight) {
         mContext = context;
+        mTwilightService = twilight;
 
         ServiceManager.addService(Context.UI_MODE_SERVICE, this);
 
-        mAlarmManager =
-            (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
-        mLocationManager =
-            (LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE);
-        mContext.registerReceiver(mTwilightUpdateReceiver,
-                new IntentFilter(ACTION_UPDATE_NIGHT_MODE));
         mContext.registerReceiver(mDockModeReceiver,
                 new IntentFilter(Intent.ACTION_DOCK_EVENT));
         mContext.registerReceiver(mBatteryReceiver,
                 new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
-        IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
-        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
-        mContext.registerReceiver(mUpdateLocationReceiver, filter);
 
-        PowerManager powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
+        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
 
         mConfiguration.setToDefaults();
 
@@ -360,81 +177,105 @@
 
         mNightMode = Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.UI_NIGHT_MODE, UiModeManager.MODE_NIGHT_AUTO);
+
+        mTwilightService.registerListener(mTwilightListener, mHandler);
     }
 
+    @Override // Binder call
     public void disableCarMode(int flags) {
-        synchronized (mLock) {
-            setCarModeLocked(false);
-            if (mSystemReady) {
-                updateLocked(0, flags);
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                setCarModeLocked(false);
+                if (mSystemReady) {
+                    updateLocked(0, flags);
+                }
             }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
+    @Override // Binder call
     public void enableCarMode(int flags) {
-        synchronized (mLock) {
-            setCarModeLocked(true);
-            if (mSystemReady) {
-                updateLocked(flags, 0);
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                setCarModeLocked(true);
+                if (mSystemReady) {
+                    updateLocked(flags, 0);
+                }
             }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
+    @Override // Binder call
     public int getCurrentModeType() {
-        synchronized (mLock) {
-            return mCurUiMode & Configuration.UI_MODE_TYPE_MASK;
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                return mCurUiMode & Configuration.UI_MODE_TYPE_MASK;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
-    public void setNightMode(int mode) throws RemoteException {
-        synchronized (mLock) {
-            switch (mode) {
-                case UiModeManager.MODE_NIGHT_NO:
-                case UiModeManager.MODE_NIGHT_YES:
-                case UiModeManager.MODE_NIGHT_AUTO:
-                    break;
-                default:
-                    throw new IllegalArgumentException("Unknown mode: " + mode);
-            }
-            if (!isDoingNightMode()) {
-                return;
-            }
+    @Override // Binder call
+    public void setNightMode(int mode) {
+        switch (mode) {
+            case UiModeManager.MODE_NIGHT_NO:
+            case UiModeManager.MODE_NIGHT_YES:
+            case UiModeManager.MODE_NIGHT_AUTO:
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown mode: " + mode);
+        }
 
-            if (mNightMode != mode) {
-                long ident = Binder.clearCallingIdentity();
-                Settings.Secure.putInt(mContext.getContentResolver(),
-                        Settings.Secure.UI_NIGHT_MODE, mode);
-                Binder.restoreCallingIdentity(ident);
-                mNightMode = mode;
-                updateLocked(0, 0);
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                if (isDoingNightModeLocked() && mNightMode != mode) {
+                    Settings.Secure.putInt(mContext.getContentResolver(),
+                            Settings.Secure.UI_NIGHT_MODE, mode);
+                    mNightMode = mode;
+                    updateLocked(0, 0);
+                }
             }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
-    public int getNightMode() throws RemoteException {
-        return mNightMode;
+    @Override // Binder call
+    public int getNightMode() {
+        synchronized (mLock) {
+            return mNightMode;
+        }
     }
 
     void systemReady() {
         synchronized (mLock) {
             mSystemReady = true;
             mCarModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR;
+            updateComputedNightModeLocked();
             updateLocked(0, 0);
-            mHandler.sendEmptyMessage(MSG_ENABLE_LOCATION_UPDATES);
         }
     }
 
-    boolean isDoingNightMode() {
+    private boolean isDoingNightModeLocked() {
         return mCarModeEnabled || mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
     }
 
-    void setCarModeLocked(boolean enabled) {
+    private void setCarModeLocked(boolean enabled) {
         if (mCarModeEnabled != enabled) {
             mCarModeEnabled = enabled;
         }
     }
 
-    void updateDockState(int newState) {
+    private void updateDockState(int newState) {
         synchronized (mLock) {
             if (newState != mDockState) {
                 mDockState = newState;
@@ -446,7 +287,7 @@
         }
     }
 
-    final static boolean isDeskDockState(int state) {
+    private static boolean isDeskDockState(int state) {
         switch (state) {
             case Intent.EXTRA_DOCK_STATE_DESK:
             case Intent.EXTRA_DOCK_STATE_LE_DESK:
@@ -457,9 +298,8 @@
         }
     }
 
-    final void updateConfigurationLocked(boolean sendIt) {
-        int uiMode = mTelevision ? Configuration.UI_MODE_TYPE_TELEVISION
-                : mDefaultUiModeType;
+    private void updateConfigurationLocked() {
+        int uiMode = mTelevision ? Configuration.UI_MODE_TYPE_TELEVISION : mDefaultUiModeType;
         if (mCarModeEnabled) {
             uiMode = Configuration.UI_MODE_TYPE_CAR;
         } else if (isDeskDockState(mDockState)) {
@@ -467,7 +307,7 @@
         }
         if (mCarModeEnabled) {
             if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
-                updateTwilightLocked();
+                updateComputedNightModeLocked();
                 uiMode |= mComputedNightMode ? Configuration.UI_MODE_NIGHT_YES
                         : Configuration.UI_MODE_NIGHT_NO;
             } else {
@@ -487,131 +327,200 @@
         }
 
         mCurUiMode = uiMode;
-
-        if (!mHoldingConfiguration && uiMode != mSetUiMode) {
-            mSetUiMode = uiMode;
+        if (!mHoldingConfiguration) {
             mConfiguration.uiMode = uiMode;
+        }
+    }
 
-            if (sendIt) {
-                try {
-                    ActivityManagerNative.getDefault().updateConfiguration(mConfiguration);
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "Failure communicating with activity manager", e);
-                }
+    private void sendConfigurationLocked() {
+        if (mSetUiMode != mConfiguration.uiMode) {
+            mSetUiMode = mConfiguration.uiMode;
+
+            try {
+                ActivityManagerNative.getDefault().updateConfiguration(mConfiguration);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Failure communicating with activity manager", e);
             }
         }
     }
 
-    final void updateLocked(int enableFlags, int disableFlags) {
-        long ident = Binder.clearCallingIdentity();
+    private void updateLocked(int enableFlags, int disableFlags) {
+        String action = null;
+        String oldAction = null;
+        if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_CAR) {
+            adjustStatusBarCarModeLocked();
+            oldAction = UiModeManager.ACTION_EXIT_CAR_MODE;
+        } else if (isDeskDockState(mLastBroadcastState)) {
+            oldAction = UiModeManager.ACTION_EXIT_DESK_MODE;
+        }
 
-        try {
-            String action = null;
-            String oldAction = null;
-            if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_CAR) {
+        if (mCarModeEnabled) {
+            if (mLastBroadcastState != Intent.EXTRA_DOCK_STATE_CAR) {
                 adjustStatusBarCarModeLocked();
-                oldAction = UiModeManager.ACTION_EXIT_CAR_MODE;
-            } else if (isDeskDockState(mLastBroadcastState)) {
-                oldAction = UiModeManager.ACTION_EXIT_DESK_MODE;
+
+                if (oldAction != null) {
+                    mContext.sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL);
+                }
+                mLastBroadcastState = Intent.EXTRA_DOCK_STATE_CAR;
+                action = UiModeManager.ACTION_ENTER_CAR_MODE;
+            }
+        } else if (isDeskDockState(mDockState)) {
+            if (!isDeskDockState(mLastBroadcastState)) {
+                if (oldAction != null) {
+                    mContext.sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL);
+                }
+                mLastBroadcastState = mDockState;
+                action = UiModeManager.ACTION_ENTER_DESK_MODE;
+            }
+        } else {
+            mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
+            action = oldAction;
+        }
+
+        if (action != null) {
+            if (LOG) {
+                Slog.v(TAG, String.format(
+                    "updateLocked: preparing broadcast: action=%s enable=0x%08x disable=0x%08x",
+                    action, enableFlags, disableFlags));
             }
 
-            if (mCarModeEnabled) {
-                if (mLastBroadcastState != Intent.EXTRA_DOCK_STATE_CAR) {
-                    adjustStatusBarCarModeLocked();
+            // Send the ordered broadcast; the result receiver will receive after all
+            // broadcasts have been sent. If any broadcast receiver changes the result
+            // code from the initial value of RESULT_OK, then the result receiver will
+            // not launch the corresponding dock application. This gives apps a chance
+            // to override the behavior and stay in their app even when the device is
+            // placed into a dock.
+            Intent intent = new Intent(action);
+            intent.putExtra("enableFlags", enableFlags);
+            intent.putExtra("disableFlags", disableFlags);
+            mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
+                    mResultReceiver, null, Activity.RESULT_OK, null, null);
 
-                    if (oldAction != null) {
-                        mContext.sendBroadcast(new Intent(oldAction));
-                    }
-                    mLastBroadcastState = Intent.EXTRA_DOCK_STATE_CAR;
-                    action = UiModeManager.ACTION_ENTER_CAR_MODE;
+            // Attempting to make this transition a little more clean, we are going
+            // to hold off on doing a configuration change until we have finished
+            // the broadcast and started the home activity.
+            mHoldingConfiguration = true;
+            updateConfigurationLocked();
+        } else {
+            String category = null;
+            if (mCarModeEnabled) {
+                if (ENABLE_LAUNCH_CAR_DOCK_APP
+                        && (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
+                    category = Intent.CATEGORY_CAR_DOCK;
                 }
             } else if (isDeskDockState(mDockState)) {
-                if (!isDeskDockState(mLastBroadcastState)) {
-                    if (oldAction != null) {
-                        mContext.sendBroadcast(new Intent(oldAction));
-                    }
-                    mLastBroadcastState = mDockState;
-                    action = UiModeManager.ACTION_ENTER_DESK_MODE;
+                if (ENABLE_LAUNCH_DESK_DOCK_APP
+                        && (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
+                    category = Intent.CATEGORY_DESK_DOCK;
                 }
             } else {
-                mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
-                action = oldAction;
+                if ((disableFlags & UiModeManager.DISABLE_CAR_MODE_GO_HOME) != 0) {
+                    category = Intent.CATEGORY_HOME;
+                }
             }
 
-            if (action != null) {
-                if (LOG) {
-                    Slog.v(TAG, String.format(
-                        "updateLocked: preparing broadcast: action=%s enable=0x%08x disable=0x%08x",
-                        action, enableFlags, disableFlags));
-                }
+            if (LOG) {
+                Slog.v(TAG, "updateLocked: null action, mDockState="
+                        + mDockState +", category=" + category);
+            }
 
-                // Send the ordered broadcast; the result receiver will receive after all
-                // broadcasts have been sent. If any broadcast receiver changes the result
-                // code from the initial value of RESULT_OK, then the result receiver will
-                // not launch the corresponding dock application. This gives apps a chance
-                // to override the behavior and stay in their app even when the device is
-                // placed into a dock.
-                Intent intent = new Intent(action);
-                intent.putExtra("enableFlags", enableFlags);
-                intent.putExtra("disableFlags", disableFlags);
-                mContext.sendOrderedBroadcast(intent, null,
-                        mResultReceiver, null, Activity.RESULT_OK, null, null);
-                // Attempting to make this transition a little more clean, we are going
-                // to hold off on doing a configuration change until we have finished
-                // the broadcast and started the home activity.
-                mHoldingConfiguration = true;
+            sendConfigurationAndStartDreamOrDockAppLocked(category);
+        }
+
+        // keep screen on when charging and in car mode
+        boolean keepScreenOn = mCharging &&
+                ((mCarModeEnabled && mCarModeKeepsScreenOn) ||
+                 (mCurUiMode == Configuration.UI_MODE_TYPE_DESK && mDeskModeKeepsScreenOn));
+        if (keepScreenOn != mWakeLock.isHeld()) {
+            if (keepScreenOn) {
+                mWakeLock.acquire();
             } else {
-                Intent homeIntent = null;
-                if (mCarModeEnabled) {
-                    if (ENABLE_LAUNCH_CAR_DOCK_APP
-                            && (enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
-                        homeIntent = buildHomeIntent(Intent.CATEGORY_CAR_DOCK);
-                    }
-                } else if (isDeskDockState(mDockState)) {
-                    if (ENABLE_LAUNCH_DESK_DOCK_APP
-                            && (enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
-                        homeIntent = buildHomeIntent(Intent.CATEGORY_DESK_DOCK);
-                    }
-                } else {
-                    if ((disableFlags&UiModeManager.DISABLE_CAR_MODE_GO_HOME) != 0) {
-                        homeIntent = buildHomeIntent(Intent.CATEGORY_HOME);
-                    }
-                }
+                mWakeLock.release();
+            }
+        }
+    }
 
-                if (LOG) {
-                    Slog.v(TAG, "updateLocked: null action, mDockState="
-                            + mDockState +", firing homeIntent: " + homeIntent);
-                }
+    private void updateAfterBroadcastLocked(String action, int enableFlags, int disableFlags) {
+        // Launch a dock activity
+        String category = null;
+        if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(action)) {
+            // Only launch car home when car mode is enabled and the caller
+            // has asked us to switch to it.
+            if (ENABLE_LAUNCH_CAR_DOCK_APP
+                    && (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
+                category = Intent.CATEGORY_CAR_DOCK;
+            }
+        } else if (UiModeManager.ACTION_ENTER_DESK_MODE.equals(action)) {
+            // Only launch car home when desk mode is enabled and the caller
+            // has asked us to switch to it.  Currently re-using the car
+            // mode flag since we don't have a formal API for "desk mode".
+            if (ENABLE_LAUNCH_DESK_DOCK_APP
+                    && (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
+                category = Intent.CATEGORY_DESK_DOCK;
+            }
+        } else {
+            // Launch the standard home app if requested.
+            if ((disableFlags & UiModeManager.DISABLE_CAR_MODE_GO_HOME) != 0) {
+                category = Intent.CATEGORY_HOME;
+            }
+        }
 
-                if (homeIntent != null) {
-                    try {
-                        mContext.startActivity(homeIntent);
-                    } catch (ActivityNotFoundException e) {
+        if (LOG) {
+            Slog.v(TAG, String.format(
+                "Handling broadcast result for action %s: enable=0x%08x, disable=0x%08x, "
+                    + "category=%s",
+                action, enableFlags, disableFlags, category));
+        }
+
+        sendConfigurationAndStartDreamOrDockAppLocked(category);
+    }
+
+    private void sendConfigurationAndStartDreamOrDockAppLocked(String category) {
+        // Update the configuration but don't send it yet.
+        mHoldingConfiguration = false;
+        updateConfigurationLocked();
+
+        // Start the dock app, if there is one.
+        boolean dockAppStarted = false;
+        if (category != null) {
+            // Now we are going to be careful about switching the
+            // configuration and starting the activity -- we need to
+            // do this in a specific order under control of the
+            // activity manager, to do it cleanly.  So compute the
+            // new config, but don't set it yet, and let the
+            // activity manager take care of both the start and config
+            // change.
+            Intent homeIntent = buildHomeIntent(category);
+            if (Sandman.shouldStartDockApp(mContext, homeIntent)) {
+                try {
+                    int result = ActivityManagerNative.getDefault().startActivityWithConfig(
+                            null, homeIntent, null, null, null, 0, 0,
+                            mConfiguration, null, UserHandle.USER_CURRENT);
+                    if (result >= ActivityManager.START_SUCCESS) {
+                        dockAppStarted = true;
+                    } else if (result != ActivityManager.START_INTENT_NOT_RESOLVED) {
+                        Slog.e(TAG, "Could not start dock app: " + homeIntent
+                                + ", startActivityWithConfig result " + result);
                     }
+                } catch (RemoteException ex) {
+                    Slog.e(TAG, "Could not start dock app: " + homeIntent, ex);
                 }
             }
+        }
 
-            updateConfigurationLocked(true);
+        // Send the new configuration.
+        sendConfigurationLocked();
 
-            // keep screen on when charging and in car mode
-            boolean keepScreenOn = mCharging &&
-                    ((mCarModeEnabled && mCarModeKeepsScreenOn) ||
-                     (mCurUiMode == Configuration.UI_MODE_TYPE_DESK && mDeskModeKeepsScreenOn));
-            if (keepScreenOn != mWakeLock.isHeld()) {
-                if (keepScreenOn) {
-                    mWakeLock.acquire();
-                } else {
-                    mWakeLock.release();
-                }
-            }
-        } finally {
-            Binder.restoreCallingIdentity(ident);
+        // If we did not start a dock app, then start dreaming if supported.
+        if (category != null && !dockAppStarted) {
+            Sandman.startDreamWhenDockedIfAppropriate(mContext);
         }
     }
 
     private void adjustStatusBarCarModeLocked() {
         if (mStatusBarManager == null) {
-            mStatusBarManager = (StatusBarManager) mContext.getSystemService(Context.STATUS_BAR_SERVICE);
+            mStatusBarManager = (StatusBarManager)
+                    mContext.getSystemService(Context.STATUS_BAR_SERVICE);
         }
 
         // Fear not: StatusBarManagerService manages a list of requests to disable
@@ -643,197 +552,31 @@
                         mContext,
                         mContext.getString(R.string.car_mode_disable_notification_title),
                         mContext.getString(R.string.car_mode_disable_notification_message),
-                        PendingIntent.getActivity(mContext, 0, carModeOffIntent, 0));
-                mNotificationManager.notify(0, n);
+                        PendingIntent.getActivityAsUser(mContext, 0, carModeOffIntent, 0,
+                                null, UserHandle.CURRENT));
+                mNotificationManager.notifyAsUser(null,
+                        R.string.car_mode_disable_notification_title, n, UserHandle.ALL);
             } else {
-                mNotificationManager.cancel(0);
+                mNotificationManager.cancelAsUser(null,
+                        R.string.car_mode_disable_notification_title, UserHandle.ALL);
             }
         }
     }
 
-    private final Handler mHandler = new Handler() {
-
-        boolean mPassiveListenerEnabled;
-        boolean mNetworkListenerEnabled;
-        boolean mDidFirstInit;
-        long mLastNetworkRegisterTime = -MIN_LOCATION_UPDATE_MS;
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_UPDATE_TWILIGHT:
-                    synchronized (mLock) {
-                        if (isDoingNightMode() && mLocation != null
-                                && mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
-                            updateTwilightLocked();
-                            updateLocked(0, 0);
-                        }
-                    }
-                    break;
-                case MSG_GET_NEW_LOCATION_UPDATE:
-                    if (!mNetworkListenerEnabled) {
-                        // Don't do anything -- we are still trying to get a
-                        // location.
-                        return;
-                    }
-                    if ((mLastNetworkRegisterTime+MIN_LOCATION_UPDATE_MS)
-                            >= SystemClock.elapsedRealtime()) {
-                        // Don't do anything -- it hasn't been long enough
-                        // since we last requested an update.
-                        return;
-                    }
-
-                    // Unregister the current location monitor, so we can
-                    // register a new one for it to get an immediate update.
-                    mNetworkListenerEnabled = false;
-                    mLocationManager.removeUpdates(mEmptyLocationListener);
-
-                    // Fall through to re-register listener.
-                case MSG_ENABLE_LOCATION_UPDATES:
-                    // enable network provider to receive at least location updates for a given
-                    // distance.
-                    boolean networkLocationEnabled;
-                    try {
-                        networkLocationEnabled =
-                            mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
-                    } catch (Exception e) {
-                        // we may get IllegalArgumentException if network location provider
-                        // does not exist or is not yet installed.
-                        networkLocationEnabled = false;
-                    }
-                    if (!mNetworkListenerEnabled && networkLocationEnabled) {
-                        mNetworkListenerEnabled = true;
-                        mLastNetworkRegisterTime = SystemClock.elapsedRealtime();
-                        mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
-                                LOCATION_UPDATE_MS, 0, mEmptyLocationListener);
-
-                        if (!mDidFirstInit) {
-                            mDidFirstInit = true;
-                            if (mLocation == null) {
-                                retrieveLocation();
-                            }
-                            synchronized (mLock) {
-                                if (isDoingNightMode() && mLocation != null
-                                        && mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
-                                    updateTwilightLocked();
-                                    updateLocked(0, 0);
-                                }
-                            }
-                        }
-                    }
-                   // enable passive provider to receive updates from location fixes (gps
-                   // and network).
-                   boolean passiveLocationEnabled;
-                    try {
-                        passiveLocationEnabled =
-                            mLocationManager.isProviderEnabled(LocationManager.PASSIVE_PROVIDER);
-                    } catch (Exception e) {
-                        // we may get IllegalArgumentException if passive location provider
-                        // does not exist or is not yet installed.
-                        passiveLocationEnabled = false;
-                    }
-                    if (!mPassiveListenerEnabled && passiveLocationEnabled) {
-                        mPassiveListenerEnabled = true;
-                        mLocationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER,
-                                0, LOCATION_UPDATE_DISTANCE_METER , mLocationListener);
-                    }
-                    if (!(mNetworkListenerEnabled && mPassiveListenerEnabled)) {
-                        long interval = msg.getData().getLong(KEY_LAST_UPDATE_INTERVAL);
-                        interval *= 1.5;
-                        if (interval == 0) {
-                            interval = LOCATION_UPDATE_ENABLE_INTERVAL_MIN;
-                        } else if (interval > LOCATION_UPDATE_ENABLE_INTERVAL_MAX) {
-                            interval = LOCATION_UPDATE_ENABLE_INTERVAL_MAX;
-                        }
-                        Bundle bundle = new Bundle();
-                        bundle.putLong(KEY_LAST_UPDATE_INTERVAL, interval);
-                        Message newMsg = mHandler.obtainMessage(MSG_ENABLE_LOCATION_UPDATES);
-                        newMsg.setData(bundle);
-                        mHandler.sendMessageDelayed(newMsg, interval);
-                    }
-                    break;
+    private void updateTwilight() {
+        synchronized (mLock) {
+            if (isDoingNightModeLocked() && mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
+                updateComputedNightModeLocked();
+                updateLocked(0, 0);
             }
         }
+    }
 
-        private void retrieveLocation() {
-            Location location = null;
-            final Iterator<String> providers =
-                    mLocationManager.getProviders(new Criteria(), true).iterator();
-            while (providers.hasNext()) {
-                final Location lastKnownLocation =
-                        mLocationManager.getLastKnownLocation(providers.next());
-                // pick the most recent location
-                if (location == null || (lastKnownLocation != null &&
-                        location.getTime() < lastKnownLocation.getTime())) {
-                    location = lastKnownLocation;
-                }
-            }
-            // In the case there is no location available (e.g. GPS fix or network location
-            // is not available yet), the longitude of the location is estimated using the timezone,
-            // latitude and accuracy are set to get a good average.
-            if (location == null) {
-                Time currentTime = new Time();
-                currentTime.set(System.currentTimeMillis());
-                double lngOffset = FACTOR_GMT_OFFSET_LONGITUDE *
-                        (currentTime.gmtoff - (currentTime.isDst > 0 ? 3600 : 0));
-                location = new Location("fake");
-                location.setLongitude(lngOffset);
-                location.setLatitude(0);
-                location.setAccuracy(417000.0f);
-                location.setTime(System.currentTimeMillis());
-            }
-            synchronized (mLock) {
-                mLocation = location;
-            }
+    private void updateComputedNightModeLocked() {
+        TwilightState state = mTwilightService.getCurrentState();
+        if (state != null) {
+            mComputedNightMode = state.isNight();
         }
-    };
-
-    void updateTwilightLocked() {
-        if (mLocation == null) {
-            return;
-        }
-        final long currentTime = System.currentTimeMillis();
-        boolean nightMode;
-        // calculate current twilight
-        TwilightCalculator tw = new TwilightCalculator();
-        tw.calculateTwilight(currentTime,
-                mLocation.getLatitude(), mLocation.getLongitude());
-        if (tw.mState == TwilightCalculator.DAY) {
-            nightMode = false;
-        } else {
-            nightMode = true;
-        }
-
-        // schedule next update
-        long nextUpdate = 0;
-        if (tw.mSunrise == -1 || tw.mSunset == -1) {
-            // In the case the day or night never ends the update is scheduled 12 hours later.
-            nextUpdate = currentTime + 12 * DateUtils.HOUR_IN_MILLIS;
-        } else {
-            final int mLastTwilightState = tw.mState;
-            // add some extra time to be on the save side.
-            nextUpdate += DateUtils.MINUTE_IN_MILLIS;
-            if (currentTime > tw.mSunset) {
-                // next update should be on the following day
-                tw.calculateTwilight(currentTime
-                        + DateUtils.DAY_IN_MILLIS, mLocation.getLatitude(),
-                        mLocation.getLongitude());
-            }
-
-            if (mLastTwilightState == TwilightCalculator.NIGHT) {
-                nextUpdate += tw.mSunrise;
-            } else {
-                nextUpdate += tw.mSunset;
-            }
-        }
-
-        Intent updateIntent = new Intent(ACTION_UPDATE_NIGHT_MODE);
-        PendingIntent pendingIntent =
-                PendingIntent.getBroadcast(mContext, 0, updateIntent, 0);
-        mAlarmManager.cancel(pendingIntent);
-        mAlarmManager.set(AlarmManager.RTC_WAKEUP, nextUpdate, pendingIntent);
-
-        mComputedNightMode = nightMode;
     }
 
     @Override
@@ -858,9 +601,8 @@
                     pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode));
             pw.print("  mHoldingConfiguration="); pw.print(mHoldingConfiguration);
                     pw.print(" mSystemReady="); pw.println(mSystemReady);
-            if (mLocation != null) {
-                pw.print("  mLocation="); pw.println(mLocation);
-            }
+            pw.print("  mTwilightService.getCurrentState()=");
+                    pw.println(mTwilightService.getCurrentState());
         }
     }
 }
diff --git a/services/java/com/android/server/UpdateLockService.java b/services/java/com/android/server/UpdateLockService.java
index 1ffd196..0f778cd 100644
--- a/services/java/com/android/server/UpdateLockService.java
+++ b/services/java/com/android/server/UpdateLockService.java
@@ -27,6 +27,7 @@
 import android.os.SystemClock;
 import android.os.TokenWatcher;
 import android.os.UpdateLock;
+import android.os.UserHandle;
 import android.util.Slog;
 
 import java.io.FileDescriptor;
@@ -78,7 +79,7 @@
                     .putExtra(UpdateLock.NOW_IS_CONVENIENT, state)
                     .putExtra(UpdateLock.TIMESTAMP, System.currentTimeMillis())
                     .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendStickyBroadcast(intent);
+            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
         } finally {
             Binder.restoreCallingIdentity(oldIdent);
         }
diff --git a/services/java/com/android/server/VibratorService.java b/services/java/com/android/server/VibratorService.java
index 72fde11..df91dec 100755
--- a/services/java/com/android/server/VibratorService.java
+++ b/services/java/com/android/server/VibratorService.java
@@ -31,6 +31,7 @@
 import android.os.IBinder;
 import android.os.Binder;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.os.Vibrator;
 import android.os.WorkSource;
 import android.provider.Settings;
@@ -139,6 +140,7 @@
 
     public void systemReady() {
         mIm = (InputManager)mContext.getSystemService(Context.INPUT_SERVICE);
+
         mContext.getContentResolver().registerContentObserver(
                 Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), true,
                 new ContentObserver(mH) {
@@ -146,7 +148,15 @@
                     public void onChange(boolean selfChange) {
                         updateInputDeviceVibrators();
                     }
-                });
+                }, UserHandle.USER_ALL);
+
+        mContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                updateInputDeviceVibrators();
+            }
+        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH);
+
         updateInputDeviceVibrators();
     }
 
@@ -341,8 +351,9 @@
             synchronized (mInputDeviceVibrators) {
                 mVibrateInputDevicesSetting = false;
                 try {
-                    mVibrateInputDevicesSetting = Settings.System.getInt(mContext.getContentResolver(),
-                            Settings.System.VIBRATE_INPUT_DEVICES) > 0;
+                    mVibrateInputDevicesSetting = Settings.System.getIntForUser(
+                            mContext.getContentResolver(),
+                            Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0;
                 } catch (SettingNotFoundException snfe) {
                 }
 
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 8a08277..82dbf54 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -16,9 +16,11 @@
 
 package com.android.server;
 
-import static android.os.FileObserver.*;
 import static android.os.ParcelFileDescriptor.*;
 
+import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
+import android.app.IUserSwitchObserver;
 import android.app.IWallpaperManager;
 import android.app.IWallpaperManagerCallback;
 import android.app.PendingIntent;
@@ -31,16 +33,19 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.IBinder;
+import android.os.IRemoteCallback;
 import android.os.RemoteException;
 import android.os.FileObserver;
 import android.os.ParcelFileDescriptor;
@@ -48,7 +53,8 @@
 import android.os.SELinux;
 import android.os.ServiceManager;
 import android.os.SystemClock;
-import android.os.UserId;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.service.wallpaper.IWallpaperConnection;
 import android.service.wallpaper.IWallpaperEngine;
 import android.service.wallpaper.IWallpaperService;
@@ -77,7 +83,6 @@
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.JournaledFile;
-import com.android.server.am.ActivityManagerService;
 
 class WallpaperManagerService extends IWallpaperManager.Stub {
     static final String TAG = "WallpaperService";
@@ -90,12 +95,17 @@
      * restarting it vs. just reverting to the static wallpaper.
      */
     static final long MIN_WALLPAPER_CRASH_TIME = 10000;
-    
-    static final File WALLPAPER_BASE_DIR = new File("/data/system/users");
     static final String WALLPAPER = "wallpaper";
     static final String WALLPAPER_INFO = "wallpaper_info.xml";
 
     /**
+     * Name of the component used to display bitmap wallpapers from either the gallery or
+     * built-in wallpapers.
+     */
+    static final ComponentName IMAGE_WALLPAPER = new ComponentName("com.android.systemui",
+            "com.android.systemui.ImageWallpaper");
+
+    /**
      * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
      * that the wallpaper has changed. The CREATE is triggered when there is no
      * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
@@ -135,8 +145,8 @@
                         if (event == CLOSE_WRITE) {
                             mWallpaper.imageWallpaperPending = false;
                         }
-                        bindWallpaperComponentLocked(mWallpaper.imageWallpaperComponent, true,
-                                false, mWallpaper);
+                        bindWallpaperComponentLocked(IMAGE_WALLPAPER, true,
+                                false, mWallpaper, null);
                         saveSettingsLocked(mWallpaper);
                     }
                 }
@@ -146,6 +156,7 @@
 
     final Context mContext;
     final IWindowManager mIWindowManager;
+    final IPackageManager mIPackageManager;
     final MyPackageMonitor mMonitor;
     WallpaperData mLastWallpaper;
 
@@ -179,13 +190,6 @@
          */
         ComponentName nextWallpaperComponent;
 
-        /**
-         * Name of the component used to display bitmap wallpapers from either the gallery or
-         * built-in wallpapers.
-         */
-        ComponentName imageWallpaperComponent = new ComponentName("com.android.systemui",
-                "com.android.systemui.ImageWallpaper");
-
         WallpaperConnection connection;
         long lastDiedTime;
         boolean wallpaperUpdating;
@@ -213,12 +217,14 @@
         IWallpaperService mService;
         IWallpaperEngine mEngine;
         WallpaperData mWallpaper;
+        IRemoteCallback mReply;
 
         public WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper) {
             mInfo = info;
             mWallpaper = wallpaper;
         }
-        
+
+        @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
             synchronized (mLock) {
                 if (mWallpaper.connection == this) {
@@ -234,6 +240,7 @@
             }
         }
 
+        @Override
         public void onServiceDisconnected(ComponentName name) {
             synchronized (mLock) {
                 mService = null;
@@ -245,16 +252,35 @@
                                 > SystemClock.uptimeMillis()
                             && mWallpaper.userId == mCurrentUserId) {
                         Slog.w(TAG, "Reverting to built-in wallpaper!");
-                        clearWallpaperLocked(true, mWallpaper.userId);
+                        clearWallpaperLocked(true, mWallpaper.userId, null);
                     }
                 }
             }
         }
 
+        @Override
         public void attachEngine(IWallpaperEngine engine) {
-            mEngine = engine;
+            synchronized (mLock) {
+                mEngine = engine;
+            }
         }
 
+        @Override
+        public void engineShown(IWallpaperEngine engine) {
+            synchronized (mLock) {
+                if (mReply != null) {
+                    long ident = Binder.clearCallingIdentity();
+                    try {
+                        mReply.sendResult(null);
+                    } catch (RemoteException e) {
+                        Binder.restoreCallingIdentity(ident);
+                    }
+                    mReply = null;
+                }
+            }
+        }
+
+        @Override
         public ParcelFileDescriptor setWallpaper(String name) {
             synchronized (mLock) {
                 if (mWallpaper.connection == this) {
@@ -269,18 +295,20 @@
         @Override
         public void onPackageUpdateFinished(String packageName, int uid) {
             synchronized (mLock) {
-                for (int i = 0; i < mWallpaperMap.size(); i++) {
-                    WallpaperData wallpaper = mWallpaperMap.valueAt(i);
+                if (mCurrentUserId != getChangingUserId()) {
+                    return;
+                }
+                WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
+                if (wallpaper != null) {
                     if (wallpaper.wallpaperComponent != null
                             && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
                         wallpaper.wallpaperUpdating = false;
                         ComponentName comp = wallpaper.wallpaperComponent;
                         clearWallpaperComponentLocked(wallpaper);
-                        // Do this only for the current user's wallpaper
-                        if (wallpaper.userId == mCurrentUserId
-                                && !bindWallpaperComponentLocked(comp, false, false, wallpaper)) {
+                        if (!bindWallpaperComponentLocked(comp, false, false,
+                                wallpaper, null)) {
                             Slog.w(TAG, "Wallpaper no longer available; reverting to default");
-                            clearWallpaperLocked(false, wallpaper.userId);
+                            clearWallpaperLocked(false, wallpaper.userId, null);
                         }
                     }
                 }
@@ -290,11 +318,14 @@
         @Override
         public void onPackageModified(String packageName) {
             synchronized (mLock) {
-                for (int i = 0; i < mWallpaperMap.size(); i++) {
-                    WallpaperData wallpaper = mWallpaperMap.valueAt(i);
+                if (mCurrentUserId != getChangingUserId()) {
+                    return;
+                }
+                WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
+                if (wallpaper != null) {
                     if (wallpaper.wallpaperComponent == null
                             || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
-                        continue;
+                        return;
                     }
                     doPackagesChangedLocked(true, wallpaper);
                 }
@@ -304,8 +335,11 @@
         @Override
         public void onPackageUpdateStarted(String packageName, int uid) {
             synchronized (mLock) {
-                for (int i = 0; i < mWallpaperMap.size(); i++) {
-                    WallpaperData wallpaper = mWallpaperMap.valueAt(i);
+                if (mCurrentUserId != getChangingUserId()) {
+                    return;
+                }
+                WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
+                if (wallpaper != null) {
                     if (wallpaper.wallpaperComponent != null
                             && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
                         wallpaper.wallpaperUpdating = true;
@@ -318,8 +352,11 @@
         public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
             synchronized (mLock) {
                 boolean changed = false;
-                for (int i = 0; i < mWallpaperMap.size(); i++) {
-                    WallpaperData wallpaper = mWallpaperMap.valueAt(i);
+                if (mCurrentUserId != getChangingUserId()) {
+                    return false;
+                }
+                WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
+                if (wallpaper != null) {
                     boolean res = doPackagesChangedLocked(doit, wallpaper);
                     changed |= res;
                 }
@@ -330,8 +367,11 @@
         @Override
         public void onSomePackagesChanged() {
             synchronized (mLock) {
-                for (int i = 0; i < mWallpaperMap.size(); i++) {
-                    WallpaperData wallpaper = mWallpaperMap.valueAt(i);
+                if (mCurrentUserId != getChangingUserId()) {
+                    return;
+                }
+                WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
+                if (wallpaper != null) {
                     doPackagesChangedLocked(true, wallpaper);
                 }
             }
@@ -348,7 +388,7 @@
                     if (doit) {
                         Slog.w(TAG, "Wallpaper uninstalled, removing: "
                                 + wallpaper.wallpaperComponent);
-                        clearWallpaperLocked(false, wallpaper.userId);
+                        clearWallpaperLocked(false, wallpaper.userId, null);
                     }
                 }
             }
@@ -368,7 +408,7 @@
                 } catch (NameNotFoundException e) {
                     Slog.w(TAG, "Wallpaper component gone, removing: "
                             + wallpaper.wallpaperComponent);
-                    clearWallpaperLocked(false, wallpaper.userId);
+                    clearWallpaperLocked(false, wallpaper.userId, null);
                 }
             }
             if (wallpaper.nextWallpaperComponent != null
@@ -389,14 +429,15 @@
         mContext = context;
         mIWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService(Context.WINDOW_SERVICE));
+        mIPackageManager = AppGlobals.getPackageManager();
         mMonitor = new MyPackageMonitor();
-        mMonitor.register(context, null, true);
-        WALLPAPER_BASE_DIR.mkdirs();
-        loadSettingsLocked(0);
+        mMonitor.register(context, null, UserHandle.ALL, true);
+        getWallpaperDir(UserHandle.USER_OWNER).mkdirs();
+        loadSettingsLocked(UserHandle.USER_OWNER);
     }
     
     private static File getWallpaperDir(int userId) {
-        return new File(WALLPAPER_BASE_DIR + "/" + userId);
+        return Environment.getUserSystemDirectory(userId);
     }
 
     @Override
@@ -410,38 +451,73 @@
 
     public void systemReady() {
         if (DEBUG) Slog.v(TAG, "systemReady");
-        WallpaperData wallpaper = mWallpaperMap.get(0);
-        switchWallpaper(wallpaper);
+        WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_OWNER);
+        switchWallpaper(wallpaper, null);
         wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
         wallpaper.wallpaperObserver.startWatching();
 
         IntentFilter userFilter = new IntentFilter();
-        userFilter.addAction(Intent.ACTION_USER_SWITCHED);
         userFilter.addAction(Intent.ACTION_USER_REMOVED);
+        userFilter.addAction(Intent.ACTION_USER_STOPPING);
         mContext.registerReceiver(new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 String action = intent.getAction();
-                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
-                    switchUser(intent.getIntExtra(Intent.EXTRA_USERID, 0));
-                } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
-                    removeUser(intent.getIntExtra(Intent.EXTRA_USERID, 0));
+                if (Intent.ACTION_USER_REMOVED.equals(action)) {
+                    onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+                            UserHandle.USER_NULL));
                 }
+                // TODO: Race condition causing problems when cleaning up on stopping a user.
+                // Comment this out for now.
+                // else if (Intent.ACTION_USER_STOPPING.equals(action)) {
+                //     onStoppingUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+                //             UserHandle.USER_NULL));
+                // }
             }
         }, userFilter);
+
+        try {
+            ActivityManagerNative.getDefault().registerUserSwitchObserver(
+                    new IUserSwitchObserver.Stub() {
+                        @Override
+                        public void onUserSwitching(int newUserId, IRemoteCallback reply) {
+                            switchUser(newUserId, reply);
+                        }
+
+                        @Override
+                        public void onUserSwitchComplete(int newUserId) throws RemoteException {
+                        }
+                    });
+        } catch (RemoteException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
     }
 
     String getName() {
-        return mWallpaperMap.get(0).name;
+        synchronized (mLock) {
+            return mWallpaperMap.get(0).name;
+        }
     }
 
-    void removeUser(int userId) {
+    void onStoppingUser(int userId) {
+        if (userId < 1) return;
         synchronized (mLock) {
             WallpaperData wallpaper = mWallpaperMap.get(userId);
             if (wallpaper != null) {
-                wallpaper.wallpaperObserver.stopWatching();
+                if (wallpaper.wallpaperObserver != null) {
+                    wallpaper.wallpaperObserver.stopWatching();
+                    wallpaper.wallpaperObserver = null;
+                }
                 mWallpaperMap.remove(userId);
             }
+        }
+    }
+
+    void onRemoveUser(int userId) {
+        if (userId < 1) return;
+        synchronized (mLock) {
+            onStoppingUser(userId);
             File wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
             wallpaperFile.delete();
             File wallpaperInfoFile = new File(getWallpaperDir(userId), WALLPAPER_INFO);
@@ -449,7 +525,7 @@
         }
     }
 
-    void switchUser(int userId) {
+    void switchUser(int userId, IRemoteCallback reply) {
         synchronized (mLock) {
             mCurrentUserId = userId;
             WallpaperData wallpaper = mWallpaperMap.get(userId);
@@ -457,38 +533,41 @@
                 wallpaper = new WallpaperData(userId);
                 mWallpaperMap.put(userId, wallpaper);
                 loadSettingsLocked(userId);
+            }
+            // Not started watching yet, in case wallpaper data was loaded for other reasons.
+            if (wallpaper.wallpaperObserver == null) {
                 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
                 wallpaper.wallpaperObserver.startWatching();
             }
-            switchWallpaper(wallpaper);
+            switchWallpaper(wallpaper, reply);
         }
     }
 
-    void switchWallpaper(WallpaperData wallpaper) {
+    void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
         synchronized (mLock) {
             RuntimeException e = null;
             try {
                 ComponentName cname = wallpaper.wallpaperComponent != null ?
                         wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
-                if (bindWallpaperComponentLocked(cname, true, false, wallpaper)) {
+                if (bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
                     return;
                 }
             } catch (RuntimeException e1) {
                 e = e1;
             }
             Slog.w(TAG, "Failure starting previous wallpaper", e);
-            clearWallpaperLocked(false, wallpaper.userId);
+            clearWallpaperLocked(false, wallpaper.userId, reply);
         }
     }
 
     public void clearWallpaper() {
         if (DEBUG) Slog.v(TAG, "clearWallpaper");
         synchronized (mLock) {
-            clearWallpaperLocked(false, UserId.getCallingUserId());
+            clearWallpaperLocked(false, UserHandle.getCallingUserId(), null);
         }
     }
 
-    void clearWallpaperLocked(boolean defaultFailed, int userId) {
+    void clearWallpaperLocked(boolean defaultFailed, int userId, IRemoteCallback reply) {
         WallpaperData wallpaper = mWallpaperMap.get(userId);
         File f = new File(getWallpaperDir(userId), WALLPAPER);
         if (f.exists()) {
@@ -500,8 +579,8 @@
             wallpaper.imageWallpaperPending = false;
             if (userId != mCurrentUserId) return;
             if (bindWallpaperComponentLocked(defaultFailed
-                    ? wallpaper.imageWallpaperComponent
-                    : null, true, false, wallpaper)) {
+                    ? IMAGE_WALLPAPER
+                    : null, true, false, wallpaper, reply)) {
                 return;
             }
         } catch (IllegalArgumentException e1) {
@@ -516,21 +595,50 @@
         // wallpaper.
         Slog.e(TAG, "Default wallpaper component not found!", e);
         clearWallpaperComponentLocked(wallpaper);
+        if (reply != null) {
+            try {
+                reply.sendResult(null);
+            } catch (RemoteException e1) {
+            }
+        }
+    }
+
+    public boolean hasNamedWallpaper(String name) {
+        synchronized (mLock) {
+            List<UserInfo> users;
+            long ident = Binder.clearCallingIdentity();
+            try {
+                users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).getUsers();
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+            for (UserInfo user: users) {
+                WallpaperData wd = mWallpaperMap.get(user.id);
+                if (wd == null) {
+                    // User hasn't started yet, so load her settings to peek at the wallpaper
+                    loadSettingsLocked(user.id);
+                    wd = mWallpaperMap.get(user.id);
+                }
+                if (wd != null && name.equals(wd.name)) {
+                    return true;
+                }
+            }
+        }
+        return false;
     }
 
     public void setDimensionHints(int width, int height) throws RemoteException {
         checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
-
-        int userId = UserId.getCallingUserId();
-        WallpaperData wallpaper = mWallpaperMap.get(userId);
-        if (wallpaper == null) {
-            throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
-        }
-        if (width <= 0 || height <= 0) {
-            throw new IllegalArgumentException("width and height must be > 0");
-        }
-
         synchronized (mLock) {
+            int userId = UserHandle.getCallingUserId();
+            WallpaperData wallpaper = mWallpaperMap.get(userId);
+            if (wallpaper == null) {
+                throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
+            }
+            if (width <= 0 || height <= 0) {
+                throw new IllegalArgumentException("width and height must be > 0");
+            }
+
             if (width != wallpaper.width || height != wallpaper.height) {
                 wallpaper.width = width;
                 wallpaper.height = height;
@@ -552,14 +660,14 @@
 
     public int getWidthHint() throws RemoteException {
         synchronized (mLock) {
-            WallpaperData wallpaper = mWallpaperMap.get(UserId.getCallingUserId());
+            WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
             return wallpaper.width;
         }
     }
 
     public int getHeightHint() throws RemoteException {
         synchronized (mLock) {
-            WallpaperData wallpaper = mWallpaperMap.get(UserId.getCallingUserId());
+            WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
             return wallpaper.height;
         }
     }
@@ -574,7 +682,7 @@
             if (callingUid == android.os.Process.SYSTEM_UID) {
                 wallpaperUserId = mCurrentUserId;
             } else {
-                wallpaperUserId = UserId.getUserId(callingUid);
+                wallpaperUserId = UserHandle.getUserId(callingUid);
             }
             WallpaperData wallpaper = mWallpaperMap.get(wallpaperUserId);
             try {
@@ -597,7 +705,7 @@
     }
 
     public WallpaperInfo getWallpaperInfo() {
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
         synchronized (mLock) {
             WallpaperData wallpaper = mWallpaperMap.get(userId);
             if (wallpaper.connection != null) {
@@ -608,14 +716,14 @@
     }
 
     public ParcelFileDescriptor setWallpaper(String name) {
-        if (DEBUG) Slog.v(TAG, "setWallpaper");
-        int userId = UserId.getCallingUserId();
-        WallpaperData wallpaper = mWallpaperMap.get(userId);
-        if (wallpaper == null) {
-            throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
-        }
         checkPermission(android.Manifest.permission.SET_WALLPAPER);
         synchronized (mLock) {
+            if (DEBUG) Slog.v(TAG, "setWallpaper");
+            int userId = UserHandle.getCallingUserId();
+            WallpaperData wallpaper = mWallpaperMap.get(userId);
+            if (wallpaper == null) {
+                throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
+            }
             final long ident = Binder.clearCallingIdentity();
             try {
                 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper);
@@ -655,18 +763,18 @@
     }
 
     public void setWallpaperComponent(ComponentName name) {
-        if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
-        int userId = UserId.getCallingUserId();
-        WallpaperData wallpaper = mWallpaperMap.get(userId);
-        if (wallpaper == null) {
-            throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
-        }
         checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
         synchronized (mLock) {
+            if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
+            int userId = UserHandle.getCallingUserId();
+            WallpaperData wallpaper = mWallpaperMap.get(userId);
+            if (wallpaper == null) {
+                throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
+            }
             final long ident = Binder.clearCallingIdentity();
             try {
                 wallpaper.imageWallpaperPending = false;
-                bindWallpaperComponentLocked(name, false, true, wallpaper);
+                bindWallpaperComponentLocked(name, false, true, wallpaper, null);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -674,7 +782,7 @@
     }
     
     boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
-            boolean fromUser, WallpaperData wallpaper) {
+            boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
         if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
         // Has the component changed?
         if (!force) {
@@ -704,14 +812,15 @@
                 }
                 if (componentName == null) {
                     // Fall back to static image wallpaper
-                    componentName = wallpaper.imageWallpaperComponent;
+                    componentName = IMAGE_WALLPAPER;
                     //clearWallpaperComponentLocked();
                     //return;
                     if (DEBUG) Slog.v(TAG, "Using image wallpaper");
                 }
             }
-            ServiceInfo si = mContext.getPackageManager().getServiceInfo(componentName,
-                    PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS);
+            int serviceUserId = wallpaper.userId;
+            ServiceInfo si = mIPackageManager.getServiceInfo(componentName,
+                    PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId);
             if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
                 String msg = "Selected service does not require "
                         + android.Manifest.permission.BIND_WALLPAPER
@@ -726,10 +835,12 @@
             WallpaperInfo wi = null;
             
             Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
-            if (componentName != null && !componentName.equals(wallpaper.imageWallpaperComponent)) {
+            if (componentName != null && !componentName.equals(IMAGE_WALLPAPER)) {
                 // Make sure the selected service is actually a wallpaper service.
-                List<ResolveInfo> ris = mContext.getPackageManager()
-                        .queryIntentServices(intent, PackageManager.GET_META_DATA);
+                List<ResolveInfo> ris =
+                        mIPackageManager.queryIntentServices(intent,
+                                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                                PackageManager.GET_META_DATA, serviceUserId);
                 for (int i=0; i<ris.size(); i++) {
                     ServiceInfo rsi = ris.get(i).serviceInfo;
                     if (rsi.name.equals(si.name) &&
@@ -767,18 +878,13 @@
             if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
             WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);
             intent.setComponent(componentName);
-            int serviceUserId = wallpaper.userId;
-            // Because the image wallpaper is running in the system ui
-            if (componentName.equals(wallpaper.imageWallpaperComponent)) {
-                serviceUserId = 0;
-            }
             intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
                     com.android.internal.R.string.wallpaper_binding_label);
-            intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+            intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
                     mContext, 0,
                     Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
                             mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
-                            0));
+                    0, null, new UserHandle(serviceUserId)));
             if (!mContext.bindService(intent, newConn, Context.BIND_AUTO_CREATE, serviceUserId)) {
                 String msg = "Unable to bind service: "
                         + componentName;
@@ -794,6 +900,7 @@
             wallpaper.wallpaperComponent = componentName;
             wallpaper.connection = newConn;
             wallpaper.lastDiedTime = SystemClock.uptimeMillis();
+            newConn.mReply = reply;
             try {
                 if (wallpaper.userId == mCurrentUserId) {
                     if (DEBUG)
@@ -804,8 +911,8 @@
                 }
             } catch (RemoteException e) {
             }
-        } catch (PackageManager.NameNotFoundException e) {
-            String msg = "Unknown component " + componentName;
+        } catch (RemoteException e) {
+            String msg = "Remote exception for " + componentName + "\n" + e;
             if (fromUser) {
                 throw new IllegalArgumentException(msg);
             }
@@ -817,6 +924,13 @@
 
     void detachWallpaperLocked(WallpaperData wallpaper) {
         if (wallpaper.connection != null) {
+            if (wallpaper.connection.mReply != null) {
+                try {
+                    wallpaper.connection.mReply.sendResult(null);
+                } catch (RemoteException e) {
+                }
+                wallpaper.connection.mReply = null;
+            }
             if (wallpaper.connection.mEngine != null) {
                 try {
                     wallpaper.connection.mEngine.destroy();
@@ -849,7 +963,7 @@
         } catch (RemoteException e) {
             Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
             if (!wallpaper.wallpaperUpdating) {
-                bindWallpaperComponentLocked(null, false, false, wallpaper);
+                bindWallpaperComponentLocked(null, false, false, wallpaper, null);
             }
         }
     }
@@ -867,7 +981,7 @@
         }
         wallpaper.callbacks.finishBroadcast();
         final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
-        mContext.sendBroadcast(intent);
+        mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
     }
 
     private void checkPermission(String permission) {
@@ -878,7 +992,7 @@
     }
 
     private static JournaledFile makeJournaledFile(int userId) {
-        final String base = getWallpaperDir(userId) + "/" + WALLPAPER_INFO;
+        final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
         return new JournaledFile(new File(base), new File(base + ".tmp"));
     }
 
@@ -896,7 +1010,7 @@
             out.attribute(null, "height", Integer.toString(wallpaper.height));
             out.attribute(null, "name", wallpaper.name);
             if (wallpaper.wallpaperComponent != null
-                    && !wallpaper.wallpaperComponent.equals(wallpaper.imageWallpaperComponent)) {
+                    && !wallpaper.wallpaperComponent.equals(IMAGE_WALLPAPER)) {
                 out.attribute(null, "component",
                         wallpaper.wallpaperComponent.flattenToShortString());
             }
@@ -968,7 +1082,7 @@
                         if (wallpaper.nextWallpaperComponent == null
                                 || "android".equals(wallpaper.nextWallpaperComponent
                                         .getPackageName())) {
-                            wallpaper.nextWallpaperComponent = wallpaper.imageWallpaperComponent;
+                            wallpaper.nextWallpaperComponent = IMAGE_WALLPAPER;
                         }
                           
                         if (DEBUG) {
@@ -1030,13 +1144,13 @@
             loadSettingsLocked(0);
             wallpaper = mWallpaperMap.get(0);
             if (wallpaper.nextWallpaperComponent != null
-                    && !wallpaper.nextWallpaperComponent.equals(wallpaper.imageWallpaperComponent)) {
+                    && !wallpaper.nextWallpaperComponent.equals(IMAGE_WALLPAPER)) {
                 if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
-                        wallpaper)) {
+                        wallpaper, null)) {
                     // No such live wallpaper or other failure; fall back to the default
                     // live wallpaper (since the profile being restored indicated that the
                     // user had selected a live rather than static one).
-                    bindWallpaperComponentLocked(null, false, false, wallpaper);
+                    bindWallpaperComponentLocked(null, false, false, wallpaper, null);
                 }
                 success = true;
             } else {
@@ -1052,7 +1166,7 @@
                 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success);
                 if (success) {
                     bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
-                            wallpaper);
+                            wallpaper, null);
                 }
             }
         }
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index c239382..8bbf923 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import com.android.server.am.ActivityManagerService;
+import com.android.server.power.PowerManagerService;
 
 import android.app.AlarmManager;
 import android.app.PendingIntent;
@@ -25,6 +26,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.os.BatteryManager;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.Message;
@@ -32,7 +34,6 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.provider.Settings;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
@@ -117,9 +118,7 @@
                 case MONITOR: {
                     // See if we should force a reboot.
                     int rebootInterval = mReqRebootInterval >= 0
-                            ? mReqRebootInterval : Settings.Secure.getInt(
-                            mResolver, Settings.Secure.REBOOT_INTERVAL,
-                            REBOOT_DEFAULT_INTERVAL);
+                            ? mReqRebootInterval : REBOOT_DEFAULT_INTERVAL;
                     if (mRebootInterval != rebootInterval) {
                         mRebootInterval = rebootInterval;
                         // We have been running long enough that a reboot can
@@ -225,9 +224,7 @@
 
     void checkReboot(boolean fromAlarm) {
         int rebootInterval = mReqRebootInterval >= 0 ? mReqRebootInterval
-                : Settings.Secure.getInt(
-                mResolver, Settings.Secure.REBOOT_INTERVAL,
-                REBOOT_DEFAULT_INTERVAL);
+                : REBOOT_DEFAULT_INTERVAL;
         mRebootInterval = rebootInterval;
         if (rebootInterval <= 0) {
             // No reboot interval requested.
@@ -237,17 +234,11 @@
         }
 
         long rebootStartTime = mReqRebootStartTime >= 0 ? mReqRebootStartTime
-                : Settings.Secure.getLong(
-                mResolver, Settings.Secure.REBOOT_START_TIME,
-                REBOOT_DEFAULT_START_TIME);
+                : REBOOT_DEFAULT_START_TIME;
         long rebootWindowMillis = (mReqRebootWindow >= 0 ? mReqRebootWindow
-                : Settings.Secure.getLong(
-                mResolver, Settings.Secure.REBOOT_WINDOW,
-                REBOOT_DEFAULT_WINDOW)) * 1000;
+                : REBOOT_DEFAULT_WINDOW) * 1000;
         long recheckInterval = (mReqRecheckInterval >= 0 ? mReqRecheckInterval
-                : Settings.Secure.getLong(
-                mResolver, Settings.Secure.MEMCHECK_RECHECK_INTERVAL,
-                MEMCHECK_DEFAULT_RECHECK_INTERVAL)) * 1000;
+                : MEMCHECK_DEFAULT_RECHECK_INTERVAL) * 1000;
 
         retrieveBrutalityAmount();
 
@@ -314,7 +305,7 @@
     void rebootSystem(String reason) {
         Slog.i(TAG, "Rebooting system because: " + reason);
         PowerManagerService pms = (PowerManagerService) ServiceManager.getService("power");
-        pms.reboot(reason);
+        pms.reboot(false, reason, false);
     }
 
     /**
@@ -324,13 +315,9 @@
      */
     void retrieveBrutalityAmount() {
         mMinScreenOff = (mReqMinScreenOff >= 0 ? mReqMinScreenOff
-                : Settings.Secure.getInt(
-                mResolver, Settings.Secure.MEMCHECK_MIN_SCREEN_OFF,
-                MEMCHECK_DEFAULT_MIN_SCREEN_OFF)) * 1000;
+                : MEMCHECK_DEFAULT_MIN_SCREEN_OFF) * 1000;
         mMinAlarm = (mReqMinNextAlarm >= 0 ? mReqMinNextAlarm
-                : Settings.Secure.getInt(
-                mResolver, Settings.Secure.MEMCHECK_MIN_ALARM,
-                MEMCHECK_DEFAULT_MIN_ALARM)) * 1000;
+                : MEMCHECK_DEFAULT_MIN_ALARM) * 1000;
     }
 
     /**
@@ -343,12 +330,12 @@
      * text of why it is not a good time.
      */
     String shouldWeBeBrutalLocked(long curTime) {
-        if (mBattery == null || !mBattery.isPowered()) {
+        if (mBattery == null || !mBattery.isPowered(BatteryManager.BATTERY_PLUGGED_ANY)) {
             return "battery";
         }
 
         if (mMinScreenOff >= 0 && (mPower == null ||
-                mPower.timeSinceScreenOn() < mMinScreenOff)) {
+                mPower.timeSinceScreenWasLastOn() < mMinScreenOff)) {
             return "screen";
         }
 
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 1f03d17..98794c9 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -16,10 +16,12 @@
 
 package com.android.server;
 
+import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.app.TaskStackBuilder;
 import android.bluetooth.BluetoothAdapter;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -55,9 +57,11 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.Log;
 import android.util.Slog;
 
 import java.util.ArrayList;
@@ -110,10 +114,6 @@
     private int mScanLocksAcquired;
     private int mScanLocksReleased;
 
-    /* A mapping from UID to scan count */
-    private HashMap<Integer, Integer> mScanCount =
-            new HashMap<Integer, Integer>();
-
     private final List<Multicaster> mMulticasters =
             new ArrayList<Multicaster>();
     private int mMulticastEnabled;
@@ -136,8 +136,8 @@
     private static final int POLL_TRAFFIC_STATS_INTERVAL_MSECS = 1000;
 
     /**
-     * See {@link Settings.Secure#WIFI_IDLE_MS}. This is the default value if a
-     * Settings.Secure value is not present. This timeout value is chosen as
+     * See {@link Settings.Global#WIFI_IDLE_MS}. This is the default value if a
+     * Settings.Global value is not present. This timeout value is chosen as
      * the approximate point at which the battery drain caused by Wi-Fi
      * being enabled but not active exceeds the battery drain caused by
      * re-establishing a connection to the mobile data network.
@@ -161,6 +161,10 @@
     /* Tracks whether wifi is enabled from WifiStateMachine's perspective */
     private boolean mWifiEnabled;
 
+    /* The work source (UID) that triggered the current WIFI scan, synchronized
+     * on this */
+    private WorkSource mScanWorkSource;
+
     private boolean mIsReceiverRegistered = false;
 
 
@@ -239,7 +243,7 @@
             switch (msg.what) {
                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
                     if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
-                        Slog.d(TAG, "New client listening to asynchronous messages");
+                        if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
                         mClients.add((AsyncChannel) msg.obj);
                     } else {
                         Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
@@ -248,9 +252,9 @@
                 }
                 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
                     if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
-                        Slog.d(TAG, "Send failed, client connection lost");
+                        if (DBG) Slog.d(TAG, "Send failed, client connection lost");
                     } else {
-                        Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
+                        if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
                     }
                     mClients.remove((AsyncChannel) msg.obj);
                     break;
@@ -302,6 +306,10 @@
                     mWifiStateMachine.sendMessage(Message.obtain(msg));
                     break;
                 }
+                case WifiManager.RSSI_PKTCNT_FETCH: {
+                    mWifiStateMachine.sendMessage(Message.obtain(msg));
+                    break;
+                }
                 default: {
                     Slog.d(TAG, "WifiServicehandler.handleMessage ignoring msg=" + msg);
                     break;
@@ -407,12 +415,14 @@
                             switch(mNetworkInfo.getDetailedState()) {
                                 case CONNECTED:
                                 case DISCONNECTED:
+                                case CAPTIVE_PORTAL_CHECK:
                                     evaluateTrafficStatsPolling();
                                     resetNotification();
                                     break;
                             }
                         } else if (intent.getAction().equals(
                                 WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
+                            noteScanEnd();
                             checkAndSetNotification();
                         }
                     }
@@ -424,12 +434,50 @@
         mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());
 
         // Setting is in seconds
-        NOTIFICATION_REPEAT_DELAY_MS = Settings.Secure.getInt(context.getContentResolver(),
-                Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, 900) * 1000l;
+        NOTIFICATION_REPEAT_DELAY_MS = Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, 900) * 1000l;
         mNotificationEnabledSettingObserver = new NotificationEnabledSettingObserver(new Handler());
         mNotificationEnabledSettingObserver.register();
     }
 
+    /** Tell battery stats about a new WIFI scan */
+    private void noteScanStart() {
+        WorkSource scanWorkSource = null;
+        synchronized (WifiService.this) {
+            if (mScanWorkSource != null) {
+                // Scan already in progress, don't add this one to battery stats
+                return;
+            }
+            scanWorkSource = new WorkSource(Binder.getCallingUid());
+            mScanWorkSource = scanWorkSource;
+        }
+
+        long id = Binder.clearCallingIdentity();
+        try {
+            mBatteryStats.noteWifiScanStartedFromSource(scanWorkSource);
+        } catch (RemoteException e) {
+            Log.w(TAG, e);
+        } finally {
+            Binder.restoreCallingIdentity(id);
+        }
+    }
+
+    /** Tell battery stats that the current WIFI scan has completed */
+    private void noteScanEnd() {
+        WorkSource scanWorkSource = null;
+        synchronized (WifiService.this) {
+            scanWorkSource = mScanWorkSource;
+            mScanWorkSource = null;
+        }
+        if (scanWorkSource != null) {
+            try {
+                mBatteryStats.noteWifiScanStoppedFromSource(scanWorkSource);
+            } catch (RemoteException e) {
+                Log.w(TAG, e);
+            }
+        }
+    }
+
     /**
      * Check if Wi-Fi needs to be enabled and start
      * if needed
@@ -457,9 +505,9 @@
         final ContentResolver cr = mContext.getContentResolver();
         int wifiSavedState = 0;
         try {
-            wifiSavedState = Settings.Secure.getInt(cr, Settings.Secure.WIFI_SAVED_STATE);
+            wifiSavedState = Settings.Global.getInt(cr, Settings.Global.WIFI_SAVED_STATE);
             if(wifiSavedState == 1)
-                Settings.Secure.putInt(cr, Settings.Secure.WIFI_SAVED_STATE, 0);
+                Settings.Global.putInt(cr, Settings.Global.WIFI_SAVED_STATE, 0);
         } catch (Settings.SettingNotFoundException e) {
             ;
         }
@@ -469,9 +517,9 @@
     private int getPersistedWifiState() {
         final ContentResolver cr = mContext.getContentResolver();
         try {
-            return Settings.Secure.getInt(cr, Settings.Secure.WIFI_ON);
+            return Settings.Global.getInt(cr, Settings.Global.WIFI_ON);
         } catch (Settings.SettingNotFoundException e) {
-            Settings.Secure.putInt(cr, Settings.Secure.WIFI_ON, WIFI_DISABLED);
+            Settings.Global.putInt(cr, Settings.Global.WIFI_ON, WIFI_DISABLED);
             return WIFI_DISABLED;
         }
     }
@@ -519,7 +567,7 @@
     private void persistWifiState(int state) {
         final ContentResolver cr = mContext.getContentResolver();
         mPersistWifiState.set(state);
-        Settings.Secure.putInt(cr, Settings.Secure.WIFI_ON, state);
+        Settings.Global.putInt(cr, Settings.Global.WIFI_ON, state);
     }
 
     /**
@@ -541,16 +589,8 @@
      */
     public void startScan(boolean forceActive) {
         enforceChangePermission();
-
-        int uid = Binder.getCallingUid();
-        int count = 0;
-        synchronized (mScanCount) {
-            if (mScanCount.containsKey(uid)) {
-                count = mScanCount.get(uid);
-            }
-            mScanCount.put(uid, ++count);
-        }
         mWifiStateMachine.startScan(forceActive);
+        noteScanStart();
     }
 
     private void enforceAccessPermission() {
@@ -570,6 +610,12 @@
                 "WifiService");
     }
 
+    private void enforceConnectivityInternalPermission() {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.CONNECTIVITY_INTERNAL,
+                "ConnectivityService");
+    }
+
     /**
      * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)}
      * @param enable {@code true} to enable, {@code false} to disable.
@@ -595,8 +641,11 @@
          */
 
         long ident = Binder.clearCallingIdentity();
-        handleWifiToggled(enable);
-        Binder.restoreCallingIdentity(ident);
+        try {
+            handleWifiToggled(enable);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
 
         if (enable) {
             if (!mIsReceiverRegistered) {
@@ -791,7 +840,18 @@
      */
     public List<ScanResult> getScanResults() {
         enforceAccessPermission();
-        return mWifiStateMachine.syncGetScanResultsList();
+        int userId = UserHandle.getCallingUserId();
+        long ident = Binder.clearCallingIdentity();
+        try {
+            int currentUser = ActivityManager.getCurrentUser();
+            if (userId != currentUser) {
+                return new ArrayList<ScanResult>();
+            } else {
+                return mWifiStateMachine.syncGetScanResultsList();
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
     }
 
     /**
@@ -874,7 +934,7 @@
      *
      */
     public void startWifi() {
-        enforceChangePermission();
+        enforceConnectivityInternalPermission();
         /* TODO: may be add permissions for access only to connectivity service
          * TODO: if a start issued, keep wifi alive until a stop issued irrespective
          * of WifiLock & device idle status unless wifi enabled status is toggled
@@ -884,20 +944,24 @@
         mWifiStateMachine.reconnectCommand();
     }
 
+    public void captivePortalCheckComplete() {
+        enforceConnectivityInternalPermission();
+        mWifiStateMachine.captivePortalCheckComplete();
+    }
+
     /**
      * see {@link android.net.wifi.WifiManager#stopWifi}
      *
      */
     public void stopWifi() {
-        enforceChangePermission();
-        /* TODO: may be add permissions for access only to connectivity service
+        enforceConnectivityInternalPermission();
+        /*
          * TODO: if a stop is issued, wifi is brought up only by startWifi
          * unless wifi enabled status is toggled
          */
         mWifiStateMachine.setDriverStart(false, mEmergencyCallbackMode);
     }
 
-
     /**
      * see {@link android.net.wifi.WifiManager#addToBlacklist}
      *
@@ -923,10 +987,6 @@
      * an AsyncChannel communication with WifiService
      */
     public Messenger getWifiServiceMessenger() {
-        /* Enforce the highest permissions
-           TODO: when we consider exposing the asynchronous API, think about
-                 how to provide both access and change permissions seperately
-         */
         enforceAccessPermission();
         enforceChangePermission();
         return new Messenger(mAsyncServiceHandler);
@@ -953,11 +1013,11 @@
             String action = intent.getAction();
 
             long idleMillis =
-                Settings.Secure.getLong(mContext.getContentResolver(),
-                                        Settings.Secure.WIFI_IDLE_MS, DEFAULT_IDLE_MS);
+                Settings.Global.getLong(mContext.getContentResolver(),
+                                        Settings.Global.WIFI_IDLE_MS, DEFAULT_IDLE_MS);
             int stayAwakeConditions =
-                Settings.System.getInt(mContext.getContentResolver(),
-                                       Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0);
+                Settings.Global.getInt(mContext.getContentResolver(),
+                                       Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
             if (action.equals(Intent.ACTION_SCREEN_ON)) {
                 if (DBG) {
                     Slog.d(TAG, "ACTION_SCREEN_ON");
@@ -1011,12 +1071,6 @@
                     mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
                 }
 
-                //Start scan stats tracking when device unplugged
-                if (pluggedType == 0) {
-                    synchronized (mScanCount) {
-                        mScanCount.clear();
-                    }
-                }
                 mPluggedType = pluggedType;
             } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
                 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
@@ -1037,14 +1091,14 @@
          */
         private boolean shouldWifiStayAwake(int stayAwakeConditions, int pluggedType) {
             //Never sleep as long as the user has not changed the settings
-            int wifiSleepPolicy = Settings.System.getInt(mContext.getContentResolver(),
-                    Settings.System.WIFI_SLEEP_POLICY,
-                    Settings.System.WIFI_SLEEP_POLICY_NEVER);
+            int wifiSleepPolicy = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.WIFI_SLEEP_POLICY,
+                    Settings.Global.WIFI_SLEEP_POLICY_NEVER);
 
-            if (wifiSleepPolicy == Settings.System.WIFI_SLEEP_POLICY_NEVER) {
+            if (wifiSleepPolicy == Settings.Global.WIFI_SLEEP_POLICY_NEVER) {
                 // Never sleep
                 return true;
-            } else if ((wifiSleepPolicy == Settings.System.WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED) &&
+            } else if ((wifiSleepPolicy == Settings.Global.WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED) &&
                     (pluggedType != 0)) {
                 // Never sleep while plugged, and we're plugged
                 return true;
@@ -1142,17 +1196,17 @@
     }
 
     private boolean isAirplaneSensitive() {
-        String airplaneModeRadios = Settings.System.getString(mContext.getContentResolver(),
-                Settings.System.AIRPLANE_MODE_RADIOS);
+        String airplaneModeRadios = Settings.Global.getString(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_RADIOS);
         return airplaneModeRadios == null
-            || airplaneModeRadios.contains(Settings.System.RADIO_WIFI);
+            || airplaneModeRadios.contains(Settings.Global.RADIO_WIFI);
     }
 
     private boolean isAirplaneToggleable() {
-        String toggleableRadios = Settings.System.getString(mContext.getContentResolver(),
-                Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
+        String toggleableRadios = Settings.Global.getString(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
         return toggleableRadios != null
-            && toggleableRadios.contains(Settings.System.RADIO_WIFI);
+            && toggleableRadios.contains(Settings.Global.RADIO_WIFI);
     }
 
     /**
@@ -1161,8 +1215,8 @@
      * @return {@code true} if airplane mode is on.
      */
     private boolean isAirplaneModeOn() {
-        return isAirplaneSensitive() && Settings.System.getInt(mContext.getContentResolver(),
-                Settings.System.AIRPLANE_MODE_ON, 0) == 1;
+        return isAirplaneSensitive() && Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
     }
 
     @Override
@@ -1176,8 +1230,8 @@
         }
         pw.println("Wi-Fi is " + mWifiStateMachine.syncGetWifiStateByName());
         pw.println("Stay-awake conditions: " +
-                Settings.System.getInt(mContext.getContentResolver(),
-                                       Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0));
+                Settings.Global.getInt(mContext.getContentResolver(),
+                                       Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0));
         pw.println();
 
         pw.println("Internal state:");
@@ -1207,13 +1261,6 @@
         pw.println("Locks held:");
         mLocks.dump(pw);
 
-        pw.println("Scan count since last plugged in");
-        synchronized (mScanCount) {
-            for(int sc : mScanCount.keySet()) {
-                pw.println("UID: " + sc + " Scan count: " + mScanCount.get(sc));
-            }
-        }
-
         pw.println();
         pw.println("WifiWatchdogStateMachine dump");
         mWifiWatchdogStateMachine.dump(pw);
@@ -1333,10 +1380,8 @@
         switch(wifiLock.mMode) {
             case WifiManager.WIFI_MODE_FULL:
             case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
-                mBatteryStats.noteFullWifiLockAcquiredFromSource(wifiLock.mWorkSource);
-                break;
             case WifiManager.WIFI_MODE_SCAN_ONLY:
-                mBatteryStats.noteScanWifiLockAcquiredFromSource(wifiLock.mWorkSource);
+                mBatteryStats.noteFullWifiLockAcquiredFromSource(wifiLock.mWorkSource);
                 break;
         }
     }
@@ -1345,10 +1390,8 @@
         switch(wifiLock.mMode) {
             case WifiManager.WIFI_MODE_FULL:
             case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
-                mBatteryStats.noteFullWifiLockReleasedFromSource(wifiLock.mWorkSource);
-                break;
             case WifiManager.WIFI_MODE_SCAN_ONLY:
-                mBatteryStats.noteScanWifiLockReleasedFromSource(wifiLock.mWorkSource);
+                mBatteryStats.noteFullWifiLockReleasedFromSource(wifiLock.mWorkSource);
                 break;
         }
     }
@@ -1724,8 +1767,10 @@
                 mNotification.when = 0;
                 mNotification.icon = ICON_NETWORKS_AVAILABLE;
                 mNotification.flags = Notification.FLAG_AUTO_CANCEL;
-                mNotification.contentIntent = PendingIntent.getActivity(mContext, 0,
-                        new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK), 0);
+                mNotification.contentIntent = TaskStackBuilder.create(mContext)
+                        .addNextIntentWithParentStack(
+                                new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK))
+                        .getPendingIntent(0, 0, null, UserHandle.CURRENT);
             }
 
             CharSequence title = mContext.getResources().getQuantityText(
@@ -1737,9 +1782,10 @@
 
             mNotificationRepeatTime = System.currentTimeMillis() + NOTIFICATION_REPEAT_DELAY_MS;
 
-            notificationManager.notify(ICON_NETWORKS_AVAILABLE, mNotification);
+            notificationManager.notifyAsUser(null, ICON_NETWORKS_AVAILABLE, mNotification,
+                    UserHandle.ALL);
         } else {
-            notificationManager.cancel(ICON_NETWORKS_AVAILABLE);
+            notificationManager.cancelAsUser(null, ICON_NETWORKS_AVAILABLE, UserHandle.ALL);
         }
 
         mNotificationShown = visible;
@@ -1753,8 +1799,8 @@
 
         public void register() {
             ContentResolver cr = mContext.getContentResolver();
-            cr.registerContentObserver(Settings.Secure.getUriFor(
-                Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON), true, this);
+            cr.registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON), true, this);
             mNotificationEnabled = getValue();
         }
 
@@ -1767,8 +1813,8 @@
         }
 
         private boolean getValue() {
-            return Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1) == 1;
+            return Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1) == 1;
         }
     }
 
diff --git a/services/java/com/android/server/WiredAccessoryManager.java b/services/java/com/android/server/WiredAccessoryManager.java
new file mode 100644
index 0000000..d5c9c8f
--- /dev/null
+++ b/services/java/com/android/server/WiredAccessoryManager.java
@@ -0,0 +1,432 @@
+/*
+ * 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.
+ */
+
+package com.android.server;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import android.os.UEventObserver;
+import android.util.Slog;
+import android.media.AudioManager;
+import android.util.Log;
+import android.view.InputDevice;
+
+import com.android.internal.R;
+import com.android.server.input.InputManagerService;
+import com.android.server.input.InputManagerService.WiredAccessoryCallbacks;
+import static com.android.server.input.InputManagerService.SW_HEADPHONE_INSERT;
+import static com.android.server.input.InputManagerService.SW_MICROPHONE_INSERT;
+import static com.android.server.input.InputManagerService.SW_HEADPHONE_INSERT_BIT;
+import static com.android.server.input.InputManagerService.SW_MICROPHONE_INSERT_BIT;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p>WiredAccessoryManager monitors for a wired headset on the main board or dock using
+ * both the InputManagerService notifyWiredAccessoryChanged interface and the UEventObserver
+ * subsystem.
+ */
+final class WiredAccessoryManager implements WiredAccessoryCallbacks {
+    private static final String TAG = WiredAccessoryManager.class.getSimpleName();
+    private static final boolean LOG = true;
+
+    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);
+    private static final int BIT_USB_HEADSET_DGTL = (1 << 3);
+    private static final int BIT_HDMI_AUDIO = (1 << 4);
+    private static final int SUPPORTED_HEADSETS = (BIT_HEADSET|BIT_HEADSET_NO_MIC|
+                                                   BIT_USB_HEADSET_ANLG|BIT_USB_HEADSET_DGTL|
+                                                   BIT_HDMI_AUDIO);
+
+    private static final String NAME_H2W = "h2w";
+    private static final String NAME_USB_AUDIO = "usb_audio";
+    private static final String NAME_HDMI_AUDIO = "hdmi_audio";
+    private static final String NAME_HDMI = "hdmi";
+
+    private static final int MSG_NEW_DEVICE_STATE = 1;
+
+    private final Object mLock = new Object();
+
+    private final WakeLock mWakeLock;  // held while there is a pending route change
+    private final AudioManager mAudioManager;
+
+    private int mHeadsetState;
+
+    private int mSwitchValues;
+
+    private final WiredAccessoryObserver mObserver;
+    private final InputManagerService mInputManager;
+
+    private final boolean mUseDevInputEventForAudioJack;
+
+    public WiredAccessoryManager(Context context, InputManagerService inputManager) {
+        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryManager");
+        mWakeLock.setReferenceCounted(false);
+        mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
+        mInputManager = inputManager;
+
+        mUseDevInputEventForAudioJack =
+                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
+
+        mObserver = new WiredAccessoryObserver();
+
+        context.registerReceiver(new BroadcastReceiver() {
+                    @Override
+                    public void onReceive(Context ctx, Intent intent) {
+                        bootCompleted();
+                    }
+                },
+                new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
+    }
+
+    private void bootCompleted() {
+        if (mUseDevInputEventForAudioJack) {
+            int switchValues = 0;
+            if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_HEADPHONE_INSERT) == 1) {
+                switchValues |= SW_HEADPHONE_INSERT_BIT;
+            }
+            if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_MICROPHONE_INSERT) == 1) {
+                switchValues |= SW_MICROPHONE_INSERT_BIT;
+            }
+            notifyWiredAccessoryChanged(0, switchValues,
+                    SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT);
+        }
+
+        mObserver.init();
+    }
+
+    @Override
+    public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask) {
+        if (LOG) Slog.v(TAG, "notifyWiredAccessoryChanged: when=" + whenNanos
+                + " bits=" + switchCodeToString(switchValues, switchMask)
+                + " mask=" + Integer.toHexString(switchMask));
+
+        synchronized (mLock) {
+            int headset;
+            mSwitchValues = (mSwitchValues & ~switchMask) | switchValues;
+            switch (mSwitchValues & (SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT)) {
+                case 0:
+                    headset = 0;
+                    break;
+
+                case SW_HEADPHONE_INSERT_BIT:
+                    headset = BIT_HEADSET_NO_MIC;
+                    break;
+
+                case SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT:
+                    headset = BIT_HEADSET;
+                    break;
+
+                case SW_MICROPHONE_INSERT_BIT:
+                    headset = BIT_HEADSET;
+                    break;
+
+                default:
+                    headset = 0;
+                    break;
+            }
+
+            updateLocked(NAME_H2W, (mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC)) | headset);
+        }
+    }
+
+    /**
+     * Compare the existing headset state with the new state and pass along accordingly. Note
+     * that this only supports a single headset at a time. Inserting both a usb and jacked headset
+     * results in support for the last one plugged in. Similarly, unplugging either is seen as
+     * unplugging all.
+     *
+     * @param newName One of the NAME_xxx variables defined above.
+     * @param newState 0 or one of the BIT_xxx variables defined above.
+     */
+    private void updateLocked(String newName, int newState) {
+        // Retain only relevant bits
+        int headsetState = newState & SUPPORTED_HEADSETS;
+        int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG;
+        int usb_headset_dgtl = headsetState & BIT_USB_HEADSET_DGTL;
+        int h2w_headset = headsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC);
+        boolean h2wStateChange = true;
+        boolean usbStateChange = true;
+        if (LOG) Slog.v(TAG, "newName=" + newName
+                + " newState=" + newState
+                + " headsetState=" + headsetState
+                + " prev headsetState=" + mHeadsetState);
+
+        if (mHeadsetState == headsetState) {
+            Log.e(TAG, "No state change.");
+            return;
+        }
+
+        // reject all suspect transitions: only accept state changes from:
+        // - a: 0 headset to 1 headset
+        // - b: 1 headset to 0 headset
+        if (h2w_headset == (BIT_HEADSET | BIT_HEADSET_NO_MIC)) {
+            Log.e(TAG, "Invalid combination, unsetting h2w flag");
+            h2wStateChange = false;
+        }
+        // - c: 0 usb headset to 1 usb headset
+        // - d: 1 usb headset to 0 usb headset
+        if (usb_headset_anlg == BIT_USB_HEADSET_ANLG && usb_headset_dgtl == BIT_USB_HEADSET_DGTL) {
+            Log.e(TAG, "Invalid combination, unsetting usb flag");
+            usbStateChange = false;
+        }
+        if (!h2wStateChange && !usbStateChange) {
+            Log.e(TAG, "invalid transition, returning ...");
+            return;
+        }
+
+        mWakeLock.acquire();
+
+        Message msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState,
+                mHeadsetState, newName);
+        mHandler.sendMessage(msg);
+
+        mHeadsetState = headsetState;
+    }
+
+    private final Handler mHandler = new Handler(Looper.myLooper(), null, true) {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_NEW_DEVICE_STATE:
+                    setDevicesState(msg.arg1, msg.arg2, (String)msg.obj);
+                    mWakeLock.release();
+            }
+        }
+    };
+
+    private void setDevicesState(
+            int headsetState, int prevHeadsetState, String headsetName) {
+        synchronized (mLock) {
+            int allHeadsets = SUPPORTED_HEADSETS;
+            for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {
+                if ((curHeadset & allHeadsets) != 0) {
+                    setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName);
+                    allHeadsets &= ~curHeadset;
+                }
+            }
+        }
+    }
+
+    private void setDeviceStateLocked(int headset,
+            int headsetState, int prevHeadsetState, String headsetName) {
+        if ((headsetState & headset) != (prevHeadsetState & headset)) {
+            int device;
+            int state;
+
+            if ((headsetState & headset) != 0) {
+                state = 1;
+            } else {
+                state = 0;
+            }
+
+            if (headset == BIT_HEADSET) {
+                device = AudioManager.DEVICE_OUT_WIRED_HEADSET;
+            } else if (headset == BIT_HEADSET_NO_MIC){
+                device = AudioManager.DEVICE_OUT_WIRED_HEADPHONE;
+            } else if (headset == BIT_USB_HEADSET_ANLG) {
+                device = AudioManager.DEVICE_OUT_ANLG_DOCK_HEADSET;
+            } else if (headset == BIT_USB_HEADSET_DGTL) {
+                device = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET;
+            } else if (headset == BIT_HDMI_AUDIO) {
+                device = AudioManager.DEVICE_OUT_AUX_DIGITAL;
+            } else {
+                Slog.e(TAG, "setDeviceState() invalid headset type: "+headset);
+                return;
+            }
+
+            if (LOG)
+                Slog.v(TAG, "device "+headsetName+((state == 1) ? " connected" : " disconnected"));
+
+            mAudioManager.setWiredDeviceConnectionState(device, state, headsetName);
+        }
+    }
+
+    private String switchCodeToString(int switchValues, int switchMask) {
+        StringBuffer sb = new StringBuffer();
+        if ((switchMask & SW_HEADPHONE_INSERT_BIT) != 0 &&
+                (switchValues & SW_HEADPHONE_INSERT_BIT) != 0) {
+            sb.append("SW_HEADPHONE_INSERT ");
+        }
+        if ((switchMask & SW_MICROPHONE_INSERT_BIT) != 0 &&
+                (switchValues & SW_MICROPHONE_INSERT_BIT) != 0) {
+            sb.append("SW_MICROPHONE_INSERT");
+        }
+        return sb.toString();
+    }
+
+    class WiredAccessoryObserver extends UEventObserver {
+        private final List<UEventInfo> mUEventInfo;
+
+        public WiredAccessoryObserver() {
+            mUEventInfo = makeObservedUEventList();
+        }
+
+        void init() {
+            synchronized (mLock) {
+                if (LOG) Slog.v(TAG, "init()");
+                char[] buffer = new char[1024];
+
+                for (int i = 0; i < mUEventInfo.size(); ++i) {
+                    UEventInfo uei = mUEventInfo.get(i);
+                    try {
+                        int curState;
+                        FileReader file = new FileReader(uei.getSwitchStatePath());
+                        int len = file.read(buffer, 0, 1024);
+                        file.close();
+                        curState = Integer.valueOf((new String(buffer, 0, len)).trim());
+
+                        if (curState > 0) {
+                            updateStateLocked(uei.getDevPath(), uei.getDevName(), curState);
+                        }
+                    } catch (FileNotFoundException e) {
+                        Slog.w(TAG, uei.getSwitchStatePath() +
+                                " not found while attempting to determine initial switch state");
+                    } catch (Exception e) {
+                        Slog.e(TAG, "" , e);
+                    }
+                }
+            }
+
+            // At any given time accessories could be inserted
+            // one on the board, one on the dock and one on HDMI:
+            // observe three UEVENTs
+            for (int i = 0; i < mUEventInfo.size(); ++i) {
+                UEventInfo uei = mUEventInfo.get(i);
+                startObserving("DEVPATH="+uei.getDevPath());
+            }
+        }
+
+        private List<UEventInfo> makeObservedUEventList() {
+            List<UEventInfo> retVal = new ArrayList<UEventInfo>();
+            UEventInfo uei;
+
+            // Monitor h2w
+            if (!mUseDevInputEventForAudioJack) {
+                uei = new UEventInfo(NAME_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(NAME_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(NAME_HDMI_AUDIO, BIT_HDMI_AUDIO, 0);
+            if (uei.checkSwitchExists()) {
+                retVal.add(uei);
+            } else {
+                uei = new UEventInfo(NAME_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;
+        }
+
+        @Override
+        public void onUEvent(UEventObserver.UEvent event) {
+            if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString());
+
+            try {
+                String devPath = event.get("DEVPATH");
+                String name = event.get("SWITCH_NAME");
+                int state = Integer.parseInt(event.get("SWITCH_STATE"));
+                synchronized (mLock) {
+                    updateStateLocked(devPath, name, state);
+                }
+            } catch (NumberFormatException e) {
+                Slog.e(TAG, "Could not parse switch state from event " + event);
+            }
+        }
+
+        private void updateStateLocked(String devPath, String name, int state) {
+            for (int i = 0; i < mUEventInfo.size(); ++i) {
+                UEventInfo uei = mUEventInfo.get(i);
+                if (devPath.equals(uei.getDevPath())) {
+                    updateLocked(name, uei.computeNewHeadsetState(mHeadsetState, state));
+                    return;
+                }
+            }
+        }
+
+        private final class UEventInfo {
+            private final String mDevName;
+            private final int mState1Bits;
+            private final int mState2Bits;
+
+            public UEventInfo(String devName, int state1Bits, int state2Bits) {
+                mDevName = devName;
+                mState1Bits = state1Bits;
+                mState2Bits = state2Bits;
+            }
+
+            public String getDevName() { return mDevName; }
+
+            public String getDevPath() {
+                return String.format("/devices/virtual/switch/%s", mDevName);
+            }
+
+            public String getSwitchStatePath() {
+                return String.format("/sys/class/switch/%s/state", mDevName);
+            }
+
+            public boolean checkSwitchExists() {
+                File f = new File(getSwitchStatePath());
+                return 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);
+            }
+        }
+    }
+}
diff --git a/services/java/com/android/server/WiredAccessoryObserver.java b/services/java/com/android/server/WiredAccessoryObserver.java
deleted file mode 100644
index 96ac493..0000000
--- a/services/java/com/android/server/WiredAccessoryObserver.java
+++ /dev/null
@@ -1,318 +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.
- */
-
-package com.android.server;
-
-import android.app.ActivityManagerNative;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Handler;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
-import android.os.UEventObserver;
-import android.util.Slog;
-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.
- */
-class WiredAccessoryObserver extends UEventObserver {
-    private static final String TAG = WiredAccessoryObserver.class.getSimpleName();
-    private static final boolean LOG = true;
-    private static final int BIT_HEADSET = (1 << 0);
-    private static final int BIT_HEADSET_NO_MIC = (1 << 1);
-    private static final int BIT_USB_HEADSET_ANLG = (1 << 2);
-    private static final int BIT_USB_HEADSET_DGTL = (1 << 3);
-    private static final int BIT_HDMI_AUDIO = (1 << 4);
-    private static final int SUPPORTED_HEADSETS = (BIT_HEADSET|BIT_HEADSET_NO_MIC|
-                                                   BIT_USB_HEADSET_ANLG|BIT_USB_HEADSET_DGTL|
-                                                   BIT_HDMI_AUDIO);
-    private static final int HEADSETS_WITH_MIC = BIT_HEADSET;
-
-    private static class UEventInfo {
-        private final String mDevName;
-        private final int mState1Bits;
-        private final int mState2Bits;
-
-        public UEventInfo(String devName, int state1Bits, int state2Bits) {
-            mDevName = devName;
-            mState1Bits = state1Bits;
-            mState2Bits = state2Bits;
-        }
-
-        public String getDevName() { return mDevName; }
-
-        public String getDevPath() {
-            return String.format("/devices/virtual/switch/%s", mDevName);
-        }
-
-        public String getSwitchStatePath() {
-            return String.format("/sys/class/switch/%s/state", mDevName);
-        }
-
-        public boolean checkSwitchExists() {
-            File f = new File(getSwitchStatePath());
-            return ((null != f) && f.exists());
-        }
-
-        public int computeNewHeadsetState(int headsetState, int switchState) {
-            int preserveMask = ~(mState1Bits | mState2Bits);
-            int setBits = ((switchState == 1) ? mState1Bits :
-                          ((switchState == 2) ? mState2Bits : 0));
-
-            return ((headsetState & preserveMask) | setBits);
-        }
-    }
-
-    private 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 final Context mContext;
-    private final WakeLock mWakeLock;  // held while there is a pending route change
-
-    private final AudioManager mAudioManager;
-
-    public WiredAccessoryObserver(Context context) {
-        mContext = context;
-        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryObserver");
-        mWakeLock.setReferenceCounted(false);
-        mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
-
-        context.registerReceiver(new BootCompletedReceiver(),
-            new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
-    }
-
-    private final class BootCompletedReceiver extends BroadcastReceiver {
-      @Override
-      public void onReceive(Context context, Intent intent) {
-        // At any given time accessories could be inserted
-        // one on the board, one on the dock and one on HDMI:
-        // observe three UEVENTs
-        init();  // set initial status
-        for (int i = 0; i < uEventInfo.size(); ++i) {
-            UEventInfo uei = uEventInfo.get(i);
-            startObserving("DEVPATH="+uei.getDevPath());
-        }
-      }
-    }
-
-    @Override
-    public void onUEvent(UEventObserver.UEvent event) {
-        if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString());
-
-        try {
-            String devPath = event.get("DEVPATH");
-            String name = event.get("SWITCH_NAME");
-            int state = Integer.parseInt(event.get("SWITCH_STATE"));
-            updateState(devPath, name, state);
-        } catch (NumberFormatException e) {
-            Slog.e(TAG, "Could not parse switch state from event " + event);
-        }
-    }
-
-    private synchronized final void updateState(String devPath, String name, int state)
-    {
-        for (int i = 0; i < uEventInfo.size(); ++i) {
-            UEventInfo uei = uEventInfo.get(i);
-            if (devPath.equals(uei.getDevPath())) {
-                update(name, uei.computeNewHeadsetState(mHeadsetState, state));
-                return;
-            }
-        }
-    }
-
-    private synchronized final void init() {
-        char[] buffer = new char[1024];
-        mPrevHeadsetState = mHeadsetState;
-
-        if (LOG) Slog.v(TAG, "init()");
-
-        for (int i = 0; i < uEventInfo.size(); ++i) {
-            UEventInfo uei = uEventInfo.get(i);
-            try {
-                int curState;
-                FileReader file = new FileReader(uei.getSwitchStatePath());
-                int len = file.read(buffer, 0, 1024);
-                file.close();
-                curState = Integer.valueOf((new String(buffer, 0, len)).trim());
-
-                if (curState > 0) {
-                    updateState(uei.getDevPath(), uei.getDevName(), curState);
-                }
-
-            } catch (FileNotFoundException e) {
-                Slog.w(TAG, uei.getSwitchStatePath() +
-                        " not found while attempting to determine initial switch state");
-            } catch (Exception e) {
-                Slog.e(TAG, "" , e);
-            }
-        }
-    }
-
-    private synchronized final void update(String newName, int newState) {
-        // Retain only relevant bits
-        int headsetState = newState & SUPPORTED_HEADSETS;
-        int newOrOld = headsetState | mHeadsetState;
-        int delay = 0;
-        int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG;
-        int usb_headset_dgtl = headsetState & BIT_USB_HEADSET_DGTL;
-        int h2w_headset = headsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC);
-        boolean h2wStateChange = true;
-        boolean usbStateChange = true;
-        // reject all suspect transitions: only accept state changes from:
-        // - a: 0 heaset to 1 headset
-        // - b: 1 headset to 0 headset
-        if (LOG) Slog.v(TAG, "newState = "+newState+", headsetState = "+headsetState+","
-            + "mHeadsetState = "+mHeadsetState);
-        if (mHeadsetState == headsetState || ((h2w_headset & (h2w_headset - 1)) != 0)) {
-            Log.e(TAG, "unsetting h2w flag");
-            h2wStateChange = false;
-        }
-        // - c: 0 usb headset to 1 usb headset
-        // - d: 1 usb headset to 0 usb headset
-        if ((usb_headset_anlg >> 2) == 1 && (usb_headset_dgtl >> 3) == 1) {
-            Log.e(TAG, "unsetting usb flag");
-            usbStateChange = false;
-        }
-        if (!h2wStateChange && !usbStateChange) {
-            Log.e(TAG, "invalid transition, returning ...");
-            return;
-        }
-
-        mHeadsetName = newName;
-        mPrevHeadsetState = mHeadsetState;
-        mHeadsetState = headsetState;
-
-        mWakeLock.acquire();
-        mHandler.sendMessage(mHandler.obtainMessage(0,
-                                                    mHeadsetState,
-                                                    mPrevHeadsetState,
-                                                    mHeadsetName));
-    }
-
-    private synchronized final void setDevicesState(int headsetState,
-                                                    int prevHeadsetState,
-                                                    String headsetName) {
-        int allHeadsets = SUPPORTED_HEADSETS;
-        for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {
-            if ((curHeadset & allHeadsets) != 0) {
-                setDeviceState(curHeadset, headsetState, prevHeadsetState, headsetName);
-                allHeadsets &= ~curHeadset;
-            }
-        }
-    }
-
-    private final void setDeviceState(int headset,
-                                      int headsetState,
-                                      int prevHeadsetState,
-                                      String headsetName) {
-        if ((headsetState & headset) != (prevHeadsetState & headset)) {
-            int device;
-            int state;
-
-            if ((headsetState & headset) != 0) {
-                state = 1;
-            } else {
-                state = 0;
-            }
-
-            if (headset == BIT_HEADSET) {
-                device = AudioManager.DEVICE_OUT_WIRED_HEADSET;
-            } else if (headset == BIT_HEADSET_NO_MIC){
-                device = AudioManager.DEVICE_OUT_WIRED_HEADPHONE;
-            } else if (headset == BIT_USB_HEADSET_ANLG) {
-                device = AudioManager.DEVICE_OUT_ANLG_DOCK_HEADSET;
-            } else if (headset == BIT_USB_HEADSET_DGTL) {
-                device = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET;
-            } else if (headset == BIT_HDMI_AUDIO) {
-                device = AudioManager.DEVICE_OUT_AUX_DIGITAL;
-            } else {
-                Slog.e(TAG, "setDeviceState() invalid headset type: "+headset);
-                return;
-            }
-
-            if (LOG)
-                Slog.v(TAG, "device "+headsetName+((state == 1) ? " connected" : " disconnected"));
-
-            mAudioManager.setWiredDeviceConnectionState(device, state, headsetName);
-        }
-    }
-
-    private final Handler mHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            setDevicesState(msg.arg1, msg.arg2, (String)msg.obj);
-            mWakeLock.release();
-        }
-    };
-}
diff --git a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 8fa6722..eb414fa 100644
--- a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -16,68 +16,59 @@
 
 package com.android.server.accessibility;
 
-import com.android.server.input.InputFilter;
-
 import android.content.Context;
 import android.os.PowerManager;
 import android.util.Slog;
 import android.view.InputDevice;
 import android.view.InputEvent;
+import android.view.InputFilter;
 import android.view.MotionEvent;
 import android.view.WindowManagerPolicy;
 import android.view.accessibility.AccessibilityEvent;
 
-/**
- * Input filter for accessibility.
- *
- * Currently just a stub but will eventually implement touch exploration, etc.
- */
-public class AccessibilityInputFilter extends InputFilter {
-    private static final String TAG = "AccessibilityInputFilter";
+class AccessibilityInputFilter extends InputFilter implements EventStreamTransformation {
+
+    private static final String TAG = AccessibilityInputFilter.class.getSimpleName();
+
     private static final boolean DEBUG = false;
 
+    private static final int UNDEFINED_DEVICE_ID = -1;
+
+    /**
+     * Flag for enabling the screen magnification feature.
+     *
+     * @see #setEnabledFeatures(int)
+     */
+    static final int FLAG_FEATURE_SCREEN_MAGNIFIER = 0x00000001;
+
+    /**
+     * Flag for enabling the touch exploration feature.
+     *
+     * @see #setEnabledFeatures(int)
+     */
+    static final int FLAG_FEATURE_TOUCH_EXPLORATION = 0x00000002;
+
     private final Context mContext;
 
     private final PowerManager mPm;
 
     private final AccessibilityManagerService mAms;
 
-    /**
-     * This is an interface for explorers that take a {@link MotionEvent}
-     * stream and perform touch exploration of the screen content.
-     */
-    public interface Explorer {
-        /**
-         * Handles a {@link MotionEvent}.
-         *
-         * @param event The event to handle.
-         * @param policyFlags The policy flags associated with the event.
-         */
-        public void onMotionEvent(MotionEvent event, int policyFlags);
+    private int mCurrentDeviceId;
 
-        /**
-         * Requests that the explorer clears its internal state.
-         *
-         * @param event The last received event.
-         * @param policyFlags The policy flags associated with the event.
-         */
-        public void clear(MotionEvent event, int policyFlags);
+    private boolean mInstalled;
 
-        /**
-         * Requests that the explorer clears its internal state.
-         */
-        public void clear();
-    }
+    private int mEnabledFeatures;
 
     private TouchExplorer mTouchExplorer;
+    private ScreenMagnifier mScreenMagnifier;
+    private EventStreamTransformation mEventHandler;
 
-    private int mTouchscreenSourceDeviceId;
-
-    public AccessibilityInputFilter(Context context, AccessibilityManagerService service) {
+    AccessibilityInputFilter(Context context, AccessibilityManagerService service) {
         super(context.getMainLooper());
         mContext = context;
         mAms = service;
-        mPm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        mPm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
     }
 
     @Override
@@ -85,7 +76,9 @@
         if (DEBUG) {
             Slog.d(TAG, "Accessibility input filter installed.");
         }
-        mTouchExplorer = new TouchExplorer(this, mContext, mAms);
+        mInstalled = true;
+        disableFeatures();
+        enableFeatures();
         super.onInstalled();
     }
 
@@ -94,7 +87,8 @@
         if (DEBUG) {
             Slog.d(TAG, "Accessibility input filter uninstalled.");
         }
-        mTouchExplorer.clear();
+        mInstalled = false;
+        disableFeatures();
         super.onUninstalled();
     }
 
@@ -104,27 +98,107 @@
             Slog.d(TAG, "Received event: " + event + ", policyFlags=0x" 
                     + Integer.toHexString(policyFlags));
         }
-        if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
-            MotionEvent motionEvent = (MotionEvent) event;
-            int deviceId = event.getDeviceId();
-            if (mTouchscreenSourceDeviceId != deviceId) {
-                mTouchscreenSourceDeviceId = deviceId;
-                mTouchExplorer.clear(motionEvent, policyFlags);
-            }
-            if ((policyFlags & WindowManagerPolicy.FLAG_PASS_TO_USER) != 0) {
-                mPm.userActivity(event.getEventTime(), false);
-                mTouchExplorer.onMotionEvent(motionEvent, policyFlags);
-            } else {
-                mTouchExplorer.clear(motionEvent, policyFlags);
-            }
-        } else {
+        if (mEventHandler == null) {
             super.onInputEvent(event, policyFlags);
+            return;
+        }
+        if (event.getSource() != InputDevice.SOURCE_TOUCHSCREEN) {
+            super.onInputEvent(event, policyFlags);
+            return;
+        }
+        if ((policyFlags & WindowManagerPolicy.FLAG_PASS_TO_USER) == 0) {
+            mEventHandler.clear();
+            super.onInputEvent(event, policyFlags);
+            return;
+        }
+        final int deviceId = event.getDeviceId();
+        if (mCurrentDeviceId != deviceId) {
+            if (mCurrentDeviceId != UNDEFINED_DEVICE_ID) {
+                mEventHandler.clear();
+            }
+            mCurrentDeviceId = deviceId;
+        }
+        mPm.userActivity(event.getEventTime(), false);
+        MotionEvent rawEvent = (MotionEvent) event;
+        MotionEvent transformedEvent = MotionEvent.obtain(rawEvent);
+        mEventHandler.onMotionEvent(transformedEvent, rawEvent, policyFlags);
+        transformedEvent.recycle();
+    }
+
+    @Override
+    public void onMotionEvent(MotionEvent transformedEvent, MotionEvent rawEvent,
+            int policyFlags) {
+        sendInputEvent(transformedEvent, policyFlags);
+    }
+
+    @Override
+    public void onAccessibilityEvent(AccessibilityEvent event) {
+        // TODO Implement this to inject the accessibility event
+        //      into the accessibility manager service similarly
+        //      to how this is done for input events.
+    }
+
+    @Override
+    public void setNext(EventStreamTransformation sink) {
+        /* do nothing */
+    }
+
+    @Override
+    public void clear() {
+        /* do nothing */
+    }
+
+    void setEnabledFeatures(int enabledFeatures) {
+        if (mEnabledFeatures == enabledFeatures) {
+            return;
+        }
+        if (mInstalled) {
+            disableFeatures();
+        }
+        mEnabledFeatures = enabledFeatures;
+        if (mInstalled) {
+            enableFeatures();
         }
     }
 
-    public void onAccessibilityEvent(AccessibilityEvent event) {
-        if (mTouchExplorer != null) {
-            mTouchExplorer.onAccessibilityEvent(event);
+    void notifyAccessibilityEvent(AccessibilityEvent event) {
+        if (mEventHandler != null) {
+            mEventHandler.onAccessibilityEvent(event);
         }
     }
+
+    private void enableFeatures() {
+        if ((mEnabledFeatures & FLAG_FEATURE_SCREEN_MAGNIFIER) != 0) {
+            mEventHandler = mScreenMagnifier = new ScreenMagnifier(mContext);
+            mEventHandler.setNext(this);
+        }
+        if ((mEnabledFeatures & FLAG_FEATURE_TOUCH_EXPLORATION) != 0) {
+            mTouchExplorer = new TouchExplorer(mContext, mAms);
+            mTouchExplorer.setNext(this);
+            if (mEventHandler != null) {
+                mEventHandler.setNext(mTouchExplorer);
+            } else {
+                mEventHandler = mTouchExplorer;
+            }
+        }
+    }
+
+    private void disableFeatures() {
+        if (mTouchExplorer != null) {
+            mTouchExplorer.clear();
+            mTouchExplorer.onDestroy();
+            mTouchExplorer = null;
+        }
+        if (mScreenMagnifier != null) {
+            mScreenMagnifier.clear();
+            mScreenMagnifier.onDestroy();
+            mScreenMagnifier = null;
+        }
+        mEventHandler = null;
+    }
+
+    @Override
+    public void onDestroy() {
+        /* ignore */
+    }
 }
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index e42ec84..671cbfe 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -40,7 +40,9 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.database.ContentObserver;
+import android.graphics.Point;
 import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
 import android.hardware.input.InputManager;
 import android.net.Uri;
 import android.os.Binder;
@@ -48,19 +50,27 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
+import android.os.Process;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.text.TextUtils.SimpleStringSplitter;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.view.Display;
 import android.view.IWindow;
+import android.view.IWindowManager;
 import android.view.InputDevice;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
+import android.view.WindowInfo;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityInteractionClient;
@@ -74,7 +84,6 @@
 import com.android.internal.R;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.statusbar.IStatusBarService;
-import com.android.server.wm.WindowManagerService;
 
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -87,6 +96,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
  * This class is instantiated by the system as a system level service and can be
@@ -102,77 +112,86 @@
 
     private static final String LOG_TAG = "AccessibilityManagerService";
 
+    // TODO: This is arbitrary. When there is time implement this by watching
+    //       when that accessibility services are bound.
+    private static final int WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS = 3000;
+
     private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE =
         "registerUiTestAutomationService";
 
+    private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED =
+            "temporaryEnableAccessibilityStateUntilKeyguardRemoved";
+
     private static final char COMPONENT_NAME_SEPARATOR = ':';
 
     private static final int OWN_PROCESS_ID = android.os.Process.myPid();
 
-    private static final int MSG_SHOW_ENABLE_TOUCH_EXPLORATION_DIALOG = 1;
-
-    private static final int MSG_TOGGLE_TOUCH_EXPLORATION = 2;
-
-    private static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 3;
-
     private static int sIdCounter = 0;
 
     private static int sNextWindowId;
 
-    final Context mContext;
+    private final Context mContext;
 
-    final Object mLock = new Object();
+    private final Object mLock = new Object();
 
-    final List<Service> mServices = new ArrayList<Service>();
+    private final SimpleStringSplitter mStringColonSplitter =
+            new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
 
-    final List<IAccessibilityManagerClient> mClients =
-        new ArrayList<IAccessibilityManagerClient>();
+    private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList =
+            new ArrayList<AccessibilityServiceInfo>();
 
-    final Map<ComponentName, Service> mComponentNameToServiceMap = new HashMap<ComponentName, Service>();
+    private final Rect mTempRect = new Rect();
 
-    private final List<AccessibilityServiceInfo> mInstalledServices = new ArrayList<AccessibilityServiceInfo>();
+    private final Point mTempPoint = new Point();
 
-    private final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>();
+    private final Display mDefaultDisplay;
 
-    private final Set<ComponentName> mTouchExplorationGrantedServices = new HashSet<ComponentName>();
+    private final PackageManager mPackageManager;
 
-    private final SparseArray<AccessibilityConnectionWrapper> mWindowIdToInteractionConnectionWrapperMap =
-        new SparseArray<AccessibilityConnectionWrapper>();
-
-    private final SparseArray<IBinder> mWindowIdToWindowTokenMap = new SparseArray<IBinder>();
-
-    private final SimpleStringSplitter mStringColonSplitter = new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
-
-    private PackageManager mPackageManager;
-
-    private int mHandledFeedbackTypes = 0;
-
-    private boolean mIsAccessibilityEnabled;
-
-    private AccessibilityInputFilter mInputFilter;
-
-    private boolean mHasInputFilter;
-
-    private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList = new ArrayList<AccessibilityServiceInfo>();
-
-    private boolean mIsTouchExplorationEnabled;
-
-    private final WindowManagerService mWindowManagerService;
+    private final IWindowManager mWindowManagerService;
 
     private final SecurityPolicy mSecurityPolicy;
 
-    private final MainHanler mMainHandler;
+    private final MainHandler mMainHandler;
 
     private Service mUiAutomationService;
 
     private Service mQueryBridge;
 
-    private boolean mTouchExplorationGestureEnded;
-
-    private boolean mTouchExplorationGestureStarted;
-
     private AlertDialog mEnableTouchExplorationDialog;
 
+    private AccessibilityInputFilter mInputFilter;
+
+    private boolean mHasInputFilter;
+
+    private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients =
+            new RemoteCallbackList<IAccessibilityManagerClient>();
+
+    private final SparseArray<AccessibilityConnectionWrapper> mGlobalInteractionConnections =
+            new SparseArray<AccessibilityConnectionWrapper>();
+
+    private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<IBinder>();
+
+    private final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
+
+    private final TempUserStateChangeMemento mTempStateChangeForCurrentUserMemento =
+            new TempUserStateChangeMemento();
+
+    private int mCurrentUserId = UserHandle.USER_OWNER;
+
+    private UserState getCurrentUserStateLocked() {
+        return getUserStateLocked(mCurrentUserId);
+    }
+
+    private UserState getUserStateLocked(int userId) {
+        UserState state = mUserStates.get(userId);
+        if (state == null) {
+            state = new UserState(userId);
+            mUserStates.put(userId, state);
+        }
+        return state;
+    }
+
     /**
      * Creates a new instance.
      *
@@ -181,29 +200,31 @@
     public AccessibilityManagerService(Context context) {
         mContext = context;
         mPackageManager = mContext.getPackageManager();
-        mWindowManagerService = (WindowManagerService) ServiceManager.getService(
-                Context.WINDOW_SERVICE);
+        mWindowManagerService = (IWindowManager) ServiceManager.getService(Context.WINDOW_SERVICE);
         mSecurityPolicy = new SecurityPolicy();
-        mMainHandler = new MainHanler();
-        registerPackageChangeAndBootCompletedBroadcastReceiver();
-        registerSettingsContentObservers();
+        mMainHandler = new MainHandler(mContext.getMainLooper());
+        //TODO: (multi-display) We need to support multiple displays.
+        DisplayManager displayManager = (DisplayManager)
+                mContext.getSystemService(Context.DISPLAY_SERVICE);
+        mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+        registerBroadcastReceivers();
+        new AccessibilityContentObserver(mMainHandler).register(
+                context.getContentResolver());
     }
 
-    /**
-     * Registers a {@link BroadcastReceiver} for the events of
-     * adding/changing/removing/restarting a package and boot completion.
-     */
-    private void registerPackageChangeAndBootCompletedBroadcastReceiver() {
-        Context context = mContext;
-
+    private void registerBroadcastReceivers() {
         PackageMonitor monitor = new PackageMonitor() {
             @Override
             public void onSomePackagesChanged() {
                 synchronized (mLock) {
+                    if (getChangingUserId() != mCurrentUserId) {
+                        return;
+                    }
                     // We will update when the automation service dies.
                     if (mUiAutomationService == null) {
-                        populateAccessibilityServiceListLocked();
-                        manageServicesLocked();
+                        UserState userState = getCurrentUserStateLocked();
+                        populateInstalledAccessibilityServiceLocked(userState);
+                        manageServicesLocked(userState);
                     }
                 }
             }
@@ -211,7 +232,12 @@
             @Override
             public void onPackageRemoved(String packageName, int uid) {
                 synchronized (mLock) {
-                    Iterator<ComponentName> it = mEnabledServices.iterator();
+                    final int userId = getChangingUserId();
+                    if (userId != mCurrentUserId) {
+                        return;
+                    }
+                    UserState state = getUserStateLocked(userId);
+                    Iterator<ComponentName> it = state.mEnabledServices.iterator();
                     while (it.hasNext()) {
                         ComponentName comp = it.next();
                         String compPkg = comp.getPackageName();
@@ -220,13 +246,13 @@
                             // Update the enabled services setting.
                             persistComponentNamesToSettingLocked(
                                     Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
-                                    mEnabledServices);
+                                    state.mEnabledServices, userId);
                             // Update the touch exploration granted services setting.
-                            mTouchExplorationGrantedServices.remove(comp);
+                            state.mTouchExplorationGrantedServices.remove(comp);
                             persistComponentNamesToSettingLocked(
                                     Settings.Secure.
                                             TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
-                                    mEnabledServices);
+                                    state.mEnabledServices, userId);
                             return;
                         }
                     }
@@ -237,7 +263,12 @@
             public boolean onHandleForceStop(Intent intent, String[] packages,
                     int uid, boolean doit) {
                 synchronized (mLock) {
-                    Iterator<ComponentName> it = mEnabledServices.iterator();
+                    final int userId = getChangingUserId();
+                    if (userId != mCurrentUserId) {
+                        return false;
+                    }
+                    UserState state = getUserStateLocked(userId);
+                    Iterator<ComponentName> it = state.mEnabledServices.iterator();
                     while (it.hasNext()) {
                         ComponentName comp = it.next();
                         String compPkg = comp.getPackageName();
@@ -249,193 +280,109 @@
                                 it.remove();
                                 persistComponentNamesToSettingLocked(
                                         Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
-                                        mEnabledServices);
+                                        state.mEnabledServices, userId);
                             }
                         }
                     }
                     return false;
                 }
             }
-
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                if (intent.getAction() == Intent.ACTION_BOOT_COMPLETED) {
-                    synchronized (mLock) {
-                        // We will update when the automation service dies.
-                        if (mUiAutomationService == null) {
-                            populateAccessibilityServiceListLocked();
-                            populateEnabledAccessibilityServicesLocked();
-                            populateTouchExplorationGrantedAccessibilityServicesLocked();
-                            handleAccessibilityEnabledSettingChangedLocked();
-                            handleTouchExplorationEnabledSettingChangedLocked();
-                            updateInputFilterLocked();
-                            sendStateToClientsLocked();
-                        }
-                    }
-                    return;
-                }
-
-                super.onReceive(context, intent);
-            }
         };
 
         // package changes
-        monitor.register(context, null, true);
+        monitor.register(mContext, null,  UserHandle.ALL, true);
 
-        // boot completed
-        IntentFilter bootFiler = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
-        mContext.registerReceiver(monitor, bootFiler, null, monitor.getRegisteredHandler());
+        // user change and unlock
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
+        intentFilter.addAction(Intent.ACTION_USER_REMOVED);
+        intentFilter.addAction(Intent.ACTION_USER_PRESENT);
+
+        mContext.registerReceiverAsUser(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                String action = intent.getAction();
+                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                    switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+                } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+                    removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+                } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
+                    restoreStateFromMementoIfNeeded();
+                }
+            }
+        }, UserHandle.ALL, intentFilter, null, null);
     }
 
-    /**
-     * {@link ContentObserver}s for {@link Settings.Secure#ACCESSIBILITY_ENABLED}
-     * and {@link Settings.Secure#ENABLED_ACCESSIBILITY_SERVICES} settings.
-     */
-    private void registerSettingsContentObservers() {
-        ContentResolver contentResolver = mContext.getContentResolver();
-
-        Uri accessibilityEnabledUri = Settings.Secure.getUriFor(
-                Settings.Secure.ACCESSIBILITY_ENABLED);
-        contentResolver.registerContentObserver(accessibilityEnabledUri, false,
-            new ContentObserver(new Handler()) {
-                @Override
-                public void onChange(boolean selfChange) {
-                    super.onChange(selfChange);
-                    synchronized (mLock) {
-                        // We will update when the automation service dies.
-                        if (mUiAutomationService == null) {
-                            handleAccessibilityEnabledSettingChangedLocked();
-                            updateInputFilterLocked();
-                            sendStateToClientsLocked();
-                        }
-                    }
-                }
-            });
-
-        Uri touchExplorationRequestedUri = Settings.Secure.getUriFor(
-                Settings.Secure.TOUCH_EXPLORATION_ENABLED);
-        contentResolver.registerContentObserver(touchExplorationRequestedUri, false,
-                new ContentObserver(new Handler()) {
-                    @Override
-                    public void onChange(boolean selfChange) {
-                        super.onChange(selfChange);
-                        synchronized (mLock) {
-                            // We will update when the automation service dies.
-                            if (mUiAutomationService == null) {
-                                handleTouchExplorationEnabledSettingChangedLocked();
-                                updateInputFilterLocked();
-                                sendStateToClientsLocked();
-                            }
-                        }
-                    }
-                });
-
-        Uri accessibilityServicesUri =
-            Settings.Secure.getUriFor(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
-        contentResolver.registerContentObserver(accessibilityServicesUri, false,
-            new ContentObserver(new Handler()) {
-                @Override
-                public void onChange(boolean selfChange) {
-                    super.onChange(selfChange);
-                    synchronized (mLock) {
-                        // We will update when the automation service dies.
-                        if (mUiAutomationService == null) {
-                            populateEnabledAccessibilityServicesLocked();
-                            manageServicesLocked();
-                        }
-                    }
-                }
-            });
-
-        Uri touchExplorationGrantedServicesUri = Settings.Secure.getUriFor(
-                Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
-        contentResolver.registerContentObserver(touchExplorationGrantedServicesUri, false,
-            new ContentObserver(new Handler()) {
-                @Override
-                public void onChange(boolean selfChange) {
-                    super.onChange(selfChange);
-                    synchronized (mLock) {
-                        // We will update when the automation service dies.
-                        if (mUiAutomationService == null) {
-                            populateTouchExplorationGrantedAccessibilityServicesLocked();
-                            unbindAllServicesLocked();
-                            manageServicesLocked();
-                        }
-                    }
-                }
-            });
-    }
-
-    public int addClient(IAccessibilityManagerClient client) throws RemoteException {
+    public int addClient(IAccessibilityManagerClient client, int userId) {
         synchronized (mLock) {
-            final IAccessibilityManagerClient addedClient = client;
-            mClients.add(addedClient);
-            // Clients are registered all the time until their process is
-            // killed, therefore we do not have a corresponding unlinkToDeath.
-            client.asBinder().linkToDeath(new DeathRecipient() {
-                public void binderDied() {
-                    synchronized (mLock) {
-                        addedClient.asBinder().unlinkToDeath(this, 0);
-                        mClients.remove(addedClient);
-                    }
+            final int resolvedUserId = mSecurityPolicy
+                    .resolveCallingUserIdEnforcingPermissionsLocked(userId);
+            // If the client is from a process that runs across users such as
+            // the system UI or the system we add it to the global state that
+            // is shared across users.
+            UserState userState = getUserStateLocked(resolvedUserId);
+            if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
+                mGlobalClients.register(client);
+                if (DEBUG) {
+                    Slog.i(LOG_TAG, "Added global client for pid:" + Binder.getCallingPid());
                 }
-            }, 0);
-            return getState();
+                return getClientState(userState);
+            } else {
+                userState.mClients.register(client);
+                // If this client is not for the current user we do not
+                // return a state since it is not for the foreground user.
+                // We will send the state to the client on a user switch.
+                if (DEBUG) {
+                    Slog.i(LOG_TAG, "Added user client for pid:" + Binder.getCallingPid()
+                            + " and userId:" + mCurrentUserId);
+                }
+                return (resolvedUserId == mCurrentUserId) ? getClientState(userState) : 0;
+            }
         }
     }
 
-    public boolean sendAccessibilityEvent(AccessibilityEvent event) {
-        final int eventType = event.getEventType();
-
-        // The event for gesture start should be strictly before the
-        // first hover enter event for the gesture.
-        if (eventType == AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
-                && mTouchExplorationGestureStarted) {
-            mTouchExplorationGestureStarted = false;
-            AccessibilityEvent gestureStartEvent = AccessibilityEvent.obtain(
-                    AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
-            sendAccessibilityEvent(gestureStartEvent);
-        }
-
+    public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) {
         synchronized (mLock) {
+            final int resolvedUserId = mSecurityPolicy
+                    .resolveCallingUserIdEnforcingPermissionsLocked(userId);
+            // This method does nothing for a background user.
+            if (resolvedUserId != mCurrentUserId) {
+                return true; // yes, recycle the event
+            }
             if (mSecurityPolicy.canDispatchAccessibilityEvent(event)) {
-                mSecurityPolicy.updateActiveWindowAndEventSourceLocked(event);
+                mSecurityPolicy.updateEventSourceLocked(event);
+                mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_ACTIVE_WINDOW,
+                        event.getWindowId(), event.getEventType()).sendToTarget();
                 notifyAccessibilityServicesDelayedLocked(event, false);
                 notifyAccessibilityServicesDelayedLocked(event, true);
             }
             if (mHasInputFilter && mInputFilter != null) {
-                mMainHandler.obtainMessage(MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER,
+                mMainHandler.obtainMessage(MainHandler.MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER,
                         AccessibilityEvent.obtain(event)).sendToTarget();
-
             }
             event.recycle();
-            mHandledFeedbackTypes = 0;
+            getUserStateLocked(resolvedUserId).mHandledFeedbackTypes = 0;
         }
-
-        // The event for gesture end should be strictly after the
-        // last hover exit event for the gesture.
-        if (eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
-                && mTouchExplorationGestureEnded) {
-            mTouchExplorationGestureEnded = false;
-            AccessibilityEvent gestureEndEvent = AccessibilityEvent.obtain(
-                    AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END);
-            sendAccessibilityEvent(gestureEndEvent);
-        }
-
         return (OWN_PROCESS_ID != Binder.getCallingPid());
     }
 
-    public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() {
+    public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) {
         synchronized (mLock) {
-            return mInstalledServices;
+            final int resolvedUserId = mSecurityPolicy
+                    .resolveCallingUserIdEnforcingPermissionsLocked(userId);
+            return getUserStateLocked(resolvedUserId).mInstalledServices;
         }
     }
 
-    public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType) {
-        List<AccessibilityServiceInfo> result = mEnabledServicesForFeedbackTempList;
-        result.clear();
-        List<Service> services = mServices;
+    public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType,
+            int userId) {
+        List<AccessibilityServiceInfo> result = null;
         synchronized (mLock) {
+            final int resolvedUserId = mSecurityPolicy
+                    .resolveCallingUserIdEnforcingPermissionsLocked(userId);
+            result = mEnabledServicesForFeedbackTempList;
+            result.clear();
+            List<Service> services = getUserStateLocked(resolvedUserId).mServices;
             while (feedbackType != 0) {
                 final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackType));
                 feedbackType &= ~feedbackTypeBit;
@@ -451,30 +398,59 @@
         return result;
     }
 
-    public void interrupt() {
+    public void interrupt(int userId) {
+        CopyOnWriteArrayList<Service> services;
         synchronized (mLock) {
-            for (int i = 0, count = mServices.size(); i < count; i++) {
-                Service service = mServices.get(i);
-                try {
-                    service.mServiceInterface.onInterrupt();
-                } catch (RemoteException re) {
-                    Slog.e(LOG_TAG, "Error during sending interrupt request to "
-                        + service.mService, re);
-                }
+            final int resolvedUserId = mSecurityPolicy
+                    .resolveCallingUserIdEnforcingPermissionsLocked(userId);
+            // This method does nothing for a background user.
+            if (resolvedUserId != mCurrentUserId) {
+                return;
+            }
+            services = getUserStateLocked(resolvedUserId).mServices;
+        }
+        for (int i = 0, count = services.size(); i < count; i++) {
+            Service service = services.get(i);
+            try {
+                service.mServiceInterface.onInterrupt();
+            } catch (RemoteException re) {
+                Slog.e(LOG_TAG, "Error during sending interrupt request to "
+                    + service.mService, re);
             }
         }
     }
 
     public int addAccessibilityInteractionConnection(IWindow windowToken,
-            IAccessibilityInteractionConnection connection) throws RemoteException {
+            IAccessibilityInteractionConnection connection, int userId) throws RemoteException {
         synchronized (mLock) {
-            final IWindow addedWindowToken = windowToken;
+            final int resolvedUserId = mSecurityPolicy
+                    .resolveCallingUserIdEnforcingPermissionsLocked(userId);
             final int windowId = sNextWindowId++;
-            AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(windowId,
-                    connection);
-            wrapper.linkToDeath();
-            mWindowIdToWindowTokenMap.put(windowId, addedWindowToken.asBinder());
-            mWindowIdToInteractionConnectionWrapperMap.put(windowId, wrapper);
+            // If the window is from a process that runs across users such as
+            // the system UI or the system we add it to the global state that
+            // is shared across users.
+            if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
+                AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
+                        windowId, connection, UserHandle.USER_ALL);
+                wrapper.linkToDeath();
+                mGlobalInteractionConnections.put(windowId, wrapper);
+                mGlobalWindowTokens.put(windowId, windowToken.asBinder());
+                if (DEBUG) {
+                    Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid()
+                            + " with windowId: " + windowId);
+                }
+            } else {
+                AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
+                        windowId, connection, resolvedUserId);
+                wrapper.linkToDeath();
+                UserState userState = getUserStateLocked(resolvedUserId);
+                userState.mInteractionConnections.put(windowId, wrapper);
+                userState.mWindowTokens.put(windowId, windowToken.asBinder());
+                if (DEBUG) {
+                    Slog.i(LOG_TAG, "Added user connection for pid:" + Binder.getCallingPid()
+                            + " with windowId: " + windowId + " and userId:" + mCurrentUserId);
+                }
+            }
             if (DEBUG) {
                 Slog.i(LOG_TAG, "Adding interaction connection to windowId: " + windowId);
             }
@@ -482,22 +458,55 @@
         }
     }
 
-    public void removeAccessibilityInteractionConnection(IWindow windowToken) {
+    public void removeAccessibilityInteractionConnection(IWindow window) {
         synchronized (mLock) {
-            final int count = mWindowIdToWindowTokenMap.size();
-            for (int i = 0; i < count; i++) {
-                if (mWindowIdToWindowTokenMap.valueAt(i) == windowToken.asBinder()) {
-                    final int windowId = mWindowIdToWindowTokenMap.keyAt(i);
-                    AccessibilityConnectionWrapper wrapper =
-                        mWindowIdToInteractionConnectionWrapperMap.get(windowId);
-                    wrapper.unlinkToDeath();
-                    removeAccessibilityInteractionConnectionLocked(windowId);
+            mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(
+                    UserHandle.getCallingUserId());
+            IBinder token = window.asBinder();
+            final int removedWindowId = removeAccessibilityInteractionConnectionInternalLocked(
+                    token, mGlobalWindowTokens, mGlobalInteractionConnections);
+            if (removedWindowId >= 0) {
+                if (DEBUG) {
+                    Slog.i(LOG_TAG, "Removed global connection for pid:" + Binder.getCallingPid()
+                            + " with windowId: " + removedWindowId);
+                }
+                return;
+            }
+            final int userCount = mUserStates.size();
+            for (int i = 0; i < userCount; i++) {
+                UserState userState = mUserStates.valueAt(i);
+                final int removedWindowIdForUser =
+                        removeAccessibilityInteractionConnectionInternalLocked(
+                        token, userState.mWindowTokens, userState.mInteractionConnections);
+                if (removedWindowIdForUser >= 0) {
+                    if (DEBUG) {
+                        Slog.i(LOG_TAG, "Removed user connection for pid:" + Binder.getCallingPid()
+                                + " with windowId: " + removedWindowIdForUser + " and userId:"
+                                + mUserStates.keyAt(i));
+                    }
                     return;
                 }
             }
         }
     }
 
+    private int removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken,
+            SparseArray<IBinder> windowTokens,
+            SparseArray<AccessibilityConnectionWrapper> interactionConnections) {
+        final int count = windowTokens.size();
+        for (int i = 0; i < count; i++) {
+            if (windowTokens.valueAt(i) == windowToken) {
+                final int windowId = windowTokens.keyAt(i);
+                windowTokens.removeAt(i);
+                AccessibilityConnectionWrapper wrapper = interactionConnections.get(windowId);
+                wrapper.unlinkToDeath();
+                interactionConnections.remove(windowId);
+                return windowId;
+            }
+        }
+        return -1;
+    }
+
     public void registerUiTestAutomationService(IAccessibilityServiceClient serviceClient,
             AccessibilityServiceInfo accessibilityServiceInfo) {
         mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT,
@@ -508,29 +517,63 @@
             // If an automation services is connected to the system all services are stopped
             // so the automation one is the only one running. Settings are not changed so when
             // the automation service goes away the state is restored from the settings.
+            UserState userState = getCurrentUserStateLocked();
+            unbindAllServicesLocked(userState);
 
-            // Disable all services.
-            final int runningServiceCount = mServices.size();
-            for (int i = 0; i < runningServiceCount; i++) {
-                Service runningService = mServices.get(i);
-                runningService.unbind();
-            }
             // If necessary enable accessibility and announce that.
-            if (!mIsAccessibilityEnabled) {
-                mIsAccessibilityEnabled = true;
-                sendStateToClientsLocked();
+            if (!userState.mIsAccessibilityEnabled) {
+                userState.mIsAccessibilityEnabled = true;
             }
+            // No touch exploration.
+            userState.mIsTouchExplorationEnabled = false;
+
+            // Hook the automation service up.
+            mUiAutomationService = new Service(mCurrentUserId, componentName,
+                    accessibilityServiceInfo, true);
+            mUiAutomationService.onServiceConnected(componentName, serviceClient.asBinder());
+
+            updateInputFilterLocked(userState);
+            scheduleSendStateToClientsLocked(userState);
         }
-        // Hook the automation service up.
-        mUiAutomationService = new Service(componentName, accessibilityServiceInfo, true);
-        mUiAutomationService.onServiceConnected(componentName, serviceClient.asBinder());
+    }
+
+    public void temporaryEnableAccessibilityStateUntilKeyguardRemoved(
+            ComponentName service, boolean touchExplorationEnabled) {
+        mSecurityPolicy.enforceCallingPermission(
+                Manifest.permission.TEMPORARY_ENABLE_ACCESSIBILITY,
+                TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED);
+        try {
+            if (!mWindowManagerService.isKeyguardLocked()) {
+                return;
+            }
+        } catch (RemoteException re) {
+            return;
+        }
+        synchronized (mLock) {
+            UserState userState = getCurrentUserStateLocked();
+            // Stash the old state so we can restore it when the keyguard is gone.
+            mTempStateChangeForCurrentUserMemento.initialize(mCurrentUserId, getCurrentUserStateLocked());
+            // Set the temporary state.
+            userState.mIsAccessibilityEnabled = true;
+            userState.mIsTouchExplorationEnabled= touchExplorationEnabled;
+            userState.mIsDisplayMagnificationEnabled = false;
+            userState.mEnabledServices.clear();
+            userState.mEnabledServices.add(service);
+            userState.mTouchExplorationGrantedServices.clear();
+            userState.mTouchExplorationGrantedServices.add(service);
+            // Update the internal state.
+            performServiceManagementLocked(userState);
+            updateInputFilterLocked(userState);
+            scheduleSendStateToClientsLocked(userState);
+        }
     }
 
     public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) {
         synchronized (mLock) {
             // Automation service is not bound, so pretend it died to perform clean up.
-            if (mUiAutomationService != null
-                    && mUiAutomationService.mServiceInterface == serviceClient) {
+            if (mUiAutomationService != null && mUiAutomationService.mServiceInterface != null
+                    && serviceClient != null && mUiAutomationService.mServiceInterface
+                            .asBinder() == serviceClient.asBinder()) {
                 mUiAutomationService.binderDied();
             }
         }
@@ -552,6 +595,7 @@
      * @param outBounds The output to which to write the focus bounds.
      * @return Whether accessibility focus was found and the bounds are populated.
      */
+    // TODO: (multi-display) Make sure this works for multiple displays. 
     boolean getAccessibilityFocusBoundsInActiveWindow(Rect outBounds) {
         // Instead of keeping track of accessibility focus events per
         // window to be able to find the focus in the active window,
@@ -573,6 +617,13 @@
                 return false;
             }
             focus.getBoundsInScreen(outBounds);
+            // Clip to the window rectangle.
+            Rect windowBounds = mTempRect;
+            getActiveWindowBounds(windowBounds);
+            outBounds.intersect(windowBounds);
+            // Clip to the screen rectangle.
+            mDefaultDisplay.getRealSize(mTempPoint);
+            outBounds.intersect(0,  0,  mTempPoint.x, mTempPoint.y);
             return true;
         } finally {
             client.removeConnection(connectionId);
@@ -584,34 +635,108 @@
      *
      * @param outBounds The output to which to write the bounds.
      */
-    void getActiveWindowBounds(Rect outBounds) {
+    boolean getActiveWindowBounds(Rect outBounds) {
+        IBinder token;
         synchronized (mLock) {
             final int windowId = mSecurityPolicy.mActiveWindowId;
-            IBinder token = mWindowIdToWindowTokenMap.get(windowId);
-            mWindowManagerService.getWindowFrame(token, outBounds);
+            token = mGlobalWindowTokens.get(windowId);
+            if (token == null) {
+                token = getCurrentUserStateLocked().mWindowTokens.get(windowId);
+            }
         }
+        WindowInfo info = null;
+        try {
+            info = mWindowManagerService.getWindowInfo(token);
+            if (info != null) {
+                outBounds.set(info.frame);
+                return true;
+            }
+        } catch (RemoteException re) {
+            /* ignore */
+        } finally {
+            if (info != null) {
+                info.recycle();
+            }
+        }
+        return false;
     }
 
     int getActiveWindowId() {
         return mSecurityPolicy.mActiveWindowId;
     }
 
+    void onTouchInteractionStart() {
+        mSecurityPolicy.onTouchInteractionStart();
+    }
+
+    void onTouchInteractionEnd() {
+        mSecurityPolicy.onTouchInteractionEnd();
+    }
+
+    private void switchUser(int userId) {
+        synchronized (mLock) {
+            // The user switched so we do not need to restore the current user
+            // state since we will fully rebuild it when he becomes current again.
+            mTempStateChangeForCurrentUserMemento.clear();
+
+            // Disconnect from services for the old user.
+            UserState oldUserState = getUserStateLocked(mCurrentUserId);
+            unbindAllServicesLocked(oldUserState);
+
+            // Disable the local managers for the old user.
+            if (oldUserState.mClients.getRegisteredCallbackCount() > 0) {
+                mMainHandler.obtainMessage(MainHandler.MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER,
+                        oldUserState.mUserId, 0).sendToTarget();
+            }
+
+            // Announce user changes only if more that one exist.
+            UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+            final boolean announceNewUser = userManager.getUsers().size() > 1;
+
+            // The user changed.
+            mCurrentUserId = userId;
+
+            // Recreate the internal state for the new user.
+            mMainHandler.obtainMessage(MainHandler.MSG_SEND_RECREATE_INTERNAL_STATE,
+                    mCurrentUserId, 0).sendToTarget();
+
+            if (announceNewUser) {
+                // Schedule announcement of the current user if needed.
+                mMainHandler.sendEmptyMessageDelayed(MainHandler.MSG_ANNOUNCE_NEW_USER_IF_NEEDED,
+                        WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS);
+            }
+        }
+    }
+
+    private void removeUser(int userId) {
+        synchronized (mLock) {
+            mUserStates.remove(userId);
+        }
+    }
+
+    private void restoreStateFromMementoIfNeeded() {
+        synchronized (mLock) {
+            if (mTempStateChangeForCurrentUserMemento.mUserId != UserHandle.USER_NULL) {
+                UserState userState = getCurrentUserStateLocked();
+                // Restore the state from the memento.
+                mTempStateChangeForCurrentUserMemento.applyTo(userState);
+                mTempStateChangeForCurrentUserMemento.clear();
+                // Update the internal state.
+                performServiceManagementLocked(userState);
+                updateInputFilterLocked(userState);
+                scheduleSendStateToClientsLocked(userState);
+            }
+        }
+    }
+
     private Service getQueryBridge() {
         if (mQueryBridge == null) {
             AccessibilityServiceInfo info = new AccessibilityServiceInfo();
-            mQueryBridge = new Service(null, info, true);
+            mQueryBridge = new Service(UserHandle.USER_NULL, null, info, true);
         }
         return mQueryBridge;
     }
 
-    public void touchExplorationGestureEnded() {
-        mTouchExplorationGestureEnded = true;
-    }
-
-    public void touchExplorationGestureStarted() {
-        mTouchExplorationGestureStarted = true;
-    }
-
     private boolean notifyGestureLocked(int gestureId, boolean isDefault) {
         // TODO: Now we are giving the gestures to the last enabled
         //       service that can handle them which is the last one
@@ -622,9 +747,10 @@
         //       gestures to avoid user frustration when different
         //       behavior is observed from different combinations of
         //       enabled accessibility services.
-        for (int i = mServices.size() - 1; i >= 0; i--) {
-            Service service = mServices.get(i);
-            if (service.mReqeustTouchExplorationMode && service.mIsDefault == isDefault) {
+        UserState state = getCurrentUserStateLocked();
+        for (int i = state.mServices.size() - 1; i >= 0; i--) {
+            Service service = state.mServices.get(i);
+            if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) {
                 service.notifyGesture(gestureId);
                 return true;
             }
@@ -636,32 +762,35 @@
      * Removes an AccessibilityInteractionConnection.
      *
      * @param windowId The id of the window to which the connection is targeted.
+     * @param userId The id of the user owning the connection. UserHandle.USER_ALL
+     *     if global.
      */
-    private void removeAccessibilityInteractionConnectionLocked(int windowId) {
-        mWindowIdToWindowTokenMap.remove(windowId);
-        mWindowIdToInteractionConnectionWrapperMap.remove(windowId);
+    private void removeAccessibilityInteractionConnectionLocked(int windowId, int userId) {
+        if (userId == UserHandle.USER_ALL) {
+            mGlobalWindowTokens.remove(windowId);
+            mGlobalInteractionConnections.remove(windowId);
+        } else {
+            UserState userState = getCurrentUserStateLocked();
+            userState.mWindowTokens.remove(windowId);
+            userState.mInteractionConnections.remove(windowId);
+        }
         if (DEBUG) {
             Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId);
         }
     }
 
-    /**
-     * Populates the cached list of installed {@link AccessibilityService}s.
-     */
-    private void populateAccessibilityServiceListLocked() {
-        mInstalledServices.clear();
+    private void populateInstalledAccessibilityServiceLocked(UserState userState) {
+        userState.mInstalledServices.clear();
 
-        List<ResolveInfo> installedServices = mPackageManager.queryIntentServices(
+        List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser(
                 new Intent(AccessibilityService.SERVICE_INTERFACE),
-                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
+                mCurrentUserId);
 
         for (int i = 0, count = installedServices.size(); i < count; i++) {
             ResolveInfo resolveInfo = installedServices.get(i);
             ServiceInfo serviceInfo = resolveInfo.serviceInfo;
-            // For now we are enforcing this if the target version is JellyBean or
-            // higher and in a later release we will enforce this for everyone.
-            if (serviceInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN
-                    && !android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE.equals(
+            if (!android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE.equals(
                     serviceInfo.permission)) {
                 Slog.w(LOG_TAG, "Skipping accessibilty service " + new ComponentName(
                         serviceInfo.packageName, serviceInfo.name).flattenToShortString()
@@ -672,7 +801,7 @@
             AccessibilityServiceInfo accessibilityServiceInfo;
             try {
                 accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext);
-                mInstalledServices.add(accessibilityServiceInfo);
+                userState.mInstalledServices.add(accessibilityServiceInfo);
             } catch (XmlPullParserException xppe) {
                 Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe);
             } catch (IOException ioe) {
@@ -681,16 +810,19 @@
         }
     }
 
-    private void populateEnabledAccessibilityServicesLocked() {
+    private void populateEnabledAccessibilityServicesLocked(UserState userState) {
         populateComponentNamesFromSettingLocked(
                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
-                mEnabledServices);
+                userState.mUserId,
+                userState.mEnabledServices);
     }
 
-    private void populateTouchExplorationGrantedAccessibilityServicesLocked() {
+    private void populateTouchExplorationGrantedAccessibilityServicesLocked(
+            UserState userState) {
         populateComponentNamesFromSettingLocked(
                 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
-                mTouchExplorationGrantedServices);
+                userState.mUserId,
+                userState.mTouchExplorationGrantedServices);
     }
 
     /**
@@ -703,12 +835,13 @@
     private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event,
             boolean isDefault) {
         try {
-            for (int i = 0, count = mServices.size(); i < count; i++) {
-                Service service = mServices.get(i);
+            UserState state = getCurrentUserStateLocked();
+            for (int i = 0, count = state.mServices.size(); i < count; i++) {
+                Service service = state.mServices.get(i);
 
                 if (service.mIsDefault == isDefault) {
-                    if (canDispathEventLocked(service, event, mHandledFeedbackTypes)) {
-                        mHandledFeedbackTypes |= service.mFeedbackType;
+                    if (canDispathEventLocked(service, event, state.mHandledFeedbackTypes)) {
+                        state.mHandledFeedbackTypes |= service.mFeedbackType;
                         service.notifyAccessibilityEvent(event);
                     }
                 }
@@ -722,19 +855,21 @@
     }
 
     /**
-     * Adds a service.
+     * Adds a service for a user.
      *
      * @param service The service to add.
+     * @param userId The user id.
      */
-    private void tryAddServiceLocked(Service service) {
+    private void tryAddServiceLocked(Service service, int userId) {
         try {
-            if (mServices.contains(service) || !service.isConfigured()) {
+            UserState userState = getUserStateLocked(userId);
+            if (userState.mServices.contains(service)) {
                 return;
             }
             service.linkToOwnDeath();
-            mServices.add(service);
-            mComponentNameToServiceMap.put(service.mComponentName, service);
-            updateInputFilterLocked();
+            userState.mServices.add(service);
+            userState.mComponentNameToServiceMap.put(service.mComponentName, service);
+            updateInputFilterLocked(userState);
             tryEnableTouchExplorationLocked(service);
         } catch (RemoteException e) {
             /* do nothing */
@@ -748,14 +883,15 @@
      * @return True if the service was removed, false otherwise.
      */
     private boolean tryRemoveServiceLocked(Service service) {
-        final boolean removed = mServices.remove(service);
+        UserState userState = getUserStateLocked(service.mUserId);
+        final boolean removed = userState.mServices.remove(service);
         if (!removed) {
             return false;
         }
-        mComponentNameToServiceMap.remove(service.mComponentName);
+        userState.mComponentNameToServiceMap.remove(service.mComponentName);
         service.unlinkToOwnDeath();
         service.dispose();
-        updateInputFilterLocked();
+        updateInputFilterLocked(userState);
         tryDisableTouchExplorationLocked(service);
         return removed;
     }
@@ -776,7 +912,7 @@
     private boolean canDispathEventLocked(Service service, AccessibilityEvent event,
             int handledFeedbackTypes) {
 
-        if (!service.isConfigured()) {
+        if (!service.canReceiveEvents()) {
             return false;
         }
 
@@ -807,23 +943,23 @@
     /**
      * Manages services by starting enabled ones and stopping disabled ones.
      */
-    private void manageServicesLocked() {
-        final int enabledInstalledServicesCount = updateServicesStateLocked(mInstalledServices,
-                mEnabledServices);
+    private void manageServicesLocked(UserState userState) {
+        final int enabledInstalledServicesCount = updateServicesStateLocked(userState);
         // No enabled installed services => disable accessibility to avoid
         // sending accessibility events with no recipient across processes.
-        if (mIsAccessibilityEnabled && enabledInstalledServicesCount == 0) {
-            Settings.Secure.putInt(mContext.getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_ENABLED, 0);
+        if (userState.mIsAccessibilityEnabled && enabledInstalledServicesCount == 0) {
+            Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId);
         }
     }
 
     /**
-     * Unbinds all bound services.
+     * Unbinds all bound services for a user.
+     *
+     * @param userState The user state.
      */
-    private void unbindAllServicesLocked() {
-        List<Service> services = mServices;
-
+    private void unbindAllServicesLocked(UserState userState) {
+        List<Service> services = userState.mServices;
         for (int i = 0, count = services.size(); i < count; i++) {
             Service service = services.get(i);
             if (service.unbind()) {
@@ -835,17 +971,17 @@
 
     /**
      * Populates a set with the {@link ComponentName}s stored in a colon
-     * separated value setting.
+     * separated value setting for a given user.
      *
      * @param settingName The setting to parse.
+     * @param userId The user id.
      * @param outComponentNames The output component names.
      */
-    private void populateComponentNamesFromSettingLocked(String settingName,
+    private void populateComponentNamesFromSettingLocked(String settingName, int userId,
             Set<ComponentName> outComponentNames) {
+        String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+                settingName, userId);
         outComponentNames.clear();
-
-        String settingValue = Settings.Secure.getString(mContext.getContentResolver(), settingName);
-
         if (settingValue != null) {
             TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
             splitter.setString(settingValue);
@@ -870,7 +1006,7 @@
      * @param componentNames The component names.
      */
     private void persistComponentNamesToSettingLocked(String settingName,
-            Set<ComponentName> componentNames) {
+            Set<ComponentName> componentNames, int userId) {
         StringBuilder builder = new StringBuilder();
         for (ComponentName componentName : componentNames) {
             if (builder.length() > 0) {
@@ -878,34 +1014,34 @@
             }
             builder.append(componentName.flattenToShortString());
         }
-        Settings.Secure.putString(mContext.getContentResolver(), settingName, builder.toString());
+        Settings.Secure.putStringForUser(mContext.getContentResolver(),
+                settingName, builder.toString(), userId);
     }
 
     /**
      * Updates the state of each service by starting (or keeping running) enabled ones and
      * stopping the rest.
      *
-     * @param installedServices All installed {@link AccessibilityService}s.
-     * @param enabledServices The {@link ComponentName}s of the enabled services.
+     * @param userState The user state for which to do that.
      * @return The number of enabled installed services.
      */
-    private int updateServicesStateLocked(List<AccessibilityServiceInfo> installedServices,
-            Set<ComponentName> enabledServices) {
-
-        Map<ComponentName, Service> componentNameToServiceMap = mComponentNameToServiceMap;
-        boolean isEnabled = mIsAccessibilityEnabled;
+    private int updateServicesStateLocked(UserState userState) {
+        Map<ComponentName, Service> componentNameToServiceMap =
+                userState.mComponentNameToServiceMap;
+        boolean isEnabled = userState.mIsAccessibilityEnabled;
 
         int enabledInstalledServices = 0;
-        for (int i = 0, count = installedServices.size(); i < count; i++) {
-            AccessibilityServiceInfo installedService = installedServices.get(i);
+        for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) {
+            AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i);
             ComponentName componentName = ComponentName.unflattenFromString(
                     installedService.getId());
             Service service = componentNameToServiceMap.get(componentName);
 
             if (isEnabled) {
-                if (enabledServices.contains(componentName)) {
+                if (userState.mEnabledServices.contains(componentName)) {
                     if (service == null) {
-                        service = new Service(componentName, installedService, false);
+                        service = new Service(userState.mUserId, componentName,
+                                installedService, false);
                     }
                     service.bind();
                     enabledInstalledServices++;
@@ -924,117 +1060,213 @@
         return enabledInstalledServices;
     }
 
-    /**
-     * Sends the state to the clients.
-     */
-    private void sendStateToClientsLocked() {
-        final int state = getState();
-        for (int i = 0, count = mClients.size(); i < count; i++) {
+    private void scheduleSendStateToClientsLocked(UserState userState) {
+        if (mGlobalClients.getRegisteredCallbackCount() > 0
+                || userState.mClients.getRegisteredCallbackCount() > 0) {
+            final int clientState = getClientState(userState);
+            mMainHandler.obtainMessage(MainHandler.MSG_SEND_STATE_TO_CLIENTS,
+                    clientState, userState.mUserId) .sendToTarget();
+        }
+    }
+
+    private void updateInputFilterLocked(UserState userState) {
+        boolean setInputFilter = false;
+        AccessibilityInputFilter inputFilter = null;
+        synchronized (mLock) {
+            if ((userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled)
+                    || userState.mIsDisplayMagnificationEnabled) {
+                if (!mHasInputFilter) {
+                    mHasInputFilter = true;
+                    if (mInputFilter == null) {
+                        mInputFilter = new AccessibilityInputFilter(mContext,
+                                AccessibilityManagerService.this);
+                    }
+                    inputFilter = mInputFilter;
+                    setInputFilter = true;
+                }
+                int flags = 0;
+                if (userState.mIsDisplayMagnificationEnabled) {
+                    flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
+                }
+                if (userState.mIsTouchExplorationEnabled) {
+                    flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
+                }
+                mInputFilter.setEnabledFeatures(flags);
+            } else {
+                if (mHasInputFilter) {
+                    mHasInputFilter = false;
+                    mInputFilter.setEnabledFeatures(0);
+                    inputFilter = null;
+                    setInputFilter = true;
+                }
+            }
+        }
+        if (setInputFilter) {
             try {
-                mClients.get(i).setState(state);
+                mWindowManagerService.setInputFilter(inputFilter);
             } catch (RemoteException re) {
-                mClients.remove(i);
-                count--;
-                i--;
+                /* ignore */
             }
         }
     }
 
-    /**
-     * Gets the current state as a set of flags.
-     *
-     * @return The state.
-     */
-    private int getState() {
-        int state = 0;
-        if (mIsAccessibilityEnabled) {
-            state |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
+    private void showEnableTouchExplorationDialog(final Service service) {
+        String label = service.mResolveInfo.loadLabel(
+                mContext.getPackageManager()).toString();
+        synchronized (mLock) {
+            final UserState state = getCurrentUserStateLocked();
+            if (state.mIsTouchExplorationEnabled) {
+                return;
+            }
+            if (mEnableTouchExplorationDialog != null
+                    && mEnableTouchExplorationDialog.isShowing()) {
+                return;
+            }
+            mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext)
+                .setIcon(android.R.drawable.ic_dialog_alert)
+                .setPositiveButton(android.R.string.ok, new OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        // The user allowed the service to toggle touch exploration.
+                        state.mTouchExplorationGrantedServices.add(service.mComponentName);
+                        persistComponentNamesToSettingLocked(
+                                Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+                                       state.mTouchExplorationGrantedServices, state.mUserId);
+                        // Enable touch exploration.
+                        Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                                Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1,
+                                service.mUserId);
+                    }
+                })
+                .setNegativeButton(android.R.string.cancel, new OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        dialog.dismiss();
+                    }
+                })
+                .setTitle(R.string.enable_explore_by_touch_warning_title)
+                .setMessage(mContext.getString(
+                        R.string.enable_explore_by_touch_warning_message, label))
+                .create();
+            mEnableTouchExplorationDialog.getWindow().setType(
+                    WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+            mEnableTouchExplorationDialog.getWindow().getAttributes().privateFlags
+                    |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+            mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true);
+            mEnableTouchExplorationDialog.show();
+        }
+    }
+
+    private int getClientState(UserState userState) {
+        int clientState = 0;
+        if (userState.mIsAccessibilityEnabled) {
+            clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
         }
         // Touch exploration relies on enabled accessibility.
-        if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
-            state |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
+        if (userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled) {
+            clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
         }
-        return state;
+        return clientState;
     }
 
-    /**
-     * Updates the touch exploration state.
-     */
-    private void updateInputFilterLocked() {
-        if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
-            if (!mHasInputFilter) {
-                mHasInputFilter = true;
-                if (mInputFilter == null) {
-                    mInputFilter = new AccessibilityInputFilter(mContext, this);
-                }
-                mWindowManagerService.setInputFilter(mInputFilter);
-            }
-            return;
-        }
-        if (mHasInputFilter) {
-            mHasInputFilter = false;
-            mWindowManagerService.setInputFilter(null);
-        }
+    private void recreateInternalStateLocked(UserState userState) {
+        populateInstalledAccessibilityServiceLocked(userState);
+        populateEnabledAccessibilityServicesLocked(userState);
+        populateTouchExplorationGrantedAccessibilityServicesLocked(userState);
+
+        handleTouchExplorationEnabledSettingChangedLocked(userState);
+        handleDisplayMagnificationEnabledSettingChangedLocked(userState);
+        handleAccessibilityEnabledSettingChangedLocked(userState);
+
+        performServiceManagementLocked(userState);
+        updateInputFilterLocked(userState);
+        scheduleSendStateToClientsLocked(userState);
     }
 
-    /**
-     * Updated the state based on the accessibility enabled setting.
-     */
-    private void handleAccessibilityEnabledSettingChangedLocked() {
-        mIsAccessibilityEnabled = Settings.Secure.getInt(
-                mContext.getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
-        if (mIsAccessibilityEnabled) {
-            manageServicesLocked();
+    private void handleAccessibilityEnabledSettingChangedLocked(UserState userState) {
+        userState.mIsAccessibilityEnabled = Settings.Secure.getIntForUser(
+               mContext.getContentResolver(),
+               Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId) == 1;
+    }
+
+    private void performServiceManagementLocked(UserState userState) {
+        if (userState.mIsAccessibilityEnabled ) {
+            manageServicesLocked(userState);
         } else {
-            unbindAllServicesLocked();
+            unbindAllServicesLocked(userState);
         }
     }
 
-    /**
-     * Updates the state based on the touch exploration enabled setting.
-     */
-    private void handleTouchExplorationEnabledSettingChangedLocked() {
-        mIsTouchExplorationEnabled = Settings.Secure.getInt(
+    private void handleTouchExplorationEnabledSettingChangedLocked(UserState userState) {
+        userState.mIsTouchExplorationEnabled = Settings.Secure.getIntForUser(
                 mContext.getContentResolver(),
-                Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1;
+                Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId) == 1;
+    }
+
+    private void handleDisplayMagnificationEnabledSettingChangedLocked(UserState userState) {
+        userState.mIsDisplayMagnificationEnabled = Settings.Secure.getIntForUser(
+                mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
+                0, userState.mUserId) == 1;
+    }
+
+    private void handleTouchExplorationGrantedAccessibilityServicesChangedLocked(
+            UserState userState) {
+        final int serviceCount = userState.mServices.size();
+        for (int i = 0; i < serviceCount; i++) {
+            Service service = userState.mServices.get(i);
+            if (service.mRequestTouchExplorationMode
+                    && userState.mTouchExplorationGrantedServices.contains(
+                            service.mComponentName)) {
+                tryEnableTouchExplorationLocked(service);
+                return;
+            }
+        }
+        if (userState.mIsTouchExplorationEnabled) {
+            Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                    Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId);
+        }
     }
 
     private void tryEnableTouchExplorationLocked(final Service service) {
-        if (!mIsTouchExplorationEnabled && service.mRequestTouchExplorationMode) {
-            final boolean canToggleTouchExploration = mTouchExplorationGrantedServices.contains(
-                    service.mComponentName);
+        UserState userState = getUserStateLocked(service.mUserId);
+        if (!userState.mIsTouchExplorationEnabled && service.mRequestTouchExplorationMode
+                && service.canReceiveEvents()) {
+            final boolean canToggleTouchExploration =
+                    userState.mTouchExplorationGrantedServices.contains(service.mComponentName);
             if (!service.mIsAutomation && !canToggleTouchExploration) {
-                mMainHandler.obtainMessage(MSG_SHOW_ENABLE_TOUCH_EXPLORATION_DIALOG,
-                        service).sendToTarget();
+                showEnableTouchExplorationDialog(service);
             } else {
-                mMainHandler.obtainMessage(MSG_TOGGLE_TOUCH_EXPLORATION, 1, 0).sendToTarget();
+                Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                        Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, userState.mUserId);
             }
         }
     }
 
     private void tryDisableTouchExplorationLocked(Service service) {
-        if (mIsTouchExplorationEnabled) {
-            synchronized (mLock) {
-                final int serviceCount = mServices.size();
-                for (int i = 0; i < serviceCount; i++) {
-                    Service other = mServices.get(i);
-                    if (other != service && other.mRequestTouchExplorationMode) {
-                        return;
-                    }
+        UserState userState = getUserStateLocked(service.mUserId);
+        if (userState.mIsTouchExplorationEnabled) {
+            final int serviceCount = userState.mServices.size();
+            for (int i = 0; i < serviceCount; i++) {
+                Service other = userState.mServices.get(i);
+                if (other != service && other.mRequestTouchExplorationMode) {
+                    return;
                 }
-                mMainHandler.obtainMessage(MSG_TOGGLE_TOUCH_EXPLORATION, 0, 0).sendToTarget();
             }
+            Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                    Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId);
         }
     }
 
     private class AccessibilityConnectionWrapper implements DeathRecipient {
         private final int mWindowId;
+        private final int mUserId;
         private final IAccessibilityInteractionConnection mConnection;
 
         public AccessibilityConnectionWrapper(int windowId,
-                IAccessibilityInteractionConnection connection) {
+                IAccessibilityInteractionConnection connection, int userId) {
             mWindowId = windowId;
+            mUserId = userId;
             mConnection = connection;
         }
 
@@ -1050,72 +1282,103 @@
         public void binderDied() {
             unlinkToDeath();
             synchronized (mLock) {
-                removeAccessibilityInteractionConnectionLocked(mWindowId);
+                removeAccessibilityInteractionConnectionLocked(mWindowId, mUserId);
             }
         }
     }
 
-    private class MainHanler extends Handler {
+    private final class MainHandler extends Handler {
+        public static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 1;
+        public static final int MSG_SEND_STATE_TO_CLIENTS = 2;
+        public static final int MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER = 3;
+        public static final int MSG_SEND_RECREATE_INTERNAL_STATE = 4;
+        public static final int MSG_UPDATE_ACTIVE_WINDOW = 5;
+        public static final int MSG_ANNOUNCE_NEW_USER_IF_NEEDED = 6;
+
+        public MainHandler(Looper looper) {
+            super(looper);
+        }
+
         @Override
         public void handleMessage(Message msg) {
             final int type = msg.what;
             switch (type) {
-                case MSG_TOGGLE_TOUCH_EXPLORATION: {
-                    final int value = msg.arg1;
-                    Settings.Secure.putInt(mContext.getContentResolver(),
-                            Settings.Secure.TOUCH_EXPLORATION_ENABLED, value);
-                } break;
-                case MSG_SHOW_ENABLE_TOUCH_EXPLORATION_DIALOG: {
-                    final Service service = (Service) msg.obj;
-                    String label = service.mResolveInfo.loadLabel(
-                            mContext.getPackageManager()).toString();
-                    synchronized (mLock) {
-                        if (mIsTouchExplorationEnabled) {
-                            return;
-                        }
-                        if (mEnableTouchExplorationDialog != null
-                                && mEnableTouchExplorationDialog.isShowing()) {
-                            return;
-                        }
-                        mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext)
-                            .setIcon(android.R.drawable.ic_dialog_alert)
-                            .setPositiveButton(android.R.string.ok, new OnClickListener() {
-                                @Override
-                                public void onClick(DialogInterface dialog, int which) {
-                                    // The user allowed the service to toggle touch exploration.
-                                    mTouchExplorationGrantedServices.add(service.mComponentName);
-                                    persistComponentNamesToSettingLocked(
-                                            Settings.Secure.
-                                                   TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
-                                            mTouchExplorationGrantedServices);
-                                    // Enable touch exploration.
-                                    Settings.Secure.putInt(mContext.getContentResolver(),
-                                            Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1);
-                                }
-                            })
-                            .setNegativeButton(android.R.string.cancel, new OnClickListener() {
-                                @Override
-                                public void onClick(DialogInterface dialog, int which) {
-                                    dialog.dismiss();
-                                }
-                            })
-                            .setTitle(R.string.enable_explore_by_touch_warning_title)
-                            .setMessage(mContext.getString(
-                                R.string.enable_explore_by_touch_warning_message, label))
-                            .create();
-                        mEnableTouchExplorationDialog.getWindow().setType(
-                                WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
-                        mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true);
-                        mEnableTouchExplorationDialog.show();
-                    }
-                } break;
                 case MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER: {
                     AccessibilityEvent event = (AccessibilityEvent) msg.obj;
-                    if (mHasInputFilter && mInputFilter != null) {
-                        mInputFilter.onAccessibilityEvent(event);
+                    synchronized (mLock) {
+                        if (mHasInputFilter && mInputFilter != null) {
+                            mInputFilter.notifyAccessibilityEvent(event);
+                        }
                     }
                     event.recycle();
                 } break;
+                case MSG_SEND_STATE_TO_CLIENTS: {
+                    final int clientState = msg.arg1;
+                    final int userId = msg.arg2;
+                    sendStateToClients(clientState, mGlobalClients);
+                    sendStateToClientsForUser(clientState, userId);
+                } break;
+                case MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER: {
+                    final int userId = msg.arg1;
+                    sendStateToClientsForUser(0, userId);
+                } break;
+                case MSG_SEND_RECREATE_INTERNAL_STATE: {
+                    final int userId = msg.arg1;
+                    synchronized (mLock) {
+                        UserState userState = getUserStateLocked(userId);
+                        recreateInternalStateLocked(userState);
+                    }
+                } break;
+                case MSG_UPDATE_ACTIVE_WINDOW: {
+                    final int windowId = msg.arg1;
+                    final int eventType = msg.arg2;
+                    mSecurityPolicy.updateActiveWindow(windowId, eventType);
+                } break;
+                case MSG_ANNOUNCE_NEW_USER_IF_NEEDED: {
+                    announceNewUserIfNeeded();
+                } break;
+            }
+        }
+
+        private void announceNewUserIfNeeded() {
+            synchronized (mLock) {
+                UserState userState = getCurrentUserStateLocked();
+                if (userState.mIsAccessibilityEnabled) {
+                    UserManager userManager = (UserManager) mContext.getSystemService(
+                            Context.USER_SERVICE);
+                    String message = mContext.getString(R.string.user_switched,
+                            userManager.getUserInfo(mCurrentUserId).name);
+                    AccessibilityEvent event = AccessibilityEvent.obtain(
+                            AccessibilityEvent.TYPE_ANNOUNCEMENT);
+                    event.getText().add(message);
+                    event.setWindowId(mSecurityPolicy.getRetrievalAllowingWindowLocked());
+                    sendAccessibilityEvent(event, mCurrentUserId);
+                }
+            }
+        }
+
+        private void sendStateToClientsForUser(int clientState, int userId) {
+            final UserState userState;
+            synchronized (mLock) {
+                userState = getUserStateLocked(userId);
+            }
+            sendStateToClients(clientState, userState.mClients);
+        }
+
+        private void sendStateToClients(int clientState,
+                RemoteCallbackList<IAccessibilityManagerClient> clients) {
+            try {
+                final int userClientCount = clients.beginBroadcast();
+                for (int i = 0; i < userClientCount; i++) {
+                    IAccessibilityManagerClient client = clients.getBroadcastItem(i);
+                    try {
+                        client.setState(clientState);
+                    } catch (RemoteException re) {
+                        /* ignore */
+                    }
+                }
+            } finally {
+                clients.finishBroadcast();
             }
         }
     }
@@ -1135,6 +1398,8 @@
         // used as message types allowing us to remove messages per event type. 
         private static final int MSG_ON_GESTURE = 0x80000000;
 
+        final int mUserId;
+
         int mId = 0;
 
         AccessibilityServiceInfo mAccessibilityServiceInfo;
@@ -1163,8 +1428,6 @@
 
         boolean mCanRetrieveScreenContent;
 
-        boolean mReqeustTouchExplorationMode;
-
         boolean mIsAutomation;
 
         final Rect mTempBounds = new Rect();
@@ -1195,8 +1458,9 @@
             }
         };
 
-        public Service(ComponentName componentName,
+        public Service(int userId, ComponentName componentName,
                 AccessibilityServiceInfo accessibilityServiceInfo, boolean isAutomation) {
+            mUserId = userId;
             mResolveInfo = accessibilityServiceInfo.getResolveInfo();
             mId = sIdCounter++;
             mComponentName = componentName;
@@ -1204,7 +1468,7 @@
             mIsAutomation = isAutomation;
             if (!isAutomation) {
                 mCanRetrieveScreenContent = accessibilityServiceInfo.getCanRetrieveWindowContent();
-                mReqeustTouchExplorationMode =
+                mRequestTouchExplorationMode =
                     (accessibilityServiceInfo.flags
                             & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
                 mIntent = new Intent().setComponent(mComponentName);
@@ -1240,7 +1504,7 @@
             // If this service is up and running we may have to enable touch
             // exploration, otherwise this will happen when the service connects.
             synchronized (mLock) {
-                if (isConfigured()) {
+                if (canReceiveEvents()) {
                     if (mRequestTouchExplorationMode) {
                         tryEnableTouchExplorationLocked(this);
                     } else {
@@ -1257,7 +1521,7 @@
          */
         public boolean bind() {
             if (!mIsAutomation && mService == null) {
-                return mContext.bindService(mIntent, this, Context.BIND_AUTO_CREATE);
+                return mContext.bindService(mIntent, this, Context.BIND_AUTO_CREATE, mUserId);
             }
             return false;
         }
@@ -1281,13 +1545,7 @@
             return false;
         }
 
-        /**
-         * Returns if the service is configured i.e. at least event types of interest
-         * and feedback type must be set.
-         *
-         * @return True if the service is configured, false otherwise.
-         */
-        public boolean isConfigured() {
+        public boolean canReceiveEvents() {
             return (mEventTypes != 0 && mFeedbackType != 0 && mService != null);
         }
 
@@ -1300,17 +1558,22 @@
 
         @Override
         public void setServiceInfo(AccessibilityServiceInfo info) {
-            synchronized (mLock) {
-                // If the XML manifest had data to configure the service its info
-                // should be already set. In such a case update only the dynamically
-                // configurable properties.
-                AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo;
-                if (oldInfo != null) {
-                    oldInfo.updateDynamicallyConfigurableProperties(info);
-                    setDynamicallyConfigurableProperties(oldInfo);
-                } else {
-                    setDynamicallyConfigurableProperties(info);
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    // If the XML manifest had data to configure the service its info
+                    // should be already set. In such a case update only the dynamically
+                    // configurable properties.
+                    AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo;
+                    if (oldInfo != null) {
+                        oldInfo.updateDynamicallyConfigurableProperties(info);
+                        setDynamicallyConfigurableProperties(oldInfo);
+                    } else {
+                        setDynamicallyConfigurableProperties(info);
+                    }
                 }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
         }
 
@@ -1321,7 +1584,7 @@
             try {
                 mServiceInterface.setConnection(this, mId);
                 synchronized (mLock) {
-                    tryAddServiceLocked(this);
+                    tryAddServiceLocked(this, mUserId);
                 }
             } catch (RemoteException re) {
                 Slog.w(LOG_TAG, "Error while setting Controller for service: " + service, re);
@@ -1333,25 +1596,26 @@
                 long accessibilityNodeId, int viewId, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
-            final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
-            final int windowLeft;
-            final int windowTop;
+            final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
+                final int resolvedUserId = mSecurityPolicy
+                        .resolveCallingUserIdEnforcingPermissionsLocked(
+                                UserHandle.getCallingUserId());
+                if (resolvedUserId != mCurrentUserId) {
+                    return -1;
+                }
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
                 final boolean permissionGranted = mSecurityPolicy.canRetrieveWindowContent(this);
                 if (!permissionGranted) {
                     return 0;
                 } else {
+                    resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
                     connection = getConnectionLocked(resolvedWindowId);
                     if (connection == null) {
                         return 0;
                     }
                 }
-                IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId);
-                mWindowManagerService.getWindowFrame(token, mTempBounds);
-                windowLeft = mTempBounds.left;
-                windowTop = mTempBounds.top;
             }
             final int flags = (mIncludeNotImportantViews) ?
                     AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
@@ -1359,8 +1623,8 @@
             final long identityToken = Binder.clearCallingIdentity();
             try {
                 connection.findAccessibilityNodeInfoByViewId(accessibilityNodeId, viewId,
-                        windowLeft, windowTop, interactionId, callback, flags, interrogatingPid,
-                        interrogatingTid);
+                        interactionId, callback, flags, interrogatingPid, interrogatingTid);
+                return getCompatibilityScale(resolvedWindowId);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId().");
@@ -1368,7 +1632,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1376,12 +1640,17 @@
                 long accessibilityNodeId, String text, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
-            final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
-            final int windowLeft;
-            final int windowTop;
+            final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
+                final int resolvedUserId = mSecurityPolicy
+                        .resolveCallingUserIdEnforcingPermissionsLocked(
+                        UserHandle.getCallingUserId());
+                if (resolvedUserId != mCurrentUserId) {
+                    return -1;
+                }
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
+                resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
                 final boolean permissionGranted =
                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
                 if (!permissionGranted) {
@@ -1392,19 +1661,16 @@
                         return 0;
                     }
                 }
-                IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId);
-                mWindowManagerService.getWindowFrame(token, mTempBounds);
-                windowLeft = mTempBounds.left;
-                windowTop = mTempBounds.top;
             }
             final int flags = (mIncludeNotImportantViews) ?
                     AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             try {
-                connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text, windowLeft,
-                        windowTop, interactionId, callback, flags, interrogatingPid,
+                connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
+                        interactionId, callback, flags, interrogatingPid,
                         interrogatingTid);
+                return getCompatibilityScale(resolvedWindowId);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()");
@@ -1412,7 +1678,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1420,12 +1686,17 @@
                 long accessibilityNodeId, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, int flags,
                 long interrogatingTid) throws RemoteException {
-            final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
-            final int windowLeft;
-            final int windowTop;
+            final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
+                final int resolvedUserId = mSecurityPolicy
+                        .resolveCallingUserIdEnforcingPermissionsLocked(
+                        UserHandle.getCallingUserId());
+                if (resolvedUserId != mCurrentUserId) {
+                    return -1;
+                }
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
+                resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
                 final boolean permissionGranted =
                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
                 if (!permissionGranted) {
@@ -1436,10 +1707,6 @@
                         return 0;
                     }
                 }
-                IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId);
-                mWindowManagerService.getWindowFrame(token, mTempBounds);
-                windowLeft = mTempBounds.left;
-                windowTop = mTempBounds.top;
             }
             final int allFlags = flags | ((mIncludeNotImportantViews) ?
                     AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0);
@@ -1447,8 +1714,8 @@
             final long identityToken = Binder.clearCallingIdentity();
             try {
                 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
-                        windowLeft, windowTop, interactionId, callback, allFlags, interrogatingPid,
-                        interrogatingTid);
+                        interactionId, callback, allFlags, interrogatingPid, interrogatingTid);
+                return getCompatibilityScale(resolvedWindowId);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
@@ -1456,7 +1723,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1464,12 +1731,17 @@
                 int focusType, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
-            final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
-            final int windowLeft;
-            final int windowTop;
+            final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
+                final int resolvedUserId = mSecurityPolicy
+                        .resolveCallingUserIdEnforcingPermissionsLocked(
+                        UserHandle.getCallingUserId());
+                if (resolvedUserId != mCurrentUserId) {
+                    return -1;
+                }
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
+                resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
                 final boolean permissionGranted =
                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
                 if (!permissionGranted) {
@@ -1480,18 +1752,15 @@
                         return 0;
                     }
                 }
-                IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId);
-                mWindowManagerService.getWindowFrame(token, mTempBounds);
-                windowLeft = mTempBounds.left;
-                windowTop = mTempBounds.top;
             }
             final int flags = (mIncludeNotImportantViews) ?
                     AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             try {
-                connection.findFocus(accessibilityNodeId, focusType, windowLeft, windowTop,
-                        interactionId, callback, flags, interrogatingPid, interrogatingTid);
+                connection.findFocus(accessibilityNodeId, focusType, interactionId, callback,
+                        flags, interrogatingPid, interrogatingTid);
+                return getCompatibilityScale(resolvedWindowId);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error calling findAccessibilityFocus()");
@@ -1499,7 +1768,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1507,12 +1776,17 @@
                 int direction, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
-            final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
-            final int windowLeft;
-            final int windowTop;
+            final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
+                final int resolvedUserId = mSecurityPolicy
+                        .resolveCallingUserIdEnforcingPermissionsLocked(
+                        UserHandle.getCallingUserId());
+                if (resolvedUserId != mCurrentUserId) {
+                    return -1;
+                }
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
+                resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
                 final boolean permissionGranted =
                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
                 if (!permissionGranted) {
@@ -1523,18 +1797,15 @@
                         return 0;
                     }
                 }
-                IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId);
-                mWindowManagerService.getWindowFrame(token, mTempBounds);
-                windowLeft = mTempBounds.left;
-                windowTop = mTempBounds.top;
             }
             final int flags = (mIncludeNotImportantViews) ?
                     AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             try {
-                connection.focusSearch(accessibilityNodeId, direction, windowLeft, windowTop,
-                        interactionId, callback, flags, interrogatingPid, interrogatingTid);
+                connection.focusSearch(accessibilityNodeId, direction, interactionId, callback,
+                        flags, interrogatingPid, interrogatingTid);
+                return getCompatibilityScale(resolvedWindowId);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()");
@@ -1542,16 +1813,25 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
         public boolean performAccessibilityAction(int accessibilityWindowId,
                 long accessibilityNodeId, int action, Bundle arguments, int interactionId,
-                IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) {
-            final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
+                IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
+                throws RemoteException {
+            final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
+                final int resolvedUserId = mSecurityPolicy
+                        .resolveCallingUserIdEnforcingPermissionsLocked(
+                        UserHandle.getCallingUserId());
+                if (resolvedUserId != mCurrentUserId) {
+                    return false;
+                }
+                mSecurityPolicy.enforceCanRetrieveWindowContent(this);
+                resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
                 final boolean permissionGranted = mSecurityPolicy.canPerformActionLocked(this,
                         resolvedWindowId, action, arguments);
                 if (!permissionGranted) {
@@ -1581,21 +1861,37 @@
         }
 
         public boolean performGlobalAction(int action) {
-            switch (action) {
-                case AccessibilityService.GLOBAL_ACTION_BACK: {
-                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
-                } return true;
-                case AccessibilityService.GLOBAL_ACTION_HOME: {
-                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME);
-                } return true;
-                case AccessibilityService.GLOBAL_ACTION_RECENTS: {
-                    openRecents();
-                } return true;
-                case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: {
-                    expandStatusBar();
-                } return true;
+            synchronized (mLock) {
+                final int resolvedUserId = mSecurityPolicy
+                        .resolveCallingUserIdEnforcingPermissionsLocked(
+                        UserHandle.getCallingUserId());
+                if (resolvedUserId != mCurrentUserId) {
+                    return false;
+                }
             }
-            return false;
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                switch (action) {
+                    case AccessibilityService.GLOBAL_ACTION_BACK: {
+                        sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
+                    } return true;
+                    case AccessibilityService.GLOBAL_ACTION_HOME: {
+                        sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME);
+                    } return true;
+                    case AccessibilityService.GLOBAL_ACTION_RECENTS: {
+                        openRecents();
+                    } return true;
+                    case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: {
+                        expandNotifications();
+                    } return true;
+                    case AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS: {
+                        expandQuickSettings();
+                    } return true;
+                }
+                return false;
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
         }
 
         public void onServiceDisconnected(ComponentName componentName) {
@@ -1630,18 +1926,7 @@
                 // the state based on values in the settings database.
                 if (mIsAutomation) {
                     mUiAutomationService = null;
-
-                    populateEnabledAccessibilityServicesLocked();
-                    populateTouchExplorationGrantedAccessibilityServicesLocked();
-
-                    handleAccessibilityEnabledSettingChangedLocked();
-                    sendStateToClientsLocked();
-
-                    handleTouchExplorationEnabledSettingChangedLocked();
-                    updateInputFilterLocked();
-
-                    populateAccessibilityServiceListLocked();
-                    manageServicesLocked();
+                    recreateInternalStateLocked(getUserStateLocked(mUserId));
                 }
             }
         }
@@ -1772,12 +2057,22 @@
             Binder.restoreCallingIdentity(token);
         }
 
-        private void expandStatusBar() {
+        private void expandNotifications() {
             final long token = Binder.clearCallingIdentity();
 
             StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
                     android.app.Service.STATUS_BAR_SERVICE);
-            statusBarManager.expand();
+            statusBarManager.expandNotificationsPanel();
+
+            Binder.restoreCallingIdentity(token);
+        }
+
+        private void expandQuickSettings() {
+            final long token = Binder.clearCallingIdentity();
+
+            StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
+                    android.app.Service.STATUS_BAR_SERVICE);
+            statusBarManager.expandSettingsPanel();
 
             Binder.restoreCallingIdentity(token);
         }
@@ -1800,8 +2095,10 @@
             if (DEBUG) {
                 Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
             }
-            AccessibilityConnectionWrapper wrapper = mWindowIdToInteractionConnectionWrapperMap.get(
-                    windowId);
+            AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId);
+            if (wrapper == null) {
+                wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId);
+            }
             if (wrapper != null && wrapper.mConnection != null) {
                 return wrapper.mConnection;
             }
@@ -1811,7 +2108,7 @@
             return null;
         }
 
-        private int resolveAccessibilityWindowId(int accessibilityWindowId) {
+        private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) {
             if (accessibilityWindowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) {
                 return mSecurityPolicy.mActiveWindowId;
             }
@@ -1819,8 +2116,19 @@
         }
 
         private float getCompatibilityScale(int windowId) {
-            IBinder windowToken = mWindowIdToWindowTokenMap.get(windowId);
-            return mWindowManagerService.getWindowCompatibilityScale(windowToken);
+            try {
+                IBinder windowToken = mGlobalWindowTokens.get(windowId);
+                if (windowToken != null) {
+                    return mWindowManagerService.getWindowCompatibilityScale(windowToken);
+                }
+                windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId);
+                if (windowToken != null) {
+                    return mWindowManagerService.getWindowCompatibilityScale(windowToken);
+                }
+            } catch (RemoteException re) {
+                /* ignore */
+            }
+            return 1.0f;
         }
     }
 
@@ -1857,38 +2165,78 @@
             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED;
 
         private int mActiveWindowId;
+        private boolean mTouchInteractionInProgress;
 
         private boolean canDispatchAccessibilityEvent(AccessibilityEvent event) {
-            // Send window changed event only for the retrieval allowing window.
-            return (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
-                    || event.getWindowId() == mActiveWindowId);
+            final int eventType = event.getEventType();
+            switch (eventType) {
+                // All events that are for changes in a global window
+                // state should *always* be dispatched.
+                case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
+                case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
+                // All events generated by the user touching the
+                // screen should *always* be dispatched.
+                case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START:
+                case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END:
+                case AccessibilityEvent.TYPE_GESTURE_DETECTION_START:
+                case AccessibilityEvent.TYPE_GESTURE_DETECTION_END:
+                case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START:
+                case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END:
+                // These will change the active window, so dispatch.
+                case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
+                case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: {
+                    return true;
+                }
+                // All events for changes in window content should be
+                // dispatched *only* if this window is the active one.
+                default:
+                    return event.getWindowId() == mActiveWindowId;
+            }
         }
 
-        public void updateActiveWindowAndEventSourceLocked(AccessibilityEvent event) {
+        public void updateEventSourceLocked(AccessibilityEvent event) {
+            if ((event.getEventType() & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) {
+                event.setSource(null);
+            }
+        }
+
+        public void updateActiveWindow(int windowId, int eventType) {
             // The active window is either the window that has input focus or
             // the window that the user is currently touching. If the user is
             // touching a window that does not have input focus as soon as the
             // the user stops touching that window the focused window becomes
             // the active one.
-            final int windowId = event.getWindowId();
-            final int eventType = event.getEventType();
             switch (eventType) {
                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
                     if (getFocusedWindowId() == windowId) {
                         mActiveWindowId = windowId;
                     }
                 } break;
-                case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
-                case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: {
-                    mActiveWindowId = windowId;
-                } break;
-                case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END: {
-                    mActiveWindowId = getFocusedWindowId();
+                case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: {
+                    // Do not allow delayed hover events to confuse us
+                    // which the active window is.
+                    if (mTouchInteractionInProgress) {
+                        mActiveWindowId = windowId;
+                    }
                 } break;
             }
-            if ((eventType & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) {
-                event.setSource(null);
-            }
+        }
+
+        public void onTouchInteractionStart() {
+            mTouchInteractionInProgress = true;
+        }
+
+        public void onTouchInteractionEnd() {
+            mTouchInteractionInProgress = false;
+            // We want to set the active window to be current immediately
+            // after the user has stopped touching the screen since if the
+            // user types with the IME he should get a feedback for the
+            // letter typed in the text view which is in the input focused
+            // window. Note that we always deliver hover accessibility events
+            // (they are a result of user touching the screen) so change of
+            // the active window before all hover accessibility events from
+            // the touched window are delivered is fine.
+            mActiveWindowId = getFocusedWindowId();
         }
 
         public int getRetrievalAllowingWindowLocked() {
@@ -1919,6 +2267,38 @@
             }
         }
 
+        public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) {
+            final int callingUid = Binder.getCallingUid();
+            if (callingUid == Process.SYSTEM_UID
+                    || callingUid == Process.SHELL_UID) {
+                return mCurrentUserId;
+            }
+            final int callingUserId = UserHandle.getUserId(callingUid);
+            if (callingUserId == userId) {
+                return userId;
+            }
+            if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS)
+                    && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) {
+                throw new SecurityException("Call from user " + callingUserId + " as user "
+                        + userId + " without permission INTERACT_ACROSS_USERS or "
+                        + "INTERACT_ACROSS_USERS_FULL not allowed.");
+            }
+            if (userId == UserHandle.USER_CURRENT
+                    || userId == UserHandle.USER_CURRENT_OR_SELF) {
+                return mCurrentUserId;
+            }
+            throw new IllegalArgumentException("Calling user can be changed to only "
+                    + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF.");
+        }
+
+        public boolean isCallerInteractingAcrossUsers(int userId) {
+            final int callingUid = Binder.getCallingUid();
+            return (Binder.getCallingPid() == android.os.Process.myPid()
+                    || callingUid == Process.SHELL_UID
+                    || userId == UserHandle.USER_CURRENT
+                    || userId == UserHandle.USER_CURRENT_OR_SELF);
+        }
+
         private boolean isRetrievalAllowingWindow(int windowId) {
             return (mActiveWindowId == windowId);
         }
@@ -1931,28 +2311,212 @@
             if (OWN_PROCESS_ID == Binder.getCallingPid()) {
                 return;
             }
-            final int permissionStatus = mContext.checkCallingPermission(permission);
-            if (permissionStatus != PackageManager.PERMISSION_GRANTED) {
+            if (!hasPermission(permission)) {
                 throw new SecurityException("You do not have " + permission
                         + " required to call " + function);
             }
         }
 
+        private boolean hasPermission(String permission) {
+            return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED;
+        }
+
         private int getFocusedWindowId() {
-            // We call this only on window focus change or after touch
-            // exploration gesture end and the shown windows are not that
-            // many, so the linear look up is just fine.
-            IBinder token = mWindowManagerService.getFocusedWindowClientToken();
-            if (token != null) {
-                SparseArray<IBinder> windows = mWindowIdToWindowTokenMap;
-                final int windowCount = windows.size();
-                for (int i = 0; i < windowCount; i++) {
-                    if (windows.valueAt(i) == token) {
-                        return windows.keyAt(i);
+            try {
+                // We call this only on window focus change or after touch
+                // exploration gesture end and the shown windows are not that
+                // many, so the linear look up is just fine.
+                IBinder token = mWindowManagerService.getFocusedWindowToken();
+                if (token != null) {
+                    synchronized (mLock) {
+                        int windowId = getFocusedWindowIdLocked(token, mGlobalWindowTokens);
+                        if (windowId < 0) {
+                            windowId = getFocusedWindowIdLocked(token,
+                                    getCurrentUserStateLocked().mWindowTokens);
+                        }
+                        return windowId;
                     }
                 }
+            } catch (RemoteException re) {
+                /* ignore */
+            }
+            return -1;
+        }
+
+        private int getFocusedWindowIdLocked(IBinder token, SparseArray<IBinder> windows) {
+            final int windowCount = windows.size();
+            for (int i = 0; i < windowCount; i++) {
+                if (windows.valueAt(i) == token) {
+                    return windows.keyAt(i);
+                }
             }
             return -1;
         }
     }
+
+    private class UserState {
+        public final int mUserId;
+
+        public final CopyOnWriteArrayList<Service> mServices = new CopyOnWriteArrayList<Service>();
+
+        public final RemoteCallbackList<IAccessibilityManagerClient> mClients =
+            new RemoteCallbackList<IAccessibilityManagerClient>();
+
+        public final Map<ComponentName, Service> mComponentNameToServiceMap =
+                new HashMap<ComponentName, Service>();
+
+        public final List<AccessibilityServiceInfo> mInstalledServices =
+                new ArrayList<AccessibilityServiceInfo>();
+
+        public final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>();
+
+        public final Set<ComponentName> mTouchExplorationGrantedServices =
+                new HashSet<ComponentName>();
+
+        public final SparseArray<AccessibilityConnectionWrapper>
+                mInteractionConnections =
+                new SparseArray<AccessibilityConnectionWrapper>();
+
+        public final SparseArray<IBinder> mWindowTokens = new SparseArray<IBinder>();
+
+        public int mHandledFeedbackTypes = 0;
+
+        public boolean mIsAccessibilityEnabled;
+        public boolean mIsTouchExplorationEnabled;
+        public boolean mIsDisplayMagnificationEnabled;
+
+        public UserState(int userId) {
+            mUserId = userId;
+        }
+    }
+
+    private class TempUserStateChangeMemento {
+        public int mUserId = UserHandle.USER_NULL;
+        public boolean mIsAccessibilityEnabled;
+        public boolean mIsTouchExplorationEnabled;
+        public boolean mIsDisplayMagnificationEnabled;
+        public final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>();
+        public final Set<ComponentName> mTouchExplorationGrantedServices =
+                new HashSet<ComponentName>();
+
+        public void initialize(int userId, UserState userState) {
+            mUserId = userId;
+            mIsAccessibilityEnabled = userState.mIsAccessibilityEnabled;
+            mIsTouchExplorationEnabled = userState.mIsTouchExplorationEnabled;
+            mIsDisplayMagnificationEnabled = userState.mIsDisplayMagnificationEnabled;
+            mEnabledServices.clear();
+            mEnabledServices.addAll(userState.mEnabledServices);
+            mTouchExplorationGrantedServices.clear();
+            mTouchExplorationGrantedServices.addAll(userState.mTouchExplorationGrantedServices);
+        }
+
+        public void applyTo(UserState userState) {
+            userState.mIsAccessibilityEnabled = mIsAccessibilityEnabled;
+            userState.mIsTouchExplorationEnabled = mIsTouchExplorationEnabled;
+            userState.mIsDisplayMagnificationEnabled = mIsDisplayMagnificationEnabled;
+            userState.mEnabledServices.clear();
+            userState.mEnabledServices.addAll(mEnabledServices);
+            userState.mTouchExplorationGrantedServices.clear();
+            userState.mTouchExplorationGrantedServices.addAll(mTouchExplorationGrantedServices);
+        }
+
+        public void clear() {
+            mUserId = UserHandle.USER_NULL;
+            mIsAccessibilityEnabled = false;
+            mIsTouchExplorationEnabled = false;
+            mIsDisplayMagnificationEnabled = false;
+            mEnabledServices.clear();
+            mTouchExplorationGrantedServices.clear();
+        }
+    }
+
+    private final class AccessibilityContentObserver extends ContentObserver {
+
+        private final Uri mAccessibilityEnabledUri = Settings.Secure.getUriFor(
+                Settings.Secure.ACCESSIBILITY_ENABLED);
+
+        private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor(
+                Settings.Secure.TOUCH_EXPLORATION_ENABLED);
+
+        private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor(
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
+
+        private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor(
+                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
+
+        private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure
+                .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
+
+        public AccessibilityContentObserver(Handler handler) {
+            super(handler);
+        }
+
+        public void register(ContentResolver contentResolver) {
+            contentResolver.registerContentObserver(mAccessibilityEnabledUri,
+                    false, this, UserHandle.USER_ALL);
+            contentResolver.registerContentObserver(mTouchExplorationEnabledUri,
+                    false, this, UserHandle.USER_ALL);
+            contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri,
+                    false, this, UserHandle.USER_ALL);
+            contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri,
+                    false, this, UserHandle.USER_ALL);
+            contentResolver.registerContentObserver(
+                    mTouchExplorationGrantedAccessibilityServicesUri,
+                    false, this, UserHandle.USER_ALL);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            if (mAccessibilityEnabledUri.equals(uri)) {
+                synchronized (mLock) {
+                    // We will update when the automation service dies.
+                    if (mUiAutomationService == null) {
+                        UserState userState = getCurrentUserStateLocked();
+                        handleAccessibilityEnabledSettingChangedLocked(userState);
+                        performServiceManagementLocked(userState);
+                        updateInputFilterLocked(userState);
+                        scheduleSendStateToClientsLocked(userState);
+                    }
+                }
+            } else if (mTouchExplorationEnabledUri.equals(uri)) {
+                synchronized (mLock) {
+                    // We will update when the automation service dies.
+                    if (mUiAutomationService == null) {
+                        UserState userState = getCurrentUserStateLocked();
+                        handleTouchExplorationEnabledSettingChangedLocked(userState);
+                        updateInputFilterLocked(userState);
+                        scheduleSendStateToClientsLocked(userState);
+                    }
+                }
+            } else if (mDisplayMagnificationEnabledUri.equals(uri)) {
+                synchronized (mLock) {
+                    // We will update when the automation service dies.
+                    if (mUiAutomationService == null) {
+                        UserState userState = getCurrentUserStateLocked();
+                        handleDisplayMagnificationEnabledSettingChangedLocked(userState);
+                        updateInputFilterLocked(userState);
+                        scheduleSendStateToClientsLocked(userState);
+                    }
+                }
+            } else if (mEnabledAccessibilityServicesUri.equals(uri)) {
+                synchronized (mLock) {
+                    // We will update when the automation service dies.
+                    if (mUiAutomationService == null) {
+                        UserState userState = getCurrentUserStateLocked();
+                        populateEnabledAccessibilityServicesLocked(userState);
+                        manageServicesLocked(userState);
+                    }
+                }
+            } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
+                synchronized (mLock) {
+                    // We will update when the automation service dies.
+                    if (mUiAutomationService == null) {
+                        UserState userState = getCurrentUserStateLocked();
+                        populateTouchExplorationGrantedAccessibilityServicesLocked(userState);
+                        handleTouchExplorationGrantedAccessibilityServicesChangedLocked(userState);
+                    }
+                }
+            }
+        }
+    }
 }
diff --git a/services/java/com/android/server/accessibility/EventStreamTransformation.java b/services/java/com/android/server/accessibility/EventStreamTransformation.java
new file mode 100644
index 0000000..3289a15
--- /dev/null
+++ b/services/java/com/android/server/accessibility/EventStreamTransformation.java
@@ -0,0 +1,93 @@
+/*
+ ** Copyright 2012, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+package com.android.server.accessibility;
+
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.accessibility.AccessibilityEvent;
+
+/**
+ * Interface for classes that can handle and potentially transform a stream of
+ * motion and accessibility events. Instances implementing this interface are
+ * ordered in a sequence to implement a transformation chain. An instance may
+ * consume, modify, and generate events. It is responsible to deliver the
+ * output events to the next transformation in the sequence set via
+ * {@link #setNext(EventStreamTransformation)}.
+ *
+ * Note that since instances implementing this interface are transformations
+ * of the event stream, an instance should work against the event stream
+ * potentially modified by previous ones. Hence, the order of transformations
+ * is important.
+ *
+ * It is a responsibility of each handler that decides to react to an event
+ * sequence and prevent any subsequent ones from performing an action to send
+ * the appropriate cancel event given it has delegated a part of the events
+ * that belong to the current gesture. This will ensure that subsequent
+ * transformations will not be left in an inconsistent state and the applications
+ * see a consistent event stream.
+ *
+ * For example, to cancel a {@link KeyEvent} the handler has to emit an event
+ * with action {@link KeyEvent#ACTION_UP} with the additional flag
+ * {@link KeyEvent#FLAG_CANCELED}. To cancel a {@link MotionEvent} the handler
+ * has to send an event with action {@link MotionEvent#ACTION_CANCEL}.
+ *
+ * It is a responsibility of each handler that received a cancel event to clear its
+ * internal state and to propagate the event to the next one to enable subsequent
+ * transformations to clear their internal state.
+ *
+ * It is a responsibility for each transformation to start handling events only
+ * after an event that designates the start of a well-formed event sequence.
+ * For example, if it received a down motion event followed by a cancel motion
+ * event, it should not handle subsequent move and up events until it gets a down.
+ */
+interface EventStreamTransformation {
+
+    /**
+     * Receives motion event. Passed are the event transformed by previous
+     * transformations and the raw event to which no transformations have
+     * been applied.
+     *
+     * @param event The transformed motion event.
+     * @param rawEvent The raw motion event.
+     * @param policyFlags Policy flags for the event.
+     */
+    public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags);
+
+    /**
+     * Receives an accessibility event.
+     *
+     * @param event The accessibility event.
+     */
+    public void onAccessibilityEvent(AccessibilityEvent event);
+
+    /**
+     * Sets the next transformation.
+     *
+     * @param next The next transformation.
+     */
+    public void setNext(EventStreamTransformation next);
+
+    /**
+     * Clears the internal state of this transformation.
+     */
+    public void clear();
+
+    /**
+     * Destroys this transformation.
+     */
+    public void onDestroy();
+}
diff --git a/services/java/com/android/server/accessibility/GestureUtils.java b/services/java/com/android/server/accessibility/GestureUtils.java
new file mode 100644
index 0000000..b68b09f
--- /dev/null
+++ b/services/java/com/android/server/accessibility/GestureUtils.java
@@ -0,0 +1,102 @@
+package com.android.server.accessibility;
+
+import android.util.MathUtils;
+import android.view.MotionEvent;
+
+/**
+ * Some helper functions for gesture detection.
+ */
+final class GestureUtils {
+
+    private GestureUtils() {
+        /* cannot be instantiated */
+    }
+
+    public static boolean isTap(MotionEvent down, MotionEvent up, int tapTimeSlop,
+            int tapDistanceSlop, int actionIndex) {
+        return eventsWithinTimeAndDistanceSlop(down, up, tapTimeSlop, tapDistanceSlop, actionIndex);
+    }
+
+    public static boolean isMultiTap(MotionEvent firstUp, MotionEvent secondUp,
+            int multiTapTimeSlop, int multiTapDistanceSlop, int actionIndex) {
+        return eventsWithinTimeAndDistanceSlop(firstUp, secondUp, multiTapTimeSlop,
+                multiTapDistanceSlop, actionIndex);
+    }
+
+    private static boolean eventsWithinTimeAndDistanceSlop(MotionEvent first, MotionEvent second,
+            int timeout, int distance, int actionIndex) {
+        if (isTimedOut(first, second, timeout)) {
+            return false;
+        }
+        final double deltaMove = computeDistance(first, second, actionIndex);
+        if (deltaMove >= distance) {
+            return false;
+        }
+        return true;
+    }
+
+    public static double computeDistance(MotionEvent first, MotionEvent second, int pointerIndex) {
+         return MathUtils.dist(first.getX(pointerIndex), first.getY(pointerIndex),
+                 second.getX(pointerIndex), second.getY(pointerIndex));
+    }
+
+    public static boolean isTimedOut(MotionEvent firstUp, MotionEvent secondUp, int timeout) {
+        final long deltaTime = secondUp.getEventTime() - firstUp.getEventTime();
+        return (deltaTime >= timeout);
+    }
+
+    public static boolean isSamePointerContext(MotionEvent first, MotionEvent second) {
+        return (first.getPointerIdBits() == second.getPointerIdBits()
+                && first.getPointerId(first.getActionIndex())
+                        == second.getPointerId(second.getActionIndex()));
+    }
+
+    /**
+     * Determines whether a two pointer gesture is a dragging one.
+     *
+     * @param event The event with the pointer data.
+     * @return True if the gesture is a dragging one.
+     */
+    public static boolean isDraggingGesture(float firstPtrDownX, float firstPtrDownY,
+            float secondPtrDownX, float secondPtrDownY, float firstPtrX, float firstPtrY,
+            float secondPtrX, float secondPtrY, float maxDraggingAngleCos) {
+
+        // Check if the pointers are moving in the same direction.
+        final float firstDeltaX = firstPtrX - firstPtrDownX;
+        final float firstDeltaY = firstPtrY - firstPtrDownY;
+
+        if (firstDeltaX == 0 && firstDeltaY == 0) {
+            return true;
+        }
+
+        final float firstMagnitude =
+            (float) Math.sqrt(firstDeltaX * firstDeltaX + firstDeltaY * firstDeltaY);
+        final float firstXNormalized =
+            (firstMagnitude > 0) ? firstDeltaX / firstMagnitude : firstDeltaX;
+        final float firstYNormalized =
+            (firstMagnitude > 0) ? firstDeltaY / firstMagnitude : firstDeltaY;
+
+        final float secondDeltaX = secondPtrX - secondPtrDownX;
+        final float secondDeltaY = secondPtrY - secondPtrDownY;
+
+        if (secondDeltaX == 0 && secondDeltaY == 0) {
+            return true;
+        }
+
+        final float secondMagnitude =
+            (float) Math.sqrt(secondDeltaX * secondDeltaX + secondDeltaY * secondDeltaY);
+        final float secondXNormalized =
+            (secondMagnitude > 0) ? secondDeltaX / secondMagnitude : secondDeltaX;
+        final float secondYNormalized =
+            (secondMagnitude > 0) ? secondDeltaY / secondMagnitude : secondDeltaY;
+
+        final float angleCos =
+            firstXNormalized * secondXNormalized + firstYNormalized * secondYNormalized;
+
+        if (angleCos < maxDraggingAngleCos) {
+            return false;
+        }
+
+        return true;
+    }
+}
diff --git a/services/java/com/android/server/accessibility/ScreenMagnifier.java b/services/java/com/android/server/accessibility/ScreenMagnifier.java
new file mode 100644
index 0000000..482bff5
--- /dev/null
+++ b/services/java/com/android/server/accessibility/ScreenMagnifier.java
@@ -0,0 +1,1861 @@
+/*
+ * 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.accessibility;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.ObjectAnimator;
+import android.animation.TypeEvaluator;
+import android.animation.ValueAnimator;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Property;
+import android.util.Slog;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.GestureDetector;
+import android.view.GestureDetector.SimpleOnGestureListener;
+import android.view.Gravity;
+import android.view.IDisplayContentChangeListener;
+import android.view.IWindowManager;
+import android.view.MotionEvent;
+import android.view.MotionEvent.PointerCoords;
+import android.view.MotionEvent.PointerProperties;
+import android.view.ScaleGestureDetector;
+import android.view.ScaleGestureDetector.OnScaleGestureListener;
+import android.view.Surface;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.WindowInfo;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+
+import com.android.internal.R;
+import com.android.internal.os.SomeArgs;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Locale;
+
+/**
+ * This class handles the screen magnification when accessibility is enabled.
+ * The behavior is as follows:
+ *
+ * 1. Triple tap toggles permanent screen magnification which is magnifying
+ *    the area around the location of the triple tap. One can think of the
+ *    location of the triple tap as the center of the magnified viewport.
+ *    For example, a triple tap when not magnified would magnify the screen
+ *    and leave it in a magnified state. A triple tapping when magnified would
+ *    clear magnification and leave the screen in a not magnified state.
+ *
+ * 2. Triple tap and hold would magnify the screen if not magnified and enable
+ *    viewport dragging mode until the finger goes up. One can think of this
+ *    mode as a way to move the magnified viewport since the area around the
+ *    moving finger will be magnified to fit the screen. For example, if the
+ *    screen was not magnified and the user triple taps and holds the screen
+ *    would magnify and the viewport will follow the user's finger. When the
+ *    finger goes up the screen will clear zoom out. If the same user interaction
+ *    is performed when the screen is magnified, the viewport movement will
+ *    be the same but when the finger goes up the screen will stay magnified.
+ *    In other words, the initial magnified state is sticky.
+ *
+ * 3. Pinching with any number of additional fingers when viewport dragging
+ *    is enabled, i.e. the user triple tapped and holds, would adjust the
+ *    magnification scale which will become the current default magnification
+ *    scale. The next time the user magnifies the same magnification scale
+ *    would be used.
+ *
+ * 4. When in a permanent magnified state the user can use two or more fingers
+ *    to pan the viewport. Note that in this mode the content is panned as
+ *    opposed to the viewport dragging mode in which the viewport is moved.
+ *
+ * 5. When in a permanent magnified state the user can use three or more
+ *    fingers to change the magnification scale which will become the current
+ *    default magnification scale. The next time the user magnifies the same
+ *    magnification scale would be used.
+ *
+ * 6. The magnification scale will be persisted in settings and in the cloud.
+ */
+public final class ScreenMagnifier implements EventStreamTransformation {
+
+    private static final boolean DEBUG_STATE_TRANSITIONS = false;
+    private static final boolean DEBUG_DETECTING = false;
+    private static final boolean DEBUG_TRANSFORMATION = false;
+    private static final boolean DEBUG_PANNING = false;
+    private static final boolean DEBUG_SCALING = false;
+    private static final boolean DEBUG_VIEWPORT_WINDOW = false;
+    private static final boolean DEBUG_WINDOW_TRANSITIONS = false;
+    private static final boolean DEBUG_ROTATION = false;
+    private static final boolean DEBUG_MAGNIFICATION_CONTROLLER = false;
+
+    private static final String LOG_TAG = ScreenMagnifier.class.getSimpleName();
+
+    private static final int STATE_DELEGATING = 1;
+    private static final int STATE_DETECTING = 2;
+    private static final int STATE_VIEWPORT_DRAGGING = 3;
+    private static final int STATE_MAGNIFIED_INTERACTION = 4;
+
+    private static final float DEFAULT_MAGNIFICATION_SCALE = 2.0f;
+    private static final int DEFAULT_SCREEN_MAGNIFICATION_AUTO_UPDATE = 1;
+    private static final float DEFAULT_WINDOW_ANIMATION_SCALE = 1.0f;
+
+    private static final int MULTI_TAP_TIME_SLOP_ADJUSTMENT = 50;
+
+    private final IWindowManager mWindowManagerService = IWindowManager.Stub.asInterface(
+            ServiceManager.getService("window"));
+    private final WindowManager mWindowManager;
+    private final DisplayProvider mDisplayProvider;
+
+    private final DetectingStateHandler mDetectingStateHandler = new DetectingStateHandler();
+    private final MagnifiedContentInteractonStateHandler mMagnifiedContentInteractonStateHandler;
+    private final StateViewportDraggingHandler mStateViewportDraggingHandler =
+            new StateViewportDraggingHandler();
+
+    private final Interpolator mInterpolator = new DecelerateInterpolator(2.5f);
+
+    private final MagnificationController mMagnificationController;
+    private final DisplayContentObserver mDisplayContentObserver;
+    private final ScreenStateObserver mScreenStateObserver;
+    private final Viewport mViewport;
+
+    private final int mTapTimeSlop = ViewConfiguration.getTapTimeout();
+    private final int mMultiTapTimeSlop =
+            ViewConfiguration.getDoubleTapTimeout() - MULTI_TAP_TIME_SLOP_ADJUSTMENT;
+    private final int mTapDistanceSlop;
+    private final int mMultiTapDistanceSlop;
+
+    private final int mShortAnimationDuration;
+    private final int mLongAnimationDuration;
+    private final float mWindowAnimationScale;
+
+    private final Context mContext;
+
+    private EventStreamTransformation mNext;
+
+    private int mCurrentState;
+    private int mPreviousState;
+    private boolean mTranslationEnabledBeforePan;
+
+    private PointerCoords[] mTempPointerCoords;
+    private PointerProperties[] mTempPointerProperties;
+
+    private long mDelegatingStateDownTime;
+
+    public ScreenMagnifier(Context context) {
+        mContext = context;
+        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+
+        mShortAnimationDuration = context.getResources().getInteger(
+                com.android.internal.R.integer.config_shortAnimTime);
+        mLongAnimationDuration = context.getResources().getInteger(
+                com.android.internal.R.integer.config_longAnimTime);
+        mTapDistanceSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+        mMultiTapDistanceSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop();
+        mWindowAnimationScale = Settings.Global.getFloat(context.getContentResolver(),
+                Settings.Global.WINDOW_ANIMATION_SCALE, DEFAULT_WINDOW_ANIMATION_SCALE);
+
+        mMagnificationController = new MagnificationController(mShortAnimationDuration);
+        mDisplayProvider = new DisplayProvider(context, mWindowManager);
+        mViewport = new Viewport(mContext, mWindowManager, mWindowManagerService,
+                mDisplayProvider, mInterpolator, mShortAnimationDuration);
+        mDisplayContentObserver = new DisplayContentObserver(mContext, mViewport,
+                mMagnificationController, mWindowManagerService, mDisplayProvider,
+                mLongAnimationDuration, mWindowAnimationScale);
+        mScreenStateObserver = new ScreenStateObserver(mContext, mViewport,
+                mMagnificationController);
+
+        mMagnifiedContentInteractonStateHandler = new MagnifiedContentInteractonStateHandler(
+                context);
+
+        transitionToState(STATE_DETECTING);
+    }
+
+    @Override
+    public void onMotionEvent(MotionEvent event, MotionEvent rawEvent,
+            int policyFlags) {
+        mMagnifiedContentInteractonStateHandler.onMotionEvent(event);
+        switch (mCurrentState) {
+            case STATE_DELEGATING: {
+                handleMotionEventStateDelegating(event, rawEvent, policyFlags);
+            } break;
+            case STATE_DETECTING: {
+                mDetectingStateHandler.onMotionEvent(event, rawEvent, policyFlags);
+            } break;
+            case STATE_VIEWPORT_DRAGGING: {
+                mStateViewportDraggingHandler.onMotionEvent(event, policyFlags);
+            } break;
+            case STATE_MAGNIFIED_INTERACTION: {
+                // mMagnifiedContentInteractonStateHandler handles events only
+                // if this is the current state since it uses ScaleGestureDetecotr
+                // and a GestureDetector which need well formed event stream.
+            } break;
+            default: {
+                throw new IllegalStateException("Unknown state: " + mCurrentState);
+            }
+        }
+    }
+
+    @Override
+    public void onAccessibilityEvent(AccessibilityEvent event) {
+        if (mNext != null) {
+            mNext.onAccessibilityEvent(event);
+        }
+    }
+
+    @Override
+    public void setNext(EventStreamTransformation next) {
+        mNext = next;
+    }
+
+    @Override
+    public void clear() {
+        mCurrentState = STATE_DETECTING;
+        mDetectingStateHandler.clear();
+        mStateViewportDraggingHandler.clear();
+        mMagnifiedContentInteractonStateHandler.clear();
+        if (mNext != null) {
+            mNext.clear();
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        mMagnificationController.setScaleAndMagnifiedRegionCenter(1.0f,
+                0, 0, true);
+        mViewport.setFrameShown(false, true);
+        mDisplayProvider.destroy();
+        mDisplayContentObserver.destroy();
+        mScreenStateObserver.destroy();
+    }
+
+    private void handleMotionEventStateDelegating(MotionEvent event,
+            MotionEvent rawEvent, int policyFlags) {
+        switch (event.getActionMasked()) {
+            case MotionEvent.ACTION_DOWN: {
+                mDelegatingStateDownTime = event.getDownTime();
+            } break;
+            case MotionEvent.ACTION_UP: {
+                if (mDetectingStateHandler.mDelayedEventQueue == null) {
+                    transitionToState(STATE_DETECTING);
+                }
+            } break;
+        }
+        if (mNext != null) {
+            // If the event is within the magnified portion of the screen we have
+            // to change its location to be where the user thinks he is poking the
+            // UI which may have been magnified and panned.
+            final float eventX = event.getX();
+            final float eventY = event.getY();
+            if (mMagnificationController.isMagnifying()
+                    && mViewport.getBounds().contains((int) eventX, (int) eventY)) {
+                final float scale = mMagnificationController.getScale();
+                final float scaledOffsetX = mMagnificationController.getScaledOffsetX();
+                final float scaledOffsetY = mMagnificationController.getScaledOffsetY();
+                final int pointerCount = event.getPointerCount();
+                PointerCoords[] coords = getTempPointerCoordsWithMinSize(pointerCount);
+                PointerProperties[] properties = getTempPointerPropertiesWithMinSize(pointerCount);
+                for (int i = 0; i < pointerCount; i++) {
+                    event.getPointerCoords(i, coords[i]);
+                    coords[i].x = (coords[i].x - scaledOffsetX) / scale;
+                    coords[i].y = (coords[i].y - scaledOffsetY) / scale;
+                    event.getPointerProperties(i, properties[i]);
+                }
+                event = MotionEvent.obtain(event.getDownTime(),
+                        event.getEventTime(), event.getAction(), pointerCount, properties,
+                        coords, 0, 0, 1.0f, 1.0f, event.getDeviceId(), 0, event.getSource(),
+                        event.getFlags());
+            }
+            // We cache some events to see if the user wants to trigger magnification.
+            // If no magnification is triggered we inject these events with adjusted
+            // time and down time to prevent subsequent transformations being confused
+            // by stale events. After the cached events, which always have a down, are
+            // injected we need to also update the down time of all subsequent non cached
+            // events. All delegated events cached and non-cached are delivered here.
+            event.setDownTime(mDelegatingStateDownTime);
+            mNext.onMotionEvent(event, rawEvent, policyFlags);
+        }
+    }
+
+    private PointerCoords[] getTempPointerCoordsWithMinSize(int size) {
+        final int oldSize = (mTempPointerCoords != null) ? mTempPointerCoords.length : 0;
+        if (oldSize < size) {
+            PointerCoords[] oldTempPointerCoords = mTempPointerCoords;
+            mTempPointerCoords = new PointerCoords[size];
+            if (oldTempPointerCoords != null) {
+                System.arraycopy(oldTempPointerCoords, 0, mTempPointerCoords, 0, oldSize);
+            }
+        }
+        for (int i = oldSize; i < size; i++) {
+            mTempPointerCoords[i] = new PointerCoords();
+        }
+        return mTempPointerCoords;
+    }
+
+    private PointerProperties[] getTempPointerPropertiesWithMinSize(int size) {
+        final int oldSize = (mTempPointerProperties != null) ? mTempPointerProperties.length : 0;
+        if (oldSize < size) {
+            PointerProperties[] oldTempPointerProperties = mTempPointerProperties;
+            mTempPointerProperties = new PointerProperties[size];
+            if (oldTempPointerProperties != null) {
+                System.arraycopy(oldTempPointerProperties, 0, mTempPointerProperties, 0, oldSize);
+            }
+        }
+        for (int i = oldSize; i < size; i++) {
+            mTempPointerProperties[i] = new PointerProperties();
+        }
+        return mTempPointerProperties;
+    }
+    
+    private void transitionToState(int state) {
+        if (DEBUG_STATE_TRANSITIONS) {
+            switch (state) {
+                case STATE_DELEGATING: {
+                    Slog.i(LOG_TAG, "mCurrentState: STATE_DELEGATING");
+                } break;
+                case STATE_DETECTING: {
+                    Slog.i(LOG_TAG, "mCurrentState: STATE_DETECTING");
+                } break;
+                case STATE_VIEWPORT_DRAGGING: {
+                    Slog.i(LOG_TAG, "mCurrentState: STATE_VIEWPORT_DRAGGING");
+                } break;
+                case STATE_MAGNIFIED_INTERACTION: {
+                    Slog.i(LOG_TAG, "mCurrentState: STATE_MAGNIFIED_INTERACTION");
+                } break;
+                default: {
+                    throw new IllegalArgumentException("Unknown state: " + state);
+                }
+            }
+        }
+        mPreviousState = mCurrentState;
+        mCurrentState = state;
+    }
+
+    private final class MagnifiedContentInteractonStateHandler
+            extends SimpleOnGestureListener implements OnScaleGestureListener {
+        private static final float MIN_SCALE = 1.3f;
+        private static final float MAX_SCALE = 5.0f;
+
+        private static final float SCALING_THRESHOLD = 0.3f;
+
+        private final ScaleGestureDetector mScaleGestureDetector;
+        private final GestureDetector mGestureDetector;
+
+        private float mInitialScaleFactor = -1;
+        private boolean mScaling;
+
+        public MagnifiedContentInteractonStateHandler(Context context) {
+            mScaleGestureDetector = new ScaleGestureDetector(context, this);
+            mGestureDetector = new GestureDetector(context, this);
+        }
+
+        public void onMotionEvent(MotionEvent event) {
+            mScaleGestureDetector.onTouchEvent(event);
+            mGestureDetector.onTouchEvent(event);
+            if (mCurrentState != STATE_MAGNIFIED_INTERACTION) {
+                return;
+            }
+            if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+                clear();
+                final float scale = Math.min(Math.max(mMagnificationController.getScale(),
+                        MIN_SCALE), MAX_SCALE);
+                if (scale != getPersistedScale()) {
+                    persistScale(scale);
+                }
+                if (mPreviousState == STATE_VIEWPORT_DRAGGING) {
+                    transitionToState(STATE_VIEWPORT_DRAGGING);
+                } else {
+                    transitionToState(STATE_DETECTING);
+                }
+            }
+        }
+
+        @Override
+        public boolean onScroll(MotionEvent first, MotionEvent second, float distanceX,
+                float distanceY) {
+            if (mCurrentState != STATE_MAGNIFIED_INTERACTION) {
+                return true;
+            }
+            final float scale = mMagnificationController.getScale();
+            final float scrollX = distanceX / scale;
+            final float scrollY = distanceY / scale;
+            final float centerX = mMagnificationController.getMagnifiedRegionCenterX() + scrollX;
+            final float centerY = mMagnificationController.getMagnifiedRegionCenterY() + scrollY;
+            if (DEBUG_PANNING) {
+                Slog.i(LOG_TAG, "Panned content by scrollX: " + scrollX
+                        + " scrollY: " + scrollY);
+            }
+            mMagnificationController.setMagnifiedRegionCenter(centerX, centerY, false);
+            return true;
+        }
+
+        @Override
+        public boolean onScale(ScaleGestureDetector detector) {
+            if (!mScaling) {
+                if (mInitialScaleFactor < 0) {
+                    mInitialScaleFactor = detector.getScaleFactor();
+                } else {
+                    final float deltaScale = detector.getScaleFactor() - mInitialScaleFactor;
+                    if (Math.abs(deltaScale) > SCALING_THRESHOLD) {
+                        mScaling = true;
+                        return true;
+                    }
+                }
+                return false;
+            }
+            final float newScale = mMagnificationController.getScale()
+                    * detector.getScaleFactor();
+            final float normalizedNewScale = Math.min(Math.max(newScale, MIN_SCALE), MAX_SCALE);
+            if (DEBUG_SCALING) {
+                Slog.i(LOG_TAG, "normalizedNewScale: " + normalizedNewScale);
+            }
+            mMagnificationController.setScale(normalizedNewScale, detector.getFocusX(),
+                    detector.getFocusY(), false);
+            return true;
+        }
+
+        @Override
+        public boolean onScaleBegin(ScaleGestureDetector detector) {
+            return (mCurrentState == STATE_MAGNIFIED_INTERACTION);
+        }
+
+        @Override
+        public void onScaleEnd(ScaleGestureDetector detector) {
+            clear();
+        }
+
+        private void clear() {
+            mInitialScaleFactor = -1;
+            mScaling = false;
+        }
+    }
+
+    private final class StateViewportDraggingHandler {
+        private boolean mLastMoveOutsideMagnifiedRegion;
+
+        private void onMotionEvent(MotionEvent event, int policyFlags) {
+            final int action = event.getActionMasked();
+            switch (action) {
+                case MotionEvent.ACTION_DOWN: {
+                    throw new IllegalArgumentException("Unexpected event type: ACTION_DOWN");
+                }
+                case MotionEvent.ACTION_POINTER_DOWN: {
+                    clear();
+                    transitionToState(STATE_MAGNIFIED_INTERACTION);
+                } break;
+                case MotionEvent.ACTION_MOVE: {
+                    if (event.getPointerCount() != 1) {
+                        throw new IllegalStateException("Should have one pointer down.");
+                    }
+                    final float eventX = event.getX();
+                    final float eventY = event.getY();
+                    if (mViewport.getBounds().contains((int) eventX, (int) eventY)) {
+                        if (mLastMoveOutsideMagnifiedRegion) {
+                            mLastMoveOutsideMagnifiedRegion = false;
+                            mMagnificationController.setMagnifiedRegionCenter(eventX,
+                                    eventY, true);
+                        } else {
+                            mMagnificationController.setMagnifiedRegionCenter(eventX,
+                                    eventY, false);
+                        }
+                    } else {
+                        mLastMoveOutsideMagnifiedRegion = true;
+                    }
+                } break;
+                case MotionEvent.ACTION_UP: {
+                    if (!mTranslationEnabledBeforePan) {
+                        mMagnificationController.reset(true);
+                        mViewport.setFrameShown(false, true);
+                    }
+                    clear();
+                    transitionToState(STATE_DETECTING);
+                } break;
+                case MotionEvent.ACTION_POINTER_UP: {
+                    throw new IllegalArgumentException("Unexpected event type: ACTION_POINTER_UP");
+                }
+            }
+        }
+
+        public void clear() {
+            mLastMoveOutsideMagnifiedRegion = false;
+        }
+    }
+
+    private final class DetectingStateHandler {
+
+        private static final int MESSAGE_ON_ACTION_TAP_AND_HOLD = 1;
+
+        private static final int MESSAGE_TRANSITION_TO_DELEGATING_STATE = 2;
+
+        private static final int ACTION_TAP_COUNT = 3;
+
+        private MotionEventInfo mDelayedEventQueue;
+
+        private MotionEvent mLastDownEvent;
+        private MotionEvent mLastTapUpEvent;
+        private int mTapCount;
+
+        private final Handler mHandler = new Handler() {
+            @Override
+            public void handleMessage(Message message) {
+                final int type = message.what;
+                switch (type) {
+                    case MESSAGE_ON_ACTION_TAP_AND_HOLD: {
+                        MotionEvent event = (MotionEvent) message.obj;
+                        final int policyFlags = message.arg1;
+                        onActionTapAndHold(event, policyFlags);
+                    } break;
+                    case MESSAGE_TRANSITION_TO_DELEGATING_STATE: {
+                        transitionToState(STATE_DELEGATING);
+                        sendDelayedMotionEvents();
+                        clear();
+                    } break;
+                    default: {
+                        throw new IllegalArgumentException("Unknown message type: " + type);
+                    }
+                }
+            }
+        };
+
+        public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+            cacheDelayedMotionEvent(event, rawEvent, policyFlags);
+            final int action = event.getActionMasked();
+            switch (action) {
+                case MotionEvent.ACTION_DOWN: {
+                    mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
+                    if (!mViewport.getBounds().contains((int) event.getX(),
+                            (int) event.getY())) {
+                        transitionToDelegatingStateAndClear();
+                        return;
+                    }
+                    if (mTapCount == ACTION_TAP_COUNT - 1 && mLastDownEvent != null
+                            && GestureUtils.isMultiTap(mLastDownEvent, event,
+                                    mMultiTapTimeSlop, mMultiTapDistanceSlop, 0)) {
+                        Message message = mHandler.obtainMessage(MESSAGE_ON_ACTION_TAP_AND_HOLD,
+                                policyFlags, 0, event);
+                        mHandler.sendMessageDelayed(message,
+                                ViewConfiguration.getLongPressTimeout());
+                    } else if (mTapCount < ACTION_TAP_COUNT) {
+                        Message message = mHandler.obtainMessage(
+                                MESSAGE_TRANSITION_TO_DELEGATING_STATE);
+                        mHandler.sendMessageDelayed(message, mMultiTapTimeSlop);
+                    }
+                    clearLastDownEvent();
+                    mLastDownEvent = MotionEvent.obtain(event);
+                } break;
+                case MotionEvent.ACTION_POINTER_DOWN: {
+                    if (mMagnificationController.isMagnifying()) {
+                        transitionToState(STATE_MAGNIFIED_INTERACTION);
+                        clear();
+                    } else {
+                        transitionToDelegatingStateAndClear();
+                    }
+                } break;
+                case MotionEvent.ACTION_MOVE: {
+                    if (mLastDownEvent != null && mTapCount < ACTION_TAP_COUNT - 1) {
+                        final double distance = GestureUtils.computeDistance(mLastDownEvent,
+                                event, 0);
+                        if (Math.abs(distance) > mTapDistanceSlop) {
+                            transitionToDelegatingStateAndClear();
+                        }
+                    }
+                } break;
+                case MotionEvent.ACTION_UP: {
+                    if (mLastDownEvent == null) {
+                        return;
+                    }
+                    mHandler.removeMessages(MESSAGE_ON_ACTION_TAP_AND_HOLD);
+                    if (!mViewport.getBounds().contains((int) event.getX(), (int) event.getY())) {
+                         transitionToDelegatingStateAndClear();
+                         return;
+                    }
+                    if (!GestureUtils.isTap(mLastDownEvent, event, mTapTimeSlop,
+                            mTapDistanceSlop, 0)) {
+                        transitionToDelegatingStateAndClear();
+                        return;
+                    }
+                    if (mLastTapUpEvent != null && !GestureUtils.isMultiTap(mLastTapUpEvent,
+                            event, mMultiTapTimeSlop, mMultiTapDistanceSlop, 0)) {
+                        transitionToDelegatingStateAndClear();
+                        return;
+                    }
+                    mTapCount++;
+                    if (DEBUG_DETECTING) {
+                        Slog.i(LOG_TAG, "Tap count:" + mTapCount);
+                    }
+                    if (mTapCount == ACTION_TAP_COUNT) {
+                        clear();
+                        onActionTap(event, policyFlags);
+                        return;
+                    }
+                    clearLastTapUpEvent();
+                    mLastTapUpEvent = MotionEvent.obtain(event);
+                } break;
+                case MotionEvent.ACTION_POINTER_UP: {
+                    /* do nothing */
+                } break;
+            }
+        }
+
+        public void clear() {
+            mHandler.removeMessages(MESSAGE_ON_ACTION_TAP_AND_HOLD);
+            mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
+            clearTapDetectionState();
+            clearDelayedMotionEvents();
+        }
+
+        private void clearTapDetectionState() {
+            mTapCount = 0;
+            clearLastTapUpEvent();
+            clearLastDownEvent();
+        }
+
+        private void clearLastTapUpEvent() {
+            if (mLastTapUpEvent != null) {
+                mLastTapUpEvent.recycle();
+                mLastTapUpEvent = null;
+            }
+        }
+
+        private void clearLastDownEvent() {
+            if (mLastDownEvent != null) {
+                mLastDownEvent.recycle();
+                mLastDownEvent = null;
+            }
+        }
+
+        private void cacheDelayedMotionEvent(MotionEvent event, MotionEvent rawEvent,
+                int policyFlags) {
+            MotionEventInfo info = MotionEventInfo.obtain(event, rawEvent,
+                    policyFlags);
+            if (mDelayedEventQueue == null) {
+                mDelayedEventQueue = info;
+            } else {
+                MotionEventInfo tail = mDelayedEventQueue;
+                while (tail.mNext != null) {
+                    tail = tail.mNext;
+                }
+                tail.mNext = info;
+            }
+        }
+
+        private void sendDelayedMotionEvents() {
+            while (mDelayedEventQueue != null) {
+                MotionEventInfo info = mDelayedEventQueue;
+                mDelayedEventQueue = info.mNext;
+                final long offset = SystemClock.uptimeMillis() - info.mCachedTimeMillis;
+                MotionEvent event = obtainEventWithOffsetTimeAndDownTime(info.mEvent, offset);
+                MotionEvent rawEvent = obtainEventWithOffsetTimeAndDownTime(info.mRawEvent, offset);
+                ScreenMagnifier.this.onMotionEvent(event, rawEvent, info.mPolicyFlags);
+                event.recycle();
+                rawEvent.recycle();
+                info.recycle();
+            }
+        }
+
+        private MotionEvent obtainEventWithOffsetTimeAndDownTime(MotionEvent event, long offset) {
+            final int pointerCount = event.getPointerCount();
+            PointerCoords[] coords = getTempPointerCoordsWithMinSize(pointerCount);
+            PointerProperties[] properties = getTempPointerPropertiesWithMinSize(pointerCount);
+            for (int i = 0; i < pointerCount; i++) {
+                event.getPointerCoords(i, coords[i]);
+                event.getPointerProperties(i, properties[i]);
+            }
+            final long downTime = event.getDownTime() + offset;
+            final long eventTime = event.getEventTime() + offset;
+            return MotionEvent.obtain(downTime, eventTime,
+                    event.getAction(), pointerCount, properties, coords,
+                    event.getMetaState(), event.getButtonState(),
+                    1.0f, 1.0f, event.getDeviceId(), event.getEdgeFlags(),
+                    event.getSource(), event.getFlags());
+        }
+
+        private void clearDelayedMotionEvents() {
+            while (mDelayedEventQueue != null) {
+                MotionEventInfo info = mDelayedEventQueue;
+                mDelayedEventQueue = info.mNext;
+                info.recycle();
+            }
+        }
+
+        private void transitionToDelegatingStateAndClear() {
+            transitionToState(STATE_DELEGATING);
+            sendDelayedMotionEvents();
+            clear();
+        }
+
+        private void onActionTap(MotionEvent up, int policyFlags) {
+            if (DEBUG_DETECTING) {
+                Slog.i(LOG_TAG, "onActionTap()");
+            }
+            if (!mMagnificationController.isMagnifying()) {
+                mMagnificationController.setScaleAndMagnifiedRegionCenter(getPersistedScale(),
+                        up.getX(), up.getY(), true);
+                mViewport.setFrameShown(true, true);
+            } else {
+                mMagnificationController.reset(true);
+                mViewport.setFrameShown(false, true);
+            }
+        }
+
+        private void onActionTapAndHold(MotionEvent down, int policyFlags) {
+            if (DEBUG_DETECTING) {
+                Slog.i(LOG_TAG, "onActionTapAndHold()");
+            }
+            clear();
+            mTranslationEnabledBeforePan = mMagnificationController.isMagnifying();
+            mMagnificationController.setScaleAndMagnifiedRegionCenter(getPersistedScale(),
+                    down.getX(), down.getY(), true);
+            mViewport.setFrameShown(true, true);
+            transitionToState(STATE_VIEWPORT_DRAGGING);
+        }
+    }
+
+    private void persistScale(final float scale) {
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                Settings.Secure.putFloat(mContext.getContentResolver(),
+                        Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, scale);
+                return null;
+            }
+        }.execute();
+    }
+
+    private float getPersistedScale() {
+        return Settings.Secure.getFloat(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+                DEFAULT_MAGNIFICATION_SCALE);
+    }
+
+    private static boolean isScreenMagnificationAutoUpdateEnabled(Context context) {
+        return (Settings.Secure.getInt(context.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE,
+                DEFAULT_SCREEN_MAGNIFICATION_AUTO_UPDATE) == 1);
+    }
+
+    private static final class MotionEventInfo {
+
+        private static final int MAX_POOL_SIZE = 10;
+
+        private static final Object sLock = new Object();
+        private static MotionEventInfo sPool;
+        private static int sPoolSize;
+
+        private MotionEventInfo mNext;
+        private boolean mInPool;
+
+        public MotionEvent mEvent;
+        public MotionEvent mRawEvent;
+        public int mPolicyFlags;
+        public long mCachedTimeMillis;
+
+        public static MotionEventInfo obtain(MotionEvent event, MotionEvent rawEvent,
+                int policyFlags) {
+            synchronized (sLock) {
+                MotionEventInfo info;
+                if (sPoolSize > 0) {
+                    sPoolSize--;
+                    info = sPool;
+                    sPool = info.mNext;
+                    info.mNext = null;
+                    info.mInPool = false;
+                } else {
+                    info = new MotionEventInfo();
+                }
+                info.initialize(event, rawEvent, policyFlags);
+                return info;
+            }
+        }
+
+        private void initialize(MotionEvent event, MotionEvent rawEvent,
+                int policyFlags) {
+            mEvent = MotionEvent.obtain(event);
+            mRawEvent = MotionEvent.obtain(rawEvent);
+            mPolicyFlags = policyFlags;
+            mCachedTimeMillis = SystemClock.uptimeMillis();
+        }
+
+        public void recycle() {
+            synchronized (sLock) {
+                if (mInPool) {
+                    throw new IllegalStateException("Already recycled.");
+                }
+                clear();
+                if (sPoolSize < MAX_POOL_SIZE) {
+                    sPoolSize++;
+                    mNext = sPool;
+                    sPool = this;
+                    mInPool = true;
+                }
+            }
+        }
+
+        private void clear() {
+            mEvent.recycle();
+            mEvent = null;
+            mRawEvent.recycle();
+            mRawEvent = null;
+            mPolicyFlags = 0;
+            mCachedTimeMillis = 0;
+        }
+    }
+
+    private static final class ScreenStateObserver extends BroadcastReceiver {
+
+        private static final int MESSAGE_ON_SCREEN_STATE_CHANGE = 1;
+
+        private final Handler mHandler = new Handler() {
+            @Override
+            public void handleMessage(Message message) {
+                switch (message.what) {
+                    case MESSAGE_ON_SCREEN_STATE_CHANGE: {
+                        String action = (String) message.obj;
+                        handleOnScreenStateChange(action);
+                    } break;
+                }
+            }
+        };
+
+        private final Context mContext;
+        private final Viewport mViewport;
+        private final MagnificationController mMagnificationController;
+
+        public ScreenStateObserver(Context context, Viewport viewport,
+                MagnificationController magnificationController) {
+            mContext = context;
+            mViewport = viewport;
+            mMagnificationController = magnificationController;
+            mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_SCREEN_OFF));
+        }
+
+        public void destroy() {
+            mContext.unregisterReceiver(this);
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            mHandler.obtainMessage(MESSAGE_ON_SCREEN_STATE_CHANGE,
+                    intent.getAction()).sendToTarget();
+        }
+
+        private void handleOnScreenStateChange(String action) {
+            if (action.equals(Intent.ACTION_SCREEN_OFF)
+                    && mMagnificationController.isMagnifying()
+                    && isScreenMagnificationAutoUpdateEnabled(mContext)) {
+                mMagnificationController.reset(false);
+                mViewport.setFrameShown(false, false);
+            }
+        }
+    }
+
+    private static final class DisplayContentObserver {
+
+        private static final int MESSAGE_SHOW_VIEWPORT_FRAME = 1;
+        private static final int MESSAGE_ON_RECTANGLE_ON_SCREEN_REQUESTED = 3;
+        private static final int MESSAGE_ON_WINDOW_TRANSITION = 4;
+        private static final int MESSAGE_ON_ROTATION_CHANGED = 5;
+        private static final int MESSAGE_ON_WINDOW_LAYERS_CHANGED = 6;
+
+        private final Handler mHandler = new MyHandler();
+
+        private final Rect mTempRect = new Rect();
+
+        private final IDisplayContentChangeListener mDisplayContentChangeListener;
+
+        private final Context mContext;
+        private final Viewport mViewport;
+        private final MagnificationController mMagnificationController;
+        private final IWindowManager mWindowManagerService;
+        private final DisplayProvider mDisplayProvider;
+        private final long mLongAnimationDuration;
+        private final float mWindowAnimationScale;
+
+        public DisplayContentObserver(Context context, Viewport viewport,
+                MagnificationController magnificationController,
+                IWindowManager windowManagerService, DisplayProvider displayProvider,
+                long longAnimationDuration, float windowAnimationScale) {
+            mContext = context;
+            mViewport = viewport;
+            mMagnificationController = magnificationController;
+            mWindowManagerService = windowManagerService;
+            mDisplayProvider = displayProvider;
+            mLongAnimationDuration = longAnimationDuration;
+            mWindowAnimationScale = windowAnimationScale;
+
+            mDisplayContentChangeListener = new IDisplayContentChangeListener.Stub() {
+                @Override
+                public void onWindowTransition(int displayId, int transition, WindowInfo info) {
+                    mHandler.obtainMessage(MESSAGE_ON_WINDOW_TRANSITION,
+                            transition, 0, WindowInfo.obtain(info)).sendToTarget();
+                }
+
+                @Override
+                public void onRectangleOnScreenRequested(int dsiplayId, Rect rectangle,
+                        boolean immediate) {
+                    SomeArgs args = SomeArgs.obtain();
+                    args.argi1 = rectangle.left;
+                    args.argi2 = rectangle.top;
+                    args.argi3 = rectangle.right;
+                    args.argi4 = rectangle.bottom;
+                    mHandler.obtainMessage(MESSAGE_ON_RECTANGLE_ON_SCREEN_REQUESTED, 0,
+                            immediate ? 1 : 0, args).sendToTarget();
+                }
+
+                @Override
+                public void onRotationChanged(int rotation) throws RemoteException {
+                    mHandler.obtainMessage(MESSAGE_ON_ROTATION_CHANGED, rotation, 0)
+                            .sendToTarget();
+                }
+
+                @Override
+                public void onWindowLayersChanged(int displayId) throws RemoteException {
+                    mHandler.sendEmptyMessage(MESSAGE_ON_WINDOW_LAYERS_CHANGED);
+                }
+            };
+
+            try {
+                mWindowManagerService.addDisplayContentChangeListener(
+                        mDisplayProvider.getDisplay().getDisplayId(),
+                        mDisplayContentChangeListener);
+            } catch (RemoteException re) {
+                /* ignore */
+            }
+        }
+
+        public void destroy() {
+            try {
+                mWindowManagerService.removeDisplayContentChangeListener(
+                        mDisplayProvider.getDisplay().getDisplayId(),
+                        mDisplayContentChangeListener);
+            } catch (RemoteException re) {
+                /* ignore*/
+            }
+        }
+
+        private void handleOnRotationChanged(int rotation) {
+            if (DEBUG_ROTATION) {
+                Slog.i(LOG_TAG, "Rotation: " + rotationToString(rotation));
+            }
+            resetMagnificationIfNeeded();
+            mViewport.setFrameShown(false, false);
+            mViewport.rotationChanged();
+            mViewport.recomputeBounds(false);
+            if (mMagnificationController.isMagnifying()) {
+                final long delay = (long) (2 * mLongAnimationDuration * mWindowAnimationScale);
+                Message message = mHandler.obtainMessage(MESSAGE_SHOW_VIEWPORT_FRAME);
+                mHandler.sendMessageDelayed(message, delay);
+            }
+        }
+
+        private void handleOnWindowTransition(int transition, WindowInfo info) {
+            if (DEBUG_WINDOW_TRANSITIONS) {
+                Slog.i(LOG_TAG, "Window transitioning: "
+                        + windowTransitionToString(transition));
+            }
+            try {
+                final boolean magnifying = mMagnificationController.isMagnifying();
+                if (magnifying) {
+                    switch (transition) {
+                        case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
+                        case WindowManagerPolicy.TRANSIT_TASK_OPEN:
+                        case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
+                        case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN:
+                        case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE:
+                        case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN: {
+                            resetMagnificationIfNeeded();
+                        }
+                    }
+                }
+                if (info.type == WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
+                        || info.type == WindowManager.LayoutParams.TYPE_INPUT_METHOD
+                        || info.type == WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG
+                        || info.type == WindowManager.LayoutParams.TYPE_KEYGUARD
+                        || info.type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
+                    switch (transition) {
+                        case WindowManagerPolicy.TRANSIT_ENTER:
+                        case WindowManagerPolicy.TRANSIT_SHOW:
+                        case WindowManagerPolicy.TRANSIT_EXIT:
+                        case WindowManagerPolicy.TRANSIT_HIDE: {
+                            mViewport.recomputeBounds(mMagnificationController.isMagnifying());
+                        } break;
+                    }
+                }
+                switch (transition) {
+                    case WindowManagerPolicy.TRANSIT_ENTER:
+                    case WindowManagerPolicy.TRANSIT_SHOW: {
+                        if (!magnifying || !isScreenMagnificationAutoUpdateEnabled(mContext)) {
+                            break;
+                        }
+                        final int type = info.type;
+                        switch (type) {
+                            // TODO: Are these all the windows we want to make
+                            //       visible when they appear on the screen?
+                            //       Do we need to take some of them out?
+                            case WindowManager.LayoutParams.TYPE_APPLICATION:
+                            case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL:
+                            case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA:
+                            case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL:
+                            case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG:
+                            case WindowManager.LayoutParams.TYPE_SEARCH_BAR:
+                            case WindowManager.LayoutParams.TYPE_PHONE:
+                            case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
+                            case WindowManager.LayoutParams.TYPE_TOAST:
+                            case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
+                            case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE:
+                            case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
+                            case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
+                            case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
+                            case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY:
+                            case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL:
+                            case WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY: {
+                                Rect magnifiedRegionBounds = mMagnificationController
+                                        .getMagnifiedRegionBounds();
+                                Rect touchableRegion = info.touchableRegion;
+                                if (!magnifiedRegionBounds.intersect(touchableRegion)) {
+                                    ensureRectangleInMagnifiedRegionBounds(
+                                            magnifiedRegionBounds, touchableRegion);
+                                }
+                            } break;
+                        } break;
+                    }
+                }
+            } finally {
+                if (info != null) {
+                    info.recycle();
+                }
+            }
+        }
+
+        private void handleOnRectangleOnScreenRequested(Rect rectangle, boolean immediate) {
+            if (!mMagnificationController.isMagnifying()) {
+                return;
+            }
+            Rect magnifiedRegionBounds = mMagnificationController.getMagnifiedRegionBounds();
+            if (magnifiedRegionBounds.contains(rectangle)) {
+                return;
+            }
+            ensureRectangleInMagnifiedRegionBounds(magnifiedRegionBounds, rectangle);
+        }
+
+        private void ensureRectangleInMagnifiedRegionBounds(Rect magnifiedRegionBounds,
+                Rect rectangle) {
+            if (!Rect.intersects(rectangle, mViewport.getBounds())) {
+                return;
+            }
+            final float scrollX;
+            final float scrollY;
+            if (rectangle.width() > magnifiedRegionBounds.width()) {
+                final int direction = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault());
+                if (direction == View.LAYOUT_DIRECTION_LTR) {
+                    scrollX = rectangle.left - magnifiedRegionBounds.left;
+                } else {
+                    scrollX = rectangle.right - magnifiedRegionBounds.right;
+                }
+            } else if (rectangle.left < magnifiedRegionBounds.left) {
+                scrollX = rectangle.left - magnifiedRegionBounds.left;
+            } else if (rectangle.right > magnifiedRegionBounds.right) {
+                scrollX = rectangle.right - magnifiedRegionBounds.right;
+            } else {
+                scrollX = 0;
+            }
+            if (rectangle.height() > magnifiedRegionBounds.height()) {
+                scrollY = rectangle.top - magnifiedRegionBounds.top;
+            } else if (rectangle.top < magnifiedRegionBounds.top) {
+                scrollY = rectangle.top - magnifiedRegionBounds.top;
+            } else if (rectangle.bottom > magnifiedRegionBounds.bottom) {
+                scrollY = rectangle.bottom - magnifiedRegionBounds.bottom;
+            } else {
+                scrollY = 0;
+            }
+            final float viewportCenterX = mMagnificationController.getMagnifiedRegionCenterX()
+                    + scrollX;
+            final float viewportCenterY = mMagnificationController.getMagnifiedRegionCenterY()
+                    + scrollY;
+            mMagnificationController.setMagnifiedRegionCenter(viewportCenterX, viewportCenterY,
+                    true);
+        }
+
+        private void resetMagnificationIfNeeded() {
+            if (mMagnificationController.isMagnifying()
+                    && isScreenMagnificationAutoUpdateEnabled(mContext)) {
+                mMagnificationController.reset(true);
+                mViewport.setFrameShown(false, true);
+            }
+        }
+
+        private String windowTransitionToString(int transition) {
+            switch (transition) {
+                case WindowManagerPolicy.TRANSIT_UNSET: {
+                    return "TRANSIT_UNSET";
+                }
+                case WindowManagerPolicy.TRANSIT_NONE: {
+                    return "TRANSIT_NONE";
+                }
+                case WindowManagerPolicy.TRANSIT_ENTER: {
+                    return "TRANSIT_ENTER";
+                }
+                case WindowManagerPolicy.TRANSIT_EXIT: {
+                    return "TRANSIT_EXIT";
+                }
+                case WindowManagerPolicy.TRANSIT_SHOW: {
+                    return "TRANSIT_SHOW";
+                }
+                case WindowManagerPolicy.TRANSIT_EXIT_MASK: {
+                    return "TRANSIT_EXIT_MASK";
+                }
+                case WindowManagerPolicy.TRANSIT_PREVIEW_DONE: {
+                    return "TRANSIT_PREVIEW_DONE";
+                }
+                case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: {
+                    return "TRANSIT_ACTIVITY_OPEN";
+                }
+                case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: {
+                    return "TRANSIT_ACTIVITY_CLOSE";
+                }
+                case WindowManagerPolicy.TRANSIT_TASK_OPEN: {
+                    return "TRANSIT_TASK_OPEN";
+                }
+                case WindowManagerPolicy.TRANSIT_TASK_CLOSE: {
+                    return "TRANSIT_TASK_CLOSE";
+                }
+                case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: {
+                    return "TRANSIT_TASK_TO_FRONT";
+                }
+                case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: {
+                    return "TRANSIT_TASK_TO_BACK";
+                }
+                case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE: {
+                    return "TRANSIT_WALLPAPER_CLOSE";
+                }
+                case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN: {
+                    return "TRANSIT_WALLPAPER_OPEN";
+                }
+                case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN: {
+                    return "TRANSIT_WALLPAPER_INTRA_OPEN";
+                }
+                case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE: {
+                    return "TRANSIT_WALLPAPER_INTRA_CLOSE";
+                }
+                default: {
+                    return "<UNKNOWN>";
+                }
+            }
+        }
+
+        private String rotationToString(int rotation) {
+            switch (rotation) {
+                case Surface.ROTATION_0: {
+                    return "ROTATION_0";
+                }
+                case Surface.ROTATION_90: {
+                    return "ROATATION_90";
+                }
+                case Surface.ROTATION_180: {
+                    return "ROATATION_180";
+                }
+                case Surface.ROTATION_270: {
+                    return "ROATATION_270";
+                }
+                default: {
+                    throw new IllegalArgumentException("Invalid rotation: "
+                        + rotation);
+                }
+            }
+        }
+
+        private final class MyHandler extends Handler {
+            @Override
+            public void handleMessage(Message message) {
+                final int action = message.what;
+                switch (action) {
+                    case MESSAGE_SHOW_VIEWPORT_FRAME: {
+                        mViewport.setFrameShown(true, true);
+                    } break;
+                    case MESSAGE_ON_RECTANGLE_ON_SCREEN_REQUESTED: {
+                        SomeArgs args = (SomeArgs) message.obj;
+                        try {
+                            mTempRect.set(args.argi1, args.argi2, args.argi3, args.argi4);
+                            final boolean immediate = (message.arg1 == 1);
+                            handleOnRectangleOnScreenRequested(mTempRect, immediate);
+                        } finally {
+                            args.recycle();
+                        }
+                    } break;
+                    case MESSAGE_ON_WINDOW_TRANSITION: {
+                        final int transition = message.arg1;
+                        WindowInfo info = (WindowInfo) message.obj;
+                        handleOnWindowTransition(transition, info);
+                    } break;
+                    case MESSAGE_ON_ROTATION_CHANGED: {
+                        final int rotation = message.arg1;
+                        handleOnRotationChanged(rotation);
+                    } break;
+                    case MESSAGE_ON_WINDOW_LAYERS_CHANGED: {
+                        mViewport.recomputeBounds(mMagnificationController.isMagnifying());
+                    } break;
+                    default: {
+                        throw new IllegalArgumentException("Unknown message: " + action);
+                    }
+                }
+            }
+        }
+    }
+
+    private final class MagnificationController {
+
+        private static final String PROPERTY_NAME_ACCESSIBILITY_TRANSFORMATION =
+                "accessibilityTransformation";
+
+        private final MagnificationSpec mSentMagnificationSpec = new MagnificationSpec();
+
+        private final MagnificationSpec mCurrentMagnificationSpec = new MagnificationSpec();
+
+        private final Rect mTempRect = new Rect();
+
+        private final ValueAnimator mTransformationAnimator;
+
+        public MagnificationController(int animationDuration) {
+            Property<MagnificationController, MagnificationSpec> property =
+                    Property.of(MagnificationController.class, MagnificationSpec.class,
+                    PROPERTY_NAME_ACCESSIBILITY_TRANSFORMATION);
+            TypeEvaluator<MagnificationSpec> evaluator = new TypeEvaluator<MagnificationSpec>() {
+                private final MagnificationSpec mTempTransformationSpec = new MagnificationSpec();
+                @Override
+                public MagnificationSpec evaluate(float fraction, MagnificationSpec fromSpec,
+                        MagnificationSpec toSpec) {
+                    MagnificationSpec result = mTempTransformationSpec;
+                    result.mScale = fromSpec.mScale
+                            + (toSpec.mScale - fromSpec.mScale) * fraction;
+                    result.mMagnifiedRegionCenterX = fromSpec.mMagnifiedRegionCenterX
+                            + (toSpec.mMagnifiedRegionCenterX - fromSpec.mMagnifiedRegionCenterX)
+                            * fraction;
+                    result.mMagnifiedRegionCenterY = fromSpec.mMagnifiedRegionCenterY
+                            + (toSpec.mMagnifiedRegionCenterY - fromSpec.mMagnifiedRegionCenterY)
+                            * fraction;
+                    result.mScaledOffsetX = fromSpec.mScaledOffsetX
+                            + (toSpec.mScaledOffsetX - fromSpec.mScaledOffsetX)
+                            * fraction;
+                    result.mScaledOffsetY = fromSpec.mScaledOffsetY
+                            + (toSpec.mScaledOffsetY - fromSpec.mScaledOffsetY)
+                            * fraction;
+                    return result;
+                }
+            };
+            mTransformationAnimator = ObjectAnimator.ofObject(this, property,
+                    evaluator, mSentMagnificationSpec, mCurrentMagnificationSpec);
+            mTransformationAnimator.setDuration((long) (animationDuration));
+            mTransformationAnimator.setInterpolator(mInterpolator);
+        }
+
+        public boolean isMagnifying() {
+            return mCurrentMagnificationSpec.mScale > 1.0f;
+        }
+
+        public void reset(boolean animate) {
+            if (mTransformationAnimator.isRunning()) {
+                mTransformationAnimator.cancel();
+            }
+            mCurrentMagnificationSpec.reset();
+            if (animate) {
+                animateAccessibilityTranformation(mSentMagnificationSpec,
+                        mCurrentMagnificationSpec);
+            } else {
+                setAccessibilityTransformation(mCurrentMagnificationSpec);
+            }
+        }
+
+        public Rect getMagnifiedRegionBounds() {
+            mTempRect.set(mViewport.getBounds());
+            mTempRect.offset((int) -mCurrentMagnificationSpec.mScaledOffsetX,
+                    (int) -mCurrentMagnificationSpec.mScaledOffsetY);
+            mTempRect.scale(1.0f / mCurrentMagnificationSpec.mScale);
+            return mTempRect;
+        }
+
+        public float getScale() {
+            return mCurrentMagnificationSpec.mScale;
+        }
+
+        public float getMagnifiedRegionCenterX() {
+            return mCurrentMagnificationSpec.mMagnifiedRegionCenterX;
+        }
+
+        public float getMagnifiedRegionCenterY() {
+            return mCurrentMagnificationSpec.mMagnifiedRegionCenterY;
+        }
+
+        public float getScaledOffsetX() {
+            return mCurrentMagnificationSpec.mScaledOffsetX;
+        }
+
+        public float getScaledOffsetY() {
+            return mCurrentMagnificationSpec.mScaledOffsetY;
+        }
+
+        public void setScale(float scale, float pivotX, float pivotY, boolean animate) {
+            MagnificationSpec spec = mCurrentMagnificationSpec;
+            final float oldScale = spec.mScale;
+            final float oldCenterX = spec.mMagnifiedRegionCenterX;
+            final float oldCenterY = spec.mMagnifiedRegionCenterY;
+            final float normPivotX = (-spec.mScaledOffsetX + pivotX) / oldScale;
+            final float normPivotY = (-spec.mScaledOffsetY + pivotY) / oldScale;
+            final float offsetX = (oldCenterX - normPivotX) * (oldScale / scale);
+            final float offsetY = (oldCenterY - normPivotY) * (oldScale / scale);
+            final float centerX = normPivotX + offsetX;
+            final float centerY = normPivotY + offsetY;
+            setScaleAndMagnifiedRegionCenter(scale, centerX, centerY, animate);
+        }
+
+        public void setMagnifiedRegionCenter(float centerX, float centerY, boolean animate) {
+            setScaleAndMagnifiedRegionCenter(mCurrentMagnificationSpec.mScale, centerX, centerY,
+                    animate);
+        }
+
+        public void setScaleAndMagnifiedRegionCenter(float scale, float centerX, float centerY,
+                boolean animate) {
+            if (Float.compare(mCurrentMagnificationSpec.mScale, scale) == 0
+                    && Float.compare(mCurrentMagnificationSpec.mMagnifiedRegionCenterX,
+                            centerX) == 0
+                    && Float.compare(mCurrentMagnificationSpec.mMagnifiedRegionCenterY,
+                            centerY) == 0) {
+                return;
+            }
+            if (mTransformationAnimator.isRunning()) {
+                mTransformationAnimator.cancel();
+            }
+            if (DEBUG_MAGNIFICATION_CONTROLLER) {
+                Slog.i(LOG_TAG, "scale: " + scale + " centerX: " + centerX
+                        + " centerY: " + centerY);
+            }
+            mCurrentMagnificationSpec.initialize(scale, centerX, centerY);
+            if (animate) {
+                animateAccessibilityTranformation(mSentMagnificationSpec,
+                        mCurrentMagnificationSpec);
+            } else {
+                setAccessibilityTransformation(mCurrentMagnificationSpec);
+            }
+        }
+
+        private void animateAccessibilityTranformation(MagnificationSpec fromSpec,
+                MagnificationSpec toSpec) {
+            mTransformationAnimator.setObjectValues(fromSpec, toSpec);
+            mTransformationAnimator.start();
+        }
+
+        @SuppressWarnings("unused")
+        // Called from an animator.
+        public MagnificationSpec getAccessibilityTransformation() {
+            return mSentMagnificationSpec;
+        }
+
+        public void setAccessibilityTransformation(MagnificationSpec transformation) {
+            if (DEBUG_TRANSFORMATION) {
+                Slog.i(LOG_TAG, "Transformation scale: " + transformation.mScale
+                        + " offsetX: " + transformation.mScaledOffsetX
+                        + " offsetY: " + transformation.mScaledOffsetY);
+            }
+            try {
+                mSentMagnificationSpec.updateFrom(transformation);
+                mWindowManagerService.magnifyDisplay(mDisplayProvider.getDisplay().getDisplayId(),
+                        transformation.mScale, transformation.mScaledOffsetX,
+                        transformation.mScaledOffsetY);
+            } catch (RemoteException re) {
+                /* ignore */
+            }
+        }
+
+        private class MagnificationSpec {
+
+            private static final float DEFAULT_SCALE = 1.0f;
+
+            public float mScale = DEFAULT_SCALE;
+
+            public float mMagnifiedRegionCenterX;
+
+            public float mMagnifiedRegionCenterY;
+
+            public float mScaledOffsetX;
+
+            public float mScaledOffsetY;
+
+            public void initialize(float scale, float magnifiedRegionCenterX,
+                    float magnifiedRegionCenterY) {
+                mScale = scale;
+
+                final int viewportWidth = mViewport.getBounds().width();
+                final int viewportHeight = mViewport.getBounds().height();
+                final float minMagnifiedRegionCenterX = (viewportWidth / 2) / scale;
+                final float minMagnifiedRegionCenterY = (viewportHeight / 2) / scale;
+                final float maxMagnifiedRegionCenterX = viewportWidth - minMagnifiedRegionCenterX;
+                final float maxMagnifiedRegionCenterY = viewportHeight - minMagnifiedRegionCenterY;
+
+                mMagnifiedRegionCenterX = Math.min(Math.max(magnifiedRegionCenterX,
+                        minMagnifiedRegionCenterX), maxMagnifiedRegionCenterX);
+                mMagnifiedRegionCenterY = Math.min(Math.max(magnifiedRegionCenterY,
+                        minMagnifiedRegionCenterY), maxMagnifiedRegionCenterY);
+
+                mScaledOffsetX = -(mMagnifiedRegionCenterX * scale - viewportWidth / 2);
+                mScaledOffsetY = -(mMagnifiedRegionCenterY * scale - viewportHeight / 2);
+            }
+
+            public void updateFrom(MagnificationSpec other) {
+                mScale = other.mScale;
+                mMagnifiedRegionCenterX = other.mMagnifiedRegionCenterX;
+                mMagnifiedRegionCenterY = other.mMagnifiedRegionCenterY;
+                mScaledOffsetX = other.mScaledOffsetX;
+                mScaledOffsetY = other.mScaledOffsetY;
+            }
+
+            public void reset() {
+                mScale = DEFAULT_SCALE;
+                mMagnifiedRegionCenterX = 0;
+                mMagnifiedRegionCenterY = 0;
+                mScaledOffsetX = 0;
+                mScaledOffsetY = 0;
+            }
+        }
+    }
+
+    private static final class Viewport {
+
+        private static final String PROPERTY_NAME_ALPHA = "alpha";
+
+        private static final String PROPERTY_NAME_BOUNDS = "bounds";
+
+        private static final int MIN_ALPHA = 0;
+
+        private static final int MAX_ALPHA = 255;
+
+        private final ArrayList<WindowInfo> mTempWindowInfoList = new ArrayList<WindowInfo>();
+
+        private final Rect mTempRect1 = new Rect();
+        private final Rect mTempRect2 = new Rect();
+        private final Rect mTempRect3 = new Rect();
+
+        private final IWindowManager mWindowManagerService;
+        private final DisplayProvider mDisplayProvider;
+
+        private final ViewportWindow mViewportFrame;
+
+        private final ValueAnimator mResizeFrameAnimator;
+
+        private final ValueAnimator mShowHideFrameAnimator;
+
+        public Viewport(Context context, WindowManager windowManager,
+                IWindowManager windowManagerService, DisplayProvider displayInfoProvider,
+                Interpolator animationInterpolator, long animationDuration) {
+            mWindowManagerService = windowManagerService;
+            mDisplayProvider = displayInfoProvider;
+            mViewportFrame = new ViewportWindow(context, windowManager, displayInfoProvider);
+
+            mShowHideFrameAnimator = ObjectAnimator.ofInt(mViewportFrame, PROPERTY_NAME_ALPHA,
+                  MIN_ALPHA, MAX_ALPHA);
+            mShowHideFrameAnimator.setInterpolator(animationInterpolator);
+            mShowHideFrameAnimator.setDuration(animationDuration);
+            mShowHideFrameAnimator.addListener(new AnimatorListener() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    if (mShowHideFrameAnimator.getAnimatedValue().equals(MIN_ALPHA)) {
+                        mViewportFrame.hide();
+                    }
+                }
+                @Override
+                public void onAnimationStart(Animator animation) {
+                    /* do nothing - stub */
+                }
+                @Override
+                public void onAnimationCancel(Animator animation) {
+                    /* do nothing - stub */
+                }
+                @Override
+                public void onAnimationRepeat(Animator animation) {
+                    /* do nothing - stub */
+                }
+            });
+
+            Property<ViewportWindow, Rect> property = Property.of(ViewportWindow.class,
+                    Rect.class, PROPERTY_NAME_BOUNDS);
+            TypeEvaluator<Rect> evaluator = new TypeEvaluator<Rect>() {
+                private final Rect mReusableResultRect = new Rect();
+                @Override
+                public Rect evaluate(float fraction, Rect fromFrame, Rect toFrame) {
+                    Rect result = mReusableResultRect;
+                    result.left = (int) (fromFrame.left
+                            + (toFrame.left - fromFrame.left) * fraction);
+                    result.top = (int) (fromFrame.top
+                            + (toFrame.top - fromFrame.top) * fraction);
+                    result.right = (int) (fromFrame.right
+                            + (toFrame.right - fromFrame.right) * fraction);
+                    result.bottom = (int) (fromFrame.bottom
+                            + (toFrame.bottom - fromFrame.bottom) * fraction);
+                    return result;
+                }
+            };
+            mResizeFrameAnimator = ObjectAnimator.ofObject(mViewportFrame, property,
+                    evaluator, mViewportFrame.mBounds, mViewportFrame.mBounds);
+            mResizeFrameAnimator.setDuration((long) (animationDuration));
+            mResizeFrameAnimator.setInterpolator(animationInterpolator);
+
+            recomputeBounds(false);
+        }
+
+        private final Comparator<WindowInfo> mWindowInfoInverseComparator =
+                new Comparator<WindowInfo>() {
+            @Override
+            public int compare(WindowInfo lhs, WindowInfo rhs) {
+                if (lhs.layer != rhs.layer) {
+                    return rhs.layer - lhs.layer;
+                }
+                if (lhs.touchableRegion.top != rhs.touchableRegion.top) {
+                    return rhs.touchableRegion.top - lhs.touchableRegion.top;
+                }
+                if (lhs.touchableRegion.left != rhs.touchableRegion.left) {
+                    return rhs.touchableRegion.left - lhs.touchableRegion.left;
+                }
+                if (lhs.touchableRegion.right != rhs.touchableRegion.right) {
+                    return rhs.touchableRegion.right - lhs.touchableRegion.right;
+                }
+                if (lhs.touchableRegion.bottom != rhs.touchableRegion.bottom) {
+                    return rhs.touchableRegion.bottom - lhs.touchableRegion.bottom;
+                }
+                return 0;
+            }
+        };
+
+        public void recomputeBounds(boolean animate) {
+            Rect magnifiedFrame = mTempRect1;
+            magnifiedFrame.set(0, 0, 0, 0);
+
+            DisplayInfo displayInfo = mDisplayProvider.getDisplayInfo();
+
+            Rect availableFrame = mTempRect2;
+            availableFrame.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
+
+            ArrayList<WindowInfo> infos = mTempWindowInfoList;
+            infos.clear();
+            int windowCount = 0;
+            try {
+                mWindowManagerService.getVisibleWindowsForDisplay(
+                        mDisplayProvider.getDisplay().getDisplayId(), infos);
+                Collections.sort(infos, mWindowInfoInverseComparator);
+                windowCount = infos.size();
+                for (int i = 0; i < windowCount; i++) {
+                    WindowInfo info = infos.get(i);
+                    if (info.type == WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY) {
+                        continue;
+                    }
+                    Rect windowFrame = mTempRect3;
+                    windowFrame.set(info.touchableRegion);
+                    if (isWindowMagnified(info.type)) {
+                        magnifiedFrame.union(windowFrame);
+                        magnifiedFrame.intersect(availableFrame);
+                    } else {
+                        subtract(windowFrame, magnifiedFrame);
+                        subtract(availableFrame, windowFrame);
+                    }
+                    if (availableFrame.equals(magnifiedFrame)) {
+                        break;
+                    }
+                }
+            } catch (RemoteException re) {
+                /* ignore */
+            } finally {
+                for (int i = windowCount - 1; i >= 0; i--) {
+                    infos.remove(i).recycle();
+                }
+            }
+
+            final int displayWidth = mDisplayProvider.getDisplayInfo().logicalWidth;
+            final int displayHeight = mDisplayProvider.getDisplayInfo().logicalHeight;
+            magnifiedFrame.intersect(0, 0, displayWidth, displayHeight);
+
+            resize(magnifiedFrame, animate);
+        }
+
+        private boolean isWindowMagnified(int type) {
+            return (type != WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
+                    && type != WindowManager.LayoutParams.TYPE_INPUT_METHOD
+                    && type != WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
+        }
+
+        public void rotationChanged() {
+            mViewportFrame.rotationChanged();
+        }
+
+        public Rect getBounds() {
+            return mViewportFrame.getBounds();
+        }
+
+        public void setFrameShown(boolean shown, boolean animate) {
+            if (mViewportFrame.isShown() == shown) {
+                return;
+            }
+            if (animate) {
+                if (mShowHideFrameAnimator.isRunning()) {
+                    mShowHideFrameAnimator.reverse();
+                } else {
+                    if (shown) {
+                        mViewportFrame.show();
+                        mShowHideFrameAnimator.start();
+                    } else {
+                        mShowHideFrameAnimator.reverse();
+                    }
+                }
+            } else {
+                mShowHideFrameAnimator.cancel();
+                if (shown) {
+                    mViewportFrame.show();
+                } else {
+                    mViewportFrame.hide();
+                }
+            }
+        }
+
+        private void resize(Rect bounds, boolean animate) {
+            if (mViewportFrame.getBounds().equals(bounds)) {
+                return;
+            }
+            if (animate) {
+                if (mResizeFrameAnimator.isRunning()) {
+                    mResizeFrameAnimator.cancel();
+                }
+                mResizeFrameAnimator.setObjectValues(mViewportFrame.mBounds, bounds);
+                mResizeFrameAnimator.start();
+            } else {
+                mViewportFrame.setBounds(bounds);
+            }
+        }
+
+        private boolean subtract(Rect lhs, Rect rhs) {
+            if (lhs.right < rhs.left || lhs.left  > rhs.right
+                    || lhs.bottom < rhs.top || lhs.top > rhs.bottom) {
+                return false;
+            }
+            if (lhs.left < rhs.left) {
+                lhs.right = rhs.left;
+            }
+            if (lhs.top < rhs.top) {
+                lhs.bottom = rhs.top;
+            }
+            if (lhs.right > rhs.right) {
+                lhs.left = rhs.right;
+            }
+            if (lhs.bottom > rhs.bottom) {
+                lhs.top = rhs.bottom;
+            }
+            return true;
+        }
+
+        private static final class ViewportWindow {
+            private static final String WINDOW_TITLE = "Magnification Overlay";
+
+            private final WindowManager mWindowManager;
+            private final DisplayProvider mDisplayProvider;
+
+            private final ContentView mWindowContent;
+            private final WindowManager.LayoutParams mWindowParams;
+
+            private final Rect mBounds = new Rect();
+            private boolean mShown;
+            private int mAlpha;
+
+            public ViewportWindow(Context context, WindowManager windowManager,
+                    DisplayProvider displayProvider) {
+                mWindowManager = windowManager;
+                mDisplayProvider = displayProvider;
+
+                ViewGroup.LayoutParams contentParams = new ViewGroup.LayoutParams(
+                        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+                mWindowContent = new ContentView(context);
+                mWindowContent.setLayoutParams(contentParams);
+                mWindowContent.setBackgroundColor(R.color.transparent);
+
+                mWindowParams = new WindowManager.LayoutParams(
+                        WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY);
+                mWindowParams.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+                mWindowParams.setTitle(WINDOW_TITLE);
+                mWindowParams.gravity = Gravity.CENTER;
+                mWindowParams.width = displayProvider.getDisplayInfo().logicalWidth;
+                mWindowParams.height = displayProvider.getDisplayInfo().logicalHeight;
+                mWindowParams.format = PixelFormat.TRANSLUCENT;
+            }
+
+            public boolean isShown() {
+                return mShown;
+            }
+
+            public void show() {
+                if (mShown) {
+                    return;
+                }
+                mShown = true;
+                mWindowManager.addView(mWindowContent, mWindowParams);
+                if (DEBUG_VIEWPORT_WINDOW) {
+                    Slog.i(LOG_TAG, "ViewportWindow shown.");
+                }
+            }
+
+            public void hide() {
+                if (!mShown) {
+                    return;
+                }
+                mShown = false;
+                mWindowManager.removeView(mWindowContent);
+                if (DEBUG_VIEWPORT_WINDOW) {
+                    Slog.i(LOG_TAG, "ViewportWindow hidden.");
+                }
+            }
+
+            @SuppressWarnings("unused")
+            // Called reflectively from an animator.
+            public int getAlpha() {
+                return mAlpha;
+            }
+
+            @SuppressWarnings("unused")
+            // Called reflectively from an animator.
+            public void setAlpha(int alpha) {
+                if (mAlpha == alpha) {
+                    return;
+                }
+                mAlpha = alpha;
+                if (mShown) {
+                    mWindowContent.invalidate();
+                }
+                if (DEBUG_VIEWPORT_WINDOW) {
+                    Slog.i(LOG_TAG, "ViewportFrame set alpha: " + alpha);
+                }
+            }
+
+            public Rect getBounds() {
+                return mBounds;
+            }
+
+            public void rotationChanged() {
+                mWindowParams.width = mDisplayProvider.getDisplayInfo().logicalWidth;
+                mWindowParams.height = mDisplayProvider.getDisplayInfo().logicalHeight;
+                if (mShown) {
+                    mWindowManager.updateViewLayout(mWindowContent, mWindowParams);
+                }
+            }
+
+            public void setBounds(Rect bounds) {
+                if (mBounds.equals(bounds)) {
+                    return;
+                }
+                mBounds.set(bounds);
+                if (mShown) {
+                    mWindowContent.invalidate();
+                }
+                if (DEBUG_VIEWPORT_WINDOW) {
+                    Slog.i(LOG_TAG, "ViewportFrame set bounds: " + bounds);
+                }
+            }
+
+            private final class ContentView extends View {
+                private final Drawable mHighlightFrame;
+
+                public ContentView(Context context) {
+                    super(context);
+                    mHighlightFrame = context.getResources().getDrawable(
+                            R.drawable.magnified_region_frame);
+                }
+
+                @Override
+                public void onDraw(Canvas canvas) {
+                    canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
+                    mHighlightFrame.setBounds(mBounds);
+                    mHighlightFrame.setAlpha(mAlpha);
+                    mHighlightFrame.draw(canvas);
+                }
+            }
+        }
+    }
+
+    private static class DisplayProvider implements DisplayListener {
+        private final WindowManager mWindowManager;
+        private final DisplayManager mDisplayManager;
+        private final Display mDefaultDisplay;
+        private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo();
+
+        public DisplayProvider(Context context, WindowManager windowManager) {
+            mWindowManager = windowManager;
+            mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
+            mDefaultDisplay = mWindowManager.getDefaultDisplay();
+            mDisplayManager.registerDisplayListener(this, null);
+            updateDisplayInfo();
+        }
+
+        public DisplayInfo getDisplayInfo() {
+            return mDefaultDisplayInfo;
+        }
+
+        public Display getDisplay() {
+            return mDefaultDisplay;
+        }
+
+        private void updateDisplayInfo() {
+            if (!mDefaultDisplay.getDisplayInfo(mDefaultDisplayInfo)) {
+                Slog.e(LOG_TAG, "Default display is not valid.");
+            }
+        }
+
+        public void destroy() {
+            mDisplayManager.unregisterDisplayListener(this);
+        }
+
+        @Override
+        public void onDisplayAdded(int displayId) {
+            /* do noting */
+        }
+
+        @Override
+        public void onDisplayRemoved(int displayId) {
+            // Having no default display
+        }
+
+        @Override
+        public void onDisplayChanged(int displayId) {
+            updateDisplayInfo();
+        }
+    }
+}
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 48c6b2a..18b46fb 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -35,9 +35,9 @@
 import android.view.ViewConfiguration;
 import android.view.WindowManagerPolicy;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
 
 import com.android.internal.R;
-import com.android.server.input.InputFilter;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -64,7 +64,7 @@
  *
  * @hide
  */
-public class TouchExplorer {
+class TouchExplorer implements EventStreamTransformation {
 
     private static final boolean DEBUG = false;
 
@@ -120,10 +120,6 @@
     // Slop between the first and second tap to be a double tap.
     private final int mDoubleTapSlop;
 
-    // The InputFilter this tracker is associated with i.e. the filter
-    // which delegates event processing to this touch explorer.
-    private final InputFilter mInputFilter;
-
     // The current state of the touch explorer.
     private int mCurrentState = STATE_TOUCH_EXPLORING;
 
@@ -139,6 +135,12 @@
     // Command for delayed sending of a hover exit event.
     private final SendHoverDelayed mSendHoverExitDelayed;
 
+    // Command for delayed sending of touch exploration end events.
+    private final SendAccessibilityEventDelayed mSendTouchExplorationEndDelayed;
+
+    // Command for delayed sending of touch interaction end events.
+    private final SendAccessibilityEventDelayed mSendTouchInteractionEndDelayed;
+
     // Command for delayed sending of a long press.
     private final PerformLongPressDelayed mPerformLongPressDelayed;
 
@@ -155,8 +157,11 @@
     // The scaled velocity above which we detect gestures.
     private final int mScaledGestureDetectionVelocity;
 
+    // The handler to which to delegate events.
+    private EventStreamTransformation mNext;
+
     // Helper to track gesture velocity.
-    private VelocityTracker mVelocityTracker;
+    private final VelocityTracker mVelocityTracker = VelocityTracker.obtain();
 
     // Helper class to track received pointers.
     private final ReceivedPointerTracker mReceivedPointerTracker;
@@ -170,6 +175,9 @@
     // Temporary rectangle to avoid instantiation.
     private final Rect mTempRect = new Rect();
 
+    // Context in which this explorer operates.
+    private final Context mContext;
+
     // The X of the previous event.
     private float mPreviousX;
 
@@ -189,7 +197,7 @@
     private GestureLibrary mGestureLibrary;
 
     // The long pressing pointer id if coordinate remapping is needed.
-    private int mLongPressingPointerId;
+    private int mLongPressingPointerId = -1;
 
     // The long pressing pointer X if coordinate remapping is needed.
     private int mLongPressingPointerDeltaX;
@@ -200,20 +208,22 @@
     // The id of the last touch explored window.
     private int mLastTouchedWindowId;
 
+    // Whether touch exploration is in progress.
+    private boolean mTouchExplorationInProgress;
+
     /**
      * Creates a new instance.
      *
      * @param inputFilter The input filter associated with this explorer.
      * @param context A context handle for accessing resources.
      */
-    public TouchExplorer(InputFilter inputFilter, Context context,
-            AccessibilityManagerService service) {
+    public TouchExplorer(Context context, AccessibilityManagerService service) {
+        mContext = context;
         mAms = service;
         mReceivedPointerTracker = new ReceivedPointerTracker(context);
         mInjectedPointerTracker = new InjectedPointerTracker();
-        mInputFilter = inputFilter;
         mTapTimeout = ViewConfiguration.getTapTimeout();
-        mDetermineUserIntentTimeout = (int) (mTapTimeout * 1.5f);
+        mDetermineUserIntentTimeout = ViewConfiguration.getDoubleTapTimeout();
         mDoubleTapTimeout = ViewConfiguration.getDoubleTapTimeout();
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
         mDoubleTapSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop();
@@ -226,6 +236,12 @@
         mGestureLibrary.load();
         mSendHoverEnterDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_ENTER, true);
         mSendHoverExitDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_EXIT, false);
+        mSendTouchExplorationEndDelayed = new SendAccessibilityEventDelayed(
+                AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END,
+                mDetermineUserIntentTimeout);
+        mSendTouchInteractionEndDelayed = new SendAccessibilityEventDelayed(
+                AccessibilityEvent.TYPE_TOUCH_INTERACTION_END,
+                mDetermineUserIntentTimeout);
         mDoubleTapDetector = new DoubleTapDetector();
         final float density = context.getResources().getDisplayMetrics().density;
         mScaledMinPointerDistanceToUseMiddleLocation =
@@ -242,11 +258,15 @@
         }
     }
 
-    public void clear(MotionEvent event, int policyFlags) {
+    public void onDestroy() {
+        // TODO: Implement
+    }
+
+    private void clear(MotionEvent event, int policyFlags) {
         switch (mCurrentState) {
             case STATE_TOUCH_EXPLORING: {
                 // If a touch exploration gesture is in progress send events for its end.
-                sendExitEventsIfNeeded(policyFlags);
+                sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
             } break;
             case STATE_DRAGGING: {
                 mDraggingPointerId = INVALID_POINTER_ID;
@@ -267,6 +287,8 @@
         mSendHoverExitDelayed.remove();
         mPerformLongPressDelayed.remove();
         mExitGestureDetectionModeDelayed.remove();
+        mSendTouchExplorationEndDelayed.remove();
+        mSendTouchInteractionEndDelayed.remove();
         // Reset the pointer trackers.
         mReceivedPointerTracker.clear();
         mInjectedPointerTracker.clear();
@@ -278,20 +300,31 @@
         mLongPressingPointerDeltaX = 0;
         mLongPressingPointerDeltaY = 0;
         mCurrentState = STATE_TOUCH_EXPLORING;
+        if (mNext != null) {
+            mNext.clear();
+        }
+        mTouchExplorationInProgress = false;
+        mAms.onTouchInteractionEnd();
     }
 
-    public void onMotionEvent(MotionEvent event, int policyFlags) {
+    @Override
+    public void setNext(EventStreamTransformation next) {
+        mNext = next;
+    }
+
+    @Override
+    public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
         if (DEBUG) {
             Slog.d(LOG_TAG, "Received event: " + event + ", policyFlags=0x"
                     + Integer.toHexString(policyFlags));
             Slog.d(LOG_TAG, getStateSymbolicName(mCurrentState));
         }
 
-        mReceivedPointerTracker.onMotionEvent(event);
+        mReceivedPointerTracker.onMotionEvent(rawEvent);
 
         switch(mCurrentState) {
             case STATE_TOUCH_EXPLORING: {
-                handleMotionEventStateTouchExploring(event, policyFlags);
+                handleMotionEventStateTouchExploring(event, rawEvent, policyFlags);
             } break;
             case STATE_DRAGGING: {
                 handleMotionEventStateDragging(event, policyFlags);
@@ -300,7 +333,7 @@
                 handleMotionEventStateDelegating(event, policyFlags);
             } break;
             case STATE_GESTURE_DETECTING: {
-                handleMotionEventGestureDetecting(event, policyFlags);
+                handleMotionEventGestureDetecting(rawEvent, policyFlags);
             } break;
             default:
                 throw new IllegalStateException("Illegal state: " + mCurrentState);
@@ -308,9 +341,26 @@
     }
 
     public void onAccessibilityEvent(AccessibilityEvent event) {
+        final int eventType = event.getEventType();
+
+        // The event for gesture end should be strictly after the
+        // last hover exit event.
+        if (mSendTouchExplorationEndDelayed.isPending()
+                && eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
+                    mSendTouchExplorationEndDelayed.remove();
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END);
+        }
+
+        // The event for touch interaction end should be strictly after the
+        // last hover exit and the touch exploration gesture end events.
+        if (mSendTouchInteractionEndDelayed.isPending()
+                && eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
+            mSendTouchInteractionEndDelayed.remove();
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
+        }
+
         // If a new window opens or the accessibility focus moves we no longer
         // want to click/long press on the last touch explored location.
-        final int eventType = event.getEventType();
         switch (eventType) {
             case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
             case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
@@ -325,32 +375,35 @@
                 mLastTouchedWindowId = event.getWindowId();
             } break;
         }
+        if (mNext != null) {
+            mNext.onAccessibilityEvent(event);
+        }
     }
 
     /**
      * Handles a motion event in touch exploring state.
      *
      * @param event The event to be handled.
+     * @param rawEvent The raw (unmodified) motion event.
      * @param policyFlags The policy flags associated with the event.
      */
-    private void handleMotionEventStateTouchExploring(MotionEvent event, int policyFlags) {
+    private void handleMotionEventStateTouchExploring(MotionEvent event, MotionEvent rawEvent,
+            int policyFlags) {
         ReceivedPointerTracker receivedTracker = mReceivedPointerTracker;
         final int activePointerCount = receivedTracker.getActivePointerCount();
 
-        if (mVelocityTracker == null) {
-            mVelocityTracker = VelocityTracker.obtain();
-        }
-        mVelocityTracker.addMovement(event);
+        mVelocityTracker.addMovement(rawEvent);
 
         mDoubleTapDetector.onMotionEvent(event, policyFlags);
 
         switch (event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN:
+                mAms.onTouchInteractionStart();
                 // Pre-feed the motion events to the gesture detector since we
                 // have a distance slop before getting into gesture detection
                 // mode and not using the points within this slop significantly
                 // decreases the quality of gesture recognition.
-                handleMotionEventGestureDetecting(event, policyFlags);
+                handleMotionEventGestureDetecting(rawEvent, policyFlags);
                 //$FALL-THROUGH$
             case MotionEvent.ACTION_POINTER_DOWN: {
                 switch (activePointerCount) {
@@ -367,6 +420,22 @@
                             mSendHoverExitDelayed.remove();
                         }
 
+                        if (mSendTouchExplorationEndDelayed.isPending()) {
+                            mSendTouchExplorationEndDelayed.forceSendAndRemove();
+                        }
+
+                        if (mSendTouchInteractionEndDelayed.isPending()) {
+                            mSendTouchInteractionEndDelayed.forceSendAndRemove();
+                        }
+
+                        // Every pointer that goes down is active until it moves or
+                        // another one goes down. Hence, having more than one pointer
+                        // down we have already send the interaction start event.
+                        if (event.getPointerCount() == 1) {
+                            sendAccessibilityEvent(
+                                    AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
+                        }
+
                         mPerformLongPressDelayed.remove();
 
                         // If we have the first tap schedule a long press and break
@@ -380,11 +449,13 @@
                             mPerformLongPressDelayed.post(event, policyFlags);
                             break;
                         }
-                        // Deliver hover enter with a delay to have a chance
-                        // to detect what the user is trying to do.
-                        final int pointerId = receivedTracker.getPrimaryActivePointerId();
-                        final int pointerIdBits = (1 << pointerId);
-                        mSendHoverEnterDelayed.post(event, pointerIdBits, policyFlags);
+                        if (!mTouchExplorationInProgress) {
+                            // Deliver hover enter with a delay to have a chance
+                            // to detect what the user is trying to do.
+                            final int pointerId = receivedTracker.getPrimaryActivePointerId();
+                            final int pointerIdBits = (1 << pointerId);
+                            mSendHoverEnterDelayed.post(event, true, pointerIdBits, policyFlags);
+                        }
                     } break;
                     default: {
                         /* do nothing - let the code for ACTION_MOVE decide what to do */
@@ -407,12 +478,13 @@
                             // have a distance slop before getting into gesture detection
                             // mode and not using the points within this slop significantly
                             // decreases the quality of gesture recognition.
-                            handleMotionEventGestureDetecting(event, policyFlags);
-
+                            handleMotionEventGestureDetecting(rawEvent, policyFlags);
+                            // It is *important* to use the distance traveled by the pointers
+                            // on the screen which may or may not be magnified.
                             final float deltaX = receivedTracker.getReceivedPointerDownX(pointerId)
-                                - event.getX(pointerIndex);
+                                - rawEvent.getX(pointerIndex);
                             final float deltaY = receivedTracker.getReceivedPointerDownY(pointerId)
-                                - event.getY(pointerIndex);
+                                - rawEvent.getY(pointerIndex);
                             final double moveDelta = Math.hypot(deltaX, deltaY);
                             // The user has moved enough for us to decide.
                             if (moveDelta > mDoubleTapSlop) {
@@ -427,10 +499,15 @@
                                     // We have to perform gesture detection, so
                                     // clear the current state and try to detect.
                                     mCurrentState = STATE_GESTURE_DETECTING;
+                                    mVelocityTracker.clear();
                                     mSendHoverEnterDelayed.remove();
                                     mSendHoverExitDelayed.remove();
                                     mPerformLongPressDelayed.remove();
                                     mExitGestureDetectionModeDelayed.post();
+                                    // Send accessibility event to announce the start
+                                    // of gesture recognition.
+                                    sendAccessibilityEvent(
+                                            AccessibilityEvent.TYPE_GESTURE_DETECTION_START);
                                 } else {
                                     // We have just decided that the user is touch,
                                     // exploring so start sending events.
@@ -443,12 +520,27 @@
                                 break;
                             }
                         } else {
+                            // Cancel the long press if pending and the user
+                            // moved more than the slop.
+                            if (mPerformLongPressDelayed.isPending()) {
+                                final float deltaX =
+                                        receivedTracker.getReceivedPointerDownX(pointerId)
+                                        - rawEvent.getX(pointerIndex);
+                                final float deltaY =
+                                        receivedTracker.getReceivedPointerDownY(pointerId)
+                                        - rawEvent.getY(pointerIndex);
+                                final double moveDelta = Math.hypot(deltaX, deltaY);
+                                // The user has moved enough for us to decide.
+                                if (moveDelta > mTouchSlop) {
+                                    mPerformLongPressDelayed.remove();
+                                }
+                            }
                             // The user is wither double tapping or performing long
                             // press so do not send move events yet.
                             if (mDoubleTapDetector.firstTapDetected()) {
                                 break;
                             }
-                            sendEnterEventsIfNeeded(policyFlags);
+                            sendTouchExplorationGestureStartAndHoverEnterIfNeeded(policyFlags);
                             sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits,
                                     policyFlags);
                         }
@@ -467,17 +559,19 @@
                             // If the user is touch exploring the second pointer may be
                             // performing a double tap to activate an item without need
                             // for the user to lift his exploring finger.
+                            // It is *important* to use the distance traveled by the pointers
+                            // on the screen which may or may not be magnified.
                             final float deltaX = receivedTracker.getReceivedPointerDownX(pointerId)
-                                    - event.getX(pointerIndex);
+                                    - rawEvent.getX(pointerIndex);
                             final float deltaY = receivedTracker.getReceivedPointerDownY(pointerId)
-                                    - event.getY(pointerIndex);
+                                    - rawEvent.getY(pointerIndex);
                             final double moveDelta = Math.hypot(deltaX, deltaY);
                             if (moveDelta < mDoubleTapSlop) {
                                 break;
                             }
                             // We are sending events so send exit and gesture
                             // end since we transition to another state.
-                            sendExitEventsIfNeeded(policyFlags);
+                            sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
                         }
 
                         // We know that a new state transition is to happen and the
@@ -490,6 +584,7 @@
                             // a given distance perform a drag.
                             mCurrentState = STATE_DRAGGING;
                             mDraggingPointerId = pointerId;
+                            event.setEdgeFlags(receivedTracker.getLastReceivedDownEdgeFlags());
                             sendMotionEvent(event, MotionEvent.ACTION_DOWN, pointerIdBits,
                                     policyFlags);
                         } else {
@@ -497,6 +592,7 @@
                             mCurrentState = STATE_DELEGATING;
                             sendDownForAllActiveNotInjectedPointers(event, policyFlags);
                         }
+                        mVelocityTracker.clear();
                     } break;
                     default: {
                         // More than one pointer so the user is not touch exploring
@@ -511,16 +607,18 @@
                             mPerformLongPressDelayed.remove();
                             // We are sending events so send exit and gesture
                             // end since we transition to another state.
-                            sendExitEventsIfNeeded(policyFlags);
+                            sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
                         }
 
                         // More than two pointers are delegated to the view hierarchy.
                         mCurrentState = STATE_DELEGATING;
                         sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+                        mVelocityTracker.clear();
                     }
                 }
             } break;
             case MotionEvent.ACTION_UP:
+                mAms.onTouchInteractionEnd();
                 // We know that we do not need the pre-fed gesture points are not
                 // needed anymore since the last pointer just went up.
                 mStrokeBuffer.clear();
@@ -539,17 +637,18 @@
 
                         // If we have not delivered the enter schedule exit.
                         if (mSendHoverEnterDelayed.isPending()) {
-                            mSendHoverExitDelayed.post(event, pointerIdBits, policyFlags);
+                            mSendHoverExitDelayed.post(event, false, pointerIdBits, policyFlags);
                         } else {
                             // The user is touch exploring so we send events for end.
-                            sendExitEventsIfNeeded(policyFlags);
+                            sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
+                        }
+
+                        if (!mSendTouchInteractionEndDelayed.isPending()) {
+                            mSendTouchInteractionEndDelayed.post();
                         }
                     } break;
                 }
-                if (mVelocityTracker != null) {
-                    mVelocityTracker.clear();
-                    mVelocityTracker = null;
-                }
+                mVelocityTracker.clear();
             } break;
             case MotionEvent.ACTION_CANCEL: {
                 clear(event, policyFlags);
@@ -574,7 +673,9 @@
                 // We are in dragging state so we have two pointers and another one
                 // goes down => delegate the three pointers to the view hierarchy
                 mCurrentState = STATE_DELEGATING;
-                sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits, policyFlags);
+                if (mDraggingPointerId != INVALID_POINTER_ID) {
+                    sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits, policyFlags);
+                }
                 sendDownForAllActiveNotInjectedPointers(event, policyFlags);
             } break;
             case MotionEvent.ACTION_MOVE: {
@@ -632,18 +733,24 @@
                 }
             } break;
             case MotionEvent.ACTION_POINTER_UP: {
-                final int activePointerCount = mReceivedPointerTracker.getActivePointerCount();
-                switch (activePointerCount) {
-                    case 1: {
-                        // Send an event to the end of the drag gesture.
-                        sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits, policyFlags);
-                    } break;
-                    default: {
-                        mCurrentState = STATE_TOUCH_EXPLORING;
-                    }
-                }
-             } break;
+                 final int pointerId = event.getPointerId(event.getActionIndex());
+                 if (pointerId == mDraggingPointerId) {
+                     mDraggingPointerId = INVALID_POINTER_ID;
+                     // Send an event to the end of the drag gesture.
+                     sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits, policyFlags);
+                 }
+            } break;
             case MotionEvent.ACTION_UP: {
+                mAms.onTouchInteractionEnd();
+                // Announce the end of a new touch interaction.
+                sendAccessibilityEvent(
+                        AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
+                final int pointerId = event.getPointerId(event.getActionIndex());
+                if (pointerId == mDraggingPointerId) {
+                    mDraggingPointerId = INVALID_POINTER_ID;
+                    // Send an event to the end of the drag gesture.
+                    sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits, policyFlags);
+                }
                 mCurrentState = STATE_TOUCH_EXPLORING;
             } break;
             case MotionEvent.ACTION_CANCEL: {
@@ -675,7 +782,12 @@
                 }
             } break;
             case MotionEvent.ACTION_UP:
+                // Announce the end of a new touch interaction.
+                sendAccessibilityEvent(
+                        AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
+                //$FALL-THROUGH$
             case MotionEvent.ACTION_POINTER_UP: {
+                mAms.onTouchInteractionEnd();
                 mLongPressingPointerId = -1;
                 mLongPressingPointerDeltaX = 0;
                 mLongPressingPointerDeltaY = 0;
@@ -713,6 +825,14 @@
                 }
             } break;
             case MotionEvent.ACTION_UP: {
+                mAms.onTouchInteractionEnd();
+                // Announce the end of gesture recognition.
+                sendAccessibilityEvent(
+                        AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
+                // Announce the end of a new touch interaction.
+                sendAccessibilityEvent(
+                        AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
+
                 float x = event.getX();
                 float y = event.getY();
                 mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
@@ -748,6 +868,27 @@
     }
 
     /**
+     * Sends an accessibility event of the given type.
+     *
+     * @param type The event type.
+     */
+    private void sendAccessibilityEvent(int type) {
+        AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(mContext);
+        if (accessibilityManager.isEnabled()) {
+            AccessibilityEvent event = AccessibilityEvent.obtain(type);
+            accessibilityManager.sendAccessibilityEvent(event);
+            switch (type) {
+                case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START: {
+                    mTouchExplorationInProgress = true;
+                } break;
+                case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END: {
+                    mTouchExplorationInProgress = false;
+                } break;
+            }
+        }
+    }
+
+    /**
      * Sends down events to the view hierarchy for all active pointers which are
      * not already being delivered i.e. pointers that are not yet injected.
      *
@@ -791,11 +932,13 @@
      *
      * @param policyFlags The policy flags associated with the event.
      */
-    private void sendExitEventsIfNeeded(int policyFlags) {
+    private void sendHoverExitAndTouchExplorationGestureEndIfNeeded(int policyFlags) {
         MotionEvent event = mInjectedPointerTracker.getLastInjectedHoverEvent();
         if (event != null && event.getActionMasked() != MotionEvent.ACTION_HOVER_EXIT) {
             final int pointerIdBits = event.getPointerIdBits();
-            mAms.touchExplorationGestureEnded();
+            if (!mSendTouchExplorationEndDelayed.isPending()) {
+                mSendTouchExplorationEndDelayed.post();
+            }
             sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits, policyFlags);
         }
     }
@@ -806,11 +949,11 @@
      *
      * @param policyFlags The policy flags associated with the event.
      */
-    private void sendEnterEventsIfNeeded(int policyFlags) {
+    private void sendTouchExplorationGestureStartAndHoverEnterIfNeeded(int policyFlags) {
         MotionEvent event = mInjectedPointerTracker.getLastInjectedHoverEvent();
         if (event != null && event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) {
             final int pointerIdBits = event.getPointerIdBits();
-            mAms.touchExplorationGestureStarted();
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
             sendMotionEvent(event, MotionEvent.ACTION_HOVER_ENTER, pointerIdBits, policyFlags);
         }
     }
@@ -958,7 +1101,12 @@
 
         // Make sure that the user will see the event.
         policyFlags |= WindowManagerPolicy.FLAG_PASS_TO_USER;
-        mInputFilter.sendInputEvent(event, policyFlags);
+        if (mNext != null) {
+            // TODO: For now pass null for the raw event since the touch
+            //       explorer is the last event transformation and it does
+            //       not care about the raw event.
+            mNext.onMotionEvent(event, null, policyFlags);
+        }
 
         mInjectedPointerTracker.onMotionEvent(event);
 
@@ -1008,11 +1156,13 @@
         private MotionEvent mFirstTapEvent;
 
         public void onMotionEvent(MotionEvent event, int policyFlags) {
+            final int actionIndex = event.getActionIndex();
             final int action = event.getActionMasked();
             switch (action) {
                 case MotionEvent.ACTION_DOWN:
                 case MotionEvent.ACTION_POINTER_DOWN: {
-                    if (mFirstTapEvent != null && !isSamePointerContext(mFirstTapEvent, event)) {
+                    if (mFirstTapEvent != null
+                            && !GestureUtils.isSamePointerContext(mFirstTapEvent, event)) {
                         clear();
                     }
                     mDownEvent = MotionEvent.obtain(event);
@@ -1022,19 +1172,21 @@
                     if (mDownEvent == null) {
                         return;
                     }
-                    if (!isSamePointerContext(mDownEvent, event)) {
+                    if (!GestureUtils.isSamePointerContext(mDownEvent, event)) {
                         clear();
                         return;
                     }
-                    if (isTap(mDownEvent, event)) {
-                        if (mFirstTapEvent == null || isTimedOut(mFirstTapEvent, event,
-                                mDoubleTapTimeout)) {
+                    if (GestureUtils.isTap(mDownEvent, event, mTapTimeout, mTouchSlop,
+                            actionIndex)) {
+                        if (mFirstTapEvent == null || GestureUtils.isTimedOut(mFirstTapEvent,
+                                event, mDoubleTapTimeout)) {
                             mFirstTapEvent = MotionEvent.obtain(event);
                             mDownEvent.recycle();
                             mDownEvent = null;
                             return;
                         }
-                        if (isDoubleTap(mFirstTapEvent, event)) {
+                        if (GestureUtils.isMultiTap(mFirstTapEvent, event, mDoubleTapTimeout,
+                                mDoubleTapSlop, actionIndex)) {
                             onDoubleTap(event, policyFlags);
                             mFirstTapEvent.recycle();
                             mFirstTapEvent = null;
@@ -1067,11 +1219,12 @@
             mSendHoverExitDelayed.remove();
             mPerformLongPressDelayed.remove();
 
-            // This is a tap so do not send hover events since
-            // this events will result in firing the corresponding
-            // accessibility events confusing the user about what
-            // is actually clicked.
-            sendExitEventsIfNeeded(policyFlags);
+            if (mSendTouchExplorationEndDelayed.isPending()) {
+                mSendTouchExplorationEndDelayed.forceSendAndRemove();
+            }
+            if (mSendTouchInteractionEndDelayed.isPending()) {
+                mSendTouchInteractionEndDelayed.forceSendAndRemove();
+            }
 
             int clickLocationX;
             int clickLocationY;
@@ -1140,42 +1293,6 @@
             }
         }
 
-        public boolean isTap(MotionEvent down, MotionEvent up) {
-            return eventsWithinTimeoutAndDistance(down, up, mTapTimeout, mTouchSlop);
-        }
-
-        private boolean isDoubleTap(MotionEvent firstUp, MotionEvent secondUp) {
-            return eventsWithinTimeoutAndDistance(firstUp, secondUp, mDoubleTapTimeout,
-                    mDoubleTapSlop);
-        }
-
-        private boolean eventsWithinTimeoutAndDistance(MotionEvent first, MotionEvent second,
-                int timeout, int distance) {
-            if (isTimedOut(first, second, timeout)) {
-                return false;
-            }
-            final int downPtrIndex = first.getActionIndex();
-            final int upPtrIndex = second.getActionIndex();
-            final float deltaX = second.getX(upPtrIndex) - first.getX(downPtrIndex);
-            final float deltaY = second.getY(upPtrIndex) - first.getY(downPtrIndex);
-            final double deltaMove = Math.hypot(deltaX, deltaY);
-            if (deltaMove >= distance) {
-                return false;
-            }
-            return true;
-        }
-
-        private boolean isTimedOut(MotionEvent firstUp, MotionEvent secondUp, int timeout) {
-            final long deltaTime = secondUp.getEventTime() - firstUp.getEventTime();
-            return (deltaTime >= timeout);
-        }
-
-        private boolean isSamePointerContext(MotionEvent first, MotionEvent second) {
-            return (first.getPointerIdBits() == second.getPointerIdBits()
-                    && first.getPointerId(first.getActionIndex())
-                            == second.getPointerId(second.getActionIndex()));
-        }
-
         public boolean firstTapDetected() {
             return mFirstTapEvent != null
                 && SystemClock.uptimeMillis() - mFirstTapEvent.getEventTime() < mDoubleTapTimeout;
@@ -1201,47 +1318,14 @@
         final float secondPtrX = event.getX(secondPtrIndex);
         final float secondPtrY = event.getY(secondPtrIndex);
 
-        // Check if the pointers are moving in the same direction.
-        final float firstDeltaX =
-            firstPtrX - receivedTracker.getReceivedPointerDownX(firstPtrIndex);
-        final float firstDeltaY =
-            firstPtrY - receivedTracker.getReceivedPointerDownY(firstPtrIndex);
+        final float firstPtrDownX = receivedTracker.getReceivedPointerDownX(firstPtrIndex);
+        final float firstPtrDownY = receivedTracker.getReceivedPointerDownY(firstPtrIndex);
+        final float secondPtrDownX = receivedTracker.getReceivedPointerDownX(secondPtrIndex);
+        final float secondPtrDownY = receivedTracker.getReceivedPointerDownY(secondPtrIndex);
 
-        if (firstDeltaX == 0 && firstDeltaY == 0) {
-            return true;
-        }
-
-        final float firstMagnitude =
-            (float) Math.sqrt(firstDeltaX * firstDeltaX + firstDeltaY * firstDeltaY);
-        final float firstXNormalized =
-            (firstMagnitude > 0) ? firstDeltaX / firstMagnitude : firstDeltaX;
-        final float firstYNormalized =
-            (firstMagnitude > 0) ? firstDeltaY / firstMagnitude : firstDeltaY;
-
-        final float secondDeltaX =
-            secondPtrX - receivedTracker.getReceivedPointerDownX(secondPtrIndex);
-        final float secondDeltaY =
-            secondPtrY - receivedTracker.getReceivedPointerDownY(secondPtrIndex);
-
-        if (secondDeltaX == 0 && secondDeltaY == 0) {
-            return true;
-        }
-
-        final float secondMagnitude =
-            (float) Math.sqrt(secondDeltaX * secondDeltaX + secondDeltaY * secondDeltaY);
-        final float secondXNormalized =
-            (secondMagnitude > 0) ? secondDeltaX / secondMagnitude : secondDeltaX;
-        final float secondYNormalized =
-            (secondMagnitude > 0) ? secondDeltaY / secondMagnitude : secondDeltaY;
-
-        final float angleCos =
-            firstXNormalized * secondXNormalized + firstYNormalized * secondYNormalized;
-
-        if (angleCos < MAX_DRAGGING_ANGLE_COS) {
-            return false;
-        }
-
-        return true;
+        return GestureUtils.isDraggingGesture(firstPtrDownX, firstPtrDownY, secondPtrDownX,
+                secondPtrDownY, firstPtrX, firstPtrY, secondPtrX, secondPtrY,
+                MAX_DRAGGING_ANGLE_COS);
     }
 
     /**
@@ -1290,6 +1374,11 @@
 
         @Override
         public void run() {
+            // Announce the end of gesture recognition.
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
+            // Clearing puts is in touch exploration state with a finger already
+            // down, so announce the transition to exploration state.
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
             clear();
         }
     }
@@ -1308,13 +1397,13 @@
         }
 
         public void remove() {
-            if (isPenidng()) {
+            if (isPending()) {
                 mHandler.removeCallbacks(this);
                 clear();
             }
         }
 
-        private boolean isPenidng() {
+        public boolean isPending() {
             return (mEvent != null);
         }
 
@@ -1369,7 +1458,7 @@
             mLongPressingPointerDeltaX = (int) mEvent.getX(pointerIndex) - clickLocationX;
             mLongPressingPointerDeltaY = (int) mEvent.getY(pointerIndex) - clickLocationY;
 
-            sendExitEventsIfNeeded(mPolicyFlags);
+            sendHoverExitAndTouchExplorationGestureEndIfNeeded(mPolicyFlags);
 
             mCurrentState = STATE_DELEGATING;
             sendDownForAllActiveNotInjectedPointers(mEvent, mPolicyFlags);
@@ -1377,7 +1466,7 @@
         }
 
         private void clear() {
-            if (!isPenidng()) {
+            if (!isPending()) {
                 return;
             }
             mEvent.recycle();
@@ -1404,7 +1493,8 @@
             mGestureStarted = gestureStarted;
         }
 
-        public void post(MotionEvent prototype, int pointerIdBits, int policyFlags) {
+        public void post(MotionEvent prototype, boolean touchExplorationInProgress,
+                int pointerIdBits, int policyFlags) {
             remove();
             mPrototype = MotionEvent.obtain(prototype);
             mPointerIdBits = pointerIdBits;
@@ -1460,15 +1550,55 @@
                         "touchExplorationGestureStarted" : "touchExplorationGestureEnded");
             }
             if (mGestureStarted) {
-                mAms.touchExplorationGestureStarted();
+                sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
             } else {
-                mAms.touchExplorationGestureEnded();
+                if (!mSendTouchExplorationEndDelayed.isPending()) {
+                    mSendTouchExplorationEndDelayed.post();
+                }
+                if (mSendTouchInteractionEndDelayed.isPending()) {
+                    mSendTouchInteractionEndDelayed.remove();
+                    mSendTouchInteractionEndDelayed.post();
+                }
             }
             sendMotionEvent(mPrototype, mHoverAction, mPointerIdBits, mPolicyFlags);
             clear();
         }
     }
 
+    private class SendAccessibilityEventDelayed implements Runnable {
+        private final int mEventType;
+        private final int mDelay;
+
+        public SendAccessibilityEventDelayed(int eventType, int delay) {
+            mEventType = eventType;
+            mDelay = delay;
+        }
+
+        public void remove() {
+            mHandler.removeCallbacks(this);
+        }
+
+        public void post() {
+            mHandler.postDelayed(this, mDelay);
+        }
+
+        public boolean isPending() {
+            return mHandler.hasCallbacks(this);
+        }
+
+        public void forceSendAndRemove() {
+            if (isPending()) {
+                run();
+                remove();
+            }
+        }
+
+        @Override
+        public void run() {
+            sendAccessibilityEvent(mEventType);
+        }
+    }
+
     @Override
     public String toString() {
         return LOG_TAG;
@@ -1623,6 +1753,9 @@
         // Which pointers are down.
         private int mReceivedPointersDown;
 
+        // The edge flags of the last received down event.
+        private int mLastReceivedDownEdgeFlags;
+
         // Which down pointers are active.
         private int mActivePointers;
 
@@ -1649,7 +1782,7 @@
          */
         public ReceivedPointerTracker(Context context) {
             mThresholdActivePointer =
-                ViewConfiguration.get(context).getScaledTouchSlop() * COEFFICIENT_ACTIVE_POINTER;//Heie govna
+                ViewConfiguration.get(context).getScaledTouchSlop() * COEFFICIENT_ACTIVE_POINTER;
         }
 
         /**
@@ -1818,6 +1951,13 @@
         }
 
         /**
+         * @return The edge flags of the last received down event.
+         */
+        public int getLastReceivedDownEdgeFlags() {
+            return mLastReceivedDownEdgeFlags;
+        }
+
+        /**
          * @return Whether the last received pointer that went up was active.
          */
         public boolean wasLastReceivedUpPointerActive() {
@@ -1866,6 +2006,8 @@
             mLastReceivedUpPointerDownX = 0;
             mLastReceivedUpPointerDownX = 0;
 
+            mLastReceivedDownEdgeFlags = event.getEdgeFlags();
+
             mReceivedPointersDown |= pointerFlag;
             mReceivedPointerDownX[pointerId] = event.getX(pointerIndex);
             mReceivedPointerDownY[pointerId] = event.getY(pointerIndex);
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
new file mode 100644
index 0000000..35999ea
--- /dev/null
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -0,0 +1,2161 @@
+/*
+ * 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.am;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import com.android.internal.os.BatteryStatsImpl;
+import com.android.server.am.ActivityManagerService.ItemMatcher;
+import com.android.server.am.ActivityManagerService.NeededUriGrants;
+
+import android.app.ActivityManager;
+import android.app.AppGlobals;
+import android.app.IApplicationThread;
+import android.app.IServiceConnection;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.util.EventLog;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.TimeUtils;
+
+public class ActiveServices {
+    static final boolean DEBUG_SERVICE = ActivityManagerService.DEBUG_SERVICE;
+    static final boolean DEBUG_SERVICE_EXECUTING = ActivityManagerService.DEBUG_SERVICE_EXECUTING;
+    static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU;
+    static final String TAG = ActivityManagerService.TAG;
+    static final String TAG_MU = ActivityManagerService.TAG_MU;
+
+    // How long we wait for a service to finish executing.
+    static final int SERVICE_TIMEOUT = 20*1000;
+
+    // How long a service needs to be running until restarting its process
+    // is no longer considered to be a relaunch of the service.
+    static final int SERVICE_RESTART_DURATION = 5*1000;
+
+    // How long a service needs to be running until it will start back at
+    // SERVICE_RESTART_DURATION after being killed.
+    static final int SERVICE_RESET_RUN_DURATION = 60*1000;
+
+    // Multiplying factor to increase restart duration time by, for each time
+    // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
+    static final int SERVICE_RESTART_DURATION_FACTOR = 4;
+
+    // The minimum amount of time between restarting services that we allow.
+    // That is, when multiple services are restarting, we won't allow each
+    // to restart less than this amount of time from the last one.
+    static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
+
+    // Maximum amount of time for there to be no activity on a service before
+    // we consider it non-essential and allow its process to go on the
+    // LRU background list.
+    static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
+
+    final ActivityManagerService mAm;
+
+    final ServiceMap mServiceMap = new ServiceMap();
+
+    /**
+     * All currently bound service connections.  Keys are the IBinder of
+     * the client's IServiceConnection.
+     */
+    final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
+            = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
+
+    /**
+     * List of services that we have been asked to start,
+     * but haven't yet been able to.  It is used to hold start requests
+     * while waiting for their corresponding application thread to get
+     * going.
+     */
+    final ArrayList<ServiceRecord> mPendingServices
+            = new ArrayList<ServiceRecord>();
+
+    /**
+     * List of services that are scheduled to restart following a crash.
+     */
+    final ArrayList<ServiceRecord> mRestartingServices
+            = new ArrayList<ServiceRecord>();
+
+    /**
+     * List of services that are in the process of being stopped.
+     */
+    final ArrayList<ServiceRecord> mStoppingServices
+            = new ArrayList<ServiceRecord>();
+
+    static class ServiceMap {
+
+        private final SparseArray<HashMap<ComponentName, ServiceRecord>> mServicesByNamePerUser
+                = new SparseArray<HashMap<ComponentName, ServiceRecord>>();
+        private final SparseArray<HashMap<Intent.FilterComparison, ServiceRecord>>
+                mServicesByIntentPerUser = new SparseArray<
+                    HashMap<Intent.FilterComparison, ServiceRecord>>();
+
+        ServiceRecord getServiceByName(ComponentName name, int callingUser) {
+            // TODO: Deal with global services
+            if (DEBUG_MU)
+                Slog.v(TAG_MU, "getServiceByName(" + name + "), callingUser = " + callingUser);
+            return getServices(callingUser).get(name);
+        }
+
+        ServiceRecord getServiceByName(ComponentName name) {
+            return getServiceByName(name, -1);
+        }
+
+        ServiceRecord getServiceByIntent(Intent.FilterComparison filter, int callingUser) {
+            // TODO: Deal with global services
+            if (DEBUG_MU)
+                Slog.v(TAG_MU, "getServiceByIntent(" + filter + "), callingUser = " + callingUser);
+            return getServicesByIntent(callingUser).get(filter);
+        }
+
+        ServiceRecord getServiceByIntent(Intent.FilterComparison filter) {
+            return getServiceByIntent(filter, -1);
+        }
+
+        void putServiceByName(ComponentName name, int callingUser, ServiceRecord value) {
+            // TODO: Deal with global services
+            getServices(callingUser).put(name, value);
+        }
+
+        void putServiceByIntent(Intent.FilterComparison filter, int callingUser,
+                ServiceRecord value) {
+            // TODO: Deal with global services
+            getServicesByIntent(callingUser).put(filter, value);
+        }
+
+        void removeServiceByName(ComponentName name, int callingUser) {
+            // TODO: Deal with global services
+            ServiceRecord removed = getServices(callingUser).remove(name);
+            if (DEBUG_MU)
+                Slog.v(TAG, "removeServiceByName user=" + callingUser + " name=" + name
+                        + " removed=" + removed);
+        }
+
+        void removeServiceByIntent(Intent.FilterComparison filter, int callingUser) {
+            // TODO: Deal with global services
+            ServiceRecord removed = getServicesByIntent(callingUser).remove(filter);
+            if (DEBUG_MU)
+                Slog.v(TAG_MU, "removeServiceByIntent user=" + callingUser + " intent=" + filter
+                        + " removed=" + removed);
+        }
+
+        Collection<ServiceRecord> getAllServices(int callingUser) {
+            // TODO: Deal with global services
+            return getServices(callingUser).values();
+        }
+
+        private HashMap<ComponentName, ServiceRecord> getServices(int callingUser) {
+            HashMap<ComponentName, ServiceRecord> map = mServicesByNamePerUser.get(callingUser);
+            if (map == null) {
+                map = new HashMap<ComponentName, ServiceRecord>();
+                mServicesByNamePerUser.put(callingUser, map);
+            }
+            return map;
+        }
+
+        private HashMap<Intent.FilterComparison, ServiceRecord> getServicesByIntent(
+                int callingUser) {
+            HashMap<Intent.FilterComparison, ServiceRecord> map
+                    = mServicesByIntentPerUser.get(callingUser);
+            if (map == null) {
+                map = new HashMap<Intent.FilterComparison, ServiceRecord>();
+                mServicesByIntentPerUser.put(callingUser, map);
+            }
+            return map;
+        }
+    }
+
+    public ActiveServices(ActivityManagerService service) {
+        mAm = service;
+    }
+
+    ComponentName startServiceLocked(IApplicationThread caller,
+            Intent service, String resolvedType,
+            int callingPid, int callingUid, int userId) {
+        if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
+                + " type=" + resolvedType + " args=" + service.getExtras());
+
+        if (caller != null) {
+            final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
+            if (callerApp == null) {
+                throw new SecurityException(
+                        "Unable to find app for caller " + caller
+                        + " (pid=" + Binder.getCallingPid()
+                        + ") when starting service " + service);
+            }
+        }
+
+        ServiceLookupResult res =
+            retrieveServiceLocked(service, resolvedType,
+                    callingPid, callingUid, userId, true);
+        if (res == null) {
+            return null;
+        }
+        if (res.record == null) {
+            return new ComponentName("!", res.permission != null
+                    ? res.permission : "private to package");
+        }
+        ServiceRecord r = res.record;
+        NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
+                callingUid, r.packageName, service, service.getFlags(), null);
+        if (unscheduleServiceRestartLocked(r)) {
+            if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
+        }
+        r.startRequested = true;
+        r.callStart = false;
+        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
+                service, neededGrants));
+        r.lastActivity = SystemClock.uptimeMillis();
+        synchronized (r.stats.getBatteryStats()) {
+            r.stats.startRunningLocked();
+        }
+        String error = bringUpServiceLocked(r, service.getFlags(), false);
+        if (error != null) {
+            return new ComponentName("!!", error);
+        }
+        return r.name;
+    }
+
+    private void stopServiceLocked(ServiceRecord service) {
+        synchronized (service.stats.getBatteryStats()) {
+            service.stats.stopRunningLocked();
+        }
+        service.startRequested = false;
+        service.callStart = false;
+        bringDownServiceLocked(service, false);
+    }
+
+    int stopServiceLocked(IApplicationThread caller, Intent service,
+            String resolvedType, int userId) {
+        if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
+                + " type=" + resolvedType);
+
+        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
+        if (caller != null && callerApp == null) {
+            throw new SecurityException(
+                    "Unable to find app for caller " + caller
+                    + " (pid=" + Binder.getCallingPid()
+                    + ") when stopping service " + service);
+        }
+
+        // If this service is active, make sure it is stopped.
+        ServiceLookupResult r = retrieveServiceLocked(service, resolvedType,
+                Binder.getCallingPid(), Binder.getCallingUid(), userId, false);
+        if (r != null) {
+            if (r.record != null) {
+                final long origId = Binder.clearCallingIdentity();
+                try {
+                    stopServiceLocked(r.record);
+                } finally {
+                    Binder.restoreCallingIdentity(origId);
+                }
+                return 1;
+            }
+            return -1;
+        }
+
+        return 0;
+    }
+
+    IBinder peekServiceLocked(Intent service, String resolvedType) {
+        ServiceLookupResult r = retrieveServiceLocked(service, resolvedType,
+                Binder.getCallingPid(), Binder.getCallingUid(),
+                UserHandle.getCallingUserId(), false);
+
+        IBinder ret = null;
+        if (r != null) {
+            // r.record is null if findServiceLocked() failed the caller permission check
+            if (r.record == null) {
+                throw new SecurityException(
+                        "Permission Denial: Accessing service " + r.record.name
+                        + " from pid=" + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid()
+                        + " requires " + r.permission);
+            }
+            IntentBindRecord ib = r.record.bindings.get(r.record.intent);
+            if (ib != null) {
+                ret = ib.binder;
+            }
+        }
+
+        return ret;
+    }
+
+    boolean stopServiceTokenLocked(ComponentName className, IBinder token,
+            int startId) {
+        if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
+                + " " + token + " startId=" + startId);
+        ServiceRecord r = findServiceLocked(className, token, UserHandle.getCallingUserId());
+        if (r != null) {
+            if (startId >= 0) {
+                // Asked to only stop if done with all work.  Note that
+                // to avoid leaks, we will take this as dropping all
+                // start items up to and including this one.
+                ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
+                if (si != null) {
+                    while (r.deliveredStarts.size() > 0) {
+                        ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
+                        cur.removeUriPermissionsLocked();
+                        if (cur == si) {
+                            break;
+                        }
+                    }
+                }
+
+                if (r.getLastStartId() != startId) {
+                    return false;
+                }
+
+                if (r.deliveredStarts.size() > 0) {
+                    Slog.w(TAG, "stopServiceToken startId " + startId
+                            + " is last, but have " + r.deliveredStarts.size()
+                            + " remaining args");
+                }
+            }
+
+            synchronized (r.stats.getBatteryStats()) {
+                r.stats.stopRunningLocked();
+                r.startRequested = false;
+                r.callStart = false;
+            }
+            final long origId = Binder.clearCallingIdentity();
+            bringDownServiceLocked(r, false);
+            Binder.restoreCallingIdentity(origId);
+            return true;
+        }
+        return false;
+    }
+
+    public void setServiceForegroundLocked(ComponentName className, IBinder token,
+            int id, Notification notification, boolean removeNotification) {
+        final int userId = UserHandle.getCallingUserId();
+        final long origId = Binder.clearCallingIdentity();
+        try {
+            ServiceRecord r = findServiceLocked(className, token, userId);
+            if (r != null) {
+                if (id != 0) {
+                    if (notification == null) {
+                        throw new IllegalArgumentException("null notification");
+                    }
+                    if (r.foregroundId != id) {
+                        r.cancelNotification();
+                        r.foregroundId = id;
+                    }
+                    notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
+                    r.foregroundNoti = notification;
+                    r.isForeground = true;
+                    r.postNotification();
+                    if (r.app != null) {
+                        updateServiceForegroundLocked(r.app, true);
+                    }
+                } else {
+                    if (r.isForeground) {
+                        r.isForeground = false;
+                        if (r.app != null) {
+                            mAm.updateLruProcessLocked(r.app, false);
+                            updateServiceForegroundLocked(r.app, true);
+                        }
+                    }
+                    if (removeNotification) {
+                        r.cancelNotification();
+                        r.foregroundId = 0;
+                        r.foregroundNoti = null;
+                    }
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    private void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
+        boolean anyForeground = false;
+        for (ServiceRecord sr : proc.services) {
+            if (sr.isForeground) {
+                anyForeground = true;
+                break;
+            }
+        }
+        if (anyForeground != proc.foregroundServices) {
+            proc.foregroundServices = anyForeground;
+            if (oomAdj) {
+                mAm.updateOomAdjLocked();
+            }
+        }
+    }
+
+    int bindServiceLocked(IApplicationThread caller, IBinder token,
+            Intent service, String resolvedType,
+            IServiceConnection connection, int flags, int userId) {
+        if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
+                + " type=" + resolvedType + " conn=" + connection.asBinder()
+                + " flags=0x" + Integer.toHexString(flags));
+        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
+        if (callerApp == null) {
+            throw new SecurityException(
+                    "Unable to find app for caller " + caller
+                    + " (pid=" + Binder.getCallingPid()
+                    + ") when binding service " + service);
+        }
+
+        ActivityRecord activity = null;
+        if (token != null) {
+            activity = mAm.mMainStack.isInStackLocked(token);
+            if (activity == null) {
+                Slog.w(TAG, "Binding with unknown activity: " + token);
+                return 0;
+            }
+        }
+
+        int clientLabel = 0;
+        PendingIntent clientIntent = null;
+
+        if (callerApp.info.uid == Process.SYSTEM_UID) {
+            // Hacky kind of thing -- allow system stuff to tell us
+            // what they are, so we can report this elsewhere for
+            // others to know why certain services are running.
+            try {
+                clientIntent = (PendingIntent)service.getParcelableExtra(
+                        Intent.EXTRA_CLIENT_INTENT);
+            } catch (RuntimeException e) {
+            }
+            if (clientIntent != null) {
+                clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
+                if (clientLabel != 0) {
+                    // There are no useful extras in the intent, trash them.
+                    // System code calling with this stuff just needs to know
+                    // this will happen.
+                    service = service.cloneFilter();
+                }
+            }
+        }
+
+        ServiceLookupResult res =
+            retrieveServiceLocked(service, resolvedType,
+                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true);
+        if (res == null) {
+            return 0;
+        }
+        if (res.record == null) {
+            return -1;
+        }
+        ServiceRecord s = res.record;
+
+        final long origId = Binder.clearCallingIdentity();
+
+        try {
+            if (unscheduleServiceRestartLocked(s)) {
+                if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
+                        + s);
+            }
+
+            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
+            ConnectionRecord c = new ConnectionRecord(b, activity,
+                    connection, flags, clientLabel, clientIntent);
+
+            IBinder binder = connection.asBinder();
+            ArrayList<ConnectionRecord> clist = s.connections.get(binder);
+            if (clist == null) {
+                clist = new ArrayList<ConnectionRecord>();
+                s.connections.put(binder, clist);
+            }
+            clist.add(c);
+            b.connections.add(c);
+            if (activity != null) {
+                if (activity.connections == null) {
+                    activity.connections = new HashSet<ConnectionRecord>();
+                }
+                activity.connections.add(c);
+            }
+            b.client.connections.add(c);
+            if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
+                b.client.hasAboveClient = true;
+            }
+            clist = mServiceConnections.get(binder);
+            if (clist == null) {
+                clist = new ArrayList<ConnectionRecord>();
+                mServiceConnections.put(binder, clist);
+            }
+            clist.add(c);
+
+            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
+                s.lastActivity = SystemClock.uptimeMillis();
+                if (bringUpServiceLocked(s, service.getFlags(), false) != null) {
+                    return 0;
+                }
+            }
+
+            if (s.app != null) {
+                // This could have made the service more important.
+                mAm.updateOomAdjLocked(s.app);
+            }
+
+            if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
+                    + ": received=" + b.intent.received
+                    + " apps=" + b.intent.apps.size()
+                    + " doRebind=" + b.intent.doRebind);
+
+            if (s.app != null && b.intent.received) {
+                // Service is already running, so we can immediately
+                // publish the connection.
+                try {
+                    c.conn.connected(s.name, b.intent.binder);
+                } catch (Exception e) {
+                    Slog.w(TAG, "Failure sending service " + s.shortName
+                            + " to connection " + c.conn.asBinder()
+                            + " (in " + c.binding.client.processName + ")", e);
+                }
+
+                // If this is the first app connected back to this binding,
+                // and the service had previously asked to be told when
+                // rebound, then do so.
+                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
+                    requestServiceBindingLocked(s, b.intent, true);
+                }
+            } else if (!b.intent.requested) {
+                requestServiceBindingLocked(s, b.intent, false);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
+
+        return 1;
+    }
+
+    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
+        final long origId = Binder.clearCallingIdentity();
+        try {
+            if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
+                    + " " + intent + ": " + service);
+            if (r != null) {
+                Intent.FilterComparison filter
+                        = new Intent.FilterComparison(intent);
+                IntentBindRecord b = r.bindings.get(filter);
+                if (b != null && !b.received) {
+                    b.binder = service;
+                    b.requested = true;
+                    b.received = true;
+                    if (r.connections.size() > 0) {
+                        Iterator<ArrayList<ConnectionRecord>> it
+                                = r.connections.values().iterator();
+                        while (it.hasNext()) {
+                            ArrayList<ConnectionRecord> clist = it.next();
+                            for (int i=0; i<clist.size(); i++) {
+                                ConnectionRecord c = clist.get(i);
+                                if (!filter.equals(c.binding.intent.intent)) {
+                                    if (DEBUG_SERVICE) Slog.v(
+                                            TAG, "Not publishing to: " + c);
+                                    if (DEBUG_SERVICE) Slog.v(
+                                            TAG, "Bound intent: " + c.binding.intent.intent);
+                                    if (DEBUG_SERVICE) Slog.v(
+                                            TAG, "Published intent: " + intent);
+                                    continue;
+                                }
+                                if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
+                                try {
+                                    c.conn.connected(r.name, service);
+                                } catch (Exception e) {
+                                    Slog.w(TAG, "Failure sending service " + r.name +
+                                          " to connection " + c.conn.asBinder() +
+                                          " (in " + c.binding.client.processName + ")", e);
+                                }
+                            }
+                        }
+                    }
+                }
+
+                serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
+            }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    boolean unbindServiceLocked(IServiceConnection connection) {
+        IBinder binder = connection.asBinder();
+        if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
+        ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
+        if (clist == null) {
+            Slog.w(TAG, "Unbind failed: could not find connection for "
+                  + connection.asBinder());
+            return false;
+        }
+
+        final long origId = Binder.clearCallingIdentity();
+        try {
+            while (clist.size() > 0) {
+                ConnectionRecord r = clist.get(0);
+                removeConnectionLocked(r, null, null);
+
+                if (r.binding.service.app != null) {
+                    // This could have made the service less important.
+                    mAm.updateOomAdjLocked(r.binding.service.app);
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
+
+        return true;
+    }
+
+    void unbindFinishedLocked(ServiceRecord r, Intent intent, boolean doRebind) {
+        final long origId = Binder.clearCallingIdentity();
+        try {
+            if (r != null) {
+                Intent.FilterComparison filter
+                        = new Intent.FilterComparison(intent);
+                IntentBindRecord b = r.bindings.get(filter);
+                if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
+                        + " at " + b + ": apps="
+                        + (b != null ? b.apps.size() : 0));
+
+                boolean inStopping = mStoppingServices.contains(r);
+                if (b != null) {
+                    if (b.apps.size() > 0 && !inStopping) {
+                        // Applications have already bound since the last
+                        // unbind, so just rebind right here.
+                        requestServiceBindingLocked(r, b, true);
+                    } else {
+                        // Note to tell the service the next time there is
+                        // a new client.
+                        b.doRebind = true;
+                    }
+                }
+
+                serviceDoneExecutingLocked(r, inStopping);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    private final ServiceRecord findServiceLocked(ComponentName name,
+            IBinder token, int userId) {
+        ServiceRecord r = mServiceMap.getServiceByName(name, userId);
+        return r == token ? r : null;
+    }
+
+    private final class ServiceLookupResult {
+        final ServiceRecord record;
+        final String permission;
+
+        ServiceLookupResult(ServiceRecord _record, String _permission) {
+            record = _record;
+            permission = _permission;
+        }
+    }
+
+    private class ServiceRestarter implements Runnable {
+        private ServiceRecord mService;
+
+        void setService(ServiceRecord service) {
+            mService = service;
+        }
+
+        public void run() {
+            synchronized(mAm) {
+                performServiceRestartLocked(mService);
+            }
+        }
+    }
+
+    private ServiceLookupResult retrieveServiceLocked(Intent service,
+            String resolvedType, int callingPid, int callingUid, int userId,
+            boolean createIfNeeded) {
+        ServiceRecord r = null;
+        if (DEBUG_SERVICE) Slog.v(TAG, "retrieveServiceLocked: " + service
+                + " type=" + resolvedType + " callingUid=" + callingUid);
+
+        userId = mAm.handleIncomingUser(callingPid, callingUid, userId,
+                false, true, "service", null);
+
+        if (service.getComponent() != null) {
+            r = mServiceMap.getServiceByName(service.getComponent(), userId);
+        }
+        if (r == null) {
+            Intent.FilterComparison filter = new Intent.FilterComparison(service);
+            r = mServiceMap.getServiceByIntent(filter, userId);
+        }
+        if (r == null) {
+            try {
+                ResolveInfo rInfo =
+                    AppGlobals.getPackageManager().resolveService(
+                                service, resolvedType,
+                                ActivityManagerService.STOCK_PM_FLAGS, userId);
+                ServiceInfo sInfo =
+                    rInfo != null ? rInfo.serviceInfo : null;
+                if (sInfo == null) {
+                    Slog.w(TAG, "Unable to start service " + service + " U=" + userId +
+                          ": not found");
+                    return null;
+                }
+                ComponentName name = new ComponentName(
+                        sInfo.applicationInfo.packageName, sInfo.name);
+                if (userId > 0) {
+                    if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
+                            sInfo.name, sInfo.flags)) {
+                        userId = 0;
+                    }
+                    sInfo = new ServiceInfo(sInfo);
+                    sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
+                }
+                r = mServiceMap.getServiceByName(name, userId);
+                if (r == null && createIfNeeded) {
+                    Intent.FilterComparison filter = new Intent.FilterComparison(
+                            service.cloneFilter());
+                    ServiceRestarter res = new ServiceRestarter();
+                    BatteryStatsImpl.Uid.Pkg.Serv ss = null;
+                    BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
+                    synchronized (stats) {
+                        ss = stats.getServiceStatsLocked(
+                                sInfo.applicationInfo.uid, sInfo.packageName,
+                                sInfo.name);
+                    }
+                    r = new ServiceRecord(mAm, ss, name, filter, sInfo, res);
+                    res.setService(r);
+                    mServiceMap.putServiceByName(name, UserHandle.getUserId(r.appInfo.uid), r);
+                    mServiceMap.putServiceByIntent(filter, UserHandle.getUserId(r.appInfo.uid), r);
+
+                    // Make sure this component isn't in the pending list.
+                    int N = mPendingServices.size();
+                    for (int i=0; i<N; i++) {
+                        ServiceRecord pr = mPendingServices.get(i);
+                        if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
+                                && pr.name.equals(name)) {
+                            mPendingServices.remove(i);
+                            i--;
+                            N--;
+                        }
+                    }
+                }
+            } catch (RemoteException ex) {
+                // pm is in same process, this will never happen.
+            }
+        }
+        if (r != null) {
+            if (mAm.checkComponentPermission(r.permission,
+                    callingPid, callingUid, r.appInfo.uid, r.exported)
+                    != PackageManager.PERMISSION_GRANTED) {
+                if (!r.exported) {
+                    Slog.w(TAG, "Permission Denial: Accessing service " + r.name
+                            + " from pid=" + callingPid
+                            + ", uid=" + callingUid
+                            + " that is not exported from uid " + r.appInfo.uid);
+                    return new ServiceLookupResult(null, "not exported from uid "
+                            + r.appInfo.uid);
+                }
+                Slog.w(TAG, "Permission Denial: Accessing service " + r.name
+                        + " from pid=" + callingPid
+                        + ", uid=" + callingUid
+                        + " requires " + r.permission);
+                return new ServiceLookupResult(null, r.permission);
+            }
+            return new ServiceLookupResult(r, null);
+        }
+        return null;
+    }
+
+    private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
+        if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
+                + why + " of " + r + " in app " + r.app);
+        else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
+                + why + " of " + r.shortName);
+        long now = SystemClock.uptimeMillis();
+        if (r.executeNesting == 0 && r.app != null) {
+            if (r.app.executingServices.size() == 0) {
+                Message msg = mAm.mHandler.obtainMessage(
+                        ActivityManagerService.SERVICE_TIMEOUT_MSG);
+                msg.obj = r.app;
+                mAm.mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
+            }
+            r.app.executingServices.add(r);
+        }
+        r.executeNesting++;
+        r.executingStart = now;
+    }
+
+    private final boolean requestServiceBindingLocked(ServiceRecord r,
+            IntentBindRecord i, boolean rebind) {
+        if (r.app == null || r.app.thread == null) {
+            // If service is not currently running, can't yet bind.
+            return false;
+        }
+        if ((!i.requested || rebind) && i.apps.size() > 0) {
+            try {
+                bumpServiceExecutingLocked(r, "bind");
+                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
+                if (!rebind) {
+                    i.requested = true;
+                }
+                i.hasBound = true;
+                i.doRebind = false;
+            } catch (RemoteException e) {
+                if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private final boolean scheduleServiceRestartLocked(ServiceRecord r,
+            boolean allowCancel) {
+        boolean canceled = false;
+
+        final long now = SystemClock.uptimeMillis();
+
+        if ((r.serviceInfo.applicationInfo.flags
+                &ApplicationInfo.FLAG_PERSISTENT) == 0) {
+            long minDuration = SERVICE_RESTART_DURATION;
+            long resetTime = SERVICE_RESET_RUN_DURATION;
+
+            // Any delivered but not yet finished starts should be put back
+            // on the pending list.
+            final int N = r.deliveredStarts.size();
+            if (N > 0) {
+                for (int i=N-1; i>=0; i--) {
+                    ServiceRecord.StartItem si = r.deliveredStarts.get(i);
+                    si.removeUriPermissionsLocked();
+                    if (si.intent == null) {
+                        // We'll generate this again if needed.
+                    } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
+                            && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
+                        r.pendingStarts.add(0, si);
+                        long dur = SystemClock.uptimeMillis() - si.deliveredTime;
+                        dur *= 2;
+                        if (minDuration < dur) minDuration = dur;
+                        if (resetTime < dur) resetTime = dur;
+                    } else {
+                        Slog.w(TAG, "Canceling start item " + si.intent + " in service "
+                                + r.name);
+                        canceled = true;
+                    }
+                }
+                r.deliveredStarts.clear();
+            }
+
+            r.totalRestartCount++;
+            if (r.restartDelay == 0) {
+                r.restartCount++;
+                r.restartDelay = minDuration;
+            } else {
+                // If it has been a "reasonably long time" since the service
+                // was started, then reset our restart duration back to
+                // the beginning, so we don't infinitely increase the duration
+                // on a service that just occasionally gets killed (which is
+                // a normal case, due to process being killed to reclaim memory).
+                if (now > (r.restartTime+resetTime)) {
+                    r.restartCount = 1;
+                    r.restartDelay = minDuration;
+                } else {
+                    if ((r.serviceInfo.applicationInfo.flags
+                            &ApplicationInfo.FLAG_PERSISTENT) != 0) {
+                        // Services in peristent processes will restart much more
+                        // quickly, since they are pretty important.  (Think SystemUI).
+                        r.restartDelay += minDuration/2;
+                    } else {
+                        r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
+                        if (r.restartDelay < minDuration) {
+                            r.restartDelay = minDuration;
+                        }
+                    }
+                }
+            }
+
+            r.nextRestartTime = now + r.restartDelay;
+
+            // Make sure that we don't end up restarting a bunch of services
+            // all at the same time.
+            boolean repeat;
+            do {
+                repeat = false;
+                for (int i=mRestartingServices.size()-1; i>=0; i--) {
+                    ServiceRecord r2 = mRestartingServices.get(i);
+                    if (r2 != r && r.nextRestartTime
+                            >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
+                            && r.nextRestartTime
+                            < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
+                        r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
+                        r.restartDelay = r.nextRestartTime - now;
+                        repeat = true;
+                        break;
+                    }
+                }
+            } while (repeat);
+
+        } else {
+            // Persistent processes are immediately restrted, so there is no
+            // reason to hold of on restarting their services.
+            r.totalRestartCount++;
+            r.restartCount = 0;
+            r.restartDelay = 0;
+            r.nextRestartTime = now;
+        }
+
+        if (!mRestartingServices.contains(r)) {
+            mRestartingServices.add(r);
+        }
+
+        r.cancelNotification();
+
+        mAm.mHandler.removeCallbacks(r.restarter);
+        mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime);
+        r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
+        Slog.w(TAG, "Scheduling restart of crashed service "
+                + r.shortName + " in " + r.restartDelay + "ms");
+        EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
+                r.userId, r.shortName, r.restartDelay);
+
+        return canceled;
+    }
+
+    final void performServiceRestartLocked(ServiceRecord r) {
+        if (!mRestartingServices.contains(r)) {
+            return;
+        }
+        bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
+    }
+
+    private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
+        if (r.restartDelay == 0) {
+            return false;
+        }
+        r.resetRestartCounter();
+        mRestartingServices.remove(r);
+        mAm.mHandler.removeCallbacks(r.restarter);
+        return true;
+    }
+
+    private final String bringUpServiceLocked(ServiceRecord r,
+            int intentFlags, boolean whileRestarting) {
+        //Slog.i(TAG, "Bring up service:");
+        //r.dump("  ");
+
+        if (r.app != null && r.app.thread != null) {
+            sendServiceArgsLocked(r, false);
+            return null;
+        }
+
+        if (!whileRestarting && r.restartDelay > 0) {
+            // If waiting for a restart, then do nothing.
+            return null;
+        }
+
+        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
+
+        // We are now bringing the service up, so no longer in the
+        // restarting state.
+        mRestartingServices.remove(r);
+
+        // Make sure that the user who owns this service is started.  If not,
+        // we don't want to allow it to run.
+        if (mAm.mStartedUsers.get(r.userId) == null) {
+            String msg = "Unable to launch app "
+                    + r.appInfo.packageName + "/"
+                    + r.appInfo.uid + " for service "
+                    + r.intent.getIntent() + ": user " + r.userId + " is stopped";
+            Slog.w(TAG, msg);
+            bringDownServiceLocked(r, true);
+            return msg;
+        }
+
+        // Service is now being launched, its package can't be stopped.
+        try {
+            AppGlobals.getPackageManager().setPackageStoppedState(
+                    r.packageName, false, r.userId);
+        } catch (RemoteException e) {
+        } catch (IllegalArgumentException e) {
+            Slog.w(TAG, "Failed trying to unstop package "
+                    + r.packageName + ": " + e);
+        }
+
+        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
+        final String procName = r.processName;
+        ProcessRecord app;
+
+        if (!isolated) {
+            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid);
+            if (DEBUG_MU)
+                Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
+            if (app != null && app.thread != null) {
+                try {
+                    app.addPackage(r.appInfo.packageName);
+                    realStartServiceLocked(r, app);
+                    return null;
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
+                }
+
+                // If a dead object exception was thrown -- fall through to
+                // restart the application.
+            }
+        } else {
+            // If this service runs in an isolated process, then each time
+            // we call startProcessLocked() we will get a new isolated
+            // process, starting another process if we are currently waiting
+            // for a previous process to come up.  To deal with this, we store
+            // in the service any current isolated process it is running in or
+            // waiting to have come up.
+            app = r.isolatedProc;
+        }
+
+        // Not running -- get it started, and enqueue this service record
+        // to be executed when the app comes up.
+        if (app == null) {
+            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
+                    "service", r.name, false, isolated)) == null) {
+                String msg = "Unable to launch app "
+                        + r.appInfo.packageName + "/"
+                        + r.appInfo.uid + " for service "
+                        + r.intent.getIntent() + ": process is bad";
+                Slog.w(TAG, msg);
+                bringDownServiceLocked(r, true);
+                return msg;
+            }
+            if (isolated) {
+                r.isolatedProc = app;
+            }
+        }
+
+        if (!mPendingServices.contains(r)) {
+            mPendingServices.add(r);
+        }
+
+        return null;
+    }
+
+    private final void requestServiceBindingsLocked(ServiceRecord r) {
+        Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
+        while (bindings.hasNext()) {
+            IntentBindRecord i = bindings.next();
+            if (!requestServiceBindingLocked(r, i, false)) {
+                break;
+            }
+        }
+    }
+
+    private final void realStartServiceLocked(ServiceRecord r,
+            ProcessRecord app) throws RemoteException {
+        if (app.thread == null) {
+            throw new RemoteException();
+        }
+        if (DEBUG_MU)
+            Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
+                    + ", ProcessRecord.uid = " + app.uid);
+        r.app = app;
+        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
+
+        app.services.add(r);
+        bumpServiceExecutingLocked(r, "create");
+        mAm.updateLruProcessLocked(app, true);
+
+        boolean created = false;
+        try {
+            mAm.mStringBuilder.setLength(0);
+            r.intent.getIntent().toShortString(mAm.mStringBuilder, true, false, true, false);
+            EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
+                    r.userId, System.identityHashCode(r), r.shortName,
+                    mAm.mStringBuilder.toString(), r.app.pid);
+            synchronized (r.stats.getBatteryStats()) {
+                r.stats.startLaunchedLocked();
+            }
+            mAm.ensurePackageDexOpt(r.serviceInfo.packageName);
+            app.thread.scheduleCreateService(r, r.serviceInfo,
+                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
+            r.postNotification();
+            created = true;
+        } finally {
+            if (!created) {
+                app.services.remove(r);
+                scheduleServiceRestartLocked(r, false);
+            }
+        }
+
+        requestServiceBindingsLocked(r);
+
+        // If the service is in the started state, and there are no
+        // pending arguments, then fake up one so its onStartCommand() will
+        // be called.
+        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
+            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
+                    null, null));
+        }
+
+        sendServiceArgsLocked(r, true);
+    }
+
+    private final void sendServiceArgsLocked(ServiceRecord r,
+            boolean oomAdjusted) {
+        final int N = r.pendingStarts.size();
+        if (N == 0) {
+            return;
+        }
+
+        while (r.pendingStarts.size() > 0) {
+            try {
+                ServiceRecord.StartItem si = r.pendingStarts.remove(0);
+                if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
+                        + r + " " + r.intent + " args=" + si.intent);
+                if (si.intent == null && N > 1) {
+                    // If somehow we got a dummy null intent in the middle,
+                    // then skip it.  DO NOT skip a null intent when it is
+                    // the only one in the list -- this is to support the
+                    // onStartCommand(null) case.
+                    continue;
+                }
+                si.deliveredTime = SystemClock.uptimeMillis();
+                r.deliveredStarts.add(si);
+                si.deliveryCount++;
+                if (si.neededGrants != null) {
+                    mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
+                            si.getUriPermissionsLocked());
+                }
+                bumpServiceExecutingLocked(r, "start");
+                if (!oomAdjusted) {
+                    oomAdjusted = true;
+                    mAm.updateOomAdjLocked(r.app);
+                }
+                int flags = 0;
+                if (si.deliveryCount > 1) {
+                    flags |= Service.START_FLAG_RETRY;
+                }
+                if (si.doneExecutingCount > 0) {
+                    flags |= Service.START_FLAG_REDELIVERY;
+                }
+                r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
+            } catch (RemoteException e) {
+                // Remote process gone...  we'll let the normal cleanup take
+                // care of this.
+                if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
+                break;
+            } catch (Exception e) {
+                Slog.w(TAG, "Unexpected exception", e);
+                break;
+            }
+        }
+    }
+
+    private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
+        //Slog.i(TAG, "Bring down service:");
+        //r.dump("  ");
+
+        // Does it still need to run?
+        if (!force && r.startRequested) {
+            return;
+        }
+        if (r.connections.size() > 0) {
+            if (!force) {
+                // XXX should probably keep a count of the number of auto-create
+                // connections directly in the service.
+                Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
+                while (it.hasNext()) {
+                    ArrayList<ConnectionRecord> cr = it.next();
+                    for (int i=0; i<cr.size(); i++) {
+                        if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
+                            return;
+                        }
+                    }
+                }
+            }
+
+            // Report to all of the connections that the service is no longer
+            // available.
+            Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
+            while (it.hasNext()) {
+                ArrayList<ConnectionRecord> c = it.next();
+                for (int i=0; i<c.size(); i++) {
+                    ConnectionRecord cr = c.get(i);
+                    // There is still a connection to the service that is
+                    // being brought down.  Mark it as dead.
+                    cr.serviceDead = true;
+                    try {
+                        cr.conn.connected(r.name, null);
+                    } catch (Exception e) {
+                        Slog.w(TAG, "Failure disconnecting service " + r.name +
+                              " to connection " + c.get(i).conn.asBinder() +
+                              " (in " + c.get(i).binding.client.processName + ")", e);
+                    }
+                }
+            }
+        }
+
+        // Tell the service that it has been unbound.
+        if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
+            Iterator<IntentBindRecord> it = r.bindings.values().iterator();
+            while (it.hasNext()) {
+                IntentBindRecord ibr = it.next();
+                if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
+                        + ": hasBound=" + ibr.hasBound);
+                if (r.app != null && r.app.thread != null && ibr.hasBound) {
+                    try {
+                        bumpServiceExecutingLocked(r, "bring down unbind");
+                        mAm.updateOomAdjLocked(r.app);
+                        ibr.hasBound = false;
+                        r.app.thread.scheduleUnbindService(r,
+                                ibr.intent.getIntent());
+                    } catch (Exception e) {
+                        Slog.w(TAG, "Exception when unbinding service "
+                                + r.shortName, e);
+                        serviceDoneExecutingLocked(r, true);
+                    }
+                }
+            }
+        }
+
+        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
+        EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
+                r.userId, System.identityHashCode(r), r.shortName,
+                (r.app != null) ? r.app.pid : -1);
+
+        mServiceMap.removeServiceByName(r.name, r.userId);
+        mServiceMap.removeServiceByIntent(r.intent, r.userId);
+        r.totalRestartCount = 0;
+        unscheduleServiceRestartLocked(r);
+
+        // Also make sure it is not on the pending list.
+        int N = mPendingServices.size();
+        for (int i=0; i<N; i++) {
+            if (mPendingServices.get(i) == r) {
+                mPendingServices.remove(i);
+                if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
+                i--;
+                N--;
+            }
+        }
+
+        r.cancelNotification();
+        r.isForeground = false;
+        r.foregroundId = 0;
+        r.foregroundNoti = null;
+
+        // Clear start entries.
+        r.clearDeliveredStartsLocked();
+        r.pendingStarts.clear();
+
+        if (r.app != null) {
+            synchronized (r.stats.getBatteryStats()) {
+                r.stats.stopLaunchedLocked();
+            }
+            r.app.services.remove(r);
+            if (r.app.thread != null) {
+                try {
+                    bumpServiceExecutingLocked(r, "stop");
+                    mStoppingServices.add(r);
+                    mAm.updateOomAdjLocked(r.app);
+                    r.app.thread.scheduleStopService(r);
+                } catch (Exception e) {
+                    Slog.w(TAG, "Exception when stopping service "
+                            + r.shortName, e);
+                    serviceDoneExecutingLocked(r, true);
+                }
+                updateServiceForegroundLocked(r.app, false);
+            } else {
+                if (DEBUG_SERVICE) Slog.v(
+                    TAG, "Removed service that has no process: " + r);
+            }
+        } else {
+            if (DEBUG_SERVICE) Slog.v(
+                TAG, "Removed service that is not running: " + r);
+        }
+
+        if (r.bindings.size() > 0) {
+            r.bindings.clear();
+        }
+
+        if (r.restarter instanceof ServiceRestarter) {
+           ((ServiceRestarter)r.restarter).setService(null);
+        }
+    }
+
+    void removeConnectionLocked(
+        ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
+        IBinder binder = c.conn.asBinder();
+        AppBindRecord b = c.binding;
+        ServiceRecord s = b.service;
+        ArrayList<ConnectionRecord> clist = s.connections.get(binder);
+        if (clist != null) {
+            clist.remove(c);
+            if (clist.size() == 0) {
+                s.connections.remove(binder);
+            }
+        }
+        b.connections.remove(c);
+        if (c.activity != null && c.activity != skipAct) {
+            if (c.activity.connections != null) {
+                c.activity.connections.remove(c);
+            }
+        }
+        if (b.client != skipApp) {
+            b.client.connections.remove(c);
+            if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
+                b.client.updateHasAboveClientLocked();
+            }
+        }
+        clist = mServiceConnections.get(binder);
+        if (clist != null) {
+            clist.remove(c);
+            if (clist.size() == 0) {
+                mServiceConnections.remove(binder);
+            }
+        }
+
+        if (b.connections.size() == 0) {
+            b.intent.apps.remove(b.client);
+        }
+
+        if (!c.serviceDead) {
+            if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
+                    + ": shouldUnbind=" + b.intent.hasBound);
+            if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
+                    && b.intent.hasBound) {
+                try {
+                    bumpServiceExecutingLocked(s, "unbind");
+                    mAm.updateOomAdjLocked(s.app);
+                    b.intent.hasBound = false;
+                    // Assume the client doesn't want to know about a rebind;
+                    // we will deal with that later if it asks for one.
+                    b.intent.doRebind = false;
+                    s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
+                } catch (Exception e) {
+                    Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
+                    serviceDoneExecutingLocked(s, true);
+                }
+            }
+
+            if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
+                bringDownServiceLocked(s, false);
+            }
+        }
+    }
+
+    void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
+        boolean inStopping = mStoppingServices.contains(r);
+        if (r != null) {
+            if (type == 1) {
+                // This is a call from a service start...  take care of
+                // book-keeping.
+                r.callStart = true;
+                switch (res) {
+                    case Service.START_STICKY_COMPATIBILITY:
+                    case Service.START_STICKY: {
+                        // We are done with the associated start arguments.
+                        r.findDeliveredStart(startId, true);
+                        // Don't stop if killed.
+                        r.stopIfKilled = false;
+                        break;
+                    }
+                    case Service.START_NOT_STICKY: {
+                        // We are done with the associated start arguments.
+                        r.findDeliveredStart(startId, true);
+                        if (r.getLastStartId() == startId) {
+                            // There is no more work, and this service
+                            // doesn't want to hang around if killed.
+                            r.stopIfKilled = true;
+                        }
+                        break;
+                    }
+                    case Service.START_REDELIVER_INTENT: {
+                        // We'll keep this item until they explicitly
+                        // call stop for it, but keep track of the fact
+                        // that it was delivered.
+                        ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
+                        if (si != null) {
+                            si.deliveryCount = 0;
+                            si.doneExecutingCount++;
+                            // Don't stop if killed.
+                            r.stopIfKilled = true;
+                        }
+                        break;
+                    }
+                    case Service.START_TASK_REMOVED_COMPLETE: {
+                        // Special processing for onTaskRemoved().  Don't
+                        // impact normal onStartCommand() processing.
+                        r.findDeliveredStart(startId, true);
+                        break;
+                    }
+                    default:
+                        throw new IllegalArgumentException(
+                                "Unknown service start result: " + res);
+                }
+                if (res == Service.START_STICKY_COMPATIBILITY) {
+                    r.callStart = false;
+                }
+            }
+            final long origId = Binder.clearCallingIdentity();
+            serviceDoneExecutingLocked(r, inStopping);
+            Binder.restoreCallingIdentity(origId);
+        } else {
+            Slog.w(TAG, "Done executing unknown service from pid "
+                    + Binder.getCallingPid());
+        }
+    }
+
+    private void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
+        if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
+                + ": nesting=" + r.executeNesting
+                + ", inStopping=" + inStopping + ", app=" + r.app);
+        else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
+        r.executeNesting--;
+        if (r.executeNesting <= 0 && r.app != null) {
+            if (DEBUG_SERVICE) Slog.v(TAG,
+                    "Nesting at 0 of " + r.shortName);
+            r.app.executingServices.remove(r);
+            if (r.app.executingServices.size() == 0) {
+                if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
+                        "No more executingServices of " + r.shortName);
+                mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
+            }
+            if (inStopping) {
+                if (DEBUG_SERVICE) Slog.v(TAG,
+                        "doneExecuting remove stopping " + r);
+                mStoppingServices.remove(r);
+                r.bindings.clear();
+            }
+            mAm.updateOomAdjLocked(r.app);
+        }
+    }
+
+    boolean attachApplicationLocked(ProcessRecord proc, String processName) throws Exception {
+        boolean didSomething = false;
+        // Collect any services that are waiting for this process to come up.
+        if (mPendingServices.size() > 0) {
+            ServiceRecord sr = null;
+            try {
+                for (int i=0; i<mPendingServices.size(); i++) {
+                    sr = mPendingServices.get(i);
+                    if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
+                            || !processName.equals(sr.processName))) {
+                        continue;
+                    }
+
+                    mPendingServices.remove(i);
+                    i--;
+                    realStartServiceLocked(sr, proc);
+                    didSomething = true;
+                }
+            } catch (Exception e) {
+                Slog.w(TAG, "Exception in new application when starting service "
+                        + sr.shortName, e);
+                throw e;
+            }
+        }
+        // Also, if there are any services that are waiting to restart and
+        // would run in this process, now is a good time to start them.  It would
+        // be weird to bring up the process but arbitrarily not let the services
+        // run at this point just because their restart time hasn't come up.
+        if (mRestartingServices.size() > 0) {
+            ServiceRecord sr = null;
+            for (int i=0; i<mRestartingServices.size(); i++) {
+                sr = mRestartingServices.get(i);
+                if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
+                        || !processName.equals(sr.processName))) {
+                    continue;
+                }
+                mAm.mHandler.removeCallbacks(sr.restarter);
+                mAm.mHandler.post(sr.restarter);
+            }
+        }
+        return didSomething;
+    }
+
+    void processStartTimedOutLocked(ProcessRecord proc) {
+        for (int i=0; i<mPendingServices.size(); i++) {
+            ServiceRecord sr = mPendingServices.get(i);
+            if ((proc.uid == sr.appInfo.uid
+                    && proc.processName.equals(sr.processName))
+                    || sr.isolatedProc == proc) {
+                Slog.w(TAG, "Forcing bringing down service: " + sr);
+                sr.isolatedProc = null;
+                mPendingServices.remove(i);
+                i--;
+                bringDownServiceLocked(sr, true);
+            }
+        }
+    }
+
+    private boolean collectForceStopServicesLocked(String name, int userId,
+            boolean evenPersistent, boolean doit,
+            HashMap<ComponentName, ServiceRecord> services,
+            ArrayList<ServiceRecord> result) {
+        boolean didSomething = false;
+        for (ServiceRecord service : services.values()) {
+            if ((name == null || service.packageName.equals(name))
+                    && (service.app == null || evenPersistent || !service.app.persistent)) {
+                if (!doit) {
+                    return true;
+                }
+                didSomething = true;
+                Slog.i(TAG, "  Force stopping service " + service);
+                if (service.app != null) {
+                    service.app.removed = true;
+                }
+                service.app = null;
+                service.isolatedProc = null;
+                result.add(service);
+            }
+        }
+        return didSomething;
+    }
+
+    boolean forceStopLocked(String name, int userId, boolean evenPersistent, boolean doit) {
+        boolean didSomething = false;
+        ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
+        if (userId == UserHandle.USER_ALL) {
+            for (int i=0; i<mServiceMap.mServicesByNamePerUser.size(); i++) {
+                didSomething |= collectForceStopServicesLocked(name, userId, evenPersistent,
+                        doit, mServiceMap.mServicesByNamePerUser.valueAt(i), services);
+                if (!doit && didSomething) {
+                    return true;
+                }
+            }
+        } else {
+            HashMap<ComponentName, ServiceRecord> items
+                    = mServiceMap.mServicesByNamePerUser.get(userId);
+            if (items != null) {
+                didSomething = collectForceStopServicesLocked(name, userId, evenPersistent,
+                        doit, items, services);
+            }
+        }
+
+        int N = services.size();
+        for (int i=0; i<N; i++) {
+            bringDownServiceLocked(services.get(i), true);
+        }
+        return didSomething;
+    }
+
+    void cleanUpRemovedTaskLocked(TaskRecord tr, ComponentName component, Intent baseIntent) {
+        ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
+        for (ServiceRecord sr : mServiceMap.getAllServices(tr.userId)) {
+            if (sr.packageName.equals(component.getPackageName())) {
+                services.add(sr);
+            }
+        }
+
+        // Take care of any running services associated with the app.
+        for (int i=0; i<services.size(); i++) {
+            ServiceRecord sr = services.get(i);
+            if (sr.startRequested) {
+                if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
+                    Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
+                    stopServiceLocked(sr);
+                } else {
+                    sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
+                            sr.makeNextStartId(), baseIntent, null));
+                    if (sr.app != null && sr.app.thread != null) {
+                        sendServiceArgsLocked(sr, false);
+                    }
+                }
+            }
+        }
+    }
+
+    final void killServicesLocked(ProcessRecord app,
+            boolean allowRestart) {
+        // Report disconnected services.
+        if (false) {
+            // XXX we are letting the client link to the service for
+            // death notifications.
+            if (app.services.size() > 0) {
+                Iterator<ServiceRecord> it = app.services.iterator();
+                while (it.hasNext()) {
+                    ServiceRecord r = it.next();
+                    if (r.connections.size() > 0) {
+                        Iterator<ArrayList<ConnectionRecord>> jt
+                                = r.connections.values().iterator();
+                        while (jt.hasNext()) {
+                            ArrayList<ConnectionRecord> cl = jt.next();
+                            for (int i=0; i<cl.size(); i++) {
+                                ConnectionRecord c = cl.get(i);
+                                if (c.binding.client != app) {
+                                    try {
+                                        //c.conn.connected(r.className, null);
+                                    } catch (Exception e) {
+                                        // todo: this should be asynchronous!
+                                        Slog.w(TAG, "Exception thrown disconnected servce "
+                                              + r.shortName
+                                              + " from app " + app.processName, e);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // Clean up any connections this application has to other services.
+        if (app.connections.size() > 0) {
+            Iterator<ConnectionRecord> it = app.connections.iterator();
+            while (it.hasNext()) {
+                ConnectionRecord r = it.next();
+                removeConnectionLocked(r, app, null);
+            }
+        }
+        app.connections.clear();
+
+        if (app.services.size() != 0) {
+            // Any services running in the application need to be placed
+            // back in the pending list.
+            Iterator<ServiceRecord> it = app.services.iterator();
+            while (it.hasNext()) {
+                ServiceRecord sr = it.next();
+                synchronized (sr.stats.getBatteryStats()) {
+                    sr.stats.stopLaunchedLocked();
+                }
+                sr.app = null;
+                sr.isolatedProc = null;
+                sr.executeNesting = 0;
+                if (mStoppingServices.remove(sr)) {
+                    if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
+                }
+
+                boolean hasClients = sr.bindings.size() > 0;
+                if (hasClients) {
+                    Iterator<IntentBindRecord> bindings
+                            = sr.bindings.values().iterator();
+                    while (bindings.hasNext()) {
+                        IntentBindRecord b = bindings.next();
+                        if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
+                                + ": shouldUnbind=" + b.hasBound);
+                        b.binder = null;
+                        b.requested = b.received = b.hasBound = false;
+                    }
+                }
+
+                if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
+                        &ApplicationInfo.FLAG_PERSISTENT) == 0) {
+                    Slog.w(TAG, "Service crashed " + sr.crashCount
+                            + " times, stopping: " + sr);
+                    EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
+                            sr.userId, sr.crashCount, sr.shortName, app.pid);
+                    bringDownServiceLocked(sr, true);
+                } else if (!allowRestart) {
+                    bringDownServiceLocked(sr, true);
+                } else {
+                    boolean canceled = scheduleServiceRestartLocked(sr, true);
+
+                    // Should the service remain running?  Note that in the
+                    // extreme case of so many attempts to deliver a command
+                    // that it failed we also will stop it here.
+                    if (sr.startRequested && (sr.stopIfKilled || canceled)) {
+                        if (sr.pendingStarts.size() == 0) {
+                            sr.startRequested = false;
+                            if (!hasClients) {
+                                // Whoops, no reason to restart!
+                                bringDownServiceLocked(sr, true);
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (!allowRestart) {
+                app.services.clear();
+            }
+        }
+
+        // Make sure we have no more records on the stopping list.
+        int i = mStoppingServices.size();
+        while (i > 0) {
+            i--;
+            ServiceRecord sr = mStoppingServices.get(i);
+            if (sr.app == app) {
+                mStoppingServices.remove(i);
+                if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
+            }
+        }
+
+        app.executingServices.clear();
+    }
+
+    ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
+        ActivityManager.RunningServiceInfo info =
+            new ActivityManager.RunningServiceInfo();
+        info.service = r.name;
+        if (r.app != null) {
+            info.pid = r.app.pid;
+        }
+        info.uid = r.appInfo.uid;
+        info.process = r.processName;
+        info.foreground = r.isForeground;
+        info.activeSince = r.createTime;
+        info.started = r.startRequested;
+        info.clientCount = r.connections.size();
+        info.crashCount = r.crashCount;
+        info.lastActivityTime = r.lastActivity;
+        if (r.isForeground) {
+            info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
+        }
+        if (r.startRequested) {
+            info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
+        }
+        if (r.app != null && r.app.pid == ActivityManagerService.MY_PID) {
+            info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
+        }
+        if (r.app != null && r.app.persistent) {
+            info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
+        }
+
+        for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
+            for (int i=0; i<connl.size(); i++) {
+                ConnectionRecord conn = connl.get(i);
+                if (conn.clientLabel != 0) {
+                    info.clientPackage = conn.binding.client.info.packageName;
+                    info.clientLabel = conn.clientLabel;
+                    return info;
+                }
+            }
+        }
+        return info;
+    }
+
+    List<ActivityManager.RunningServiceInfo> getRunningServiceInfoLocked(int maxNum,
+            int flags) {
+        ArrayList<ActivityManager.RunningServiceInfo> res
+                = new ArrayList<ActivityManager.RunningServiceInfo>();
+
+        final int uid = Binder.getCallingUid();
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            if (ActivityManager.checkUidPermission(
+                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    uid) == PackageManager.PERMISSION_GRANTED) {
+                int[] users = mAm.getUsersLocked();
+                for (int ui=0; ui<users.length && res.size() < maxNum; ui++) {
+                    if (mServiceMap.getAllServices(users[ui]).size() > 0) {
+                        Iterator<ServiceRecord> it = mServiceMap.getAllServices(
+                                users[ui]).iterator();
+                        while (it.hasNext() && res.size() < maxNum) {
+                            res.add(makeRunningServiceInfoLocked(it.next()));
+                        }
+                    }
+                }
+
+                for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
+                    ServiceRecord r = mRestartingServices.get(i);
+                    ActivityManager.RunningServiceInfo info =
+                            makeRunningServiceInfoLocked(r);
+                    info.restarting = r.nextRestartTime;
+                    res.add(info);
+                }
+            } else {
+                int userId = UserHandle.getUserId(uid);
+                if (mServiceMap.getAllServices(userId).size() > 0) {
+                    Iterator<ServiceRecord> it
+                            = mServiceMap.getAllServices(userId).iterator();
+                    while (it.hasNext() && res.size() < maxNum) {
+                        res.add(makeRunningServiceInfoLocked(it.next()));
+                    }
+                }
+
+                for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
+                    ServiceRecord r = mRestartingServices.get(i);
+                    if (r.userId == userId) {
+                        ActivityManager.RunningServiceInfo info =
+                                makeRunningServiceInfoLocked(r);
+                        info.restarting = r.nextRestartTime;
+                        res.add(info);
+                    }
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+
+        return res;
+    }
+
+    public PendingIntent getRunningServiceControlPanelLocked(ComponentName name) {
+        int userId = UserHandle.getUserId(Binder.getCallingUid());
+        ServiceRecord r = mServiceMap.getServiceByName(name, userId);
+        if (r != null) {
+            for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
+                for (int i=0; i<conn.size(); i++) {
+                    if (conn.get(i).clientIntent != null) {
+                        return conn.get(i).clientIntent;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    void serviceTimeout(ProcessRecord proc) {
+        String anrMessage = null;
+
+        synchronized(this) {
+            if (proc.executingServices.size() == 0 || proc.thread == null) {
+                return;
+            }
+            long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
+            Iterator<ServiceRecord> it = proc.executingServices.iterator();
+            ServiceRecord timeout = null;
+            long nextTime = 0;
+            while (it.hasNext()) {
+                ServiceRecord sr = it.next();
+                if (sr.executingStart < maxTime) {
+                    timeout = sr;
+                    break;
+                }
+                if (sr.executingStart > nextTime) {
+                    nextTime = sr.executingStart;
+                }
+            }
+            if (timeout != null && mAm.mLruProcesses.contains(proc)) {
+                Slog.w(TAG, "Timeout executing service: " + timeout);
+                anrMessage = "Executing service " + timeout.shortName;
+            } else {
+                Message msg = mAm.mHandler.obtainMessage(
+                        ActivityManagerService.SERVICE_TIMEOUT_MSG);
+                msg.obj = proc;
+                mAm.mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
+            }
+        }
+
+        if (anrMessage != null) {
+            mAm.appNotResponding(proc, null, null, false, anrMessage);
+        }
+    }
+
+    /**
+     * Prints a list of ServiceRecords (dumpsys activity services)
+     */
+    boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
+            int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
+        boolean needSep = false;
+
+        ItemMatcher matcher = new ItemMatcher();
+        matcher.build(args, opti);
+
+        pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
+        try {
+            int[] users = mAm.getUsersLocked();
+            for (int user : users) {
+                if (mServiceMap.getAllServices(user).size() > 0) {
+                    boolean printed = false;
+                    long nowReal = SystemClock.elapsedRealtime();
+                    Iterator<ServiceRecord> it = mServiceMap.getAllServices(
+                            user).iterator();
+                    needSep = false;
+                    while (it.hasNext()) {
+                        ServiceRecord r = it.next();
+                        if (!matcher.match(r, r.name)) {
+                            continue;
+                        }
+                        if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
+                            continue;
+                        }
+                        if (!printed) {
+                            if (user != 0) {
+                                pw.println();
+                            }
+                            pw.println("  User " + user + " active services:");
+                            printed = true;
+                        }
+                        if (needSep) {
+                            pw.println();
+                        }
+                        pw.print("  * ");
+                        pw.println(r);
+                        if (dumpAll) {
+                            r.dump(pw, "    ");
+                            needSep = true;
+                        } else {
+                            pw.print("    app=");
+                            pw.println(r.app);
+                            pw.print("    created=");
+                            TimeUtils.formatDuration(r.createTime, nowReal, pw);
+                            pw.print(" started=");
+                            pw.print(r.startRequested);
+                            pw.print(" connections=");
+                            pw.println(r.connections.size());
+                            if (r.connections.size() > 0) {
+                                pw.println("    Connections:");
+                                for (ArrayList<ConnectionRecord> clist : r.connections.values()) {
+                                    for (int i = 0; i < clist.size(); i++) {
+                                        ConnectionRecord conn = clist.get(i);
+                                        pw.print("      ");
+                                        pw.print(conn.binding.intent.intent.getIntent()
+                                                .toShortString(false, false, false, false));
+                                        pw.print(" -> ");
+                                        ProcessRecord proc = conn.binding.client;
+                                        pw.println(proc != null ? proc.toShortString() : "null");
+                                    }
+                                }
+                            }
+                        }
+                        if (dumpClient && r.app != null && r.app.thread != null) {
+                            pw.println("    Client:");
+                            pw.flush();
+                            try {
+                                TransferPipe tp = new TransferPipe();
+                                try {
+                                    r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(),
+                                            r, args);
+                                    tp.setBufferPrefix("      ");
+                                    // Short timeout, since blocking here can
+                                    // deadlock with the application.
+                                    tp.go(fd, 2000);
+                                } finally {
+                                    tp.kill();
+                                }
+                            } catch (IOException e) {
+                                pw.println("      Failure while dumping the service: " + e);
+                            } catch (RemoteException e) {
+                                pw.println("      Got a RemoteException while dumping the service");
+                            }
+                            needSep = true;
+                        }
+                    }
+                    needSep = printed;
+                }
+            }
+        } catch (Exception e) {
+            Log.w(TAG, "Exception in dumpServicesLocked: " + e);
+        }
+
+        if (mPendingServices.size() > 0) {
+            boolean printed = false;
+            for (int i=0; i<mPendingServices.size(); i++) {
+                ServiceRecord r = mPendingServices.get(i);
+                if (!matcher.match(r, r.name)) {
+                    continue;
+                }
+                if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
+                    continue;
+                }
+                if (!printed) {
+                    if (needSep) pw.println(" ");
+                    needSep = true;
+                    pw.println("  Pending services:");
+                    printed = true;
+                }
+                pw.print("  * Pending "); pw.println(r);
+                r.dump(pw, "    ");
+            }
+            needSep = true;
+        }
+
+        if (mRestartingServices.size() > 0) {
+            boolean printed = false;
+            for (int i=0; i<mRestartingServices.size(); i++) {
+                ServiceRecord r = mRestartingServices.get(i);
+                if (!matcher.match(r, r.name)) {
+                    continue;
+                }
+                if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
+                    continue;
+                }
+                if (!printed) {
+                    if (needSep) pw.println(" ");
+                    needSep = true;
+                    pw.println("  Restarting services:");
+                    printed = true;
+                }
+                pw.print("  * Restarting "); pw.println(r);
+                r.dump(pw, "    ");
+            }
+            needSep = true;
+        }
+
+        if (mStoppingServices.size() > 0) {
+            boolean printed = false;
+            for (int i=0; i<mStoppingServices.size(); i++) {
+                ServiceRecord r = mStoppingServices.get(i);
+                if (!matcher.match(r, r.name)) {
+                    continue;
+                }
+                if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
+                    continue;
+                }
+                if (!printed) {
+                    if (needSep) pw.println(" ");
+                    needSep = true;
+                    pw.println("  Stopping services:");
+                    printed = true;
+                }
+                pw.print("  * Stopping "); pw.println(r);
+                r.dump(pw, "    ");
+            }
+            needSep = true;
+        }
+
+        if (dumpAll) {
+            if (mServiceConnections.size() > 0) {
+                boolean printed = false;
+                Iterator<ArrayList<ConnectionRecord>> it
+                        = mServiceConnections.values().iterator();
+                while (it.hasNext()) {
+                    ArrayList<ConnectionRecord> r = it.next();
+                    for (int i=0; i<r.size(); i++) {
+                        ConnectionRecord cr = r.get(i);
+                        if (!matcher.match(cr.binding.service, cr.binding.service.name)) {
+                            continue;
+                        }
+                        if (dumpPackage != null && (cr.binding.client == null
+                                || !dumpPackage.equals(cr.binding.client.info.packageName))) {
+                            continue;
+                        }
+                        if (!printed) {
+                            if (needSep) pw.println(" ");
+                            needSep = true;
+                            pw.println("  Connection bindings to services:");
+                            printed = true;
+                        }
+                        pw.print("  * "); pw.println(cr);
+                        cr.dump(pw, "    ");
+                    }
+                }
+                needSep = true;
+            }
+        }
+
+        return needSep;
+    }
+
+    /**
+     * There are three ways to call this:
+     *  - no service specified: dump all the services
+     *  - a flattened component name that matched an existing service was specified as the
+     *    first arg: dump that one service
+     *  - the first arg isn't the flattened component name of an existing service:
+     *    dump all services whose component contains the first arg as a substring
+     */
+    protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
+            int opti, boolean dumpAll) {
+        ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
+
+        synchronized (this) {
+            int[] users = mAm.getUsersLocked();
+            if ("all".equals(name)) {
+                for (int user : users) {
+                    for (ServiceRecord r1 : mServiceMap.getAllServices(user)) {
+                        services.add(r1);
+                    }
+                }
+            } else {
+                ComponentName componentName = name != null
+                        ? ComponentName.unflattenFromString(name) : null;
+                int objectId = 0;
+                if (componentName == null) {
+                    // Not a '/' separated full component name; maybe an object ID?
+                    try {
+                        objectId = Integer.parseInt(name, 16);
+                        name = null;
+                        componentName = null;
+                    } catch (RuntimeException e) {
+                    }
+                }
+
+                for (int user : users) {
+                    for (ServiceRecord r1 : mServiceMap.getAllServices(user)) {
+                        if (componentName != null) {
+                            if (r1.name.equals(componentName)) {
+                                services.add(r1);
+                            }
+                        } else if (name != null) {
+                            if (r1.name.flattenToString().contains(name)) {
+                                services.add(r1);
+                            }
+                        } else if (System.identityHashCode(r1) == objectId) {
+                            services.add(r1);
+                        }
+                    }
+                }
+            }
+        }
+
+        if (services.size() <= 0) {
+            return false;
+        }
+
+        boolean needSep = false;
+        for (int i=0; i<services.size(); i++) {
+            if (needSep) {
+                pw.println();
+            }
+            needSep = true;
+            dumpService("", fd, pw, services.get(i), args, dumpAll);
+        }
+        return true;
+    }
+
+    /**
+     * Invokes IApplicationThread.dumpService() on the thread of the specified service if
+     * there is a thread associated with the service.
+     */
+    private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
+            final ServiceRecord r, String[] args, boolean dumpAll) {
+        String innerPrefix = prefix + "  ";
+        synchronized (this) {
+            pw.print(prefix); pw.print("SERVICE ");
+                    pw.print(r.shortName); pw.print(" ");
+                    pw.print(Integer.toHexString(System.identityHashCode(r)));
+                    pw.print(" pid=");
+                    if (r.app != null) pw.println(r.app.pid);
+                    else pw.println("(not running)");
+            if (dumpAll) {
+                r.dump(pw, innerPrefix);
+            }
+        }
+        if (r.app != null && r.app.thread != null) {
+            pw.print(prefix); pw.println("  Client:");
+            pw.flush();
+            try {
+                TransferPipe tp = new TransferPipe();
+                try {
+                    r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
+                    tp.setBufferPrefix(prefix + "    ");
+                    tp.go(fd);
+                } finally {
+                    tp.kill();
+                }
+            } catch (IOException e) {
+                pw.println(prefix + "    Failure while dumping the service: " + e);
+            } catch (RemoteException e) {
+                pw.println(prefix + "    Got a RemoteException while dumping the service");
+            }
+        }
+    }
+
+}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 5d74cf3..d2cd646 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -21,12 +21,14 @@
 import com.android.internal.R;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.ProcessStats;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.server.AttributeCache;
 import com.android.server.IntentResolver;
 import com.android.server.ProcessMap;
 import com.android.server.SystemServer;
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.pm.UserManagerService;
 import com.android.server.wm.WindowManagerService;
 
 import dalvik.system.Zygote;
@@ -46,12 +48,13 @@
 import android.app.INotificationManager;
 import android.app.IProcessObserver;
 import android.app.IServiceConnection;
+import android.app.IStopUserCallback;
 import android.app.IThumbnailReceiver;
+import android.app.IUserSwitchObserver;
 import android.app.Instrumentation;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.app.Service;
 import android.app.backup.IBackupManager;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
@@ -76,12 +79,12 @@
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PathPermission;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.UserInfo;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
@@ -99,6 +102,8 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IPermissionController;
+import android.os.IRemoteCallback;
+import android.os.IUserManager;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
@@ -111,7 +116,7 @@
 import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.format.Time;
 import android.util.EventLog;
@@ -120,7 +125,6 @@
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.util.SparseIntArray;
 import android.util.TimeUtils;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -144,7 +148,7 @@
 import java.io.StringWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
-import java.util.Collection;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -153,7 +157,6 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
@@ -167,6 +170,7 @@
     static final boolean localLOGV = DEBUG;
     static final boolean DEBUG_SWITCH = localLOGV || false;
     static final boolean DEBUG_TASKS = localLOGV || false;
+    static final boolean DEBUG_THUMBNAILS = localLOGV || false;
     static final boolean DEBUG_PAUSE = localLOGV || false;
     static final boolean DEBUG_OOM_ADJ = localLOGV || false;
     static final boolean DEBUG_TRANSITION = localLOGV || false;
@@ -178,6 +182,7 @@
     static final boolean DEBUG_VISBILITY = localLOGV || false;
     static final boolean DEBUG_PROCESSES = localLOGV || false;
     static final boolean DEBUG_PROCESS_OBSERVERS = localLOGV || false;
+    static final boolean DEBUG_CLEANUP = localLOGV || false;
     static final boolean DEBUG_PROVIDER = localLOGV || false;
     static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
     static final boolean DEBUG_USER_LEAVING = localLOGV || false;
@@ -242,37 +247,19 @@
     static final int BROADCAST_FG_TIMEOUT = 10*1000;
     static final int BROADCAST_BG_TIMEOUT = 60*1000;
 
-    // How long we wait for a service to finish executing.
-    static final int SERVICE_TIMEOUT = 20*1000;
-
-    // How long a service needs to be running until restarting its process
-    // is no longer considered to be a relaunch of the service.
-    static final int SERVICE_RESTART_DURATION = 5*1000;
-
-    // How long a service needs to be running until it will start back at
-    // SERVICE_RESTART_DURATION after being killed.
-    static final int SERVICE_RESET_RUN_DURATION = 60*1000;
-
-    // Multiplying factor to increase restart duration time by, for each time
-    // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
-    static final int SERVICE_RESTART_DURATION_FACTOR = 4;
-    
-    // The minimum amount of time between restarting services that we allow.
-    // That is, when multiple services are restarting, we won't allow each
-    // to restart less than this amount of time from the last one.
-    static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
-
-    // Maximum amount of time for there to be no activity on a service before
-    // we consider it non-essential and allow its process to go on the
-    // LRU background list.
-    static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
-    
     // How long we wait until we timeout on key dispatching.
     static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
 
     // How long we wait until we timeout on key dispatching during instrumentation.
     static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
 
+    // Amount of time we wait for observers to handle a user switch before
+    // giving up on them and unfreezing the screen.
+    static final int USER_SWITCH_TIMEOUT = 2*1000;
+
+    // Maximum number of users we allow to be running at a time.
+    static final int MAX_RUNNING_USERS = 3;
+
     static final int MY_PID = Process.myPid();
     
     static final String[] EMPTY_STRING_ARRAY = new String[0];
@@ -454,6 +441,32 @@
     long mPreviousProcessVisibleTime;
 
     /**
+     * Which uses have been started, so are allowed to run code.
+     */
+    final SparseArray<UserStartedState> mStartedUsers = new SparseArray<UserStartedState>();
+
+    /**
+     * LRU list of history of current users.  Most recently current is at the end.
+     */
+    final ArrayList<Integer> mUserLru = new ArrayList<Integer>();
+
+    /**
+     * Constant array of the users that are currently started.
+     */
+    int[] mStartedUserArray = new int[] { 0 };
+
+    /**
+     * Registered observers of the user switching mechanics.
+     */
+    final RemoteCallbackList<IUserSwitchObserver> mUserSwitchObservers
+            = new RemoteCallbackList<IUserSwitchObserver>();
+
+    /**
+     * Currently active user switch.
+     */
+    Object mCurUserSwitchCallback;
+
+    /**
      * Packages that the user has asked to have run in screen size
      * compatibility mode instead of filling the screen.
      */
@@ -514,48 +527,36 @@
         }
 
         @Override
+        protected BroadcastFilter newResult(BroadcastFilter filter, int match, int userId) {
+            if (userId == UserHandle.USER_ALL || filter.owningUserId == UserHandle.USER_ALL
+                    || userId == filter.owningUserId) {
+                return super.newResult(filter, match, userId);
+            }
+            return null;
+        }
+
+        @Override
+        protected BroadcastFilter[] newArray(int size) {
+            return new BroadcastFilter[size];
+        }
+
+        @Override
         protected String packageForFilter(BroadcastFilter filter) {
             return filter.packageName;
         }
     };
 
     /**
-     * State of all active sticky broadcasts.  Keys are the action of the
+     * State of all active sticky broadcasts per user.  Keys are the action of the
      * sticky Intent, values are an ArrayList of all broadcasted intents with
-     * that action (which should usually be one).
+     * that action (which should usually be one).  The SparseArray is keyed
+     * by the user ID the sticky is for, and can include UserHandle.USER_ALL
+     * for stickies that are sent to all users.
      */
-    final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
-            new HashMap<String, ArrayList<Intent>>();
+    final SparseArray<HashMap<String, ArrayList<Intent>>> mStickyBroadcasts =
+            new SparseArray<HashMap<String, ArrayList<Intent>>>();
 
-    final ServiceMap mServiceMap = new ServiceMap();
-
-    /**
-     * All currently bound service connections.  Keys are the IBinder of
-     * the client's IServiceConnection.
-     */
-    final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
-            = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
-
-    /**
-     * List of services that we have been asked to start,
-     * but haven't yet been able to.  It is used to hold start requests
-     * while waiting for their corresponding application thread to get
-     * going.
-     */
-    final ArrayList<ServiceRecord> mPendingServices
-            = new ArrayList<ServiceRecord>();
-
-    /**
-     * List of services that are scheduled to restart following a crash.
-     */
-    final ArrayList<ServiceRecord> mRestartingServices
-            = new ArrayList<ServiceRecord>();
-
-    /**
-     * List of services that are in the process of being stopped.
-     */
-    final ArrayList<ServiceRecord> mStoppingServices
-            = new ArrayList<ServiceRecord>();
+    final ActiveServices mServices;
 
     /**
      * Backup/restore process management
@@ -575,7 +576,7 @@
      */
     final ArrayList mCancelledThumbnails = new ArrayList();
 
-    final ProviderMap mProviderMap = new ProviderMap();
+    final ProviderMap mProviderMap;
 
     /**
      * List of content providers who have clients waiting for them.  The
@@ -733,6 +734,18 @@
     int mLruSeq = 0;
 
     /**
+     * Keep track of the non-hidden/empty process we last found, to help
+     * determine how to distribute hidden/empty processes next time.
+     */
+    int mNumNonHiddenProcs = 0;
+
+    /**
+     * Keep track of the number of hidden procs, to balance oom adj
+     * distribution between those and empty procs.
+     */
+    int mNumHiddenProcs = 0;
+
+    /**
      * Keep track of the number of service processes we last found, to
      * determine on the next iteration which should be B services.
      */
@@ -827,6 +840,10 @@
     static ActivityManagerService mSelf;
     static ActivityThread mSystemThread;
 
+    private int mCurrentUserId = 0;
+    private int[] mCurrentUserArray = new int[] { 0 };
+    private UserManagerService mUserManager;
+
     private final class AppDeathRecipient implements IBinder.DeathRecipient {
         final ProcessRecord mApp;
         final int mPid;
@@ -876,6 +893,9 @@
     static final int DISPATCH_PROCESSES_CHANGED = 31;
     static final int DISPATCH_PROCESS_DIED = 32;
     static final int REPORT_MEM_USAGE = 33;
+    static final int REPORT_USER_SWITCH_MSG = 34;
+    static final int CONTINUE_USER_SWITCH_MSG = 35;
+    static final int USER_SWITCH_TIMEOUT_MSG = 36;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
     static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -894,21 +914,38 @@
             switch (msg.what) {
             case SHOW_ERROR_MSG: {
                 HashMap data = (HashMap) msg.obj;
+                boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
+                        Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
                 synchronized (ActivityManagerService.this) {
                     ProcessRecord proc = (ProcessRecord)data.get("app");
+                    AppErrorResult res = (AppErrorResult) data.get("result");
                     if (proc != null && proc.crashDialog != null) {
                         Slog.e(TAG, "App already has crash dialog: " + proc);
+                        if (res != null) {
+                            res.set(0);
+                        }
                         return;
                     }
-                    AppErrorResult res = (AppErrorResult) data.get("result");
+                    if (!showBackground && UserHandle.getAppId(proc.uid)
+                            >= Process.FIRST_APPLICATION_UID && proc.userId != mCurrentUserId
+                            && proc.pid != MY_PID) {
+                        Slog.w(TAG, "Skipping crash dialog of " + proc + ": background");
+                        if (res != null) {
+                            res.set(0);
+                        }
+                        return;
+                    }
                     if (mShowDialogs && !mSleeping && !mShuttingDown) {
-                        Dialog d = new AppErrorDialog(mContext, res, proc);
+                        Dialog d = new AppErrorDialog(mContext,
+                                ActivityManagerService.this, res, proc);
                         d.show();
                         proc.crashDialog = d;
                     } else {
                         // The device is asleep, so just pretend that the user
                         // saw a crash dialog and hit "force quit".
-                        res.set(0);
+                        if (res != null) {
+                            res.set(0);
+                        }
                     }
                 }
                 
@@ -934,7 +971,8 @@
 
                     if (mShowDialogs) {
                         Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
-                                mContext, proc, (ActivityRecord)data.get("activity"));
+                                mContext, proc, (ActivityRecord)data.get("activity"),
+                                msg.arg1 != 0);
                         d.show();
                         proc.anrDialog = d;
                     } else {
@@ -959,7 +997,8 @@
                     }
                     AppErrorResult res = (AppErrorResult) data.get("result");
                     if (mShowDialogs && !mSleeping && !mShuttingDown) {
-                        Dialog d = new StrictModeViolationDialog(mContext, res, proc);
+                        Dialog d = new StrictModeViolationDialog(mContext,
+                                ActivityManagerService.this, res, proc);
                         d.show();
                         proc.crashDialog = d;
                     } else {
@@ -1010,10 +1049,10 @@
                     mDidDexOpt = false;
                     Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
                     nmsg.obj = msg.obj;
-                    mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
+                    mHandler.sendMessageDelayed(nmsg, ActiveServices.SERVICE_TIMEOUT);
                     return;
                 }
-                serviceTimeout((ProcessRecord)msg.obj);
+                mServices.serviceTimeout((ProcessRecord)msg.obj);
             } break;
             case UPDATE_TIME_ZONE: {
                 synchronized (ActivityManagerService.this) {
@@ -1111,11 +1150,11 @@
             } break;
             case KILL_APPLICATION_MSG: {
                 synchronized (ActivityManagerService.this) {
-                    int uid = msg.arg1;
+                    int appid = msg.arg1;
                     boolean restart = (msg.arg2 == 1);
                     String pkg = (String) msg.obj;
-                    forceStopPackageLocked(pkg, uid, restart, false, true, false,
-                            UserId.getUserId(uid));
+                    forceStopPackageLocked(pkg, appid, restart, false, true, false,
+                            UserHandle.USER_ALL);
                 }
             } break;
             case FINALIZE_PENDING_INTENT_MSG: {
@@ -1147,13 +1186,15 @@
                     notification.vibrate = null;
                     notification.setLatestEventInfo(context, text,
                             mContext.getText(R.string.heavy_weight_notification_detail),
-                            PendingIntent.getActivity(mContext, 0, root.intent,
-                                    PendingIntent.FLAG_CANCEL_CURRENT));
+                            PendingIntent.getActivityAsUser(mContext, 0, root.intent,
+                                    PendingIntent.FLAG_CANCEL_CURRENT, null,
+                                    new UserHandle(root.userId)));
                     
                     try {
                         int[] outId = new int[1];
-                        inm.enqueueNotification("android", R.string.heavy_weight_notification,
-                                notification, outId);
+                        inm.enqueueNotificationWithTag("android", null,
+                                R.string.heavy_weight_notification,
+                                notification, outId, root.userId);
                     } catch (RuntimeException e) {
                         Slog.w(ActivityManagerService.TAG,
                                 "Error showing notification for heavy-weight app", e);
@@ -1169,8 +1210,8 @@
                     return;
                 }
                 try {
-                    inm.cancelNotification("android",
-                            R.string.heavy_weight_notification);
+                    inm.cancelNotificationWithTag("android", null,
+                            R.string.heavy_weight_notification,  msg.arg1);
                 } catch (RuntimeException e) {
                     Slog.w(ActivityManagerService.TAG,
                             "Error canceling notification for service", e);
@@ -1284,7 +1325,8 @@
                             catPw.println();
                             dumpProcessesLocked(null, catPw, emptyArgs, 0, false, null);
                             catPw.println();
-                            dumpServicesLocked(null, catPw, emptyArgs, 0, false, false, null);
+                            mServices.dumpServicesLocked(null, catPw, emptyArgs, 0,
+                                    false, false, null);
                             catPw.println();
                             dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null);
                         }
@@ -1303,6 +1345,18 @@
                 thread.start();
                 break;
             }
+            case REPORT_USER_SWITCH_MSG: {
+                dispatchUserSwitch((UserStartedState)msg.obj, msg.arg1, msg.arg2);
+                break;
+            }
+            case CONTINUE_USER_SWITCH_MSG: {
+                continueUserSwitch((UserStartedState)msg.obj, msg.arg1, msg.arg2);
+                break;
+            }
+            case USER_SWITCH_TIMEOUT_MSG: {
+                timeoutUserSwitch((UserStartedState)msg.obj, msg.arg1, msg.arg2);
+                break;
+            }
             }
         }
     };
@@ -1336,7 +1390,7 @@
                 synchronized (mSelf.mPidsSelfLocked) {
                     mSelf.mPidsSelfLocked.put(app.pid, app);
                 }
-                mSelf.updateLruProcessLocked(app, true, true);
+                mSelf.updateLruProcessLocked(app, true);
             }
         } catch (PackageManager.NameNotFoundException e) {
             throw new RuntimeException(
@@ -1521,6 +1575,9 @@
         mBroadcastQueues[0] = mFgBroadcastQueue;
         mBroadcastQueues[1] = mBgBroadcastQueue;
 
+        mServices = new ActiveServices(this);
+        mProviderMap = new ProviderMap(this);
+
         File dataDir = Environment.getDataDirectory();
         File systemDir = new File(dataDir, "system");
         systemDir.mkdirs();
@@ -1536,11 +1593,17 @@
                 systemDir, "usagestats").toString());
         mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
 
+        // User 0 is the first and only user that runs at boot.
+        mStartedUsers.put(0, new UserStartedState(new UserHandle(0), true));
+        mUserLru.add(Integer.valueOf(0));
+        updateStartedUserArrayLocked();
+
         GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
             ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
 
         mConfiguration.setToDefaults();
-        mConfiguration.locale = Locale.getDefault();
+        mConfiguration.setLocale(Locale.getDefault());
+
         mConfigurationSeq = mConfiguration.seq = 1;
         mProcessStats.init();
         
@@ -1763,8 +1826,7 @@
         }
     }
 
-    private final void updateLruProcessInternalLocked(ProcessRecord app,
-            boolean oomAdj, boolean updateActivityTime, int bestPos) {
+    private final void updateLruProcessInternalLocked(ProcessRecord app, int bestPos) {
         // put it on the LRU to keep track of when it should be exited.
         int lrui = mLruProcesses.indexOf(app);
         if (lrui >= 0) mLruProcesses.remove(lrui);
@@ -1775,9 +1837,7 @@
         app.lruSeq = mLruSeq;
         
         // compute the new weight for this process.
-        if (updateActivityTime) {
-            app.lastActivityTime = SystemClock.uptimeMillis();
-        }
+        app.lastActivityTime = SystemClock.uptimeMillis();
         if (app.activities.size() > 0) {
             // If this process has activities, we more strongly want to keep
             // it around.
@@ -1796,7 +1856,7 @@
             // Also don't let it kick out the first few "real" hidden processes.
             skipTop = ProcessList.MIN_HIDDEN_APPS;
         }
-        
+
         while (i >= 0) {
             ProcessRecord p = mLruProcesses.get(i);
             // If this app shouldn't be in front of the first N background
@@ -1821,29 +1881,27 @@
                 if (cr.binding != null && cr.binding.service != null
                         && cr.binding.service.app != null
                         && cr.binding.service.app.lruSeq != mLruSeq) {
-                    updateLruProcessInternalLocked(cr.binding.service.app, false,
-                            updateActivityTime, i+1);
+                    updateLruProcessInternalLocked(cr.binding.service.app, i+1);
                 }
             }
         }
         for (int j=app.conProviders.size()-1; j>=0; j--) {
             ContentProviderRecord cpr = app.conProviders.get(j).provider;
             if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq) {
-                updateLruProcessInternalLocked(cpr.proc, false,
-                        updateActivityTime, i+1);
+                updateLruProcessInternalLocked(cpr.proc, i+1);
             }
         }
-        
-        //Slog.i(TAG, "Putting proc to front: " + app.processName);
-        if (oomAdj) {
-            updateOomAdjLocked();
-        }
     }
 
     final void updateLruProcessLocked(ProcessRecord app,
-            boolean oomAdj, boolean updateActivityTime) {
+            boolean oomAdj) {
         mLruSeq++;
-        updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
+        updateLruProcessInternalLocked(app, 0);
+
+        //Slog.i(TAG, "Putting proc to front: " + app.processName);
+        if (oomAdj) {
+            updateOomAdjLocked();
+        }
     }
 
     final ProcessRecord getProcessRecordLocked(
@@ -1857,7 +1915,7 @@
             if (procs == null) return null;
             final int N = procs.size();
             for (int i = 0; i < N; i++) {
-                if (UserId.isSameUser(procs.keyAt(i), uid)) return procs.valueAt(i);
+                if (UserHandle.isSameUser(procs.keyAt(i), uid)) return procs.valueAt(i);
             }
         }
         ProcessRecord proc = mProcessNames.get(processName, uid);
@@ -1913,7 +1971,7 @@
             } else {
                 // An application record is attached to a previous process,
                 // clean it up now.
-                if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
+                if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG, "App died: " + app);
                 handleAppDiedLocked(app, true, true);
             }
         }
@@ -1939,7 +1997,8 @@
                         + "/" + info.processName);
                 mProcessCrashTimes.remove(info.processName, info.uid);
                 if (mBadProcesses.get(info.processName, info.uid) != null) {
-                    EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
+                    EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
+                            UserHandle.getUserId(info.uid), info.uid,
                             info.processName);
                     mBadProcesses.remove(info.processName, info.uid);
                     if (app != null) {
@@ -1992,7 +2051,7 @@
                 mPidsSelfLocked.remove(app.pid);
                 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
             }
-            app.pid = 0;
+            app.setPid(0);
         }
 
         if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
@@ -2008,13 +2067,37 @@
             int uid = app.uid;
 
             int[] gids = null;
+            int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
             if (!app.isolated) {
+                int[] permGids = null;
                 try {
-                    gids = mContext.getPackageManager().getPackageGids(
-                            app.info.packageName);
+                    final PackageManager pm = mContext.getPackageManager();
+                    permGids = pm.getPackageGids(app.info.packageName);
+
+                    if (Environment.isExternalStorageEmulated()) {
+                        if (pm.checkPermission(
+                                android.Manifest.permission.ACCESS_ALL_EXTERNAL_STORAGE,
+                                app.info.packageName) == PERMISSION_GRANTED) {
+                            mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
+                        } else {
+                            mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
+                        }
+                    }
                 } catch (PackageManager.NameNotFoundException e) {
                     Slog.w(TAG, "Unable to retrieve gids", e);
                 }
+
+                /*
+                 * Add shared application GID so applications can share some
+                 * resources like shared libraries
+                 */
+                if (permGids == null) {
+                    gids = new int[1];
+                } else {
+                    gids = new int[permGids.length + 1];
+                    System.arraycopy(permGids, 0, gids, 1, permGids.length);
+                }
+                gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
             }
             if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
                 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
@@ -2053,7 +2136,7 @@
             // Start the process.  It will either succeed and return a result containing
             // the PID of the new process, or else throw a RuntimeException.
             Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
-                    app.processName, uid, uid, gids, debugFlags,
+                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                     app.info.targetSdkVersion, null, null);
 
             BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
@@ -2063,7 +2146,8 @@
                 }
             }
             
-            EventLog.writeEvent(EventLogTags.AM_PROC_START, startResult.pid, uid,
+            EventLog.writeEvent(EventLogTags.AM_PROC_START,
+                    UserHandle.getUserId(uid), startResult.pid, uid,
                     app.processName, hostingType,
                     hostingNameStr != null ? hostingNameStr : "");
             
@@ -2095,7 +2179,7 @@
             }
             buf.append("}");
             Slog.i(TAG, buf.toString());
-            app.pid = startResult.pid;
+            app.setPid(startResult.pid);
             app.usingWrapper = startResult.usingWrapper;
             app.removed = false;
             synchronized (mPidsSelfLocked) {
@@ -2107,7 +2191,7 @@
             }
         } catch (RuntimeException e) {
             // XXX do better error recovery.
-            app.pid = 0;
+            app.setPid(0);
             Slog.e(TAG, "Failure starting process " + app.processName, e);
         }
     }
@@ -2143,8 +2227,7 @@
             intent.addCategory(Intent.CATEGORY_HOME);
         }
         ActivityInfo aInfo =
-            intent.resolveActivityInfo(mContext.getPackageManager(),
-                    STOCK_PM_FLAGS);
+            resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
         if (aInfo != null) {
             intent.setComponent(new ComponentName(
                     aInfo.applicationInfo.packageName, aInfo.name));
@@ -2164,6 +2247,29 @@
         return true;
     }
 
+    private ActivityInfo resolveActivityInfo(Intent intent, int flags, int userId) {
+        ActivityInfo ai = null;
+        ComponentName comp = intent.getComponent();
+        try {
+            if (comp != null) {
+                ai = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
+            } else {
+                ResolveInfo info = AppGlobals.getPackageManager().resolveIntent(
+                        intent,
+                        intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                            flags, userId);
+    
+                if (info != null) {
+                    ai = info.activityInfo;
+                }
+            }
+        } catch (RemoteException e) {
+            // ignore
+        }
+
+        return ai;
+    }
+
     /**
      * Starts the "new version setup screen" if appropriate.
      */
@@ -2178,8 +2284,8 @@
         // low-level factory test mode.
         final ContentResolver resolver = mContext.getContentResolver();
         if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
-                Settings.Secure.getInt(resolver,
-                        Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
+                Settings.Global.getInt(resolver,
+                        Settings.Global.DEVICE_PROVISIONED, 0) != 0) {
             mCheckedForSetup = true;
             
             // See if we should be showing the platform update setup UI.
@@ -2223,7 +2329,7 @@
     }
 
     void enforceNotIsolatedCaller(String caller) {
-        if (UserId.isIsolated(Binder.getCallingUid())) {
+        if (UserHandle.isIsolated(Binder.getCallingUid())) {
             throw new SecurityException("Isolated process not allowed to call " + caller);
         }
     }
@@ -2351,21 +2457,17 @@
             Intent intent, String resolvedType, IBinder resultTo,
             String resultWho, int requestCode, int startFlags,
             String profileFile, ParcelFileDescriptor profileFd, Bundle options) {
+        return startActivityAsUser(caller, intent, resolvedType, resultTo, resultWho, requestCode,
+                startFlags, profileFile, profileFd, options, UserHandle.getCallingUserId());
+    }
+
+    public final int startActivityAsUser(IApplicationThread caller,
+            Intent intent, String resolvedType, IBinder resultTo,
+            String resultWho, int requestCode, int startFlags,
+            String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {
         enforceNotIsolatedCaller("startActivity");
-        int userId = 0;
-        if (intent.getCategories() != null && intent.getCategories().contains(Intent.CATEGORY_HOME)) {
-            // Requesting home, set the identity to the current user
-            // HACK!
-            userId = mCurrentUserId;
-        } else {
-            // TODO: Fix this in a better way - calls coming from SystemUI should probably carry
-            // the current user's userId
-            if (Binder.getCallingUid() < Process.FIRST_APPLICATION_UID) {
-                userId = 0;
-            } else {
-                userId = Binder.getOrigCallingUser();
-            }
-        }
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                false, true, "startActivity", null);
         return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
                 resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
                 null, null, options, userId);
@@ -2374,24 +2476,27 @@
     public final WaitResult startActivityAndWait(IApplicationThread caller,
             Intent intent, String resolvedType, IBinder resultTo,
             String resultWho, int requestCode, int startFlags, String profileFile,
-            ParcelFileDescriptor profileFd, Bundle options) {
+            ParcelFileDescriptor profileFd, Bundle options, int userId) {
         enforceNotIsolatedCaller("startActivityAndWait");
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                false, true, "startActivityAndWait", null);
         WaitResult res = new WaitResult();
-        int userId = Binder.getOrigCallingUser();
         mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
                 resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
-                res, null, options, userId);
+                res, null, options, UserHandle.getCallingUserId());
         return res;
     }
 
     public final int startActivityWithConfig(IApplicationThread caller,
             Intent intent, String resolvedType, IBinder resultTo,
             String resultWho, int requestCode, int startFlags, Configuration config,
-            Bundle options) {
+            Bundle options, int userId) {
         enforceNotIsolatedCaller("startActivityWithConfig");
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                false, true, "startActivityWithConfig", null);
         int ret = mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
                 resultTo, resultWho, requestCode, startFlags,
-                null, null, null, config, options, Binder.getOrigCallingUser());
+                null, null, null, config, options, userId);
         return ret;
     }
 
@@ -2456,7 +2561,7 @@
                     AppGlobals.getPackageManager().queryIntentActivities(
                             intent, r.resolvedType,
                             PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS,
-                            UserId.getCallingUserId());
+                            UserHandle.getCallingUserId());
 
                 // Look for the original activity in the list...
                 final int N = resolves != null ? resolves.size() : 0;
@@ -2522,18 +2627,12 @@
         }
     }
 
-    public final int startActivityInPackage(int uid,
+    final int startActivityInPackage(int uid,
             Intent intent, String resolvedType, IBinder resultTo,
-            String resultWho, int requestCode, int startFlags, Bundle options) {
-        
-        // This is so super not safe, that only the system (or okay root)
-        // can do it.
-        int userId = Binder.getOrigCallingUser();
-        final int callingUid = Binder.getCallingUid();
-        if (callingUid != 0 && callingUid != Process.myUid()) {
-            throw new SecurityException(
-                    "startActivityInPackage only available to the system");
-        }
+            String resultWho, int requestCode, int startFlags, Bundle options, int userId) {
+
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                false, true, "startActivityInPackage", null);
 
         int ret = mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
                 resultTo, resultWho, requestCode, startFlags,
@@ -2542,26 +2641,24 @@
     }
 
     public final int startActivities(IApplicationThread caller,
-            Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle options) {
+            Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle options,
+            int userId) {
         enforceNotIsolatedCaller("startActivities");
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                false, true, "startActivity", null);
         int ret = mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo,
-                options, Binder.getOrigCallingUser());
+                options, userId);
         return ret;
     }
 
-    public final int startActivitiesInPackage(int uid,
+    final int startActivitiesInPackage(int uid,
             Intent[] intents, String[] resolvedTypes, IBinder resultTo,
-            Bundle options) {
+            Bundle options, int userId) {
 
-        // This is so super not safe, that only the system (or okay root)
-        // can do it.
-        final int callingUid = Binder.getCallingUid();
-        if (callingUid != 0 && callingUid != Process.myUid()) {
-            throw new SecurityException(
-                    "startActivityInPackage only available to the system");
-        }
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                false, true, "startActivityInPackage", null);
         int ret = mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo,
-                options, UserId.getUserId(uid));
+                options, userId);
         return ret;
     }
 
@@ -2660,7 +2757,7 @@
             }
             final long origId = Binder.clearCallingIdentity();
             boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
-                    resultData, "app-request");
+                    resultData, "app-request", true);
             Binder.restoreCallingIdentity(origId);
             return res;
         }
@@ -2690,13 +2787,14 @@
                     int index = mMainStack.indexOfTokenLocked(r.appToken);
                     if (index >= 0) {
                         mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
-                                null, "finish-heavy");
+                                null, "finish-heavy", true);
                     }
                 }
             }
             
+            mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
+                    mHeavyWeightProcess.userId, 0));
             mHeavyWeightProcess = null;
-            mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
         }
     }
     
@@ -2830,7 +2928,8 @@
 
         // Just in case...
         if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
-            if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
+            if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG,
+                    "App died while pausing: " + mMainStack.mPausingActivity);
             mMainStack.mPausingActivity = null;
         }
         if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
@@ -2838,61 +2937,7 @@
         }
 
         // Remove this application's activities from active lists.
-        mMainStack.removeHistoryRecordsForAppLocked(app);
-
-        boolean atTop = true;
-        boolean hasVisibleActivities = false;
-
-        // Clean out the history list.
-        int i = mMainStack.mHistory.size();
-        if (localLOGV) Slog.v(
-            TAG, "Removing app " + app + " from history with " + i + " entries");
-        while (i > 0) {
-            i--;
-            ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
-            if (localLOGV) Slog.v(
-                TAG, "Record #" + i + " " + r + ": app=" + r.app);
-            if (r.app == app) {
-                if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
-                    if (ActivityStack.DEBUG_ADD_REMOVE) {
-                        RuntimeException here = new RuntimeException("here");
-                        here.fillInStackTrace();
-                        Slog.i(TAG, "Removing activity " + r + " from stack at " + i
-                                + ": haveState=" + r.haveState
-                                + " stateNotNeeded=" + r.stateNotNeeded
-                                + " finishing=" + r.finishing
-                                + " state=" + r.state, here);
-                    }
-                    if (!r.finishing) {
-                        Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
-                        EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
-                                System.identityHashCode(r),
-                                r.task.taskId, r.shortComponentName,
-                                "proc died without state saved");
-                    }
-                    mMainStack.removeActivityFromHistoryLocked(r);
-
-                } else {
-                    // We have the current state for this activity, so
-                    // it can be restarted later when needed.
-                    if (localLOGV) Slog.v(
-                        TAG, "Keeping entry, setting app to null");
-                    if (r.visible) {
-                        hasVisibleActivities = true;
-                    }
-                    r.app = null;
-                    r.nowVisible = false;
-                    if (!r.haveState) {
-                        if (ActivityStack.DEBUG_SAVED_STATE) Slog.i(TAG,
-                                "App died, clearing saved state of " + r);
-                        r.icicle = null;
-                    }
-                }
-
-                r.stack.cleanUpActivityLocked(r, true, true);
-            }
-            atTop = false;
-        }
+        boolean hasVisibleActivities = mMainStack.removeHistoryRecordsForAppLocked(app);
 
         app.activities.clear();
         
@@ -2957,8 +3002,8 @@
                 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
                         + ") has died.");
             }
-            EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
-            if (localLOGV) Slog.v(
+            EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName);
+            if (DEBUG_CLEANUP) Slog.v(
                 TAG, "Dying app: " + app + ", pid: " + pid
                 + ", thread: " + thread.asBinder());
             boolean doLowMem = app.instrumentationClass == null;
@@ -3006,7 +3051,7 @@
             // A new process has already been started.
             Slog.i(TAG, "Process " + app.processName + " (pid " + pid
                     + ") has died and restarted (pid " + app.pid + ").");
-            EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
+            EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName);
         } else if (DEBUG_PROCESSES) {
             Slog.d(TAG, "Received spurious death notification for thread "
                     + thread.asBinder());
@@ -3204,7 +3249,7 @@
     }
 
     final void appNotResponding(ProcessRecord app, ActivityRecord activity,
-            ActivityRecord parent, final String annotation) {
+            ActivityRecord parent, boolean aboveSystem, final String annotation) {
         ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
         SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
 
@@ -3241,8 +3286,8 @@
             app.notResponding = true;
 
             // Log the ANR to the event log.
-            EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
-                    annotation);
+            EventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid,
+                    app.processName, app.info.flags, annotation);
 
             // Dump thread traces as quickly as we can, starting with "interesting" processes.
             firstPids.add(app.pid);
@@ -3328,7 +3373,7 @@
         synchronized (this) {
             if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
                 Slog.w(TAG, "Killing " + app + ": background ANR");
-                EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
+                EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
                         app.processName, app.setAdj, "background ANR");
                 Process.killProcessQuiet(app.pid);
                 return;
@@ -3345,6 +3390,7 @@
             HashMap map = new HashMap();
             msg.what = SHOW_NOT_RESPONDING_MSG;
             msg.obj = map;
+            msg.arg1 = aboveSystem ? 1 : 0;
             map.put("app", app);
             if (activity != null) {
                 map.put("activity", activity);
@@ -3379,10 +3425,12 @@
     }
     
     public boolean clearApplicationUserData(final String packageName,
-            final IPackageDataObserver observer, final int userId) {
+            final IPackageDataObserver observer, int userId) {
         enforceNotIsolatedCaller("clearApplicationUserData");
         int uid = Binder.getCallingUid();
         int pid = Binder.getCallingPid();
+        userId = handleIncomingUser(pid, uid,
+                userId, false, true, "clearApplicationUserData", null);
         long callingId = Binder.clearCallingIdentity();
         try {
             IPackageManager pm = AppGlobals.getPackageManager();
@@ -3424,7 +3472,7 @@
         return true;
     }
 
-    public void killBackgroundProcesses(final String packageName) {
+    public void killBackgroundProcesses(final String packageName, int userId) {
         if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
                 != PackageManager.PERMISSION_GRANTED &&
                 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
@@ -3436,22 +3484,23 @@
             Slog.w(TAG, msg);
             throw new SecurityException(msg);
         }
-        
-        int userId = UserId.getCallingUserId();
+
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+                userId, true, true, "killBackgroundProcesses", null);
         long callingId = Binder.clearCallingIdentity();
         try {
             IPackageManager pm = AppGlobals.getPackageManager();
-            int pkgUid = -1;
             synchronized(this) {
+                int appId = -1;
                 try {
-                    pkgUid = pm.getPackageUid(packageName, userId);
+                    appId = UserHandle.getAppId(pm.getPackageUid(packageName, 0));
                 } catch (RemoteException e) {
                 }
-                if (pkgUid == -1) {
+                if (appId == -1) {
                     Slog.w(TAG, "Invalid packageName: " + packageName);
                     return;
                 }
-                killPackageProcessesLocked(packageName, pkgUid,
+                killPackageProcessesLocked(packageName, appId, userId,
                         ProcessList.SERVICE_ADJ, false, true, true, false, "kill background");
             }
         } finally {
@@ -3501,7 +3550,7 @@
         }
     }
 
-    public void forceStopPackage(final String packageName) {
+    public void forceStopPackage(final String packageName, int userId) {
         if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
                 != PackageManager.PERMISSION_GRANTED) {
             String msg = "Permission Denial: forceStopPackage() from pid="
@@ -3511,27 +3560,34 @@
             Slog.w(TAG, msg);
             throw new SecurityException(msg);
         }
-        final int userId = UserId.getCallingUserId();
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+                userId, true, true, "forceStopPackage", null);
         long callingId = Binder.clearCallingIdentity();
         try {
             IPackageManager pm = AppGlobals.getPackageManager();
-            int pkgUid = -1;
             synchronized(this) {
-                try {
-                    pkgUid = pm.getPackageUid(packageName, userId);
-                } catch (RemoteException e) {
-                }
-                if (pkgUid == -1) {
-                    Slog.w(TAG, "Invalid packageName: " + packageName);
-                    return;
-                }
-                forceStopPackageLocked(packageName, pkgUid);
-                try {
-                    pm.setPackageStoppedState(packageName, true, userId);
-                } catch (RemoteException e) {
-                } catch (IllegalArgumentException e) {
-                    Slog.w(TAG, "Failed trying to unstop package "
-                            + packageName + ": " + e);
+                int[] users = userId == UserHandle.USER_ALL
+                        ? getUsersLocked() : new int[] { userId };
+                for (int user : users) {
+                    int pkgUid = -1;
+                    try {
+                        pkgUid = pm.getPackageUid(packageName, user);
+                    } catch (RemoteException e) {
+                    }
+                    if (pkgUid == -1) {
+                        Slog.w(TAG, "Invalid packageName: " + packageName);
+                        continue;
+                    }
+                    try {
+                        pm.setPackageStoppedState(packageName, true, user);
+                    } catch (RemoteException e) {
+                    } catch (IllegalArgumentException e) {
+                        Slog.w(TAG, "Failed trying to unstop package "
+                                + packageName + ": " + e);
+                    }
+                    if (isUserRunningLocked(user, false)) {
+                        forceStopPackageLocked(packageName, pkgUid);
+                    }
                 }
             }
         } finally {
@@ -3540,16 +3596,15 @@
     }
 
     /*
-     * The pkg name and uid have to be specified.
-     * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
+     * The pkg name and app id have to be specified.
      */
-    public void killApplicationWithUid(String pkg, int uid) {
+    public void killApplicationWithAppId(String pkg, int appid) {
         if (pkg == null) {
             return;
         }
         // Make sure the uid is valid.
-        if (uid < 0) {
-            Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
+        if (appid < 0) {
+            Slog.w(TAG, "Invalid appid specified for pkg : " + pkg);
             return;
         }
         int callerUid = Binder.getCallingUid();
@@ -3557,7 +3612,7 @@
         if (callerUid == Process.SYSTEM_UID) {
             // Post an aysnc message to kill the application
             Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
-            msg.arg1 = uid;
+            msg.arg1 = appid;
             msg.arg2 = 0;
             msg.obj = pkg;
             mHandler.sendMessage(msg);
@@ -3570,33 +3625,51 @@
     public void closeSystemDialogs(String reason) {
         enforceNotIsolatedCaller("closeSystemDialogs");
 
+        final int pid = Binder.getCallingPid();
         final int uid = Binder.getCallingUid();
         final long origId = Binder.clearCallingIdentity();
-        synchronized (this) {
-            closeSystemDialogsLocked(uid, reason);
+        try {
+            synchronized (this) {
+                // Only allow this from foreground processes, so that background
+                // applications can't abuse it to prevent system UI from being shown.
+                if (uid >= Process.FIRST_APPLICATION_UID) {
+                    ProcessRecord proc;
+                    synchronized (mPidsSelfLocked) {
+                        proc = mPidsSelfLocked.get(pid);
+                    }
+                    if (proc.curRawAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+                        Slog.w(TAG, "Ignoring closeSystemDialogs " + reason
+                                + " from background process " + proc);
+                        return;
+                    }
+                }
+                closeSystemDialogsLocked(reason);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
         }
-        Binder.restoreCallingIdentity(origId);
     }
 
-    void closeSystemDialogsLocked(int callingUid, String reason) {
+    void closeSystemDialogsLocked(String reason) {
         Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
-        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                | Intent.FLAG_RECEIVER_FOREGROUND);
         if (reason != null) {
             intent.putExtra("reason", reason);
         }
         mWindowManager.closeSystemDialogs(reason);
-        
+
         for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
             ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
             if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
                 r.stack.finishActivityLocked(r, i,
-                        Activity.RESULT_CANCELED, null, "close-sys");
+                        Activity.RESULT_CANCELED, null, "close-sys", true);
             }
         }
-        
+
         broadcastIntentLocked(null, null, intent, null,
                 null, 0, null, null, null, false, false, -1,
-                callingUid, 0 /* TODO: Verify */);
+                Process.SYSTEM_UID, UserHandle.USER_ALL);
     }
 
     public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
@@ -3647,28 +3720,43 @@
     }
 
     private void forceStopPackageLocked(final String packageName, int uid) {
-        forceStopPackageLocked(packageName, uid, false, false, true, false, UserId.getUserId(uid));
+        forceStopPackageLocked(packageName, UserHandle.getAppId(uid), false,
+                false, true, false, UserHandle.getUserId(uid));
         Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
                 Uri.fromParts("package", packageName, null));
         if (!mProcessesReady) {
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                    | Intent.FLAG_RECEIVER_FOREGROUND);
         }
         intent.putExtra(Intent.EXTRA_UID, uid);
+        intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(uid));
         broadcastIntentLocked(null, null, intent,
                 null, null, 0, null, null, null,
                 false, false,
-                MY_PID, Process.SYSTEM_UID, UserId.getUserId(uid));
+                MY_PID, Process.SYSTEM_UID, UserHandle.getUserId(uid));
     }
-    
-    private final boolean killPackageProcessesLocked(String packageName, int uid,
-            int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit,
-            boolean evenPersistent, String reason) {
+
+    private void forceStopUserLocked(int userId) {
+        forceStopPackageLocked(null, -1, false, false, true, false, userId);
+        Intent intent = new Intent(Intent.ACTION_USER_STOPPED);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                | Intent.FLAG_RECEIVER_FOREGROUND);
+        intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+        broadcastIntentLocked(null, null, intent,
+                null, null, 0, null, null, null,
+                false, false,
+                MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+    }
+
+    private final boolean killPackageProcessesLocked(String packageName, int appId,
+            int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
+            boolean doit, boolean evenPersistent, String reason) {
         ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
 
         // Remove all processes this package may have touched: all with the
         // same UID (except for the system or root user), and all whose name
         // matches the package name.
-        final String procNamePrefix = packageName + ":";
+        final String procNamePrefix = packageName != null ? (packageName + ":") : null;
         for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
             final int NA = apps.size();
             for (int ia=0; ia<NA; ia++) {
@@ -3681,20 +3769,41 @@
                     if (doit) {
                         procs.add(app);
                     }
-                // If uid is specified and the uid and process name match
-                // Or, the uid is not specified and the process name matches
-                } else if (((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
-                            || ((app.processName.equals(packageName)
-                                 || app.processName.startsWith(procNamePrefix))
-                                && uid < 0))) {
-                    if (app.setAdj >= minOomAdj) {
-                        if (!doit) {
-                            return true;
-                        }
-                        app.removed = true;
-                        procs.add(app);
+                    continue;
+                }
+
+                // Skip process if it doesn't meet our oom adj requirement.
+                if (app.setAdj < minOomAdj) {
+                    continue;
+                }
+
+                // If no package is specified, we call all processes under the
+                // give user id.
+                if (packageName == null) {
+                    if (app.userId != userId) {
+                        continue;
+                    }
+                // Package has been specified, we want to hit all processes
+                // that match it.  We need to qualify this by the processes
+                // that are running under the specified app and user ID.
+                } else {
+                    if (UserHandle.getAppId(app.uid) != appId) {
+                        continue;
+                    }
+                    if (userId != UserHandle.USER_ALL && app.userId != userId) {
+                        continue;
+                    }
+                    if (!app.pkgList.contains(packageName)) {
+                        continue;
                     }
                 }
+
+                // Process has passed all conditions, kill it!
+                if (!doit) {
+                    return true;
+                }
+                app.removed = true;
+                procs.add(app);
             }
         }
         
@@ -3705,39 +3814,71 @@
         return N > 0;
     }
 
-    private final boolean forceStopPackageLocked(String name, int uid,
+    private final boolean forceStopPackageLocked(String name, int appId,
             boolean callerWillRestart, boolean purgeCache, boolean doit,
             boolean evenPersistent, int userId) {
         int i;
         int N;
 
-        if (uid < 0) {
+        if (userId == UserHandle.USER_ALL && name == null) {
+            Slog.w(TAG, "Can't force stop all processes of all users, that is insane!");
+        }
+
+        if (appId < 0 && name != null) {
             try {
-                uid = AppGlobals.getPackageManager().getPackageUid(name, userId);
+                appId = UserHandle.getAppId(
+                        AppGlobals.getPackageManager().getPackageUid(name, 0));
             } catch (RemoteException e) {
             }
         }
 
         if (doit) {
-            Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
+            if (name != null) {
+                Slog.i(TAG, "Force stopping package " + name + " appid=" + appId
+                        + " user=" + userId);
+            } else {
+                Slog.i(TAG, "Force stopping user " + userId);
+            }
 
             Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
             while (badApps.hasNext()) {
                 SparseArray<Long> ba = badApps.next();
-                if (ba.get(uid) != null) {
+                for (i=ba.size()-1; i>=0; i--) {
+                    boolean remove = false;
+                    final int entUid = ba.keyAt(i);
+                    if (name != null) {
+                        if (userId == UserHandle.USER_ALL) {
+                            if (UserHandle.getAppId(entUid) == appId) {
+                                remove = true;
+                            }
+                        } else {
+                            if (entUid == UserHandle.getUid(userId, appId)) {
+                                remove = true;
+                            }
+                        }
+                    } else if (UserHandle.getUserId(entUid) == userId) {
+                        remove = true;
+                    }
+                    if (remove) {
+                        ba.removeAt(i);
+                    }
+                }
+                if (ba.size() == 0) {
                     badApps.remove();
                 }
             }
         }
-        
-        boolean didSomething = killPackageProcessesLocked(name, uid, -100,
-                callerWillRestart, false, doit, evenPersistent, "force stop");
+
+        boolean didSomething = killPackageProcessesLocked(name, appId, userId,
+                -100, callerWillRestart, false, doit, evenPersistent,
+                name == null ? ("force stop user " + userId) : ("force stop " + name));
         
         TaskRecord lastTask = null;
         for (i=0; i<mMainStack.mHistory.size(); i++) {
             ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
-            final boolean samePackage = r.packageName.equals(name);
-            if (r.userId == userId
+            final boolean samePackage = r.packageName.equals(name)
+                    || (name == null && r.userId == userId);
+            if ((userId == UserHandle.USER_ALL || r.userId == userId)
                     && (samePackage || r.task == lastTask)
                     && (r.app == null || evenPersistent || !r.app.persistent)) {
                 if (!doit) {
@@ -3764,48 +3905,85 @@
             }
         }
 
-        ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
-        for (ServiceRecord service : mServiceMap.getAllServices(userId)) {
-            if (service.packageName.equals(name)
-                    && (service.app == null || evenPersistent || !service.app.persistent)) {
-                if (!doit) {
-                    return true;
-                }
-                didSomething = true;
-                Slog.i(TAG, "  Force stopping service " + service);
-                if (service.app != null) {
-                    service.app.removed = true;
-                }
-                service.app = null;
-                service.isolatedProc = null;
-                services.add(service);
+        if (mServices.forceStopLocked(name, userId, evenPersistent, doit)) {
+            if (!doit) {
+                return true;
             }
+            didSomething = true;
         }
 
-        N = services.size();
-        for (i=0; i<N; i++) {
-            bringDownServiceLocked(services.get(i), true);
+        if (name == null) {
+            // Remove all sticky broadcasts from this user.
+            mStickyBroadcasts.remove(userId);
         }
 
         ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
-        for (ContentProviderRecord provider : mProviderMap.getProvidersByClass(userId).values()) {
-            if (provider.info.packageName.equals(name)
-                    && (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
-                if (!doit) {
-                    return true;
-                }
-                didSomething = true;
-                providers.add(provider);
+        if (mProviderMap.collectForceStopProviders(name, appId, doit, evenPersistent,
+                userId, providers)) {
+            if (!doit) {
+                return true;
             }
+            didSomething = true;
         }
-
         N = providers.size();
         for (i=0; i<N; i++) {
             removeDyingProviderLocked(null, providers.get(i), true);
         }
 
+        if (name == null) {
+            // Remove pending intents.  For now we only do this when force
+            // stopping users, because we have some problems when doing this
+            // for packages -- app widgets are not currently cleaned up for
+            // such packages, so they can be left with bad pending intents.
+            if (mIntentSenderRecords.size() > 0) {
+                Iterator<WeakReference<PendingIntentRecord>> it
+                        = mIntentSenderRecords.values().iterator();
+                while (it.hasNext()) {
+                    WeakReference<PendingIntentRecord> wpir = it.next();
+                    if (wpir == null) {
+                        it.remove();
+                        continue;
+                    }
+                    PendingIntentRecord pir = wpir.get();
+                    if (pir == null) {
+                        it.remove();
+                        continue;
+                    }
+                    if (name == null) {
+                        // Stopping user, remove all objects for the user.
+                        if (pir.key.userId != userId) {
+                            // Not the same user, skip it.
+                            continue;
+                        }
+                    } else {
+                        if (UserHandle.getAppId(pir.uid) != appId) {
+                            // Different app id, skip it.
+                            continue;
+                        }
+                        if (userId != UserHandle.USER_ALL && pir.key.userId != userId) {
+                            // Different user, skip it.
+                            continue;
+                        }
+                        if (!pir.key.packageName.equals(name)) {
+                            // Different package, skip it.
+                            continue;
+                        }
+                    }
+                    if (!doit) {
+                        return true;
+                    }
+                    didSomething = true;
+                    it.remove();
+                    pir.canceled = true;
+                    if (pir.key.activity != null) {
+                        pir.key.activity.pendingResults.remove(pir.ref);
+                    }
+                }
+            }
+        }
+
         if (doit) {
-            if (purgeCache) {
+            if (purgeCache && name != null) {
                 AttributeCache ac = AttributeCache.instance();
                 if (ac != null) {
                     ac.removePackage(name);
@@ -3831,8 +4009,9 @@
         mProcessNames.remove(name, uid);
         mIsolatedProcesses.remove(app.uid);
         if (mHeavyWeightProcess == app) {
+            mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
+                    mHeavyWeightProcess.userId, 0));
             mHeavyWeightProcess = null;
-            mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
         }
         boolean needRestart = false;
         if (app.pid > 0 && app.pid != MY_PID) {
@@ -3873,30 +4052,20 @@
         
         if (gone) {
             Slog.w(TAG, "Process " + app + " failed to attach");
-            EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.uid,
-                    app.processName);
+            EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, app.userId,
+                    pid, app.uid, app.processName);
             mProcessNames.remove(app.processName, app.uid);
             mIsolatedProcesses.remove(app.uid);
             if (mHeavyWeightProcess == app) {
+                mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
+                        mHeavyWeightProcess.userId, 0));
                 mHeavyWeightProcess = null;
-                mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
             }
             // Take care of any launching providers waiting for this process.
             checkAppInLaunchingProvidersLocked(app, true);
             // Take care of any services that are waiting for the process.
-            for (int i=0; i<mPendingServices.size(); i++) {
-                ServiceRecord sr = mPendingServices.get(i);
-                if ((app.uid == sr.appInfo.uid
-                        && app.processName.equals(sr.processName))
-                        || sr.isolatedProc == app) {
-                    Slog.w(TAG, "Forcing bringing down service: " + sr);
-                    sr.isolatedProc = null;
-                    mPendingServices.remove(i);
-                    i--;
-                    bringDownServiceLocked(sr, true);
-                }
-            }
-            EventLog.writeEvent(EventLogTags.AM_KILL, pid,
+            mServices.processStartTimedOutLocked(app);
+            EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, pid,
                     app.processName, app.setAdj, "start timeout");
             Process.killProcessQuiet(pid);
             if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
@@ -3972,7 +4141,7 @@
             return false;
         }
 
-        EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
+        EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);
         
         app.thread = thread;
         app.curAdj = app.setAdj = -100;
@@ -4050,7 +4219,7 @@
                     enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent,
                     new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
                     mCoreSettingsObserver.getCoreSettingsLocked());
-            updateLruProcessLocked(app, false, true);
+            updateLruProcessLocked(app, false);
             app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
         } catch (Exception e) {
             // todo: Yikes!  What should we do?  For now we will try to
@@ -4095,24 +4264,10 @@
         }
 
         // Find any services that should be running in this process...
-        if (!badApp && mPendingServices.size() > 0) {
-            ServiceRecord sr = null;
+        if (!badApp) {
             try {
-                for (int i=0; i<mPendingServices.size(); i++) {
-                    sr = mPendingServices.get(i);
-                    if (app != sr.isolatedProc && (app.uid != sr.appInfo.uid
-                            || !processName.equals(sr.processName))) {
-                        continue;
-                    }
-
-                    mPendingServices.remove(i);
-                    i--;
-                    realStartServiceLocked(sr, app);
-                    didSomething = true;
-                }
+                didSomething |= mServices.attachApplicationLocked(app, processName);
             } catch (Exception e) {
-                Slog.w(TAG, "Exception in new application when starting service "
-                      + sr.shortName, e);
                 badApp = true;
             }
         }
@@ -4235,15 +4390,6 @@
             }
         }, pkgFilter);
 
-        IntentFilter userFilter = new IntentFilter();
-        userFilter.addAction(Intent.ACTION_USER_REMOVED);
-        mContext.registerReceiver(new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                onUserRemoved(intent);
-            }
-        }, userFilter);
-
         synchronized (this) {
             // Ensure that any processes we had put on hold are now started
             // up.
@@ -4265,12 +4411,19 @@
                 // Tell anyone interested that we are done booting!
                 SystemProperties.set("sys.boot_completed", "1");
                 SystemProperties.set("dev.bootcomplete", "1");
-                /* TODO: Send this to all users that are to be logged in on startup */
-                broadcastIntentLocked(null, null,
-                        new Intent(Intent.ACTION_BOOT_COMPLETED, null),
-                        null, null, 0, null, null,
-                        android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
-                        false, false, MY_PID, Process.SYSTEM_UID, Binder.getOrigCallingUser());
+                for (int i=0; i<mStartedUsers.size(); i++) {
+                    UserStartedState uss = mStartedUsers.valueAt(i);
+                    if (uss.mState == UserStartedState.STATE_BOOTING) {
+                        uss.mState = UserStartedState.STATE_RUNNING;
+                        final int userId = mStartedUsers.keyAt(i);
+                        Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
+                        intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+                        broadcastIntentLocked(null, null, intent,
+                                null, null, 0, null, null,
+                                android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
+                                false, false, MY_PID, Process.SYSTEM_UID, userId);
+                    }
+                }
             }
         }
     }
@@ -4293,7 +4446,13 @@
             enableScreenAfterBoot();
         }
     }
-    
+
+    public final void activityResumed(IBinder token) {
+        final long origId = Binder.clearCallingIdentity();
+        mMainStack.activityResumed(token);
+        Binder.restoreCallingIdentity(origId);
+    }
+
     public final void activityPaused(IBinder token) {
         final long origId = Binder.clearCallingIdentity();
         mMainStack.activityPaused(token, false);
@@ -4380,7 +4539,7 @@
     public IIntentSender getIntentSender(int type,
             String packageName, IBinder token, String resultWho,
             int requestCode, Intent[] intents, String[] resolvedTypes,
-            int flags, Bundle options) {
+            int flags, Bundle options, int userId) {
         enforceNotIsolatedCaller("getIntentSender");
         // Refuse possible leaked file descriptors
         if (intents != null) {
@@ -4414,11 +4573,21 @@
         
         synchronized(this) {
             int callingUid = Binder.getCallingUid();
+            int origUserId = userId;
+            userId = handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
+                    type == ActivityManager.INTENT_SENDER_BROADCAST, false,
+                    "getIntentSender", null);
+            if (origUserId == UserHandle.USER_CURRENT) {
+                // We don't want to evaluate this until the pending intent is
+                // actually executed.  However, we do want to always do the
+                // security checking for it above.
+                userId = UserHandle.USER_CURRENT;
+            }
             try {
                 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
                     int uid = AppGlobals.getPackageManager()
-                            .getPackageUid(packageName, UserId.getUserId(callingUid));
-                    if (!UserId.isSameApp(callingUid, uid)) {
+                            .getPackageUid(packageName, UserHandle.getUserId(callingUid));
+                    if (!UserHandle.isSameApp(callingUid, uid)) {
                         String msg = "Permission Denial: getIntentSender() from pid="
                             + Binder.getCallingPid()
                             + ", uid=" + Binder.getCallingUid()
@@ -4428,11 +4597,8 @@
                         throw new SecurityException(msg);
                     }
                 }
-                
-                if (DEBUG_MU)
-                    Slog.i(TAG_MU, "Getting intent sender for origCallingUid="
-                            + Binder.getOrigCallingUid());
-                return getIntentSenderLocked(type, packageName, Binder.getOrigCallingUid(),
+
+                return getIntentSenderLocked(type, packageName, callingUid, userId,
                         token, resultWho, requestCode, intents, resolvedTypes, flags, options);
                 
             } catch (RemoteException e) {
@@ -4441,8 +4607,8 @@
         }
     }
     
-    IIntentSender getIntentSenderLocked(int type,
-            String packageName, int callingUid, IBinder token, String resultWho,
+    IIntentSender getIntentSenderLocked(int type, String packageName,
+            int callingUid, int userId, IBinder token, String resultWho,
             int requestCode, Intent[] intents, String[] resolvedTypes, int flags,
             Bundle options) {
         if (DEBUG_MU)
@@ -4466,7 +4632,7 @@
 
         PendingIntentRecord.Key key = new PendingIntentRecord.Key(
                 type, packageName, activity, resultWho,
-                requestCode, intents, resolvedTypes, flags, options);
+                requestCode, intents, resolvedTypes, flags, options, userId);
         WeakReference<PendingIntentRecord> ref;
         ref = mIntentSenderRecords.get(key);
         PendingIntentRecord rec = ref != null ? ref.get() : null;
@@ -4514,8 +4680,8 @@
             PendingIntentRecord rec = (PendingIntentRecord)sender;
             try {
                 int uid = AppGlobals.getPackageManager()
-                        .getPackageUid(rec.key.packageName, UserId.getCallingUserId());
-                if (!UserId.isSameApp(uid, Binder.getCallingUid())) {
+                        .getPackageUid(rec.key.packageName, UserHandle.getCallingUserId());
+                if (!UserHandle.isSameApp(uid, Binder.getCallingUid())) {
                     String msg = "Permission Denial: cancelIntentSender() from pid="
                         + Binder.getCallingPid()
                         + ", uid=" + Binder.getCallingUid()
@@ -4734,7 +4900,7 @@
         if (permission == null) {
             return PackageManager.PERMISSION_DENIED;
         }
-        return checkComponentPermission(permission, pid, UserId.getAppId(uid), -1, true);
+        return checkComponentPermission(permission, pid, UserHandle.getAppId(uid), -1, true);
     }
 
     /**
@@ -4744,7 +4910,7 @@
     int checkCallingPermission(String permission) {
         return checkPermission(permission,
                 Binder.getCallingPid(),
-                UserId.getAppId(Binder.getCallingUid()));
+                UserHandle.getAppId(Binder.getCallingUid()));
     }
 
     /**
@@ -4875,7 +5041,6 @@
             pid = tlsIdentity.pid;
         }
 
-        uid = UserId.getAppId(uid);
         // Our own process gets to do everything.
         if (pid == MY_PID) {
             return PackageManager.PERMISSION_GRANTED;
@@ -4921,13 +5086,14 @@
         String name = uri.getAuthority();
         ProviderInfo pi = null;
         ContentProviderRecord cpr = mProviderMap.getProviderByName(name,
-                UserId.getUserId(callingUid));
+                UserHandle.getUserId(callingUid));
         if (cpr != null) {
             pi = cpr.info;
         } else {
             try {
                 pi = pm.resolveContentProvider(name,
-                        PackageManager.GET_URI_PERMISSION_PATTERNS, UserId.getUserId(callingUid));
+                        PackageManager.GET_URI_PERMISSION_PATTERNS,
+                        UserHandle.getUserId(callingUid));
             } catch (RemoteException ex) {
             }
         }
@@ -4939,7 +5105,7 @@
         int targetUid = lastTargetUid;
         if (targetUid < 0 && targetPkg != null) {
             try {
-                targetUid = pm.getPackageUid(targetPkg, UserId.getUserId(callingUid));
+                targetUid = pm.getPackageUid(targetPkg, UserHandle.getUserId(callingUid));
                 if (targetUid < 0) {
                     if (DEBUG_URI_PERMISSION) Slog.v(TAG,
                             "Can't grant URI permission no uid for: " + targetPkg);
@@ -5231,7 +5397,7 @@
 
         final String authority = uri.getAuthority();
         ProviderInfo pi = null;
-        int userId = UserId.getUserId(callingUid);
+        int userId = UserHandle.getUserId(callingUid);
         ContentProviderRecord cpr = mProviderMap.getProviderByName(authority, userId);
         if (cpr != null) {
             pi = cpr.info;
@@ -5567,13 +5733,10 @@
     }
 
     public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
-            int flags) {
-        final int callingUid = Binder.getCallingUid();
-        // If it's the system uid asking, then use the current user id.
-        // TODO: Make sure that there aren't any other legitimate calls from the system uid that
-        // require the entire list.
-        final int callingUserId = callingUid == Process.SYSTEM_UID
-                ? mCurrentUserId : UserId.getUserId(callingUid);
+            int flags, int userId) {
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                false, true, "getRecentTasks", null);
+
         synchronized (this) {
             enforceCallingPermission(android.Manifest.permission.GET_TASKS,
                     "getRecentTasks()");
@@ -5582,7 +5745,7 @@
                     == PackageManager.PERMISSION_GRANTED;
 
             IPackageManager pm = AppGlobals.getPackageManager();
-            
+
             final int N = mRecentTasks.size();
             ArrayList<ActivityManager.RecentTaskInfo> res
                     = new ArrayList<ActivityManager.RecentTaskInfo>(
@@ -5590,7 +5753,7 @@
             for (int i=0; i<N && maxNum > 0; i++) {
                 TaskRecord tr = mRecentTasks.get(i);
                 // Only add calling user's recent tasks
-                if (tr.userId != callingUserId) continue;
+                if (tr.userId != userId) continue;
                 // Return the entry if desired by the caller.  We always return
                 // the first entry, because callers always expect this to be the
                 // foreground app.  We may filter others if the caller has
@@ -5618,13 +5781,13 @@
                         // Check whether this activity is currently available.
                         try {
                             if (rti.origActivity != null) {
-                                if (pm.getActivityInfo(rti.origActivity, 0, callingUserId)
+                                if (pm.getActivityInfo(rti.origActivity, 0, userId)
                                         == null) {
                                     continue;
                                 }
                             } else if (rti.baseIntent != null) {
                                 if (pm.queryIntentActivities(rti.baseIntent,
-                                        null, 0, callingUserId) == null) {
+                                        null, 0, userId) == null) {
                                     continue;
                                 }
                             }
@@ -5664,6 +5827,18 @@
         return null;
     }
 
+    public Bitmap getTaskTopThumbnail(int id) {
+        synchronized (this) {
+            enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
+                    "getTaskTopThumbnail()");
+            TaskRecord tr = taskForIdLocked(id);
+            if (tr != null) {
+                return mMainStack.getTaskTopThumbnailLocked(tr);
+            }
+        }
+        return null;
+    }
+
     public boolean removeSubTask(int taskId, int subTaskIndex) {
         synchronized (this) {
             enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
@@ -5689,29 +5864,7 @@
         }
 
         // Find any running services associated with this app.
-        ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
-        for (ServiceRecord sr : mServiceMap.getAllServices(tr.userId)) {
-            if (sr.packageName.equals(component.getPackageName())) {
-                services.add(sr);
-            }
-        }
-
-        // Take care of any running services associated with the app.
-        for (int i=0; i<services.size(); i++) {
-            ServiceRecord sr = services.get(i);
-            if (sr.startRequested) {
-                if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
-                    Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
-                    stopServiceLocked(sr);
-                } else {
-                    sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
-                            sr.makeNextStartId(), baseIntent, null));
-                    if (sr.app != null && sr.app.thread != null) {
-                        sendServiceArgsLocked(sr, false);
-                    }
-                }
-            }
-        }
+        mServices.cleanUpRemovedTaskLocked(tr, component, baseIntent);
 
         if (killProcesses) {
             // Find any running processes associated with this app.
@@ -5736,7 +5889,7 @@
                 ProcessRecord pr = procs.get(i);
                 if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
                     Slog.i(TAG, "Killing " + pr.toShortString() + ": remove task");
-                    EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
+                    EventLog.writeEvent(EventLogTags.AM_KILL, pr.userId, pr.pid,
                             pr.processName, pr.setAdj, "remove task");
                     pr.killedBackground = true;
                     Process.killProcessQuiet(pr.pid);
@@ -6055,15 +6208,26 @@
             Slog.v(TAG_MU, "generateApplicationProvidersLocked, app.info.uid = " + app.uid);
         int userId = app.userId;
         if (providers != null) {
-            final int N = providers.size();
+            int N = providers.size();
             for (int i=0; i<N; i++) {
                 ProviderInfo cpi =
                     (ProviderInfo)providers.get(i);
+                boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo,
+                        cpi.name, cpi.flags);
+                if (singleton && UserHandle.getUserId(app.uid) != 0) {
+                    // This is a singleton provider, but a user besides the
+                    // default user is asking to initialize a process it runs
+                    // in...  well, no, it doesn't actually run in this process,
+                    // it runs in the process of the default user.  Get rid of it.
+                    providers.remove(i);
+                    N--;
+                    continue;
+                }
 
                 ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
                 ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId);
                 if (cpr == null) {
-                    cpr = new ContentProviderRecord(this, cpi, app.info, comp);
+                    cpr = new ContentProviderRecord(this, cpi, app.info, comp, singleton);
                     mProviderMap.putProviderByClass(comp, cpr);
                 }
                 if (DEBUG_MU)
@@ -6203,7 +6367,7 @@
     }
 
     private final ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
-            String name, IBinder token, boolean stable) {
+            String name, IBinder token, boolean stable, int userId) {
         ContentProviderRecord cpr;
         ContentProviderConnection conn = null;
         ProviderInfo cpi = null;
@@ -6221,7 +6385,6 @@
             }
 
             // First check if this content provider has been published...
-            int userId = UserId.getUserId(r != null ? r.uid : Binder.getCallingUid());
             cpr = mProviderMap.getProviderByName(name, userId);
             boolean providerRunning = cpr != null;
             if (providerRunning) {
@@ -6254,7 +6417,7 @@
                         // make sure to count it as being accessed and thus
                         // back up on the LRU list.  This is good because
                         // content providers are often expensive to start.
-                        updateLruProcessLocked(cpr.proc, false, true);
+                        updateLruProcessLocked(cpr.proc, false);
                     }
                 }
 
@@ -6296,6 +6459,7 @@
                 Binder.restoreCallingIdentity(origId);
             }
 
+            boolean singleton;
             if (!providerRunning) {
                 try {
                     cpi = AppGlobals.getPackageManager().
@@ -6306,7 +6470,9 @@
                 if (cpi == null) {
                     return null;
                 }
-                if (isSingleton(cpi.processName, cpi.applicationInfo)) {
+                singleton = isSingleton(cpi.processName, cpi.applicationInfo,
+                        cpi.name, cpi.flags); 
+                if (singleton) {
                     userId = 0;
                 }
                 cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId);
@@ -6325,6 +6491,16 @@
                             "Attempt to launch content provider before system ready");
                 }
 
+                // Make sure that the user who owns this provider is started.  If not,
+                // we don't want to allow it to run.
+                if (mStartedUsers.get(userId) == null) {
+                    Slog.w(TAG, "Unable to launch app "
+                            + cpi.applicationInfo.packageName + "/"
+                            + cpi.applicationInfo.uid + " for provider "
+                            + name + ": user " + userId + " is stopped");
+                    return null;
+                }
+
                 ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
                 cpr = mProviderMap.getProviderByClass(comp, userId);
                 final boolean firstClass = cpr == null;
@@ -6341,7 +6517,7 @@
                             return null;
                         }
                         ai = getAppInfoForUser(ai, userId);
-                        cpr = new ContentProviderRecord(this, cpi, ai, comp);
+                        cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton);
                     } catch (RemoteException ex) {
                         // pm is in same process, this will never happen.
                     }
@@ -6429,6 +6605,7 @@
                             + cpi.applicationInfo.uid + " for provider "
                             + name + ": launching app became null");
                     EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
+                            UserHandle.getUserId(cpi.applicationInfo.uid),
                             cpi.applicationInfo.packageName,
                             cpi.applicationInfo.uid, name);
                     return null;
@@ -6454,7 +6631,7 @@
     }
 
     public final ContentProviderHolder getContentProvider(
-            IApplicationThread caller, String name, boolean stable) {
+            IApplicationThread caller, String name, int userId, boolean stable) {
         enforceNotIsolatedCaller("getContentProvider");
         if (caller == null) {
             String msg = "null IApplicationThread when getting content provider "
@@ -6463,17 +6640,23 @@
             throw new SecurityException(msg);
         }
 
-        return getContentProviderImpl(caller, name, null, stable);
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                false, true, "getContentProvider", null);
+        return getContentProviderImpl(caller, name, null, stable, userId);
     }
 
-    public ContentProviderHolder getContentProviderExternal(String name, IBinder token) {
+    public ContentProviderHolder getContentProviderExternal(
+            String name, int userId, IBinder token) {
         enforceCallingPermission(android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
             "Do not have permission in call getContentProviderExternal()");
-        return getContentProviderExternalUnchecked(name, token);
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                false, true, "getContentProvider", null);
+        return getContentProviderExternalUnchecked(name, token, userId);
     }
 
-    private ContentProviderHolder getContentProviderExternalUnchecked(String name,IBinder token) {
-        return getContentProviderImpl(null, name, token, true);
+    private ContentProviderHolder getContentProviderExternalUnchecked(String name,
+            IBinder token, int userId) {
+        return getContentProviderImpl(null, name, token, true, userId);
     }
 
     /**
@@ -6504,13 +6687,12 @@
     public void removeContentProviderExternal(String name, IBinder token) {
         enforceCallingPermission(android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
             "Do not have permission in call removeContentProviderExternal()");
-        removeContentProviderExternalUnchecked(name, token);
+        removeContentProviderExternalUnchecked(name, token, UserHandle.getCallingUserId());
     }
 
-    private void removeContentProviderExternalUnchecked(String name, IBinder token) {
+    private void removeContentProviderExternalUnchecked(String name, IBinder token, int userId) {
         synchronized (this) {
-            ContentProviderRecord cpr = mProviderMap.getProviderByName(name,
-                    Binder.getOrigCallingUser());
+            ContentProviderRecord cpr = mProviderMap.getProviderByName(name, userId);
             if(cpr == null) {
                 //remove from mProvidersByClass
                 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
@@ -6519,8 +6701,7 @@
 
             //update content provider record entry info
             ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
-            ContentProviderRecord localCpr = mProviderMap.getProviderByClass(comp,
-                    Binder.getOrigCallingUser());
+            ContentProviderRecord localCpr = mProviderMap.getProviderByClass(comp, userId);
             if (localCpr.hasExternalProcessHandles()) {
                 if (localCpr.removeExternalProcessHandleLocked(token)) {
                     updateOomAdjLocked();
@@ -6731,14 +6912,16 @@
      * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
      *     src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
      */
-    public String getProviderMimeType(Uri uri) {
+    public String getProviderMimeType(Uri uri, int userId) {
         enforceNotIsolatedCaller("getProviderMimeType");
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+                userId, false, true, "getProviderMimeType", null);
         final String name = uri.getAuthority();
         final long ident = Binder.clearCallingIdentity();
         ContentProviderHolder holder = null;
 
         try {
-            holder = getContentProviderExternalUnchecked(name, null);
+            holder = getContentProviderExternalUnchecked(name, null, userId);
             if (holder != null) {
                 return holder.provider.getType(uri);
             }
@@ -6747,7 +6930,7 @@
             return null;
         } finally {
             if (holder != null) {
-                removeContentProviderExternalUnchecked(name, null);
+                removeContentProviderExternalUnchecked(name, null, userId);
             }
             Binder.restoreCallingIdentity(ident);
         }
@@ -6766,7 +6949,7 @@
         BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
         int uid = info.uid;
         if (isolated) {
-            int userId = UserId.getUserId(uid);
+            int userId = UserHandle.getUserId(uid);
             int stepsLeft = Process.LAST_ISOLATED_UID - Process.FIRST_ISOLATED_UID + 1;
             uid = 0;
             while (true) {
@@ -6774,7 +6957,7 @@
                         || mNextIsolatedProcessUid > Process.LAST_ISOLATED_UID) {
                     mNextIsolatedProcessUid = Process.FIRST_ISOLATED_UID;
                 }
-                uid = UserId.getUid(userId, mNextIsolatedProcessUid);
+                uid = UserHandle.getUid(userId, mNextIsolatedProcessUid);
                 mNextIsolatedProcessUid++;
                 if (mIsolatedProcesses.indexOfKey(uid) < 0) {
                     // No process for this uid, use it.
@@ -6806,13 +6989,13 @@
             if (isolated) {
                 mIsolatedProcesses.put(app.uid, app);
             }
-            updateLruProcessLocked(app, true, true);
+            updateLruProcessLocked(app, true);
         }
 
         // This package really, really can not be stopped.
         try {
             AppGlobals.getPackageManager().setPackageStoppedState(
-                    info.packageName, false, UserId.getUserId(app.uid));
+                    info.packageName, false, UserHandle.getUserId(app.uid));
         } catch (RemoteException e) {
         } catch (IllegalArgumentException e) {
             Slog.w(TAG, "Failed trying to unstop package "
@@ -6843,7 +7026,7 @@
             if (count > 1) {
                 final long origId = Binder.clearCallingIdentity();
                 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
-                        count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
+                        count-1, Activity.RESULT_CANCELED, null, "unhandled-back", true);
                 Binder.restoreCallingIdentity(origId);
             }
         }
@@ -6851,8 +7034,9 @@
 
     public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
         enforceNotIsolatedCaller("openContentUri");
+        final int userId = UserHandle.getCallingUserId();
         String name = uri.getAuthority();
-        ContentProviderHolder cph = getContentProviderExternalUnchecked(name, null);
+        ContentProviderHolder cph = getContentProviderExternalUnchecked(name, null, userId);
         ParcelFileDescriptor pfd = null;
         if (cph != null) {
             // We record the binder invoker's uid in thread-local storage before
@@ -6874,7 +7058,7 @@
             }
 
             // We've got the fd now, so we're done with the provider.
-            removeContentProviderExternalUnchecked(name, null);
+            removeContentProviderExternalUnchecked(name, null, userId);
         } else {
             Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
         }
@@ -7067,11 +7251,11 @@
         // care about.
         if (persistent) {
             final ContentResolver resolver = mContext.getContentResolver();
-            Settings.System.putString(
-                resolver, Settings.System.DEBUG_APP,
+            Settings.Global.putString(
+                resolver, Settings.Global.DEBUG_APP,
                 packageName);
-            Settings.System.putInt(
-                resolver, Settings.System.WAIT_FOR_DEBUGGER,
+            Settings.Global.putInt(
+                resolver, Settings.Global.WAIT_FOR_DEBUGGER,
                 waitForDebugger ? 1 : 0);
         }
 
@@ -7085,7 +7269,8 @@
             mDebugTransient = !persistent;
             if (packageName != null) {
                 final long origId = Binder.clearCallingIdentity();
-                forceStopPackageLocked(packageName, -1, false, false, true, true, 0);
+                forceStopPackageLocked(packageName, -1, false, false, true, true,
+                        UserHandle.USER_ALL);
                 Binder.restoreCallingIdentity(origId);
             }
         }
@@ -7132,9 +7317,9 @@
         enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
                 "setAlwaysFinish()");
 
-        Settings.System.putInt(
+        Settings.Global.putInt(
                 mContext.getContentResolver(),
-                Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
+                Settings.Global.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
         
         synchronized (this) {
             mAlwaysFinishActivities = enabled;
@@ -7156,7 +7341,59 @@
             return mController != null;
         }
     }
-    
+
+    public void requestBugReport() {
+        // No permission check because this can't do anything harmful --
+        // it will just eventually cause the user to be presented with
+        // a UI to select where the bug report goes.
+        SystemProperties.set("ctl.start", "bugreport");
+    }
+
+    public long inputDispatchingTimedOut(int pid, boolean aboveSystem) {
+        if (checkCallingPermission(android.Manifest.permission.FILTER_EVENTS)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Requires permission "
+                    + android.Manifest.permission.FILTER_EVENTS);
+        }
+
+        ProcessRecord proc;
+
+        // TODO: Unify this code with ActivityRecord.keyDispatchingTimedOut().
+        synchronized (this) {
+            synchronized (mPidsSelfLocked) {
+                proc = mPidsSelfLocked.get(pid);
+            }
+            if (proc != null) {
+                if (proc.debugging) {
+                    return -1;
+                }
+
+                if (mDidDexOpt) {
+                    // Give more time since we were dexopting.
+                    mDidDexOpt = false;
+                    return -1;
+                }
+
+                if (proc.instrumentationClass != null) {
+                    Bundle info = new Bundle();
+                    info.putString("shortMsg", "keyDispatchingTimedOut");
+                    info.putString("longMsg", "Timed out while dispatching key event");
+                    finishInstrumentationLocked(proc, Activity.RESULT_CANCELED, info);
+                    proc = null;
+                }
+            }
+        }
+
+        if (proc != null) {
+            appNotResponding(proc, null, null, aboveSystem, "keyDispatchingTimedOut");
+            if (proc.instrumentationClass != null || proc.usingWrapper) {
+                return INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT;
+            }
+        }
+
+        return KEY_DISPATCHING_TIMEOUT;
+    }
+
     public void registerProcessObserver(IProcessObserver observer) {
         enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
                 "registerProcessObserver()");
@@ -7219,10 +7456,11 @@
         lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
         lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
         lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
-        lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
+        lp.gravity = Gravity.BOTTOM | Gravity.START;
         lp.format = v.getBackground().getOpacity();
         lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
         ((WindowManager)mContext.getSystemService(
                 Context.WINDOW_SERVICE)).addView(v, lp);
     }
@@ -7290,7 +7528,7 @@
                 int adj = proc.setAdj;
                 if (adj >= worstType && !proc.killedBackground) {
                     Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
-                    EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
+                    EventLog.writeEvent(EventLogTags.AM_KILL, proc.userId, proc.pid,
                             proc.processName, adj, reason);
                     killed = true;
                     proc.killedBackground = true;
@@ -7326,8 +7564,8 @@
                 final int adj = proc.setAdj;
                 if (adj > belowAdj && !proc.killedBackground) {
                     Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
-                    EventLog.writeEvent(
-                            EventLogTags.AM_KILL, proc.pid, proc.processName, adj, reason);
+                    EventLog.writeEvent(EventLogTags.AM_KILL, proc.userId,
+                            proc.pid, proc.processName, adj, reason);
                     killed = true;
                     proc.killedBackground = true;
                     Process.killProcessQuiet(pid);
@@ -7358,12 +7596,12 @@
 
     private void retrieveSettings() {
         final ContentResolver resolver = mContext.getContentResolver();
-        String debugApp = Settings.System.getString(
-            resolver, Settings.System.DEBUG_APP);
-        boolean waitForDebugger = Settings.System.getInt(
-            resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
-        boolean alwaysFinishActivities = Settings.System.getInt(
-            resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
+        String debugApp = Settings.Global.getString(
+            resolver, Settings.Global.DEBUG_APP);
+        boolean waitForDebugger = Settings.Global.getInt(
+            resolver, Settings.Global.WAIT_FOR_DEBUGGER, 0) != 0;
+        boolean alwaysFinishActivities = Settings.Global.getInt(
+            resolver, Settings.Global.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
 
         Configuration configuration = new Configuration();
         Settings.System.getConfiguration(resolver, configuration);
@@ -7491,9 +7729,9 @@
                         }
                     }
                     intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
-                    
+
                     ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
-                    
+
                     final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
                     for (int i=0; i<ris.size(); i++) {
                         ActivityInfo ai = ris.get(i).activityInfo;
@@ -7504,42 +7742,45 @@
                         }
                     }
 
+                    final int[] users = getUsersLocked();
                     for (int i=0; i<ris.size(); i++) {
                         ActivityInfo ai = ris.get(i).activityInfo;
                         ComponentName comp = new ComponentName(ai.packageName, ai.name);
                         doneReceivers.add(comp);
                         intent.setComponent(comp);
-                        IIntentReceiver finisher = null;
-                        if (i == ris.size()-1) {
-                            finisher = new IIntentReceiver.Stub() {
-                                public void performReceive(Intent intent, int resultCode,
-                                        String data, Bundle extras, boolean ordered,
-                                        boolean sticky) {
-                                    // The raw IIntentReceiver interface is called
-                                    // with the AM lock held, so redispatch to
-                                    // execute our code without the lock.
-                                    mHandler.post(new Runnable() {
-                                        public void run() {
-                                            synchronized (ActivityManagerService.this) {
-                                                mDidUpdate = true;
+                        for (int j=0; j<users.length; j++) {
+                            IIntentReceiver finisher = null;
+                            if (i == ris.size()-1 && j == users.length-1) {
+                                finisher = new IIntentReceiver.Stub() {
+                                    public void performReceive(Intent intent, int resultCode,
+                                            String data, Bundle extras, boolean ordered,
+                                            boolean sticky, int sendingUser) {
+                                        // The raw IIntentReceiver interface is called
+                                        // with the AM lock held, so redispatch to
+                                        // execute our code without the lock.
+                                        mHandler.post(new Runnable() {
+                                            public void run() {
+                                                synchronized (ActivityManagerService.this) {
+                                                    mDidUpdate = true;
+                                                }
+                                                writeLastDonePreBootReceivers(doneReceivers);
+                                                showBootMessage(mContext.getText(
+                                                        R.string.android_upgrading_complete),
+                                                        false);
+                                                systemReady(goingCallback);
                                             }
-                                            writeLastDonePreBootReceivers(doneReceivers);
-                                            showBootMessage(mContext.getText(
-                                                    R.string.android_upgrading_complete),
-                                                    false);
-                                            systemReady(goingCallback);
-                                        }
-                                    });
-                                }
-                            };
-                        }
-                        Slog.i(TAG, "Sending system update to: " + intent.getComponent());
-                        /* TODO: Send this to all users */
-                        broadcastIntentLocked(null, null, intent, null, finisher,
-                                0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID,
-                                0 /* UserId zero */);
-                        if (finisher != null) {
-                            mWaitingUpdate = true;
+                                        });
+                                    }
+                                };
+                            }
+                            Slog.i(TAG, "Sending system update to " + intent.getComponent()
+                                    + " for user " + users[j]);
+                            broadcastIntentLocked(null, null, intent, null, finisher,
+                                    0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID,
+                                    users[j]);
+                            if (finisher != null) {
+                                mWaitingUpdate = true;
+                            }
                         }
                     }
                 }
@@ -7661,7 +7902,33 @@
             } catch (RemoteException e) {
             }
 
+            long ident = Binder.clearCallingIdentity();
+            try {
+                Intent intent = new Intent(Intent.ACTION_USER_STARTED);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                        | Intent.FLAG_RECEIVER_FOREGROUND);
+                intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
+                broadcastIntentLocked(null, null, intent,
+                        null, null, 0, null, null, null,
+                        false, false, MY_PID, Process.SYSTEM_UID, mCurrentUserId);
+                intent = new Intent(Intent.ACTION_USER_STARTING);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
+                broadcastIntentLocked(null, null, intent,
+                        null, new IIntentReceiver.Stub() {
+                            @Override
+                            public void performReceive(Intent intent, int resultCode, String data,
+                                    Bundle extras, boolean ordered, boolean sticky, int sendingUser)
+                                    throws RemoteException {
+                            }
+                        }, 0, null, null,
+                        android.Manifest.permission.INTERACT_ACROSS_USERS,
+                        false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
             mMainStack.resumeTopActivityLocked(null);
+            sendUserSwitchBroadcastsLocked(-1, mCurrentUserId);
         }
     }
 
@@ -7729,7 +7996,7 @@
             if (app.pid > 0 && app.pid != MY_PID) {
                 handleAppCrashLocked(app);
                 Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
-                EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
+                EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
                         app.processName, app.setAdj, "user's request after error");
                 Process.killProcessQuiet(app.pid);
             }
@@ -7754,13 +8021,14 @@
             Slog.w(TAG, "Process " + app.info.processName
                     + " has crashed too many times: killing!");
             EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
-                    app.info.processName, app.uid);
+                    app.userId, app.info.processName, app.uid);
             for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
                 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
                 if (r.app == app) {
                     Slog.w(TAG, "  Force finishing activity "
                         + r.intent.getComponent().flattenToShortString());
-                    r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
+                    r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
+                            null, "crashed", false);
                 }
             }
             if (!app.persistent) {
@@ -7768,7 +8036,7 @@
                 // explicitly does so...  but for persistent process, we really
                 // need to keep it running.  If a persistent process is actually
                 // repeatedly crashing, then badness for everyone.
-                EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.uid,
+                EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.userId, app.uid,
                         app.info.processName);
                 if (!app.isolated) {
                     // XXX We don't have a way to mark isolated processes
@@ -7795,7 +8063,7 @@
                         + r.intent.getComponent().flattenToShortString());
                 int index = mMainStack.indexOfActivityLocked(r);
                 r.stack.finishActivityLocked(r, index,
-                        Activity.RESULT_CANCELED, null, "crashed");
+                        Activity.RESULT_CANCELED, null, "crashed", false);
                 // Also terminate any activities below it that aren't yet
                 // stopped, to avoid a situation where one will get
                 // re-start our crashing activity once it gets resumed again.
@@ -7809,7 +8077,7 @@
                             Slog.w(TAG, "  Force finishing activity "
                                     + r.intent.getComponent().flattenToShortString());
                             r.stack.finishActivityLocked(r, index,
-                                    Activity.RESULT_CANCELED, null, "crashed");
+                                    Activity.RESULT_CANCELED, null, "crashed", false);
                         }
                     }
                 }
@@ -7858,8 +8126,15 @@
     }
 
     void startAppProblemLocked(ProcessRecord app) {
-        app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
-                mContext, app.info.packageName, app.info.flags);
+        if (app.userId == mCurrentUserId) {
+            app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
+                    mContext, app.info.packageName, app.info.flags);
+        } else {
+            // If this app is not running under the current user, then we
+            // can't give it a report button because that would require
+            // launching the report UI under a different user.
+            app.errorReportReceiver = null;
+        }
         skipCurrentReceiverLocked(app);
     }
 
@@ -7881,7 +8156,7 @@
                 : (r == null ? "unknown" : r.processName);
 
         EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
-                processName,
+                UserHandle.getUserId(Binder.getCallingUid()), processName,
                 r == null ? -1 : r.info.flags,
                 crashInfo.exceptionClassName,
                 crashInfo.exceptionMessage,
@@ -8079,7 +8354,8 @@
         final String processName = app == null ? "system_server"
                 : (r == null ? "unknown" : r.processName);
 
-        EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
+        EventLog.writeEvent(EventLogTags.AM_WTF,
+                UserHandle.getUserId(Binder.getCallingUid()), Binder.getCallingPid(),
                 processName,
                 r == null ? -1 : r.info.flags,
                 tag, crashInfo.exceptionMessage);
@@ -8087,8 +8363,8 @@
         addErrorToDropBox("wtf", r, processName, null, null, tag, null, null, crashInfo);
 
         if (r != null && r.pid != Process.myPid() &&
-                Settings.Secure.getInt(mContext.getContentResolver(),
-                        Settings.Secure.WTF_IS_FATAL, 0) != 0) {
+                Settings.Global.getInt(mContext.getContentResolver(),
+                        Settings.Global.WTF_IS_FATAL, 0) != 0) {
             crashApplication(r, crashInfo);
             return true;
         } else {
@@ -8150,7 +8426,7 @@
             for (String pkg : process.pkgList) {
                 sb.append("Package: ").append(pkg);
                 try {
-                    PackageInfo pi = pm.getPackageInfo(pkg, 0, 0);
+                    PackageInfo pi = pm.getPackageInfo(pkg, 0, UserHandle.getCallingUserId());
                     if (pi != null) {
                         sb.append(" v").append(pi.versionCode);
                         if (pi.versionName != null) {
@@ -8240,8 +8516,8 @@
                     sb.append(crashInfo.stackTrace);
                 }
 
-                String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
-                int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
+                String setting = Settings.Global.ERROR_LOGCAT_PREFIX + dropboxTag;
+                int lines = Settings.Global.getInt(mContext.getContentResolver(), setting, 0);
                 if (lines > 0) {
                     sb.append("\n");
 
@@ -8366,7 +8642,7 @@
 
         if (appErrorIntent != null) {
             try {
-                mContext.startActivity(appErrorIntent);
+                mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId));
             } catch (ActivityNotFoundException e) {
                 Slog.w(TAG, "bug report receiver dissappeared", e);
             }
@@ -8423,11 +8699,19 @@
         // assume our apps are happy - lazy create the list
         List<ActivityManager.ProcessErrorStateInfo> errList = null;
 
+        final boolean allUsers = ActivityManager.checkUidPermission(
+                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                Binder.getCallingUid()) == PackageManager.PERMISSION_GRANTED;
+        int userId = UserHandle.getUserId(Binder.getCallingUid());
+
         synchronized (this) {
 
             // iterate across all processes
             for (int i=mLruProcesses.size()-1; i>=0; i--) {
                 ProcessRecord app = mLruProcesses.get(i);
+                if (!allUsers && app.userId != userId) {
+                    continue;
+                }
                 if ((app.thread != null) && (app.crashing || app.notResponding)) {
                     // This one's in trouble, so we'll generate a report for it
                     // crashes are higher priority (in case there's a crash *and* an anr)
@@ -8491,6 +8775,9 @@
         if (app.persistent) {
             outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
         }
+        if (app.hasActivities) {
+            outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HAS_ACTIVITIES;
+        }
         outInfo.lastTrimLevel = app.trimMemoryLevel;
         int adj = app.curAdj;
         outInfo.importance = oomAdjToImportance(adj, outInfo);
@@ -8501,10 +8788,17 @@
         enforceNotIsolatedCaller("getRunningAppProcesses");
         // Lazy instantiation of list
         List<ActivityManager.RunningAppProcessInfo> runList = null;
+        final boolean allUsers = ActivityManager.checkUidPermission(
+                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                Binder.getCallingUid()) == PackageManager.PERMISSION_GRANTED;
+        int userId = UserHandle.getUserId(Binder.getCallingUid());
         synchronized (this) {
             // Iterate across all processes
             for (int i=mLruProcesses.size()-1; i>=0; i--) {
                 ProcessRecord app = mLruProcesses.get(i);
+                if (!allUsers && app.userId != userId) {
+                    continue;
+                }
                 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
                     // Generate process state info for running application
                     ActivityManager.RunningAppProcessInfo currApp = 
@@ -8550,7 +8844,7 @@
             IPackageManager pm = AppGlobals.getPackageManager();
             for (String pkg : extList) {
                 try {
-                    ApplicationInfo info = pm.getApplicationInfo(pkg, 0, UserId.getCallingUserId());
+                    ApplicationInfo info = pm.getApplicationInfo(pkg, 0, UserHandle.getCallingUserId());
                     if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
                         retList.add(info);
                     }
@@ -8605,7 +8899,7 @@
                 pw.println("  [-a] [-c] [-h] [cmd] ...");
                 pw.println("  cmd may be one of:");
                 pw.println("    a[ctivities]: activity stack state");
-                pw.println("    b[roadcasts] [PACKAGE_NAME]: broadcast state");
+                pw.println("    b[roadcasts] [PACKAGE_NAME] [history [-s]]: broadcast state");
                 pw.println("    i[ntents] [PACKAGE_NAME]: pending intent state");
                 pw.println("    p[rocesses] [PACKAGE_NAME]: process state");
                 pw.println("    o[om]: out of memory management");
@@ -8723,7 +9017,7 @@
                     if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
                             args.length - opti);
                 }
-                if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
+                if (!mServices.dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
                     pw.println("No services match: " + name);
                     pw.println("Use -h for help.");
                 }
@@ -8744,7 +9038,7 @@
                 }
             } else if ("services".equals(cmd) || "s".equals(cmd)) {
                 synchronized (this) {
-                    dumpServicesLocked(fd, pw, args, opti, true, dumpClient, null);
+                    mServices.dumpServicesLocked(fd, pw, args, opti, true, dumpClient, null);
                 }
             } else {
                 // Dumping a single activity?
@@ -8783,7 +9077,7 @@
             if (dumpAll) {
                 pw.println("-------------------------------------------------------------------------------");
             }
-            needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
+            needSep = mServices.dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
             if (needSep) {
                 pw.println(" ");
             }
@@ -9058,6 +9352,27 @@
         }
 
         pw.println();
+        pw.println("  mStartedUsers:");
+        for (int i=0; i<mStartedUsers.size(); i++) {
+            UserStartedState uss = mStartedUsers.valueAt(i);
+            pw.print("    User #"); pw.print(uss.mHandle.getIdentifier());
+                    pw.print(": "); uss.dump("", pw);
+        }
+        pw.print("  mStartedUserArray: [");
+        for (int i=0; i<mStartedUserArray.length; i++) {
+            if (i > 0) pw.print(", ");
+            pw.print(mStartedUserArray[i]);
+        }
+        pw.println("]");
+        pw.print("  mUserLru: [");
+        for (int i=0; i<mUserLru.size(); i++) {
+            if (i > 0) pw.print(", ");
+            pw.print(mUserLru.get(i));
+        }
+        pw.println("]");
+        if (dumpAll) {
+            pw.print("  mStartedUserArray: "); pw.println(Arrays.toString(mStartedUserArray));
+        }
         pw.println("  mHomeProcess: " + mHomeProcess);
         pw.println("  mPreviousProcess: " + mPreviousProcess);
         if (dumpAll) {
@@ -9134,7 +9449,9 @@
             pw.println("  mGoingToSleep=" + mMainStack.mGoingToSleep);
             pw.println("  mLaunchingActivity=" + mMainStack.mLaunchingActivity);
             pw.println("  mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
-            pw.println("  mNumServiceProcs=" + mNumServiceProcs
+            pw.println("  mNumNonHiddenProcs=" + mNumNonHiddenProcs
+                    + " mNumHiddenProcs=" + mNumHiddenProcs
+                    + " mNumServiceProcs=" + mNumServiceProcs
                     + " mNewNumServiceProcs=" + mNewNumServiceProcs);
         }
         
@@ -9214,120 +9531,6 @@
 
     /**
      * There are three ways to call this:
-     *  - no service specified: dump all the services
-     *  - a flattened component name that matched an existing service was specified as the
-     *    first arg: dump that one service
-     *  - the first arg isn't the flattened component name of an existing service:
-     *    dump all services whose component contains the first arg as a substring
-     */
-    protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
-            int opti, boolean dumpAll) {
-        ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
-
-        if ("all".equals(name)) {
-            synchronized (this) {
-                try {
-                    List<UserInfo> users = AppGlobals.getPackageManager().getUsers();
-                    for (UserInfo user : users) {
-                        for (ServiceRecord r1 : mServiceMap.getAllServices(user.id)) {
-                            services.add(r1);
-                        }
-                    }
-                } catch (RemoteException re) {
-                }
-            }
-        } else {
-            ComponentName componentName = name != null
-                    ? ComponentName.unflattenFromString(name) : null;
-            int objectId = 0;
-            if (componentName == null) {
-                // Not a '/' separated full component name; maybe an object ID?
-                try {
-                    objectId = Integer.parseInt(name, 16);
-                    name = null;
-                    componentName = null;
-                } catch (RuntimeException e) {
-                }
-            }
-
-            synchronized (this) {
-                try {
-                    List<UserInfo> users = AppGlobals.getPackageManager().getUsers();
-                    for (UserInfo user : users) {
-                        for (ServiceRecord r1 : mServiceMap.getAllServices(user.id)) {
-                            if (componentName != null) {
-                                if (r1.name.equals(componentName)) {
-                                    services.add(r1);
-                                }
-                            } else if (name != null) {
-                                if (r1.name.flattenToString().contains(name)) {
-                                    services.add(r1);
-                                }
-                            } else if (System.identityHashCode(r1) == objectId) {
-                                services.add(r1);
-                            }
-                        }
-                    }
-                } catch (RemoteException re) {
-                }
-            }
-        }
-
-        if (services.size() <= 0) {
-            return false;
-        }
-
-        boolean needSep = false;
-        for (int i=0; i<services.size(); i++) {
-            if (needSep) {
-                pw.println();
-            }
-            needSep = true;
-            dumpService("", fd, pw, services.get(i), args, dumpAll);
-        }
-        return true;
-    }
-
-    /**
-     * Invokes IApplicationThread.dumpService() on the thread of the specified service if
-     * there is a thread associated with the service.
-     */
-    private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
-            final ServiceRecord r, String[] args, boolean dumpAll) {
-        String innerPrefix = prefix + "  ";
-        synchronized (this) {
-            pw.print(prefix); pw.print("SERVICE ");
-                    pw.print(r.shortName); pw.print(" ");
-                    pw.print(Integer.toHexString(System.identityHashCode(r)));
-                    pw.print(" pid=");
-                    if (r.app != null) pw.println(r.app.pid);
-                    else pw.println("(not running)");
-            if (dumpAll) {
-                r.dump(pw, innerPrefix);
-            }
-        }
-        if (r.app != null && r.app.thread != null) {
-            pw.print(prefix); pw.println("  Client:");
-            pw.flush();
-            try {
-                TransferPipe tp = new TransferPipe();
-                try {
-                    r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
-                    tp.setBufferPrefix(prefix + "    ");
-                    tp.go(fd);
-                } finally {
-                    tp.kill();
-                }
-            } catch (IOException e) {
-                pw.println(prefix + "    Failure while dumping the service: " + e);
-            } catch (RemoteException e) {
-                pw.println(prefix + "    Got a RemoteException while dumping the service");
-            }
-        }
-    }
-
-    /**
-     * There are three ways to call this:
      *  - no provider specified: dump all the providers
      *  - a flattened component name that matched an existing provider was specified as the
      *    first arg: dump that one provider
@@ -9527,9 +9730,18 @@
     boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, String dumpPackage) {
         boolean needSep = false;
-        
+        boolean onlyHistory = false;
+
+        if ("history".equals(dumpPackage)) {
+            if (opti < args.length && "-s".equals(args[opti])) {
+                dumpAll = false;
+            }
+            onlyHistory = true;
+            dumpPackage = null;
+        }
+
         pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
-        if (dumpAll) {
+        if (!onlyHistory && dumpAll) {
             if (mRegisteredReceivers.size() > 0) {
                 boolean printed = false;
                 Iterator it = mRegisteredReceivers.values().iterator();
@@ -9562,39 +9774,41 @@
 
         needSep = true;
         
-        if (mStickyBroadcasts != null && dumpPackage == null) {
-            if (needSep) {
-                pw.println();
-            }
-            needSep = true;
-            pw.println("  Sticky broadcasts:");
-            StringBuilder sb = new StringBuilder(128);
-            for (Map.Entry<String, ArrayList<Intent>> ent
-                    : mStickyBroadcasts.entrySet()) {
-                pw.print("  * Sticky action "); pw.print(ent.getKey());
-                if (dumpAll) {
-                    pw.println(":");
-                    ArrayList<Intent> intents = ent.getValue();
-                    final int N = intents.size();
-                    for (int i=0; i<N; i++) {
-                        sb.setLength(0);
-                        sb.append("    Intent: ");
-                        intents.get(i).toShortString(sb, false, true, false, false);
-                        pw.println(sb.toString());
-                        Bundle bundle = intents.get(i).getExtras();
-                        if (bundle != null) {
-                            pw.print("      ");
-                            pw.println(bundle.toString());
+        if (!onlyHistory && mStickyBroadcasts != null && dumpPackage == null) {
+            for (int user=0; user<mStickyBroadcasts.size(); user++) {
+                if (needSep) {
+                    pw.println();
+                }
+                needSep = true;
+                pw.print("  Sticky broadcasts for user ");
+                        pw.print(mStickyBroadcasts.keyAt(user)); pw.println(":");
+                StringBuilder sb = new StringBuilder(128);
+                for (Map.Entry<String, ArrayList<Intent>> ent
+                        : mStickyBroadcasts.valueAt(user).entrySet()) {
+                    pw.print("  * Sticky action "); pw.print(ent.getKey());
+                    if (dumpAll) {
+                        pw.println(":");
+                        ArrayList<Intent> intents = ent.getValue();
+                        final int N = intents.size();
+                        for (int i=0; i<N; i++) {
+                            sb.setLength(0);
+                            sb.append("    Intent: ");
+                            intents.get(i).toShortString(sb, false, true, false, false);
+                            pw.println(sb.toString());
+                            Bundle bundle = intents.get(i).getExtras();
+                            if (bundle != null) {
+                                pw.print("      ");
+                                pw.println(bundle.toString());
+                            }
                         }
+                    } else {
+                        pw.println("");
                     }
-                } else {
-                    pw.println("");
                 }
             }
-            needSep = true;
         }
         
-        if (dumpAll) {
+        if (!onlyHistory && dumpAll) {
             pw.println();
             for (BroadcastQueue queue : mBroadcastQueues) {
                 pw.println("  mBroadcastsScheduled [" + queue.mQueueName + "]="
@@ -9608,199 +9822,6 @@
         return needSep;
     }
 
-    /**
-     * Prints a list of ServiceRecords (dumpsys activity services)
-     */
-    boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
-            int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
-        boolean needSep = false;
-
-        ItemMatcher matcher = new ItemMatcher();
-        matcher.build(args, opti);
-
-        pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
-        try {
-            List<UserInfo> users = AppGlobals.getPackageManager().getUsers();
-            for (UserInfo user : users) {
-                if (mServiceMap.getAllServices(user.id).size() > 0) {
-                    boolean printed = false;
-                    long nowReal = SystemClock.elapsedRealtime();
-                    Iterator<ServiceRecord> it = mServiceMap.getAllServices(
-                            user.id).iterator();
-                    needSep = false;
-                    while (it.hasNext()) {
-                        ServiceRecord r = it.next();
-                        if (!matcher.match(r, r.name)) {
-                            continue;
-                        }
-                        if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
-                            continue;
-                        }
-                        if (!printed) {
-                            pw.println("  Active services:");
-                            printed = true;
-                        }
-                        if (needSep) {
-                            pw.println();
-                        }
-                        pw.print("  * ");
-                        pw.println(r);
-                        if (dumpAll) {
-                            r.dump(pw, "    ");
-                            needSep = true;
-                        } else {
-                            pw.print("    app=");
-                            pw.println(r.app);
-                            pw.print("    created=");
-                            TimeUtils.formatDuration(r.createTime, nowReal, pw);
-                            pw.print(" started=");
-                            pw.print(r.startRequested);
-                            pw.print(" connections=");
-                            pw.println(r.connections.size());
-                            if (r.connections.size() > 0) {
-                                pw.println("    Connections:");
-                                for (ArrayList<ConnectionRecord> clist : r.connections.values()) {
-                                    for (int i = 0; i < clist.size(); i++) {
-                                        ConnectionRecord conn = clist.get(i);
-                                        pw.print("      ");
-                                        pw.print(conn.binding.intent.intent.getIntent()
-                                                .toShortString(false, false, false, false));
-                                        pw.print(" -> ");
-                                        ProcessRecord proc = conn.binding.client;
-                                        pw.println(proc != null ? proc.toShortString() : "null");
-                                    }
-                                }
-                            }
-                        }
-                        if (dumpClient && r.app != null && r.app.thread != null) {
-                            pw.println("    Client:");
-                            pw.flush();
-                            try {
-                                TransferPipe tp = new TransferPipe();
-                                try {
-                                    r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(),
-                                            r, args);
-                                    tp.setBufferPrefix("      ");
-                                    // Short timeout, since blocking here can
-                                    // deadlock with the application.
-                                    tp.go(fd, 2000);
-                                } finally {
-                                    tp.kill();
-                                }
-                            } catch (IOException e) {
-                                pw.println("      Failure while dumping the service: " + e);
-                            } catch (RemoteException e) {
-                                pw.println("      Got a RemoteException while dumping the service");
-                            }
-                            needSep = true;
-                        }
-                    }
-                    needSep = printed;
-                }
-            }
-        } catch (RemoteException re) {
-
-        }
-
-        if (mPendingServices.size() > 0) {
-            boolean printed = false;
-            for (int i=0; i<mPendingServices.size(); i++) {
-                ServiceRecord r = mPendingServices.get(i);
-                if (!matcher.match(r, r.name)) {
-                    continue;
-                }
-                if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
-                    continue;
-                }
-                if (!printed) {
-                    if (needSep) pw.println(" ");
-                    needSep = true;
-                    pw.println("  Pending services:");
-                    printed = true;
-                }
-                pw.print("  * Pending "); pw.println(r);
-                r.dump(pw, "    ");
-            }
-            needSep = true;
-        }
-
-        if (mRestartingServices.size() > 0) {
-            boolean printed = false;
-            for (int i=0; i<mRestartingServices.size(); i++) {
-                ServiceRecord r = mRestartingServices.get(i);
-                if (!matcher.match(r, r.name)) {
-                    continue;
-                }
-                if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
-                    continue;
-                }
-                if (!printed) {
-                    if (needSep) pw.println(" ");
-                    needSep = true;
-                    pw.println("  Restarting services:");
-                    printed = true;
-                }
-                pw.print("  * Restarting "); pw.println(r);
-                r.dump(pw, "    ");
-            }
-            needSep = true;
-        }
-
-        if (mStoppingServices.size() > 0) {
-            boolean printed = false;
-            for (int i=0; i<mStoppingServices.size(); i++) {
-                ServiceRecord r = mStoppingServices.get(i);
-                if (!matcher.match(r, r.name)) {
-                    continue;
-                }
-                if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
-                    continue;
-                }
-                if (!printed) {
-                    if (needSep) pw.println(" ");
-                    needSep = true;
-                    pw.println("  Stopping services:");
-                    printed = true;
-                }
-                pw.print("  * Stopping "); pw.println(r);
-                r.dump(pw, "    ");
-            }
-            needSep = true;
-        }
-
-        if (dumpAll) {
-            if (mServiceConnections.size() > 0) {
-                boolean printed = false;
-                Iterator<ArrayList<ConnectionRecord>> it
-                        = mServiceConnections.values().iterator();
-                while (it.hasNext()) {
-                    ArrayList<ConnectionRecord> r = it.next();
-                    for (int i=0; i<r.size(); i++) {
-                        ConnectionRecord cr = r.get(i);
-                        if (!matcher.match(cr.binding.service, cr.binding.service.name)) {
-                            continue;
-                        }
-                        if (dumpPackage != null && (cr.binding.client == null
-                                || !dumpPackage.equals(cr.binding.client.info.packageName))) {
-                            continue;
-                        }
-                        if (!printed) {
-                            if (needSep) pw.println(" ");
-                            needSep = true;
-                            pw.println("  Connection bindings to services:");
-                            printed = true;
-                        }
-                        pw.print("  * "); pw.println(cr);
-                        cr.dump(pw, "    ");
-                    }
-                }
-                needSep = true;
-            }
-        }
-        
-        return needSep;
-    }
-
     boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, String dumpPackage) {
         boolean needSep = true;
@@ -10106,6 +10127,8 @@
                 pw.print("    ");
                 pw.print("oom: max="); pw.print(r.maxAdj);
                 pw.print(" hidden="); pw.print(r.hiddenAdj);
+                pw.print(" client="); pw.print(r.clientHiddenAdj);
+                pw.print(" empty="); pw.print(r.emptyAdj);
                 pw.print(" curRaw="); pw.print(r.curRawAdj);
                 pw.print(" setRaw="); pw.print(r.setRawAdj);
                 pw.print(" cur="); pw.print(r.curAdj);
@@ -10594,125 +10617,6 @@
         return false;
     }
 
-    private final void killServicesLocked(ProcessRecord app,
-            boolean allowRestart) {
-        // Report disconnected services.
-        if (false) {
-            // XXX we are letting the client link to the service for
-            // death notifications.
-            if (app.services.size() > 0) {
-                Iterator<ServiceRecord> it = app.services.iterator();
-                while (it.hasNext()) {
-                    ServiceRecord r = it.next();
-                    if (r.connections.size() > 0) {
-                        Iterator<ArrayList<ConnectionRecord>> jt
-                                = r.connections.values().iterator();
-                        while (jt.hasNext()) {
-                            ArrayList<ConnectionRecord> cl = jt.next();
-                            for (int i=0; i<cl.size(); i++) {
-                                ConnectionRecord c = cl.get(i);
-                                if (c.binding.client != app) {
-                                    try {
-                                        //c.conn.connected(r.className, null);
-                                    } catch (Exception e) {
-                                        // todo: this should be asynchronous!
-                                        Slog.w(TAG, "Exception thrown disconnected servce "
-                                              + r.shortName
-                                              + " from app " + app.processName, e);
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        // Clean up any connections this application has to other services.
-        if (app.connections.size() > 0) {
-            Iterator<ConnectionRecord> it = app.connections.iterator();
-            while (it.hasNext()) {
-                ConnectionRecord r = it.next();
-                removeConnectionLocked(r, app, null);
-            }
-        }
-        app.connections.clear();
-
-        if (app.services.size() != 0) {
-            // Any services running in the application need to be placed
-            // back in the pending list.
-            Iterator<ServiceRecord> it = app.services.iterator();
-            while (it.hasNext()) {
-                ServiceRecord sr = it.next();
-                synchronized (sr.stats.getBatteryStats()) {
-                    sr.stats.stopLaunchedLocked();
-                }
-                sr.app = null;
-                sr.isolatedProc = null;
-                sr.executeNesting = 0;
-                if (mStoppingServices.remove(sr)) {
-                    if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
-                }
-                
-                boolean hasClients = sr.bindings.size() > 0;
-                if (hasClients) {
-                    Iterator<IntentBindRecord> bindings
-                            = sr.bindings.values().iterator();
-                    while (bindings.hasNext()) {
-                        IntentBindRecord b = bindings.next();
-                        if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
-                                + ": shouldUnbind=" + b.hasBound);
-                        b.binder = null;
-                        b.requested = b.received = b.hasBound = false;
-                    }
-                }
-
-                if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
-                        &ApplicationInfo.FLAG_PERSISTENT) == 0) {
-                    Slog.w(TAG, "Service crashed " + sr.crashCount
-                            + " times, stopping: " + sr);
-                    EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
-                            sr.crashCount, sr.shortName, app.pid);
-                    bringDownServiceLocked(sr, true);
-                } else if (!allowRestart) {
-                    bringDownServiceLocked(sr, true);
-                } else {
-                    boolean canceled = scheduleServiceRestartLocked(sr, true);
-                    
-                    // Should the service remain running?  Note that in the
-                    // extreme case of so many attempts to deliver a command
-                    // that it failed we also will stop it here.
-                    if (sr.startRequested && (sr.stopIfKilled || canceled)) {
-                        if (sr.pendingStarts.size() == 0) {
-                            sr.startRequested = false;
-                            if (!hasClients) {
-                                // Whoops, no reason to restart!
-                                bringDownServiceLocked(sr, true);
-                            }
-                        }
-                    }
-                }
-            }
-
-            if (!allowRestart) {
-                app.services.clear();
-            }
-        }
-
-        // Make sure we have no more records on the stopping list.
-        int i = mStoppingServices.size();
-        while (i > 0) {
-            i--;
-            ServiceRecord sr = mStoppingServices.get(i);
-            if (sr.app == app) {
-                mStoppingServices.remove(i);
-                if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
-            }
-        }
-        
-        app.executingServices.clear();
-    }
-
     private final boolean removeDyingProviderLocked(ProcessRecord proc,
             ContentProviderRecord cpr, boolean always) {
         final boolean inLaunching = mLaunchingProviders.contains(cpr);
@@ -10722,10 +10626,10 @@
                 cpr.launchingApp = null;
                 cpr.notifyAll();
             }
-            mProviderMap.removeProviderByClass(cpr.name, UserId.getUserId(cpr.uid));
+            mProviderMap.removeProviderByClass(cpr.name, UserHandle.getUserId(cpr.uid));
             String names[] = cpr.info.authority.split(";");
             for (int j = 0; j < names.length; j++) {
-                mProviderMap.removeProviderByName(names[j], UserId.getUserId(cpr.uid));
+                mProviderMap.removeProviderByName(names[j], UserHandle.getUserId(cpr.uid));
             }
         }
 
@@ -10748,7 +10652,7 @@
                     Slog.i(TAG, "Kill " + capp.processName
                             + " (pid " + capp.pid + "): provider " + cpr.info.name
                             + " in dying process " + (proc != null ? proc.processName : "??"));
-                    EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
+                    EventLog.writeEvent(EventLogTags.AM_KILL, capp.userId, capp.pid,
                             capp.processName, capp.setAdj, "dying provider "
                                     + cpr.name.toShortString());
                     Process.killProcessQuiet(capp.pid);
@@ -10810,7 +10714,7 @@
         app.hasShownUi = false;
         app.hasAboveClient = false;
 
-        killServicesLocked(app, allowRestart);
+        mServices.killServicesLocked(app, allowRestart);
 
         boolean restart = false;
 
@@ -10878,7 +10782,8 @@
         
         // If the app is undergoing backup, tell the backup manager about it
         if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
-            if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
+            if (DEBUG_BACKUP || DEBUG_CLEANUP) Slog.d(TAG, "App "
+                    + mBackupTarget.appInfo + " died during backup");
             try {
                 IBackupManager bm = IBackupManager.Stub.asInterface(
                         ServiceManager.getService(Context.BACKUP_SERVICE));
@@ -10904,13 +10809,14 @@
         }
 
         if (!app.persistent || app.isolated) {
-            if (DEBUG_PROCESSES) Slog.v(TAG,
+            if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG,
                     "Removing non-persistent process during cleanup: " + app);
             mProcessNames.remove(app.processName, app.uid);
             mIsolatedProcesses.remove(app.uid);
             if (mHeavyWeightProcess == app) {
+                mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
+                        mHeavyWeightProcess.userId, 0));
                 mHeavyWeightProcess = null;
-                mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
             }
         } else if (!app.removed) {
             // This app is persistent, so we need to keep its record around.
@@ -10921,7 +10827,7 @@
                 restart = true;
             }
         }
-        if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
+        if ((DEBUG_PROCESSES || DEBUG_CLEANUP) && mProcessesOnHold.contains(app)) Slog.v(TAG,
                 "Clean-up removing on hold: " + app);
         mProcessesOnHold.remove(app);
 
@@ -10974,806 +10880,23 @@
     // SERVICES
     // =========================================================
 
-    ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
-        ActivityManager.RunningServiceInfo info =
-            new ActivityManager.RunningServiceInfo();
-        info.service = r.name;
-        if (r.app != null) {
-            info.pid = r.app.pid;
-        }
-        info.uid = r.appInfo.uid;
-        info.process = r.processName;
-        info.foreground = r.isForeground;
-        info.activeSince = r.createTime;
-        info.started = r.startRequested;
-        info.clientCount = r.connections.size();
-        info.crashCount = r.crashCount;
-        info.lastActivityTime = r.lastActivity;
-        if (r.isForeground) {
-            info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
-        }
-        if (r.startRequested) {
-            info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
-        }
-        if (r.app != null && r.app.pid == MY_PID) {
-            info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
-        }
-        if (r.app != null && r.app.persistent) {
-            info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
-        }
-
-        for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
-            for (int i=0; i<connl.size(); i++) {
-                ConnectionRecord conn = connl.get(i);
-                if (conn.clientLabel != 0) {
-                    info.clientPackage = conn.binding.client.info.packageName;
-                    info.clientLabel = conn.clientLabel;
-                    return info;
-                }
-            }
-        }
-        return info;
-    }
-    
     public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
             int flags) {
         enforceNotIsolatedCaller("getServices");
         synchronized (this) {
-            ArrayList<ActivityManager.RunningServiceInfo> res
-                    = new ArrayList<ActivityManager.RunningServiceInfo>();
-            
-            int userId = UserId.getUserId(Binder.getCallingUid());
-            if (mServiceMap.getAllServices(userId).size() > 0) {
-                Iterator<ServiceRecord> it
-                        = mServiceMap.getAllServices(userId).iterator();
-                while (it.hasNext() && res.size() < maxNum) {
-                    res.add(makeRunningServiceInfoLocked(it.next()));
-                }
-            }
-
-            for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
-                ServiceRecord r = mRestartingServices.get(i);
-                ActivityManager.RunningServiceInfo info =
-                        makeRunningServiceInfoLocked(r);
-                info.restarting = r.nextRestartTime;
-                res.add(info);
-            }
-            
-            return res;
+            return mServices.getRunningServiceInfoLocked(maxNum, flags);
         }
     }
 
     public PendingIntent getRunningServiceControlPanel(ComponentName name) {
         enforceNotIsolatedCaller("getRunningServiceControlPanel");
         synchronized (this) {
-            int userId = UserId.getUserId(Binder.getCallingUid());
-            ServiceRecord r = mServiceMap.getServiceByName(name, userId);
-            if (r != null) {
-                for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
-                    for (int i=0; i<conn.size(); i++) {
-                        if (conn.get(i).clientIntent != null) {
-                            return conn.get(i).clientIntent;
-                        }
-                    }
-                }
-            }
+            return mServices.getRunningServiceControlPanelLocked(name);
         }
-        return null;
     }
     
-    private final ServiceRecord findServiceLocked(ComponentName name,
-            IBinder token) {
-        ServiceRecord r = mServiceMap.getServiceByName(name, Binder.getOrigCallingUser());
-        return r == token ? r : null;
-    }
-
-    private final class ServiceLookupResult {
-        final ServiceRecord record;
-        final String permission;
-
-        ServiceLookupResult(ServiceRecord _record, String _permission) {
-            record = _record;
-            permission = _permission;
-        }
-    };
-
-    private ServiceLookupResult findServiceLocked(Intent service,
-            String resolvedType, int userId) {
-        ServiceRecord r = null;
-        if (service.getComponent() != null) {
-            r = mServiceMap.getServiceByName(service.getComponent(), userId);
-        }
-        if (r == null) {
-            Intent.FilterComparison filter = new Intent.FilterComparison(service);
-            r = mServiceMap.getServiceByIntent(filter, userId);
-        }
-
-        if (r == null) {
-            try {
-                ResolveInfo rInfo =
-                    AppGlobals.getPackageManager().resolveService(
-                                service, resolvedType, 0, userId);
-                ServiceInfo sInfo =
-                    rInfo != null ? rInfo.serviceInfo : null;
-                if (sInfo == null) {
-                    return null;
-                }
-
-                ComponentName name = new ComponentName(
-                        sInfo.applicationInfo.packageName, sInfo.name);
-                r = mServiceMap.getServiceByName(name, Binder.getOrigCallingUser());
-            } catch (RemoteException ex) {
-                // pm is in same process, this will never happen.
-            }
-        }
-        if (r != null) {
-            int callingPid = Binder.getCallingPid();
-            int callingUid = Binder.getCallingUid();
-            if (checkComponentPermission(r.permission,
-                    callingPid, callingUid, r.appInfo.uid, r.exported)
-                    != PackageManager.PERMISSION_GRANTED) {
-                if (!r.exported) {
-                    Slog.w(TAG, "Permission Denial: Accessing service " + r.name
-                            + " from pid=" + callingPid
-                            + ", uid=" + callingUid
-                            + " that is not exported from uid " + r.appInfo.uid);
-                    return new ServiceLookupResult(null, "not exported from uid "
-                            + r.appInfo.uid);
-                }
-                Slog.w(TAG, "Permission Denial: Accessing service " + r.name
-                        + " from pid=" + callingPid
-                        + ", uid=" + callingUid
-                        + " requires " + r.permission);
-                return new ServiceLookupResult(null, r.permission);
-            }
-            return new ServiceLookupResult(r, null);
-        }
-        return null;
-    }
-
-    private class ServiceRestarter implements Runnable {
-        private ServiceRecord mService;
-
-        void setService(ServiceRecord service) {
-            mService = service;
-        }
-
-        public void run() {
-            synchronized(ActivityManagerService.this) {
-                performServiceRestartLocked(mService);
-            }
-        }
-    }
-
-    private ServiceLookupResult retrieveServiceLocked(Intent service,
-            String resolvedType, int callingPid, int callingUid, int userId) {
-        ServiceRecord r = null;
-        if (DEBUG_SERVICE)
-            Slog.v(TAG, "retrieveServiceLocked: " + service + " type=" + resolvedType
-                    + " callingUid=" + callingUid);
-
-        if (service.getComponent() != null) {
-            r = mServiceMap.getServiceByName(service.getComponent(), userId);
-        }
-        if (r == null) {
-            Intent.FilterComparison filter = new Intent.FilterComparison(service);
-            r = mServiceMap.getServiceByIntent(filter, userId);
-        }
-        if (r == null) {
-            try {
-                ResolveInfo rInfo =
-                    AppGlobals.getPackageManager().resolveService(
-                                service, resolvedType, STOCK_PM_FLAGS, userId);
-                ServiceInfo sInfo =
-                    rInfo != null ? rInfo.serviceInfo : null;
-                if (sInfo == null) {
-                    Slog.w(TAG, "Unable to start service " + service +
-                          ": not found");
-                    return null;
-                }
-                if (userId > 0) {
-                    if (isSingleton(sInfo.processName, sInfo.applicationInfo)) {
-                        userId = 0;
-                    }
-                    sInfo.applicationInfo = getAppInfoForUser(sInfo.applicationInfo, userId);
-                }
-                ComponentName name = new ComponentName(
-                        sInfo.applicationInfo.packageName, sInfo.name);
-                r = mServiceMap.getServiceByName(name, userId);
-                if (r == null) {
-                    Intent.FilterComparison filter = new Intent.FilterComparison(
-                            service.cloneFilter());
-                    ServiceRestarter res = new ServiceRestarter();
-                    BatteryStatsImpl.Uid.Pkg.Serv ss = null;
-                    BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
-                    synchronized (stats) {
-                        ss = stats.getServiceStatsLocked(
-                                sInfo.applicationInfo.uid, sInfo.packageName,
-                                sInfo.name);
-                    }
-                    r = new ServiceRecord(this, ss, name, filter, sInfo, res);
-                    res.setService(r);
-                    mServiceMap.putServiceByName(name, UserId.getUserId(r.appInfo.uid), r);
-                    mServiceMap.putServiceByIntent(filter, UserId.getUserId(r.appInfo.uid), r);
-                    
-                    // Make sure this component isn't in the pending list.
-                    int N = mPendingServices.size();
-                    for (int i=0; i<N; i++) {
-                        ServiceRecord pr = mPendingServices.get(i);
-                        if (pr.name.equals(name)) {
-                            mPendingServices.remove(i);
-                            i--;
-                            N--;
-                        }
-                    }
-                }
-            } catch (RemoteException ex) {
-                // pm is in same process, this will never happen.
-            }
-        }
-        if (r != null) {
-            if (checkComponentPermission(r.permission,
-                    callingPid, callingUid, r.appInfo.uid, r.exported)
-                    != PackageManager.PERMISSION_GRANTED) {
-                if (!r.exported) {
-                    Slog.w(TAG, "Permission Denial: Accessing service " + r.name
-                            + " from pid=" + callingPid
-                            + ", uid=" + callingUid
-                            + " that is not exported from uid " + r.appInfo.uid);
-                    return new ServiceLookupResult(null, "not exported from uid "
-                            + r.appInfo.uid);
-                }
-                Slog.w(TAG, "Permission Denial: Accessing service " + r.name
-                        + " from pid=" + callingPid
-                        + ", uid=" + callingUid
-                        + " requires " + r.permission);
-                return new ServiceLookupResult(null, r.permission);
-            }
-            return new ServiceLookupResult(r, null);
-        }
-        return null;
-    }
-
-    private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
-        if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
-                + why + " of " + r + " in app " + r.app);
-        else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
-                + why + " of " + r.shortName);
-        long now = SystemClock.uptimeMillis();
-        if (r.executeNesting == 0 && r.app != null) {
-            if (r.app.executingServices.size() == 0) {
-                Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
-                msg.obj = r.app;
-                mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
-            }
-            r.app.executingServices.add(r);
-        }
-        r.executeNesting++;
-        r.executingStart = now;
-    }
-
-    private final void sendServiceArgsLocked(ServiceRecord r,
-            boolean oomAdjusted) {
-        final int N = r.pendingStarts.size();
-        if (N == 0) {
-            return;
-        }
-
-        while (r.pendingStarts.size() > 0) {
-            try {
-                ServiceRecord.StartItem si = r.pendingStarts.remove(0);
-                if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
-                        + r + " " + r.intent + " args=" + si.intent);
-                if (si.intent == null && N > 1) {
-                    // If somehow we got a dummy null intent in the middle,
-                    // then skip it.  DO NOT skip a null intent when it is
-                    // the only one in the list -- this is to support the
-                    // onStartCommand(null) case.
-                    continue;
-                }
-                si.deliveredTime = SystemClock.uptimeMillis();
-                r.deliveredStarts.add(si);
-                si.deliveryCount++;
-                if (si.neededGrants != null) {
-                    grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
-                            si.getUriPermissionsLocked());
-                }
-                bumpServiceExecutingLocked(r, "start");
-                if (!oomAdjusted) {
-                    oomAdjusted = true;
-                    updateOomAdjLocked(r.app);
-                }
-                int flags = 0;
-                if (si.deliveryCount > 1) {
-                    flags |= Service.START_FLAG_RETRY;
-                }
-                if (si.doneExecutingCount > 0) {
-                    flags |= Service.START_FLAG_REDELIVERY;
-                }
-                r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
-            } catch (RemoteException e) {
-                // Remote process gone...  we'll let the normal cleanup take
-                // care of this.
-                if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
-                break;
-            } catch (Exception e) {
-                Slog.w(TAG, "Unexpected exception", e);
-                break;
-            }
-        }
-    }
-
-    private final boolean requestServiceBindingLocked(ServiceRecord r,
-            IntentBindRecord i, boolean rebind) {
-        if (r.app == null || r.app.thread == null) {
-            // If service is not currently running, can't yet bind.
-            return false;
-        }
-        if ((!i.requested || rebind) && i.apps.size() > 0) {
-            try {
-                bumpServiceExecutingLocked(r, "bind");
-                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
-                if (!rebind) {
-                    i.requested = true;
-                }
-                i.hasBound = true;
-                i.doRebind = false;
-            } catch (RemoteException e) {
-                if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private final void requestServiceBindingsLocked(ServiceRecord r) {
-        Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
-        while (bindings.hasNext()) {
-            IntentBindRecord i = bindings.next();
-            if (!requestServiceBindingLocked(r, i, false)) {
-                break;
-            }
-        }
-    }
-
-    private final void realStartServiceLocked(ServiceRecord r,
-            ProcessRecord app) throws RemoteException {
-        if (app.thread == null) {
-            throw new RemoteException();
-        }
-        if (DEBUG_MU)
-            Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
-                    + ", ProcessRecord.uid = " + app.uid);
-        r.app = app;
-        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
-
-        app.services.add(r);
-        bumpServiceExecutingLocked(r, "create");
-        updateLruProcessLocked(app, true, true);
-
-        boolean created = false;
-        try {
-            mStringBuilder.setLength(0);
-            r.intent.getIntent().toShortString(mStringBuilder, true, false, true, false);
-            EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
-                    System.identityHashCode(r), r.shortName,
-                    mStringBuilder.toString(), r.app.pid);
-            synchronized (r.stats.getBatteryStats()) {
-                r.stats.startLaunchedLocked();
-            }
-            ensurePackageDexOpt(r.serviceInfo.packageName);
-            app.thread.scheduleCreateService(r, r.serviceInfo,
-                    compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
-            r.postNotification();
-            created = true;
-        } finally {
-            if (!created) {
-                app.services.remove(r);
-                scheduleServiceRestartLocked(r, false);
-            }
-        }
-
-        requestServiceBindingsLocked(r);
-        
-        // If the service is in the started state, and there are no
-        // pending arguments, then fake up one so its onStartCommand() will
-        // be called.
-        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
-            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
-                    null, null));
-        }
-        
-        sendServiceArgsLocked(r, true);
-    }
-
-    private final boolean scheduleServiceRestartLocked(ServiceRecord r,
-            boolean allowCancel) {
-        boolean canceled = false;
-        
-        final long now = SystemClock.uptimeMillis();
-        long minDuration = SERVICE_RESTART_DURATION;
-        long resetTime = SERVICE_RESET_RUN_DURATION;
-        
-        if ((r.serviceInfo.applicationInfo.flags
-                &ApplicationInfo.FLAG_PERSISTENT) != 0) {
-            minDuration /= 4;
-        }
-        
-        // Any delivered but not yet finished starts should be put back
-        // on the pending list.
-        final int N = r.deliveredStarts.size();
-        if (N > 0) {
-            for (int i=N-1; i>=0; i--) {
-                ServiceRecord.StartItem si = r.deliveredStarts.get(i);
-                si.removeUriPermissionsLocked();
-                if (si.intent == null) {
-                    // We'll generate this again if needed.
-                } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
-                        && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
-                    r.pendingStarts.add(0, si);
-                    long dur = SystemClock.uptimeMillis() - si.deliveredTime;
-                    dur *= 2;
-                    if (minDuration < dur) minDuration = dur;
-                    if (resetTime < dur) resetTime = dur;
-                } else {
-                    Slog.w(TAG, "Canceling start item " + si.intent + " in service "
-                            + r.name);
-                    canceled = true;
-                }
-            }
-            r.deliveredStarts.clear();
-        }
-        
-        r.totalRestartCount++;
-        if (r.restartDelay == 0) {
-            r.restartCount++;
-            r.restartDelay = minDuration;
-        } else {
-            // If it has been a "reasonably long time" since the service
-            // was started, then reset our restart duration back to
-            // the beginning, so we don't infinitely increase the duration
-            // on a service that just occasionally gets killed (which is
-            // a normal case, due to process being killed to reclaim memory).
-            if (now > (r.restartTime+resetTime)) {
-                r.restartCount = 1;
-                r.restartDelay = minDuration;
-            } else {
-                if ((r.serviceInfo.applicationInfo.flags
-                        &ApplicationInfo.FLAG_PERSISTENT) != 0) {
-                    // Services in peristent processes will restart much more
-                    // quickly, since they are pretty important.  (Think SystemUI).
-                    r.restartDelay += minDuration/2;
-                } else {
-                    r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
-                    if (r.restartDelay < minDuration) {
-                        r.restartDelay = minDuration;
-                    }
-                }
-            }
-        }
-        
-        r.nextRestartTime = now + r.restartDelay;
-        
-        // Make sure that we don't end up restarting a bunch of services
-        // all at the same time.
-        boolean repeat;
-        do {
-            repeat = false;
-            for (int i=mRestartingServices.size()-1; i>=0; i--) {
-                ServiceRecord r2 = mRestartingServices.get(i);
-                if (r2 != r && r.nextRestartTime
-                        >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
-                        && r.nextRestartTime
-                        < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
-                    r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
-                    r.restartDelay = r.nextRestartTime - now;
-                    repeat = true;
-                    break;
-                }
-            }
-        } while (repeat);
-        
-        if (!mRestartingServices.contains(r)) {
-            mRestartingServices.add(r);
-        }
-        
-        r.cancelNotification();
-        
-        mHandler.removeCallbacks(r.restarter);
-        mHandler.postAtTime(r.restarter, r.nextRestartTime);
-        r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
-        Slog.w(TAG, "Scheduling restart of crashed service "
-                + r.shortName + " in " + r.restartDelay + "ms");
-        EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
-                r.shortName, r.restartDelay);
-
-        return canceled;
-    }
-
-    final void performServiceRestartLocked(ServiceRecord r) {
-        if (!mRestartingServices.contains(r)) {
-            return;
-        }
-        bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
-    }
-
-    private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
-        if (r.restartDelay == 0) {
-            return false;
-        }
-        r.resetRestartCounter();
-        mRestartingServices.remove(r);
-        mHandler.removeCallbacks(r.restarter);
-        return true;
-    }
-
-    private final boolean bringUpServiceLocked(ServiceRecord r,
-            int intentFlags, boolean whileRestarting) {
-        //Slog.i(TAG, "Bring up service:");
-        //r.dump("  ");
-
-        if (r.app != null && r.app.thread != null) {
-            sendServiceArgsLocked(r, false);
-            return true;
-        }
-
-        if (!whileRestarting && r.restartDelay > 0) {
-            // If waiting for a restart, then do nothing.
-            return true;
-        }
-
-        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
-
-        // We are now bringing the service up, so no longer in the
-        // restarting state.
-        mRestartingServices.remove(r);
-        
-        // Service is now being launched, its package can't be stopped.
-        try {
-            AppGlobals.getPackageManager().setPackageStoppedState(
-                    r.packageName, false, r.userId);
-        } catch (RemoteException e) {
-        } catch (IllegalArgumentException e) {
-            Slog.w(TAG, "Failed trying to unstop package "
-                    + r.packageName + ": " + e);
-        }
-
-        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
-        final String appName = r.processName;
-        ProcessRecord app;
-
-        if (!isolated) {
-            app = getProcessRecordLocked(appName, r.appInfo.uid);
-            if (DEBUG_MU)
-                Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
-            if (app != null && app.thread != null) {
-                try {
-                    app.addPackage(r.appInfo.packageName);
-                    realStartServiceLocked(r, app);
-                    return true;
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
-                }
-
-                // If a dead object exception was thrown -- fall through to
-                // restart the application.
-            }
-        } else {
-            // If this service runs in an isolated process, then each time
-            // we call startProcessLocked() we will get a new isolated
-            // process, starting another process if we are currently waiting
-            // for a previous process to come up.  To deal with this, we store
-            // in the service any current isolated process it is running in or
-            // waiting to have come up.
-            app = r.isolatedProc;
-        }
-
-        // Not running -- get it started, and enqueue this service record
-        // to be executed when the app comes up.
-        if (app == null) {
-            if ((app=startProcessLocked(appName, r.appInfo, true, intentFlags,
-                    "service", r.name, false, isolated)) == null) {
-                Slog.w(TAG, "Unable to launch app "
-                        + r.appInfo.packageName + "/"
-                        + r.appInfo.uid + " for service "
-                        + r.intent.getIntent() + ": process is bad");
-                bringDownServiceLocked(r, true);
-                return false;
-            }
-            if (isolated) {
-                r.isolatedProc = app;
-            }
-        }
-
-        if (!mPendingServices.contains(r)) {
-            mPendingServices.add(r);
-        }
-        
-        return true;
-    }
-
-    private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
-        //Slog.i(TAG, "Bring down service:");
-        //r.dump("  ");
-
-        // Does it still need to run?
-        if (!force && r.startRequested) {
-            return;
-        }
-        if (r.connections.size() > 0) {
-            if (!force) {
-                // XXX should probably keep a count of the number of auto-create
-                // connections directly in the service.
-                Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
-                while (it.hasNext()) {
-                    ArrayList<ConnectionRecord> cr = it.next();
-                    for (int i=0; i<cr.size(); i++) {
-                        if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
-                            return;
-                        }
-                    }
-                }
-            }
-
-            // Report to all of the connections that the service is no longer
-            // available.
-            Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
-            while (it.hasNext()) {
-                ArrayList<ConnectionRecord> c = it.next();
-                for (int i=0; i<c.size(); i++) {
-                    ConnectionRecord cr = c.get(i);
-                    // There is still a connection to the service that is
-                    // being brought down.  Mark it as dead.
-                    cr.serviceDead = true;
-                    try {
-                        cr.conn.connected(r.name, null);
-                    } catch (Exception e) {
-                        Slog.w(TAG, "Failure disconnecting service " + r.name +
-                              " to connection " + c.get(i).conn.asBinder() +
-                              " (in " + c.get(i).binding.client.processName + ")", e);
-                    }
-                }
-            }
-        }
-
-        // Tell the service that it has been unbound.
-        if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
-            Iterator<IntentBindRecord> it = r.bindings.values().iterator();
-            while (it.hasNext()) {
-                IntentBindRecord ibr = it.next();
-                if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
-                        + ": hasBound=" + ibr.hasBound);
-                if (r.app != null && r.app.thread != null && ibr.hasBound) {
-                    try {
-                        bumpServiceExecutingLocked(r, "bring down unbind");
-                        updateOomAdjLocked(r.app);
-                        ibr.hasBound = false;
-                        r.app.thread.scheduleUnbindService(r,
-                                ibr.intent.getIntent());
-                    } catch (Exception e) {
-                        Slog.w(TAG, "Exception when unbinding service "
-                                + r.shortName, e);
-                        serviceDoneExecutingLocked(r, true);
-                    }
-                }
-            }
-        }
-
-        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
-        EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
-                System.identityHashCode(r), r.shortName,
-                (r.app != null) ? r.app.pid : -1);
-
-        mServiceMap.removeServiceByName(r.name, r.userId);
-        mServiceMap.removeServiceByIntent(r.intent, r.userId);
-        r.totalRestartCount = 0;
-        unscheduleServiceRestartLocked(r);
-
-        // Also make sure it is not on the pending list.
-        int N = mPendingServices.size();
-        for (int i=0; i<N; i++) {
-            if (mPendingServices.get(i) == r) {
-                mPendingServices.remove(i);
-                if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
-                i--;
-                N--;
-            }
-        }
-
-        r.cancelNotification();
-        r.isForeground = false;
-        r.foregroundId = 0;
-        r.foregroundNoti = null;
-        
-        // Clear start entries.
-        r.clearDeliveredStartsLocked();
-        r.pendingStarts.clear();
-        
-        if (r.app != null) {
-            synchronized (r.stats.getBatteryStats()) {
-                r.stats.stopLaunchedLocked();
-            }
-            r.app.services.remove(r);
-            if (r.app.thread != null) {
-                try {
-                    bumpServiceExecutingLocked(r, "stop");
-                    mStoppingServices.add(r);
-                    updateOomAdjLocked(r.app);
-                    r.app.thread.scheduleStopService(r);
-                } catch (Exception e) {
-                    Slog.w(TAG, "Exception when stopping service "
-                            + r.shortName, e);
-                    serviceDoneExecutingLocked(r, true);
-                }
-                updateServiceForegroundLocked(r.app, false);
-            } else {
-                if (DEBUG_SERVICE) Slog.v(
-                    TAG, "Removed service that has no process: " + r);
-            }
-        } else {
-            if (DEBUG_SERVICE) Slog.v(
-                TAG, "Removed service that is not running: " + r);
-        }
-
-        if (r.bindings.size() > 0) {
-            r.bindings.clear();
-        }
-
-        if (r.restarter instanceof ServiceRestarter) {
-           ((ServiceRestarter)r.restarter).setService(null);
-        }
-    }
-
-    ComponentName startServiceLocked(IApplicationThread caller,
-            Intent service, String resolvedType,
-            int callingPid, int callingUid) {
-        synchronized(this) {
-            if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
-                    + " type=" + resolvedType + " args=" + service.getExtras());
-
-            if (caller != null) {
-                final ProcessRecord callerApp = getRecordForAppLocked(caller);
-                if (callerApp == null) {
-                    throw new SecurityException(
-                            "Unable to find app for caller " + caller
-                            + " (pid=" + Binder.getCallingPid()
-                            + ") when starting service " + service);
-                }
-            }
-
-            ServiceLookupResult res =
-                retrieveServiceLocked(service, resolvedType,
-                        callingPid, callingUid, UserId.getUserId(callingUid));
-            if (res == null) {
-                return null;
-            }
-            if (res.record == null) {
-                return new ComponentName("!", res.permission != null
-                        ? res.permission : "private to package");
-            }
-            ServiceRecord r = res.record;
-            NeededUriGrants neededGrants = checkGrantUriPermissionFromIntentLocked(
-                    callingUid, r.packageName, service, service.getFlags(), null);
-            if (unscheduleServiceRestartLocked(r)) {
-                if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
-            }
-            r.startRequested = true;
-            r.callStart = false;
-            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
-                    service, neededGrants));
-            r.lastActivity = SystemClock.uptimeMillis();
-            synchronized (r.stats.getBatteryStats()) {
-                r.stats.startRunningLocked();
-            }
-            if (!bringUpServiceLocked(r, service.getFlags(), false)) {
-                return new ComponentName("!", "Service process is bad");
-            }
-            return r.name;
-        }
-    }
-
     public ComponentName startService(IApplicationThread caller, Intent service,
-            String resolvedType) {
+            String resolvedType, int userId) {
         enforceNotIsolatedCaller("startService");
         // Refuse possible leaked file descriptors
         if (service != null && service.hasFileDescriptors() == true) {
@@ -11785,74 +10908,41 @@
         synchronized(this) {
             final int callingPid = Binder.getCallingPid();
             final int callingUid = Binder.getCallingUid();
+            checkValidCaller(callingUid, userId);
             final long origId = Binder.clearCallingIdentity();
-            ComponentName res = startServiceLocked(caller, service,
-                    resolvedType, callingPid, callingUid);
+            ComponentName res = mServices.startServiceLocked(caller, service,
+                    resolvedType, callingPid, callingUid, userId);
             Binder.restoreCallingIdentity(origId);
             return res;
         }
     }
 
     ComponentName startServiceInPackage(int uid,
-            Intent service, String resolvedType) {
+            Intent service, String resolvedType, int userId) {
         synchronized(this) {
             if (DEBUG_SERVICE)
                 Slog.v(TAG, "startServiceInPackage: " + service + " type=" + resolvedType);
             final long origId = Binder.clearCallingIdentity();
-            ComponentName res = startServiceLocked(null, service,
-                    resolvedType, -1, uid);
+            ComponentName res = mServices.startServiceLocked(null, service,
+                    resolvedType, -1, uid, userId);
             Binder.restoreCallingIdentity(origId);
             return res;
         }
     }
 
-    private void stopServiceLocked(ServiceRecord service) {
-        synchronized (service.stats.getBatteryStats()) {
-            service.stats.stopRunningLocked();
-        }
-        service.startRequested = false;
-        service.callStart = false;
-        bringDownServiceLocked(service, false);
-    }
-
     public int stopService(IApplicationThread caller, Intent service,
-            String resolvedType) {
+            String resolvedType, int userId) {
         enforceNotIsolatedCaller("stopService");
         // Refuse possible leaked file descriptors
         if (service != null && service.hasFileDescriptors() == true) {
             throw new IllegalArgumentException("File descriptors passed in Intent");
         }
 
+        checkValidCaller(Binder.getCallingUid(), userId);
+
         synchronized(this) {
-            if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
-                    + " type=" + resolvedType);
-
-            final ProcessRecord callerApp = getRecordForAppLocked(caller);
-            if (caller != null && callerApp == null) {
-                throw new SecurityException(
-                        "Unable to find app for caller " + caller
-                        + " (pid=" + Binder.getCallingPid()
-                        + ") when stopping service " + service);
-            }
-
-            // If this service is active, make sure it is stopped.
-            ServiceLookupResult r = findServiceLocked(service, resolvedType,
-                    callerApp == null ? UserId.getCallingUserId() : callerApp.userId);
-            if (r != null) {
-                if (r.record != null) {
-                    final long origId = Binder.clearCallingIdentity();
-                    try {
-                        stopServiceLocked(r.record);
-                    } finally {
-                        Binder.restoreCallingIdentity(origId);
-                    }
-                    return 1;
-                }
-                return -1;
-            }
+            return mServices.stopServiceLocked(caller, service, resolvedType, userId);
         }
-
-        return 0;
     }
 
     public IBinder peekService(Intent service, String resolvedType) {
@@ -11861,149 +10951,107 @@
         if (service != null && service.hasFileDescriptors() == true) {
             throw new IllegalArgumentException("File descriptors passed in Intent");
         }
-
-        IBinder ret = null;
-
         synchronized(this) {
-            ServiceLookupResult r = findServiceLocked(service, resolvedType,
-                    UserId.getCallingUserId());
-            
-            if (r != null) {
-                // r.record is null if findServiceLocked() failed the caller permission check
-                if (r.record == null) {
-                    throw new SecurityException(
-                            "Permission Denial: Accessing service " + r.record.name
-                            + " from pid=" + Binder.getCallingPid()
-                            + ", uid=" + Binder.getCallingUid()
-                            + " requires " + r.permission);
-                }
-                IntentBindRecord ib = r.record.bindings.get(r.record.intent);
-                if (ib != null) {
-                    ret = ib.binder;
-                }
-            }
+            return mServices.peekServiceLocked(service, resolvedType);
         }
-
-        return ret;
     }
     
     public boolean stopServiceToken(ComponentName className, IBinder token,
             int startId) {
         synchronized(this) {
-            if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
-                    + " " + token + " startId=" + startId);
-            ServiceRecord r = findServiceLocked(className, token);
-            if (r != null) {
-                if (startId >= 0) {
-                    // Asked to only stop if done with all work.  Note that
-                    // to avoid leaks, we will take this as dropping all
-                    // start items up to and including this one.
-                    ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
-                    if (si != null) {
-                        while (r.deliveredStarts.size() > 0) {
-                            ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
-                            cur.removeUriPermissionsLocked();
-                            if (cur == si) {
-                                break;
-                            }
-                        }
-                    }
-                    
-                    if (r.getLastStartId() != startId) {
-                        return false;
-                    }
-                    
-                    if (r.deliveredStarts.size() > 0) {
-                        Slog.w(TAG, "stopServiceToken startId " + startId
-                                + " is last, but have " + r.deliveredStarts.size()
-                                + " remaining args");
-                    }
-                }
-                
-                synchronized (r.stats.getBatteryStats()) {
-                    r.stats.stopRunningLocked();
-                    r.startRequested = false;
-                    r.callStart = false;
-                }
-                final long origId = Binder.clearCallingIdentity();
-                bringDownServiceLocked(r, false);
-                Binder.restoreCallingIdentity(origId);
-                return true;
-            }
+            return mServices.stopServiceTokenLocked(className, token, startId);
         }
-        return false;
     }
 
     public void setServiceForeground(ComponentName className, IBinder token,
             int id, Notification notification, boolean removeNotification) {
-        final long origId = Binder.clearCallingIdentity();
-        try {
         synchronized(this) {
-            ServiceRecord r = findServiceLocked(className, token);
-            if (r != null) {
-                if (id != 0) {
-                    if (notification == null) {
-                        throw new IllegalArgumentException("null notification");
-                    }
-                    if (r.foregroundId != id) {
-                        r.cancelNotification();
-                        r.foregroundId = id;
-                    }
-                    notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
-                    r.foregroundNoti = notification;
-                    r.isForeground = true;
-                    r.postNotification();
-                    if (r.app != null) {
-                        updateServiceForegroundLocked(r.app, true);
-                    }
-                } else {
-                    if (r.isForeground) {
-                        r.isForeground = false;
-                        if (r.app != null) {
-                            updateLruProcessLocked(r.app, false, true);
-                            updateServiceForegroundLocked(r.app, true);
+            mServices.setServiceForegroundLocked(className, token, id, notification,
+                    removeNotification);
+        }
+    }
+
+    public int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
+            boolean requireFull, String name, String callerPackage) {
+        final int callingUserId = UserHandle.getUserId(callingUid);
+        if (callingUserId != userId) {
+            if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
+                if ((requireFull || checkComponentPermission(
+                        android.Manifest.permission.INTERACT_ACROSS_USERS,
+                        callingPid, callingUid, -1, true) != PackageManager.PERMISSION_GRANTED)
+                        && checkComponentPermission(
+                                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                                callingPid, callingUid, -1, true)
+                                != PackageManager.PERMISSION_GRANTED) {
+                    if (userId == UserHandle.USER_CURRENT_OR_SELF) {
+                        // In this case, they would like to just execute as their
+                        // owner user instead of failing.
+                        userId = callingUserId;
+                    } else {
+                        StringBuilder builder = new StringBuilder(128);
+                        builder.append("Permission Denial: ");
+                        builder.append(name);
+                        if (callerPackage != null) {
+                            builder.append(" from ");
+                            builder.append(callerPackage);
                         }
-                    }
-                    if (removeNotification) {
-                        r.cancelNotification();
-                        r.foregroundId = 0;
-                        r.foregroundNoti = null;
+                        builder.append(" asks to run as user ");
+                        builder.append(userId);
+                        builder.append(" but is calling from user ");
+                        builder.append(UserHandle.getUserId(callingUid));
+                        builder.append("; this requires ");
+                        builder.append(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
+                        if (!requireFull) {
+                            builder.append(" or ");
+                            builder.append(android.Manifest.permission.INTERACT_ACROSS_USERS);
+                        }
+                        String msg = builder.toString();
+                        Slog.w(TAG, msg);
+                        throw new SecurityException(msg);
                     }
                 }
             }
-        }
-        } finally {
-            Binder.restoreCallingIdentity(origId);
-        }
-    }
-
-    public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
-        boolean anyForeground = false;
-        for (ServiceRecord sr : proc.services) {
-            if (sr.isForeground) {
-                anyForeground = true;
-                break;
+            if (userId == UserHandle.USER_CURRENT
+                    || userId == UserHandle.USER_CURRENT_OR_SELF) {
+                // Note that we may be accessing this outside of a lock...
+                // shouldn't be a big deal, if this is being called outside
+                // of a locked context there is intrinsically a race with
+                // the value the caller will receive and someone else changing it.
+                userId = mCurrentUserId;
+            }
+            if (!allowAll && userId < 0) {
+                throw new IllegalArgumentException(
+                        "Call does not support special user #" + userId);
             }
         }
-        if (anyForeground != proc.foregroundServices) {
-            proc.foregroundServices = anyForeground;
-            if (oomAdj) {
-                updateOomAdjLocked();
-            }
-        }
+        return userId;
     }
 
-    boolean isSingleton(String componentProcessName, ApplicationInfo aInfo) {
+    boolean isSingleton(String componentProcessName, ApplicationInfo aInfo,
+            String className, int flags) {
         boolean result = false;
-        if (UserId.getAppId(aInfo.uid) >= Process.FIRST_APPLICATION_UID) {
-            result = false;
+        if (UserHandle.getAppId(aInfo.uid) >= Process.FIRST_APPLICATION_UID) {
+            if ((flags&ServiceInfo.FLAG_SINGLE_USER) != 0) {
+                if (ActivityManager.checkUidPermission(
+                        android.Manifest.permission.INTERACT_ACROSS_USERS,
+                        aInfo.uid) != PackageManager.PERMISSION_GRANTED) {
+                    ComponentName comp = new ComponentName(aInfo.packageName, className);
+                    String msg = "Permission Denial: Component " + comp.flattenToShortString()
+                            + " requests FLAG_SINGLE_USER, but app does not hold "
+                            + android.Manifest.permission.INTERACT_ACROSS_USERS;
+                    Slog.w(TAG, msg);
+                    throw new SecurityException(msg);
+                }
+                result = true;
+            }
         } else if (componentProcessName == aInfo.packageName) {
             result = (aInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0;
         } else if ("system".equals(componentProcessName)) {
             result = true;
         }
         if (DEBUG_MU) {
-            Slog.v(TAG, "isSingleton(" + componentProcessName + ", " + aInfo + ") = " + result);
+            Slog.v(TAG, "isSingleton(" + componentProcessName + ", " + aInfo
+                    + ", " + className + ", 0x" + Integer.toHexString(flags) + ") = " + result);
         }
         return result;
     }
@@ -12017,239 +11065,16 @@
             throw new IllegalArgumentException("File descriptors passed in Intent");
         }
 
-        checkValidCaller(Binder.getCallingUid(), userId);
-
         synchronized(this) {
-            if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
-                    + " type=" + resolvedType + " conn=" + connection.asBinder()
-                    + " flags=0x" + Integer.toHexString(flags));
-            if (DEBUG_MU)
-                Slog.i(TAG_MU, "bindService uid=" + Binder.getCallingUid() + " origUid="
-                        + Binder.getOrigCallingUid());
-            final ProcessRecord callerApp = getRecordForAppLocked(caller);
-            if (callerApp == null) {
-                throw new SecurityException(
-                        "Unable to find app for caller " + caller
-                        + " (pid=" + Binder.getCallingPid()
-                        + ") when binding service " + service);
-            }
-
-            ActivityRecord activity = null;
-            if (token != null) {
-                activity = mMainStack.isInStackLocked(token);
-                if (activity == null) {
-                    Slog.w(TAG, "Binding with unknown activity: " + token);
-                    return 0;
-                }
-            }
-
-            int clientLabel = 0;
-            PendingIntent clientIntent = null;
-            
-            if (callerApp.info.uid == Process.SYSTEM_UID) {
-                // Hacky kind of thing -- allow system stuff to tell us
-                // what they are, so we can report this elsewhere for
-                // others to know why certain services are running.
-                try {
-                    clientIntent = (PendingIntent)service.getParcelableExtra(
-                            Intent.EXTRA_CLIENT_INTENT);
-                } catch (RuntimeException e) {
-                }
-                if (clientIntent != null) {
-                    clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
-                    if (clientLabel != 0) {
-                        // There are no useful extras in the intent, trash them.
-                        // System code calling with this stuff just needs to know
-                        // this will happen.
-                        service = service.cloneFilter();
-                    }
-                }
-            }
-            
-            ServiceLookupResult res =
-                retrieveServiceLocked(service, resolvedType,
-                        Binder.getCallingPid(), Binder.getCallingUid(), userId);
-            if (res == null) {
-                return 0;
-            }
-            if (res.record == null) {
-                return -1;
-            }
-            if (isSingleton(res.record.processName, res.record.appInfo)) {
-                userId = 0;
-                res = retrieveServiceLocked(service, resolvedType, Binder.getCallingPid(),
-                        Binder.getCallingUid(), 0);
-            }
-            ServiceRecord s = res.record;
-
-            final long origId = Binder.clearCallingIdentity();
-
-            if (unscheduleServiceRestartLocked(s)) {
-                if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
-                        + s);
-            }
-
-            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
-            ConnectionRecord c = new ConnectionRecord(b, activity,
-                    connection, flags, clientLabel, clientIntent);
-
-            IBinder binder = connection.asBinder();
-            ArrayList<ConnectionRecord> clist = s.connections.get(binder);
-            if (clist == null) {
-                clist = new ArrayList<ConnectionRecord>();
-                s.connections.put(binder, clist);
-            }
-            clist.add(c);
-            b.connections.add(c);
-            if (activity != null) {
-                if (activity.connections == null) {
-                    activity.connections = new HashSet<ConnectionRecord>();
-                }
-                activity.connections.add(c);
-            }
-            b.client.connections.add(c);
-            if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
-                b.client.hasAboveClient = true;
-            }
-            clist = mServiceConnections.get(binder);
-            if (clist == null) {
-                clist = new ArrayList<ConnectionRecord>();
-                mServiceConnections.put(binder, clist);
-            }
-            clist.add(c);
-
-            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
-                s.lastActivity = SystemClock.uptimeMillis();
-                if (!bringUpServiceLocked(s, service.getFlags(), false)) {
-                    return 0;
-                }
-            }
-
-            if (s.app != null) {
-                // This could have made the service more important.
-                updateOomAdjLocked(s.app);
-            }
-
-            if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
-                    + ": received=" + b.intent.received
-                    + " apps=" + b.intent.apps.size()
-                    + " doRebind=" + b.intent.doRebind);
-
-            if (s.app != null && b.intent.received) {
-                // Service is already running, so we can immediately
-                // publish the connection.
-                try {
-                    c.conn.connected(s.name, b.intent.binder);
-                } catch (Exception e) {
-                    Slog.w(TAG, "Failure sending service " + s.shortName
-                            + " to connection " + c.conn.asBinder()
-                            + " (in " + c.binding.client.processName + ")", e);
-                }
-
-                // If this is the first app connected back to this binding,
-                // and the service had previously asked to be told when
-                // rebound, then do so.
-                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
-                    requestServiceBindingLocked(s, b.intent, true);
-                }
-            } else if (!b.intent.requested) {
-                requestServiceBindingLocked(s, b.intent, false);
-            }
-
-            Binder.restoreCallingIdentity(origId);
-        }
-
-        return 1;
-    }
-
-    void removeConnectionLocked(
-        ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
-        IBinder binder = c.conn.asBinder();
-        AppBindRecord b = c.binding;
-        ServiceRecord s = b.service;
-        ArrayList<ConnectionRecord> clist = s.connections.get(binder);
-        if (clist != null) {
-            clist.remove(c);
-            if (clist.size() == 0) {
-                s.connections.remove(binder);
-            }
-        }
-        b.connections.remove(c);
-        if (c.activity != null && c.activity != skipAct) {
-            if (c.activity.connections != null) {
-                c.activity.connections.remove(c);
-            }
-        }
-        if (b.client != skipApp) {
-            b.client.connections.remove(c);
-            if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
-                b.client.updateHasAboveClientLocked();
-            }
-        }
-        clist = mServiceConnections.get(binder);
-        if (clist != null) {
-            clist.remove(c);
-            if (clist.size() == 0) {
-                mServiceConnections.remove(binder);
-            }
-        }
-
-        if (b.connections.size() == 0) {
-            b.intent.apps.remove(b.client);
-        }
-
-        if (!c.serviceDead) {
-            if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
-                    + ": shouldUnbind=" + b.intent.hasBound);
-            if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
-                    && b.intent.hasBound) {
-                try {
-                    bumpServiceExecutingLocked(s, "unbind");
-                    updateOomAdjLocked(s.app);
-                    b.intent.hasBound = false;
-                    // Assume the client doesn't want to know about a rebind;
-                    // we will deal with that later if it asks for one.
-                    b.intent.doRebind = false;
-                    s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
-                } catch (Exception e) {
-                    Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
-                    serviceDoneExecutingLocked(s, true);
-                }
-            }
-    
-            if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
-                bringDownServiceLocked(s, false);
-            }
+            return mServices.bindServiceLocked(caller, token, service, resolvedType,
+                    connection, flags, userId);
         }
     }
 
     public boolean unbindService(IServiceConnection connection) {
         synchronized (this) {
-            IBinder binder = connection.asBinder();
-            if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
-            ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
-            if (clist == null) {
-                Slog.w(TAG, "Unbind failed: could not find connection for "
-                      + connection.asBinder());
-                return false;
-            }
-
-            final long origId = Binder.clearCallingIdentity();
-
-            while (clist.size() > 0) {
-                ConnectionRecord r = clist.get(0);
-                removeConnectionLocked(r, null, null);
-
-                if (r.binding.service.app != null) {
-                    // This could have made the service less important.
-                    updateOomAdjLocked(r.binding.service.app);
-                }
-            }
-
-            Binder.restoreCallingIdentity(origId);
+            return mServices.unbindServiceLocked(connection);
         }
-
-        return true;
     }
 
     public void publishService(IBinder token, Intent intent, IBinder service) {
@@ -12262,53 +11087,7 @@
             if (!(token instanceof ServiceRecord)) {
                 throw new IllegalArgumentException("Invalid service token");
             }
-            ServiceRecord r = (ServiceRecord)token;
-
-            final long origId = Binder.clearCallingIdentity();
-
-            if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
-                    + " " + intent + ": " + service);
-            if (r != null) {
-                Intent.FilterComparison filter
-                        = new Intent.FilterComparison(intent);
-                IntentBindRecord b = r.bindings.get(filter);
-                if (b != null && !b.received) {
-                    b.binder = service;
-                    b.requested = true;
-                    b.received = true;
-                    if (r.connections.size() > 0) {
-                        Iterator<ArrayList<ConnectionRecord>> it
-                                = r.connections.values().iterator();
-                        while (it.hasNext()) {
-                            ArrayList<ConnectionRecord> clist = it.next();
-                            for (int i=0; i<clist.size(); i++) {
-                                ConnectionRecord c = clist.get(i);
-                                if (!filter.equals(c.binding.intent.intent)) {
-                                    if (DEBUG_SERVICE) Slog.v(
-                                            TAG, "Not publishing to: " + c);
-                                    if (DEBUG_SERVICE) Slog.v(
-                                            TAG, "Bound intent: " + c.binding.intent.intent);
-                                    if (DEBUG_SERVICE) Slog.v(
-                                            TAG, "Published intent: " + intent);
-                                    continue;
-                                }
-                                if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
-                                try {
-                                    c.conn.connected(r.name, service);
-                                } catch (Exception e) {
-                                    Slog.w(TAG, "Failure sending service " + r.name +
-                                          " to connection " + c.conn.asBinder() +
-                                          " (in " + c.binding.client.processName + ")", e);
-                                }
-                            }
-                        }
-                    }
-                }
-
-                serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
-
-                Binder.restoreCallingIdentity(origId);
-            }
+            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
         }
     }
 
@@ -12319,38 +11098,7 @@
         }
 
         synchronized(this) {
-            if (!(token instanceof ServiceRecord)) {
-                throw new IllegalArgumentException("Invalid service token");
-            }
-            ServiceRecord r = (ServiceRecord)token;
-
-            final long origId = Binder.clearCallingIdentity();
-
-            if (r != null) {
-                Intent.FilterComparison filter
-                        = new Intent.FilterComparison(intent);
-                IntentBindRecord b = r.bindings.get(filter);
-                if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
-                        + " at " + b + ": apps="
-                        + (b != null ? b.apps.size() : 0));
-
-                boolean inStopping = mStoppingServices.contains(r);
-                if (b != null) {
-                    if (b.apps.size() > 0 && !inStopping) {
-                        // Applications have already bound since the last
-                        // unbind, so just rebind right here.
-                        requestServiceBindingLocked(r, b, true);
-                    } else {
-                        // Note to tell the service the next time there is
-                        // a new client.
-                        b.doRebind = true;
-                    }
-                }
-
-                serviceDoneExecutingLocked(r, inStopping);
-
-                Binder.restoreCallingIdentity(origId);
-            }
+            mServices.unbindFinishedLocked((ServiceRecord)token, intent, doRebind);
         }
     }
 
@@ -12359,137 +11107,7 @@
             if (!(token instanceof ServiceRecord)) {
                 throw new IllegalArgumentException("Invalid service token");
             }
-            ServiceRecord r = (ServiceRecord)token;
-            boolean inStopping = mStoppingServices.contains(token);
-            if (r != null) {
-                if (r != token) {
-                    Slog.w(TAG, "Done executing service " + r.name
-                          + " with incorrect token: given " + token
-                          + ", expected " + r);
-                    return;
-                }
-
-                if (type == 1) {
-                    // This is a call from a service start...  take care of
-                    // book-keeping.
-                    r.callStart = true;
-                    switch (res) {
-                        case Service.START_STICKY_COMPATIBILITY:
-                        case Service.START_STICKY: {
-                            // We are done with the associated start arguments.
-                            r.findDeliveredStart(startId, true);
-                            // Don't stop if killed.
-                            r.stopIfKilled = false;
-                            break;
-                        }
-                        case Service.START_NOT_STICKY: {
-                            // We are done with the associated start arguments.
-                            r.findDeliveredStart(startId, true);
-                            if (r.getLastStartId() == startId) {
-                                // There is no more work, and this service
-                                // doesn't want to hang around if killed.
-                                r.stopIfKilled = true;
-                            }
-                            break;
-                        }
-                        case Service.START_REDELIVER_INTENT: {
-                            // We'll keep this item until they explicitly
-                            // call stop for it, but keep track of the fact
-                            // that it was delivered.
-                            ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
-                            if (si != null) {
-                                si.deliveryCount = 0;
-                                si.doneExecutingCount++;
-                                // Don't stop if killed.
-                                r.stopIfKilled = true;
-                            }
-                            break;
-                        }
-                        case Service.START_TASK_REMOVED_COMPLETE: {
-                            // Special processing for onTaskRemoved().  Don't
-                            // impact normal onStartCommand() processing.
-                            r.findDeliveredStart(startId, true);
-                            break;
-                        }
-                        default:
-                            throw new IllegalArgumentException(
-                                    "Unknown service start result: " + res);
-                    }
-                    if (res == Service.START_STICKY_COMPATIBILITY) {
-                        r.callStart = false;
-                    }
-                }
-                if (DEBUG_MU)
-                    Slog.v(TAG_MU, "before serviceDontExecutingLocked, uid="
-                            + Binder.getOrigCallingUid());
-                final long origId = Binder.clearCallingIdentity();
-                serviceDoneExecutingLocked(r, inStopping);
-                Binder.restoreCallingIdentity(origId);
-            } else {
-                Slog.w(TAG, "Done executing unknown service from pid "
-                        + Binder.getCallingPid());
-            }
-        }
-    }
-
-    public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
-        if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
-                + ": nesting=" + r.executeNesting
-                + ", inStopping=" + inStopping + ", app=" + r.app);
-        else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
-        r.executeNesting--;
-        if (r.executeNesting <= 0 && r.app != null) {
-            if (DEBUG_SERVICE) Slog.v(TAG,
-                    "Nesting at 0 of " + r.shortName);
-            r.app.executingServices.remove(r);
-            if (r.app.executingServices.size() == 0) {
-                if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
-                        "No more executingServices of " + r.shortName);
-                mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
-            }
-            if (inStopping) {
-                if (DEBUG_SERVICE) Slog.v(TAG,
-                        "doneExecuting remove stopping " + r);
-                mStoppingServices.remove(r);
-                r.bindings.clear();
-            }
-            updateOomAdjLocked(r.app);
-        }
-    }
-
-    void serviceTimeout(ProcessRecord proc) {
-        String anrMessage = null;
-        
-        synchronized(this) {
-            if (proc.executingServices.size() == 0 || proc.thread == null) {
-                return;
-            }
-            long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
-            Iterator<ServiceRecord> it = proc.executingServices.iterator();
-            ServiceRecord timeout = null;
-            long nextTime = 0;
-            while (it.hasNext()) {
-                ServiceRecord sr = it.next();
-                if (sr.executingStart < maxTime) {
-                    timeout = sr;
-                    break;
-                }
-                if (sr.executingStart > nextTime) {
-                    nextTime = sr.executingStart;
-                }
-            }
-            if (timeout != null && mLruProcesses.contains(proc)) {
-                Slog.w(TAG, "Timeout executing service: " + timeout);
-                anrMessage = "Executing service " + timeout.shortName;
-            } else {
-                Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
-                msg.obj = proc;
-                mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
-            }
-        }
-        
-        if (anrMessage != null) {
-            appNotResponding(proc, null, null, anrMessage);
+            mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
         }
     }
     
@@ -12501,8 +11119,8 @@
     // instantiated.  The backup agent will invoke backupAgentCreated() on the
     // activity manager to announce its creation.
     public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
-        if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
-        enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
+        if (DEBUG_BACKUP) Slog.v(TAG, "bindBackupAgent: app=" + app + " mode=" + backupMode);
+        enforceCallingPermission("android.permission.BACKUP", "bindBackupAgent");
 
         synchronized(this) {
             // !!! TODO: currently no check here that we're already bound
@@ -12515,7 +11133,7 @@
             // Backup agent is now in use, its package can't be stopped.
             try {
                 AppGlobals.getPackageManager().setPackageStoppedState(
-                        app.packageName, false, UserId.getUserId(app.uid));
+                        app.packageName, false, UserHandle.getUserId(app.uid));
             } catch (RemoteException e) {
             } catch (IllegalArgumentException e) {
                 Slog.w(TAG, "Failed trying to unstop package "
@@ -12563,6 +11181,17 @@
         return true;
     }
 
+    @Override
+    public void clearPendingBackup() {
+        if (DEBUG_BACKUP) Slog.v(TAG, "clearPendingBackup");
+        enforceCallingPermission("android.permission.BACKUP", "clearPendingBackup");
+
+        synchronized (this) {
+            mBackupTarget = null;
+            mBackupAppName = null;
+        }
+    }
+
     // A backup agent has just come up                    
     public void backupAgentCreated(String agentPackageName, IBinder agent) {
         if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
@@ -12599,32 +11228,34 @@
         }
 
         synchronized(this) {
-            if (mBackupAppName == null) {
-                Slog.w(TAG, "Unbinding backup agent with no active backup");
-                return;
-            }
-
-            if (!mBackupAppName.equals(appInfo.packageName)) {
-                Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
-                return;
-            }
-
-            ProcessRecord proc = mBackupTarget.app;
-            mBackupTarget = null;
-            mBackupAppName = null;
-
-            // Not backing this app up any more; reset its OOM adjustment
-            updateOomAdjLocked(proc);
-
-            // If the app crashed during backup, 'thread' will be null here
-            if (proc.thread != null) {
-                try {
-                    proc.thread.scheduleDestroyBackupAgent(appInfo,
-                            compatibilityInfoForPackageLocked(appInfo));
-                } catch (Exception e) {
-                    Slog.e(TAG, "Exception when unbinding backup agent:");
-                    e.printStackTrace();
+            try {
+                if (mBackupAppName == null) {
+                    Slog.w(TAG, "Unbinding backup agent with no active backup");
+                    return;
                 }
+
+                if (!mBackupAppName.equals(appInfo.packageName)) {
+                    Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
+                    return;
+                }
+
+                // Not backing this app up any more; reset its OOM adjustment
+                final ProcessRecord proc = mBackupTarget.app;
+                updateOomAdjLocked(proc);
+
+                // If the app crashed during backup, 'thread' will be null here
+                if (proc.thread != null) {
+                    try {
+                        proc.thread.scheduleDestroyBackupAgent(appInfo,
+                                compatibilityInfoForPackageLocked(appInfo));
+                    } catch (Exception e) {
+                        Slog.e(TAG, "Exception when unbinding backup agent:");
+                        e.printStackTrace();
+                    }
+                }
+            } finally {
+                mBackupTarget = null;
+                mBackupAppName = null;
             }
         }
     }
@@ -12633,9 +11264,13 @@
     // =========================================================
 
     private final List getStickiesLocked(String action, IntentFilter filter,
-            List cur) {
+            List cur, int userId) {
         final ContentResolver resolver = mContext.getContentResolver();
-        final ArrayList<Intent> list = mStickyBroadcasts.get(action);
+        HashMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
+        if (stickies == null) {
+            return cur;
+        }
+        final ArrayList<Intent> list = stickies.get(action);
         if (list == null) {
             return cur;
         }
@@ -12674,8 +11309,10 @@
     }
 
     public Intent registerReceiver(IApplicationThread caller, String callerPackage,
-            IIntentReceiver receiver, IntentFilter filter, String permission) {
+            IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
         enforceNotIsolatedCaller("registerReceiver");
+        int callingUid;
+        int callingPid;
         synchronized(this) {
             ProcessRecord callerApp = null;
             if (caller != null) {
@@ -12691,10 +11328,17 @@
                     throw new SecurityException("Given caller package " + callerPackage
                             + " is not running in process " + callerApp);
                 }
+                callingUid = callerApp.info.uid;
+                callingPid = callerApp.pid;
             } else {
                 callerPackage = null;
+                callingUid = Binder.getCallingUid();
+                callingPid = Binder.getCallingPid();
             }
 
+            userId = this.handleIncomingUser(callingPid, callingUid, userId,
+                    true, true, "registerReceiver", callerPackage);
+
             List allSticky = null;
 
             // Look for any matching sticky broadcasts...
@@ -12702,10 +11346,16 @@
             if (actions != null) {
                 while (actions.hasNext()) {
                     String action = (String)actions.next();
-                    allSticky = getStickiesLocked(action, filter, allSticky);
+                    allSticky = getStickiesLocked(action, filter, allSticky,
+                            UserHandle.USER_ALL);
+                    allSticky = getStickiesLocked(action, filter, allSticky,
+                            UserHandle.getUserId(callingUid));
                 }
             } else {
-                allSticky = getStickiesLocked(null, filter, allSticky);
+                allSticky = getStickiesLocked(null, filter, allSticky,
+                        UserHandle.USER_ALL);
+                allSticky = getStickiesLocked(null, filter, allSticky,
+                        UserHandle.getUserId(callingUid));
             }
 
             // The first sticky in the list is returned directly back to
@@ -12722,9 +11372,8 @@
             ReceiverList rl
                 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
             if (rl == null) {
-                rl = new ReceiverList(this, callerApp,
-                        Binder.getCallingPid(),
-                        Binder.getCallingUid(), receiver);
+                rl = new ReceiverList(this, callerApp, callingPid, callingUid,
+                        userId, receiver);
                 if (rl.app != null) {
                     rl.app.receivers.add(rl);
                 } else {
@@ -12736,8 +11385,21 @@
                     rl.linkedToDeath = true;
                 }
                 mRegisteredReceivers.put(receiver.asBinder(), rl);
+            } else if (rl.uid != callingUid) {
+                throw new IllegalArgumentException(
+                        "Receiver requested to register for uid " + callingUid
+                        + " was previously registered for uid " + rl.uid);
+            } else if (rl.pid != callingPid) {
+                throw new IllegalArgumentException(
+                        "Receiver requested to register for pid " + callingPid
+                        + " was previously registered for pid " + rl.pid);
+            } else if (rl.userId != userId) {
+                throw new IllegalArgumentException(
+                        "Receiver requested to register for user " + userId
+                        + " was previously registered for user " + rl.userId);
             }
-            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
+            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
+                    permission, callingUid, userId);
             rl.add(bf);
             if (!bf.debugCheck()) {
                 Slog.w(TAG, "==> For Dynamic broadast");
@@ -12756,7 +11418,7 @@
                     BroadcastQueue queue = broadcastQueueForIntent(intent);
                     BroadcastRecord r = new BroadcastRecord(queue, intent, null,
                             null, -1, -1, null, receivers, null, 0, null, null,
-                            false, true, true);
+                            false, true, true, -1);
                     queue.enqueueParallelBroadcastLocked(r);
                     queue.scheduleBroadcastsLocked();
                 }
@@ -12819,10 +11481,10 @@
         }
     }
     
-    private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
+    private final void sendPackageBroadcastLocked(int cmd, String[] packages, int userId) {
         for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
             ProcessRecord r = mLruProcesses.get(i);
-            if (r.thread != null) {
+            if (r.thread != null && (userId == UserHandle.USER_ALL || r.userId == userId)) {
                 try {
                     r.thread.dispatchPackageBroadcast(cmd, packages);
                 } catch (RemoteException ex) {
@@ -12830,7 +11492,78 @@
             }
         }
     }
-    
+
+    private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
+            int[] users) {
+        List<ResolveInfo> receivers = null;
+        try {
+            HashSet<ComponentName> singleUserReceivers = null;
+            boolean scannedFirstReceivers = false;
+            for (int user : users) {
+                List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
+                        .queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS, user);
+                if (user != 0 && newReceivers != null) {
+                    // If this is not the primary user, we need to check for
+                    // any receivers that should be filtered out.
+                    for (int i=0; i<newReceivers.size(); i++) {
+                        ResolveInfo ri = newReceivers.get(i);
+                        if ((ri.activityInfo.flags&ActivityInfo.FLAG_PRIMARY_USER_ONLY) != 0) {
+                            newReceivers.remove(i);
+                            i--;
+                        }
+                    }
+                }
+                if (newReceivers != null && newReceivers.size() == 0) {
+                    newReceivers = null;
+                }
+                if (receivers == null) {
+                    receivers = newReceivers;
+                } else if (newReceivers != null) {
+                    // We need to concatenate the additional receivers
+                    // found with what we have do far.  This would be easy,
+                    // but we also need to de-dup any receivers that are
+                    // singleUser.
+                    if (!scannedFirstReceivers) {
+                        // Collect any single user receivers we had already retrieved.
+                        scannedFirstReceivers = true;
+                        for (int i=0; i<receivers.size(); i++) {
+                            ResolveInfo ri = receivers.get(i);
+                            if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
+                                ComponentName cn = new ComponentName(
+                                        ri.activityInfo.packageName, ri.activityInfo.name);
+                                if (singleUserReceivers == null) {
+                                    singleUserReceivers = new HashSet<ComponentName>();
+                                }
+                                singleUserReceivers.add(cn);
+                            }
+                        }
+                    }
+                    // Add the new results to the existing results, tracking
+                    // and de-dupping single user receivers.
+                    for (int i=0; i<newReceivers.size(); i++) {
+                        ResolveInfo ri = newReceivers.get(i);
+                        if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
+                            ComponentName cn = new ComponentName(
+                                    ri.activityInfo.packageName, ri.activityInfo.name);
+                            if (singleUserReceivers == null) {
+                                singleUserReceivers = new HashSet<ComponentName>();
+                            }
+                            if (!singleUserReceivers.contains(cn)) {
+                                singleUserReceivers.add(cn);
+                                receivers.add(ri);
+                            }
+                        } else {
+                            receivers.add(ri);
+                        }
+                    }
+                }
+            }
+        } catch (RemoteException ex) {
+            // pm is in same process, this will never happen.
+        }
+        return receivers;
+    }
+
     private final int broadcastIntentLocked(ProcessRecord callerApp,
             String callerPackage, Intent intent, String resolvedType,
             IIntentReceiver resultTo, int resultCode, String resultData,
@@ -12848,7 +11581,46 @@
         if ((resultTo != null) && !ordered) {
             Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
         }
-        
+
+        userId = handleIncomingUser(callingPid, callingUid, userId,
+                true, false, "broadcast", callerPackage);
+
+        // Make sure that the user who is receiving this broadcast is started.
+        // If not, we will just skip it.
+        if (userId != UserHandle.USER_ALL && mStartedUsers.get(userId) == null) {
+            if (callingUid != Process.SYSTEM_UID || (intent.getFlags()
+                    & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
+                Slog.w(TAG, "Skipping broadcast of " + intent
+                        + ": user " + userId + " is stopped");
+                return ActivityManager.BROADCAST_SUCCESS;
+            }
+        }
+
+        /*
+         * Prevent non-system code (defined here to be non-persistent
+         * processes) from sending protected broadcasts.
+         */
+        int callingAppId = UserHandle.getAppId(callingUid);
+        if (callingAppId == Process.SYSTEM_UID || callingAppId == Process.PHONE_UID
+            || callingAppId == Process.SHELL_UID || callingAppId == Process.BLUETOOTH_UID ||
+            callingUid == 0) {
+            // Always okay.
+        } else if (callerApp == null || !callerApp.persistent) {
+            try {
+                if (AppGlobals.getPackageManager().isProtectedBroadcast(
+                        intent.getAction())) {
+                    String msg = "Permission Denial: not allowed to send broadcast "
+                            + intent.getAction() + " from pid="
+                            + callingPid + ", uid=" + callingUid;
+                    Slog.w(TAG, msg);
+                    throw new SecurityException(msg);
+                }
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Remote exception", e);
+                return ActivityManager.BROADCAST_SUCCESS;
+            }
+        }
+
         // Handle special intents: if this broadcast is from the package
         // manager about a package being removed, we need to remove all of
         // its activities from the history stack.
@@ -12873,7 +11645,7 @@
                         }
                     }
                 } else {
-                    // If resources are unvailble just force stop all
+                    // If resources are unavailable just force stop all
                     // those packages and flush the attribute cache as well.
                     if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
                         String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
@@ -12882,7 +11654,7 @@
                                 forceStopPackageLocked(pkg, -1, false, true, true, false, userId);
                             }
                             sendPackageBroadcastLocked(
-                                    IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
+                                    IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list, userId);
                         }
                     } else {
                         Uri data = intent.getData();
@@ -12895,7 +11667,7 @@
                             }
                             if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
                                 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
-                                        new String[] {ssp});
+                                        new String[] {ssp}, userId);
                             }
                         }
                     }
@@ -12939,29 +11711,6 @@
             mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
         }
 
-        /*
-         * Prevent non-system code (defined here to be non-persistent
-         * processes) from sending protected broadcasts.
-         */
-        if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
-                || callingUid == Process.SHELL_UID || callingUid == 0) {
-            // Always okay.
-        } else if (callerApp == null || !callerApp.persistent) {
-            try {
-                if (AppGlobals.getPackageManager().isProtectedBroadcast(
-                        intent.getAction())) {
-                    String msg = "Permission Denial: not allowed to send broadcast "
-                            + intent.getAction() + " from pid="
-                            + callingPid + ", uid=" + callingUid;
-                    Slog.w(TAG, msg);
-                    throw new SecurityException(msg);
-                }
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Remote exception", e);
-                return ActivityManager.BROADCAST_SUCCESS;
-            }
-        }
-        
         // Add to the sticky list if requested.
         if (sticky) {
             if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
@@ -12982,10 +11731,38 @@
                 throw new SecurityException(
                         "Sticky broadcasts can't target a specific component");
             }
-            ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
+            // We use userId directly here, since the "all" target is maintained
+            // as a separate set of sticky broadcasts.
+            if (userId != UserHandle.USER_ALL) {
+                // But first, if this is not a broadcast to all users, then
+                // make sure it doesn't conflict with an existing broadcast to
+                // all users.
+                HashMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(
+                        UserHandle.USER_ALL);
+                if (stickies != null) {
+                    ArrayList<Intent> list = stickies.get(intent.getAction());
+                    if (list != null) {
+                        int N = list.size();
+                        int i;
+                        for (i=0; i<N; i++) {
+                            if (intent.filterEquals(list.get(i))) {
+                                throw new IllegalArgumentException(
+                                        "Sticky broadcast " + intent + " for user "
+                                        + userId + " conflicts with existing global broadcast");
+                            }
+                        }
+                    }
+                }
+            }
+            HashMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
+            if (stickies == null) {
+                stickies = new HashMap<String, ArrayList<Intent>>();
+                mStickyBroadcasts.put(userId, stickies);
+            }
+            ArrayList<Intent> list = stickies.get(intent.getAction());
             if (list == null) {
                 list = new ArrayList<Intent>();
-                mStickyBroadcasts.put(intent.getAction(), list);
+                stickies.put(intent.getAction(), list);
             }
             int N = list.size();
             int i;
@@ -13001,37 +11778,26 @@
             }
         }
 
+        int[] users;
+        if (userId == UserHandle.USER_ALL) {
+            // Caller wants broadcast to go to all started users.
+            users = mStartedUserArray;
+        } else {
+            // Caller wants broadcast to go to one specific user.
+            users = new int[] {userId};
+        }
+
         // Figure out who all will receive this broadcast.
         List receivers = null;
         List<BroadcastFilter> registeredReceivers = null;
-        try {
-            if (intent.getComponent() != null) {
-                // Broadcast is going to one specific receiver class...
-                ActivityInfo ai = AppGlobals.getPackageManager().
-                        getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS, userId);
-                if (ai != null) {
-                    receivers = new ArrayList();
-                    ResolveInfo ri = new ResolveInfo();
-                    if (isSingleton(ai.processName, ai.applicationInfo)) {
-                        ri.activityInfo = getActivityInfoForUser(ai, 0);
-                    } else {
-                        ri.activityInfo = getActivityInfoForUser(ai, userId);
-                    }
-                    receivers.add(ri);
-                }
-            } else {
-                // 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, userId);
-                }
-                registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false,
-                        userId);
-            }
-        } catch (RemoteException ex) {
-            // pm is in same process, this will never happen.
+        // Need to resolve the intent to interested receivers...
+        if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
+                 == 0) {
+            receivers = collectReceiverComponents(intent, resolvedType, users);
+        }
+        if (intent.getComponent() == null) {
+            registeredReceivers = mReceiverResolver.queryIntent(intent,
+                    resolvedType, false, userId);
         }
 
         final boolean replacePending =
@@ -13049,7 +11815,7 @@
             BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                     callerPackage, callingPid, callingUid, requiredPermission,
                     registeredReceivers, resultTo, resultCode, resultData, map,
-                    ordered, sticky, false);
+                    ordered, sticky, false, userId);
             if (DEBUG_BROADCAST) Slog.v(
                     TAG, "Enqueueing parallel broadcast " + r);
             final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
@@ -13139,7 +11905,7 @@
             BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                     callerPackage, callingPid, callingUid, requiredPermission,
                     receivers, resultTo, resultCode, resultData, map, ordered,
-                    sticky, false);
+                    sticky, false, userId);
             if (DEBUG_BROADCAST) Slog.v(
                     TAG, "Enqueueing ordered broadcast " + r
                     + ": prev had " + queue.mOrderedBroadcasts.size());
@@ -13224,13 +11990,15 @@
         }
     }
 
-    // TODO: Use the userId; maybe mStickyBroadcasts need to be tied to the user.
     public final void unbroadcastIntent(IApplicationThread caller, Intent intent, int userId) {
         // Refuse possible leaked file descriptors
         if (intent != null && intent.hasFileDescriptors() == true) {
             throw new IllegalArgumentException("File descriptors passed in Intent");
         }
 
+        userId = handleIncomingUser(Binder.getCallingPid(),
+                Binder.getCallingUid(), userId, true, false, "removeStickyBroadcast", null);
+
         synchronized(this) {
             if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
                     != PackageManager.PERMISSION_GRANTED) {
@@ -13241,15 +12009,24 @@
                 Slog.w(TAG, msg);
                 throw new SecurityException(msg);
             }
-            ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
-            if (list != null) {
-                int N = list.size();
-                int i;
-                for (i=0; i<N; i++) {
-                    if (intent.filterEquals(list.get(i))) {
-                        list.remove(i);
-                        break;
+            HashMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
+            if (stickies != null) {
+                ArrayList<Intent> list = stickies.get(intent.getAction());
+                if (list != null) {
+                    int N = list.size();
+                    int i;
+                    for (i=0; i<N; i++) {
+                        if (intent.filterEquals(list.get(i))) {
+                            list.remove(i);
+                            break;
+                        }
                     }
+                    if (list.size() <= 0) {
+                        stickies.remove(intent.getAction());
+                    }
+                }
+                if (stickies.size() <= 0) {
+                    mStickyBroadcasts.remove(userId);
                 }
             }
         }
@@ -13305,8 +12082,10 @@
 
     public boolean startInstrumentation(ComponentName className,
             String profileFile, int flags, Bundle arguments,
-            IInstrumentationWatcher watcher) {
+            IInstrumentationWatcher watcher, int userId) {
         enforceNotIsolatedCaller("startInstrumentation");
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+                userId, false, true, "startInstrumentation", null);
         // Refuse possible leaked file descriptors
         if (arguments != null && arguments.hasFileDescriptors()) {
             throw new IllegalArgumentException("File descriptors passed in Bundle");
@@ -13318,9 +12097,10 @@
             try {
                 ii = mContext.getPackageManager().getInstrumentationInfo(
                     className, STOCK_PM_FLAGS);
-                ai = mContext.getPackageManager().getApplicationInfo(
-                        ii.targetPackage, STOCK_PM_FLAGS);
+                ai = AppGlobals.getPackageManager().getApplicationInfo(
+                        ii.targetPackage, STOCK_PM_FLAGS, userId);
             } catch (PackageManager.NameNotFoundException e) {
+            } catch (RemoteException e) {
             }
             if (ii == null) {
                 reportStartInstrumentationFailure(watcher, className,
@@ -13347,7 +12127,6 @@
                 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, userId);
@@ -13405,12 +12184,12 @@
         app.instrumentationProfileFile = null;
         app.instrumentationArguments = null;
 
-        forceStopPackageLocked(app.processName, -1, false, false, true, true, app.userId);
+        forceStopPackageLocked(app.info.packageName, -1, false, false, true, true, app.userId);
     }
 
     public void finishInstrumentation(IApplicationThread target,
             int resultCode, Bundle results) {
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
         // Refuse possible leaked file descriptors
         if (results != null && results.hasFileDescriptors()) {
             throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -13578,14 +12357,16 @@
                 }
                 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
-                        | Intent.FLAG_RECEIVER_REPLACE_PENDING);
+                        | Intent.FLAG_RECEIVER_REPLACE_PENDING
+                        | Intent.FLAG_RECEIVER_FOREGROUND);
                 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
-                        null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
+                        null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
                 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
-                    broadcastIntentLocked(null, null,
-                            new Intent(Intent.ACTION_LOCALE_CHANGED),
+                    intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
+                    intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+                    broadcastIntentLocked(null, null, intent,
                             null, null, 0, null, null,
-                            null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
+                            null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
                 }
             }
         }
@@ -13706,7 +12487,7 @@
             for (int i = start; i > finishTo; i--) {
                 ActivityRecord r = history.get(i);
                 mMainStack.requestFinishActivityLocked(r.appToken, resultCode, resultData,
-                        "navigate-up");
+                        "navigate-up", true);
                 // Only return the supplied result for the first activity finished
                 resultCode = Activity.RESULT_CANCELED;
                 resultData = null;
@@ -13723,7 +12504,7 @@
                 } else {
                     try {
                         ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
-                                destIntent.getComponent(), 0, UserId.getCallingUserId());
+                                destIntent.getComponent(), 0, srec.userId);
                         int res = mMainStack.startActivityLocked(srec.app.thread, destIntent,
                                 null, aInfo, parent.appToken, null,
                                 0, -1, parent.launchedFromUid, 0, null, true, null);
@@ -13732,7 +12513,7 @@
                         foundParentInTask = false;
                     }
                     mMainStack.requestFinishActivityLocked(parent.appToken, resultCode,
-                            resultData, "navigate-up");
+                            resultData, "navigate-up", true);
                 }
             }
             Binder.restoreCallingIdentity(origId);
@@ -13774,15 +12555,21 @@
         return null;
     }
 
-    private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
-            ProcessRecord TOP_APP, boolean recursed, boolean doingAll) {
+    private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj, int clientHiddenAdj,
+            int emptyAdj, ProcessRecord TOP_APP, boolean recursed, boolean doingAll) {
         if (mAdjSeq == app.adjSeq) {
             // This adjustment has already been computed.  If we are calling
             // from the top, we may have already computed our adjustment with
             // an earlier hidden adjustment that isn't really for us... if
             // so, use the new hidden adjustment.
             if (!recursed && app.hidden) {
-                app.curAdj = app.curRawAdj = app.nonStoppingAdj = hiddenAdj;
+                if (app.hasActivities) {
+                    app.curAdj = app.curRawAdj = app.nonStoppingAdj = hiddenAdj;
+                } else if (app.hasClientActivities) {
+                    app.curAdj = app.curRawAdj = app.nonStoppingAdj = clientHiddenAdj;
+                } else {
+                    app.curAdj = app.curRawAdj = app.nonStoppingAdj = emptyAdj;
+                }
             }
             return app.curRawAdj;
         }
@@ -13790,7 +12577,7 @@
         if (app.thread == null) {
             app.adjSeq = mAdjSeq;
             app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
-            return (app.curAdj=ProcessList.HIDDEN_APP_MAX_ADJ);
+            return (app.curAdj=app.curRawAdj=ProcessList.HIDDEN_APP_MAX_ADJ);
         }
 
         app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
@@ -13798,6 +12585,7 @@
         app.adjTarget = null;
         app.empty = false;
         app.hidden = false;
+        app.hasClientActivities = false;
 
         final int activitiesSize = app.activities.size();
 
@@ -13807,6 +12595,7 @@
             app.adjType = "fixed";
             app.adjSeq = mAdjSeq;
             app.curRawAdj = app.nonStoppingAdj = app.maxAdj;
+            app.hasActivities = false;
             app.foregroundActivities = false;
             app.keeping = true;
             app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
@@ -13817,12 +12606,15 @@
             app.systemNoUi = true;
             if (app == TOP_APP) {
                 app.systemNoUi = false;
+                app.hasActivities = true;
             } else if (activitiesSize > 0) {
                 for (int j = 0; j < activitiesSize; j++) {
                     final ActivityRecord r = app.activities.get(j);
                     if (r.visible) {
                         app.systemNoUi = false;
-                        break;
+                    }
+                    if (r.app == app) {
+                        app.hasActivities = true;
                     }
                 }
             }
@@ -13831,6 +12623,7 @@
 
         app.keeping = false;
         app.systemNoUi = false;
+        app.hasActivities = false;
 
         // Determine the importance of the process, starting with most
         // important to least, and assign an appropriate OOM adjustment.
@@ -13846,6 +12639,7 @@
             app.adjType = "top-activity";
             foregroundActivities = true;
             interesting = true;
+            app.hasActivities = true;
         } else if (app.instrumentationClass != null) {
             // Don't want to kill running instrumentation.
             adj = ProcessList.FOREGROUND_APP_ADJ;
@@ -13867,21 +12661,13 @@
             adj = ProcessList.FOREGROUND_APP_ADJ;
             schedGroup = Process.THREAD_GROUP_DEFAULT;
             app.adjType = "exec-service";
-        } else if (activitiesSize > 0) {
-            // This app is in the background with paused activities.
-            // We inspect activities to potentially upgrade adjustment further below.
-            adj = hiddenAdj;
-            schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
-            app.hidden = true;
-            app.adjType = "bg-activities";
         } else {
-            // A very not-needed process.  If this is lower in the lru list,
-            // we will push it in to the empty bucket.
+            // Assume process is hidden (has activities); we will correct
+            // later if this is not the case.
             adj = hiddenAdj;
             schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
             app.hidden = true;
-            app.empty = true;
-            app.adjType = "bg-empty";
+            app.adjType = "bg-act";
         }
 
         boolean hasStoppingActivities = false;
@@ -13898,6 +12684,7 @@
                     }
                     schedGroup = Process.THREAD_GROUP_DEFAULT;
                     app.hidden = false;
+                    app.hasActivities = true;
                     foregroundActivities = true;
                     break;
                 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {
@@ -13915,6 +12702,22 @@
                     foregroundActivities = true;
                     hasStoppingActivities = true;
                 }
+                if (r.app == app) {
+                    app.hasActivities = true;
+                }
+            }
+        }
+
+        if (adj == hiddenAdj && !app.hasActivities) {
+            if (app.hasClientActivities) {
+                adj = clientHiddenAdj;
+                app.adjType = "bg-client-act";
+            } else {
+                // Whoops, this process is completely empty as far as we know
+                // at this point.
+                adj = emptyAdj;
+                app.empty = true;
+                app.adjType = "bg-empty";
             }
         }
 
@@ -13923,13 +12726,13 @@
                 // The user is aware of this app, so make it visible.
                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                 app.hidden = false;
-                app.adjType = "foreground-service";
+                app.adjType = "fg-service";
                 schedGroup = Process.THREAD_GROUP_DEFAULT;
             } else if (app.forcingToForeground != null) {
                 // The user is aware of this app, so make it visible.
                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                 app.hidden = false;
-                app.adjType = "force-foreground";
+                app.adjType = "force-fg";
                 app.adjSource = app.forcingToForeground;
                 schedGroup = Process.THREAD_GROUP_DEFAULT;
             }
@@ -14005,7 +12808,7 @@
                             app.adjType = "started-bg-ui-services";
                         }
                     } else {
-                        if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
+                        if (now < (s.lastActivity + ActiveServices.MAX_SERVICE_INACTIVITY)) {
                             // This service has seen some activity within
                             // recent memory, so we will keep its process ahead
                             // of the background processes.
@@ -14051,8 +12854,24 @@
                                         myHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
                                     }
                                 }
-                                clientAdj = computeOomAdjLocked(
-                                    client, myHiddenAdj, TOP_APP, true, doingAll);
+                                int myClientHiddenAdj = clientHiddenAdj;
+                                if (myClientHiddenAdj > client.clientHiddenAdj) {
+                                    if (client.clientHiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
+                                        myClientHiddenAdj = client.clientHiddenAdj;
+                                    } else {
+                                        myClientHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
+                                    }
+                                }
+                                int myEmptyAdj = emptyAdj;
+                                if (myEmptyAdj > client.emptyAdj) {
+                                    if (client.emptyAdj >= ProcessList.VISIBLE_APP_ADJ) {
+                                        myEmptyAdj = client.emptyAdj;
+                                    } else {
+                                        myEmptyAdj = ProcessList.VISIBLE_APP_ADJ;
+                                    }
+                                }
+                                clientAdj = computeOomAdjLocked(client, myHiddenAdj,
+                                        myClientHiddenAdj, myEmptyAdj, TOP_APP, true, doingAll);
                                 String adjType = null;
                                 if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
                                     // Not doing bind OOM management, so treat
@@ -14068,7 +12887,8 @@
                                         app.hidden = false;
                                         clientAdj = adj;
                                     } else {
-                                        if (now >= (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
+                                        if (now >= (s.lastActivity
+                                                + ActiveServices.MAX_SERVICE_INACTIVITY)) {
                                             // This service has not seen activity within
                                             // recent memory, so allow it to drop to the
                                             // LRU list if there is no other reason to keep
@@ -14080,6 +12900,19 @@
                                             clientAdj = adj;
                                         }
                                     }
+                                } else if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
+                                    if ((cr.flags&Context.BIND_NOT_VISIBLE) == 0) {
+                                        // If this connection is keeping the service
+                                        // created, then we want to try to better follow
+                                        // its memory management semantics for activities.
+                                        // That is, if it is sitting in the background
+                                        // LRU list as a hidden process (with activities),
+                                        // we don't want the service it is connected to
+                                        // to go into the empty LRU and quickly get killed,
+                                        // because I'll we'll do is just end up restarting
+                                        // the service.
+                                        app.hasClientActivities |= client.hasActivities;
+                                    }
                                 }
                                 if (adj > clientAdj) {
                                     // If this process has recently shown UI, and
@@ -14131,8 +12964,8 @@
                                     }
                                 }
                             }
+                            final ActivityRecord a = cr.activity;
                             if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
-                                ActivityRecord a = cr.activity;
                                 if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
                                         (a.visible || a.state == ActivityState.RESUMED
                                          || a.state == ActivityState.PAUSING)) {
@@ -14190,8 +13023,24 @@
                             myHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
                         }
                     }
-                    int clientAdj = computeOomAdjLocked(
-                        client, myHiddenAdj, TOP_APP, true, doingAll);
+                    int myClientHiddenAdj = clientHiddenAdj;
+                    if (myClientHiddenAdj > client.clientHiddenAdj) {
+                        if (client.clientHiddenAdj >= ProcessList.FOREGROUND_APP_ADJ) {
+                            myClientHiddenAdj = client.clientHiddenAdj;
+                        } else {
+                            myClientHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
+                        }
+                    }
+                    int myEmptyAdj = emptyAdj;
+                    if (myEmptyAdj > client.emptyAdj) {
+                        if (client.emptyAdj > ProcessList.FOREGROUND_APP_ADJ) {
+                            myEmptyAdj = client.emptyAdj;
+                        } else {
+                            myEmptyAdj = ProcessList.FOREGROUND_APP_ADJ;
+                        }
+                    }
+                    int clientAdj = computeOomAdjLocked(client, myHiddenAdj,
+                            myClientHiddenAdj, myEmptyAdj, TOP_APP, true, doingAll);
                     if (adj > clientAdj) {
                         if (app.hasShownUi && app != mHomeProcess
                                 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
@@ -14581,7 +13430,7 @@
                     Slog.w(TAG, "Excessive wake lock in " + app.processName
                             + " (pid " + app.pid + "): held " + wtimeUsed
                             + " during " + realtimeSince);
-                    EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
+                    EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
                             app.processName, app.setAdj, "excessive wake lock");
                     Process.killProcessQuiet(app.pid);
                 } else if (doCpuKills && uptimeSince > 0
@@ -14593,7 +13442,7 @@
                     Slog.w(TAG, "Excessive CPU in " + app.processName
                             + " (pid " + app.pid + "): used " + cputimeUsed
                             + " during " + uptimeSince);
-                    EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
+                    EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
                             app.processName, app.setAdj, "excessive cpu");
                     Process.killProcessQuiet(app.pid);
                 } else {
@@ -14604,9 +13453,11 @@
         }
     }
 
-    private final boolean updateOomAdjLocked(
-            ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP, boolean doingAll) {
+    private final boolean updateOomAdjLocked(ProcessRecord app, int hiddenAdj,
+            int clientHiddenAdj, int emptyAdj, ProcessRecord TOP_APP, boolean doingAll) {
         app.hiddenAdj = hiddenAdj;
+        app.clientHiddenAdj = clientHiddenAdj;
+        app.emptyAdj = emptyAdj;
 
         if (app.thread == null) {
             return false;
@@ -14616,7 +13467,7 @@
 
         boolean success = true;
 
-        computeOomAdjLocked(app, hiddenAdj, TOP_APP, false, doingAll);
+        computeOomAdjLocked(app, hiddenAdj, clientHiddenAdj, emptyAdj, TOP_APP, false, doingAll);
 
         if (app.curRawAdj != app.setRawAdj) {
             if (wasKeeping && !app.keeping) {
@@ -14653,7 +13504,7 @@
             if (app.waitingToKill != null &&
                     app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
                 Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
-                EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
+                EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
                         app.processName, app.setAdj, app.waitingToKill);
                 app.killedBackground = true;
                 Process.killProcessQuiet(app.pid);
@@ -14694,7 +13545,7 @@
         return resumedActivity;
     }
 
-    private final boolean updateOomAdjLocked(ProcessRecord app) {
+    final boolean updateOomAdjLocked(ProcessRecord app) {
         final ActivityRecord TOP_ACT = resumedAppLocked();
         final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
         int curAdj = app.curAdj;
@@ -14703,7 +13554,8 @@
 
         mAdjSeq++;
 
-        boolean success = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP, false);
+        boolean success = updateOomAdjLocked(app, app.hiddenAdj, app.clientHiddenAdj,
+                app.emptyAdj, TOP_APP, false);
         final boolean nowHidden = app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
             && app.curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
         if (nowHidden != wasHidden) {
@@ -14717,6 +13569,7 @@
     final void updateOomAdjLocked() {
         final ActivityRecord TOP_ACT = resumedAppLocked();
         final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
+        final long oldTime = SystemClock.uptimeMillis() - ProcessList.MAX_EMPTY_TIME;
 
         if (false) {
             RuntimeException e = new RuntimeException();
@@ -14727,47 +13580,143 @@
         mAdjSeq++;
         mNewNumServiceProcs = 0;
 
+        final int emptyProcessLimit;
+        final int hiddenProcessLimit;
+        if (mProcessLimit <= 0) {
+            emptyProcessLimit = hiddenProcessLimit = 0;
+        } else if (mProcessLimit == 1) {
+            emptyProcessLimit = 1;
+            hiddenProcessLimit = 0;
+        } else {
+            emptyProcessLimit = (mProcessLimit*2)/3;
+            hiddenProcessLimit = mProcessLimit - emptyProcessLimit;
+        }
+
         // Let's determine how many processes we have running vs.
         // how many slots we have for background processes; we may want
         // to put multiple processes in a slot of there are enough of
         // them.
-        int numSlots = ProcessList.HIDDEN_APP_MAX_ADJ - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
-        int factor = (mLruProcesses.size()-4)/numSlots;
-        if (factor < 1) factor = 1;
-        int step = 0;
+        int numSlots = (ProcessList.HIDDEN_APP_MAX_ADJ
+                - ProcessList.HIDDEN_APP_MIN_ADJ + 1) / 2;
+        int numEmptyProcs = mLruProcesses.size()-mNumNonHiddenProcs-mNumHiddenProcs;
+        if (numEmptyProcs > hiddenProcessLimit) {
+            // If there are more empty processes than our limit on hidden
+            // processes, then use the hidden process limit for the factor.
+            // This ensures that the really old empty processes get pushed
+            // down to the bottom, so if we are running low on memory we will
+            // have a better chance at keeping around more hidden processes
+            // instead of a gazillion empty processes.
+            numEmptyProcs = hiddenProcessLimit;
+        }
+        int emptyFactor = numEmptyProcs/numSlots;
+        if (emptyFactor < 1) emptyFactor = 1;
+        int hiddenFactor = (mNumHiddenProcs > 0 ? mNumHiddenProcs : 1)/numSlots;
+        if (hiddenFactor < 1) hiddenFactor = 1;
+        int stepHidden = 0;
+        int stepEmpty = 0;
         int numHidden = 0;
+        int numEmpty = 0;
         int numTrimming = 0;
-        
+
+        mNumNonHiddenProcs = 0;
+        mNumHiddenProcs = 0;
+
         // First update the OOM adjustment for each of the
         // application processes based on their current state.
         int i = mLruProcesses.size();
         int curHiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
+        int nextHiddenAdj = curHiddenAdj+1;
+        int curEmptyAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
+        int nextEmptyAdj = curEmptyAdj+2;
+        int curClientHiddenAdj = curEmptyAdj;
         while (i > 0) {
             i--;
             ProcessRecord app = mLruProcesses.get(i);
             //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
-            updateOomAdjLocked(app, curHiddenAdj, TOP_APP, true);
-            if (curHiddenAdj < ProcessList.HIDDEN_APP_MAX_ADJ
-                && app.curAdj == curHiddenAdj) {
-                step++;
-                if (step >= factor) {
-                    step = 0;
-                    curHiddenAdj++;
-                }
-            }
+            updateOomAdjLocked(app, curHiddenAdj, curClientHiddenAdj, curEmptyAdj, TOP_APP, true);
             if (!app.killedBackground) {
-                if (app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
+                if (app.curRawAdj == curHiddenAdj && app.hasActivities) {
+                    // This process was assigned as a hidden process...  step the
+                    // hidden level.
+                    mNumHiddenProcs++;
+                    if (curHiddenAdj != nextHiddenAdj) {
+                        stepHidden++;
+                        if (stepHidden >= hiddenFactor) {
+                            stepHidden = 0;
+                            curHiddenAdj = nextHiddenAdj;
+                            nextHiddenAdj += 2;
+                            if (nextHiddenAdj > ProcessList.HIDDEN_APP_MAX_ADJ) {
+                                nextHiddenAdj = ProcessList.HIDDEN_APP_MAX_ADJ;
+                            }
+                            if (curClientHiddenAdj <= curHiddenAdj) {
+                                curClientHiddenAdj = curHiddenAdj + 1;
+                                if (curClientHiddenAdj > ProcessList.HIDDEN_APP_MAX_ADJ) {
+                                    curClientHiddenAdj = ProcessList.HIDDEN_APP_MAX_ADJ;
+                                }
+                            }
+                        }
+                    }
                     numHidden++;
-                    if (numHidden > mProcessLimit) {
+                    if (numHidden > hiddenProcessLimit) {
                         Slog.i(TAG, "No longer want " + app.processName
                                 + " (pid " + app.pid + "): hidden #" + numHidden);
-                        EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
+                        EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
                                 app.processName, app.setAdj, "too many background");
                         app.killedBackground = true;
                         Process.killProcessQuiet(app.pid);
                     }
+                } else if (app.curRawAdj == curHiddenAdj && app.hasClientActivities) {
+                    // This process has a client that has activities.  We will have
+                    // given it the current hidden adj; here we will just leave it
+                    // without stepping the hidden adj.
+                    curClientHiddenAdj++;
+                    if (curClientHiddenAdj > ProcessList.HIDDEN_APP_MAX_ADJ) {
+                        curClientHiddenAdj = ProcessList.HIDDEN_APP_MAX_ADJ;
+                    }
+                } else {
+                    if (app.curRawAdj == curEmptyAdj || app.curRawAdj == curHiddenAdj) {
+                        // This process was assigned as an empty process...  step the
+                        // empty level.
+                        if (curEmptyAdj != nextEmptyAdj) {
+                            stepEmpty++;
+                            if (stepEmpty >= emptyFactor) {
+                                stepEmpty = 0;
+                                curEmptyAdj = nextEmptyAdj;
+                                nextEmptyAdj += 2;
+                                if (nextEmptyAdj > ProcessList.HIDDEN_APP_MAX_ADJ) {
+                                    nextEmptyAdj = ProcessList.HIDDEN_APP_MAX_ADJ;
+                                }
+                            }
+                        }
+                    } else if (app.curRawAdj < ProcessList.HIDDEN_APP_MIN_ADJ) {
+                        mNumNonHiddenProcs++;
+                    }
+                    if (app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
+                            && !app.hasClientActivities) {
+                        if (numEmpty > ProcessList.TRIM_EMPTY_APPS
+                                && app.lastActivityTime < oldTime) {
+                            Slog.i(TAG, "No longer want " + app.processName
+                                    + " (pid " + app.pid + "): empty for "
+                                    + ((oldTime+ProcessList.MAX_EMPTY_TIME-app.lastActivityTime)
+                                            / 1000) + "s");
+                            EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
+                                    app.processName, app.setAdj, "old background process");
+                            app.killedBackground = true;
+                            Process.killProcessQuiet(app.pid);
+                        } else {
+                            numEmpty++;
+                            if (numEmpty > emptyProcessLimit) {
+                                Slog.i(TAG, "No longer want " + app.processName
+                                        + " (pid " + app.pid + "): empty #" + numEmpty);
+                                EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
+                                        app.processName, app.setAdj, "too many background");
+                                app.killedBackground = true;
+                                Process.killProcessQuiet(app.pid);
+                            }
+                        }
+                    }
                 }
-                if (!app.killedBackground && app.isolated && app.services.size() <= 0) {
+                if (app.isolated && app.services.size() <= 0) {
                     // If this is an isolated process, and there are no
                     // services running in it, then the process is no longer
                     // needed.  We agressively kill these because we can by
@@ -14776,7 +13725,7 @@
                     // left sitting around after no longer needed.
                     Slog.i(TAG, "Isolated process " + app.processName
                             + " (pid " + app.pid + ") no longer needed");
-                    EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
+                    EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
                             app.processName, app.setAdj, "isolated not needed");
                     app.killedBackground = true;
                     Process.killProcessQuiet(app.pid);
@@ -14797,18 +13746,20 @@
         // are managing to keep around is less than half the maximum we desire;
         // if we are keeping a good number around, we'll let them use whatever
         // memory they want.
-        if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/2)) {
+        if (numHidden <= ProcessList.TRIM_HIDDEN_APPS
+                && numEmpty <= ProcessList.TRIM_EMPTY_APPS) {
+            final int numHiddenAndEmpty = numHidden + numEmpty;
             final int N = mLruProcesses.size();
-            factor = numTrimming/3;
+            int factor = numTrimming/3;
             int minFactor = 2;
             if (mHomeProcess != null) minFactor++;
             if (mPreviousProcess != null) minFactor++;
             if (factor < minFactor) factor = minFactor;
-            step = 0;
+            int step = 0;
             int fgTrimLevel;
-            if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/5)) {
+            if (numHiddenAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
                 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
-            } else if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/3)) {
+            } else if (numHiddenAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
                 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
             } else {
                 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
@@ -14928,7 +13879,7 @@
                         + (app.thread != null ? app.thread.asBinder() : null)
                         + ")\n");
                     if (app.pid > 0 && app.pid != MY_PID) {
-                        EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
+                        EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
                                 app.processName, app.setAdj, "empty");
                         Process.killProcessQuiet(app.pid);
                     } else {
@@ -15007,7 +13958,7 @@
         mAutoStopProfiler = false;
     }
 
-    public boolean profileControl(String process, boolean start,
+    public boolean profileControl(String process, int userId, boolean start,
             String path, ParcelFileDescriptor fd, int profileType) throws RemoteException {
 
         try {
@@ -15026,22 +13977,7 @@
 
                 ProcessRecord proc = null;
                 if (process != null) {
-                    try {
-                        int pid = Integer.parseInt(process);
-                        synchronized (mPidsSelfLocked) {
-                            proc = mPidsSelfLocked.get(pid);
-                        }
-                    } catch (NumberFormatException e) {
-                    }
-
-                    if (proc == null) {
-                        HashMap<String, SparseArray<ProcessRecord>> all
-                                = mProcessNames.getMap();
-                        SparseArray<ProcessRecord> procs = all.get(process);
-                        if (procs != null && procs.size() > 0) {
-                            proc = procs.valueAt(0);
-                        }
-                    }
+                    proc = findProcessLocked(process, userId, "profileControl");
                 }
 
                 if (start && (proc == null || proc.thread == null)) {
@@ -15085,7 +14021,40 @@
         }
     }
 
-    public boolean dumpHeap(String process, boolean managed,
+    private ProcessRecord findProcessLocked(String process, int userId, String callName) {
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+                userId, true, true, callName, null);
+        ProcessRecord proc = null;
+        try {
+            int pid = Integer.parseInt(process);
+            synchronized (mPidsSelfLocked) {
+                proc = mPidsSelfLocked.get(pid);
+            }
+        } catch (NumberFormatException e) {
+        }
+
+        if (proc == null) {
+            HashMap<String, SparseArray<ProcessRecord>> all
+                    = mProcessNames.getMap();
+            SparseArray<ProcessRecord> procs = all.get(process);
+            if (procs != null && procs.size() > 0) {
+                proc = procs.valueAt(0);
+                if (userId != UserHandle.USER_ALL && proc.userId != userId) {
+                    for (int i=1; i<procs.size(); i++) {
+                        ProcessRecord thisProc = procs.valueAt(i);
+                        if (thisProc.userId == userId) {
+                            proc = thisProc;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        return proc;
+    }
+
+    public boolean dumpHeap(String process, int userId, boolean managed,
             String path, ParcelFileDescriptor fd) throws RemoteException {
 
         try {
@@ -15102,24 +14071,7 @@
                     throw new IllegalArgumentException("null fd");
                 }
 
-                ProcessRecord proc = null;
-                try {
-                    int pid = Integer.parseInt(process);
-                    synchronized (mPidsSelfLocked) {
-                        proc = mPidsSelfLocked.get(pid);
-                    }
-                } catch (NumberFormatException e) {
-                }
-
-                if (proc == null) {
-                    HashMap<String, SparseArray<ProcessRecord>> all
-                            = mProcessNames.getMap();
-                    SparseArray<ProcessRecord> procs = all.get(process);
-                    if (procs != null && procs.size() > 0) {
-                        proc = procs.valueAt(0);
-                    }
-                }
-
+                ProcessRecord proc = findProcessLocked(process, userId, "dumpHeap");
                 if (proc == null || proc.thread == null) {
                     throw new IllegalArgumentException("Unknown process: " + process);
                 }
@@ -15167,101 +14119,572 @@
 
     // Multi-user methods
 
-    private int mCurrentUserId;
-    private SparseIntArray mLoggedInUsers = new SparseIntArray(5);
-
+    @Override
     public boolean switchUser(int userId) {
-        final int callingUid = Binder.getCallingUid();
-        if (callingUid != 0 && callingUid != Process.myUid()) {
-            Slog.e(TAG, "Trying to switch user from unauthorized app");
-            return false;
+        if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+                != PackageManager.PERMISSION_GRANTED) {
+            String msg = "Permission Denial: switchUser() from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " requires " + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+            Slog.w(TAG, msg);
+            throw new SecurityException(msg);
         }
-        if (mCurrentUserId == userId)
-            return true;
 
-        synchronized (this) {
-            // Check if user is already logged in, otherwise check if user exists first before
-            // adding to the list of logged in users.
-            if (mLoggedInUsers.indexOfKey(userId) < 0) {
-                if (!userExists(userId)) {
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (this) {
+                final int oldUserId = mCurrentUserId;
+                if (oldUserId == userId) {
+                    return true;
+                }
+
+                final UserInfo userInfo = getUserManagerLocked().getUserInfo(userId);
+                if (userInfo == null) {
+                    Slog.w(TAG, "No user info for user #" + userId);
                     return false;
                 }
-                mLoggedInUsers.append(userId, userId);
-            }
 
-            mCurrentUserId = userId;
-            boolean haveActivities = mMainStack.switchUser(userId);
-            if (!haveActivities) {
-                startHomeActivityLocked(userId);
-            }
+                mWindowManager.startFreezingScreen(R.anim.screen_user_exit,
+                        R.anim.screen_user_enter);
 
+                boolean needStart = false;
+
+                // If the user we are switching to is not currently started, then
+                // we need to start it now.
+                if (mStartedUsers.get(userId) == null) {
+                    mStartedUsers.put(userId, new UserStartedState(new UserHandle(userId), false));
+                    updateStartedUserArrayLocked();
+                    needStart = true;
+                }
+
+                mCurrentUserId = userId;
+                mCurrentUserArray = new int[] { userId };
+                final Integer userIdInt = Integer.valueOf(userId);
+                mUserLru.remove(userIdInt);
+                mUserLru.add(userIdInt);
+
+                mWindowManager.setCurrentUser(userId);
+
+                // Once the internal notion of the active user has switched, we lock the device
+                // with the option to show the user switcher on the keyguard.
+                mWindowManager.lockNow(LockPatternUtils.USER_SWITCH_LOCK_OPTIONS);
+
+                final UserStartedState uss = mStartedUsers.get(userId);
+
+                // Make sure user is in the started state.  If it is currently
+                // stopping, we need to knock that off.
+                if (uss.mState == UserStartedState.STATE_STOPPING) {
+                    // If we are stopping, we haven't sent ACTION_SHUTDOWN,
+                    // so we can just fairly silently bring the user back from
+                    // the almost-dead.
+                    uss.mState = UserStartedState.STATE_RUNNING;
+                    updateStartedUserArrayLocked();
+                    needStart = true;
+                } else if (uss.mState == UserStartedState.STATE_SHUTDOWN) {
+                    // This means ACTION_SHUTDOWN has been sent, so we will
+                    // need to treat this as a new boot of the user.
+                    uss.mState = UserStartedState.STATE_BOOTING;
+                    updateStartedUserArrayLocked();
+                    needStart = true;
+                }
+
+                mHandler.removeMessages(REPORT_USER_SWITCH_MSG);
+                mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG);
+                mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_MSG,
+                        oldUserId, userId, uss));
+                mHandler.sendMessageDelayed(mHandler.obtainMessage(USER_SWITCH_TIMEOUT_MSG,
+                        oldUserId, userId, uss), USER_SWITCH_TIMEOUT);
+                if (needStart) {
+                    Intent intent = new Intent(Intent.ACTION_USER_STARTED);
+                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                            | Intent.FLAG_RECEIVER_FOREGROUND);
+                    intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+                    broadcastIntentLocked(null, null, intent,
+                            null, null, 0, null, null, null,
+                            false, false, MY_PID, Process.SYSTEM_UID, userId);
+                }
+
+                if ((userInfo.flags&UserInfo.FLAG_INITIALIZED) == 0) {
+                    if (userId != 0) {
+                        Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE);
+                        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+                        broadcastIntentLocked(null, null, intent, null,
+                                new IIntentReceiver.Stub() {
+                                    public void performReceive(Intent intent, int resultCode,
+                                            String data, Bundle extras, boolean ordered,
+                                            boolean sticky, int sendingUser) {
+                                        userInitialized(uss);
+                                    }
+                                }, 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID,
+                                userId);
+                        uss.initializing = true;
+                    } else {
+                        getUserManagerLocked().makeInitialized(userInfo.id);
+                    }
+                }
+
+                boolean haveActivities = mMainStack.switchUserLocked(userId, uss);
+                if (!haveActivities) {
+                    startHomeActivityLocked(userId);
+                }
+
+                getUserManagerLocked().userForeground(userId);
+                sendUserSwitchBroadcastsLocked(oldUserId, userId);
+                if (needStart) {
+                    Intent intent = new Intent(Intent.ACTION_USER_STARTING);
+                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                    intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+                    broadcastIntentLocked(null, null, intent,
+                            null, new IIntentReceiver.Stub() {
+                                @Override
+                                public void performReceive(Intent intent, int resultCode, String data,
+                                        Bundle extras, boolean ordered, boolean sticky, int sendingUser)
+                                        throws RemoteException {
+                                }
+                            }, 0, null, null,
+                            android.Manifest.permission.INTERACT_ACROSS_USERS,
+                            false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
 
-        // Inform of user switch
-        Intent addedIntent = new Intent(Intent.ACTION_USER_SWITCHED);
-        addedIntent.putExtra(Intent.EXTRA_USERID, userId);
-        mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
-
         return true;
     }
 
-    @Override
-    public UserInfo getCurrentUser() throws RemoteException {
-        final int callingUid = Binder.getCallingUid();
-        if (callingUid != 0 && callingUid != Process.myUid()) {
-            Slog.e(TAG, "Trying to get user from unauthorized app");
-            return null;
+    void sendUserSwitchBroadcastsLocked(int oldUserId, int newUserId) {
+        long ident = Binder.clearCallingIdentity();
+        try {
+            Intent intent;
+            if (oldUserId >= 0) {
+                intent = new Intent(Intent.ACTION_USER_BACKGROUND);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                        | Intent.FLAG_RECEIVER_FOREGROUND);
+                intent.putExtra(Intent.EXTRA_USER_HANDLE, oldUserId);
+                broadcastIntentLocked(null, null, intent,
+                        null, null, 0, null, null, null,
+                        false, false, MY_PID, Process.SYSTEM_UID, oldUserId);
+            }
+            if (newUserId >= 0) {
+                intent = new Intent(Intent.ACTION_USER_FOREGROUND);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                        | Intent.FLAG_RECEIVER_FOREGROUND);
+                intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId);
+                broadcastIntentLocked(null, null, intent,
+                        null, null, 0, null, null, null,
+                        false, false, MY_PID, Process.SYSTEM_UID, newUserId);
+                intent = new Intent(Intent.ACTION_USER_SWITCHED);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                        | Intent.FLAG_RECEIVER_FOREGROUND);
+                intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId);
+                broadcastIntentLocked(null, null, intent,
+                        null, null, 0, null, null,
+                        android.Manifest.permission.MANAGE_USERS,
+                        false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
-        return AppGlobals.getPackageManager().getUser(mCurrentUserId);
     }
 
-    private void onUserRemoved(Intent intent) {
-        int extraUserId = intent.getIntExtra(Intent.EXTRA_USERID, -1);
-        if (extraUserId < 1) return;
-
-        // Kill all the processes for the user
-        ArrayList<Pair<String, Integer>> pkgAndUids = new ArrayList<Pair<String,Integer>>();
-        synchronized (this) {
-            HashMap<String,SparseArray<ProcessRecord>> map = mProcessNames.getMap();
-            for (Entry<String, SparseArray<ProcessRecord>> uidMap : map.entrySet()) {
-                SparseArray<ProcessRecord> uids = uidMap.getValue();
-                for (int i = 0; i < uids.size(); i++) {
-                    if (UserId.getUserId(uids.keyAt(i)) == extraUserId) {
-                        pkgAndUids.add(new Pair<String,Integer>(uidMap.getKey(), uids.keyAt(i)));
+    void dispatchUserSwitch(final UserStartedState uss, final int oldUserId,
+            final int newUserId) {
+        final int N = mUserSwitchObservers.beginBroadcast();
+        if (N > 0) {
+            final IRemoteCallback callback = new IRemoteCallback.Stub() {
+                int mCount = 0;
+                @Override
+                public void sendResult(Bundle data) throws RemoteException {
+                    synchronized (ActivityManagerService.this) {
+                        if (mCurUserSwitchCallback == this) {
+                            mCount++;
+                            if (mCount == N) {
+                                sendContinueUserSwitchLocked(uss, oldUserId, newUserId);
+                            }
+                        }
                     }
                 }
+            };
+            synchronized (this) {
+                uss.switching = true;
+                mCurUserSwitchCallback = callback;
             }
-
-            for (Pair<String,Integer> pkgAndUid : pkgAndUids) {
-                forceStopPackageLocked(pkgAndUid.first, pkgAndUid.second,
-                        false, false, true, true, extraUserId);
+            for (int i=0; i<N; i++) {
+                try {
+                    mUserSwitchObservers.getBroadcastItem(i).onUserSwitching(
+                            newUserId, callback);
+                } catch (RemoteException e) {
+                }
+            }
+        } else {
+            synchronized (this) {
+                sendContinueUserSwitchLocked(uss, oldUserId, newUserId);
             }
         }
+        mUserSwitchObservers.finishBroadcast();
+    }
+
+    void timeoutUserSwitch(UserStartedState uss, int oldUserId, int newUserId) {
+        synchronized (this) {
+            Slog.w(TAG, "User switch timeout: from " + oldUserId + " to " + newUserId);
+            sendContinueUserSwitchLocked(uss, oldUserId, newUserId);
+        }
+    }
+
+    void sendContinueUserSwitchLocked(UserStartedState uss, int oldUserId, int newUserId) {
+        mCurUserSwitchCallback = null;
+        mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG);
+        mHandler.sendMessage(mHandler.obtainMessage(CONTINUE_USER_SWITCH_MSG,
+                oldUserId, newUserId, uss));
+    }
+
+    void userInitialized(UserStartedState uss) {
+        synchronized (ActivityManagerService.this) {
+            getUserManagerLocked().makeInitialized(uss.mHandle.getIdentifier());
+            uss.initializing = false;
+            completeSwitchAndInitalizeLocked(uss);
+        }
+    }
+
+    void continueUserSwitch(UserStartedState uss, int oldUserId, int newUserId) {
+        final int N = mUserSwitchObservers.beginBroadcast();
+        for (int i=0; i<N; i++) {
+            try {
+                mUserSwitchObservers.getBroadcastItem(i).onUserSwitchComplete(newUserId);
+            } catch (RemoteException e) {
+            }
+        }
+        mUserSwitchObservers.finishBroadcast();
+        synchronized (this) {
+            uss.switching = false;
+            completeSwitchAndInitalizeLocked(uss);
+        }
+    }
+
+    void completeSwitchAndInitalizeLocked(UserStartedState uss) {
+        if (!uss.switching && !uss.initializing) {
+            mWindowManager.stopFreezingScreen();
+        }
+    }
+
+    void finishUserSwitch(UserStartedState uss) {
+        synchronized (this) {
+            if (uss.mState == UserStartedState.STATE_BOOTING
+                    && mStartedUsers.get(uss.mHandle.getIdentifier()) == uss) {
+                uss.mState = UserStartedState.STATE_RUNNING;
+                final int userId = uss.mHandle.getIdentifier();
+                Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
+                intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+                broadcastIntentLocked(null, null, intent,
+                        null, null, 0, null, null,
+                        android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
+                        false, false, MY_PID, Process.SYSTEM_UID, userId);
+            }
+            int num = mUserLru.size();
+            int i = 0;
+            while (num > MAX_RUNNING_USERS && i < mUserLru.size()) {
+                Integer oldUserId = mUserLru.get(i);
+                UserStartedState oldUss = mStartedUsers.get(oldUserId);
+                if (oldUss == null) {
+                    // Shouldn't happen, but be sane if it does.
+                    mUserLru.remove(i);
+                    num--;
+                    continue;
+                }
+                if (oldUss.mState == UserStartedState.STATE_STOPPING
+                        || oldUss.mState == UserStartedState.STATE_SHUTDOWN) {
+                    // This user is already stopping, doesn't count.
+                    num--;
+                    i++;
+                    continue;
+                }
+                if (oldUserId == UserHandle.USER_OWNER || oldUserId == mCurrentUserId) {
+                    // Owner and current can't be stopped, but count as running.
+                    i++;
+                    continue;
+                }
+                // This is a user to be stopped.
+                stopUserLocked(oldUserId, null);
+                num--;
+                i++;
+            }
+        }
+    }
+
+    @Override
+    public int stopUser(final int userId, final IStopUserCallback callback) {
+        if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+                != PackageManager.PERMISSION_GRANTED) {
+            String msg = "Permission Denial: switchUser() from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " requires " + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+            Slog.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+        if (userId <= 0) {
+            throw new IllegalArgumentException("Can't stop primary user " + userId);
+        }
+        synchronized (this) {
+            return stopUserLocked(userId, callback);
+        }
+    }
+
+    private int stopUserLocked(final int userId, final IStopUserCallback callback) {
+        if (mCurrentUserId == userId) {
+            return ActivityManager.USER_OP_IS_CURRENT;
+        }
+
+        final UserStartedState uss = mStartedUsers.get(userId);
+        if (uss == null) {
+            // User is not started, nothing to do...  but we do need to
+            // callback if requested.
+            if (callback != null) {
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        try {
+                            callback.userStopped(userId);
+                        } catch (RemoteException e) {
+                        }
+                    }
+                });
+            }
+            return ActivityManager.USER_OP_SUCCESS;
+        }
+
+        if (callback != null) {
+            uss.mStopCallbacks.add(callback);
+        }
+
+        if (uss.mState != UserStartedState.STATE_STOPPING
+                && uss.mState != UserStartedState.STATE_SHUTDOWN) {
+            uss.mState = UserStartedState.STATE_STOPPING;
+            updateStartedUserArrayLocked();
+
+            long ident = Binder.clearCallingIdentity();
+            try {
+                // We are going to broadcast ACTION_USER_STOPPING and then
+                // once that is down send a final ACTION_SHUTDOWN and then
+                // stop the user.
+                final Intent stoppingIntent = new Intent(Intent.ACTION_USER_STOPPING);
+                stoppingIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                stoppingIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+                final Intent shutdownIntent = new Intent(Intent.ACTION_SHUTDOWN);
+                // This is the result receiver for the final shutdown broadcast.
+                final IIntentReceiver shutdownReceiver = new IIntentReceiver.Stub() {
+                    @Override
+                    public void performReceive(Intent intent, int resultCode, String data,
+                            Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
+                        finishUserStop(uss);
+                    }
+                };
+                // This is the result receiver for the initial stopping broadcast.
+                final IIntentReceiver stoppingReceiver = new IIntentReceiver.Stub() {
+                    @Override
+                    public void performReceive(Intent intent, int resultCode, String data,
+                            Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
+                        // On to the next.
+                        synchronized (ActivityManagerService.this) {
+                            if (uss.mState != UserStartedState.STATE_STOPPING) {
+                                // Whoops, we are being started back up.  Abort, abort!
+                                return;
+                            }
+                            uss.mState = UserStartedState.STATE_SHUTDOWN;
+                        }
+                        broadcastIntentLocked(null, null, shutdownIntent,
+                                null, shutdownReceiver, 0, null, null, null,
+                                true, false, MY_PID, Process.SYSTEM_UID, userId);
+                    }
+                };
+                // Kick things off.
+                broadcastIntentLocked(null, null, stoppingIntent,
+                        null, stoppingReceiver, 0, null, null,
+                        android.Manifest.permission.INTERACT_ACROSS_USERS,
+                        true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        return ActivityManager.USER_OP_SUCCESS;
+    }
+
+    void finishUserStop(UserStartedState uss) {
+        final int userId = uss.mHandle.getIdentifier();
+        boolean stopped;
+        ArrayList<IStopUserCallback> callbacks;
+        synchronized (this) {
+            callbacks = new ArrayList<IStopUserCallback>(uss.mStopCallbacks);
+            if (mStartedUsers.get(userId) != uss) {
+                stopped = false;
+            } else if (uss.mState != UserStartedState.STATE_SHUTDOWN) {
+                stopped = false;
+            } else {
+                stopped = true;
+                // User can no longer run.
+                mStartedUsers.remove(userId);
+                mUserLru.remove(Integer.valueOf(userId));
+                updateStartedUserArrayLocked();
+
+                // Clean up all state and processes associated with the user.
+                // Kill all the processes for the user.
+                forceStopUserLocked(userId);
+            }
+        }
+
+        for (int i=0; i<callbacks.size(); i++) {
+            try {
+                if (stopped) callbacks.get(i).userStopped(userId);
+                else callbacks.get(i).userStopAborted(userId);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    @Override
+    public UserInfo getCurrentUser() {
+        if ((checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
+                != PackageManager.PERMISSION_GRANTED) && (
+                checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+                != PackageManager.PERMISSION_GRANTED)) {
+            String msg = "Permission Denial: getCurrentUser() from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " requires " + android.Manifest.permission.INTERACT_ACROSS_USERS;
+            Slog.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+        synchronized (this) {
+            return getUserManagerLocked().getUserInfo(mCurrentUserId);
+        }
+    }
+
+    int getCurrentUserIdLocked() {
+        return mCurrentUserId;
+    }
+
+    @Override
+    public boolean isUserRunning(int userId, boolean orStopped) {
+        if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
+                != PackageManager.PERMISSION_GRANTED) {
+            String msg = "Permission Denial: isUserRunning() from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " requires " + android.Manifest.permission.INTERACT_ACROSS_USERS;
+            Slog.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+        synchronized (this) {
+            return isUserRunningLocked(userId, orStopped);
+        }
+    }
+
+    boolean isUserRunningLocked(int userId, boolean orStopped) {
+        UserStartedState state = mStartedUsers.get(userId);
+        if (state == null) {
+            return false;
+        }
+        if (orStopped) {
+            return true;
+        }
+        return state.mState != UserStartedState.STATE_STOPPING
+                && state.mState != UserStartedState.STATE_SHUTDOWN;
+    }
+
+    @Override
+    public int[] getRunningUserIds() {
+        if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
+                != PackageManager.PERMISSION_GRANTED) {
+            String msg = "Permission Denial: isUserRunning() from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " requires " + android.Manifest.permission.INTERACT_ACROSS_USERS;
+            Slog.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+        synchronized (this) {
+            return mStartedUserArray;
+        }
+    }
+
+    private void updateStartedUserArrayLocked() {
+        int num = 0;
+        for (int i=0; i<mStartedUsers.size();  i++) {
+            UserStartedState uss = mStartedUsers.valueAt(i);
+            // This list does not include stopping users.
+            if (uss.mState != UserStartedState.STATE_STOPPING
+                    && uss.mState != UserStartedState.STATE_SHUTDOWN) {
+                num++;
+            }
+        }
+        mStartedUserArray = new int[num];
+        num = 0;
+        for (int i=0; i<mStartedUsers.size();  i++) {
+            UserStartedState uss = mStartedUsers.valueAt(i);
+            if (uss.mState != UserStartedState.STATE_STOPPING
+                    && uss.mState != UserStartedState.STATE_SHUTDOWN) {
+                mStartedUserArray[num] = mStartedUsers.keyAt(i);
+                num++;
+            }
+        }
+    }
+
+    @Override
+    public void registerUserSwitchObserver(IUserSwitchObserver observer) {
+        if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+                != PackageManager.PERMISSION_GRANTED) {
+            String msg = "Permission Denial: registerUserSwitchObserver() from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " requires " + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+            Slog.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+
+        mUserSwitchObservers.register(observer);
+    }
+
+    @Override
+    public void unregisterUserSwitchObserver(IUserSwitchObserver observer) {
+        mUserSwitchObservers.unregister(observer);
     }
 
     private boolean userExists(int userId) {
-        try {
-            UserInfo user = AppGlobals.getPackageManager().getUser(userId);
-            return user != null;
-        } catch (RemoteException re) {
-            // Won't happen, in same process
+        if (userId == 0) {
+            return true;
         }
+        UserManagerService ums = getUserManagerLocked();
+        return ums != null ? (ums.getUserInfo(userId) != null) : false;
+    }
 
-        return false;
+    int[] getUsersLocked() {
+        UserManagerService ums = getUserManagerLocked();
+        return ums != null ? ums.getUserIds() : new int[] { 0 };
+    }
+
+    UserManagerService getUserManagerLocked() {
+        if (mUserManager == null) {
+            IBinder b = ServiceManager.getService(Context.USER_SERVICE);
+            mUserManager = (UserManagerService)IUserManager.Stub.asInterface(b);
+        }
+        return mUserManager;
     }
 
     private void checkValidCaller(int uid, int userId) {
-        if (UserId.getUserId(uid) == userId || uid == Process.SYSTEM_UID || uid == 0) return;
+        if (UserHandle.getUserId(uid) == userId || uid == Process.SYSTEM_UID || uid == 0) return;
 
         throw new SecurityException("Caller uid=" + uid
                 + " is not privileged to communicate with user=" + userId);
     }
 
     private int applyUserId(int uid, int userId) {
-        return UserId.getUid(userId, uid);
+        return UserHandle.getUid(userId, uid);
     }
 
-    private ApplicationInfo getAppInfoForUser(ApplicationInfo info, int userId) {
+    ApplicationInfo getAppInfoForUser(ApplicationInfo info, int userId) {
         if (info == null) return null;
         ApplicationInfo newInfo = new ApplicationInfo(info);
         newInfo.uid = applyUserId(info.uid, userId);
@@ -15272,7 +14695,7 @@
 
     ActivityInfo getActivityInfoForUser(ActivityInfo aInfo, int userId) {
         if (aInfo == null
-                || (userId < 1 && aInfo.applicationInfo.uid < UserId.PER_USER_RANGE)) {
+                || (userId < 1 && aInfo.applicationInfo.uid < UserHandle.PER_USER_RANGE)) {
             return aInfo;
         }
 
@@ -15280,86 +14703,4 @@
         info.applicationInfo = getAppInfoForUser(info.applicationInfo, userId);
         return info;
     }
-
-    static class ServiceMap {
-
-        private final SparseArray<HashMap<ComponentName, ServiceRecord>> mServicesByNamePerUser
-                = new SparseArray<HashMap<ComponentName, ServiceRecord>>();
-        private final SparseArray<HashMap<Intent.FilterComparison, ServiceRecord>>
-                mServicesByIntentPerUser = new SparseArray<
-                    HashMap<Intent.FilterComparison, ServiceRecord>>();
-
-        ServiceRecord getServiceByName(ComponentName name, int callingUser) {
-            // TODO: Deal with global services
-            if (DEBUG_MU)
-                Slog.v(TAG_MU, "getServiceByName(" + name + "), callingUser = " + callingUser);
-            return getServices(callingUser).get(name);
-        }
-
-        ServiceRecord getServiceByName(ComponentName name) {
-            return getServiceByName(name, -1);
-        }
-
-        ServiceRecord getServiceByIntent(Intent.FilterComparison filter, int callingUser) {
-            // TODO: Deal with global services
-            if (DEBUG_MU)
-                Slog.v(TAG_MU, "getServiceByIntent(" + filter + "), callingUser = " + callingUser);
-            return getServicesByIntent(callingUser).get(filter);
-        }
-
-        ServiceRecord getServiceByIntent(Intent.FilterComparison filter) {
-            return getServiceByIntent(filter, -1);
-        }
-
-        void putServiceByName(ComponentName name, int callingUser, ServiceRecord value) {
-            // TODO: Deal with global services
-            getServices(callingUser).put(name, value);
-        }
-
-        void putServiceByIntent(Intent.FilterComparison filter, int callingUser,
-                ServiceRecord value) {
-            // TODO: Deal with global services
-            getServicesByIntent(callingUser).put(filter, value);
-        }
-
-        void removeServiceByName(ComponentName name, int callingUser) {
-            // TODO: Deal with global services
-            ServiceRecord removed = getServices(callingUser).remove(name);
-            if (DEBUG_MU)
-                Slog.v(TAG, "removeServiceByName user=" + callingUser + " name=" + name
-                        + " removed=" + removed);
-        }
-
-        void removeServiceByIntent(Intent.FilterComparison filter, int callingUser) {
-            // TODO: Deal with global services
-            ServiceRecord removed = getServicesByIntent(callingUser).remove(filter);
-            if (DEBUG_MU)
-                Slog.v(TAG_MU, "removeServiceByIntent user=" + callingUser + " intent=" + filter
-                        + " removed=" + removed);
-        }
-
-        Collection<ServiceRecord> getAllServices(int callingUser) {
-            // TODO: Deal with global services
-            return getServices(callingUser).values();
-        }
-
-        private HashMap<ComponentName, ServiceRecord> getServices(int callingUser) {
-            HashMap map = mServicesByNamePerUser.get(callingUser);
-            if (map == null) {
-                map = new HashMap<ComponentName, ServiceRecord>();
-                mServicesByNamePerUser.put(callingUser, map);
-            }
-            return map;
-        }
-
-        private HashMap<Intent.FilterComparison, ServiceRecord> getServicesByIntent(
-                int callingUser) {
-            HashMap map = mServicesByIntentPerUser.get(callingUser);
-            if (map == null) {
-                map = new HashMap<Intent.FilterComparison, ServiceRecord>();
-                mServicesByIntentPerUser.put(callingUser, map);
-            }
-            return map;
-        }
-    }
 }
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index c40abb7..749dc66 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -37,7 +37,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
@@ -219,7 +219,13 @@
         pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
                 pw.print(" thumbnailNeeded="); pw.print(thumbnailNeeded);
                 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
-        pw.print(prefix); pw.print("thumbHolder="); pw.println(thumbHolder);
+        pw.print(prefix); pw.print("thumbHolder: ");
+                pw.print(Integer.toHexString(System.identityHashCode(thumbHolder)));
+                if (thumbHolder != null) {
+                    pw.print(" bm="); pw.print(thumbHolder.lastThumbnail);
+                    pw.print(" desc="); pw.print(thumbHolder.lastDescription);
+                }
+                pw.println();
         if (launchTime != 0 || startTime != 0) {
             pw.print(prefix); pw.print("launchTime=");
                     if (launchTime == 0) pw.print("0");
@@ -321,7 +327,7 @@
         appToken = new Token(this);
         info = aInfo;
         launchedFromUid = _launchedFromUid;
-        userId = UserId.getUserId(aInfo.applicationInfo.uid);
+        userId = UserHandle.getUserId(aInfo.applicationInfo.uid);
         intent = _intent;
         shortComponentName = _intent.getComponent().flattenToShortString();
         resolvedType = _resolvedType;
@@ -333,7 +339,6 @@
         state = ActivityState.INITIALIZING;
         frontOfTask = false;
         launchFailed = false;
-        haveState = false;
         stopped = false;
         delayedResume = false;
         finishing = false;
@@ -347,6 +352,11 @@
         idle = false;
         hasBeenLaunched = false;
 
+        // This starts out true, since the initial state of an activity
+        // is that we have everything, and we shouldn't never consider it
+        // lacking in state to be removed if it dies.
+        haveState = true;
+
         if (aInfo != null) {
             if (aInfo.targetActivity == null
                     || aInfo.launchMode == ActivityInfo.LAUNCH_MULTIPLE
@@ -592,6 +602,15 @@
         }
     }
 
+    void updateOptionsLocked(ActivityOptions options) {
+        if (options != null) {
+            if (pendingOptions != null) {
+                pendingOptions.abort();
+            }
+            pendingOptions = options;
+        }
+    }
+
     void applyOptionsLocked() {
         if (pendingOptions != null) {
             final int animationType = pendingOptions.getAnimationType();
@@ -614,14 +633,14 @@
                                 pendingOptions.getStartY()+pendingOptions.getStartHeight()));
                     }
                     break;
-                case ActivityOptions.ANIM_THUMBNAIL:
-                case ActivityOptions.ANIM_THUMBNAIL_DELAYED:
-                    boolean delayed = (animationType == ActivityOptions.ANIM_THUMBNAIL_DELAYED);
+                case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP:
+                case ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN:
+                    boolean scaleUp = (animationType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP);
                     service.mWindowManager.overridePendingAppTransitionThumb(
                             pendingOptions.getThumbnail(),
                             pendingOptions.getStartX(), pendingOptions.getStartY(),
                             pendingOptions.getOnAnimationStartListener(),
-                            delayed);
+                            scaleUp);
                     if (intent.getSourceBounds() == null) {
                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
                                 pendingOptions.getStartY(),
@@ -643,6 +662,12 @@
         }
     }
 
+    ActivityOptions takeOptionsLocked() {
+        ActivityOptions opts = pendingOptions;
+        pendingOptions = null;
+        return opts;
+    }
+
     void removeUriPermissionsLocked() {
         if (uriPermissions != null) {
             uriPermissions.removeUriPermissionsLocked();
@@ -670,19 +695,15 @@
         }
         if (thumbHolder != null) {
             if (newThumbnail != null) {
+                if (ActivityManagerService.DEBUG_THUMBNAILS) Slog.i(ActivityManagerService.TAG,
+                        "Setting thumbnail of " + this + " holder " + thumbHolder
+                        + " to " + newThumbnail);
                 thumbHolder.lastThumbnail = newThumbnail;
             }
             thumbHolder.lastDescription = description;
         }
     }
 
-    void clearThumbnail() {
-        if (thumbHolder != null) {
-            thumbHolder.lastThumbnail = null;
-            thumbHolder.lastDescription = null;
-        }
-    }
-
     void startLaunchTickingLocked() {
         if (ActivityManagerService.IS_USER_BUILD) {
             return;
@@ -740,8 +761,8 @@
                 final long totalTime = stack.mInitialStartTime != 0
                         ? (curTime - stack.mInitialStartTime) : thisTime;
                 if (ActivityManagerService.SHOW_ACTIVITY_START_TIME) {
-                    EventLog.writeEvent(EventLogTags.ACTIVITY_LAUNCH_TIME,
-                            System.identityHashCode(this), shortComponentName,
+                    EventLog.writeEvent(EventLogTags.AM_ACTIVITY_LAUNCH_TIME,
+                            userId, System.identityHashCode(this), shortComponentName,
                             thisTime, totalTime);
                     StringBuilder sb = service.mStringBuilder;
                     sb.setLength(0);
@@ -835,6 +856,7 @@
     }
 
     public boolean keyDispatchingTimedOut() {
+        // TODO: Unify this code with ActivityManagerService.inputDispatchingTimedOut().
         ActivityRecord r;
         ProcessRecord anrApp = null;
         synchronized(service) {
@@ -863,8 +885,7 @@
         }
         
         if (anrApp != null) {
-            service.appNotResponding(anrApp, r, this,
-                    "keyDispatchingTimedOut");
+            service.appNotResponding(anrApp, r, this, false, "keyDispatchingTimedOut");
         }
         
         return true;
@@ -917,6 +938,8 @@
         StringBuilder sb = new StringBuilder(128);
         sb.append("ActivityRecord{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(" u");
+        sb.append(userId);
         sb.append(' ');
         sb.append(intent.getComponent().flattenToShortString());
         sb.append('}');
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index b9e63b7..4546dc3 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -52,13 +52,13 @@
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
+import android.view.Display;
 import android.view.WindowManagerPolicy;
 
 import java.io.IOException;
@@ -81,6 +81,7 @@
     static final boolean DEBUG_RESULTS = ActivityManagerService.DEBUG_RESULTS;
     static final boolean DEBUG_CONFIGURATION = ActivityManagerService.DEBUG_CONFIGURATION;
     static final boolean DEBUG_TASKS = ActivityManagerService.DEBUG_TASKS;
+    static final boolean DEBUG_CLEANUP = ActivityManagerService.DEBUG_CLEANUP;
     
     static final boolean DEBUG_STATES = false;
     static final boolean DEBUG_ADD_REMOVE = false;
@@ -210,7 +211,10 @@
      */
     final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
             = new ArrayList<IActivityManager.WaitResult>();
-    
+
+    final ArrayList<UserStartedState> mStartingUsers
+            = new ArrayList<UserStartedState>();
+
     /**
      * Set when the system is going to sleep, until we have
      * successfully paused the current activity and released our wake lock.
@@ -416,13 +420,17 @@
         mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
         mLaunchingActivity.setReferenceCounted(false);
     }
-    
+
+    private boolean okToShow(ActivityRecord r) {
+        return r.userId == mCurrentUser
+                || (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0;
+    }
+
     final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) {
-        // TODO: Don't look for any tasks from other users
         int i = mHistory.size()-1;
         while (i >= 0) {
             ActivityRecord r = mHistory.get(i);
-            if (!r.finishing && r != notTop) {
+            if (!r.finishing && r != notTop && okToShow(r)) {
                 return r;
             }
             i--;
@@ -431,11 +439,10 @@
     }
 
     final ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
-        // TODO: Don't look for any tasks from other users
         int i = mHistory.size()-1;
         while (i >= 0) {
             ActivityRecord r = mHistory.get(i);
-            if (!r.finishing && !r.delayedResume && r != notTop) {
+            if (!r.finishing && !r.delayedResume && r != notTop && okToShow(r)) {
                 return r;
             }
             i--;
@@ -453,12 +460,12 @@
      * @return Returns the HistoryRecord of the next activity on the stack.
      */
     final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
-        // TODO: Don't look for any tasks from other users
         int i = mHistory.size()-1;
         while (i >= 0) {
             ActivityRecord r = mHistory.get(i);
             // Note: the taskId check depends on real taskId fields being non-zero
-            if (!r.finishing && (token != r.appToken) && (taskId != r.task.taskId)) {
+            if (!r.finishing && (token != r.appToken) && (taskId != r.task.taskId)
+                    && okToShow(r)) {
                 return r;
             }
             i--;
@@ -500,7 +507,7 @@
 
         TaskRecord cp = null;
 
-        final int userId = UserId.getUserId(info.applicationInfo.uid);
+        final int userId = UserHandle.getUserId(info.applicationInfo.uid);
         final int N = mHistory.size();
         for (int i=(N-1); i>=0; i--) {
             ActivityRecord r = mHistory.get(i);
@@ -544,7 +551,7 @@
         if (info.targetActivity != null) {
             cls = new ComponentName(info.packageName, info.targetActivity);
         }
-        final int userId = UserId.getUserId(info.applicationInfo.uid);
+        final int userId = UserHandle.getUserId(info.applicationInfo.uid);
 
         final int N = mHistory.size();
         for (int i=(N-1); i>=0; i--) {
@@ -573,37 +580,36 @@
      * Move the activities around in the stack to bring a user to the foreground.
      * @return whether there are any activities for the specified user.
      */
-    final boolean switchUser(int userId) {
-        synchronized (mService) {
-            mCurrentUser = userId;
+    final boolean switchUserLocked(int userId, UserStartedState uss) {
+        mCurrentUser = userId;
+        mStartingUsers.add(uss);
 
-            // Only one activity? Nothing to do...
-            if (mHistory.size() < 2)
-                return false;
+        // Only one activity? Nothing to do...
+        if (mHistory.size() < 2)
+            return false;
 
-            boolean haveActivities = false;
-            // Check if the top activity is from the new user.
-            ActivityRecord top = mHistory.get(mHistory.size() - 1);
-            if (top.userId == userId) return true;
-            // Otherwise, move the user's activities to the top.
-            int N = mHistory.size();
-            int i = 0;
-            while (i < N) {
-                ActivityRecord r = mHistory.get(i);
-                if (r.userId == userId) {
-                    ActivityRecord moveToTop = mHistory.remove(i);
-                    mHistory.add(moveToTop);
-                    // No need to check the top one now
-                    N--;
-                    haveActivities = true;
-                } else {
-                    i++;
-                }
+        boolean haveActivities = false;
+        // Check if the top activity is from the new user.
+        ActivityRecord top = mHistory.get(mHistory.size() - 1);
+        if (top.userId == userId) return true;
+        // Otherwise, move the user's activities to the top.
+        int N = mHistory.size();
+        int i = 0;
+        while (i < N) {
+            ActivityRecord r = mHistory.get(i);
+            if (r.userId == userId) {
+                ActivityRecord moveToTop = mHistory.remove(i);
+                mHistory.add(moveToTop);
+                // No need to check the top one now
+                N--;
+                haveActivities = true;
+            } else {
+                i++;
             }
-            // Transition from the old top to the new top
-            resumeTopActivityLocked(top);
-            return haveActivities;
         }
+        // Transition from the old top to the new top
+        resumeTopActivityLocked(top);
+        return haveActivities;
     }
 
     final boolean realStartActivityLocked(ActivityRecord r,
@@ -638,7 +644,7 @@
         if (idx < 0) {
             app.activities.add(r);
         }
-        mService.updateLruProcessLocked(app, true, true);
+        mService.updateLruProcessLocked(app, true);
 
         try {
             if (app.thread == null) {
@@ -656,7 +662,7 @@
                     + " andResume=" + andResume);
             if (andResume) {
                 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
-                        System.identityHashCode(r),
+                        r.userId, System.identityHashCode(r),
                         r.task.taskId, r.shortComponentName);
             }
             if (r.isHomeActivity) {
@@ -723,7 +729,7 @@
                       + ", giving up", e);
                 mService.appDiedLocked(app, app.pid, app.thread);
                 requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
-                        "2nd-crash");
+                        "2nd-crash", false);
                 return false;
             }
 
@@ -754,8 +760,6 @@
             completeResumeLocked(r);
             checkReadyForSleepLocked();
             if (DEBUG_SAVED_STATE) Slog.i(TAG, "Launch completed; removing icicle of " + r.icicle);
-            r.icicle = null;
-            r.haveState = false;
         } else {
             // This activity is not starting in the resumed state... which
             // should look like we asked it to pause+stop (but remain visible),
@@ -902,7 +906,7 @@
             mService.notifyAll();
         }
     }
-    
+
     public final Bitmap screenshotActivities(ActivityRecord who) {
         if (who.noDisplay) {
             return null;
@@ -919,7 +923,8 @@
         }
 
         if (w > 0) {
-            return mService.mWindowManager.screenshotApplications(who.appToken, w, h);
+            return mService.mWindowManager.screenshotApplications(who.appToken,
+                    Display.DEFAULT_DISPLAY, w, h);
         }
         return null;
     }
@@ -952,7 +957,7 @@
             if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
             try {
                 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
-                        System.identityHashCode(prev),
+                        prev.userId, System.identityHashCode(prev),
                         prev.shortComponentName);
                 prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                         userLeaving, prev.configChangeFlags);
@@ -1008,7 +1013,21 @@
             resumeTopActivityLocked(null);
         }
     }
-    
+
+    final void activityResumed(IBinder token) {
+        ActivityRecord r = null;
+
+        synchronized (mService) {
+            int index = indexOfTokenLocked(token);
+            if (index >= 0) {
+                r = mHistory.get(index);
+                if (DEBUG_SAVED_STATE) Slog.i(TAG, "Resumed activity; dropping state of: " + r);
+                r.icicle = null;
+                r.haveState = false;
+            }
+        }
+    }
+
     final void activityPaused(IBinder token, boolean timeout) {
         if (DEBUG_PAUSE) Slog.v(
             TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
@@ -1027,7 +1046,7 @@
                     completePauseLocked();
                 } else {
                     EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
-                            System.identityHashCode(r), r.shortComponentName, 
+                            r.userId, System.identityHashCode(r), r.shortComponentName, 
                             mPausingActivity != null
                                 ? mPausingActivity.shortComponentName : "(none)");
                 }
@@ -1089,7 +1108,7 @@
         if (prev != null) {
             if (prev.finishing) {
                 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
-                prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
+                prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
             } else if (prev.app != null) {
                 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
                 if (prev.waitingVisible) {
@@ -1129,9 +1148,13 @@
             resumeTopActivityLocked(prev);
         } else {
             checkReadyForSleepLocked();
-            if (topRunningActivityLocked(null) == null) {
-                // If there are no more activities available to run, then
-                // do resume anyway to start something.
+            ActivityRecord top = topRunningActivityLocked(null);
+            if (top == null || (prev != null && top != prev)) {
+                // If there are no more activities available to run,
+                // do resume anyway to start something.  Also if the top
+                // activity on the stack is not the just paused activity,
+                // we need to go ahead and resume it to ensure we complete
+                // an in-flight app switch.
                 resumeTopActivityLocked(null);
             }
         }
@@ -1190,8 +1213,7 @@
         if (mMainStack) {
             mService.reportResumedActivityLocked(next);
         }
-        
-        next.clearThumbnail();
+
         if (mMainStack) {
             mService.setFocusedActivityLocked(next);
         }
@@ -1395,7 +1417,7 @@
             // Launcher...
             if (mMainStack) {
                 ActivityOptions.abort(options);
-                return mService.startHomeActivityLocked(0);
+                return mService.startHomeActivityLocked(mCurrentUser);
             }
         }
 
@@ -1425,7 +1447,16 @@
             ActivityOptions.abort(options);
             return false;
         }
-        
+
+        // Make sure that the user who owns this activity is started.  If not,
+        // we will just leave it as is because someone should be bringing
+        // another user's activities to the top of the stack.
+        if (mService.mStartedUsers.get(next.userId) == null) {
+            Slog.w(TAG, "Skipping resume of top activity " + next
+                    + ": user " + next.userId + " is stopped");
+            return false;
+        }
+
         // The activity may be waiting for stop, but that is no longer
         // appropriate for it.
         mStoppingActivities.remove(next);
@@ -1440,7 +1471,8 @@
         // If we are currently pausing an activity, then don't do anything
         // until that is done.
         if (mPausingActivity != null) {
-            if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
+            if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG,
+                    "Skip resume: pausing=" + mPausingActivity);
             return false;
         }
 
@@ -1477,6 +1509,15 @@
         // can be resumed...
         if (mResumedActivity != null) {
             if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
+            // At this point we want to put the upcoming activity's process
+            // at the top of the LRU list, since we know we will be needing it
+            // very soon and it would be a waste to let it get killed if it
+            // happens to be sitting towards the end.
+            if (next.app != null && next.app.thread != null) {
+                // No reason to do full oom adj update here; we'll let that
+                // happen whenever it needs to later.
+                mService.updateLruProcessLocked(next.app, false);
+            }
             startPausingLocked(userLeaving, false);
             return true;
         }
@@ -1492,7 +1533,7 @@
                     Slog.d(TAG, "no-history finish of " + last + " on new resume");
                 }
                 requestFinishActivityLocked(last.appToken, Activity.RESULT_CANCELED, null,
-                "no-history");
+                        "no-history", false);
             }
         }
 
@@ -1611,7 +1652,7 @@
             if (mMainStack) {
                 mService.addRecentTaskLocked(next.task);
             }
-            mService.updateLruProcessLocked(next.app, true, true);
+            mService.updateLruProcessLocked(next.app, true);
             updateLRUListLocked(next);
 
             // Have the window manager re-evaluate the orientation of
@@ -1669,7 +1710,7 @@
                 }
 
                 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
-                        System.identityHashCode(next),
+                        next.userId, System.identityHashCode(next),
                         next.task.taskId, next.shortComponentName);
                 
                 next.sleeping = false;
@@ -1714,14 +1755,9 @@
                 // activity and try the next one.
                 Slog.w(TAG, "Exception thrown during resume of " + next, e);
                 requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
-                        "resume-exception");
+                        "resume-exception", true);
                 return true;
             }
-
-            // Didn't need to use the icicle, and it is now out of date.
-            if (DEBUG_SAVED_STATE) Slog.i(TAG, "Resumed activity; didn't need icicle of: " + next);
-            next.icicle = null;
-            next.haveState = false;
             next.stopped = false;
 
         } else {
@@ -1775,7 +1811,8 @@
                         mHistory.add(addPos, r);
                         r.putInHistory();
                         mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
-                                r.info.screenOrientation, r.fullscreen);
+                                r.info.screenOrientation, r.fullscreen,
+                                (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
                         if (VALIDATE_TOKENS) {
                             validateAppTokensLocked();
                         }
@@ -1839,7 +1876,8 @@
             }
             r.updateOptionsLocked(options);
             mService.mWindowManager.addAppToken(
-                    addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen);
+                    addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen,
+                    (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
             boolean doShow = true;
             if (newTask) {
                 // Even though this activity is starting fresh, we still need
@@ -1877,7 +1915,8 @@
             // If this is the first activity, don't do any fancy animations,
             // 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);
+                    r.info.screenOrientation, r.fullscreen,
+                    (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
             ActivityOptions.abort(options);
         }
         if (VALIDATE_TOKENS) {
@@ -1924,6 +1963,8 @@
         int taskTopI = -1;
         int replyChainEnd = -1;
         int lastReparentPos = -1;
+        ActivityOptions topOptions = null;
+        boolean canMoveOptions = true;
         for (int i=mHistory.size()-1; i>=-1; i--) {
             ActivityRecord below = i >= 0 ? mHistory.get(i) : null;
             
@@ -2009,6 +2050,7 @@
                         }
                         int dstPos = 0;
                         ThumbnailHolder curThumbHolder = target.thumbHolder;
+                        boolean gotOptions = !canMoveOptions;
                         for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
                             p = mHistory.get(srcPos);
                             if (p.finishing) {
@@ -2018,6 +2060,13 @@
                                     + " out to target's task " + target.task);
                             p.setTask(target.task, curThumbHolder, false);
                             curThumbHolder = p.thumbHolder;
+                            canMoveOptions = false;
+                            if (!gotOptions && topOptions == null) {
+                                topOptions = p.takeOptionsLocked();
+                                if (topOptions != null) {
+                                    gotOptions = true;
+                                }
+                            }
                             if (DEBUG_ADD_REMOVE) {
                                 RuntimeException here = new RuntimeException("here");
                                 here.fillInStackTrace();
@@ -2062,13 +2111,21 @@
                             replyChainEnd = targetI;
                         }
                         ActivityRecord p = null;
+                        boolean gotOptions = !canMoveOptions;
                         for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
                             p = mHistory.get(srcPos);
                             if (p.finishing) {
                                 continue;
                             }
+                            canMoveOptions = false;
+                            if (!gotOptions && topOptions == null) {
+                                topOptions = p.takeOptionsLocked();
+                                if (topOptions != null) {
+                                    gotOptions = true;
+                                }
+                            }
                             if (finishActivityLocked(p, srcPos,
-                                    Activity.RESULT_CANCELED, null, "reset")) {
+                                    Activity.RESULT_CANCELED, null, "reset", false)) {
                                 replyChainEnd--;
                                 srcPos--;
                             }
@@ -2131,7 +2188,7 @@
                             continue;
                         }
                         if (finishActivityLocked(p, srcPos,
-                                Activity.RESULT_CANCELED, null, "reset")) {
+                                Activity.RESULT_CANCELED, null, "reset", false)) {
                             taskTopI--;
                             lastReparentPos--;
                             replyChainEnd--;
@@ -2188,7 +2245,7 @@
                             }
                             if (p.intent.getComponent().equals(target.intent.getComponent())) {
                                 if (finishActivityLocked(p, j,
-                                        Activity.RESULT_CANCELED, null, "replace")) {
+                                        Activity.RESULT_CANCELED, null, "replace", false)) {
                                     taskTopI--;
                                     lastReparentPos--;
                                 }
@@ -2206,7 +2263,17 @@
             target = below;
             targetI = i;
         }
-        
+
+        if (topOptions != null) {
+            // If we got some ActivityOptions from an activity on top that
+            // was removed from the task, propagate them to the new real top.
+            if (taskTop != null) {
+                taskTop.updateOptionsLocked(topOptions);
+            } else {
+                topOptions.abort();
+            }
+        }
+
         return taskTop;
     }
     
@@ -2257,8 +2324,12 @@
                     if (r.finishing) {
                         continue;
                     }
+                    ActivityOptions opts = r.takeOptionsLocked();
+                    if (opts != null) {
+                        ret.updateOptionsLocked(opts);
+                    }
                     if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
-                            null, "clear")) {
+                            null, "clear", false)) {
                         i--;
                     }
                 }
@@ -2272,7 +2343,7 @@
                         int index = indexOfTokenLocked(ret.appToken);
                         if (index >= 0) {
                             finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
-                                    null, "clear");
+                                    null, "clear", false);
                         }
                         return null;
                     }
@@ -2301,7 +2372,7 @@
                 continue;
             }
             if (!finishActivityLocked(r, i, Activity.RESULT_CANCELED,
-                    null, "clear")) {
+                    null, "clear", false)) {
                 i++;
             }
         }
@@ -2404,9 +2475,9 @@
         }
 
         if (err == ActivityManager.START_SUCCESS) {
-            final int userId = aInfo != null ? UserId.getUserId(aInfo.applicationInfo.uid) : 0;
-            Slog.i(TAG, "START {" + intent.toShortString(true, true, true, false)
-                    + " u=" + userId + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
+            final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
+            Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
+                    + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
         }
 
         ActivityRecord sourceRecord = null;
@@ -2585,7 +2656,6 @@
             Bundle options) {
         final Intent intent = r.intent;
         final int callingUid = r.launchedFromUid;
-        final int userId = r.userId;
 
         int launchFlags = intent.getFlags();
         
@@ -2942,7 +3012,7 @@
                 intent, r.getUriPermissionsLocked());
 
         if (newTask) {
-            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
+            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
         }
         logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
         startActivityLocked(r, newTask, doResume, keepCurTransition, options);
@@ -3013,10 +3083,6 @@
         // Collect information about the target of the Intent.
         ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
                 profileFile, profileFd, userId);
-        if (aInfo != null && mService.isSingleton(aInfo.processName, aInfo.applicationInfo)) {
-            userId = 0;
-        }
-        aInfo = mService.getActivityInfoForUser(aInfo, userId);
 
         synchronized (mService) {
             int callingPid;
@@ -3062,7 +3128,7 @@
                         
                         IIntentSender target = mService.getIntentSenderLocked(
                                 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
-                                realCallingUid, null, null, 0, new Intent[] { intent },
+                                realCallingUid, userId, null, null, 0, new Intent[] { intent },
                                 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
                                 | PendingIntent.FLAG_ONE_SHOT, null);
                         
@@ -3306,7 +3372,7 @@
                         Slog.d(TAG, "no-history finish of " + r);
                     }
                     requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
-                            "no-history");
+                            "no-history", false);
                 } else {
                     if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r
                             + " on stop because we're just sleeping");
@@ -3412,6 +3478,7 @@
         ArrayList<ActivityRecord> stops = null;
         ArrayList<ActivityRecord> finishes = null;
         ArrayList<ActivityRecord> thumbnails = null;
+        ArrayList<UserStartedState> startingUsers = null;
         int NS = 0;
         int NF = 0;
         int NT = 0;
@@ -3493,6 +3560,10 @@
                 booting = mService.mBooting;
                 mService.mBooting = false;
             }
+            if (mStartingUsers.size() > 0) {
+                startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
+                mStartingUsers.clear();
+            }
         }
 
         int i;
@@ -3513,7 +3584,7 @@
             ActivityRecord r = (ActivityRecord)stops.get(i);
             synchronized (mService) {
                 if (r.finishing) {
-                    finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
+                    finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
                 } else {
                     stopActivityLocked(r);
                 }
@@ -3537,6 +3608,10 @@
 
         if (booting) {
             mService.finishBooting();
+        } else if (startingUsers != null) {
+            for (i=0; i<startingUsers.size(); i++) {
+                mService.finishUserSwitch(startingUsers.get(i));
+            }
         }
 
         mService.trimApplications();
@@ -3559,7 +3634,7 @@
      * some reason it is being left as-is.
      */
     final boolean requestFinishActivityLocked(IBinder token, int resultCode,
-            Intent resultData, String reason) {
+            Intent resultData, String reason, boolean oomAdj) {
         int index = indexOfTokenLocked(token);
         if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(
                 TAG, "Finishing activity @" + index + ": token=" + token
@@ -3570,7 +3645,7 @@
         }
         ActivityRecord r = mHistory.get(index);
 
-        finishActivityLocked(r, index, resultCode, resultData, reason);
+        finishActivityLocked(r, index, resultCode, resultData, reason, oomAdj);
         return true;
     }
 
@@ -3587,10 +3662,11 @@
                 if ((r.resultWho == null && resultWho == null) ||
                     (r.resultWho != null && r.resultWho.equals(resultWho))) {
                     finishActivityLocked(r, i,
-                            Activity.RESULT_CANCELED, null, "request-sub");
+                            Activity.RESULT_CANCELED, null, "request-sub", false);
                 }
             }
         }
+        mService.updateOomAdjLocked();
     }
 
     final boolean finishActivityAffinityLocked(IBinder token) {
@@ -3613,7 +3689,8 @@
             if (cur.taskAffinity != null && !cur.taskAffinity.equals(r.taskAffinity)) {
                 break;
             }
-            finishActivityLocked(cur, index, Activity.RESULT_CANCELED, null, "request-affinity");
+            finishActivityLocked(cur, index, Activity.RESULT_CANCELED, null,
+                    "request-affinity", true);
             index--;
         }
         return true;
@@ -3651,16 +3728,16 @@
      * 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) {
-        return finishActivityLocked(r, index, resultCode, resultData, reason, false);
+            int resultCode, Intent resultData, String reason, boolean oomAdj) {
+        return finishActivityLocked(r, index, resultCode, resultData, reason, false, oomAdj);
     }
 
     /**
      * @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) {
+    final boolean finishActivityLocked(ActivityRecord r, int index, int resultCode,
+            Intent resultData, String reason, boolean immediate, boolean oomAdj) {
         if (r.finishing) {
             Slog.w(TAG, "Duplicate finish request for " + r);
             return false;
@@ -3668,7 +3745,7 @@
 
         r.makeFinishing();
         EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
-                System.identityHashCode(r),
+                r.userId, System.identityHashCode(r),
                 r.task.taskId, r.shortComponentName, reason);
         if (index < (mHistory.size()-1)) {
             ActivityRecord next = mHistory.get(index+1);
@@ -3704,7 +3781,7 @@
 
         if (immediate) {
             return finishCurrentActivityLocked(r, index,
-                    FINISH_IMMEDIATELY) == null;
+                    FINISH_IMMEDIATELY, oomAdj) == null;
         } else if (mResumedActivity == r) {
             boolean endTask = index <= 0
                     || (mHistory.get(index-1)).task != r.task;
@@ -3728,7 +3805,7 @@
             // it is done pausing; else we can just directly finish it here.
             if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
             return finishCurrentActivityLocked(r, index,
-                    FINISH_AFTER_PAUSE) == null;
+                    FINISH_AFTER_PAUSE, oomAdj) == null;
         } else {
             if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
         }
@@ -3741,17 +3818,17 @@
     private static final int FINISH_AFTER_VISIBLE = 2;
 
     private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
-            int mode) {
+            int mode, boolean oomAdj) {
         final int index = indexOfActivityLocked(r);
         if (index < 0) {
             return null;
         }
 
-        return finishCurrentActivityLocked(r, index, mode);
+        return finishCurrentActivityLocked(r, index, mode, oomAdj);
     }
 
     private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
-            int index, int mode) {
+            int index, int mode, boolean oomAdj) {
         // First things first: if this activity is currently visible,
         // and the resumed activity is not yet visible, then hold off on
         // finishing until the resumed one becomes visible.
@@ -3770,7 +3847,9 @@
             if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
                     + " (finish requested)");
             r.state = ActivityState.STOPPING;
-            mService.updateOomAdjLocked();
+            if (oomAdj) {
+                mService.updateOomAdjLocked();
+            }
             return r;
         }
 
@@ -3790,7 +3869,8 @@
                 || prevState == ActivityState.INITIALIZING) {
             // If this activity is already stopped, we can just finish
             // it right now.
-            boolean activityRemoved = destroyActivityLocked(r, true, true, "finish-imm");
+            boolean activityRemoved = destroyActivityLocked(r, true,
+                    oomAdj, "finish-imm");
             if (activityRemoved) {
                 resumeTopActivityLocked(null);
             }
@@ -3827,6 +3907,7 @@
         if (setState) {
             if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (cleaning up)");
             r.state = ActivityState.DESTROYED;
+            r.app = null;
         }
 
         // Make sure this record is no longer in the pending finishes list.
@@ -3870,26 +3951,26 @@
     }
 
     final void removeActivityFromHistoryLocked(ActivityRecord r) {
-        if (r.state != ActivityState.DESTROYED) {
-            finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
-            r.makeFinishing();
-            if (DEBUG_ADD_REMOVE) {
-                RuntimeException here = new RuntimeException("here");
-                here.fillInStackTrace();
-                Slog.i(TAG, "Removing activity " + r + " from stack");
-            }
-            mHistory.remove(r);
-            r.takeFromHistory();
-            if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
-                    + " (removed from history)");
-            r.state = ActivityState.DESTROYED;
-            mService.mWindowManager.removeAppToken(r.appToken);
-            if (VALIDATE_TOKENS) {
-                validateAppTokensLocked();
-            }
-            cleanUpActivityServicesLocked(r);
-            r.removeUriPermissionsLocked();
+        finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
+        r.makeFinishing();
+        if (DEBUG_ADD_REMOVE) {
+            RuntimeException here = new RuntimeException("here");
+            here.fillInStackTrace();
+            Slog.i(TAG, "Removing activity " + r + " from stack");
         }
+        mHistory.remove(r);
+        r.takeFromHistory();
+        removeTimeoutsForActivityLocked(r);
+        if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
+                + " (removed from history)");
+        r.state = ActivityState.DESTROYED;
+        r.app = null;
+        mService.mWindowManager.removeAppToken(r.appToken);
+        if (VALIDATE_TOKENS) {
+            validateAppTokensLocked();
+        }
+        cleanUpActivityServicesLocked(r);
+        r.removeUriPermissionsLocked();
     }
     
     /**
@@ -3901,7 +3982,7 @@
             Iterator<ConnectionRecord> it = r.connections.iterator();
             while (it.hasNext()) {
                 ConnectionRecord c = it.next();
-                mService.removeConnectionLocked(c, null, r);
+                mService.mServices.removeConnectionLocked(c, null, r);
             }
             r.connections = null;
         }
@@ -3957,19 +4038,19 @@
      */
     final boolean destroyActivityLocked(ActivityRecord r,
             boolean removeFromApp, boolean oomAdj, String reason) {
-        if (DEBUG_SWITCH) Slog.v(
+        if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(
             TAG, "Removing activity from " + reason + ": token=" + r
               + ", app=" + (r.app != null ? r.app.processName : "(null)"));
         EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
-                System.identityHashCode(r),
+                r.userId, System.identityHashCode(r),
                 r.task.taskId, r.shortComponentName, reason);
 
         boolean removedFromHistory = false;
-        
+
         cleanUpActivityLocked(r, false, false);
 
         final boolean hadApp = r.app != null;
-        
+
         if (hadApp) {
             if (removeFromApp) {
                 int idx = r.app.activities.indexOf(r);
@@ -3982,9 +4063,8 @@
                             ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
                 }
                 if (r.app.activities.size() == 0) {
-                    // No longer have activities, so update location in
-                    // LRU list.
-                    mService.updateLruProcessLocked(r.app, oomAdj, false);
+                    // No longer have activities, so update oom adj.
+                    mService.updateOomAdjLocked();
                 }
             }
 
@@ -4006,7 +4086,6 @@
                 }
             }
 
-            r.app = null;
             r.nowVisible = false;
             
             // If the activity is finishing, we need to wait on removing it
@@ -4027,6 +4106,7 @@
                 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
                         + " (destroy skipped)");
                 r.state = ActivityState.DESTROYED;
+                r.app = null;
             }
         } else {
             // remove this record from the history.
@@ -4037,6 +4117,7 @@
                 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
                         + " (no app)");
                 r.state = ActivityState.DESTROYED;
+                r.app = null;
             }
         }
 
@@ -4072,30 +4153,85 @@
         }
     }
     
-    private void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
+    private void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app,
+            String listName) {
         int i = list.size();
-        if (localLOGV) Slog.v(
-            TAG, "Removing app " + app + " from list " + list
+        if (DEBUG_CLEANUP) Slog.v(
+            TAG, "Removing app " + app + " from list " + listName
             + " with " + i + " entries");
         while (i > 0) {
             i--;
             ActivityRecord r = (ActivityRecord)list.get(i);
-            if (localLOGV) Slog.v(
-                TAG, "Record #" + i + " " + r + ": app=" + r.app);
+            if (DEBUG_CLEANUP) Slog.v(TAG, "Record #" + i + " " + r);
             if (r.app == app) {
-                if (localLOGV) Slog.v(TAG, "Removing this entry!");
+                if (DEBUG_CLEANUP) Slog.v(TAG, "---> REMOVING this entry!");
                 list.remove(i);
                 removeTimeoutsForActivityLocked(r);
             }
         }
     }
 
-    void removeHistoryRecordsForAppLocked(ProcessRecord app) {
-        removeHistoryRecordsForAppLocked(mLRUActivities, app);
-        removeHistoryRecordsForAppLocked(mStoppingActivities, app);
-        removeHistoryRecordsForAppLocked(mGoingToSleepActivities, app);
-        removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
-        removeHistoryRecordsForAppLocked(mFinishingActivities, app);
+    boolean removeHistoryRecordsForAppLocked(ProcessRecord app) {
+        removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities");
+        removeHistoryRecordsForAppLocked(mStoppingActivities, app, "mStoppingActivities");
+        removeHistoryRecordsForAppLocked(mGoingToSleepActivities, app, "mGoingToSleepActivities");
+        removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app,
+                "mWaitingVisibleActivities");
+        removeHistoryRecordsForAppLocked(mFinishingActivities, app, "mFinishingActivities");
+
+        boolean hasVisibleActivities = false;
+
+        // Clean out the history list.
+        int i = mHistory.size();
+        if (DEBUG_CLEANUP) Slog.v(
+            TAG, "Removing app " + app + " from history with " + i + " entries");
+        while (i > 0) {
+            i--;
+            ActivityRecord r = (ActivityRecord)mHistory.get(i);
+            if (DEBUG_CLEANUP) Slog.v(
+                TAG, "Record #" + i + " " + r + ": app=" + r.app);
+            if (r.app == app) {
+                if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
+                    if (ActivityStack.DEBUG_ADD_REMOVE || DEBUG_CLEANUP) {
+                        RuntimeException here = new RuntimeException("here");
+                        here.fillInStackTrace();
+                        Slog.i(TAG, "Removing activity " + r + " from stack at " + i
+                                + ": haveState=" + r.haveState
+                                + " stateNotNeeded=" + r.stateNotNeeded
+                                + " finishing=" + r.finishing
+                                + " state=" + r.state, here);
+                    }
+                    if (!r.finishing) {
+                        Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
+                        EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
+                                r.userId, System.identityHashCode(r),
+                                r.task.taskId, r.shortComponentName,
+                                "proc died without state saved");
+                    }
+                    removeActivityFromHistoryLocked(r);
+
+                } else {
+                    // We have the current state for this activity, so
+                    // it can be restarted later when needed.
+                    if (localLOGV) Slog.v(
+                        TAG, "Keeping entry, setting app to null");
+                    if (r.visible) {
+                        hasVisibleActivities = true;
+                    }
+                    r.app = null;
+                    r.nowVisible = false;
+                    if (!r.haveState) {
+                        if (ActivityStack.DEBUG_SAVED_STATE) Slog.i(TAG,
+                                "App died, clearing saved state of " + r);
+                        r.icicle = null;
+                    }
+                }
+
+                r.stack.cleanUpActivityLocked(r, true, true);
+            }
+        }
+
+        return hasVisibleActivities;
     }
     
     /**
@@ -4194,7 +4330,7 @@
         }
 
         finishTaskMoveLocked(task);
-        EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
+        EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, task);
     }
 
     private final void finishTaskMoveLocked(int task) {
@@ -4288,18 +4424,36 @@
         finishTaskMoveLocked(task);
         return true;
     }
-    
+
     public ActivityManager.TaskThumbnails getTaskThumbnailsLocked(TaskRecord tr) {
         TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true);
         ActivityRecord resumed = mResumedActivity;
         if (resumed != null && resumed.thumbHolder == tr) {
             info.mainThumbnail = resumed.stack.screenshotActivities(resumed);
-        } else {
+        }
+        if (info.mainThumbnail == null) {
             info.mainThumbnail = tr.lastThumbnail;
         }
         return info;
     }
 
+    public Bitmap getTaskTopThumbnailLocked(TaskRecord tr) {
+        ActivityRecord resumed = mResumedActivity;
+        if (resumed != null && resumed.task == tr) {
+            // This task is the current resumed task, we just need to take
+            // a screenshot of it and return that.
+            return resumed.stack.screenshotActivities(resumed);
+        }
+        // Return the information about the task, to figure out the top
+        // thumbnail to return.
+        TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true);
+        if (info.numSubThumbbails <= 0) {
+            return info.mainThumbnail != null ? info.mainThumbnail : tr.lastThumbnail;
+        } else {
+            return info.subtasks.get(info.numSubThumbbails-1).holder.lastThumbnail;
+        }
+    }
+
     public ActivityRecord removeTaskActivitiesLocked(int taskId, int subTaskIndex,
             boolean taskRequired) {
         TaskAccessInfo info = getTaskAccessInfoLocked(taskId, false);
@@ -4323,14 +4477,13 @@
             return null;
         }
 
-        // Remove all of this task's activies starting at the sub task.
+        // Remove all of this task's activities starting at the sub task.
         TaskAccessInfo.SubTask subtask = info.subtasks.get(subTaskIndex);
         performClearTaskAtIndexLocked(taskId, subtask.index);
         return subtask.activity;
     }
 
     public TaskAccessInfo getTaskAccessInfoLocked(int taskId, boolean inclThumbs) {
-        ActivityRecord resumed = mResumedActivity;
         final TaskAccessInfo thumbs = new TaskAccessInfo();
         // How many different sub-thumbnails?
         final int NA = mHistory.size();
@@ -4339,7 +4492,13 @@
         while (j < NA) {
             ActivityRecord ar = mHistory.get(j);
             if (!ar.finishing && ar.task.taskId == taskId) {
+                thumbs.root = ar;
+                thumbs.rootIndex = j;
                 holder = ar.thumbHolder;
+                if (holder != null) {
+                    thumbs.mainThumbnail = holder.lastThumbnail;
+                }
+                j++;
                 break;
             }
             j++;
@@ -4349,12 +4508,8 @@
             return thumbs;
         }
 
-        thumbs.root = mHistory.get(j);
-        thumbs.rootIndex = j;
-
         ArrayList<TaskAccessInfo.SubTask> subtasks = new ArrayList<TaskAccessInfo.SubTask>();
         thumbs.subtasks = subtasks;
-        ActivityRecord lastActivity = null;
         while (j < NA) {
             ActivityRecord ar = mHistory.get(j);
             j++;
@@ -4364,30 +4519,28 @@
             if (ar.task.taskId != taskId) {
                 break;
             }
-            lastActivity = ar;
             if (ar.thumbHolder != holder && holder != null) {
                 thumbs.numSubThumbbails++;
                 holder = ar.thumbHolder;
                 TaskAccessInfo.SubTask sub = new TaskAccessInfo.SubTask();
-                sub.thumbnail = holder.lastThumbnail;
+                sub.holder = holder;
                 sub.activity = ar;
                 sub.index = j-1;
                 subtasks.add(sub);
             }
         }
-        if (lastActivity != null && subtasks.size() > 0) {
-            if (resumed == lastActivity) {
-                TaskAccessInfo.SubTask sub = subtasks.get(subtasks.size()-1);
-                sub.thumbnail = lastActivity.stack.screenshotActivities(lastActivity);
-            }
-        }
         if (thumbs.numSubThumbbails > 0) {
             thumbs.retriever = new IThumbnailRetriever.Stub() {
                 public Bitmap getThumbnail(int index) {
                     if (index < 0 || index >= thumbs.subtasks.size()) {
                         return null;
                     }
-                    return thumbs.subtasks.get(index).thumbnail;
+                    TaskAccessInfo.SubTask sub = thumbs.subtasks.get(index);
+                    ActivityRecord resumed = mResumedActivity;
+                    if (resumed != null && resumed.thumbHolder == sub.holder) {
+                        return resumed.stack.screenshotActivities(resumed);
+                    }
+                    return sub.holder.lastThumbnail;
                 }
             };
         }
@@ -4397,7 +4550,7 @@
     private final void logStartActivity(int tag, ActivityRecord r,
             TaskRecord task) {
         EventLog.writeEvent(tag,
-                System.identityHashCode(r), task.taskId,
+                r.userId, System.identityHashCode(r), task.taskId,
                 r.shortComponentName, r.intent.getAction(),
                 r.intent.getType(), r.intent.getDataString(),
                 r.intent.getFlags());
@@ -4539,7 +4692,7 @@
                 + " with results=" + results + " newIntents=" + newIntents
                 + " andResume=" + andResume);
         EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
-                : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
+                : EventLogTags.AM_RELAUNCH_ACTIVITY, r.userId, System.identityHashCode(r),
                 r.task.taskId, r.shortComponentName);
         
         r.startFreezingScreenLocked(r.app, 0);
diff --git a/services/java/com/android/server/am/AppErrorDialog.java b/services/java/com/android/server/am/AppErrorDialog.java
index 57e11cf..ffa1e92 100644
--- a/services/java/com/android/server/am/AppErrorDialog.java
+++ b/services/java/com/android/server/am/AppErrorDialog.java
@@ -23,12 +23,10 @@
 import android.content.res.Resources;
 import android.os.Handler;
 import android.os.Message;
-import android.util.Slog;
 import android.view.WindowManager;
 
 class AppErrorDialog extends BaseErrorDialog {
-    private final static String TAG = "AppErrorDialog";
-
+    private final ActivityManagerService mService;
     private final AppErrorResult mResult;
     private final ProcessRecord mProc;
 
@@ -39,11 +37,13 @@
     // 5-minute timeout, then we automatically dismiss the crash dialog
     static final long DISMISS_TIMEOUT = 1000 * 60 * 5;
     
-    public AppErrorDialog(Context context, AppErrorResult result, ProcessRecord app) {
+    public AppErrorDialog(Context context, ActivityManagerService service,
+            AppErrorResult result, ProcessRecord app) {
         super(context);
         
         Resources res = context.getResources();
         
+        mService = service;
         mProc = app;
         mResult = result;
         CharSequence name;
@@ -73,7 +73,10 @@
 
         setTitle(res.getText(com.android.internal.R.string.aerr_title));
         getWindow().addFlags(FLAG_SYSTEM_ERROR);
-        getWindow().setTitle("Application Error: " + app.info.processName);
+        WindowManager.LayoutParams attrs = getWindow().getAttributes();
+        attrs.setTitle("Application Error: " + app.info.processName);
+        attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+        getWindow().setAttributes(attrs);
         if (app.persistent) {
             getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
         }
@@ -86,7 +89,7 @@
 
     private final Handler mHandler = new Handler() {
         public void handleMessage(Message msg) {
-            synchronized (mProc) {
+            synchronized (mService) {
                 if (mProc != null && mProc.crashDialog == AppErrorDialog.this) {
                     mProc.crashDialog = null;
                 }
diff --git a/services/java/com/android/server/am/AppNotRespondingDialog.java b/services/java/com/android/server/am/AppNotRespondingDialog.java
index b546ae7..af61c9b 100644
--- a/services/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/java/com/android/server/am/AppNotRespondingDialog.java
@@ -25,8 +25,8 @@
 import android.content.res.Resources;
 import android.os.Handler;
 import android.os.Message;
-import android.os.Process;
 import android.util.Slog;
+import android.view.WindowManager;
 
 class AppNotRespondingDialog extends BaseErrorDialog {
     private static final String TAG = "AppNotRespondingDialog";
@@ -40,7 +40,7 @@
     private final ProcessRecord mProc;
     
     public AppNotRespondingDialog(ActivityManagerService service, Context context,
-            ProcessRecord app, ActivityRecord activity) {
+            ProcessRecord app, ActivityRecord activity, boolean aboveSystem) {
         super(context);
         
         mService = service;
@@ -91,8 +91,14 @@
         }
 
         setTitle(res.getText(com.android.internal.R.string.anr_title));
+        if (aboveSystem) {
+            getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+        }
         getWindow().addFlags(FLAG_SYSTEM_ERROR);
-        getWindow().setTitle("Application Not Responding: " + app.info.processName);
+        WindowManager.LayoutParams attrs = getWindow().getAttributes();
+        attrs.setTitle("Application Not Responding: " + app.info.processName);
+        attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+        getWindow().setAttributes(attrs);
     }
 
     public void onStop() {
diff --git a/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java b/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java
index 9fb48b3..d08bb10 100644
--- a/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java
+++ b/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java
@@ -20,6 +20,7 @@
 import android.content.DialogInterface;
 import android.os.Handler;
 import android.os.Message;
+import android.view.WindowManager;
 
 class AppWaitingForDebuggerDialog extends BaseErrorDialog {
     final ActivityManagerService mService;
@@ -52,7 +53,9 @@
         setMessage(text.toString());
         setButton(DialogInterface.BUTTON_POSITIVE, "Force Close", mHandler.obtainMessage(1, app));
         setTitle("Waiting For Debugger");
-        getWindow().setTitle("Waiting For Debugger: " + app.info.processName);
+        WindowManager.LayoutParams attrs = getWindow().getAttributes();
+        attrs.setTitle("Waiting For Debugger: " + app.info.processName);
+        getWindow().setAttributes(attrs);
     }
     
     public void onStop() {
diff --git a/services/java/com/android/server/am/BaseErrorDialog.java b/services/java/com/android/server/am/BaseErrorDialog.java
index d1e89bc..6ede8f8 100644
--- a/services/java/com/android/server/am/BaseErrorDialog.java
+++ b/services/java/com/android/server/am/BaseErrorDialog.java
@@ -33,7 +33,9 @@
         getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
         getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
-        getWindow().setTitle("Error Dialog");
+        WindowManager.LayoutParams attrs = getWindow().getAttributes();
+        attrs.setTitle("Error Dialog");
+        getWindow().setAttributes(attrs);
         setIconAttribute(R.attr.alertDialogIcon);
     }
 
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index 8f797ec..ab20208 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -346,18 +346,18 @@
             mStats.noteFullWifiLockReleasedLocked(uid);
         }
     }
-    
-    public void noteScanWifiLockAcquired(int uid) {
+
+    public void noteWifiScanStarted(int uid) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteScanWifiLockAcquiredLocked(uid);
+            mStats.noteWifiScanStartedLocked(uid);
         }
     }
-    
-    public void noteScanWifiLockReleased(int uid) {
+
+    public void noteWifiScanStopped(int uid) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteScanWifiLockReleasedLocked(uid);
+            mStats.noteWifiScanStoppedLocked(uid);
         }
     }
 
@@ -389,17 +389,17 @@
         }
     }
 
-    public void noteScanWifiLockAcquiredFromSource(WorkSource ws) {
+    public void noteWifiScanStartedFromSource(WorkSource ws) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteScanWifiLockAcquiredFromSourceLocked(ws);
+            mStats.noteWifiScanStartedFromSourceLocked(ws);
         }
     }
 
-    public void noteScanWifiLockReleasedFromSource(WorkSource ws) {
+    public void noteWifiScanStoppedFromSource(WorkSource ws) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteScanWifiLockReleasedFromSourceLocked(ws);
+            mStats.noteWifiScanStoppedFromSourceLocked(ws);
         }
     }
 
diff --git a/services/java/com/android/server/am/BroadcastFilter.java b/services/java/com/android/server/am/BroadcastFilter.java
index b49bc22..c631b6e 100644
--- a/services/java/com/android/server/am/BroadcastFilter.java
+++ b/services/java/com/android/server/am/BroadcastFilter.java
@@ -27,13 +27,17 @@
     final ReceiverList receiverList;
     final String packageName;
     final String requiredPermission;
+    final int owningUid;
+    final int owningUserId;
 
     BroadcastFilter(IntentFilter _filter, ReceiverList _receiverList,
-            String _packageName, String _requiredPermission) {
+            String _packageName, String _requiredPermission, int _owningUid, int _userId) {
         super(_filter);
         receiverList = _receiverList;
         packageName = _packageName;
         requiredPermission = _requiredPermission;
+        owningUid = _owningUid;
+        owningUserId = _userId;
     }
     
     public void dump(PrintWriter pw, String prefix) {
@@ -60,6 +64,8 @@
         StringBuilder sb = new StringBuilder();
         sb.append("BroadcastFilter{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(" u");
+        sb.append(owningUserId);
         sb.append(' ');
         sb.append(receiverList);
         sb.append('}');
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index 47b8c0a..f9630ae 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -20,12 +20,15 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
+import android.app.ActivityManager;
 import android.app.AppGlobals;
 import android.content.ComponentName;
 import android.content.IIntentReceiver;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -33,7 +36,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.EventLog;
 import android.util.Slog;
 
@@ -51,6 +54,7 @@
     static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU;
 
     static final int MAX_BROADCAST_HISTORY = 25;
+    static final int MAX_BROADCAST_SUMMARY_HISTORY = 100;
 
     final ActivityManagerService mService;
 
@@ -90,6 +94,12 @@
             = new BroadcastRecord[MAX_BROADCAST_HISTORY];
 
     /**
+     * Summary of historical data of past broadcasts, for debugging.
+     */
+    final Intent[] mBroadcastSummaryHistory
+            = new Intent[MAX_BROADCAST_SUMMARY_HISTORY];
+
+    /**
      * Set when we current have a BROADCAST_INTENT_MSG in flight.
      */
     boolean mBroadcastsScheduled = false;
@@ -148,7 +158,7 @@
 
         @Override
         public void run() {
-            mService.appNotResponding(mApp, null, null, mAnnotation);
+            mService.appNotResponding(mApp, null, null, false, mAnnotation);
         }
     }
 
@@ -206,7 +216,7 @@
         r.receiver = app.thread.asBinder();
         r.curApp = app;
         app.curReceiver = r;
-        mService.updateLruProcessLocked(app, true, true);
+        mService.updateLruProcessLocked(app, true);
 
         // Tell the application to launch this receiver.
         r.intent.setComponent(r.curComponent);
@@ -219,7 +229,7 @@
             mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
             app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
                     mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
-                    r.resultCode, r.resultData, r.resultExtras, r.ordered);
+                    r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId);
             if (DEBUG_BROADCAST)  Slog.v(TAG,
                     "Process cur broadcast " + r + " DELIVERED for app " + app);
             started = true;
@@ -249,7 +259,7 @@
                 finishReceiverLocked(br, br.resultCode, br.resultData,
                         br.resultExtras, br.resultAbort, true);
                 scheduleBroadcastsLocked();
-                // We need to reset the state if we fails to start the receiver.
+                // We need to reset the state if we failed to start the receiver.
                 br.state = BroadcastRecord.IDLE;
                 throw new RuntimeException(e.getMessage());
             }
@@ -354,15 +364,16 @@
 
     private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
             Intent intent, int resultCode, String data, Bundle extras,
-            boolean ordered, boolean sticky) throws RemoteException {
+            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
         // Send the intent to the receiver asynchronously using one-way binder calls.
         if (app != null && app.thread != null) {
             // If we have an app thread, do the call through that so it is
             // correctly ordered with other one-way calls.
             app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
-                    data, extras, ordered, sticky);
+                    data, extras, ordered, sticky, sendingUser);
         } else {
-            receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
+            receiver.performReceive(intent, resultCode, data, extras, ordered,
+                    sticky, sendingUser);
         }
     }
 
@@ -382,7 +393,7 @@
                 skip = true;
             }
         }
-        if (r.requiredPermission != null) {
+        if (!skip && r.requiredPermission != null) {
             int perm = mService.checkComponentPermission(r.requiredPermission,
                     filter.receiverList.pid, filter.receiverList.uid, -1, true);
             if (perm != PackageManager.PERMISSION_GRANTED) {
@@ -425,8 +436,8 @@
                             + " (seq=" + seq + "): " + r);
                 }
                 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
-                    new Intent(r.intent), r.resultCode,
-                    r.resultData, r.resultExtras, r.ordered, r.initialSticky);
+                    new Intent(r.intent), r.resultCode, r.resultData,
+                    r.resultExtras, r.ordered, r.initialSticky, r.userId);
                 if (ordered) {
                     r.state = BroadcastRecord.CALL_DONE_RECEIVE;
                 }
@@ -576,7 +587,7 @@
                             }
                             performReceiveLocked(r.callerApp, r.resultTo,
                                 new Intent(r.intent), r.resultCode,
-                                r.resultData, r.resultExtras, false, false);
+                                r.resultData, r.resultExtras, false, false, r.userId);
                             // Set this to null so that the reference
                             // (local and remote) isnt kept in the mBroadcastHistory.
                             r.resultTo = null;
@@ -649,6 +660,9 @@
 
             ResolveInfo info =
                 (ResolveInfo)nextReceiver;
+            ComponentName component = new ComponentName(
+                    info.activityInfo.applicationInfo.packageName,
+                    info.activityInfo.name);
 
             boolean skip = false;
             int perm = mService.checkComponentPermission(info.activityInfo.permission,
@@ -661,16 +675,14 @@
                             + " from " + r.callerPackage + " (pid=" + r.callingPid
                             + ", uid=" + r.callingUid + ")"
                             + " is not exported from uid " + info.activityInfo.applicationInfo.uid
-                            + " due to receiver " + info.activityInfo.packageName
-                            + "/" + info.activityInfo.name);
+                            + " due to receiver " + component.flattenToShortString());
                 } else {
                     Slog.w(TAG, "Permission Denial: broadcasting "
                             + r.intent.toString()
                             + " from " + r.callerPackage + " (pid=" + r.callingPid
                             + ", uid=" + r.callingUid + ")"
                             + " requires " + info.activityInfo.permission
-                            + " due to receiver " + info.activityInfo.packageName
-                            + "/" + info.activityInfo.name);
+                            + " due to receiver " + component.flattenToShortString());
                 }
                 skip = true;
             }
@@ -686,13 +698,33 @@
                 if (perm != PackageManager.PERMISSION_GRANTED) {
                     Slog.w(TAG, "Permission Denial: receiving "
                             + r.intent + " to "
-                            + info.activityInfo.applicationInfo.packageName
+                            + component.flattenToShortString()
                             + " requires " + r.requiredPermission
                             + " due to sender " + r.callerPackage
                             + " (uid " + r.callingUid + ")");
                     skip = true;
                 }
             }
+            boolean isSingleton = false;
+            try {
+                isSingleton = mService.isSingleton(info.activityInfo.processName,
+                        info.activityInfo.applicationInfo,
+                        info.activityInfo.name, info.activityInfo.flags);
+            } catch (SecurityException e) {
+                Slog.w(TAG, e.getMessage());
+                skip = true;
+            }
+            if ((info.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
+                if (ActivityManager.checkUidPermission(
+                        android.Manifest.permission.INTERACT_ACROSS_USERS,
+                        info.activityInfo.applicationInfo.uid)
+                                != PackageManager.PERMISSION_GRANTED) {
+                    Slog.w(TAG, "Permission Denial: Receiver " + component.flattenToShortString()
+                            + " requests FLAG_SINGLE_USER, but app does not hold "
+                            + android.Manifest.permission.INTERACT_ACROSS_USERS);
+                    skip = true;
+                }
+            }
             if (r.curApp != null && r.curApp.crashing) {
                 // If the target process is crashing, just skip it.
                 if (DEBUG_BROADCAST)  Slog.v(TAG,
@@ -715,17 +747,12 @@
 
             r.state = BroadcastRecord.APP_RECEIVE;
             String targetProcess = info.activityInfo.processName;
-            r.curComponent = new ComponentName(
-                    info.activityInfo.applicationInfo.packageName,
-                    info.activityInfo.name);
-            if (r.callingUid != Process.SYSTEM_UID) {
-                boolean isSingleton = mService.isSingleton(info.activityInfo.processName,
-                        info.activityInfo.applicationInfo);
-                int targetUserId = isSingleton ? 0 : UserId.getUserId(r.callingUid);
-                info.activityInfo = mService.getActivityInfoForUser(info.activityInfo,targetUserId);
+            r.curComponent = component;
+            if (r.callingUid != Process.SYSTEM_UID && isSingleton) {
+                info.activityInfo = mService.getActivityInfoForUser(info.activityInfo, 0);
             }
             r.curReceiver = info.activityInfo;
-            if (DEBUG_MU && r.callingUid > UserId.PER_USER_RANGE) {
+            if (DEBUG_MU && r.callingUid > UserHandle.PER_USER_RANGE) {
                 Slog.v(TAG_MU, "Updated broadcast record activity info for secondary user, "
                         + info.activityInfo + ", callingUid = " + r.callingUid + ", uid = "
                         + info.activityInfo.applicationInfo.uid);
@@ -734,7 +761,7 @@
             // Broadcast is being executed, its package can't be stopped.
             try {
                 AppGlobals.getPackageManager().setPackageStoppedState(
-                        r.curComponent.getPackageName(), false, UserId.getUserId(r.callingUid));
+                        r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));
             } catch (RemoteException e) {
             } catch (IllegalArgumentException e) {
                 Slog.w(TAG, "Failed trying to unstop package "
@@ -902,6 +929,9 @@
                 MAX_BROADCAST_HISTORY-1);
         r.finishTime = SystemClock.uptimeMillis();
         mBroadcastHistory[0] = r;
+        System.arraycopy(mBroadcastSummaryHistory, 0, mBroadcastSummaryHistory, 1,
+                MAX_BROADCAST_SUMMARY_HISTORY-1);
+        mBroadcastSummaryHistory[0] = r.intent;
     }
 
     final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
@@ -910,22 +940,22 @@
             if (curReceiver instanceof BroadcastFilter) {
                 BroadcastFilter bf = (BroadcastFilter) curReceiver;
                 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
-                        System.identityHashCode(r),
+                        bf.owningUserId, System.identityHashCode(r),
                         r.intent.getAction(),
                         r.nextReceiver - 1,
                         System.identityHashCode(bf));
             } else {
+                ResolveInfo ri = (ResolveInfo)curReceiver;
                 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
-                        System.identityHashCode(r),
-                        r.intent.getAction(),
-                        r.nextReceiver - 1,
-                        ((ResolveInfo)curReceiver).toString());
+                        UserHandle.getUserId(ri.activityInfo.applicationInfo.uid),
+                        System.identityHashCode(r), r.intent.getAction(),
+                        r.nextReceiver - 1, ri.toString());
             }
         } else {
             Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
                     + r);
             EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
-                    System.identityHashCode(r),
+                    -1, System.identityHashCode(r),
                     r.intent.getAction(),
                     r.nextReceiver,
                     "NONE");
@@ -945,12 +975,12 @@
                 if (!printed) {
                     if (needSep) {
                         pw.println();
-                        needSep = false;
                     }
+                    needSep = true;
                     printed = true;
                     pw.println("  Active broadcasts [" + mQueueName + "]:");
                 }
-                pw.println("  Broadcast #" + i + ":");
+                pw.println("  Active Broadcast " + mQueueName + " #" + i + ":");
                 br.dump(pw, "    ");
             }
             printed = false;
@@ -965,9 +995,10 @@
                         pw.println();
                     }
                     needSep = true;
+                    printed = true;
                     pw.println("  Active ordered broadcasts [" + mQueueName + "]:");
                 }
-                pw.println("  Ordered Broadcast #" + i + ":");
+                pw.println("  Active Ordered Broadcast " + mQueueName + " #" + i + ":");
                 mOrderedBroadcasts.get(i).dump(pw, "    ");
             }
             if (dumpPackage == null || (mPendingBroadcast != null
@@ -985,8 +1016,9 @@
             }
         }
 
+        int i;
         boolean printed = false;
-        for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
+        for (i=0; i<MAX_BROADCAST_HISTORY; i++) {
             BroadcastRecord r = mBroadcastHistory[i];
             if (r == null) {
                 break;
@@ -1003,14 +1035,48 @@
                 printed = true;
             }
             if (dumpAll) {
-                pw.print("  Historical Broadcast #"); pw.print(i); pw.println(":");
+                pw.print("  Historical Broadcast " + mQueueName + " #");
+                        pw.print(i); pw.println(":");
                 r.dump(pw, "    ");
             } else {
-                if (i >= 50) {
+                pw.print("  #"); pw.print(i); pw.print(": "); pw.println(r);
+                pw.print("    ");
+                pw.println(r.intent.toShortString(false, true, true, false));
+                Bundle bundle = r.intent.getExtras();
+                if (bundle != null) {
+                    pw.print("    extras: "); pw.println(bundle.toString());
+                }
+            }
+        }
+
+        if (dumpPackage == null) {
+            if (dumpAll) {
+                i = 0;
+                printed = false;
+            }
+            for (; i<MAX_BROADCAST_SUMMARY_HISTORY; i++) {
+                Intent intent = mBroadcastSummaryHistory[i];
+                if (intent == null) {
+                    break;
+                }
+                if (!printed) {
+                    if (needSep) {
+                        pw.println();
+                    }
+                    needSep = true;
+                    pw.println("  Historical broadcasts summary [" + mQueueName + "]:");
+                    printed = true;
+                }
+                if (!dumpAll && i >= 50) {
                     pw.println("  ...");
                     break;
                 }
-                pw.print("  #"); pw.print(i); pw.print(": "); pw.println(r);
+                pw.print("  #"); pw.print(i); pw.print(": ");
+                pw.println(intent.toShortString(false, true, true, false));
+                Bundle bundle = intent.getExtras();
+                if (bundle != null) {
+                    pw.print("    extras: "); pw.println(bundle.toString());
+                }
             }
         }
 
diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java
index dd560fc..1cf5b9c 100644
--- a/services/java/com/android/server/am/BroadcastRecord.java
+++ b/services/java/com/android/server/am/BroadcastRecord.java
@@ -44,6 +44,7 @@
     final boolean ordered;  // serialize the send to receivers?
     final boolean sticky;   // originated from existing sticky data?
     final boolean initialSticky; // initial broadcast from register to sticky?
+    final int userId;       // user id this broadcast was for
     final String requiredPermission; // a permission the caller has required
     final List receivers;   // contains BroadcastFilter and ResolveInfo
     IIntentReceiver resultTo; // who receives final result if non-null
@@ -79,13 +80,11 @@
     void dump(PrintWriter pw, String prefix) {
         final long now = SystemClock.uptimeMillis();
 
-        pw.print(prefix); pw.println(this);
-        pw.print(prefix); pw.println(intent);
-        if (sticky) {
-            Bundle bundle = intent.getExtras();
-            if (bundle != null) {
-                pw.print(prefix); pw.print("extras: "); pw.println(bundle.toString());
-            }
+        pw.print(prefix); pw.print(this); pw.print(" to user "); pw.println(userId);
+        pw.print(prefix); pw.println(intent.toInsecureString());
+        Bundle bundle = intent.getExtras();
+        if (bundle != null) {
+            pw.print(prefix); pw.print("extras: "); pw.println(bundle.toString());
         }
         pw.print(prefix); pw.print("caller="); pw.print(callerPackage); pw.print(" ");
                 pw.print(callerApp != null ? callerApp.toShortString() : "null");
@@ -140,14 +139,15 @@
                         pw.println(curReceiver.applicationInfo.sourceDir);
             }
         }
-        String stateStr = " (?)";
-        switch (state) {
-            case IDLE:              stateStr=" (IDLE)"; break;
-            case APP_RECEIVE:       stateStr=" (APP_RECEIVE)"; break;
-            case CALL_IN_RECEIVE:   stateStr=" (CALL_IN_RECEIVE)"; break;
-            case CALL_DONE_RECEIVE: stateStr=" (CALL_DONE_RECEIVE)"; break;
+        if (state != IDLE) {
+            String stateStr = " (?)";
+            switch (state) {
+                case APP_RECEIVE:       stateStr=" (APP_RECEIVE)"; break;
+                case CALL_IN_RECEIVE:   stateStr=" (CALL_IN_RECEIVE)"; break;
+                case CALL_DONE_RECEIVE: stateStr=" (CALL_DONE_RECEIVE)"; break;
+            }
+            pw.print(prefix); pw.print("state="); pw.print(state); pw.println(stateStr);
         }
-        pw.print(prefix); pw.print("state="); pw.print(state); pw.println(stateStr);
         final int N = receivers != null ? receivers.size() : 0;
         String p2 = prefix + "  ";
         PrintWriterPrinter printer = new PrintWriterPrinter(pw);
@@ -167,7 +167,8 @@
             int _callingPid, int _callingUid, String _requiredPermission,
             List _receivers, IIntentReceiver _resultTo, int _resultCode,
             String _resultData, Bundle _resultExtras, boolean _serialized,
-            boolean _sticky, boolean _initialSticky) {
+            boolean _sticky, boolean _initialSticky,
+            int _userId) {
         queue = _queue;
         intent = _intent;
         callerApp = _callerApp;
@@ -183,6 +184,7 @@
         ordered = _serialized;
         sticky = _sticky;
         initialSticky = _initialSticky;
+        userId = _userId;
         nextReceiver = 0;
         state = IDLE;
     }
@@ -190,6 +192,6 @@
     public String toString() {
         return "BroadcastRecord{"
             + Integer.toHexString(System.identityHashCode(this))
-            + " " + intent.getAction() + "}";
+            + " u" + userId + " " + intent.getAction() + "}";
     }
 }
diff --git a/services/java/com/android/server/am/CompatModePackages.java b/services/java/com/android/server/am/CompatModePackages.java
index 3ba3fbb..3a6492e 100644
--- a/services/java/com/android/server/am/CompatModePackages.java
+++ b/services/java/com/android/server/am/CompatModePackages.java
@@ -4,7 +4,6 @@
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
 
@@ -12,7 +11,6 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
-import com.android.internal.os.AtomicFile;
 import com.android.internal.util.FastXmlSerializer;
 
 import android.app.ActivityManager;
@@ -24,6 +22,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.RemoteException;
+import android.util.AtomicFile;
 import android.util.Slog;
 import android.util.Xml;
 
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java
index 0106114..4ed3c31 100644
--- a/services/java/com/android/server/am/ConnectionRecord.java
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -18,6 +18,7 @@
 
 import android.app.IServiceConnection;
 import android.app.PendingIntent;
+import android.content.Context;
 
 import java.io.PrintWriter;
 
@@ -61,7 +62,39 @@
         StringBuilder sb = new StringBuilder(128);
         sb.append("ConnectionRecord{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(" u");
+        sb.append(binding.client.userId);
         sb.append(' ');
+        if ((flags&Context.BIND_AUTO_CREATE) != 0) {
+            sb.append("CR ");
+        }
+        if ((flags&Context.BIND_DEBUG_UNBIND) != 0) {
+            sb.append("DBG ");
+        }
+        if ((flags&Context.BIND_NOT_FOREGROUND) != 0) {
+            sb.append("!FG ");
+        }
+        if ((flags&Context.BIND_ABOVE_CLIENT) != 0) {
+            sb.append("ABCLT ");
+        }
+        if ((flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
+            sb.append("OOM ");
+        }
+        if ((flags&Context.BIND_WAIVE_PRIORITY) != 0) {
+            sb.append("WPRI ");
+        }
+        if ((flags&Context.BIND_IMPORTANT) != 0) {
+            sb.append("IMP ");
+        }
+        if ((flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
+            sb.append("ACT ");
+        }
+        if ((flags&Context.BIND_NOT_VISIBLE) != 0) {
+            sb.append("!VIS ");
+        }
+        if ((flags&Context.BIND_VISIBLE) != 0) {
+            sb.append("VIS ");
+        }
         if (serviceDead) {
             sb.append("DEAD ");
         }
diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/java/com/android/server/am/ContentProviderRecord.java
index fb21b06..8fb6a93 100644
--- a/services/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/java/com/android/server/am/ContentProviderRecord.java
@@ -25,6 +25,7 @@
 import android.os.IBinder.DeathRecipient;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.Slog;
 
 import java.io.PrintWriter;
@@ -38,6 +39,7 @@
     final int uid;
     final ApplicationInfo appInfo;
     final ComponentName name;
+    final boolean singleton;
     public IContentProvider provider;
     public boolean noReleaseNeeded;
     // All attached clients
@@ -54,12 +56,13 @@
     String shortStringName;
 
     public ContentProviderRecord(ActivityManagerService _service, ProviderInfo _info,
-            ApplicationInfo ai, ComponentName _name) {
+            ApplicationInfo ai, ComponentName _name, boolean _singleton) {
         service = _service;
         info = _info;
         uid = ai.uid;
         appInfo = ai;
         name = _name;
+        singleton = _singleton;
         noReleaseNeeded = uid == 0 || uid == Process.SYSTEM_UID;
     }
 
@@ -69,6 +72,7 @@
         uid = cpr.uid;
         appInfo = cpr.appInfo;
         name = cpr.name;
+        singleton = cpr.singleton;
         noReleaseNeeded = cpr.noReleaseNeeded;
     }
 
@@ -82,7 +86,7 @@
 
     public boolean canRunHere(ProcessRecord app) {
         return (info.multiprocess || info.processName.equals(app.processName))
-                && (uid == Process.SYSTEM_UID || uid == app.info.uid);
+                && uid == app.info.uid;
     }
 
     public void addExternalProcessHandleLocked(IBinder token) {
@@ -150,6 +154,9 @@
             pw.print(prefix); pw.print("uid="); pw.print(uid);
                     pw.print(" provider="); pw.println(provider);
         }
+        if (singleton) {
+            pw.print(prefix); pw.print("singleton="); pw.println(singleton);
+        }
         pw.print(prefix); pw.print("authority="); pw.println(info.authority);
         if (full) {
             if (info.isSyncable || info.multiprocess || info.initOrder != 0) {
@@ -193,6 +200,8 @@
         StringBuilder sb = new StringBuilder(128);
         sb.append("ContentProviderRecord{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(" u");
+        sb.append(UserHandle.getUserId(uid));
         sb.append(' ');
         sb.append(name.flattenToShortString());
         sb.append('}');
diff --git a/services/java/com/android/server/am/EventLogTags.logtags b/services/java/com/android/server/am/EventLogTags.logtags
index a579f44..6ee7507 100644
--- a/services/java/com/android/server/am/EventLogTags.logtags
+++ b/services/java/com/android/server/am/EventLogTags.logtags
@@ -14,72 +14,72 @@
 # google3/googledata/wireless/android/provisioning/gservices.config !!
 #
 # An activity is being finished:
-30001 am_finish_activity (Token|1|5),(Task ID|1|5),(Component Name|3),(Reason|3)
+30001 am_finish_activity (User|1|5),(Token|1|5),(Task ID|1|5),(Component Name|3),(Reason|3)
 # A task is being brought to the front of the screen:
-30002 am_task_to_front (Task|1|5)
+30002 am_task_to_front (User|1|5),(Task|1|5)
 # An existing activity is being given a new intent:
-30003 am_new_intent (Token|1|5),(Task ID|1|5),(Component Name|3),(Action|3),(MIME Type|3),(URI|3),(Flags|1|5)
+30003 am_new_intent (User|1|5),(Token|1|5),(Task ID|1|5),(Component Name|3),(Action|3),(MIME Type|3),(URI|3),(Flags|1|5)
 # A new task is being created:
-30004 am_create_task (Task ID|1|5)
+30004 am_create_task (User|1|5),(Task ID|1|5)
 # A new activity is being created in an existing task:
-30005 am_create_activity (Token|1|5),(Task ID|1|5),(Component Name|3),(Action|3),(MIME Type|3),(URI|3),(Flags|1|5)
+30005 am_create_activity (User|1|5),(Token|1|5),(Task ID|1|5),(Component Name|3),(Action|3),(MIME Type|3),(URI|3),(Flags|1|5)
 # An activity has been resumed into the foreground but was not already running:
-30006 am_restart_activity (Token|1|5),(Task ID|1|5),(Component Name|3)
+30006 am_restart_activity (User|1|5),(Token|1|5),(Task ID|1|5),(Component Name|3)
 # An activity has been resumed and is now in the foreground:
-30007 am_resume_activity (Token|1|5),(Task ID|1|5),(Component Name|3)
+30007 am_resume_activity (User|1|5),(Token|1|5),(Task ID|1|5),(Component Name|3)
 # Application Not Responding
-30008 am_anr (pid|1|5),(Package Name|3),(Flags|1|5),(reason|3)
+30008 am_anr (User|1|5),(pid|1|5),(Package Name|3),(Flags|1|5),(reason|3)
 # Activity launch time
-30009 activity_launch_time (Token|1|5),(Component Name|3),(time|2|3)
+30009 am_activity_launch_time (User|1|5),(Token|1|5),(Component Name|3),(time|2|3)
 # Application process bound to work
-30010 am_proc_bound (PID|1|5),(Process Name|3)
+30010 am_proc_bound (User|1|5),(PID|1|5),(Process Name|3)
 # Application process died
-30011 am_proc_died (PID|1|5),(Process Name|3)
+30011 am_proc_died (User|1|5),(PID|1|5),(Process Name|3)
 # The Activity Manager failed to pause the given activity.
-30012 am_failed_to_pause (Token|1|5),(Wanting to pause|3),(Currently pausing|3)
+30012 am_failed_to_pause (User|1|5),(Token|1|5),(Wanting to pause|3),(Currently pausing|3)
 # Attempting to pause the current activity
-30013 am_pause_activity (Token|1|5),(Component Name|3)
+30013 am_pause_activity (User|1|5),(Token|1|5),(Component Name|3)
 # Application process has been started
-30014 am_proc_start (PID|1|5),(UID|1|5),(Process Name|3),(Type|3),(Component|3)
+30014 am_proc_start (User|1|5),(PID|1|5),(UID|1|5),(Process Name|3),(Type|3),(Component|3)
 # An application process has been marked as bad
-30015 am_proc_bad (UID|1|5),(Process Name|3)
+30015 am_proc_bad (User|1|5),(UID|1|5),(Process Name|3)
 # An application process that was bad is now marked as good
-30016 am_proc_good (UID|1|5),(Process Name|3)
+30016 am_proc_good (User|1|5),(UID|1|5),(Process Name|3)
 # Reporting to applications that memory is low
 30017 am_low_memory (Num Processes|1|1)
 # An activity is being destroyed:
-30018 am_destroy_activity (Token|1|5),(Task ID|1|5),(Component Name|3),(Reason|3)
+30018 am_destroy_activity (User|1|5),(Token|1|5),(Task ID|1|5),(Component Name|3),(Reason|3)
 # An activity has been relaunched, resumed, and is now in the foreground:
-30019 am_relaunch_resume_activity (Token|1|5),(Task ID|1|5),(Component Name|3)
+30019 am_relaunch_resume_activity (User|1|5),(Token|1|5),(Task ID|1|5),(Component Name|3)
 # An activity has been relaunched:
-30020 am_relaunch_activity (Token|1|5),(Task ID|1|5),(Component Name|3)
+30020 am_relaunch_activity (User|1|5),(Token|1|5),(Task ID|1|5),(Component Name|3)
 # The activity's onPause has been called.
-30021 am_on_paused_called (Component Name|3)
+30021 am_on_paused_called (User|1|5),(Component Name|3)
 # The activity's onResume has been called.
-30022 am_on_resume_called (Component Name|3)
+30022 am_on_resume_called (User|1|5),(Component Name|3)
 # Kill a process to reclaim memory.
-30023 am_kill (PID|1|5),(Process Name|3),(OomAdj|1|5),(Reason|3)
+30023 am_kill (User|1|5),(PID|1|5),(Process Name|3),(OomAdj|1|5),(Reason|3)
 # Discard an undelivered serialized broadcast (timeout/ANR/crash)
-30024 am_broadcast_discard_filter (Broadcast|1|5),(Action|3),(Receiver Number|1|1),(BroadcastFilter|1|5)
-30025 am_broadcast_discard_app (Broadcast|1|5),(Action|3),(Receiver Number|1|1),(App|3)
+30024 am_broadcast_discard_filter (User|1|5),(Broadcast|1|5),(Action|3),(Receiver Number|1|1),(BroadcastFilter|1|5)
+30025 am_broadcast_discard_app (User|1|5),(Broadcast|1|5),(Action|3),(Receiver Number|1|1),(App|3)
 # A service is being created
-30030 am_create_service (Service Record|1|5),(Name|3),(Intent|3),(PID|1|5)
+30030 am_create_service (User|1|5),(Service Record|1|5),(Name|3),(Intent|3),(PID|1|5)
 # A service is being destroyed
-30031 am_destroy_service (Service Record|1|5),(Name|3),(PID|1|5)
+30031 am_destroy_service (User|1|5),(Service Record|1|5),(Name|3),(PID|1|5)
 # A process has crashed too many times, it is being cleared
-30032 am_process_crashed_too_much (Name|3),(PID|1|5)
+30032 am_process_crashed_too_much (User|1|5),(Name|3),(PID|1|5)
 # An unknown process is trying to attach to the activity manager
 30033 am_drop_process (PID|1|5)
 # A service has crashed too many times, it is being stopped
-30034 am_service_crashed_too_much (Crash Count|1|1),(Component Name|3),(PID|1|5)
+30034 am_service_crashed_too_much (User|1|5),(Crash Count|1|1),(Component Name|3),(PID|1|5)
 # A service is going to be restarted after its process went away
-30035 am_schedule_service_restart (Component Name|3),(Time|2|3)
+30035 am_schedule_service_restart (User|1|5),(Component Name|3),(Time|2|3)
 # A client was waiting for a content provider, but its process was lost
-30036 am_provider_lost_process (Package Name|3),(UID|1|5),(Name|3)
+30036 am_provider_lost_process (User|1|5),(Package Name|3),(UID|1|5),(Name|3)
 # The activity manager gave up on a new process taking too long to start
-30037 am_process_start_timeout (PID|1|5),(UID|1|5),(Process Name|3)
+30037 am_process_start_timeout (User|1|5),(PID|1|5),(UID|1|5),(Process Name|3)
 
 # Unhandled exception
-30039 am_crash (PID|1|5),(Process Name|3),(Flags|1|5),(Exception|3),(Message|3),(File|3),(Line|1|5)
+30039 am_crash (User|1|5),(PID|1|5),(Process Name|3),(Flags|1|5),(Exception|3),(Message|3),(File|3),(Line|1|5)
 # Log.wtf() called
-30040 am_wtf (PID|1|5),(Process Name|3),(Flags|1|5),(Tag|3),(Message|3)
+30040 am_wtf (User|1|5),(PID|1|5),(Process Name|3),(Flags|1|5),(Tag|3),(Message|3)
diff --git a/services/java/com/android/server/am/FactoryErrorDialog.java b/services/java/com/android/server/am/FactoryErrorDialog.java
index b19bb5ca..0ffb588 100644
--- a/services/java/com/android/server/am/FactoryErrorDialog.java
+++ b/services/java/com/android/server/am/FactoryErrorDialog.java
@@ -20,6 +20,7 @@
 import android.content.DialogInterface;
 import android.os.Handler;
 import android.os.Message;
+import android.view.WindowManager;
 
 class FactoryErrorDialog extends BaseErrorDialog {
     public FactoryErrorDialog(Context context, CharSequence msg) {
@@ -30,7 +31,9 @@
         setButton(DialogInterface.BUTTON_POSITIVE,
                 context.getText(com.android.internal.R.string.factorytest_reboot),
                 mHandler.obtainMessage(0));
-        getWindow().setTitle("Factory Error");
+        WindowManager.LayoutParams attrs = getWindow().getAttributes();
+        attrs.setTitle("Factory Error");
+        getWindow().setAttributes(attrs);
     }
     
     public void onStop() {
diff --git a/services/java/com/android/server/am/IntentBindRecord.java b/services/java/com/android/server/am/IntentBindRecord.java
index c94f714..0a92964 100644
--- a/services/java/com/android/server/am/IntentBindRecord.java
+++ b/services/java/com/android/server/am/IntentBindRecord.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import android.content.Context;
 import android.content.Intent;
 import android.os.IBinder;
 
@@ -78,6 +79,20 @@
         intent = _intent;
     }
 
+    int collectFlags() {
+        int flags = 0;
+        if (apps.size() > 0) {
+            for (AppBindRecord app : apps.values()) {
+                if (app.connections.size() > 0) {
+                    for (ConnectionRecord conn : app.connections) {
+                        flags |= conn.flags;
+                    }
+                }
+            }
+        }
+        return flags;
+    }
+
     public String toString() {
         if (stringName != null) {
             return stringName;
@@ -86,6 +101,9 @@
         sb.append("IntentBindRecord{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
         sb.append(' ');
+        if ((collectFlags()&Context.BIND_AUTO_CREATE) != 0) {
+            sb.append("CR ");
+        }
         sb.append(service.shortName);
         sb.append(':');
         if (intent != null) {
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index ad15da1..8ee303f 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -25,7 +25,7 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.Slog;
 
 import java.io.PrintWriter;
@@ -54,11 +54,12 @@
         String[] allResolvedTypes;
         final int flags;
         final int hashCode;
+        final int userId;
         
         private static final int ODD_PRIME_NUMBER = 37;
         
         Key(int _t, String _p, ActivityRecord _a, String _w,
-                int _r, Intent[] _i, String[] _it, int _f, Bundle _o) {
+                int _r, Intent[] _i, String[] _it, int _f, Bundle _o, int _userId) {
             type = _t;
             packageName = _p;
             activity = _a;
@@ -70,10 +71,12 @@
             allResolvedTypes = _it;
             flags = _f;
             options = _o;
-            
+            userId = _userId;
+
             int hash = 23;
             hash = (ODD_PRIME_NUMBER*hash) + _f;
             hash = (ODD_PRIME_NUMBER*hash) + _r;
+            hash = (ODD_PRIME_NUMBER*hash) + _userId;
             if (_w != null) {
                 hash = (ODD_PRIME_NUMBER*hash) + _w.hashCode();
             }
@@ -102,6 +105,9 @@
                 if (type != other.type) {
                     return false;
                 }
+                if (userId != other.userId){
+                    return false;
+                }
                 if (!packageName.equals(other.packageName)) {
                     return false;
                 }
@@ -156,7 +162,7 @@
                 + " intent="
                 + (requestIntent != null
                         ? requestIntent.toShortString(false, true, false, false) : "<null>")
-                + " flags=0x" + Integer.toHexString(flags) + "}";
+                + " flags=0x" + Integer.toHexString(flags) + " u=" + userId + "}";
         }
         
         String typeName() {
@@ -215,6 +221,10 @@
                 final long origId = Binder.clearCallingIdentity();
                 
                 boolean sendFinish = finishedReceiver != null;
+                int userId = key.userId;
+                if (userId == UserHandle.USER_CURRENT) {
+                    userId = owner.getCurrentUserIdLocked();
+                }
                 switch (key.type) {
                     case ActivityManager.INTENT_SENDER_ACTIVITY:
                         if (options == null) {
@@ -237,11 +247,10 @@
                                 allIntents[allIntents.length-1] = finalIntent;
                                 allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
                                 owner.startActivitiesInPackage(uid, allIntents,
-                                        allResolvedTypes, resultTo, options);
+                                        allResolvedTypes, resultTo, options, userId);
                             } else {
-                                owner.startActivityInPackage(uid,
-                                        finalIntent, resolvedType,
-                                        resultTo, resultWho, requestCode, 0, options);
+                                owner.startActivityInPackage(uid, finalIntent, resolvedType,
+                                        resultTo, resultWho, requestCode, 0, options, userId);
                             }
                         } catch (RuntimeException e) {
                             Slog.w(ActivityManagerService.TAG,
@@ -259,8 +268,7 @@
                             owner.broadcastIntentInPackage(key.packageName, uid,
                                     finalIntent, resolvedType,
                                     finishedReceiver, code, null, null,
-                                requiredPermission, (finishedReceiver != null), false, UserId
-                                        .getUserId(uid));
+                                requiredPermission, (finishedReceiver != null), false, userId);
                             sendFinish = false;
                         } catch (RuntimeException e) {
                             Slog.w(ActivityManagerService.TAG,
@@ -270,7 +278,7 @@
                     case ActivityManager.INTENT_SENDER_SERVICE:
                         try {
                             owner.startServiceInPackage(uid,
-                                    finalIntent, resolvedType);
+                                    finalIntent, resolvedType, userId);
                         } catch (RuntimeException e) {
                             Slog.w(ActivityManagerService.TAG,
                                     "Unable to send startService intent", e);
@@ -281,7 +289,7 @@
                 if (sendFinish) {
                     try {
                         finishedReceiver.performReceive(new Intent(finalIntent), 0,
-                                null, null, false, false);
+                                null, null, false, false, key.userId);
                     } catch (RemoteException e) {
                     }
                 }
diff --git a/services/java/com/android/server/am/ProcessList.java b/services/java/com/android/server/am/ProcessList.java
index af7b314..9e25e30 100644
--- a/services/java/com/android/server/am/ProcessList.java
+++ b/services/java/com/android/server/am/ProcessList.java
@@ -24,6 +24,7 @@
 
 import android.graphics.Point;
 import android.util.Slog;
+import android.view.Display;
 
 /**
  * Activity manager code dealing with processes.
@@ -100,7 +101,24 @@
     // The maximum number of hidden processes we will keep around before
     // killing them; this is just a control to not let us go too crazy with
     // keeping around processes on devices with large amounts of RAM.
-    static final int MAX_HIDDEN_APPS = 15;
+    static final int MAX_HIDDEN_APPS = 24;
+
+    // We allow empty processes to stick around for at most 30 minutes.
+    static final long MAX_EMPTY_TIME = 30*60*1000;
+
+    // The number of hidden at which we don't consider it necessary to do
+    // memory trimming.
+    static final int TRIM_HIDDEN_APPS = 3;
+
+    // The number of empty apps at which we don't consider it necessary to do
+    // memory trimming.
+    static final int TRIM_EMPTY_APPS = 3;
+
+    // Threshold of number of hidden+empty where we consider memory critical.
+    static final int TRIM_CRITICAL_THRESHOLD = 3;
+
+    // Threshold of number of hidden+empty where we consider memory critical.
+    static final int TRIM_LOW_THRESHOLD = 5;
 
     // We put empty content processes after any hidden processes that have
     // been idle for less than 15 seconds.
@@ -146,7 +164,7 @@
     void applyDisplaySize(WindowManagerService wm) {
         if (!mHaveDisplaySize) {
             Point p = new Point();
-            wm.getInitialDisplaySize(p);
+            wm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, p);
             if (p.x != 0 && p.y != 0) {
                 updateOomLevels(p.x, p.y, true);
                 mHaveDisplaySize = true;
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index cba9480..7fbab04 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -30,7 +30,7 @@
 import android.os.IBinder;
 import android.os.Process;
 import android.os.SystemClock;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.PrintWriterPrinter;
 import android.util.TimeUtils;
 
@@ -61,6 +61,8 @@
     long lruWeight;             // Weight for ordering in LRU list
     int maxAdj;                 // Maximum OOM adjustment for this process
     int hiddenAdj;              // If hidden, this is the adjustment to use
+    int clientHiddenAdj;        // If empty but hidden client, this is the adjustment to use
+    int emptyAdj;               // If empty, this is the adjustment to use
     int curRawAdj;              // Current OOM unlimited adjustment for this process
     int setRawAdj;              // Last set OOM unlimited adjustment for this process
     int nonStoppingAdj;         // Adjustment not counting any stopping activities
@@ -73,6 +75,8 @@
     boolean serviceb;           // Process currently is on the service B list
     boolean keeping;            // Actively running code so don't kill due to that?
     boolean setIsForeground;    // Running foreground UI when last set?
+    boolean hasActivities;      // Are there any activities running in this process?
+    boolean hasClientActivities;  // Are there any client services with activities?
     boolean foregroundServices; // Running any services that are foreground?
     boolean foregroundActivities; // Running any activities that are foreground?
     boolean systemNoUi;         // This is a system process, but not currently showing UI.
@@ -186,8 +190,7 @@
                 instrumentationInfo.dump(new PrintWriterPrinter(pw), prefix + "  ");
             }
         }
-        pw.print(prefix); pw.print("thread="); pw.print(thread);
-                pw.print(" curReceiver="); pw.println(curReceiver);
+        pw.print(prefix); pw.print("thread="); pw.println(thread);
         pw.print(prefix); pw.print("pid="); pw.print(pid); pw.print(" starting=");
                 pw.print(starting); pw.print(" lastPss="); pw.println(lastPss);
         pw.print(prefix); pw.print("lastActivityTime=");
@@ -199,6 +202,8 @@
                 pw.print(" empty="); pw.println(empty);
         pw.print(prefix); pw.print("oom: max="); pw.print(maxAdj);
                 pw.print(" hidden="); pw.print(hiddenAdj);
+                pw.print(" client="); pw.print(clientHiddenAdj);
+                pw.print(" empty="); pw.print(emptyAdj);
                 pw.print(" curRaw="); pw.print(curRawAdj);
                 pw.print(" setRaw="); pw.print(setRawAdj);
                 pw.print(" nonStopping="); pw.print(nonStoppingAdj);
@@ -208,16 +213,27 @@
                 pw.print(" setSchedGroup="); pw.print(setSchedGroup);
                 pw.print(" systemNoUi="); pw.print(systemNoUi);
                 pw.print(" trimMemoryLevel="); pw.println(trimMemoryLevel);
-        pw.print(prefix); pw.print("hasShownUi="); pw.print(hasShownUi);
-                pw.print(" pendingUiClean="); pw.print(pendingUiClean);
-                pw.print(" hasAboveClient="); pw.println(hasAboveClient);
-        pw.print(prefix); pw.print("setIsForeground="); pw.print(setIsForeground);
-                pw.print(" foregroundServices="); pw.print(foregroundServices);
-                pw.print(" forcingToForeground="); pw.println(forcingToForeground);
-        pw.print(prefix); pw.print("persistent="); pw.print(persistent);
-                pw.print(" removed="); pw.println(removed);
         pw.print(prefix); pw.print("adjSeq="); pw.print(adjSeq);
                 pw.print(" lruSeq="); pw.println(lruSeq);
+        if (hasShownUi || pendingUiClean || hasAboveClient) {
+            pw.print(prefix); pw.print("hasShownUi="); pw.print(hasShownUi);
+                    pw.print(" pendingUiClean="); pw.print(pendingUiClean);
+                    pw.print(" hasAboveClient="); pw.println(hasAboveClient);
+        }
+        if (setIsForeground || foregroundServices || forcingToForeground != null) {
+            pw.print(prefix); pw.print("setIsForeground="); pw.print(setIsForeground);
+                    pw.print(" foregroundServices="); pw.print(foregroundServices);
+                    pw.print(" forcingToForeground="); pw.println(forcingToForeground);
+        }
+        if (persistent || removed) {
+            pw.print(prefix); pw.print("persistent="); pw.print(persistent);
+                    pw.print(" removed="); pw.println(removed);
+        }
+        if (hasActivities || hasClientActivities || foregroundActivities) {
+            pw.print(prefix); pw.print("hasActivities="); pw.print(hasActivities);
+                    pw.print(" hasClientActivities="); pw.print(hasClientActivities);
+                    pw.print(" foregroundActivities="); pw.println(foregroundActivities);
+        }
         if (!keeping) {
             long wtime;
             synchronized (batteryStats.getBatteryStats()) {
@@ -226,10 +242,10 @@
             }
             long timeUsed = wtime - lastWakeTime;
             pw.print(prefix); pw.print("lastWakeTime="); pw.print(lastWakeTime);
-                    pw.print(" time used=");
+                    pw.print(" timeUsed=");
                     TimeUtils.formatDuration(timeUsed, pw); pw.println("");
             pw.print(prefix); pw.print("lastCpuTime="); pw.print(lastCpuTime);
-                    pw.print(" time used=");
+                    pw.print(" timeUsed=");
                     TimeUtils.formatDuration(curCpuTime-lastCpuTime, pw); pw.println("");
         }
         pw.print(prefix); pw.print("lastRequestedGc=");
@@ -294,6 +310,9 @@
                 pw.print(prefix); pw.print("  - "); pw.println(conProviders.get(i).toShortString());
             }
         }
+        if (curReceiver != null) {
+            pw.print(prefix); pw.print("curReceiver="); pw.println(curReceiver);
+        }
         if (receivers.size() > 0) {
             pw.print(prefix); pw.println("Receivers:");
             for (ReceiverList rl : receivers) {
@@ -308,12 +327,12 @@
         info = _info;
         isolated = _info.uid != _uid;
         uid = _uid;
-        userId = UserId.getUserId(_uid);
+        userId = UserHandle.getUserId(_uid);
         processName = _processName;
         pkgList.add(_info.packageName);
         thread = _thread;
         maxAdj = ProcessList.HIDDEN_APP_MAX_ADJ;
-        hiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
+        hiddenAdj = clientHiddenAdj = emptyAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
         curRawAdj = setRawAdj = -100;
         curAdj = setAdj = -100;
         persistent = false;
@@ -388,10 +407,10 @@
             sb.append('u');
             sb.append(userId);
             sb.append('a');
-            sb.append(info.uid%Process.FIRST_APPLICATION_UID);
+            sb.append(UserHandle.getAppId(info.uid));
             if (uid != info.uid) {
                 sb.append('i');
-                sb.append(UserId.getAppId(uid) - Process.FIRST_ISOLATED_UID);
+                sb.append(UserHandle.getAppId(uid) - Process.FIRST_ISOLATED_UID);
             }
         }
     }
diff --git a/services/java/com/android/server/am/ProviderMap.java b/services/java/com/android/server/am/ProviderMap.java
index e4608a2..9dbf5f5 100644
--- a/services/java/com/android/server/am/ProviderMap.java
+++ b/services/java/com/android/server/am/ProviderMap.java
@@ -18,9 +18,8 @@
 
 import android.content.ComponentName;
 import android.os.Binder;
-import android.os.Process;
 import android.os.RemoteException;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.Slog;
 import android.util.SparseArray;
 
@@ -31,8 +30,6 @@
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
 
 /**
  * Keeps track of content providers by authority (name) and class. It separates the mapping by
@@ -44,9 +41,11 @@
 
     private static final boolean DBG = false;
 
-    private final HashMap<String, ContentProviderRecord> mGlobalByName
+    private final ActivityManagerService mAm;
+
+    private final HashMap<String, ContentProviderRecord> mSingletonByName
             = new HashMap<String, ContentProviderRecord>();
-    private final HashMap<ComponentName, ContentProviderRecord> mGlobalByClass
+    private final HashMap<ComponentName, ContentProviderRecord> mSingletonByClass
             = new HashMap<ComponentName, ContentProviderRecord>();
 
     private final SparseArray<HashMap<String, ContentProviderRecord>> mProvidersByNamePerUser
@@ -54,6 +53,10 @@
     private final SparseArray<HashMap<ComponentName, ContentProviderRecord>> mProvidersByClassPerUser
             = new SparseArray<HashMap<ComponentName, ContentProviderRecord>>();
 
+    ProviderMap(ActivityManagerService am) {
+        mAm = am;
+    }
+
     ContentProviderRecord getProviderByName(String name) {
         return getProviderByName(name, -1);
     }
@@ -63,7 +66,7 @@
             Slog.i(TAG, "getProviderByName: " + name + " , callingUid = " + Binder.getCallingUid());
         }
         // Try to find it in the global list
-        ContentProviderRecord record = mGlobalByName.get(name);
+        ContentProviderRecord record = mSingletonByName.get(name);
         if (record != null) {
             return record;
         }
@@ -81,7 +84,7 @@
             Slog.i(TAG, "getProviderByClass: " + name + ", callingUid = " + Binder.getCallingUid());
         }
         // Try to find it in the global list
-        ContentProviderRecord record = mGlobalByClass.get(name);
+        ContentProviderRecord record = mSingletonByClass.get(name);
         if (record != null) {
             return record;
         }
@@ -95,10 +98,10 @@
             Slog.i(TAG, "putProviderByName: " + name + " , callingUid = " + Binder.getCallingUid()
                 + ", record uid = " + record.appInfo.uid);
         }
-        if (record.appInfo.uid < Process.FIRST_APPLICATION_UID) {
-            mGlobalByName.put(name, record);
+        if (record.singleton) {
+            mSingletonByName.put(name, record);
         } else {
-            final int userId = UserId.getUserId(record.appInfo.uid);
+            final int userId = UserHandle.getUserId(record.appInfo.uid);
             getProvidersByName(userId).put(name, record);
         }
     }
@@ -108,56 +111,54 @@
             Slog.i(TAG, "putProviderByClass: " + name + " , callingUid = " + Binder.getCallingUid()
                 + ", record uid = " + record.appInfo.uid);
         }
-        if (record.appInfo.uid < Process.FIRST_APPLICATION_UID) {
-            mGlobalByClass.put(name, record);
+        if (record.singleton) {
+            mSingletonByClass.put(name, record);
         } else {
-            final int userId = UserId.getUserId(record.appInfo.uid);
+            final int userId = UserHandle.getUserId(record.appInfo.uid);
             getProvidersByClass(userId).put(name, record);
         }
     }
 
-    void removeProviderByName(String name, int optionalUserId) {
-        if (mGlobalByName.containsKey(name)) {
+    void removeProviderByName(String name, int userId) {
+        if (mSingletonByName.containsKey(name)) {
             if (DBG)
                 Slog.i(TAG, "Removing from globalByName name=" + name);
-            mGlobalByName.remove(name);
+            mSingletonByName.remove(name);
         } else {
-            // TODO: Verify this works, i.e., the caller happens to be from the correct user
+            if (userId < 0) throw new IllegalArgumentException("Bad user " + userId);
             if (DBG)
                 Slog.i(TAG,
-                        "Removing from providersByName name=" + name + " user="
-                        + (optionalUserId == -1 ? Binder.getOrigCallingUser() : optionalUserId));
-            HashMap<String, ContentProviderRecord> map = getProvidersByName(optionalUserId);
+                        "Removing from providersByName name=" + name + " user=" + userId);
+            HashMap<String, ContentProviderRecord> map = getProvidersByName(userId);
             // map returned by getProvidersByName wouldn't be null
             map.remove(name);
             if (map.size() == 0) {
-                mProvidersByNamePerUser.remove(optionalUserId);
+                mProvidersByNamePerUser.remove(userId);
             }
         }
     }
 
-    void removeProviderByClass(ComponentName name, int optionalUserId) {
-        if (mGlobalByClass.containsKey(name)) {
+    void removeProviderByClass(ComponentName name, int userId) {
+        if (mSingletonByClass.containsKey(name)) {
             if (DBG)
                 Slog.i(TAG, "Removing from globalByClass name=" + name);
-            mGlobalByClass.remove(name);
+            mSingletonByClass.remove(name);
         } else {
+            if (userId < 0) throw new IllegalArgumentException("Bad user " + userId);
             if (DBG)
                 Slog.i(TAG,
-                        "Removing from providersByClass name=" + name + " user="
-                        + (optionalUserId == -1 ? Binder.getOrigCallingUser() : optionalUserId));
-            HashMap<ComponentName, ContentProviderRecord> map = getProvidersByClass(optionalUserId);
+                        "Removing from providersByClass name=" + name + " user=" + userId);
+            HashMap<ComponentName, ContentProviderRecord> map = getProvidersByClass(userId);
             // map returned by getProvidersByClass wouldn't be null
             map.remove(name);
             if (map.size() == 0) {
-                mProvidersByClassPerUser.remove(optionalUserId);
+                mProvidersByClassPerUser.remove(userId);
             }
         }
     }
 
-    private HashMap<String, ContentProviderRecord> getProvidersByName(int optionalUserId) {
-        final int userId = optionalUserId >= 0
-                ? optionalUserId : Binder.getOrigCallingUser();
+    private HashMap<String, ContentProviderRecord> getProvidersByName(int userId) {
+        if (userId < 0) throw new IllegalArgumentException("Bad user " + userId);
         final HashMap<String, ContentProviderRecord> map = mProvidersByNamePerUser.get(userId);
         if (map == null) {
             HashMap<String, ContentProviderRecord> newMap = new HashMap<String, ContentProviderRecord>();
@@ -168,12 +169,13 @@
         }
     }
 
-    HashMap<ComponentName, ContentProviderRecord> getProvidersByClass(int optionalUserId) {
-        final int userId = optionalUserId >= 0
-                ? optionalUserId : Binder.getOrigCallingUser();
-        final HashMap<ComponentName, ContentProviderRecord> map = mProvidersByClassPerUser.get(userId);
+    HashMap<ComponentName, ContentProviderRecord> getProvidersByClass(int userId) {
+        if (userId < 0) throw new IllegalArgumentException("Bad user " + userId);
+        final HashMap<ComponentName, ContentProviderRecord> map
+                = mProvidersByClassPerUser.get(userId);
         if (map == null) {
-            HashMap<ComponentName, ContentProviderRecord> newMap = new HashMap<ComponentName, ContentProviderRecord>();
+            HashMap<ComponentName, ContentProviderRecord> newMap
+                    = new HashMap<ComponentName, ContentProviderRecord>();
             mProvidersByClassPerUser.put(userId, newMap);
             return newMap;
         } else {
@@ -181,6 +183,53 @@
         }
     }
 
+    private boolean collectForceStopProvidersLocked(String name, int appId,
+            boolean doit, boolean evenPersistent, int userId,
+            HashMap<ComponentName, ContentProviderRecord> providers,
+            ArrayList<ContentProviderRecord> result) {
+        boolean didSomething = false;
+        for (ContentProviderRecord provider : providers.values()) {
+            if ((name == null || provider.info.packageName.equals(name))
+                    && (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
+                if (!doit) {
+                    return true;
+                }
+                didSomething = true;
+                result.add(provider);
+            }
+        }
+        return didSomething;
+    }
+
+    boolean collectForceStopProviders(String name, int appId,
+            boolean doit, boolean evenPersistent, int userId,
+            ArrayList<ContentProviderRecord> result) {
+        boolean didSomething = collectForceStopProvidersLocked(name, appId, doit,
+                evenPersistent, userId, mSingletonByClass, result);
+        if (!doit && didSomething) {
+            return true;
+        }
+        if (userId == UserHandle.USER_ALL) {
+            for (int i=0; i<mProvidersByClassPerUser.size(); i++) {
+                if (collectForceStopProvidersLocked(name, appId, doit, evenPersistent,
+                        userId, mProvidersByClassPerUser.valueAt(i), result)) {
+                    if (!doit) {
+                        return true;
+                    }
+                    didSomething = true;
+                }
+            }
+        } else {
+            HashMap<ComponentName, ContentProviderRecord> items
+                    = getProvidersByClass(userId);
+            if (items != null) {
+                didSomething |= collectForceStopProvidersLocked(name, appId, doit,
+                        evenPersistent, userId, items, result);
+            }
+        }
+        return didSomething;
+    }
+
     private void dumpProvidersByClassLocked(PrintWriter pw, boolean dumpAll,
             HashMap<ComponentName, ContentProviderRecord> map) {
         Iterator<Map.Entry<ComponentName, ContentProviderRecord>> it = map.entrySet().iterator();
@@ -207,37 +256,29 @@
     }
 
     void dumpProvidersLocked(PrintWriter pw, boolean dumpAll) {
-        boolean needSep = false;
-        if (mGlobalByClass.size() > 0) {
-            if (needSep)
-                pw.println(" ");
-            pw.println("  Published content providers (by class):");
-            dumpProvidersByClassLocked(pw, dumpAll, mGlobalByClass);
+        if (mSingletonByClass.size() > 0) {
+            pw.println("  Published single-user content providers (by class):");
+            dumpProvidersByClassLocked(pw, dumpAll, mSingletonByClass);
         }
 
-        if (mProvidersByClassPerUser.size() > 1) {
+        pw.println("");
+        for (int i = 0; i < mProvidersByClassPerUser.size(); i++) {
+            HashMap<ComponentName, ContentProviderRecord> map = mProvidersByClassPerUser.valueAt(i);
             pw.println("");
-            for (int i = 0; i < mProvidersByClassPerUser.size(); i++) {
-                HashMap<ComponentName, ContentProviderRecord> map = mProvidersByClassPerUser.valueAt(i);
-                pw.println("  User " + mProvidersByClassPerUser.keyAt(i) + ":");
-                dumpProvidersByClassLocked(pw, dumpAll, map);
-                pw.println(" ");
-            }
-        } else if (mProvidersByClassPerUser.size() == 1) {
-            HashMap<ComponentName, ContentProviderRecord> map = mProvidersByClassPerUser.valueAt(0);
+            pw.println("  Published user " + mProvidersByClassPerUser.keyAt(i)
+                    + " content providers (by class):");
             dumpProvidersByClassLocked(pw, dumpAll, map);
         }
-        needSep = true;
 
         if (dumpAll) {
-            pw.println(" ");
-            pw.println("  Authority to provider mappings:");
-            dumpProvidersByNameLocked(pw, mGlobalByName);
+            pw.println("");
+            pw.println("  Single-user authority to provider mappings:");
+            dumpProvidersByNameLocked(pw, mSingletonByName);
 
             for (int i = 0; i < mProvidersByNamePerUser.size(); i++) {
-                if (i > 0) {
-                    pw.println("  User " + mProvidersByNamePerUser.keyAt(i) + ":");
-                }
+                pw.println("");
+                pw.println("  User " + mProvidersByNamePerUser.keyAt(i)
+                        + " authority to provider mappings:");
                 dumpProvidersByNameLocked(pw, mProvidersByNamePerUser.valueAt(i));
             }
         }
@@ -245,30 +286,33 @@
 
     protected boolean dumpProvider(FileDescriptor fd, PrintWriter pw, String name, String[] args,
             int opti, boolean dumpAll) {
+        ArrayList<ContentProviderRecord> allProviders = new ArrayList<ContentProviderRecord>();
         ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
 
-        if ("all".equals(name)) {
-            synchronized (this) {
-                for (ContentProviderRecord r1 : getProvidersByClass(-1).values()) {
-                    providers.add(r1);
-                }
-            }
-        } else {
-            ComponentName componentName = name != null
-                    ? ComponentName.unflattenFromString(name) : null;
-            int objectId = 0;
-            if (componentName == null) {
-                // Not a '/' separated full component name; maybe an object ID?
-                try {
-                    objectId = Integer.parseInt(name, 16);
-                    name = null;
-                    componentName = null;
-                } catch (RuntimeException e) {
-                }
+        synchronized (mAm) {
+            allProviders.addAll(mSingletonByClass.values());
+            for (int i=0; i<mProvidersByClassPerUser.size(); i++) {
+                allProviders.addAll(mProvidersByClassPerUser.valueAt(i).values());
             }
 
-            synchronized (this) {
-                for (ContentProviderRecord r1 : getProvidersByClass(-1).values()) {
+            if ("all".equals(name)) {
+                providers.addAll(allProviders);
+            } else {
+                ComponentName componentName = name != null
+                        ? ComponentName.unflattenFromString(name) : null;
+                int objectId = 0;
+                if (componentName == null) {
+                    // Not a '/' separated full component name; maybe an object ID?
+                    try {
+                        objectId = Integer.parseInt(name, 16);
+                        name = null;
+                        componentName = null;
+                    } catch (RuntimeException e) {
+                    }
+                }
+
+                for (int i=0; i<allProviders.size(); i++) {
+                    ContentProviderRecord r1 = allProviders.get(i);
                     if (componentName != null) {
                         if (r1.name.equals(componentName)) {
                             providers.add(r1);
@@ -306,7 +350,7 @@
     private void dumpProvider(String prefix, FileDescriptor fd, PrintWriter pw,
             final ContentProviderRecord r, String[] args, boolean dumpAll) {
         String innerPrefix = prefix + "  ";
-        synchronized (this) {
+        synchronized (mAm) {
             pw.print(prefix); pw.print("PROVIDER ");
                     pw.print(r);
                     pw.print(" pid=");
@@ -338,6 +382,4 @@
             }
         }
     }
-
-
 }
diff --git a/services/java/com/android/server/am/ReceiverList.java b/services/java/com/android/server/am/ReceiverList.java
index 32c24c6..9b6701e 100644
--- a/services/java/com/android/server/am/ReceiverList.java
+++ b/services/java/com/android/server/am/ReceiverList.java
@@ -39,18 +39,20 @@
     public final ProcessRecord app;
     public final int pid;
     public final int uid;
+    public final int userId;
     BroadcastRecord curBroadcast = null;
     boolean linkedToDeath = false;
 
     String stringName;
     
     ReceiverList(ActivityManagerService _owner, ProcessRecord _app,
-            int _pid, int _uid, IIntentReceiver _receiver) {
+            int _pid, int _uid, int _userId, IIntentReceiver _receiver) {
         owner = _owner;
         receiver = _receiver;
         app = _app;
         pid = _pid;
         uid = _uid;
+        userId = _userId;
     }
 
     // Want object identity, not the array identity we are inheriting.
@@ -67,8 +69,9 @@
     }
     
     void dumpLocal(PrintWriter pw, String prefix) {
-        pw.print(prefix); pw.print("app="); pw.print(app);
-            pw.print(" pid="); pw.print(pid); pw.print(" uid="); pw.println(uid);
+        pw.print(prefix); pw.print("app="); pw.print(app.toShortString());
+            pw.print(" pid="); pw.print(pid); pw.print(" uid="); pw.print(uid);
+            pw.print(" user="); pw.println(userId);
         if (curBroadcast != null || linkedToDeath) {
             pw.print(prefix); pw.print("curBroadcast="); pw.print(curBroadcast);
                 pw.print(" linkedToDeath="); pw.println(linkedToDeath);
@@ -103,6 +106,8 @@
         sb.append((app != null ? app.processName : "(unknown name)"));
         sb.append('/');
         sb.append(uid);
+        sb.append("/u");
+        sb.append(userId);
         sb.append((receiver.asBinder() instanceof Binder) ? " local:" : " remote:");
         sb.append(Integer.toHexString(System.identityHashCode(receiver.asBinder())));
         sb.append('}');
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 828eef7..84e824a 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -23,6 +23,7 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -31,7 +32,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.Slog;
 import android.util.TimeUtils;
 
@@ -260,6 +261,9 @@
                 IntentBindRecord b = it.next();
                 pw.print(prefix); pw.print("* IntentBindRecord{");
                         pw.print(Integer.toHexString(System.identityHashCode(b)));
+                        if ((b.collectFlags()&Context.BIND_AUTO_CREATE) != 0) {
+                            pw.append(" CREATE");
+                        }
                         pw.println("}:");
                 b.dumpInService(pw, prefix + "  ");
             }
@@ -296,7 +300,7 @@
         this.restarter = restarter;
         createTime = SystemClock.elapsedRealtime();
         lastActivity = SystemClock.uptimeMillis();
-        userId = UserId.getUserId(appInfo.uid);
+        userId = UserHandle.getUserId(appInfo.uid);
     }
 
     public AppBindRecord retrieveAppBindingLocked(Intent intent,
@@ -366,7 +370,7 @@
                     try {
                         int[] outId = new int[1];
                         nm.enqueueNotificationInternal(localPackageName, appUid, appPid,
-                                null, localForegroundId, localForegroundNoti, outId);
+                                null, localForegroundId, localForegroundNoti, outId, userId);
                     } catch (RuntimeException e) {
                         Slog.w(ActivityManagerService.TAG,
                                 "Error showing notification for service", e);
@@ -395,7 +399,8 @@
                         return;
                     }
                     try {
-                        inm.cancelNotification(localPackageName, localForegroundId);
+                        inm.cancelNotificationWithTag(localPackageName, null,
+                                localForegroundId, userId);
                     } catch (RuntimeException e) {
                         Slog.w(ActivityManagerService.TAG,
                                 "Error canceling notification for service", e);
@@ -420,6 +425,7 @@
         StringBuilder sb = new StringBuilder(128);
         sb.append("ServiceRecord{")
             .append(Integer.toHexString(System.identityHashCode(this)))
+            .append(" u").append(userId)
             .append(' ').append(shortName).append('}');
         return stringName = sb.toString();
     }
diff --git a/services/java/com/android/server/am/StrictModeViolationDialog.java b/services/java/com/android/server/am/StrictModeViolationDialog.java
index fe76d18..35d50a1 100644
--- a/services/java/com/android/server/am/StrictModeViolationDialog.java
+++ b/services/java/com/android/server/am/StrictModeViolationDialog.java
@@ -28,6 +28,7 @@
 class StrictModeViolationDialog extends BaseErrorDialog {
     private final static String TAG = "StrictModeViolationDialog";
 
+    private final ActivityManagerService mService;
     private final AppErrorResult mResult;
     private final ProcessRecord mProc;
 
@@ -39,11 +40,13 @@
     // dialog
     static final long DISMISS_TIMEOUT = 1000 * 60 * 1;
 
-    public StrictModeViolationDialog(Context context, AppErrorResult result, ProcessRecord app) {
+    public StrictModeViolationDialog(Context context, ActivityManagerService service,
+            AppErrorResult result, ProcessRecord app) {
         super(context);
 
         Resources res = context.getResources();
 
+        mService = service;
         mProc = app;
         mResult = result;
         CharSequence name;
@@ -83,7 +86,7 @@
 
     private final Handler mHandler = new Handler() {
         public void handleMessage(Message msg) {
-            synchronized (mProc) {
+            synchronized (mService) {
                 if (mProc != null && mProc.crashDialog == StrictModeViolationDialog.this) {
                     mProc.crashDialog = null;
                 }
diff --git a/services/java/com/android/server/am/TaskAccessInfo.java b/services/java/com/android/server/am/TaskAccessInfo.java
index 5618c1aa..50aeec1 100644
--- a/services/java/com/android/server/am/TaskAccessInfo.java
+++ b/services/java/com/android/server/am/TaskAccessInfo.java
@@ -19,11 +19,10 @@
 import java.util.ArrayList;
 
 import android.app.ActivityManager.TaskThumbnails;
-import android.graphics.Bitmap;
 
 final class TaskAccessInfo extends TaskThumbnails {
     final static class SubTask {
-        Bitmap thumbnail;
+        ThumbnailHolder holder;
         ActivityRecord activity;
         int index;
     }
diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java
index 3a767c2..1bae9ca 100644
--- a/services/java/com/android/server/am/TaskRecord.java
+++ b/services/java/com/android/server/am/TaskRecord.java
@@ -19,7 +19,7 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.Slog;
 
 import java.io.PrintWriter;
@@ -101,7 +101,7 @@
         }
 
         if (info.applicationInfo != null) {
-            userId = UserId.getUserId(info.applicationInfo.uid);
+            userId = UserHandle.getUserId(info.applicationInfo.uid);
         }
     }
     
diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java
index ba65f39..6dae4aa 100644
--- a/services/java/com/android/server/am/UsageStatsService.java
+++ b/services/java/com/android/server/am/UsageStatsService.java
@@ -27,12 +27,12 @@
 import android.os.Process;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.util.AtomicFile;
 import android.util.Slog;
 import android.util.Xml;
 
 import com.android.internal.app.IUsageStats;
 import com.android.internal.content.PackageMonitor;
-import com.android.internal.os.AtomicFile;
 import com.android.internal.os.PkgUsageStats;
 import com.android.internal.util.FastXmlSerializer;
 
@@ -650,7 +650,7 @@
     public void monitorPackages() {
         mPackageMonitor = new PackageMonitor() {
             @Override
-            public void onPackageRemoved(String packageName, int uid) {
+            public void onPackageRemovedAllUsers(String packageName, int uid) {
                 synchronized (mStatsLock) {
                     mLastResumeTimes.remove(packageName);
                 }
diff --git a/services/java/com/android/server/am/UserStartedState.java b/services/java/com/android/server/am/UserStartedState.java
new file mode 100644
index 0000000..0e71f81
--- /dev/null
+++ b/services/java/com/android/server/am/UserStartedState.java
@@ -0,0 +1,60 @@
+/*
+ * 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.am;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+import android.app.IStopUserCallback;
+import android.os.UserHandle;
+
+public class UserStartedState {
+    // User is first coming up.
+    public final static int STATE_BOOTING = 0;
+    // User is in the normal running state.
+    public final static int STATE_RUNNING = 1;
+    // User is in the initial process of being stopped.
+    public final static int STATE_STOPPING = 2;
+    // User is in the final phase of stopping, sending Intent.ACTION_SHUTDOWN.
+    public final static int STATE_SHUTDOWN = 3;
+
+    public final UserHandle mHandle;
+    public final ArrayList<IStopUserCallback> mStopCallbacks
+            = new ArrayList<IStopUserCallback>();
+
+    public int mState = STATE_BOOTING;
+    public boolean switching;
+    public boolean initializing;
+
+    public UserStartedState(UserHandle handle, boolean initial) {
+        mHandle = handle;
+    }
+
+    void dump(String prefix, PrintWriter pw) {
+        pw.print(prefix); pw.print("mState=");
+        switch (mState) {
+            case STATE_BOOTING: pw.print("BOOTING"); break;
+            case STATE_RUNNING: pw.print("RUNNING"); break;
+            case STATE_STOPPING: pw.print("STOPPING"); break;
+            case STATE_SHUTDOWN: pw.print("SHUTDOWN"); break;
+            default: pw.print(mState); break; 
+        }
+        if (switching) pw.print(" SWITCHING");
+        if (initializing) pw.print(" INITIALIZING");
+        pw.println();
+    }
+}
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 682ecf8..e4a7ead 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -43,6 +43,7 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
 
@@ -319,6 +320,8 @@
 
     public void limitReached(String limitName, String iface) {}
 
+    public void interfaceClassDataActivityChanged(String label, boolean active) {}
+
     public int tether(String iface) {
         if (DBG) Log.d(TAG, "Tethering " + iface);
         TetherInterfaceSM sm = null;
@@ -415,7 +418,7 @@
         broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
         broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
                 erroredList);
-        mContext.sendStickyBroadcast(broadcast);
+        mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
         if (DBG) {
             Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " +
                     activeList.size() + ", " + erroredList.size());
@@ -451,14 +454,16 @@
             if (mTetheredNotification.icon == icon) {
                 return;
             }
-            notificationManager.cancel(mTetheredNotification.icon);
+            notificationManager.cancelAsUser(null, mTetheredNotification.icon,
+                    UserHandle.ALL);
         }
 
         Intent intent = new Intent();
         intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
         intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
 
-        PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
+        PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0,
+                null, UserHandle.CURRENT);
 
         Resources r = Resources.getSystem();
         CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
@@ -475,14 +480,16 @@
         mTetheredNotification.tickerText = title;
         mTetheredNotification.setLatestEventInfo(mContext, title, message, pi);
 
-        notificationManager.notify(mTetheredNotification.icon, mTetheredNotification);
+        notificationManager.notifyAsUser(null, mTetheredNotification.icon,
+                mTetheredNotification, UserHandle.ALL);
     }
 
     private void clearTetheredNotification() {
         NotificationManager notificationManager =
             (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
         if (notificationManager != null && mTetheredNotification != null) {
-            notificationManager.cancel(mTetheredNotification.icon);
+            notificationManager.cancelAsUser(null, mTetheredNotification.icon,
+                    UserHandle.ALL);
             mTetheredNotification = null;
         }
     }
@@ -501,8 +508,13 @@
                     mUsbTetherRequested = false;
                 }
             } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
-                if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
-                mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
+                NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra(
+                        ConnectivityManager.EXTRA_NETWORK_INFO);
+                if (networkInfo != null &&
+                        networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) {
+                    if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
+                    mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
+                }
             }
         }
     }
@@ -616,8 +628,8 @@
     }
 
     public void checkDunRequired() {
-        int secureSetting = Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.TETHER_DUN_REQUIRED, 2);
+        int secureSetting = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.TETHER_DUN_REQUIRED, 2);
         synchronized (mPublicSync) {
             // 2 = not set, 0 = DUN not required, 1 = DUN required
             if (secureSetting != 2) {
@@ -1135,7 +1147,7 @@
         private State mStopTetheringErrorState;
         private State mSetDnsForwardersErrorState;
 
-        private ArrayList mNotifyList;
+        private ArrayList<TetherInterfaceSM> mNotifyList;
 
         private int mCurrentConnectionSequence;
         private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
@@ -1165,7 +1177,7 @@
             mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
             addState(mSetDnsForwardersErrorState);
 
-            mNotifyList = new ArrayList();
+            mNotifyList = new ArrayList<TetherInterfaceSM>();
             setInitialState(mInitialState);
         }
 
@@ -1362,8 +1374,7 @@
             protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
                 if (DBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
                 mUpstreamIfaceName = ifaceName;
-                for (Object o : mNotifyList) {
-                    TetherInterfaceSM sm = (TetherInterfaceSM)o;
+                for (TetherInterfaceSM sm : mNotifyList) {
                     sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
                             ifaceName);
                 }
@@ -1381,13 +1392,13 @@
                 switch (message.what) {
                     case CMD_TETHER_MODE_REQUESTED:
                         TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
-                        if (VDBG) Log.d(TAG, "Tether Mode requested by " + who.toString());
+                        if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
                         mNotifyList.add(who);
                         transitionTo(mTetherModeAliveState);
                         break;
                     case CMD_TETHER_MODE_UNREQUESTED:
                         who = (TetherInterfaceSM)message.obj;
-                        if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who.toString());
+                        if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
                         int index = mNotifyList.indexOf(who);
                         if (index != -1) {
                             mNotifyList.remove(who);
@@ -1424,18 +1435,29 @@
                 switch (message.what) {
                     case CMD_TETHER_MODE_REQUESTED:
                         TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
+                        if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
                         mNotifyList.add(who);
                         who.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
                                 mUpstreamIfaceName);
                         break;
                     case CMD_TETHER_MODE_UNREQUESTED:
                         who = (TetherInterfaceSM)message.obj;
+                        if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
                         int index = mNotifyList.indexOf(who);
                         if (index != -1) {
+                            if (DBG) Log.d(TAG, "TetherModeAlive removing notifyee " + who);
                             mNotifyList.remove(index);
                             if (mNotifyList.isEmpty()) {
                                 turnOffMasterTetherSettings(); // transitions appropriately
+                            } else {
+                                if (DBG) {
+                                    Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
+                                            " live requests:");
+                                    for (Object o : mNotifyList) Log.d(TAG, "  " + o);
+                                }
                             }
+                        } else {
+                           Log.e(TAG, "TetherModeAliveState UNREQUESTED has unknown who: " + who);
                         }
                         break;
                     case CMD_UPSTREAM_CHANGED:
@@ -1562,7 +1584,7 @@
             pw.println();
             pw.println("Tether state:");
             for (Object o : mIfaces.values()) {
-                pw.println(" "+o.toString());
+                pw.println(" " + o);
             }
         }
         pw.println();
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index 4b82037..bb19cc7 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -16,8 +16,11 @@
 
 package com.android.server.connectivity;
 
+import static android.Manifest.permission.BIND_VPN_SERVICE;
+
 import android.app.Notification;
 import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -25,55 +28,117 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
+import android.net.BaseNetworkStateTracker;
+import android.net.ConnectivityManager;
 import android.net.INetworkManagementEventObserver;
+import android.net.LinkProperties;
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
+import android.net.NetworkInfo;
+import android.net.RouteInfo;
+import android.net.NetworkInfo.DetailedState;
 import android.os.Binder;
 import android.os.FileUtils;
 import android.os.IBinder;
+import android.os.INetworkManagementService;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
+import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.SystemProperties;
+import android.os.SystemService;
+import android.os.UserHandle;
+import android.security.Credentials;
+import android.security.KeyStore;
 import android.util.Log;
+import android.widget.Toast;
 
 import com.android.internal.R;
 import com.android.internal.net.LegacyVpnInfo;
 import com.android.internal.net.VpnConfig;
+import com.android.internal.net.VpnProfile;
+import com.android.internal.util.Preconditions;
 import com.android.server.ConnectivityService.VpnCallback;
+import com.android.server.net.BaseNetworkObserver;
 
 import java.io.File;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.net.Inet4Address;
+import java.net.InetAddress;
 import java.nio.charset.Charsets;
 import java.util.Arrays;
 
+import libcore.io.IoUtils;
+
 /**
  * @hide
  */
-public class Vpn extends INetworkManagementEventObserver.Stub {
+public class Vpn extends BaseNetworkStateTracker {
+    private static final String TAG = "Vpn";
+    private static final boolean LOGD = true;
+    
+    // TODO: create separate trackers for each unique VPN to support
+    // automated reconnection
 
-    private final static String TAG = "Vpn";
-
-    private final static String BIND_VPN_SERVICE =
-            android.Manifest.permission.BIND_VPN_SERVICE;
-
-    private final Context mContext;
     private final VpnCallback mCallback;
 
     private String mPackage = VpnConfig.LEGACY_VPN;
     private String mInterface;
     private Connection mConnection;
     private LegacyVpnRunner mLegacyVpnRunner;
+    private PendingIntent mStatusIntent;
+    private boolean mEnableNotif = true;
 
-    public Vpn(Context context, VpnCallback callback) {
+    public Vpn(Context context, VpnCallback callback, INetworkManagementService netService) {
+        // TODO: create dedicated TYPE_VPN network type
+        super(ConnectivityManager.TYPE_DUMMY);
         mContext = context;
         mCallback = callback;
+
+        try {
+            netService.registerObserver(mObserver);
+        } catch (RemoteException e) {
+            Log.wtf(TAG, "Problem registering observer", e);
+        }
+    }
+
+    public void setEnableNotifications(boolean enableNotif) {
+        mEnableNotif = enableNotif;
+    }
+
+    @Override
+    protected void startMonitoringInternal() {
+        // Ignored; events are sent through callbacks for now
+    }
+
+    @Override
+    public boolean teardown() {
+        // TODO: finish migration to unique tracker for each VPN
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean reconnect() {
+        // TODO: finish migration to unique tracker for each VPN
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getTcpBufferSizesPropName() {
+        return PROP_TCP_BUFFER_UNKNOWN;
+    }
+
+    /**
+     * Update current state, dispaching event to listeners.
+     */
+    private void updateState(DetailedState detailedState, String reason) {
+        if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason);
+        mNetworkInfo.setDetailedState(detailedState, reason, null);
+        mCallback.onStateChanged(new NetworkInfo(mNetworkInfo));
     }
 
     /**
@@ -112,10 +177,13 @@
         // Reset the interface and hide the notification.
         if (mInterface != null) {
             jniReset(mInterface);
-            long identity = Binder.clearCallingIdentity();
-            mCallback.restore();
-            hideNotification();
-            Binder.restoreCallingIdentity(identity);
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mCallback.restore();
+                hideNotification();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
             mInterface = null;
         }
 
@@ -136,6 +204,7 @@
 
         Log.i(TAG, "Switched from " + mPackage + " to " + newPackage);
         mPackage = newPackage;
+        updateState(DetailedState.IDLE, "prepare");
         return true;
     }
 
@@ -144,7 +213,7 @@
      * interface. The socket is NOT closed by this method.
      *
      * @param socket The socket to be bound.
-     * @param name The name of the interface.
+     * @param interfaze The name of the interface.
      */
     public void protect(ParcelFileDescriptor socket, String interfaze) throws Exception {
         PackageManager pm = mContext.getPackageManager();
@@ -208,6 +277,7 @@
         // Configure the interface. Abort if any of these steps fails.
         ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
         try {
+            updateState(DetailedState.CONNECTING, "establish");
             String interfaze = jniGetName(tun.getFd());
             if (jniSetAddresses(interfaze, config.addresses) < 1) {
                 throw new IllegalArgumentException("At least one address must be specified");
@@ -228,11 +298,8 @@
             mConnection = connection;
             mInterface = interfaze;
         } catch (RuntimeException e) {
-            try {
-                tun.close();
-            } catch (Exception ex) {
-                // ignore
-            }
+            updateState(DetailedState.FAILED, "establish");
+            IoUtils.closeQuietly(tun);
             throw e;
         }
         Log.i(TAG, "Established by " + config.user + " on " + mInterface);
@@ -242,54 +309,61 @@
         config.interfaze = mInterface;
 
         // Override DNS servers and show the notification.
-        long identity = Binder.clearCallingIdentity();
-        mCallback.override(config.dnsServers, config.searchDomains);
-        showNotification(config, label, bitmap);
-        Binder.restoreCallingIdentity(identity);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            mCallback.override(config.dnsServers, config.searchDomains);
+            showNotification(config, label, bitmap);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+        // TODO: ensure that contract class eventually marks as connected
+        updateState(DetailedState.AUTHENTICATING, "establish");
         return tun;
     }
 
-    // INetworkManagementEventObserver.Stub
-    @Override
-    public void interfaceAdded(String interfaze) {
-    }
-
-    // INetworkManagementEventObserver.Stub
-    @Override
-    public synchronized void interfaceStatusChanged(String interfaze, boolean up) {
-        if (!up && mLegacyVpnRunner != null) {
-            mLegacyVpnRunner.check(interfaze);
+    @Deprecated
+    public synchronized void interfaceStatusChanged(String iface, boolean up) {
+        try {
+            mObserver.interfaceStatusChanged(iface, up);
+        } catch (RemoteException e) {
+            // ignored; target is local
         }
     }
 
-    // INetworkManagementEventObserver.Stub
-    @Override
-    public void interfaceLinkStateChanged(String interfaze, boolean up) {
-    }
-
-    // INetworkManagementEventObserver.Stub
-    @Override
-    public synchronized void interfaceRemoved(String interfaze) {
-        if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) {
-            long identity = Binder.clearCallingIdentity();
-            mCallback.restore();
-            hideNotification();
-            Binder.restoreCallingIdentity(identity);
-            mInterface = null;
-            if (mConnection != null) {
-                mContext.unbindService(mConnection);
-                mConnection = null;
-            } else if (mLegacyVpnRunner != null) {
-                mLegacyVpnRunner.exit();
-                mLegacyVpnRunner = null;
+    private INetworkManagementEventObserver mObserver = new BaseNetworkObserver() {
+        @Override
+        public void interfaceStatusChanged(String interfaze, boolean up) {
+            synchronized (Vpn.this) {
+                if (!up && mLegacyVpnRunner != null) {
+                    mLegacyVpnRunner.check(interfaze);
+                }
             }
         }
-    }
 
-    // INetworkManagementEventObserver.Stub
-    @Override
-    public void limitReached(String limit, String interfaze) {
-    }
+        @Override
+        public void interfaceRemoved(String interfaze) {
+            synchronized (Vpn.this) {
+                if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) {
+                    final long token = Binder.clearCallingIdentity();
+                    try {
+                        mCallback.restore();
+                        hideNotification();
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                    mInterface = null;
+                    if (mConnection != null) {
+                        mContext.unbindService(mConnection);
+                        mConnection = null;
+                        updateState(DetailedState.DISCONNECTED, "interfaceRemoved");
+                    } else if (mLegacyVpnRunner != null) {
+                        mLegacyVpnRunner.exit();
+                        mLegacyVpnRunner = null;
+                    }
+                }
+            }
+        }
+    };
 
     private void enforceControlPermission() {
         // System user is allowed to control VPN.
@@ -326,6 +400,9 @@
     }
 
     private void showNotification(VpnConfig config, String label, Bitmap icon) {
+        if (!mEnableNotif) return;
+        mStatusIntent = VpnConfig.getIntentForStatusPanel(mContext, config);
+
         NotificationManager nm = (NotificationManager)
                 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
 
@@ -341,20 +418,23 @@
                     .setLargeIcon(icon)
                     .setContentTitle(title)
                     .setContentText(text)
-                    .setContentIntent(VpnConfig.getIntentForStatusPanel(mContext, config))
+                    .setContentIntent(mStatusIntent)
                     .setDefaults(0)
                     .setOngoing(true)
-                    .getNotification();
-            nm.notify(R.drawable.vpn_connected, notification);
+                    .build();
+            nm.notifyAsUser(null, R.drawable.vpn_connected, notification, UserHandle.ALL);
         }
     }
 
     private void hideNotification() {
+        if (!mEnableNotif) return;
+        mStatusIntent = null;
+
         NotificationManager nm = (NotificationManager)
                 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
 
         if (nm != null) {
-            nm.cancel(R.drawable.vpn_connected);
+            nm.cancelAsUser(null, R.drawable.vpn_connected, UserHandle.ALL);
         }
     }
 
@@ -366,31 +446,172 @@
     private native int jniCheck(String interfaze);
     private native void jniProtect(int socket, String interfaze);
 
+    private static String findLegacyVpnGateway(LinkProperties prop) {
+        for (RouteInfo route : prop.getRoutes()) {
+            // Currently legacy VPN only works on IPv4.
+            if (route.isDefaultRoute() && route.getGateway() instanceof Inet4Address) {
+                return route.getGateway().getHostAddress();
+            }
+        }
+
+        throw new IllegalStateException("Unable to find suitable gateway");
+    }
+
     /**
-     * Start legacy VPN. This method stops the daemons and restart them
-     * if arguments are not null. Heavy things are offloaded to another
-     * thread, so callers will not be blocked for a long time.
-     *
-     * @param config The parameters to configure the network.
-     * @param raoocn The arguments to be passed to racoon.
-     * @param mtpd The arguments to be passed to mtpd.
+     * Start legacy VPN, controlling native daemons as needed. Creates a
+     * secondary thread to perform connection work, returning quickly.
      */
-    public synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) {
+    public void startLegacyVpn(VpnProfile profile, KeyStore keyStore, LinkProperties egress) {
+        if (keyStore.state() != KeyStore.State.UNLOCKED) {
+            throw new IllegalStateException("KeyStore isn't unlocked");
+        }
+
+        final String iface = egress.getInterfaceName();
+        final String gateway = findLegacyVpnGateway(egress);
+
+        // Load certificates.
+        String privateKey = "";
+        String userCert = "";
+        String caCert = "";
+        String serverCert = "";
+        if (!profile.ipsecUserCert.isEmpty()) {
+            privateKey = Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert;
+            byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecUserCert);
+            userCert = (value == null) ? null : new String(value, Charsets.UTF_8);
+        }
+        if (!profile.ipsecCaCert.isEmpty()) {
+            byte[] value = keyStore.get(Credentials.CA_CERTIFICATE + profile.ipsecCaCert);
+            caCert = (value == null) ? null : new String(value, Charsets.UTF_8);
+        }
+        if (!profile.ipsecServerCert.isEmpty()) {
+            byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecServerCert);
+            serverCert = (value == null) ? null : new String(value, Charsets.UTF_8);
+        }
+        if (privateKey == null || userCert == null || caCert == null || serverCert == null) {
+            throw new IllegalStateException("Cannot load credentials");
+        }
+
+        // Prepare arguments for racoon.
+        String[] racoon = null;
+        switch (profile.type) {
+            case VpnProfile.TYPE_L2TP_IPSEC_PSK:
+                racoon = new String[] {
+                    iface, profile.server, "udppsk", profile.ipsecIdentifier,
+                    profile.ipsecSecret, "1701",
+                };
+                break;
+            case VpnProfile.TYPE_L2TP_IPSEC_RSA:
+                racoon = new String[] {
+                    iface, profile.server, "udprsa", privateKey, userCert,
+                    caCert, serverCert, "1701",
+                };
+                break;
+            case VpnProfile.TYPE_IPSEC_XAUTH_PSK:
+                racoon = new String[] {
+                    iface, profile.server, "xauthpsk", profile.ipsecIdentifier,
+                    profile.ipsecSecret, profile.username, profile.password, "", gateway,
+                };
+                break;
+            case VpnProfile.TYPE_IPSEC_XAUTH_RSA:
+                racoon = new String[] {
+                    iface, profile.server, "xauthrsa", privateKey, userCert,
+                    caCert, serverCert, profile.username, profile.password, "", gateway,
+                };
+                break;
+            case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
+                racoon = new String[] {
+                    iface, profile.server, "hybridrsa",
+                    caCert, serverCert, profile.username, profile.password, "", gateway,
+                };
+                break;
+        }
+
+        // Prepare arguments for mtpd.
+        String[] mtpd = null;
+        switch (profile.type) {
+            case VpnProfile.TYPE_PPTP:
+                mtpd = new String[] {
+                    iface, "pptp", profile.server, "1723",
+                    "name", profile.username, "password", profile.password,
+                    "linkname", "vpn", "refuse-eap", "nodefaultroute",
+                    "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
+                    (profile.mppe ? "+mppe" : "nomppe"),
+                };
+                break;
+            case VpnProfile.TYPE_L2TP_IPSEC_PSK:
+            case VpnProfile.TYPE_L2TP_IPSEC_RSA:
+                mtpd = new String[] {
+                    iface, "l2tp", profile.server, "1701", profile.l2tpSecret,
+                    "name", profile.username, "password", profile.password,
+                    "linkname", "vpn", "refuse-eap", "nodefaultroute",
+                    "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
+                };
+                break;
+        }
+
+        VpnConfig config = new VpnConfig();
+        config.legacy = true;
+        config.user = profile.key;
+        config.interfaze = iface;
+        config.session = profile.name;
+        config.routes = profile.routes;
+        if (!profile.dnsServers.isEmpty()) {
+            config.dnsServers = Arrays.asList(profile.dnsServers.split(" +"));
+        }
+        if (!profile.searchDomains.isEmpty()) {
+            config.searchDomains = Arrays.asList(profile.searchDomains.split(" +"));
+        }
+
+        startLegacyVpn(config, racoon, mtpd);
+    }
+
+    private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) {
+        stopLegacyVpn();
+
         // Prepare for the new request. This also checks the caller.
         prepare(null, VpnConfig.LEGACY_VPN);
+        updateState(DetailedState.CONNECTING, "startLegacyVpn");
 
         // Start a new LegacyVpnRunner and we are done!
         mLegacyVpnRunner = new LegacyVpnRunner(config, racoon, mtpd);
         mLegacyVpnRunner.start();
     }
 
+    public synchronized void stopLegacyVpn() {
+        if (mLegacyVpnRunner != null) {
+            mLegacyVpnRunner.exit();
+            mLegacyVpnRunner = null;
+
+            synchronized (LegacyVpnRunner.TAG) {
+                // wait for old thread to completely finish before spinning up
+                // new instance, otherwise state updates can be out of order.
+            }
+        }
+    }
+
     /**
      * Return the information of the current ongoing legacy VPN.
      */
     public synchronized LegacyVpnInfo getLegacyVpnInfo() {
         // Check if the caller is authorized.
         enforceControlPermission();
-        return (mLegacyVpnRunner == null) ? null : mLegacyVpnRunner.getInfo();
+        if (mLegacyVpnRunner == null) return null;
+
+        final LegacyVpnInfo info = new LegacyVpnInfo();
+        info.key = mLegacyVpnRunner.mConfig.user;
+        info.state = LegacyVpnInfo.stateFromNetworkInfo(mNetworkInfo);
+        if (mNetworkInfo.isConnected()) {
+            info.intent = mStatusIntent;
+        }
+        return info;
+    }
+
+    public VpnConfig getLegacyVpnConfig() {
+        if (mLegacyVpnRunner != null) {
+            return mLegacyVpnRunner.mConfig;
+        } else {
+            return null;
+        }
     }
 
     /**
@@ -408,7 +629,6 @@
         private final String[][] mArguments;
         private final LocalSocket[] mSockets;
         private final String mOuterInterface;
-        private final LegacyVpnInfo mInfo;
 
         private long mTimer = -1;
 
@@ -416,16 +636,14 @@
             super(TAG);
             mConfig = config;
             mDaemons = new String[] {"racoon", "mtpd"};
+            // TODO: clear arguments from memory once launched
             mArguments = new String[][] {racoon, mtpd};
             mSockets = new LocalSocket[mDaemons.length];
-            mInfo = new LegacyVpnInfo();
 
-            // This is the interface which VPN is running on.
+            // This is the interface which VPN is running on,
+            // mConfig.interfaze will change to point to OUR
+            // internal interface soon. TODO - add inner/outer to mconfig
             mOuterInterface = mConfig.interfaze;
-
-            // Legacy VPN is not a real package, so we use it to carry the key.
-            mInfo.key = mConfig.user;
-            mConfig.user = VpnConfig.LEGACY_VPN;
         }
 
         public void check(String interfaze) {
@@ -439,21 +657,9 @@
             // We assume that everything is reset after stopping the daemons.
             interrupt();
             for (LocalSocket socket : mSockets) {
-                try {
-                    socket.close();
-                } catch (Exception e) {
-                    // ignore
-                }
+                IoUtils.closeQuietly(socket);
             }
-        }
-
-        public LegacyVpnInfo getInfo() {
-            // Update the info when VPN is disconnected.
-            if (mInfo.state == LegacyVpnInfo.STATE_CONNECTED && mInterface == null) {
-                mInfo.state = LegacyVpnInfo.STATE_DISCONNECTED;
-                mInfo.intent = null;
-            }
-            return mInfo;
+            updateState(DetailedState.DISCONNECTED, "exit");
         }
 
         @Override
@@ -463,6 +669,7 @@
             synchronized (TAG) {
                 Log.v(TAG, "Executing");
                 execute();
+                monitorDaemons();
             }
         }
 
@@ -474,22 +681,21 @@
             } else if (now - mTimer <= 60000) {
                 Thread.sleep(yield ? 200 : 1);
             } else {
-                mInfo.state = LegacyVpnInfo.STATE_TIMEOUT;
+                updateState(DetailedState.FAILED, "checkpoint");
                 throw new IllegalStateException("Time is up");
             }
         }
 
         private void execute() {
             // Catch all exceptions so we can clean up few things.
+            boolean initFinished = false;
             try {
                 // Initialize the timer.
                 checkpoint(false);
-                mInfo.state = LegacyVpnInfo.STATE_INITIALIZING;
 
                 // Wait for the daemons to stop.
                 for (String daemon : mDaemons) {
-                    String key = "init.svc." + daemon;
-                    while (!"stopped".equals(SystemProperties.get(key, "stopped"))) {
+                    while (!SystemService.isStopped(daemon)) {
                         checkpoint(true);
                     }
                 }
@@ -501,6 +707,7 @@
                     throw new IllegalStateException("Cannot delete the state");
                 }
                 new File("/data/misc/vpn/abort").delete();
+                initFinished = true;
 
                 // Check if we need to restart any of the daemons.
                 boolean restart = false;
@@ -508,10 +715,10 @@
                     restart = restart || (arguments != null);
                 }
                 if (!restart) {
-                    mInfo.state = LegacyVpnInfo.STATE_DISCONNECTED;
+                    updateState(DetailedState.DISCONNECTED, "execute");
                     return;
                 }
-                mInfo.state = LegacyVpnInfo.STATE_CONNECTING;
+                updateState(DetailedState.CONNECTING, "execute");
 
                 // Start the daemon with arguments.
                 for (int i = 0; i < mDaemons.length; ++i) {
@@ -522,11 +729,10 @@
 
                     // Start the daemon.
                     String daemon = mDaemons[i];
-                    SystemProperties.set("ctl.start", daemon);
+                    SystemService.start(daemon);
 
                     // Wait for the daemon to start.
-                    String key = "init.svc." + daemon;
-                    while (!"running".equals(SystemProperties.get(key))) {
+                    while (!SystemService.isRunning(daemon)) {
                         checkpoint(true);
                     }
 
@@ -582,8 +788,7 @@
                     // Check if a running daemon is dead.
                     for (int i = 0; i < mDaemons.length; ++i) {
                         String daemon = mDaemons[i];
-                        if (mArguments[i] != null && !"running".equals(
-                                SystemProperties.get("init.svc." + daemon))) {
+                        if (mArguments[i] != null && !SystemService.isRunning(daemon)) {
                             throw new IllegalStateException(daemon + " is dead");
                         }
                     }
@@ -640,26 +845,53 @@
                     showNotification(mConfig, null, null);
 
                     Log.i(TAG, "Connected!");
-                    mInfo.state = LegacyVpnInfo.STATE_CONNECTED;
-                    mInfo.intent = VpnConfig.getIntentForStatusPanel(mContext, null);
+                    updateState(DetailedState.CONNECTED, "execute");
                 }
             } catch (Exception e) {
                 Log.i(TAG, "Aborting", e);
                 exit();
             } finally {
                 // Kill the daemons if they fail to stop.
-                if (mInfo.state == LegacyVpnInfo.STATE_INITIALIZING) {
+                if (!initFinished) {
                     for (String daemon : mDaemons) {
-                        SystemProperties.set("ctl.stop", daemon);
+                        SystemService.stop(daemon);
                     }
                 }
 
                 // Do not leave an unstable state.
-                if (mInfo.state == LegacyVpnInfo.STATE_INITIALIZING ||
-                        mInfo.state == LegacyVpnInfo.STATE_CONNECTING) {
-                    mInfo.state = LegacyVpnInfo.STATE_FAILED;
+                if (!initFinished || mNetworkInfo.getDetailedState() == DetailedState.CONNECTING) {
+                    updateState(DetailedState.FAILED, "execute");
                 }
             }
         }
+
+        /**
+         * Monitor the daemons we started, moving to disconnected state if the
+         * underlying services fail.
+         */
+        private void monitorDaemons() {
+            if (!mNetworkInfo.isConnected()) {
+                return;
+            }
+
+            try {
+                while (true) {
+                    Thread.sleep(2000);
+                    for (int i = 0; i < mDaemons.length; i++) {
+                        if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) {
+                            return;
+                        }
+                    }
+                }
+            } catch (InterruptedException e) {
+                Log.d(TAG, "interrupted during monitorDaemons(); stopping services");
+            } finally {
+                for (String daemon : mDaemons) {
+                    SystemService.stop(daemon);
+                }
+
+                updateState(DetailedState.DISCONNECTED, "babysit");
+            }
+        }
     }
 }
diff --git a/services/java/com/android/server/display/DisplayAdapter.java b/services/java/com/android/server/display/DisplayAdapter.java
new file mode 100644
index 0000000..b411a0d
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayAdapter.java
@@ -0,0 +1,129 @@
+/*
+ * 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.display;
+
+import android.content.Context;
+import android.os.Handler;
+
+import java.io.PrintWriter;
+
+/**
+ * A display adapter makes zero or more display devices available to the system
+ * and provides facilities for discovering when displays are connected or disconnected.
+ * <p>
+ * For now, all display adapters are registered in the system server but
+ * in principle it could be done from other processes.
+ * </p><p>
+ * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
+ * </p>
+ */
+abstract class DisplayAdapter {
+    private final DisplayManagerService.SyncRoot mSyncRoot;
+    private final Context mContext;
+    private final Handler mHandler;
+    private final Listener mListener;
+    private final String mName;
+
+    public static final int DISPLAY_DEVICE_EVENT_ADDED = 1;
+    public static final int DISPLAY_DEVICE_EVENT_CHANGED = 2;
+    public static final int DISPLAY_DEVICE_EVENT_REMOVED = 3;
+
+    // Called with SyncRoot lock held.
+    public DisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
+            Context context, Handler handler, Listener listener, String name) {
+        mSyncRoot = syncRoot;
+        mContext = context;
+        mHandler = handler;
+        mListener = listener;
+        mName = name;
+    }
+
+    /**
+     * Gets the object that the display adapter should synchronize on when handling
+     * calls that come in from outside of the display manager service.
+     */
+    public final DisplayManagerService.SyncRoot getSyncRoot() {
+        return mSyncRoot;
+    }
+
+    /**
+     * Gets the display adapter's context.
+     */
+    public final Context getContext() {
+        return mContext;
+    }
+
+    /**
+     * Gets a handler that the display adapter may use to post asynchronous messages.
+     */
+    public final Handler getHandler() {
+        return mHandler;
+    }
+
+    /**
+     * Gets the display adapter name for debugging purposes.
+     */
+    public final String getName() {
+        return mName;
+    }
+
+    /**
+     * Registers the display adapter with the display manager.
+     *
+     * The display adapter should register any built-in display devices as soon as possible.
+     * The boot process will wait for the default display to be registered.
+     * Other display devices can be registered dynamically later.
+     */
+    public void registerLocked() {
+    }
+
+    /**
+     * Dumps the local state of the display adapter.
+     */
+    public void dumpLocked(PrintWriter pw) {
+    }
+
+    /**
+     * Sends a display device event to the display adapter listener asynchronously.
+     */
+    protected final void sendDisplayDeviceEventLocked(
+            final DisplayDevice device, final int event) {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mListener.onDisplayDeviceEvent(device, event);
+            }
+        });
+    }
+
+    /**
+     * Sends a request to perform traversals.
+     */
+    protected final void sendTraversalRequestLocked() {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mListener.onTraversalRequested();
+            }
+        });
+    }
+
+    public interface Listener {
+        public void onDisplayDeviceEvent(DisplayDevice device, int event);
+        public void onTraversalRequested();
+    }
+}
diff --git a/services/java/com/android/server/display/DisplayDevice.java b/services/java/com/android/server/display/DisplayDevice.java
new file mode 100644
index 0000000..a3ab3c1
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayDevice.java
@@ -0,0 +1,212 @@
+/*
+ * 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.display;
+
+import android.graphics.Rect;
+import android.os.IBinder;
+import android.view.Surface;
+
+import java.io.PrintWriter;
+
+/**
+ * Represents a physical display device such as the built-in display
+ * an external monitor, or a WiFi display.
+ * <p>
+ * Display devices are guarded by the {@link DisplayManagerService.SyncRoot} lock.
+ * </p>
+ */
+abstract class DisplayDevice {
+    private final DisplayAdapter mDisplayAdapter;
+    private final IBinder mDisplayToken;
+
+    // The display device does not manage these properties itself, they are set by
+    // the display manager service.  The display device shouldn't really be looking at these.
+    private int mCurrentLayerStack = -1;
+    private int mCurrentOrientation = -1;
+    private Rect mCurrentLayerStackRect;
+    private Rect mCurrentDisplayRect;
+
+    // The display device owns its surface, but it should only set it
+    // within a transaction from performTraversalInTransactionLocked.
+    private Surface mCurrentSurface;
+
+    public DisplayDevice(DisplayAdapter displayAdapter, IBinder displayToken) {
+        mDisplayAdapter = displayAdapter;
+        mDisplayToken = displayToken;
+    }
+
+    /**
+     * Gets the display adapter that owns the display device.
+     *
+     * @return The display adapter.
+     */
+    public final DisplayAdapter getAdapterLocked() {
+        return mDisplayAdapter;
+    }
+
+    /**
+     * Gets the Surface Flinger display token for this display.
+     *
+     * @return The display token, or null if the display is not being managed
+     * by Surface Flinger.
+     */
+    public final IBinder getDisplayTokenLocked() {
+        return mDisplayToken;
+    }
+
+    /**
+     * Gets the name of the display device.
+     *
+     * @return The display device name.
+     */
+    public final String getNameLocked() {
+        return getDisplayDeviceInfoLocked().name;
+    }
+
+    /**
+     * Gets information about the display device.
+     *
+     * The information returned should not change between calls unless the display
+     * adapter sent a {@link DisplayAdapter#DISPLAY_DEVICE_EVENT_CHANGED} event and
+     * {@link #applyPendingDisplayDeviceInfoChangesLocked()} has been called to apply
+     * the pending changes.
+     *
+     * @return The display device info, which should be treated as immutable by the caller.
+     * The display device should allocate a new display device info object whenever
+     * the data changes.
+     */
+    public abstract DisplayDeviceInfo getDisplayDeviceInfoLocked();
+
+    /**
+     * Applies any pending changes to the observable state of the display device
+     * if the display adapter sent a {@link DisplayAdapter#DISPLAY_DEVICE_EVENT_CHANGED} event.
+     */
+    public void applyPendingDisplayDeviceInfoChangesLocked() {
+    }
+
+    /**
+     * Gives the display device a chance to update its properties while in a transaction.
+     */
+    public void performTraversalInTransactionLocked() {
+    }
+
+    /**
+     * Blanks the display, if supported.
+     */
+    public void blankLocked() {
+    }
+
+    /**
+     * Unblanks the display, if supported.
+     */
+    public void unblankLocked() {
+    }
+
+    /**
+     * Sets the display layer stack while in a transaction.
+     */
+    public final void setLayerStackInTransactionLocked(int layerStack) {
+        if (mCurrentLayerStack != layerStack) {
+            mCurrentLayerStack = layerStack;
+            Surface.setDisplayLayerStack(mDisplayToken, layerStack);
+        }
+    }
+
+    /**
+     * Sets the display projection while in a transaction.
+     *
+     * @param orientation defines the display's orientation
+     * @param layerStackRect defines which area of the window manager coordinate
+     *            space will be used
+     * @param displayRect defines where on the display will layerStackRect be
+     *            mapped to. displayRect is specified post-orientation, that is
+     *            it uses the orientation seen by the end-user
+     */
+    public final void setProjectionInTransactionLocked(int orientation,
+            Rect layerStackRect, Rect displayRect) {
+        if (mCurrentOrientation != orientation
+                || mCurrentLayerStackRect == null
+                || !mCurrentLayerStackRect.equals(layerStackRect)
+                || mCurrentDisplayRect == null
+                || !mCurrentDisplayRect.equals(displayRect)) {
+            mCurrentOrientation = orientation;
+
+            if (mCurrentLayerStackRect == null) {
+                mCurrentLayerStackRect = new Rect();
+            }
+            mCurrentLayerStackRect.set(layerStackRect);
+
+            if (mCurrentDisplayRect == null) {
+                mCurrentDisplayRect = new Rect();
+            }
+            mCurrentDisplayRect.set(displayRect);
+
+            Surface.setDisplayProjection(mDisplayToken,
+                    orientation, layerStackRect, displayRect);
+        }
+    }
+
+    /**
+     * Sets the display surface while in a transaction.
+     */
+    public final void setSurfaceInTransactionLocked(Surface surface) {
+        if (mCurrentSurface != surface) {
+            mCurrentSurface = surface;
+            Surface.setDisplaySurface(mDisplayToken, surface);
+        }
+    }
+
+    /**
+     * Populates the specified viewport object with orientation,
+     * physical and logical rects based on the display's current projection.
+     */
+    public final void populateViewportLocked(DisplayViewport viewport) {
+        viewport.orientation = mCurrentOrientation;
+
+        if (mCurrentLayerStackRect != null) {
+            viewport.logicalFrame.set(mCurrentLayerStackRect);
+        } else {
+            viewport.logicalFrame.setEmpty();
+        }
+
+        if (mCurrentDisplayRect != null) {
+            viewport.physicalFrame.set(mCurrentDisplayRect);
+        } else {
+            viewport.physicalFrame.setEmpty();
+        }
+
+        boolean isRotated = (mCurrentOrientation == Surface.ROTATION_90
+                || mCurrentOrientation == Surface.ROTATION_270);
+        DisplayDeviceInfo info = getDisplayDeviceInfoLocked();
+        viewport.deviceWidth = isRotated ? info.height : info.width;
+        viewport.deviceHeight = isRotated ? info.width : info.height;
+    }
+
+    /**
+     * Dumps the local state of the display device.
+     * Does not need to dump the display device info because that is already dumped elsewhere.
+     */
+    public void dumpLocked(PrintWriter pw) {
+        pw.println("mAdapter=" + mDisplayAdapter.getName());
+        pw.println("mDisplayToken=" + mDisplayToken);
+        pw.println("mCurrentLayerStack=" + mCurrentLayerStack);
+        pw.println("mCurrentOrientation=" + mCurrentOrientation);
+        pw.println("mCurrentLayerStackRect=" + mCurrentLayerStackRect);
+        pw.println("mCurrentDisplayRect=" + mCurrentDisplayRect);
+        pw.println("mCurrentSurface=" + mCurrentSurface);
+    }
+}
diff --git a/services/java/com/android/server/display/DisplayDeviceInfo.java b/services/java/com/android/server/display/DisplayDeviceInfo.java
new file mode 100644
index 0000000..247d8a0
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayDeviceInfo.java
@@ -0,0 +1,244 @@
+/*
+ * 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.display;
+
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.Surface;
+
+import libcore.util.Objects;
+
+/**
+ * Describes the characteristics of a physical display device.
+ */
+final class DisplayDeviceInfo {
+    /**
+     * Flag: Indicates that this display device should be considered the default display
+     * device of the system.
+     */
+    public static final int FLAG_DEFAULT_DISPLAY = 1 << 0;
+
+    /**
+     * Flag: Indicates that the orientation of this display device is coupled to the
+     * rotation of its associated logical display.
+     * <p>
+     * This flag should be applied to the default display to indicate that the user
+     * physically rotates the display when content is presented in a different orientation.
+     * The display manager will apply a coordinate transformation assuming that the
+     * physical orientation of the display matches the logical orientation of its content.
+     * </p><p>
+     * The flag should not be set when the display device is mounted in a fixed orientation
+     * such as on a desk.  The display manager will apply a coordinate transformation
+     * such as a scale and translation to letterbox or pillarbox format under the
+     * assumption that the physical orientation of the display is invariant.
+     * </p>
+     */
+    public static final int FLAG_ROTATES_WITH_CONTENT = 1 << 1;
+
+    /**
+     * Flag: Indicates that this display device has secure video output, such as HDCP.
+     */
+    public static final int FLAG_SECURE = 1 << 2;
+
+    /**
+     * Flag: Indicates that this display device supports compositing
+     * from gralloc protected buffers.
+     */
+    public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 3;
+
+    /**
+     * Touch attachment: Display does not receive touch.
+     */
+    public static final int TOUCH_NONE = 0;
+
+    /**
+     * Touch attachment: Touch input is via the internal interface.
+     */
+    public static final int TOUCH_INTERNAL = 1;
+
+    /**
+     * Touch attachment: Touch input is via an external interface, such as USB.
+     */
+    public static final int TOUCH_EXTERNAL = 2;
+
+    /**
+     * Gets the name of the display device, which may be derived from
+     * EDID or other sources.  The name may be displayed to the user.
+     */
+    public String name;
+
+    /**
+     * The width of the display in its natural orientation, in pixels.
+     * This value is not affected by display rotation.
+     */
+    public int width;
+
+    /**
+     * The height of the display in its natural orientation, in pixels.
+     * This value is not affected by display rotation.
+     */
+    public int height;
+
+    /**
+     * The refresh rate of the display.
+     */
+    public float refreshRate;
+
+    /**
+     * The nominal apparent density of the display in DPI used for layout calculations.
+     * This density is sensitive to the viewing distance.  A big TV and a tablet may have
+     * the same apparent density even though the pixels on the TV are much bigger than
+     * those on the tablet.
+     */
+    public int densityDpi;
+
+    /**
+     * The physical density of the display in DPI in the X direction.
+     * This density should specify the physical size of each pixel.
+     */
+    public float xDpi;
+
+    /**
+     * The physical density of the display in DPI in the X direction.
+     * This density should specify the physical size of each pixel.
+     */
+    public float yDpi;
+
+    /**
+     * Display flags.
+     */
+    public int flags;
+
+    /**
+     * The touch attachment, per {@link DisplayViewport#touch}.
+     */
+    public int touch;
+
+    /**
+     * The additional rotation to apply to all content presented on the display device
+     * relative to its physical coordinate system.  Default is {@link Surface#ROTATION_0}.
+     * <p>
+     * This field can be used to compensate for the fact that the display has been
+     * physically rotated relative to its natural orientation such as an HDMI monitor
+     * that has been mounted sideways to appear to be portrait rather than landscape.
+     * </p>
+     */
+    public int rotation = Surface.ROTATION_0;
+
+    /**
+     * Display type.
+     */
+    public int type;
+
+    /**
+     * Display address, or null if none.
+     * Interpretation varies by display type.
+     */
+    public String address;
+
+    public void setAssumedDensityForExternalDisplay(int width, int height) {
+        densityDpi = Math.min(width, height) * DisplayMetrics.DENSITY_XHIGH / 1080;
+        // Technically, these values should be smaller than the apparent density
+        // but we don't know the physical size of the display.
+        xDpi = densityDpi;
+        yDpi = densityDpi;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o instanceof DisplayDeviceInfo && equals((DisplayDeviceInfo)o);
+    }
+
+    public boolean equals(DisplayDeviceInfo other) {
+        return other != null
+                && Objects.equal(name, other.name)
+                && width == other.width
+                && height == other.height
+                && refreshRate == other.refreshRate
+                && densityDpi == other.densityDpi
+                && xDpi == other.xDpi
+                && yDpi == other.yDpi
+                && flags == other.flags
+                && touch == other.touch
+                && rotation == other.rotation
+                && type == other.type
+                && Objects.equal(address, other.address);
+    }
+
+    @Override
+    public int hashCode() {
+        return 0; // don't care
+    }
+
+    public void copyFrom(DisplayDeviceInfo other) {
+        name = other.name;
+        width = other.width;
+        height = other.height;
+        refreshRate = other.refreshRate;
+        densityDpi = other.densityDpi;
+        xDpi = other.xDpi;
+        yDpi = other.yDpi;
+        flags = other.flags;
+        touch = other.touch;
+        rotation = other.rotation;
+        type = other.type;
+        address = other.address;
+    }
+
+    // For debugging purposes
+    @Override
+    public String toString() {
+        return "DisplayDeviceInfo{\"" + name + "\": " + width + " x " + height + ", "
+                + refreshRate + " fps, "
+                + "density " + densityDpi + ", " + xDpi + " x " + yDpi + " dpi"
+                + ", touch " + touchToString(touch) + flagsToString(flags)
+                + ", rotation " + rotation
+                + ", type " + Display.typeToString(type)
+                + ", address " + address
+                + "}";
+    }
+
+    private static String touchToString(int touch) {
+        switch (touch) {
+            case TOUCH_NONE:
+                return "NONE";
+            case TOUCH_INTERNAL:
+                return "INTERNAL";
+            case TOUCH_EXTERNAL:
+                return "EXTERNAL";
+            default:
+                return Integer.toString(touch);
+        }
+    }
+
+    private static String flagsToString(int flags) {
+        StringBuilder msg = new StringBuilder();
+        if ((flags & FLAG_DEFAULT_DISPLAY) != 0) {
+            msg.append(", FLAG_DEFAULT_DISPLAY");
+        }
+        if ((flags & FLAG_ROTATES_WITH_CONTENT) != 0) {
+            msg.append(", FLAG_ROTATES_WITH_CONTENT");
+        }
+        if ((flags & FLAG_SECURE) != 0) {
+            msg.append(", FLAG_SECURE");
+        }
+        if ((flags & FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
+            msg.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
+        }
+        return msg.toString();
+    }
+}
diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java
new file mode 100644
index 0000000..e58a0a5cb
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayManagerService.java
@@ -0,0 +1,1028 @@
+/*
+ * 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.display;
+
+import com.android.internal.util.IndentingPrintWriter;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.display.DisplayManagerGlobal;
+import android.hardware.display.IDisplayManager;
+import android.hardware.display.IDisplayManagerCallback;
+import android.hardware.display.WifiDisplayStatus;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.DisplayInfo;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Manages attached displays.
+ * <p>
+ * The {@link DisplayManagerService} manages the global lifecycle of displays,
+ * decides how to configure logical displays based on the physical display devices currently
+ * attached, sends notifications to the system and to applications when the state
+ * changes, and so on.
+ * </p><p>
+ * The display manager service relies on a collection of {@link DisplayAdapter} components,
+ * for discovering and configuring physical display devices attached to the system.
+ * There are separate display adapters for each manner that devices are attached:
+ * one display adapter for built-in local displays, one for simulated non-functional
+ * displays when the system is headless, one for simulated overlay displays used for
+ * development, one for wifi displays, etc.
+ * </p><p>
+ * Display adapters are only weakly coupled to the display manager service.
+ * Display adapters communicate changes in display device state to the display manager
+ * service asynchronously via a {@link DisplayAdapter.Listener} registered
+ * by the display manager service.  This separation of concerns is important for
+ * two main reasons.  First, it neatly encapsulates the responsibilities of these
+ * two classes: display adapters handle individual display devices whereas
+ * the display manager service handles the global state.  Second, it eliminates
+ * the potential for deadlocks resulting from asynchronous display device discovery.
+ * </p>
+ *
+ * <h3>Synchronization</h3>
+ * <p>
+ * Because the display manager may be accessed by multiple threads, the synchronization
+ * story gets a little complicated.  In particular, the window manager may call into
+ * the display manager while holding a surface transaction with the expectation that
+ * it can apply changes immediately.  Unfortunately, that means we can't just do
+ * everything asynchronously (*grump*).
+ * </p><p>
+ * To make this work, all of the objects that belong to the display manager must
+ * use the same lock.  We call this lock the synchronization root and it has a unique
+ * type {@link DisplayManagerService.SyncRoot}.  Methods that require this lock are
+ * named with the "Locked" suffix.
+ * </p><p>
+ * Where things get tricky is that the display manager is not allowed to make
+ * any potentially reentrant calls, especially into the window manager.  We generally
+ * avoid this by making all potentially reentrant out-calls asynchronous.
+ * </p>
+ */
+public final class DisplayManagerService extends IDisplayManager.Stub {
+    private static final String TAG = "DisplayManagerService";
+    private static final boolean DEBUG = false;
+
+    // When this system property is set to 0, WFD is forcibly disabled on boot.
+    // When this system property is set to 1, WFD is forcibly enabled on boot.
+    // Otherwise WFD is enabled according to the value of config_enableWifiDisplay.
+    private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
+
+    private static final String SYSTEM_HEADLESS = "ro.config.headless";
+    private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
+
+    private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1;
+    private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
+    private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
+    private static final int MSG_REQUEST_TRAVERSAL = 4;
+    private static final int MSG_UPDATE_VIEWPORT = 5;
+
+    private static final int DISPLAY_BLANK_STATE_UNKNOWN = 0;
+    private static final int DISPLAY_BLANK_STATE_BLANKED = 1;
+    private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2;
+
+    private final Context mContext;
+    private final boolean mHeadless;
+    private final DisplayManagerHandler mHandler;
+    private final Handler mUiHandler;
+    private final DisplayAdapterListener mDisplayAdapterListener;
+    private WindowManagerFuncs mWindowManagerFuncs;
+    private InputManagerFuncs mInputManagerFuncs;
+
+    // The synchronization root for the display manager.
+    // This lock guards most of the display manager's state.
+    private final SyncRoot mSyncRoot = new SyncRoot();
+
+    // True if in safe mode.
+    // This option may disable certain display adapters.
+    public boolean mSafeMode;
+
+    // True if we are in a special boot mode where only core applications and
+    // services should be started.  This option may disable certain display adapters.
+    public boolean mOnlyCore;
+
+    // True if the display manager service should pretend there is only one display
+    // and only tell applications about the existence of the default logical display.
+    // The display manager can still mirror content to secondary displays but applications
+    // cannot present unique content on those displays.
+    // Used for demonstration purposes only.
+    private final boolean mSingleDisplayDemoMode;
+
+    // All callback records indexed by calling process id.
+    public final SparseArray<CallbackRecord> mCallbacks =
+            new SparseArray<CallbackRecord>();
+
+    // List of all currently registered display adapters.
+    private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
+
+    // List of all currently connected display devices.
+    private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();
+
+    // List of all removed display devices.
+    private final ArrayList<DisplayDevice> mRemovedDisplayDevices = new ArrayList<DisplayDevice>();
+
+    // List of all logical displays indexed by logical display id.
+    private final SparseArray<LogicalDisplay> mLogicalDisplays =
+            new SparseArray<LogicalDisplay>();
+    private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
+
+    // Set to true if all displays have been blanked by the power manager.
+    private int mAllDisplayBlankStateFromPowerManager;
+
+    // Set to true when there are pending display changes that have yet to be applied
+    // to the surface flinger state.
+    private boolean mPendingTraversal;
+
+    // The Wifi display adapter, or null if not registered.
+    private WifiDisplayAdapter mWifiDisplayAdapter;
+
+    // Viewports of the default display and the display that should receive touch
+    // input from an external source.  Used by the input system.
+    private final DisplayViewport mDefaultViewport = new DisplayViewport();
+    private final DisplayViewport mExternalTouchViewport = new DisplayViewport();
+
+    // Persistent data store for all internal settings maintained by the display manager service.
+    private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
+
+    // Temporary callback list, used when sending display events to applications.
+    // May be used outside of the lock but only on the handler thread.
+    private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
+
+    // Temporary display info, used for comparing display configurations.
+    private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
+
+    // Temporary viewports, used when sending new viewport information to the
+    // input system.  May be used outside of the lock but only on the handler thread.
+    private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
+    private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
+
+    public DisplayManagerService(Context context, Handler mainHandler, Handler uiHandler) {
+        mContext = context;
+        mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
+
+        mHandler = new DisplayManagerHandler(mainHandler.getLooper());
+        mUiHandler = uiHandler;
+        mDisplayAdapterListener = new DisplayAdapterListener();
+        mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
+
+        mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
+    }
+
+    /**
+     * Pauses the boot process to wait for the first display to be initialized.
+     */
+    public boolean waitForDefaultDisplay() {
+        synchronized (mSyncRoot) {
+            long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
+            while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
+                long delay = timeout - SystemClock.uptimeMillis();
+                if (delay <= 0) {
+                    return false;
+                }
+                if (DEBUG) {
+                    Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
+                }
+                try {
+                    mSyncRoot.wait(delay);
+                } catch (InterruptedException ex) {
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Called during initialization to associate the display manager with the
+     * window manager.
+     */
+    public void setWindowManager(WindowManagerFuncs windowManagerFuncs) {
+        synchronized (mSyncRoot) {
+            mWindowManagerFuncs = windowManagerFuncs;
+            scheduleTraversalLocked(false);
+        }
+    }
+
+    /**
+     * Called during initialization to associate the display manager with the
+     * input manager.
+     */
+    public void setInputManager(InputManagerFuncs inputManagerFuncs) {
+        synchronized (mSyncRoot) {
+            mInputManagerFuncs = inputManagerFuncs;
+            scheduleTraversalLocked(false);
+        }
+    }
+
+    /**
+     * Called when the system is ready to go.
+     */
+    public void systemReady(boolean safeMode, boolean onlyCore) {
+        synchronized (mSyncRoot) {
+            mSafeMode = safeMode;
+            mOnlyCore = onlyCore;
+        }
+
+        mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
+    }
+
+    /**
+     * Returns true if the device is headless.
+     *
+     * @return True if the device is headless.
+     */
+    public boolean isHeadless() {
+        return mHeadless;
+    }
+
+    /**
+     * Overrides the display information of a particular logical display.
+     * This is used by the window manager to control the size and characteristics
+     * of the default display.  It is expected to apply the requested change
+     * to the display information synchronously so that applications will immediately
+     * observe the new state.
+     *
+     * @param displayId The logical display id.
+     * @param info The new data to be stored.
+     */
+    public void setDisplayInfoOverrideFromWindowManager(
+            int displayId, DisplayInfo info) {
+        synchronized (mSyncRoot) {
+            LogicalDisplay display = mLogicalDisplays.get(displayId);
+            if (display != null) {
+                mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
+                display.setDisplayInfoOverrideFromWindowManagerLocked(info);
+                if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
+                    sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+                    scheduleTraversalLocked(false);
+                }
+            }
+        }
+    }
+
+    /**
+     * Called by the window manager to perform traversals while holding a
+     * surface flinger transaction.
+     */
+    public void performTraversalInTransactionFromWindowManager() {
+        synchronized (mSyncRoot) {
+            if (!mPendingTraversal) {
+                return;
+            }
+            mPendingTraversal = false;
+
+            performTraversalInTransactionLocked();
+        }
+    }
+
+    /**
+     * Called by the power manager to blank all displays.
+     */
+    public void blankAllDisplaysFromPowerManager() {
+        synchronized (mSyncRoot) {
+            if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) {
+                mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED;
+
+                final int count = mDisplayDevices.size();
+                for (int i = 0; i < count; i++) {
+                    DisplayDevice device = mDisplayDevices.get(i);
+                    device.blankLocked();
+                }
+
+                scheduleTraversalLocked(false);
+            }
+        }
+    }
+
+    /**
+     * Called by the power manager to unblank all displays.
+     */
+    public void unblankAllDisplaysFromPowerManager() {
+        synchronized (mSyncRoot) {
+            if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) {
+                mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED;
+
+                final int count = mDisplayDevices.size();
+                for (int i = 0; i < count; i++) {
+                    DisplayDevice device = mDisplayDevices.get(i);
+                    device.unblankLocked();
+                }
+
+                scheduleTraversalLocked(false);
+            }
+        }
+    }
+
+    /**
+     * Returns information about the specified logical display.
+     *
+     * @param displayId The logical display id.
+     * @return The logical display info, or null if the display does not exist.  The
+     * returned object must be treated as immutable.
+     */
+    @Override // Binder call
+    public DisplayInfo getDisplayInfo(int displayId) {
+        synchronized (mSyncRoot) {
+            LogicalDisplay display = mLogicalDisplays.get(displayId);
+            if (display != null) {
+                return display.getDisplayInfoLocked();
+            }
+            return null;
+        }
+    }
+
+    /**
+     * Returns the list of all display ids.
+     */
+    @Override // Binder call
+    public int[] getDisplayIds() {
+        synchronized (mSyncRoot) {
+            final int count = mLogicalDisplays.size();
+            int[] displayIds = new int[count];
+            for (int i = 0; i < count; i++) {
+                displayIds[i] = mLogicalDisplays.keyAt(i);
+            }
+            return displayIds;
+        }
+    }
+
+    @Override // Binder call
+    public void registerCallback(IDisplayManagerCallback callback) {
+        if (callback == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+
+        synchronized (mSyncRoot) {
+            int callingPid = Binder.getCallingPid();
+            if (mCallbacks.get(callingPid) != null) {
+                throw new SecurityException("The calling process has already "
+                        + "registered an IDisplayManagerCallback.");
+            }
+
+            CallbackRecord record = new CallbackRecord(callingPid, callback);
+            try {
+                IBinder binder = callback.asBinder();
+                binder.linkToDeath(record, 0);
+            } catch (RemoteException ex) {
+                // give up
+                throw new RuntimeException(ex);
+            }
+
+            mCallbacks.put(callingPid, record);
+        }
+    }
+
+    private void onCallbackDied(int pid) {
+        synchronized (mSyncRoot) {
+            mCallbacks.remove(pid);
+        }
+    }
+
+    @Override // Binder call
+    public void scanWifiDisplays() {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mSyncRoot) {
+                if (mWifiDisplayAdapter != null) {
+                    mWifiDisplayAdapter.requestScanLocked();
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    @Override // Binder call
+    public void connectWifiDisplay(String address) {
+        if (address == null) {
+            throw new IllegalArgumentException("address must not be null");
+        }
+
+        final boolean trusted = canCallerConfigureWifiDisplay();
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mSyncRoot) {
+                if (mWifiDisplayAdapter != null) {
+                    mWifiDisplayAdapter.requestConnectLocked(address, trusted);
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    @Override // Binder call
+    public void disconnectWifiDisplay() {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mSyncRoot) {
+                if (mWifiDisplayAdapter != null) {
+                    mWifiDisplayAdapter.requestDisconnectLocked();
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    @Override // Binder call
+    public void renameWifiDisplay(String address, String alias) {
+        if (address == null) {
+            throw new IllegalArgumentException("address must not be null");
+        }
+        if (!canCallerConfigureWifiDisplay()) {
+            throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
+                    + "rename a wifi display.");
+        }
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mSyncRoot) {
+                if (mWifiDisplayAdapter != null) {
+                    mWifiDisplayAdapter.requestRenameLocked(address, alias);
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    @Override // Binder call
+    public void forgetWifiDisplay(String address) {
+        if (address == null) {
+            throw new IllegalArgumentException("address must not be null");
+        }
+        if (!canCallerConfigureWifiDisplay()) {
+            throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
+                    + "forget a wifi display.");
+        }
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mSyncRoot) {
+                if (mWifiDisplayAdapter != null) {
+                    mWifiDisplayAdapter.requestForgetLocked(address);
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    @Override // Binder call
+    public WifiDisplayStatus getWifiDisplayStatus() {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mSyncRoot) {
+                if (mWifiDisplayAdapter != null) {
+                    return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
+                } else {
+                    return new WifiDisplayStatus();
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private boolean canCallerConfigureWifiDisplay() {
+        return mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
+                == PackageManager.PERMISSION_GRANTED;
+    }
+
+    private void registerDefaultDisplayAdapter() {
+        // Register default display adapter.
+        synchronized (mSyncRoot) {
+            if (mHeadless) {
+                registerDisplayAdapterLocked(new HeadlessDisplayAdapter(
+                        mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
+            } else {
+                registerDisplayAdapterLocked(new LocalDisplayAdapter(
+                        mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
+            }
+        }
+    }
+
+    private void registerAdditionalDisplayAdapters() {
+        synchronized (mSyncRoot) {
+            if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
+                registerOverlayDisplayAdapterLocked();
+                registerWifiDisplayAdapterLocked();
+            }
+        }
+    }
+
+    private void registerOverlayDisplayAdapterLocked() {
+        registerDisplayAdapterLocked(new OverlayDisplayAdapter(
+                mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
+    }
+
+    private void registerWifiDisplayAdapterLocked() {
+        if (mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_enableWifiDisplay)
+                || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
+            mWifiDisplayAdapter = new WifiDisplayAdapter(
+                    mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
+                    mPersistentDataStore);
+            registerDisplayAdapterLocked(mWifiDisplayAdapter);
+        }
+    }
+
+    private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
+        // In safe mode, we disable non-essential display adapters to give the user
+        // an opportunity to fix broken settings or other problems that might affect
+        // system stability.
+        // In only-core mode, we disable non-essential display adapters to minimize
+        // the number of dependencies that are started while in this mode and to
+        // prevent problems that might occur due to the device being encrypted.
+        return !mSafeMode && !mOnlyCore;
+    }
+
+    private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
+        mDisplayAdapters.add(adapter);
+        adapter.registerLocked();
+    }
+
+    private void handleDisplayDeviceAdded(DisplayDevice device) {
+        synchronized (mSyncRoot) {
+            if (mDisplayDevices.contains(device)) {
+                Slog.w(TAG, "Attempted to add already added display device: "
+                        + device.getDisplayDeviceInfoLocked());
+                return;
+            }
+
+            Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked());
+
+            mDisplayDevices.add(device);
+            addLogicalDisplayLocked(device);
+            scheduleTraversalLocked(false);
+
+            // Blank or unblank the display immediately to match the state requested
+            // by the power manager (if known).
+            switch (mAllDisplayBlankStateFromPowerManager) {
+                case DISPLAY_BLANK_STATE_BLANKED:
+                    device.blankLocked();
+                    break;
+                case DISPLAY_BLANK_STATE_UNBLANKED:
+                    device.unblankLocked();
+                    break;
+            }
+        }
+    }
+
+    private void handleDisplayDeviceChanged(DisplayDevice device) {
+        synchronized (mSyncRoot) {
+            if (!mDisplayDevices.contains(device)) {
+                Slog.w(TAG, "Attempted to change non-existent display device: "
+                        + device.getDisplayDeviceInfoLocked());
+                return;
+            }
+
+            Slog.i(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked());
+
+            device.applyPendingDisplayDeviceInfoChangesLocked();
+            if (updateLogicalDisplaysLocked()) {
+                scheduleTraversalLocked(false);
+            }
+        }
+    }
+
+    private void handleDisplayDeviceRemoved(DisplayDevice device) {
+        synchronized (mSyncRoot) {
+            if (!mDisplayDevices.remove(device)) {
+                Slog.w(TAG, "Attempted to remove non-existent display device: "
+                        + device.getDisplayDeviceInfoLocked());
+                return;
+            }
+
+            Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked());
+
+            mRemovedDisplayDevices.add(device);
+            updateLogicalDisplaysLocked();
+            scheduleTraversalLocked(false);
+        }
+    }
+
+    // Adds a new logical display based on the given display device.
+    // Sends notifications if needed.
+    private void addLogicalDisplayLocked(DisplayDevice device) {
+        DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
+        boolean isDefault = (deviceInfo.flags
+                & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
+        if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
+            Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
+            isDefault = false;
+        }
+
+        if (!isDefault && mSingleDisplayDemoMode) {
+            Slog.i(TAG, "Not creating a logical display for a secondary display "
+                    + " because single display demo mode is enabled: " + deviceInfo);
+            return;
+        }
+
+        final int displayId = assignDisplayIdLocked(isDefault);
+        final int layerStack = assignLayerStackLocked(displayId);
+
+        LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
+        display.updateLocked(mDisplayDevices);
+        if (!display.isValidLocked()) {
+            // This should never happen currently.
+            Slog.w(TAG, "Ignoring display device because the logical display "
+                    + "created from it was not considered valid: " + deviceInfo);
+            return;
+        }
+
+        mLogicalDisplays.put(displayId, display);
+
+        // Wake up waitForDefaultDisplay.
+        if (isDefault) {
+            mSyncRoot.notifyAll();
+        }
+
+        sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
+    }
+
+    private int assignDisplayIdLocked(boolean isDefault) {
+        return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
+    }
+
+    private int assignLayerStackLocked(int displayId) {
+        // Currently layer stacks and display ids are the same.
+        // This need not be the case.
+        return displayId;
+    }
+
+    // Updates all existing logical displays given the current set of display devices.
+    // Removes invalid logical displays.
+    // Sends notifications if needed.
+    private boolean updateLogicalDisplaysLocked() {
+        boolean changed = false;
+        for (int i = mLogicalDisplays.size(); i-- > 0; ) {
+            final int displayId = mLogicalDisplays.keyAt(i);
+            LogicalDisplay display = mLogicalDisplays.valueAt(i);
+
+            mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
+            display.updateLocked(mDisplayDevices);
+            if (!display.isValidLocked()) {
+                mLogicalDisplays.removeAt(i);
+                sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
+                changed = true;
+            } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
+                sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+                changed = true;
+            }
+        }
+        return changed;
+    }
+
+    private void performTraversalInTransactionLocked() {
+        // Perform one last traversal for each removed display device.
+        final int removedCount = mRemovedDisplayDevices.size();
+        for (int i = 0; i < removedCount; i++) {
+            DisplayDevice device = mRemovedDisplayDevices.get(i);
+            device.performTraversalInTransactionLocked();
+        }
+        mRemovedDisplayDevices.clear();
+
+        // Clear all viewports before configuring displays so that we can keep
+        // track of which ones we have configured.
+        clearViewportsLocked();
+
+        // Configure each display device.
+        final int count = mDisplayDevices.size();
+        for (int i = 0; i < count; i++) {
+            DisplayDevice device = mDisplayDevices.get(i);
+            configureDisplayInTransactionLocked(device);
+            device.performTraversalInTransactionLocked();
+        }
+
+        // Tell the input system about these new viewports.
+        if (mInputManagerFuncs != null) {
+            mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
+        }
+    }
+
+    /**
+     * Tells the display manager whether there is interesting unique content on the
+     * specified logical display.  This is used to control automatic mirroring.
+     * <p>
+     * If the display has unique content, then the display manager arranges for it
+     * to be presented on a physical display if appropriate.  Otherwise, the display manager
+     * may choose to make the physical display mirror some other logical display.
+     * </p>
+     *
+     * @param displayId The logical display id to update.
+     * @param hasContent True if the logical display has content.
+     * @param inTraversal True if called from WindowManagerService during a window traversal prior
+     * to call to performTraversalInTransactionFromWindowManager.
+     */
+    public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) {
+        synchronized (mSyncRoot) {
+            LogicalDisplay display = mLogicalDisplays.get(displayId);
+            if (display != null && display.hasContentLocked() != hasContent) {
+                display.setHasContentLocked(hasContent);
+                scheduleTraversalLocked(inTraversal);
+            }
+        }
+    }
+
+    private void clearViewportsLocked() {
+        mDefaultViewport.valid = false;
+        mExternalTouchViewport.valid = false;
+    }
+
+    private void configureDisplayInTransactionLocked(DisplayDevice device) {
+        // Find the logical display that the display device is showing.
+        LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
+        if (display != null && !display.hasContentLocked()) {
+            display = null;
+        }
+        if (display == null) {
+            display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
+        }
+
+        // Apply the logical display configuration to the display device.
+        if (display == null) {
+            // TODO: no logical display for the device, blank it
+            Slog.w(TAG, "Missing logical display to use for physical display device: "
+                    + device.getDisplayDeviceInfoLocked());
+            return;
+        } else {
+            boolean isBlanked = (mAllDisplayBlankStateFromPowerManager
+                    == DISPLAY_BLANK_STATE_BLANKED);
+            display.configureDisplayInTransactionLocked(device, isBlanked);
+        }
+
+        // Update the viewports if needed.
+        DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
+        if (!mDefaultViewport.valid
+                && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
+            setViewportLocked(mDefaultViewport, display, device);
+        }
+        if (!mExternalTouchViewport.valid
+                && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
+            setViewportLocked(mExternalTouchViewport, display, device);
+        }
+    }
+
+    private static void setViewportLocked(DisplayViewport viewport,
+            LogicalDisplay display, DisplayDevice device) {
+        viewport.valid = true;
+        viewport.displayId = display.getDisplayIdLocked();
+        device.populateViewportLocked(viewport);
+    }
+
+    private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
+        final int count = mLogicalDisplays.size();
+        for (int i = 0; i < count; i++) {
+            LogicalDisplay display = mLogicalDisplays.valueAt(i);
+            if (display.getPrimaryDisplayDeviceLocked() == device) {
+                return display;
+            }
+        }
+        return null;
+    }
+
+    private void sendDisplayEventLocked(int displayId, int event) {
+        Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
+        mHandler.sendMessage(msg);
+    }
+
+    // Requests that performTraversalsInTransactionFromWindowManager be called at a
+    // later time to apply changes to surfaces and displays.
+    private void scheduleTraversalLocked(boolean inTraversal) {
+        if (!mPendingTraversal && mWindowManagerFuncs != null) {
+            mPendingTraversal = true;
+            if (!inTraversal) {
+                mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
+            }
+        }
+    }
+
+    // Runs on Handler thread.
+    // Delivers display event notifications to callbacks.
+    private void deliverDisplayEvent(int displayId, int event) {
+        if (DEBUG) {
+            Slog.d(TAG, "Delivering display event: displayId="
+                    + displayId + ", event=" + event);
+        }
+
+        // Grab the lock and copy the callbacks.
+        final int count;
+        synchronized (mSyncRoot) {
+            count = mCallbacks.size();
+            mTempCallbacks.clear();
+            for (int i = 0; i < count; i++) {
+                mTempCallbacks.add(mCallbacks.valueAt(i));
+            }
+        }
+
+        // After releasing the lock, send the notifications out.
+        for (int i = 0; i < count; i++) {
+            mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
+        }
+        mTempCallbacks.clear();
+    }
+
+    @Override // Binder call
+    public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
+        if (mContext == null
+                || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
+                        != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump DisplayManager from from pid="
+                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+            return;
+        }
+
+        pw.println("DISPLAY MANAGER (dumpsys display)");
+
+        synchronized (mSyncRoot) {
+            pw.println("  mHeadless=" + mHeadless);
+            pw.println("  mOnlyCode=" + mOnlyCore);
+            pw.println("  mSafeMode=" + mSafeMode);
+            pw.println("  mPendingTraversal=" + mPendingTraversal);
+            pw.println("  mAllDisplayBlankStateFromPowerManager="
+                    + mAllDisplayBlankStateFromPowerManager);
+            pw.println("  mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
+            pw.println("  mDefaultViewport=" + mDefaultViewport);
+            pw.println("  mExternalTouchViewport=" + mExternalTouchViewport);
+            pw.println("  mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
+
+            IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
+            ipw.increaseIndent();
+
+            pw.println();
+            pw.println("Display Adapters: size=" + mDisplayAdapters.size());
+            for (DisplayAdapter adapter : mDisplayAdapters) {
+                pw.println("  " + adapter.getName());
+                adapter.dumpLocked(ipw);
+            }
+
+            pw.println();
+            pw.println("Display Devices: size=" + mDisplayDevices.size());
+            for (DisplayDevice device : mDisplayDevices) {
+                pw.println("  " + device.getDisplayDeviceInfoLocked());
+                device.dumpLocked(ipw);
+            }
+
+            final int logicalDisplayCount = mLogicalDisplays.size();
+            pw.println();
+            pw.println("Logical Displays: size=" + logicalDisplayCount);
+            for (int i = 0; i < logicalDisplayCount; i++) {
+                int displayId = mLogicalDisplays.keyAt(i);
+                LogicalDisplay display = mLogicalDisplays.valueAt(i);
+                pw.println("  Display " + displayId + ":");
+                display.dumpLocked(ipw);
+            }
+        }
+    }
+
+    /**
+     * This is the object that everything in the display manager locks on.
+     * We make it an inner class within the {@link DisplayManagerService} to so that it is
+     * clear that the object belongs to the display manager service and that it is
+     * a unique object with a special purpose.
+     */
+    public static final class SyncRoot {
+    }
+
+    /**
+     * Private interface to the window manager.
+     */
+    public interface WindowManagerFuncs {
+        /**
+         * Request that the window manager call
+         * {@link #performTraversalInTransactionFromWindowManager} within a surface
+         * transaction at a later time.
+         */
+        void requestTraversal();
+    }
+
+    /**
+     * Private interface to the input manager.
+     */
+    public interface InputManagerFuncs {
+        /**
+         * Sets information about the displays as needed by the input system.
+         * The input system should copy this information if required.
+         */
+        void setDisplayViewports(DisplayViewport defaultViewport,
+                DisplayViewport externalTouchViewport);
+    }
+
+    private final class DisplayManagerHandler extends Handler {
+        public DisplayManagerHandler(Looper looper) {
+            super(looper, null, true /*async*/);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
+                    registerDefaultDisplayAdapter();
+                    break;
+
+                case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
+                    registerAdditionalDisplayAdapters();
+                    break;
+
+                case MSG_DELIVER_DISPLAY_EVENT:
+                    deliverDisplayEvent(msg.arg1, msg.arg2);
+                    break;
+
+                case MSG_REQUEST_TRAVERSAL:
+                    mWindowManagerFuncs.requestTraversal();
+                    break;
+
+                case MSG_UPDATE_VIEWPORT: {
+                    synchronized (mSyncRoot) {
+                        mTempDefaultViewport.copyFrom(mDefaultViewport);
+                        mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
+                    }
+                    mInputManagerFuncs.setDisplayViewports(
+                            mTempDefaultViewport, mTempExternalTouchViewport);
+                    break;
+                }
+            }
+        }
+    }
+
+    private final class DisplayAdapterListener implements DisplayAdapter.Listener {
+        @Override
+        public void onDisplayDeviceEvent(DisplayDevice device, int event) {
+            switch (event) {
+                case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
+                    handleDisplayDeviceAdded(device);
+                    break;
+
+                case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
+                    handleDisplayDeviceChanged(device);
+                    break;
+
+                case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
+                    handleDisplayDeviceRemoved(device);
+                    break;
+            }
+        }
+
+        @Override
+        public void onTraversalRequested() {
+            synchronized (mSyncRoot) {
+                scheduleTraversalLocked(false);
+            }
+        }
+    }
+
+    private final class CallbackRecord implements DeathRecipient {
+        private final int mPid;
+        private final IDisplayManagerCallback mCallback;
+
+        public CallbackRecord(int pid, IDisplayManagerCallback callback) {
+            mPid = pid;
+            mCallback = callback;
+        }
+
+        @Override
+        public void binderDied() {
+            if (DEBUG) {
+                Slog.d(TAG, "Display listener for pid " + mPid + " died.");
+            }
+            onCallbackDied(mPid);
+        }
+
+        public void notifyDisplayEventAsync(int displayId, int event) {
+            try {
+                mCallback.onDisplayEvent(displayId, event);
+            } catch (RemoteException ex) {
+                Slog.w(TAG, "Failed to notify process "
+                        + mPid + " that displays changed, assuming it died.", ex);
+                binderDied();
+            }
+        }
+    }
+}
diff --git a/services/java/com/android/server/display/DisplayViewport.java b/services/java/com/android/server/display/DisplayViewport.java
new file mode 100644
index 0000000..5080556
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayViewport.java
@@ -0,0 +1,75 @@
+/*
+ * 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.display;
+
+import android.graphics.Rect;
+
+/**
+ * Describes how the pixels of physical display device reflects the content of
+ * a logical display.
+ * <p>
+ * This information is used by the input system to translate touch input from
+ * physical display coordinates into logical display coordinates.
+ * </p>
+ */
+public final class DisplayViewport {
+    // True if this viewport is valid.
+    public boolean valid;
+
+    // The logical display id.
+    public int displayId;
+
+    // The rotation applied to the physical coordinate system.
+    public int orientation;
+
+    // The portion of the logical display that are presented on this physical display.
+    public final Rect logicalFrame = new Rect();
+
+    // The portion of the (rotated) physical display that shows the logical display contents.
+    // The relation between logical and physical frame defines how the coordinate system
+    // should be scaled or translated after rotation.
+    public final Rect physicalFrame = new Rect();
+
+    // The full width and height of the display device, rotated in the same
+    // manner as physicalFrame.  This expresses the full native size of the display device.
+    // The physical frame should usually fit within this area.
+    public int deviceWidth;
+    public int deviceHeight;
+
+    public void copyFrom(DisplayViewport viewport) {
+        valid = viewport.valid;
+        displayId = viewport.displayId;
+        orientation = viewport.orientation;
+        logicalFrame.set(viewport.logicalFrame);
+        physicalFrame.set(viewport.physicalFrame);
+        deviceWidth = viewport.deviceWidth;
+        deviceHeight = viewport.deviceHeight;
+    }
+
+    // For debugging purposes.
+    @Override
+    public String toString() {
+        return "DisplayViewport{valid=" + valid
+                + ", displayId=" + displayId
+                + ", orientation=" + orientation
+                + ", logicalFrame=" + logicalFrame
+                + ", physicalFrame=" + physicalFrame
+                + ", deviceWidth=" + deviceWidth
+                + ", deviceHeight=" + deviceHeight
+                + "}";
+    }
+}
diff --git a/services/java/com/android/server/display/HeadlessDisplayAdapter.java b/services/java/com/android/server/display/HeadlessDisplayAdapter.java
new file mode 100644
index 0000000..7a104d7
--- /dev/null
+++ b/services/java/com/android/server/display/HeadlessDisplayAdapter.java
@@ -0,0 +1,73 @@
+/*
+ * 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.display;
+
+import android.content.Context;
+import android.os.Handler;
+import android.util.DisplayMetrics;
+import android.view.Display;
+
+/**
+ * Provides a fake default display for headless systems.
+ * <p>
+ * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
+ * </p>
+ */
+final class HeadlessDisplayAdapter extends DisplayAdapter {
+    private static final String TAG = "HeadlessDisplayAdapter";
+
+    // Called with SyncRoot lock held.
+    public HeadlessDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
+            Context context, Handler handler, Listener listener) {
+        super(syncRoot, context, handler, listener, TAG);
+    }
+
+    @Override
+    public void registerLocked() {
+        super.registerLocked();
+        sendDisplayDeviceEventLocked(new HeadlessDisplayDevice(), DISPLAY_DEVICE_EVENT_ADDED);
+    }
+
+    private final class HeadlessDisplayDevice extends DisplayDevice {
+        private DisplayDeviceInfo mInfo;
+
+        public HeadlessDisplayDevice() {
+            super(HeadlessDisplayAdapter.this, null);
+        }
+
+        @Override
+        public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
+            if (mInfo == null) {
+                mInfo = new DisplayDeviceInfo();
+                mInfo.name = getContext().getResources().getString(
+                        com.android.internal.R.string.display_manager_built_in_display_name);
+                mInfo.width = 640;
+                mInfo.height = 480;
+                mInfo.refreshRate = 60;
+                mInfo.densityDpi = DisplayMetrics.DENSITY_DEFAULT;
+                mInfo.xDpi = 160;
+                mInfo.yDpi = 160;
+                mInfo.flags = DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
+                        | DisplayDeviceInfo.FLAG_SECURE
+                        | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
+                mInfo.type = Display.TYPE_BUILT_IN;
+                mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
+            }
+            return mInfo;
+        }
+    }
+}
diff --git a/services/java/com/android/server/display/LocalDisplayAdapter.java b/services/java/com/android/server/display/LocalDisplayAdapter.java
new file mode 100644
index 0000000..b37d57f
--- /dev/null
+++ b/services/java/com/android/server/display/LocalDisplayAdapter.java
@@ -0,0 +1,198 @@
+/*
+ * 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.display;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.SystemProperties;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.DisplayEventReceiver;
+import android.view.Surface;
+import android.view.Surface.PhysicalDisplayInfo;
+
+import java.io.PrintWriter;
+
+/**
+ * A display adapter for the local displays managed by Surface Flinger.
+ * <p>
+ * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
+ * </p>
+ */
+final class LocalDisplayAdapter extends DisplayAdapter {
+    private static final String TAG = "LocalDisplayAdapter";
+
+    private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] {
+            Surface.BUILT_IN_DISPLAY_ID_MAIN,
+            Surface.BUILT_IN_DISPLAY_ID_HDMI,
+    };
+
+    private final SparseArray<LocalDisplayDevice> mDevices =
+            new SparseArray<LocalDisplayDevice>();
+    private HotplugDisplayEventReceiver mHotplugReceiver;
+
+    private final PhysicalDisplayInfo mTempPhys = new PhysicalDisplayInfo();
+
+    // Called with SyncRoot lock held.
+    public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
+            Context context, Handler handler, Listener listener) {
+        super(syncRoot, context, handler, listener, TAG);
+    }
+
+    @Override
+    public void registerLocked() {
+        super.registerLocked();
+
+        mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
+        scanDisplaysLocked();
+    }
+
+    private void scanDisplaysLocked() {
+        for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
+            IBinder displayToken = Surface.getBuiltInDisplay(builtInDisplayId);
+            if (displayToken != null && Surface.getDisplayInfo(displayToken, mTempPhys)) {
+                LocalDisplayDevice device = mDevices.get(builtInDisplayId);
+                if (device == null) {
+                    // Display was added.
+                    device = new LocalDisplayDevice(displayToken, builtInDisplayId, mTempPhys);
+                    mDevices.put(builtInDisplayId, device);
+                    sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
+                } else if (device.updatePhysicalDisplayInfoLocked(mTempPhys)) {
+                    // Display properties changed.
+                    sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
+                }
+            } else {
+                LocalDisplayDevice device = mDevices.get(builtInDisplayId);
+                if (device != null) {
+                    // Display was removed.
+                    mDevices.remove(builtInDisplayId);
+                    sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
+                }
+            }
+        }
+    }
+
+    private final class LocalDisplayDevice extends DisplayDevice {
+        private final int mBuiltInDisplayId;
+        private final PhysicalDisplayInfo mPhys;
+
+        private DisplayDeviceInfo mInfo;
+        private boolean mHavePendingChanges;
+        private boolean mBlanked;
+
+        public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
+                PhysicalDisplayInfo phys) {
+            super(LocalDisplayAdapter.this, displayToken);
+            mBuiltInDisplayId = builtInDisplayId;
+            mPhys = new PhysicalDisplayInfo(phys);
+        }
+
+        public boolean updatePhysicalDisplayInfoLocked(PhysicalDisplayInfo phys) {
+            if (!mPhys.equals(phys)) {
+                mPhys.copyFrom(phys);
+                mHavePendingChanges = true;
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public void applyPendingDisplayDeviceInfoChangesLocked() {
+            if (mHavePendingChanges) {
+                mInfo = null;
+                mHavePendingChanges = false;
+            }
+        }
+
+        @Override
+        public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
+            if (mInfo == null) {
+                mInfo = new DisplayDeviceInfo();
+                mInfo.width = mPhys.width;
+                mInfo.height = mPhys.height;
+                mInfo.refreshRate = mPhys.refreshRate;
+
+                // Assume that all built-in displays that have secure output (eg. HDCP) also
+                // support compositing from gralloc protected buffers.
+                if (mPhys.secure) {
+                    mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
+                            | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
+                }
+
+                if (mBuiltInDisplayId == Surface.BUILT_IN_DISPLAY_ID_MAIN) {
+                    mInfo.name = getContext().getResources().getString(
+                            com.android.internal.R.string.display_manager_built_in_display_name);
+                    mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
+                            | DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
+                    mInfo.type = Display.TYPE_BUILT_IN;
+                    mInfo.densityDpi = (int)(mPhys.density * 160 + 0.5f);
+                    mInfo.xDpi = mPhys.xDpi;
+                    mInfo.yDpi = mPhys.yDpi;
+                    mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
+                } else {
+                    mInfo.type = Display.TYPE_HDMI;
+                    mInfo.name = getContext().getResources().getString(
+                            com.android.internal.R.string.display_manager_hdmi_display_name);
+                    mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
+                    mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height);
+
+                    // For demonstration purposes, allow rotation of the external display.
+                    // In the future we might allow the user to configure this directly.
+                    if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
+                        mInfo.rotation = Surface.ROTATION_270;
+                    }
+                }
+            }
+            return mInfo;
+        }
+
+        @Override
+        public void blankLocked() {
+            mBlanked = true;
+            Surface.blankDisplay(getDisplayTokenLocked());
+        }
+
+        @Override
+        public void unblankLocked() {
+            mBlanked = false;
+            Surface.unblankDisplay(getDisplayTokenLocked());
+        }
+
+        @Override
+        public void dumpLocked(PrintWriter pw) {
+            super.dumpLocked(pw);
+            pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
+            pw.println("mPhys=" + mPhys);
+            pw.println("mBlanked=" + mBlanked);
+        }
+    }
+
+    private final class HotplugDisplayEventReceiver extends DisplayEventReceiver {
+        public HotplugDisplayEventReceiver(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
+            synchronized (getSyncRoot()) {
+                scanDisplaysLocked();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/display/LogicalDisplay.java b/services/java/com/android/server/display/LogicalDisplay.java
new file mode 100644
index 0000000..1583137
--- /dev/null
+++ b/services/java/com/android/server/display/LogicalDisplay.java
@@ -0,0 +1,324 @@
+/*
+ * 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.display;
+
+import android.graphics.Rect;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.Surface;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+import libcore.util.Objects;
+
+/**
+ * Describes how a logical display is configured.
+ * <p>
+ * At this time, we only support logical displays that are coupled to a particular
+ * primary display device from which the logical display derives its basic properties
+ * such as its size, density and refresh rate.
+ * </p><p>
+ * A logical display may be mirrored onto multiple display devices in addition to its
+ * primary display device.  Note that the contents of a logical display may not
+ * always be visible, even on its primary display device, such as in the case where
+ * the primary display device is currently mirroring content from a different
+ * logical display.
+ * </p><p>
+ * This object is designed to encapsulate as much of the policy of logical
+ * displays as possible.  The idea is to make it easy to implement new kinds of
+ * logical displays mostly by making local changes to this class.
+ * </p><p>
+ * Note: The display manager architecture does not actually require logical displays
+ * to be associated with any individual display device.  Logical displays and
+ * display devices are orthogonal concepts.  Some mapping will exist between
+ * logical displays and display devices but it can be many-to-many and
+ * and some might have no relation at all.
+ * </p><p>
+ * Logical displays are guarded by the {@link DisplayManagerService.SyncRoot} lock.
+ * </p>
+ */
+final class LogicalDisplay {
+    private final DisplayInfo mBaseDisplayInfo = new DisplayInfo();
+
+    // The layer stack we use when the display has been blanked to prevent any
+    // of its content from appearing.
+    private static final int BLANK_LAYER_STACK = -1;
+
+    private final int mDisplayId;
+    private final int mLayerStack;
+    private DisplayInfo mOverrideDisplayInfo; // set by the window manager
+    private DisplayInfo mInfo;
+
+    // The display device that this logical display is based on and which
+    // determines the base metrics that it uses.
+    private DisplayDevice mPrimaryDisplayDevice;
+    private DisplayDeviceInfo mPrimaryDisplayDeviceInfo;
+
+    // True if the logical display has unique content.
+    private boolean mHasContent;
+
+    // Temporary rectangle used when needed.
+    private final Rect mTempLayerStackRect = new Rect();
+    private final Rect mTempDisplayRect = new Rect();
+
+    public LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice) {
+        mDisplayId = displayId;
+        mLayerStack = layerStack;
+        mPrimaryDisplayDevice = primaryDisplayDevice;
+    }
+
+    /**
+     * Gets the logical display id of this logical display.
+     *
+     * @return The logical display id.
+     */
+    public int getDisplayIdLocked() {
+        return mDisplayId;
+    }
+
+    /**
+     * Gets the primary display device associated with this logical display.
+     *
+     * @return The primary display device.
+     */
+    public DisplayDevice getPrimaryDisplayDeviceLocked() {
+        return mPrimaryDisplayDevice;
+    }
+
+    /**
+     * Gets information about the logical display.
+     *
+     * @return The device info, which should be treated as immutable by the caller.
+     * The logical display should allocate a new display info object whenever
+     * the data changes.
+     */
+    public DisplayInfo getDisplayInfoLocked() {
+        if (mInfo == null) {
+            mInfo = new DisplayInfo();
+            if (mOverrideDisplayInfo != null) {
+                mInfo.copyFrom(mOverrideDisplayInfo);
+                mInfo.layerStack = mBaseDisplayInfo.layerStack;
+                mInfo.name = mBaseDisplayInfo.name;
+            } else {
+                mInfo.copyFrom(mBaseDisplayInfo);
+            }
+        }
+        return mInfo;
+    }
+
+    /**
+     * Sets overridden logical display information from the window manager.
+     * This method can be used to adjust application insets, rotation, and other
+     * properties that the window manager takes care of.
+     *
+     * @param info The logical display information, may be null.
+     */
+    public void setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo info) {
+        if (info != null) {
+            if (mOverrideDisplayInfo == null) {
+                mOverrideDisplayInfo = new DisplayInfo(info);
+                mInfo = null;
+            } else if (!mOverrideDisplayInfo.equals(info)) {
+                mOverrideDisplayInfo.copyFrom(info);
+                mInfo = null;
+            }
+        } else if (mOverrideDisplayInfo != null) {
+            mOverrideDisplayInfo = null;
+            mInfo = null;
+        }
+    }
+
+    /**
+     * Returns true if the logical display is in a valid state.
+     * This method should be checked after calling {@link #updateLocked} to handle the
+     * case where a logical display should be removed because all of its associated
+     * display devices are gone or if it is otherwise no longer needed.
+     *
+     * @return True if the logical display is still valid.
+     */
+    public boolean isValidLocked() {
+        return mPrimaryDisplayDevice != null;
+    }
+
+    /**
+     * Updates the state of the logical display based on the available display devices.
+     * The logical display might become invalid if it is attached to a display device
+     * that no longer exists.
+     *
+     * @param devices The list of all connected display devices.
+     */
+    public void updateLocked(List<DisplayDevice> devices) {
+        // Nothing to update if already invalid.
+        if (mPrimaryDisplayDevice == null) {
+            return;
+        }
+
+        // Check whether logical display has become invalid.
+        if (!devices.contains(mPrimaryDisplayDevice)) {
+            mPrimaryDisplayDevice = null;
+            return;
+        }
+
+        // Bootstrap the logical display using its associated primary physical display.
+        // We might use more elaborate configurations later.  It's possible that the
+        // configuration of several physical displays might be used to determine the
+        // logical display that they are sharing.  (eg. Adjust size for pixel-perfect
+        // mirroring over HDMI.)
+        DisplayDeviceInfo deviceInfo = mPrimaryDisplayDevice.getDisplayDeviceInfoLocked();
+        if (!Objects.equal(mPrimaryDisplayDeviceInfo, deviceInfo)) {
+            mBaseDisplayInfo.layerStack = mLayerStack;
+            mBaseDisplayInfo.flags = 0;
+            if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
+                mBaseDisplayInfo.flags |= Display.FLAG_SUPPORTS_PROTECTED_BUFFERS;
+            }
+            if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SECURE) != 0) {
+                mBaseDisplayInfo.flags |= Display.FLAG_SECURE;
+            }
+            mBaseDisplayInfo.type = deviceInfo.type;
+            mBaseDisplayInfo.address = deviceInfo.address;
+            mBaseDisplayInfo.name = deviceInfo.name;
+            mBaseDisplayInfo.appWidth = deviceInfo.width;
+            mBaseDisplayInfo.appHeight = deviceInfo.height;
+            mBaseDisplayInfo.logicalWidth = deviceInfo.width;
+            mBaseDisplayInfo.logicalHeight = deviceInfo.height;
+            mBaseDisplayInfo.rotation = Surface.ROTATION_0;
+            mBaseDisplayInfo.refreshRate = deviceInfo.refreshRate;
+            mBaseDisplayInfo.logicalDensityDpi = deviceInfo.densityDpi;
+            mBaseDisplayInfo.physicalXDpi = deviceInfo.xDpi;
+            mBaseDisplayInfo.physicalYDpi = deviceInfo.yDpi;
+            mBaseDisplayInfo.smallestNominalAppWidth = deviceInfo.width;
+            mBaseDisplayInfo.smallestNominalAppHeight = deviceInfo.height;
+            mBaseDisplayInfo.largestNominalAppWidth = deviceInfo.width;
+            mBaseDisplayInfo.largestNominalAppHeight = deviceInfo.height;
+
+            mPrimaryDisplayDeviceInfo = deviceInfo;
+            mInfo = null;
+        }
+    }
+
+    /**
+     * Applies the layer stack and transformation to the given display device
+     * so that it shows the contents of this logical display.
+     *
+     * We know that the given display device is only ever showing the contents of
+     * a single logical display, so this method is expected to blow away all of its
+     * transformation properties to make it happen regardless of what the
+     * display device was previously showing.
+     *
+     * The caller must have an open Surface transaction.
+     *
+     * The display device may not be the primary display device, in the case
+     * where the display is being mirrored.
+     *
+     * @param device The display device to modify.
+     * @param isBlanked True if the device is being blanked.
+     */
+    public void configureDisplayInTransactionLocked(DisplayDevice device,
+            boolean isBlanked) {
+        final DisplayInfo displayInfo = getDisplayInfoLocked();
+        final DisplayDeviceInfo displayDeviceInfo = device.getDisplayDeviceInfoLocked();
+
+        // Set the layer stack.
+        device.setLayerStackInTransactionLocked(isBlanked ? BLANK_LAYER_STACK : mLayerStack);
+
+        // Set the viewport.
+        // This is the area of the logical display that we intend to show on the
+        // display device.  For now, it is always the full size of the logical display.
+        mTempLayerStackRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
+
+        // Set the orientation.
+        // The orientation specifies how the physical coordinate system of the display
+        // is rotated when the contents of the logical display are rendered.
+        int orientation = Surface.ROTATION_0;
+        if (device == mPrimaryDisplayDevice
+                && (displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0) {
+            orientation = displayInfo.rotation;
+        }
+
+        // Apply the physical rotation of the display device itself.
+        orientation = (orientation + displayDeviceInfo.rotation) % 4;
+
+        // Set the frame.
+        // The frame specifies the rotated physical coordinates into which the viewport
+        // is mapped.  We need to take care to preserve the aspect ratio of the viewport.
+        // Currently we maximize the area to fill the display, but we could try to be
+        // more clever and match resolutions.
+        boolean rotated = (orientation == Surface.ROTATION_90
+                || orientation == Surface.ROTATION_270);
+        int physWidth = rotated ? displayDeviceInfo.height : displayDeviceInfo.width;
+        int physHeight = rotated ? displayDeviceInfo.width : displayDeviceInfo.height;
+
+        // Determine whether the width or height is more constrained to be scaled.
+        //    physWidth / displayInfo.logicalWidth    => letter box
+        // or physHeight / displayInfo.logicalHeight  => pillar box
+        //
+        // We avoid a division (and possible floating point imprecision) here by
+        // multiplying the fractions by the product of their denominators before
+        // comparing them.
+        int displayRectWidth, displayRectHeight;
+        if (physWidth * displayInfo.logicalHeight
+                < physHeight * displayInfo.logicalWidth) {
+            // Letter box.
+            displayRectWidth = physWidth;
+            displayRectHeight = displayInfo.logicalHeight * physWidth / displayInfo.logicalWidth;
+        } else {
+            // Pillar box.
+            displayRectWidth = displayInfo.logicalWidth * physHeight / displayInfo.logicalHeight;
+            displayRectHeight = physHeight;
+        }
+        int displayRectTop = (physHeight - displayRectHeight) / 2;
+        int displayRectLeft = (physWidth - displayRectWidth) / 2;
+        mTempDisplayRect.set(displayRectLeft, displayRectTop,
+                displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight);
+
+        device.setProjectionInTransactionLocked(orientation, mTempLayerStackRect, mTempDisplayRect);
+    }
+
+    /**
+     * Returns true if the logical display has unique content.
+     * <p>
+     * If the display has unique content then we will try to ensure that it is
+     * visible on at least its primary display device.  Otherwise we will ignore the
+     * logical display and perhaps show mirrored content on the primary display device.
+     * </p>
+     *
+     * @return True if the display has unique content.
+     */
+    public boolean hasContentLocked() {
+        return mHasContent;
+    }
+
+    /**
+     * Sets whether the logical display has unique content.
+     *
+     * @param hasContent True if the display has unique content.
+     */
+    public void setHasContentLocked(boolean hasContent) {
+        mHasContent = hasContent;
+    }
+
+    public void dumpLocked(PrintWriter pw) {
+        pw.println("mDisplayId=" + mDisplayId);
+        pw.println("mLayerStack=" + mLayerStack);
+        pw.println("mHasContent=" + mHasContent);
+        pw.println("mPrimaryDisplayDevice=" + (mPrimaryDisplayDevice != null ?
+                mPrimaryDisplayDevice.getNameLocked() : "null"));
+        pw.println("mBaseDisplayInfo=" + mBaseDisplayInfo);
+        pw.println("mOverrideDisplayInfo=" + mOverrideDisplayInfo);
+    }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/display/OverlayDisplayAdapter.java b/services/java/com/android/server/display/OverlayDisplayAdapter.java
new file mode 100644
index 0000000..36e9f74
--- /dev/null
+++ b/services/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -0,0 +1,352 @@
+/*
+ * 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.display;
+
+import com.android.internal.util.DumpUtils;
+import com.android.internal.util.IndentingPrintWriter;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.graphics.SurfaceTexture;
+import android.os.Handler;
+import android.os.IBinder;
+import android.provider.Settings;
+import android.util.DisplayMetrics;
+import android.util.Slog;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.Surface;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A display adapter that uses overlay windows to simulate secondary displays
+ * for development purposes.  Use Development Settings to enable one or more
+ * overlay displays.
+ * <p>
+ * This object has two different handlers (which may be the same) which must not
+ * get confused.  The main handler is used to posting messages to the display manager
+ * service as usual.  The UI handler is only used by the {@link OverlayDisplayWindow}.
+ * </p><p>
+ * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
+ * </p>
+ */
+final class OverlayDisplayAdapter extends DisplayAdapter {
+    static final String TAG = "OverlayDisplayAdapter";
+    static final boolean DEBUG = false;
+
+    private static final int MIN_WIDTH = 100;
+    private static final int MIN_HEIGHT = 100;
+    private static final int MAX_WIDTH = 4096;
+    private static final int MAX_HEIGHT = 4096;
+
+    private static final Pattern SETTING_PATTERN =
+            Pattern.compile("(\\d+)x(\\d+)/(\\d+)");
+
+    private final Handler mUiHandler;
+    private final ArrayList<OverlayDisplayHandle> mOverlays =
+            new ArrayList<OverlayDisplayHandle>();
+    private String mCurrentOverlaySetting = "";
+
+    // Called with SyncRoot lock held.
+    public OverlayDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
+            Context context, Handler handler, Listener listener, Handler uiHandler) {
+        super(syncRoot, context, handler, listener, TAG);
+        mUiHandler = uiHandler;
+    }
+
+    @Override
+    public void dumpLocked(PrintWriter pw) {
+        super.dumpLocked(pw);
+
+        pw.println("mCurrentOverlaySetting=" + mCurrentOverlaySetting);
+        pw.println("mOverlays: size=" + mOverlays.size());
+        for (OverlayDisplayHandle overlay : mOverlays) {
+            overlay.dumpLocked(pw);
+        }
+    }
+
+    @Override
+    public void registerLocked() {
+        super.registerLocked();
+
+        getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                getContext().getContentResolver().registerContentObserver(
+                        Settings.Global.getUriFor(Settings.Global.OVERLAY_DISPLAY_DEVICES),
+                        true, new ContentObserver(getHandler()) {
+                            @Override
+                            public void onChange(boolean selfChange) {
+                                updateOverlayDisplayDevices();
+                            }
+                        });
+
+                updateOverlayDisplayDevices();
+            }
+        });
+    }
+
+    private void updateOverlayDisplayDevices() {
+        synchronized (getSyncRoot()) {
+            updateOverlayDisplayDevicesLocked();
+        }
+    }
+
+    private void updateOverlayDisplayDevicesLocked() {
+        String value = Settings.Global.getString(getContext().getContentResolver(),
+                Settings.Global.OVERLAY_DISPLAY_DEVICES);
+        if (value == null) {
+            value = "";
+        }
+
+        if (value.equals(mCurrentOverlaySetting)) {
+            return;
+        }
+        mCurrentOverlaySetting = value;
+
+        if (!mOverlays.isEmpty()) {
+            Slog.i(TAG, "Dismissing all overlay display devices.");
+            for (OverlayDisplayHandle overlay : mOverlays) {
+                overlay.dismissLocked();
+            }
+            mOverlays.clear();
+        }
+
+        int count = 0;
+        for (String part : value.split(";")) {
+            Matcher matcher = SETTING_PATTERN.matcher(part);
+            if (matcher.matches()) {
+                if (count >= 4) {
+                    Slog.w(TAG, "Too many overlay display devices specified: " + value);
+                    break;
+                }
+                try {
+                    int width = Integer.parseInt(matcher.group(1), 10);
+                    int height = Integer.parseInt(matcher.group(2), 10);
+                    int densityDpi = Integer.parseInt(matcher.group(3), 10);
+                    if (width >= MIN_WIDTH && width <= MAX_WIDTH
+                            && height >= MIN_HEIGHT && height <= MAX_HEIGHT
+                            && densityDpi >= DisplayMetrics.DENSITY_LOW
+                            && densityDpi <= DisplayMetrics.DENSITY_XXHIGH) {
+                        int number = ++count;
+                        String name = getContext().getResources().getString(
+                                com.android.internal.R.string.display_manager_overlay_display_name,
+                                number);
+                        int gravity = chooseOverlayGravity(number);
+
+                        Slog.i(TAG, "Showing overlay display device #" + number
+                                + ": name=" + name + ", width=" + width + ", height=" + height
+                                + ", densityDpi=" + densityDpi);
+
+                        mOverlays.add(new OverlayDisplayHandle(name,
+                                width, height, densityDpi, gravity));
+                        continue;
+                    }
+                } catch (NumberFormatException ex) {
+                }
+            } else if (part.isEmpty()) {
+                continue;
+            }
+            Slog.w(TAG, "Malformed overlay display devices setting: " + value);
+        }
+    }
+
+    private static int chooseOverlayGravity(int overlayNumber) {
+        switch (overlayNumber) {
+            case 1:
+                return Gravity.TOP | Gravity.LEFT;
+            case 2:
+                return Gravity.BOTTOM | Gravity.RIGHT;
+            case 3:
+                return Gravity.TOP | Gravity.RIGHT;
+            case 4:
+            default:
+                return Gravity.BOTTOM | Gravity.LEFT;
+        }
+    }
+
+    private final class OverlayDisplayDevice extends DisplayDevice {
+        private final String mName;
+        private final int mWidth;
+        private final int mHeight;
+        private final float mRefreshRate;
+        private final int mDensityDpi;
+
+        private Surface mSurface;
+        private SurfaceTexture mSurfaceTexture;
+        private DisplayDeviceInfo mInfo;
+
+        public OverlayDisplayDevice(IBinder displayToken, String name,
+                int width, int height, float refreshRate, int densityDpi,
+                SurfaceTexture surfaceTexture) {
+            super(OverlayDisplayAdapter.this, displayToken);
+            mName = name;
+            mWidth = width;
+            mHeight = height;
+            mRefreshRate = refreshRate;
+            mDensityDpi = densityDpi;
+            mSurfaceTexture = surfaceTexture;
+        }
+
+        public void clearSurfaceTextureLocked() {
+            if (mSurfaceTexture != null) {
+                mSurfaceTexture = null;
+            }
+            sendTraversalRequestLocked();
+        }
+
+        @Override
+        public void performTraversalInTransactionLocked() {
+            if (mSurfaceTexture != null) {
+                if (mSurface == null) {
+                    mSurface = new Surface(mSurfaceTexture);
+                }
+                setSurfaceInTransactionLocked(mSurface);
+            } else {
+                setSurfaceInTransactionLocked(null);
+                if (mSurface != null) {
+                    mSurface.destroy();
+                    mSurface = null;
+                }
+            }
+        }
+
+        @Override
+        public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
+            if (mInfo == null) {
+                mInfo = new DisplayDeviceInfo();
+                mInfo.name = mName;
+                mInfo.width = mWidth;
+                mInfo.height = mHeight;
+                mInfo.refreshRate = mRefreshRate;
+                mInfo.densityDpi = mDensityDpi;
+                mInfo.xDpi = mDensityDpi;
+                mInfo.yDpi = mDensityDpi;
+                mInfo.flags = 0;
+                mInfo.type = Display.TYPE_OVERLAY;
+                mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
+            }
+            return mInfo;
+        }
+    }
+
+    /**
+     * Functions as a handle for overlay display devices which are created and
+     * destroyed asynchronously.
+     *
+     * Guarded by the {@link DisplayManagerService.SyncRoot} lock.
+     */
+    private final class OverlayDisplayHandle implements OverlayDisplayWindow.Listener {
+        private final String mName;
+        private final int mWidth;
+        private final int mHeight;
+        private final int mDensityDpi;
+        private final int mGravity;
+
+        private OverlayDisplayWindow mWindow;
+        private OverlayDisplayDevice mDevice;
+
+        public OverlayDisplayHandle(String name,
+                int width, int height, int densityDpi, int gravity) {
+            mName = name;
+            mWidth = width;
+            mHeight = height;
+            mDensityDpi = densityDpi;
+            mGravity = gravity;
+
+            mUiHandler.post(mShowRunnable);
+        }
+
+        public void dismissLocked() {
+            mUiHandler.removeCallbacks(mShowRunnable);
+            mUiHandler.post(mDismissRunnable);
+        }
+
+        // Called on the UI thread.
+        @Override
+        public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate) {
+            synchronized (getSyncRoot()) {
+                IBinder displayToken = Surface.createDisplay(mName, false);
+                mDevice = new OverlayDisplayDevice(displayToken, mName,
+                        mWidth, mHeight, refreshRate, mDensityDpi, surfaceTexture);
+
+                sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_ADDED);
+            }
+        }
+
+        // Called on the UI thread.
+        @Override
+        public void onWindowDestroyed() {
+            synchronized (getSyncRoot()) {
+                if (mDevice != null) {
+                    mDevice.clearSurfaceTextureLocked();
+                    sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_REMOVED);
+                }
+            }
+        }
+
+        public void dumpLocked(PrintWriter pw) {
+            pw.println("  " + mName + ":");
+            pw.println("    mWidth=" + mWidth);
+            pw.println("    mHeight=" + mHeight);
+            pw.println("    mDensityDpi=" + mDensityDpi);
+            pw.println("    mGravity=" + mGravity);
+
+            // Try to dump the window state.
+            if (mWindow != null) {
+                final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
+                ipw.increaseIndent();
+                DumpUtils.dumpAsync(mUiHandler, mWindow, ipw, 200);
+            }
+        }
+
+        // Runs on the UI thread.
+        private final Runnable mShowRunnable = new Runnable() {
+            @Override
+            public void run() {
+                OverlayDisplayWindow window = new OverlayDisplayWindow(getContext(),
+                        mName, mWidth, mHeight, mDensityDpi, mGravity,
+                        OverlayDisplayHandle.this);
+                window.show();
+
+                synchronized (getSyncRoot()) {
+                    mWindow = window;
+                }
+            }
+        };
+
+        // Runs on the UI thread.
+        private final Runnable mDismissRunnable = new Runnable() {
+            @Override
+            public void run() {
+                OverlayDisplayWindow window;
+                synchronized (getSyncRoot()) {
+                    window = mWindow;
+                    mWindow = null;
+                }
+
+                if (window != null) {
+                    window.dismiss();
+                }
+            }
+        };
+    }
+}
diff --git a/services/java/com/android/server/display/OverlayDisplayWindow.java b/services/java/com/android/server/display/OverlayDisplayWindow.java
new file mode 100644
index 0000000..a0edced
--- /dev/null
+++ b/services/java/com/android/server/display/OverlayDisplayWindow.java
@@ -0,0 +1,366 @@
+/*
+ * 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.display;
+
+import com.android.internal.util.DumpUtils;
+
+import android.content.Context;
+import android.graphics.SurfaceTexture;
+import android.hardware.display.DisplayManager;
+import android.util.Slog;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.GestureDetector;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+import android.view.TextureView;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.TextureView.SurfaceTextureListener;
+import android.widget.TextView;
+
+import java.io.PrintWriter;
+
+/**
+ * Manages an overlay window on behalf of {@link OverlayDisplayAdapter}.
+ * <p>
+ * This object must only be accessed on the UI thread.
+ * No locks are held by this object and locks must not be held while making called into it.
+ * </p>
+ */
+final class OverlayDisplayWindow implements DumpUtils.Dump {
+    private static final String TAG = "OverlayDisplayWindow";
+    private static final boolean DEBUG = false;
+
+    private final float INITIAL_SCALE = 0.5f;
+    private final float MIN_SCALE = 0.3f;
+    private final float MAX_SCALE = 1.0f;
+    private final float WINDOW_ALPHA = 0.8f;
+
+    // When true, disables support for moving and resizing the overlay.
+    // The window is made non-touchable, which makes it possible to
+    // directly interact with the content underneath.
+    private final boolean DISABLE_MOVE_AND_RESIZE = false;
+
+    private final Context mContext;
+    private final String mName;
+    private final int mWidth;
+    private final int mHeight;
+    private final int mDensityDpi;
+    private final int mGravity;
+    private final Listener mListener;
+    private final String mTitle;
+
+    private final DisplayManager mDisplayManager;
+    private final WindowManager mWindowManager;
+
+
+    private final Display mDefaultDisplay;
+    private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo();
+
+    private View mWindowContent;
+    private WindowManager.LayoutParams mWindowParams;
+    private TextureView mTextureView;
+    private TextView mTitleTextView;
+
+    private GestureDetector mGestureDetector;
+    private ScaleGestureDetector mScaleGestureDetector;
+
+    private boolean mWindowVisible;
+    private int mWindowX;
+    private int mWindowY;
+    private float mWindowScale;
+
+    private float mLiveTranslationX;
+    private float mLiveTranslationY;
+    private float mLiveScale = 1.0f;
+
+    public OverlayDisplayWindow(Context context, String name,
+            int width, int height, int densityDpi, int gravity, Listener listener) {
+        mContext = context;
+        mName = name;
+        mWidth = width;
+        mHeight = height;
+        mDensityDpi = densityDpi;
+        mGravity = gravity;
+        mListener = listener;
+        mTitle = context.getResources().getString(
+                com.android.internal.R.string.display_manager_overlay_display_title,
+                mName, mWidth, mHeight, mDensityDpi);
+
+        mDisplayManager = (DisplayManager)context.getSystemService(
+                Context.DISPLAY_SERVICE);
+        mWindowManager = (WindowManager)context.getSystemService(
+                Context.WINDOW_SERVICE);
+
+        mDefaultDisplay = mWindowManager.getDefaultDisplay();
+        updateDefaultDisplayInfo();
+
+        createWindow();
+    }
+
+    public void show() {
+        if (!mWindowVisible) {
+            mDisplayManager.registerDisplayListener(mDisplayListener, null);
+            if (!updateDefaultDisplayInfo()) {
+                mDisplayManager.unregisterDisplayListener(mDisplayListener);
+                return;
+            }
+
+            clearLiveState();
+            updateWindowParams();
+            mWindowManager.addView(mWindowContent, mWindowParams);
+            mWindowVisible = true;
+        }
+    }
+
+    public void dismiss() {
+        if (mWindowVisible) {
+            mDisplayManager.unregisterDisplayListener(mDisplayListener);
+            mWindowManager.removeView(mWindowContent);
+            mWindowVisible = false;
+        }
+    }
+
+    public void relayout() {
+        if (mWindowVisible) {
+            updateWindowParams();
+            mWindowManager.updateViewLayout(mWindowContent, mWindowParams);
+        }
+    }
+
+    @Override
+    public void dump(PrintWriter pw) {
+        pw.println("mWindowVisible=" + mWindowVisible);
+        pw.println("mWindowX=" + mWindowX);
+        pw.println("mWindowY=" + mWindowY);
+        pw.println("mWindowScale=" + mWindowScale);
+        pw.println("mWindowParams=" + mWindowParams);
+        if (mTextureView != null) {
+            pw.println("mTextureView.getScaleX()=" + mTextureView.getScaleX());
+            pw.println("mTextureView.getScaleY()=" + mTextureView.getScaleY());
+        }
+        pw.println("mLiveTranslationX=" + mLiveTranslationX);
+        pw.println("mLiveTranslationY=" + mLiveTranslationY);
+        pw.println("mLiveScale=" + mLiveScale);
+    }
+
+    private boolean updateDefaultDisplayInfo() {
+        if (!mDefaultDisplay.getDisplayInfo(mDefaultDisplayInfo)) {
+            Slog.w(TAG, "Cannot show overlay display because there is no "
+                    + "default display upon which to show it.");
+            return false;
+        }
+        return true;
+    }
+
+    private void createWindow() {
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+
+        mWindowContent = inflater.inflate(
+                com.android.internal.R.layout.overlay_display_window, null);
+        mWindowContent.setOnTouchListener(mOnTouchListener);
+
+        mTextureView = (TextureView)mWindowContent.findViewById(
+                com.android.internal.R.id.overlay_display_window_texture);
+        mTextureView.setPivotX(0);
+        mTextureView.setPivotY(0);
+        mTextureView.getLayoutParams().width = mWidth;
+        mTextureView.getLayoutParams().height = mHeight;
+        mTextureView.setOpaque(false);
+        mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
+
+        mTitleTextView = (TextView)mWindowContent.findViewById(
+                com.android.internal.R.id.overlay_display_window_title);
+        mTitleTextView.setText(mTitle);
+
+        mWindowParams = new WindowManager.LayoutParams(
+                WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY);
+        mWindowParams.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
+                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+        if (DISABLE_MOVE_AND_RESIZE) {
+            mWindowParams.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+        }
+        mWindowParams.privateFlags |=
+                WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
+        mWindowParams.alpha = WINDOW_ALPHA;
+        mWindowParams.gravity = Gravity.TOP | Gravity.LEFT;
+        mWindowParams.setTitle(mTitle);
+
+        mGestureDetector = new GestureDetector(mContext, mOnGestureListener);
+        mScaleGestureDetector = new ScaleGestureDetector(mContext, mOnScaleGestureListener);
+
+        // Set the initial position and scale.
+        // The position and scale will be clamped when the display is first shown.
+        mWindowX = (mGravity & Gravity.LEFT) == Gravity.LEFT ?
+                0 : mDefaultDisplayInfo.logicalWidth;
+        mWindowY = (mGravity & Gravity.TOP) == Gravity.TOP ?
+                0 : mDefaultDisplayInfo.logicalHeight;
+        mWindowScale = INITIAL_SCALE;
+    }
+
+    private void updateWindowParams() {
+        float scale = mWindowScale * mLiveScale;
+        scale = Math.min(scale, (float)mDefaultDisplayInfo.logicalWidth / mWidth);
+        scale = Math.min(scale, (float)mDefaultDisplayInfo.logicalHeight / mHeight);
+        scale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, scale));
+
+        float offsetScale = (scale / mWindowScale - 1.0f) * 0.5f;
+        int width = (int)(mWidth * scale);
+        int height = (int)(mHeight * scale);
+        int x = (int)(mWindowX + mLiveTranslationX - width * offsetScale);
+        int y = (int)(mWindowY + mLiveTranslationY - height * offsetScale);
+        x = Math.max(0, Math.min(x, mDefaultDisplayInfo.logicalWidth - width));
+        y = Math.max(0, Math.min(y, mDefaultDisplayInfo.logicalHeight - height));
+
+        if (DEBUG) {
+            Slog.d(TAG, "updateWindowParams: scale=" + scale
+                    + ", offsetScale=" + offsetScale
+                    + ", x=" + x + ", y=" + y
+                    + ", width=" + width + ", height=" + height);
+        }
+
+        mTextureView.setScaleX(scale);
+        mTextureView.setScaleY(scale);
+
+        mWindowParams.x = x;
+        mWindowParams.y = y;
+        mWindowParams.width = width;
+        mWindowParams.height = height;
+    }
+
+    private void saveWindowParams() {
+        mWindowX = mWindowParams.x;
+        mWindowY = mWindowParams.y;
+        mWindowScale = mTextureView.getScaleX();
+        clearLiveState();
+    }
+
+    private void clearLiveState() {
+        mLiveTranslationX = 0f;
+        mLiveTranslationY = 0f;
+        mLiveScale = 1.0f;
+    }
+
+    private final DisplayManager.DisplayListener mDisplayListener =
+            new DisplayManager.DisplayListener() {
+        @Override
+        public void onDisplayAdded(int displayId) {
+        }
+
+        @Override
+        public void onDisplayChanged(int displayId) {
+            if (displayId == mDefaultDisplay.getDisplayId()) {
+                if (updateDefaultDisplayInfo()) {
+                    relayout();
+                } else {
+                    dismiss();
+                }
+            }
+        }
+
+        @Override
+        public void onDisplayRemoved(int displayId) {
+            if (displayId == mDefaultDisplay.getDisplayId()) {
+                dismiss();
+            }
+        }
+    };
+
+    private final SurfaceTextureListener mSurfaceTextureListener =
+            new SurfaceTextureListener() {
+        @Override
+        public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
+                int width, int height) {
+            mListener.onWindowCreated(surfaceTexture, mDefaultDisplayInfo.refreshRate);
+        }
+
+        @Override
+        public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
+            mListener.onWindowDestroyed();
+            return true;
+        }
+
+        @Override
+        public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,
+                int width, int height) {
+        }
+
+        @Override
+        public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
+        }
+    };
+
+    private final View.OnTouchListener mOnTouchListener = new View.OnTouchListener() {
+        @Override
+        public boolean onTouch(View view, MotionEvent event) {
+            // Work in screen coordinates.
+            final float oldX = event.getX();
+            final float oldY = event.getY();
+            event.setLocation(event.getRawX(), event.getRawY());
+
+            mGestureDetector.onTouchEvent(event);
+            mScaleGestureDetector.onTouchEvent(event);
+
+            switch (event.getActionMasked()) {
+                case MotionEvent.ACTION_UP:
+                case MotionEvent.ACTION_CANCEL:
+                    saveWindowParams();
+                    break;
+            }
+
+            // Revert to window coordinates.
+            event.setLocation(oldX, oldY);
+            return true;
+        }
+    };
+
+    private final GestureDetector.OnGestureListener mOnGestureListener =
+            new GestureDetector.SimpleOnGestureListener() {
+        @Override
+        public boolean onScroll(MotionEvent e1, MotionEvent e2,
+                float distanceX, float distanceY) {
+            mLiveTranslationX -= distanceX;
+            mLiveTranslationY -= distanceY;
+            relayout();
+            return true;
+        }
+    };
+
+    private final ScaleGestureDetector.OnScaleGestureListener mOnScaleGestureListener =
+            new ScaleGestureDetector.SimpleOnScaleGestureListener() {
+        @Override
+        public boolean onScale(ScaleGestureDetector detector) {
+            mLiveScale *= detector.getScaleFactor();
+            relayout();
+            return true;
+        }
+    };
+
+    /**
+     * Watches for significant changes in the overlay display window lifecycle.
+     */
+    public interface Listener {
+        public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate);
+        public void onWindowDestroyed();
+    }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/display/PersistentDataStore.java b/services/java/com/android/server/display/PersistentDataStore.java
new file mode 100644
index 0000000..3a6e1a6
--- /dev/null
+++ b/services/java/com/android/server/display/PersistentDataStore.java
@@ -0,0 +1,292 @@
+/*
+ * 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.display;
+
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import android.hardware.display.WifiDisplay;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.Xml;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+
+import libcore.io.IoUtils;
+import libcore.util.Objects;
+
+/**
+ * Manages persistent state recorded by the display manager service as an XML file.
+ * Caller must acquire lock on the data store before accessing it.
+ *
+ * File format:
+ * <code>
+ * &lt;display-manager-state>
+ *   &lt;remembered-wifi-displays>
+ *     &lt;wifi-display deviceAddress="00:00:00:00:00:00" deviceName="XXXX" deviceAlias="YYYY" />
+ *   &gt;remembered-wifi-displays>
+ * &gt;/display-manager-state>
+ * </code>
+ *
+ * TODO: refactor this to extract common code shared with the input manager's data store
+ */
+final class PersistentDataStore {
+    static final String TAG = "DisplayManager";
+
+    // Remembered Wifi display devices.
+    private ArrayList<WifiDisplay> mRememberedWifiDisplays = new ArrayList<WifiDisplay>();
+
+    // The atomic file used to safely read or write the file.
+    private final AtomicFile mAtomicFile;
+
+    // True if the data has been loaded.
+    private boolean mLoaded;
+
+    // True if there are changes to be saved.
+    private boolean mDirty;
+
+    public PersistentDataStore() {
+        mAtomicFile = new AtomicFile(new File("/data/system/display-manager-state.xml"));
+    }
+
+    public void saveIfNeeded() {
+        if (mDirty) {
+            save();
+            mDirty = false;
+        }
+    }
+
+    public WifiDisplay[] getRememberedWifiDisplays() {
+        loadIfNeeded();
+        return mRememberedWifiDisplays.toArray(new WifiDisplay[mRememberedWifiDisplays.size()]);
+    }
+
+    public WifiDisplay applyWifiDisplayAlias(WifiDisplay display) {
+        if (display != null) {
+            loadIfNeeded();
+
+            String alias = null;
+            int index = findRememberedWifiDisplay(display.getDeviceAddress());
+            if (index >= 0) {
+                alias = mRememberedWifiDisplays.get(index).getDeviceAlias();
+            }
+            if (!Objects.equal(display.getDeviceAlias(), alias)) {
+                return new WifiDisplay(display.getDeviceAddress(), display.getDeviceName(), alias);
+            }
+        }
+        return display;
+    }
+
+    public WifiDisplay[] applyWifiDisplayAliases(WifiDisplay[] displays) {
+        WifiDisplay[] results = displays;
+        if (results != null) {
+            int count = displays.length;
+            for (int i = 0; i < count; i++) {
+                WifiDisplay result = applyWifiDisplayAlias(displays[i]);
+                if (result != displays[i]) {
+                    if (results == displays) {
+                        results = new WifiDisplay[count];
+                        System.arraycopy(displays, 0, results, 0, count);
+                    }
+                    results[i] = result;
+                }
+            }
+        }
+        return results;
+    }
+
+    public boolean rememberWifiDisplay(WifiDisplay display) {
+        loadIfNeeded();
+
+        int index = findRememberedWifiDisplay(display.getDeviceAddress());
+        if (index >= 0) {
+            WifiDisplay other = mRememberedWifiDisplays.get(index);
+            if (other.equals(display)) {
+                return false; // already remembered without change
+            }
+            mRememberedWifiDisplays.set(index, display);
+        } else {
+            mRememberedWifiDisplays.add(display);
+        }
+        setDirty();
+        return true;
+    }
+
+    public boolean renameWifiDisplay(String deviceAddress, String alias) {
+        int index = findRememberedWifiDisplay(deviceAddress);
+        if (index >= 0) {
+            WifiDisplay display = mRememberedWifiDisplays.get(index);
+            if (Objects.equal(display.getDeviceAlias(), alias)) {
+                return false; // already has this alias
+            }
+            WifiDisplay renamedDisplay = new WifiDisplay(deviceAddress,
+                    display.getDeviceName(), alias);
+            mRememberedWifiDisplays.set(index, renamedDisplay);
+            setDirty();
+            return true;
+        }
+        return false;
+    }
+
+    public boolean forgetWifiDisplay(String deviceAddress) {
+        int index = findRememberedWifiDisplay(deviceAddress);
+        if (index >= 0) {
+            mRememberedWifiDisplays.remove(index);
+            setDirty();
+            return true;
+        }
+        return false;
+    }
+
+    private int findRememberedWifiDisplay(String deviceAddress) {
+        int count = mRememberedWifiDisplays.size();
+        for (int i = 0; i < count; i++) {
+            if (mRememberedWifiDisplays.get(i).getDeviceAddress().equals(deviceAddress)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private void loadIfNeeded() {
+        if (!mLoaded) {
+            load();
+            mLoaded = true;
+        }
+    }
+
+    private void setDirty() {
+        mDirty = true;
+    }
+
+    private void clearState() {
+        mRememberedWifiDisplays.clear();
+    }
+
+    private void load() {
+        clearState();
+
+        final InputStream is;
+        try {
+            is = mAtomicFile.openRead();
+        } catch (FileNotFoundException ex) {
+            return;
+        }
+
+        XmlPullParser parser;
+        try {
+            parser = Xml.newPullParser();
+            parser.setInput(new BufferedInputStream(is), null);
+            loadFromXml(parser);
+        } catch (IOException ex) {
+            Slog.w(TAG, "Failed to load display manager persistent store data.", ex);
+            clearState();
+        } catch (XmlPullParserException ex) {
+            Slog.w(TAG, "Failed to load display manager persistent store data.", ex);
+            clearState();
+        } finally {
+            IoUtils.closeQuietly(is);
+        }
+    }
+
+    private void save() {
+        final FileOutputStream os;
+        try {
+            os = mAtomicFile.startWrite();
+            boolean success = false;
+            try {
+                XmlSerializer serializer = new FastXmlSerializer();
+                serializer.setOutput(new BufferedOutputStream(os), "utf-8");
+                saveToXml(serializer);
+                serializer.flush();
+                success = true;
+            } finally {
+                if (success) {
+                    mAtomicFile.finishWrite(os);
+                } else {
+                    mAtomicFile.failWrite(os);
+                }
+            }
+        } catch (IOException ex) {
+            Slog.w(TAG, "Failed to save display manager persistent store data.", ex);
+        }
+    }
+
+    private void loadFromXml(XmlPullParser parser)
+            throws IOException, XmlPullParserException {
+        XmlUtils.beginDocument(parser, "display-manager-state");
+        final int outerDepth = parser.getDepth();
+        while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+            if (parser.getName().equals("remembered-wifi-displays")) {
+                loadRememberedWifiDisplaysFromXml(parser);
+            }
+        }
+    }
+
+    private void loadRememberedWifiDisplaysFromXml(XmlPullParser parser)
+            throws IOException, XmlPullParserException {
+        final int outerDepth = parser.getDepth();
+        while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+            if (parser.getName().equals("wifi-display")) {
+                String deviceAddress = parser.getAttributeValue(null, "deviceAddress");
+                String deviceName = parser.getAttributeValue(null, "deviceName");
+                String deviceAlias = parser.getAttributeValue(null, "deviceAlias");
+                if (deviceAddress == null || deviceName == null) {
+                    throw new XmlPullParserException(
+                            "Missing deviceAddress or deviceName attribute on wifi-display.");
+                }
+                if (findRememberedWifiDisplay(deviceAddress) >= 0) {
+                    throw new XmlPullParserException(
+                            "Found duplicate wifi display device address.");
+                }
+
+                mRememberedWifiDisplays.add(
+                        new WifiDisplay(deviceAddress, deviceName, deviceAlias));
+            }
+        }
+    }
+
+    private void saveToXml(XmlSerializer serializer) throws IOException {
+        serializer.startDocument(null, true);
+        serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+        serializer.startTag(null, "display-manager-state");
+        serializer.startTag(null, "remembered-wifi-displays");
+        for (WifiDisplay display : mRememberedWifiDisplays) {
+            serializer.startTag(null, "wifi-display");
+            serializer.attribute(null, "deviceAddress", display.getDeviceAddress());
+            serializer.attribute(null, "deviceName", display.getDeviceName());
+            if (display.getDeviceAlias() != null) {
+                serializer.attribute(null, "deviceAlias", display.getDeviceAlias());
+            }
+            serializer.endTag(null, "wifi-display");
+        }
+        serializer.endTag(null, "remembered-wifi-displays");
+        serializer.endTag(null, "display-manager-state");
+        serializer.endDocument();
+    }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java
new file mode 100644
index 0000000..45fff30
--- /dev/null
+++ b/services/java/com/android/server/display/WifiDisplayAdapter.java
@@ -0,0 +1,589 @@
+/*
+ * 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.display;
+
+import com.android.internal.R;
+import com.android.internal.util.DumpUtils;
+import com.android.internal.util.IndentingPrintWriter;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.WifiDisplay;
+import android.hardware.display.WifiDisplayStatus;
+import android.media.RemoteDisplay;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Slog;
+import android.view.Display;
+import android.view.Surface;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+
+/**
+ * Connects to Wifi displays that implement the Miracast protocol.
+ * <p>
+ * The Wifi display protocol relies on Wifi direct for discovering and pairing
+ * with the display.  Once connected, the Media Server opens an RTSP socket and accepts
+ * a connection from the display.  After session negotiation, the Media Server
+ * streams encoded buffers to the display.
+ * </p><p>
+ * This class is responsible for connecting to Wifi displays and mediating
+ * the interactions between Media Server, Surface Flinger and the Display Manager Service.
+ * </p><p>
+ * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
+ * </p>
+ */
+final class WifiDisplayAdapter extends DisplayAdapter {
+    private static final String TAG = "WifiDisplayAdapter";
+
+    private static final boolean DEBUG = false;
+
+    private static final int MSG_SEND_STATUS_CHANGE_BROADCAST = 1;
+    private static final int MSG_UPDATE_NOTIFICATION = 2;
+
+    private static final String ACTION_DISCONNECT = "android.server.display.wfd.DISCONNECT";
+
+    private final WifiDisplayHandler mHandler;
+    private final PersistentDataStore mPersistentDataStore;
+    private final boolean mSupportsProtectedBuffers;
+    private final NotificationManager mNotificationManager;
+
+    private PendingIntent mSettingsPendingIntent;
+    private PendingIntent mDisconnectPendingIntent;
+
+    private WifiDisplayController mDisplayController;
+    private WifiDisplayDevice mDisplayDevice;
+
+    private WifiDisplayStatus mCurrentStatus;
+    private int mFeatureState;
+    private int mScanState;
+    private int mActiveDisplayState;
+    private WifiDisplay mActiveDisplay;
+    private WifiDisplay[] mAvailableDisplays = WifiDisplay.EMPTY_ARRAY;
+    private WifiDisplay[] mRememberedDisplays = WifiDisplay.EMPTY_ARRAY;
+
+    private boolean mPendingStatusChangeBroadcast;
+    private boolean mPendingNotificationUpdate;
+
+    // Called with SyncRoot lock held.
+    public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
+            Context context, Handler handler, Listener listener,
+            PersistentDataStore persistentDataStore) {
+        super(syncRoot, context, handler, listener, TAG);
+        mHandler = new WifiDisplayHandler(handler.getLooper());
+        mPersistentDataStore = persistentDataStore;
+        mSupportsProtectedBuffers = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers);
+        mNotificationManager = (NotificationManager)context.getSystemService(
+                Context.NOTIFICATION_SERVICE);
+    }
+
+    @Override
+    public void dumpLocked(PrintWriter pw) {
+        super.dumpLocked(pw);
+
+        pw.println("mCurrentStatus=" + getWifiDisplayStatusLocked());
+        pw.println("mFeatureState=" + mFeatureState);
+        pw.println("mScanState=" + mScanState);
+        pw.println("mActiveDisplayState=" + mActiveDisplayState);
+        pw.println("mActiveDisplay=" + mActiveDisplay);
+        pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays));
+        pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays));
+        pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast);
+        pw.println("mPendingNotificationUpdate=" + mPendingNotificationUpdate);
+        pw.println("mSupportsProtectedBuffers=" + mSupportsProtectedBuffers);
+
+        // Try to dump the controller state.
+        if (mDisplayController == null) {
+            pw.println("mDisplayController=null");
+        } else {
+            pw.println("mDisplayController:");
+            final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
+            ipw.increaseIndent();
+            DumpUtils.dumpAsync(getHandler(), mDisplayController, ipw, 200);
+        }
+    }
+
+    @Override
+    public void registerLocked() {
+        super.registerLocked();
+
+        updateRememberedDisplaysLocked();
+
+        getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                mDisplayController = new WifiDisplayController(
+                        getContext(), getHandler(), mWifiDisplayListener);
+
+                getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
+                        new IntentFilter(ACTION_DISCONNECT), null, mHandler);
+            }
+        });
+    }
+
+    public void requestScanLocked() {
+        if (DEBUG) {
+            Slog.d(TAG, "requestScanLocked");
+        }
+
+        getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                if (mDisplayController != null) {
+                    mDisplayController.requestScan();
+                }
+            }
+        });
+    }
+
+    public void requestConnectLocked(final String address, final boolean trusted) {
+        if (DEBUG) {
+            Slog.d(TAG, "requestConnectLocked: address=" + address + ", trusted=" + trusted);
+        }
+
+        if (!trusted) {
+            synchronized (getSyncRoot()) {
+                if (!isRememberedDisplayLocked(address)) {
+                    Slog.w(TAG, "Ignoring request by an untrusted client to connect to "
+                            + "an unknown wifi display: " + address);
+                    return;
+                }
+            }
+        }
+
+        getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                if (mDisplayController != null) {
+                    mDisplayController.requestConnect(address);
+                }
+            }
+        });
+    }
+
+    private boolean isRememberedDisplayLocked(String address) {
+        for (WifiDisplay display : mRememberedDisplays) {
+            if (display.getDeviceAddress().equals(address)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void requestDisconnectLocked() {
+        if (DEBUG) {
+            Slog.d(TAG, "requestDisconnectedLocked");
+        }
+
+        getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                if (mDisplayController != null) {
+                    mDisplayController.requestDisconnect();
+                }
+            }
+        });
+    }
+
+    public void requestRenameLocked(String address, String alias) {
+        if (DEBUG) {
+            Slog.d(TAG, "requestRenameLocked: address=" + address + ", alias=" + alias);
+        }
+
+        if (alias != null) {
+            alias = alias.trim();
+            if (alias.isEmpty() || alias.equals(address)) {
+                alias = null;
+            }
+        }
+
+        if (mPersistentDataStore.renameWifiDisplay(address, alias)) {
+            mPersistentDataStore.saveIfNeeded();
+            updateRememberedDisplaysLocked();
+            scheduleStatusChangedBroadcastLocked();
+        }
+
+        if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)
+                && mDisplayDevice != null) {
+            mDisplayDevice.setNameLocked(mActiveDisplay.getFriendlyDisplayName());
+            sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_CHANGED);
+        }
+    }
+
+    public void requestForgetLocked(String address) {
+        if (DEBUG) {
+            Slog.d(TAG, "requestForgetLocked: address=" + address);
+        }
+
+        if (mPersistentDataStore.forgetWifiDisplay(address)) {
+            mPersistentDataStore.saveIfNeeded();
+            updateRememberedDisplaysLocked();
+            scheduleStatusChangedBroadcastLocked();
+        }
+
+        if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) {
+            requestDisconnectLocked();
+        }
+    }
+
+    public WifiDisplayStatus getWifiDisplayStatusLocked() {
+        if (mCurrentStatus == null) {
+            mCurrentStatus = new WifiDisplayStatus(
+                    mFeatureState, mScanState, mActiveDisplayState,
+                    mActiveDisplay, mAvailableDisplays, mRememberedDisplays);
+        }
+
+        if (DEBUG) {
+            Slog.d(TAG, "getWifiDisplayStatusLocked: result=" + mCurrentStatus);
+        }
+        return mCurrentStatus;
+    }
+
+    private void updateRememberedDisplaysLocked() {
+        mRememberedDisplays = mPersistentDataStore.getRememberedWifiDisplays();
+        mActiveDisplay = mPersistentDataStore.applyWifiDisplayAlias(mActiveDisplay);
+        mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays);
+    }
+
+    private void handleConnectLocked(WifiDisplay display,
+            Surface surface, int width, int height, int flags) {
+        handleDisconnectLocked();
+
+        if (mPersistentDataStore.rememberWifiDisplay(display)) {
+            mPersistentDataStore.saveIfNeeded();
+            updateRememberedDisplaysLocked();
+            scheduleStatusChangedBroadcastLocked();
+        }
+
+        boolean secure = (flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0;
+        int deviceFlags = 0;
+        if (secure) {
+            deviceFlags |= DisplayDeviceInfo.FLAG_SECURE;
+            if (mSupportsProtectedBuffers) {
+                deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
+            }
+        }
+
+        float refreshRate = 60.0f; // TODO: get this for real
+
+        String name = display.getFriendlyDisplayName();
+        String address = display.getDeviceAddress();
+        IBinder displayToken = Surface.createDisplay(name, secure);
+        mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height,
+                refreshRate, deviceFlags, address, surface);
+        sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED);
+
+        scheduleUpdateNotificationLocked();
+    }
+
+    private void handleDisconnectLocked() {
+        if (mDisplayDevice != null) {
+            mDisplayDevice.clearSurfaceLocked();
+            sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED);
+            mDisplayDevice = null;
+
+            scheduleUpdateNotificationLocked();
+        }
+    }
+
+    private void scheduleStatusChangedBroadcastLocked() {
+        mCurrentStatus = null;
+        if (!mPendingStatusChangeBroadcast) {
+            mPendingStatusChangeBroadcast = true;
+            mHandler.sendEmptyMessage(MSG_SEND_STATUS_CHANGE_BROADCAST);
+        }
+    }
+
+    private void scheduleUpdateNotificationLocked() {
+        if (!mPendingNotificationUpdate) {
+            mPendingNotificationUpdate = true;
+            mHandler.sendEmptyMessage(MSG_UPDATE_NOTIFICATION);
+        }
+    }
+
+    // Runs on the handler.
+    private void handleSendStatusChangeBroadcast() {
+        final Intent intent;
+        synchronized (getSyncRoot()) {
+            if (!mPendingStatusChangeBroadcast) {
+                return;
+            }
+
+            mPendingStatusChangeBroadcast = false;
+            intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+            intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS,
+                    getWifiDisplayStatusLocked());
+        }
+
+        // Send protected broadcast about wifi display status to registered receivers.
+        getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
+    }
+
+    // Runs on the handler.
+    private void handleUpdateNotification() {
+        final boolean isConnected;
+        synchronized (getSyncRoot()) {
+            if (!mPendingNotificationUpdate) {
+                return;
+            }
+
+            mPendingNotificationUpdate = false;
+            isConnected = (mDisplayDevice != null);
+        }
+
+        // Cancel the old notification if there is one.
+        mNotificationManager.cancelAsUser(null,
+                R.string.wifi_display_notification_title, UserHandle.ALL);
+
+        if (isConnected) {
+            Context context = getContext();
+
+            // Initialize pending intents for the notification outside of the lock because
+            // creating a pending intent requires a call into the activity manager.
+            if (mSettingsPendingIntent == null) {
+                Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS);
+                settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+                        | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                mSettingsPendingIntent = PendingIntent.getActivityAsUser(
+                        context, 0, settingsIntent, 0, null, UserHandle.CURRENT);
+            }
+
+            if (mDisconnectPendingIntent == null) {
+                Intent disconnectIntent = new Intent(ACTION_DISCONNECT);
+                mDisconnectPendingIntent = PendingIntent.getBroadcastAsUser(
+                        context, 0, disconnectIntent, 0, UserHandle.CURRENT);
+            }
+
+            // Post the notification.
+            Resources r = context.getResources();
+            Notification notification = new Notification.Builder(context)
+                    .setContentTitle(r.getString(
+                            R.string.wifi_display_notification_title))
+                    .setContentText(r.getString(
+                            R.string.wifi_display_notification_message))
+                    .setContentIntent(mSettingsPendingIntent)
+                    .setSmallIcon(R.drawable.ic_notify_wifidisplay)
+                    .setOngoing(true)
+                    .addAction(android.R.drawable.ic_menu_close_clear_cancel,
+                            r.getString(R.string.wifi_display_notification_disconnect),
+                            mDisconnectPendingIntent)
+                    .build();
+            mNotificationManager.notifyAsUser(null,
+                    R.string.wifi_display_notification_title,
+                    notification, UserHandle.ALL);
+        }
+    }
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals(ACTION_DISCONNECT)) {
+                synchronized (getSyncRoot()) {
+                    requestDisconnectLocked();
+                }
+            }
+        }
+    };
+
+    private final WifiDisplayController.Listener mWifiDisplayListener =
+            new WifiDisplayController.Listener() {
+        @Override
+        public void onFeatureStateChanged(int featureState) {
+            synchronized (getSyncRoot()) {
+                if (mFeatureState != featureState) {
+                    mFeatureState = featureState;
+                    scheduleStatusChangedBroadcastLocked();
+                }
+            }
+        }
+
+        @Override
+        public void onScanStarted() {
+            synchronized (getSyncRoot()) {
+                if (mScanState != WifiDisplayStatus.SCAN_STATE_SCANNING) {
+                    mScanState = WifiDisplayStatus.SCAN_STATE_SCANNING;
+                    scheduleStatusChangedBroadcastLocked();
+                }
+            }
+        }
+
+        @Override
+        public void onScanFinished(WifiDisplay[] availableDisplays) {
+            synchronized (getSyncRoot()) {
+                availableDisplays = mPersistentDataStore.applyWifiDisplayAliases(
+                        availableDisplays);
+
+                if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING
+                        || !Arrays.equals(mAvailableDisplays, availableDisplays)) {
+                    mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING;
+                    mAvailableDisplays = availableDisplays;
+                    scheduleStatusChangedBroadcastLocked();
+                }
+            }
+        }
+
+        @Override
+        public void onDisplayConnecting(WifiDisplay display) {
+            synchronized (getSyncRoot()) {
+                display = mPersistentDataStore.applyWifiDisplayAlias(display);
+
+                if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTING
+                        || mActiveDisplay == null
+                        || !mActiveDisplay.equals(display)) {
+                    mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING;
+                    mActiveDisplay = display;
+                    scheduleStatusChangedBroadcastLocked();
+                }
+            }
+        }
+
+        @Override
+        public void onDisplayConnectionFailed() {
+            synchronized (getSyncRoot()) {
+                if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED
+                        || mActiveDisplay != null) {
+                    mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
+                    mActiveDisplay = null;
+                    scheduleStatusChangedBroadcastLocked();
+                }
+            }
+        }
+
+        @Override
+        public void onDisplayConnected(WifiDisplay display, Surface surface,
+                int width, int height, int flags) {
+            synchronized (getSyncRoot()) {
+                display = mPersistentDataStore.applyWifiDisplayAlias(display);
+                handleConnectLocked(display, surface, width, height, flags);
+
+                if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED
+                        || mActiveDisplay == null
+                        || !mActiveDisplay.equals(display)) {
+                    mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED;
+                    mActiveDisplay = display;
+                    scheduleStatusChangedBroadcastLocked();
+                }
+            }
+        }
+
+        @Override
+        public void onDisplayDisconnected() {
+            // Stop listening.
+            synchronized (getSyncRoot()) {
+                handleDisconnectLocked();
+
+                if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED
+                        || mActiveDisplay != null) {
+                    mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
+                    mActiveDisplay = null;
+                    scheduleStatusChangedBroadcastLocked();
+                }
+            }
+        }
+    };
+
+    private final class WifiDisplayDevice extends DisplayDevice {
+        private String mName;
+        private final int mWidth;
+        private final int mHeight;
+        private final float mRefreshRate;
+        private final int mFlags;
+        private final String mAddress;
+
+        private Surface mSurface;
+        private DisplayDeviceInfo mInfo;
+
+        public WifiDisplayDevice(IBinder displayToken, String name,
+                int width, int height, float refreshRate, int flags, String address,
+                Surface surface) {
+            super(WifiDisplayAdapter.this, displayToken);
+            mName = name;
+            mWidth = width;
+            mHeight = height;
+            mRefreshRate = refreshRate;
+            mFlags = flags;
+            mAddress = address;
+            mSurface = surface;
+        }
+
+        public void clearSurfaceLocked() {
+            mSurface = null;
+            sendTraversalRequestLocked();
+        }
+
+        public void setNameLocked(String name) {
+            mName = name;
+            mInfo = null;
+        }
+
+        @Override
+        public void performTraversalInTransactionLocked() {
+            setSurfaceInTransactionLocked(mSurface);
+        }
+
+        @Override
+        public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
+            if (mInfo == null) {
+                mInfo = new DisplayDeviceInfo();
+                mInfo.name = mName;
+                mInfo.width = mWidth;
+                mInfo.height = mHeight;
+                mInfo.refreshRate = mRefreshRate;
+                mInfo.flags = mFlags;
+                mInfo.type = Display.TYPE_WIFI;
+                mInfo.address = mAddress;
+                mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
+                mInfo.setAssumedDensityForExternalDisplay(mWidth, mHeight);
+            }
+            return mInfo;
+        }
+    }
+
+    private final class WifiDisplayHandler extends Handler {
+        public WifiDisplayHandler(Looper looper) {
+            super(looper, null, true /*async*/);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_SEND_STATUS_CHANGE_BROADCAST:
+                    handleSendStatusChangeBroadcast();
+                    break;
+
+                case MSG_UPDATE_NOTIFICATION:
+                    handleUpdateNotification();
+                    break;
+            }
+        }
+    }
+}
diff --git a/services/java/com/android/server/display/WifiDisplayController.java b/services/java/com/android/server/display/WifiDisplayController.java
new file mode 100644
index 0000000..39d042f
--- /dev/null
+++ b/services/java/com/android/server/display/WifiDisplayController.java
@@ -0,0 +1,892 @@
+/*
+ * 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.display;
+
+import com.android.internal.util.DumpUtils;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.hardware.display.WifiDisplay;
+import android.hardware.display.WifiDisplayStatus;
+import android.media.AudioManager;
+import android.media.RemoteDisplay;
+import android.net.NetworkInfo;
+import android.net.Uri;
+import android.net.wifi.p2p.WifiP2pConfig;
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.net.wifi.p2p.WifiP2pDeviceList;
+import android.net.wifi.p2p.WifiP2pGroup;
+import android.net.wifi.p2p.WifiP2pManager;
+import android.net.wifi.p2p.WifiP2pWfdInfo;
+import android.net.wifi.p2p.WifiP2pManager.ActionListener;
+import android.net.wifi.p2p.WifiP2pManager.Channel;
+import android.net.wifi.p2p.WifiP2pManager.GroupInfoListener;
+import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
+import android.os.Handler;
+import android.provider.Settings;
+import android.util.Slog;
+import android.view.Surface;
+
+import java.io.PrintWriter;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+import libcore.util.Objects;
+
+/**
+ * Manages all of the various asynchronous interactions with the {@link WifiP2pManager}
+ * on behalf of {@link WifiDisplayAdapter}.
+ * <p>
+ * This code is isolated from {@link WifiDisplayAdapter} so that we can avoid
+ * accidentally introducing any deadlocks due to the display manager calling
+ * outside of itself while holding its lock.  It's also way easier to write this
+ * asynchronous code if we can assume that it is single-threaded.
+ * </p><p>
+ * The controller must be instantiated on the handler thread.
+ * </p>
+ */
+final class WifiDisplayController implements DumpUtils.Dump {
+    private static final String TAG = "WifiDisplayController";
+    private static final boolean DEBUG = false;
+
+    private static final int DEFAULT_CONTROL_PORT = 7236;
+    private static final int MAX_THROUGHPUT = 50;
+    private static final int CONNECTION_TIMEOUT_SECONDS = 60;
+    private static final int RTSP_TIMEOUT_SECONDS = 15;
+
+    private static final int DISCOVER_PEERS_MAX_RETRIES = 10;
+    private static final int DISCOVER_PEERS_RETRY_DELAY_MILLIS = 500;
+
+    private static final int CONNECT_MAX_RETRIES = 3;
+    private static final int CONNECT_RETRY_DELAY_MILLIS = 500;
+
+    // A unique token to identify the remote submix that is managed by Wifi display.
+    // It must match what the media server uses when it starts recording the submix
+    // for transmission.  We use 0 although the actual value is currently ignored.
+    private static final int REMOTE_SUBMIX_ADDRESS = 0;
+
+    private final Context mContext;
+    private final Handler mHandler;
+    private final Listener mListener;
+
+    private final WifiP2pManager mWifiP2pManager;
+    private final Channel mWifiP2pChannel;
+
+    private final AudioManager mAudioManager;
+
+    private boolean mWifiP2pEnabled;
+    private boolean mWfdEnabled;
+    private boolean mWfdEnabling;
+    private NetworkInfo mNetworkInfo;
+
+    private final ArrayList<WifiP2pDevice> mAvailableWifiDisplayPeers =
+            new ArrayList<WifiP2pDevice>();
+
+    // True if Wifi display is enabled by the user.
+    private boolean mWifiDisplayOnSetting;
+
+    // True if there is a call to discoverPeers in progress.
+    private boolean mDiscoverPeersInProgress;
+
+    // Number of discover peers retries remaining.
+    private int mDiscoverPeersRetriesLeft;
+
+    // The device to which we want to connect, or null if we want to be disconnected.
+    private WifiP2pDevice mDesiredDevice;
+
+    // The device to which we are currently connecting, or null if we have already connected
+    // or are not trying to connect.
+    private WifiP2pDevice mConnectingDevice;
+
+    // The device to which we are currently connected, which means we have an active P2P group.
+    private WifiP2pDevice mConnectedDevice;
+
+    // The group info obtained after connecting.
+    private WifiP2pGroup mConnectedDeviceGroupInfo;
+
+    // Number of connection retries remaining.
+    private int mConnectionRetriesLeft;
+
+    // The remote display that is listening on the connection.
+    // Created after the Wifi P2P network is connected.
+    private RemoteDisplay mRemoteDisplay;
+
+    // The remote display interface.
+    private String mRemoteDisplayInterface;
+
+    // True if RTSP has connected.
+    private boolean mRemoteDisplayConnected;
+
+    // True if the remote submix is enabled.
+    private boolean mRemoteSubmixOn;
+
+    // The information we have most recently told WifiDisplayAdapter about.
+    private WifiDisplay mAdvertisedDisplay;
+    private Surface mAdvertisedDisplaySurface;
+    private int mAdvertisedDisplayWidth;
+    private int mAdvertisedDisplayHeight;
+    private int mAdvertisedDisplayFlags;
+
+    public WifiDisplayController(Context context, Handler handler, Listener listener) {
+        mContext = context;
+        mHandler = handler;
+        mListener = listener;
+
+        mWifiP2pManager = (WifiP2pManager)context.getSystemService(Context.WIFI_P2P_SERVICE);
+        mWifiP2pChannel = mWifiP2pManager.initialize(context, handler.getLooper(), null);
+
+        mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
+
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
+        intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
+        intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
+        context.registerReceiver(mWifiP2pReceiver, intentFilter, null, mHandler);
+
+        ContentObserver settingsObserver = new ContentObserver(mHandler) {
+            @Override
+            public void onChange(boolean selfChange, Uri uri) {
+                updateSettings();
+            }
+        };
+
+        final ContentResolver resolver = mContext.getContentResolver();
+        resolver.registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.WIFI_DISPLAY_ON), false, settingsObserver);
+        updateSettings();
+    }
+
+    private void updateSettings() {
+        final ContentResolver resolver = mContext.getContentResolver();
+        mWifiDisplayOnSetting = Settings.Global.getInt(resolver,
+                Settings.Global.WIFI_DISPLAY_ON, 0) != 0;
+
+        updateWfdEnableState();
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.println("mWifiDisplayOnSetting=" + mWifiDisplayOnSetting);
+        pw.println("mWifiP2pEnabled=" + mWifiP2pEnabled);
+        pw.println("mWfdEnabled=" + mWfdEnabled);
+        pw.println("mWfdEnabling=" + mWfdEnabling);
+        pw.println("mNetworkInfo=" + mNetworkInfo);
+        pw.println("mDiscoverPeersInProgress=" + mDiscoverPeersInProgress);
+        pw.println("mDiscoverPeersRetriesLeft=" + mDiscoverPeersRetriesLeft);
+        pw.println("mDesiredDevice=" + describeWifiP2pDevice(mDesiredDevice));
+        pw.println("mConnectingDisplay=" + describeWifiP2pDevice(mConnectingDevice));
+        pw.println("mConnectedDevice=" + describeWifiP2pDevice(mConnectedDevice));
+        pw.println("mConnectionRetriesLeft=" + mConnectionRetriesLeft);
+        pw.println("mRemoteDisplay=" + mRemoteDisplay);
+        pw.println("mRemoteDisplayInterface=" + mRemoteDisplayInterface);
+        pw.println("mRemoteDisplayConnected=" + mRemoteDisplayConnected);
+        pw.println("mRemoteSubmixOn=" + mRemoteSubmixOn);
+        pw.println("mAdvertisedDisplay=" + mAdvertisedDisplay);
+        pw.println("mAdvertisedDisplaySurface=" + mAdvertisedDisplaySurface);
+        pw.println("mAdvertisedDisplayWidth=" + mAdvertisedDisplayWidth);
+        pw.println("mAdvertisedDisplayHeight=" + mAdvertisedDisplayHeight);
+        pw.println("mAdvertisedDisplayFlags=" + mAdvertisedDisplayFlags);
+
+        pw.println("mAvailableWifiDisplayPeers: size=" + mAvailableWifiDisplayPeers.size());
+        for (WifiP2pDevice device : mAvailableWifiDisplayPeers) {
+            pw.println("  " + describeWifiP2pDevice(device));
+        }
+    }
+
+    public void requestScan() {
+        discoverPeers();
+    }
+
+    public void requestConnect(String address) {
+        for (WifiP2pDevice device : mAvailableWifiDisplayPeers) {
+            if (device.deviceAddress.equals(address)) {
+                connect(device);
+            }
+        }
+    }
+
+    public void requestDisconnect() {
+        disconnect();
+    }
+
+    private void updateWfdEnableState() {
+        if (mWifiDisplayOnSetting && mWifiP2pEnabled) {
+            // WFD should be enabled.
+            if (!mWfdEnabled && !mWfdEnabling) {
+                mWfdEnabling = true;
+
+                WifiP2pWfdInfo wfdInfo = new WifiP2pWfdInfo();
+                wfdInfo.setWfdEnabled(true);
+                wfdInfo.setDeviceType(WifiP2pWfdInfo.WFD_SOURCE);
+                wfdInfo.setSessionAvailable(true);
+                wfdInfo.setControlPort(DEFAULT_CONTROL_PORT);
+                wfdInfo.setMaxThroughput(MAX_THROUGHPUT);
+                mWifiP2pManager.setWFDInfo(mWifiP2pChannel, wfdInfo, new ActionListener() {
+                    @Override
+                    public void onSuccess() {
+                        if (DEBUG) {
+                            Slog.d(TAG, "Successfully set WFD info.");
+                        }
+                        if (mWfdEnabling) {
+                            mWfdEnabling = false;
+                            mWfdEnabled = true;
+                            reportFeatureState();
+                        }
+                    }
+
+                    @Override
+                    public void onFailure(int reason) {
+                        if (DEBUG) {
+                            Slog.d(TAG, "Failed to set WFD info with reason " + reason + ".");
+                        }
+                        mWfdEnabling = false;
+                    }
+                });
+            }
+        } else {
+            // WFD should be disabled.
+            mWfdEnabling = false;
+            mWfdEnabled = false;
+            reportFeatureState();
+            disconnect();
+        }
+    }
+
+    private void reportFeatureState() {
+        final int featureState = computeFeatureState();
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mListener.onFeatureStateChanged(featureState);
+            }
+        });
+    }
+
+    private int computeFeatureState() {
+        if (!mWifiP2pEnabled) {
+            return WifiDisplayStatus.FEATURE_STATE_DISABLED;
+        }
+        return mWifiDisplayOnSetting ? WifiDisplayStatus.FEATURE_STATE_ON :
+                WifiDisplayStatus.FEATURE_STATE_OFF;
+    }
+
+    private void discoverPeers() {
+        if (!mDiscoverPeersInProgress) {
+            mDiscoverPeersInProgress = true;
+            mDiscoverPeersRetriesLeft = DISCOVER_PEERS_MAX_RETRIES;
+            handleScanStarted();
+            tryDiscoverPeers();
+        }
+    }
+
+    private void tryDiscoverPeers() {
+        mWifiP2pManager.discoverPeers(mWifiP2pChannel, new ActionListener() {
+            @Override
+            public void onSuccess() {
+                if (DEBUG) {
+                    Slog.d(TAG, "Discover peers succeeded.  Requesting peers now.");
+                }
+
+                mDiscoverPeersInProgress = false;
+                requestPeers();
+            }
+
+            @Override
+            public void onFailure(int reason) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Discover peers failed with reason " + reason + ".");
+                }
+
+                if (mDiscoverPeersInProgress) {
+                    if (reason == 0 && mDiscoverPeersRetriesLeft > 0 && mWfdEnabled) {
+                        mHandler.postDelayed(new Runnable() {
+                            @Override
+                            public void run() {
+                                if (mDiscoverPeersInProgress) {
+                                    if (mDiscoverPeersRetriesLeft > 0 && mWfdEnabled) {
+                                        mDiscoverPeersRetriesLeft -= 1;
+                                        if (DEBUG) {
+                                            Slog.d(TAG, "Retrying discovery.  Retries left: "
+                                                    + mDiscoverPeersRetriesLeft);
+                                        }
+                                        tryDiscoverPeers();
+                                    } else {
+                                        handleScanFinished();
+                                        mDiscoverPeersInProgress = false;
+                                    }
+                                }
+                            }
+                        }, DISCOVER_PEERS_RETRY_DELAY_MILLIS);
+                    } else {
+                        handleScanFinished();
+                        mDiscoverPeersInProgress = false;
+                    }
+                }
+            }
+        });
+    }
+
+    private void requestPeers() {
+        mWifiP2pManager.requestPeers(mWifiP2pChannel, new PeerListListener() {
+            @Override
+            public void onPeersAvailable(WifiP2pDeviceList peers) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Received list of peers.");
+                }
+
+                mAvailableWifiDisplayPeers.clear();
+                for (WifiP2pDevice device : peers.getDeviceList()) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "  " + describeWifiP2pDevice(device));
+                    }
+
+                    if (isWifiDisplay(device)) {
+                        mAvailableWifiDisplayPeers.add(device);
+                    }
+                }
+
+                handleScanFinished();
+            }
+        });
+    }
+
+    private void handleScanStarted() {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mListener.onScanStarted();
+            }
+        });
+    }
+
+    private void handleScanFinished() {
+        final int count = mAvailableWifiDisplayPeers.size();
+        final WifiDisplay[] displays = WifiDisplay.CREATOR.newArray(count);
+        for (int i = 0; i < count; i++) {
+            displays[i] = createWifiDisplay(mAvailableWifiDisplayPeers.get(i));
+        }
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mListener.onScanFinished(displays);
+            }
+        });
+    }
+
+    private void connect(final WifiP2pDevice device) {
+        if (mDesiredDevice != null
+                && !mDesiredDevice.deviceAddress.equals(device.deviceAddress)) {
+            if (DEBUG) {
+                Slog.d(TAG, "connect: nothing to do, already connecting to "
+                        + describeWifiP2pDevice(device));
+            }
+            return;
+        }
+
+        if (mConnectedDevice != null
+                && !mConnectedDevice.deviceAddress.equals(device.deviceAddress)
+                && mDesiredDevice == null) {
+            if (DEBUG) {
+                Slog.d(TAG, "connect: nothing to do, already connected to "
+                        + describeWifiP2pDevice(device) + " and not part way through "
+                        + "connecting to a different device.");
+            }
+            return;
+        }
+
+        mDesiredDevice = device;
+        mConnectionRetriesLeft = CONNECT_MAX_RETRIES;
+        updateConnection();
+    }
+
+    private void disconnect() {
+        mDesiredDevice = null;
+        updateConnection();
+    }
+
+    private void retryConnection() {
+        // Cheap hack.  Make a new instance of the device object so that we
+        // can distinguish it from the previous connection attempt.
+        // This will cause us to tear everything down before we try again.
+        mDesiredDevice = new WifiP2pDevice(mDesiredDevice);
+        updateConnection();
+    }
+
+    /**
+     * This function is called repeatedly after each asynchronous operation
+     * until all preconditions for the connection have been satisfied and the
+     * connection is established (or not).
+     */
+    private void updateConnection() {
+        // Step 1. Before we try to connect to a new device, tell the system we
+        // have disconnected from the old one.
+        if (mRemoteDisplay != null && mConnectedDevice != mDesiredDevice) {
+            Slog.i(TAG, "Stopped listening for RTSP connection on " + mRemoteDisplayInterface
+                    + " from Wifi display: " + mConnectedDevice.deviceName);
+
+            mRemoteDisplay.dispose();
+            mRemoteDisplay = null;
+            mRemoteDisplayInterface = null;
+            mRemoteDisplayConnected = false;
+            mHandler.removeCallbacks(mRtspTimeout);
+
+            setRemoteSubmixOn(false);
+            unadvertiseDisplay();
+
+            // continue to next step
+        }
+
+        // Step 2. Before we try to connect to a new device, disconnect from the old one.
+        if (mConnectedDevice != null && mConnectedDevice != mDesiredDevice) {
+            Slog.i(TAG, "Disconnecting from Wifi display: " + mConnectedDevice.deviceName);
+
+            unadvertiseDisplay();
+
+            final WifiP2pDevice oldDevice = mConnectedDevice;
+            mWifiP2pManager.removeGroup(mWifiP2pChannel, new ActionListener() {
+                @Override
+                public void onSuccess() {
+                    Slog.i(TAG, "Disconnected from Wifi display: " + oldDevice.deviceName);
+                    next();
+                }
+
+                @Override
+                public void onFailure(int reason) {
+                    Slog.i(TAG, "Failed to disconnect from Wifi display: "
+                            + oldDevice.deviceName + ", reason=" + reason);
+                    next();
+                }
+
+                private void next() {
+                    if (mConnectedDevice == oldDevice) {
+                        mConnectedDevice = null;
+                        updateConnection();
+                    }
+                }
+            });
+            return; // wait for asynchronous callback
+        }
+
+        // Step 3. Before we try to connect to a new device, stop trying to connect
+        // to the old one.
+        if (mConnectingDevice != null && mConnectingDevice != mDesiredDevice) {
+            Slog.i(TAG, "Canceling connection to Wifi display: " + mConnectingDevice.deviceName);
+
+            unadvertiseDisplay();
+            mHandler.removeCallbacks(mConnectionTimeout);
+
+            final WifiP2pDevice oldDevice = mConnectingDevice;
+            mWifiP2pManager.cancelConnect(mWifiP2pChannel, new ActionListener() {
+                @Override
+                public void onSuccess() {
+                    Slog.i(TAG, "Canceled connection to Wifi display: " + oldDevice.deviceName);
+                    next();
+                }
+
+                @Override
+                public void onFailure(int reason) {
+                    Slog.i(TAG, "Failed to cancel connection to Wifi display: "
+                            + oldDevice.deviceName + ", reason=" + reason);
+                    next();
+                }
+
+                private void next() {
+                    if (mConnectingDevice == oldDevice) {
+                        mConnectingDevice = null;
+                        updateConnection();
+                    }
+                }
+            });
+            return; // wait for asynchronous callback
+        }
+
+        // Step 4. If we wanted to disconnect, then mission accomplished.
+        if (mDesiredDevice == null) {
+            unadvertiseDisplay();
+            return; // done
+        }
+
+        // Step 5. Try to connect.
+        if (mConnectedDevice == null && mConnectingDevice == null) {
+            Slog.i(TAG, "Connecting to Wifi display: " + mDesiredDevice.deviceName);
+
+            mConnectingDevice = mDesiredDevice;
+            WifiP2pConfig config = new WifiP2pConfig();
+            config.deviceAddress = mConnectingDevice.deviceAddress;
+            // Helps with STA & P2P concurrency
+            config.groupOwnerIntent = WifiP2pConfig.MIN_GROUP_OWNER_INTENT;
+
+            WifiDisplay display = createWifiDisplay(mConnectingDevice);
+            advertiseDisplay(display, null, 0, 0, 0);
+
+            final WifiP2pDevice newDevice = mDesiredDevice;
+            mWifiP2pManager.connect(mWifiP2pChannel, config, new ActionListener() {
+                @Override
+                public void onSuccess() {
+                    // The connection may not yet be established.  We still need to wait
+                    // for WIFI_P2P_CONNECTION_CHANGED_ACTION.  However, we might never
+                    // get that broadcast, so we register a timeout.
+                    Slog.i(TAG, "Initiated connection to Wifi display: " + newDevice.deviceName);
+
+                    mHandler.postDelayed(mConnectionTimeout, CONNECTION_TIMEOUT_SECONDS * 1000);
+                }
+
+                @Override
+                public void onFailure(int reason) {
+                    if (mConnectingDevice == newDevice) {
+                        Slog.i(TAG, "Failed to initiate connection to Wifi display: "
+                                + newDevice.deviceName + ", reason=" + reason);
+                        mConnectingDevice = null;
+                        handleConnectionFailure(false);
+                    }
+                }
+            });
+            return; // wait for asynchronous callback
+        }
+
+        // Step 6. Listen for incoming connections.
+        if (mConnectedDevice != null && mRemoteDisplay == null) {
+            Inet4Address addr = getInterfaceAddress(mConnectedDeviceGroupInfo);
+            if (addr == null) {
+                Slog.i(TAG, "Failed to get local interface address for communicating "
+                        + "with Wifi display: " + mConnectedDevice.deviceName);
+                handleConnectionFailure(false);
+                return; // done
+            }
+
+            setRemoteSubmixOn(true);
+
+            final WifiP2pDevice oldDevice = mConnectedDevice;
+            final int port = getPortNumber(mConnectedDevice);
+            final String iface = addr.getHostAddress() + ":" + port;
+            mRemoteDisplayInterface = iface;
+
+            Slog.i(TAG, "Listening for RTSP connection on " + iface
+                    + " from Wifi display: " + mConnectedDevice.deviceName);
+
+            mRemoteDisplay = RemoteDisplay.listen(iface, new RemoteDisplay.Listener() {
+                @Override
+                public void onDisplayConnected(Surface surface,
+                        int width, int height, int flags) {
+                    if (mConnectedDevice == oldDevice && !mRemoteDisplayConnected) {
+                        Slog.i(TAG, "Opened RTSP connection with Wifi display: "
+                                + mConnectedDevice.deviceName);
+                        mRemoteDisplayConnected = true;
+                        mHandler.removeCallbacks(mRtspTimeout);
+
+                        final WifiDisplay display = createWifiDisplay(mConnectedDevice);
+                        advertiseDisplay(display, surface, width, height, flags);
+                    }
+                }
+
+                @Override
+                public void onDisplayDisconnected() {
+                    if (mConnectedDevice == oldDevice) {
+                        Slog.i(TAG, "Closed RTSP connection with Wifi display: "
+                                + mConnectedDevice.deviceName);
+                        mHandler.removeCallbacks(mRtspTimeout);
+                        disconnect();
+                    }
+                }
+
+                @Override
+                public void onDisplayError(int error) {
+                    if (mConnectedDevice == oldDevice) {
+                        Slog.i(TAG, "Lost RTSP connection with Wifi display due to error "
+                                + error + ": " + mConnectedDevice.deviceName);
+                        mHandler.removeCallbacks(mRtspTimeout);
+                        handleConnectionFailure(false);
+                    }
+                }
+            }, mHandler);
+
+            mHandler.postDelayed(mRtspTimeout, RTSP_TIMEOUT_SECONDS * 1000);
+        }
+    }
+
+    private void setRemoteSubmixOn(boolean on) {
+        if (mRemoteSubmixOn != on) {
+            mRemoteSubmixOn = on;
+            mAudioManager.setRemoteSubmixOn(on, REMOTE_SUBMIX_ADDRESS);
+        }
+    }
+
+    private void handleStateChanged(boolean enabled) {
+        mWifiP2pEnabled = enabled;
+        updateWfdEnableState();
+    }
+
+    private void handlePeersChanged() {
+        // Even if wfd is disabled, it is best to get the latest set of peers to
+        // keep in sync with the p2p framework
+        requestPeers();
+    }
+
+    private void handleConnectionChanged(NetworkInfo networkInfo) {
+        mNetworkInfo = networkInfo;
+        if (mWfdEnabled && networkInfo.isConnected()) {
+            if (mDesiredDevice != null) {
+                mWifiP2pManager.requestGroupInfo(mWifiP2pChannel, new GroupInfoListener() {
+                    @Override
+                    public void onGroupInfoAvailable(WifiP2pGroup info) {
+                        if (DEBUG) {
+                            Slog.d(TAG, "Received group info: " + describeWifiP2pGroup(info));
+                        }
+
+                        if (mConnectingDevice != null && !info.contains(mConnectingDevice)) {
+                            Slog.i(TAG, "Aborting connection to Wifi display because "
+                                    + "the current P2P group does not contain the device "
+                                    + "we expected to find: " + mConnectingDevice.deviceName
+                                    + ", group info was: " + describeWifiP2pGroup(info));
+                            handleConnectionFailure(false);
+                            return;
+                        }
+
+                        if (mDesiredDevice != null && !info.contains(mDesiredDevice)) {
+                            disconnect();
+                            return;
+                        }
+
+                        if (mConnectingDevice != null && mConnectingDevice == mDesiredDevice) {
+                            Slog.i(TAG, "Connected to Wifi display: "
+                                    + mConnectingDevice.deviceName);
+
+                            mHandler.removeCallbacks(mConnectionTimeout);
+                            mConnectedDeviceGroupInfo = info;
+                            mConnectedDevice = mConnectingDevice;
+                            mConnectingDevice = null;
+                            updateConnection();
+                        }
+                    }
+                });
+            }
+        } else {
+            disconnect();
+
+            // After disconnection for a group, for some reason we have a tendency
+            // to get a peer change notification with an empty list of peers.
+            // Perform a fresh scan.
+            if (mWfdEnabled) {
+                requestPeers();
+            }
+        }
+    }
+
+    private final Runnable mConnectionTimeout = new Runnable() {
+        @Override
+        public void run() {
+            if (mConnectingDevice != null && mConnectingDevice == mDesiredDevice) {
+                Slog.i(TAG, "Timed out waiting for Wifi display connection after "
+                        + CONNECTION_TIMEOUT_SECONDS + " seconds: "
+                        + mConnectingDevice.deviceName);
+                handleConnectionFailure(true);
+            }
+        }
+    };
+
+    private final Runnable mRtspTimeout = new Runnable() {
+        @Override
+        public void run() {
+            if (mConnectedDevice != null
+                    && mRemoteDisplay != null && !mRemoteDisplayConnected) {
+                Slog.i(TAG, "Timed out waiting for Wifi display RTSP connection after "
+                        + RTSP_TIMEOUT_SECONDS + " seconds: "
+                        + mConnectedDevice.deviceName);
+                handleConnectionFailure(true);
+            }
+        }
+    };
+
+    private void handleConnectionFailure(boolean timeoutOccurred) {
+        Slog.i(TAG, "Wifi display connection failed!");
+
+        if (mDesiredDevice != null) {
+            if (mConnectionRetriesLeft > 0) {
+                final WifiP2pDevice oldDevice = mDesiredDevice;
+                mHandler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (mDesiredDevice == oldDevice && mConnectionRetriesLeft > 0) {
+                            mConnectionRetriesLeft -= 1;
+                            Slog.i(TAG, "Retrying Wifi display connection.  Retries left: "
+                                    + mConnectionRetriesLeft);
+                            retryConnection();
+                        }
+                    }
+                }, timeoutOccurred ? 0 : CONNECT_RETRY_DELAY_MILLIS);
+            } else {
+                disconnect();
+            }
+        }
+    }
+
+    private void advertiseDisplay(final WifiDisplay display,
+            final Surface surface, final int width, final int height, final int flags) {
+        if (!Objects.equal(mAdvertisedDisplay, display)
+                || mAdvertisedDisplaySurface != surface
+                || mAdvertisedDisplayWidth != width
+                || mAdvertisedDisplayHeight != height
+                || mAdvertisedDisplayFlags != flags) {
+            final WifiDisplay oldDisplay = mAdvertisedDisplay;
+            final Surface oldSurface = mAdvertisedDisplaySurface;
+
+            mAdvertisedDisplay = display;
+            mAdvertisedDisplaySurface = surface;
+            mAdvertisedDisplayWidth = width;
+            mAdvertisedDisplayHeight = height;
+            mAdvertisedDisplayFlags = flags;
+
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    if (oldSurface != null && surface != oldSurface) {
+                        mListener.onDisplayDisconnected();
+                    } else if (oldDisplay != null && !Objects.equal(display, oldDisplay)) {
+                        mListener.onDisplayConnectionFailed();
+                    }
+
+                    if (display != null) {
+                        if (!Objects.equal(display, oldDisplay)) {
+                            mListener.onDisplayConnecting(display);
+                        }
+                        if (surface != null && surface != oldSurface) {
+                            mListener.onDisplayConnected(display, surface, width, height, flags);
+                        }
+                    }
+                }
+            });
+        }
+    }
+
+    private void unadvertiseDisplay() {
+        advertiseDisplay(null, null, 0, 0, 0);
+    }
+
+    private static Inet4Address getInterfaceAddress(WifiP2pGroup info) {
+        NetworkInterface iface;
+        try {
+            iface = NetworkInterface.getByName(info.getInterface());
+        } catch (SocketException ex) {
+            Slog.w(TAG, "Could not obtain address of network interface "
+                    + info.getInterface(), ex);
+            return null;
+        }
+
+        Enumeration<InetAddress> addrs = iface.getInetAddresses();
+        while (addrs.hasMoreElements()) {
+            InetAddress addr = addrs.nextElement();
+            if (addr instanceof Inet4Address) {
+                return (Inet4Address)addr;
+            }
+        }
+
+        Slog.w(TAG, "Could not obtain address of network interface "
+                + info.getInterface() + " because it had no IPv4 addresses.");
+        return null;
+    }
+
+    private static int getPortNumber(WifiP2pDevice device) {
+        if (device.deviceName.startsWith("DIRECT-")
+                && device.deviceName.endsWith("Broadcom")) {
+            // These dongles ignore the port we broadcast in our WFD IE.
+            return 8554;
+        }
+        return DEFAULT_CONTROL_PORT;
+    }
+
+    private static boolean isWifiDisplay(WifiP2pDevice device) {
+        return device.wfdInfo != null
+                && device.wfdInfo.isWfdEnabled()
+                && isPrimarySinkDeviceType(device.wfdInfo.getDeviceType());
+    }
+
+    private static boolean isPrimarySinkDeviceType(int deviceType) {
+        return deviceType == WifiP2pWfdInfo.PRIMARY_SINK
+                || deviceType == WifiP2pWfdInfo.SOURCE_OR_PRIMARY_SINK;
+    }
+
+    private static String describeWifiP2pDevice(WifiP2pDevice device) {
+        return device != null ? device.toString().replace('\n', ',') : "null";
+    }
+
+    private static String describeWifiP2pGroup(WifiP2pGroup group) {
+        return group != null ? group.toString().replace('\n', ',') : "null";
+    }
+
+    private static WifiDisplay createWifiDisplay(WifiP2pDevice device) {
+        return new WifiDisplay(device.deviceAddress, device.deviceName, null);
+    }
+
+    private final BroadcastReceiver mWifiP2pReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            if (action.equals(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION)) {
+                // This broadcast is sticky so we'll always get the initial Wifi P2P state
+                // on startup.
+                boolean enabled = (intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE,
+                        WifiP2pManager.WIFI_P2P_STATE_DISABLED)) ==
+                        WifiP2pManager.WIFI_P2P_STATE_ENABLED;
+                if (DEBUG) {
+                    Slog.d(TAG, "Received WIFI_P2P_STATE_CHANGED_ACTION: enabled="
+                            + enabled);
+                }
+
+                handleStateChanged(enabled);
+            } else if (action.equals(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION)) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Received WIFI_P2P_PEERS_CHANGED_ACTION.");
+                }
+
+                handlePeersChanged();
+            } else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) {
+                NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra(
+                        WifiP2pManager.EXTRA_NETWORK_INFO);
+                if (DEBUG) {
+                    Slog.d(TAG, "Received WIFI_P2P_CONNECTION_CHANGED_ACTION: networkInfo="
+                            + networkInfo);
+                }
+
+                handleConnectionChanged(networkInfo);
+            }
+        }
+    };
+
+    /**
+     * Called on the handler thread when displays are connected or disconnected.
+     */
+    public interface Listener {
+        void onFeatureStateChanged(int featureState);
+
+        void onScanStarted();
+        void onScanFinished(WifiDisplay[] availableDisplays);
+
+        void onDisplayConnecting(WifiDisplay display);
+        void onDisplayConnectionFailed();
+        void onDisplayConnected(WifiDisplay display,
+                Surface surface, int width, int height, int flags);
+        void onDisplayDisconnected();
+    }
+}
diff --git a/services/java/com/android/server/dreams/DreamController.java b/services/java/com/android/server/dreams/DreamController.java
new file mode 100644
index 0000000..1ab6a77
--- /dev/null
+++ b/services/java/com/android/server/dreams/DreamController.java
@@ -0,0 +1,255 @@
+/*
+ * 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.dreams;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.IBinder.DeathRecipient;
+import android.os.UserHandle;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamService;
+import android.util.Slog;
+import android.view.IWindowManager;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+
+import java.io.PrintWriter;
+import java.util.NoSuchElementException;
+
+/**
+ * Internal controller for starting and stopping the current dream and managing related state.
+ *
+ * Assumes all operations are called from the dream handler thread.
+ */
+final class DreamController {
+    private static final String TAG = "DreamController";
+
+    private final Context mContext;
+    private final Handler mHandler;
+    private final Listener mListener;
+    private final IWindowManager mIWindowManager;
+
+    private final Intent mDreamingStartedIntent = new Intent(Intent.ACTION_DREAMING_STARTED)
+            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+    private final Intent mDreamingStoppedIntent = new Intent(Intent.ACTION_DREAMING_STOPPED)
+            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+
+    private final Intent mCloseNotificationShadeIntent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+
+    private DreamRecord mCurrentDream;
+
+    public DreamController(Context context, Handler handler, Listener listener) {
+        mContext = context;
+        mHandler = handler;
+        mListener = listener;
+        mIWindowManager = WindowManagerGlobal.getWindowManagerService();
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.println("Dreamland:");
+        if (mCurrentDream != null) {
+            pw.println("  mCurrentDream:");
+            pw.println("    mToken=" + mCurrentDream.mToken);
+            pw.println("    mName=" + mCurrentDream.mName);
+            pw.println("    mIsTest=" + mCurrentDream.mIsTest);
+            pw.println("    mUserId=" + mCurrentDream.mUserId);
+            pw.println("    mBound=" + mCurrentDream.mBound);
+            pw.println("    mService=" + mCurrentDream.mService);
+            pw.println("    mSentStartBroadcast=" + mCurrentDream.mSentStartBroadcast);
+        } else {
+            pw.println("  mCurrentDream: null");
+        }
+    }
+
+    public void startDream(Binder token, ComponentName name, boolean isTest, int userId) {
+        stopDream();
+
+        // Close the notification shade. Don't need to send to all, but better to be explicit.
+        mContext.sendBroadcastAsUser(mCloseNotificationShadeIntent, UserHandle.ALL);
+
+        Slog.i(TAG, "Starting dream: name=" + name + ", isTest=" + isTest + ", userId=" + userId);
+
+        mCurrentDream = new DreamRecord(token, name, isTest, userId);
+
+        try {
+            mIWindowManager.addWindowToken(token, WindowManager.LayoutParams.TYPE_DREAM);
+        } catch (RemoteException ex) {
+            Slog.e(TAG, "Unable to add window token for dream.", ex);
+            stopDream();
+            return;
+        }
+
+        Intent intent = new Intent(DreamService.SERVICE_INTERFACE);
+        intent.setComponent(name);
+        intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+        try {
+            if (!mContext.bindService(intent, mCurrentDream,
+                    Context.BIND_AUTO_CREATE, userId)) {
+                Slog.e(TAG, "Unable to bind dream service: " + intent);
+                stopDream();
+                return;
+            }
+        } catch (SecurityException ex) {
+            Slog.e(TAG, "Unable to bind dream service: " + intent, ex);
+            stopDream();
+            return;
+        }
+
+        mCurrentDream.mBound = true;
+    }
+
+    public void stopDream() {
+        if (mCurrentDream == null) {
+            return;
+        }
+
+        final DreamRecord oldDream = mCurrentDream;
+        mCurrentDream = null;
+        Slog.i(TAG, "Stopping dream: name=" + oldDream.mName
+                + ", isTest=" + oldDream.mIsTest + ", userId=" + oldDream.mUserId);
+
+        if (oldDream.mSentStartBroadcast) {
+            mContext.sendBroadcastAsUser(mDreamingStoppedIntent, UserHandle.ALL);
+        }
+
+        if (oldDream.mService != null) {
+            // Tell the dream that it's being stopped so that
+            // it can shut down nicely before we yank its window token out from
+            // under it.
+            try {
+                oldDream.mService.detach();
+            } catch (RemoteException ex) {
+                // we don't care; this thing is on the way out
+            }
+
+            try {
+                oldDream.mService.asBinder().unlinkToDeath(oldDream, 0);
+            } catch (NoSuchElementException ex) {
+                // don't care
+            }
+            oldDream.mService = null;
+        }
+
+        if (oldDream.mBound) {
+            mContext.unbindService(oldDream);
+        }
+
+        try {
+            mIWindowManager.removeWindowToken(oldDream.mToken);
+        } catch (RemoteException ex) {
+            Slog.w(TAG, "Error removing window token for dream.", ex);
+        }
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mListener.onDreamStopped(oldDream.mToken);
+            }
+        });
+    }
+
+    private void attach(IDreamService service) {
+        try {
+            service.asBinder().linkToDeath(mCurrentDream, 0);
+            service.attach(mCurrentDream.mToken);
+        } catch (RemoteException ex) {
+            Slog.e(TAG, "The dream service died unexpectedly.", ex);
+            stopDream();
+            return;
+        }
+
+        mCurrentDream.mService = service;
+
+        if (!mCurrentDream.mIsTest) {
+            mContext.sendBroadcastAsUser(mDreamingStartedIntent, UserHandle.ALL);
+            mCurrentDream.mSentStartBroadcast = true;
+        }
+    }
+
+    /**
+     * Callback interface to be implemented by the {@link DreamManagerService}.
+     */
+    public interface Listener {
+        void onDreamStopped(Binder token);
+    }
+
+    private final class DreamRecord implements DeathRecipient, ServiceConnection {
+        public final Binder mToken;
+        public final ComponentName mName;
+        public final boolean mIsTest;
+        public final int mUserId;
+
+        public boolean mBound;
+        public IDreamService mService;
+        public boolean mSentStartBroadcast;
+
+        public DreamRecord(Binder token, ComponentName name,
+                boolean isTest, int userId) {
+            mToken = token;
+            mName = name;
+            mIsTest = isTest;
+            mUserId  = userId;
+        }
+
+        // May be called on any thread.
+        @Override
+        public void binderDied() {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mService = null;
+                    if (mCurrentDream == DreamRecord.this) {
+                        stopDream();
+                    }
+                }
+            });
+        }
+
+        // May be called on any thread.
+        @Override
+        public void onServiceConnected(ComponentName name, final IBinder service) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    if (mCurrentDream == DreamRecord.this && mService == null) {
+                        attach(IDreamService.Stub.asInterface(service));
+                    }
+                }
+            });
+        }
+
+        // May be called on any thread.
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mService = null;
+                    if (mCurrentDream == DreamRecord.this) {
+                        stopDream();
+                    }
+                }
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/dreams/DreamManagerService.java b/services/java/com/android/server/dreams/DreamManagerService.java
new file mode 100644
index 0000000..1f40176
--- /dev/null
+++ b/services/java/com/android/server/dreams/DreamManagerService.java
@@ -0,0 +1,383 @@
+/*
+ * 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.dreams;
+
+import com.android.internal.util.DumpUtils;
+
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.dreams.IDreamManager;
+import android.util.Slog;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+import libcore.util.Objects;
+
+/**
+ * Service api for managing dreams.
+ *
+ * @hide
+ */
+public final class DreamManagerService extends IDreamManager.Stub {
+    private static final boolean DEBUG = true;
+    private static final String TAG = "DreamManagerService";
+
+    private final Object mLock = new Object();
+
+    private final Context mContext;
+    private final DreamHandler mHandler;
+    private final DreamController mController;
+    private final PowerManager mPowerManager;
+
+    private Binder mCurrentDreamToken;
+    private ComponentName mCurrentDreamName;
+    private int mCurrentDreamUserId;
+    private boolean mCurrentDreamIsTest;
+
+    public DreamManagerService(Context context, Handler mainHandler) {
+        mContext = context;
+        mHandler = new DreamHandler(mainHandler.getLooper());
+        mController = new DreamController(context, mHandler, mControllerListener);
+
+        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+    }
+
+    public void systemReady() {
+        mContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                synchronized (mLock) {
+                    stopDreamLocked();
+                }
+            }
+        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+
+        pw.println("DREAM MANAGER (dumpsys dreams)");
+        pw.println();
+
+        pw.println("mCurrentDreamToken=" + mCurrentDreamToken);
+        pw.println("mCurrentDreamName=" + mCurrentDreamName);
+        pw.println("mCurrentDreamUserId=" + mCurrentDreamUserId);
+        pw.println("mCurrentDreamIsTest=" + mCurrentDreamIsTest);
+        pw.println();
+
+        DumpUtils.dumpAsync(mHandler, new DumpUtils.Dump() {
+            @Override
+            public void dump(PrintWriter pw) {
+                mController.dump(pw);
+            }
+        }, pw, 200);
+    }
+
+    @Override // Binder call
+    public ComponentName[] getDreamComponents() {
+        checkPermission(android.Manifest.permission.READ_DREAM_STATE);
+
+        final int userId = UserHandle.getCallingUserId();
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            return getDreamComponentsForUser(userId);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @Override // Binder call
+    public void setDreamComponents(ComponentName[] componentNames) {
+        checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
+
+        final int userId = UserHandle.getCallingUserId();
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            Settings.Secure.putStringForUser(mContext.getContentResolver(),
+                    Settings.Secure.SCREENSAVER_COMPONENTS,
+                    componentsToString(componentNames),
+                    userId);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @Override // Binder call
+    public ComponentName getDefaultDreamComponent() {
+        checkPermission(android.Manifest.permission.READ_DREAM_STATE);
+
+        final int userId = UserHandle.getCallingUserId();
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            String name = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+                    Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
+                    userId);
+            return name == null ? null : ComponentName.unflattenFromString(name);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @Override // Binder call
+    public boolean isDreaming() {
+        checkPermission(android.Manifest.permission.READ_DREAM_STATE);
+
+        synchronized (mLock) {
+            return mCurrentDreamToken != null && !mCurrentDreamIsTest;
+        }
+    }
+
+    @Override // Binder call
+    public void dream() {
+        checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            // Ask the power manager to nap.  It will eventually call back into
+            // startDream() if/when it is appropriate to start dreaming.
+            // Because napping could cause the screen to turn off immediately if the dream
+            // cannot be started, we keep one eye open and gently poke user activity.
+            long time = SystemClock.uptimeMillis();
+            mPowerManager.userActivity(time, true /*noChangeLights*/);
+            mPowerManager.nap(time);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @Override // Binder call
+    public void testDream(ComponentName dream) {
+        checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
+
+        if (dream == null) {
+            throw new IllegalArgumentException("dream must not be null");
+        }
+
+        final int callingUserId = UserHandle.getCallingUserId();
+        final int currentUserId = ActivityManager.getCurrentUser();
+        if (callingUserId != currentUserId) {
+            // This check is inherently prone to races but at least it's something.
+            Slog.w(TAG, "Aborted attempt to start a test dream while a different "
+                    + " user is active: callingUserId=" + callingUserId
+                    + ", currentUserId=" + currentUserId);
+            return;
+        }
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                startDreamLocked(dream, true /*isTest*/, callingUserId);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @Override // Binder call
+    public void awaken() {
+        checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            // Treat an explicit request to awaken as user activity so that the
+            // device doesn't immediately go to sleep if the timeout expired,
+            // for example when being undocked.
+            long time = SystemClock.uptimeMillis();
+            mPowerManager.userActivity(time, false /*noChangeLights*/);
+            stopDream();
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @Override // Binder call
+    public void finishSelf(IBinder token) {
+        // Requires no permission, called by Dream from an arbitrary process.
+        if (token == null) {
+            throw new IllegalArgumentException("token must not be null");
+        }
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            if (DEBUG) {
+                Slog.d(TAG, "Dream finished: " + token);
+            }
+
+            // Note that a dream finishing and self-terminating is not
+            // itself considered user activity.  If the dream is ending because
+            // the user interacted with the device then user activity will already
+            // have been poked so the device will stay awake a bit longer.
+            // If the dream is ending on its own for other reasons and no wake
+            // locks are held and the user activity timeout has expired then the
+            // device may simply go to sleep.
+            synchronized (mLock) {
+                if (mCurrentDreamToken == token) {
+                    stopDreamLocked();
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    /**
+     * Called by the power manager to start a dream.
+     */
+    public void startDream() {
+        int userId = ActivityManager.getCurrentUser();
+        ComponentName dream = chooseDreamForUser(userId);
+        if (dream != null) {
+            synchronized (mLock) {
+                startDreamLocked(dream, false /*isTest*/, userId);
+            }
+        }
+    }
+
+    /**
+     * Called by the power manager to stop a dream.
+     */
+    public void stopDream() {
+        synchronized (mLock) {
+            stopDreamLocked();
+        }
+    }
+
+    private ComponentName chooseDreamForUser(int userId) {
+        ComponentName[] dreams = getDreamComponentsForUser(userId);
+        return dreams != null && dreams.length != 0 ? dreams[0] : null;
+    }
+
+    private ComponentName[] getDreamComponentsForUser(int userId) {
+        String names = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+                Settings.Secure.SCREENSAVER_COMPONENTS,
+                userId);
+        return names == null ? null : componentsFromString(names);
+    }
+
+    private void startDreamLocked(final ComponentName name,
+            final boolean isTest, final int userId) {
+        if (Objects.equal(mCurrentDreamName, name)
+                && mCurrentDreamIsTest == isTest
+                && mCurrentDreamUserId == userId) {
+            return;
+        }
+
+        stopDreamLocked();
+
+        Slog.i(TAG, "Entering dreamland.");
+
+        final Binder newToken = new Binder();
+        mCurrentDreamToken = newToken;
+        mCurrentDreamName = name;
+        mCurrentDreamIsTest = isTest;
+        mCurrentDreamUserId = userId;
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mController.startDream(newToken, name, isTest, userId);
+            }
+        });
+    }
+
+    private void stopDreamLocked() {
+        if (mCurrentDreamToken != null) {
+            Slog.i(TAG, "Leaving dreamland.");
+
+            cleanupDreamLocked();
+
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mController.stopDream();
+                }
+            });
+        }
+    }
+
+    private void cleanupDreamLocked() {
+        mCurrentDreamToken = null;
+        mCurrentDreamName = null;
+        mCurrentDreamIsTest = false;
+        mCurrentDreamUserId = 0;
+    }
+
+    private void checkPermission(String permission) {
+        if (mContext.checkCallingOrSelfPermission(permission)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
+                    + ", must have permission " + permission);
+        }
+    }
+
+    private static String componentsToString(ComponentName[] componentNames) {
+        StringBuilder names = new StringBuilder();
+        if (componentNames != null) {
+            for (ComponentName componentName : componentNames) {
+                if (names.length() > 0) {
+                    names.append(',');
+                }
+                names.append(componentName.flattenToString());
+            }
+        }
+        return names.toString();
+    }
+
+    private static ComponentName[] componentsFromString(String names) {
+        String[] namesArray = names.split(",");
+        ComponentName[] componentNames = new ComponentName[namesArray.length];
+        for (int i = 0; i < namesArray.length; i++) {
+            componentNames[i] = ComponentName.unflattenFromString(namesArray[i]);
+        }
+        return componentNames;
+    }
+
+    private final DreamController.Listener mControllerListener = new DreamController.Listener() {
+        @Override
+        public void onDreamStopped(Binder token) {
+            synchronized (mLock) {
+                if (mCurrentDreamToken == token) {
+                    cleanupDreamLocked();
+                }
+            }
+        }
+    };
+
+    /**
+     * Handler for asynchronous operations performed by the dream manager.
+     * Ensures operations to {@link DreamController} are single-threaded.
+     */
+    private final class DreamHandler extends Handler {
+        public DreamHandler(Looper looper) {
+            super(looper, null, true /*async*/);
+        }
+    }
+}
diff --git a/services/java/com/android/server/input/InputFilter.java b/services/java/com/android/server/input/InputFilter.java
deleted file mode 100644
index 2ce0a02..0000000
--- a/services/java/com/android/server/input/InputFilter.java
+++ /dev/null
@@ -1,258 +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.
- */
-
-package com.android.server.input;
-
-import com.android.server.wm.WindowManagerService;
-
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.view.InputEvent;
-import android.view.InputEventConsistencyVerifier;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.WindowManagerPolicy;
-
-/**
- * Filters input events before they are dispatched to the system.
- * <p>
- * At most one input filter can be installed by calling
- * {@link WindowManagerService#setInputFilter}.  When an input filter is installed, the
- * system's behavior changes as follows:
- * <ul>
- * <li>Input events are first delivered to the {@link WindowManagerPolicy}
- * interception methods before queuing as usual.  This critical step takes care of managing
- * the power state of the device and handling wake keys.</li>
- * <li>Input events are then asynchronously delivered to the input filter's
- * {@link #onInputEvent(InputEvent)} method instead of being enqueued for dispatch to
- * applications as usual.  The input filter only receives input events that were
- * generated by input device; the input filter will not receive input events that were
- * injected into the system by other means, such as by instrumentation.</li>
- * <li>The input filter processes and optionally transforms the stream of events.  For example,
- * it may transform a sequence of motion events representing an accessibility gesture into
- * a different sequence of motion events, key presses or other system-level interactions.
- * The input filter can send events to be dispatched by calling
- * {@link #sendInputEvent(InputEvent)} and passing appropriate policy flags for the
- * input event.</li>
- * </ul>
- * </p>
- * <h3>The importance of input event consistency</h3>
- * <p>
- * The input filter mechanism is very low-level.  At a minimum, it needs to ensure that it
- * sends an internally consistent stream of input events to the dispatcher.  There are
- * very important invariants to be maintained.
- * </p><p>
- * For example, if a key down is sent, a corresponding key up should also be sent eventually.
- * Likewise, for touch events, each pointer must individually go down with
- * {@link MotionEvent#ACTION_DOWN} or {@link MotionEvent#ACTION_POINTER_DOWN} and then
- * individually go up with {@link MotionEvent#ACTION_POINTER_UP} or {@link MotionEvent#ACTION_UP}
- * and the sequence of pointer ids used must be consistent throughout the gesture.
- * </p><p>
- * Sometimes a filter may wish to cancel a previously dispatched key or motion.  It should
- * use {@link KeyEvent#FLAG_CANCELED} or {@link MotionEvent#ACTION_CANCEL} accordingly.
- * </p><p>
- * The input filter must take into account the fact that the input events coming from different
- * devices or even different sources all consist of distinct streams of input.
- * Use {@link InputEvent#getDeviceId()} and {@link InputEvent#getSource()} to identify
- * the source of the event and its semantics.  There are be multiple sources of keys,
- * touches and other input: they must be kept separate.
- * </p>
- * <h3>Policy flags</h3>
- * <p>
- * Input events received from the dispatcher and sent to the dispatcher have policy flags
- * associated with them.  Policy flags control some functions of the dispatcher.
- * </p><p>
- * The early policy interception decides whether an input event should be delivered
- * to applications or dropped.  The policy indicates its decision by setting the
- * {@link WindowManagerPolicy#FLAG_PASS_TO_USER} policy flag.  The input filter may
- * sometimes receive events that do not have this flag set.  It should take note of
- * the fact that the policy intends to drop the event, clean up its state, and
- * then send appropriate cancellation events to the dispatcher if needed.
- * </p><p>
- * For example, suppose the input filter is processing a gesture and one of the touch events
- * it receives does not have the {@link WindowManagerPolicy#FLAG_PASS_TO_USER} flag set.
- * The input filter should clear its internal state about the gesture and then send key or
- * motion events to the dispatcher to cancel any keys or pointers that are down.
- * </p><p>
- * Corollary: Events that set sent to the dispatcher should usually include the
- * {@link WindowManagerPolicy#FLAG_PASS_TO_USER} flag.  Otherwise, they will be dropped!
- * </p><p>
- * It may be prudent to disable automatic key repeating for synthetic key events
- * by setting the {@link WindowManagerPolicy#FLAG_DISABLE_KEY_REPEAT} policy flag.
- * </p>
- */
-public abstract class InputFilter {
-    private static final int MSG_INSTALL = 1;
-    private static final int MSG_UNINSTALL = 2;
-    private static final int MSG_INPUT_EVENT = 3;
-
-    private final H mH;
-    private Host mHost;
-
-    // Consistency verifiers for debugging purposes.
-    private final InputEventConsistencyVerifier mInboundInputEventConsistencyVerifier =
-            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
-                    new InputEventConsistencyVerifier(this,
-                            InputEventConsistencyVerifier.FLAG_RAW_DEVICE_INPUT,
-                            "InputFilter#InboundInputEventConsistencyVerifier") : null;
-    private final InputEventConsistencyVerifier mOutboundInputEventConsistencyVerifier =
-            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
-                    new InputEventConsistencyVerifier(this,
-                            InputEventConsistencyVerifier.FLAG_RAW_DEVICE_INPUT,
-                            "InputFilter#OutboundInputEventConsistencyVerifier") : null;
-
-    /**
-     * Creates the input filter.
-     *
-     * @param looper The looper to run callbacks on.
-     */
-    public InputFilter(Looper looper) {
-        mH = new H(looper);
-    }
-
-    /**
-     * Called when the input filter is installed.
-     * This method is guaranteed to be non-reentrant.
-     *
-     * @param host The input filter host environment.
-     */
-    final void install(Host host) {
-        mH.obtainMessage(MSG_INSTALL, host).sendToTarget();
-    }
-
-    /**
-     * Called when the input filter is uninstalled.
-     * This method is guaranteed to be non-reentrant.
-     */
-    final void uninstall() {
-        mH.obtainMessage(MSG_UNINSTALL).sendToTarget();
-    }
-
-    /**
-     * Called to enqueue the input event for filtering.
-     * The event will be recycled after the input filter processes it.
-     * This method is guaranteed to be non-reentrant.
-     *
-     * @param event The input event to enqueue.
-     */
-    final void filterInputEvent(InputEvent event, int policyFlags) {
-        mH.obtainMessage(MSG_INPUT_EVENT, policyFlags, 0, event).sendToTarget();
-    }
-
-    /**
-     * Sends an input event to the dispatcher.
-     *
-     * @param event The input event to publish.
-     * @param policyFlags The input event policy flags.
-     */
-    public void sendInputEvent(InputEvent event, int policyFlags) {
-        if (event == null) {
-            throw new IllegalArgumentException("event must not be null");
-        }
-        if (mHost == null) {
-            throw new IllegalStateException("Cannot send input event because the input filter " +
-                    "is not installed.");
-        }
-        if (mOutboundInputEventConsistencyVerifier != null) {
-            mOutboundInputEventConsistencyVerifier.onInputEvent(event, 0);
-        }
-        mHost.sendInputEvent(event, policyFlags);
-    }
-
-    /**
-     * Called when an input event has been received from the dispatcher.
-     * <p>
-     * The default implementation sends the input event back to the dispatcher, unchanged.
-     * </p><p>
-     * The event will be recycled when this method returns.  If you want to keep it around,
-     * make a copy!
-     * </p>
-     *
-     * @param event The input event that was received.
-     * @param policyFlags The input event policy flags.
-     */
-    public void onInputEvent(InputEvent event, int policyFlags) {
-        sendInputEvent(event, policyFlags);
-    }
-
-    /**
-     * Called when the filter is installed into the dispatch pipeline.
-     * <p>
-     * This method is called before the input filter receives any input events.
-     * The input filter should take this opportunity to prepare itself.
-     * </p>
-     */
-    public void onInstalled() {
-    }
-
-    /**
-     * Called when the filter is uninstalled from the dispatch pipeline.
-     * <p>
-     * This method is called after the input filter receives its last input event.
-     * The input filter should take this opportunity to clean up.
-     * </p>
-     */
-    public void onUninstalled() {
-    }
-
-    private final class H extends Handler {
-        public H(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_INSTALL:
-                    mHost = (Host)msg.obj;
-                    if (mInboundInputEventConsistencyVerifier != null) {
-                        mInboundInputEventConsistencyVerifier.reset();
-                    }
-                    if (mOutboundInputEventConsistencyVerifier != null) {
-                        mOutboundInputEventConsistencyVerifier.reset();
-                    }
-                    onInstalled();
-                    break;
-
-                case MSG_UNINSTALL:
-                    try {
-                        onUninstalled();
-                    } finally {
-                        mHost = null;
-                    }
-                    break;
-
-                case MSG_INPUT_EVENT: {
-                    final InputEvent event = (InputEvent)msg.obj;
-                    try {
-                        if (mInboundInputEventConsistencyVerifier != null) {
-                            mInboundInputEventConsistencyVerifier.onInputEvent(event, 0);
-                        }
-                        onInputEvent(event, msg.arg1);
-                    } finally {
-                        event.recycle();
-                    }
-                    break;
-                }
-            }
-        }
-    }
-
-    interface Host {
-        public void sendInputEvent(InputEvent event, int policyFlags);
-    }
-}
diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java
index bdd0aa4..5e4907e 100644
--- a/services/java/com/android/server/input/InputManagerService.java
+++ b/services/java/com/android/server/input/InputManagerService.java
@@ -19,6 +19,8 @@
 import com.android.internal.R;
 import com.android.internal.util.XmlUtils;
 import com.android.server.Watchdog;
+import com.android.server.display.DisplayManagerService;
+import com.android.server.display.DisplayViewport;
 
 import org.xmlpull.v1.XmlPullParser;
 
@@ -42,8 +44,8 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.database.ContentObserver;
-import android.hardware.input.IInputManager;
 import android.hardware.input.IInputDevicesChangedListener;
+import android.hardware.input.IInputManager;
 import android.hardware.input.InputManager;
 import android.hardware.input.KeyboardLayout;
 import android.os.Binder;
@@ -51,23 +53,25 @@
 import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
 import android.os.MessageQueue;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
-import android.server.BluetoothService;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.Xml;
+import android.view.IInputFilter;
+import android.view.IInputFilterHost;
 import android.view.InputChannel;
 import android.view.InputDevice;
 import android.view.InputEvent;
 import android.view.KeyEvent;
 import android.view.PointerIcon;
-import android.view.Surface;
 import android.view.ViewConfiguration;
 import android.view.WindowManagerPolicy;
 import android.widget.Toast;
@@ -89,7 +93,8 @@
 /*
  * Wraps the C++ InputManager and provides its callbacks.
  */
-public class InputManagerService extends IInputManager.Stub implements Watchdog.Monitor {
+public class InputManagerService extends IInputManager.Stub
+        implements Watchdog.Monitor, DisplayManagerService.InputManagerFuncs {
     static final String TAG = "InputManager";
     static final boolean DEBUG = false;
 
@@ -105,10 +110,11 @@
     private final int mPtr;
 
     private final Context mContext;
-    private final Callbacks mCallbacks;
     private final InputManagerHandler mHandler;
+
+    private WindowManagerCallbacks mWindowManagerCallbacks;
+    private WiredAccessoryCallbacks mWiredAccessoryCallbacks;
     private boolean mSystemReady;
-    private BluetoothService mBluetoothService;
     private NotificationManager mNotificationManager;
 
     // Persistent data store.  Must be locked each time during use.
@@ -137,17 +143,18 @@
 
     // State for the currently installed input filter.
     final Object mInputFilterLock = new Object();
-    InputFilter mInputFilter; // guarded by mInputFilterLock
+    IInputFilter mInputFilter; // guarded by mInputFilterLock
     InputFilterHost mInputFilterHost; // guarded by mInputFilterLock
 
     private static native int nativeInit(InputManagerService service,
             Context context, MessageQueue messageQueue);
     private static native void nativeStart(int ptr);
-    private static native void nativeSetDisplaySize(int ptr, int displayId,
-            int width, int height, int externalWidth, int externalHeight);
-    private static native void nativeSetDisplayOrientation(int ptr, int displayId,
-            int rotation, int externalRotation);
-    
+    private static native void nativeSetDisplayViewport(int ptr, boolean external,
+            int displayId, int rotation,
+            int logicalLeft, int logicalTop, int logicalRight, int logicalBottom,
+            int physicalLeft, int physicalTop, int physicalRight, int physicalBottom,
+            int deviceWidth, int deviceHeight);
+
     private static native int nativeGetScanCodeState(int ptr,
             int deviceId, int sourceMask, int scanCode);
     private static native int nativeGetKeyCodeState(int ptr,
@@ -191,7 +198,7 @@
 
     // Key states (may be returned by queries about the current state of a
     // particular key code, scan code or switch).
-    
+
     /** The key state is unknown or the requested key itself is not supported. */
     public static final int KEY_STATE_UNKNOWN = -1;
 
@@ -207,21 +214,52 @@
     /** Scan code: Mouse / trackball button. */
     public static final int BTN_MOUSE = 0x110;
 
+    // Switch code values must match bionic/libc/kernel/common/linux/input.h
     /** Switch code: Lid switch.  When set, lid is shut. */
     public static final int SW_LID = 0x00;
 
     /** Switch code: Keypad slide.  When set, keyboard is exposed. */
     public static final int SW_KEYPAD_SLIDE = 0x0a;
 
-    public InputManagerService(Context context, Callbacks callbacks) {
-        this.mContext = context;
-        this.mCallbacks = callbacks;
-        this.mHandler = new InputManagerHandler();
+    /** Switch code: Headphone.  When set, headphone is inserted. */
+    public static final int SW_HEADPHONE_INSERT = 0x02;
 
-        Slog.i(TAG, "Initializing input manager");
+    /** Switch code: Microphone.  When set, microphone is inserted. */
+    public static final int SW_MICROPHONE_INSERT = 0x04;
+
+    /** Switch code: Headphone/Microphone Jack.  When set, something is inserted. */
+    public static final int SW_JACK_PHYSICAL_INSERT = 0x07;
+
+    public static final int SW_LID_BIT = 1 << SW_LID;
+    public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE;
+    public static final int SW_HEADPHONE_INSERT_BIT = 1 << SW_HEADPHONE_INSERT;
+    public static final int SW_MICROPHONE_INSERT_BIT = 1 << SW_MICROPHONE_INSERT;
+    public static final int SW_JACK_PHYSICAL_INSERT_BIT = 1 << SW_JACK_PHYSICAL_INSERT;
+    public static final int SW_JACK_BITS =
+            SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_JACK_PHYSICAL_INSERT_BIT;
+
+    /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */
+    final boolean mUseDevInputEventForAudioJack;
+
+    public InputManagerService(Context context, Handler handler) {
+        this.mContext = context;
+        this.mHandler = new InputManagerHandler(handler.getLooper());
+
+        mUseDevInputEventForAudioJack =
+                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
+        Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
+                + mUseDevInputEventForAudioJack);
         mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
     }
 
+    public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
+        mWindowManagerCallbacks = callbacks;
+    }
+
+    public void setWiredAccessoryCallbacks(WiredAccessoryCallbacks callbacks) {
+        mWiredAccessoryCallbacks = callbacks;
+    }
+
     public void start() {
         Slog.i(TAG, "Starting input manager");
         nativeStart(mPtr);
@@ -232,15 +270,23 @@
         registerPointerSpeedSettingObserver();
         registerShowTouchesSettingObserver();
 
+        mContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                updatePointerSpeedFromSettings();
+                updateShowTouchesFromSettings();
+            }
+        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
+
         updatePointerSpeedFromSettings();
         updateShowTouchesFromSettings();
     }
 
-    public void systemReady(BluetoothService bluetoothService) {
+    // TODO(BT) Pass in paramter for bluetooth system
+    public void systemReady() {
         if (DEBUG) {
             Slog.d(TAG, "System ready.");
         }
-        mBluetoothService = bluetoothService;
         mNotificationManager = (NotificationManager)mContext.getSystemService(
                 Context.NOTIFICATION_SERVICE);
         mSystemReady = true;
@@ -282,29 +328,28 @@
         nativeReloadDeviceAliases(mPtr);
     }
 
-    public void setDisplaySize(int displayId, int width, int height,
-            int externalWidth, int externalHeight) {
-        if (width <= 0 || height <= 0 || externalWidth <= 0 || externalHeight <= 0) {
-            throw new IllegalArgumentException("Invalid display id or dimensions.");
+    @Override
+    public void setDisplayViewports(DisplayViewport defaultViewport,
+            DisplayViewport externalTouchViewport) {
+        if (defaultViewport.valid) {
+            setDisplayViewport(false, defaultViewport);
         }
-        
-        if (DEBUG) {
-            Slog.d(TAG, "Setting display #" + displayId + " size to " + width + "x" + height
-                    + " external size " + externalWidth + "x" + externalHeight);
+
+        if (externalTouchViewport.valid) {
+            setDisplayViewport(true, externalTouchViewport);
+        } else if (defaultViewport.valid) {
+            setDisplayViewport(true, defaultViewport);
         }
-        nativeSetDisplaySize(mPtr, displayId, width, height, externalWidth, externalHeight);
     }
-    
-    public void setDisplayOrientation(int displayId, int rotation, int externalRotation) {
-        if (rotation < Surface.ROTATION_0 || rotation > Surface.ROTATION_270) {
-            throw new IllegalArgumentException("Invalid rotation.");
-        }
-        
-        if (DEBUG) {
-            Slog.d(TAG, "Setting display #" + displayId + " orientation to rotation " + rotation
-                    + " external rotation " + externalRotation);
-        }
-        nativeSetDisplayOrientation(mPtr, displayId, rotation, externalRotation);
+
+    private void setDisplayViewport(boolean external, DisplayViewport viewport) {
+        nativeSetDisplayViewport(mPtr, external,
+                viewport.displayId, viewport.orientation,
+                viewport.logicalFrame.left, viewport.logicalFrame.top,
+                viewport.logicalFrame.right, viewport.logicalFrame.bottom,
+                viewport.physicalFrame.left, viewport.physicalFrame.top,
+                viewport.physicalFrame.right, viewport.physicalFrame.bottom,
+                viewport.deviceWidth, viewport.deviceHeight);
     }
 
     /**
@@ -319,7 +364,7 @@
     public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) {
         return nativeGetKeyCodeState(mPtr, deviceId, sourceMask, keyCode);
     }
-    
+
     /**
      * Gets the current state of a key or button by scan code.
      * @param deviceId The input device id, or -1 to consult all devices.
@@ -425,9 +470,9 @@
      *
      * @param filter The input filter, or null to remove the current filter.
      */
-    public void setInputFilter(InputFilter filter) {
+    public void setInputFilter(IInputFilter filter) {
         synchronized (mInputFilterLock) {
-            final InputFilter oldFilter = mInputFilter;
+            final IInputFilter oldFilter = mInputFilter;
             if (oldFilter == filter) {
                 return; // nothing to do
             }
@@ -436,13 +481,21 @@
                 mInputFilter = null;
                 mInputFilterHost.disconnectLocked();
                 mInputFilterHost = null;
-                oldFilter.uninstall();
+                try {
+                    oldFilter.uninstall();
+                } catch (RemoteException re) {
+                    /* ignore */
+                }
             }
 
             if (filter != null) {
                 mInputFilter = filter;
                 mInputFilterHost = new InputFilterHost();
-                filter.install(mInputFilterHost);
+                try {
+                    filter.install(mInputFilterHost);
+                } catch (RemoteException re) {
+                    /* ignore */
+                }
             }
 
             nativeSetInputFilterEnabled(mPtr, filter != null);
@@ -489,7 +542,7 @@
 
     /**
      * Gets information about the input device with the specified id.
-     * @param id The device id.
+     * @param deviceId The device id.
      * @return The input device or null if not found.
      */
     @Override // Binder call
@@ -645,7 +698,8 @@
                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                         | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                         | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-                mKeyboardLayoutIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
+                mKeyboardLayoutIntent = PendingIntent.getActivityAsUser(mContext, 0,
+                        intent, 0, null, UserHandle.CURRENT);
             }
 
             Resources r = mContext.getResources();
@@ -658,8 +712,9 @@
                     .setSmallIcon(R.drawable.ic_settings_language)
                     .setPriority(Notification.PRIORITY_LOW)
                     .build();
-            mNotificationManager.notify(R.string.select_keyboard_layout_notification_title,
-                    notification);
+            mNotificationManager.notifyAsUser(null,
+                    R.string.select_keyboard_layout_notification_title,
+                    notification, UserHandle.ALL);
             mKeyboardLayoutNotificationShown = true;
         }
     }
@@ -668,7 +723,9 @@
     private void hideMissingKeyboardLayoutNotification() {
         if (mKeyboardLayoutNotificationShown) {
             mKeyboardLayoutNotificationShown = false;
-            mNotificationManager.cancel(R.string.select_keyboard_layout_notification_title);
+            mNotificationManager.cancelAsUser(null,
+                    R.string.select_keyboard_layout_notification_title,
+                    UserHandle.ALL);
         }
     }
 
@@ -948,8 +1005,8 @@
     // Must be called on handler.
     private void handleSwitchKeyboardLayout(int deviceId, int direction) {
         final InputDevice device = getInputDevice(deviceId);
-        final String inputDeviceDescriptor = device.getDescriptor();
         if (device != null) {
+            final String inputDeviceDescriptor = device.getDescriptor();
             final boolean changed;
             final String keyboardLayoutDescriptor;
             synchronized (mDataStore) {
@@ -1053,14 +1110,14 @@
                     public void onChange(boolean selfChange) {
                         updatePointerSpeedFromSettings();
                     }
-                });
+                }, UserHandle.USER_ALL);
     }
 
     private int getPointerSpeedSetting() {
         int speed = InputManager.DEFAULT_POINTER_SPEED;
         try {
-            speed = Settings.System.getInt(mContext.getContentResolver(),
-                    Settings.System.POINTER_SPEED);
+            speed = Settings.System.getIntForUser(mContext.getContentResolver(),
+                    Settings.System.POINTER_SPEED, UserHandle.USER_CURRENT);
         } catch (SettingNotFoundException snfe) {
         }
         return speed;
@@ -1079,14 +1136,14 @@
                     public void onChange(boolean selfChange) {
                         updateShowTouchesFromSettings();
                     }
-                });
+                }, UserHandle.USER_ALL);
     }
 
     private int getShowTouchesSetting(int defaultValue) {
         int result = defaultValue;
         try {
-            result = Settings.System.getInt(mContext.getContentResolver(),
-                    Settings.System.SHOW_TOUCHES);
+            result = Settings.System.getIntForUser(mContext.getContentResolver(),
+                    Settings.System.SHOW_TOUCHES, UserHandle.USER_CURRENT);
         } catch (SettingNotFoundException snfe) {
         }
         return result;
@@ -1186,6 +1243,7 @@
     }
 
     // Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection).
+    @Override
     public void monitor() {
         synchronized (mInputFilterLock) { }
         nativeMonitor(mPtr);
@@ -1193,7 +1251,7 @@
 
     // Native callback.
     private void notifyConfigurationChanged(long whenNanos) {
-        mCallbacks.notifyConfigurationChanged();
+        mWindowManagerCallbacks.notifyConfigurationChanged();
     }
 
     // Native callback.
@@ -1210,26 +1268,43 @@
     }
 
     // Native callback.
-    private void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
-        mCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
+    private void notifySwitch(long whenNanos, int switchValues, int switchMask) {
+        if (DEBUG) {
+            Slog.d(TAG, "notifySwitch: values=" + Integer.toHexString(switchValues)
+                    + ", mask=" + Integer.toHexString(switchMask));
+        }
+
+        if ((switchMask & SW_LID_BIT) != 0) {
+            final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
+            mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
+        }
+
+        if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
+            mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
+                    switchMask);
+        }
     }
 
     // Native callback.
     private void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
-        mCallbacks.notifyInputChannelBroken(inputWindowHandle);
+        mWindowManagerCallbacks.notifyInputChannelBroken(inputWindowHandle);
     }
 
     // Native callback.
     private long notifyANR(InputApplicationHandle inputApplicationHandle,
             InputWindowHandle inputWindowHandle) {
-        return mCallbacks.notifyANR(inputApplicationHandle, inputWindowHandle);
+        return mWindowManagerCallbacks.notifyANR(inputApplicationHandle, inputWindowHandle);
     }
 
     // Native callback.
     final boolean filterInputEvent(InputEvent event, int policyFlags) {
         synchronized (mInputFilterLock) {
             if (mInputFilter != null) {
-                mInputFilter.filterInputEvent(event, policyFlags);
+                try {
+                    mInputFilter.filterInputEvent(event, policyFlags);
+                } catch (RemoteException e) {
+                    /* ignore */
+                }
                 return false;
             }
         }
@@ -1239,25 +1314,25 @@
 
     // Native callback.
     private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
-        return mCallbacks.interceptKeyBeforeQueueing(
+        return mWindowManagerCallbacks.interceptKeyBeforeQueueing(
                 event, policyFlags, isScreenOn);
     }
 
     // Native callback.
     private int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
-        return mCallbacks.interceptMotionBeforeQueueingWhenScreenOff(policyFlags);
+        return mWindowManagerCallbacks.interceptMotionBeforeQueueingWhenScreenOff(policyFlags);
     }
 
     // Native callback.
     private long interceptKeyBeforeDispatching(InputWindowHandle focus,
             KeyEvent event, int policyFlags) {
-        return mCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);
+        return mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);
     }
 
     // Native callback.
     private KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
             KeyEvent event, int policyFlags) {
-        return mCallbacks.dispatchUnhandledKey(focus, event, policyFlags);
+        return mWindowManagerCallbacks.dispatchUnhandledKey(focus, event, policyFlags);
     }
 
     // Native callback.
@@ -1340,7 +1415,7 @@
 
     // Native callback.
     private int getPointerLayer() {
-        return mCallbacks.getPointerLayer();
+        return mWindowManagerCallbacks.getPointerLayer();
     }
 
     // Native callback.
@@ -1384,18 +1459,17 @@
 
     // Native callback.
     private String getDeviceAlias(String uniqueId) {
-        if (mBluetoothService != null &&
-                BluetoothAdapter.checkBluetoothAddress(uniqueId)) {
-            return mBluetoothService.getRemoteAlias(uniqueId);
+        if (BluetoothAdapter.checkBluetoothAddress(uniqueId)) {
+            // TODO(BT) mBluetoothService.getRemoteAlias(uniqueId)
+            return null;
         }
         return null;
     }
 
-
     /**
      * Callback interface implemented by the Window Manager.
      */
-    public interface Callbacks {
+    public interface WindowManagerCallbacks {
         public void notifyConfigurationChanged();
 
         public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
@@ -1419,9 +1493,20 @@
     }
 
     /**
+     * Callback interface implemented by WiredAccessoryObserver.
+     */
+    public interface WiredAccessoryCallbacks {
+        public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask);
+    }
+
+    /**
      * Private handler for the input manager.
      */
     private final class InputManagerHandler extends Handler {
+        public InputManagerHandler(Looper looper) {
+            super(looper, null, true /*async*/);
+        }
+
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
@@ -1447,13 +1532,14 @@
     /**
      * Hosting interface for input filters to call back into the input manager.
      */
-    private final class InputFilterHost implements InputFilter.Host {
+    private final class InputFilterHost extends IInputFilterHost.Stub {
         private boolean mDisconnected;
 
         public void disconnectLocked() {
             mDisconnected = true;
         }
 
+        @Override
         public void sendInputEvent(InputEvent event, int policyFlags) {
             if (event == null) {
                 throw new IllegalArgumentException("event must not be null");
diff --git a/services/java/com/android/server/input/InputWindowHandle.java b/services/java/com/android/server/input/InputWindowHandle.java
index 03d66af..ad4fdd1 100644
--- a/services/java/com/android/server/input/InputWindowHandle.java
+++ b/services/java/com/android/server/input/InputWindowHandle.java
@@ -87,12 +87,16 @@
     // Window input features.
     public int inputFeatures;
 
+    // Display this input is on.
+    public final int displayId;
+
     private native void nativeDispose();
 
     public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
-            Object windowState) {
+            Object windowState, int displayId) {
         this.inputApplicationHandle = inputApplicationHandle;
         this.windowState = windowState;
+        this.displayId = displayId;
     }
 
     @Override
diff --git a/services/java/com/android/server/input/PersistentDataStore.java b/services/java/com/android/server/input/PersistentDataStore.java
index fbe3e8b..71de776 100644
--- a/services/java/com/android/server/input/PersistentDataStore.java
+++ b/services/java/com/android/server/input/PersistentDataStore.java
@@ -16,7 +16,6 @@
 
 package com.android.server.input;
 
-import com.android.internal.os.AtomicFile;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
@@ -25,6 +24,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import android.util.AtomicFile;
 import android.util.Slog;
 import android.util.Xml;
 
diff --git a/services/java/com/android/server/location/ComprehensiveCountryDetector.java b/services/java/com/android/server/location/ComprehensiveCountryDetector.java
index 1026a0d..354858b 100755
--- a/services/java/com/android/server/location/ComprehensiveCountryDetector.java
+++ b/services/java/com/android/server/location/ComprehensiveCountryDetector.java
@@ -384,8 +384,8 @@
     }
 
     protected boolean isAirplaneModeOff() {
-        return Settings.System.getInt(
-                mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) == 0;
+        return Settings.Global.getInt(
+                mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) == 0;
     }
 
     /**
diff --git a/services/java/com/android/server/location/GeocoderProxy.java b/services/java/com/android/server/location/GeocoderProxy.java
index 07f3125..f5cc59f 100644
--- a/services/java/com/android/server/location/GeocoderProxy.java
+++ b/services/java/com/android/server/location/GeocoderProxy.java
@@ -16,92 +16,65 @@
 
 package com.android.server.location;
 
-import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
 import android.location.Address;
 import android.location.GeocoderParams;
 import android.location.IGeocodeProvider;
-import android.os.IBinder;
 import android.os.RemoteException;
-import android.os.SystemClock;
+import android.os.UserHandle;
 import android.util.Log;
 
+import com.android.server.ServiceWatcher;
 import java.util.List;
 
 /**
- * A class for proxying IGeocodeProvider implementations.
- *
- * {@hide}
+ * Proxy for IGeocodeProvider implementations.
  */
 public class GeocoderProxy {
-
     private static final String TAG = "GeocoderProxy";
 
-    public static final String SERVICE_ACTION =
-        "com.android.location.service.GeocodeProvider";
+    private static final String SERVICE_ACTION = "com.android.location.service.GeocodeProvider";
 
     private final Context mContext;
-    private final Intent mIntent;
-    private final Object mMutex = new Object();  // synchronizes access to mServiceConnection
-    private Connection mServiceConnection;  // never null after ctor
+    private final ServiceWatcher mServiceWatcher;
 
-    public GeocoderProxy(Context context, String packageName) {
+    public static GeocoderProxy createAndBind(Context context,
+            List<String> initialPackageNames, int userId) {
+        GeocoderProxy proxy = new GeocoderProxy(context, initialPackageNames, userId);
+        if (proxy.bind()) {
+            return proxy;
+        } else {
+            return null;
+        }
+    }
+
+    public GeocoderProxy(Context context, List<String> initialPackageNames, int userId) {
         mContext = context;
-        mIntent = new Intent(SERVICE_ACTION);
-        reconnect(packageName);
+
+        mServiceWatcher = new ServiceWatcher(mContext, TAG, SERVICE_ACTION, initialPackageNames,
+                null, null, userId);
     }
 
-    /** Bind to service. Will reconnect if already connected */
-    public void reconnect(String packageName) {
-        synchronized (mMutex) {
-            if (mServiceConnection != null) {
-                mContext.unbindService(mServiceConnection);
-            }
-            mServiceConnection = new Connection();
-            mIntent.setPackage(packageName);
-            mContext.bindService(mIntent, mServiceConnection,
-                    Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
-                    | Context.BIND_ALLOW_OOM_MANAGEMENT);
-        }
+    private boolean bind () {
+        return mServiceWatcher.start();
     }
 
-    private class Connection implements ServiceConnection {
+    private IGeocodeProvider getService() {
+        return IGeocodeProvider.Stub.asInterface(mServiceWatcher.getBinder());
+    }
 
-        private IGeocodeProvider mProvider;
-
-        public void onServiceConnected(ComponentName className, IBinder service) {
-            synchronized (this) {
-                mProvider = IGeocodeProvider.Stub.asInterface(service);
-            }
-        }
-
-        public void onServiceDisconnected(ComponentName className) {
-            synchronized (this) {
-                mProvider = null;
-            }
-        }
-
-        public IGeocodeProvider getProvider() {
-            synchronized (this) {
-                return mProvider;
-            }
-        }
+    public String getConnectedPackageName() {
+        return mServiceWatcher.getBestPackageName();
     }
 
     public String getFromLocation(double latitude, double longitude, int maxResults,
             GeocoderParams params, List<Address> addrs) {
-        IGeocodeProvider provider;
-        synchronized (mMutex) {
-            provider = mServiceConnection.getProvider();
-        }
+        IGeocodeProvider provider = getService();
         if (provider != null) {
             try {
-                return provider.getFromLocation(latitude, longitude, maxResults,
-                        params, addrs);
+                return provider.getFromLocation(latitude, longitude, maxResults, params, addrs);
             } catch (RemoteException e) {
-                Log.e(TAG, "getFromLocation failed", e);
+                Log.w(TAG, e);
             }
         }
         return "Service not Available";
@@ -111,19 +84,17 @@
             double lowerLeftLatitude, double lowerLeftLongitude,
             double upperRightLatitude, double upperRightLongitude, int maxResults,
             GeocoderParams params, List<Address> addrs) {
-        IGeocodeProvider provider;
-        synchronized (mMutex) {
-            provider = mServiceConnection.getProvider();
-        }
+        IGeocodeProvider provider = getService();
         if (provider != null) {
             try {
                 return provider.getFromLocationName(locationName, lowerLeftLatitude,
                         lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
                         maxResults, params, addrs);
             } catch (RemoteException e) {
-                Log.e(TAG, "getFromLocationName failed", e);
+                Log.w(TAG, e);
             }
         }
         return "Service not Available";
     }
+
 }
diff --git a/services/java/com/android/server/location/GeofenceManager.java b/services/java/com/android/server/location/GeofenceManager.java
new file mode 100644
index 0000000..f9be719
--- /dev/null
+++ b/services/java/com/android/server/location/GeofenceManager.java
@@ -0,0 +1,425 @@
+/*
+ * 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.location;
+
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.location.Geofence;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.location.LocationRequest;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.util.Slog;
+
+import com.android.server.LocationManagerService;
+
+public class GeofenceManager implements LocationListener, PendingIntent.OnFinished {
+    private static final String TAG = "GeofenceManager";
+    private static final boolean D = LocationManagerService.D;
+
+    private static final int MSG_UPDATE_FENCES = 1;
+
+    /**
+     * Assume a maximum land speed, as a heuristic to throttle location updates.
+     * (Air travel should result in an airplane mode toggle which will
+     * force a new location update anyway).
+     */
+    private static final int MAX_SPEED_M_S = 100;  // 360 km/hr (high speed train)
+
+    /**
+     * Maximum age after which a location is no longer considered fresh enough to use.
+     */
+    private static final long MAX_AGE_NANOS = 5 * 60 * 1000000000L; // five minutes
+
+    /**
+     * Most frequent update interval allowed.
+     */
+    private static final long MIN_INTERVAL_MS = 1 * 60 * 1000; // one minute
+
+    /**
+     * Least frequent update interval allowed.
+     */
+    private static final long MAX_INTERVAL_MS = 2 * 60 * 60 * 1000; // two hours
+
+    private final Context mContext;
+    private final LocationManager mLocationManager;
+    private final PowerManager.WakeLock mWakeLock;
+    private final GeofenceHandler mHandler;
+    private final LocationBlacklist mBlacklist;
+
+    private Object mLock = new Object();
+
+    // access to members below is synchronized on mLock
+    /**
+     * A list containing all registered geofences.
+     */
+    private List<GeofenceState> mFences = new LinkedList<GeofenceState>();
+
+    /**
+     * This is set true when we have an active request for {@link Location} updates via
+     * {@link LocationManager#requestLocationUpdates(LocationRequest, LocationListener,
+     * android.os.Looper).
+     */
+    private boolean mReceivingLocationUpdates;
+
+    /**
+     * The update interval component of the current active {@link Location} update request.
+     */
+    private long mLocationUpdateInterval;
+
+    /**
+     * The {@link Location} most recently received via {@link #onLocationChanged(Location)}.
+     */
+    private Location mLastLocationUpdate;
+
+    /**
+     * This is set true when a {@link Location} is received via
+     * {@link #onLocationChanged(Location)} or {@link #scheduleUpdateFencesLocked()}, and cleared
+     * when that Location has been processed via {@link #updateFences()}
+     */
+    private boolean mPendingUpdate;
+
+    public GeofenceManager(Context context, LocationBlacklist blacklist) {
+        mContext = context;
+        mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
+        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+        mHandler = new GeofenceHandler();
+        mBlacklist = blacklist;
+    }
+
+    public void addFence(LocationRequest request, Geofence geofence, PendingIntent intent,
+            int uid, String packageName) {
+        if (D) {
+            Slog.d(TAG, "addFence: request=" + request + ", geofence=" + geofence
+                    + ", intent=" + intent + ", uid=" + uid + ", packageName=" + packageName);
+        }
+
+        GeofenceState state = new GeofenceState(geofence,
+                request.getExpireAt(), packageName, intent);
+        synchronized (mLock) {
+            // first make sure it doesn't already exist
+            for (int i = mFences.size() - 1; i >= 0; i--) {
+                GeofenceState w = mFences.get(i);
+                if (geofence.equals(w.mFence) && intent.equals(w.mIntent)) {
+                    // already exists, remove the old one
+                    mFences.remove(i);
+                    break;
+                }
+            }
+            mFences.add(state);
+            scheduleUpdateFencesLocked();
+        }
+    }
+
+    public void removeFence(Geofence fence, PendingIntent intent) {
+        if (D) {
+            Slog.d(TAG, "removeFence: fence=" + fence + ", intent=" + intent);
+        }
+
+        synchronized (mLock) {
+            Iterator<GeofenceState> iter = mFences.iterator();
+            while (iter.hasNext()) {
+                GeofenceState state = iter.next();
+                if (state.mIntent.equals(intent)) {
+
+                    if (fence == null) {
+                        // always remove
+                        iter.remove();
+                    } else {
+                        // just remove matching fences
+                        if (fence.equals(state.mFence)) {
+                            iter.remove();
+                        }
+                    }
+                }
+            }
+            scheduleUpdateFencesLocked();
+        }
+    }
+
+    public void removeFence(String packageName) {
+        if (D) {
+            Slog.d(TAG, "removeFence: packageName=" + packageName);
+        }
+
+        synchronized (mLock) {
+            Iterator<GeofenceState> iter = mFences.iterator();
+            while (iter.hasNext()) {
+                GeofenceState state = iter.next();
+                if (state.mPackageName.equals(packageName)) {
+                    iter.remove();
+                }
+            }
+            scheduleUpdateFencesLocked();
+        }
+    }
+
+    private void removeExpiredFencesLocked() {
+        long time = SystemClock.elapsedRealtime();
+        Iterator<GeofenceState> iter = mFences.iterator();
+        while (iter.hasNext()) {
+            GeofenceState state = iter.next();
+            if (state.mExpireAt < time) {
+                iter.remove();
+            }
+        }
+    }
+
+    private void scheduleUpdateFencesLocked() {
+        if (!mPendingUpdate) {
+            mPendingUpdate = true;
+            mHandler.sendEmptyMessage(MSG_UPDATE_FENCES);
+        }
+    }
+
+    /**
+     * Returns the location received most recently from {@link #onLocationChanged(Location)},
+     * or consult {@link LocationManager#getLastLocation()} if none has arrived. Does not return
+     * either if the location would be too stale to be useful.
+     *
+     * @return a fresh, valid Location, or null if none is available
+     */
+    private Location getFreshLocationLocked() {
+        // Prefer mLastLocationUpdate to LocationManager.getLastLocation().
+        Location location = mReceivingLocationUpdates ? mLastLocationUpdate : null;
+        if (location == null && !mFences.isEmpty()) {
+            location = mLocationManager.getLastLocation();
+        }
+
+        // Early out for null location.
+        if (location == null) {
+            return null;
+        }
+
+        // Early out for stale location.
+        long now = SystemClock.elapsedRealtimeNanos();
+        if (now - location.getElapsedRealtimeNanos() > MAX_AGE_NANOS) {
+            return null;
+        }
+
+        // Made it this far? Return our fresh, valid location.
+        return location;
+    }
+
+    /**
+     * The geofence update loop. This function removes expired fences, then tests the most
+     * recently-received {@link Location} against each registered {@link GeofenceState}, sending
+     * {@link Intent}s for geofences that have been tripped. It also adjusts the active location
+     * update request with {@link LocationManager} as appropriate for any active geofences.
+     */
+    // Runs on the handler.
+    private void updateFences() {
+        List<PendingIntent> enterIntents = new LinkedList<PendingIntent>();
+        List<PendingIntent> exitIntents = new LinkedList<PendingIntent>();
+
+        synchronized (mLock) {
+            mPendingUpdate = false;
+
+            // Remove expired fences.
+            removeExpiredFencesLocked();
+
+            // Get a location to work with, either received via onLocationChanged() or
+            // via LocationManager.getLastLocation().
+            Location location = getFreshLocationLocked();
+
+            // Update all fences.
+            // Keep track of the distance to the nearest fence.
+            double minFenceDistance = Double.MAX_VALUE;
+            boolean needUpdates = false;
+            for (GeofenceState state : mFences) {
+                if (mBlacklist.isBlacklisted(state.mPackageName)) {
+                    if (D) {
+                        Slog.d(TAG, "skipping geofence processing for blacklisted app: "
+                                + state.mPackageName);
+                    }
+                    continue;
+                }
+
+                needUpdates = true;
+                if (location != null) {
+                    int event = state.processLocation(location);
+                    if ((event & GeofenceState.FLAG_ENTER) != 0) {
+                        enterIntents.add(state.mIntent);
+                    }
+                    if ((event & GeofenceState.FLAG_EXIT) != 0) {
+                        exitIntents.add(state.mIntent);
+                    }
+
+                    // FIXME: Ideally this code should take into account the accuracy of the
+                    // location fix that was used to calculate the distance in the first place.
+                    double fenceDistance = state.getDistanceToBoundary(); // MAX_VALUE if unknown
+                    if (fenceDistance < minFenceDistance) {
+                        minFenceDistance = fenceDistance;
+                    }
+                }
+            }
+
+            // Request or cancel location updates if needed.
+            if (needUpdates) {
+                // Request location updates.
+                // Compute a location update interval based on the distance to the nearest fence.
+                long intervalMs;
+                if (location != null && Double.compare(minFenceDistance, Double.MAX_VALUE) != 0) {
+                    intervalMs = (long)Math.min(MAX_INTERVAL_MS, Math.max(MIN_INTERVAL_MS,
+                            minFenceDistance * 1000 / MAX_SPEED_M_S));
+                } else {
+                    intervalMs = MIN_INTERVAL_MS;
+                }
+                if (!mReceivingLocationUpdates || mLocationUpdateInterval != intervalMs) {
+                    mReceivingLocationUpdates = true;
+                    mLocationUpdateInterval = intervalMs;
+                    mLastLocationUpdate = location;
+
+                    LocationRequest request = new LocationRequest();
+                    request.setInterval(intervalMs).setFastestInterval(0);
+                    mLocationManager.requestLocationUpdates(request, this, mHandler.getLooper());
+                }
+            } else {
+                // Cancel location updates.
+                if (mReceivingLocationUpdates) {
+                    mReceivingLocationUpdates = false;
+                    mLocationUpdateInterval = 0;
+                    mLastLocationUpdate = null;
+
+                    mLocationManager.removeUpdates(this);
+                }
+            }
+
+            if (D) {
+                Slog.d(TAG, "updateFences: location=" + location
+                        + ", mFences.size()=" + mFences.size()
+                        + ", mReceivingLocationUpdates=" + mReceivingLocationUpdates
+                        + ", mLocationUpdateInterval=" + mLocationUpdateInterval
+                        + ", mLastLocationUpdate=" + mLastLocationUpdate);
+            }
+        }
+
+        // release lock before sending intents
+        for (PendingIntent intent : exitIntents) {
+            sendIntentExit(intent);
+        }
+        for (PendingIntent intent : enterIntents) {
+            sendIntentEnter(intent);
+        }
+    }
+
+    private void sendIntentEnter(PendingIntent pendingIntent) {
+        if (D) {
+            Slog.d(TAG, "sendIntentEnter: pendingIntent=" + pendingIntent);
+        }
+
+        Intent intent = new Intent();
+        intent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, true);
+        sendIntent(pendingIntent, intent);
+    }
+
+    private void sendIntentExit(PendingIntent pendingIntent) {
+        if (D) {
+            Slog.d(TAG, "sendIntentExit: pendingIntent=" + pendingIntent);
+        }
+
+        Intent intent = new Intent();
+        intent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);
+        sendIntent(pendingIntent, intent);
+    }
+
+    private void sendIntent(PendingIntent pendingIntent, Intent intent) {
+        mWakeLock.acquire();
+        try {
+            pendingIntent.send(mContext, 0, intent, this, null,
+                    android.Manifest.permission.ACCESS_FINE_LOCATION);
+        } catch (PendingIntent.CanceledException e) {
+            removeFence(null, pendingIntent);
+            mWakeLock.release();
+        }
+        // ...otherwise, mWakeLock.release() gets called by onSendFinished()
+    }
+
+    // Runs on the handler (which was passed into LocationManager.requestLocationUpdates())
+    @Override
+    public void onLocationChanged(Location location) {
+        synchronized (mLock) {
+            if (mReceivingLocationUpdates) {
+                mLastLocationUpdate = location;
+            }
+
+            // Update the fences immediately before returning in
+            // case the caller is holding a wakelock.
+            if (mPendingUpdate) {
+                mHandler.removeMessages(MSG_UPDATE_FENCES);
+            } else {
+                mPendingUpdate = true;
+            }
+        }
+        updateFences();
+    }
+
+    @Override
+    public void onStatusChanged(String provider, int status, Bundle extras) { }
+
+    @Override
+    public void onProviderEnabled(String provider) { }
+
+    @Override
+    public void onProviderDisabled(String provider) { }
+
+    @Override
+    public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
+            String resultData, Bundle resultExtras) {
+        mWakeLock.release();
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.println("  Geofences:");
+
+        for (GeofenceState state : mFences) {
+            pw.append("    ");
+            pw.append(state.mPackageName);
+            pw.append(" ");
+            pw.append(state.mFence.toString());
+            pw.append("\n");
+        }
+    }
+
+    private final class GeofenceHandler extends Handler {
+        public GeofenceHandler() {
+            super(true /*async*/);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_UPDATE_FENCES: {
+                    updateFences();
+                    break;
+                }
+            }
+        }
+    }
+}
diff --git a/services/java/com/android/server/location/GeofenceState.java b/services/java/com/android/server/location/GeofenceState.java
new file mode 100644
index 0000000..11705ff
--- /dev/null
+++ b/services/java/com/android/server/location/GeofenceState.java
@@ -0,0 +1,110 @@
+/*
+ * 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.location;
+
+import android.app.PendingIntent;
+import android.location.Geofence;
+import android.location.Location;
+
+/**
+ * Represents state associated with a geofence
+ */
+public class GeofenceState {
+    public final static int FLAG_ENTER = 0x01;
+    public final static int FLAG_EXIT = 0x02;
+
+    private static final int STATE_UNKNOWN = 0;
+    private static final int STATE_INSIDE = 1;
+    private static final int STATE_OUTSIDE = 2;
+
+    public final Geofence mFence;
+    private final Location mLocation;
+    public final long mExpireAt;
+    public final String mPackageName;
+    public final PendingIntent mIntent;
+
+    int mState;  // current state
+    double mDistanceToCenter;  // current distance to center of fence
+
+    public GeofenceState(Geofence fence, long expireAt,
+            String packageName, PendingIntent intent) {
+        mState = STATE_UNKNOWN;
+        mDistanceToCenter = Double.MAX_VALUE;
+
+        mFence = fence;
+        mExpireAt = expireAt;
+        mPackageName = packageName;
+        mIntent = intent;
+
+        mLocation = new Location("");
+        mLocation.setLatitude(fence.getLatitude());
+        mLocation.setLongitude(fence.getLongitude());
+    }
+
+    /**
+     * Process a new location.
+     * @return FLAG_ENTER or FLAG_EXIT if the fence was crossed, 0 otherwise
+     */
+    public int processLocation(Location location) {
+        mDistanceToCenter = mLocation.distanceTo(location);
+
+        int prevState = mState;
+        //TODO: inside/outside detection could be made more rigorous
+        boolean inside = mDistanceToCenter <= Math.max(mFence.getRadius(), location.getAccuracy());
+        if (inside) {
+            mState = STATE_INSIDE;
+            if (prevState != STATE_INSIDE) {
+                return FLAG_ENTER; // return enter if previously exited or unknown
+            }
+        } else {
+            mState = STATE_OUTSIDE;
+            if (prevState == STATE_INSIDE) {
+                return FLAG_EXIT; // return exit only if previously entered
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Gets the distance from the current location to the fence's boundary.
+     * @return The distance or {@link Double#MAX_VALUE} if unknown.
+     */
+    public double getDistanceToBoundary() {
+        if (Double.compare(mDistanceToCenter, Double.MAX_VALUE) == 0) {
+            return Double.MAX_VALUE;
+        } else {
+            return Math.abs(mFence.getRadius() - mDistanceToCenter);
+        }
+    }
+
+    @Override
+    public String toString() {
+        String state;
+        switch (mState) {
+            case STATE_INSIDE:
+                state = "IN";
+                break;
+            case STATE_OUTSIDE:
+                state = "OUT";
+                break;
+            default:
+                state = "?";
+        }
+        return String.format("%s d=%.0f %s", mFence.toString(), mDistanceToCenter, state);
+    }
+}
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 4ad6140..c272da4 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -29,22 +29,23 @@
 import android.location.ILocationManager;
 import android.location.INetInitiatedListener;
 import android.location.Location;
+import android.location.LocationListener;
 import android.location.LocationManager;
 import android.location.LocationProvider;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.provider.Telephony.Carriers;
@@ -54,23 +55,24 @@
 import android.telephony.gsm.GsmCellLocation;
 import android.util.Log;
 import android.util.NtpTrustedTime;
-import android.util.SparseIntArray;
-
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.location.GpsNetInitiatedHandler;
+import com.android.internal.location.ProviderProperties;
+import com.android.internal.location.ProviderRequest;
 import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
 
 import java.io.File;
+import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.PrintWriter;
 import java.io.StringReader;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.Map.Entry;
 import java.util.Properties;
-import java.util.concurrent.CountDownLatch;
 
 /**
  * A GPS implementation of LocationProvider used by LocationManager.
@@ -81,8 +83,12 @@
 
     private static final String TAG = "GpsLocationProvider";
 
-    private static final boolean DEBUG = false;
-    private static final boolean VERBOSE = false;
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    private static final ProviderProperties PROPERTIES = new ProviderProperties(
+            true, true, false, false, true, true, true,
+            Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
 
     // these need to match GpsPositionMode enum in gps.h
     private static final int GPS_POSITION_MODE_STANDALONE = 0;
@@ -150,14 +156,15 @@
     // Handler messages
     private static final int CHECK_LOCATION = 1;
     private static final int ENABLE = 2;
-    private static final int ENABLE_TRACKING = 3;
+    private static final int SET_REQUEST = 3;
     private static final int UPDATE_NETWORK_STATE = 4;
     private static final int INJECT_NTP_TIME = 5;
     private static final int DOWNLOAD_XTRA_DATA = 6;
     private static final int UPDATE_LOCATION = 7;
     private static final int ADD_LISTENER = 8;
     private static final int REMOVE_LISTENER = 9;
-    private static final int REQUEST_SINGLE_SHOT = 10;
+    private static final int INJECT_NTP_TIME_FINISHED = 10;
+    private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11;
 
     // Request setid
     private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
@@ -179,6 +186,18 @@
 
     private static final String PROPERTIES_FILE = "/etc/gps.conf";
 
+    /** simpler wrapper for ProviderRequest + Worksource */
+    private static class GpsRequest {
+        public ProviderRequest request;
+        public WorkSource source;
+        public GpsRequest(ProviderRequest request, WorkSource source) {
+            this.request = request;
+            this.source = source;
+        }
+    }
+
+    private Object mLock = new Object();
+
     private int mLocationFlags = LOCATION_INVALID;
 
     // current status
@@ -198,16 +217,28 @@
     // Typical hot TTTF is ~5 seconds, so 10 seconds seems sane.
     private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000;
 
-    // true if we are enabled
-    private volatile boolean mEnabled;
-    
+    // how often to request NTP time, in milliseconds
+    // current setting 24 hours
+    private static final long NTP_INTERVAL = 24*60*60*1000;
+    // how long to wait if we have a network error in NTP or XTRA downloading
+    // current setting - 5 minutes
+    private static final long RETRY_INTERVAL = 5*60*1000;
+
+    // true if we are enabled, protected by this
+    private boolean mEnabled;
+
     // true if we have network connectivity
     private boolean mNetworkAvailable;
 
+    // states for injecting ntp and downloading xtra data
+    private static final int STATE_PENDING_NETWORK = 0;
+    private static final int STATE_DOWNLOADING = 1;
+    private static final int STATE_IDLE = 2;
+
     // flags to trigger NTP or XTRA data download when network becomes available
     // initialized to true so we do NTP and XTRA when the network comes up after booting
-    private boolean mInjectNtpTimePending = true;
-    private boolean mDownloadXtraDataPending = true;
+    private int mInjectNtpTimePending = STATE_PENDING_NETWORK;
+    private int mDownloadXtraDataPending = STATE_PENDING_NETWORK;
 
     // set to true if the GPS engine does not do on-demand NTP time requests
     private boolean mPeriodicTimeInjection;
@@ -217,16 +248,13 @@
 
     // true if GPS engine is on
     private boolean mEngineOn;
-    
+
     // requested frequency of fixes, in milliseconds
     private int mFixInterval = 1000;
 
     // true if we started navigation
     private boolean mStarted;
 
-    // true if single shot request is in progress
-    private boolean mSingleShot;
-
     // capabilities of the GPS engine
     private int mEngineCapabilities;
 
@@ -236,7 +264,7 @@
     // for calculating time to first fix
     private long mFixRequestTime = 0;
     // time to first fix for most recent session
-    private int mTTFF = 0;
+    private int mTimeToFirstFix = 0;
     // time we received our last fix
     private long mLastFixTime;
 
@@ -251,33 +279,23 @@
 
     private final Context mContext;
     private final NtpTrustedTime mNtpTime;
-    private final ILocationManager mLocationManager;
+    private final ILocationManager mILocationManager;
     private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
     private Bundle mLocationExtras = new Bundle();
     private ArrayList<Listener> mListeners = new ArrayList<Listener>();
 
-    // GpsLocationProvider's handler thread
-    private final Thread mThread;
-    // Handler for processing events in mThread.
+    // Handler for processing events
     private Handler mHandler;
-    // Used to signal when our main thread has initialized everything
-    private final CountDownLatch mInitializedLatch = new CountDownLatch(1);
 
     private String mAGpsApn;
     private int mAGpsDataConnectionState;
     private int mAGpsDataConnectionIpAddr;
     private final ConnectivityManager mConnMgr;
-    private final GpsNetInitiatedHandler mNIHandler; 
+    private final GpsNetInitiatedHandler mNIHandler;
 
     // Wakelocks
     private final static String WAKELOCK_KEY = "GpsLocationProvider";
     private final PowerManager.WakeLock mWakeLock;
-    // bitfield of pending messages to our Handler
-    // used only for messages that cannot have multiple instances queued
-    private int mPendingMessageBits;
-    // separate counter for ADD_LISTENER and REMOVE_LISTENER messages,
-    // which might have multiple instances queued
-    private int mPendingListenerMessages;
 
     // Alarms
     private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
@@ -287,22 +305,18 @@
     private final PendingIntent mTimeoutIntent;
 
     private final IBatteryStats mBatteryStats;
-    private final SparseIntArray mClientUids = new SparseIntArray();
 
-    // how often to request NTP time, in milliseconds
-    // current setting 24 hours
-    private static final long NTP_INTERVAL = 24*60*60*1000;
-    // how long to wait if we have a network error in NTP or XTRA downloading
-    // current setting - 5 minutes
-    private static final long RETRY_INTERVAL = 5*60*1000;
+    // only modified on handler thread
+    private int[] mClientUids = new int[0];
 
     private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
+        @Override
         public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
             if (listener == null) {
                 throw new NullPointerException("listener is null in addGpsStatusListener");
             }
 
-            synchronized(mListeners) {
+            synchronized (mListeners) {
                 IBinder binder = listener.asBinder();
                 int size = mListeners.size();
                 for (int i = 0; i < size; i++) {
@@ -319,12 +333,13 @@
             }
         }
 
+        @Override
         public void removeGpsStatusListener(IGpsStatusListener listener) {
             if (listener == null) {
                 throw new NullPointerException("listener is null in addGpsStatusListener");
             }
 
-            synchronized(mListeners) {
+            synchronized (mListeners) {
                 IBinder binder = listener.asBinder();
                 Listener l = null;
                 int size = mListeners.size();
@@ -353,7 +368,7 @@
 
             if (action.equals(ALARM_WAKEUP)) {
                 if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");
-                startNavigating(false);
+                startNavigating();
             } else if (action.equals(ALARM_TIMEOUT)) {
                 if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
                 hibernate();
@@ -361,6 +376,22 @@
                 checkSmsSuplInit(intent);
             } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
                 checkWapSuplInit(intent);
+             } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+                 int networkState;
+                 if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)) {
+                     networkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
+                 } else {
+                     networkState = LocationProvider.AVAILABLE;
+                 }
+
+                 // retrieve NetworkInfo result for this UID
+                 NetworkInfo info =
+                         intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
+                 ConnectivityManager connManager = (ConnectivityManager)
+                         mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+                 info = connManager.getNetworkInfo(info.getType());
+
+                 updateNetworkState(networkState, info);
              }
         }
     };
@@ -382,10 +413,10 @@
         return native_is_supported();
     }
 
-    public GpsLocationProvider(Context context, ILocationManager locationManager) {
+    public GpsLocationProvider(Context context, ILocationManager ilocationManager) {
         mContext = context;
         mNtpTime = NtpTrustedTime.getInstance(context);
-        mLocationManager = locationManager;
+        mILocationManager = ilocationManager;
         mNIHandler = new GpsNetInitiatedHandler(context);
 
         mLocation.setExtras(mLocationExtras);
@@ -393,27 +424,12 @@
         // Create a wake lock
         PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
-        mWakeLock.setReferenceCounted(false);
+        mWakeLock.setReferenceCounted(true);
 
         mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
         mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
         mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
 
-        IntentFilter intentFilter = new IntentFilter();
-        intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
-        intentFilter.addDataScheme("sms");
-        intentFilter.addDataAuthority("localhost","7275");
-        context.registerReceiver(mBroadcastReciever, intentFilter);
-
-        intentFilter = new IntentFilter();
-        intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
-        try {
-            intentFilter.addDataType("application/vnd.omaloc-supl-init");
-        } catch (IntentFilter.MalformedMimeTypeException e) {
-            Log.w(TAG, "Malformed SUPL init mime type");
-        }
-        context.registerReceiver(mBroadcastReciever, intentFilter);
-
         mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
 
         // Battery statistics service to be notified when GPS turns on or off
@@ -449,40 +465,56 @@
             Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
         }
 
-        // wait until we are fully initialized before returning
-        mThread = new GpsLocationProviderThread();
-        mThread.start();
-        while (true) {
-            try {
-                mInitializedLatch.await();
-                break;
-            } catch (InterruptedException e) {
-                Thread.currentThread().interrupt();
+        // construct handler, listen for events
+        mHandler = new ProviderHandler();
+        listenForBroadcasts();
+
+        // also listen for PASSIVE_PROVIDER updates
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                LocationManager locManager =
+                        (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
+                locManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER,
+                        0, 0, new NetworkLocationListener(), mHandler.getLooper());                
             }
-        }
+        });
     }
 
-    private void initialize() {
-        // register our receiver on our thread rather than the main thread
+    private void listenForBroadcasts() {
         IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
+        intentFilter.addDataScheme("sms");
+        intentFilter.addDataAuthority("localhost","7275");
+        mContext.registerReceiver(mBroadcastReciever, intentFilter, null, mHandler);
+
+        intentFilter = new IntentFilter();
+        intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
+        try {
+            intentFilter.addDataType("application/vnd.omaloc-supl-init");
+        } catch (IntentFilter.MalformedMimeTypeException e) {
+            Log.w(TAG, "Malformed SUPL init mime type");
+        }
+        mContext.registerReceiver(mBroadcastReciever, intentFilter, null, mHandler);
+
+        intentFilter = new IntentFilter();
         intentFilter.addAction(ALARM_WAKEUP);
         intentFilter.addAction(ALARM_TIMEOUT);
-        mContext.registerReceiver(mBroadcastReciever, intentFilter);
+        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+        mContext.registerReceiver(mBroadcastReciever, intentFilter, null, mHandler);
     }
 
     /**
      * Returns the name of this provider.
      */
+    @Override
     public String getName() {
         return LocationManager.GPS_PROVIDER;
     }
 
-    /**
-     * Returns true if the provider requires access to a
-     * data network (e.g., the Internet), false otherwise.
-     */
-    public boolean requiresNetwork() {
-        return true;
+    @Override
+    public ProviderProperties getProperties() {
+        return PROPERTIES;
     }
 
     public void updateNetworkState(int state, NetworkInfo info) {
@@ -498,8 +530,8 @@
         }
 
         if (info != null) {
-            boolean dataEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
-                                                         Settings.Secure.MOBILE_DATA, 1) == 1;
+            boolean dataEnabled = Settings.Global.getInt(mContext.getContentResolver(),
+                                                         Settings.Global.MOBILE_DATA, 1) == 1;
             boolean networkAvailable = info.isAvailable() && dataEnabled;
             String defaultApn = getSelectedApn();
             if (defaultApn == null) {
@@ -516,7 +548,7 @@
             String apnName = info.getExtraInfo();
             if (mNetworkAvailable) {
                 if (apnName == null) {
-                    /* Assign a dummy value in the case of C2K as otherwise we will have a runtime 
+                    /* Assign a dummy value in the case of C2K as otherwise we will have a runtime
                     exception in the following call to native_agps_data_conn_open*/
                     apnName = "dummy-apn";
                 }
@@ -541,88 +573,111 @@
         }
 
         if (mNetworkAvailable) {
-            if (mInjectNtpTimePending) {
+            if (mInjectNtpTimePending == STATE_PENDING_NETWORK) {
                 sendMessage(INJECT_NTP_TIME, 0, null);
             }
-            if (mDownloadXtraDataPending) {
+            if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
                 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
             }
         }
     }
 
     private void handleInjectNtpTime() {
-        if (!mNetworkAvailable) {
-            // try again when network is up
-            mInjectNtpTimePending = true;
+        if (mInjectNtpTimePending == STATE_DOWNLOADING) {
+            // already downloading data
             return;
         }
-        mInjectNtpTimePending = false;
-
-        long delay;
-
-        // force refresh NTP cache when outdated
-        if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
-            mNtpTime.forceRefresh();
+        if (!mNetworkAvailable) {
+            // try again when network is up
+            mInjectNtpTimePending = STATE_PENDING_NETWORK;
+            return;
         }
+        mInjectNtpTimePending = STATE_DOWNLOADING;
 
-        // only update when NTP time is fresh
-        if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
-            long time = mNtpTime.getCachedNtpTime();
-            long timeReference = mNtpTime.getCachedNtpTimeReference();
-            long certainty = mNtpTime.getCacheCertainty();
-            long now = System.currentTimeMillis();
+        // hold wake lock while task runs
+        mWakeLock.acquire();
+        AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
+            @Override
+            public void run() {
+                long delay;
 
-            Log.d(TAG, "NTP server returned: "
-                    + time + " (" + new Date(time)
-                    + ") reference: " + timeReference
-                    + " certainty: " + certainty
-                    + " system time offset: " + (time - now));
+                // force refresh NTP cache when outdated
+                if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
+                    mNtpTime.forceRefresh();
+                }
 
-            native_inject_time(time, timeReference, (int) certainty);
-            delay = NTP_INTERVAL;
-        } else {
-            if (DEBUG) Log.d(TAG, "requestTime failed");
-            delay = RETRY_INTERVAL;
-        }
+                // only update when NTP time is fresh
+                if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
+                    long time = mNtpTime.getCachedNtpTime();
+                    long timeReference = mNtpTime.getCachedNtpTimeReference();
+                    long certainty = mNtpTime.getCacheCertainty();
+                    long now = System.currentTimeMillis();
 
-        if (mPeriodicTimeInjection) {
-            // send delayed message for next NTP injection
-            // since this is delayed and not urgent we do not hold a wake lock here
-            mHandler.removeMessages(INJECT_NTP_TIME);
-            mHandler.sendMessageDelayed(Message.obtain(mHandler, INJECT_NTP_TIME), delay);
-        }
+                    Log.d(TAG, "NTP server returned: "
+                            + time + " (" + new Date(time)
+                            + ") reference: " + timeReference
+                            + " certainty: " + certainty
+                            + " system time offset: " + (time - now));
+
+                    native_inject_time(time, timeReference, (int) certainty);
+                    delay = NTP_INTERVAL;
+                } else {
+                    if (DEBUG) Log.d(TAG, "requestTime failed");
+                    delay = RETRY_INTERVAL;
+                }
+
+                sendMessage(INJECT_NTP_TIME_FINISHED, 0, null);
+
+                if (mPeriodicTimeInjection) {
+                    // send delayed message for next NTP injection
+                    // since this is delayed and not urgent we do not hold a wake lock here
+                    mHandler.sendEmptyMessageDelayed(INJECT_NTP_TIME, delay);
+                }
+
+                // release wake lock held by task
+                mWakeLock.release();
+            }
+        });
     }
 
     private void handleDownloadXtraData() {
-        if (!mNetworkAvailable) {
-            // try again when network is up
-            mDownloadXtraDataPending = true;
+        if (mDownloadXtraDataPending == STATE_DOWNLOADING) {
+            // already downloading data
             return;
         }
-        mDownloadXtraDataPending = false;
-
-
-        GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
-        byte[] data = xtraDownloader.downloadXtraData();
-        if (data != null) {
-            if (DEBUG) {
-                Log.d(TAG, "calling native_inject_xtra_data");
-            }
-            native_inject_xtra_data(data, data.length);
-        } else {
-            // try again later
-            // since this is delayed and not urgent we do not hold a wake lock here
-            mHandler.removeMessages(DOWNLOAD_XTRA_DATA);
-            mHandler.sendMessageDelayed(Message.obtain(mHandler, DOWNLOAD_XTRA_DATA), RETRY_INTERVAL);
+        if (!mNetworkAvailable) {
+            // try again when network is up
+            mDownloadXtraDataPending = STATE_PENDING_NETWORK;
+            return;
         }
-    }
+        mDownloadXtraDataPending = STATE_DOWNLOADING;
 
-    /**
-     * This is called to inform us when another location provider returns a location.
-     * Someday we might use this for network location injection to aid the GPS
-     */
-    public void updateLocation(Location location) {
-        sendMessage(UPDATE_LOCATION, 0, location);
+        // hold wake lock while task runs
+        mWakeLock.acquire();
+        AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
+            @Override
+            public void run() {
+                GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
+                byte[] data = xtraDownloader.downloadXtraData();
+                if (data != null) {
+                    if (DEBUG) {
+                        Log.d(TAG, "calling native_inject_xtra_data");
+                    }
+                    native_inject_xtra_data(data, data.length);
+                }
+
+                sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null);
+
+                if (data == null) {
+                    // try again later
+                    // since this is delayed and not urgent we do not hold a wake lock here
+                    mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA, RETRY_INTERVAL);
+                }
+
+                // release wake lock held by task
+                mWakeLock.release();
+            }
+        });
     }
 
     private void handleUpdateLocation(Location location) {
@@ -633,107 +688,26 @@
     }
 
     /**
-     * Returns true if the provider requires access to a
-     * satellite-based positioning system (e.g., GPS), false
-     * otherwise.
-     */
-    public boolean requiresSatellite() {
-        return true;
-    }
-
-    /**
-     * Returns true if the provider requires access to an appropriate
-     * cellular network (e.g., to make use of cell tower IDs), false
-     * otherwise.
-     */
-    public boolean requiresCell() {
-        return false;
-    }
-
-    /**
-     * Returns true if the use of this provider may result in a
-     * monetary charge to the user, false if use is free.  It is up to
-     * each provider to give accurate information.
-     */
-    public boolean hasMonetaryCost() {
-        return false;
-    }
-
-    /**
-     * Returns true if the provider is able to provide altitude
-     * information, false otherwise.  A provider that reports altitude
-     * under most circumstances but may occassionally not report it
-     * should return true.
-     */
-    public boolean supportsAltitude() {
-        return true;
-    }
-
-    /**
-     * Returns true if the provider is able to provide speed
-     * information, false otherwise.  A provider that reports speed
-     * under most circumstances but may occassionally not report it
-     * should return true.
-     */
-    public boolean supportsSpeed() {
-        return true;
-    }
-
-    /**
-     * Returns true if the provider is able to provide bearing
-     * information, false otherwise.  A provider that reports bearing
-     * under most circumstances but may occassionally not report it
-     * should return true.
-     */
-    public boolean supportsBearing() {
-        return true;
-    }
-
-    /**
-     * Returns the power requirement for this provider.
-     *
-     * @return the power requirement for this provider, as one of the
-     * constants Criteria.POWER_REQUIREMENT_*.
-     */
-    public int getPowerRequirement() {
-        return Criteria.POWER_HIGH;
-    }
-
-    /**
-     * Returns true if this provider meets the given criteria,
-     * false otherwise.
-     */
-    public boolean meetsCriteria(Criteria criteria) {
-        return (criteria.getPowerRequirement() != Criteria.POWER_LOW);
-    }
-
-    /**
-     * Returns the horizontal accuracy of this provider
-     *
-     * @return the accuracy of location from this provider, as one
-     * of the constants Criteria.ACCURACY_*.
-     */
-    public int getAccuracy() {
-        return Criteria.ACCURACY_FINE;
-    }
-
-    /**
      * Enables this provider.  When enabled, calls to getStatus()
      * must be handled.  Hardware may be started up
      * when the provider is enabled.
      */
+    @Override
     public void enable() {
-        synchronized (mHandler) {
-            sendMessage(ENABLE, 1, null);
-        }
+        sendMessage(ENABLE, 1, null);
     }
 
     private void handleEnable() {
         if (DEBUG) Log.d(TAG, "handleEnable");
-        if (mEnabled) return;
-        mEnabled = native_init();
 
-        if (mEnabled) {
+        synchronized (mLock) {
+            if (mEnabled) return;
+            mEnabled = true;
+        }
+
+        boolean enabled = native_init();
+
+        if (enabled) {
             mSupportsXtra = native_supports_xtra();
             if (mSuplServerHost != null) {
                 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
@@ -742,6 +716,9 @@
                 native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
             }
         } else {
+            synchronized (mLock) {
+                mEnabled = false;
+            }
             Log.w(TAG, "Failed to enable location provider");
         }
     }
@@ -751,27 +728,35 @@
      * need not be handled.  Hardware may be shut
      * down while the provider is disabled.
      */
+    @Override
     public void disable() {
-        synchronized (mHandler) {
-            sendMessage(ENABLE, 0, null);
-        }
+        sendMessage(ENABLE, 0, null);
     }
 
     private void handleDisable() {
         if (DEBUG) Log.d(TAG, "handleDisable");
-        if (!mEnabled) return;
 
-        mEnabled = false;
+        synchronized (mLock) {
+            if (!mEnabled) return;
+            mEnabled = false;
+        }
+
         stopNavigating();
+        mAlarmManager.cancel(mWakeupIntent);
+        mAlarmManager.cancel(mTimeoutIntent);
 
         // do this before releasing wakelock
         native_cleanup();
     }
 
+    @Override
     public boolean isEnabled() {
-        return mEnabled;
+        synchronized (mLock) {
+            return mEnabled;
+        }
     }
 
+    @Override
     public int getStatus(Bundle extras) {
         if (extras != null) {
             extras.putInt("satellites", mSvCount);
@@ -788,93 +773,74 @@
         }
     }
 
+    @Override
     public long getStatusUpdateTime() {
         return mStatusUpdateTime;
     }
 
-    public void enableLocationTracking(boolean enable) {
-        // FIXME - should set a flag here to avoid race conditions with single shot request
-        synchronized (mHandler) {
-            sendMessage(ENABLE_TRACKING, (enable ? 1 : 0), null);
-        }
+    @Override
+    public void setRequest(ProviderRequest request, WorkSource source) {
+        sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
     }
 
-    private void handleEnableLocationTracking(boolean enable) {
-        if (enable) {
-            mTTFF = 0;
-            mLastFixTime = 0;
-            startNavigating(false);
-        } else {
-            if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
-                mAlarmManager.cancel(mWakeupIntent);
-                mAlarmManager.cancel(mTimeoutIntent);
+    @Override
+    public void switchUser(int userId) {
+        // nothing to do here
+    }
+
+    private void handleSetRequest(ProviderRequest request, WorkSource source) {
+        if (DEBUG) Log.d(TAG, "setRequest " + request);
+
+
+
+        if (request.reportLocation) {
+            // update client uids
+            int[] uids = new int[source.size()];
+            for (int i=0; i < source.size(); i++) {
+                uids[i] = source.get(i);
             }
-            stopNavigating();
-        }
-    }
+            updateClientUids(uids);
 
-    public boolean requestSingleShotFix() {
-        if (mStarted) {
-            // cannot do single shot if already navigating
-            return false;
-        }
-        synchronized (mHandler) {
-            mHandler.removeMessages(REQUEST_SINGLE_SHOT);
-            Message m = Message.obtain(mHandler, REQUEST_SINGLE_SHOT);
-            mHandler.sendMessage(m);
-        }
-        return true;
-    }
+            mFixInterval = (int) request.interval;
 
-    private void handleRequestSingleShot() {
-        mTTFF = 0;
-        mLastFixTime = 0;
-        startNavigating(true);
-    }
+            // check for overflow
+            if (mFixInterval != request.interval) {
+                Log.w(TAG, "interval overflow: " + request.interval);
+                mFixInterval = Integer.MAX_VALUE;
+            }
 
-    public void setMinTime(long minTime, WorkSource ws) {
-        if (DEBUG) Log.d(TAG, "setMinTime " + minTime);
-        
-        if (minTime >= 0) {
-            mFixInterval = (int)minTime;
-
+            // apply request to GPS engine
             if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
+                // change period
                 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
                         mFixInterval, 0, 0)) {
                     Log.e(TAG, "set_position_mode failed in setMinTime()");
                 }
+            } else if (!mStarted) {
+                // start GPS
+                startNavigating();
             }
+        } else {
+            updateClientUids(new int[0]);
+
+            stopNavigating();
+            mAlarmManager.cancel(mWakeupIntent);
+            mAlarmManager.cancel(mTimeoutIntent);
         }
     }
 
-    public String getInternalState() {
-        StringBuilder s = new StringBuilder();
-        s.append("  mFixInterval=").append(mFixInterval).append("\n");
-        s.append("  mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities)).append(" (");
-        if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHED ");
-        if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
-        if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
-        if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
-        if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
-        s.append(")\n");
-
-        s.append(native_get_internal_state());
-        return s.toString();
-    }
-
     private final class Listener implements IBinder.DeathRecipient {
         final IGpsStatusListener mListener;
-        
-        int mSensors = 0;
-        
+
         Listener(IGpsStatusListener listener) {
             mListener = listener;
         }
-        
+
+        @Override
         public void binderDied() {
             if (DEBUG) Log.d(TAG, "GPS status listener died");
 
-            synchronized(mListeners) {
+            synchronized (mListeners) {
                 mListeners.remove(this);
             }
             if (mListener != null) {
@@ -883,64 +849,50 @@
         }
     }
 
-    public void addListener(int uid) {
-        synchronized (mWakeLock) {
-            mPendingListenerMessages++;
-            mWakeLock.acquire();
-            Message m = Message.obtain(mHandler, ADD_LISTENER);
-            m.arg1 = uid;
-            mHandler.sendMessage(m);
-        }
-    }
-
-    private void handleAddListener(int uid) {
-        synchronized(mListeners) {
-            if (mClientUids.indexOfKey(uid) >= 0) {
-                // Shouldn't be here -- already have this uid.
-                Log.w(TAG, "Duplicate add listener for uid " + uid);
-                return;
+    private void updateClientUids(int[] uids) {
+        // Find uid's that were not previously tracked
+        for (int uid1 : uids) {
+            boolean newUid = true;
+            for (int uid2 : mClientUids) {
+                if (uid1 == uid2) {
+                    newUid = false;
+                    break;
+                }
             }
-            mClientUids.put(uid, 0);
-            if (mNavigating) {
+            if (newUid) {
                 try {
-                    mBatteryStats.noteStartGps(uid);
+                    mBatteryStats.noteStartGps(uid1);
                 } catch (RemoteException e) {
-                    Log.w(TAG, "RemoteException in addListener");
+                    Log.w(TAG, "RemoteException", e);
                 }
             }
         }
-    }
 
-    public void removeListener(int uid) {
-        synchronized (mWakeLock) {
-            mPendingListenerMessages++;
-            mWakeLock.acquire();
-            Message m = Message.obtain(mHandler, REMOVE_LISTENER);
-            m.arg1 = uid;
-            mHandler.sendMessage(m);
-        }
-    }
-
-    private void handleRemoveListener(int uid) {
-        synchronized(mListeners) {
-            if (mClientUids.indexOfKey(uid) < 0) {
-                // Shouldn't be here -- don't have this uid.
-                Log.w(TAG, "Unneeded remove listener for uid " + uid);
-                return;
+        // Find uid'd that were tracked but have now disappeared
+        for (int uid1 : mClientUids) {
+            boolean oldUid = true;
+            for (int uid2 : uids) {
+                if (uid1 == uid2) {
+                    oldUid = false;
+                    break;
+                }
             }
-            mClientUids.delete(uid);
-            if (mNavigating) {
+            if (oldUid) {
                 try {
-                    mBatteryStats.noteStopGps(uid);
+                    mBatteryStats.noteStopGps(uid1);
                 } catch (RemoteException e) {
-                    Log.w(TAG, "RemoteException in removeListener");
+                    Log.w(TAG, "RemoteException", e);
                 }
             }
         }
+
+        // save current uids
+        mClientUids = uids;
     }
 
+    @Override
     public boolean sendExtraCommand(String command, Bundle extras) {
-        
+
         long identity = Binder.clearCallingIdentity();
         boolean result = false;
 
@@ -957,7 +909,7 @@
         } else {
             Log.w(TAG, "sendExtraCommand: unknown command " + command);
         }
-        
+
         Binder.restoreCallingIdentity(identity);
         return result;
     }
@@ -992,18 +944,17 @@
         return false;
     }
 
-    private void startNavigating(boolean singleShot) {
+    private void startNavigating() {
         if (!mStarted) {
             if (DEBUG) Log.d(TAG, "startNavigating");
+            mTimeToFirstFix = 0;
+            mLastFixTime = 0;
             mStarted = true;
-            mSingleShot = singleShot;
             mPositionMode = GPS_POSITION_MODE_STANDALONE;
 
-             if (Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.ASSISTED_GPS_ENABLED, 1) != 0) {
-                if (singleShot && hasCapability(GPS_CAPABILITY_MSA)) {
-                    mPositionMode = GPS_POSITION_MODE_MS_ASSISTED;
-                } else if (hasCapability(GPS_CAPABILITY_MSB)) {
+             if (Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0) {
+                if (hasCapability(GPS_CAPABILITY_MSB)) {
                     mPositionMode = GPS_POSITION_MODE_MS_BASED;
                 }
             }
@@ -1039,9 +990,8 @@
         if (DEBUG) Log.d(TAG, "stopNavigating");
         if (mStarted) {
             mStarted = false;
-            mSingleShot = false;
             native_stop();
-            mTTFF = 0;
+            mTimeToFirstFix = 0;
             mLastFixTime = 0;
             mLocationFlags = LOCATION_INVALID;
 
@@ -1056,8 +1006,7 @@
         mAlarmManager.cancel(mTimeoutIntent);
         mAlarmManager.cancel(mWakeupIntent);
         long now = SystemClock.elapsedRealtime();
-        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
-                SystemClock.elapsedRealtime() + mFixInterval, mWakeupIntent);
+        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent);
     }
 
     private boolean hasCapability(int capability) {
@@ -1078,6 +1027,9 @@
                 mLocation.setLatitude(latitude);
                 mLocation.setLongitude(longitude);
                 mLocation.setTime(timestamp);
+                // It would be nice to push the elapsed real-time timestamp
+                // further down the stack, but this is still useful
+                mLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
             }
             if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
                 mLocation.setAltitude(altitude);
@@ -1102,7 +1054,7 @@
             mLocation.setExtras(mLocationExtras);
 
             try {
-                mLocationManager.reportLocation(mLocation, false);
+                mILocationManager.reportLocation(mLocation, false);
             } catch (RemoteException e) {
                 Log.e(TAG, "RemoteException calling reportLocation");
             }
@@ -1110,17 +1062,17 @@
 
         mLastFixTime = System.currentTimeMillis();
         // report time to first fix
-        if (mTTFF == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
-            mTTFF = (int)(mLastFixTime - mFixRequestTime);
-            if (DEBUG) Log.d(TAG, "TTFF: " + mTTFF);
+        if (mTimeToFirstFix == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
+            mTimeToFirstFix = (int)(mLastFixTime - mFixRequestTime);
+            if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix);
 
             // notify status listeners
-            synchronized(mListeners) {
+            synchronized (mListeners) {
                 int size = mListeners.size();
                 for (int i = 0; i < size; i++) {
                     Listener listener = mListeners.get(i);
                     try {
-                        listener.mListener.onFirstFix(mTTFF); 
+                        listener.mListener.onFirstFix(mTimeToFirstFix);
                     } catch (RemoteException e) {
                         Log.w(TAG, "RemoteException in stopNavigating");
                         mListeners.remove(listener);
@@ -1131,9 +1083,6 @@
             }
         }
 
-        if (mSingleShot) {
-            stopNavigating();
-        }
         if (mStarted && mStatus != LocationProvider.AVAILABLE) {
             // we want to time out if we do not receive a fix
             // within the time out and we are requesting infrequent fixes
@@ -1144,7 +1093,7 @@
             // send an intent to notify that the GPS is receiving fixes.
             Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
             intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
-            mContext.sendBroadcast(intent);
+            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
             updateStatus(LocationProvider.AVAILABLE, mSvCount);
         }
 
@@ -1161,7 +1110,7 @@
     private void reportStatus(int status) {
         if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
 
-        synchronized(mListeners) {
+        synchronized (mListeners) {
             boolean wasNavigating = mNavigating;
 
             switch (status) {
@@ -1199,24 +1148,10 @@
                     }
                 }
 
-                try {
-                    // update battery stats
-                    for (int i=mClientUids.size() - 1; i >= 0; i--) {
-                        int uid = mClientUids.keyAt(i);
-                        if (mNavigating) {
-                            mBatteryStats.noteStartGps(uid);
-                        } else {
-                            mBatteryStats.noteStopGps(uid);
-                        }
-                    }
-                } catch (RemoteException e) {
-                    Log.w(TAG, "RemoteException in reportStatus");
-                }
-
                 // send an intent to notify that the GPS has been enabled or disabled.
                 Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
                 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
-                mContext.sendBroadcast(intent);
+                mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
             }
         }
     }
@@ -1227,15 +1162,15 @@
     private void reportSvStatus() {
 
         int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
-        
-        synchronized(mListeners) {
+
+        synchronized (mListeners) {
             int size = mListeners.size();
             for (int i = 0; i < size; i++) {
                 Listener listener = mListeners.get(i);
                 try {
-                    listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs, 
-                            mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK], 
-                            mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]); 
+                    listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
+                            mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],
+                            mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]);
                 } catch (RemoteException e) {
                     Log.w(TAG, "RemoteException in reportSvInfo");
                     mListeners.remove(listener);
@@ -1251,7 +1186,7 @@
                     " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
             for (int i = 0; i < svCount; i++) {
                 Log.v(TAG, "sv: " + mSvs[i] +
-                        " snr: " + (float)mSnrs[i]/10 +
+                        " snr: " + mSnrs[i]/10 +
                         " elev: " + mSvElevations[i] +
                         " azimuth: " + mSvAzimuths[i] +
                         ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " E") +
@@ -1268,7 +1203,7 @@
             // send an intent to notify that the GPS is no longer receiving fixes.
             Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
             intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
-            mContext.sendBroadcast(intent);
+            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
             updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
         }
     }
@@ -1339,7 +1274,7 @@
      * called from native code to report NMEA data received
      */
     private void reportNmea(long timestamp) {
-        synchronized(mListeners) {
+        synchronized (mListeners) {
             int size = mListeners.size();
             if (size > 0) {
                 // don't bother creating the String if we have no listeners
@@ -1386,19 +1321,18 @@
     //=============================================================
     private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
         // Sends a response for an NI reqeust to HAL.
+        @Override
         public boolean sendNiResponse(int notificationId, int userResponse)
         {
             // TODO Add Permission check
 
-            StringBuilder extrasBuf = new StringBuilder();
-
             if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
                     ", response: " + userResponse);
             native_send_ni_response(notificationId, userResponse);
             return true;
         }
     };
-        
+
     public INetInitiatedListener getNetInitiatedListener() {
         return mNetInitiatedListener;
     }
@@ -1547,19 +1481,18 @@
     }
 
     private void sendMessage(int message, int arg, Object obj) {
-        // hold a wake lock while messages are pending
-        synchronized (mWakeLock) {
-            mPendingMessageBits |= (1 << message);
-            mWakeLock.acquire();
-            mHandler.removeMessages(message);
-            Message m = Message.obtain(mHandler, message);
-            m.arg1 = arg;
-            m.obj = obj;
-            mHandler.sendMessage(m);
-        }
+        // hold a wake lock until this message is delivered
+        // note that this assumes the message will not be removed from the queue before
+        // it is handled (otherwise the wake lock would be leaked).
+        mWakeLock.acquire();
+        mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
     }
 
     private final class ProviderHandler extends Handler {
+        public ProviderHandler() {
+            super(true /*async*/);
+        }
+
         @Override
         public void handleMessage(Message msg) {
             int message = msg.what;
@@ -1571,11 +1504,9 @@
                         handleDisable();
                     }
                     break;
-                case ENABLE_TRACKING:
-                    handleEnableLocationTracking(msg.arg1 == 1);
-                    break;
-                case REQUEST_SINGLE_SHOT:
-                    handleRequestSingleShot();
+                case SET_REQUEST:
+                    GpsRequest gpsRequest = (GpsRequest) msg.obj;
+                    handleSetRequest(gpsRequest.request, gpsRequest.source);
                     break;
                 case UPDATE_NETWORK_STATE:
                     handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj);
@@ -1588,44 +1519,37 @@
                         handleDownloadXtraData();
                     }
                     break;
+                case INJECT_NTP_TIME_FINISHED:
+                    mInjectNtpTimePending = STATE_IDLE;
+                    break;
+                case DOWNLOAD_XTRA_DATA_FINISHED:
+                    mDownloadXtraDataPending = STATE_IDLE;
+                    break;
                 case UPDATE_LOCATION:
                     handleUpdateLocation((Location)msg.obj);
                     break;
-                case ADD_LISTENER:
-                    handleAddListener(msg.arg1);
-                    break;
-                case REMOVE_LISTENER:
-                    handleRemoveListener(msg.arg1);
-                    break;
             }
-            // release wake lock if no messages are pending
-            synchronized (mWakeLock) {
-                mPendingMessageBits &= ~(1 << message);
-                if (message == ADD_LISTENER || message == REMOVE_LISTENER) {
-                    mPendingListenerMessages--;
-                }
-                if (mPendingMessageBits == 0 && mPendingListenerMessages == 0) {
-                    mWakeLock.release();
-                }
+            if (msg.arg2 == 1) {
+                // wakelock was taken for this message, release it
+                mWakeLock.release();
             }
         }
     };
 
-    private final class GpsLocationProviderThread extends Thread {
-
-        public GpsLocationProviderThread() {
-            super("GpsLocationProvider");
+    private final class NetworkLocationListener implements LocationListener {
+        @Override
+        public void onLocationChanged(Location location) {
+            // this callback happens on mHandler looper
+            if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
+                handleUpdateLocation(location);
+            }
         }
-
-        public void run() {
-            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-            initialize();
-            Looper.prepare();
-            mHandler = new ProviderHandler();
-            // signal when we are initialized and ready to go
-            mInitializedLatch.countDown();
-            Looper.loop();
-        }
+        @Override
+        public void onStatusChanged(String provider, int status, Bundle extras) { }
+        @Override
+        public void onProviderEnabled(String provider) { }
+        @Override
+        public void onProviderDisabled(String provider) { }
     }
 
     private String getSelectedApn() {
@@ -1647,6 +1571,22 @@
         return apn;
     }
 
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        StringBuilder s = new StringBuilder();
+        s.append("  mFixInterval=").append(mFixInterval).append("\n");
+        s.append("  mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities)).append(" (");
+        if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHED ");
+        if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
+        if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
+        if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
+        if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
+        s.append(")\n");
+
+        s.append(native_get_internal_state());
+        pw.append(s);
+    }
+
     // for GPS SV statistics
     private static final int MAX_SVS = 32;
     private static final int EPHEMERIS_MASK = 0;
diff --git a/services/java/com/android/server/location/LocationBasedCountryDetector.java b/services/java/com/android/server/location/LocationBasedCountryDetector.java
index d4fb8ee..03db621 100755
--- a/services/java/com/android/server/location/LocationBasedCountryDetector.java
+++ b/services/java/com/android/server/location/LocationBasedCountryDetector.java
@@ -114,7 +114,9 @@
         for (String provider : providers) {
             Location lastKnownLocation = mLocationManager.getLastKnownLocation(provider);
             if (lastKnownLocation != null) {
-                if (bestLocation == null || bestLocation.getTime() < lastKnownLocation.getTime()) {
+                if (bestLocation == null ||
+                        bestLocation.getElapsedRealtimeNanos() <
+                        lastKnownLocation.getElapsedRealtimeNanos()) {
                     bestLocation = lastKnownLocation;
                 }
             }
diff --git a/services/java/com/android/server/location/LocationBlacklist.java b/services/java/com/android/server/location/LocationBlacklist.java
new file mode 100644
index 0000000..2437a37b
--- /dev/null
+++ b/services/java/com/android/server/location/LocationBlacklist.java
@@ -0,0 +1,151 @@
+/*
+ * 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.location;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+import android.util.Slog;
+
+import com.android.server.LocationManagerService;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Allows applications to be blacklisted from location updates at run-time.
+ *
+ * This is a silent blacklist. Applications can still call Location Manager
+ * API's, but they just won't receive any locations.
+ */
+public final class LocationBlacklist extends ContentObserver {
+    private static final String TAG = "LocationBlacklist";
+    private static final boolean D = LocationManagerService.D;
+    private static final String BLACKLIST_CONFIG_NAME = "locationPackagePrefixBlacklist";
+    private static final String WHITELIST_CONFIG_NAME = "locationPackagePrefixWhitelist";
+
+    private final Context mContext;
+    private final Object mLock = new Object();
+
+    // all fields below synchronized on mLock
+    private String[] mWhitelist = new String[0];
+    private String[] mBlacklist = new String[0];
+
+    private int mCurrentUserId = UserHandle.USER_OWNER;
+    
+    public LocationBlacklist(Context context, Handler handler) {
+        super(handler);
+        mContext = context;
+    }
+
+    public void init() {
+        mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
+                BLACKLIST_CONFIG_NAME), false, this, UserHandle.USER_ALL);
+//        mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
+//                WHITELIST_CONFIG_NAME), false, this, UserHandle.USER_ALL);
+        reloadBlacklist();
+    }
+
+    private void reloadBlacklistLocked() {
+        mWhitelist = getStringArrayLocked(WHITELIST_CONFIG_NAME);
+        Slog.i(TAG, "whitelist: " + Arrays.toString(mWhitelist));
+        mBlacklist = getStringArrayLocked(BLACKLIST_CONFIG_NAME);
+        Slog.i(TAG, "blacklist: " + Arrays.toString(mBlacklist));
+    }
+
+    private void reloadBlacklist() {
+        synchronized (mLock) {
+            reloadBlacklistLocked();
+        }
+    }
+
+    /**
+     * Return true if in blacklist
+     * (package name matches blacklist, and does not match whitelist)
+     */
+    public boolean isBlacklisted(String packageName) {
+        synchronized (mLock) {
+            for (String black : mBlacklist) {
+                if (packageName.startsWith(black)) {
+                    if (inWhitelist(packageName)) {
+                        continue;
+                    } else {
+                        if (D) Log.d(TAG, "dropping location (blacklisted): "
+                                + packageName + " matches " + black);
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return true if any of packages are in whitelist
+     */
+    private boolean inWhitelist(String pkg) {
+        synchronized (mLock) {
+            for (String white : mWhitelist) {
+                if (pkg.startsWith(white)) return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void onChange(boolean selfChange) {
+        reloadBlacklist();
+    }
+
+    public void switchUser(int userId) {
+        synchronized(mLock) {
+            mCurrentUserId = userId;
+            reloadBlacklistLocked();
+        }
+    }
+
+    private String[] getStringArrayLocked(String key) {
+        String flatString;
+        synchronized(mLock) {
+            flatString = Settings.Secure.getStringForUser(mContext.getContentResolver(), key,
+                    mCurrentUserId);
+        }
+        if (flatString == null) {
+            return new String[0];
+        }
+        String[] splitStrings = flatString.split(",");
+        ArrayList<String> result = new ArrayList<String>();
+        for (String pkg : splitStrings) {
+            pkg = pkg.trim();
+            if (pkg.isEmpty()) {
+                continue;
+            }
+            result.add(pkg);
+        }
+        return result.toArray(new String[result.size()]);
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.println("mWhitelist=" + Arrays.toString(mWhitelist) + " mBlacklist=" +
+                Arrays.toString(mBlacklist));
+    }
+}
diff --git a/services/java/com/android/server/location/LocationFudger.java b/services/java/com/android/server/location/LocationFudger.java
new file mode 100644
index 0000000..2a68743
--- /dev/null
+++ b/services/java/com/android/server/location/LocationFudger.java
@@ -0,0 +1,385 @@
+/*
+ * 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.location;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.security.SecureRandom;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.location.Location;
+import android.location.LocationManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Parcelable;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.util.Log;
+
+
+/**
+ * Contains the logic to obfuscate (fudge) locations for coarse applications.
+ *
+ * <p>The goal is just to prevent applications with only
+ * the coarse location permission from receiving a fine location.
+ */
+public class LocationFudger {
+    private static final boolean D = false;
+    private static final String TAG = "LocationFudge";
+
+    /**
+     * Default coarse accuracy in meters.
+     */
+    private static final float DEFAULT_ACCURACY_IN_METERS = 2000.0f;
+
+    /**
+     * Minimum coarse accuracy in meters.
+     */
+    private static final float MINIMUM_ACCURACY_IN_METERS = 200.0f;
+
+    /**
+     * Secure settings key for coarse accuracy.
+     */
+    private static final String COARSE_ACCURACY_CONFIG_NAME = "locationCoarseAccuracy";
+
+    /**
+     * This is the fastest interval that applications can receive coarse
+     * locations.
+     */
+    public static final long FASTEST_INTERVAL_MS = 10 * 60 * 1000;  // 10 minutes
+
+    /**
+     * The duration until we change the random offset.
+     */
+    private static final long CHANGE_INTERVAL_MS = 60 * 60 * 1000;  // 1 hour
+
+    /**
+     * The percentage that we change the random offset at every interval.
+     *
+     * <p>0.0 indicates the random offset doesn't change. 1.0
+     * indicates the random offset is completely replaced every interval.
+     */
+    private static final double CHANGE_PER_INTERVAL = 0.03;  // 3% change
+
+    // Pre-calculated weights used to move the random offset.
+    //
+    // The goal is to iterate on the previous offset, but keep
+    // the resulting standard deviation the same. The variance of
+    // two gaussian distributions summed together is equal to the
+    // sum of the variance of each distribution. So some quick
+    // algebra results in the following sqrt calculation to
+    // weigh in a new offset while keeping the final standard
+    // deviation unchanged.
+    private static final double NEW_WEIGHT = CHANGE_PER_INTERVAL;
+    private static final double PREVIOUS_WEIGHT = Math.sqrt(1 - NEW_WEIGHT * NEW_WEIGHT);
+
+    /**
+     * This number actually varies because the earth is not round, but
+     * 111,000 meters is considered generally acceptable.
+     */
+    private static final int APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR = 111000;
+
+    /**
+     * Maximum latitude.
+     *
+     * <p>We pick a value 1 meter away from 90.0 degrees in order
+     * to keep cosine(MAX_LATITUDE) to a non-zero value, so that we avoid
+     * divide by zero fails.
+     */
+    private static final double MAX_LATITUDE = 90.0 -
+            (1.0 / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR);
+
+    private final Object mLock = new Object();
+    private final SecureRandom mRandom = new SecureRandom();
+
+    /**
+     * Used to monitor coarse accuracy secure setting for changes.
+     */
+    private final ContentObserver mSettingsObserver;
+
+    /**
+     * Used to resolve coarse accuracy setting.
+     */
+    private final Context mContext;
+
+    // all fields below protected by mLock
+    private double mOffsetLatitudeMeters;
+    private double mOffsetLongitudeMeters;
+    private long mNextInterval;
+
+    /**
+     * Best location accuracy allowed for coarse applications.
+     * This value should only be set by {@link #setAccuracyInMetersLocked(float)}.
+     */
+    private float mAccuracyInMeters;
+
+    /**
+     * The distance between grids for snap-to-grid. See {@link #createCoarse}.
+     * This value should only be set by {@link #setAccuracyInMetersLocked(float)}.
+     */
+    private double mGridSizeInMeters;
+
+    /**
+     * Standard deviation of the (normally distributed) random offset applied
+     * to coarse locations. It does not need to be as large as
+     * {@link #COARSE_ACCURACY_METERS} because snap-to-grid is the primary obfuscation
+     * method. See further details in the implementation.
+     * This value should only be set by {@link #setAccuracyInMetersLocked(float)}.
+     */
+    private double mStandardDeviationInMeters;
+
+    public LocationFudger(Context context, Handler handler) {
+        mContext = context;
+        mSettingsObserver = new ContentObserver(handler) {
+            @Override
+            public void onChange(boolean selfChange) {
+                setAccuracyInMeters(loadCoarseAccuracy());
+            }
+        };
+        mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
+                COARSE_ACCURACY_CONFIG_NAME), false, mSettingsObserver);
+
+        float accuracy = loadCoarseAccuracy();
+        synchronized (mLock) {
+            setAccuracyInMetersLocked(accuracy);
+            mOffsetLatitudeMeters = nextOffsetLocked();
+            mOffsetLongitudeMeters = nextOffsetLocked();
+            mNextInterval = SystemClock.elapsedRealtime() + CHANGE_INTERVAL_MS;
+        }
+    }
+
+    /**
+     * Get the cached coarse location, or generate a new one and cache it.
+     */
+    public Location getOrCreate(Location location) {
+        synchronized (mLock) {
+            Location coarse = location.getExtraLocation(Location.EXTRA_COARSE_LOCATION);
+            if (coarse == null) {
+                return addCoarseLocationExtraLocked(location);
+            }
+            if (coarse.getAccuracy() < mAccuracyInMeters) {
+                return addCoarseLocationExtraLocked(location);
+            }
+            return coarse;
+        }
+    }
+
+    private Location addCoarseLocationExtraLocked(Location location) {
+        Location coarse = createCoarseLocked(location);
+        location.setExtraLocation(Location.EXTRA_COARSE_LOCATION, coarse);
+        return coarse;
+    }
+
+    /**
+     * Create a coarse location.
+     *
+     * <p>Two techniques are used: random offsets and snap-to-grid.
+     *
+     * <p>First we add a random offset. This mitigates against detecting
+     * grid transitions. Without a random offset it is possible to detect
+     * a users position very accurately when they cross a grid boundary.
+     * The random offset changes very slowly over time, to mitigate against
+     * taking many location samples and averaging them out.
+     *
+     * <p>Second we snap-to-grid (quantize). This has the nice property of
+     * producing stable results, and mitigating against taking many samples
+     * to average out a random offset.
+     */
+    private Location createCoarseLocked(Location fine) {
+        Location coarse = new Location(fine);
+
+        // clean all the optional information off the location, because
+        // this can leak detailed location information
+        coarse.removeBearing();
+        coarse.removeSpeed();
+        coarse.removeAltitude();
+        coarse.setExtras(null);
+
+        double lat = coarse.getLatitude();
+        double lon = coarse.getLongitude();
+
+        // wrap
+        lat = wrapLatitude(lat);
+        lon = wrapLongitude(lon);
+
+        // Step 1) apply a random offset
+        //
+        // The goal of the random offset is to prevent the application
+        // from determining that the device is on a grid boundary
+        // when it crosses from one grid to the next.
+        //
+        // We apply the offset even if the location already claims to be
+        // inaccurate, because it may be more accurate than claimed.
+        updateRandomOffsetLocked();
+        // perform lon first whilst lat is still within bounds
+        lon += metersToDegreesLongitude(mOffsetLongitudeMeters, lat);
+        lat += metersToDegreesLatitude(mOffsetLatitudeMeters);
+        if (D) Log.d(TAG, String.format("applied offset of %.0f, %.0f (meters)",
+                mOffsetLongitudeMeters, mOffsetLatitudeMeters));
+
+        // wrap
+        lat = wrapLatitude(lat);
+        lon = wrapLongitude(lon);
+
+        // Step 2) Snap-to-grid (quantize)
+        //
+        // This is the primary means of obfuscation. It gives nice consistent
+        // results and is very effective at hiding the true location
+        // (as long as you are not sitting on a grid boundary, which
+        // step 1 mitigates).
+        //
+        // Note we quantize the latitude first, since the longitude
+        // quantization depends on the latitude value and so leaks information
+        // about the latitude
+        double latGranularity = metersToDegreesLatitude(mGridSizeInMeters);
+        lat = Math.round(lat / latGranularity) * latGranularity;
+        double lonGranularity = metersToDegreesLongitude(mGridSizeInMeters, lat);
+        lon = Math.round(lon / lonGranularity) * lonGranularity;
+
+        // wrap again
+        lat = wrapLatitude(lat);
+        lon = wrapLongitude(lon);
+
+        // apply
+        coarse.setLatitude(lat);
+        coarse.setLongitude(lon);
+        coarse.setAccuracy(Math.max(mAccuracyInMeters, coarse.getAccuracy()));
+
+        if (D) Log.d(TAG, "fudged " + fine + " to " + coarse);
+        return coarse;
+    }
+
+    /**
+     * Update the random offset over time.
+     *
+     * <p>If the random offset was new for every location
+     * fix then an application can more easily average location results
+     * over time,
+     * especially when the location is near a grid boundary. On the
+     * other hand if the random offset is constant then if an application
+     * found a way to reverse engineer the offset they would be able
+     * to detect location at grid boundaries very accurately. So
+     * we choose a random offset and then very slowly move it, to
+     * make both approaches very hard.
+     *
+     * <p>The random offset does not need to be large, because snap-to-grid
+     * is the primary obfuscation mechanism. It just needs to be large
+     * enough to stop information leakage as we cross grid boundaries.
+     */
+    private void updateRandomOffsetLocked() {
+        long now = SystemClock.elapsedRealtime();
+        if (now < mNextInterval) {
+            return;
+        }
+
+        if (D) Log.d(TAG, String.format("old offset: %.0f, %.0f (meters)",
+                mOffsetLongitudeMeters, mOffsetLatitudeMeters));
+
+        // ok, need to update the random offset
+        mNextInterval = now + CHANGE_INTERVAL_MS;
+
+        mOffsetLatitudeMeters *= PREVIOUS_WEIGHT;
+        mOffsetLatitudeMeters += NEW_WEIGHT * nextOffsetLocked();
+        mOffsetLongitudeMeters *= PREVIOUS_WEIGHT;
+        mOffsetLongitudeMeters += NEW_WEIGHT * nextOffsetLocked();
+
+        if (D) Log.d(TAG, String.format("new offset: %.0f, %.0f (meters)",
+                mOffsetLongitudeMeters, mOffsetLatitudeMeters));
+    }
+
+    private double nextOffsetLocked() {
+        return mRandom.nextGaussian() * mStandardDeviationInMeters;
+    }
+
+    private static double wrapLatitude(double lat) {
+         if (lat > MAX_LATITUDE) {
+             lat = MAX_LATITUDE;
+         }
+         if (lat < -MAX_LATITUDE) {
+             lat = -MAX_LATITUDE;
+         }
+         return lat;
+    }
+
+    private static double wrapLongitude(double lon) {
+        lon %= 360.0;  // wraps into range (-360.0, +360.0)
+        if (lon >= 180.0) {
+            lon -= 360.0;
+        }
+        if (lon < -180.0) {
+            lon += 360.0;
+        }
+        return lon;
+    }
+
+    private static double metersToDegreesLatitude(double distance) {
+        return distance / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR;
+    }
+
+    /**
+     * Requires latitude since longitudinal distances change with distance from equator.
+     */
+    private static double metersToDegreesLongitude(double distance, double lat) {
+        return distance / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR / Math.cos(Math.toRadians(lat));
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println(String.format("offset: %.0f, %.0f (meters)", mOffsetLongitudeMeters,
+                mOffsetLatitudeMeters));
+    }
+
+    /**
+     * This is the main control: call this to set the best location accuracy
+     * allowed for coarse applications and all derived values.
+     */
+    private void setAccuracyInMetersLocked(float accuracyInMeters) {
+        mAccuracyInMeters = Math.max(accuracyInMeters, MINIMUM_ACCURACY_IN_METERS);
+        if (D) {
+            Log.d(TAG, "setAccuracyInMetersLocked: new accuracy = " + mAccuracyInMeters);
+        }
+        mGridSizeInMeters = mAccuracyInMeters;
+        mStandardDeviationInMeters = mGridSizeInMeters / 4.0;
+    }
+
+    /**
+     * Same as setAccuracyInMetersLocked without the pre-lock requirement.
+     */
+    private void setAccuracyInMeters(float accuracyInMeters) {
+        synchronized (mLock) {
+            setAccuracyInMetersLocked(accuracyInMeters);
+        }
+    }
+
+    /**
+     * Loads the coarse accuracy value from secure settings.
+     */
+    private float loadCoarseAccuracy() {
+        String newSetting = Settings.Secure.getString(mContext.getContentResolver(),
+                COARSE_ACCURACY_CONFIG_NAME);
+        if (D) {
+            Log.d(TAG, "loadCoarseAccuracy: newSetting = \"" + newSetting + "\"");
+        }
+        if (newSetting == null) {
+            return DEFAULT_ACCURACY_IN_METERS;
+        }
+        try {
+            return Float.parseFloat(newSetting);
+        } catch (NumberFormatException e) {
+            return DEFAULT_ACCURACY_IN_METERS;
+        }
+    }
+}
diff --git a/services/java/com/android/server/location/LocationProviderInterface.java b/services/java/com/android/server/location/LocationProviderInterface.java
index 858a582..80e71f1 100644
--- a/services/java/com/android/server/location/LocationProviderInterface.java
+++ b/services/java/com/android/server/location/LocationProviderInterface.java
@@ -16,42 +16,35 @@
 
 package com.android.server.location;
 
-import android.location.Criteria;
-import android.location.Location;
-import android.net.NetworkInfo;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+import com.android.internal.location.ProviderProperties;
+import com.android.internal.location.ProviderRequest;
+
+
 import android.os.Bundle;
 import android.os.WorkSource;
 
 /**
  * Location Manager's interface for location providers.
- *
- * {@hide}
+ * @hide
  */
 public interface LocationProviderInterface {
-    String getName();
-    boolean requiresNetwork();
-    boolean requiresSatellite();
-    boolean requiresCell();
-    boolean hasMonetaryCost();
-    boolean supportsAltitude();
-    boolean supportsSpeed();
-    boolean supportsBearing();
-    int getPowerRequirement();
-    boolean meetsCriteria(Criteria criteria);
-    int getAccuracy();
-    boolean isEnabled();
-    void enable();
-    void disable();
-    int getStatus(Bundle extras);
-    long getStatusUpdateTime();
-    void enableLocationTracking(boolean enable);
-    /* returns false if single shot is not supported */
-    boolean requestSingleShotFix();
-    String getInternalState();
-    void setMinTime(long minTime, WorkSource ws);
-    void updateNetworkState(int state, NetworkInfo info);
-    void updateLocation(Location location);
-    boolean sendExtraCommand(String command, Bundle extras);
-    void addListener(int uid);
-    void removeListener(int uid);
+    public String getName();
+
+    public void enable();
+    public void disable();
+    public boolean isEnabled();
+    public void setRequest(ProviderRequest request, WorkSource source);
+
+    public void switchUser(int userId);
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args);
+
+    // --- deprecated (but still supported) ---
+    public ProviderProperties getProperties();
+    public int getStatus(Bundle extras);
+    public long getStatusUpdateTime();
+    public boolean sendExtraCommand(String command, Bundle extras);
 }
diff --git a/services/java/com/android/server/location/LocationProviderProxy.java b/services/java/com/android/server/location/LocationProviderProxy.java
index a227ab6..dd2e71c 100644
--- a/services/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/java/com/android/server/location/LocationProviderProxy.java
@@ -16,458 +16,278 @@
 
 package com.android.server.location;
 
-import android.content.ComponentName;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.List;
+
 import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.location.Criteria;
-import android.location.ILocationProvider;
-import android.location.Location;
-import android.net.NetworkInfo;
+import android.location.LocationProvider;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.os.WorkSource;
 import android.util.Log;
 
-import com.android.internal.location.DummyLocationProvider;
+import com.android.internal.location.ProviderProperties;
+import com.android.internal.location.ILocationProvider;
+import com.android.internal.location.ProviderRequest;
+import com.android.server.LocationManagerService;
+import com.android.server.ServiceWatcher;
 
 /**
- * A class for proxying location providers implemented as services.
- *
- * {@hide}
+ * Proxy for ILocationProvider implementations.
  */
 public class LocationProviderProxy implements LocationProviderInterface {
-
     private static final String TAG = "LocationProviderProxy";
-
-    public static final String SERVICE_ACTION =
-        "com.android.location.service.NetworkLocationProvider";
+    private static final boolean D = LocationManagerService.D;
 
     private final Context mContext;
     private final String mName;
-    private final Intent mIntent;
-    private final Handler mHandler;
-    private final Object mMutex = new Object();  // synchronizes access to non-final members
-    private Connection mServiceConnection;  // never null after ctor
+    private final ServiceWatcher mServiceWatcher;
 
-    // cached values set by the location manager
-    private boolean mLocationTracking = false;
+    private Object mLock = new Object();
+
+    // cached values set by the location manager, synchronized on mLock
+    private ProviderProperties mProperties;
     private boolean mEnabled = false;
-    private long mMinTime = -1;
-    private WorkSource mMinTimeSource = new WorkSource();
-    private int mNetworkState;
-    private NetworkInfo mNetworkInfo;
+    private ProviderRequest mRequest = null;
+    private WorkSource mWorksource = new WorkSource();
 
-    // constructor for proxying location providers implemented in a separate service
-    public LocationProviderProxy(Context context, String name, String packageName,
-            Handler handler) {
+    public static LocationProviderProxy createAndBind(Context context, String name, String action,
+            List<String> initialPackageNames, Handler handler, int userId) {
+        LocationProviderProxy proxy = new LocationProviderProxy(context, name, action,
+                initialPackageNames, handler, userId);
+        if (proxy.bind()) {
+            return proxy;
+        } else {
+            return null;
+        }
+    }
+
+    private LocationProviderProxy(Context context, String name, String action,
+            List<String> initialPackageNames, Handler handler, int userId) {
         mContext = context;
         mName = name;
-        mIntent = new Intent(SERVICE_ACTION);
-        mHandler = handler;
-        reconnect(packageName);
+        mServiceWatcher = new ServiceWatcher(mContext, TAG, action, initialPackageNames,
+                mNewServiceWork, handler, userId);
     }
 
-    /** Bind to service. Will reconnect if already connected */
-    public void reconnect(String packageName) {
-        synchronized (mMutex) {
-            if (mServiceConnection != null) {
-                mContext.unbindService(mServiceConnection);
-            }
-            mServiceConnection = new Connection();
-            mIntent.setPackage(packageName);
-            mContext.bindService(mIntent, mServiceConnection,
-                    Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND |
-                    Context.BIND_ALLOW_OOM_MANAGEMENT);
-        }
+    private boolean bind () {
+        return mServiceWatcher.start();
     }
 
-    private class Connection implements ServiceConnection, Runnable {
+    private ILocationProvider getService() {
+        return ILocationProvider.Stub.asInterface(mServiceWatcher.getBinder());
+    }
 
-        private ILocationProvider mProvider;
+    public String getConnectedPackageName() {
+        return mServiceWatcher.getBestPackageName();
+    }
 
-        // for caching requiresNetwork, requiresSatellite, etc.
-        private DummyLocationProvider mCachedAttributes;  // synchronized by mMutex
-
-        public void onServiceConnected(ComponentName className, IBinder service) {
-            synchronized (this) {
-                mProvider = ILocationProvider.Stub.asInterface(service);
-                if (mProvider != null) {
-                    mHandler.post(this);
-                }
-            }
-        }
-
-        public void onServiceDisconnected(ComponentName className) {
-            synchronized (this) {
-                mProvider = null;
-            }
-        }
-
-        public synchronized ILocationProvider getProvider() {
-            return mProvider;
-        }
-
-        public synchronized DummyLocationProvider getCachedAttributes() {
-            return mCachedAttributes;
-        }
-
+    /**
+     * Work to apply current state to a newly connected provider.
+     * Remember we can switch the service that implements a providers
+     * at run-time, so need to apply current state.
+     */
+    private Runnable mNewServiceWork = new Runnable() {
+        @Override
         public void run() {
-            synchronized (mMutex) {
-                if (mServiceConnection != this) {
-                    // This ServiceConnection no longer the one we want to bind to.
-                    return;
-                }
-                ILocationProvider provider = getProvider();
-                if (provider == null) {
-                    return;
+            if (D) Log.d(TAG, "applying state to connected service");
+
+            boolean enabled;
+            ProviderProperties properties = null;
+            ProviderRequest request;
+            WorkSource source;
+            ILocationProvider service;
+            synchronized (mLock) {
+                enabled = mEnabled;
+                request = mRequest;
+                source = mWorksource;
+                service = getService();
+            }
+
+            if (service == null) return;
+
+            try {
+                // load properties from provider
+                properties = service.getProperties();
+                if (properties == null) {
+                    Log.e(TAG, mServiceWatcher.getBestPackageName() +
+                            " has invalid locatino provider properties");
                 }
 
-                // resend previous values from the location manager if the service has restarted
-                try {
-                    if (mEnabled) {
-                        provider.enable();
+                // apply current state to new service
+                if (enabled) {
+                    service.enable();
+                    if (request != null) {
+                        service.setRequest(request, source);
                     }
-                    if (mLocationTracking) {
-                        provider.enableLocationTracking(true);
-                    }
-                    if (mMinTime >= 0) {
-                        provider.setMinTime(mMinTime, mMinTimeSource);
-                    }
-                    if (mNetworkInfo != null) {
-                        provider.updateNetworkState(mNetworkState, mNetworkInfo);
-                    }
-                } catch (RemoteException e) {
                 }
+            } catch (RemoteException e) {
+                Log.w(TAG, e);
+            } catch (Exception e) {
+                // never let remote service crash system server
+                Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
+            }
 
-                // init cache of parameters
-                if (mCachedAttributes == null) {
-                    try {
-                        mCachedAttributes = new DummyLocationProvider(mName, null);
-                        mCachedAttributes.setRequiresNetwork(provider.requiresNetwork());
-                        mCachedAttributes.setRequiresSatellite(provider.requiresSatellite());
-                        mCachedAttributes.setRequiresCell(provider.requiresCell());
-                        mCachedAttributes.setHasMonetaryCost(provider.hasMonetaryCost());
-                        mCachedAttributes.setSupportsAltitude(provider.supportsAltitude());
-                        mCachedAttributes.setSupportsSpeed(provider.supportsSpeed());
-                        mCachedAttributes.setSupportsBearing(provider.supportsBearing());
-                        mCachedAttributes.setPowerRequirement(provider.getPowerRequirement());
-                        mCachedAttributes.setAccuracy(provider.getAccuracy());
-                    } catch (RemoteException e) {
-                        mCachedAttributes = null;
-                    }
-                }
+            synchronized (mLock) {
+                mProperties = properties;
             }
         }
     };
 
+    @Override
     public String getName() {
         return mName;
     }
 
-    private DummyLocationProvider getCachedAttributes() {
-        synchronized (mMutex) {
-            return mServiceConnection.getCachedAttributes();
+    @Override
+    public ProviderProperties getProperties() {
+        synchronized (mLock) {
+            return mProperties;
         }
     }
 
-    public boolean requiresNetwork() {
-        DummyLocationProvider cachedAttributes = getCachedAttributes();
-        if (cachedAttributes != null) {
-            return cachedAttributes.requiresNetwork();
-        } else {
-            return false;
-        }
-    }
-
-    public boolean requiresSatellite() {
-        DummyLocationProvider cachedAttributes = getCachedAttributes();
-        if (cachedAttributes != null) {
-            return cachedAttributes.requiresSatellite();
-        } else {
-            return false;
-        }
-    }
-
-    public boolean requiresCell() {
-        DummyLocationProvider cachedAttributes = getCachedAttributes();
-        if (cachedAttributes != null) {
-            return cachedAttributes.requiresCell();
-        } else {
-            return false;
-        }
-    }
-
-    public boolean hasMonetaryCost() {
-        DummyLocationProvider cachedAttributes = getCachedAttributes();
-        if (cachedAttributes != null) {
-            return cachedAttributes.hasMonetaryCost();
-        } else {
-            return false;
-        }
-    }
-
-    public boolean supportsAltitude() {
-        DummyLocationProvider cachedAttributes = getCachedAttributes();
-        if (cachedAttributes != null) {
-            return cachedAttributes.supportsAltitude();
-        } else {
-            return false;
-        }
-    }
-
-    public boolean supportsSpeed() {
-        DummyLocationProvider cachedAttributes = getCachedAttributes();
-        if (cachedAttributes != null) {
-            return cachedAttributes.supportsSpeed();
-        } else {
-            return false;
-        }
-    }
-
-     public boolean supportsBearing() {
-        DummyLocationProvider cachedAttributes = getCachedAttributes();
-        if (cachedAttributes != null) {
-            return cachedAttributes.supportsBearing();
-        } else {
-            return false;
-        }
-    }
-
-    public int getPowerRequirement() {
-        DummyLocationProvider cachedAttributes = getCachedAttributes();
-        if (cachedAttributes != null) {
-            return cachedAttributes.getPowerRequirement();
-        } else {
-            return -1;
-        }
-    }
-
-    public int getAccuracy() {
-        DummyLocationProvider cachedAttributes = getCachedAttributes();
-        if (cachedAttributes != null) {
-            return cachedAttributes.getAccuracy();
-        } else {
-            return -1;
-        }
-    }
-
-    public boolean meetsCriteria(Criteria criteria) {
-        synchronized (mMutex) {
-            ILocationProvider provider = mServiceConnection.getProvider();
-            if (provider != null) {
-                try {
-                    return provider.meetsCriteria(criteria);
-                } catch (RemoteException e) {
-                }
-            }
-        }
-        // default implementation if we lost connection to the provider
-        if ((criteria.getAccuracy() != Criteria.NO_REQUIREMENT) &&
-            (criteria.getAccuracy() < getAccuracy())) {
-            return false;
-        }
-        int criteriaPower = criteria.getPowerRequirement();
-        if ((criteriaPower != Criteria.NO_REQUIREMENT) &&
-            (criteriaPower < getPowerRequirement())) {
-            return false;
-        }
-        if (criteria.isAltitudeRequired() && !supportsAltitude()) {
-            return false;
-        }
-        if (criteria.isSpeedRequired() && !supportsSpeed()) {
-            return false;
-        }
-        if (criteria.isBearingRequired() && !supportsBearing()) {
-            return false;
-        }
-        return true;
-    }
-
+    @Override
     public void enable() {
-        synchronized (mMutex) {
+        synchronized (mLock) {
             mEnabled = true;
-            ILocationProvider provider = mServiceConnection.getProvider();
-            if (provider != null) {
-                try {
-                    provider.enable();
-                } catch (RemoteException e) {
-                }
-            }
+        }
+        ILocationProvider service = getService();
+        if (service == null) return;
+
+        try {
+            service.enable();
+        } catch (RemoteException e) {
+            Log.w(TAG, e);
+        } catch (Exception e) {
+            // never let remote service crash system server
+            Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
         }
     }
 
+    @Override
     public void disable() {
-        synchronized (mMutex) {
+        synchronized (mLock) {
             mEnabled = false;
-            ILocationProvider provider = mServiceConnection.getProvider();
-            if (provider != null) {
-                try {
-                    provider.disable();
-                } catch (RemoteException e) {
-                }
-            }
+        }
+        ILocationProvider service = getService();
+        if (service == null) return;
+
+        try {
+            service.disable();
+        } catch (RemoteException e) {
+            Log.w(TAG, e);
+        } catch (Exception e) {
+            // never let remote service crash system server
+            Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
         }
     }
 
+    @Override
     public boolean isEnabled() {
-        synchronized (mMutex) {
+        synchronized (mLock) {
             return mEnabled;
         }
     }
 
+    @Override
+    public void setRequest(ProviderRequest request, WorkSource source) {
+        synchronized (mLock) {
+            mRequest = request;
+            mWorksource = source;
+        }
+        ILocationProvider service = getService();
+        if (service == null) return;
+
+        try {
+            service.setRequest(request, source);
+        } catch (RemoteException e) {
+            Log.w(TAG, e);
+        } catch (Exception e) {
+            // never let remote service crash system server
+            Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
+        }
+    }
+
+    @Override
+    public void switchUser(int userId) {
+        mServiceWatcher.switchUser(userId);
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.append("REMOTE SERVICE");
+        pw.append(" name=").append(mName);
+        pw.append(" pkg=").append(mServiceWatcher.getBestPackageName());
+        pw.append(" version=").append("" + mServiceWatcher.getBestVersion());
+        pw.append('\n');
+
+        ILocationProvider service = getService();
+        if (service == null) {
+            pw.println("service down (null)");
+            return;
+        }
+        pw.flush();
+
+        try {
+            service.asBinder().dump(fd, args);
+        } catch (RemoteException e) {
+            pw.println("service down (RemoteException)");
+            Log.w(TAG, e);
+        } catch (Exception e) {
+            pw.println("service down (Exception)");
+            // never let remote service crash system server
+            Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
+        }
+    }
+
+    @Override
     public int getStatus(Bundle extras) {
-        ILocationProvider provider;
-        synchronized (mMutex) {
-            provider = mServiceConnection.getProvider();
+        ILocationProvider service = getService();
+        if (service == null) return LocationProvider.TEMPORARILY_UNAVAILABLE;
+
+        try {
+            return service.getStatus(extras);
+        } catch (RemoteException e) {
+            Log.w(TAG, e);
+        } catch (Exception e) {
+            // never let remote service crash system server
+            Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
         }
-        if (provider != null) {
-            try {
-                return provider.getStatus(extras);
-            } catch (RemoteException e) {
-            }
-        }
-        return 0;
+        return LocationProvider.TEMPORARILY_UNAVAILABLE;
     }
 
+    @Override
     public long getStatusUpdateTime() {
-        ILocationProvider provider;
-        synchronized (mMutex) {
-            provider = mServiceConnection.getProvider();
-        }
-        if (provider != null) {
-            try {
-                return provider.getStatusUpdateTime();
-            } catch (RemoteException e) {
-            }
+        ILocationProvider service = getService();
+        if (service == null) return 0;
+
+        try {
+            return service.getStatusUpdateTime();
+        } catch (RemoteException e) {
+            Log.w(TAG, e);
+        } catch (Exception e) {
+            // never let remote service crash system server
+            Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
         }
         return 0;
-     }
-
-    public String getInternalState() {
-        ILocationProvider provider;
-        synchronized (mMutex) {
-            provider = mServiceConnection.getProvider();
-        }
-        if (provider != null) {
-            try {
-                return provider.getInternalState();
-            } catch (RemoteException e) {
-                Log.e(TAG, "getInternalState failed", e);
-            }
-        }
-        return null;
     }
 
-    public boolean isLocationTracking() {
-        synchronized (mMutex) {
-            return mLocationTracking;
-        }
-    }
-
-    public void enableLocationTracking(boolean enable) {
-        synchronized (mMutex) {
-            mLocationTracking = enable;
-            if (!enable) {
-                mMinTime = -1;
-                mMinTimeSource.clear();
-            }
-            ILocationProvider provider = mServiceConnection.getProvider();
-            if (provider != null) {
-                try {
-                    provider.enableLocationTracking(enable);
-                } catch (RemoteException e) {
-                }
-            }
-        }
-    }
-
-    public boolean requestSingleShotFix() {
-        return false;
-    }
-
-    public long getMinTime() {
-        synchronized (mMutex) {
-            return mMinTime;
-        }
-    }
-
-    public void setMinTime(long minTime, WorkSource ws) {
-        synchronized (mMutex) {
-            mMinTime = minTime;
-            mMinTimeSource.set(ws);
-            ILocationProvider provider = mServiceConnection.getProvider();
-            if (provider != null) {
-                try {
-                    provider.setMinTime(minTime, ws);
-                } catch (RemoteException e) {
-                }
-            }
-        }
-    }
-
-    public void updateNetworkState(int state, NetworkInfo info) {
-        synchronized (mMutex) {
-            mNetworkState = state;
-            mNetworkInfo = info;
-            ILocationProvider provider = mServiceConnection.getProvider();
-            if (provider != null) {
-                try {
-                    provider.updateNetworkState(state, info);
-                } catch (RemoteException e) {
-                }
-            }
-        }
-    }
-
-    public void updateLocation(Location location) {
-        synchronized (mMutex) {
-            ILocationProvider provider = mServiceConnection.getProvider();
-            if (provider != null) {
-                try {
-                    provider.updateLocation(location);
-                } catch (RemoteException e) {
-                }
-            }
-        }
-    }
-
+    @Override
     public boolean sendExtraCommand(String command, Bundle extras) {
-        synchronized (mMutex) {
-            ILocationProvider provider = mServiceConnection.getProvider();
-            if (provider != null) {
-                try {
-                    return provider.sendExtraCommand(command, extras);
-                } catch (RemoteException e) {
-                }
-            }
+        ILocationProvider service = getService();
+        if (service == null) return false;
+
+        try {
+            return service.sendExtraCommand(command, extras);
+        } catch (RemoteException e) {
+            Log.w(TAG, e);
+        } catch (Exception e) {
+            // never let remote service crash system server
+            Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
         }
         return false;
     }
-
-    public void addListener(int uid) {
-        synchronized (mMutex) {
-            ILocationProvider provider = mServiceConnection.getProvider();
-            if (provider != null) {
-                try {
-                    provider.addListener(uid);
-                } catch (RemoteException e) {
-                }
-            }
-        }
-    }
-
-    public void removeListener(int uid) {
-        synchronized (mMutex) {
-            ILocationProvider provider = mServiceConnection.getProvider();
-            if (provider != null) {
-                try {
-                    provider.removeListener(uid);
-                } catch (RemoteException e) {
-                }
-            }
-        }
-    }
-}
+ }
diff --git a/services/java/com/android/server/location/MockProvider.java b/services/java/com/android/server/location/MockProvider.java
index 09d799f..1194cbc 100644
--- a/services/java/com/android/server/location/MockProvider.java
+++ b/services/java/com/android/server/location/MockProvider.java
@@ -20,15 +20,19 @@
 import android.location.ILocationManager;
 import android.location.Location;
 import android.location.LocationProvider;
-import android.net.NetworkInfo;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.WorkSource;
 import android.util.Log;
 import android.util.PrintWriterPrinter;
 
+
+import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
+import com.android.internal.location.ProviderProperties;
+import com.android.internal.location.ProviderRequest;
+
 /**
  * A mock location provider used by LocationManagerService to implement test providers.
  *
@@ -36,60 +40,56 @@
  */
 public class MockProvider implements LocationProviderInterface {
     private final String mName;
+    private final ProviderProperties mProperties;
     private final ILocationManager mLocationManager;
-    private final boolean mRequiresNetwork;
-    private final boolean mRequiresSatellite;
-    private final boolean mRequiresCell;
-    private final boolean mHasMonetaryCost;
-    private final boolean mSupportsAltitude;
-    private final boolean mSupportsSpeed;
-    private final boolean mSupportsBearing;
-    private final int mPowerRequirement;
-    private final int mAccuracy;
+
     private final Location mLocation;
+    private final Bundle mExtras = new Bundle();
+
     private int mStatus;
     private long mStatusUpdateTime;
-    private final Bundle mExtras = new Bundle();
     private boolean mHasLocation;
     private boolean mHasStatus;
     private boolean mEnabled;
 
     private static final String TAG = "MockProvider";
 
-    public MockProvider(String name,  ILocationManager locationManager,
-        boolean requiresNetwork, boolean requiresSatellite,
-        boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
-        boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
+    public MockProvider(String name, ILocationManager locationManager,
+            ProviderProperties properties) {
+        if (properties == null) throw new NullPointerException("properties is null");
+
         mName = name;
         mLocationManager = locationManager;
-        mRequiresNetwork = requiresNetwork;
-        mRequiresSatellite = requiresSatellite;
-        mRequiresCell = requiresCell;
-        mHasMonetaryCost = hasMonetaryCost;
-        mSupportsAltitude = supportsAltitude;
-        mSupportsBearing = supportsBearing;
-        mSupportsSpeed = supportsSpeed;
-        mPowerRequirement = powerRequirement;
-        mAccuracy = accuracy;
+        mProperties = properties;
         mLocation = new Location(name);
     }
 
+    @Override
     public String getName() {
         return mName;
     }
 
+    @Override
+    public ProviderProperties getProperties() {
+        return mProperties;
+    }
+
+    @Override
     public void disable() {
         mEnabled = false;
     }
 
+    @Override
     public void enable() {
         mEnabled = true;
     }
 
+    @Override
     public boolean isEnabled() {
         return mEnabled;
     }
 
+    @Override
     public int getStatus(Bundle extras) {
         if (mHasStatus) {
             extras.clear();
@@ -100,75 +100,20 @@
         }
     }
 
+    @Override
     public long getStatusUpdateTime() {
         return mStatusUpdateTime;
     }
 
-    public int getAccuracy() {
-        return mAccuracy;
-    }
-
-    public int getPowerRequirement() {
-        return mPowerRequirement;
-    }
-
-    public boolean hasMonetaryCost() {
-        return mHasMonetaryCost;
-    }
-
-    public boolean requiresCell() {
-        return mRequiresCell;
-    }
-
-    public boolean requiresNetwork() {
-        return mRequiresNetwork;
-    }
-
-    public boolean requiresSatellite() {
-        return mRequiresSatellite;
-    }
-
-    public boolean supportsAltitude() {
-        return mSupportsAltitude;
-    }
-
-    public boolean supportsBearing() {
-        return mSupportsBearing;
-    }
-
-    public boolean supportsSpeed() {
-        return mSupportsSpeed;
-    }
-
-    public boolean meetsCriteria(Criteria criteria) {
-        if ((criteria.getAccuracy() != Criteria.NO_REQUIREMENT) &&
-            (criteria.getAccuracy() < mAccuracy)) {
-            return false;
-        }
-        int criteriaPower = criteria.getPowerRequirement();
-        if ((criteriaPower != Criteria.NO_REQUIREMENT) &&
-            (criteriaPower < mPowerRequirement)) {
-            return false;
-        }
-        if (criteria.isAltitudeRequired() && !mSupportsAltitude) {
-            return false;
-        }
-        if (criteria.isSpeedRequired() && !mSupportsSpeed) {
-            return false;
-        }
-        if (criteria.isBearingRequired() && !mSupportsBearing) {
-            return false;
-        }
-        return true;
-    }
-
     public void setLocation(Location l) {
         mLocation.set(l);
         mHasLocation = true;
-        try {
-            mLocationManager.reportLocation(mLocation, false);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException calling reportLocation");
+        if (mEnabled) {
+            try {
+                mLocationManager.reportLocation(mLocation, false);
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException calling reportLocation");
+            }
         }
     }
 
@@ -191,34 +136,9 @@
         mStatusUpdateTime = 0;
     }
 
-    public String getInternalState() {
-        return null;
-    }
-
-    public void enableLocationTracking(boolean enable) {
-    }
-
-    public boolean requestSingleShotFix() {
-        return false;
-    }
-
-    public void setMinTime(long minTime, WorkSource ws) {
-    }
-
-    public void updateNetworkState(int state, NetworkInfo info) {
-    }
-
-    public void updateLocation(Location location) {
-    }
-
-    public boolean sendExtraCommand(String command, Bundle extras) {
-        return false;
-    }
-
-    public void addListener(int uid) {
-    }
-
-    public void removeListener(int uid) {
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        dump(pw, "");
     }
 
     public void dump(PrintWriter pw, String prefix) {
@@ -231,4 +151,17 @@
         pw.println(prefix + "mStatusUpdateTime=" + mStatusUpdateTime);
         pw.println(prefix + "mExtras=" + mExtras);
     }
+
+    @Override
+    public void setRequest(ProviderRequest request, WorkSource source) { }
+
+    @Override
+    public void switchUser(int userId) {
+        // nothing to do here
+    }
+
+    @Override
+    public boolean sendExtraCommand(String command, Bundle extras) {
+        return false;
+    }
 }
diff --git a/services/java/com/android/server/location/PassiveProvider.java b/services/java/com/android/server/location/PassiveProvider.java
index ea0d1b0..734c572 100644
--- a/services/java/com/android/server/location/PassiveProvider.java
+++ b/services/java/com/android/server/location/PassiveProvider.java
@@ -16,17 +16,23 @@
 
 package com.android.server.location;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+import com.android.internal.location.ProviderProperties;
+import com.android.internal.location.ProviderRequest;
+
 import android.location.Criteria;
 import android.location.ILocationManager;
 import android.location.Location;
 import android.location.LocationManager;
 import android.location.LocationProvider;
-import android.net.NetworkInfo;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.WorkSource;
 import android.util.Log;
 
+
 /**
  * A passive location provider reports locations received from other providers
  * for clients that want to listen passively without actually triggering
@@ -35,103 +41,68 @@
  * {@hide}
  */
 public class PassiveProvider implements LocationProviderInterface {
-
     private static final String TAG = "PassiveProvider";
 
+    private static final ProviderProperties PROPERTIES = new ProviderProperties(
+            false, false, false, false, false, false, false,
+            Criteria.POWER_LOW, Criteria.ACCURACY_COARSE);
+
     private final ILocationManager mLocationManager;
-    private boolean mTracking;
+    private boolean mReportLocation;
 
     public PassiveProvider(ILocationManager locationManager) {
         mLocationManager = locationManager;
     }
 
+    @Override
     public String getName() {
         return LocationManager.PASSIVE_PROVIDER;
     }
 
-    public boolean requiresNetwork() {
-        return false;
+    @Override
+    public ProviderProperties getProperties() {
+        return PROPERTIES;
     }
 
-    public boolean requiresSatellite() {
-        return false;
-    }
-
-    public boolean requiresCell() {
-        return false;
-    }
-
-    public boolean hasMonetaryCost() {
-        return false;
-    }
-
-    public boolean supportsAltitude() {
-        return false;
-    }
-
-    public boolean supportsSpeed() {
-        return false;
-    }
-
-    public boolean supportsBearing() {
-        return false;
-    }
-
-    public int getPowerRequirement() {
-        return -1;
-    }
-
-    public boolean meetsCriteria(Criteria criteria) {
-        // We do not want to match the special passive provider based on criteria.
-        return false;
-    }
-
-    public int getAccuracy() {
-        return -1;
-    }
-
+    @Override
     public boolean isEnabled() {
         return true;
     }
 
+    @Override
     public void enable() {
     }
 
+    @Override
     public void disable() {
     }
 
+    @Override
     public int getStatus(Bundle extras) {
-        if (mTracking) {
+        if (mReportLocation) {
             return LocationProvider.AVAILABLE;
         } else {
             return LocationProvider.TEMPORARILY_UNAVAILABLE;
         }
     }
 
+    @Override
     public long getStatusUpdateTime() {
         return -1;
     }
 
-    public String getInternalState() {
-        return null;
+    @Override
+    public void setRequest(ProviderRequest request, WorkSource source) {
+        mReportLocation = request.reportLocation;
     }
 
-    public void enableLocationTracking(boolean enable) {
-        mTracking = enable;
-    }
-
-    public boolean requestSingleShotFix() {
-        return false;
-    }
-
-    public void setMinTime(long minTime, WorkSource ws) {
-    }
-
-    public void updateNetworkState(int state, NetworkInfo info) {
+    @Override
+    public void switchUser(int userId) {
+        // nothing to do here
     }
 
     public void updateLocation(Location location) {
-        if (mTracking) {
+        if (mReportLocation) {
             try {
                 // pass the location back to the location manager
                 mLocationManager.reportLocation(location, true);
@@ -141,13 +112,13 @@
         }
     }
 
+    @Override
     public boolean sendExtraCommand(String command, Bundle extras) {
         return false;
     }
 
-    public void addListener(int uid) {
-    }
-
-    public void removeListener(int uid) {
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("mReportLocation=" + mReportLocation);
     }
 }
diff --git a/services/java/com/android/server/net/BaseNetworkObserver.java b/services/java/com/android/server/net/BaseNetworkObserver.java
new file mode 100644
index 0000000..8b2aa5d
--- /dev/null
+++ b/services/java/com/android/server/net/BaseNetworkObserver.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+package com.android.server.net;
+
+import android.net.INetworkManagementEventObserver;
+
+/**
+ * Base {@link INetworkManagementEventObserver} that provides no-op
+ * implementations which can be overridden.
+ *
+ * @hide
+ */
+public class BaseNetworkObserver extends INetworkManagementEventObserver.Stub {
+    @Override
+    public void interfaceStatusChanged(String iface, boolean up) {
+        // default no-op
+    }
+
+    @Override
+    public void interfaceRemoved(String iface) {
+        // default no-op
+    }
+
+    @Override
+    public void interfaceLinkStateChanged(String iface, boolean up) {
+        // default no-op
+    }
+
+    @Override
+    public void interfaceAdded(String iface) {
+        // default no-op
+    }
+
+    @Override
+    public void interfaceClassDataActivityChanged(String label, boolean active) {
+        // default no-op
+    }
+
+    @Override
+    public void limitReached(String limitName, String iface) {
+        // default no-op
+    }
+}
diff --git a/services/java/com/android/server/net/LockdownVpnTracker.java b/services/java/com/android/server/net/LockdownVpnTracker.java
new file mode 100644
index 0000000..f32dd09
--- /dev/null
+++ b/services/java/com/android/server/net/LockdownVpnTracker.java
@@ -0,0 +1,294 @@
+/*
+ * 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.net;
+
+import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.LinkProperties;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkInfo.State;
+import android.os.INetworkManagementService;
+import android.os.RemoteException;
+import android.security.Credentials;
+import android.security.KeyStore;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import com.android.internal.R;
+import com.android.internal.net.VpnConfig;
+import com.android.internal.net.VpnProfile;
+import com.android.internal.util.Preconditions;
+import com.android.server.ConnectivityService;
+import com.android.server.EventLogTags;
+import com.android.server.connectivity.Vpn;
+
+/**
+ * State tracker for lockdown mode. Watches for normal {@link NetworkInfo} to be
+ * connected and kicks off VPN connection, managing any required {@code netd}
+ * firewall rules.
+ */
+public class LockdownVpnTracker {
+    private static final String TAG = "LockdownVpnTracker";
+
+    /** Number of VPN attempts before waiting for user intervention. */
+    private static final int MAX_ERROR_COUNT = 4;
+
+    private static final String ACTION_LOCKDOWN_RESET = "com.android.server.action.LOCKDOWN_RESET";
+    private static final String ACTION_VPN_SETTINGS = "android.net.vpn.SETTINGS";
+
+    private final Context mContext;
+    private final INetworkManagementService mNetService;
+    private final ConnectivityService mConnService;
+    private final Vpn mVpn;
+    private final VpnProfile mProfile;
+
+    private final Object mStateLock = new Object();
+
+    private PendingIntent mResetIntent;
+
+    private String mAcceptedEgressIface;
+    private String mAcceptedIface;
+    private String mAcceptedSourceAddr;
+
+    private int mErrorCount;
+
+    public static boolean isEnabled() {
+        return KeyStore.getInstance().contains(Credentials.LOCKDOWN_VPN);
+    }
+
+    public LockdownVpnTracker(Context context, INetworkManagementService netService,
+            ConnectivityService connService, Vpn vpn, VpnProfile profile) {
+        mContext = Preconditions.checkNotNull(context);
+        mNetService = Preconditions.checkNotNull(netService);
+        mConnService = Preconditions.checkNotNull(connService);
+        mVpn = Preconditions.checkNotNull(vpn);
+        mProfile = Preconditions.checkNotNull(profile);
+
+        final Intent resetIntent = new Intent(ACTION_LOCKDOWN_RESET);
+        resetIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        mResetIntent = PendingIntent.getBroadcast(mContext, 0, resetIntent, 0);
+    }
+
+    private BroadcastReceiver mResetReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            reset();
+        }
+    };
+
+    /**
+     * Watch for state changes to both active egress network, kicking off a VPN
+     * connection when ready, or setting firewall rules once VPN is connected.
+     */
+    private void handleStateChangedLocked() {
+        Slog.d(TAG, "handleStateChanged()");
+
+        final NetworkInfo egressInfo = mConnService.getActiveNetworkInfoUnfiltered();
+        final LinkProperties egressProp = mConnService.getActiveLinkProperties();
+
+        final NetworkInfo vpnInfo = mVpn.getNetworkInfo();
+        final VpnConfig vpnConfig = mVpn.getLegacyVpnConfig();
+
+        // Restart VPN when egress network disconnected or changed
+        final boolean egressDisconnected = egressInfo == null
+                || State.DISCONNECTED.equals(egressInfo.getState());
+        final boolean egressChanged = egressProp == null
+                || !TextUtils.equals(mAcceptedEgressIface, egressProp.getInterfaceName());
+        if (egressDisconnected || egressChanged) {
+            clearSourceRulesLocked();
+            mAcceptedEgressIface = null;
+            mVpn.stopLegacyVpn();
+        }
+        if (egressDisconnected) return;
+
+        final int egressType = egressInfo.getType();
+        if (vpnInfo.getDetailedState() == DetailedState.FAILED) {
+            EventLogTags.writeLockdownVpnError(egressType);
+        }
+
+        if (mErrorCount > MAX_ERROR_COUNT) {
+            showNotification(R.string.vpn_lockdown_error, R.drawable.vpn_disconnected);
+
+        } else if (egressInfo.isConnected() && !vpnInfo.isConnectedOrConnecting()) {
+            if (mProfile.isValidLockdownProfile()) {
+                Slog.d(TAG, "Active network connected; starting VPN");
+                EventLogTags.writeLockdownVpnConnecting(egressType);
+                showNotification(R.string.vpn_lockdown_connecting, R.drawable.vpn_disconnected);
+
+                mAcceptedEgressIface = egressProp.getInterfaceName();
+                mVpn.startLegacyVpn(mProfile, KeyStore.getInstance(), egressProp);
+
+            } else {
+                Slog.e(TAG, "Invalid VPN profile; requires IP-based server and DNS");
+                showNotification(R.string.vpn_lockdown_error, R.drawable.vpn_disconnected);
+            }
+
+        } else if (vpnInfo.isConnected() && vpnConfig != null) {
+            final String iface = vpnConfig.interfaze;
+            final String sourceAddr = vpnConfig.addresses;
+
+            if (TextUtils.equals(iface, mAcceptedIface)
+                    && TextUtils.equals(sourceAddr, mAcceptedSourceAddr)) {
+                return;
+            }
+
+            Slog.d(TAG, "VPN connected using iface=" + iface + ", sourceAddr=" + sourceAddr);
+            EventLogTags.writeLockdownVpnConnected(egressType);
+            showNotification(R.string.vpn_lockdown_connected, R.drawable.vpn_connected);
+
+            try {
+                clearSourceRulesLocked();
+
+                mNetService.setFirewallInterfaceRule(iface, true);
+                mNetService.setFirewallEgressSourceRule(sourceAddr, true);
+
+                mErrorCount = 0;
+                mAcceptedIface = iface;
+                mAcceptedSourceAddr = sourceAddr;
+            } catch (RemoteException e) {
+                throw new RuntimeException("Problem setting firewall rules", e);
+            }
+
+            mConnService.sendConnectedBroadcast(augmentNetworkInfo(egressInfo));
+        }
+    }
+
+    public void init() {
+        synchronized (mStateLock) {
+            initLocked();
+        }
+    }
+
+    private void initLocked() {
+        Slog.d(TAG, "initLocked()");
+
+        mVpn.setEnableNotifications(false);
+
+        final IntentFilter resetFilter = new IntentFilter(ACTION_LOCKDOWN_RESET);
+        mContext.registerReceiver(mResetReceiver, resetFilter, CONNECTIVITY_INTERNAL, null);
+
+        try {
+            // TODO: support non-standard port numbers
+            mNetService.setFirewallEgressDestRule(mProfile.server, 500, true);
+            mNetService.setFirewallEgressDestRule(mProfile.server, 4500, true);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Problem setting firewall rules", e);
+        }
+
+        synchronized (mStateLock) {
+            handleStateChangedLocked();
+        }
+    }
+
+    public void shutdown() {
+        synchronized (mStateLock) {
+            shutdownLocked();
+        }
+    }
+
+    private void shutdownLocked() {
+        Slog.d(TAG, "shutdownLocked()");
+
+        mAcceptedEgressIface = null;
+        mErrorCount = 0;
+
+        mVpn.stopLegacyVpn();
+        try {
+            mNetService.setFirewallEgressDestRule(mProfile.server, 500, false);
+            mNetService.setFirewallEgressDestRule(mProfile.server, 4500, false);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Problem setting firewall rules", e);
+        }
+        clearSourceRulesLocked();
+        hideNotification();
+
+        mContext.unregisterReceiver(mResetReceiver);
+        mVpn.setEnableNotifications(true);
+    }
+
+    public void reset() {
+        synchronized (mStateLock) {
+            // cycle tracker, reset error count, and trigger retry
+            shutdownLocked();
+            initLocked();
+            handleStateChangedLocked();
+        }
+    }
+
+    private void clearSourceRulesLocked() {
+        try {
+            if (mAcceptedIface != null) {
+                mNetService.setFirewallInterfaceRule(mAcceptedIface, false);
+                mAcceptedIface = null;
+            }
+            if (mAcceptedSourceAddr != null) {
+                mNetService.setFirewallEgressSourceRule(mAcceptedSourceAddr, false);
+                mAcceptedSourceAddr = null;
+            }
+        } catch (RemoteException e) {
+            throw new RuntimeException("Problem setting firewall rules", e);
+        }
+    }
+
+    public void onNetworkInfoChanged(NetworkInfo info) {
+        synchronized (mStateLock) {
+            handleStateChangedLocked();
+        }
+    }
+
+    public void onVpnStateChanged(NetworkInfo info) {
+        if (info.getDetailedState() == DetailedState.FAILED) {
+            mErrorCount++;
+        }
+        synchronized (mStateLock) {
+            handleStateChangedLocked();
+        }
+    }
+
+    public NetworkInfo augmentNetworkInfo(NetworkInfo info) {
+        if (info.isConnected()) {
+            final NetworkInfo vpnInfo = mVpn.getNetworkInfo();
+            info = new NetworkInfo(info);
+            info.setDetailedState(vpnInfo.getDetailedState(), vpnInfo.getReason(), null);
+        }
+        return info;
+    }
+
+    private void showNotification(int titleRes, int iconRes) {
+        final Notification.Builder builder = new Notification.Builder(mContext);
+        builder.setWhen(0);
+        builder.setSmallIcon(iconRes);
+        builder.setContentTitle(mContext.getString(titleRes));
+        builder.setContentText(mContext.getString(R.string.vpn_lockdown_reset));
+        builder.setContentIntent(mResetIntent);
+        builder.setPriority(Notification.PRIORITY_LOW);
+        builder.setOngoing(true);
+        NotificationManager.from(mContext).notify(TAG, 0, builder.build());
+    }
+
+    private void hideNotification() {
+        NotificationManager.from(mContext).cancel(TAG, 0);
+    }
+}
diff --git a/services/java/com/android/server/net/NetworkAlertObserver.java b/services/java/com/android/server/net/NetworkAlertObserver.java
deleted file mode 100644
index 0d1c3b2..0000000
--- a/services/java/com/android/server/net/NetworkAlertObserver.java
+++ /dev/null
@@ -1,44 +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.
- */
-
-package com.android.server.net;
-
-import android.net.INetworkManagementEventObserver;
-
-/**
- * @hide
- */
-public abstract class NetworkAlertObserver extends INetworkManagementEventObserver.Stub {
-    @Override
-    public void interfaceStatusChanged(String iface, boolean up) {
-        // ignored; interface changes come through ConnectivityService
-    }
-
-    @Override
-    public void interfaceRemoved(String iface) {
-        // ignored; interface changes come through ConnectivityService
-    }
-
-    @Override
-    public void interfaceLinkStateChanged(String iface, boolean up) {
-        // ignored; interface changes come through ConnectivityService
-    }
-
-    @Override
-    public void interfaceAdded(String iface) {
-        // ignored; interface changes come through ConnectivityService
-    }
-}
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index fe43d11..43ddf8d 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -24,6 +24,8 @@
 import static android.Manifest.permission.READ_PHONE_STATE;
 import static android.content.Intent.ACTION_PACKAGE_ADDED;
 import static android.content.Intent.ACTION_UID_REMOVED;
+import static android.content.Intent.ACTION_USER_ADDED;
+import static android.content.Intent.ACTION_USER_REMOVED;
 import static android.content.Intent.EXTRA_UID;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
 import static android.net.ConnectivityManager.TYPE_ETHERNET;
@@ -112,11 +114,13 @@
 import android.os.MessageQueue.IdleHandler;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
-import android.os.UserId;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
 import android.text.format.Formatter;
 import android.text.format.Time;
+import android.util.AtomicFile;
 import android.util.Log;
 import android.util.NtpTrustedTime;
 import android.util.Slog;
@@ -127,7 +131,6 @@
 import android.util.Xml;
 
 import com.android.internal.R;
-import com.android.internal.os.AtomicFile;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Objects;
@@ -178,7 +181,8 @@
     private static final int VERSION_ADDED_INFERRED = 7;
     private static final int VERSION_SWITCH_APP_ID = 8;
     private static final int VERSION_ADDED_NETWORK_ID = 9;
-    private static final int VERSION_LATEST = VERSION_ADDED_NETWORK_ID;
+    private static final int VERSION_SWITCH_UID = 10;
+    private static final int VERSION_LATEST = VERSION_SWITCH_UID;
 
     // @VisibleForTesting
     public static final int TYPE_WARNING = 0x1;
@@ -249,8 +253,8 @@
     /** Currently active network rules for ifaces. */
     private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap();
 
-    /** Defined app policies. */
-    private SparseIntArray mAppPolicy = new SparseIntArray();
+    /** Defined UID policies. */
+    private SparseIntArray mUidPolicy = new SparseIntArray();
     /** Currently derived rules for each UID. */
     private SparseIntArray mUidRules = new SparseIntArray();
 
@@ -356,12 +360,22 @@
         final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
         mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
 
-        // listen for package/uid changes to update policy
+        // listen for package changes to update policy
         final IntentFilter packageFilter = new IntentFilter();
         packageFilter.addAction(ACTION_PACKAGE_ADDED);
-        packageFilter.addAction(ACTION_UID_REMOVED);
+        packageFilter.addDataScheme("package");
         mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler);
 
+        // listen for UID changes to update policy
+        mContext.registerReceiver(
+                mUidRemovedReceiver, new IntentFilter(ACTION_UID_REMOVED), null, mHandler);
+
+        // listen for user changes to update policy
+        final IntentFilter userFilter = new IntentFilter();
+        userFilter.addAction(ACTION_USER_ADDED);
+        userFilter.addAction(ACTION_USER_REMOVED);
+        mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
+
         // listen for stats update events
         final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED);
         mContext.registerReceiver(
@@ -420,37 +434,62 @@
     private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            // on background handler thread, and PACKAGE_ADDED and UID_REMOVED
-            // are protected broadcasts.
+            // on background handler thread, and PACKAGE_ADDED is protected
 
             final String action = intent.getAction();
-            final int uid = intent.getIntExtra(EXTRA_UID, 0);
-            final int appId = UserId.getAppId(uid);
-            synchronized (mRulesLock) {
-                if (ACTION_PACKAGE_ADDED.equals(action)) {
-                    // NOTE: PACKAGE_ADDED is currently only sent once, and is
-                    // not broadcast when users are added.
+            final int uid = intent.getIntExtra(EXTRA_UID, -1);
+            if (uid == -1) return;
 
-                    // update rules for UID, since it might be subject to
-                    // global background data policy.
-                    if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
-                    updateRulesForAppLocked(appId);
-
-                } else if (ACTION_UID_REMOVED.equals(action)) {
-                    // NOTE: UID_REMOVED is currently only sent once, and is not
-                    // broadcast when users are removed.
-
-                    // remove any policy and update rules to clean up.
-                    if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
-
-                    mAppPolicy.delete(appId);
-                    updateRulesForAppLocked(appId);
-                    writePolicyLocked();
+            if (ACTION_PACKAGE_ADDED.equals(action)) {
+                // update rules for UID, since it might be subject to
+                // global background data policy
+                if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
+                synchronized (mRulesLock) {
+                    updateRulesForUidLocked(uid);
                 }
             }
         }
     };
 
+    private BroadcastReceiver mUidRemovedReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // on background handler thread, and UID_REMOVED is protected
+
+            final int uid = intent.getIntExtra(EXTRA_UID, -1);
+            if (uid == -1) return;
+
+            // remove any policy and update rules to clean up
+            if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
+            synchronized (mRulesLock) {
+                mUidPolicy.delete(uid);
+                updateRulesForUidLocked(uid);
+                writePolicyLocked();
+            }
+        }
+    };
+
+    private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // on background handler thread, and USER_ADDED and USER_REMOVED
+            // broadcasts are protected
+
+            final String action = intent.getAction();
+            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+            if (userId == -1) return;
+
+            // Remove any policies for given user; both cleaning up after a
+            // USER_REMOVED, and one last sanity check during USER_ADDED
+            removePoliciesForUserLocked(userId);
+
+            // Update global restrict for new user
+            synchronized (mRulesLock) {
+                updateRulesForRestrictBackgroundLocked();
+            }
+        }
+    };
+
     /**
      * Receiver that watches for {@link INetworkStatsService} updates, which we
      * use to check against {@link NetworkPolicy#warningBytes}.
@@ -570,7 +609,7 @@
     /**
      * Observer that watches for {@link INetworkManagementService} alerts.
      */
-    private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() {
+    private INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() {
         @Override
         public void limitReached(String limitName, String iface) {
             // only someone like NMS should be calling us
@@ -787,11 +826,13 @@
         }
 
         // TODO: move to NotificationManager once we can mock it
+        // XXX what to do about multi-user?
         try {
             final String packageName = mContext.getPackageName();
             final int[] idReceived = new int[1];
             mNotifManager.enqueueNotificationWithTag(
-                    packageName, tag, 0x0, builder.getNotification(), idReceived);
+                    packageName, tag, 0x0, builder.getNotification(), idReceived,
+                    UserHandle.USER_OWNER);
             mActiveNotifs.add(tag);
         } catch (RemoteException e) {
             // ignored; service lives in system_server
@@ -821,11 +862,12 @@
                 PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
 
         // TODO: move to NotificationManager once we can mock it
+        // XXX what to do about multi-user?
         try {
             final String packageName = mContext.getPackageName();
             final int[] idReceived = new int[1];
             mNotifManager.enqueueNotificationWithTag(packageName, tag,
-                    0x0, builder.getNotification(), idReceived);
+                    0x0, builder.getNotification(), idReceived, UserHandle.USER_OWNER);
             mActiveNotifs.add(tag);
         } catch (RemoteException e) {
             // ignored; service lives in system_server
@@ -834,10 +876,11 @@
 
     private void cancelNotification(String tag) {
         // TODO: move to NotificationManager once we can mock it
+        // XXX what to do about multi-user?
         try {
             final String packageName = mContext.getPackageName();
             mNotifManager.cancelNotificationWithTag(
-                    packageName, tag, 0x0);
+                    packageName, tag, 0x0, UserHandle.USER_OWNER);
         } catch (RemoteException e) {
             // ignored; service lives in system_server
         }
@@ -1102,7 +1145,7 @@
 
         // clear any existing policy and read from disk
         mNetworkPolicy.clear();
-        mAppPolicy.clear();
+        mUidPolicy.clear();
 
         FileInputStream fis = null;
         try {
@@ -1183,24 +1226,25 @@
                                 cycleTimezone, warningBytes, limitBytes, lastWarningSnooze,
                                 lastLimitSnooze, metered, inferred));
 
-                    } else if (TAG_UID_POLICY.equals(tag) && version < VERSION_SWITCH_APP_ID) {
+                    } else if (TAG_UID_POLICY.equals(tag)) {
                         final int uid = readIntAttribute(in, ATTR_UID);
                         final int policy = readIntAttribute(in, ATTR_POLICY);
 
-                        final int appId = UserId.getAppId(uid);
-                        if (UserId.isApp(appId)) {
-                            setAppPolicyUnchecked(appId, policy, false);
+                        if (UserHandle.isApp(uid)) {
+                            setUidPolicyUnchecked(uid, policy, false);
                         } else {
                             Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
                         }
-                    } else if (TAG_APP_POLICY.equals(tag) && version >= VERSION_SWITCH_APP_ID) {
+                    } else if (TAG_APP_POLICY.equals(tag)) {
                         final int appId = readIntAttribute(in, ATTR_APP_ID);
                         final int policy = readIntAttribute(in, ATTR_POLICY);
 
-                        if (UserId.isApp(appId)) {
-                            setAppPolicyUnchecked(appId, policy, false);
+                        // TODO: set for other users during upgrade
+                        final int uid = UserHandle.getUid(UserHandle.USER_OWNER, appId);
+                        if (UserHandle.isApp(uid)) {
+                            setUidPolicyUnchecked(uid, policy, false);
                         } else {
-                            Slog.w(TAG, "unable to apply policy to appId " + appId + "; ignoring");
+                            Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
                         }
                     }
                 }
@@ -1230,7 +1274,7 @@
         if (mRestrictBackground) {
             final Intent broadcast = new Intent(
                     ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
-            mContext.sendBroadcast(broadcast);
+            mContext.sendBroadcastAsUser(broadcast, UserHandle.ALL);
         }
     }
 
@@ -1275,17 +1319,17 @@
             }
 
             // write all known uid policies
-            for (int i = 0; i < mAppPolicy.size(); i++) {
-                final int appId = mAppPolicy.keyAt(i);
-                final int policy = mAppPolicy.valueAt(i);
+            for (int i = 0; i < mUidPolicy.size(); i++) {
+                final int uid = mUidPolicy.keyAt(i);
+                final int policy = mUidPolicy.valueAt(i);
 
                 // skip writing empty policies
                 if (policy == POLICY_NONE) continue;
 
-                out.startTag(null, TAG_APP_POLICY);
-                writeIntAttribute(out, ATTR_APP_ID, appId);
+                out.startTag(null, TAG_UID_POLICY);
+                writeIntAttribute(out, ATTR_UID, uid);
                 writeIntAttribute(out, ATTR_POLICY, policy);
-                out.endTag(null, TAG_APP_POLICY);
+                out.endTag(null, TAG_UID_POLICY);
             }
 
             out.endTag(null, TAG_POLICY_LIST);
@@ -1300,24 +1344,24 @@
     }
 
     @Override
-    public void setAppPolicy(int appId, int policy) {
+    public void setUidPolicy(int uid, int policy) {
         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
 
-        if (!UserId.isApp(appId)) {
-            throw new IllegalArgumentException("cannot apply policy to appId " + appId);
+        if (!UserHandle.isApp(uid)) {
+            throw new IllegalArgumentException("cannot apply policy to UID " + uid);
         }
 
-        setAppPolicyUnchecked(appId, policy, true);
+        setUidPolicyUnchecked(uid, policy, true);
     }
 
-    private void setAppPolicyUnchecked(int appId, int policy, boolean persist) {
+    private void setUidPolicyUnchecked(int uid, int policy, boolean persist) {
         final int oldPolicy;
         synchronized (mRulesLock) {
-            oldPolicy = getAppPolicy(appId);
-            mAppPolicy.put(appId, policy);
+            oldPolicy = getUidPolicy(uid);
+            mUidPolicy.put(uid, policy);
 
             // uid policy changed, recompute rules and persist policy.
-            updateRulesForAppLocked(appId);
+            updateRulesForUidLocked(uid);
             if (persist) {
                 writePolicyLocked();
             }
@@ -1325,29 +1369,53 @@
     }
 
     @Override
-    public int getAppPolicy(int appId) {
+    public int getUidPolicy(int uid) {
         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
 
         synchronized (mRulesLock) {
-            return mAppPolicy.get(appId, POLICY_NONE);
+            return mUidPolicy.get(uid, POLICY_NONE);
         }
     }
 
     @Override
-    public int[] getAppsWithPolicy(int policy) {
+    public int[] getUidsWithPolicy(int policy) {
         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
 
-        int[] appIds = new int[0];
+        int[] uids = new int[0];
         synchronized (mRulesLock) {
-            for (int i = 0; i < mAppPolicy.size(); i++) {
-                final int appId = mAppPolicy.keyAt(i);
-                final int appPolicy = mAppPolicy.valueAt(i);
-                if (appPolicy == policy) {
-                    appIds = appendInt(appIds, appId);
+            for (int i = 0; i < mUidPolicy.size(); i++) {
+                final int uid = mUidPolicy.keyAt(i);
+                final int uidPolicy = mUidPolicy.valueAt(i);
+                if (uidPolicy == policy) {
+                    uids = appendInt(uids, uid);
                 }
             }
         }
-        return appIds;
+        return uids;
+    }
+
+    /**
+     * Remove any policies associated with given {@link UserHandle}, persisting
+     * if any changes are made.
+     */
+    private void removePoliciesForUserLocked(int userId) {
+        if (LOGV) Slog.v(TAG, "removePoliciesForUserLocked()");
+
+        int[] uids = new int[0];
+        for (int i = 0; i < mUidPolicy.size(); i++) {
+            final int uid = mUidPolicy.keyAt(i);
+            if (UserHandle.getUserId(uid) == userId) {
+                uids = appendInt(uids, uid);
+            }
+        }
+
+        if (uids.length > 0) {
+            for (int uid : uids) {
+                mUidPolicy.delete(uid);
+                updateRulesForUidLocked(uid);
+            }
+            writePolicyLocked();
+        }
     }
 
     @Override
@@ -1581,14 +1649,14 @@
             }
             fout.decreaseIndent();
 
-            fout.println("Policy for apps:");
+            fout.println("Policy for UIDs:");
             fout.increaseIndent();
-            int size = mAppPolicy.size();
+            int size = mUidPolicy.size();
             for (int i = 0; i < size; i++) {
-                final int appId = mAppPolicy.keyAt(i);
-                final int policy = mAppPolicy.valueAt(i);
-                fout.print("appId=");
-                fout.print(appId);
+                final int uid = mUidPolicy.keyAt(i);
+                final int policy = mUidPolicy.valueAt(i);
+                fout.print("UID=");
+                fout.print(uid);
                 fout.print(" policy=");
                 dumpPolicy(fout, policy);
                 fout.println();
@@ -1693,12 +1761,19 @@
      * Update rules that might be changed by {@link #mRestrictBackground} value.
      */
     private void updateRulesForRestrictBackgroundLocked() {
-        // update rules for all installed applications
         final PackageManager pm = mContext.getPackageManager();
-        final List<ApplicationInfo> apps = pm.getInstalledApplications(0);
-        for (ApplicationInfo app : apps) {
-            final int appId = UserId.getAppId(app.uid);
-            updateRulesForAppLocked(appId);
+        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+
+        // update rules for all installed applications
+        final List<UserInfo> users = um.getUsers();
+        final List<ApplicationInfo> apps = pm.getInstalledApplications(
+                PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS);
+
+        for (UserInfo user : users) {
+            for (ApplicationInfo app : apps) {
+                final int uid = UserHandle.getUid(user.id, app.uid);
+                updateRulesForUidLocked(uid);
+            }
         }
 
         // limit data usage for some internal system services
@@ -1706,17 +1781,10 @@
         updateRulesForUidLocked(android.os.Process.DRM_UID);
     }
 
-    private void updateRulesForAppLocked(int appId) {
-        for (UserInfo user : mContext.getPackageManager().getUsers()) {
-            final int uid = UserId.getUid(user.id, appId);
-            updateRulesForUidLocked(uid);
-        }
-    }
-
     private static boolean isUidValidForRules(int uid) {
         // allow rules on specific system services, and any apps
         if (uid == android.os.Process.MEDIA_UID || uid == android.os.Process.DRM_UID
-                || UserId.isApp(uid)) {
+                || UserHandle.isApp(uid)) {
             return true;
         }
 
@@ -1726,13 +1794,12 @@
     private void updateRulesForUidLocked(int uid) {
         if (!isUidValidForRules(uid)) return;
 
-        final int appId = UserId.getAppId(uid);
-        final int appPolicy = getAppPolicy(appId);
+        final int uidPolicy = getUidPolicy(uid);
         final boolean uidForeground = isUidForeground(uid);
 
         // derive active rules based on policy and active state
         int uidRules = RULE_ALLOW_ALL;
-        if (!uidForeground && (appPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
+        if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
             // uid in background, and policy says to block metered data
             uidRules = RULE_REJECT_METERED;
         }
diff --git a/services/java/com/android/server/net/NetworkStatsCollection.java b/services/java/com/android/server/net/NetworkStatsCollection.java
index 9ddf011..3169035 100644
--- a/services/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/java/com/android/server/net/NetworkStatsCollection.java
@@ -29,8 +29,9 @@
 import android.net.NetworkTemplate;
 import android.net.TrafficStats;
 import android.text.format.DateUtils;
+import android.util.AtomicFile;
 
-import com.android.internal.os.AtomicFile;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FileRotator;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Objects;
@@ -431,13 +432,13 @@
      * moving any {@link NetworkStats#TAG_NONE} series to
      * {@link TrafficStats#UID_REMOVED}.
      */
-    public void removeUid(int uid) {
+    public void removeUids(int[] uids) {
         final ArrayList<Key> knownKeys = Lists.newArrayList();
         knownKeys.addAll(mStats.keySet());
 
         // migrate all UID stats into special "removed" bucket
         for (Key key : knownKeys) {
-            if (key.uid == uid) {
+            if (ArrayUtils.contains(uids, key.uid)) {
                 // only migrate combined TAG_NONE history
                 if (key.tag == TAG_NONE) {
                     final NetworkStatsHistory uidHistory = mStats.get(key);
diff --git a/services/java/com/android/server/net/NetworkStatsRecorder.java b/services/java/com/android/server/net/NetworkStatsRecorder.java
index c3ecf54..2b32b41 100644
--- a/services/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/java/com/android/server/net/NetworkStatsRecorder.java
@@ -42,6 +42,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.lang.ref.WeakReference;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Map;
 
@@ -233,23 +234,27 @@
      * Remove the given UID from all {@link FileRotator} history, migrating it
      * to {@link TrafficStats#UID_REMOVED}.
      */
-    public void removeUidLocked(int uid) {
+    public void removeUidsLocked(int[] uids) {
         try {
-            // process all existing data to migrate uid
-            mRotator.rewriteAll(new RemoveUidRewriter(mBucketDuration, uid));
+            // Rewrite all persisted data to migrate UID stats
+            mRotator.rewriteAll(new RemoveUidRewriter(mBucketDuration, uids));
         } catch (IOException e) {
-            Log.wtf(TAG, "problem removing UID " + uid, e);
+            Log.wtf(TAG, "problem removing UIDs " + Arrays.toString(uids), e);
             recoverFromWtf();
         }
 
-        // clear UID from current stats snapshot
+        // Remove any pending stats
+        mPending.removeUids(uids);
+        mSinceBoot.removeUids(uids);
+
+        // Clear UID from current stats snapshot
         if (mLastSnapshot != null) {
-            mLastSnapshot = mLastSnapshot.withoutUid(uid);
+            mLastSnapshot = mLastSnapshot.withoutUids(uids);
         }
 
         final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null;
         if (complete != null) {
-            complete.removeUid(uid);
+            complete.removeUids(uids);
         }
     }
 
@@ -293,11 +298,11 @@
      */
     public static class RemoveUidRewriter implements FileRotator.Rewriter {
         private final NetworkStatsCollection mTemp;
-        private final int mUid;
+        private final int[] mUids;
 
-        public RemoveUidRewriter(long bucketDuration, int uid) {
+        public RemoveUidRewriter(long bucketDuration, int[] uids) {
             mTemp = new NetworkStatsCollection(bucketDuration);
-            mUid = uid;
+            mUids = uids;
         }
 
         @Override
@@ -309,7 +314,7 @@
         public void read(InputStream in) throws IOException {
             mTemp.read(in);
             mTemp.clearDirty();
-            mTemp.removeUid(mUid);
+            mTemp.removeUids(mUids);
         }
 
         @Override
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index ba122ec..0efdead 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -23,6 +23,7 @@
 import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
 import static android.content.Intent.ACTION_SHUTDOWN;
 import static android.content.Intent.ACTION_UID_REMOVED;
+import static android.content.Intent.ACTION_USER_REMOVED;
 import static android.content.Intent.EXTRA_UID;
 import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
@@ -38,23 +39,23 @@
 import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
 import static android.net.TrafficStats.KB_IN_BYTES;
 import static android.net.TrafficStats.MB_IN_BYTES;
-import static android.provider.Settings.Secure.NETSTATS_DEV_BUCKET_DURATION;
-import static android.provider.Settings.Secure.NETSTATS_DEV_DELETE_AGE;
-import static android.provider.Settings.Secure.NETSTATS_DEV_PERSIST_BYTES;
-import static android.provider.Settings.Secure.NETSTATS_DEV_ROTATE_AGE;
-import static android.provider.Settings.Secure.NETSTATS_GLOBAL_ALERT_BYTES;
-import static android.provider.Settings.Secure.NETSTATS_POLL_INTERVAL;
-import static android.provider.Settings.Secure.NETSTATS_REPORT_XT_OVER_DEV;
-import static android.provider.Settings.Secure.NETSTATS_SAMPLE_ENABLED;
-import static android.provider.Settings.Secure.NETSTATS_TIME_CACHE_MAX_AGE;
-import static android.provider.Settings.Secure.NETSTATS_UID_BUCKET_DURATION;
-import static android.provider.Settings.Secure.NETSTATS_UID_DELETE_AGE;
-import static android.provider.Settings.Secure.NETSTATS_UID_PERSIST_BYTES;
-import static android.provider.Settings.Secure.NETSTATS_UID_ROTATE_AGE;
-import static android.provider.Settings.Secure.NETSTATS_UID_TAG_BUCKET_DURATION;
-import static android.provider.Settings.Secure.NETSTATS_UID_TAG_DELETE_AGE;
-import static android.provider.Settings.Secure.NETSTATS_UID_TAG_PERSIST_BYTES;
-import static android.provider.Settings.Secure.NETSTATS_UID_TAG_ROTATE_AGE;
+import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION;
+import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE;
+import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES;
+import static android.provider.Settings.Global.NETSTATS_DEV_ROTATE_AGE;
+import static android.provider.Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES;
+import static android.provider.Settings.Global.NETSTATS_POLL_INTERVAL;
+import static android.provider.Settings.Global.NETSTATS_REPORT_XT_OVER_DEV;
+import static android.provider.Settings.Global.NETSTATS_SAMPLE_ENABLED;
+import static android.provider.Settings.Global.NETSTATS_TIME_CACHE_MAX_AGE;
+import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION;
+import static android.provider.Settings.Global.NETSTATS_UID_DELETE_AGE;
+import static android.provider.Settings.Global.NETSTATS_UID_PERSIST_BYTES;
+import static android.provider.Settings.Global.NETSTATS_UID_ROTATE_AGE;
+import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION;
+import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE;
+import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES;
+import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE;
 import static android.telephony.PhoneStateListener.LISTEN_DATA_CONNECTION_STATE;
 import static android.telephony.PhoneStateListener.LISTEN_NONE;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
@@ -76,6 +77,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.net.IConnectivityManager;
 import android.net.INetworkManagementEventObserver;
 import android.net.INetworkStatsService;
@@ -99,8 +102,9 @@
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.provider.Settings;
-import android.provider.Settings.Secure;
+import android.provider.Settings.Global;
 import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
 import android.util.EventLog;
@@ -111,6 +115,7 @@
 import android.util.SparseIntArray;
 import android.util.TrustedTime;
 
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FileRotator;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.EventLogTags;
@@ -121,8 +126,10 @@
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 
 /**
  * Collect and persist detailed network statistics, and provide this data to
@@ -321,6 +328,10 @@
         final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
         mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
 
+        // listen for user changes to clean stats
+        final IntentFilter userFilter = new IntentFilter(ACTION_USER_REMOVED);
+        mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
+
         // persist stats during clean shutdown
         final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN);
         mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
@@ -685,7 +696,7 @@
     /**
      * Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to
      * reflect current {@link #mPersistThreshold} value. Always defers to
-     * {@link Secure} values when defined.
+     * {@link Global} values when defined.
      */
     private void updatePersistThresholds() {
         mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold));
@@ -738,11 +749,34 @@
         public void onReceive(Context context, Intent intent) {
             // on background handler thread, and UID_REMOVED is protected
             // broadcast.
-            final int uid = intent.getIntExtra(EXTRA_UID, 0);
+
+            final int uid = intent.getIntExtra(EXTRA_UID, -1);
+            if (uid == -1) return;
+
             synchronized (mStatsLock) {
                 mWakeLock.acquire();
                 try {
-                    removeUidLocked(uid);
+                    removeUidsLocked(uid);
+                } finally {
+                    mWakeLock.release();
+                }
+            }
+        }
+    };
+
+    private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // On background handler thread, and USER_REMOVED is protected
+            // broadcast.
+
+            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+            if (userId == -1) return;
+
+            synchronized (mStatsLock) {
+                mWakeLock.acquire();
+                try {
+                    removeUserLocked(userId);
                 } finally {
                     mWakeLock.release();
                 }
@@ -763,7 +797,7 @@
     /**
      * Observer that watches for {@link INetworkManagementService} alerts.
      */
-    private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() {
+    private INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() {
         @Override
         public void limitReached(String limitName, String iface) {
             // only someone like NMS should be calling us
@@ -989,7 +1023,8 @@
         // finally, dispatch updated event to any listeners
         final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
         updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-        mContext.sendBroadcast(updatedIntent, READ_NETWORK_USAGE_HISTORY);
+        mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL,
+                READ_NETWORK_USAGE_HISTORY);
     }
 
     /**
@@ -1032,15 +1067,37 @@
     /**
      * Clean up {@link #mUidRecorder} after UID is removed.
      */
-    private void removeUidLocked(int uid) {
-        // perform one last poll before removing
+    private void removeUidsLocked(int... uids) {
+        if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids));
+
+        // Perform one last poll before removing
         performPollLocked(FLAG_PERSIST_ALL);
 
-        mUidRecorder.removeUidLocked(uid);
-        mUidTagRecorder.removeUidLocked(uid);
+        mUidRecorder.removeUidsLocked(uids);
+        mUidTagRecorder.removeUidsLocked(uids);
 
-        // clear kernel stats associated with UID
-        resetKernelUidStats(uid);
+        // Clear kernel stats associated with UID
+        for (int uid : uids) {
+            resetKernelUidStats(uid);
+        }
+    }
+
+    /**
+     * Clean up {@link #mUidRecorder} after user is removed.
+     */
+    private void removeUserLocked(int userId) {
+        if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId);
+
+        // Build list of UIDs that we should clean up
+        int[] uids = new int[0];
+        final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
+                PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS);
+        for (ApplicationInfo app : apps) {
+            final int uid = UserHandle.getUid(userId, app.uid);
+            uids = ArrayUtils.appendInt(uids, uid);
+        }
+
+        removeUidsLocked(uids);
     }
 
     @Override
@@ -1206,7 +1263,7 @@
 
     /**
      * Default external settings that read from
-     * {@link android.provider.Settings.Secure}.
+     * {@link android.provider.Settings.Global}.
      */
     private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
         private final ContentResolver mResolver;
@@ -1216,39 +1273,39 @@
             // TODO: adjust these timings for production builds
         }
 
-        private long getSecureLong(String name, long def) {
-            return Settings.Secure.getLong(mResolver, name, def);
+        private long getGlobalLong(String name, long def) {
+            return Settings.Global.getLong(mResolver, name, def);
         }
-        private boolean getSecureBoolean(String name, boolean def) {
+        private boolean getGlobalBoolean(String name, boolean def) {
             final int defInt = def ? 1 : 0;
-            return Settings.Secure.getInt(mResolver, name, defInt) != 0;
+            return Settings.Global.getInt(mResolver, name, defInt) != 0;
         }
 
         @Override
         public long getPollInterval() {
-            return getSecureLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
+            return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
         }
         @Override
         public long getTimeCacheMaxAge() {
-            return getSecureLong(NETSTATS_TIME_CACHE_MAX_AGE, DAY_IN_MILLIS);
+            return getGlobalLong(NETSTATS_TIME_CACHE_MAX_AGE, DAY_IN_MILLIS);
         }
         @Override
         public long getGlobalAlertBytes(long def) {
-            return getSecureLong(NETSTATS_GLOBAL_ALERT_BYTES, def);
+            return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def);
         }
         @Override
         public boolean getSampleEnabled() {
-            return getSecureBoolean(NETSTATS_SAMPLE_ENABLED, true);
+            return getGlobalBoolean(NETSTATS_SAMPLE_ENABLED, true);
         }
         @Override
         public boolean getReportXtOverDev() {
-            return getSecureBoolean(NETSTATS_REPORT_XT_OVER_DEV, true);
+            return getGlobalBoolean(NETSTATS_REPORT_XT_OVER_DEV, true);
         }
         @Override
         public Config getDevConfig() {
-            return new Config(getSecureLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS),
-                    getSecureLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS),
-                    getSecureLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS));
+            return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS),
+                    getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS),
+                    getGlobalLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS));
         }
         @Override
         public Config getXtConfig() {
@@ -1256,19 +1313,19 @@
         }
         @Override
         public Config getUidConfig() {
-            return new Config(getSecureLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
-                    getSecureLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS),
-                    getSecureLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS));
+            return new Config(getGlobalLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
+                    getGlobalLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS),
+                    getGlobalLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS));
         }
         @Override
         public Config getUidTagConfig() {
-            return new Config(getSecureLong(NETSTATS_UID_TAG_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
-                    getSecureLong(NETSTATS_UID_TAG_ROTATE_AGE, 5 * DAY_IN_MILLIS),
-                    getSecureLong(NETSTATS_UID_TAG_DELETE_AGE, 15 * DAY_IN_MILLIS));
+            return new Config(getGlobalLong(NETSTATS_UID_TAG_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
+                    getGlobalLong(NETSTATS_UID_TAG_ROTATE_AGE, 5 * DAY_IN_MILLIS),
+                    getGlobalLong(NETSTATS_UID_TAG_DELETE_AGE, 15 * DAY_IN_MILLIS));
         }
         @Override
         public long getDevPersistBytes(long def) {
-            return getSecureLong(NETSTATS_DEV_PERSIST_BYTES, def);
+            return getGlobalLong(NETSTATS_DEV_PERSIST_BYTES, def);
         }
         @Override
         public long getXtPersistBytes(long def) {
@@ -1276,11 +1333,11 @@
         }
         @Override
         public long getUidPersistBytes(long def) {
-            return getSecureLong(NETSTATS_UID_PERSIST_BYTES, def);
+            return getGlobalLong(NETSTATS_UID_PERSIST_BYTES, def);
         }
         @Override
         public long getUidTagPersistBytes(long def) {
-            return getSecureLong(NETSTATS_UID_TAG_PERSIST_BYTES, def);
+            return getGlobalLong(NETSTATS_UID_TAG_PERSIST_BYTES, def);
         }
     }
 }
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index 48004bb..71a6a018 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -25,7 +25,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 
-class Installer {
+public final class Installer {
     private static final String TAG = "Installer";
 
     private static final boolean LOCAL_DEBUG = false;
@@ -254,10 +254,12 @@
         return execute(builder.toString());
     }
 
-    public int deleteCacheFiles(String name) {
+    public int deleteCacheFiles(String name, int userId) {
         StringBuilder builder = new StringBuilder("rmcache");
         builder.append(' ');
         builder.append(name);
+        builder.append(' ');
+        builder.append(userId);
         return execute(builder.toString());
     }
 
@@ -324,26 +326,14 @@
         return execute(builder.toString());
     }
 
-    /*
-     * @param packagePathSuffix The name of the path relative to install
-     * directory. Say if the path name is /data/app/com.test-1.apk, the package
-     * suffix path will be com.test-1
-     */
-    public int setForwardLockPerm(String packagePathSuffix, int gid) {
-        StringBuilder builder = new StringBuilder("protect");
-        builder.append(' ');
-        builder.append(packagePathSuffix);
-        builder.append(' ');
-        builder.append(gid);
-        return execute(builder.toString());
-    }
-
-    public int getSizeInfo(String pkgName, String apkPath, String fwdLockApkPath,
+    public int getSizeInfo(String pkgName, int persona, String apkPath, String fwdLockApkPath,
             String asecPath, PackageStats pStats) {
         StringBuilder builder = new StringBuilder("getsize");
         builder.append(' ');
         builder.append(pkgName);
         builder.append(' ');
+        builder.append(persona);
+        builder.append(' ');
         builder.append(apkPath);
         builder.append(' ');
         builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
@@ -371,12 +361,20 @@
         return execute("movefiles");
     }
 
-    public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) {
+    /**
+     * Links the native library directory in an application's directory to its
+     * real location.
+     *
+     * @param dataPath data directory where the application is
+     * @param nativeLibPath target native library path
+     * @return -1 on error
+     */
+    public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath, int userId) {
         if (dataPath == null) {
-            Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null");
+            Slog.e(TAG, "linkNativeLibraryDirectory dataPath is null");
             return -1;
         } else if (nativeLibPath == null) {
-            Slog.e(TAG, "unlinkNativeLibraryDirectory nativeLibPath is null");
+            Slog.e(TAG, "linkNativeLibraryDirectory nativeLibPath is null");
             return -1;
         }
 
@@ -384,18 +382,8 @@
         builder.append(dataPath);
         builder.append(' ');
         builder.append(nativeLibPath);
-
-        return execute(builder.toString());
-    }
-
-    public int unlinkNativeLibraryDirectory(String dataPath) {
-        if (dataPath == null) {
-            Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null");
-            return -1;
-        }
-
-        StringBuilder builder = new StringBuilder("unlinklib ");
-        builder.append(dataPath);
+        builder.append(' ');
+        builder.append(userId);
 
         return execute(builder.toString());
     }
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index f914271..83672c5 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -25,6 +25,11 @@
 import static com.android.internal.util.ArrayUtils.appendInt;
 import static com.android.internal.util.ArrayUtils.removeInt;
 import static libcore.io.OsConstants.S_ISLNK;
+import static libcore.io.OsConstants.S_IRWXU;
+import static libcore.io.OsConstants.S_IRGRP;
+import static libcore.io.OsConstants.S_IXGRP;
+import static libcore.io.OsConstants.S_IROTH;
+import static libcore.io.OsConstants.S_IXOTH;
 
 import com.android.internal.app.IMediaContainerService;
 import com.android.internal.app.ResolverActivity;
@@ -40,6 +45,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
 import android.app.admin.IDevicePolicyManager;
@@ -64,10 +70,13 @@
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstrumentationInfo;
+import android.content.pm.PackageCleanItem;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInfoLite;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
+import android.content.pm.PackageUserState;
+import android.content.pm.PackageParser.ActivityIntentInfo;
 import android.content.pm.PackageStats;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionGroupInfo;
@@ -76,8 +85,8 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.Signature;
-import android.content.pm.UserInfo;
 import android.content.pm.ManifestDigest;
+import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.pm.VerifierInfo;
 import android.net.Uri;
@@ -100,7 +109,8 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.os.UserId;
+import android.os.UserHandle;
+import android.os.Environment.UserEnvironment;
 import android.provider.Settings.Secure;
 import android.security.SystemKeyStore;
 import android.util.DisplayMetrics;
@@ -144,6 +154,7 @@
 import libcore.io.ErrnoException;
 import libcore.io.IoUtils;
 import libcore.io.Libcore;
+import libcore.io.OsConstants;
 import libcore.io.StructStat;
 
 /**
@@ -165,6 +176,7 @@
     static final boolean DEBUG_UPGRADE = false;
     private static final boolean DEBUG_INSTALL = false;
     private static final boolean DEBUG_REMOVE = false;
+    private static final boolean DEBUG_BROADCASTS = false;
     private static final boolean DEBUG_SHOW_INFO = false;
     private static final boolean DEBUG_PACKAGE_INFO = false;
     private static final boolean DEBUG_INTENT_MATCHING = false;
@@ -175,6 +187,7 @@
     private static final int RADIO_UID = Process.PHONE_UID;
     private static final int LOG_UID = Process.LOG_UID;
     private static final int NFC_UID = Process.NFC_UID;
+    private static final int BLUETOOTH_UID = Process.BLUETOOTH_UID;
 
     private static final boolean GET_CERTIFICATES = true;
 
@@ -203,14 +216,21 @@
     /**
      * Whether verification is enabled by default.
      */
-    // STOPSHIP: change this to true
-    private static final boolean DEFAULT_VERIFY_ENABLE = false;
+    private static final boolean DEFAULT_VERIFY_ENABLE = true;
 
     /**
      * The default maximum time to wait for the verification agent to return in
      * milliseconds.
      */
-    private static final long DEFAULT_VERIFICATION_TIMEOUT = 60 * 1000;
+    private static final long DEFAULT_VERIFICATION_TIMEOUT = 10 * 1000;
+
+    /**
+     * The default response for package verification timeout.
+     *
+     * This can be either PackageManager.VERIFICATION_ALLOW or
+     * PackageManager.VERIFICATION_REJECT.
+     */
+    private static final int DEFAULT_VERIFICATION_RESPONSE = PackageManager.VERIFICATION_ALLOW;
 
     static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
 
@@ -264,7 +284,7 @@
     // This is the object monitoring mDrmAppPrivateInstallDir.
     final FileObserver mDrmAppInstallObserver;
 
-    // Used for priviledge escalation.  MUST NOT BE CALLED WITH mPackages
+    // Used for privilege escalation. MUST NOT BE CALLED WITH mPackages
     // LOCK HELD.  Can be called with mInstallLock held.
     final Installer mInstaller;
 
@@ -274,6 +294,12 @@
     final File mAppInstallDir;
     final File mDalvikCacheDir;
 
+    /**
+     * Directory to which applications installed internally have native
+     * libraries copied.
+     */
+    private File mAppLibInstallDir;
+
     // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
     // apps.
     final File mDrmAppPrivateInstallDir;
@@ -410,7 +436,7 @@
     // Delay time in millisecs
     static final int BROADCAST_DELAY = 10 * 1000;
 
-    static UserManager sUserManager;
+    static UserManagerService sUserManager;
 
     // Stores a list of users whose package restrictions file needs to be updated
     private HashSet<Integer> mDirtyUsers = new HashSet<Integer>();
@@ -457,7 +483,7 @@
             Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
             Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
             if (mContext.bindService(service, mDefContainerConn,
-                    Context.BIND_AUTO_CREATE)) {
+                    Context.BIND_AUTO_CREATE, UserHandle.USER_OWNER)) {
                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                 mBound = true;
                 return true;
@@ -650,11 +676,20 @@
                     break;
                 }
                 case START_CLEANING_PACKAGE: {
-                    String packageName = (String)msg.obj;
                     Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
+                    final String packageName = (String)msg.obj;
+                    final int userId = msg.arg1;
+                    final boolean andCode = msg.arg2 != 0;
                     synchronized (mPackages) {
-                        if (!mSettings.mPackagesToBeCleaned.contains(packageName)) {
-                            mSettings.mPackagesToBeCleaned.add(packageName);
+                        if (userId == UserHandle.USER_ALL) {
+                            int[] users = sUserManager.getUserIds();
+                            for (int user : users) {
+                                mSettings.addPackageToCleanLPw(
+                                        new PackageCleanItem(user, packageName, andCode));
+                            }
+                        } else {
+                            mSettings.addPackageToCleanLPw(
+                                    new PackageCleanItem(userId, packageName, andCode));
                         }
                     }
                     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
@@ -671,29 +706,68 @@
                         PackageInstalledInfo res = data.res;
 
                         if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
-                            res.removedInfo.sendBroadcast(false, true);
+                            res.removedInfo.sendBroadcast(false, true, false);
                             Bundle extras = new Bundle(1);
                             extras.putInt(Intent.EXTRA_UID, res.uid);
+                            // Determine the set of users who are adding this
+                            // package for the first time vs. those who are seeing
+                            // an update.
+                            int[] firstUsers;
+                            int[] updateUsers = new int[0];
+                            if (res.origUsers == null || res.origUsers.length == 0) {
+                                firstUsers = res.newUsers;
+                            } else {
+                                firstUsers = new int[0];
+                                for (int i=0; i<res.newUsers.length; i++) {
+                                    int user = res.newUsers[i];
+                                    boolean isNew = true;
+                                    for (int j=0; j<res.origUsers.length; j++) {
+                                        if (res.origUsers[j] == user) {
+                                            isNew = false;
+                                            break;
+                                        }
+                                    }
+                                    if (isNew) {
+                                        int[] newFirst = new int[firstUsers.length+1];
+                                        System.arraycopy(firstUsers, 0, newFirst, 0,
+                                                firstUsers.length);
+                                        newFirst[firstUsers.length] = user;
+                                        firstUsers = newFirst;
+                                    } else {
+                                        int[] newUpdate = new int[updateUsers.length+1];
+                                        System.arraycopy(updateUsers, 0, newUpdate, 0,
+                                                updateUsers.length);
+                                        newUpdate[updateUsers.length] = user;
+                                        updateUsers = newUpdate;
+                                    }
+                                }
+                            }
+                            sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
+                                    res.pkg.applicationInfo.packageName,
+                                    extras, null, null, firstUsers);
                             final boolean update = res.removedInfo.removedPackage != null;
                             if (update) {
                                 extras.putBoolean(Intent.EXTRA_REPLACING, true);
                             }
                             sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
                                     res.pkg.applicationInfo.packageName,
-                                    extras, null, null, UserId.USER_ALL);
+                                    extras, null, null, updateUsers);
                             if (update) {
                                 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
                                         res.pkg.applicationInfo.packageName,
-                                        extras, null, null, UserId.USER_ALL);
+                                        extras, null, null, updateUsers);
                                 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
                                         null, null,
-                                        res.pkg.applicationInfo.packageName, null,
-                                        UserId.USER_ALL);
+                                        res.pkg.applicationInfo.packageName, null, updateUsers);
                             }
                             if (res.removedInfo.args != null) {
                                 // Remove the replaced package's older resources safely now
                                 deleteOld = true;
                             }
+
+                            // Log current value of "unknown sources" setting
+                            EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED,
+                                getUnknownSourcesSettings());
                         }
                         // Force a gc to clear up things
                         Runtime.getRuntime().gc();
@@ -764,17 +838,35 @@
                     final int verificationId = msg.arg1;
                     final PackageVerificationState state = mPendingVerification.get(verificationId);
 
-                    if (state != null) {
+                    if ((state != null) && !state.timeoutExtended()) {
                         final InstallArgs args = state.getInstallArgs();
                         Slog.i(TAG, "Verification timed out for " + args.packageURI.toString());
                         mPendingVerification.remove(verificationId);
 
-                        int ret = PackageManager.INSTALL_FAILED_VERIFICATION_TIMEOUT;
-                        processPendingInstall(args, ret);
+                        int ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
 
+                        if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) {
+                            Slog.i(TAG, "Continuing with installation of "
+                                    + args.packageURI.toString());
+                            state.setVerifierResponse(Binder.getCallingUid(),
+                                    PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
+                            broadcastPackageVerified(verificationId, args.packageURI,
+                                    PackageManager.VERIFICATION_ALLOW,
+                                    state.getInstallArgs().getUser());
+                            try {
+                                ret = args.copyApk(mContainerService, true);
+                            } catch (RemoteException e) {
+                                Slog.e(TAG, "Could not contact the ContainerService");
+                            }
+                        } else {
+                            broadcastPackageVerified(verificationId, args.packageURI,
+                                    PackageManager.VERIFICATION_REJECT,
+                                    state.getInstallArgs().getUser());
+                        }
+
+                        processPendingInstall(args, ret);
                         mHandler.sendEmptyMessage(MCS_UNBIND);
                     }
-
                     break;
                 }
                 case PACKAGE_VERIFIED: {
@@ -798,6 +890,8 @@
                         int ret;
                         if (state.isInstallAllowed()) {
                             ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+                            broadcastPackageVerified(verificationId, args.packageURI,
+                                    response.code, state.getInstallArgs().getUser());
                             try {
                                 ret = args.copyApk(mContainerService, true);
                             } catch (RemoteException e) {
@@ -832,9 +926,10 @@
         }
     }
 
-    public static final IPackageManager main(Context context, boolean factoryTest,
-            boolean onlyCore) {
-        PackageManagerService m = new PackageManagerService(context, factoryTest, onlyCore);
+    public static final IPackageManager main(Context context, Installer installer,
+            boolean factoryTest, boolean onlyCore) {
+        PackageManagerService m = new PackageManagerService(context, installer,
+                factoryTest, onlyCore);
         ServiceManager.addService("package", m);
         return m;
     }
@@ -861,7 +956,8 @@
         return res;
     }
 
-    public PackageManagerService(Context context, boolean factoryTest, boolean onlyCore) {
+    public PackageManagerService(Context context, Installer installer,
+            boolean factoryTest, boolean onlyCore) {
         EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                 SystemClock.uptimeMillis());
 
@@ -874,12 +970,13 @@
         mOnlyCore = onlyCore;
         mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
         mMetrics = new DisplayMetrics();
-        mSettings = new Settings();
+        mSettings = new Settings(context);
         mSettings.addSharedUserLPw("android.uid.system",
                 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
         mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM);
         mSettings.addSharedUserLPw("android.uid.log", LOG_UID, ApplicationInfo.FLAG_SYSTEM);
         mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID, ApplicationInfo.FLAG_SYSTEM);
+        mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID, ApplicationInfo.FLAG_SYSTEM);
 
         String separateProcesses = SystemProperties.get("debug.separate_processes");
         if (separateProcesses != null && separateProcesses.length() > 0) {
@@ -898,7 +995,7 @@
             mSeparateProcesses = null;
         }
 
-        mInstaller = new Installer();
+        mInstaller = installer;
 
         WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
         Display d = wm.getDefaultDisplay();
@@ -912,15 +1009,18 @@
 
             File dataDir = Environment.getDataDirectory();
             mAppDataDir = new File(dataDir, "data");
+            mAppInstallDir = new File(dataDir, "app");
+            mAppLibInstallDir = new File(dataDir, "app-lib");
             mAsecInternalPath = new File(dataDir, "app-asec").getPath();
             mUserAppDataDir = new File(dataDir, "user");
             mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
 
-            sUserManager = new UserManager(mInstaller, mUserAppDataDir);
+            sUserManager = new UserManagerService(context, this,
+                    mInstallLock, mPackages);
 
             readPermissions();
 
-            mRestoredSettings = mSettings.readLPw(getUsers());
+            mRestoredSettings = mSettings.readLPw(sUserManager.getUsers(false));
             long startTime = SystemClock.uptimeMillis();
 
             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
@@ -1099,7 +1199,7 @@
                         if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
                             Slog.i(TAG, "Expecting better updatd system app for " + ps.name
                                     + "; removing system app");
-                            removePackageLI(scannedPkg, true);
+                            removePackageLI(ps, true);
                         }
 
                         continue;
@@ -1110,8 +1210,7 @@
                         String msg = "System package " + ps.name
                                 + " no longer exists; wiping its data";
                         reportSettingsProblem(Log.WARN, msg);
-                        mInstaller.remove(ps.name, 0);
-                        sUserManager.removePackageForAllUsers(ps.name);
+                        removeDataDirsLI(ps.name);
                     } else {
                         final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
                         if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
@@ -1121,7 +1220,6 @@
                 }
             }
 
-            mAppInstallDir = new File(dataDir, "app");
             //look for any incomplete package installations
             ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
             //clean up list
@@ -1160,9 +1258,7 @@
                     if (deletedPkg == null) {
                         msg = "Updated system package " + deletedAppName
                                 + " no longer exists; wiping its data";
-
-                        mInstaller.remove(deletedAppName, 0);
-                        sUserManager.removePackageForAllUsers(deletedAppName);
+                        removeDataDirsLI(deletedAppName);
                     } else {
                         msg = "Updated system app + " + deletedAppName
                                 + " no longer present; removing system privileges for "
@@ -1204,27 +1300,6 @@
                             ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
                             : 0));
 
-            // Verify that all of the preferred activity components actually
-            // exist.  It is possible for applications to be updated and at
-            // that point remove a previously declared activity component that
-            // had been set as a preferred activity.  We try to clean this up
-            // the next time we encounter that preferred activity, but it is
-            // possible for the user flow to never be able to return to that
-            // situation so here we do a sanity check to make sure we haven't
-            // left any junk around.
-            ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
-            for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
-                if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
-                    removed.add(pa);
-                }
-            }
-            for (int i=0; i<removed.size(); i++) {
-                PreferredActivity pa = removed.get(i);
-                Slog.w(TAG, "Removing dangling preferred activity: "
-                        + pa.mPref.mComponent);
-                mSettings.mPreferredActivities.removeFilter(pa);
-            }
-
             // can downgrade to reader
             mSettings.writeLPr();
 
@@ -1297,13 +1372,7 @@
 
     void cleanupInstallFailedPackage(PackageSetting ps) {
         Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
-        int retCode = mInstaller.remove(ps.name, 0);
-        if (retCode < 0) {
-            Slog.w(TAG, "Couldn't remove app data directory for package: "
-                       + ps.name + ", retcode=" + retCode);
-        } else {
-            sUserManager.removePackageForAllUsers(ps.name);
-        }
+        removeDataDirsLI(ps.name);
         if (ps.codePath != null) {
             if (!ps.codePath.delete()) {
                 Slog.w(TAG, "Unable to remove old code file: " + ps.codePath);
@@ -1533,19 +1602,17 @@
     PackageInfo generatePackageInfo(PackageParser.Package p, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         PackageInfo pi;
-        if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
-            // The package has been uninstalled but has retained data and resources.
-            pi = PackageParser.generatePackageInfo(p, null, flags, 0, 0, null, false, 0, userId);
-        } else {
-            final PackageSetting ps = (PackageSetting) p.mExtras;
-            if (ps == null) {
-                return null;
-            }
-            final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
-            pi = PackageParser.generatePackageInfo(p, gp.gids, flags,
-                    ps.firstInstallTime, ps.lastUpdateTime, gp.grantedPermissions,
-                    ps.getStopped(userId), ps.getEnabled(userId), userId);
-            pi.applicationInfo.enabledSetting = ps.getEnabled(userId);
+        final PackageSetting ps = (PackageSetting) p.mExtras;
+        if (ps == null) {
+            return null;
+        }
+        final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
+        final PackageUserState state = ps.readUserState(userId);
+        pi = PackageParser.generatePackageInfo(p, gp.gids, flags,
+                ps.firstInstallTime, ps.lastUpdateTime, gp.grantedPermissions,
+                state, userId);
+        if (pi != null) {
+            pi.applicationInfo.enabledSetting = state.enabled;
             pi.applicationInfo.enabled =
                     pi.applicationInfo.enabledSetting == COMPONENT_ENABLED_STATE_DEFAULT
                     || pi.applicationInfo.enabledSetting == COMPONENT_ENABLED_STATE_ENABLED;
@@ -1556,6 +1623,7 @@
     @Override
     public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get package info");
         // reader
         synchronized (mPackages) {
             PackageParser.Package p = mPackages.get(packageName);
@@ -1598,22 +1666,24 @@
     @Override
     public int getPackageUid(String packageName, int userId) {
         if (!sUserManager.exists(userId)) return -1;
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get package uid");
         // reader
         synchronized (mPackages) {
             PackageParser.Package p = mPackages.get(packageName);
             if(p != null) {
-                return UserId.getUid(userId, p.applicationInfo.uid);
+                return UserHandle.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 ? UserId.getUid(userId, p.applicationInfo.uid) : -1;
+            return p != null ? UserHandle.getUid(userId, p.applicationInfo.uid) : -1;
         }
     }
 
     public int[] getPackageGids(String packageName) {
+        final boolean enforcedDefault = isPermissionEnforcedDefault(READ_EXTERNAL_STORAGE);
         // reader
         synchronized (mPackages) {
             PackageParser.Package p = mPackages.get(packageName);
@@ -1625,7 +1695,7 @@
                 int[] gids = suid != null ? suid.gids : ps.gids;
 
                 // include GIDs for any unenforced permissions
-                if (!isPermissionEnforcedLocked(READ_EXTERNAL_STORAGE)) {
+                if (!isPermissionEnforcedLocked(READ_EXTERNAL_STORAGE, enforcedDefault)) {
                     final BasePermission basePerm = mSettings.mPermissions.get(
                             READ_EXTERNAL_STORAGE);
                     gids = appendInts(gids, basePerm.gids);
@@ -1712,14 +1782,15 @@
         PackageSetting ps = mSettings.mPackages.get(packageName);
         if (ps != null) {
             if (ps.pkg == null) {
-                PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName, flags, userId);
+                PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName,
+                        flags, userId);
                 if (pInfo != null) {
                     return pInfo.applicationInfo;
                 }
                 return null;
             }
-            return PackageParser.generateApplicationInfo(ps.pkg, flags, ps.getStopped(userId),
-                    ps.getEnabled(userId), userId);
+            return PackageParser.generateApplicationInfo(ps.pkg, flags,
+                    ps.readUserState(userId), userId);
         }
         return null;
     }
@@ -1729,20 +1800,23 @@
         if (!sUserManager.exists(userId)) return null;
         PackageSetting ps = mSettings.mPackages.get(packageName);
         if (ps != null) {
-            PackageParser.Package pkg = new PackageParser.Package(packageName);
-            if (ps.pkg == null) {
-                ps.pkg = new PackageParser.Package(packageName);
-                ps.pkg.applicationInfo.packageName = packageName;
-                ps.pkg.applicationInfo.flags = ps.pkgFlags;
-                ps.pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
-                ps.pkg.applicationInfo.sourceDir = ps.codePathString;
-                ps.pkg.applicationInfo.dataDir =
-                        getDataPathForPackage(ps.pkg.packageName, 0).getPath();
-                ps.pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
+            PackageParser.Package pkg = ps.pkg;
+            if (pkg == null) {
+                if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) == 0) {
+                    return null;
+                }
+                pkg = new PackageParser.Package(packageName);
+                pkg.applicationInfo.packageName = packageName;
+                pkg.applicationInfo.flags = ps.pkgFlags | ApplicationInfo.FLAG_IS_DATA_ONLY;
+                pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
+                pkg.applicationInfo.sourceDir = ps.codePathString;
+                pkg.applicationInfo.dataDir =
+                        getDataPathForPackage(packageName, 0).getPath();
+                pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
             }
-            // ps.pkg.mSetEnabled = ps.getEnabled(userId);
-            // ps.pkg.mSetStopped = ps.getStopped(userId);
-            return generatePackageInfo(ps.pkg, flags, userId);
+            // pkg.mSetEnabled = ps.getEnabled(userId);
+            // pkg.mSetStopped = ps.getStopped(userId);
+            return generatePackageInfo(pkg, flags, userId);
         }
         return null;
     }
@@ -1750,6 +1824,7 @@
     @Override
     public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get application info");
         // writer
         synchronized (mPackages) {
             PackageParser.Package p = mPackages.get(packageName);
@@ -1760,13 +1835,13 @@
                 PackageSetting ps = mSettings.mPackages.get(packageName);
                 if (ps == null) return null;
                 // Note: isEnabledLP() does not apply here - always return info
-                return PackageParser.generateApplicationInfo(p, flags, ps.getStopped(userId),
-                        ps.getEnabled(userId));
+                return PackageParser.generateApplicationInfo(
+                        p, flags, ps.readUserState(userId), userId);
             }
             if ("android".equals(packageName)||"system".equals(packageName)) {
                 return mAndroidApplication;
             }
-            if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
+            if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
                 return generateApplicationInfoFromSettingsLPw(packageName, flags, userId);
             }
         }
@@ -1782,9 +1857,11 @@
             public void run() {
                 mHandler.removeCallbacks(this);
                 int retCode = -1;
-                retCode = mInstaller.freeCache(freeStorageSize);
-                if (retCode < 0) {
-                    Slog.w(TAG, "Couldn't clear application caches");
+                synchronized (mInstallLock) {
+                    retCode = mInstaller.freeCache(freeStorageSize);
+                    if (retCode < 0) {
+                        Slog.w(TAG, "Couldn't clear application caches");
+                    }
                 }
                 if (observer != null) {
                     try {
@@ -1805,9 +1882,11 @@
             public void run() {
                 mHandler.removeCallbacks(this);
                 int retCode = -1;
-                retCode = mInstaller.freeCache(freeStorageSize);
-                if (retCode < 0) {
-                    Slog.w(TAG, "Couldn't clear application caches");
+                synchronized (mInstallLock) {
+                    retCode = mInstaller.freeCache(freeStorageSize);
+                    if (retCode < 0) {
+                        Slog.w(TAG, "Couldn't clear application caches");
+                    }
                 }
                 if(pi != null) {
                     try {
@@ -1826,6 +1905,7 @@
     @Override
     public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get activity info");
         synchronized (mPackages) {
             PackageParser.Activity a = mActivities.mActivities.get(component);
 
@@ -1833,8 +1913,8 @@
             if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
-                return PackageParser.generateActivityInfo(a, flags, ps.getStopped(userId),
-                        ps.getEnabled(userId), userId);
+                return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
+                        userId);
             }
             if (mResolveComponentName.equals(component)) {
                 return mResolveActivity;
@@ -1846,6 +1926,7 @@
     @Override
     public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get receiver info");
         synchronized (mPackages) {
             PackageParser.Activity a = mReceivers.mActivities.get(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
@@ -1853,8 +1934,8 @@
             if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
-                return PackageParser.generateActivityInfo(a, flags, ps.getStopped(userId),
-                        ps.getEnabled(userId), userId);
+                return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
+                        userId);
             }
         }
         return null;
@@ -1863,6 +1944,7 @@
     @Override
     public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get service info");
         synchronized (mPackages) {
             PackageParser.Service s = mServices.mServices.get(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
@@ -1870,8 +1952,8 @@
             if (s != null && mSettings.isEnabledLPr(s.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
-                return PackageParser.generateServiceInfo(s, flags, ps.getStopped(userId),
-                        ps.getEnabled(userId), userId);
+                return PackageParser.generateServiceInfo(s, flags, ps.readUserState(userId),
+                        userId);
             }
         }
         return null;
@@ -1880,6 +1962,7 @@
     @Override
     public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get provider info");
         synchronized (mPackages) {
             PackageParser.Provider p = mProvidersByComponent.get(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
@@ -1887,8 +1970,8 @@
             if (p != null && mSettings.isEnabledLPr(p.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
-                return PackageParser.generateProviderInfo(p, flags, ps.getStopped(userId),
-                        ps.getEnabled(userId), userId);
+                return PackageParser.generateProviderInfo(p, flags, ps.readUserState(userId),
+                        userId);
             }
         }
         return null;
@@ -1933,7 +2016,7 @@
     }
 
     private void checkValidCaller(int uid, int userId) {
-        if (UserId.getUserId(uid) == userId || uid == Process.SYSTEM_UID || uid == 0)
+        if (UserHandle.getUserId(uid) == userId || uid == Process.SYSTEM_UID || uid == 0)
             return;
 
         throw new SecurityException("Caller uid=" + uid
@@ -1941,6 +2024,7 @@
     }
 
     public int checkPermission(String permName, String pkgName) {
+        final boolean enforcedDefault = isPermissionEnforcedDefault(permName);
         synchronized (mPackages) {
             PackageParser.Package p = mPackages.get(pkgName);
             if (p != null && p.mExtras != null) {
@@ -1953,7 +2037,7 @@
                     return PackageManager.PERMISSION_GRANTED;
                 }
             }
-            if (!isPermissionEnforcedLocked(permName)) {
+            if (!isPermissionEnforcedLocked(permName, enforcedDefault)) {
                 return PackageManager.PERMISSION_GRANTED;
             }
         }
@@ -1961,8 +2045,9 @@
     }
 
     public int checkUidPermission(String permName, int uid) {
+        final boolean enforcedDefault = isPermissionEnforcedDefault(permName);
         synchronized (mPackages) {
-            Object obj = mSettings.getUserIdLPr(UserId.getAppId(uid));
+            Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
             if (obj != null) {
                 GrantedPermissions gp = (GrantedPermissions)obj;
                 if (gp.grantedPermissions.contains(permName)) {
@@ -1974,13 +2059,41 @@
                     return PackageManager.PERMISSION_GRANTED;
                 }
             }
-            if (!isPermissionEnforcedLocked(permName)) {
+            if (!isPermissionEnforcedLocked(permName, enforcedDefault)) {
                 return PackageManager.PERMISSION_GRANTED;
             }
         }
         return PackageManager.PERMISSION_DENIED;
     }
 
+    /**
+     * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS
+     * or INTERACT_ACROSS_USERS_FULL permissions, if the userid is not for the caller.
+     * @param message the message to log on security exception
+     * @return
+     */
+    private void enforceCrossUserPermission(int callingUid, int userId,
+            boolean requireFullPermission, String message) {
+        if (userId < 0) {
+            throw new IllegalArgumentException("Invalid userId " + userId);
+        }
+        if (userId == UserHandle.getUserId(callingUid)) return;
+        if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
+            if (requireFullPermission) {
+                mContext.enforceCallingOrSelfPermission(
+                        android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
+            } else {
+                try {
+                    mContext.enforceCallingOrSelfPermission(
+                            android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
+                } catch (SecurityException se) {
+                    mContext.enforceCallingOrSelfPermission(
+                            android.Manifest.permission.INTERACT_ACROSS_USERS, message);
+                }
+            }
+        }
+    }
+
     private BasePermission findPermissionTreeLP(String permName) {
         for(BasePermission bp : mSettings.mPermissionTrees.values()) {
             if (permName.startsWith(bp.name) &&
@@ -1996,7 +2109,7 @@
         if (permName != null) {
             BasePermission bp = findPermissionTreeLP(permName);
             if (bp != null) {
-                if (bp.uid == UserId.getAppId(Binder.getCallingUid())) {
+                if (bp.uid == UserHandle.getAppId(Binder.getCallingUid())) {
                     return bp;
                 }
                 throw new SecurityException("Calling uid "
@@ -2199,8 +2312,8 @@
 
     public int checkUidSignatures(int uid1, int uid2) {
         // Map to base uids.
-        uid1 = UserId.getAppId(uid1);
-        uid2 = UserId.getAppId(uid2);
+        uid1 = UserHandle.getAppId(uid1);
+        uid2 = UserHandle.getAppId(uid2);
         // reader
         synchronized (mPackages) {
             Signature[] s1;
@@ -2258,7 +2371,7 @@
     }
 
     public String[] getPackagesForUid(int uid) {
-        uid = UserId.getAppId(uid);
+        uid = UserHandle.getAppId(uid);
         // reader
         synchronized (mPackages) {
             Object obj = mSettings.getUserIdLPr(uid);
@@ -2283,7 +2396,7 @@
     public String getNameForUid(int uid) {
         // reader
         synchronized (mPackages) {
-            Object obj = mSettings.getUserIdLPr(UserId.getAppId(uid));
+            Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
             if (obj instanceof SharedUserSetting) {
                 final SharedUserSetting sus = (SharedUserSetting) obj;
                 return sus.name + ":" + sus.userId;
@@ -2313,6 +2426,7 @@
     public ResolveInfo resolveIntent(Intent intent, String resolvedType,
             int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "resolve intent");
         List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
         return chooseBestActivity(intent, resolvedType, flags, query, userId);
     }
@@ -2346,6 +2460,15 @@
                 if (ri != null) {
                     return ri;
                 }
+                if (userId != 0) {
+                    ri = new ResolveInfo(mResolveInfo);
+                    ri.activityInfo = new ActivityInfo(ri.activityInfo);
+                    ri.activityInfo.applicationInfo = new ApplicationInfo(
+                            ri.activityInfo.applicationInfo);
+                    ri.activityInfo.applicationInfo.uid = UserHandle.getUid(userId,
+                            UserHandle.getAppId(ri.activityInfo.applicationInfo.uid));
+                    return ri;
+                }
                 return mResolveInfo;
             }
         }
@@ -2361,9 +2484,11 @@
                 intent = intent.getSelector(); 
             }
             if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
-            List<PreferredActivity> prefs =
-                    mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
-                            (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
+            PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
+            List<PreferredActivity> prefs = pir != null
+                    ? pir.queryIntent(intent, resolvedType,
+                            (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId)
+                    : null;
             if (prefs != null && prefs.size() > 0) {
                 // First figure out how good the original match set is.
                 // We will only allow preferred activities that came
@@ -2397,7 +2522,8 @@
                     if (pa.mPref.mMatch != match) {
                         continue;
                     }
-                    final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent, flags, userId);
+                    final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent,
+                            flags | PackageManager.GET_DISABLED_COMPONENTS, userId);
                     if (DEBUG_PREFERRED) {
                         Log.v(TAG, "Got preferred activity:");
                         if (ai != null) {
@@ -2414,7 +2540,7 @@
                         // it from the preferred activities list, and skip it.
                         Slog.w(TAG, "Removing dangling preferred activity: "
                                 + pa.mPref.mComponent);
-                        mSettings.mPreferredActivities.removeFilter(pa);
+                        pir.removeFilter(pa);
                         continue;
                     }
                     for (int j=0; j<N; j++) {
@@ -2434,7 +2560,7 @@
                         if (!pa.mPref.sameSet(query, priority)) {
                             Slog.i(TAG, "Result set changed, dropping preferred activity for "
                                     + intent + " type " + resolvedType);
-                            mSettings.mPreferredActivities.removeFilter(pa);
+                            pir.removeFilter(pa);
                             return null;
                         }
 
@@ -2450,7 +2576,8 @@
     @Override
     public List<ResolveInfo> queryIntentActivities(Intent intent,
             String resolvedType, int flags, int userId) {
-        if (!sUserManager.exists(userId)) return null;
+        if (!sUserManager.exists(userId)) return Collections.emptyList();
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "query intent activities");
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -2489,7 +2616,9 @@
     public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
             Intent[] specifics, String[] specificTypes, Intent intent,
             String resolvedType, int flags, int userId) {
-        if (!sUserManager.exists(userId)) return null;
+        if (!sUserManager.exists(userId)) return Collections.emptyList();
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, false,
+                "query intent activity options");
         final String resultsAction = intent.getAction();
 
         List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags
@@ -2659,7 +2788,7 @@
     @Override
     public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags,
             int userId) {
-        if (!sUserManager.exists(userId)) return null;
+        if (!sUserManager.exists(userId)) return Collections.emptyList();
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -2710,7 +2839,7 @@
     @Override
     public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags,
             int userId) {
-        if (!sUserManager.exists(userId)) return null;
+        if (!sUserManager.exists(userId)) return Collections.emptyList();
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -2759,11 +2888,14 @@
         return index;
     }
 
-    public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, String lastRead) {
+    @Override
+    public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, String lastRead,
+            int userId) {
         final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>();
         final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
         final String[] keys;
-        int userId = UserId.getCallingUserId();
+
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "get installed packages");
 
         // writer
         synchronized (mPackages) {
@@ -2838,8 +2970,8 @@
                 } else {
                     final PackageParser.Package p = mPackages.get(packageName);
                     if (p != null && ps != null) {
-                        ai = PackageParser.generateApplicationInfo(p, flags, ps.getStopped(userId),
-                                ps.getEnabled(userId), userId);
+                        ai = PackageParser.generateApplicationInfo(p, flags,
+                                ps.readUserState(userId), userId);
                     }
                 }
 
@@ -2862,17 +2994,20 @@
         // reader
         synchronized (mPackages) {
             final Iterator<PackageParser.Package> i = mPackages.values().iterator();
-            final int userId = UserId.getCallingUserId();
+            final int userId = UserHandle.getCallingUserId();
             while (i.hasNext()) {
                 final PackageParser.Package p = i.next();
                 if (p.applicationInfo != null
                         && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
                         && (!mSafeMode || isSystemApp(p))) {
                     PackageSetting ps = mSettings.mPackages.get(p.packageName);
-                    finalList.add(PackageParser.generateApplicationInfo(p, flags,
-                            ps != null ? ps.getStopped(userId) : false,
-                            ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
-                            userId));
+                    if (ps != null) {
+                        ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
+                                ps.readUserState(userId), userId);
+                        if (ai != null) {
+                            finalList.add(ai);
+                        }
+                    }
                 }
             }
         }
@@ -2889,14 +3024,12 @@
             PackageSetting ps = provider != null
                     ? mSettings.mPackages.get(provider.owner.packageName)
                     : null;
-            return provider != null
+            return ps != null
                     && mSettings.isEnabledLPr(provider.info, flags, userId)
                     && (!mSafeMode || (provider.info.applicationInfo.flags
                             &ApplicationInfo.FLAG_SYSTEM) != 0)
                     ? PackageParser.generateProviderInfo(provider, flags,
-                            ps != null ? ps.getStopped(userId) : false,
-                            ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
-                            userId)
+                            ps.readUserState(userId), userId)
                     : null;
         }
     }
@@ -2910,20 +3043,21 @@
         synchronized (mPackages) {
             final Iterator<Map.Entry<String, PackageParser.Provider>> i = mProviders.entrySet()
                     .iterator();
-            final int userId = UserId.getCallingUserId();
+            final int userId = UserHandle.getCallingUserId();
             while (i.hasNext()) {
                 Map.Entry<String, PackageParser.Provider> entry = i.next();
                 PackageParser.Provider p = entry.getValue();
                 PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
 
-                if (p.syncable
+                if (ps != null && p.syncable
                         && (!mSafeMode || (p.info.applicationInfo.flags
                                 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
-                    outNames.add(entry.getKey());
-                    outInfo.add(PackageParser.generateProviderInfo(p, 0,
-                            ps != null ? ps.getStopped(userId) : false,
-                            ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
-                            userId));
+                    ProviderInfo info = PackageParser.generateProviderInfo(p, 0,
+                            ps.readUserState(userId), userId);
+                    if (info != null) {
+                        outNames.add(entry.getKey());
+                        outInfo.add(info);
+                    }
                 }
             }
         }
@@ -2937,24 +3071,25 @@
         synchronized (mPackages) {
             final Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
             final int userId = processName != null ?
-                    UserId.getUserId(uid) : UserId.getCallingUserId();
+                    UserHandle.getUserId(uid) : UserHandle.getCallingUserId();
             while (i.hasNext()) {
                 final PackageParser.Provider p = i.next();
                 PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
-                if (p.info.authority != null
+                if (ps != null && p.info.authority != null
                         && (processName == null
                                 || (p.info.processName.equals(processName)
-                                        && UserId.isSameApp(p.info.applicationInfo.uid, uid)))
+                                        && UserHandle.isSameApp(p.info.applicationInfo.uid, uid)))
                         && mSettings.isEnabledLPr(p.info, flags, userId)
                         && (!mSafeMode
                                 || (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
                     if (finalList == null) {
                         finalList = new ArrayList<ProviderInfo>(3);
                     }
-                    finalList.add(PackageParser.generateProviderInfo(p, flags,
-                            ps != null ? ps.getStopped(userId) : false,
-                            ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
-                            userId));
+                    ProviderInfo info = PackageParser.generateProviderInfo(p, flags,
+                            ps.readUserState(userId), userId);
+                    if (info != null) {
+                        finalList.add(info);
+                    }
                 }
             }
         }
@@ -2987,8 +3122,11 @@
                 final PackageParser.Instrumentation p = i.next();
                 if (targetPackage == null
                         || targetPackage.equals(p.info.targetPackage)) {
-                    finalList.add(PackageParser.generateInstrumentationInfo(p,
-                            flags));
+                    InstrumentationInfo ii = PackageParser.generateInstrumentationInfo(p,
+                            flags);
+                    if (ii != null) {
+                        finalList.add(ii);
+                    }
                 }
             }
         }
@@ -3015,7 +3153,7 @@
                 continue;
             }
             PackageParser.Package pkg = scanPackageLI(file,
-                    flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);
+                    flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);
             // Don't mess around with apps in system partition.
             if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
                     mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
@@ -3083,7 +3221,7 @@
      *  Returns null in case of errors and the error code is stored in mLastScanError
      */
     private PackageParser.Package scanPackageLI(File scanFile,
-            int parseFlags, int scanMode, long currentTime) {
+            int parseFlags, int scanMode, long currentTime, UserHandle user) {
         mLastScanError = PackageManager.INSTALL_SUCCEEDED;
         String scanPath = scanFile.getPath();
         parseFlags |= mDefParseFlags;
@@ -3149,7 +3287,7 @@
 
                     InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
                             ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
-                    synchronized (mInstaller) {
+                    synchronized (mInstallLock) {
                         args.cleanUpResourcesLI();
                     }
                     synchronized (mPackages) {
@@ -3183,7 +3321,7 @@
              */
             if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
                     != PackageManager.SIGNATURE_MATCH) {
-                deletePackageLI(pkg.packageName, true, 0, null, false);
+                deletePackageLI(pkg.packageName, null, true, 0, null, false);
                 ps = null;
             } else {
                 /*
@@ -3205,7 +3343,7 @@
                             + " better than installed " + ps.versionCode);
                     InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
                             ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
-                    synchronized (mInstaller) {
+                    synchronized (mInstallLock) {
                         args.cleanUpResourcesLI();
                     }
                 }
@@ -3236,7 +3374,7 @@
         setApplicationInfoPaths(pkg, codePath, resPath);
         // Note that we invoke the following method only if we are about to unpack an application
         PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode
-                | SCAN_UPDATE_SIGNATURE, currentTime);
+                | SCAN_UPDATE_SIGNATURE, currentTime, user);
 
         /*
          * If the system app should be overridden by a previously installed
@@ -3378,8 +3516,8 @@
                         return DEX_OPT_DEFERRED;
                     } else {
                         Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName);
-                        ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
-                                !isForwardLocked(pkg));
+                        final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
+                        ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg));
                         pkg.mDidDexOpt = true;
                         performed = true;
                     }
@@ -3439,8 +3577,45 @@
         }
     }
 
+    private int createDataDirsLI(String packageName, int uid) {
+        int[] users = sUserManager.getUserIds();
+        int res = mInstaller.install(packageName, uid, uid);
+        if (res < 0) {
+            return res;
+        }
+        for (int user : users) {
+            if (user != 0) {
+                res = mInstaller.createUserData(packageName,
+                        UserHandle.getUid(user, uid), user);
+                if (res < 0) {
+                    return res;
+                }
+            }
+        }
+        return res;
+    }
+
+    private int removeDataDirsLI(String packageName) {
+        int[] users = sUserManager.getUserIds();
+        int res = 0;
+        for (int user : users) {
+            int resInner = mInstaller.remove(packageName, user);
+            if (resInner < 0) {
+                res = resInner;
+            }
+        }
+
+        final File nativeLibraryFile = new File(mAppLibInstallDir, packageName);
+        NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
+        if (!nativeLibraryFile.delete()) {
+            Slog.w(TAG, "Couldn't delete native library directory " + nativeLibraryFile.getPath());
+        }
+
+        return res;
+    }
+
     private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
-            int parseFlags, int scanMode, long currentTime) {
+            int parseFlags, int scanMode, long currentTime, UserHandle user) {
         File scanFile = new File(pkg.mScanPath);
         if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
                 pkg.applicationInfo.publicSourceDir == null) {
@@ -3474,7 +3649,7 @@
                 mResolveActivity.applicationInfo = mAndroidApplication;
                 mResolveActivity.name = ResolverActivity.class.getName();
                 mResolveActivity.packageName = mAndroidApplication.packageName;
-                mResolveActivity.processName = mAndroidApplication.processName;
+                mResolveActivity.processName = "system:ui";
                 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
                 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
                 mResolveActivity.theme = com.android.internal.R.style.Theme_Holo_Dialog_Alert;
@@ -3632,7 +3807,7 @@
             // the PkgSetting exists already and doesn't have to be created.
             pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
                     destResourceFile, pkg.applicationInfo.nativeLibraryDir,
-                    pkg.applicationInfo.flags, true, false);
+                    pkg.applicationInfo.flags, user, false);
             if (pkgSetting == null) {
                 Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
                 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
@@ -3791,11 +3966,9 @@
                             || (scanMode&SCAN_BOOTING) != 0)) {
                         // If this is a system app, we can at least delete its
                         // current data so the application will still work.
-                        int ret = mInstaller.remove(pkgName, 0);
+                        int ret = removeDataDirsLI(pkgName);
                         if (ret >= 0) {
                             // TODO: Kill the processes first
-                            // Remove the data directories for all users
-                            sUserManager.removePackageForAllUsers(pkgName);
                             // Old data gone!
                             String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
                                     ? "System package " : "Third party package ";
@@ -3807,8 +3980,7 @@
                             recovered = true;
 
                             // And now re-install the app.
-                            ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
-                                    pkg.applicationInfo.uid);
+                            ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
                             if (ret == -1) {
                                 // Ack should not happen!
                                 msg = prefix + pkg.packageName
@@ -3817,9 +3989,6 @@
                                 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                                 return null;
                             }
-                            // Create data directories for all users
-                            sUserManager.installPackageForAllUsers(pkgName,
-                                    pkg.applicationInfo.uid);
                         }
                         if (!recovered) {
                             mHasSystemUidErrors = true;
@@ -3857,15 +4026,12 @@
                         Log.v(TAG, "Want this data dir: " + dataPath);
                 }
                 //invoke installer to do the actual installation
-                int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
-                        pkg.applicationInfo.uid);
+                int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
                 if (ret < 0) {
                     // Error from installer
                     mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                     return null;
                 }
-                // Create data directories for all users
-                sUserManager.installPackageForAllUsers(pkgName, pkg.applicationInfo.uid);
 
                 if (dataPath.exists()) {
                     pkg.applicationInfo.dataDir = dataPath.getPath();
@@ -3886,9 +4052,7 @@
              */
             if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
                 if (pkgSetting.nativeLibraryPathString == null) {
-                    final String nativeLibraryPath = new File(dataPath, LIB_DIR_NAME).getPath();
-                    pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
-                    pkgSetting.nativeLibraryPathString = nativeLibraryPath;
+                    setInternalAppNativeLibraryPath(pkg, pkgSetting);
                 } else {
                     pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
                 }
@@ -3910,7 +4074,7 @@
          */
         if (pkg.applicationInfo.nativeLibraryDir != null) {
             try {
-                final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
+                File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
                 final String dataPathString = dataPath.getCanonicalPath();
 
                 if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
@@ -3925,37 +4089,46 @@
                         Log.i(TAG, "removed obsolete native libraries for system package "
                                 + path);
                     }
-                } else if (nativeLibraryDir.getParentFile().getCanonicalPath()
-                        .equals(dataPathString)) {
-                    /*
-                     * Make sure the native library dir isn't a symlink to
-                     * something. If it is, ask installd to remove it and create
-                     * a directory so we can copy to it afterwards.
-                     */
-                    boolean isSymLink;
-                    try {
-                        isSymLink = S_ISLNK(Libcore.os.lstat(nativeLibraryDir.getPath()).st_mode);
-                    } catch (ErrnoException e) {
-                        // This shouldn't happen, but we'll fail-safe.
-                        isSymLink = true;
-                    }
-                    if (isSymLink) {
-                        mInstaller.unlinkNativeLibraryDirectory(dataPathString);
+                } else {
+                    if (!isForwardLocked(pkg) && !isExternal(pkg)) {
+                        /*
+                         * Update native library dir if it starts with
+                         * /data/data
+                         */
+                        if (nativeLibraryDir.getPath().startsWith(dataPathString)) {
+                            setInternalAppNativeLibraryPath(pkg, pkgSetting);
+                            nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
+                        }
+
+                        try {
+                            if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
+                                Slog.e(TAG, "Unable to copy native libraries");
+                                mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+                                return null;
+                            }
+                        } catch (IOException e) {
+                            Slog.e(TAG, "Unable to copy native libraries", e);
+                            mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+                            return null;
+                        }
                     }
 
-                    /*
-                     * If this is an internal application or our
-                     * nativeLibraryPath points to our data directory, unpack
-                     * the libraries if necessary.
-                     */
-                    NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
-                } else {
                     Slog.i(TAG, "Linking native library dir for " + path);
-                    mInstaller.linkNativeLibraryDirectory(dataPathString,
-                            pkg.applicationInfo.nativeLibraryDir);
+                    final int[] userIds = sUserManager.getUserIds();
+                    synchronized (mInstallLock) {
+                        for (int userId : userIds) {
+                            if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
+                                    pkg.applicationInfo.nativeLibraryDir, userId) < 0) {
+                                Slog.w(TAG, "Failed linking native library dir (user=" + userId
+                                        + ")");
+                                mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+                                return null;
+                            }
+                        }
+                    }
                 }
             } catch (IOException ioe) {
-                Log.e(TAG, "Unable to get canonical file " + ioe.toString());
+                Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
             }
         }
         pkg.mScanPath = path;
@@ -3992,8 +4165,14 @@
             // Add the new setting to mPackages
             mPackages.put(pkg.applicationInfo.packageName, pkg);
             // Make sure we don't accidentally delete its data.
-            mSettings.mPackagesToBeCleaned.remove(pkgName);
-            
+            final Iterator<PackageCleanItem> iter = mSettings.mPackagesToBeCleaned.iterator();
+            while (iter.hasNext()) {
+                PackageCleanItem item = iter.next();
+                if (pkgName.equals(item.packageName)) {
+                    iter.remove();
+                }
+            }
+
             // Take care of first install / last update times.
             if (currentTime != 0) {
                 if (pkgSetting.firstInstallTime == 0) {
@@ -4268,20 +4447,75 @@
         return pkg;
     }
 
-    private void killApplication(String pkgName, int uid) {
+    private void setInternalAppNativeLibraryPath(PackageParser.Package pkg,
+            PackageSetting pkgSetting) {
+        final String apkLibPath = getApkName(pkgSetting.codePathString);
+        final String nativeLibraryPath = new File(mAppLibInstallDir, apkLibPath).getPath();
+        pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
+        pkgSetting.nativeLibraryPathString = nativeLibraryPath;
+    }
+
+    private static int copyNativeLibrariesForInternalApp(File scanFile, final File nativeLibraryDir)
+            throws IOException {
+        if (!nativeLibraryDir.isDirectory()) {
+            nativeLibraryDir.delete();
+
+            if (!nativeLibraryDir.mkdir()) {
+                throw new IOException("Cannot create " + nativeLibraryDir.getPath());
+            }
+
+            try {
+                Libcore.os.chmod(nativeLibraryDir.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH
+                        | S_IXOTH);
+            } catch (ErrnoException e) {
+                throw new IOException("Cannot chmod native library directory "
+                        + nativeLibraryDir.getPath(), e);
+            }
+        } else if (!SELinux.restorecon(nativeLibraryDir)) {
+            throw new IOException("Cannot set SELinux context for " + nativeLibraryDir.getPath());
+        }
+
+        /*
+         * If this is an internal application or our nativeLibraryPath points to
+         * the app-lib directory, unpack the libraries if necessary.
+         */
+        return NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
+    }
+
+    private void killApplication(String pkgName, int appId) {
         // Request the ActivityManager to kill the process(only for existing packages)
         // so that we do not end up in a confused state while the user is still using the older
         // version of the application while the new one gets installed.
         IActivityManager am = ActivityManagerNative.getDefault();
         if (am != null) {
             try {
-                am.killApplicationWithUid(pkgName, uid);
+                am.killApplicationWithAppId(pkgName, appId);
             } catch (RemoteException e) {
             }
         }
     }
 
-    void removePackageLI(PackageParser.Package pkg, boolean chatty) {
+    void removePackageLI(PackageSetting ps, boolean chatty) {
+        if (DEBUG_INSTALL) {
+            if (chatty)
+                Log.d(TAG, "Removing package " + ps.name);
+        }
+
+        // writer
+        synchronized (mPackages) {
+            mPackages.remove(ps.name);
+            if (ps.codePathString != null) {
+                mAppDirs.remove(ps.codePathString);
+            }
+
+            final PackageParser.Package pkg = ps.pkg;
+            if (pkg != null) {
+                cleanPackageDataStructuresLILPw(pkg, chatty);
+            }
+        }
+    }
+
+    void removeInstalledPackageLI(PackageParser.Package pkg, boolean chatty) {
         if (DEBUG_INSTALL) {
             if (chatty)
                 Log.d(TAG, "Removing package " + pkg.applicationInfo.packageName);
@@ -4293,34 +4527,115 @@
             if (pkg.mPath != null) {
                 mAppDirs.remove(pkg.mPath);
             }
+            cleanPackageDataStructuresLILPw(pkg, chatty);
+        }
+    }
 
-            int N = pkg.providers.size();
-            StringBuilder r = null;
-            int i;
-            for (i=0; i<N; i++) {
-                PackageParser.Provider p = pkg.providers.get(i);
-                mProvidersByComponent.remove(new ComponentName(p.info.packageName,
-                        p.info.name));
-                if (p.info.authority == null) {
+    void cleanPackageDataStructuresLILPw(PackageParser.Package pkg, boolean chatty) {
+        int N = pkg.providers.size();
+        StringBuilder r = null;
+        int i;
+        for (i=0; i<N; i++) {
+            PackageParser.Provider p = pkg.providers.get(i);
+            mProvidersByComponent.remove(new ComponentName(p.info.packageName,
+                    p.info.name));
+            if (p.info.authority == null) {
 
-                    /* The is another ContentProvider with this authority when
-                     * this app was installed so this authority is null,
-                     * Ignore it as we don't have to unregister the provider.
-                     */
-                    continue;
-                }
-                String names[] = p.info.authority.split(";");
-                for (int j = 0; j < names.length; j++) {
-                    if (mProviders.get(names[j]) == p) {
-                        mProviders.remove(names[j]);
-                        if (DEBUG_REMOVE) {
-                            if (chatty)
-                                Log.d(TAG, "Unregistered content provider: " + names[j]
-                                        + ", className = " + p.info.name + ", isSyncable = "
-                                        + p.info.isSyncable);
-                        }
+                /* There was another ContentProvider with this authority when
+                 * this app was installed so this authority is null,
+                 * Ignore it as we don't have to unregister the provider.
+                 */
+                continue;
+            }
+            String names[] = p.info.authority.split(";");
+            for (int j = 0; j < names.length; j++) {
+                if (mProviders.get(names[j]) == p) {
+                    mProviders.remove(names[j]);
+                    if (DEBUG_REMOVE) {
+                        if (chatty)
+                            Log.d(TAG, "Unregistered content provider: " + names[j]
+                                    + ", className = " + p.info.name + ", isSyncable = "
+                                    + p.info.isSyncable);
                     }
                 }
+            }
+            if (chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(p.info.name);
+            }
+        }
+        if (r != null) {
+            if (DEBUG_REMOVE) Log.d(TAG, "  Providers: " + r);
+        }
+
+        N = pkg.services.size();
+        r = null;
+        for (i=0; i<N; i++) {
+            PackageParser.Service s = pkg.services.get(i);
+            mServices.removeService(s);
+            if (chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(s.info.name);
+            }
+        }
+        if (r != null) {
+            if (DEBUG_REMOVE) Log.d(TAG, "  Services: " + r);
+        }
+
+        N = pkg.receivers.size();
+        r = null;
+        for (i=0; i<N; i++) {
+            PackageParser.Activity a = pkg.receivers.get(i);
+            mReceivers.removeActivity(a, "receiver");
+            if (chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(a.info.name);
+            }
+        }
+        if (r != null) {
+            if (DEBUG_REMOVE) Log.d(TAG, "  Receivers: " + r);
+        }
+
+        N = pkg.activities.size();
+        r = null;
+        for (i=0; i<N; i++) {
+            PackageParser.Activity a = pkg.activities.get(i);
+            mActivities.removeActivity(a, "activity");
+            if (chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(a.info.name);
+            }
+        }
+        if (r != null) {
+            if (DEBUG_REMOVE) Log.d(TAG, "  Activities: " + r);
+        }
+
+        N = pkg.permissions.size();
+        r = null;
+        for (i=0; i<N; i++) {
+            PackageParser.Permission p = pkg.permissions.get(i);
+            BasePermission bp = mSettings.mPermissions.get(p.info.name);
+            if (bp == null) {
+                bp = mSettings.mPermissionTrees.get(p.info.name);
+            }
+            if (bp != null && bp.perm == p) {
+                bp.perm = null;
                 if (chatty) {
                     if (r == null) {
                         r = new StringBuilder(256);
@@ -4330,105 +4645,27 @@
                     r.append(p.info.name);
                 }
             }
-            if (r != null) {
-                if (DEBUG_REMOVE) Log.d(TAG, "  Providers: " + r);
-            }
+        }
+        if (r != null) {
+            if (DEBUG_REMOVE) Log.d(TAG, "  Permissions: " + r);
+        }
 
-            N = pkg.services.size();
-            r = null;
-            for (i=0; i<N; i++) {
-                PackageParser.Service s = pkg.services.get(i);
-                mServices.removeService(s);
-                if (chatty) {
-                    if (r == null) {
-                        r = new StringBuilder(256);
-                    } else {
-                        r.append(' ');
-                    }
-                    r.append(s.info.name);
+        N = pkg.instrumentation.size();
+        r = null;
+        for (i=0; i<N; i++) {
+            PackageParser.Instrumentation a = pkg.instrumentation.get(i);
+            mInstrumentation.remove(a.getComponentName());
+            if (chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
                 }
+                r.append(a.info.name);
             }
-            if (r != null) {
-                if (DEBUG_REMOVE) Log.d(TAG, "  Services: " + r);
-            }
-
-            N = pkg.receivers.size();
-            r = null;
-            for (i=0; i<N; i++) {
-                PackageParser.Activity a = pkg.receivers.get(i);
-                mReceivers.removeActivity(a, "receiver");
-                if (chatty) {
-                    if (r == null) {
-                        r = new StringBuilder(256);
-                    } else {
-                        r.append(' ');
-                    }
-                    r.append(a.info.name);
-                }
-            }
-            if (r != null) {
-                if (DEBUG_REMOVE) Log.d(TAG, "  Receivers: " + r);
-            }
-
-            N = pkg.activities.size();
-            r = null;
-            for (i=0; i<N; i++) {
-                PackageParser.Activity a = pkg.activities.get(i);
-                mActivities.removeActivity(a, "activity");
-                if (chatty) {
-                    if (r == null) {
-                        r = new StringBuilder(256);
-                    } else {
-                        r.append(' ');
-                    }
-                    r.append(a.info.name);
-                }
-            }
-            if (r != null) {
-                if (DEBUG_REMOVE) Log.d(TAG, "  Activities: " + r);
-            }
-
-            N = pkg.permissions.size();
-            r = null;
-            for (i=0; i<N; i++) {
-                PackageParser.Permission p = pkg.permissions.get(i);
-                BasePermission bp = mSettings.mPermissions.get(p.info.name);
-                if (bp == null) {
-                    bp = mSettings.mPermissionTrees.get(p.info.name);
-                }
-                if (bp != null && bp.perm == p) {
-                    bp.perm = null;
-                    if (chatty) {
-                        if (r == null) {
-                            r = new StringBuilder(256);
-                        } else {
-                            r.append(' ');
-                        }
-                        r.append(p.info.name);
-                    }
-                }
-            }
-            if (r != null) {
-                if (DEBUG_REMOVE) Log.d(TAG, "  Permissions: " + r);
-            }
-
-            N = pkg.instrumentation.size();
-            r = null;
-            for (i=0; i<N; i++) {
-                PackageParser.Instrumentation a = pkg.instrumentation.get(i);
-                mInstrumentation.remove(a.getComponentName());
-                if (chatty) {
-                    if (r == null) {
-                        r = new StringBuilder(256);
-                    } else {
-                        r.append(' ');
-                    }
-                    r.append(a.info.name);
-                }
-            }
-            if (r != null) {
-                if (DEBUG_REMOVE) Log.d(TAG, "  Instrumentation: " + r);
-            }
+        }
+        if (r != null) {
+            if (DEBUG_REMOVE) Log.d(TAG, "  Instrumentation: " + r);
         }
     }
 
@@ -4716,14 +4953,17 @@
             mFlags = flags;
             final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
             final int N = packageActivities.size();
-            ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
-                new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
+            ArrayList<PackageParser.ActivityIntentInfo[]> listCut =
+                new ArrayList<PackageParser.ActivityIntentInfo[]>(N);
 
             ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
             for (int i = 0; i < N; ++i) {
                 intentFilters = packageActivities.get(i).intents;
                 if (intentFilters != null && intentFilters.size() > 0) {
-                    listCut.add(intentFilters);
+                    PackageParser.ActivityIntentInfo[] array =
+                            new PackageParser.ActivityIntentInfo[intentFilters.size()];
+                    intentFilters.toArray(array);
+                    listCut.add(array);
                 }
             }
             return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
@@ -4791,6 +5031,11 @@
         }
 
         @Override
+        protected ActivityIntentInfo[] newArray(int size) {
+            return new ActivityIntentInfo[size];
+        }
+
+        @Override
         protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) {
             if (!sUserManager.exists(userId)) return true;
             PackageParser.Package p = filter.activity.owner;
@@ -4800,7 +5045,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.getStopped(userId) && (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0;
+                    return (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
+                            && ps.getStopped(userId);
                 }
             }
             return false;
@@ -4823,12 +5069,17 @@
                     &ApplicationInfo.FLAG_SYSTEM) == 0) {
                 return null;
             }
-            final ResolveInfo res = new ResolveInfo();
             PackageSetting ps = (PackageSetting) activity.owner.mExtras;
-            res.activityInfo = PackageParser.generateActivityInfo(activity, mFlags,
-                    ps != null ? ps.getStopped(userId) : false,
-                    ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
-                    userId);
+            if (ps == null) {
+                return null;
+            }
+            ActivityInfo ai = PackageParser.generateActivityInfo(activity, mFlags,
+                    ps.readUserState(userId), userId);
+            if (ai == null) {
+                return null;
+            }
+            final ResolveInfo res = new ResolveInfo();
+            res.activityInfo = ai;
             if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
                 res.filter = info;
             }
@@ -4904,14 +5155,17 @@
             mFlags = flags;
             final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
             final int N = packageServices.size();
-            ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
-                new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
+            ArrayList<PackageParser.ServiceIntentInfo[]> listCut =
+                new ArrayList<PackageParser.ServiceIntentInfo[]>(N);
 
             ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
             for (int i = 0; i < N; ++i) {
                 intentFilters = packageServices.get(i).intents;
                 if (intentFilters != null && intentFilters.size() > 0) {
-                    listCut.add(intentFilters);
+                    PackageParser.ServiceIntentInfo[] array =
+                            new PackageParser.ServiceIntentInfo[intentFilters.size()];
+                    intentFilters.toArray(array);
+                    listCut.add(array);
                 }
             }
             return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
@@ -4974,6 +5228,11 @@
         }
 
         @Override
+        protected PackageParser.ServiceIntentInfo[] newArray(int size) {
+            return new PackageParser.ServiceIntentInfo[size];
+        }
+
+        @Override
         protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) {
             if (!sUserManager.exists(userId)) return true;
             PackageParser.Package p = filter.service.owner;
@@ -4983,8 +5242,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.getStopped(userId)
-                            && (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0;
+                    return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
+                            && ps.getStopped(userId);
                 }
             }
             return false;
@@ -5008,12 +5267,17 @@
                     &ApplicationInfo.FLAG_SYSTEM) == 0) {
                 return null;
             }
-            final ResolveInfo res = new ResolveInfo();
             PackageSetting ps = (PackageSetting) service.owner.mExtras;
-            res.serviceInfo = PackageParser.generateServiceInfo(service, mFlags,
-                    ps != null ? ps.getStopped(userId) : false,
-                    ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
-                    userId);
+            if (ps == null) {
+                return null;
+            }
+            ServiceInfo si = PackageParser.generateServiceInfo(service, mFlags,
+                    ps.readUserState(userId), userId);
+            if (si == null) {
+                return null;
+            }
+            final ResolveInfo res = new ResolveInfo();
+            res.serviceInfo = si;
             if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
                 res.filter = filter;
             }
@@ -5104,13 +5368,14 @@
     };
 
     static final void sendPackageBroadcast(String action, String pkg,
-            Bundle extras, String targetPkg, IIntentReceiver finishedReceiver, int userId) {
+            Bundle extras, String targetPkg, IIntentReceiver finishedReceiver,
+            int[] userIds) {
         IActivityManager am = ActivityManagerNative.getDefault();
         if (am != null) {
             try {
-                int[] userIds = userId == UserId.USER_ALL
-                        ? sUserManager.getUserIds() 
-                        : new int[] {userId};
+                if (userIds == null) {
+                    userIds = am.getRunningUserIds();
+                }
                 for (int id : userIds) {
                     final Intent intent = new Intent(action,
                             pkg != null ? Uri.fromParts("package", pkg, null) : null);
@@ -5122,11 +5387,19 @@
                     }
                     // Modify the UID when posting to other users
                     int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
-                    if (uid > 0 && id > 0) {
-                        uid = UserId.getUid(id, UserId.getAppId(uid));
+                    if (uid > 0 && UserHandle.getUserId(uid) != id) {
+                        uid = UserHandle.getUid(id, UserHandle.getAppId(uid));
                         intent.putExtra(Intent.EXTRA_UID, uid);
                     }
+                    intent.putExtra(Intent.EXTRA_USER_HANDLE, id);
                     intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                    if (DEBUG_BROADCASTS) {
+                        RuntimeException here = new RuntimeException("here");
+                        here.fillInStackTrace();
+                        Slog.d(TAG, "Sending to user " + id + ": "
+                                + intent.toShortString(false, true, false, false)
+                                + " " + intent.getExtras(), here);
+                    }
                     am.broadcastIntent(null, intent, null, finishedReceiver,
                             0, null, null, null, finishedReceiver != null, false, id);
                 }
@@ -5144,7 +5417,7 @@
         return mMediaMounted || Environment.isExternalStorageEmulated();
     }
 
-    public String nextPackageToClean(String lastPackage) {
+    public PackageCleanItem nextPackageToClean(PackageCleanItem lastPackage) {
         // writer
         synchronized (mPackages) {
             if (!isExternalMediaAvailable()) {
@@ -5153,16 +5426,26 @@
                 // packages files and can not delete any more.  Bail.
                 return null;
             }
+            final ArrayList<PackageCleanItem> pkgs = mSettings.mPackagesToBeCleaned;
             if (lastPackage != null) {
-                mSettings.mPackagesToBeCleaned.remove(lastPackage);
+                pkgs.remove(lastPackage);
             }
-            return mSettings.mPackagesToBeCleaned.size() > 0
-                    ? mSettings.mPackagesToBeCleaned.get(0) : null;
+            if (pkgs.size() > 0) {
+                return pkgs.get(0);
+            }
         }
+        return null;
     }
 
-    void schedulePackageCleaning(String packageName) {
-        mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName));
+    void schedulePackageCleaning(String packageName, int userId, boolean andCode) {
+        if (false) {
+            RuntimeException here = new RuntimeException("here");
+            here.fillInStackTrace();
+            Slog.d(TAG, "Schedule cleaning " + packageName + " user=" + userId
+                    + " andCode=" + andCode, here);
+        }
+        mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE,
+                userId, andCode ? 1 : 0, packageName));
     }
     
     void startCleaningPackages() {
@@ -5171,7 +5454,7 @@
             if (!isExternalMediaAvailable()) {
                 return;
             }
-            if (mSettings.mPackagesToBeCleaned.size() <= 0) {
+            if (mSettings.mPackagesToBeCleaned.isEmpty()) {
                 return;
             }
         }
@@ -5180,7 +5463,7 @@
         IActivityManager am = ActivityManagerNative.getDefault();
         if (am != null) {
             try {
-                am.startService(null, intent, null);
+                am.startService(null, intent, null, UserHandle.USER_OWNER);
             } catch (RemoteException e) {
             }
         }
@@ -5195,9 +5478,11 @@
 
         public void onEvent(int event, String path) {
             String removedPackage = null;
-            int removedUid = -1;
+            int removedAppId = -1;
+            int[] removedUsers = null;
             String addedPackage = null;
-            int addedUid = -1;
+            int addedAppId = -1;
+            int[] addedUsers = null;
 
             // TODO post a message to the handler to obtain serial ordering
             synchronized (mInstallLock) {
@@ -5223,15 +5508,25 @@
                     return;
                 }
                 PackageParser.Package p = null;
+                PackageSetting ps = null;
                 // reader
                 synchronized (mPackages) {
                     p = mAppDirs.get(fullPathStr);
+                    if (p != null) {
+                        ps = mSettings.mPackages.get(p.applicationInfo.packageName);
+                        if (ps != null) {
+                            removedUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
+                        } else {
+                            removedUsers = sUserManager.getUserIds();
+                        }
+                    }
+                    addedUsers = sUserManager.getUserIds();
                 }
                 if ((event&REMOVE_EVENTS) != 0) {
-                    if (p != null) {
-                        removePackageLI(p, true);
-                        removedPackage = p.applicationInfo.packageName;
-                        removedUid = p.applicationInfo.uid;
+                    if (ps != null) {
+                        removePackageLI(ps, true);
+                        removedPackage = ps.name;
+                        removedAppId = ps.appId;
                     }
                 }
 
@@ -5243,7 +5538,7 @@
                                 PackageParser.PARSE_CHATTY |
                                 PackageParser.PARSE_MUST_BE_APK,
                                 SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
-                                System.currentTimeMillis());
+                                System.currentTimeMillis(), UserHandle.ALL);
                         if (p != null) {
                             /*
                              * TODO this seems dangerous as the package may have
@@ -5256,7 +5551,7 @@
                                         p.permissions.size() > 0 ? UPDATE_PERMISSIONS_ALL : 0);
                             }
                             addedPackage = p.applicationInfo.packageName;
-                            addedUid = p.applicationInfo.uid;
+                            addedAppId = UserHandle.getAppId(p.applicationInfo.uid);
                         }
                     }
                 }
@@ -5269,16 +5564,16 @@
 
             if (removedPackage != null) {
                 Bundle extras = new Bundle(1);
-                extras.putInt(Intent.EXTRA_UID, removedUid);
+                extras.putInt(Intent.EXTRA_UID, removedAppId);
                 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
                 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
-                        extras, null, null, UserId.USER_ALL);
+                        extras, null, null, removedUsers);
             }
             if (addedPackage != null) {
                 Bundle extras = new Bundle(1);
-                extras.putInt(Intent.EXTRA_UID, addedUid);
+                extras.putInt(Intent.EXTRA_UID, addedAppId);
                 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
-                        extras, null, null, UserId.USER_ALL);
+                        extras, null, null, addedUsers);
             }
         }
 
@@ -5304,9 +5599,25 @@
     public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
             int flags, String installerPackageName, Uri verificationURI,
             ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
+        VerificationParams verificationParams = new VerificationParams(verificationURI, null, null,
+                VerificationParams.NO_UID, manifestDigest);
+        installPackageWithVerificationAndEncryption(packageURI, observer, flags,
+                installerPackageName, verificationParams, encryptionParams);
+    }
+
+    public void installPackageWithVerificationAndEncryption(Uri packageURI,
+            IPackageInstallObserver observer, int flags, String installerPackageName,
+            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
+                null);
 
         final int uid = Binder.getCallingUid();
+        UserHandle user;
+        if ((flags&PackageManager.INSTALL_ALL_USERS) != 0) {
+            user = UserHandle.ALL;
+        } else {
+            user = new UserHandle(UserHandle.getUserId(uid));
+        }
 
         final int filteredFlags;
 
@@ -5319,14 +5630,61 @@
             filteredFlags = flags & ~PackageManager.INSTALL_FROM_ADB;
         }
 
+        verificationParams.setInstallerUid(uid);
+
         final Message msg = mHandler.obtainMessage(INIT_COPY);
         msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
-                verificationURI, manifestDigest, encryptionParams);
+                verificationParams, encryptionParams, user);
         mHandler.sendMessage(msg);
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public int installExistingPackage(String packageName) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
+                null);
+        PackageSetting pkgSetting;
+        final int uid = Binder.getCallingUid();
+        final int userId = UserHandle.getUserId(uid);
+
+        long callingId = Binder.clearCallingIdentity();
+        try {
+            boolean sendAdded = false;
+            Bundle extras = new Bundle(1);
+
+            // writer
+            synchronized (mPackages) {
+                pkgSetting = mSettings.mPackages.get(packageName);
+                if (pkgSetting == null) {
+                    return PackageManager.INSTALL_FAILED_INVALID_URI;
+                }
+                if (!pkgSetting.getInstalled(userId)) {
+                    pkgSetting.setInstalled(true, userId);
+                    mSettings.writePackageRestrictionsLPr(userId);
+                    extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userId, pkgSetting.appId));
+                    sendAdded = true;
+                }
+            }
+
+            if (sendAdded) {
+                sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
+                        packageName, extras, null, null, new int[] {userId});
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingId);
+        }
+
+        return PackageManager.INSTALL_SUCCEEDED;
+    }
+    
     @Override
     public void verifyPendingInstall(int id, int verificationCode) throws RemoteException {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
+                "Only package verification agents can verify applications");
+
         final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
         final PackageVerificationResponse response = new PackageVerificationResponse(
                 verificationCode, Binder.getCallingUid());
@@ -5335,6 +5693,50 @@
         mHandler.sendMessage(msg);
     }
 
+    @Override
+    public void extendVerificationTimeout(int id, int verificationCodeAtTimeout,
+            long millisecondsToDelay) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
+                "Only package verification agents can extend verification timeouts");
+
+        final PackageVerificationState state = mPendingVerification.get(id);
+        final PackageVerificationResponse response = new PackageVerificationResponse(
+                verificationCodeAtTimeout, Binder.getCallingUid());
+
+        if (millisecondsToDelay > PackageManager.MAXIMUM_VERIFICATION_TIMEOUT) {
+            millisecondsToDelay = PackageManager.MAXIMUM_VERIFICATION_TIMEOUT;
+        }
+        if (millisecondsToDelay < 0) {
+            millisecondsToDelay = 0;
+        }
+        if ((verificationCodeAtTimeout != PackageManager.VERIFICATION_ALLOW)
+                && (verificationCodeAtTimeout != PackageManager.VERIFICATION_REJECT)) {
+            verificationCodeAtTimeout = PackageManager.VERIFICATION_REJECT;
+        }
+
+        if ((state != null) && !state.timeoutExtended()) {
+            state.extendTimeout();
+
+            final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
+            msg.arg1 = id;
+            msg.obj = response;
+            mHandler.sendMessageDelayed(msg, millisecondsToDelay);
+        }
+    }
+
+    private void broadcastPackageVerified(int verificationId, Uri packageUri,
+            int verificationCode, UserHandle user) {
+        final Intent intent = new Intent(Intent.ACTION_PACKAGE_VERIFIED);
+        intent.setDataAndType(packageUri, PACKAGE_MIME_TYPE);
+        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        intent.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
+        intent.putExtra(PackageManager.EXTRA_VERIFICATION_RESULT, verificationCode);
+
+        mContext.sendBroadcastAsUser(intent, user,
+                android.Manifest.permission.PACKAGE_VERIFICATION_AGENT);
+    }
+
     private ComponentName matchComponentForVerifier(String packageName,
             List<ResolveInfo> receivers) {
         ActivityInfo targetReceiver = null;
@@ -5447,20 +5849,58 @@
      * @return verification timeout in milliseconds
      */
     private long getVerificationTimeout() {
-        return android.provider.Settings.Secure.getLong(mContext.getContentResolver(),
-                android.provider.Settings.Secure.PACKAGE_VERIFIER_TIMEOUT,
+        return android.provider.Settings.Global.getLong(mContext.getContentResolver(),
+                android.provider.Settings.Global.PACKAGE_VERIFIER_TIMEOUT,
                 DEFAULT_VERIFICATION_TIMEOUT);
     }
 
     /**
+     * Get the default verification agent response code.
+     *
+     * @return default verification response code
+     */
+    private int getDefaultVerificationResponse() {
+        return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
+                android.provider.Settings.Global.PACKAGE_VERIFIER_DEFAULT_RESPONSE,
+                DEFAULT_VERIFICATION_RESPONSE);
+    }
+
+    /**
      * Check whether or not package verification has been enabled.
      *
      * @return true if verification should be performed
      */
-    private boolean isVerificationEnabled() {
-        return android.provider.Settings.Secure.getInt(mContext.getContentResolver(),
-                android.provider.Settings.Secure.PACKAGE_VERIFIER_ENABLE,
-                DEFAULT_VERIFY_ENABLE ? 1 : 0) == 1 ? true : false;
+    private boolean isVerificationEnabled(int flags) {
+        if (!DEFAULT_VERIFY_ENABLE) {
+            return false;
+        }
+
+        // Check if installing from ADB
+        if ((flags & PackageManager.INSTALL_FROM_ADB) != 0) {
+            // Do not run verification in a test harness environment
+            if (ActivityManager.isRunningInTestHarness()) {
+                return false;
+            }
+            // Check if the developer does not want package verification for ADB installs
+            if (android.provider.Settings.Global.getInt(mContext.getContentResolver(),
+                    android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) == 0) {
+                return false;
+            }
+        }
+
+        return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
+                android.provider.Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) == 1;
+    }
+
+    /**
+     * Get the "allow unknown sources" setting.
+     *
+     * @return the current "allow unknown sources" setting
+     */
+    private int getUnknownSourcesSettings() {
+        return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
+                android.provider.Settings.Global.INSTALL_NON_MARKET_APPS,
+                -1);
     }
 
     public void setInstallerPackageName(String targetPackage, String installerPackageName) {
@@ -5615,6 +6055,17 @@
          */
         private int mRetries = 0;
 
+        /** User handle for the user requesting the information or installation. */
+        private final UserHandle mUser;
+
+        HandlerParams(UserHandle user) {
+            mUser = user;
+        }
+
+        UserHandle getUser() {
+            return mUser;
+        }
+
         final boolean startCopy() {
             boolean res;
             try {
@@ -5656,6 +6107,7 @@
         private final IPackageStatsObserver mObserver;
 
         public MeasureParams(PackageStats stats, IPackageStatsObserver observer) {
+            super(new UserHandle(stats.userHandle));
             mObserver = observer;
             mStats = stats;
         }
@@ -5663,7 +6115,7 @@
         @Override
         void handleStartCopy() throws RemoteException {
             synchronized (mInstallLock) {
-                mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats);
+                mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats.userHandle, mStats);
             }
 
             final boolean mounted;
@@ -5671,19 +6123,20 @@
                 mounted = true;
             } else {
                 final String status = Environment.getExternalStorageState();
-
-                mounted = status.equals(Environment.MEDIA_MOUNTED)
-                        || status.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
+                mounted = (Environment.MEDIA_MOUNTED.equals(status)
+                        || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status));
             }
 
             if (mounted) {
-                final File externalCacheDir = Environment
+                final UserEnvironment userEnv = new UserEnvironment(mStats.userHandle);
+
+                final File externalCacheDir = userEnv
                         .getExternalStorageAppCacheDirectory(mStats.packageName);
                 final long externalCacheSize = mContainerService
                         .calculateDirectorySize(externalCacheDir.getPath());
                 mStats.externalCacheSize = externalCacheSize;
 
-                final File externalDataDir = Environment
+                final File externalDataDir = userEnv
                         .getExternalStorageAppDataDirectory(mStats.packageName);
                 long externalDataSize = mContainerService.calculateDirectorySize(externalDataDir
                         .getPath());
@@ -5693,12 +6146,12 @@
                 }
                 mStats.externalDataSize = externalDataSize;
 
-                final File externalMediaDir = Environment
+                final File externalMediaDir = userEnv
                         .getExternalStorageAppMediaDirectory(mStats.packageName);
                 mStats.externalMediaSize = mContainerService
                         .calculateDirectorySize(externalMediaDir.getPath());
 
-                final File externalObbDir = Environment
+                final File externalObbDir = userEnv
                         .getExternalStorageAppObbDirectory(mStats.packageName);
                 mStats.externalObbSize = mContainerService.calculateDirectorySize(externalObbDir
                         .getPath());
@@ -5729,8 +6182,7 @@
 
         private final Uri mPackageURI;
         final String installerPackageName;
-        final Uri verificationURI;
-        final ManifestDigest manifestDigest;
+        final VerificationParams verificationParams;
         private InstallArgs mArgs;
         private int mRet;
         private File mTempPackage;
@@ -5738,17 +6190,24 @@
 
         InstallParams(Uri packageURI,
                 IPackageInstallObserver observer, int flags,
-                String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest,
-                ContainerEncryptionParams encryptionParams) {
+                String installerPackageName, VerificationParams verificationParams,
+                ContainerEncryptionParams encryptionParams, UserHandle user) {
+            super(user);
             this.mPackageURI = packageURI;
             this.flags = flags;
             this.observer = observer;
             this.installerPackageName = installerPackageName;
-            this.verificationURI = verificationURI;
-            this.manifestDigest = manifestDigest;
+            this.verificationParams = verificationParams;
             this.encryptionParams = encryptionParams;
         }
 
+        public ManifestDigest getManifestDigest() {
+            if (verificationParams == null) {
+                return null;
+            }
+            return verificationParams.getManifestDigest();
+        }
+
         private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
             String packageName = pkgLite.packageName;
             int installLocation = pkgLite.installLocation;
@@ -5758,6 +6217,16 @@
                 PackageParser.Package pkg = mPackages.get(packageName);
                 if (pkg != null) {
                     if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
+                        // Check for downgrading.
+                        if ((flags & PackageManager.INSTALL_ALLOW_DOWNGRADE) == 0) {
+                            if (pkgLite.versionCode < pkg.mVersionCode) {
+                                Slog.w(TAG, "Can't install update of " + packageName
+                                        + " update version " + pkgLite.versionCode
+                                        + " is older than installed version "
+                                        + pkg.mVersionCode);
+                                return PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE;
+                            }
+                        }
                         // Check for updated system application.
                         if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                             if (onSd) {
@@ -5850,7 +6319,8 @@
                             packageFile = mTempPackage;
 
                             FileUtils.setPermissions(packageFile.getAbsolutePath(),
-                                    FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IROTH,
+                                    FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP
+                                            | FileUtils.S_IROTH,
                                     -1, -1);
                         } else {
                             packageFile = null;
@@ -5861,8 +6331,23 @@
 
                     if (packageFile != null) {
                         // Remote call to find out default install location
-                        pkgLite = mContainerService.getMinimalPackageInfo(
-                                packageFile.getAbsolutePath(), flags, lowThreshold);
+                        final String packageFilePath = packageFile.getAbsolutePath();
+                        pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath, flags,
+                                lowThreshold);
+
+                        /*
+                         * If we have too little free space, try to free cache
+                         * before giving up.
+                         */
+                        if (pkgLite.recommendedInstallLocation
+                                == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
+                            final long size = mContainerService.calculateInstalledSize(
+                                    packageFilePath, isForwardLocked());
+                            if (mInstaller.freeCache(size + lowThreshold) >= 0) {
+                                pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath,
+                                        flags, lowThreshold);
+                            }
+                        }
                     }
                 } finally {
                     mContext.revokeUriPermission(mPackageURI,
@@ -5887,7 +6372,9 @@
                 } else {
                     // Override with defaults if needed.
                     loc = installLocationPolicy(pkgLite, flags);
-                    if (!onSd && !onInt) {
+                    if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
+                        ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
+                    } else if (!onSd && !onInt) {
                         // Override install location with flags
                         if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
                             // Set the flag to install on external media.
@@ -5907,20 +6394,31 @@
             mArgs = args;
 
             if (ret == PackageManager.INSTALL_SUCCEEDED) {
+                 /*
+                 * ADB installs appear as UserHandle.USER_ALL, and can only be performed by
+                 * UserHandle.USER_OWNER, so use the package verifier for UserHandle.USER_OWNER.
+                 */
+                int userIdentifier = getUser().getIdentifier();
+                if (userIdentifier == UserHandle.USER_ALL
+                        && ((flags & PackageManager.INSTALL_FROM_ADB) != 0)) {
+                    userIdentifier = UserHandle.USER_OWNER;
+                }
+
                 /*
                  * Determine if we have any installed package verifiers. If we
                  * do, then we'll defer to them to verify the packages.
                  */
                 final int requiredUid = mRequiredVerifierPackage == null ? -1
-                        : getPackageUid(mRequiredVerifierPackage, 0);
-                if (requiredUid != -1 && isVerificationEnabled()) {
+                        : getPackageUid(mRequiredVerifierPackage, userIdentifier);
+                if (requiredUid != -1 && isVerificationEnabled(flags)) {
                     final Intent verification = new Intent(
                             Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
                     verification.setDataAndType(getPackageUri(), PACKAGE_MIME_TYPE);
                     verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
 
-                    final List<ResolveInfo> receivers = queryIntentReceivers(verification, null,
-                            PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
+                    final List<ResolveInfo> receivers = queryIntentReceivers(verification,
+                            PACKAGE_MIME_TYPE, PackageManager.GET_DISABLED_COMPONENTS,
+                            0 /* TODO: Which userId? */);
 
                     if (DEBUG_VERIFY) {
                         Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
@@ -5937,9 +6435,33 @@
 
                     verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, flags);
 
-                    if (verificationURI != null) {
-                        verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
-                                verificationURI);
+                    verification.putExtra(PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME,
+                            pkgLite.packageName);
+
+                    verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE,
+                            pkgLite.versionCode);
+
+                    if (verificationParams != null) {
+                        if (verificationParams.getVerificationURI() != null) {
+                           verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
+                                 verificationParams.getVerificationURI());
+                        }
+                        if (verificationParams.getOriginatingURI() != null) {
+                            verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
+                                  verificationParams.getOriginatingURI());
+                        }
+                        if (verificationParams.getReferrer() != null) {
+                            verification.putExtra(Intent.EXTRA_REFERRER,
+                                  verificationParams.getReferrer());
+                        }
+                        if (verificationParams.getOriginatingUid() >= 0) {
+                            verification.putExtra(Intent.EXTRA_ORIGINATING_UID,
+                                  verificationParams.getOriginatingUid());
+                        }
+                        if (verificationParams.getInstallerUid() >= 0) {
+                            verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
+                                  verificationParams.getInstallerUid());
+                        }
                     }
 
                     final PackageVerificationState verificationState = new PackageVerificationState(
@@ -5966,7 +6488,7 @@
                                 final Intent sufficientIntent = new Intent(verification);
                                 sufficientIntent.setComponent(verifierComponent);
 
-                                mContext.sendBroadcast(sufficientIntent);
+                                mContext.sendBroadcastAsUser(sufficientIntent, getUser());
                             }
                         }
                     }
@@ -5981,7 +6503,7 @@
                          * target BroadcastReceivers have run.
                          */
                         verification.setComponent(requiredVerifierComponent);
-                        mContext.sendOrderedBroadcast(verification,
+                        mContext.sendOrderedBroadcastAsUser(verification, getUser(),
                                 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
                                 new BroadcastReceiver() {
                                     @Override
@@ -6018,12 +6540,12 @@
             // will succeed.
             if (mArgs != null) {
                 processPendingInstall(mArgs, mRet);
-            }
 
-            if (mTempPackage != null) {
-                if (!mTempPackage.delete()) {
-                    Slog.w(TAG, "Couldn't delete temporary file: "
-                            + mTempPackage.getAbsolutePath());
+                if (mTempPackage != null) {
+                    if (!mTempPackage.delete()) {
+                        Slog.w(TAG, "Couldn't delete temporary file: " +
+                                mTempPackage.getAbsolutePath());
+                    }
                 }
             }
         }
@@ -6064,7 +6586,8 @@
         int mRet;
 
         MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
-                String packageName, String dataDir, int uid) {
+                String packageName, String dataDir, int uid, UserHandle user) {
+            super(user);
             this.srcArgs = srcArgs;
             this.observer = observer;
             this.flags = flags;
@@ -6217,14 +6740,17 @@
         final Uri packageURI;
         final String installerPackageName;
         final ManifestDigest manifestDigest;
+        final UserHandle user;
 
         InstallArgs(Uri packageURI, IPackageInstallObserver observer, int flags,
-                String installerPackageName, ManifestDigest manifestDigest) {
+                String installerPackageName, ManifestDigest manifestDigest,
+                UserHandle user) {
             this.packageURI = packageURI;
             this.flags = flags;
             this.observer = observer;
             this.installerPackageName = installerPackageName;
             this.manifestDigest = manifestDigest;
+            this.user = user;
         }
 
         abstract void createCopyFile();
@@ -6264,6 +6790,10 @@
         protected boolean isFwdLocked() {
             return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
         }
+
+        UserHandle getUser() {
+            return user;
+        }
     }
 
     class FileInstallArgs extends InstallArgs {
@@ -6275,11 +6805,12 @@
 
         FileInstallArgs(InstallParams params) {
             super(params.getPackageUri(), params.observer, params.flags,
-                    params.installerPackageName, params.manifestDigest);
+                    params.installerPackageName, params.getManifestDigest(),
+                    params.getUser());
         }
 
         FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
-            super(null, null, 0, null, null);
+            super(null, null, 0, null, null, null);
             File codeFile = new File(fullCodePath);
             installDir = codeFile.getParentFile();
             codeFileName = fullCodePath;
@@ -6288,12 +6819,12 @@
         }
 
         FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
-            super(packageURI, null, 0, null, null);
+            super(packageURI, null, 0, null, null, null);
             installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
             String apkName = getNextCodePath(null, pkgName, ".apk");
             codeFileName = new File(installDir, apkName + ".apk").getPath();
             resourceFileName = getResourcePathFromCodePath();
-            libraryPath = new File(dataDir, LIB_DIR_NAME).getPath();
+            libraryPath = new File(mAppLibInstallDir, pkgName).getPath();
         }
 
         boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
@@ -6330,6 +6861,7 @@
             installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
             codeFileName = createTempPackageFile(installDir).getPath();
             resourceFileName = getResourcePathFromCodePath();
+            libraryPath = getLibraryPathFromCodePath();
             created = true;
         }
 
@@ -6384,6 +6916,23 @@
                     return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                 }
             }
+
+            final File nativeLibraryFile = new File(getNativeLibraryPath());
+            Slog.i(TAG, "Copying native libraries to " + nativeLibraryFile.getPath());
+            if (nativeLibraryFile.exists()) {
+                NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
+                nativeLibraryFile.delete();
+            }
+            try {
+                int copyRet = copyNativeLibrariesForInternalApp(codeFile, nativeLibraryFile);
+                if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
+                    return copyRet;
+                }
+            } catch (IOException e) {
+                Slog.e(TAG, "Copying native libraries failed", e);
+                ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+            }
+
             return ret;
         }
 
@@ -6401,6 +6950,7 @@
             } else {
                 final File oldCodeFile = new File(getCodePath());
                 final File oldResourceFile = new File(getResourcePath());
+                final File oldLibraryFile = new File(getNativeLibraryPath());
 
                 // Rename APK file based on packageName
                 final String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
@@ -6415,7 +6965,20 @@
                 if (isFwdLocked() && !oldResourceFile.renameTo(newResFile)) {
                     return false;
                 }
-                resourceFileName = getResourcePathFromCodePath();
+                resourceFileName = newResFile.getPath();
+
+                // Rename library path
+                final File newLibraryFile = new File(getLibraryPathFromCodePath());
+                if (newLibraryFile.exists()) {
+                    NativeLibraryHelper.removeNativeBinariesFromDirLI(newLibraryFile);
+                    newLibraryFile.delete();
+                }
+                if (!oldLibraryFile.renameTo(newLibraryFile)) {
+                    Slog.e(TAG, "Cannot rename native library directory "
+                            + oldLibraryFile.getPath() + " to " + newLibraryFile.getPath());
+                    return false;
+                }
+                libraryPath = newLibraryFile.getPath();
 
                 // Attempt to set permissions
                 if (!setPermissions()) {
@@ -6466,8 +7029,15 @@
             }
         }
 
+        private String getLibraryPathFromCodePath() {
+            return new File(mAppLibInstallDir, getApkName(getCodePath())).getPath();
+        }
+
         @Override
         String getNativeLibraryPath() {
+            if (libraryPath == null) {
+                libraryPath = getLibraryPathFromCodePath();
+            }
             return libraryPath;
         }
 
@@ -6493,6 +7063,15 @@
                     publicSourceFile.delete();
                 }
             }
+
+            if (libraryPath != null) {
+                File nativeLibraryFile = new File(libraryPath);
+                NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
+                if (!nativeLibraryFile.delete()) {
+                    Slog.w(TAG, "Couldn't delete native library directory " + libraryPath);
+                }
+            }
+
             return ret;
         }
 
@@ -6562,13 +7141,15 @@
 
         AsecInstallArgs(InstallParams params) {
             super(params.getPackageUri(), params.observer, params.flags,
-                    params.installerPackageName, params.manifestDigest);
+                    params.installerPackageName, params.getManifestDigest(),
+                    params.getUser());
         }
 
         AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
                 boolean isExternal, boolean isForwardLocked) {
             super(null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
-                    | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), null, null);
+                    | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
+                    null, null, null);
             // Extract cid from fullCodePath
             int eidx = fullCodePath.lastIndexOf("/");
             String subStr1 = fullCodePath.substring(0, eidx);
@@ -6579,14 +7160,16 @@
 
         AsecInstallArgs(String cid, boolean isForwardLocked) {
             super(null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0)
-                    | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), null, null);
+                    | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
+                    null, null, null);
             this.cid = cid;
             setCachePath(PackageHelper.getSdDir(cid));
         }
 
         AsecInstallArgs(Uri packageURI, String cid, boolean isExternal, boolean isForwardLocked) {
             super(packageURI, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
-                    | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), null, null);
+                    | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
+                    null, null, null);
             this.cid = cid;
         }
 
@@ -6735,7 +7318,7 @@
                 final int groupOwner;
                 final String protectedFile;
                 if (isFwdLocked()) {
-                    groupOwner = uid;
+                    groupOwner = UserHandle.getSharedAppGid(uid);
                     protectedFile = RES_FILE_NAME;
                 } else {
                     groupOwner = -1;
@@ -6817,7 +7400,8 @@
         int doPostCopy(int uid) {
             if (isFwdLocked()) {
                 if (uid < Process.FIRST_APPLICATION_UID
-                        || !PackageHelper.fixSdPermissions(cid, uid, RES_FILE_NAME)) {
+                        || !PackageHelper.fixSdPermissions(cid, UserHandle.getSharedAppGid(uid),
+                                RES_FILE_NAME)) {
                     Slog.e(TAG, "Failed to finalize " + cid);
                     PackageHelper.destroySdDir(cid);
                     return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
@@ -6910,6 +7494,10 @@
     class PackageInstalledInfo {
         String name;
         int uid;
+        // The set of users that originally had this package installed.
+        int[] origUsers;
+        // The set of users that now have this package installed.
+        int[] newUsers;
         PackageParser.Package pkg;
         int returnCode;
         PackageRemovedInfo removedInfo;
@@ -6919,14 +7507,12 @@
      * Install a non-existing package.
      */
     private void installNewPackageLI(PackageParser.Package pkg,
-            int parseFlags,
-            int scanMode,
+            int parseFlags, int scanMode, UserHandle user,
             String installerPackageName, PackageInstalledInfo res) {
         // Remember this for later, in case we need to rollback this install
         String pkgName = pkg.packageName;
 
         boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists();
-        res.name = pkgName;
         synchronized(mPackages) {
             if (mSettings.mRenamedPackages.containsKey(pkgName)) {
                 // A package with the same name is already installed, though
@@ -6949,7 +7535,7 @@
         }
         mLastScanError = PackageManager.INSTALL_SUCCEEDED;
         PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
-                System.currentTimeMillis());
+                System.currentTimeMillis(), user);
         if (newPackage == null) {
             Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
             if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -6966,17 +7552,15 @@
                 // delete the package data and cache directories that it created in
                 // scanPackageLocked, unless those directories existed before we even tried to
                 // install.
-                deletePackageLI(
-                        pkgName, false,
-                        dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
+                deletePackageLI(pkgName, UserHandle.ALL, false,
+                        dataDirExists ? PackageManager.DELETE_KEEP_DATA : 0,
                                 res.removedInfo, true);
             }
         }
     }
 
     private void replacePackageLI(PackageParser.Package pkg,
-            int parseFlags,
-            int scanMode,
+            int parseFlags, int scanMode, UserHandle user,
             String installerPackageName, PackageInstalledInfo res) {
 
         PackageParser.Package oldPackage;
@@ -6993,15 +7577,16 @@
         }
         boolean sysPkg = (isSystemApp(oldPackage));
         if (sysPkg) {
-            replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
+            replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
+                    user, installerPackageName, res);
         } else {
-            replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
+            replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
+                    user, installerPackageName, res);
         }
     }
 
     private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
-            PackageParser.Package pkg,
-            int parseFlags, int scanMode,
+            PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
             String installerPackageName, PackageInstalledInfo res) {
         PackageParser.Package newPackage = null;
         String pkgName = deletedPackage.packageName;
@@ -7016,7 +7601,7 @@
         }
 
         // First delete the existing package while retaining the data directory
-        if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
+        if (!deletePackageLI(pkgName, null, true, PackageManager.DELETE_KEEP_DATA,
                 res.removedInfo, true)) {
             // If the existing package wasn't successfully deleted
             res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
@@ -7025,7 +7610,7 @@
             // Successfully deleted the old package. Now proceed with re-installation
             mLastScanError = PackageManager.INSTALL_SUCCEEDED;
             newPackage = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_TIME,
-                    System.currentTimeMillis());
+                    System.currentTimeMillis(), user);
             if (newPackage == null) {
                 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
                 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -7046,8 +7631,8 @@
             // install.
             if(updatedSettings) {
                 deletePackageLI(
-                        pkgName, true,
-                        PackageManager.DONT_DELETE_DATA,
+                        pkgName, null, true,
+                        PackageManager.DELETE_KEEP_DATA,
                                 res.removedInfo, true);
             }
             // Since we failed to install the new package we need to restore the old
@@ -7062,7 +7647,7 @@
                 int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE
                         | SCAN_UPDATE_TIME;
                 if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode,
-                        origUpdateTime) == null) {
+                        origUpdateTime, null) == null) {
                     Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
                     return;
                 }
@@ -7080,8 +7665,7 @@
     }
 
     private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
-            PackageParser.Package pkg,
-            int parseFlags, int scanMode,
+            PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
             String installerPackageName, PackageInstalledInfo res) {
         PackageParser.Package newPackage = null;
         boolean updatedSettings = false;
@@ -7111,7 +7695,7 @@
         res.removedInfo.uid = oldPkg.applicationInfo.uid;
         res.removedInfo.removedPackage = packageName;
         // Remove existing system package
-        removePackageLI(oldPkg, true);
+        removePackageLI(oldPkgSetting, true);
         // writer
         synchronized (mPackages) {
             if (!mSettings.disableSystemPackageLPw(packageName) && deletedPackage != null) {
@@ -7130,7 +7714,7 @@
         // Successfully disabled the old package. Now proceed with re-installation
         mLastScanError = PackageManager.INSTALL_SUCCEEDED;
         pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
-        newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0);
+        newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0, user);
         if (newPackage == null) {
             Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
             if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -7150,10 +7734,10 @@
             // Re installation failed. Restore old information
             // Remove new pkg information
             if (newPackage != null) {
-                removePackageLI(newPackage, true);
+                removeInstalledPackageLI(newPackage, true);
             }
             // Add back the old system package
-            scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0);
+            scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0, user);
             // Restore the old system information in Settings
             synchronized(mPackages) {
                 if (updatedSettings) {
@@ -7309,6 +7893,7 @@
                     systemApp = (ps.pkg.applicationInfo.flags &
                             ApplicationInfo.FLAG_SYSTEM) != 0;
                 }
+                res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
             }
         }
 
@@ -7327,11 +7912,17 @@
         setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
         pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
         if (replace) {
-            replacePackageLI(pkg, parseFlags, scanMode,
+            replacePackageLI(pkg, parseFlags, scanMode, args.user,
                     installerPackageName, res);
         } else {
-            installNewPackageLI(pkg, parseFlags, scanMode,
-                    installerPackageName,res);
+            installNewPackageLI(pkg, parseFlags, scanMode, args.user,
+                    installerPackageName, res);
+        }
+        synchronized (mPackages) {
+            final PackageSetting ps = mSettings.mPackages.get(pkgName);
+            if (ps != null) {
+                res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
+            }
         }
     }
 
@@ -7380,17 +7971,23 @@
     }
 
     private void deleteTempPackageFiles() {
-        FilenameFilter filter = new FilenameFilter() {
+        final FilenameFilter filter = new FilenameFilter() {
             public boolean accept(File dir, String name) {
                 return name.startsWith("vmdl") && name.endsWith(".tmp");
             }
         };
-        String tmpFilesList[] = mAppInstallDir.list(filter);
-        if(tmpFilesList == null) {
+        deleteTempPackageFilesInDirectory(mAppInstallDir, filter);
+        deleteTempPackageFilesInDirectory(mDrmAppPrivateInstallDir, filter);
+    }
+
+    private static final void deleteTempPackageFilesInDirectory(File directory,
+            FilenameFilter filter) {
+        final String[] tmpFilesList = directory.list(filter);
+        if (tmpFilesList == null) {
             return;
         }
-        for(int i = 0; i < tmpFilesList.length; i++) {
-            File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
+        for (int i = 0; i < tmpFilesList.length; i++) {
+            final File tmpFile = new File(directory, tmpFilesList[i]);
             tmpFile.delete();
         }
     }
@@ -7423,10 +8020,11 @@
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.DELETE_PACKAGES, null);
         // Queue up an async operation since the package deletion may take a little while.
+        final int uid = Binder.getCallingUid();
         mHandler.post(new Runnable() {
             public void run() {
                 mHandler.removeCallbacks(this);
-                final int returnCode = deletePackageX(packageName, true, true, flags);
+                final int returnCode = deletePackageX(packageName, uid, flags);
                 if (observer != null) {
                     try {
                         observer.packageDeleted(packageName, returnCode);
@@ -7452,43 +8050,50 @@
      *  persisting settings for later use
      *  sending a broadcast if necessary
      */
-    private int deletePackageX(String packageName, boolean sendBroadCast,
-                                   boolean deleteCodeAndResources, int flags) {
+    private int deletePackageX(String packageName, int uid, int flags) {
         final PackageRemovedInfo info = new PackageRemovedInfo();
         final boolean res;
 
         IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
                 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
         try {
-            if (dpm != null && dpm.packageHasActiveAdmins(packageName)) {
+            if (dpm != null && dpm.packageHasActiveAdmins(packageName, UserHandle.getUserId(uid))) {
                 Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
                 return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
             }
         } catch (RemoteException e) {
         }
-        
+
+        boolean removedForAllUsers = false;
+        boolean systemUpdate = false;
         synchronized (mInstallLock) {
-            res = deletePackageLI(packageName, deleteCodeAndResources,
-                    flags | REMOVE_CHATTY, info, true);
+            res = deletePackageLI(packageName,
+                    (flags & PackageManager.DELETE_ALL_USERS) != 0
+                            ? UserHandle.ALL : new UserHandle(UserHandle.getUserId(uid)),
+                    true, flags | REMOVE_CHATTY, info, true);
+            systemUpdate = info.isRemovedPackageSystemUpdate;
+            if (res && !systemUpdate && mPackages.get(packageName) == null) {
+                removedForAllUsers = true;
+            }
         }
 
-        if (res && sendBroadCast) {
-            boolean systemUpdate = info.isRemovedPackageSystemUpdate;
-            info.sendBroadcast(deleteCodeAndResources, systemUpdate);
+        if (res) {
+            info.sendBroadcast(true, systemUpdate, removedForAllUsers);
 
-            // If the removed package was a system update, the old system packaged
+            // If the removed package was a system update, the old system package
             // was re-enabled; we need to broadcast this information
             if (systemUpdate) {
                 Bundle extras = new Bundle(1);
-                extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
+                extras.putInt(Intent.EXTRA_UID, info.removedAppId >= 0
+                        ? info.removedAppId : info.uid);
                 extras.putBoolean(Intent.EXTRA_REPLACING, true);
 
                 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
-                        extras, null, null, UserId.USER_ALL);
+                        extras, null, null, null);
                 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
-                        extras, null, null, UserId.USER_ALL);
+                        extras, null, null, null);
                 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
-                        null, packageName, null, UserId.USER_ALL);
+                        null, packageName, null, null);
             }
         }
         // Force a gc here.
@@ -7497,7 +8102,7 @@
         // other processes clean up before deleting resources.
         if (info.args != null) {
             synchronized (mInstallLock) {
-                info.args.doPostDeleteLI(deleteCodeAndResources);
+                info.args.doPostDeleteLI(true);
             }
         }
 
@@ -7507,29 +8112,31 @@
     static class PackageRemovedInfo {
         String removedPackage;
         int uid = -1;
-        int removedUid = -1;
+        int removedAppId = -1;
+        int[] removedUsers = null;
         boolean isRemovedPackageSystemUpdate = false;
         // Clean up resources deleted packages.
         InstallArgs args = null;
 
-        void sendBroadcast(boolean fullRemove, boolean replacing) {
+        void sendBroadcast(boolean fullRemove, boolean replacing, boolean removedForAllUsers) {
             Bundle extras = new Bundle(1);
-            extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
+            extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
             extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
             if (replacing) {
                 extras.putBoolean(Intent.EXTRA_REPLACING, true);
             }
+            extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, removedForAllUsers);
             if (removedPackage != null) {
                 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
-                        extras, null, null, UserId.USER_ALL);
+                        extras, null, null, removedUsers);
                 if (fullRemove && !replacing) {
                     sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, removedPackage,
-                            extras, null, null, UserId.USER_ALL);
+                            extras, null, null, removedUsers);
                 }
             }
-            if (removedUid >= 0) {
+            if (removedAppId >= 0) {
                 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null, null,
-                        UserId.getUserId(removedUid));
+                        removedUsers);
             }
         }
     }
@@ -7540,37 +8147,32 @@
      * make sure this flag is set for partially installed apps. If not its meaningless to
      * delete a partially installed application.
      */
-    private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
+    private void removePackageDataLI(PackageSetting ps, PackageRemovedInfo outInfo,
             int flags, boolean writeSettings) {
-        String packageName = p.packageName;
-        if (outInfo != null) {
-            outInfo.removedPackage = packageName;
-        }
-        removePackageLI(p, (flags&REMOVE_CHATTY) != 0);
+        String packageName = ps.name;
+        removePackageLI(ps, (flags&REMOVE_CHATTY) != 0);
         // Retrieve object to delete permissions for shared user later on
         final PackageSetting deletedPs;
         // reader
         synchronized (mPackages) {
             deletedPs = mSettings.mPackages.get(packageName);
-        }
-        if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
-            int retCode = mInstaller.remove(packageName, 0);
-            if (retCode < 0) {
-                Slog.w(TAG, "Couldn't remove app data or cache directory for package: "
-                           + packageName + ", retcode=" + retCode);
-                // we don't consider this to be a failure of the core package deletion
-            } else {
-                // TODO: Kill the processes first
-                sUserManager.removePackageForAllUsers(packageName);
+            if (outInfo != null) {
+                outInfo.removedPackage = packageName;
+                outInfo.removedUsers = deletedPs != null
+                        ? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true)
+                        : null;
             }
-            schedulePackageCleaning(packageName);
+        }
+        if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
+            removeDataDirsLI(packageName);
+            schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);
         }
         // writer
         synchronized (mPackages) {
             if (deletedPs != null) {
-                if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
+                if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
                     if (outInfo != null) {
-                        outInfo.removedUid = mSettings.removePackageLPw(packageName);
+                        outInfo.removedAppId = mSettings.removePackageLPw(packageName);
                     }
                     if (deletedPs != null) {
                         updatePermissionsLPw(deletedPs.name, null, 0);
@@ -7579,7 +8181,7 @@
                             mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids);
                         }
                     }
-                    clearPackagePreferredActivitiesLPw(deletedPs.name);
+                    clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
                 }
             }
             // can downgrade to reader
@@ -7593,38 +8195,32 @@
     /*
      * Tries to delete system package.
      */
-    private boolean deleteSystemPackageLI(PackageParser.Package p,
+    private boolean deleteSystemPackageLI(PackageSetting newPs,
             int flags, PackageRemovedInfo outInfo, boolean writeSettings) {
-        ApplicationInfo applicationInfo = p.applicationInfo;
-        //applicable for non-partially installed applications only
-        if (applicationInfo == null) {
-            Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
-            return false;
-        }
-        PackageSetting ps = null;
+        PackageSetting disabledPs = null;
         // Confirm if the system package has been updated
         // An updated system app can be deleted. This will also have to restore
         // the system pkg from system partition
         // reader
         synchronized (mPackages) {
-            ps = mSettings.getDisabledSystemPkgLPr(p.packageName);
+            disabledPs = mSettings.getDisabledSystemPkgLPr(newPs.name);
         }
-        if (ps == null) {
-            Slog.w(TAG, "Attempt to delete unknown system package "+ p.packageName);
+        if (disabledPs == null) {
+            Slog.w(TAG, "Attempt to delete unknown system package "+ newPs.name);
             return false;
         } else {
             Log.i(TAG, "Deleting system pkg from data partition");
         }
         // Delete the updated package
         outInfo.isRemovedPackageSystemUpdate = true;
-        if (ps.versionCode < p.mVersionCode) {
+        if (disabledPs.versionCode < newPs.versionCode) {
             // Delete data for downgrades
-            flags &= ~PackageManager.DONT_DELETE_DATA;
+            flags &= ~PackageManager.DELETE_KEEP_DATA;
         } else {
             // Preserve data by setting flag
-            flags |= PackageManager.DONT_DELETE_DATA;
+            flags |= PackageManager.DELETE_KEEP_DATA;
         }
-        boolean ret = deleteInstalledPackageLI(p, true, flags, outInfo,
+        boolean ret = deleteInstalledPackageLI(newPs, true, flags, outInfo,
                 writeSettings);
         if (!ret) {
             return false;
@@ -7632,17 +8228,18 @@
         // writer
         synchronized (mPackages) {
             // Reinstate the old system package
-            mSettings.enableSystemPackageLPw(p.packageName);
+            mSettings.enableSystemPackageLPw(newPs.name);
             // Remove any native libraries from the upgraded package.
-            NativeLibraryHelper.removeNativeBinariesLI(p.applicationInfo.nativeLibraryDir);
+            NativeLibraryHelper.removeNativeBinariesLI(newPs.nativeLibraryPathString);
         }
         // Install the system package
-        PackageParser.Package newPkg = scanPackageLI(ps.codePath,
+        PackageParser.Package newPkg = scanPackageLI(disabledPs.codePath,
                 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
-                SCAN_MONITOR | SCAN_NO_PATHS, 0);
+                SCAN_MONITOR | SCAN_NO_PATHS, 0, null);
 
         if (newPkg == null) {
-            Slog.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
+            Slog.w(TAG, "Failed to restore system package:" + newPs.name
+                    + " with error:" + mLastScanError);
             return false;
         }
         // writer
@@ -7657,28 +8254,20 @@
         return true;
     }
 
-    private boolean deleteInstalledPackageLI(PackageParser.Package p,
+    private boolean deleteInstalledPackageLI(PackageSetting ps,
             boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
             boolean writeSettings) {
-        ApplicationInfo applicationInfo = p.applicationInfo;
-        if (applicationInfo == null) {
-            Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
-            return false;
-        }
         if (outInfo != null) {
-            outInfo.uid = applicationInfo.uid;
+            outInfo.uid = ps.appId;
         }
 
         // Delete package data from internal structures and also remove data if flag is set
-        removePackageDataLI(p, outInfo, flags, writeSettings);
+        removePackageDataLI(ps, outInfo, flags, writeSettings);
 
         // Delete application code and resources
-        if (deleteCodeAndResources) {
-            // TODO can pick up from PackageSettings as well
-            int installFlags = isExternal(p) ? PackageManager.INSTALL_EXTERNAL : 0;
-            installFlags |= isForwardLocked(p) ? PackageManager.INSTALL_FORWARD_LOCK : 0;
-            outInfo.args = createInstallArgs(installFlags, applicationInfo.sourceDir,
-                    applicationInfo.publicSourceDir, applicationInfo.nativeLibraryDir);
+        if (deleteCodeAndResources && (outInfo != null)) {
+            outInfo.args = createInstallArgs(packageFlagsToInstallFlags(ps), ps.codePathString,
+                    ps.resourcePathString, ps.nativeLibraryPathString);
         }
         return true;
     }
@@ -7686,54 +8275,78 @@
     /*
      * This method handles package deletion in general
      */
-    private boolean deletePackageLI(String packageName,
+    private boolean deletePackageLI(String packageName, UserHandle user,
             boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
             boolean writeSettings) {
         if (packageName == null) {
             Slog.w(TAG, "Attempt to delete null packageName.");
             return false;
         }
-        PackageParser.Package p;
+        PackageSetting ps;
         boolean dataOnly = false;
+        int removeUser = -1;
+        int appId = -1;
         synchronized (mPackages) {
-            p = mPackages.get(packageName);
-            if (p == null) {
-                //this retrieves partially installed apps
-                dataOnly = true;
-                PackageSetting ps = mSettings.mPackages.get(packageName);
-                if (ps == null) {
-                    Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
-                    return false;
+            ps = mSettings.mPackages.get(packageName);
+            if (ps == null) {
+                Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
+                return false;
+            }
+            if (!isSystemApp(ps) && user != null
+                    && user.getIdentifier() != UserHandle.USER_ALL) {
+                // The caller is asking that the package only be deleted for a single
+                // user.  To do this, we just mark its uninstalled state and delete
+                // its data.
+                ps.setUserState(user.getIdentifier(),
+                        COMPONENT_ENABLED_STATE_DEFAULT,
+                        false, //installed
+                        true,  //stopped
+                        true,  //notLaunched
+                        null, null);
+                if (ps.isAnyInstalled(sUserManager.getUserIds())) {
+                    // Other user still have this package installed, so all
+                    // we need to do is clear this user's data and save that
+                    // it is uninstalled.
+                    removeUser = user.getIdentifier();
+                    appId = ps.appId;
+                    mSettings.writePackageRestrictionsLPr(removeUser);
+                } else {
+                    // We need to set it back to 'installed' so the uninstall
+                    // broadcasts will be sent correctly.
+                    ps.setInstalled(true, user.getIdentifier());
                 }
-                p = ps.pkg;
             }
         }
-        if (p == null) {
-            Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
-            return false;
+
+        if (removeUser >= 0) {
+            // From above, we determined that we are deleting this only
+            // for a single user.  Continue the work here.
+            if (outInfo != null) {
+                outInfo.removedPackage = packageName;
+                outInfo.removedAppId = appId;
+                outInfo.removedUsers = new int[] {removeUser};
+            }
+            mInstaller.clearUserData(packageName, removeUser);
+            schedulePackageCleaning(packageName, removeUser, false);
+            return true;
         }
 
         if (dataOnly) {
             // Delete application data first
-            removePackageDataLI(p, outInfo, flags, writeSettings);
+            removePackageDataLI(ps, outInfo, flags, writeSettings);
             return true;
         }
-        // At this point the package should have ApplicationInfo associated with it
-        if (p.applicationInfo == null) {
-            Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
-            return false;
-        }
         boolean ret = false;
-        if (isSystemApp(p)) {
-            Log.i(TAG, "Removing system package:"+p.packageName);
+        if (isSystemApp(ps)) {
+            Log.i(TAG, "Removing system package:" + ps.name);
             // When an updated system application is deleted we delete the existing resources as well and
             // fall back to existing code in system partition
-            ret = deleteSystemPackageLI(p, flags, outInfo, writeSettings);
+            ret = deleteSystemPackageLI(ps, flags, outInfo, writeSettings);
         } else {
-            Log.i(TAG, "Removing non-system package:"+p.packageName);
+            Log.i(TAG, "Removing non-system package:" + ps.name);
             // Kill application pre-emptively especially for apps on sd.
-            killApplication(packageName, p.applicationInfo.uid);
-            ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo,
+            killApplication(packageName, ps.appId);
+            ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags, outInfo,
                     writeSettings);
         }
         return ret;
@@ -7755,7 +8368,7 @@
         }
     }
 
-    private void clearExternalStorageDataSync(String packageName, boolean allData) {
+    private void clearExternalStorageDataSync(String packageName, int userId, boolean allData) {
         final boolean mounted;
         if (Environment.isExternalStorageEmulated()) {
             mounted = true;
@@ -7771,40 +8384,51 @@
         }
 
         final Intent containerIntent = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
-        ClearStorageConnection conn = new ClearStorageConnection();
-        if (mContext.bindService(containerIntent, conn, Context.BIND_AUTO_CREATE)) {
+        int[] users;
+        if (userId == UserHandle.USER_ALL) {
+            users = sUserManager.getUserIds();
+        } else {
+            users = new int[] { userId };
+        }
+        final ClearStorageConnection conn = new ClearStorageConnection();
+        if (mContext.bindService(
+                containerIntent, conn, Context.BIND_AUTO_CREATE, UserHandle.USER_OWNER)) {
             try {
-                long timeout = SystemClock.uptimeMillis() + 5000;
-                synchronized (conn) {
-                    long now = SystemClock.uptimeMillis();
-                    while (conn.mContainerService == null && now < timeout) {
-                        try {
-                            conn.wait(timeout - now);
-                        } catch (InterruptedException e) {
+                for (int curUser : users) {
+                    long timeout = SystemClock.uptimeMillis() + 5000;
+                    synchronized (conn) {
+                        long now = SystemClock.uptimeMillis();
+                        while (conn.mContainerService == null && now < timeout) {
+                            try {
+                                conn.wait(timeout - now);
+                            } catch (InterruptedException e) {
+                            }
                         }
                     }
-                }
-                if (conn.mContainerService == null) {
-                    return;
-                }
-                final File externalCacheDir = Environment
-                        .getExternalStorageAppCacheDirectory(packageName);
-                try {
-                    conn.mContainerService.clearDirectory(externalCacheDir.toString());
-                } catch (RemoteException e) {
-                }
-                if (allData) {
-                    final File externalDataDir = Environment
-                            .getExternalStorageAppDataDirectory(packageName);
+                    if (conn.mContainerService == null) {
+                        return;
+                    }
+
+                    final UserEnvironment userEnv = new UserEnvironment(curUser);
+                    final File externalCacheDir = userEnv
+                            .getExternalStorageAppCacheDirectory(packageName);
                     try {
-                        conn.mContainerService.clearDirectory(externalDataDir.toString());
+                        conn.mContainerService.clearDirectory(externalCacheDir.toString());
                     } catch (RemoteException e) {
                     }
-                    final File externalMediaDir = Environment
-                            .getExternalStorageAppMediaDirectory(packageName);
-                    try {
-                        conn.mContainerService.clearDirectory(externalMediaDir.toString());
-                    } catch (RemoteException e) {
+                    if (allData) {
+                        final File externalDataDir = userEnv
+                                .getExternalStorageAppDataDirectory(packageName);
+                        try {
+                            conn.mContainerService.clearDirectory(externalDataDir.toString());
+                        } catch (RemoteException e) {
+                        }
+                        final File externalMediaDir = userEnv
+                                .getExternalStorageAppMediaDirectory(packageName);
+                        try {
+                            conn.mContainerService.clearDirectory(externalMediaDir.toString());
+                        } catch (RemoteException e) {
+                        }
                     }
                 }
             } finally {
@@ -7818,7 +8442,7 @@
             final IPackageDataObserver observer, final int userId) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
-        checkValidCaller(Binder.getCallingUid(), userId);
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "clear application data");
         // Queue up an async operation since the package deletion may take a little while.
         mHandler.post(new Runnable() {
             public void run() {
@@ -7827,7 +8451,7 @@
                 synchronized (mInstallLock) {
                     succeeded = clearApplicationUserDataLI(packageName, userId);
                 }
-                clearExternalStorageDataSync(packageName, true);
+                clearExternalStorageDataSync(packageName, userId, true);
                 if (succeeded) {
                     // invoke DeviceStorageMonitor's update method to clear any notifications
                     DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
@@ -7893,7 +8517,7 @@
         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();
+        final int userId = UserHandle.getCallingUserId();
         mHandler.post(new Runnable() {
             public void run() {
                 mHandler.removeCallbacks(this);
@@ -7901,7 +8525,7 @@
                 synchronized (mInstallLock) {
                     succeded = deleteApplicationCacheFilesLI(packageName, userId);
                 }
-                clearExternalStorageDataSync(packageName, false);
+                clearExternalStorageDataSync(packageName, userId, false);
                 if(observer != null) {
                     try {
                         observer.onRemoveCompleted(packageName, succeded);
@@ -7931,22 +8555,21 @@
             Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
             return false;
         }
-        // TODO: Pass userId to deleteCacheFiles
-        int retCode = mInstaller.deleteCacheFiles(packageName);
+        int retCode = mInstaller.deleteCacheFiles(packageName, userId);
         if (retCode < 0) {
             Slog.w(TAG, "Couldn't remove cache files for package: "
-                       + packageName);
+                       + packageName + " u" + userId);
             return false;
         }
         return true;
     }
 
-    public void getPackageSizeInfo(final String packageName,
+    public void getPackageSizeInfo(final String packageName, int userHandle,
             final IPackageStatsObserver observer) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.GET_PACKAGE_SIZE, null);
 
-        PackageStats stats = new PackageStats(packageName);
+        PackageStats stats = new PackageStats(packageName, userHandle);
 
         /*
          * Queue up an async operation since the package measurement may take a
@@ -7957,7 +8580,8 @@
         mHandler.sendMessage(msg);
     }
 
-    private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
+    private boolean getPackageSizeInfoLI(String packageName, int userHandle,
+            PackageStats pStats) {
         if (packageName == null) {
             Slog.w(TAG, "Attempt to get size of null packageName.");
             return false;
@@ -7994,7 +8618,7 @@
                 publicSrcDir = applicationInfo.publicSourceDir;
             }
         }
-        int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir,
+        int res = mInstaller.getSizeInfo(packageName, userHandle, p.mPath, publicSrcDir,
                 asecPath, pStats);
         if (res < 0) {
             return false;
@@ -8046,27 +8670,29 @@
     }
     
     public void addPreferredActivity(IntentFilter filter, int match,
-            ComponentName[] set, ComponentName activity) {
+            ComponentName[] set, ComponentName activity, int userId) {
         // writer
+        int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId, true, "add preferred activity");
         synchronized (mPackages) {
             if (mContext.checkCallingOrSelfPermission(
                     android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
                     != PackageManager.PERMISSION_GRANTED) {
-                if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
+                if (getUidTargetSdkVersionLockedLPr(callingUid)
                         < Build.VERSION_CODES.FROYO) {
                     Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
-                            + Binder.getCallingUid());
+                            + callingUid);
                     return;
                 }
                 mContext.enforceCallingOrSelfPermission(
                         android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
             }
-            
-            Slog.i(TAG, "Adding preferred activity " + activity + ":");
+
+            Slog.i(TAG, "Adding preferred activity " + activity + " for user " + userId + " :");
             filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
-            mSettings.mPreferredActivities.addFilter(
+            mSettings.editPreferredActivitiesLPw(userId).addFilter(
                     new PreferredActivity(filter, match, set, activity));
-            scheduleWriteSettingsLocked();            
+            mSettings.writePackageRestrictionsLPr(userId);
         }
     }
 
@@ -8101,29 +8727,33 @@
                 mContext.enforceCallingOrSelfPermission(
                         android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
             }
-            
+
+            final int callingUserId = UserHandle.getCallingUserId();
             ArrayList<PreferredActivity> removed = null;
-            Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
-            String action = filter.getAction(0);
-            String category = filter.getCategory(0);
-            while (it.hasNext()) {
-                PreferredActivity pa = it.next();
-                if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
-                    if (removed == null) {
-                        removed = new ArrayList<PreferredActivity>();
+            PreferredIntentResolver pir = mSettings.mPreferredActivities.get(callingUserId);
+            if (pir != null) {
+                Iterator<PreferredActivity> it = pir.filterIterator();
+                String action = filter.getAction(0);
+                String category = filter.getCategory(0);
+                while (it.hasNext()) {
+                    PreferredActivity pa = it.next();
+                    if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
+                        if (removed == null) {
+                            removed = new ArrayList<PreferredActivity>();
+                        }
+                        removed.add(pa);
+                        Log.i(TAG, "Removing preferred activity " + pa.mPref.mComponent + ":");
+                        filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
                     }
-                    removed.add(pa);
-                    Log.i(TAG, "Removing preferred activity " + pa.mPref.mComponent + ":");
-                    filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
+                }
+                if (removed != null) {
+                    for (int i=0; i<removed.size(); i++) {
+                        PreferredActivity pa = removed.get(i);
+                        pir.removeFilter(pa);
+                    }
                 }
             }
-            if (removed != null) {
-                for (int i=0; i<removed.size(); i++) {
-                    PreferredActivity pa = removed.get(i);
-                    mSettings.mPreferredActivities.removeFilter(pa);
-                }
-            }
-            addPreferredActivity(filter, match, set, activity);
+            addPreferredActivity(filter, match, set, activity, callingUserId);
         }
     }
 
@@ -8147,50 +8777,64 @@
                 }
             }
 
-            if (clearPackagePreferredActivitiesLPw(packageName)) {
+            if (clearPackagePreferredActivitiesLPw(packageName, UserHandle.getCallingUserId())) {
                 scheduleWriteSettingsLocked();            
             }
         }
     }
 
-    boolean clearPackagePreferredActivitiesLPw(String packageName) {
+    /** This method takes a specific user id as well as UserHandle.USER_ALL. */
+    boolean clearPackagePreferredActivitiesLPw(String packageName, int userId) {
         ArrayList<PreferredActivity> removed = null;
-        Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
-        while (it.hasNext()) {
-            PreferredActivity pa = it.next();
-            if (pa.mPref.mComponent.getPackageName().equals(packageName)) {
-                if (removed == null) {
-                    removed = new ArrayList<PreferredActivity>();
+        boolean changed = false;
+        for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
+            final int thisUserId = mSettings.mPreferredActivities.keyAt(i);
+            PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
+            if (userId != UserHandle.USER_ALL && userId != thisUserId) {
+                continue;
+            }
+            Iterator<PreferredActivity> it = pir.filterIterator();
+            while (it.hasNext()) {
+                PreferredActivity pa = it.next();
+                if (pa.mPref.mComponent.getPackageName().equals(packageName)) {
+                    if (removed == null) {
+                        removed = new ArrayList<PreferredActivity>();
+                    }
+                    removed.add(pa);
                 }
-                removed.add(pa);
+            }
+            if (removed != null) {
+                for (int j=0; j<removed.size(); j++) {
+                    PreferredActivity pa = removed.get(j);
+                    pir.removeFilter(pa);
+                }
+                changed = true;
+                mSettings.writePackageRestrictionsLPr(thisUserId);
             }
         }
-        if (removed != null) {
-            for (int i=0; i<removed.size(); i++) {
-                PreferredActivity pa = removed.get(i);
-                mSettings.mPreferredActivities.removeFilter(pa);
-            }
-            return true;
-        }
-        return false;
+        return changed;
     }
 
     public int getPreferredActivities(List<IntentFilter> outFilters,
             List<ComponentName> outActivities, String packageName) {
 
         int num = 0;
+        final int userId = UserHandle.getCallingUserId();
         // reader
         synchronized (mPackages) {
-            final Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
-            while (it.hasNext()) {
-                final PreferredActivity pa = it.next();
-                if (packageName == null
-                        || pa.mPref.mComponent.getPackageName().equals(packageName)) {
-                    if (outFilters != null) {
-                        outFilters.add(new IntentFilter(pa));
-                    }
-                    if (outActivities != null) {
-                        outActivities.add(pa.mPref.mComponent);
+            PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
+            if (pir != null) {
+                final Iterator<PreferredActivity> it = pir.filterIterator();
+                while (it.hasNext()) {
+                    final PreferredActivity pa = it.next();
+                    if (packageName == null
+                            || pa.mPref.mComponent.getPackageName().equals(packageName)) {
+                        if (outFilters != null) {
+                            outFilters.add(new IntentFilter(pa));
+                        }
+                        if (outActivities != null) {
+                            outActivities.add(pa.mPref.mComponent);
+                        }
                     }
                 }
             }
@@ -8227,7 +8871,7 @@
         final int uid = Binder.getCallingUid();
         final int permission = mContext.checkCallingPermission(
                 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
-        checkValidCaller(uid, userId);
+        enforceCrossUserPermission(uid, userId, false, "set enabled");
         final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
         boolean sendNow = false;
         boolean isApp = (className == null);
@@ -8248,7 +8892,7 @@
                         + "/" + className);
             }
             // Allow root and verify that userId is not being specified by a different user
-            if (!allowedByPermission && !UserId.isSameApp(uid, pkgSetting.appId)) {
+            if (!allowedByPermission && !UserHandle.isSameApp(uid, pkgSetting.appId)) {
                 throw new SecurityException(
                         "Permission Denial: attempt to change component state from pid="
                         + Binder.getCallingPid()
@@ -8297,7 +8941,7 @@
                 }
             }
             mSettings.writePackageRestrictionsLPr(userId);
-            packageUid = UserId.getUid(userId, pkgSetting.appId);
+            packageUid = UserHandle.getUid(userId, pkgSetting.appId);
             components = mPendingBroadcasts.get(packageName);
             final boolean newPackage = components == null;
             if (newPackage) {
@@ -8346,7 +8990,7 @@
         extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
         extras.putInt(Intent.EXTRA_UID, packageUid);
         sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED,  packageName, extras, null, null,
-                UserId.getUserId(packageUid));
+                new int[] {UserHandle.getUserId(packageUid)});
     }
 
     public void setPackageStoppedState(String packageName, boolean stopped, int userId) {
@@ -8355,7 +8999,7 @@
         final int permission = mContext.checkCallingOrSelfPermission(
                 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
         final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
-        checkValidCaller(uid, userId);
+        enforceCrossUserPermission(uid, userId, true, "stop package");
         // writer
         synchronized (mPackages) {
             if (mSettings.setPackageStoppedStateLPw(packageName, stopped, allowedByPermission,
@@ -8376,7 +9020,7 @@
     public int getApplicationEnabledSetting(String packageName, int userId) {
         if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
         int uid = Binder.getCallingUid();
-        checkValidCaller(uid, userId);
+        enforceCrossUserPermission(uid, userId, false, "get enabled");
         // reader
         synchronized (mPackages) {
             return mSettings.getApplicationEnabledSettingLPr(packageName, userId);
@@ -8387,7 +9031,7 @@
     public int getComponentEnabledSetting(ComponentName componentName, int userId) {
         if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
         int uid = Binder.getCallingUid();
-        checkValidCaller(uid, userId);
+        enforceCrossUserPermission(uid, userId, false, "get component enabled");
         // reader
         synchronized (mPackages) {
             return mSettings.getComponentEnabledSettingLPr(componentName, userId);
@@ -8406,13 +9050,46 @@
         mSystemReady = true;
 
         // Read the compatibilty setting when the system is ready.
-        boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
+        boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt(
                 mContext.getContentResolver(),
-                android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
+                android.provider.Settings.Global.COMPATIBILITY_MODE, 1) == 1;
         PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
         if (DEBUG_SETTINGS) {
             Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
         }
+
+        synchronized (mPackages) {
+            // Verify that all of the preferred activity components actually
+            // exist.  It is possible for applications to be updated and at
+            // that point remove a previously declared activity component that
+            // had been set as a preferred activity.  We try to clean this up
+            // the next time we encounter that preferred activity, but it is
+            // possible for the user flow to never be able to return to that
+            // situation so here we do a sanity check to make sure we haven't
+            // left any junk around.
+            ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
+            for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
+                PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
+                removed.clear();
+                for (PreferredActivity pa : pir.filterSet()) {
+                    if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
+                        removed.add(pa);
+                    }
+                }
+                if (removed.size() > 0) {
+                    for (int j=0; j<removed.size(); j++) {
+                        PreferredActivity pa = removed.get(i);
+                        RuntimeException here = new RuntimeException("here");
+                        here.fillInStackTrace();
+                        Slog.w(TAG, "Removing dangling preferred activity: "
+                                + pa.mPref.mComponent, here);
+                        pir.removeFilter(pa);
+                    }
+                    mSettings.writePackageRestrictionsLPr(
+                            mSettings.mPreferredActivities.keyAt(i));
+                }
+            }
+        }
     }
 
     public boolean isSafeMode() {
@@ -8653,11 +9330,16 @@
             }
 
             if (dumpState.isDumping(DumpState.DUMP_PREFERRED)) {
-                if (mSettings.mPreferredActivities.dump(pw,
-                        dumpState.getTitlePrinted() ? "\nPreferred Activities:"
-                            : "Preferred Activities:", "  ",
-                        packageName, dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
-                    dumpState.setTitlePrinted(true);
+                for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
+                    PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
+                    int user = mSettings.mPreferredActivities.keyAt(i);
+                    if (pir.dump(pw,
+                            dumpState.getTitlePrinted()
+                                ? "\nPreferred Activities User " + user + ":"
+                                : "Preferred Activities User " + user + ":", "  ",
+                            packageName, dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
+                        dumpState.setTitlePrinted(true);
+                    }
                 }
             }
 
@@ -8671,7 +9353,7 @@
                     serializer.startDocument(null, true);
                     serializer.setFeature(
                             "http://xmlpull.org/v1/doc/features.html#indent-output", true);
-                    mSettings.writePreferredActivitiesLPr(serializer);
+                    mSettings.writePreferredActivitiesLPr(serializer, 0);
                     serializer.endDocument();
                     serializer.flush();
                 } catch (IllegalArgumentException e) {
@@ -8972,7 +9654,7 @@
             }
             String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
                     : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
-            sendPackageBroadcast(action, null, extras, null, finishedReceiver, UserId.USER_ALL);
+            sendPackageBroadcast(action, null, extras, null, finishedReceiver, null);
         }
     }
 
@@ -9017,7 +9699,7 @@
                 doGc = true;
                 synchronized (mInstallLock) {
                     final PackageParser.Package pkg = scanPackageLI(new File(codePath), parseFlags,
-                            0, 0);
+                            0, 0, null);
                     // Scan the package
                     if (pkg != null) {
                         /*
@@ -9126,8 +9808,8 @@
             // Delete package internally
             PackageRemovedInfo outInfo = new PackageRemovedInfo();
             synchronized (mInstallLock) {
-                boolean res = deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
-                        outInfo, false);
+                boolean res = deletePackageLI(pkgName, null, false,
+                        PackageManager.DELETE_KEEP_DATA, outInfo, false);
                 if (res) {
                     pkgList.add(pkgName);
                 } else {
@@ -9151,7 +9833,8 @@
         if (pkgList.size() > 0) {
             sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() {
                 public void performReceive(Intent intent, int resultCode, String data,
-                        Bundle extras, boolean ordered, boolean sticky) throws RemoteException {
+                        Bundle extras, boolean ordered, boolean sticky,
+                        int sendingUser) throws RemoteException {
                     Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
                             reportStatus ? 1 : 0, 1, keys);
                     mHandler.sendMessage(msg);
@@ -9164,9 +9847,12 @@
         }
     }
 
+    /** Binder call */
+    @Override
     public void movePackage(final String packageName, final IPackageMoveObserver observer,
             final int flags) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
+        UserHandle user = new UserHandle(UserHandle.getCallingUserId());
         int returnCode = PackageManager.MOVE_SUCCEEDED;
         int currFlags = 0;
         int newFlags = 0;
@@ -9217,14 +9903,15 @@
              * anyway.
              */
             if (returnCode != PackageManager.MOVE_SUCCEEDED) {
-                processPendingMove(new MoveParams(null, observer, 0, packageName, null, -1),
+                processPendingMove(new MoveParams(null, observer, 0, packageName,
+                        null, -1, user),
                         returnCode);
             } else {
                 Message msg = mHandler.obtainMessage(INIT_COPY);
                 InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
                         pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir);
                 MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
-                        pkg.applicationInfo.dataDir, pkg.applicationInfo.uid);
+                        pkg.applicationInfo.dataDir, pkg.applicationInfo.uid, user);
                 msg.obj = mp;
                 mHandler.sendMessage(msg);
             }
@@ -9288,30 +9975,19 @@
                                     final String newNativePath = mp.targetArgs
                                             .getNativeLibraryPath();
 
-                                    try {
-                                        final File newNativeDir = new File(newNativePath);
+                                    final File newNativeDir = new File(newNativePath);
 
-                                        final String libParentDir = newNativeDir.getParentFile()
-                                                .getCanonicalPath();
-                                        if (newNativeDir.getParentFile().getCanonicalPath()
-                                                .equals(pkg.applicationInfo.dataDir)) {
-                                            if (mInstaller
-                                                    .unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) {
-                                                returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
-                                            } else {
-                                                NativeLibraryHelper.copyNativeBinariesIfNeededLI(
-                                                        new File(newCodePath), newNativeDir);
-                                            }
-                                        } else {
-                                            if (mInstaller.linkNativeLibraryDirectory(
-                                                    pkg.applicationInfo.dataDir, newNativePath) < 0) {
-                                                returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
-                                            }
-                                        }
-                                    } catch (IOException e) {
-                                        returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
+                                    if (!isForwardLocked(pkg) && !isExternal(pkg)) {
+                                        NativeLibraryHelper.copyNativeBinariesIfNeededLI(
+                                                new File(newCodePath), newNativeDir);
                                     }
-
+                                    final int[] users = sUserManager.getUserIds();
+                                    for (int user : users) {
+                                        if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
+                                                newNativePath, user) < 0) {
+                                            returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
+                                        }
+                                    }
 
                                     if (returnCode == PackageManager.MOVE_SUCCEEDED) {
                                         pkg.mPath = newCodePath;
@@ -9402,61 +10078,35 @@
         }
         if (loc == PackageHelper.APP_INSTALL_AUTO || loc == PackageHelper.APP_INSTALL_INTERNAL
                 || loc == PackageHelper.APP_INSTALL_EXTERNAL) {
-            android.provider.Settings.System.putInt(mContext.getContentResolver(),
-                    android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, loc);
+            android.provider.Settings.Global.putInt(mContext.getContentResolver(),
+                    android.provider.Settings.Global.DEFAULT_INSTALL_LOCATION, loc);
             return true;
         }
         return false;
    }
 
     public int getInstallLocation() {
-        return android.provider.Settings.System.getInt(mContext.getContentResolver(),
-                android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION,
+        return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
+                android.provider.Settings.Global.DEFAULT_INSTALL_LOCATION,
                 PackageHelper.APP_INSTALL_AUTO);
     }
 
-    public UserInfo createUser(String name, int flags) {
-        // TODO(kroot): Add a real permission for creating users
-        enforceSystemOrRoot("Only the system can create users");
-
-        UserInfo userInfo = sUserManager.createUser(name, flags);
-        if (userInfo != null) {
-            Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
-            addedIntent.putExtra(Intent.EXTRA_USERID, userInfo.id);
-            mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
+    /** Called by UserManagerService */
+    void cleanUpUserLILPw(int userHandle) {
+        if (mDirtyUsers.remove(userHandle));
+        mSettings.removeUserLPr(userHandle);
+        if (mInstaller != null) {
+            // Technically, we shouldn't be doing this with the package lock
+            // held.  However, this is very rare, and there is already so much
+            // other disk I/O going on, that we'll let it slide for now.
+            mInstaller.removeUserDataDirs(userHandle);
         }
-        return userInfo;
     }
 
-    public boolean removeUser(int userId) {
-        // TODO(kroot): Add a real permission for removing users
-        enforceSystemOrRoot("Only the system can remove users");
-
-        if (userId == 0 || !sUserManager.exists(userId)) {
-            return false;
-        }
-
-        cleanUpUser(userId);
-
-        if (sUserManager.removeUser(userId)) {
-            // Let other services shutdown any activity
-            Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
-            addedIntent.putExtra(Intent.EXTRA_USERID, userId);
-            mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
-        }
-        sUserManager.removePackageFolders(userId);
-        return true;
-    }
-
-    private void cleanUpUser(int userId) {
-        // Disable all the packages for the user first
-        synchronized (mPackages) {
-            Set<Entry<String, PackageSetting>> entries = mSettings.mPackages.entrySet();
-            for (Entry<String, PackageSetting> entry : entries) {
-                entry.getValue().removeUser(userId);
-            }
-            if (mDirtyUsers.remove(userId));
-            mSettings.removeUserLPr(userId);
+    /** Called by UserManagerService */
+    void createNewUserLILPw(int userHandle, File path) {
+        if (mInstaller != null) {
+            mSettings.createNewUserLILPw(mInstaller, userHandle, path);
         }
     }
 
@@ -9472,24 +10122,6 @@
     }
 
     @Override
-    public List<UserInfo> getUsers() {
-        enforceSystemOrRoot("Only the system can query users");
-        return sUserManager.getUsers();
-    }
-
-    @Override
-    public UserInfo getUser(int userId) {
-        enforceSystemOrRoot("Only the system can remove users");
-        return sUserManager.getUser(userId);
-    }
-
-    @Override
-    public void updateUserName(int userId, String name) {
-        enforceSystemOrRoot("Only the system can rename users");
-        sUserManager.updateUserName(userId, name);
-    }
-
-    @Override
     public void setPermissionEnforced(String permission, boolean enforced) {
         mContext.enforceCallingOrSelfPermission(GRANT_REVOKE_PERMISSIONS, null);
         if (READ_EXTERNAL_STORAGE.equals(permission)) {
@@ -9520,19 +10152,37 @@
 
     @Override
     public boolean isPermissionEnforced(String permission) {
+        final boolean enforcedDefault = isPermissionEnforcedDefault(permission);
         synchronized (mPackages) {
-            return isPermissionEnforcedLocked(permission);
+            return isPermissionEnforcedLocked(permission, enforcedDefault);
         }
     }
 
-    private boolean isPermissionEnforcedLocked(String permission) {
+    /**
+     * Check if given permission should be enforced by default. Should always be
+     * called outside of {@link #mPackages} lock.
+     */
+    private boolean isPermissionEnforcedDefault(String permission) {
+        if (READ_EXTERNAL_STORAGE.equals(permission)) {
+            return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
+                    android.provider.Settings.Global.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT, 0)
+                    != 0;
+        } else {
+            return true;
+        }
+    }
+
+    /**
+     * Check if user has requested that given permission be enforced, using
+     * given default if undefined.
+     */
+    private boolean isPermissionEnforcedLocked(String permission, boolean enforcedDefault) {
         if (READ_EXTERNAL_STORAGE.equals(permission)) {
             if (mSettings.mReadExternalStorageEnforced != null) {
                 return mSettings.mReadExternalStorageEnforced;
             } else {
-                // if user hasn't defined, fall back to secure default
-                return Secure.getInt(mContext.getContentResolver(),
-                        Secure.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT, 0) != 0;
+                // User hasn't defined; fall back to secure default
+                return enforcedDefault;
             }
         } else {
             return true;
diff --git a/services/java/com/android/server/pm/PackageSettingBase.java b/services/java/com/android/server/pm/PackageSettingBase.java
index 56f2166..ae1b213 100644
--- a/services/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/java/com/android/server/pm/PackageSettingBase.java
@@ -20,11 +20,14 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageUserState;
+import android.content.pm.UserInfo;
 import android.util.SparseArray;
-import android.util.SparseIntArray;
 
 import java.io.File;
 import java.util.HashSet;
+import java.util.List;
 
 /**
  * Settings base class for pending and resolved classes.
@@ -62,19 +65,11 @@
     boolean permissionsFixed;
     boolean haveGids;
 
+    private static final PackageUserState DEFAULT_USER_STATE = new PackageUserState();
+
     // Whether this package is currently stopped, thus can not be
     // started until explicitly launched by the user.
-    private SparseArray<Boolean> stopped = new SparseArray<Boolean>();
-
-    // Set to true if we have never launched this app.
-    private SparseArray<Boolean> notLaunched = new SparseArray<Boolean>();
-
-    /* Explicitly disabled components */
-    private SparseArray<HashSet<String>> disabledComponents = new SparseArray<HashSet<String>>();
-    /* Explicitly enabled components */
-    private SparseArray<HashSet<String>> enabledComponents = new SparseArray<HashSet<String>>();
-    /* Enabled state */
-    private SparseIntArray enabled = new SparseIntArray();
+    private final SparseArray<PackageUserState> userState = new SparseArray<PackageUserState>();
 
     int installStatus = PKG_INSTALL_COMPLETE;
 
@@ -115,12 +110,11 @@
 
         permissionsFixed = base.permissionsFixed;
         haveGids = base.haveGids;
-        notLaunched = base.notLaunched;
-
-        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();
+        userState.clear();
+        for (int i=0; i<base.userState.size(); i++) {
+            userState.put(base.userState.keyAt(i),
+                    new PackageUserState(base.userState.valueAt(i)));
+        }
         installStatus = base.installStatus;
 
         origPackage = base.origPackage;
@@ -171,103 +165,177 @@
         signatures = base.signatures;
         permissionsFixed = base.permissionsFixed;
         haveGids = base.haveGids;
-        stopped = base.stopped;
-        notLaunched = base.notLaunched;
-        disabledComponents = base.disabledComponents;
-        enabledComponents = base.enabledComponents;
-        enabled = base.enabled;
+        userState.clear();
+        for (int i=0; i<base.userState.size(); i++) {
+            userState.put(base.userState.keyAt(i), base.userState.valueAt(i));
+        }
         installStatus = base.installStatus;
     }
 
+    private PackageUserState modifyUserState(int userId) {
+        PackageUserState state = userState.get(userId);
+        if (state == null) {
+            state = new PackageUserState();
+            userState.put(userId, state);
+        }
+        return state;
+    }
+
+    public PackageUserState readUserState(int userId) {
+        PackageUserState state = userState.get(userId);
+        if (state != null) {
+            return state;
+        }
+        return DEFAULT_USER_STATE;
+    }
+
     void setEnabled(int state, int userId) {
-        enabled.put(userId, state);
+        modifyUserState(userId).enabled = state;
     }
 
     int getEnabled(int userId) {
-        return enabled.get(userId, COMPONENT_ENABLED_STATE_DEFAULT);
+        return readUserState(userId).enabled;
+    }
+
+    void setInstalled(boolean inst, int userId) {
+        modifyUserState(userId).installed = inst;
+    }
+
+    boolean getInstalled(int userId) {
+        return readUserState(userId).installed;
+    }
+
+    boolean isAnyInstalled(int[] users) {
+        for (int user: users) {
+            if (readUserState(user).installed) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    int[] queryInstalledUsers(int[] users, boolean installed) {
+        int num = 0;
+        for (int user : users) {
+            if (getInstalled(user) == installed) {
+                num++;
+            }
+        }
+        int[] res = new int[num];
+        num = 0;
+        for (int user : users) {
+            if (getInstalled(user) == installed) {
+                res[num] = user;
+                num++;
+            }
+        }
+        return res;
     }
 
     boolean getStopped(int userId) {
-        return stopped.get(userId, false);
+        return readUserState(userId).stopped;
     }
 
     void setStopped(boolean stop, int userId) {
-        stopped.put(userId, stop);
+        modifyUserState(userId).stopped = stop;
     }
 
     boolean getNotLaunched(int userId) {
-        return notLaunched.get(userId, false);
+        return readUserState(userId).notLaunched;
     }
 
     void setNotLaunched(boolean stop, int userId) {
-        notLaunched.put(userId, stop);
+        modifyUserState(userId).notLaunched = stop;
+    }
+
+    void setUserState(int userId, int enabled, boolean installed, boolean stopped,
+            boolean notLaunched, HashSet<String> enabledComponents,
+            HashSet<String> disabledComponents) {
+        PackageUserState state = modifyUserState(userId);
+        state.enabled = enabled;
+        state.installed = installed;
+        state.stopped = stopped;
+        state.notLaunched = notLaunched;
+        state.enabledComponents = enabledComponents;
+        state.disabledComponents = disabledComponents;
     }
 
     HashSet<String> getEnabledComponents(int userId) {
-        return getComponentHashSet(enabledComponents, userId);
+        return readUserState(userId).enabledComponents;
     }
 
     HashSet<String> getDisabledComponents(int userId) {
-        return getComponentHashSet(disabledComponents, userId);
+        return readUserState(userId).disabledComponents;
     }
 
     void setEnabledComponents(HashSet<String> components, int userId) {
-        enabledComponents.put(userId, components);
+        modifyUserState(userId).enabledComponents = components;
     }
 
     void setDisabledComponents(HashSet<String> components, int userId) {
-        disabledComponents.put(userId, components);
+        modifyUserState(userId).disabledComponents = 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);
+    void setEnabledComponentsCopy(HashSet<String> components, int userId) {
+        modifyUserState(userId).enabledComponents = components != null
+                ? new HashSet<String>(components) : null;
+    }
+
+    void setDisabledComponentsCopy(HashSet<String> components, int userId) {
+        modifyUserState(userId).disabledComponents = components != null
+                ? new HashSet<String>(components) : null;
+    }
+
+    PackageUserState modifyUserStateComponents(int userId, boolean disabled, boolean enabled) {
+        PackageUserState state = modifyUserState(userId);
+        if (disabled && state.disabledComponents == null) {
+            state.disabledComponents = new HashSet<String>(1);
         }
-        return set;
+        if (enabled && state.enabledComponents == null) {
+            state.enabledComponents = new HashSet<String>(1);
+        }
+        return state;
     }
 
     void addDisabledComponent(String componentClassName, int userId) {
-        HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
-        disabled.add(componentClassName);
+        modifyUserStateComponents(userId, true, false).disabledComponents.add(componentClassName);
     }
 
     void addEnabledComponent(String componentClassName, int userId) {
-        HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
-        enabled.add(componentClassName);
+        modifyUserStateComponents(userId, false, true).enabledComponents.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);
+        PackageUserState state = modifyUserStateComponents(userId, false, true);
+        boolean changed = state.disabledComponents != null
+                ? state.disabledComponents.remove(componentClassName) : false;
+        changed |= state.enabledComponents.add(componentClassName);
         return changed;
     }
 
     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);
+        PackageUserState state = modifyUserStateComponents(userId, true, false);
+        boolean changed = state.enabledComponents != null
+                ? state.enabledComponents.remove(componentClassName) : false;
+        changed |= state.disabledComponents.add(componentClassName);
         return changed;
     }
 
     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);
+        PackageUserState state = modifyUserStateComponents(userId, true, true);
+        boolean changed = state.disabledComponents != null
+                ? state.disabledComponents.remove(componentClassName) : false;
+        changed |= state.enabledComponents != null
+                ? state.enabledComponents.remove(componentClassName) : false;
         return changed;
     }
 
     int getCurrentEnabledStateLPr(String componentName, int userId) {
-        HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
-        HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
-        if (enabled.contains(componentName)) {
+        PackageUserState state = readUserState(userId);
+        if (state.enabledComponents != null && state.enabledComponents.contains(componentName)) {
             return COMPONENT_ENABLED_STATE_ENABLED;
-        } else if (disabled.contains(componentName)) {
+        } else if (state.disabledComponents != null
+                && state.disabledComponents.contains(componentName)) {
             return COMPONENT_ENABLED_STATE_DISABLED;
         } else {
             return COMPONENT_ENABLED_STATE_DEFAULT;
@@ -275,11 +343,6 @@
     }
 
     void removeUser(int userId) {
-        enabled.delete(userId);
-        stopped.delete(userId);
-        enabledComponents.delete(userId);
-        disabledComponents.delete(userId);
-        notLaunched.delete(userId);
+        userState.delete(userId);
     }
-
 }
diff --git a/services/java/com/android/server/pm/PackageVerificationState.java b/services/java/com/android/server/pm/PackageVerificationState.java
index e5b89c1..3214e88 100644
--- a/services/java/com/android/server/pm/PackageVerificationState.java
+++ b/services/java/com/android/server/pm/PackageVerificationState.java
@@ -43,6 +43,8 @@
 
     private boolean mRequiredVerificationPassed;
 
+    private boolean mExtendedTimeout;
+
     /**
      * Create a new package verification state where {@code requiredVerifierUid}
      * is the user ID for the package that must reply affirmative before things
@@ -55,6 +57,7 @@
         mRequiredVerifierUid = requiredVerifierUid;
         mArgs = args;
         mSufficientVerifierUids = new SparseBooleanArray();
+        mExtendedTimeout = false;
     }
 
     public InstallArgs getInstallArgs() {
@@ -146,4 +149,22 @@
 
         return true;
     }
+
+    /**
+     * Extend the timeout for this Package to be verified.
+     */
+    public void extendTimeout() {
+        if (!mExtendedTimeout) {
+            mExtendedTimeout = true;
+        }
+    }
+
+    /**
+     * Returns whether the timeout was extended for verification.
+     *
+     * @return {@code true} if a timeout was already extended.
+     */
+    public boolean timeoutExtended() {
+        return mExtendedTimeout;
+    }
 }
diff --git a/services/java/com/android/server/pm/PreferredActivity.java b/services/java/com/android/server/pm/PreferredActivity.java
index b100eb1..dbf56ef 100644
--- a/services/java/com/android/server/pm/PreferredActivity.java
+++ b/services/java/com/android/server/pm/PreferredActivity.java
@@ -33,6 +33,7 @@
     private static final String TAG = "PreferredActivity";
 
     private static final boolean DEBUG_FILTERS = false;
+    static final String ATTR_USER_ID = "userId";
 
     final PreferredComponent mPref;
 
@@ -48,7 +49,7 @@
     public void writeToXml(XmlSerializer serializer) throws IOException {
         mPref.writeToXml(serializer);
         serializer.startTag(null, "filter");
-        super.writeToXml(serializer);
+            super.writeToXml(serializer);
         serializer.endTag(null, "filter");
     }
 
diff --git a/services/java/com/android/server/pm/PreferredIntentResolver.java b/services/java/com/android/server/pm/PreferredIntentResolver.java
new file mode 100644
index 0000000..3f1e50c
--- /dev/null
+++ b/services/java/com/android/server/pm/PreferredIntentResolver.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import java.io.PrintWriter;
+
+import com.android.server.IntentResolver;
+
+public class PreferredIntentResolver
+        extends IntentResolver<PreferredActivity, PreferredActivity> {
+    @Override
+    protected PreferredActivity[] newArray(int size) {
+        return new PreferredActivity[size];
+    }
+    @Override
+    protected String packageForFilter(PreferredActivity filter) {
+        return filter.mPref.mComponent.getPackageName();
+    }
+    @Override
+    protected void dumpFilter(PrintWriter out, String prefix,
+            PreferredActivity filter) {
+        filter.mPref.dump(out, prefix, filter);
+    }
+}
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 120b650..94494ae 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -32,23 +32,24 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
-import android.app.AppGlobals;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ComponentInfo;
+import android.content.pm.PackageCleanItem;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
 import android.content.pm.PermissionInfo;
 import android.content.pm.Signature;
 import android.content.pm.UserInfo;
+import android.content.pm.PackageUserState;
 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.os.UserHandle;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -69,6 +70,8 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
 
 import libcore.io.IoUtils;
 
@@ -79,6 +82,7 @@
     private static final String TAG = "PackageSettings";
 
     private static final boolean DEBUG_STOPPED = false;
+    private static final boolean DEBUG_MU = false;
 
     private static final String TAG_READ_EXTERNAL_STORAGE = "read-external-storage";
     private static final String ATTR_ENFORCEMENT = "enforcement";
@@ -90,9 +94,12 @@
     private static final String TAG_PACKAGE = "pkg";
 
     private static final String ATTR_NAME = "name";
+    private static final String ATTR_USER = "user";
+    private static final String ATTR_CODE = "code";
     private static final String ATTR_NOT_LAUNCHED = "nl";
     private static final String ATTR_ENABLED = "enabled";
     private static final String ATTR_STOPPED = "stopped";
+    private static final String ATTR_INSTALLED = "inst";
 
     private final File mSettingsFilename;
     private final File mBackupSettingsFilename;
@@ -118,18 +125,9 @@
 
     // The user's preferred activities associated with particular intent
     // filters.
-    final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
-                new IntentResolver<PreferredActivity, PreferredActivity>() {
-        @Override
-        protected String packageForFilter(PreferredActivity filter) {
-            return filter.mPref.mComponent.getPackageName();
-        }
-        @Override
-        protected void dumpFilter(PrintWriter out, String prefix,
-                PreferredActivity filter) {
-            filter.mPref.dump(out, prefix, filter);
-        }
-    };
+    final SparseArray<PreferredIntentResolver> mPreferredActivities =
+            new SparseArray<PreferredIntentResolver>();
+
     final HashMap<String, SharedUserSetting> mSharedUsers =
             new HashMap<String, SharedUserSetting>();
     private final ArrayList<Object> mUserIds = new ArrayList<Object>();
@@ -150,7 +148,7 @@
 
     // Packages that have been uninstalled and still need their external
     // storage data deleted.
-    final ArrayList<String> mPackagesToBeCleaned = new ArrayList<String>();
+    final ArrayList<PackageCleanItem> mPackagesToBeCleaned = new ArrayList<PackageCleanItem>();
     
     // Packages that have been renamed since they were first installed.
     // Keys are the new names of the packages, values are the original
@@ -169,12 +167,15 @@
      */
     private final ArrayList<PendingPackage> mPendingPackages = new ArrayList<PendingPackage>();
 
+    private final Context mContext;
+
     private final File mSystemDir;
-    Settings() {
-        this(Environment.getDataDirectory());
+    Settings(Context context) {
+        this(context, Environment.getDataDirectory());
     }
 
-    Settings(File dataDir) {
+    Settings(Context context, File dataDir) {
+        mContext = context;
         mSystemDir = new File(dataDir, "system");
         mSystemDir.mkdirs();
         FileUtils.setPermissions(mSystemDir.toString(),
@@ -191,10 +192,11 @@
 
     PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
             String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
-            String nativeLibraryPathString, int pkgFlags, boolean create, boolean add) {
+            String nativeLibraryPathString, int pkgFlags, UserHandle user, boolean add) {
         final String name = pkg.packageName;
         PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath,
-                resourcePath, nativeLibraryPathString, pkg.mVersionCode, pkgFlags, create, add);
+                resourcePath, nativeLibraryPathString, pkg.mVersionCode, pkgFlags,
+                user, add, true /* allowInstall */);
         return p;
     }
 
@@ -355,7 +357,8 @@
 
     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) {
+            String nativeLibraryPathString, int vc, int pkgFlags,
+            UserHandle installUser, boolean add, boolean allowInstall) {
         PackageSetting p = mPackages.get(name);
         if (p != null) {
             if (!p.codePath.equals(codePath)) {
@@ -398,11 +401,6 @@
             }
         }
         if (p == null) {
-            // Create a new PackageSettings entry. this can end up here because
-            // of code path mismatch or user id mismatch of an updated system partition
-            if (!create) {
-                return null;
-            }
             if (origPackage != null) {
                 // We are consuming the data from an existing package.
                 p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
@@ -434,10 +432,22 @@
                         Slog.i(PackageManagerService.TAG, "Stopping package " + name, e);
                     }
                     List<UserInfo> users = getAllUsers();
-                    if (users != null) {
+                    if (users != null && allowInstall) {
                         for (UserInfo user : users) {
-                            p.setStopped(true, user.id);
-                            p.setNotLaunched(true, user.id);
+                            // By default we consider this app to be installed
+                            // for the user if no user has been specified (which
+                            // means to leave it at its original value, and the
+                            // original default value is true), or we are being
+                            // asked to install for all users, or this is the
+                            // user we are installing for.
+                            final boolean installed = installUser == null
+                                    || installUser.getIdentifier() == UserHandle.USER_ALL
+                                    || installUser.getIdentifier() == user.id;
+                            p.setUserState(user.id, COMPONENT_ENABLED_STATE_DEFAULT,
+                                    installed,
+                                    true, // stopped,
+                                    true, // notLaunched
+                                    null, null);
                             writePackageRestrictionsLPr(user.id);
                         }
                     }
@@ -463,12 +473,10 @@
                         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);
+                                p.setDisabledComponentsCopy(
+                                        dis.getDisabledComponents(userId), userId);
+                                p.setEnabledComponentsCopy(
+                                        dis.getEnabledComponents(userId), userId);
                             }
                         }
                         // Add new setting to list of user ids
@@ -489,6 +497,25 @@
                 // user preferences
                 addPackageSettingLPw(p, name, sharedUser);
             }
+        } else {
+            if (installUser != null && allowInstall) {
+                // The caller has explicitly specified the user they want this
+                // package installed for, and the package already exists.
+                // Make sure it conforms to the new request.
+                List<UserInfo> users = getAllUsers();
+                if (users != null) {
+                    for (UserInfo user : users) {
+                        if (installUser.getIdentifier() == UserHandle.USER_ALL
+                                || installUser.getIdentifier() == user.id) {
+                            boolean installed = p.getInstalled(user.id);
+                            if (!installed) {
+                                p.setInstalled(true, user.id);
+                                writePackageRestrictionsLPr(user.id);
+                            }
+                        }
+                    }
+                }
+            }
         }
         return p;
     }
@@ -527,6 +554,10 @@
         if (p.signatures.mSignatures == null) {
             p.signatures.assignSignatures(pkg.mSignatures);
         }
+        // Update flags if needed.
+        if (pkg.applicationInfo.flags != p.pkgFlags) {
+            p.pkgFlags = pkg.applicationInfo.flags;
+        }
         // If this app defines a shared user id initialize
         // the shared user signatures as well.
         if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
@@ -703,14 +734,22 @@
         }
     }
 
+    PreferredIntentResolver editPreferredActivitiesLPw(int userId) {
+        PreferredIntentResolver pir = mPreferredActivities.get(userId);
+        if (pir == null) {
+            pir = new PreferredIntentResolver();
+            mPreferredActivities.put(userId, pir);
+        }
+        return pir;
+    }
+
     private File getUserPackagesStateFile(int userId) {
-        return new File(mSystemDir,
-                "users/" + userId + "/package-restrictions.xml");
+        return new File(Environment.getUserSystemDirectory(userId), "package-restrictions.xml");
     }
 
     private File getUserPackagesStateBackupFile(int userId) {
-        return new File(mSystemDir,
-                "users/" + userId + "/package-restrictions-backup.xml");
+        return new File(Environment.getUserSystemDirectory(userId),
+                "package-restrictions-backup.xml");
     }
 
     void writeAllUsersPackageRestrictionsLPr() {
@@ -734,7 +773,39 @@
         }
     }
 
+    private void readPreferredActivitiesLPw(XmlPullParser parser, int userId)
+            throws XmlPullParserException, IOException {
+        int outerDepth = parser.getDepth();
+        int type;
+        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_ITEM)) {
+                PreferredActivity pa = new PreferredActivity(parser);
+                if (pa.mPref.getParseError() == null) {
+                    editPreferredActivitiesLPw(userId).addFilter(pa);
+                } else {
+                    PackageManagerService.reportSettingsProblem(Log.WARN,
+                            "Error in package manager settings: <preferred-activity> "
+                                    + pa.mPref.getParseError() + " at "
+                                    + parser.getPositionDescription());
+                }
+            } else {
+                PackageManagerService.reportSettingsProblem(Log.WARN,
+                        "Unknown element under <preferred-activities>: " + parser.getName());
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+    }
+
     void readPackageRestrictionsLPr(int userId) {
+        if (DEBUG_MU) {
+            Log.i(TAG, "Reading package restrictions for user=" + userId);
+        }
         FileInputStream str = null;
         File userPackagesStateFile = getUserPackagesStateFile(userId);
         File backupFile = getUserPackagesStateBackupFile(userId);
@@ -766,10 +837,14 @@
                             + "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.
+                    // in the stopped state, but not at first boot.  Also
+                    // consider all applications to be installed.
                     for (PackageSetting pkg : mPackages.values()) {
-                        pkg.setStopped(false, userId);
-                        pkg.setNotLaunched(false, userId);
+                        pkg.setUserState(userId, COMPONENT_ENABLED_STATE_DEFAULT,
+                                true,   // installed
+                                false,  // stopped
+                                false,  // notLaunched
+                                null, null);
                     }
                     return;
                 }
@@ -811,17 +886,21 @@
                         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);
+                    final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
+                    final int enabled = enabledStr == null
+                            ? COMPONENT_ENABLED_STATE_DEFAULT : Integer.parseInt(enabledStr);
+                    final String installedStr = parser.getAttributeValue(null, ATTR_INSTALLED);
+                    final boolean installed = installedStr == null
+                            ? true : Boolean.parseBoolean(installedStr);
+                    final String stoppedStr = parser.getAttributeValue(null, ATTR_STOPPED);
+                    final boolean stopped = stoppedStr == null
+                            ? false : Boolean.parseBoolean(stoppedStr);
+                    final String notLaunchedStr = parser.getAttributeValue(null, ATTR_NOT_LAUNCHED);
+                    final boolean notLaunched = stoppedStr == null
+                            ? false : Boolean.parseBoolean(notLaunchedStr);
+
+                    HashSet<String> enabledComponents = null;
+                    HashSet<String> disabledComponents = null;
 
                     int packageDepth = parser.getDepth();
                     while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
@@ -833,13 +912,16 @@
                         }
                         tagName = parser.getName();
                         if (tagName.equals(TAG_ENABLED_COMPONENTS)) {
-                            HashSet<String> components = readComponentsLPr(parser);
-                            ps.setEnabledComponents(components, userId);
+                            enabledComponents = readComponentsLPr(parser);
                         } else if (tagName.equals(TAG_DISABLED_COMPONENTS)) {
-                            HashSet<String> components = readComponentsLPr(parser);
-                            ps.setDisabledComponents(components, userId);
+                            disabledComponents = readComponentsLPr(parser);
                         }
                     }
+
+                    ps.setUserState(userId, enabled, installed, stopped, notLaunched,
+                            enabledComponents, disabledComponents);
+                } else if (tagName.equals("preferred-activities")) {
+                    readPreferredActivitiesLPw(parser, userId);
                 } else {
                     Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
                           + parser.getName());
@@ -864,7 +946,7 @@
 
     private HashSet<String> readComponentsLPr(XmlPullParser parser)
             throws IOException, XmlPullParserException {
-        HashSet<String> components = new HashSet<String>();
+        HashSet<String> components = null;
         int type;
         int outerDepth = parser.getDepth();
         String tagName;
@@ -879,6 +961,9 @@
             if (tagName.equals(TAG_ITEM)) {
                 String componentName = parser.getAttributeValue(null, ATTR_NAME);
                 if (componentName != null) {
+                    if (components == null) {
+                        components = new HashSet<String>();
+                    }
                     components.add(componentName);
                 }
             }
@@ -886,7 +971,24 @@
         return components;
     }
 
+    void writePreferredActivitiesLPr(XmlSerializer serializer, int userId)
+            throws IllegalArgumentException, IllegalStateException, IOException {
+        serializer.startTag(null, "preferred-activities");
+        PreferredIntentResolver pir = mPreferredActivities.get(userId);
+        if (pir != null) {
+            for (final PreferredActivity pa : pir.filterSet()) {
+                serializer.startTag(null, TAG_ITEM);
+                pa.writeToXml(serializer);
+                serializer.endTag(null, TAG_ITEM);
+            }
+        }
+        serializer.endTag(null, "preferred-activities");
+    }
+
     void writePackageRestrictionsLPr(int userId) {
+        if (DEBUG_MU) {
+            Log.i(TAG, "Writing package restrictions for user=" + userId);
+        }
         // Keep the old stopped packages around until we know the new ones have
         // been successfully written.
         File userPackagesStateFile = getUserPackagesStateFile(userId);
@@ -921,40 +1023,44 @@
             serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
 
             for (final PackageSetting pkg : mPackages.values()) {
-                if (pkg.getStopped(userId)
-                        || pkg.getNotLaunched(userId)
-                        || pkg.getEnabled(userId) != COMPONENT_ENABLED_STATE_DEFAULT
-                        || pkg.getEnabledComponents(userId).size() > 0
-                        || pkg.getDisabledComponents(userId).size() > 0) {
+                PackageUserState ustate = pkg.readUserState(userId);
+                if (ustate.stopped || ustate.notLaunched || !ustate.installed
+                        || ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT
+                        || (ustate.enabledComponents != null
+                                && ustate.enabledComponents.size() > 0)
+                        || (ustate.disabledComponents != null
+                                && ustate.disabledComponents.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 (DEBUG_MU) Log.i(TAG, "  pkg=" + pkg.name + ", state=" + ustate.enabled);
 
-                    if (stopped) {
+                    if (!ustate.installed) {
+                        serializer.attribute(null, ATTR_INSTALLED, "false");
+                    }
+                    if (ustate.stopped) {
                         serializer.attribute(null, ATTR_STOPPED, "true");
                     }
-                    if (notLaunched) {
+                    if (ustate.notLaunched) {
                         serializer.attribute(null, ATTR_NOT_LAUNCHED, "true");
                     }
-                    if (enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
-                        serializer.attribute(null, ATTR_ENABLED, Integer.toString(enabled));
+                    if (ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
+                        serializer.attribute(null, ATTR_ENABLED,
+                                Integer.toString(ustate.enabled));
                     }
-                    if (enabledComponents.size() > 0) {
+                    if (ustate.enabledComponents != null
+                            && ustate.enabledComponents.size() > 0) {
                         serializer.startTag(null, TAG_ENABLED_COMPONENTS);
-                        for (final String name : enabledComponents) {
+                        for (final String name : ustate.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) {
+                    if (ustate.disabledComponents != null
+                            && ustate.disabledComponents.size() > 0) {
                         serializer.startTag(null, TAG_DISABLED_COMPONENTS);
-                        for (final String name : disabledComponents) {
+                        for (final String name : ustate.disabledComponents) {
                             serializer.startTag(null, TAG_ITEM);
                             serializer.attribute(null, ATTR_NAME, name);
                             serializer.endTag(null, TAG_ITEM);
@@ -965,6 +1071,8 @@
                 }
             }
 
+            writePreferredActivitiesLPr(serializer, userId);
+
             serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
 
             serializer.endDocument();
@@ -1174,8 +1282,6 @@
                 writeDisabledSysPackageLPr(serializer, pkg);
             }
 
-            writePreferredActivitiesLPr(serializer);
-
             for (final SharedUserSetting usr : mSharedUsers.values()) {
                 serializer.startTag(null, "shared-user");
                 serializer.attribute(null, ATTR_NAME, usr.name);
@@ -1193,9 +1299,12 @@
             }
 
             if (mPackagesToBeCleaned.size() > 0) {
-                for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
+                for (PackageCleanItem item : mPackagesToBeCleaned) {
+                    final String userStr = Integer.toString(item.userId);
                     serializer.startTag(null, "cleaning-package");
-                    serializer.attribute(null, ATTR_NAME, mPackagesToBeCleaned.get(i));
+                    serializer.attribute(null, ATTR_NAME, item.packageName);
+                    serializer.attribute(null, ATTR_CODE, item.andCode ? "true" : "false");
+                    serializer.attribute(null, ATTR_USER, userStr);
                     serializer.endTag(null, "cleaning-package");
                 }
             }
@@ -1300,17 +1409,6 @@
         //Debug.stopMethodTracing();
     }
 
-    void writePreferredActivitiesLPr(XmlSerializer serializer)
-            throws IllegalArgumentException, IllegalStateException, IOException {
-        serializer.startTag(null, "preferred-activities");
-        for (final PreferredActivity pa : mPreferredActivities.filterSet()) {
-            serializer.startTag(null, TAG_ITEM);
-            pa.writeToXml(serializer);
-            serializer.endTag(null, TAG_ITEM);
-        }
-        serializer.endTag(null, "preferred-activities");
-    }
-
     void writeDisabledSysPackageLPr(XmlSerializer serializer, final PackageSetting pkg)
             throws java.io.IOException {
         serializer.startTag(null, "updated-package");
@@ -1452,6 +1550,12 @@
         return ret;
     }
 
+    void addPackageToCleanLPw(PackageCleanItem pkg) {
+        if (!mPackagesToBeCleaned.contains(pkg)) {
+            mPackagesToBeCleaned.add(pkg);
+        }
+    }
+
     boolean readLPw(List<UserInfo> users) {
         FileInputStream str = null;
         if (mBackupSettingsFilename.exists()) {
@@ -1482,7 +1586,7 @@
                     mReadMessages.append("No settings file found\n");
                     PackageManagerService.reportSettingsProblem(Log.INFO,
                             "No settings file; creating initial state");
-                    readDefaultPreferredAppsLPw();
+                    readDefaultPreferredAppsLPw(0);
                     return false;
                 }
                 str = new FileInputStream(mSettingsFilename);
@@ -1524,13 +1628,28 @@
                 } else if (tagName.equals("preferred-packages")) {
                     // no longer used.
                 } else if (tagName.equals("preferred-activities")) {
-                    readPreferredActivitiesLPw(parser);
+                    // Upgrading from old single-user implementation;
+                    // these are the preferred activities for user 0.
+                    readPreferredActivitiesLPw(parser, 0);
                 } else if (tagName.equals("updated-package")) {
                     readDisabledSysPackageLPw(parser);
                 } else if (tagName.equals("cleaning-package")) {
                     String name = parser.getAttributeValue(null, ATTR_NAME);
+                    String userStr = parser.getAttributeValue(null, ATTR_USER);
+                    String codeStr = parser.getAttributeValue(null, ATTR_CODE);
                     if (name != null) {
-                        mPackagesToBeCleaned.add(name);
+                        int userId = 0;
+                        boolean andCode = true;
+                        try {
+                            if (userStr != null) {
+                                userId = Integer.parseInt(userStr);
+                            }
+                        } catch (NumberFormatException e) {
+                        }
+                        if (codeStr != null) {
+                            andCode = Boolean.parseBoolean(codeStr);
+                        }
+                        addPackageToCleanLPw(new PackageCleanItem(userId, name, andCode));
                     }
                 } else if (tagName.equals("renamed-package")) {
                     String nname = parser.getAttributeValue(null, "new");
@@ -1580,7 +1699,6 @@
             mReadMessages.append("Error reading: " + e.toString());
             PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
             Log.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);
-
         }
 
         final int N = mPendingPackages.size();
@@ -1590,7 +1708,8 @@
             if (idObj != null && idObj instanceof SharedUserSetting) {
                 PackageSetting p = getPackageLPw(pp.name, null, pp.realName,
                         (SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
-                        pp.nativeLibraryPathString, pp.versionCode, pp.pkgFlags, true, true);
+                        pp.nativeLibraryPathString, pp.versionCode, pp.pkgFlags,
+                        null, true /* add */, false /* allowInstall */);
                 if (p == null) {
                     PackageManagerService.reportSettingsProblem(Log.WARN,
                             "Unable to create application package for " + pp.name);
@@ -1611,19 +1730,6 @@
         }
         mPendingPackages.clear();
 
-        /*
-         * Make sure all the updated system packages have their shared users
-         * associated with them.
-         */
-        final Iterator<PackageSetting> disabledIt = mDisabledSysPackages.values().iterator();
-        while (disabledIt.hasNext()) {
-            final PackageSetting disabledPs = disabledIt.next();
-            final Object id = getUserIdLPr(disabledPs.appId);
-            if (id != null && id instanceof SharedUserSetting) {
-                disabledPs.sharedUser = (SharedUserSetting) id;
-            }
-        }
-
         if (mBackupStoppedPackagesFilename.exists()
                 || mStoppedPackagesFilename.exists()) {
             // Read old file
@@ -1641,13 +1747,27 @@
                 }
             }
         }
+
+        /*
+         * Make sure all the updated system packages have their shared users
+         * associated with them.
+         */
+        final Iterator<PackageSetting> disabledIt = mDisabledSysPackages.values().iterator();
+        while (disabledIt.hasNext()) {
+            final PackageSetting disabledPs = disabledIt.next();
+            final Object id = getUserIdLPr(disabledPs.appId);
+            if (id != null && id instanceof SharedUserSetting) {
+                disabledPs.sharedUser = (SharedUserSetting) id;
+            }
+        }
+
         mReadMessages.append("Read completed successfully: " + mPackages.size() + " packages, "
                 + mSharedUsers.size() + " shared uids\n");
 
         return true;
     }
 
-    private void readDefaultPreferredAppsLPw() {
+    private void readDefaultPreferredAppsLPw(int userId) {
         // Read preferred apps from .../etc/preferred-apps directory.
         File preferredDir = new File(Environment.getRootDirectory(), "etc/preferred-apps");
         if (!preferredDir.exists() || !preferredDir.isDirectory()) {
@@ -1690,7 +1810,7 @@
                             + " does not start with 'preferred-activities'");
                     continue;
                 }
-                readPreferredActivitiesLPw(parser);
+                readPreferredActivitiesLPw(parser, userId);
             } catch (XmlPullParserException e) {
                 Slog.w(TAG, "Error reading apps file " + f, e);
             } catch (IOException e) {
@@ -2205,36 +2325,27 @@
         }
     }
 
-    private void readPreferredActivitiesLPw(XmlPullParser parser) throws XmlPullParserException,
-            IOException {
-        int outerDepth = parser.getDepth();
-        int type;
-        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_ITEM)) {
-                PreferredActivity pa = new PreferredActivity(parser);
-                if (pa.mPref.getParseError() == null) {
-                    mPreferredActivities.addFilter(pa);
-                } else {
-                    PackageManagerService.reportSettingsProblem(Log.WARN,
-                            "Error in package manager settings: <preferred-activity> "
-                                    + pa.mPref.getParseError() + " at "
-                                    + parser.getPositionDescription());
-                }
-            } else {
-                PackageManagerService.reportSettingsProblem(Log.WARN,
-                        "Unknown element under <preferred-activities>: " + parser.getName());
-                XmlUtils.skipCurrentTag(parser);
-            }
+    void createNewUserLILPw(Installer installer, int userHandle, File path) {
+        path.mkdir();
+        FileUtils.setPermissions(path.toString(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
+                | FileUtils.S_IXOTH, -1, -1);
+        for (PackageSetting ps : mPackages.values()) {
+            // Only system apps are initially installed.
+            ps.setInstalled((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0, userHandle);
+            // Need to create a data directory for all apps under this user.
+            installer.createUserData(ps.name,
+                    UserHandle.getUid(userHandle, ps.appId), userHandle);
         }
+        readDefaultPreferredAppsLPw(userHandle);
+        writePackageRestrictionsLPr(userHandle);
     }
 
     void removeUserLPr(int userId) {
+        Set<Entry<String, PackageSetting>> entries = mPackages.entrySet();
+        for (Entry<String, PackageSetting> entry : entries) {
+            entry.getValue().removeUser(userId);
+        }
+        mPreferredActivities.remove(userId);
         File file = getUserPackagesStateFile(userId);
         file.delete();
         file = getUserPackagesStateBackupFile(userId);
@@ -2276,6 +2387,10 @@
         return ps;
     }
 
+    private String compToString(HashSet<String> cmp) {
+        return cmp != null ? Arrays.toString(cmp.toArray()) : "[]";
+    }
+ 
     boolean isEnabledLPr(ComponentInfo componentInfo, int flags, int userId) {
         if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
             return true;
@@ -2286,24 +2401,26 @@
             Log.v(PackageManagerService.TAG, "isEnabledLock - packageName = "
                     + componentInfo.packageName + " componentName = " + componentInfo.name);
             Log.v(PackageManagerService.TAG, "enabledComponents: "
-                    + Arrays.toString(packageSettings.getEnabledComponents(userId).toArray()));
+                    + compToString(packageSettings.getEnabledComponents(userId)));
             Log.v(PackageManagerService.TAG, "disabledComponents: "
-                    + Arrays.toString(packageSettings.getDisabledComponents(userId).toArray()));
+                    + compToString(packageSettings.getDisabledComponents(userId)));
         }
         if (packageSettings == null) {
             return false;
         }
-        final int enabled = packageSettings.getEnabled(userId);
-        if (enabled == COMPONENT_ENABLED_STATE_DISABLED
-                || enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
+        PackageUserState ustate = packageSettings.readUserState(userId);
+        if (ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED
+                || ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
                 || (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled
-                    && enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
+                    && ustate.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
             return false;
         }
-        if (packageSettings.getEnabledComponents(userId).contains(componentInfo.name)) {
+        if (ustate.enabledComponents != null
+                && ustate.enabledComponents.contains(componentInfo.name)) {
             return true;
         }
-        if (packageSettings.getDisabledComponents(userId).contains(componentInfo.name)) {
+        if (ustate.disabledComponents != null
+                && ustate.disabledComponents.contains(componentInfo.name)) {
             return false;
         }
         return componentInfo.enabled;
@@ -2337,7 +2454,7 @@
 
     boolean setPackageStoppedStateLPw(String packageName, boolean stopped,
             boolean allowedByPermission, int uid, int userId) {
-        int appId = UserId.getAppId(uid);
+        int appId = UserHandle.getAppId(uid);
         final PackageSetting pkgSetting = mPackages.get(packageName);
         if (pkgSetting == null) {
             throw new IllegalArgumentException("Unknown package: " + packageName);
@@ -2362,7 +2479,7 @@
                 if (pkgSetting.installerPackageName != null) {
                     PackageManagerService.sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH,
                             pkgSetting.name, null,
-                            pkgSetting.installerPackageName, null, userId);
+                            pkgSetting.installerPackageName, null, new int[] {userId});
                 }
                 pkgSetting.setNotLaunched(false, userId);
             }
@@ -2374,9 +2491,7 @@
     private List<UserInfo> getAllUsers() {
         long id = Binder.clearCallingIdentity();
         try {
-            return AppGlobals.getPackageManager().getUsers();
-        } catch (RemoteException re) {
-            // Local to system process, shouldn't happen
+            return UserManagerService.getInstance().getUsers(false);
         } catch (NullPointerException npe) {
             // packagemanager not yet initialized
         } finally {
@@ -2413,7 +2528,6 @@
         ApplicationInfo.FLAG_RESTORE_ANY_VERSION, "RESTORE_ANY_VERSION",
         ApplicationInfo.FLAG_EXTERNAL_STORAGE, "EXTERNAL_STORAGE",
         ApplicationInfo.FLAG_LARGE_HEAP, "LARGE_HEAP",
-        ApplicationInfo.FLAG_STOPPED, "STOPPED",
         ApplicationInfo.FLAG_FORWARD_LOCK, "FORWARD_LOCK",
         ApplicationInfo.FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE",
     };
@@ -2505,8 +2619,8 @@
                     first = false;
                     pw.print("anyDensity");
                 }
+                pw.println("]");
             }
-            pw.println("]");
             pw.print("    timeStamp=");
                 date.setTime(ps.timeStamp);
                 pw.println(sdf.format(date));
@@ -2521,24 +2635,31 @@
             }
             pw.print("    signatures="); pw.println(ps.signatures);
             pw.print("    permissionsFixed="); pw.print(ps.permissionsFixed);
-            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(" haveGids="); pw.print(ps.haveGids);
+                    pw.print(" installStatus="); pw.println(ps.installStatus);
+            pw.print("    pkgFlags="); printFlags(pw, ps.pkgFlags, FLAG_DUMP_SPEC);
+                    pw.println();
             for (UserInfo user : users) {
-                pw.print(" User "); pw.print(user.id); pw.print(": ");
+                pw.print("    User "); pw.print(user.id); pw.print(": ");
+                pw.print(" installed=");
+                pw.print(ps.getInstalled(user.id));
                 pw.print(" stopped=");
                 pw.print(ps.getStopped(user.id));
+                pw.print(" notLaunched=");
+                pw.print(ps.getNotLaunched(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)) {
+                HashSet<String> cmp = ps.getDisabledComponents(user.id);
+                if (cmp != null && cmp.size() > 0) {
+                    pw.println("      disabledComponents:");
+                    for (String s : cmp) {
                         pw.print("      "); pw.println(s);
                     }
                 }
-                if (ps.getEnabledComponents(user.id).size() > 0) {
-                    pw.println("    enabledComponents:");
-                    for (String s : ps.getEnabledComponents(user.id)) {
+                cmp = ps.getEnabledComponents(user.id);
+                if (cmp != null && cmp.size() > 0) {
+                    pw.println("      enabledComponents:");
+                    for (String s : cmp) {
                         pw.print("      "); pw.println(s);
                     }
                 }
diff --git a/services/java/com/android/server/pm/ShutdownThread.java b/services/java/com/android/server/pm/ShutdownThread.java
deleted file mode 100644
index 3675d41..0000000
--- a/services/java/com/android/server/pm/ShutdownThread.java
+++ /dev/null
@@ -1,521 +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.
- */
-
- 
-package com.android.server.pm;
-
-import android.app.ActivityManagerNative;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.IActivityManager;
-import android.app.ProgressDialog;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.IBluetooth;
-import android.nfc.NfcAdapter;
-import android.nfc.INfcAdapter;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Handler;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.Vibrator;
-import android.os.SystemVibrator;
-import android.os.storage.IMountService;
-import android.os.storage.IMountShutdownObserver;
-
-import com.android.internal.telephony.ITelephony;
-import com.android.server.PowerManagerService;
-
-import android.util.Log;
-import android.view.WindowManager;
-
-public final class ShutdownThread extends Thread {
-    // constants
-    private static final String TAG = "ShutdownThread";
-    private static final int PHONE_STATE_POLL_SLEEP_MSEC = 500;
-    // maximum time we wait for the shutdown broadcast before going on.
-    private static final int MAX_BROADCAST_TIME = 10*1000;
-    private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000;
-    private static final int MAX_RADIO_WAIT_TIME = 12*1000;
-
-    // length of vibration before shutting down
-    private static final int SHUTDOWN_VIBRATE_MS = 500;
-    
-    // state tracking
-    private static Object sIsStartedGuard = new Object();
-    private static boolean sIsStarted = false;
-    
-    private static boolean mReboot;
-    private static boolean mRebootSafeMode;
-    private static String mRebootReason;
-
-    // Provides shutdown assurance in case the system_server is killed
-    public static final String SHUTDOWN_ACTION_PROPERTY = "sys.shutdown.requested";
-
-    // Indicates whether we are rebooting into safe mode
-    public static final String REBOOT_SAFEMODE_PROPERTY = "persist.sys.safemode";
-
-    // static instance of this thread
-    private static final ShutdownThread sInstance = new ShutdownThread();
-    
-    private final Object mActionDoneSync = new Object();
-    private boolean mActionDone;
-    private Context mContext;
-    private PowerManager mPowerManager;
-    private PowerManager.WakeLock mCpuWakeLock;
-    private PowerManager.WakeLock mScreenWakeLock;
-    private Handler mHandler;
-
-    private static AlertDialog sConfirmDialog;
-    
-    private ShutdownThread() {
-    }
- 
-    /**
-     * Request a clean shutdown, waiting for subsystems to clean up their
-     * state etc.  Must be called from a Looper thread in which its UI
-     * is shown.
-     *
-     * @param context Context used to display the shutdown progress dialog.
-     * @param confirm true if user confirmation is needed before shutting down.
-     */
-    public static void shutdown(final Context context, boolean confirm) {
-        mReboot = false;
-        mRebootSafeMode = false;
-        shutdownInner(context, confirm);
-    }
-
-    static void shutdownInner(final Context context, boolean confirm) {
-        // ensure that only one thread is trying to power down.
-        // any additional calls are just returned
-        synchronized (sIsStartedGuard) {
-            if (sIsStarted) {
-                Log.d(TAG, "Request to shutdown already running, returning.");
-                return;
-            }
-        }
-
-        final int longPressBehavior = context.getResources().getInteger(
-                        com.android.internal.R.integer.config_longPressOnPowerBehavior);
-        final int resourceId = mRebootSafeMode
-                ? com.android.internal.R.string.reboot_safemode_confirm
-                : (longPressBehavior == 2
-                        ? com.android.internal.R.string.shutdown_confirm_question
-                        : com.android.internal.R.string.shutdown_confirm);
-
-        Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior);
-
-        if (confirm) {
-            final CloseDialogReceiver closer = new CloseDialogReceiver(context);
-            if (sConfirmDialog != null) {
-                sConfirmDialog.dismiss();
-            }
-            sConfirmDialog = new AlertDialog.Builder(context)
-                    .setTitle(mRebootSafeMode
-                            ? com.android.internal.R.string.reboot_safemode_title
-                            : com.android.internal.R.string.power_off)
-                    .setMessage(resourceId)
-                    .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
-                        public void onClick(DialogInterface dialog, int which) {
-                            beginShutdownSequence(context);
-                        }
-                    })
-                    .setNegativeButton(com.android.internal.R.string.no, null)
-                    .create();
-            closer.dialog = sConfirmDialog;
-            sConfirmDialog.setOnDismissListener(closer);
-            sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
-            sConfirmDialog.show();
-        } else {
-            beginShutdownSequence(context);
-        }
-    }
-
-    private static class CloseDialogReceiver extends BroadcastReceiver
-            implements DialogInterface.OnDismissListener {
-        private Context mContext;
-        public Dialog dialog;
-
-        CloseDialogReceiver(Context context) {
-            mContext = context;
-            IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
-            context.registerReceiver(this, filter);
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            dialog.cancel();
-        }
-
-        public void onDismiss(DialogInterface unused) {
-            mContext.unregisterReceiver(this);
-        }
-    }
-
-    /**
-     * Request a clean shutdown, waiting for subsystems to clean up their
-     * state etc.  Must be called from a Looper thread in which its UI
-     * is shown.
-     *
-     * @param context Context used to display the shutdown progress dialog.
-     * @param reason code to pass to the kernel (e.g. "recovery"), or null.
-     * @param confirm true if user confirmation is needed before shutting down.
-     */
-    public static void reboot(final Context context, String reason, boolean confirm) {
-        mReboot = true;
-        mRebootSafeMode = false;
-        mRebootReason = reason;
-        shutdownInner(context, confirm);
-    }
-
-    /**
-     * Request a reboot into safe mode.  Must be called from a Looper thread in which its UI
-     * is shown.
-     *
-     * @param context Context used to display the shutdown progress dialog.
-     * @param confirm true if user confirmation is needed before shutting down.
-     */
-    public static void rebootSafeMode(final Context context, boolean confirm) {
-        mReboot = true;
-        mRebootSafeMode = true;
-        mRebootReason = null;
-        shutdownInner(context, confirm);
-    }
-
-    private static void beginShutdownSequence(Context context) {
-        synchronized (sIsStartedGuard) {
-            if (sIsStarted) {
-                Log.d(TAG, "Shutdown sequence already running, returning.");
-                return;
-            }
-            sIsStarted = true;
-        }
-
-        // throw up an indeterminate system dialog to indicate radio is
-        // shutting down.
-        ProgressDialog pd = new ProgressDialog(context);
-        pd.setTitle(context.getText(com.android.internal.R.string.power_off));
-        pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
-        pd.setIndeterminate(true);
-        pd.setCancelable(false);
-        pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
-
-        pd.show();
-
-        sInstance.mContext = context;
-        sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
-
-        // make sure we never fall asleep again
-        sInstance.mCpuWakeLock = null;
-        try {
-            sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock(
-                    PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu");
-            sInstance.mCpuWakeLock.setReferenceCounted(false);
-            sInstance.mCpuWakeLock.acquire();
-        } catch (SecurityException e) {
-            Log.w(TAG, "No permission to acquire wake lock", e);
-            sInstance.mCpuWakeLock = null;
-        }
-
-        // also make sure the screen stays on for better user experience
-        sInstance.mScreenWakeLock = null;
-        if (sInstance.mPowerManager.isScreenOn()) {
-            try {
-                sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock(
-                        PowerManager.FULL_WAKE_LOCK, TAG + "-screen");
-                sInstance.mScreenWakeLock.setReferenceCounted(false);
-                sInstance.mScreenWakeLock.acquire();
-            } catch (SecurityException e) {
-                Log.w(TAG, "No permission to acquire wake lock", e);
-                sInstance.mScreenWakeLock = null;
-            }
-        }
-
-        // start the thread that initiates shutdown
-        sInstance.mHandler = new Handler() {
-        };
-        sInstance.start();
-    }
-
-    void actionDone() {
-        synchronized (mActionDoneSync) {
-            mActionDone = true;
-            mActionDoneSync.notifyAll();
-        }
-    }
-
-    /**
-     * Makes sure we handle the shutdown gracefully.
-     * Shuts off power regardless of radio and bluetooth state if the alloted time has passed.
-     */
-    public void run() {
-        BroadcastReceiver br = new BroadcastReceiver() {
-            @Override public void onReceive(Context context, Intent intent) {
-                // We don't allow apps to cancel this, so ignore the result.
-                actionDone();
-            }
-        };
-
-        /*
-         * Write a system property in case the system_server reboots before we
-         * get to the actual hardware restart. If that happens, we'll retry at
-         * the beginning of the SystemServer startup.
-         */
-        {
-            String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : "");
-            SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);
-        }
-
-        /*
-         * If we are rebooting into safe mode, write a system property
-         * indicating so.
-         */
-        if (mRebootSafeMode) {
-            SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1");
-        }
-
-        Log.i(TAG, "Sending shutdown broadcast...");
-        
-        // First send the high-level shut down broadcast.
-        mActionDone = false;
-        mContext.sendOrderedBroadcast(new Intent(Intent.ACTION_SHUTDOWN), null,
-                br, mHandler, 0, null, null);
-        
-        final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
-        synchronized (mActionDoneSync) {
-            while (!mActionDone) {
-                long delay = endTime - SystemClock.elapsedRealtime();
-                if (delay <= 0) {
-                    Log.w(TAG, "Shutdown broadcast timed out");
-                    break;
-                }
-                try {
-                    mActionDoneSync.wait(delay);
-                } catch (InterruptedException e) {
-                }
-            }
-        }
-        
-        Log.i(TAG, "Shutting down activity manager...");
-        
-        final IActivityManager am =
-            ActivityManagerNative.asInterface(ServiceManager.checkService("activity"));
-        if (am != null) {
-            try {
-                am.shutdown(MAX_BROADCAST_TIME);
-            } catch (RemoteException e) {
-            }
-        }
-
-        // Shutdown radios.
-        shutdownRadios(MAX_RADIO_WAIT_TIME);
-
-        // Shutdown MountService to ensure media is in a safe state
-        IMountShutdownObserver observer = new IMountShutdownObserver.Stub() {
-            public void onShutDownComplete(int statusCode) throws RemoteException {
-                Log.w(TAG, "Result code " + statusCode + " from MountService.shutdown");
-                actionDone();
-            }
-        };
-
-        Log.i(TAG, "Shutting down MountService");
-
-        // Set initial variables and time out time.
-        mActionDone = false;
-        final long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME;
-        synchronized (mActionDoneSync) {
-            try {
-                final IMountService mount = IMountService.Stub.asInterface(
-                        ServiceManager.checkService("mount"));
-                if (mount != null) {
-                    mount.shutdown(observer);
-                } else {
-                    Log.w(TAG, "MountService unavailable for shutdown");
-                }
-            } catch (Exception e) {
-                Log.e(TAG, "Exception during MountService shutdown", e);
-            }
-            while (!mActionDone) {
-                long delay = endShutTime - SystemClock.elapsedRealtime();
-                if (delay <= 0) {
-                    Log.w(TAG, "Shutdown wait timed out");
-                    break;
-                }
-                try {
-                    mActionDoneSync.wait(delay);
-                } catch (InterruptedException e) {
-                }
-            }
-        }
-
-        rebootOrShutdown(mReboot, mRebootReason);
-    }
-
-    private void shutdownRadios(int timeout) {
-        // If a radio is wedged, disabling it may hang so we do this work in another thread,
-        // just in case.
-        final long endTime = SystemClock.elapsedRealtime() + timeout;
-        final boolean[] done = new boolean[1];
-        Thread t = new Thread() {
-            public void run() {
-                boolean nfcOff;
-                boolean bluetoothOff;
-                boolean radioOff;
-
-                final INfcAdapter nfc =
-                        INfcAdapter.Stub.asInterface(ServiceManager.checkService("nfc"));
-                final ITelephony phone =
-                        ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
-                final IBluetooth bluetooth =
-                        IBluetooth.Stub.asInterface(ServiceManager.checkService(
-                                BluetoothAdapter.BLUETOOTH_SERVICE));
-
-                try {
-                    nfcOff = nfc == null ||
-                             nfc.getState() == NfcAdapter.STATE_OFF;
-                    if (!nfcOff) {
-                        Log.w(TAG, "Turning off NFC...");
-                        nfc.disable(false); // Don't persist new state
-                    }
-                } catch (RemoteException ex) {
-                Log.e(TAG, "RemoteException during NFC shutdown", ex);
-                    nfcOff = true;
-                }
-
-                try {
-                    bluetoothOff = bluetooth == null ||
-                                   bluetooth.getBluetoothState() == BluetoothAdapter.STATE_OFF;
-                    if (!bluetoothOff) {
-                        Log.w(TAG, "Disabling Bluetooth...");
-                        bluetooth.disable(false);  // disable but don't persist new state
-                    }
-                } catch (RemoteException ex) {
-                    Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
-                    bluetoothOff = true;
-                }
-
-                try {
-                    radioOff = phone == null || !phone.isRadioOn();
-                    if (!radioOff) {
-                        Log.w(TAG, "Turning off radio...");
-                        phone.setRadio(false);
-                    }
-                } catch (RemoteException ex) {
-                    Log.e(TAG, "RemoteException during radio shutdown", ex);
-                    radioOff = true;
-                }
-
-                Log.i(TAG, "Waiting for NFC, Bluetooth and Radio...");
-
-                while (SystemClock.elapsedRealtime() < endTime) {
-                    if (!bluetoothOff) {
-                        try {
-                            bluetoothOff =
-                                    bluetooth.getBluetoothState() == BluetoothAdapter.STATE_OFF;
-                        } catch (RemoteException ex) {
-                            Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
-                            bluetoothOff = true;
-                        }
-                        if (bluetoothOff) {
-                            Log.i(TAG, "Bluetooth turned off.");
-                        }
-                    }
-                    if (!radioOff) {
-                        try {
-                            radioOff = !phone.isRadioOn();
-                        } catch (RemoteException ex) {
-                            Log.e(TAG, "RemoteException during radio shutdown", ex);
-                            radioOff = true;
-                        }
-                        if (radioOff) {
-                            Log.i(TAG, "Radio turned off.");
-                        }
-                    }
-                    if (!nfcOff) {
-                        try {
-                            nfcOff = nfc.getState() == NfcAdapter.STATE_OFF;
-                        } catch (RemoteException ex) {
-                            Log.e(TAG, "RemoteException during NFC shutdown", ex);
-                            nfcOff = true;
-                        }
-                        if (radioOff) {
-                            Log.i(TAG, "NFC turned off.");
-                        }
-                    }
-
-                    if (radioOff && bluetoothOff && nfcOff) {
-                        Log.i(TAG, "NFC, Radio and Bluetooth shutdown complete.");
-                        done[0] = true;
-                        break;
-                    }
-                    SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC);
-                }
-            }
-        };
-
-        t.start();
-        try {
-            t.join(timeout);
-        } catch (InterruptedException ex) {
-        }
-        if (!done[0]) {
-            Log.w(TAG, "Timed out waiting for NFC, Radio and Bluetooth shutdown.");
-        }
-    }
-
-    /**
-     * Do not call this directly. Use {@link #reboot(Context, String, boolean)}
-     * or {@link #shutdown(Context, boolean)} instead.
-     *
-     * @param reboot true to reboot or false to shutdown
-     * @param reason reason for reboot
-     */
-    public static void rebootOrShutdown(boolean reboot, String reason) {
-        if (reboot) {
-            Log.i(TAG, "Rebooting, reason: " + reason);
-            try {
-                PowerManagerService.lowLevelReboot(reason);
-            } catch (Exception e) {
-                Log.e(TAG, "Reboot failed, will attempt shutdown instead", e);
-            }
-        } else if (SHUTDOWN_VIBRATE_MS > 0) {
-            // vibrate before shutting down
-            Vibrator vibrator = new SystemVibrator();
-            try {
-                vibrator.vibrate(SHUTDOWN_VIBRATE_MS);
-            } catch (Exception e) {
-                // Failure to vibrate shouldn't interrupt shutdown.  Just log it.
-                Log.w(TAG, "Failed to vibrate during shutdown.", e);
-            }
-
-            // vibrator is asynchronous so we need to wait to avoid shutting down too soon.
-            try {
-                Thread.sleep(SHUTDOWN_VIBRATE_MS);
-            } catch (InterruptedException unused) {
-            }
-        }
-
-        // Shutdown power
-        Log.i(TAG, "Performing low-level shutdown...");
-        PowerManagerService.lowLevelShutdown();
-    }
-}
diff --git a/services/java/com/android/server/pm/UserManager.java b/services/java/com/android/server/pm/UserManager.java
deleted file mode 100644
index 4e9e666..0000000
--- a/services/java/com/android/server/pm/UserManager.java
+++ /dev/null
@@ -1,465 +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.
- */
-
-package com.android.server.pm;
-
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.FastXmlSerializer;
-
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
-import android.os.Environment;
-import android.os.FileUtils;
-import android.os.SystemClock;
-import android.os.UserId;
-import android.util.Log;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.util.Xml;
-
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-public class UserManager {
-    private static final String TAG_NAME = "name";
-
-    private static final String ATTR_FLAGS = "flags";
-
-    private static final String ATTR_ID = "id";
-
-    private static final String TAG_USERS = "users";
-
-    private static final String TAG_USER = "user";
-
-    private static final String LOG_TAG = "UserManager";
-
-    private static final String USER_INFO_DIR = "system" + File.separator + "users";
-    private static final String USER_LIST_FILENAME = "userlist.xml";
-
-    private SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>();
-
-    private final File mUsersDir;
-    private final File mUserListFile;
-    private int[] mUserIds;
-
-    private Installer mInstaller;
-    private File mBaseUserPath;
-
-    /**
-     * Available for testing purposes.
-     */
-    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
-                |FileUtils.S_IROTH|FileUtils.S_IXOTH,
-                -1, -1);
-        mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
-        readUserList();
-    }
-
-    public UserManager(Installer installer, File baseUserPath) {
-        this(Environment.getDataDirectory(), baseUserPath);
-        mInstaller = installer;
-    }
-
-    public List<UserInfo> getUsers() {
-        synchronized (mUsers) {
-            ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
-            for (int i = 0; i < mUsers.size(); i++) {
-                users.add(mUsers.valueAt(i));
-            }
-            return users;
-        }
-    }
-
-    public UserInfo getUser(int userId) {
-        synchronized (mUsers) {
-            UserInfo info = mUsers.get(userId);
-            return info;
-        }
-    }
-
-    public boolean exists(int userId) {
-        synchronized (mUsers) {
-            return ArrayUtils.contains(mUserIds, userId);
-        }
-    }
-
-    public void updateUserName(int userId, String name) {
-        synchronized (mUsers) {
-            UserInfo info = mUsers.get(userId);
-            if (name != null && !name.equals(info.name)) {
-                info.name = name;
-                writeUserLocked(info);
-            }
-        }
-    }
-
-    /**
-     * Returns an array of user ids. This array is cached here for quick access, so do not modify or
-     * cache it elsewhere.
-     * @return the array of user ids.
-     */
-    int[] getUserIds() {
-        return mUserIds;
-    }
-
-    private void readUserList() {
-        synchronized (mUsers) {
-            readUserListLocked();
-        }
-    }
-
-    private void readUserListLocked() {
-        if (!mUserListFile.exists()) {
-            fallbackToSingleUserLocked();
-            return;
-        }
-        FileInputStream fis = null;
-        try {
-            fis = new FileInputStream(mUserListFile);
-            XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(fis, null);
-            int type;
-            while ((type = parser.next()) != XmlPullParser.START_TAG
-                    && type != XmlPullParser.END_DOCUMENT) {
-                ;
-            }
-
-            if (type != XmlPullParser.START_TAG) {
-                Slog.e(LOG_TAG, "Unable to read user list");
-                fallbackToSingleUserLocked();
-                return;
-            }
-
-            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
-                if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_USER)) {
-                    String id = parser.getAttributeValue(null, ATTR_ID);
-                    UserInfo user = readUser(Integer.parseInt(id));
-                    if (user != null) {
-                        mUsers.put(user.id, user);
-                    }
-                }
-            }
-            updateUserIdsLocked();
-        } catch (IOException ioe) {
-            fallbackToSingleUserLocked();
-        } catch (XmlPullParserException pe) {
-            fallbackToSingleUserLocked();
-        } finally {
-            if (fis != null) {
-                try {
-                    fis.close();
-                } catch (IOException e) {
-                }
-            }
-        }
-    }
-
-    private void fallbackToSingleUserLocked() {
-        // Create the primary user
-        UserInfo primary = new UserInfo(0, "Primary",
-                UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY);
-        mUsers.put(0, primary);
-        updateUserIdsLocked();
-
-        writeUserListLocked();
-        writeUserLocked(primary);
-    }
-
-    /*
-     * Writes the user file in this format:
-     *
-     * <user flags="20039023" id="0">
-     *   <name>Primary</name>
-     * </user>
-     */
-    private void writeUserLocked(UserInfo userInfo) {
-        FileOutputStream fos = null;
-        try {
-            final File mUserFile = new File(mUsersDir, userInfo.id + ".xml");
-            fos = new FileOutputStream(mUserFile);
-            final BufferedOutputStream bos = new BufferedOutputStream(fos);
-
-            // XmlSerializer serializer = XmlUtils.serializerInstance();
-            final XmlSerializer serializer = new FastXmlSerializer();
-            serializer.setOutput(bos, "utf-8");
-            serializer.startDocument(null, true);
-            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
-
-            serializer.startTag(null, TAG_USER);
-            serializer.attribute(null, ATTR_ID, Integer.toString(userInfo.id));
-            serializer.attribute(null, ATTR_FLAGS, Integer.toString(userInfo.flags));
-
-            serializer.startTag(null, TAG_NAME);
-            serializer.text(userInfo.name);
-            serializer.endTag(null, TAG_NAME);
-
-            serializer.endTag(null, TAG_USER);
-
-            serializer.endDocument();
-        } catch (IOException ioe) {
-            Slog.e(LOG_TAG, "Error writing user info " + userInfo.id + "\n" + ioe);
-        } finally {
-            if (fos != null) {
-                try {
-                    fos.close();
-                } catch (IOException ioe) {
-                }
-            }
-        }
-    }
-
-    /*
-     * Writes the user list file in this format:
-     *
-     * <users>
-     *   <user id="0"></user>
-     *   <user id="2"></user>
-     * </users>
-     */
-    private void writeUserListLocked() {
-        FileOutputStream fos = null;
-        try {
-            fos = new FileOutputStream(mUserListFile);
-            final BufferedOutputStream bos = new BufferedOutputStream(fos);
-
-            // XmlSerializer serializer = XmlUtils.serializerInstance();
-            final XmlSerializer serializer = new FastXmlSerializer();
-            serializer.setOutput(bos, "utf-8");
-            serializer.startDocument(null, true);
-            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
-
-            serializer.startTag(null, TAG_USERS);
-
-            for (int i = 0; i < mUsers.size(); i++) {
-                UserInfo user = mUsers.valueAt(i);
-                serializer.startTag(null, TAG_USER);
-                serializer.attribute(null, ATTR_ID, Integer.toString(user.id));
-                serializer.endTag(null, TAG_USER);
-            }
-
-            serializer.endTag(null, TAG_USERS);
-
-            serializer.endDocument();
-        } catch (IOException ioe) {
-            Slog.e(LOG_TAG, "Error writing user list");
-        } finally {
-            if (fos != null) {
-                try {
-                    fos.close();
-                } catch (IOException ioe) {
-                }
-            }
-        }
-    }
-
-    private UserInfo readUser(int id) {
-        int flags = 0;
-        String name = null;
-
-        FileInputStream fis = null;
-        try {
-            File userFile = new File(mUsersDir, Integer.toString(id) + ".xml");
-            fis = new FileInputStream(userFile);
-            XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(fis, null);
-            int type;
-            while ((type = parser.next()) != XmlPullParser.START_TAG
-                    && type != XmlPullParser.END_DOCUMENT) {
-                ;
-            }
-
-            if (type != XmlPullParser.START_TAG) {
-                Slog.e(LOG_TAG, "Unable to read user " + id);
-                return null;
-            }
-
-            if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_USER)) {
-                String storedId = parser.getAttributeValue(null, ATTR_ID);
-                if (Integer.parseInt(storedId) != id) {
-                    Slog.e(LOG_TAG, "User id does not match the file name");
-                    return null;
-                }
-                String flagString = parser.getAttributeValue(null, ATTR_FLAGS);
-                flags = Integer.parseInt(flagString);
-
-                while ((type = parser.next()) != XmlPullParser.START_TAG
-                        && type != XmlPullParser.END_DOCUMENT) {
-                }
-                if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_NAME)) {
-                    type = parser.next();
-                    if (type == XmlPullParser.TEXT) {
-                        name = parser.getText();
-                    }
-                }
-            }
-
-            UserInfo userInfo = new UserInfo(id, name, flags);
-            return userInfo;
-
-        } catch (IOException ioe) {
-        } catch (XmlPullParserException pe) {
-        } finally {
-            if (fis != null) {
-                try {
-                    fis.close();
-                } catch (IOException e) {
-                }
-            }
-        }
-        return null;
-    }
-
-    public UserInfo createUser(String name, int flags) {
-        int userId = getNextAvailableId();
-        UserInfo userInfo = new UserInfo(userId, name, flags);
-        File userPath = new File(mBaseUserPath, Integer.toString(userId));
-        if (!createPackageFolders(userId, userPath)) {
-            return null;
-        }
-        synchronized (mUsers) {
-            mUsers.put(userId, userInfo);
-            writeUserListLocked();
-            writeUserLocked(userInfo);
-            updateUserIdsLocked();
-        }
-        return userInfo;
-    }
-
-    /**
-     * Removes a user and all data directories created for that user. This method should be called
-     * after the user's processes have been terminated.
-     * @param id the user's id
-     */
-    public boolean removeUser(int id) {
-        synchronized (mUsers) {
-            return removeUserLocked(id);
-        }
-    }
-
-    private boolean removeUserLocked(int id) {
-        // Remove from the list
-        UserInfo userInfo = mUsers.get(id);
-        if (userInfo != null) {
-            // Remove this user from the list
-            mUsers.remove(id);
-            // Remove user file
-            File userFile = new File(mUsersDir, id + ".xml");
-            userFile.delete();
-            // Update the user list
-            writeUserListLocked();
-            updateUserIdsLocked();
-            return true;
-        }
-        return false;
-    }
-
-    public void installPackageForAllUsers(String packageName, int uid) {
-        for (int userId : mUserIds) {
-            // Don't do it for the primary user, it will become recursive.
-            if (userId == 0)
-                continue;
-            mInstaller.createUserData(packageName, UserId.getUid(userId, uid),
-                    userId);
-        }
-    }
-
-    public void clearUserDataForAllUsers(String packageName) {
-        for (int userId : mUserIds) {
-            // Don't do it for the primary user, it will become recursive.
-            if (userId == 0)
-                continue;
-            mInstaller.clearUserData(packageName, userId);
-        }
-    }
-
-    public void removePackageForAllUsers(String packageName) {
-        for (int userId : mUserIds) {
-            // Don't do it for the primary user, it will become recursive.
-            if (userId == 0)
-                continue;
-            mInstaller.remove(packageName, userId);
-        }
-    }
-
-    /**
-     * Caches the list of user ids in an array, adjusting the array size when necessary.
-     */
-    private void updateUserIdsLocked() {
-        if (mUserIds == null || mUserIds.length != mUsers.size()) {
-            mUserIds = new int[mUsers.size()];
-        }
-        for (int i = 0; i < mUsers.size(); i++) {
-            mUserIds[i] = mUsers.keyAt(i);
-        }
-    }
-
-    /**
-     * Returns the next available user id, filling in any holes in the ids.
-     * TODO: May not be a good idea to recycle ids, in case it results in confusion
-     * for data and battery stats collection, or unexpected cross-talk.
-     * @return
-     */
-    private int getNextAvailableId() {
-        int i = 0;
-        while (i < Integer.MAX_VALUE) {
-            if (mUsers.indexOfKey(i) < 0) {
-                break;
-            }
-            i++;
-        }
-        return i;
-    }
-
-    private boolean createPackageFolders(int id, File userPath) {
-        // mInstaller may not be available for unit-tests.
-        if (mInstaller == null) return true;
-
-        // Create the user path
-        userPath.mkdir();
-        FileUtils.setPermissions(userPath.toString(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
-                | FileUtils.S_IXOTH, -1, -1);
-
-        mInstaller.cloneUserData(0, id, false);
-
-        return true;
-    }
-
-    boolean removePackageFolders(int id) {
-        // mInstaller may not be available for unit-tests.
-        if (mInstaller == null) return true;
-
-        mInstaller.removeUserDataDirs(id);
-        return true;
-    }
-}
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
new file mode 100644
index 0000000..e05442b
--- /dev/null
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -0,0 +1,965 @@
+/*
+ * 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.
+ */
+
+package com.android.server.pm;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.FastXmlSerializer;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.app.IStopUserCallback;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Binder;
+import android.os.Environment;
+import android.os.FileUtils;
+import android.os.IUserManager;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.TimeUtils;
+import android.util.Xml;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+public class UserManagerService extends IUserManager.Stub {
+
+    private static final String LOG_TAG = "UserManagerService";
+
+    private static final boolean DBG = false;
+
+    private static final String TAG_NAME = "name";
+    private static final String ATTR_FLAGS = "flags";
+    private static final String ATTR_ICON_PATH = "icon";
+    private static final String ATTR_ID = "id";
+    private static final String ATTR_CREATION_TIME = "created";
+    private static final String ATTR_LAST_LOGGED_IN_TIME = "lastLoggedIn";
+    private static final String ATTR_SERIAL_NO = "serialNumber";
+    private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
+    private static final String ATTR_PARTIAL = "partial";
+    private static final String ATTR_USER_VERSION = "version";
+    private static final String TAG_USERS = "users";
+    private static final String TAG_USER = "user";
+
+    private static final String USER_INFO_DIR = "system" + File.separator + "users";
+    private static final String USER_LIST_FILENAME = "userlist.xml";
+    private static final String USER_PHOTO_FILENAME = "photo.png";
+
+    private static final int MIN_USER_ID = 10;
+
+    private static final int USER_VERSION = 1;
+
+    private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
+
+    private final Context mContext;
+    private final PackageManagerService mPm;
+    private final Object mInstallLock;
+    private final Object mPackagesLock;
+
+    private final File mUsersDir;
+    private final File mUserListFile;
+    private final File mBaseUserPath;
+
+    private SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>();
+    private HashSet<Integer> mRemovingUserIds = new HashSet<Integer>();
+
+    private int[] mUserIds;
+    private boolean mGuestEnabled;
+    private int mNextSerialNumber;
+    // This resets on a reboot. Otherwise it keeps incrementing so that user ids are
+    // not reused in quick succession
+    private int mNextUserId = MIN_USER_ID;
+    private int mUserVersion = 0;
+
+    private static UserManagerService sInstance;
+
+    public static UserManagerService getInstance() {
+        synchronized (UserManagerService.class) {
+            return sInstance;
+        }
+    }
+
+    /**
+     * Available for testing purposes.
+     */
+    UserManagerService(File dataDir, File baseUserPath) {
+        this(null, null, new Object(), new Object(), dataDir, baseUserPath);
+    }
+
+    /**
+     * Called by package manager to create the service.  This is closely
+     * associated with the package manager, and the given lock is the
+     * package manager's own lock.
+     */
+    UserManagerService(Context context, PackageManagerService pm,
+            Object installLock, Object packagesLock) {
+        this(context, pm, installLock, packagesLock,
+                Environment.getDataDirectory(),
+                new File(Environment.getDataDirectory(), "user"));
+    }
+
+    /**
+     * Available for testing purposes.
+     */
+    private UserManagerService(Context context, PackageManagerService pm,
+            Object installLock, Object packagesLock,
+            File dataDir, File baseUserPath) {
+        mContext = context;
+        mPm = pm;
+        mInstallLock = installLock;
+        mPackagesLock = packagesLock;
+        synchronized (mInstallLock) {
+            synchronized (mPackagesLock) {
+                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
+                        |FileUtils.S_IROTH|FileUtils.S_IXOTH,
+                        -1, -1);
+                mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
+                readUserListLocked();
+                // Prune out any partially created/partially removed users.
+                ArrayList<UserInfo> partials = new ArrayList<UserInfo>();
+                for (int i = 0; i < mUsers.size(); i++) {
+                    UserInfo ui = mUsers.valueAt(i);
+                    if (ui.partial && i != 0) {
+                        partials.add(ui);
+                    }
+                }
+                for (int i = 0; i < partials.size(); i++) {
+                    UserInfo ui = partials.get(i);
+                    Slog.w(LOG_TAG, "Removing partially created user #" + i
+                            + " (name=" + ui.name + ")");
+                    removeUserStateLocked(ui.id);
+                }
+                sInstance = this;
+            }
+        }
+    }
+
+    @Override
+    public List<UserInfo> getUsers(boolean excludeDying) {
+        checkManageUsersPermission("query users");
+        synchronized (mPackagesLock) {
+            ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
+            for (int i = 0; i < mUsers.size(); i++) {
+                UserInfo ui = mUsers.valueAt(i);
+                if (ui.partial) {
+                    continue;
+                }
+                if (!excludeDying || !mRemovingUserIds.contains(ui.id)) {
+                    users.add(ui);
+                }
+            }
+            return users;
+        }
+    }
+
+    @Override
+    public UserInfo getUserInfo(int userId) {
+        checkManageUsersPermission("query user");
+        synchronized (mPackagesLock) {
+            return getUserInfoLocked(userId);
+        }
+    }
+
+    /*
+     * Should be locked on mUsers before calling this.
+     */
+    private UserInfo getUserInfoLocked(int userId) {
+        UserInfo ui = mUsers.get(userId);
+        // If it is partial and not in the process of being removed, return as unknown user.
+        if (ui != null && ui.partial && !mRemovingUserIds.contains(userId)) {
+            Slog.w(LOG_TAG, "getUserInfo: unknown user #" + userId);
+            return null;
+        }
+        return ui;
+    }
+
+    public boolean exists(int userId) {
+        synchronized (mPackagesLock) {
+            return ArrayUtils.contains(mUserIds, userId);
+        }
+    }
+
+    @Override
+    public void setUserName(int userId, String name) {
+        checkManageUsersPermission("rename users");
+        boolean changed = false;
+        synchronized (mPackagesLock) {
+            UserInfo info = mUsers.get(userId);
+            if (info == null || info.partial) {
+                Slog.w(LOG_TAG, "setUserName: unknown user #" + userId);
+                return;
+            }
+            if (name != null && !name.equals(info.name)) {
+                info.name = name;
+                writeUserLocked(info);
+                changed = true;
+            }
+        }
+        if (changed) {
+            sendUserInfoChangedBroadcast(userId);
+        }
+    }
+
+    @Override
+    public void setUserIcon(int userId, Bitmap bitmap) {
+        checkManageUsersPermission("update users");
+        synchronized (mPackagesLock) {
+            UserInfo info = mUsers.get(userId);
+            if (info == null || info.partial) {
+                Slog.w(LOG_TAG, "setUserIcon: unknown user #" + userId);
+                return;
+            }
+            writeBitmapLocked(info, bitmap);
+            writeUserLocked(info);
+        }
+        sendUserInfoChangedBroadcast(userId);
+    }
+
+    private void sendUserInfoChangedBroadcast(int userId) {
+        Intent changedIntent = new Intent(Intent.ACTION_USER_INFO_CHANGED);
+        changedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+        changedIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        mContext.sendBroadcastAsUser(changedIntent, new UserHandle(userId));
+    }
+
+    @Override
+    public Bitmap getUserIcon(int userId) {
+        checkManageUsersPermission("read users");
+        synchronized (mPackagesLock) {
+            UserInfo info = mUsers.get(userId);
+            if (info == null || info.partial) {
+                Slog.w(LOG_TAG, "getUserIcon: unknown user #" + userId);
+                return null;
+            }
+            if (info.iconPath == null) {
+                return null;
+            }
+            return BitmapFactory.decodeFile(info.iconPath);
+        }
+    }
+
+    @Override
+    public void setGuestEnabled(boolean enable) {
+        checkManageUsersPermission("enable guest users");
+        synchronized (mPackagesLock) {
+            if (mGuestEnabled != enable) {
+                mGuestEnabled = enable;
+                // Erase any guest user that currently exists
+                for (int i = 0; i < mUsers.size(); i++) {
+                    UserInfo user = mUsers.valueAt(i);
+                    if (!user.partial && user.isGuest()) {
+                        if (!enable) {
+                            removeUser(user.id);
+                        }
+                        return;
+                    }
+                }
+                // No guest was found
+                if (enable) {
+                    createUser("Guest", UserInfo.FLAG_GUEST);
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean isGuestEnabled() {
+        synchronized (mPackagesLock) {
+            return mGuestEnabled;
+        }
+    }
+
+    @Override
+    public void wipeUser(int userHandle) {
+        checkManageUsersPermission("wipe user");
+        // TODO:
+    }
+
+    public void makeInitialized(int userId) {
+        checkManageUsersPermission("makeInitialized");
+        synchronized (mPackagesLock) {
+            UserInfo info = mUsers.get(userId);
+            if (info == null || info.partial) {
+                Slog.w(LOG_TAG, "makeInitialized: unknown user #" + userId);
+            }
+            if ((info.flags&UserInfo.FLAG_INITIALIZED) == 0) {
+                info.flags |= UserInfo.FLAG_INITIALIZED;
+                writeUserLocked(info);
+            }
+        }
+    }
+
+    /**
+     * Check if we've hit the limit of how many users can be created.
+     */
+    private boolean isUserLimitReachedLocked() {
+        int nUsers = mUsers.size();
+        return nUsers >= UserManager.getMaxSupportedUsers();
+    }
+
+    /**
+     * Enforces that only the system UID or root's UID or apps that have the
+     * {@link android.Manifest.permission.MANAGE_USERS MANAGE_USERS}
+     * permission can make certain calls to the UserManager.
+     *
+     * @param message used as message if SecurityException is thrown
+     * @throws SecurityException if the caller is not system or root
+     */
+    private static final void checkManageUsersPermission(String message) {
+        final int uid = Binder.getCallingUid();
+        if (uid != Process.SYSTEM_UID && uid != 0
+                && ActivityManager.checkComponentPermission(
+                        android.Manifest.permission.MANAGE_USERS,
+                        uid, -1, true) != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("You need MANAGE_USERS permission to: " + message);
+        }
+    }
+
+    private void writeBitmapLocked(UserInfo info, Bitmap bitmap) {
+        try {
+            File dir = new File(mUsersDir, Integer.toString(info.id));
+            File file = new File(dir, USER_PHOTO_FILENAME);
+            if (!dir.exists()) {
+                dir.mkdir();
+                FileUtils.setPermissions(
+                        dir.getPath(),
+                        FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
+                        -1, -1);
+            }
+            FileOutputStream os;
+            if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, os = new FileOutputStream(file))) {
+                info.iconPath = file.getAbsolutePath();
+            }
+            try {
+                os.close();
+            } catch (IOException ioe) {
+                // What the ... !
+            }
+        } catch (FileNotFoundException e) {
+            Slog.w(LOG_TAG, "Error setting photo for user ", e);
+        }
+    }
+
+    /**
+     * Returns an array of user ids. This array is cached here for quick access, so do not modify or
+     * cache it elsewhere.
+     * @return the array of user ids.
+     */
+    public int[] getUserIds() {
+        synchronized (mPackagesLock) {
+            return mUserIds;
+        }
+    }
+
+    int[] getUserIdsLPr() {
+        return mUserIds;
+    }
+
+    private void readUserList() {
+        synchronized (mPackagesLock) {
+            readUserListLocked();
+        }
+    }
+
+    private void readUserListLocked() {
+        mGuestEnabled = false;
+        if (!mUserListFile.exists()) {
+            fallbackToSingleUserLocked();
+            return;
+        }
+        FileInputStream fis = null;
+        AtomicFile userListFile = new AtomicFile(mUserListFile);
+        try {
+            fis = userListFile.openRead();
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(fis, null);
+            int type;
+            while ((type = parser.next()) != XmlPullParser.START_TAG
+                    && type != XmlPullParser.END_DOCUMENT) {
+                ;
+            }
+
+            if (type != XmlPullParser.START_TAG) {
+                Slog.e(LOG_TAG, "Unable to read user list");
+                fallbackToSingleUserLocked();
+                return;
+            }
+
+            mNextSerialNumber = -1;
+            if (parser.getName().equals(TAG_USERS)) {
+                String lastSerialNumber = parser.getAttributeValue(null, ATTR_NEXT_SERIAL_NO);
+                if (lastSerialNumber != null) {
+                    mNextSerialNumber = Integer.parseInt(lastSerialNumber);
+                }
+                String versionNumber = parser.getAttributeValue(null, ATTR_USER_VERSION);
+                if (versionNumber != null) {
+                    mUserVersion = Integer.parseInt(versionNumber);
+                }
+            }
+
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+                if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_USER)) {
+                    String id = parser.getAttributeValue(null, ATTR_ID);
+                    UserInfo user = readUser(Integer.parseInt(id));
+
+                    if (user != null) {
+                        mUsers.put(user.id, user);
+                        if (user.isGuest()) {
+                            mGuestEnabled = true;
+                        }
+                        if (mNextSerialNumber < 0 || mNextSerialNumber <= user.id) {
+                            mNextSerialNumber = user.id + 1;
+                        }
+                    }
+                }
+            }
+            updateUserIdsLocked();
+            upgradeIfNecessary();
+        } catch (IOException ioe) {
+            fallbackToSingleUserLocked();
+        } catch (XmlPullParserException pe) {
+            fallbackToSingleUserLocked();
+        } finally {
+            if (fis != null) {
+                try {
+                    fis.close();
+                } catch (IOException e) {
+                }
+            }
+        }
+    }
+
+    /**
+     * This fixes an incorrect initialization of user name for the owner.
+     * TODO: Remove in the next release.
+     */
+    private void upgradeIfNecessary() {
+        int userVersion = mUserVersion;
+        if (userVersion < 1) {
+            // Assign a proper name for the owner, if not initialized correctly before
+            UserInfo user = mUsers.get(UserHandle.USER_OWNER);
+            if ("Primary".equals(user.name)) {
+                user.name = mContext.getResources().getString(com.android.internal.R.string.owner_name);
+                writeUserLocked(user);
+            }
+            userVersion = 1;
+        }
+
+        if (userVersion < USER_VERSION) {
+            Slog.w(LOG_TAG, "User version " + mUserVersion + " didn't upgrade as expected to "
+                    + USER_VERSION);
+        } else {
+            mUserVersion = userVersion;
+            writeUserListLocked();
+        }
+    }
+
+    private void fallbackToSingleUserLocked() {
+        // Create the primary user
+        UserInfo primary = new UserInfo(0, 
+                mContext.getResources().getString(com.android.internal.R.string.owner_name), null,
+                UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY | UserInfo.FLAG_INITIALIZED);
+        mUsers.put(0, primary);
+        mNextSerialNumber = MIN_USER_ID;
+        updateUserIdsLocked();
+
+        writeUserListLocked();
+        writeUserLocked(primary);
+    }
+
+    /*
+     * Writes the user file in this format:
+     *
+     * <user flags="20039023" id="0">
+     *   <name>Primary</name>
+     * </user>
+     */
+    private void writeUserLocked(UserInfo userInfo) {
+        FileOutputStream fos = null;
+        AtomicFile userFile = new AtomicFile(new File(mUsersDir, userInfo.id + ".xml"));
+        try {
+            fos = userFile.startWrite();
+            final BufferedOutputStream bos = new BufferedOutputStream(fos);
+
+            // XmlSerializer serializer = XmlUtils.serializerInstance();
+            final XmlSerializer serializer = new FastXmlSerializer();
+            serializer.setOutput(bos, "utf-8");
+            serializer.startDocument(null, true);
+            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+
+            serializer.startTag(null, TAG_USER);
+            serializer.attribute(null, ATTR_ID, Integer.toString(userInfo.id));
+            serializer.attribute(null, ATTR_SERIAL_NO, Integer.toString(userInfo.serialNumber));
+            serializer.attribute(null, ATTR_FLAGS, Integer.toString(userInfo.flags));
+            serializer.attribute(null, ATTR_CREATION_TIME, Long.toString(userInfo.creationTime));
+            serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME,
+                    Long.toString(userInfo.lastLoggedInTime));
+            if (userInfo.iconPath != null) {
+                serializer.attribute(null,  ATTR_ICON_PATH, userInfo.iconPath);
+            }
+            if (userInfo.partial) {
+                serializer.attribute(null, ATTR_PARTIAL, "true");
+            }
+
+            serializer.startTag(null, TAG_NAME);
+            serializer.text(userInfo.name);
+            serializer.endTag(null, TAG_NAME);
+
+            serializer.endTag(null, TAG_USER);
+
+            serializer.endDocument();
+            userFile.finishWrite(fos);
+        } catch (Exception ioe) {
+            Slog.e(LOG_TAG, "Error writing user info " + userInfo.id + "\n" + ioe);
+            userFile.failWrite(fos);
+        }
+    }
+
+    /*
+     * Writes the user list file in this format:
+     *
+     * <users nextSerialNumber="3">
+     *   <user id="0"></user>
+     *   <user id="2"></user>
+     * </users>
+     */
+    private void writeUserListLocked() {
+        FileOutputStream fos = null;
+        AtomicFile userListFile = new AtomicFile(mUserListFile);
+        try {
+            fos = userListFile.startWrite();
+            final BufferedOutputStream bos = new BufferedOutputStream(fos);
+
+            // XmlSerializer serializer = XmlUtils.serializerInstance();
+            final XmlSerializer serializer = new FastXmlSerializer();
+            serializer.setOutput(bos, "utf-8");
+            serializer.startDocument(null, true);
+            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+
+            serializer.startTag(null, TAG_USERS);
+            serializer.attribute(null, ATTR_NEXT_SERIAL_NO, Integer.toString(mNextSerialNumber));
+            serializer.attribute(null, ATTR_USER_VERSION, Integer.toString(mUserVersion));
+
+            for (int i = 0; i < mUsers.size(); i++) {
+                UserInfo user = mUsers.valueAt(i);
+                serializer.startTag(null, TAG_USER);
+                serializer.attribute(null, ATTR_ID, Integer.toString(user.id));
+                serializer.endTag(null, TAG_USER);
+            }
+
+            serializer.endTag(null, TAG_USERS);
+
+            serializer.endDocument();
+            userListFile.finishWrite(fos);
+        } catch (Exception e) {
+            userListFile.failWrite(fos);
+            Slog.e(LOG_TAG, "Error writing user list");
+        }
+    }
+
+    private UserInfo readUser(int id) {
+        int flags = 0;
+        int serialNumber = id;
+        String name = null;
+        String iconPath = null;
+        long creationTime = 0L;
+        long lastLoggedInTime = 0L;
+        boolean partial = false;
+
+        FileInputStream fis = null;
+        try {
+            AtomicFile userFile =
+                    new AtomicFile(new File(mUsersDir, Integer.toString(id) + ".xml"));
+            fis = userFile.openRead();
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(fis, null);
+            int type;
+            while ((type = parser.next()) != XmlPullParser.START_TAG
+                    && type != XmlPullParser.END_DOCUMENT) {
+                ;
+            }
+
+            if (type != XmlPullParser.START_TAG) {
+                Slog.e(LOG_TAG, "Unable to read user " + id);
+                return null;
+            }
+
+            if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_USER)) {
+                int storedId = readIntAttribute(parser, ATTR_ID, -1);
+                if (storedId != id) {
+                    Slog.e(LOG_TAG, "User id does not match the file name");
+                    return null;
+                }
+                serialNumber = readIntAttribute(parser, ATTR_SERIAL_NO, id);
+                flags = readIntAttribute(parser, ATTR_FLAGS, 0);
+                iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
+                creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0);
+                lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0);
+                String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
+                if ("true".equals(valueString)) {
+                    partial = true;
+                }
+
+                while ((type = parser.next()) != XmlPullParser.START_TAG
+                        && type != XmlPullParser.END_DOCUMENT) {
+                }
+                if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_NAME)) {
+                    type = parser.next();
+                    if (type == XmlPullParser.TEXT) {
+                        name = parser.getText();
+                    }
+                }
+            }
+
+            UserInfo userInfo = new UserInfo(id, name, iconPath, flags);
+            userInfo.serialNumber = serialNumber;
+            userInfo.creationTime = creationTime;
+            userInfo.lastLoggedInTime = lastLoggedInTime;
+            userInfo.partial = partial;
+            return userInfo;
+
+        } catch (IOException ioe) {
+        } catch (XmlPullParserException pe) {
+        } finally {
+            if (fis != null) {
+                try {
+                    fis.close();
+                } catch (IOException e) {
+                }
+            }
+        }
+        return null;
+    }
+
+    private int readIntAttribute(XmlPullParser parser, String attr, int defaultValue) {
+        String valueString = parser.getAttributeValue(null, attr);
+        if (valueString == null) return defaultValue;
+        try {
+            return Integer.parseInt(valueString);
+        } catch (NumberFormatException nfe) {
+            return defaultValue;
+        }
+    }
+
+    private long readLongAttribute(XmlPullParser parser, String attr, long defaultValue) {
+        String valueString = parser.getAttributeValue(null, attr);
+        if (valueString == null) return defaultValue;
+        try {
+            return Long.parseLong(valueString);
+        } catch (NumberFormatException nfe) {
+            return defaultValue;
+        }
+    }
+
+    @Override
+    public UserInfo createUser(String name, int flags) {
+        checkManageUsersPermission("Only the system can create users");
+
+        final long ident = Binder.clearCallingIdentity();
+        final UserInfo userInfo;
+        try {
+            synchronized (mInstallLock) {
+                synchronized (mPackagesLock) {
+                    if (isUserLimitReachedLocked()) return null;
+                    int userId = getNextAvailableIdLocked();
+                    userInfo = new UserInfo(userId, name, null, flags);
+                    File userPath = new File(mBaseUserPath, Integer.toString(userId));
+                    userInfo.serialNumber = mNextSerialNumber++;
+                    long now = System.currentTimeMillis();
+                    userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0;
+                    userInfo.partial = true;
+                    Environment.getUserSystemDirectory(userInfo.id).mkdirs();
+                    mUsers.put(userId, userInfo);
+                    writeUserListLocked();
+                    writeUserLocked(userInfo);
+                    mPm.createNewUserLILPw(userId, userPath);
+                    userInfo.partial = false;
+                    writeUserLocked(userInfo);
+                    updateUserIdsLocked();
+                }
+            }
+            if (userInfo != null) {
+                Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
+                addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userInfo.id);
+                mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL,
+                        android.Manifest.permission.MANAGE_USERS);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+        return userInfo;
+    }
+
+    /**
+     * Removes a user and all data directories created for that user. This method should be called
+     * after the user's processes have been terminated.
+     * @param id the user's id
+     */
+    public boolean removeUser(int userHandle) {
+        checkManageUsersPermission("Only the system can remove users");
+        final UserInfo user;
+        synchronized (mPackagesLock) {
+            user = mUsers.get(userHandle);
+            if (userHandle == 0 || user == null) {
+                return false;
+            }
+            mRemovingUserIds.add(userHandle);
+            // Set this to a partially created user, so that the user will be purged
+            // on next startup, in case the runtime stops now before stopping and
+            // removing the user completely.
+            user.partial = true;
+            writeUserLocked(user);
+        }
+        if (DBG) Slog.i(LOG_TAG, "Stopping user " + userHandle);
+        int res;
+        try {
+            res = ActivityManagerNative.getDefault().stopUser(userHandle,
+                    new IStopUserCallback.Stub() {
+                        @Override
+                        public void userStopped(int userId) {
+                            finishRemoveUser(userId);
+                        }
+                        @Override
+                        public void userStopAborted(int userId) {
+                        }
+            });
+        } catch (RemoteException e) {
+            return false;
+        }
+
+        return res == ActivityManager.USER_OP_SUCCESS;
+    }
+
+    void finishRemoveUser(final int userHandle) {
+        if (DBG) Slog.i(LOG_TAG, "finishRemoveUser " + userHandle);
+        // Let other services shutdown any activity and clean up their state before completely
+        // wiping the user's system directory and removing from the user list
+        long ident = Binder.clearCallingIdentity();
+        try {
+            Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
+            addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
+            mContext.sendOrderedBroadcastAsUser(addedIntent, UserHandle.ALL,
+                    android.Manifest.permission.MANAGE_USERS,
+
+                    new BroadcastReceiver() {
+                        @Override
+                        public void onReceive(Context context, Intent intent) {
+                            if (DBG) {
+                                Slog.i(LOG_TAG,
+                                        "USER_REMOVED broadcast sent, cleaning up user data "
+                                        + userHandle);
+                            }
+                            new Thread() {
+                                public void run() {
+                                    synchronized (mInstallLock) {
+                                        synchronized (mPackagesLock) {
+                                            removeUserStateLocked(userHandle);
+                                        }
+                                    }
+                                }
+                            }.start();
+                        }
+                    },
+
+                    null, Activity.RESULT_OK, null, null);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void removeUserStateLocked(int userHandle) {
+        // Cleanup package manager settings
+        mPm.cleanUpUserLILPw(userHandle);
+
+        // Remove this user from the list
+        mUsers.remove(userHandle);
+        mRemovingUserIds.remove(userHandle);
+        // Remove user file
+        AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + ".xml"));
+        userFile.delete();
+        // Update the user list
+        writeUserListLocked();
+        updateUserIdsLocked();
+        removeDirectoryRecursive(Environment.getUserSystemDirectory(userHandle));
+    }
+
+    private void removeDirectoryRecursive(File parent) {
+        if (parent.isDirectory()) {
+            String[] files = parent.list();
+            for (String filename : files) {
+                File child = new File(parent, filename);
+                removeDirectoryRecursive(child);
+            }
+        }
+        parent.delete();
+    }
+
+    @Override
+    public int getUserSerialNumber(int userHandle) {
+        synchronized (mPackagesLock) {
+            if (!exists(userHandle)) return -1;
+            return getUserInfoLocked(userHandle).serialNumber;
+        }
+    }
+
+    @Override
+    public int getUserHandle(int userSerialNumber) {
+        synchronized (mPackagesLock) {
+            for (int userId : mUserIds) {
+                if (getUserInfoLocked(userId).serialNumber == userSerialNumber) return userId;
+            }
+            // Not found
+            return -1;
+        }
+    }
+
+    /**
+     * Caches the list of user ids in an array, adjusting the array size when necessary.
+     */
+    private void updateUserIdsLocked() {
+        int num = 0;
+        for (int i = 0; i < mUsers.size(); i++) {
+            if (!mUsers.valueAt(i).partial) {
+                num++;
+            }
+        }
+        final int[] newUsers = new int[num];
+        int n = 0;
+        for (int i = 0; i < mUsers.size(); i++) {
+            if (!mUsers.valueAt(i).partial) {
+                newUsers[n++] = mUsers.keyAt(i);
+            }
+        }
+        mUserIds = newUsers;
+    }
+
+    /**
+     * Make a note of the last started time of a user.
+     * @param userId the user that was just foregrounded
+     */
+    public void userForeground(int userId) {
+        synchronized (mPackagesLock) {
+            UserInfo user = mUsers.get(userId);
+            long now = System.currentTimeMillis();
+            if (user == null || user.partial) {
+                Slog.w(LOG_TAG, "userForeground: unknown user #" + userId);
+                return;
+            }
+            if (now > EPOCH_PLUS_30_YEARS) {
+                user.lastLoggedInTime = now;
+                writeUserLocked(user);
+            }
+        }
+    }
+
+    /**
+     * Returns the next available user id, filling in any holes in the ids.
+     * TODO: May not be a good idea to recycle ids, in case it results in confusion
+     * for data and battery stats collection, or unexpected cross-talk.
+     * @return
+     */
+    private int getNextAvailableIdLocked() {
+        synchronized (mPackagesLock) {
+            int i = mNextUserId;
+            while (i < Integer.MAX_VALUE) {
+                if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.contains(i)) {
+                    break;
+                }
+                i++;
+            }
+            mNextUserId = i + 1;
+            return i;
+        }
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump UserManager from from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " without permission "
+                    + android.Manifest.permission.DUMP);
+            return;
+        }
+
+        long now = System.currentTimeMillis();
+        StringBuilder sb = new StringBuilder();
+        synchronized (mPackagesLock) {
+            pw.println("Users:");
+            for (int i = 0; i < mUsers.size(); i++) {
+                UserInfo user = mUsers.valueAt(i);
+                if (user == null) continue;
+                pw.print("  "); pw.print(user); pw.print(" serialNo="); pw.print(user.serialNumber);
+                if (mRemovingUserIds.contains(mUsers.keyAt(i))) pw.print(" <removing> ");
+                if (user.partial) pw.print(" <partial>");
+                pw.println();
+                pw.print("    Created: ");
+                if (user.creationTime == 0) {
+                    pw.println("<unknown>");
+                } else {
+                    sb.setLength(0);
+                    TimeUtils.formatDuration(now - user.creationTime, sb);
+                    sb.append(" ago");
+                    pw.println(sb);
+                }
+                pw.print("    Last logged in: ");
+                if (user.lastLoggedInTime == 0) {
+                    pw.println("<unknown>");
+                } else {
+                    sb.setLength(0);
+                    TimeUtils.formatDuration(now - user.lastLoggedInTime, sb);
+                    sb.append(" ago");
+                    pw.println(sb);
+                }
+            }
+        }
+    }
+}
diff --git a/services/java/com/android/server/power/DisplayBlanker.java b/services/java/com/android/server/power/DisplayBlanker.java
new file mode 100644
index 0000000..6072053
--- /dev/null
+++ b/services/java/com/android/server/power/DisplayBlanker.java
@@ -0,0 +1,25 @@
+/*
+ * 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.power;
+
+/**
+ * Blanks or unblanks all displays.
+ */
+interface DisplayBlanker {
+    public void blankAllDisplays();
+    public void unblankAllDisplays();
+}
diff --git a/services/java/com/android/server/power/DisplayPowerController.java b/services/java/com/android/server/power/DisplayPowerController.java
new file mode 100644
index 0000000..317fec0
--- /dev/null
+++ b/services/java/com/android/server/power/DisplayPowerController.java
@@ -0,0 +1,1330 @@
+/*
+ * 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.power;
+
+import com.android.server.LightsService;
+import com.android.server.TwilightService;
+import com.android.server.TwilightService.TwilightState;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.hardware.SystemSensorManager;
+import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.text.format.DateUtils;
+import android.util.FloatMath;
+import android.util.Slog;
+import android.util.Spline;
+import android.util.TimeUtils;
+import android.view.Display;
+
+import java.io.PrintWriter;
+
+/**
+ * Controls the power state of the display.
+ *
+ * Handles the proximity sensor, light sensor, and animations between states
+ * including the screen off animation.
+ *
+ * This component acts independently of the rest of the power manager service.
+ * In particular, it does not share any state and it only communicates
+ * via asynchronous callbacks to inform the power manager that something has
+ * changed.
+ *
+ * Everything this class does internally is serialized on its handler although
+ * it may be accessed by other threads from the outside.
+ *
+ * Note that the power manager service guarantees that it will hold a suspend
+ * blocker as long as the display is not ready.  So most of the work done here
+ * does not need to worry about holding a suspend blocker unless it happens
+ * independently of the display ready signal.
+ *
+ * For debugging, you can make the electron beam and brightness animations run
+ * slower by changing the "animator duration scale" option in Development Settings.
+ */
+final class DisplayPowerController {
+    private static final String TAG = "DisplayPowerController";
+
+    private static boolean DEBUG = false;
+    private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false;
+    private static final boolean DEBUG_PRETEND_LIGHT_SENSOR_ABSENT = false;
+
+    // If true, uses the electron beam on animation.
+    // We might want to turn this off if we cannot get a guarantee that the screen
+    // actually turns on and starts showing new content after the call to set the
+    // screen state returns.  Playing the animation can also be somewhat slow.
+    private static final boolean USE_ELECTRON_BEAM_ON_ANIMATION = false;
+
+    // If true, enables the use of the screen auto-brightness adjustment setting.
+    private static final boolean USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT =
+            PowerManager.useScreenAutoBrightnessAdjustmentFeature();
+
+    // The maximum range of gamma adjustment possible using the screen
+    // auto-brightness adjustment setting.
+    private static final float SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA = 3.0f;
+
+    // The minimum reduction in brightness when dimmed.
+    private static final int SCREEN_DIM_MINIMUM_REDUCTION = 10;
+
+    // If true, enables the use of the current time as an auto-brightness adjustment.
+    // The basic idea here is to expand the dynamic range of auto-brightness
+    // when it is especially dark outside.  The light sensor tends to perform
+    // poorly at low light levels so we compensate for it by making an
+    // assumption about the environment.
+    private static final boolean USE_TWILIGHT_ADJUSTMENT =
+            PowerManager.useTwilightAdjustmentFeature();
+
+    // Specifies the maximum magnitude of the time of day adjustment.
+    private static final float TWILIGHT_ADJUSTMENT_MAX_GAMMA = 1.5f;
+
+    // The amount of time after or before sunrise over which to start adjusting
+    // the gamma.  We want the change to happen gradually so that it is below the
+    // threshold of perceptibility and so that the adjustment has maximum effect
+    // well after dusk.
+    private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 2;
+
+    private static final int ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS = 250;
+    private static final int ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS = 400;
+
+    private static final int MSG_UPDATE_POWER_STATE = 1;
+    private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
+    private static final int MSG_LIGHT_SENSOR_DEBOUNCED = 3;
+
+    private static final int PROXIMITY_UNKNOWN = -1;
+    private static final int PROXIMITY_NEGATIVE = 0;
+    private static final int PROXIMITY_POSITIVE = 1;
+
+    // Proximity sensor debounce delay in milliseconds for positive or negative transitions.
+    private static final int PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY = 0;
+    private static final int PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY = 500;
+
+    // Trigger proximity if distance is less than 5 cm.
+    private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
+
+    // Light sensor event rate in milliseconds.
+    private static final int LIGHT_SENSOR_RATE_MILLIS = 1000;
+
+    // A rate for generating synthetic light sensor events in the case where the light
+    // sensor hasn't reported any new data in a while and we need it to update the
+    // debounce filter.  We only synthesize light sensor measurements when needed.
+    private static final int SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS =
+            LIGHT_SENSOR_RATE_MILLIS * 2;
+
+    // Brightness animation ramp rate in brightness units per second.
+    private static final int BRIGHTNESS_RAMP_RATE_FAST = 200;
+    private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;
+
+    // IIR filter time constants in milliseconds for computing two moving averages of
+    // the light samples.  One is a long-term average and the other is a short-term average.
+    // We can use these filters to assess trends in ambient brightness.
+    // The short term average gives us a filtered but relatively low latency measurement.
+    // The long term average informs us about the overall trend.
+    private static final long SHORT_TERM_AVERAGE_LIGHT_TIME_CONSTANT = 1000;
+    private static final long LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT = 5000;
+
+    // Stability requirements in milliseconds for accepting a new brightness
+    // level.  This is used for debouncing the light sensor.  Different constants
+    // are used to debounce the light sensor when adapting to brighter or darker environments.
+    // This parameter controls how quickly brightness changes occur in response to
+    // an observed change in light level that exceeds the hysteresis threshold.
+    private static final long BRIGHTENING_LIGHT_DEBOUNCE = 4000;
+    private static final long DARKENING_LIGHT_DEBOUNCE = 8000;
+
+    // Hysteresis constraints for brightening or darkening.
+    // The recent lux must have changed by at least this fraction relative to the
+    // current ambient lux before a change will be considered.
+    private static final float BRIGHTENING_LIGHT_HYSTERESIS = 0.10f;
+    private static final float DARKENING_LIGHT_HYSTERESIS = 0.20f;
+
+    private final Object mLock = new Object();
+
+    // Notifier for sending asynchronous notifications.
+    private final Notifier mNotifier;
+
+    // The display blanker.
+    private final DisplayBlanker mDisplayBlanker;
+
+    // Our handler.
+    private final DisplayControllerHandler mHandler;
+
+    // Asynchronous callbacks into the power manager service.
+    // Only invoked from the handler thread while no locks are held.
+    private final Callbacks mCallbacks;
+    private Handler mCallbackHandler;
+
+    // The lights service.
+    private final LightsService mLights;
+
+    // The twilight service.
+    private final TwilightService mTwilight;
+
+    // The display manager.
+    private final DisplayManager mDisplayManager;
+
+    // The sensor manager.
+    private final SensorManager mSensorManager;
+
+    // The proximity sensor, or null if not available or needed.
+    private Sensor mProximitySensor;
+
+    // The light sensor, or null if not available or needed.
+    private Sensor mLightSensor;
+
+    // The dim screen brightness.
+    private final int mScreenBrightnessDimConfig;
+
+    // The minimum allowed brightness.
+    private final int mScreenBrightnessRangeMinimum;
+
+    // The maximum allowed brightness.
+    private final int mScreenBrightnessRangeMaximum;
+
+    // True if auto-brightness should be used.
+    private boolean mUseSoftwareAutoBrightnessConfig;
+
+    // The auto-brightness spline adjustment.
+    // The brightness values have been scaled to a range of 0..1.
+    private Spline mScreenAutoBrightnessSpline;
+
+    // Amount of time to delay auto-brightness after screen on while waiting for
+    // the light sensor to warm-up in milliseconds.
+    // May be 0 if no warm-up is required.
+    private int mLightSensorWarmUpTimeConfig;
+
+    // True if we should fade the screen while turning it off, false if we should play
+    // a stylish electron beam animation instead.
+    private boolean mElectronBeamFadesConfig;
+
+    // The pending power request.
+    // Initially null until the first call to requestPowerState.
+    // Guarded by mLock.
+    private DisplayPowerRequest mPendingRequestLocked;
+
+    // True if a request has been made to wait for the proximity sensor to go negative.
+    // Guarded by mLock.
+    private boolean mPendingWaitForNegativeProximityLocked;
+
+    // True if the pending power request or wait for negative proximity flag
+    // has been changed since the last update occurred.
+    // Guarded by mLock.
+    private boolean mPendingRequestChangedLocked;
+
+    // Set to true when the important parts of the pending power request have been applied.
+    // The important parts are mainly the screen state.  Brightness changes may occur
+    // concurrently.
+    // Guarded by mLock.
+    private boolean mDisplayReadyLocked;
+
+    // Set to true if a power state update is required.
+    // Guarded by mLock.
+    private boolean mPendingUpdatePowerStateLocked;
+
+    /* The following state must only be accessed by the handler thread. */
+
+    // The currently requested power state.
+    // The power controller will progressively update its internal state to match
+    // the requested power state.  Initially null until the first update.
+    private DisplayPowerRequest mPowerRequest;
+
+    // The current power state.
+    // Must only be accessed on the handler thread.
+    private DisplayPowerState mPowerState;
+
+    // True if the device should wait for negative proximity sensor before
+    // waking up the screen.  This is set to false as soon as a negative
+    // proximity sensor measurement is observed or when the device is forced to
+    // go to sleep by the user.  While true, the screen remains off.
+    private boolean mWaitingForNegativeProximity;
+
+    // The actual proximity sensor threshold value.
+    private float mProximityThreshold;
+
+    // Set to true if the proximity sensor listener has been registered
+    // with the sensor manager.
+    private boolean mProximitySensorEnabled;
+
+    // The debounced proximity sensor state.
+    private int mProximity = PROXIMITY_UNKNOWN;
+
+    // The raw non-debounced proximity sensor state.
+    private int mPendingProximity = PROXIMITY_UNKNOWN;
+    private long mPendingProximityDebounceTime;
+
+    // True if the screen was turned off because of the proximity sensor.
+    // When the screen turns on again, we report user activity to the power manager.
+    private boolean mScreenOffBecauseOfProximity;
+
+    // True if the screen on is being blocked.
+    private boolean mScreenOnWasBlocked;
+
+    // The elapsed real time when the screen on was blocked.
+    private long mScreenOnBlockStartRealTime;
+
+    // Set to true if the light sensor is enabled.
+    private boolean mLightSensorEnabled;
+
+    // The time when the light sensor was enabled.
+    private long mLightSensorEnableTime;
+
+    // The currently accepted nominal ambient light level.
+    private float mAmbientLux;
+
+    // True if mAmbientLux holds a valid value.
+    private boolean mAmbientLuxValid;
+
+    // The most recent light sample.
+    private float mLastObservedLux;
+
+    // The time of the most light recent sample.
+    private long mLastObservedLuxTime;
+
+    // The number of light samples collected since the light sensor was enabled.
+    private int mRecentLightSamples;
+
+    // The long-term and short-term filtered light measurements.
+    private float mRecentShortTermAverageLux;
+    private float mRecentLongTermAverageLux;
+
+    // The direction in which the average lux is moving relative to the current ambient lux.
+    //    0 if not changing or within hysteresis threshold.
+    //    1 if brightening beyond hysteresis threshold.
+    //   -1 if darkening beyond hysteresis threshold.
+    private int mDebounceLuxDirection;
+
+    // The time when the average lux last changed direction.
+    private long mDebounceLuxTime;
+
+    // The screen brightness level that has been chosen by the auto-brightness
+    // algorithm.  The actual brightness should ramp towards this value.
+    // We preserve this value even when we stop using the light sensor so
+    // that we can quickly revert to the previous auto-brightness level
+    // while the light sensor warms up.
+    // Use -1 if there is no current auto-brightness value available.
+    private int mScreenAutoBrightness = -1;
+
+    // The last screen auto-brightness gamma.  (For printing in dump() only.)
+    private float mLastScreenAutoBrightnessGamma = 1.0f;
+
+    // True if the screen auto-brightness value is actually being used to
+    // set the display brightness.
+    private boolean mUsingScreenAutoBrightness;
+
+    // Animators.
+    private ObjectAnimator mElectronBeamOnAnimator;
+    private ObjectAnimator mElectronBeamOffAnimator;
+    private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
+
+    // Twilight changed.  We might recalculate auto-brightness values.
+    private boolean mTwilightChanged;
+
+    /**
+     * Creates the display power controller.
+     */
+    public DisplayPowerController(Looper looper, Context context, Notifier notifier,
+            LightsService lights, TwilightService twilight,
+            DisplayBlanker displayBlanker,
+            Callbacks callbacks, Handler callbackHandler) {
+        mHandler = new DisplayControllerHandler(looper);
+        mNotifier = notifier;
+        mDisplayBlanker = displayBlanker;
+        mCallbacks = callbacks;
+        mCallbackHandler = callbackHandler;
+
+        mLights = lights;
+        mTwilight = twilight;
+        mSensorManager = new SystemSensorManager(mHandler.getLooper());
+        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
+
+        final Resources resources = context.getResources();
+
+        mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger(
+                com.android.internal.R.integer.config_screenBrightnessDim));
+
+        int screenBrightnessMinimum = Math.min(resources.getInteger(
+                com.android.internal.R.integer.config_screenBrightnessSettingMinimum),
+                mScreenBrightnessDimConfig);
+
+        mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
+                com.android.internal.R.bool.config_automatic_brightness_available);
+        if (mUseSoftwareAutoBrightnessConfig) {
+            int[] lux = resources.getIntArray(
+                    com.android.internal.R.array.config_autoBrightnessLevels);
+            int[] screenBrightness = resources.getIntArray(
+                    com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
+
+            mScreenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness);
+            if (mScreenAutoBrightnessSpline == null) {
+                Slog.e(TAG, "Error in config.xml.  config_autoBrightnessLcdBacklightValues "
+                        + "(size " + screenBrightness.length + ") "
+                        + "must be monotic and have exactly one more entry than "
+                        + "config_autoBrightnessLevels (size " + lux.length + ") "
+                        + "which must be strictly increasing.  "
+                        + "Auto-brightness will be disabled.");
+                mUseSoftwareAutoBrightnessConfig = false;
+            } else {
+                if (screenBrightness[0] < screenBrightnessMinimum) {
+                    screenBrightnessMinimum = screenBrightness[0];
+                }
+            }
+
+            mLightSensorWarmUpTimeConfig = resources.getInteger(
+                    com.android.internal.R.integer.config_lightSensorWarmupTime);
+        }
+
+        mScreenBrightnessRangeMinimum = clampAbsoluteBrightness(screenBrightnessMinimum);
+        mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON;
+
+        mElectronBeamFadesConfig = resources.getBoolean(
+                com.android.internal.R.bool.config_animateScreenLights);
+
+        if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
+            mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
+            if (mProximitySensor != null) {
+                mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
+                        TYPICAL_PROXIMITY_THRESHOLD);
+            }
+        }
+
+        if (mUseSoftwareAutoBrightnessConfig
+                && !DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {
+            mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
+        }
+
+        if (mUseSoftwareAutoBrightnessConfig && USE_TWILIGHT_ADJUSTMENT) {
+            mTwilight.registerListener(mTwilightListener, mHandler);
+        }
+    }
+
+    private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) {
+        try {
+            final int n = brightness.length;
+            float[] x = new float[n];
+            float[] y = new float[n];
+            y[0] = normalizeAbsoluteBrightness(brightness[0]);
+            for (int i = 1; i < n; i++) {
+                x[i] = lux[i - 1];
+                y[i] = normalizeAbsoluteBrightness(brightness[i]);
+            }
+
+            Spline spline = Spline.createMonotoneCubicSpline(x, y);
+            if (DEBUG) {
+                Slog.d(TAG, "Auto-brightness spline: " + spline);
+                for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) {
+                    Slog.d(TAG, String.format("  %7.1f: %7.1f", v, spline.interpolate(v)));
+                }
+            }
+            return spline;
+        } catch (IllegalArgumentException ex) {
+            Slog.e(TAG, "Could not create auto-brightness spline.", ex);
+            return null;
+        }
+    }
+
+    /**
+     * Returns true if the proximity sensor screen-off function is available.
+     */
+    public boolean isProximitySensorAvailable() {
+        return mProximitySensor != null;
+    }
+
+    /**
+     * Requests a new power state.
+     * The controller makes a copy of the provided object and then
+     * begins adjusting the power state to match what was requested.
+     *
+     * @param request The requested power state.
+     * @param waitForNegativeProximity If true, issues a request to wait for
+     * negative proximity before turning the screen back on, assuming the screen
+     * was turned off by the proximity sensor.
+     * @return True if display is ready, false if there are important changes that must
+     * be made asynchronously (such as turning the screen on), in which case the caller
+     * should grab a wake lock, watch for {@link Callbacks#onStateChanged()} then try
+     * the request again later until the state converges.
+     */
+    public boolean requestPowerState(DisplayPowerRequest request,
+            boolean waitForNegativeProximity) {
+        if (DEBUG) {
+            Slog.d(TAG, "requestPowerState: "
+                    + request + ", waitForNegativeProximity=" + waitForNegativeProximity);
+        }
+
+        synchronized (mLock) {
+            boolean changed = false;
+
+            if (waitForNegativeProximity
+                    && !mPendingWaitForNegativeProximityLocked) {
+                mPendingWaitForNegativeProximityLocked = true;
+                changed = true;
+            }
+
+            if (mPendingRequestLocked == null) {
+                mPendingRequestLocked = new DisplayPowerRequest(request);
+                changed = true;
+            } else if (!mPendingRequestLocked.equals(request)) {
+                mPendingRequestLocked.copyFrom(request);
+                changed = true;
+            }
+
+            if (changed) {
+                mDisplayReadyLocked = false;
+            }
+
+            if (changed && !mPendingRequestChangedLocked) {
+                mPendingRequestChangedLocked = true;
+                sendUpdatePowerStateLocked();
+            }
+
+            return mDisplayReadyLocked;
+        }
+    }
+
+    private void sendUpdatePowerState() {
+        synchronized (mLock) {
+            sendUpdatePowerStateLocked();
+        }
+    }
+
+    private void sendUpdatePowerStateLocked() {
+        if (!mPendingUpdatePowerStateLocked) {
+            mPendingUpdatePowerStateLocked = true;
+            Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
+            msg.setAsynchronous(true);
+            mHandler.sendMessage(msg);
+        }
+    }
+
+    private void initialize() {
+        Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
+        mPowerState = new DisplayPowerState(
+                new ElectronBeam(display), mDisplayBlanker,
+                mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT));
+
+        mElectronBeamOnAnimator = ObjectAnimator.ofFloat(
+                mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f);
+        mElectronBeamOnAnimator.setDuration(ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS);
+        mElectronBeamOnAnimator.addListener(mAnimatorListener);
+
+        mElectronBeamOffAnimator = ObjectAnimator.ofFloat(
+                mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 1.0f, 0.0f);
+        mElectronBeamOffAnimator.setDuration(ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS);
+        mElectronBeamOffAnimator.addListener(mAnimatorListener);
+
+        mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
+                mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
+    }
+
+    private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
+        @Override
+        public void onAnimationStart(Animator animation) {
+        }
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            sendUpdatePowerState();
+        }
+        @Override
+        public void onAnimationRepeat(Animator animation) {
+        }
+        @Override
+        public void onAnimationCancel(Animator animation) {
+        }
+    };
+
+    private void updatePowerState() {
+        // Update the power state request.
+        final boolean mustNotify;
+        boolean mustInitialize = false;
+        boolean updateAutoBrightness = mTwilightChanged;
+        boolean wasDim = false;
+        mTwilightChanged = false;
+
+        synchronized (mLock) {
+            mPendingUpdatePowerStateLocked = false;
+            if (mPendingRequestLocked == null) {
+                return; // wait until first actual power request
+            }
+
+            if (mPowerRequest == null) {
+                mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
+                mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
+                mPendingWaitForNegativeProximityLocked = false;
+                mPendingRequestChangedLocked = false;
+                mustInitialize = true;
+            } else if (mPendingRequestChangedLocked) {
+                if (mPowerRequest.screenAutoBrightnessAdjustment
+                        != mPendingRequestLocked.screenAutoBrightnessAdjustment) {
+                    updateAutoBrightness = true;
+                }
+                wasDim = (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM);
+                mPowerRequest.copyFrom(mPendingRequestLocked);
+                mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
+                mPendingWaitForNegativeProximityLocked = false;
+                mPendingRequestChangedLocked = false;
+                mDisplayReadyLocked = false;
+            }
+
+            mustNotify = !mDisplayReadyLocked;
+        }
+
+        // Initialize things the first time the power state is changed.
+        if (mustInitialize) {
+            initialize();
+        }
+
+        // Apply the proximity sensor.
+        if (mProximitySensor != null) {
+            if (mPowerRequest.useProximitySensor
+                    && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
+                setProximitySensorEnabled(true);
+                if (!mScreenOffBecauseOfProximity
+                        && mProximity == PROXIMITY_POSITIVE) {
+                    mScreenOffBecauseOfProximity = true;
+                    sendOnProximityPositive();
+                    setScreenOn(false);
+                }
+            } else if (mWaitingForNegativeProximity
+                    && mScreenOffBecauseOfProximity
+                    && mProximity == PROXIMITY_POSITIVE
+                    && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
+                setProximitySensorEnabled(true);
+            } else {
+                setProximitySensorEnabled(false);
+                mWaitingForNegativeProximity = false;
+            }
+            if (mScreenOffBecauseOfProximity
+                    && mProximity != PROXIMITY_POSITIVE) {
+                mScreenOffBecauseOfProximity = false;
+                sendOnProximityNegative();
+            }
+        } else {
+            mWaitingForNegativeProximity = false;
+        }
+
+        // Turn on the light sensor if needed.
+        if (mLightSensor != null) {
+            setLightSensorEnabled(mPowerRequest.useAutoBrightness
+                    && wantScreenOn(mPowerRequest.screenState), updateAutoBrightness);
+        }
+
+        // Set the screen brightness.
+        if (wantScreenOn(mPowerRequest.screenState)) {
+            int target;
+            boolean slow;
+            if (mScreenAutoBrightness >= 0 && mLightSensorEnabled) {
+                // Use current auto-brightness value.
+                target = mScreenAutoBrightness;
+                slow = mUsingScreenAutoBrightness;
+                mUsingScreenAutoBrightness = true;
+            } else {
+                // Light sensor is disabled or not ready yet.
+                // Use the current brightness setting from the request, which is expected
+                // provide a nominal default value for the case where auto-brightness
+                // is not ready yet.
+                target = mPowerRequest.screenBrightness;
+                slow = false;
+                mUsingScreenAutoBrightness = false;
+            }
+            if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) {
+                // Dim quickly by at least some minimum amount.
+                target = Math.min(target - SCREEN_DIM_MINIMUM_REDUCTION,
+                        mScreenBrightnessDimConfig);
+                slow = false;
+            } else if (wasDim) {
+                // Brighten quickly.
+                slow = false;
+            }
+            animateScreenBrightness(clampScreenBrightness(target),
+                    slow ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
+        } else {
+            // Screen is off.  Don't bother changing the brightness.
+            mUsingScreenAutoBrightness = false;
+        }
+
+        // Animate the screen on or off.
+        if (!mScreenOffBecauseOfProximity) {
+            if (wantScreenOn(mPowerRequest.screenState)) {
+                // Want screen on.
+                // Wait for previous off animation to complete beforehand.
+                // It is relatively short but if we cancel it and switch to the
+                // on animation immediately then the results are pretty ugly.
+                if (!mElectronBeamOffAnimator.isStarted()) {
+                    // Turn the screen on.  The contents of the screen may not yet
+                    // be visible if the electron beam has not been dismissed because
+                    // its last frame of animation is solid black.
+                    setScreenOn(true);
+
+                    if (mPowerRequest.blockScreenOn
+                            && mPowerState.getElectronBeamLevel() == 0.0f) {
+                        blockScreenOn();
+                    } else {
+                        unblockScreenOn();
+                        if (USE_ELECTRON_BEAM_ON_ANIMATION) {
+                            if (!mElectronBeamOnAnimator.isStarted()) {
+                                if (mPowerState.getElectronBeamLevel() == 1.0f) {
+                                    mPowerState.dismissElectronBeam();
+                                } else if (mPowerState.prepareElectronBeam(
+                                        mElectronBeamFadesConfig ?
+                                                ElectronBeam.MODE_FADE :
+                                                        ElectronBeam.MODE_WARM_UP)) {
+                                    mElectronBeamOnAnimator.start();
+                                } else {
+                                    mElectronBeamOnAnimator.end();
+                                }
+                            }
+                        } else {
+                            mPowerState.setElectronBeamLevel(1.0f);
+                            mPowerState.dismissElectronBeam();
+                        }
+                    }
+                }
+            } else {
+                // Want screen off.
+                // Wait for previous on animation to complete beforehand.
+                if (!mElectronBeamOnAnimator.isStarted()) {
+                    if (!mElectronBeamOffAnimator.isStarted()) {
+                        if (mPowerState.getElectronBeamLevel() == 0.0f) {
+                            setScreenOn(false);
+                        } else if (mPowerState.prepareElectronBeam(
+                                mElectronBeamFadesConfig ?
+                                        ElectronBeam.MODE_FADE :
+                                                ElectronBeam.MODE_COOL_DOWN)
+                                && mPowerState.isScreenOn()) {
+                            mElectronBeamOffAnimator.start();
+                        } else {
+                            mElectronBeamOffAnimator.end();
+                        }
+                    }
+                }
+            }
+        }
+
+        // Report whether the display is ready for use.
+        // We mostly care about the screen state here, ignoring brightness changes
+        // which will be handled asynchronously.
+        if (mustNotify
+                && !mScreenOnWasBlocked
+                && !mElectronBeamOnAnimator.isStarted()
+                && !mElectronBeamOffAnimator.isStarted()
+                && mPowerState.waitUntilClean(mCleanListener)) {
+            synchronized (mLock) {
+                if (!mPendingRequestChangedLocked) {
+                    mDisplayReadyLocked = true;
+
+                    if (DEBUG) {
+                        Slog.d(TAG, "Display ready!");
+                    }
+                }
+            }
+            sendOnStateChanged();
+        }
+    }
+
+    private void blockScreenOn() {
+        if (!mScreenOnWasBlocked) {
+            mScreenOnWasBlocked = true;
+            if (DEBUG) {
+                Slog.d(TAG, "Blocked screen on.");
+                mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
+            }
+        }
+    }
+
+    private void unblockScreenOn() {
+        if (mScreenOnWasBlocked) {
+            mScreenOnWasBlocked = false;
+            if (DEBUG) {
+                Slog.d(TAG, "Unblocked screen on after " +
+                        (SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime) + " ms");
+            }
+        }
+    }
+
+    private void setScreenOn(boolean on) {
+        if (!mPowerState.isScreenOn() == on) {
+            mPowerState.setScreenOn(on);
+            if (on) {
+                mNotifier.onScreenOn();
+            } else {
+                mNotifier.onScreenOff();
+            }
+        }
+    }
+
+    private int clampScreenBrightness(int value) {
+        return clamp(value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
+    }
+
+    private static int clampAbsoluteBrightness(int value) {
+        return clamp(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
+    }
+
+    private static int clamp(int value, int min, int max) {
+        if (value <= min) {
+            return min;
+        }
+        if (value >= max) {
+            return max;
+        }
+        return value;
+    }
+
+    private static float normalizeAbsoluteBrightness(int value) {
+        return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON;
+    }
+
+    private void animateScreenBrightness(int target, int rate) {
+        if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
+            mNotifier.onScreenBrightness(target);
+        }
+    }
+
+    private final Runnable mCleanListener = new Runnable() {
+        @Override
+        public void run() {
+            sendUpdatePowerState();
+        }
+    };
+
+    private void setProximitySensorEnabled(boolean enable) {
+        if (enable) {
+            if (!mProximitySensorEnabled) {
+                mProximitySensorEnabled = true;
+                mPendingProximity = PROXIMITY_UNKNOWN;
+                mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
+                        SensorManager.SENSOR_DELAY_NORMAL, mHandler);
+            }
+        } else {
+            if (mProximitySensorEnabled) {
+                mProximitySensorEnabled = false;
+                mProximity = PROXIMITY_UNKNOWN;
+                mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
+                mSensorManager.unregisterListener(mProximitySensorListener);
+            }
+        }
+    }
+
+    private void handleProximitySensorEvent(long time, boolean positive) {
+        if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
+            return; // no change
+        }
+        if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
+            return; // no change
+        }
+
+        // Only accept a proximity sensor reading if it remains
+        // stable for the entire debounce delay.
+        mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
+        if (positive) {
+            mPendingProximity = PROXIMITY_POSITIVE;
+            mPendingProximityDebounceTime = time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY;
+        } else {
+            mPendingProximity = PROXIMITY_NEGATIVE;
+            mPendingProximityDebounceTime = time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY;
+        }
+        debounceProximitySensor();
+    }
+
+    private void debounceProximitySensor() {
+        if (mPendingProximity != PROXIMITY_UNKNOWN) {
+            final long now = SystemClock.uptimeMillis();
+            if (mPendingProximityDebounceTime <= now) {
+                mProximity = mPendingProximity;
+                sendUpdatePowerState();
+            } else {
+                Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
+                msg.setAsynchronous(true);
+                mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
+            }
+        }
+    }
+
+    private void setLightSensorEnabled(boolean enable, boolean updateAutoBrightness) {
+        if (enable) {
+            if (!mLightSensorEnabled) {
+                updateAutoBrightness = true;
+                mLightSensorEnabled = true;
+                mLightSensorEnableTime = SystemClock.uptimeMillis();
+                mSensorManager.registerListener(mLightSensorListener, mLightSensor,
+                        LIGHT_SENSOR_RATE_MILLIS * 1000, mHandler);
+            }
+        } else {
+            if (mLightSensorEnabled) {
+                mLightSensorEnabled = false;
+                mAmbientLuxValid = false;
+                mRecentLightSamples = 0;
+                mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
+                mSensorManager.unregisterListener(mLightSensorListener);
+            }
+        }
+        if (updateAutoBrightness) {
+            updateAutoBrightness(false);
+        }
+    }
+
+    private void handleLightSensorEvent(long time, float lux) {
+        mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
+
+        applyLightSensorMeasurement(time, lux);
+        updateAmbientLux(time);
+    }
+
+    private void applyLightSensorMeasurement(long time, float lux) {
+        // Update our filters.
+        mRecentLightSamples += 1;
+        if (mRecentLightSamples == 1) {
+            mRecentShortTermAverageLux = lux;
+            mRecentLongTermAverageLux = lux;
+        } else {
+            final long timeDelta = time - mLastObservedLuxTime;
+            mRecentShortTermAverageLux += (lux - mRecentShortTermAverageLux)
+                    * timeDelta / (SHORT_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta);
+            mRecentLongTermAverageLux += (lux - mRecentLongTermAverageLux)
+                    * timeDelta / (LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta);
+        }
+
+        // Remember this sample value.
+        mLastObservedLux = lux;
+        mLastObservedLuxTime = time;
+    }
+
+    private void updateAmbientLux(long time) {
+        // If the light sensor was just turned on then immediately update our initial
+        // estimate of the current ambient light level.
+        if (!mAmbientLuxValid
+                || (time - mLightSensorEnableTime) < mLightSensorWarmUpTimeConfig) {
+            mAmbientLux = mRecentShortTermAverageLux;
+            mAmbientLuxValid = true;
+            mDebounceLuxDirection = 0;
+            mDebounceLuxTime = time;
+            if (DEBUG) {
+                Slog.d(TAG, "updateAmbientLux: Initializing: "
+                        + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
+                        + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
+                        + ", mAmbientLux=" + mAmbientLux);
+            }
+            updateAutoBrightness(true);
+            return;
+        }
+
+        // Determine whether the ambient environment appears to be brightening.
+        float brighteningLuxThreshold = mAmbientLux * (1.0f + BRIGHTENING_LIGHT_HYSTERESIS);
+        if (mRecentShortTermAverageLux > brighteningLuxThreshold
+                && mRecentLongTermAverageLux > brighteningLuxThreshold) {
+            if (mDebounceLuxDirection <= 0) {
+                mDebounceLuxDirection = 1;
+                mDebounceLuxTime = time;
+                if (DEBUG) {
+                    Slog.d(TAG, "updateAmbientLux: Possibly brightened, waiting for "
+                            + BRIGHTENING_LIGHT_DEBOUNCE + " ms: "
+                            + "brighteningLuxThreshold=" + brighteningLuxThreshold
+                            + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
+                            + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
+                            + ", mAmbientLux=" + mAmbientLux);
+                }
+            }
+            long debounceTime = mDebounceLuxTime + BRIGHTENING_LIGHT_DEBOUNCE;
+            if (time >= debounceTime) {
+                mAmbientLux = mRecentShortTermAverageLux;
+                if (DEBUG) {
+                    Slog.d(TAG, "updateAmbientLux: Brightened: "
+                            + "brighteningLuxThreshold=" + brighteningLuxThreshold
+                            + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
+                            + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
+                            + ", mAmbientLux=" + mAmbientLux);
+                }
+                updateAutoBrightness(true);
+            } else {
+                mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime);
+            }
+            return;
+        }
+
+        // Determine whether the ambient environment appears to be darkening.
+        float darkeningLuxThreshold = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS);
+        if (mRecentShortTermAverageLux < darkeningLuxThreshold
+                && mRecentLongTermAverageLux < darkeningLuxThreshold) {
+            if (mDebounceLuxDirection >= 0) {
+                mDebounceLuxDirection = -1;
+                mDebounceLuxTime = time;
+                if (DEBUG) {
+                    Slog.d(TAG, "updateAmbientLux: Possibly darkened, waiting for "
+                            + DARKENING_LIGHT_DEBOUNCE + " ms: "
+                            + "darkeningLuxThreshold=" + darkeningLuxThreshold
+                            + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
+                            + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
+                            + ", mAmbientLux=" + mAmbientLux);
+                }
+            }
+            long debounceTime = mDebounceLuxTime + DARKENING_LIGHT_DEBOUNCE;
+            if (time >= debounceTime) {
+                // Be conservative about reducing the brightness, only reduce it a little bit
+                // at a time to avoid having to bump it up again soon.
+                mAmbientLux = Math.max(mRecentShortTermAverageLux, mRecentLongTermAverageLux);
+                if (DEBUG) {
+                    Slog.d(TAG, "updateAmbientLux: Darkened: "
+                            + "darkeningLuxThreshold=" + darkeningLuxThreshold
+                            + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
+                            + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
+                            + ", mAmbientLux=" + mAmbientLux);
+                }
+                updateAutoBrightness(true);
+            } else {
+                mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime);
+            }
+            return;
+        }
+
+        // No change or change is within the hysteresis thresholds.
+        if (mDebounceLuxDirection != 0) {
+            mDebounceLuxDirection = 0;
+            mDebounceLuxTime = time;
+            if (DEBUG) {
+                Slog.d(TAG, "updateAmbientLux: Canceled debounce: "
+                        + "brighteningLuxThreshold=" + brighteningLuxThreshold
+                        + ", darkeningLuxThreshold=" + darkeningLuxThreshold
+                        + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
+                        + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
+                        + ", mAmbientLux=" + mAmbientLux);
+            }
+        }
+
+        // If the light level does not change, then the sensor may not report
+        // a new value.  This can cause problems for the auto-brightness algorithm
+        // because the filters might not be updated.  To work around it, we want to
+        // make sure to update the filters whenever the observed light level could
+        // possibly exceed one of the hysteresis thresholds.
+        if (mLastObservedLux > brighteningLuxThreshold
+                || mLastObservedLux < darkeningLuxThreshold) {
+            mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED,
+                    time + SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS);
+        }
+    }
+
+    private void debounceLightSensor() {
+        if (mLightSensorEnabled) {
+            long time = SystemClock.uptimeMillis();
+            if (time >= mLastObservedLuxTime + SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS) {
+                if (DEBUG) {
+                    Slog.d(TAG, "debounceLightSensor: Synthesizing light sensor measurement "
+                            + "after " + (time - mLastObservedLuxTime) + " ms.");
+                }
+                applyLightSensorMeasurement(time, mLastObservedLux);
+            }
+            updateAmbientLux(time);
+        }
+    }
+
+    private void updateAutoBrightness(boolean sendUpdate) {
+        if (!mAmbientLuxValid) {
+            return;
+        }
+
+        float value = mScreenAutoBrightnessSpline.interpolate(mAmbientLux);
+        float gamma = 1.0f;
+
+        if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT
+                && mPowerRequest.screenAutoBrightnessAdjustment != 0.0f) {
+            final float adjGamma = FloatMath.pow(SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA,
+                    Math.min(1.0f, Math.max(-1.0f,
+                            -mPowerRequest.screenAutoBrightnessAdjustment)));
+            gamma *= adjGamma;
+            if (DEBUG) {
+                Slog.d(TAG, "updateAutoBrightness: adjGamma=" + adjGamma);
+            }
+        }
+
+        if (USE_TWILIGHT_ADJUSTMENT) {
+            TwilightState state = mTwilight.getCurrentState();
+            if (state != null && state.isNight()) {
+                final long now = System.currentTimeMillis();
+                final float earlyGamma =
+                        getTwilightGamma(now, state.getYesterdaySunset(), state.getTodaySunrise());
+                final float lateGamma =
+                        getTwilightGamma(now, state.getTodaySunset(), state.getTomorrowSunrise());
+                gamma *= earlyGamma * lateGamma;
+                if (DEBUG) {
+                    Slog.d(TAG, "updateAutoBrightness: earlyGamma=" + earlyGamma
+                            + ", lateGamma=" + lateGamma);
+                }
+            }
+        }
+
+        if (gamma != 1.0f) {
+            final float in = value;
+            value = FloatMath.pow(value, gamma);
+            if (DEBUG) {
+                Slog.d(TAG, "updateAutoBrightness: gamma=" + gamma
+                        + ", in=" + in + ", out=" + value);
+            }
+        }
+
+        int newScreenAutoBrightness = clampScreenBrightness(
+                Math.round(value * PowerManager.BRIGHTNESS_ON));
+        if (mScreenAutoBrightness != newScreenAutoBrightness) {
+            if (DEBUG) {
+                Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness="
+                        + mScreenAutoBrightness + ", newScreenAutoBrightness="
+                        + newScreenAutoBrightness);
+            }
+
+            mScreenAutoBrightness = newScreenAutoBrightness;
+            mLastScreenAutoBrightnessGamma = gamma;
+            if (sendUpdate) {
+                sendUpdatePowerState();
+            }
+        }
+    }
+
+    private static float getTwilightGamma(long now, long lastSunset, long nextSunrise) {
+        if (lastSunset < 0 || nextSunrise < 0
+                || now < lastSunset || now > nextSunrise) {
+            return 1.0f;
+        }
+
+        if (now < lastSunset + TWILIGHT_ADJUSTMENT_TIME) {
+            return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
+                    (float)(now - lastSunset) / TWILIGHT_ADJUSTMENT_TIME);
+        }
+
+        if (now > nextSunrise - TWILIGHT_ADJUSTMENT_TIME) {
+            return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
+                    (float)(nextSunrise - now) / TWILIGHT_ADJUSTMENT_TIME);
+        }
+
+        return TWILIGHT_ADJUSTMENT_MAX_GAMMA;
+    }
+
+    private static float lerp(float x, float y, float alpha) {
+        return x + (y - x) * alpha;
+    }
+
+    private void sendOnStateChanged() {
+        mCallbackHandler.post(mOnStateChangedRunnable);
+    }
+
+    private final Runnable mOnStateChangedRunnable = new Runnable() {
+        @Override
+        public void run() {
+            mCallbacks.onStateChanged();
+        }
+    };
+
+    private void sendOnProximityPositive() {
+        mCallbackHandler.post(mOnProximityPositiveRunnable);
+    }
+
+    private final Runnable mOnProximityPositiveRunnable = new Runnable() {
+        @Override
+        public void run() {
+            mCallbacks.onProximityPositive();
+        }
+    };
+
+    private void sendOnProximityNegative() {
+        mCallbackHandler.post(mOnProximityNegativeRunnable);
+    }
+
+    private final Runnable mOnProximityNegativeRunnable = new Runnable() {
+        @Override
+        public void run() {
+            mCallbacks.onProximityNegative();
+        }
+    };
+
+    public void dump(final PrintWriter pw) {
+        synchronized (mLock) {
+            pw.println();
+            pw.println("Display Controller Locked State:");
+            pw.println("  mDisplayReadyLocked=" + mDisplayReadyLocked);
+            pw.println("  mPendingRequestLocked=" + mPendingRequestLocked);
+            pw.println("  mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
+            pw.println("  mPendingWaitForNegativeProximityLocked="
+                    + mPendingWaitForNegativeProximityLocked);
+            pw.println("  mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
+        }
+
+        pw.println();
+        pw.println("Display Controller Configuration:");
+        pw.println("  mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
+        pw.println("  mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
+        pw.println("  mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
+        pw.println("  mUseSoftwareAutoBrightnessConfig="
+                + mUseSoftwareAutoBrightnessConfig);
+        pw.println("  mScreenAutoBrightnessSpline=" + mScreenAutoBrightnessSpline);
+        pw.println("  mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig);
+
+        mHandler.runWithScissors(new Runnable() {
+            @Override
+            public void run() {
+                dumpLocal(pw);
+            }
+        }, 1000);
+    }
+
+    private void dumpLocal(PrintWriter pw) {
+        pw.println();
+        pw.println("Display Controller Thread State:");
+        pw.println("  mPowerRequest=" + mPowerRequest);
+        pw.println("  mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);
+
+        pw.println("  mProximitySensor=" + mProximitySensor);
+        pw.println("  mProximitySensorEnabled=" + mProximitySensorEnabled);
+        pw.println("  mProximityThreshold=" + mProximityThreshold);
+        pw.println("  mProximity=" + proximityToString(mProximity));
+        pw.println("  mPendingProximity=" + proximityToString(mPendingProximity));
+        pw.println("  mPendingProximityDebounceTime="
+                + TimeUtils.formatUptime(mPendingProximityDebounceTime));
+        pw.println("  mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
+
+        pw.println("  mLightSensor=" + mLightSensor);
+        pw.println("  mLightSensorEnabled=" + mLightSensorEnabled);
+        pw.println("  mLightSensorEnableTime="
+                + TimeUtils.formatUptime(mLightSensorEnableTime));
+        pw.println("  mAmbientLux=" + mAmbientLux);
+        pw.println("  mAmbientLuxValid=" + mAmbientLuxValid);
+        pw.println("  mLastObservedLux=" + mLastObservedLux);
+        pw.println("  mLastObservedLuxTime="
+                + TimeUtils.formatUptime(mLastObservedLuxTime));
+        pw.println("  mRecentLightSamples=" + mRecentLightSamples);
+        pw.println("  mRecentShortTermAverageLux=" + mRecentShortTermAverageLux);
+        pw.println("  mRecentLongTermAverageLux=" + mRecentLongTermAverageLux);
+        pw.println("  mDebounceLuxDirection=" + mDebounceLuxDirection);
+        pw.println("  mDebounceLuxTime=" + TimeUtils.formatUptime(mDebounceLuxTime));
+        pw.println("  mScreenAutoBrightness=" + mScreenAutoBrightness);
+        pw.println("  mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness);
+        pw.println("  mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma);
+        pw.println("  mTwilight.getCurrentState()=" + mTwilight.getCurrentState());
+
+        if (mElectronBeamOnAnimator != null) {
+            pw.println("  mElectronBeamOnAnimator.isStarted()=" +
+                    mElectronBeamOnAnimator.isStarted());
+        }
+        if (mElectronBeamOffAnimator != null) {
+            pw.println("  mElectronBeamOffAnimator.isStarted()=" +
+                    mElectronBeamOffAnimator.isStarted());
+        }
+
+        if (mPowerState != null) {
+            mPowerState.dump(pw);
+        }
+    }
+
+    private static String proximityToString(int state) {
+        switch (state) {
+            case PROXIMITY_UNKNOWN:
+                return "Unknown";
+            case PROXIMITY_NEGATIVE:
+                return "Negative";
+            case PROXIMITY_POSITIVE:
+                return "Positive";
+            default:
+                return Integer.toString(state);
+        }
+    }
+
+    private static boolean wantScreenOn(int state) {
+        switch (state) {
+            case DisplayPowerRequest.SCREEN_STATE_BRIGHT:
+            case DisplayPowerRequest.SCREEN_STATE_DIM:
+                return true;
+        }
+        return false;
+    }
+
+    /**
+     * Asynchronous callbacks from the power controller to the power manager service.
+     */
+    public interface Callbacks {
+        void onStateChanged();
+        void onProximityPositive();
+        void onProximityNegative();
+    }
+
+    private final class DisplayControllerHandler extends Handler {
+        public DisplayControllerHandler(Looper looper) {
+            super(looper, null, true /*async*/);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_UPDATE_POWER_STATE:
+                    updatePowerState();
+                    break;
+
+                case MSG_PROXIMITY_SENSOR_DEBOUNCED:
+                    debounceProximitySensor();
+                    break;
+
+                case MSG_LIGHT_SENSOR_DEBOUNCED:
+                    debounceLightSensor();
+                    break;
+            }
+        }
+    }
+
+    private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
+        @Override
+        public void onSensorChanged(SensorEvent event) {
+            if (mProximitySensorEnabled) {
+                final long time = SystemClock.uptimeMillis();
+                final float distance = event.values[0];
+                boolean positive = distance >= 0.0f && distance < mProximityThreshold;
+                handleProximitySensorEvent(time, positive);
+            }
+        }
+
+        @Override
+        public void onAccuracyChanged(Sensor sensor, int accuracy) {
+            // Not used.
+        }
+    };
+
+    private final SensorEventListener mLightSensorListener = new SensorEventListener() {
+        @Override
+        public void onSensorChanged(SensorEvent event) {
+            if (mLightSensorEnabled) {
+                final long time = SystemClock.uptimeMillis();
+                final float lux = event.values[0];
+                handleLightSensorEvent(time, lux);
+            }
+        }
+
+        @Override
+        public void onAccuracyChanged(Sensor sensor, int accuracy) {
+            // Not used.
+        }
+    };
+
+    private final TwilightService.TwilightListener mTwilightListener =
+            new TwilightService.TwilightListener() {
+        @Override
+        public void onTwilightStateChanged() {
+            mTwilightChanged = true;
+            updatePowerState();
+        }
+    };
+}
diff --git a/services/java/com/android/server/power/DisplayPowerRequest.java b/services/java/com/android/server/power/DisplayPowerRequest.java
new file mode 100644
index 0000000..22f17d7
--- /dev/null
+++ b/services/java/com/android/server/power/DisplayPowerRequest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.power;
+
+import android.os.PowerManager;
+
+/**
+ * Describes the requested power state of the display.
+ *
+ * This object is intended to describe the general characteristics of the
+ * power state, such as whether the screen should be on or off and the current
+ * brightness controls leaving the {@link DisplayPowerController} to manage the
+ * details of how the transitions between states should occur.  The goal is for
+ * the {@link PowerManagerService} to focus on the global power state and not
+ * have to micro-manage screen off animations, auto-brightness and other effects.
+ */
+final class DisplayPowerRequest {
+    public static final int SCREEN_STATE_OFF = 0;
+    public static final int SCREEN_STATE_DIM = 1;
+    public static final int SCREEN_STATE_BRIGHT = 2;
+
+    // The requested minimum screen power state: off, dim or bright.
+    public int screenState;
+
+    // If true, the proximity sensor overrides the screen state when an object is
+    // nearby, turning it off temporarily until the object is moved away.
+    public boolean useProximitySensor;
+
+    // The desired screen brightness in the range 0 (minimum / off) to 255 (brightest).
+    // The display power controller may choose to clamp the brightness.
+    // When auto-brightness is enabled, this field should specify a nominal default
+    // value to use while waiting for the light sensor to report enough data.
+    public int screenBrightness;
+
+    // The screen auto-brightness adjustment factor in the range -1 (dimmer) to 1 (brighter).
+    public float screenAutoBrightnessAdjustment;
+
+    // If true, enables automatic brightness control.
+    public boolean useAutoBrightness;
+
+    // If true, prevents the screen from completely turning on if it is currently off.
+    // The display does not enter a "ready" state if this flag is true and screen on is
+    // blocked.  The window manager policy blocks screen on while it prepares the keyguard to
+    // prevent the user from seeing intermediate updates.
+    //
+    // Technically, we may not block the screen itself from turning on (because that introduces
+    // extra unnecessary latency) but we do prevent content on screen from becoming
+    // visible to the user.
+    public boolean blockScreenOn;
+
+    public DisplayPowerRequest() {
+        screenState = SCREEN_STATE_BRIGHT;
+        useProximitySensor = false;
+        screenBrightness = PowerManager.BRIGHTNESS_ON;
+        screenAutoBrightnessAdjustment = 0.0f;
+        useAutoBrightness = false;
+        blockScreenOn = false;
+    }
+
+    public DisplayPowerRequest(DisplayPowerRequest other) {
+        copyFrom(other);
+    }
+
+    public void copyFrom(DisplayPowerRequest other) {
+        screenState = other.screenState;
+        useProximitySensor = other.useProximitySensor;
+        screenBrightness = other.screenBrightness;
+        screenAutoBrightnessAdjustment = other.screenAutoBrightnessAdjustment;
+        useAutoBrightness = other.useAutoBrightness;
+        blockScreenOn = other.blockScreenOn;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o instanceof DisplayPowerRequest
+                && equals((DisplayPowerRequest)o);
+    }
+
+    public boolean equals(DisplayPowerRequest other) {
+        return other != null
+                && screenState == other.screenState
+                && useProximitySensor == other.useProximitySensor
+                && screenBrightness == other.screenBrightness
+                && screenAutoBrightnessAdjustment == other.screenAutoBrightnessAdjustment
+                && useAutoBrightness == other.useAutoBrightness
+                && blockScreenOn == other.blockScreenOn;
+    }
+
+    @Override
+    public int hashCode() {
+        return 0; // don't care
+    }
+
+    @Override
+    public String toString() {
+        return "screenState=" + screenState
+                + ", useProximitySensor=" + useProximitySensor
+                + ", screenBrightness=" + screenBrightness
+                + ", screenAutoBrightnessAdjustment=" + screenAutoBrightnessAdjustment
+                + ", useAutoBrightness=" + useAutoBrightness
+                + ", blockScreenOn=" + blockScreenOn;
+    }
+}
diff --git a/services/java/com/android/server/power/DisplayPowerState.java b/services/java/com/android/server/power/DisplayPowerState.java
new file mode 100644
index 0000000..fa318f8b
--- /dev/null
+++ b/services/java/com/android/server/power/DisplayPowerState.java
@@ -0,0 +1,414 @@
+/*
+ * 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.power;
+
+import com.android.server.LightsService;
+
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.util.FloatProperty;
+import android.util.IntProperty;
+import android.util.Slog;
+import android.view.Choreographer;
+
+import java.io.PrintWriter;
+
+/**
+ * Controls the display power state.
+ * <p>
+ * This component is similar in nature to a {@link View} except that it describes
+ * the properties of a display.  When properties are changed, the component
+ * invalidates itself and posts a callback to apply the changes in a consistent order.
+ * This mechanism enables multiple properties of the display power state to be animated
+ * together smoothly by the animation framework.  Some of the work to blank or unblank
+ * the display is done on a separate thread to avoid blocking the looper.
+ * </p><p>
+ * This component must only be created or accessed by the {@link Looper} thread
+ * that belongs to the {@link DisplayPowerController}.
+ * </p><p>
+ * We don't need to worry about holding a suspend blocker here because the
+ * {@link PowerManagerService} does that for us whenever there is a change
+ * in progress.
+ * </p>
+ */
+final class DisplayPowerState {
+    private static final String TAG = "DisplayPowerState";
+
+    private static boolean DEBUG = false;
+
+    private final Handler mHandler;
+    private final Choreographer mChoreographer;
+    private final ElectronBeam mElectronBeam;
+    private final DisplayBlanker mDisplayBlanker;
+    private final LightsService.Light mBacklight;
+    private final PhotonicModulator mPhotonicModulator;
+
+    private boolean mScreenOn;
+    private int mScreenBrightness;
+    private boolean mScreenReady;
+    private boolean mScreenUpdatePending;
+
+    private boolean mElectronBeamPrepared;
+    private float mElectronBeamLevel;
+    private boolean mElectronBeamReady;
+    private boolean mElectronBeamDrawPending;
+
+    private Runnable mCleanListener;
+
+    public DisplayPowerState(ElectronBeam electronBean,
+            DisplayBlanker displayBlanker, LightsService.Light backlight) {
+        mHandler = new Handler(true /*async*/);
+        mChoreographer = Choreographer.getInstance();
+        mElectronBeam = electronBean;
+        mDisplayBlanker = displayBlanker;
+        mBacklight = backlight;
+        mPhotonicModulator = new PhotonicModulator();
+
+        // At boot time, we know that the screen is on and the electron beam
+        // animation is not playing.  We don't know the screen's brightness though,
+        // so prepare to set it to a known state when the state is next applied.
+        // Although we set the brightness to full on here, the display power controller
+        // will reset the brightness to a new level immediately before the changes
+        // actually have a chance to be applied.
+        mScreenOn = true;
+        mScreenBrightness = PowerManager.BRIGHTNESS_ON;
+        scheduleScreenUpdate();
+
+        mElectronBeamPrepared = false;
+        mElectronBeamLevel = 1.0f;
+        mElectronBeamReady = true;
+    }
+
+    public static final FloatProperty<DisplayPowerState> ELECTRON_BEAM_LEVEL =
+            new FloatProperty<DisplayPowerState>("electronBeamLevel") {
+        @Override
+        public void setValue(DisplayPowerState object, float value) {
+            object.setElectronBeamLevel(value);
+        }
+
+        @Override
+        public Float get(DisplayPowerState object) {
+            return object.getElectronBeamLevel();
+        }
+    };
+
+    public static final IntProperty<DisplayPowerState> SCREEN_BRIGHTNESS =
+            new IntProperty<DisplayPowerState>("screenBrightness") {
+        @Override
+        public void setValue(DisplayPowerState object, int value) {
+            object.setScreenBrightness(value);
+        }
+
+        @Override
+        public Integer get(DisplayPowerState object) {
+            return object.getScreenBrightness();
+        }
+    };
+
+    /**
+     * Sets whether the screen is on or off.
+     */
+    public void setScreenOn(boolean on) {
+        if (mScreenOn != on) {
+            if (DEBUG) {
+                Slog.d(TAG, "setScreenOn: on=" + on);
+            }
+
+            mScreenOn = on;
+            mScreenReady = false;
+            scheduleScreenUpdate();
+        }
+    }
+
+    /**
+     * Returns true if the screen is on.
+     */
+    public boolean isScreenOn() {
+        return mScreenOn;
+    }
+
+    /**
+     * Sets the display brightness.
+     *
+     * @param brightness The brightness, ranges from 0 (minimum / off) to 255 (brightest).
+     */
+    public void setScreenBrightness(int brightness) {
+        if (mScreenBrightness != brightness) {
+            if (DEBUG) {
+                Slog.d(TAG, "setScreenBrightness: brightness=" + brightness);
+            }
+
+            mScreenBrightness = brightness;
+            if (mScreenOn) {
+                mScreenReady = false;
+                scheduleScreenUpdate();
+            }
+        }
+    }
+
+    /**
+     * Gets the screen brightness.
+     */
+    public int getScreenBrightness() {
+        return mScreenBrightness;
+    }
+
+    /**
+     * Prepares the electron beam to turn on or off.
+     * This method should be called before starting an animation because it
+     * can take a fair amount of time to prepare the electron beam surface.
+     *
+     * @param mode The electron beam animation mode to prepare.
+     * @return True if the electron beam was prepared.
+     */
+    public boolean prepareElectronBeam(int mode) {
+        if (!mElectronBeam.prepare(mode)) {
+            mElectronBeamPrepared = false;
+            mElectronBeamReady = true;
+            return false;
+        }
+
+        mElectronBeamPrepared = true;
+        mElectronBeamReady = false;
+        scheduleElectronBeamDraw();
+        return true;
+    }
+
+    /**
+     * Dismisses the electron beam surface.
+     */
+    public void dismissElectronBeam() {
+        mElectronBeam.dismiss();
+        mElectronBeamPrepared = false;
+        mElectronBeamReady = true;
+    }
+
+    /**
+     * Sets the level of the electron beam steering current.
+     *
+     * The display is blanked when the level is 0.0.  In normal use, the electron
+     * beam should have a value of 1.0.  The electron beam is unstable in between
+     * these states and the picture quality may be compromised.  For best effect,
+     * the electron beam should be warmed up or cooled off slowly.
+     *
+     * Warning: Electron beam emits harmful radiation.  Avoid direct exposure to
+     * skin or eyes.
+     *
+     * @param level The level, ranges from 0.0 (full off) to 1.0 (full on).
+     */
+    public void setElectronBeamLevel(float level) {
+        if (mElectronBeamLevel != level) {
+            if (DEBUG) {
+                Slog.d(TAG, "setElectronBeamLevel: level=" + level);
+            }
+
+            mElectronBeamLevel = level;
+            if (mScreenOn) {
+                mScreenReady = false;
+                scheduleScreenUpdate(); // update backlight brightness
+            }
+            if (mElectronBeamPrepared) {
+                mElectronBeamReady = false;
+                scheduleElectronBeamDraw();
+            }
+        }
+    }
+
+    /**
+     * Gets the level of the electron beam steering current.
+     */
+    public float getElectronBeamLevel() {
+        return mElectronBeamLevel;
+    }
+
+    /**
+     * Returns true if no properties have been invalidated.
+     * Otherwise, returns false and promises to invoke the specified listener
+     * when the properties have all been applied.
+     * The listener always overrides any previously set listener.
+     */
+    public boolean waitUntilClean(Runnable listener) {
+        if (!mScreenReady || !mElectronBeamReady) {
+            mCleanListener = listener;
+            return false;
+        } else {
+            mCleanListener = null;
+            return true;
+        }
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.println();
+        pw.println("Display Power State:");
+        pw.println("  mScreenOn=" + mScreenOn);
+        pw.println("  mScreenBrightness=" + mScreenBrightness);
+        pw.println("  mScreenReady=" + mScreenReady);
+        pw.println("  mScreenUpdatePending=" + mScreenUpdatePending);
+        pw.println("  mElectronBeamPrepared=" + mElectronBeamPrepared);
+        pw.println("  mElectronBeamLevel=" + mElectronBeamLevel);
+        pw.println("  mElectronBeamReady=" + mElectronBeamReady);
+        pw.println("  mElectronBeamDrawPending=" + mElectronBeamDrawPending);
+
+        mPhotonicModulator.dump(pw);
+        mElectronBeam.dump(pw);
+    }
+
+    private void scheduleScreenUpdate() {
+        if (!mScreenUpdatePending) {
+            mScreenUpdatePending = true;
+            postScreenUpdateThreadSafe();
+        }
+    }
+
+    private void postScreenUpdateThreadSafe() {
+        mHandler.removeCallbacks(mScreenUpdateRunnable);
+        mHandler.post(mScreenUpdateRunnable);
+    }
+
+    private void scheduleElectronBeamDraw() {
+        if (!mElectronBeamDrawPending) {
+            mElectronBeamDrawPending = true;
+            mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL,
+                    mElectronBeamDrawRunnable, null);
+        }
+    }
+
+    private void invokeCleanListenerIfNeeded() {
+        final Runnable listener = mCleanListener;
+        if (listener != null && mScreenReady && mElectronBeamReady) {
+            mCleanListener = null;
+            listener.run();
+        }
+    }
+
+    private final Runnable mScreenUpdateRunnable = new Runnable() {
+        @Override
+        public void run() {
+            mScreenUpdatePending = false;
+
+            int brightness = mScreenOn && mElectronBeamLevel > 0f ? mScreenBrightness : 0;
+            if (mPhotonicModulator.setState(mScreenOn, brightness)) {
+                mScreenReady = true;
+                invokeCleanListenerIfNeeded();
+            }
+        }
+    };
+
+    private final Runnable mElectronBeamDrawRunnable = new Runnable() {
+        @Override
+        public void run() {
+            mElectronBeamDrawPending = false;
+
+            if (mElectronBeamPrepared) {
+                mElectronBeam.draw(mElectronBeamLevel);
+            }
+
+            mElectronBeamReady = true;
+            invokeCleanListenerIfNeeded();
+        }
+    };
+
+    /**
+     * Updates the state of the screen and backlight asynchronously on a separate thread.
+     */
+    private final class PhotonicModulator {
+        private static final boolean INITIAL_SCREEN_ON = false; // unknown, assume off
+        private static final int INITIAL_BACKLIGHT = -1; // unknown
+
+        private final Object mLock = new Object();
+
+        private boolean mPendingOn = INITIAL_SCREEN_ON;
+        private int mPendingBacklight = INITIAL_BACKLIGHT;
+        private boolean mActualOn = INITIAL_SCREEN_ON;
+        private int mActualBacklight = INITIAL_BACKLIGHT;
+        private boolean mChangeInProgress;
+
+        public boolean setState(boolean on, int backlight) {
+            synchronized (mLock) {
+                if (on != mPendingOn || backlight != mPendingBacklight) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Requesting new screen state: on=" + on
+                                + ", backlight=" + backlight);
+                    }
+
+                    mPendingOn = on;
+                    mPendingBacklight = backlight;
+
+                    if (!mChangeInProgress) {
+                        mChangeInProgress = true;
+                        AsyncTask.THREAD_POOL_EXECUTOR.execute(mTask);
+                    }
+                }
+                return mChangeInProgress;
+            }
+        }
+
+        public void dump(PrintWriter pw) {
+            pw.println();
+            pw.println("Photonic Modulator State:");
+            pw.println("  mPendingOn=" + mPendingOn);
+            pw.println("  mPendingBacklight=" + mPendingBacklight);
+            pw.println("  mActualOn=" + mActualOn);
+            pw.println("  mActualBacklight=" + mActualBacklight);
+            pw.println("  mChangeInProgress=" + mChangeInProgress);
+        }
+
+        private final Runnable mTask = new Runnable() {
+            @Override
+            public void run() {
+                // Apply pending changes until done.
+                for (;;) {
+                    final boolean on;
+                    final boolean onChanged;
+                    final int backlight;
+                    final boolean backlightChanged;
+                    synchronized (mLock) {
+                        on = mPendingOn;
+                        onChanged = (on != mActualOn);
+                        backlight = mPendingBacklight;
+                        backlightChanged = (backlight != mActualBacklight);
+                        if (!onChanged && !backlightChanged) {
+                            mChangeInProgress = false;
+                            break;
+                        }
+                        mActualOn = on;
+                        mActualBacklight = backlight;
+                    }
+
+                    if (DEBUG) {
+                        Slog.d(TAG, "Updating screen state: on=" + on
+                                + ", backlight=" + backlight);
+                    }
+                    if (onChanged && on) {
+                        mDisplayBlanker.unblankAllDisplays();
+                    }
+                    if (backlightChanged) {
+                        mBacklight.setBrightness(backlight);
+                    }
+                    if (onChanged && !on) {
+                        mDisplayBlanker.blankAllDisplays();
+                    }
+                }
+
+                // Let the outer class know that all changes have been applied.
+                postScreenUpdateThreadSafe();
+            }
+        };
+    }
+}
diff --git a/services/java/com/android/server/power/ElectronBeam.java b/services/java/com/android/server/power/ElectronBeam.java
new file mode 100644
index 0000000..9a53648
--- /dev/null
+++ b/services/java/com/android/server/power/ElectronBeam.java
@@ -0,0 +1,720 @@
+/*
+ * 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.power;
+
+import android.graphics.Bitmap;
+import android.graphics.PixelFormat;
+import android.opengl.EGL14;
+import android.opengl.EGLConfig;
+import android.opengl.EGLContext;
+import android.opengl.EGLDisplay;
+import android.opengl.EGLSurface;
+import android.opengl.GLES10;
+import android.opengl.GLUtils;
+import android.os.Looper;
+import android.util.FloatMath;
+import android.util.Slog;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.Surface;
+import android.view.SurfaceSession;
+
+import java.io.PrintWriter;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+/**
+ * Bzzzoooop!  *crackle*
+ * <p>
+ * Animates a screen transition from on to off or off to on by applying
+ * some GL transformations to a screenshot.
+ * </p><p>
+ * This component must only be created or accessed by the {@link Looper} thread
+ * that belongs to the {@link DisplayPowerController}.
+ * </p>
+ */
+final class ElectronBeam {
+    private static final String TAG = "ElectronBeam";
+
+    private static final boolean DEBUG = false;
+
+    // The layer for the electron beam surface.
+    // This is currently hardcoded to be one layer above the boot animation.
+    private static final int ELECTRON_BEAM_LAYER = 0x40000001;
+
+    // The relative proportion of the animation to spend performing
+    // the horizontal stretch effect.  The remainder is spent performing
+    // the vertical stretch effect.
+    private static final float HSTRETCH_DURATION = 0.5f;
+    private static final float VSTRETCH_DURATION = 1.0f - HSTRETCH_DURATION;
+
+    // The number of frames to draw when preparing the animation so that it will
+    // be ready to run smoothly.  We use 3 frames because we are triple-buffered.
+    // See code for details.
+    private static final int DEJANK_FRAMES = 3;
+
+    // Set to true when the animation context has been fully prepared.
+    private boolean mPrepared;
+    private int mMode;
+
+    private final Display mDisplay;
+    private final DisplayInfo mDisplayInfo = new DisplayInfo();
+    private int mDisplayLayerStack; // layer stack associated with primary display
+    private int mDisplayRotation;
+    private int mDisplayWidth;      // real width, not rotated
+    private int mDisplayHeight;     // real height, not rotated
+    private SurfaceSession mSurfaceSession;
+    private Surface mSurface;
+    private EGLDisplay mEglDisplay;
+    private EGLConfig mEglConfig;
+    private EGLContext mEglContext;
+    private EGLSurface mEglSurface;
+    private boolean mSurfaceVisible;
+    private float mSurfaceAlpha;
+
+    // Texture names.  We only use one texture, which contains the screenshot.
+    private final int[] mTexNames = new int[1];
+    private boolean mTexNamesGenerated;
+
+    // Vertex and corresponding texture coordinates.
+    // We have 4 2D vertices, so 8 elements.  The vertices form a quad.
+    private final FloatBuffer mVertexBuffer = createNativeFloatBuffer(8);
+    private final FloatBuffer mTexCoordBuffer = createNativeFloatBuffer(8);
+
+    /**
+     * Animates an electron beam warming up.
+     */
+    public static final int MODE_WARM_UP = 0;
+
+    /**
+     * Animates an electron beam shutting off.
+     */
+    public static final int MODE_COOL_DOWN = 1;
+
+    /**
+     * Animates a simple dim layer to fade the contents of the screen in or out progressively.
+     */
+    public static final int MODE_FADE = 2;
+
+    public ElectronBeam(Display display) {
+        mDisplay = display;
+    }
+
+    /**
+     * Warms up the electron beam in preparation for turning on or off.
+     * This method prepares a GL context, and captures a screen shot.
+     *
+     * @param mode The desired mode for the upcoming animation.
+     * @return True if the electron beam is ready, false if it is uncontrollable.
+     */
+    public boolean prepare(int mode) {
+        if (DEBUG) {
+            Slog.d(TAG, "prepare: mode=" + mode);
+        }
+
+        mMode = mode;
+
+        // Get the display size and adjust it for rotation.
+        mDisplay.getDisplayInfo(mDisplayInfo);
+        mDisplayLayerStack = mDisplay.getLayerStack();
+        mDisplayRotation = mDisplayInfo.rotation;
+        if (mDisplayRotation == Surface.ROTATION_90
+                || mDisplayRotation == Surface.ROTATION_270) {
+            mDisplayWidth = mDisplayInfo.logicalHeight;
+            mDisplayHeight = mDisplayInfo.logicalWidth;
+        } else {
+            mDisplayWidth = mDisplayInfo.logicalWidth;
+            mDisplayHeight = mDisplayInfo.logicalHeight;
+        }
+
+        // Prepare the surface for drawing.
+        if (!tryPrepare()) {
+            dismiss();
+            return false;
+        }
+
+        // Done.
+        mPrepared = true;
+
+        // Dejanking optimization.
+        // Some GL drivers can introduce a lot of lag in the first few frames as they
+        // initialize their state and allocate graphics buffers for rendering.
+        // Work around this problem by rendering the first frame of the animation a few
+        // times.  The rest of the animation should run smoothly thereafter.
+        // The frames we draw here aren't visible because we are essentially just
+        // painting the screenshot as-is.
+        if (mode == MODE_COOL_DOWN) {
+            for (int i = 0; i < DEJANK_FRAMES; i++) {
+                draw(1.0f);
+            }
+        }
+        return true;
+    }
+
+    private boolean tryPrepare() {
+        if (createSurface()) {
+            if (mMode == MODE_FADE) {
+                return true;
+            }
+            return createEglContext()
+                    && createEglSurface()
+                    && captureScreenshotTextureAndSetViewport();
+        }
+        return false;
+    }
+
+    /**
+     * Dismisses the electron beam animation surface and cleans up.
+     *
+     * To prevent stray photons from leaking out after the electron beam has been
+     * turned off, it is a good idea to defer dismissing the animation until the
+     * electron beam has been turned back on fully.
+     */
+    public void dismiss() {
+        if (DEBUG) {
+            Slog.d(TAG, "dismiss");
+        }
+
+        destroyScreenshotTexture();
+        destroyEglSurface();
+        destroySurface();
+        mPrepared = false;
+    }
+
+    /**
+     * Draws an animation frame showing the electron beam activated at the
+     * specified level.
+     *
+     * @param level The electron beam level.
+     * @return True if successful.
+     */
+    public boolean draw(float level) {
+        if (DEBUG) {
+            Slog.d(TAG, "drawFrame: level=" + level);
+        }
+
+        if (!mPrepared) {
+            return false;
+        }
+
+        if (mMode == MODE_FADE) {
+            return showSurface(1.0f - level);
+        }
+
+        if (!attachEglContext()) {
+            return false;
+        }
+        try {
+            // Clear frame to solid black.
+            GLES10.glClearColor(0f, 0f, 0f, 1f);
+            GLES10.glClear(GLES10.GL_COLOR_BUFFER_BIT);
+
+            // Draw the frame.
+            if (level < HSTRETCH_DURATION) {
+                drawHStretch(1.0f - (level / HSTRETCH_DURATION));
+            } else {
+                drawVStretch(1.0f - ((level - HSTRETCH_DURATION) / VSTRETCH_DURATION));
+            }
+            if (checkGlErrors("drawFrame")) {
+                return false;
+            }
+
+            EGL14.eglSwapBuffers(mEglDisplay, mEglSurface);
+        } finally {
+            detachEglContext();
+        }
+        return showSurface(1.0f);
+    }
+
+    /**
+     * Draws a frame where the content of the electron beam is collapsing inwards upon
+     * itself vertically with red / green / blue channels dispersing and eventually
+     * merging down to a single horizontal line.
+     *
+     * @param stretch The stretch factor.  0.0 is no collapse, 1.0 is full collapse.
+     */
+    private void drawVStretch(float stretch) {
+        // compute interpolation scale factors for each color channel
+        final float ar = scurve(stretch, 7.5f);
+        final float ag = scurve(stretch, 8.0f);
+        final float ab = scurve(stretch, 8.5f);
+        if (DEBUG) {
+            Slog.d(TAG, "drawVStretch: stretch=" + stretch
+                    + ", ar=" + ar + ", ag=" + ag + ", ab=" + ab);
+        }
+
+        // set blending
+        GLES10.glBlendFunc(GLES10.GL_ONE, GLES10.GL_ONE);
+        GLES10.glEnable(GLES10.GL_BLEND);
+
+        // bind vertex buffer
+        GLES10.glVertexPointer(2, GLES10.GL_FLOAT, 0, mVertexBuffer);
+        GLES10.glEnableClientState(GLES10.GL_VERTEX_ARRAY);
+
+        // bind texture and set blending for drawing planes
+        GLES10.glBindTexture(GLES10.GL_TEXTURE_2D, mTexNames[0]);
+        GLES10.glTexEnvx(GLES10.GL_TEXTURE_ENV, GLES10.GL_TEXTURE_ENV_MODE,
+                mMode == MODE_WARM_UP ? GLES10.GL_MODULATE : GLES10.GL_REPLACE);
+        GLES10.glTexParameterx(GLES10.GL_TEXTURE_2D,
+                GLES10.GL_TEXTURE_MAG_FILTER, GLES10.GL_LINEAR);
+        GLES10.glTexParameterx(GLES10.GL_TEXTURE_2D,
+                GLES10.GL_TEXTURE_MIN_FILTER, GLES10.GL_LINEAR);
+        GLES10.glTexParameterx(GLES10.GL_TEXTURE_2D,
+                GLES10.GL_TEXTURE_WRAP_S, GLES10.GL_CLAMP_TO_EDGE);
+        GLES10.glTexParameterx(GLES10.GL_TEXTURE_2D,
+                GLES10.GL_TEXTURE_WRAP_T, GLES10.GL_CLAMP_TO_EDGE);
+        GLES10.glEnable(GLES10.GL_TEXTURE_2D);
+        GLES10.glTexCoordPointer(2, GLES10.GL_FLOAT, 0, mTexCoordBuffer);
+        GLES10.glEnableClientState(GLES10.GL_TEXTURE_COORD_ARRAY);
+
+        // draw the red plane
+        setVStretchQuad(mVertexBuffer, mDisplayWidth, mDisplayHeight, ar);
+        GLES10.glColorMask(true, false, false, true);
+        GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4);
+
+        // draw the green plane
+        setVStretchQuad(mVertexBuffer, mDisplayWidth, mDisplayHeight, ag);
+        GLES10.glColorMask(false, true, false, true);
+        GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4);
+
+        // draw the blue plane
+        setVStretchQuad(mVertexBuffer, mDisplayWidth, mDisplayHeight, ab);
+        GLES10.glColorMask(false, false, true, true);
+        GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4);
+
+        // clean up after drawing planes
+        GLES10.glDisable(GLES10.GL_TEXTURE_2D);
+        GLES10.glDisableClientState(GLES10.GL_TEXTURE_COORD_ARRAY);
+        GLES10.glColorMask(true, true, true, true);
+
+        // draw the white highlight (we use the last vertices)
+        if (mMode == MODE_COOL_DOWN) {
+            GLES10.glColor4f(ag, ag, ag, 1.0f);
+            GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4);
+        }
+
+        // clean up
+        GLES10.glDisableClientState(GLES10.GL_VERTEX_ARRAY);
+        GLES10.glDisable(GLES10.GL_BLEND);
+    }
+
+    /**
+     * Draws a frame where the electron beam has been stretched out into
+     * a thin white horizontal line that fades as it expands outwards.
+     *
+     * @param stretch The stretch factor.  0.0 is no stretch / no fade,
+     * 1.0 is maximum stretch / maximum fade.
+     */
+    private void drawHStretch(float stretch) {
+        // compute interpolation scale factor
+        final float ag = scurve(stretch, 8.0f);
+        if (DEBUG) {
+            Slog.d(TAG, "drawHStretch: stretch=" + stretch + ", ag=" + ag);
+        }
+
+        if (stretch < 1.0f) {
+            // bind vertex buffer
+            GLES10.glVertexPointer(2, GLES10.GL_FLOAT, 0, mVertexBuffer);
+            GLES10.glEnableClientState(GLES10.GL_VERTEX_ARRAY);
+
+            // draw narrow fading white line
+            setHStretchQuad(mVertexBuffer, mDisplayWidth, mDisplayHeight, ag);
+            GLES10.glColor4f(1.0f - ag, 1.0f - ag, 1.0f - ag, 1.0f);
+            GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4);
+
+            // clean up
+            GLES10.glDisableClientState(GLES10.GL_VERTEX_ARRAY);
+        }
+    }
+
+    private static void setVStretchQuad(FloatBuffer vtx, float dw, float dh, float a) {
+        final float w = dw + (dw * a);
+        final float h = dh - (dh * a);
+        final float x = (dw - w) * 0.5f;
+        final float y = (dh - h) * 0.5f;
+        setQuad(vtx, x, y, w, h);
+    }
+
+    private static void setHStretchQuad(FloatBuffer vtx, float dw, float dh, float a) {
+        final float w = dw + (dw * a);
+        final float h = 1.0f;
+        final float x = (dw - w) * 0.5f;
+        final float y = (dh - h) * 0.5f;
+        setQuad(vtx, x, y, w, h);
+    }
+
+    private static void setQuad(FloatBuffer vtx, float x, float y, float w, float h) {
+        if (DEBUG) {
+            Slog.d(TAG, "setQuad: x=" + x + ", y=" + y + ", w=" + w + ", h=" + h);
+        }
+        vtx.put(0, x);
+        vtx.put(1, y);
+        vtx.put(2, x);
+        vtx.put(3, y + h);
+        vtx.put(4, x + w);
+        vtx.put(5, y + h);
+        vtx.put(6, x + w);
+        vtx.put(7, y);
+    }
+
+    private boolean captureScreenshotTextureAndSetViewport() {
+        // TODO: Use a SurfaceTexture to avoid the extra texture upload.
+        Bitmap bitmap = Surface.screenshot(mDisplayWidth, mDisplayHeight,
+                0, ELECTRON_BEAM_LAYER - 1);
+        if (bitmap == null) {
+            Slog.e(TAG, "Could not take a screenshot!");
+            return false;
+        }
+        try {
+            if (!attachEglContext()) {
+                return false;
+            }
+            try {
+                if (!mTexNamesGenerated) {
+                    GLES10.glGenTextures(1, mTexNames, 0);
+                    if (checkGlErrors("glGenTextures")) {
+                        return false;
+                    }
+                    mTexNamesGenerated = true;
+                }
+
+                GLES10.glBindTexture(GLES10.GL_TEXTURE_2D, mTexNames[0]);
+                if (checkGlErrors("glBindTexture")) {
+                    return false;
+                }
+
+                float u = 1.0f;
+                float v = 1.0f;
+                GLUtils.texImage2D(GLES10.GL_TEXTURE_2D, 0, bitmap, 0);
+                if (checkGlErrors("glTexImage2D, first try", false)) {
+                    // Try a power of two size texture instead.
+                    int tw = nextPowerOfTwo(mDisplayWidth);
+                    int th = nextPowerOfTwo(mDisplayHeight);
+                    int format = GLUtils.getInternalFormat(bitmap);
+                    GLES10.glTexImage2D(GLES10.GL_TEXTURE_2D, 0,
+                            format, tw, th, 0,
+                            format, GLES10.GL_UNSIGNED_BYTE, null);
+                    if (checkGlErrors("glTexImage2D, second try")) {
+                        return false;
+                    }
+
+                    GLUtils.texSubImage2D(GLES10.GL_TEXTURE_2D, 0, 0, 0, bitmap);
+                    if (checkGlErrors("glTexSubImage2D")) {
+                        return false;
+                    }
+
+                    u = (float)mDisplayWidth / tw;
+                    v = (float)mDisplayHeight / th;
+                }
+
+                // Set up texture coordinates for a quad.
+                // We might need to change this if the texture ends up being
+                // a different size from the display for some reason.
+                mTexCoordBuffer.put(0, 0f);
+                mTexCoordBuffer.put(1, v);
+                mTexCoordBuffer.put(2, 0f);
+                mTexCoordBuffer.put(3, 0f);
+                mTexCoordBuffer.put(4, u);
+                mTexCoordBuffer.put(5, 0f);
+                mTexCoordBuffer.put(6, u);
+                mTexCoordBuffer.put(7, v);
+
+                // Set up our viewport.
+                GLES10.glViewport(0, 0, mDisplayWidth, mDisplayHeight);
+                GLES10.glMatrixMode(GLES10.GL_PROJECTION);
+                GLES10.glLoadIdentity();
+                GLES10.glOrthof(0, mDisplayWidth, 0, mDisplayHeight, 0, 1);
+                GLES10.glMatrixMode(GLES10.GL_MODELVIEW);
+                GLES10.glLoadIdentity();
+                GLES10.glMatrixMode(GLES10.GL_TEXTURE);
+                GLES10.glLoadIdentity();
+            } finally {
+                detachEglContext();
+            }
+        } finally {
+            bitmap.recycle();
+        }
+        return true;
+    }
+
+    private void destroyScreenshotTexture() {
+        if (mTexNamesGenerated) {
+            mTexNamesGenerated = false;
+            if (attachEglContext()) {
+                try {
+                    GLES10.glDeleteTextures(1, mTexNames, 0);
+                    checkGlErrors("glDeleteTextures");
+                } finally {
+                    detachEglContext();
+                }
+            }
+        }
+    }
+
+    private boolean createEglContext() {
+        if (mEglDisplay == null) {
+            mEglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
+            if (mEglDisplay == EGL14.EGL_NO_DISPLAY) {
+                logEglError("eglGetDisplay");
+                return false;
+            }
+
+            int[] version = new int[2];
+            if (!EGL14.eglInitialize(mEglDisplay, version, 0, version, 1)) {
+                mEglDisplay = null;
+                logEglError("eglInitialize");
+                return false;
+            }
+        }
+
+        if (mEglConfig == null) {
+            int[] eglConfigAttribList = new int[] {
+                    EGL14.EGL_RED_SIZE, 8,
+                    EGL14.EGL_GREEN_SIZE, 8,
+                    EGL14.EGL_BLUE_SIZE, 8,
+                    EGL14.EGL_ALPHA_SIZE, 8,
+                    EGL14.EGL_NONE
+            };
+            int[] numEglConfigs = new int[1];
+            EGLConfig[] eglConfigs = new EGLConfig[1];
+            if (!EGL14.eglChooseConfig(mEglDisplay, eglConfigAttribList, 0,
+                    eglConfigs, 0, eglConfigs.length, numEglConfigs, 0)) {
+                logEglError("eglChooseConfig");
+                return false;
+            }
+            mEglConfig = eglConfigs[0];
+        }
+
+        if (mEglContext == null) {
+            int[] eglContextAttribList = new int[] {
+                    EGL14.EGL_NONE
+            };
+            mEglContext = EGL14.eglCreateContext(mEglDisplay, mEglConfig,
+                    EGL14.EGL_NO_CONTEXT, eglContextAttribList, 0);
+            if (mEglContext == null) {
+                logEglError("eglCreateContext");
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /* not used because it is too expensive to create / destroy contexts all of the time
+    private void destroyEglContext() {
+        if (mEglContext != null) {
+            if (!EGL14.eglDestroyContext(mEglDisplay, mEglContext)) {
+                logEglError("eglDestroyContext");
+            }
+            mEglContext = null;
+        }
+    }*/
+
+    private boolean createSurface() {
+        if (mSurfaceSession == null) {
+            mSurfaceSession = new SurfaceSession();
+        }
+
+        Surface.openTransaction();
+        try {
+            if (mSurface == null) {
+                try {
+                    int flags;
+                    if (mMode == MODE_FADE) {
+                        flags = Surface.FX_SURFACE_DIM | Surface.HIDDEN;
+                    } else {
+                        flags = Surface.OPAQUE | Surface.HIDDEN;
+                    }
+                    mSurface = new Surface(mSurfaceSession,
+                            "ElectronBeam", mDisplayWidth, mDisplayHeight,
+                            PixelFormat.OPAQUE, flags);
+                } catch (Surface.OutOfResourcesException ex) {
+                    Slog.e(TAG, "Unable to create surface.", ex);
+                    return false;
+                }
+            }
+
+            mSurface.setLayerStack(mDisplayLayerStack);
+            mSurface.setSize(mDisplayWidth, mDisplayHeight);
+
+            switch (mDisplayRotation) {
+                case Surface.ROTATION_0:
+                    mSurface.setPosition(0, 0);
+                    mSurface.setMatrix(1, 0, 0, 1);
+                    break;
+                case Surface.ROTATION_90:
+                    mSurface.setPosition(0, mDisplayWidth);
+                    mSurface.setMatrix(0, -1, 1, 0);
+                    break;
+                case Surface.ROTATION_180:
+                    mSurface.setPosition(mDisplayWidth, mDisplayHeight);
+                    mSurface.setMatrix(-1, 0, 0, -1);
+                    break;
+                case Surface.ROTATION_270:
+                    mSurface.setPosition(mDisplayHeight, 0);
+                    mSurface.setMatrix(0, 1, -1, 0);
+                    break;
+            }
+        } finally {
+            Surface.closeTransaction();
+        }
+        return true;
+    }
+
+    private boolean createEglSurface() {
+        if (mEglSurface == null) {
+            int[] eglSurfaceAttribList = new int[] {
+                    EGL14.EGL_NONE
+            };
+            mEglSurface = EGL14.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface,
+                    eglSurfaceAttribList, 0);
+            if (mEglSurface == null) {
+                logEglError("eglCreateWindowSurface");
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private void destroyEglSurface() {
+        if (mEglSurface != null) {
+            if (!EGL14.eglDestroySurface(mEglDisplay, mEglSurface)) {
+                logEglError("eglDestroySurface");
+            }
+            mEglSurface = null;
+        }
+    }
+
+    private void destroySurface() {
+        if (mSurface != null) {
+            Surface.openTransaction();
+            try {
+                mSurface.destroy();
+            } finally {
+                Surface.closeTransaction();
+            }
+            mSurface = null;
+            mSurfaceVisible = false;
+            mSurfaceAlpha = 0f;
+        }
+    }
+
+    private boolean showSurface(float alpha) {
+        if (!mSurfaceVisible || mSurfaceAlpha != alpha) {
+            Surface.openTransaction();
+            try {
+                mSurface.setLayer(ELECTRON_BEAM_LAYER);
+                mSurface.setAlpha(alpha);
+                mSurface.show();
+            } finally {
+                Surface.closeTransaction();
+            }
+            mSurfaceVisible = true;
+            mSurfaceAlpha = alpha;
+        }
+        return true;
+    }
+
+    private boolean attachEglContext() {
+        if (mEglSurface == null) {
+            return false;
+        }
+        if (!EGL14.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
+            logEglError("eglMakeCurrent");
+            return false;
+        }
+        return true;
+    }
+
+    private void detachEglContext() {
+        if (mEglDisplay != null) {
+            EGL14.eglMakeCurrent(mEglDisplay,
+                    EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
+        }
+    }
+
+    /**
+     * Interpolates a value in the range 0 .. 1 along a sigmoid curve
+     * yielding a result in the range 0 .. 1 scaled such that:
+     * scurve(0) == 0, scurve(0.5) == 0.5, scurve(1) == 1.
+     */
+    private static float scurve(float value, float s) {
+        // A basic sigmoid has the form y = 1.0f / FloatMap.exp(-x * s).
+        // Here we take the input datum and shift it by 0.5 so that the
+        // domain spans the range -0.5 .. 0.5 instead of 0 .. 1.
+        final float x = value - 0.5f;
+
+        // Next apply the sigmoid function to the scaled value
+        // which produces a value in the range 0 .. 1 so we subtract
+        // 0.5 to get a value in the range -0.5 .. 0.5 instead.
+        final float y = sigmoid(x, s) - 0.5f;
+
+        // To obtain the desired boundary conditions we need to scale
+        // the result so that it fills a range of -1 .. 1.
+        final float v = sigmoid(0.5f, s) - 0.5f;
+
+        // And finally remap the value back to a range of 0 .. 1.
+        return y / v * 0.5f + 0.5f;
+    }
+
+    private static float sigmoid(float x, float s) {
+        return 1.0f / (1.0f + FloatMath.exp(-x * s));
+    }
+
+    private static int nextPowerOfTwo(int value) {
+        return 1 << (32 - Integer.numberOfLeadingZeros(value));
+    }
+
+    private static FloatBuffer createNativeFloatBuffer(int size) {
+        ByteBuffer bb = ByteBuffer.allocateDirect(size * 4);
+        bb.order(ByteOrder.nativeOrder());
+        return bb.asFloatBuffer();
+    }
+
+    private static void logEglError(String func) {
+        Slog.e(TAG, func + " failed: error " + EGL14.eglGetError(), new Throwable());
+    }
+
+    private static boolean checkGlErrors(String func) {
+        return checkGlErrors(func, true);
+    }
+
+    private static boolean checkGlErrors(String func, boolean log) {
+        boolean hadError = false;
+        int error;
+        while ((error = GLES10.glGetError()) != GLES10.GL_NO_ERROR) {
+            if (log) {
+                Slog.e(TAG, func + " failed: error " + error, new Throwable());
+            }
+            hadError = true;
+        }
+        return hadError;
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.println();
+        pw.println("Electron Beam State:");
+        pw.println("  mPrepared=" + mPrepared);
+        pw.println("  mMode=" + mMode);
+        pw.println("  mDisplayLayerStack=" + mDisplayLayerStack);
+        pw.println("  mDisplayRotation=" + mDisplayRotation);
+        pw.println("  mDisplayWidth=" + mDisplayWidth);
+        pw.println("  mDisplayHeight=" + mDisplayHeight);
+        pw.println("  mSurfaceVisible=" + mSurfaceVisible);
+        pw.println("  mSurfaceAlpha=" + mSurfaceAlpha);
+    }
+}
diff --git a/services/java/com/android/server/power/Notifier.java b/services/java/com/android/server/power/Notifier.java
new file mode 100644
index 0000000..5e05693
--- /dev/null
+++ b/services/java/com/android/server/power/Notifier.java
@@ -0,0 +1,494 @@
+/*
+ * 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.power;
+
+import com.android.internal.app.IBatteryStats;
+import com.android.server.EventLogTags;
+
+import android.app.ActivityManagerNative;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.BatteryStats;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.os.WorkSource;
+import android.util.EventLog;
+import android.util.Slog;
+import android.view.WindowManagerPolicy;
+
+/**
+ * Sends broadcasts about important power state changes.
+ * <p>
+ * This methods of this class may be called by the power manager service while
+ * its lock is being held.  Internally it takes care of sending broadcasts to
+ * notify other components of the system or applications asynchronously.
+ * </p><p>
+ * The notifier is designed to collapse unnecessary broadcasts when it is not
+ * possible for the system to have observed an intermediate state.
+ * </p><p>
+ * For example, if the device wakes up, goes to sleep, wakes up again and goes to
+ * sleep again before the wake up notification is sent, then the system will
+ * be told about only one wake up and sleep.  However, we always notify the
+ * fact that at least one transition occurred.  It is especially important to
+ * tell the system when we go to sleep so that it can lock the keyguard if needed.
+ * </p>
+ */
+final class Notifier {
+    private static final String TAG = "PowerManagerNotifier";
+
+    private static final boolean DEBUG = false;
+
+    private static final int POWER_STATE_UNKNOWN = 0;
+    private static final int POWER_STATE_AWAKE = 1;
+    private static final int POWER_STATE_ASLEEP = 2;
+
+    private static final int MSG_USER_ACTIVITY = 1;
+    private static final int MSG_BROADCAST = 2;
+
+    private final Object mLock = new Object();
+
+    private final Context mContext;
+    private final IBatteryStats mBatteryStats;
+    private final SuspendBlocker mSuspendBlocker;
+    private final ScreenOnBlocker mScreenOnBlocker;
+    private final WindowManagerPolicy mPolicy;
+
+    private final NotifierHandler mHandler;
+    private final Intent mScreenOnIntent;
+    private final Intent mScreenOffIntent;
+
+    // The current power state.
+    private int mActualPowerState;
+    private int mLastGoToSleepReason;
+
+    // True if there is a pending transition that needs to be reported.
+    private boolean mPendingWakeUpBroadcast;
+    private boolean mPendingGoToSleepBroadcast;
+
+    // The currently broadcasted power state.  This reflects what other parts of the
+    // system have observed.
+    private int mBroadcastedPowerState;
+    private boolean mBroadcastInProgress;
+    private long mBroadcastStartTime;
+
+    // True if a user activity message should be sent.
+    private boolean mUserActivityPending;
+
+    // True if the screen on blocker has been acquired.
+    private boolean mScreenOnBlockerAcquired;
+
+    public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
+            SuspendBlocker suspendBlocker, ScreenOnBlocker screenOnBlocker,
+            WindowManagerPolicy policy) {
+        mContext = context;
+        mBatteryStats = batteryStats;
+        mSuspendBlocker = suspendBlocker;
+        mScreenOnBlocker = screenOnBlocker;
+        mPolicy = policy;
+
+        mHandler = new NotifierHandler(looper);
+        mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
+        mScreenOnIntent.addFlags(
+                Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+        mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
+        mScreenOffIntent.addFlags(
+                Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+    }
+
+    /**
+     * Called when a wake lock is acquired.
+     */
+    public void onWakeLockAcquired(int flags, String tag, int ownerUid, int ownerPid,
+            WorkSource workSource) {
+        if (DEBUG) {
+            Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag
+                    + "\", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
+                    + ", workSource=" + workSource);
+        }
+
+        try {
+            final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
+            if (workSource != null) {
+                mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag, monitorType);
+            } else {
+                mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, monitorType);
+            }
+        } catch (RemoteException ex) {
+            // Ignore
+        }
+    }
+
+    /**
+     * Called when a wake lock is released.
+     */
+    public void onWakeLockReleased(int flags, String tag, int ownerUid, int ownerPid,
+            WorkSource workSource) {
+        if (DEBUG) {
+            Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag
+                    + "\", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
+                    + ", workSource=" + workSource);
+        }
+
+        try {
+            final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
+            if (workSource != null) {
+                mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag, monitorType);
+            } else {
+                mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag, monitorType);
+            }
+        } catch (RemoteException ex) {
+            // Ignore
+        }
+    }
+
+    private static int getBatteryStatsWakeLockMonitorType(int flags) {
+        switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
+            case PowerManager.PARTIAL_WAKE_LOCK:
+            case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
+                return BatteryStats.WAKE_TYPE_PARTIAL;
+            default:
+                return BatteryStats.WAKE_TYPE_FULL;
+        }
+    }
+
+    /**
+     * Called when the screen is turned on.
+     */
+    public void onScreenOn() {
+        if (DEBUG) {
+            Slog.d(TAG, "onScreenOn");
+        }
+
+        try {
+            mBatteryStats.noteScreenOn();
+        } catch (RemoteException ex) {
+            // Ignore
+        }
+    }
+
+    /**
+     * Called when the screen is turned off.
+     */
+    public void onScreenOff() {
+        if (DEBUG) {
+            Slog.d(TAG, "onScreenOff");
+        }
+
+        try {
+            mBatteryStats.noteScreenOff();
+        } catch (RemoteException ex) {
+            // Ignore
+        }
+    }
+
+    /**
+     * Called when the screen changes brightness.
+     */
+    public void onScreenBrightness(int brightness) {
+        if (DEBUG) {
+            Slog.d(TAG, "onScreenBrightness: brightness=" + brightness);
+        }
+
+        try {
+            mBatteryStats.noteScreenBrightness(brightness);
+        } catch (RemoteException ex) {
+            // Ignore
+        }
+    }
+
+    /**
+     * Called when the device is waking up from sleep and the
+     * display is about to be turned on.
+     */
+    public void onWakeUpStarted() {
+        if (DEBUG) {
+            Slog.d(TAG, "onWakeUpStarted");
+        }
+
+        synchronized (mLock) {
+            if (mActualPowerState != POWER_STATE_AWAKE) {
+                mActualPowerState = POWER_STATE_AWAKE;
+                mPendingWakeUpBroadcast = true;
+                if (!mScreenOnBlockerAcquired) {
+                    mScreenOnBlockerAcquired = true;
+                    mScreenOnBlocker.acquire();
+                }
+                updatePendingBroadcastLocked();
+            }
+        }
+    }
+
+    /**
+     * Called when the device has finished waking up from sleep
+     * and the display has been turned on.
+     */
+    public void onWakeUpFinished() {
+        if (DEBUG) {
+            Slog.d(TAG, "onWakeUpFinished");
+        }
+    }
+
+    /**
+     * Called when the device is going to sleep.
+     */
+    public void onGoToSleepStarted(int reason) {
+        if (DEBUG) {
+            Slog.d(TAG, "onGoToSleepStarted");
+        }
+
+        synchronized (mLock) {
+            mLastGoToSleepReason = reason;
+        }
+    }
+
+    /**
+     * Called when the device has finished going to sleep and the
+     * display has been turned off.
+     *
+     * This is a good time to make transitions that we don't want the user to see,
+     * such as bringing the key guard to focus.  There's no guarantee for this,
+     * however because the user could turn the device on again at any time.
+     * Some things may need to be protected by other mechanisms that defer screen on.
+     */
+    public void onGoToSleepFinished() {
+        if (DEBUG) {
+            Slog.d(TAG, "onGoToSleepFinished");
+        }
+
+        synchronized (mLock) {
+            if (mActualPowerState != POWER_STATE_ASLEEP) {
+                mActualPowerState = POWER_STATE_ASLEEP;
+                mPendingGoToSleepBroadcast = true;
+                if (mUserActivityPending) {
+                    mUserActivityPending = false;
+                    mHandler.removeMessages(MSG_USER_ACTIVITY);
+                }
+                updatePendingBroadcastLocked();
+            }
+        }
+    }
+
+    /**
+     * Called when there has been user activity.
+     */
+    public void onUserActivity(int event, int uid) {
+        if (DEBUG) {
+            Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid);
+        }
+
+        try {
+            mBatteryStats.noteUserActivity(uid, event);
+        } catch (RemoteException ex) {
+            // Ignore
+        }
+
+        synchronized (mLock) {
+            if (!mUserActivityPending) {
+                mUserActivityPending = true;
+                Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY);
+                msg.setAsynchronous(true);
+                mHandler.sendMessage(msg);
+            }
+        }
+    }
+
+    private void updatePendingBroadcastLocked() {
+        if (!mBroadcastInProgress
+                && mActualPowerState != POWER_STATE_UNKNOWN
+                && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
+                        || mActualPowerState != mBroadcastedPowerState)) {
+            mBroadcastInProgress = true;
+            mSuspendBlocker.acquire();
+            Message msg = mHandler.obtainMessage(MSG_BROADCAST);
+            msg.setAsynchronous(true);
+            mHandler.sendMessage(msg);
+        }
+    }
+
+    private void finishPendingBroadcastLocked() {
+        mBroadcastInProgress = false;
+        mSuspendBlocker.release();
+    }
+
+    private void sendUserActivity() {
+        synchronized (mLock) {
+            if (!mUserActivityPending) {
+                return;
+            }
+            mUserActivityPending = false;
+        }
+
+        mPolicy.userActivity();
+    }
+
+    private void sendNextBroadcast() {
+        final int powerState;
+        final int goToSleepReason;
+        synchronized (mLock) {
+            if (mBroadcastedPowerState == POWER_STATE_UNKNOWN) {
+                // Broadcasted power state is unknown.  Send wake up.
+                mPendingWakeUpBroadcast = false;
+                mBroadcastedPowerState = POWER_STATE_AWAKE;
+            } else if (mBroadcastedPowerState == POWER_STATE_AWAKE) {
+                // Broadcasted power state is awake.  Send asleep if needed.
+                if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
+                        || mActualPowerState == POWER_STATE_ASLEEP) {
+                    mPendingGoToSleepBroadcast = false;
+                    mBroadcastedPowerState = POWER_STATE_ASLEEP;
+                } else {
+                    finishPendingBroadcastLocked();
+                    return;
+                }
+            } else {
+                // Broadcasted power state is asleep.  Send awake if needed.
+                if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
+                        || mActualPowerState == POWER_STATE_AWAKE) {
+                    mPendingWakeUpBroadcast = false;
+                    mBroadcastedPowerState = POWER_STATE_AWAKE;
+                } else {
+                    finishPendingBroadcastLocked();
+                    return;
+                }
+            }
+
+            mBroadcastStartTime = SystemClock.uptimeMillis();
+            powerState = mBroadcastedPowerState;
+            goToSleepReason = mLastGoToSleepReason;
+        }
+
+        EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);
+
+        if (powerState == POWER_STATE_AWAKE) {
+            sendWakeUpBroadcast();
+        } else {
+            sendGoToSleepBroadcast(goToSleepReason);
+        }
+    }
+
+    private void sendWakeUpBroadcast() {
+        if (DEBUG) {
+            Slog.d(TAG, "Sending wake up broadcast.");
+        }
+
+        EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
+
+        mPolicy.screenTurningOn(mScreenOnListener);
+
+        try {
+            ActivityManagerNative.getDefault().wakingUp();
+        } catch (RemoteException e) {
+            // ignore it
+        }
+
+        if (ActivityManagerNative.isSystemReady()) {
+            mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null,
+                    mWakeUpBroadcastDone, mHandler, 0, null, null);
+        } else {
+            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);
+            sendNextBroadcast();
+        }
+    }
+
+    private final WindowManagerPolicy.ScreenOnListener mScreenOnListener =
+            new WindowManagerPolicy.ScreenOnListener() {
+        @Override
+        public void onScreenOn() {
+            synchronized (mLock) {
+                if (mScreenOnBlockerAcquired && !mPendingWakeUpBroadcast) {
+                    mScreenOnBlockerAcquired = false;
+                    mScreenOnBlocker.release();
+                }
+            }
+        }
+    };
+
+    private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
+                    SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
+            sendNextBroadcast();
+        }
+    };
+
+    private void sendGoToSleepBroadcast(int reason) {
+        if (DEBUG) {
+            Slog.d(TAG, "Sending go to sleep broadcast.");
+        }
+
+        int why = WindowManagerPolicy.OFF_BECAUSE_OF_USER;
+        switch (reason) {
+            case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
+                why = WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN;
+                break;
+            case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
+                why = WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
+                break;
+        }
+
+        EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0);
+
+        mPolicy.screenTurnedOff(why);
+        try {
+            ActivityManagerNative.getDefault().goingToSleep();
+        } catch (RemoteException e) {
+            // ignore it.
+        }
+
+        if (ActivityManagerNative.isSystemReady()) {
+            mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null,
+                    mGoToSleepBroadcastDone, mHandler, 0, null, null);
+        } else {
+            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1);
+            sendNextBroadcast();
+        }
+    }
+
+    private final BroadcastReceiver mGoToSleepBroadcastDone = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
+                    SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
+            sendNextBroadcast();
+        }
+    };
+
+    private final class NotifierHandler extends Handler {
+        public NotifierHandler(Looper looper) {
+            super(looper, null, true /*async*/);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_USER_ACTIVITY:
+                    sendUserActivity();
+                    break;
+
+                case MSG_BROADCAST:
+                    sendNextBroadcast();
+                    break;
+            }
+        }
+    }
+}
diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java
new file mode 100644
index 0000000..8650192
--- /dev/null
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -0,0 +1,2590 @@
+/*
+ * 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.
+ */
+
+package com.android.server.power;
+
+import com.android.internal.app.IBatteryStats;
+import com.android.server.BatteryService;
+import com.android.server.EventLogTags;
+import com.android.server.LightsService;
+import com.android.server.TwilightService;
+import com.android.server.Watchdog;
+import com.android.server.am.ActivityManagerService;
+import com.android.server.display.DisplayManagerService;
+import com.android.server.dreams.DreamManagerService;
+
+import android.Manifest;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.BatteryManager;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.IPowerManager;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.SystemService;
+import android.os.UserHandle;
+import android.os.WorkSource;
+import android.provider.Settings;
+import android.util.EventLog;
+import android.util.Log;
+import android.util.Slog;
+import android.util.TimeUtils;
+import android.view.WindowManagerPolicy;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+import libcore.util.Objects;
+
+/**
+ * The power manager service is responsible for coordinating power management
+ * functions on the device.
+ */
+public final class PowerManagerService extends IPowerManager.Stub
+        implements Watchdog.Monitor {
+    private static final String TAG = "PowerManagerService";
+
+    private static final boolean DEBUG = false;
+    private static final boolean DEBUG_SPEW = DEBUG && true;
+
+    // Message: Sent when a user activity timeout occurs to update the power state.
+    private static final int MSG_USER_ACTIVITY_TIMEOUT = 1;
+    // Message: Sent when the device enters or exits a napping or dreaming state.
+    private static final int MSG_SANDMAN = 2;
+    // Message: Sent when the screen on blocker is released.
+    private static final int MSG_SCREEN_ON_BLOCKER_RELEASED = 3;
+    // Message: Sent to poll whether the boot animation has terminated.
+    private static final int MSG_CHECK_IF_BOOT_ANIMATION_FINISHED = 4;
+
+    // Dirty bit: mWakeLocks changed
+    private static final int DIRTY_WAKE_LOCKS = 1 << 0;
+    // Dirty bit: mWakefulness changed
+    private static final int DIRTY_WAKEFULNESS = 1 << 1;
+    // Dirty bit: user activity was poked or may have timed out
+    private static final int DIRTY_USER_ACTIVITY = 1 << 2;
+    // Dirty bit: actual display power state was updated asynchronously
+    private static final int DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED = 1 << 3;
+    // Dirty bit: mBootCompleted changed
+    private static final int DIRTY_BOOT_COMPLETED = 1 << 4;
+    // Dirty bit: settings changed
+    private static final int DIRTY_SETTINGS = 1 << 5;
+    // Dirty bit: mIsPowered changed
+    private static final int DIRTY_IS_POWERED = 1 << 6;
+    // Dirty bit: mStayOn changed
+    private static final int DIRTY_STAY_ON = 1 << 7;
+    // Dirty bit: battery state changed
+    private static final int DIRTY_BATTERY_STATE = 1 << 8;
+    // Dirty bit: proximity state changed
+    private static final int DIRTY_PROXIMITY_POSITIVE = 1 << 9;
+    // Dirty bit: screen on blocker state became held or unheld
+    private static final int DIRTY_SCREEN_ON_BLOCKER_RELEASED = 1 << 10;
+    // Dirty bit: dock state changed
+    private static final int DIRTY_DOCK_STATE = 1 << 11;
+
+    // Wakefulness: The device is asleep and can only be awoken by a call to wakeUp().
+    // The screen should be off or in the process of being turned off by the display controller.
+    private static final int WAKEFULNESS_ASLEEP = 0;
+    // Wakefulness: The device is fully awake.  It can be put to sleep by a call to goToSleep().
+    // When the user activity timeout expires, the device may start napping or go to sleep.
+    private static final int WAKEFULNESS_AWAKE = 1;
+    // Wakefulness: The device is napping.  It is deciding whether to dream or go to sleep
+    // but hasn't gotten around to it yet.  It can be awoken by a call to wakeUp(), which
+    // ends the nap. User activity may brighten the screen but does not end the nap.
+    private static final int WAKEFULNESS_NAPPING = 2;
+    // Wakefulness: The device is dreaming.  It can be awoken by a call to wakeUp(),
+    // which ends the dream.  The device goes to sleep when goToSleep() is called, when
+    // the dream ends or when unplugged.
+    // User activity may brighten the screen but does not end the dream.
+    private static final int WAKEFULNESS_DREAMING = 3;
+
+    // Summarizes the state of all active wakelocks.
+    private static final int WAKE_LOCK_CPU = 1 << 0;
+    private static final int WAKE_LOCK_SCREEN_BRIGHT = 1 << 1;
+    private static final int WAKE_LOCK_SCREEN_DIM = 1 << 2;
+    private static final int WAKE_LOCK_BUTTON_BRIGHT = 1 << 3;
+    private static final int WAKE_LOCK_PROXIMITY_SCREEN_OFF = 1 << 4;
+    private static final int WAKE_LOCK_STAY_AWAKE = 1 << 5; // only set if already awake
+
+    // Summarizes the user activity state.
+    private static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0;
+    private static final int USER_ACTIVITY_SCREEN_DIM = 1 << 1;
+
+    // Default and minimum screen off timeout in milliseconds.
+    private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15 * 1000;
+    private static final int MINIMUM_SCREEN_OFF_TIMEOUT = 10 * 1000;
+
+    // The screen dim duration, in milliseconds.
+    // This is subtracted from the end of the screen off timeout so the
+    // minimum screen off timeout should be longer than this.
+    private static final int SCREEN_DIM_DURATION = 7 * 1000;
+
+    // The maximum screen dim time expressed as a ratio relative to the screen
+    // off timeout.  If the screen off timeout is very short then we want the
+    // dim timeout to also be quite short so that most of the time is spent on.
+    // Otherwise the user won't get much screen on time before dimming occurs.
+    private static final float MAXIMUM_SCREEN_DIM_RATIO = 0.2f;
+
+    // Upper bound on the battery charge percentage in order to consider turning
+    // the screen on when the device starts charging wirelessly.
+    // See point of use for more details.
+    private static final int WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT = 95;
+
+    // The name of the boot animation service in init.rc.
+    private static final String BOOT_ANIMATION_SERVICE = "bootanim";
+
+    // Poll interval in milliseconds for watching boot animation finished.
+    private static final int BOOT_ANIMATION_POLL_INTERVAL = 200;
+
+    // If the battery level drops by this percentage and the user activity timeout
+    // has expired, then assume the device is receiving insufficient current to charge
+    // effectively and terminate the dream.
+    private static final int DREAM_BATTERY_LEVEL_DRAIN_CUTOFF = 5;
+
+    private Context mContext;
+    private LightsService mLightsService;
+    private BatteryService mBatteryService;
+    private DisplayManagerService mDisplayManagerService;
+    private IBatteryStats mBatteryStats;
+    private HandlerThread mHandlerThread;
+    private PowerManagerHandler mHandler;
+    private WindowManagerPolicy mPolicy;
+    private Notifier mNotifier;
+    private DisplayPowerController mDisplayPowerController;
+    private SettingsObserver mSettingsObserver;
+    private DreamManagerService mDreamManager;
+    private LightsService.Light mAttentionLight;
+
+    private final Object mLock = new Object();
+
+    // A bitfield that indicates what parts of the power state have
+    // changed and need to be recalculated.
+    private int mDirty;
+
+    // Indicates whether the device is awake or asleep or somewhere in between.
+    // This is distinct from the screen power state, which is managed separately.
+    private int mWakefulness;
+
+    // True if MSG_SANDMAN has been scheduled.
+    private boolean mSandmanScheduled;
+
+    // Table of all suspend blockers.
+    // There should only be a few of these.
+    private final ArrayList<SuspendBlocker> mSuspendBlockers = new ArrayList<SuspendBlocker>();
+
+    // Table of all wake locks acquired by applications.
+    private final ArrayList<WakeLock> mWakeLocks = new ArrayList<WakeLock>();
+
+    // A bitfield that summarizes the state of all active wakelocks.
+    private int mWakeLockSummary;
+
+    // If true, instructs the display controller to wait for the proximity sensor to
+    // go negative before turning the screen on.
+    private boolean mRequestWaitForNegativeProximity;
+
+    // Timestamp of the last time the device was awoken or put to sleep.
+    private long mLastWakeTime;
+    private long mLastSleepTime;
+
+    // True if we need to send a wake up or go to sleep finished notification
+    // when the display is ready.
+    private boolean mSendWakeUpFinishedNotificationWhenReady;
+    private boolean mSendGoToSleepFinishedNotificationWhenReady;
+
+    // Timestamp of the last call to user activity.
+    private long mLastUserActivityTime;
+    private long mLastUserActivityTimeNoChangeLights;
+
+    // A bitfield that summarizes the effect of the user activity timer.
+    // A zero value indicates that the user activity timer has expired.
+    private int mUserActivitySummary;
+
+    // The desired display power state.  The actual state may lag behind the
+    // requested because it is updated asynchronously by the display power controller.
+    private final DisplayPowerRequest mDisplayPowerRequest = new DisplayPowerRequest();
+
+    // The time the screen was last turned off, in elapsedRealtime() timebase.
+    private long mLastScreenOffEventElapsedRealTime;
+
+    // True if the display power state has been fully applied, which means the display
+    // is actually on or actually off or whatever was requested.
+    private boolean mDisplayReady;
+
+    // True if holding a wake-lock to block suspend of the CPU.
+    private boolean mHoldingWakeLockSuspendBlocker;
+
+    // The suspend blocker used to keep the CPU alive when wake locks have been acquired.
+    private final SuspendBlocker mWakeLockSuspendBlocker;
+
+    // The screen on blocker used to keep the screen from turning on while the lock
+    // screen is coming up.
+    private final ScreenOnBlockerImpl mScreenOnBlocker;
+
+    // The display blanker used to turn the screen on or off.
+    private final DisplayBlankerImpl mDisplayBlanker;
+
+    // True if systemReady() has been called.
+    private boolean mSystemReady;
+
+    // True if boot completed occurred.  We keep the screen on until this happens.
+    private boolean mBootCompleted;
+
+    // True if the device is plugged into a power source.
+    private boolean mIsPowered;
+
+    // The current plug type, such as BatteryManager.BATTERY_PLUGGED_WIRELESS.
+    private int mPlugType;
+
+    // The current battery level percentage.
+    private int mBatteryLevel;
+
+    // The battery level percentage at the time the dream started.
+    // This is used to terminate a dream and go to sleep if the battery is
+    // draining faster than it is charging and the user activity timeout has expired.
+    private int mBatteryLevelWhenDreamStarted;
+
+    // The current dock state.
+    private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
+
+    // True if the device should wake up when plugged or unplugged.
+    private boolean mWakeUpWhenPluggedOrUnpluggedConfig;
+
+    // True if dreams are supported on this device.
+    private boolean mDreamsSupportedConfig;
+
+    // Default value for dreams enabled
+    private boolean mDreamsEnabledByDefaultConfig;
+
+    // Default value for dreams activate-on-sleep
+    private boolean mDreamsActivatedOnSleepByDefaultConfig;
+
+    // Default value for dreams activate-on-dock
+    private boolean mDreamsActivatedOnDockByDefaultConfig;
+
+    // True if dreams are enabled by the user.
+    private boolean mDreamsEnabledSetting;
+
+    // True if dreams should be activated on sleep.
+    private boolean mDreamsActivateOnSleepSetting;
+
+    // True if dreams should be activated on dock.
+    private boolean mDreamsActivateOnDockSetting;
+
+    // The screen off timeout setting value in milliseconds.
+    private int mScreenOffTimeoutSetting;
+
+    // The maximum allowable screen off timeout according to the device
+    // administration policy.  Overrides other settings.
+    private int mMaximumScreenOffTimeoutFromDeviceAdmin = Integer.MAX_VALUE;
+
+    // The stay on while plugged in setting.
+    // A bitfield of battery conditions under which to make the screen stay on.
+    private int mStayOnWhilePluggedInSetting;
+
+    // True if the device should stay on.
+    private boolean mStayOn;
+
+    // True if the proximity sensor reads a positive result.
+    private boolean mProximityPositive;
+
+    // Screen brightness setting limits.
+    private int mScreenBrightnessSettingMinimum;
+    private int mScreenBrightnessSettingMaximum;
+    private int mScreenBrightnessSettingDefault;
+
+    // The screen brightness setting, from 0 to 255.
+    // Use -1 if no value has been set.
+    private int mScreenBrightnessSetting;
+
+    // The screen auto-brightness adjustment setting, from -1 to 1.
+    // Use 0 if there is no adjustment.
+    private float mScreenAutoBrightnessAdjustmentSetting;
+
+    // The screen brightness mode.
+    // One of the Settings.System.SCREEN_BRIGHTNESS_MODE_* constants.
+    private int mScreenBrightnessModeSetting;
+
+    // The screen brightness setting override from the window manager
+    // to allow the current foreground activity to override the brightness.
+    // Use -1 to disable.
+    private int mScreenBrightnessOverrideFromWindowManager = -1;
+
+    // The user activity timeout override from the window manager
+    // to allow the current foreground activity to override the user activity timeout.
+    // Use -1 to disable.
+    private long mUserActivityTimeoutOverrideFromWindowManager = -1;
+
+    // The screen brightness setting override from the settings application
+    // to temporarily adjust the brightness until next updated,
+    // Use -1 to disable.
+    private int mTemporaryScreenBrightnessSettingOverride = -1;
+
+    // The screen brightness adjustment setting override from the settings
+    // application to temporarily adjust the auto-brightness adjustment factor
+    // until next updated, in the range -1..1.
+    // Use NaN to disable.
+    private float mTemporaryScreenAutoBrightnessAdjustmentSettingOverride = Float.NaN;
+
+    // Time when we last logged a warning about calling userActivity() without permission.
+    private long mLastWarningAboutUserActivityPermission = Long.MIN_VALUE;
+
+    private native void nativeInit();
+    private static native void nativeShutdown();
+    private static native void nativeReboot(String reason) throws IOException;
+
+    private static native void nativeSetPowerState(boolean screenOn, boolean screenBright);
+    private static native void nativeAcquireSuspendBlocker(String name);
+    private static native void nativeReleaseSuspendBlocker(String name);
+    private static native void nativeSetInteractive(boolean enable);
+    private static native void nativeSetAutoSuspend(boolean enable);
+
+    public PowerManagerService() {
+        synchronized (mLock) {
+            mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService");
+            mWakeLockSuspendBlocker.acquire();
+            mScreenOnBlocker = new ScreenOnBlockerImpl();
+            mDisplayBlanker = new DisplayBlankerImpl();
+            mHoldingWakeLockSuspendBlocker = true;
+            mWakefulness = WAKEFULNESS_AWAKE;
+        }
+
+        nativeInit();
+        nativeSetPowerState(true, true);
+    }
+
+    /**
+     * Initialize the power manager.
+     * Must be called before any other functions within the power manager are called.
+     */
+    public void init(Context context, LightsService ls,
+            ActivityManagerService am, BatteryService bs, IBatteryStats bss,
+            DisplayManagerService dm) {
+        mContext = context;
+        mLightsService = ls;
+        mBatteryService = bs;
+        mBatteryStats = bss;
+        mDisplayManagerService = dm;
+        mHandlerThread = new HandlerThread(TAG);
+        mHandlerThread.start();
+        mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
+
+        Watchdog.getInstance().addMonitor(this);
+
+        // Forcibly turn the screen on at boot so that it is in a known power state.
+        // We do this in init() rather than in the constructor because setting the
+        // screen state requires a call into surface flinger which then needs to call back
+        // into the activity manager to check permissions.  Unfortunately the
+        // activity manager is not running when the constructor is called, so we
+        // have to defer setting the screen state until this point.
+        mDisplayBlanker.unblankAllDisplays();
+    }
+
+    public void setPolicy(WindowManagerPolicy policy) {
+        synchronized (mLock) {
+            mPolicy = policy;
+        }
+    }
+
+    public void systemReady(TwilightService twilight, DreamManagerService dreamManager) {
+        synchronized (mLock) {
+            mSystemReady = true;
+            mDreamManager = dreamManager;
+
+            PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+            mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
+            mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
+            mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
+
+            // The notifier runs on the system server's main looper so as not to interfere
+            // with the animations and other critical functions of the power manager.
+            mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
+                    createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
+                    mScreenOnBlocker, mPolicy);
+
+            // The display power controller runs on the power manager service's
+            // own handler thread.
+            mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(),
+                    mContext, mNotifier, mLightsService, twilight,
+                    mDisplayBlanker, mDisplayPowerControllerCallbacks, mHandler);
+
+            mSettingsObserver = new SettingsObserver(mHandler);
+            mAttentionLight = mLightsService.getLight(LightsService.LIGHT_ID_ATTENTION);
+
+            // Register for broadcasts from other components of the system.
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+            mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler);
+
+            filter = new IntentFilter();
+            filter.addAction(Intent.ACTION_BOOT_COMPLETED);
+            mContext.registerReceiver(new BootCompletedReceiver(), filter, null, mHandler);
+
+            filter = new IntentFilter();
+            filter.addAction(Intent.ACTION_DREAMING_STARTED);
+            filter.addAction(Intent.ACTION_DREAMING_STOPPED);
+            mContext.registerReceiver(new DreamReceiver(), filter, null, mHandler);
+
+            filter = new IntentFilter();
+            filter.addAction(Intent.ACTION_USER_SWITCHED);
+            mContext.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler);
+
+            filter = new IntentFilter();
+            filter.addAction(Intent.ACTION_DOCK_EVENT);
+            mContext.registerReceiver(new DockReceiver(), filter, null, mHandler);
+
+            // Register for settings changes.
+            final ContentResolver resolver = mContext.getContentResolver();
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.SCREENSAVER_ENABLED),
+                    false, mSettingsObserver, UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP),
+                    false, mSettingsObserver, UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK),
+                    false, mSettingsObserver, UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.SCREEN_OFF_TIMEOUT),
+                    false, mSettingsObserver, UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.STAY_ON_WHILE_PLUGGED_IN),
+                    false, mSettingsObserver, UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.SCREEN_BRIGHTNESS),
+                    false, mSettingsObserver, UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.SCREEN_BRIGHTNESS_MODE),
+                    false, mSettingsObserver, UserHandle.USER_ALL);
+
+            // Go.
+            readConfigurationLocked();
+            updateSettingsLocked();
+            mDirty |= DIRTY_BATTERY_STATE;
+            updatePowerStateLocked();
+        }
+    }
+
+    private void readConfigurationLocked() {
+        final Resources resources = mContext.getResources();
+
+        mWakeUpWhenPluggedOrUnpluggedConfig = resources.getBoolean(
+                com.android.internal.R.bool.config_unplugTurnsOnScreen);
+        mDreamsSupportedConfig = resources.getBoolean(
+                com.android.internal.R.bool.config_dreamsSupported);
+        mDreamsEnabledByDefaultConfig = resources.getBoolean(
+                com.android.internal.R.bool.config_dreamsEnabledByDefault);
+        mDreamsActivatedOnSleepByDefaultConfig = resources.getBoolean(
+                com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
+        mDreamsActivatedOnDockByDefaultConfig = resources.getBoolean(
+                com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
+    }
+
+    private void updateSettingsLocked() {
+        final ContentResolver resolver = mContext.getContentResolver();
+
+        mDreamsEnabledSetting = (Settings.Secure.getIntForUser(resolver,
+                Settings.Secure.SCREENSAVER_ENABLED,
+                mDreamsEnabledByDefaultConfig ? 1 : 0,
+                UserHandle.USER_CURRENT) != 0);
+        mDreamsActivateOnSleepSetting = (Settings.Secure.getIntForUser(resolver,
+                Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
+                mDreamsActivatedOnSleepByDefaultConfig ? 1 : 0,
+                UserHandle.USER_CURRENT) != 0);
+        mDreamsActivateOnDockSetting = (Settings.Secure.getIntForUser(resolver,
+                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
+                mDreamsActivatedOnDockByDefaultConfig ? 1 : 0,
+                UserHandle.USER_CURRENT) != 0);
+        mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver,
+                Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT,
+                UserHandle.USER_CURRENT);
+        mStayOnWhilePluggedInSetting = Settings.Global.getInt(resolver,
+                Settings.Global.STAY_ON_WHILE_PLUGGED_IN, BatteryManager.BATTERY_PLUGGED_AC);
+
+        final int oldScreenBrightnessSetting = mScreenBrightnessSetting;
+        mScreenBrightnessSetting = Settings.System.getIntForUser(resolver,
+                Settings.System.SCREEN_BRIGHTNESS, mScreenBrightnessSettingDefault,
+                UserHandle.USER_CURRENT);
+        if (oldScreenBrightnessSetting != mScreenBrightnessSetting) {
+            mTemporaryScreenBrightnessSettingOverride = -1;
+        }
+
+        final float oldScreenAutoBrightnessAdjustmentSetting =
+                mScreenAutoBrightnessAdjustmentSetting;
+        mScreenAutoBrightnessAdjustmentSetting = Settings.System.getFloatForUser(resolver,
+                Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f,
+                UserHandle.USER_CURRENT);
+        if (oldScreenAutoBrightnessAdjustmentSetting != mScreenAutoBrightnessAdjustmentSetting) {
+            mTemporaryScreenAutoBrightnessAdjustmentSettingOverride = Float.NaN;
+        }
+
+        mScreenBrightnessModeSetting = Settings.System.getIntForUser(resolver,
+                Settings.System.SCREEN_BRIGHTNESS_MODE,
+                Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT);
+
+        mDirty |= DIRTY_SETTINGS;
+    }
+
+    private void handleSettingsChangedLocked() {
+        updateSettingsLocked();
+        updatePowerStateLocked();
+    }
+
+    @Override // Binder call
+    public void acquireWakeLock(IBinder lock, int flags, String tag, WorkSource ws) {
+        if (lock == null) {
+            throw new IllegalArgumentException("lock must not be null");
+        }
+        PowerManager.validateWakeLockParameters(flags, tag);
+
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+        if (ws != null && ws.size() != 0) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.UPDATE_DEVICE_STATS, null);
+        } else {
+            ws = null;
+        }
+
+        final int uid = Binder.getCallingUid();
+        final int pid = Binder.getCallingPid();
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            acquireWakeLockInternal(lock, flags, tag, ws, uid, pid);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void acquireWakeLockInternal(IBinder lock, int flags, String tag, WorkSource ws,
+            int uid, int pid) {
+        synchronized (mLock) {
+            if (DEBUG_SPEW) {
+                Slog.d(TAG, "acquireWakeLockInternal: lock=" + Objects.hashCode(lock)
+                        + ", flags=0x" + Integer.toHexString(flags)
+                        + ", tag=\"" + tag + "\", ws=" + ws + ", uid=" + uid + ", pid=" + pid);
+            }
+
+            WakeLock wakeLock;
+            int index = findWakeLockIndexLocked(lock);
+            if (index >= 0) {
+                wakeLock = mWakeLocks.get(index);
+                if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {
+                    // Update existing wake lock.  This shouldn't happen but is harmless.
+                    notifyWakeLockReleasedLocked(wakeLock);
+                    wakeLock.updateProperties(flags, tag, ws, uid, pid);
+                    notifyWakeLockAcquiredLocked(wakeLock);
+                }
+            } else {
+                wakeLock = new WakeLock(lock, flags, tag, ws, uid, pid);
+                try {
+                    lock.linkToDeath(wakeLock, 0);
+                } catch (RemoteException ex) {
+                    throw new IllegalArgumentException("Wake lock is already dead.");
+                }
+                notifyWakeLockAcquiredLocked(wakeLock);
+                mWakeLocks.add(wakeLock);
+            }
+
+            applyWakeLockFlagsOnAcquireLocked(wakeLock);
+            mDirty |= DIRTY_WAKE_LOCKS;
+            updatePowerStateLocked();
+        }
+    }
+
+    private void applyWakeLockFlagsOnAcquireLocked(WakeLock wakeLock) {
+        if ((wakeLock.mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
+            wakeUpNoUpdateLocked(SystemClock.uptimeMillis());
+        }
+    }
+
+    @Override // Binder call
+    public void releaseWakeLock(IBinder lock, int flags) {
+        if (lock == null) {
+            throw new IllegalArgumentException("lock must not be null");
+        }
+
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            releaseWakeLockInternal(lock, flags);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void releaseWakeLockInternal(IBinder lock, int flags) {
+        synchronized (mLock) {
+            if (DEBUG_SPEW) {
+                Slog.d(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock)
+                        + ", flags=0x" + Integer.toHexString(flags));
+            }
+
+            int index = findWakeLockIndexLocked(lock);
+            if (index < 0) {
+                return;
+            }
+
+            WakeLock wakeLock = mWakeLocks.get(index);
+            mWakeLocks.remove(index);
+            notifyWakeLockReleasedLocked(wakeLock);
+            wakeLock.mLock.unlinkToDeath(wakeLock, 0);
+
+            if ((flags & PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE) != 0) {
+                mRequestWaitForNegativeProximity = true;
+            }
+
+            applyWakeLockFlagsOnReleaseLocked(wakeLock);
+            mDirty |= DIRTY_WAKE_LOCKS;
+            updatePowerStateLocked();
+        }
+    }
+
+    private void handleWakeLockDeath(WakeLock wakeLock) {
+        synchronized (mLock) {
+            if (DEBUG_SPEW) {
+                Slog.d(TAG, "handleWakeLockDeath: lock=" + Objects.hashCode(wakeLock.mLock));
+            }
+
+            int index = mWakeLocks.indexOf(wakeLock);
+            if (index < 0) {
+                return;
+            }
+
+            mWakeLocks.remove(index);
+            notifyWakeLockReleasedLocked(wakeLock);
+
+            applyWakeLockFlagsOnReleaseLocked(wakeLock);
+            mDirty |= DIRTY_WAKE_LOCKS;
+            updatePowerStateLocked();
+        }
+    }
+
+    private void applyWakeLockFlagsOnReleaseLocked(WakeLock wakeLock) {
+        if ((wakeLock.mFlags & PowerManager.ON_AFTER_RELEASE) != 0) {
+            userActivityNoUpdateLocked(SystemClock.uptimeMillis(),
+                    PowerManager.USER_ACTIVITY_EVENT_OTHER,
+                    PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS,
+                    wakeLock.mOwnerUid);
+        }
+    }
+
+    @Override // Binder call
+    public void updateWakeLockWorkSource(IBinder lock, WorkSource ws) {
+        if (lock == null) {
+            throw new IllegalArgumentException("lock must not be null");
+        }
+
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+        if (ws != null && ws.size() != 0) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.UPDATE_DEVICE_STATS, null);
+        } else {
+            ws = null;
+        }
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            updateWakeLockWorkSourceInternal(lock, ws);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void updateWakeLockWorkSourceInternal(IBinder lock, WorkSource ws) {
+        synchronized (mLock) {
+            int index = findWakeLockIndexLocked(lock);
+            if (index < 0) {
+                throw new IllegalArgumentException("Wake lock not active");
+            }
+
+            WakeLock wakeLock = mWakeLocks.get(index);
+            if (!wakeLock.hasSameWorkSource(ws)) {
+                notifyWakeLockReleasedLocked(wakeLock);
+                wakeLock.updateWorkSource(ws);
+                notifyWakeLockAcquiredLocked(wakeLock);
+            }
+        }
+    }
+
+    private int findWakeLockIndexLocked(IBinder lock) {
+        final int count = mWakeLocks.size();
+        for (int i = 0; i < count; i++) {
+            if (mWakeLocks.get(i).mLock == lock) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private void notifyWakeLockAcquiredLocked(WakeLock wakeLock) {
+        if (mSystemReady) {
+            mNotifier.onWakeLockAcquired(wakeLock.mFlags, wakeLock.mTag,
+                    wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource);
+        }
+    }
+
+    private void notifyWakeLockReleasedLocked(WakeLock wakeLock) {
+        if (mSystemReady) {
+            mNotifier.onWakeLockReleased(wakeLock.mFlags, wakeLock.mTag,
+                    wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource);
+        }
+    }
+
+    @Override // Binder call
+    public boolean isWakeLockLevelSupported(int level) {
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            return isWakeLockLevelSupportedInternal(level);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private boolean isWakeLockLevelSupportedInternal(int level) {
+        synchronized (mLock) {
+            switch (level) {
+                case PowerManager.PARTIAL_WAKE_LOCK:
+                case PowerManager.SCREEN_DIM_WAKE_LOCK:
+                case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
+                case PowerManager.FULL_WAKE_LOCK:
+                    return true;
+
+                case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
+                    return mSystemReady && mDisplayPowerController.isProximitySensorAvailable();
+
+                default:
+                    return false;
+            }
+        }
+    }
+
+    @Override // Binder call
+    public void userActivity(long eventTime, int event, int flags) {
+        final long now = SystemClock.uptimeMillis();
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
+                != PackageManager.PERMISSION_GRANTED) {
+            // Once upon a time applications could call userActivity().
+            // Now we require the DEVICE_POWER permission.  Log a warning and ignore the
+            // request instead of throwing a SecurityException so we don't break old apps.
+            synchronized (mLock) {
+                if (now >= mLastWarningAboutUserActivityPermission + (5 * 60 * 1000)) {
+                    mLastWarningAboutUserActivityPermission = now;
+                    Slog.w(TAG, "Ignoring call to PowerManager.userActivity() because the "
+                            + "caller does not have DEVICE_POWER permission.  "
+                            + "Please fix your app!  "
+                            + " pid=" + Binder.getCallingPid()
+                            + " uid=" + Binder.getCallingUid());
+                }
+            }
+            return;
+        }
+
+        if (eventTime > SystemClock.uptimeMillis()) {
+            throw new IllegalArgumentException("event time must not be in the future");
+        }
+
+        final int uid = Binder.getCallingUid();
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            userActivityInternal(eventTime, event, flags, uid);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    // Called from native code.
+    private void userActivityFromNative(long eventTime, int event, int flags) {
+        userActivityInternal(eventTime, event, flags, Process.SYSTEM_UID);
+    }
+
+    private void userActivityInternal(long eventTime, int event, int flags, int uid) {
+        synchronized (mLock) {
+            if (userActivityNoUpdateLocked(eventTime, event, flags, uid)) {
+                updatePowerStateLocked();
+            }
+        }
+    }
+
+    private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, int uid) {
+        if (DEBUG_SPEW) {
+            Slog.d(TAG, "userActivityNoUpdateLocked: eventTime=" + eventTime
+                    + ", event=" + event + ", flags=0x" + Integer.toHexString(flags)
+                    + ", uid=" + uid);
+        }
+
+        if (eventTime < mLastSleepTime || eventTime < mLastWakeTime
+                || mWakefulness == WAKEFULNESS_ASLEEP || !mBootCompleted || !mSystemReady) {
+            return false;
+        }
+
+        mNotifier.onUserActivity(event, uid);
+
+        if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {
+            if (eventTime > mLastUserActivityTimeNoChangeLights
+                    && eventTime > mLastUserActivityTime) {
+                mLastUserActivityTimeNoChangeLights = eventTime;
+                mDirty |= DIRTY_USER_ACTIVITY;
+                return true;
+            }
+        } else {
+            if (eventTime > mLastUserActivityTime) {
+                mLastUserActivityTime = eventTime;
+                mDirty |= DIRTY_USER_ACTIVITY;
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override // Binder call
+    public void wakeUp(long eventTime) {
+        if (eventTime > SystemClock.uptimeMillis()) {
+            throw new IllegalArgumentException("event time must not be in the future");
+        }
+
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            wakeUpInternal(eventTime);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    // Called from native code.
+    private void wakeUpFromNative(long eventTime) {
+        wakeUpInternal(eventTime);
+    }
+
+    private void wakeUpInternal(long eventTime) {
+        synchronized (mLock) {
+            if (wakeUpNoUpdateLocked(eventTime)) {
+                updatePowerStateLocked();
+            }
+        }
+    }
+
+    private boolean wakeUpNoUpdateLocked(long eventTime) {
+        if (DEBUG_SPEW) {
+            Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime);
+        }
+
+        if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE
+                || !mBootCompleted || !mSystemReady) {
+            return false;
+        }
+
+        switch (mWakefulness) {
+            case WAKEFULNESS_ASLEEP:
+                Slog.i(TAG, "Waking up from sleep...");
+                sendPendingNotificationsLocked();
+                mNotifier.onWakeUpStarted();
+                mSendWakeUpFinishedNotificationWhenReady = true;
+                break;
+            case WAKEFULNESS_DREAMING:
+                Slog.i(TAG, "Waking up from dream...");
+                break;
+            case WAKEFULNESS_NAPPING:
+                Slog.i(TAG, "Waking up from nap...");
+                break;
+        }
+
+        mLastWakeTime = eventTime;
+        mWakefulness = WAKEFULNESS_AWAKE;
+        mDirty |= DIRTY_WAKEFULNESS;
+
+        userActivityNoUpdateLocked(
+                eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
+        return true;
+    }
+
+    @Override // Binder call
+    public void goToSleep(long eventTime, int reason) {
+        if (eventTime > SystemClock.uptimeMillis()) {
+            throw new IllegalArgumentException("event time must not be in the future");
+        }
+
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            goToSleepInternal(eventTime, reason);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    // Called from native code.
+    private void goToSleepFromNative(long eventTime, int reason) {
+        goToSleepInternal(eventTime, reason);
+    }
+
+    private void goToSleepInternal(long eventTime, int reason) {
+        synchronized (mLock) {
+            if (goToSleepNoUpdateLocked(eventTime, reason)) {
+                updatePowerStateLocked();
+            }
+        }
+    }
+
+    private boolean goToSleepNoUpdateLocked(long eventTime, int reason) {
+        if (DEBUG_SPEW) {
+            Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime + ", reason=" + reason);
+        }
+
+        if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP
+                || !mBootCompleted || !mSystemReady) {
+            return false;
+        }
+
+        switch (reason) {
+            case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
+                Slog.i(TAG, "Going to sleep due to device administration policy...");
+                break;
+            case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
+                Slog.i(TAG, "Going to sleep due to screen timeout...");
+                break;
+            default:
+                Slog.i(TAG, "Going to sleep by user request...");
+                reason = PowerManager.GO_TO_SLEEP_REASON_USER;
+                break;
+        }
+
+        sendPendingNotificationsLocked();
+        mNotifier.onGoToSleepStarted(reason);
+        mSendGoToSleepFinishedNotificationWhenReady = true;
+
+        mLastSleepTime = eventTime;
+        mDirty |= DIRTY_WAKEFULNESS;
+        mWakefulness = WAKEFULNESS_ASLEEP;
+
+        // Report the number of wake locks that will be cleared by going to sleep.
+        int numWakeLocksCleared = 0;
+        final int numWakeLocks = mWakeLocks.size();
+        for (int i = 0; i < numWakeLocks; i++) {
+            final WakeLock wakeLock = mWakeLocks.get(i);
+            switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
+                case PowerManager.FULL_WAKE_LOCK:
+                case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
+                case PowerManager.SCREEN_DIM_WAKE_LOCK:
+                    numWakeLocksCleared += 1;
+                    break;
+            }
+        }
+        EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);
+        return true;
+    }
+
+    @Override // Binder call
+    public void nap(long eventTime) {
+        if (eventTime > SystemClock.uptimeMillis()) {
+            throw new IllegalArgumentException("event time must not be in the future");
+        }
+
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            napInternal(eventTime);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void napInternal(long eventTime) {
+        synchronized (mLock) {
+            if (napNoUpdateLocked(eventTime)) {
+                updatePowerStateLocked();
+            }
+        }
+    }
+
+    private boolean napNoUpdateLocked(long eventTime) {
+        if (DEBUG_SPEW) {
+            Slog.d(TAG, "napNoUpdateLocked: eventTime=" + eventTime);
+        }
+
+        if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE
+                || !mBootCompleted || !mSystemReady) {
+            return false;
+        }
+
+        Slog.i(TAG, "Nap time...");
+
+        mDirty |= DIRTY_WAKEFULNESS;
+        mWakefulness = WAKEFULNESS_NAPPING;
+        return true;
+    }
+
+    /**
+     * Updates the global power state based on dirty bits recorded in mDirty.
+     *
+     * This is the main function that performs power state transitions.
+     * We centralize them here so that we can recompute the power state completely
+     * each time something important changes, and ensure that we do it the same
+     * way each time.  The point is to gather all of the transition logic here.
+     */
+    private void updatePowerStateLocked() {
+        if (!mSystemReady || mDirty == 0) {
+            return;
+        }
+
+        // Phase 0: Basic state updates.
+        updateIsPoweredLocked(mDirty);
+        updateStayOnLocked(mDirty);
+
+        // Phase 1: Update wakefulness.
+        // Loop because the wake lock and user activity computations are influenced
+        // by changes in wakefulness.
+        final long now = SystemClock.uptimeMillis();
+        int dirtyPhase2 = 0;
+        for (;;) {
+            int dirtyPhase1 = mDirty;
+            dirtyPhase2 |= dirtyPhase1;
+            mDirty = 0;
+
+            updateWakeLockSummaryLocked(dirtyPhase1);
+            updateUserActivitySummaryLocked(now, dirtyPhase1);
+            if (!updateWakefulnessLocked(dirtyPhase1)) {
+                break;
+            }
+        }
+
+        // Phase 2: Update dreams and display power state.
+        updateDreamLocked(dirtyPhase2);
+        updateDisplayPowerStateLocked(dirtyPhase2);
+
+        // Phase 3: Send notifications, if needed.
+        if (mDisplayReady) {
+            sendPendingNotificationsLocked();
+        }
+
+        // Phase 4: Update suspend blocker.
+        // Because we might release the last suspend blocker here, we need to make sure
+        // we finished everything else first!
+        updateSuspendBlockerLocked();
+    }
+
+    private void sendPendingNotificationsLocked() {
+        if (mSendWakeUpFinishedNotificationWhenReady) {
+            mSendWakeUpFinishedNotificationWhenReady = false;
+            mNotifier.onWakeUpFinished();
+        }
+        if (mSendGoToSleepFinishedNotificationWhenReady) {
+            mSendGoToSleepFinishedNotificationWhenReady = false;
+            mNotifier.onGoToSleepFinished();
+        }
+    }
+
+    /**
+     * Updates the value of mIsPowered.
+     * Sets DIRTY_IS_POWERED if a change occurred.
+     */
+    private void updateIsPoweredLocked(int dirty) {
+        if ((dirty & DIRTY_BATTERY_STATE) != 0) {
+            final boolean wasPowered = mIsPowered;
+            final int oldPlugType = mPlugType;
+            mIsPowered = mBatteryService.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
+            mPlugType = mBatteryService.getPlugType();
+            mBatteryLevel = mBatteryService.getBatteryLevel();
+
+            if (DEBUG) {
+                Slog.d(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered
+                        + ", mIsPowered=" + mIsPowered
+                        + ", oldPlugType=" + oldPlugType
+                        + ", mPlugType=" + mPlugType
+                        + ", mBatteryLevel=" + mBatteryLevel);
+            }
+
+            if (wasPowered != mIsPowered || oldPlugType != mPlugType) {
+                mDirty |= DIRTY_IS_POWERED;
+
+                // Treat plugging and unplugging the devices as a user activity.
+                // Users find it disconcerting when they plug or unplug the device
+                // and it shuts off right away.
+                // Some devices also wake the device when plugged or unplugged because
+                // they don't have a charging LED.
+                final long now = SystemClock.uptimeMillis();
+                if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType)) {
+                    wakeUpNoUpdateLocked(now);
+                }
+                userActivityNoUpdateLocked(
+                        now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
+            }
+        }
+    }
+
+    private boolean shouldWakeUpWhenPluggedOrUnpluggedLocked(boolean wasPowered, int oldPlugType) {
+        // Don't wake when powered unless configured to do so.
+        if (!mWakeUpWhenPluggedOrUnpluggedConfig) {
+            return false;
+        }
+
+        // FIXME: Need more accurate detection of wireless chargers.
+        //
+        // We are unable to accurately detect whether the device is resting on the
+        // charger unless it is actually receiving power.  This causes us some grief
+        // because the device might not appear to be plugged into the wireless charger
+        // unless it actually charging.
+        //
+        // To avoid spuriously waking the screen, we apply a special policy to
+        // wireless chargers.
+        //
+        // 1. Don't wake the device when unplugged from wireless charger because
+        //    it might be that the device is still resting on the wireless charger
+        //    but is not receiving power anymore because the battery is full.
+        //
+        // 2. Don't wake the device when plugged into a wireless charger if the
+        //    battery already appears to be mostly full.  This situation may indicate
+        //    that the device was resting on the charger the whole time and simply
+        //    wasn't receiving power because the battery was full.  We can't tell
+        //    whether the device was just placed on the charger or whether it has
+        //    been there for half of the night slowly discharging until it hit
+        //    the point where it needed to start charging again.
+        if (wasPowered && !mIsPowered
+                && oldPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
+            return false;
+        }
+        if (!wasPowered && mIsPowered
+                && mPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS
+                && mBatteryLevel >= WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT) {
+            return false;
+        }
+
+        // If already dreaming and becoming powered, then don't wake.
+        if (mIsPowered && (mWakefulness == WAKEFULNESS_NAPPING
+                || mWakefulness == WAKEFULNESS_DREAMING)) {
+            return false;
+        }
+
+        // Otherwise wake up!
+        return true;
+    }
+
+    /**
+     * Updates the value of mStayOn.
+     * Sets DIRTY_STAY_ON if a change occurred.
+     */
+    private void updateStayOnLocked(int dirty) {
+        if ((dirty & (DIRTY_BATTERY_STATE | DIRTY_SETTINGS)) != 0) {
+            final boolean wasStayOn = mStayOn;
+            if (mStayOnWhilePluggedInSetting != 0
+                    && !isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
+                mStayOn = mBatteryService.isPowered(mStayOnWhilePluggedInSetting);
+            } else {
+                mStayOn = false;
+            }
+
+            if (mStayOn != wasStayOn) {
+                mDirty |= DIRTY_STAY_ON;
+            }
+        }
+    }
+
+    /**
+     * Updates the value of mWakeLockSummary to summarize the state of all active wake locks.
+     * Note that most wake-locks are ignored when the system is asleep.
+     *
+     * This function must have no other side-effects.
+     */
+    private void updateWakeLockSummaryLocked(int dirty) {
+        if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
+            mWakeLockSummary = 0;
+
+            final int numWakeLocks = mWakeLocks.size();
+            for (int i = 0; i < numWakeLocks; i++) {
+                final WakeLock wakeLock = mWakeLocks.get(i);
+                switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
+                    case PowerManager.PARTIAL_WAKE_LOCK:
+                        mWakeLockSummary |= WAKE_LOCK_CPU;
+                        break;
+                    case PowerManager.FULL_WAKE_LOCK:
+                        if (mWakefulness != WAKEFULNESS_ASLEEP) {
+                            mWakeLockSummary |= WAKE_LOCK_CPU
+                                    | WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
+                            if (mWakefulness == WAKEFULNESS_AWAKE) {
+                                mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
+                            }
+                        }
+                        break;
+                    case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
+                        if (mWakefulness != WAKEFULNESS_ASLEEP) {
+                            mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_BRIGHT;
+                            if (mWakefulness == WAKEFULNESS_AWAKE) {
+                                mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
+                            }
+                        }
+                        break;
+                    case PowerManager.SCREEN_DIM_WAKE_LOCK:
+                        if (mWakefulness != WAKEFULNESS_ASLEEP) {
+                            mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_DIM;
+                            if (mWakefulness == WAKEFULNESS_AWAKE) {
+                                mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
+                            }
+                        }
+                        break;
+                    case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
+                        if (mWakefulness != WAKEFULNESS_ASLEEP) {
+                            mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_PROXIMITY_SCREEN_OFF;
+                        }
+                        break;
+                }
+            }
+
+            if (DEBUG_SPEW) {
+                Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
+                        + wakefulnessToString(mWakefulness)
+                        + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
+            }
+        }
+    }
+
+    /**
+     * Updates the value of mUserActivitySummary to summarize the user requested
+     * state of the system such as whether the screen should be bright or dim.
+     * Note that user activity is ignored when the system is asleep.
+     *
+     * This function must have no other side-effects.
+     */
+    private void updateUserActivitySummaryLocked(long now, int dirty) {
+        // Update the status of the user activity timeout timer.
+        if ((dirty & (DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
+            mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
+
+            long nextTimeout = 0;
+            if (mWakefulness != WAKEFULNESS_ASLEEP) {
+                final int screenOffTimeout = getScreenOffTimeoutLocked();
+                final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
+
+                mUserActivitySummary = 0;
+                if (mLastUserActivityTime >= mLastWakeTime) {
+                    nextTimeout = mLastUserActivityTime
+                            + screenOffTimeout - screenDimDuration;
+                    if (now < nextTimeout) {
+                        mUserActivitySummary |= USER_ACTIVITY_SCREEN_BRIGHT;
+                    } else {
+                        nextTimeout = mLastUserActivityTime + screenOffTimeout;
+                        if (now < nextTimeout) {
+                            mUserActivitySummary |= USER_ACTIVITY_SCREEN_DIM;
+                        }
+                    }
+                }
+                if (mUserActivitySummary == 0
+                        && mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
+                    nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
+                    if (now < nextTimeout
+                            && mDisplayPowerRequest.screenState
+                                    != DisplayPowerRequest.SCREEN_STATE_OFF) {
+                        mUserActivitySummary = mDisplayPowerRequest.screenState
+                                == DisplayPowerRequest.SCREEN_STATE_BRIGHT ?
+                                USER_ACTIVITY_SCREEN_BRIGHT : USER_ACTIVITY_SCREEN_DIM;
+                    }
+                }
+                if (mUserActivitySummary != 0) {
+                    Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
+                    msg.setAsynchronous(true);
+                    mHandler.sendMessageAtTime(msg, nextTimeout);
+                }
+            } else {
+                mUserActivitySummary = 0;
+            }
+
+            if (DEBUG_SPEW) {
+                Slog.d(TAG, "updateUserActivitySummaryLocked: mWakefulness="
+                        + wakefulnessToString(mWakefulness)
+                        + ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+                        + ", nextTimeout=" + TimeUtils.formatUptime(nextTimeout));
+            }
+        }
+    }
+
+    /**
+     * Called when a user activity timeout has occurred.
+     * Simply indicates that something about user activity has changed so that the new
+     * state can be recomputed when the power state is updated.
+     *
+     * This function must have no other side-effects besides setting the dirty
+     * bit and calling update power state.  Wakefulness transitions are handled elsewhere.
+     */
+    private void handleUserActivityTimeout() { // runs on handler thread
+        synchronized (mLock) {
+            if (DEBUG_SPEW) {
+                Slog.d(TAG, "handleUserActivityTimeout");
+            }
+
+            mDirty |= DIRTY_USER_ACTIVITY;
+            updatePowerStateLocked();
+        }
+    }
+
+    private int getScreenOffTimeoutLocked() {
+        int timeout = mScreenOffTimeoutSetting;
+        if (isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
+            timeout = Math.min(timeout, mMaximumScreenOffTimeoutFromDeviceAdmin);
+        }
+        if (mUserActivityTimeoutOverrideFromWindowManager >= 0) {
+            timeout = (int)Math.min(timeout, mUserActivityTimeoutOverrideFromWindowManager);
+        }
+        return Math.max(timeout, MINIMUM_SCREEN_OFF_TIMEOUT);
+    }
+
+    private int getScreenDimDurationLocked(int screenOffTimeout) {
+        return Math.min(SCREEN_DIM_DURATION,
+                (int)(screenOffTimeout * MAXIMUM_SCREEN_DIM_RATIO));
+    }
+
+    /**
+     * Updates the wakefulness of the device.
+     *
+     * This is the function that decides whether the device should start napping
+     * based on the current wake locks and user activity state.  It may modify mDirty
+     * if the wakefulness changes.
+     *
+     * Returns true if the wakefulness changed and we need to restart power state calculation.
+     */
+    private boolean updateWakefulnessLocked(int dirty) {
+        boolean changed = false;
+        if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED
+                | DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE
+                | DIRTY_DOCK_STATE)) != 0) {
+            if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {
+                if (DEBUG_SPEW) {
+                    Slog.d(TAG, "updateWakefulnessLocked: Bed time...");
+                }
+                final long time = SystemClock.uptimeMillis();
+                if (shouldNapAtBedTimeLocked()) {
+                    changed = napNoUpdateLocked(time);
+                } else {
+                    changed = goToSleepNoUpdateLocked(time,
+                            PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
+                }
+            }
+        }
+        return changed;
+    }
+
+    /**
+     * Returns true if the device should automatically nap and start dreaming when the user
+     * activity timeout has expired and it's bedtime.
+     */
+    private boolean shouldNapAtBedTimeLocked() {
+        return mDreamsActivateOnSleepSetting
+                || (mDreamsActivateOnDockSetting
+                        && mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED);
+    }
+
+    /**
+     * Returns true if the device should go to sleep now.
+     * Also used when exiting a dream to determine whether we should go back
+     * to being fully awake or else go to sleep for good.
+     */
+    private boolean isItBedTimeYetLocked() {
+        return mBootCompleted && !isBeingKeptAwakeLocked();
+    }
+
+    /**
+     * Returns true if the device is being kept awake by a wake lock, user activity
+     * or the stay on while powered setting.
+     */
+    private boolean isBeingKeptAwakeLocked() {
+        return mStayOn
+                || mProximityPositive
+                || (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0
+                || (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
+                        | USER_ACTIVITY_SCREEN_DIM)) != 0;
+    }
+
+    /**
+     * Determines whether to post a message to the sandman to update the dream state.
+     */
+    private void updateDreamLocked(int dirty) {
+        if ((dirty & (DIRTY_WAKEFULNESS
+                | DIRTY_USER_ACTIVITY
+                | DIRTY_WAKE_LOCKS
+                | DIRTY_BOOT_COMPLETED
+                | DIRTY_SETTINGS
+                | DIRTY_IS_POWERED
+                | DIRTY_STAY_ON
+                | DIRTY_PROXIMITY_POSITIVE
+                | DIRTY_BATTERY_STATE)) != 0) {
+            scheduleSandmanLocked();
+        }
+    }
+
+    private void scheduleSandmanLocked() {
+        if (!mSandmanScheduled) {
+            mSandmanScheduled = true;
+            Message msg = mHandler.obtainMessage(MSG_SANDMAN);
+            msg.setAsynchronous(true);
+            mHandler.sendMessage(msg);
+        }
+    }
+
+    /**
+     * Called when the device enters or exits a napping or dreaming state.
+     *
+     * We do this asynchronously because we must call out of the power manager to start
+     * the dream and we don't want to hold our lock while doing so.  There is a risk that
+     * the device will wake or go to sleep in the meantime so we have to handle that case.
+     */
+    private void handleSandman() { // runs on handler thread
+        // Handle preconditions.
+        boolean startDreaming = false;
+        synchronized (mLock) {
+            mSandmanScheduled = false;
+            boolean canDream = canDreamLocked();
+            if (DEBUG_SPEW) {
+                Slog.d(TAG, "handleSandman: canDream=" + canDream
+                        + ", mWakefulness=" + wakefulnessToString(mWakefulness));
+            }
+
+            if (canDream && mWakefulness == WAKEFULNESS_NAPPING) {
+                startDreaming = true;
+            }
+        }
+
+        // Start dreaming if needed.
+        // We only control the dream on the handler thread, so we don't need to worry about
+        // concurrent attempts to start or stop the dream.
+        boolean isDreaming = false;
+        if (mDreamManager != null) {
+            if (startDreaming) {
+                mDreamManager.startDream();
+            }
+            isDreaming = mDreamManager.isDreaming();
+        }
+
+        // Update dream state.
+        // We might need to stop the dream again if the preconditions changed.
+        boolean continueDreaming = false;
+        synchronized (mLock) {
+            if (isDreaming && canDreamLocked()) {
+                if (mWakefulness == WAKEFULNESS_NAPPING) {
+                    mWakefulness = WAKEFULNESS_DREAMING;
+                    mDirty |= DIRTY_WAKEFULNESS;
+                    mBatteryLevelWhenDreamStarted = mBatteryLevel;
+                    updatePowerStateLocked();
+                    continueDreaming = true;
+                } else if (mWakefulness == WAKEFULNESS_DREAMING) {
+                    if (!isBeingKeptAwakeLocked()
+                            && mBatteryLevel < mBatteryLevelWhenDreamStarted
+                                    - DREAM_BATTERY_LEVEL_DRAIN_CUTOFF) {
+                        // If the user activity timeout expired and the battery appears
+                        // to be draining faster than it is charging then stop dreaming
+                        // and go to sleep.
+                        Slog.i(TAG, "Stopping dream because the battery appears to "
+                                + "be draining faster than it is charging.  "
+                                + "Battery level when dream started: "
+                                + mBatteryLevelWhenDreamStarted + "%.  "
+                                + "Battery level now: " + mBatteryLevel + "%.");
+                    } else {
+                        continueDreaming = true;
+                    }
+                }
+            }
+            if (!continueDreaming) {
+                handleDreamFinishedLocked();
+            }
+        }
+
+        // Stop dreaming if needed.
+        // It's possible that something else changed to make us need to start the dream again.
+        // If so, then the power manager will have posted another message to the handler
+        // to take care of it later.
+        if (mDreamManager != null) {
+            if (!continueDreaming) {
+                mDreamManager.stopDream();
+            }
+        }
+    }
+
+    /**
+     * Returns true if the device is allowed to dream in its current state
+     * assuming that it is currently napping or dreaming.
+     */
+    private boolean canDreamLocked() {
+        return mDreamsSupportedConfig
+                && mDreamsEnabledSetting
+                && mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF
+                && mBootCompleted
+                && (mIsPowered || isBeingKeptAwakeLocked());
+    }
+
+    /**
+     * Called when a dream is ending to figure out what to do next.
+     */
+    private void handleDreamFinishedLocked() {
+        if (mWakefulness == WAKEFULNESS_NAPPING
+                || mWakefulness == WAKEFULNESS_DREAMING) {
+            if (isItBedTimeYetLocked()) {
+                goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),
+                        PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
+                updatePowerStateLocked();
+            } else {
+                wakeUpNoUpdateLocked(SystemClock.uptimeMillis());
+                updatePowerStateLocked();
+            }
+        }
+    }
+
+    private void handleScreenOnBlockerReleased() {
+        synchronized (mLock) {
+            mDirty |= DIRTY_SCREEN_ON_BLOCKER_RELEASED;
+            updatePowerStateLocked();
+        }
+    }
+
+    /**
+     * Updates the display power state asynchronously.
+     * When the update is finished, mDisplayReady will be set to true.  The display
+     * controller posts a message to tell us when the actual display power state
+     * has been updated so we come back here to double-check and finish up.
+     *
+     * This function recalculates the display power state each time.
+     */
+    private void updateDisplayPowerStateLocked(int dirty) {
+        if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
+                | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
+                | DIRTY_SETTINGS | DIRTY_SCREEN_ON_BLOCKER_RELEASED)) != 0) {
+            int newScreenState = getDesiredScreenPowerStateLocked();
+            if (newScreenState != mDisplayPowerRequest.screenState) {
+                if (newScreenState == DisplayPowerRequest.SCREEN_STATE_OFF
+                        && mDisplayPowerRequest.screenState
+                                != DisplayPowerRequest.SCREEN_STATE_OFF) {
+                    mLastScreenOffEventElapsedRealTime = SystemClock.elapsedRealtime();
+                }
+
+                mDisplayPowerRequest.screenState = newScreenState;
+                nativeSetPowerState(
+                        newScreenState != DisplayPowerRequest.SCREEN_STATE_OFF,
+                        newScreenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT);
+            }
+
+            int screenBrightness = mScreenBrightnessSettingDefault;
+            float screenAutoBrightnessAdjustment = 0.0f;
+            boolean autoBrightness = (mScreenBrightnessModeSetting ==
+                    Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
+            if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
+                screenBrightness = mScreenBrightnessOverrideFromWindowManager;
+                autoBrightness = false;
+            } else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) {
+                screenBrightness = mTemporaryScreenBrightnessSettingOverride;
+            } else if (isValidBrightness(mScreenBrightnessSetting)) {
+                screenBrightness = mScreenBrightnessSetting;
+            }
+            if (autoBrightness) {
+                screenBrightness = mScreenBrightnessSettingDefault;
+                if (isValidAutoBrightnessAdjustment(
+                        mTemporaryScreenAutoBrightnessAdjustmentSettingOverride)) {
+                    screenAutoBrightnessAdjustment =
+                            mTemporaryScreenAutoBrightnessAdjustmentSettingOverride;
+                } else if (isValidAutoBrightnessAdjustment(
+                        mScreenAutoBrightnessAdjustmentSetting)) {
+                    screenAutoBrightnessAdjustment = mScreenAutoBrightnessAdjustmentSetting;
+                }
+            }
+            screenBrightness = Math.max(Math.min(screenBrightness,
+                    mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
+            screenAutoBrightnessAdjustment = Math.max(Math.min(
+                    screenAutoBrightnessAdjustment, 1.0f), -1.0f);
+            mDisplayPowerRequest.screenBrightness = screenBrightness;
+            mDisplayPowerRequest.screenAutoBrightnessAdjustment =
+                    screenAutoBrightnessAdjustment;
+            mDisplayPowerRequest.useAutoBrightness = autoBrightness;
+
+            mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
+
+            mDisplayPowerRequest.blockScreenOn = mScreenOnBlocker.isHeld();
+
+            mDisplayReady = mDisplayPowerController.requestPowerState(mDisplayPowerRequest,
+                    mRequestWaitForNegativeProximity);
+            mRequestWaitForNegativeProximity = false;
+
+            if (DEBUG_SPEW) {
+                Slog.d(TAG, "updateScreenStateLocked: mDisplayReady=" + mDisplayReady
+                        + ", newScreenState=" + newScreenState
+                        + ", mWakefulness=" + mWakefulness
+                        + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
+                        + ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+                        + ", mBootCompleted=" + mBootCompleted);
+            }
+        }
+    }
+
+    private static boolean isValidBrightness(int value) {
+        return value >= 0 && value <= 255;
+    }
+
+    private static boolean isValidAutoBrightnessAdjustment(float value) {
+        // Handles NaN by always returning false.
+        return value >= -1.0f && value <= 1.0f;
+    }
+
+    private int getDesiredScreenPowerStateLocked() {
+        if (mWakefulness == WAKEFULNESS_ASLEEP) {
+            return DisplayPowerRequest.SCREEN_STATE_OFF;
+        }
+
+        if ((mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0
+                || (mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0
+                || !mBootCompleted) {
+            return DisplayPowerRequest.SCREEN_STATE_BRIGHT;
+        }
+
+        return DisplayPowerRequest.SCREEN_STATE_DIM;
+    }
+
+    private final DisplayPowerController.Callbacks mDisplayPowerControllerCallbacks =
+            new DisplayPowerController.Callbacks() {
+        @Override
+        public void onStateChanged() {
+            mDirty |= DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED;
+            updatePowerStateLocked();
+        }
+
+        @Override
+        public void onProximityPositive() {
+            mProximityPositive = true;
+            mDirty |= DIRTY_PROXIMITY_POSITIVE;
+            updatePowerStateLocked();
+        }
+
+        @Override
+        public void onProximityNegative() {
+            mProximityPositive = false;
+            mDirty |= DIRTY_PROXIMITY_POSITIVE;
+            userActivityNoUpdateLocked(SystemClock.uptimeMillis(),
+                    PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
+            updatePowerStateLocked();
+        }
+    };
+
+    private boolean shouldUseProximitySensorLocked() {
+        return (mWakeLockSummary & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0;
+    }
+
+    /**
+     * Updates the suspend blocker that keeps the CPU alive.
+     *
+     * This function must have no other side-effects.
+     */
+    private void updateSuspendBlockerLocked() {
+        boolean wantCpu = isCpuNeededLocked();
+        if (wantCpu != mHoldingWakeLockSuspendBlocker) {
+            mHoldingWakeLockSuspendBlocker = wantCpu;
+            if (wantCpu) {
+                if (DEBUG) {
+                    Slog.d(TAG, "updateSuspendBlockerLocked: Acquiring suspend blocker.");
+                }
+                mWakeLockSuspendBlocker.acquire();
+            } else {
+                if (DEBUG) {
+                    Slog.d(TAG, "updateSuspendBlockerLocked: Releasing suspend blocker.");
+                }
+                mWakeLockSuspendBlocker.release();
+            }
+        }
+    }
+
+    private boolean isCpuNeededLocked() {
+        return !mBootCompleted
+                || mWakeLockSummary != 0
+                || mUserActivitySummary != 0
+                || mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF
+                || !mDisplayReady;
+    }
+
+    @Override // Binder call
+    public boolean isScreenOn() {
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            return isScreenOnInternal();
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private boolean isScreenOnInternal() {
+        synchronized (mLock) {
+            return !mSystemReady
+                    || mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF;
+        }
+    }
+
+    private void handleBatteryStateChangedLocked() {
+        mDirty |= DIRTY_BATTERY_STATE;
+        updatePowerStateLocked();
+    }
+
+    private void startWatchingForBootAnimationFinished() {
+        mHandler.sendEmptyMessage(MSG_CHECK_IF_BOOT_ANIMATION_FINISHED);
+    }
+
+    private void checkIfBootAnimationFinished() {
+        if (DEBUG) {
+            Slog.d(TAG, "Check if boot animation finished...");
+        }
+
+        if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) {
+            mHandler.sendEmptyMessageDelayed(MSG_CHECK_IF_BOOT_ANIMATION_FINISHED,
+                    BOOT_ANIMATION_POLL_INTERVAL);
+            return;
+        }
+
+        synchronized (mLock) {
+            if (!mBootCompleted) {
+                Slog.i(TAG, "Boot animation finished.");
+                handleBootCompletedLocked();
+            }
+        }
+    }
+
+    private void handleBootCompletedLocked() {
+        final long now = SystemClock.uptimeMillis();
+        mBootCompleted = true;
+        mDirty |= DIRTY_BOOT_COMPLETED;
+        userActivityNoUpdateLocked(
+                now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
+        updatePowerStateLocked();
+    }
+
+    /**
+     * Reboots the device.
+     *
+     * @param confirm If true, shows a reboot confirmation dialog.
+     * @param reason The reason for the reboot, or null if none.
+     * @param wait If true, this call waits for the reboot to complete and does not return.
+     */
+    @Override // Binder call
+    public void reboot(boolean confirm, String reason, boolean wait) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            shutdownOrRebootInternal(false, confirm, reason, wait);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    /**
+     * Shuts down the device.
+     *
+     * @param confirm If true, shows a shutdown confirmation dialog.
+     * @param wait If true, this call waits for the shutdown to complete and does not return.
+     */
+    @Override // Binder call
+    public void shutdown(boolean confirm, boolean wait) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            shutdownOrRebootInternal(true, confirm, null, wait);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm,
+            final String reason, boolean wait) {
+        if (mHandler == null || !mSystemReady) {
+            throw new IllegalStateException("Too early to call shutdown() or reboot()");
+        }
+
+        Runnable runnable = new Runnable() {
+            @Override
+            public void run() {
+                synchronized (this) {
+                    if (shutdown) {
+                        ShutdownThread.shutdown(mContext, confirm);
+                    } else {
+                        ShutdownThread.reboot(mContext, reason, confirm);
+                    }
+                }
+            }
+        };
+
+        // ShutdownThread must run on a looper capable of displaying the UI.
+        Message msg = Message.obtain(mHandler, runnable);
+        msg.setAsynchronous(true);
+        mHandler.sendMessage(msg);
+
+        // PowerManager.reboot() is documented not to return so just wait for the inevitable.
+        if (wait) {
+            synchronized (runnable) {
+                while (true) {
+                    try {
+                        runnable.wait();
+                    } catch (InterruptedException e) {
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Crash the runtime (causing a complete restart of the Android framework).
+     * Requires REBOOT permission.  Mostly for testing.  Should not return.
+     */
+    @Override // Binder call
+    public void crash(String message) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            crashInternal(message);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void crashInternal(final String message) {
+        Thread t = new Thread("PowerManagerService.crash()") {
+            @Override
+            public void run() {
+                throw new RuntimeException(message);
+            }
+        };
+        try {
+            t.start();
+            t.join();
+        } catch (InterruptedException e) {
+            Log.wtf(TAG, e);
+        }
+    }
+
+    /**
+     * Set the setting that determines whether the device stays on when plugged in.
+     * The argument is a bit string, with each bit specifying a power source that,
+     * when the device is connected to that source, causes the device to stay on.
+     * See {@link android.os.BatteryManager} for the list of power sources that
+     * can be specified. Current values include {@link android.os.BatteryManager#BATTERY_PLUGGED_AC}
+     * and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB}
+     *
+     * Used by "adb shell svc power stayon ..."
+     *
+     * @param val an {@code int} containing the bits that specify which power sources
+     * should cause the device to stay on.
+     */
+    @Override // Binder call
+    public void setStayOnSetting(int val) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS, null);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            setStayOnSettingInternal(val);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void setStayOnSettingInternal(int val) {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.STAY_ON_WHILE_PLUGGED_IN, val);
+    }
+
+    /**
+     * Used by device administration to set the maximum screen off timeout.
+     *
+     * This method must only be called by the device administration policy manager.
+     */
+    @Override // Binder call
+    public void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs) {
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            setMaximumScreenOffTimeoutFromDeviceAdminInternal(timeMs);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void setMaximumScreenOffTimeoutFromDeviceAdminInternal(int timeMs) {
+        synchronized (mLock) {
+            mMaximumScreenOffTimeoutFromDeviceAdmin = timeMs;
+            mDirty |= DIRTY_SETTINGS;
+            updatePowerStateLocked();
+        }
+    }
+
+    private boolean isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked() {
+        return mMaximumScreenOffTimeoutFromDeviceAdmin >= 0
+                && mMaximumScreenOffTimeoutFromDeviceAdmin < Integer.MAX_VALUE;
+    }
+
+    /**
+     * Used by the phone application to make the attention LED flash when ringing.
+     */
+    @Override // Binder call
+    public void setAttentionLight(boolean on, int color) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            setAttentionLightInternal(on, color);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void setAttentionLightInternal(boolean on, int color) {
+        LightsService.Light light;
+        synchronized (mLock) {
+            if (!mSystemReady) {
+                return;
+            }
+            light = mAttentionLight;
+        }
+
+        // Control light outside of lock.
+        light.setFlashing(color, LightsService.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0);
+    }
+
+    /**
+     * Used by the Watchdog.
+     */
+    public long timeSinceScreenWasLastOn() {
+        synchronized (mLock) {
+            if (mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
+                return 0;
+            }
+            return SystemClock.elapsedRealtime() - mLastScreenOffEventElapsedRealTime;
+        }
+    }
+
+    /**
+     * Used by the window manager to override the screen brightness based on the
+     * current foreground activity.
+     *
+     * This method must only be called by the window manager.
+     *
+     * @param brightness The overridden brightness, or -1 to disable the override.
+     */
+    public void setScreenBrightnessOverrideFromWindowManager(int brightness) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            setScreenBrightnessOverrideFromWindowManagerInternal(brightness);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void setScreenBrightnessOverrideFromWindowManagerInternal(int brightness) {
+        synchronized (mLock) {
+            if (mScreenBrightnessOverrideFromWindowManager != brightness) {
+                mScreenBrightnessOverrideFromWindowManager = brightness;
+                mDirty |= DIRTY_SETTINGS;
+                updatePowerStateLocked();
+            }
+        }
+    }
+
+    /**
+     * Used by the window manager to override the button brightness based on the
+     * current foreground activity.
+     *
+     * This method must only be called by the window manager.
+     *
+     * @param brightness The overridden brightness, or -1 to disable the override.
+     */
+    public void setButtonBrightnessOverrideFromWindowManager(int brightness) {
+        // Do nothing.
+        // Button lights are not currently supported in the new implementation.
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+    }
+
+    /**
+     * Used by the window manager to override the user activity timeout based on the
+     * current foreground activity.  It can only be used to make the timeout shorter
+     * than usual, not longer.
+     *
+     * This method must only be called by the window manager.
+     *
+     * @param timeoutMillis The overridden timeout, or -1 to disable the override.
+     */
+    public void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            setUserActivityTimeoutOverrideFromWindowManagerInternal(timeoutMillis);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void setUserActivityTimeoutOverrideFromWindowManagerInternal(long timeoutMillis) {
+        synchronized (mLock) {
+            if (mUserActivityTimeoutOverrideFromWindowManager != timeoutMillis) {
+                mUserActivityTimeoutOverrideFromWindowManager = timeoutMillis;
+                mDirty |= DIRTY_SETTINGS;
+                updatePowerStateLocked();
+            }
+        }
+    }
+
+    /**
+     * Used by the settings application and brightness control widgets to
+     * temporarily override the current screen brightness setting so that the
+     * user can observe the effect of an intended settings change without applying
+     * it immediately.
+     *
+     * The override will be canceled when the setting value is next updated.
+     *
+     * @param brightness The overridden brightness.
+     *
+     * @see Settings.System#SCREEN_BRIGHTNESS
+     */
+    @Override // Binder call
+    public void setTemporaryScreenBrightnessSettingOverride(int brightness) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            setTemporaryScreenBrightnessSettingOverrideInternal(brightness);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void setTemporaryScreenBrightnessSettingOverrideInternal(int brightness) {
+        synchronized (mLock) {
+            if (mTemporaryScreenBrightnessSettingOverride != brightness) {
+                mTemporaryScreenBrightnessSettingOverride = brightness;
+                mDirty |= DIRTY_SETTINGS;
+                updatePowerStateLocked();
+            }
+        }
+    }
+
+    /**
+     * Used by the settings application and brightness control widgets to
+     * temporarily override the current screen auto-brightness adjustment setting so that the
+     * user can observe the effect of an intended settings change without applying
+     * it immediately.
+     *
+     * The override will be canceled when the setting value is next updated.
+     *
+     * @param adj The overridden brightness, or Float.NaN to disable the override.
+     *
+     * @see Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ
+     */
+    @Override // Binder call
+    public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(adj);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(float adj) {
+        synchronized (mLock) {
+            // Note: This condition handles NaN because NaN is not equal to any other
+            // value, including itself.
+            if (mTemporaryScreenAutoBrightnessAdjustmentSettingOverride != adj) {
+                mTemporaryScreenAutoBrightnessAdjustmentSettingOverride = adj;
+                mDirty |= DIRTY_SETTINGS;
+                updatePowerStateLocked();
+            }
+        }
+    }
+
+    /**
+     * Low-level function turn the device off immediately, without trying
+     * to be clean.  Most people should use {@link ShutdownThread} for a clean shutdown.
+     */
+    public static void lowLevelShutdown() {
+        nativeShutdown();
+    }
+
+    /**
+     * Low-level function to reboot the device.
+     *
+     * @param reason code to pass to the kernel (e.g. "recovery"), or null.
+     * @throws IOException if reboot fails for some reason (eg, lack of
+     *         permission)
+     */
+    public static void lowLevelReboot(String reason) throws IOException {
+        nativeReboot(reason);
+    }
+
+    @Override // Watchdog.Monitor implementation
+    public void monitor() {
+        // Grab and release lock for watchdog monitor to detect deadlocks.
+        synchronized (mLock) {
+        }
+    }
+
+    @Override // Binder call
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump PowerManager from from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid());
+            return;
+        }
+
+        pw.println("POWER MANAGER (dumpsys power)\n");
+
+        final DisplayPowerController dpc;
+        synchronized (mLock) {
+            pw.println("Power Manager State:");
+            pw.println("  mDirty=0x" + Integer.toHexString(mDirty));
+            pw.println("  mWakefulness=" + wakefulnessToString(mWakefulness));
+            pw.println("  mIsPowered=" + mIsPowered);
+            pw.println("  mPlugType=" + mPlugType);
+            pw.println("  mBatteryLevel=" + mBatteryLevel);
+            pw.println("  mBatteryLevelWhenDreamStarted=" + mBatteryLevelWhenDreamStarted);
+            pw.println("  mDockState=" + mDockState);
+            pw.println("  mStayOn=" + mStayOn);
+            pw.println("  mProximityPositive=" + mProximityPositive);
+            pw.println("  mBootCompleted=" + mBootCompleted);
+            pw.println("  mSystemReady=" + mSystemReady);
+            pw.println("  mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
+            pw.println("  mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary));
+            pw.println("  mRequestWaitForNegativeProximity=" + mRequestWaitForNegativeProximity);
+            pw.println("  mSandmanScheduled=" + mSandmanScheduled);
+            pw.println("  mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime));
+            pw.println("  mLastSleepTime=" + TimeUtils.formatUptime(mLastSleepTime));
+            pw.println("  mSendWakeUpFinishedNotificationWhenReady="
+                    + mSendWakeUpFinishedNotificationWhenReady);
+            pw.println("  mSendGoToSleepFinishedNotificationWhenReady="
+                    + mSendGoToSleepFinishedNotificationWhenReady);
+            pw.println("  mLastUserActivityTime=" + TimeUtils.formatUptime(mLastUserActivityTime));
+            pw.println("  mLastUserActivityTimeNoChangeLights="
+                    + TimeUtils.formatUptime(mLastUserActivityTimeNoChangeLights));
+            pw.println("  mDisplayReady=" + mDisplayReady);
+            pw.println("  mHoldingWakeLockSuspendBlocker=" + mHoldingWakeLockSuspendBlocker);
+
+            pw.println();
+            pw.println("Settings and Configuration:");
+            pw.println("  mDreamsSupportedConfig=" + mDreamsSupportedConfig);
+            pw.println("  mDreamsEnabledSetting=" + mDreamsEnabledSetting);
+            pw.println("  mDreamsActivateOnSleepSetting=" + mDreamsActivateOnSleepSetting);
+            pw.println("  mDreamsActivateOnDockSetting=" + mDreamsActivateOnDockSetting);
+            pw.println("  mScreenOffTimeoutSetting=" + mScreenOffTimeoutSetting);
+            pw.println("  mMaximumScreenOffTimeoutFromDeviceAdmin="
+                    + mMaximumScreenOffTimeoutFromDeviceAdmin + " (enforced="
+                    + isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked() + ")");
+            pw.println("  mStayOnWhilePluggedInSetting=" + mStayOnWhilePluggedInSetting);
+            pw.println("  mScreenBrightnessSetting=" + mScreenBrightnessSetting);
+            pw.println("  mScreenAutoBrightnessAdjustmentSetting="
+                    + mScreenAutoBrightnessAdjustmentSetting);
+            pw.println("  mScreenBrightnessModeSetting=" + mScreenBrightnessModeSetting);
+            pw.println("  mScreenBrightnessOverrideFromWindowManager="
+                    + mScreenBrightnessOverrideFromWindowManager);
+            pw.println("  mUserActivityTimeoutOverrideFromWindowManager="
+                    + mUserActivityTimeoutOverrideFromWindowManager);
+            pw.println("  mTemporaryScreenBrightnessSettingOverride="
+                    + mTemporaryScreenBrightnessSettingOverride);
+            pw.println("  mTemporaryScreenAutoBrightnessAdjustmentSettingOverride="
+                    + mTemporaryScreenAutoBrightnessAdjustmentSettingOverride);
+            pw.println("  mScreenBrightnessSettingMinimum=" + mScreenBrightnessSettingMinimum);
+            pw.println("  mScreenBrightnessSettingMaximum=" + mScreenBrightnessSettingMaximum);
+            pw.println("  mScreenBrightnessSettingDefault=" + mScreenBrightnessSettingDefault);
+
+            final int screenOffTimeout = getScreenOffTimeoutLocked();
+            final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
+            pw.println();
+            pw.println("Screen off timeout: " + screenOffTimeout + " ms");
+            pw.println("Screen dim duration: " + screenDimDuration + " ms");
+
+            pw.println();
+            pw.println("Wake Locks: size=" + mWakeLocks.size());
+            for (WakeLock wl : mWakeLocks) {
+                pw.println("  " + wl);
+            }
+
+            pw.println();
+            pw.println("Suspend Blockers: size=" + mSuspendBlockers.size());
+            for (SuspendBlocker sb : mSuspendBlockers) {
+                pw.println("  " + sb);
+            }
+
+            pw.println();
+            pw.println("Screen On Blocker: " + mScreenOnBlocker);
+
+            pw.println();
+            pw.println("Display Blanker: " + mDisplayBlanker);
+
+            dpc = mDisplayPowerController;
+        }
+
+        if (dpc != null) {
+            dpc.dump(pw);
+        }
+    }
+
+    private SuspendBlocker createSuspendBlockerLocked(String name) {
+        SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name);
+        mSuspendBlockers.add(suspendBlocker);
+        return suspendBlocker;
+    }
+
+    private static String wakefulnessToString(int wakefulness) {
+        switch (wakefulness) {
+            case WAKEFULNESS_ASLEEP:
+                return "Asleep";
+            case WAKEFULNESS_AWAKE:
+                return "Awake";
+            case WAKEFULNESS_DREAMING:
+                return "Dreaming";
+            case WAKEFULNESS_NAPPING:
+                return "Napping";
+            default:
+                return Integer.toString(wakefulness);
+        }
+    }
+
+    private static WorkSource copyWorkSource(WorkSource workSource) {
+        return workSource != null ? new WorkSource(workSource) : null;
+    }
+
+    private final class BatteryReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            synchronized (mLock) {
+                handleBatteryStateChangedLocked();
+            }
+        }
+    }
+
+    private final class BootCompletedReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // This is our early signal that the system thinks it has finished booting.
+            // However, the boot animation may still be running for a few more seconds
+            // since it is ultimately in charge of when it terminates.
+            // Defer transitioning into the boot completed state until the animation exits.
+            // We do this so that the screen does not start to dim prematurely before
+            // the user has actually had a chance to interact with the device.
+            startWatchingForBootAnimationFinished();
+        }
+    }
+
+    private final class DreamReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            synchronized (mLock) {
+                scheduleSandmanLocked();
+            }
+        }
+    }
+
+    private final class UserSwitchedReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            synchronized (mLock) {
+                handleSettingsChangedLocked();
+            }
+        }
+    }
+
+    private final class DockReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            synchronized (mLock) {
+                int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
+                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
+                if (mDockState != dockState) {
+                    mDockState = dockState;
+                    mDirty |= DIRTY_DOCK_STATE;
+                    updatePowerStateLocked();
+                }
+            }
+        }
+    }
+
+    private final class SettingsObserver extends ContentObserver {
+        public SettingsObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            synchronized (mLock) {
+                handleSettingsChangedLocked();
+            }
+        }
+    }
+
+    /**
+     * Handler for asynchronous operations performed by the power manager.
+     */
+    private final class PowerManagerHandler extends Handler {
+        public PowerManagerHandler(Looper looper) {
+            super(looper, null, true /*async*/);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_USER_ACTIVITY_TIMEOUT:
+                    handleUserActivityTimeout();
+                    break;
+                case MSG_SANDMAN:
+                    handleSandman();
+                    break;
+                case MSG_SCREEN_ON_BLOCKER_RELEASED:
+                    handleScreenOnBlockerReleased();
+                    break;
+                case MSG_CHECK_IF_BOOT_ANIMATION_FINISHED:
+                    checkIfBootAnimationFinished();
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Represents a wake lock that has been acquired by an application.
+     */
+    private final class WakeLock implements IBinder.DeathRecipient {
+        public final IBinder mLock;
+        public int mFlags;
+        public String mTag;
+        public WorkSource mWorkSource;
+        public int mOwnerUid;
+        public int mOwnerPid;
+
+        public WakeLock(IBinder lock, int flags, String tag, WorkSource workSource,
+                int ownerUid, int ownerPid) {
+            mLock = lock;
+            mFlags = flags;
+            mTag = tag;
+            mWorkSource = copyWorkSource(workSource);
+            mOwnerUid = ownerUid;
+            mOwnerPid = ownerPid;
+        }
+
+        @Override
+        public void binderDied() {
+            PowerManagerService.this.handleWakeLockDeath(this);
+        }
+
+        public boolean hasSameProperties(int flags, String tag, WorkSource workSource,
+                int ownerUid, int ownerPid) {
+            return mFlags == flags
+                    && mTag.equals(tag)
+                    && hasSameWorkSource(workSource)
+                    && mOwnerUid == ownerUid
+                    && mOwnerPid == ownerPid;
+        }
+
+        public void updateProperties(int flags, String tag, WorkSource workSource,
+                int ownerUid, int ownerPid) {
+            mFlags = flags;
+            mTag = tag;
+            updateWorkSource(workSource);
+            mOwnerUid = ownerUid;
+            mOwnerPid = ownerPid;
+        }
+
+        public boolean hasSameWorkSource(WorkSource workSource) {
+            return Objects.equal(mWorkSource, workSource);
+        }
+
+        public void updateWorkSource(WorkSource workSource) {
+            mWorkSource = copyWorkSource(workSource);
+        }
+
+        @Override
+        public String toString() {
+            return getLockLevelString()
+                    + " '" + mTag + "'" + getLockFlagsString()
+                    + " (uid=" + mOwnerUid + ", pid=" + mOwnerPid + ", ws=" + mWorkSource + ")";
+        }
+
+        private String getLockLevelString() {
+            switch (mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
+                case PowerManager.FULL_WAKE_LOCK:
+                    return "FULL_WAKE_LOCK                ";
+                case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
+                    return "SCREEN_BRIGHT_WAKE_LOCK       ";
+                case PowerManager.SCREEN_DIM_WAKE_LOCK:
+                    return "SCREEN_DIM_WAKE_LOCK          ";
+                case PowerManager.PARTIAL_WAKE_LOCK:
+                    return "PARTIAL_WAKE_LOCK             ";
+                case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
+                    return "PROXIMITY_SCREEN_OFF_WAKE_LOCK";
+                default:
+                    return "???                           ";
+            }
+        }
+
+        private String getLockFlagsString() {
+            String result = "";
+            if ((mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
+                result += " ACQUIRE_CAUSES_WAKEUP";
+            }
+            if ((mFlags & PowerManager.ON_AFTER_RELEASE) != 0) {
+                result += " ON_AFTER_RELEASE";
+            }
+            return result;
+        }
+    }
+
+    private final class SuspendBlockerImpl implements SuspendBlocker {
+        private final String mName;
+        private int mReferenceCount;
+
+        public SuspendBlockerImpl(String name) {
+            mName = name;
+        }
+
+        @Override
+        protected void finalize() throws Throwable {
+            try {
+                if (mReferenceCount != 0) {
+                    Log.wtf(TAG, "Suspend blocker \"" + mName
+                            + "\" was finalized without being released!");
+                    mReferenceCount = 0;
+                    nativeReleaseSuspendBlocker(mName);
+                }
+            } finally {
+                super.finalize();
+            }
+        }
+
+        @Override
+        public void acquire() {
+            synchronized (this) {
+                mReferenceCount += 1;
+                if (mReferenceCount == 1) {
+                    nativeAcquireSuspendBlocker(mName);
+                }
+            }
+        }
+
+        @Override
+        public void release() {
+            synchronized (this) {
+                mReferenceCount -= 1;
+                if (mReferenceCount == 0) {
+                    nativeReleaseSuspendBlocker(mName);
+                } else if (mReferenceCount < 0) {
+                    Log.wtf(TAG, "Suspend blocker \"" + mName
+                            + "\" was released without being acquired!", new Throwable());
+                    mReferenceCount = 0;
+                }
+            }
+        }
+
+        @Override
+        public String toString() {
+            synchronized (this) {
+                return mName + ": ref count=" + mReferenceCount;
+            }
+        }
+    }
+
+    private final class ScreenOnBlockerImpl implements ScreenOnBlocker {
+        private int mNestCount;
+
+        public boolean isHeld() {
+            synchronized (this) {
+                return mNestCount != 0;
+            }
+        }
+
+        @Override
+        public void acquire() {
+            synchronized (this) {
+                mNestCount += 1;
+                if (DEBUG) {
+                    Slog.d(TAG, "Screen on blocked: mNestCount=" + mNestCount);
+                }
+            }
+        }
+
+        @Override
+        public void release() {
+            synchronized (this) {
+                mNestCount -= 1;
+                if (mNestCount < 0) {
+                    Log.wtf(TAG, "Screen on blocker was released without being acquired!",
+                            new Throwable());
+                    mNestCount = 0;
+                }
+                if (mNestCount == 0) {
+                    mHandler.sendEmptyMessage(MSG_SCREEN_ON_BLOCKER_RELEASED);
+                }
+                if (DEBUG) {
+                    Slog.d(TAG, "Screen on unblocked: mNestCount=" + mNestCount);
+                }
+            }
+        }
+
+        @Override
+        public String toString() {
+            synchronized (this) {
+                return "held=" + (mNestCount != 0) + ", mNestCount=" + mNestCount;
+            }
+        }
+    }
+
+    private final class DisplayBlankerImpl implements DisplayBlanker {
+        private boolean mBlanked;
+
+        @Override
+        public void blankAllDisplays() {
+            synchronized (this) {
+                mBlanked = true;
+                mDisplayManagerService.blankAllDisplaysFromPowerManager();
+                nativeSetInteractive(false);
+                nativeSetAutoSuspend(true);
+            }
+        }
+
+        @Override
+        public void unblankAllDisplays() {
+            synchronized (this) {
+                nativeSetAutoSuspend(false);
+                nativeSetInteractive(true);
+                mDisplayManagerService.unblankAllDisplaysFromPowerManager();
+                mBlanked = false;
+            }
+        }
+
+        @Override
+        public String toString() {
+            synchronized (this) {
+                return "blanked=" + mBlanked;
+            }
+        }
+    }
+}
diff --git a/services/java/com/android/server/power/RampAnimator.java b/services/java/com/android/server/power/RampAnimator.java
new file mode 100644
index 0000000..6f063c3
--- /dev/null
+++ b/services/java/com/android/server/power/RampAnimator.java
@@ -0,0 +1,131 @@
+/*
+ * 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.power;
+
+import android.animation.ValueAnimator;
+import android.util.IntProperty;
+import android.view.Choreographer;
+
+/**
+ * A custom animator that progressively updates a property value at
+ * a given variable rate until it reaches a particular target value.
+ */
+final class RampAnimator<T> {
+    private final T mObject;
+    private final IntProperty<T> mProperty;
+    private final Choreographer mChoreographer;
+
+    private int mCurrentValue;
+    private int mTargetValue;
+    private int mRate;
+
+    private boolean mAnimating;
+    private float mAnimatedValue; // higher precision copy of mCurrentValue
+    private long mLastFrameTimeNanos;
+
+    private boolean mFirstTime = true;
+
+    public RampAnimator(T object, IntProperty<T> property) {
+        mObject = object;
+        mProperty = property;
+        mChoreographer = Choreographer.getInstance();
+    }
+
+    /**
+     * Starts animating towards the specified value.
+     *
+     * If this is the first time the property is being set, the value jumps
+     * directly to the target.
+     *
+     * @param target The target value.
+     * @param rate The convergence rate, in units per second.
+     * @return True if the target differs from the previous target.
+     */
+    public boolean animateTo(int target, int rate) {
+        // Immediately jump to the target the first time.
+        if (mFirstTime) {
+            mFirstTime = false;
+            mProperty.setValue(mObject, target);
+            mCurrentValue = target;
+            return true;
+        }
+
+        // Adjust the rate based on the closest target.
+        // If a faster rate is specified, then use the new rate so that we converge
+        // more rapidly based on the new request.
+        // If a slower rate is specified, then use the new rate only if the current
+        // value is somewhere in between the new and the old target meaning that
+        // we will be ramping in a different direction to get there.
+        // Otherwise, continue at the previous rate.
+        if (!mAnimating
+                || rate > mRate
+                || (target <= mCurrentValue && mCurrentValue <= mTargetValue)
+                || (mTargetValue <= mCurrentValue && mCurrentValue <= target)) {
+            mRate = rate;
+        }
+
+        final boolean changed = (mTargetValue != target);
+        mTargetValue = target;
+
+        // Start animating.
+        if (!mAnimating && target != mCurrentValue) {
+            mAnimating = true;
+            mAnimatedValue = mCurrentValue;
+            mLastFrameTimeNanos = System.nanoTime();
+            postCallback();
+        }
+
+        return changed;
+    }
+
+    private void postCallback() {
+        mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mCallback, null);
+    }
+
+    private final Runnable mCallback = new Runnable() {
+        @Override // Choreographer callback
+        public void run() {
+            final long frameTimeNanos = mChoreographer.getFrameTimeNanos();
+            final float timeDelta = (frameTimeNanos - mLastFrameTimeNanos)
+                    * 0.000000001f;
+            final float amount = timeDelta * mRate / ValueAnimator.getDurationScale();
+            mLastFrameTimeNanos = frameTimeNanos;
+
+            // Advance the animated value towards the target at the specified rate
+            // and clamp to the target. This gives us the new current value but
+            // we keep the animated value around to allow for fractional increments
+            // towards the target.
+            int oldCurrentValue = mCurrentValue;
+            if (mTargetValue > mCurrentValue) {
+                mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue);
+            } else {
+                mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue);
+            }
+            mCurrentValue = (int)Math.round(mAnimatedValue);
+
+            if (oldCurrentValue != mCurrentValue) {
+                mProperty.setValue(mObject, mCurrentValue);
+            }
+
+            if (mTargetValue != mCurrentValue) {
+                postCallback();
+            } else {
+                mAnimating = false;
+            }
+        }
+    };
+}
diff --git a/services/java/com/android/server/power/ScreenOnBlocker.java b/services/java/com/android/server/power/ScreenOnBlocker.java
new file mode 100644
index 0000000..dbbbc6d
--- /dev/null
+++ b/services/java/com/android/server/power/ScreenOnBlocker.java
@@ -0,0 +1,41 @@
+/*
+ * 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.power;
+
+/**
+ * Low-level screen on blocker mechanism which is used to keep the screen off
+ * or the contents of the screen hidden until the window manager is ready to show new content.
+ */
+interface ScreenOnBlocker {
+    /**
+     * Acquires the screen on blocker.
+     * Prevents the screen from turning on.
+     *
+     * Calls to acquire() nest and must be matched by the same number
+     * of calls to release().
+     */
+    void acquire();
+
+    /**
+     * Releases the screen on blocker.
+     * Allows the screen to turn on.
+     *
+     * It is an error to call release() if the screen on blocker has not been acquired.
+     * The system may crash.
+     */
+    void release();
+}
diff --git a/services/java/com/android/server/power/ShutdownThread.java b/services/java/com/android/server/power/ShutdownThread.java
new file mode 100644
index 0000000..c7f7390
--- /dev/null
+++ b/services/java/com/android/server/power/ShutdownThread.java
@@ -0,0 +1,519 @@
+/*
+ * 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.
+ */
+
+ 
+package com.android.server.power;
+
+import android.app.ActivityManagerNative;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.IActivityManager;
+import android.app.ProgressDialog;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.IBluetoothManager;
+import android.nfc.NfcAdapter;
+import android.nfc.INfcAdapter;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.os.Vibrator;
+import android.os.SystemVibrator;
+import android.os.storage.IMountService;
+import android.os.storage.IMountShutdownObserver;
+
+import com.android.internal.telephony.ITelephony;
+
+import android.util.Log;
+import android.view.WindowManager;
+
+public final class ShutdownThread extends Thread {
+    // constants
+    private static final String TAG = "ShutdownThread";
+    private static final int PHONE_STATE_POLL_SLEEP_MSEC = 500;
+    // maximum time we wait for the shutdown broadcast before going on.
+    private static final int MAX_BROADCAST_TIME = 10*1000;
+    private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000;
+    private static final int MAX_RADIO_WAIT_TIME = 12*1000;
+
+    // length of vibration before shutting down
+    private static final int SHUTDOWN_VIBRATE_MS = 500;
+    
+    // state tracking
+    private static Object sIsStartedGuard = new Object();
+    private static boolean sIsStarted = false;
+    
+    private static boolean mReboot;
+    private static boolean mRebootSafeMode;
+    private static String mRebootReason;
+
+    // Provides shutdown assurance in case the system_server is killed
+    public static final String SHUTDOWN_ACTION_PROPERTY = "sys.shutdown.requested";
+
+    // Indicates whether we are rebooting into safe mode
+    public static final String REBOOT_SAFEMODE_PROPERTY = "persist.sys.safemode";
+
+    // static instance of this thread
+    private static final ShutdownThread sInstance = new ShutdownThread();
+    
+    private final Object mActionDoneSync = new Object();
+    private boolean mActionDone;
+    private Context mContext;
+    private PowerManager mPowerManager;
+    private PowerManager.WakeLock mCpuWakeLock;
+    private PowerManager.WakeLock mScreenWakeLock;
+    private Handler mHandler;
+
+    private static AlertDialog sConfirmDialog;
+    
+    private ShutdownThread() {
+    }
+ 
+    /**
+     * Request a clean shutdown, waiting for subsystems to clean up their
+     * state etc.  Must be called from a Looper thread in which its UI
+     * is shown.
+     *
+     * @param context Context used to display the shutdown progress dialog.
+     * @param confirm true if user confirmation is needed before shutting down.
+     */
+    public static void shutdown(final Context context, boolean confirm) {
+        mReboot = false;
+        mRebootSafeMode = false;
+        shutdownInner(context, confirm);
+    }
+
+    static void shutdownInner(final Context context, boolean confirm) {
+        // ensure that only one thread is trying to power down.
+        // any additional calls are just returned
+        synchronized (sIsStartedGuard) {
+            if (sIsStarted) {
+                Log.d(TAG, "Request to shutdown already running, returning.");
+                return;
+            }
+        }
+
+        final int longPressBehavior = context.getResources().getInteger(
+                        com.android.internal.R.integer.config_longPressOnPowerBehavior);
+        final int resourceId = mRebootSafeMode
+                ? com.android.internal.R.string.reboot_safemode_confirm
+                : (longPressBehavior == 2
+                        ? com.android.internal.R.string.shutdown_confirm_question
+                        : com.android.internal.R.string.shutdown_confirm);
+
+        Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior);
+
+        if (confirm) {
+            final CloseDialogReceiver closer = new CloseDialogReceiver(context);
+            if (sConfirmDialog != null) {
+                sConfirmDialog.dismiss();
+            }
+            sConfirmDialog = new AlertDialog.Builder(context)
+                    .setTitle(mRebootSafeMode
+                            ? com.android.internal.R.string.reboot_safemode_title
+                            : com.android.internal.R.string.power_off)
+                    .setMessage(resourceId)
+                    .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
+                        public void onClick(DialogInterface dialog, int which) {
+                            beginShutdownSequence(context);
+                        }
+                    })
+                    .setNegativeButton(com.android.internal.R.string.no, null)
+                    .create();
+            closer.dialog = sConfirmDialog;
+            sConfirmDialog.setOnDismissListener(closer);
+            sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+            sConfirmDialog.show();
+        } else {
+            beginShutdownSequence(context);
+        }
+    }
+
+    private static class CloseDialogReceiver extends BroadcastReceiver
+            implements DialogInterface.OnDismissListener {
+        private Context mContext;
+        public Dialog dialog;
+
+        CloseDialogReceiver(Context context) {
+            mContext = context;
+            IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+            context.registerReceiver(this, filter);
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            dialog.cancel();
+        }
+
+        public void onDismiss(DialogInterface unused) {
+            mContext.unregisterReceiver(this);
+        }
+    }
+
+    /**
+     * Request a clean shutdown, waiting for subsystems to clean up their
+     * state etc.  Must be called from a Looper thread in which its UI
+     * is shown.
+     *
+     * @param context Context used to display the shutdown progress dialog.
+     * @param reason code to pass to the kernel (e.g. "recovery"), or null.
+     * @param confirm true if user confirmation is needed before shutting down.
+     */
+    public static void reboot(final Context context, String reason, boolean confirm) {
+        mReboot = true;
+        mRebootSafeMode = false;
+        mRebootReason = reason;
+        shutdownInner(context, confirm);
+    }
+
+    /**
+     * Request a reboot into safe mode.  Must be called from a Looper thread in which its UI
+     * is shown.
+     *
+     * @param context Context used to display the shutdown progress dialog.
+     * @param confirm true if user confirmation is needed before shutting down.
+     */
+    public static void rebootSafeMode(final Context context, boolean confirm) {
+        mReboot = true;
+        mRebootSafeMode = true;
+        mRebootReason = null;
+        shutdownInner(context, confirm);
+    }
+
+    private static void beginShutdownSequence(Context context) {
+        synchronized (sIsStartedGuard) {
+            if (sIsStarted) {
+                Log.d(TAG, "Shutdown sequence already running, returning.");
+                return;
+            }
+            sIsStarted = true;
+        }
+
+        // throw up an indeterminate system dialog to indicate radio is
+        // shutting down.
+        ProgressDialog pd = new ProgressDialog(context);
+        pd.setTitle(context.getText(com.android.internal.R.string.power_off));
+        pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
+        pd.setIndeterminate(true);
+        pd.setCancelable(false);
+        pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+
+        pd.show();
+
+        sInstance.mContext = context;
+        sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+
+        // make sure we never fall asleep again
+        sInstance.mCpuWakeLock = null;
+        try {
+            sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock(
+                    PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu");
+            sInstance.mCpuWakeLock.setReferenceCounted(false);
+            sInstance.mCpuWakeLock.acquire();
+        } catch (SecurityException e) {
+            Log.w(TAG, "No permission to acquire wake lock", e);
+            sInstance.mCpuWakeLock = null;
+        }
+
+        // also make sure the screen stays on for better user experience
+        sInstance.mScreenWakeLock = null;
+        if (sInstance.mPowerManager.isScreenOn()) {
+            try {
+                sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock(
+                        PowerManager.FULL_WAKE_LOCK, TAG + "-screen");
+                sInstance.mScreenWakeLock.setReferenceCounted(false);
+                sInstance.mScreenWakeLock.acquire();
+            } catch (SecurityException e) {
+                Log.w(TAG, "No permission to acquire wake lock", e);
+                sInstance.mScreenWakeLock = null;
+            }
+        }
+
+        // start the thread that initiates shutdown
+        sInstance.mHandler = new Handler() {
+        };
+        sInstance.start();
+    }
+
+    void actionDone() {
+        synchronized (mActionDoneSync) {
+            mActionDone = true;
+            mActionDoneSync.notifyAll();
+        }
+    }
+
+    /**
+     * Makes sure we handle the shutdown gracefully.
+     * Shuts off power regardless of radio and bluetooth state if the alloted time has passed.
+     */
+    public void run() {
+        BroadcastReceiver br = new BroadcastReceiver() {
+            @Override public void onReceive(Context context, Intent intent) {
+                // We don't allow apps to cancel this, so ignore the result.
+                actionDone();
+            }
+        };
+
+        /*
+         * Write a system property in case the system_server reboots before we
+         * get to the actual hardware restart. If that happens, we'll retry at
+         * the beginning of the SystemServer startup.
+         */
+        {
+            String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : "");
+            SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);
+        }
+
+        /*
+         * If we are rebooting into safe mode, write a system property
+         * indicating so.
+         */
+        if (mRebootSafeMode) {
+            SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1");
+        }
+
+        Log.i(TAG, "Sending shutdown broadcast...");
+        
+        // First send the high-level shut down broadcast.
+        mActionDone = false;
+        mContext.sendOrderedBroadcastAsUser(new Intent(Intent.ACTION_SHUTDOWN),
+                UserHandle.ALL, null, br, mHandler, 0, null, null);
+        
+        final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
+        synchronized (mActionDoneSync) {
+            while (!mActionDone) {
+                long delay = endTime - SystemClock.elapsedRealtime();
+                if (delay <= 0) {
+                    Log.w(TAG, "Shutdown broadcast timed out");
+                    break;
+                }
+                try {
+                    mActionDoneSync.wait(delay);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+        
+        Log.i(TAG, "Shutting down activity manager...");
+        
+        final IActivityManager am =
+            ActivityManagerNative.asInterface(ServiceManager.checkService("activity"));
+        if (am != null) {
+            try {
+                am.shutdown(MAX_BROADCAST_TIME);
+            } catch (RemoteException e) {
+            }
+        }
+
+        // Shutdown radios.
+        shutdownRadios(MAX_RADIO_WAIT_TIME);
+
+        // Shutdown MountService to ensure media is in a safe state
+        IMountShutdownObserver observer = new IMountShutdownObserver.Stub() {
+            public void onShutDownComplete(int statusCode) throws RemoteException {
+                Log.w(TAG, "Result code " + statusCode + " from MountService.shutdown");
+                actionDone();
+            }
+        };
+
+        Log.i(TAG, "Shutting down MountService");
+
+        // Set initial variables and time out time.
+        mActionDone = false;
+        final long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME;
+        synchronized (mActionDoneSync) {
+            try {
+                final IMountService mount = IMountService.Stub.asInterface(
+                        ServiceManager.checkService("mount"));
+                if (mount != null) {
+                    mount.shutdown(observer);
+                } else {
+                    Log.w(TAG, "MountService unavailable for shutdown");
+                }
+            } catch (Exception e) {
+                Log.e(TAG, "Exception during MountService shutdown", e);
+            }
+            while (!mActionDone) {
+                long delay = endShutTime - SystemClock.elapsedRealtime();
+                if (delay <= 0) {
+                    Log.w(TAG, "Shutdown wait timed out");
+                    break;
+                }
+                try {
+                    mActionDoneSync.wait(delay);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+
+        rebootOrShutdown(mReboot, mRebootReason);
+    }
+
+    private void shutdownRadios(int timeout) {
+        // If a radio is wedged, disabling it may hang so we do this work in another thread,
+        // just in case.
+        final long endTime = SystemClock.elapsedRealtime() + timeout;
+        final boolean[] done = new boolean[1];
+        Thread t = new Thread() {
+            public void run() {
+                boolean nfcOff;
+                boolean bluetoothOff;
+                boolean radioOff;
+
+                final INfcAdapter nfc =
+                        INfcAdapter.Stub.asInterface(ServiceManager.checkService("nfc"));
+                final ITelephony phone =
+                        ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
+                final IBluetoothManager bluetooth =
+                        IBluetoothManager.Stub.asInterface(ServiceManager.checkService(
+                                BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE));
+
+                try {
+                    nfcOff = nfc == null ||
+                             nfc.getState() == NfcAdapter.STATE_OFF;
+                    if (!nfcOff) {
+                        Log.w(TAG, "Turning off NFC...");
+                        nfc.disable(false); // Don't persist new state
+                    }
+                } catch (RemoteException ex) {
+                Log.e(TAG, "RemoteException during NFC shutdown", ex);
+                    nfcOff = true;
+                }
+
+                try {
+                    bluetoothOff = bluetooth == null || !bluetooth.isEnabled();
+                    if (!bluetoothOff) {
+                        Log.w(TAG, "Disabling Bluetooth...");
+                        bluetooth.disable(false);  // disable but don't persist new state
+                    }
+                } catch (RemoteException ex) {
+                    Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
+                    bluetoothOff = true;
+                }
+
+                try {
+                    radioOff = phone == null || !phone.isRadioOn();
+                    if (!radioOff) {
+                        Log.w(TAG, "Turning off radio...");
+                        phone.setRadio(false);
+                    }
+                } catch (RemoteException ex) {
+                    Log.e(TAG, "RemoteException during radio shutdown", ex);
+                    radioOff = true;
+                }
+
+                Log.i(TAG, "Waiting for NFC, Bluetooth and Radio...");
+
+                while (SystemClock.elapsedRealtime() < endTime) {
+                    if (!bluetoothOff) {
+                        try {
+                            bluetoothOff = !bluetooth.isEnabled();
+                        } catch (RemoteException ex) {
+                            Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
+                            bluetoothOff = true;
+                        }
+                        if (bluetoothOff) {
+                            Log.i(TAG, "Bluetooth turned off.");
+                        }
+                    }
+                    if (!radioOff) {
+                        try {
+                            radioOff = !phone.isRadioOn();
+                        } catch (RemoteException ex) {
+                            Log.e(TAG, "RemoteException during radio shutdown", ex);
+                            radioOff = true;
+                        }
+                        if (radioOff) {
+                            Log.i(TAG, "Radio turned off.");
+                        }
+                    }
+                    if (!nfcOff) {
+                        try {
+                            nfcOff = nfc.getState() == NfcAdapter.STATE_OFF;
+                        } catch (RemoteException ex) {
+                            Log.e(TAG, "RemoteException during NFC shutdown", ex);
+                            nfcOff = true;
+                        }
+                        if (radioOff) {
+                            Log.i(TAG, "NFC turned off.");
+                        }
+                    }
+
+                    if (radioOff && bluetoothOff && nfcOff) {
+                        Log.i(TAG, "NFC, Radio and Bluetooth shutdown complete.");
+                        done[0] = true;
+                        break;
+                    }
+                    SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC);
+                }
+            }
+        };
+
+        t.start();
+        try {
+            t.join(timeout);
+        } catch (InterruptedException ex) {
+        }
+        if (!done[0]) {
+            Log.w(TAG, "Timed out waiting for NFC, Radio and Bluetooth shutdown.");
+        }
+    }
+
+    /**
+     * Do not call this directly. Use {@link #reboot(Context, String, boolean)}
+     * or {@link #shutdown(Context, boolean)} instead.
+     *
+     * @param reboot true to reboot or false to shutdown
+     * @param reason reason for reboot
+     */
+    public static void rebootOrShutdown(boolean reboot, String reason) {
+        if (reboot) {
+            Log.i(TAG, "Rebooting, reason: " + reason);
+            try {
+                PowerManagerService.lowLevelReboot(reason);
+            } catch (Exception e) {
+                Log.e(TAG, "Reboot failed, will attempt shutdown instead", e);
+            }
+        } else if (SHUTDOWN_VIBRATE_MS > 0) {
+            // vibrate before shutting down
+            Vibrator vibrator = new SystemVibrator();
+            try {
+                vibrator.vibrate(SHUTDOWN_VIBRATE_MS);
+            } catch (Exception e) {
+                // Failure to vibrate shouldn't interrupt shutdown.  Just log it.
+                Log.w(TAG, "Failed to vibrate during shutdown.", e);
+            }
+
+            // vibrator is asynchronous so we need to wait to avoid shutting down too soon.
+            try {
+                Thread.sleep(SHUTDOWN_VIBRATE_MS);
+            } catch (InterruptedException unused) {
+            }
+        }
+
+        // Shutdown power
+        Log.i(TAG, "Performing low-level shutdown...");
+        PowerManagerService.lowLevelShutdown();
+    }
+}
diff --git a/services/java/com/android/server/power/SuspendBlocker.java b/services/java/com/android/server/power/SuspendBlocker.java
new file mode 100644
index 0000000..70b278a
--- /dev/null
+++ b/services/java/com/android/server/power/SuspendBlocker.java
@@ -0,0 +1,43 @@
+/*
+ * 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.power;
+
+/**
+ * Low-level suspend blocker mechanism equivalent to holding a partial wake lock.
+ *
+ * This interface is used internally to avoid introducing internal dependencies
+ * on the high-level wake lock mechanism.
+ */
+interface SuspendBlocker {
+    /**
+     * Acquires the suspend blocker.
+     * Prevents the CPU from going to sleep.
+     *
+     * Calls to acquire() nest and must be matched by the same number
+     * of calls to release().
+     */
+    void acquire();
+
+    /**
+     * Releases the suspend blocker.
+     * Allows the CPU to go to sleep if no other suspend blockers are held.
+     *
+     * It is an error to call release() if the suspend blocker has not been acquired.
+     * The system may crash.
+     */
+    void release();
+}
diff --git a/services/java/com/android/server/updates/CertPinInstallReceiver.java b/services/java/com/android/server/updates/CertPinInstallReceiver.java
new file mode 100644
index 0000000..c03fbc3
--- /dev/null
+++ b/services/java/com/android/server/updates/CertPinInstallReceiver.java
@@ -0,0 +1,24 @@
+/*
+ * 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.updates;
+
+public class CertPinInstallReceiver extends ConfigUpdateInstallReceiver {
+
+    public CertPinInstallReceiver() {
+        super("/data/misc/keychain/", "pins", "metadata/", "version");
+    }
+}
diff --git a/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java b/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
new file mode 100644
index 0000000..4480151
--- /dev/null
+++ b/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
@@ -0,0 +1,262 @@
+/*
+ * 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.updates;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.os.FileUtils;
+import android.util.Base64;
+import android.util.EventLog;
+import android.util.Slog;
+
+import com.android.server.EventLogTags;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Signature;
+import java.security.SignatureException;
+
+import libcore.io.IoUtils;
+
+public class ConfigUpdateInstallReceiver extends BroadcastReceiver {
+
+    private static final String TAG = "ConfigUpdateInstallReceiver";
+
+    private static final String EXTRA_CONTENT_PATH = "CONTENT_PATH";
+    private static final String EXTRA_REQUIRED_HASH = "REQUIRED_HASH";
+    private static final String EXTRA_SIGNATURE = "SIGNATURE";
+    private static final String EXTRA_VERSION_NUMBER = "VERSION";
+
+    private static final String UPDATE_CERTIFICATE_KEY = "config_update_certificate";
+
+    private final File updateDir;
+    private final File updateContent;
+    private final File updateVersion;
+
+    public ConfigUpdateInstallReceiver(String updateDir, String updateContentPath,
+                                       String updateMetadataPath, String updateVersionPath) {
+        this.updateDir = new File(updateDir);
+        this.updateContent = new File(updateDir, updateContentPath);
+        File updateMetadataDir = new File(updateDir, updateMetadataPath);
+        this.updateVersion = new File(updateMetadataDir, updateVersionPath);
+    }
+
+    @Override
+    public void onReceive(final Context context, final Intent intent) {
+        new Thread() {
+            @Override
+            public void run() {
+                try {
+                    // get the certificate from Settings.Secure
+                    X509Certificate cert = getCert(context.getContentResolver());
+                    // get the content path from the extras
+                    String altContent = getAltContent(intent);
+                    // get the version from the extras
+                    int altVersion = getVersionFromIntent(intent);
+                    // get the previous value from the extras
+                    String altRequiredHash = getRequiredHashFromIntent(intent);
+                    // get the signature from the extras
+                    String altSig = getSignatureFromIntent(intent);
+                    // get the version currently being used
+                    int currentVersion = getCurrentVersion();
+                    // get the hash of the currently used value
+                    String currentHash = getCurrentHash(getCurrentContent());
+                    if (!verifyVersion(currentVersion, altVersion)) {
+                        Slog.i(TAG, "Not installing, new version is <= current version");
+                    } else if (!verifyPreviousHash(currentHash, altRequiredHash)) {
+                        EventLog.writeEvent(EventLogTags.CONFIG_INSTALL_FAILED,
+                                            "Current hash did not match required value");
+                    } else if (!verifySignature(altContent, altVersion, altRequiredHash, altSig,
+                               cert)) {
+                        EventLog.writeEvent(EventLogTags.CONFIG_INSTALL_FAILED,
+                                            "Signature did not verify");
+                    } else {
+                        // install the new content
+                        Slog.i(TAG, "Found new update, installing...");
+                        install(altContent, altVersion);
+                        Slog.i(TAG, "Installation successful");
+                    }
+                } catch (Exception e) {
+                    Slog.e(TAG, "Could not update content!", e);
+                    // keep the error message <= 100 chars
+                    String errMsg = e.toString();
+                    if (errMsg.length() > 100) {
+                        errMsg = errMsg.substring(0, 99);
+                    }
+                    EventLog.writeEvent(EventLogTags.CONFIG_INSTALL_FAILED, errMsg);
+                }
+            }
+        }.start();
+    }
+
+    private X509Certificate getCert(ContentResolver cr) {
+        // get the cert from settings
+        String cert = Settings.Secure.getString(cr, UPDATE_CERTIFICATE_KEY);
+        // convert it into a real certificate
+        try {
+            byte[] derCert = Base64.decode(cert.getBytes(), Base64.DEFAULT);
+            InputStream istream = new ByteArrayInputStream(derCert);
+            CertificateFactory cf = CertificateFactory.getInstance("X.509");
+            return (X509Certificate) cf.generateCertificate(istream);
+        } catch (CertificateException e) {
+            throw new IllegalStateException("Got malformed certificate from settings, ignoring");
+        }
+    }
+
+    private String getContentFromIntent(Intent i) {
+        String extraValue = i.getStringExtra(EXTRA_CONTENT_PATH);
+        if (extraValue == null) {
+            throw new IllegalStateException("Missing required content path, ignoring.");
+        }
+        return extraValue;
+    }
+
+    private int getVersionFromIntent(Intent i) throws NumberFormatException {
+        String extraValue = i.getStringExtra(EXTRA_VERSION_NUMBER);
+        if (extraValue == null) {
+            throw new IllegalStateException("Missing required version number, ignoring.");
+        }
+        return Integer.parseInt(extraValue.trim());
+    }
+
+    private String getRequiredHashFromIntent(Intent i) {
+        String extraValue = i.getStringExtra(EXTRA_REQUIRED_HASH);
+        if (extraValue == null) {
+            throw new IllegalStateException("Missing required previous hash, ignoring.");
+        }
+        return extraValue.trim();
+    }
+
+    private String getSignatureFromIntent(Intent i) {
+        String extraValue = i.getStringExtra(EXTRA_SIGNATURE);
+        if (extraValue == null) {
+            throw new IllegalStateException("Missing required signature, ignoring.");
+        }
+        return extraValue.trim();
+    }
+
+    private int getCurrentVersion() throws NumberFormatException {
+        try {
+            String strVersion = IoUtils.readFileAsString(updateVersion.getCanonicalPath()).trim();
+            return Integer.parseInt(strVersion);
+        } catch (IOException e) {
+            Slog.i(TAG, "Couldn't find current metadata, assuming first update");
+            return 0;
+        }
+    }
+
+    private String getAltContent(Intent i) throws IOException {
+        String contents = IoUtils.readFileAsString(getContentFromIntent(i));
+        return contents.trim();
+    }
+
+    private String getCurrentContent() {
+        try {
+            return IoUtils.readFileAsString(updateContent.getCanonicalPath()).trim();
+        } catch (IOException e) {
+            Slog.i(TAG, "Failed to read current content, assuming first update!");
+            return null;
+        }
+    }
+
+    private static String getCurrentHash(String content) {
+        if (content == null) {
+            return "0";
+        }
+        try {
+            MessageDigest dgst = MessageDigest.getInstance("SHA512");
+            byte[] encoded = content.getBytes();
+            byte[] fingerprint = dgst.digest(encoded);
+            return IntegralToString.bytesToHexString(fingerprint, false);
+        } catch (NoSuchAlgorithmException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    private boolean verifyVersion(int current, int alternative) {
+        return (current < alternative);
+    }
+
+    private boolean verifyPreviousHash(String current, String required) {
+        // this is an optional value- if the required field is NONE then we ignore it
+        if (required.equals("NONE")) {
+            return true;
+        }
+        // otherwise, verify that we match correctly
+        return current.equals(required);
+    }
+
+    private boolean verifySignature(String content, int version, String requiredPrevious,
+                                   String signature, X509Certificate cert) throws Exception {
+        Signature signer = Signature.getInstance("SHA512withRSA");
+        signer.initVerify(cert);
+        signer.update(content.getBytes());
+        signer.update(Long.toString(version).getBytes());
+        signer.update(requiredPrevious.getBytes());
+        return signer.verify(Base64.decode(signature.getBytes(), Base64.DEFAULT));
+    }
+
+    private void writeUpdate(File dir, File file, String content) throws IOException {
+        FileOutputStream out = null;
+        File tmp = null;
+        try {
+            // create the temporary file
+            tmp = File.createTempFile("journal", "", dir);
+            // create the parents for the destination file
+            File parent = file.getParentFile();
+            parent.mkdirs();
+            // check that they were created correctly
+            if (!parent.exists()) {
+                throw new IOException("Failed to create directory " + parent.getCanonicalPath());
+            }
+            // mark tmp -rw-r--r--
+            tmp.setReadable(true, false);
+            // write to it
+            out = new FileOutputStream(tmp);
+            out.write(content.getBytes());
+            // sync to disk
+            out.getFD().sync();
+            // atomic rename
+            if (!tmp.renameTo(file)) {
+                throw new IOException("Failed to atomically rename " + file.getCanonicalPath());
+            }
+        } finally {
+            if (tmp != null) {
+                tmp.delete();
+            }
+            IoUtils.closeQuietly(out);
+        }
+    }
+
+    private void install(String content, int version) throws IOException {
+        writeUpdate(updateDir, updateContent, content);
+        writeUpdate(updateDir, updateVersion, Long.toString(version));
+    }
+}
diff --git a/services/java/com/android/server/updates/SmsShortCodesInstallReceiver.java b/services/java/com/android/server/updates/SmsShortCodesInstallReceiver.java
new file mode 100644
index 0000000..0f14f57
--- /dev/null
+++ b/services/java/com/android/server/updates/SmsShortCodesInstallReceiver.java
@@ -0,0 +1,24 @@
+/*
+ * 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.updates;
+
+public class SmsShortCodesInstallReceiver extends ConfigUpdateInstallReceiver {
+
+    public SmsShortCodesInstallReceiver() {
+        super("/data/misc/sms/", "codes", "metadata/", "version");
+    }
+}
diff --git a/services/java/com/android/server/usb/UsbDebuggingManager.java b/services/java/com/android/server/usb/UsbDebuggingManager.java
new file mode 100644
index 0000000..1bb3a2c
--- /dev/null
+++ b/services/java/com/android/server/usb/UsbDebuggingManager.java
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions an
+ * limitations under the License.
+ */
+
+package com.android.server.usb;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Environment;
+import android.os.FileUtils;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.util.Base64;
+
+import java.lang.Thread;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.security.MessageDigest;
+import java.util.Arrays;
+
+public class UsbDebuggingManager implements Runnable {
+    private static final String TAG = "UsbDebuggingManager";
+    private static final boolean DEBUG = false;
+
+    private final String ADBD_SOCKET = "adbd";
+    private final String ADB_DIRECTORY = "misc/adb";
+    private final String ADB_KEYS_FILE = "adb_keys";
+    private final int BUFFER_SIZE = 4096;
+
+    private final Context mContext;
+    private final Handler mHandler;
+    private final HandlerThread mHandlerThread;
+    private Thread mThread;
+    private boolean mAdbEnabled = false;
+    private String mFingerprints;
+    private LocalSocket mSocket = null;
+    private OutputStream mOutputStream = null;
+
+    public UsbDebuggingManager(Context context) {
+        mHandlerThread = new HandlerThread("UsbDebuggingHandler");
+        mHandlerThread.start();
+        mHandler = new UsbDebuggingHandler(mHandlerThread.getLooper());
+        mContext = context;
+    }
+
+    private void listenToSocket() throws IOException {
+        try {
+            byte[] buffer = new byte[BUFFER_SIZE];
+            LocalSocketAddress address = new LocalSocketAddress(ADBD_SOCKET,
+                                         LocalSocketAddress.Namespace.RESERVED);
+            InputStream inputStream = null;
+
+            mSocket = new LocalSocket();
+            mSocket.connect(address);
+
+            mOutputStream = mSocket.getOutputStream();
+            inputStream = mSocket.getInputStream();
+
+            while (true) {
+                int count = inputStream.read(buffer);
+                if (count < 0) {
+                    Slog.e(TAG, "got " + count + " reading");
+                    break;
+                }
+
+                if (buffer[0] == 'P' && buffer[1] == 'K') {
+                    String key = new String(Arrays.copyOfRange(buffer, 2, count));
+                    Slog.d(TAG, "Received public key: " + key);
+                    Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_CONFIRM);
+                    msg.obj = key;
+                    mHandler.sendMessage(msg);
+                }
+                else {
+                    Slog.e(TAG, "Wrong message: " + (new String(Arrays.copyOfRange(buffer, 0, 2))));
+                    break;
+                }
+            }
+        } catch (IOException ex) {
+            Slog.e(TAG, "Communication error: ", ex);
+            throw ex;
+        } finally {
+            closeSocket();
+        }
+    }
+
+    @Override
+    public void run() {
+        while (mAdbEnabled) {
+            try {
+                listenToSocket();
+            } catch (Exception e) {
+                /* Don't loop too fast if adbd dies, before init restarts it */
+                SystemClock.sleep(1000);
+            }
+        }
+    }
+
+    private void closeSocket() {
+        try {
+            mOutputStream.close();
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed closing output stream: " + e);
+        }
+
+        try {
+            mSocket.close();
+        } catch (IOException ex) {
+            Slog.e(TAG, "Failed closing socket: " + ex);
+        }
+    }
+
+    private void sendResponse(String msg) {
+        if (mOutputStream != null) {
+            try {
+                mOutputStream.write(msg.getBytes());
+            }
+            catch (IOException ex) {
+                Slog.e(TAG, "Failed to write response:", ex);
+            }
+        }
+    }
+
+    class UsbDebuggingHandler extends Handler {
+        private static final int MESSAGE_ADB_ENABLED = 1;
+        private static final int MESSAGE_ADB_DISABLED = 2;
+        private static final int MESSAGE_ADB_ALLOW = 3;
+        private static final int MESSAGE_ADB_DENY = 4;
+        private static final int MESSAGE_ADB_CONFIRM = 5;
+
+        public UsbDebuggingHandler(Looper looper) {
+            super(looper);
+        }
+
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MESSAGE_ADB_ENABLED:
+                    if (mAdbEnabled)
+                        break;
+
+                    mAdbEnabled = true;
+
+                    mThread = new Thread(UsbDebuggingManager.this);
+                    mThread.start();
+
+                    break;
+
+                case MESSAGE_ADB_DISABLED:
+                    if (!mAdbEnabled)
+                        break;
+
+                    mAdbEnabled = false;
+                    closeSocket();
+
+                    try {
+                        mThread.join();
+                    } catch (Exception ex) {
+                    }
+
+                    mThread = null;
+                    mOutputStream = null;
+                    mSocket = null;
+                    break;
+
+                case MESSAGE_ADB_ALLOW: {
+                    String key = (String)msg.obj;
+                    String fingerprints = getFingerprints(key);
+
+                    if (!fingerprints.equals(mFingerprints)) {
+                        Slog.e(TAG, "Fingerprints do not match. Got "
+                                + fingerprints + ", expected " + mFingerprints);
+                        break;
+                    }
+
+                    if (msg.arg1 == 1) {
+                        writeKey(key);
+                    }
+
+                    sendResponse("OK");
+                    break;
+                }
+
+                case MESSAGE_ADB_DENY:
+                    sendResponse("NO");
+                    break;
+
+                case MESSAGE_ADB_CONFIRM: {
+                    String key = (String)msg.obj;
+                    mFingerprints = getFingerprints(key);
+                    showConfirmationDialog(key, mFingerprints);
+                    break;
+                }
+            }
+        }
+    }
+
+    private String getFingerprints(String key) {
+        String hex = "0123456789ABCDEF";
+        StringBuilder sb = new StringBuilder();
+        MessageDigest digester;
+
+        try {
+            digester = MessageDigest.getInstance("MD5");
+        } catch (Exception ex) {
+            Slog.e(TAG, "Error getting digester: " + ex);
+            return "";
+        }
+
+        byte[] base64_data = key.split("\\s+")[0].getBytes();
+        byte[] digest = digester.digest(Base64.decode(base64_data, Base64.DEFAULT));
+
+        for (int i = 0; i < digest.length; i++) {
+            sb.append(hex.charAt((digest[i] >> 4) & 0xf));
+            sb.append(hex.charAt(digest[i] & 0xf));
+            if (i < digest.length - 1)
+                sb.append(":");
+        }
+        return sb.toString();
+    }
+
+    private void showConfirmationDialog(String key, String fingerprints) {
+        Intent dialogIntent = new Intent();
+
+        dialogIntent.setClassName("com.android.systemui",
+                "com.android.systemui.usb.UsbDebuggingActivity");
+        dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        dialogIntent.putExtra("key", key);
+        dialogIntent.putExtra("fingerprints", fingerprints);
+        try {
+            mContext.startActivity(dialogIntent);
+        } catch (ActivityNotFoundException e) {
+            Slog.e(TAG, "unable to start UsbDebuggingActivity");
+        }
+    }
+
+    private void writeKey(String key) {
+        File dataDir = Environment.getDataDirectory();
+        File adbDir = new File(dataDir, ADB_DIRECTORY);
+
+        if (!adbDir.exists()) {
+            Slog.e(TAG, "ADB data directory does not exist");
+            return;
+        }
+
+        try {
+            File keyFile = new File(adbDir, ADB_KEYS_FILE);
+
+            if (!keyFile.exists()) {
+                keyFile.createNewFile();
+                FileUtils.setPermissions(keyFile.toString(),
+                    FileUtils.S_IRUSR | FileUtils.S_IWUSR |
+                    FileUtils.S_IRGRP, -1, -1);
+            }
+
+            FileOutputStream fo = new FileOutputStream(keyFile, true);
+            fo.write(key.getBytes());
+            fo.write('\n');
+            fo.close();
+        }
+        catch (IOException ex) {
+            Slog.e(TAG, "Error writing key:" + ex);
+        }
+    }
+
+
+    public void setAdbEnabled(boolean enabled) {
+        mHandler.sendEmptyMessage(enabled ? UsbDebuggingHandler.MESSAGE_ADB_ENABLED
+                                          : UsbDebuggingHandler.MESSAGE_ADB_DISABLED);
+    }
+
+    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
+        Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_ALLOW);
+        msg.arg1 = alwaysAllow ? 1 : 0;
+        msg.obj = publicKey;
+        mHandler.sendMessage(msg);
+    }
+
+    public void denyUsbDebugging() {
+        mHandler.sendEmptyMessage(UsbDebuggingHandler.MESSAGE_ADB_DENY);
+    }
+
+
+    public void dump(FileDescriptor fd, PrintWriter pw) {
+        pw.println("  USB Debugging State:");
+        pw.println("    Connected to adbd: " + (mOutputStream != null));
+        pw.println("    Last key received: " + mFingerprints);
+        pw.println("    User keys:");
+        try {
+            pw.println(FileUtils.readTextFile(new File("/data/misc/adb/adb_keys"), 0, null));
+        } catch (IOException e) {
+            pw.println("IOException: " + e);
+        }
+        pw.println("    System keys:");
+        try {
+            pw.println(FileUtils.readTextFile(new File("/adb_keys"), 0, null));
+        } catch (IOException e) {
+            pw.println("IOException: " + e);
+        }
+    }
+}
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index a115345c..f34a52d 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -16,9 +16,9 @@
 
 package com.android.server.usb;
 
-import android.app.PendingIntent;
 import android.app.Notification;
 import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -30,22 +30,19 @@
 import android.database.ContentObserver;
 import android.hardware.usb.UsbAccessory;
 import android.hardware.usb.UsbManager;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.Bundle;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Parcelable;
 import android.os.ParcelFileDescriptor;
 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.os.UserHandle;
+import android.os.storage.StorageManager;
+import android.os.storage.StorageVolume;
 import android.provider.Settings;
 import android.util.Pair;
 import android.util.Slog;
@@ -55,10 +52,9 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.HashMap;
 import java.util.Map;
 import java.util.Scanner;
 
@@ -90,6 +86,7 @@
     private static final int MSG_SET_CURRENT_FUNCTIONS = 2;
     private static final int MSG_SYSTEM_READY = 3;
     private static final int MSG_BOOT_COMPLETED = 4;
+    private static final int MSG_USER_SWITCHED = 5;
 
     private static final int AUDIO_MODE_NONE = 0;
     private static final int AUDIO_MODE_SOURCE = 1;
@@ -104,9 +101,12 @@
     private UsbHandler mHandler;
     private boolean mBootCompleted;
 
+    private final Object mLock = new Object();
+
     private final Context mContext;
     private final ContentResolver mContentResolver;
-    private final UsbSettingsManager mSettingsManager;
+    // @GuardedBy("mLock")
+    private UsbSettingsManager mCurrentSettings;
     private NotificationManager mNotificationManager;
     private final boolean mHasUsbAccessory;
     private boolean mUseUsbNotification;
@@ -114,6 +114,7 @@
     private boolean mAudioSourceEnabled;
     private Map<String, List<Pair<String, String>>> mOemModeMap;
     private String[] mAccessoryStrings;
+    private UsbDebuggingManager mDebuggingManager;
 
     private class AdbSettingsObserver extends ContentObserver {
         public AdbSettingsObserver() {
@@ -121,8 +122,8 @@
         }
         @Override
         public void onChange(boolean selfChange) {
-            boolean enable = (Settings.Secure.getInt(mContentResolver,
-                    Settings.Secure.ADB_ENABLED, 0) > 0);
+            boolean enable = (Settings.Global.getInt(mContentResolver,
+                    Settings.Global.ADB_ENABLED, 0) > 0);
             mHandler.sendMessage(MSG_ENABLE_ADB, enable);
         }
     }
@@ -146,10 +147,9 @@
         }
     };
 
-    public UsbDeviceManager(Context context, UsbSettingsManager settingsManager) {
+    public UsbDeviceManager(Context context) {
         mContext = context;
         mContentResolver = context.getContentResolver();
-        mSettingsManager = settingsManager;
         PackageManager pm = mContext.getPackageManager();
         mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
         initRndisAddress();
@@ -166,6 +166,22 @@
             if (DEBUG) Slog.d(TAG, "accessory attached at boot");
             startAccessoryMode();
         }
+
+        if ("1".equals(SystemProperties.get("ro.adb.secure"))) {
+            mDebuggingManager = new UsbDebuggingManager(context);
+        }
+    }
+
+    public void setCurrentSettings(UsbSettingsManager settings) {
+        synchronized (mLock) {
+            mCurrentSettings = settings;
+        }
+    }
+
+    private UsbSettingsManager getCurrentSettings() {
+        synchronized (mLock) {
+            return mCurrentSettings;
+        }
     }
 
     public void systemReady() {
@@ -177,16 +193,13 @@
         // We do not show the USB notification if the primary volume supports mass storage.
         // The legacy mass storage UI will be used instead.
         boolean massStorageSupported = false;
-        StorageManager storageManager = (StorageManager)
-                mContext.getSystemService(Context.STORAGE_SERVICE);
-        StorageVolume[] volumes = storageManager.getVolumeList();
-        if (volumes.length > 0) {
-            massStorageSupported = volumes[0].allowMassStorage();
-        }
+        final StorageManager storageManager = StorageManager.from(mContext);
+        final StorageVolume primary = storageManager.getPrimaryVolume();
+        massStorageSupported = primary != null && primary.allowMassStorage();
         mUseUsbNotification = !massStorageSupported;
 
         // make sure the ADB_ENABLED setting value matches the current state
-        Settings.Secure.putInt(mContentResolver, Settings.Secure.ADB_ENABLED, mAdbEnabled ? 1 : 0);
+        Settings.Global.putInt(mContentResolver, Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0);
 
         mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
     }
@@ -292,14 +305,24 @@
         private UsbAccessory mCurrentAccessory;
         private int mUsbNotificationId;
         private boolean mAdbNotificationShown;
+        private int mCurrentUser = UserHandle.USER_NULL;
 
         private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
+            @Override
             public void onReceive(Context context, Intent intent) {
                 if (DEBUG) Slog.d(TAG, "boot completed");
                 mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
             }
         };
 
+        private final BroadcastReceiver mUserSwitchedReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+                mHandler.obtainMessage(MSG_USER_SWITCHED, userId, 0).sendToTarget();
+            }
+        };
+
         public UsbHandler(Looper looper) {
             super(looper);
             try {
@@ -337,15 +360,17 @@
 
                 // register observer to listen for settings changes
                 mContentResolver.registerContentObserver(
-                        Settings.Secure.getUriFor(Settings.Secure.ADB_ENABLED),
+                        Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
                                 false, new AdbSettingsObserver());
 
                 // Watch for USB configuration changes
                 mUEventObserver.startObserving(USB_STATE_MATCH);
                 mUEventObserver.startObserving(ACCESSORY_START_MATCH);
 
-                mContext.registerReceiver(mBootCompletedReceiver,
-                        new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+                mContext.registerReceiver(
+                        mBootCompletedReceiver, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+                mContext.registerReceiver(
+                        mUserSwitchedReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED));
             } catch (Exception e) {
                 Slog.e(TAG, "Error initializing UsbHandler", e);
             }
@@ -425,6 +450,9 @@
                 setEnabledFunctions(mDefaultFunctions, true);
                 updateAdbNotification();
             }
+            if (mDebuggingManager != null) {
+                mDebuggingManager.setAdbEnabled(mAdbEnabled);
+            }
         }
 
         private void setEnabledFunctions(String functions, boolean makeDefault) {
@@ -497,7 +525,7 @@
                     Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
                     // defer accessoryAttached if system is not ready
                     if (mBootCompleted) {
-                        mSettingsManager.accessoryAttached(mCurrentAccessory);
+                        getCurrentSettings().accessoryAttached(mCurrentAccessory);
                     } // else handle in mBootCompletedReceiver
                 } else {
                     Slog.e(TAG, "nativeGetAccessoryStrings failed");
@@ -510,7 +538,7 @@
 
                 if (mCurrentAccessory != null) {
                     if (mBootCompleted) {
-                        mSettingsManager.accessoryDetached(mCurrentAccessory);
+                        getCurrentSettings().accessoryDetached(mCurrentAccessory);
                     }
                     mCurrentAccessory = null;
                     mAccessoryStrings = null;
@@ -532,7 +560,7 @@
                 }
             }
 
-            mContext.sendStickyBroadcast(intent);
+            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
         }
 
         private void updateAudioSourceFunction() {
@@ -555,7 +583,7 @@
                         Slog.e(TAG, "could not open audio source PCM file", e);
                     }
                 }
-                mContext.sendStickyBroadcast(intent);
+                mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
                 mAudioSourceEnabled = enabled;
             }
         }
@@ -599,9 +627,24 @@
                 case MSG_BOOT_COMPLETED:
                     mBootCompleted = true;
                     if (mCurrentAccessory != null) {
-                        mSettingsManager.accessoryAttached(mCurrentAccessory);
+                        getCurrentSettings().accessoryAttached(mCurrentAccessory);
+                    }
+                    if (mDebuggingManager != null) {
+                        mDebuggingManager.setAdbEnabled(mAdbEnabled);
                     }
                     break;
+                case MSG_USER_SWITCHED: {
+                    final boolean mtpActive =
+                            containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)
+                            || containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP);
+                    if (mtpActive && mCurrentUser != UserHandle.USER_NULL) {
+                        Slog.v(TAG, "Current user switched; resetting USB host stack for MTP");
+                        setUsbConfig("none");
+                        setUsbConfig(mCurrentFunctions);
+                    }
+                    mCurrentUser = msg.arg1;
+                    break;
+                }
             }
         }
 
@@ -625,15 +668,16 @@
                     id = com.android.internal.R.string.usb_accessory_notification_title;
                 } else {
                     // There is a different notification for USB tethering so we don't need one here
-                    if (!containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_RNDIS)) {
-                        Slog.e(TAG, "No known USB function in updateUsbNotification");
-                    }
+                    //if (!containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_RNDIS)) {
+                    //    Slog.e(TAG, "No known USB function in updateUsbNotification");
+                    //}
                 }
             }
             if (id != mUsbNotificationId) {
                 // clear notification if title needs changing
                 if (mUsbNotificationId != 0) {
-                    mNotificationManager.cancel(mUsbNotificationId);
+                    mNotificationManager.cancelAsUser(null, mUsbNotificationId,
+                            UserHandle.ALL);
                     mUsbNotificationId = 0;
                 }
                 if (id != 0) {
@@ -654,10 +698,11 @@
                     Intent intent = Intent.makeRestartActivityTask(
                             new ComponentName("com.android.settings",
                                     "com.android.settings.UsbSettings"));
-                    PendingIntent pi = PendingIntent.getActivity(mContext, 0,
-                            intent, 0);
+                    PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
+                            intent, 0, null, UserHandle.CURRENT);
                     notification.setLatestEventInfo(mContext, title, message, pi);
-                    mNotificationManager.notify(id, notification);
+                    mNotificationManager.notifyAsUser(null, id, notification,
+                            UserHandle.ALL);
                     mUsbNotificationId = id;
                 }
             }
@@ -688,15 +733,16 @@
                     Intent intent = Intent.makeRestartActivityTask(
                             new ComponentName("com.android.settings",
                                     "com.android.settings.DevelopmentSettings"));
-                    PendingIntent pi = PendingIntent.getActivity(mContext, 0,
-                            intent, 0);
+                    PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
+                            intent, 0, null, UserHandle.CURRENT);
                     notification.setLatestEventInfo(mContext, title, message, pi);
                     mAdbNotificationShown = true;
-                    mNotificationManager.notify(id, notification);
+                    mNotificationManager.notifyAsUser(null, id, notification,
+                            UserHandle.ALL);
                 }
             } else if (mAdbNotificationShown) {
                 mAdbNotificationShown = false;
-                mNotificationManager.cancel(id);
+                mNotificationManager.cancelAsUser(null, id, UserHandle.ALL);
             }
         }
 
@@ -737,7 +783,7 @@
                     + currentAccessory;
             throw new IllegalArgumentException(error);
         }
-        mSettingsManager.checkPermission(accessory);
+        getCurrentSettings().checkPermission(accessory);
         return nativeOpenAccessory();
     }
 
@@ -802,10 +848,25 @@
         return usbFunctions;
     }
 
+    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
+        if (mDebuggingManager != null) {
+            mDebuggingManager.allowUsbDebugging(alwaysAllow, publicKey);
+        }
+    }
+
+    public void denyUsbDebugging() {
+        if (mDebuggingManager != null) {
+            mDebuggingManager.denyUsbDebugging();
+        }
+    }
+
     public void dump(FileDescriptor fd, PrintWriter pw) {
         if (mHandler != null) {
             mHandler.dump(fd, pw);
         }
+        if (mDebuggingManager != null) {
+            mDebuggingManager.dump(fd, pw);
+        }
     }
 
     private native String[] nativeGetAccessoryStrings();
diff --git a/services/java/com/android/server/usb/UsbHostManager.java b/services/java/com/android/server/usb/UsbHostManager.java
index 0a0ff59..175ae6f 100644
--- a/services/java/com/android/server/usb/UsbHostManager.java
+++ b/services/java/com/android/server/usb/UsbHostManager.java
@@ -16,35 +16,19 @@
 
 package com.android.server.usb;
 
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.hardware.usb.IUsbManager;
 import android.hardware.usb.UsbConstants;
 import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbEndpoint;
 import android.hardware.usb.UsbInterface;
-import android.hardware.usb.UsbManager;
-import android.net.Uri;
-import android.os.Binder;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Parcelable;
 import android.os.ParcelFileDescriptor;
-import android.os.UEventObserver;
-import android.provider.Settings;
+import android.os.Parcelable;
 import android.util.Slog;
 
-import java.io.File;
 import java.io.FileDescriptor;
-import java.io.FileReader;
 import java.io.PrintWriter;
 import java.util.HashMap;
-import java.util.List;
 
 /**
  * UsbHostManager manages USB state in host mode.
@@ -54,22 +38,35 @@
     private static final boolean LOG = false;
 
     // contains all connected USB devices
-    private final HashMap<String,UsbDevice> mDevices = new HashMap<String,UsbDevice>();
+    private final HashMap<String, UsbDevice> mDevices = new HashMap<String, UsbDevice>();
 
     // USB busses to exclude from USB host support
     private final String[] mHostBlacklist;
 
     private final Context mContext;
     private final Object mLock = new Object();
-    private final UsbSettingsManager mSettingsManager;
 
-    public UsbHostManager(Context context, UsbSettingsManager settingsManager) {
+    // @GuardedBy("mLock")
+    private UsbSettingsManager mCurrentSettings;
+
+    public UsbHostManager(Context context) {
         mContext = context;
-        mSettingsManager = settingsManager;
         mHostBlacklist = context.getResources().getStringArray(
                 com.android.internal.R.array.config_usbHostBlacklist);
     }
 
+    public void setCurrentSettings(UsbSettingsManager settings) {
+        synchronized (mLock) {
+            mCurrentSettings = settings;
+        }
+    }
+
+    private UsbSettingsManager getCurrentSettings() {
+        synchronized (mLock) {
+            return mCurrentSettings;
+        }
+    }
+
     private boolean isBlackListed(String deviceName) {
         int count = mHostBlacklist.length;
         for (int i = 0; i < count; i++) {
@@ -154,7 +151,7 @@
             UsbDevice device = new UsbDevice(deviceName, vendorID, productID,
                     deviceClass, deviceSubclass, deviceProtocol, interfaces);
             mDevices.put(deviceName, device);
-            mSettingsManager.deviceAttached(device);
+            getCurrentSettings().deviceAttached(device);
         }
     }
 
@@ -163,7 +160,7 @@
         synchronized (mLock) {
             UsbDevice device = mDevices.remove(deviceName);
             if (device != null) {
-                mSettingsManager.deviceDetached(device);
+                getCurrentSettings().deviceDetached(device);
             }
         }
     }
@@ -202,7 +199,7 @@
                 throw new IllegalArgumentException(
                         "device " + deviceName + " does not exist or is restricted");
             }
-            mSettingsManager.checkPermission(device);
+            getCurrentSettings().checkPermission(device);
             return nativeOpenDevice(deviceName);
         }
     }
diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java
index 0205ef8..629f5fa 100644
--- a/services/java/com/android/server/usb/UsbService.java
+++ b/services/java/com/android/server/usb/UsbService.java
@@ -17,15 +17,20 @@
 package com.android.server.usb;
 
 import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.hardware.usb.IUsbManager;
 import android.hardware.usb.UsbAccessory;
 import android.hardware.usb.UsbDevice;
-import android.net.Uri;
-import android.os.Binder;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
+import android.util.SparseArray;
+
+import com.android.internal.util.IndentingPrintWriter;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -37,21 +42,72 @@
  * support is delegated to UsbDeviceManager.
  */
 public class UsbService extends IUsbManager.Stub {
+    private static final String TAG = "UsbService";
+
     private final Context mContext;
+
     private UsbDeviceManager mDeviceManager;
     private UsbHostManager mHostManager;
-    private final UsbSettingsManager mSettingsManager;
 
+    private final Object mLock = new Object();
+
+    /** Map from {@link UserHandle} to {@link UsbSettingsManager} */
+    // @GuardedBy("mLock")
+    private final SparseArray<UsbSettingsManager>
+            mSettingsByUser = new SparseArray<UsbSettingsManager>();
+
+    private UsbSettingsManager getSettingsForUser(int userId) {
+        synchronized (mLock) {
+            UsbSettingsManager settings = mSettingsByUser.get(userId);
+            if (settings == null) {
+                settings = new UsbSettingsManager(mContext, new UserHandle(userId));
+                mSettingsByUser.put(userId, settings);
+            }
+            return settings;
+        }
+    }
 
     public UsbService(Context context) {
         mContext = context;
-        mSettingsManager = new UsbSettingsManager(context);
-        PackageManager pm = mContext.getPackageManager();
+
+        final PackageManager pm = mContext.getPackageManager();
         if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
-            mHostManager = new UsbHostManager(context, mSettingsManager);
+            mHostManager = new UsbHostManager(context);
         }
         if (new File("/sys/class/android_usb").exists()) {
-            mDeviceManager = new UsbDeviceManager(context, mSettingsManager);
+            mDeviceManager = new UsbDeviceManager(context);
+        }
+
+        setCurrentUser(UserHandle.USER_OWNER);
+
+        final IntentFilter userFilter = new IntentFilter();
+        userFilter.addAction(Intent.ACTION_USER_SWITCHED);
+        userFilter.addAction(Intent.ACTION_USER_STOPPED);
+        mContext.registerReceiver(mUserReceiver, userFilter, null, null);
+    }
+
+    private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+            final String action = intent.getAction();
+            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                setCurrentUser(userId);
+            } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
+                synchronized (mLock) {
+                    mSettingsByUser.remove(userId);
+                }
+            }
+        }
+    };
+
+    private void setCurrentUser(int userId) {
+        final UsbSettingsManager userSettings = getSettingsForUser(userId);
+        if (mHostManager != null) {
+            mHostManager.setCurrentSettings(userSettings);
+        }
+        if (mDeviceManager != null) {
+            mDeviceManager.setCurrentSettings(userSettings);
         }
     }
 
@@ -65,6 +121,7 @@
     }
 
     /* Returns a list of all currently attached USB devices (host mdoe) */
+    @Override
     public void getDeviceList(Bundle devices) {
         if (mHostManager != null) {
             mHostManager.getDeviceList(devices);
@@ -72,6 +129,7 @@
     }
 
     /* Opens the specified USB device (host mode) */
+    @Override
     public ParcelFileDescriptor openDevice(String deviceName) {
         if (mHostManager != null) {
             return mHostManager.openDevice(deviceName);
@@ -81,6 +139,7 @@
     }
 
     /* returns the currently attached USB accessory (device mode) */
+    @Override
     public UsbAccessory getCurrentAccessory() {
         if (mDeviceManager != null) {
             return mDeviceManager.getCurrentAccessory();
@@ -90,6 +149,7 @@
     }
 
     /* opens the currently attached USB accessory (device mode) */
+    @Override
     public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
         if (mDeviceManager != null) {
             return mDeviceManager.openAccessory(accessory);
@@ -98,54 +158,70 @@
         }
     }
 
-    public void setDevicePackage(UsbDevice device, String packageName) {
+    @Override
+    public void setDevicePackage(UsbDevice device, String packageName, int userId) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
-        mSettingsManager.setDevicePackage(device, packageName);
+        getSettingsForUser(userId).setDevicePackage(device, packageName);
     }
 
-    public void setAccessoryPackage(UsbAccessory accessory, String packageName) {
+    @Override
+    public void setAccessoryPackage(UsbAccessory accessory, String packageName, int userId) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
-        mSettingsManager.setAccessoryPackage(accessory, packageName);
+        getSettingsForUser(userId).setAccessoryPackage(accessory, packageName);
     }
 
+    @Override
     public boolean hasDevicePermission(UsbDevice device) {
-        return mSettingsManager.hasPermission(device);
+        final int userId = UserHandle.getCallingUserId();
+        return getSettingsForUser(userId).hasPermission(device);
     }
 
+    @Override
     public boolean hasAccessoryPermission(UsbAccessory accessory) {
-        return mSettingsManager.hasPermission(accessory);
+        final int userId = UserHandle.getCallingUserId();
+        return getSettingsForUser(userId).hasPermission(accessory);
     }
 
-    public void requestDevicePermission(UsbDevice device, String packageName,
-            PendingIntent pi) {
-        mSettingsManager.requestPermission(device, packageName, pi);
+    @Override
+    public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) {
+        final int userId = UserHandle.getCallingUserId();
+        getSettingsForUser(userId).requestPermission(device, packageName, pi);
     }
 
-    public void requestAccessoryPermission(UsbAccessory accessory, String packageName,
-            PendingIntent pi) {
-        mSettingsManager.requestPermission(accessory, packageName, pi);
+    @Override
+    public void requestAccessoryPermission(
+            UsbAccessory accessory, String packageName, PendingIntent pi) {
+        final int userId = UserHandle.getCallingUserId();
+        getSettingsForUser(userId).requestPermission(accessory, packageName, pi);
     }
 
+    @Override
     public void grantDevicePermission(UsbDevice device, int uid) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
-        mSettingsManager.grantDevicePermission(device, uid);
+        final int userId = UserHandle.getUserId(uid);
+        getSettingsForUser(userId).grantDevicePermission(device, uid);
     }
 
+    @Override
     public void grantAccessoryPermission(UsbAccessory accessory, int uid) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
-        mSettingsManager.grantAccessoryPermission(accessory, uid);
+        final int userId = UserHandle.getUserId(uid);
+        getSettingsForUser(userId).grantAccessoryPermission(accessory, uid);
     }
 
-    public boolean hasDefaults(String packageName) {
+    @Override
+    public boolean hasDefaults(String packageName, int userId) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
-        return mSettingsManager.hasDefaults(packageName);
+        return getSettingsForUser(userId).hasDefaults(packageName);
     }
 
-    public void clearDefaults(String packageName) {
+    @Override
+    public void clearDefaults(String packageName, int userId) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
-        mSettingsManager.clearDefaults(packageName);
+        getSettingsForUser(userId).clearDefaults(packageName);
     }
 
+    @Override
     public void setCurrentFunction(String function, boolean makeDefault) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
         if (mDeviceManager != null) {
@@ -155,6 +231,7 @@
         }
     }
 
+    @Override
     public void setMassStorageBackingFile(String path) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
         if (mDeviceManager != null) {
@@ -165,23 +242,40 @@
     }
 
     @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump UsbManager from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
+    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);
+    }
+
+    @Override
+    public void denyUsbDebugging() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        mDeviceManager.denyUsbDebugging();
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
 
         pw.println("USB Manager State:");
-
         if (mDeviceManager != null) {
             mDeviceManager.dump(fd, pw);
         }
         if (mHostManager != null) {
             mHostManager.dump(fd, pw);
         }
-        mSettingsManager.dump(fd, pw);
+
+        synchronized (mLock) {
+            for (int i = 0; i < mSettingsByUser.size(); i++) {
+                final int userId = mSettingsByUser.keyAt(i);
+                final UsbSettingsManager settings = mSettingsByUser.valueAt(i);
+                pw.increaseIndent();
+                pw.println("Settings for user " + userId + ":");
+                settings.dump(fd, pw);
+                pw.decreaseIndent();
+            }
+        }
+        pw.decreaseIndent();
     }
 }
diff --git a/services/java/com/android/server/usb/UsbSettingsManager.java b/services/java/com/android/server/usb/UsbSettingsManager.java
index 9b3459b..4b2bbfe 100644
--- a/services/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/java/com/android/server/usb/UsbSettingsManager.java
@@ -33,8 +33,10 @@
 import android.hardware.usb.UsbInterface;
 import android.hardware.usb.UsbManager;
 import android.os.Binder;
-import android.os.FileUtils;
-import android.os.Process;
+import android.os.Environment;
+import android.os.UserHandle;
+import android.util.AtomicFile;
+import android.util.Log;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
 import android.util.Xml;
@@ -47,7 +49,6 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
-import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
@@ -59,13 +60,21 @@
 import java.util.HashMap;
 import java.util.List;
 
-class UsbSettingsManager {
+import libcore.io.IoUtils;
 
+class UsbSettingsManager {
     private static final String TAG = "UsbSettingsManager";
     private static final boolean DEBUG = false;
-    private static final File sSettingsFile = new File("/data/system/usb_device_manager.xml");
+
+    /** Legacy settings file, before multi-user */
+    private static final File sSingleUserSettingsFile = new File(
+            "/data/system/usb_device_manager.xml");
+
+    private final UserHandle mUser;
+    private final AtomicFile mSettingsFile;
 
     private final Context mContext;
+    private final Context mUserContext;
     private final PackageManager mPackageManager;
 
     // Temporary mapping USB device name to list of UIDs with permissions for the device
@@ -349,28 +358,49 @@
     }
 
     private class MyPackageMonitor extends PackageMonitor {
-
+        @Override
         public void onPackageAdded(String packageName, int uid) {
             handlePackageUpdate(packageName);
         }
 
+        @Override
         public void onPackageChanged(String packageName, int uid, String[] components) {
             handlePackageUpdate(packageName);
         }
 
+        @Override
         public void onPackageRemoved(String packageName, int uid) {
             clearDefaults(packageName);
         }
     }
+
     MyPackageMonitor mPackageMonitor = new MyPackageMonitor();
 
-    public UsbSettingsManager(Context context) {
+    public UsbSettingsManager(Context context, UserHandle user) {
+        if (DEBUG) Slog.v(TAG, "Creating settings for " + user);
+
+        try {
+            mUserContext = context.createPackageContextAsUser("android", 0, user);
+        } catch (NameNotFoundException e) {
+            throw new RuntimeException("Missing android package");
+        }
+
         mContext = context;
-        mPackageManager = context.getPackageManager();
+        mPackageManager = mUserContext.getPackageManager();
+
+        mUser = user;
+        mSettingsFile = new AtomicFile(new File(
+                Environment.getUserSystemDirectory(user.getIdentifier()),
+                "usb_device_manager.xml"));
+
         synchronized (mLock) {
+            if (UserHandle.OWNER.equals(user)) {
+                upgradeSingleUserLocked();
+            }
             readSettingsLocked();
         }
-        mPackageMonitor.register(context, null, true);
+
+        mPackageMonitor.register(mUserContext, null, true);
     }
 
     private void readPreference(XmlPullParser parser)
@@ -394,10 +424,54 @@
         XmlUtils.nextElement(parser);
     }
 
+    /**
+     * Upgrade any single-user settings from {@link #sSingleUserSettingsFile}.
+     * Should only by called by owner.
+     */
+    private void upgradeSingleUserLocked() {
+        if (sSingleUserSettingsFile.exists()) {
+            mDevicePreferenceMap.clear();
+            mAccessoryPreferenceMap.clear();
+
+            FileInputStream fis = null;
+            try {
+                fis = new FileInputStream(sSingleUserSettingsFile);
+                XmlPullParser parser = Xml.newPullParser();
+                parser.setInput(fis, null);
+
+                XmlUtils.nextElement(parser);
+                while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+                    final String tagName = parser.getName();
+                    if ("preference".equals(tagName)) {
+                        readPreference(parser);
+                    } else {
+                        XmlUtils.nextElement(parser);
+                    }
+                }
+            } catch (IOException e) {
+                Log.wtf(TAG, "Failed to read single-user settings", e);
+            } catch (XmlPullParserException e) {
+                Log.wtf(TAG, "Failed to read single-user settings", e);
+            } finally {
+                IoUtils.closeQuietly(fis);
+            }
+
+            writeSettingsLocked();
+
+            // Success or failure, we delete single-user file
+            sSingleUserSettingsFile.delete();
+        }
+    }
+
     private void readSettingsLocked() {
+        if (DEBUG) Slog.v(TAG, "readSettingsLocked()");
+
+        mDevicePreferenceMap.clear();
+        mAccessoryPreferenceMap.clear();
+
         FileInputStream stream = null;
         try {
-            stream = new FileInputStream(sSettingsFile);
+            stream = mSettingsFile.openRead();
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(stream, null);
 
@@ -406,7 +480,7 @@
                 String tagName = parser.getName();
                 if ("preference".equals(tagName)) {
                     readPreference(parser);
-                 } else {
+                } else {
                     XmlUtils.nextElement(parser);
                 }
             }
@@ -414,25 +488,21 @@
             if (DEBUG) Slog.d(TAG, "settings file not found");
         } catch (Exception e) {
             Slog.e(TAG, "error reading settings file, deleting to start fresh", e);
-            sSettingsFile.delete();
+            mSettingsFile.delete();
         } finally {
-            if (stream != null) {
-                try {
-                    stream.close();
-                } catch (IOException e) {
-                }
-            }
+            IoUtils.closeQuietly(stream);
         }
     }
 
     private void writeSettingsLocked() {
+        if (DEBUG) Slog.v(TAG, "writeSettingsLocked()");
+
         FileOutputStream fos = null;
         try {
-            FileOutputStream fstr = new FileOutputStream(sSettingsFile);
-            if (DEBUG) Slog.d(TAG, "writing settings to " + fstr);
-            BufferedOutputStream str = new BufferedOutputStream(fstr);
+            fos = mSettingsFile.startWrite();
+
             FastXmlSerializer serializer = new FastXmlSerializer();
-            serializer.setOutput(str, "utf-8");
+            serializer.setOutput(fos, "utf-8");
             serializer.startDocument(null, true);
             serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
             serializer.startTag(null, "settings");
@@ -454,12 +524,12 @@
             serializer.endTag(null, "settings");
             serializer.endDocument();
 
-            str.flush();
-            FileUtils.sync(fstr);
-            str.close();
-        } catch (Exception e) {
-            Slog.e(TAG, "error writing settings file, deleting to start fresh", e);
-            sSettingsFile.delete();
+            mSettingsFile.finishWrite(fos);
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to write settings", e);
+            if (fos != null) {
+                mSettingsFile.failWrite(fos);
+            }
         }
     }
 
@@ -546,7 +616,7 @@
         }
 
         // Send broadcast to running activity with registered intent
-        mContext.sendBroadcast(intent);
+        mUserContext.sendBroadcast(intent);
 
         // Start activity with registered intent
         resolveActivity(intent, matches, defaultPackage, device, null);
@@ -559,7 +629,7 @@
         Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED);
         intent.putExtra(UsbManager.EXTRA_DEVICE, device);
         if (DEBUG) Slog.d(TAG, "usbDeviceRemoved, sending " + intent);
-        mContext.sendBroadcast(intent);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     public void accessoryAttached(UsbAccessory accessory) {
@@ -586,7 +656,7 @@
         Intent intent = new Intent(
                 UsbManager.ACTION_USB_ACCESSORY_DETACHED);
         intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
-        mContext.sendBroadcast(intent);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void resolveActivity(Intent intent, ArrayList<ResolveInfo> matches,
@@ -607,7 +677,7 @@
                     dialogIntent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
                     dialogIntent.putExtra("uri", uri);
                     try {
-                        mContext.startActivity(dialogIntent);
+                        mUserContext.startActivityAsUser(dialogIntent, mUser);
                     } catch (ActivityNotFoundException e) {
                         Slog.e(TAG, "unable to start UsbAccessoryUriActivity");
                     }
@@ -655,7 +725,7 @@
                 intent.setComponent(
                         new ComponentName(defaultRI.activityInfo.packageName,
                                 defaultRI.activityInfo.name));
-                mContext.startActivity(intent);
+                mUserContext.startActivityAsUser(intent, mUser);
             } catch (ActivityNotFoundException e) {
                 Slog.e(TAG, "startActivity failed", e);
             }
@@ -682,7 +752,7 @@
                 resolverIntent.putExtra(Intent.EXTRA_INTENT, intent);
             }
             try {
-                mContext.startActivity(resolverIntent);
+                mUserContext.startActivityAsUser(resolverIntent, mUser);
             } catch (ActivityNotFoundException e) {
                 Slog.e(TAG, "unable to start activity " + resolverIntent);
             }
@@ -813,7 +883,7 @@
     }
 
     private void requestPermissionDialog(Intent intent, String packageName, PendingIntent pi) {
-        int uid = Binder.getCallingUid();
+        final int uid = Binder.getCallingUid();
 
         // compare uid with packageName to foil apps pretending to be someone else
         try {
@@ -832,9 +902,9 @@
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         intent.putExtra(Intent.EXTRA_INTENT, pi);
         intent.putExtra("package", packageName);
-        intent.putExtra("uid", uid);
+        intent.putExtra(Intent.EXTRA_UID, uid);
         try {
-            mContext.startActivity(intent);
+            mUserContext.startActivityAsUser(intent, mUser);
         } catch (ActivityNotFoundException e) {
             Slog.e(TAG, "unable to start UsbPermissionActivity");
         } finally {
@@ -850,7 +920,7 @@
             intent.putExtra(UsbManager.EXTRA_DEVICE, device);
             intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
             try {
-                pi.send(mContext, 0, intent);
+                pi.send(mUserContext, 0, intent);
             } catch (PendingIntent.CanceledException e) {
                 if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled");
             }
@@ -863,14 +933,14 @@
     }
 
     public void requestPermission(UsbAccessory accessory, String packageName, PendingIntent pi) {
-      Intent intent = new Intent();
+        Intent intent = new Intent();
 
         // respond immediately if permission has already been granted
         if (hasPermission(accessory)) {
             intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
             intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
-           try {
-                pi.send(mContext, 0, intent);
+            try {
+                pi.send(mUserContext, 0, intent);
             } catch (PendingIntent.CanceledException e) {
                 if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled");
             }
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java
index 13e8bc5..ca94d04 100644
--- a/services/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/java/com/android/server/wm/AppWindowAnimator.java
@@ -4,16 +4,15 @@
 
 import android.graphics.Matrix;
 import android.util.Slog;
+import android.view.Display;
 import android.view.Surface;
 import android.view.WindowManagerPolicy;
 import android.view.animation.Animation;
 import android.view.animation.Transformation;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
 
-/**
- *
- */
 public class AppWindowAnimator {
     static final String TAG = "AppWindowAnimator";
 
@@ -48,12 +47,15 @@
     Animation thumbnailAnimation;
     final Transformation thumbnailTransformation = new Transformation();
 
+    /** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */
+    ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<WindowStateAnimator>();
+
     static final Animation sDummyAnimation = new DummyAnimation();
 
-    public AppWindowAnimator(final WindowManagerService service, final AppWindowToken atoken) {
-        mService = service;
+    public AppWindowAnimator(final AppWindowToken atoken) {
         mAppToken = atoken;
-        mAnimator = service.mAnimator;
+        mService = atoken.service;
+        mAnimator = atoken.mAnimator;
     }
 
     public void setAnimation(Animation anim, boolean initialized) {
@@ -123,7 +125,7 @@
             if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) {
                 mService.setInputMethodAnimLayerAdjustment(adj);
             }
-            if (w == mService.mWallpaperTarget && mService.mLowerWallpaperTarget == null) {
+            if (w == mAnimator.mWallpaperTarget && mAnimator.mLowerWallpaperTarget == null) {
                 mService.setWallpaperAnimLayerAdjustmentLocked(adj);
             }
         }
@@ -133,11 +135,13 @@
         thumbnailTransformation.clear();
         thumbnailAnimation.getTransformation(currentTime, thumbnailTransformation);
         thumbnailTransformation.getMatrix().preTranslate(thumbnailX, thumbnailY);
-        final boolean screenAnimation = mAnimator.mScreenRotationAnimation != null
-                && mAnimator.mScreenRotationAnimation.isAnimating();
+
+        ScreenRotationAnimation screenRotationAnimation =
+                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
+        final boolean screenAnimation = screenRotationAnimation != null
+                && screenRotationAnimation.isAnimating();
         if (screenAnimation) {
-            thumbnailTransformation.postCompose(
-                    mAnimator.mScreenRotationAnimation.getEnterTransformation());
+            thumbnailTransformation.postCompose(screenRotationAnimation.getEnterTransformation());
         }
         // cache often used attributes locally
         final float tmpFloats[] = mService.mTmpFloats;
@@ -168,7 +172,7 @@
         }
         transformation.clear();
         final boolean more = animation.getTransformation(currentTime, transformation);
-        if (WindowManagerService.DEBUG_ANIM) Slog.v(
+        if (false && WindowManagerService.DEBUG_ANIM) Slog.v(
             TAG, "Stepped animation in " + mAppToken + ": more=" + more + ", xform=" + transformation);
         if (!more) {
             animation = null;
@@ -233,10 +237,8 @@
             return false;
         }
 
-        mAnimator.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
-        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-            mService.debugLayoutRepeats("AppWindowToken", mAnimator.mPendingLayoutChanges);
-        }
+        mAnimator.setAppLayoutChanges(this, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
+                "AppWindowToken");
 
         clearAnimation();
         animating = false;
@@ -255,9 +257,9 @@
 
         transformation.clear();
 
-        final int N = mAppToken.windows.size();
+        final int N = mAllAppWinAnimators.size();
         for (int i=0; i<N; i++) {
-            mAppToken.windows.get(i).mWinAnimator.finishExit();
+            mAllAppWinAnimators.get(i).finishExit();
         }
         mAppToken.updateReportedVisibilityLocked();
 
@@ -266,9 +268,9 @@
 
     boolean showAllWindowsLocked() {
         boolean isAnimating = false;
-        final int NW = mAppToken.allAppWindows.size();
+        final int NW = mAllAppWinAnimators.size();
         for (int i=0; i<NW; i++) {
-            WindowStateAnimator winAnimator = mAppToken.allAppWindows.get(i).mWinAnimator;
+            WindowStateAnimator winAnimator = mAllAppWinAnimators.get(i);
             if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
                     "performing show on: " + winAnimator);
             winAnimator.performShowLocked();
@@ -277,22 +279,22 @@
         return isAnimating;
     }
 
-    void dump(PrintWriter pw, String prefix) {
-        if (freezingScreen) {
-            pw.print(prefix); pw.print(" freezingScreen="); pw.println(freezingScreen);
-        }
+    void dump(PrintWriter pw, String prefix, boolean dumpAll) {
+        pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
+        pw.print(prefix); pw.print("mAnimator="); pw.println(mAnimator);
+        pw.print(prefix); pw.print("freezingScreen="); pw.print(freezingScreen);
+                pw.print(" allDrawn="); pw.print(allDrawn);
+                pw.print(" animLayerAdjustment="); pw.println(animLayerAdjustment);
         if (animating || animation != null) {
             pw.print(prefix); pw.print("animating="); pw.print(animating);
-                    pw.print(" animation="); pw.println(animation);
+                    pw.print(" animInitialized="); pw.println(animInitialized);
+            pw.print(prefix); pw.print("animation="); pw.println(animation);
         }
         if (hasTransformation) {
             pw.print(prefix); pw.print("XForm: ");
                     transformation.printShortString(pw);
                     pw.println();
         }
-        if (animLayerAdjustment != 0) {
-            pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
-        }
         if (thumbnail != null) {
             pw.print(prefix); pw.print("thumbnail="); pw.print(thumbnail);
                     pw.print(" x="); pw.print(thumbnailX);
@@ -302,6 +304,11 @@
             pw.print(prefix); pw.print("thumbnailTransformation=");
                     pw.println(thumbnailTransformation.toShortString());
         }
+        for (int i=0; i<mAllAppWinAnimators.size(); i++) {
+            WindowStateAnimator wanim = mAllAppWinAnimators.get(i);
+            pw.print(prefix); pw.print("App Win Anim #"); pw.print(i);
+                    pw.print(": "); pw.println(wanim);
+        }
     }
 
     // This is an animation that does nothing: it just immediately finishes
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 6ecbb8e..7efffe5 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -50,6 +50,7 @@
     int groupId = -1;
     boolean appFullscreen;
     int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+    boolean showWhenLocked;
 
     // The input dispatching timeout for this application token in nanoseconds.
     long inputDispatchingTimeoutNanos;
@@ -104,7 +105,7 @@
         appToken = _token;
         mInputApplicationHandle = new InputApplicationHandle(this);
         mAnimator = service.mAnimator;
-        mAppAnimator = new AppWindowAnimator(_service, this);
+        mAppAnimator = new AppWindowAnimator(this);
     }
 
     void sendAppVisibilityToClients() {
diff --git a/services/java/com/android/server/wm/BlackFrame.java b/services/java/com/android/server/wm/BlackFrame.java
index 27af313..5b77b20 100644
--- a/services/java/com/android/server/wm/BlackFrame.java
+++ b/services/java/com/android/server/wm/BlackFrame.java
@@ -35,7 +35,7 @@
         final int layer;
         final Surface surface;
 
-        BlackSurface(SurfaceSession session, int layer, int l, int t, int r, int b)
+        BlackSurface(SurfaceSession session, int layer, int l, int t, int r, int b, int layerStack)
                 throws Surface.OutOfResourcesException {
             left = l;
             top = t;
@@ -43,14 +43,15 @@
             int w = r-l;
             int h = b-t;
             if (WindowManagerService.DEBUG_SURFACE_TRACE) {
-                surface = new WindowStateAnimator.SurfaceTrace(session, 0, "BlackSurface("
+                surface = new WindowStateAnimator.SurfaceTrace(session, "BlackSurface("
                         + l + ", " + t + ")",
-                        -1, w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM);
+                        w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM | Surface.HIDDEN);
             } else {
-                surface = new Surface(session, 0, "BlackSurface",
-                        -1, w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM);
+                surface = new Surface(session, "BlackSurface",
+                        w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM | Surface.HIDDEN);
             }
             surface.setAlpha(1);
+            surface.setLayerStack(layerStack);
             surface.setLayer(layer);
             surface.show();
             if (WindowManagerService.SHOW_TRANSACTIONS ||
@@ -103,7 +104,7 @@
     }
 
     public BlackFrame(SurfaceSession session, Rect outer, Rect inner,
-            int layer) throws Surface.OutOfResourcesException {
+            int layer, final int layerStack) throws Surface.OutOfResourcesException {
         boolean success = false;
 
         mOuterRect = new Rect(outer);
@@ -111,19 +112,19 @@
         try {
             if (outer.top < inner.top) {
                 mBlackSurfaces[0] = new BlackSurface(session, layer,
-                        outer.left, outer.top, inner.right, inner.top);
+                        outer.left, outer.top, inner.right, inner.top, layerStack);
             }
             if (outer.left < inner.left) {
                 mBlackSurfaces[1] = new BlackSurface(session, layer,
-                        outer.left, inner.top, inner.left, outer.bottom);
+                        outer.left, inner.top, inner.left, outer.bottom, layerStack);
             }
             if (outer.bottom > inner.bottom) {
                 mBlackSurfaces[2] = new BlackSurface(session, layer,
-                        inner.left, inner.bottom, outer.right, outer.bottom);
+                        inner.left, inner.bottom, outer.right, outer.bottom, layerStack);
             }
             if (outer.right > inner.right) {
                 mBlackSurfaces[3] = new BlackSurface(session, layer,
-                        inner.right, outer.top, outer.right, inner.bottom);
+                        inner.right, outer.top, outer.right, inner.bottom, layerStack);
             }
             success = true;
         } finally {
diff --git a/services/java/com/android/server/wm/DimAnimator.java b/services/java/com/android/server/wm/DimAnimator.java
index e8f56c8..5874202 100644
--- a/services/java/com/android/server/wm/DimAnimator.java
+++ b/services/java/com/android/server/wm/DimAnimator.java
@@ -30,36 +30,37 @@
  * all state used for dim animation.
  */
 class DimAnimator {
+    static final String TAG = "DimAnimator";
+
     Surface mDimSurface;
     boolean mDimShown = false;
     float mDimCurrentAlpha;
     float mDimTargetAlpha;
     float mDimDeltaPerMs;
     long mLastDimAnimTime;
-    
+
     int mLastDimWidth, mLastDimHeight;
 
-    DimAnimator (SurfaceSession session) {
-        if (mDimSurface == null) {
-            try {
-                if (WindowManagerService.DEBUG_SURFACE_TRACE) {
-                    mDimSurface = new WindowStateAnimator.SurfaceTrace(session, 0,
-                        "DimAnimator",
-                        -1, 16, 16, PixelFormat.OPAQUE,
-                        Surface.FX_SURFACE_DIM);
-                } else {
-                    mDimSurface = new Surface(session, 0,
-                        "DimAnimator",
-                        -1, 16, 16, PixelFormat.OPAQUE,
-                        Surface.FX_SURFACE_DIM);
-                }
-                if (WindowManagerService.SHOW_TRANSACTIONS ||
-                        WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
-                                "  DIM " + mDimSurface + ": CREATE");
-                mDimSurface.setAlpha(0.0f);
-            } catch (Exception e) {
-                Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
+    DimAnimator (SurfaceSession session, final int layerStack) {
+        try {
+            if (WindowManagerService.DEBUG_SURFACE_TRACE) {
+                mDimSurface = new WindowStateAnimator.SurfaceTrace(session,
+                    "DimAnimator",
+                    16, 16, PixelFormat.OPAQUE,
+                    Surface.FX_SURFACE_DIM | Surface.HIDDEN);
+            } else {
+                mDimSurface = new Surface(session, "DimAnimator",
+                    16, 16, PixelFormat.OPAQUE,
+                    Surface.FX_SURFACE_DIM | Surface.HIDDEN);
             }
+            if (WindowManagerService.SHOW_TRANSACTIONS ||
+                    WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
+                            "  DIM " + mDimSurface + ": CREATE");
+            mDimSurface.setLayerStack(layerStack);
+            mDimSurface.setAlpha(0.0f);
+            mDimSurface.show();
+        } catch (Exception e) {
+            Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
         }
     }
 
@@ -68,6 +69,11 @@
      * {@link #updateSurface} after all windows are examined.
      */
     void updateParameters(final Resources res, final Parameters params, final long currentTime) {
+        if (mDimSurface == null) {
+            Slog.e(TAG, "updateParameters: no Surface");
+            return;
+        }
+
         // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose a
         // corner.
         final int dw = (int) (params.mDimWidth * 1.5);
@@ -132,6 +138,11 @@
      * false when the animation is finished and the dim surface is hidden.
      */
     boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
+        if (mDimSurface == null) {
+            Slog.e(TAG, "updateSurface: no Surface");
+            return false;
+        }
+
         if (!dimming) {
             if (mDimTargetAlpha != 0) {
                 mLastDimAnimTime = currentTime;
@@ -186,6 +197,13 @@
         return animating;
     }
 
+    public void kill() {
+        if (mDimSurface != null) {
+            mDimSurface.destroy();
+            mDimSurface = null;
+        }
+    }
+
     public void printTo(String prefix, PrintWriter pw) {
         pw.print(prefix);
         pw.print("mDimSurface="); pw.print(mDimSurface);
@@ -211,5 +229,20 @@
             mDimHeight = dimHeight;
             mDimTarget = dimTarget;
         }
+
+        Parameters(Parameters o) {
+            mDimWinAnimator = o.mDimWinAnimator;
+            mDimWidth = o.mDimWidth;
+            mDimHeight = o.mDimHeight;
+            mDimTarget = o.mDimTarget;
+        }
+
+        public void printTo(String prefix, PrintWriter pw) {
+            pw.print(prefix);
+            pw.print("mDimWinAnimator="); pw.print(mDimWinAnimator.mWin.mAttrs.getTitle());
+                    pw.print(" "); pw.print(mDimWidth); pw.print(" x ");
+                    pw.print(mDimHeight);
+            pw.print(" mDimTarget="); pw.println(mDimTarget);
+        }
     }
-}
\ No newline at end of file
+}
diff --git a/services/java/com/android/server/wm/DimSurface.java b/services/java/com/android/server/wm/DimSurface.java
index 9fca4183..4225868 100644
--- a/services/java/com/android/server/wm/DimSurface.java
+++ b/services/java/com/android/server/wm/DimSurface.java
@@ -24,33 +24,34 @@
 import java.io.PrintWriter;
 
 class DimSurface {
+    static final String TAG = "DimSurface";
+
     Surface mDimSurface;
     boolean mDimShown = false;
     int mDimColor = 0;
     int mLayer = -1;
     int mLastDimWidth, mLastDimHeight;
 
-    DimSurface(SurfaceSession session) {
-        if (mDimSurface == null) {
-            try {
-                if (WindowManagerService.DEBUG_SURFACE_TRACE) {
-                    mDimSurface = new WindowStateAnimator.SurfaceTrace(session, 0,
-                        "DimSurface",
-                        -1, 16, 16, PixelFormat.OPAQUE,
-                        Surface.FX_SURFACE_DIM);
-                } else {
-                    mDimSurface = new Surface(session, 0,
-                        "DimSurface",
-                        -1, 16, 16, PixelFormat.OPAQUE,
-                        Surface.FX_SURFACE_DIM);
-                }
-                if (WindowManagerService.SHOW_TRANSACTIONS ||
-                        WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
-                                "  DIM " + mDimSurface + ": CREATE");
-                mDimSurface.setAlpha(0.0f);
-            } catch (Exception e) {
-                Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
+    DimSurface(SurfaceSession session, final int layerStack) {
+        try {
+            if (WindowManagerService.DEBUG_SURFACE_TRACE) {
+                mDimSurface = new WindowStateAnimator.SurfaceTrace(session,
+                    "DimSurface",
+                    16, 16, PixelFormat.OPAQUE,
+                    Surface.FX_SURFACE_DIM | Surface.HIDDEN);
+            } else {
+                mDimSurface = new Surface(session, "DimSurface",
+                    16, 16, PixelFormat.OPAQUE,
+                    Surface.FX_SURFACE_DIM | Surface.HIDDEN);
             }
+            if (WindowManagerService.SHOW_TRANSACTIONS ||
+                    WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
+                            "  DIM " + mDimSurface + ": CREATE");
+            mDimSurface.setLayerStack(layerStack);
+            mDimSurface.setAlpha(0.0f);
+            mDimSurface.show();
+        } catch (Exception e) {
+            Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
         }
     }
 
@@ -58,6 +59,11 @@
      * Show the dim surface.
      */
     void show(int dw, int dh, int layer, int color) {
+        if (mDimSurface == null) {
+            Slog.e(TAG, "show: no Surface");
+            return;
+        }
+
         if (!mDimShown) {
             if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
                     dw + "x" + dh + " layer=" + layer + ")");
@@ -87,6 +93,11 @@
     }
 
     void hide() {
+        if (mDimSurface == null) {
+            Slog.e(TAG, "hide: no Surface");
+            return;
+        }
+
         if (mDimShown) {
             mDimShown = false;
             try {
@@ -98,6 +109,13 @@
         }
     }
 
+    void kill() {
+        if (mDimSurface != null) {
+            mDimSurface.destroy();
+            mDimSurface = null;
+        }
+    }
+
     public void printTo(String prefix, PrintWriter pw) {
         pw.print(prefix); pw.print("mDimSurface="); pw.println(mDimSurface);
         pw.print(prefix); pw.print("mDimShown="); pw.print(mDimShown);
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
new file mode 100644
index 0000000..68cdbfc
--- /dev/null
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -0,0 +1,136 @@
+/*
+ * 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.wm;
+
+import android.os.RemoteCallbackList;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.IDisplayContentChangeListener;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+class DisplayContentList extends ArrayList<DisplayContent> {
+}
+
+/**
+ * Utility class for keeping track of the WindowStates and other pertinent contents of a
+ * particular Display.
+ *
+ * IMPORTANT: No method from this class should ever be used without holding
+ * WindowManagerService.mWindowMap.
+ */
+class DisplayContent {
+
+    /** Unique identifier of this stack. */
+    private final int mDisplayId;
+
+    /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element
+     * from mDisplayWindows; */
+    private WindowList mWindows = new WindowList();
+
+    // Specification for magnifying the display content.
+    MagnificationSpec mMagnificationSpec;
+
+    // Callback for observing content changes on a display.
+    RemoteCallbackList<IDisplayContentChangeListener> mDisplayContentChangeListeners;
+
+    // This protects the following display size properties, so that
+    // getDisplaySize() doesn't need to acquire the global lock.  This is
+    // needed because the window manager sometimes needs to use ActivityThread
+    // while it has its global state locked (for example to load animation
+    // resources), but the ActivityThread also needs get the current display
+    // size sometimes when it has its package lock held.
+    //
+    // These will only be modified with both mWindowMap and mDisplaySizeLock
+    // held (in that order) so the window manager doesn't need to acquire this
+    // lock when needing these values in its normal operation.
+    final Object mDisplaySizeLock = new Object();
+    int mInitialDisplayWidth = 0;
+    int mInitialDisplayHeight = 0;
+    int mInitialDisplayDensity = 0;
+    int mBaseDisplayWidth = 0;
+    int mBaseDisplayHeight = 0;
+    int mBaseDisplayDensity = 0;
+    private final DisplayInfo mDisplayInfo = new DisplayInfo();
+    private final Display mDisplay;
+
+    // Accessed directly by all users.
+    boolean layoutNeeded;
+    int pendingLayoutChanges;
+    final boolean isDefaultDisplay;
+
+    /**
+     * @param display May not be null.
+     */
+    DisplayContent(Display display) {
+        mDisplay = display;
+        mDisplayId = display.getDisplayId();
+        display.getDisplayInfo(mDisplayInfo);
+        isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
+    }
+
+    int getDisplayId() {
+        return mDisplayId;
+    }
+
+    WindowList getWindowList() {
+        return mWindows;
+    }
+
+    Display getDisplay() {
+        return mDisplay;
+    }
+
+    DisplayInfo getDisplayInfo() {
+        return mDisplayInfo;
+    }
+
+    public void updateDisplayInfo() {
+        mDisplay.getDisplayInfo(mDisplayInfo);
+    }
+
+    public void dump(String prefix, PrintWriter pw) {
+        pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
+        final String subPrefix = "  " + prefix;
+        pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
+            pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
+            pw.print("dpi");
+            if (mInitialDisplayWidth != mBaseDisplayWidth
+                    || mInitialDisplayHeight != mBaseDisplayHeight
+                    || mInitialDisplayDensity != mBaseDisplayDensity) {
+                pw.print(" base=");
+                pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
+                pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
+            }
+            pw.print(" cur=");
+            pw.print(mDisplayInfo.logicalWidth);
+            pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
+            pw.print(" app=");
+            pw.print(mDisplayInfo.appWidth);
+            pw.print("x"); pw.print(mDisplayInfo.appHeight);
+            pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
+            pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
+            pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
+            pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
+        pw.print(subPrefix); pw.print("layoutNeeded="); pw.print(layoutNeeded);
+        if (mMagnificationSpec != null) {
+            pw.print(" mMagnificationSpec="); pw.print(mMagnificationSpec);
+        }
+        pw.println();
+    }
+}
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index b2cf3e0c..72fc180 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -23,12 +23,14 @@
 
 import android.content.ClipData;
 import android.content.ClipDescription;
+import android.graphics.Point;
 import android.graphics.Region;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
 import android.util.Slog;
+import android.view.Display;
 import android.view.DragEvent;
 import android.view.InputChannel;
 import android.view.Surface;
@@ -58,6 +60,7 @@
     WindowState mTargetWindow;
     ArrayList<WindowState> mNotifiedWindows;
     boolean mDragInProgress;
+    Display mDisplay;
 
     private final Region mTmpRegion = new Region();
 
@@ -84,7 +87,11 @@
         mNotifiedWindows = null;
     }
 
-    void register() {
+    /**
+     * @param display The Display that the window being dragged is on.
+     */
+    void register(Display display) {
+        mDisplay = display;
         if (WindowManagerService.DEBUG_DRAG) Slog.d(WindowManagerService.TAG, "registering drag input channel");
         if (mClientChannel != null) {
             Slog.e(WindowManagerService.TAG, "Duplicate register of drag input channel");
@@ -101,7 +108,8 @@
             mDragApplicationHandle.dispatchingTimeoutNanos =
                     WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
 
-            mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null);
+            mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
+                    mDisplay.getDisplayId());
             mDragWindowHandle.name = "drag";
             mDragWindowHandle.inputChannel = mServerChannel;
             mDragWindowHandle.layer = getDragLayerLw();
@@ -125,8 +133,10 @@
             // The drag window covers the entire display
             mDragWindowHandle.frameLeft = 0;
             mDragWindowHandle.frameTop = 0;
-            mDragWindowHandle.frameRight = mService.mCurDisplayWidth;
-            mDragWindowHandle.frameBottom = mService.mCurDisplayHeight;
+            Point p = new Point();
+            mDisplay.getRealSize(p);
+            mDragWindowHandle.frameRight = p.x;
+            mDragWindowHandle.frameBottom = p.y;
 
             // Pause rotations before a drag.
             if (WindowManagerService.DEBUG_ORIENTATION) {
@@ -179,9 +189,12 @@
             Slog.d(WindowManagerService.TAG, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")");
         }
 
-        final int N = mService.mWindows.size();
-        for (int i = 0; i < N; i++) {
-            sendDragStartedLw(mService.mWindows.get(i), touchX, touchY, mDataDescription);
+        final WindowList windows = mService.getWindowListLocked(mDisplay);
+        if (windows != null) {
+            final int N = windows.size();
+            for (int i = 0; i < N; i++) {
+                sendDragStartedLw(windows.get(i), touchX, touchY, mDataDescription);
+            }
         }
     }
 
@@ -380,7 +393,11 @@
         WindowState touchedWin = null;
         final int x = (int) xf;
         final int y = (int) yf;
-        final ArrayList<WindowState> windows = mService.mWindows;
+
+        final WindowList windows = mService.getWindowListLocked(mDisplay);
+        if (windows == null) {
+            return null;
+        }
         final int N = windows.size();
         for (int i = N - 1; i >= 0; i--) {
             WindowState child = windows.get(i);
diff --git a/services/java/com/android/server/wm/FakeWindowImpl.java b/services/java/com/android/server/wm/FakeWindowImpl.java
index 2527f46d8..5ec72cc 100644
--- a/services/java/com/android/server/wm/FakeWindowImpl.java
+++ b/services/java/com/android/server/wm/FakeWindowImpl.java
@@ -22,6 +22,7 @@
 import android.os.Looper;
 import android.os.Process;
 import android.util.Slog;
+import android.view.Display;
 import android.view.InputChannel;
 import android.view.InputEventReceiver;
 import android.view.InputQueue;
@@ -56,7 +57,7 @@
         mApplicationHandle.dispatchingTimeoutNanos =
                 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
 
-        mWindowHandle = new InputWindowHandle(mApplicationHandle, null);
+        mWindowHandle = new InputWindowHandle(mApplicationHandle, null, Display.DEFAULT_DISPLAY);
         mWindowHandle.name = name;
         mWindowHandle.inputChannel = mServerChannel;
         mWindowLayer = getLayerLw(windowType);
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index 285d230..d966001 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -19,11 +19,14 @@
 import com.android.server.input.InputManagerService;
 import com.android.server.input.InputApplicationHandle;
 import com.android.server.input.InputWindowHandle;
+import com.android.server.wm.WindowManagerService.AllWindowsIterator;
 
+import android.app.ActivityManagerNative;
 import android.graphics.Rect;
 import android.os.RemoteException;
 import android.util.Log;
 import android.util.Slog;
+import android.view.Display;
 import android.view.InputChannel;
 import android.view.KeyEvent;
 import android.view.WindowManager;
@@ -31,7 +34,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 
-final class InputMonitor implements InputManagerService.Callbacks {
+final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
     private final WindowManagerService mService;
     
     // Current window with input focus for keys and other non-touch events.  May be null.
@@ -87,8 +90,9 @@
     public long notifyANR(InputApplicationHandle inputApplicationHandle,
             InputWindowHandle inputWindowHandle) {
         AppWindowToken appWindowToken = null;
+        WindowState windowState = null;
+        boolean aboveSystem = false;
         synchronized (mService.mWindowMap) {
-            WindowState windowState = null;
             if (inputWindowHandle != null) {
                 windowState = (WindowState) inputWindowHandle.windowState;
                 if (windowState != null) {
@@ -102,6 +106,12 @@
             if (windowState != null) {
                 Slog.i(WindowManagerService.TAG, "Input event dispatching timed out "
                         + "sending to " + windowState.mAttrs.getTitle());
+                // Figure out whether this window is layered above system windows.
+                // We need to do this here to help the activity manager know how to
+                // layer its ANR dialog.
+                int systemAlertLayer = mService.mPolicy.windowTypeToLayerLw(
+                        WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+                aboveSystem = windowState.mBaseLayer > systemAlertLayer;
             } else if (appWindowToken != null) {
                 Slog.i(WindowManagerService.TAG, "Input event dispatching timed out "
                         + "sending to application " + appWindowToken.stringName);
@@ -124,11 +134,24 @@
                 }
             } catch (RemoteException ex) {
             }
+        } else if (windowState != null) {
+            try {
+                // Notify the activity manager about the timeout and let it decide whether
+                // to abort dispatching or keep waiting.
+                long timeout = ActivityManagerNative.getDefault().inputDispatchingTimedOut(
+                        windowState.mSession.mPid, aboveSystem);
+                if (timeout >= 0) {
+                    // The activity manager declined to abort dispatching.
+                    // Wait a bit longer and timeout again later.
+                    return timeout;
+                }
+            } catch (RemoteException ex) {
+            }
         }
         return 0; // abort dispatching
     }
 
-    private void addInputWindowHandleLw(InputWindowHandle windowHandle) {
+    private void addInputWindowHandleLw(final InputWindowHandle windowHandle) {
         if (mInputWindowHandles == null) {
             mInputWindowHandles = new InputWindowHandle[16];
         }
@@ -139,6 +162,44 @@
         mInputWindowHandles[mInputWindowHandleCount++] = windowHandle;
     }
 
+    private void addInputWindowHandleLw(final InputWindowHandle inputWindowHandle,
+            final WindowState child, final int flags, final int type,
+            final boolean isVisible, final boolean hasFocus, final boolean hasWallpaper) {
+        // Add a window to our list of input windows.
+        inputWindowHandle.name = child.toString();
+        inputWindowHandle.layoutParamsFlags = flags;
+        inputWindowHandle.layoutParamsType = type;
+        inputWindowHandle.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
+        inputWindowHandle.visible = isVisible;
+        inputWindowHandle.canReceiveKeys = child.canReceiveKeys();
+        inputWindowHandle.hasFocus = hasFocus;
+        inputWindowHandle.hasWallpaper = hasWallpaper;
+        inputWindowHandle.paused = child.mAppToken != null ? child.mAppToken.paused : false;
+        inputWindowHandle.layer = child.mLayer;
+        inputWindowHandle.ownerPid = child.mSession.mPid;
+        inputWindowHandle.ownerUid = child.mSession.mUid;
+        inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures;
+
+        final Rect frame = child.mFrame;
+        inputWindowHandle.frameLeft = frame.left;
+        inputWindowHandle.frameTop = frame.top;
+        inputWindowHandle.frameRight = frame.right;
+        inputWindowHandle.frameBottom = frame.bottom;
+
+        if (child.mGlobalScale != 1) {
+            // If we are scaling the window, input coordinates need
+            // to be inversely scaled to map from what is on screen
+            // to what is actually being touched in the UI.
+            inputWindowHandle.scaleFactor = 1.0f/child.mGlobalScale;
+        } else {
+            inputWindowHandle.scaleFactor = 1;
+        }
+
+        child.getTouchableRegion(inputWindowHandle.touchableRegion);
+
+        addInputWindowHandleLw(inputWindowHandle);
+    }
+
     private void clearInputWindowHandlesLw() {
         while (mInputWindowHandleCount != 0) {
             mInputWindowHandles[--mInputWindowHandleCount] = null;
@@ -163,7 +224,9 @@
         // As an optimization, we could try to prune the list of windows but this turns
         // out to be difficult because only the native code knows for sure which window
         // currently has touch focus.
-        final ArrayList<WindowState> windows = mService.mWindows;
+        final WindowStateAnimator universeBackground = mService.mAnimator.mUniverseBackground;
+        final int aboveUniverseLayer = mService.mAnimator.mAboveUniverseLayer;
+        boolean addedUniverse = false;
 
         // If there's a drag in flight, provide a pseudowindow to catch drag input
         final boolean inDrag = (mService.mDragState != null);
@@ -185,9 +248,11 @@
             addInputWindowHandleLw(mService.mFakeWindows.get(i).mWindowHandle);
         }
 
-        final int N = windows.size();
-        for (int i = N - 1; i >= 0; i--) {
-            final WindowState child = windows.get(i);
+        // Add all windows on the default display.
+        final AllWindowsIterator iterator = mService.new AllWindowsIterator(
+                WindowManagerService.REVERSE_ITERATOR);
+        while (iterator.hasNext()) {
+            final WindowState child = iterator.next();
             final InputChannel inputChannel = child.mInputChannel;
             final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
             if (inputChannel == null || inputWindowHandle == null || child.mRemoved) {
@@ -202,46 +267,28 @@
             final boolean isVisible = child.isVisibleLw();
             final boolean hasWallpaper = (child == mService.mWallpaperTarget)
                     && (type != WindowManager.LayoutParams.TYPE_KEYGUARD);
+            final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY);
 
             // If there's a drag in progress and 'child' is a potential drop target,
             // make sure it's been told about the drag
-            if (inDrag && isVisible) {
+            if (inDrag && isVisible && onDefaultDisplay) {
                 mService.mDragState.sendDragStartedIfNeededLw(child);
             }
 
-            // Add a window to our list of input windows.
-            inputWindowHandle.name = child.toString();
-            inputWindowHandle.layoutParamsFlags = flags;
-            inputWindowHandle.layoutParamsType = type;
-            inputWindowHandle.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
-            inputWindowHandle.visible = isVisible;
-            inputWindowHandle.canReceiveKeys = child.canReceiveKeys();
-            inputWindowHandle.hasFocus = hasFocus;
-            inputWindowHandle.hasWallpaper = hasWallpaper;
-            inputWindowHandle.paused = child.mAppToken != null ? child.mAppToken.paused : false;
-            inputWindowHandle.layer = child.mLayer;
-            inputWindowHandle.ownerPid = child.mSession.mPid;
-            inputWindowHandle.ownerUid = child.mSession.mUid;
-            inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures;
-
-            final Rect frame = child.mFrame;
-            inputWindowHandle.frameLeft = frame.left;
-            inputWindowHandle.frameTop = frame.top;
-            inputWindowHandle.frameRight = frame.right;
-            inputWindowHandle.frameBottom = frame.bottom;
-
-            if (child.mGlobalScale != 1) {
-                // If we are scaling the window, input coordinates need
-                // to be inversely scaled to map from what is on screen
-                // to what is actually being touched in the UI.
-                inputWindowHandle.scaleFactor = 1.0f/child.mGlobalScale;
-            } else {
-                inputWindowHandle.scaleFactor = 1;
+            if (universeBackground != null && !addedUniverse
+                    && child.mBaseLayer < aboveUniverseLayer && onDefaultDisplay) {
+                final WindowState u = universeBackground.mWin;
+                if (u.mInputChannel != null && u.mInputWindowHandle != null) {
+                    addInputWindowHandleLw(u.mInputWindowHandle, u, u.mAttrs.flags,
+                            u.mAttrs.type, true, u == mInputFocus, false);
+                }
+                addedUniverse = true;
             }
 
-            child.getTouchableRegion(inputWindowHandle.touchableRegion);
-
-            addInputWindowHandleLw(inputWindowHandle);
+            if (child.mWinAnimator != universeBackground) {
+                addInputWindowHandleLw(inputWindowHandle, child, flags, type,
+                        isVisible, hasFocus, hasWallpaper);
+            }
         }
 
         // Send windows to native code.
diff --git a/services/java/com/android/server/wm/KeyguardDisableHandler.java b/services/java/com/android/server/wm/KeyguardDisableHandler.java
new file mode 100644
index 0000000..859df51
--- /dev/null
+++ b/services/java/com/android/server/wm/KeyguardDisableHandler.java
@@ -0,0 +1,115 @@
+/*
+ * 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.wm;
+
+import android.app.ActivityManagerNative;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.TokenWatcher;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.Pair;
+import android.view.WindowManagerPolicy;
+
+public class KeyguardDisableHandler extends Handler {
+    private static final String TAG = "KeyguardDisableHandler";
+
+    private static final int ALLOW_DISABLE_YES = 1;
+    private static final int ALLOW_DISABLE_NO = 0;
+    private static final int ALLOW_DISABLE_UNKNOWN = -1; // check with DevicePolicyManager
+    private int mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN; // sync'd by mKeyguardTokenWatcher
+
+    // Message.what constants
+    static final int KEYGUARD_DISABLE = 1;
+    static final int KEYGUARD_REENABLE = 2;
+    static final int KEYGUARD_POLICY_CHANGED = 3;
+
+    final Context mContext;
+    final WindowManagerPolicy mPolicy;
+    KeyguardTokenWatcher mKeyguardTokenWatcher;
+
+    public KeyguardDisableHandler(final Context context, final WindowManagerPolicy policy) {
+        mContext = context;
+        mPolicy = policy;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void handleMessage(Message msg) {
+        if (mKeyguardTokenWatcher == null) {
+            mKeyguardTokenWatcher = new KeyguardTokenWatcher(this);
+        }
+
+        switch (msg.what) {
+            case KEYGUARD_DISABLE:
+                final Pair<IBinder, String> pair = (Pair<IBinder, String>)msg.obj;
+                mKeyguardTokenWatcher.acquire(pair.first, pair.second);
+                break;
+
+            case KEYGUARD_REENABLE:
+                mKeyguardTokenWatcher.release((IBinder)msg.obj);
+                break;
+
+            case KEYGUARD_POLICY_CHANGED:
+                mPolicy.enableKeyguard(true);
+                // lazily evaluate this next time we're asked to disable keyguard
+                mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN;
+                break;
+        }
+    }
+
+    class KeyguardTokenWatcher extends TokenWatcher {
+
+        public KeyguardTokenWatcher(final Handler handler) {
+            super(handler, TAG);
+        }
+
+        @Override
+        public void acquired() {
+            // We fail safe and prevent disabling keyguard in the unlikely event this gets
+            // called before DevicePolicyManagerService has started.
+            if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) {
+                DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
+                        Context.DEVICE_POLICY_SERVICE);
+                if (dpm != null) {
+                    try {
+                        mAllowDisableKeyguard = dpm.getPasswordQuality(null, 
+                                ActivityManagerNative.getDefault().getCurrentUser().id)
+                                == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
+                                        ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
+                    } catch (RemoteException re) {
+                        // Nothing much we can do
+                    }
+                }
+            }
+            if (mAllowDisableKeyguard == ALLOW_DISABLE_YES) {
+                mPolicy.enableKeyguard(false);
+            } else {
+                Log.v(TAG, "Not disabling keyguard since device policy is enforced");
+            }
+        }
+
+        @Override
+        public void released() {
+            mPolicy.enableKeyguard(true);
+        }
+    }
+}
diff --git a/services/java/com/android/server/wm/MagnificationSpec.java b/services/java/com/android/server/wm/MagnificationSpec.java
new file mode 100644
index 0000000..31aae66
--- /dev/null
+++ b/services/java/com/android/server/wm/MagnificationSpec.java
@@ -0,0 +1,46 @@
+/*
+ * 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.wm;
+
+public class MagnificationSpec {
+    public float mScale = 1.0f;
+    public float mOffsetX;
+    public float mOffsetY;
+
+    public void initialize(float scale, float offsetX, float offsetY) {
+        mScale = scale;
+        mOffsetX = offsetX;
+        mOffsetY = offsetY;
+    }
+
+    public boolean isNop() {
+        return mScale == 1.0f && mOffsetX == 0 && mOffsetY == 0;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("<scale:");
+        builder.append(mScale);
+        builder.append(",offsetX:");
+        builder.append(mOffsetX);
+        builder.append(",offsetY:");
+        builder.append(mOffsetY);
+        builder.append(">");
+        return builder.toString();
+    }
+}
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 938db9e..8d2e2e8 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -25,6 +25,7 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.util.Slog;
+import android.view.Display;
 import android.view.Surface;
 import android.view.SurfaceSession;
 import android.view.animation.Animation;
@@ -41,11 +42,13 @@
     static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200;
 
     final Context mContext;
+    final Display mDisplay;
     Surface mSurface;
     BlackFrame mCustomBlackFrame;
     BlackFrame mExitingBlackFrame;
     BlackFrame mEnteringBlackFrame;
     int mWidth, mHeight;
+    int mExitAnimId, mEnterAnimId;
 
     int mOriginalRotation;
     int mOriginalWidth, mOriginalHeight;
@@ -185,9 +188,13 @@
                 pw.println();
     }
 
-    public ScreenRotationAnimation(Context context, SurfaceSession session,
-            boolean inTransaction, int originalWidth, int originalHeight, int originalRotation) {
+    public ScreenRotationAnimation(Context context, Display display, SurfaceSession session,
+            boolean inTransaction, int originalWidth, int originalHeight, int originalRotation,
+            int exitAnim, int enterAnim) {
         mContext = context;
+        mDisplay = display;
+        mExitAnimId = exitAnim;
+        mEnterAnimId = enterAnim;
 
         // Screenshot does NOT include rotation!
         if (originalRotation == Surface.ROTATION_90
@@ -212,17 +219,20 @@
         try {
             try {
                 if (WindowManagerService.DEBUG_SURFACE_TRACE) {
-                    mSurface = new SurfaceTrace(session, 0, "FreezeSurface", -1, mWidth, mHeight,
-                        PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
+                    mSurface = new SurfaceTrace(session, "FreezeSurface",
+                            mWidth, mHeight,
+                            PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
                 } else {
-                    mSurface = new Surface(session, 0, "FreezeSurface", -1, mWidth, mHeight,
-                        PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
+                    mSurface = new Surface(session, "FreezeSurface",
+                            mWidth, mHeight,
+                            PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
                 }
                 if (!mSurface.isValid()) {
                     // Screenshot failed, punt.
                     mSurface = null;
                     return;
                 }
+                mSurface.setLayerStack(mDisplay.getLayerStack());
                 mSurface.setLayer(FREEZE_LAYER + 1);
                 mSurface.setAlpha(0);
                 mSurface.show();
@@ -234,7 +244,7 @@
                     WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
                             "  FREEZE " + mSurface + ": CREATE");
 
-            setRotation(originalRotation);
+            setRotationInTransaction(originalRotation);
         } finally {
             if (!inTransaction) {
                 Surface.closeTransaction();
@@ -254,7 +264,7 @@
         return delta;
     }
 
-    void setSnapshotTransform(Matrix matrix, float alpha) {
+    private void setSnapshotTransformInTransaction(Matrix matrix, float alpha) {
         if (mSurface != null) {
             matrix.getValues(mTmpFloats);
             mSurface.setPosition(mTmpFloats[Matrix.MTRANS_X],
@@ -297,7 +307,7 @@
     }
 
     // Must be called while in a transaction.
-    private void setRotation(int rotation) {
+    private void setRotationInTransaction(int rotation) {
         mCurRotation = rotation;
 
         // Compute the transformation matrix that must be applied
@@ -307,13 +317,13 @@
         createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
 
         if (DEBUG_STATE) Slog.v(TAG, "**** ROTATION: " + delta);
-        setSnapshotTransform(mSnapshotInitialMatrix, 1.0f);
+        setSnapshotTransformInTransaction(mSnapshotInitialMatrix, 1.0f);
     }
 
     // Must be called while in a transaction.
-    public boolean setRotation(int rotation, SurfaceSession session,
+    public boolean setRotationInTransaction(int rotation, SurfaceSession session,
             long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight) {
-        setRotation(rotation);
+        setRotationInTransaction(rotation);
         if (TWO_PHASE_ANIMATION) {
             return startAnimation(session, maxAnimationDuration, animationScale,
                     finalWidth, finalHeight, false);
@@ -369,58 +379,68 @@
                 + finalWidth + " finalHeight=" + finalHeight
                 + " origWidth=" + mOriginalWidth + " origHeight=" + mOriginalHeight);
 
-        switch (delta) {
-            case Surface.ROTATION_0:
-                mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
-                        com.android.internal.R.anim.screen_rotate_0_exit);
-                mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
-                        com.android.internal.R.anim.screen_rotate_0_enter);
-                if (USE_CUSTOM_BLACK_FRAME) {
-                    mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
-                            com.android.internal.R.anim.screen_rotate_0_frame);
-                }
-                break;
-            case Surface.ROTATION_90:
-                mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
-                        com.android.internal.R.anim.screen_rotate_plus_90_exit);
-                mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
-                        com.android.internal.R.anim.screen_rotate_plus_90_enter);
-                if (USE_CUSTOM_BLACK_FRAME) {
-                    mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
-                            com.android.internal.R.anim.screen_rotate_plus_90_frame);
-                }
-                break;
-            case Surface.ROTATION_180:
-                mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
-                        com.android.internal.R.anim.screen_rotate_180_exit);
-                mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
-                        com.android.internal.R.anim.screen_rotate_180_enter);
-                mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
-                        com.android.internal.R.anim.screen_rotate_180_frame);
-                break;
-            case Surface.ROTATION_270:
-                mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
-                        com.android.internal.R.anim.screen_rotate_minus_90_exit);
-                mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
-                        com.android.internal.R.anim.screen_rotate_minus_90_enter);
-                if (USE_CUSTOM_BLACK_FRAME) {
-                    mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
-                            com.android.internal.R.anim.screen_rotate_minus_90_frame);
-                }
-                break;
+        final boolean customAnim;
+        if (mExitAnimId != 0 && mEnterAnimId != 0) {
+            customAnim = true;
+            mRotateExitAnimation = AnimationUtils.loadAnimation(mContext, mExitAnimId);
+            mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext, mEnterAnimId);
+        } else {
+            customAnim = false;
+            switch (delta) {
+                case Surface.ROTATION_0:
+                    mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
+                            com.android.internal.R.anim.screen_rotate_0_exit);
+                    mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
+                            com.android.internal.R.anim.screen_rotate_0_enter);
+                    if (USE_CUSTOM_BLACK_FRAME) {
+                        mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
+                                com.android.internal.R.anim.screen_rotate_0_frame);
+                    }
+                    break;
+                case Surface.ROTATION_90:
+                    mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
+                            com.android.internal.R.anim.screen_rotate_plus_90_exit);
+                    mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
+                            com.android.internal.R.anim.screen_rotate_plus_90_enter);
+                    if (USE_CUSTOM_BLACK_FRAME) {
+                        mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
+                                com.android.internal.R.anim.screen_rotate_plus_90_frame);
+                    }
+                    break;
+                case Surface.ROTATION_180:
+                    mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
+                            com.android.internal.R.anim.screen_rotate_180_exit);
+                    mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
+                            com.android.internal.R.anim.screen_rotate_180_enter);
+                    if (USE_CUSTOM_BLACK_FRAME) {
+                        mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
+                                com.android.internal.R.anim.screen_rotate_180_frame);
+                    }
+                    break;
+                case Surface.ROTATION_270:
+                    mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
+                            com.android.internal.R.anim.screen_rotate_minus_90_exit);
+                    mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
+                            com.android.internal.R.anim.screen_rotate_minus_90_enter);
+                    if (USE_CUSTOM_BLACK_FRAME) {
+                        mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
+                                com.android.internal.R.anim.screen_rotate_minus_90_frame);
+                    }
+                    break;
+            }
         }
 
-        // Compute partial steps between original and final sizes.  These
-        // are used for the dimensions of the exiting and entering elements,
-        // so they are never stretched too significantly.
-        final int halfWidth = (finalWidth + mOriginalWidth) / 2;
-        final int halfHeight = (finalHeight + mOriginalHeight) / 2;
-
         // Initialize the animations.  This is a hack, redefining what "parent"
         // means to allow supplying the last and next size.  In this definition
         // "%p" is the original (let's call it "previous") size, and "%" is the
         // screen's current/new size.
         if (TWO_PHASE_ANIMATION && firstStart) {
+            // Compute partial steps between original and final sizes.  These
+            // are used for the dimensions of the exiting and entering elements,
+            // so they are never stretched too significantly.
+            final int halfWidth = (finalWidth + mOriginalWidth) / 2;
+            final int halfHeight = (finalHeight + mOriginalHeight) / 2;
+
             if (DEBUG_STATE) Slog.v(TAG, "Initializing start and finish animations");
             mStartEnterAnimation.initialize(finalWidth, finalHeight,
                     halfWidth, halfHeight);
@@ -472,6 +492,7 @@
             mRotateFrameAnimation.scaleCurrentDuration(animationScale);
         }
 
+        final int layerStack = mDisplay.getLayerStack();
         if (USE_CUSTOM_BLACK_FRAME && mCustomBlackFrame == null) {
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
                     WindowManagerService.TAG,
@@ -490,7 +511,8 @@
                 Rect outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1,
                         mOriginalWidth*2, mOriginalHeight*2);
                 Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
-                mCustomBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 3);
+                mCustomBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 3,
+                        layerStack);
                 mCustomBlackFrame.setMatrix(mFrameInitialMatrix);
             } catch (Surface.OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
@@ -502,25 +524,25 @@
             }
         }
 
-        if (mExitingBlackFrame == null) {
+        if (!customAnim && mExitingBlackFrame == null) {
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
                     WindowManagerService.TAG,
                     ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
             Surface.openTransaction();
-
-            // Compute the transformation matrix that must be applied
-            // the the black frame to make it stay in the initial position
-            // before the new screen rotation.  This is different than the
-            // snapshot transformation because the snapshot is always based
-            // of the native orientation of the screen, not the orientation
-            // we were last in.
-            createRotationMatrix(delta, mOriginalWidth, mOriginalHeight, mFrameInitialMatrix);
-
             try {
+                // Compute the transformation matrix that must be applied
+                // the the black frame to make it stay in the initial position
+                // before the new screen rotation.  This is different than the
+                // snapshot transformation because the snapshot is always based
+                // of the native orientation of the screen, not the orientation
+                // we were last in.
+                createRotationMatrix(delta, mOriginalWidth, mOriginalHeight, mFrameInitialMatrix);
+
                 Rect outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1,
                         mOriginalWidth*2, mOriginalHeight*2);
                 Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
-                mExitingBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 2);
+                mExitingBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 2,
+                        layerStack);
                 mExitingBlackFrame.setMatrix(mFrameInitialMatrix);
             } catch (Surface.OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
@@ -532,7 +554,7 @@
             }
         }
 
-        if (false && mEnteringBlackFrame == null) {
+        if (customAnim && mEnteringBlackFrame == null) {
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
                     WindowManagerService.TAG,
                     ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
@@ -542,7 +564,8 @@
                 Rect outer = new Rect(-finalWidth*1, -finalHeight*1,
                         finalWidth*2, finalHeight*2);
                 Rect inner = new Rect(0, 0, finalWidth, finalHeight);
-                mEnteringBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER);
+                mEnteringBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER,
+                        layerStack);
             } catch (Surface.OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
             } finally {
@@ -834,7 +857,7 @@
         return more;
     }
 
-    void updateSurfaces() {
+    void updateSurfacesInTransaction() {
         if (!mStarted) {
             return;
         }
@@ -874,7 +897,7 @@
             }
         }
 
-        setSnapshotTransform(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
+        setSnapshotTransformInTransaction(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
     }
 
     public boolean stepAnimationLocked(long now) {
diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java
index 61c0e9c..3b4c1ab 100644
--- a/services/java/com/android/server/wm/Session.java
+++ b/services/java/com/android/server/wm/Session.java
@@ -30,9 +30,12 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Parcel;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.Slog;
+import android.view.Display;
 import android.view.IWindow;
 import android.view.IWindowSession;
 import android.view.InputChannel;
@@ -68,8 +71,17 @@
         StringBuilder sb = new StringBuilder();
         sb.append("Session{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
-        sb.append(" uid ");
-        sb.append(mUid);
+        sb.append(" ");
+        sb.append(mPid);
+        if (mUid < Process.FIRST_APPLICATION_UID) {
+            sb.append(":");
+            sb.append(mUid);
+        } else {
+            sb.append(":u");
+            sb.append(UserHandle.getUserId(mUid));
+            sb.append('a');
+            sb.append(UserHandle.getAppId(mUid));
+        }
         sb.append("}");
         mStringName = sb.toString();
 
@@ -134,15 +146,33 @@
         }
     }
 
+    @Override
     public int add(IWindow window, int seq, WindowManager.LayoutParams attrs,
             int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) {
-        return mService.addWindow(this, window, seq, attrs, viewVisibility, outContentInsets,
-                outInputChannel);
+        return addToDisplay(window, seq, attrs, viewVisibility, Display.DEFAULT_DISPLAY,
+                outContentInsets, outInputChannel);
     }
-    
+
+    @Override
+    public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
+            int viewVisibility, int displayId, Rect outContentInsets,
+            InputChannel outInputChannel) {
+        return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
+                outContentInsets, outInputChannel);
+    }
+
+    @Override
     public int addWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs,
             int viewVisibility, Rect outContentInsets) {
-        return mService.addWindow(this, window, seq, attrs, viewVisibility, outContentInsets, null);
+        return addToDisplayWithoutInputChannel(window, seq, attrs, viewVisibility,
+                Display.DEFAULT_DISPLAY, outContentInsets);
+    }
+
+    @Override
+    public int addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs,
+            int viewVisibility, int displayId, Rect outContentInsets) {
+        return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
+            outContentInsets, null);
     }
 
     public void remove(IWindow window) {
@@ -261,7 +291,8 @@
             // !!! FIXME: put all this heavy stuff onto the mH looper, as well as
             // the actual drag event dispatch stuff in the dragstate
 
-            mService.mDragState.register();
+            Display display = callingWin.mDisplayContent.getDisplay();
+            mService.mDragState.register(display);
             mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
             if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel,
                     mService.mDragState.mServerChannel)) {
@@ -291,6 +322,7 @@
                         touchY - thumbCenterY);
                 surface.setAlpha(.7071f);
                 surface.setLayer(mService.mDragState.getDragLayerLw());
+                surface.setLayerStack(display.getLayerStack());
                 surface.show();
             } finally {
                 Surface.closeTransaction();
@@ -389,6 +421,31 @@
         mService.wallpaperCommandComplete(window, result);
     }
 
+    public void setUniverseTransform(IBinder window, float alpha, float offx, float offy,
+            float dsdx, float dtdx, float dsdy, float dtdy) {
+        synchronized(mService.mWindowMap) {
+            long ident = Binder.clearCallingIdentity();
+            try {
+                mService.setUniverseTransformLocked(
+                        mService.windowForClientLocked(this, window, true),
+                        alpha, offx, offy, dsdx, dtdx, dsdy, dtdy);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
+    public void onRectangleOnScreenRequested(IBinder token, Rect rectangle, boolean immediate) {
+        synchronized(mService.mWindowMap) {
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                mService.onRectangleOnScreenRequested(token, rectangle, immediate);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+    }
+
     void windowAddedLocked() {
         if (mSurfaceSession == null) {
             if (WindowManagerService.localLOGV) Slog.v(
diff --git a/services/java/com/android/server/wm/StrictModeFlash.java b/services/java/com/android/server/wm/StrictModeFlash.java
index 768d2db..90bbd08 100644
--- a/services/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/java/com/android/server/wm/StrictModeFlash.java
@@ -22,8 +22,6 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.Region;
-import android.util.DisplayMetrics;
-import android.util.Slog;
 import android.view.Display;
 import android.view.Surface;
 import android.view.SurfaceSession;
@@ -39,13 +37,16 @@
 
     public StrictModeFlash(Display display, SurfaceSession session) {
         try {
-            mSurface = new Surface(session, 0, "StrictModeFlash", -1, 1, 1, PixelFormat.TRANSLUCENT, 0);
+            mSurface = new Surface(session, "StrictModeFlash",
+                1, 1, PixelFormat.TRANSLUCENT, Surface.HIDDEN);
         } catch (Surface.OutOfResourcesException e) {
             return;
         }
 
+        mSurface.setLayerStack(display.getLayerStack());
         mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 101);  // one more than Watermark? arbitrary.
         mSurface.setPosition(0, 0);
+        mSurface.show();
         mDrawNeeded = true;
     }
 
diff --git a/services/java/com/android/server/wm/Watermark.java b/services/java/com/android/server/wm/Watermark.java
index 5497eb4..ac152c9 100644
--- a/services/java/com/android/server/wm/Watermark.java
+++ b/services/java/com/android/server/wm/Watermark.java
@@ -35,6 +35,7 @@
  * Displays a watermark on top of the window manager's windows.
  */
 class Watermark {
+    final Display mDisplay;
     final String[] mTokens;
     final String mText;
     final Paint mTextPaint;
@@ -50,7 +51,7 @@
     int mLastDH;
     boolean mDrawNeeded;
 
-    Watermark(DisplayMetrics dm, SurfaceSession session, String[] tokens) {
+    Watermark(Display display, DisplayMetrics dm, SurfaceSession session, String[] tokens) {
         if (false) {
             Log.i(WindowManagerService.TAG, "*********************** WATERMARK");
             for (int i=0; i<tokens.length; i++) {
@@ -58,6 +59,7 @@
             }
         }
 
+        mDisplay = display;
         mTokens = tokens;
 
         StringBuilder builder = new StringBuilder(32);
@@ -111,8 +113,9 @@
         mTextPaint.setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor);
 
         try {
-            mSurface = new Surface(session, 0,
-                    "WatermarkSurface", -1, 1, 1, PixelFormat.TRANSLUCENT, 0);
+            mSurface = new Surface(session, "WatermarkSurface",
+                    1, 1, PixelFormat.TRANSLUCENT, Surface.HIDDEN);
+            mSurface.setLayerStack(mDisplay.getLayerStack());
             mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER*100);
             mSurface.setPosition(0, 0);
             mSurface.show();
@@ -171,4 +174,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index 62cf711..54914c2 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -8,19 +8,26 @@
 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_UPDATE_ROTATION;
 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_MAY_CHANGE;
 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED;
+import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE;
 
-import static com.android.server.wm.WindowManagerService.H.SET_DIM_PARAMETERS;
+import static com.android.server.wm.WindowManagerService.H.UPDATE_ANIM_PARAMETERS;
 
 import android.content.Context;
+import android.os.Debug;
 import android.os.SystemClock;
 import android.util.Log;
 import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.util.TimeUtils;
+import android.view.Display;
 import android.view.Surface;
-import android.view.WindowManager;
 import android.view.WindowManagerPolicy;
 import android.view.animation.Animation;
 
-import com.android.internal.policy.impl.PhoneWindowManager;
+import com.android.server.wm.WindowManagerService.AppWindowAnimParams;
+import com.android.server.wm.WindowManagerService.LayoutFields;
+import com.android.server.wm.WindowManagerService.LayoutToAnimatorParams;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -32,26 +39,20 @@
 public class WindowAnimator {
     private static final String TAG = "WindowAnimator";
 
-    // mForceHiding states.
-    private static final int KEYGUARD_NOT_SHOWN     = 0;
-    private static final int KEYGUARD_ANIMATING_IN  = 1;
-    private static final int KEYGUARD_SHOWN         = 2;
-    private static final int KEYGUARD_ANIMATING_OUT = 3;
-    int mForceHiding;
-
     final WindowManagerService mService;
     final Context mContext;
     final WindowManagerPolicy mPolicy;
 
-    ArrayList<WindowStateAnimator> mWinAnimators = new ArrayList<WindowStateAnimator>();
-
     boolean mAnimating;
-    WindowState mWindowAnimationBackground;
-    int mWindowAnimationBackgroundColor;
+
+    final Runnable mAnimationRunnable;
+
     int mAdjResult;
 
-    int mPendingLayoutChanges;
+    // Layout changes for individual Displays. Indexed by displayId.
+    SparseIntArray mPendingLayoutChanges = new SparseIntArray();
 
+    // TODO: Assign these from each iteration through DisplayContent. Only valid between loops.
     /** Overall window dimensions */
     int mDw, mDh;
 
@@ -65,105 +66,257 @@
      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
     private int mAnimTransactionSequence;
 
-    /** The one and only screen rotation if one is happening */
-    ScreenRotationAnimation mScreenRotationAnimation = null;
-
     // Window currently running an animation that has requested it be detached
     // from the wallpaper.  This means we need to ensure the wallpaper is
     // visible behind it in case it animates in a way that would allow it to be
-    // seen.
+    // seen. If multiple windows satisfy this, use the lowest window.
     WindowState mWindowDetachedWallpaper = null;
-    WindowState mDetachedWallpaper = null;
-    DimSurface mWindowAnimationBackgroundSurface = null;
+
+    WindowStateAnimator mUniverseBackground = null;
+    int mAboveUniverseLayer = 0;
 
     int mBulkUpdateParams = 0;
 
-    DimAnimator mDimAnimator = null;
-    DimAnimator.Parameters mDimParams = null;
+    SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators =
+            new SparseArray<WindowAnimator.DisplayContentsAnimator>();
 
     static final int WALLPAPER_ACTION_PENDING = 1;
     int mPendingActions;
 
-    WindowAnimator(final WindowManagerService service, final Context context,
-            final WindowManagerPolicy policy) {
-        mService = service;
-        mContext = context;
-        mPolicy = policy;
+    WindowState mWallpaperTarget = null;
+    AppWindowAnimator mWpAppAnimator = null;
+    WindowState mLowerWallpaperTarget = null;
+    WindowState mUpperWallpaperTarget = null;
+
+    ArrayList<AppWindowAnimator> mAppAnimators = new ArrayList<AppWindowAnimator>();
+
+    ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
+
+    /** Parameters being passed from this into mService. */
+    static class AnimatorToLayoutParams {
+        boolean mUpdateQueued;
+        int mBulkUpdateParams;
+        SparseIntArray mPendingLayoutChanges;
+        WindowState mWindowDetachedWallpaper;
+    }
+    /** Do not modify unless holding mService.mWindowMap or this and mAnimToLayout in that order */
+    final AnimatorToLayoutParams mAnimToLayout = new AnimatorToLayoutParams();
+
+    boolean mInitialized = false;
+
+    // forceHiding states.
+    static final int KEYGUARD_NOT_SHOWN     = 0;
+    static final int KEYGUARD_ANIMATING_IN  = 1;
+    static final int KEYGUARD_SHOWN         = 2;
+    static final int KEYGUARD_ANIMATING_OUT = 3;
+    int mForceHiding = KEYGUARD_NOT_SHOWN;
+
+    private String forceHidingToString() {
+        switch (mForceHiding) {
+            case KEYGUARD_NOT_SHOWN:    return "KEYGUARD_NOT_SHOWN";
+            case KEYGUARD_ANIMATING_IN: return "KEYGUARD_ANIMATING_IN";
+            case KEYGUARD_SHOWN:        return "KEYGUARD_SHOWN";
+            case KEYGUARD_ANIMATING_OUT:return "KEYGUARD_ANIMATING_OUT";
+            default: return "KEYGUARD STATE UNKNOWN " + mForceHiding;
+        }
     }
 
-    void hideWallpapersLocked(final WindowState w) {
-        if ((mService.mWallpaperTarget == w && mService.mLowerWallpaperTarget == null)
-                || mService.mWallpaperTarget == null) {
-            for (final WindowToken token : mService.mWallpaperTokens) {
-                for (final WindowState wallpaper : token.windows) {
+    WindowAnimator(final WindowManagerService service) {
+        mService = service;
+        mContext = service.mContext;
+        mPolicy = service.mPolicy;
+
+        mAnimationRunnable = new Runnable() {
+            @Override
+            public void run() {
+                // TODO(cmautner): When full isolation is achieved for animation, the first lock
+                // goes away and only the WindowAnimator.this remains.
+                synchronized(mService.mWindowMap) {
+                    synchronized(WindowAnimator.this) {
+                        copyLayoutToAnimParamsLocked();
+                        animateLocked();
+                    }
+                }
+            }
+        };
+    }
+
+    void addDisplayLocked(final int displayId) {
+        // Create the DisplayContentsAnimator object by retrieving it.
+        getDisplayContentsAnimatorLocked(displayId);
+        if (displayId == Display.DEFAULT_DISPLAY) {
+            mInitialized = true;
+        }
+    }
+
+    void removeDisplayLocked(final int displayId) {
+        final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
+        if (displayAnimator != null) {
+            if (displayAnimator.mWindowAnimationBackgroundSurface != null) {
+                displayAnimator.mWindowAnimationBackgroundSurface.kill();
+                displayAnimator.mWindowAnimationBackgroundSurface = null;
+            }
+            if (displayAnimator.mScreenRotationAnimation != null) {
+                displayAnimator.mScreenRotationAnimation.kill();
+                displayAnimator.mScreenRotationAnimation = null;
+            }
+            if (displayAnimator.mDimAnimator != null) {
+                displayAnimator.mDimAnimator.kill();
+                displayAnimator.mDimAnimator = null;
+            }
+        }
+
+        mDisplayContentsAnimators.delete(displayId);
+    }
+
+    /** Locked on mAnimToLayout */
+    void updateAnimToLayoutLocked() {
+        final AnimatorToLayoutParams animToLayout = mAnimToLayout;
+        synchronized (animToLayout) {
+            animToLayout.mBulkUpdateParams = mBulkUpdateParams;
+            animToLayout.mPendingLayoutChanges = mPendingLayoutChanges.clone();
+            animToLayout.mWindowDetachedWallpaper = mWindowDetachedWallpaper;
+
+            if (!animToLayout.mUpdateQueued) {
+                animToLayout.mUpdateQueued = true;
+                mService.mH.sendMessage(mService.mH.obtainMessage(UPDATE_ANIM_PARAMETERS));
+            }
+        }
+    }
+
+    /** Copy all WindowManagerService params into local params here. Locked on 'this'. */
+    private void copyLayoutToAnimParamsLocked() {
+        final LayoutToAnimatorParams layoutToAnim = mService.mLayoutToAnim;
+        synchronized(layoutToAnim) {
+            layoutToAnim.mAnimationScheduled = false;
+
+            if (!layoutToAnim.mParamsModified) {
+                return;
+            }
+            layoutToAnim.mParamsModified = false;
+
+            if ((layoutToAnim.mChanges & LayoutToAnimatorParams.WALLPAPER_TOKENS_CHANGED) != 0) {
+                layoutToAnim.mChanges &= ~LayoutToAnimatorParams.WALLPAPER_TOKENS_CHANGED;
+                mWallpaperTokens = new ArrayList<WindowToken>(layoutToAnim.mWallpaperTokens);
+            }
+
+            if (WindowManagerService.DEBUG_WALLPAPER_LIGHT) {
+                if (mWallpaperTarget != layoutToAnim.mWallpaperTarget
+                        || mLowerWallpaperTarget != layoutToAnim.mLowerWallpaperTarget
+                        || mUpperWallpaperTarget != layoutToAnim.mUpperWallpaperTarget) {
+                    Slog.d(TAG, "Pulling anim wallpaper: target=" + layoutToAnim.mWallpaperTarget
+                            + " lower=" + layoutToAnim.mLowerWallpaperTarget + " upper="
+                            + layoutToAnim.mUpperWallpaperTarget);
+                }
+            }
+            mWallpaperTarget = layoutToAnim.mWallpaperTarget;
+            mWpAppAnimator = mWallpaperTarget == null
+                    ? null : mWallpaperTarget.mAppToken == null
+                            ? null : mWallpaperTarget.mAppToken.mAppAnimator;
+            mLowerWallpaperTarget = layoutToAnim.mLowerWallpaperTarget;
+            mUpperWallpaperTarget = layoutToAnim.mUpperWallpaperTarget;
+
+            // Set the new DimAnimator params.
+            final int numDisplays = mDisplayContentsAnimators.size();
+            for (int i = 0; i < numDisplays; i++) {
+                final int displayId = mDisplayContentsAnimators.keyAt(i);
+                DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
+
+                displayAnimator.mWinAnimators.clear();
+                final WinAnimatorList winAnimators = layoutToAnim.mWinAnimatorLists.get(displayId);
+                if (winAnimators != null) {
+                    displayAnimator.mWinAnimators.addAll(winAnimators);
+                }
+
+                DimAnimator.Parameters dimParams = layoutToAnim.mDimParams.get(displayId);
+                if (dimParams == null) {
+                    displayAnimator.mDimParams = null;
+                } else {
+                    final WindowStateAnimator newWinAnimator = dimParams.mDimWinAnimator;
+
+                    // Only set dim params on the highest dimmed layer.
+                    final WindowStateAnimator existingDimWinAnimator =
+                            displayAnimator.mDimParams == null ?
+                                    null : displayAnimator.mDimParams.mDimWinAnimator;
+                    // Don't turn on for an unshown surface, or for any layer but the highest
+                    // dimmed layer.
+                    if (newWinAnimator.mSurfaceShown && (existingDimWinAnimator == null
+                            || !existingDimWinAnimator.mSurfaceShown
+                            || existingDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) {
+                        displayAnimator.mDimParams = new DimAnimator.Parameters(dimParams);
+                    }
+                }
+            }
+
+            mAppAnimators.clear();
+            final int N = layoutToAnim.mAppWindowAnimParams.size();
+            for (int i = 0; i < N; i++) {
+                final AppWindowAnimParams params = layoutToAnim.mAppWindowAnimParams.get(i);
+                AppWindowAnimator appAnimator = params.mAppAnimator;
+                appAnimator.mAllAppWinAnimators.clear();
+                appAnimator.mAllAppWinAnimators.addAll(params.mWinAnimators);
+                mAppAnimators.add(appAnimator);
+            }
+        }
+    }
+
+    void hideWallpapersLocked(final WindowState w, boolean fromAnimator) {
+        // There is an issue where this function can be called either from
+        // the animation or the layout side of the window manager.  The problem
+        // is that if it is called from the layout side, we may not yet have
+        // propagated the current layout wallpaper state over into the animation
+        // state.  If that is the case, we can do bad things like hide the
+        // wallpaper when we had just made it shown because the animation side
+        // doesn't yet see that there is now a wallpaper target.  As a temporary
+        // work-around, we tell the function here which side of the window manager
+        // is calling so it can use the right state.
+        if (fromAnimator) {
+            hideWallpapersLocked(w, mWallpaperTarget, mLowerWallpaperTarget, mWallpaperTokens);
+        } else {
+            hideWallpapersLocked(w, mService.mWallpaperTarget,
+                    mService.mLowerWallpaperTarget, mService.mWallpaperTokens);
+        }
+    }
+
+    void hideWallpapersLocked(final WindowState w, final WindowState wallpaperTarget,
+            final WindowState lowerWallpaperTarget, final ArrayList<WindowToken> wallpaperTokens) {
+        if ((wallpaperTarget == w && lowerWallpaperTarget == null) || wallpaperTarget == null) {
+            final int numTokens = wallpaperTokens.size();
+            for (int i = numTokens - 1; i >= 0; i--) {
+                final WindowToken token = wallpaperTokens.get(i);
+                final int numWindows = token.windows.size();
+                for (int j = numWindows - 1; j >= 0; j--) {
+                    final WindowState wallpaper = token.windows.get(j);
                     final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
                     if (!winAnimator.mLastHidden) {
                         winAnimator.hide();
                         mService.dispatchWallpaperVisibility(wallpaper, false);
-                        mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+                        setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
+                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
                     }
                 }
+                if (WindowManagerService.DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG,
+                        "Hiding wallpaper " + token + " from " + w
+                        + " target=" + wallpaperTarget + " lower=" + lowerWallpaperTarget
+                        + "\n" + Debug.getCallers(5, "  "));
                 token.hidden = true;
             }
         }
     }
 
-    private void testWallpaperAndBackgroundLocked() {
-        if (mWindowDetachedWallpaper != mDetachedWallpaper) {
-            if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
-                    "Detached wallpaper changed from " + mWindowDetachedWallpaper
-                    + " to " + mDetachedWallpaper);
-            mWindowDetachedWallpaper = mDetachedWallpaper;
-            mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
-        }
-
-        if (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 = mWindowAnimationBackground;
-            if (mService.mWallpaperTarget == target
-                    || mService.mLowerWallpaperTarget == target
-                    || mService.mUpperWallpaperTarget == target) {
-                final int N = mService.mWindows.size();
-                for (int i = 0; i < N; i++) {
-                    WindowState w = mService.mWindows.get(i);
-                    if (w.mIsWallpaper) {
-                        target = w;
-                        break;
-                    }
-                }
-            }
-            if (mWindowAnimationBackgroundSurface == null) {
-                mWindowAnimationBackgroundSurface = new DimSurface(mService.mFxSession);
-            }
-            final int dw = mDw;
-            final int dh = mDh;
-            mWindowAnimationBackgroundSurface.show(dw, dh,
-                    target.mWinAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM,
-                    mWindowAnimationBackgroundColor);
-        } else if (mWindowAnimationBackgroundSurface != null) {
-            mWindowAnimationBackgroundSurface.hide();
-        }
-    }
-
-    private void updateWindowsAppsAndRotationAnimationsLocked() {
-        final ArrayList<AppWindowToken> appTokens = mService.mAnimatingAppTokens;
+    private void updateAppWindowsLocked() {
         int i;
-        final int NAT = appTokens.size();
+        final int NAT = mAppAnimators.size();
         for (i=0; i<NAT; i++) {
-            final AppWindowAnimator appAnimator = appTokens.get(i).mAppAnimator;
+            final AppWindowAnimator appAnimator = mAppAnimators.get(i);
             final boolean wasAnimating = appAnimator.animation != null
                     && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
             if (appAnimator.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 (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                    mService.debugLayoutRepeats("appToken " + appAnimator.mAppToken + " done",
-                        mPendingLayoutChanges);
-                }
+                setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
+                        "appToken " + appAnimator.mAppToken + " done");
                 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
                         "updateWindowsApps...: done animating " + appAnimator.mAppToken);
             }
@@ -178,36 +331,26 @@
                 mAnimating = true;
             } else if (wasAnimating) {
                 // stopped animating, do one more pass through the layout
-                mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-                if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                    mService.debugLayoutRepeats("exiting appToken " + appAnimator.mAppToken
-                        + " done", mPendingLayoutChanges);
-                }
+                setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
+                    "exiting appToken " + appAnimator.mAppToken + " done");
                 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
                         "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
             }
         }
-
-        if (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating()) {
-            if (mScreenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
-                mAnimating = true;
-            } else {
-                mBulkUpdateParams |= SET_UPDATE_ROTATION;
-                mScreenRotationAnimation.kill();
-                mScreenRotationAnimation = null;
-            }
-        }
     }
 
-    private void updateWindowsAndWallpaperLocked() {
+    private void updateWindowsLocked(final int displayId) {
         ++mAnimTransactionSequence;
 
+        final WinAnimatorList winAnimatorList =
+                getDisplayContentsAnimatorLocked(displayId).mWinAnimators;
         ArrayList<WindowStateAnimator> unForceHiding = null;
         boolean wallpaperInUnForceHiding = false;
+        mForceHiding = KEYGUARD_NOT_SHOWN;
 
-        for (int i = mService.mWindows.size() - 1; i >= 0; i--) {
-            WindowState win = mService.mWindows.get(i);
-            WindowStateAnimator winAnimator = win.mWinAnimator;
+        for (int i = winAnimatorList.size() - 1; i >= 0; i--) {
+            WindowStateAnimator winAnimator = winAnimatorList.get(i);
+            WindowState win = winAnimator.mWin;
             final int flags = winAnimator.mAttrFlags;
 
             if (winAnimator.mSurface != null) {
@@ -219,56 +362,13 @@
                             ", 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 (winAnimator.mAnimation != null) {
-                        if ((flags & FLAG_SHOW_WALLPAPER) != 0
-                                && winAnimator.mAnimation.getDetachWallpaper()) {
-                            mDetachedWallpaper = win;
-                        }
-                        final int backgroundColor = winAnimator.mAnimation.getBackgroundColor();
-                        if (backgroundColor != 0) {
-                            if (mWindowAnimationBackground == null
-                                    || (winAnimator.mAnimLayer <
-                                            mWindowAnimationBackground.mWinAnimator.mAnimLayer)) {
-                                mWindowAnimationBackground = win;
-                                mWindowAnimationBackgroundColor = backgroundColor;
-                            }
-                        }
-                    }
-                    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.
-                final AppWindowAnimator appAnimator =
-                        win.mAppToken == null ? null : win.mAppToken.mAppAnimator;
-                if (appAnimator != null && appAnimator.animation != null
-                        && appAnimator.animating) {
-                    if ((flags & FLAG_SHOW_WALLPAPER) != 0
-                            && appAnimator.animation.getDetachWallpaper()) {
-                        mDetachedWallpaper = win;
-                    }
-                    final int backgroundColor = appAnimator.animation.getBackgroundColor();
-                    if (backgroundColor != 0) {
-                        if (mWindowAnimationBackground == null
-                                || (winAnimator.mAnimLayer <
-                                        mWindowAnimationBackground.mWinAnimator.mAnimLayer)) {
-                            mWindowAnimationBackground = win;
-                            mWindowAnimationBackgroundColor = backgroundColor;
-                        }
-                    }
-                }
-
-                if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == win) {
+                if (wasAnimating && !winAnimator.mAnimating && mWallpaperTarget == win) {
                     mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
-                    mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+                    setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
+                            WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
                     if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
                         mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2",
-                            mPendingLayoutChanges);
+                            mPendingLayoutChanges.get(Display.DEFAULT_DISPLAY));
                     }
                 }
 
@@ -278,10 +378,11 @@
                                 WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
                                 "Animation started that could impact force hide: " + win);
                         mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
-                        mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+                        setPendingLayoutChanges(displayId,
+                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
                             mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3",
-                                mPendingLayoutChanges);
+                                mPendingLayoutChanges.get(displayId));
                         }
                         mService.mFocusMayChange = true;
                     }
@@ -326,7 +427,7 @@
                                     unForceHiding = new ArrayList<WindowStateAnimator>();
                                 }
                                 unForceHiding.add(winAnimator);
-                                if ((win.mAttrs.flags&WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
+                                if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
                                     wallpaperInUnForceHiding = true;
                                 }
                             }
@@ -338,12 +439,13 @@
                             }
                         }
                     }
-                    if (changed && (flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
+                    if (changed && (flags & FLAG_SHOW_WALLPAPER) != 0) {
                         mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
-                        mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+                        setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
+                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
                             mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4",
-                                mPendingLayoutChanges);
+                                mPendingLayoutChanges.get(Display.DEFAULT_DISPLAY));
                         }
                     }
                 }
@@ -353,16 +455,16 @@
             if (winAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW) {
                 if (atoken == null || atoken.allDrawn) {
                     if (winAnimator.performShowLocked()) {
-                        mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+                        mPendingLayoutChanges.put(displayId,
+                                WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
                             mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5",
-                                mPendingLayoutChanges);
+                                mPendingLayoutChanges.get(displayId));
                         }
                     }
                 }
             }
-            final AppWindowAnimator appAnimator =
-                    atoken == null ? null : atoken.mAppAnimator;
+            final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
             if (appAnimator != null && appAnimator.thumbnail != null) {
                 if (appAnimator.thumbnailTransactionSeq != mAnimTransactionSequence) {
                     appAnimator.thumbnailTransactionSeq = mAnimTransactionSequence;
@@ -388,38 +490,138 @@
         }
     }
 
+    private void updateWallpaperLocked(int displayId) {
+        final DisplayContentsAnimator displayAnimator =
+                getDisplayContentsAnimatorLocked(displayId);
+        final WinAnimatorList winAnimatorList = displayAnimator.mWinAnimators;
+        WindowStateAnimator windowAnimationBackground = null;
+        int windowAnimationBackgroundColor = 0;
+        WindowState detachedWallpaper = null;
+        final DimSurface windowAnimationBackgroundSurface =
+                displayAnimator.mWindowAnimationBackgroundSurface;
+
+        for (int i = winAnimatorList.size() - 1; i >= 0; i--) {
+            WindowStateAnimator winAnimator = winAnimatorList.get(i);
+            if (winAnimator.mSurface == null) {
+                continue;
+            }
+
+            final int flags = winAnimator.mAttrFlags;
+            final WindowState win = winAnimator.mWin;
+
+            // 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 (winAnimator.mAnimating) {
+                if (winAnimator.mAnimation != null) {
+                    if ((flags & FLAG_SHOW_WALLPAPER) != 0
+                            && winAnimator.mAnimation.getDetachWallpaper()) {
+                        detachedWallpaper = win;
+                    }
+                    final int backgroundColor = winAnimator.mAnimation.getBackgroundColor();
+                    if (backgroundColor != 0) {
+                        if (windowAnimationBackground == null || (winAnimator.mAnimLayer <
+                                windowAnimationBackground.mAnimLayer)) {
+                            windowAnimationBackground = winAnimator;
+                            windowAnimationBackgroundColor = backgroundColor;
+                        }
+                    }
+                }
+                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.
+            final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
+            if (appAnimator != null && appAnimator.animation != null
+                    && appAnimator.animating) {
+                if ((flags & FLAG_SHOW_WALLPAPER) != 0
+                        && appAnimator.animation.getDetachWallpaper()) {
+                    detachedWallpaper = win;
+                }
+
+                final int backgroundColor = appAnimator.animation.getBackgroundColor();
+                if (backgroundColor != 0) {
+                    if (windowAnimationBackground == null || (winAnimator.mAnimLayer <
+                            windowAnimationBackground.mAnimLayer)) {
+                        windowAnimationBackground = winAnimator;
+                        windowAnimationBackgroundColor = backgroundColor;
+                    }
+                }
+            }
+        } // end forall windows
+
+        if (mWindowDetachedWallpaper != detachedWallpaper) {
+            if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
+                    "Detached wallpaper changed from " + mWindowDetachedWallpaper
+                    + " to " + detachedWallpaper);
+            mWindowDetachedWallpaper = detachedWallpaper;
+            mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
+        }
+
+        if (windowAnimationBackgroundColor != 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.
+            int animLayer = windowAnimationBackground.mAnimLayer;
+            WindowState win = windowAnimationBackground.mWin;
+            if (mWallpaperTarget == win
+                    || mLowerWallpaperTarget == win || mUpperWallpaperTarget == win) {
+                final int N = winAnimatorList.size();
+                for (int i = 0; i < N; i++) {
+                    WindowStateAnimator winAnimator = winAnimatorList.get(i);
+                    if (winAnimator.mIsWallpaper) {
+                        animLayer = winAnimator.mAnimLayer;
+                        break;
+                    }
+                }
+            }
+
+            if (windowAnimationBackgroundSurface != null) {
+                windowAnimationBackgroundSurface.show(mDw, mDh,
+                        animLayer - WindowManagerService.LAYER_OFFSET_DIM,
+                        windowAnimationBackgroundColor);
+            }
+        } else {
+            if (windowAnimationBackgroundSurface != null) {
+                windowAnimationBackgroundSurface.hide();
+            }
+        }
+    }
+
     private void testTokenMayBeDrawnLocked() {
         // See if any windows have been drawn, so they (and others
         // associated with them) can now be shown.
-        final ArrayList<AppWindowToken> appTokens = mService.mAnimatingAppTokens;
-        final int NT = appTokens.size();
+        final int NT = mAppAnimators.size();
         for (int i=0; i<NT; i++) {
-            AppWindowToken wtoken = appTokens.get(i);
+            AppWindowAnimator appAnimator = mAppAnimators.get(i);
+            AppWindowToken wtoken = appAnimator.mAppToken;
             final boolean allDrawn = wtoken.allDrawn;
-            if (allDrawn != wtoken.mAppAnimator.allDrawn) {
-                wtoken.mAppAnimator.allDrawn = allDrawn;
+            if (allDrawn != appAnimator.allDrawn) {
+                appAnimator.allDrawn = allDrawn;
                 if (allDrawn) {
                     // The token has now changed state to having all
                     // windows shown...  what to do, what to do?
-                    if (wtoken.mAppAnimator.freezingScreen) {
-                        wtoken.mAppAnimator.showAllWindowsLocked();
+                    if (appAnimator.freezingScreen) {
+                        appAnimator.showAllWindowsLocked();
                         mService.unsetAppFreezingScreenLocked(wtoken, false, true);
                         if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
                                 "Setting mOrientationChangeComplete=true because wtoken "
                                 + wtoken + " numInteresting=" + wtoken.numInterestingWindows
                                 + " numDrawn=" + wtoken.numDrawnWindows);
                         // This will set mOrientationChangeComplete and cause a pass through layout.
-                        mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+                        setAppLayoutChanges(appAnimator,
+                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
+                                "testTokenMayBeDrawnLocked: freezingScreen");
                     } else {
-                        mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
-                        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                            mService.debugLayoutRepeats("testTokenMayBeDrawnLocked",
-                                mPendingLayoutChanges);
-                        }
-
+                        setAppLayoutChanges(appAnimator,
+                                WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
+                                "testTokenMayBeDrawnLocked");
+ 
                         // We can now show all of the drawn windows!
                         if (!mService.mOpeningApps.contains(wtoken)) {
-                            mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked();
+                            mAnimating |= appAnimator.showAllWindowsLocked();
                         }
                     }
                 }
@@ -427,64 +629,82 @@
         }
     }
 
-    private void performAnimationsLocked() {
-        mForceHiding = KEYGUARD_NOT_SHOWN;
-        mDetachedWallpaper = null;
-        mWindowAnimationBackground = null;
-        mWindowAnimationBackgroundColor = 0;
-
-        updateWindowsAndWallpaperLocked();
-        if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
-            mPendingActions |= WALLPAPER_ACTION_PENDING;
-        }
-
-        testTokenMayBeDrawnLocked();
+    private void performAnimationsLocked(final int displayId) {
+        updateWindowsLocked(displayId);
+        updateWallpaperLocked(displayId);
     }
 
-    synchronized void animate() {
-        mPendingLayoutChanges = 0;
+    // TODO(cmautner): Change the following comment when no longer locked on mWindowMap */
+    /** Locked on mService.mWindowMap and this. */
+    private void animateLocked() {
+        if (!mInitialized) {
+            return;
+        }
+
+        mPendingLayoutChanges.clear();
         mCurrentTime = SystemClock.uptimeMillis();
-        mBulkUpdateParams = 0;
+        mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
         boolean wasAnimating = mAnimating;
         mAnimating = false;
         if (WindowManagerService.DEBUG_WINDOW_TRACE) {
             Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
         }
 
-        // Update animations of all applications, including those
-        // associated with exiting/removed apps
+        if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
+                TAG, ">>> OPEN TRANSACTION animateLocked");
         Surface.openTransaction();
-
+        Surface.setAnimationTransaction();
         try {
-            updateWindowsAppsAndRotationAnimationsLocked();
-            performAnimationsLocked();
-            testWallpaperAndBackgroundLocked();
+            updateAppWindowsLocked();
 
-            // THIRD LOOP: Update the surfaces of all windows.
+            final int numDisplays = mDisplayContentsAnimators.size();
+            for (int i = 0; i < numDisplays; i++) {
+                final int displayId = mDisplayContentsAnimators.keyAt(i);
+                DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
 
-            if (mScreenRotationAnimation != null) {
-                mScreenRotationAnimation.updateSurfaces();
+                final ScreenRotationAnimation screenRotationAnimation =
+                        displayAnimator.mScreenRotationAnimation;
+                if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
+                    if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
+                        mAnimating = true;
+                    } else {
+                        mBulkUpdateParams |= SET_UPDATE_ROTATION;
+                        screenRotationAnimation.kill();
+                        displayAnimator.mScreenRotationAnimation = null;
+                    }
+                }
+
+                // Update animations of all applications, including those
+                // associated with exiting/removed apps
+                performAnimationsLocked(displayId);
+
+                final WinAnimatorList winAnimatorList = displayAnimator.mWinAnimators;
+                final int N = winAnimatorList.size();
+                for (int j = 0; j < N; j++) {
+                    winAnimatorList.get(j).prepareSurfaceLocked(true);
+                }
             }
 
-            final int N = mWinAnimators.size();
-            for (int i = 0; i < N; i++) {
-                mWinAnimators.get(i).prepareSurfaceLocked(true);
-            }
+            testTokenMayBeDrawnLocked();
 
-            if (mDimParams != null) {
-                mDimAnimator.updateParameters(mContext.getResources(), mDimParams, mCurrentTime);
-            }
-            if (mDimAnimator != null && mDimAnimator.mDimShown) {
-                mAnimating |= mDimAnimator.updateSurface(isDimming(), mCurrentTime,
-                        !mService.okToDisplay());
-            }
+            for (int i = 0; i < numDisplays; i++) {
+                final int displayId = mDisplayContentsAnimators.keyAt(i);
+                DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
 
-            if (mService.mBlackFrame != null) {
-                if (mScreenRotationAnimation != null) {
-                    mService.mBlackFrame.setMatrix(
-                            mScreenRotationAnimation.getEnterTransformation().getMatrix());
-                } else {
-                    mService.mBlackFrame.clearMatrix();
+                final ScreenRotationAnimation screenRotationAnimation =
+                        displayAnimator.mScreenRotationAnimation;
+                if (screenRotationAnimation != null) {
+                    screenRotationAnimation.updateSurfacesInTransaction();
+                }
+
+                final DimAnimator.Parameters dimParams = displayAnimator.mDimParams;
+                final DimAnimator dimAnimator = displayAnimator.mDimAnimator;
+                if (dimAnimator != null && dimParams != null) {
+                    dimAnimator.updateParameters(mContext.getResources(), dimParams, mCurrentTime);
+                }
+                if (dimAnimator != null && dimAnimator.mDimShown) {
+                    mAnimating |= dimAnimator.updateSurface(isDimmingLocked(displayId),
+                            mCurrentTime, !mService.okToDisplay());
                 }
             }
 
@@ -495,19 +715,33 @@
             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
         } finally {
             Surface.closeTransaction();
+            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
+                    TAG, "<<< CLOSE TRANSACTION animateLocked");
         }
 
-        mService.bulkSetParameters(mBulkUpdateParams, mPendingLayoutChanges);
+        for (int i = mPendingLayoutChanges.size() - 1; i >= 0; i--) {
+            if ((mPendingLayoutChanges.valueAt(i)
+                    & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
+                mPendingActions |= WALLPAPER_ACTION_PENDING;
+            }
+        }
+
+        if (mBulkUpdateParams != 0 || mPendingLayoutChanges.size() > 0) {
+            updateAnimToLayoutLocked();
+        }
 
         if (mAnimating) {
-            mService.scheduleAnimationLocked();
+            synchronized (mService.mLayoutToAnim) {
+                mService.scheduleAnimationLocked();
+            }
         } else if (wasAnimating) {
             mService.requestTraversalLocked();
         }
         if (WindowManagerService.DEBUG_WINDOW_TRACE) {
             Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
                 + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
-                + " mPendingLayoutChanges=" + Integer.toHexString(mPendingLayoutChanges));
+                + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
+                + Integer.toHexString(mPendingLayoutChanges.get(Display.DEFAULT_DISPLAY)));
         }
     }
 
@@ -524,72 +758,211 @@
         mInnerDh = appHeight;
     }
 
-    void startDimming(final WindowStateAnimator winAnimator, final float target,
-                      final int width, final int height) {
-        if (mDimAnimator == null) {
-            mDimAnimator = new DimAnimator(mService.mFxSession);
+    boolean isDimmingLocked(int displayId) {
+        return getDisplayContentsAnimatorLocked(displayId).mDimParams != null;
+    }
+
+    boolean isDimmingLocked(final WindowStateAnimator winAnimator) {
+        DimAnimator.Parameters dimParams =
+                getDisplayContentsAnimatorLocked(winAnimator.mWin.getDisplayId()).mDimParams;
+        return dimParams != null && dimParams.mDimWinAnimator == winAnimator;
+    }
+
+    static String bulkUpdateParamsToString(int bulkUpdateParams) {
+        StringBuilder builder = new StringBuilder(128);
+        if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
+            builder.append(" UPDATE_ROTATION");
         }
-        // Only set dim params on the highest dimmed layer.
-        final WindowStateAnimator dimWinAnimator = mDimParams == null
-                ? null : mDimParams.mDimWinAnimator;
-        // Don't turn on for an unshown surface, or for any layer but the highest dimmed one.
-        if (winAnimator.mSurfaceShown &&
-                (dimWinAnimator == null || !dimWinAnimator.mSurfaceShown
-                || dimWinAnimator.mAnimLayer < winAnimator.mAnimLayer)) {
-            mService.mH.sendMessage(mService.mH.obtainMessage(SET_DIM_PARAMETERS,
-                    new DimAnimator.Parameters(winAnimator, width, height, target)));
+        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
+            builder.append(" WALLPAPER_MAY_CHANGE");
         }
+        if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
+            builder.append(" FORCE_HIDING_CHANGED");
+        }
+        if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
+            builder.append(" ORIENTATION_CHANGE_COMPLETE");
+        }
+        if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
+            builder.append(" TURN_ON_SCREEN");
+        }
+        return builder.toString();
     }
 
-    // TODO(cmautner): Move into Handler
-    void stopDimming() {
-        mService.mH.sendMessage(mService.mH.obtainMessage(SET_DIM_PARAMETERS, null));
-    }
+    public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
+        final String subPrefix = "  " + prefix;
+        final String subSubPrefix = "  " + subPrefix;
 
-    boolean isDimming() {
-        return mDimParams != null;
-    }
+        boolean needSep = false;
+        if (mAppAnimators.size() > 0) {
+            needSep = true;
+            pw.println("  App Animators:");
+            for (int i=mAppAnimators.size()-1; i>=0; i--) {
+                AppWindowAnimator anim = mAppAnimators.get(i);
+                pw.print(prefix); pw.print("App Animator #"); pw.print(i);
+                        pw.print(' '); pw.print(anim);
+                if (dumpAll) {
+                    pw.println(':');
+                    anim.dump(pw, subPrefix, dumpAll);
+                } else {
+                    pw.println();
+                }
+            }
+        }
+        if (mWallpaperTokens.size() > 0) {
+            if (needSep) {
+                pw.println();
+            }
+            needSep = true;
+            pw.print(prefix); pw.println("Wallpaper tokens:");
+            for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
+                WindowToken token = mWallpaperTokens.get(i);
+                pw.print(prefix); pw.print("Wallpaper #"); pw.print(i);
+                        pw.print(' '); pw.print(token);
+                if (dumpAll) {
+                    pw.println(':');
+                    token.dump(pw, subPrefix);
+                } else {
+                    pw.println();
+                }
+            }
+        }
 
-    boolean isDimming(final WindowStateAnimator winAnimator) {
-        return mDimParams != null && mDimParams.mDimWinAnimator == winAnimator;
-    }
+        if (needSep) {
+            pw.println();
+        }
+        for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
+            pw.print(prefix); pw.print("DisplayContentsAnimator #");
+                    pw.print(mDisplayContentsAnimators.keyAt(i));
+                    pw.println(":");
+            DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
+            for (int j=0; j<displayAnimator.mWinAnimators.size(); j++) {
+                WindowStateAnimator wanim = displayAnimator.mWinAnimators.get(j);
+                pw.print(subPrefix); pw.print("Window #"); pw.print(j);
+                        pw.print(": "); pw.println(wanim);
+            }
+            if (displayAnimator.mWindowAnimationBackgroundSurface != null) {
+                if (dumpAll || displayAnimator.mWindowAnimationBackgroundSurface.mDimShown) {
+                    pw.print(subPrefix); pw.println("mWindowAnimationBackgroundSurface:");
+                    displayAnimator.mWindowAnimationBackgroundSurface.printTo(subSubPrefix, pw);
+                }
+            }
+            if (displayAnimator.mDimAnimator != null) {
+                if (dumpAll || displayAnimator.mDimAnimator.mDimShown) {
+                    pw.print(subPrefix); pw.println("mDimAnimator:");
+                    displayAnimator.mDimAnimator.printTo(subSubPrefix, pw);
+                }
+            } else if (dumpAll) {
+                pw.print(subPrefix); pw.println("no DimAnimator ");
+            }
+            if (displayAnimator.mDimParams != null) {
+                pw.print(subPrefix); pw.println("mDimParams:");
+                displayAnimator.mDimParams.printTo(subSubPrefix, pw);
+            } else if (dumpAll) {
+                pw.print(subPrefix); pw.println("no DimParams ");
+            }
+            if (displayAnimator.mScreenRotationAnimation != null) {
+                pw.print(subPrefix); pw.println("mScreenRotationAnimation:");
+                displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw);
+            } else if (dumpAll) {
+                pw.print(subPrefix); pw.println("no ScreenRotationAnimation ");
+            }
+        }
 
-    public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
+        pw.println();
+
         if (dumpAll) {
-            if (mWindowDetachedWallpaper != null) {
-                pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
-                        pw.println(mWindowDetachedWallpaper);
-            }
             pw.print(prefix); pw.print("mAnimTransactionSequence=");
-                    pw.println(mAnimTransactionSequence);
-            if (mWindowAnimationBackgroundSurface != null) {
-                pw.print(prefix); pw.print("mWindowAnimationBackgroundSurface:");
-                        mWindowAnimationBackgroundSurface.printTo(prefix + "  ", pw);
-            }
-            if (mDimAnimator != null) {
-                pw.print(prefix); pw.print("mDimAnimator:");
-                mDimAnimator.printTo(prefix + "  ", pw);
-            } else {
-                pw.print(prefix); pw.print("no DimAnimator ");
+                    pw.print(mAnimTransactionSequence);
+                    pw.print(" mForceHiding="); pw.println(forceHidingToString());
+            pw.print(prefix); pw.print("mCurrentTime=");
+                    pw.println(TimeUtils.formatUptime(mCurrentTime));
+            pw.print(prefix); pw.print("mDw=");
+                    pw.print(mDw); pw.print(" mDh="); pw.print(mDh);
+                    pw.print(" mInnerDw="); pw.print(mInnerDw);
+                    pw.print(" mInnerDh="); pw.println(mInnerDh);
+        }
+        if (mBulkUpdateParams != 0) {
+            pw.print(prefix); pw.print("mBulkUpdateParams=0x");
+                    pw.print(Integer.toHexString(mBulkUpdateParams));
+                    pw.println(bulkUpdateParamsToString(mBulkUpdateParams));
+        }
+        if (mPendingActions != 0) {
+            pw.print(prefix); pw.print("mPendingActions=0x");
+                    pw.println(Integer.toHexString(mPendingActions));
+        }
+        if (mWindowDetachedWallpaper != null) {
+            pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
+                pw.println(mWindowDetachedWallpaper);
+        }
+        pw.print(prefix); pw.print("mWallpaperTarget="); pw.println(mWallpaperTarget);
+        pw.print(prefix); pw.print("mWpAppAnimator="); pw.println(mWpAppAnimator);
+        if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
+            pw.print(prefix); pw.print("mLowerWallpaperTarget=");
+                    pw.println(mLowerWallpaperTarget);
+            pw.print(prefix); pw.print("mUpperWallpaperTarget=");
+                    pw.println(mUpperWallpaperTarget);
+        }
+        if (mUniverseBackground != null) {
+            pw.print(prefix); pw.print("mUniverseBackground="); pw.print(mUniverseBackground);
+                    pw.print(" mAboveUniverseLayer="); pw.println(mAboveUniverseLayer);
+        }
+    }
+
+    void clearPendingActions() {
+        synchronized (this) {
+            mPendingActions = 0;
+        }
+    }
+
+    void setPendingLayoutChanges(final int displayId, final int changes) {
+        mPendingLayoutChanges.put(displayId, mPendingLayoutChanges.get(displayId) | changes);
+    }
+
+    void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String s) {
+        // Used to track which displays layout changes have been done.
+        SparseIntArray displays = new SparseIntArray();
+        for (int i = appAnimator.mAllAppWinAnimators.size() - 1; i >= 0; i--) {
+            WindowStateAnimator winAnimator = appAnimator.mAllAppWinAnimators.get(i);
+            final int displayId = winAnimator.mWin.mDisplayContent.getDisplayId();
+            if (displays.indexOfKey(displayId) < 0) {
+                setPendingLayoutChanges(displayId, changes);
+                if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+                    mService.debugLayoutRepeats(s, mPendingLayoutChanges.get(displayId));
+                }
+                // Keep from processing this display again.
+                displays.put(displayId, changes);
             }
         }
     }
 
-    static class SetAnimationParams {
-        final WindowStateAnimator mWinAnimator;
-        final Animation mAnimation;
-        final int mAnimDw;
-        final int mAnimDh;
-        public SetAnimationParams(final WindowStateAnimator winAnimator,
-                                  final Animation animation, final int animDw, final int animDh) {
-            mWinAnimator = winAnimator;
-            mAnimation = animation;
-            mAnimDw = animDw;
-            mAnimDh = animDh;
+    private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) {
+        DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
+        if (displayAnimator == null) {
+            displayAnimator = new DisplayContentsAnimator(displayId);
+            mDisplayContentsAnimators.put(displayId, displayAnimator);
         }
+        return displayAnimator;
     }
 
-    synchronized void clearPendingActions() {
-        mPendingActions = 0;
+    void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) {
+        getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation;
+    }
+
+    ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) {
+        return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
+    }
+
+    private class DisplayContentsAnimator {
+        WinAnimatorList mWinAnimators = new WinAnimatorList();
+        DimAnimator mDimAnimator = null;
+        DimAnimator.Parameters mDimParams = null;
+        DimSurface mWindowAnimationBackgroundSurface = null;
+        ScreenRotationAnimation mScreenRotationAnimation = null;
+
+        public DisplayContentsAnimator(int displayId) {
+            mDimAnimator = new DimAnimator(mService.mFxSession, displayId);
+            mWindowAnimationBackgroundSurface =
+                    new DimSurface(mService.mFxSession, displayId);
+        }
     }
 }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 7011343..51edb44 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -18,19 +18,26 @@
 
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
 import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
+import static android.view.WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
 import com.android.internal.app.IBatteryStats;
@@ -42,12 +49,12 @@
 import com.android.internal.view.WindowManagerPolicyThread;
 import com.android.server.AttributeCache;
 import com.android.server.EventLogTags;
-import com.android.server.PowerManagerService;
 import com.android.server.Watchdog;
 import com.android.server.am.BatteryStatsService;
-import com.android.server.input.InputFilter;
+import com.android.server.display.DisplayManagerService;
 import com.android.server.input.InputManagerService;
-import com.android.server.pm.ShutdownThread;
+import com.android.server.power.PowerManagerService;
+import com.android.server.power.ShutdownThread;
 
 import android.Manifest;
 import android.app.ActivityManagerNative;
@@ -55,6 +62,7 @@
 import android.app.IActivityManager;
 import android.app.StatusBarManager;
 import android.app.admin.DevicePolicyManager;
+import android.animation.ValueAnimator;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -69,42 +77,46 @@
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.graphics.Region;
-import android.os.BatteryStats;
+import android.hardware.display.DisplayManager;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
-import android.os.LocalPowerManager;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
 import android.os.Process;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.os.TokenWatcher;
 import android.os.Trace;
+import android.os.WorkSource;
 import android.provider.Settings;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.FloatMath;
 import android.util.Log;
-import android.util.LogPrinter;
+import android.util.SparseArray;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseIntArray;
 import android.util.TypedValue;
 import android.view.Choreographer;
 import android.view.Display;
+import android.view.DisplayInfo;
 import android.view.Gravity;
 import android.view.IApplicationToken;
+import android.view.IDisplayContentChangeListener;
+import android.view.IInputFilter;
 import android.view.IOnKeyguardExitResult;
 import android.view.IRotationWatcher;
 import android.view.IWindow;
@@ -119,8 +131,10 @@
 import android.view.Surface;
 import android.view.SurfaceSession;
 import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.WindowInfo;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+import android.view.WindowManagerGlobal;
 import android.view.WindowManagerPolicy;
 import android.view.WindowManager.LayoutParams;
 import android.view.WindowManagerPolicy.FakeWindow;
@@ -131,6 +145,7 @@
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.view.animation.ScaleAnimation;
+import android.view.animation.Transformation;
 
 import java.io.BufferedWriter;
 import java.io.DataInputStream;
@@ -151,10 +166,12 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.NoSuchElementException;
 
 /** {@hide} */
 public class WindowManagerService extends IWindowManager.Stub
-        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
+        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs,
+                DisplayManagerService.WindowManagerFuncs, DisplayManager.DisplayListener {
     static final String TAG = "WindowManager";
     static final boolean DEBUG = false;
     static final boolean DEBUG_ADD_REMOVE = false;
@@ -175,6 +192,7 @@
     static final boolean DEBUG_STARTING_WINDOW = false;
     static final boolean DEBUG_REORDER = false;
     static final boolean DEBUG_WALLPAPER = false;
+    static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
     static final boolean DEBUG_DRAG = false;
     static final boolean DEBUG_SCREEN_ON = false;
     static final boolean DEBUG_SCREENSHOT = false;
@@ -247,6 +265,9 @@
      */
     static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
 
+    /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
+    static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
+
     /**
      * If true, the window manager will do its own custom freezing and general
      * management of the screen during rotation.
@@ -267,58 +288,27 @@
 
     private static final String SYSTEM_SECURE = "ro.secure";
     private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
-    private static final String SYSTEM_HEADLESS = "ro.config.headless";
 
-    /**
-     * Condition waited on by {@link #reenableKeyguard} to know the call to
-     * the window policy has finished.
-     * This is set to true only if mKeyguardTokenWatcher.acquired() has
-     * actually disabled the keyguard.
-     */
-    private boolean mKeyguardDisabled = false;
+    final private KeyguardDisableHandler mKeyguardDisableHandler;
 
     private final boolean mHeadless;
 
-    private static final int ALLOW_DISABLE_YES = 1;
-    private static final int ALLOW_DISABLE_NO = 0;
-    private static final int ALLOW_DISABLE_UNKNOWN = -1; // check with DevicePolicyManager
-    private int mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN; // sync'd by mKeyguardTokenWatcher
-
     private static final float THUMBNAIL_ANIMATION_DECELERATE_FACTOR = 1.5f;
 
-    final TokenWatcher mKeyguardTokenWatcher = new TokenWatcher(
-            new Handler(), "WindowManagerService.mKeyguardTokenWatcher") {
-        @Override
-        public void acquired() {
-            if (shouldAllowDisableKeyguard()) {
-                mPolicy.enableKeyguard(false);
-                mKeyguardDisabled = true;
-            } else {
-                Log.v(TAG, "Not disabling keyguard since device policy is enforced");
-            }
-        }
-        @Override
-        public void released() {
-            mPolicy.enableKeyguard(true);
-            synchronized (mKeyguardTokenWatcher) {
-                mKeyguardDisabled = false;
-                mKeyguardTokenWatcher.notifyAll();
-            }
-        }
-    };
-
     final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            mPolicy.enableKeyguard(true);
-            synchronized(mKeyguardTokenWatcher) {
-                // lazily evaluate this next time we're asked to disable keyguard
-                mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN;
-                mKeyguardDisabled = false;
+            final String action = intent.getAction();
+            if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
+                mKeyguardDisableHandler.sendEmptyMessage(
+                    KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED);
             }
         }
     };
 
+    // Current user when multi-user is enabled. Don't show windows of non-current user.
+    int mCurrentUserId;
+
     final Context mContext;
 
     final boolean mHaveInputMethods;
@@ -383,11 +373,6 @@
     final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
 
     /**
-     * Z-ordered (bottom-most first) list of all Window objects.
-     */
-    final ArrayList<WindowState> mWindows = new ArrayList<WindowState>();
-
-    /**
      * Fake windows added to the window manager.  Note: ordered from top to
      * bottom, opposite of mWindows.
      */
@@ -451,10 +436,9 @@
     Watermark mWatermark;
     StrictModeFlash mStrictModeFlash;
 
-    BlackFrame mBlackFrame;
-
     final float[] mTmpFloats = new float[9];
 
+    boolean mDisplayReady;
     boolean mSafeMode;
     boolean mDisplayEnabled = false;
     boolean mSystemBooted = false;
@@ -463,29 +447,8 @@
 
     String mLastANRState;
 
-    // This protects the following display size properties, so that
-    // getDisplaySize() doesn't need to acquire the global lock.  This is
-    // needed because the window manager sometimes needs to use ActivityThread
-    // while it has its global state locked (for example to load animation
-    // resources), but the ActivityThread also needs get the current display
-    // size sometimes when it has its package lock held.
-    //
-    // These will only be modified with both mWindowMap and mDisplaySizeLock
-    // held (in that order) so the window manager doesn't need to acquire this
-    // lock when needing these values in its normal operation.
-    final Object mDisplaySizeLock = new Object();
-    int mInitialDisplayWidth = 0;
-    int mInitialDisplayHeight = 0;
-    int mBaseDisplayWidth = 0;
-    int mBaseDisplayHeight = 0;
-    int mCurDisplayWidth = 0;
-    int mCurDisplayHeight = 0;
-    int mAppDisplayWidth = 0;
-    int mAppDisplayHeight = 0;
-    int mSmallestDisplayWidth = 0;
-    int mSmallestDisplayHeight = 0;
-    int mLargestDisplayWidth = 0;
-    int mLargestDisplayHeight = 0;
+    /** All DisplayDontents in the world, kept here */
+    private SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>();
 
     int mRotation = 0;
     int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -496,13 +459,13 @@
 
     final Rect mSystemDecorRect = new Rect();
     int mSystemDecorLayer = 0;
+    final Rect mScreenRect = new Rect();
 
-    int mPendingLayoutChanges = 0;
-    boolean mLayoutNeeded = true;
     boolean mTraversalScheduled = false;
     boolean mDisplayFrozen = false;
     boolean mWaitingForConfig = false;
     boolean mWindowsFreezingScreen = false;
+    boolean mClientFreezingScreen = false;
     int mAppsFreezingScreen = 0;
     int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 
@@ -512,9 +475,9 @@
 
     // State while inside of layoutAndPlaceSurfacesLocked().
     boolean mFocusMayChange;
-    
+
     Configuration mCurConfiguration = new Configuration();
-    
+
     // This is held as long as we have the screen frozen, to give us time to
     // perform a rotation animation when turning off shows the lock screen which
     // changes the orientation.
@@ -529,7 +492,8 @@
     int mNextAppTransitionType = ActivityOptions.ANIM_NONE;
     String mNextAppTransitionPackage;
     Bitmap mNextAppTransitionThumbnail;
-    boolean mNextAppTransitionDelayed;
+    // Used for thumbnail transitions. True if we're scaling up, false if scaling down
+    boolean mNextAppTransitionScaleUp;
     IRemoteCallback mNextAppTransitionCallback;
     int mNextAppTransitionEnter;
     int mNextAppTransitionExit;
@@ -545,8 +509,6 @@
     final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
     final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
 
-    Display mDisplay;
-
     boolean mIsTouchDevice;
 
     final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
@@ -586,7 +548,7 @@
     WindowState mLowerWallpaperTarget = null;
     // If non-null, we are in the middle of animating from one wallpaper target
     // to another, and this is the higher one in Z-order.
-    WindowState mUpperWallpaperTarget = null;
+    private WindowState mUpperWallpaperTarget = null;
     int mWallpaperAnimLayerAdjustment;
     float mLastWallpaperX = -1;
     float mLastWallpaperY = -1;
@@ -611,6 +573,8 @@
     float mAnimatorDurationScale = 1.0f;
 
     final InputManagerService mInputManager;
+    final DisplayManagerService mDisplayManagerService;
+    final DisplayManager mDisplayManager;
 
     // Who is holding the screen on.
     Session mHoldingScreenOn;
@@ -626,7 +590,7 @@
         static final int SET_UPDATE_ROTATION                = 1 << 0;
         static final int SET_WALLPAPER_MAY_CHANGE           = 1 << 1;
         static final int SET_FORCE_HIDING_CHANGED           = 1 << 2;
-        static final int CLEAR_ORIENTATION_CHANGE_COMPLETE  = 1 << 3;
+        static final int SET_ORIENTATION_CHANGE_COMPLETE    = 1 << 3;
         static final int SET_TURN_ON_SCREEN                 = 1 << 4;
 
         boolean mWallpaperForceHidingChanged = false;
@@ -639,9 +603,53 @@
         private boolean mSyswin = false;
         private float mScreenBrightness = -1;
         private float mButtonBrightness = -1;
+        private long mUserActivityTimeout = -1;
         private boolean mUpdateRotation = false;
+
+        private static final int DISPLAY_CONTENT_UNKNOWN = 0;
+        private static final int DISPLAY_CONTENT_MIRROR = 1;
+        private static final int DISPLAY_CONTENT_UNIQUE = 2;
+        private int mDisplayHasContent = DISPLAY_CONTENT_UNKNOWN;
     }
-    LayoutFields mInnerFields = new LayoutFields();
+    final LayoutFields mInnerFields = new LayoutFields();
+
+    static class AppWindowAnimParams {
+        AppWindowAnimator mAppAnimator;
+        ArrayList<WindowStateAnimator> mWinAnimators;
+
+        public AppWindowAnimParams(final AppWindowAnimator appAnimator) {
+            mAppAnimator = appAnimator;
+
+            final AppWindowToken atoken = appAnimator.mAppToken;
+            mWinAnimators = new ArrayList<WindowStateAnimator>();
+            final int N = atoken.allAppWindows.size();
+            for (int i = 0; i < N; i++) {
+                mWinAnimators.add(atoken.allAppWindows.get(i).mWinAnimator);
+            }
+        }
+    }
+
+    static class LayoutToAnimatorParams {
+        boolean mParamsModified;
+
+        static final long WALLPAPER_TOKENS_CHANGED = 1 << 0;
+        long mChanges;
+
+        boolean mAnimationScheduled;
+        SparseArray<WinAnimatorList> mWinAnimatorLists = new SparseArray<WinAnimatorList>();
+        WindowState mWallpaperTarget;
+        WindowState mLowerWallpaperTarget;
+        WindowState mUpperWallpaperTarget;
+        SparseArray<DimAnimator.Parameters> mDimParams = new SparseArray<DimAnimator.Parameters>();
+        ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
+        ArrayList<AppWindowAnimParams> mAppWindowAnimParams = new ArrayList<AppWindowAnimParams>();
+    }
+    /** Params from WindowManagerService to WindowAnimator. Do not modify or read without first
+     * locking on either mWindowMap or mAnimator and then on mLayoutToAnim */
+    final LayoutToAnimatorParams mLayoutToAnim = new LayoutToAnimatorParams();
+
+    /** The lowest wallpaper target with a detached wallpaper animation on it. */
+    WindowState mWindowDetachedWallpaper = null;
 
     /** 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. */
@@ -650,33 +658,6 @@
     /** Only do a maximum of 6 repeated layouts. After that quit */
     private int mLayoutRepeatCount;
 
-    private final class AnimationRunnable implements Runnable {
-        @Override
-        public void run() {
-            synchronized(mWindowMap) {
-                mAnimationScheduled = false;
-                // Update animations of all applications, including those
-                // associated with exiting/removed apps
-                synchronized (mAnimator) {
-                    Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmAnimate");
-                    final ArrayList<WindowStateAnimator> winAnimators = mAnimator.mWinAnimators;
-                    winAnimators.clear();
-                    final int N = mWindows.size();
-                    for (int i = 0; i < N; i++) {
-                        final WindowStateAnimator winAnimator = mWindows.get(i).mWinAnimator;
-                        if (winAnimator.mSurface != null) {
-                            winAnimators.add(winAnimator);
-                        }
-                    }
-                    mAnimator.animate();
-                    Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
-                }
-            }
-        }
-    }
-    final AnimationRunnable mAnimationRunnable = new AnimationRunnable();
-    boolean mAnimationScheduled;
-    
     final WindowAnimator mAnimator;
 
     final class DragInputEventReceiver extends InputEventReceiver {
@@ -748,6 +729,9 @@
      */
     boolean mInTouchMode = true;
 
+    // Temp regions for intermediary calculations.
+    private final Region mTempRegion = new Region();
+
     private ViewServer mViewServer;
     private ArrayList<WindowChangeListener> mWindowChangeListeners =
         new ArrayList<WindowChangeListener>();
@@ -768,111 +752,40 @@
     // For example, when this flag is true, there will be no wallpaper service.
     final boolean mOnlyCore;
 
-    public static WindowManagerService main(Context context,
-            PowerManagerService pm, boolean haveInputMethods, boolean allowBootMsgs,
-            boolean onlyCore) {
-        WMThread thr = new WMThread(context, pm, haveInputMethods, allowBootMsgs, onlyCore);
-        thr.start();
-
-        synchronized (thr) {
-            while (thr.mService == null) {
-                try {
-                    thr.wait();
-                } catch (InterruptedException e) {
-                }
+    public static WindowManagerService main(final Context context,
+            final PowerManagerService pm, final DisplayManagerService dm,
+            final InputManagerService im,
+            final Handler uiHandler, final Handler wmHandler,
+            final boolean haveInputMethods, final boolean showBootMsgs,
+            final boolean onlyCore) {
+        final WindowManagerService[] holder = new WindowManagerService[1];
+        wmHandler.runWithScissors(new Runnable() {
+            @Override
+            public void run() {
+                holder[0] = new WindowManagerService(context, pm, dm, im,
+                        uiHandler, haveInputMethods, showBootMsgs, onlyCore);
             }
-            return thr.mService;
-        }
+        }, 0);
+        return holder[0];
     }
 
-    static class WMThread extends Thread {
-        WindowManagerService mService;
+    private void initPolicy(Handler uiHandler) {
+        uiHandler.runWithScissors(new Runnable() {
+            @Override
+            public void run() {
+                WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
 
-        private final Context mContext;
-        private final PowerManagerService mPM;
-        private final boolean mHaveInputMethods;
-        private final boolean mAllowBootMessages;
-        private final boolean mOnlyCore;
-
-        public WMThread(Context context, PowerManagerService pm,
-                boolean haveInputMethods, boolean allowBootMsgs, boolean onlyCore) {
-            super("WindowManager");
-            mContext = context;
-            mPM = pm;
-            mHaveInputMethods = haveInputMethods;
-            mAllowBootMessages = allowBootMsgs;
-            mOnlyCore = onlyCore;
-        }
-
-        @Override
-        public void run() {
-            Looper.prepare();
-            //Looper.myLooper().setMessageLogging(new LogPrinter(
-            //        android.util.Log.DEBUG, TAG, android.util.Log.LOG_ID_SYSTEM));
-            WindowManagerService s = new WindowManagerService(mContext, mPM,
-                    mHaveInputMethods, mAllowBootMessages, mOnlyCore);
-            android.os.Process.setThreadPriority(
-                    android.os.Process.THREAD_PRIORITY_DISPLAY);
-            android.os.Process.setCanSelfBackground(false);
-
-            synchronized (this) {
-                mService = s;
-                notifyAll();
+                mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
+                mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer()
+                        * TYPE_LAYER_MULTIPLIER
+                        + TYPE_LAYER_OFFSET;
             }
-
-            // For debug builds, log event loop stalls to dropbox for analysis.
-            if (StrictMode.conditionallyEnableDebugLogging()) {
-                Slog.i(TAG, "Enabled StrictMode logging for WMThread's Looper");
-            }
-
-            Looper.loop();
-        }
-    }
-
-    static class PolicyThread extends Thread {
-        private final WindowManagerPolicy mPolicy;
-        private final WindowManagerService mService;
-        private final Context mContext;
-        private final PowerManagerService mPM;
-        boolean mRunning = false;
-
-        public PolicyThread(WindowManagerPolicy policy,
-                WindowManagerService service, Context context,
-                PowerManagerService pm) {
-            super("WindowManagerPolicy");
-            mPolicy = policy;
-            mService = service;
-            mContext = context;
-            mPM = pm;
-        }
-
-        @Override
-        public void run() {
-            Looper.prepare();
-            WindowManagerPolicyThread.set(this, Looper.myLooper());
-            
-            //Looper.myLooper().setMessageLogging(new LogPrinter(
-            //        Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM));
-            android.os.Process.setThreadPriority(
-                    android.os.Process.THREAD_PRIORITY_FOREGROUND);
-            android.os.Process.setCanSelfBackground(false);
-            mPolicy.init(mContext, mService, mService, mPM);
-
-            synchronized (this) {
-                mRunning = true;
-                notifyAll();
-            }
-
-            // For debug builds, log event loop stalls to dropbox for analysis.
-            if (StrictMode.conditionallyEnableDebugLogging()) {
-                Slog.i(TAG, "Enabled StrictMode for PolicyThread's Looper");
-            }
-
-            Looper.loop();
-        }
+        }, 0);
     }
 
     private WindowManagerService(Context context, PowerManagerService pm,
+            DisplayManagerService displayManager, InputManagerService inputManager,
+            Handler uiHandler,
             boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
         mContext = context;
         mHaveInputMethods = haveInputMethods;
@@ -880,7 +793,17 @@
         mOnlyCore = onlyCore;
         mLimitedAlphaCompositing = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_sf_limitedAlpha);
-        mHeadless = "1".equals(SystemProperties.get(SYSTEM_HEADLESS, "0"));
+        mDisplayManagerService = displayManager;
+        mHeadless = displayManager.isHeadless();
+
+        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
+        mDisplayManager.registerDisplayListener(this, null);
+        Display[] displays = mDisplayManager.getDisplays();
+        for (Display display : displays) {
+            createDisplayContentLocked(display);
+        }
+
+        mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
 
         mPowerManager = pm;
         mPowerManager.setPolicy(mPolicy);
@@ -893,12 +816,12 @@
         mBatteryStats = BatteryStatsService.getService();
 
         // Get persisted window scale setting
-        mWindowAnimationScale = Settings.System.getFloat(context.getContentResolver(),
-                Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
-        mTransitionAnimationScale = Settings.System.getFloat(context.getContentResolver(),
-                Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
-        mAnimatorDurationScale = Settings.System.getFloat(context.getContentResolver(),
-                Settings.System.ANIMATOR_DURATION_SCALE, mTransitionAnimationScale);
+        mWindowAnimationScale = Settings.Global.getFloat(context.getContentResolver(),
+                Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
+        mTransitionAnimationScale = Settings.Global.getFloat(context.getContentResolver(),
+                Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
+        setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
+                Settings.Global.ANIMATOR_DURATION_SCALE, mTransitionAnimationScale));
 
         // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
         IntentFilter filter = new IntentFilter();
@@ -906,37 +829,28 @@
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
         mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
-                | PowerManager.ON_AFTER_RELEASE, "KEEP_SCREEN_ON_FLAG");
+                | PowerManager.ON_AFTER_RELEASE, TAG);
         mHoldingScreenWakeLock.setReferenceCounted(false);
 
-        mInputManager = new InputManagerService(context, mInputMonitor);
-        mAnimator = new WindowAnimator(this, context, mPolicy);
+        mInputManager = inputManager;
+        mFxSession = new SurfaceSession();
+        mAnimator = new WindowAnimator(this);
 
-        PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
-        thr.start();
-
-        synchronized (thr) {
-            while (!thr.mRunning) {
-                try {
-                    thr.wait();
-                } catch (InterruptedException e) {
-                }
-            }
-        }
-
-        mInputManager.start();
+        initPolicy(uiHandler);
 
         // Add ourself to the Watchdog monitors.
         Watchdog.getInstance().addMonitor(this);
-        mFxSession = new SurfaceSession();
 
         Surface.openTransaction();
-        createWatermark();
-        Surface.closeTransaction();
+        try {
+            createWatermarkInTransaction();
+        } finally {
+            Surface.closeTransaction();
+        }
     }
 
-    public InputManagerService getInputManagerService() {
-        return mInputManager;
+    public InputMonitor getInputMonitor() {
+        return mInputMonitor;
     }
 
     @Override
@@ -955,34 +869,31 @@
     }
 
     private void placeWindowAfter(WindowState pos, WindowState window) {
-        final int i = mWindows.indexOf(pos);
+        final WindowList windows = pos.getWindowList();
+        final int i = windows.indexOf(pos);
         if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
             TAG, "Adding window " + window + " at "
-            + (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
-        mWindows.add(i+1, window);
+            + (i+1) + " of " + windows.size() + " (after " + pos + ")");
+        windows.add(i+1, window);
         mWindowsChanged = true;
     }
 
     private void placeWindowBefore(WindowState pos, WindowState window) {
-        final int i = mWindows.indexOf(pos);
+        final WindowList windows = pos.getWindowList();
+        final int i = windows.indexOf(pos);
         if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
             TAG, "Adding window " + window + " at "
-            + i + " of " + mWindows.size() + " (before " + pos + ")");
-        mWindows.add(i, window);
+            + i + " of " + windows.size() + " (before " + pos + ")");
+        windows.add(i, window);
         mWindowsChanged = true;
     }
 
     //This method finds out the index of a window that has the same app token as
     //win. used for z ordering the windows in mWindows
     private int findIdxBasedOnAppTokens(WindowState win) {
-        //use a local variable to cache mWindows
-        ArrayList<WindowState> localmWindows = mWindows;
-        int jmax = localmWindows.size();
-        if(jmax == 0) {
-            return -1;
-        }
-        for(int j = (jmax-1); j >= 0; j--) {
-            WindowState wentry = localmWindows.get(j);
+        WindowList windows = win.getWindowList();
+        for(int j = windows.size() - 1; j >= 0; j--) {
+            WindowState wentry = windows.get(j);
             if(wentry.mAppToken == win.mAppToken) {
                 return j;
             }
@@ -990,49 +901,76 @@
         return -1;
     }
 
+    /**
+     * Return the list of Windows from the passed token on the given Display.
+     * @param token The token with all the windows.
+     * @param displayContent The display we are interested in.
+     * @return List of windows from token that are on displayContent.
+     */
+    WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) {
+        final WindowList windowList = new WindowList();
+        final int count = token.windows.size();
+        for (int i = 0; i < count; i++) {
+            final WindowState win = token.windows.get(i);
+            if (win.mDisplayContent == displayContent) {
+                windowList.add(win);
+            }
+        }
+        return windowList;
+    }
+
     private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) {
         final IWindow client = win.mClient;
         final WindowToken token = win.mToken;
-        final ArrayList<WindowState> localmWindows = mWindows;
+        final DisplayContent displayContent = win.mDisplayContent;
 
-        final int N = localmWindows.size();
+        final WindowList windows = win.getWindowList();
+        final int N = windows.size();
         final WindowState attached = win.mAttachedWindow;
         int i;
+        WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
         if (attached == null) {
-            int tokenWindowsPos = token.windows.size();
+            int tokenWindowsPos = 0;
+            int windowListPos = tokenWindowList.size();
             if (token.appWindowToken != null) {
-                int index = tokenWindowsPos-1;
+                int index = windowListPos - 1;
                 if (index >= 0) {
                     // If this application has existing windows, we
                     // simply place the new window on top of them... but
                     // keep the starting window on top.
                     if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
                         // Base windows go behind everything else.
-                        placeWindowBefore(token.windows.get(0), win);
-                        tokenWindowsPos = 0;
+                        WindowState lowestWindow = tokenWindowList.get(0);
+                        placeWindowBefore(lowestWindow, win);
+                        tokenWindowsPos = token.windows.indexOf(lowestWindow);
                     } else {
                         AppWindowToken atoken = win.mAppToken;
-                        if (atoken != null &&
-                                token.windows.get(index) == atoken.startingWindow) {
-                            placeWindowBefore(token.windows.get(index), win);
-                            tokenWindowsPos--;
+                        WindowState lastWindow = tokenWindowList.get(index);
+                        if (atoken != null && lastWindow == atoken.startingWindow) {
+                            placeWindowBefore(lastWindow, win);
+                            tokenWindowsPos = token.windows.indexOf(lastWindow);
                         } else {
-                            int newIdx =  findIdxBasedOnAppTokens(win);
-                            if(newIdx != -1) {
-                                //there is a window above this one associated with the same
-                                //apptoken note that the window could be a floating window
-                                //that was created later or a window at the top of the list of
-                                //windows associated with this token.
-                                if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
-                                    Slog.v(TAG, "Adding window " + win + " at "
-                                            + (newIdx+1) + " of " + N);
-                                }
-                                localmWindows.add(newIdx+1, win);
-                                mWindowsChanged = true;
+                            int newIdx = findIdxBasedOnAppTokens(win);
+                            //there is a window above this one associated with the same
+                            //apptoken note that the window could be a floating window
+                            //that was created later or a window at the top of the list of
+                            //windows associated with this token.
+                            if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
+                                Slog.v(TAG, "Adding window " + win + " at "
+                                        + (newIdx + 1) + " of " + N);
                             }
+                            windows.add(newIdx + 1, win);
+                            if (newIdx < 0) {
+                                // No window from token found on win's display.
+                                tokenWindowsPos = 0;
+                            } else {
+                                tokenWindowsPos = token.windows.indexOf(windows.get(newIdx)) + 1;
+                            }
+                            mWindowsChanged = true;
                         }
                     }
                 } else {
+                    // No windows from this token on this display
                     if (localLOGV) Slog.v(
                         TAG, "Figuring out where to add app window "
                         + client.asBinder() + " (token=" + token + ")");
@@ -1048,10 +986,11 @@
                         }
 
                         // We haven't reached the token yet; if this token
-                        // is not going to the bottom and has windows, we can
+                        // is not going to the bottom and has windows on this display, we can
                         // use it as an anchor for when we do reach the token.
-                        if (!t.sendingToBottom && t.windows.size() > 0) {
-                            pos = t.windows.get(0);
+                        tokenWindowList = getTokenWindowsOnDisplay(t, win.mDisplayContent);
+                        if (!t.sendingToBottom && tokenWindowList.size() > 0) {
+                            pos = tokenWindowList.get(0);
                         }
                     }
                     // We now know the index into the apps.  If we found
@@ -1061,9 +1000,11 @@
                         // Move behind any windows attached to this one.
                         WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
                         if (atoken != null) {
-                            final int NC = atoken.windows.size();
+                            tokenWindowList =
+                                    getTokenWindowsOnDisplay(atoken, win.mDisplayContent);
+                            final int NC = tokenWindowList.size();
                             if (NC > 0) {
-                                WindowState bottom = atoken.windows.get(0);
+                                WindowState bottom = tokenWindowList.get(0);
                                 if (bottom.mSubLayer < 0) {
                                     pos = bottom;
                                 }
@@ -1072,12 +1013,13 @@
                         placeWindowBefore(pos, win);
                     } else {
                         // Continue looking down until we find the first
-                        // token that has windows.
+                        // token that has windows on this display.
                         while (i >= 0) {
                             AppWindowToken t = mAnimatingAppTokens.get(i);
-                            final int NW = t.windows.size();
+                            tokenWindowList = getTokenWindowsOnDisplay(t, win.mDisplayContent);
+                            final int NW = tokenWindowList.size();
                             if (NW > 0) {
-                                pos = t.windows.get(NW-1);
+                                pos = tokenWindowList.get(NW-1);
                                 break;
                             }
                             i--;
@@ -1100,7 +1042,7 @@
                             // Just search for the start of this layer.
                             final int myLayer = win.mBaseLayer;
                             for (i=0; i<N; i++) {
-                                WindowState w = localmWindows.get(i);
+                                WindowState w = windows.get(i);
                                 if (w.mBaseLayer > myLayer) {
                                     break;
                                 }
@@ -1109,7 +1051,7 @@
                                 Slog.v(TAG, "Adding window " + win + " at "
                                         + i + " of " + N);
                             }
-                            localmWindows.add(i, win);
+                            windows.add(i, win);
                             mWindowsChanged = true;
                         }
                     }
@@ -1118,18 +1060,18 @@
                 // Figure out where window should go, based on layer.
                 final int myLayer = win.mBaseLayer;
                 for (i=N-1; i>=0; i--) {
-                    if (localmWindows.get(i).mBaseLayer <= myLayer) {
-                        i++;
+                    if (windows.get(i).mBaseLayer <= myLayer) {
                         break;
                     }
                 }
-                if (i < 0) i = 0;
+                i++;
                 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
                         TAG, "Adding window " + win + " at "
                         + i + " of " + N);
-                localmWindows.add(i, win);
+                windows.add(i, win);
                 mWindowsChanged = true;
             }
+
             if (addToToken) {
                 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
                 token.windows.add(tokenWindowsPos, win);
@@ -1138,12 +1080,12 @@
         } else {
             // Figure out this window's ordering relative to the window
             // it is attached to.
-            final int NA = token.windows.size();
+            final int NA = tokenWindowList.size();
             final int sublayer = win.mSubLayer;
             int largestSublayer = Integer.MIN_VALUE;
             WindowState windowWithLargestSublayer = null;
             for (i=0; i<NA; i++) {
-                WindowState w = token.windows.get(i);
+                WindowState w = tokenWindowList.get(i);
                 final int wSublayer = w.mSubLayer;
                 if (wSublayer >= largestSublayer) {
                     largestSublayer = wSublayer;
@@ -1157,8 +1099,7 @@
                             if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
                             token.windows.add(i, win);
                         }
-                        placeWindowBefore(
-                            wSublayer >= 0 ? attached : w, win);
+                        placeWindowBefore(wSublayer >= 0 ? attached : w, win);
                         break;
                     }
                 } else {
@@ -1200,7 +1141,7 @@
         final int fl = w.mAttrs.flags
                 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
         if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)
-                || w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
+                || w.mAttrs.type == TYPE_APPLICATION_STARTING) {
             if (DEBUG_INPUT_METHOD) {
                 Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
                 if (!w.isVisibleOrAdding()) {
@@ -1226,13 +1167,16 @@
      * @return The index+1 in mWindows of the discovered target.
      */
     int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
-        final ArrayList<WindowState> localmWindows = mWindows;
-        final int N = localmWindows.size();
+        // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
+        // same display. Or even when the current IME/target are not on the same screen as the next
+        // IME/target. For now only look for input windows on the main screen.
+        WindowList windows = getDefaultWindowListLocked();
+        final int N = windows.size();
         WindowState w = null;
         int i = N;
         while (i > 0) {
             i--;
-            w = localmWindows.get(i);
+            w = windows.get(i);
 
             if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i
                     + " " + w + " fl=0x" + Integer.toHexString(w.mAttrs.flags));
@@ -1245,9 +1189,9 @@
                 // is not actually looking to move the IME, look down below
                 // for a real window to target...
                 if (!willMove
-                        && w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
+                        && w.mAttrs.type == TYPE_APPLICATION_STARTING
                         && i > 0) {
-                    WindowState wb = localmWindows.get(i-1);
+                    WindowState wb = windows.get(i-1);
                     if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
                         i--;
                         w = wb;
@@ -1267,34 +1211,33 @@
         // the IME shown: when the Dialog is dismissed, we want to keep
         // the IME above it until it is completely gone so it doesn't drop
         // behind the dialog or its full-screen scrim.
-        if (mInputMethodTarget != null && w != null
-                && mInputMethodTarget.isDisplayedLw()
-                && mInputMethodTarget.mExiting) {
-            if (mInputMethodTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
-                w = mInputMethodTarget;
-                i = localmWindows.indexOf(w);
-                if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, switching to: " + w);
-            }
+        final WindowState curTarget = mInputMethodTarget;
+        if (curTarget != null && w != null
+                && curTarget.isDisplayedLw()
+                && curTarget.isClosing()
+                && (curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
+            if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing");
+            return windows.indexOf(curTarget) + 1;
         }
 
         if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target="
                 + w + " willMove=" + willMove);
 
         if (willMove && w != null) {
-            final WindowState curTarget = mInputMethodTarget;
-            if (curTarget != null && curTarget.mAppToken != null) {
+            AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
+            if (token != null) {
 
                 // Now some fun for dealing with window animations that
                 // modify the Z order.  We need to look at all windows below
                 // the current target that are in this app, finding the highest
                 // visible one in layering.
-                AppWindowToken token = curTarget.mAppToken;
                 WindowState highestTarget = null;
                 int highestPos = 0;
                 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
-                    int pos = localmWindows.indexOf(curTarget);
+                    WindowList curWindows = curTarget.getWindowList();
+                    int pos = curWindows.indexOf(curTarget);
                     while (pos >= 0) {
-                        WindowState win = localmWindows.get(pos);
+                        WindowState win = curWindows.get(pos);
                         if (win.mAppToken != token) {
                             break;
                         }
@@ -1339,15 +1282,8 @@
         //Slog.i(TAG, "Placing input method @" + (i+1));
         if (w != null) {
             if (willMove) {
-                if (DEBUG_INPUT_METHOD) {
-                    RuntimeException e = null;
-                    if (!HIDE_STACK_CRAWLS) {
-                        e = new RuntimeException();
-                        e.fillInStackTrace();
-                    }
-                    Slog.w(TAG, "Moving IM target from "
-                            + mInputMethodTarget + " to " + w, e);
-                }
+                if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to "
+                        + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
                 mInputMethodTarget = w;
                 mInputMethodTargetWaitingAnim = false;
                 if (w.mAppToken != null) {
@@ -1359,15 +1295,8 @@
             return i+1;
         }
         if (willMove) {
-            if (DEBUG_INPUT_METHOD) {
-                RuntimeException e = null;
-                if (!HIDE_STACK_CRAWLS) {
-                    e = new RuntimeException();
-                    e.fillInStackTrace();
-                }
-                Slog.w(TAG, "Moving IM target from "
-                        + mInputMethodTarget + " to null", e);
-            }
+            if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null."
+                    + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
             mInputMethodTarget = null;
             setInputMethodAnimLayerAdjustment(0);
         }
@@ -1380,7 +1309,8 @@
             win.mTargetAppToken = mInputMethodTarget.mAppToken;
             if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
                     TAG, "Adding input method window " + win + " at " + pos);
-            mWindows.add(pos, win);
+            // TODO(multidisplay): IMEs are only supported on the default display.
+            getDefaultWindowListLocked().add(pos, win);
             mWindowsChanged = true;
             moveInputMethodDialogsLocked(pos+1);
             return;
@@ -1418,22 +1348,23 @@
     }
 
     private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
-        int wpos = mWindows.indexOf(win);
+        WindowList windows = win.getWindowList();
+        int wpos = windows.indexOf(win);
         if (wpos >= 0) {
             if (wpos < interestingPos) interestingPos--;
             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win);
-            mWindows.remove(wpos);
+            windows.remove(wpos);
             mWindowsChanged = true;
             int NC = win.mChildWindows.size();
             while (NC > 0) {
                 NC--;
                 WindowState cw = win.mChildWindows.get(NC);
-                int cpos = mWindows.indexOf(cw);
+                int cpos = windows.indexOf(cw);
                 if (cpos >= 0) {
                     if (cpos < interestingPos) interestingPos--;
                     if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at "
                             + cpos + ": " + cw);
-                    mWindows.remove(cpos);
+                    windows.remove(cpos);
                 }
             }
         }
@@ -1445,27 +1376,29 @@
         // This is a hack to get all of the child windows added as well
         // at the right position.  Child windows should be rare and
         // this case should be rare, so it shouldn't be that big a deal.
-        int wpos = mWindows.indexOf(win);
+        WindowList windows = win.getWindowList();
+        int wpos = windows.indexOf(win);
         if (wpos >= 0) {
-            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos
-                    + ": " + win);
-            mWindows.remove(wpos);
+            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win);
+            windows.remove(wpos);
             mWindowsChanged = true;
             reAddWindowLocked(wpos, win);
         }
     }
 
-    void logWindowList(String prefix) {
-        int N = mWindows.size();
+    void logWindowList(final WindowList windows, String prefix) {
+        int N = windows.size();
         while (N > 0) {
             N--;
-            Slog.v(TAG, prefix + "#" + N + ": " + mWindows.get(N));
+            Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N));
         }
     }
 
     void moveInputMethodDialogsLocked(int pos) {
         ArrayList<WindowState> dialogs = mInputMethodDialogs;
 
+        // TODO(multidisplay): IMEs are only supported on the default display.
+        WindowList windows = getDefaultWindowListLocked();
         final int N = dialogs.size();
         if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
         for (int i=0; i<N; i++) {
@@ -1473,13 +1406,13 @@
         }
         if (DEBUG_INPUT_METHOD) {
             Slog.v(TAG, "Window list w/pos=" + pos);
-            logWindowList("  ");
+            logWindowList(windows, "  ");
         }
 
         if (pos >= 0) {
             final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
-            if (pos < mWindows.size()) {
-                WindowState wp = mWindows.get(pos);
+            if (pos < windows.size()) {
+                WindowState wp = windows.get(pos);
                 if (wp == mInputMethodWindow) {
                     pos++;
                 }
@@ -1492,7 +1425,7 @@
             }
             if (DEBUG_INPUT_METHOD) {
                 Slog.v(TAG, "Final window list:");
-                logWindowList("  ");
+                logWindowList(windows, "  ");
             }
             return;
         }
@@ -1502,7 +1435,7 @@
             reAddWindowToListInOrderLocked(win);
             if (DEBUG_INPUT_METHOD) {
                 Slog.v(TAG, "No IM target, final list:");
-                logWindowList("  ");
+                logWindowList(windows, "  ");
             }
         }
     }
@@ -1514,6 +1447,9 @@
             return false;
         }
 
+        // TODO(multidisplay): IMEs are only supported on the default display.
+        WindowList windows = getDefaultWindowListLocked();
+
         int imPos = findDesiredInputMethodWindowIndexLocked(true);
         if (imPos >= 0) {
             // In this case, the input method windows are to be placed
@@ -1521,9 +1457,9 @@
 
             // First check to see if the input method windows are already
             // located here, and contiguous.
-            final int N = mWindows.size();
+            final int N = windows.size();
             WindowState firstImWin = imPos < N
-                    ? mWindows.get(imPos) : null;
+                    ? windows.get(imPos) : null;
 
             // Figure out the actual input method window that should be
             // at the bottom of their stack.
@@ -1539,7 +1475,7 @@
                 // First find the top IM window.
                 int pos = imPos+1;
                 while (pos < N) {
-                    if (!(mWindows.get(pos)).mIsImWindow) {
+                    if (!(windows.get(pos)).mIsImWindow) {
                         break;
                     }
                     pos++;
@@ -1547,7 +1483,7 @@
                 pos++;
                 // Now there should be no more input method windows above.
                 while (pos < N) {
-                    if ((mWindows.get(pos)).mIsImWindow) {
+                    if ((windows.get(pos)).mIsImWindow) {
                         break;
                     }
                     pos++;
@@ -1561,18 +1497,18 @@
             if (imWin != null) {
                 if (DEBUG_INPUT_METHOD) {
                     Slog.v(TAG, "Moving IM from " + imPos);
-                    logWindowList("  ");
+                    logWindowList(windows, "  ");
                 }
                 imPos = tmpRemoveWindowLocked(imPos, imWin);
                 if (DEBUG_INPUT_METHOD) {
                     Slog.v(TAG, "List after removing with new pos " + imPos + ":");
-                    logWindowList("  ");
+                    logWindowList(windows, "  ");
                 }
                 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
                 reAddWindowLocked(imPos, imWin);
                 if (DEBUG_INPUT_METHOD) {
                     Slog.v(TAG, "List after moving IM to " + imPos + ":");
-                    logWindowList("  ");
+                    logWindowList(windows, "  ");
                 }
                 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
             } else {
@@ -1590,17 +1526,17 @@
                 reAddWindowToListInOrderLocked(imWin);
                 if (DEBUG_INPUT_METHOD) {
                     Slog.v(TAG, "List with no IM target:");
-                    logWindowList("  ");
+                    logWindowList(windows, "  ");
                 }
-                if (DN > 0) moveInputMethodDialogsLocked(-1);;
+                if (DN > 0) moveInputMethodDialogsLocked(-1);
             } else {
-                moveInputMethodDialogsLocked(-1);;
+                moveInputMethodDialogsLocked(-1);
             }
 
         }
 
         if (needAssignLayers) {
-            assignLayersLocked();
+            assignLayersLocked(windows);
         }
 
         return true;
@@ -1630,14 +1566,17 @@
     int adjustWallpaperWindowsLocked() {
         mInnerFields.mWallpaperMayChange = false;
         int changed = 0;
+        boolean targetChanged = false;
 
-        final int dw = mAppDisplayWidth;
-        final int dh = mAppDisplayHeight;
+        // TODO(multidisplay): Wallpapers on main screen only.
+        final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo();
+        final int dw = displayInfo.appWidth;
+        final int dh = displayInfo.appHeight;
 
         // First find top-most window that has asked to be on top of the
         // wallpaper; all wallpapers go behind it.
-        final ArrayList<WindowState> localmWindows = mWindows;
-        int N = localmWindows.size();
+        final WindowList windows = getDefaultWindowListLocked();
+        int N = windows.size();
         WindowState w = null;
         WindowState foundW = null;
         int foundI = 0;
@@ -1647,8 +1586,8 @@
         int i = N;
         while (i > 0) {
             i--;
-            w = localmWindows.get(i);
-            if ((w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER)) {
+            w = windows.get(i);
+            if ((w.mAttrs.type == TYPE_WALLPAPER)) {
                 if (topCurW == null) {
                     topCurW = w;
                     topCurI = i;
@@ -1656,7 +1595,7 @@
                 continue;
             }
             topCurW = null;
-            if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
+            if (w != mWindowDetachedWallpaper && w.mAppToken != null) {
                 // If this window's app token is hidden and not animating,
                 // it is of no interest to us.
                 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
@@ -1670,7 +1609,7 @@
             if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay()
                     && (mWallpaperTarget == w || w.isDrawnLw())) {
                 if (DEBUG_WALLPAPER) Slog.v(TAG,
-                        "Found wallpaper activity: #" + i + "=" + w);
+                        "Found wallpaper target: #" + i + "=" + w);
                 foundW = w;
                 foundI = i;
                 if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) {
@@ -1682,13 +1621,13 @@
                     continue;
                 }
                 break;
-            } else if (w == mAnimator.mWindowDetachedWallpaper) {
+            } else if (w == mWindowDetachedWallpaper) {
                 windowDetachedI = i;
             }
         }
 
         if (foundW == null && windowDetachedI >= 0) {
-            if (DEBUG_WALLPAPER) Slog.v(TAG,
+            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
                     "Found animating detached wallpaper activity: #" + i + "=" + w);
             foundW = w;
             foundI = windowDetachedI;
@@ -1704,19 +1643,20 @@
             // enough (we'll just wait until whatever transition is pending
             // executes).
             if (mWallpaperTarget != null && mWallpaperTarget.mAppToken != null) {
-                if (DEBUG_WALLPAPER) Slog.v(TAG,
+                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
                         "Wallpaper not changing: waiting for app anim in current target");
                 return 0;
             }
             if (foundW != null && foundW.mAppToken != null) {
-                if (DEBUG_WALLPAPER) Slog.v(TAG,
+                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
                         "Wallpaper not changing: waiting for app anim in found target");
                 return 0;
             }
         }
 
-        if (mWallpaperTarget != foundW) {
-            if (DEBUG_WALLPAPER) {
+        if (mWallpaperTarget != foundW
+                && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) {
+            if (DEBUG_WALLPAPER_LIGHT) {
                 Slog.v(TAG, "New wallpaper target: " + foundW
                         + " oldTarget: " + mWallpaperTarget);
             }
@@ -1726,6 +1666,7 @@
 
             WindowState oldW = mWallpaperTarget;
             mWallpaperTarget = foundW;
+            targetChanged = true;
 
             // Now what is happening...  if the current and new targets are
             // animating, then we are in our super special mode!
@@ -1736,17 +1677,17 @@
                 boolean foundAnim = foundW.mWinAnimator.mAnimation != null
                         || (foundW.mAppToken != null &&
                             foundW.mAppToken.mAppAnimator.animation != null);
-                if (DEBUG_WALLPAPER) {
+                if (DEBUG_WALLPAPER_LIGHT) {
                     Slog.v(TAG, "New animation: " + foundAnim
                             + " old animation: " + oldAnim);
                 }
                 if (foundAnim && oldAnim) {
-                    int oldI = localmWindows.indexOf(oldW);
-                    if (DEBUG_WALLPAPER) {
+                    int oldI = windows.indexOf(oldW);
+                    if (DEBUG_WALLPAPER_LIGHT) {
                         Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
                     }
                     if (oldI >= 0) {
-                        if (DEBUG_WALLPAPER) {
+                        if (DEBUG_WALLPAPER_LIGHT) {
                             Slog.v(TAG, "Animating wallpapers: old#" + oldI
                                     + "=" + oldW + "; new#" + foundI
                                     + "=" + foundW);
@@ -1754,19 +1695,19 @@
 
                         // Set the new target correctly.
                         if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
-                            if (DEBUG_WALLPAPER) {
+                            if (DEBUG_WALLPAPER_LIGHT) {
                                 Slog.v(TAG, "Old wallpaper still the target.");
                             }
                             mWallpaperTarget = oldW;
                             foundW = oldW;
                             foundI = oldI;
-                        } 
+                        }
                         // Now set the upper and lower wallpaper targets
                         // correctly, and make sure that we are positioning
                         // the wallpaper below the lower.
                         else if (foundI > oldI) {
                             // The new target is on top of the old one.
-                            if (DEBUG_WALLPAPER) {
+                            if (DEBUG_WALLPAPER_LIGHT) {
                                 Slog.v(TAG, "Found target above old target.");
                             }
                             mUpperWallpaperTarget = foundW;
@@ -1775,7 +1716,7 @@
                             foundI = oldI;
                         } else {
                             // The new target is below the old one.
-                            if (DEBUG_WALLPAPER) {
+                            if (DEBUG_WALLPAPER_LIGHT) {
                                 Slog.v(TAG, "Found target below old target.");
                             }
                             mUpperWallpaperTarget = oldW;
@@ -1794,11 +1735,13 @@
                     || (mUpperWallpaperTarget.mAppToken != null
                             && mUpperWallpaperTarget.mAppToken.mAppAnimator.animation != null);
             if (!lowerAnimating || !upperAnimating) {
-                if (DEBUG_WALLPAPER) {
+                if (DEBUG_WALLPAPER_LIGHT) {
                     Slog.v(TAG, "No longer animating wallpaper targets!");
                 }
                 mLowerWallpaperTarget = null;
                 mUpperWallpaperTarget = null;
+                mWallpaperTarget = foundW;
+                targetChanged = true;
             }
         }
 
@@ -1825,7 +1768,7 @@
             // AND any starting window associated with it, AND below the
             // maximum layer the policy allows for wallpapers.
             while (foundI > 0) {
-                WindowState wb = localmWindows.get(foundI-1);
+                WindowState wb = windows.get(foundI-1);
                 if (wb.mBaseLayer < maxLayer &&
                         wb.mAttachedWindow != foundW &&
                         (foundW.mAttachedWindow == null ||
@@ -1851,7 +1794,7 @@
         } else {
             // Okay i is the position immediately above the wallpaper.  Look at
             // what is below it for later.
-            foundW = foundI > 0 ? localmWindows.get(foundI-1) : null;
+            foundW = foundI > 0 ? windows.get(foundI-1) : null;
         }
 
         if (visible) {
@@ -1872,11 +1815,13 @@
             curTokenIndex--;
             WindowToken token = mWallpaperTokens.get(curTokenIndex);
             if (token.hidden == visible) {
+                if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
+                        "Wallpaper token " + token + " hidden=" + !visible);
                 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
                 token.hidden = !visible;
                 // Need to do a layout to ensure the wallpaper now has the
                 // correct size.
-                mLayoutNeeded = true;
+                getDefaultDisplayContentLocked().layoutNeeded = true;
             }
 
             int curWallpaperIndex = token.windows.size();
@@ -1893,7 +1838,7 @@
                 dispatchWallpaperVisibility(wallpaper, visible);
 
                 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
-                if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "adjustWallpaper win "
+                if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
                         + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
 
                 // First, if this window is at the current index, then all
@@ -1901,18 +1846,18 @@
                 if (wallpaper == foundW) {
                     foundI--;
                     foundW = foundI > 0
-                            ? localmWindows.get(foundI-1) : null;
+                            ? windows.get(foundI-1) : null;
                     continue;
                 }
 
                 // The window didn't match...  the current wallpaper window,
                 // wherever it is, is in the wrong place, so make sure it is
                 // not in the list.
-                int oldIndex = localmWindows.indexOf(wallpaper);
+                int oldIndex = windows.indexOf(wallpaper);
                 if (oldIndex >= 0) {
                     if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
                             + oldIndex + ": " + wallpaper);
-                    localmWindows.remove(oldIndex);
+                    windows.remove(oldIndex);
                     mWindowsChanged = true;
                     if (oldIndex < foundI) {
                         foundI--;
@@ -1920,17 +1865,23 @@
                 }
 
                 // Now stick it in.
-                if (DEBUG_WALLPAPER || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
+                if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
                     Slog.v(TAG, "Moving wallpaper " + wallpaper
                             + " from " + oldIndex + " to " + foundI);
                 }
 
-                localmWindows.add(foundI, wallpaper);
+                windows.add(foundI, wallpaper);
                 mWindowsChanged = true;
                 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
             }
         }
 
+        if (targetChanged && DEBUG_WALLPAPER_LIGHT) {
+            Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget
+                    + " lower=" + mLowerWallpaperTarget + " upper="
+                    + mUpperWallpaperTarget);
+        }
+
         return changed;
     }
 
@@ -2040,14 +1991,11 @@
         }
     }
 
-    // TODO(cmautner):  Move to WindowAnimator.
-    void setWallpaperOffset(final WindowStateAnimator winAnimator, final int left, final int top) {
-        mH.sendMessage(mH.obtainMessage(H.SET_WALLPAPER_OFFSET, left, top, winAnimator));
-    }
-
     void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
-        final int dw = mAppDisplayWidth;
-        final int dh = mAppDisplayHeight;
+        final DisplayContent displayContent = changingTarget.mDisplayContent;
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final int dw = displayInfo.appWidth;
+        final int dh = displayInfo.appHeight;
 
         WindowState target = mWallpaperTarget;
         if (target != null) {
@@ -2079,19 +2027,8 @@
                     // TODO(cmautner): Don't move this from here, just lock the WindowAnimator.
                     if (winAnimator.mSurfaceX != wallpaper.mShownFrame.left
                             || winAnimator.mSurfaceY != wallpaper.mShownFrame.top) {
-                        Surface.openTransaction();
-                        try {
-                            if (SHOW_TRANSACTIONS) logSurface(wallpaper,
-                                    "POS " + wallpaper.mShownFrame.left
-                                    + ", " + wallpaper.mShownFrame.top, null);
-                            setWallpaperOffset(winAnimator, (int) wallpaper.mShownFrame.left,
+                        winAnimator.setWallpaperOffset((int) wallpaper.mShownFrame.left,
                                 (int) wallpaper.mShownFrame.top);
-                        } catch (RuntimeException e) {
-                            Slog.w(TAG, "Error positioning surface of " + wallpaper
-                                    + " pos=(" + wallpaper.mShownFrame.left
-                                    + "," + wallpaper.mShownFrame.top + ")", e);
-                        }
-                        Surface.closeTransaction();
                     }
                     // We only want to be synchronous with one wallpaper.
                     sync = false;
@@ -2109,9 +2046,9 @@
         if (wallpaper.mWallpaperVisible != visible) {
             wallpaper.mWallpaperVisible = visible;
             try {
-                if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG,
-                        "Updating visibility of wallpaper " + wallpaper
-                        + ": " + visible + " Callers=" + Debug.getCallers(2));
+                if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+                        "Updating vis of wallpaper " + wallpaper
+                        + ": " + visible + " from:\n" + Debug.getCallers(4, "  "));
                 wallpaper.mClient.dispatchAppVisibility(visible);
             } catch (RemoteException e) {
             }
@@ -2120,8 +2057,10 @@
 
     void updateWallpaperVisibilityLocked() {
         final boolean visible = isWallpaperVisible(mWallpaperTarget);
-        final int dw = mAppDisplayWidth;
-        final int dh = mAppDisplayHeight;
+        final DisplayContent displayContent = mWallpaperTarget.mDisplayContent;
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final int dw = displayInfo.appWidth;
+        final int dh = displayInfo.appHeight;
 
         int curTokenIndex = mWallpaperTokens.size();
         while (curTokenIndex > 0) {
@@ -2131,7 +2070,7 @@
                 token.hidden = !visible;
                 // Need to do a layout to ensure the wallpaper now has the
                 // correct size.
-                mLayoutNeeded = true;
+                getDefaultDisplayContentLocked().layoutNeeded = true;
             }
 
             int curWallpaperIndex = token.windows.size();
@@ -2146,12 +2085,12 @@
             }
         }
     }
-    
+
     public int addWindow(Session session, IWindow client, int seq,
-            WindowManager.LayoutParams attrs, int viewVisibility,
+            WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
             Rect outContentInsets, InputChannel outInputChannel) {
         int res = mPolicy.checkAddPermission(attrs);
-        if (res != WindowManagerImpl.ADD_OKAY) {
+        if (res != WindowManagerGlobal.ADD_OKAY) {
             return res;
         }
 
@@ -2159,126 +2098,131 @@
         WindowState attachedWindow = null;
         WindowState win = null;
         long origId;
+        final int type = attrs.type;
 
         synchronized(mWindowMap) {
-            if (mDisplay == null) {
+            if (!mDisplayReady) {
                 throw new IllegalStateException("Display has not been initialialized");
             }
 
+            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            if (displayContent == null) {
+                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
+            }
+
             if (mWindowMap.containsKey(client.asBinder())) {
                 Slog.w(TAG, "Window " + client + " is already added");
-                return WindowManagerImpl.ADD_DUPLICATE_ADD;
+                return WindowManagerGlobal.ADD_DUPLICATE_ADD;
             }
 
-            if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {
+            if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
                 attachedWindow = windowForClientLocked(null, attrs.token, false);
                 if (attachedWindow == null) {
                     Slog.w(TAG, "Attempted to add window with token that is not a window: "
                           + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
                 }
                 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
                         && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
                     Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
                             + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
                 }
             }
 
             boolean addToken = false;
             WindowToken token = mTokenMap.get(attrs.token);
             if (token == null) {
-                if (attrs.type >= FIRST_APPLICATION_WINDOW
-                        && attrs.type <= LAST_APPLICATION_WINDOW) {
+                if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
                     Slog.w(TAG, "Attempted to add application window with unknown token "
                           + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
-                if (attrs.type == TYPE_INPUT_METHOD) {
+                if (type == TYPE_INPUT_METHOD) {
                     Slog.w(TAG, "Attempted to add input method window with unknown token "
                           + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
-                if (attrs.type == TYPE_WALLPAPER) {
+                if (type == TYPE_WALLPAPER) {
                     Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
                           + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
-                if (attrs.type == TYPE_DREAM) {
+                if (type == TYPE_DREAM) {
                     Slog.w(TAG, "Attempted to add Dream window with unknown token "
                           + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
                 token = new WindowToken(this, attrs.token, -1, false);
                 addToken = true;
-            } else if (attrs.type >= FIRST_APPLICATION_WINDOW
-                    && attrs.type <= LAST_APPLICATION_WINDOW) {
+            } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
                 AppWindowToken atoken = token.appWindowToken;
                 if (atoken == null) {
                     Slog.w(TAG, "Attempted to add window with non-application token "
                           + token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_NOT_APP_TOKEN;
+                    return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
                 } else if (atoken.removed) {
                     Slog.w(TAG, "Attempted to add window with exiting application token "
                           + token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_APP_EXITING;
+                    return WindowManagerGlobal.ADD_APP_EXITING;
                 }
-                if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
+                if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
                     // No need for this guy!
                     if (localLOGV) Slog.v(
                             TAG, "**** NO NEED TO START: " + attrs.getTitle());
-                    return WindowManagerImpl.ADD_STARTING_NOT_NEEDED;
+                    return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
                 }
-            } else if (attrs.type == TYPE_INPUT_METHOD) {
+            } else if (type == TYPE_INPUT_METHOD) {
                 if (token.windowType != TYPE_INPUT_METHOD) {
                     Slog.w(TAG, "Attempted to add input method window with bad token "
                             + attrs.token + ".  Aborting.");
-                      return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
-            } else if (attrs.type == TYPE_WALLPAPER) {
+            } else if (type == TYPE_WALLPAPER) {
                 if (token.windowType != TYPE_WALLPAPER) {
                     Slog.w(TAG, "Attempted to add wallpaper window with bad token "
                             + attrs.token + ".  Aborting.");
-                      return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
-            } else if (attrs.type == TYPE_DREAM) {
+            } else if (type == TYPE_DREAM) {
                 if (token.windowType != TYPE_DREAM) {
                     Slog.w(TAG, "Attempted to add Dream window with bad token "
                             + attrs.token + ".  Aborting.");
-                      return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
             }
 
             win = new WindowState(this, session, client, token,
-                    attachedWindow, seq, attrs, viewVisibility);
+                    attachedWindow, seq, attrs, viewVisibility, displayContent);
             if (win.mDeathRecipient == null) {
                 // Client has apparently died, so there is no reason to
                 // continue.
                 Slog.w(TAG, "Adding window client " + client.asBinder()
                         + " that is dead, aborting.");
-                return WindowManagerImpl.ADD_APP_EXITING;
+                return WindowManagerGlobal.ADD_APP_EXITING;
             }
 
             mPolicy.adjustWindowParamsLw(win.mAttrs);
+            win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
 
             res = mPolicy.prepareAddWindowLw(win, attrs);
-            if (res != WindowManagerImpl.ADD_OKAY) {
+            if (res != WindowManagerGlobal.ADD_OKAY) {
                 return res;
             }
-            
+
             if (outInputChannel != null && (attrs.inputFeatures
                     & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                 String name = win.makeInputChannelName();
                 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
                 win.setInputChannel(inputChannels[0]);
                 inputChannels[1].transferTo(outInputChannel);
-                
+
                 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
             }
 
             // From now on, no exceptions or errors allowed!
 
-            res = WindowManagerImpl.ADD_OKAY;
+            res = WindowManagerGlobal.ADD_OKAY;
 
             origId = Binder.clearCallingIdentity();
 
@@ -2288,8 +2232,7 @@
             win.attach();
             mWindowMap.put(client.asBinder(), win);
 
-            if (attrs.type == TYPE_APPLICATION_STARTING &&
-                    token.appWindowToken != null) {
+            if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) {
                 token.appWindowToken.startingWindow = win;
                 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken
                         + " startingWindow=" + win);
@@ -2297,35 +2240,47 @@
 
             boolean imMayMove = true;
 
-            if (attrs.type == TYPE_INPUT_METHOD) {
+            if (type == TYPE_INPUT_METHOD) {
                 win.mGivenInsetsPending = true;
                 mInputMethodWindow = win;
                 addInputMethodWindowToListLocked(win);
                 imMayMove = false;
-            } else if (attrs.type == TYPE_INPUT_METHOD_DIALOG) {
+            } else if (type == TYPE_INPUT_METHOD_DIALOG) {
                 mInputMethodDialogs.add(win);
                 addWindowToListInOrderLocked(win, true);
                 adjustInputMethodDialogsLocked();
                 imMayMove = false;
             } else {
                 addWindowToListInOrderLocked(win, true);
-                if (attrs.type == TYPE_WALLPAPER) {
+                if (type == TYPE_WALLPAPER) {
                     mLastWallpaperTimeoutTime = 0;
                     adjustWallpaperWindowsLocked();
                 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
                     adjustWallpaperWindowsLocked();
+                } else if (mWallpaperTarget != null
+                        && mWallpaperTarget.mLayer >= win.mBaseLayer) {
+                    // If there is currently a wallpaper being shown, and
+                    // the base layer of the new window is below the current
+                    // layer of the target window, then adjust the wallpaper.
+                    // This is to avoid a new window being placed between the
+                    // wallpaper and its target.
+                    adjustWallpaperWindowsLocked();
                 }
             }
 
             win.mWinAnimator.mEnterAnimationPending = true;
 
-            mPolicy.getContentInsetHintLw(attrs, outContentInsets);
+            if (displayContent.isDefaultDisplay) {
+                mPolicy.getContentInsetHintLw(attrs, outContentInsets);
+            } else {
+                outContentInsets.setEmpty();
+            }
 
             if (mInTouchMode) {
-                res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE;
+                res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
             }
             if (win.mAppToken == null || !win.mAppToken.clientHidden) {
-                res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE;
+                res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
             }
 
             mInputMonitor.setUpdateInputWindowsNeededLw();
@@ -2343,7 +2298,7 @@
                 moveInputMethodWindowsIfNeededLocked(false);
             }
 
-            assignLayersLocked();
+            assignLayersLocked(displayContent.getWindowList());
             // Don't do layout here, the window must call
             // relayout to be displayed, so we'll do it there.
 
@@ -2357,7 +2312,7 @@
             if (localLOGV) Slog.v(
                 TAG, "New client " + client.asBinder()
                 + ": window=" + win);
-            
+
             if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
                 reportNewConfig = true;
             }
@@ -2423,13 +2378,14 @@
                 if (win.mWinAnimator.applyAnimationLocked(transit, false)) {
                     win.mExiting = true;
                 }
+                scheduleNotifyWindowTranstionIfNeededLocked(win, transit);
             }
             if (win.mExiting || win.mWinAnimator.isAnimating()) {
                 // The exit animation is running... wait for it!
                 //Slog.i(TAG, "*** Running exit animation...");
                 win.mExiting = true;
                 win.mRemoveOnExit = true;
-                mLayoutNeeded = true;
+                win.mDisplayContent.layoutNeeded = true;
                 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
                         false /*updateInputWindows*/);
                 performLayoutAndPlaceSurfacesLocked();
@@ -2485,8 +2441,11 @@
 
         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win);
         mWindowMap.remove(win.mClient.asBinder());
-        mWindows.remove(win);
+
+        final WindowList windows = win.getWindowList();
+        windows.remove(win);
         mPendingRemove.remove(win);
+        mResizingWindows.remove(win);
         mWindowsChanged = true;
         if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
 
@@ -2543,14 +2502,14 @@
         }
 
         if (!mInLayout) {
-            assignLayersLocked();
-            mLayoutNeeded = true;
+            assignLayersLocked(windows);
+            win.mDisplayContent.layoutNeeded = true;
             performLayoutAndPlaceSurfacesLocked();
             if (win.mAppToken != null) {
                 win.mAppToken.updateReportedVisibilityLocked();
             }
         }
-        
+
         mInputMonitor.updateInputWindowsLw(true /*force*/);
     }
 
@@ -2610,7 +2569,7 @@
                         w.mGivenVisibleInsets.scale(w.mGlobalScale);
                         w.mGivenTouchableRegion.scale(w.mGlobalScale);
                     }
-                    mLayoutNeeded = true;
+                    w.mDisplayContent.layoutNeeded = true;
                     performLayoutAndPlaceSurfacesLocked();
                 }
             }
@@ -2683,6 +2642,80 @@
         return null;
     }
 
+    public void setUniverseTransformLocked(WindowState window, float alpha,
+            float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) {
+        Transformation transform = window.mWinAnimator.mUniverseTransform;
+        transform.setAlpha(alpha);
+        Matrix matrix = transform.getMatrix();
+        matrix.getValues(mTmpFloats);
+        mTmpFloats[Matrix.MTRANS_X] = offx;
+        mTmpFloats[Matrix.MTRANS_Y] = offy;
+        mTmpFloats[Matrix.MSCALE_X] = dsdx;
+        mTmpFloats[Matrix.MSKEW_Y] = dtdx;
+        mTmpFloats[Matrix.MSKEW_X] = dsdy;
+        mTmpFloats[Matrix.MSCALE_Y] = dtdy;
+        matrix.setValues(mTmpFloats);
+        final DisplayInfo displayInfo = window.mDisplayContent.getDisplayInfo();
+        final RectF dispRect = new RectF(0, 0,
+                displayInfo.logicalWidth, displayInfo.logicalHeight);
+        matrix.mapRect(dispRect);
+        window.mGivenTouchableRegion.set(0, 0,
+                displayInfo.logicalWidth, displayInfo.logicalHeight);
+        window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top,
+                (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE);
+        window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
+        window.mDisplayContent.layoutNeeded = true;
+        performLayoutAndPlaceSurfacesLocked();
+    }
+
+    public void onRectangleOnScreenRequested(IBinder token, Rect rectangle, boolean immediate) {
+        synchronized (mWindowMap) {
+            WindowState window = mWindowMap.get(token);
+            if (window != null) {
+                scheduleNotifyRectangleOnScreenRequestedIfNeededLocked(window, rectangle,
+                        immediate);
+            }
+        }
+    }
+
+    private void scheduleNotifyRectangleOnScreenRequestedIfNeededLocked(WindowState window,
+            Rect rectangle, boolean immediate) {
+        DisplayContent displayContent = window.mDisplayContent;
+        if (displayContent.mDisplayContentChangeListeners != null
+                && displayContent.mDisplayContentChangeListeners.getRegisteredCallbackCount() > 0) {
+            mH.obtainMessage(H.NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED, displayContent.getDisplayId(),
+                    immediate? 1 : 0, new Rect(rectangle)).sendToTarget();
+        }
+    }
+
+    private void handleNotifyRectangleOnScreenRequested(int displayId, Rect rectangle,
+            boolean immediate) {
+        RemoteCallbackList<IDisplayContentChangeListener> callbacks = null;
+        synchronized (mWindowMap) {
+            DisplayContent displayContent = getDisplayContentLocked(displayId);
+            if (displayContent == null) {
+                return;
+            }
+            callbacks = displayContent.mDisplayContentChangeListeners;
+            if (callbacks == null) {
+                return;
+            }
+        }
+        final int callbackCount = callbacks.beginBroadcast();
+        try {
+            for (int i = 0; i < callbackCount; i++) {
+                try {
+                    callbacks.getBroadcastItem(i).onRectangleOnScreenRequested(displayId,
+                            rectangle, immediate);
+                } catch (RemoteException re) {
+                    /* ignore */
+                }
+            }
+        } finally {
+            callbacks.finishBroadcast();
+        }
+    }
+
     public int relayoutWindow(Session session, IWindow client, int seq,
             WindowManager.LayoutParams attrs, int requestedWidth,
             int requestedHeight, int viewVisibility, int flags,
@@ -2729,7 +2762,7 @@
             }
 
             winAnimator.mSurfaceDestroyDeferred =
-                    (flags&WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
+                    (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
 
             int attrChanges = 0;
             int flagChanges = 0;
@@ -2746,7 +2779,8 @@
                 }
             }
 
-            if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": " + win.mAttrs);
+            if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
+                    + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
 
             win.mEnforceSizeCompat = (win.mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
 
@@ -2768,13 +2802,12 @@
                 win.mHScale = win.mVScale = 1;
             }
 
-            boolean imMayMove = (flagChanges&(
-                    WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
-                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)) != 0;
+            boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
 
-            boolean focusMayChange = win.mViewVisibility != viewVisibility
-                    || ((flagChanges&WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0)
-                    || (!win.mRelayoutCalled);
+            final boolean isDefaultDisplay = win.isDefaultDisplay();
+            boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
+                    || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
+                    || (!win.mRelayoutCalled));
 
             boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
                     && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
@@ -2813,22 +2846,15 @@
                                 "Relayout window turning screen on: " + win);
                         win.mTurnOnScreen = true;
                     }
-                    int diff = 0;
-                    if (win.mConfiguration != mCurConfiguration
-                            && (win.mConfiguration == null
-                                    || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0)) {
-                        win.mConfiguration = mCurConfiguration;
-                        if (DEBUG_CONFIGURATION) {
-                            Slog.i(TAG, "Window " + win + " visible with new config: "
-                                    + win.mConfiguration + " / 0x"
-                                    + Integer.toHexString(diff));
-                        }
+                    if (win.isConfigChanged()) {
+                        if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win
+                                + " visible with new config: " + win.mConfiguration);
                         outConfig.setTo(mCurConfiguration);
                     }
                 }
                 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
                     // To change the format, we need to re-build the surface.
-                    winAnimator.destroySurfaceLocked();
+                    winAnimator.destroySurfaceLocked(false);
                     toBeDisplayed = true;
                     surfaceChanged = true;
                 }
@@ -2848,7 +2874,7 @@
                     }
                 } catch (Exception e) {
                     mInputMonitor.updateInputWindowsLw(true /*force*/);
-                    
+
                     Slog.w(TAG, "Exception thrown when creating surface for client "
                              + client + " (" + win.mAttrs.getTitle() + ")",
                              e);
@@ -2856,7 +2882,7 @@
                     return 0;
                 }
                 if (toBeDisplayed) {
-                    focusMayChange = true;
+                    focusMayChange = isDefaultDisplay;
                 }
                 if (win.mAttrs.type == TYPE_INPUT_METHOD
                         && mInputMethodWindow == null) {
@@ -2893,7 +2919,7 @@
                         }
                         if (win.isWinVisibleLw() &&
                                 winAnimator.applyAnimationLocked(transit, false)) {
-                            focusMayChange = true;
+                            focusMayChange = isDefaultDisplay;
                             win.mExiting = true;
                         } else if (win.mWinAnimator.isAnimating()) {
                             // Currently in a hide animation... turn this into
@@ -2909,8 +2935,9 @@
                             if (mInputMethodWindow == win) {
                                 mInputMethodWindow = null;
                             }
-                            winAnimator.destroySurfaceLocked();
+                            winAnimator.destroySurfaceLocked(false);
                         }
+                        scheduleNotifyWindowTranstionIfNeededLocked(win, transit);
                     }
                 }
 
@@ -2947,15 +2974,17 @@
                 }
             }
 
-            mLayoutNeeded = true;
-            win.mGivenInsetsPending = (flags&WindowManagerImpl.RELAYOUT_INSETS_PENDING) != 0;
+            win.mDisplayContent.layoutNeeded = true;
+            win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
             if (assignLayers) {
-                assignLayersLocked();
+                assignLayersLocked(win.getWindowList());
             }
             configChanged = updateOrientationFromAppTokensLocked(false);
             performLayoutAndPlaceSurfacesLocked();
             if (toBeDisplayed && win.mIsWallpaper) {
-                updateWallpaperOffsetLocked(win, mAppDisplayWidth, mAppDisplayHeight, false);
+                DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
+                updateWallpaperOffsetLocked(win,
+                        displayInfo.appWidth, displayInfo.appHeight, false);
             }
             if (win.mAppToken != null) {
                 win.mAppToken.updateReportedVisibilityLocked();
@@ -2981,6 +3010,10 @@
             }
 
             mInputMonitor.updateInputWindowsLw(true /*force*/);
+
+            if (DEBUG_LAYOUT) {
+                Slog.v(TAG, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
+            }
         }
 
         if (configChanged) {
@@ -2989,10 +3022,10 @@
 
         Binder.restoreCallingIdentity(origId);
 
-        return (inTouchMode ? WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE : 0)
-                | (toBeDisplayed ? WindowManagerImpl.RELAYOUT_RES_FIRST_TIME : 0)
-                | (surfaceChanged ? WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED : 0)
-                | (animating ? WindowManagerImpl.RELAYOUT_RES_ANIMATING : 0);
+        return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0)
+                | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0)
+                | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0)
+                | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0);
     }
 
     public void performDeferredDestroyWindow(Session session, IWindow client) {
@@ -3004,7 +3037,7 @@
                 if (win == null) {
                     return;
                 }
-                win.mWinAnimator.destroyDeferredSurfaceLocked();
+                win.mWinAnimator.destroyDeferredSurfaceLocked(false);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -3035,20 +3068,116 @@
                 if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
                     adjustWallpaperWindowsLocked();
                 }
-                mLayoutNeeded = true;
+                win.mDisplayContent.layoutNeeded = true;
                 performLayoutAndPlaceSurfacesLocked();
             }
         }
         Binder.restoreCallingIdentity(origId);
     }
 
+    @Override
     public float getWindowCompatibilityScale(IBinder windowToken) {
+        if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
+                "getWindowCompatibilityScale()")) {
+            throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
+        }
         synchronized (mWindowMap) {
             WindowState windowState = mWindowMap.get(windowToken);
             return (windowState != null) ? windowState.mGlobalScale : 1.0f;
         }
     }
 
+    @Override
+    public WindowInfo getWindowInfo(IBinder token) {
+        if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
+                "getWindowInfo()")) {
+            throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
+        }
+        synchronized (mWindowMap) {
+            WindowState window = mWindowMap.get(token);
+            if (window != null) {
+                return getWindowInfoForWindowStateLocked(window);
+            }
+            return null;
+        }
+    }
+
+    @Override
+    public void getVisibleWindowsForDisplay(int displayId, List<WindowInfo> outInfos) {
+        if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
+                "getWindowInfos()")) {
+            throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
+        }
+        synchronized (mWindowMap) {
+            DisplayContent displayContent = getDisplayContentLocked(displayId);
+            if (displayContent == null) {
+                return;
+            }
+            WindowList windows = displayContent.getWindowList();
+            final int windowCount = windows.size();
+            for (int i = 0; i < windowCount; i++) {
+                WindowState window = windows.get(i);
+                if (window.isVisibleLw() || window.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
+                    WindowInfo info = getWindowInfoForWindowStateLocked(window);
+                    outInfos.add(info);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void magnifyDisplay(int displayId, float scale, float offsetX, float offsetY) {
+        if (!checkCallingPermission(
+                android.Manifest.permission.MAGNIFY_DISPLAY, "magnifyDisplay()")) {
+            throw new SecurityException("Requires MAGNIFY_DISPLAY permission");
+        }
+        synchronized (mWindowMap) {
+            MagnificationSpec spec = getDisplayMagnificationSpecLocked(displayId);
+            if (spec != null) {
+                final boolean scaleChanged = spec.mScale != scale;
+                final boolean offsetChanged = spec.mOffsetX != offsetX || spec.mOffsetY != offsetY;
+                if (!scaleChanged && !offsetChanged) {
+                    return;
+                }
+                spec.initialize(scale, offsetX, offsetY);
+                // If the offset has changed we need to re-add the input windows
+                // since the offsets have to be propagated to the input system.
+                if (offsetChanged) {
+                    // TODO(multidisplay): Input only occurs on the default display.
+                    if (displayId == Display.DEFAULT_DISPLAY) {
+                        mInputMonitor.updateInputWindowsLw(true);
+                    }
+                }
+                scheduleAnimationLocked();
+            }
+        }
+    }
+
+    MagnificationSpec getDisplayMagnificationSpecLocked(int displayId) {
+        DisplayContent displayContent = getDisplayContentLocked(displayId);
+        if (displayContent != null) {
+            if (displayContent.mMagnificationSpec == null) {
+                displayContent.mMagnificationSpec = new MagnificationSpec();
+            }
+            return displayContent.mMagnificationSpec;
+        }
+        return null;
+    }
+
+    private WindowInfo getWindowInfoForWindowStateLocked(WindowState window) {
+        WindowInfo info = WindowInfo.obtain();
+        info.token = window.mToken.token;
+        info.frame.set(window.mFrame);
+        info.type = window.mAttrs.type;
+        info.displayId = window.getDisplayId();
+        info.compatibilityScale = window.mGlobalScale;
+        info.visible = window.isVisibleLw() || info.type == TYPE_UNIVERSE_BACKGROUND;
+        info.layer = window.mLayer;
+        window.getTouchableRegion(mTempRegion);
+        mTempRegion.getBounds(info.touchableRegion);
+        return info;
+    }
+
     private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
         if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg="
                 + (lp != null ? lp.packageName : null)
@@ -3128,12 +3257,11 @@
             a.setDetachWallpaper(true);
             a.setDuration(duration);
             return a;
-        } else {
-            // For normal animations, the exiting element just holds in place.
-            Animation a = new AlphaAnimation(1, 1);
-            a.setDuration(duration);
-            return a;
         }
+        // For normal animations, the exiting element just holds in place.
+        Animation a = new AlphaAnimation(1, 1);
+        a.setDuration(duration);
+        return a;
     }
 
     /**
@@ -3170,10 +3298,12 @@
                 duration = 300;
                 break;
         }
+        // TODO(multidisplay): For now assume all app animation is on main display.
+        final DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
         if (enter) {
             // Entering app zooms out from the center of the initial rect.
-            float scaleW = mNextAppTransitionStartWidth / (float) mAppDisplayWidth;
-            float scaleH = mNextAppTransitionStartHeight / (float) mAppDisplayHeight;
+            float scaleW = mNextAppTransitionStartWidth / (float) displayInfo.appWidth;
+            float scaleH = mNextAppTransitionStartHeight / (float) displayInfo.appHeight;
             Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
                     computePivot(mNextAppTransitionStartX, scaleW),
                     computePivot(mNextAppTransitionStartY, scaleH));
@@ -3193,13 +3323,13 @@
         final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext,
                 com.android.internal.R.interpolator.decelerate_cubic);
         a.setInterpolator(interpolator);
-        a.initialize(mAppDisplayWidth, mAppDisplayHeight,
-                mAppDisplayWidth, mAppDisplayHeight);
+        a.initialize(displayInfo.appWidth, displayInfo.appHeight,
+                displayInfo.appWidth, displayInfo.appHeight);
         return a;
     }
 
     private Animation createThumbnailAnimationLocked(int transit,
-            boolean enter, boolean thumb, boolean delayed) {
+            boolean enter, boolean thumb, boolean scaleUp) {
         Animation a;
         final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
         final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
@@ -3209,7 +3339,6 @@
         // it  is the standard duration for that.  Otherwise we use the longer
         // task transition duration.
         int duration;
-        int delayDuration = delayed ? 270 : 0;
         switch (transit) {
             case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
             case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
@@ -3217,66 +3346,113 @@
                         com.android.internal.R.integer.config_shortAnimTime);
                 break;
             default:
-                duration = delayed ? 250 : 300;
+                duration = 250;
                 break;
         }
+        // TOOD(multidisplay): For now assume all app animation is on the main screen.
+        DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
         if (thumb) {
             // Animation for zooming thumbnail from its initial size to
             // filling the screen.
-            float scaleW = mAppDisplayWidth/thumbWidth;
-            float scaleH = mAppDisplayHeight/thumbHeight;
+            if (scaleUp) {
+                float scaleW = displayInfo.appWidth / thumbWidth;
+                float scaleH = displayInfo.appHeight / thumbHeight;
 
-            Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
-                    computePivot(mNextAppTransitionStartX, 1/scaleW),
-                    computePivot(mNextAppTransitionStartY, 1/scaleH));
-            AnimationSet set = new AnimationSet(true);
-            Animation alpha = new AlphaAnimation(1, 0);
-            scale.setDuration(duration);
-            scale.setInterpolator(
-                    new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
-            set.addAnimation(scale);
-            alpha.setDuration(duration);
-            set.addAnimation(alpha);
-            set.setFillBefore(true);
-            if (delayDuration > 0) {
-                set.setStartOffset(delayDuration);
+                Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
+                        computePivot(mNextAppTransitionStartX, 1 / scaleW),
+                        computePivot(mNextAppTransitionStartY, 1 / scaleH));
+                AnimationSet set = new AnimationSet(true);
+                Animation alpha = new AlphaAnimation(1, 0);
+                scale.setDuration(duration);
+                scale.setInterpolator(
+                        new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
+                set.addAnimation(scale);
+                alpha.setDuration(duration);
+                set.addAnimation(alpha);
+                set.setFillBefore(true);
+                a = set;
+            } else {
+                float scaleW = displayInfo.appWidth / thumbWidth;
+                float scaleH = displayInfo.appHeight / thumbHeight;
+
+                Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
+                        computePivot(mNextAppTransitionStartX, 1 / scaleW),
+                        computePivot(mNextAppTransitionStartY, 1 / scaleH));
+                AnimationSet set = new AnimationSet(true);
+                Animation alpha = new AlphaAnimation(1, 1);
+                scale.setDuration(duration);
+                scale.setInterpolator(
+                        new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
+                set.addAnimation(scale);
+                alpha.setDuration(duration);
+                set.addAnimation(alpha);
+                set.setFillBefore(true);
+
+                a = set;
             }
-            a = set;
         } else if (enter) {
             // Entering app zooms out from the center of the thumbnail.
-            float scaleW = thumbWidth / mAppDisplayWidth;
-            float scaleH = thumbHeight / mAppDisplayHeight;
-            Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
-                    computePivot(mNextAppTransitionStartX, scaleW),
-                    computePivot(mNextAppTransitionStartY, scaleH));
-            scale.setDuration(duration);
-            scale.setInterpolator(
-                    new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
-            scale.setFillBefore(true);
-            if (delayDuration > 0) {
-                scale.setStartOffset(delayDuration);
-            }
-            a = scale;
-        } else {
-            if (delayed) {
-                a = new AlphaAnimation(1, 0);
-                a.setStartOffset(0);
-                a.setDuration(delayDuration - 120);
-                a.setBackgroundColor(0xFF000000);
+            if (scaleUp) {
+                float scaleW = thumbWidth / displayInfo.appWidth;
+                float scaleH = thumbHeight / displayInfo.appHeight;
+                Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
+                        computePivot(mNextAppTransitionStartX, scaleW),
+                        computePivot(mNextAppTransitionStartY, scaleH));
+                scale.setDuration(duration);
+                scale.setInterpolator(
+                        new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
+                scale.setFillBefore(true);
+                a = scale;
             } else {
-                a = createExitAnimationLocked(transit, duration);
+                // noop animation
+                a = new AlphaAnimation(1, 1);
+                a.setDuration(duration);
+            }
+        } else {
+            // Exiting app
+            if (scaleUp) {
+                if (transit == WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN) {
+                    // Fade out while bringing up selected activity. This keeps the
+                    // current activity from showing through a launching wallpaper
+                    // activity.
+                    a = new AlphaAnimation(1, 0);
+                } else {
+                    // noop animation
+                    a = new AlphaAnimation(1, 1);
+                }
+                a.setDuration(duration);
+            } else {
+                float scaleW = thumbWidth / displayInfo.appWidth;
+                float scaleH = thumbHeight / displayInfo.appHeight;
+                Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
+                        computePivot(mNextAppTransitionStartX, scaleW),
+                        computePivot(mNextAppTransitionStartY, scaleH));
+                scale.setDuration(duration);
+                scale.setInterpolator(
+                        new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
+                scale.setFillBefore(true);
+                AnimationSet set = new AnimationSet(true);
+                Animation alpha = new AlphaAnimation(1, 0);
+                set.addAnimation(scale);
+                alpha.setDuration(duration);
+                alpha.setInterpolator(new DecelerateInterpolator(
+                        THUMBNAIL_ANIMATION_DECELERATE_FACTOR));
+                set.addAnimation(alpha);
+                set.setFillBefore(true);
+                set.setZAdjustment(Animation.ZORDER_TOP);
+                a = set;
             }
         }
         a.setFillAfter(true);
         final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext,
                 com.android.internal.R.interpolator.decelerate_quad);
         a.setInterpolator(interpolator);
-        a.initialize(mAppDisplayWidth, mAppDisplayHeight,
-                mAppDisplayWidth, mAppDisplayHeight);
+        a.initialize(displayInfo.appWidth, displayInfo.appHeight,
+                displayInfo.appWidth, displayInfo.appHeight);
         return a;
     }
 
-    private boolean applyAnimationLocked(AppWindowToken wtoken,
+    private boolean applyAnimationLocked(AppWindowToken atoken,
             WindowManager.LayoutParams lp, int transit, boolean enter) {
         // Only apply an animation if the display isn't frozen.  If it is
         // frozen, there is no reason to animate and it can cause strange
@@ -3289,27 +3465,29 @@
                 a = loadAnimation(mNextAppTransitionPackage, enter ?
                         mNextAppTransitionEnter : mNextAppTransitionExit);
                 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
-                        "applyAnimation: wtoken=" + wtoken
+                        "applyAnimation: atoken=" + atoken
                         + " anim=" + a + " nextAppTransition=ANIM_CUSTOM"
-                        + " transit=" + transit + " Callers " + Debug.getCallers(3));
+                        + " transit=" + transit + " isEntrance=" + enter
+                        + " Callers=" + Debug.getCallers(3));
             } else if (mNextAppTransitionType == ActivityOptions.ANIM_SCALE_UP) {
                 a = createScaleUpAnimationLocked(transit, enter);
                 initialized = true;
                 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
-                        "applyAnimation: wtoken=" + wtoken
+                        "applyAnimation: atoken=" + atoken
                         + " anim=" + a + " nextAppTransition=ANIM_SCALE_UP"
-                        + " transit=" + transit + " Callers " + Debug.getCallers(3));
-            } else if (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL ||
-                    mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_DELAYED) {
-                boolean delayed = (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_DELAYED);
-                a = createThumbnailAnimationLocked(transit, enter, false, delayed);
+                        + " transit=" + transit + " isEntrance=" + enter
+                        + " Callers=" + Debug.getCallers(3));
+            } else if (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP ||
+                    mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN) {
+                boolean scaleUp = (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP);
+                a = createThumbnailAnimationLocked(transit, enter, false, scaleUp);
                 initialized = true;
-
                 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
-                    String animName = delayed ? "ANIM_THUMBNAIL_DELAYED" : "ANIM_THUMBNAIL";
-                    Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
+                    String animName = scaleUp ? "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
+                    Slog.v(TAG, "applyAnimation: atoken=" + atoken
                             + " anim=" + a + " nextAppTransition=" + animName
-                            + " transit=" + transit + " Callers " + Debug.getCallers(3));
+                            + " transit=" + transit + " isEntrance=" + enter
+                            + " Callers=" + Debug.getCallers(3));
                 }
             } else {
                 int animAttr = 0;
@@ -3367,10 +3545,11 @@
                 }
                 a = animAttr != 0 ? loadAnimation(lp, animAttr) : null;
                 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
-                        "applyAnimation: wtoken=" + wtoken
+                        "applyAnimation: atoken=" + atoken
                         + " anim=" + a
                         + " animAttr=0x" + Integer.toHexString(animAttr)
-                        + " transit=" + transit + " Callers " + Debug.getCallers(3));
+                        + " transit=" + transit + " isEntrance=" + enter
+                        + " Callers=" + Debug.getCallers(3));
             }
             if (a != null) {
                 if (DEBUG_ANIM) {
@@ -3379,15 +3558,15 @@
                         e = new RuntimeException();
                         e.fillInStackTrace();
                     }
-                    Slog.v(TAG, "Loaded animation " + a + " for " + wtoken, e);
+                    Slog.v(TAG, "Loaded animation " + a + " for " + atoken, e);
                 }
-                wtoken.mAppAnimator.setAnimation(a, initialized);
+                atoken.mAppAnimator.setAnimation(a, initialized);
             }
         } else {
-            wtoken.mAppAnimator.clearAnimation();
+            atoken.mAppAnimator.clearAnimation();
         }
 
-        return wtoken.mAppAnimator.animation != null;
+        return atoken.mAppAnimator.animation != null;
     }
 
     // -------------------------------------------------------------
@@ -3398,14 +3577,14 @@
         int v = tokens.size()-1;
         int m = mAppTokens.size()-1;
         while (v >= 0 && m >= 0) {
-            AppWindowToken wtoken = mAppTokens.get(m);
-            if (wtoken.removed) {
+            AppWindowToken atoken = mAppTokens.get(m);
+            if (atoken.removed) {
                 m--;
                 continue;
             }
-            if (tokens.get(v) != wtoken.token) {
+            if (tokens.get(v) != atoken.token) {
                 Slog.w(TAG, "Tokens out of sync: external is " + tokens.get(v)
-                      + " @ " + v + ", internal is " + wtoken.token + " @ " + m);
+                      + " @ " + v + ", internal is " + atoken.token + " @ " + m);
             }
             v--;
             m--;
@@ -3415,9 +3594,9 @@
             v--;
         }
         while (m >= 0) {
-            AppWindowToken wtoken = mAppTokens.get(m);
-            if (!wtoken.removed) {
-                Slog.w(TAG, "Invalid internal token: " + wtoken.token + " @ " + m);
+            AppWindowToken atoken = mAppTokens.get(m);
+            if (!atoken.removed) {
+                Slog.w(TAG, "Invalid internal atoken: " + atoken.token + " @ " + m);
             }
             m--;
         }
@@ -3440,7 +3619,7 @@
         Slog.w(TAG, msg);
         return false;
     }
-    
+
     boolean okToDisplay() {
         return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully();
     }
@@ -3470,10 +3649,12 @@
             mTokenMap.put(token, wtoken);
             if (type == TYPE_WALLPAPER) {
                 mWallpaperTokens.add(wtoken);
+                updateLayoutToAnimWallpaperTokens();
             }
         }
     }
 
+    @Override
     public void removeWindowToken(IBinder token) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "removeWindowToken()")) {
@@ -3486,8 +3667,6 @@
             if (wtoken != null) {
                 boolean delayed = false;
                 if (!wtoken.hidden) {
-                    wtoken.hidden = true;
-
                     final int N = wtoken.windows.size();
                     boolean changed = false;
 
@@ -3499,13 +3678,18 @@
                         }
 
                         if (win.isVisibleNow()) {
-                            win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, false);
+                            win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
+                                    false);
+                            scheduleNotifyWindowTranstionIfNeededLocked(win,
+                                    WindowManagerPolicy.TRANSIT_EXIT);
                             changed = true;
+                            win.mDisplayContent.layoutNeeded = true;
                         }
                     }
 
+                    wtoken.hidden = true;
+
                     if (changed) {
-                        mLayoutNeeded = true;
                         performLayoutAndPlaceSurfacesLocked();
                         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
                                 false /*updateInputWindows*/);
@@ -3515,6 +3699,7 @@
                         mExitingTokens.add(wtoken);
                     } else if (wtoken.windowType == TYPE_WALLPAPER) {
                         mWallpaperTokens.remove(wtoken);
+                        updateLayoutToAnimWallpaperTokens();
                     }
                 }
 
@@ -3530,23 +3715,23 @@
      *  Find the location to insert a new AppWindowToken into the window-ordered app token list.
      *  Note that mAppTokens.size() == mAnimatingAppTokens.size() + 1.
      * @param addPos The location the token was inserted into in mAppTokens.
-     * @param wtoken The token to insert.
+     * @param atoken The token to insert.
      */
-    private void addAppTokenToAnimating(final int addPos, final AppWindowToken wtoken) {
+    private void addAppTokenToAnimating(final int addPos, final AppWindowToken atoken) {
         if (addPos == 0 || addPos == mAnimatingAppTokens.size()) {
             // It was inserted into the beginning or end of mAppTokens. Honor that.
-            mAnimatingAppTokens.add(addPos, wtoken);
+            mAnimatingAppTokens.add(addPos, atoken);
             return;
         }
         // Find the item immediately above the mAppTokens insertion point and put the token
         // immediately below that one in mAnimatingAppTokens.
         final AppWindowToken aboveAnchor = mAppTokens.get(addPos + 1);
-        mAnimatingAppTokens.add(mAnimatingAppTokens.indexOf(aboveAnchor), wtoken);
+        mAnimatingAppTokens.add(mAnimatingAppTokens.indexOf(aboveAnchor), atoken);
     }
 
     @Override
     public void addAppToken(int addPos, IApplicationToken token,
-            int groupId, int requestedOrientation, boolean fullscreen) {
+            int groupId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "addAppToken()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
@@ -3567,30 +3752,32 @@
         }
 
         synchronized(mWindowMap) {
-            AppWindowToken wtoken = findAppWindowToken(token.asBinder());
-            if (wtoken != null) {
+            AppWindowToken atoken = findAppWindowToken(token.asBinder());
+            if (atoken != null) {
                 Slog.w(TAG, "Attempted to add existing app token: " + token);
                 return;
             }
-            wtoken = new AppWindowToken(this, token);
-            wtoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
-            wtoken.groupId = groupId;
-            wtoken.appFullscreen = fullscreen;
-            wtoken.requestedOrientation = requestedOrientation;
-            if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + wtoken
+            atoken = new AppWindowToken(this, token);
+            atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
+            atoken.groupId = groupId;
+            atoken.appFullscreen = fullscreen;
+            atoken.showWhenLocked = showWhenLocked;
+            atoken.requestedOrientation = requestedOrientation;
+            if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
                     + " at " + addPos);
-            mAppTokens.add(addPos, wtoken);
-            addAppTokenToAnimating(addPos, wtoken);
-            mTokenMap.put(token.asBinder(), wtoken);
+            mAppTokens.add(addPos, atoken);
+            addAppTokenToAnimating(addPos, atoken);
+            mTokenMap.put(token.asBinder(), atoken);
 
             // Application tokens start out hidden.
-            wtoken.hidden = true;
-            wtoken.hiddenRequested = true;
+            atoken.hidden = true;
+            atoken.hiddenRequested = true;
 
             //dump();
         }
     }
 
+    @Override
     public void setAppGroupId(IBinder token, int groupId) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setAppGroupId()")) {
@@ -3598,12 +3785,12 @@
         }
 
         synchronized(mWindowMap) {
-            AppWindowToken wtoken = findAppWindowToken(token);
-            if (wtoken == null) {
+            AppWindowToken atoken = findAppWindowToken(token);
+            if (atoken == null) {
                 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
                 return;
             }
-            wtoken.groupId = groupId;
+            atoken.groupId = groupId;
         }
     }
 
@@ -3617,9 +3804,11 @@
             return mLastWindowForcedOrientation;
         }
 
-        int pos = mWindows.size() - 1;
+        // TODO(multidisplay): Change to the correct display.
+        final WindowList windows = getDefaultWindowListLocked();
+        int pos = windows.size() - 1;
         while (pos >= 0) {
-            WindowState wtoken = mWindows.get(pos);
+            WindowState wtoken = windows.get(pos);
             pos--;
             if (wtoken.mAppToken != null) {
                 // We hit an application window. so the orientation will be determined by the
@@ -3633,9 +3822,9 @@
             if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
                     (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
                 continue;
-            } else {
-                return (mLastWindowForcedOrientation=req);
             }
+
+            return (mLastWindowForcedOrientation=req);
         }
         return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
     }
@@ -3647,20 +3836,20 @@
         boolean haveGroup = false;
         boolean lastFullscreen = false;
         for (int pos = mAppTokens.size() - 1; pos >= 0; pos--) {
-            AppWindowToken wtoken = mAppTokens.get(pos);
+            AppWindowToken atoken = mAppTokens.get(pos);
 
-            if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + wtoken);
+            if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken);
 
             // if we're about to tear down this window and not seek for
             // the behind activity, don't use it for orientation
             if (!findingBehind
-                    && (!wtoken.hidden && wtoken.hiddenRequested)) {
-                if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + wtoken
+                    && (!atoken.hidden && atoken.hiddenRequested)) {
+                if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
                         + " -- going to hide");
                 continue;
             }
 
-            if (haveGroup == true && curGroup != wtoken.groupId) {
+            if (haveGroup == true && curGroup != atoken.groupId) {
                 // If we have hit a new application group, and the bottom
                 // of the previous group didn't explicitly say to use
                 // the orientation behind it, and the last app was
@@ -3668,33 +3857,33 @@
                 // user's orientation.
                 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
                         && lastFullscreen) {
-                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + wtoken
+                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
                             + " -- end of group, return " + lastOrientation);
                     return lastOrientation;
                 }
             }
 
             // We ignore any hidden applications on the top.
-            if (wtoken.hiddenRequested || wtoken.willBeHidden) {
-                if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + wtoken
+            if (atoken.hiddenRequested || atoken.willBeHidden) {
+                if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
                         + " -- hidden on top");
                 continue;
             }
 
             if (!haveGroup) {
                 haveGroup = true;
-                curGroup = wtoken.groupId;
-                lastOrientation = wtoken.requestedOrientation;
-            } 
+                curGroup = atoken.groupId;
+                lastOrientation = atoken.requestedOrientation;
+            }
 
-            int or = wtoken.requestedOrientation;
+            int or = atoken.requestedOrientation;
             // If this application is fullscreen, and didn't explicitly say
             // to use the orientation behind it, then just take whatever
             // orientation it has and ignores whatever is under it.
-            lastFullscreen = wtoken.appFullscreen;
+            lastFullscreen = atoken.appFullscreen;
             if (lastFullscreen
                     && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
-                if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + wtoken
+                if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
                         + " -- full screen, return " + or);
                 return or;
             }
@@ -3702,7 +3891,7 @@
             // then use it.
             if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
                     && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
-                if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + wtoken
+                if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
                         + " -- explicitly set, return " + or);
                 return or;
             }
@@ -3712,6 +3901,7 @@
         return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     }
 
+    @Override
     public Configuration updateOrientationFromAppTokens(
             Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
@@ -3721,7 +3911,7 @@
 
         Configuration config = null;
         long ident = Binder.clearCallingIdentity();
-        
+
         synchronized(mWindowMap) {
             config = updateOrientationFromAppTokensLocked(currentConfig,
                     freezeThisOneIfNeeded);
@@ -3737,10 +3927,10 @@
 
         if (updateOrientationFromAppTokensLocked(false)) {
             if (freezeThisOneIfNeeded != null) {
-                AppWindowToken wtoken = findAppWindowToken(
+                AppWindowToken atoken = findAppWindowToken(
                         freezeThisOneIfNeeded);
-                if (wtoken != null) {
-                    startAppFreezingScreenLocked(wtoken,
+                if (atoken != null) {
+                    startAppFreezingScreenLocked(atoken,
                             ActivityInfo.CONFIG_ORIENTATION);
                 }
             }
@@ -3756,13 +3946,13 @@
             if (computeScreenConfigurationLocked(mTempConfiguration)) {
                 if (currentConfig.diff(mTempConfiguration) != 0) {
                     mWaitingForConfig = true;
-                    mLayoutNeeded = true;
-                    startFreezingDisplayLocked(false);
+                    getDefaultDisplayContentLocked().layoutNeeded = true;
+                    startFreezingDisplayLocked(false, 0, 0);
                     config = new Configuration(mTempConfiguration);
                 }
             }
         }
-        
+
         return config;
     }
 
@@ -3773,7 +3963,7 @@
      * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
      * SCREEN.  This will typically be done for you if you call
      * sendNewConfiguration().
-     * 
+     *
      * The orientation is computed from non-application windows first. If none of
      * the non-application windows specify orientation, the orientation is computed from
      * application tokens.
@@ -3810,6 +4000,7 @@
         return req;
     }
 
+    @Override
     public void setNewConfiguration(Configuration config) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setNewConfiguration()")) {
@@ -3822,7 +4013,8 @@
             performLayoutAndPlaceSurfacesLocked();
         }
     }
-    
+
+    @Override
     public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setAppOrientation()")) {
@@ -3830,16 +4022,17 @@
         }
 
         synchronized(mWindowMap) {
-            AppWindowToken wtoken = findAppWindowToken(token.asBinder());
-            if (wtoken == null) {
+            AppWindowToken atoken = findAppWindowToken(token.asBinder());
+            if (atoken == null) {
                 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
                 return;
             }
 
-            wtoken.requestedOrientation = requestedOrientation;
+            atoken.requestedOrientation = requestedOrientation;
         }
     }
 
+    @Override
     public int getAppOrientation(IApplicationToken token) {
         synchronized(mWindowMap) {
             AppWindowToken wtoken = findAppWindowToken(token.asBinder());
@@ -3851,6 +4044,7 @@
         }
     }
 
+    @Override
     public void setFocusedApp(IBinder token, boolean moveFocusNow) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setFocusedApp()")) {
@@ -3874,7 +4068,8 @@
                 }
                 changed = mFocusedApp != newFocus;
                 mFocusedApp = newFocus;
-                if (DEBUG_FOCUS) Slog.v(TAG, "Set focused app to: " + mFocusedApp);
+                if (DEBUG_FOCUS) Slog.v(TAG, "Set focused app to: " + mFocusedApp
+                        + " moveFocusNow=" + moveFocusNow);
                 if (changed) {
                     mInputMonitor.setFocusedAppLw(newFocus);
                 }
@@ -3888,6 +4083,7 @@
         }
     }
 
+    @Override
     public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "prepareAppTransition()")) {
@@ -3926,6 +4122,7 @@
         }
     }
 
+    @Override
     public int getPendingAppTransition() {
         return mNextAppTransition;
     }
@@ -3936,6 +4133,7 @@
         }
     }
 
+    @Override
     public void overridePendingAppTransition(String packageName,
             int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
         synchronized(mWindowMap) {
@@ -3953,6 +4151,7 @@
         }
     }
 
+    @Override
     public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
             int startHeight) {
         synchronized(mWindowMap) {
@@ -3970,15 +4169,16 @@
         }
     }
 
+    @Override
     public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
-            int startY, IRemoteCallback startedCallback, boolean delayed) {
+            int startY, IRemoteCallback startedCallback, boolean scaleUp) {
         synchronized(mWindowMap) {
             if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
-                mNextAppTransitionType = delayed
-                        ? ActivityOptions.ANIM_THUMBNAIL_DELAYED : ActivityOptions.ANIM_THUMBNAIL;
+                mNextAppTransitionType = scaleUp
+                        ? ActivityOptions.ANIM_THUMBNAIL_SCALE_UP : ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
                 mNextAppTransitionPackage = null;
                 mNextAppTransitionThumbnail = srcThumb;
-                mNextAppTransitionDelayed = delayed;
+                mNextAppTransitionScaleUp = scaleUp;
                 mNextAppTransitionStartX = startX;
                 mNextAppTransitionStartY = startY;
                 scheduleAnimationCallback(mNextAppTransitionCallback);
@@ -3989,6 +4189,7 @@
         }
     }
 
+    @Override
     public void executeAppTransition() {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "executeAppTransition()")) {
@@ -4011,6 +4212,7 @@
         }
     }
 
+    @Override
     public void setAppStartingWindow(IBinder token, String pkg,
             int theme, CompatibilityInfo compatInfo,
             CharSequence nonLocalizedLabel, int labelRes, int icon,
@@ -4022,7 +4224,7 @@
 
         synchronized(mWindowMap) {
             if (DEBUG_STARTING_WINDOW) Slog.v(
-                    TAG, "setAppStartingIcon: token=" + token + " pkg=" + pkg
+                    TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg
                     + " transferFrom=" + transferFrom);
 
             AppWindowToken wtoken = findAppWindowToken(token);
@@ -4054,7 +4256,7 @@
                             mSkipAppTransitionAnimation = true;
                         }
                         if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
-                                "Moving existing starting from " + ttoken
+                                "Moving existing starting " + startingWindow + " from " + ttoken
                                 + " to " + wtoken);
                         final long origId = Binder.clearCallingIdentity();
 
@@ -4063,6 +4265,7 @@
                         wtoken.startingData = ttoken.startingData;
                         wtoken.startingView = ttoken.startingView;
                         wtoken.startingDisplayed = ttoken.startingDisplayed;
+                        ttoken.startingDisplayed = false;
                         wtoken.startingWindow = startingWindow;
                         wtoken.reportedVisible = ttoken.reportedVisible;
                         ttoken.startingData = null;
@@ -4072,10 +4275,12 @@
                         startingWindow.mToken = wtoken;
                         startingWindow.mRootToken = wtoken;
                         startingWindow.mAppToken = wtoken;
+                        startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator;
+
                         if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) {
                             Slog.v(TAG, "Removing starting window: " + startingWindow);
                         }
-                        mWindows.remove(startingWindow);
+                        startingWindow.getWindowList().remove(startingWindow);
                         mWindowsChanged = true;
                         if (DEBUG_ADD_REMOVE) Slog.v(TAG,
                                 "Removing starting " + startingWindow + " from " + ttoken);
@@ -4117,7 +4322,7 @@
 
                         updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
                                 true /*updateInputWindows*/);
-                        mLayoutNeeded = true;
+                        getDefaultDisplayContentLocked().layoutNeeded = true;
                         performLayoutAndPlaceSurfacesLocked();
                         Binder.restoreCallingIdentity(origId);
                         return;
@@ -4200,7 +4405,7 @@
                         // an opaque window and our starting window transition animation
                         // can still work.  We just need to make sure the starting window
                         // is also showing the wallpaper.
-                        windowFlags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+                        windowFlags |= FLAG_SHOW_WALLPAPER;
                     } else {
                         return;
                     }
@@ -4263,6 +4468,10 @@
                 if (applyAnimationLocked(wtoken, lp, transit, visible)) {
                     delayed = runningAppAnimation = true;
                 }
+                WindowState window = wtoken.findMainWindow();
+                if (window != null) {
+                    scheduleNotifyWindowTranstionIfNeededLocked(window, transit);
+                }
                 changed = true;
             }
 
@@ -4280,15 +4489,21 @@
                         if (!runningAppAnimation) {
                             win.mWinAnimator.applyAnimationLocked(
                                     WindowManagerPolicy.TRANSIT_ENTER, true);
+                            scheduleNotifyWindowTranstionIfNeededLocked(win,
+                                    WindowManagerPolicy.TRANSIT_ENTER);
                         }
                         changed = true;
+                        win.mDisplayContent.layoutNeeded = true;
                     }
                 } else if (win.isVisibleNow()) {
                     if (!runningAppAnimation) {
                         win.mWinAnimator.applyAnimationLocked(
                                 WindowManagerPolicy.TRANSIT_EXIT, false);
+                        scheduleNotifyWindowTranstionIfNeededLocked(win,
+                                WindowManagerPolicy.TRANSIT_EXIT);
                     }
                     changed = true;
+                    win.mDisplayContent.layoutNeeded = true;
                 }
             }
 
@@ -4310,7 +4525,6 @@
                       + wtoken.hiddenRequested);
 
             if (changed) {
-                mLayoutNeeded = true;
                 mInputMonitor.setUpdateInputWindowsNeededLw();
                 if (performLayout) {
                     updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
@@ -4370,9 +4584,9 @@
                 }
                 wtoken.hiddenRequested = !visible;
 
-                if (DEBUG_APP_TRANSITIONS) Slog.v(
-                        TAG, "Setting dummy animation on: " + wtoken);
                 if (!wtoken.startingDisplayed) {
+                    if (DEBUG_APP_TRANSITIONS) Slog.v(
+                            TAG, "Setting dummy animation on: " + wtoken);
                     wtoken.mAppAnimator.setDummyAnimation();
                 }
                 mOpeningApps.remove(wtoken);
@@ -4438,6 +4652,7 @@
                         mInnerFields.mOrientationChangeComplete = false;
                     }
                     unfrozeWindows = true;
+                    w.mDisplayContent.layoutNeeded = true;
                 }
             }
             if (force || unfrozeWindows) {
@@ -4447,7 +4662,6 @@
             }
             if (unfreezeSurfaceNow) {
                 if (unfrozeWindows) {
-                    mLayoutNeeded = true;
                     performLayoutAndPlaceSurfacesLocked();
                 }
                 stopFreezingDisplayLocked();
@@ -4472,7 +4686,7 @@
                 wtoken.mAppAnimator.freezingScreen = true;
                 mAppsFreezingScreen++;
                 if (mAppsFreezingScreen == 1) {
-                    startFreezingDisplayLocked(false);
+                    startFreezingDisplayLocked(false, 0, 0);
                     mH.removeMessages(H.APP_FREEZE_TIMEOUT);
                     mH.sendMessageDelayed(mH.obtainMessage(H.APP_FREEZE_TIMEOUT),
                             5000);
@@ -4612,14 +4826,14 @@
         for (int i=0; i<NW; i++) {
             WindowState win = token.windows.get(i);
             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
-            mWindows.remove(win);
+            win.getWindowList().remove(win);
             int j = win.mChildWindows.size();
             while (j > 0) {
                 j--;
                 WindowState cwin = win.mChildWindows.get(j);
                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
                         "Tmp removing child window " + cwin);
-                mWindows.remove(cwin);
+                cwin.getWindowList().remove(cwin);
             }
         }
         return NW > 0;
@@ -4638,19 +4852,22 @@
     }
 
     void dumpWindowsLocked() {
-        for (int i=mWindows.size()-1; i>=0; i--) {
-            Slog.v(TAG, "  #" + i + ": " + mWindows.get(i));
+        int i = 0;
+        final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+        while (iterator.hasNext()) {
+            final WindowState w = iterator.next();
+            Slog.v(TAG, "  #" + i++ + ": " + w);
         }
     }
 
-    private int findWindowOffsetLocked(int tokenPos) {
-        final int NW = mWindows.size();
+    private int findWindowOffsetLocked(WindowList windows, int tokenPos) {
+        final int NW = windows.size();
 
         if (tokenPos >= mAnimatingAppTokens.size()) {
             int i = NW;
             while (i > 0) {
                 i--;
-                WindowState win = mWindows.get(i);
+                WindowState win = windows.get(i);
                 if (win.getAppToken() != null) {
                     return i+1;
                 }
@@ -4660,7 +4877,7 @@
         while (tokenPos > 0) {
             // Find the first app token below the new position that has
             // a window displayed.
-            final AppWindowToken wtoken = mAnimatingAppTokens.get(tokenPos-1);
+            final AppWindowToken wtoken = mAppTokens.get(tokenPos-1);
             if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows @ "
                     + tokenPos + " -- " + wtoken.token);
             if (wtoken.sendingToBottom) {
@@ -4679,7 +4896,7 @@
                     WindowState cwin = win.mChildWindows.get(j);
                     if (cwin.mSubLayer >= 0) {
                         for (int pos=NW-1; pos>=0; pos--) {
-                            if (mWindows.get(pos) == cwin) {
+                            if (windows.get(pos) == cwin) {
                                 if (DEBUG_REORDER) Slog.v(TAG,
                                         "Found child win @" + (pos+1));
                                 return pos+1;
@@ -4688,7 +4905,7 @@
                     }
                 }
                 for (int pos=NW-1; pos>=0; pos--) {
-                    if (mWindows.get(pos) == win) {
+                    if (windows.get(pos) == win) {
                         if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos+1));
                         return pos+1;
                     }
@@ -4701,6 +4918,7 @@
     }
 
     private final int reAddWindowLocked(int index, WindowState win) {
+        final WindowList windows = win.getWindowList();
         final int NCW = win.mChildWindows.size();
         boolean added = false;
         for (int j=0; j<NCW; j++) {
@@ -4709,31 +4927,35 @@
                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
                         + index + ": " + cwin);
                 win.mRebuilding = false;
-                mWindows.add(index, win);
+                windows.add(index, win);
                 index++;
                 added = true;
             }
             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
                     + index + ": " + cwin);
             cwin.mRebuilding = false;
-            mWindows.add(index, cwin);
+            windows.add(index, cwin);
             index++;
         }
         if (!added) {
             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
                     + index + ": " + win);
             win.mRebuilding = false;
-            mWindows.add(index, win);
+            windows.add(index, win);
             index++;
         }
         mWindowsChanged = true;
         return index;
     }
 
-    private final int reAddAppWindowsLocked(int index, WindowToken token) {
+    private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index,
+                                            WindowToken token) {
         final int NW = token.windows.size();
         for (int i=0; i<NW; i++) {
-            index = reAddWindowLocked(index, token.windows.get(i));
+            final WindowState win = token.windows.get(i);
+            if (win.mDisplayContent == displayContent) {
+                index = reAddWindowLocked(index, win);
+            }
         }
         return index;
     }
@@ -4779,12 +5001,20 @@
                 if (tmpRemoveAppWindowsLocked(wtoken)) {
                     if (DEBUG_REORDER) Slog.v(TAG, "Adding windows back in:");
                     if (DEBUG_REORDER) dumpWindowsLocked();
-                    reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken);
+                    DisplayContentsIterator iterator = new DisplayContentsIterator();
+                    while(iterator.hasNext()) {
+                        final DisplayContent displayContent = iterator.next();
+                        final WindowList windows = displayContent.getWindowList();
+                        final int pos = findWindowOffsetLocked(windows, index);
+                        final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
+                        if (pos != newPos) {
+                            displayContent.layoutNeeded = true;
+                        }
+                    }
                     if (DEBUG_REORDER) Slog.v(TAG, "Final window list:");
                     if (DEBUG_REORDER) dumpWindowsLocked();
                     updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
                             false /*updateInputWindows*/);
-                    mLayoutNeeded = true;
                     mInputMonitor.setUpdateInputWindowsNeededLw();
                     performLayoutAndPlaceSurfacesLocked();
                     mInputMonitor.updateInputWindowsLw(false /*force*/);
@@ -4818,19 +5048,28 @@
         // First remove all of the windows from the list.
         tmpRemoveAppWindowsLocked(wtoken);
 
-        // Where to start adding?
-        int pos = findWindowOffsetLocked(tokenPos);
-
         // And now add them back at the correct place.
-        pos = reAddAppWindowsLocked(pos, wtoken);
+        DisplayContentsIterator iterator = new DisplayContentsIterator();
+        while (iterator.hasNext()) {
+            final DisplayContent displayContent = iterator.next();
+            final WindowList windows = displayContent.getWindowList();
+            final int pos = findWindowOffsetLocked(windows, tokenPos);
+            final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
+            if (pos != newPos) {
+                displayContent.layoutNeeded = true;
+            }
+
+            if (updateFocusAndLayout && !updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                    false /*updateInputWindows*/)) {
+                assignLayersLocked(windows);
+            }
+        }
 
         if (updateFocusAndLayout) {
             mInputMonitor.setUpdateInputWindowsNeededLw();
-            if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
-                    false /*updateInputWindows*/)) {
-                assignLayersLocked();
-            }
-            mLayoutNeeded = true;
+
+            // Note that the above updateFocusedWindowLocked conditional used to sit here.
+
             if (!mInLayout) {
                 performLayoutAndPlaceSurfacesLocked();
             }
@@ -4849,23 +5088,33 @@
             }
         }
 
-        // Where to start adding?
-        int pos = findWindowOffsetLocked(tokenPos);
-
         // And now add them back at the correct place.
-        for (i=0; i<N; i++) {
-            WindowToken token = mTokenMap.get(tokens.get(i));
-            if (token != null) {
-                pos = reAddAppWindowsLocked(pos, token);
+        DisplayContentsIterator iterator = new DisplayContentsIterator();
+        while (iterator.hasNext()) {
+            final DisplayContent displayContent = iterator.next();
+            final WindowList windows = displayContent.getWindowList();
+            // Where to start adding?
+            int pos = findWindowOffsetLocked(windows, tokenPos);
+            for (i=0; i<N; i++) {
+                WindowToken token = mTokenMap.get(tokens.get(i));
+                if (token != null) {
+                    final int newPos = reAddAppWindowsLocked(displayContent, pos, token);
+                    if (newPos != pos) {
+                        displayContent.layoutNeeded = true;
+                    }
+                    pos = newPos;
+                }
+            }
+            if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                    false /*updateInputWindows*/)) {
+                assignLayersLocked(windows);
             }
         }
 
         mInputMonitor.setUpdateInputWindowsNeededLw();
-        if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
-                false /*updateInputWindows*/)) {
-            assignLayersLocked();
-        }
-        mLayoutNeeded = true;
+
+        // Note that the above updateFocusedWindowLocked used to sit here.
+
         performLayoutAndPlaceSurfacesLocked();
         mInputMonitor.updateInputWindowsLw(false /*force*/);
 
@@ -4946,59 +5195,69 @@
     // Misc IWindowSession methods
     // -------------------------------------------------------------
 
-    private boolean shouldAllowDisableKeyguard()
-    {
-        // We fail safe and prevent disabling keyguard in the unlikely event this gets 
-        // called before DevicePolicyManagerService has started.
-        if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) {
-            DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
-                    Context.DEVICE_POLICY_SERVICE);
-            if (dpm != null) {
-                mAllowDisableKeyguard = dpm.getPasswordQuality(null)
-                        == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
-                                ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
+    @Override
+    public void startFreezingScreen(int exitAnim, int enterAnim) {
+        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
+                "startFreezingScreen()")) {
+            throw new SecurityException("Requires FREEZE_SCREEN permission");
+        }
+
+        synchronized(mWindowMap) {
+            if (!mClientFreezingScreen) {
+                mClientFreezingScreen = true;
+                final long origId = Binder.clearCallingIdentity();
+                try {
+                    startFreezingDisplayLocked(false, exitAnim, enterAnim);
+                    mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
+                    mH.sendMessageDelayed(mH.obtainMessage(H.CLIENT_FREEZE_TIMEOUT),
+                            5000);
+                } finally {
+                    Binder.restoreCallingIdentity(origId);
+                }
             }
         }
-        return mAllowDisableKeyguard == ALLOW_DISABLE_YES;
     }
 
+    @Override
+    public void stopFreezingScreen() {
+        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
+                "stopFreezingScreen()")) {
+            throw new SecurityException("Requires FREEZE_SCREEN permission");
+        }
+
+        synchronized(mWindowMap) {
+            if (mClientFreezingScreen) {
+                mClientFreezingScreen = false;
+                final long origId = Binder.clearCallingIdentity();
+                try {
+                    stopFreezingDisplayLocked();
+                } finally {
+                    Binder.restoreCallingIdentity(origId);
+                }
+            }
+        }
+    }
+
+    @Override
     public void disableKeyguard(IBinder token, String tag) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
             != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
         }
 
-        synchronized (mKeyguardTokenWatcher) {
-            mKeyguardTokenWatcher.acquire(token, tag);
-        }
+        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
+                KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
     }
 
+    @Override
     public void reenableKeyguard(IBinder token) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
             != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
         }
 
-        synchronized (mKeyguardTokenWatcher) {
-            mKeyguardTokenWatcher.release(token);
-
-            if (!mKeyguardTokenWatcher.isAcquired()) {
-                // If we are the last one to reenable the keyguard wait until
-                // we have actually finished reenabling until returning.
-                // It is possible that reenableKeyguard() can be called before
-                // the previous disableKeyguard() is handled, in which case
-                // neither mKeyguardTokenWatcher.acquired() or released() would
-                // be called. In that case mKeyguardDisabled will be false here
-                // and we have nothing to wait for.
-                while (mKeyguardDisabled) {
-                    try {
-                        mKeyguardTokenWatcher.wait();
-                    } catch (InterruptedException e) {
-                        Thread.currentThread().interrupt();
-                    }
-                }
-            }
-        }
+        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
+                KeyguardDisableHandler.KEYGUARD_REENABLE, token));
     }
 
     /**
@@ -5044,8 +5303,9 @@
 
     public void closeSystemDialogs(String reason) {
         synchronized(mWindowMap) {
-            for (int i=mWindows.size()-1; i>=0; i--) {
-                WindowState w = mWindows.get(i);
+            final AllWindowsIterator iterator = new AllWindowsIterator();
+            while (iterator.hasNext()) {
+                final WindowState w = iterator.next();
                 if (w.mHasSurface) {
                     try {
                         w.mClient.closeSystemDialogs(reason);
@@ -5095,7 +5355,7 @@
                 mTransitionAnimationScale = fixScale(scales[1]);
             }
             if (scales.length >= 3) {
-                mAnimatorDurationScale = fixScale(scales[2]);
+                setAnimatorDurationScale(fixScale(scales[2]));
             }
         }
 
@@ -5103,6 +5363,11 @@
         mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
     }
 
+    private void setAnimatorDurationScale(float scale) {
+        mAnimatorDurationScale = scale;
+        ValueAnimator.setDurationScale(scale);
+    }
+
     public float getAnimationScale(int which) {
         switch (which) {
             case 0: return mWindowAnimationScale;
@@ -5148,20 +5413,46 @@
 
     // Called by window manager policy.  Not exposed externally.
     @Override
-    public void shutdown() {
-        ShutdownThread.shutdown(mContext, true);
+    public void shutdown(boolean confirm) {
+        ShutdownThread.shutdown(mContext, confirm);
     }
 
     // Called by window manager policy.  Not exposed externally.
     @Override
-    public void rebootSafeMode() {
-        ShutdownThread.rebootSafeMode(mContext, true);
+    public void rebootSafeMode(boolean confirm) {
+        ShutdownThread.rebootSafeMode(mContext, confirm);
     }
 
-    public void setInputFilter(InputFilter filter) {
+    public void setInputFilter(IInputFilter filter) {
+        if (!checkCallingPermission(android.Manifest.permission.FILTER_EVENTS, "setInputFilter()")) {
+            throw new SecurityException("Requires FILTER_EVENTS permission");
+        }
         mInputManager.setInputFilter(filter);
     }
 
+    public void setCurrentUser(final int newUserId) {
+        synchronized (mWindowMap) {
+            mCurrentUserId = newUserId;
+            mPolicy.setCurrentUserLw(newUserId);
+
+            // Hide windows that should not be seen by the new user.
+            DisplayContentsIterator iterator = new DisplayContentsIterator();
+            while (iterator.hasNext()) {
+                final WindowList windows = iterator.next().getWindowList();
+                for (int i = 0; i < windows.size(); i++) {
+                    final WindowState win = windows.get(i);
+                    if (win.isHiddenFromUserLocked()) {
+                        Slog.w(TAG, "current user violation " + newUserId + " hiding "
+                                + win + ", attrs=" + win.mAttrs.type + ", belonging to "
+                                + win.mOwnerUid);
+                        win.hideLw(false);
+                    }
+                }
+            }
+            performLayoutAndPlaceSurfacesLocked();
+        }
+    }
+
     public void enableScreenAfterBoot() {
         synchronized(mWindowMap) {
             if (DEBUG_BOOT) {
@@ -5247,10 +5538,12 @@
                         com.android.internal.R.bool.config_enableWallpaperService)
                         && !mOnlyCore;
                 boolean haveKeyguard = true;
-                final int N = mWindows.size();
+                // TODO(multidisplay): Expand to all displays?
+                final WindowList windows = getDefaultWindowListLocked();
+                final int N = windows.size();
                 for (int i=0; i<N; i++) {
-                    WindowState w = mWindows.get(i);
-                    if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD) {
+                    WindowState w = windows.get(i);
+                    if (w.mAttrs.type == TYPE_KEYGUARD) {
                         // Only if there is a keyguard attached to the window manager
                         // will we consider ourselves as having a keyguard.  If it
                         // isn't attached, we don't know if it wants to be shown or
@@ -5266,13 +5559,13 @@
                         return;
                     }
                     if (w.isDrawnLw()) {
-                        if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) {
+                        if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
                             haveBootMsg = true;
-                        } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION) {
+                        } else if (w.mAttrs.type == TYPE_APPLICATION) {
                             haveApp = true;
-                        } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER) {
+                        } else if (w.mAttrs.type == TYPE_WALLPAPER) {
                             haveWallpaper = true;
-                        } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD) {
+                        } else if (w.mAttrs.type == TYPE_KEYGUARD) {
                             haveKeyguard = true;
                         }
                     }
@@ -5389,20 +5682,21 @@
     @Override
     public void showStrictModeViolation(boolean on) {
         if (mHeadless) return;
-        mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, 0));
+        int pid = Binder.getCallingPid();
+        mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
     }
 
-    private void showStrictModeViolation(int arg) {
+    private void showStrictModeViolation(int arg, int pid) {
         final boolean on = arg != 0;
-        int pid = Binder.getCallingPid();
         synchronized(mWindowMap) {
             // Ignoring requests to enable the red border from clients
             // which aren't on screen.  (e.g. Broadcast Receivers in
             // the background..)
             if (on) {
                 boolean isVisible = false;
-                for (int i = mWindows.size() - 1; i >= 0; i--) {
-                    final WindowState ws = mWindows.get(i);
+                final AllWindowsIterator iterator = new AllWindowsIterator();
+                while (iterator.hasNext()) {
+                    final WindowState ws = iterator.next();
                     if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
                         isVisible = true;
                         break;
@@ -5417,8 +5711,10 @@
                     ">>> OPEN TRANSACTION showStrictModeViolation");
             Surface.openTransaction();
             try {
+                // TODO(multi-display): support multiple displays
                 if (mStrictModeFlash == null) {
-                    mStrictModeFlash = new StrictModeFlash(mDisplay, mFxSession);
+                    mStrictModeFlash = new StrictModeFlash(
+                            getDefaultDisplayContentLocked().getDisplay(), mFxSession);
                 }
                 mStrictModeFlash.setVisibility(on);
             } finally {
@@ -5438,10 +5734,12 @@
      * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
      * of the target image.
      * 
+     * @param displayId the Display to take a screenshot of.
      * @param width the width of the target bitmap
      * @param height the height of the target bitmap
      */
-    public Bitmap screenshotApplications(IBinder appToken, int width, int height) {
+    @Override
+    public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height) {
         if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
                 "screenshotApplications()")) {
             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
@@ -5459,12 +5757,16 @@
         synchronized(mWindowMap) {
             long ident = Binder.clearCallingIdentity();
 
-            dw = mCurDisplayWidth;
-            dh = mCurDisplayHeight;
+            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            if (displayContent == null) {
+                return null;
+            }
+            final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+            dw = displayInfo.logicalWidth;
+            dh = displayInfo.logicalHeight;
 
-            int aboveAppLayer = mPolicy.windowTypeToLayerLw(
-                    WindowManager.LayoutParams.TYPE_APPLICATION) * TYPE_LAYER_MULTIPLIER
-                    + TYPE_LAYER_OFFSET;
+            int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION)
+                    * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
             aboveAppLayer += TYPE_LAYER_MULTIPLIER;
 
             boolean isImeTarget = mInputMethodTarget != null
@@ -5474,8 +5776,9 @@
 
             // Figure out the part of the screen that is actually the app.
             boolean including = false;
-            for (int i=mWindows.size()-1; i>=0; i--) {
-                WindowState ws = mWindows.get(i);
+            final WindowList windows = displayContent.getWindowList();
+            for (int i = windows.size() - 1; i >= 0; i--) {
+                WindowState ws = windows.get(i);
                 if (!ws.mHasSurface) {
                     continue;
                 }
@@ -5527,7 +5830,7 @@
             }
 
             // The screenshot API does not apply the current screen rotation.
-            rot = mDisplay.getRotation();
+            rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
             int fw = frame.width();
             int fh = frame.height();
 
@@ -5562,10 +5865,11 @@
             }
             if (DEBUG_SCREENSHOT) {
                 Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from 0 to " + maxLayer);
-                for (int i=0; i<mWindows.size(); i++) {
-                    Slog.i(TAG, mWindows.get(i) + ": " + mWindows.get(i).mLayer
-                            + " animLayer=" + mWindows.get(i).mWinAnimator.mAnimLayer
-                            + " surfaceLayer=" + mWindows.get(i).mWinAnimator.mSurfaceLayer);
+                for (int i = 0; i < windows.size(); i++) {
+                    WindowState win = windows.get(i);
+                    Slog.i(TAG, win + ": " + win.mLayer
+                            + " animLayer=" + win.mWinAnimator.mAnimLayer
+                            + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
                 }
             }
             rawss = Surface.screenshot(dw, dh, 0, maxLayer);
@@ -5675,7 +5979,7 @@
         synchronized(mWindowMap) {
             changed = updateRotationUncheckedLocked(false);
             if (!changed || forceRelayout) {
-                mLayoutNeeded = true;
+                getDefaultDisplayContentLocked().layoutNeeded = true;
                 performLayoutAndPlaceSurfacesLocked();
             }
         }
@@ -5687,6 +5991,7 @@
         Binder.restoreCallingIdentity(origId);
     }
 
+    // TODO(multidisplay): Rotate any display?
     /**
      * Updates the current rotation.
      *
@@ -5701,8 +6006,9 @@
             return false;
         }
 
-        if (mAnimator.mScreenRotationAnimation != null &&
-                mAnimator.mScreenRotationAnimation.isAnimating()) {
+        ScreenRotationAnimation screenRotationAnimation =
+                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
+        if (screenRotationAnimation != null && screenRotationAnimation.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.
@@ -5750,62 +6056,73 @@
 
         mWindowsFreezingScreen = true;
         mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
-        mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT), 2000);
+        mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),
+                WINDOW_FREEZE_TIMEOUT_DURATION);
         mWaitingForConfig = true;
-        mLayoutNeeded = true;
-        startFreezingDisplayLocked(inTransaction);
-        mInputManager.setDisplayOrientation(0, rotation,
-                mDisplay != null ? mDisplay.getExternalRotation() : Surface.ROTATION_0);
+        getDefaultDisplayContentLocked().layoutNeeded = true;
+        startFreezingDisplayLocked(inTransaction, 0, 0);
+        // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
+        screenRotationAnimation =
+                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
 
         // We need to update our screen size information to match the new
         // rotation.  Note that this is redundant with the later call to
         // sendNewConfiguration() that must be called after this function
         // returns...  however we need to do the screen size part of that
-        // before then so we have the correct size to use when initializiation
+        // before then so we have the correct size to use when initializing
         // the rotation animation for the new rotation.
         computeScreenConfigurationLocked(null);
 
+        final DisplayContent displayContent = getDefaultDisplayContentLocked();
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
         if (!inTransaction) {
-            if (SHOW_TRANSACTIONS)  Slog.i(TAG,
-                    ">>> OPEN TRANSACTION setRotationUnchecked");
+            if (SHOW_TRANSACTIONS) {
+                Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");
+            }
             Surface.openTransaction();
         }
         try {
             // NOTE: We disable the rotation in the emulator because
             //       it doesn't support hardware OpenGL emulation yet.
-            if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null
-                    && mAnimator.mScreenRotationAnimation.hasScreenshot()) {
-                if (mAnimator.mScreenRotationAnimation.setRotation(rotation, mFxSession,
+            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
+                    && screenRotationAnimation.hasScreenshot()) {
+                if (screenRotationAnimation.setRotationInTransaction(
+                        rotation, mFxSession,
                         MAX_ANIMATION_DURATION, mTransitionAnimationScale,
-                        mCurDisplayWidth, mCurDisplayHeight)) {
-                    scheduleAnimationLocked();
+                        displayInfo.logicalWidth, displayInfo.logicalHeight)) {
+                    updateLayoutToAnimationLocked();
                 }
             }
-            Surface.setOrientation(0, rotation);
+
+            mDisplayManagerService.performTraversalInTransactionFromWindowManager();
         } finally {
             if (!inTransaction) {
                 Surface.closeTransaction();
-                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
-                        "<<< CLOSE TRANSACTION setRotationUnchecked");
+                if (SHOW_LIGHT_TRANSACTIONS) {
+                    Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");
+                }
             }
         }
 
-        rebuildBlackFrame();
-
-        for (int i=mWindows.size()-1; i>=0; i--) {
-            WindowState w = mWindows.get(i);
+        final WindowList windows = displayContent.getWindowList();
+        for (int i = windows.size() - 1; i >= 0; i--) {
+            WindowState w = windows.get(i);
             if (w.mHasSurface) {
                 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
                 w.mOrientationChanging = true;
                 mInnerFields.mOrientationChangeComplete = false;
             }
         }
+
         for (int i=mRotationWatchers.size()-1; i>=0; i--) {
             try {
                 mRotationWatchers.get(i).onRotationChanged(rotation);
             } catch (RemoteException e) {
             }
         }
+
+        scheduleNotifyRotationChangedIfNeededLocked(displayContent, rotation);
+
         return true;
     }
 
@@ -5864,7 +6181,9 @@
         synchronized (mWindowMap) {
             final int rotation = getRotation();
 
-            if (mInitialDisplayWidth < mInitialDisplayHeight) {
+            // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
+            final DisplayContent displayContent = getDefaultDisplayContentLocked();
+            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
                 // On devices with a natural orientation of portrait
                 switch (rotation) {
                     default:
@@ -5875,7 +6194,7 @@
                     case Surface.ROTATION_180:
                         return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
                     case Surface.ROTATION_270:
-                        return Gravity.LEFT | Gravity.BOTTOM;
+                        return Gravity.START | Gravity.BOTTOM;
                 }
             } else {
                 // On devices with a natural orientation of landscape
@@ -5886,7 +6205,7 @@
                     case Surface.ROTATION_90:
                         return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
                     case Surface.ROTATION_180:
-                        return Gravity.LEFT | Gravity.BOTTOM;
+                        return Gravity.START | Gravity.BOTTOM;
                     case Surface.ROTATION_270:
                         return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
                 }
@@ -6000,10 +6319,13 @@
 
         boolean result = true;
 
-        WindowState[] windows;
+        WindowList windows = new WindowList();
         synchronized (mWindowMap) {
             //noinspection unchecked
-            windows = mWindows.toArray(new WindowState[mWindows.size()]);
+            DisplayContentsIterator iterator = new DisplayContentsIterator();
+            while(iterator.hasNext()) {
+                windows.addAll(iterator.next().getWindowList());
+            }
         }
 
         BufferedWriter out = null;
@@ -6013,9 +6335,9 @@
             OutputStream clientStream = client.getOutputStream();
             out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
 
-            final int count = windows.length;
+            final int count = windows.size();
             for (int i = 0; i < count; i++) {
-                final WindowState w = windows[i];
+                final WindowState w = windows.get(i);
                 out.write(Integer.toHexString(System.identityHashCode(w)));
                 out.write(' ');
                 out.append(w.mAttrs.getTitle());
@@ -6039,6 +6361,7 @@
         return result;
     }
 
+    // TODO(multidisplay): Extend to multiple displays.
     /**
      * Returns the focused window in the following format:
      * windowHashCodeInHexadecimal windowName
@@ -6180,6 +6503,146 @@
         return success;
     }
 
+    @Override
+    public void addDisplayContentChangeListener(int displayId,
+            IDisplayContentChangeListener listener) {
+        if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
+                "addDisplayContentChangeListener()")) {
+            throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission");
+        }
+        synchronized(mWindowMap) {
+            DisplayContent displayContent = getDisplayContentLocked(displayId);
+            if (displayContent != null) {
+                if (displayContent.mDisplayContentChangeListeners == null) {
+                    displayContent.mDisplayContentChangeListeners =
+                            new RemoteCallbackList<IDisplayContentChangeListener>();
+                    displayContent.mDisplayContentChangeListeners.register(listener);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void removeDisplayContentChangeListener(int displayId,
+            IDisplayContentChangeListener listener) {
+        if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
+                "removeDisplayContentChangeListener()")) {
+            throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission");
+        }
+        synchronized(mWindowMap) {
+            DisplayContent displayContent = getDisplayContentLocked(displayId);
+            if (displayContent != null) {
+                if (displayContent.mDisplayContentChangeListeners != null) {
+                    displayContent.mDisplayContentChangeListeners.unregister(listener);
+                    if (displayContent.mDisplayContentChangeListeners
+                            .getRegisteredCallbackCount() == 0) {
+                        displayContent.mDisplayContentChangeListeners = null;
+                    }
+                }
+            }
+        }
+    }
+
+    void scheduleNotifyWindowTranstionIfNeededLocked(WindowState window, int transition) {
+        DisplayContent displayContent = window.mDisplayContent;
+        if (displayContent.mDisplayContentChangeListeners != null) {
+            WindowInfo info = getWindowInfoForWindowStateLocked(window);
+            mH.obtainMessage(H.NOTIFY_WINDOW_TRANSITION, transition, 0, info).sendToTarget();
+        }
+    }
+
+    private void handleNotifyWindowTranstion(int transition, WindowInfo info) {
+        RemoteCallbackList<IDisplayContentChangeListener> callbacks = null;
+        synchronized (mWindowMap) {
+            DisplayContent displayContent = getDisplayContentLocked(info.displayId);
+            if (displayContent == null) {
+                return;
+            }
+            callbacks = displayContent.mDisplayContentChangeListeners;
+            if (callbacks == null) {
+                return;
+            }
+        }
+        final int callbackCount = callbacks.beginBroadcast();
+        try {
+            for (int i = 0; i < callbackCount; i++) {
+                try {
+                    callbacks.getBroadcastItem(i).onWindowTransition(info.displayId,
+                            transition, info);
+                } catch (RemoteException re) {
+                    /* ignore */
+                }
+            }
+        } finally {
+            callbacks.finishBroadcast();
+        }
+    }
+
+    private void scheduleNotifyRotationChangedIfNeededLocked(DisplayContent displayContent,
+            int rotation) {
+        if (displayContent.mDisplayContentChangeListeners != null
+                && displayContent.mDisplayContentChangeListeners.getRegisteredCallbackCount() > 0) {
+            mH.obtainMessage(H.NOTIFY_ROTATION_CHANGED, displayContent.getDisplayId(),
+                    rotation).sendToTarget();
+        }
+    }
+
+    private void handleNotifyRotationChanged(int displayId, int rotation) {
+        RemoteCallbackList<IDisplayContentChangeListener> callbacks = null;
+        synchronized (mWindowMap) {
+            DisplayContent displayContent = getDisplayContentLocked(displayId);
+            if (displayContent == null) {
+                return;
+            }
+            callbacks = displayContent.mDisplayContentChangeListeners;
+            if (callbacks == null) {
+                return;
+            }
+        }
+        try {
+            final int watcherCount = callbacks.beginBroadcast();
+            for (int i = 0; i < watcherCount; i++) {
+                try {
+                    callbacks.getBroadcastItem(i).onRotationChanged(rotation);
+                } catch (RemoteException re) {
+                    /* ignore */
+                }
+            }
+        } finally {
+            callbacks.finishBroadcast();
+        }
+    }
+
+    private void scheduleNotifyWindowLayersChangedIfNeededLocked(DisplayContent displayContent) {
+        if (displayContent.mDisplayContentChangeListeners != null
+                && displayContent.mDisplayContentChangeListeners.getRegisteredCallbackCount() > 0) {
+            mH.obtainMessage(H.NOTIFY_WINDOW_LAYERS_CHANGED, displayContent) .sendToTarget();
+        }
+    }
+
+    private void handleNotifyWindowLayersChanged(DisplayContent displayContent) {
+        RemoteCallbackList<IDisplayContentChangeListener> callbacks = null;
+        synchronized (mWindowMap) {
+            callbacks = displayContent.mDisplayContentChangeListeners;
+            if (callbacks == null) {
+                return;
+            }
+        }
+        try {
+            final int watcherCount = callbacks.beginBroadcast();
+            for (int i = 0; i < watcherCount; i++) {
+                try {
+                    callbacks.getBroadcastItem(i).onWindowLayersChanged(
+                            displayContent.getDisplayId());
+                } catch (RemoteException re) {
+                    /* ignore */
+                }
+            }
+        } finally {
+            callbacks.finishBroadcast();
+        }
+    }
+
     public void addWindowChangeListener(WindowChangeListener listener) {
         synchronized(mWindowMap) {
             mWindowChangeListeners.add(listener);
@@ -6224,15 +6687,14 @@
 
     private WindowState findWindow(int hashCode) {
         if (hashCode == -1) {
+            // TODO(multidisplay): Extend to multiple displays.
             return getFocusedWindow();
         }
 
         synchronized (mWindowMap) {
-            final ArrayList<WindowState> windows = mWindows;
-            final int count = windows.size();
-
-            for (int i = 0; i < count; i++) {
-                WindowState w = windows.get(i);
+            final AllWindowsIterator iterator = new AllWindowsIterator();
+            while (iterator.hasNext()) {
+                final WindowState w = iterator.next();
                 if (System.identityHashCode(w) == hashCode) {
                     return w;
                 }
@@ -6274,33 +6736,32 @@
         return config;
     }
 
-    private void adjustDisplaySizeRanges(int rotation, int dw, int dh) {
+    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
+        // TODO: Multidisplay: for now only use with default display.
         final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
-        if (width < mSmallestDisplayWidth) {
-            mSmallestDisplayWidth = width;
+        if (width < displayInfo.smallestNominalAppWidth) {
+            displayInfo.smallestNominalAppWidth = width;
         }
-        if (width > mLargestDisplayWidth) {
-            mLargestDisplayWidth = width;
+        if (width > displayInfo.largestNominalAppWidth) {
+            displayInfo.largestNominalAppWidth = width;
         }
         final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
-        if (height < mSmallestDisplayHeight) {
-            mSmallestDisplayHeight = height;
+        if (height < displayInfo.smallestNominalAppHeight) {
+            displayInfo.smallestNominalAppHeight = height;
         }
-        if (height > mLargestDisplayHeight) {
-            mLargestDisplayHeight = height;
+        if (height > displayInfo.largestNominalAppHeight) {
+            displayInfo.largestNominalAppHeight = height;
         }
     }
 
     private int reduceConfigLayout(int curLayout, int rotation, float density,
             int dw, int dh) {
+        // TODO: Multidisplay: for now only use with default display.
         // Get the app screen size at this rotation.
         int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
         int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
 
         // Compute the screen layout size class for this rotation.
-        int screenLayoutSize;
-        boolean screenLayoutLong;
-        boolean screenLayoutCompatNeeded;
         int longSize = w;
         int shortSize = h;
         if (longSize < shortSize) {
@@ -6310,68 +6771,13 @@
         }
         longSize = (int)(longSize/density);
         shortSize = (int)(shortSize/density);
-
-        // These semi-magic numbers define our compatibility modes for
-        // applications with different screens.  These are guarantees to
-        // app developers about the space they can expect for a particular
-        // configuration.  DO NOT CHANGE!
-        if (longSize < 470) {
-            // This is shorter than an HVGA normal density screen (which
-            // is 480 pixels on its long side).
-            screenLayoutSize = Configuration.SCREENLAYOUT_SIZE_SMALL;
-            screenLayoutLong = false;
-            screenLayoutCompatNeeded = false;
-        } else {
-            // What size is this screen screen?
-            if (longSize >= 960 && shortSize >= 720) {
-                // 1.5xVGA or larger screens at medium density are the point
-                // at which we consider it to be an extra large screen.
-                screenLayoutSize = Configuration.SCREENLAYOUT_SIZE_XLARGE;
-            } else if (longSize >= 640 && shortSize >= 480) {
-                // VGA or larger screens at medium density are the point
-                // at which we consider it to be a large screen.
-                screenLayoutSize = Configuration.SCREENLAYOUT_SIZE_LARGE;
-            } else {
-                screenLayoutSize = Configuration.SCREENLAYOUT_SIZE_NORMAL;
-            }
-
-            // If this screen is wider than normal HVGA, or taller
-            // than FWVGA, then for old apps we want to run in size
-            // compatibility mode.
-            if (shortSize > 321 || longSize > 570) {
-                screenLayoutCompatNeeded = true;
-            } else {
-                screenLayoutCompatNeeded = false;
-            }
-
-            // Is this a long screen?
-            if (((longSize*3)/5) >= (shortSize-1)) {
-                // Anything wider than WVGA (5:3) is considering to be long.
-                screenLayoutLong = true;
-            } else {
-                screenLayoutLong = false;
-            }
-        }
-
-        // Now reduce the last screenLayout to not be better than what we
-        // have found.
-        if (!screenLayoutLong) {
-            curLayout = (curLayout&~Configuration.SCREENLAYOUT_LONG_MASK)
-                    | Configuration.SCREENLAYOUT_LONG_NO;
-        }
-        if (screenLayoutCompatNeeded) {
-            curLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
-        }
-        int curSize = curLayout&Configuration.SCREENLAYOUT_SIZE_MASK;
-        if (screenLayoutSize < curSize) {
-            curLayout = (curLayout&~Configuration.SCREENLAYOUT_SIZE_MASK)
-                    | screenLayoutSize;
-        }
-        return curLayout;
+        return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
     }
 
-    private void computeSizeRangesAndScreenLayout(boolean rotated, int dw, int dh,
-            float density, Configuration outConfig) {
+    private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
+                  int dw, int dh, float density, Configuration outConfig) {
+        // TODO: Multidisplay: for now only use with default display.
+
         // We need to determine the smallest width that will occur under normal
         // operation.  To this, start with the base screen size and compute the
         // width under the different possible rotations.  We need to un-rotate
@@ -6384,26 +6790,26 @@
             unrotDw = dw;
             unrotDh = dh;
         }
-        mSmallestDisplayWidth = 1<<30;
-        mSmallestDisplayHeight = 1<<30;
-        mLargestDisplayWidth = 0;
-        mLargestDisplayHeight = 0;
-        adjustDisplaySizeRanges(Surface.ROTATION_0, unrotDw, unrotDh);
-        adjustDisplaySizeRanges(Surface.ROTATION_90, unrotDh, unrotDw);
-        adjustDisplaySizeRanges(Surface.ROTATION_180, unrotDw, unrotDh);
-        adjustDisplaySizeRanges(Surface.ROTATION_270, unrotDh, unrotDw);
-        int sl = Configuration.SCREENLAYOUT_SIZE_XLARGE
-                | Configuration.SCREENLAYOUT_LONG_YES;
+        displayInfo.smallestNominalAppWidth = 1<<30;
+        displayInfo.smallestNominalAppHeight = 1<<30;
+        displayInfo.largestNominalAppWidth = 0;
+        displayInfo.largestNominalAppHeight = 0;
+        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
+        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
+        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
+        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
+        int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
         sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
         sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
         sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
         sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
-        outConfig.smallestScreenWidthDp = (int)(mSmallestDisplayWidth / density);
+        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
         outConfig.screenLayout = sl;
     }
 
     private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
             int dw, int dh) {
+        // TODO: Multidisplay: for now only use with default display.
         dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
         dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
         float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
@@ -6415,9 +6821,10 @@
     }
 
     private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) {
+        // TODO: Multidisplay: for now only use with default display.
         mTmpDisplayMetrics.setTo(dm);
-        dm = mTmpDisplayMetrics;
-        int unrotDw, unrotDh;
+        final DisplayMetrics tmpDm = mTmpDisplayMetrics;
+        final int unrotDw, unrotDh;
         if (rotated) {
             unrotDw = dh;
             unrotDh = dw;
@@ -6425,79 +6832,75 @@
             unrotDw = dw;
             unrotDh = dh;
         }
-        int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, dm, unrotDw, unrotDh);
-        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, dm, unrotDh, unrotDw);
-        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, dm, unrotDw, unrotDh);
-        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, dm, unrotDh, unrotDw);
+        int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh);
+        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw);
+        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh);
+        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw);
         return sw;
     }
 
     boolean computeScreenConfigurationLocked(Configuration config) {
-        if (mDisplay == null) {
+        if (!mDisplayReady) {
             return false;
         }
 
+        // TODO(multidisplay): For now, apply Configuration to main screen only.
+        final DisplayContent displayContent = getDefaultDisplayContentLocked();
+
         // Use the effective "visual" dimensions based on current rotation
         final boolean rotated = (mRotation == Surface.ROTATION_90
                 || mRotation == Surface.ROTATION_270);
-        final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
-        final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
+        final int realdw = rotated ?
+                displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
+        final int realdh = rotated ?
+                displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
+        int dw = realdw;
+        int dh = realdh;
 
-        synchronized(mDisplaySizeLock) {
-            if (mAltOrientation) {
-                mCurDisplayWidth = realdw;
-                mCurDisplayHeight = realdh;
-                if (realdw > realdh) {
-                    // Turn landscape into portrait.
-                    int maxw = (int)(realdh/1.3f);
-                    if (maxw < realdw) {
-                        mCurDisplayWidth = maxw;
-                    }
-                } else {
-                    // Turn portrait into landscape.
-                    int maxh = (int)(realdw/1.3f);
-                    if (maxh < realdh) {
-                        mCurDisplayHeight = maxh;
-                    }
+        if (mAltOrientation) {
+            if (realdw > realdh) {
+                // Turn landscape into portrait.
+                int maxw = (int)(realdh/1.3f);
+                if (maxw < realdw) {
+                    dw = maxw;
                 }
             } else {
-                mCurDisplayWidth = realdw;
-                mCurDisplayHeight = realdh;
+                // Turn portrait into landscape.
+                int maxh = (int)(realdw/1.3f);
+                if (maxh < realdh) {
+                    dh = maxh;
+                }
             }
         }
 
-        final int dw = mCurDisplayWidth;
-        final int dh = mCurDisplayHeight;
-
         if (config != null) {
-            int orientation = Configuration.ORIENTATION_SQUARE;
-            if (dw < dh) {
-                orientation = Configuration.ORIENTATION_PORTRAIT;
-            } else if (dw > dh) {
-                orientation = Configuration.ORIENTATION_LANDSCAPE;
-            }
-            config.orientation = orientation;
+            config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
+                    Configuration.ORIENTATION_LANDSCAPE;
         }
 
-        // Update real display metrics.
-        mDisplay.getMetricsWithSize(mRealDisplayMetrics, mCurDisplayWidth, mCurDisplayHeight);
-
         // Update application display metrics.
-        final DisplayMetrics dm = mDisplayMetrics;
         final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
         final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
-        synchronized(mDisplaySizeLock) {
-            mAppDisplayWidth = appWidth;
-            mAppDisplayHeight = appHeight;
-            mAnimator.setDisplayDimensions(mCurDisplayWidth, mCurDisplayHeight,
-                    mAppDisplayWidth, mAppDisplayHeight);
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        synchronized(displayContent.mDisplaySizeLock) {
+            displayInfo.rotation = mRotation;
+            displayInfo.logicalWidth = dw;
+            displayInfo.logicalHeight = dh;
+            displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
+            displayInfo.appWidth = appWidth;
+            displayInfo.appHeight = appHeight;
+            displayInfo.getLogicalMetrics(mRealDisplayMetrics, null);
+            displayInfo.getAppMetrics(mDisplayMetrics, null);
+            mDisplayManagerService.setDisplayInfoOverrideFromWindowManager(
+                    displayContent.getDisplayId(), displayInfo);
+
+            mAnimator.setDisplayDimensions(dw, dh, appWidth, appHeight);
         }
         if (false) {
-            Slog.i(TAG, "Set app display size: " + mAppDisplayWidth
-                    + " x " + mAppDisplayHeight);
+            Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
         }
-        mDisplay.getMetricsWithSize(dm, mAppDisplayWidth, mAppDisplayHeight);
 
+        final DisplayMetrics dm = mDisplayMetrics;
         mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
                 mCompatDisplayMetrics);
 
@@ -6506,11 +6909,12 @@
                     / dm.density);
             config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
                     / dm.density);
-            computeSizeRangesAndScreenLayout(rotated, dw, dh, dm.density, config);
+            computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
 
             config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
             config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
             config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
+            config.densityDpi = displayContent.mBaseDisplayDensity;
 
             // Update the configuration based on available input devices, lid switch,
             // and platform configuration.
@@ -6638,8 +7042,12 @@
             synchronized (mWindowMap) {
                 try {
                     if (mDragState == null) {
-                        Surface surface = new Surface(session, callerPid, "drag surface", 0,
+                        // TODO(multi-display): support other displays
+                        final DisplayContent displayContent = getDefaultDisplayContentLocked();
+                        final Display display = displayContent.getDisplay();
+                        Surface surface = new Surface(session, "drag surface",
                                 width, height, PixelFormat.TRANSLUCENT, Surface.HIDDEN);
+                        surface.setLayerStack(display.getLayerStack());
                         if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
                                 + surface + ": CREATE");
                         outSurface.copyFrom(surface);
@@ -6720,8 +7128,11 @@
         }
     }
 
-    // TODO: Put this on the IWindowManagerService and guard with a permission.
-    public IBinder getFocusedWindowClientToken() {
+    public IBinder getFocusedWindowToken() {
+        if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
+                "getFocusedWindowToken()")) {
+            throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
+        }
         synchronized (mWindowMap) {
             WindowState windowState = getFocusedWindowLocked();
             if (windowState != null) {
@@ -6731,18 +7142,6 @@
         }
     }
 
-    // TODO: This is a workaround - remove when 6623031 is fixed.
-    public boolean getWindowFrame(IBinder token, Rect outBounds) {
-        synchronized (mWindowMap) {
-            WindowState windowState = mWindowMap.get(token);
-            if (windowState != null) {
-                outBounds.set(windowState.getFrameLw());
-                return true;
-            }
-        }
-        return false;
-    }
-
     private WindowState getFocusedWindow() {
         synchronized (mWindowMap) {
             return getFocusedWindowLocked();
@@ -6790,45 +7189,53 @@
     }
 
     public void displayReady() {
+        displayReady(Display.DEFAULT_DISPLAY);
+
         synchronized(mWindowMap) {
-            if (mDisplay != null) {
-                throw new IllegalStateException("Display already initialized");
-            }
-            WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
-            mDisplay = wm.getDefaultDisplay();
+            final DisplayContent displayContent = getDefaultDisplayContentLocked();
+            readForcedDisplaySizeAndDensityLocked(displayContent);
+
+            mDisplayReady = true;
             mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
                     PackageManager.FEATURE_TOUCHSCREEN);
-            synchronized(mDisplaySizeLock) {
-                mInitialDisplayWidth = mDisplay.getRawWidth();
-                mInitialDisplayHeight = mDisplay.getRawHeight();
-                int rot = mDisplay.getRotation();
-                if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
-                    // If the screen is currently rotated, we need to swap the
-                    // initial width and height to get the true natural values.
-                    int tmp = mInitialDisplayWidth;
-                    mInitialDisplayWidth = mInitialDisplayHeight;
-                    mInitialDisplayHeight = tmp;
-                }
-                mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth;
-                mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight;
-                mAnimator.setDisplayDimensions(mCurDisplayWidth, mCurDisplayHeight,
-                        mAppDisplayWidth, mAppDisplayHeight);
-            }
-            mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY,
-                    mDisplay.getRawWidth(), mDisplay.getRawHeight(),
-                    mDisplay.getRawExternalWidth(), mDisplay.getRawExternalHeight());
-            mInputManager.setDisplayOrientation(Display.DEFAULT_DISPLAY,
-                    mDisplay.getRotation(), mDisplay.getExternalRotation());
-            mPolicy.setInitialDisplaySize(mDisplay, mInitialDisplayWidth, mInitialDisplayHeight);
+
+            final DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
+            mAnimator.setDisplayDimensions(
+                    displayInfo.logicalWidth, displayInfo.logicalHeight,
+                    displayInfo.appWidth, displayInfo.appHeight);
+
+            mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
+                    displayContent.mInitialDisplayWidth,
+                    displayContent.mInitialDisplayHeight,
+                    displayContent.mInitialDisplayDensity);
         }
 
         try {
             mActivityManager.updateConfiguration(null);
         } catch (RemoteException e) {
         }
-        
-        synchronized (mWindowMap) {
-            readForcedDisplaySizeLocked();
+    }
+
+    private void displayReady(int displayId) {
+        synchronized(mWindowMap) {
+            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            if (displayContent != null) {
+                mAnimator.addDisplayLocked(displayId);
+                synchronized(displayContent.mDisplaySizeLock) {
+                    // Bootstrap the default logical display from the display manager.
+                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+                    DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId);
+                    if (newDisplayInfo != null) {
+                        displayInfo.copyFrom(newDisplayInfo);
+                    }
+                    displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
+                    displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
+                    displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
+                    displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
+                    displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
+                    displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
+                }
+            }
         }
     }
 
@@ -6836,14 +7243,13 @@
         mPolicy.systemReady();
     }
 
+    // TODO(multidisplay): Call isScreenOn for each display.
     private void sendScreenStatusToClientsLocked() {
-        final ArrayList<WindowState> windows = mWindows;
-        final int count = windows.size();
-        boolean on = mPowerManager.isScreenOn();
-        for (int i = count - 1; i >= 0; i--) {
-            WindowState win = mWindows.get(i);
+        final boolean on = mPowerManager.isScreenOn();
+        final AllWindowsIterator iterator = new AllWindowsIterator();
+        while (iterator.hasNext()) {
             try {
-                win.mClient.dispatchScreenState(on);
+                iterator.next().mClient.dispatchScreenState(on);
             } catch (RemoteException e) {
                 // Ignored
             }
@@ -6864,7 +7270,7 @@
         public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
         public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
         public static final int WINDOW_FREEZE_TIMEOUT = 11;
-        public static final int HOLD_SCREEN_CHANGED = 12;
+
         public static final int APP_TRANSITION_TIMEOUT = 13;
         public static final int PERSIST_ANIMATION_SCALE = 14;
         public static final int FORCE_GC = 15;
@@ -6877,17 +7283,23 @@
         public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
         public static final int BOOT_TIMEOUT = 23;
         public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
-        public static final int BULK_UPDATE_PARAMETERS = 25;
+        public static final int UPDATE_ANIM_PARAMETERS = 25;
         public static final int SHOW_STRICT_MODE_VIOLATION = 26;
         public static final int DO_ANIMATION_CALLBACK = 27;
+        public static final int NOTIFY_ROTATION_CHANGED = 28;
+        public static final int NOTIFY_WINDOW_TRANSITION = 29;
+        public static final int NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED = 30;
+        public static final int NOTIFY_WINDOW_LAYERS_CHANGED = 31;
+
+        public static final int DO_DISPLAY_ADDED = 32;
+        public static final int DO_DISPLAY_REMOVED = 33;
+        public static final int DO_DISPLAY_CHANGED = 34;
+
+        public static final int CLIENT_FREEZE_TIMEOUT = 35;
 
         public static final int ANIMATOR_WHAT_OFFSET = 100000;
         public static final int SET_TRANSPARENT_REGION = ANIMATOR_WHAT_OFFSET + 1;
-        public static final int SET_WALLPAPER_OFFSET = ANIMATOR_WHAT_OFFSET + 2;
-        public static final int SET_DIM_PARAMETERS = ANIMATOR_WHAT_OFFSET + 3;
-        public static final int CLEAR_PENDING_ACTIONS = ANIMATOR_WHAT_OFFSET + 4;
-
-        private Session mLastReportedHold;
+        public static final int CLEAR_PENDING_ACTIONS = ANIMATOR_WHAT_OFFSET + 2;
 
         public H() {
         }
@@ -7122,12 +7534,14 @@
                 } break;
 
                 case WINDOW_FREEZE_TIMEOUT: {
+                    // TODO(multidisplay): Can non-default displays rotate?
                     synchronized (mWindowMap) {
                         Slog.w(TAG, "Window freeze timeout expired.");
-                        int i = mWindows.size();
+                        final WindowList windows = getDefaultWindowListLocked();
+                        int i = windows.size();
                         while (i > 0) {
                             i--;
-                            WindowState w = mWindows.get(i);
+                            WindowState w = windows.get(i);
                             if (w.mOrientationChanging) {
                                 w.mOrientationChanging = false;
                                 Slog.w(TAG, "Force clearing orientation change: " + w);
@@ -7138,33 +7552,6 @@
                     break;
                 }
 
-                case HOLD_SCREEN_CHANGED: {
-                    Session oldHold;
-                    Session newHold;
-                    synchronized (mWindowMap) {
-                        oldHold = mLastReportedHold;
-                        newHold = (Session)msg.obj;
-                        mLastReportedHold = newHold;
-                    }
-
-                    if (oldHold != newHold) {
-                        try {
-                            if (oldHold != null) {
-                                mBatteryStats.noteStopWakelock(oldHold.mUid, -1,
-                                        "window",
-                                        BatteryStats.WAKE_TYPE_WINDOW);
-                            }
-                            if (newHold != null) {
-                                mBatteryStats.noteStartWakelock(newHold.mUid, -1,
-                                        "window",
-                                        BatteryStats.WAKE_TYPE_WINDOW);
-                            }
-                        } catch (RemoteException e) {
-                        }
-                    }
-                    break;
-                }
-
                 case APP_TRANSITION_TIMEOUT: {
                     synchronized (mWindowMap) {
                         if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
@@ -7181,28 +7568,32 @@
                 }
 
                 case PERSIST_ANIMATION_SCALE: {
-                    Settings.System.putFloat(mContext.getContentResolver(),
-                            Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
-                    Settings.System.putFloat(mContext.getContentResolver(),
-                            Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
-                    Settings.System.putFloat(mContext.getContentResolver(),
-                            Settings.System.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale);
+                    Settings.Global.putFloat(mContext.getContentResolver(),
+                            Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
+                    Settings.Global.putFloat(mContext.getContentResolver(),
+                            Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
+                    Settings.Global.putFloat(mContext.getContentResolver(),
+                            Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale);
                     break;
                 }
 
                 case FORCE_GC: {
-                    synchronized(mWindowMap) {
-                        if (mAnimationScheduled) {
-                            // If we are animating, don't do the gc now but
-                            // delay a bit so we don't interrupt the animation.
-                            mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
-                                    2000);
-                            return;
-                        }
-                        // If we are currently rotating the display, it will
-                        // schedule a new message when done.
-                        if (mDisplayFrozen) {
-                            return;
+                    synchronized (mWindowMap) {
+                        synchronized (mAnimator) {
+                            // Since we're holding both mWindowMap and mAnimator we don't need to
+                            // hold mAnimator.mLayoutToAnim.
+                            if (mAnimator.mAnimating || mLayoutToAnim.mAnimationScheduled) {
+                                // If we are animating, don't do the gc now but
+                                // delay a bit so we don't interrupt the animation.
+                                mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
+                                        2000);
+                                return;
+                            }
+                            // If we are currently rotating the display, it will
+                            // schedule a new message when done.
+                            if (mDisplayFrozen) {
+                                return;
+                            }
                         }
                     }
                     Runtime.getRuntime().gc();
@@ -7232,6 +7623,16 @@
                     break;
                 }
 
+                case CLIENT_FREEZE_TIMEOUT: {
+                    synchronized (mWindowMap) {
+                        if (mClientFreezingScreen) {
+                            mClientFreezingScreen = false;
+                            stopFreezingDisplayLocked();
+                        }
+                    }
+                    break;
+                }
+
                 case SEND_NEW_CONFIGURATION: {
                     removeMessages(SEND_NEW_CONFIGURATION);
                     sendNewConfiguration();
@@ -7306,42 +7707,10 @@
                     break;
                 }
 
-                case BULK_UPDATE_PARAMETERS: {
+                case UPDATE_ANIM_PARAMETERS: {
                     // Used to send multiple changes from the animation side to the layout side.
                     synchronized (mWindowMap) {
-                        boolean doRequest = false;
-                        // TODO(cmautner): As the number of bits grows, use masks of bit groups to
-                        //  eliminate unnecessary tests.
-                        if ((msg.arg1 & LayoutFields.SET_UPDATE_ROTATION) != 0) {
-                            mInnerFields.mUpdateRotation = true;
-                            doRequest = true;
-                        }
-                        if ((msg.arg1 & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
-                            mInnerFields.mWallpaperMayChange = true;
-                            doRequest = true;
-                        }
-                        if ((msg.arg1 & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
-                            mInnerFields.mWallpaperForceHidingChanged = true;
-                            doRequest = true;
-                        }
-                        if ((msg.arg1 & LayoutFields.CLEAR_ORIENTATION_CHANGE_COMPLETE) != 0) {
-                            mInnerFields.mOrientationChangeComplete = false;
-                        } else {
-                            mInnerFields.mOrientationChangeComplete = true;
-                            if (mWindowsFreezingScreen) {
-                                doRequest = true;
-                            }
-                        }
-                        if ((msg.arg1 & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
-                            mTurnOnScreen = true;
-                        }
-
-                        mPendingLayoutChanges |= msg.arg2;
-                        if (mPendingLayoutChanges != 0) {
-                            doRequest = true;
-                        }
-
-                        if (doRequest) {
+                        if (copyAnimToLayoutParamsLocked()) {
                             mH.sendEmptyMessage(CLEAR_PENDING_ACTIONS);
                             performLayoutAndPlaceSurfacesLocked();
                         }
@@ -7350,7 +7719,7 @@
                 }
 
                 case SHOW_STRICT_MODE_VIOLATION: {
-                    showStrictModeViolation(msg.arg1);
+                    showStrictModeViolation(msg.arg1, msg.arg2);
                     break;
                 }
 
@@ -7363,21 +7732,6 @@
                     break;
                 }
 
-                case SET_WALLPAPER_OFFSET: {
-                    final WindowStateAnimator winAnimator = (WindowStateAnimator) msg.obj;
-                    winAnimator.setWallpaperOffset(msg.arg1, msg.arg2);
-
-                    scheduleAnimationLocked();
-                    break;
-                }
-
-                case SET_DIM_PARAMETERS: {
-                    mAnimator.mDimParams = (DimAnimator.Parameters) msg.obj;
-
-                    scheduleAnimationLocked();
-                    break;
-                }
-
                 case CLEAR_PENDING_ACTIONS: {
                     mAnimator.clearPendingActions();
                     break;
@@ -7390,6 +7744,52 @@
                     }
                     break;
                 }
+
+                case NOTIFY_ROTATION_CHANGED: {
+                    final int displayId = msg.arg1;
+                    final int rotation = msg.arg2;
+                    handleNotifyRotationChanged(displayId, rotation);
+                    break;
+                }
+
+                case NOTIFY_WINDOW_TRANSITION: {
+                    final int transition = msg.arg1;
+                    WindowInfo info = (WindowInfo) msg.obj;
+                    handleNotifyWindowTranstion(transition, info);
+                    break;
+                }
+
+                case NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED: {
+                    final int displayId = msg.arg1;
+                    final boolean immediate = (msg.arg2 == 1);
+                    Rect rectangle = (Rect) msg.obj;
+                    handleNotifyRectangleOnScreenRequested(displayId, rectangle, immediate);
+                    break;
+                }
+
+                case NOTIFY_WINDOW_LAYERS_CHANGED: {
+                    DisplayContent displayContent = (DisplayContent) msg.obj;
+                    handleNotifyWindowLayersChanged(displayContent);
+                    break;
+                }
+
+                case DO_DISPLAY_ADDED:
+                    synchronized (mWindowMap) {
+                        handleDisplayAddedLocked(msg.arg1);
+                    }
+                    break;
+
+                case DO_DISPLAY_REMOVED:
+                    synchronized (mWindowMap) {
+                        handleDisplayRemovedLocked(msg.arg1);
+                    }
+                    break;
+
+                case DO_DISPLAY_CHANGED:
+                    synchronized (mWindowMap) {
+                        handleDisplayChangedLocked(msg.arg1);
+                    }
+                    break;
             }
             if (DEBUG_WINDOW_TRACE) {
                 Slog.v(TAG, "handleMessage: exit");
@@ -7416,13 +7816,13 @@
             // The focus for the client is the window immediately below
             // where we would place the input method window.
             int idx = findDesiredInputMethodWindowIndexLocked(false);
-            WindowState imFocus;
             if (idx > 0) {
-                imFocus = mWindows.get(idx-1);
+                // TODO(multidisplay): IMEs are only supported on the default display.
+                WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
                 if (DEBUG_INPUT_METHOD) {
                     Slog.i(TAG, "Desired input method target: " + imFocus);
-                    Slog.i(TAG, "Current focus: " + this.mCurrentFocus);
-                    Slog.i(TAG, "Last focus: " + this.mLastFocus);
+                    Slog.i(TAG, "Current focus: " + mCurrentFocus);
+                    Slog.i(TAG, "Last focus: " + mLastFocus);
                 }
                 if (imFocus != null) {
                     // This may be a starting window, in which case we still want
@@ -7452,143 +7852,164 @@
                             imFocus.mSession.mClient.asBinder() == client.asBinder()) {
                         return true;
                     }
-                    
-                    // Okay, how about this...  what is the current focus?
-                    // It seems in some cases we may not have moved the IM
-                    // target window, such as when it was in a pop-up window,
-                    // so let's also look at the current focus.  (An example:
-                    // go to Gmail, start searching so the keyboard goes up,
-                    // press home.  Sometimes the IME won't go down.)
-                    // Would be nice to fix this more correctly, but it's
-                    // way at the end of a release, and this should be good enough.
-                    if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null &&
-                            mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
-                        return true;
-                    }
                 }
             }
+
+            // Okay, how about this...  what is the current focus?
+            // It seems in some cases we may not have moved the IM
+            // target window, such as when it was in a pop-up window,
+            // so let's also look at the current focus.  (An example:
+            // go to Gmail, start searching so the keyboard goes up,
+            // press home.  Sometimes the IME won't go down.)
+            // Would be nice to fix this more correctly, but it's
+            // way at the end of a release, and this should be good enough.
+            if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
+                    && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
+                return true;
+            }
         }
         return false;
     }
 
-    public void getDisplaySize(Point size) {
-        synchronized(mDisplaySizeLock) {
-            size.x = mAppDisplayWidth;
-            size.y = mAppDisplayHeight;
+    public void getInitialDisplaySize(int displayId, Point size) {
+        // TODO(cmautner): Access to DisplayContent should be locked on mWindowMap. Doing that
+        //  could lead to deadlock since this is called from ActivityManager.
+        final DisplayContent displayContent = getDisplayContentLocked(displayId);
+        if (displayContent != null) {
+            synchronized(displayContent.mDisplaySizeLock) {
+                size.x = displayContent.mInitialDisplayWidth;
+                size.y = displayContent.mInitialDisplayHeight;
+            }
         }
     }
 
-    public void getRealDisplaySize(Point size) {
-        synchronized(mDisplaySizeLock) {
-            size.x = mCurDisplayWidth;
-            size.y = mCurDisplayHeight;
-        }
-    }
-
-    public void getInitialDisplaySize(Point size) {
-        synchronized(mDisplaySizeLock) {
-            size.x = mInitialDisplayWidth;
-            size.y = mInitialDisplayHeight;
-        }
-    }
-
-    public int getMaximumSizeDimension() {
-        synchronized(mDisplaySizeLock) {
-            // Do this based on the raw screen size, until we are smarter.
-            return mBaseDisplayWidth > mBaseDisplayHeight
-                    ? mBaseDisplayWidth : mBaseDisplayHeight;
-        }
-    }
-
-    public void getCurrentSizeRange(Point smallestSize, Point largestSize) {
-        synchronized(mDisplaySizeLock) {
-            smallestSize.x = mSmallestDisplayWidth;
-            smallestSize.y = mSmallestDisplayHeight;
-            largestSize.x = mLargestDisplayWidth;
-            largestSize.y = mLargestDisplayHeight;
-        }
-    }
-
-    public void setForcedDisplaySize(int longDimen, int shortDimen) {
+    @Override
+    public void setForcedDisplaySize(int displayId, int width, int height) {
         synchronized(mWindowMap) {
-            int width, height;
-            if (mInitialDisplayWidth < mInitialDisplayHeight) {
-                width = shortDimen < mInitialDisplayWidth
-                        ? shortDimen : mInitialDisplayWidth;
-                height = longDimen < mInitialDisplayHeight
-                        ? longDimen : mInitialDisplayHeight;
-            } else {
-                width = longDimen < mInitialDisplayWidth
-                        ? longDimen : mInitialDisplayWidth;
-                height = shortDimen < mInitialDisplayHeight
-                        ? shortDimen : mInitialDisplayHeight;
+            // Set some sort of reasonable bounds on the size of the display that we
+            // will try to emulate.
+            final int MIN_WIDTH = 200;
+            final int MIN_HEIGHT = 200;
+            final int MAX_SCALE = 2;
+            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            if (displayContent != null) {
+                width = Math.min(Math.max(width, MIN_WIDTH),
+                        displayContent.mInitialDisplayWidth * MAX_SCALE);
+                height = Math.min(Math.max(height, MIN_HEIGHT),
+                        displayContent.mInitialDisplayHeight * MAX_SCALE);
+                setForcedDisplaySizeLocked(displayContent, width, height);
+                Settings.Global.putString(mContext.getContentResolver(),
+                        Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
             }
-            setForcedDisplaySizeLocked(width, height);
-            Settings.Secure.putString(mContext.getContentResolver(),
-                    Settings.Secure.DISPLAY_SIZE_FORCED, width + "," + height);
         }
     }
 
-    private void rebuildBlackFrame() {
-        if (mBlackFrame != null) {
-            mBlackFrame.kill();
-            mBlackFrame = null;
-        }
-        if (mBaseDisplayWidth < mInitialDisplayWidth
-                || mBaseDisplayHeight < mInitialDisplayHeight) {
-            int initW, initH, baseW, baseH;
-            final boolean rotated = (mRotation == Surface.ROTATION_90
-                    || mRotation == Surface.ROTATION_270);
-            if (rotated) {
-                initW = mInitialDisplayHeight;
-                initH = mInitialDisplayWidth;
-                baseW = mBaseDisplayHeight;
-                baseH = mBaseDisplayWidth;
-            } else {
-                initW = mInitialDisplayWidth;
-                initH = mInitialDisplayHeight;
-                baseW = mBaseDisplayWidth;
-                baseH = mBaseDisplayHeight;
+    private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) {
+        final String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
+                Settings.Global.DISPLAY_SIZE_FORCED);
+        if (sizeStr != null && sizeStr.length() > 0) {
+            final int pos = sizeStr.indexOf(',');
+            if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
+                int width, height;
+                try {
+                    width = Integer.parseInt(sizeStr.substring(0, pos));
+                    height = Integer.parseInt(sizeStr.substring(pos+1));
+                    synchronized(displayContent.mDisplaySizeLock) {
+                        if (displayContent.mBaseDisplayWidth != width
+                                || displayContent.mBaseDisplayHeight != height) {
+                            Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height);
+                            displayContent.mBaseDisplayWidth = width;
+                            displayContent.mBaseDisplayHeight = height;
+                        }
+                    }
+                } catch (NumberFormatException ex) {
+                }
             }
-            Rect outer = new Rect(0, 0, initW, initH);
-            Rect inner = new Rect(0, 0, baseW, baseH);
+        }
+        final String densityStr = Settings.Global.getString(mContext.getContentResolver(),
+                Settings.Global.DISPLAY_DENSITY_FORCED);
+        if (densityStr != null && densityStr.length() > 0) {
+            int density;
             try {
-                mBlackFrame = new BlackFrame(mFxSession, outer, inner, MASK_LAYER);
-            } catch (Surface.OutOfResourcesException e) {
+                density = Integer.parseInt(densityStr);
+                synchronized(displayContent.mDisplaySizeLock) {
+                    if (displayContent.mBaseDisplayDensity != density) {
+                        Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density);
+                        displayContent.mBaseDisplayDensity = density;
+                    }
+                }
+            } catch (NumberFormatException ex) {
             }
         }
     }
 
-    private void readForcedDisplaySizeLocked() {
-        final String str = Settings.Secure.getString(mContext.getContentResolver(),
-                Settings.Secure.DISPLAY_SIZE_FORCED);
-        if (str == null || str.length() == 0) {
-            return;
-        }
-        final int pos = str.indexOf(',');
-        if (pos <= 0 || str.lastIndexOf(',') != pos) {
-            return;
-        }
-        int width, height;
-        try {
-            width = Integer.parseInt(str.substring(0, pos));
-            height = Integer.parseInt(str.substring(pos+1));
-        } catch (NumberFormatException ex) {
-            return;
-        }
-        setForcedDisplaySizeLocked(width, height);
-    }
-
-    private void setForcedDisplaySizeLocked(int width, int height) {
+    // displayContent must not be null
+    private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
         Slog.i(TAG, "Using new display size: " + width + "x" + height);
 
-        synchronized(mDisplaySizeLock) {
-            mBaseDisplayWidth = width;
-            mBaseDisplayHeight = height;
+        synchronized(displayContent.mDisplaySizeLock) {
+            displayContent.mBaseDisplayWidth = width;
+            displayContent.mBaseDisplayHeight = height;
         }
-        mPolicy.setInitialDisplaySize(mDisplay, mBaseDisplayWidth, mBaseDisplayHeight);
+        reconfigureDisplayLocked(displayContent);
+    }
 
-        mLayoutNeeded = true;
+    @Override
+    public void clearForcedDisplaySize(int displayId) {
+        synchronized(mWindowMap) {
+            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            if (displayContent != null) {
+                setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
+                        displayContent.mInitialDisplayHeight);
+                Settings.Global.putString(mContext.getContentResolver(),
+                        Settings.Global.DISPLAY_SIZE_FORCED, "");
+            }
+        }
+    }
+
+    @Override
+    public void setForcedDisplayDensity(int displayId, int density) {
+        synchronized(mWindowMap) {
+            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            if (displayContent != null) {
+                setForcedDisplayDensityLocked(displayContent, density);
+                Settings.Global.putString(mContext.getContentResolver(),
+                        Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
+            }
+        }
+    }
+
+    // displayContent must not be null
+    private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
+        Slog.i(TAG, "Using new display density: " + density);
+
+        synchronized(displayContent.mDisplaySizeLock) {
+            displayContent.mBaseDisplayDensity = density;
+        }
+        reconfigureDisplayLocked(displayContent);
+    }
+
+    @Override
+    public void clearForcedDisplayDensity(int displayId) {
+        synchronized(mWindowMap) {
+            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            if (displayContent != null) {
+                setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity);
+                Settings.Global.putString(mContext.getContentResolver(),
+                        Settings.Global.DISPLAY_DENSITY_FORCED, "");
+            }
+        }
+    }
+
+    // displayContent must not be null
+    private void reconfigureDisplayLocked(DisplayContent displayContent) {
+        // TODO: Multidisplay: for now only use with default display.
+        mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
+                displayContent.mBaseDisplayWidth,
+                displayContent.mBaseDisplayHeight,
+                displayContent.mBaseDisplayDensity);
+
+        displayContent.layoutNeeded = true;
 
         boolean configChanged = updateOrientationFromAppTokensLocked(false);
         mTempConfiguration.setToDefaults();
@@ -7601,23 +8022,13 @@
 
         if (configChanged) {
             mWaitingForConfig = true;
-            startFreezingDisplayLocked(false);
+            startFreezingDisplayLocked(false, 0, 0);
             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
         }
 
-        rebuildBlackFrame();
-
         performLayoutAndPlaceSurfacesLocked();
     }
 
-    public void clearForcedDisplaySize() {
-        synchronized(mWindowMap) {
-            setForcedDisplaySizeLocked(mInitialDisplayWidth, mInitialDisplayHeight);
-            Settings.Secure.putString(mContext.getContentResolver(),
-                    Settings.Secure.DISPLAY_SIZE_FORCED, "");
-        }
-    }
-
     public boolean hasSystemNavBar() {
         return mPolicy.hasSystemNavBar();
     }
@@ -7660,9 +8071,17 @@
     }
 
     final void rebuildAppWindowListLocked() {
-        int NW = mWindows.size();
+        DisplayContentsIterator iterator = new DisplayContentsIterator();
+        while (iterator.hasNext()) {
+            rebuildAppWindowListLocked(iterator.next());
+        }
+    }
+
+    private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
+        final WindowList windows = displayContent.getWindowList();
+        int NW = windows.size();
         int i;
-        int lastWallpaper = -1;
+        int lastBelow = -1;
         int numRemoved = 0;
 
         if (mRebuildTmp.length < NW) {
@@ -7672,9 +8091,9 @@
         // First remove all existing app windows.
         i=0;
         while (i < NW) {
-            WindowState w = mWindows.get(i);
+            WindowState w = windows.get(i);
             if (w.mAppToken != null) {
-                WindowState win = mWindows.remove(i);
+                WindowState win = windows.remove(i);
                 win.mRebuilding = true;
                 mRebuildTmp[numRemoved] = win;
                 mWindowsChanged = true;
@@ -7683,17 +8102,18 @@
                 NW--;
                 numRemoved++;
                 continue;
-            } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER
-                    && lastWallpaper == i-1) {
-                lastWallpaper = i;
+            } else if (lastBelow == i-1) {
+                if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
+                    lastBelow = i;
+                }
             }
             i++;
         }
 
-        // The wallpaper window(s) typically live at the bottom of the stack,
-        // so skip them before adding app tokens.
-        lastWallpaper++;
-        i = lastWallpaper;
+        // Keep whatever windows were below the app windows still below,
+        // by skipping them.
+        lastBelow++;
+        i = lastBelow;
 
         // First add all of the exiting app tokens...  these are no longer
         // in the main app list, but still have windows shown.  We put them
@@ -7701,16 +8121,16 @@
         // will care about them.
         int NT = mExitingAppTokens.size();
         for (int j=0; j<NT; j++) {
-            i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j));
+            i = reAddAppWindowsLocked(displayContent, i, mExitingAppTokens.get(j));
         }
 
         // And add in the still active app tokens in Z order.
         NT = mAnimatingAppTokens.size();
         for (int j=0; j<NT; j++) {
-            i = reAddAppWindowsLocked(i, mAnimatingAppTokens.get(j));
+            i = reAddAppWindowsLocked(displayContent, i, mAnimatingAppTokens.get(j));
         }
 
-        i -= lastWallpaper;
+        i -= lastBelow;
         if (i != numRemoved) {
             Slog.w(TAG, "Rebuild removed " + numRemoved
                     + " windows but added " + i);
@@ -7723,7 +8143,7 @@
                     pw.flush();
                     Slog.w(TAG, "This window was lost: " + ws);
                     Slog.w(TAG, sw.toString());
-                    ws.mWinAnimator.destroySurfaceLocked();
+                    ws.mWinAnimator.destroySurfaceLocked(false);
                 }
             }
             Slog.w(TAG, "Current app token list:");
@@ -7733,8 +8153,8 @@
         }
     }
 
-    private final void assignLayersLocked() {
-        int N = mWindows.size();
+    private final void assignLayersLocked(WindowList windows) {
+        int N = windows.size();
         int curBaseLayer = 0;
         int curLayer = 0;
         int i;
@@ -7745,8 +8165,10 @@
             Slog.v(TAG, "Assigning layers", here);
         }
 
+        boolean anyLayerChanged = false;
+
         for (i=0; i<N; i++) {
-            final WindowState w = mWindows.get(i);
+            final WindowState w = windows.get(i);
             final WindowStateAnimator winAnimator = w.mWinAnimator;
             boolean layerChanged = false;
             int oldLayer = w.mLayer;
@@ -7760,6 +8182,7 @@
             }
             if (w.mLayer != oldLayer) {
                 layerChanged = true;
+                anyLayerChanged = true;
             }
             oldLayer = winAnimator.mAnimLayer;
             if (w.mTargetAppToken != null) {
@@ -7778,20 +8201,39 @@
             }
             if (winAnimator.mAnimLayer != oldLayer) {
                 layerChanged = true;
+                anyLayerChanged = true;
             }
-            if (layerChanged && mAnimator.isDimming(winAnimator)) {
+            if (layerChanged && mAnimator.isDimmingLocked(winAnimator)) {
                 // Force an animation pass just to update the mDimAnimator layer.
-                scheduleAnimationLocked();
+                updateLayoutToAnimationLocked();
             }
             if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
-                    + winAnimator.mAnimLayer);
+                    + "mBase=" + w.mBaseLayer
+                    + " mLayer=" + w.mLayer
+                    + (w.mAppToken == null ?
+                            "" : " mAppLayer=" + w.mAppToken.mAppAnimator.animLayerAdjustment)
+                    + " =mAnimLayer=" + winAnimator.mAnimLayer);
             //System.out.println(
             //    "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
         }
+
+        if (anyLayerChanged) {
+            scheduleNotifyWindowLayersChangedIfNeededLocked(getDefaultDisplayContentLocked());
+        }
+    }
+
+    private final void performLayoutAndPlaceSurfacesLocked() {
+        int loopCount = 6;
+        do {
+            mTraversalScheduled = false;
+            performLayoutAndPlaceSurfacesLockedLoop();
+            mH.removeMessages(H.DO_TRAVERSAL);
+            loopCount--;
+        } while (mTraversalScheduled && loopCount > 0);
     }
 
     private boolean mInLayout = false;
-    private final void performLayoutAndPlaceSurfacesLocked() {
+    private final void performLayoutAndPlaceSurfacesLockedLoop() {
         if (mInLayout) {
             if (DEBUG) {
                 throw new RuntimeException("Recursive call!");
@@ -7808,7 +8250,7 @@
             return;
         }
         
-        if (mDisplay == null) {
+        if (!mDisplayReady) {
             // Not yet initialized, nothing to do.
             return;
         }
@@ -7839,35 +8281,13 @@
         } catch (RuntimeException e) {
             Log.wtf(TAG, "Unhandled exception while force removing for memory", e);
         }
-        
+
         try {
             performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
 
-            final int N = mPendingRemove.size();
-            if (N > 0) {
-                if (mPendingRemoveTmp.length < N) {
-                    mPendingRemoveTmp = new WindowState[N+10];
-                }
-                mPendingRemove.toArray(mPendingRemoveTmp);
-                mPendingRemove.clear();
-                for (int i=0; i<N; i++) {
-                    WindowState w = mPendingRemoveTmp[i];
-                    removeWindowInnerLocked(w.mSession, w);
-                }
+            mInLayout = false;
 
-                mInLayout = false;
-                assignLayersLocked();
-                mLayoutNeeded = true;
-                // XXX this recursion seems broken!
-                Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
-                performLayoutAndPlaceSurfacesLocked();
-                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
-
-            } else {
-                mInLayout = false;
-            }
-
-            if (mLayoutNeeded) {
+            if (needsLayout()) {
                 if (++mLayoutRepeatCount < 6) {
                     requestTraversalLocked();
                 } else {
@@ -7890,52 +8310,65 @@
         Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
     }
 
-    private final void performLayoutLockedInner(boolean initial, boolean updateInputWindows) {
-        if (!mLayoutNeeded) {
+    private final void performLayoutLockedInner(final DisplayContent displayContent,
+                                    boolean initial, boolean updateInputWindows) {
+        if (!displayContent.layoutNeeded) {
             return;
         }
-        
-        mLayoutNeeded = false;
-        
-        final int dw = mCurDisplayWidth;
-        final int dh = mCurDisplayHeight;
+        displayContent.layoutNeeded = false;
+        WindowList windows = displayContent.getWindowList();
+        boolean isDefaultDisplay = displayContent.isDefaultDisplay;
+
+        DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final int dw = displayInfo.logicalWidth;
+        final int dh = displayInfo.logicalHeight;
 
         final int NFW = mFakeWindows.size();
         for (int i=0; i<NFW; i++) {
             mFakeWindows.get(i).layout(dw, dh);
         }
 
-        final int N = mWindows.size();
+        final int N = windows.size();
         int i;
 
         if (DEBUG_LAYOUT) {
             Slog.v(TAG, "-------------------------------------");
             Slog.v(TAG, "performLayout: needed="
-                    + mLayoutNeeded + " dw=" + dw + " dh=" + dh);
+                    + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
         }
-        
-        mPolicy.beginLayoutLw(dw, dh, mRotation);
-        mSystemDecorLayer = mPolicy.getSystemDecorRectLw(mSystemDecorRect);
+
+        WindowStateAnimator universeBackground = null;
+
+        mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
+        if (isDefaultDisplay) {
+            // Not needed on non-default displays.
+            mSystemDecorLayer = mPolicy.getSystemDecorRectLw(mSystemDecorRect);
+            mScreenRect.set(0, 0, dw, dh);
+        }
 
         int seq = mLayoutSeq+1;
         if (seq < 0) seq = 0;
         mLayoutSeq = seq;
-        
+
+        boolean behindDream = false;
+
         // First perform layout of any root windows (not attached
         // to another window).
         int topAttached = -1;
         for (i = N-1; i >= 0; i--) {
-            final WindowState win = mWindows.get(i);
+            final WindowState win = windows.get(i);
 
             // Don't do layout of a window if it is not visible, or
             // soon won't be visible, to avoid wasting time and funky
             // changes while a window is animating away.
-            final boolean gone = win.isGoneForLayoutLw();
+            final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs))
+                    || win.isGoneForLayoutLw();
 
             if (DEBUG_LAYOUT && !win.mLayoutAttached) {
                 Slog.v(TAG, "1ST PASS " + win
                         + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
-                        + " mLayoutAttached=" + win.mLayoutAttached);
+                        + " mLayoutAttached=" + win.mLayoutAttached
+                        + " screen changed=" + win.isConfigChanged());
                 final AppWindowToken atoken = win.mAppToken;
                 if (gone) Slog.v(TAG, "  GONE: mViewVisibility="
                         + win.mViewVisibility + " mRelayoutCalled="
@@ -7950,18 +8383,27 @@
                         + (atoken != null && atoken.hiddenRequested)
                         + " mAttachedHidden=" + win.mAttachedHidden);
             }
-            
+
             // If this view is GONE, then skip it -- keep the current
             // frame, and let the caller know so they can ignore it
             // if they want.  (We do the normal layout for INVISIBLE
             // windows, since that means "perform layout as normal,
             // just don't display").
-            if (!gone || !win.mHaveFrame || win.mLayoutNeeded) {
+            if (!gone || !win.mHaveFrame || win.mLayoutNeeded
+                    || ((win.mAttrs.type == TYPE_KEYGUARD || win.mAttrs.type == TYPE_WALLPAPER) &&
+                        win.isConfigChanged())
+                    || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
                 if (!win.mLayoutAttached) {
                     if (initial) {
                         //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
                         win.mContentChanged = false;
                     }
+                    if (win.mAttrs.type == TYPE_DREAM) {
+                        // Don't layout windows behind a dream, so that if it
+                        // does stuff like hide the status bar we won't get a
+                        // bad transition when it goes away.
+                        behindDream = true;
+                    }
                     win.mLayoutNeeded = false;
                     win.prelayout();
                     mPolicy.layoutWindowLw(win, win.mAttrs, null);
@@ -7974,14 +8416,26 @@
                     if (topAttached < 0) topAttached = i;
                 }
             }
+            if (win.mViewVisibility == View.VISIBLE
+                    && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
+                    && universeBackground == null) {
+                universeBackground = win.mWinAnimator;
+            }
         }
 
+        if (mAnimator.mUniverseBackground  != universeBackground) {
+            mFocusMayChange = true;
+            mAnimator.mUniverseBackground = universeBackground;
+        }
+
+        boolean attachedBehindDream = false;
+
         // Now perform layout of attached windows, which usually
         // depend on the position of the window they are attached to.
         // XXX does not deal with windows that are attached to windows
         // that are themselves attached.
         for (i = topAttached; i >= 0; i--) {
-            final WindowState win = mWindows.get(i);
+            final WindowState win = windows.get(i);
 
             if (win.mLayoutAttached) {
                 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win
@@ -7993,6 +8447,9 @@
                 // if they want.  (We do the normal layout for INVISIBLE
                 // windows, since that means "perform layout as normal,
                 // just don't display").
+                if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) {
+                    continue;
+                }
                 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
                         || !win.mHaveFrame || win.mLayoutNeeded) {
                     if (initial) {
@@ -8008,6 +8465,11 @@
                             + win.mContainingFrame + " mDisplayFrame="
                             + win.mDisplayFrame);
                 }
+            } else if (win.mAttrs.type == TYPE_DREAM) {
+                // Don't layout windows behind a dream, so that if it
+                // does stuff like hide the status bar we won't get a
+                // bad transition when it goes away.
+                attachedBehindDream = behindDream;
             }
         }
         
@@ -8035,17 +8497,17 @@
                 // when we first froze the display.
                 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
                 mH.sendMessageDelayed(mH.obtainMessage(
-                        H.WINDOW_FREEZE_TIMEOUT), 2000);
+                        H.WINDOW_FREEZE_TIMEOUT), WINDOW_FREEZE_TIMEOUT_DURATION);
             }
         }
     }
 
     /**
      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
-     *
+     * @param windows List of windows on default display.
      * @return bitmap indicating if another pass through layout must be made.
      */
-    public int handleAppTransitionReadyLocked() {
+    public int handleAppTransitionReadyLocked(WindowList windows) {
         int changes = 0;
         int i;
         int NN = mOpeningApps.size();
@@ -8178,7 +8640,7 @@
                 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE;
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                         "New transit away from wallpaper: " + transit);
-            } else if (mWallpaperTarget != null) {
+            } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
                 // We are transitioning from an activity without
                 // a wallpaper to now showing the wallpaper
                 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN;
@@ -8200,15 +8662,23 @@
             NN = mOpeningApps.size();
             for (i=0; i<NN; i++) {
                 AppWindowToken wtoken = mOpeningApps.get(i);
+                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
-                wtoken.mAppAnimator.clearThumbnail();
+                appAnimator.clearThumbnail();
                 wtoken.reportedVisible = false;
                 wtoken.inPendingTransaction = false;
-                wtoken.mAppAnimator.animation = null;
+                appAnimator.animation = null;
                 setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
                 wtoken.updateReportedVisibilityLocked();
                 wtoken.waitingToShow = false;
-                mAnimator.mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked();
+
+                appAnimator.mAllAppWinAnimators.clear();
+                final int N = wtoken.allAppWindows.size();
+                for (int j = 0; j < N; j++) {
+                    appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
+                }
+                mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
+
                 if (animLp != null) {
                     int layer = -1;
                     for (int j=0; j<wtoken.windows.size(); j++) {
@@ -8227,7 +8697,7 @@
             for (i=0; i<NN; i++) {
                 AppWindowToken wtoken = mClosingApps.get(i);
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
-                        "Now closing app" + wtoken);
+                        "Now closing app " + wtoken);
                 wtoken.mAppAnimator.clearThumbnail();
                 wtoken.inPendingTransaction = false;
                 wtoken.mAppAnimator.animation = null;
@@ -8248,9 +8718,14 @@
                 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(),
+                    // TODO(multi-display): support other displays
+                    final DisplayContent displayContent = getDefaultDisplayContentLocked();
+                    final Display display = displayContent.getDisplay();
+                    Surface surface = new Surface(mFxSession,
+                            "thumbnail anim",
+                            dirty.width(), dirty.height(),
                             PixelFormat.TRANSLUCENT, Surface.HIDDEN);
+                    surface.setLayerStack(display.getLayerStack());
                     topOpeningApp.mAppAnimator.thumbnail = surface;
                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  THUMBNAIL "
                             + surface + ": CREATE");
@@ -8262,7 +8737,7 @@
                     drawSurface.release();
                     topOpeningApp.mAppAnimator.thumbnailLayer = topOpeningLayer;
                     Animation anim = createThumbnailAnimationLocked(
-                            transit, true, true, mNextAppTransitionDelayed);
+                            transit, true, true, mNextAppTransitionScaleUp);
                     topOpeningApp.mAppAnimator.thumbnailAnimation = anim;
                     anim.restrictDuration(MAX_ANIMATION_DURATION);
                     anim.scaleCurrentDuration(mTransitionAnimationScale);
@@ -8286,14 +8761,16 @@
 
             // This has changed the visibility of windows, so perform
             // a new layout to get them all up-to-date.
-            changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT
+            changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
                     | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
-            mLayoutNeeded = true;
-            if (!moveInputMethodWindowsIfNeededLocked(true)) {
-                assignLayersLocked();
+            getDefaultDisplayContentLocked().layoutNeeded = true;
+
+            // TODO(multidisplay): IMEs are only supported on the default display.
+            if (windows == getDefaultWindowListLocked()
+                    && !moveInputMethodWindowsIfNeededLocked(true)) {
+                assignLayersLocked(windows);
             }
-            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
-                    false /*updateInputWindows*/);
+            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/);
             mFocusMayChange = false;
         }
 
@@ -8302,7 +8779,6 @@
 
     /**
      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
-     *
      * @return bitmap indicating if another pass through layout must be made.
      */
     private int handleAnimatingStoppedAndTransitionLocked() {
@@ -8339,10 +8815,10 @@
         WindowState oldWallpaper = mWallpaperTarget;
         if (mLowerWallpaperTarget != null
                 && mLowerWallpaperTarget.mAppToken != null) {
-            if (DEBUG_WALLPAPER) Slog.v(TAG,
+            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
                     "wallpaperForceHiding changed with lower="
                     + mLowerWallpaperTarget);
-            if (DEBUG_WALLPAPER) Slog.v(TAG,
+            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
                     "hidden=" + mLowerWallpaperTarget.mAppToken.hidden +
                     " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested);
             if (mLowerWallpaperTarget.mAppToken.hidden) {
@@ -8354,7 +8830,7 @@
             }
         }
         mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked();
-        if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper
+        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "****** OLD: " + oldWallpaper
                 + " NEW: " + mWallpaperTarget
                 + " LOWER: " + mLowerWallpaperTarget);
         return changes;
@@ -8362,15 +8838,12 @@
 
     private void updateResizingWindows(final WindowState w) {
         final WindowStateAnimator winAnimator = w.mWinAnimator;
-        if (w.mHasSurface && !w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
+        if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
             w.mContentInsetsChanged |=
                     !w.mLastContentInsets.equals(w.mContentInsets);
             w.mVisibleInsetsChanged |=
                     !w.mLastVisibleInsets.equals(w.mVisibleInsets);
-            boolean configChanged =
-                w.mConfiguration != mCurConfiguration
-                && (w.mConfiguration == null
-                        || mCurConfiguration.diff(w.mConfiguration) != 0);
+            boolean configChanged = w.isConfigChanged();
             if (DEBUG_CONFIGURATION && configChanged) {
                 Slog.v(TAG, "Win " + w + " config changed: "
                         + mCurConfiguration);
@@ -8451,12 +8924,28 @@
                     && mInnerFields.mButtonBrightness < 0) {
                 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness;
             }
+            if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0
+                    && mInnerFields.mUserActivityTimeout < 0) {
+                mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout;
+            }
+
+            final int type = attrs.type;
             if (canBeSeen
-                    && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
-                     || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD
-                     || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) {
+                    && (type == TYPE_SYSTEM_DIALOG
+                     || type == TYPE_RECENTS_OVERLAY
+                     || type == TYPE_KEYGUARD
+                     || type == TYPE_SYSTEM_ERROR)) {
                 mInnerFields.mSyswin = true;
             }
+
+            if (canBeSeen) {
+                if (type == TYPE_DREAM || type == TYPE_KEYGUARD) {
+                    mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_MIRROR;
+                } else if (mInnerFields.mDisplayHasContent
+                        == LayoutFields.DISPLAY_CONTENT_UNKNOWN) {
+                    mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNIQUE;
+                }
+            }
         }
 
         boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
@@ -8473,17 +8962,18 @@
                 //Slog.i(TAG, "DIM BEHIND: " + w);
                 mInnerFields.mDimming = true;
                 final WindowStateAnimator winAnimator = w.mWinAnimator;
-                if (!mAnimator.isDimming(winAnimator)) {
+                if (!mAnimator.isDimmingLocked(winAnimator)) {
                     final int width, height;
-                    if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) {
-                        width = mCurDisplayWidth;
-                        height = mCurDisplayHeight;
+                    if (attrs.type == TYPE_BOOT_PROGRESS) {
+                        final DisplayInfo displayInfo = w.mDisplayContent.getDisplayInfo();
+                        width = displayInfo.logicalWidth;
+                        height = displayInfo.logicalHeight;
                     } else {
                         width = innerDw;
                         height = innerDh;
                     }
-                    mAnimator.startDimming(winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount,
-                            width, height);
+                    startDimmingLocked(
+                        winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, width, height);
                 }
             }
         }
@@ -8510,22 +9000,13 @@
     }
 
     // "Something has changed!  Let's make it correct now."
-    private final void performLayoutAndPlaceSurfacesLockedInner(
-            boolean recoveringMemory) {
+    private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
         if (DEBUG_WINDOW_TRACE) {
             Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
                     + Debug.getCallers(3));
         }
-        if (mDisplay == null) {
-            Slog.i(TAG, "skipping performLayoutAndPlaceSurfacesLockedInner with no mDisplay");
-            return;
-        }
 
         final long currentTime = SystemClock.uptimeMillis();
-        final int dw = mCurDisplayWidth;
-        final int dh = mCurDisplayHeight;
-        final int innerDw = mAppDisplayWidth;
-        final int innerDh = mAppDisplayHeight;
 
         int i;
 
@@ -8548,195 +9029,272 @@
         mInnerFields.mHoldScreen = null;
         mInnerFields.mScreenBrightness = -1;
         mInnerFields.mButtonBrightness = -1;
+        mInnerFields.mUserActivityTimeout = -1;
+        mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN;
+
         mTransactionSequence++;
 
+        final DisplayContent defaultDisplay = getDefaultDisplayContentLocked();
+        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
+        final int defaultDw = defaultInfo.logicalWidth;
+        final int defaultDh = defaultInfo.logicalHeight;
+
         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
-
         Surface.openTransaction();
-
-        if (mWatermark != null) {
-            mWatermark.positionSurface(dw, dh);
-        }
-        if (mStrictModeFlash != null) {
-            mStrictModeFlash.positionSurface(dw, dh);
-        }
-
         try {
-            int repeats = 0;
 
-            do {
-                repeats++;
-                if (repeats > 6) {
-                    Slog.w(TAG, "Animation repeat aborted after too many iterations");
-                    mLayoutNeeded = false;
-                    break;
-                }
-
-                if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
-                    mPendingLayoutChanges);
-
-                if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
-                    if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
-                        assignLayersLocked();
-                        mLayoutNeeded = true;
-                    }
-                }
-
-                if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
-                    if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
-                    if (updateOrientationFromAppTokensLocked(true)) {
-                        mLayoutNeeded = true;
-                        mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
-                    }
-                }
-
-                if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
-                    mLayoutNeeded = true;
-                }
-
-                // FIRST LOOP: Perform a layout, if needed.
-                if (repeats < 4) {
-                    performLayoutLockedInner(repeats == 1, false /*updateInputWindows*/);
-                } else {
-                    Slog.w(TAG, "Layout repeat skipped after too many iterations");
-                }
-
-                // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
-                // it is animating.
-                mPendingLayoutChanges = 0;
-                if (DEBUG_LAYOUT_REPEATS)  debugLayoutRepeats("loop number " + mLayoutRepeatCount,
-                    mPendingLayoutChanges);
-                mPolicy.beginAnimationLw(dw, dh);
-                for (i = mWindows.size() - 1; i >= 0; i--) {
-                    WindowState w = mWindows.get(i);
-                    if (w.mHasSurface) {
-                        mPolicy.animatingWindowLw(w, w.mAttrs);
-                    }
-                }
-                mPendingLayoutChanges |= mPolicy.finishAnimationLw();
-                if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishAnimationLw",
-                    mPendingLayoutChanges);
-            } while (mPendingLayoutChanges != 0);
-
-            final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
-
-            mInnerFields.mObscured = false;
-            mInnerFields.mDimming = false;
-            mInnerFields.mSyswin = false;
+            if (mWatermark != null) {
+                mWatermark.positionSurface(defaultDw, defaultDh);
+            }
+            if (mStrictModeFlash != null) {
+                mStrictModeFlash.positionSurface(defaultDw, defaultDh);
+            }
 
             boolean focusDisplayed = false;
             boolean updateAllDrawn = false;
-            final int N = mWindows.size();
-            for (i=N-1; i>=0; i--) {
-                WindowState w = mWindows.get(i);
 
-                final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
+            DisplayContentsIterator iterator = new DisplayContentsIterator();
+            while (iterator.hasNext()) {
+                final DisplayContent displayContent = iterator.next();
+                WindowList windows = displayContent.getWindowList();
+                DisplayInfo displayInfo = displayContent.getDisplayInfo();
+                final int displayId = displayContent.getDisplayId();
+                final int dw = displayInfo.logicalWidth;
+                final int dh = displayInfo.logicalHeight;
+                final int innerDw = displayInfo.appWidth;
+                final int innerDh = displayInfo.appHeight;
+                final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
 
-                // Update effect.
-                w.mObscured = mInnerFields.mObscured;
-                if (!mInnerFields.mObscured) {
-                    handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
+                // Reset for each display unless we are forcing mirroring.
+                if (mInnerFields.mDisplayHasContent != LayoutFields.DISPLAY_CONTENT_MIRROR) {
+                    mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN;
                 }
 
-                if (obscuredChanged && (mWallpaperTarget == w) && w.isVisibleLw()) {
-                    // This is the wallpaper target and its obscured state
-                    // changed... make sure the current wallaper's visibility
-                    // has been updated accordingly.
-                    updateWallpaperVisibilityLocked();
-                }
+                int repeats = 0;
+                do {
+                    repeats++;
+                    if (repeats > 6) {
+                        Slog.w(TAG, "Animation repeat aborted after too many iterations");
+                        displayContent.layoutNeeded = false;
+                        break;
+                    }
 
-                final WindowStateAnimator winAnimator = w.mWinAnimator;
+                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
+                        displayContent.pendingLayoutChanges);
 
-                // If the window has moved due to its containing
-                // content frame changing, then we'd like to animate
-                // it.
-                if (w.mHasSurface && 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);
-                    winAnimator.setAnimation(a);
-                    winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
-                    winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
-                }
+                    if (isDefaultDisplay && ((displayContent.pendingLayoutChanges
+                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0)
+                            && ((adjustWallpaperWindowsLocked()
+                                    & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0)) {
+                        assignLayersLocked(windows);
+                        displayContent.layoutNeeded = true;
+                    }
 
-                //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
-                w.mContentChanged = false;
+                    if (isDefaultDisplay && (displayContent.pendingLayoutChanges
+                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
+                        if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
+                        if (updateOrientationFromAppTokensLocked(true)) {
+                            displayContent.layoutNeeded = true;
+                            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
+                        }
+                    }
 
-                // Moved from updateWindowsAndWallpaperLocked().
-                if (w.mHasSurface) {
-                    // Take care of the window being ready to display.
-                    if (winAnimator.commitFinishDrawingLocked(currentTime)) {
-                        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);
-                            mInnerFields.mWallpaperMayChange = true;
-                            mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-                            if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                                debugLayoutRepeats("updateWindowsAndWallpaperLocked 1",
-                                    mPendingLayoutChanges);
+                    if ((displayContent.pendingLayoutChanges
+                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
+                        displayContent.layoutNeeded = true;
+                    }
+
+                    // FIRST LOOP: Perform a layout, if needed.
+                    if (repeats < 4) {
+                        performLayoutLockedInner(displayContent, repeats == 1,
+                                false /*updateInputWindows*/);
+                    } else {
+                        Slog.w(TAG, "Layout repeat skipped after too many iterations");
+                    }
+
+                    // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
+                    // it is animating.
+                    displayContent.pendingLayoutChanges = 0;
+
+                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number "
+                            + mLayoutRepeatCount, displayContent.pendingLayoutChanges);
+
+                    if (isDefaultDisplay) {
+                        mPolicy.beginPostLayoutPolicyLw(dw, dh);
+                        for (i = windows.size() - 1; i >= 0; i--) {
+                            WindowState w = windows.get(i);
+                            if (w.mHasSurface) {
+                                mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs);
                             }
                         }
+                        displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw();
+                        if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
+                            "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges);
+                    }
+                } while (displayContent.pendingLayoutChanges != 0);
+
+                mInnerFields.mObscured = false;
+                mInnerFields.mDimming = false;
+                mInnerFields.mSyswin = false;
+
+                // Only used if default window
+                final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
+
+                final int N = windows.size();
+                for (i=N-1; i>=0; i--) {
+                    WindowState w = windows.get(i);
+
+                    final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
+
+                    // Update effect.
+                    w.mObscured = mInnerFields.mObscured;
+                    if (!mInnerFields.mObscured) {
+                        handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
                     }
 
-                    winAnimator.setSurfaceBoundaries(recoveringMemory);
-
-                    final AppWindowToken atoken = w.mAppToken;
-                    if (DEBUG_STARTING_WINDOW && atoken != null && w == atoken.startingWindow) {
-                        Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
-                            + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
-                            + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
+                    if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
+                            && w.isVisibleLw()) {
+                        // This is the wallpaper target and its obscured state
+                        // changed... make sure the current wallaper's visibility
+                        // has been updated accordingly.
+                        updateWallpaperVisibilityLocked();
                     }
-                    if (atoken != null && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
-                        if (atoken.lastTransactionSequence != mTransactionSequence) {
-                            atoken.lastTransactionSequence = mTransactionSequence;
-                            atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
-                            atoken.startingDisplayed = false;
+
+                    final WindowStateAnimator winAnimator = w.mWinAnimator;
+
+                    // If the window has moved due to its containing
+                    // content frame changing, then we'd like to animate
+                    // it.
+                    if (w.mHasSurface && 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);
+                        winAnimator.setAnimation(a);
+                        winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
+                        winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
+                        try {
+                            w.mClient.moved(w.mFrame.left, w.mFrame.top);
+                        } catch (RemoteException e) {
                         }
-                        if ((w.isOnScreen() || winAnimator.mAttrType
-                                == 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=" + winAnimator.isAnimating());
-                                if (!w.isDrawnLw()) {
-                                    Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurface
-                                            + " pv=" + w.mPolicyVisibility
-                                            + " mDrawState=" + winAnimator.mDrawState
-                                            + " ah=" + w.mAttachedHidden
-                                            + " th=" + atoken.hiddenRequested
-                                            + " a=" + winAnimator.mAnimating);
+                    }
+
+                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
+                    w.mContentChanged = false;
+
+                    // Moved from updateWindowsAndWallpaperLocked().
+                    if (w.mHasSurface) {
+                        // Take care of the window being ready to display.
+                        final boolean committed =
+                                winAnimator.commitFinishDrawingLocked(currentTime);
+                        if (isDefaultDisplay && committed) {
+                            if (w.mAttrs.type == TYPE_DREAM) {
+                                // HACK: When a dream is shown, it may at that
+                                // point hide the lock screen.  So we need to
+                                // redo the layout to let the phone window manager
+                                // make this happen.
+                                displayContent.pendingLayoutChanges |=
+                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
+                                if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+                                    debugLayoutRepeats(
+                                        "dream and commitFinishDrawingLocked true",
+                                        displayContent.pendingLayoutChanges);
                                 }
                             }
-                            if (w != atoken.startingWindow) {
-                                if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
-                                    atoken.numInterestingWindows++;
-                                    if (w.isDrawnLw()) {
-                                        atoken.numDrawnWindows++;
-                                        if (WindowManagerService.DEBUG_VISIBILITY ||
-                                                WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
-                                                "tokenMayBeDrawn: " + atoken
-                                                + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
-                                                + " mAppFreezing=" + w.mAppFreezing);
-                                        updateAllDrawn = true;
+                            if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
+                                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+                                        "First draw done in potential wallpaper target " + w);
+                                mInnerFields.mWallpaperMayChange = true;
+                                displayContent.pendingLayoutChanges |=
+                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+                                if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+                                    debugLayoutRepeats(
+                                        "wallpaper and commitFinishDrawingLocked true",
+                                        displayContent.pendingLayoutChanges);
+                                }
+                            }
+                        }
+
+                        winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
+
+                        final AppWindowToken atoken = w.mAppToken;
+                        if (DEBUG_STARTING_WINDOW && atoken != null
+                                && w == atoken.startingWindow) {
+                            Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
+                                + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
+                                + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
+                        }
+                        if (atoken != null
+                                && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
+                            if (atoken.lastTransactionSequence != mTransactionSequence) {
+                                atoken.lastTransactionSequence = mTransactionSequence;
+                                atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
+                                atoken.startingDisplayed = false;
+                            }
+                            if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
+                                    && !w.mExiting && !w.mDestroying) {
+                                if (WindowManagerService.DEBUG_VISIBILITY ||
+                                        WindowManagerService.DEBUG_ORIENTATION) {
+                                    Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
+                                            + ", isAnimating=" + winAnimator.isAnimating());
+                                    if (!w.isDrawnLw()) {
+                                        Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurface
+                                                + " pv=" + w.mPolicyVisibility
+                                                + " mDrawState=" + winAnimator.mDrawState
+                                                + " ah=" + w.mAttachedHidden
+                                                + " th=" + atoken.hiddenRequested
+                                                + " a=" + winAnimator.mAnimating);
                                     }
                                 }
-                            } else if (w.isDrawnLw()) {
-                                atoken.startingDisplayed = true;
+                                if (w != atoken.startingWindow) {
+                                    if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
+                                        atoken.numInterestingWindows++;
+                                        if (w.isDrawnLw()) {
+                                            atoken.numDrawnWindows++;
+                                            if (WindowManagerService.DEBUG_VISIBILITY ||
+                                                    WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
+                                                    "tokenMayBeDrawn: " + atoken
+                                                    + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
+                                                    + " mAppFreezing=" + w.mAppFreezing);
+                                            updateAllDrawn = true;
+                                        }
+                                    }
+                                } else if (w.isDrawnLw()) {
+                                    atoken.startingDisplayed = true;
+                                }
                             }
                         }
                     }
+
+                    if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus)
+                            && w.isDisplayedLw()) {
+                        focusDisplayed = true;
+                    }
+
+                    updateResizingWindows(w);
                 }
 
-                if (someoneLosingFocus && w == mCurrentFocus && w.isDisplayedLw()) {
-                    focusDisplayed = true;
+                final boolean hasUniqueContent;
+                switch (mInnerFields.mDisplayHasContent) {
+                    case LayoutFields.DISPLAY_CONTENT_MIRROR:
+                        hasUniqueContent = isDefaultDisplay;
+                        break;
+                    case LayoutFields.DISPLAY_CONTENT_UNIQUE:
+                        hasUniqueContent = true;
+                        break;
+                    case LayoutFields.DISPLAY_CONTENT_UNKNOWN:
+                    default:
+                        hasUniqueContent = false;
+                        break;
                 }
+                mDisplayManagerService.setDisplayHasContent(displayId, hasUniqueContent,
+                        true /* inTraversal, must call performTraversalInTrans... below */);
 
-                updateResizingWindows(w);
+                if (!mInnerFields.mDimming && mAnimator.isDimmingLocked(displayId)) {
+                    stopDimmingLocked(displayId);
+                }
             }
 
             if (updateAllDrawn) {
@@ -8747,22 +9305,27 @@
                 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
             }
 
-            if (!mInnerFields.mDimming && mAnimator.isDimming()) {
-                mAnimator.stopDimming();
-            }
+            // Give the display manager a chance to adjust properties
+            // like display rotation if it needs to.
+            mDisplayManagerService.performTraversalInTransactionFromWindowManager();
+
         } catch (RuntimeException e) {
             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
         } finally {
             Surface.closeTransaction();
+            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
         }
 
+        final WindowList defaultWindows = defaultDisplay.getWindowList();
+
         // 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();
+            defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
             if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
-                mPendingLayoutChanges);
+                defaultDisplay.pendingLayoutChanges);
         }
 
         mInnerFields.mAdjResult = 0;
@@ -8774,92 +9337,90 @@
             // 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();
+            defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
             if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock",
-                mPendingLayoutChanges);
+                defaultDisplay.pendingLayoutChanges);
         }
 
-        if (mInnerFields.mWallpaperForceHidingChanged && mPendingLayoutChanges == 0 &&
-                !mAppTransitionReady) {
+        if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 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();
+            defaultDisplay.pendingLayoutChanges |= animateAwayWallpaperLocked();
             if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked",
-                mPendingLayoutChanges);
+                defaultDisplay.pendingLayoutChanges);
         }
         mInnerFields.mWallpaperForceHidingChanged = false;
 
         if (mInnerFields.mWallpaperMayChange) {
-            if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
+            if (WindowManagerService.DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
                     "Wallpaper may change!  Adjusting");
             mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked();
         }
 
         if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
-            if (DEBUG_WALLPAPER) Slog.v(TAG,
+            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
                     "Wallpaper layer changed: assigning layers + relayout");
-            mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
-            assignLayersLocked();
+            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
+            assignLayersLocked(defaultWindows);
         } else if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) {
-            if (DEBUG_WALLPAPER) Slog.v(TAG,
+            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
                     "Wallpaper visibility changed: relayout");
-            mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
+            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
         }
 
         if (mFocusMayChange) {
             mFocusMayChange = false;
             if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
                     false /*updateInputWindows*/)) {
-                mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
+                defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
                 mInnerFields.mAdjResult = 0;
             }
         }
 
-        if (mLayoutNeeded) {
-            mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
-            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", mPendingLayoutChanges);
+        if (needsLayout()) {
+            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
+            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
+                    defaultDisplay.pendingLayoutChanges);
         }
 
-        if (!mResizingWindows.isEmpty()) {
-            for (i = mResizingWindows.size() - 1; i >= 0; i--) {
-                WindowState win = mResizingWindows.get(i);
-                final WindowStateAnimator winAnimator = win.mWinAnimator;
-                try {
-                    if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
-                            "Reporting new frame to " + win + ": " + win.mCompatFrame);
-                    int diff = 0;
-                    boolean configChanged =
-                        win.mConfiguration != mCurConfiguration
-                        && (win.mConfiguration == null
-                                || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0);
-                    if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
-                            && configChanged) {
-                        Slog.i(TAG, "Sending new config to window " + win + ": "
-                                + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH
-                                + " / " + mCurConfiguration + " / 0x"
-                                + Integer.toHexString(diff));
-                    }
-                    win.mConfiguration = mCurConfiguration;
-                    if (DEBUG_ORIENTATION &&
-                            winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i(
-                            TAG, "Resizing " + win + " WITH DRAW PENDING");
-                    win.mClient.resized((int)winAnimator.mSurfaceW,
-                            (int)winAnimator.mSurfaceH,
-                            win.mLastContentInsets, win.mLastVisibleInsets,
-                            winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING,
-                            configChanged ? win.mConfiguration : null);
-                    win.mContentInsetsChanged = false;
-                    win.mVisibleInsetsChanged = false;
-                    winAnimator.mSurfaceResized = false;
-                } catch (RemoteException e) {
-                    win.mOrientationChanging = false;
-                }
+        for (i = mResizingWindows.size() - 1; i >= 0; i--) {
+            WindowState win = mResizingWindows.get(i);
+            if (win.mAppFreezing) {
+                // Don't remove this window until rotation has completed.
+                continue;
             }
-            mResizingWindows.clear();
+            final WindowStateAnimator winAnimator = win.mWinAnimator;
+            try {
+                if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
+                        "Reporting new frame to " + win + ": " + win.mCompatFrame);
+                int diff = 0;
+                boolean configChanged = win.isConfigChanged();
+                if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
+                        && configChanged) {
+                    Slog.i(TAG, "Sending new config to window " + win + ": "
+                            + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH
+                            + " / " + mCurConfiguration + " / 0x"
+                            + Integer.toHexString(diff));
+                }
+                win.mConfiguration = mCurConfiguration;
+                if (DEBUG_ORIENTATION &&
+                        winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i(
+                        TAG, "Resizing " + win + " WITH DRAW PENDING");
+                win.mClient.resized(win.mFrame, win.mLastContentInsets, win.mLastVisibleInsets,
+                        winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING,
+                        configChanged ? win.mConfiguration : null);
+                win.mContentInsetsChanged = false;
+                win.mVisibleInsetsChanged = false;
+                winAnimator.mSurfaceResized = false;
+            } catch (RemoteException e) {
+                win.mOrientationChanging = false;
+            }
+            mResizingWindows.remove(i);
         }
 
         if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
@@ -8887,7 +9448,7 @@
                 if (win == mWallpaperTarget) {
                     wallpaperDestroyed = true;
                 }
-                win.mWinAnimator.destroySurfaceLocked();
+                win.mWinAnimator.destroySurfaceLocked(false);
             } while (i > 0);
             mDestroySurface.clear();
         }
@@ -8899,6 +9460,7 @@
                 mExitingTokens.remove(i);
                 if (token.windowType == TYPE_WALLPAPER) {
                     mWallpaperTokens.remove(token);
+                    updateLayoutToAnimWallpaperTokens();
                 }
             }
         }
@@ -8930,41 +9492,42 @@
             mRelayoutWhileAnimating.clear();
         }
 
-        if (wallpaperDestroyed) {
-            mLayoutNeeded |= adjustWallpaperWindowsLocked() != 0;
+        if (wallpaperDestroyed && (adjustWallpaperWindowsLocked() != 0)) {
+            getDefaultDisplayContentLocked().layoutNeeded = true;
         }
-        if (mPendingLayoutChanges != 0) {
-            mLayoutNeeded = true;
+
+        DisplayContentsIterator iterator = new DisplayContentsIterator();
+        while (iterator.hasNext()) {
+            DisplayContent displayContent = iterator.next();
+            if (displayContent.pendingLayoutChanges != 0) {
+                displayContent.layoutNeeded = true;
+            }
         }
 
         // Finally update all input windows now that the window changes have stabilized.
         mInputMonitor.updateInputWindowsLw(true /*force*/);
 
-        setHoldScreenLocked(mInnerFields.mHoldScreen != null);
+        setHoldScreenLocked(mInnerFields.mHoldScreen);
         if (!mDisplayFrozen) {
             if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
-                mPowerManager.setScreenBrightnessOverride(-1);
+                mPowerManager.setScreenBrightnessOverrideFromWindowManager(-1);
             } else {
-                mPowerManager.setScreenBrightnessOverride((int)
-                        (mInnerFields.mScreenBrightness * PowerManager.BRIGHTNESS_ON));
+                mPowerManager.setScreenBrightnessOverrideFromWindowManager(
+                        toBrightnessOverride(mInnerFields.mScreenBrightness));
             }
             if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
-                mPowerManager.setButtonBrightnessOverride(-1);
+                mPowerManager.setButtonBrightnessOverrideFromWindowManager(-1);
             } else {
-                mPowerManager.setButtonBrightnessOverride((int)
-                        (mInnerFields.mButtonBrightness * PowerManager.BRIGHTNESS_ON));
+                mPowerManager.setButtonBrightnessOverrideFromWindowManager(
+                        toBrightnessOverride(mInnerFields.mButtonBrightness));
             }
-        }
-        if (mInnerFields.mHoldScreen != mHoldingScreenOn) {
-            mHoldingScreenOn = mInnerFields.mHoldScreen;
-            Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, mInnerFields.mHoldScreen);
-            mH.sendMessage(m);
+            mPowerManager.setUserActivityTimeoutOverrideFromWindowManager(
+                    mInnerFields.mUserActivityTimeout);
         }
 
         if (mTurnOnScreen) {
             if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
-            mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
-                    LocalPowerManager.BUTTON_EVENT, true);
+            mPowerManager.wakeUp(SystemClock.uptimeMillis());
             mTurnOnScreen = false;
         }
 
@@ -8977,24 +9540,49 @@
             }
         }
 
-        if (mInnerFields.mOrientationChangeComplete && !mLayoutNeeded &&
-                !mInnerFields.mUpdateRotation) {
+        if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded
+                && !mInnerFields.mUpdateRotation) {
             checkDrawnWindowsLocked();
         }
 
+        final int N = mPendingRemove.size();
+        if (N > 0) {
+            if (mPendingRemoveTmp.length < N) {
+                mPendingRemoveTmp = new WindowState[N+10];
+            }
+            mPendingRemove.toArray(mPendingRemoveTmp);
+            mPendingRemove.clear();
+            DisplayContentList displayList = new DisplayContentList();
+            for (i = 0; i < N; i++) {
+                WindowState w = mPendingRemoveTmp[i];
+                removeWindowInnerLocked(w.mSession, w);
+                if (!displayList.contains(w.mDisplayContent)) {
+                    displayList.add(w.mDisplayContent);
+                }
+            }
+
+            for (DisplayContent displayContent : displayList) {
+                assignLayersLocked(displayContent.getWindowList());
+                displayContent.layoutNeeded = true;
+            }
+        }
+
         // Check to see if we are now in a state where the screen should
         // be enabled, because the window obscured flags have changed.
         enableScreenIfNeededLocked();
 
-        scheduleAnimationLocked();
+        updateLayoutToAnimationLocked();
 
         if (DEBUG_WINDOW_TRACE) {
-            Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: mPendingLayoutChanges="
-                + Integer.toHexString(mPendingLayoutChanges) + " mLayoutNeeded=" + mLayoutNeeded
-                + " animating=" + mAnimator.mAnimating);
+            Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating="
+                    + mAnimator.mAnimating);
         }
     }
 
+    private int toBrightnessOverride(float value) {
+        return (int)(value * PowerManager.BRIGHTNESS_ON);
+    }
+
     void checkDrawnWindowsLocked() {
         if (mWaitingForDrawn.size() > 0) {
             for (int j=mWaitingForDrawn.size()-1; j>=0; j--) {
@@ -9026,33 +9614,48 @@
         }
     }
 
-    public void waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
-        synchronized (mWindowMap) {
-            WindowState win = windowForClientLocked(null, token, true);
-            if (win != null) {
-                Pair<WindowState, IRemoteCallback> pair =
-                        new Pair<WindowState, IRemoteCallback>(win, callback);
-                Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
-                mH.sendMessageDelayed(m, 2000);
-                mWaitingForDrawn.add(pair);
-                checkDrawnWindowsLocked();
+    public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
+        if (token != null && callback != null) {
+            synchronized (mWindowMap) {
+                WindowState win = windowForClientLocked(null, token, true);
+                if (win != null) {
+                    Pair<WindowState, IRemoteCallback> pair =
+                            new Pair<WindowState, IRemoteCallback>(win, callback);
+                    Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
+                    mH.sendMessageDelayed(m, 2000);
+                    mWaitingForDrawn.add(pair);
+                    checkDrawnWindowsLocked();
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    void setHoldScreenLocked(final Session newHoldScreen) {
+        final boolean hold = newHoldScreen != null;
+
+        if (hold && mHoldingScreenOn != newHoldScreen) {
+            mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
+        }
+        mHoldingScreenOn = newHoldScreen;
+
+        final boolean state = mHoldingScreenWakeLock.isHeld();
+        if (hold != state) {
+            if (hold) {
+                mHoldingScreenWakeLock.acquire();
+                mPolicy.keepScreenOnStartedLw();
+            } else {
+                mPolicy.keepScreenOnStoppedLw();
+                mHoldingScreenWakeLock.release();
             }
         }
     }
 
-    /**
-     * Must be called with the main window manager lock held.
-     */
-    void setHoldScreenLocked(boolean holding) {
-        boolean state = mHoldingScreenWakeLock.isHeld();
-        if (holding != state) {
-            if (holding) {
-                mPolicy.screenOnStartedLw();
-                mHoldingScreenWakeLock.acquire();
-            } else {
-                mPolicy.screenOnStoppedLw();
-                mHoldingScreenWakeLock.release();
-            }
+    @Override
+    public void requestTraversal() {
+        synchronized (mWindowMap) {
+            requestTraversalLocked();
         }
     }
 
@@ -9063,13 +9666,146 @@
         }
     }
 
+    /** Note that Locked in this case is on mLayoutToAnim */
     void scheduleAnimationLocked() {
-        if (!mAnimationScheduled) {
-            mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationRunnable, null);
-            mAnimationScheduled = true;
+        final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim;
+        if (!layoutToAnim.mAnimationScheduled) {
+            layoutToAnim.mAnimationScheduled = true;
+            mChoreographer.postCallback(
+                    Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);
         }
     }
 
+    void updateLayoutToAnimationLocked() {
+        final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim;
+        synchronized (layoutToAnim) {
+            // Copy local params to transfer params.
+            SparseArray<WinAnimatorList> allWinAnimatorLists = layoutToAnim.mWinAnimatorLists;
+            allWinAnimatorLists.clear();
+            DisplayContentsIterator iterator = new DisplayContentsIterator();
+            while (iterator.hasNext()) {
+                final DisplayContent displayContent = iterator.next();
+                WinAnimatorList winAnimatorList = new WinAnimatorList();
+                final WindowList windows = displayContent.getWindowList();
+                int N = windows.size();
+                for (int i = 0; i < N; i++) {
+                    final WindowStateAnimator winAnimator = windows.get(i).mWinAnimator;
+                    if (winAnimator.mSurface != null) {
+                        winAnimatorList.add(winAnimator);
+                    }
+                }
+                allWinAnimatorLists.put(displayContent.getDisplayId(), winAnimatorList);
+            }
+
+            if (WindowManagerService.DEBUG_WALLPAPER_LIGHT) {
+                if (mWallpaperTarget != layoutToAnim.mWallpaperTarget
+                        || mLowerWallpaperTarget != layoutToAnim.mLowerWallpaperTarget
+                        || mUpperWallpaperTarget != layoutToAnim.mUpperWallpaperTarget) {
+                    Slog.d(TAG, "Pushing anim wallpaper: target=" + mWallpaperTarget
+                            + " lower=" + mLowerWallpaperTarget + " upper="
+                            + mUpperWallpaperTarget + "\n" + Debug.getCallers(5, "  "));
+                }
+            }
+            layoutToAnim.mWallpaperTarget = mWallpaperTarget;
+            layoutToAnim.mLowerWallpaperTarget = mLowerWallpaperTarget;
+            layoutToAnim.mUpperWallpaperTarget = mUpperWallpaperTarget;
+
+            final ArrayList<AppWindowAnimParams> paramList = layoutToAnim.mAppWindowAnimParams;
+            paramList.clear();
+            int N = mAnimatingAppTokens.size();
+            for (int i = 0; i < N; i++) {
+                paramList.add(new AppWindowAnimParams(mAnimatingAppTokens.get(i).mAppAnimator));
+            }
+
+            layoutToAnim.mParamsModified = true;
+            scheduleAnimationLocked();
+        }
+    }
+
+    void updateLayoutToAnimWallpaperTokens() {
+        synchronized(mLayoutToAnim) {
+            mLayoutToAnim.mWallpaperTokens = new ArrayList<WindowToken>(mWallpaperTokens);
+            mLayoutToAnim.mChanges |= LayoutToAnimatorParams.WALLPAPER_TOKENS_CHANGED;
+        }
+    }
+
+    void setAnimDimParams(int displayId, DimAnimator.Parameters params) {
+        synchronized (mLayoutToAnim) {
+            mLayoutToAnim.mDimParams.put(displayId, params);
+            scheduleAnimationLocked();
+        }
+    }
+
+    void startDimmingLocked(final WindowStateAnimator winAnimator, final float target,
+                      final int width, final int height) {
+        setAnimDimParams(winAnimator.mWin.getDisplayId(),
+                new DimAnimator.Parameters(winAnimator, width, height, target));
+    }
+
+    void stopDimmingLocked(int displayId) {
+        setAnimDimParams(displayId, null);
+    }
+
+    private boolean needsLayout() {
+        DisplayContentsIterator iterator = new DisplayContentsIterator();
+        while (iterator.hasNext()) {
+            if (iterator.next().layoutNeeded) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean copyAnimToLayoutParamsLocked() {
+        boolean doRequest = false;
+        final WindowAnimator.AnimatorToLayoutParams animToLayout = mAnimator.mAnimToLayout;
+        synchronized (animToLayout) {
+            animToLayout.mUpdateQueued = false;
+            final int bulkUpdateParams = animToLayout.mBulkUpdateParams;
+            // TODO(cmautner): As the number of bits grows, use masks of bit groups to
+            //  eliminate unnecessary tests.
+            if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
+                mInnerFields.mUpdateRotation = true;
+                doRequest = true;
+            }
+            if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
+                mInnerFields.mWallpaperMayChange = true;
+                doRequest = true;
+            }
+            if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
+                mInnerFields.mWallpaperForceHidingChanged = true;
+                doRequest = true;
+            }
+            if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
+                mInnerFields.mOrientationChangeComplete = false;
+            } else {
+                mInnerFields.mOrientationChangeComplete = true;
+                if (mWindowsFreezingScreen) {
+                    doRequest = true;
+                }
+            }
+            if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
+                mTurnOnScreen = true;
+            }
+
+            SparseIntArray pendingLayouts = animToLayout.mPendingLayoutChanges;
+            final int count = pendingLayouts.size();
+            if (count > 0) {
+                doRequest = true;
+            }
+            for (int i = 0; i < count; ++i) {
+                final DisplayContent displayContent =
+                        getDisplayContentLocked(pendingLayouts.keyAt(i));
+                if (displayContent != null) {
+                    displayContent.pendingLayoutChanges |= pendingLayouts.valueAt(i);
+                }
+            }
+
+            mWindowDetachedWallpaper = animToLayout.mWindowDetachedWallpaper;
+        }
+        return doRequest;
+    }
+
     boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
                                            boolean secure) {
         final Surface surface = winAnimator.mSurface;
@@ -9088,10 +9824,11 @@
             // There was some problem...   first, do a sanity check of the
             // window list to make sure we haven't left any dangling surfaces
             // around.
-            int N = mWindows.size();
+
+            AllWindowsIterator iterator = new AllWindowsIterator();
             Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
-            for (int i=0; i<N; i++) {
-                WindowState ws = mWindows.get(i);
+            while (iterator.hasNext()) {
+                WindowState ws = iterator.next();
                 WindowStateAnimator wsa = ws.mWinAnimator;
                 if (wsa.mSurface != null) {
                     if (!mSessions.contains(wsa.mSession)) {
@@ -9106,8 +9843,6 @@
                         wsa.mSurface = null;
                         ws.mHasSurface = false;
                         mForceRemoves.add(ws);
-                        i--;
-                        N--;
                         leakedSurface = true;
                     } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
                         Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
@@ -9126,8 +9861,13 @@
             if (!leakedSurface) {
                 Slog.w(TAG, "No leaked surfaces; killing applicatons!");
                 SparseIntArray pidCandidates = new SparseIntArray();
-                for (int i=0; i<N; i++) {
-                    WindowStateAnimator wsa = mWindows.get(i).mWinAnimator;
+                iterator = new AllWindowsIterator();
+                while (iterator.hasNext()) {
+                    WindowState ws = iterator.next();
+                    if (mForceRemoves.contains(ws)) {
+                        continue;
+                    }
+                    WindowStateAnimator wsa = ws.mWinAnimator;
                     if (wsa.mSurface != null) {
                         pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
                     }
@@ -9187,28 +9927,31 @@
             mLosingFocus.remove(newFocus);
             int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
 
+            // TODO(multidisplay): Focused windows on default display only.
+            final DisplayContent displayContent = getDefaultDisplayContentLocked();
+
             final WindowState imWindow = mInputMethodWindow;
             if (newFocus != imWindow && oldFocus != imWindow) {
                 if (moveInputMethodWindowsIfNeededLocked(
                         mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS &&
                         mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
-                    mLayoutNeeded = true;
+                    displayContent.layoutNeeded = true;
                 }
                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
-                    performLayoutLockedInner(true /*initial*/, updateInputWindows);
+                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
                     focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
                 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
                     // Client will do the layout, but we need to assign layers
                     // for handleNewWindowLocked() below.
-                    assignLayersLocked();
+                    assignLayersLocked(displayContent.getWindowList());
                 }
             }
 
-            if ((focusChanged&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
+            if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
                 // The change in focus caused us to need to do a layout.  Okay.
-                mLayoutNeeded = true;
+                displayContent.layoutNeeded = true;
                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
-                    performLayoutLockedInner(true /*initial*/, updateInputWindows);
+                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
                 }
             }
 
@@ -9229,15 +9972,29 @@
     }
 
     private WindowState computeFocusedWindowLocked() {
-        WindowState result = null;
-        WindowState win;
+        if (mAnimator.mUniverseBackground != null
+                && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
+            return mAnimator.mUniverseBackground.mWin;
+        }
 
+        final int displayCount = mDisplayContents.size();
+        for (int i = 0; i < displayCount; i++) {
+            final DisplayContent displayContent = mDisplayContents.valueAt(i);
+            WindowState win = findFocusedWindowLocked(displayContent);
+            if (win != null) {
+                return win;
+            }
+        }
+        return null;
+    }
+
+    private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
         int nextAppIndex = mAppTokens.size()-1;
-        WindowToken nextApp = nextAppIndex >= 0
-            ? mAppTokens.get(nextAppIndex) : null;
+        WindowToken nextApp = nextAppIndex >= 0 ? mAppTokens.get(nextAppIndex) : null;
 
-        for (int i = mWindows.size() - 1; i >= 0; i--) {
-            win = mWindows.get(i);
+        final WindowList windows = displayContent.getWindowList();
+        for (int i = windows.size() - 1; i >= 0; i--) {
+            final WindowState win = windows.get(i);
 
             if (localLOGV || DEBUG_FOCUS) Slog.v(
                 TAG, "Looking for focus: " + i
@@ -9287,20 +10044,19 @@
             if (win.canReceiveKeys()) {
                 if (DEBUG_FOCUS) Slog.v(
                         TAG, "Found focus @ " + i + " = " + win);
-                result = win;
-                break;
+                return win;
             }
         }
-
-        return result;
+        return null;
     }
 
-    private void startFreezingDisplayLocked(boolean inTransaction) {
+    private void startFreezingDisplayLocked(boolean inTransaction,
+            int exitAnim, int enterAnim) {
         if (mDisplayFrozen) {
             return;
         }
 
-        if (mDisplay == null || !mPolicy.isScreenOnFully()) {
+        if (!mDisplayReady || !mPolicy.isScreenOnFully()) {
             // No need to freeze the screen before the system is ready or if
             // the screen is off.
             return;
@@ -9312,6 +10068,11 @@
 
         mInputMonitor.freezeInputDispatchingLw();
 
+        // Clear the last input window -- that is just used for
+        // clean transitions between IMEs, and if we are freezing
+        // the screen then the whole world is changing behind the scenes.
+        mPolicy.setLastInputMethodWindowLw(null, null);
+
         if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
             mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
             mNextAppTransitionType = ActivityOptions.ANIM_NONE;
@@ -9326,20 +10087,22 @@
         }
 
         if (CUSTOM_SCREEN_ROTATION) {
-            if (mAnimator.mScreenRotationAnimation != null) {
-                mAnimator.mScreenRotationAnimation.kill();
-                mAnimator.mScreenRotationAnimation = null;
+            final DisplayContent displayContent = getDefaultDisplayContentLocked();
+            final int displayId = displayContent.getDisplayId();
+            ScreenRotationAnimation screenRotationAnimation =
+                    mAnimator.getScreenRotationAnimationLocked(displayId);
+            if (screenRotationAnimation != null) {
+                screenRotationAnimation.kill();
             }
 
-            mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
-                    mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight,
-                    mDisplay.getRotation());
-
-            if (!mAnimator.mScreenRotationAnimation.hasScreenshot()) {
-                Surface.freezeDisplay(0);
-            }
-        } else {
-            Surface.freezeDisplay(0);
+            // TODO(multidisplay): rotation on main screen only.
+            final Display display = displayContent.getDisplay();
+            final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+            screenRotationAnimation = new ScreenRotationAnimation(mContext,
+                    display, mFxSession, inTransaction, displayInfo.logicalWidth,
+                    displayInfo.logicalHeight, display.getRotation(),
+                    exitAnim, enterAnim);
+            mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
         }
     }
 
@@ -9348,41 +10111,52 @@
             return;
         }
 
-        if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) {
+        if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen
+                || mClientFreezingScreen) {
             if (DEBUG_ORIENTATION) Slog.d(TAG,
                 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
                 + ", mAppsFreezingScreen=" + mAppsFreezingScreen
-                + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen);
+                + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
+                + ", mClientFreezingScreen=" + mClientFreezingScreen);
             return;
         }
         
         mDisplayFrozen = false;
         mH.removeMessages(H.APP_FREEZE_TIMEOUT);
+        mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
         if (PROFILE_ORIENTATION) {
             Debug.stopMethodTracing();
         }
 
         boolean updateRotation = false;
-        
-        if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null
-                && mAnimator.mScreenRotationAnimation.hasScreenshot()) {
+
+        final DisplayContent displayContent = getDefaultDisplayContentLocked();
+        final int displayId = displayContent.getDisplayId();
+        ScreenRotationAnimation screenRotationAnimation =
+                mAnimator.getScreenRotationAnimationLocked(displayId);
+        if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
+                && screenRotationAnimation.hasScreenshot()) {
             if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
-            if (mAnimator.mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
-                    mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) {
-                scheduleAnimationLocked();
+            // TODO(multidisplay): rotation on main screen only.
+            DisplayInfo displayInfo = displayContent.getDisplayInfo();
+            if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
+                    mTransitionAnimationScale, displayInfo.logicalWidth,
+                        displayInfo.logicalHeight)) {
+                updateLayoutToAnimationLocked();
             } else {
-                mAnimator.mScreenRotationAnimation.kill();
-                mAnimator.mScreenRotationAnimation = null;
+                screenRotationAnimation.kill();
+                screenRotationAnimation = null;
+                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
                 updateRotation = true;
             }
         } else {
-            if (mAnimator.mScreenRotationAnimation != null) {
-                mAnimator.mScreenRotationAnimation.kill();
-                mAnimator.mScreenRotationAnimation = null;
+            if (screenRotationAnimation != null) {
+                screenRotationAnimation.kill();
+                screenRotationAnimation = null;
+                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
             }
             updateRotation = true;
         }
-        Surface.unfreezeDisplay(0);
 
         mInputMonitor.thawInputDispatchingLw();
 
@@ -9434,7 +10208,7 @@
         return val;
     }
 
-    void createWatermark() {
+    void createWatermarkInTransaction() {
         if (mWatermark != null) {
             return;
         }
@@ -9448,7 +10222,8 @@
             if (line != null) {
                 String[] toks = line.split("%");
                 if (toks != null && toks.length > 0) {
-                    mWatermark = new Watermark(mRealDisplayMetrics, mFxSession, toks);
+                    mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
+                            mRealDisplayMetrics, mFxSession, toks);
                 }
             }
         } catch (FileNotFoundException e) {
@@ -9478,11 +10253,13 @@
         }
     }
 
+    // TOOD(multidisplay): StatusBar on multiple screens?
     void updateStatusBarVisibilityLocked(int visibility) {
         mInputManager.setSystemUiVisibility(visibility);
-        final int N = mWindows.size();
+        final WindowList windows = getDefaultWindowListLocked();
+        final int N = windows.size();
         for (int i = 0; i < N; i++) {
-            WindowState ws = mWindows.get(i);
+            WindowState ws = windows.get(i);
             try {
                 int curValue = ws.mSystemUiVisibility;
                 int diff = curValue ^ visibility;
@@ -9549,6 +10326,8 @@
     // It is assumed that this method is called only by InputMethodManagerService.
     public void saveLastInputMethodWindowForTransition() {
         synchronized (mWindowMap) {
+            // TODO(multidisplay): Pass in the displayID.
+            DisplayContent displayContent = getDefaultDisplayContentLocked();
             if (mInputMethodWindow != null) {
                 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
             }
@@ -9560,8 +10339,21 @@
         return mPolicy.hasNavigationBar();
     }
 
-    public void lockNow() {
-        mPolicy.lockNow();
+    public void lockNow(Bundle options) {
+        mPolicy.lockNow(options);
+    }
+    
+    public boolean isSafeModeEnabled() {
+        return mSafeMode;
+    }
+
+    public void showAssistant() {
+        // TODO: What permission?
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
+                != PackageManager.PERMISSION_GRANTED) {
+            return;
+        }
+        mPolicy.showAssistant();
     }
 
     void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
@@ -9569,6 +10361,11 @@
         mPolicy.dump("    ", pw, args);
     }
 
+    void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
+        pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
+        mAnimator.dumpLocked(pw, "    ", dumpAll);
+    }
+
     void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
         pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
         if (mTokenMap.size() > 0) {
@@ -9576,7 +10373,7 @@
             Iterator<WindowToken> it = mTokenMap.values().iterator();
             while (it.hasNext()) {
                 WindowToken token = it.next();
-                pw.print("  Token "); pw.print(token.token);
+                pw.print("  "); pw.print(token);
                 if (dumpAll) {
                     pw.println(':');
                     token.dump(pw, "    ");
@@ -9604,8 +10401,9 @@
             pw.println();
             pw.println("  Application tokens in Z order:");
             for (int i=mAppTokens.size()-1; i>=0; i--) {
-                pw.print("  App #"); pw.print(i); pw.println(": ");
-                        mAppTokens.get(i).dump(pw, "    ");
+                pw.print("  App #"); pw.print(i);
+                        pw.print(' '); pw.print(mAppTokens.get(i)); pw.println(":");
+                mAppTokens.get(i).dump(pw, "    ");
             }
         }
         if (mFinishedStarting.size() > 0) {
@@ -9699,10 +10497,12 @@
 
     void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
             ArrayList<WindowState> windows) {
-        for (int i=mWindows.size()-1; i>=0; i--) {
-            WindowState w = mWindows.get(i);
+        int j = 0;
+        final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+        while (iterator.hasNext()) {
+            final WindowState w = iterator.next();
             if (windows == null || windows.contains(w)) {
-                pw.print("  Window #"); pw.print(i); pw.print(' ');
+                pw.print("  Window #"); pw.print(j++); pw.print(' ');
                         pw.print(w); pw.println(":");
                 w.dump(pw, "    ", dumpAll || windows != null);
             }
@@ -9810,27 +10610,12 @@
             }
         }
         pw.println();
-        if (mDisplay != null) {
-            pw.print("  Display: init="); pw.print(mInitialDisplayWidth); pw.print("x");
-                    pw.print(mInitialDisplayHeight);
-                    if (mInitialDisplayWidth != mBaseDisplayWidth
-                            || mInitialDisplayHeight != mBaseDisplayHeight) {
-                        pw.print(" base=");
-                        pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
-                    }
-                    final int rawWidth = mDisplay.getRawWidth();
-                    final int rawHeight = mDisplay.getRawHeight();
-                    if (rawWidth != mCurDisplayWidth || rawHeight != mCurDisplayHeight) {
-                        pw.print(" raw="); pw.print(rawWidth); pw.print("x"); pw.print(rawHeight);
-                    }
-                    pw.print(" cur=");
-                    pw.print(mCurDisplayWidth); pw.print("x"); pw.print(mCurDisplayHeight);
-                    pw.print(" app=");
-                    pw.print(mAppDisplayWidth); pw.print("x"); pw.print(mAppDisplayHeight);
-                    pw.print(" rng="); pw.print(mSmallestDisplayWidth);
-                    pw.print("x"); pw.print(mSmallestDisplayHeight);
-                    pw.print("-"); pw.print(mLargestDisplayWidth);
-                    pw.print("x"); pw.println(mLargestDisplayHeight);
+        pw.println("  DisplayContents:");
+        if (mDisplayReady) {
+            DisplayContentsIterator dCIterator = new DisplayContentsIterator();
+            while (dCIterator.hasNext()) {
+                dCIterator.next().dump("    ", pw);
+            }
         } else {
             pw.println("  NO DISPLAY");
         }
@@ -9847,7 +10632,8 @@
                 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
         if (dumpAll) {
             pw.print("  mSystemDecorRect="); pw.print(mSystemDecorRect.toShortString());
-                    pw.print(" mSystemDecorLayer="); pw.println(mSystemDecorLayer);
+                    pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer);
+                    pw.print(" mScreenRecr="); pw.println(mScreenRect.toShortString());
             if (mLastStatusBarVisibility != 0) {
                 pw.print("  mLastStatusBarVisibility=0x");
                         pw.println(Integer.toHexString(mLastStatusBarVisibility));
@@ -9856,7 +10642,7 @@
                 pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
             }
             pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
-            if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) {
+            if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
                 pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
                 pw.print("  mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
             }
@@ -9871,21 +10657,28 @@
             }
             pw.print("  mSystemBooted="); pw.print(mSystemBooted);
                     pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
-            pw.print("  mLayoutNeeded="); pw.print(mLayoutNeeded);
-                    pw.print("mTransactionSequence="); pw.println(mTransactionSequence);
+            if (needsLayout()) {
+                pw.print("  layoutNeeded on displays=");
+                DisplayContentsIterator dcIterator = new DisplayContentsIterator();
+                while (dcIterator.hasNext()) {
+                    final DisplayContent displayContent = dcIterator.next();
+                    if (displayContent.layoutNeeded) {
+                        pw.print(displayContent.getDisplayId());
+                    }
+                }
+                pw.println();
+            }
+            pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
             pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
-                    pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
-                    pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen);
-                    pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig);
+                    pw.print(" windows="); pw.print(mWindowsFreezingScreen);
+                    pw.print(" client="); pw.print(mClientFreezingScreen);
+                    pw.print(" apps="); pw.print(mAppsFreezingScreen);
+                    pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
             pw.print("  mRotation="); pw.print(mRotation);
                     pw.print(" mAltOrientation="); pw.println(mAltOrientation);
             pw.print("  mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
                     pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
             pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
-            if (mAnimator.mScreenRotationAnimation != null) {
-                pw.println("  mScreenRotationAnimation:");
-                mAnimator.mScreenRotationAnimation.printTo("    ", pw);
-            }
             pw.print("  mWindowAnimationScale="); pw.print(mWindowAnimationScale);
                     pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale);
                     pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale);
@@ -9916,15 +10709,15 @@
                             pw.print(" mNextAppTransitionStartHeight=");
                             pw.println(mNextAppTransitionStartHeight);
                     break;
-                case ActivityOptions.ANIM_THUMBNAIL:
-                case ActivityOptions.ANIM_THUMBNAIL_DELAYED:
+                case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP:
+                case ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN:
                     pw.print("  mNextAppTransitionThumbnail=");
                             pw.print(mNextAppTransitionThumbnail);
                             pw.print(" mNextAppTransitionStartX=");
                             pw.print(mNextAppTransitionStartX);
                             pw.print(" mNextAppTransitionStartY=");
                             pw.println(mNextAppTransitionStartY);
-                    pw.print("  mNextAppTransitionDelayed="); pw.println(mNextAppTransitionDelayed);
+                    pw.print("  mNextAppTransitionScaleUp="); pw.println(mNextAppTransitionScaleUp);
                     break;
             }
             if (mNextAppTransitionCallback != null) {
@@ -9933,18 +10726,43 @@
             }
             pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
                     pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
-            pw.println("  Window Animator:");
-            mAnimator.dump(pw, "    ", dumpAll);
+            pw.println("  mLayoutToAnim:");
+            pw.print("    mParamsModified="); pw.print(mLayoutToAnim.mParamsModified);
+                    pw.print(" mAnimationScheduled="); pw.print(mLayoutToAnim.mAnimationScheduled);
+                    pw.print(" mChanges=0x");
+                    pw.println(Long.toHexString(mLayoutToAnim.mChanges));
+            pw.print("    mWallpaperTarget="); pw.println(mLayoutToAnim.mWallpaperTarget);
+            if (mLayoutToAnim.mLowerWallpaperTarget != null
+                    || mLayoutToAnim.mUpperWallpaperTarget != null) {
+                pw.print("    mLowerWallpaperTarget=");
+                        pw.println(mLayoutToAnim.mLowerWallpaperTarget);
+                pw.print("    mUpperWallpaperTarget=");
+                        pw.println(mLayoutToAnim.mUpperWallpaperTarget);
+            }
+            for (int i=0; i<mLayoutToAnim.mWinAnimatorLists.size(); i++) {
+                pw.print("    Win Animator List #");
+                        pw.print(mLayoutToAnim.mWinAnimatorLists.keyAt(i)); pw.println(":");
+                WinAnimatorList wanim = mLayoutToAnim.mWinAnimatorLists.valueAt(i);
+                for (int wi=0; wi<wanim.size(); wi++) {
+                    pw.print("      "); pw.println(wanim.get(wi));
+                }
+            }
+            for (int i=0; i<mLayoutToAnim.mWallpaperTokens.size(); i++) {
+                pw.print("    Wallpaper Token #"); pw.print(i); pw.print(": ");
+                        pw.println(mLayoutToAnim.mWallpaperTokens.get(i));
+            }
+            // XXX also need to print mDimParams and mAppWindowAnimParams.  I am lazy.
         }
     }
 
     boolean dumpWindows(PrintWriter pw, String name, String[] args,
             int opti, boolean dumpAll) {
-        ArrayList<WindowState> windows = new ArrayList<WindowState>();
+        WindowList windows = new WindowList();
         if ("visible".equals(name)) {
             synchronized(mWindowMap) {
-                for (int i=mWindows.size()-1; i>=0; i--) {
-                    WindowState w = mWindows.get(i);
+                final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+                while (iterator.hasNext()) {
+                    final WindowState w = iterator.next();
                     if (w.mWinAnimator.mSurfaceShown) {
                         windows.add(w);
                     }
@@ -9959,8 +10777,9 @@
             } catch (RuntimeException e) {
             }
             synchronized(mWindowMap) {
-                for (int i=mWindows.size()-1; i>=0; i--) {
-                    WindowState w = mWindows.get(i);
+                final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+                while (iterator.hasNext()) {
+                    final WindowState w = iterator.next();
                     if (name != null) {
                         if (w.mAttrs.getTitle().toString().contains(name)) {
                             windows.add(w);
@@ -10042,6 +10861,7 @@
                 pw.println("  cmd may be one of:");
                 pw.println("    l[astanr]: last ANR information");
                 pw.println("    p[policy]: policy state");
+                pw.println("    a[animator]: animator state");
                 pw.println("    s[essions]: active sessions");
                 pw.println("    t[okens]: token list");
                 pw.println("    w[indows]: window list");
@@ -10071,6 +10891,11 @@
                     dumpPolicyLocked(pw, args, true);
                 }
                 return;
+            } else if ("animator".equals(cmd) || "a".equals(cmd)) {
+                synchronized(mWindowMap) {
+                    dumpAnimatorLocked(pw, args, true);
+                }
+                return;
             } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
                 synchronized(mWindowMap) {
                     dumpSessionsLocked(pw, true);
@@ -10116,6 +10941,11 @@
             if (dumpAll) {
                 pw.println("-------------------------------------------------------------------------------");
             }
+            dumpAnimatorLocked(pw, args, dumpAll);
+            pw.println();
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
             dumpSessionsLocked(pw, dumpAll);
             pw.println();
             if (dumpAll) {
@@ -10133,7 +10963,6 @@
     // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
     public void monitor() {
         synchronized (mWindowMap) { }
-        synchronized (mKeyguardTokenWatcher) { }
     }
 
     public interface OnHardKeyboardStatusChangeListener {
@@ -10147,8 +10976,176 @@
         }
     }
 
-    void bulkSetParameters(final int bulkUpdateParams, int pendingLayoutChanges) {
-        mH.sendMessage(mH.obtainMessage(H.BULK_UPDATE_PARAMETERS, bulkUpdateParams,
-                pendingLayoutChanges));
+    public void createDisplayContentLocked(final Display display) {
+        if (display == null) {
+            throw new IllegalArgumentException("getDisplayContent: display must not be null");
+        }
+        final DisplayContent displayContent = new DisplayContent(display);
+        mDisplayContents.put(display.getDisplayId(), displayContent);
+    }
+
+    /**
+     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
+     * there is a Display for the displayId.
+     * @param displayId The display the caller is interested in.
+     * @return The DisplayContent associated with displayId or null if there is no Display for it.
+     */
+    public DisplayContent getDisplayContentLocked(final int displayId) {
+        DisplayContent displayContent = mDisplayContents.get(displayId);
+        if (displayContent == null) {
+            final Display display = mDisplayManager.getDisplay(displayId);
+            if (display != null) {
+                displayContent = new DisplayContent(display);
+                mDisplayContents.put(displayId, displayContent);
+            }
+        }
+        return displayContent;
+    }
+
+    class DisplayContentsIterator implements Iterator<DisplayContent> {
+        private int cur;
+
+        @Override
+        public boolean hasNext() {
+            return cur < mDisplayContents.size();
+        }
+
+        @Override
+        public DisplayContent next() {
+            if (hasNext()) {
+                return mDisplayContents.valueAt(cur++);
+            }
+            throw new NoSuchElementException();
+        }
+
+        @Override
+        public void remove() {
+            throw new IllegalArgumentException("AllDisplayContentIterator.remove not implemented");
+        }
+    }
+
+    final static boolean REVERSE_ITERATOR = true;
+    class AllWindowsIterator implements Iterator<WindowState> {
+        private DisplayContent mDisplayContent;
+        private DisplayContentsIterator mDisplayContentsIterator;
+        private WindowList mWindowList;
+        private int mWindowListIndex;
+        private boolean mReverse;
+
+        AllWindowsIterator() {
+            mDisplayContentsIterator = new DisplayContentsIterator();
+            mDisplayContent = mDisplayContentsIterator.next();
+            mWindowList = mDisplayContent.getWindowList();
+        }
+
+        AllWindowsIterator(boolean reverse) {
+            this();
+            mReverse = reverse;
+            mWindowListIndex = reverse ? mWindowList.size() - 1 : 0;
+        }
+
+        @Override
+        public boolean hasNext() {
+            if (mReverse) {
+                return mWindowListIndex >= 0;
+            }
+            return mWindowListIndex < mWindowList.size();
+        }
+
+        @Override
+        public WindowState next() {
+            if (hasNext()) {
+                WindowState win = mWindowList.get(mWindowListIndex);
+                if (mReverse) {
+                    mWindowListIndex--;
+                    if (mWindowListIndex < 0 && mDisplayContentsIterator.hasNext()) {
+                        mDisplayContent = mDisplayContentsIterator.next();
+                        mWindowList = mDisplayContent.getWindowList();
+                        mWindowListIndex = mWindowList.size() - 1;
+                    }
+                } else {
+                    mWindowListIndex++;
+                    if (mWindowListIndex >= mWindowList.size()
+                            && mDisplayContentsIterator.hasNext()) {
+                        mDisplayContent = mDisplayContentsIterator.next();
+                        mWindowList = mDisplayContent.getWindowList();
+                        mWindowListIndex = 0;
+                    }
+                }
+                return win;
+            }
+            throw new NoSuchElementException();
+        }
+
+        @Override
+        public void remove() {
+            throw new IllegalArgumentException("AllWindowsIterator.remove not implemented");
+        }
+    }
+
+    // There is an inherent assumption that this will never return null.
+    public DisplayContent getDefaultDisplayContentLocked() {
+        return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
+    }
+
+    public WindowList getDefaultWindowListLocked() {
+        return getDefaultDisplayContentLocked().getWindowList();
+    }
+
+    public DisplayInfo getDefaultDisplayInfoLocked() {
+        return getDefaultDisplayContentLocked().getDisplayInfo();
+    }
+
+    /**
+     * Return the list of WindowStates associated on the passed display.
+     * @param display The screen to return windows from.
+     * @return The list of WindowStates on the screen, or null if the there is no screen.
+     */
+    public WindowList getWindowListLocked(final Display display) {
+        final DisplayContent displayContent = getDisplayContentLocked(display.getDisplayId());
+        return displayContent != null ? displayContent.getWindowList() : null;
+    }
+
+    @Override
+    public void onDisplayAdded(int displayId) {
+        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
+    }
+
+    private void handleDisplayAddedLocked(int displayId) {
+        final Display display = mDisplayManager.getDisplay(displayId);
+        if (display != null) {
+            createDisplayContentLocked(display);
+            displayReady(displayId);
+        }
+    }
+
+    @Override
+    public void onDisplayRemoved(int displayId) {
+        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
+    }
+
+    private void handleDisplayRemovedLocked(int displayId) {
+        final DisplayContent displayContent = getDisplayContentLocked(displayId);
+        if (displayContent != null) {
+            mDisplayContents.delete(displayId);
+            WindowList windows = displayContent.getWindowList();
+            while (!windows.isEmpty()) {
+                final WindowState win = windows.get(windows.size() - 1);
+                removeWindowLocked(win.mSession, win);
+            }
+        }
+        mAnimator.removeDisplayLocked(displayId);
+    }
+
+    @Override
+    public void onDisplayChanged(int displayId) {
+        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
+    }
+
+    private void handleDisplayChangedLocked(int displayId) {
+        final DisplayContent displayContent = getDisplayContentLocked(displayId);
+        if (displayContent != null) {
+            displayContent.updateDisplayInfo();
+        }
     }
 }
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index a00e8a51..35bebbe 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -34,7 +34,9 @@
 import android.graphics.Region;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.Slog;
+import android.view.DisplayInfo;
 import android.view.Gravity;
 import android.view.IApplicationToken;
 import android.view.IWindow;
@@ -47,6 +49,9 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
+class WindowList extends ArrayList<WindowState> {
+}
+
 /**
  * A window in the window manager.
  */
@@ -245,21 +250,31 @@
     // Used to improve performance of toString()
     String mStringNameCache;
     CharSequence mLastTitle;
-    boolean mWasPaused;
+    boolean mWasExiting;
 
     final WindowStateAnimator mWinAnimator;
 
     boolean mHasSurface = false;
 
+    DisplayContent  mDisplayContent;
+
+    // UserId and appId of the owner. Don't display windows of non-current user.
+    int mOwnerUid;
+
+    /** When true this window can be displayed on screens owther than mOwnerUid's */
+    private boolean mShowToOwnerOnly;
+
     WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState attachedWindow, int seq, WindowManager.LayoutParams a,
-           int viewVisibility) {
+           int viewVisibility, final DisplayContent displayContent) {
         mService = service;
         mSession = s;
         mClient = c;
         mToken = token;
+        mOwnerUid = s.mUid;
         mAttrs.copyFrom(a);
         mViewVisibility = viewVisibility;
+        mDisplayContent = displayContent;
         mPolicy = mService.mPolicy;
         mContext = mService.mContext;
         DeathRecipient deathRecipient = new DeathRecipient();
@@ -267,7 +282,7 @@
         mEnforceSizeCompat = (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
         if (WindowManagerService.localLOGV) Slog.v(
             TAG, "Window " + this + " client=" + c.asBinder()
-            + " token=" + token + " (" + mAttrs.token + ")");
+            + " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
         try {
             c.asBinder().linkToDeath(deathRecipient, 0);
         } catch (RemoteException e) {
@@ -317,9 +332,6 @@
             mIsFloatingLayer = mIsImWindow || mIsWallpaper;
         }
 
-        mWinAnimator = new WindowStateAnimator(service, this, mAttachedWindow);
-        mWinAnimator.mAlpha = a.alpha;
-
         WindowState appWin = this;
         while (appWin.mAttachedWindow != null) {
             appWin = appWin.mAttachedWindow;
@@ -335,6 +347,9 @@
         mRootToken = appToken;
         mAppToken = appToken.appWindowToken;
 
+        mWinAnimator = new WindowStateAnimator(this);
+        mWinAnimator.mAlpha = a.alpha;
+
         mRequestedWidth = 0;
         mRequestedHeight = 0;
         mLastRequestedWidth = 0;
@@ -343,7 +358,8 @@
         mYOffset = 0;
         mLayer = 0;
         mInputWindowHandle = new InputWindowHandle(
-                mAppToken != null ? mAppToken.mInputApplicationHandle : null, this);
+                mAppToken != null ? mAppToken.mInputApplicationHandle : null, this,
+                displayContent.getDisplayId());
     }
 
     void attach() {
@@ -479,8 +495,9 @@
         }
 
         if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
-            mService.updateWallpaperOffsetLocked(this,
-                    mService.mAppDisplayWidth, mService.mAppDisplayHeight, false);
+            final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
+            mService.updateWallpaperOffsetLocked(this, displayInfo.appWidth, displayInfo.appHeight,
+                    false);
         }
 
         if (WindowManagerService.localLOGV) {
@@ -496,6 +513,21 @@
         }
     }
 
+    MagnificationSpec getWindowMagnificationSpecLocked() {
+        MagnificationSpec spec = mDisplayContent.mMagnificationSpec;
+        if (spec != null && !spec.isNop()) {
+            if (mAttachedWindow != null) {
+                if (!mPolicy.canMagnifyWindowLw(mAttachedWindow.mAttrs)) {
+                    return null;
+                }
+            }
+            if (!mPolicy.canMagnifyWindowLw(mAttrs)) {
+                return null;
+            }
+        }
+        return spec;
+    }
+
     @Override
     public Rect getFrameLw() {
         return mFrame;
@@ -541,9 +573,11 @@
         return mAttrs;
     }
 
+    @Override
     public boolean getNeedsMenuLw(WindowManagerPolicy.WindowState bottom) {
         int index = -1;
         WindowState ws = this;
+        WindowList windows = getWindowList();
         while (true) {
             if ((ws.mAttrs.privateFlags
                     & WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY) != 0) {
@@ -558,28 +592,35 @@
             // look behind it.
             // First, we may need to determine the starting position.
             if (index < 0) {
-                index = mService.mWindows.indexOf(ws);
+                index = windows.indexOf(ws);
             }
             index--;
             if (index < 0) {
                 return false;
             }
-            ws = mService.mWindows.get(index);
+            ws = windows.get(index);
         }
     }
 
+    @Override
     public int getSystemUiVisibility() {
         return mSystemUiVisibility;
     }
 
+    @Override
     public int getSurfaceLayer() {
         return mLayer;
     }
 
+    @Override
     public IApplicationToken getAppToken() {
         return mAppToken != null ? mAppToken.appToken : null;
     }
-    
+
+    public int getDisplayId() {
+        return mDisplayContent.getDisplayId();
+    }
+
     public long getInputDispatchingTimeoutNanos() {
         return mAppToken != null
                 ? mAppToken.inputDispatchingTimeoutNanos
@@ -612,6 +653,7 @@
      * surface, or we are in the process of running an exit animation
      * that will remove the surface, or its app token has been hidden.
      */
+    @Override
     public boolean isVisibleLw() {
         final AppWindowToken atoken = mAppToken;
         return mHasSurface && mPolicyVisibility && !mAttachedHidden
@@ -627,6 +669,7 @@
      * for this "hidden behind keyguard" state rather than overloading
      * mPolicyVisibility.  Ungh.
      */
+    @Override
     public boolean isVisibleOrBehindKeyguardLw() {
         if (mRootToken.waitingToShow &&
                 mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
@@ -745,22 +788,26 @@
      * Like isOnScreen, but returns false if the surface hasn't yet
      * been drawn.
      */
+    @Override
     public boolean isDisplayedLw() {
         final AppWindowToken atoken = mAppToken;
         return isDrawnLw() && mPolicyVisibility
             && ((!mAttachedHidden &&
                     (atoken == null || !atoken.hiddenRequested))
-                    || mWinAnimator.mAnimating);
+                        || mWinAnimator.mAnimating
+                        || (atoken != null && atoken.mAppAnimator.animation != null));
     }
 
     /**
      * Return true if this window (or a window it is attached to, but not
      * considering its app token) is currently animating.
      */
+    @Override
     public boolean isAnimatingLw() {
         return mWinAnimator.mAnimation != null;
     }
 
+    @Override
     public boolean isGoneForLayoutLw() {
         final AppWindowToken atoken = mAppToken;
         return mViewVisibility == View.GONE
@@ -809,6 +856,18 @@
                 mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
     }
 
+    boolean isConfigChanged() {
+        return mConfiguration != mService.mCurConfiguration
+                && (mConfiguration == null
+                        || (mConfiguration.diff(mService.mCurConfiguration) != 0));
+    }
+
+    boolean isConfigDiff(int mask) {
+        return mConfiguration != mService.mCurConfiguration
+                && mConfiguration != null
+                && (mConfiguration.diff(mService.mCurConfiguration) & mask) != 0;
+    }
+
     void removeLocked() {
         disposeInputChannel();
         
@@ -816,8 +875,8 @@
             if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + this + " from " + mAttachedWindow);
             mAttachedWindow.mChildWindows.remove(this);
         }
-        mWinAnimator.destroyDeferredSurfaceLocked();
-        mWinAnimator.destroySurfaceLocked();
+        mWinAnimator.destroyDeferredSurfaceLocked(false);
+        mWinAnimator.destroySurfaceLocked(false);
         mSession.windowRemovedLocked();
         try {
             mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
@@ -884,6 +943,11 @@
     }
 
     boolean showLw(boolean doAnimation, boolean requestAnim) {
+        if (isHiddenFromUserLocked()) {
+            Slog.w(TAG, "current user violation " + mService.mCurrentUserId + " trying to display "
+                    + this + ", type " + mAttrs.type + ", belonging to " + mOwnerUid);
+            return false;
+        }
         if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
             // Already showing.
             return false;
@@ -907,7 +971,7 @@
             mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_ENTER, true);
         }
         if (requestAnim) {
-            mService.scheduleAnimationLocked();
+            mService.updateLayoutToAnimationLocked();
         }
         return true;
     }
@@ -950,7 +1014,7 @@
             }
         }
         if (requestAnim) {
-            mService.scheduleAnimationLocked();
+            mService.updateLayoutToAnimationLocked();
         }
         return true;
     }
@@ -960,6 +1024,42 @@
         return mClient.asBinder().isBinderAlive();
     }
 
+    boolean isClosing() {
+        return mExiting || (mService.mClosingApps.contains(mAppToken));
+    }
+
+    @Override
+    public boolean isDefaultDisplay() {
+        return mDisplayContent.isDefaultDisplay;
+    }
+
+    public void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) {
+        mShowToOwnerOnly = showToOwnerOnly;
+    }
+
+    boolean isHiddenFromUserLocked() {
+        // Attached windows are evaluated based on the window that they are attached to.
+        WindowState win = this;
+        while (win.mAttachedWindow != null) {
+            win = win.mAttachedWindow;
+        }
+        if (win.mAttrs.type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
+                && win.mAppToken != null && win.mAppToken.showWhenLocked) {
+            // Save some cycles by not calling getDisplayInfo unless it is an application
+            // window intended for all users.
+            final DisplayInfo displayInfo = win.mDisplayContent.getDisplayInfo();
+            if (win.mFrame.left <= 0 && win.mFrame.top <= 0
+                    && win.mFrame.right >= displayInfo.appWidth
+                    && win.mFrame.bottom >= displayInfo.appHeight) {
+                // Is a fullscreen window, like the clock alarm. Show to everyone.
+                return false;
+            }
+        }
+
+        return win.mShowToOwnerOnly
+                && UserHandle.getUserId(win.mOwnerUid) != mService.mCurrentUserId;
+    }
+
     private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
         outRegion.set(
                 frame.left + inset.left, frame.top + inset.top,
@@ -988,9 +1088,16 @@
         }
     }
 
+    WindowList getWindowList() {
+        return mDisplayContent.getWindowList();
+    }
+
     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
-        pw.print(prefix); pw.print("mSession="); pw.print(mSession);
+        pw.print(prefix); pw.print("mDisplayId="); pw.print(mDisplayContent.getDisplayId());
+                pw.print(" mSession="); pw.print(mSession);
                 pw.print(" mClient="); pw.println(mClient.asBinder());
+        pw.print(prefix); pw.print("mOwnerUid="); pw.print(mOwnerUid);
+                pw.print(" mShowToOwnerOnly="); pw.println(mShowToOwnerOnly);
         pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
         pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
                 pw.print(" h="); pw.print(mRequestedHeight);
@@ -1060,11 +1167,15 @@
             if (mTouchableInsets != 0 || mGivenInsetsPending) {
                 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
                         pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
+                Region region = new Region();
+                getTouchableRegion(region);
+                pw.print(prefix); pw.print("touchable region="); pw.println(region);
             }
             pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
         }
         pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface);
-                pw.print(" mShownFrame="); mShownFrame.printShortString(pw); pw.println();
+                pw.print(" mShownFrame="); mShownFrame.printShortString(pw);
+                pw.print(" isReadyForDisplay()="); pw.println(isReadyForDisplay());
         if (dumpAll) {
             pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
                     pw.print(" last="); mLastFrame.printShortString(pw);
@@ -1095,7 +1206,8 @@
                     pw.print(" visible="); mLastVisibleInsets.printShortString(pw);
                     pw.println();
         }
-        mWinAnimator.dump(pw, prefix, dumpAll);
+        pw.print(prefix); pw.print(mWinAnimator); pw.println(":");
+        mWinAnimator.dump(pw, prefix + "  ", dumpAll);
         if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
             pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
                     pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
@@ -1130,11 +1242,12 @@
     @Override
     public String toString() {
         if (mStringNameCache == null || mLastTitle != mAttrs.getTitle()
-                || mWasPaused != mToken.paused) {
+                || mWasExiting != mExiting) {
             mLastTitle = mAttrs.getTitle();
-            mWasPaused = mToken.paused;
+            mWasExiting = mExiting;
             mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this))
-                    + " " + mLastTitle + " paused=" + mWasPaused + "}";
+                    + " u" + UserHandle.getUserId(mSession.mUid)
+                    + " " + mLastTitle + (mExiting ? " EXITING}" : "}");
         }
         return mStringNameCache;
     }
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 03e52fe..7b30c89 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -3,9 +3,7 @@
 package com.android.server.wm;
 
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-
-import static com.android.server.wm.WindowManagerService.LayoutFields.CLEAR_ORIENTATION_CHANGE_COMPLETE;
+import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE;
 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_TURN_ON_SCREEN;
 
 import android.content.Context;
@@ -17,6 +15,7 @@
 import android.graphics.Region;
 import android.os.Debug;
 import android.util.Slog;
+import android.view.DisplayInfo;
 import android.view.Surface;
 import android.view.SurfaceSession;
 import android.view.WindowManager;
@@ -31,6 +30,16 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
+class WinAnimatorList extends ArrayList<WindowStateAnimator> {
+    public WinAnimatorList() {
+        super();
+    }
+
+    public WinAnimatorList(WinAnimatorList other) {
+        super(other);
+    }
+}
+
 /**
  * Keep track of animations and surface operations for a single WindowState.
  **/
@@ -48,13 +57,20 @@
 
     static final String TAG = "WindowStateAnimator";
 
+    // Unchanging local convenience fields.
     final WindowManagerService mService;
     final WindowState mWin;
-    final WindowState mAttachedWindow;
+    final WindowStateAnimator mAttachedWinAnimator;
     final WindowAnimator mAnimator;
+    AppWindowAnimator mAppAnimator;
     final Session mSession;
     final WindowManagerPolicy mPolicy;
     final Context mContext;
+    final boolean mIsWallpaper;
+
+    // If this is a universe background window, this is the transformation
+    // it is applying to the rest of the universe.
+    final Transformation mUniverseTransform = new Transformation();
 
     // Currently running animation.
     boolean mAnimating;
@@ -138,19 +154,28 @@
     int mAttrFlags;
     int mAttrType;
 
-    public WindowStateAnimator(final WindowManagerService service, final WindowState win,
-                               final WindowState attachedWindow) {
+    final int mLayerStack;
+
+    public WindowStateAnimator(final WindowState win) {
+        final WindowManagerService service = win.mService;
+
         mService = service;
+        mAnimator = service.mAnimator;
+        mPolicy = service.mPolicy;
+        mContext = service.mContext;
+        final DisplayInfo displayInfo = win.mDisplayContent.getDisplayInfo();
+        mAnimDw = displayInfo.appWidth;
+        mAnimDh = displayInfo.appHeight;
+
         mWin = win;
-        mAttachedWindow = attachedWindow;
-        mAnimator = mService.mAnimator;
+        mAttachedWinAnimator = win.mAttachedWindow == null
+                ? null : win.mAttachedWindow.mWinAnimator;
+        mAppAnimator = win.mAppToken == null ? null : win.mAppToken.mAppAnimator;
         mSession = win.mSession;
-        mPolicy = mService.mPolicy;
-        mContext = mService.mContext;
         mAttrFlags = win.mAttrs.flags;
         mAttrType = win.mAttrs.type;
-        mAnimDw = service.mAppDisplayWidth;
-        mAnimDh = service.mAppDisplayHeight;
+        mIsWallpaper = win.mIsWallpaper;
+        mLayerStack = win.mDisplayContent.getDisplay().getLayerStack();
     }
 
     public void setAnimation(Animation anim) {
@@ -177,20 +202,17 @@
 
     /** Is the window or its container currently animating? */
     boolean isAnimating() {
-        final WindowState attached = mAttachedWindow;
-        final AppWindowToken atoken = mWin.mAppToken;
         return mAnimation != null
-                || (attached != null && attached.mWinAnimator.mAnimation != null)
-                || (atoken != null &&
-                        (atoken.mAppAnimator.animation != null
-                                || atoken.inPendingTransaction));
+                || (mAttachedWinAnimator != null && mAttachedWinAnimator.mAnimation != null)
+                || (mAppAnimator != null &&
+                        (mAppAnimator.animation != null
+                                || mAppAnimator.mAppToken.inPendingTransaction));
     }
 
     /** Is the window animating the DummyAnimation? */
     boolean isDummyAnimation() {
-        final AppWindowToken atoken = mWin.mAppToken;
-        return atoken != null
-                && atoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation;
+        return mAppAnimator != null
+                && mAppAnimator.animation == AppWindowAnimator.sDummyAnimation;
     }
 
     /** Is this window currently animating? */
@@ -203,7 +225,7 @@
             mAnimation.cancel();
             mAnimation = null;
             mLocalAnimating = false;
-            destroySurfaceLocked();
+            destroySurfaceLocked(true);
         }
     }
 
@@ -213,7 +235,7 @@
         }
         mTransformation.clear();
         final boolean more = mAnimation.getTransformation(currentTime, mTransformation);
-        if (DEBUG_ANIM) Slog.v(
+        if (false && DEBUG_ANIM) Slog.v(
             TAG, "Stepped animation in " + this +
             ": more=" + more + ", xform=" + mTransformation);
         return more;
@@ -240,8 +262,9 @@
                         " scale=" + mService.mWindowAnimationScale);
                     mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(),
                             mAnimDw, mAnimDh);
-                    mAnimDw = mService.mAppDisplayWidth;
-                    mAnimDh = mService.mAppDisplayHeight;
+                    final DisplayInfo displayInfo = mWin.mDisplayContent.getDisplayInfo();
+                    mAnimDw = displayInfo.appWidth;
+                    mAnimDh = displayInfo.appHeight;
                     mAnimation.setStartTime(currentTime);
                     mLocalAnimating = true;
                     mAnimating = true;
@@ -257,8 +280,8 @@
                 //WindowManagerService.this.dump();
             }
             mHasLocalTransformation = false;
-            if ((!mLocalAnimating || mAnimationIsEntrance) && mWin.mAppToken != null
-                    && mWin.mAppToken.mAppAnimator.animation != null) {
+            if ((!mLocalAnimating || mAnimationIsEntrance) && mAppAnimator != null
+                    && mAppAnimator.animation != null) {
                 // When our app token is animating, we kind-of pretend like
                 // we are as well.  Note the mLocalAnimating mAnimationIsEntrance
                 // part of this check means that we will only do this if
@@ -305,7 +328,7 @@
         mAnimLayer = mWin.mLayer;
         if (mWin.mIsImWindow) {
             mAnimLayer += mService.mInputMethodAnimLayerAdjustment;
-        } else if (mWin.mIsWallpaper) {
+        } else if (mIsWallpaper) {
             mAnimLayer += mService.mWallpaperAnimLayerAdjustment;
         }
         if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this
@@ -318,7 +341,7 @@
                         + mWin.mPolicyVisibilityAfterAnim);
             }
             mWin.mPolicyVisibility = mWin.mPolicyVisibilityAfterAnim;
-            mService.mLayoutNeeded = true;
+            mWin.mDisplayContent.layoutNeeded = true;
             if (!mWin.mPolicyVisibility) {
                 if (mService.mCurrentFocus == mWin) {
                     mService.mFocusMayChange = true;
@@ -342,9 +365,10 @@
         }
 
         finishExit();
-        mAnimator.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+        final int displayId = mWin.mDisplayContent.getDisplayId();
+        mAnimator.setPendingLayoutChanges(displayId, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) mService.debugLayoutRepeats(
-                "WindowStateAnimator", mAnimator.mPendingLayoutChanges);
+                "WindowStateAnimator", mAnimator.mPendingLayoutChanges.get(displayId));
 
         if (mWin.mAppToken != null) {
             mWin.mAppToken.updateReportedVisibilityLocked();
@@ -388,7 +412,7 @@
             mService.mPendingRemove.add(mWin);
             mWin.mRemoveOnExit = false;
         }
-        mAnimator.hideWallpapersLocked(mWin);
+        mAnimator.hideWallpapersLocked(mWin, true);
     }
 
     void hide() {
@@ -460,22 +484,14 @@
         private final Point mSize = new Point();
         private final Rect mWindowCrop = new Rect();
         private boolean mShown = false;
-        private String mName = "Not named";
+        private int mLayerStack;
+        private String mName;
 
         public SurfaceTrace(SurfaceSession s,
-                       int pid, int display, int w, int h, int format, int flags) throws
-                       OutOfResourcesException {
-            super(s, pid, display, w, h, format, flags);
-            mSize.set(w, h);
-            Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by "
-                    + Debug.getCallers(3));
-        }
-
-        public SurfaceTrace(SurfaceSession s,
-                       int pid, String name, int display, int w, int h, int format, int flags)
+                       String name, int w, int h, int format, int flags)
                    throws OutOfResourcesException {
-            super(s, pid, name, display, w, h, format, flags);
-            mName = name;
+            super(s, name, w, h, format, flags);
+            mName = name != null ? name : "Not named";
             mSize.set(w, h);
             Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by "
                     + Debug.getCallers(3));
@@ -484,17 +500,21 @@
         @Override
         public void setAlpha(float alpha) {
             super.setAlpha(alpha);
+            if (alpha != mSurfaceTraceAlpha) {
+                Slog.v(SURFACE_TAG, "setAlpha: " + this + ". Called by "
+                        + Debug.getCallers(3));
+            }
             mSurfaceTraceAlpha = alpha;
-            Slog.v(SURFACE_TAG, "setAlpha: " + this + ". Called by "
-                    + Debug.getCallers(3));
         }
 
         @Override
         public void setLayer(int zorder) {
             super.setLayer(zorder);
+            if (zorder != mLayer) {
+                Slog.v(SURFACE_TAG, "setLayer: " + this + ". Called by "
+                        + Debug.getCallers(3));
+            }
             mLayer = zorder;
-            Slog.v(SURFACE_TAG, "setLayer: " + this + ". Called by "
-                    + Debug.getCallers(3));
 
             sSurfaces.remove(this);
             int i;
@@ -510,42 +530,61 @@
         @Override
         public void setPosition(float x, float y) {
             super.setPosition(x, y);
+            if (x != mPosition.x || y != mPosition.y) {
+                Slog.v(SURFACE_TAG, "setPosition: " + this + ". Called by "
+                        + Debug.getCallers(3));
+            }
             mPosition.set(x, y);
-            Slog.v(SURFACE_TAG, "setPosition: " + this + ". Called by "
-                    + Debug.getCallers(3));
         }
 
         @Override
         public void setSize(int w, int h) {
             super.setSize(w, h);
+            if (w != mSize.x || h != mSize.y) {
+                Slog.v(SURFACE_TAG, "setSize: " + this + ". Called by "
+                        + Debug.getCallers(3));
+            }
             mSize.set(w, h);
-            Slog.v(SURFACE_TAG, "setSize: " + this + ". Called by "
-                    + Debug.getCallers(3));
         }
 
         @Override
         public void setWindowCrop(Rect crop) {
             super.setWindowCrop(crop);
             if (crop != null) {
+                if (!crop.equals(mWindowCrop)) {
+                    Slog.v(SURFACE_TAG, "setWindowCrop: " + this + ". Called by "
+                            + Debug.getCallers(3));
+                }
                 mWindowCrop.set(crop);
             }
-            Slog.v(SURFACE_TAG, "setWindowCrop: " + this + ". Called by "
-                    + Debug.getCallers(3));
+        }
+
+        @Override
+        public void setLayerStack(int layerStack) {
+            super.setLayerStack(layerStack);
+            if (layerStack != mLayerStack) {
+                Slog.v(SURFACE_TAG, "setLayerStack: " + this + ". Called by " + Debug.getCallers(3));
+            }
+            mLayerStack = layerStack;
         }
 
         @Override
         public void hide() {
             super.hide();
+            if (mShown) {
+                Slog.v(SURFACE_TAG, "hide: " + this + ". Called by "
+                        + Debug.getCallers(3));
+            }
             mShown = false;
-            Slog.v(SURFACE_TAG, "hide: " + this + ". Called by "
-                    + Debug.getCallers(3));
         }
         @Override
         public void show() {
             super.show();
+            if (!mShown) {
+                Slog.v(SURFACE_TAG, "show: " + this + ". Called by "
+                        + Debug.getCallers(3));
+            }
             mShown = true;
-            Slog.v(SURFACE_TAG, "show: " + this + ". Called by "
-                    + Debug.getCallers(3));
         }
 
         @Override
@@ -574,7 +613,7 @@
         @Override
         public String toString() {
             return "Surface " + Integer.toHexString(System.identityHashCode(this)) + " "
-                    + mName + ": shown=" + mShown + " layer=" + mLayer
+                    + mName + " (" + mLayerStack + "): shown=" + mShown + " layer=" + mLayer
                     + " alpha=" + mSurfaceTraceAlpha + " " + mPosition.x + "," + mPosition.y
                     + " " + mSize.x + "x" + mSize.y
                     + " crop=" + mWindowCrop.toShortString();
@@ -592,7 +631,7 @@
 
             mService.makeWindowFreezingScreenIfNeededLocked(mWin);
 
-            int flags = 0;
+            int flags = Surface.HIDDEN;
             final WindowManager.LayoutParams attrs = mWin.mAttrs;
 
             if ((attrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
@@ -636,14 +675,14 @@
                 }
                 if (DEBUG_SURFACE_TRACE) {
                     mSurface = new SurfaceTrace(
-                            mSession.mSurfaceSession, mSession.mPid,
+                            mSession.mSurfaceSession,
                             attrs.getTitle().toString(),
-                            0, w, h, format, flags);
+                            w, h, format, flags);
                 } else {
                     mSurface = new Surface(
-                        mSession.mSurfaceSession, mSession.mPid,
+                        mSession.mSurfaceSession,
                         attrs.getTitle().toString(),
-                        0, w, h, format, flags);
+                        w, h, format, flags);
                 }
                 mWin.mHasSurface = true;
                 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG,
@@ -685,14 +724,10 @@
                     mSurfaceY = mWin.mFrame.top + mWin.mYOffset;
                     mSurface.setPosition(mSurfaceX, mSurfaceY);
                     mSurfaceLayer = mAnimLayer;
+                    mSurface.setLayerStack(mLayerStack);
                     mSurface.setLayer(mAnimLayer);
                     mSurface.setAlpha(0);
                     mSurfaceShown = false;
-                    mSurface.hide();
-                    if ((mWin.mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
-                        if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "DITHER", null);
-                        mSurface.setFlags(Surface.SURFACE_DITHER, Surface.SURFACE_DITHER);
-                    }
                 } catch (RuntimeException e) {
                     Slog.w(TAG, "Error creating surface in " + w, e);
                     mService.reclaimSomeSurfaceMemoryLocked(this, "create-init", true);
@@ -709,7 +744,7 @@
         return mSurface;
     }
 
-    void destroySurfaceLocked() {
+    void destroySurfaceLocked(boolean fromAnimator) {
         if (mWin.mAppToken != null && mWin == mWin.mAppToken.startingWindow) {
             mWin.mAppToken.startingDisplayed = false;
         }
@@ -759,7 +794,7 @@
                     }
                     mSurface.destroy();
                 }
-                mAnimator.hideWallpapersLocked(mWin);
+                mAnimator.hideWallpapersLocked(mWin, fromAnimator);
             } catch (RuntimeException e) {
                 Slog.w(TAG, "Exception thrown when destroying Window " + this
                     + " surface " + mSurface + " session " + mSession
@@ -773,7 +808,7 @@
         }
     }
 
-    void destroyDeferredSurfaceLocked() {
+    void destroyDeferredSurfaceLocked(boolean fromAnimator) {
         try {
             if (mPendingDestroySurface != null) {
                 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
@@ -785,7 +820,7 @@
                     WindowManagerService.logSurface(mWin, "DESTROY PENDING", e);
                 }
                 mPendingDestroySurface.destroy();
-                mAnimator.hideWallpapersLocked(mWin);
+                mAnimator.hideWallpapersLocked(mWin, fromAnimator);
             }
         } catch (RuntimeException e) {
             Slog.w(TAG, "Exception thrown when destroying Window "
@@ -799,31 +834,28 @@
     void computeShownFrameLocked() {
         final boolean selfTransformation = mHasLocalTransformation;
         Transformation attachedTransformation =
-                (mAttachedWindow != null && mAttachedWindow.mWinAnimator.mHasLocalTransformation)
-                ? mAttachedWindow.mWinAnimator.mTransformation : null;
-        final AppWindowAnimator appAnimator =
-                mWin.mAppToken == null ? null : mWin.mAppToken.mAppAnimator;
-        Transformation appTransformation = (appAnimator != null && appAnimator.hasTransformation)
-                ? appAnimator.transformation : null;
+                (mAttachedWinAnimator != null && mAttachedWinAnimator.mHasLocalTransformation)
+                ? mAttachedWinAnimator.mTransformation : null;
+        Transformation appTransformation = (mAppAnimator != null && mAppAnimator.hasTransformation)
+                ? mAppAnimator.transformation : null;
 
         // Wallpapers are animated based on the "real" window they
         // are currently targeting.
-        if (mWin.mAttrs.type == TYPE_WALLPAPER && mService.mLowerWallpaperTarget == null
-                && mService.mWallpaperTarget != null) {
-            if (mService.mWallpaperTarget.mWinAnimator.mHasLocalTransformation &&
-                    mService.mWallpaperTarget.mWinAnimator.mAnimation != null &&
-                    !mService.mWallpaperTarget.mWinAnimator.mAnimation.getDetachWallpaper()) {
-                attachedTransformation = mService.mWallpaperTarget.mWinAnimator.mTransformation;
+        if (mIsWallpaper && mAnimator.mLowerWallpaperTarget == null
+                && mAnimator.mWallpaperTarget != null) {
+            final WindowStateAnimator wallpaperAnimator = mAnimator.mWallpaperTarget.mWinAnimator;
+            if (wallpaperAnimator.mHasLocalTransformation &&
+                    wallpaperAnimator.mAnimation != null &&
+                    !wallpaperAnimator.mAnimation.getDetachWallpaper()) {
+                attachedTransformation = wallpaperAnimator.mTransformation;
                 if (WindowManagerService.DEBUG_WALLPAPER && attachedTransformation != null) {
                     Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
                 }
             }
-            final AppWindowAnimator wpAppAnimator = mService.mWallpaperTarget.mAppToken == null
-                    ? null : mService.mWallpaperTarget.mAppToken.mAppAnimator;
-            if (wpAppAnimator != null &&
-                    wpAppAnimator.hasTransformation &&
-                    wpAppAnimator.animation != null &&
-                    !wpAppAnimator.animation.getDetachWallpaper()) {
+            final AppWindowAnimator wpAppAnimator = mAnimator.mWpAppAnimator;
+            if (wpAppAnimator != null && wpAppAnimator.hasTransformation
+                    && wpAppAnimator.animation != null
+                    && !wpAppAnimator.animation.getDetachWallpaper()) {
                 appTransformation = wpAppAnimator.transformation;
                 if (WindowManagerService.DEBUG_WALLPAPER && appTransformation != null) {
                     Slog.v(TAG, "WP target app xform: " + appTransformation);
@@ -831,8 +863,11 @@
             }
         }
 
-        final boolean screenAnimation = mService.mAnimator.mScreenRotationAnimation != null
-                && mService.mAnimator.mScreenRotationAnimation.isAnimating();
+        final int displayId = mWin.getDisplayId();
+        final ScreenRotationAnimation screenRotationAnimation =
+                mAnimator.getScreenRotationAnimationLocked(displayId);
+        final boolean screenAnimation =
+                screenRotationAnimation != null && screenRotationAnimation.isAnimating();
         if (selfTransformation || attachedTransformation != null
                 || appTransformation != null || screenAnimation) {
             // cache often used attributes locally
@@ -870,9 +905,16 @@
             if (appTransformation != null) {
                 tmpMatrix.postConcat(appTransformation.getMatrix());
             }
+            if (mAnimator.mUniverseBackground != null) {
+                tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix());
+            }
             if (screenAnimation) {
-                tmpMatrix.postConcat(
-                        mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getMatrix());
+                tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
+            }
+            MagnificationSpec spec = mWin.getWindowMagnificationSpecLocked();
+            if (spec != null && !spec.isNop()) {
+                tmpMatrix.postScale(spec.mScale, spec.mScale);
+                tmpMatrix.postTranslate(spec.mOffsetX, spec.mOffsetY);
             }
 
             // "convert" it into SurfaceFlinger's format
@@ -913,24 +955,27 @@
                 if (appTransformation != null) {
                     mShownAlpha *= appTransformation.getAlpha();
                 }
+                if (mAnimator.mUniverseBackground != null) {
+                    mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha();
+                }
                 if (screenAnimation) {
-                    mShownAlpha *=
-                        mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getAlpha();
+                    mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha();
                 }
             } else {
                 //Slog.i(TAG, "Not applying alpha transform");
             }
 
-            if (WindowManagerService.localLOGV && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v(
-                TAG, "computeShownFrameLocked: Animating " + this +
-                " mAlpha=" + mAlpha +
-                " self=" + (selfTransformation ? mTransformation.getAlpha() : "null") +
-                " attached=" + (attachedTransformation == null ? "null" : attachedTransformation.getAlpha()) +
-                " app=" + (appTransformation == null ? "null" : appTransformation.getAlpha()) +
-                " screen=" + (screenAnimation ? mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getAlpha()
-                        : "null"));
+            if ((DEBUG_SURFACE_TRACE || WindowManagerService.localLOGV)
+                    && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v(
+                    TAG, "computeShownFrameLocked: Animating " + this + " mAlpha=" + mAlpha
+                    + " self=" + (selfTransformation ? mTransformation.getAlpha() : "null")
+                    + " attached=" + (attachedTransformation == null ?
+                            "null" : attachedTransformation.getAlpha())
+                    + " app=" + (appTransformation == null ? "null" : appTransformation.getAlpha())
+                    + " screen=" + (screenAnimation ?
+                            screenRotationAnimation.getEnterTransformation().getAlpha() : "null"));
             return;
-        } else if (mWin.mIsWallpaper &&
+        } else if (mIsWallpaper &&
                     (mAnimator.mPendingActions & WindowAnimator.WALLPAPER_ACTION_PENDING) != 0) {
             return;
         }
@@ -938,53 +983,117 @@
         if (WindowManagerService.localLOGV) Slog.v(
                 TAG, "computeShownFrameLocked: " + this +
                 " not attached, mAlpha=" + mAlpha);
-        mWin.mShownFrame.set(mWin.mFrame);
-        if (mWin.mXOffset != 0 || mWin.mYOffset != 0) {
-            mWin.mShownFrame.offset(mWin.mXOffset, mWin.mYOffset);
+
+        final boolean applyUniverseTransformation = (mAnimator.mUniverseBackground != null
+                && mWin.mAttrs.type != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND
+                && mWin.mBaseLayer < mAnimator.mAboveUniverseLayer);
+        MagnificationSpec spec = mWin.getWindowMagnificationSpecLocked();
+        if (applyUniverseTransformation || spec != null) {
+            final Rect frame = mWin.mFrame;
+            final float tmpFloats[] = mService.mTmpFloats;
+            final Matrix tmpMatrix = mWin.mTmpMatrix;
+
+            tmpMatrix.setScale(mWin.mGlobalScale, mWin.mGlobalScale);
+            tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
+
+            if (applyUniverseTransformation) {
+                tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix());
+            }
+
+            if (spec != null && !spec.isNop()) {
+                tmpMatrix.postScale(spec.mScale, spec.mScale);
+                tmpMatrix.postTranslate(spec.mOffsetX, spec.mOffsetY);
+            }
+
+            tmpMatrix.getValues(tmpFloats);
+
+            mHaveMatrix = true;
+            mDsDx = tmpFloats[Matrix.MSCALE_X];
+            mDtDx = tmpFloats[Matrix.MSKEW_Y];
+            mDsDy = tmpFloats[Matrix.MSKEW_X];
+            mDtDy = tmpFloats[Matrix.MSCALE_Y];
+            float x = tmpFloats[Matrix.MTRANS_X];
+            float y = tmpFloats[Matrix.MTRANS_Y];
+            int w = frame.width();
+            int h = frame.height();
+            mWin.mShownFrame.set(x, y, x + w, y + h);
+
+            mShownAlpha = mAlpha;
+            if (applyUniverseTransformation) {
+                mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha();
+            }
+        } else {
+            mWin.mShownFrame.set(mWin.mFrame);
+            if (mWin.mXOffset != 0 || mWin.mYOffset != 0) {
+                mWin.mShownFrame.offset(mWin.mXOffset, mWin.mYOffset);
+            }
+            mShownAlpha = mAlpha;
+            mHaveMatrix = false;
+            mDsDx = mWin.mGlobalScale;
+            mDtDx = 0;
+            mDsDy = 0;
+            mDtDy = mWin.mGlobalScale;
         }
-        mShownAlpha = mAlpha;
-        mHaveMatrix = false;
-        mDsDx = mWin.mGlobalScale;
-        mDtDx = 0;
-        mDsDy = 0;
-        mDtDy = mWin.mGlobalScale;
+    }
+
+    void applyDecorRect(final Rect decorRect) {
+        final WindowState w = mWin;
+        // Compute the offset of the window in relation to the decor rect.
+        final int offX = w.mXOffset + w.mFrame.left;
+        final int offY = w.mYOffset + w.mFrame.top;
+        // Initialize the decor rect to the entire frame.
+        w.mSystemDecorRect.set(0, 0, w.mFrame.width(), w.mFrame.height());
+        // Intersect with the decor rect, offsetted by window position.
+        w.mSystemDecorRect.intersect(decorRect.left-offX, decorRect.top-offY,
+                decorRect.right-offX, decorRect.bottom-offY);
+        // If size compatibility is being applied to the window, the
+        // surface is scaled relative to the screen.  Also apply this
+        // scaling to the crop rect.  We aren't using the standard rect
+        // scale function because we want to round things to make the crop
+        // always round to a larger rect to ensure we don't crop too
+        // much and hide part of the window that should be seen.
+        if (w.mEnforceSizeCompat && w.mInvGlobalScale != 1.0f) {
+            final float scale = w.mInvGlobalScale;
+            w.mSystemDecorRect.left = (int) (w.mSystemDecorRect.left * scale - 0.5f);
+            w.mSystemDecorRect.top = (int) (w.mSystemDecorRect.top * scale - 0.5f);
+            w.mSystemDecorRect.right = (int) ((w.mSystemDecorRect.right+1) * scale - 0.5f);
+            w.mSystemDecorRect.bottom = (int) ((w.mSystemDecorRect.bottom+1) * scale - 0.5f);
+        }
     }
 
     void updateSurfaceWindowCrop(final boolean recoveringMemory) {
         final WindowState w = mWin;
+        DisplayInfo displayInfo = w.mDisplayContent.getDisplayInfo();
 
         // Need to recompute a new system decor rect each time.
         if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
             // Currently can't do this cropping for scaled windows.  We'll
             // just keep the crop rect the same as the source surface.
             w.mSystemDecorRect.set(0, 0, w.mRequestedWidth, w.mRequestedHeight);
+        } else if (!w.isDefaultDisplay()) {
+            // On a different display there is no system decor.  Crop the window
+            // by the screen boundaries.
+            w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
+            w.mSystemDecorRect.intersect(-w.mCompatFrame.left, -w.mCompatFrame.top,
+                    displayInfo.logicalWidth - w.mCompatFrame.left,
+                    displayInfo.logicalHeight - w.mCompatFrame.top);
         } else if (w.mLayer >= mService.mSystemDecorLayer) {
             // Above the decor layer is easy, just use the entire window.
+            // Unless we have a universe background...  in which case all the
+            // windows need to be cropped by the screen, so they don't cover
+            // the universe background.
+            if (mAnimator.mUniverseBackground == null) {
+                w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(),
+                        w.mCompatFrame.height());
+            } else {
+                applyDecorRect(mService.mScreenRect);
+            }
+        } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND) {
+            // The universe background isn't cropped.
             w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(),
                     w.mCompatFrame.height());
         } else {
-            final Rect decorRect = mService.mSystemDecorRect;
-            // Compute the offset of the window in relation to the decor rect.
-            final int offX = w.mXOffset + w.mFrame.left;
-            final int offY = w.mYOffset + w.mFrame.top;
-            // Initialize the decor rect to the entire frame.
-            w.mSystemDecorRect.set(0, 0, w.mFrame.width(), w.mFrame.height());
-            // Intersect with the decor rect, offsetted by window position.
-            w.mSystemDecorRect.intersect(decorRect.left-offX, decorRect.top-offY,
-                    decorRect.right-offX, decorRect.bottom-offY);
-            // If size compatibility is being applied to the window, the
-            // surface is scaled relative to the screen.  Also apply this
-            // scaling to the crop rect.  We aren't using the standard rect
-            // scale function because we want to round things to make the crop
-            // always round to a larger rect to ensure we don't crop too
-            // much and hide part of the window that should be seen.
-            if (w.mEnforceSizeCompat && w.mInvGlobalScale != 1.0f) {
-                final float scale = w.mInvGlobalScale;
-                w.mSystemDecorRect.left = (int) (w.mSystemDecorRect.left * scale - 0.5f);
-                w.mSystemDecorRect.top = (int) (w.mSystemDecorRect.top * scale - 0.5f);
-                w.mSystemDecorRect.right = (int) ((w.mSystemDecorRect.right+1) * scale - 0.5f);
-                w.mSystemDecorRect.bottom = (int) ((w.mSystemDecorRect.bottom+1) * scale - 0.5f);
-            }
+            applyDecorRect(mService.mSystemDecorRect);
         }
 
         if (!w.mSystemDecorRect.equals(w.mLastSystemDecorRect)) {
@@ -1003,7 +1112,7 @@
         }
     }
 
-    void setSurfaceBoundaries(final boolean recoveringMemory) {
+    void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
         final WindowState w = mWin;
         int width, height;
         if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
@@ -1053,11 +1162,13 @@
                         "SIZE " + width + "x" + height, null);
                 mSurfaceResized = true;
                 mSurface.setSize(width, height);
-                mAnimator.mPendingLayoutChanges |=
-                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+                final int displayId = w.mDisplayContent.getDisplayId();
+                mAnimator.setPendingLayoutChanges(displayId,
+                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
                 if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) {
-                    mAnimator.startDimming(this, w.mExiting ? 0 : w.mAttrs.dimAmount,
-                            mService.mAppDisplayWidth, mService.mAppDisplayHeight);
+                    final DisplayInfo displayInfo = mWin.mDisplayContent.getDisplayInfo();
+                    mService.startDimmingLocked(this, w.mExiting ? 0 : w.mAttrs.dimAmount,
+                            displayInfo.appWidth, displayInfo.appHeight);
                 }
             } catch (RuntimeException e) {
                 // If something goes wrong with the surface (such
@@ -1090,14 +1201,14 @@
 
         computeShownFrameLocked();
 
-        setSurfaceBoundaries(recoveringMemory);
+        setSurfaceBoundariesLocked(recoveringMemory);
 
-        if (mWin.mIsWallpaper && !mWin.mWallpaperVisible) {
+        if (mIsWallpaper && !mWin.mWallpaperVisible) {
             // Wallpaper is no longer visible and there is no wp target => hide it.
             hide();
         } else if (w.mAttachedHidden || !w.isReadyForDisplay()) {
             hide();
-            mAnimator.hideWallpapersLocked(w);
+            mAnimator.hideWallpapersLocked(w, true);
 
             // If we are waiting for this window to handle an
             // orientation change, well, it is hidden, so
@@ -1151,7 +1262,7 @@
                                 + " during relayout");
                         if (showSurfaceRobustlyLocked()) {
                             mLastHidden = false;
-                            if (w.mIsWallpaper) {
+                            if (mIsWallpaper) {
                                 mService.dispatchWallpaperVisibility(w, true);
                             }
                         } else {
@@ -1169,8 +1280,8 @@
                 }
             }
         } else {
-            if (DEBUG_ANIM) {
-                // Slog.v(TAG, "prepareSurface: No changes in animation for " + mWin);
+            if (DEBUG_ANIM && isAnimating()) {
+                Slog.v(TAG, "prepareSurface: No changes in animation for " + this);
             }
             displayed = true;
         }
@@ -1178,7 +1289,7 @@
         if (displayed) {
             if (w.mOrientationChanging) {
                 if (!w.isDrawnLw()) {
-                    mAnimator.mBulkUpdateParams |= CLEAR_ORIENTATION_CHANGE_COMPLETE;
+                    mAnimator.mBulkUpdateParams &= ~SET_ORIENTATION_CHANGE_COMPLETE;
                     if (DEBUG_ORIENTATION) Slog.v(TAG,
                             "Orientation continue waiting for draw in " + w);
                 } else {
@@ -1239,6 +1350,11 @@
 
     // This must be called while inside a transaction.
     boolean performShowLocked() {
+        if (mWin.isHiddenFromUserLocked()) {
+            Slog.w(TAG, "current user violation " + mService.mCurrentUserId + " trying to display "
+                    + this + ", type " + mWin.mAttrs.type + ", belonging to " + mWin.mOwnerUid);
+            return false;
+        }
         if (DEBUG_VISIBILITY || (DEBUG_STARTING_WINDOW &&
                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING)) {
             RuntimeException e = null;
@@ -1258,7 +1374,7 @@
                     + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false)
                     + " animating=" + mAnimating
                     + " tok animating="
-                    + (mWin.mAppToken != null ? mWin.mAppToken.mAppAnimator.animating : false), e);
+                    + (mAppAnimator != null ? mAppAnimator.animating : false), e);
         }
         if (mDrawState == READY_TO_SHOW && mWin.isReadyForDisplayIgnoringKeyguard()) {
             if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
@@ -1274,7 +1390,7 @@
                         + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false)
                         + " animating=" + mAnimating
                         + " tok animating="
-                        + (mWin.mAppToken != null ? mWin.mAppToken.mAppAnimator.animating : false));
+                        + (mAppAnimator != null ? mAppAnimator.animating : false));
             }
 
             mService.enableScreenIfNeededLocked();
@@ -1286,7 +1402,7 @@
             if (DEBUG_SURFACE_TRACE || DEBUG_ANIM)
                 Slog.v(TAG, "performShowLocked: mDrawState=HAS_DRAWN in " + this);
             mDrawState = HAS_DRAWN;
-            mService.scheduleAnimationLocked();
+            mService.updateLayoutToAnimationLocked();
 
             int i = mWin.mChildWindows.size();
             while (i > 0) {
@@ -1301,7 +1417,7 @@
                         // do a layout.  If called from within the transaction
                         // loop, this will cause it to restart with a new
                         // layout.
-                        mService.mLayoutNeeded = true;
+                        c.mDisplayContent.layoutNeeded = true;
                     }
                 }
             }
@@ -1370,8 +1486,8 @@
         } else {
             transit = WindowManagerPolicy.TRANSIT_SHOW;
         }
-
         applyAnimationLocked(transit, true);
+        mService.scheduleNotifyWindowTranstionIfNeededLocked(mWin, transit);
     }
 
     // TODO(cmautner): Move back to WindowState?
@@ -1400,7 +1516,7 @@
             int attr = -1;
             Animation a = null;
             if (anim != 0) {
-                a = AnimationUtils.loadAnimation(mContext, anim);
+                a = anim != -1 ? AnimationUtils.loadAnimation(mContext, anim) : null;
             } else {
                 switch (transit) {
                     case WindowManagerPolicy.TRANSIT_ENTER:
@@ -1424,7 +1540,7 @@
                     "applyAnimation: win=" + this
                     + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
                     + " a=" + a
-                    + " mAnimation=" + mAnimation
+                    + " transit=" + transit
                     + " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3));
             if (a != null) {
                 if (WindowManagerService.DEBUG_ANIM) {
@@ -1483,6 +1599,11 @@
             pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized);
                     pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred);
         }
+        if (mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND) {
+            pw.print(prefix); pw.print("mUniverseTransform=");
+                    mUniverseTransform.printShortString(pw);
+                    pw.println();
+        }
         if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
             pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
                     pw.print(" mAlpha="); pw.print(mAlpha);
@@ -1499,10 +1620,11 @@
 
     @Override
     public String toString() {
-        StringBuffer sb = new StringBuffer("WindowStateAnimator (");
-        sb.append(mWin.mLastTitle + "): ");
-        sb.append("mSurface " + mSurface);
-        sb.append(", mAnimation " + mAnimation);
+        StringBuffer sb = new StringBuffer("WindowStateAnimator{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(mWin.mAttrs.getTitle());
+        sb.append('}');
         return sb.toString();
     }
 }
diff --git a/services/java/com/android/server/wm/WindowToken.java b/services/java/com/android/server/wm/WindowToken.java
index 5ec151b..e581915 100644
--- a/services/java/com/android/server/wm/WindowToken.java
+++ b/services/java/com/android/server/wm/WindowToken.java
@@ -79,7 +79,6 @@
     }
 
     void dump(PrintWriter pw, String prefix) {
-        pw.print(prefix); pw.print("token="); pw.println(token);
         pw.print(prefix); pw.print("windows="); pw.println(windows);
         pw.print(prefix); pw.print("windowType="); pw.print(windowType);
                 pw.print(" hidden="); pw.print(hidden);
@@ -97,7 +96,7 @@
             StringBuilder sb = new StringBuilder();
             sb.append("WindowToken{");
             sb.append(Integer.toHexString(System.identityHashCode(this)));
-            sb.append(" token="); sb.append(token); sb.append('}');
+            sb.append(" "); sb.append(token); sb.append('}');
             stringName = sb.toString();
         }
         return stringName;
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index e0a14af..d097a93 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -8,7 +8,7 @@
     com_android_server_input_InputManagerService.cpp \
     com_android_server_input_InputWindowHandle.cpp \
     com_android_server_LightsService.cpp \
-    com_android_server_PowerManagerService.cpp \
+    com_android_server_power_PowerManagerService.cpp \
     com_android_server_SerialService.cpp \
     com_android_server_SystemServer.cpp \
     com_android_server_UsbDeviceManager.cpp \
diff --git a/services/jni/com_android_server_BatteryService.cpp b/services/jni/com_android_server_BatteryService.cpp
index ca6f206..e6133af 100644
--- a/services/jni/com_android_server_BatteryService.cpp
+++ b/services/jni/com_android_server_BatteryService.cpp
@@ -42,6 +42,7 @@
     // members
     jfieldID mAcOnline;
     jfieldID mUsbOnline;
+    jfieldID mWirelessOnline;
     jfieldID mBatteryStatus;
     jfieldID mBatteryHealth;
     jfieldID mBatteryPresent;
@@ -71,6 +72,7 @@
 struct PowerSupplyPaths {
     char* acOnlinePath;
     char* usbOnlinePath;
+    char* wirelessOnlinePath;
     char* batteryStatusPath;
     char* batteryHealthPath;
     char* batteryPresentPath;
@@ -88,8 +90,8 @@
     switch (status[0]) {
         case 'C': return gConstants.statusCharging;         // Charging
         case 'D': return gConstants.statusDischarging;      // Discharging
-        case 'F': return gConstants.statusFull;             // Not charging
-        case 'N': return gConstants.statusNotCharging;      // Full
+        case 'F': return gConstants.statusFull;             // Full
+        case 'N': return gConstants.statusNotCharging;      // Not charging
         case 'U': return gConstants.statusUnknown;          // Unknown
             
         default: {
@@ -198,6 +200,7 @@
 {
     setBooleanField(env, obj, gPaths.acOnlinePath, gFieldIds.mAcOnline);
     setBooleanField(env, obj, gPaths.usbOnlinePath, gFieldIds.mUsbOnline);
+    setBooleanField(env, obj, gPaths.wirelessOnlinePath, gFieldIds.mWirelessOnline);
     setBooleanField(env, obj, gPaths.batteryPresentPath, gFieldIds.mBatteryPresent);
     
     setIntField(env, obj, gPaths.batteryCapacityPath, gFieldIds.mBatteryLevel);
@@ -260,6 +263,11 @@
                     if (access(path, R_OK) == 0)
                         gPaths.usbOnlinePath = strdup(path);
                 }
+                else if (strcmp(buf, "Wireless") == 0) {
+                    snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        gPaths.wirelessOnlinePath = strdup(path);
+                }
                 else if (strcmp(buf, "Battery") == 0) {
                     snprintf(path, sizeof(path), "%s/%s/status", POWER_SUPPLY_PATH, name);
                     if (access(path, R_OK) == 0)
@@ -307,6 +315,8 @@
         ALOGE("acOnlinePath not found");
     if (!gPaths.usbOnlinePath)
         ALOGE("usbOnlinePath not found");
+    if (!gPaths.wirelessOnlinePath)
+        ALOGE("wirelessOnlinePath not found");
     if (!gPaths.batteryStatusPath)
         ALOGE("batteryStatusPath not found");
     if (!gPaths.batteryHealthPath)
@@ -331,6 +341,7 @@
     
     gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");
     gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z");
+    gFieldIds.mWirelessOnline = env->GetFieldID(clazz, "mWirelessOnline", "Z");
     gFieldIds.mBatteryStatus = env->GetFieldID(clazz, "mBatteryStatus", "I");
     gFieldIds.mBatteryHealth = env->GetFieldID(clazz, "mBatteryHealth", "I");
     gFieldIds.mBatteryPresent = env->GetFieldID(clazz, "mBatteryPresent", "Z");
@@ -341,6 +352,7 @@
 
     LOG_FATAL_IF(gFieldIds.mAcOnline == NULL, "Unable to find BatteryService.AC_ONLINE_PATH");
     LOG_FATAL_IF(gFieldIds.mUsbOnline == NULL, "Unable to find BatteryService.USB_ONLINE_PATH");
+    LOG_FATAL_IF(gFieldIds.mWirelessOnline == NULL, "Unable to find BatteryService.WIRELESS_ONLINE_PATH");
     LOG_FATAL_IF(gFieldIds.mBatteryStatus == NULL, "Unable to find BatteryService.BATTERY_STATUS_PATH");
     LOG_FATAL_IF(gFieldIds.mBatteryHealth == NULL, "Unable to find BatteryService.BATTERY_HEALTH_PATH");
     LOG_FATAL_IF(gFieldIds.mBatteryPresent == NULL, "Unable to find BatteryService.BATTERY_PRESENT_PATH");
diff --git a/services/jni/com_android_server_LightsService.cpp b/services/jni/com_android_server_LightsService.cpp
index 9ed495195..401e1aa 100644
--- a/services/jni/com_android_server_LightsService.cpp
+++ b/services/jni/com_android_server_LightsService.cpp
@@ -120,7 +120,10 @@
     state.flashOffMS = offMS;
     state.brightnessMode = brightnessMode;
 
-    devices->lights[light]->set_light(devices->lights[light], &state);
+    {
+        ALOGD_IF_SLOW(50, "Excessive delay setting light");
+        devices->lights[light]->set_light(devices->lights[light], &state);
+    }
 }
 
 static JNINativeMethod method_table[] = {
diff --git a/services/jni/com_android_server_PowerManagerService.cpp b/services/jni/com_android_server_PowerManagerService.cpp
deleted file mode 100644
index 0904bdd..0000000
--- a/services/jni/com_android_server_PowerManagerService.cpp
+++ /dev/null
@@ -1,272 +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.
- */
-
-#define LOG_TAG "PowerManagerService-JNI"
-
-//#define LOG_NDEBUG 0
-
-#include "JNIHelp.h"
-#include "jni.h"
-
-#include <limits.h>
-
-#include <android_runtime/AndroidRuntime.h>
-#include <gui/ISurfaceComposer.h>
-#include <utils/Timers.h>
-#include <utils/misc.h>
-#include <utils/String8.h>
-#include <hardware/power.h>
-#include <hardware_legacy/power.h>
-#include <cutils/android_reboot.h>
-#include <suspend/autosuspend.h>
-
-#include <private/gui/ComposerService.h>
-
-#include "com_android_server_PowerManagerService.h"
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-static struct {
-    jmethodID goToSleep;
-    jmethodID userActivity;
-} gPowerManagerServiceClassInfo;
-
-// ----------------------------------------------------------------------------
-
-static jobject gPowerManagerServiceObj;
-static struct power_module* gPowerModule;
-
-static Mutex gPowerManagerLock;
-static bool gScreenOn;
-static bool gScreenBright;
-
-static nsecs_t gLastEventTime[POWER_MANAGER_LAST_EVENT + 1];
-
-// Throttling interval for user activity calls.
-static const nsecs_t MIN_TIME_BETWEEN_USERACTIVITIES = 500 * 1000000L; // 500ms
-
-// ----------------------------------------------------------------------------
-
-static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
-    if (env->ExceptionCheck()) {
-        ALOGE("An exception was thrown by callback '%s'.", methodName);
-        LOGE_EX(env);
-        env->ExceptionClear();
-        return true;
-    }
-    return false;
-}
-
-bool android_server_PowerManagerService_isScreenOn() {
-    AutoMutex _l(gPowerManagerLock);
-    return gScreenOn;
-}
-
-bool android_server_PowerManagerService_isScreenBright() {
-    AutoMutex _l(gPowerManagerLock);
-    return gScreenBright;
-}
-
-void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {
-    // Tell the power HAL when user activity occurs.
-    if (gPowerModule && gPowerModule->powerHint) {
-        gPowerModule->powerHint(gPowerModule, POWER_HINT_INTERACTION, NULL);
-    }
-
-    if (gPowerManagerServiceObj) {
-        // Throttle calls into user activity by event type.
-        // We're a little conservative about argument checking here in case the caller
-        // passes in bad data which could corrupt system state.
-        if (eventType >= 0 && eventType <= POWER_MANAGER_LAST_EVENT) {
-            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-            if (eventTime > now) {
-                eventTime = now;
-            }
-
-            if (gLastEventTime[eventType] + MIN_TIME_BETWEEN_USERACTIVITIES > eventTime) {
-                return;
-            }
-            gLastEventTime[eventType] = eventTime;
-        }
-
-        JNIEnv* env = AndroidRuntime::getJNIEnv();
-
-        env->CallVoidMethod(gPowerManagerServiceObj, gPowerManagerServiceClassInfo.userActivity,
-                nanoseconds_to_milliseconds(eventTime), false, eventType, false);
-        checkAndClearExceptionFromCallback(env, "userActivity");
-    }
-}
-
-void android_server_PowerManagerService_goToSleep(nsecs_t eventTime) {
-    if (gPowerManagerServiceObj) {
-        JNIEnv* env = AndroidRuntime::getJNIEnv();
-
-        env->CallVoidMethod(gPowerManagerServiceObj, gPowerManagerServiceClassInfo.goToSleep,
-                nanoseconds_to_milliseconds(eventTime));
-        checkAndClearExceptionFromCallback(env, "goToSleep");
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-static void nativeInit(JNIEnv* env, jobject obj) {
-    gPowerManagerServiceObj = env->NewGlobalRef(obj);
-
-    status_t err = hw_get_module(POWER_HARDWARE_MODULE_ID,
-            (hw_module_t const**)&gPowerModule);
-    if (!err) {
-        gPowerModule->init(gPowerModule);
-    } else {
-        ALOGE("Couldn't load %s module (%s)", POWER_HARDWARE_MODULE_ID, strerror(-err));
-    }
-}
-
-static void nativeSetPowerState(JNIEnv* env,
-        jobject serviceObj, jboolean screenOn, jboolean screenBright) {
-    AutoMutex _l(gPowerManagerLock);
-    gScreenOn = screenOn;
-    gScreenBright = screenBright;
-}
-
-static void nativeStartSurfaceFlingerAnimation(JNIEnv* env,
-        jobject obj, jint mode) {
-    sp<ISurfaceComposer> s(ComposerService::getComposerService());
-    s->turnElectronBeamOff(mode);
-}
-
-static void nativeAcquireWakeLock(JNIEnv *env, jobject clazz, jint lock, jstring idObj) {
-    if (idObj == NULL) {
-        jniThrowNullPointerException(env, "id is null");
-        return;
-    }
-
-    const char *id = env->GetStringUTFChars(idObj, NULL);
-
-    acquire_wake_lock(lock, id);
-
-    env->ReleaseStringUTFChars(idObj, id);
-}
-
-static void nativeReleaseWakeLock(JNIEnv *env, jobject clazz, jstring idObj) {
-    if (idObj == NULL) {
-        jniThrowNullPointerException(env, "id is null");
-        return ;
-    }
-
-    const char *id = env->GetStringUTFChars(idObj, NULL);
-
-    release_wake_lock(id);
-
-    env->ReleaseStringUTFChars(idObj, id);
-
-}
-
-static int nativeSetScreenState(JNIEnv *env, jobject clazz, jboolean on) {
-    if (on) {
-        autosuspend_disable();
-        if (gPowerModule) {
-            gPowerModule->setInteractive(gPowerModule, true);
-        }
-    } else {
-        if (gPowerModule) {
-            gPowerModule->setInteractive(gPowerModule, false);
-        }
-        autosuspend_enable();
-    }
-
-    return 0;
-}
-
-static void nativeShutdown(JNIEnv *env, jobject clazz) {
-    android_reboot(ANDROID_RB_POWEROFF, 0, 0);
-}
-
-static void nativeReboot(JNIEnv *env, jobject clazz, jstring reason) {
-    if (reason == NULL) {
-        android_reboot(ANDROID_RB_RESTART, 0, 0);
-    } else {
-        const char *chars = env->GetStringUTFChars(reason, NULL);
-        android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars);
-        env->ReleaseStringUTFChars(reason, chars);  // In case it fails.
-    }
-    jniThrowIOException(env, errno);
-}
-
-
-// ----------------------------------------------------------------------------
-
-static JNINativeMethod gPowerManagerServiceMethods[] = {
-    /* name, signature, funcPtr */
-    { "nativeInit", "()V",
-            (void*) nativeInit },
-    { "nativeSetPowerState", "(ZZ)V",
-            (void*) nativeSetPowerState },
-    { "nativeStartSurfaceFlingerAnimation", "(I)V",
-            (void*) nativeStartSurfaceFlingerAnimation },
-    { "nativeAcquireWakeLock", "(ILjava/lang/String;)V",
-            (void*) nativeAcquireWakeLock },
-    { "nativeReleaseWakeLock", "(Ljava/lang/String;)V",
-            (void*) nativeReleaseWakeLock },
-    { "nativeSetScreenState", "(Z)I",
-            (void*) nativeSetScreenState },
-    { "nativeShutdown", "()V",
-            (void*) nativeShutdown },
-    { "nativeReboot", "(Ljava/lang/String;)V",
-            (void*) nativeReboot },
-};
-
-#define FIND_CLASS(var, className) \
-        var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className);
-
-#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
-        var = env->GetMethodID(clazz, methodName, methodDescriptor); \
-        LOG_FATAL_IF(! var, "Unable to find method " methodName);
-
-#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
-        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
-        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
-
-int register_android_server_PowerManagerService(JNIEnv* env) {
-    int res = jniRegisterNativeMethods(env, "com/android/server/PowerManagerService",
-            gPowerManagerServiceMethods, NELEM(gPowerManagerServiceMethods));
-    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
-
-    // Callbacks
-
-    jclass clazz;
-    FIND_CLASS(clazz, "com/android/server/PowerManagerService");
-
-    GET_METHOD_ID(gPowerManagerServiceClassInfo.goToSleep, clazz,
-            "goToSleep", "(J)V");
-
-    GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivity, clazz,
-            "userActivity", "(JZIZ)V");
-
-    // Initialize
-    for (int i = 0; i < POWER_MANAGER_LAST_EVENT; i++) {
-        gLastEventTime[i] = LLONG_MIN;
-    }
-    gScreenOn = true;
-    gScreenBright = true;
-    gPowerManagerServiceObj = NULL;
-    gPowerModule = NULL;
-    return 0;
-}
-
-} /* namespace android */
diff --git a/services/jni/com_android_server_PowerManagerService.h b/services/jni/com_android_server_PowerManagerService.h
deleted file mode 100644
index cc3b5ef5..0000000
--- a/services/jni/com_android_server_PowerManagerService.h
+++ /dev/null
@@ -1,34 +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_SERVER_POWER_MANAGER_SERVICE_H
-#define _ANDROID_SERVER_POWER_MANAGER_SERVICE_H
-
-#include "JNIHelp.h"
-#include "jni.h"
-
-#include <androidfw/PowerManager.h>
-
-namespace android {
-
-extern bool android_server_PowerManagerService_isScreenOn();
-extern bool android_server_PowerManagerService_isScreenBright();
-extern void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType);
-extern void android_server_PowerManagerService_goToSleep(nsecs_t eventTime);
-
-} // namespace android
-
-#endif // _ANDROID_SERVER_POWER_MANAGER_SERVICE_H
diff --git a/services/jni/com_android_server_input_InputManagerService.cpp b/services/jni/com_android_server_input_InputManagerService.cpp
index 0e1ce51..a97becf 100644
--- a/services/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/jni/com_android_server_input_InputManagerService.cpp
@@ -49,7 +49,7 @@
 #include <ScopedLocalRef.h>
 #include <ScopedUtfChars.h>
 
-#include "com_android_server_PowerManagerService.h"
+#include "com_android_server_power_PowerManagerService.h"
 #include "com_android_server_input_InputApplicationHandle.h"
 #include "com_android_server_input_InputWindowHandle.h"
 
@@ -63,7 +63,7 @@
 static struct {
     jmethodID notifyConfigurationChanged;
     jmethodID notifyInputDevicesChanged;
-    jmethodID notifyLidSwitchChanged;
+    jmethodID notifySwitch;
     jmethodID notifyInputChannelBroken;
     jmethodID notifyANR;
     jmethodID filterInputEvent;
@@ -143,7 +143,7 @@
 
 enum {
     WM_ACTION_PASS_TO_USER = 1,
-    WM_ACTION_POKE_USER_ACTIVITY = 2,
+    WM_ACTION_WAKE_UP = 2,
     WM_ACTION_GO_TO_SLEEP = 4,
 };
 
@@ -164,9 +164,7 @@
 
     void dump(String8& dump);
 
-    void setDisplaySize(int32_t displayId, int32_t width, int32_t height,
-            int32_t externalWidth, int32_t externalHeight);
-    void setDisplayOrientation(int32_t displayId, int32_t orientation, int32_t externalOrientation);
+    void setDisplayViewport(bool external, const DisplayViewport& viewport);
 
     status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
             const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
@@ -189,7 +187,7 @@
 
     /* --- InputDispatcherPolicyInterface implementation --- */
 
-    virtual void notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
+    virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
             uint32_t policyFlags);
     virtual void notifyConfigurationChanged(nsecs_t when);
     virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
@@ -223,10 +221,8 @@
     Mutex mLock;
     struct Locked {
         // Display size information.
-        int32_t displayWidth, displayHeight; // -1 when not initialized
-        int32_t displayOrientation;
-        int32_t displayExternalWidth, displayExternalHeight; // -1 when not initialized
-        int32_t displayExternalOrientation;
+        DisplayViewport internalViewport;
+        DisplayViewport externalViewport;
 
         // System UI visibility.
         int32_t systemUiVisibility;
@@ -274,13 +270,6 @@
 
     {
         AutoMutex _l(mLock);
-        mLocked.displayWidth = -1;
-        mLocked.displayHeight = -1;
-        mLocked.displayOrientation = DISPLAY_ORIENTATION_0;
-        mLocked.displayExternalWidth = -1;
-        mLocked.displayExternalHeight = -1;
-        mLocked.displayExternalOrientation = DISPLAY_ORIENTATION_0;
-
         mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
         mLocked.pointerSpeed = 0;
         mLocked.pointerGesturesEnabled = true;
@@ -316,57 +305,26 @@
     return false;
 }
 
-void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height,
-        int32_t externalWidth, int32_t externalHeight) {
+void NativeInputManager::setDisplayViewport(bool external, const DisplayViewport& viewport) {
     bool changed = false;
-    if (displayId == 0) {
+    {
         AutoMutex _l(mLock);
 
-        if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
+        DisplayViewport& v = external ? mLocked.externalViewport : mLocked.internalViewport;
+        if (v != viewport) {
             changed = true;
-            mLocked.displayWidth = width;
-            mLocked.displayHeight = height;
+            v = viewport;
 
-            sp<PointerController> controller = mLocked.pointerController.promote();
-            if (controller != NULL) {
-                controller->setDisplaySize(width, height);
+            if (!external) {
+                sp<PointerController> controller = mLocked.pointerController.promote();
+                if (controller != NULL) {
+                    controller->setDisplayViewport(
+                            viewport.logicalRight - viewport.logicalLeft,
+                            viewport.logicalBottom - viewport.logicalTop,
+                            viewport.orientation);
+                }
             }
         }
-
-        if (mLocked.displayExternalWidth != externalWidth
-                || mLocked.displayExternalHeight != externalHeight) {
-            changed = true;
-            mLocked.displayExternalWidth = externalWidth;
-            mLocked.displayExternalHeight = externalHeight;
-        }
-    }
-
-    if (changed) {
-        mInputManager->getReader()->requestRefreshConfiguration(
-                InputReaderConfiguration::CHANGE_DISPLAY_INFO);
-    }
-}
-
-void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation,
-        int32_t externalOrientation) {
-    bool changed = false;
-    if (displayId == 0) {
-        AutoMutex _l(mLock);
-
-        if (mLocked.displayOrientation != orientation) {
-            changed = true;
-            mLocked.displayOrientation = orientation;
-
-            sp<PointerController> controller = mLocked.pointerController.promote();
-            if (controller != NULL) {
-                controller->setDisplayOrientation(orientation);
-            }
-        }
-
-        if (mLocked.displayExternalOrientation != externalOrientation) {
-            changed = true;
-            mLocked.displayExternalOrientation = externalOrientation;
-        }
     }
 
     if (changed) {
@@ -448,11 +406,8 @@
 
         outConfig->showTouches = mLocked.showTouches;
 
-        outConfig->setDisplayInfo(0, false /*external*/,
-                mLocked.displayWidth, mLocked.displayHeight, mLocked.displayOrientation);
-        outConfig->setDisplayInfo(0, true /*external*/,
-                mLocked.displayExternalWidth, mLocked.displayExternalHeight,
-                mLocked.displayExternalOrientation);
+        outConfig->setDisplayInfo(false /*external*/, mLocked.internalViewport);
+        outConfig->setDisplayInfo(true /*external*/, mLocked.externalViewport);
     } // release lock
 }
 
@@ -466,8 +421,11 @@
         controller = new PointerController(this, mLooper, mLocked.spriteController);
         mLocked.pointerController = controller;
 
-        controller->setDisplaySize(mLocked.displayWidth, mLocked.displayHeight);
-        controller->setDisplayOrientation(mLocked.displayOrientation);
+        DisplayViewport& v = mLocked.internalViewport;
+        controller->setDisplayViewport(
+                v.logicalRight - v.logicalLeft,
+                v.logicalBottom - v.logicalTop,
+                v.orientation);
 
         JNIEnv* env = jniEnv();
         jobject pointerIconObj = env->CallObjectMethod(mServiceObj,
@@ -569,23 +527,18 @@
     return result;
 }
 
-void NativeInputManager::notifySwitch(nsecs_t when, int32_t switchCode,
-        int32_t switchValue, uint32_t policyFlags) {
+void NativeInputManager::notifySwitch(nsecs_t when,
+        uint32_t switchValues, uint32_t switchMask, uint32_t policyFlags) {
 #if DEBUG_INPUT_DISPATCHER_POLICY
-    ALOGD("notifySwitch - when=%lld, switchCode=%d, switchValue=%d, policyFlags=0x%x",
-            when, switchCode, switchValue, policyFlags);
+    ALOGD("notifySwitch - when=%lld, switchValues=0x%08x, switchMask=0x%08x, policyFlags=0x%x",
+            when, switchValues, switchMask, policyFlags);
 #endif
 
     JNIEnv* env = jniEnv();
 
-    switch (switchCode) {
-    case SW_LID:
-        // When switch value is set indicates lid is closed.
-        env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyLidSwitchChanged,
-                when, switchValue == 0 /*lidOpen*/);
-        checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
-        break;
-    }
+    env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifySwitch,
+            when, switchValues, switchMask);
+    checkAndClearExceptionFromCallback(env, "notifySwitch");
 }
 
 void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
@@ -899,11 +852,11 @@
         android_server_PowerManagerService_goToSleep(when);
     }
 
-    if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
+    if (wmActions & WM_ACTION_WAKE_UP) {
 #if DEBUG_INPUT_DISPATCHER_POLICY
-        ALOGD("handleInterceptActions: Poking user activity.");
+        ALOGD("handleInterceptActions: Waking up.");
 #endif
-        android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT);
+        android_server_PowerManagerService_wakeUp(when);
     }
 
     if (wmActions & WM_ACTION_PASS_TO_USER) {
@@ -1037,22 +990,27 @@
     }
 }
 
-static void nativeSetDisplaySize(JNIEnv* env, jclass clazz, jint ptr,
-        jint displayId, jint width, jint height, jint externalWidth, jint externalHeight) {
+static void nativeSetDisplayViewport(JNIEnv* env, jclass clazz, jint ptr, jboolean external,
+        jint displayId, jint orientation,
+        jint logicalLeft, jint logicalTop, jint logicalRight, jint logicalBottom,
+        jint physicalLeft, jint physicalTop, jint physicalRight, jint physicalBottom,
+        jint deviceWidth, jint deviceHeight) {
     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
-    // XXX we could get this from the SurfaceFlinger directly instead of requiring it
-    // to be passed in like this, not sure which is better but leaving it like this
-    // keeps the window manager in direct control of when display transitions propagate down
-    // to the input dispatcher
-    im->setDisplaySize(displayId, width, height, externalWidth, externalHeight);
-}
-
-static void nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
-        jint ptr, jint displayId, jint orientation, jint externalOrientation) {
-    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
-
-    im->setDisplayOrientation(displayId, orientation, externalOrientation);
+    DisplayViewport v;
+    v.displayId = displayId;
+    v.orientation = orientation;
+    v.logicalLeft = logicalLeft;
+    v.logicalTop = logicalTop;
+    v.logicalRight = logicalRight;
+    v.logicalBottom = logicalBottom;
+    v.physicalLeft = physicalLeft;
+    v.physicalTop = physicalTop;
+    v.physicalRight = physicalRight;
+    v.physicalBottom = physicalBottom;
+    v.deviceWidth = deviceWidth;
+    v.deviceHeight = deviceHeight;
+    im->setDisplayViewport(external, v);
 }
 
 static jint nativeGetScanCodeState(JNIEnv* env, jclass clazz,
@@ -1333,10 +1291,8 @@
             (void*) nativeInit },
     { "nativeStart", "(I)V",
             (void*) nativeStart },
-    { "nativeSetDisplaySize", "(IIIIII)V",
-            (void*) nativeSetDisplaySize },
-    { "nativeSetDisplayOrientation", "(IIII)V",
-            (void*) nativeSetDisplayOrientation },
+    { "nativeSetDisplayViewport", "(IZIIIIIIIIIIII)V",
+            (void*) nativeSetDisplayViewport },
     { "nativeGetScanCodeState", "(IIII)I",
             (void*) nativeGetScanCodeState },
     { "nativeGetKeyCodeState", "(IIII)I",
@@ -1410,8 +1366,8 @@
     GET_METHOD_ID(gServiceClassInfo.notifyInputDevicesChanged, clazz,
             "notifyInputDevicesChanged", "([Landroid/view/InputDevice;)V");
 
-    GET_METHOD_ID(gServiceClassInfo.notifyLidSwitchChanged, clazz,
-            "notifyLidSwitchChanged", "(JZ)V");
+    GET_METHOD_ID(gServiceClassInfo.notifySwitch, clazz,
+            "notifySwitch", "(JII)V");
 
     GET_METHOD_ID(gServiceClassInfo.notifyInputChannelBroken, clazz,
             "notifyInputChannelBroken", "(Lcom/android/server/input/InputWindowHandle;)V");
diff --git a/services/jni/com_android_server_input_InputWindowHandle.cpp b/services/jni/com_android_server_input_InputWindowHandle.cpp
index 01fb781..6692994 100644
--- a/services/jni/com_android_server_input_InputWindowHandle.cpp
+++ b/services/jni/com_android_server_input_InputWindowHandle.cpp
@@ -52,6 +52,7 @@
     jfieldID ownerPid;
     jfieldID ownerUid;
     jfieldID inputFeatures;
+    jfieldID displayId;
 } gInputWindowHandleClassInfo;
 
 static Mutex gHandleMutex;
@@ -151,6 +152,8 @@
             gInputWindowHandleClassInfo.ownerUid);
     mInfo->inputFeatures = env->GetIntField(obj,
             gInputWindowHandleClassInfo.inputFeatures);
+    mInfo->displayId = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.displayId);
 
     env->DeleteLocalRef(obj);
     return true;
@@ -291,6 +294,9 @@
 
     GET_FIELD_ID(gInputWindowHandleClassInfo.inputFeatures, clazz,
             "inputFeatures", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.displayId, clazz,
+            "displayId", "I");
     return 0;
 }
 
diff --git a/services/jni/com_android_server_power_PowerManagerService.cpp b/services/jni/com_android_server_power_PowerManagerService.cpp
new file mode 100644
index 0000000..23c33af
--- /dev/null
+++ b/services/jni/com_android_server_power_PowerManagerService.cpp
@@ -0,0 +1,272 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "PowerManagerService-JNI"
+
+//#define LOG_NDEBUG 0
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+#include <ScopedUtfChars.h>
+
+#include <limits.h>
+
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/Timers.h>
+#include <utils/misc.h>
+#include <utils/String8.h>
+#include <utils/Log.h>
+#include <hardware/power.h>
+#include <hardware_legacy/power.h>
+#include <cutils/android_reboot.h>
+#include <suspend/autosuspend.h>
+
+#include "com_android_server_power_PowerManagerService.h"
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+static struct {
+    jmethodID wakeUpFromNative;
+    jmethodID goToSleepFromNative;
+    jmethodID userActivityFromNative;
+} gPowerManagerServiceClassInfo;
+
+// ----------------------------------------------------------------------------
+
+static jobject gPowerManagerServiceObj;
+static struct power_module* gPowerModule;
+
+static Mutex gPowerManagerLock;
+static bool gScreenOn;
+static bool gScreenBright;
+
+static nsecs_t gLastEventTime[USER_ACTIVITY_EVENT_LAST + 1];
+
+// Throttling interval for user activity calls.
+static const nsecs_t MIN_TIME_BETWEEN_USERACTIVITIES = 500 * 1000000L; // 500ms
+
+// ----------------------------------------------------------------------------
+
+static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
+    if (env->ExceptionCheck()) {
+        ALOGE("An exception was thrown by callback '%s'.", methodName);
+        LOGE_EX(env);
+        env->ExceptionClear();
+        return true;
+    }
+    return false;
+}
+
+bool android_server_PowerManagerService_isScreenOn() {
+    AutoMutex _l(gPowerManagerLock);
+    return gScreenOn;
+}
+
+bool android_server_PowerManagerService_isScreenBright() {
+    AutoMutex _l(gPowerManagerLock);
+    return gScreenBright;
+}
+
+void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {
+    // Tell the power HAL when user activity occurs.
+    if (gPowerModule && gPowerModule->powerHint) {
+        gPowerModule->powerHint(gPowerModule, POWER_HINT_INTERACTION, NULL);
+    }
+
+    if (gPowerManagerServiceObj) {
+        // Throttle calls into user activity by event type.
+        // We're a little conservative about argument checking here in case the caller
+        // passes in bad data which could corrupt system state.
+        if (eventType >= 0 && eventType <= USER_ACTIVITY_EVENT_LAST) {
+            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+            if (eventTime > now) {
+                eventTime = now;
+            }
+
+            if (gLastEventTime[eventType] + MIN_TIME_BETWEEN_USERACTIVITIES > eventTime) {
+                return;
+            }
+            gLastEventTime[eventType] = eventTime;
+        }
+
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+        env->CallVoidMethod(gPowerManagerServiceObj,
+                gPowerManagerServiceClassInfo.userActivityFromNative,
+                nanoseconds_to_milliseconds(eventTime), eventType, 0);
+        checkAndClearExceptionFromCallback(env, "userActivityFromNative");
+    }
+}
+
+void android_server_PowerManagerService_wakeUp(nsecs_t eventTime) {
+    if (gPowerManagerServiceObj) {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+        env->CallVoidMethod(gPowerManagerServiceObj,
+                gPowerManagerServiceClassInfo.wakeUpFromNative,
+                nanoseconds_to_milliseconds(eventTime));
+        checkAndClearExceptionFromCallback(env, "wakeUpFromNative");
+    }
+}
+
+void android_server_PowerManagerService_goToSleep(nsecs_t eventTime) {
+    if (gPowerManagerServiceObj) {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+        env->CallVoidMethod(gPowerManagerServiceObj,
+                gPowerManagerServiceClassInfo.goToSleepFromNative,
+                nanoseconds_to_milliseconds(eventTime), 0);
+        checkAndClearExceptionFromCallback(env, "goToSleepFromNative");
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+static void nativeInit(JNIEnv* env, jobject obj) {
+    gPowerManagerServiceObj = env->NewGlobalRef(obj);
+
+    status_t err = hw_get_module(POWER_HARDWARE_MODULE_ID,
+            (hw_module_t const**)&gPowerModule);
+    if (!err) {
+        gPowerModule->init(gPowerModule);
+    } else {
+        ALOGE("Couldn't load %s module (%s)", POWER_HARDWARE_MODULE_ID, strerror(-err));
+    }
+}
+
+static void nativeSetPowerState(JNIEnv* env,
+        jclass clazz, jboolean screenOn, jboolean screenBright) {
+    AutoMutex _l(gPowerManagerLock);
+    gScreenOn = screenOn;
+    gScreenBright = screenBright;
+}
+
+static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
+    ScopedUtfChars name(env, nameStr);
+    acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
+}
+
+static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
+    ScopedUtfChars name(env, nameStr);
+    release_wake_lock(name.c_str());
+}
+
+static void nativeSetInteractive(JNIEnv *env, jclass clazz, jboolean enable) {
+    if (gPowerModule) {
+        if (enable) {
+            ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(true) while turning screen on");
+            gPowerModule->setInteractive(gPowerModule, true);
+        } else {
+            ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(false) while turning screen off");
+            gPowerModule->setInteractive(gPowerModule, false);
+        }
+    }
+}
+
+static void nativeSetAutoSuspend(JNIEnv *env, jclass clazz, jboolean enable) {
+    if (enable) {
+        ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_enable() while turning screen off");
+        autosuspend_enable();
+    } else {
+        ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_disable() while turning screen on");
+        autosuspend_disable();
+    }
+}
+
+static void nativeShutdown(JNIEnv *env, jclass clazz) {
+    android_reboot(ANDROID_RB_POWEROFF, 0, 0);
+}
+
+static void nativeReboot(JNIEnv *env, jclass clazz, jstring reason) {
+    if (reason == NULL) {
+        android_reboot(ANDROID_RB_RESTART, 0, 0);
+    } else {
+        const char *chars = env->GetStringUTFChars(reason, NULL);
+        android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars);
+        env->ReleaseStringUTFChars(reason, chars);  // In case it fails.
+    }
+    jniThrowIOException(env, errno);
+}
+
+
+// ----------------------------------------------------------------------------
+
+static JNINativeMethod gPowerManagerServiceMethods[] = {
+    /* name, signature, funcPtr */
+    { "nativeInit", "()V",
+            (void*) nativeInit },
+    { "nativeSetPowerState", "(ZZ)V",
+            (void*) nativeSetPowerState },
+    { "nativeAcquireSuspendBlocker", "(Ljava/lang/String;)V",
+            (void*) nativeAcquireSuspendBlocker },
+    { "nativeReleaseSuspendBlocker", "(Ljava/lang/String;)V",
+            (void*) nativeReleaseSuspendBlocker },
+    { "nativeSetInteractive", "(Z)V",
+            (void*) nativeSetInteractive },
+    { "nativeSetAutoSuspend", "(Z)V",
+            (void*) nativeSetAutoSuspend },
+    { "nativeShutdown", "()V",
+            (void*) nativeShutdown },
+    { "nativeReboot", "(Ljava/lang/String;)V",
+            (void*) nativeReboot },
+};
+
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className);
+
+#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
+        var = env->GetMethodID(clazz, methodName, methodDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find method " methodName);
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_PowerManagerService(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, "com/android/server/power/PowerManagerService",
+            gPowerManagerServiceMethods, NELEM(gPowerManagerServiceMethods));
+    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    // Callbacks
+
+    jclass clazz;
+    FIND_CLASS(clazz, "com/android/server/power/PowerManagerService");
+
+    GET_METHOD_ID(gPowerManagerServiceClassInfo.wakeUpFromNative, clazz,
+            "wakeUpFromNative", "(J)V");
+
+    GET_METHOD_ID(gPowerManagerServiceClassInfo.goToSleepFromNative, clazz,
+            "goToSleepFromNative", "(JI)V");
+
+    GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivityFromNative, clazz,
+            "userActivityFromNative", "(JII)V");
+
+    // Initialize
+    for (int i = 0; i <= USER_ACTIVITY_EVENT_LAST; i++) {
+        gLastEventTime[i] = LLONG_MIN;
+    }
+    gScreenOn = true;
+    gScreenBright = true;
+    gPowerManagerServiceObj = NULL;
+    gPowerModule = NULL;
+    return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_power_PowerManagerService.h b/services/jni/com_android_server_power_PowerManagerService.h
new file mode 100644
index 0000000..0808b80
--- /dev/null
+++ b/services/jni/com_android_server_power_PowerManagerService.h
@@ -0,0 +1,35 @@
+/*
+ * 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_SERVER_POWER_MANAGER_SERVICE_H
+#define _ANDROID_SERVER_POWER_MANAGER_SERVICE_H
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+#include <androidfw/PowerManager.h>
+
+namespace android {
+
+extern bool android_server_PowerManagerService_isScreenOn();
+extern bool android_server_PowerManagerService_isScreenBright();
+extern void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType);
+extern void android_server_PowerManagerService_wakeUp(nsecs_t eventTime);
+extern void android_server_PowerManagerService_goToSleep(nsecs_t eventTime);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_POWER_MANAGER_SERVICE_H
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
deleted file mode 100644
index 6a302c0..0000000
--- a/services/sensorservice/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	CorrectedGyroSensor.cpp \
-    Fusion.cpp \
-    GravitySensor.cpp \
-    LinearAccelerationSensor.cpp \
-    OrientationSensor.cpp \
-    RotationVectorSensor.cpp \
-    SensorDevice.cpp \
-    SensorFusion.cpp \
-    SensorInterface.cpp \
-    SensorService.cpp \
-
-
-LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libhardware \
-	libutils \
-	libbinder \
-	libui \
-	libgui
-
-
-
-LOCAL_MODULE:= libsensorservice
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/services/sensorservice/CorrectedGyroSensor.cpp b/services/sensorservice/CorrectedGyroSensor.cpp
deleted file mode 100644
index 1857443..0000000
--- a/services/sensorservice/CorrectedGyroSensor.cpp
+++ /dev/null
@@ -1,86 +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.
- */
-
-#include <stdint.h>
-#include <math.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-
-#include <hardware/sensors.h>
-
-#include "CorrectedGyroSensor.h"
-#include "SensorDevice.h"
-#include "SensorFusion.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-CorrectedGyroSensor::CorrectedGyroSensor(sensor_t const* list, size_t count)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
-    for (size_t i=0 ; i<count ; i++) {
-        if (list[i].type == SENSOR_TYPE_GYROSCOPE) {
-            mGyro = Sensor(list + i);
-            break;
-        }
-    }
-}
-
-bool CorrectedGyroSensor::process(sensors_event_t* outEvent,
-        const sensors_event_t& event)
-{
-    if (event.type == SENSOR_TYPE_GYROSCOPE) {
-        const vec3_t bias(mSensorFusion.getGyroBias());
-        *outEvent = event;
-        outEvent->data[0] -= bias.x;
-        outEvent->data[1] -= bias.y;
-        outEvent->data[2] -= bias.z;
-        outEvent->sensor = '_cgy';
-        return true;
-    }
-    return false;
-}
-
-status_t CorrectedGyroSensor::activate(void* ident, bool enabled) {
-    mSensorDevice.activate(this, mGyro.getHandle(), enabled);
-    return mSensorFusion.activate(this, enabled);
-}
-
-status_t CorrectedGyroSensor::setDelay(void* ident, int handle, int64_t ns) {
-    mSensorDevice.setDelay(this, mGyro.getHandle(), ns);
-    return mSensorFusion.setDelay(this, ns);
-}
-
-Sensor CorrectedGyroSensor::getSensor() const {
-    sensor_t hwSensor;
-    hwSensor.name       = "Corrected Gyroscope Sensor";
-    hwSensor.vendor     = "Google Inc.";
-    hwSensor.version    = 1;
-    hwSensor.handle     = '_cgy';
-    hwSensor.type       = SENSOR_TYPE_GYROSCOPE;
-    hwSensor.maxRange   = mGyro.getMaxValue();
-    hwSensor.resolution = mGyro.getResolution();
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mGyro.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/services/sensorservice/CorrectedGyroSensor.h b/services/sensorservice/CorrectedGyroSensor.h
deleted file mode 100644
index 3c49c08..0000000
--- a/services/sensorservice/CorrectedGyroSensor.h
+++ /dev/null
@@ -1,52 +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.
- */
-
-#ifndef ANDROID_CORRECTED_GYRO_SENSOR_H
-#define ANDROID_CORRECTED_GYRO_SENSOR_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/Sensor.h>
-
-#include "SensorInterface.h"
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class SensorDevice;
-class SensorFusion;
-
-class CorrectedGyroSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
-    Sensor mGyro;
-
-public:
-    CorrectedGyroSensor(sensor_t const* list, size_t count);
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_CORRECTED_GYRO_SENSOR_H
diff --git a/services/sensorservice/Fusion.cpp b/services/sensorservice/Fusion.cpp
deleted file mode 100644
index b724ce2..0000000
--- a/services/sensorservice/Fusion.cpp
+++ /dev/null
@@ -1,438 +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.
- */
-
-#include <stdio.h>
-
-#include <utils/Log.h>
-
-#include "Fusion.h"
-
-namespace android {
-
-// -----------------------------------------------------------------------
-
-/*
- * gyroVAR gives the measured variance of the gyro's output per
- * Hz (or variance at 1 Hz). This is an "intrinsic" parameter of the gyro,
- * which is independent of the sampling frequency.
- *
- * The variance of gyro's output at a given sampling period can be
- * calculated as:
- *      variance(T) = gyroVAR / T
- *
- * The variance of the INTEGRATED OUTPUT at a given sampling period can be
- * calculated as:
- *       variance_integrate_output(T) = gyroVAR * T
- *
- */
-static const float gyroVAR = 1e-7;      // (rad/s)^2 / Hz
-static const float biasVAR = 1e-8;      // (rad/s)^2 / s (guessed)
-
-/*
- * Standard deviations of accelerometer and magnetometer
- */
-static const float accSTDEV  = 0.05f;   // m/s^2 (measured 0.08 / CDD 0.05)
-static const float magSTDEV  = 0.5f;    // uT    (measured 0.7  / CDD 0.5)
-
-static const float SYMMETRY_TOLERANCE = 1e-10f;
-
-/*
- * Accelerometer updates will not be performed near free fall to avoid
- * ill-conditioning and div by zeros.
- * Threshhold: 10% of g, in m/s^2
- */
-static const float FREE_FALL_THRESHOLD = 0.981f;
-static const float FREE_FALL_THRESHOLD_SQ =
-        FREE_FALL_THRESHOLD*FREE_FALL_THRESHOLD;
-
-/*
- * The geomagnetic-field should be between 30uT and 60uT.
- * Fields strengths greater than this likely indicate a local magnetic
- * disturbance which we do not want to update into the fused frame.
- */
-static const float MAX_VALID_MAGNETIC_FIELD = 100; // uT
-static const float MAX_VALID_MAGNETIC_FIELD_SQ =
-        MAX_VALID_MAGNETIC_FIELD*MAX_VALID_MAGNETIC_FIELD;
-
-/*
- * Values of the field smaller than this should be ignored in fusion to avoid
- * ill-conditioning. This state can happen with anomalous local magnetic
- * disturbances canceling the Earth field.
- */
-static const float MIN_VALID_MAGNETIC_FIELD = 10; // uT
-static const float MIN_VALID_MAGNETIC_FIELD_SQ =
-        MIN_VALID_MAGNETIC_FIELD*MIN_VALID_MAGNETIC_FIELD;
-
-/*
- * If the cross product of two vectors has magnitude squared less than this,
- * we reject it as invalid due to alignment of the vectors.
- * This threshold is used to check for the case where the magnetic field sample
- * is parallel to the gravity field, which can happen in certain places due
- * to magnetic field disturbances.
- */
-static const float MIN_VALID_CROSS_PRODUCT_MAG = 1.0e-3;
-static const float MIN_VALID_CROSS_PRODUCT_MAG_SQ =
-    MIN_VALID_CROSS_PRODUCT_MAG*MIN_VALID_CROSS_PRODUCT_MAG;
-
-// -----------------------------------------------------------------------
-
-template <typename TYPE, size_t C, size_t R>
-static mat<TYPE, R, R> scaleCovariance(
-        const mat<TYPE, C, R>& A,
-        const mat<TYPE, C, C>& P) {
-    // A*P*transpose(A);
-    mat<TYPE, R, R> APAt;
-    for (size_t r=0 ; r<R ; r++) {
-        for (size_t j=r ; j<R ; j++) {
-            double apat(0);
-            for (size_t c=0 ; c<C ; c++) {
-                double v(A[c][r]*P[c][c]*0.5);
-                for (size_t k=c+1 ; k<C ; k++)
-                    v += A[k][r] * P[c][k];
-                apat += 2 * v * A[c][j];
-            }
-            APAt[j][r] = apat;
-            APAt[r][j] = apat;
-        }
-    }
-    return APAt;
-}
-
-template <typename TYPE, typename OTHER_TYPE>
-static mat<TYPE, 3, 3> crossMatrix(const vec<TYPE, 3>& p, OTHER_TYPE diag) {
-    mat<TYPE, 3, 3> r;
-    r[0][0] = diag;
-    r[1][1] = diag;
-    r[2][2] = diag;
-    r[0][1] = p.z;
-    r[1][0] =-p.z;
-    r[0][2] =-p.y;
-    r[2][0] = p.y;
-    r[1][2] = p.x;
-    r[2][1] =-p.x;
-    return r;
-}
-
-
-template<typename TYPE, size_t SIZE>
-class Covariance {
-    mat<TYPE, SIZE, SIZE> mSumXX;
-    vec<TYPE, SIZE> mSumX;
-    size_t mN;
-public:
-    Covariance() : mSumXX(0.0f), mSumX(0.0f), mN(0) { }
-    void update(const vec<TYPE, SIZE>& x) {
-        mSumXX += x*transpose(x);
-        mSumX  += x;
-        mN++;
-    }
-    mat<TYPE, SIZE, SIZE> operator()() const {
-        const float N = 1.0f / mN;
-        return mSumXX*N - (mSumX*transpose(mSumX))*(N*N);
-    }
-    void reset() {
-        mN = 0;
-        mSumXX = 0;
-        mSumX = 0;
-    }
-    size_t getCount() const {
-        return mN;
-    }
-};
-
-// -----------------------------------------------------------------------
-
-Fusion::Fusion() {
-    Phi[0][1] = 0;
-    Phi[1][1] = 1;
-
-    Ba.x = 0;
-    Ba.y = 0;
-    Ba.z = 1;
-
-    Bm.x = 0;
-    Bm.y = 1;
-    Bm.z = 0;
-
-    x0 = 0;
-    x1 = 0;
-
-    init();
-}
-
-void Fusion::init() {
-    mInitState = 0;
-
-    mGyroRate = 0;
-
-    mCount[0] = 0;
-    mCount[1] = 0;
-    mCount[2] = 0;
-
-    mData = 0;
-}
-
-void Fusion::initFusion(const vec4_t& q, float dT)
-{
-    // initial estimate: E{ x(t0) }
-    x0 = q;
-    x1 = 0;
-
-    // process noise covariance matrix: G.Q.Gt, with
-    //
-    //  G = | -1 0 |        Q = | q00 q10 |
-    //      |  0 1 |            | q01 q11 |
-    //
-    // q00 = sv^2.dt + 1/3.su^2.dt^3
-    // q10 = q01 = 1/2.su^2.dt^2
-    // q11 = su^2.dt
-    //
-
-    // variance of integrated output at 1/dT Hz
-    // (random drift)
-    const float q00 = gyroVAR * dT;
-
-    // variance of drift rate ramp
-    const float q11 = biasVAR * dT;
-
-    const float u   = q11 / dT;
-    const float q10 = 0.5f*u*dT*dT;
-    const float q01 = q10;
-
-    GQGt[0][0] =  q00;      // rad^2
-    GQGt[1][0] = -q10;
-    GQGt[0][1] = -q01;
-    GQGt[1][1] =  q11;      // (rad/s)^2
-
-    // initial covariance: Var{ x(t0) }
-    // TODO: initialize P correctly
-    P = 0;
-}
-
-bool Fusion::hasEstimate() const {
-    return (mInitState == (MAG|ACC|GYRO));
-}
-
-bool Fusion::checkInitComplete(int what, const vec3_t& d, float dT) {
-    if (hasEstimate())
-        return true;
-
-    if (what == ACC) {
-        mData[0] += d * (1/length(d));
-        mCount[0]++;
-        mInitState |= ACC;
-    } else if (what == MAG) {
-        mData[1] += d * (1/length(d));
-        mCount[1]++;
-        mInitState |= MAG;
-    } else if (what == GYRO) {
-        mGyroRate = dT;
-        mData[2] += d*dT;
-        mCount[2]++;
-        if (mCount[2] == 64) {
-            // 64 samples is good enough to estimate the gyro drift and
-            // doesn't take too much time.
-            mInitState |= GYRO;
-        }
-    }
-
-    if (mInitState == (MAG|ACC|GYRO)) {
-        // Average all the values we collected so far
-        mData[0] *= 1.0f/mCount[0];
-        mData[1] *= 1.0f/mCount[1];
-        mData[2] *= 1.0f/mCount[2];
-
-        // calculate the MRPs from the data collection, this gives us
-        // a rough estimate of our initial state
-        mat33_t R;
-        vec3_t up(mData[0]);
-        vec3_t east(cross_product(mData[1], up));
-        east *= 1/length(east);
-        vec3_t north(cross_product(up, east));
-        R << east << north << up;
-        const vec4_t q = matrixToQuat(R);
-
-        initFusion(q, mGyroRate);
-    }
-
-    return false;
-}
-
-void Fusion::handleGyro(const vec3_t& w, float dT) {
-    if (!checkInitComplete(GYRO, w, dT))
-        return;
-
-    predict(w, dT);
-}
-
-status_t Fusion::handleAcc(const vec3_t& a) {
-    // ignore acceleration data if we're close to free-fall
-    if (length_squared(a) < FREE_FALL_THRESHOLD_SQ) {
-        return BAD_VALUE;
-    }
-
-    if (!checkInitComplete(ACC, a))
-        return BAD_VALUE;
-
-    const float l = 1/length(a);
-    update(a*l, Ba, accSTDEV*l);
-    return NO_ERROR;
-}
-
-status_t Fusion::handleMag(const vec3_t& m) {
-    // the geomagnetic-field should be between 30uT and 60uT
-    // reject if too large to avoid spurious magnetic sources
-    const float magFieldSq = length_squared(m);
-    if (magFieldSq > MAX_VALID_MAGNETIC_FIELD_SQ) {
-        return BAD_VALUE;
-    } else if (magFieldSq < MIN_VALID_MAGNETIC_FIELD_SQ) {
-        // Also reject if too small since we will get ill-defined (zero mag)
-        // cross-products below
-        return BAD_VALUE;
-    }
-
-    if (!checkInitComplete(MAG, m))
-        return BAD_VALUE;
-
-    // Orthogonalize the magnetic field to the gravity field, mapping it into
-    // tangent to Earth.
-    const vec3_t up( getRotationMatrix() * Ba );
-    const vec3_t east( cross_product(m, up) );
-
-    // If the m and up vectors align, the cross product magnitude will
-    // approach 0.
-    // Reject this case as well to avoid div by zero problems and
-    // ill-conditioning below.
-    if (length_squared(east) < MIN_VALID_CROSS_PRODUCT_MAG_SQ) {
-        return BAD_VALUE;
-    }
-
-    // If we have created an orthogonal magnetic field successfully,
-    // then pass it in as the update.
-    vec3_t north( cross_product(up, east) );
-
-    const float l = 1 / length(north);
-    north *= l;
-
-    update(north, Bm, magSTDEV*l);
-    return NO_ERROR;
-}
-
-void Fusion::checkState() {
-    // P needs to stay positive semidefinite or the fusion diverges. When we
-    // detect divergence, we reset the fusion.
-    // TODO(braun): Instead, find the reason for the divergence and fix it.
-
-    if (!isPositiveSemidefinite(P[0][0], SYMMETRY_TOLERANCE) ||
-        !isPositiveSemidefinite(P[1][1], SYMMETRY_TOLERANCE)) {
-        ALOGW("Sensor fusion diverged; resetting state.");
-        P = 0;
-    }
-}
-
-vec4_t Fusion::getAttitude() const {
-    return x0;
-}
-
-vec3_t Fusion::getBias() const {
-    return x1;
-}
-
-mat33_t Fusion::getRotationMatrix() const {
-    return quatToMatrix(x0);
-}
-
-mat34_t Fusion::getF(const vec4_t& q) {
-    mat34_t F;
-    F[0].x = q.w;   F[1].x =-q.z;   F[2].x = q.y;
-    F[0].y = q.z;   F[1].y = q.w;   F[2].y =-q.x;
-    F[0].z =-q.y;   F[1].z = q.x;   F[2].z = q.w;
-    F[0].w =-q.x;   F[1].w =-q.y;   F[2].w =-q.z;
-    return F;
-}
-
-void Fusion::predict(const vec3_t& w, float dT) {
-    const vec4_t q  = x0;
-    const vec3_t b  = x1;
-    const vec3_t we = w - b;
-    const vec4_t dq = getF(q)*((0.5f*dT)*we);
-    x0 = normalize_quat(q + dq);
-
-    // P(k+1) = F*P(k)*Ft + G*Q*Gt
-
-    //  Phi = | Phi00 Phi10 |
-    //        |   0     1   |
-    const mat33_t I33(1);
-    const mat33_t I33dT(dT);
-    const mat33_t wx(crossMatrix(we, 0));
-    const mat33_t wx2(wx*wx);
-    const float lwedT = length(we)*dT;
-    const float ilwe = 1/length(we);
-    const float k0 = (1-cosf(lwedT))*(ilwe*ilwe);
-    const float k1 = sinf(lwedT);
-
-    Phi[0][0] = I33 - wx*(k1*ilwe) + wx2*k0;
-    Phi[1][0] = wx*k0 - I33dT - wx2*(ilwe*ilwe*ilwe)*(lwedT-k1);
-
-    P = Phi*P*transpose(Phi) + GQGt;
-
-    checkState();
-}
-
-void Fusion::update(const vec3_t& z, const vec3_t& Bi, float sigma) {
-    vec4_t q(x0);
-    // measured vector in body space: h(p) = A(p)*Bi
-    const mat33_t A(quatToMatrix(q));
-    const vec3_t Bb(A*Bi);
-
-    // Sensitivity matrix H = dh(p)/dp
-    // H = [ L 0 ]
-    const mat33_t L(crossMatrix(Bb, 0));
-
-    // gain...
-    // K = P*Ht / [H*P*Ht + R]
-    vec<mat33_t, 2> K;
-    const mat33_t R(sigma*sigma);
-    const mat33_t S(scaleCovariance(L, P[0][0]) + R);
-    const mat33_t Si(invert(S));
-    const mat33_t LtSi(transpose(L)*Si);
-    K[0] = P[0][0] * LtSi;
-    K[1] = transpose(P[1][0])*LtSi;
-
-    // update...
-    // P -= K*H*P;
-    const mat33_t K0L(K[0] * L);
-    const mat33_t K1L(K[1] * L);
-    P[0][0] -= K0L*P[0][0];
-    P[1][1] -= K1L*P[1][0];
-    P[1][0] -= K0L*P[1][0];
-    P[0][1] = transpose(P[1][0]);
-
-    const vec3_t e(z - Bb);
-    const vec3_t dq(K[0]*e);
-    const vec3_t db(K[1]*e);
-
-    q += getF(q)*(0.5f*dq);
-    x0 = normalize_quat(q);
-    x1 += db;
-
-    checkState();
-}
-
-// -----------------------------------------------------------------------
-
-}; // namespace android
-
diff --git a/services/sensorservice/Fusion.h b/services/sensorservice/Fusion.h
deleted file mode 100644
index 7062999..0000000
--- a/services/sensorservice/Fusion.h
+++ /dev/null
@@ -1,85 +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.
- */
-
-#ifndef ANDROID_FUSION_H
-#define ANDROID_FUSION_H
-
-#include <utils/Errors.h>
-
-#include "quat.h"
-#include "mat.h"
-#include "vec.h"
-
-namespace android {
-
-typedef mat<float, 3, 4> mat34_t;
-
-class Fusion {
-    /*
-     * the state vector is made of two sub-vector containing respectively:
-     * - modified Rodrigues parameters
-     * - the estimated gyro bias
-     */
-    quat_t  x0;
-    vec3_t  x1;
-
-    /*
-     * the predicated covariance matrix is made of 4 3x3 sub-matrices and it is
-     * semi-definite positive.
-     *
-     * P = | P00  P10 | = | P00  P10 |
-     *     | P01  P11 |   | P10t P11 |
-     *
-     * Since P01 = transpose(P10), the code below never calculates or
-     * stores P01.
-     */
-    mat<mat33_t, 2, 2> P;
-
-    /*
-     * the process noise covariance matrix
-     */
-    mat<mat33_t, 2, 2> GQGt;
-
-public:
-    Fusion();
-    void init();
-    void handleGyro(const vec3_t& w, float dT);
-    status_t handleAcc(const vec3_t& a);
-    status_t handleMag(const vec3_t& m);
-    vec4_t getAttitude() const;
-    vec3_t getBias() const;
-    mat33_t getRotationMatrix() const;
-    bool hasEstimate() const;
-
-private:
-    mat<mat33_t, 2, 2> Phi;
-    vec3_t Ba, Bm;
-    uint32_t mInitState;
-    float mGyroRate;
-    vec<vec3_t, 3> mData;
-    size_t mCount[3];
-    enum { ACC=0x1, MAG=0x2, GYRO=0x4 };
-    bool checkInitComplete(int, const vec3_t& w, float d = 0);
-    void initFusion(const vec4_t& q0, float dT);
-    void checkState();
-    void predict(const vec3_t& w, float dT);
-    void update(const vec3_t& z, const vec3_t& Bi, float sigma);
-    static mat34_t getF(const vec4_t& p);
-};
-
-}; // namespace android
-
-#endif // ANDROID_FUSION_H
diff --git a/services/sensorservice/GravitySensor.cpp b/services/sensorservice/GravitySensor.cpp
deleted file mode 100644
index c57715f..0000000
--- a/services/sensorservice/GravitySensor.cpp
+++ /dev/null
@@ -1,94 +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.
- */
-
-#include <stdint.h>
-#include <math.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-
-#include <hardware/sensors.h>
-
-#include "GravitySensor.h"
-#include "SensorDevice.h"
-#include "SensorFusion.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-GravitySensor::GravitySensor(sensor_t const* list, size_t count)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
-    for (size_t i=0 ; i<count ; i++) {
-        if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
-            mAccelerometer = Sensor(list + i);
-            break;
-        }
-    }
-}
-
-bool GravitySensor::process(sensors_event_t* outEvent,
-        const sensors_event_t& event)
-{
-    const static double NS2S = 1.0 / 1000000000.0;
-    if (event.type == SENSOR_TYPE_ACCELEROMETER) {
-        vec3_t g;
-        if (!mSensorFusion.hasEstimate())
-            return false;
-        const mat33_t R(mSensorFusion.getRotationMatrix());
-        // FIXME: we need to estimate the length of gravity because
-        // the accelerometer may have a small scaling error. This
-        // translates to an offset in the linear-acceleration sensor.
-        g = R[2] * GRAVITY_EARTH;
-
-        *outEvent = event;
-        outEvent->data[0] = g.x;
-        outEvent->data[1] = g.y;
-        outEvent->data[2] = g.z;
-        outEvent->sensor = '_grv';
-        outEvent->type = SENSOR_TYPE_GRAVITY;
-        return true;
-    }
-    return false;
-}
-
-status_t GravitySensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(this, enabled);
-}
-
-status_t GravitySensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mSensorFusion.setDelay(this, ns);
-}
-
-Sensor GravitySensor::getSensor() const {
-    sensor_t hwSensor;
-    hwSensor.name       = "Gravity Sensor";
-    hwSensor.vendor     = "Google Inc.";
-    hwSensor.version    = 3;
-    hwSensor.handle     = '_grv';
-    hwSensor.type       = SENSOR_TYPE_GRAVITY;
-    hwSensor.maxRange   = GRAVITY_EARTH * 2;
-    hwSensor.resolution = mAccelerometer.getResolution();
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/services/sensorservice/GravitySensor.h b/services/sensorservice/GravitySensor.h
deleted file mode 100644
index ac177c4..0000000
--- a/services/sensorservice/GravitySensor.h
+++ /dev/null
@@ -1,52 +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_GRAVITY_SENSOR_H
-#define ANDROID_GRAVITY_SENSOR_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/Sensor.h>
-
-#include "SensorInterface.h"
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class SensorDevice;
-class SensorFusion;
-
-class GravitySensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
-    Sensor mAccelerometer;
-
-public:
-    GravitySensor(sensor_t const* list, size_t count);
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GRAVITY_SENSOR_H
diff --git a/services/sensorservice/LinearAccelerationSensor.cpp b/services/sensorservice/LinearAccelerationSensor.cpp
deleted file mode 100644
index f0054f2..0000000
--- a/services/sensorservice/LinearAccelerationSensor.cpp
+++ /dev/null
@@ -1,79 +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.
- */
-
-#include <stdint.h>
-#include <math.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-
-#include <hardware/sensors.h>
-
-#include "LinearAccelerationSensor.h"
-#include "SensorDevice.h"
-#include "SensorFusion.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-LinearAccelerationSensor::LinearAccelerationSensor(sensor_t const* list, size_t count)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mGravitySensor(list, count)
-{
-}
-
-bool LinearAccelerationSensor::process(sensors_event_t* outEvent,
-        const sensors_event_t& event)
-{
-    bool result = mGravitySensor.process(outEvent, event);
-    if (result && event.type == SENSOR_TYPE_ACCELEROMETER) {
-        outEvent->data[0] = event.acceleration.x - outEvent->data[0];
-        outEvent->data[1] = event.acceleration.y - outEvent->data[1];
-        outEvent->data[2] = event.acceleration.z - outEvent->data[2];
-        outEvent->sensor = '_lin';
-        outEvent->type = SENSOR_TYPE_LINEAR_ACCELERATION;
-        return true;
-    }
-    return false;
-}
-
-status_t LinearAccelerationSensor::activate(void* ident, bool enabled) {
-    return mGravitySensor.activate(this, enabled);
-}
-
-status_t LinearAccelerationSensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mGravitySensor.setDelay(this, handle, ns);
-}
-
-Sensor LinearAccelerationSensor::getSensor() const {
-    Sensor gsensor(mGravitySensor.getSensor());
-    sensor_t hwSensor;
-    hwSensor.name       = "Linear Acceleration Sensor";
-    hwSensor.vendor     = "Google Inc.";
-    hwSensor.version    = gsensor.getVersion();
-    hwSensor.handle     = '_lin';
-    hwSensor.type       = SENSOR_TYPE_LINEAR_ACCELERATION;
-    hwSensor.maxRange   = gsensor.getMaxValue();
-    hwSensor.resolution = gsensor.getResolution();
-    hwSensor.power      = gsensor.getPowerUsage();
-    hwSensor.minDelay   = gsensor.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/services/sensorservice/LinearAccelerationSensor.h b/services/sensorservice/LinearAccelerationSensor.h
deleted file mode 100644
index 5deb24f..0000000
--- a/services/sensorservice/LinearAccelerationSensor.h
+++ /dev/null
@@ -1,52 +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_LINEAR_ACCELERATION_SENSOR_H
-#define ANDROID_LINEAR_ACCELERATION_SENSOR_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/Sensor.h>
-
-#include "SensorInterface.h"
-#include "GravitySensor.h"
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class SensorDevice;
-class SensorFusion;
-
-class LinearAccelerationSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    GravitySensor mGravitySensor;
-
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-public:
-    LinearAccelerationSensor(sensor_t const* list, size_t count);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_LINEAR_ACCELERATION_SENSOR_H
diff --git a/services/sensorservice/OrientationSensor.cpp b/services/sensorservice/OrientationSensor.cpp
deleted file mode 100644
index 037adaa..0000000
--- a/services/sensorservice/OrientationSensor.cpp
+++ /dev/null
@@ -1,90 +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.
- */
-
-#include <stdint.h>
-#include <math.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-
-#include <hardware/sensors.h>
-
-#include "OrientationSensor.h"
-#include "SensorDevice.h"
-#include "SensorFusion.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-OrientationSensor::OrientationSensor()
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
-}
-
-bool OrientationSensor::process(sensors_event_t* outEvent,
-        const sensors_event_t& event)
-{
-    if (event.type == SENSOR_TYPE_ACCELEROMETER) {
-        if (mSensorFusion.hasEstimate()) {
-            vec3_t g;
-            const float rad2deg = 180 / M_PI;
-            const mat33_t R(mSensorFusion.getRotationMatrix());
-            g[0] = atan2f(-R[1][0], R[0][0])    * rad2deg;
-            g[1] = atan2f(-R[2][1], R[2][2])    * rad2deg;
-            g[2] = asinf ( R[2][0])             * rad2deg;
-            if (g[0] < 0)
-                g[0] += 360;
-
-            *outEvent = event;
-            outEvent->orientation.azimuth = g.x;
-            outEvent->orientation.pitch   = g.y;
-            outEvent->orientation.roll    = g.z;
-            outEvent->orientation.status  = SENSOR_STATUS_ACCURACY_HIGH;
-            outEvent->sensor = '_ypr';
-            outEvent->type = SENSOR_TYPE_ORIENTATION;
-            return true;
-        }
-    }
-    return false;
-}
-
-status_t OrientationSensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(this, enabled);
-}
-
-status_t OrientationSensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mSensorFusion.setDelay(this, ns);
-}
-
-Sensor OrientationSensor::getSensor() const {
-    sensor_t hwSensor;
-    hwSensor.name       = "Orientation Sensor";
-    hwSensor.vendor     = "Google Inc.";
-    hwSensor.version    = 1;
-    hwSensor.handle     = '_ypr';
-    hwSensor.type       = SENSOR_TYPE_ORIENTATION;
-    hwSensor.maxRange   = 360.0f;
-    hwSensor.resolution = 1.0f/256.0f; // FIXME: real value here
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/services/sensorservice/OrientationSensor.h b/services/sensorservice/OrientationSensor.h
deleted file mode 100644
index 855949d..0000000
--- a/services/sensorservice/OrientationSensor.h
+++ /dev/null
@@ -1,51 +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.
- */
-
-#ifndef ANDROID_ORIENTATION_SENSOR_H
-#define ANDROID_ORIENTATION_SENSOR_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/Sensor.h>
-
-#include "SensorInterface.h"
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class SensorDevice;
-class SensorFusion;
-
-class OrientationSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
-
-public:
-    OrientationSensor();
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_ORIENTATION_SENSOR_H
diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp
deleted file mode 100644
index 5ea9568..0000000
--- a/services/sensorservice/RotationVectorSensor.cpp
+++ /dev/null
@@ -1,129 +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.
- */
-
-#include <stdint.h>
-#include <math.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-
-#include <hardware/sensors.h>
-
-#include "RotationVectorSensor.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-RotationVectorSensor::RotationVectorSensor()
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
-}
-
-bool RotationVectorSensor::process(sensors_event_t* outEvent,
-        const sensors_event_t& event)
-{
-    if (event.type == SENSOR_TYPE_ACCELEROMETER) {
-        if (mSensorFusion.hasEstimate()) {
-            const vec4_t q(mSensorFusion.getAttitude());
-            *outEvent = event;
-            outEvent->data[0] = q.x;
-            outEvent->data[1] = q.y;
-            outEvent->data[2] = q.z;
-            outEvent->data[3] = q.w;
-            outEvent->sensor = '_rov';
-            outEvent->type = SENSOR_TYPE_ROTATION_VECTOR;
-            return true;
-        }
-    }
-    return false;
-}
-
-status_t RotationVectorSensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(this, enabled);
-}
-
-status_t RotationVectorSensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mSensorFusion.setDelay(this, ns);
-}
-
-Sensor RotationVectorSensor::getSensor() const {
-    sensor_t hwSensor;
-    hwSensor.name       = "Rotation Vector Sensor";
-    hwSensor.vendor     = "Google Inc.";
-    hwSensor.version    = 3;
-    hwSensor.handle     = '_rov';
-    hwSensor.type       = SENSOR_TYPE_ROTATION_VECTOR;
-    hwSensor.maxRange   = 1;
-    hwSensor.resolution = 1.0f / (1<<24);
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
-}
-
-// ---------------------------------------------------------------------------
-
-GyroDriftSensor::GyroDriftSensor()
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
-}
-
-bool GyroDriftSensor::process(sensors_event_t* outEvent,
-        const sensors_event_t& event)
-{
-    if (event.type == SENSOR_TYPE_ACCELEROMETER) {
-        if (mSensorFusion.hasEstimate()) {
-            const vec3_t b(mSensorFusion.getGyroBias());
-            *outEvent = event;
-            outEvent->data[0] = b.x;
-            outEvent->data[1] = b.y;
-            outEvent->data[2] = b.z;
-            outEvent->sensor = '_gbs';
-            outEvent->type = SENSOR_TYPE_ACCELEROMETER;
-            return true;
-        }
-    }
-    return false;
-}
-
-status_t GyroDriftSensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(this, enabled);
-}
-
-status_t GyroDriftSensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mSensorFusion.setDelay(this, ns);
-}
-
-Sensor GyroDriftSensor::getSensor() const {
-    sensor_t hwSensor;
-    hwSensor.name       = "Gyroscope Bias (debug)";
-    hwSensor.vendor     = "Google Inc.";
-    hwSensor.version    = 1;
-    hwSensor.handle     = '_gbs';
-    hwSensor.type       = SENSOR_TYPE_ACCELEROMETER;
-    hwSensor.maxRange   = 1;
-    hwSensor.resolution = 1.0f / (1<<24);
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/services/sensorservice/RotationVectorSensor.h b/services/sensorservice/RotationVectorSensor.h
deleted file mode 100644
index bb97fe1..0000000
--- a/services/sensorservice/RotationVectorSensor.h
+++ /dev/null
@@ -1,66 +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_ROTATION_VECTOR_SENSOR_H
-#define ANDROID_ROTATION_VECTOR_SENSOR_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/Sensor.h>
-
-#include "SensorDevice.h"
-#include "SensorInterface.h"
-
-#include "Fusion.h"
-#include "SensorFusion.h"
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class RotationVectorSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
-
-public:
-    RotationVectorSensor();
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
-};
-
-class GyroDriftSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
-
-public:
-    GyroDriftSensor();
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_ROTATION_VECTOR_SENSOR_H
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
deleted file mode 100644
index 2244a86..0000000
--- a/services/sensorservice/SensorDevice.cpp
+++ /dev/null
@@ -1,282 +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.
- */
-
-#include <stdint.h>
-#include <math.h>
-#include <sys/types.h>
-
-#include <utils/Atomic.h>
-#include <utils/Errors.h>
-#include <utils/Singleton.h>
-
-#include <binder/BinderService.h>
-#include <binder/Parcel.h>
-#include <binder/IServiceManager.h>
-
-#include <hardware/sensors.h>
-
-#include "SensorDevice.h"
-#include "SensorService.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-class BatteryService : public Singleton<BatteryService> {
-    static const int TRANSACTION_noteStartSensor = IBinder::FIRST_CALL_TRANSACTION + 3;
-    static const int TRANSACTION_noteStopSensor = IBinder::FIRST_CALL_TRANSACTION + 4;
-    static const String16 DESCRIPTOR;
-
-    friend class Singleton<BatteryService>;
-    sp<IBinder> mBatteryStatService;
-
-    BatteryService() {
-        const sp<IServiceManager> sm(defaultServiceManager());
-        if (sm != NULL) {
-            const String16 name("batteryinfo");
-            mBatteryStatService = sm->getService(name);
-        }
-    }
-
-    status_t noteStartSensor(int uid, int handle) {
-        Parcel data, reply;
-        data.writeInterfaceToken(DESCRIPTOR);
-        data.writeInt32(uid);
-        data.writeInt32(handle);
-        status_t err = mBatteryStatService->transact(
-                TRANSACTION_noteStartSensor, data, &reply, 0);
-        err = reply.readExceptionCode();
-        return err;
-    }
-
-    status_t noteStopSensor(int uid, int handle) {
-        Parcel data, reply;
-        data.writeInterfaceToken(DESCRIPTOR);
-        data.writeInt32(uid);
-        data.writeInt32(handle);
-        status_t err = mBatteryStatService->transact(
-                TRANSACTION_noteStopSensor, data, &reply, 0);
-        err = reply.readExceptionCode();
-        return err;
-    }
-
-public:
-    void enableSensor(int handle) {
-        if (mBatteryStatService != 0) {
-            int uid = IPCThreadState::self()->getCallingUid();
-            int64_t identity = IPCThreadState::self()->clearCallingIdentity();
-            noteStartSensor(uid, handle);
-            IPCThreadState::self()->restoreCallingIdentity(identity);
-        }
-    }
-    void disableSensor(int handle) {
-        if (mBatteryStatService != 0) {
-            int uid = IPCThreadState::self()->getCallingUid();
-            int64_t identity = IPCThreadState::self()->clearCallingIdentity();
-            noteStopSensor(uid, handle);
-            IPCThreadState::self()->restoreCallingIdentity(identity);
-        }
-    }
-};
-
-const String16 BatteryService::DESCRIPTOR("com.android.internal.app.IBatteryStats");
-
-ANDROID_SINGLETON_STATIC_INSTANCE(BatteryService)
-
-// ---------------------------------------------------------------------------
-
-ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)
-
-SensorDevice::SensorDevice()
-    :  mSensorDevice(0),
-       mSensorModule(0)
-{
-    status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
-            (hw_module_t const**)&mSensorModule);
-
-    ALOGE_IF(err, "couldn't load %s module (%s)",
-            SENSORS_HARDWARE_MODULE_ID, strerror(-err));
-
-    if (mSensorModule) {
-        err = sensors_open(&mSensorModule->common, &mSensorDevice);
-
-        ALOGE_IF(err, "couldn't open device for module %s (%s)",
-                SENSORS_HARDWARE_MODULE_ID, strerror(-err));
-
-        if (mSensorDevice) {
-            sensor_t const* list;
-            ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
-            mActivationCount.setCapacity(count);
-            Info model;
-            for (size_t i=0 ; i<size_t(count) ; i++) {
-                mActivationCount.add(list[i].handle, model);
-                mSensorDevice->activate(mSensorDevice, list[i].handle, 0);
-            }
-        }
-    }
-}
-
-void SensorDevice::dump(String8& result, char* buffer, size_t SIZE)
-{
-    if (!mSensorModule) return;
-    sensor_t const* list;
-    ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
-
-    snprintf(buffer, SIZE, "%d h/w sensors:\n", int(count));
-    result.append(buffer);
-
-    Mutex::Autolock _l(mLock);
-    for (size_t i=0 ; i<size_t(count) ; i++) {
-        const Info& info = mActivationCount.valueFor(list[i].handle);
-        snprintf(buffer, SIZE, "handle=0x%08x, active-count=%d, rates(ms)={ ",
-                list[i].handle,
-                info.rates.size());
-        result.append(buffer);
-        for (size_t j=0 ; j<info.rates.size() ; j++) {
-            snprintf(buffer, SIZE, "%4.1f%s",
-                    info.rates.valueAt(j) / 1e6f,
-                    j<info.rates.size()-1 ? ", " : "");
-            result.append(buffer);
-        }
-        snprintf(buffer, SIZE, " }, selected=%4.1f ms\n",  info.delay / 1e6f);
-        result.append(buffer);
-    }
-}
-
-ssize_t SensorDevice::getSensorList(sensor_t const** list) {
-    if (!mSensorModule) return NO_INIT;
-    ssize_t count = mSensorModule->get_sensors_list(mSensorModule, list);
-    return count;
-}
-
-status_t SensorDevice::initCheck() const {
-    return mSensorDevice && mSensorModule ? NO_ERROR : NO_INIT;
-}
-
-ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
-    if (!mSensorDevice) return NO_INIT;
-    ssize_t c;
-    do {
-        c = mSensorDevice->poll(mSensorDevice, buffer, count);
-    } while (c == -EINTR);
-    return c;
-}
-
-status_t SensorDevice::activate(void* ident, int handle, int enabled)
-{
-    if (!mSensorDevice) return NO_INIT;
-    status_t err(NO_ERROR);
-    bool actuateHardware = false;
-
-    Info& info( mActivationCount.editValueFor(handle) );
-
-
-    ALOGD_IF(DEBUG_CONNECTIONS,
-            "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%d",
-            ident, handle, enabled, info.rates.size());
-
-    if (enabled) {
-        Mutex::Autolock _l(mLock);
-        ALOGD_IF(DEBUG_CONNECTIONS, "... index=%ld",
-                info.rates.indexOfKey(ident));
-
-        if (info.rates.indexOfKey(ident) < 0) {
-            info.rates.add(ident, DEFAULT_EVENTS_PERIOD);
-            if (info.rates.size() == 1) {
-                actuateHardware = true;
-            }
-        } else {
-            // sensor was already activated for this ident
-        }
-    } else {
-        Mutex::Autolock _l(mLock);
-        ALOGD_IF(DEBUG_CONNECTIONS, "... index=%ld",
-                info.rates.indexOfKey(ident));
-
-        ssize_t idx = info.rates.removeItem(ident);
-        if (idx >= 0) {
-            if (info.rates.size() == 0) {
-                actuateHardware = true;
-            }
-        } else {
-            // sensor wasn't enabled for this ident
-        }
-    }
-
-    if (actuateHardware) {
-        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w");
-
-        err = mSensorDevice->activate(mSensorDevice, handle, enabled);
-        if (enabled) {
-            ALOGE_IF(err, "Error activating sensor %d (%s)", handle, strerror(-err));
-            if (err == 0) {
-                BatteryService::getInstance().enableSensor(handle);
-            }
-        } else {
-            if (err == 0) {
-                BatteryService::getInstance().disableSensor(handle);
-            }
-        }
-    }
-
-    { // scope for the lock
-        Mutex::Autolock _l(mLock);
-        nsecs_t ns = info.selectDelay();
-        mSensorDevice->setDelay(mSensorDevice, handle, ns);
-    }
-
-    return err;
-}
-
-status_t SensorDevice::setDelay(void* ident, int handle, int64_t ns)
-{
-    if (!mSensorDevice) return NO_INIT;
-    Mutex::Autolock _l(mLock);
-    Info& info( mActivationCount.editValueFor(handle) );
-    status_t err = info.setDelayForIdent(ident, ns);
-    if (err < 0) return err;
-    ns = info.selectDelay();
-    return mSensorDevice->setDelay(mSensorDevice, handle, ns);
-}
-
-// ---------------------------------------------------------------------------
-
-status_t SensorDevice::Info::setDelayForIdent(void* ident, int64_t ns)
-{
-    ssize_t index = rates.indexOfKey(ident);
-    if (index < 0) {
-        ALOGE("Info::setDelayForIdent(ident=%p, ns=%lld) failed (%s)",
-                ident, ns, strerror(-index));
-        return BAD_INDEX;
-    }
-    rates.editValueAt(index) = ns;
-    return NO_ERROR;
-}
-
-nsecs_t SensorDevice::Info::selectDelay()
-{
-    nsecs_t ns = rates.valueAt(0);
-    for (size_t i=1 ; i<rates.size() ; i++) {
-        nsecs_t cur = rates.valueAt(i);
-        if (cur < ns) {
-            ns = cur;
-        }
-    }
-    delay = ns;
-    return ns;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
deleted file mode 100644
index 728b6cb..0000000
--- a/services/sensorservice/SensorDevice.h
+++ /dev/null
@@ -1,64 +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_DEVICE_H
-#define ANDROID_SENSOR_DEVICE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/KeyedVector.h>
-#include <utils/Singleton.h>
-#include <utils/String8.h>
-
-#include <gui/Sensor.h>
-
-// ---------------------------------------------------------------------------
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-static const nsecs_t DEFAULT_EVENTS_PERIOD = 200000000; //    5 Hz
-
-class SensorDevice : public Singleton<SensorDevice> {
-    friend class Singleton<SensorDevice>;
-    struct sensors_poll_device_t* mSensorDevice;
-    struct sensors_module_t* mSensorModule;
-    mutable Mutex mLock; // protect mActivationCount[].rates
-    // fixed-size array after construction
-    struct Info {
-        Info() : delay(0) { }
-        KeyedVector<void*, nsecs_t> rates;
-        nsecs_t delay;
-        status_t setDelayForIdent(void* ident, int64_t ns);
-        nsecs_t selectDelay();
-    };
-    DefaultKeyedVector<int, Info> mActivationCount;
-
-    SensorDevice();
-public:
-    ssize_t getSensorList(sensor_t const** list);
-    status_t initCheck() const;
-    ssize_t poll(sensors_event_t* buffer, size_t count);
-    status_t activate(void* ident, int handle, int enabled);
-    status_t setDelay(void* ident, int handle, int64_t ns);
-    void dump(String8& result, char* buffer, size_t SIZE);
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SENSOR_DEVICE_H
diff --git a/services/sensorservice/SensorFusion.cpp b/services/sensorservice/SensorFusion.cpp
deleted file mode 100644
index d23906d..0000000
--- a/services/sensorservice/SensorFusion.cpp
+++ /dev/null
@@ -1,148 +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.
- */
-
-#include "SensorDevice.h"
-#include "SensorFusion.h"
-#include "SensorService.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-ANDROID_SINGLETON_STATIC_INSTANCE(SensorFusion)
-
-SensorFusion::SensorFusion()
-    : mSensorDevice(SensorDevice::getInstance()),
-      mEnabled(false), mGyroTime(0)
-{
-    sensor_t const* list;
-    ssize_t count = mSensorDevice.getSensorList(&list);
-    if (count > 0) {
-        for (size_t i=0 ; i<size_t(count) ; i++) {
-            if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
-                mAcc = Sensor(list + i);
-            }
-            if (list[i].type == SENSOR_TYPE_MAGNETIC_FIELD) {
-                mMag = Sensor(list + i);
-            }
-            if (list[i].type == SENSOR_TYPE_GYROSCOPE) {
-                mGyro = Sensor(list + i);
-                // 200 Hz for gyro events is a good compromise between precision
-                // and power/cpu usage.
-                mGyroRate = 200;
-                mTargetDelayNs = 1000000000LL/mGyroRate;
-            }
-        }
-        mFusion.init();
-    }
-}
-
-void SensorFusion::process(const sensors_event_t& event) {
-    if (event.type == SENSOR_TYPE_GYROSCOPE) {
-        if (mGyroTime != 0) {
-            const float dT = (event.timestamp - mGyroTime) / 1000000000.0f;
-            const float freq = 1 / dT;
-            if (freq >= 100 && freq<1000) { // filter values obviously wrong
-                const float alpha = 1 / (1 + dT); // 1s time-constant
-                mGyroRate = freq + (mGyroRate - freq)*alpha;
-            }
-        }
-        mGyroTime = event.timestamp;
-        mFusion.handleGyro(vec3_t(event.data), 1.0f/mGyroRate);
-    } else if (event.type == SENSOR_TYPE_MAGNETIC_FIELD) {
-        const vec3_t mag(event.data);
-        mFusion.handleMag(mag);
-    } else if (event.type == SENSOR_TYPE_ACCELEROMETER) {
-        const vec3_t acc(event.data);
-        mFusion.handleAcc(acc);
-        mAttitude = mFusion.getAttitude();
-    }
-}
-
-template <typename T> inline T min(T a, T b) { return a<b ? a : b; }
-template <typename T> inline T max(T a, T b) { return a>b ? a : b; }
-
-status_t SensorFusion::activate(void* ident, bool enabled) {
-
-    ALOGD_IF(DEBUG_CONNECTIONS,
-            "SensorFusion::activate(ident=%p, enabled=%d)",
-            ident, enabled);
-
-    const ssize_t idx = mClients.indexOf(ident);
-    if (enabled) {
-        if (idx < 0) {
-            mClients.add(ident);
-        }
-    } else {
-        if (idx >= 0) {
-            mClients.removeItemsAt(idx);
-        }
-    }
-
-    mSensorDevice.activate(ident, mAcc.getHandle(), enabled);
-    mSensorDevice.activate(ident, mMag.getHandle(), enabled);
-    mSensorDevice.activate(ident, mGyro.getHandle(), enabled);
-
-    const bool newState = mClients.size() != 0;
-    if (newState != mEnabled) {
-        mEnabled = newState;
-        if (newState) {
-            mFusion.init();
-            mGyroTime = 0;
-        }
-    }
-    return NO_ERROR;
-}
-
-status_t SensorFusion::setDelay(void* ident, int64_t ns) {
-    mSensorDevice.setDelay(ident, mAcc.getHandle(), ns);
-    mSensorDevice.setDelay(ident, mMag.getHandle(), ms2ns(20));
-    mSensorDevice.setDelay(ident, mGyro.getHandle(), mTargetDelayNs);
-    return NO_ERROR;
-}
-
-
-float SensorFusion::getPowerUsage() const {
-    float power =   mAcc.getPowerUsage() +
-                    mMag.getPowerUsage() +
-                    mGyro.getPowerUsage();
-    return power;
-}
-
-int32_t SensorFusion::getMinDelay() const {
-    return mAcc.getMinDelay();
-}
-
-void SensorFusion::dump(String8& result, char* buffer, size_t SIZE) {
-    const Fusion& fusion(mFusion);
-    snprintf(buffer, SIZE, "9-axis fusion %s (%d clients), gyro-rate=%7.2fHz, "
-            "q=< %g, %g, %g, %g > (%g), "
-            "b=< %g, %g, %g >\n",
-            mEnabled ? "enabled" : "disabled",
-            mClients.size(),
-            mGyroRate,
-            fusion.getAttitude().x,
-            fusion.getAttitude().y,
-            fusion.getAttitude().z,
-            fusion.getAttitude().w,
-            length(fusion.getAttitude()),
-            fusion.getBias().x,
-            fusion.getBias().y,
-            fusion.getBias().z);
-    result.append(buffer);
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/services/sensorservice/SensorFusion.h b/services/sensorservice/SensorFusion.h
deleted file mode 100644
index 4c99bcb..0000000
--- a/services/sensorservice/SensorFusion.h
+++ /dev/null
@@ -1,78 +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.
- */
-
-#ifndef ANDROID_SENSOR_FUSION_H
-#define ANDROID_SENSOR_FUSION_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/SortedVector.h>
-#include <utils/Singleton.h>
-#include <utils/String8.h>
-
-#include <gui/Sensor.h>
-
-#include "Fusion.h"
-
-// ---------------------------------------------------------------------------
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-class SensorDevice;
-
-class SensorFusion : public Singleton<SensorFusion> {
-    friend class Singleton<SensorFusion>;
-
-    SensorDevice& mSensorDevice;
-    Sensor mAcc;
-    Sensor mMag;
-    Sensor mGyro;
-    Fusion mFusion;
-    bool mEnabled;
-    float mGyroRate;
-    nsecs_t mTargetDelayNs;
-    nsecs_t mGyroTime;
-    vec4_t mAttitude;
-    SortedVector<void*> mClients;
-
-    SensorFusion();
-
-public:
-    void process(const sensors_event_t& event);
-
-    bool isEnabled() const { return mEnabled; }
-    bool hasEstimate() const { return mFusion.hasEstimate(); }
-    mat33_t getRotationMatrix() const { return mFusion.getRotationMatrix(); }
-    vec4_t getAttitude() const { return mAttitude; }
-    vec3_t getGyroBias() const { return mFusion.getBias(); }
-    float getEstimatedRate() const { return mGyroRate; }
-
-    status_t activate(void* ident, bool enabled);
-    status_t setDelay(void* ident, int64_t ns);
-
-    float getPowerUsage() const;
-    int32_t getMinDelay() const;
-
-    void dump(String8& result, char* buffer, size_t SIZE);
-};
-
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SENSOR_FUSION_H
diff --git a/services/sensorservice/SensorInterface.cpp b/services/sensorservice/SensorInterface.cpp
deleted file mode 100644
index 468aa61..0000000
--- a/services/sensorservice/SensorInterface.cpp
+++ /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.
- */
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <cutils/log.h>
-
-#include "SensorInterface.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-SensorInterface::~SensorInterface()
-{
-}
-
-// ---------------------------------------------------------------------------
-
-HardwareSensor::HardwareSensor(const sensor_t& sensor)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensor(&sensor)
-{
-    ALOGI("%s", sensor.name);
-}
-
-HardwareSensor::~HardwareSensor() {
-}
-
-bool HardwareSensor::process(sensors_event_t* outEvent,
-        const sensors_event_t& event) {
-    *outEvent = event;
-    return true;
-}
-
-status_t HardwareSensor::activate(void* ident, bool enabled) {
-    return mSensorDevice.activate(ident, mSensor.getHandle(), enabled);
-}
-
-status_t HardwareSensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mSensorDevice.setDelay(ident, handle, ns);
-}
-
-Sensor HardwareSensor::getSensor() const {
-    return mSensor;
-}
-
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/services/sensorservice/SensorInterface.h b/services/sensorservice/SensorInterface.h
deleted file mode 100644
index fb357d7..0000000
--- a/services/sensorservice/SensorInterface.h
+++ /dev/null
@@ -1,70 +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_INTERFACE_H
-#define ANDROID_SENSOR_INTERFACE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/Sensor.h>
-
-#include "SensorDevice.h"
-
-// ---------------------------------------------------------------------------
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-class SensorInterface {
-public:
-    virtual ~SensorInterface();
-
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event) = 0;
-
-    virtual status_t activate(void* ident, bool enabled) = 0;
-    virtual status_t setDelay(void* ident, int handle, int64_t ns) = 0;
-    virtual Sensor getSensor() const = 0;
-    virtual bool isVirtual() const = 0;
-};
-
-// ---------------------------------------------------------------------------
-
-class HardwareSensor : public SensorInterface
-{
-    SensorDevice& mSensorDevice;
-    Sensor mSensor;
-
-public:
-    HardwareSensor(const sensor_t& sensor);
-
-    virtual ~HardwareSensor();
-
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return false; }
-};
-
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SENSOR_INTERFACE_H
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
deleted file mode 100644
index 9e5e84b..0000000
--- a/services/sensorservice/SensorService.cpp
+++ /dev/null
@@ -1,637 +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.
- */
-
-#include <stdint.h>
-#include <math.h>
-#include <sys/types.h>
-
-#include <cutils/properties.h>
-
-#include <utils/SortedVector.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-#include <utils/Atomic.h>
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-#include <utils/Singleton.h>
-#include <utils/String16.h>
-
-#include <binder/BinderService.h>
-#include <binder/IServiceManager.h>
-#include <binder/PermissionCache.h>
-
-#include <gui/ISensorServer.h>
-#include <gui/ISensorEventConnection.h>
-#include <gui/SensorEventQueue.h>
-
-#include <hardware/sensors.h>
-
-#include "CorrectedGyroSensor.h"
-#include "GravitySensor.h"
-#include "LinearAccelerationSensor.h"
-#include "OrientationSensor.h"
-#include "RotationVectorSensor.h"
-#include "SensorFusion.h"
-#include "SensorService.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-/*
- * Notes:
- *
- * - what about a gyro-corrected magnetic-field sensor?
- * - run mag sensor from time to time to force calibration
- * - gravity sensor length is wrong (=> drift in linear-acc sensor)
- *
- */
-
-SensorService::SensorService()
-    : mInitCheck(NO_INIT)
-{
-}
-
-void SensorService::onFirstRef()
-{
-    ALOGD("nuSensorService starting...");
-
-    SensorDevice& dev(SensorDevice::getInstance());
-
-    if (dev.initCheck() == NO_ERROR) {
-        sensor_t const* list;
-        ssize_t count = dev.getSensorList(&list);
-        if (count > 0) {
-            ssize_t orientationIndex = -1;
-            bool hasGyro = false;
-            uint32_t virtualSensorsNeeds =
-                    (1<<SENSOR_TYPE_GRAVITY) |
-                    (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |
-                    (1<<SENSOR_TYPE_ROTATION_VECTOR);
-
-            mLastEventSeen.setCapacity(count);
-            for (ssize_t i=0 ; i<count ; i++) {
-                registerSensor( new HardwareSensor(list[i]) );
-                switch (list[i].type) {
-                    case SENSOR_TYPE_ORIENTATION:
-                        orientationIndex = i;
-                        break;
-                    case SENSOR_TYPE_GYROSCOPE:
-                        hasGyro = true;
-                        break;
-                    case SENSOR_TYPE_GRAVITY:
-                    case SENSOR_TYPE_LINEAR_ACCELERATION:
-                    case SENSOR_TYPE_ROTATION_VECTOR:
-                        virtualSensorsNeeds &= ~(1<<list[i].type);
-                        break;
-                }
-            }
-
-            // it's safe to instantiate the SensorFusion object here
-            // (it wants to be instantiated after h/w sensors have been
-            // registered)
-            const SensorFusion& fusion(SensorFusion::getInstance());
-
-            if (hasGyro) {
-                // Always instantiate Android's virtual sensors. Since they are
-                // instantiated behind sensors from the HAL, they won't
-                // interfere with applications, unless they looks specifically
-                // for them (by name).
-
-                registerVirtualSensor( new RotationVectorSensor() );
-                registerVirtualSensor( new GravitySensor(list, count) );
-                registerVirtualSensor( new LinearAccelerationSensor(list, count) );
-
-                // these are optional
-                registerVirtualSensor( new OrientationSensor() );
-                registerVirtualSensor( new CorrectedGyroSensor(list, count) );
-
-                // virtual debugging sensors...
-                char value[PROPERTY_VALUE_MAX];
-                property_get("debug.sensors", value, "0");
-                if (atoi(value)) {
-                    registerVirtualSensor( new GyroDriftSensor() );
-                }
-            }
-
-            // build the sensor list returned to users
-            mUserSensorList = mSensorList;
-            if (hasGyro &&
-                    (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR))) {
-                // if we have the fancy sensor fusion, and it's not provided by the
-                // HAL, use our own (fused) orientation sensor by removing the
-                // HAL supplied one form the user list.
-                if (orientationIndex >= 0) {
-                    mUserSensorList.removeItemsAt(orientationIndex);
-                }
-            }
-
-            run("SensorService", PRIORITY_URGENT_DISPLAY);
-            mInitCheck = NO_ERROR;
-        }
-    }
-}
-
-void SensorService::registerSensor(SensorInterface* s)
-{
-    sensors_event_t event;
-    memset(&event, 0, sizeof(event));
-
-    const Sensor sensor(s->getSensor());
-    // add to the sensor list (returned to clients)
-    mSensorList.add(sensor);
-    // add to our handle->SensorInterface mapping
-    mSensorMap.add(sensor.getHandle(), s);
-    // create an entry in the mLastEventSeen array
-    mLastEventSeen.add(sensor.getHandle(), event);
-}
-
-void SensorService::registerVirtualSensor(SensorInterface* s)
-{
-    registerSensor(s);
-    mVirtualSensorList.add( s );
-}
-
-SensorService::~SensorService()
-{
-    for (size_t i=0 ; i<mSensorMap.size() ; i++)
-        delete mSensorMap.valueAt(i);
-}
-
-static const String16 sDump("android.permission.DUMP");
-
-status_t SensorService::dump(int fd, const Vector<String16>& args)
-{
-    const size_t SIZE = 1024;
-    char buffer[SIZE];
-    String8 result;
-    if (!PermissionCache::checkCallingPermission(sDump)) {
-        snprintf(buffer, SIZE, "Permission Denial: "
-                "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
-                IPCThreadState::self()->getCallingPid(),
-                IPCThreadState::self()->getCallingUid());
-        result.append(buffer);
-    } else {
-        Mutex::Autolock _l(mLock);
-        snprintf(buffer, SIZE, "Sensor List:\n");
-        result.append(buffer);
-        for (size_t i=0 ; i<mSensorList.size() ; i++) {
-            const Sensor& s(mSensorList[i]);
-            const sensors_event_t& e(mLastEventSeen.valueFor(s.getHandle()));
-            snprintf(buffer, SIZE,
-                    "%-48s| %-32s | 0x%08x | maxRate=%7.2fHz | "
-                    "last=<%5.1f,%5.1f,%5.1f>\n",
-                    s.getName().string(),
-                    s.getVendor().string(),
-                    s.getHandle(),
-                    s.getMinDelay() ? (1000000.0f / s.getMinDelay()) : 0.0f,
-                    e.data[0], e.data[1], e.data[2]);
-            result.append(buffer);
-        }
-        SensorFusion::getInstance().dump(result, buffer, SIZE);
-        SensorDevice::getInstance().dump(result, buffer, SIZE);
-
-        snprintf(buffer, SIZE, "%d active connections\n",
-                mActiveConnections.size());
-        result.append(buffer);
-        snprintf(buffer, SIZE, "Active sensors:\n");
-        result.append(buffer);
-        for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
-            int handle = mActiveSensors.keyAt(i);
-            snprintf(buffer, SIZE, "%s (handle=0x%08x, connections=%d)\n",
-                    getSensorName(handle).string(),
-                    handle,
-                    mActiveSensors.valueAt(i)->getNumConnections());
-            result.append(buffer);
-        }
-    }
-    write(fd, result.string(), result.size());
-    return NO_ERROR;
-}
-
-bool SensorService::threadLoop()
-{
-    ALOGD("nuSensorService thread starting...");
-
-    const size_t numEventMax = 16;
-    const size_t minBufferSize = numEventMax + numEventMax * mVirtualSensorList.size();
-    sensors_event_t buffer[minBufferSize];
-    sensors_event_t scratch[minBufferSize];
-    SensorDevice& device(SensorDevice::getInstance());
-    const size_t vcount = mVirtualSensorList.size();
-
-    ssize_t count;
-    do {
-        count = device.poll(buffer, numEventMax);
-        if (count<0) {
-            ALOGE("sensor poll failed (%s)", strerror(-count));
-            break;
-        }
-
-        recordLastValue(buffer, count);
-
-        // handle virtual sensors
-        if (count && vcount) {
-            sensors_event_t const * const event = buffer;
-            const DefaultKeyedVector<int, SensorInterface*> virtualSensors(
-                    getActiveVirtualSensors());
-            const size_t activeVirtualSensorCount = virtualSensors.size();
-            if (activeVirtualSensorCount) {
-                size_t k = 0;
-                SensorFusion& fusion(SensorFusion::getInstance());
-                if (fusion.isEnabled()) {
-                    for (size_t i=0 ; i<size_t(count) ; i++) {
-                        fusion.process(event[i]);
-                    }
-                }
-                for (size_t i=0 ; i<size_t(count) && k<minBufferSize ; i++) {
-                    for (size_t j=0 ; j<activeVirtualSensorCount ; j++) {
-                        if (count + k >= minBufferSize) {
-                            ALOGE("buffer too small to hold all events: "
-                                    "count=%u, k=%u, size=%u",
-                                    count, k, minBufferSize);
-                            break;
-                        }
-                        sensors_event_t out;
-                        SensorInterface* si = virtualSensors.valueAt(j);
-                        if (si->process(&out, event[i])) {
-                            buffer[count + k] = out;
-                            k++;
-                        }
-                    }
-                }
-                if (k) {
-                    // record the last synthesized values
-                    recordLastValue(&buffer[count], k);
-                    count += k;
-                    // sort the buffer by time-stamps
-                    sortEventBuffer(buffer, count);
-                }
-            }
-        }
-
-        // send our events to clients...
-        const SortedVector< wp<SensorEventConnection> > activeConnections(
-                getActiveConnections());
-        size_t numConnections = activeConnections.size();
-        for (size_t i=0 ; i<numConnections ; i++) {
-            sp<SensorEventConnection> connection(
-                    activeConnections[i].promote());
-            if (connection != 0) {
-                connection->sendEvents(buffer, count, scratch);
-            }
-        }
-    } while (count >= 0 || Thread::exitPending());
-
-    ALOGW("Exiting SensorService::threadLoop => aborting...");
-    abort();
-    return false;
-}
-
-void SensorService::recordLastValue(
-        sensors_event_t const * buffer, size_t count)
-{
-    Mutex::Autolock _l(mLock);
-
-    // record the last event for each sensor
-    int32_t prev = buffer[0].sensor;
-    for (size_t i=1 ; i<count ; i++) {
-        // record the last event of each sensor type in this buffer
-        int32_t curr = buffer[i].sensor;
-        if (curr != prev) {
-            mLastEventSeen.editValueFor(prev) = buffer[i-1];
-            prev = curr;
-        }
-    }
-    mLastEventSeen.editValueFor(prev) = buffer[count-1];
-}
-
-void SensorService::sortEventBuffer(sensors_event_t* buffer, size_t count)
-{
-    struct compar {
-        static int cmp(void const* lhs, void const* rhs) {
-            sensors_event_t const* l = static_cast<sensors_event_t const*>(lhs);
-            sensors_event_t const* r = static_cast<sensors_event_t const*>(rhs);
-            return l->timestamp - r->timestamp;
-        }
-    };
-    qsort(buffer, count, sizeof(sensors_event_t), compar::cmp);
-}
-
-SortedVector< wp<SensorService::SensorEventConnection> >
-SensorService::getActiveConnections() const
-{
-    Mutex::Autolock _l(mLock);
-    return mActiveConnections;
-}
-
-DefaultKeyedVector<int, SensorInterface*>
-SensorService::getActiveVirtualSensors() const
-{
-    Mutex::Autolock _l(mLock);
-    return mActiveVirtualSensors;
-}
-
-String8 SensorService::getSensorName(int handle) const {
-    size_t count = mUserSensorList.size();
-    for (size_t i=0 ; i<count ; i++) {
-        const Sensor& sensor(mUserSensorList[i]);
-        if (sensor.getHandle() == handle) {
-            return sensor.getName();
-        }
-    }
-    String8 result("unknown");
-    return result;
-}
-
-Vector<Sensor> SensorService::getSensorList()
-{
-    return mUserSensorList;
-}
-
-sp<ISensorEventConnection> SensorService::createSensorEventConnection()
-{
-    sp<SensorEventConnection> result(new SensorEventConnection(this));
-    return result;
-}
-
-void SensorService::cleanupConnection(SensorEventConnection* c)
-{
-    Mutex::Autolock _l(mLock);
-    const wp<SensorEventConnection> connection(c);
-    size_t size = mActiveSensors.size();
-    ALOGD_IF(DEBUG_CONNECTIONS, "%d active sensors", size);
-    for (size_t i=0 ; i<size ; ) {
-        int handle = mActiveSensors.keyAt(i);
-        if (c->hasSensor(handle)) {
-            ALOGD_IF(DEBUG_CONNECTIONS, "%i: disabling handle=0x%08x", i, handle);
-            SensorInterface* sensor = mSensorMap.valueFor( handle );
-            ALOGE_IF(!sensor, "mSensorMap[handle=0x%08x] is null!", handle);
-            if (sensor) {
-                sensor->activate(c, false);
-            }
-        }
-        SensorRecord* rec = mActiveSensors.valueAt(i);
-        ALOGE_IF(!rec, "mActiveSensors[%d] is null (handle=0x%08x)!", i, handle);
-        ALOGD_IF(DEBUG_CONNECTIONS,
-                "removing connection %p for sensor[%d].handle=0x%08x",
-                c, i, handle);
-
-        if (rec && rec->removeConnection(connection)) {
-            ALOGD_IF(DEBUG_CONNECTIONS, "... and it was the last connection");
-            mActiveSensors.removeItemsAt(i, 1);
-            mActiveVirtualSensors.removeItem(handle);
-            delete rec;
-            size--;
-        } else {
-            i++;
-        }
-    }
-    mActiveConnections.remove(connection);
-}
-
-status_t SensorService::enable(const sp<SensorEventConnection>& connection,
-        int handle)
-{
-    if (mInitCheck != NO_ERROR)
-        return mInitCheck;
-
-    Mutex::Autolock _l(mLock);
-    SensorInterface* sensor = mSensorMap.valueFor(handle);
-    status_t err = sensor ? sensor->activate(connection.get(), true) : status_t(BAD_VALUE);
-    if (err == NO_ERROR) {
-        SensorRecord* rec = mActiveSensors.valueFor(handle);
-        if (rec == 0) {
-            rec = new SensorRecord(connection);
-            mActiveSensors.add(handle, rec);
-            if (sensor->isVirtual()) {
-                mActiveVirtualSensors.add(handle, sensor);
-            }
-        } else {
-            if (rec->addConnection(connection)) {
-                // this sensor is already activated, but we are adding a
-                // connection that uses it. Immediately send down the last
-                // known value of the requested sensor if it's not a
-                // "continuous" sensor.
-                if (sensor->getSensor().getMinDelay() == 0) {
-                    sensors_event_t scratch;
-                    sensors_event_t& event(mLastEventSeen.editValueFor(handle));
-                    if (event.version == sizeof(sensors_event_t)) {
-                        connection->sendEvents(&event, 1);
-                    }
-                }
-            }
-        }
-        if (err == NO_ERROR) {
-            // connection now active
-            if (connection->addSensor(handle)) {
-                // the sensor was added (which means it wasn't already there)
-                // so, see if this connection becomes active
-                if (mActiveConnections.indexOf(connection) < 0) {
-                    mActiveConnections.add(connection);
-                }
-            }
-        }
-    }
-    return err;
-}
-
-status_t SensorService::disable(const sp<SensorEventConnection>& connection,
-        int handle)
-{
-    if (mInitCheck != NO_ERROR)
-        return mInitCheck;
-
-    status_t err = NO_ERROR;
-    Mutex::Autolock _l(mLock);
-    SensorRecord* rec = mActiveSensors.valueFor(handle);
-    if (rec) {
-        // see if this connection becomes inactive
-        connection->removeSensor(handle);
-        if (connection->hasAnySensor() == false) {
-            mActiveConnections.remove(connection);
-        }
-        // see if this sensor becomes inactive
-        if (rec->removeConnection(connection)) {
-            mActiveSensors.removeItem(handle);
-            mActiveVirtualSensors.removeItem(handle);
-            delete rec;
-        }
-        SensorInterface* sensor = mSensorMap.valueFor(handle);
-        err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
-    }
-    return err;
-}
-
-status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection,
-        int handle, nsecs_t ns)
-{
-    if (mInitCheck != NO_ERROR)
-        return mInitCheck;
-
-    SensorInterface* sensor = mSensorMap.valueFor(handle);
-    if (!sensor)
-        return BAD_VALUE;
-
-    if (ns < 0)
-        return BAD_VALUE;
-
-    nsecs_t minDelayNs = sensor->getSensor().getMinDelayNs();
-    if (ns < minDelayNs) {
-        ns = minDelayNs;
-    }
-
-    if (ns < MINIMUM_EVENTS_PERIOD)
-        ns = MINIMUM_EVENTS_PERIOD;
-
-    return sensor->setDelay(connection.get(), handle, ns);
-}
-
-// ---------------------------------------------------------------------------
-
-SensorService::SensorRecord::SensorRecord(
-        const sp<SensorEventConnection>& connection)
-{
-    mConnections.add(connection);
-}
-
-bool SensorService::SensorRecord::addConnection(
-        const sp<SensorEventConnection>& connection)
-{
-    if (mConnections.indexOf(connection) < 0) {
-        mConnections.add(connection);
-        return true;
-    }
-    return false;
-}
-
-bool SensorService::SensorRecord::removeConnection(
-        const wp<SensorEventConnection>& connection)
-{
-    ssize_t index = mConnections.indexOf(connection);
-    if (index >= 0) {
-        mConnections.removeItemsAt(index, 1);
-    }
-    return mConnections.size() ? false : true;
-}
-
-// ---------------------------------------------------------------------------
-
-SensorService::SensorEventConnection::SensorEventConnection(
-        const sp<SensorService>& service)
-    : mService(service), mChannel(new BitTube())
-{
-}
-
-SensorService::SensorEventConnection::~SensorEventConnection()
-{
-    ALOGD_IF(DEBUG_CONNECTIONS, "~SensorEventConnection(%p)", this);
-    mService->cleanupConnection(this);
-}
-
-void SensorService::SensorEventConnection::onFirstRef()
-{
-}
-
-bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
-    Mutex::Autolock _l(mConnectionLock);
-    if (mSensorInfo.indexOf(handle) <= 0) {
-        mSensorInfo.add(handle);
-        return true;
-    }
-    return false;
-}
-
-bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
-    Mutex::Autolock _l(mConnectionLock);
-    if (mSensorInfo.remove(handle) >= 0) {
-        return true;
-    }
-    return false;
-}
-
-bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const {
-    Mutex::Autolock _l(mConnectionLock);
-    return mSensorInfo.indexOf(handle) >= 0;
-}
-
-bool SensorService::SensorEventConnection::hasAnySensor() const {
-    Mutex::Autolock _l(mConnectionLock);
-    return mSensorInfo.size() ? true : false;
-}
-
-status_t SensorService::SensorEventConnection::sendEvents(
-        sensors_event_t const* buffer, size_t numEvents,
-        sensors_event_t* scratch)
-{
-    // filter out events not for this connection
-    size_t count = 0;
-    if (scratch) {
-        Mutex::Autolock _l(mConnectionLock);
-        size_t i=0;
-        while (i<numEvents) {
-            const int32_t curr = buffer[i].sensor;
-            if (mSensorInfo.indexOf(curr) >= 0) {
-                do {
-                    scratch[count++] = buffer[i++];
-                } while ((i<numEvents) && (buffer[i].sensor == curr));
-            } else {
-                i++;
-            }
-        }
-    } else {
-        scratch = const_cast<sensors_event_t *>(buffer);
-        count = numEvents;
-    }
-
-    // NOTE: ASensorEvent and sensors_event_t are the same type
-    ssize_t size = SensorEventQueue::write(mChannel,
-            reinterpret_cast<ASensorEvent const*>(scratch), count);
-    if (size == -EAGAIN) {
-        // the destination doesn't accept events anymore, it's probably
-        // full. For now, we just drop the events on the floor.
-        //ALOGW("dropping %d events on the floor", count);
-        return size;
-    }
-
-    return size < 0 ? status_t(size) : status_t(NO_ERROR);
-}
-
-sp<BitTube> SensorService::SensorEventConnection::getSensorChannel() const
-{
-    return mChannel;
-}
-
-status_t SensorService::SensorEventConnection::enableDisable(
-        int handle, bool enabled)
-{
-    status_t err;
-    if (enabled) {
-        err = mService->enable(this, handle);
-    } else {
-        err = mService->disable(this, handle);
-    }
-    return err;
-}
-
-status_t SensorService::SensorEventConnection::setEventRate(
-        int handle, nsecs_t ns)
-{
-    return mService->setEventRate(this, handle, ns);
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
deleted file mode 100644
index e357f96..0000000
--- a/services/sensorservice/SensorService.h
+++ /dev/null
@@ -1,142 +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_SERVICE_H
-#define ANDROID_SENSOR_SERVICE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Vector.h>
-#include <utils/SortedVector.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-#include <utils/RefBase.h>
-
-#include <binder/BinderService.h>
-
-#include <gui/Sensor.h>
-#include <gui/BitTube.h>
-#include <gui/ISensorServer.h>
-#include <gui/ISensorEventConnection.h>
-
-#include "SensorInterface.h"
-
-// ---------------------------------------------------------------------------
-
-#define DEBUG_CONNECTIONS   false
-
-struct sensors_poll_device_t;
-struct sensors_module_t;
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-class SensorService :
-        public BinderService<SensorService>,
-        public BnSensorServer,
-        protected Thread
-{
-   friend class BinderService<SensorService>;
-
-   static const nsecs_t MINIMUM_EVENTS_PERIOD =   1000000; // 1000 Hz
-
-            SensorService();
-    virtual ~SensorService();
-
-    virtual void onFirstRef();
-
-    // Thread interface
-    virtual bool threadLoop();
-
-    // ISensorServer interface
-    virtual Vector<Sensor> getSensorList();
-    virtual sp<ISensorEventConnection> createSensorEventConnection();
-    virtual status_t dump(int fd, const Vector<String16>& args);
-
-
-    class SensorEventConnection : public BnSensorEventConnection {
-        virtual ~SensorEventConnection();
-        virtual void onFirstRef();
-        virtual sp<BitTube> getSensorChannel() const;
-        virtual status_t enableDisable(int handle, bool enabled);
-        virtual status_t setEventRate(int handle, nsecs_t ns);
-
-        sp<SensorService> const mService;
-        sp<BitTube> const mChannel;
-        mutable Mutex mConnectionLock;
-
-        // protected by SensorService::mLock
-        SortedVector<int> mSensorInfo;
-
-    public:
-        SensorEventConnection(const sp<SensorService>& service);
-
-        status_t sendEvents(sensors_event_t const* buffer, size_t count,
-                sensors_event_t* scratch = NULL);
-        bool hasSensor(int32_t handle) const;
-        bool hasAnySensor() const;
-        bool addSensor(int32_t handle);
-        bool removeSensor(int32_t handle);
-    };
-
-    class SensorRecord {
-        SortedVector< wp<SensorEventConnection> > mConnections;
-    public:
-        SensorRecord(const sp<SensorEventConnection>& connection);
-        bool addConnection(const sp<SensorEventConnection>& connection);
-        bool removeConnection(const wp<SensorEventConnection>& connection);
-        size_t getNumConnections() const { return mConnections.size(); }
-    };
-
-    SortedVector< wp<SensorEventConnection> > getActiveConnections() const;
-    DefaultKeyedVector<int, SensorInterface*> getActiveVirtualSensors() const;
-
-    String8 getSensorName(int handle) const;
-    void recordLastValue(sensors_event_t const * buffer, size_t count);
-    static void sortEventBuffer(sensors_event_t* buffer, size_t count);
-    void registerSensor(SensorInterface* sensor);
-    void registerVirtualSensor(SensorInterface* sensor);
-
-    // constants
-    Vector<Sensor> mSensorList;
-    Vector<Sensor> mUserSensorList;
-    DefaultKeyedVector<int, SensorInterface*> mSensorMap;
-    Vector<SensorInterface *> mVirtualSensorList;
-    status_t mInitCheck;
-
-    // protected by mLock
-    mutable Mutex mLock;
-    DefaultKeyedVector<int, SensorRecord*> mActiveSensors;
-    DefaultKeyedVector<int, SensorInterface*> mActiveVirtualSensors;
-    SortedVector< wp<SensorEventConnection> > mActiveConnections;
-
-    // The size of this vector is constant, only the items are mutable
-    KeyedVector<int32_t, sensors_event_t> mLastEventSeen;
-
-public:
-    static char const* getServiceName() { return "sensorservice"; }
-
-    void cleanupConnection(SensorEventConnection* connection);
-    status_t enable(const sp<SensorEventConnection>& connection, int handle);
-    status_t disable(const sp<SensorEventConnection>& connection, int handle);
-    status_t setEventRate(const sp<SensorEventConnection>& connection, int handle, nsecs_t ns);
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SENSOR_SERVICE_H
diff --git a/services/sensorservice/mat.h b/services/sensorservice/mat.h
deleted file mode 100644
index a76fc91..0000000
--- a/services/sensorservice/mat.h
+++ /dev/null
@@ -1,393 +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.
- */
-
-#ifndef ANDROID_MAT_H
-#define ANDROID_MAT_H
-
-#include "vec.h"
-#include "traits.h"
-
-// -----------------------------------------------------------------------
-
-namespace android {
-
-template <typename TYPE, size_t C, size_t R>
-class mat;
-
-namespace helpers {
-
-template <typename TYPE, size_t C, size_t R>
-mat<TYPE, C, R>& doAssign(
-        mat<TYPE, C, R>& lhs,
-        typename TypeTraits<TYPE>::ParameterType rhs) {
-    for (size_t i=0 ; i<C ; i++)
-        for (size_t j=0 ; j<R ; j++)
-            lhs[i][j] = (i==j) ? rhs : 0;
-    return lhs;
-}
-
-template <typename TYPE, size_t C, size_t R, size_t D>
-mat<TYPE, C, R> PURE doMul(
-        const mat<TYPE, D, R>& lhs,
-        const mat<TYPE, C, D>& rhs)
-{
-    mat<TYPE, C, R> res;
-    for (size_t c=0 ; c<C ; c++) {
-        for (size_t r=0 ; r<R ; r++) {
-            TYPE v(0);
-            for (size_t k=0 ; k<D ; k++) {
-                v += lhs[k][r] * rhs[c][k];
-            }
-            res[c][r] = v;
-        }
-    }
-    return res;
-}
-
-template <typename TYPE, size_t R, size_t D>
-vec<TYPE, R> PURE doMul(
-        const mat<TYPE, D, R>& lhs,
-        const vec<TYPE, D>& rhs)
-{
-    vec<TYPE, R> res;
-    for (size_t r=0 ; r<R ; r++) {
-        TYPE v(0);
-        for (size_t k=0 ; k<D ; k++) {
-            v += lhs[k][r] * rhs[k];
-        }
-        res[r] = v;
-    }
-    return res;
-}
-
-template <typename TYPE, size_t C, size_t R>
-mat<TYPE, C, R> PURE doMul(
-        const vec<TYPE, R>& lhs,
-        const mat<TYPE, C, 1>& rhs)
-{
-    mat<TYPE, C, R> res;
-    for (size_t c=0 ; c<C ; c++) {
-        for (size_t r=0 ; r<R ; r++) {
-            res[c][r] = lhs[r] * rhs[c][0];
-        }
-    }
-    return res;
-}
-
-template <typename TYPE, size_t C, size_t R>
-mat<TYPE, C, R> PURE doMul(
-        const mat<TYPE, C, R>& rhs,
-        typename TypeTraits<TYPE>::ParameterType v)
-{
-    mat<TYPE, C, R> res;
-    for (size_t c=0 ; c<C ; c++) {
-        for (size_t r=0 ; r<R ; r++) {
-            res[c][r] = rhs[c][r] * v;
-        }
-    }
-    return res;
-}
-
-template <typename TYPE, size_t C, size_t R>
-mat<TYPE, C, R> PURE doMul(
-        typename TypeTraits<TYPE>::ParameterType v,
-        const mat<TYPE, C, R>& rhs)
-{
-    mat<TYPE, C, R> res;
-    for (size_t c=0 ; c<C ; c++) {
-        for (size_t r=0 ; r<R ; r++) {
-            res[c][r] = v * rhs[c][r];
-        }
-    }
-    return res;
-}
-
-
-}; // namespace helpers
-
-// -----------------------------------------------------------------------
-
-template <typename TYPE, size_t C, size_t R>
-class mat : public vec< vec<TYPE, R>, C > {
-    typedef typename TypeTraits<TYPE>::ParameterType pTYPE;
-    typedef vec< vec<TYPE, R>, C > base;
-public:
-    // STL-like interface.
-    typedef TYPE value_type;
-    typedef TYPE& reference;
-    typedef TYPE const& const_reference;
-    typedef size_t size_type;
-    size_type size() const { return R*C; }
-    enum { ROWS = R, COLS = C };
-
-
-    // -----------------------------------------------------------------------
-    // default constructors
-
-    mat() { }
-    mat(const mat& rhs)  : base(rhs) { }
-    mat(const base& rhs) : base(rhs) { }
-
-    // -----------------------------------------------------------------------
-    // conversion constructors
-
-    // sets the diagonal to the value, off-diagonal to zero
-    mat(pTYPE rhs) {
-        helpers::doAssign(*this, rhs);
-    }
-
-    // -----------------------------------------------------------------------
-    // Assignment
-
-    mat& operator=(const mat& rhs) {
-        base::operator=(rhs);
-        return *this;
-    }
-
-    mat& operator=(const base& rhs) {
-        base::operator=(rhs);
-        return *this;
-    }
-
-    mat& operator=(pTYPE rhs) {
-        return helpers::doAssign(*this, rhs);
-    }
-
-    // -----------------------------------------------------------------------
-    // non-member function declaration and definition
-
-    friend inline mat PURE operator + (const mat& lhs, const mat& rhs) {
-        return helpers::doAdd(
-                static_cast<const base&>(lhs),
-                static_cast<const base&>(rhs));
-    }
-    friend inline mat PURE operator - (const mat& lhs, const mat& rhs) {
-        return helpers::doSub(
-                static_cast<const base&>(lhs),
-                static_cast<const base&>(rhs));
-    }
-
-    // matrix*matrix
-    template <size_t D>
-    friend mat PURE operator * (
-            const mat<TYPE, D, R>& lhs,
-            const mat<TYPE, C, D>& rhs) {
-        return helpers::doMul(lhs, rhs);
-    }
-
-    // matrix*vector
-    friend vec<TYPE, R> PURE operator * (
-            const mat& lhs, const vec<TYPE, C>& rhs) {
-        return helpers::doMul(lhs, rhs);
-    }
-
-    // vector*matrix
-    friend mat PURE operator * (
-            const vec<TYPE, R>& lhs, const mat<TYPE, C, 1>& rhs) {
-        return helpers::doMul(lhs, rhs);
-    }
-
-    // matrix*scalar
-    friend inline mat PURE operator * (const mat& lhs, pTYPE v) {
-        return helpers::doMul(lhs, v);
-    }
-
-    // scalar*matrix
-    friend inline mat PURE operator * (pTYPE v, const mat& rhs) {
-        return helpers::doMul(v, rhs);
-    }
-
-    // -----------------------------------------------------------------------
-    // streaming operator to set the columns of the matrix:
-    // example:
-    //    mat33_t m;
-    //    m << v0 << v1 << v2;
-
-    // column_builder<> stores the matrix and knows which column to set
-    template<size_t PREV_COLUMN>
-    struct column_builder {
-        mat& matrix;
-        column_builder(mat& matrix) : matrix(matrix) { }
-    };
-
-    // operator << is not a method of column_builder<> so we can
-    // overload it for unauthorized values (partial specialization
-    // not allowed in class-scope).
-    // we just set the column and return the next column_builder<>
-    template<size_t PREV_COLUMN>
-    friend column_builder<PREV_COLUMN+1> operator << (
-            const column_builder<PREV_COLUMN>& lhs,
-            const vec<TYPE, R>& rhs) {
-        lhs.matrix[PREV_COLUMN+1] = rhs;
-        return column_builder<PREV_COLUMN+1>(lhs.matrix);
-    }
-
-    // we return void here so we get a compile-time error if the
-    // user tries to set too many columns
-    friend void operator << (
-            const column_builder<C-2>& lhs,
-            const vec<TYPE, R>& rhs) {
-        lhs.matrix[C-1] = rhs;
-    }
-
-    // this is where the process starts. we set the first columns and
-    // return the next column_builder<>
-    column_builder<0> operator << (const vec<TYPE, R>& rhs) {
-        (*this)[0] = rhs;
-        return column_builder<0>(*this);
-    }
-};
-
-// Specialize column matrix so they're exactly equivalent to a vector
-template <typename TYPE, size_t R>
-class mat<TYPE, 1, R> : public vec<TYPE, R> {
-    typedef vec<TYPE, R> base;
-public:
-    // STL-like interface.
-    typedef TYPE value_type;
-    typedef TYPE& reference;
-    typedef TYPE const& const_reference;
-    typedef size_t size_type;
-    size_type size() const { return R; }
-    enum { ROWS = R, COLS = 1 };
-
-    mat() { }
-    mat(const base& rhs) : base(rhs) { }
-    mat(const mat& rhs) : base(rhs) { }
-    mat(const TYPE& rhs) { helpers::doAssign(*this, rhs); }
-    mat& operator=(const mat& rhs) { base::operator=(rhs); return *this; }
-    mat& operator=(const base& rhs) { base::operator=(rhs); return *this; }
-    mat& operator=(const TYPE& rhs) { return helpers::doAssign(*this, rhs); }
-    // we only have one column, so ignore the index
-    const base& operator[](size_t) const { return *this; }
-    base& operator[](size_t) { return *this; }
-    void operator << (const vec<TYPE, R>& rhs) { base::operator[](0) = rhs; }
-};
-
-// -----------------------------------------------------------------------
-// matrix functions
-
-// transpose. this handles matrices of matrices
-inline int     PURE transpose(int v)    { return v; }
-inline float   PURE transpose(float v)  { return v; }
-inline double  PURE transpose(double v) { return v; }
-
-// Transpose a matrix
-template <typename TYPE, size_t C, size_t R>
-mat<TYPE, R, C> PURE transpose(const mat<TYPE, C, R>& m) {
-    mat<TYPE, R, C> r;
-    for (size_t i=0 ; i<R ; i++)
-        for (size_t j=0 ; j<C ; j++)
-            r[i][j] = transpose(m[j][i]);
-    return r;
-}
-
-// Calculate the trace of a matrix
-template <typename TYPE, size_t C> static TYPE trace(const mat<TYPE, C, C>& m) {
-    TYPE t;
-    for (size_t i=0 ; i<C ; i++)
-        t += m[i][i];
-    return t;
-}
-
-// Test positive-semidefiniteness of a matrix
-template <typename TYPE, size_t C>
-static bool isPositiveSemidefinite(const mat<TYPE, C, C>& m, TYPE tolerance) {
-    for (size_t i=0 ; i<C ; i++)
-        if (m[i][i] < 0)
-            return false;
-
-    for (size_t i=0 ; i<C ; i++)
-      for (size_t j=i+1 ; j<C ; j++)
-          if (fabs(m[i][j] - m[j][i]) > tolerance)
-              return false;
-
-    return true;
-}
-
-// Transpose a vector
-template <
-    template<typename T, size_t S> class VEC,
-    typename TYPE,
-    size_t SIZE
->
-mat<TYPE, SIZE, 1> PURE transpose(const VEC<TYPE, SIZE>& v) {
-    mat<TYPE, SIZE, 1> r;
-    for (size_t i=0 ; i<SIZE ; i++)
-        r[i][0] = transpose(v[i]);
-    return r;
-}
-
-// -----------------------------------------------------------------------
-// "dumb" matrix inversion
-template<typename T, size_t N>
-mat<T, N, N> PURE invert(const mat<T, N, N>& src) {
-    T t;
-    size_t swap;
-    mat<T, N, N> tmp(src);
-    mat<T, N, N> inverse(1);
-
-    for (size_t i=0 ; i<N ; i++) {
-        // look for largest element in column
-        swap = i;
-        for (size_t j=i+1 ; j<N ; j++) {
-            if (fabs(tmp[j][i]) > fabs(tmp[i][i])) {
-                swap = j;
-            }
-        }
-
-        if (swap != i) {
-            /* swap rows. */
-            for (size_t k=0 ; k<N ; k++) {
-                t = tmp[i][k];
-                tmp[i][k] = tmp[swap][k];
-                tmp[swap][k] = t;
-
-                t = inverse[i][k];
-                inverse[i][k] = inverse[swap][k];
-                inverse[swap][k] = t;
-            }
-        }
-
-        t = 1 / tmp[i][i];
-        for (size_t k=0 ; k<N ; k++) {
-            tmp[i][k] *= t;
-            inverse[i][k] *= t;
-        }
-        for (size_t j=0 ; j<N ; j++) {
-            if (j != i) {
-                t = tmp[j][i];
-                for (size_t k=0 ; k<N ; k++) {
-                    tmp[j][k] -= tmp[i][k] * t;
-                    inverse[j][k] -= inverse[i][k] * t;
-                }
-            }
-        }
-    }
-    return inverse;
-}
-
-// -----------------------------------------------------------------------
-
-typedef mat<float, 2, 2> mat22_t;
-typedef mat<float, 3, 3> mat33_t;
-typedef mat<float, 4, 4> mat44_t;
-
-// -----------------------------------------------------------------------
-
-}; // namespace android
-
-#endif /* ANDROID_MAT_H */
diff --git a/services/sensorservice/quat.h b/services/sensorservice/quat.h
deleted file mode 100644
index fea1afe..0000000
--- a/services/sensorservice/quat.h
+++ /dev/null
@@ -1,98 +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.
- */
-
-#ifndef ANDROID_QUAT_H
-#define ANDROID_QUAT_H
-
-#include <math.h>
-
-#include "vec.h"
-#include "mat.h"
-
-// -----------------------------------------------------------------------
-namespace android {
-// -----------------------------------------------------------------------
-
-template <typename TYPE>
-mat<TYPE, 3, 3> quatToMatrix(const vec<TYPE, 4>& q) {
-    mat<TYPE, 3, 3> R;
-    TYPE q0(q.w);
-    TYPE q1(q.x);
-    TYPE q2(q.y);
-    TYPE q3(q.z);
-    TYPE sq_q1 = 2 * q1 * q1;
-    TYPE sq_q2 = 2 * q2 * q2;
-    TYPE sq_q3 = 2 * q3 * q3;
-    TYPE q1_q2 = 2 * q1 * q2;
-    TYPE q3_q0 = 2 * q3 * q0;
-    TYPE q1_q3 = 2 * q1 * q3;
-    TYPE q2_q0 = 2 * q2 * q0;
-    TYPE q2_q3 = 2 * q2 * q3;
-    TYPE q1_q0 = 2 * q1 * q0;
-    R[0][0] = 1 - sq_q2 - sq_q3;
-    R[0][1] = q1_q2 - q3_q0;
-    R[0][2] = q1_q3 + q2_q0;
-    R[1][0] = q1_q2 + q3_q0;
-    R[1][1] = 1 - sq_q1 - sq_q3;
-    R[1][2] = q2_q3 - q1_q0;
-    R[2][0] = q1_q3 - q2_q0;
-    R[2][1] = q2_q3 + q1_q0;
-    R[2][2] = 1 - sq_q1 - sq_q2;
-    return R;
-}
-
-template <typename TYPE>
-vec<TYPE, 4> matrixToQuat(const mat<TYPE, 3, 3>& R) {
-    // matrix to quaternion
-
-    struct {
-        inline TYPE operator()(TYPE v) {
-            return v < 0 ? 0 : v;
-        }
-    } clamp;
-
-    vec<TYPE, 4> q;
-    const float Hx = R[0].x;
-    const float My = R[1].y;
-    const float Az = R[2].z;
-    q.x = sqrtf( clamp( Hx - My - Az + 1) * 0.25f );
-    q.y = sqrtf( clamp(-Hx + My - Az + 1) * 0.25f );
-    q.z = sqrtf( clamp(-Hx - My + Az + 1) * 0.25f );
-    q.w = sqrtf( clamp( Hx + My + Az + 1) * 0.25f );
-    q.x = copysignf(q.x, R[2].y - R[1].z);
-    q.y = copysignf(q.y, R[0].z - R[2].x);
-    q.z = copysignf(q.z, R[1].x - R[0].y);
-    // guaranteed to be unit-quaternion
-    return q;
-}
-
-template <typename TYPE>
-vec<TYPE, 4> normalize_quat(const vec<TYPE, 4>& q) {
-    vec<TYPE, 4> r(q);
-    if (r.w < 0) {
-        r = -r;
-    }
-    return normalize(r);
-}
-
-// -----------------------------------------------------------------------
-
-typedef vec4_t quat_t;
-
-// -----------------------------------------------------------------------
-}; // namespace android
-
-#endif /* ANDROID_QUAT_H */
diff --git a/services/sensorservice/tests/Android.mk b/services/sensorservice/tests/Android.mk
deleted file mode 100644
index 45296dd..0000000
--- a/services/sensorservice/tests/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	sensorservicetest.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils libutils libui libgui
-
-LOCAL_MODULE:= test-sensorservice
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/sensorservice/tests/sensorservicetest.cpp b/services/sensorservice/tests/sensorservicetest.cpp
deleted file mode 100644
index 1025fa8..0000000
--- a/services/sensorservice/tests/sensorservicetest.cpp
+++ /dev/null
@@ -1,110 +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.
- */
-
-#include <android/sensor.h>
-#include <gui/Sensor.h>
-#include <gui/SensorManager.h>
-#include <gui/SensorEventQueue.h>
-#include <utils/Looper.h>
-
-using namespace android;
-
-static nsecs_t sStartTime = 0;
-
-
-int receiver(int fd, int events, void* data)
-{
-    sp<SensorEventQueue> q((SensorEventQueue*)data);
-    ssize_t n;
-    ASensorEvent buffer[8];
-
-    static nsecs_t oldTimeStamp = 0;
-
-    while ((n = q->read(buffer, 8)) > 0) {
-        for (int i=0 ; i<n ; i++) {
-            float t;
-            if (oldTimeStamp) {
-                t = float(buffer[i].timestamp - oldTimeStamp) / s2ns(1);
-            } else {
-                t = float(buffer[i].timestamp - sStartTime) / s2ns(1);
-            }
-            oldTimeStamp = buffer[i].timestamp;
-
-            if (buffer[i].type == Sensor::TYPE_ACCELEROMETER) {
-                printf("%lld\t%8f\t%8f\t%8f\t%f\n",
-                        buffer[i].timestamp,
-                        buffer[i].data[0], buffer[i].data[1], buffer[i].data[2],
-                        1.0/t);
-            }
-
-        }
-    }
-    if (n<0 && n != -EAGAIN) {
-        printf("error reading events (%s)\n", strerror(-n));
-    }
-    return 1;
-}
-
-
-int main(int argc, char** argv)
-{
-    SensorManager& mgr(SensorManager::getInstance());
-
-    Sensor const* const* list;
-    ssize_t count = mgr.getSensorList(&list);
-    printf("numSensors=%d\n", int(count));
-
-    sp<SensorEventQueue> q = mgr.createEventQueue();
-    printf("queue=%p\n", q.get());
-
-    Sensor const* accelerometer = mgr.getDefaultSensor(Sensor::TYPE_ACCELEROMETER);
-    printf("accelerometer=%p (%s)\n",
-            accelerometer, accelerometer->getName().string());
-
-    sStartTime = systemTime();
-
-    q->enableSensor(accelerometer);
-
-    q->setEventRate(accelerometer, ms2ns(10));
-
-    sp<Looper> loop = new Looper(false);
-    loop->addFd(q->getFd(), 0, ALOOPER_EVENT_INPUT, receiver, q.get());
-
-    do {
-        //printf("about to poll...\n");
-        int32_t ret = loop->pollOnce(-1);
-        switch (ret) {
-            case ALOOPER_POLL_WAKE:
-                //("ALOOPER_POLL_WAKE\n");
-                break;
-            case ALOOPER_POLL_CALLBACK:
-                //("ALOOPER_POLL_CALLBACK\n");
-                break;
-            case ALOOPER_POLL_TIMEOUT:
-                printf("ALOOPER_POLL_TIMEOUT\n");
-                break;
-            case ALOOPER_POLL_ERROR:
-                printf("ALOOPER_POLL_TIMEOUT\n");
-                break;
-            default:
-                printf("ugh? poll returned %d\n", ret);
-                break;
-        }
-    } while (1);
-
-
-    return 0;
-}
diff --git a/services/sensorservice/traits.h b/services/sensorservice/traits.h
deleted file mode 100644
index da4c599..0000000
--- a/services/sensorservice/traits.h
+++ /dev/null
@@ -1,118 +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.
- */
-
-#ifndef ANDROID_TRAITS_H
-#define ANDROID_TRAITS_H
-
-// -----------------------------------------------------------------------
-// Typelists
-
-namespace android {
-
-// end-of-list marker
-class NullType {};
-
-// type-list node
-template <typename T, typename U>
-struct TypeList {
-    typedef T Head;
-    typedef U Tail;
-};
-
-// helpers to build typelists
-#define TYPELIST_1(T1) TypeList<T1, NullType>
-#define TYPELIST_2(T1, T2) TypeList<T1, TYPELIST_1(T2)>
-#define TYPELIST_3(T1, T2, T3) TypeList<T1, TYPELIST_2(T2, T3)>
-#define TYPELIST_4(T1, T2, T3, T4) TypeList<T1, TYPELIST_3(T2, T3, T4)>
-
-// typelists algorithms
-namespace TL {
-template <typename TList, typename T> struct IndexOf;
-
-template <typename T>
-struct IndexOf<NullType, T> {
-    enum { value = -1 };
-};
-
-template <typename T, typename Tail>
-struct IndexOf<TypeList<T, Tail>, T> {
-    enum { value = 0 };
-};
-
-template <typename Head, typename Tail, typename T>
-struct IndexOf<TypeList<Head, Tail>, T> {
-private:
-    enum { temp = IndexOf<Tail, T>::value };
-public:
-    enum { value = temp == -1 ? -1 : 1 + temp };
-};
-
-}; // namespace TL
-
-// type selection based on a boolean
-template <bool flag, typename T, typename U>
-struct Select {
-    typedef T Result;
-};
-template <typename T, typename U>
-struct Select<false, T, U> {
-    typedef U Result;
-};
-
-// -----------------------------------------------------------------------
-// Type traits
-
-template <typename T>
-class TypeTraits {
-    typedef TYPELIST_4(
-            unsigned char, unsigned short,
-            unsigned int, unsigned long int) UnsignedInts;
-
-    typedef TYPELIST_4(
-            signed char, signed short,
-            signed int, signed long int) SignedInts;
-
-    typedef TYPELIST_1(
-            bool) OtherInts;
-
-    typedef TYPELIST_3(
-            float, double, long double) Floats;
-
-    template<typename U> struct PointerTraits {
-        enum { result = false };
-        typedef NullType PointeeType;
-    };
-    template<typename U> struct PointerTraits<U*> {
-        enum { result = true };
-        typedef U PointeeType;
-    };
-
-public:
-    enum { isStdUnsignedInt = TL::IndexOf<UnsignedInts, T>::value >= 0 };
-    enum { isStdSignedInt   = TL::IndexOf<SignedInts,   T>::value >= 0 };
-    enum { isStdIntegral    = TL::IndexOf<OtherInts,    T>::value >= 0 || isStdUnsignedInt || isStdSignedInt };
-    enum { isStdFloat       = TL::IndexOf<Floats,       T>::value >= 0 };
-    enum { isPointer        = PointerTraits<T>::result };
-    enum { isStdArith       = isStdIntegral || isStdFloat };
-
-    // best parameter type for given type
-    typedef typename Select<isStdArith || isPointer, T, const T&>::Result ParameterType;
-};
-
-// -----------------------------------------------------------------------
-}; // namespace android
-
-#endif /* ANDROID_TRAITS_H */
diff --git a/services/sensorservice/vec.h b/services/sensorservice/vec.h
deleted file mode 100644
index 24f30ff..0000000
--- a/services/sensorservice/vec.h
+++ /dev/null
@@ -1,438 +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.
- */
-
-#ifndef ANDROID_VEC_H
-#define ANDROID_VEC_H
-
-#include <math.h>
-
-#include <stdint.h>
-#include <stddef.h>
-
-#include "traits.h"
-
-// -----------------------------------------------------------------------
-
-#define PURE __attribute__((pure))
-
-namespace android {
-
-// -----------------------------------------------------------------------
-// non-inline helpers
-
-template <typename TYPE, size_t SIZE>
-class vec;
-
-template <typename TYPE, size_t SIZE>
-class vbase;
-
-namespace helpers {
-
-template <typename T> inline T min(T a, T b) { return a<b ? a : b; }
-template <typename T> inline T max(T a, T b) { return a>b ? a : b; }
-
-template < template<typename T, size_t S> class VEC,
-    typename TYPE, size_t SIZE, size_t S>
-vec<TYPE, SIZE>& doAssign(
-        vec<TYPE, SIZE>& lhs, const VEC<TYPE, S>& rhs) {
-    const size_t minSize = min(SIZE, S);
-    const size_t maxSize = max(SIZE, S);
-    for (size_t i=0 ; i<minSize ; i++)
-        lhs[i] = rhs[i];
-    for (size_t i=minSize ; i<maxSize ; i++)
-        lhs[i] = 0;
-    return lhs;
-}
-
-
-template <
-    template<typename T, size_t S> class VLHS,
-    template<typename T, size_t S> class VRHS,
-    typename TYPE,
-    size_t SIZE
->
-VLHS<TYPE, SIZE> PURE doAdd(
-        const VLHS<TYPE, SIZE>& lhs,
-        const VRHS<TYPE, SIZE>& rhs) {
-    VLHS<TYPE, SIZE> r;
-    for (size_t i=0 ; i<SIZE ; i++)
-        r[i] = lhs[i] + rhs[i];
-    return r;
-}
-
-template <
-    template<typename T, size_t S> class VLHS,
-    template<typename T, size_t S> class VRHS,
-    typename TYPE,
-    size_t SIZE
->
-VLHS<TYPE, SIZE> PURE doSub(
-        const VLHS<TYPE, SIZE>& lhs,
-        const VRHS<TYPE, SIZE>& rhs) {
-    VLHS<TYPE, SIZE> r;
-    for (size_t i=0 ; i<SIZE ; i++)
-        r[i] = lhs[i] - rhs[i];
-    return r;
-}
-
-template <
-    template<typename T, size_t S> class VEC,
-    typename TYPE,
-    size_t SIZE
->
-VEC<TYPE, SIZE> PURE doMulScalar(
-        const VEC<TYPE, SIZE>& lhs,
-        typename TypeTraits<TYPE>::ParameterType rhs) {
-    VEC<TYPE, SIZE> r;
-    for (size_t i=0 ; i<SIZE ; i++)
-        r[i] = lhs[i] * rhs;
-    return r;
-}
-
-template <
-    template<typename T, size_t S> class VEC,
-    typename TYPE,
-    size_t SIZE
->
-VEC<TYPE, SIZE> PURE doScalarMul(
-        typename TypeTraits<TYPE>::ParameterType lhs,
-        const VEC<TYPE, SIZE>& rhs) {
-    VEC<TYPE, SIZE> r;
-    for (size_t i=0 ; i<SIZE ; i++)
-        r[i] = lhs * rhs[i];
-    return r;
-}
-
-}; // namespace helpers
-
-// -----------------------------------------------------------------------
-// Below we define the mathematical operators for vectors.
-// We use template template arguments so we can generically
-// handle the case where the right-hand-size and left-hand-side are
-// different vector types (but with same value_type and size).
-// This is needed for performance when using ".xy{z}" element access
-// on vec<>. Without this, an extra conversion to vec<> would be needed.
-//
-// example:
-//      vec4_t a;
-//      vec3_t b;
-//      vec3_t c = a.xyz + b;
-//
-//  "a.xyz + b" is a mixed-operation between a vbase<> and a vec<>, requiring
-//  a conversion of vbase<> to vec<>. The template gunk below avoids this,
-// by allowing the addition on these different vector types directly
-//
-
-template <
-    template<typename T, size_t S> class VLHS,
-    template<typename T, size_t S> class VRHS,
-    typename TYPE,
-    size_t SIZE
->
-inline VLHS<TYPE, SIZE> PURE operator + (
-        const VLHS<TYPE, SIZE>& lhs,
-        const VRHS<TYPE, SIZE>& rhs) {
-    return helpers::doAdd(lhs, rhs);
-}
-
-template <
-    template<typename T, size_t S> class VLHS,
-    template<typename T, size_t S> class VRHS,
-    typename TYPE,
-    size_t SIZE
->
-inline VLHS<TYPE, SIZE> PURE operator - (
-        const VLHS<TYPE, SIZE>& lhs,
-        const VRHS<TYPE, SIZE>& rhs) {
-    return helpers::doSub(lhs, rhs);
-}
-
-template <
-    template<typename T, size_t S> class VEC,
-    typename TYPE,
-    size_t SIZE
->
-inline VEC<TYPE, SIZE> PURE operator * (
-        const VEC<TYPE, SIZE>& lhs,
-        typename TypeTraits<TYPE>::ParameterType rhs) {
-    return helpers::doMulScalar(lhs, rhs);
-}
-
-template <
-    template<typename T, size_t S> class VEC,
-    typename TYPE,
-    size_t SIZE
->
-inline VEC<TYPE, SIZE> PURE operator * (
-        typename TypeTraits<TYPE>::ParameterType lhs,
-        const VEC<TYPE, SIZE>& rhs) {
-    return helpers::doScalarMul(lhs, rhs);
-}
-
-
-template <
-    template<typename T, size_t S> class VLHS,
-    template<typename T, size_t S> class VRHS,
-    typename TYPE,
-    size_t SIZE
->
-TYPE PURE dot_product(
-        const VLHS<TYPE, SIZE>& lhs,
-        const VRHS<TYPE, SIZE>& rhs) {
-    TYPE r(0);
-    for (size_t i=0 ; i<SIZE ; i++)
-        r += lhs[i] * rhs[i];
-    return r;
-}
-
-template <
-    template<typename T, size_t S> class V,
-    typename TYPE,
-    size_t SIZE
->
-TYPE PURE length(const V<TYPE, SIZE>& v) {
-    return sqrt(dot_product(v, v));
-}
-
-template <
-    template<typename T, size_t S> class V,
-    typename TYPE,
-    size_t SIZE
->
-TYPE PURE length_squared(const V<TYPE, SIZE>& v) {
-    return dot_product(v, v);
-}
-
-template <
-    template<typename T, size_t S> class V,
-    typename TYPE,
-    size_t SIZE
->
-V<TYPE, SIZE> PURE normalize(const V<TYPE, SIZE>& v) {
-    return v * (1/length(v));
-}
-
-template <
-    template<typename T, size_t S> class VLHS,
-    template<typename T, size_t S> class VRHS,
-    typename TYPE
->
-VLHS<TYPE, 3> PURE cross_product(
-        const VLHS<TYPE, 3>& u,
-        const VRHS<TYPE, 3>& v) {
-    VLHS<TYPE, 3> r;
-    r.x = u.y*v.z - u.z*v.y;
-    r.y = u.z*v.x - u.x*v.z;
-    r.z = u.x*v.y - u.y*v.x;
-    return r;
-}
-
-
-template <typename TYPE, size_t SIZE>
-vec<TYPE, SIZE> PURE operator - (const vec<TYPE, SIZE>& lhs) {
-    vec<TYPE, SIZE> r;
-    for (size_t i=0 ; i<SIZE ; i++)
-        r[i] = -lhs[i];
-    return r;
-}
-
-// -----------------------------------------------------------------------
-
-// This our basic vector type, it just implements the data storage
-// and accessors.
-
-template <typename TYPE, size_t SIZE>
-struct vbase {
-    TYPE v[SIZE];
-    inline const TYPE& operator[](size_t i) const { return v[i]; }
-    inline       TYPE& operator[](size_t i)       { return v[i]; }
-};
-template<> struct vbase<float, 2> {
-    union {
-        float v[2];
-        struct { float x, y; };
-        struct { float s, t; };
-    };
-    inline const float& operator[](size_t i) const { return v[i]; }
-    inline       float& operator[](size_t i)       { return v[i]; }
-};
-template<> struct vbase<float, 3> {
-    union {
-        float v[3];
-        struct { float x, y, z; };
-        struct { float s, t, r; };
-        vbase<float, 2> xy;
-        vbase<float, 2> st;
-    };
-    inline const float& operator[](size_t i) const { return v[i]; }
-    inline       float& operator[](size_t i)       { return v[i]; }
-};
-template<> struct vbase<float, 4> {
-    union {
-        float v[4];
-        struct { float x, y, z, w; };
-        struct { float s, t, r, q; };
-        vbase<float, 3> xyz;
-        vbase<float, 3> str;
-        vbase<float, 2> xy;
-        vbase<float, 2> st;
-    };
-    inline const float& operator[](size_t i) const { return v[i]; }
-    inline       float& operator[](size_t i)       { return v[i]; }
-};
-
-// -----------------------------------------------------------------------
-
-template <typename TYPE, size_t SIZE>
-class vec : public vbase<TYPE, SIZE>
-{
-    typedef typename TypeTraits<TYPE>::ParameterType pTYPE;
-    typedef vbase<TYPE, SIZE> base;
-
-public:
-    // STL-like interface.
-    typedef TYPE value_type;
-    typedef TYPE& reference;
-    typedef TYPE const& const_reference;
-    typedef size_t size_type;
-
-    typedef TYPE* iterator;
-    typedef TYPE const* const_iterator;
-    iterator begin() { return base::v; }
-    iterator end() { return base::v + SIZE; }
-    const_iterator begin() const { return base::v; }
-    const_iterator end() const { return base::v + SIZE; }
-    size_type size() const { return SIZE; }
-
-    // -----------------------------------------------------------------------
-    // default constructors
-
-    vec() { }
-    vec(const vec& rhs)  : base(rhs) { }
-    vec(const base& rhs) : base(rhs) { }
-
-    // -----------------------------------------------------------------------
-    // conversion constructors
-
-    vec(pTYPE rhs) {
-        for (size_t i=0 ; i<SIZE ; i++)
-            base::operator[](i) = rhs;
-    }
-
-    template < template<typename T, size_t S> class VEC, size_t S>
-    explicit vec(const VEC<TYPE, S>& rhs) {
-        helpers::doAssign(*this, rhs);
-    }
-
-    explicit vec(TYPE const* array) {
-        for (size_t i=0 ; i<SIZE ; i++)
-            base::operator[](i) = array[i];
-    }
-
-    // -----------------------------------------------------------------------
-    // Assignment
-
-    vec& operator = (const vec& rhs) {
-        base::operator=(rhs);
-        return *this;
-    }
-
-    vec& operator = (const base& rhs) {
-        base::operator=(rhs);
-        return *this;
-    }
-
-    vec& operator = (pTYPE rhs) {
-        for (size_t i=0 ; i<SIZE ; i++)
-            base::operator[](i) = rhs;
-        return *this;
-    }
-
-    template < template<typename T, size_t S> class VEC, size_t S>
-    vec& operator = (const VEC<TYPE, S>& rhs) {
-        return helpers::doAssign(*this, rhs);
-    }
-
-    // -----------------------------------------------------------------------
-    // operation-assignment
-
-    vec& operator += (const vec& rhs);
-    vec& operator -= (const vec& rhs);
-    vec& operator *= (pTYPE rhs);
-
-    // -----------------------------------------------------------------------
-    // non-member function declaration and definition
-    // NOTE: we declare the non-member function as friend inside the class
-    // so that they are known to the compiler when the class is instantiated.
-    // This helps the compiler doing template argument deduction when the
-    // passed types are not identical. Essentially this helps with
-    // type conversion so that you can multiply a vec<float> by an scalar int
-    // (for instance).
-
-    friend inline vec PURE operator + (const vec& lhs, const vec& rhs) {
-        return helpers::doAdd(lhs, rhs);
-    }
-    friend inline vec PURE operator - (const vec& lhs, const vec& rhs) {
-        return helpers::doSub(lhs, rhs);
-    }
-    friend inline vec PURE operator * (const vec& lhs, pTYPE v) {
-        return helpers::doMulScalar(lhs, v);
-    }
-    friend inline vec PURE operator * (pTYPE v, const vec& rhs) {
-        return helpers::doScalarMul(v, rhs);
-    }
-    friend inline TYPE PURE dot_product(const vec& lhs, const vec& rhs) {
-        return android::dot_product(lhs, rhs);
-    }
-};
-
-// -----------------------------------------------------------------------
-
-template <typename TYPE, size_t SIZE>
-vec<TYPE, SIZE>& vec<TYPE, SIZE>::operator += (const vec<TYPE, SIZE>& rhs) {
-    vec<TYPE, SIZE>& lhs(*this);
-    for (size_t i=0 ; i<SIZE ; i++)
-        lhs[i] += rhs[i];
-    return lhs;
-}
-
-template <typename TYPE, size_t SIZE>
-vec<TYPE, SIZE>& vec<TYPE, SIZE>::operator -= (const vec<TYPE, SIZE>& rhs) {
-    vec<TYPE, SIZE>& lhs(*this);
-    for (size_t i=0 ; i<SIZE ; i++)
-        lhs[i] -= rhs[i];
-    return lhs;
-}
-
-template <typename TYPE, size_t SIZE>
-vec<TYPE, SIZE>& vec<TYPE, SIZE>::operator *= (vec<TYPE, SIZE>::pTYPE rhs) {
-    vec<TYPE, SIZE>& lhs(*this);
-    for (size_t i=0 ; i<SIZE ; i++)
-        lhs[i] *= rhs;
-    return lhs;
-}
-
-// -----------------------------------------------------------------------
-
-typedef vec<float, 2> vec2_t;
-typedef vec<float, 3> vec3_t;
-typedef vec<float, 4> vec4_t;
-
-// -----------------------------------------------------------------------
-
-}; // namespace android
-
-#endif /* ANDROID_VEC_H */
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 295f324..81a2c14 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -9,7 +9,8 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     easymocklib \
-    guava
+    guava \
+    littlemock
 
 LOCAL_JAVA_LIBRARIES := android.test.runner services
 
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 3f66de6..7848b1d 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -33,7 +33,9 @@
     <uses-permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING" />
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
-
+    <uses-permission android:name="android.permission.MANAGE_USERS" />
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+    
     <application>
         <uses-library android:name="android.test.runner" />
 
diff --git a/services/tests/servicestests/res/raw/test1.obb b/services/tests/servicestests/res/raw/test1.obb
new file mode 100644
index 0000000..7d2b4f6
--- /dev/null
+++ b/services/tests/servicestests/res/raw/test1.obb
Binary files differ
diff --git a/core/tests/coretests/res/raw/test1_nosig.obb b/services/tests/servicestests/res/raw/test1_nosig.obb
similarity index 100%
rename from core/tests/coretests/res/raw/test1_nosig.obb
rename to services/tests/servicestests/res/raw/test1_nosig.obb
Binary files differ
diff --git a/core/tests/coretests/res/raw/test1_wrongpackage.obb b/services/tests/servicestests/res/raw/test1_wrongpackage.obb
similarity index 100%
rename from core/tests/coretests/res/raw/test1_wrongpackage.obb
rename to services/tests/servicestests/res/raw/test1_wrongpackage.obb
Binary files differ
diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
index 46bcc4a..fd9fc98 100644
--- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
@@ -25,6 +25,7 @@
 import android.os.Message;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
@@ -98,7 +99,7 @@
         MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient();
 
         // invoke the method under test
-        final int stateFlagsDisabled = mManagerService.addClient(mockClient);
+        final int stateFlagsDisabled = mManagerService.addClient(mockClient, UserHandle.USER_OWNER);
         boolean enabledAccessibilityDisabled =
             (stateFlagsDisabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
 
@@ -110,7 +111,7 @@
         ensureAccessibilityEnabled(mContext, true);
 
         // invoke the method under test
-        final int stateFlagsEnabled = mManagerService.addClient(mockClient);
+        final int stateFlagsEnabled = mManagerService.addClient(mockClient, UserHandle.USER_OWNER);
         boolean enabledAccessibilityEnabled =
             (stateFlagsEnabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
 
@@ -129,7 +130,7 @@
         MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient();
 
         // invoke the method under test
-        final int stateFlagsEnabled = mManagerService.addClient(mockClient);
+        final int stateFlagsEnabled = mManagerService.addClient(mockClient, UserHandle.USER_OWNER);
         boolean enabledAccessibilityEnabled =
             (stateFlagsEnabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
 
@@ -141,7 +142,7 @@
         ensureAccessibilityEnabled(mContext, false);
 
         // invoke the method under test
-        final int stateFlagsDisabled = mManagerService.addClient(mockClient);
+        final int stateFlagsDisabled = mManagerService.addClient(mockClient, UserHandle.USER_OWNER);
         boolean enabledAccessibilityDisabled =
             (stateFlagsDisabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
 
@@ -160,7 +161,8 @@
         String secondMockServiceClassName = MySecondMockAccessibilityService.class.getName();
 
         // look for the two mock services
-        for (AccessibilityServiceInfo info : mManagerService.getInstalledAccessibilityServiceList()) {
+        for (AccessibilityServiceInfo info : mManagerService.getInstalledAccessibilityServiceList(
+                UserHandle.USER_OWNER)) {
             ServiceInfo serviceInfo = info.getResolveInfo().serviceInfo;
             if (packageName.equals(serviceInfo.packageName)) {
                 if (firstMockServiceClassName.equals(serviceInfo.name)) {
@@ -201,7 +203,7 @@
         service.replay();
 
         // send the event
-        mManagerService.sendAccessibilityEvent(sentEvent);
+        mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);
 
         // verify if all expected methods have been called
         assertMockServiceVerifiedWithinTimeout(service);
@@ -231,7 +233,7 @@
         service.replay();
 
         // send the event
-        mManagerService.sendAccessibilityEvent(sentEvent);
+        mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);
 
         // verify if all expected methods have been called
         assertMockServiceVerifiedWithinTimeout(service);
@@ -261,7 +263,7 @@
         service.replay();
 
         // send the event
-        mManagerService.sendAccessibilityEvent(sentEvent);
+        mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);
 
         // verify if all expected methods have been called
         assertMockServiceVerifiedWithinTimeout(service);
@@ -297,8 +299,8 @@
         service.replay();
 
         // send the events
-        mManagerService.sendAccessibilityEvent(firstEvent);
-        mManagerService.sendAccessibilityEvent(secondEvent);
+        mManagerService.sendAccessibilityEvent(firstEvent, UserHandle.USER_OWNER);
+        mManagerService.sendAccessibilityEvent(secondEvent, UserHandle.USER_OWNER);
 
         // wait for #sendAccessibilityEvent to reach the backing service
         Thread.sleep(TIMEOUT_BINDER_CALL);
@@ -354,7 +356,7 @@
         secondService.replay();
 
         // send the event
-        mManagerService.sendAccessibilityEvent(sentEvent);
+        mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);
 
         // verify if all expected methods have been called
         assertMockServiceVerifiedWithinTimeout(firstService);
@@ -393,7 +395,7 @@
         secondService.replay();
 
         // send the event
-        mManagerService.sendAccessibilityEvent(sentEvent);
+        mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);
 
         // verify if all expected methods have been called
         assertMockServiceVerifiedWithinTimeout(firstService);
@@ -434,7 +436,7 @@
         secondService.replay();
 
         // send the event
-        mManagerService.sendAccessibilityEvent(sentEvent);
+        mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);
 
         // verify if all expected methods have been called
         assertMockServiceVerifiedWithinTimeout(firstService);
@@ -477,7 +479,7 @@
         secondService.replay();
 
         // send the event
-        mManagerService.sendAccessibilityEvent(sentEvent);
+        mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);
 
         // verify if all expected methods have been called
         assertMockServiceVerifiedWithinTimeout(firstService);
@@ -512,7 +514,7 @@
         secondService.replay();
 
         // call the method under test
-        mManagerService.interrupt();
+        mManagerService.interrupt(UserHandle.USER_OWNER);
 
         // verify if all expected methods have been called
         assertMockServiceVerifiedWithinTimeout(firstService);
diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
index e083815..e7366ea 100644
--- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
@@ -26,7 +26,7 @@
 import org.easymock.IArgumentMatcher;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
-import android.content.pm.ServiceInfo;
+import android.os.UserHandle;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
@@ -70,14 +70,16 @@
 
         // configure the mock service behavior
         IAccessibilityManager mockServiceInterface = mMockServiceInterface;
-        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(
+        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(),
+                UserHandle.USER_OWNER)).andReturn(
                 AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
-        expect(mockServiceInterface.getInstalledAccessibilityServiceList()).andReturn(
-                expectedServices);
+        expect(mockServiceInterface.getInstalledAccessibilityServiceList(UserHandle.USER_OWNER))
+                .andReturn(expectedServices);
         replay(mockServiceInterface);
 
         // invoke the method under test
-        AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface);
+        AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface,
+                UserHandle.USER_OWNER);
         List<AccessibilityServiceInfo> receivedServices =
             manager.getInstalledAccessibilityServiceList();
 
@@ -92,13 +94,15 @@
     public void testInterrupt() throws Exception {
         // configure the mock service behavior
         IAccessibilityManager mockServiceInterface = mMockServiceInterface;
-        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(
-                AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
-        mockServiceInterface.interrupt();
+        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(),
+                UserHandle.USER_OWNER)).andReturn(
+                        AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
+        mockServiceInterface.interrupt(UserHandle.USER_OWNER);
         replay(mockServiceInterface);
 
         // invoke the method under test
-        AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface);
+        AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface,
+                UserHandle.USER_OWNER);
         manager.interrupt();
 
         // verify the mock service was properly called
@@ -109,12 +113,14 @@
     public void testIsEnabled() throws Exception {
         // configure the mock service behavior
         IAccessibilityManager mockServiceInterface = mMockServiceInterface;
-        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(
-                AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
+        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(),
+                UserHandle.USER_OWNER)).andReturn(
+                        AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
         replay(mockServiceInterface);
 
         // invoke the method under test
-        AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface);
+        AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface,
+                UserHandle.USER_OWNER);
         boolean isEnabledServiceEnabled = manager.isEnabled();
 
         // check expected result
@@ -144,16 +150,18 @@
 
         // configure the mock service behavior
         IAccessibilityManager mockServiceInterface = mMockServiceInterface;
-        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(
-                AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
-        expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent)))
-                .andReturn(true);
-        expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent)))
-                .andReturn(false);
+        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(),
+                UserHandle.USER_OWNER)).andReturn(
+                        AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
+        expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent),
+                UserHandle.USER_OWNER)).andReturn(true);
+        expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent),
+                UserHandle.USER_OWNER)).andReturn(false);
         replay(mockServiceInterface);
 
         // invoke the method under test (manager and service in different processes)
-        AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface);
+        AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface,
+                UserHandle.USER_OWNER);
         manager.sendAccessibilityEvent(sentEvent);
 
         // check expected result
@@ -180,11 +188,13 @@
 
         // configure the mock service behavior
         IAccessibilityManager mockServiceInterface = mMockServiceInterface;
-        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(0);
+        expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(),
+                UserHandle.USER_OWNER)).andReturn(0);
         replay(mockServiceInterface);
 
         // invoke the method under test (accessibility disabled)
-        AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface);
+        AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface,
+                UserHandle.USER_OWNER);
         try {
             manager.sendAccessibilityEvent(sentEvent);
             fail("No accessibility events are sent if accessibility is disabled");
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
new file mode 100644
index 0000000..93ea6a2
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -0,0 +1,224 @@
+/*
+ * 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;
+
+import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.ConnectivityManager.getNetworkTypeName;
+import static android.net.NetworkStateTracker.EVENT_STATE_CHANGED;
+import static com.google.testing.littlemock.LittleMock.anyInt;
+import static com.google.testing.littlemock.LittleMock.createCaptor;
+import static com.google.testing.littlemock.LittleMock.doNothing;
+import static com.google.testing.littlemock.LittleMock.doReturn;
+import static com.google.testing.littlemock.LittleMock.doThrow;
+import static com.google.testing.littlemock.LittleMock.eq;
+import static com.google.testing.littlemock.LittleMock.isA;
+import static com.google.testing.littlemock.LittleMock.mock;
+import static com.google.testing.littlemock.LittleMock.reset;
+import static com.google.testing.littlemock.LittleMock.verify;
+
+import android.content.Context;
+import android.net.INetworkPolicyManager;
+import android.net.INetworkStatsService;
+import android.net.LinkProperties;
+import android.net.NetworkConfig;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkStateTracker;
+import android.net.RouteInfo;
+import android.os.Handler;
+import android.os.INetworkManagementService;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.util.LogPrinter;
+
+import com.google.testing.littlemock.ArgumentCaptor;
+
+import java.net.InetAddress;
+import java.util.concurrent.Future;
+
+/**
+ * Tests for {@link ConnectivityService}.
+ */
+@LargeTest
+public class ConnectivityServiceTest extends AndroidTestCase {
+    private static final String TAG = "ConnectivityServiceTest";
+
+    private static final String MOBILE_IFACE = "rmnet3";
+    private static final String WIFI_IFACE = "wlan6";
+
+    private static final RouteInfo MOBILE_ROUTE_V4 = RouteInfo.makeHostRoute(parse("10.0.0.33"));
+    private static final RouteInfo MOBILE_ROUTE_V6 = RouteInfo.makeHostRoute(parse("fd00::33"));
+
+    private static final RouteInfo WIFI_ROUTE_V4 = RouteInfo.makeHostRoute(
+            parse("192.168.0.66"), parse("192.168.0.1"));
+    private static final RouteInfo WIFI_ROUTE_V6 = RouteInfo.makeHostRoute(
+            parse("fd00::66"), parse("fd00::"));
+
+    private INetworkManagementService mNetManager;
+    private INetworkStatsService mStatsService;
+    private INetworkPolicyManager mPolicyService;
+    private ConnectivityService.NetworkFactory mNetFactory;
+
+    private BroadcastInterceptingContext mServiceContext;
+    private ConnectivityService mService;
+
+    private MockNetwork mMobile;
+    private MockNetwork mWifi;
+
+    private Handler mTrackerHandler;
+
+    private static class MockNetwork {
+        public NetworkStateTracker tracker;
+        public NetworkInfo info;
+        public LinkProperties link;
+
+        public MockNetwork(int type) {
+            tracker = mock(NetworkStateTracker.class);
+            info = new NetworkInfo(type, -1, getNetworkTypeName(type), null);
+            link = new LinkProperties();
+        }
+
+        public void doReturnDefaults() {
+            // TODO: eventually CS should make defensive copies
+            doReturn(new NetworkInfo(info)).when(tracker).getNetworkInfo();
+            doReturn(new LinkProperties(link)).when(tracker).getLinkProperties();
+
+            // fallback to default TCP buffers
+            doReturn("").when(tracker).getTcpBufferSizesPropName();
+        }
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        mServiceContext = new BroadcastInterceptingContext(getContext());
+
+        mNetManager = mock(INetworkManagementService.class);
+        mStatsService = mock(INetworkStatsService.class);
+        mPolicyService = mock(INetworkPolicyManager.class);
+        mNetFactory = mock(ConnectivityService.NetworkFactory.class);
+
+        mMobile = new MockNetwork(TYPE_MOBILE);
+        mWifi = new MockNetwork(TYPE_WIFI);
+
+        // omit most network trackers
+        doThrow(new IllegalArgumentException("Not supported in test environment"))
+                .when(mNetFactory).createTracker(anyInt(), isA(NetworkConfig.class));
+
+        doReturn(mMobile.tracker)
+                .when(mNetFactory).createTracker(eq(TYPE_MOBILE), isA(NetworkConfig.class));
+        doReturn(mWifi.tracker)
+                .when(mNetFactory).createTracker(eq(TYPE_WIFI), isA(NetworkConfig.class));
+
+        final ArgumentCaptor<Handler> trackerHandler = createCaptor();
+        doNothing().when(mMobile.tracker)
+                .startMonitoring(isA(Context.class), trackerHandler.capture());
+
+        mService = new ConnectivityService(
+                mServiceContext, mNetManager, mStatsService, mPolicyService, mNetFactory);
+        mService.systemReady();
+
+        mTrackerHandler = trackerHandler.getValue();
+        mTrackerHandler.getLooper().setMessageLogging(new LogPrinter(Log.INFO, TAG));
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testMobileConnectedAddedRoutes() throws Exception {
+        Future<?> nextConnBroadcast;
+
+        // bring up mobile network
+        mMobile.info.setDetailedState(DetailedState.CONNECTED, null, null);
+        mMobile.link.setInterfaceName(MOBILE_IFACE);
+        mMobile.link.addRoute(MOBILE_ROUTE_V4);
+        mMobile.link.addRoute(MOBILE_ROUTE_V6);
+        mMobile.doReturnDefaults();
+
+        nextConnBroadcast = mServiceContext.nextBroadcastIntent(CONNECTIVITY_ACTION_IMMEDIATE);
+        mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget();
+        nextConnBroadcast.get();
+
+        // verify that both routes were added and DNS was flushed
+        verify(mNetManager).addRoute(eq(MOBILE_IFACE), eq(MOBILE_ROUTE_V4));
+        verify(mNetManager).addRoute(eq(MOBILE_IFACE), eq(MOBILE_ROUTE_V6));
+        verify(mNetManager).flushInterfaceDnsCache(MOBILE_IFACE);
+
+    }
+
+    public void testMobileWifiHandoff() throws Exception {
+        Future<?> nextConnBroadcast;
+
+        // bring up mobile network
+        mMobile.info.setDetailedState(DetailedState.CONNECTED, null, null);
+        mMobile.link.setInterfaceName(MOBILE_IFACE);
+        mMobile.link.addRoute(MOBILE_ROUTE_V4);
+        mMobile.link.addRoute(MOBILE_ROUTE_V6);
+        mMobile.doReturnDefaults();
+
+        nextConnBroadcast = mServiceContext.nextBroadcastIntent(CONNECTIVITY_ACTION_IMMEDIATE);
+        mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget();
+        nextConnBroadcast.get();
+
+        reset(mNetManager);
+
+        // now bring up wifi network
+        mWifi.info.setDetailedState(DetailedState.CONNECTED, null, null);
+        mWifi.link.setInterfaceName(WIFI_IFACE);
+        mWifi.link.addRoute(WIFI_ROUTE_V4);
+        mWifi.link.addRoute(WIFI_ROUTE_V6);
+        mWifi.doReturnDefaults();
+
+        // expect that mobile will be torn down
+        doReturn(true).when(mMobile.tracker).teardown();
+
+        nextConnBroadcast = mServiceContext.nextBroadcastIntent(CONNECTIVITY_ACTION_IMMEDIATE);
+        mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mWifi.info).sendToTarget();
+        nextConnBroadcast.get();
+
+        // verify that wifi routes added, and teardown requested
+        verify(mNetManager).addRoute(eq(WIFI_IFACE), eq(WIFI_ROUTE_V4));
+        verify(mNetManager).addRoute(eq(WIFI_IFACE), eq(WIFI_ROUTE_V6));
+        verify(mNetManager).flushInterfaceDnsCache(WIFI_IFACE);
+        verify(mMobile.tracker).teardown();
+
+        reset(mNetManager, mMobile.tracker);
+
+        // tear down mobile network, as requested
+        mMobile.info.setDetailedState(DetailedState.DISCONNECTED, null, null);
+        mMobile.link.clear();
+        mMobile.doReturnDefaults();
+
+        nextConnBroadcast = mServiceContext.nextBroadcastIntent(CONNECTIVITY_ACTION_IMMEDIATE);
+        mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget();
+        nextConnBroadcast.get();
+
+        verify(mNetManager).removeRoute(eq(MOBILE_IFACE), eq(MOBILE_ROUTE_V4));
+        verify(mNetManager).removeRoute(eq(MOBILE_IFACE), eq(MOBILE_ROUTE_V6));
+
+    }
+
+    private static InetAddress parse(String addr) {
+        return InetAddress.parseNumericAddress(addr);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/DropBoxTest.java b/services/tests/servicestests/src/com/android/server/DropBoxTest.java
index f3baff4..6ce0a48 100644
--- a/services/tests/servicestests/src/com/android/server/DropBoxTest.java
+++ b/services/tests/servicestests/src/com/android/server/DropBoxTest.java
@@ -45,10 +45,10 @@
 public class DropBoxTest extends AndroidTestCase {
     public void tearDown() throws Exception {
         ContentResolver cr = getContext().getContentResolver();
-        Settings.Secure.putString(cr, Settings.Secure.DROPBOX_AGE_SECONDS, "");
-        Settings.Secure.putString(cr, Settings.Secure.DROPBOX_MAX_FILES, "");
-        Settings.Secure.putString(cr, Settings.Secure.DROPBOX_QUOTA_KB, "");
-        Settings.Secure.putString(cr, Settings.Secure.DROPBOX_TAG_PREFIX + "DropBoxTest", "");
+        Settings.Global.putString(cr, Settings.Global.DROPBOX_AGE_SECONDS, "");
+        Settings.Global.putString(cr, Settings.Global.DROPBOX_MAX_FILES, "");
+        Settings.Global.putString(cr, Settings.Global.DROPBOX_QUOTA_KB, "");
+        Settings.Global.putString(cr, Settings.Global.DROPBOX_TAG_PREFIX + "DropBoxTest", "");
     }
 
     public void testAddText() throws Exception {
@@ -254,13 +254,13 @@
         assertTrue(dropbox.isTagEnabled("DropBoxTest"));
 
         ContentResolver cr = getContext().getContentResolver();
-        Settings.Secure.putString(cr, Settings.Secure.DROPBOX_TAG_PREFIX + "DropBoxTest",
+        Settings.Global.putString(cr, Settings.Global.DROPBOX_TAG_PREFIX + "DropBoxTest",
                                   "disabled");
 
         dropbox.addText("DropBoxTest", "TEST-DISABLED");
         assertFalse(dropbox.isTagEnabled("DropBoxTest"));
 
-        Settings.Secure.putString(cr, Settings.Secure.DROPBOX_TAG_PREFIX + "DropBoxTest",
+        Settings.Global.putString(cr, Settings.Global.DROPBOX_TAG_PREFIX + "DropBoxTest",
                                   "");
 
         dropbox.addText("DropBoxTest", "TEST-ENABLED-AGAIN");
@@ -330,7 +330,7 @@
         // Limit storage to 10 blocks
         int kb = blockSize * 10 / 1024;
         ContentResolver cr = getContext().getContentResolver();
-        Settings.Secure.putString(cr, Settings.Secure.DROPBOX_QUOTA_KB, Integer.toString(kb));
+        Settings.Global.putString(cr, Settings.Global.DROPBOX_QUOTA_KB, Integer.toString(kb));
 
         // Three tags using a total of 12 blocks:
         // DropBoxTest0 [ ][ ]
@@ -432,8 +432,8 @@
         // Limit storage to 10 blocks with an expiration of 1 second
         int kb = blockSize * 10 / 1024;
         ContentResolver cr = getContext().getContentResolver();
-        Settings.Secure.putString(cr, Settings.Secure.DROPBOX_AGE_SECONDS, "1");
-        Settings.Secure.putString(cr, Settings.Secure.DROPBOX_QUOTA_KB, Integer.toString(kb));
+        Settings.Global.putString(cr, Settings.Global.DROPBOX_AGE_SECONDS, "1");
+        Settings.Global.putString(cr, Settings.Global.DROPBOX_QUOTA_KB, Integer.toString(kb));
 
         // Write one normal entry and another so big that it is instantly tombstoned
         long before = System.currentTimeMillis();
@@ -497,7 +497,7 @@
 
         // Limit to 3 files and add one more entry
         ContentResolver cr = getContext().getContentResolver();
-        Settings.Secure.putString(cr, Settings.Secure.DROPBOX_MAX_FILES, "3");
+        Settings.Global.putString(cr, Settings.Global.DROPBOX_MAX_FILES, "3");
         dropbox.addText("DropBoxTest", "TEST6");
 
         // Verify only 3 files left
diff --git a/services/tests/servicestests/src/com/android/server/MountServiceTests.java b/services/tests/servicestests/src/com/android/server/MountServiceTests.java
new file mode 100644
index 0000000..9c88b40
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/MountServiceTests.java
@@ -0,0 +1,317 @@
+/*
+ * 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.
+ */
+
+package com.android.server;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+import android.os.FileUtils;
+import android.os.storage.OnObbStateChangeListener;
+import android.os.storage.StorageManager;
+import android.test.AndroidTestCase;
+import android.test.ComparisonFailure;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import static com.android.server.MountService.buildObbPath;
+
+import com.android.frameworks.servicestests.R;
+
+import java.io.File;
+import java.io.InputStream;
+
+public class MountServiceTests extends AndroidTestCase {
+    private static final String TAG = "MountServiceTests";
+
+    private static final long MAX_WAIT_TIME = 25*1000;
+    private static final long WAIT_TIME_INCR = 5*1000;
+
+    private static final String OBB_MOUNT_PREFIX = "/mnt/obb/";
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    private static void assertStartsWith(String message, String prefix, String actual) {
+        if (!actual.startsWith(prefix)) {
+            throw new ComparisonFailure(message, prefix, actual);
+        }
+    }
+
+    private static class ObbObserver extends OnObbStateChangeListener {
+        private String path;
+
+        public int state = -1;
+        boolean done = false;
+
+        @Override
+        public void onObbStateChange(String path, int state) {
+            Log.d(TAG, "Received message.  path=" + path + ", state=" + state);
+            synchronized (this) {
+                this.path = path;
+                this.state = state;
+                done = true;
+                notifyAll();
+            }
+        }
+
+        public String getPath() {
+            assertTrue("Expected ObbObserver to have received a state change.", done);
+            return path;
+        }
+
+        public int getState() {
+            assertTrue("Expected ObbObserver to have received a state change.", done);
+            return state;
+        }
+
+        public void reset() {
+            this.path = null;
+            this.state = -1;
+            done = false;
+        }
+
+        public boolean isDone() {
+            return done;
+        }
+
+        public boolean waitForCompletion() {
+            long waitTime = 0;
+            synchronized (this) {
+                while (!isDone() && waitTime < MAX_WAIT_TIME) {
+                    try {
+                        wait(WAIT_TIME_INCR);
+                        waitTime += WAIT_TIME_INCR;
+                    } catch (InterruptedException e) {
+                        Log.i(TAG, "Interrupted during sleep", e);
+                    }
+                }
+            }
+
+            return isDone();
+        }
+    }
+
+    private File getFilePath(String name) {
+        final File filesDir = mContext.getFilesDir();
+        final File outFile = new File(filesDir, name);
+        return outFile;
+    }
+
+    private void copyRawToFile(int rawResId, File outFile) {
+        Resources res = mContext.getResources();
+        InputStream is = null;
+        try {
+            is = res.openRawResource(rawResId);
+        } catch (NotFoundException e) {
+            fail("Failed to load resource with id: " + rawResId);
+        }
+        FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
+                | FileUtils.S_IRWXO, -1, -1);
+        assertTrue(FileUtils.copyToFile(is, outFile));
+        FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
+                | FileUtils.S_IRWXO, -1, -1);
+    }
+
+    private StorageManager getStorageManager() {
+        return (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE);
+    }
+
+    private void mountObb(StorageManager sm, final int resource, final File file,
+            int expectedState) {
+        copyRawToFile(resource, file);
+
+        final ObbObserver observer = new ObbObserver();
+        assertTrue("mountObb call on " + file.getPath() + " should succeed",
+                sm.mountObb(file.getPath(), null, observer));
+
+        assertTrue("Mount should have completed",
+                observer.waitForCompletion());
+
+        if (expectedState == OnObbStateChangeListener.MOUNTED) {
+            assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath()));
+        }
+
+        assertEquals("Actual file and resolved file should be the same",
+                file.getPath(), observer.getPath());
+
+        assertEquals(expectedState, observer.getState());
+    }
+
+    private ObbObserver mountObbWithoutWait(final StorageManager sm, final int resource,
+            final File file) {
+        copyRawToFile(resource, file);
+
+        final ObbObserver observer = new ObbObserver();
+        assertTrue("mountObb call on " + file.getPath() + " should succeed", sm.mountObb(file
+                .getPath(), null, observer));
+
+        return observer;
+    }
+
+    private void waitForObbActionCompletion(final StorageManager sm, final File file,
+            final ObbObserver observer, int expectedState, boolean checkPath) {
+        assertTrue("Mount should have completed", observer.waitForCompletion());
+
+        assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath()));
+
+        if (checkPath) {
+            assertEquals("Actual file and resolved file should be the same", file.getPath(),
+                    observer.getPath());
+        }
+
+        assertEquals(expectedState, observer.getState());
+    }
+
+    private String checkMountedPath(final StorageManager sm, final File file) {
+        final String mountPath = sm.getMountedObbPath(file.getPath());
+        assertStartsWith("Path should be in " + OBB_MOUNT_PREFIX,
+                OBB_MOUNT_PREFIX,
+                mountPath);
+        return mountPath;
+    }
+
+    private void unmountObb(final StorageManager sm, final File file, int expectedState) {
+        final ObbObserver observer = new ObbObserver();
+
+        assertTrue("unmountObb call on test1.obb should succeed",
+ sm.unmountObb(file.getPath(),
+                false, observer));
+
+        assertTrue("Unmount should have completed",
+                observer.waitForCompletion());
+
+        assertEquals(expectedState, observer.getState());
+
+        if (expectedState == OnObbStateChangeListener.UNMOUNTED) {
+            assertFalse("OBB should not be mounted", sm.isObbMounted(file.getPath()));
+        }
+    }
+
+    @LargeTest
+    public void testMountAndUnmountObbNormal() {
+        StorageManager sm = getStorageManager();
+
+        final File outFile = getFilePath("test1.obb");
+
+        mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.MOUNTED);
+
+        mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
+
+        final String mountPath = checkMountedPath(sm, outFile);
+        final File mountDir = new File(mountPath);
+
+        assertTrue("OBB mounted path should be a directory",
+                mountDir.isDirectory());
+
+        unmountObb(sm, outFile, OnObbStateChangeListener.UNMOUNTED);
+    }
+
+    @LargeTest
+    public void testAttemptMountNonObb() {
+        StorageManager sm = getStorageManager();
+
+        final File outFile = getFilePath("test1_nosig.obb");
+
+        mountObb(sm, R.raw.test1_nosig, outFile, OnObbStateChangeListener.ERROR_INTERNAL);
+
+        assertFalse("OBB should not be mounted",
+                sm.isObbMounted(outFile.getPath()));
+
+        assertNull("OBB's mounted path should be null",
+                sm.getMountedObbPath(outFile.getPath()));
+    }
+
+    @LargeTest
+    public void testAttemptMountObbWrongPackage() {
+        StorageManager sm = getStorageManager();
+
+        final File outFile = getFilePath("test1_wrongpackage.obb");
+
+        mountObb(sm, R.raw.test1_wrongpackage, outFile,
+                OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
+
+        assertFalse("OBB should not be mounted",
+                sm.isObbMounted(outFile.getPath()));
+
+        assertNull("OBB's mounted path should be null",
+                sm.getMountedObbPath(outFile.getPath()));
+    }
+
+    @LargeTest
+    public void testMountAndUnmountTwoObbs() {
+        StorageManager sm = getStorageManager();
+
+        final File file1 = getFilePath("test1.obb");
+        final File file2 = getFilePath("test2.obb");
+
+        ObbObserver oo1 = mountObbWithoutWait(sm, R.raw.test1, file1);
+        ObbObserver oo2 = mountObbWithoutWait(sm, R.raw.test1, file2);
+
+        Log.d(TAG, "Waiting for OBB #1 to complete mount");
+        waitForObbActionCompletion(sm, file1, oo1, OnObbStateChangeListener.MOUNTED, false);
+        Log.d(TAG, "Waiting for OBB #2 to complete mount");
+        waitForObbActionCompletion(sm, file2, oo2, OnObbStateChangeListener.MOUNTED, false);
+
+        final String mountPath1 = checkMountedPath(sm, file1);
+        final File mountDir1 = new File(mountPath1);
+        assertTrue("OBB mounted path should be a directory", mountDir1.isDirectory());
+
+        final String mountPath2 = checkMountedPath(sm, file2);
+        final File mountDir2 = new File(mountPath2);
+        assertTrue("OBB mounted path should be a directory", mountDir2.isDirectory());
+
+        unmountObb(sm, file1, OnObbStateChangeListener.UNMOUNTED);
+        unmountObb(sm, file2, OnObbStateChangeListener.UNMOUNTED);
+    }
+
+    public void testBuildObbPath() {
+        final int userId = 10;
+
+        // Paths outside external storage should remain untouched
+        assertEquals("/storage/random/foo",
+                buildObbPath("/storage/random/foo", userId, true));
+        assertEquals("/storage/random/foo",
+                buildObbPath("/storage/random/foo", userId, false));
+
+        // Paths on user-specific emulated storage
+        assertEquals("/mnt/shell/emulated/10/foo",
+                buildObbPath("/storage/emulated_legacy/foo", userId, true));
+        assertEquals("/storage/emulated/10/foo",
+                buildObbPath("/storage/emulated_legacy/foo", userId, false));
+        assertEquals("/mnt/shell/emulated/10/foo",
+                buildObbPath("/storage/emulated/10/foo", userId, true));
+        assertEquals("/storage/emulated/10/foo",
+                buildObbPath("/storage/emulated/10/foo", userId, false));
+
+        // Paths on shared OBB emulated storage
+        assertEquals("/mnt/shell/emulated/obb/foo",
+                buildObbPath("/storage/emulated_legacy/Android/obb/foo", userId, true));
+        assertEquals("/storage/emulated/0/Android/obb/foo",
+                buildObbPath("/storage/emulated_legacy/Android/obb/foo", userId, false));
+        assertEquals("/mnt/shell/emulated/obb/foo",
+                buildObbPath("/storage/emulated/10/Android/obb/foo", userId, true));
+        assertEquals("/storage/emulated/0/Android/obb/foo",
+                buildObbPath("/storage/emulated/10/Android/obb/foo", userId, false));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index c23e868..167b6c2 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -54,7 +54,6 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.Signature;
-import android.content.pm.UserInfo;
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
 import android.net.INetworkManagementEventObserver;
@@ -71,7 +70,7 @@
 import android.os.INetworkManagementService;
 import android.os.IPowerManager;
 import android.os.MessageQueue.IdleHandler;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.test.AndroidTestCase;
 import android.test.mock.MockPackageManager;
 import android.test.suitebuilder.annotation.LargeTest;
@@ -87,9 +86,7 @@
 import org.easymock.IAnswer;
 
 import java.io.File;
-import java.util.ArrayList;
 import java.util.LinkedHashSet;
-import java.util.List;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
@@ -133,15 +130,12 @@
     private long mElapsedRealtime;
 
     private static final int USER_ID = 0;
-    private static final int USER_ID_GUEST = 1;
 
     private static final int APP_ID_A = android.os.Process.FIRST_APPLICATION_UID + 800;
     private static final int APP_ID_B = android.os.Process.FIRST_APPLICATION_UID + 801;
 
-    private static final int UID_A = UserId.getUid(USER_ID, APP_ID_A);
-    private static final int UID_B = UserId.getUid(USER_ID, APP_ID_B);
-    private static final int UID_A_GUEST = UserId.getUid(USER_ID_GUEST, APP_ID_A);
-    private static final int UID_B_GUEST = UserId.getUid(USER_ID_GUEST, APP_ID_B);
+    private static final int UID_A = UserHandle.getUid(USER_ID, APP_ID_A);
+    private static final int UID_B = UserHandle.getUid(USER_ID, APP_ID_B);
 
     private static final int PID_1 = 400;
     private static final int PID_2 = 401;
@@ -176,13 +170,6 @@
                         return info;
                     }
 
-                    @Override
-                    public List<UserInfo> getUsers() {
-                        final ArrayList<UserInfo> users = new ArrayList<UserInfo>();
-                        users.add(new UserInfo(USER_ID, "Primary", UserInfo.FLAG_PRIMARY));
-                        users.add(new UserInfo(USER_ID_GUEST, "Guest", 0));
-                        return users;
-                    }
                 };
             }
 
@@ -265,13 +252,13 @@
 
     @Suppress
     public void testPolicyChangeTriggersBroadcast() throws Exception {
-        mService.setAppPolicy(APP_ID_A, POLICY_NONE);
+        mService.setUidPolicy(APP_ID_A, POLICY_NONE);
 
         // change background policy and expect broadcast
         final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent(
                 ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
 
-        mService.setAppPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
+        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
 
         backgroundChanged.get();
     }
@@ -325,7 +312,6 @@
 
     public void testScreenChangesRules() throws Exception {
         Future<Void> future;
-        Future<Void> futureGuest;
 
         expectSetUidNetworkRules(UID_A, false);
         expectSetUidForeground(UID_A, true);
@@ -338,14 +324,10 @@
         // push strict policy for foreground uid, verify ALLOW rule
         expectSetUidNetworkRules(UID_A, false);
         expectSetUidForeground(UID_A, true);
-        expectSetUidNetworkRules(UID_A_GUEST, true);
-        expectSetUidForeground(UID_A_GUEST, false);
         future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
-        futureGuest = expectRulesChanged(UID_A_GUEST, RULE_REJECT_METERED);
         replay();
-        mService.setAppPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
+        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
         future.get();
-        futureGuest.get();
         verifyAndReset();
 
         // now turn screen off and verify REJECT rule
@@ -371,7 +353,6 @@
 
     public void testPolicyNone() throws Exception {
         Future<Void> future;
-        Future<Void> futureGuest;
 
         expectSetUidNetworkRules(UID_A, false);
         expectSetUidForeground(UID_A, true);
@@ -384,14 +365,10 @@
         // POLICY_NONE should RULE_ALLOW in foreground
         expectSetUidNetworkRules(UID_A, false);
         expectSetUidForeground(UID_A, true);
-        expectSetUidNetworkRules(UID_A_GUEST, false);
-        expectSetUidForeground(UID_A_GUEST, false);
         future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
-        futureGuest = expectRulesChanged(UID_A_GUEST, RULE_ALLOW_ALL);
         replay();
-        mService.setAppPolicy(APP_ID_A, POLICY_NONE);
+        mService.setUidPolicy(APP_ID_A, POLICY_NONE);
         future.get();
-        futureGuest.get();
         verifyAndReset();
 
         // POLICY_NONE should RULE_ALLOW in background
@@ -406,19 +383,14 @@
 
     public void testPolicyReject() throws Exception {
         Future<Void> future;
-        Future<Void> futureGuest;
 
         // POLICY_REJECT should RULE_ALLOW in background
         expectSetUidNetworkRules(UID_A, true);
         expectSetUidForeground(UID_A, false);
-        expectSetUidNetworkRules(UID_A_GUEST, true);
-        expectSetUidForeground(UID_A_GUEST, false);
         future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
-        futureGuest = expectRulesChanged(UID_A_GUEST, RULE_REJECT_METERED);
         replay();
-        mService.setAppPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
+        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
         future.get();
-        futureGuest.get();
         verifyAndReset();
 
         // POLICY_REJECT should RULE_ALLOW in foreground
@@ -442,46 +414,33 @@
 
     public void testPolicyRejectAddRemove() throws Exception {
         Future<Void> future;
-        Future<Void> futureGuest;
 
         // POLICY_NONE should have RULE_ALLOW in background
         expectSetUidNetworkRules(UID_A, false);
         expectSetUidForeground(UID_A, false);
-        expectSetUidNetworkRules(UID_A_GUEST, false);
-        expectSetUidForeground(UID_A_GUEST, false);
         future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
-        futureGuest = expectRulesChanged(UID_A_GUEST, RULE_ALLOW_ALL);
         replay();
         mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
-        mService.setAppPolicy(APP_ID_A, POLICY_NONE);
+        mService.setUidPolicy(APP_ID_A, POLICY_NONE);
         future.get();
-        futureGuest.get();
         verifyAndReset();
 
         // adding POLICY_REJECT should cause RULE_REJECT
         expectSetUidNetworkRules(UID_A, true);
         expectSetUidForeground(UID_A, false);
-        expectSetUidNetworkRules(UID_A_GUEST, true);
-        expectSetUidForeground(UID_A_GUEST, false);
         future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
-        futureGuest = expectRulesChanged(UID_A_GUEST, RULE_REJECT_METERED);
         replay();
-        mService.setAppPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
+        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
         future.get();
-        futureGuest.get();
         verifyAndReset();
 
         // removing POLICY_REJECT should return us to RULE_ALLOW
         expectSetUidNetworkRules(UID_A, false);
         expectSetUidForeground(UID_A, false);
-        expectSetUidNetworkRules(UID_A_GUEST, false);
-        expectSetUidForeground(UID_A_GUEST, false);
         future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
-        futureGuest = expectRulesChanged(UID_A_GUEST, RULE_ALLOW_ALL);
         replay();
-        mService.setAppPolicy(APP_ID_A, POLICY_NONE);
+        mService.setUidPolicy(APP_ID_A, POLICY_NONE);
         future.get();
-        futureGuest.get();
         verifyAndReset();
     }
 
@@ -652,34 +611,25 @@
 
     public void testUidRemovedPolicyCleared() throws Exception {
         Future<Void> future;
-        Future<Void> futureGuest;
 
         // POLICY_REJECT should RULE_REJECT in background
         expectSetUidNetworkRules(UID_A, true);
         expectSetUidForeground(UID_A, false);
-        expectSetUidNetworkRules(UID_A_GUEST, true);
-        expectSetUidForeground(UID_A_GUEST, false);
         future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
-        futureGuest = expectRulesChanged(UID_A_GUEST, RULE_REJECT_METERED);
         replay();
-        mService.setAppPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
+        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
         future.get();
-        futureGuest.get();
         verifyAndReset();
 
         // uninstall should clear RULE_REJECT
         expectSetUidNetworkRules(UID_A, false);
         expectSetUidForeground(UID_A, false);
-        expectSetUidNetworkRules(UID_A_GUEST, false);
-        expectSetUidForeground(UID_A_GUEST, false);
         future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
-        futureGuest = expectRulesChanged(UID_A_GUEST, RULE_ALLOW_ALL);
         replay();
         final Intent intent = new Intent(ACTION_UID_REMOVED);
         intent.putExtra(EXTRA_UID, UID_A);
         mServiceContext.sendBroadcast(intent);
         future.get();
-        futureGuest.get();
         verifyAndReset();
     }
 
@@ -887,7 +837,8 @@
 
     private Future<Void> expectClearNotifications() throws Exception {
         final FutureAnswer future = new FutureAnswer();
-        mNotifManager.cancelNotificationWithTag(isA(String.class), isA(String.class), anyInt());
+        mNotifManager.cancelNotificationWithTag(
+                isA(String.class), isA(String.class), anyInt(), anyInt());
         expectLastCall().andAnswer(future).anyTimes();
         return future;
     }
@@ -895,7 +846,7 @@
     private Future<String> expectEnqueueNotification() throws Exception {
         final FutureCapture<String> tag = new FutureCapture<String>();
         mNotifManager.enqueueNotificationWithTag(isA(String.class), capture(tag.capture), anyInt(),
-                isA(Notification.class), isA(int[].class));
+                isA(Notification.class), isA(int[].class), UserHandle.myUserId());
         return tag;
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
index afa0eec..569acee 100644
--- a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
@@ -242,9 +242,9 @@
      */
     public void setThrottlePolicy(long thresholdBytes, int valueKbitps, int resetDay) {
         final ContentResolver resolver = getContext().getContentResolver();
-        Settings.Secure.putLong(resolver, Settings.Secure.THROTTLE_THRESHOLD_BYTES, thresholdBytes);
-        Settings.Secure.putInt(resolver, Settings.Secure.THROTTLE_VALUE_KBITSPS, valueKbitps);
-        Settings.Secure.putInt(resolver, Settings.Secure.THROTTLE_RESET_DAY, resetDay);
+        Settings.Global.putLong(resolver, Settings.Global.THROTTLE_THRESHOLD_BYTES, thresholdBytes);
+        Settings.Global.putInt(resolver, Settings.Global.THROTTLE_VALUE_KBITSPS, valueKbitps);
+        Settings.Global.putInt(resolver, Settings.Global.THROTTLE_RESET_DAY, resetDay);
     }
 
     /**
@@ -252,9 +252,9 @@
      */
     public void clearThrottlePolicy() {
         final ContentResolver resolver = getContext().getContentResolver();
-        Settings.Secure.putString(resolver, Settings.Secure.THROTTLE_THRESHOLD_BYTES, null);
-        Settings.Secure.putString(resolver, Settings.Secure.THROTTLE_VALUE_KBITSPS, null);
-        Settings.Secure.putString(resolver, Settings.Secure.THROTTLE_RESET_DAY, null);
+        Settings.Global.putString(resolver, Settings.Global.THROTTLE_THRESHOLD_BYTES, null);
+        Settings.Global.putString(resolver, Settings.Global.THROTTLE_VALUE_KBITSPS, null);
+        Settings.Global.putString(resolver, Settings.Global.THROTTLE_RESET_DAY, null);
     }
 
     /**
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 796372d..5f93e6f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -138,7 +138,7 @@
 
         // Write the package files and make sure they're parsed properly the first time
         writeOldFiles();
-        Settings settings = new Settings(getContext().getFilesDir());
+        Settings settings = new Settings(getContext(), getContext().getFilesDir());
         assertEquals(true, settings.readLPw(null));
         assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_3));
         assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_1));
@@ -156,11 +156,11 @@
     public void testNewPackageRestrictionsFile() {
         // Write the package files and make sure they're parsed properly the first time
         writeOldFiles();
-        Settings settings = new Settings(getContext().getFilesDir());
+        Settings settings = new Settings(getContext(), getContext().getFilesDir());
         assertEquals(true, settings.readLPw(null));
 
         // Create Settings again to make it read from the new files
-        settings = new Settings(getContext().getFilesDir());
+        settings = new Settings(getContext(), getContext().getFilesDir());
         assertEquals(true, settings.readLPw(null));
 
         PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_2);
@@ -171,7 +171,7 @@
     public void testEnableDisable() {
         // Write the package files and make sure they're parsed properly the first time
         writeOldFiles();
-        Settings settings = new Settings(getContext().getFilesDir());
+        Settings settings = new Settings(getContext(), getContext().getFilesDir());
         assertEquals(true, settings.readLPw(null));
 
         // Enable/Disable a package
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index d736ac1..1758d93 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -16,35 +16,37 @@
 
 package com.android.server.pm;
 
-import com.android.server.pm.UserManager;
-
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.UserInfo;
 import android.os.Debug;
 import android.os.Environment;
+import android.os.UserManager;
 import android.test.AndroidTestCase;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /** Test {@link UserManager} functionality. */
 public class UserManagerTest extends AndroidTestCase {
 
     UserManager mUserManager = null;
+    Object mUserLock = new Object();
 
     @Override
     public void setUp() throws Exception {
-        mUserManager = new UserManager(Environment.getExternalStorageDirectory(),
-                Environment.getExternalStorageDirectory());
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        List<UserInfo> users = mUserManager.getUsers();
-        // Remove all except the primary user
-        for (UserInfo user : users) {
-            if (!user.isPrimary()) {
-                mUserManager.removeUser(user.id);
+        mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
+        IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
+        getContext().registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                synchronized (mUserLock) {
+                    mUserLock.notifyAll();
+                }
             }
-        }
+        }, filter);
     }
 
     public void testHasPrimary() throws Exception {
@@ -52,12 +54,10 @@
     }
 
     public void testAddUser() throws Exception {
-        final UserManager details = mUserManager;
-
-        UserInfo userInfo = details.createUser("Guest 1", UserInfo.FLAG_GUEST);
+        UserInfo userInfo = mUserManager.createUser("Guest 1", UserInfo.FLAG_GUEST);
         assertTrue(userInfo != null);
 
-        List<UserInfo> list = details.getUsers();
+        List<UserInfo> list = mUserManager.getUsers();
         boolean found = false;
         for (UserInfo user : list) {
             if (user.id == userInfo.id && user.name.equals("Guest 1")
@@ -68,13 +68,12 @@
             }
         }
         assertTrue(found);
+        removeUser(userInfo.id);
     }
 
     public void testAdd2Users() throws Exception {
-        final UserManager details = mUserManager;
-
-        UserInfo user1 = details.createUser("Guest 1", UserInfo.FLAG_GUEST);
-        UserInfo user2 = details.createUser("User 2", UserInfo.FLAG_ADMIN);
+        UserInfo user1 = mUserManager.createUser("Guest 1", UserInfo.FLAG_GUEST);
+        UserInfo user2 = mUserManager.createUser("User 2", UserInfo.FLAG_ADMIN);
 
         assertTrue(user1 != null);
         assertTrue(user2 != null);
@@ -82,14 +81,13 @@
         assertTrue(findUser(0));
         assertTrue(findUser(user1.id));
         assertTrue(findUser(user2.id));
+        removeUser(user1.id);
+        removeUser(user2.id);
     }
 
     public void testRemoveUser() throws Exception {
-        final UserManager details = mUserManager;
-
-        UserInfo userInfo = details.createUser("Guest 1", UserInfo.FLAG_GUEST);
-
-        details.removeUser(userInfo.id);
+        UserInfo userInfo = mUserManager.createUser("Guest 1", UserInfo.FLAG_GUEST);
+        removeUser(userInfo.id);
 
         assertFalse(findUser(userInfo.id));
     }
@@ -104,4 +102,53 @@
         }
         return false;
     }
+
+    public void testSerialNumber() {
+        UserInfo user1 = mUserManager.createUser("User 1", UserInfo.FLAG_RESTRICTED);
+        int serialNumber1 = user1.serialNumber;
+        assertEquals(serialNumber1, mUserManager.getUserSerialNumber(user1.id));
+        assertEquals(user1.id, mUserManager.getUserHandle(serialNumber1));
+        removeUser(user1.id);
+        UserInfo user2 = mUserManager.createUser("User 2", UserInfo.FLAG_RESTRICTED);
+        int serialNumber2 = user2.serialNumber;
+        assertFalse(serialNumber1 == serialNumber2);
+        assertEquals(serialNumber2, mUserManager.getUserSerialNumber(user2.id));
+        assertEquals(user2.id, mUserManager.getUserHandle(serialNumber2));
+        removeUser(user2.id);
+    }
+
+    public void testMaxUsers() {
+        int N = UserManager.getMaxSupportedUsers();
+        int count = mUserManager.getUsers().size();
+        List<UserInfo> created = new ArrayList<UserInfo>();
+        // Create as many users as permitted and make sure creation passes
+        while (count < N) {
+            UserInfo ui = mUserManager.createUser("User " + count, 0);
+            assertNotNull(ui);
+            created.add(ui);
+            count++;
+        }
+        // Try to create one more user and make sure it fails
+        UserInfo extra = null;
+        assertNull(extra = mUserManager.createUser("One more", 0));
+        if (extra != null) {
+            removeUser(extra.id);
+        }
+        while (!created.isEmpty()) {
+            UserInfo user = created.remove(0);
+            removeUser(user.id);
+        }
+    }
+
+    private void removeUser(int userId) {
+        synchronized (mUserLock) {
+            mUserManager.removeUser(userId);
+            while (mUserManager.getUserInfo(userId) != null) {
+                try {
+                    mUserLock.wait(1000);
+                } catch (InterruptedException ie) {
+                }
+            }
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/updates/CertPinInstallReceiverTest.java b/services/tests/servicestests/src/com/android/server/updates/CertPinInstallReceiverTest.java
new file mode 100644
index 0000000..b6742a1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/updates/CertPinInstallReceiverTest.java
@@ -0,0 +1,243 @@
+/*
+ * 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.updates;
+
+import android.content.Context;
+import android.content.Intent;
+import android.test.AndroidTestCase;
+import android.provider.Settings;
+import android.util.Base64;
+import android.util.Log;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.cert.CertificateFactory;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.KeyFactory;
+import java.util.HashSet;
+import java.io.*;
+import libcore.io.IoUtils;
+
+/**
+ * Tests for {@link com.android.server.CertPinInstallReceiver}
+ */
+public class CertPinInstallReceiverTest extends AndroidTestCase {
+
+    private static final String TAG = "CertPinInstallReceiverTest";
+
+    private static final String PINLIST_ROOT = System.getenv("ANDROID_DATA") + "/misc/keychain/";
+
+    public static final String PINLIST_CONTENT_PATH = PINLIST_ROOT + "pins";
+    public static final String PINLIST_METADATA_PATH = PINLIST_CONTENT_PATH + "metadata";
+
+    public static final String PINLIST_CONTENT_URL_KEY = "pinlist_content_url";
+    public static final String PINLIST_METADATA_URL_KEY = "pinlist_metadata_url";
+    public static final String PINLIST_CERTIFICATE_KEY = "config_update_certificate";
+    public static final String PINLIST_VERSION_KEY = "pinlist_version";
+
+    private static final String EXTRA_CONTENT_PATH = "CONTENT_PATH";
+    private static final String EXTRA_REQUIRED_HASH = "REQUIRED_HASH";
+    private static final String EXTRA_SIGNATURE = "SIGNATURE";
+    private static final String EXTRA_VERSION_NUMBER = "VERSION";
+
+    public static final String TEST_CERT = "" +
+                    "MIIDsjCCAxugAwIBAgIJAPLf2gS0zYGUMA0GCSqGSIb3DQEBBQUAMIGYMQswCQYDVQQGEwJVUzET" +
+                    "MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEPMA0GA1UEChMGR29v" +
+                    "Z2xlMRAwDgYDVQQLEwd0ZXN0aW5nMRYwFAYDVQQDEw1HZXJlbXkgQ29uZHJhMSEwHwYJKoZIhvcN" +
+                    "AQkBFhJnY29uZHJhQGdvb2dsZS5jb20wHhcNMTIwNzE0MTc1MjIxWhcNMTIwODEzMTc1MjIxWjCB" +
+                    "mDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZp" +
+                    "ZXcxDzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMHdGVzdGluZzEWMBQGA1UEAxMNR2VyZW15IENv" +
+                    "bmRyYTEhMB8GCSqGSIb3DQEJARYSZ2NvbmRyYUBnb29nbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUA" +
+                    "A4GNADCBiQKBgQCjGGHATBYlmas+0sEECkno8LZ1KPglb/mfe6VpCT3GhSr+7br7NG/ZwGZnEhLq" +
+                    "E7YIH4fxltHmQC3Tz+jM1YN+kMaQgRRjo/LBCJdOKaMwUbkVynAH6OYsKevjrOPk8lfM5SFQzJMG" +
+                    "sA9+Tfopr5xg0BwZ1vA/+E3mE7Tr3M2UvwIDAQABo4IBADCB/TAdBgNVHQ4EFgQUhzkS9E6G+x8W" +
+                    "L4EsmRjDxu28tHUwgc0GA1UdIwSBxTCBwoAUhzkS9E6G+x8WL4EsmRjDxu28tHWhgZ6kgZswgZgx" +
+                    "CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3" +
+                    "MQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB3Rlc3RpbmcxFjAUBgNVBAMTDUdlcmVteSBDb25k" +
+                    "cmExITAfBgkqhkiG9w0BCQEWEmdjb25kcmFAZ29vZ2xlLmNvbYIJAPLf2gS0zYGUMAwGA1UdEwQF" +
+                    "MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAYiugFDmbDOQ2U/+mqNt7o8ftlEo9SJrns6O8uTtK6AvR" +
+                    "orDrR1AXTXkuxwLSbmVfedMGOZy7Awh7iZa8hw5x9XmUudfNxvmrKVEwGQY2DZ9PXbrnta/dwbhK" +
+                    "mWfoepESVbo7CKIhJp8gRW0h1Z55ETXD57aGJRvQS4pxkP8ANhM=";
+
+
+    public static final String TEST_KEY = "" +
+                    "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKMYYcBMFiWZqz7SwQQKSejwtnUo" +
+                    "+CVv+Z97pWkJPcaFKv7tuvs0b9nAZmcSEuoTtggfh/GW0eZALdPP6MzVg36QxpCBFGOj8sEIl04p" +
+                    "ozBRuRXKcAfo5iwp6+Os4+TyV8zlIVDMkwawD35N+imvnGDQHBnW8D/4TeYTtOvczZS/AgMBAAEC" +
+                    "gYBxwFalNSwZK3WJipq+g6KLCiBn1JxGGDQlLKrweFaSuFyFky9fd3IvkIabirqQchD612sMb+GT" +
+                    "0t1jptW6z4w2w6++IW0A3apDOCwoD+uvDBXrbFqI0VbyAWUNqHVdaFFIRk2IHGEE6463mGRdmILX" +
+                    "IlCd/85RTHReg4rl/GFqWQJBANgLAIR4pWbl5Gm+DtY18wp6Q3pJAAMkmP/lISCBIidu1zcqYIKt" +
+                    "PoDW4Knq9xnhxPbXrXKv4YzZWHBK8GkKhQ0CQQDBQnXufQcMew+PwiS0oJvS+eQ6YJwynuqG2ejg" +
+                    "WE+T7489jKtscRATpUXpZUYmDLGg9bLt7L62hFvFSj2LO2X7AkBcdrD9AWnBFWlh/G77LVHczSEu" +
+                    "KCoyLiqxcs5vy/TjLaQ8vw1ZQG580/qJnr+tOxyCjSJ18GK3VppsTRaBznfNAkB3nuCKNp9HTWCL" +
+                    "dfrsRsFMrFpk++mSt6SoxXaMbn0LL2u1CD4PCEiQMGt+lK3/3TmRTKNs+23sYS7Ahjxj0udDAkEA" +
+                    "p57Nj65WNaWeYiOfTwKXkLj8l29H5NbaGWxPT0XkWr4PvBOFZVH/wj0/qc3CMVGnv11+DyO+QUCN" +
+                    "SqBB5aRe8g==";
+
+    private void overrideSettings(String key, String value) throws Exception {
+        assertTrue(Settings.Secure.putString(mContext.getContentResolver(), key, value));
+        Thread.sleep(1000);
+    }
+
+    private void overrideCert(String value) throws Exception {
+        overrideSettings(PINLIST_CERTIFICATE_KEY, value);
+    }
+
+    private String readPins() throws Exception {
+        return IoUtils.readFileAsString(PINLIST_CONTENT_PATH);
+    }
+
+    private String readCurrentVersion() throws Exception {
+        return IoUtils.readFileAsString("/data/misc/keychain/metadata/version");
+    }
+
+    private String getNextVersion() throws Exception {
+        int currentVersion = Integer.parseInt(readCurrentVersion());
+        return Integer.toString(currentVersion + 1);
+    }
+
+    private static String getCurrentHash(String content) throws Exception {
+        if (content == null) {
+            return "0";
+        }
+        MessageDigest dgst = MessageDigest.getInstance("SHA512");
+        byte[] encoded = content.getBytes();
+        byte[] fingerprint = dgst.digest(encoded);
+        return IntegralToString.bytesToHexString(fingerprint, false);
+    }
+
+    private static String getHashOfCurrentContent() throws Exception {
+        String content = IoUtils.readFileAsString("/data/misc/keychain/pins");
+        return getCurrentHash(content);
+    }
+
+    private PrivateKey createKey() throws Exception {
+        byte[] derKey = Base64.decode(TEST_KEY.getBytes(), Base64.DEFAULT);
+        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(derKey);
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        return (PrivateKey) keyFactory.generatePrivate(keySpec);
+    }
+
+    private X509Certificate createCertificate() throws Exception {
+        byte[] derCert = Base64.decode(TEST_CERT.getBytes(), Base64.DEFAULT);
+        InputStream istream = new ByteArrayInputStream(derCert);
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        return (X509Certificate) cf.generateCertificate(istream);
+    }
+
+    private String makeTemporaryContentFile(String content) throws Exception {
+        FileOutputStream fw = mContext.openFileOutput("content.txt", mContext.MODE_WORLD_READABLE);
+        fw.write(content.getBytes(), 0, content.length());
+        fw.close();
+        return mContext.getFilesDir() + "/content.txt";
+    }
+
+    private String createSignature(String content, String version, String requiredHash)
+                                   throws Exception {
+        Signature signer = Signature.getInstance("SHA512withRSA");
+        signer.initSign(createKey());
+        signer.update(content.trim().getBytes());
+        signer.update(version.trim().getBytes());
+        signer.update(requiredHash.getBytes());
+        String sig = new String(Base64.encode(signer.sign(), Base64.DEFAULT));
+        assertEquals(true,
+                     verifySignature(content, version, requiredHash, sig, createCertificate()));
+        return sig;
+    }
+
+    public boolean verifySignature(String content, String version, String requiredPrevious,
+                                   String signature, X509Certificate cert) throws Exception {
+        Signature signer = Signature.getInstance("SHA512withRSA");
+        signer.initVerify(cert);
+        signer.update(content.trim().getBytes());
+        signer.update(version.trim().getBytes());
+        signer.update(requiredPrevious.trim().getBytes());
+        return signer.verify(Base64.decode(signature.getBytes(), Base64.DEFAULT));
+    }
+
+    private void sendIntent(String contentPath, String version, String required, String sig) {
+        Intent i = new Intent();
+        i.setAction("android.intent.action.UPDATE_PINS");
+        i.putExtra(EXTRA_CONTENT_PATH, contentPath);
+        i.putExtra(EXTRA_VERSION_NUMBER, version);
+        i.putExtra(EXTRA_REQUIRED_HASH, required);
+        i.putExtra(EXTRA_SIGNATURE, sig);
+        mContext.sendBroadcast(i);
+    }
+
+    private String runTest(String cert, String content, String version, String required, String sig)
+                           throws Exception {
+        Log.e(TAG, "started test");
+        overrideCert(cert);
+        String contentPath = makeTemporaryContentFile(content);
+        sendIntent(contentPath, version, required, sig);
+        Thread.sleep(1000);
+        return readPins();
+    }
+
+    private String runTestWithoutSig(String cert, String content, String version, String required)
+                                     throws Exception {
+        String sig = createSignature(content, version, required);
+        return runTest(cert, content, version, required, sig);
+    }
+
+    public void testOverwritePinlist() throws Exception {
+        Log.e(TAG, "started testOverwritePinList");
+        assertEquals("abcde", runTestWithoutSig(TEST_CERT, "abcde", getNextVersion(), getHashOfCurrentContent()));
+        Log.e(TAG, "started testOverwritePinList");
+    }
+
+   public void testBadSignatureFails() throws Exception {
+        Log.e(TAG, "started testOverwritePinList");
+        String text = "blahblah";
+        runTestWithoutSig(TEST_CERT, text, getNextVersion(), getHashOfCurrentContent());
+        assertEquals(text, runTest(TEST_CERT, "bcdef", getNextVersion(), getCurrentHash(text), ""));
+        Log.e(TAG, "started testOverwritePinList");
+    }
+
+    public void testBadRequiredHashFails() throws Exception {
+        runTestWithoutSig(TEST_CERT, "blahblahblah", getNextVersion(), getHashOfCurrentContent());
+        assertEquals("blahblahblah", runTestWithoutSig(TEST_CERT, "cdefg", getNextVersion(), "0"));
+        Log.e(TAG, "started testOverwritePinList");
+    }
+
+    public void testBadVersionFails() throws Exception {
+        String text = "blahblahblahblah";
+        String version = getNextVersion();
+        runTestWithoutSig(TEST_CERT, text, version, getHashOfCurrentContent());
+        assertEquals(text, runTestWithoutSig(TEST_CERT, "defgh", version, getCurrentHash(text)));
+        Log.e(TAG, "started testOverwritePinList");
+    }
+
+    public void testOverrideRequiredHash() throws Exception {
+        runTestWithoutSig(TEST_CERT, "blahblahblah", getNextVersion(), getHashOfCurrentContent());
+        assertEquals("blahblahblah", runTestWithoutSig(TEST_CERT, "cdefg", "NONE", "0"));
+        Log.e(TAG, "started testOverwritePinList");
+    }
+
+}
diff --git a/telephony/java/android/telephony/CdmaCellIdentity.java b/telephony/java/android/telephony/CdmaCellIdentity.java
deleted file mode 100644
index 5b8454f..0000000
--- a/telephony/java/android/telephony/CdmaCellIdentity.java
+++ /dev/null
@@ -1,164 +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.
- */
-
-package android.telephony;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * CellIdentity is to represent a unique CDMA cell
- *
- * @hide pending API review
- */
-public final class CdmaCellIdentity extends CellIdentity implements Parcelable {
-    // Network Id 0..65535
-    private final int mNetworkId;
-    // CDMA System Id 0..32767
-    private final int mSystemId;
-    // Base Station Id 0..65535
-    private final int mBasestationId;
-    /**
-     * Longitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
-     * It is represented in units of 0.25 seconds and ranges from -2592000
-     * to 2592000, both values inclusive (corresponding to a range of -180
-     * to +180 degrees).
-     */
-    private final int mLongitude;
-    /**
-     * Latitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
-     * It is represented in units of 0.25 seconds and ranges from -1296000
-     * to 1296000, both values inclusive (corresponding to a range of -90
-     * to +90 degrees).
-     */
-    private final int mLatitude;
-
-    /**
-     * public constructor
-     * @param nid Network Id 0..65535
-     * @param sid CDMA System Id 0..32767
-     * @param bid Base Station Id 0..65535
-     * @param lon Longitude is a decimal number ranges from -2592000
-     *        to 2592000
-     * @param lat Latitude is a decimal number ranges from -1296000
-     *        to 1296000
-     * @param attr is comma separated “key=value” attribute pairs.
-     */
-    public CdmaCellIdentity (int nid, int sid,
-            int bid, int lon, int lat, String attr) {
-        super(CELLID_TYPE_CDMA, attr);
-        mNetworkId = nid;
-        mSystemId = sid;
-        mBasestationId = bid;
-        mLongitude = lon;
-        mLatitude = lat;
-    }
-
-    private CdmaCellIdentity(Parcel in) {
-        super(in);
-        mNetworkId = in.readInt();
-        mSystemId = in.readInt();
-        mBasestationId = in.readInt();
-        mLongitude = in.readInt();
-        mLatitude = in.readInt();
-    }
-
-    CdmaCellIdentity(CdmaCellIdentity cid) {
-        super(cid);
-        mNetworkId = cid.mNetworkId;
-        mSystemId = cid.mSystemId;
-        mBasestationId = cid.mBasestationId;
-        mLongitude = cid.mLongitude;
-        mLatitude = cid.mLatitude;
-    }
-
-    /**
-     * @return Network Id 0..65535
-     */
-    public int getNetworkId() {
-        return mNetworkId;
-    }
-
-    /**
-     * @return System Id 0..32767
-     */
-    public int getSystemId() {
-        return mSystemId;
-    }
-
-    /**
-     * @return Base Station Id 0..65535
-     */
-    public int getBasestationId() {
-        return mBasestationId;
-    }
-
-    /**
-     * @return Base station longitude, which is a decimal number as
-     * specified in 3GPP2 C.S0005-A v6.0. It is represented in units
-     * of 0.25 seconds and ranges from -2592000 to 2592000, both
-     * values inclusive (corresponding to a range of -180
-     * to +180 degrees).
-     */
-    public int getLongitude() {
-        return mLongitude;
-    }
-
-    /**
-     * @return Base station
-     */
-    /**
-     * @return Base station latitude, which is a decimal number as
-     * specified in 3GPP2 C.S0005-A v6.0. It is represented in units
-     * of 0.25 seconds and ranges from -1296000 to 1296000, both
-     * values inclusive (corresponding to a range of -90
-     * to +90 degrees).
-     */
-    public int getLatitude() {
-        return mLatitude;
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
-        dest.writeInt(mNetworkId);
-        dest.writeInt(mSystemId);
-        dest.writeInt(mBasestationId);
-        dest.writeInt(mLongitude);
-        dest.writeInt(mLatitude);
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    public static final Creator<CdmaCellIdentity> CREATOR =
-            new Creator<CdmaCellIdentity>() {
-        @Override
-        public CdmaCellIdentity createFromParcel(Parcel in) {
-            return new CdmaCellIdentity(in);
-        }
-
-        @Override
-        public CdmaCellIdentity[] newArray(int size) {
-            return new CdmaCellIdentity[size];
-        }
-    };
-}
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
deleted file mode 100644
index 65c220f..0000000
--- a/telephony/java/android/telephony/CellIdentity.java
+++ /dev/null
@@ -1,89 +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.
- */
-
-package android.telephony;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * CellIdentity is to represent ONE unique cell in the world
- * it contains all levels of info to identity country, carrier, etc.
- *
- * @hide pending API review
- */
-public abstract class CellIdentity implements Parcelable {
-
-    // Cell is a GSM Cell {@link GsmCellIdentity}
-    public static final int CELLID_TYPE_GSM = 1;
-    // Cell is a CMDA Cell {@link CdmaCellIdentity}
-    public static final int CELLID_TYPE_CDMA = 2;
-    // Cell is a LTE Cell {@link LteCellIdentity}
-    public static final int CELLID_TYPE_LTE = 3;
-
-    private int mCellIdType;
-    private String mCellIdAttributes;
-
-    protected CellIdentity(int type, String attr) {
-        this.mCellIdType = type;
-        this.mCellIdAttributes = new String(attr);
-    }
-
-    protected CellIdentity(Parcel in) {
-        this.mCellIdType = in.readInt();
-        this.mCellIdAttributes = new String(in.readString());
-    }
-
-    protected CellIdentity(CellIdentity cid) {
-        this.mCellIdType = cid.mCellIdType;
-        this.mCellIdAttributes = new String(cid.mCellIdAttributes);
-    }
-
-    /**
-     * @return Cell Identity type as one of CELLID_TYPE_XXXX
-     */
-    public int getCellIdType() {
-        return mCellIdType;
-    }
-
-
-    /**
-     * @return Cell identity attribute pairs
-     * Comma separated “key=value” pairs.
-     *   key := must must an single alpha-numeric word
-     *   value := “quoted value string”
-     *
-     * Current list of keys and values:
-     *   type = fixed | mobile
-     */
-    public String getCellIdAttributes() {
-        return mCellIdAttributes;
-    }
-
-
-    /** Implement the Parcelable interface {@hide} */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mCellIdType);
-        dest.writeString(mCellIdAttributes);
-    }
-}
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
new file mode 100644
index 0000000..9579b91
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -0,0 +1,224 @@
+/*
+ * 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * CellIdentity is to represent a unique CDMA cell
+ */
+public final class CellIdentityCdma implements Parcelable {
+
+    private static final String LOG_TAG = "CellSignalStrengthCdma";
+    private static final boolean DBG = false;
+
+    // Network Id 0..65535
+    private final int mNetworkId;
+    // CDMA System Id 0..32767
+    private final int mSystemId;
+    // Base Station Id 0..65535
+    private final int mBasestationId;
+    /**
+     * Longitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
+     * It is represented in units of 0.25 seconds and ranges from -2592000
+     * to 2592000, both values inclusive (corresponding to a range of -180
+     * to +180 degrees).
+     */
+    private final int mLongitude;
+    /**
+     * Latitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
+     * It is represented in units of 0.25 seconds and ranges from -1296000
+     * to 1296000, both values inclusive (corresponding to a range of -90
+     * to +90 degrees).
+     */
+    private final int mLatitude;
+
+    /**
+     * @hide
+     */
+    public CellIdentityCdma() {
+        mNetworkId = Integer.MAX_VALUE;
+        mSystemId = Integer.MAX_VALUE;
+        mBasestationId = Integer.MAX_VALUE;
+        mLongitude = Integer.MAX_VALUE;
+        mLatitude = Integer.MAX_VALUE;
+    }
+
+    /**
+     * public constructor
+     * @param nid Network Id 0..65535
+     * @param sid CDMA System Id 0..32767
+     * @param bid Base Station Id 0..65535
+     * @param lon Longitude is a decimal number ranges from -2592000
+     *        to 2592000
+     * @param lat Latitude is a decimal number ranges from -1296000
+     *        to 1296000
+     *
+     * @hide
+     */
+    public CellIdentityCdma (int nid, int sid, int bid, int lon, int lat) {
+        mNetworkId = nid;
+        mSystemId = sid;
+        mBasestationId = bid;
+        mLongitude = lon;
+        mLatitude = lat;
+    }
+
+    private CellIdentityCdma(CellIdentityCdma cid) {
+        mNetworkId = cid.mNetworkId;
+        mSystemId = cid.mSystemId;
+        mBasestationId = cid.mBasestationId;
+        mLongitude = cid.mLongitude;
+        mLatitude = cid.mLatitude;
+    }
+
+    CellIdentityCdma copy() {
+        return new CellIdentityCdma(this);
+    }
+
+    /**
+     * @return Network Id 0..65535
+     */
+    public int getNetworkId() {
+        return mNetworkId;
+    }
+
+    /**
+     * @return System Id 0..32767
+     */
+    public int getSystemId() {
+        return mSystemId;
+    }
+
+    /**
+     * @return Base Station Id 0..65535
+     */
+    public int getBasestationId() {
+        return mBasestationId;
+    }
+
+    /**
+     * @return Base station longitude, which is a decimal number as
+     * specified in 3GPP2 C.S0005-A v6.0. It is represented in units
+     * of 0.25 seconds and ranges from -2592000 to 2592000, both
+     * values inclusive (corresponding to a range of -180
+     * to +180 degrees).
+     */
+    public int getLongitude() {
+        return mLongitude;
+    }
+
+    /**
+     * @return Base station latitude, which is a decimal number as
+     * specified in 3GPP2 C.S0005-A v6.0. It is represented in units
+     * of 0.25 seconds and ranges from -1296000 to 1296000, both
+     * values inclusive (corresponding to a range of -90
+     * to +90 degrees).
+     */
+    public int getLatitude() {
+        return mLatitude;
+    }
+
+    @Override
+    public int hashCode() {
+        int primeNum = 31;
+        return (mNetworkId * primeNum) + (mSystemId * primeNum) + (mBasestationId * primeNum) +
+                (mLatitude * primeNum) + (mLongitude * primeNum);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (super.equals(other)) {
+            try {
+                CellIdentityCdma o = (CellIdentityCdma)other;
+                return mNetworkId == o.mNetworkId &&
+                        mSystemId == o.mSystemId &&
+                        mBasestationId == o.mBasestationId &&
+                        mLatitude == o.mLatitude &&
+                        mLongitude == o.mLongitude;
+            } catch (ClassCastException e) {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("CdmaCellIdentitiy:");
+        sb.append(super.toString());
+        sb.append(" mNetworkId="); sb.append(mNetworkId);
+        sb.append(" mSystemId="); sb.append(mSystemId);
+        sb.append(" mBasestationId="); sb.append(mBasestationId);
+        sb.append(" mLongitude="); sb.append(mLongitude);
+        sb.append(" mLatitude="); sb.append(mLatitude);
+
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        dest.writeInt(mNetworkId);
+        dest.writeInt(mSystemId);
+        dest.writeInt(mBasestationId);
+        dest.writeInt(mLongitude);
+        dest.writeInt(mLatitude);
+    }
+
+    /** Construct from Parcel, type has already been processed */
+    private CellIdentityCdma(Parcel in) {
+        mNetworkId = in.readInt();
+        mSystemId = in.readInt();
+        mBasestationId = in.readInt();
+        mLongitude = in.readInt();
+        mLatitude = in.readInt();
+        if (DBG) log("CellIdentityCdma(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    @SuppressWarnings("hiding")
+    public static final Creator<CellIdentityCdma> CREATOR =
+            new Creator<CellIdentityCdma>() {
+        @Override
+        public CellIdentityCdma createFromParcel(Parcel in) {
+            return new CellIdentityCdma(in);
+        }
+
+        @Override
+        public CellIdentityCdma[] newArray(int size) {
+            return new CellIdentityCdma[size];
+        }
+    };
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
new file mode 100644
index 0000000..21cb790
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -0,0 +1,209 @@
+/*
+ * 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * CellIdentity to represent a unique GSM or UMTS cell
+ */
+public final class CellIdentityGsm implements Parcelable {
+
+    private static final String LOG_TAG = "CellIdentityGsm";
+    private static final boolean DBG = false;
+
+    // 3-digit Mobile Country Code, 0..999
+    private final int mMcc;
+    // 2 or 3-digit Mobile Network Code, 0..999
+    private final int mMnc;
+    // 16-bit Location Area Code, 0..65535
+    private final int mLac;
+    // 16-bit GSM Cell Identity described in TS 27.007, 0..65535
+    // 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455
+    private final int mCid;
+    // 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511
+    private final int mPsc;
+
+    /**
+     * @hide
+     */
+    public CellIdentityGsm() {
+        mMcc = Integer.MAX_VALUE;
+        mMnc = Integer.MAX_VALUE;
+        mLac = Integer.MAX_VALUE;
+        mCid = Integer.MAX_VALUE;
+        mPsc = Integer.MAX_VALUE;
+    }
+    /**
+     * public constructor
+     * @param mcc 3-digit Mobile Country Code, 0..999
+     * @param mnc 2 or 3-digit Mobile Network Code, 0..999
+     * @param lac 16-bit Location Area Code, 0..65535
+     * @param cid 16-bit GSM Cell Identity or 28-bit UMTS Cell Identity
+     * @param psc 9-bit UMTS Primary Scrambling Code
+     *
+     * @hide
+     */
+    public CellIdentityGsm (int mcc, int mnc, int lac, int cid, int psc) {
+        mMcc = mcc;
+        mMnc = mnc;
+        mLac = lac;
+        mCid = cid;
+        mPsc = psc;
+    }
+
+    private CellIdentityGsm(CellIdentityGsm cid) {
+        mMcc = cid.mMcc;
+        mMnc = cid.mMnc;
+        mLac = cid.mLac;
+        mCid = cid.mCid;
+        mPsc = cid.mPsc;
+    }
+
+    CellIdentityGsm copy() {
+       return new CellIdentityGsm(this);
+    }
+
+    /**
+     * @return 3-digit Mobile Country Code, 0..999
+     */
+    public int getMcc() {
+        return mMcc;
+    }
+
+    /**
+     * @return 2 or 3-digit Mobile Network Code, 0..999
+     */
+    public int getMnc() {
+        return mMnc;
+    }
+
+    /**
+     * @return 16-bit Location Area Code, 0..65535
+     */
+    public int getLac() {
+        return mLac;
+    }
+
+    /**
+     * @return CID
+     * Either 16-bit GSM Cell Identity described
+     * in TS 27.007, 0..65535
+     * or 28-bit UMTS Cell Identity described
+     * in TS 25.331, 0..268435455
+     */
+    public int getCid() {
+        return mCid;
+    }
+
+    /**
+     * @return 9-bit UMTS Primary Scrambling Code described in
+     * TS 25.331, 0..511
+     */
+    public int getPsc() {
+        return mPsc;
+    }
+
+    @Override
+    public int hashCode() {
+        int primeNum = 31;
+        return (mMcc * primeNum) + (mMnc * primeNum) + (mLac * primeNum) + (mCid * primeNum) +
+                (mPsc * primeNum);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (super.equals(other)) {
+            try {
+                CellIdentityGsm o = (CellIdentityGsm)other;
+                return mMcc == o.mMcc &&
+                        mMnc == o.mMnc &&
+                        mLac == o.mLac &&
+                        mCid == o.mCid &&
+                        mPsc == o.mPsc;
+            } catch (ClassCastException e) {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("GsmCellIdentitiy:");
+        sb.append(super.toString());
+        sb.append(" mMcc=").append(mMcc);
+        sb.append(" mMnc=").append(mMcc);
+        sb.append(" mLac=").append(mLac);
+        sb.append(" mCid=").append(mCid);
+        sb.append(" mPsc=").append(mPsc);
+
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        dest.writeInt(mMcc);
+        dest.writeInt(mMnc);
+        dest.writeInt(mLac);
+        dest.writeInt(mCid);
+        dest.writeInt(mPsc);
+    }
+
+    /** Construct from Parcel, type has already been processed */
+    private CellIdentityGsm(Parcel in) {
+        mMcc = in.readInt();
+        mMnc = in.readInt();
+        mLac = in.readInt();
+        mCid = in.readInt();
+        mPsc = in.readInt();
+        if (DBG) log("CellIdentityGsm(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    @SuppressWarnings("hiding")
+    public static final Creator<CellIdentityGsm> CREATOR =
+            new Creator<CellIdentityGsm>() {
+        @Override
+        public CellIdentityGsm createFromParcel(Parcel in) {
+            return new CellIdentityGsm(in);
+        }
+
+        @Override
+        public CellIdentityGsm[] newArray(int size) {
+            return new CellIdentityGsm[size];
+        }
+    };
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
new file mode 100644
index 0000000..ad822bb
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -0,0 +1,204 @@
+/*
+ * 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * CellIdentity is to represent a unique LTE cell
+ */
+public final class CellIdentityLte implements Parcelable {
+
+    private static final String LOG_TAG = "CellIdentityLte";
+    private static final boolean DBG = false;
+
+    // 3-digit Mobile Country Code, 0..999
+    private final int mMcc;
+    // 2 or 3-digit Mobile Network Code, 0..999
+    private final int mMnc;
+    // 28-bit cell identity
+    private final int mCi;
+    // physical cell id 0..503
+    private final int mPci;
+    // 16-bit tracking area code
+    private final int mTac;
+
+    /**
+     * @hide
+     */
+    public CellIdentityLte() {
+        mMcc = Integer.MAX_VALUE;
+        mMnc = Integer.MAX_VALUE;
+        mCi = Integer.MAX_VALUE;
+        mPci = Integer.MAX_VALUE;
+        mTac = Integer.MAX_VALUE;
+    }
+
+    /**
+     *
+     * @param mcc 3-digit Mobile Country Code, 0..999
+     * @param mnc 2 or 3-digit Mobile Network Code, 0..999
+     * @param ci 28-bit Cell Identity
+     * @param pci Physical Cell Id 0..503
+     * @param tac 16-bit Tracking Area Code
+     *
+     * @hide
+     */
+    public CellIdentityLte (int mcc, int mnc, int ci, int pci, int tac) {
+        mMcc = mcc;
+        mMnc = mnc;
+        mCi = ci;
+        mPci = pci;
+        mTac = tac;
+    }
+
+    private CellIdentityLte(CellIdentityLte cid) {
+        mMcc = cid.mMcc;
+        mMnc = cid.mMnc;
+        mCi = cid.mCi;
+        mPci = cid.mPci;
+        mTac = cid.mTac;
+    }
+
+    CellIdentityLte copy() {
+        return new CellIdentityLte(this);
+    }
+
+    /**
+     * @return 3-digit Mobile Country Code, 0..999
+     */
+    public int getMcc() {
+        return mMcc;
+    }
+
+    /**
+     * @return 2 or 3-digit Mobile Network Code, 0..999
+     */
+    public int getMnc() {
+        return mMnc;
+    }
+
+    /**
+     * @return 28-bit Cell Identity
+     */
+    public int getCi() {
+        return mCi;
+    }
+
+    /**
+     * @return Physical Cell Id 0..503
+     */
+    public int getPci() {
+        return mPci;
+    }
+
+    /**
+     * @return 16-bit Tracking Area Code
+     */
+    public int getTac() {
+        return mTac;
+    }
+
+    @Override
+    public int hashCode() {
+        int primeNum = 31;
+        return (mMcc * primeNum) + (mMnc * primeNum) + (mCi * primeNum) + (mPci * primeNum) +
+                (mTac * primeNum);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (super.equals(other)) {
+            try {
+                CellIdentityLte o = (CellIdentityLte)other;
+                return mMcc == o.mMcc &&
+                        mMnc == o.mMnc &&
+                        mCi == o.mCi &&
+                        mPci == o.mCi &&
+                        mTac == o.mTac;
+            } catch (ClassCastException e) {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("LteCellIdentitiy:");
+        sb.append(super.toString());
+        sb.append(" mMcc="); sb.append(mMcc);
+        sb.append(" mMnc="); sb.append(mMnc);
+        sb.append(" mCi="); sb.append(mCi);
+        sb.append(" mPci="); sb.append(mPci);
+        sb.append(" mTac="); sb.append(mTac);
+
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        dest.writeInt(mMcc);
+        dest.writeInt(mMnc);
+        dest.writeInt(mCi);
+        dest.writeInt(mPci);
+        dest.writeInt(mTac);
+    }
+
+    /** Construct from Parcel, type has already been processed */
+    private CellIdentityLte(Parcel in) {
+        mMcc = in.readInt();
+        mMnc = in.readInt();
+        mCi = in.readInt();
+        mPci = in.readInt();
+        mTac = in.readInt();
+        if (DBG) log("CellIdentityLte(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    @SuppressWarnings("hiding")
+    public static final Creator<CellIdentityLte> CREATOR =
+            new Creator<CellIdentityLte>() {
+        @Override
+        public CellIdentityLte createFromParcel(Parcel in) {
+            return new CellIdentityLte(in);
+        }
+
+        @Override
+        public CellIdentityLte[] newArray(int size) {
+            return new CellIdentityLte[size];
+        }
+    };
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index 9bea30c..f367f99 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 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.
@@ -20,194 +20,189 @@
 import android.os.Parcelable;
 
 /**
- * Represent one snapshot observation of one cell info
- * which contains the time of observation.
- *
- * @hide Pending API review
+ * Immutable cell information from a point in time.
  */
-public final class CellInfo implements Parcelable {
+public abstract class CellInfo implements Parcelable {
+
+    // Type fields for parceling
+    /** @hide */
+    protected static final int TYPE_GSM = 1;
+    /** @hide */
+    protected static final int TYPE_CDMA = 2;
+    /** @hide */
+    protected static final int TYPE_LTE = 3;
+
     // Type to distinguish where time stamp gets recorded.
-    public static final int CELL_INFO_TIMESTAMP_TYPE_UNKNOWN = 0;
-    public static final int CELL_INFO_TIMESTAMP_TYPE_ANTENNA = 1;
-    public static final int CELL_INFO_TIMESTAMP_TYPE_MODEM = 2;
-    public static final int CELL_INFO_TIMESTAMP_TYPE_OEM_RIL = 3;
-    public static final int CELL_INFO_TIMESTAMP_TYPE_JAVA_RIL = 4;
+
+    /** @hide */
+    public static final int TIMESTAMP_TYPE_UNKNOWN = 0;
+    /** @hide */
+    public static final int TIMESTAMP_TYPE_ANTENNA = 1;
+    /** @hide */
+    public static final int TIMESTAMP_TYPE_MODEM = 2;
+    /** @hide */
+    public static final int TIMESTAMP_TYPE_OEM_RIL = 3;
+    /** @hide */
+    public static final int TIMESTAMP_TYPE_JAVA_RIL = 4;
+
+    // True if device is mRegistered to the mobile network
+    private boolean mRegistered;
 
     // Observation time stamped as type in nanoseconds since boot
-    private final long mTimeStamp;
+    private long mTimeStamp;
+
     // Where time stamp gets recorded.
-    // Value of CELL_INFO_TIMESTAMP_TYPE_XXXX
-    private final int mTimeStampType;
+    // Value of TIMESTAMP_TYPE_XXXX
+    private int mTimeStampType;
 
-    private final boolean mRegistered;
-
-    private final SignalStrength mStrength;
-    private final long mTimingAdvance;
-
-    private final int mCellIdentityType;
-    private final CellIdentity mCellIdentity;
-
-    /**
-     * Public constructor
-     * @param timeStampType is one of CELL_INFO_TIMESTAMP_TYPE_XXXX
-     * @param timeStamp is observation time in nanoseconds since boot
-     * @param timingAdv is observed timing advance
-     * @param registered is true when register to this cellIdentity
-     * @param strength is observed signal strength
-     * @param cellIdentity is observed mobile cell
-     */
-    public CellInfo(int timeStampType, long timeStamp, long timingAdv,
-            boolean registered, SignalStrength strength,
-            CellIdentity cellIdentity) {
-
-        if (timeStampType < CELL_INFO_TIMESTAMP_TYPE_UNKNOWN ||
-                timeStampType > CELL_INFO_TIMESTAMP_TYPE_JAVA_RIL) {
-            mTimeStampType = CELL_INFO_TIMESTAMP_TYPE_UNKNOWN;
-        } else {
-            mTimeStampType = timeStampType;
-        }
-
-        mRegistered = registered;
-        mTimeStamp = timeStamp;
-        mTimingAdvance = timingAdv;
-        mStrength = new SignalStrength(strength);
-
-        mCellIdentityType = cellIdentity.getCellIdType();
-        // TODO: make defense copy
-        mCellIdentity = cellIdentity;
+    /** @hide */
+    protected CellInfo() {
+        this.mRegistered = false;
+        this.mTimeStampType = TIMESTAMP_TYPE_UNKNOWN;
+        this.mTimeStamp = Long.MAX_VALUE;
     }
 
-    public CellInfo(CellInfo ci) {
-        this.mTimeStampType = ci.mTimeStampType;
+    /** @hide */
+    protected CellInfo(CellInfo ci) {
         this.mRegistered = ci.mRegistered;
+        this.mTimeStampType = ci.mTimeStampType;
         this.mTimeStamp = ci.mTimeStamp;
-        this.mTimingAdvance = ci.mTimingAdvance;
-        this.mCellIdentityType = ci.mCellIdentityType;
-        this.mStrength = new SignalStrength(ci.mStrength);
-        switch(mCellIdentityType) {
-            case CellIdentity.CELLID_TYPE_GSM:
-                mCellIdentity = new GsmCellIdentity((GsmCellIdentity)ci.mCellIdentity);
-                break;
-            default:
-                mCellIdentity = null;
-        }
     }
 
-    private CellInfo(Parcel in) {
-        mTimeStampType = in.readInt();
-        mRegistered = (in.readInt() == 1) ? true : false;
-        mTimeStamp = in.readLong();
-        mTimingAdvance = in.readLong();
-        mCellIdentityType = in.readInt();
-        mStrength = SignalStrength.CREATOR.createFromParcel(in);
-        switch(mCellIdentityType) {
-            case CellIdentity.CELLID_TYPE_GSM:
-                mCellIdentity = GsmCellIdentity.CREATOR.createFromParcel(in);
-                break;
-            default:
-                mCellIdentity = null;
-        }
+    /** True if this cell is registered to the mobile network */
+    public boolean isRegistered() {
+        return mRegistered;
+    }
+    /** @hide */
+    public void setRegisterd(boolean registered) {
+        mRegistered = registered;
     }
 
-    /**
-     * @return the observation time in nanoseconds since boot
-     */
+    /** Approximate time of this cell information in nanos since boot */
     public long getTimeStamp() {
         return mTimeStamp;
     }
+    /** @hide */
+    public void setTimeStamp(long timeStamp) {
+        mTimeStamp = timeStamp;
+    }
 
     /**
-     * @return Where time stamp gets recorded.
-     * one of CELL_INFO_TIMESTAMP_TYPE_XXXX
+     * Where time stamp gets recorded.
+     * @return one of TIMESTAMP_TYPE_XXXX
+     *
+     * @hide
      */
     public int getTimeStampType() {
         return mTimeStampType;
     }
-
-    /**
-     * @return true when register to this cellIdentity
-     */
-    public boolean isRegistered() {
-        return mRegistered;
+    /** @hide */
+    public void setTimeStampType(int timeStampType) {
+        if (timeStampType < TIMESTAMP_TYPE_UNKNOWN || timeStampType > TIMESTAMP_TYPE_JAVA_RIL) {
+            mTimeStampType = TIMESTAMP_TYPE_UNKNOWN;
+        } else {
+            mTimeStampType = timeStampType;
+        }
     }
 
-    /**
-     * @return observed timing advance
-     */
-    public long getTimingAdvance() {
-        return mTimingAdvance;
+    @Override
+    public int hashCode() {
+        int primeNum = 31;
+        return ((mRegistered ? 0 : 1) * primeNum) + ((int)(mTimeStamp / 1000) * primeNum)
+                + (mTimeStampType * primeNum);
     }
 
-    /**
-     * @return observed signal strength
-     */
-    public SignalStrength getSignalStrength() {
-        // make a defense copy
-        return new SignalStrength(mStrength);
+    @Override
+    public boolean equals(Object other) {
+        if (other == null) {
+            return false;
+        }
+        if (this == other) {
+            return true;
+        }
+        try {
+            CellInfo o = (CellInfo) other;
+            return mRegistered == o.mRegistered
+                    && mTimeStamp == o.mTimeStamp && mTimeStampType == o.mTimeStampType;
+        } catch (ClassCastException e) {
+            return false;
+        }
     }
 
-    /**
-     * @return observed cell identity
-     */
-    public CellIdentity getCellIdentity() {
-        // TODO: make a defense copy
-        return mCellIdentity;
+    private static String timeStampTypeToString(int type) {
+        switch (type) {
+            case 1:
+                return "antenna";
+            case 2:
+                return "modem";
+            case 3:
+                return "oem_ril";
+            case 4:
+                return "java_ril";
+            default:
+                return "unknown";
+        }
     }
 
     @Override
     public String toString() {
         StringBuffer sb = new StringBuffer();
+        String timeStampType;
 
-        sb.append("TimeStampType: ");
-        switch(mTimeStampType) {
-            case 1:
-                sb.append("antenna");
-                break;
-            case 2:
-                sb.append("modem");
-                break;
-            case 3:
-                sb.append("oem_ril");
-                break;
-            case 4:
-                sb.append("java_ril");
-                break;
-            default:
-                sb.append("unknown");
-        }
-        sb.append(", TimeStamp: ").append(mTimeStamp).append(" ns");
-        sb.append(", Registered: ").append(mRegistered ? "YES" : "NO");
-        sb.append(", TimingAdvance: ").append(mTimingAdvance);
-        sb.append(", Strength : " + mStrength);
-        sb.append(", Cell Iden: " + mCellIdentity);
+        sb.append(" mRegistered=").append(mRegistered ? "YES" : "NO");
+        timeStampType = timeStampTypeToString(mTimeStampType);
+        sb.append(" mTimeStampType=").append(timeStampType);
+        sb.append(" mTimeStamp=").append(mTimeStamp).append("ns");
 
         return sb.toString();
     }
 
-    /** Implement the Parcelable interface {@hide} */
+    /**
+     * Implement the Parcelable interface
+     */
     @Override
     public int describeContents() {
         return 0;
     }
 
-    /** Implement the Parcelable interface {@hide} */
+    /** Implement the Parcelable interface */
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mTimeStampType);
+    public abstract void writeToParcel(Parcel dest, int flags);
+
+    /**
+     * Used by child classes for parceling.
+     *
+     * @hide
+     */
+    protected void writeToParcel(Parcel dest, int flags, int type) {
+        dest.writeInt(type);
         dest.writeInt(mRegistered ? 1 : 0);
+        dest.writeInt(mTimeStampType);
         dest.writeLong(mTimeStamp);
-        dest.writeLong(mTimingAdvance);
-        dest.writeInt(mCellIdentityType);
-        mStrength.writeToParcel(dest, flags);
-        mCellIdentity.writeToParcel(dest, flags);
     }
 
-    /** Implement the Parcelable interface {@hide} */
-    public static final Creator<CellInfo> CREATOR =
-            new Creator<CellInfo>() {
+    /**
+     * Used by child classes for parceling
+     *
+     * @hide
+     */
+    protected CellInfo(Parcel in) {
+        mRegistered = (in.readInt() == 1) ? true : false;
+        mTimeStampType = in.readInt();
+        mTimeStamp = in.readLong();
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<CellInfo> CREATOR = new Creator<CellInfo>() {
         @Override
         public CellInfo createFromParcel(Parcel in) {
-            return new CellInfo(in);
+                int type = in.readInt();
+                switch (type) {
+                    case TYPE_GSM: return CellInfoGsm.createFromParcelBody(in);
+                    case TYPE_CDMA: return CellInfoCdma.createFromParcelBody(in);
+                    case TYPE_LTE: return CellInfoLte.createFromParcelBody(in);
+                    default: throw new RuntimeException("Bad CellInfo Parcel");
+                }
         }
 
         @Override
diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java
new file mode 100644
index 0000000..ea48e2e
--- /dev/null
+++ b/telephony/java/android/telephony/CellInfoCdma.java
@@ -0,0 +1,148 @@
+/*
+ * 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * Immutable cell information from a point in time.
+ */
+public final class CellInfoCdma extends CellInfo implements Parcelable {
+
+    private static final String LOG_TAG = "CellInfoCdma";
+    private static final boolean DBG = false;
+
+    private CellIdentityCdma mCellIdentityCdma;
+    private CellSignalStrengthCdma mCellSignalStrengthCdma;
+
+    /** @hide */
+    public CellInfoCdma() {
+        super();
+        mCellIdentityCdma = new CellIdentityCdma();
+        mCellSignalStrengthCdma = new CellSignalStrengthCdma();
+    }
+
+    /** @hide */
+    public CellInfoCdma(CellInfoCdma ci) {
+        super(ci);
+        this.mCellIdentityCdma = ci.mCellIdentityCdma.copy();
+        this.mCellSignalStrengthCdma = ci.mCellSignalStrengthCdma.copy();
+    }
+
+    public CellIdentityCdma getCellIdentity() {
+        return mCellIdentityCdma;
+    }
+    /** @hide */
+    public void setCellIdentity(CellIdentityCdma cid) {
+        mCellIdentityCdma = cid;
+    }
+
+    public CellSignalStrengthCdma getCellSignalStrength() {
+        return mCellSignalStrengthCdma;
+    }
+    /** @hide */
+    public void setCellSignalStrength(CellSignalStrengthCdma css) {
+        mCellSignalStrengthCdma = css;
+    }
+
+    /**
+     * @return hash code
+     */
+    @Override
+    public int hashCode() {
+        return super.hashCode() + mCellIdentityCdma.hashCode() + mCellSignalStrengthCdma.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!super.equals(other)) {
+            return false;
+        }
+        try {
+            CellInfoCdma o = (CellInfoCdma) other;
+            return mCellIdentityCdma.equals(o.mCellIdentityCdma)
+                    && mCellSignalStrengthCdma.equals(o.mCellSignalStrengthCdma);
+        } catch (ClassCastException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append("CellInfoCdma:");
+        sb.append(super.toString());
+        sb.append(", ").append(mCellIdentityCdma);
+        sb.append(", ").append(mCellSignalStrengthCdma);
+
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags, TYPE_CDMA);
+        mCellIdentityCdma.writeToParcel(dest, flags);
+        mCellSignalStrengthCdma.writeToParcel(dest, flags);
+    }
+
+    /**
+     * Construct a CellInfoCdma object from the given parcel
+     * where the token is already been processed.
+     */
+    private CellInfoCdma(Parcel in) {
+        super(in);
+        mCellIdentityCdma = CellIdentityCdma.CREATOR.createFromParcel(in);
+        mCellSignalStrengthCdma = CellSignalStrengthCdma.CREATOR.createFromParcel(in);
+        if (DBG) log("CellInfoCdma(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<CellInfoCdma> CREATOR = new Creator<CellInfoCdma>() {
+        @Override
+        public CellInfoCdma createFromParcel(Parcel in) {
+            in.readInt(); // Skip past token, we know what it is
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellInfoCdma[] newArray(int size) {
+            return new CellInfoCdma[size];
+        }
+    };
+
+    /** @hide */
+    protected static CellInfoCdma createFromParcelBody(Parcel in) {
+        return new CellInfoCdma(in);
+    }
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java
new file mode 100644
index 0000000..bd14d45a
--- /dev/null
+++ b/telephony/java/android/telephony/CellInfoGsm.java
@@ -0,0 +1,147 @@
+/*
+ * 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * Immutable cell information from a point in time.
+ */
+public final class CellInfoGsm extends CellInfo implements Parcelable {
+
+    private static final String LOG_TAG = "CellInfoGsm";
+    private static final boolean DBG = false;
+
+    private CellIdentityGsm mCellIdentityGsm;
+    private CellSignalStrengthGsm mCellSignalStrengthGsm;
+
+    /** @hide */
+    public CellInfoGsm() {
+        super();
+        mCellIdentityGsm = new CellIdentityGsm();
+        mCellSignalStrengthGsm = new CellSignalStrengthGsm();
+    }
+
+    /** @hide */
+    public CellInfoGsm(CellInfoGsm ci) {
+        super(ci);
+        this.mCellIdentityGsm = ci.mCellIdentityGsm.copy();
+        this.mCellSignalStrengthGsm = ci.mCellSignalStrengthGsm.copy();
+    }
+
+    public CellIdentityGsm getCellIdentity() {
+        return mCellIdentityGsm;
+    }
+    /** @hide */
+    public void setCellIdentity(CellIdentityGsm cid) {
+        mCellIdentityGsm = cid;
+    }
+
+    public CellSignalStrengthGsm getCellSignalStrength() {
+        return mCellSignalStrengthGsm;
+    }
+    /** @hide */
+    public void setCellSignalStrength(CellSignalStrengthGsm css) {
+        mCellSignalStrengthGsm = css;
+    }
+
+    /**
+     * @return hash code
+     */
+    @Override
+    public int hashCode() {
+        return super.hashCode() + mCellIdentityGsm.hashCode() + mCellSignalStrengthGsm.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!super.equals(other)) {
+            return false;
+        }
+        try {
+            CellInfoGsm o = (CellInfoGsm) other;
+            return mCellIdentityGsm.equals(o.mCellIdentityGsm)
+                    && mCellSignalStrengthGsm.equals(o.mCellSignalStrengthGsm);
+        } catch (ClassCastException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append("CellInfoGsm:");
+        sb.append(super.toString());
+        sb.append(", ").append(mCellIdentityGsm);
+        sb.append(", ").append(mCellSignalStrengthGsm);
+
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags, TYPE_GSM);
+        mCellIdentityGsm.writeToParcel(dest, flags);
+        mCellSignalStrengthGsm.writeToParcel(dest, flags);
+    }
+
+    /**
+     * Construct a CellInfoGsm object from the given parcel
+     * where the token is already been processed.
+     */
+    private CellInfoGsm(Parcel in) {
+        super(in);
+        mCellIdentityGsm = CellIdentityGsm.CREATOR.createFromParcel(in);
+        mCellSignalStrengthGsm = CellSignalStrengthGsm.CREATOR.createFromParcel(in);
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<CellInfoGsm> CREATOR = new Creator<CellInfoGsm>() {
+        @Override
+        public CellInfoGsm createFromParcel(Parcel in) {
+            in.readInt(); // Skip past token, we know what it is
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellInfoGsm[] newArray(int size) {
+            return new CellInfoGsm[size];
+        }
+    };
+
+    /** @hide */
+    protected static CellInfoGsm createFromParcelBody(Parcel in) {
+        return new CellInfoGsm(in);
+    }
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
new file mode 100644
index 0000000..2f81b65
--- /dev/null
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -0,0 +1,153 @@
+/*
+ * 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * Immutable cell information from a point in time.
+ */
+public final class CellInfoLte extends CellInfo implements Parcelable {
+
+    private static final String LOG_TAG = "CellInfoLte";
+    private static final boolean DBG = true;
+
+    private CellIdentityLte mCellIdentityLte;
+    private CellSignalStrengthLte mCellSignalStrengthLte;
+
+    /** @hide */
+    public CellInfoLte() {
+        super();
+        mCellIdentityLte = new CellIdentityLte();
+        mCellSignalStrengthLte = new CellSignalStrengthLte();
+    }
+
+    /** @hide */
+    public CellInfoLte(CellInfoLte ci) {
+        super(ci);
+        this.mCellIdentityLte = ci.mCellIdentityLte.copy();
+        this.mCellSignalStrengthLte = ci.mCellSignalStrengthLte.copy();
+    }
+
+    public CellIdentityLte getCellIdentity() {
+        if (DBG) log("getCellIdentity: " + mCellIdentityLte);
+        return mCellIdentityLte;
+    }
+    /** @hide */
+    public void setCellIdentity(CellIdentityLte cid) {
+        if (DBG) log("setCellIdentity: " + cid);
+        mCellIdentityLte = cid;
+    }
+
+    public CellSignalStrengthLte getCellSignalStrength() {
+        if (DBG) log("getCellSignalStrength: " + mCellSignalStrengthLte);
+        return mCellSignalStrengthLte;
+    }
+    /** @hide */
+    public void setCellSignalStrength(CellSignalStrengthLte css) {
+        if (DBG) log("setCellSignalStrength: " + css);
+        mCellSignalStrengthLte = css;
+    }
+
+    /**
+     * @return hash code
+     */
+    @Override
+    public int hashCode() {
+        return super.hashCode() + mCellIdentityLte.hashCode() + mCellSignalStrengthLte.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!super.equals(other)) {
+            return false;
+        }
+        try {
+            CellInfoLte o = (CellInfoLte) other;
+            return mCellIdentityLte.equals(o.mCellIdentityLte)
+                    && mCellSignalStrengthLte.equals(o.mCellSignalStrengthLte);
+        } catch (ClassCastException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append("CellInfoLte:");
+        sb.append(super.toString());
+        sb.append(", ").append(mCellIdentityLte);
+        sb.append(", ").append(mCellSignalStrengthLte);
+
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        super.writeToParcel(dest, flags, TYPE_LTE);
+        mCellIdentityLte.writeToParcel(dest, flags);
+        mCellSignalStrengthLte.writeToParcel(dest, flags);
+    }
+
+    /**
+     * Construct a CellInfoLte object from the given parcel
+     * where the TYPE_LTE token is already been processed.
+     */
+    private CellInfoLte(Parcel in) {
+        super(in);
+        mCellIdentityLte = CellIdentityLte.CREATOR.createFromParcel(in);
+        mCellSignalStrengthLte = CellSignalStrengthLte.CREATOR.createFromParcel(in);
+        if (DBG) log("CellInfoLte(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<CellInfoLte> CREATOR = new Creator<CellInfoLte>() {
+        @Override
+        public CellInfoLte createFromParcel(Parcel in) {
+            in.readInt(); // Skip past token, we know what it is
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellInfoLte[] newArray(int size) {
+            return new CellInfoLte[size];
+        }
+    };
+
+    /** @hide */
+    protected static CellInfoLte createFromParcelBody(Parcel in) {
+        return new CellInfoLte(in);
+    }
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellSignalStrength.java b/telephony/java/android/telephony/CellSignalStrength.java
new file mode 100644
index 0000000..3b470fc
--- /dev/null
+++ b/telephony/java/android/telephony/CellSignalStrength.java
@@ -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.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Abstract base class for cell phone signal strength related information.
+ */
+public abstract class CellSignalStrength {
+
+    /** @hide */
+    public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
+    /** @hide */
+    public static final int SIGNAL_STRENGTH_POOR = 1;
+    /** @hide */
+    public static final int SIGNAL_STRENGTH_MODERATE = 2;
+    /** @hide */
+    public static final int SIGNAL_STRENGTH_GOOD = 3;
+    /** @hide */
+    public static final int SIGNAL_STRENGTH_GREAT = 4;
+    /** @hide */
+    public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
+    /** @hide */
+    public static final String[] SIGNAL_STRENGTH_NAMES = {
+        "none", "poor", "moderate", "good", "great"
+    };
+
+    /** @hide */
+    protected CellSignalStrength() {
+    }
+
+    /** @hide */
+    public abstract void setDefaultValues();
+
+    /**
+     * Get signal level as an int from 0..4
+     */
+    public abstract int getLevel();
+
+    /**
+     * Get the signal level as an asu value between 0..31, 99 is unknown
+     */
+    public abstract int getAsuLevel();
+
+    /**
+     * Get the signal strength as dBm
+     */
+    public abstract int getDbm();
+
+    /**
+     * Copies the CellSignalStrength.
+     *
+     * @return A deep copy of this class.
+     * @hide
+     */
+    public abstract CellSignalStrength copy();
+
+    @Override
+    public abstract int hashCode();
+
+    @Override
+    public abstract boolean equals (Object o);
+}
diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java
new file mode 100644
index 0000000..660326c
--- /dev/null
+++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java
@@ -0,0 +1,381 @@
+/*
+ * 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * LTE signal strength related information.
+ */
+public final class CellSignalStrengthCdma extends CellSignalStrength implements Parcelable {
+
+    private static final String LOG_TAG = "CellSignalStrengthCdma";
+    private static final boolean DBG = false;
+
+    private int mCdmaDbm;   // This value is the RSSI value
+    private int mCdmaEcio;  // This value is the Ec/Io
+    private int mEvdoDbm;   // This value is the EVDO RSSI value
+    private int mEvdoEcio;  // This value is the EVDO Ec/Io
+    private int mEvdoSnr;   // Valid values are 0-8.  8 is the highest signal to noise ratio
+
+    /**
+     * Empty constructor
+     *
+     * @hide
+     */
+    public CellSignalStrengthCdma() {
+        setDefaultValues();
+    }
+
+    /**
+     * Constructor
+     *
+     * @hide
+     */
+    public CellSignalStrengthCdma(int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio,
+            int evdoSnr) {
+        initialize(cdmaDbm, cdmaEcio, evdoDbm, evdoEcio, evdoSnr);
+    }
+
+    /**
+     * Copy constructors
+     *
+     * @param s Source SignalStrength
+     *
+     * @hide
+     */
+    public CellSignalStrengthCdma(CellSignalStrengthCdma s) {
+        copyFrom(s);
+    }
+
+    /**
+     * Initialize all the values
+     *
+     * @param cdmaDbm
+     * @param cdmaEcio
+     * @param evdoDbm
+     * @param evdoEcio
+     * @param evdoSnr
+     *
+     * @hide
+     */
+    public void initialize(int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio, int evdoSnr) {
+        mCdmaDbm = cdmaDbm;
+        mCdmaEcio = cdmaEcio;
+        mEvdoDbm = evdoDbm;
+        mEvdoEcio = evdoEcio;
+        mEvdoSnr = evdoSnr;
+    }
+
+    /**
+     * @hide
+     */
+    protected void copyFrom(CellSignalStrengthCdma s) {
+        mCdmaDbm = s.mCdmaDbm;
+        mCdmaEcio = s.mCdmaEcio;
+        mEvdoDbm = s.mEvdoDbm;
+        mEvdoEcio = s.mEvdoEcio;
+        mEvdoSnr = s.mEvdoSnr;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public CellSignalStrengthCdma copy() {
+        return new CellSignalStrengthCdma(this);
+    }
+
+    /** @hide */
+    @Override
+    public void setDefaultValues() {
+        mCdmaDbm = Integer.MAX_VALUE;
+        mCdmaEcio = Integer.MAX_VALUE;
+        mEvdoDbm = Integer.MAX_VALUE;
+        mEvdoEcio = Integer.MAX_VALUE;
+        mEvdoSnr = Integer.MAX_VALUE;
+    }
+
+    /**
+     * Get signal level as an int from 0..4
+     */
+    @Override
+    public int getLevel() {
+        int level;
+
+        int cdmaLevel = getCdmaLevel();
+        int evdoLevel = getEvdoLevel();
+        if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
+            /* We don't know evdo, use cdma */
+            level = getCdmaLevel();
+        } else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
+            /* We don't know cdma, use evdo */
+            level = getEvdoLevel();
+        } else {
+            /* We know both, use the lowest level */
+            level = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel;
+        }
+        if (DBG) log("getLevel=" + level);
+        return level;
+    }
+
+    /**
+     * Get the LTE signal level as an asu value between 0..97, 99 is unknown
+     * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+     */
+    @Override
+    public int getAsuLevel() {
+        final int cdmaDbm = getCdmaDbm();
+        final int cdmaEcio = getCdmaEcio();
+        int cdmaAsuLevel;
+        int ecioAsuLevel;
+
+        if (cdmaDbm >= -75) cdmaAsuLevel = 16;
+        else if (cdmaDbm >= -82) cdmaAsuLevel = 8;
+        else if (cdmaDbm >= -90) cdmaAsuLevel = 4;
+        else if (cdmaDbm >= -95) cdmaAsuLevel = 2;
+        else if (cdmaDbm >= -100) cdmaAsuLevel = 1;
+        else cdmaAsuLevel = 99;
+
+        // Ec/Io are in dB*10
+        if (cdmaEcio >= -90) ecioAsuLevel = 16;
+        else if (cdmaEcio >= -100) ecioAsuLevel = 8;
+        else if (cdmaEcio >= -115) ecioAsuLevel = 4;
+        else if (cdmaEcio >= -130) ecioAsuLevel = 2;
+        else if (cdmaEcio >= -150) ecioAsuLevel = 1;
+        else ecioAsuLevel = 99;
+
+        int level = (cdmaAsuLevel < ecioAsuLevel) ? cdmaAsuLevel : ecioAsuLevel;
+        if (DBG) log("getAsuLevel=" + level);
+        return level;
+    }
+
+    /**
+     * Get cdma as level 0..4
+     */
+    public int getCdmaLevel() {
+        final int cdmaDbm = getCdmaDbm();
+        final int cdmaEcio = getCdmaEcio();
+        int levelDbm;
+        int levelEcio;
+
+        if (cdmaDbm >= -75) levelDbm = SIGNAL_STRENGTH_GREAT;
+        else if (cdmaDbm >= -85) levelDbm = SIGNAL_STRENGTH_GOOD;
+        else if (cdmaDbm >= -95) levelDbm = SIGNAL_STRENGTH_MODERATE;
+        else if (cdmaDbm >= -100) levelDbm = SIGNAL_STRENGTH_POOR;
+        else levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+
+        // Ec/Io are in dB*10
+        if (cdmaEcio >= -90) levelEcio = SIGNAL_STRENGTH_GREAT;
+        else if (cdmaEcio >= -110) levelEcio = SIGNAL_STRENGTH_GOOD;
+        else if (cdmaEcio >= -130) levelEcio = SIGNAL_STRENGTH_MODERATE;
+        else if (cdmaEcio >= -150) levelEcio = SIGNAL_STRENGTH_POOR;
+        else levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+
+        int level = (levelDbm < levelEcio) ? levelDbm : levelEcio;
+        if (DBG) log("getCdmaLevel=" + level);
+        return level;
+    }
+
+    /**
+     * Get Evdo as level 0..4
+     */
+    public int getEvdoLevel() {
+        int evdoDbm = getEvdoDbm();
+        int evdoSnr = getEvdoSnr();
+        int levelEvdoDbm;
+        int levelEvdoSnr;
+
+        if (evdoDbm >= -65) levelEvdoDbm = SIGNAL_STRENGTH_GREAT;
+        else if (evdoDbm >= -75) levelEvdoDbm = SIGNAL_STRENGTH_GOOD;
+        else if (evdoDbm >= -90) levelEvdoDbm = SIGNAL_STRENGTH_MODERATE;
+        else if (evdoDbm >= -105) levelEvdoDbm = SIGNAL_STRENGTH_POOR;
+        else levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+
+        if (evdoSnr >= 7) levelEvdoSnr = SIGNAL_STRENGTH_GREAT;
+        else if (evdoSnr >= 5) levelEvdoSnr = SIGNAL_STRENGTH_GOOD;
+        else if (evdoSnr >= 3) levelEvdoSnr = SIGNAL_STRENGTH_MODERATE;
+        else if (evdoSnr >= 1) levelEvdoSnr = SIGNAL_STRENGTH_POOR;
+        else levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+
+        int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
+        if (DBG) log("getEvdoLevel=" + level);
+        return level;
+    }
+
+    /**
+     * Get the signal strength as dBm
+     */
+    @Override
+    public int getDbm() {
+        int cdmaDbm = getCdmaDbm();
+        int evdoDbm = getEvdoDbm();
+
+        // Use the lower value to be conservative
+        return (cdmaDbm < evdoDbm) ? cdmaDbm : evdoDbm;
+    }
+
+    /**
+     * Get the CDMA RSSI value in dBm
+     */
+    public int getCdmaDbm() {
+        return mCdmaDbm;
+    }
+    /** @hide */
+    public void setCdmaDbm(int cdmaDbm) {
+        mCdmaDbm = cdmaDbm;
+    }
+
+    /**
+     * Get the CDMA Ec/Io value in dB*10
+     */
+    public int getCdmaEcio() {
+        return mCdmaEcio;
+    }
+    /** @hide */
+    public void setCdmaEcio(int cdmaEcio) {
+        mCdmaEcio = cdmaEcio;
+    }
+
+    /**
+     * Get the EVDO RSSI value in dBm
+     */
+    public int getEvdoDbm() {
+        return mEvdoDbm;
+    }
+    /** @hide */
+    public void setEvdoDbm(int evdoDbm) {
+        mEvdoDbm = evdoDbm;
+    }
+
+    /**
+     * Get the EVDO Ec/Io value in dB*10
+     */
+    public int getEvdoEcio() {
+        return mEvdoEcio;
+    }
+    /** @hide */
+    public void setEvdoEcio(int evdoEcio) {
+        mEvdoEcio = evdoEcio;
+    }
+
+    /**
+     * Get the signal to noise ratio. Valid values are 0-8. 8 is the highest.
+     */
+    public int getEvdoSnr() {
+        return mEvdoSnr;
+    }
+    /** @hide */
+    public void setEvdoSnr(int evdoSnr) {
+        mEvdoSnr = evdoSnr;
+    }
+
+    @Override
+    public int hashCode() {
+        int primeNum = 31;
+        return ((mCdmaDbm * primeNum) + (mCdmaEcio * primeNum)
+                + (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum));
+    }
+
+    @Override
+    public boolean equals (Object o) {
+        CellSignalStrengthCdma s;
+
+        try {
+            s = (CellSignalStrengthCdma) o;
+        } catch (ClassCastException ex) {
+            return false;
+        }
+
+        if (o == null) {
+            return false;
+        }
+
+        return mCdmaDbm == s.mCdmaDbm
+                && mCdmaEcio == s.mCdmaEcio
+                && mEvdoDbm == s.mEvdoDbm
+                && mEvdoEcio == s.mEvdoEcio
+                && mEvdoSnr == s.mEvdoSnr;
+    }
+
+    /**
+     * @return string representation.
+     */
+    @Override
+    public String toString() {
+        return "CellSignalStrengthCdma:"
+                + " cdmaDbm=" + mCdmaDbm
+                + " cdmaEcio=" + mCdmaEcio
+                + " evdoDbm=" + mEvdoDbm
+                + " evdoEcio=" + mEvdoEcio
+                + " evdoSnr=" + mEvdoSnr;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        dest.writeInt(mCdmaDbm);
+        dest.writeInt(mCdmaEcio);
+        dest.writeInt(mEvdoDbm);
+        dest.writeInt(mEvdoEcio);
+        dest.writeInt(mEvdoSnr);
+    }
+
+    /**
+     * Construct a SignalStrength object from the given parcel
+     * where the TYPE_LTE token is already been processed.
+     */
+    private CellSignalStrengthCdma(Parcel in) {
+        mCdmaDbm = in.readInt();
+        mCdmaEcio = in.readInt();
+        mEvdoDbm = in.readInt();
+        mEvdoEcio = in.readInt();
+        mEvdoSnr = in.readInt();
+        if (DBG) log("CellSignalStrengthCdma(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @SuppressWarnings("hiding")
+    public static final Parcelable.Creator<CellSignalStrengthCdma> CREATOR =
+            new Parcelable.Creator<CellSignalStrengthCdma>() {
+        @Override
+        public CellSignalStrengthCdma createFromParcel(Parcel in) {
+            return new CellSignalStrengthCdma(in);
+        }
+
+        @Override
+        public CellSignalStrengthCdma[] newArray(int size) {
+            return new CellSignalStrengthCdma[size];
+        }
+    };
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
new file mode 100644
index 0000000..4108f61
--- /dev/null
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -0,0 +1,234 @@
+/*
+ * 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * LTE signal strength related information.
+ */
+public final class CellSignalStrengthGsm extends CellSignalStrength implements Parcelable {
+
+    private static final String LOG_TAG = "CellSignalStrengthGsm";
+    private static final boolean DBG = false;
+
+    private static final int GSM_SIGNAL_STRENGTH_GREAT = 12;
+    private static final int GSM_SIGNAL_STRENGTH_GOOD = 8;
+    private static final int GSM_SIGNAL_STRENGTH_MODERATE = 8;
+
+    private int mSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
+    private int mBitErrorRate;   // bit error rate (0-7, 99) as defined in TS 27.007 8.5
+
+    /**
+     * Empty constructor
+     *
+     * @hide
+     */
+    public CellSignalStrengthGsm() {
+        setDefaultValues();
+    }
+
+    /**
+     * Constructor
+     *
+     * @hide
+     */
+    public CellSignalStrengthGsm(int ss, int ber) {
+        initialize(ss, ber);
+    }
+
+    /**
+     * Copy constructors
+     *
+     * @param s Source SignalStrength
+     *
+     * @hide
+     */
+    public CellSignalStrengthGsm(CellSignalStrengthGsm s) {
+        copyFrom(s);
+    }
+
+    /**
+     * Initialize all the values
+     *
+     * @param SignalStrength
+     *
+     * @hide
+     */
+    public void initialize(int ss, int ber) {
+        mSignalStrength = ss;
+        mBitErrorRate = ber;
+    }
+
+    /**
+     * @hide
+     */
+    protected void copyFrom(CellSignalStrengthGsm s) {
+        mSignalStrength = s.mSignalStrength;
+        mBitErrorRate = s.mBitErrorRate;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public CellSignalStrengthGsm copy() {
+        return new CellSignalStrengthGsm(this);
+    }
+
+    /** @hide */
+    @Override
+    public void setDefaultValues() {
+        mSignalStrength = Integer.MAX_VALUE;
+        mBitErrorRate = Integer.MAX_VALUE;
+    }
+
+    /**
+     * Get signal level as an int from 0..4
+     */
+    @Override
+    public int getLevel() {
+        int level;
+
+        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
+        // asu = 0 (-113dB or less) is very weak
+        // signal, its better to show 0 bars to the user in such cases.
+        // asu = 99 is a special case, where the signal strength is unknown.
+        int asu = mSignalStrength;
+        if (asu <= 2 || asu == 99) level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        else if (asu >= GSM_SIGNAL_STRENGTH_GREAT) level = SIGNAL_STRENGTH_GREAT;
+        else if (asu >= GSM_SIGNAL_STRENGTH_GOOD)  level = SIGNAL_STRENGTH_GOOD;
+        else if (asu >= GSM_SIGNAL_STRENGTH_MODERATE)  level = SIGNAL_STRENGTH_MODERATE;
+        else level = SIGNAL_STRENGTH_POOR;
+        if (DBG) log("getLevel=" + level);
+        return level;
+    }
+
+    /**
+     * Get the signal strength as dBm
+     */
+    @Override
+    public int getDbm() {
+        int dBm;
+
+        int level = mSignalStrength;
+        int asu = (level == 99 ? Integer.MAX_VALUE : level);
+        if (asu != Integer.MAX_VALUE) {
+            dBm = -113 + (2 * asu);
+        } else {
+            dBm = Integer.MAX_VALUE;
+        }
+        if (DBG) log("getDbm=" + dBm);
+        return dBm;
+    }
+
+    /**
+     * Get the LTE signal level as an asu value between 0..97, 99 is unknown
+     * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+     */
+    @Override
+    public int getAsuLevel() {
+        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
+        // asu = 0 (-113dB or less) is very weak
+        // signal, its better to show 0 bars to the user in such cases.
+        // asu = 99 is a special case, where the signal strength is unknown.
+        int level = mSignalStrength;
+        if (DBG) log("getAsuLevel=" + level);
+        return level;
+    }
+
+    @Override
+    public int hashCode() {
+        int primeNum = 31;
+        return (mSignalStrength * primeNum) + (mBitErrorRate * primeNum);
+    }
+
+    @Override
+    public boolean equals (Object o) {
+        CellSignalStrengthGsm s;
+
+        try {
+            s = (CellSignalStrengthGsm) o;
+        } catch (ClassCastException ex) {
+            return false;
+        }
+
+        if (o == null) {
+            return false;
+        }
+
+        return mSignalStrength == s.mSignalStrength && mBitErrorRate == s.mBitErrorRate;
+    }
+
+    /**
+     * @return string representation.
+     */
+    @Override
+    public String toString() {
+        return "CellSignalStrengthGsm:"
+                + " ss=" + mSignalStrength
+                + " ber=" + mBitErrorRate;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        dest.writeInt(mSignalStrength);
+        dest.writeInt(mBitErrorRate);
+    }
+
+    /**
+     * Construct a SignalStrength object from the given parcel
+     * where the token is already been processed.
+     */
+    private CellSignalStrengthGsm(Parcel in) {
+        mSignalStrength = in.readInt();
+        mBitErrorRate = in.readInt();
+        if (DBG) log("CellSignalStrengthGsm(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @SuppressWarnings("hiding")
+    public static final Parcelable.Creator<CellSignalStrengthGsm> CREATOR =
+            new Parcelable.Creator<CellSignalStrengthGsm>() {
+        @Override
+        public CellSignalStrengthGsm createFromParcel(Parcel in) {
+            return new CellSignalStrengthGsm(in);
+        }
+
+        @Override
+        public CellSignalStrengthGsm[] newArray(int size) {
+            return new CellSignalStrengthGsm[size];
+        }
+    };
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
new file mode 100644
index 0000000..925f4d4
--- /dev/null
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -0,0 +1,298 @@
+/*
+ * 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * LTE signal strength related information.
+ */
+public final class CellSignalStrengthLte extends CellSignalStrength implements Parcelable {
+
+    private static final String LOG_TAG = "CellSignalStrengthLte";
+    private static final boolean DBG = false;
+
+    private int mSignalStrength;
+    private int mRsrp;
+    private int mRsrq;
+    private int mRssnr;
+    private int mCqi;
+    private int mTimingAdvance;
+
+    /**
+     * Empty constructor
+     *
+     * @hide
+     */
+    public CellSignalStrengthLte() {
+        setDefaultValues();
+    }
+
+    /**
+     * Constructor
+     *
+     * @hide
+     */
+    public CellSignalStrengthLte(int signalStrength, int rsrp, int rsrq, int rssnr, int cqi,
+            int timingAdvance) {
+        initialize(signalStrength, rsrp, rsrq, rssnr, cqi, timingAdvance);
+    }
+
+    /**
+     * Copy constructors
+     *
+     * @param s Source SignalStrength
+     *
+     * @hide
+     */
+    public CellSignalStrengthLte(CellSignalStrengthLte s) {
+        copyFrom(s);
+    }
+
+    /**
+     * Initialize all the values
+     *
+     * @param lteSignalStrength
+     * @param rsrp
+     * @param rsrq
+     * @param rssnr
+     * @param cqi
+     *
+     * @hide
+     */
+    public void initialize(int lteSignalStrength, int rsrp, int rsrq, int rssnr, int cqi,
+            int timingAdvance) {
+        mSignalStrength = lteSignalStrength;
+        mRsrp = rsrp;
+        mRsrq = rsrq;
+        mRssnr = rssnr;
+        mCqi = cqi;
+        mTimingAdvance = timingAdvance;
+    }
+
+    /**
+     * Initialize from the SignalStrength structure.
+     *
+     * @param ss
+     *
+     * @hide
+     */
+    public void initialize(SignalStrength ss, int timingAdvance) {
+        mSignalStrength = ss.getLteSignalStrenght();
+        mRsrp = ss.getLteRsrp();
+        mRsrq = ss.getLteRsrq();
+        mRssnr = ss.getLteRssnr();
+        mCqi = ss.getLteCqi();
+        mTimingAdvance = timingAdvance;
+    }
+
+    /**
+     * @hide
+     */
+    protected void copyFrom(CellSignalStrengthLte s) {
+        mSignalStrength = s.mSignalStrength;
+        mRsrp = s.mRsrp;
+        mRsrq = s.mRsrq;
+        mRssnr = s.mRssnr;
+        mCqi = s.mCqi;
+        mTimingAdvance = s.mTimingAdvance;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public CellSignalStrengthLte copy() {
+        return new CellSignalStrengthLte(this);
+    }
+
+    /** @hide */
+    @Override
+    public void setDefaultValues() {
+        mSignalStrength = Integer.MAX_VALUE;
+        mRsrp = Integer.MAX_VALUE;
+        mRsrq = Integer.MAX_VALUE;
+        mRssnr = Integer.MAX_VALUE;
+        mCqi = Integer.MAX_VALUE;
+        mTimingAdvance = Integer.MAX_VALUE;
+    }
+
+    /**
+     * Get signal level as an int from 0..4
+     */
+    @Override
+    public int getLevel() {
+        int levelRsrp = 0;
+        int levelRssnr = 0;
+
+        if (mRsrp == Integer.MAX_VALUE) levelRsrp = 0;
+        else if (mRsrp >= -95) levelRsrp = SIGNAL_STRENGTH_GREAT;
+        else if (mRsrp >= -105) levelRsrp = SIGNAL_STRENGTH_GOOD;
+        else if (mRsrp >= -115) levelRsrp = SIGNAL_STRENGTH_MODERATE;
+        else levelRsrp = SIGNAL_STRENGTH_POOR;
+
+        // See RIL_LTE_SignalStrength in ril.h
+        if (mRssnr == Integer.MAX_VALUE) levelRssnr = 0;
+        else if (mRssnr >= 45) levelRssnr = SIGNAL_STRENGTH_GREAT;
+        else if (mRssnr >= 10) levelRssnr = SIGNAL_STRENGTH_GOOD;
+        else if (mRssnr >= -30) levelRssnr = SIGNAL_STRENGTH_MODERATE;
+        else levelRssnr = SIGNAL_STRENGTH_POOR;
+
+        int level;
+        if (mRsrp == Integer.MAX_VALUE)
+            level = levelRssnr;
+        else if (mRssnr == Integer.MAX_VALUE)
+            level = levelRsrp;
+        else
+            level = (levelRssnr < levelRsrp) ? levelRssnr : levelRsrp;
+
+        if (DBG) log("Lte rsrp level: " + levelRsrp
+                + " snr level: " + levelRssnr + " level: " + level);
+        return level;
+    }
+
+    /**
+     * Get signal strength as dBm
+     */
+    @Override
+    public int getDbm() {
+        return mRsrp;
+    }
+
+    /**
+     * Get the LTE signal level as an asu value between 0..97, 99 is unknown
+     * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+     */
+    @Override
+    public int getAsuLevel() {
+        int lteAsuLevel = 99;
+        int lteDbm = getDbm();
+        if (lteDbm <= -140) lteAsuLevel = 0;
+        else if (lteDbm >= -43) lteAsuLevel = 97;
+        else lteAsuLevel = lteDbm + 140;
+        if (DBG) log("Lte Asu level: "+lteAsuLevel);
+        return lteAsuLevel;
+    }
+
+    /**
+     * Get the timing advance value for LTE.
+     * See 3GPP xxxx
+     */
+    public int getTimingAdvance() {
+        return mTimingAdvance;
+    }
+
+    @Override
+    public int hashCode() {
+        int primeNum = 31;
+        return (mSignalStrength * primeNum) + (mRsrp * primeNum)
+                + (mRsrq * primeNum) + (mRssnr * primeNum) + (mCqi * primeNum)
+                + (mTimingAdvance * primeNum);
+    }
+
+    @Override
+    public boolean equals (Object o) {
+        CellSignalStrengthLte s;
+
+        try {
+            s = (CellSignalStrengthLte) o;
+        } catch (ClassCastException ex) {
+            return false;
+        }
+
+        if (o == null) {
+            return false;
+        }
+
+        return mSignalStrength == s.mSignalStrength
+                && mRsrp == s.mRsrp
+                && mRsrq == s.mRsrq
+                && mRssnr == s.mRssnr
+                && mCqi == s.mCqi
+                && mTimingAdvance == s.mTimingAdvance;
+    }
+
+    /**
+     * @return string representation.
+     */
+    @Override
+    public String toString() {
+        return "CellSignalStrengthLte:"
+                + " ss=" + mSignalStrength
+                + " rsrp=" + mRsrp
+                + " rsrq=" + mRsrq
+                + " rssnr=" + mRssnr
+                + " cqi=" + mCqi
+                + " ta=" + mTimingAdvance;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        dest.writeInt(mSignalStrength);
+        dest.writeInt(mRsrp);
+        dest.writeInt(mRsrq);
+        dest.writeInt(mRssnr);
+        dest.writeInt(mCqi);
+        dest.writeInt(mTimingAdvance);
+    }
+
+    /**
+     * Construct a SignalStrength object from the given parcel
+     * where the token is already been processed.
+     */
+    private CellSignalStrengthLte(Parcel in) {
+        mSignalStrength = in.readInt();
+        mRsrp = in.readInt();
+        mRsrq = in.readInt();
+        mRssnr = in.readInt();
+        mCqi = in.readInt();
+        mTimingAdvance = in.readInt();
+        if (DBG) log("CellSignalStrengthLte(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @SuppressWarnings("hiding")
+    public static final Parcelable.Creator<CellSignalStrengthLte> CREATOR =
+            new Parcelable.Creator<CellSignalStrengthLte>() {
+        @Override
+        public CellSignalStrengthLte createFromParcel(Parcel in) {
+            return new CellSignalStrengthLte(in);
+        }
+
+        @Override
+        public CellSignalStrengthLte[] newArray(int size) {
+            return new CellSignalStrengthLte[size];
+        }
+    };
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/GsmCellIdentity.java b/telephony/java/android/telephony/GsmCellIdentity.java
deleted file mode 100644
index 159cb52..0000000
--- a/telephony/java/android/telephony/GsmCellIdentity.java
+++ /dev/null
@@ -1,148 +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.
- */
-
-package android.telephony;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * CellIdentity to represent a unique GSM or UMTS cell
- *
- * @hide pending API review
- */
-public final class GsmCellIdentity extends CellIdentity implements Parcelable {
-
-    // 3-digit Mobile Country Code, 0..999
-    private final int mMcc;
-    // 2 or 3-digit Mobile Network Code, 0..999
-    private final int mMnc;
-    // 16-bit Location Area Code, 0..65535
-    private final int mLac;
-    // 16-bit GSM Cell Identity described in TS 27.007, 0..65535
-    // 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455
-    private final int mCid;
-    // 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511
-    private final int mPsc;
-
-    /**
-     * public constructor
-     * @param mcc 3-digit Mobile Country Code, 0..999
-     * @param mnc 2 or 3-digit Mobile Network Code, 0..999
-     * @param lac 16-bit Location Area Code, 0..65535
-     * @param cid 16-bit GSM Cell Identity or 28-bit UMTS Cell Identity
-     * @param psc 9-bit UMTS Primary Scrambling Code
-     * @param attr is comma separated “key=value” attribute pairs.
-     */
-    public GsmCellIdentity (int mcc, int mnc,
-            int lac, int cid, int psc, String attr) {
-        super(CELLID_TYPE_GSM, attr);
-        mMcc = mcc;
-        mMnc = mnc;
-        mLac = lac;
-        mCid = cid;
-        mPsc = psc;
-    }
-
-    private GsmCellIdentity(Parcel in) {
-        super(in);
-        mMcc = in.readInt();
-        mMnc = in.readInt();
-        mLac = in.readInt();
-        mCid = in.readInt();
-        mPsc = in.readInt();
-    }
-
-    GsmCellIdentity(GsmCellIdentity cid) {
-        super(cid);
-        mMcc = cid.mMcc;
-        mMnc = cid.mMnc;
-        mLac = cid.mLac;
-        mCid = cid.mCid;
-        mPsc = cid.mPsc;
-    }
-
-    /**
-     * @return 3-digit Mobile Country Code, 0..999
-     */
-    public int getMcc() {
-        return mMcc;
-    }
-
-    /**
-     * @return 2 or 3-digit Mobile Network Code, 0..999
-     */
-    public int getMnc() {
-        return mMnc;
-    }
-
-    /**
-     * @return 16-bit Location Area Code, 0..65535
-     */
-    public int getLac() {
-        return mLac;
-    }
-
-    /**
-     * @return CID
-     * Either 16-bit GSM Cell Identity described
-     * in TS 27.007, 0..65535
-     * or 28-bit UMTS Cell Identity described
-     * in TS 25.331, 0..268435455
-     */
-    public int getCid() {
-        return mCid;
-    }
-
-    /**
-     * @return 9-bit UMTS Primary Scrambling Code described in
-     * TS 25.331, 0..511
-     */
-    public int getPsc() {
-        return mPsc;
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
-        dest.writeInt(mMcc);
-        dest.writeInt(mMnc);
-        dest.writeInt(mLac);
-        dest.writeInt(mCid);
-        dest.writeInt(mPsc);
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    public static final Creator<GsmCellIdentity> CREATOR =
-            new Creator<GsmCellIdentity>() {
-        @Override
-        public GsmCellIdentity createFromParcel(Parcel in) {
-            return new GsmCellIdentity(in);
-        }
-
-        @Override
-        public GsmCellIdentity[] newArray(int size) {
-            return new GsmCellIdentity[size];
-        }
-    };
-}
diff --git a/telephony/java/android/telephony/LteCellIdentity.java b/telephony/java/android/telephony/LteCellIdentity.java
deleted file mode 100644
index 396922e..0000000
--- a/telephony/java/android/telephony/LteCellIdentity.java
+++ /dev/null
@@ -1,142 +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.
- */
-
-package android.telephony;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * CellIdentity is to represent a unique LTE cell
- *
- * @hide pending API review
- */
-public final class LteCellIdentity extends CellIdentity implements Parcelable {
-
-    // 3-digit Mobile Country Code, 0..999
-    private final int mMcc;
-    // 2 or 3-digit Mobile Network Code, 0..999
-    private final int mMnc;
-    // 28-bit cell identity
-    private final int mCi;
-    // physical cell id 0..503
-    private final int mPci;
-    // 16-bit tracking area code
-    private final int mTac;
-
-    /**
-     *
-     * @param mcc 3-digit Mobile Country Code, 0..999
-     * @param mnc 2 or 3-digit Mobile Network Code, 0..999
-     * @param ci 28-bit Cell Identity
-     * @param pci Physical Cell Id 0..503
-     * @param tac 16-bit Tracking Area Code
-     * @param attr is comma separated “key=value” attribute pairs.
-     */
-    public LteCellIdentity (int mcc, int mnc,
-            int ci, int pci, int tac, String attr) {
-        super(CELLID_TYPE_CDMA, attr);
-        mMcc = mcc;
-        mMnc = mnc;
-        mCi = ci;
-        mPci = pci;
-        mTac = tac;
-    }
-
-    private LteCellIdentity(Parcel in) {
-        super(in);
-        mMcc = in.readInt();
-        mMnc = in.readInt();
-        mCi = in.readInt();
-        mPci = in.readInt();
-        mTac = in.readInt();
-    }
-
-    LteCellIdentity(LteCellIdentity cid) {
-        super(cid);
-        mMcc = cid.mMcc;
-        mMnc = cid.mMnc;
-        mCi = cid.mCi;
-        mPci = cid.mPci;
-        mTac = cid.mTac;
-    }
-
-    /**
-     * @return 3-digit Mobile Country Code, 0..999
-     */
-    public int getMcc() {
-        return mMcc;
-    }
-
-    /**
-     * @return 2 or 3-digit Mobile Network Code, 0..999
-     */
-    public int getMnc() {
-        return mMnc;
-    }
-
-    /**
-     * @return 28-bit Cell Identity
-     */
-    public int getCi() {
-        return mCi;
-    }
-
-    /**
-     * @return Physical Cell Id 0..503
-     */
-    public int getPci() {
-        return mPci;
-    }
-
-    /**
-     * @return 16-bit Tracking Area Code
-     */
-    public int getTac() {
-        return mTac;
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
-        dest.writeInt(mMcc);
-        dest.writeInt(mMnc);
-        dest.writeInt(mCi);
-        dest.writeInt(mPci);
-        dest.writeInt(mTac);
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    public static final Creator<LteCellIdentity> CREATOR =
-            new Creator<LteCellIdentity>() {
-        @Override
-        public LteCellIdentity createFromParcel(Parcel in) {
-            return new LteCellIdentity(in);
-        }
-
-        @Override
-        public LteCellIdentity[] newArray(int size) {
-            return new LteCellIdentity[size];
-        }
-    };
-}
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index def6939..f3ccae6 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -27,6 +27,8 @@
 
 import com.android.internal.telephony.IPhoneStateListener;
 
+import java.util.List;
+
 /**
  * A listener class for monitoring changes in specific telephony states
  * on the device, including service state, signal strength, message
@@ -160,7 +162,6 @@
      * Listen for changes to observed cell info.
      *
      * @see #onCellInfoChanged
-     * @hide pending API review
      */
     public static final int LISTEN_CELL_INFO = 0x00000400;
 
@@ -284,17 +285,11 @@
     }
 
     /**
-     * Callback invoked when a observed cell info gets changed.
-     *
-     * A notification should be sent when:
-     *     1. a cell is newly-observed.
-     *     2. a observed cell is not visible.
-     *     3. any of the cell info of a observed cell has changed.
-     *
-     * @hide pending API review
+     * Callback invoked when a observed cell info has changed,
+     * or new cells have been added or removed.
+     * @param cellInfo is the list of currently visible cells.
      */
-    public void onCellInfoChanged(CellInfo cellInfo) {
-        // default implementation empty
+    public void onCellInfoChanged(List<CellInfo> cellInfo) {
     }
 
     /**
@@ -346,8 +341,8 @@
             Message.obtain(mHandler, LISTEN_OTASP_CHANGED, otaspMode, 0).sendToTarget();
         }
 
-        public void onCellInfoChanged(CellInfo cellInfo) {
-            Message.obtain(mHandler, LISTEN_CELL_INFO, 0, 0).sendToTarget();
+        public void onCellInfoChanged(List<CellInfo> cellInfo) {
+            Message.obtain(mHandler, LISTEN_CELL_INFO, 0, 0, cellInfo).sendToTarget();
         }
     };
 
@@ -387,7 +382,7 @@
                     PhoneStateListener.this.onOtaspChanged(msg.arg1);
                     break;
                 case LISTEN_CELL_INFO:
-                    PhoneStateListener.this.onCellInfoChanged((CellInfo)msg.obj);
+                    PhoneStateListener.this.onCellInfoChanged((List<CellInfo>)msg.obj);
             }
         }
     };
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
old mode 100755
new mode 100644
index 92b889b..f998935
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -1,6 +1,5 @@
 /*
- * Copyright (C) 2009 Qualcomm Innovation Center, Inc.  All Rights Reserved.
- * Copyright (C) 2009 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.
@@ -65,6 +64,7 @@
     private int mLteCqi;
 
     private boolean isGsm; // This value is set by the ServiceStateTracker onSignalStrengthResult
+
     /**
      * Create a new SignalStrength from a intent notifier Bundle
      *
@@ -137,6 +137,83 @@
             int cdmaDbm, int cdmaEcio,
             int evdoDbm, int evdoEcio, int evdoSnr,
             int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
+            boolean gsmFlag) {
+        initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
+                evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
+                lteRsrq, lteRssnr, lteCqi, gsmFlag);
+    }
+
+    /**
+     * Constructor
+     *
+     * @hide
+     */
+    public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
+            int cdmaDbm, int cdmaEcio,
+            int evdoDbm, int evdoEcio, int evdoSnr,
+            boolean gsmFlag) {
+        initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
+                evdoDbm, evdoEcio, evdoSnr, 99, INVALID,
+                INVALID, INVALID, INVALID, gsmFlag);
+    }
+
+    /**
+     * Copy constructors
+     *
+     * @param s Source SignalStrength
+     *
+     * @hide
+     */
+    public SignalStrength(SignalStrength s) {
+        copyFrom(s);
+    }
+
+    /**
+     * Initialize gsm/cdma values, sets lte values to defaults.
+     *
+     * @param gsmSignalStrength
+     * @param gsmBitErrorRate
+     * @param cdmaDbm
+     * @param cdmaEcio
+     * @param evdoDbm
+     * @param evdoEcio
+     * @param evdoSnr
+     * @param gsm
+     *
+     * @hide
+     */
+    public void initialize(int gsmSignalStrength, int gsmBitErrorRate,
+            int cdmaDbm, int cdmaEcio,
+            int evdoDbm, int evdoEcio, int evdoSnr,
+            boolean gsm) {
+        initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
+                evdoDbm, evdoEcio, evdoSnr, 99, INVALID,
+                INVALID, INVALID, INVALID, gsm);
+    }
+
+    /**
+     * Initialize all the values
+     *
+     * @param gsmSignalStrength
+     * @param gsmBitErrorRate
+     * @param cdmaDbm
+     * @param cdmaEcio
+     * @param evdoDbm
+     * @param evdoEcio
+     * @param evdoSnr
+     * @param lteSignalStrength
+     * @param lteRsrp
+     * @param lteRsrq
+     * @param lteRssnr
+     * @param lteCqi
+     * @param gsm
+     *
+     * @hide
+     */
+    public void initialize(int gsmSignalStrength, int gsmBitErrorRate,
+            int cdmaDbm, int cdmaEcio,
+            int evdoDbm, int evdoEcio, int evdoSnr,
+            int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
             boolean gsm) {
         mGsmSignalStrength = gsmSignalStrength;
         mGsmBitErrorRate = gsmBitErrorRate;
@@ -151,30 +228,7 @@
         mLteRssnr = lteRssnr;
         mLteCqi = lteCqi;
         isGsm = gsm;
-    }
-
-    /**
-     * Constructor
-     *
-     * @hide
-     */
-    public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
-            int cdmaDbm, int cdmaEcio,
-            int evdoDbm, int evdoEcio, int evdoSnr,
-            boolean gsm) {
-         this(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio, evdoDbm, evdoEcio, evdoSnr, 99,
-                INVALID, INVALID, INVALID, INVALID, gsm);
-    }
-
-    /**
-     * Copy constructors
-     *
-     * @param s Source SignalStrength
-     *
-     * @hide
-     */
-    public SignalStrength(SignalStrength s) {
-        copyFrom(s);
+        if (DBG) log("initialize: " + toString());
     }
 
     /**
@@ -202,6 +256,8 @@
      * @hide
      */
     public SignalStrength(Parcel in) {
+        if (DBG) log("Size of signalstrength parcel:" + in.dataSize());
+
         mGsmSignalStrength = in.readInt();
         mGsmBitErrorRate = in.readInt();
         mCdmaDbm = in.readInt();
@@ -354,6 +410,31 @@
         return this.mEvdoSnr;
     }
 
+    /** @hide */
+    public int getLteSignalStrenght() {
+        return mLteSignalStrength;
+    }
+
+    /** @hide */
+    public int getLteRsrp() {
+        return mLteRsrp;
+    }
+
+    /** @hide */
+    public int getLteRsrq() {
+        return mLteRsrq;
+    }
+
+    /** @hide */
+    public int getLteRssnr() {
+        return mLteRssnr;
+    }
+
+    /** @hide */
+    public int getLteCqi() {
+        return mLteCqi;
+    }
+
     /**
      * Get signal level as an int from 0..4
      *
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index fa4b7cd..2fa41e7 100755
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -220,6 +220,7 @@
     public CellLocation getCellLocation() {
         try {
             Bundle bundle = getITelephony().getCellLocation();
+            if (bundle.isEmpty()) return null;
             CellLocation cl = CellLocation.newFromBundle(bundle);
             if (cl.isEmpty())
                 return null;
@@ -1271,8 +1272,6 @@
      *
      * <p>Requires Permission:
      * (@link android.Manifest.permission#ACCESS_COARSE_UPDATES}
-     *
-     * @hide pending API review
      */
     public List<CellInfo> getAllCellInfo() {
         try {
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index d6a1edd..3a04ceb 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -34,6 +34,6 @@
     void onDataActivity(int direction);
     void onSignalStrengthsChanged(in SignalStrength signalStrength);
     void onOtaspChanged(in int otaspMode);
-    void onCellInfoChanged(in CellInfo cellInfo);
+    void onCellInfoChanged(in List<CellInfo> cellInfo);
 }
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 3c9a99b..59c8472 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -40,5 +40,5 @@
     void notifyDataConnectionFailed(String reason, String apnType);
     void notifyCellLocation(in Bundle cellLocation);
     void notifyOtaspChanged(in int otaspMode);
-    void notifyCellInfo(in CellInfo cellInfo);
+    void notifyCellInfo(in List<CellInfo> cellInfo);
 }
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index 6d81b71..0d9e4f1 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_JAVA_LIBRARIES := core core-junit framework
+LOCAL_STATIC_JAVA_LIBRARIES := junit-runner
 
 LOCAL_MODULE:= android.test.runner
 
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index bf583e1..1f815e7 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -28,6 +28,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.AssetManager;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.DatabaseErrorHandler;
 import android.database.sqlite.SQLiteDatabase;
@@ -37,6 +38,9 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.UserHandle;
+import android.view.CompatibilityInfoHolder;
+import android.view.Display;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -284,12 +288,6 @@
         throw new UnsupportedOperationException();
     }
 
-    /** @hide */
-    @Override
-    public void sendBroadcast(Intent intent, int userId) {
-        throw new UnsupportedOperationException();
-    }
-
     @Override
     public void sendBroadcast(Intent intent, String receiverPermission) {
         throw new UnsupportedOperationException();
@@ -309,6 +307,24 @@
     }
 
     @Override
+    public void sendBroadcastAsUser(Intent intent, UserHandle user) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void sendBroadcastAsUser(Intent intent, UserHandle user,
+            String receiverPermission) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
+            String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
+            int initialCode, String initialData, Bundle initialExtras) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void sendStickyBroadcast(Intent intent) {
         throw new UnsupportedOperationException();
     }
@@ -326,6 +342,24 @@
     }
 
     @Override
+    public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void sendStickyOrderedBroadcastAsUser(Intent intent,
+            UserHandle user, BroadcastReceiver resultReceiver,
+            Handler scheduler, int initialCode, String initialData,
+            Bundle initialExtras) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
         throw new UnsupportedOperationException();
     }
@@ -336,6 +370,13 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+            IntentFilter filter, String broadcastPermission, Handler scheduler) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public void unregisterReceiver(BroadcastReceiver receiver) {
         throw new UnsupportedOperationException();
@@ -351,6 +392,18 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public ComponentName startServiceAsUser(Intent service, UserHandle user) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** @hide */
+    @Override
+    public boolean stopServiceAsUser(Intent service, UserHandle user) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public boolean bindService(Intent service, ServiceConnection conn, int flags) {
         throw new UnsupportedOperationException();
@@ -470,8 +523,31 @@
         throw new UnsupportedOperationException();
     }
 
+    /** {@hide} */
+    @Override
+    public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
+            throws PackageManager.NameNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Context createConfigurationContext(Configuration overrideConfiguration) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Context createDisplayContext(Display display) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public boolean isRestricted() {
         throw new UnsupportedOperationException();        
     }
+
+    /** @hide */
+    @Override
+    public CompatibilityInfoHolder getCompatibilityInfo(int displayId) {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 86689f3..2eba4e1 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -38,8 +38,9 @@
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.UserInfo;
+import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
@@ -138,6 +139,12 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public List<PackageInfo> getInstalledPackages(int flags, int userId) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public int checkPermission(String permName, String pkgName) {
         throw new UnsupportedOperationException();
@@ -208,11 +215,24 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent,
+                                                   int flags, int userId) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
             Intent[] specifics, Intent intent, int flags) {
@@ -224,6 +244,12 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags, int userId) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public ResolveInfo resolveService(Intent intent, int flags) {
         throw new UnsupportedOperationException();
@@ -234,6 +260,12 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public ProviderInfo resolveContentProvider(String name, int flags) {
         throw new UnsupportedOperationException();
@@ -340,6 +372,12 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public Resources getResourcesForApplicationAsUser(String appPackageName, int userId) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) {
         throw new UnsupportedOperationException();
@@ -479,7 +517,8 @@
      * @hide - to match hiding in superclass
      */
     @Override
-    public void getPackageSizeInfo(String packageName, IPackageStatsObserver observer) {
+    public void getPackageSizeInfo(String packageName, int userHandle,
+            IPackageStatsObserver observer) {
         throw new UnsupportedOperationException();
     }
 
@@ -513,65 +552,42 @@
      * @hide
      */
     @Override
-    public UserInfo createUser(String name, int flags) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public List<UserInfo> getUsers() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public UserInfo getUser(int userId) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public boolean removeUser(int id) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public void updateUserName(int id, String name) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public void updateUserFlags(int id, int flags) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @hide
-     */
-    @Override
     public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
             int flags, String installerPackageName, Uri verificationURI,
             ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public void installPackageWithVerificationAndEncryption(Uri packageURI,
+            IPackageInstallObserver observer, int flags, String installerPackageName,
+            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public int installExistingPackage(String packageName)
+            throws NameNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public void verifyPendingInstall(int id, int verificationCode) {
         throw new UnsupportedOperationException();
     }
 
+    @Override
+    public void extendVerificationTimeout(int id, int verificationCodeAtTimeout,
+            long millisecondsToDelay) {
+        throw new UnsupportedOperationException();
+    }
+
     /**
      * @hide
      */
diff --git a/test-runner/src/junit/runner/BaseTestRunner.java b/test-runner/src/junit/runner/BaseTestRunner.java
deleted file mode 100644
index 8cfd7fa..0000000
--- a/test-runner/src/junit/runner/BaseTestRunner.java
+++ /dev/null
@@ -1,342 +0,0 @@
-package junit.runner;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintWriter;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.text.NumberFormat;
-import java.util.Properties;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.Test;
-import junit.framework.TestListener;
-import junit.framework.TestSuite;
-
-/**
- * Base class for all test runners.
- * This class was born live on stage in Sardinia during XP2000.
- */
-public abstract class BaseTestRunner implements TestListener {
-    public static final String SUITE_METHODNAME= "suite";
-
-    private static Properties fPreferences;
-    static int fgMaxMessageLength= 500;
-    static boolean fgFilterStack= true;
-    boolean fLoading= true;
-
-    /*
-     * Implementation of TestListener
-     */
-    public synchronized void startTest(Test test) {
-        testStarted(test.toString());
-    }
-
-    protected static void setPreferences(Properties preferences) {
-        fPreferences= preferences;
-    }
-
-    protected static Properties getPreferences() {
-        if (fPreferences == null) {
-            fPreferences= new Properties();
-            fPreferences.put("loading", "true");
-            fPreferences.put("filterstack", "true");
-            readPreferences();
-        }
-        return fPreferences;
-    }
-
-    public static void savePreferences() throws IOException {
-        FileOutputStream fos= new FileOutputStream(getPreferencesFile());
-        try {
-            getPreferences().store(fos, "");
-        } finally {
-            fos.close();
-        }
-    }
-
-    // android-changed remove 'static' qualifier for API compatibility
-    public void setPreference(String key, String value) {
-        getPreferences().put(key, value);
-    }
-
-    public synchronized void endTest(Test test) {
-        testEnded(test.toString());
-    }
-
-    public synchronized void addError(final Test test, final Throwable t) {
-        testFailed(TestRunListener.STATUS_ERROR, test, t);
-    }
-
-    public synchronized void addFailure(final Test test, final AssertionFailedError t) {
-        testFailed(TestRunListener.STATUS_FAILURE, test, t);
-    }
-
-    // TestRunListener implementation
-
-    public abstract void testStarted(String testName);
-
-    public abstract void testEnded(String testName);
-
-    public abstract void testFailed(int status, Test test, Throwable t);
-
-    /**
-     * Returns the Test corresponding to the given suite. This is
-     * a template method, subclasses override runFailed(), clearStatus().
-     */
-    public Test getTest(String suiteClassName) {
-        if (suiteClassName.length() <= 0) {
-            clearStatus();
-            return null;
-        }
-        Class testClass= null;
-        try {
-            testClass= loadSuiteClass(suiteClassName);
-        } catch (ClassNotFoundException e) {
-            String clazz= e.getMessage();
-            if (clazz == null)
-                clazz= suiteClassName;
-            runFailed("Class not found \""+clazz+"\"");
-            return null;
-        } catch(Exception e) {
-            runFailed("Error: "+e.toString());
-            return null;
-        }
-        Method suiteMethod= null;
-        try {
-            suiteMethod= testClass.getMethod(SUITE_METHODNAME, new Class[0]);
-        } catch(Exception e) {
-            // try to extract a test suite automatically
-            clearStatus();
-            return new TestSuite(testClass);
-        }
-        if (! Modifier.isStatic(suiteMethod.getModifiers())) {
-            runFailed("Suite() method must be static");
-            return null;
-        }
-        Test test= null;
-        try {
-            test= (Test)suiteMethod.invoke(null, (Object[])new Class[0]); // static method
-            if (test == null)
-                return test;
-        }
-        catch (InvocationTargetException e) {
-            runFailed("Failed to invoke suite():" + e.getTargetException().toString());
-            return null;
-        }
-        catch (IllegalAccessException e) {
-            runFailed("Failed to invoke suite():" + e.toString());
-            return null;
-        }
-
-        clearStatus();
-        return test;
-    }
-
-    /**
-     * Returns the formatted string of the elapsed time.
-     */
-    public String elapsedTimeAsString(long runTime) {
-        return NumberFormat.getInstance().format((double)runTime/1000);
-    }
-
-    /**
-     * Processes the command line arguments and
-     * returns the name of the suite class to run or null
-     */
-    protected String processArguments(String[] args) {
-        String suiteName= null;
-        for (int i= 0; i < args.length; i++) {
-            if (args[i].equals("-noloading")) {
-                setLoading(false);
-            } else if (args[i].equals("-nofilterstack")) {
-                fgFilterStack= false;
-            } else if (args[i].equals("-c")) {
-                if (args.length > i+1)
-                    suiteName= extractClassName(args[i+1]);
-                else
-                    System.out.println("Missing Test class name");
-                i++;
-            } else {
-                suiteName= args[i];
-            }
-        }
-        return suiteName;
-    }
-
-    /**
-     * Sets the loading behaviour of the test runner
-     */
-    public void setLoading(boolean enable) {
-        fLoading= enable;
-    }
-    /**
-     * Extract the class name from a String in VA/Java style
-     */
-    public String extractClassName(String className) {
-        if(className.startsWith("Default package for"))
-            return className.substring(className.lastIndexOf(".")+1);
-        return className;
-    }
-
-    /**
-     * Truncates a String to the maximum length.
-     */
-    public static String truncate(String s) {
-        if (fgMaxMessageLength != -1 && s.length() > fgMaxMessageLength)
-            s= s.substring(0, fgMaxMessageLength)+"...";
-        return s;
-    }
-
-    /**
-     * Override to define how to handle a failed loading of
-     * a test suite.
-     */
-    protected abstract void runFailed(String message);
-
-    // BEGIN android-changed - add back getLoader() for API compatibility
-    /**
-     * Returns the loader to be used.
-     * 
-     * @deprecated not present in JUnit4.10
-     */
-    public TestSuiteLoader getLoader() {
-        if (useReloadingTestSuiteLoader())
-            return new ReloadingTestSuiteLoader();
-        return new StandardTestSuiteLoader();
-    }
-    // END android-changed
-
-    /**
-     * Returns the loaded Class for a suite name.
-     */
-    protected Class<?> loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
-        return Class.forName(suiteClassName);
-    }
-
-    /**
-     * Clears the status message.
-     */
-    protected void clearStatus() { // Belongs in the GUI TestRunner class
-    }
-
-    protected boolean useReloadingTestSuiteLoader() {
-        return getPreference("loading").equals("true") && fLoading;
-    }
-
-    private static File getPreferencesFile() {
-        String home= System.getProperty("user.home");
-        return new File(home, "junit.properties");
-    }
-
-    private static void readPreferences() {
-        InputStream is= null;
-        try {
-            is= new FileInputStream(getPreferencesFile());
-            setPreferences(new Properties(getPreferences()));
-            getPreferences().load(is);
-        } catch (IOException e) {
-            try {
-                if (is != null)
-                    is.close();
-            } catch (IOException e1) {
-            }
-        }
-    }
-
-    public static String getPreference(String key) {
-        return getPreferences().getProperty(key);
-    }
-
-    public static int getPreference(String key, int dflt) {
-        String value= getPreference(key);
-        int intValue= dflt;
-        if (value == null)
-            return intValue;
-        try {
-            intValue= Integer.parseInt(value);
-        } catch (NumberFormatException ne) {
-        }
-        return intValue;
-    }
-
-    /**
-     * Returns a filtered stack trace
-     */
-    public static String getFilteredTrace(Throwable t) {
-        StringWriter stringWriter= new StringWriter();
-        PrintWriter writer= new PrintWriter(stringWriter);
-        t.printStackTrace(writer);
-        StringBuffer buffer= stringWriter.getBuffer();
-        String trace= buffer.toString();
-        return BaseTestRunner.getFilteredTrace(trace);
-    }
-
-    // BEGIN android-changed - add back this method for API compatibility
-    /** @deprecated not present in JUnit4.10 */
-    public static boolean inVAJava() {
-        return false;
-    }
-    // END android-changed
-
-    /**
-     * Filters stack frames from internal JUnit classes
-     */
-    public static String getFilteredTrace(String stack) {
-        if (showStackRaw())
-            return stack;
-
-        StringWriter sw= new StringWriter();
-        PrintWriter pw= new PrintWriter(sw);
-        StringReader sr= new StringReader(stack);
-        // BEGIN android-changed
-        // Use a sensible default buffer size
-        BufferedReader br= new BufferedReader(sr, 1000);
-        // END android-changed
-
-        String line;
-        try {
-            while ((line= br.readLine()) != null) {
-                if (!filterLine(line))
-                    pw.println(line);
-            }
-        } catch (Exception IOException) {
-            return stack; // return the stack unfiltered
-        }
-        return sw.toString();
-    }
-
-    protected static boolean showStackRaw() {
-        return !getPreference("filterstack").equals("true") || fgFilterStack == false;
-    }
-
-    static boolean filterLine(String line) {
-        String[] patterns= new String[] {
-                "junit.framework.TestCase",
-                "junit.framework.TestResult",
-                "junit.framework.TestSuite",
-                "junit.framework.Assert.", // don't filter AssertionFailure
-                "junit.swingui.TestRunner",
-                "junit.awtui.TestRunner",
-                "junit.textui.TestRunner",
-                "java.lang.reflect.Method.invoke("
-        };
-        for (int i= 0; i < patterns.length; i++) {
-            if (line.indexOf(patterns[i]) > 0)
-                return true;
-        }
-        return false;
-    }
-
-    static {
-        fgMaxMessageLength= getPreference("maxmessage", fgMaxMessageLength);
-    }
-
-}
diff --git a/test-runner/src/junit/runner/StandardTestSuiteLoader.java b/test-runner/src/junit/runner/StandardTestSuiteLoader.java
deleted file mode 100644
index 381e684..0000000
--- a/test-runner/src/junit/runner/StandardTestSuiteLoader.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package junit.runner;
-
-/**
- * The standard test suite loader. It can only load the same class once.
- * {@hide} - Not needed for 1.0 SDK
- */
-public class StandardTestSuiteLoader implements TestSuiteLoader {
-    /**
-     * Uses the system class loader to load the test class
-     */
-    public Class load(String suiteClassName) throws ClassNotFoundException {
-        return Class.forName(suiteClassName);
-    }
-    /**
-     * Uses the system class loader to load the test class
-     */
-    public Class reload(Class aClass) throws ClassNotFoundException {
-        return aClass;
-    }
-}
diff --git a/test-runner/src/junit/runner/TestRunListener.java b/test-runner/src/junit/runner/TestRunListener.java
deleted file mode 100644
index 0410f0c..0000000
--- a/test-runner/src/junit/runner/TestRunListener.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package junit.runner;
-/**
- * A listener interface for observing the
- * execution of a test run. Unlike TestListener,
- * this interface using only primitive objects,
- * making it suitable for remote test execution.
- * {@hide} - Not needed for 1.0 SDK
- */
-public interface TestRunListener {
-    /* test status constants*/
-    public static final int STATUS_ERROR= 1;
-    public static final int STATUS_FAILURE= 2;
-
-    public void testRunStarted(String testSuiteName, int testCount);
-    public void testRunEnded(long elapsedTime);
-    public void testRunStopped(long elapsedTime);
-    public void testStarted(String testName);
-    public void testEnded(String testName);
-    public void testFailed(int status, String testName, String trace);
-}
diff --git a/test-runner/src/junit/runner/TestSuiteLoader.java b/test-runner/src/junit/runner/TestSuiteLoader.java
deleted file mode 100644
index 581ea23..0000000
--- a/test-runner/src/junit/runner/TestSuiteLoader.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package junit.runner;
-
-/**
- * An interface to define how a test suite should be loaded.
- */
-public interface TestSuiteLoader {
-    abstract public Class load(String suiteClassName) throws ClassNotFoundException;
-    abstract public Class reload(Class aClass) throws ClassNotFoundException;
-}
diff --git a/test-runner/src/junit/runner/Version.java b/test-runner/src/junit/runner/Version.java
deleted file mode 100644
index 4a6dc85..0000000
--- a/test-runner/src/junit/runner/Version.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package junit.runner;
-
-/**
- * This class defines the current version of JUnit
- */
-public class Version {
-    private Version() {
-        // don't instantiate
-    }
-
-    public static String id() {
-        return "4.10";
-    }
-
-    // android-changed
-    /** @hide - not needed for public API */
-    public static void main(String[] args) {
-        System.out.println(id());
-    }
-}
diff --git a/test-runner/src/junit/textui/ResultPrinter.java b/test-runner/src/junit/textui/ResultPrinter.java
deleted file mode 100644
index 4b26558..0000000
--- a/test-runner/src/junit/textui/ResultPrinter.java
+++ /dev/null
@@ -1,142 +0,0 @@
-
-package junit.textui;
-
-import java.io.PrintStream;
-// The following line was removed for compatibility with Android libraries.
-//import java.text.NumberFormat;
-import java.util.Enumeration;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.Test;
-import junit.framework.TestFailure;
-import junit.framework.TestListener;
-import junit.framework.TestResult;
-import junit.runner.BaseTestRunner;
-
-public class ResultPrinter implements TestListener {
-    PrintStream fWriter;
-    int fColumn= 0;
-
-    public ResultPrinter(PrintStream writer) {
-        fWriter= writer;
-    }
-
-    /* API for use by textui.TestRunner
-     */
-
-    synchronized void print(TestResult result, long runTime) {
-        printHeader(runTime);
-        printErrors(result);
-        printFailures(result);
-        printFooter(result);
-    }
-
-    void printWaitPrompt() {
-        getWriter().println();
-        getWriter().println("<RETURN> to continue");
-    }
-
-    /* Internal methods
-     */
-
-    protected void printHeader(long runTime) {
-        getWriter().println();
-        getWriter().println("Time: "+elapsedTimeAsString(runTime));
-    }
-
-    protected void printErrors(TestResult result) {
-        printDefects(result.errors(), result.errorCount(), "error");
-    }
-
-    protected void printFailures(TestResult result) {
-        printDefects(result.failures(), result.failureCount(), "failure");
-    }
-
-    protected void printDefects(Enumeration<TestFailure> booBoos, int count, String type) {
-        if (count == 0) return;
-        if (count == 1)
-            getWriter().println("There was " + count + " " + type + ":");
-        else
-            getWriter().println("There were " + count + " " + type + "s:");
-        for (int i= 1; booBoos.hasMoreElements(); i++) {
-            printDefect(booBoos.nextElement(), i);
-        }
-    }
-
-    public void printDefect(TestFailure booBoo, int count) { // only public for testing purposes
-        printDefectHeader(booBoo, count);
-        printDefectTrace(booBoo);
-    }
-
-    protected void printDefectHeader(TestFailure booBoo, int count) {
-        // I feel like making this a println, then adding a line giving the throwable a chance to print something
-        // before we get to the stack trace.
-        getWriter().print(count + ") " + booBoo.failedTest());
-    }
-
-    protected void printDefectTrace(TestFailure booBoo) {
-        getWriter().print(BaseTestRunner.getFilteredTrace(booBoo.trace()));
-    }
-
-    protected void printFooter(TestResult result) {
-        if (result.wasSuccessful()) {
-            getWriter().println();
-            getWriter().print("OK");
-            getWriter().println (" (" + result.runCount() + " test" + (result.runCount() == 1 ? "": "s") + ")");
-
-        } else {
-            getWriter().println();
-            getWriter().println("FAILURES!!!");
-            getWriter().println("Tests run: "+result.runCount()+
-                    ",  Failures: "+result.failureCount()+
-                    ",  Errors: "+result.errorCount());
-        }
-        getWriter().println();
-    }
-
-
-    /**
-     * Returns the formatted string of the elapsed time.
-     * Duplicated from BaseTestRunner. Fix it.
-     */
-    protected String elapsedTimeAsString(long runTime) {
-        // The following line was altered for compatibility with
-        // Android libraries.
-        return Double.toString((double)runTime/1000);
-    }
-
-    public PrintStream getWriter() {
-        return fWriter;
-    }
-    /**
-     * @see junit.framework.TestListener#addError(Test, Throwable)
-     */
-    public void addError(Test test, Throwable t) {
-        getWriter().print("E");
-    }
-
-    /**
-     * @see junit.framework.TestListener#addFailure(Test, AssertionFailedError)
-     */
-    public void addFailure(Test test, AssertionFailedError t) {
-        getWriter().print("F");
-    }
-
-    /**
-     * @see junit.framework.TestListener#endTest(Test)
-     */
-    public void endTest(Test test) {
-    }
-
-    /**
-     * @see junit.framework.TestListener#startTest(Test)
-     */
-    public void startTest(Test test) {
-        getWriter().print(".");
-        if (fColumn++ >= 40) {
-            getWriter().println();
-            fColumn= 0;
-        }
-    }
-
-}
diff --git a/test-runner/src/junit/textui/TestRunner.java b/test-runner/src/junit/textui/TestRunner.java
deleted file mode 100644
index e955e0e..0000000
--- a/test-runner/src/junit/textui/TestRunner.java
+++ /dev/null
@@ -1,203 +0,0 @@
-package junit.textui;
-
-
-import java.io.PrintStream;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestResult;
-import junit.framework.TestSuite;
-import junit.runner.BaseTestRunner;
-import junit.runner.Version;
-
-/**
- * A command line based tool to run tests.
- * <pre>
- * java junit.textui.TestRunner [-wait] TestCaseClass
- * </pre>
- * 
- * <p>TestRunner expects the name of a TestCase class as argument.
- * If this class defines a static <code>suite</code> method it
- * will be invoked and the returned test is run. Otherwise all
- * the methods starting with "test" having no arguments are run.
- * <p>
- * When the wait command line argument is given TestRunner
- * waits until the users types RETURN.
- * <p>
- * TestRunner prints a trace as the tests are executed followed by a
- * summary at the end.
- */
-public class TestRunner extends BaseTestRunner {
-    private ResultPrinter fPrinter;
-
-    public static final int SUCCESS_EXIT= 0;
-    public static final int FAILURE_EXIT= 1;
-    public static final int EXCEPTION_EXIT= 2;
-
-    /**
-     * Constructs a TestRunner.
-     */
-    public TestRunner() {
-        this(System.out);
-    }
-
-    /**
-     * Constructs a TestRunner using the given stream for all the output
-     */
-    public TestRunner(PrintStream writer) {
-        this(new ResultPrinter(writer));
-    }
-
-    /**
-     * Constructs a TestRunner using the given ResultPrinter all the output
-     */
-    public TestRunner(ResultPrinter printer) {
-        fPrinter= printer;
-    }
-
-    /**
-     * Runs a suite extracted from a TestCase subclass.
-     */
-    static public void run(Class<? extends TestCase> testClass) {
-        run(new TestSuite(testClass));
-    }
-
-    /**
-     * Runs a single test and collects its results.
-     * This method can be used to start a test run
-     * from your program.
-     * <pre>
-     * public static void main (String[] args) {
-     *    test.textui.TestRunner.run(suite());
-     * }
-     * </pre>
-     */
-    static public TestResult run(Test test) {
-        TestRunner runner= new TestRunner();
-        return runner.doRun(test);
-    }
-
-    /**
-     * Runs a single test and waits until the user
-     * types RETURN.
-     */
-    static public void runAndWait(Test suite) {
-        TestRunner aTestRunner= new TestRunner();
-        aTestRunner.doRun(suite, true);
-    }
-
-    @Override
-    public void testFailed(int status, Test test, Throwable t) {
-    }
-
-    @Override
-    public void testStarted(String testName) {
-    }
-
-    @Override
-    public void testEnded(String testName) {
-    }
-
-    /**
-     * Creates the TestResult to be used for the test run.
-     */
-    protected TestResult createTestResult() {
-        return new TestResult();
-    }
-
-    public TestResult doRun(Test test) {
-        return doRun(test, false);
-    }
-
-    public TestResult doRun(Test suite, boolean wait) {
-        TestResult result= createTestResult();
-        result.addListener(fPrinter);
-        long startTime= System.currentTimeMillis();
-        suite.run(result);
-        long endTime= System.currentTimeMillis();
-        long runTime= endTime-startTime;
-        fPrinter.print(result, runTime);
-
-        pause(wait);
-        return result;
-    }
-
-    protected void pause(boolean wait) {
-        if (!wait) return;
-        fPrinter.printWaitPrompt();
-        try {
-            System.in.read();
-        }
-        catch(Exception e) {
-        }
-    }
-
-    public static void main(String args[]) {
-        TestRunner aTestRunner= new TestRunner();
-        try {
-            TestResult r= aTestRunner.start(args);
-            if (!r.wasSuccessful())
-                System.exit(FAILURE_EXIT);
-            System.exit(SUCCESS_EXIT);
-        } catch(Exception e) {
-            System.err.println(e.getMessage());
-            System.exit(EXCEPTION_EXIT);
-        }
-    }
-
-    /**
-     * Starts a test run. Analyzes the command line arguments
-     * and runs the given test suite.
-     */
-    public TestResult start(String args[]) throws Exception {
-        String testCase= "";
-        String method= "";
-        boolean wait= false;
-
-        for (int i= 0; i < args.length; i++) {
-            if (args[i].equals("-wait"))
-                wait= true;
-            else if (args[i].equals("-c"))
-                testCase= extractClassName(args[++i]);
-            else if (args[i].equals("-m")) {
-                String arg= args[++i];
-                int lastIndex= arg.lastIndexOf('.');
-                testCase= arg.substring(0, lastIndex);
-                method= arg.substring(lastIndex + 1);
-            } else if (args[i].equals("-v"))
-                System.err.println("JUnit " + Version.id() + " by Kent Beck and Erich Gamma");
-            else
-                testCase= args[i];
-        }
-
-        if (testCase.equals(""))
-            throw new Exception("Usage: TestRunner [-wait] testCaseName, where name is the name of the TestCase class");
-
-        try {
-            if (!method.equals(""))
-                return runSingleMethod(testCase, method, wait);
-            Test suite= getTest(testCase);
-            return doRun(suite, wait);
-        } catch (Exception e) {
-            throw new Exception("Could not create and run test suite: " + e);
-        }
-    }
-
-    protected TestResult runSingleMethod(String testCase, String method, boolean wait) throws Exception {
-        Class<? extends TestCase> testClass= loadSuiteClass(testCase).asSubclass(TestCase.class);
-        Test test= TestSuite.createTest(testClass, method);
-        return doRun(test, wait);
-    }
-
-    @Override
-    protected void runFailed(String message) {
-        System.err.println(message);
-        System.exit(FAILURE_EXIT);
-    }
-
-    public void setPrinter(ResultPrinter printer) {
-        fPrinter= printer;
-    }
-
-
-}
diff --git a/tests/ActivityTests/AndroidManifest.xml b/tests/ActivityTests/AndroidManifest.xml
index de3b6d1..15d075c 100644
--- a/tests/ActivityTests/AndroidManifest.xml
+++ b/tests/ActivityTests/AndroidManifest.xml
@@ -20,6 +20,9 @@
     <uses-permission android:name="android.permission.REORDER_TASKS" />
     <uses-permission android:name="android.permission.REMOVE_TASKS" />
     <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+    <uses-permission android:name="android.permission.MANAGE_USERS" />
     <application android:label="ActivityTest">
         <activity android:name="ActivityTestMain">
             <intent-filter>
@@ -27,5 +30,18 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+        <service android:name="SingleUserService"
+            android:singleUser="true" android:exported="true">
+        </service>
+        <service android:name="ServiceUserTarget">
+        </service>
+        <receiver android:name="UserTarget">
+        </receiver>
+        <receiver android:name="SingleUserReceiver"
+            android:singleUser="true" android:exported="true" >
+        </receiver>
+        <provider android:name="SingleUserProvider"
+            android:authorities="com.google.android.test.activity.single_user"
+            android:singleUser="true" android:exported="true" />
     </application>
 </manifest>
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index ae42e29..f0c3b22 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -21,33 +21,54 @@
 
 import android.app.Activity;
 import android.app.ActivityManager;
-import android.app.ActivityThread;
 import android.app.AlertDialog;
-import android.app.Application;
 import android.content.ActivityNotFoundException;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentProviderClient;
+import android.content.Intent;
+import android.content.ServiceConnection;
 import android.os.Bundle;
-import android.graphics.BitmapFactory;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 import android.widget.ScrollView;
-import android.view.LayoutInflater;
+import android.widget.Toast;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
 import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.res.CompatibilityInfo;
-import android.util.DisplayMetrics;
+import android.content.pm.UserInfo;
+import android.content.res.Configuration;
 import android.util.Log;
 
 public class ActivityTestMain extends Activity {
+    static final String TAG = "ActivityTest";
+
+    static final String KEY_CONFIGURATION = "configuration";
+
     ActivityManager mAm;
+    Configuration mOverrideConfig;
+    int mSecondUser;
+
+    ArrayList<ServiceConnection> mConnections = new ArrayList<ServiceConnection>();
+
+    class BroadcastResultReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Bundle res = getResultExtras(true);
+            int user = res.getInt("user", -1);
+            Toast.makeText(ActivityTestMain.this,
+                    "Receiver executed as user "
+                    + (user >= 0 ? Integer.toString(user) : "unknown"),
+                    Toast.LENGTH_LONG).show();
+        }
+    }
 
     private void addThumbnail(LinearLayout container, Bitmap bm,
             final ActivityManager.RecentTaskInfo task,
@@ -101,6 +122,21 @@
         super.onCreate(savedInstanceState);
 
         mAm = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
+        if (savedInstanceState != null) {
+            mOverrideConfig = savedInstanceState.getParcelable(KEY_CONFIGURATION);
+            if (mOverrideConfig != null) {
+                applyOverrideConfiguration(mOverrideConfig);
+            }
+        }
+
+        UserManager um = (UserManager)getSystemService(Context.USER_SERVICE);
+        List<UserInfo> users = um.getUsers();
+        mSecondUser = Integer.MAX_VALUE;
+        for (UserInfo ui : users) {
+            if (ui.id != 0 && mSecondUser > ui.id) {
+                mSecondUser = ui.id;
+            }
+        }
     }
 
     @Override
@@ -114,6 +150,140 @@
                 return true;
             }
         });
+        menu.add("Bind!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+            @Override public boolean onMenuItemClick(MenuItem item) {
+                Intent intent = new Intent(ActivityTestMain.this, SingleUserService.class);
+                ServiceConnection conn = new ServiceConnection() {
+                    @Override
+                    public void onServiceConnected(ComponentName name, IBinder service) {
+                        Log.i(TAG, "Service connected " + name + " " + service);
+                    }
+                    @Override
+                    public void onServiceDisconnected(ComponentName name) {
+                        Log.i(TAG, "Service disconnected " + name);
+                    }
+                };
+                if (bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
+                    mConnections.add(conn);
+                } else {
+                    Toast.makeText(ActivityTestMain.this, "Failed to bind",
+                            Toast.LENGTH_LONG).show();
+                }
+                return true;
+            }
+        });
+        menu.add("Start!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+            @Override public boolean onMenuItemClick(MenuItem item) {
+                Intent intent = new Intent(ActivityTestMain.this, SingleUserService.class);
+                startService(intent);
+                return true;
+            }
+        });
+        menu.add("Send!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+            @Override public boolean onMenuItemClick(MenuItem item) {
+                Intent intent = new Intent(ActivityTestMain.this, SingleUserReceiver.class);
+                sendOrderedBroadcast(intent, null, new BroadcastResultReceiver(), 
+                        null, Activity.RESULT_OK, null, null);
+                return true;
+            }
+        });
+        menu.add("Call!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+            @Override public boolean onMenuItemClick(MenuItem item) {
+                ContentProviderClient cpl = getContentResolver().acquireContentProviderClient(
+                        SingleUserProvider.AUTHORITY);
+                Bundle res = null;
+                try {
+                    res = cpl.call("getuser", null, null);
+                } catch (RemoteException e) {
+                }
+                int user = res != null ? res.getInt("user", -1) : -1;
+                Toast.makeText(ActivityTestMain.this,
+                        "Provider executed as user "
+                        + (user >= 0 ? Integer.toString(user) : "unknown"),
+                        Toast.LENGTH_LONG).show();
+                cpl.release();
+                return true;
+            }
+        });
+        menu.add("Send to user 0!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+            @Override public boolean onMenuItemClick(MenuItem item) {
+                Intent intent = new Intent(ActivityTestMain.this, UserTarget.class);
+                sendOrderedBroadcastAsUser(intent, new UserHandle(0), null,
+                        new BroadcastResultReceiver(),
+                        null, Activity.RESULT_OK, null, null);
+                return true;
+            }
+        });
+        menu.add("Send to user " + mSecondUser + "!").setOnMenuItemClickListener(
+                new MenuItem.OnMenuItemClickListener() {
+            @Override public boolean onMenuItemClick(MenuItem item) {
+                Intent intent = new Intent(ActivityTestMain.this, UserTarget.class);
+                sendOrderedBroadcastAsUser(intent, new UserHandle(mSecondUser), null,
+                        new BroadcastResultReceiver(), 
+                        null, Activity.RESULT_OK, null, null);
+                return true;
+            }
+        });
+        menu.add("Bind to user 0!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+            @Override public boolean onMenuItemClick(MenuItem item) {
+                Intent intent = new Intent(ActivityTestMain.this, ServiceUserTarget.class);
+                ServiceConnection conn = new ServiceConnection() {
+                    @Override
+                    public void onServiceConnected(ComponentName name, IBinder service) {
+                        Log.i(TAG, "Service connected " + name + " " + service);
+                    }
+                    @Override
+                    public void onServiceDisconnected(ComponentName name) {
+                        Log.i(TAG, "Service disconnected " + name);
+                    }
+                };
+                if (bindService(intent, conn, Context.BIND_AUTO_CREATE, 0)) {
+                    mConnections.add(conn);
+                } else {
+                    Toast.makeText(ActivityTestMain.this, "Failed to bind",
+                            Toast.LENGTH_LONG).show();
+                }
+                return true;
+            }
+        });
+        menu.add("Bind to user " + mSecondUser + "!").setOnMenuItemClickListener(
+                new MenuItem.OnMenuItemClickListener() {
+            @Override public boolean onMenuItemClick(MenuItem item) {
+                Intent intent = new Intent(ActivityTestMain.this, ServiceUserTarget.class);
+                ServiceConnection conn = new ServiceConnection() {
+                    @Override
+                    public void onServiceConnected(ComponentName name, IBinder service) {
+                        Log.i(TAG, "Service connected " + name + " " + service);
+                    }
+                    @Override
+                    public void onServiceDisconnected(ComponentName name) {
+                        Log.i(TAG, "Service disconnected " + name);
+                    }
+                };
+                if (bindService(intent, conn, Context.BIND_AUTO_CREATE, mSecondUser)) {
+                    mConnections.add(conn);
+                } else {
+                    Toast.makeText(ActivityTestMain.this, "Failed to bind",
+                            Toast.LENGTH_LONG).show();
+                }
+                return true;
+            }
+        });
+        menu.add("Density!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+            @Override public boolean onMenuItemClick(MenuItem item) {
+                if (mOverrideConfig == null) {
+                    mOverrideConfig = new Configuration();
+                }
+                if (mOverrideConfig.densityDpi == Configuration.DENSITY_DPI_UNDEFINED) {
+                    mOverrideConfig.densityDpi = (getApplicationContext().getResources()
+                            .getConfiguration().densityDpi*2)/3;
+                } else {
+                    mOverrideConfig.densityDpi = Configuration.DENSITY_DPI_UNDEFINED;
+                }
+                recreate();
+                return true;
+            }
+        });
         return true;
     }
 
@@ -123,6 +293,23 @@
         buildUi();
     }
 
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        if (mOverrideConfig != null) {
+            outState.putParcelable(KEY_CONFIGURATION, mOverrideConfig);
+        }
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        for (ServiceConnection conn : mConnections) {
+            unbindService(conn);
+        }
+        mConnections.clear();
+    }
+
     private View scrollWrap(View view) {
         ScrollView scroller = new ScrollView(this);
         scroller.addView(view, new ScrollView.LayoutParams(ScrollView.LayoutParams.MATCH_PARENT,
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ServiceUserTarget.java b/tests/ActivityTests/src/com/google/android/test/activity/ServiceUserTarget.java
new file mode 100644
index 0000000..a7474ec
--- /dev/null
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ServiceUserTarget.java
@@ -0,0 +1,41 @@
+/*
+ * 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.google.android.test.activity;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.UserHandle;
+import android.widget.Toast;
+
+public class ServiceUserTarget extends Service {
+    Binder mBinder = new Binder();
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        Toast.makeText(this,
+                "Service created as user " + UserHandle.myUserId(),
+                Toast.LENGTH_LONG).show();
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+}
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/SingleUserProvider.java b/tests/ActivityTests/src/com/google/android/test/activity/SingleUserProvider.java
new file mode 100644
index 0000000..1e7b8f4
--- /dev/null
+++ b/tests/ActivityTests/src/com/google/android/test/activity/SingleUserProvider.java
@@ -0,0 +1,66 @@
+/*
+ * 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.google.android.test.activity;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.UserHandle;
+
+public class SingleUserProvider extends ContentProvider {
+    static final String AUTHORITY = "com.google.android.test.activity.single_user";
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        return null;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return null;
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public Bundle call(String method, String arg, Bundle extras) {
+        Bundle res = new Bundle();
+        res.putInt("user", UserHandle.myUserId());
+        return res;
+    }
+}
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/SingleUserReceiver.java b/tests/ActivityTests/src/com/google/android/test/activity/SingleUserReceiver.java
new file mode 100644
index 0000000..8afa478
--- /dev/null
+++ b/tests/ActivityTests/src/com/google/android/test/activity/SingleUserReceiver.java
@@ -0,0 +1,33 @@
+/*
+ * 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.google.android.test.activity;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.UserHandle;
+
+public class SingleUserReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        Bundle res = getResultExtras(true);
+        res.putInt("user", UserHandle.myUserId());
+        setResultExtras(res);
+    }
+}
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/SingleUserService.java b/tests/ActivityTests/src/com/google/android/test/activity/SingleUserService.java
new file mode 100644
index 0000000..e9c340f
--- /dev/null
+++ b/tests/ActivityTests/src/com/google/android/test/activity/SingleUserService.java
@@ -0,0 +1,41 @@
+/*
+ * 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.google.android.test.activity;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.UserHandle;
+import android.widget.Toast;
+
+public class SingleUserService extends Service {
+    Binder mBinder = new Binder();
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        Toast.makeText(this,
+                "Service created as user " + UserHandle.myUserId(),
+                Toast.LENGTH_LONG).show();
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+}
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/UserTarget.java b/tests/ActivityTests/src/com/google/android/test/activity/UserTarget.java
new file mode 100644
index 0000000..47539a1
--- /dev/null
+++ b/tests/ActivityTests/src/com/google/android/test/activity/UserTarget.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.test.activity;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.UserHandle;
+import android.util.Log;
+
+public class UserTarget extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        Log.i("ActivityTest", "Received: " + intent);
+        Bundle res = getResultExtras(true);
+        res.putInt("user", UserHandle.myUserId());
+        setResultExtras(res);
+    }
+}
diff --git a/tests/BiDiTests/AndroidPrivate.mk b/tests/BiDiTests/Android.mk
similarity index 100%
rename from tests/BiDiTests/AndroidPrivate.mk
rename to tests/BiDiTests/Android.mk
diff --git a/tests/Compatibility/Android.mk b/tests/Compatibility/Android.mk
new file mode 100644
index 0000000..5385413
--- /dev/null
+++ b/tests/Compatibility/Android.mk
@@ -0,0 +1,31 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files.
+LOCAL_SRC_FILES := \
+	$(call all-java-files-under, src)
+
+
+LOCAL_SDK_VERSION := 8
+LOCAL_PACKAGE_NAME := AppCompatibilityTest
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/Compatibility/AndroidManifest.xml b/tests/Compatibility/AndroidManifest.xml
new file mode 100644
index 0000000..103ef4c
--- /dev/null
+++ b/tests/Compatibility/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.compatibilitytest" >
+    <application >
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name=".AppCompatibilityRunner"
+        android:targetPackage="com.android.compatibilitytest"
+        android:label="App Compability Test Runner" />
+
+    <uses-sdk android:minSdkVersion="8"></uses-sdk>
+</manifest>
diff --git a/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
new file mode 100644
index 0000000..4d60c83
--- /dev/null
+++ b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
@@ -0,0 +1,165 @@
+/*
+ * 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.compatibilitytest;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.ProcessErrorStateInfo;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import junit.framework.Assert;
+
+import java.util.Collection;
+
+/**
+ * Application Compatibility Test that launches an application and detects crashes.
+ */
+public class AppCompatibility extends InstrumentationTestCase {
+
+    private static final String TAG = "AppCompability";
+    private static final String PACKAGE_TO_LAUNCH = "package_to_launch";
+    private static final String APP_LAUNCH_TIMEOUT_MSECS = "app_launch_timeout_ms";
+    private static final String WORKSPACE_LAUNCH_TIMEOUT_MSECS = "workspace_launch_timeout_ms";
+
+    private int mAppLaunchTimeout = 7000;
+    private int mWorkspaceLaunchTimeout = 2000;
+
+    private Context mContext;
+    private ActivityManager mActivityManager;
+    private PackageManager mPackageManager;
+    private AppCompatibilityRunner mRunner;
+    private Bundle mArgs;
+
+    @Override
+    public void setUp() throws Exception{
+        super.setUp();
+        mRunner = (AppCompatibilityRunner) getInstrumentation();
+        assertNotNull("Could not fetch InstrumentationTestRunner.",mRunner);
+
+        mContext = mRunner.getTargetContext();
+        Assert.assertNotNull("Could not get the Context", mContext);
+
+        mActivityManager = (ActivityManager)
+                mContext.getSystemService(Context.ACTIVITY_SERVICE);
+        Assert.assertNotNull("Could not get Activity Manager", mActivityManager);
+
+        mPackageManager = mContext.getPackageManager();
+        Assert.assertNotNull("Missing Package Manager", mPackageManager);
+
+        mArgs = mRunner.getBundle();
+
+        // Parse optional inputs.
+        String appLaunchTimeoutMsecs = mArgs.getString(APP_LAUNCH_TIMEOUT_MSECS);
+        if (appLaunchTimeoutMsecs != null) {
+            mAppLaunchTimeout = Integer.parseInt(appLaunchTimeoutMsecs);
+        }
+        String workspaceLaunchTimeoutMsecs = mArgs.getString(WORKSPACE_LAUNCH_TIMEOUT_MSECS);
+        if (workspaceLaunchTimeoutMsecs != null) {
+            mWorkspaceLaunchTimeout = Integer.parseInt(workspaceLaunchTimeoutMsecs);
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Actual test case that launches the package and throws an exception on the first error.
+     * @throws Exception
+     */
+    public void testAppStability() throws Exception {
+        String packageName = mArgs.getString(PACKAGE_TO_LAUNCH);
+        if (packageName != null) {
+            Log.d(TAG, "Launching app " + packageName);
+            Collection<ProcessErrorStateInfo> err = launchActivity(packageName);
+            // Make sure there are no errors when launching the application, otherwise raise an
+            // exception with the first error encountered.
+            assertNull(getFirstError(err), err);
+        } else {
+            Log.d(TAG, "Missing argument, use " + PACKAGE_TO_LAUNCH +
+                    " to specify the package to launch");
+        }
+    }
+
+    /**
+     * Gets the first error in collection and return the long message for it.
+     * @param in {@link Collection} of {@link ProcessErrorStateInfo} to parse.
+     * @return {@link String} the long message of the error.
+     */
+    private String getFirstError(Collection<ProcessErrorStateInfo> in) {
+        if (in == null) {
+            return null;
+        }
+        ProcessErrorStateInfo err = in.iterator().next();
+        if (err != null) {
+            return err.stackTrace;
+        }
+        return null;
+    }
+
+    /**
+     * Launches and activity and queries for errors.
+     * @param packageName {@link String} the package name of the application to launch.
+     * @return  {@link Collection} of {@link ProcessErrorStateInfo} detected during the app launch.
+     */
+    private Collection<ProcessErrorStateInfo> launchActivity(String packageName) {
+        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+        homeIntent.addCategory(Intent.CATEGORY_HOME);
+        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        Intent intent = mPackageManager.getLaunchIntentForPackage(packageName);
+
+        // We check for any Crash or ANR dialogs that are already up, and we ignore them.  This is
+        // so that we don't report crashes that were caused by prior apps (which those particular
+        // tests should have caught and reported already).  Otherwise, test failures would cascade
+        // from the initial broken app to many/all of the tests following that app's launch.
+        final Collection<ProcessErrorStateInfo> preErr = mActivityManager.getProcessesInErrorState();
+
+        // Launch Activity
+        mContext.startActivity(intent);
+
+        try {
+            Thread.sleep(mAppLaunchTimeout);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+
+        // Send the "home" intent and wait 2 seconds for us to get there
+        mContext.startActivity(homeIntent);
+        try {
+            Thread.sleep(mWorkspaceLaunchTimeout);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+
+        // See if there are any errors.  We wait until down here to give ANRs as much time as
+        // possible to occur.
+        final Collection<ProcessErrorStateInfo> postErr =
+                mActivityManager.getProcessesInErrorState();
+        // Take the difference between the error processes we see now, and the ones that were
+        // present when we started
+        if (preErr != null && postErr != null) {
+            postErr.removeAll(preErr);
+        }
+        return postErr;
+    }
+}
diff --git a/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibilityRunner.java b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibilityRunner.java
new file mode 100644
index 0000000..258937f
--- /dev/null
+++ b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibilityRunner.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibilitytest;
+
+import android.os.Bundle;
+import android.test.InstrumentationTestRunner;
+
+public class AppCompatibilityRunner extends InstrumentationTestRunner {
+
+    private Bundle mArgs;
+
+    @Override
+    public void onCreate(Bundle args) {
+        super.onCreate(args);
+        mArgs = args;
+    }
+
+    public Bundle getBundle() {
+        return mArgs;
+    }
+}
diff --git a/tests/DumpRenderTree/AndroidManifest.xml b/tests/DumpRenderTree/AndroidManifest.xml
index dc44b25..bcb821b 100644
--- a/tests/DumpRenderTree/AndroidManifest.xml
+++ b/tests/DumpRenderTree/AndroidManifest.xml
@@ -41,4 +41,6 @@
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.WRITE_SDCARD" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-sdk android:minSdkVersion="5"
+              android:targetSdkVersion="5" />
 </manifest>
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
index d74f5f7..9d621d6 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
@@ -19,7 +19,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
-import android.webkit.MockGeolocation;
 import android.webkit.WebStorage;
 
 import java.util.HashMap;
@@ -48,7 +47,6 @@
     private static final int EVENT_CLEAR_TOUCH_POINTS = 17;
     private static final int EVENT_CANCEL_TOUCH_POINT = 18;
     private static final int EVENT_SET_TOUCH_MODIFIER = 19;
-    
     private static final int LAYOUT_CLEAR_LIST = 20;
     private static final int LAYOUT_DISPLAY = 21;
     private static final int LAYOUT_DUMP_TEXT = 22;
@@ -72,10 +70,9 @@
     private static final int LAYOUT_WAIT_UNTIL_DONE = 40;
     private static final int LAYOUT_DUMP_DATABASE_CALLBACKS = 41;
     private static final int LAYOUT_SET_CAN_OPEN_WINDOWS = 42;
-    private static final int SET_GEOLOCATION_PERMISSION = 43;
-    private static final int OVERRIDE_PREFERENCE = 44;
-    private static final int LAYOUT_DUMP_CHILD_FRAMES_TEXT = 45;
-    private static final int SET_XSS_AUDITOR_ENABLED = 46;
+    private static final int OVERRIDE_PREFERENCE = 43;
+    private static final int LAYOUT_DUMP_CHILD_FRAMES_TEXT = 44;
+    private static final int SET_XSS_AUDITOR_ENABLED = 45;
     
     CallbackProxy(EventSender eventSender, 
             LayoutTestController layoutTestController) {
@@ -269,11 +266,6 @@
             mLayoutTestController.setCanOpenWindows();
             break;
 
-        case SET_GEOLOCATION_PERMISSION:
-            mLayoutTestController.setGeolocationPermission(
-                    msg.arg1 == 1 ? true : false);
-            break;
-
         case OVERRIDE_PREFERENCE:
             String key = msg.getData().getString("key");
             boolean value = msg.getData().getBoolean("value");
@@ -497,17 +489,23 @@
     public void setMockGeolocationPosition(double latitude,
                                            double longitude,
                                            double accuracy) {
-        MockGeolocation.getInstance().setPosition(latitude,
-                                                  longitude,
-                                                  accuracy);
+        // Configuration is in WebKit, so stay on WebCore thread, but go via the TestShellActivity
+        // as we need access to the Webview.
+        mLayoutTestController.setMockGeolocationPosition(latitude,
+                                                         longitude,
+                                                         accuracy);
     }
 
     public void setMockGeolocationError(int code, String message) {
-        MockGeolocation.getInstance().setError(code, message);
+        // Configuration is in WebKit, so stay on WebCore thread, but go via the TestShellActivity
+        // as we need access to the Webview.
+        mLayoutTestController.setMockGeolocationError(code, message);
     }
 
     public void setGeolocationPermission(boolean allow) {
-        obtainMessage(SET_GEOLOCATION_PERMISSION, allow ? 1 : 0, 0).sendToTarget();
+        // Configuration is in WebKit, so stay on WebCore thread, but go via the TestShellActivity
+        // as we need access to the Webview.
+        mLayoutTestController.setGeolocationPermission(allow);
     }
 
     public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java
index 9be2f1c..c936a6c 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java
@@ -72,6 +72,10 @@
     // For XSSAuditor tests
     public void setXSSAuditorEnabled(boolean flag);
 
+    // For Geolocation tests
+    public void setMockGeolocationPosition(double latitude, double longitude, double accuracy);
+    public void setMockGeolocationError(int code, String message);
+
     // For DeviceOrientation tests
     public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
             boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma);
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index bbfbfc4..42d6457 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -539,24 +539,21 @@
         mCanOpenWindows = true;
     }
 
-    /**
-     * Sets the Geolocation permission state to be used for all future requests.
-     */
+    @Override
+    public void setMockGeolocationPosition(double latitude, double longitude, double accuracy) {
+        WebViewClassic.fromWebView(mWebView).setMockGeolocationPosition(latitude, longitude,
+                accuracy);
+    }
+
+    @Override
+    public void setMockGeolocationError(int code, String message) {
+        WebViewClassic.fromWebView(mWebView).setMockGeolocationError(code, message);
+    }
+
     @Override
     public void setGeolocationPermission(boolean allow) {
-        mIsGeolocationPermissionSet = true;
-        mGeolocationPermission = allow;
-
-        if (mPendingGeolocationPermissionCallbacks != null) {
-            Iterator iter = mPendingGeolocationPermissionCallbacks.keySet().iterator();
-            while (iter.hasNext()) {
-                GeolocationPermissions.Callback callback =
-                        (GeolocationPermissions.Callback) iter.next();
-                String origin = (String) mPendingGeolocationPermissionCallbacks.get(callback);
-                callback.invoke(origin, mGeolocationPermission, false);
-            }
-            mPendingGeolocationPermissionCallbacks = null;
-        }
+        Log.v(LOGTAG, "setGeolocationPermission() allow=" + allow);
+        WebViewClassic.fromWebView(mWebView).setMockGeolocationPermission(allow);
     }
 
     @Override
@@ -749,22 +746,11 @@
             callback.updateQuota(currentQuota + 1024 * 1024 * 5);
         }
 
-        /**
-         * Instructs the client to show a prompt to ask the user to set the
-         * Geolocation permission state for the specified origin.
-         */
         @Override
         public void onGeolocationPermissionsShowPrompt(String origin,
                 GeolocationPermissions.Callback callback) {
-            if (mIsGeolocationPermissionSet) {
-                callback.invoke(origin, mGeolocationPermission, false);
-                return;
-            }
-            if (mPendingGeolocationPermissionCallbacks == null) {
-                mPendingGeolocationPermissionCallbacks =
-                        new HashMap<GeolocationPermissions.Callback, String>();
-            }
-            mPendingGeolocationPermissionCallbacks.put(callback, origin);
+            throw new RuntimeException(
+                    "The WebCore mock used by DRT should bypass the usual permissions flow.");
         }
 
         @Override
@@ -849,9 +835,8 @@
         mPageFinished = false;
         mDumpWebKitData = false;
         setDefaultWebSettings(mWebView);
-        mIsGeolocationPermissionSet = false;
-        mPendingGeolocationPermissionCallbacks = null;
         CookieManager.getInstance().removeAllCookie();
+        mWebViewClassic.setUseMockGeolocation();
     }
 
     private boolean canMoveToNextTest() {
@@ -958,8 +943,4 @@
     static final int DRAW_RUNS = 5;
     static final String DRAW_TIME_LOG = Environment.getExternalStorageDirectory() +
         "/android/page_draw_time.txt";
-
-    private boolean mIsGeolocationPermissionSet;
-    private boolean mGeolocationPermission;
-    private Map mPendingGeolocationPermissionCallbacks;
 }
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java
index d0c59d3..c9c35ce 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java
@@ -80,6 +80,17 @@
                 quota);
     }
 
+    public void setMockGeolocationPosition(double latitude, double longitude, double accuracy) {
+        Log.i(LOG_TAG, "setMockGeolocationPosition(): " + "latitude=" + latitude +
+                " longitude=" + longitude + " accuracy=" + accuracy);
+        mLayoutTestsExecutor.setMockGeolocationPosition(latitude, longitude, accuracy);
+    }
+
+    public void setMockGeolocationError(int code, String message) {
+        Log.i(LOG_TAG, "setMockGeolocationError(): " + "code=" + code + " message=" + message);
+        mLayoutTestsExecutor.setMockGeolocationError(code, message);
+    }
+
     public void setGeolocationPermission(boolean allow) {
         mLayoutTestsExecutor.setGeolocationPermission(allow);
     }
@@ -95,17 +106,6 @@
                 canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma);
     }
 
-    public void setMockGeolocationError(int code, String message) {
-        Log.i(LOG_TAG, "setMockGeolocationError(): " + "code=" + code + " message=" + message);
-        MockGeolocation.getInstance().setError(code, message);
-    }
-
-    public void setMockGeolocationPosition(double latitude, double longitude, double accuracy) {
-        Log.i(LOG_TAG, "setMockGeolocationPosition(): " + "latitude=" + latitude +
-                " longitude=" + longitude + " accuracy=" + accuracy);
-        MockGeolocation.getInstance().setPosition(latitude, longitude, accuracy);
-    }
-
     public void setXSSAuditorEnabled(boolean flag) {
         mLayoutTestsExecutor.setXSSAuditorEnabled(flag);
     }
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
index f958ade..25ac700 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
@@ -109,9 +109,6 @@
     private LayoutTestController mLayoutTestController = new LayoutTestController(this);
     private boolean mCanOpenWindows;
     private boolean mDumpDatabaseCallbacks;
-    private boolean mIsGeolocationPermissionSet;
-    private boolean mGeolocationPermission;
-    private Map<GeolocationPermissions.Callback, String> mPendingGeolocationPermissionCallbacks;
 
     private EventSender mEventSender = new EventSender();
 
@@ -255,15 +252,8 @@
         @Override
         public void onGeolocationPermissionsShowPrompt(String origin,
                 GeolocationPermissions.Callback callback) {
-            if (mIsGeolocationPermissionSet) {
-                callback.invoke(origin, mGeolocationPermission, false);
-                return;
-            }
-            if (mPendingGeolocationPermissionCallbacks == null) {
-                mPendingGeolocationPermissionCallbacks =
-                        new HashMap<GeolocationPermissions.Callback, String>();
-            }
-            mPendingGeolocationPermissionCallbacks.put(callback, origin);
+            throw new RuntimeException(
+                    "The WebCore mock used by DRT should bypass the usual permissions flow.");
         }
     };
 
@@ -394,6 +384,7 @@
         webViewSettings.setPageCacheCapacity(0);
 
         // This is asynchronous, but it gets processed by WebCore before it starts loading pages.
+        WebViewClassic.fromWebView(mCurrentWebView).setUseMockGeolocation();
         WebViewClassic.fromWebView(mCurrentWebView).setUseMockDeviceOrientation();
 
         // Must do this after setting the AppCache path.
@@ -573,9 +564,8 @@
     private static final int MSG_DUMP_CHILD_FRAMES_AS_TEXT = 3;
     private static final int MSG_SET_CAN_OPEN_WINDOWS = 4;
     private static final int MSG_DUMP_DATABASE_CALLBACKS = 5;
-    private static final int MSG_SET_GEOLOCATION_PERMISSION = 6;
-    private static final int MSG_OVERRIDE_PREFERENCE = 7;
-    private static final int MSG_SET_XSS_AUDITOR_ENABLED = 8;
+    private static final int MSG_OVERRIDE_PREFERENCE = 6;
+    private static final int MSG_SET_XSS_AUDITOR_ENABLED = 7;
 
     /** String constants for use with layoutTestController.overridePreference() */
     private final String WEBKIT_OFFLINE_WEB_APPLICATION_CACHE_ENABLED =
@@ -644,22 +634,6 @@
                     mCanOpenWindows = true;
                     break;
 
-                case MSG_SET_GEOLOCATION_PERMISSION:
-                    mIsGeolocationPermissionSet = true;
-                    mGeolocationPermission = msg.arg1 == 1;
-
-                    if (mPendingGeolocationPermissionCallbacks != null) {
-                        Iterator<GeolocationPermissions.Callback> iter =
-                                mPendingGeolocationPermissionCallbacks.keySet().iterator();
-                        while (iter.hasNext()) {
-                            GeolocationPermissions.Callback callback = iter.next();
-                            String origin = mPendingGeolocationPermissionCallbacks.get(callback);
-                            callback.invoke(origin, mGeolocationPermission, false);
-                        }
-                        mPendingGeolocationPermissionCallbacks = null;
-                    }
-                    break;
-
                 case MSG_SET_XSS_AUDITOR_ENABLED:
                     WebViewClassic.fromWebView(mCurrentWebView).getSettings().
                             setXSSAuditorEnabled(msg.arg1 == 1);
@@ -679,8 +653,6 @@
     private void resetLayoutTestController() {
         mCanOpenWindows = false;
         mDumpDatabaseCallbacks = false;
-        mIsGeolocationPermissionSet = false;
-        mPendingGeolocationPermissionCallbacks = null;
     }
 
     public void dumpAsText(boolean enablePixelTest) {
@@ -721,12 +693,19 @@
         mLayoutTestControllerHandler.sendEmptyMessage(MSG_SET_CAN_OPEN_WINDOWS);
     }
 
+    public void setMockGeolocationPosition(double latitude, double longitude, double accuracy) {
+        WebViewClassic.fromWebView(mCurrentWebView).setMockGeolocationPosition(latitude, longitude,
+                accuracy);
+    }
+
+    public void setMockGeolocationError(int code, String message) {
+        WebViewClassic.fromWebView(mCurrentWebView).setMockGeolocationError(code, message);
+    }
+
     public void setGeolocationPermission(boolean allow) {
         Log.i(LOG_TAG, mCurrentTestRelativePath + ": setGeolocationPermission(" + allow +
                 ") called");
-        Message msg = mLayoutTestControllerHandler.obtainMessage(MSG_SET_GEOLOCATION_PERMISSION);
-        msg.arg1 = allow ? 1 : 0;
-        msg.sendToTarget();
+        WebViewClassic.fromWebView(mCurrentWebView).setMockGeolocationPermission(allow);
     }
 
     public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 9e103ac..9118aea 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -33,6 +33,60 @@
         <meta-data android:name="android.graphics.renderThread" android:value="true" />
 
         <activity
+                android:name="MipMapActivity"
+                android:label="_MipMap">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
+                android:name="PathOffsetActivity"
+                android:label="_PathOffset">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
+                android:name="MultiLayersActivity"
+                android:label="_MultiLayers">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
+                android:name="TJunctionActivity"
+                android:label="_T-Junction">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
+                android:name="TextPathActivity"
+                android:label="_TextPath">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
+                android:name="GradientStopsActivity"
+                android:label="_GradientStops">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
                 android:name="PaintDrawFilterActivity"
                 android:label="_DrawFilter">
             <intent-filter>
@@ -42,6 +96,15 @@
         </activity>
 
         <activity
+                android:name="BigGradientActivity"
+                android:label="_BigGradient">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        
+        <activity
                 android:name="DatePickerActivity"
                 android:label="_DatePicker">
             <intent-filter>
@@ -150,6 +213,15 @@
         </activity>
 
         <activity
+                android:name="GlyphCacheActivity"
+                android:label="_GlyphCache">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
                 android:name="CanvasTextureViewActivity"
                 android:label="_CanvasTextureView">
             <intent-filter>
@@ -277,15 +349,6 @@
         </activity>
 
         <activity
-                android:name="ViewLayersActivity6"
-                android:label="_ViewLayers6">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-
-        <activity
                 android:name="AlphaLayersActivity"
                 android:label="_αLayers">
             <intent-filter>
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/very_large_photo.jpg b/tests/HwAccelerationTest/res/drawable-nodpi/very_large_photo.jpg
new file mode 100644
index 0000000..7f047b1
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/very_large_photo.jpg
Binary files differ
diff --git a/tests/HwAccelerationTest/res/layout/text_fade.xml b/tests/HwAccelerationTest/res/layout/text_fade.xml
index 8da2204..08a70b3 100644
--- a/tests/HwAccelerationTest/res/layout/text_fade.xml
+++ b/tests/HwAccelerationTest/res/layout/text_fade.xml
@@ -32,6 +32,7 @@
         android:ellipsize="marquee"
         android:fadingEdgeLength="16sp"
         android:fadingEdge="horizontal"
+        android:requiresFadingEdge="horizontal"
         android:text="This is a really really really really really really long string"
         android:textSize="16sp" />
 
diff --git a/tests/HwAccelerationTest/res/layout/view_layers_5.xml b/tests/HwAccelerationTest/res/layout/view_layers_5.xml
index 653f3a8..36cf8c9 100644
--- a/tests/HwAccelerationTest/res/layout/view_layers_5.xml
+++ b/tests/HwAccelerationTest/res/layout/view_layers_5.xml
@@ -26,16 +26,28 @@
         android:layout_weight="1">
 
         <Button
-            android:onClick="setLayerEnabled"
+            android:onClick="enableLayer"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="Enable layer" />
 
         <Button
-            android:onClick="setLayerDisabled"
+            android:onClick="disableLayer"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="Disable layer" />
+
+        <Button
+            android:onClick="shrinkLayer"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Shrink layer" />
+
+        <Button
+            android:onClick="growLayer"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Grow layer" />
         
     </LinearLayout>
 
diff --git a/tests/HwAccelerationTest/res/layout/view_layers_6.xml b/tests/HwAccelerationTest/res/layout/view_layers_6.xml
deleted file mode 100644
index 36cf8c9..0000000
--- a/tests/HwAccelerationTest/res/layout/view_layers_6.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="horizontal"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <LinearLayout
-        android:orientation="vertical"
-        android:layout_width="0dip"
-        android:layout_height="match_parent"
-        android:layout_weight="1">
-
-        <Button
-            android:onClick="enableLayer"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="Enable layer" />
-
-        <Button
-            android:onClick="disableLayer"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="Disable layer" />
-
-        <Button
-            android:onClick="shrinkLayer"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="Shrink layer" />
-
-        <Button
-            android:onClick="growLayer"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="Grow layer" />
-        
-    </LinearLayout>
-
-    <ListView
-        android:id="@+id/list1"
-        android:layout_width="0dip"
-        android:layout_height="match_parent"
-        android:layout_weight="1" />
-
-</LinearLayout>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BigGradientActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/BigGradientActivity.java
new file mode 100644
index 0000000..4d28f51
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/BigGradientActivity.java
@@ -0,0 +1,50 @@
+/*
+ * 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.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.Shader;
+import android.os.Bundle;
+import android.view.View;
+
+public class BigGradientActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        setContentView(new BigGradientView(this));
+    }
+
+    private class BigGradientView extends View {
+        public BigGradientView(Context context) {
+            super(context);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            Paint p = new Paint();
+            p.setShader(new LinearGradient(0.0f, 0.0f, 0.0f, getHeight(), 0xff000000,
+                    0xff333333, Shader.TileMode.CLAMP));
+
+            canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), p);
+        }
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshActivity.java
index 8cc2246..854dd69 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshActivity.java
@@ -68,9 +68,16 @@
             super.onDraw(canvas);
 
             canvas.drawARGB(255, 255, 255, 255);
+
             canvas.translate(100, 100);
             canvas.drawBitmapMesh(mBitmap1, 3, 3, mVertices, 0, null, 0, null);
 
+            canvas.save();
+            canvas.translate(0, 400);
+            canvas.clipRect(0.0f, 0.0f, 80.0f, 80.0f);
+            canvas.drawBitmapMesh(mBitmap1, 3, 3, mVertices, 0, null, 0, null);
+            canvas.restore();
+
             canvas.translate(400, 0);
             canvas.drawBitmapMesh(mBitmap1, 3, 3, mVertices, 0, mColors, 0, null);
         }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java
index e8cdbc3..7ea2a62d 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java
@@ -113,6 +113,12 @@
                 canvas.rotate(45);
                 canvas.drawRect(0, 0, 20, 10, p);
                 canvas.restore();
+                canvas.save();
+                canvas.translate(mOffset + 280, yOffset);
+                canvas.scale(0.5f, 8);
+                canvas.rotate(0.5f);
+                canvas.drawRect(0, 0, 80, 5, p);
+                canvas.restore();
                 canvas.restore();
 
                 yOffset += 100;
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java b/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java
index db247e3..eb4e3fd 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java
@@ -102,7 +102,7 @@
         inflater.inflate(R.layout.date_picker, this, true);
 
         mDayPicker = (NumberPicker) findViewById(R.id.day);
-        mDayPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
+        mDayPicker.setFormatter(NumberPicker.getTwoDigitFormatter());
         mDayPicker.setOnLongPressUpdateInterval(100);
         mDayPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
             public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
@@ -111,7 +111,7 @@
             }
         });
         mMonthPicker = (NumberPicker) findViewById(R.id.month);
-        mMonthPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
+        mMonthPicker.setFormatter(NumberPicker.getTwoDigitFormatter());
         DateFormatSymbols dfs = new DateFormatSymbols();
         String[] months = dfs.getShortMonths();
 
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
index 0e75b80..733e44f 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
@@ -22,7 +22,6 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
 import android.graphics.SurfaceTexture;
 import android.opengl.GLUtils;
 import android.os.Bundle;
@@ -278,7 +277,7 @@
             return texture;
         }
         
-        private int buildProgram(String vertex, String fragment) {
+        private static int buildProgram(String vertex, String fragment) {
             int vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
             if (vertexShader == 0) return 0;
 
@@ -309,7 +308,7 @@
             return program;
         }
         
-        private int buildShader(String source, int type) {
+        private static int buildShader(String source, int type) {
             int shader = glCreateShader(type);
 
             glShaderSource(shader, source);
@@ -337,7 +336,7 @@
             }
         }
 
-        private void checkGlError() {
+        private static void checkGlError() {
             int error = glGetError();
             if (error != GL_NO_ERROR) {
                 Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error));
@@ -420,7 +419,7 @@
             return null;
         }
         
-        private int[] getConfig() {
+        private static int[] getConfig() {
             return new int[] {
                     EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                     EGL10.EGL_RED_SIZE, 8,
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GlyphCacheActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GlyphCacheActivity.java
new file mode 100644
index 0000000..e89b294
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GlyphCacheActivity.java
@@ -0,0 +1,75 @@
+/*
+ * 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.test.hwui;
+
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import static android.widget.LinearLayout.LayoutParams;
+
+public class GlyphCacheActivity extends Activity {
+
+    private static final String mCharacterSet = "abcdefghijklmnopqrstuvwxyz" +
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "~!@#$%^&*()_+-={}[]:\";'<>?,./";
+    private int mTotalChars = 0;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        ScrollView scrollView = new ScrollView(this);
+        scrollView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT));
+        LinearLayout layout = new LinearLayout(this);
+        layout.setOrientation(LinearLayout.VERTICAL);
+        layout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT));
+        scrollView.addView(layout);
+
+        while (mTotalChars < 10000) {
+            layout.addView(createTextView());
+        }
+        setContentView(scrollView);
+    }
+
+    private TextView createTextView() {
+        TextView textview = new TextView(this);
+        textview.setTextSize(6 + (int) (Math.random() * 5) * 10);
+        textview.setTextColor(0xff << 24 | (int) (Math.random() * 255) << 16 |
+                (int) (Math.random() * 255) << 8 | (int) (Math.random() * 255) << 16);
+        textview.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT));
+        int numChars = 5 + (int) (Math.random() * 10);
+        mTotalChars += numChars;
+        textview.setText(createString(numChars));
+
+        return textview;
+    }
+
+    private String createString(int length) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < length; i++) {
+            sb.append(mCharacterSet.charAt((int)(Math.random() * mCharacterSet.length())));
+        }
+        return sb.toString();
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GradientStopsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GradientStopsActivity.java
new file mode 100644
index 0000000..a73eab5
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GradientStopsActivity.java
@@ -0,0 +1,125 @@
+/*
+ * 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.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.Shader;
+import android.os.Bundle;
+import android.view.View;
+
+@SuppressWarnings("UnusedDeclaration")
+public class GradientStopsActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        setContentView(new GradientView(this));
+    }
+
+    private class GradientView extends View {
+        public GradientView(Context context) {
+            super(context);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            int[] colors = new int[] { 0xffff0000, 0xff0000ff };
+            float[] positions = new float[] { 0.3f, 0.6f };
+            LinearGradient gradient = new LinearGradient(0.0f, 0.0f, 256.0f, 0.0f,
+                    colors, positions, Shader.TileMode.CLAMP);
+            
+            Paint paint = new Paint();
+            paint.setShader(gradient);
+
+            canvas.drawRect(0.0f, 0.0f, 256.0f, 50.0f, paint);
+
+            colors = new int[] { 0xffff0000, 0xff0000ff, 0xff00ff00 };
+            positions = new float[] { 0.3f, 0.6f, 1.0f };
+            gradient = new LinearGradient(0.0f, 0.0f, 256.0f, 0.0f,
+                    colors, positions, Shader.TileMode.CLAMP);
+
+            paint.setShader(gradient);
+
+            canvas.translate(0.0f, 75.0f);
+            canvas.drawRect(0.0f, 0.0f, 256.0f, 50.0f, paint);
+
+            colors = new int[] { 0xffff0000, 0xff0000ff, 0xff00ff00 };
+            positions = new float[] { 0.0f, 0.3f, 0.6f };
+            gradient = new LinearGradient(0.0f, 0.0f, 256.0f, 0.0f,
+                    colors, positions, Shader.TileMode.CLAMP);
+
+            paint.setShader(gradient);
+
+            canvas.translate(0.0f, 75.0f);
+            canvas.drawRect(0.0f, 0.0f, 256.0f, 50.0f, paint);
+
+            colors = new int[] { 0xff000000, 0xffffffff };
+            gradient = new LinearGradient(0.0f, 0.0f, 256.0f, 0.0f,
+                    colors, null, Shader.TileMode.CLAMP);
+
+            paint.setShader(gradient);
+
+            canvas.translate(0.0f, 75.0f);
+            canvas.drawRect(0.0f, 0.0f, 256.0f, 50.0f, paint);
+
+            gradient = new LinearGradient(0.0f, 0.0f, 256.0f, 0.0f,
+                    colors, null, Shader.TileMode.REPEAT);
+            
+            paint.setShader(gradient);
+
+            canvas.translate(0.0f, 75.0f);
+            canvas.drawRect(0.0f, 0.0f, 768.0f, 50.0f, paint);
+
+            gradient = new LinearGradient(0.0f, 0.0f, 256.0f, 0.0f,
+                    colors, null, Shader.TileMode.MIRROR);
+
+            paint.setShader(gradient);
+
+            canvas.translate(0.0f, 75.0f);
+            canvas.drawRect(0.0f, 0.0f, 768.0f, 50.0f, paint);
+
+            gradient = new LinearGradient(0.0f, 0.0f, 256.0f, 0.0f,
+                    colors, null, Shader.TileMode.CLAMP);
+
+            paint.setShader(gradient);
+
+            canvas.translate(0.0f, 75.0f);
+            canvas.drawRect(0.0f, 0.0f, 768.0f, 50.0f, paint);
+
+            gradient = new LinearGradient(0.0f, 0.0f, 768.0f, 0.0f,
+                    colors, null, Shader.TileMode.CLAMP);
+
+            paint.setShader(gradient);
+
+            canvas.translate(0.0f, 75.0f);
+            canvas.drawRect(0.0f, 0.0f, 768.0f, 50.0f, paint);
+
+            gradient = new LinearGradient(0.0f, 0.0f, 512.0f, 0.0f,
+                    colors, null, Shader.TileMode.CLAMP);
+
+            paint.setShader(gradient);
+
+            canvas.translate(0.0f, 75.0f);
+            canvas.drawRect(0.0f, 0.0f, 512.0f, 50.0f, paint);
+        }
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java
index f0abb50..eed0ec8 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java
@@ -153,6 +153,14 @@
             canvas.drawLine(10.0f, 45.0f, 20.0f, 55.0f, mSmallPaint);
             canvas.drawLine(10.0f, 60.0f, 50.0f, 60.0f, mHairLinePaint);
             canvas.restore();
+
+            canvas.save();
+            canvas.scale(10.0f, 50.0f);
+            mSmallPaint.setStrokeWidth(0.0f);
+            canvas.drawLine(20.0f, 9.0f, 30.0f, 11.0f, mSmallPaint);
+            mSmallPaint.setStrokeWidth(1.0f);
+            canvas.drawLine(30.0f, 9.0f, 40.0f, 11.0f, mSmallPaint);
+            canvas.restore();
         }
     }
 }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MipMapActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MipMapActivity.java
new file mode 100644
index 0000000..1034649
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MipMapActivity.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.ScaleAnimation;
+import android.widget.FrameLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class MipMapActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final BitmapsView view = new BitmapsView(this);
+        setContentView(view);
+    }
+
+    static class BitmapsView extends View {
+        private Paint mBitmapPaint;
+        private final Bitmap mBitmap1;
+        private final Bitmap mBitmap2;
+
+        BitmapsView(Context c) {
+            super(c);
+
+            mBitmap1 = BitmapFactory.decodeResource(c.getResources(), R.drawable.very_large_photo);
+            mBitmap2 = BitmapFactory.decodeResource(c.getResources(), R.drawable.very_large_photo);
+
+            mBitmap1.setHasMipMap(true);
+
+            mBitmapPaint = new Paint();
+            mBitmapPaint.setFilterBitmap(true);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            super.onDraw(canvas);
+
+            canvas.save();
+            canvas.scale(0.3f, 0.3f);
+            canvas.drawBitmap(mBitmap1, 0, 0, mBitmapPaint);
+            canvas.restore();
+
+            canvas.save();
+            canvas.translate(mBitmap1.getWidth() * 0.3f + 96.0f, 0.0f);
+            canvas.scale(0.3f, 0.3f);
+            canvas.drawBitmap(mBitmap2, 0, 0, mBitmapPaint);
+            canvas.restore();
+        }
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MultiLayersActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MultiLayersActivity.java
new file mode 100644
index 0000000..eb8a0a9
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MultiLayersActivity.java
@@ -0,0 +1,75 @@
+/*
+ * 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.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.LinearLayout;
+
+@SuppressWarnings("UnusedDeclaration")
+public class MultiLayersActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        LinearLayout grid = new LinearLayout(this);
+        grid.setOrientation(LinearLayout.VERTICAL);
+
+        LinearLayout row1 = new LinearLayout(this);
+        row1.setOrientation(LinearLayout.HORIZONTAL);
+        grid.addView(row1, new LinearLayout.LayoutParams(
+                LinearLayout.LayoutParams.MATCH_PARENT, 0, 1.0f));
+
+        LinearLayout row2 = new LinearLayout(this);
+        row2.setOrientation(LinearLayout.HORIZONTAL);
+        grid.addView(row2, new LinearLayout.LayoutParams(
+                LinearLayout.LayoutParams.MATCH_PARENT, 0, 1.0f));
+
+        row1.addView(new LayerView(this, 0xffff0000), new LinearLayout.LayoutParams(
+                0, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f));
+        row1.addView(new LayerView(this, 0x0f00ff00), new LinearLayout.LayoutParams(
+                0, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f));
+
+        row2.addView(new LayerView(this, 0x0f0000ff), new LinearLayout.LayoutParams(
+                0, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f));
+        row2.addView(new LayerView(this, 0xffffff00), new LinearLayout.LayoutParams(
+                0, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f));
+
+        setContentView(grid);
+    }
+
+    private class LayerView extends View {
+        private final Paint mPaint;
+
+        public LayerView(Context context, int color) {
+            super(context);
+            mPaint = new Paint();
+            mPaint.setColor(color);
+            setLayerType(LAYER_TYPE_HARDWARE, null);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mPaint);
+            invalidate();
+        }
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PathOffsetActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PathOffsetActivity.java
new file mode 100644
index 0000000..fa73de1
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PathOffsetActivity.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.os.Bundle;
+import android.view.MotionEvent;
+import android.view.View;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class PathOffsetActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final PathsView view = new PathsView(this);
+        setContentView(view);
+    }
+
+    public class PathsView extends View {
+        private Path mPath;
+        private Paint mPaint;
+
+        public PathsView(Context context) {
+            super(context);
+
+            mPaint = new Paint();
+            mPaint.setStyle(Paint.Style.STROKE);
+            mPaint.setStrokeWidth(3);
+
+            mPath = new Path();
+            mPath.lineTo(100, 100);
+            mPath.lineTo(200, 300);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            mPath.offset(1, 1);
+            mPaint.setColor(Color.RED);
+            canvas.drawPath(mPath, mPaint);
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent event) {
+            invalidate();
+            return super.onTouchEvent(event);
+        }
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TJunctionActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TJunctionActivity.java
new file mode 100644
index 0000000..d2bcae9
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TJunctionActivity.java
@@ -0,0 +1,81 @@
+/*
+ * 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.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.view.View;
+
+@SuppressWarnings("UnusedDeclaration")
+public class TJunctionActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(new TJunctionView(this));
+    }
+
+    private class TJunctionView extends View {
+        private final Paint mPaint;
+
+        public TJunctionView(Context context) {
+            super(context);
+
+            setLayerType(LAYER_TYPE_HARDWARE, null);
+
+            mPaint = new Paint();
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            super.onDraw(canvas);
+
+            mPaint.setColor(0xffff0000);
+
+            canvas.translate(10.0f, 10.0f);
+            canvas.drawRect(0.0f, 0.0f, 100.0f, 50.0f, mPaint);
+
+            mPaint.setColor(0xff00ff00);
+
+            canvas.translate(50.0f, 50.0f);
+            canvas.drawRect(0.0f, 0.0f, 100.0f, 50.0f, mPaint);
+
+            mPaint.setColor(0xff0000ff);
+
+            canvas.translate(-25.0f, 50.0f);
+            canvas.drawRect(0.0f, 0.0f, 100.0f, 50.0f, mPaint);
+
+            mPaint.setColor(0xffffffff);
+
+            canvas.translate(150.0f, 75.0f);
+            canvas.drawRect(0.0f, 0.0f, 100.0f, 50.0f, mPaint);
+
+            canvas.translate(-50.0f, 75.0f);
+            canvas.drawRect(0.0f, 0.0f, 100.0f, 50.0f, mPaint);
+
+            canvas.translate(-75.0f, 50.0f);
+            canvas.drawRect(0.0f, 0.0f, 100.0f, 50.0f, mPaint);
+
+            canvas.translate(150.0f, 0.0f);
+            canvas.drawRect(0.0f, 0.0f, 100.0f, 50.0f, mPaint);
+
+            invalidate();
+        }
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
index 0a868fa..4a1f5a2 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
@@ -153,6 +153,12 @@
             canvas.drawText("Hello OpenGL renderer!", 100, 300, mLargePaint);
             canvas.restore();
 
+//            mStrikePaint.setUnderlineText(false);
+//            canvas.save();
+//            canvas.scale(20.0f, 20.0f);
+//            canvas.drawText("aeiouyw", 5.0f, 750 / 20.0f, mStrikePaint);
+//            canvas.restore();
+//            mStrikePaint.setUnderlineText(true);
         }
     }
 }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextFadeActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextFadeActivity.java
index c8bbc7d..d307ef8 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextFadeActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextFadeActivity.java
@@ -21,7 +21,9 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.os.Bundle;
+import android.text.TextUtils;
 import android.view.View;
+import android.widget.TextView;
 
 @SuppressWarnings({"UnusedDeclaration"})
 public class TextFadeActivity extends Activity {
@@ -30,5 +32,8 @@
         super.onCreate(savedInstanceState);
 
         setContentView(R.layout.text_fade);
+        
+        findViewById(R.id.contact_tile_name).setHorizontalFadingEdgeEnabled(true);
+        ((TextView) findViewById(R.id.contact_tile_name)).setEllipsize(TextUtils.TruncateAt.MARQUEE);
     }
 }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextPathActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextPathActivity.java
new file mode 100644
index 0000000..35a1fc9
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextPathActivity.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ScrollView;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class TextPathActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        ScrollView scroller = new ScrollView(this);
+        scroller.addView(new CustomTextView(this));
+        setContentView(scroller);
+    }
+
+    static class CustomTextView extends View {
+        private final Paint mHugePaint;
+
+        CustomTextView(Context c) {
+            super(c);
+
+            mHugePaint = new Paint();
+            mHugePaint.setAntiAlias(true);
+            mHugePaint.setColor(0xff000000);
+            mHugePaint.setTextSize(300f);
+        }
+
+        @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), 3000);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            super.onDraw(canvas);
+            canvas.drawRGB(255, 255, 255);
+
+            Path path = new Path();
+
+            canvas.translate(100.0f, 300.0f);
+            drawTextAsPath(canvas, "Hello", path);
+
+            canvas.translate(0.0f, 400.0f);
+            drawTextAsPath(canvas, "OpenGL", path);
+        }
+
+        private void drawTextAsPath(Canvas canvas, String text, Path path) {
+            int count = text.length();
+            mHugePaint.getTextPath(text, 0, count, 0, 0, path);
+            path.close();
+            canvas.drawPath(path, mHugePaint);
+        }
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
index 359447d..0ddd7fd 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
@@ -81,11 +81,14 @@
                 leftList.setAlpha(0.5f);
                 middleList.setLayerType(View.LAYER_TYPE_HARDWARE, p3);
                 middleList.setAlpha(0.5f);
+                middleList.setVerticalFadingEdgeEnabled(true);
                 rightList.setLayerType(View.LAYER_TYPE_SOFTWARE, p2);
 
                 moveRight.start();
                 moveLeft.start();
                 rotate.start();
+
+                ((View) leftList.getParent()).setAlpha(0.5f);
             }
         }, 2000);
     }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
index 95a5b0d..2664977 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
@@ -32,30 +32,40 @@
 
 @SuppressWarnings({"UnusedDeclaration"})
 public class ViewLayersActivity5 extends Activity {
+    private final Paint mPaint = new Paint();
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         
         setContentView(R.layout.view_layers_5);
 
+        mPaint.setColorFilter(new PorterDuffColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY));
+
         setupList(R.id.list1);
     }
 
-    public void setLayerDisabled(View v) {
-        ((ViewGroup) findViewById(R.id.list1).getParent()).setChildrenLayersEnabled(false);
+    public void enableLayer(View v) {
+        findViewById(R.id.list1).setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
+    }
+
+    public void disableLayer(View v) {
+        findViewById(R.id.list1).setLayerType(View.LAYER_TYPE_NONE, null);
     }
     
-    public void setLayerEnabled(View v) {
-        ((ViewGroup) findViewById(R.id.list1).getParent()).setChildrenLayersEnabled(true);
+    public void growLayer(View v) {
+        findViewById(R.id.list1).getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
+        findViewById(R.id.list1).requestLayout();
+    }
+
+    public void shrinkLayer(View v) {
+        findViewById(R.id.list1).getLayoutParams().height = 300;
+        findViewById(R.id.list1).requestLayout();
     }
     
     private void setupList(int listId) {
-        final Paint p = new Paint();
-        p.setColorFilter(new PorterDuffColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY));
-
         final ListView list = (ListView) findViewById(listId);
         list.setAdapter(new SimpleListAdapter(this));
-        list.setLayerType(View.LAYER_TYPE_HARDWARE, p);
     }
 
     private static class SimpleListAdapter extends ArrayAdapter<String> {
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity6.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity6.java
deleted file mode 100644
index 2edfec70..0000000
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity6.java
+++ /dev/null
@@ -1,131 +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.
- */
-
-package com.android.test.hwui;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-import android.os.Bundle;
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-import android.widget.TextView;
-
-@SuppressWarnings({"UnusedDeclaration"})
-public class ViewLayersActivity6 extends Activity {
-    private final Paint mPaint = new Paint();
-    
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        
-        setContentView(R.layout.view_layers_6);
-
-        mPaint.setColorFilter(new PorterDuffColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY));
-
-        setupList(R.id.list1);
-    }
-
-    public void enableLayer(View v) {
-        findViewById(R.id.list1).setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
-    }
-    
-    public void disableLayer(View v) {
-        findViewById(R.id.list1).setLayerType(View.LAYER_TYPE_NONE, null);
-    }
-    
-    public void growLayer(View v) {
-        findViewById(R.id.list1).getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
-        findViewById(R.id.list1).requestLayout();
-    }
-    
-    public void shrinkLayer(View v) {
-        findViewById(R.id.list1).getLayoutParams().height = 300;        
-        findViewById(R.id.list1).requestLayout();
-    }
-    
-    private void setupList(int listId) {
-        final ListView list = (ListView) findViewById(listId);
-        list.setAdapter(new SimpleListAdapter(this));
-    }
-
-    private static class SimpleListAdapter extends ArrayAdapter<String> {
-        public SimpleListAdapter(Context context) {
-            super(context, android.R.layout.simple_list_item_1, DATA_LIST);
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            TextView v = (TextView) super.getView(position, convertView, parent);
-            final Resources r = getContext().getResources();
-            final DisplayMetrics metrics = r.getDisplayMetrics();
-            v.setCompoundDrawablePadding((int) (6 * metrics.density + 0.5f));
-            v.setCompoundDrawablesWithIntrinsicBounds(r.getDrawable(R.drawable.icon),
-                    null, null, null);
-            return v;
-        }
-    }
-
-    private static final String[] DATA_LIST = {
-            "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
-            "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
-            "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
-            "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
-            "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
-            "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil",
-            "British Indian Ocean Territory", "British Virgin Islands", "Brunei", "Bulgaria",
-            "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
-            "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
-            "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
-            "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
-            "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
-            "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
-            "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
-            "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
-            "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
-            "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
-            "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
-            "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
-            "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
-            "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
-            "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
-            "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
-            "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
-            "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
-            "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
-            "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
-            "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
-            "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
-            "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
-            "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
-            "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
-            "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
-            "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
-            "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
-            "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
-            "Ukraine", "United Arab Emirates", "United Kingdom",
-            "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
-            "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
-            "Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
-    };
-}
diff --git a/tests/MemoryUsage/Android.mk b/tests/MemoryUsage/Android.mk
new file mode 100644
index 0000000..e7bfb4f
--- /dev/null
+++ b/tests/MemoryUsage/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := MemoryUsage
+
+LOCAL_SDK_VERSION := 7
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/tests/MemoryUsage/AndroidManifest.xml b/tests/MemoryUsage/AndroidManifest.xml
new file mode 100644
index 0000000..3932e5b
--- /dev/null
+++ b/tests/MemoryUsage/AndroidManifest.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.tests.memoryusage">
+    <instrumentation android:label="Memory usage instrumentation"
+                     android:name="com.android.tests.memoryusage.MemoryUsageInstrumentation"
+                     android:targetPackage="com.android.tests.memoryusage" />
+
+    <application android:label="Memory Usage Test">
+        <uses-library android:name="android.test.runner" />
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageInstrumentation.java b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageInstrumentation.java
new file mode 100644
index 0000000..ed6d7e6
--- /dev/null
+++ b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageInstrumentation.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tests.memoryusage;
+
+import android.os.Bundle;
+import android.test.InstrumentationTestRunner;
+
+/**
+ * InstrumentationTestRunner for use with the {@link MemoryUsageTest}.
+ */
+public class MemoryUsageInstrumentation extends InstrumentationTestRunner {
+
+    private Bundle arguments;
+
+    @Override
+    public void onCreate(Bundle arguments) {
+        this.arguments = arguments;
+        super.onCreate(arguments);
+    }
+
+    public Bundle getBundle() {
+        return arguments;
+    }
+
+}
diff --git a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
new file mode 100644
index 0000000..5e27ba7
--- /dev/null
+++ b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tests.memoryusage;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.ProcessErrorStateInfo;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.os.Debug.MemoryInfo;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This test is intended to measure the amount of memory applications use when
+ * they start. Names of the applications are passed in command line, and the
+ * test starts each application, waits until its memory usage is stabilized and
+ * reports the total PSS in kilobytes of each processes.
+ * The instrumentation expects the following key to be passed on the command line:
+ * apps - A list of applications to start and their corresponding result keys
+ * in the following format:
+ * -e apps <app name>^<result key>|<app name>^<result key>
+ */
+public class MemoryUsageTest extends InstrumentationTestCase {
+
+    private static final int SLEEP_TIME = 1000;
+    private static final int THRESHOLD = 1024;
+    private static final int MAX_ITERATIONS = 10;
+    private static final int MIN_ITERATIONS = 4;
+
+    private static final String TAG = "MemoryUsageInstrumentation";
+    private static final String KEY_APPS = "apps";
+
+    private Map<String, Intent> mNameToIntent;
+    private Map<String, String> mNameToProcess;
+    private Map<String, String> mNameToResultKey;
+
+    public void testMemory() {
+        MemoryUsageInstrumentation instrumentation =
+                    (MemoryUsageInstrumentation) getInstrumentation();
+        Bundle args = instrumentation.getBundle();
+
+        createMappings();
+        parseArgs(args);
+
+        Bundle results = new Bundle();
+        for (String app : mNameToResultKey.keySet()) {
+            String processName;
+            try {
+                processName = startApp(app);
+                measureMemory(app, processName, results);
+                closeApp();
+            } catch (NameNotFoundException e) {
+                Log.i(TAG, "Application " + app + " not found");
+            }
+
+        }
+        instrumentation.sendStatus(0, results);
+    }
+
+    private void parseArgs(Bundle args) {
+        mNameToResultKey = new HashMap<String, String>();
+        String appList = args.getString(KEY_APPS);
+
+        if (appList == null)
+            return;
+
+        String appNames[] = appList.split("\\|");
+        for (String pair : appNames) {
+            String[] parts = pair.split("\\^");
+            if (parts.length != 2) {
+                Log.e(TAG, "The apps key is incorectly formatted");
+                fail();
+            }
+
+            mNameToResultKey.put(parts[0], parts[1]);
+        }
+    }
+
+    private void createMappings() {
+        mNameToIntent = new HashMap<String, Intent>();
+        mNameToProcess = new HashMap<String, String>();
+
+        PackageManager pm = getInstrumentation().getContext()
+                .getPackageManager();
+        Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
+        intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
+        List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0);
+        if (ris == null || ris.isEmpty()) {
+            Log.i(TAG, "Could not find any apps");
+        } else {
+            for (ResolveInfo ri : ris) {
+                Log.i(TAG, "Name: " + ri.loadLabel(pm).toString()
+                        + " package: " + ri.activityInfo.packageName
+                        + " name: " + ri.activityInfo.name);
+                Intent startIntent = new Intent(intentToResolve);
+                startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                startIntent.setClassName(ri.activityInfo.packageName,
+                        ri.activityInfo.name);
+                mNameToIntent.put(ri.loadLabel(pm).toString(), startIntent);
+                mNameToProcess.put(ri.loadLabel(pm).toString(),
+                        ri.activityInfo.processName);
+            }
+        }
+    }
+
+    private String startApp(String appName) throws NameNotFoundException {
+        Log.i(TAG, "Starting " + appName);
+
+        if (!mNameToProcess.containsKey(appName))
+            throw new NameNotFoundException("Could not find: " + appName);
+
+        String process = mNameToProcess.get(appName);
+        Intent startIntent = mNameToIntent.get(appName);
+        getInstrumentation().getContext().startActivity(startIntent);
+        return process;
+    }
+
+    private void closeApp() {
+        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+        homeIntent.addCategory(Intent.CATEGORY_HOME);
+        homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+        getInstrumentation().getContext().startActivity(homeIntent);
+        sleep(3000);
+    }
+
+    private void measureMemory(String appName, String processName,
+            Bundle results) {
+        List<Integer> pssData = new ArrayList<Integer>();
+        int pss = 0;
+        int iteration = 0;
+        while (iteration < MAX_ITERATIONS) {
+            sleep(SLEEP_TIME);
+            pss = getPss(processName);
+            Log.i(TAG, appName + "=" + pss);
+            if (pss < 0) {
+                reportError(appName, processName, results);
+                return;
+            }
+            pssData.add(pss);
+            if (iteration >= MIN_ITERATIONS && stabilized(pssData)) {
+                results.putInt(mNameToResultKey.get(appName), pss);
+                return;
+            }
+            iteration++;
+        }
+
+        Log.w(TAG, appName + " memory usage did not stabilize");
+        results.putInt(mNameToResultKey.get(appName), average(pssData));
+    }
+
+    private int average(List<Integer> pssData) {
+        int sum = 0;
+        for (int sample : pssData) {
+            sum += sample;
+        }
+
+        return sum / pssData.size();
+    }
+
+    private boolean stabilized(List<Integer> pssData) {
+        if (pssData.size() < 3)
+            return false;
+        int diff1 = Math.abs(pssData.get(pssData.size() - 1) - pssData.get(pssData.size() - 2));
+        int diff2 = Math.abs(pssData.get(pssData.size() - 2) - pssData.get(pssData.size() - 3));
+
+        Log.i(TAG, "diff1=" + diff1 + " diff2=" + diff2);
+
+        return (diff1 + diff2) < THRESHOLD;
+    }
+
+    private void sleep(int time) {
+        try {
+            Thread.sleep(time);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+    }
+
+    private void reportError(String appName, String processName, Bundle results) {
+        ActivityManager am = (ActivityManager) getInstrumentation()
+                .getContext().getSystemService(Context.ACTIVITY_SERVICE);
+        List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState();
+        if (crashes != null) {
+            for (ProcessErrorStateInfo crash : crashes) {
+                if (!crash.processName.equals(processName))
+                    continue;
+
+                Log.w(TAG, appName + " crashed: " + crash.shortMsg);
+                results.putString(mNameToResultKey.get(appName), crash.shortMsg);
+                return;
+            }
+        }
+
+        results.putString(mNameToResultKey.get(appName),
+                "Crashed for unknown reason");
+        Log.w(TAG, appName
+                + " not found in process list, most likely it is crashed");
+    }
+
+    private int getPss(String processName) {
+        ActivityManager am = (ActivityManager) getInstrumentation()
+                .getContext().getSystemService(Context.ACTIVITY_SERVICE);
+        List<RunningAppProcessInfo> apps = am.getRunningAppProcesses();
+
+        for (RunningAppProcessInfo proc : apps) {
+            if (!proc.processName.equals(processName)) {
+                continue;
+            }
+
+            int[] pids = {
+                proc.pid };
+
+            MemoryInfo meminfo = am.getProcessMemoryInfo(pids)[0];
+            return meminfo.getTotalPss();
+
+        }
+        return -1;
+    }
+}
diff --git a/tests/RenderScriptTests/Balls/Android.mk b/tests/RenderScriptTests/Balls/Android.mk
index b109584..77281ce 100644
--- a/tests/RenderScriptTests/Balls/Android.mk
+++ b/tests/RenderScriptTests/Balls/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/ComputeBenchmark/Android.mk b/tests/RenderScriptTests/ComputeBenchmark/Android.mk
new file mode 100644
index 0000000..8d47e89
--- /dev/null
+++ b/tests/RenderScriptTests/ComputeBenchmark/Android.mk
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+                   $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := RsComputeBenchmark
+
+include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/ComputeBenchmark/AndroidManifest.xml b/tests/RenderScriptTests/ComputeBenchmark/AndroidManifest.xml
new file mode 100644
index 0000000..c8fcc17
--- /dev/null
+++ b/tests/RenderScriptTests/ComputeBenchmark/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.rs.computebench">
+
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-sdk android:minSdkVersion="17" />
+    <application android:label="_RS_Compute_Bench">
+        <activity android:name="ComputeBench">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/RenderScriptTests/ComputeBenchmark/res/layout/main.xml b/tests/RenderScriptTests/ComputeBenchmark/res/layout/main.xml
new file mode 100644
index 0000000..9e9dab8
--- /dev/null
+++ b/tests/RenderScriptTests/ComputeBenchmark/res/layout/main.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+    <ImageView
+        android:id="@+id/displayin"
+        android:layout_width="320dip"
+        android:layout_height="266dip" />
+
+    <ImageView
+        android:id="@+id/displayout"
+        android:layout_width="320dip"
+        android:layout_height="266dip" />
+
+</LinearLayout>
diff --git a/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/Benchmark.java b/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/Benchmark.java
new file mode 100644
index 0000000..ec80719
--- /dev/null
+++ b/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/Benchmark.java
@@ -0,0 +1,39 @@
+/*
+ * 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.example.android.rs.computebench;
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class Benchmark implements Runnable {
+    private final RenderScript mRS;
+    private ScriptC_compute_benchmark mScript;
+
+    public Benchmark(RenderScript rs, Resources res) {
+        mRS = rs;
+        mScript = new ScriptC_compute_benchmark(mRS, res, R.raw.compute_benchmark);
+    }
+
+    public void run() {
+        long t = java.lang.System.currentTimeMillis();
+        mScript.invoke_bench();
+        mRS.finish();
+        t = java.lang.System.currentTimeMillis() - t;
+        android.util.Log.v("ComputeBench", "Total benchmark took " + t + " ms");
+    }
+
+}
diff --git a/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/ComputeBench.java b/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/ComputeBench.java
new file mode 100644
index 0000000..2d3e843
--- /dev/null
+++ b/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/ComputeBench.java
@@ -0,0 +1,37 @@
+/*
+ * 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.example.android.rs.computebench;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.renderscript.RenderScript;
+
+public class ComputeBench extends Activity {
+    private RenderScript mRS;
+    private Benchmark mBenchmark;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mRS = RenderScript.create(this);
+
+        mBenchmark = new Benchmark(mRS, getResources());
+        mBenchmark.run();
+    }
+}
diff --git a/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs b/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs
new file mode 100644
index 0000000..2ee56ec
--- /dev/null
+++ b/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs
@@ -0,0 +1,407 @@
+// 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.
+
+#pragma version(1)
+#pragma rs java_package_name(com.example.android.rs.computebench)
+
+// Test configuration (accessible from Java)
+uint priming_runs   = 1000000;
+uint timing_runs    = 5000000;
+
+// Reused variables
+
+static volatile int64_t bench_time;
+static float inv_timing_runs;
+
+#define DECL_VAR_SET(prefix)                \
+static volatile float prefix##_f_1 = 1;     \
+static volatile float2 prefix##_f_2 = 1;    \
+static volatile float3 prefix##_f_3 = 1;    \
+static volatile float4 prefix##_f_4 = 1;    \
+static volatile char prefix##_c_1 = 1;      \
+static volatile char2 prefix##_c_2 = 1;     \
+static volatile char3 prefix##_c_3 = 1;     \
+static volatile char4 prefix##_c_4 = 1;     \
+static volatile uchar prefix##_uc_1 = 1;    \
+static volatile uchar2 prefix##_uc_2 = 1;   \
+static volatile uchar3 prefix##_uc_3 = 1;   \
+static volatile uchar4 prefix##_uc_4 = 1;   \
+static volatile short prefix##_s_1 = 1;     \
+static volatile short2 prefix##_s_2 = 1;    \
+static volatile short3 prefix##_s_3 = 1;    \
+static volatile short4 prefix##_s_4 = 1;    \
+static volatile ushort prefix##_us_1 = 1;   \
+static volatile ushort2 prefix##_us_2 = 1;  \
+static volatile ushort3 prefix##_us_3 = 1;  \
+static volatile ushort4 prefix##_us_4 = 1;  \
+static volatile int prefix##_i_1 = 1;       \
+static volatile int2 prefix##_i_2 = 1;      \
+static volatile int3 prefix##_i_3 = 1;      \
+static volatile int4 prefix##_i_4 = 1;      \
+static volatile uint prefix##_ui_1 = 1;     \
+static volatile uint2 prefix##_ui_2 = 1;    \
+static volatile uint3 prefix##_ui_3 = 1;    \
+static volatile uint4 prefix##_ui_4 = 1;    \
+static volatile long prefix##_l_1 = 1;      \
+static volatile long2 prefix##_l_2 = 1;     \
+static volatile long3 prefix##_l_3 = 1;     \
+static volatile long4 prefix##_l_4 = 1;     \
+static volatile ulong prefix##_ul_1 = 1;    \
+static volatile ulong2 prefix##_ul_2 = 1;   \
+static volatile ulong3 prefix##_ul_3 = 1;   \
+static volatile ulong4 prefix##_ul_4 = 1;   \
+
+DECL_VAR_SET(res)
+DECL_VAR_SET(src1)
+DECL_VAR_SET(src2)
+DECL_VAR_SET(src3)
+
+
+// Testing macros
+
+#define RUN_BENCH(line, op)                         \
+    for (int i = priming_runs - 1; i >= 0; --i) {   \
+        line;                                       \
+    }                                               \
+    bench_time = rsUptimeMillis();                  \
+    for (int i = timing_runs - 1; i >= 0; --i) {    \
+        line;                                       \
+    }                                               \
+    bench_time = rsUptimeMillis() - bench_time;     \
+    rsDebug("    " op " took ns", (float)bench_time * inv_timing_runs);
+
+#define BENCH_BASIC_OP_TYPE(op, type)                                                               \
+    RUN_BENCH(res_##type##_1 = src1_##type##_1 op src2_##type##_1, #type "1 " #op " " #type "1")    \
+    RUN_BENCH(res_##type##_2 = src1_##type##_2 op src2_##type##_2, #type "2 " #op " " #type "2")    \
+    RUN_BENCH(res_##type##_3 = src1_##type##_3 op src2_##type##_3, #type "3 " #op " " #type "3")    \
+    RUN_BENCH(res_##type##_4 = src1_##type##_4 op src2_##type##_4, #type "4 " #op " " #type "4")    \
+
+#define BENCH_BASIC_INT_OP(op)                                  \
+    rsDebug("Testing basic operation " #op, 0);                 \
+    BENCH_BASIC_OP_TYPE(op, c)                                  \
+    BENCH_BASIC_OP_TYPE(op, uc)                                 \
+    BENCH_BASIC_OP_TYPE(op, s)                                  \
+    BENCH_BASIC_OP_TYPE(op, us)                                 \
+    BENCH_BASIC_OP_TYPE(op, i)                                  \
+    BENCH_BASIC_OP_TYPE(op, ui)                                 \
+    RUN_BENCH(res_l_1 = src1_l_1 op src2_l_1, "l1 " #op " l1")  \
+    RUN_BENCH(res_ul_1 = src1_ul_1 op src2_ul_1, "ul1 " #op " ul1")
+
+#define BENCH_BASIC_OP(op)      \
+    BENCH_BASIC_INT_OP(op)      \
+    BENCH_BASIC_OP_TYPE(op, f)
+
+#define BENCH_CVT(to, from, type)                                                                           \
+    rsDebug("Testing convert from " #from " to " #to, 0);                                                   \
+    RUN_BENCH(res_##to##_1 = (type)src1_##from##_1, "(" #to ")" #from)                                      \
+    RUN_BENCH(res_##to##_2 = convert_##type##2(src1_##from##_2), #to "2 convert_" #type "2(" #from "2)")    \
+    RUN_BENCH(res_##to##_3 = convert_##type##3(src1_##from##_3), #to "3 convert_" #type "3(" #from "3)")    \
+    RUN_BENCH(res_##to##_4 = convert_##type##4(src1_##from##_4), #to "4 convert_" #type "4(" #from "4)")
+
+#define BENCH_CVT_MATRIX(to, type)  \
+    BENCH_CVT(to, c, type);         \
+    BENCH_CVT(to, uc, type);        \
+    BENCH_CVT(to, s, type);         \
+    BENCH_CVT(to, us, type);        \
+    BENCH_CVT(to, i, type);         \
+    BENCH_CVT(to, ui, type);        \
+    BENCH_CVT(to, f, type);         \
+
+#define BENCH_XN_FUNC_YN(typeout, fnc, typein)                                                  \
+    RUN_BENCH(res_##typeout##_1 = fnc(src1_##typein##_1);, #typeout "1 " #fnc "(" #typein "1)") \
+    RUN_BENCH(res_##typeout##_2 = fnc(src1_##typein##_2);, #typeout "2 " #fnc "(" #typein "2)") \
+    RUN_BENCH(res_##typeout##_3 = fnc(src1_##typein##_3);, #typeout "3 " #fnc "(" #typein "3)") \
+    RUN_BENCH(res_##typeout##_4 = fnc(src1_##typein##_4);, #typeout "4 " #fnc "(" #typein "4)")
+
+#define BENCH_XN_FUNC_XN_XN(type, fnc)                                                                              \
+    RUN_BENCH(res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1), #type "1 " #fnc "(" #type "1, " #type "1)")   \
+    RUN_BENCH(res_##type##_2 = fnc(src1_##type##_2, src2_##type##_2), #type "2 " #fnc "(" #type "2, " #type "2)")   \
+    RUN_BENCH(res_##type##_3 = fnc(src1_##type##_3, src2_##type##_3), #type "3 " #fnc "(" #type "3, " #type "3)")   \
+    RUN_BENCH(res_##type##_4 = fnc(src1_##type##_4, src2_##type##_4), #type "4 " #fnc "(" #type "4, " #type "4)")   \
+
+#define BENCH_X_FUNC_X_X_X(type, fnc)   \
+    RUN_BENCH(res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1, src3_##type##_1), #type "1 " #fnc "(" #type "1, " #type "1, " #type "1)")
+
+#define BENCH_IN_FUNC_IN(fnc)       \
+    rsDebug("Testing " #fnc, 0);    \
+    BENCH_XN_FUNC_YN(uc, fnc, uc)   \
+    BENCH_XN_FUNC_YN(c, fnc, c)     \
+    BENCH_XN_FUNC_YN(us, fnc, us)   \
+    BENCH_XN_FUNC_YN(s, fnc, s)     \
+    BENCH_XN_FUNC_YN(ui, fnc, ui)   \
+    BENCH_XN_FUNC_YN(i, fnc, i)
+
+#define BENCH_UIN_FUNC_IN(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    BENCH_XN_FUNC_YN(uc, fnc, c)    \
+    BENCH_XN_FUNC_YN(us, fnc, s)    \
+    BENCH_XN_FUNC_YN(ui, fnc, i)    \
+
+#define BENCH_IN_FUNC_IN_IN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    BENCH_XN_FUNC_XN_XN(uc, fnc)    \
+    BENCH_XN_FUNC_XN_XN(c, fnc)     \
+    BENCH_XN_FUNC_XN_XN(us, fnc)    \
+    BENCH_XN_FUNC_XN_XN(s, fnc)     \
+    BENCH_XN_FUNC_XN_XN(ui, fnc)    \
+    BENCH_XN_FUNC_XN_XN(i, fnc)
+
+#define BENCH_I_FUNC_I_I_I(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    BENCH_X_FUNC_X_X_X(uc, fnc)     \
+    BENCH_X_FUNC_X_X_X(c, fnc)      \
+    BENCH_X_FUNC_X_X_X(us, fnc)     \
+    BENCH_X_FUNC_X_X_X(s, fnc)      \
+    BENCH_X_FUNC_X_X_X(ui, fnc)     \
+    BENCH_X_FUNC_X_X_X(i, fnc)
+
+#define BENCH_FN_FUNC_FN(fnc)                               \
+    rsDebug("Testing " #fnc, 0);                            \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1), "f1 " #fnc "(f1)")   \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2), "f2 " #fnc "(f2)")   \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3), "f3 " #fnc "(f3)")   \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4), "f4 " #fnc "(f4)")
+
+#define BENCH_FN_FUNC_FN_PFN(fnc)                                                   \
+    rsDebug("Testing " #fnc, 0);                                                    \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, (float*) &src2_f_1), "f1 " #fnc "(f1, f1*)")  \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, (float2*) &src2_f_2), "f2 " #fnc "(f2, f2*)") \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, (float3*) &src2_f_3), "f3 " #fnc "(f3, f3*)") \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, (float4*) &src2_f_4), "f4 " #fnc "(f4, f4*)")
+
+#define BENCH_FN_FUNC_FN_FN(fnc)                                        \
+    rsDebug("Testing " #fnc, 0);                                        \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1), "f1 " #fnc "(f1, f1)") \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, src2_f_2), "f2 " #fnc "(f2, f2)") \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_3), "f3 " #fnc "(f3, f3)") \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_4), "f4 " #fnc "(f4, f4)")
+
+#define BENCH_F34_FUNC_F34_F34(fnc)                                     \
+    rsDebug("Testing " #fnc, 0);                                        \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_3), "f3 " #fnc "(f3, f3)") \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_4), "f4 " #fnc "(f4, f4)")
+
+#define BENCH_FN_FUNC_FN_F(fnc)                                         \
+    rsDebug("Testing " #fnc, 0);                                        \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1), "f1 " #fnc "(f1, f1)") \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, src2_f_1), "f2 " #fnc "(f2, f1)") \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_1), "f3 " #fnc "(f3, f1)") \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_1), "f4 " #fnc "(f4, f1)")
+
+#define BENCH_F_FUNC_FN(fnc)                                \
+    rsDebug("Testing " #fnc, 0);                            \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1), "f1 " #fnc "(f1)")   \
+    RUN_BENCH(res_f_1 = fnc(src1_f_2), "f1 " #fnc "(f2)")   \
+    RUN_BENCH(res_f_1 = fnc(src1_f_3), "f1 " #fnc "(f3)")   \
+    RUN_BENCH(res_f_1 = fnc(src1_f_4), "f1 " #fnc "(f4)")
+
+#define BENCH_F_FUNC_FN_FN(fnc)                                         \
+    rsDebug("Testing " #fnc, 0);                                        \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1), "f1 " #fnc "(f1, f1)") \
+    RUN_BENCH(res_f_1 = fnc(src1_f_2, src2_f_2), "f1 " #fnc "(f2, f2)") \
+    RUN_BENCH(res_f_1 = fnc(src1_f_3, src2_f_3), "f1 " #fnc "(f3, f3)") \
+    RUN_BENCH(res_f_1 = fnc(src1_f_4, src2_f_4), "f1 " #fnc "(f4, f4)")
+
+#define BENCH_FN_FUNC_FN_IN(fnc)                                        \
+    rsDebug("Testing " #fnc, 0);                                        \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, src1_i_1), "f1 " #fnc "(f1, i1)") \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, src1_i_2), "f2 " #fnc "(f2, i2)") \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, src1_i_3), "f3 " #fnc "(f3, i3)") \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, src1_i_4), "f4 " #fnc "(f4, i4)")
+
+#define BENCH_FN_FUNC_FN_I(fnc)                                         \
+    rsDebug("Testing " #fnc, 0);                                        \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, src1_i_1), "f1 " #fnc "(f1, i1)") \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, src1_i_1), "f2 " #fnc "(f2, i1)") \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, src1_i_1), "f3 " #fnc "(f3, i1)") \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, src1_i_1), "f4 " #fnc "(f4, i1)")
+
+#define BENCH_FN_FUNC_FN_FN_FN(fnc)                                                     \
+    rsDebug("Testing " #fnc, 0);                                                        \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1, src3_f_1), "f1 " #fnc "(f1, f1, f1)")   \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, src2_f_2, src3_f_2), "f2 " #fnc "(f2, f2, f2)")   \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_3, src3_f_3), "f3 " #fnc "(f3, f3, f3)")   \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_4, src3_f_4), "f4 " #fnc "(f4, f4, f4)")
+
+#define BENCH_FN_FUNC_FN_FN_F(fnc)                                                      \
+    rsDebug("Testing " #fnc, 0);                                                        \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1, src3_f_1), "f1 " #fnc "(f1, f1, f1)")   \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, src2_f_2, src3_f_1), "f2 " #fnc "(f2, f2, f1)")   \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_3, src3_f_1), "f3 " #fnc "(f3, f3, f1)")   \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_4, src3_f_1), "f4 " #fnc "(f4, f4, f1)")
+
+#define BENCH_FN_FUNC_FN_PIN(fnc)                                                   \
+    rsDebug("Testing " #fnc, 0);                                                    \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, (int*) &src1_i_1), "f1 " #fnc "(f1, i1*)")    \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, (int2*) &src1_i_2), "f2 " #fnc "(f2, i2*)")   \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, (int3*) &src1_i_3), "f3 " #fnc "(f3, i3*)")   \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, (int4*) &src1_i_4), "f4 " #fnc "(f4, i4*)")
+
+#define BENCH_FN_FUNC_FN_FN_PIN(fnc)                                                            \
+    rsDebug("Testing " #fnc, 0);                                                                \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1, (int*) &src1_i_1), "f1 " #fnc "(f1, f1, i1*)")  \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, src2_f_2, (int2*) &src1_i_2), "f2 " #fnc "(f2, f2, i2*)") \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_3, (int3*) &src1_i_3), "f3 " #fnc "(f3, f3, i3*)") \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_4, (int4*) &src1_i_4), "f4 " #fnc "(f4, f4, i4*)")
+
+#define BENCH_IN_FUNC_FN(fnc)                               \
+    rsDebug("Testing " #fnc, 0);                            \
+    RUN_BENCH(res_i_1 = fnc(src1_f_1), "i1 " #fnc "(f1)")   \
+    RUN_BENCH(res_i_2 = fnc(src1_f_2), "i2 " #fnc "(f2)")   \
+    RUN_BENCH(res_i_3 = fnc(src1_f_3), "i3 " #fnc "(f3)")   \
+    RUN_BENCH(res_i_4 = fnc(src1_f_4), "i4 " #fnc "(f4)")
+
+
+// Testing functions
+
+static void bench_basic_operators() {
+    int i = 0;
+    BENCH_BASIC_OP(+);
+    BENCH_BASIC_OP(-);
+    BENCH_BASIC_OP(*);
+    BENCH_BASIC_OP(/);
+    BENCH_BASIC_INT_OP(%);
+    BENCH_BASIC_INT_OP(<<);
+    BENCH_BASIC_INT_OP(>>);
+}
+
+static void bench_convert() {
+    BENCH_CVT_MATRIX(c, char);
+    BENCH_CVT_MATRIX(uc, uchar);
+    BENCH_CVT_MATRIX(s, short);
+    BENCH_CVT_MATRIX(us, ushort);
+    BENCH_CVT_MATRIX(i, int);
+    BENCH_CVT_MATRIX(ui, uint);
+    BENCH_CVT_MATRIX(f, float);
+}
+
+static void bench_int_math() {
+    BENCH_UIN_FUNC_IN(abs);
+    BENCH_IN_FUNC_IN(clz);
+    BENCH_IN_FUNC_IN_IN(min);
+    BENCH_IN_FUNC_IN_IN(max);
+    BENCH_I_FUNC_I_I_I(rsClamp);
+}
+
+static void bench_fp_math() {
+    BENCH_FN_FUNC_FN(acos);
+    BENCH_FN_FUNC_FN(acosh);
+    BENCH_FN_FUNC_FN(acospi);
+    BENCH_FN_FUNC_FN(asin);
+    BENCH_FN_FUNC_FN(asinh);
+    BENCH_FN_FUNC_FN(asinpi);
+    BENCH_FN_FUNC_FN(atan);
+    BENCH_FN_FUNC_FN_FN(atan2);
+    BENCH_FN_FUNC_FN(atanh);
+    BENCH_FN_FUNC_FN(atanpi);
+    BENCH_FN_FUNC_FN_FN(atan2pi);
+    BENCH_FN_FUNC_FN(cbrt);
+    BENCH_FN_FUNC_FN(ceil);
+    BENCH_FN_FUNC_FN_FN_FN(clamp);
+    BENCH_FN_FUNC_FN_FN_F(clamp);
+    BENCH_FN_FUNC_FN_FN(copysign);
+    BENCH_FN_FUNC_FN(cos);
+    BENCH_FN_FUNC_FN(cosh);
+    BENCH_FN_FUNC_FN(cospi);
+    BENCH_F34_FUNC_F34_F34(cross);
+    BENCH_FN_FUNC_FN(degrees);
+    BENCH_F_FUNC_FN_FN(distance);
+    BENCH_F_FUNC_FN_FN(dot);
+    BENCH_FN_FUNC_FN(erfc);
+    BENCH_FN_FUNC_FN(erf);
+    BENCH_FN_FUNC_FN(exp);
+    BENCH_FN_FUNC_FN(exp2);
+    BENCH_FN_FUNC_FN(exp10);
+    BENCH_FN_FUNC_FN(expm1);
+    BENCH_FN_FUNC_FN(fabs);
+    BENCH_FN_FUNC_FN_FN(fdim);
+    BENCH_FN_FUNC_FN(floor);
+    BENCH_FN_FUNC_FN_FN_FN(fma);
+    BENCH_FN_FUNC_FN_FN(fmax);
+    BENCH_FN_FUNC_FN_F(fmax);
+    BENCH_FN_FUNC_FN_FN(fmin);
+    BENCH_FN_FUNC_FN_F(fmin);
+    BENCH_FN_FUNC_FN_FN(fmod);
+    BENCH_FN_FUNC_FN_PFN(fract);
+    BENCH_FN_FUNC_FN_PIN(frexp);
+    BENCH_FN_FUNC_FN_FN(hypot);
+    BENCH_IN_FUNC_FN(ilogb);
+    BENCH_FN_FUNC_FN_IN(ldexp);
+    BENCH_FN_FUNC_FN_I(ldexp);
+    BENCH_F_FUNC_FN(length);
+    BENCH_FN_FUNC_FN(lgamma);
+    BENCH_FN_FUNC_FN_PIN(lgamma);
+    BENCH_FN_FUNC_FN(log);
+    BENCH_FN_FUNC_FN(log2);
+    BENCH_FN_FUNC_FN(log10);
+    BENCH_FN_FUNC_FN(log1p);
+    BENCH_FN_FUNC_FN(logb);
+    BENCH_FN_FUNC_FN_FN_FN(mad);
+    BENCH_FN_FUNC_FN_FN(max);
+    BENCH_FN_FUNC_FN_F(max);
+    BENCH_FN_FUNC_FN_FN(min);
+    BENCH_FN_FUNC_FN_F(min);
+    BENCH_FN_FUNC_FN_FN_FN(mix);
+    BENCH_FN_FUNC_FN_FN_F(mix);
+    BENCH_FN_FUNC_FN_PFN(modf);
+    BENCH_FN_FUNC_FN_FN(nextafter);
+    BENCH_FN_FUNC_FN(normalize);
+    BENCH_FN_FUNC_FN_FN(pow);
+    BENCH_FN_FUNC_FN_IN(pown);
+    BENCH_FN_FUNC_FN_FN(powr);
+    BENCH_FN_FUNC_FN(radians);
+    BENCH_FN_FUNC_FN_FN(remainder);
+    BENCH_FN_FUNC_FN_FN_PIN(remquo);
+    BENCH_FN_FUNC_FN(rint);
+    BENCH_FN_FUNC_FN_IN(rootn);
+    BENCH_FN_FUNC_FN(round);
+    BENCH_FN_FUNC_FN(rsqrt);
+    BENCH_FN_FUNC_FN(sign);
+    BENCH_FN_FUNC_FN(sin);
+    BENCH_FN_FUNC_FN_PFN(sincos);
+    BENCH_FN_FUNC_FN(sinh);
+    BENCH_FN_FUNC_FN(sinpi);
+    BENCH_FN_FUNC_FN(sqrt);
+    BENCH_FN_FUNC_FN_FN(step);
+    BENCH_FN_FUNC_FN_F(step);
+    BENCH_FN_FUNC_FN(tan);
+    BENCH_FN_FUNC_FN(tanh);
+    BENCH_FN_FUNC_FN(tanpi);
+    BENCH_FN_FUNC_FN(tgamma);
+    BENCH_FN_FUNC_FN(trunc);
+}
+
+static void bench_approx_math() {
+    BENCH_FN_FUNC_FN(half_recip);
+    BENCH_FN_FUNC_FN(half_sqrt);
+    BENCH_FN_FUNC_FN(half_rsqrt);
+    BENCH_FN_FUNC_FN(fast_length);
+    BENCH_FN_FUNC_FN_FN(fast_distance);
+    BENCH_FN_FUNC_FN(fast_normalize);
+}
+
+void bench() {
+    rsDebug("RS Compute Benchmark", 0);
+    rsDebug("Current configuration:", 0);
+    rsDebug("Priming runs", priming_runs);
+    rsDebug("Timing runs", timing_runs);
+    rsDebug("Beginning test", 0);
+    inv_timing_runs = 1000000.f / (float)timing_runs;
+    bench_basic_operators();
+    bench_convert();
+    bench_int_math();
+    bench_fp_math();
+    bench_approx_math();
+}
+
diff --git a/tests/RenderScriptTests/ComputePerf/Android.mk b/tests/RenderScriptTests/ComputePerf/Android.mk
index 1d67d29..6ed5884 100644
--- a/tests/RenderScriptTests/ComputePerf/Android.mk
+++ b/tests/RenderScriptTests/ComputePerf/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
                    $(call all-renderscript-files-under, src)
diff --git a/tests/RenderScriptTests/FBOTest/Android.mk b/tests/RenderScriptTests/FBOTest/Android.mk
index 1df7b26..434d5928 100644
--- a/tests/RenderScriptTests/FBOTest/Android.mk
+++ b/tests/RenderScriptTests/FBOTest/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/Fountain/Android.mk b/tests/RenderScriptTests/Fountain/Android.mk
index 2049ecf..4a6560b 100644
--- a/tests/RenderScriptTests/Fountain/Android.mk
+++ b/tests/RenderScriptTests/Fountain/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/FountainFbo/Android.mk b/tests/RenderScriptTests/FountainFbo/Android.mk
index 55a4fd8..4535eb1 100644
--- a/tests/RenderScriptTests/FountainFbo/Android.mk
+++ b/tests/RenderScriptTests/FountainFbo/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/Fountain_v11/Android.mk b/tests/RenderScriptTests/Fountain_v11/Android.mk
index e51115c..fe7f9e7 100644
--- a/tests/RenderScriptTests/Fountain_v11/Android.mk
+++ b/tests/RenderScriptTests/Fountain_v11/Android.mk
@@ -19,7 +19,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 #LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
diff --git a/tests/RenderScriptTests/HelloWorld/Android.mk b/tests/RenderScriptTests/HelloWorld/Android.mk
index 2af1cdb..54824f4 100644
--- a/tests/RenderScriptTests/HelloWorld/Android.mk
+++ b/tests/RenderScriptTests/HelloWorld/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/img1600x1067.jpg b/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/img1600x1067.jpg
new file mode 100644
index 0000000..05d3ee2
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/img1600x1067.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/img1600x1067b.jpg b/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/img1600x1067b.jpg
new file mode 100644
index 0000000..aed0781
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/img1600x1067b.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing/res/layout/main.xml b/tests/RenderScriptTests/ImageProcessing/res/layout/main.xml
index 08a010d..f0a2b92 100644
--- a/tests/RenderScriptTests/ImageProcessing/res/layout/main.xml
+++ b/tests/RenderScriptTests/ImageProcessing/res/layout/main.xml
@@ -50,8 +50,16 @@
                         android:textSize="8pt"
                         android:text="@string/saturation"/>
             </LinearLayout>
+            <Spinner
+                android:id="@+id/filterselection"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <Spinner
+                android:id="@+id/spinner1"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
             <TextView
-                android:id="@+id/inSaturationText"
+                android:id="@+id/slider1Text"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:textSize="8pt"
@@ -59,13 +67,13 @@
                 android:layout_marginTop="15sp"
                 android:text="@string/saturation"/>
              <SeekBar
-                android:id="@+id/inSaturation"
+                android:id="@+id/slider1"
                 android:layout_marginLeft="10sp"
                 android:layout_marginRight="10sp"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"/>
             <TextView
-                android:id="@+id/inGammaText"
+                android:id="@+id/slider2Text"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:textSize="8pt"
@@ -73,13 +81,13 @@
                 android:layout_marginTop="15sp"
                 android:text="@string/gamma"/>
             <SeekBar
-                android:id="@+id/inGamma"
+                android:id="@+id/slider2"
                 android:layout_marginLeft="10sp"
                 android:layout_marginRight="10sp"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"/>
             <TextView
-                android:id="@+id/outWhiteText"
+                android:id="@+id/slider3Text"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_marginLeft="10sp"
@@ -87,13 +95,13 @@
                 android:textSize="8pt"
                 android:text="@string/out_white"/>
             <SeekBar
-                android:id="@+id/outWhite"
+                android:id="@+id/slider3"
                 android:layout_marginLeft="10sp"
                 android:layout_marginRight="10sp"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"/>
             <TextView
-                android:id="@+id/inWhiteText"
+                android:id="@+id/slider4Text"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:textSize="8pt"
@@ -101,53 +109,30 @@
                 android:layout_marginTop="15sp"
                 android:text="@string/in_white"/>
             <SeekBar
-                android:id="@+id/inWhite"
+                android:id="@+id/slider4"
                 android:layout_marginLeft="10sp"
                 android:layout_marginRight="10sp"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"/>
             <TextView
-                android:id="@+id/outBlackText"
+                android:id="@+id/slider5Text"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:textSize="8pt"
                 android:layout_marginLeft="10sp"
                 android:layout_marginTop="15sp"
-                android:text="@string/out_black"/>
+                android:text="@string/in_white"/>
             <SeekBar
-                android:id="@+id/outBlack"
+                android:id="@+id/slider5"
                 android:layout_marginLeft="10sp"
                 android:layout_marginRight="10sp"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"/>
-            <TextView
-                android:id="@+id/inBlackText"
-                android:layout_width="match_parent"
+            <Button
+                android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:textSize="8pt"
-                android:layout_marginLeft="10sp"
-                android:layout_marginTop="15sp"
-                android:text="@string/in_black"/>
-            <SeekBar
-                android:id="@+id/inBlack"
-                android:layout_marginLeft="10sp"
-                android:layout_marginRight="10sp"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"/>
-            <TextView
-                android:id="@+id/blurText"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:textSize="8pt"
-                 android:layout_marginLeft="10sp"
-                android:layout_marginTop="15sp"
-                android:text="@string/blur_description"/>
-            <SeekBar
-                android:id="@+id/radius"
-                android:layout_marginLeft="10sp"
-                android:layout_marginRight="10sp"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"/>
+                android:text="@string/benchmark_all"
+                    android:onClick="benchmark_all"/>
             </LinearLayout>
     </ScrollView>
 </LinearLayout>
diff --git a/tests/RenderScriptTests/ImageProcessing/res/layout/spinner_layout.xml b/tests/RenderScriptTests/ImageProcessing/res/layout/spinner_layout.xml
new file mode 100644
index 0000000..8196bbf
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/res/layout/spinner_layout.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:padding="10dp"
+    android:textSize="16sp"
+/>
diff --git a/tests/RenderScriptTests/ImageProcessing/res/values/strings.xml b/tests/RenderScriptTests/ImageProcessing/res/values/strings.xml
index cc5cc4d..a7dd165 100644
--- a/tests/RenderScriptTests/ImageProcessing/res/values/strings.xml
+++ b/tests/RenderScriptTests/ImageProcessing/res/values/strings.xml
@@ -29,5 +29,6 @@
     <string name="gamma">Gamma</string>
     <string name="saturation">Saturation</string>
     <string name="benchmark">Benchmark</string>
+    <string name="benchmark_all">Benchmark All</string>
 
 </resources>
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blend.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blend.java
new file mode 100644
index 0000000..2303fc3
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blend.java
@@ -0,0 +1,178 @@
+/*
+ * 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.rs.image;
+
+import java.lang.Math;
+import java.lang.Short;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsicBlend;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.view.View;
+import android.widget.Spinner;
+
+public class Blend extends TestBase {
+    private ScriptIntrinsicBlend mBlend;
+    private ScriptC_blend mBlendHelper;
+    private short image1Alpha = 128;
+    private short image2Alpha = 128;
+
+    String mIntrinsicNames[];
+
+    private Allocation image1;
+    private Allocation image2;
+    private int currentIntrinsic = 0;
+
+    private AdapterView.OnItemSelectedListener mIntrinsicSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                    currentIntrinsic = pos;
+                    if (mRS != null) {
+                        runTest();
+                        act.updateDisplay();
+                    }
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+            };
+
+    public void createTest(android.content.res.Resources res) {
+        mBlend = ScriptIntrinsicBlend.create(mRS, Element.U8_4(mRS));
+        mBlendHelper = new ScriptC_blend(mRS);
+        mBlendHelper.set_alpha((short)128);
+
+        image1 = Allocation.createTyped(mRS, mInPixelsAllocation.getType());
+        image2 = Allocation.createTyped(mRS, mInPixelsAllocation2.getType());
+
+        mIntrinsicNames = new String[14];
+        mIntrinsicNames[0] = "Source";
+        mIntrinsicNames[1] = "Destination";
+        mIntrinsicNames[2] = "Source Over";
+        mIntrinsicNames[3] = "Destination Over";
+        mIntrinsicNames[4] = "Source In";
+        mIntrinsicNames[5] = "Destination In";
+        mIntrinsicNames[6] = "Source Out";
+        mIntrinsicNames[7] = "Destination Out";
+        mIntrinsicNames[8] = "Source Atop";
+        mIntrinsicNames[9] = "Destination Atop";
+        mIntrinsicNames[10] = "XOR";
+        mIntrinsicNames[11] = "Add";
+        mIntrinsicNames[12] = "Subtract";
+        mIntrinsicNames[13] = "Multiply";
+    }
+
+    public boolean onSpinner1Setup(Spinner s) {
+        s.setAdapter(new ArrayAdapter<String>(
+            act, R.layout.spinner_layout, mIntrinsicNames));
+        s.setOnItemSelectedListener(mIntrinsicSpinnerListener);
+        return true;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Image 1 Alpha");
+        b.setMax(255);
+        b.setProgress(image1Alpha);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        image1Alpha = (short)progress;
+    }
+
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Image 2 Alpha");
+        b.setMax(255);
+        b.setProgress(image2Alpha);
+        return true;
+    }
+
+    public void onBar2Changed(int progress) {
+        image2Alpha = (short)progress;
+    }
+
+    public void runTest() {
+        image1.copy2DRangeFrom(0, 0, mInPixelsAllocation.getType().getX(), mInPixelsAllocation.getType().getY(), mInPixelsAllocation, 0, 0);
+        image2.copy2DRangeFrom(0, 0, mInPixelsAllocation2.getType().getX(), mInPixelsAllocation2.getType().getY(), mInPixelsAllocation2, 0, 0);
+
+        mBlendHelper.set_alpha(image1Alpha);
+        mBlendHelper.forEach_setImageAlpha(image1);
+
+        mBlendHelper.set_alpha(image2Alpha);
+        mBlendHelper.forEach_setImageAlpha(image2);
+
+        switch (currentIntrinsic) {
+        case 0:
+            mBlend.forEachSrc(image1, image2);
+            break;
+        case 1:
+            mBlend.forEachDst(image1, image2);
+            break;
+        case 2:
+            mBlend.forEachSrcOver(image1, image2);
+            break;
+        case 3:
+            mBlend.forEachDstOver(image1, image2);
+            break;
+        case 4:
+            mBlend.forEachSrcIn(image1, image2);
+            break;
+        case 5:
+            mBlend.forEachDstIn(image1, image2);
+            break;
+        case 6:
+            mBlend.forEachSrcOut(image1, image2);
+            break;
+        case 7:
+            mBlend.forEachDstOut(image1, image2);
+            break;
+        case 8:
+            mBlend.forEachSrcAtop(image1, image2);
+            break;
+        case 9:
+            mBlend.forEachDstAtop(image1, image2);
+            break;
+        case 10:
+            mBlend.forEachXor(image1, image2);
+            break;
+        case 11:
+            mBlend.forEachAdd(image1, image2);
+            break;
+        case 12:
+            mBlend.forEachSubtract(image1, image2);
+            break;
+        case 13:
+            mBlend.forEachMultiply(image1, image2);
+            break;
+        }
+
+        mOutPixelsAllocation.copy2DRangeFrom(0, 0, image2.getType().getX(), image2.getType().getY(), image2, 0, 0);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blur25.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blur25.java
new file mode 100644
index 0000000..0c6d41d
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blur25.java
@@ -0,0 +1,118 @@
+/*
+ * 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.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicBlur;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Blur25 extends TestBase {
+    private boolean mUseIntrinsic = false;
+    private ScriptIntrinsicBlur mIntrinsic;
+
+    private int MAX_RADIUS = 25;
+    private ScriptC_threshold mScript;
+    private float mRadius = MAX_RADIUS;
+    private float mSaturation = 1.0f;
+    private Allocation mScratchPixelsAllocation1;
+    private Allocation mScratchPixelsAllocation2;
+
+
+    public Blur25(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Radius");
+        b.setProgress(100);
+        return true;
+    }
+
+
+    public void onBar1Changed(int progress) {
+        mRadius = ((float)progress) / 100.0f * MAX_RADIUS;
+        if (mRadius <= 0.10f) {
+            mRadius = 0.10f;
+        }
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(mRadius);
+        } else {
+            mScript.invoke_setRadius((int)mRadius);
+        }
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setRadius(MAX_RADIUS);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+
+            Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
+            tb.setX(width);
+            tb.setY(height);
+            mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+            mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+
+            mScript = new ScriptC_threshold(mRS, res, R.raw.threshold);
+            mScript.set_width(width);
+            mScript.set_height(height);
+            mScript.invoke_setRadius(MAX_RADIUS);
+
+            mScript.set_InPixel(mInPixelsAllocation);
+            mScript.set_ScratchPixel1(mScratchPixelsAllocation1);
+            mScript.set_ScratchPixel2(mScratchPixelsAllocation2);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_copyIn(mInPixelsAllocation, mScratchPixelsAllocation1);
+            mScript.forEach_horz(mScratchPixelsAllocation2);
+            mScript.forEach_vert(mOutPixelsAllocation);
+        }
+    }
+
+    public void setupBenchmark() {
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(MAX_RADIUS);
+        } else {
+            mScript.invoke_setRadius(MAX_RADIUS);
+        }
+    }
+
+    public void exitBenchmark() {
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(mRadius);
+        } else {
+            mScript.invoke_setRadius((int)mRadius);
+        }
+    }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ColorMatrix.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ColorMatrix.java
new file mode 100644
index 0000000..2ac40a1
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ColorMatrix.java
@@ -0,0 +1,70 @@
+/*
+ * 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.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsicColorMatrix;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class ColorMatrix extends TestBase {
+    private ScriptC_colormatrix mScript;
+    private ScriptIntrinsicColorMatrix mIntrinsic;
+    private boolean mUseIntrinsic;
+    private boolean mUseGrey;
+
+    public ColorMatrix(boolean useIntrinsic, boolean useGrey) {
+        mUseIntrinsic = useIntrinsic;
+        mUseGrey = useGrey;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+            if (mUseGrey) {
+                mIntrinsic.setGreyscale();
+            } else {
+                mIntrinsic.setColorMatrix(m);
+            }
+        } else {
+            mScript = new ScriptC_colormatrix(mRS, res, R.raw.colormatrix);
+            mScript.invoke_setMatrix(m);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Convolve3x3.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Convolve3x3.java
new file mode 100644
index 0000000..18e9b43
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Convolve3x3.java
@@ -0,0 +1,74 @@
+/*
+ * 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.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsicConvolve3x3;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Convolve3x3 extends TestBase {
+    private ScriptC_convolve3x3 mScript;
+    private ScriptIntrinsicConvolve3x3 mIntrinsic;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseIntrinsic;
+
+    public Convolve3x3(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        float f[] = new float[9];
+        f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
+        f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
+        f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setCoefficients(f);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+            mScript = new ScriptC_convolve3x3(mRS, res, R.raw.convolve3x3);
+            mScript.set_gCoeffs(f);
+            mScript.set_gIn(mInPixelsAllocation);
+            mScript.set_gWidth(mWidth);
+            mScript.set_gHeight(mHeight);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Convolve5x5.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Convolve5x5.java
new file mode 100644
index 0000000..03b3bb8
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Convolve5x5.java
@@ -0,0 +1,88 @@
+/*
+ * 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.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsicConvolve5x5;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Convolve5x5 extends TestBase {
+    private ScriptC_convolve5x5 mScript;
+    private ScriptIntrinsicConvolve5x5 mIntrinsic;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseIntrinsic;
+
+    public Convolve5x5(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        float f[] = new float[25];
+        //f[0] = 0.012f; f[1] = 0.025f; f[2] = 0.031f; f[3] = 0.025f; f[4] = 0.012f;
+        //f[5] = 0.025f; f[6] = 0.057f; f[7] = 0.075f; f[8] = 0.057f; f[9] = 0.025f;
+        //f[10]= 0.031f; f[11]= 0.075f; f[12]= 0.095f; f[13]= 0.075f; f[14]= 0.031f;
+        //f[15]= 0.025f; f[16]= 0.057f; f[17]= 0.075f; f[18]= 0.057f; f[19]= 0.025f;
+        //f[20]= 0.012f; f[21]= 0.025f; f[22]= 0.031f; f[23]= 0.025f; f[24]= 0.012f;
+
+        //f[0] = 1.f; f[1] = 2.f; f[2] = 0.f; f[3] = -2.f; f[4] = -1.f;
+        //f[5] = 4.f; f[6] = 8.f; f[7] = 0.f; f[8] = -8.f; f[9] = -4.f;
+        //f[10]= 6.f; f[11]=12.f; f[12]= 0.f; f[13]=-12.f; f[14]= -6.f;
+        //f[15]= 4.f; f[16]= 8.f; f[17]= 0.f; f[18]= -8.f; f[19]= -4.f;
+        //f[20]= 1.f; f[21]= 2.f; f[22]= 0.f; f[23]= -2.f; f[24]= -1.f;
+
+        f[0] = -1.f; f[1] = -3.f; f[2] = -4.f; f[3] = -3.f; f[4] = -1.f;
+        f[5] = -3.f; f[6] =  0.f; f[7] =  6.f; f[8] =  0.f; f[9] = -3.f;
+        f[10]= -4.f; f[11]=  6.f; f[12]= 20.f; f[13]=  6.f; f[14]= -4.f;
+        f[15]= -3.f; f[16]=  0.f; f[17]=  6.f; f[18]=  0.f; f[19]= -3.f;
+        f[20]= -1.f; f[21]= -3.f; f[22]= -4.f; f[23]= -3.f; f[24]= -1.f;
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicConvolve5x5.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setCoefficients(f);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+            mScript = new ScriptC_convolve5x5(mRS, res, R.raw.convolve5x5);
+            mScript.set_gCoeffs(f);
+            mScript.set_gIn(mInPixelsAllocation);
+            mScript.set_gWidth(mWidth);
+            mScript.set_gHeight(mHeight);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Copy.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Copy.java
new file mode 100644
index 0000000..efca0b5
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Copy.java
@@ -0,0 +1,40 @@
+/*
+ * 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.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Copy extends TestBase {
+    private ScriptC_copy mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_copy(mRS, res, R.raw.copy);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/CrossProcess.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/CrossProcess.java
new file mode 100644
index 0000000..b9e3524
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/CrossProcess.java
@@ -0,0 +1,63 @@
+/*
+ * 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.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicLUT;
+import android.util.Log;
+
+public class CrossProcess extends TestBase {
+    private ScriptIntrinsicLUT mIntrinsic;
+
+    public void createTest(android.content.res.Resources res) {
+        mIntrinsic = ScriptIntrinsicLUT.create(mRS, Element.U8_4(mRS));
+        for (int ct=0; ct < 256; ct++) {
+            float f = ((float)ct) / 255.f;
+
+            float r = f;
+            if (r < 0.5f) {
+                r = 4.0f * r * r * r;
+            } else {
+                r = 1.0f - r;
+                r = 1.0f - (4.0f * r * r * r);
+            }
+            mIntrinsic.setRed(ct, (int)(r * 255.f + 0.5f));
+
+            float g = f;
+            if (g < 0.5f) {
+                g = 2.0f * g * g;
+            } else {
+                g = 1.0f - g;
+                g = 1.0f - (2.0f * g * g);
+            }
+            mIntrinsic.setGreen(ct, (int)(g * 255.f + 0.5f));
+
+            float b = f * 0.5f + 0.25f;
+            mIntrinsic.setBlue(ct, (int)(b * 255.f + 0.5f));
+        }
+
+    }
+
+    public void runTest() {
+        mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Fisheye.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Fisheye.java
new file mode 100644
index 0000000..81868b10
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Fisheye.java
@@ -0,0 +1,138 @@
+/*
+ * 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.rs.image;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Sampler;
+import android.renderscript.Type;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Fisheye extends TestBase {
+    private ScriptC_fisheye_full mScript_full = null;
+    private ScriptC_fisheye_relaxed mScript_relaxed = null;
+    private ScriptC_fisheye_approx_full mScript_approx_full = null;
+    private ScriptC_fisheye_approx_relaxed mScript_approx_relaxed = null;
+    private final boolean approx;
+    private final boolean relaxed;
+    private float center_x = 0.5f;
+    private float center_y = 0.5f;
+    private float scale = 0.5f;
+
+    public Fisheye(boolean approx, boolean relaxed) {
+        this.approx = approx;
+        this.relaxed = relaxed;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Scale");
+        b.setMax(100);
+        b.setProgress(25);
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Shift center X");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Shift center Y");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        scale = progress / 50.0f;
+        do_init();
+    }
+    public void onBar2Changed(int progress) {
+        center_x = progress / 100.0f;
+        do_init();
+    }
+    public void onBar3Changed(int progress) {
+        center_y = progress / 100.0f;
+        do_init();
+    }
+
+    private void do_init() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.invoke_init_filter(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale);
+            else
+                mScript_approx_full.invoke_init_filter(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale);
+        } else if (relaxed)
+            mScript_relaxed.invoke_init_filter(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale);
+        else
+            mScript_full.invoke_init_filter(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        if (approx) {
+            if (relaxed) {
+                mScript_approx_relaxed = new ScriptC_fisheye_approx_relaxed(mRS,
+                        res, R.raw.fisheye_approx_relaxed);
+                mScript_approx_relaxed.set_in_alloc(mInPixelsAllocation);
+                mScript_approx_relaxed.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+            } else {
+                mScript_approx_full = new ScriptC_fisheye_approx_full(mRS, res,
+                        R.raw.fisheye_approx_full);
+                mScript_approx_full.set_in_alloc(mInPixelsAllocation);
+                mScript_approx_full.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+            }
+        } else if (relaxed) {
+            mScript_relaxed = new ScriptC_fisheye_relaxed(mRS, res,
+                    R.raw.fisheye_relaxed);
+            mScript_relaxed.set_in_alloc(mInPixelsAllocation);
+            mScript_relaxed.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+        } else {
+            mScript_full = new ScriptC_fisheye_full(mRS, res,
+                    R.raw.fisheye_full);
+            mScript_full.set_in_alloc(mInPixelsAllocation);
+            mScript_full.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+        }
+        do_init();
+    }
+
+    public void runTest() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.forEach_root(mOutPixelsAllocation);
+            else
+                mScript_approx_full.forEach_root(mOutPixelsAllocation);
+        } else if (relaxed)
+            mScript_relaxed.forEach_root(mOutPixelsAllocation);
+        else
+            mScript_full.forEach_root(mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Grain.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Grain.java
new file mode 100644
index 0000000..8618cc8
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Grain.java
@@ -0,0 +1,94 @@
+/*
+ * 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.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Grain extends TestBase {
+    private ScriptC_grain mScript;
+    private Allocation mNoise;
+    private Allocation mNoise2;
+
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Strength");
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        float s = progress / 100.0f;
+        mScript.set_gNoiseStrength(s);
+    }
+
+    private int findHighBit(int v) {
+        int bit = 0;
+        while (v > 1) {
+            bit++;
+            v >>= 1;
+        }
+        return bit;
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        int noiseW = findHighBit(width);
+        int noiseH = findHighBit(height);
+        if (noiseW > 9) {
+            noiseW = 9;
+        }
+        if (noiseH > 9) {
+            noiseH = 9;
+        }
+        noiseW = 1 << noiseW;
+        noiseH = 1 << noiseH;
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
+        tb.setX(noiseW);
+        tb.setY(noiseH);
+        mNoise = Allocation.createTyped(mRS, tb.create());
+        mNoise2 = Allocation.createTyped(mRS, tb.create());
+
+        mScript = new ScriptC_grain(mRS, res, R.raw.grain);
+        mScript.set_gWMask(noiseW - 1);
+        mScript.set_gHMask(noiseH - 1);
+        mScript.set_gNoiseStrength(0.5f);
+        mScript.set_gBlendSource(mNoise);
+        mScript.set_gNoise(mNoise2);
+    }
+
+    public void runTest() {
+        mScript.forEach_genRand(mNoise);
+        mScript.forEach_blend9(mNoise2);
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Greyscale.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Greyscale.java
new file mode 100644
index 0000000..3db210a
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Greyscale.java
@@ -0,0 +1,40 @@
+/*
+ * 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.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Greyscale extends TestBase {
+    private ScriptC_greyscale mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_greyscale(mRS, res, R.raw.greyscale);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/GroupTest.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/GroupTest.java
new file mode 100644
index 0000000..29c204c
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/GroupTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicConvolve3x3;
+import android.renderscript.ScriptIntrinsicColorMatrix;
+import android.renderscript.Type;
+import android.renderscript.Matrix4f;
+import android.renderscript.ScriptGroup;
+import android.util.Log;
+
+public class GroupTest extends TestBase {
+    private ScriptIntrinsicConvolve3x3 mConvolve;
+    private ScriptIntrinsicColorMatrix mMatrix;
+
+    private Allocation mScratchPixelsAllocation1;
+    private ScriptGroup mGroup;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseNative;
+
+
+    public GroupTest(boolean useNative) {
+        mUseNative = useNative;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        mConvolve = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+        mMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+
+        float f[] = new float[9];
+        f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
+        f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
+        f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
+        mConvolve.setCoefficients(f);
+
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+        mMatrix.setColorMatrix(m);
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8_4(mRS));
+        tb.setX(mWidth);
+        tb.setY(mHeight);
+        Type connect = tb.create();
+
+        if (mUseNative) {
+            ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
+            b.addKernel(mConvolve.getKernelID());
+            b.addKernel(mMatrix.getKernelID());
+            b.addConnection(connect, mConvolve.getKernelID(), mMatrix.getKernelID());
+            mGroup = b.create();
+        } else {
+            mScratchPixelsAllocation1 = Allocation.createTyped(mRS, connect);
+        }
+    }
+
+    public void runTest() {
+        mConvolve.setInput(mInPixelsAllocation);
+        if (mUseNative) {
+            mGroup.setOutput(mMatrix.getKernelID(), mOutPixelsAllocation);
+            mGroup.execute();
+        } else {
+            mConvolve.forEach(mScratchPixelsAllocation1);
+            mMatrix.forEach(mScratchPixelsAllocation1, mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index 7368260..db0ef78 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 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.
@@ -29,124 +29,82 @@
 import android.renderscript.Script;
 import android.view.SurfaceView;
 import android.view.SurfaceHolder;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
 import android.widget.ImageView;
 import android.widget.SeekBar;
+import android.widget.Spinner;
 import android.widget.TextView;
 import android.view.View;
 import android.util.Log;
 import java.lang.Math;
 
-public class ImageProcessingActivity extends Activity
-                                       implements SurfaceHolder.Callback,
-                                       SeekBar.OnSeekBarChangeListener {
-    private final String TAG = "Img";
-    private Bitmap mBitmapIn;
-    private Bitmap mBitmapOut;
-    private ScriptC_threshold mScript;
-    private ScriptC_vertical_blur mScriptVBlur;
-    private ScriptC_horizontal_blur mScriptHBlur;
-    private int mRadius = 0;
-    private SeekBar mRadiusSeekBar;
+import android.os.Environment;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
 
-    private float mInBlack = 0.0f;
-    private SeekBar mInBlackSeekBar;
-    private float mOutBlack = 0.0f;
-    private SeekBar mOutBlackSeekBar;
-    private float mInWhite = 255.0f;
-    private SeekBar mInWhiteSeekBar;
-    private float mOutWhite = 255.0f;
-    private SeekBar mOutWhiteSeekBar;
-    private float mGamma = 1.0f;
-    private SeekBar mGammaSeekBar;
+public class ImageProcessingActivity extends Activity
+                                       implements SeekBar.OnSeekBarChangeListener {
+    private final String TAG = "Img";
+    private final String RESULT_FILE = "image_processing_result.csv";
+
+    Bitmap mBitmapIn;
+    Bitmap mBitmapIn2;
+    Bitmap mBitmapOut;
+    String mTestNames[];
+
+    private Spinner mSpinner;
+    private SeekBar mBar1;
+    private SeekBar mBar2;
+    private SeekBar mBar3;
+    private SeekBar mBar4;
+    private SeekBar mBar5;
+    private TextView mText1;
+    private TextView mText2;
+    private TextView mText3;
+    private TextView mText4;
+    private TextView mText5;
 
     private float mSaturation = 1.0f;
-    private SeekBar mSaturationSeekBar;
 
     private TextView mBenchmarkResult;
-
-    @SuppressWarnings({"FieldCanBeLocal"})
-    private RenderScript mRS;
-    @SuppressWarnings({"FieldCanBeLocal"})
-    private Type mPixelType;
-    @SuppressWarnings({"FieldCanBeLocal"})
-    private Allocation mInPixelsAllocation;
-    @SuppressWarnings({"FieldCanBeLocal"})
-    private Allocation mOutPixelsAllocation;
-    @SuppressWarnings({"FieldCanBeLocal"})
-    private Allocation mScratchPixelsAllocation1;
-    private Allocation mScratchPixelsAllocation2;
+    private Spinner mTestSpinner;
 
     private SurfaceView mSurfaceView;
     private ImageView mDisplayView;
 
-    private boolean mIsProcessing;
+    private boolean mDoingBenchmark;
 
-    class FilterCallback extends RenderScript.RSMessageHandler {
-        private Runnable mAction = new Runnable() {
-            public void run() {
+    private TestBase mTest;
 
-                synchronized (mDisplayView) {
-                    mIsProcessing = false;
-                }
-
-                mOutPixelsAllocation.copyTo(mBitmapOut);
-                mDisplayView.invalidate();
-            }
-        };
-
-        @Override
-        public void run() {
-            mSurfaceView.removeCallbacks(mAction);
-            mSurfaceView.post(mAction);
-        }
+    public void updateDisplay() {
+            mTest.updateBitmap(mBitmapOut);
+            mDisplayView.invalidate();
     }
 
-    int in[];
-    int interm[];
-    int out[];
-    int MAX_RADIUS = 25;
-    // Store our coefficients here
-    float gaussian[];
-
     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
         if (fromUser) {
 
-            if (seekBar == mRadiusSeekBar) {
-                float fRadius = progress / 100.0f;
-                fRadius *= (float)(MAX_RADIUS);
-                mRadius = (int)fRadius;
-
-                mScript.set_radius(mRadius);
-            } else if (seekBar == mInBlackSeekBar) {
-                mInBlack = (float)progress;
-                mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
-            } else if (seekBar == mOutBlackSeekBar) {
-                mOutBlack = (float)progress;
-                mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
-            } else if (seekBar == mInWhiteSeekBar) {
-                mInWhite = (float)progress + 127.0f;
-                mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
-            } else if (seekBar == mOutWhiteSeekBar) {
-                mOutWhite = (float)progress + 127.0f;
-                mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
-            } else if (seekBar == mGammaSeekBar) {
-                mGamma = (float)progress/100.0f;
-                mGamma = Math.max(mGamma, 0.1f);
-                mGamma = 1.0f / mGamma;
-                mScriptVBlur.invoke_setGamma(mGamma);
-            } else if (seekBar == mSaturationSeekBar) {
-                mSaturation = (float)progress / 50.0f;
-                mScriptVBlur.invoke_setSaturation(mSaturation);
+            if (seekBar == mBar1) {
+                mTest.onBar1Changed(progress);
+            } else if (seekBar == mBar2) {
+                mTest.onBar2Changed(progress);
+            } else if (seekBar == mBar3) {
+                mTest.onBar3Changed(progress);
+            } else if (seekBar == mBar4) {
+                mTest.onBar4Changed(progress);
+            } else if (seekBar == mBar5) {
+                mTest.onBar5Changed(progress);
             }
 
-            synchronized (mDisplayView) {
-                if (mIsProcessing) {
-                    return;
-                }
-                mIsProcessing = true;
-            }
-
-            mScript.invoke_filter();
+            mTest.runTest();
+            updateDisplay();
         }
     }
 
@@ -156,103 +114,225 @@
     public void onStopTrackingTouch(SeekBar seekBar) {
     }
 
+    void setupBars() {
+        mSpinner.setVisibility(View.VISIBLE);
+        mTest.onSpinner1Setup(mSpinner);
+
+        mBar1.setVisibility(View.VISIBLE);
+        mText1.setVisibility(View.VISIBLE);
+        mTest.onBar1Setup(mBar1, mText1);
+
+        mBar2.setVisibility(View.VISIBLE);
+        mText2.setVisibility(View.VISIBLE);
+        mTest.onBar2Setup(mBar2, mText2);
+
+        mBar3.setVisibility(View.VISIBLE);
+        mText3.setVisibility(View.VISIBLE);
+        mTest.onBar3Setup(mBar3, mText3);
+
+        mBar4.setVisibility(View.VISIBLE);
+        mText4.setVisibility(View.VISIBLE);
+        mTest.onBar4Setup(mBar4, mText4);
+
+        mBar5.setVisibility(View.VISIBLE);
+        mText5.setVisibility(View.VISIBLE);
+        mTest.onBar5Setup(mBar5, mText5);
+    }
+
+
+    void changeTest(int testID) {
+        if (mTest != null) {
+            mTest.destroy();
+        }
+        switch(testID) {
+        case 0:
+            mTest = new LevelsV4(false, false);
+            break;
+        case 1:
+            mTest = new LevelsV4(false, true);
+            break;
+        case 2:
+            mTest = new LevelsV4(true, false);
+            break;
+        case 3:
+            mTest = new LevelsV4(true, true);
+            break;
+        case 4:
+            mTest = new Blur25(false);
+            break;
+        case 5:
+            mTest = new Blur25(true);
+            break;
+        case 6:
+            mTest = new Greyscale();
+            break;
+        case 7:
+            mTest = new Grain();
+            break;
+        case 8:
+            mTest = new Fisheye(false, false);
+            break;
+        case 9:
+            mTest = new Fisheye(false, true);
+            break;
+        case 10:
+            mTest = new Fisheye(true, false);
+            break;
+        case 11:
+            mTest = new Fisheye(true, true);
+            break;
+        case 12:
+            mTest = new Vignette(false, false);
+            break;
+        case 13:
+            mTest = new Vignette(false, true);
+            break;
+        case 14:
+            mTest = new Vignette(true, false);
+            break;
+        case 15:
+            mTest = new Vignette(true, true);
+            break;
+        case 16:
+            mTest = new GroupTest(false);
+            break;
+        case 17:
+            mTest = new GroupTest(true);
+            break;
+        case 18:
+            mTest = new Convolve3x3(false);
+            break;
+        case 19:
+            mTest = new Convolve3x3(true);
+            break;
+        case 20:
+            mTest = new ColorMatrix(false, false);
+            break;
+        case 21:
+            mTest = new ColorMatrix(true, false);
+            break;
+        case 22:
+            mTest = new ColorMatrix(true, true);
+            break;
+        case 23:
+            mTest = new Copy();
+            break;
+        case 24:
+            mTest = new CrossProcess();
+            break;
+        case 25:
+            mTest = new Convolve5x5(false);
+            break;
+        case 26:
+            mTest = new Convolve5x5(true);
+            break;
+        case 27:
+            mTest = new Mandelbrot();
+            break;
+        case 28:
+            mTest = new Blend();
+            break;
+        }
+
+        mTest.createBaseTest(this, mBitmapIn, mBitmapIn2);
+        setupBars();
+
+        mTest.runTest();
+        updateDisplay();
+        mBenchmarkResult.setText("Result: not run");
+    }
+
+    void setupTests() {
+        mTestNames = new String[29];
+        mTestNames[0] = "Levels Vec3 Relaxed";
+        mTestNames[1] = "Levels Vec4 Relaxed";
+        mTestNames[2] = "Levels Vec3 Full";
+        mTestNames[3] = "Levels Vec4 Full";
+        mTestNames[4] = "Blur radius 25";
+        mTestNames[5] = "Intrinsic Blur radius 25";
+        mTestNames[6] = "Greyscale";
+        mTestNames[7] = "Grain";
+        mTestNames[8] = "Fisheye Full";
+        mTestNames[9] = "Fisheye Relaxed";
+        mTestNames[10] = "Fisheye Approximate Full";
+        mTestNames[11] = "Fisheye Approximate Relaxed";
+        mTestNames[12] = "Vignette Full";
+        mTestNames[13] = "Vignette Relaxed";
+        mTestNames[14] = "Vignette Approximate Full";
+        mTestNames[15] = "Vignette Approximate Relaxed";
+        mTestNames[16] = "Group Test (emulated)";
+        mTestNames[17] = "Group Test (native)";
+        mTestNames[18] = "Convolve 3x3";
+        mTestNames[19] = "Intrinsics Convolve 3x3";
+        mTestNames[20] = "ColorMatrix";
+        mTestNames[21] = "Intrinsics ColorMatrix";
+        mTestNames[22] = "Intrinsics ColorMatrix Grey";
+        mTestNames[23] = "Copy";
+        mTestNames[24] = "CrossProcess (using LUT)";
+        mTestNames[25] = "Convolve 5x5";
+        mTestNames[26] = "Intrinsics Convolve 5x5";
+        mTestNames[27] = "Mandelbrot";
+        mTestNames[28] = "Intrinsics Blend";
+
+        mTestSpinner.setAdapter(new ArrayAdapter<String>(
+            this, R.layout.spinner_layout, mTestNames));
+    }
+
+    private AdapterView.OnItemSelectedListener mTestSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                    changeTest(pos);
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+            };
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
 
-        mBitmapIn = loadBitmap(R.drawable.city);
-        mBitmapOut = loadBitmap(R.drawable.city);
+        mBitmapIn = loadBitmap(R.drawable.img1600x1067);
+        mBitmapIn2 = loadBitmap(R.drawable.img1600x1067b);
+        mBitmapOut = loadBitmap(R.drawable.img1600x1067);
 
         mSurfaceView = (SurfaceView) findViewById(R.id.surface);
-        mSurfaceView.getHolder().addCallback(this);
 
         mDisplayView = (ImageView) findViewById(R.id.display);
         mDisplayView.setImageBitmap(mBitmapOut);
 
-        mRadiusSeekBar = (SeekBar) findViewById(R.id.radius);
-        mRadiusSeekBar.setOnSeekBarChangeListener(this);
+        mSpinner = (Spinner) findViewById(R.id.spinner1);
 
-        mInBlackSeekBar = (SeekBar)findViewById(R.id.inBlack);
-        mInBlackSeekBar.setOnSeekBarChangeListener(this);
-        mInBlackSeekBar.setMax(128);
-        mInBlackSeekBar.setProgress(0);
-        mOutBlackSeekBar = (SeekBar)findViewById(R.id.outBlack);
-        mOutBlackSeekBar.setOnSeekBarChangeListener(this);
-        mOutBlackSeekBar.setMax(128);
-        mOutBlackSeekBar.setProgress(0);
+        mBar1 = (SeekBar) findViewById(R.id.slider1);
+        mBar2 = (SeekBar) findViewById(R.id.slider2);
+        mBar3 = (SeekBar) findViewById(R.id.slider3);
+        mBar4 = (SeekBar) findViewById(R.id.slider4);
+        mBar5 = (SeekBar) findViewById(R.id.slider5);
 
-        mInWhiteSeekBar = (SeekBar)findViewById(R.id.inWhite);
-        mInWhiteSeekBar.setOnSeekBarChangeListener(this);
-        mInWhiteSeekBar.setMax(128);
-        mInWhiteSeekBar.setProgress(128);
-        mOutWhiteSeekBar = (SeekBar)findViewById(R.id.outWhite);
-        mOutWhiteSeekBar.setOnSeekBarChangeListener(this);
-        mOutWhiteSeekBar.setMax(128);
-        mOutWhiteSeekBar.setProgress(128);
+        mBar1.setOnSeekBarChangeListener(this);
+        mBar2.setOnSeekBarChangeListener(this);
+        mBar3.setOnSeekBarChangeListener(this);
+        mBar4.setOnSeekBarChangeListener(this);
+        mBar5.setOnSeekBarChangeListener(this);
 
-        mGammaSeekBar = (SeekBar)findViewById(R.id.inGamma);
-        mGammaSeekBar.setOnSeekBarChangeListener(this);
-        mGammaSeekBar.setMax(150);
-        mGammaSeekBar.setProgress(100);
+        mText1 = (TextView) findViewById(R.id.slider1Text);
+        mText2 = (TextView) findViewById(R.id.slider2Text);
+        mText3 = (TextView) findViewById(R.id.slider3Text);
+        mText4 = (TextView) findViewById(R.id.slider4Text);
+        mText5 = (TextView) findViewById(R.id.slider5Text);
 
-        mSaturationSeekBar = (SeekBar)findViewById(R.id.inSaturation);
-        mSaturationSeekBar.setOnSeekBarChangeListener(this);
-        mSaturationSeekBar.setProgress(50);
+        mTestSpinner = (Spinner) findViewById(R.id.filterselection);
+        mTestSpinner.setOnItemSelectedListener(mTestSpinnerListener);
 
         mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
         mBenchmarkResult.setText("Result: not run");
+
+        setupTests();
+        changeTest(0);
     }
 
-    public void surfaceCreated(SurfaceHolder holder) {
-        createScript();
-        mScript.invoke_filter();
-        mOutPixelsAllocation.copyTo(mBitmapOut);
-    }
-
-    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
-    }
-
-    public void surfaceDestroyed(SurfaceHolder holder) {
-    }
-
-    private void createScript() {
-        mRS = RenderScript.create(this);
-        mRS.setMessageHandler(new FilterCallback());
-
-        mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
-                                                          Allocation.MipmapControl.MIPMAP_NONE,
-                                                          Allocation.USAGE_SCRIPT);
-        mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut,
-                                                           Allocation.MipmapControl.MIPMAP_NONE,
-                                                           Allocation.USAGE_SCRIPT);
-
-        Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
-        tb.setX(mBitmapIn.getWidth());
-        tb.setY(mBitmapIn.getHeight());
-        mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
-        mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
-
-        mScriptVBlur = new ScriptC_vertical_blur(mRS, getResources(), R.raw.vertical_blur);
-        mScriptHBlur = new ScriptC_horizontal_blur(mRS, getResources(), R.raw.horizontal_blur);
-
-        mScript = new ScriptC_threshold(mRS, getResources(), R.raw.threshold);
-        mScript.set_width(mBitmapIn.getWidth());
-        mScript.set_height(mBitmapIn.getHeight());
-        mScript.set_radius(mRadius);
-
-        mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite);
-        mScriptVBlur.invoke_setGamma(mGamma);
-        mScriptVBlur.invoke_setSaturation(mSaturation);
-
-        mScript.bind_InPixel(mInPixelsAllocation);
-        mScript.bind_OutPixel(mOutPixelsAllocation);
-        mScript.bind_ScratchPixel1(mScratchPixelsAllocation1);
-        mScript.bind_ScratchPixel2(mScratchPixelsAllocation2);
-
-        mScript.set_vBlurScript(mScriptVBlur);
-        mScript.set_hBlurScript(mScriptHBlur);
-    }
 
     private Bitmap loadBitmap(int resource) {
         final BitmapFactory.Options options = new BitmapFactory.Options();
@@ -270,34 +350,69 @@
 
     // button hook
     public void benchmark(View v) {
-        long t = getBenchmark();
+        float t = getBenchmark();
         //long javaTime = javaFilter();
         //mBenchmarkResult.setText("RS: " + t + " ms  Java: " + javaTime + " ms");
         mBenchmarkResult.setText("Result: " + t + " ms");
+        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
+    }
+
+    public void benchmark_all(View v) {
+        // write result into a file
+        File externalStorage = Environment.getExternalStorageDirectory();
+        if (!externalStorage.canWrite()) {
+            Log.v(TAG, "sdcard is not writable");
+            return;
+        }
+        File resultFile = new File(externalStorage, RESULT_FILE);
+        resultFile.setWritable(true, false);
+        try {
+            BufferedWriter rsWriter = new BufferedWriter(new FileWriter(resultFile));
+            Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath());
+            for (int i = 0; i < mTestNames.length; i++ ) {
+                changeTest(i);
+                float t = getBenchmark();
+                String s = new String("" + mTestNames[i] + ", " + t);
+                rsWriter.write(s + "\n");
+                Log.v(TAG, "Test " + s + "ms\n");
+            }
+            rsWriter.close();
+        } catch (IOException e) {
+            Log.v(TAG, "Unable to write result file " + e.getMessage());
+        }
+        changeTest(0);
     }
 
     // For benchmark test
-    public long getBenchmark() {
-        Log.v(TAG, "Benchmarking");
-        int oldRadius = mRadius;
-        mRadius = MAX_RADIUS;
-        mScript.set_radius(mRadius);
+    public float getBenchmark() {
+        mDoingBenchmark = true;
 
-        mScript.invoke_filter();
-        mRS.finish();
+        mTest.setupBenchmark();
+        long result = 0;
 
-        long t = java.lang.System.currentTimeMillis();
+        //Log.v(TAG, "Warming");
+        long t = java.lang.System.currentTimeMillis() + 250;
+        do {
+            mTest.runTest();
+            mTest.finish();
+        } while (t > java.lang.System.currentTimeMillis());
 
-        mScript.invoke_filter();
-        mOutPixelsAllocation.copyTo(mBitmapOut);
 
+        //Log.v(TAG, "Benchmarking");
+        int ct = 0;
+        t = java.lang.System.currentTimeMillis();
+        do {
+            mTest.runTest();
+            mTest.finish();
+            ct++;
+        } while ((t+1000) > java.lang.System.currentTimeMillis());
         t = java.lang.System.currentTimeMillis() - t;
-        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
-        mRadius = oldRadius;
-        mScript.set_radius(mRadius);
+        float ft = (float)t;
+        ft /= ct;
 
-        mScript.invoke_filter();
-        mOutPixelsAllocation.copyTo(mBitmapOut);
-        return t;
+        mTest.exitBenchmark();
+        mDoingBenchmark = false;
+
+        return ft;
     }
 }
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingTest.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingTest.java
index 912d863..f995437 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingTest.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingTest.java
@@ -78,7 +78,7 @@
             BufferedWriter rsWriter = new BufferedWriter(new FileWriter(resultFile));
             Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath());
             for (int i = 0; i < ITERATION; i++ ) {
-                t = mAct.getBenchmark();
+                t = (long)mAct.getBenchmark();
                 sum += t;
                 rsWriter.write("Renderscript frame time core: " + t + " ms\n");
                 Log.v(TAG, "RenderScript framew time core: " + t + " ms");
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/LevelsV4.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/LevelsV4.java
new file mode 100644
index 0000000..9eb5647
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/LevelsV4.java
@@ -0,0 +1,167 @@
+/*
+ * 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.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Matrix3f;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+
+public class LevelsV4 extends TestBase {
+    private ScriptC_levels_relaxed mScriptR;
+    private ScriptC_levels_full mScriptF;
+    private float mInBlack = 0.0f;
+    private float mOutBlack = 0.0f;
+    private float mInWhite = 255.0f;
+    private float mOutWhite = 255.0f;
+    private float mSaturation = 1.0f;
+
+    Matrix3f satMatrix = new Matrix3f();
+    float mInWMinInB;
+    float mOutWMinOutB;
+    float mOverInWMinInB;
+
+    boolean mUseFull;
+    boolean mUseV4;
+
+    LevelsV4(boolean useFull, boolean useV4) {
+        mUseFull = useFull;
+        mUseV4 = useV4;
+    }
+
+
+    private void setLevels() {
+        mInWMinInB = mInWhite - mInBlack;
+        mOutWMinOutB = mOutWhite - mOutBlack;
+        mOverInWMinInB = 1.f / mInWMinInB;
+
+        mScriptR.set_inBlack(mInBlack);
+        mScriptR.set_outBlack(mOutBlack);
+        mScriptR.set_inWMinInB(mInWMinInB);
+        mScriptR.set_outWMinOutB(mOutWMinOutB);
+        mScriptR.set_overInWMinInB(mOverInWMinInB);
+        mScriptF.set_inBlack(mInBlack);
+        mScriptF.set_outBlack(mOutBlack);
+        mScriptF.set_inWMinInB(mInWMinInB);
+        mScriptF.set_outWMinOutB(mOutWMinOutB);
+        mScriptF.set_overInWMinInB(mOverInWMinInB);
+    }
+
+    private void setSaturation() {
+        float rWeight = 0.299f;
+        float gWeight = 0.587f;
+        float bWeight = 0.114f;
+        float oneMinusS = 1.0f - mSaturation;
+
+        satMatrix.set(0, 0, oneMinusS * rWeight + mSaturation);
+        satMatrix.set(0, 1, oneMinusS * rWeight);
+        satMatrix.set(0, 2, oneMinusS * rWeight);
+        satMatrix.set(1, 0, oneMinusS * gWeight);
+        satMatrix.set(1, 1, oneMinusS * gWeight + mSaturation);
+        satMatrix.set(1, 2, oneMinusS * gWeight);
+        satMatrix.set(2, 0, oneMinusS * bWeight);
+        satMatrix.set(2, 1, oneMinusS * bWeight);
+        satMatrix.set(2, 2, oneMinusS * bWeight + mSaturation);
+        mScriptR.set_colorMat(satMatrix);
+        mScriptF.set_colorMat(satMatrix);
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        b.setProgress(50);
+        t.setText("Saturation");
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(0);
+        t.setText("In Black");
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(0);
+        t.setText("Out Black");
+        return true;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(128);
+        t.setText("Out White");
+        return true;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(128);
+        t.setText("Out White");
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        mSaturation = (float)progress / 50.0f;
+        setSaturation();
+    }
+    public void onBar2Changed(int progress) {
+        mInBlack = (float)progress;
+        setLevels();
+    }
+    public void onBar3Changed(int progress) {
+        mOutBlack = (float)progress;
+        setLevels();
+    }
+    public void onBar4Changed(int progress) {
+        mInWhite = (float)progress + 127.0f;
+        setLevels();
+    }
+    public void onBar5Changed(int progress) {
+        mOutWhite = (float)progress + 127.0f;
+        setLevels();
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mScriptR = new ScriptC_levels_relaxed(mRS, res, R.raw.levels_relaxed);
+        mScriptF = new ScriptC_levels_full(mRS, res, R.raw.levels_full);
+        setSaturation();
+        setLevels();
+    }
+
+    public void runTest() {
+        if (mUseFull) {
+            if (mUseV4) {
+                mScriptF.forEach_root4(mInPixelsAllocation, mOutPixelsAllocation);
+            } else {
+                mScriptF.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+            }
+        } else {
+            if (mUseV4) {
+                mScriptR.forEach_root4(mInPixelsAllocation, mOutPixelsAllocation);
+            } else {
+                mScriptR.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+            }
+        }
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Mandelbrot.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Mandelbrot.java
new file mode 100644
index 0000000..20036e6
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Mandelbrot.java
@@ -0,0 +1,98 @@
+/*
+ * 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.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Mandelbrot extends TestBase {
+    private ScriptC_mandelbrot mScript;
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Iterations");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        int iters = progress * 3 + 50;
+        mScript.set_gMaxIteration(iters);
+    }
+
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Lower Bound: X");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar2Changed(int progress) {
+        float scaleFactor = mScript.get_scaleFactor();
+        // allow viewport to be moved by 2x scale factor
+        float lowerBoundX = -2.f + ((progress / scaleFactor) / 50.f);
+        mScript.set_lowerBoundX(lowerBoundX);
+    }
+
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Lower Bound: Y");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar3Changed(int progress) {
+        float scaleFactor = mScript.get_scaleFactor();
+        // allow viewport to be moved by 2x scale factor
+        float lowerBoundY = -2.f + ((progress / scaleFactor) / 50.f);
+        mScript.set_lowerBoundY(lowerBoundY);
+    }
+
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        t.setText("Scale Factor");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar4Changed(int progress) {
+        float scaleFactor = 4.f - (3.96f * (progress / 100.f));
+        mScript.set_scaleFactor(scaleFactor);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mOutPixelsAllocation.getType().getX();
+        int height = mOutPixelsAllocation.getType().getY();
+
+        mScript = new ScriptC_mandelbrot(mRS, res, R.raw.mandelbrot);
+        mScript.set_gDimX(width);
+        mScript.set_gDimY(height);
+        mScript.set_gMaxIteration(50);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mOutPixelsAllocation);
+        mRS.finish();
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/TestBase.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/TestBase.java
new file mode 100644
index 0000000..bb3f2f3
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/TestBase.java
@@ -0,0 +1,140 @@
+/*
+ * 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.rs.image;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.renderscript.ScriptC;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Script;
+import android.view.SurfaceView;
+import android.view.SurfaceHolder;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.view.View;
+import android.util.Log;
+import java.lang.Math;
+import android.widget.Spinner;
+
+public class TestBase  {
+    protected final String TAG = "Img";
+
+    protected RenderScript mRS;
+    protected Allocation mInPixelsAllocation;
+    protected Allocation mInPixelsAllocation2;
+    protected Allocation mOutPixelsAllocation;
+
+    protected ImageProcessingActivity act;
+
+    // Override to use UI elements
+    public void onBar1Changed(int progress) {
+    }
+    public void onBar2Changed(int progress) {
+    }
+    public void onBar3Changed(int progress) {
+    }
+    public void onBar4Changed(int progress) {
+    }
+    public void onBar5Changed(int progress) {
+    }
+
+    // Override to use UI elements
+    // Unused bars will be hidden.
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+
+    public boolean onSpinner1Setup(Spinner s) {
+        s.setVisibility(View.INVISIBLE);
+        return false;
+    }
+
+    public final void createBaseTest(ImageProcessingActivity ipact, Bitmap b, Bitmap b2) {
+        act = ipact;
+        mRS = RenderScript.create(act);
+        mInPixelsAllocation = Allocation.createFromBitmap(mRS, b,
+                                                          Allocation.MipmapControl.MIPMAP_NONE,
+                                                          Allocation.USAGE_SCRIPT);
+        mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, b2,
+                                                          Allocation.MipmapControl.MIPMAP_NONE,
+                                                          Allocation.USAGE_SCRIPT);
+        mOutPixelsAllocation = Allocation.createFromBitmap(mRS, b,
+                                                           Allocation.MipmapControl.MIPMAP_NONE,
+                                                           Allocation.USAGE_SCRIPT);
+        createTest(act.getResources());
+    }
+
+    // Must override
+    public void createTest(android.content.res.Resources res) {
+        android.util.Log.e("img", "implement createTest");
+    }
+
+    // Must override
+    public void runTest() {
+    }
+
+    public void finish() {
+        mRS.finish();
+    }
+
+    public void destroy() {
+        mRS.destroy();
+        mRS = null;
+    }
+
+    public void updateBitmap(Bitmap b) {
+        mOutPixelsAllocation.copyTo(b);
+    }
+
+    // Override to configure specific benchmark config.
+    public void setupBenchmark() {
+    }
+
+    // Override to reset after benchmark.
+    public void exitBenchmark() {
+    }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Vignette.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Vignette.java
new file mode 100644
index 0000000..18d1103
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Vignette.java
@@ -0,0 +1,154 @@
+/*
+ * 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.rs.image;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Sampler;
+import android.renderscript.Type;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Vignette extends TestBase {
+    private ScriptC_vignette_full mScript_full = null;
+    private ScriptC_vignette_relaxed mScript_relaxed = null;
+    private ScriptC_vignette_approx_full mScript_approx_full = null;
+    private ScriptC_vignette_approx_relaxed mScript_approx_relaxed = null;
+    private final boolean approx;
+    private final boolean relaxed;
+    private float center_x = 0.5f;
+    private float center_y = 0.5f;
+    private float scale = 0.5f;
+    private float shade = 0.5f;
+    private float slope = 20.0f;
+
+    public Vignette(boolean approx, boolean relaxed) {
+        this.approx = approx;
+        this.relaxed = relaxed;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Scale");
+        b.setMax(100);
+        b.setProgress(25);
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Shade");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Slope");
+        b.setMax(100);
+        b.setProgress(20);
+        return true;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        t.setText("Shift center X");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        t.setText("Shift center Y");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        scale = progress / 50.0f;
+        do_init();
+    }
+    public void onBar2Changed(int progress) {
+        shade = progress / 100.0f;
+        do_init();
+    }
+    public void onBar3Changed(int progress) {
+        slope = (float)progress;
+        do_init();
+    }
+    public void onBar4Changed(int progress) {
+        center_x = progress / 100.0f;
+        do_init();
+    }
+    public void onBar5Changed(int progress) {
+        center_y = progress / 100.0f;
+        do_init();
+    }
+
+    private void do_init() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.invoke_init_vignette(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale, shade, slope);
+            else
+                mScript_approx_full.invoke_init_vignette(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale, shade, slope);
+        } else if (relaxed)
+            mScript_relaxed.invoke_init_vignette(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale, shade, slope);
+        else
+            mScript_full.invoke_init_vignette(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale, shade, slope);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed = new ScriptC_vignette_approx_relaxed(
+                        mRS, res, R.raw.vignette_approx_relaxed);
+            else
+                mScript_approx_full = new ScriptC_vignette_approx_full(
+                        mRS, res, R.raw.vignette_approx_full);
+        } else if (relaxed)
+            mScript_relaxed = new ScriptC_vignette_relaxed(mRS, res,
+                    R.raw.vignette_relaxed);
+        else
+            mScript_full = new ScriptC_vignette_full(mRS, res,
+                    R.raw.vignette_full);
+        do_init();
+    }
+
+    public void runTest() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.forEach_root(mInPixelsAllocation,
+                        mOutPixelsAllocation);
+            else
+                mScript_approx_full.forEach_root(mInPixelsAllocation,
+                        mOutPixelsAllocation);
+        } else if (relaxed)
+            mScript_relaxed.forEach_root(mInPixelsAllocation,
+                    mOutPixelsAllocation);
+        else
+            mScript_full.forEach_root(mInPixelsAllocation,
+                    mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/blend.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/blend.rs
new file mode 100644
index 0000000..87b56f77
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/blend.rs
@@ -0,0 +1,24 @@
+// 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.
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+
+uchar alpha = 0x0;
+
+void setImageAlpha(uchar4 *v_out, uint32_t x, uint32_t y) {
+  v_out->rgba = convert_uchar4((convert_uint4(v_out->rgba) * alpha) >> (uint4)8);
+  v_out->a = alpha;
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/colormatrix.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/colormatrix.fs
new file mode 100644
index 0000000..ba8711b
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/colormatrix.fs
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
+
+
+static rs_matrix4x4 Mat;
+
+void init() {
+    rsMatrixLoadIdentity(&Mat);
+}
+
+void setMatrix(rs_matrix4x4 m) {
+    Mat = m;
+}
+
+uchar4 __attribute__((kernel)) root(uchar4 in) {
+    float4 f = convert_float4(in);
+    f = rsMatrixMultiply(&Mat, f);
+    f = clamp(f, 0.f, 255.f);
+    return convert_uchar4(f);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve3x3.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve3x3.fs
new file mode 100644
index 0000000..772503f
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve3x3.fs
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[9];
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+    uint32_t x1 = min((int32_t)x+1, gWidth-1);
+    uint32_t x2 = max((int32_t)x-1, 0);
+    uint32_t y1 = min((int32_t)y+1, gHeight-1);
+    uint32_t y2 = max((int32_t)y-1, 0);
+
+    float4 p00 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y1));
+    float4 p01 = convert_float4(rsGetElementAt_uchar4(gIn, x, y1));
+    float4 p02 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y1));
+    float4 p10 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y));
+    float4 p11 = convert_float4(rsGetElementAt_uchar4(gIn, x, y));
+    float4 p12 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y));
+    float4 p20 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y2));
+    float4 p21 = convert_float4(rsGetElementAt_uchar4(gIn, x, y2));
+    float4 p22 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y2));
+    p00 *= gCoeffs[0];
+    p01 *= gCoeffs[1];
+    p02 *= gCoeffs[2];
+    p10 *= gCoeffs[3];
+    p11 *= gCoeffs[4];
+    p12 *= gCoeffs[5];
+    p20 *= gCoeffs[6];
+    p21 *= gCoeffs[7];
+    p22 *= gCoeffs[8];
+
+    p00 += p01;
+    p02 += p10;
+    p11 += p12;
+    p20 += p21;
+
+    p22 += p00;
+    p02 += p11;
+
+    p20 += p22;
+    p20 += p02;
+
+    p20 = clamp(p20, 0.f, 255.f);
+    return convert_uchar4(p20);
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve5x5.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve5x5.fs
new file mode 100644
index 0000000..a916bfb
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve5x5.fs
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[25];
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+    uint32_t x0 = max((int32_t)x-2, 0);
+    uint32_t x1 = max((int32_t)x-1, 0);
+    uint32_t x2 = x;
+    uint32_t x3 = min((int32_t)x+1, gWidth-1);
+    uint32_t x4 = min((int32_t)x+2, gWidth-1);
+
+    uint32_t y0 = max((int32_t)y-2, 0);
+    uint32_t y1 = max((int32_t)y-1, 0);
+    uint32_t y2 = y;
+    uint32_t y3 = min((int32_t)y+1, gHeight-1);
+    uint32_t y4 = min((int32_t)y+2, gHeight-1);
+
+    float4 p0 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y0)) * gCoeffs[0]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y0)) * gCoeffs[1]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y0)) * gCoeffs[2]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y0)) * gCoeffs[3]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y0)) * gCoeffs[4];
+
+    float4 p1 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y1)) * gCoeffs[5]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y1)) * gCoeffs[6]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y1)) * gCoeffs[7]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y1)) * gCoeffs[8]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y1)) * gCoeffs[9];
+
+    float4 p2 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y2)) * gCoeffs[10]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y2)) * gCoeffs[11]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y2)) * gCoeffs[12]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y2)) * gCoeffs[13]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y2)) * gCoeffs[14];
+
+    float4 p3 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y3)) * gCoeffs[15]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y3)) * gCoeffs[16]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y3)) * gCoeffs[17]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y3)) * gCoeffs[18]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y3)) * gCoeffs[19];
+
+    float4 p4 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y4)) * gCoeffs[20]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y4)) * gCoeffs[21]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y4)) * gCoeffs[22]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y4)) * gCoeffs[23]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y4)) * gCoeffs[24];
+
+    p0 = clamp(p0 + p1 + p2 + p3 + p4, 0.f, 255.f);
+    return convert_uchar4(p0);
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/copy.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/copy.fs
new file mode 100644
index 0000000..5f03483
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/copy.fs
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+
+uchar4 __attribute__((kernel)) root(uchar4 v_in) {
+    return v_in;
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye.rsh b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye.rsh
new file mode 100644
index 0000000..2eacb7d
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye.rsh
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+rs_allocation in_alloc;
+rs_sampler sampler;
+
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
+
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+    center.x = center_x;
+    center.y = center_y;
+    neg_center = -center;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+    alpha = k * 2.0f + 0.75f;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+    
+    const float bound2 = 0.25f * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+    const float bound = sqrt(bound2);
+    const float radius = 1.15f * bound;
+    radius2 = radius*radius;
+    const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
+    factor = bound / max_radian;
+}
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float2 scaledCoord = axis_scale * coord;
+    const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+    const float inv_dist = rsqrt(dist2);
+    const float radian = M_PI_2 - atan((alpha * sqrt(radius2 - dist2)) * inv_dist);
+    const float scalar = radian * factor * inv_dist;
+    const float2 new_coord = mad(coord, scalar, center);
+    const float4 fout = rsSample(in_alloc, sampler, new_coord);
+    return rsPackColorTo8888(fout);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx.rsh b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx.rsh
new file mode 100644
index 0000000..fcf0a3d
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx.rsh
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+rs_allocation in_alloc;
+rs_sampler sampler;
+
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
+
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+    center.x = center_x;
+    center.y = center_y;
+    neg_center = -center;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+    alpha = k * 2.0f + 0.75f;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float bound2 = 0.25f * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+    const float bound = sqrt(bound2);
+    const float radius = 1.15f * bound;
+    radius2 = radius*radius;
+    const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
+    factor = bound / max_radian;
+}
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float2 scaledCoord = axis_scale * coord;
+    const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+    const float inv_dist = half_rsqrt(dist2);
+    const float radian = M_PI_2 - atan((alpha * half_sqrt(radius2 - dist2)) * inv_dist);
+    const float scalar = radian * factor * inv_dist;
+    const float2 new_coord = mad(coord, scalar, center);
+    const float4 fout = rsSample(in_alloc, sampler, new_coord);
+    return rsPackColorTo8888(fout);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs
new file mode 100644
index 0000000..1ea37db
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+
+#include "fisheye_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.fs
new file mode 100644
index 0000000..3e76368
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.fs
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
+
+#include "fisheye_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_full.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_full.rs
new file mode 100644
index 0000000..20f27e2
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_full.rs
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+
+#include "fisheye.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.fs
new file mode 100644
index 0000000..dc3ffcb
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.fs
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
+
+#include "fisheye.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.fs
new file mode 100644
index 0000000..4ae095d
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.fs
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
+
+uchar __attribute__((kernel)) genRand() {
+    return (uchar)rsRand(0xff);
+}
+
+/*
+ * Convolution matrix of distance 2 with fixed point of 'kShiftBits' bits
+ * shifted. Thus the sum of this matrix should be 'kShiftValue'. Entries of
+ * small values are not calculated to gain efficiency.
+ * The order ot pixels represented in this matrix is:
+ *  1  2  3
+ *  4  0  5
+ *  6  7  8
+ *  and the matrix should be: {230, 56, 114, 56, 114, 114, 56, 114, 56}.
+ *  However, since most of the valus are identical, we only use the first three
+ *  entries and the entries corresponding to the pixels is:
+ *  1  2  1
+ *  2  0  2
+ *  1  2  1
+ */
+
+int32_t gWMask;
+int32_t gHMask;
+
+rs_allocation gBlendSource;
+uchar __attribute__((kernel)) blend9(uint32_t x, uint32_t y) {
+    uint32_t x1 = (x-1) & gWMask;
+    uint32_t x2 = (x+1) & gWMask;
+    uint32_t y1 = (y-1) & gHMask;
+    uint32_t y2 = (y+1) & gHMask;
+
+    uint p00 = 56 *  rsGetElementAt_uchar(gBlendSource, x1, y1);
+    uint p01 = 114 * rsGetElementAt_uchar(gBlendSource, x, y1);
+    uint p02 = 56 *  rsGetElementAt_uchar(gBlendSource, x2, y1);
+    uint p10 = 114 * rsGetElementAt_uchar(gBlendSource, x1, y);
+    uint p11 = 230 * rsGetElementAt_uchar(gBlendSource, x, y);
+    uint p12 = 114 * rsGetElementAt_uchar(gBlendSource, x2, y);
+    uint p20 = 56 *  rsGetElementAt_uchar(gBlendSource, x1, y2);
+    uint p21 = 114 * rsGetElementAt_uchar(gBlendSource, x, y2);
+    uint p22 = 56 *  rsGetElementAt_uchar(gBlendSource, x2, y2);
+
+    p00 += p01;
+    p02 += p10;
+    p11 += p12;
+    p20 += p21;
+
+    p22 += p00;
+    p02 += p11;
+
+    p20 += p22;
+    p20 += p02;
+
+    p20 = min(p20 >> 10, (uint)255);
+    return (uchar)p20;
+}
+
+float gNoiseStrength;
+
+rs_allocation gNoise;
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+    float4 ip = convert_float4(in);
+    float pnoise = (float) rsGetElementAt_uchar(gNoise, x & gWMask, y & gHMask);
+
+    float energy_level = ip.r + ip.g + ip.b;
+    float energy_mask = (28.f - sqrt(energy_level)) * 0.03571f;
+    pnoise = (pnoise - 128.f) * energy_mask;
+
+    ip += pnoise * gNoiseStrength;
+    ip = clamp(ip, 0.f, 255.f);
+
+    uchar4 p = convert_uchar4(ip);
+    p.a = 0xff;
+    return p;
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.fs
new file mode 100644
index 0000000..90ba058
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.fs
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
+
+const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
+
+uchar4 __attribute__((kernel)) root(uchar4 v_in) {
+    float4 f4 = rsUnpackColor8888(v_in);
+
+    float3 mono = dot(f4.rgb, gMonoMult);
+    return rsPackColorTo8888(mono);
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs
deleted file mode 100644
index ee83496..0000000
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#pragma version(1)
-#pragma rs_fp_relaxed
-
-#include "ip.rsh"
-
-void root(float4 *out, const void *usrData, uint32_t x, uint32_t y) {
-    const FilterStruct *fs = (const FilterStruct *)usrData;
-    float3 blurredPixel = 0;
-    const float *gPtr = fs->gaussian;
-    if ((x > fs->radius) && (x < (fs->width - fs->radius))) {
-        for (int r = -fs->radius; r <= fs->radius; r ++) {
-            const float4 *i = (const float4 *)rsGetElementAt(fs->ain, x + r, y);
-            blurredPixel += i->xyz * gPtr[0];
-            gPtr++;
-        }
-    } else {
-        for (int r = -fs->radius; r <= fs->radius; r ++) {
-            // Stepping left and right away from the pixel
-            int validX = rsClamp((int)x + r, (int)0, (int)(fs->width - 1));
-            const float4 *i = (const float4 *)rsGetElementAt(fs->ain, validX, y);
-            blurredPixel += i->xyz * gPtr[0];
-            gPtr++;
-        }
-    }
-
-    out->xyz = blurredPixel;
-}
-
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ip.rsh b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ip.rsh
deleted file mode 100644
index 1d7a719..0000000
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ip.rsh
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma rs java_package_name(com.android.rs.image)
-
-#define MAX_RADIUS 25
-
-typedef struct FilterStruct_s {
-    rs_allocation ain;
-
-    float *gaussian; //[MAX_RADIUS * 2 + 1];
-    int height;
-    int width;
-    int radius;
-
-} FilterStruct;
-
-
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels.rsh b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels.rsh
new file mode 100644
index 0000000..e289906
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels.rsh
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+float inBlack;
+float outBlack;
+float inWMinInB;
+float outWMinOutB;
+float overInWMinInB;
+rs_matrix3x3 colorMat;
+
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+    uchar4 out;
+    float3 pixel = convert_float4(in).rgb;
+    pixel = rsMatrixMultiply(&colorMat, pixel);
+    pixel = clamp(pixel, 0.f, 255.f);
+    pixel = (pixel - inBlack) * overInWMinInB;
+    pixel = pixel * outWMinOutB + outBlack;
+    pixel = clamp(pixel, 0.f, 255.f);
+    out.xyz = convert_uchar3(pixel);
+    out.w = 0xff;
+    return out;
+}
+
+uchar4 __attribute__((kernel)) root4(uchar4 in, uint32_t x, uint32_t y) {
+    float4 pixel = convert_float4(in);
+    pixel.rgb = rsMatrixMultiply(&colorMat, pixel.rgb);
+    pixel = clamp(pixel, 0.f, 255.f);
+    pixel = (pixel - inBlack) * overInWMinInB;
+    pixel = pixel * outWMinOutB + outBlack;
+    pixel = clamp(pixel, 0.f, 255.f);
+    return convert_uchar4(pixel);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_full.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_full.rs
new file mode 100644
index 0000000..da6a291
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_full.rs
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+
+#include "levels.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.fs
new file mode 100644
index 0000000..b115445
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.fs
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
+
+#include "levels.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/mandelbrot.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/mandelbrot.fs
new file mode 100644
index 0000000..ac2061b
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/mandelbrot.fs
@@ -0,0 +1,56 @@
+// 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.
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+
+uint32_t gMaxIteration = 500;
+uint32_t gDimX = 1024;
+uint32_t gDimY = 1024;
+
+float lowerBoundX = -2.f;
+float lowerBoundY = -2.f;
+float scaleFactor = 4.f;
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+  float2 p;
+  p.x = lowerBoundX + ((float)x / gDimX) * scaleFactor;
+  p.y = lowerBoundY + ((float)y / gDimY) * scaleFactor;
+
+  float2 t = 0;
+  float2 t2 = t * t;
+  int iter = 0;
+  while((t2.x + t2.y < 4.f) && (iter < gMaxIteration)) {
+    float xtemp = t2.x - t2.y + p.x;
+    t.y = 2 * t.x * t.y + p.y;
+    t.x = xtemp;
+    iter++;
+    t2 = t * t;
+  }
+
+  if(iter >= gMaxIteration) {
+    // write a non-transparent black pixel
+    return (uchar4){0, 0, 0, 0xff};
+  } else {
+    float mi3 = gMaxIteration / 3.f;
+    if (iter <= (gMaxIteration / 3))
+      return (uchar4){0xff * (iter / mi3), 0, 0, 0xff};
+    else if (iter <= (((gMaxIteration / 3) * 2)))
+      return (uchar4){0xff - (0xff * ((iter - mi3) / mi3)),
+                      (0xff * ((iter - mi3) / mi3)), 0, 0xff};
+    else
+      return (uchar4){0, 0xff - (0xff * ((iter - (mi3 * 2)) / mi3)),
+                      (0xff * ((iter - (mi3 * 2)) / mi3)), 0xff};
+  }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.fs
new file mode 100644
index 0000000..86e155a
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.fs
@@ -0,0 +1,104 @@
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
+
+
+int height;
+int width;
+static int radius;
+
+rs_allocation InPixel;
+rs_allocation ScratchPixel1;
+rs_allocation ScratchPixel2;
+
+const int MAX_RADIUS = 25;
+
+// Store our coefficients here
+static float gaussian[MAX_RADIUS * 2 + 1];
+
+void setRadius(int rad) {
+    radius = rad;
+    // Compute gaussian weights for the blur
+    // e is the euler's number
+    float e = 2.718281828459045f;
+    float pi = 3.1415926535897932f;
+    // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 )
+    // x is of the form [-radius .. 0 .. radius]
+    // and sigma varies with radius.
+    // Based on some experimental radius values and sigma's
+    // we approximately fit sigma = f(radius) as
+    // sigma = radius * 0.4  + 0.6
+    // The larger the radius gets, the more our gaussian blur
+    // will resemble a box blur since with large sigma
+    // the gaussian curve begins to lose its shape
+    float sigma = 0.4f * (float)radius + 0.6f;
+
+    // Now compute the coefficints
+    // We will store some redundant values to save some math during
+    // the blur calculations
+    // precompute some values
+    float coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma);
+    float coeff2 = - 1.0f / (2.0f * sigma * sigma);
+
+    float normalizeFactor = 0.0f;
+    float floatR = 0.0f;
+    for (int r = -radius; r <= radius; r ++) {
+        floatR = (float)r;
+        gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
+        normalizeFactor += gaussian[r + radius];
+    }
+
+    //Now we need to normalize the weights because all our coefficients need to add up to one
+    normalizeFactor = 1.0f / normalizeFactor;
+    for (int r = -radius; r <= radius; r ++) {
+        floatR = (float)r;
+        gaussian[r + radius] *= normalizeFactor;
+    }
+}
+
+float4 __attribute__((kernel)) copyIn(uchar4 in) {
+    return convert_float4(in);
+}
+
+uchar4 __attribute__((kernel)) vert(uint32_t x, uint32_t y) {
+    float3 blurredPixel = 0;
+    int gi = 0;
+    uchar4 out;
+    if ((y > radius) && (y < (height - radius))) {
+        for (int r = -radius; r <= radius; r ++) {
+            float4 i = rsGetElementAt_float4(ScratchPixel2, x, y + r);
+            blurredPixel += i.xyz * gaussian[gi++];
+        }
+    } else {
+        for (int r = -radius; r <= radius; r ++) {
+            int validH = rsClamp((int)y + r, (int)0, (int)(height - 1));
+            float4 i = rsGetElementAt_float4(ScratchPixel2, x, validH);
+            blurredPixel += i.xyz * gaussian[gi++];
+        }
+    }
+
+    out.xyz = convert_uchar3(clamp(blurredPixel, 0.f, 255.f));
+    out.w = 0xff;
+    return out;
+}
+
+float4 __attribute__((kernel)) horz(uint32_t x, uint32_t y) {
+    float4 blurredPixel = 0;
+    int gi = 0;
+    if ((x > radius) && (x < (width - radius))) {
+        for (int r = -radius; r <= radius; r ++) {
+            float4 i = rsGetElementAt_float4(ScratchPixel1, x + r, y);
+            blurredPixel += i * gaussian[gi++];
+        }
+    } else {
+        for (int r = -radius; r <= radius; r ++) {
+            // Stepping left and right away from the pixel
+            int validX = rsClamp((int)x + r, (int)0, (int)(width - 1));
+            float4 i = rsGetElementAt_float4(ScratchPixel1, validX, y);
+            blurredPixel += i * gaussian[gi++];
+        }
+    }
+
+    return blurredPixel;
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs
deleted file mode 100644
index d93238c..0000000
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs
+++ /dev/null
@@ -1,93 +0,0 @@
-#pragma version(1)
-
-#include "ip.rsh"
-
-int height;
-int width;
-int radius;
-
-uchar4 * InPixel;
-uchar4 * OutPixel;
-float4 * ScratchPixel1;
-float4 * ScratchPixel2;
-
-rs_script vBlurScript;
-rs_script hBlurScript;
-
-const int CMD_FINISHED = 1;
-
-// Store our coefficients here
-static float gaussian[MAX_RADIUS * 2 + 1];
-
-
-static void computeGaussianWeights() {
-    // Compute gaussian weights for the blur
-    // e is the euler's number
-    float e = 2.718281828459045f;
-    float pi = 3.1415926535897932f;
-    // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 )
-    // x is of the form [-radius .. 0 .. radius]
-    // and sigma varies with radius.
-    // Based on some experimental radius values and sigma's
-    // we approximately fit sigma = f(radius) as
-    // sigma = radius * 0.4  + 0.6
-    // The larger the radius gets, the more our gaussian blur
-    // will resemble a box blur since with large sigma
-    // the gaussian curve begins to lose its shape
-    float sigma = 0.4f * (float)radius + 0.6f;
-
-    // Now compute the coefficints
-    // We will store some redundant values to save some math during
-    // the blur calculations
-    // precompute some values
-    float coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma);
-    float coeff2 = - 1.0f / (2.0f * sigma * sigma);
-
-    float normalizeFactor = 0.0f;
-    float floatR = 0.0f;
-    int r;
-    for (r = -radius; r <= radius; r ++) {
-        floatR = (float)r;
-        gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
-        normalizeFactor += gaussian[r + radius];
-    }
-
-    //Now we need to normalize the weights because all our coefficients need to add up to one
-    normalizeFactor = 1.0f / normalizeFactor;
-    for (r = -radius; r <= radius; r ++) {
-        floatR = (float)r;
-        gaussian[r + radius] *= normalizeFactor;
-    }
-}
-
-
-static void copyInput() {
-    rs_allocation ain;
-    ain = rsGetAllocation(InPixel);
-    uint32_t dimx = rsAllocationGetDimX(ain);
-    uint32_t dimy = rsAllocationGetDimY(ain);
-    for (uint32_t y = 0; y < dimy; y++) {
-        for (uint32_t x = 0; x < dimx; x++) {
-            ScratchPixel1[x + y * dimx] = convert_float4(InPixel[x + y * dimx]);
-        }
-    }
-}
-
-void filter() {
-    copyInput();
-    computeGaussianWeights();
-
-    FilterStruct fs;
-    fs.gaussian = gaussian;
-    fs.width = width;
-    fs.height = height;
-    fs.radius = radius;
-
-    fs.ain = rsGetAllocation(ScratchPixel1);
-    rsForEach(hBlurScript, fs.ain, rsGetAllocation(ScratchPixel2), &fs, sizeof(fs));
-
-    fs.ain = rsGetAllocation(ScratchPixel2);
-    rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs, sizeof(fs));
-    rsSendToClientBlocking(CMD_FINISHED);
-}
-
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vertical_blur.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
deleted file mode 100644
index a6da192..0000000
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-#pragma version(1)
-#pragma rs_fp_relaxed
-
-#include "ip.rsh"
-
-static float inBlack;
-static float outBlack;
-static float inWhite;
-static float outWhite;
-static float3 gamma;
-static float saturation;
-
-static float inWMinInB;
-static float outWMinOutB;
-static float overInWMinInB;
-static rs_matrix3x3 colorMat;
-
-void setLevels(float iBlk, float oBlk, float iWht, float oWht) {
-    inBlack = iBlk;
-    outBlack = oBlk;
-    inWhite = iWht;
-    outWhite = oWht;
-
-    inWMinInB = inWhite - inBlack;
-    outWMinOutB = outWhite - outBlack;
-    overInWMinInB = 1.f / inWMinInB;
-}
-
-void setSaturation(float sat) {
-    saturation = sat;
-
-    // Saturation
-    // Linear weights
-    //float rWeight = 0.3086f;
-    //float gWeight = 0.6094f;
-    //float bWeight = 0.0820f;
-
-    // Gamma 2.2 weights (we haven't converted our image to linear space yet for perf reasons)
-    float rWeight = 0.299f;
-    float gWeight = 0.587f;
-    float bWeight = 0.114f;
-
-    float oneMinusS = 1.0f - saturation;
-    rsMatrixSet(&colorMat, 0, 0, oneMinusS * rWeight + saturation);
-    rsMatrixSet(&colorMat, 0, 1, oneMinusS * rWeight);
-    rsMatrixSet(&colorMat, 0, 2, oneMinusS * rWeight);
-    rsMatrixSet(&colorMat, 1, 0, oneMinusS * gWeight);
-    rsMatrixSet(&colorMat, 1, 1, oneMinusS * gWeight + saturation);
-    rsMatrixSet(&colorMat, 1, 2, oneMinusS * gWeight);
-    rsMatrixSet(&colorMat, 2, 0, oneMinusS * bWeight);
-    rsMatrixSet(&colorMat, 2, 1, oneMinusS * bWeight);
-    rsMatrixSet(&colorMat, 2, 2, oneMinusS * bWeight + saturation);
-}
-
-void setGamma(float g) {
-    gamma = (float3)g;
-}
-
-void root(uchar4 *out, const void *usrData, uint32_t x, uint32_t y) {
-    const FilterStruct *fs = (const FilterStruct *)usrData;
-    float3 blurredPixel = 0;
-    const float *gPtr = fs->gaussian;
-    if ((y > fs->radius) && (y < (fs->height - fs->radius))) {
-        for (int r = -fs->radius; r <= fs->radius; r ++) {
-            const float4 *i = (const float4 *)rsGetElementAt(fs->ain, x, y + r);
-            blurredPixel += i->xyz * gPtr[0];
-            gPtr++;
-        }
-    } else {
-        for (int r = -fs->radius; r <= fs->radius; r ++) {
-            int validH = rsClamp((int)y + r, (int)0, (int)(fs->height - 1));
-            const float4 *i = (const float4 *)rsGetElementAt(fs->ain, x, validH);
-            blurredPixel += i->xyz * gPtr[0];
-            gPtr++;
-        }
-    }
-
-    float3 temp = rsMatrixMultiply(&colorMat, blurredPixel);
-    temp = (clamp(temp, 0.f, 255.f) - inBlack) * overInWMinInB;
-    if (gamma.x != 1.0f)
-        temp = pow(temp, (float3)gamma);
-    temp = clamp(temp * outWMinOutB + outBlack, 0.f, 255.f);
-
-    out->xyz = convert_uchar3(temp);
-    //output->w = input->w;
-}
-
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette.rsh b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette.rsh
new file mode 100644
index 0000000..04ca1f1
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette.rsh
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+static float2 neg_center, axis_scale, inv_dimensions;
+static float sloped_neg_range, sloped_inv_max_dist, shade, opp_shade;
+
+void init_vignette(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y,
+        float desired_scale, float desired_shade, float desired_slope) {
+
+    neg_center.x = -center_x;
+    neg_center.y = -center_y;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float max_dist = 0.5f * length(axis_scale);
+    sloped_inv_max_dist = desired_slope * 1.f/max_dist;
+
+    // Range needs to be between 1.3 to 0.6. When scale is zero then range is
+    // 1.3 which means no vignette at all because the luminousity difference is
+    // less than 1/256.  Expect input scale to be between 0.0 and 1.0.
+    const float neg_range = 0.7f*sqrt(desired_scale) - 1.3f;
+    sloped_neg_range = exp(neg_range * desired_slope);
+
+    shade = desired_shade;
+    opp_shade = 1.f - desired_shade;
+}
+
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float4 fin = convert_float4(in);
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float sloped_dist_ratio = length(axis_scale * coord)  * sloped_inv_max_dist;
+    const float lumen = opp_shade + shade / ( 1.0f + sloped_neg_range * exp(sloped_dist_ratio) );
+    float4 fout;
+    fout.rgb = fin.rgb * lumen;
+    fout.w = fin.w;
+    return convert_uchar4(fout);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx.rsh b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx.rsh
new file mode 100644
index 0000000..05a5929
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx.rsh
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+static float2 neg_center, axis_scale, inv_dimensions;
+static float sloped_neg_range, sloped_inv_max_dist, shade, opp_shade;
+
+void init_vignette(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y,
+        float desired_scale, float desired_shade, float desired_slope) {
+
+    neg_center.x = -center_x;
+    neg_center.y = -center_y;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float max_dist = 0.5f * length(axis_scale);
+    sloped_inv_max_dist = desired_slope * 1.f/max_dist;
+
+    // Range needs to be between 1.3 to 0.6. When scale is zero then range is
+    // 1.3 which means no vignette at all because the luminousity difference is
+    // less than 1/256.  Expect input scale to be between 0.0 and 1.0.
+    const float neg_range = 0.7f*sqrt(desired_scale) - 1.3f;
+    sloped_neg_range = exp(neg_range * desired_slope);
+
+    shade = desired_shade;
+    opp_shade = 1.f - desired_shade;
+}
+
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float4 fin = convert_float4(in);
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float sloped_dist_ratio = fast_length(axis_scale * coord)  * sloped_inv_max_dist;
+    // TODO:  add half_exp once implemented
+    const float lumen = opp_shade + shade * half_recip(1.f + sloped_neg_range * exp(sloped_dist_ratio));
+    float4 fout;
+    fout.rgb = fin.rgb * lumen;
+    fout.w = fin.w;
+    return convert_uchar4(fout);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rs
new file mode 100644
index 0000000..c83c6e1
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rs
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+
+#include "vignette_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.fs
new file mode 100644
index 0000000..9120612
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.fs
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
+
+#include "vignette_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_full.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_full.rs
new file mode 100644
index 0000000..64942d9
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_full.rs
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+
+#include "vignette.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_relaxed.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_relaxed.fs
new file mode 100644
index 0000000..8e47ea9
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_relaxed.fs
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
+
+#include "vignette.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/Android.mk b/tests/RenderScriptTests/ImageProcessing2/Android.mk
new file mode 100644
index 0000000..e05a518
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/Android.mk
@@ -0,0 +1,39 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+                   $(call all-renderscript-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := android.support.v8.renderscript
+
+LOCAL_PACKAGE_NAME := ImageProcessing2
+LOCAL_SDK_VERSION := 8
+LOCAL_RENDERSCRIPT_TARGET_API := 17
+LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE := $(TOPDIR)external/clang/lib/Headers \
+                                        $(TOPDIR)frameworks/rs/scriptc
+
+LOCAL_RENDERSCRIPT_FLAGS := -rs-package-name=android.support.v8.renderscript
+LOCAL_REQUIRED_MODULES := librsjni
+
+include $(BUILD_PACKAGE)
+
+#include $(call all-makefiles-under, $(LOCAL_PATH))
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/AndroidManifest.xml b/tests/RenderScriptTests/ImageProcessing2/AndroidManifest.xml
new file mode 100644
index 0000000..20ee053
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/AndroidManifest.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.image2">
+    <uses-sdk android:minSdkVersion="8" />
+    <application android:label="IP GB">
+        <activity android:name="ImageProcessingActivity2">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/city.png b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/city.png
similarity index 100%
rename from tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/city.png
rename to tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/city.png
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg
new file mode 100644
index 0000000..05d3ee2
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg
new file mode 100644
index 0000000..aed0781
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml b/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml
new file mode 100644
index 0000000..f0a2b92
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:orientation="vertical"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:id="@+id/toplevel">
+    <SurfaceView
+        android:id="@+id/surface"
+        android:layout_width="1dip"
+        android:layout_height="1dip" />
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="vertical"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent">
+            <ImageView
+                android:id="@+id/display"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="horizontal"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content">
+                    <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/benchmark"
+                        android:onClick="benchmark"/>
+                    <TextView
+                        android:id="@+id/benchmarkText"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/saturation"/>
+            </LinearLayout>
+            <Spinner
+                android:id="@+id/filterselection"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <Spinner
+                android:id="@+id/spinner1"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider1Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/saturation"/>
+             <SeekBar
+                android:id="@+id/slider1"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider2Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/gamma"/>
+            <SeekBar
+                android:id="@+id/slider2"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider3Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:textSize="8pt"
+                android:text="@string/out_white"/>
+            <SeekBar
+                android:id="@+id/slider3"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider4Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/slider4"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider5Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/slider5"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/benchmark_all"
+                    android:onClick="benchmark_all"/>
+            </LinearLayout>
+    </ScrollView>
+</LinearLayout>
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/layout/spinner_layout.xml b/tests/RenderScriptTests/ImageProcessing2/res/layout/spinner_layout.xml
new file mode 100644
index 0000000..8196bbf
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/res/layout/spinner_layout.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:padding="10dp"
+    android:textSize="16sp"
+/>
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/values/strings.xml b/tests/RenderScriptTests/ImageProcessing2/res/values/strings.xml
new file mode 100644
index 0000000..a7dd165
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/res/values/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- General -->
+    <skip />
+    <!--slider label -->
+    <string name="blur_description">Blur Radius</string>
+    <string name="in_white">In White</string>
+    <string name="out_white">Out White</string>
+    <string name="in_black">In Black</string>
+    <string name="out_black">Out Black</string>
+    <string name="gamma">Gamma</string>
+    <string name="saturation">Saturation</string>
+    <string name="benchmark">Benchmark</string>
+    <string name="benchmark_all">Benchmark All</string>
+
+</resources>
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blend.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blend.java
new file mode 100644
index 0000000..ac02101
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blend.java
@@ -0,0 +1,168 @@
+/*
+ * 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.rs.image2;
+
+import java.lang.Math;
+import java.lang.Short;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.view.View;
+import android.widget.Spinner;
+
+public class Blend extends TestBase {
+    private ScriptIntrinsicBlend mBlend;
+    private ScriptC_blend mBlendHelper;
+    private short image1Alpha = 128;
+    private short image2Alpha = 128;
+
+    String mIntrinsicNames[];
+
+    private Allocation image1;
+    private Allocation image2;
+    private int currentIntrinsic = 0;
+
+    private AdapterView.OnItemSelectedListener mIntrinsicSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                    currentIntrinsic = pos;
+                    runTest();
+                    act.updateDisplay();
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+            };
+
+    public void createTest(android.content.res.Resources res) {
+        mBlend = ScriptIntrinsicBlend.create(mRS, Element.U8_4(mRS));
+        mBlendHelper = new ScriptC_blend(mRS);
+        mBlendHelper.set_alpha((short)128);
+
+        image1 = Allocation.createTyped(mRS, mInPixelsAllocation.getType());
+        image2 = Allocation.createTyped(mRS, mInPixelsAllocation2.getType());
+
+        mIntrinsicNames = new String[14];
+        mIntrinsicNames[0] = "Source";
+        mIntrinsicNames[1] = "Destination";
+        mIntrinsicNames[2] = "Source Over";
+        mIntrinsicNames[3] = "Destination Over";
+        mIntrinsicNames[4] = "Source In";
+        mIntrinsicNames[5] = "Destination In";
+        mIntrinsicNames[6] = "Source Out";
+        mIntrinsicNames[7] = "Destination Out";
+        mIntrinsicNames[8] = "Source Atop";
+        mIntrinsicNames[9] = "Destination Atop";
+        mIntrinsicNames[10] = "XOR";
+        mIntrinsicNames[11] = "Add";
+        mIntrinsicNames[12] = "Subtract";
+        mIntrinsicNames[13] = "Multiply";
+    }
+
+    public boolean onSpinner1Setup(Spinner s) {
+        s.setAdapter(new ArrayAdapter<String>(
+            act, R.layout.spinner_layout, mIntrinsicNames));
+        s.setOnItemSelectedListener(mIntrinsicSpinnerListener);
+        return true;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Image 1 Alpha");
+        b.setMax(255);
+        b.setProgress(image1Alpha);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        image1Alpha = (short)progress;
+    }
+
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Image 2 Alpha");
+        b.setMax(255);
+        b.setProgress(image2Alpha);
+        return true;
+    }
+
+    public void onBar2Changed(int progress) {
+        image2Alpha = (short)progress;
+    }
+
+    public void runTest() {
+        image1.copy2DRangeFrom(0, 0, mInPixelsAllocation.getType().getX(), mInPixelsAllocation.getType().getY(), mInPixelsAllocation, 0, 0);
+        image2.copy2DRangeFrom(0, 0, mInPixelsAllocation2.getType().getX(), mInPixelsAllocation2.getType().getY(), mInPixelsAllocation2, 0, 0);
+
+        mBlendHelper.set_alpha(image1Alpha);
+        mBlendHelper.forEach_setImageAlpha(image1);
+
+        mBlendHelper.set_alpha(image2Alpha);
+        mBlendHelper.forEach_setImageAlpha(image2);
+
+        switch (currentIntrinsic) {
+        case 0:
+            mBlend.forEachSrc(image1, image2);
+            break;
+        case 1:
+            mBlend.forEachDst(image1, image2);
+            break;
+        case 2:
+            mBlend.forEachSrcOver(image1, image2);
+            break;
+        case 3:
+            mBlend.forEachDstOver(image1, image2);
+            break;
+        case 4:
+            mBlend.forEachSrcIn(image1, image2);
+            break;
+        case 5:
+            mBlend.forEachDstIn(image1, image2);
+            break;
+        case 6:
+            mBlend.forEachSrcOut(image1, image2);
+            break;
+        case 7:
+            mBlend.forEachDstOut(image1, image2);
+            break;
+        case 8:
+            mBlend.forEachSrcAtop(image1, image2);
+            break;
+        case 9:
+            mBlend.forEachDstAtop(image1, image2);
+            break;
+        case 10:
+            mBlend.forEachXor(image1, image2);
+            break;
+        case 11:
+            mBlend.forEachAdd(image1, image2);
+            break;
+        case 12:
+            mBlend.forEachSubtract(image1, image2);
+            break;
+        case 13:
+            mBlend.forEachMultiply(image1, image2);
+            break;
+        }
+
+        mOutPixelsAllocation.copy2DRangeFrom(0, 0, image2.getType().getX(), image2.getType().getY(), image2, 0, 0);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25.java
new file mode 100644
index 0000000..b518b02
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25.java
@@ -0,0 +1,114 @@
+/*
+ * 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.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Blur25 extends TestBase {
+    private boolean mUseIntrinsic = false;
+    private ScriptIntrinsicBlur mIntrinsic;
+
+    private int MAX_RADIUS = 25;
+    private ScriptC_threshold mScript;
+    private float mRadius = MAX_RADIUS;
+    private float mSaturation = 1.0f;
+    private Allocation mScratchPixelsAllocation1;
+    private Allocation mScratchPixelsAllocation2;
+
+
+    public Blur25(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Radius");
+        b.setProgress(100);
+        return true;
+    }
+
+
+    public void onBar1Changed(int progress) {
+        mRadius = ((float)progress) / 100.0f * MAX_RADIUS;
+        if (mRadius <= 0.10f) {
+            mRadius = 0.10f;
+        }
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(mRadius);
+        } else {
+            mScript.invoke_setRadius((int)mRadius);
+        }
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setRadius(MAX_RADIUS);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+
+            Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
+            tb.setX(width);
+            tb.setY(height);
+            mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+            mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+
+            mScript = new ScriptC_threshold(mRS, res, R.raw.threshold);
+            mScript.set_width(width);
+            mScript.set_height(height);
+            mScript.invoke_setRadius(MAX_RADIUS);
+
+            mScript.set_InPixel(mInPixelsAllocation);
+            mScript.set_ScratchPixel1(mScratchPixelsAllocation1);
+            mScript.set_ScratchPixel2(mScratchPixelsAllocation2);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_copyIn(mInPixelsAllocation, mScratchPixelsAllocation1);
+            mScript.forEach_horz(mScratchPixelsAllocation2);
+            mScript.forEach_vert(mOutPixelsAllocation);
+        }
+    }
+
+    public void setupBenchmark() {
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(MAX_RADIUS);
+        } else {
+            mScript.invoke_setRadius(MAX_RADIUS);
+        }
+    }
+
+    public void exitBenchmark() {
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(mRadius);
+        } else {
+            mScript.invoke_setRadius((int)mRadius);
+        }
+    }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java
new file mode 100644
index 0000000..3b0f86a
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java
@@ -0,0 +1,62 @@
+/*
+ * 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.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class ColorMatrix extends TestBase {
+    private ScriptC_colormatrix mScript;
+    private ScriptIntrinsicColorMatrix mIntrinsic;
+    private boolean mUseIntrinsic;
+    private boolean mUseGrey;
+
+    public ColorMatrix(boolean useIntrinsic, boolean useGrey) {
+        mUseIntrinsic = useIntrinsic;
+        mUseGrey = useGrey;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+            if (mUseGrey) {
+                mIntrinsic.setGreyscale();
+            } else {
+                mIntrinsic.setColorMatrix(m);
+            }
+        } else {
+            mScript = new ScriptC_colormatrix(mRS, res, R.raw.colormatrix);
+            mScript.invoke_setMatrix(m);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java
new file mode 100644
index 0000000..7635e13
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java
@@ -0,0 +1,66 @@
+/*
+ * 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.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class Convolve3x3 extends TestBase {
+    private ScriptC_convolve3x3 mScript;
+    private ScriptIntrinsicConvolve3x3 mIntrinsic;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseIntrinsic;
+
+    public Convolve3x3(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        float f[] = new float[9];
+        f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
+        f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
+        f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setCoefficients(f);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+            mScript = new ScriptC_convolve3x3(mRS, res, R.raw.convolve3x3);
+            mScript.set_gCoeffs(f);
+            mScript.set_gIn(mInPixelsAllocation);
+            mScript.set_gWidth(mWidth);
+            mScript.set_gHeight(mHeight);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java
new file mode 100644
index 0000000..d2da3c4
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java
@@ -0,0 +1,80 @@
+/*
+ * 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.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class Convolve5x5 extends TestBase {
+    private ScriptC_convolve5x5 mScript;
+    private ScriptIntrinsicConvolve5x5 mIntrinsic;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseIntrinsic;
+
+    public Convolve5x5(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        float f[] = new float[25];
+        //f[0] = 0.012f; f[1] = 0.025f; f[2] = 0.031f; f[3] = 0.025f; f[4] = 0.012f;
+        //f[5] = 0.025f; f[6] = 0.057f; f[7] = 0.075f; f[8] = 0.057f; f[9] = 0.025f;
+        //f[10]= 0.031f; f[11]= 0.075f; f[12]= 0.095f; f[13]= 0.075f; f[14]= 0.031f;
+        //f[15]= 0.025f; f[16]= 0.057f; f[17]= 0.075f; f[18]= 0.057f; f[19]= 0.025f;
+        //f[20]= 0.012f; f[21]= 0.025f; f[22]= 0.031f; f[23]= 0.025f; f[24]= 0.012f;
+
+        //f[0] = 1.f; f[1] = 2.f; f[2] = 0.f; f[3] = -2.f; f[4] = -1.f;
+        //f[5] = 4.f; f[6] = 8.f; f[7] = 0.f; f[8] = -8.f; f[9] = -4.f;
+        //f[10]= 6.f; f[11]=12.f; f[12]= 0.f; f[13]=-12.f; f[14]= -6.f;
+        //f[15]= 4.f; f[16]= 8.f; f[17]= 0.f; f[18]= -8.f; f[19]= -4.f;
+        //f[20]= 1.f; f[21]= 2.f; f[22]= 0.f; f[23]= -2.f; f[24]= -1.f;
+
+        f[0] = -1.f; f[1] = -3.f; f[2] = -4.f; f[3] = -3.f; f[4] = -1.f;
+        f[5] = -3.f; f[6] =  0.f; f[7] =  6.f; f[8] =  0.f; f[9] = -3.f;
+        f[10]= -4.f; f[11]=  6.f; f[12]= 20.f; f[13]=  6.f; f[14]= -4.f;
+        f[15]= -3.f; f[16]=  0.f; f[17]=  6.f; f[18]=  0.f; f[19]= -3.f;
+        f[20]= -1.f; f[21]= -3.f; f[22]= -4.f; f[23]= -3.f; f[24]= -1.f;
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicConvolve5x5.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setCoefficients(f);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+            mScript = new ScriptC_convolve5x5(mRS, res, R.raw.convolve5x5);
+            mScript.set_gCoeffs(f);
+            mScript.set_gIn(mInPixelsAllocation);
+            mScript.set_gWidth(mWidth);
+            mScript.set_gHeight(mHeight);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Copy.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Copy.java
new file mode 100644
index 0000000..ef71907
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Copy.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class Copy extends TestBase {
+    private ScriptC_copy mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_copy(mRS, res, R.raw.copy);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/CrossProcess.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/CrossProcess.java
new file mode 100644
index 0000000..96787d7
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/CrossProcess.java
@@ -0,0 +1,60 @@
+/*
+ * 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.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class CrossProcess extends TestBase {
+    private ScriptIntrinsicLUT mIntrinsic;
+
+    public void createTest(android.content.res.Resources res) {
+        mIntrinsic = ScriptIntrinsicLUT.create(mRS, Element.U8_4(mRS));
+        for (int ct=0; ct < 256; ct++) {
+            float f = ((float)ct) / 255.f;
+
+            float r = f;
+            if (r < 0.5f) {
+                r = 4.0f * r * r * r;
+            } else {
+                r = 1.0f - r;
+                r = 1.0f - (4.0f * r * r * r);
+            }
+            mIntrinsic.setRed(ct, (int)(r * 255.f + 0.5f));
+
+            float g = f;
+            if (g < 0.5f) {
+                g = 2.0f * g * g;
+            } else {
+                g = 1.0f - g;
+                g = 1.0f - (2.0f * g * g);
+            }
+            mIntrinsic.setGreen(ct, (int)(g * 255.f + 0.5f));
+
+            float b = f * 0.5f + 0.25f;
+            mIntrinsic.setBlue(ct, (int)(b * 255.f + 0.5f));
+        }
+
+    }
+
+    public void runTest() {
+        mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Fisheye.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
new file mode 100644
index 0000000..97beb88
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
@@ -0,0 +1,135 @@
+/*
+ * 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.rs.image2;
+
+import android.support.v8.renderscript.*;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Fisheye extends TestBase {
+    private ScriptC_fisheye_full mScript_full = null;
+    private ScriptC_fisheye_relaxed mScript_relaxed = null;
+    private ScriptC_fisheye_approx_full mScript_approx_full = null;
+    private ScriptC_fisheye_approx_relaxed mScript_approx_relaxed = null;
+    private final boolean approx;
+    private final boolean relaxed;
+    private float center_x = 0.5f;
+    private float center_y = 0.5f;
+    private float scale = 0.5f;
+
+    public Fisheye(boolean approx, boolean relaxed) {
+        this.approx = approx;
+        this.relaxed = relaxed;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Scale");
+        b.setMax(100);
+        b.setProgress(25);
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Shift center X");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Shift center Y");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        scale = progress / 50.0f;
+        do_init();
+    }
+    public void onBar2Changed(int progress) {
+        center_x = progress / 100.0f;
+        do_init();
+    }
+    public void onBar3Changed(int progress) {
+        center_y = progress / 100.0f;
+        do_init();
+    }
+
+    private void do_init() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.invoke_init_filter(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale);
+            else
+                mScript_approx_full.invoke_init_filter(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale);
+        } else if (relaxed)
+            mScript_relaxed.invoke_init_filter(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale);
+        else
+            mScript_full.invoke_init_filter(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        if (approx) {
+            if (relaxed) {
+                mScript_approx_relaxed = new ScriptC_fisheye_approx_relaxed(mRS,
+                        res, R.raw.fisheye_approx_relaxed);
+                mScript_approx_relaxed.set_in_alloc(mInPixelsAllocation);
+                mScript_approx_relaxed.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+            } else {
+                mScript_approx_full = new ScriptC_fisheye_approx_full(mRS, res,
+                        R.raw.fisheye_approx_full);
+                mScript_approx_full.set_in_alloc(mInPixelsAllocation);
+                mScript_approx_full.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+            }
+        } else if (relaxed) {
+            mScript_relaxed = new ScriptC_fisheye_relaxed(mRS, res,
+                    R.raw.fisheye_relaxed);
+            mScript_relaxed.set_in_alloc(mInPixelsAllocation);
+            mScript_relaxed.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+        } else {
+            mScript_full = new ScriptC_fisheye_full(mRS, res,
+                    R.raw.fisheye_full);
+            mScript_full.set_in_alloc(mInPixelsAllocation);
+            mScript_full.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+        }
+        do_init();
+    }
+
+    public void runTest() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.forEach_root(mOutPixelsAllocation);
+            else
+                mScript_approx_full.forEach_root(mOutPixelsAllocation);
+        } else if (relaxed)
+            mScript_relaxed.forEach_root(mOutPixelsAllocation);
+        else
+            mScript_full.forEach_root(mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Grain.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Grain.java
new file mode 100644
index 0000000..dfd3c32
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Grain.java
@@ -0,0 +1,89 @@
+/*
+ * 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.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Grain extends TestBase {
+    private ScriptC_grain mScript;
+    private Allocation mNoise;
+    private Allocation mNoise2;
+
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Strength");
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        float s = progress / 100.0f;
+        mScript.set_gNoiseStrength(s);
+    }
+
+    private int findHighBit(int v) {
+        int bit = 0;
+        while (v > 1) {
+            bit++;
+            v >>= 1;
+        }
+        return bit;
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        int noiseW = findHighBit(width);
+        int noiseH = findHighBit(height);
+        if (noiseW > 9) {
+            noiseW = 9;
+        }
+        if (noiseH > 9) {
+            noiseH = 9;
+        }
+        noiseW = 1 << noiseW;
+        noiseH = 1 << noiseH;
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
+        tb.setX(noiseW);
+        tb.setY(noiseH);
+        mNoise = Allocation.createTyped(mRS, tb.create());
+        mNoise2 = Allocation.createTyped(mRS, tb.create());
+
+        mScript = new ScriptC_grain(mRS, res, R.raw.grain);
+        mScript.set_gWMask(noiseW - 1);
+        mScript.set_gHMask(noiseH - 1);
+        mScript.set_gNoiseStrength(0.5f);
+        mScript.set_gBlendSource(mNoise);
+        mScript.set_gNoise(mNoise2);
+    }
+
+    public void runTest() {
+        mScript.forEach_genRand(mNoise);
+        mScript.forEach_blend9(mNoise2);
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Greyscale.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Greyscale.java
new file mode 100644
index 0000000..2d85ae7
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Greyscale.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class Greyscale extends TestBase {
+    private ScriptC_greyscale mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_greyscale(mRS, res, R.raw.greyscale);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/GroupTest.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/GroupTest.java
new file mode 100644
index 0000000..a7ceebe
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/GroupTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class GroupTest extends TestBase {
+    private ScriptIntrinsicConvolve3x3 mConvolve;
+    private ScriptIntrinsicColorMatrix mMatrix;
+
+    private Allocation mScratchPixelsAllocation1;
+    private ScriptGroup mGroup;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseNative;
+
+
+    public GroupTest(boolean useNative) {
+        mUseNative = useNative;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        mConvolve = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+        mMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+
+        float f[] = new float[9];
+        f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
+        f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
+        f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
+        mConvolve.setCoefficients(f);
+
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+        mMatrix.setColorMatrix(m);
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8_4(mRS));
+        tb.setX(mWidth);
+        tb.setY(mHeight);
+        Type connect = tb.create();
+
+        if (mUseNative) {
+            ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
+            b.addKernel(mConvolve.getKernelID());
+            b.addKernel(mMatrix.getKernelID());
+            b.addConnection(connect, mConvolve.getKernelID(), mMatrix.getKernelID());
+            mGroup = b.create();
+        } else {
+            mScratchPixelsAllocation1 = Allocation.createTyped(mRS, connect);
+        }
+    }
+
+    public void runTest() {
+        mConvolve.setInput(mInPixelsAllocation);
+        if (mUseNative) {
+            mGroup.setOutput(mMatrix.getKernelID(), mOutPixelsAllocation);
+            mGroup.execute();
+        } else {
+            mConvolve.forEach(mScratchPixelsAllocation1);
+            mMatrix.forEach(mScratchPixelsAllocation1, mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
new file mode 100644
index 0000000..227518f
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
@@ -0,0 +1,413 @@
+/*
+ * 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.rs.image2;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.support.v8.renderscript.*;
+import android.view.SurfaceView;
+import android.view.SurfaceHolder;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.view.View;
+import android.util.Log;
+import java.lang.Math;
+
+import android.os.Environment;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+public class ImageProcessingActivity2 extends Activity
+                                       implements SeekBar.OnSeekBarChangeListener {
+    private final String TAG = "Img";
+    private final String RESULT_FILE = "image_processing_result.csv";
+
+    Bitmap mBitmapIn;
+    Bitmap mBitmapIn2;
+    Bitmap mBitmapOut;
+    String mTestNames[];
+
+    private Spinner mSpinner;
+    private SeekBar mBar1;
+    private SeekBar mBar2;
+    private SeekBar mBar3;
+    private SeekBar mBar4;
+    private SeekBar mBar5;
+    private TextView mText1;
+    private TextView mText2;
+    private TextView mText3;
+    private TextView mText4;
+    private TextView mText5;
+
+    private float mSaturation = 1.0f;
+
+    private TextView mBenchmarkResult;
+    private Spinner mTestSpinner;
+
+    private SurfaceView mSurfaceView;
+    private ImageView mDisplayView;
+
+    private boolean mDoingBenchmark;
+
+    private TestBase mTest;
+
+    public void updateDisplay() {
+            mTest.updateBitmap(mBitmapOut);
+            mDisplayView.invalidate();
+    }
+
+    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+        if (fromUser) {
+
+            if (seekBar == mBar1) {
+                mTest.onBar1Changed(progress);
+            } else if (seekBar == mBar2) {
+                mTest.onBar2Changed(progress);
+            } else if (seekBar == mBar3) {
+                mTest.onBar3Changed(progress);
+            } else if (seekBar == mBar4) {
+                mTest.onBar4Changed(progress);
+            } else if (seekBar == mBar5) {
+                mTest.onBar5Changed(progress);
+            }
+
+            mTest.runTest();
+            updateDisplay();
+        }
+    }
+
+    public void onStartTrackingTouch(SeekBar seekBar) {
+    }
+
+    public void onStopTrackingTouch(SeekBar seekBar) {
+    }
+
+    void setupBars() {
+        mSpinner.setVisibility(View.VISIBLE);
+        mTest.onSpinner1Setup(mSpinner);
+
+        mBar1.setVisibility(View.VISIBLE);
+        mText1.setVisibility(View.VISIBLE);
+        mTest.onBar1Setup(mBar1, mText1);
+
+        mBar2.setVisibility(View.VISIBLE);
+        mText2.setVisibility(View.VISIBLE);
+        mTest.onBar2Setup(mBar2, mText2);
+
+        mBar3.setVisibility(View.VISIBLE);
+        mText3.setVisibility(View.VISIBLE);
+        mTest.onBar3Setup(mBar3, mText3);
+
+        mBar4.setVisibility(View.VISIBLE);
+        mText4.setVisibility(View.VISIBLE);
+        mTest.onBar4Setup(mBar4, mText4);
+
+        mBar5.setVisibility(View.VISIBLE);
+        mText5.setVisibility(View.VISIBLE);
+        mTest.onBar5Setup(mBar5, mText5);
+    }
+
+
+    void changeTest(int testID) {
+        if (mTest != null) {
+            mTest.destroy();
+        }
+        switch(testID) {
+        case 0:
+            mTest = new LevelsV4(false, false);
+            break;
+        case 1:
+            mTest = new LevelsV4(false, true);
+            break;
+        case 2:
+            mTest = new LevelsV4(true, false);
+            break;
+        case 3:
+            mTest = new LevelsV4(true, true);
+            break;
+        case 4:
+            mTest = new Blur25(false);
+            break;
+        case 5:
+            mTest = new Blur25(true);
+            break;
+        case 6:
+            mTest = new Greyscale();
+            break;
+        case 7:
+            mTest = new Grain();
+            break;
+        case 8:
+            mTest = new Fisheye(false, false);
+            break;
+        case 9:
+            mTest = new Fisheye(false, true);
+            break;
+        case 10:
+            mTest = new Fisheye(true, false);
+            break;
+        case 11:
+            mTest = new Fisheye(true, true);
+            break;
+        case 12:
+            mTest = new Vignette(false, false);
+            break;
+        case 13:
+            mTest = new Vignette(false, true);
+            break;
+        case 14:
+            mTest = new Vignette(true, false);
+            break;
+        case 15:
+            mTest = new Vignette(true, true);
+            break;
+        case 16:
+            mTest = new GroupTest(false);
+            break;
+        case 17:
+            mTest = new GroupTest(true);
+            break;
+        case 18:
+            mTest = new Convolve3x3(false);
+            break;
+        case 19:
+            mTest = new Convolve3x3(true);
+            break;
+        case 20:
+            mTest = new ColorMatrix(false, false);
+            break;
+        case 21:
+            mTest = new ColorMatrix(true, false);
+            break;
+        case 22:
+            mTest = new ColorMatrix(true, true);
+            break;
+        case 23:
+            mTest = new Copy();
+            break;
+        case 24:
+            mTest = new CrossProcess();
+            break;
+        case 25:
+            mTest = new Convolve5x5(false);
+            break;
+        case 26:
+            mTest = new Convolve5x5(true);
+            break;
+        case 27:
+            mTest = new Mandelbrot();
+            break;
+        case 28:
+            mTest = new Blend();
+            break;
+        }
+
+        mTest.createBaseTest(this, mBitmapIn, mBitmapIn2);
+        setupBars();
+
+        mTest.runTest();
+        updateDisplay();
+        mBenchmarkResult.setText("Result: not run");
+    }
+
+    void setupTests() {
+        mTestNames = new String[29];
+        mTestNames[0] = "Levels Vec3 Relaxed";
+        mTestNames[1] = "Levels Vec4 Relaxed";
+        mTestNames[2] = "Levels Vec3 Full";
+        mTestNames[3] = "Levels Vec4 Full";
+        mTestNames[4] = "Blur radius 25";
+        mTestNames[5] = "Intrinsic Blur radius 25";
+        mTestNames[6] = "Greyscale";
+        mTestNames[7] = "Grain";
+        mTestNames[8] = "Fisheye Full";
+        mTestNames[9] = "Fisheye Relaxed";
+        mTestNames[10] = "Fisheye Approximate Full";
+        mTestNames[11] = "Fisheye Approximate Relaxed";
+        mTestNames[12] = "Vignette Full";
+        mTestNames[13] = "Vignette Relaxed";
+        mTestNames[14] = "Vignette Approximate Full";
+        mTestNames[15] = "Vignette Approximate Relaxed";
+        mTestNames[16] = "Group Test (emulated)";
+        mTestNames[17] = "Group Test (native)";
+        mTestNames[18] = "Convolve 3x3";
+        mTestNames[19] = "Intrinsics Convolve 3x3";
+        mTestNames[20] = "ColorMatrix";
+        mTestNames[21] = "Intrinsics ColorMatrix";
+        mTestNames[22] = "Intrinsics ColorMatrix Grey";
+        mTestNames[23] = "Copy";
+        mTestNames[24] = "CrossProcess (using LUT)";
+        mTestNames[25] = "Convolve 5x5";
+        mTestNames[26] = "Intrinsics Convolve 5x5";
+        mTestNames[27] = "Mandelbrot";
+        mTestNames[28] = "Intrinsics Blend";
+
+        mTestSpinner.setAdapter(new ArrayAdapter<String>(
+            this, R.layout.spinner_layout, mTestNames));
+    }
+
+    private AdapterView.OnItemSelectedListener mTestSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                    changeTest(pos);
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+            };
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mBitmapIn = loadBitmap(R.drawable.img1600x1067);
+        mBitmapIn2 = loadBitmap(R.drawable.img1600x1067b);
+        mBitmapOut = loadBitmap(R.drawable.img1600x1067);
+
+        mSurfaceView = (SurfaceView) findViewById(R.id.surface);
+
+        mDisplayView = (ImageView) findViewById(R.id.display);
+        mDisplayView.setImageBitmap(mBitmapOut);
+
+        mSpinner = (Spinner) findViewById(R.id.spinner1);
+
+        mBar1 = (SeekBar) findViewById(R.id.slider1);
+        mBar2 = (SeekBar) findViewById(R.id.slider2);
+        mBar3 = (SeekBar) findViewById(R.id.slider3);
+        mBar4 = (SeekBar) findViewById(R.id.slider4);
+        mBar5 = (SeekBar) findViewById(R.id.slider5);
+
+        mBar1.setOnSeekBarChangeListener(this);
+        mBar2.setOnSeekBarChangeListener(this);
+        mBar3.setOnSeekBarChangeListener(this);
+        mBar4.setOnSeekBarChangeListener(this);
+        mBar5.setOnSeekBarChangeListener(this);
+
+        mText1 = (TextView) findViewById(R.id.slider1Text);
+        mText2 = (TextView) findViewById(R.id.slider2Text);
+        mText3 = (TextView) findViewById(R.id.slider3Text);
+        mText4 = (TextView) findViewById(R.id.slider4Text);
+        mText5 = (TextView) findViewById(R.id.slider5Text);
+
+        mTestSpinner = (Spinner) findViewById(R.id.filterselection);
+        mTestSpinner.setOnItemSelectedListener(mTestSpinnerListener);
+
+        mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
+        mBenchmarkResult.setText("Result: not run");
+
+        setupTests();
+        changeTest(0);
+    }
+
+
+    private Bitmap loadBitmap(int resource) {
+        final BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        return copyBitmap(BitmapFactory.decodeResource(getResources(), resource, options));
+    }
+
+    private static Bitmap copyBitmap(Bitmap source) {
+        Bitmap b = Bitmap.createBitmap(source.getWidth(), source.getHeight(), source.getConfig());
+        Canvas c = new Canvas(b);
+        c.drawBitmap(source, 0, 0, null);
+        source.recycle();
+        return b;
+    }
+
+    // button hook
+    public void benchmark(View v) {
+        float t = getBenchmark();
+        //long javaTime = javaFilter();
+        //mBenchmarkResult.setText("RS: " + t + " ms  Java: " + javaTime + " ms");
+        mBenchmarkResult.setText("Result: " + t + " ms");
+        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
+    }
+
+    public void benchmark_all(View v) {
+        // write result into a file
+        File externalStorage = Environment.getExternalStorageDirectory();
+        if (!externalStorage.canWrite()) {
+            Log.v(TAG, "sdcard is not writable");
+            return;
+        }
+        File resultFile = new File(externalStorage, RESULT_FILE);
+        //resultFile.setWritable(true, false);
+        try {
+            BufferedWriter rsWriter = new BufferedWriter(new FileWriter(resultFile));
+            Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath());
+            for (int i = 0; i < mTestNames.length; i++ ) {
+                changeTest(i);
+                float t = getBenchmark();
+                String s = new String("" + mTestNames[i] + ", " + t);
+                rsWriter.write(s + "\n");
+                Log.v(TAG, "Test " + s + "ms\n");
+            }
+            rsWriter.close();
+        } catch (IOException e) {
+            Log.v(TAG, "Unable to write result file " + e.getMessage());
+        }
+        changeTest(0);
+    }
+
+    // For benchmark test
+    public float getBenchmark() {
+        mDoingBenchmark = true;
+
+        mTest.setupBenchmark();
+        long result = 0;
+
+        //Log.v(TAG, "Warming");
+        long t = java.lang.System.currentTimeMillis() + 250;
+        do {
+            mTest.runTest();
+            mTest.finish();
+        } while (t > java.lang.System.currentTimeMillis());
+
+
+        //Log.v(TAG, "Benchmarking");
+        int ct = 0;
+        t = java.lang.System.currentTimeMillis();
+        do {
+            mTest.runTest();
+            mTest.finish();
+            ct++;
+        } while ((t+1000) > java.lang.System.currentTimeMillis());
+        t = java.lang.System.currentTimeMillis() - t;
+        float ft = (float)t;
+        ft /= ct;
+
+        mTest.exitBenchmark();
+        mDoingBenchmark = false;
+
+        return ft;
+    }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/LevelsV4.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/LevelsV4.java
new file mode 100644
index 0000000..fbe3727
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/LevelsV4.java
@@ -0,0 +1,161 @@
+/*
+ * 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.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+
+public class LevelsV4 extends TestBase {
+    private ScriptC_levels_relaxed mScriptR;
+    private ScriptC_levels_full mScriptF;
+    private float mInBlack = 0.0f;
+    private float mOutBlack = 0.0f;
+    private float mInWhite = 255.0f;
+    private float mOutWhite = 255.0f;
+    private float mSaturation = 1.0f;
+
+    Matrix3f satMatrix = new Matrix3f();
+    float mInWMinInB;
+    float mOutWMinOutB;
+    float mOverInWMinInB;
+
+    boolean mUseFull;
+    boolean mUseV4;
+
+    LevelsV4(boolean useFull, boolean useV4) {
+        mUseFull = useFull;
+        mUseV4 = useV4;
+    }
+
+
+    private void setLevels() {
+        mInWMinInB = mInWhite - mInBlack;
+        mOutWMinOutB = mOutWhite - mOutBlack;
+        mOverInWMinInB = 1.f / mInWMinInB;
+
+        mScriptR.set_inBlack(mInBlack);
+        mScriptR.set_outBlack(mOutBlack);
+        mScriptR.set_inWMinInB(mInWMinInB);
+        mScriptR.set_outWMinOutB(mOutWMinOutB);
+        mScriptR.set_overInWMinInB(mOverInWMinInB);
+        mScriptF.set_inBlack(mInBlack);
+        mScriptF.set_outBlack(mOutBlack);
+        mScriptF.set_inWMinInB(mInWMinInB);
+        mScriptF.set_outWMinOutB(mOutWMinOutB);
+        mScriptF.set_overInWMinInB(mOverInWMinInB);
+    }
+
+    private void setSaturation() {
+        float rWeight = 0.299f;
+        float gWeight = 0.587f;
+        float bWeight = 0.114f;
+        float oneMinusS = 1.0f - mSaturation;
+
+        satMatrix.set(0, 0, oneMinusS * rWeight + mSaturation);
+        satMatrix.set(0, 1, oneMinusS * rWeight);
+        satMatrix.set(0, 2, oneMinusS * rWeight);
+        satMatrix.set(1, 0, oneMinusS * gWeight);
+        satMatrix.set(1, 1, oneMinusS * gWeight + mSaturation);
+        satMatrix.set(1, 2, oneMinusS * gWeight);
+        satMatrix.set(2, 0, oneMinusS * bWeight);
+        satMatrix.set(2, 1, oneMinusS * bWeight);
+        satMatrix.set(2, 2, oneMinusS * bWeight + mSaturation);
+        mScriptR.set_colorMat(satMatrix);
+        mScriptF.set_colorMat(satMatrix);
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        b.setProgress(50);
+        t.setText("Saturation");
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(0);
+        t.setText("In Black");
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(0);
+        t.setText("Out Black");
+        return true;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(128);
+        t.setText("Out White");
+        return true;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(128);
+        t.setText("Out White");
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        mSaturation = (float)progress / 50.0f;
+        setSaturation();
+    }
+    public void onBar2Changed(int progress) {
+        mInBlack = (float)progress;
+        setLevels();
+    }
+    public void onBar3Changed(int progress) {
+        mOutBlack = (float)progress;
+        setLevels();
+    }
+    public void onBar4Changed(int progress) {
+        mInWhite = (float)progress + 127.0f;
+        setLevels();
+    }
+    public void onBar5Changed(int progress) {
+        mOutWhite = (float)progress + 127.0f;
+        setLevels();
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mScriptR = new ScriptC_levels_relaxed(mRS, res, R.raw.levels_relaxed);
+        mScriptF = new ScriptC_levels_full(mRS, res, R.raw.levels_full);
+        setSaturation();
+        setLevels();
+    }
+
+    public void runTest() {
+        if (mUseFull) {
+            if (mUseV4) {
+                mScriptF.forEach_root4(mInPixelsAllocation, mOutPixelsAllocation);
+            } else {
+                mScriptF.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+            }
+        } else {
+            if (mUseV4) {
+                mScriptR.forEach_root4(mInPixelsAllocation, mOutPixelsAllocation);
+            } else {
+                mScriptR.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+            }
+        }
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java
new file mode 100644
index 0000000..556d797
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java
@@ -0,0 +1,93 @@
+/*
+ * 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.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Mandelbrot extends TestBase {
+    private ScriptC_mandelbrot mScript;
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Iterations");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        int iters = progress * 3 + 50;
+        mScript.set_gMaxIteration(iters);
+    }
+
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Lower Bound: X");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar2Changed(int progress) {
+        float scaleFactor = mScript.get_scaleFactor();
+        // allow viewport to be moved by 2x scale factor
+        float lowerBoundX = -2.f + ((progress / scaleFactor) / 50.f);
+        mScript.set_lowerBoundX(lowerBoundX);
+    }
+
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Lower Bound: Y");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar3Changed(int progress) {
+        float scaleFactor = mScript.get_scaleFactor();
+        // allow viewport to be moved by 2x scale factor
+        float lowerBoundY = -2.f + ((progress / scaleFactor) / 50.f);
+        mScript.set_lowerBoundY(lowerBoundY);
+    }
+
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        t.setText("Scale Factor");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar4Changed(int progress) {
+        float scaleFactor = 4.f - (3.96f * (progress / 100.f));
+        mScript.set_scaleFactor(scaleFactor);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mOutPixelsAllocation.getType().getX();
+        int height = mOutPixelsAllocation.getType().getY();
+
+        mScript = new ScriptC_mandelbrot(mRS, res, R.raw.mandelbrot);
+        mScript.set_gDimX(width);
+        mScript.set_gDimY(height);
+        mScript.set_gMaxIteration(50);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mOutPixelsAllocation);
+        mRS.finish();
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
new file mode 100644
index 0000000..9df2eff
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
@@ -0,0 +1,134 @@
+/*
+ * 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.rs.image2;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.support.v8.renderscript.*;
+import android.view.SurfaceView;
+import android.view.SurfaceHolder;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.view.View;
+import android.util.Log;
+import java.lang.Math;
+import android.widget.Spinner;
+
+public class TestBase  {
+    protected final String TAG = "Img";
+
+    protected RenderScript mRS;
+    protected Allocation mInPixelsAllocation;
+    protected Allocation mInPixelsAllocation2;
+    protected Allocation mOutPixelsAllocation;
+
+    protected ImageProcessingActivity2 act;
+
+    // Override to use UI elements
+    public void onBar1Changed(int progress) {
+    }
+    public void onBar2Changed(int progress) {
+    }
+    public void onBar3Changed(int progress) {
+    }
+    public void onBar4Changed(int progress) {
+    }
+    public void onBar5Changed(int progress) {
+    }
+
+    // Override to use UI elements
+    // Unused bars will be hidden.
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+
+    public boolean onSpinner1Setup(Spinner s) {
+        s.setVisibility(View.INVISIBLE);
+        return false;
+    }
+
+    public final void createBaseTest(ImageProcessingActivity2 ipact, Bitmap b, Bitmap b2) {
+        act = ipact;
+        mRS = RenderScript.create(act);
+        mInPixelsAllocation = Allocation.createFromBitmap(mRS, b,
+                                                          Allocation.MipmapControl.MIPMAP_NONE,
+                                                          Allocation.USAGE_SCRIPT);
+        mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, b2,
+                                                          Allocation.MipmapControl.MIPMAP_NONE,
+                                                          Allocation.USAGE_SCRIPT);
+        mOutPixelsAllocation = Allocation.createFromBitmap(mRS, b,
+                                                           Allocation.MipmapControl.MIPMAP_NONE,
+                                                           Allocation.USAGE_SCRIPT);
+        createTest(act.getResources());
+    }
+
+    // Must override
+    public void createTest(android.content.res.Resources res) {
+        android.util.Log.e("img", "implement createTest");
+    }
+
+    // Must override
+    public void runTest() {
+    }
+
+    public void finish() {
+        mRS.finish();
+    }
+
+    public void destroy() {
+        mRS.destroy();
+    }
+
+    public void updateBitmap(Bitmap b) {
+        mOutPixelsAllocation.copyTo(b);
+    }
+
+    // Override to configure specific benchmark config.
+    public void setupBenchmark() {
+    }
+
+    // Override to reset after benchmark.
+    public void exitBenchmark() {
+    }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java
new file mode 100644
index 0000000..8618d5a
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java
@@ -0,0 +1,151 @@
+/*
+ * 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.rs.image2;
+
+import android.support.v8.renderscript.*;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Vignette extends TestBase {
+    private ScriptC_vignette_full mScript_full = null;
+    private ScriptC_vignette_relaxed mScript_relaxed = null;
+    private ScriptC_vignette_approx_full mScript_approx_full = null;
+    private ScriptC_vignette_approx_relaxed mScript_approx_relaxed = null;
+    private final boolean approx;
+    private final boolean relaxed;
+    private float center_x = 0.5f;
+    private float center_y = 0.5f;
+    private float scale = 0.5f;
+    private float shade = 0.5f;
+    private float slope = 20.0f;
+
+    public Vignette(boolean approx, boolean relaxed) {
+        this.approx = approx;
+        this.relaxed = relaxed;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Scale");
+        b.setMax(100);
+        b.setProgress(25);
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Shade");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Slope");
+        b.setMax(100);
+        b.setProgress(20);
+        return true;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        t.setText("Shift center X");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        t.setText("Shift center Y");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        scale = progress / 50.0f;
+        do_init();
+    }
+    public void onBar2Changed(int progress) {
+        shade = progress / 100.0f;
+        do_init();
+    }
+    public void onBar3Changed(int progress) {
+        slope = (float)progress;
+        do_init();
+    }
+    public void onBar4Changed(int progress) {
+        center_x = progress / 100.0f;
+        do_init();
+    }
+    public void onBar5Changed(int progress) {
+        center_y = progress / 100.0f;
+        do_init();
+    }
+
+    private void do_init() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.invoke_init_vignette(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale, shade, slope);
+            else
+                mScript_approx_full.invoke_init_vignette(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale, shade, slope);
+        } else if (relaxed)
+            mScript_relaxed.invoke_init_vignette(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale, shade, slope);
+        else
+            mScript_full.invoke_init_vignette(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale, shade, slope);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed = new ScriptC_vignette_approx_relaxed(
+                        mRS, res, R.raw.vignette_approx_relaxed);
+            else
+                mScript_approx_full = new ScriptC_vignette_approx_full(
+                        mRS, res, R.raw.vignette_approx_full);
+        } else if (relaxed)
+            mScript_relaxed = new ScriptC_vignette_relaxed(mRS, res,
+                    R.raw.vignette_relaxed);
+        else
+            mScript_full = new ScriptC_vignette_full(mRS, res,
+                    R.raw.vignette_full);
+        do_init();
+    }
+
+    public void runTest() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.forEach_root(mInPixelsAllocation,
+                        mOutPixelsAllocation);
+            else
+                mScript_approx_full.forEach_root(mInPixelsAllocation,
+                        mOutPixelsAllocation);
+        } else if (relaxed)
+            mScript_relaxed.forEach_root(mInPixelsAllocation,
+                    mOutPixelsAllocation);
+        else
+            mScript_full.forEach_root(mInPixelsAllocation,
+                    mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/blend.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/blend.rs
new file mode 100644
index 0000000..4d90725
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/blend.rs
@@ -0,0 +1,24 @@
+// 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.
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+uchar alpha = 0x0;
+
+void setImageAlpha(uchar4 *v_out, uint32_t x, uint32_t y) {
+  v_out->rgba = convert_uchar4((convert_uint4(v_out->rgba) * alpha) >> (uint4)8);
+  v_out->a = alpha;
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs
new file mode 100644
index 0000000..e93bef3
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+
+static rs_matrix4x4 Mat;
+
+void init() {
+    rsMatrixLoadIdentity(&Mat);
+}
+
+void setMatrix(rs_matrix4x4 m) {
+    Mat = m;
+}
+
+void root(const uchar4 *in, uchar4 *out) {
+    float4 f = convert_float4(*in);
+    f = rsMatrixMultiply(&Mat, f);
+    f = clamp(f, 0.f, 255.f);
+    *out = convert_uchar4(f);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve3x3.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve3x3.rs
new file mode 100644
index 0000000..b55190c
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve3x3.rs
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[9];
+
+void root(uchar4 *out, uint32_t x, uint32_t y) {
+    uint32_t x1 = min((int32_t)x+1, gWidth);
+    uint32_t x2 = max((int32_t)x-1, 0);
+    uint32_t y1 = min((int32_t)y+1, gHeight);
+    uint32_t y2 = max((int32_t)y-1, 0);
+
+    float4 p00 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y1))[0]);
+    float4 p01 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x, y1))[0]);
+    float4 p02 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y1))[0]);
+    float4 p10 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y))[0]);
+    float4 p11 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x, y))[0]);
+    float4 p12 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y))[0]);
+    float4 p20 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y2))[0]);
+    float4 p21 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x, y2))[0]);
+    float4 p22 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y2))[0]);
+    p00 *= gCoeffs[0];
+    p01 *= gCoeffs[1];
+    p02 *= gCoeffs[2];
+    p10 *= gCoeffs[3];
+    p11 *= gCoeffs[4];
+    p12 *= gCoeffs[5];
+    p20 *= gCoeffs[6];
+    p21 *= gCoeffs[7];
+    p22 *= gCoeffs[8];
+
+    p00 += p01;
+    p02 += p10;
+    p11 += p12;
+    p20 += p21;
+
+    p22 += p00;
+    p02 += p11;
+
+    p20 += p22;
+    p20 += p02;
+
+    p20 = clamp(p20, 0.f, 255.f);
+    *out = convert_uchar4(p20);
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
new file mode 100644
index 0000000..b110b88
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[25];
+
+void root(uchar4 *out, uint32_t x, uint32_t y) {
+    uint32_t x0 = max((int32_t)x-2, 0);
+    uint32_t x1 = max((int32_t)x-1, 0);
+    uint32_t x2 = x;
+    uint32_t x3 = min((int32_t)x+1, gWidth-1);
+    uint32_t x4 = min((int32_t)x+2, gWidth-1);
+
+    uint32_t y0 = max((int32_t)y-2, 0);
+    uint32_t y1 = max((int32_t)y-1, 0);
+    uint32_t y2 = y;
+    uint32_t y3 = min((int32_t)y+1, gHeight-1);
+    uint32_t y4 = min((int32_t)y+2, gHeight-1);
+
+    float4 p0 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y0)) * gCoeffs[0]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y0)) * gCoeffs[1]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y0)) * gCoeffs[2]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y0)) * gCoeffs[3]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y0)) * gCoeffs[4];
+
+    float4 p1 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y1)) * gCoeffs[5]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y1)) * gCoeffs[6]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y1)) * gCoeffs[7]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y1)) * gCoeffs[8]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y1)) * gCoeffs[9];
+
+    float4 p2 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y2)) * gCoeffs[10]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y2)) * gCoeffs[11]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y2)) * gCoeffs[12]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y2)) * gCoeffs[13]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y2)) * gCoeffs[14];
+
+    float4 p3 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y3)) * gCoeffs[15]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y3)) * gCoeffs[16]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y3)) * gCoeffs[17]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y3)) * gCoeffs[18]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y3)) * gCoeffs[19];
+
+    float4 p4 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y4)) * gCoeffs[20]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y4)) * gCoeffs[21]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y4)) * gCoeffs[22]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y4)) * gCoeffs[23]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y4)) * gCoeffs[24];
+
+    p0 = clamp(p0 + p1 + p2 + p3 + p4, 0.f, 255.f);
+    *out = convert_uchar4(p0);
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.rs
new file mode 100644
index 0000000..31e4241
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.rs
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+void root(const uchar4 *v_in, uchar4 *v_out) {
+    *v_out = *v_in;
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
new file mode 100644
index 0000000..3809912
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+rs_allocation in_alloc;
+rs_sampler sampler;
+
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
+
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+    center.x = center_x;
+    center.y = center_y;
+    neg_center = -center;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+    alpha = k * 2.0 + 0.75;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+    
+    const float bound2 = 0.25 * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+    const float bound = sqrt(bound2);
+    const float radius = 1.15 * bound;
+    radius2 = radius*radius;
+    const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
+    factor = bound / max_radian;
+}
+
+void root(uchar4 *out, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float2 scaledCoord = axis_scale * coord;
+    const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+    const float inv_dist = rsqrt(dist2);
+    const float radian = M_PI_2 - atan((alpha * sqrt(radius2 - dist2)) * inv_dist);
+    const float scalar = radian * factor * inv_dist;
+    const float2 new_coord = mad(coord, scalar, center);
+    const float4 fout = rsSample(in_alloc, sampler, new_coord);
+    *out = rsPackColorTo8888(fout);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx.rsh
new file mode 100644
index 0000000..08b4126
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx.rsh
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+rs_allocation in_alloc;
+rs_sampler sampler;
+
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
+
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+    center.x = center_x;
+    center.y = center_y;
+    neg_center = -center;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+    alpha = k * 2.0 + 0.75;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float bound2 = 0.25 * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+    const float bound = sqrt(bound2);
+    const float radius = 1.15 * bound;
+    radius2 = radius*radius;
+    const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
+    factor = bound / max_radian;
+}
+
+void root(uchar4 *out, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float2 scaledCoord = axis_scale * coord;
+    const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+    const float inv_dist = half_rsqrt(dist2);
+    const float radian = M_PI_2 - atan((alpha * half_sqrt(radius2 - dist2)) * inv_dist);
+    const float scalar = radian * factor * inv_dist;
+    const float2 new_coord = mad(coord, scalar, center);
+    const float4 fout = rsSample(in_alloc, sampler, new_coord);
+    *out = rsPackColorTo8888(fout);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs
new file mode 100644
index 0000000..cce42f9
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+#include "fisheye_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
new file mode 100644
index 0000000..64d27ed
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+#include "fisheye_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_full.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_full.rs
new file mode 100644
index 0000000..e42df13
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_full.rs
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+#include "fisheye.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs
new file mode 100644
index 0000000..990310b
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+#include "fisheye.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs
new file mode 100644
index 0000000..44320a5
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+void genRand(uchar *out) {
+    *out = (uchar)rsRand(0xff);
+}
+
+/*
+ * Convolution matrix of distance 2 with fixed point of 'kShiftBits' bits
+ * shifted. Thus the sum of this matrix should be 'kShiftValue'. Entries of
+ * small values are not calculated to gain efficiency.
+ * The order ot pixels represented in this matrix is:
+ *  1  2  3
+ *  4  0  5
+ *  6  7  8
+ *  and the matrix should be: {230, 56, 114, 56, 114, 114, 56, 114, 56}.
+ *  However, since most of the valus are identical, we only use the first three
+ *  entries and the entries corresponding to the pixels is:
+ *  1  2  1
+ *  2  0  2
+ *  1  2  1
+ */
+
+int32_t gWMask;
+int32_t gHMask;
+
+rs_allocation gBlendSource;
+void blend9(uchar *out, uint32_t x, uint32_t y) {
+    uint32_t x1 = (x-1) & gWMask;
+    uint32_t x2 = (x+1) & gWMask;
+    uint32_t y1 = (y-1) & gHMask;
+    uint32_t y2 = (y+1) & gHMask;
+
+    uint p00 = 56 *  rsGetElementAt_uchar(gBlendSource, x1, y1);
+    uint p01 = 114 * rsGetElementAt_uchar(gBlendSource, x, y1);
+    uint p02 = 56 *  rsGetElementAt_uchar(gBlendSource, x2, y1);
+    uint p10 = 114 * rsGetElementAt_uchar(gBlendSource, x1, y);
+    uint p11 = 230 * rsGetElementAt_uchar(gBlendSource, x, y);
+    uint p12 = 114 * rsGetElementAt_uchar(gBlendSource, x2, y);
+    uint p20 = 56 *  rsGetElementAt_uchar(gBlendSource, x1, y2);
+    uint p21 = 114 * rsGetElementAt_uchar(gBlendSource, x, y2);
+    uint p22 = 56 *  rsGetElementAt_uchar(gBlendSource, x2, y2);
+
+    p00 += p01;
+    p02 += p10;
+    p11 += p12;
+    p20 += p21;
+
+    p22 += p00;
+    p02 += p11;
+
+    p20 += p22;
+    p20 += p02;
+
+    p20 = min(p20 >> 10, (uint)255);
+    *out = (uchar)p20;
+}
+
+float gNoiseStrength;
+
+rs_allocation gNoise;
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    float4 ip = convert_float4(*in);
+    float pnoise = (float) rsGetElementAt_uchar(gNoise, x & gWMask, y & gHMask);
+
+    float energy_level = ip.r + ip.g + ip.b;
+    float energy_mask = (28.f - sqrt(energy_level)) * 0.03571f;
+    pnoise = (pnoise - 128.f) * energy_mask;
+
+    ip += pnoise * gNoiseStrength;
+    ip = clamp(ip, 0.f, 255.f);
+
+    uchar4 p = convert_uchar4(ip);
+    p.a = 0xff;
+    *out = p;
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/greyscale.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/greyscale.rs
new file mode 100644
index 0000000..b5abf3f0
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/greyscale.rs
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
+
+void root(const uchar4 *v_in, uchar4 *v_out) {
+    float4 f4 = rsUnpackColor8888(*v_in);
+
+    float3 mono = dot(f4.rgb, gMonoMult);
+    *v_out = rsPackColorTo8888(mono);
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels.rsh
new file mode 100644
index 0000000..7c5d930
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels.rsh
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+float inBlack;
+float outBlack;
+float inWMinInB;
+float outWMinOutB;
+float overInWMinInB;
+rs_matrix3x3 colorMat;
+
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    float3 pixel = convert_float4(in[0]).rgb;
+    pixel = rsMatrixMultiply(&colorMat, pixel);
+    pixel = clamp(pixel, 0.f, 255.f);
+    pixel = (pixel - inBlack) * overInWMinInB;
+    pixel = pixel * outWMinOutB + outBlack;
+    pixel = clamp(pixel, 0.f, 255.f);
+    out->xyz = convert_uchar3(pixel);
+    out->w = 0xff;
+}
+
+void root4(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    float4 pixel = convert_float4(in[0]);
+    pixel.rgb = rsMatrixMultiply(&colorMat, pixel.rgb);
+    pixel = clamp(pixel, 0.f, 255.f);
+    pixel = (pixel - inBlack) * overInWMinInB;
+    pixel = pixel * outWMinOutB + outBlack;
+    pixel = clamp(pixel, 0.f, 255.f);
+    out->xyzw = convert_uchar4(pixel);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_full.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_full.rs
new file mode 100644
index 0000000..a4aa388
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_full.rs
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+#include "levels.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
new file mode 100644
index 0000000..ffdcfe3
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+#include "levels.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
new file mode 100644
index 0000000..55e5304
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
@@ -0,0 +1,56 @@
+// 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.
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+uint32_t gMaxIteration = 500;
+uint32_t gDimX = 1024;
+uint32_t gDimY = 1024;
+
+float lowerBoundX = -2.f;
+float lowerBoundY = -2.f;
+float scaleFactor = 4.f;
+
+void root(uchar4 *v_out, uint32_t x, uint32_t y) {
+  float2 p;
+  p.x = lowerBoundX + ((float)x / gDimX) * scaleFactor;
+  p.y = lowerBoundY + ((float)y / gDimY) * scaleFactor;
+
+  float2 t = 0;
+  float2 t2 = t * t;
+  int iter = 0;
+  while((t2.x + t2.y < 4.f) && (iter < gMaxIteration)) {
+    float xtemp = t2.x - t2.y + p.x;
+    t.y = 2 * t.x * t.y + p.y;
+    t.x = xtemp;
+    iter++;
+    t2 = t * t;
+  }
+
+  if(iter >= gMaxIteration) {
+    // write a non-transparent black pixel
+    *v_out = (uchar4){0, 0, 0, 0xff};
+  } else {
+    float mi3 = gMaxIteration / 3.;
+    if (iter <= (gMaxIteration / 3))
+      *v_out = (uchar4){0xff * (iter / mi3), 0, 0, 0xff};
+    else if (iter <= (((gMaxIteration / 3) * 2)))
+      *v_out = (uchar4){0xff - (0xff * ((iter - mi3) / mi3)),
+                        (0xff * ((iter - mi3) / mi3)), 0, 0xff};
+    else
+      *v_out = (uchar4){0, 0xff - (0xff * ((iter - (mi3 * 2)) / mi3)),
+                        (0xff * ((iter - (mi3 * 2)) / mi3)), 0xff};
+  }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs
new file mode 100644
index 0000000..9ef4898
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs
@@ -0,0 +1,106 @@
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+
+int height;
+int width;
+static int radius;
+
+rs_allocation InPixel;
+rs_allocation ScratchPixel1;
+rs_allocation ScratchPixel2;
+
+const int MAX_RADIUS = 25;
+
+// Store our coefficients here
+static float gaussian[MAX_RADIUS * 2 + 1];
+
+void setRadius(int rad) {
+    radius = rad;
+    // Compute gaussian weights for the blur
+    // e is the euler's number
+    float e = 2.718281828459045f;
+    float pi = 3.1415926535897932f;
+    // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 )
+    // x is of the form [-radius .. 0 .. radius]
+    // and sigma varies with radius.
+    // Based on some experimental radius values and sigma's
+    // we approximately fit sigma = f(radius) as
+    // sigma = radius * 0.4  + 0.6
+    // The larger the radius gets, the more our gaussian blur
+    // will resemble a box blur since with large sigma
+    // the gaussian curve begins to lose its shape
+    float sigma = 0.4f * (float)radius + 0.6f;
+
+    // Now compute the coefficints
+    // We will store some redundant values to save some math during
+    // the blur calculations
+    // precompute some values
+    float coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma);
+    float coeff2 = - 1.0f / (2.0f * sigma * sigma);
+
+    float normalizeFactor = 0.0f;
+    float floatR = 0.0f;
+    for (int r = -radius; r <= radius; r ++) {
+        floatR = (float)r;
+        gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
+        normalizeFactor += gaussian[r + radius];
+    }
+
+    //Now we need to normalize the weights because all our coefficients need to add up to one
+    normalizeFactor = 1.0f / normalizeFactor;
+    for (int r = -radius; r <= radius; r ++) {
+        floatR = (float)r;
+        gaussian[r + radius] *= normalizeFactor;
+    }
+}
+
+void copyIn(const uchar4 *in, float4 *out) {
+    *out = convert_float4(*in);
+}
+
+void vert(uchar4 *out, uint32_t x, uint32_t y) {
+    float3 blurredPixel = 0;
+    const float *gPtr = gaussian;
+    if ((y > radius) && (y < (height - radius))) {
+        for (int r = -radius; r <= radius; r ++) {
+            const float4 *i = (const float4 *)rsGetElementAt(ScratchPixel2, x, y + r);
+            blurredPixel += i->xyz * gPtr[0];
+            gPtr++;
+        }
+    } else {
+        for (int r = -radius; r <= radius; r ++) {
+            int validH = rsClamp((int)y + r, (int)0, (int)(height - 1));
+            const float4 *i = (const float4 *)rsGetElementAt(ScratchPixel2, x, validH);
+            blurredPixel += i->xyz * gPtr[0];
+            gPtr++;
+        }
+    }
+
+    out->xyz = convert_uchar3(clamp(blurredPixel, 0.f, 255.f));
+    out->w = 0xff;
+}
+
+void horz(float4 *out, uint32_t x, uint32_t y) {
+    float3 blurredPixel = 0;
+    const float *gPtr = gaussian;
+    if ((x > radius) && (x < (width - radius))) {
+        for (int r = -radius; r <= radius; r ++) {
+            const float4 *i = (const float4 *)rsGetElementAt(ScratchPixel1, x + r, y);
+            blurredPixel += i->xyz * gPtr[0];
+            gPtr++;
+        }
+    } else {
+        for (int r = -radius; r <= radius; r ++) {
+            // Stepping left and right away from the pixel
+            int validX = rsClamp((int)x + r, (int)0, (int)(width - 1));
+            const float4 *i = (const float4 *)rsGetElementAt(ScratchPixel1, validX, y);
+            blurredPixel += i->xyz * gPtr[0];
+            gPtr++;
+        }
+    }
+
+    out->xyz = blurredPixel;
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette.rsh
new file mode 100644
index 0000000..a1e4ae5
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette.rsh
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+static float2 neg_center, axis_scale, inv_dimensions;
+static float sloped_neg_range, sloped_inv_max_dist, shade, opp_shade;
+
+void init_vignette(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y,
+        float desired_scale, float desired_shade, float desired_slope) {
+
+    neg_center.x = -center_x;
+    neg_center.y = -center_y;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float max_dist = 0.5 * length(axis_scale);
+    sloped_inv_max_dist = desired_slope * 1.f/max_dist;
+
+    // Range needs to be between 1.3 to 0.6. When scale is zero then range is
+    // 1.3 which means no vignette at all because the luminousity difference is
+    // less than 1/256.  Expect input scale to be between 0.0 and 1.0.
+    const float neg_range = 0.7*sqrt(desired_scale) - 1.3;
+    sloped_neg_range = exp(neg_range * desired_slope);
+
+    shade = desired_shade;
+    opp_shade = 1.f - desired_shade;
+}
+
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float4 fin = convert_float4(*in);
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float sloped_dist_ratio = length(axis_scale * coord)  * sloped_inv_max_dist;
+    const float lumen = opp_shade + shade / ( 1.0 + sloped_neg_range * exp(sloped_dist_ratio) );
+    float4 fout;
+    fout.rgb = fin.rgb * lumen;
+    fout.w = fin.w;
+    *out = convert_uchar4(fout);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh
new file mode 100644
index 0000000..7f7bdcf
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+static float2 neg_center, axis_scale, inv_dimensions;
+static float sloped_neg_range, sloped_inv_max_dist, shade, opp_shade;
+
+void init_vignette(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y,
+        float desired_scale, float desired_shade, float desired_slope) {
+
+    neg_center.x = -center_x;
+    neg_center.y = -center_y;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float max_dist = 0.5 * length(axis_scale);
+    sloped_inv_max_dist = desired_slope * 1.f/max_dist;
+
+    // Range needs to be between 1.3 to 0.6. When scale is zero then range is
+    // 1.3 which means no vignette at all because the luminousity difference is
+    // less than 1/256.  Expect input scale to be between 0.0 and 1.0.
+    const float neg_range = 0.7*sqrt(desired_scale) - 1.3;
+    sloped_neg_range = exp(neg_range * desired_slope);
+
+    shade = desired_shade;
+    opp_shade = 1.f - desired_shade;
+}
+
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float4 fin = convert_float4(*in);
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float sloped_dist_ratio = fast_length(axis_scale * coord)  * sloped_inv_max_dist;
+    // TODO:  add half_exp once implemented
+    const float lumen = opp_shade + shade * half_recip(1.f + sloped_neg_range * exp(sloped_dist_ratio));
+    float4 fout;
+    fout.rgb = fin.rgb * lumen;
+    fout.w = fin.w;
+    *out = convert_uchar4(fout);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs
new file mode 100644
index 0000000..3612509
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+#include "vignette_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
new file mode 100644
index 0000000..b714e9b
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+#include "vignette_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_full.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_full.rs
new file mode 100644
index 0000000..5fc2dda
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_full.rs
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+#include "vignette.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.rs
new file mode 100644
index 0000000..430b685
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.rs
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+#include "vignette.rsh"
+
diff --git a/tests/RenderScriptTests/LivePreview/Android.mk b/tests/RenderScriptTests/LivePreview/Android.mk
new file mode 100644
index 0000000..1b45573
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/Android.mk
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := PreviewRS
+
+include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/LivePreview/AndroidManifest.xml b/tests/RenderScriptTests/LivePreview/AndroidManifest.xml
new file mode 100644
index 0000000..1b91464
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* 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.
+*/
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.livepreview">
+    <uses-sdk android:minSdkVersion="14" />
+    <uses-permission android:name="android.permission.CAMERA" />
+    <application android:label="Preview FS"
+                 android:hardwareAccelerated="true">
+
+        <activity android:name="CameraPreviewActivity"
+                  android:label="Preview FS"
+                  android:screenOrientation="landscape">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+    </application>
+</manifest>
diff --git a/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/city.png b/tests/RenderScriptTests/LivePreview/res/drawable-nodpi/city.png
similarity index 100%
copy from tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/city.png
copy to tests/RenderScriptTests/LivePreview/res/drawable-nodpi/city.png
Binary files differ
diff --git a/tests/RenderScriptTests/LivePreview/res/layout/cf_format_list_item.xml b/tests/RenderScriptTests/LivePreview/res/layout/cf_format_list_item.xml
new file mode 100644
index 0000000..8196bbf
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/res/layout/cf_format_list_item.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:padding="10dp"
+    android:textSize="16sp"
+/>
diff --git a/tests/RenderScriptTests/LivePreview/res/layout/cf_main.xml b/tests/RenderScriptTests/LivePreview/res/layout/cf_main.xml
new file mode 100644
index 0000000..c7dcca5
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/res/layout/cf_main.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" >
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="3" >
+
+            <TextureView
+                android:id="@+id/preview_view"
+                android:layout_height="0dp"
+                android:layout_width="fill_parent"
+                android:layout_weight="3" />
+            <TextView
+                android:id="@+id/preview_label"
+                android:layout_height="wrap_content"
+                android:layout_width="fill_parent"
+                android:text="@string/cf_preview_label"
+                android:padding="2dp"
+                android:textSize="16sp"
+                android:gravity="center" />
+
+        </LinearLayout>
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="3" >
+
+            <ImageView
+                android:id="@+id/format_view"
+                android:layout_height="0dp"
+                android:layout_width="fill_parent"
+                android:layout_weight="3" />
+            <TextView
+                android:id="@+id/format_label"
+                android:layout_height="wrap_content"
+                android:layout_width="fill_parent"
+                android:text="@string/cf_format_label"
+                android:padding="2dp"
+                android:textSize="16sp"
+                android:gravity="center" />
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="2" >
+
+            <Spinner
+                android:id="@+id/cameras_selection"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <Spinner
+                android:id="@+id/resolution_selection"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <Spinner
+                android:id="@+id/format_selection"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+
+</LinearLayout>
diff --git a/tests/RenderScriptTests/LivePreview/res/layout/main.xml b/tests/RenderScriptTests/LivePreview/res/layout/main.xml
new file mode 100644
index 0000000..a6a075c
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/res/layout/main.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:orientation="vertical"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:id="@+id/toplevel">
+    <SurfaceView
+        android:id="@+id/surface"
+        android:layout_width="1dip"
+        android:layout_height="1dip" />
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="vertical"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent">
+            <ImageView
+                android:id="@+id/display"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="horizontal"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content">
+                    <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/benchmark"
+                        android:onClick="benchmark"/>
+                    <TextView
+                        android:id="@+id/benchmarkText"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/saturation"/>
+            </LinearLayout>
+            <TextView
+                android:id="@+id/inSaturationText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/saturation"/>
+             <SeekBar
+                android:id="@+id/inSaturation"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/outWhiteText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:textSize="8pt"
+                android:text="@string/out_white"/>
+            <SeekBar
+                android:id="@+id/outWhite"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inWhiteText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/inWhite"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/outBlackText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/out_black"/>
+            <SeekBar
+                android:id="@+id/outBlack"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inBlackText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_black"/>
+            <SeekBar
+                android:id="@+id/inBlack"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inGammaText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/gamma"/>
+            <SeekBar
+                android:id="@+id/inGamma"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            </LinearLayout>
+    </ScrollView>
+</LinearLayout>
+
diff --git a/tests/RenderScriptTests/LivePreview/res/layout/rs.xml b/tests/RenderScriptTests/LivePreview/res/layout/rs.xml
new file mode 100644
index 0000000..6fde1b9
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/res/layout/rs.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:orientation="vertical"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:id="@+id/toplevel">
+    <SurfaceView
+        android:id="@+id/surface"
+        android:layout_width="1dip"
+        android:layout_height="1dip" />
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="vertical"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent">
+            <TextureView
+                android:id="@+id/display"
+                android:layout_width="800sp"
+                android:layout_height="423sp" />
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="horizontal"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content">
+                    <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/benchmark"
+                        android:onClick="benchmark"/>
+                    <TextView
+                        android:id="@+id/benchmarkText"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/saturation"/>
+            </LinearLayout>
+            <TextView
+                android:id="@+id/inSaturationText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/saturation"/>
+             <SeekBar
+                android:id="@+id/inSaturation"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/outWhiteText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:textSize="8pt"
+                android:text="@string/out_white"/>
+            <SeekBar
+                android:id="@+id/outWhite"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inWhiteText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/inWhite"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/outBlackText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/out_black"/>
+            <SeekBar
+                android:id="@+id/outBlack"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inBlackText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_black"/>
+            <SeekBar
+                android:id="@+id/inBlack"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inGammaText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/gamma"/>
+            <SeekBar
+                android:id="@+id/inGamma"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            </LinearLayout>
+    </ScrollView>
+</LinearLayout>
+
diff --git a/tests/RenderScriptTests/LivePreview/res/values/strings.xml b/tests/RenderScriptTests/LivePreview/res/values/strings.xml
new file mode 100644
index 0000000..d651bfb
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/res/values/strings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+    <string name="in_white">In White</string>
+    <string name="out_white">Out White</string>
+    <string name="in_black">In Black</string>
+    <string name="out_black">Out Black</string>
+    <string name="gamma">Gamma</string>
+    <string name="saturation">Saturation</string>
+    <string name="benchmark">Benchmark</string>
+
+    <string name="app_name">CTS Verifier</string>
+    <string name="welcome_text">Welcome to the CTS Verifier!</string>
+    <string name="version_text">%1$s</string>
+    <string name="continue_button_text">Continue</string>
+
+    <string name="cf_preview_label">Normal preview</string>
+    <string name="cf_format_label">Processed callback data</string>
+    <string name="camera_format">Camera Formats</string>
+
+
+</resources>
diff --git a/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/CameraPreviewActivity.java b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/CameraPreviewActivity.java
new file mode 100644
index 0000000..89eec2c
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/CameraPreviewActivity.java
@@ -0,0 +1,379 @@
+/*
+ * 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.rs.livepreview;
+
+//import com.android.cts.verifier.PassFailButtons;
+//import com.android.cts.verifier.R;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.ImageFormat;
+import android.graphics.Matrix;
+import android.graphics.SurfaceTexture;
+import android.hardware.Camera;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.View;
+import android.view.TextureView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.Spinner;
+
+import java.io.IOException;
+import java.lang.InterruptedException;
+import java.lang.Math;
+import java.lang.Thread;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.TreeSet;
+
+import android.renderscript.*;
+
+/**
+ * Tests for manual verification of the CDD-required camera output formats
+ * for preview callbacks
+ */
+public class CameraPreviewActivity extends Activity
+        implements TextureView.SurfaceTextureListener, Camera.PreviewCallback {
+
+    private static final String TAG = "CameraFormats";
+
+    private TextureView mPreviewView;
+    private SurfaceTexture mPreviewTexture;
+    private int mPreviewTexWidth;
+    private int mPreviewTexHeight;
+
+    private ImageView mFormatView;
+
+    private Spinner mCameraSpinner;
+    private Spinner mResolutionSpinner;
+
+    private int mCurrentCameraId = -1;
+    private Camera mCamera;
+
+    private List<Camera.Size> mPreviewSizes;
+    private Camera.Size mNextPreviewSize;
+    private Camera.Size mPreviewSize;
+
+    private Bitmap mCallbackBitmap;
+
+    private static final int STATE_OFF = 0;
+    private static final int STATE_PREVIEW = 1;
+    private static final int STATE_NO_CALLBACKS = 2;
+    private int mState = STATE_OFF;
+    private boolean mProcessInProgress = false;
+    private boolean mProcessingFirstFrame = false;
+
+
+    private RenderScript mRS;
+    private RsYuv mFilterYuv;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.cf_main);
+
+        mPreviewView = (TextureView) findViewById(R.id.preview_view);
+        mFormatView = (ImageView) findViewById(R.id.format_view);
+
+        mPreviewView.setSurfaceTextureListener(this);
+
+        int numCameras = Camera.getNumberOfCameras();
+        String[] cameraNames = new String[numCameras];
+        for (int i = 0; i < numCameras; i++) {
+            cameraNames[i] = "Camera " + i;
+        }
+        mCameraSpinner = (Spinner) findViewById(R.id.cameras_selection);
+        mCameraSpinner.setAdapter(
+            new ArrayAdapter<String>(
+                this, R.layout.cf_format_list_item, cameraNames));
+        mCameraSpinner.setOnItemSelectedListener(mCameraSpinnerListener);
+
+        mResolutionSpinner = (Spinner) findViewById(R.id.resolution_selection);
+        mResolutionSpinner.setOnItemSelectedListener(mResolutionSelectedListener);
+
+
+        mRS = RenderScript.create(this);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        setUpCamera(mCameraSpinner.getSelectedItemPosition());
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+
+        shutdownCamera();
+    }
+
+    public void onSurfaceTextureAvailable(SurfaceTexture surface,
+            int width, int height) {
+        mPreviewTexture = surface;
+        mPreviewTexWidth = width;
+        mPreviewTexHeight = height;
+        if (mCamera != null) {
+            startPreview();
+        }
+    }
+
+    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+        // Ignored, Camera does all the work for us
+    }
+
+    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+        return true;
+    }
+
+    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+        // Invoked every time there's a new Camera preview frame
+    }
+
+    private AdapterView.OnItemSelectedListener mCameraSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent,
+                        View view, int pos, long id) {
+                    if (mCurrentCameraId != pos) {
+                        setUpCamera(pos);
+                    }
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+
+            };
+
+    private AdapterView.OnItemSelectedListener mResolutionSelectedListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent,
+                        View view, int position, long id) {
+                    if (mPreviewSizes.get(position) != mPreviewSize) {
+                        mNextPreviewSize = mPreviewSizes.get(position);
+                        startPreview();
+                    }
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+
+            };
+
+
+    private void setUpCamera(int id) {
+        shutdownCamera();
+
+        mCurrentCameraId = id;
+        mCamera = Camera.open(id);
+        Camera.Parameters p = mCamera.getParameters();
+
+        // Get preview resolutions
+
+        List<Camera.Size> unsortedSizes = p.getSupportedPreviewSizes();
+
+        class SizeCompare implements Comparator<Camera.Size> {
+            public int compare(Camera.Size lhs, Camera.Size rhs) {
+                if (lhs.width < rhs.width) return -1;
+                if (lhs.width > rhs.width) return 1;
+                if (lhs.height < rhs.height) return -1;
+                if (lhs.height > rhs.height) return 1;
+                return 0;
+            }
+        };
+
+        SizeCompare s = new SizeCompare();
+        TreeSet<Camera.Size> sortedResolutions = new TreeSet<Camera.Size>(s);
+        sortedResolutions.addAll(unsortedSizes);
+
+        mPreviewSizes = new ArrayList<Camera.Size>(sortedResolutions);
+
+        String[] availableSizeNames = new String[mPreviewSizes.size()];
+        for (int i = 0; i < mPreviewSizes.size(); i++) {
+            availableSizeNames[i] =
+                    Integer.toString(mPreviewSizes.get(i).width) + " x " +
+                    Integer.toString(mPreviewSizes.get(i).height);
+        }
+        mResolutionSpinner.setAdapter(
+            new ArrayAdapter<String>(
+                this, R.layout.cf_format_list_item, availableSizeNames));
+
+
+        // Set initial values
+
+        mNextPreviewSize = mPreviewSizes.get(0);
+        mResolutionSpinner.setSelection(0);
+
+        if (mPreviewTexture != null) {
+            startPreview();
+        }
+    }
+
+    private void shutdownCamera() {
+        if (mCamera != null) {
+            mCamera.setPreviewCallbackWithBuffer(null);
+            mCamera.stopPreview();
+            mCamera.release();
+            mCamera = null;
+            mState = STATE_OFF;
+        }
+    }
+
+    private void startPreview() {
+        if (mState != STATE_OFF) {
+            // Stop for a while to drain callbacks
+            mCamera.setPreviewCallbackWithBuffer(null);
+            mCamera.stopPreview();
+            mState = STATE_OFF;
+            Handler h = new Handler();
+            Runnable mDelayedPreview = new Runnable() {
+                public void run() {
+                    startPreview();
+                }
+            };
+            h.postDelayed(mDelayedPreview, 300);
+            return;
+        }
+        mState = STATE_PREVIEW;
+
+        Matrix transform = new Matrix();
+        float widthRatio = mNextPreviewSize.width / (float)mPreviewTexWidth;
+        float heightRatio = mNextPreviewSize.height / (float)mPreviewTexHeight;
+
+        transform.setScale(1, heightRatio/widthRatio);
+        transform.postTranslate(0,
+                mPreviewTexHeight * (1 - heightRatio/widthRatio)/2);
+
+        mPreviewView.setTransform(transform);
+
+        mPreviewSize   = mNextPreviewSize;
+
+        Camera.Parameters p = mCamera.getParameters();
+        p.setPreviewFormat(ImageFormat.NV21);
+        p.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
+        mCamera.setParameters(p);
+
+        mCamera.setPreviewCallbackWithBuffer(this);
+        int expectedBytes = mPreviewSize.width * mPreviewSize.height *
+                ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8;
+        for (int i=0; i < 4; i++) {
+            mCamera.addCallbackBuffer(new byte[expectedBytes]);
+        }
+        //mFormatView.setColorFilter(mYuv2RgbFilter);
+
+        mProcessingFirstFrame = true;
+        try {
+            mCamera.setPreviewTexture(mPreviewTexture);
+            mCamera.startPreview();
+        } catch (IOException ioe) {
+            // Something bad happened
+            Log.e(TAG, "Unable to start up preview");
+        }
+
+    }
+
+
+    private class ProcessPreviewDataTask extends AsyncTask<byte[], Void, Boolean> {
+        protected Boolean doInBackground(byte[]... datas) {
+            byte[] data = datas[0];
+
+            long t1 = java.lang.System.currentTimeMillis();
+
+            mFilterYuv.execute(data, mCallbackBitmap);
+
+            long t2 = java.lang.System.currentTimeMillis();
+            mTiming[mTimingSlot++] = t2 - t1;
+            if (mTimingSlot >= mTiming.length) {
+                float total = 0;
+                for (int i=0; i<mTiming.length; i++) {
+                    total += (float)mTiming[i];
+                }
+                total /= mTiming.length;
+                Log.e(TAG, "time + " + total);
+                mTimingSlot = 0;
+            }
+
+            mCamera.addCallbackBuffer(data);
+            mProcessInProgress = false;
+            return true;
+        }
+
+        protected void onPostExecute(Boolean result) {
+            mFormatView.invalidate();
+        }
+
+    }
+
+    private long mTiming[] = new long[50];
+    private int mTimingSlot = 0;
+
+    public void onPreviewFrame(byte[] data, Camera camera) {
+        if (mProcessInProgress || mState != STATE_PREVIEW) {
+            mCamera.addCallbackBuffer(data);
+            return;
+        }
+        if (data == null) {
+            return;
+        }
+
+        int expectedBytes = mPreviewSize.width * mPreviewSize.height *
+                ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8;
+
+        if (expectedBytes != data.length) {
+            Log.e(TAG, "Mismatched size of buffer! Expected ");
+
+            mState = STATE_NO_CALLBACKS;
+            mCamera.setPreviewCallbackWithBuffer(null);
+            return;
+        }
+
+        mProcessInProgress = true;
+
+        if (mCallbackBitmap == null ||
+                mPreviewSize.width != mCallbackBitmap.getWidth() ||
+                mPreviewSize.height != mCallbackBitmap.getHeight() ) {
+            mCallbackBitmap =
+                    Bitmap.createBitmap(
+                        mPreviewSize.width, mPreviewSize.height,
+                        Bitmap.Config.ARGB_8888);
+            mFilterYuv = new RsYuv(mRS, getResources(), mPreviewSize.width, mPreviewSize.height);
+            mFormatView.setImageBitmap(mCallbackBitmap);
+        }
+
+
+        mFormatView.invalidate();
+
+        mCamera.addCallbackBuffer(data);
+        mProcessInProgress = true;
+        new ProcessPreviewDataTask().execute(data);
+    }
+
+
+
+}
\ No newline at end of file
diff --git a/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/RsYuv.java b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/RsYuv.java
new file mode 100644
index 0000000..978ae12
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/RsYuv.java
@@ -0,0 +1,78 @@
+/*
+ * 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.rs.livepreview;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.os.Bundle;
+import android.graphics.SurfaceTexture;
+import android.renderscript.Allocation;
+import android.renderscript.Matrix3f;
+import android.renderscript.RenderScript;
+import android.util.Log;
+import android.view.TextureView;
+import android.view.View;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+
+import android.graphics.Bitmap;
+
+public class RsYuv
+{
+    private int mHeight;
+    private int mWidth;
+    private RenderScript mRS;
+    private Allocation mAllocationOut;
+    private Allocation mAllocationIn;
+    private ScriptC_yuv mScript;
+    private ScriptIntrinsicYuvToRGB mYuv;
+
+    RsYuv(RenderScript rs, Resources res, int width, int height) {
+        mHeight = height;
+        mWidth = width;
+        mRS = rs;
+        mScript = new ScriptC_yuv(mRS, res, R.raw.yuv);
+        mScript.invoke_setSize(mWidth, mHeight);
+
+        mYuv = ScriptIntrinsicYuvToRGB.create(rs, Element.RGBA_8888(mRS));
+
+        Type.Builder tb = new Type.Builder(mRS, Element.RGBA_8888(mRS));
+        tb.setX(mWidth);
+        tb.setY(mHeight);
+
+        mAllocationOut = Allocation.createTyped(rs, tb.create());
+        mAllocationIn = Allocation.createSized(rs, Element.U8(mRS), (mHeight * mWidth) +
+                                               ((mHeight / 2) * (mWidth / 2) * 2));
+
+        mYuv.setInput(mAllocationIn);
+    }
+
+    private long mTiming[] = new long[50];
+    private int mTimingSlot = 0;
+
+    void execute(byte[] yuv, Bitmap b) {
+        mAllocationIn.copyFrom(yuv);
+        mYuv.forEach(mAllocationOut);
+        mScript.forEach_root(mAllocationOut, mAllocationOut);
+        mAllocationOut.copyTo(b);
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/yuv.rs b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/yuv.rs
new file mode 100644
index 0000000..884812d
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/yuv.rs
@@ -0,0 +1,126 @@
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.livepreview)
+#pragma rs_fp_relaxed
+
+static int gWidth;
+static int gHeight;
+static uchar crossProcess_tableR[256];
+static uchar crossProcess_tableG[256];
+static uchar crossProcess_tableB[256];
+static uchar vignette_table[512];
+
+
+static float4 crossProcess(float4 color) {
+    float4 ncolor = 0.f;
+    float v;
+
+    if (color.r < 0.5f) {
+        v = color.r;
+        ncolor.r = 4.0f * v * v * v;
+    } else {
+        v = 1.0f - color.r;
+        ncolor.r = 1.0f - (4.0f * v * v * v);
+    }
+
+    if (color.g < 0.5f) {
+        v = color.g;
+        ncolor.g = 2.0f * v * v;
+    } else {
+        v = 1.0f - color.g;
+        ncolor.g = 1.0f - (2.0f * v * v);
+    }
+
+    ncolor.b = color.b * 0.5f + 0.25f;
+    ncolor.a = color.a;
+    return ncolor;
+}
+
+static uchar4 crossProcess_i(uchar4 color) {
+    uchar4 ncolor = color;
+    ncolor.r = crossProcess_tableR[color.r];
+    ncolor.g = crossProcess_tableG[color.g];
+    ncolor.b = crossProcess_tableB[color.b];
+    return ncolor;
+}
+
+
+float temp = 0.2f;
+static float4 colortemp(float4 color) {
+    float4 new_color = color;
+    float4 t = color * ((float4)1.0f - color) * temp;
+
+    new_color.r = color.r + t.r;
+    new_color.b = color.b - t.b;
+    if (temp > 0.0f) {
+        color.g = color.g + t.g * 0.25f;
+    }
+    float max_value = max(new_color.r, max(new_color.g, new_color.b));
+    if (max_value > 1.0f) {
+        new_color /= max_value;
+    }
+
+    return new_color;
+}
+
+
+static float vignette_dist_mod;
+int2 vignette_half_dims;
+static uchar4 vignette(uchar4 color, uint32_t x, uint32_t y) {
+    int2 xy = {x, y};
+    xy -= vignette_half_dims;
+    xy *= xy;
+
+    float d = vignette_dist_mod * (xy.x + xy.y);
+    ushort4 c = convert_ushort4(color);
+    c *= vignette_table[(int)d];
+    c >>= (ushort4)8;
+    return convert_uchar4(c);
+}
+
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    uchar4 p;
+    p = crossProcess_i(*in);
+    p = vignette(p, x, y);
+
+    out->rgba = p;
+    out->a = 0xff;
+}
+
+float vignetteScale = 0.5f;
+float vignetteShade = 0.85f;
+
+static void precompute() {
+    for(int i=0; i <256; i++) {
+        float4 f = ((float)i) / 255.f;
+        float4 res = crossProcess(f);
+        res = colortemp(res);
+        crossProcess_tableR[i] = (uchar)(res.r * 255.f);
+        crossProcess_tableG[i] = (uchar)(res.g * 255.f);
+        crossProcess_tableB[i] = (uchar)(res.b * 255.f);
+    }
+
+    for(int i=0; i <512; i++) {
+        const float slope = 20.0f;
+        float f = ((float)i) / 511.f;
+
+        float range = 1.30f - sqrt(vignetteScale) * 0.7f;
+        float lumen = vignetteShade / (1.0f + exp((sqrt(f) - range) * slope)) + (1.0f - vignetteShade);
+        lumen = clamp(lumen, 0.f, 1.f);
+
+        vignette_table[i] = (uchar)(lumen * 255.f + 0.5f);
+    }
+}
+
+void init() {
+    precompute();
+}
+
+void setSize(int w, int h) {
+    gWidth = w;
+    gHeight = h;
+    vignette_half_dims = (int2){w / 2, h / 2};
+    vignette_dist_mod = 512.f;
+    vignette_dist_mod /= (float)(w*w + h*h) / 4.f;
+
+}
diff --git a/tests/RenderScriptTests/MiscSamples/Android.mk b/tests/RenderScriptTests/MiscSamples/Android.mk
index 6b8b691..bdff46a 100644
--- a/tests/RenderScriptTests/MiscSamples/Android.mk
+++ b/tests/RenderScriptTests/MiscSamples/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/ModelViewer/Android.mk b/tests/RenderScriptTests/ModelViewer/Android.mk
index 1d9bacf..18ceac5 100644
--- a/tests/RenderScriptTests/ModelViewer/Android.mk
+++ b/tests/RenderScriptTests/ModelViewer/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 #LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
diff --git a/tests/RenderScriptTests/SampleTest/Android.mk b/tests/RenderScriptTests/SampleTest/Android.mk
index 7d74c55..f3439b0 100644
--- a/tests/RenderScriptTests/SampleTest/Android.mk
+++ b/tests/RenderScriptTests/SampleTest/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/SceneGraph/Android.mk b/tests/RenderScriptTests/SceneGraph/Android.mk
index ba4b3c5..163a95d 100644
--- a/tests/RenderScriptTests/SceneGraph/Android.mk
+++ b/tests/RenderScriptTests/SceneGraph/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/ShadersTest/Android.mk b/tests/RenderScriptTests/ShadersTest/Android.mk
index 109b0a0..0912591 100644
--- a/tests/RenderScriptTests/ShadersTest/Android.mk
+++ b/tests/RenderScriptTests/ShadersTest/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/SurfaceTexture/Android.mk b/tests/RenderScriptTests/SurfaceTexture/Android.mk
index bbd4d55..d5262ee2 100644
--- a/tests/RenderScriptTests/SurfaceTexture/Android.mk
+++ b/tests/RenderScriptTests/SurfaceTexture/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/tests/Android.mk b/tests/RenderScriptTests/tests/Android.mk
index 880b80f..198693c 100644
--- a/tests/RenderScriptTests/tests/Android.mk
+++ b/tests/RenderScriptTests/tests/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
index d0f3e62..7662007 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
@@ -67,12 +67,17 @@
         unitTests.add(new UT_primitives(this, mRes, mCtx));
         unitTests.add(new UT_constant(this, mRes, mCtx));
         unitTests.add(new UT_vector(this, mRes, mCtx));
+        unitTests.add(new UT_unsigned(this, mRes, mCtx));
         unitTests.add(new UT_array_init(this, mRes, mCtx));
         unitTests.add(new UT_array_alloc(this, mRes, mCtx));
+        unitTests.add(new UT_kernel(this, mRes, mCtx));
+        unitTests.add(new UT_kernel_struct(this, mRes, mCtx));
+        unitTests.add(new UT_bug_char(this, mRes, mCtx));
         unitTests.add(new UT_clamp(this, mRes, mCtx));
         unitTests.add(new UT_clamp_relaxed(this, mRes, mCtx));
         unitTests.add(new UT_convert(this, mRes, mCtx));
         unitTests.add(new UT_convert_relaxed(this, mRes, mCtx));
+        unitTests.add(new UT_copy_test(this, mRes, mCtx));
         unitTests.add(new UT_rsdebug(this, mRes, mCtx));
         unitTests.add(new UT_rstime(this, mRes, mCtx));
         unitTests.add(new UT_rstypes(this, mRes, mCtx));
@@ -84,6 +89,9 @@
         unitTests.add(new UT_struct(this, mRes, mCtx));
         unitTests.add(new UT_math(this, mRes, mCtx));
         unitTests.add(new UT_math_conformance(this, mRes, mCtx));
+        unitTests.add(new UT_math_agree(this, mRes, mCtx));
+        unitTests.add(new UT_min(this, mRes, mCtx));
+        unitTests.add(new UT_int4(this, mRes, mCtx));
         unitTests.add(new UT_element(this, mRes, mCtx));
         unitTests.add(new UT_sampler(this, mRes, mCtx));
         unitTests.add(new UT_program_store(this, mRes, mCtx));
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_alloc.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_alloc.java
index b583b1c..a06d820 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_alloc.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_alloc.java
@@ -56,7 +56,7 @@
 
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
-        ScriptC_alloc s = new ScriptC_alloc(pRS, mRes, R.raw.alloc);
+        ScriptC_alloc s = new ScriptC_alloc(pRS);
         pRS.setMessageHandler(mRsMessage);
         initializeGlobals(pRS, s);
         s.invoke_alloc_test();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_array_alloc.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_array_alloc.java
index befe865..ac01a93 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_array_alloc.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_array_alloc.java
@@ -30,7 +30,7 @@
 
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
-        ScriptC_array_alloc s = new ScriptC_array_alloc(pRS, mRes, R.raw.array_alloc);
+        ScriptC_array_alloc s = new ScriptC_array_alloc(pRS);
         pRS.setMessageHandler(mRsMessage);
 
         int dimX = s.get_dimX();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_array_init.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_array_init.java
index b98b753..c74e4b3 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_array_init.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_array_init.java
@@ -83,7 +83,7 @@
 
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
-        ScriptC_array_init s = new ScriptC_array_init(pRS, mRes, R.raw.array_init);
+        ScriptC_array_init s = new ScriptC_array_init(pRS);
         pRS.setMessageHandler(mRsMessage);
         checkInit(s);
         s.invoke_array_init_test();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_atomic.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_atomic.java
index 267c5b2..0b8e072 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_atomic.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_atomic.java
@@ -30,7 +30,7 @@
 
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
-        ScriptC_atomic s = new ScriptC_atomic(pRS, mRes, R.raw.atomic);
+        ScriptC_atomic s = new ScriptC_atomic(pRS);
         pRS.setMessageHandler(mRsMessage);
         s.invoke_atomic_test();
         pRS.finish();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_bug_char.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_bug_char.java
new file mode 100644
index 0000000..faf3a31
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_bug_char.java
@@ -0,0 +1,89 @@
+/*
+ * 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+import java.util.Arrays;
+
+public class UT_bug_char extends UnitTest {
+    private Resources mRes;
+
+    protected UT_bug_char(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Bug Char", ctx);
+        mRes = res;
+    }
+
+    // packing functions
+    private Byte2 pack_b2(byte[] val) {
+        assert val.length == 2;
+        Log.i("bug_char", "pack_b2 " + val[0] + " " + val[1]);
+        return new Byte2(val[0], val[1]);
+    }
+
+    private byte min(byte v1, byte v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private byte[] min(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+
+    private void initializeValues(ScriptC_bug_char s) {
+        byte rand_sc1_0 = (byte)7;
+        byte[] rand_sc2_0 = new byte[2];
+        rand_sc2_0[0] = 11;
+        rand_sc2_0[1] = 21;
+        Log.i("bug_char", "Generated sc2_0 to " + Arrays.toString(rand_sc2_0));
+        byte rand_sc1_1 = (byte)10;
+        byte[] rand_sc2_1 = new byte[2];
+        rand_sc2_1[0] = 13;
+        rand_sc2_1[1] = 15;
+        Log.i("bug_char", "Generated sc2_1 to " + Arrays.toString(rand_sc2_1));
+
+        s.set_rand_sc1_0(rand_sc1_0);
+        s.set_rand_sc2_0(pack_b2(rand_sc2_0));
+        s.set_rand_sc1_1(rand_sc1_1);
+        s.set_rand_sc2_1(pack_b2(rand_sc2_1));
+        // Set results for min
+        s.set_min_rand_sc1_sc1(min(rand_sc1_0, rand_sc1_1));
+        byte[] min_rand_sc2_raw = min(rand_sc2_0, rand_sc2_1);
+        Log.i("bug_char", "Generating min_rand_sc2_sc2 to " +
+              Arrays.toString(min_rand_sc2_raw));
+        Byte2 min_rand_sc2 = pack_b2(min_rand_sc2_raw);
+        Log.i("bug_char", "Setting min_rand_sc2_sc2 to [" + min_rand_sc2.x +
+              ", " + min_rand_sc2.y + "]");
+        s.set_min_rand_sc2_sc2(min_rand_sc2);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_bug_char s = new ScriptC_bug_char(pRS, mRes,
+                R.raw.bug_char);
+        pRS.setMessageHandler(mRsMessage);
+        initializeValues(s);
+        s.invoke_bug_char_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_clamp.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_clamp.java
index 08c96bb..de98d0c 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_clamp.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_clamp.java
@@ -30,7 +30,7 @@
 
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
-        ScriptC_clamp s = new ScriptC_clamp(pRS, mRes, R.raw.clamp);
+        ScriptC_clamp s = new ScriptC_clamp(pRS);
         pRS.setMessageHandler(mRsMessage);
         s.invoke_clamp_test();
         pRS.finish();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_clamp_relaxed.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_clamp_relaxed.java
index a6fd868..91e7140 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_clamp_relaxed.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_clamp_relaxed.java
@@ -31,7 +31,7 @@
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
         ScriptC_clamp_relaxed s =
-                new ScriptC_clamp_relaxed(pRS, mRes, R.raw.clamp_relaxed);
+                new ScriptC_clamp_relaxed(pRS);
         pRS.setMessageHandler(mRsMessage);
         s.invoke_clamp_test();
         pRS.finish();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_convert.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_convert.java
index 4fc6c55..adf79bc 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_convert.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_convert.java
@@ -30,7 +30,7 @@
 
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
-        ScriptC_convert s = new ScriptC_convert(pRS, mRes, R.raw.convert);
+        ScriptC_convert s = new ScriptC_convert(pRS);
         pRS.setMessageHandler(mRsMessage);
         s.invoke_convert_test();
         pRS.finish();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_convert_relaxed.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_convert_relaxed.java
index 728806c..a0757f3 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_convert_relaxed.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_convert_relaxed.java
@@ -31,7 +31,7 @@
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
         ScriptC_convert_relaxed s =
-                new ScriptC_convert_relaxed(pRS, mRes, R.raw.convert_relaxed);
+                new ScriptC_convert_relaxed(pRS);
         pRS.setMessageHandler(mRsMessage);
         s.invoke_convert_test();
         pRS.finish();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_copy_test.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_copy_test.java
new file mode 100644
index 0000000..380f6ec
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_copy_test.java
@@ -0,0 +1,120 @@
+/*
+ * 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+public class UT_copy_test extends UnitTest {
+    private Resources mRes;
+    boolean pass = true;
+
+    protected UT_copy_test(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Copy", ctx);
+        mRes = res;
+    }
+
+    void testFloat2(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_2(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_2(rs), 1024);
+
+        float[] f1 = new float[1024 * 2];
+        float[] f2 = new float[1024 * 2];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat2(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if (f1[ct] != f2[ct]) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    void testFloat3(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_3(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_3(rs), 1024);
+
+        float[] f1 = new float[1024 * 4];
+        float[] f2 = new float[1024 * 4];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat3(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if ((f1[ct] != f2[ct]) && ((ct&3) != 3)) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    void testFloat4(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_4(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_4(rs), 1024);
+
+        float[] f1 = new float[1024 * 4];
+        float[] f2 = new float[1024 * 4];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat4(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if (f1[ct] != f2[ct]) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_copy_test s = new ScriptC_copy_test(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        testFloat2(pRS, s);
+        testFloat3(pRS, s);
+        testFloat4(pRS, s);
+        s.invoke_sendResult(true);
+
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_element.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_element.java
index f52fe6ff..07bcc74 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_element.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_element.java
@@ -84,7 +84,7 @@
     }
 
     private void testScriptSide(RenderScript pRS) {
-        ScriptC_element s = new ScriptC_element(pRS, mRes, R.raw.element);
+        ScriptC_element s = new ScriptC_element(pRS);
         pRS.setMessageHandler(mRsMessage);
         initializeGlobals(pRS, s);
         s.invoke_element_test();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_foreach.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_foreach.java
index 04e9270..4951970 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_foreach.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_foreach.java
@@ -44,7 +44,7 @@
 
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
-        ScriptC_foreach s = new ScriptC_foreach(pRS, mRes, R.raw.foreach);
+        ScriptC_foreach s = new ScriptC_foreach(pRS);
         pRS.setMessageHandler(mRsMessage);
         initializeGlobals(pRS, s);
         s.forEach_root(A);
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_fp_mad.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_fp_mad.java
index f2c91af..5b7344d 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_fp_mad.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_fp_mad.java
@@ -30,7 +30,7 @@
 
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
-        ScriptC_fp_mad s = new ScriptC_fp_mad(pRS, mRes, R.raw.fp_mad);
+        ScriptC_fp_mad s = new ScriptC_fp_mad(pRS);
         pRS.setMessageHandler(mRsMessage);
         s.invoke_fp_mad_test(0, 0);
         pRS.finish();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_int4.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_int4.java
new file mode 100644
index 0000000..89a2a71
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_int4.java
@@ -0,0 +1,40 @@
+/*
+ * 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_int4 extends UnitTest {
+    private Resources mRes;
+
+    protected UT_int4(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "int4", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_int4 s = new ScriptC_int4(pRS, mRes, R.raw.int4);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_int4_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_kernel.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_kernel.java
new file mode 100644
index 0000000..e0bd33e
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_kernel.java
@@ -0,0 +1,60 @@
+/*
+ * 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+public class UT_kernel extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+    private Allocation B;
+
+    protected UT_kernel(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Kernels (pass-by-value)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_kernel s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        s.set_dimX(X);
+        typeBuilder.setX(X);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_ain(A);
+        B = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_aout(B);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_kernel s = new ScriptC_kernel(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_init_vars(A);
+        s.forEach_root(A, B);
+        s.invoke_verify_root();
+        s.invoke_kernel_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_kernel_struct.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_kernel_struct.java
new file mode 100644
index 0000000..8e22810
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_kernel_struct.java
@@ -0,0 +1,61 @@
+/*
+ * 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+public class UT_kernel_struct extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+    private Allocation B;
+
+    protected UT_kernel_struct(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Kernels (struct pass-by-value)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_kernel_struct s) {
+        int X = 5;
+        s.set_dimX(X);
+        ScriptField_simpleStruct t;
+        t = new ScriptField_simpleStruct(RS, X);
+        s.bind_ain(t);
+        A = t.getAllocation();
+        t = new ScriptField_simpleStruct(RS, X);
+        s.bind_aout(t);
+        B = t.getAllocation();
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_kernel_struct s = new ScriptC_kernel_struct(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_init_vars(A);
+        s.forEach_root(A, B);
+        s.invoke_verify_root();
+        s.invoke_kernel_struct_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math.java
index bf133be..8ad462b 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math.java
@@ -30,7 +30,7 @@
 
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
-        ScriptC_math s = new ScriptC_math(pRS, mRes, R.raw.math);
+        ScriptC_math s = new ScriptC_math(pRS);
         pRS.setMessageHandler(mRsMessage);
         s.invoke_math_test(0, 0);
         pRS.finish();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java
new file mode 100644
index 0000000..220509c
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java
@@ -0,0 +1,527 @@
+/*
+ * 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+import java.util.Arrays;
+import java.util.Random;
+
+public class UT_math_agree extends UnitTest {
+    private Resources mRes;
+    private Random rand;
+
+    protected UT_math_agree(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Math Agreement", ctx);
+        mRes = res;
+        rand = new Random();
+    }
+
+    // packing functions
+    private Float2 pack_f2(float[] val) {
+        assert val.length == 2;
+        return new Float2(val[0], val[1]);
+    }
+    private Float3 pack_f3(float[] val) {
+        assert val.length == 3;
+        return new Float3(val[0], val[1], val[2]);
+    }
+    private Float4 pack_f4(float[] val) {
+        assert val.length == 4;
+        return new Float4(val[0], val[1], val[2], val[3]);
+    }
+    private Byte2 pack_b2(byte[] val) {
+        assert val.length == 2;
+        return new Byte2(val[0], val[1]);
+    }
+    private Byte3 pack_b3(byte[] val) {
+        assert val.length == 3;
+        return new Byte3(val[0], val[1], val[2]);
+    }
+    private Byte4 pack_b4(byte[] val) {
+        assert val.length == 4;
+        return new Byte4(val[0], val[1], val[2], val[3]);
+    }
+    private Short2 pack_s2(short[] val) {
+        assert val.length == 2;
+        return new Short2(val[0], val[1]);
+    }
+    private Short3 pack_s3(short[] val) {
+        assert val.length == 3;
+        return new Short3(val[0], val[1], val[2]);
+    }
+    private Short4 pack_s4(short[] val) {
+        assert val.length == 4;
+        return new Short4(val[0], val[1], val[2], val[3]);
+    }
+    private Int2 pack_i2(int[] val) {
+        assert val.length == 2;
+        return new Int2(val[0], val[1]);
+    }
+    private Int3 pack_i3(int[] val) {
+        assert val.length == 3;
+        return new Int3(val[0], val[1], val[2]);
+    }
+    private Int4 pack_i4(int[] val) {
+        assert val.length == 4;
+        return new Int4(val[0], val[1], val[2], val[3]);
+    }
+    private Long2 pack_l2(long[] val) {
+        assert val.length == 2;
+        return new Long2(val[0], val[1]);
+    }
+    private Long3 pack_l3(long[] val) {
+        assert val.length == 3;
+        return new Long3(val[0], val[1], val[2]);
+    }
+    private Long4 pack_l4(long[] val) {
+        assert val.length == 4;
+        return new Long4(val[0], val[1], val[2], val[3]);
+    }
+
+    // random vector generation functions
+    private float[] randvec_float(int dim) {
+        float[] fv = new float[dim];
+        for (int i = 0; i < dim; ++i)
+            fv[i] = rand.nextFloat();
+        return fv;
+    }
+    private byte[] randvec_char(int dim) {
+        byte[] cv = new byte[dim];
+        rand.nextBytes(cv);
+        return cv;
+    }
+    private short[] randvec_uchar(int dim) {
+       short[] ucv = new short[dim];
+       for (int i = 0; i < dim; ++i)
+           ucv[i] = (short)rand.nextInt(0x1 << 8);
+       return ucv;
+    }
+    private short[] randvec_short(int dim) {
+        short[] sv = new short[dim];
+        for (int i = 0; i < dim; ++i)
+            sv[i] = (short)rand.nextInt(0x1 << 16);
+        return sv;
+    }
+    private int[] randvec_ushort(int dim) {
+        int[] usv = new int[dim];
+        for (int i = 0; i < dim; ++i)
+            usv[i] = rand.nextInt(0x1 << 16);
+        return usv;
+    }
+    private int[] randvec_int(int dim) {
+        int[] iv = new int[dim];
+        for (int i = 0; i < dim; ++i)
+            iv[i] = rand.nextInt();
+        return iv;
+    }
+    private long[] randvec_uint(int dim) {
+        long[] uiv = new long[dim];
+        for (int i = 0; i < dim; ++i)
+            uiv[i] = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        return uiv;
+    }
+    private long[] randvec_long(int dim) {
+        long[] lv = new long[dim];
+        for (int i = 0; i < dim; ++i)
+            lv[i] = rand.nextLong();
+        return lv;
+    }
+    // TODO:  unsigned long generator
+
+    // min reference functions
+    private float min(float v1, float v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private float[] min(float[] v1, float[] v2) {
+        assert v1.length == v2.length;
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private byte min(byte v1, byte v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private byte[] min(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private short min(short v1, short v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private short[] min(short[] v1, short[] v2) {
+        assert v1.length == v2.length;
+        short[] rv = new short[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private int min(int v1, int v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private int[] min(int[] v1, int[] v2) {
+        assert v1.length == v2.length;
+        int[] rv = new int[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private long min(long v1, long v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private long[] min(long[] v1, long[] v2) {
+        assert v1.length == v2.length;
+        long[] rv = new long[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    // TODO:  unsigned long version of min
+
+    // max reference functions
+    private float max(float v1, float v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private float[] max(float[] v1, float[] v2) {
+        assert v1.length == v2.length;
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private byte max(byte v1, byte v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private byte[] max(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private short max(short v1, short v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private short[] max(short[] v1, short[] v2) {
+        assert v1.length == v2.length;
+        short[] rv = new short[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private int max(int v1, int v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private int[] max(int[] v1, int[] v2) {
+        assert v1.length == v2.length;
+        int[] rv = new int[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private long max(long v1, long v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private long[] max(long[] v1, long[] v2) {
+        assert v1.length == v2.length;
+        long[] rv = new long[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    // TODO:  unsigned long version of max
+
+    // fmin reference functions
+    private float fmin(float v1, float v2) {
+        return min(v1, v2);
+    }
+    private float[] fmin(float[] v1, float[] v2) {
+        return min(v1, v2);
+    }
+    private float[] fmin(float[] v1, float v2) {
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2);
+        return rv;
+    }
+
+    // fmax reference functions
+    private float fmax(float v1, float v2) {
+        return max(v1, v2);
+    }
+    private float[] fmax(float[] v1, float[] v2) {
+        return max(v1, v2);
+    }
+    private float[] fmax(float[] v1, float v2) {
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2);
+        return rv;
+    }
+
+    private void initializeValues(ScriptC_math_agree s) {
+        float x = rand.nextFloat();
+        float y = rand.nextFloat();
+
+        s.set_x(x);
+        s.set_y(y);
+        s.set_result_add(x + y);
+        s.set_result_sub(x - y);
+        s.set_result_mul(x * y);
+        s.set_result_div(x / y);
+
+        // Generate random vectors of all types
+        float rand_f1_0 = rand.nextFloat();
+        float[] rand_f2_0 = randvec_float(2);
+        float[] rand_f3_0 = randvec_float(3);
+        float[] rand_f4_0 = randvec_float(4);
+        float rand_f1_1 = rand.nextFloat();
+        float[] rand_f2_1 = randvec_float(2);
+        float[] rand_f3_1 = randvec_float(3);
+        float[] rand_f4_1 = randvec_float(4);
+        short rand_uc1_0 = (short)rand.nextInt(0x1 << 8);
+        short[] rand_uc2_0 = randvec_uchar(2);
+        short[] rand_uc3_0 = randvec_uchar(3);
+        short[] rand_uc4_0 = randvec_uchar(4);
+        short rand_uc1_1 = (short)rand.nextInt(0x1 << 8);
+        short[] rand_uc2_1 = randvec_uchar(2);
+        short[] rand_uc3_1 = randvec_uchar(3);
+        short[] rand_uc4_1 = randvec_uchar(4);
+        short rand_ss1_0 = (short)rand.nextInt(0x1 << 16);
+        short[] rand_ss2_0 = randvec_short(2);
+        short[] rand_ss3_0 = randvec_short(3);
+        short[] rand_ss4_0 = randvec_short(4);
+        short rand_ss1_1 = (short)rand.nextInt(0x1 << 16);
+        short[] rand_ss2_1 = randvec_short(2);
+        short[] rand_ss3_1 = randvec_short(3);
+        short[] rand_ss4_1 = randvec_short(4);
+        int rand_us1_0 = rand.nextInt(0x1 << 16);
+        int[] rand_us2_0 = randvec_ushort(2);
+        int[] rand_us3_0 = randvec_ushort(3);
+        int[] rand_us4_0 = randvec_ushort(4);
+        int rand_us1_1 = rand.nextInt(0x1 << 16);
+        int[] rand_us2_1 = randvec_ushort(2);
+        int[] rand_us3_1 = randvec_ushort(3);
+        int[] rand_us4_1 = randvec_ushort(4);
+        int rand_si1_0 = rand.nextInt();
+        int[] rand_si2_0 = randvec_int(2);
+        int[] rand_si3_0 = randvec_int(3);
+        int[] rand_si4_0 = randvec_int(4);
+        int rand_si1_1 = rand.nextInt();
+        int[] rand_si2_1 = randvec_int(2);
+        int[] rand_si3_1 = randvec_int(3);
+        int[] rand_si4_1 = randvec_int(4);
+        long rand_ui1_0 = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        long[] rand_ui2_0 = randvec_uint(2);
+        long[] rand_ui3_0 = randvec_uint(3);
+        long[] rand_ui4_0 = randvec_uint(4);
+        long rand_ui1_1 = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        long[] rand_ui2_1 = randvec_uint(2);
+        long[] rand_ui3_1 = randvec_uint(3);
+        long[] rand_ui4_1 = randvec_uint(4);
+        long rand_sl1_0 = rand.nextLong();
+        long[] rand_sl2_0 = randvec_long(2);
+        long[] rand_sl3_0 = randvec_long(3);
+        long[] rand_sl4_0 = randvec_long(4);
+        long rand_sl1_1 = rand.nextLong();
+        long[] rand_sl2_1 = randvec_long(2);
+        long[] rand_sl3_1 = randvec_long(3);
+        long[] rand_sl4_1 = randvec_long(4);
+        byte rand_sc1_0 = (byte)rand.nextInt(0x1 << 8);
+        byte[] rand_sc2_0 = randvec_char(2);
+        byte[] rand_sc3_0 = randvec_char(3);
+        byte[] rand_sc4_0 = randvec_char(4);
+        byte rand_sc1_1 = (byte)rand.nextInt(0x1 << 8);
+        byte[] rand_sc2_1 = randvec_char(2);
+        byte[] rand_sc3_1 = randvec_char(3);
+        byte[] rand_sc4_1 = randvec_char(4);
+        // TODO:  generate unsigned long vectors
+
+        // Set random vectors in renderscript code
+        s.set_rand_f1_0(rand_f1_0);
+        s.set_rand_f2_0(pack_f2(rand_f2_0));
+        s.set_rand_f3_0(pack_f3(rand_f3_0));
+        s.set_rand_f4_0(pack_f4(rand_f4_0));
+        s.set_rand_f1_1(rand_f1_1);
+        s.set_rand_f2_1(pack_f2(rand_f2_1));
+        s.set_rand_f3_1(pack_f3(rand_f3_1));
+        s.set_rand_f4_1(pack_f4(rand_f4_1));
+        s.set_rand_uc1_1(rand_uc1_1);
+        s.set_rand_uc2_1(pack_s2(rand_uc2_1));
+        s.set_rand_uc3_1(pack_s3(rand_uc3_1));
+        s.set_rand_uc4_1(pack_s4(rand_uc4_1));
+        s.set_rand_ss1_0(rand_ss1_0);
+        s.set_rand_ss2_0(pack_s2(rand_ss2_0));
+        s.set_rand_ss3_0(pack_s3(rand_ss3_0));
+        s.set_rand_ss4_0(pack_s4(rand_ss4_0));
+        s.set_rand_ss1_1(rand_ss1_1);
+        s.set_rand_ss2_1(pack_s2(rand_ss2_1));
+        s.set_rand_ss3_1(pack_s3(rand_ss3_1));
+        s.set_rand_ss4_1(pack_s4(rand_ss4_1));
+        s.set_rand_us1_0(rand_us1_0);
+        s.set_rand_us2_0(pack_i2(rand_us2_0));
+        s.set_rand_us3_0(pack_i3(rand_us3_0));
+        s.set_rand_us4_0(pack_i4(rand_us4_0));
+        s.set_rand_us1_1(rand_us1_1);
+        s.set_rand_us2_1(pack_i2(rand_us2_1));
+        s.set_rand_us3_1(pack_i3(rand_us3_1));
+        s.set_rand_us4_1(pack_i4(rand_us4_1));
+        s.set_rand_si1_0(rand_si1_0);
+        s.set_rand_si2_0(pack_i2(rand_si2_0));
+        s.set_rand_si3_0(pack_i3(rand_si3_0));
+        s.set_rand_si4_0(pack_i4(rand_si4_0));
+        s.set_rand_si1_1(rand_si1_1);
+        s.set_rand_si2_1(pack_i2(rand_si2_1));
+        s.set_rand_si3_1(pack_i3(rand_si3_1));
+        s.set_rand_si4_1(pack_i4(rand_si4_1));
+        s.set_rand_ui1_0(rand_ui1_0);
+        s.set_rand_ui2_0(pack_l2(rand_ui2_0));
+        s.set_rand_ui3_0(pack_l3(rand_ui3_0));
+        s.set_rand_ui4_0(pack_l4(rand_ui4_0));
+        s.set_rand_ui1_1(rand_ui1_1);
+        s.set_rand_ui2_1(pack_l2(rand_ui2_1));
+        s.set_rand_ui3_1(pack_l3(rand_ui3_1));
+        s.set_rand_ui4_1(pack_l4(rand_ui4_1));
+        s.set_rand_sl1_0(rand_sl1_0);
+        s.set_rand_sl2_0(pack_l2(rand_sl2_0));
+        s.set_rand_sl3_0(pack_l3(rand_sl3_0));
+        s.set_rand_sl4_0(pack_l4(rand_sl4_0));
+        s.set_rand_sl1_1(rand_sl1_1);
+        s.set_rand_sl2_1(pack_l2(rand_sl2_1));
+        s.set_rand_sl3_1(pack_l3(rand_sl3_1));
+        s.set_rand_sl4_1(pack_l4(rand_sl4_1));
+        s.set_rand_uc1_0(rand_uc1_0);
+        s.set_rand_uc2_0(pack_s2(rand_uc2_0));
+        s.set_rand_uc3_0(pack_s3(rand_uc3_0));
+        s.set_rand_uc4_0(pack_s4(rand_uc4_0));
+        s.set_rand_sc1_0(rand_sc1_0);
+        s.set_rand_sc2_0(pack_b2(rand_sc2_0));
+        s.set_rand_sc3_0(pack_b3(rand_sc3_0));
+        s.set_rand_sc4_0(pack_b4(rand_sc4_0));
+        s.set_rand_sc1_1(rand_sc1_1);
+        s.set_rand_sc2_1(pack_b2(rand_sc2_1));
+        s.set_rand_sc3_1(pack_b3(rand_sc3_1));
+        s.set_rand_sc4_1(pack_b4(rand_sc4_1));
+        // TODO:  set unsigned long vectors
+
+        // Set results for min
+        s.set_min_rand_f1_f1(min(rand_f1_0, rand_f1_1));
+        s.set_min_rand_f2_f2(pack_f2(min(rand_f2_0, rand_f2_1)));
+        s.set_min_rand_f3_f3(pack_f3(min(rand_f3_0, rand_f3_1)));
+        s.set_min_rand_f4_f4(pack_f4(min(rand_f4_0, rand_f4_1)));
+        s.set_min_rand_uc1_uc1(min(rand_uc1_0, rand_uc1_1));
+        s.set_min_rand_uc2_uc2(pack_s2(min(rand_uc2_0, rand_uc2_1)));
+        s.set_min_rand_uc3_uc3(pack_s3(min(rand_uc3_0, rand_uc3_1)));
+        s.set_min_rand_uc4_uc4(pack_s4(min(rand_uc4_0, rand_uc4_1)));
+        s.set_min_rand_ss1_ss1(min(rand_ss1_0, rand_ss1_1));
+        s.set_min_rand_ss2_ss2(pack_s2(min(rand_ss2_0, rand_ss2_1)));
+        s.set_min_rand_ss3_ss3(pack_s3(min(rand_ss3_0, rand_ss3_1)));
+        s.set_min_rand_ss4_ss4(pack_s4(min(rand_ss4_0, rand_ss4_1)));
+        s.set_min_rand_us1_us1(min(rand_us1_0, rand_us1_1));
+        s.set_min_rand_us2_us2(pack_i2(min(rand_us2_0, rand_us2_1)));
+        s.set_min_rand_us3_us3(pack_i3(min(rand_us3_0, rand_us3_1)));
+        s.set_min_rand_us4_us4(pack_i4(min(rand_us4_0, rand_us4_1)));
+        s.set_min_rand_si1_si1(min(rand_si1_0, rand_si1_1));
+        s.set_min_rand_si2_si2(pack_i2(min(rand_si2_0, rand_si2_1)));
+        s.set_min_rand_si3_si3(pack_i3(min(rand_si3_0, rand_si3_1)));
+        s.set_min_rand_si4_si4(pack_i4(min(rand_si4_0, rand_si4_1)));
+        s.set_min_rand_ui1_ui1(min(rand_ui1_0, rand_ui1_1));
+        s.set_min_rand_ui2_ui2(pack_l2(min(rand_ui2_0, rand_ui2_1)));
+        s.set_min_rand_ui3_ui3(pack_l3(min(rand_ui3_0, rand_ui3_1)));
+        s.set_min_rand_ui4_ui4(pack_l4(min(rand_ui4_0, rand_ui4_1)));
+        s.set_min_rand_sl1_sl1(min(rand_sl1_0, rand_sl1_1));
+        s.set_min_rand_sl2_sl2(pack_l2(min(rand_sl2_0, rand_sl2_1)));
+        s.set_min_rand_sl3_sl3(pack_l3(min(rand_sl3_0, rand_sl3_1)));
+        s.set_min_rand_sl4_sl4(pack_l4(min(rand_sl4_0, rand_sl4_1)));
+        s.set_min_rand_sc1_sc1(min(rand_sc1_0, rand_sc1_1));
+        s.set_min_rand_sc2_sc2(pack_b2(min(rand_sc2_0, rand_sc2_1)));
+        s.set_min_rand_sc3_sc3(pack_b3(min(rand_sc3_0, rand_sc3_1)));
+        s.set_min_rand_sc4_sc4(pack_b4(min(rand_sc4_0, rand_sc4_1)));
+        // TODO:  set results for unsigned long min
+
+        // Set results for max
+        s.set_max_rand_f1_f1(max(rand_f1_0, rand_f1_1));
+        s.set_max_rand_f2_f2(pack_f2(max(rand_f2_0, rand_f2_1)));
+        s.set_max_rand_f3_f3(pack_f3(max(rand_f3_0, rand_f3_1)));
+        s.set_max_rand_f4_f4(pack_f4(max(rand_f4_0, rand_f4_1)));
+        s.set_max_rand_uc1_uc1(max(rand_uc1_0, rand_uc1_1));
+        s.set_max_rand_uc2_uc2(pack_s2(max(rand_uc2_0, rand_uc2_1)));
+        s.set_max_rand_uc3_uc3(pack_s3(max(rand_uc3_0, rand_uc3_1)));
+        s.set_max_rand_uc4_uc4(pack_s4(max(rand_uc4_0, rand_uc4_1)));
+        s.set_max_rand_ss1_ss1(max(rand_ss1_0, rand_ss1_1));
+        s.set_max_rand_ss2_ss2(pack_s2(max(rand_ss2_0, rand_ss2_1)));
+        s.set_max_rand_ss3_ss3(pack_s3(max(rand_ss3_0, rand_ss3_1)));
+        s.set_max_rand_ss4_ss4(pack_s4(max(rand_ss4_0, rand_ss4_1)));
+        s.set_max_rand_us1_us1(max(rand_us1_0, rand_us1_1));
+        s.set_max_rand_us2_us2(pack_i2(max(rand_us2_0, rand_us2_1)));
+        s.set_max_rand_us3_us3(pack_i3(max(rand_us3_0, rand_us3_1)));
+        s.set_max_rand_us4_us4(pack_i4(max(rand_us4_0, rand_us4_1)));
+        s.set_max_rand_si1_si1(max(rand_si1_0, rand_si1_1));
+        s.set_max_rand_si2_si2(pack_i2(max(rand_si2_0, rand_si2_1)));
+        s.set_max_rand_si3_si3(pack_i3(max(rand_si3_0, rand_si3_1)));
+        s.set_max_rand_si4_si4(pack_i4(max(rand_si4_0, rand_si4_1)));
+        s.set_max_rand_ui1_ui1(max(rand_ui1_0, rand_ui1_1));
+        s.set_max_rand_ui2_ui2(pack_l2(max(rand_ui2_0, rand_ui2_1)));
+        s.set_max_rand_ui3_ui3(pack_l3(max(rand_ui3_0, rand_ui3_1)));
+        s.set_max_rand_ui4_ui4(pack_l4(max(rand_ui4_0, rand_ui4_1)));
+        s.set_max_rand_sl1_sl1(max(rand_sl1_0, rand_sl1_1));
+        s.set_max_rand_sl2_sl2(pack_l2(max(rand_sl2_0, rand_sl2_1)));
+        s.set_max_rand_sl3_sl3(pack_l3(max(rand_sl3_0, rand_sl3_1)));
+        s.set_max_rand_sl4_sl4(pack_l4(max(rand_sl4_0, rand_sl4_1)));
+        s.set_max_rand_sc1_sc1(max(rand_sc1_0, rand_sc1_1));
+        s.set_max_rand_sc2_sc2(pack_b2(max(rand_sc2_0, rand_sc2_1)));
+        s.set_max_rand_sc3_sc3(pack_b3(max(rand_sc3_0, rand_sc3_1)));
+        s.set_max_rand_sc4_sc4(pack_b4(max(rand_sc4_0, rand_sc4_1)));
+
+        // TODO:  set results for unsigned long max
+
+        // Set results for fmin
+        s.set_fmin_rand_f1_f1(fmin(rand_f1_0, rand_f1_1));
+        s.set_fmin_rand_f2_f2(pack_f2(fmin(rand_f2_0, rand_f2_1)));
+        s.set_fmin_rand_f3_f3(pack_f3(fmin(rand_f3_0, rand_f3_1)));
+        s.set_fmin_rand_f4_f4(pack_f4(fmin(rand_f4_0, rand_f4_1)));
+        s.set_fmin_rand_f2_f1(pack_f2(fmin(rand_f2_0, rand_f1_1)));
+        s.set_fmin_rand_f3_f1(pack_f3(fmin(rand_f3_0, rand_f1_1)));
+        s.set_fmin_rand_f4_f1(pack_f4(fmin(rand_f4_0, rand_f1_1)));
+
+        // Set results for fmax
+        s.set_fmax_rand_f1_f1(fmax(rand_f1_0, rand_f1_1));
+        s.set_fmax_rand_f2_f2(pack_f2(fmax(rand_f2_0, rand_f2_1)));
+        s.set_fmax_rand_f3_f3(pack_f3(fmax(rand_f3_0, rand_f3_1)));
+        s.set_fmax_rand_f4_f4(pack_f4(fmax(rand_f4_0, rand_f4_1)));
+        s.set_fmax_rand_f2_f1(pack_f2(fmax(rand_f2_0, rand_f1_1)));
+        s.set_fmax_rand_f3_f1(pack_f3(fmax(rand_f3_0, rand_f1_1)));
+        s.set_fmax_rand_f4_f1(pack_f4(fmax(rand_f4_0, rand_f1_1)));
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_math_agree s = new ScriptC_math_agree(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeValues(s);
+        s.invoke_math_agree_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_conformance.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_conformance.java
index f256a3a..620eeb5 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_conformance.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_conformance.java
@@ -31,7 +31,7 @@
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
         ScriptC_math_conformance s =
-                new ScriptC_math_conformance(pRS, mRes, R.raw.math_conformance);
+                new ScriptC_math_conformance(pRS);
         pRS.setMessageHandler(mRsMessage);
         s.invoke_math_conformance_test();
         pRS.finish();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_mesh.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_mesh.java
index 0c93702..29e5025 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_mesh.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_mesh.java
@@ -54,7 +54,7 @@
     }
 
     private void testScriptSide(RenderScript pRS) {
-        ScriptC_mesh s = new ScriptC_mesh(pRS, mRes, R.raw.mesh);
+        ScriptC_mesh s = new ScriptC_mesh(pRS);
         pRS.setMessageHandler(mRsMessage);
         initializeGlobals(pRS, s);
         s.invoke_mesh_test();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_min.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_min.java
new file mode 100644
index 0000000..137cae9
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_min.java
@@ -0,0 +1,40 @@
+/*
+ * 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_min extends UnitTest {
+    private Resources mRes;
+
+    protected UT_min(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Min (relaxed)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_min s = new ScriptC_min(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_min_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_noroot.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_noroot.java
index c660fc5..cc48591 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_noroot.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_noroot.java
@@ -44,7 +44,7 @@
 
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
-        ScriptC_noroot s = new ScriptC_noroot(pRS, mRes, R.raw.noroot);
+        ScriptC_noroot s = new ScriptC_noroot(pRS);
         pRS.setMessageHandler(mRsMessage);
         initializeGlobals(pRS, s);
         s.forEach_foo(A, A);
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_primitives.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_primitives.java
index 18829c2..c1234f0 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_primitives.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_primitives.java
@@ -89,7 +89,7 @@
 
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
-        ScriptC_primitives s = new ScriptC_primitives(pRS, mRes, R.raw.primitives);
+        ScriptC_primitives s = new ScriptC_primitives(pRS);
         pRS.setMessageHandler(mRsMessage);
         if (!initializeGlobals(s)) {
             failTest();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_raster.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_raster.java
index ca54ac4..046a215 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_raster.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_raster.java
@@ -51,7 +51,7 @@
     }
 
     private void testScriptSide(RenderScript pRS) {
-        ScriptC_program_raster s = new ScriptC_program_raster(pRS, mRes, R.raw.program_raster);
+        ScriptC_program_raster s = new ScriptC_program_raster(pRS);
         pRS.setMessageHandler(mRsMessage);
         initializeGlobals(pRS, s);
         s.invoke_program_raster_test();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_store.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_store.java
index 4410ee3..6510b6b 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_store.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_store.java
@@ -94,7 +94,7 @@
     }
 
     private void testScriptSide(RenderScript pRS) {
-        ScriptC_program_store s = new ScriptC_program_store(pRS, mRes, R.raw.program_store);
+        ScriptC_program_store s = new ScriptC_program_store(pRS);
         pRS.setMessageHandler(mRsMessage);
         initializeGlobals(pRS, s);
         s.invoke_program_store_test();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_refcount.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_refcount.java
index 6bb28f8..22bbd2f 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_refcount.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_refcount.java
@@ -40,7 +40,7 @@
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
         pRS.setMessageHandler(mRsMessage);
-        ScriptC_refcount s = new ScriptC_refcount(pRS, mRes, R.raw.refcount);
+        ScriptC_refcount s = new ScriptC_refcount(pRS);
         initializeGlobals(pRS, s);
         s.invoke_refcount_test();
         pRS.finish();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rsdebug.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rsdebug.java
index 0614b1a..548288b 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rsdebug.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rsdebug.java
@@ -30,7 +30,7 @@
 
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
-        ScriptC_rsdebug s = new ScriptC_rsdebug(pRS, mRes, R.raw.rsdebug);
+        ScriptC_rsdebug s = new ScriptC_rsdebug(pRS);
         pRS.setMessageHandler(mRsMessage);
         s.invoke_test_rsdebug(0, 0);
         pRS.finish();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rstime.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rstime.java
index 21e657c..f000412 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rstime.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rstime.java
@@ -30,7 +30,7 @@
 
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
-        ScriptC_rstime s = new ScriptC_rstime(pRS, mRes, R.raw.rstime);
+        ScriptC_rstime s = new ScriptC_rstime(pRS);
         pRS.setMessageHandler(mRsMessage);
         s.setTimeZone("America/Los_Angeles");
         s.invoke_test_rstime(0, 0);
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rstypes.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rstypes.java
index 74211c8..f677f10 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rstypes.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rstypes.java
@@ -30,7 +30,7 @@
 
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
-        ScriptC_rstypes s = new ScriptC_rstypes(pRS, mRes, R.raw.rstypes);
+        ScriptC_rstypes s = new ScriptC_rstypes(pRS);
         pRS.setMessageHandler(mRsMessage);
         s.invoke_test_rstypes(0, 0);
         pRS.finish();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_sampler.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_sampler.java
index c328cf6..00c850c 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_sampler.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_sampler.java
@@ -75,7 +75,7 @@
     }
 
     private void testScriptSide(RenderScript pRS) {
-        ScriptC_sampler s = new ScriptC_sampler(pRS, mRes, R.raw.sampler);
+        ScriptC_sampler s = new ScriptC_sampler(pRS);
         pRS.setMessageHandler(mRsMessage);
         initializeGlobals(pRS, s);
         s.invoke_sampler_test();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_struct.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_struct.java
index 2a55686..6f47b72 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_struct.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_struct.java
@@ -30,7 +30,7 @@
 
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
-        ScriptC_struct s = new ScriptC_struct(pRS, mRes, R.raw.struct);
+        ScriptC_struct s = new ScriptC_struct(pRS);
         pRS.setMessageHandler(mRsMessage);
 
         ScriptField_Point2 p = new ScriptField_Point2(pRS, 1);
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_unsigned.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_unsigned.java
new file mode 100644
index 0000000..9ea0f8a
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_unsigned.java
@@ -0,0 +1,60 @@
+/*
+ * 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_unsigned extends UnitTest {
+    private Resources mRes;
+
+    protected UT_unsigned(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Unsigned", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_unsigned s) {
+        short pUC = s.get_uc();
+        if (pUC != 5) {
+            return false;
+        }
+        s.set_uc((short)129);
+
+        long pUI = s.get_ui();
+        if (pUI != 37) {
+            return false;
+        }
+        s.set_ui(0x7fffffff);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_unsigned s = new ScriptC_unsigned(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            failTest();
+        } else {
+            s.invoke_unsigned_test();
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_vector.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_vector.java
index 0ac09ca..91cc0af 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_vector.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_vector.java
@@ -304,7 +304,7 @@
 
     public void run() {
         RenderScript pRS = RenderScript.create(mCtx);
-        ScriptC_vector s = new ScriptC_vector(pRS, mRes, R.raw.vector);
+        ScriptC_vector s = new ScriptC_vector(pRS);
         pRS.setMessageHandler(mRsMessage);
         if (!initializeGlobals(s)) {
             failTest();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/bug_char.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/bug_char.rs
new file mode 100644
index 0000000..dcd7b72
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/bug_char.rs
@@ -0,0 +1,47 @@
+#include "shared.rsh"
+
+char rand_sc1_0, rand_sc1_1;
+char2 rand_sc2_0, rand_sc2_1;
+
+char min_rand_sc1_sc1;
+char2 min_rand_sc2_sc2;
+
+static bool test_bug_char() {
+    bool failed = false;
+
+    rsDebug("rand_sc2_0.x: ", rand_sc2_0.x);
+    rsDebug("rand_sc2_0.y: ", rand_sc2_0.y);
+    rsDebug("rand_sc2_1.x: ", rand_sc2_1.x);
+    rsDebug("rand_sc2_1.y: ", rand_sc2_1.y);
+    char temp_sc1;
+    char2 temp_sc2;
+
+    temp_sc1 = min( rand_sc1_0, rand_sc1_1 );
+    if (temp_sc1 != min_rand_sc1_sc1) {
+        rsDebug("temp_sc1", temp_sc1);
+        failed = true;
+    }
+    rsDebug("broken", 'y');
+
+    temp_sc2 = min( rand_sc2_0, rand_sc2_1 );
+    if (temp_sc2.x != min_rand_sc2_sc2.x
+            || temp_sc2.y != min_rand_sc2_sc2.y) {
+        failed = true;
+    }
+
+
+    return failed;
+}
+
+void bug_char_test() {
+    bool failed = false;
+    failed |= test_bug_char();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/copy_test.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/copy_test.rs
new file mode 100644
index 0000000..f4243eb
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/copy_test.rs
@@ -0,0 +1,41 @@
+/*
+ * 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 "shared.rsh"
+
+void sendResult(bool pass) {
+    if (pass) {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+}
+
+
+float2 __attribute((kernel)) copyFloat2(float2 i) {
+    return i;
+}
+
+float3 __attribute((kernel)) copyFloat3(float3 i) {
+    return i;
+}
+
+float4 __attribute((kernel)) copyFloat4(float4 i) {
+    return i;
+}
+
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/int4.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/int4.rs
new file mode 100644
index 0000000..c791cab
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/int4.rs
@@ -0,0 +1,29 @@
+#include "shared.rsh"
+#pragma rs_fp_relaxed
+
+uchar4 u4 = 4;
+int4 gi4 = {2, 2, 2, 2};
+
+void int4_test() {
+    bool failed = false;
+    int4 i4 = {u4.x, u4.y, u4.z, u4.w};
+    i4 *= gi4;
+
+    rsDebug("i4.x", i4.x);
+    rsDebug("i4.y", i4.y);
+    rsDebug("i4.z", i4.z);
+    rsDebug("i4.w", i4.w);
+
+    _RS_ASSERT(i4.x == 8);
+    _RS_ASSERT(i4.y == 8);
+    _RS_ASSERT(i4.z == 8);
+    _RS_ASSERT(i4.w == 8);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/kernel.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/kernel.rs
new file mode 100644
index 0000000..d6c9df3
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/kernel.rs
@@ -0,0 +1,47 @@
+#include "shared.rsh"
+
+int *ain;
+int *aout;
+int dimX;
+static bool failed = false;
+
+void init_vars(int *out) {
+    *out = 7;
+}
+
+
+int __attribute__((kernel)) root(int ain, uint32_t x) {
+    _RS_ASSERT(ain == 7);
+    return ain + x;
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i;
+
+    for (i = 0; i < dimX; i++) {
+        _RS_ASSERT(aout[i] == (i + ain[i]));
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void kernel_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/kernel_struct.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/kernel_struct.rs
new file mode 100644
index 0000000..62c30ae
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/kernel_struct.rs
@@ -0,0 +1,66 @@
+#include "shared.rsh"
+
+struct simpleStruct {
+    int i1;
+    char ignored1;
+    float f1;
+    int i2;
+    char ignored2;
+    float f2;
+};
+
+struct simpleStruct *ain;
+struct simpleStruct *aout;
+int dimX;
+static bool failed = false;
+
+void init_vars(struct simpleStruct *out, uint32_t x) {
+    out->i1 = 0;
+    out->f1 = 0.f;
+    out->i2 = 1;
+    out->f2 = 1.0f;
+}
+
+struct simpleStruct __attribute__((kernel))
+        root(struct simpleStruct in, uint32_t x) {
+    struct simpleStruct s;
+    s.i1 = in.i1 + x;
+    s.f1 = in.f1 + x;
+    s.i2 = in.i2 + x;
+    s.f2 = in.f2 + x;
+    return s;
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i;
+
+    for (i = 0; i < dimX; i++) {
+        _RS_ASSERT(aout[i].i1 == (i + ain[i].i1));
+        _RS_ASSERT(aout[i].f1 == (i + ain[i].f1));
+        _RS_ASSERT(aout[i].i2 == (i + ain[i].i2));
+        _RS_ASSERT(aout[i].f2 == (i + ain[i].f2));
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void kernel_struct_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/math_agree.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/math_agree.rs
new file mode 100644
index 0000000..5bfbb2b
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/math_agree.rs
@@ -0,0 +1,409 @@
+#include "shared.rsh"
+//#pragma rs_fp_relaxed
+
+volatile float x = 0.0f;
+volatile float y = 0.0f;
+volatile float result_add = 0.0f;
+volatile float result_sub = 0.0f;
+volatile float result_mul = 0.0f;
+volatile float result_div = 0.0f;
+
+#define DECLARE_INPUT_SET(type, abbrev)         \
+volatile type    rand_##abbrev##1_0, rand_##abbrev##1_1; \
+volatile type##2 rand_##abbrev##2_0, rand_##abbrev##2_1; \
+volatile type##3 rand_##abbrev##3_0, rand_##abbrev##3_1; \
+volatile type##4 rand_##abbrev##4_0, rand_##abbrev##4_1;
+
+#define DECLARE_ALL_INPUT_SETS()    \
+DECLARE_INPUT_SET(float, f);        \
+DECLARE_INPUT_SET(char, sc);        \
+DECLARE_INPUT_SET(uchar, uc);       \
+DECLARE_INPUT_SET(short, ss);       \
+DECLARE_INPUT_SET(ushort, us);      \
+DECLARE_INPUT_SET(int, si);         \
+DECLARE_INPUT_SET(uint, ui);        \
+DECLARE_INPUT_SET(long, sl);        \
+DECLARE_INPUT_SET(ulong, ul);
+
+DECLARE_ALL_INPUT_SETS();
+
+#define DECLARE_REFERENCE_SET_VEC_VEC(type, abbrev, func)   \
+volatile type    func##_rand_##abbrev##1_##abbrev##1;                \
+volatile type##2 func##_rand_##abbrev##2_##abbrev##2;                \
+volatile type##3 func##_rand_##abbrev##3_##abbrev##3;                \
+volatile type##4 func##_rand_##abbrev##4_##abbrev##4;
+#define DECLARE_REFERENCE_SET_VEC_SCL(type, abbrev, func)   \
+volatile type##2 func##_rand_##abbrev##2_##abbrev##1;                \
+volatile type##3 func##_rand_##abbrev##3_##abbrev##1;                \
+volatile type##4 func##_rand_##abbrev##4_##abbrev##1;
+
+#define DECLARE_ALL_REFERENCE_SETS_VEC_VEC(func)    \
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(char, sc, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(uchar, uc, func);     \
+DECLARE_REFERENCE_SET_VEC_VEC(short, ss, func);     \
+DECLARE_REFERENCE_SET_VEC_VEC(ushort, us, func);    \
+DECLARE_REFERENCE_SET_VEC_VEC(int, si, func);       \
+DECLARE_REFERENCE_SET_VEC_VEC(uint, ui, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(long, sl, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(ulong, ul, func);
+
+DECLARE_ALL_REFERENCE_SETS_VEC_VEC(min);
+DECLARE_ALL_REFERENCE_SETS_VEC_VEC(max);
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, fmin);
+DECLARE_REFERENCE_SET_VEC_SCL(float, f, fmin);
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, fmax);
+DECLARE_REFERENCE_SET_VEC_SCL(float, f, fmax);
+
+static void fail_f1(float v1, float v2, float actual, float expected, char *op_name) {
+    int dist = float_dist(actual, expected);
+    rsDebug("float operation did not match!", op_name);
+    rsDebug("v1", v1);
+    rsDebug("v2", v2);
+    rsDebug("Dalvik result", expected);
+    rsDebug("Renderscript result", actual);
+    rsDebug("ULP difference", dist);
+}
+
+static void fail_f2(float2 v1, float2 v2, float2 actual, float2 expected, char *op_name) {
+    int2 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    rsDebug("float2 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+}
+
+static void fail_f3(float3 v1, float3 v2, float3 actual, float3 expected, char *op_name) {
+    int3 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    dist.z = float_dist(actual.z, expected.z);
+    rsDebug("float3 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v1.z", v1.z);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("v2.z", v2.z);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Dalvik result .z", expected.z);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("Renderscript result .z", actual.z);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+    rsDebug("ULP difference .z", dist.z);
+}
+
+static void fail_f4(float4 v1, float4 v2, float4 actual, float4 expected, char *op_name) {
+    int4 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    dist.z = float_dist(actual.z, expected.z);
+    dist.w = float_dist(actual.w, expected.w);
+    rsDebug("float4 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v1.z", v1.z);
+    rsDebug("v1.w", v1.w);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("v2.z", v2.z);
+    rsDebug("v2.w", v2.w);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Dalvik result .z", expected.z);
+    rsDebug("Dalvik result .w", expected.w);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("Renderscript result .z", actual.z);
+    rsDebug("Renderscript result .w", actual.w);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+    rsDebug("ULP difference .z", dist.z);
+    rsDebug("ULP difference .w", dist.w);
+}
+
+static bool f1_almost_equal(float a, float b) {
+    return float_almost_equal(a, b);
+}
+
+static bool f2_almost_equal(float2 a, float2 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y);
+}
+
+
+static bool f3_almost_equal(float3 a, float3 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y)
+            && float_almost_equal(a.z, b.z);
+}
+
+static bool f4_almost_equal(float4 a, float4 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y)
+            && float_almost_equal(a.z, b.z) && float_almost_equal(a.w, b.w);
+}
+
+#define TEST_BASIC_FLOAT_OP(op, opName)                 \
+temp_f1 = x op y;                                       \
+if (! float_almost_equal(temp_f1, result_##opName)) {   \
+    fail_f1(x, y , temp_f1, result_##opName, #opName);  \
+    failed = true;                                      \
+}
+
+#define TEST_FN_FN(func, size)                                                  \
+temp_f##size = func(rand_f##size##_0, rand_f##size##_1);                        \
+if (! f##size##_almost_equal(temp_f##size , func##_rand_f##size##_f##size)) {   \
+    fail_f##size (x, y , temp_f##size, func##_rand_f##size##_f##size, #func);   \
+    failed = true;                                                              \
+}
+#define TEST_FN_F(func, size)                                               \
+temp_f##size = func(rand_f##size##_0, rand_f1_1);                           \
+if (! f##size##_almost_equal(temp_f##size , func##_rand_f##size##_f1)) {    \
+    fail_f##size (x, y , temp_f##size, func##_rand_f##size##_f1 , #func);   \
+    failed = true;                                                          \
+}
+
+#define TEST_FN_FN_ALL(func)    \
+TEST_FN_FN(func, 1)             \
+TEST_FN_FN(func, 2)             \
+TEST_FN_FN(func, 3)             \
+TEST_FN_FN(func, 4)
+#define TEST_FN_F_ALL(func) \
+TEST_FN_F(func, 2)          \
+TEST_FN_F(func, 3)          \
+TEST_FN_F(func, 4)
+
+#define TEST_VEC1_VEC1(func, type)                              \
+temp_##type##1 = func( rand_##type##1_0, rand_##type##1_1 );    \
+if (temp_##type##1 != func##_rand_##type##1_##type##1) {        \
+    rsDebug(#func " " #type "1 operation did not match!", 0);   \
+    rsDebug("v1", rand_##type##1_0);                            \
+    rsDebug("v2", rand_##type##1_1);                            \
+    rsDebug("Dalvik result", func##_rand_##type##1_##type##1);  \
+    rsDebug("Renderscript result", temp_##type##1);             \
+    failed = true;                                              \
+}
+#define TEST_VEC2_VEC2(func, type)                                      \
+temp_##type##2 = func( rand_##type##2_0, rand_##type##2_1 );            \
+if (temp_##type##2 .x != func##_rand_##type##2_##type##2 .x             \
+        || temp_##type##2 .y != func##_rand_##type##2_##type##2 .y) {   \
+    rsDebug(#func " " #type "2 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##2_0 .x);                               \
+    rsDebug("v1.y", rand_##type##2_0 .y);                               \
+    rsDebug("v2.x", rand_##type##2_1 .x);                               \
+    rsDebug("v2.y", rand_##type##2_1 .y);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##2_##type##2 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##2_##type##2 .y);    \
+    rsDebug("Renderscript result .x", temp_##type##2 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##2 .y);               \
+    failed = true;                                                      \
+}
+#define TEST_VEC3_VEC3(func, type)                                      \
+temp_##type##3 = func( rand_##type##3_0, rand_##type##3_1 );            \
+if (temp_##type##3 .x != func##_rand_##type##3_##type##3 .x             \
+        || temp_##type##3 .y != func##_rand_##type##3_##type##3 .y      \
+        || temp_##type##3 .z != func##_rand_##type##3_##type##3 .z) {   \
+    rsDebug(#func " " #type "3 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##3_0 .x);                               \
+    rsDebug("v1.y", rand_##type##3_0 .y);                               \
+    rsDebug("v1.z", rand_##type##3_0 .z);                               \
+    rsDebug("v2.x", rand_##type##3_1 .x);                               \
+    rsDebug("v2.y", rand_##type##3_1 .y);                               \
+    rsDebug("v2.z", rand_##type##3_1 .z);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##3_##type##3 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##3_##type##3 .y);    \
+    rsDebug("Dalvik result .z", func##_rand_##type##3_##type##3 .z);    \
+    rsDebug("Renderscript result .x", temp_##type##3 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##3 .y);               \
+    rsDebug("Renderscript result .z", temp_##type##3 .z);               \
+    failed = true;                                                      \
+}
+#define TEST_VEC4_VEC4(func, type)                                      \
+temp_##type##4 = func( rand_##type##4_0, rand_##type##4_1 );            \
+if (temp_##type##4 .x != func##_rand_##type##4_##type##4 .x             \
+        || temp_##type##4 .y != func##_rand_##type##4_##type##4 .y      \
+        || temp_##type##4 .z != func##_rand_##type##4_##type##4 .z      \
+        || temp_##type##4 .w != func##_rand_##type##4_##type##4 .w) {   \
+    rsDebug(#func " " #type "4 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##4_0 .x);                               \
+    rsDebug("v1.y", rand_##type##4_0 .y);                               \
+    rsDebug("v1.z", rand_##type##4_0 .z);                               \
+    rsDebug("v1.w", rand_##type##4_0 .w);                               \
+    rsDebug("v2.x", rand_##type##4_1 .x);                               \
+    rsDebug("v2.y", rand_##type##4_1 .y);                               \
+    rsDebug("v2.z", rand_##type##4_1 .z);                               \
+    rsDebug("v2.w", rand_##type##4_1 .w);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##4_##type##4 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##4_##type##4 .y);    \
+    rsDebug("Dalvik result .z", func##_rand_##type##4_##type##4 .z);    \
+    rsDebug("Dalvik result .w", func##_rand_##type##4_##type##4 .w);    \
+    rsDebug("Renderscript result .x", temp_##type##4 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##4 .y);               \
+    rsDebug("Renderscript result .z", temp_##type##4 .z);               \
+    rsDebug("Renderscript result .w", temp_##type##4 .w);               \
+    failed = true;                                                      \
+}
+
+#define TEST_SC1_SC1(func)  TEST_VEC1_VEC1(func, sc)
+#define TEST_SC2_SC2(func)  TEST_VEC2_VEC2(func, sc)
+#define TEST_SC3_SC3(func)  TEST_VEC3_VEC3(func, sc)
+#define TEST_SC4_SC4(func)  TEST_VEC4_VEC4(func, sc)
+
+#define TEST_UC1_UC1(func)  TEST_VEC1_VEC1(func, uc)
+#define TEST_UC2_UC2(func)  TEST_VEC2_VEC2(func, uc)
+#define TEST_UC3_UC3(func)  TEST_VEC3_VEC3(func, uc)
+#define TEST_UC4_UC4(func)  TEST_VEC4_VEC4(func, uc)
+
+#define TEST_SS1_SS1(func)  TEST_VEC1_VEC1(func, ss)
+#define TEST_SS2_SS2(func)  TEST_VEC2_VEC2(func, ss)
+#define TEST_SS3_SS3(func)  TEST_VEC3_VEC3(func, ss)
+#define TEST_SS4_SS4(func)  TEST_VEC4_VEC4(func, ss)
+
+#define TEST_US1_US1(func)  TEST_VEC1_VEC1(func, us)
+#define TEST_US2_US2(func)  TEST_VEC2_VEC2(func, us)
+#define TEST_US3_US3(func)  TEST_VEC3_VEC3(func, us)
+#define TEST_US4_US4(func)  TEST_VEC4_VEC4(func, us)
+
+#define TEST_SI1_SI1(func)  TEST_VEC1_VEC1(func, si)
+#define TEST_SI2_SI2(func)  TEST_VEC2_VEC2(func, si)
+#define TEST_SI3_SI3(func)  TEST_VEC3_VEC3(func, si)
+#define TEST_SI4_SI4(func)  TEST_VEC4_VEC4(func, si)
+
+#define TEST_UI1_UI1(func)  TEST_VEC1_VEC1(func, ui)
+#define TEST_UI2_UI2(func)  TEST_VEC2_VEC2(func, ui)
+#define TEST_UI3_UI3(func)  TEST_VEC3_VEC3(func, ui)
+#define TEST_UI4_UI4(func)  TEST_VEC4_VEC4(func, ui)
+
+#define TEST_SL1_SL1(func)  TEST_VEC1_VEC1(func, sl)
+#define TEST_SL2_SL2(func)  TEST_VEC2_VEC2(func, sl)
+#define TEST_SL3_SL3(func)  TEST_VEC3_VEC3(func, sl)
+#define TEST_SL4_SL4(func)  TEST_VEC4_VEC4(func, sl)
+
+#define TEST_UL1_UL1(func)  TEST_VEC1_VEC1(func, ul)
+#define TEST_UL2_UL2(func)  TEST_VEC2_VEC2(func, ul)
+#define TEST_UL3_UL3(func)  TEST_VEC3_VEC3(func, ul)
+#define TEST_UL4_UL4(func)  TEST_VEC4_VEC4(func, ul)
+
+#define TEST_SC_SC_ALL(func)    \
+TEST_SC1_SC1(func)              \
+TEST_SC2_SC2(func)              \
+TEST_SC3_SC3(func)              \
+TEST_SC4_SC4(func)
+#define TEST_UC_UC_ALL(func)    \
+TEST_UC1_UC1(func)              \
+TEST_UC2_UC2(func)              \
+TEST_UC3_UC3(func)              \
+TEST_UC4_UC4(func)
+
+#define TEST_SS_SS_ALL(func)    \
+TEST_SS1_SS1(func)              \
+TEST_SS2_SS2(func)              \
+TEST_SS3_SS3(func)              \
+TEST_SS4_SS4(func)
+#define TEST_US_US_ALL(func)    \
+TEST_US1_US1(func)              \
+TEST_US2_US2(func)              \
+TEST_US3_US3(func)              \
+TEST_US4_US4(func)
+#define TEST_SI_SI_ALL(func)    \
+TEST_SI1_SI1(func)              \
+TEST_SI2_SI2(func)              \
+TEST_SI3_SI3(func)              \
+TEST_SI4_SI4(func)
+#define TEST_UI_UI_ALL(func)    \
+TEST_UI1_UI1(func)              \
+TEST_UI2_UI2(func)              \
+TEST_UI3_UI3(func)              \
+TEST_UI4_UI4(func)
+#define TEST_SL_SL_ALL(func)    \
+TEST_SL1_SL1(func)              \
+TEST_SL2_SL2(func)              \
+TEST_SL3_SL3(func)              \
+TEST_SL4_SL4(func)
+#define TEST_UL_UL_ALL(func)    \
+TEST_UL1_UL1(func)              \
+TEST_UL2_UL2(func)              \
+TEST_UL3_UL3(func)              \
+TEST_UL4_UL4(func)
+
+#define TEST_VEC_VEC_ALL(func)  \
+TEST_FN_FN_ALL(func)            \
+TEST_SC_SC_ALL(func)            \
+TEST_UC_UC_ALL(func)            \
+TEST_SS_SS_ALL(func)            \
+TEST_US_US_ALL(func)            \
+TEST_SI_SI_ALL(func)            \
+TEST_UI_UI_ALL(func)
+
+// TODO:  add long types to ALL macro
+#if 0
+TEST_SL_SL_ALL(func)            \
+TEST_UL_UL_ALL(func)
+#endif
+
+#define DECLARE_TEMP_SET(type, abbrev)  \
+volatile type    temp_##abbrev##1;               \
+volatile type##2 temp_##abbrev##2;               \
+volatile type##3 temp_##abbrev##3;               \
+volatile type##4 temp_##abbrev##4;
+
+#define DECLARE_ALL_TEMP_SETS() \
+DECLARE_TEMP_SET(float, f);     \
+DECLARE_TEMP_SET(char, sc);     \
+DECLARE_TEMP_SET(uchar, uc);    \
+DECLARE_TEMP_SET(short, ss);    \
+DECLARE_TEMP_SET(ushort, us);   \
+DECLARE_TEMP_SET(int, si);      \
+DECLARE_TEMP_SET(uint, ui);     \
+DECLARE_TEMP_SET(long, sl);     \
+DECLARE_TEMP_SET(ulong, ul);
+
+static bool test_math_agree() {
+    bool failed = false;
+
+    DECLARE_ALL_TEMP_SETS();
+
+    TEST_BASIC_FLOAT_OP(+, add);
+    TEST_BASIC_FLOAT_OP(-, sub);
+    TEST_BASIC_FLOAT_OP(*, mul);
+    TEST_BASIC_FLOAT_OP(/, div);
+
+    TEST_VEC_VEC_ALL(min);
+    TEST_VEC_VEC_ALL(max);
+    TEST_FN_FN_ALL(fmin);
+    TEST_FN_F_ALL(fmin);
+    TEST_FN_FN_ALL(fmax);
+    TEST_FN_F_ALL(fmax);
+
+    if (failed) {
+        rsDebug("test_math_agree FAILED", 0);
+    }
+    else {
+        rsDebug("test_math_agree PASSED", 0);
+    }
+
+    return failed;
+}
+
+void math_agree_test() {
+    bool failed = false;
+    failed |= test_math_agree();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/min.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/min.rs
new file mode 100644
index 0000000..4b92763
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/min.rs
@@ -0,0 +1,20 @@
+#include "shared.rsh"
+#pragma rs_fp_relaxed
+
+volatile uchar2 res_uc_2 = 1;
+volatile uchar2 src1_uc_2 = 1;
+volatile uchar2 src2_uc_2 = 1;
+
+void min_test() {
+    bool failed = false;
+
+    res_uc_2 = min(src1_uc_2, src2_uc_2);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/rsdebug.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/rsdebug.rs
index f7942a5..68ac168 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/rsdebug.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/rsdebug.rs
@@ -2,6 +2,9 @@
 
 // Testing primitive types
 float floatTest = 1.99f;
+float2 float2Test = {2.99f, 12.99f};
+float3 float3Test = {3.99f, 13.99f, 23.99f};
+float4 float4Test = {4.99f, 14.99f, 24.99f, 34.99f};
 double doubleTest = 2.05;
 char charTest = -8;
 short shortTest = -16;
@@ -23,6 +26,9 @@
     // For this reason, none of the outputs are actually checked.
 
     rsDebug("floatTest", floatTest);
+    rsDebug("float2Test", float2Test);
+    rsDebug("float3Test", float3Test);
+    rsDebug("float4Test", float4Test);
     rsDebug("doubleTest", doubleTest);
     rsDebug("charTest", charTest);
     rsDebug("shortTest", shortTest);
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/shared.rsh b/tests/RenderScriptTests/tests/src/com/android/rs/test/shared.rsh
index 8cdf0d8..3adc999 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/shared.rsh
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/shared.rsh
@@ -74,6 +74,40 @@
     return isposzero(f) || isnegzero(f);
 }
 
+/* Absolute epsilon used for floats.  Value is similar to float.h. */
+#ifndef FLT_EPSILON
+#define FLT_EPSILON 1.19e7f
+#endif
+/* Max ULPs while still being considered "equal".  Only used when this number
+   of ULPs is of a greater size than FLT_EPSILON. */
+#define FLT_MAX_ULP 1
+
+/* Calculate the difference in ULPs between the two values.  (Return zero on
+   perfect equality.) */
+static int float_dist(float f1, float f2) {
+    return *((int *)(&f1)) - *((int *)(&f2));
+}
+
+/* Check if two floats are essentially equal.  Will fail with some values
+   due to design.  (Validate using FLT_EPSILON or similar if necessary.) */
+static bool float_almost_equal(float f1, float f2) {
+    int *i1 = (int*)(&f1);
+    int *i2 = (int*)(&f2);
+
+    // Check for sign equality
+    if ( ((*i1 >> 31) == 0) != ((*i2 >> 31) == 0) ) {
+        // Handle signed zeroes
+        if (f1 == f2)
+            return true;
+        return false;
+    }
+
+    // Check with ULP distance
+    if (float_dist(f1, f2) > FLT_MAX_ULP)
+        return false;
+    return true;
+}
+
 /* These constants must match those in UnitTest.java */
 static const int RS_MSG_TEST_PASSED = 100;
 static const int RS_MSG_TEST_FAILED = 101;
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/unsigned.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/unsigned.rs
new file mode 100644
index 0000000..2c056f4
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/unsigned.rs
@@ -0,0 +1,36 @@
+#include "shared.rsh"
+
+// Testing unsigned types for Bug 6764163
+unsigned int ui = 37;
+unsigned char uc = 5;
+
+static bool test_unsigned() {
+    bool failed = false;
+
+    rsDebug("ui", ui);
+    rsDebug("uc", uc);
+    _RS_ASSERT(ui == 0x7fffffff);
+    _RS_ASSERT(uc == 129);
+
+    if (failed) {
+        rsDebug("test_unsigned FAILED", -1);
+    }
+    else {
+        rsDebug("test_unsigned PASSED", 0);
+    }
+
+    return failed;
+}
+
+void unsigned_test() {
+    bool failed = false;
+    failed |= test_unsigned();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/tests_v11/Android.mk b/tests/RenderScriptTests/tests_v11/Android.mk
index 93a429b..52d326b 100644
--- a/tests/RenderScriptTests/tests_v11/Android.mk
+++ b/tests/RenderScriptTests/tests_v11/Android.mk
@@ -19,7 +19,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/tests_v14/Android.mk b/tests/RenderScriptTests/tests_v14/Android.mk
index c4c3a37..a4386a44 100644
--- a/tests/RenderScriptTests/tests_v14/Android.mk
+++ b/tests/RenderScriptTests/tests_v14/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/StatusBar/res/layout/notification_builder_test.xml b/tests/StatusBar/res/layout/notification_builder_test.xml
index 6c384f7..94fc089 100644
--- a/tests/StatusBar/res/layout/notification_builder_test.xml
+++ b/tests/StatusBar/res/layout/notification_builder_test.xml
@@ -371,6 +371,12 @@
                         android:tag="Oh my goodness.  SOMETHING HAPPENED!!!!"
                         />
                 <RadioButton
+                        android:id="@+id/text_emoji"
+                        style="@style/FieldContents"
+                        android:text="emoji"
+                        android:tag="_ Cactus _ Cactus _"
+                        />
+                <RadioButton
                         android:id="@+id/text_haiku"
                         style="@style/FieldContents"
                         android:text="haiku"
@@ -572,6 +578,12 @@
                         android:tag="sholes final approach\nlanding gear punted to flan\nrunway foam glistens"
                         />
                 <RadioButton
+                        android:id="@+id/ticker_emoji"
+                        style="@style/FieldContents"
+                        android:text="emoji"
+                        android:tag="_ Cactus _ Cactus _"
+                        />
+                <RadioButton
                         android:id="@+id/ticker_custom"
                         style="@style/FieldContents.Disabled"
                         android:text="custom view"
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
index fefd890..2f0c173 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
@@ -32,6 +32,7 @@
 import android.os.Environment;
 import android.os.Vibrator;
 import android.os.Handler;
+import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.util.Log;
 import android.net.Uri;
@@ -187,6 +188,20 @@
         mNM.notify(id, n);
     }
 
+    private static CharSequence subst(CharSequence in, char ch, CharSequence sub) {
+        int i=0;
+        SpannableStringBuilder edit = new SpannableStringBuilder(in);
+        while (i<edit.length()) {
+            if (edit.charAt(i) == ch) {
+                edit.replace(i, i+1, sub);
+                i += sub.length();
+            } else {
+                i ++;
+            }
+        }
+        return edit;
+    }
+
     private Notification buildNotification(int id) {
         Notification.Builder b = new Notification.Builder(this);
 
@@ -223,19 +238,25 @@
         }
 
         // title
-        final String title = getRadioTag(R.id.group_title);
+        final CharSequence title = getRadioTag(R.id.group_title);
         if (!TextUtils.isEmpty(title)) {
             b.setContentTitle(title);
         }
 
         // text
-        final String text = getRadioTag(R.id.group_text);
+        final CharSequence text = getRadioTag(R.id.group_text);
         if (!TextUtils.isEmpty(text)) {
-            b.setContentText(text);
+            if (getRadioChecked(R.id.group_text) == R.id.text_emoji) {
+                // UTF-16 for +1F335
+                b.setContentText(subst(text,
+                        '_', "\ud83c\udf35"));
+            } else {
+                b.setContentText(text);
+            }
         }
 
         // info
-        final String info = getRadioTag(R.id.group_info);
+        final CharSequence info = getRadioTag(R.id.group_info);
         if (!TextUtils.isEmpty(info)) {
             b.setContentInfo(info);
         }
@@ -272,6 +293,11 @@
             case R.id.ticker_haiku:
                 b.setTicker(getRadioTag(R.id.group_ticker));
                 break;
+            case R.id.ticker_emoji:
+                // UTF-16 for +1F335
+                b.setTicker(subst(getRadioTag(R.id.group_ticker),
+                        '_', "\ud83c\udf35"));
+                break;
             case R.id.ticker_custom:
                 // TODO
                 break;
@@ -370,19 +396,19 @@
         return g.getCheckedRadioButtonId();
     }
 
-    private String getRadioTag(int id) {
+    private CharSequence getRadioTag(int id) {
         final RadioGroup g = (RadioGroup)findViewById(id);
         final View v = findViewById(g.getCheckedRadioButtonId());
-        return (String)v.getTag();
+        return (CharSequence) v.getTag();
     }
 
     private int getRadioInt(int id, int def) {
-        String str = getRadioTag(id);
+        CharSequence str = getRadioTag(id);
         if (TextUtils.isEmpty(str)) {
             return def;
         } else {
             try {
-                return Integer.parseInt(str);
+                return Integer.parseInt(str.toString());
             } catch (NumberFormatException ex) {
                 return def;
             }
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 70e2aac..ec39aab 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -28,6 +28,7 @@
 import android.os.Environment;
 import android.os.Vibrator;
 import android.os.Handler;
+import android.os.UserHandle;
 import android.util.Log;
 import android.net.Uri;
 import android.os.SystemClock;
@@ -798,7 +799,8 @@
                             null, 
                             100, 
                             n,
-                            idOut);
+                            idOut,
+                            UserHandle.myUserId());
                 } catch (android.os.RemoteException ex) {
                     // oh well
                 }
@@ -822,7 +824,8 @@
                             null, 
                             200, 
                             n,
-                            idOut);
+                            idOut,
+                            UserHandle.myUserId());
                 } catch (android.os.RemoteException ex) {
                     // oh well
                 }
@@ -846,7 +849,8 @@
                             null, 
                             1, 
                             n,
-                            idOut);
+                            idOut,
+                            UserHandle.myUserId());
                 } catch (android.os.RemoteException ex) {
                     // oh well
                 }
diff --git a/tests/StatusBar/src/com/android/statusbartest/PowerTest.java b/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
index 31a1cf5a..0cab10d 100644
--- a/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
@@ -16,32 +16,13 @@
 
 package com.android.statusbartest;
 
-import android.app.ListActivity;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.widget.ArrayAdapter;
-import android.view.View;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.IPowerManager;
-import android.widget.ListView;
-import android.content.Intent;
 import android.content.ComponentName;
 import android.content.pm.PackageManager;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.StatusBarManager;
-import android.os.RemoteException;
-import android.os.Vibrator;
-import android.os.Bundle;
 import android.os.Handler;
-import android.os.LocalPowerManager;
 import android.os.ServiceManager;
-import android.util.Log;
-import android.net.Uri;
-import android.os.SystemClock;
-import android.widget.RemoteViews;
-import android.widget.Toast;
 import android.os.PowerManager;
 
 public class PowerTest extends TestActivity
@@ -101,68 +82,26 @@
                 mProx.release(PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE);
             }
         },
-        new Test("Touch events don't poke") {
+        new Test("Enable proximity, wait 5 seconds then disable") {
             public void run() {
-                mPokeState |= LocalPowerManager.POKE_LOCK_IGNORE_TOUCH_EVENTS;
-                try {
-                    mPowerManager.setPokeLock(mPokeState, mPokeToken, TAG);
-                } catch (RemoteException e) {
-                    throw new RuntimeException(e);
-                }
+                mProx.acquire();
+                mHandler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        mProx.release();
+                    }
+                }, 5000);
             }
         },
-
-        new Test("Touch events poke") {
+        new Test("Enable proximity, wait 5 seconds then disable  (WAIT_FOR_PROXIMITY_NEGATIVE)") {
             public void run() {
-                mPokeState &= ~LocalPowerManager.POKE_LOCK_IGNORE_TOUCH_EVENTS;
-                try {
-                    mPowerManager.setPokeLock(mPokeState, mPokeToken, TAG);
-                } catch (RemoteException e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        },
-        new Test("Short timeout") {
-            public void run() {
-                mPokeState &= ~LocalPowerManager.POKE_LOCK_TIMEOUT_MASK;
-                mPokeState |= LocalPowerManager.POKE_LOCK_SHORT_TIMEOUT;
-                try {
-                    mPowerManager.setPokeLock(mPokeState, mPokeToken, TAG);
-                } catch (RemoteException e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        },
-        new Test("Medium timeout") {
-            public void run() {
-                mPokeState &= ~LocalPowerManager.POKE_LOCK_TIMEOUT_MASK;
-                mPokeState |= LocalPowerManager.POKE_LOCK_MEDIUM_TIMEOUT;
-                try {
-                    mPowerManager.setPokeLock(mPokeState, mPokeToken, TAG);
-                } catch (RemoteException e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        },
-        new Test("Normal timeout") {
-            public void run() {
-                mPokeState &= ~LocalPowerManager.POKE_LOCK_TIMEOUT_MASK;
-                try {
-                    mPowerManager.setPokeLock(mPokeState, mPokeToken, TAG);
-                } catch (RemoteException e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        },
-        new Test("Illegal timeout") {
-            public void run() {
-                mPokeState |= LocalPowerManager.POKE_LOCK_SHORT_TIMEOUT
-                        | LocalPowerManager.POKE_LOCK_MEDIUM_TIMEOUT;
-                try {
-                    mPowerManager.setPokeLock(mPokeState, mPokeToken, TAG);
-                } catch (RemoteException e) {
-                    throw new RuntimeException(e);
-                }
+                mProx.acquire();
+                mHandler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        mProx.release(PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE);
+                    }
+                }, 5000);
             }
         },
     };
diff --git a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
index 94ad620..50f98b8 100644
--- a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
@@ -16,29 +16,15 @@
 
 package com.android.statusbartest;
 
-import android.app.ListActivity;
 import android.app.Notification;
 import android.app.NotificationManager;
-import android.widget.ArrayAdapter;
 import android.view.View;
-import android.widget.ListView;
 import android.content.Intent;
 import android.app.PendingIntent;
-import android.app.Notification;
-import android.app.NotificationManager;
 import android.app.StatusBarManager;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.os.Vibrator;
-import android.os.Bundle;
 import android.os.Handler;
 import android.util.Log;
-import android.net.Uri;
 import android.os.SystemClock;
-import android.widget.RemoteViews;
-import android.widget.Toast;
-import android.os.PowerManager;
-import android.view.View;
 import android.view.Window;
 import android.view.WindowManager;
 
@@ -298,25 +284,39 @@
                     }, 3000);
             }
         },
-        new Test("Expand") {
+        new Test("Expand notifications") {
             public void run() {
-                mStatusBarManager.expand();
+                mStatusBarManager.expandNotificationsPanel();
             }
         },
-        new Test("Expand in 3 sec.") {
+        new Test(" ... in 3 sec.") {
             public void run() {
                 mHandler.postDelayed(new Runnable() {
                         public void run() {
-                            mStatusBarManager.expand();
+                            mStatusBarManager.expandNotificationsPanel();
                         }
                     }, 3000);
             }
         },
-        new Test("Collapse in 3 sec.") {
+        new Test("Expand settings") {
+            public void run() {
+                mStatusBarManager.expandSettingsPanel();
+            }
+        },
+        new Test(" ... in 3 sec.") {
             public void run() {
                 mHandler.postDelayed(new Runnable() {
                         public void run() {
-                            mStatusBarManager.collapse();
+                            mStatusBarManager.expandSettingsPanel();
+                        }
+                    }, 3000);
+            }
+        },
+        new Test("Collapse panels in 3 sec.") {
+            public void run() {
+                mHandler.postDelayed(new Runnable() {
+                        public void run() {
+                            mStatusBarManager.collapsePanels();
                         }
                     }, 3000);
             }
diff --git a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeChildFrameTest.java b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeChildFrameTest.java
new file mode 100644
index 0000000..3f0e2b3
--- /dev/null
+++ b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeChildFrameTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+/**
+ * Part of the test suite for the WebView's Java Bridge.
+ *
+ * Ensures that injected objects are exposed to child frames as well as the
+ * main frame.
+ *
+ * To run this test ...
+ *  adb shell am instrument -w -e class com.android.webviewtests.JavaBridgeChildFrameTest \
+ *          com.android.webviewtests/android.test.InstrumentationTestRunner
+ */
+
+package com.android.webviewtests;
+
+public class JavaBridgeChildFrameTest extends JavaBridgeTestBase {
+    private class TestController extends Controller {
+        private String mStringValue;
+
+       public synchronized void setStringValue(String x) {
+            mStringValue = x;
+            notifyResultIsReady();
+        }
+       public synchronized String waitForStringValue() {
+            waitForResult();
+            return mStringValue;
+        }
+    }
+
+    TestController mTestController;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mTestController = new TestController();
+        setUpWebView(mTestController, "testController");
+    }
+
+    public void testInjectedObjectPresentInChildFrame() throws Throwable {
+        // In the case that the test fails (i.e. the child frame doesn't get the injected object,
+        // the call to testController.setStringValue in the child frame's onload handler will
+        // not be made.
+        getActivity().getWebView().loadData(
+                "<html><head></head><body>" +
+                "<iframe id=\"childFrame\" onload=\"testController.setStringValue('PASS');\" />" +
+                "</body></html>", "text/html", null);
+        assertEquals("PASS", mTestController.waitForStringValue());
+    }
+}
diff --git a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeTestBase.java b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeTestBase.java
index 1af3f63..a451015 100644
--- a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeTestBase.java
+++ b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeTestBase.java
@@ -106,7 +106,12 @@
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
-                getWebView().loadUrl("javascript:" + script);
+                // When a JavaScript URL is executed, if the value of the last
+                // expression evaluated is not 'undefined', this value is
+                // converted to a string and used as the new document for the
+                // frame. We don't want this behaviour, so wrap the script in
+                // an anonymous function.
+                getWebView().loadUrl("javascript:(function() { " + script + " })()");
             }
         });
     }
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index 1f6279c..746ac06 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -93,7 +93,7 @@
         }
         
         try {
-            mWm.addAppToken(0, null, 0, 0, false);
+            mWm.addAppToken(0, null, 0, 0, false, false);
             fail("IWindowManager.addAppToken did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 46b8a27..5b71adc 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -183,6 +183,13 @@
         return 0;
     }
 
+    // layout direction
+    if (getLayoutDirectionName(part.string(), &config)) {
+        *axis = AXIS_LAYOUTDIR;
+        *value = (config.screenLayout&ResTable_config::MASK_LAYOUTDIR);
+        return 0;
+    }
+
     // smallest screen dp width
     if (getSmallestScreenWidthDpName(part.string(), &config)) {
         *axis = AXIS_SMALLESTSCREENWIDTHDP;
@@ -309,6 +316,8 @@
         case AXIS_LANGUAGE:
             return (((uint32_t)config.country[1]) << 24) | (((uint32_t)config.country[0]) << 16)
                 | (((uint32_t)config.language[1]) << 8) | (config.language[0]);
+        case AXIS_LAYOUTDIR:
+            return config.screenLayout&ResTable_config::MASK_LAYOUTDIR;
         case AXIS_SCREENLAYOUTSIZE:
             return config.screenLayout&ResTable_config::MASK_SCREENSIZE;
         case AXIS_ORIENTATION:
@@ -364,7 +373,7 @@
     Vector<String8> parts;
 
     String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
-    String8 touch, key, keysHidden, nav, navHidden, size, vers;
+    String8 touch, key, keysHidden, nav, navHidden, size, layoutDir, vers;
     String8 uiModeType, uiModeNight, smallestwidthdp, widthdp, heightdp;
 
     const char *p = dir;
@@ -452,6 +461,18 @@
         //printf("not region: %s\n", part.string());
     }
 
+    if (getLayoutDirectionName(part.string())) {
+        layoutDir = part;
+
+        index++;
+        if (index == N) {
+            goto success;
+        }
+        part = parts[index];
+    } else {
+        //printf("not layout direction: %s\n", part.string());
+    }
+
     if (getSmallestScreenWidthDpName(part.string())) {
         smallestwidthdp = part;
 
@@ -674,6 +695,7 @@
     this->navHidden = navHidden;
     this->navigation = nav;
     this->screenSize = size;
+    this->layoutDirection = layoutDir;
     this->version = vers;
 
     // what is this anyway?
@@ -691,6 +713,8 @@
     s += ",";
     s += this->locale;
     s += ",";
+    s += layoutDirection;
+    s += ",";
     s += smallestScreenWidthDp;
     s += ",";
     s += screenWidthDp;
@@ -747,6 +771,12 @@
         }
         s += locale;
     }
+    if (this->layoutDirection != "") {
+        if (s.length() > 0) {
+            s += "-";
+        }
+        s += layoutDirection;
+    }
     if (this->smallestScreenWidthDp != "") {
         if (s.length() > 0) {
             s += "-";
@@ -958,6 +988,28 @@
     return false;
 }
 
+bool AaptGroupEntry::getLayoutDirectionName(const char* name, ResTable_config* out)
+{
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR)
+                | ResTable_config::LAYOUTDIR_ANY;
+        return true;
+    } else if (strcmp(name, "ldltr") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR)
+                | ResTable_config::LAYOUTDIR_LTR;
+        return true;
+    } else if (strcmp(name, "ldrtl") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR)
+                | ResTable_config::LAYOUTDIR_RTL;
+        return true;
+    }
+
+    return false;
+}
+
 bool AaptGroupEntry::getScreenLayoutSizeName(const char* name,
                                      ResTable_config* out)
 {
@@ -1415,6 +1467,7 @@
     int v = mcc.compare(o.mcc);
     if (v == 0) v = mnc.compare(o.mnc);
     if (v == 0) v = locale.compare(o.locale);
+    if (v == 0) v = layoutDirection.compare(o.layoutDirection);
     if (v == 0) v = vendor.compare(o.vendor);
     if (v == 0) v = smallestScreenWidthDp.compare(o.smallestScreenWidthDp);
     if (v == 0) v = screenWidthDp.compare(o.screenWidthDp);
@@ -1447,6 +1500,7 @@
     getMccName(mcc.string(), &params);
     getMncName(mnc.string(), &params);
     getLocaleName(locale.string(), &params);
+    getLayoutDirectionName(layoutDirection.string(), &params);
     getSmallestScreenWidthDpName(smallestScreenWidthDp.string(), &params);
     getScreenWidthDpName(screenWidthDp.string(), &params);
     getScreenHeightDpName(screenHeightDp.string(), &params);
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index d5f296c..5cfa913 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -51,6 +51,7 @@
     AXIS_SMALLESTSCREENWIDTHDP,
     AXIS_SCREENWIDTHDP,
     AXIS_SCREENHEIGHTDP,
+    AXIS_LAYOUTDIR,
     AXIS_VERSION,
 
     AXIS_START = AXIS_MCC,
@@ -95,6 +96,7 @@
     static bool getSmallestScreenWidthDpName(const char* name, ResTable_config* out = NULL);
     static bool getScreenWidthDpName(const char* name, ResTable_config* out = NULL);
     static bool getScreenHeightDpName(const char* name, ResTable_config* out = NULL);
+    static bool getLayoutDirectionName(const char* name, ResTable_config* out = NULL);
     static bool getVersionName(const char* name, ResTable_config* out = NULL);
 
     int compare(const AaptGroupEntry& o) const;
@@ -133,6 +135,7 @@
     String8 navHidden;
     String8 navigation;
     String8 screenSize;
+    String8 layoutDirection;
     String8 version;
 
     mutable bool mParamsChanged;
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index d98fe65..3d7b088 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2811,7 +2811,7 @@
 
                 NOISY(printf("Writing config %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
                      "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
-                     "sw%ddp w%ddp h%ddp\n",
+                     "sw%ddp w%ddp h%ddp dir:%d\n",
                       ti+1,
                       config.mcc, config.mnc,
                       config.language[0] ? config.language[0] : '-',
@@ -2829,7 +2829,8 @@
                       config.screenHeight,
                       config.smallestScreenWidthDp,
                       config.screenWidthDp,
-                      config.screenHeightDp));
+                      config.screenHeightDp,
+                      config.layoutDirection));
                       
                 if (filterable && !filter.match(config)) {
                     continue;
@@ -2853,7 +2854,7 @@
                 tHeader->config = config;
                 NOISY(printf("Writing type %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
                      "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
-                     "sw%ddp w%ddp h%ddp\n",
+                     "sw%ddp w%ddp h%ddp dir:%d\n",
                       ti+1,
                       tHeader->config.mcc, tHeader->config.mnc,
                       tHeader->config.language[0] ? tHeader->config.language[0] : '-',
@@ -2871,7 +2872,8 @@
                       tHeader->config.screenHeight,
                       tHeader->config.smallestScreenWidthDp,
                       tHeader->config.screenWidthDp,
-                      tHeader->config.screenHeightDp));
+                      tHeader->config.screenHeightDp,
+                      tHeader->config.layoutDirection));
                 tHeader->config.swapHtoD();
 
                 // Build the entries inside of this type.
@@ -3489,7 +3491,7 @@
         if (config != NULL) {
             NOISY(printf("New entry at %s:%d: imsi:%d/%d lang:%c%c cnt:%c%c "
                     "orien:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
-                    "sw%ddp w%ddp h%ddp\n",
+                    "sw%ddp w%ddp h%ddp dir:%d\n",
                       sourcePos.file.string(), sourcePos.line,
                       config->mcc, config->mnc,
                       config->language[0] ? config->language[0] : '-',
@@ -3506,7 +3508,8 @@
                       config->screenHeight,
                       config->smallestScreenWidthDp,
                       config->screenWidthDp,
-                      config->screenHeightDp));
+                      config->screenHeightDp,
+                      config->layoutDirection));
         } else {
             NOISY(printf("New entry at %s:%d: NULL config\n",
                       sourcePos.file.string(), sourcePos.line));
diff --git a/tools/aidl/aidl.cpp b/tools/aidl/aidl.cpp
index 8dbbf50..0728246 100644
--- a/tools/aidl/aidl.cpp
+++ b/tools/aidl/aidl.cpp
@@ -590,7 +590,8 @@
     }
 
     const document_item_type* next = items->next;
-    if (items->next != NULL) {
+    // Allow parcelables to skip the "one-only" rule.
+    if (items->next != NULL && next->item_type != USER_DATA_TYPE) {
         int lineno = -1;
         if (next->item_type == INTERFACE_TYPE_BINDER) {
             lineno = ((interface_type*)next)->interface_token.lineno;
@@ -598,9 +599,6 @@
         else if (next->item_type == INTERFACE_TYPE_RPC) {
             lineno = ((interface_type*)next)->interface_token.lineno;
         }
-        else if (next->item_type == USER_DATA_TYPE) {
-            lineno = ((user_data_type*)next)->keyword_token.lineno;
-        }
         fprintf(stderr, "%s:%d aidl can only handle one interface per file\n",
                             filename, lineno);
         return 1;
diff --git a/tools/aidl/generate_java_rpc.cpp b/tools/aidl/generate_java_rpc.cpp
index e5fa076..5e4dacc 100644
--- a/tools/aidl/generate_java_rpc.cpp
+++ b/tools/aidl/generate_java_rpc.cpp
@@ -786,7 +786,10 @@
     }
 
     // Call the callback method
-    dispatchMethod->statements->Add(realCall);
+    IfStatement* ifst = new IfStatement;
+        ifst->expression = new Comparison(new FieldVariable(THIS_VALUE, "callback"), "!=", NULL_VALUE);
+    dispatchMethod->statements->Add(ifst);
+    ifst->statements->Add(realCall);
 }
 
 static void
diff --git a/tools/layoutlib/bridge/.classpath b/tools/layoutlib/bridge/.classpath
index a5db7b1..3c124d9 100644
--- a/tools/layoutlib/bridge/.classpath
+++ b/tools/layoutlib/bridge/.classpath
@@ -2,10 +2,10 @@
 <classpath>
 	<classpathentry excluding="org/kxml2/io/" kind="src" path="src"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilt/common/layoutlib_api/layoutlib_api-prebuilt.jar"/>
+	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/layoutlib_api/layoutlib_api-prebuilt.jar"/>
 	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/kxml2/kxml2-2.3.0.jar" sourcepath="/ANDROID_PLAT_SRC/dalvik/libcore/xml/src/main/java"/>
 	<classpathentry kind="var" path="ANDROID_PLAT_SRC/out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar" sourcepath="/ANDROID_PLAT_SRC/frameworks/base"/>
-	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilt/common/ninepatch/ninepatch-prebuilt.jar"/>
-	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilt/common/tools-common/tools-common-prebuilt.jar"/>
+	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/ninepatch/ninepatch-prebuilt.jar"/>
+	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/tools-common/tools-common-prebuilt.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml b/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml
deleted file mode 100644
index c5acddb..0000000
--- a/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-	<ImageView
-			android:layout_height="wrap_content"
-			android:layout_width="wrap_content"/>
-	<ImageView
-			android:layout_height="wrap_content"
-			android:layout_width="wrap_content"/>
-	<ImageView
-			android:layout_height="wrap_content"
-			android:layout_width="wrap_content"/>
-	<TextView
-			android:layout_width="wrap_content"
-			android:layout_height="wrap_content"
-			android:layout_weight="1"/>
-	<ImageView
-			android:layout_height="wrap_content"
-			android:layout_width="wrap_content"/>
-	<ImageView
-			android:layout_height="wrap_content"
-			android:layout_width="wrap_content"
-			android:layout_marginLeft="3dip"
-			android:layout_marginRight="15dip"/>
-</merge>
diff --git a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java
index bd332a6..fd594f7 100644
--- a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java
@@ -31,6 +31,7 @@
  */
 public class SystemClock_Delegate {
     private static long sBootTime = System.currentTimeMillis();
+    private static long sBootTimeNano = System.nanoTime();
 
     @LayoutlibDelegate
     /*package*/ static boolean setCurrentTimeMillis(long millis) {
@@ -60,6 +61,16 @@
     }
 
     /**
+     * Returns nanoseconds since boot, including time spent in sleep.
+     *
+     * @return elapsed nanoseconds since boot.
+     */
+    @LayoutlibDelegate
+    /*package*/ static long elapsedRealtimeNanos() {
+        return System.nanoTime() - sBootTimeNano;
+    }
+
+    /**
      * Returns milliseconds running in the current thread.
      *
      * @return elapsed milliseconds in the thread
diff --git a/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java b/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java
index 1df78c2..8b4c60b 100644
--- a/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java
@@ -91,4 +91,42 @@
     /*package*/ static float sqrt(float value) {
         return (float)Math.sqrt(value);
     }
+
+    /**
+     * Returns the closest float approximation of the raising "e" to the power
+     * of the argument.
+     *
+     * @param value to compute the exponential of
+     * @return the exponential of value
+     */
+    @LayoutlibDelegate
+    /*package*/ static float exp(float value) {
+        return (float)Math.exp(value);
+    }
+
+    /**
+     * Returns the closest float approximation of the result of raising {@code
+     * x} to the power of {@code y}.
+     *
+     * @param x the base of the operation.
+     * @param y the exponent of the operation.
+     * @return {@code x} to the power of {@code y}.
+     */
+    @LayoutlibDelegate
+    /*package*/ static float pow(float x, float y) {
+        return (float)Math.pow(x, y);
+    }
+
+    /**
+     * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +} <i>
+     * {@code y}</i><sup>{@code 2}</sup>{@code )}.
+     *
+     * @param x a float number
+     * @param y a float number
+     * @return the hypotenuse
+     */
+    @LayoutlibDelegate
+    /*package*/ static float hypot(float x, float y) {
+        return (float)Math.sqrt(x*x + y*y);
+    }
 }
diff --git a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
index 97d9969..4901f72 100644
--- a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
+++ b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
@@ -19,6 +19,7 @@
 import com.android.layoutlib.bridge.android.BridgeWindow;
 import com.android.layoutlib.bridge.android.BridgeWindowSession;
 
+import android.content.Context;
 import android.os.Handler;
 import android.view.View.AttachInfo;
 
@@ -28,8 +29,12 @@
 public class AttachInfo_Accessor {
 
     public static void setAttachInfo(View view) {
+        Context context = view.getContext();
+        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+        Display display = wm.getDefaultDisplay();
+        ViewRootImpl root = new ViewRootImpl(context, display);
         AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(),
-                new ViewRootImpl(view.getContext()), new Handler(), null);
+                display, root, new Handler(), null);
         info.mHasWindowFocus = true;
         info.mWindowVisibility = View.VISIBLE;
         info.mInTouchMode = false; // this is so that we can display selections.
diff --git a/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java b/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java
new file mode 100644
index 0000000..f75ee50
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java
@@ -0,0 +1,33 @@
+/*
+ * 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 Choreographer}
+ *
+ * Through the layoutlib_create tool, the original  methods of Choreographer have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ */
+public class Choreographer_Delegate {
+
+    @LayoutlibDelegate
+    public static float getRefreshRate() {
+        return 60.f;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
index 8868c65..53dc821 100644
--- a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
@@ -16,11 +16,8 @@
 
 package android.view;
 
-import com.android.layoutlib.bridge.android.BridgeWindowManager;
-import com.android.layoutlib.bridge.impl.RenderAction;
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
-import android.os.RemoteException;
 
 /**
  * Delegate used to provide new implementation of a select few methods of {@link Display}
@@ -31,57 +28,9 @@
  */
 public class Display_Delegate {
 
-    // ---- Overridden methods ----
-
     @LayoutlibDelegate
-    public static IWindowManager getWindowManager() {
-        return RenderAction.getCurrentContext().getIWindowManager();
+    static void updateDisplayInfoLocked(Display theDisplay) {
+        // do nothing
     }
 
-    // ---- Native methods ----
-
-    @LayoutlibDelegate
-    /*package*/ static int getDisplayCount() {
-        return 1;
-    }
-
-    @LayoutlibDelegate
-    /** @hide special for when we are faking the screen size. */
-    /*package*/ static int getRawWidthNative(Display theDisplay) {
-        // same as real since we're not faking compatibility mode.
-        return RenderAction.getCurrentContext().getIWindowManager().getMetrics().widthPixels;
-    }
-
-    @LayoutlibDelegate
-    /** @hide special for when we are faking the screen size. */
-    /*package*/ static int getRawHeightNative(Display theDisplay) {
-        // same as real since we're not faking compatibility mode.
-        return RenderAction.getCurrentContext().getIWindowManager().getMetrics().heightPixels;
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static int getOrientation(Display theDisplay) {
-        try {
-            // always dynamically query for the current window manager
-            return getWindowManager().getRotation();
-        } catch (RemoteException e) {
-            // this will never been thrown since this is not a true RPC.
-        }
-
-        return Surface.ROTATION_0;
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static void nativeClassInit() {
-        // not needed for now.
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static void init(Display theDisplay, int display) {
-        // always dynamically query for the current window manager
-        BridgeWindowManager wm = RenderAction.getCurrentContext().getIWindowManager();
-        theDisplay.mDensity = wm.getMetrics().density;
-        theDisplay.mDpiX = wm.getMetrics().xdpi;
-        theDisplay.mDpiY = wm.getMetrics().ydpi;
-    }
 }
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
new file mode 100644
index 0000000..3e625f9
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -0,0 +1,506 @@
+/*
+ * 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.
+ */
+
+package android.view;
+
+import com.android.internal.view.IInputContext;
+import com.android.internal.view.IInputMethodClient;
+
+import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.IRemoteCallback;
+import android.os.RemoteException;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.IApplicationToken;
+import android.view.IDisplayContentChangeListener;
+import android.view.IInputFilter;
+import android.view.IOnKeyguardExitResult;
+import android.view.IRotationWatcher;
+import android.view.IWindowManager;
+import android.view.IWindowSession;
+import android.view.WindowInfo;
+
+import java.util.List;
+
+/**
+ * Basic implementation of {@link IWindowManager} so that {@link Display} (and
+ * {@link Display_Delegate}) can return a valid instance.
+ */
+public class IWindowManagerImpl implements IWindowManager {
+
+    private final Configuration mConfig;
+    private final DisplayMetrics mMetrics;
+    private final int mRotation;
+    private final boolean mHasSystemNavBar;
+    private final boolean mHasNavigationBar;
+
+    public IWindowManagerImpl(Configuration config, DisplayMetrics metrics, int rotation,
+            boolean hasSystemNavBar, boolean hasNavigationBar) {
+        mConfig = config;
+        mMetrics = metrics;
+        mRotation = rotation;
+        mHasSystemNavBar = hasSystemNavBar;
+        mHasNavigationBar = hasNavigationBar;
+    }
+
+    // custom API.
+
+    public DisplayMetrics getMetrics() {
+        return mMetrics;
+    }
+
+    // ---- implementation of IWindowManager that we care about ----
+
+    @Override
+    public int getRotation() throws RemoteException {
+        return mRotation;
+    }
+
+    @Override
+    public boolean hasNavigationBar() {
+        return mHasNavigationBar;
+    }
+
+    @Override
+    public boolean hasSystemNavBar() throws RemoteException {
+        return mHasSystemNavBar;
+    }
+
+    // ---- unused implementation of IWindowManager ----
+
+    @Override
+    public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, boolean arg4,
+                            boolean arg5)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void addWindowToken(IBinder arg0, int arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void clearForcedDisplaySize(int displayId) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void clearForcedDisplayDensity(int displayId) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void closeSystemDialogs(String arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void startFreezingScreen(int exitAnim, int enterAnim) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void stopFreezingScreen() {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void disableKeyguard(IBinder arg0, String arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void executeAppTransition() throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void exitKeyguardSecurely(IOnKeyguardExitResult arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void freezeRotation(int arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public float getAnimationScale(int arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public float[] getAnimationScales() throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public int getAppOrientation(IApplicationToken arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int getPendingAppTransition() throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public boolean inKeyguardRestrictedInputMode() throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean inputMethodClientHasFocus(IInputMethodClient arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean isKeyguardLocked() throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean isKeyguardSecure() throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean isViewServerRunning() throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public void moveAppToken(int arg0, IBinder arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void moveAppTokensToBottom(List<IBinder> arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void moveAppTokensToTop(List<IBinder> arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public IWindowSession openSession(IInputMethodClient arg0, IInputContext arg1)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void overridePendingAppTransition(String arg0, int arg1, int arg2,
+            IRemoteCallback startedCallback) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
+            int startHeight) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
+            IRemoteCallback startedCallback, boolean scaleUp) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void pauseKeyDispatching(IBinder arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void prepareAppTransition(int arg0, boolean arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void reenableKeyguard(IBinder arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void removeAppToken(IBinder arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void removeWindowToken(IBinder arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void resumeKeyDispatching(IBinder arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public Bitmap screenshotApplications(IBinder arg0, int displayId, int arg1, int arg2)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void setAnimationScale(int arg0, float arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setAnimationScales(float[] arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setAppGroupId(IBinder arg0, int arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setAppOrientation(IApplicationToken arg0, int arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void setAppStartingWindow(IBinder arg0, String arg1, int arg2, CompatibilityInfo arg3,
+            CharSequence arg4, int arg5, int arg6, int arg7, IBinder arg8, boolean arg9)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void setAppVisibility(IBinder arg0, boolean arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setAppWillBeHidden(IBinder arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void setEventDispatching(boolean arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void setFocusedApp(IBinder arg0, boolean arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void setForcedDisplaySize(int displayId, int arg0, int arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void setForcedDisplayDensity(int displayId, int density) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void setInTouchMode(boolean arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void setNewConfiguration(Configuration arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void updateRotation(boolean arg0, boolean arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void setStrictModeVisualIndicatorPreference(String arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void showStrictModeViolation(boolean arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void startAppFreezingScreen(IBinder arg0, int arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public boolean startViewServer(int arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public void statusBarVisibilityChanged(int arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void stopAppFreezingScreen(IBinder arg0, boolean arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public boolean stopViewServer() throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public void thawRotation() throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public Configuration updateOrientationFromAppTokens(Configuration arg0, IBinder arg1)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public int watchRotation(IRotationWatcher arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
+        return false;
+    }
+
+    @Override
+    public IBinder asBinder() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public int getPreferredOptionsPanelGravity() throws RemoteException {
+        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
+    }
+
+    @Override
+    public void dismissKeyguard() {
+    }
+
+    @Override
+    public void lockNow(Bundle options) {
+        // TODO Auto-generated method stub
+    }
+    
+    @Override
+    public boolean isSafeModeEnabled() {
+        return false;
+    }
+
+    @Override
+    public void showAssistant() {
+
+    }
+
+    @Override
+    public IBinder getFocusedWindowToken() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public float getWindowCompatibilityScale(IBinder windowToken) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void setInputFilter(IInputFilter filter) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void magnifyDisplay(int dipslayId, float scale, float offsetX, float offsetY)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void addDisplayContentChangeListener(int displayId,
+            IDisplayContentChangeListener listener) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void removeDisplayContentChangeListener(int displayId,
+            IDisplayContentChangeListener listener) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public WindowInfo getWindowInfo(IBinder token) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void getVisibleWindowsForDisplay(int displayId, List<WindowInfo> outInfos)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java b/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java
new file mode 100644
index 0000000..2606e55
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java
@@ -0,0 +1,43 @@
+/*
+ * 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 WindowManagerGlobal}
+ *
+ * Through the layoutlib_create tool, the original  methods of WindowManagerGlobal have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ */
+public class WindowManagerGlobal_Delegate {
+
+    private static IWindowManager sService;
+
+    @LayoutlibDelegate
+    public static IWindowManager getWindowManagerService() {
+        return sService;
+    }
+
+    // ---- internal implementation stuff ----
+
+    public static void setWindowManagerService(IWindowManager service) {
+        sService = service;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 3ae660d..e2fced6 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -25,6 +25,7 @@
 import com.android.ide.common.rendering.api.StyleResourceValue;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.BridgeConstants;
+import com.android.layoutlib.bridge.android.view.WindowManagerImpl;
 import com.android.layoutlib.bridge.impl.ParserFactory;
 import com.android.layoutlib.bridge.impl.Stack;
 import com.android.resources.ResourceType;
@@ -61,13 +62,16 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.PowerManager;
+import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
 import android.view.BridgeInflater;
-import android.view.Surface;
+import android.view.CompatibilityInfoHolder;
+import android.view.Display;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.WindowManager;
 import android.view.textservice.TextServicesManager;
 
 import java.io.File;
@@ -95,7 +99,7 @@
     private final Configuration mConfig;
     private final ApplicationInfo mApplicationInfo;
     private final IProjectCallback mProjectCallback;
-    private final BridgeWindowManager mIWindowManager;
+    private final WindowManager mWindowManager;
 
     private Resources.Theme mTheme;
 
@@ -136,10 +140,10 @@
         mRenderResources = renderResources;
         mConfig = config;
 
-        mIWindowManager = new BridgeWindowManager(mConfig, metrics, Surface.ROTATION_0);
-
         mApplicationInfo = new ApplicationInfo();
         mApplicationInfo.targetSdkVersion = targetSdkVersion;
+
+        mWindowManager = new WindowManagerImpl(mMetrics);
     }
 
     /**
@@ -195,14 +199,14 @@
         return mRenderResources;
     }
 
-    public BridgeWindowManager getIWindowManager() {
-        return mIWindowManager;
-    }
-
     public Map<String, String> getDefaultPropMap(Object key) {
         return mDefaultPropMaps.get(key);
     }
 
+    public Configuration getConfiguration() {
+        return mConfig;
+    }
+
     /**
      * Adds a parser to the stack.
      * @param parser the parser to add.
@@ -428,10 +432,8 @@
             return TextServicesManager.getInstance();
         }
 
-        // AutoCompleteTextView and MultiAutoCompleteTextView want a window
-        // service. We don't have any but it's not worth an exception.
         if (WINDOW_SERVICE.equals(service)) {
-            return null;
+            return mWindowManager;
         }
 
         // needed by SearchView
@@ -440,7 +442,7 @@
         }
 
         if (POWER_SERVICE.equals(service)) {
-            return new PowerManager(new BridgePowerManager(), new Handler());
+            return new PowerManager(this, new BridgePowerManager(), new Handler());
         }
 
         throw new UnsupportedOperationException("Unsupported Service: " + service);
@@ -917,6 +919,24 @@
     }
 
     @Override
+    public Context createPackageContextAsUser(String arg0, int arg1, UserHandle user) {
+        // pass
+        return null;
+    }
+
+    @Override
+    public Context createConfigurationContext(Configuration overrideConfiguration) {
+        // pass
+        return null;
+    }
+
+    @Override
+    public Context createDisplayContext(Display display) {
+        // pass
+        return null;
+    }
+
+    @Override
     public String[] databaseList() {
         // pass
         return null;
@@ -1149,6 +1169,13 @@
     }
 
     @Override
+    public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5,
+            IntentFilter arg1, String arg2, Handler arg3) {
+        // pass
+        return null;
+    }
+
+    @Override
     public void removeStickyBroadcast(Intent arg0) {
         // pass
 
@@ -1187,6 +1214,24 @@
     }
 
     @Override
+    public void sendBroadcastAsUser(Intent intent, UserHandle user) {
+        // pass
+    }
+
+    @Override
+    public void sendBroadcastAsUser(Intent intent, UserHandle user,
+            String receiverPermission) {
+        // pass
+    }
+
+    @Override
+    public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
+            String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
+            int initialCode, String initialData, Bundle initialExtras) {
+        // pass
+    }
+
+    @Override
     public void sendStickyBroadcast(Intent arg0) {
         // pass
 
@@ -1200,6 +1245,24 @@
     }
 
     @Override
+    public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
+        // pass
+    }
+
+    @Override
+    public void sendStickyOrderedBroadcastAsUser(Intent intent,
+            UserHandle user, BroadcastReceiver resultReceiver,
+            Handler scheduler, int initialCode, String initialData,
+            Bundle initialExtras) {
+        // pass
+    }
+
+    @Override
+    public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
+        // pass
+    }
+
+    @Override
     public void setTheme(int arg0) {
         // pass
 
@@ -1261,6 +1324,18 @@
     }
 
     @Override
+    public ComponentName startServiceAsUser(Intent arg0, UserHandle arg1) {
+        // pass
+        return null;
+    }
+
+    @Override
+    public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) {
+        // pass
+        return false;
+    }
+
+    @Override
     public void unbindService(ServiceConnection arg0) {
         // pass
 
@@ -1299,4 +1374,10 @@
         Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "OBB not supported", null);
         return null;
     }
+
+    @Override
+    public CompatibilityInfoHolder getCompatibilityInfo(int displayId) {
+        // pass
+        return null;
+    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 6071a6b..1ccbc40 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -39,44 +39,33 @@
     }
 
     @Override
-    public void acquireWakeLock(int arg0, IBinder arg1, String arg2, WorkSource arg3)
+    public void acquireWakeLock(IBinder arg0, int arg1, String arg2, WorkSource arg3)
             throws RemoteException {
         // pass for now.
     }
 
     @Override
-    public void clearUserActivityTimeout(long arg0, long arg1) throws RemoteException {
-        // pass for now.
-    }
-
-    @Override
     public void crash(String arg0) throws RemoteException {
         // pass for now.
     }
 
     @Override
-    public int getSupportedWakeLockFlags() throws RemoteException {
-        // pass for now.
-        return 0;
-    }
-
-    @Override
-    public void goToSleep(long arg0) throws RemoteException {
+    public void goToSleep(long arg0, int arg1) throws RemoteException {
         // pass for now.
     }
 
     @Override
-    public void goToSleepWithReason(long arg0, int arg1) throws RemoteException {
+    public void nap(long arg0) throws RemoteException {
         // pass for now.
     }
 
     @Override
-    public void preventScreenOn(boolean arg0) throws RemoteException {
+    public void reboot(boolean confirm, String reason, boolean wait) {
         // pass for now.
     }
 
     @Override
-    public void reboot(String arg0) throws RemoteException {
+    public void shutdown(boolean confirm, boolean wait) {
         // pass for now.
     }
 
@@ -91,22 +80,17 @@
     }
 
     @Override
-    public void setAutoBrightnessAdjustment(float arg0) throws RemoteException {
+    public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float arg0) throws RemoteException {
         // pass for now.
     }
 
     @Override
-    public void setBacklightBrightness(int arg0) throws RemoteException {
+    public void setTemporaryScreenBrightnessSettingOverride(int arg0) throws RemoteException {
         // pass for now.
     }
 
     @Override
-    public void setMaximumScreenOffTimeount(int arg0) throws RemoteException {
-        // pass for now.
-    }
-
-    @Override
-    public void setPokeLock(int arg0, IBinder arg1, String arg2) throws RemoteException {
+    public void setMaximumScreenOffTimeoutFromDeviceAdmin(int arg0) throws RemoteException {
         // pass for now.
     }
 
@@ -121,12 +105,18 @@
     }
 
     @Override
-    public void userActivity(long arg0, boolean arg1) throws RemoteException {
+    public boolean isWakeLockLevelSupported(int level) throws RemoteException {
+        // pass for now.
+        return true;
+    }
+
+    @Override
+    public void userActivity(long time, int event, int flags) throws RemoteException {
         // pass for now.
     }
 
     @Override
-    public void userActivityWithForce(long arg0, boolean arg1, boolean arg2) throws RemoteException {
+    public void wakeUp(long time) throws RemoteException {
         // pass for now.
     }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
index 379fb81..fa660e6 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -47,12 +47,17 @@
     }
 
     @Override
-    public void resized(int arg0, int arg1, Rect arg2, Rect arg3,
+    public void resized(Rect arg1, Rect arg2, Rect arg3,
             boolean arg4, Configuration arg5) throws RemoteException {
         // pass for now.
     }
 
     @Override
+    public void moved(int arg0, int arg1) throws RemoteException {
+        // pass for now.
+    }
+
+    @Override
     public void dispatchScreenState(boolean on) throws RemoteException {
         // pass for now.
     }
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
deleted file mode 100644
index 8ab875f..0000000
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
+++ /dev/null
@@ -1,458 +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.
- */
-
-package com.android.layoutlib.bridge.android;
-
-import com.android.internal.view.IInputContext;
-import com.android.internal.view.IInputMethodClient;
-
-import android.content.res.CompatibilityInfo;
-import android.content.res.Configuration;
-import android.graphics.Bitmap;
-import android.graphics.Point;
-import android.os.IBinder;
-import android.os.IRemoteCallback;
-import android.os.RemoteException;
-import android.util.DisplayMetrics;
-import android.view.Display;
-import android.view.Display_Delegate;
-import android.view.Gravity;
-import android.view.IApplicationToken;
-import android.view.IOnKeyguardExitResult;
-import android.view.IRotationWatcher;
-import android.view.IWindowManager;
-import android.view.IWindowSession;
-import android.view.InputChannel;
-import android.view.InputDevice;
-import android.view.InputEvent;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-
-import java.util.List;
-
-/**
- * Basic implementation of {@link IWindowManager} so that {@link Display} (and
- * {@link Display_Delegate}) can return a valid instance.
- */
-public class BridgeWindowManager implements IWindowManager {
-
-    private final Configuration mConfig;
-    private final DisplayMetrics mMetrics;
-    private final int mRotation;
-
-    public BridgeWindowManager(Configuration config, DisplayMetrics metrics, int rotation) {
-        mConfig = config;
-        mMetrics = metrics;
-        mRotation = rotation;
-    }
-
-    // custom API.
-
-    public DisplayMetrics getMetrics() {
-        return mMetrics;
-    }
-
-    // ---- implementation of IWindowManager that we care about ----
-
-    @Override
-    public int getRotation() throws RemoteException {
-        return mRotation;
-    }
-
-    @Override
-    public int getMaximumSizeDimension() throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public void getCurrentSizeRange(Point smallestSize, Point largestSize) {
-    }
-
-    @Override
-    public void getDisplaySize(Point arg0) throws RemoteException {
-    }
-
-    @Override
-    public void getRealDisplaySize(Point arg0) throws RemoteException {
-    }
-
-    // ---- unused implementation of IWindowManager ----
-
-    @Override
-    public boolean hasSystemNavBar() throws RemoteException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, boolean arg4)
-            throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void addWindowToken(IBinder arg0, int arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void clearForcedDisplaySize() throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void closeSystemDialogs(String arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void disableKeyguard(IBinder arg0, String arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void executeAppTransition() throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void exitKeyguardSecurely(IOnKeyguardExitResult arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void freezeRotation(int arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public float getAnimationScale(int arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public float[] getAnimationScales() throws RemoteException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public int getAppOrientation(IApplicationToken arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getPendingAppTransition() throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public boolean inKeyguardRestrictedInputMode() throws RemoteException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean inputMethodClientHasFocus(IInputMethodClient arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean isKeyguardLocked() throws RemoteException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean isKeyguardSecure() throws RemoteException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean isViewServerRunning() throws RemoteException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public void moveAppToken(int arg0, IBinder arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void moveAppTokensToBottom(List<IBinder> arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void moveAppTokensToTop(List<IBinder> arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public IWindowSession openSession(IInputMethodClient arg0, IInputContext arg1)
-            throws RemoteException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public void overridePendingAppTransition(String arg0, int arg1, int arg2,
-            IRemoteCallback startedCallback) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
-            int startHeight) throws RemoteException {
-        // TODO Auto-generated method stub
-    }
-
-    @Override
-    public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
-            IRemoteCallback startedCallback, boolean delayed) throws RemoteException {
-        // TODO Auto-generated method stub
-    }
-
-    @Override
-    public void pauseKeyDispatching(IBinder arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void prepareAppTransition(int arg0, boolean arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void reenableKeyguard(IBinder arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void removeAppToken(IBinder arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void removeWindowToken(IBinder arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void resumeKeyDispatching(IBinder arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public Bitmap screenshotApplications(IBinder arg0, int arg1, int arg2) throws RemoteException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public void setAnimationScale(int arg0, float arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setAnimationScales(float[] arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setAppGroupId(IBinder arg0, int arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setAppOrientation(IApplicationToken arg0, int arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setAppStartingWindow(IBinder arg0, String arg1, int arg2, CompatibilityInfo arg3,
-            CharSequence arg4, int arg5, int arg6, int arg7, IBinder arg8, boolean arg9)
-            throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setAppVisibility(IBinder arg0, boolean arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setAppWillBeHidden(IBinder arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setEventDispatching(boolean arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setFocusedApp(IBinder arg0, boolean arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setForcedDisplaySize(int arg0, int arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setInTouchMode(boolean arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNewConfiguration(Configuration arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateRotation(boolean arg0, boolean arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-    }
-
-    @Override
-    public void setStrictModeVisualIndicatorPreference(String arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void showStrictModeViolation(boolean arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void startAppFreezingScreen(IBinder arg0, int arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public boolean startViewServer(int arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public void statusBarVisibilityChanged(int arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void stopAppFreezingScreen(IBinder arg0, boolean arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public boolean stopViewServer() throws RemoteException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public void thawRotation() throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public Configuration updateOrientationFromAppTokens(Configuration arg0, IBinder arg1)
-            throws RemoteException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public int watchRotation(IRotationWatcher arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public void waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
-        // TODO Auto-generated method stub
-    }
-
-    @Override
-    public IBinder asBinder() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public int getPreferredOptionsPanelGravity() throws RemoteException {
-        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
-    }
-
-    @Override
-    public void dismissKeyguard() {
-    }
-
-    @Override
-    public boolean hasNavigationBar() {
-        return false; // should this return something else?
-    }
-
-    @Override
-    public void lockNow() {
-        // TODO Auto-generated method stub
-    }
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index 6fb599d..67b0a9c 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -45,7 +45,24 @@
     }
 
     @Override
-    public int addWithoutInputChannel(IWindow arg0, int seq, LayoutParams arg1, int arg2, Rect arg3)
+    public int addToDisplay(IWindow arg0, int seq, LayoutParams arg1, int arg2, int displayId,
+                            Rect arg3, InputChannel outInputchannel)
+            throws RemoteException {
+        // pass for now.
+        return 0;
+    }
+
+    @Override
+    public int addWithoutInputChannel(IWindow arg0, int seq, LayoutParams arg1, int arg2,
+                                      Rect arg3)
+            throws RemoteException {
+        // pass for now.
+        return 0;
+    }
+
+    @Override
+    public int addToDisplayWithoutInputChannel(IWindow arg0, int seq, LayoutParams arg1, int arg2,
+                                               int displayId, Rect arg3)
             throws RemoteException {
         // pass for now.
         return 0;
@@ -167,8 +184,19 @@
     }
 
     @Override
+    public void setUniverseTransform(IBinder window, float alpha, float offx, float offy,
+            float dsdx, float dtdx, float dsdy, float dtdy) {
+        // pass for now.
+    }
+
+    @Override
     public IBinder asBinder() {
         // pass for now.
         return null;
     }
+
+    @Override
+    public void onRectangleOnScreenRequested(IBinder window, Rect rectangle, boolean immediate) {
+        // pass for now.
+    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java
new file mode 100644
index 0000000..9a633bf
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java
@@ -0,0 +1,64 @@
+/*
+ * 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.layoutlib.bridge.android.view;
+
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.View;
+import android.view.WindowManager;
+
+public class WindowManagerImpl implements WindowManager {
+
+    private final DisplayMetrics mMetrics;
+    private final Display mDisplay;
+
+    public WindowManagerImpl(DisplayMetrics metrics) {
+        mMetrics = metrics;
+
+        DisplayInfo info = new DisplayInfo();
+        info.logicalHeight = mMetrics.heightPixels;
+        info.logicalWidth = mMetrics.widthPixels;
+        mDisplay = new Display(null, Display.DEFAULT_DISPLAY, info, null);
+    }
+
+    @Override
+    public Display getDefaultDisplay() {
+        return mDisplay;
+    }
+
+
+    @Override
+    public void addView(View arg0, android.view.ViewGroup.LayoutParams arg1) {
+        // pass
+    }
+
+    @Override
+    public void removeView(View arg0) {
+        // pass
+    }
+
+    @Override
+    public void updateViewLayout(View arg0, android.view.ViewGroup.LayoutParams arg1) {
+        // pass
+    }
+
+
+    @Override
+    public void removeViewImmediate(View arg0) {
+        // pass
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index ec9ec75..ea9d8d9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -56,7 +56,7 @@
  *
  * It also provides a few utility methods to configure the content of the layout.
  */
-public abstract class CustomBar extends LinearLayout {
+abstract class CustomBar extends LinearLayout {
 
     protected abstract TextView getStyleableTextView();
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java
deleted file mode 100644
index 5ddb34e..0000000
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java
+++ /dev/null
@@ -1,56 +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.
- */
-
-package com.android.layoutlib.bridge.bars;
-
-import com.android.resources.Density;
-import com.android.resources.ResourceType;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LevelListDrawable;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-public class TabletSystemBar extends CustomBar {
-
-    public TabletSystemBar(Context context, Density density) throws XmlPullParserException {
-        super(context, density, LinearLayout.HORIZONTAL,
-                "/bars/tablet_system_bar.xml", "tablet_system_bar.xml");
-
-        setBackgroundColor(0xFF000000);
-
-        // Cannot access the inside items through id because no R.id values have been
-        // created for them.
-        // We do know the order though.
-        loadIcon(0, "ic_sysbar_back.png", density);
-        loadIcon(1, "ic_sysbar_home.png", density);
-        loadIcon(2, "ic_sysbar_recent.png", density);
-        // 3 is the spacer
-        loadIcon(4, "stat_sys_wifi_signal_4_fully.png", density);
-        Drawable drawable = loadIcon(5, ResourceType.DRAWABLE, "stat_sys_battery_charge");
-        if (drawable instanceof LevelListDrawable) {
-            ((LevelListDrawable) drawable).setLevel(100);
-        }
-    }
-
-    @Override
-    protected TextView getStyleableTextView() {
-        return null;
-    }
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index 1db7994..f109e39 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -103,7 +103,8 @@
 
         // setup the display Metrics.
         DisplayMetrics metrics = new DisplayMetrics();
-        metrics.densityDpi = hardwareConfig.getDensity().getDpiValue();
+        metrics.densityDpi = metrics.noncompatDensityDpi =
+                hardwareConfig.getDensity().getDpiValue();
 
         metrics.density = metrics.noncompatDensity =
                 metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
@@ -340,6 +341,7 @@
         } else {
             config.smallestScreenWidthDp = config.screenWidthDp;
         }
+        config.densityDpi = density.getDpiValue();
 
         // never run in compat mode:
         config.compatScreenWidthDp = config.screenWidthDp;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 7169db3..c14af4a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -43,17 +43,14 @@
 import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
 import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.layoutlib.bridge.bars.CustomBar;
 import com.android.layoutlib.bridge.bars.FakeActionBar;
 import com.android.layoutlib.bridge.bars.NavigationBar;
 import com.android.layoutlib.bridge.bars.StatusBar;
-import com.android.layoutlib.bridge.bars.TabletSystemBar;
 import com.android.layoutlib.bridge.bars.TitleBar;
 import com.android.layoutlib.bridge.impl.binding.FakeAdapter;
 import com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
 import com.android.resources.ResourceType;
 import com.android.resources.ScreenOrientation;
-import com.android.resources.ScreenSize;
 import com.android.util.Pair;
 
 import org.xmlpull.v1.XmlPullParserException;
@@ -72,11 +69,15 @@
 import android.util.TypedValue;
 import android.view.AttachInfo_Accessor;
 import android.view.BridgeInflater;
+import android.view.IWindowManager;
+import android.view.IWindowManagerImpl;
+import android.view.Surface;
 import android.view.View;
 import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.ViewGroup.MarginLayoutParams;
+import android.view.WindowManagerGlobal_Delegate;
 import android.widget.AbsListView;
 import android.widget.AbsSpinner;
 import android.widget.AdapterView;
@@ -190,6 +191,14 @@
         findActionBar(resources, metrics);
         findNavigationBar(resources, metrics);
 
+        // FIXME: find those out, and possibly add them to the render params
+        boolean hasSystemNavBar = true;
+        boolean hasNavigationBar = true;
+        IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(),
+                metrics, Surface.ROTATION_0,
+                hasSystemNavBar, hasNavigationBar);
+        WindowManagerGlobal_Delegate.setWindowManagerService(iwm);
+
         // build the inflater and parser.
         mInflater = new BridgeInflater(context, params.getProjectCallback());
         context.setBridgeInflater(mInflater);
@@ -264,7 +273,7 @@
                  * we're creating the following layout
                  *
                    +-------------------------------------------------+
-                   | Status bar (except for xlarge tablets)          |
+                   | Status bar (always)                             |
                    +-------------------------------------------------+
                    | (Layout with background drawable)               |
                    | +---------------------------------------------+ |
@@ -356,15 +365,8 @@
                         mNavigationBarSize > 0) {
                     // system bar
                     try {
-                        CustomBar navigationBar;
-                        if (hardwareConfig.getScreenSize() == ScreenSize.XLARGE) {
-                            navigationBar = new TabletSystemBar(context,
-                                    hardwareConfig.getDensity());
-                        } else {
-                            navigationBar = new NavigationBar(context,
-                                    hardwareConfig.getDensity(), LinearLayout.HORIZONTAL);
-                        }
-
+                        NavigationBar navigationBar = new NavigationBar(context,
+                                hardwareConfig.getDensity(), LinearLayout.HORIZONTAL);
                         navigationBar.setLayoutParams(
                                 new LinearLayout.LayoutParams(
                                         LayoutParams.MATCH_PARENT, mNavigationBarSize));
@@ -1028,27 +1030,23 @@
     }
 
     private void findStatusBar(RenderResources resources, DisplayMetrics metrics) {
-        // status bar is on for all but x-large device
-        HardwareConfig hardwareConfig = getParams().getHardwareConfig();
-        if (hardwareConfig.getScreenSize() != ScreenSize.XLARGE) {
-            boolean windowFullscreen = getBooleanThemeValue(resources,
-                    "windowFullscreen", false /*defaultValue*/);
+        boolean windowFullscreen = getBooleanThemeValue(resources,
+                "windowFullscreen", false /*defaultValue*/);
 
-            if (windowFullscreen == false && mWindowIsFloating == false) {
-                // default value
-                mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
+        if (windowFullscreen == false && mWindowIsFloating == false) {
+            // default value
+            mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
 
-                // get the real value
-                ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
-                        "status_bar_height");
+            // get the real value
+            ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
+                    "status_bar_height");
 
-                if (value != null) {
-                    TypedValue typedValue = ResourceHelper.getValue("status_bar_height",
-                            value.getValue(), true /*requireUnit*/);
-                    if (typedValue != null) {
-                        // compute the pixel value based on the display metrics
-                        mStatusBarSize = (int)typedValue.getDimension(metrics);
-                    }
+            if (value != null) {
+                TypedValue typedValue = ResourceHelper.getValue("status_bar_height",
+                        value.getValue(), true /*requireUnit*/);
+                if (typedValue != null) {
+                    // compute the pixel value based on the display metrics
+                    mStatusBarSize = (int)typedValue.getDimension(metrics);
                 }
             }
         }
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 5109810..80a1a60 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
@@ -110,11 +110,13 @@
         "android.os.Handler#sendMessageAtTime",
         "android.os.HandlerThread#run",
         "android.os.Build#getString",
-        "android.view.Display#getWindowManager",
+        "android.view.Choreographer#getRefreshRate",
+        "android.view.Display#updateDisplayInfoLocked",
         "android.view.LayoutInflater#rInflate",
         "android.view.LayoutInflater#parseInclude",
         "android.view.View#isInEditMode",
         "android.view.ViewRootImpl#isInTouchMode",
+        "android.view.WindowManagerGlobal#getWindowManagerService",
         "android.view.inputmethod.InputMethodManager#getInstance",
         "com.android.internal.util.XmlUtils#convertValueToInt",
         "com.android.internal.textservice.ITextServicesManager$Stub#asInterface",
diff --git a/tools/preload/Record.java b/tools/preload/Record.java
index ac99f1c..14e9201 100644
--- a/tools/preload/Record.java
+++ b/tools/preload/Record.java
@@ -28,12 +28,16 @@
             "com.google.android.apps.maps\\u003AFriendService",
             "com.google.android.apps.maps:driveabout",
             "com.google.android.apps.maps\\u003Adriveabout",
+            "com.google.android.apps.maps:GoogleLocationService",
+            "com.google.android.apps.maps\\u003AGoogleLocationService",
             "com.google.android.apps.maps:LocationFriendService",
             "com.google.android.apps.maps\\u003ALocationFriendService",
             "com.google.android.apps.maps:MapsBackgroundService",
             "com.google.android.apps.maps\\u003AMapsBackgroundService",
             "com.google.android.apps.maps:NetworkLocationService",
             "com.google.android.apps.maps\\u003ANetworkLocationService",
+            "com.android.chrome:sandboxed_process",
+            "com.android.chrome\\u003Asandboxed_process",
             "com.android.fakeoemfeatures:background",
             "com.android.fakeoemfeatures\\u003Abackground",
             "com.android.fakeoemfeatures:core",
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index 673a650..1579e6a4 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -790,7 +790,7 @@
     if (AudioTrack::getMinFrameCount(&output, AUDIO_STREAM_VOICE_CALL,
         sampleRate) != NO_ERROR || output <= 0 ||
         AudioRecord::getMinFrameCount(&input, sampleRate,
-        AUDIO_FORMAT_PCM_16_BIT, 1) != NO_ERROR || input <= 0) {
+        AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO) != NO_ERROR || input <= 0) {
         ALOGE("cannot compute frame count");
         return false;
     }
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 6b08074..55de065 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -106,5 +106,7 @@
     Messenger getWifiStateMachineMessenger();
 
     String getConfigFile();
+
+    void captivePortalCheckComplete();
 }
 
diff --git a/wifi/java/android/net/wifi/RssiPacketCountInfo.java b/wifi/java/android/net/wifi/RssiPacketCountInfo.java
new file mode 100644
index 0000000..f549e1d
--- /dev/null
+++ b/wifi/java/android/net/wifi/RssiPacketCountInfo.java
@@ -0,0 +1,71 @@
+/*
+ * 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.net.wifi;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Bundle of RSSI and packet count information, for WiFi watchdog
+ *
+ * @see WifiWatchdogStateMachine
+ *
+ * @hide
+ */
+public class RssiPacketCountInfo implements Parcelable {
+
+    public int rssi;
+
+    public int txgood;
+
+    public int txbad;
+
+    public RssiPacketCountInfo() {
+        rssi = txgood = txbad = 0;
+    }
+
+    private RssiPacketCountInfo(Parcel in) {
+        rssi = in.readInt();
+        txgood = in.readInt();
+        txbad = in.readInt();
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(rssi);
+        out.writeInt(txgood);
+        out.writeInt(txbad);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Parcelable.Creator<RssiPacketCountInfo> CREATOR =
+            new Parcelable.Creator<RssiPacketCountInfo>() {
+        @Override
+        public RssiPacketCountInfo createFromParcel(Parcel in) {
+            return new RssiPacketCountInfo(in);
+        }
+
+        @Override
+        public RssiPacketCountInfo[] newArray(int size) {
+            return new RssiPacketCountInfo[size];
+        }
+    };
+}
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 32261de..9977419 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -28,6 +28,10 @@
 public class ScanResult implements Parcelable {
     /** The network name. */
     public String SSID;
+
+    /** Ascii encoded SSID. This will replace SSID when we deprecate it. @hide */
+    public WifiSsid wifiSsid;
+
     /** The address of the access point. */
     public String BSSID;
     /**
@@ -47,19 +51,35 @@
     public int frequency;
 
     /**
-     * We'd like to obtain the following attributes,
-     * but they are not reported via the socket
-     * interface, even though they are known
-     * internally by wpa_supplicant.
-     * {@hide}
+     * Time Synchronization Function (tsf) timestamp in microseconds when
+     * this result was last seen.
      */
-    public ScanResult(String SSID, String BSSID, String caps, int level, int frequency) {
-        this.SSID = SSID;
+     public long timestamp;
+
+    /** {@hide} */
+    public ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency,
+            long tsf) {
+        this.wifiSsid = wifiSsid;
+        this.SSID = (wifiSsid != null) ? wifiSsid.toString() : WifiSsid.NONE;
         this.BSSID = BSSID;
         this.capabilities = caps;
         this.level = level;
         this.frequency = frequency;
-        //networkConfig = null;
+        this.timestamp = tsf;
+    }
+
+
+    /** copy constructor {@hide} */
+    public ScanResult(ScanResult source) {
+        if (source != null) {
+            wifiSsid = source.wifiSsid;
+            SSID = source.SSID;
+            BSSID = source.BSSID;
+            capabilities = source.capabilities;
+            level = source.level;
+            frequency = source.frequency;
+            timestamp = source.timestamp;
+        }
     }
 
     @Override
@@ -68,7 +88,7 @@
         String none = "<none>";
 
         sb.append("SSID: ").
-            append(SSID == null ? none : SSID).
+            append(wifiSsid == null ? WifiSsid.NONE : wifiSsid).
             append(", BSSID: ").
             append(BSSID == null ? none : BSSID).
             append(", capabilities: ").
@@ -76,7 +96,9 @@
             append(", level: ").
             append(level).
             append(", frequency: ").
-            append(frequency);
+            append(frequency).
+            append(", timestamp: ").
+            append(timestamp);
 
         return sb.toString();
     }
@@ -88,23 +110,34 @@
 
     /** Implement the Parcelable interface {@hide} */
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(SSID);
+        if (wifiSsid != null) {
+            dest.writeInt(1);
+            wifiSsid.writeToParcel(dest, flags);
+        } else {
+            dest.writeInt(0);
+        }
         dest.writeString(BSSID);
         dest.writeString(capabilities);
         dest.writeInt(level);
         dest.writeInt(frequency);
+        dest.writeLong(timestamp);
     }
 
     /** Implement the Parcelable interface {@hide} */
     public static final Creator<ScanResult> CREATOR =
         new Creator<ScanResult>() {
             public ScanResult createFromParcel(Parcel in) {
+                WifiSsid wifiSsid = null;
+                if (in.readInt() == 1) {
+                    wifiSsid = WifiSsid.CREATOR.createFromParcel(in);
+                }
                 return new ScanResult(
-                    in.readString(),
+                    wifiSsid,
                     in.readString(),
                     in.readString(),
                     in.readInt(),
-                    in.readInt()
+                    in.readInt(),
+                    in.readLong()
                 );
             }
 
diff --git a/wifi/java/android/net/wifi/StateChangeResult.java b/wifi/java/android/net/wifi/StateChangeResult.java
index b15c4a6..c334b91 100644
--- a/wifi/java/android/net/wifi/StateChangeResult.java
+++ b/wifi/java/android/net/wifi/StateChangeResult.java
@@ -23,15 +23,16 @@
  * @hide
  */
 public class StateChangeResult {
-    StateChangeResult(int networkId, String SSID, String BSSID, SupplicantState state) {
+    StateChangeResult(int networkId, WifiSsid wifiSsid, String BSSID,
+            SupplicantState state) {
         this.state = state;
-        this.SSID = SSID;
+        this.wifiSsid= wifiSsid;
         this.BSSID = BSSID;
         this.networkId = networkId;
     }
 
     int networkId;
-    String SSID;
+    WifiSsid wifiSsid;
     String BSSID;
     SupplicantState state;
 }
diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java
index 6aeac5f..d1e9b67 100644
--- a/wifi/java/android/net/wifi/SupplicantStateTracker.java
+++ b/wifi/java/android/net/wifi/SupplicantStateTracker.java
@@ -25,6 +25,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.Parcelable;
+import android.os.UserHandle;
 import android.util.Log;
 
 /**
@@ -145,7 +146,7 @@
                 WifiManager.EXTRA_SUPPLICANT_ERROR,
                 WifiManager.ERROR_AUTHENTICATING);
         }
-        mContext.sendStickyBroadcast(intent);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     /********************************************************
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index e9f3480..84506b6 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -36,6 +36,7 @@
 import android.os.Message;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -601,7 +602,7 @@
         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);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     /**
@@ -611,7 +612,7 @@
         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);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     void loadConfiguredNetworks() {
@@ -1317,7 +1318,13 @@
 
         value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.ssidVarName);
         if (!TextUtils.isEmpty(value)) {
-            config.SSID = value;
+            if (value.charAt(0) != '"') {
+                config.SSID = "\"" + WifiSsid.createFromHex(value).toString() + "\"";
+                //TODO: convert a hex string that is not UTF-8 decodable to a P-formatted
+                //supplicant string
+            } else {
+                config.SSID = value;
+            }
         } else {
             config.SSID = null;
         }
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 0a846fd..c4fe1b4 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -524,6 +524,27 @@
     }
     */
 
+    /** {@hide} */
+    public String getPrintableSsid() {
+        if (SSID == null) return "";
+        final int length = SSID.length();
+        if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') {
+            return SSID.substring(1, length - 1);
+        }
+
+        /** The ascii-encoded string format is P"<ascii-encoded-string>"
+         * The decoding is implemented in the supplicant for a newly configured
+         * network.
+         */
+        if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') &&
+                (SSID.charAt(length-1) == '"')) {
+            WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded(
+                    SSID.substring(2, length - 1));
+            return wifiSsid.toString();
+        }
+        return SSID;
+    }
+
     private static BitSet readBitSet(Parcel src) {
         int cardinality = src.readInt();
 
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 1f1cfdd..05db571 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -20,6 +20,7 @@
 import android.os.Parcel;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkUtils;
+import android.text.TextUtils;
 
 import java.net.InetAddress;
 import java.net.Inet6Address;
@@ -31,6 +32,7 @@
  * is in the process of being set up.
  */
 public class WifiInfo implements Parcelable {
+    private static final String TAG = "WifiInfo";
     /**
      * This is the map described in the Javadoc comment above. The positions
      * of the elements of the array must correspond to the ordinal values
@@ -57,7 +59,7 @@
 
     private SupplicantState mSupplicantState;
     private String mBSSID;
-    private String mSSID;
+    private WifiSsid mWifiSsid;
     private int mNetworkId;
     private boolean mHiddenSSID;
     /** Received Signal Strength Indicator */
@@ -77,7 +79,7 @@
     private boolean mMeteredHint;
 
     WifiInfo() {
-        mSSID = null;
+        mWifiSsid = null;
         mBSSID = null;
         mNetworkId = -1;
         mSupplicantState = SupplicantState.UNINITIALIZED;
@@ -94,7 +96,7 @@
         if (source != null) {
             mSupplicantState = source.mSupplicantState;
             mBSSID = source.mBSSID;
-            mSSID = source.mSSID;
+            mWifiSsid = source.mWifiSsid;
             mNetworkId = source.mNetworkId;
             mHiddenSSID = source.mHiddenSSID;
             mRssi = source.mRssi;
@@ -105,21 +107,34 @@
         }
     }
 
-    void setSSID(String SSID) {
-        mSSID = SSID;
+    void setSSID(WifiSsid wifiSsid) {
+        mWifiSsid = wifiSsid;
         // network is considered not hidden by default
         mHiddenSSID = false;
     }
 
     /**
      * Returns the service set identifier (SSID) of the current 802.11 network.
-     * If the SSID is an ASCII string, it will be returned surrounded by double
-     * quotation marks.Otherwise, it is returned as a string of hex digits. The
+     * If the SSID can be decoded as UTF-8, it will be returned surrounded by double
+     * quotation marks. Otherwise, it is returned as a string of hex digits. The
      * SSID may be {@code null} if there is no network currently connected.
      * @return the SSID
      */
     public String getSSID() {
-        return mSSID;
+        if (mWifiSsid != null) {
+            String unicode = mWifiSsid.toString();
+            if (!TextUtils.isEmpty(unicode)) {
+                return "\"" + unicode + "\"";
+            } else {
+                return mWifiSsid.getHexString();
+            }
+        }
+        return WifiSsid.NONE;
+    }
+
+    /** @hide */
+    public WifiSsid getWifiSsid() {
+        return mWifiSsid;
     }
 
     void setBSSID(String BSSID) {
@@ -279,7 +294,7 @@
         StringBuffer sb = new StringBuffer();
         String none = "<none>";
 
-        sb.append("SSID: ").append(mSSID == null ? none : mSSID).
+        sb.append("SSID: ").append(mWifiSsid == null ? WifiSsid.NONE : mWifiSsid).
             append(", BSSID: ").append(mBSSID == null ? none : mBSSID).
             append(", MAC: ").append(mMacAddress == null ? none : mMacAddress).
             append(", Supplicant state: ").
@@ -308,7 +323,12 @@
         } else {
             dest.writeByte((byte)0);
         }
-        dest.writeString(getSSID());
+        if (mWifiSsid != null) {
+            dest.writeInt(1);
+            mWifiSsid.writeToParcel(dest, flags);
+        } else {
+            dest.writeInt(0);
+        }
         dest.writeString(mBSSID);
         dest.writeString(mMacAddress);
         dest.writeInt(mMeteredHint ? 1 : 0);
@@ -328,7 +348,9 @@
                         info.setInetAddress(InetAddress.getByAddress(in.createByteArray()));
                     } catch (UnknownHostException e) {}
                 }
-                info.setSSID(in.readString());
+                if (in.readInt() == 1) {
+                    info.mWifiSsid = WifiSsid.CREATOR.createFromParcel(in);
+                }
                 info.mBSSID = in.readString();
                 info.mMacAddress = in.readString();
                 info.mMeteredHint = in.readInt() != 0;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 36f38f9..b871cdc 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -23,13 +23,17 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.WorkSource;
 import android.os.Messenger;
+import android.util.Log;
 import android.util.SparseArray;
 
+import java.util.concurrent.CountDownLatch;
+
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 
@@ -58,6 +62,7 @@
  */
 public class WifiManager {
 
+    private static final String TAG = "WifiManager";
     // Supplicant error codes:
     /**
      * The error code if there was a problem authenticating.
@@ -481,9 +486,6 @@
     /** @hide */
     public static final int DATA_ACTIVITY_INOUT        = 0x03;
 
-    IWifiManager mService;
-    Handler mHandler;
-
     /* Maximum number of active locks we allow.
      * This limit was added to prevent apps from creating a ridiculous number
      * of locks and crashing the system by overflowing the global ref table.
@@ -493,19 +495,33 @@
     /* Number of currently active WifiLocks and MulticastLocks */
     private int mActiveLockCount;
 
+    private Context mContext;
+    IWifiManager mService;
+
+    private static final int INVALID_KEY = 0;
+    private int mListenerKey = 1;
+    private final SparseArray mListenerMap = new SparseArray();
+    private final Object mListenerMapLock = new Object();
+
+    private AsyncChannel mAsyncChannel = new AsyncChannel();
+    private ServiceHandler mHandler;
+    private Messenger mWifiServiceMessenger;
+    private final CountDownLatch mConnected = new CountDownLatch(1);
+
     /**
      * Create a new WifiManager instance.
      * Applications will almost always want to use
      * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
      * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
+     * @param context the application context
      * @param service the Binder interface
-     * @param handler target for messages
      * @hide - hide this because it takes in a parameter of type IWifiManager, which
      * is a system private class.
      */
-    public WifiManager(IWifiManager service, Handler handler) {
+    public WifiManager(Context context, IWifiManager service) {
+        mContext = context;
         mService = service;
-        mHandler = handler;
+        init();
     }
 
     /**
@@ -524,7 +540,8 @@
      * <li>allowedGroupCiphers</li>
      * </ul>
      * @return a list of network configurations in the form of a list
-     * of {@link WifiConfiguration} objects.
+     * of {@link WifiConfiguration} objects. Upon failure to fetch or
+     * when when Wi-Fi is turned off, it can be null.
      */
     public List<WifiConfiguration> getConfiguredNetworks() {
         try {
@@ -890,6 +907,17 @@
     }
 
     /**
+     * Return TX packet counter, for CTS test of WiFi watchdog.
+     * @param listener is the interface to receive result
+     *
+     * @hide for CTS test only
+     */
+    public void getTxPacketCount(TxPacketCountListener listener) {
+        validateChannel();
+        mAsyncChannel.sendMessage(RSSI_PKTCNT_FETCH, 0, putListener(listener));
+    }
+
+    /**
      * Calculates the level of the signal. This should be used any time a signal
      * is being shown.
      *
@@ -1127,11 +1155,18 @@
     /** @hide */
     public static final int DISABLE_NETWORK_SUCCEEDED       = BASE + 19;
 
+    /** @hide */
+    public static final int RSSI_PKTCNT_FETCH               = BASE + 20;
+    /** @hide */
+    public static final int RSSI_PKTCNT_FETCH_SUCCEEDED     = BASE + 21;
+    /** @hide */
+    public static final int RSSI_PKTCNT_FETCH_FAILED        = BASE + 22;
+
     /* For system use only */
     /** @hide */
-    public static final int ENABLE_TRAFFIC_STATS_POLL       = BASE + 21;
+    public static final int ENABLE_TRAFFIC_STATS_POLL       = BASE + 31;
     /** @hide */
-    public static final int TRAFFIC_STATS_POLL              = BASE + 22;
+    public static final int TRAFFIC_STATS_POLL              = BASE + 32;
 
 
     /**
@@ -1168,15 +1203,6 @@
     /** WPS timed out {@hide} */
     public static final int WPS_TIMED_OUT               = 7;
 
-    /** Interface for callback invocation when framework channel is lost {@hide} */
-    public interface ChannelListener {
-        /**
-         * The channel to the framework has been disconnected.
-         * Application could try re-initializing using {@link #initialize}
-         */
-        public void onChannelDisconnected();
-    }
-
     /** Interface for callback invocation on an application action {@hide} */
     public interface ActionListener {
         /** The operation succeeded */
@@ -1205,132 +1231,154 @@
         public void onFailure(int reason);
     }
 
-    /**
-     * A channel that connects the application to the Wifi framework.
-     * Most operations require a Channel as an argument. An instance of Channel is obtained
-     * by doing a call on {@link #initialize}
-     * @hide
-     */
-    public static class Channel {
-        Channel(Looper looper, ChannelListener l) {
-            mAsyncChannel = new AsyncChannel();
-            mHandler = new WifiHandler(looper);
-            mChannelListener = l;
-        }
-        private ChannelListener mChannelListener;
-        private SparseArray<Object> mListenerMap = new SparseArray<Object>();
-        private Object mListenerMapLock = new Object();
-        private int mListenerKey = 0;
-        private static final int INVALID_KEY = -1;
+    /** Interface for callback invocation on a TX packet count poll action {@hide} */
+    public interface TxPacketCountListener {
+        /**
+         * The operation succeeded
+         * @param count TX packet counter
+         */
+        public void onSuccess(int count);
+        /**
+         * The operation failed
+         * @param reason The reason for failure could be one of
+         * {@link #ERROR}, {@link #IN_PROGRESS} or {@link #BUSY}
+         */
+        public void onFailure(int reason);
+    }
 
-        AsyncChannel mAsyncChannel;
-        WifiHandler mHandler;
-        class WifiHandler extends Handler {
-            WifiHandler(Looper looper) {
-                super(looper);
-            }
-
-            @Override
-            public void handleMessage(Message message) {
-                Object listener = removeListener(message.arg2);
-                switch (message.what) {
-                    case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
-                        if (mChannelListener != null) {
-                            mChannelListener.onChannelDisconnected();
-                            mChannelListener = null;
-                        }
-                        break;
-                        /* ActionListeners grouped together */
-                    case WifiManager.CONNECT_NETWORK_FAILED:
-                    case WifiManager.FORGET_NETWORK_FAILED:
-                    case WifiManager.SAVE_NETWORK_FAILED:
-                    case WifiManager.CANCEL_WPS_FAILED:
-                    case WifiManager.DISABLE_NETWORK_FAILED:
-                        if (listener != null) {
-                            ((ActionListener) listener).onFailure(message.arg1);
-                        }
-                        break;
-                        /* ActionListeners grouped together */
-                    case WifiManager.CONNECT_NETWORK_SUCCEEDED:
-                    case WifiManager.FORGET_NETWORK_SUCCEEDED:
-                    case WifiManager.SAVE_NETWORK_SUCCEEDED:
-                    case WifiManager.CANCEL_WPS_SUCCEDED:
-                    case WifiManager.DISABLE_NETWORK_SUCCEEDED:
-                        if (listener != null) {
-                            ((ActionListener) listener).onSuccess();
-                        }
-                        break;
-                    case WifiManager.START_WPS_SUCCEEDED:
-                        if (listener != null) {
-                            WpsResult result = (WpsResult) message.obj;
-                            ((WpsListener) listener).onStartSuccess(result.pin);
-                            //Listener needs to stay until completion or failure
-                            synchronized(mListenerMapLock) {
-                                mListenerMap.put(message.arg2, listener);
-                            }
-                        }
-                        break;
-                    case WifiManager.WPS_COMPLETED:
-                        if (listener != null) {
-                            ((WpsListener) listener).onCompletion();
-                        }
-                        break;
-                    case WifiManager.WPS_FAILED:
-                        if (listener != null) {
-                            ((WpsListener) listener).onFailure(message.arg1);
-                        }
-                        break;
-                    default:
-                        //ignore
-                        break;
-                }
-            }
+    private class ServiceHandler extends Handler {
+        ServiceHandler(Looper looper) {
+            super(looper);
         }
 
-        int putListener(Object listener) {
-            if (listener == null) return INVALID_KEY;
-            int key;
-            synchronized (mListenerMapLock) {
-                do {
-                    key = mListenerKey++;
-                } while (key == INVALID_KEY);
-                mListenerMap.put(key, listener);
-            }
-            return key;
-        }
-
-        Object removeListener(int key) {
-            if (key == INVALID_KEY) return null;
-            synchronized (mListenerMapLock) {
-                Object listener = mListenerMap.get(key);
-                mListenerMap.remove(key);
-                return listener;
+        @Override
+        public void handleMessage(Message message) {
+            Object listener = removeListener(message.arg2);
+            switch (message.what) {
+                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+                    if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+                        mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
+                    } else {
+                        Log.e(TAG, "Failed to set up channel connection");
+                        // This will cause all further async API calls on the WifiManager
+                        // to fail and throw an exception
+                        mAsyncChannel = null;
+                    }
+                    mConnected.countDown();
+                    break;
+                case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
+                    // Ignore
+                    break;
+                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
+                    Log.e(TAG, "Channel connection lost");
+                    // This will cause all further async API calls on the WifiManager
+                    // to fail and throw an exception
+                    mAsyncChannel = null;
+                    getLooper().quit();
+                    break;
+                    /* ActionListeners grouped together */
+                case WifiManager.CONNECT_NETWORK_FAILED:
+                case WifiManager.FORGET_NETWORK_FAILED:
+                case WifiManager.SAVE_NETWORK_FAILED:
+                case WifiManager.CANCEL_WPS_FAILED:
+                case WifiManager.DISABLE_NETWORK_FAILED:
+                    if (listener != null) {
+                        ((ActionListener) listener).onFailure(message.arg1);
+                    }
+                    break;
+                    /* ActionListeners grouped together */
+                case WifiManager.CONNECT_NETWORK_SUCCEEDED:
+                case WifiManager.FORGET_NETWORK_SUCCEEDED:
+                case WifiManager.SAVE_NETWORK_SUCCEEDED:
+                case WifiManager.CANCEL_WPS_SUCCEDED:
+                case WifiManager.DISABLE_NETWORK_SUCCEEDED:
+                    if (listener != null) {
+                        ((ActionListener) listener).onSuccess();
+                    }
+                    break;
+                case WifiManager.START_WPS_SUCCEEDED:
+                    if (listener != null) {
+                        WpsResult result = (WpsResult) message.obj;
+                        ((WpsListener) listener).onStartSuccess(result.pin);
+                        //Listener needs to stay until completion or failure
+                        synchronized(mListenerMapLock) {
+                            mListenerMap.put(message.arg2, listener);
+                        }
+                    }
+                    break;
+                case WifiManager.WPS_COMPLETED:
+                    if (listener != null) {
+                        ((WpsListener) listener).onCompletion();
+                    }
+                    break;
+                case WifiManager.WPS_FAILED:
+                    if (listener != null) {
+                        ((WpsListener) listener).onFailure(message.arg1);
+                    }
+                    break;
+                case WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED:
+                    if (listener != null) {
+                        RssiPacketCountInfo info = (RssiPacketCountInfo) message.obj;
+                        if (info != null)
+                            ((TxPacketCountListener) listener).onSuccess(info.txgood + info.txbad);
+                        else
+                            ((TxPacketCountListener) listener).onFailure(ERROR);
+                    }
+                    break;
+                case WifiManager.RSSI_PKTCNT_FETCH_FAILED:
+                    if (listener != null) {
+                        ((TxPacketCountListener) listener).onFailure(message.arg1);
+                    }
+                    break;
+                default:
+                    //ignore
+                    break;
             }
         }
     }
 
-    /**
-     * Registers the application with the Wi-Fi framework. This function
-     * must be the first to be called before any Wi-Fi operations are performed.
-     *
-     * @param srcContext is the context of the source
-     * @param srcLooper is the Looper on which the callbacks are receivied
-     * @param listener for callback at loss of framework communication. Can be null.
-     * @return Channel instance that is necessary for performing any further Wi-Fi operations.
-     *         A null is returned upon failure to initialize.
-     * @hide
-     */
-    public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {
-        Messenger messenger = getWifiServiceMessenger();
-        if (messenger == null) return null;
-
-        Channel c = new Channel(srcLooper, listener);
-        if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger)
-                == AsyncChannel.STATUS_SUCCESSFUL) {
-            return c;
-        } else {
-            return null;
+    private int putListener(Object listener) {
+        if (listener == null) return INVALID_KEY;
+        int key;
+        synchronized (mListenerMapLock) {
+            do {
+                key = mListenerKey++;
+            } while (key == INVALID_KEY);
+            mListenerMap.put(key, listener);
         }
+        return key;
+    }
+
+    private Object removeListener(int key) {
+        if (key == INVALID_KEY) return null;
+        synchronized (mListenerMapLock) {
+            Object listener = mListenerMap.get(key);
+            mListenerMap.remove(key);
+            return listener;
+        }
+    }
+
+    private void init() {
+        mWifiServiceMessenger = getWifiServiceMessenger();
+        if (mWifiServiceMessenger == null) {
+            mAsyncChannel = null;
+            return;
+        }
+
+        HandlerThread t = new HandlerThread("WifiManager");
+        t.start();
+        mHandler = new ServiceHandler(t.getLooper());
+        mAsyncChannel.connect(mContext, mHandler, mWifiServiceMessenger);
+        try {
+            mConnected.await();
+        } catch (InterruptedException e) {
+            Log.e(TAG, "interrupted wait at init");
+        }
+    }
+
+    private void validateChannel() {
+        if (mAsyncChannel == null) throw new IllegalStateException(
+                "No permission to access and change wifi or a bad initialization");
     }
 
     /**
@@ -1341,20 +1389,21 @@
      * sequence of addNetwork(), enableNetwork(), saveConfiguration() and
      * reconnect()
      *
-     * @param c is the channel created at {@link #initialize}
      * @param config the set of variables that describe the configuration,
      *            contained in a {@link WifiConfiguration} object.
      * @param listener for callbacks on success or failure. Can be null.
+     * @throws IllegalStateException if the WifiManager instance needs to be
+     * initialized again
+     *
      * @hide
      */
-    public void connect(Channel c, WifiConfiguration config, ActionListener listener) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+    public void connect(WifiConfiguration config, ActionListener listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
-
+        validateChannel();
         // Use INVALID_NETWORK_ID for arg1 when passing a config object
         // arg1 is used to pass network id when the network already exists
-        c.mAsyncChannel.sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID,
-                c.putListener(listener), config);
+        mAsyncChannel.sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID,
+                putListener(listener), config);
     }
 
     /**
@@ -1363,17 +1412,17 @@
      * This function is used instead of a enableNetwork(), saveConfiguration() and
      * reconnect()
      *
-     * @param c is the channel created at {@link #initialize}
      * @param networkId the network id identifiying the network in the
      *                supplicant configuration list
      * @param listener for callbacks on success or failure. Can be null.
+     * @throws IllegalStateException if the WifiManager instance needs to be
+     * initialized again
      * @hide
      */
-    public void connect(Channel c, int networkId, ActionListener listener) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+    public void connect(int networkId, ActionListener listener) {
         if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");
-
-        c.mAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, c.putListener(listener));
+        validateChannel();
+        mAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, putListener(listener));
     }
 
     /**
@@ -1387,17 +1436,17 @@
      * For an existing network, it accomplishes the task of updateNetwork()
      * and saveConfiguration()
      *
-     * @param c is the channel created at {@link #initialize}
      * @param config the set of variables that describe the configuration,
      *            contained in a {@link WifiConfiguration} object.
      * @param listener for callbacks on success or failure. Can be null.
+     * @throws IllegalStateException if the WifiManager instance needs to be
+     * initialized again
      * @hide
      */
-    public void save(Channel c, WifiConfiguration config, ActionListener listener) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+    public void save(WifiConfiguration config, ActionListener listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
-
-        c.mAsyncChannel.sendMessage(SAVE_NETWORK, 0, c.putListener(listener), config);
+        validateChannel();
+        mAsyncChannel.sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
     }
 
     /**
@@ -1406,64 +1455,62 @@
      * This function is used instead of a sequence of removeNetwork()
      * and saveConfiguration().
      *
-     * @param c is the channel created at {@link #initialize}
      * @param config the set of variables that describe the configuration,
      *            contained in a {@link WifiConfiguration} object.
      * @param listener for callbacks on success or failure. Can be null.
+     * @throws IllegalStateException if the WifiManager instance needs to be
+     * initialized again
      * @hide
      */
-    public void forget(Channel c, int netId, ActionListener listener) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+    public void forget(int netId, ActionListener listener) {
         if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
-
-        c.mAsyncChannel.sendMessage(FORGET_NETWORK, netId, c.putListener(listener));
+        validateChannel();
+        mAsyncChannel.sendMessage(FORGET_NETWORK, netId, putListener(listener));
     }
 
     /**
      * Disable network
      *
-     * @param c is the channel created at {@link #initialize}
      * @param netId is the network Id
      * @param listener for callbacks on success or failure. Can be null.
+     * @throws IllegalStateException if the WifiManager instance needs to be
+     * initialized again
      * @hide
      */
-    public void disable(Channel c, int netId, ActionListener listener) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+    public void disable(int netId, ActionListener listener) {
         if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
-
-        c.mAsyncChannel.sendMessage(DISABLE_NETWORK, netId, c.putListener(listener));
+        validateChannel();
+        mAsyncChannel.sendMessage(DISABLE_NETWORK, netId, putListener(listener));
     }
 
     /**
      * Start Wi-fi Protected Setup
      *
-     * @param c is the channel created at {@link #initialize}
      * @param config WPS configuration
      * @param listener for callbacks on success or failure. Can be null.
+     * @throws IllegalStateException if the WifiManager instance needs to be
+     * initialized again
      * @hide
      */
-    public void startWps(Channel c, WpsInfo config, WpsListener listener) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+    public void startWps(WpsInfo config, WpsListener listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
-
-        c.mAsyncChannel.sendMessage(START_WPS, 0, c.putListener(listener), config);
+        validateChannel();
+        mAsyncChannel.sendMessage(START_WPS, 0, putListener(listener), config);
     }
 
     /**
      * Cancel any ongoing Wi-fi Protected Setup
      *
-     * @param c is the channel created at {@link #initialize}
      * @param listener for callbacks on success or failure. Can be null.
+     * @throws IllegalStateException if the WifiManager instance needs to be
+     * initialized again
      * @hide
      */
-    public void cancelWps(Channel c, ActionListener listener) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
-
-        c.mAsyncChannel.sendMessage(CANCEL_WPS, 0, c.putListener(listener));
+    public void cancelWps(ActionListener listener) {
+        validateChannel();
+        mAsyncChannel.sendMessage(CANCEL_WPS, 0, putListener(listener));
     }
 
-
-
     /**
      * Get a reference to WifiService handler. This is used by a client to establish
      * an AsyncChannel communication with WifiService
@@ -1476,6 +1523,8 @@
             return mService.getWifiServiceMessenger();
         } catch (RemoteException e) {
             return null;
+        } catch (SecurityException e) {
+            return null;
         }
     }
 
@@ -1492,8 +1541,6 @@
         }
     }
 
-
-
     /**
      * Returns the file in which IP and proxy configuration data is stored
      * @hide
@@ -1926,4 +1973,21 @@
              return false;
         }
     }
+
+    /** @hide */
+    public void captivePortalCheckComplete() {
+        try {
+            mService.captivePortalCheckComplete();
+        } catch (RemoteException e) {}
+    }
+
+    protected void finalize() throws Throwable {
+        try {
+            if (mHandler != null && mHandler.getLooper() != null) {
+                mHandler.getLooper().quit();
+            }
+        } finally {
+            super.finalize();
+        }
+    }
 }
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index 17c930b..0b0d7388e 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -178,6 +178,7 @@
 
     private static final String P2P_GO_NEG_SUCCESS_STR = "P2P-GO-NEG-SUCCESS";
 
+    /* P2P-GO-NEG-FAILURE status=x */
     private static final String P2P_GO_NEG_FAILURE_STR = "P2P-GO-NEG-FAILURE";
 
     private static final String P2P_GROUP_FORMATION_SUCCESS_STR =
@@ -217,6 +218,8 @@
        pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27
        group_capab=0x0 */
     private static final String P2P_PROV_DISC_SHOW_PIN_STR = "P2P-PROV-DISC-SHOW-PIN";
+    /* P2P-PROV-DISC-FAILURE p2p_dev_addr=42:fc:89:e1:e2:27 */
+    private static final String P2P_PROV_DISC_FAILURE_STR = "P2P-PROV-DISC-FAILURE";
 
     /*
      * Protocol format is as follows.<br>
@@ -319,6 +322,7 @@
     public static final int P2P_PROV_DISC_SHOW_PIN_EVENT         = BASE + 36;
     public static final int P2P_FIND_STOPPED_EVENT               = BASE + 37;
     public static final int P2P_SERV_DISC_RESP_EVENT             = BASE + 38;
+    public static final int P2P_PROV_DISC_FAILURE_EVENT          = BASE + 39;
 
     /* hostap events */
     public static final int AP_STA_DISCONNECTED_EVENT            = BASE + 41;
@@ -563,6 +567,26 @@
                     WifiManager.ERROR, 0));
         }
 
+        /* <event> status=<err> and the special case of <event> reason=FREQ_CONFLICT */
+        private P2pStatus p2pError(String dataString) {
+            P2pStatus err = P2pStatus.UNKNOWN;
+            String[] tokens = dataString.split(" ");
+            if (tokens.length < 2) return err;
+            String[] nameValue = tokens[1].split("=");
+            if (nameValue.length != 2) return err;
+
+            /* Handle the special case of reason=FREQ+CONFLICT */
+            if (nameValue[1].equals("FREQ_CONFLICT")) {
+                return P2pStatus.NO_COMMON_CHANNEL;
+            }
+            try {
+                err = P2pStatus.valueOf(Integer.parseInt(nameValue[1]));
+            } catch (NumberFormatException e) {
+                e.printStackTrace();
+            }
+            return err;
+        }
+
         /**
          * Handle p2p events
          */
@@ -579,11 +603,11 @@
             } else if (dataString.startsWith(P2P_GO_NEG_SUCCESS_STR)) {
                 mStateMachine.sendMessage(P2P_GO_NEGOTIATION_SUCCESS_EVENT);
             } else if (dataString.startsWith(P2P_GO_NEG_FAILURE_STR)) {
-                mStateMachine.sendMessage(P2P_GO_NEGOTIATION_FAILURE_EVENT);
+                mStateMachine.sendMessage(P2P_GO_NEGOTIATION_FAILURE_EVENT, p2pError(dataString));
             } else if (dataString.startsWith(P2P_GROUP_FORMATION_SUCCESS_STR)) {
                 mStateMachine.sendMessage(P2P_GROUP_FORMATION_SUCCESS_EVENT);
             } else if (dataString.startsWith(P2P_GROUP_FORMATION_FAILURE_STR)) {
-                mStateMachine.sendMessage(P2P_GROUP_FORMATION_FAILURE_EVENT);
+                mStateMachine.sendMessage(P2P_GROUP_FORMATION_FAILURE_EVENT, p2pError(dataString));
             } else if (dataString.startsWith(P2P_GROUP_STARTED_STR)) {
                 mStateMachine.sendMessage(P2P_GROUP_STARTED_EVENT, new WifiP2pGroup(dataString));
             } else if (dataString.startsWith(P2P_GROUP_REMOVED_STR)) {
@@ -592,17 +616,7 @@
                 mStateMachine.sendMessage(P2P_INVITATION_RECEIVED_EVENT,
                         new WifiP2pGroup(dataString));
             } else if (dataString.startsWith(P2P_INVITATION_RESULT_STR)) {
-                String[] tokens = dataString.split(" ");
-                if (tokens.length != 2) return;
-                String[] nameValue = tokens[1].split("=");
-                if (nameValue.length != 2) return;
-                P2pStatus err = P2pStatus.UNKNOWN;
-                try {
-                    err = P2pStatus.valueOf(Integer.parseInt(nameValue[1]));
-                } catch (NumberFormatException e) {
-                    e.printStackTrace();
-                }
-                mStateMachine.sendMessage(P2P_INVITATION_RESULT_EVENT, err);
+                mStateMachine.sendMessage(P2P_INVITATION_RESULT_EVENT, p2pError(dataString));
             } else if (dataString.startsWith(P2P_PROV_DISC_PBC_REQ_STR)) {
                 mStateMachine.sendMessage(P2P_PROV_DISC_PBC_REQ_EVENT,
                         new WifiP2pProvDiscEvent(dataString));
@@ -615,6 +629,8 @@
             } else if (dataString.startsWith(P2P_PROV_DISC_SHOW_PIN_STR)) {
                 mStateMachine.sendMessage(P2P_PROV_DISC_SHOW_PIN_EVENT,
                         new WifiP2pProvDiscEvent(dataString));
+            } else if (dataString.startsWith(P2P_PROV_DISC_FAILURE_STR)) {
+                mStateMachine.sendMessage(P2P_PROV_DISC_FAILURE_EVENT);
             } else if (dataString.startsWith(P2P_SERV_DISC_RESP_STR)) {
                 List<WifiP2pServiceResponse> list = WifiP2pServiceResponse.newInstance(dataString);
                 if (list != null) {
@@ -645,9 +661,12 @@
          * id=network-id state=new-state
          */
         private void handleSupplicantStateChange(String dataString) {
-            String SSID = null;
+            WifiSsid wifiSsid = null;
             int index = dataString.lastIndexOf("SSID=");
-            if (index != -1) SSID = dataString.substring(index + 5);
+            if (index != -1) {
+                wifiSsid = WifiSsid.createFromAsciiEncoded(
+                        dataString.substring(index + 5));
+            }
             String[] dataTokens = dataString.split(" ");
 
             String BSSID = null;
@@ -690,7 +709,7 @@
             if (newSupplicantState == SupplicantState.INVALID) {
                 Log.w(TAG, "Invalid supplicant state: " + newState);
             }
-            notifySupplicantStateChange(networkId, SSID, BSSID, newSupplicantState);
+            notifySupplicantStateChange(networkId, wifiSsid, BSSID, newSupplicantState);
         }
     }
 
@@ -739,13 +758,14 @@
      * Send the state machine a notification that the state of the supplicant
      * has changed.
      * @param networkId the configured network on which the state change occurred
-     * @param SSID network name
+     * @param wifiSsid network name
      * @param BSSID network address
      * @param newState the new {@code SupplicantState}
      */
-    void notifySupplicantStateChange(int networkId, String SSID, String BSSID, SupplicantState newState) {
+    void notifySupplicantStateChange(int networkId, WifiSsid wifiSsid, String BSSID,
+            SupplicantState newState) {
         mStateMachine.sendMessage(mStateMachine.obtainMessage(SUPPLICANT_STATE_CHANGE_EVENT,
-                new StateChangeResult(networkId, SSID, BSSID, newState)));
+                new StateChangeResult(networkId, wifiSsid, BSSID, newState)));
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index e520185..4c5fc5d 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -49,6 +49,7 @@
     static final int BLUETOOTH_COEXISTENCE_MODE_SENSE = 2;
 
     String mInterface = "";
+    private boolean mSuspendOptEnabled = false;
 
     public native static boolean loadDriver();
 
@@ -197,8 +198,22 @@
         return null;
     }
 
+    /**
+     * Format of results:
+     * =================
+     * bssid=68:7f:74:d7:1b:6e
+     * freq=2412
+     * level=-43
+     * tsf=1344621975160944
+     * age=2623
+     * flags=[WPA2-PSK-CCMP][WPS][ESS]
+     * ssid=zubyb
+     *
+     * RANGE=ALL gets all scan results
+     * MASK=<N> see wpa_supplicant/src/common/wpa_ctrl.h for details
+     */
     public String scanResults() {
-        return doStringCommand("SCAN_RESULTS");
+        return doStringCommand("BSS RANGE=ALL MASK=0x1986");
     }
 
     public boolean startDriver() {
@@ -335,6 +350,8 @@
     }
 
     public boolean setSuspendOptimizations(boolean enabled) {
+        if (mSuspendOptEnabled == enabled) return true;
+        mSuspendOptEnabled = enabled;
         if (enabled) {
             return doBooleanCommand("DRIVER SETSUSPENDMODE 1");
         } else {
@@ -368,6 +385,14 @@
         return doStringCommand("SIGNAL_POLL");
     }
 
+    /** Example outout:
+     * TXGOOD=396
+     * TXBAD=1
+     */
+    public String pktcntPoll() {
+        return doStringCommand("PKTCNT_POLL");
+    }
+
     public boolean startWpsPbc(String bssid) {
         if (TextUtils.isEmpty(bssid)) {
             return doBooleanCommand("WPS_PBC");
@@ -478,6 +503,14 @@
         }
     }
 
+    public boolean setWfdEnable(boolean enable) {
+        return doBooleanCommand("SET wifi_display " + (enable ? "1" : "0"));
+    }
+
+    public boolean setWfdDeviceInfo(String hex) {
+        return doBooleanCommand("WFD_SUBELEM_SET 0 " + hex);
+    }
+
     /**
      * "sta" prioritizes STA connection over P2P and "p2p" prioritizes
      * P2P connection over STA
diff --git a/wifi/java/android/net/wifi/WifiSsid.java b/wifi/java/android/net/wifi/WifiSsid.java
new file mode 100644
index 0000000..55e9b2d
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiSsid.java
@@ -0,0 +1,234 @@
+/*
+ * 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.net.wifi;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+
+/**
+ * Stores SSID octets and handles conversion.
+ *
+ * For Ascii encoded string, any octet < 32 or > 127 is encoded as
+ * a "\x" followed by the hex representation of the octet.
+ * Exception chars are ", \, \e, \n, \r, \t which are escaped by a \
+ * See src/utils/common.c for the implementation in the supplicant.
+ *
+ * @hide
+ */
+public class WifiSsid implements Parcelable {
+    private static final String TAG = "WifiSsid";
+
+    public ByteArrayOutputStream octets = new ByteArrayOutputStream(32);
+
+    private static final int HEX_RADIX = 16;
+    public static final String NONE = "<unknown ssid>";
+
+    private WifiSsid() {
+    }
+
+    public static WifiSsid createFromAsciiEncoded(String asciiEncoded) {
+        WifiSsid a = new WifiSsid();
+        a.convertToBytes(asciiEncoded);
+        return a;
+    }
+
+    public static WifiSsid createFromHex(String hexStr) {
+        WifiSsid a = new WifiSsid();
+        int length = 0;
+        if (hexStr == null) return a;
+
+        if (hexStr.startsWith("0x") || hexStr.startsWith("0X")) {
+            hexStr = hexStr.substring(2);
+        }
+
+        for (int i = 0; i < hexStr.length()-1; i += 2) {
+            int val;
+            try {
+                val = Integer.parseInt(hexStr.substring(i, i + 2), HEX_RADIX);
+            } catch(NumberFormatException e) {
+                val = 0;
+            }
+            a.octets.write(val);
+        }
+        return a;
+    }
+
+    /* This function is equivalent to printf_decode() at src/utils/common.c in
+     * the supplicant */
+    private void convertToBytes(String asciiEncoded) {
+        int i = 0;
+        int val = 0;
+        while (i< asciiEncoded.length()) {
+            char c = asciiEncoded.charAt(i);
+            switch (c) {
+                case '\\':
+                    i++;
+                    switch(asciiEncoded.charAt(i)) {
+                        case '\\':
+                            octets.write('\\');
+                            i++;
+                            break;
+                        case '"':
+                            octets.write('"');
+                            i++;
+                            break;
+                        case 'n':
+                            octets.write('\n');
+                            i++;
+                            break;
+                        case 'r':
+                            octets.write('\r');
+                            i++;
+                            break;
+                        case 't':
+                            octets.write('\t');
+                            i++;
+                            break;
+                        case 'e':
+                            octets.write(27); //escape char
+                            i++;
+                            break;
+                        case 'x':
+                            i++;
+                            try {
+                                val = Integer.parseInt(asciiEncoded.substring(i, i + 2), HEX_RADIX);
+                            } catch (NumberFormatException e) {
+                                val = -1;
+                            }
+                            if (val < 0) {
+                                val = Character.digit(asciiEncoded.charAt(i), HEX_RADIX);
+                                if (val < 0) break;
+                                octets.write(val);
+                                i++;
+                            } else {
+                                octets.write(val);
+                                i += 2;
+                            }
+                            break;
+                        case '0':
+                        case '1':
+                        case '2':
+                        case '3':
+                        case '4':
+                        case '5':
+                        case '6':
+                        case '7':
+                            val = asciiEncoded.charAt(i) - '0';
+                            i++;
+                            if (asciiEncoded.charAt(i) >= '0' && asciiEncoded.charAt(i) <= '7') {
+                                val = val * 8 + asciiEncoded.charAt(i) - '0';
+                                i++;
+                            }
+                            if (asciiEncoded.charAt(i) >= '0' && asciiEncoded.charAt(i) <= '7') {
+                                val = val * 8 + asciiEncoded.charAt(i) - '0';
+                                i++;
+                            }
+                            octets.write(val);
+                            break;
+                        default:
+                            break;
+                    }
+                    break;
+                default:
+                    octets.write(c);
+                    i++;
+                    break;
+            }
+        }
+    }
+
+    @Override
+    public String toString() {
+        byte[] ssidBytes = octets.toByteArray();
+        // Supplicant returns \x00\x00\x00\x00\x00\x00\x00\x00 hex string
+        // for a hidden access point. Make sure we maintain the previous
+        // behavior of returning empty string for this case.
+        if (octets.size() <= 0 || isArrayAllZeroes(ssidBytes)) return "";
+        // TODO: Handle conversion to other charsets upon failure
+        Charset charset = Charset.forName("UTF-8");
+        CharsetDecoder decoder = charset.newDecoder()
+                .onMalformedInput(CodingErrorAction.REPLACE)
+                .onUnmappableCharacter(CodingErrorAction.REPLACE);
+        CharBuffer out = CharBuffer.allocate(32);
+
+        CoderResult result = decoder.decode(ByteBuffer.wrap(ssidBytes), out, true);
+        out.flip();
+        if (result.isError()) {
+            return NONE;
+        }
+        return out.toString();
+    }
+
+    private boolean isArrayAllZeroes(byte[] ssidBytes) {
+        for (int i = 0; i< ssidBytes.length; i++) {
+            if (ssidBytes[i] != 0) return false;
+        }
+        return true;
+    }
+
+    /** @hide */
+    public byte[] getOctets() {
+        return  octets.toByteArray();
+    }
+
+    /** @hide */
+    public String getHexString() {
+        String out = "0x";
+        byte[] ssidbytes = getOctets();
+        for (int i = 0; i < octets.size(); i++) {
+            out += String.format("%02x", ssidbytes[i]);
+        }
+        return out;
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(octets.size());
+        dest.writeByteArray(octets.toByteArray());
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Creator<WifiSsid> CREATOR =
+        new Creator<WifiSsid>() {
+            public WifiSsid createFromParcel(Parcel in) {
+                WifiSsid ssid = new WifiSsid();
+                int length = in.readInt();
+                byte b[] = new byte[length];
+                in.readByteArray(b);
+                ssid.octets.write(b, 0, length);
+                return ssid;
+            }
+
+            public WifiSsid[] newArray(int size) {
+                return new WifiSsid[size];
+            }
+        };
+}
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 15eb9b9..040ff24 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -23,13 +23,8 @@
 import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
 
 /**
- * TODO: Add soft AP states as part of WIFI_STATE_XXX
- * Retain WIFI_STATE_ENABLING that indicates driver is loading
- * Add WIFI_STATE_AP_ENABLED to indicate soft AP has started
- * and WIFI_STATE_FAILED for failure
+ * TODO:
  * Deprecate WIFI_STATE_UNKNOWN
- *
- * Doing this will simplify the logic for sending broadcasts
  */
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
@@ -46,6 +41,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.database.ContentObserver;
 import android.net.ConnectivityManager;
 import android.net.DhcpInfo;
 import android.net.DhcpInfoInternal;
@@ -56,6 +52,7 @@
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkUtils;
+import android.net.wifi.RssiPacketCountInfo;
 import android.net.wifi.WpsResult.Status;
 import android.net.wifi.p2p.WifiP2pManager;
 import android.net.wifi.p2p.WifiP2pService;
@@ -71,12 +68,14 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.LruCache;
 
+import com.android.internal.R;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
@@ -94,13 +93,10 @@
  * Track the state of Wifi connectivity. All event handling is done here,
  * and all changes in connectivity state are initiated here.
  *
- * Wi-Fi now supports three modes of operation: Client, Soft Ap and Direct
- * In the current implementation, we do not support any concurrency and thus only
- * one of Client, Soft Ap or Direct operation is supported at any time.
- *
- * The WifiStateMachine supports Soft Ap and Client operations while WifiP2pService
- * handles Direct. WifiP2pService and WifiStateMachine co-ordinate to ensure only
- * one exists at a certain time.
+ * Wi-Fi now supports three modes of operation: Client, SoftAp and p2p
+ * In the current implementation, we support concurrent wifi p2p and wifi operation.
+ * The WifiStateMachine handles SoftAp and Client operations while WifiP2pService
+ * handles p2p operation.
  *
  * @hide
  */
@@ -110,9 +106,6 @@
     private static final String NETWORKTYPE = "WIFI";
     private static final boolean DBG = false;
 
-    /* TODO: This is no more used with the hostapd code. Clean up */
-    private static final String SOFTAP_IFACE = "wl0.1";
-
     private WifiMonitor mWifiMonitor;
     private WifiNative mWifiNative;
     private WifiConfigStore mWifiConfigStore;
@@ -120,10 +113,12 @@
     private ConnectivityManager mCm;
 
     private final boolean mP2pSupported;
+    private final AtomicBoolean mP2pConnected = new AtomicBoolean(false);
+    private boolean mTemporarilyDisconnectWifi = false;
     private final String mPrimaryDeviceType;
 
     /* Scan results handling */
-    private List<ScanResult> mScanResults;
+    private List<ScanResult> mScanResults = new ArrayList<ScanResult>();
     private static final Pattern scanResultPattern = Pattern.compile("\t+");
     private static final int SCAN_RESULT_CACHE_SIZE = 80;
     private final LruCache<String, ScanResult> mScanResultCache;
@@ -146,13 +141,13 @@
     private boolean mScanResultIsPending = false;
     /* Tracks if the current scan settings are active */
     private boolean mSetScanActive = false;
-    /* High perf mode is true if an app has held a high perf Wifi Lock */
-    private boolean mHighPerfMode = false;
+    /* Tracks if state machine has received any screen state change broadcast yet.
+     * We can miss one of these at boot.
+     */
+    private AtomicBoolean mScreenBroadcastReceived = new AtomicBoolean(false);
 
     private boolean mBluetoothConnectionActive = false;
 
-    private BroadcastReceiver mScreenReceiver;
-    private IntentFilter mScreenFilter;
     private PowerManager.WakeLock mSuspendWakeLock;
 
     /**
@@ -263,6 +258,8 @@
     static final int CMD_DELAYED_STOP_DRIVER              = BASE + 18;
     /* A delayed message sent to start driver when it fail to come up */
     static final int CMD_DRIVER_START_TIMED_OUT           = BASE + 19;
+    /* Ready to switch to network as default */
+    static final int CMD_CAPTIVE_CHECK_COMPLETE           = BASE + 20;
 
     /* Start the soft access point */
     static final int CMD_START_AP                         = BASE + 21;
@@ -342,10 +339,8 @@
     static final int CMD_START_PACKET_FILTERING           = BASE + 84;
     /* Clear packet filter */
     static final int CMD_STOP_PACKET_FILTERING            = BASE + 85;
-    /* Set suspend mode optimizations in the driver */
-    static final int CMD_SET_SUSPEND_OPTIMIZATIONS        = BASE + 86;
-    /* Clear suspend mode optimizations in the driver */
-    static final int CMD_CLEAR_SUSPEND_OPTIMIZATIONS      = BASE + 87;
+    /* Enable suspend mode optimizations in the driver */
+    static final int CMD_SET_SUSPEND_OPT_ENABLED          = BASE + 86;
     /* When there are no saved networks, we do a periodic scan to notify user of
      * an open network */
     static final int CMD_NO_NETWORKS_PERIODIC_SCAN        = BASE + 88;
@@ -364,8 +359,12 @@
     static final int CMD_RESET_SUPPLICANT_STATE           = BASE + 111;
 
     /* P2p commands */
+    /* We are ok with no response here since we wont do much with it anyway */
     public static final int CMD_ENABLE_P2P                = BASE + 131;
-    public static final int CMD_DISABLE_P2P               = BASE + 132;
+    /* In order to shut down supplicant cleanly, we wait till p2p has
+     * been disabled */
+    public static final int CMD_DISABLE_P2P_REQ           = BASE + 132;
+    public static final int CMD_DISABLE_P2P_RSP           = BASE + 133;
 
     private static final int CONNECT_MODE   = 1;
     private static final int SCAN_ONLY_MODE = 2;
@@ -390,21 +389,32 @@
      */
     private static final int DEFAULT_MAX_DHCP_RETRIES = 9;
 
-    /* Tracks if power save is enabled in driver */
-    private boolean mPowerSaveEnabled = true;;
+    /* Tracks if suspend optimizations need to be disabled by DHCP,
+     * screen or due to high perf mode.
+     * When any of them needs to disable it, we keep the suspend optimizations
+     * disabled
+     */
+    private int mSuspendOptNeedsDisabled = 0;
+
+    private static final int SUSPEND_DUE_TO_DHCP       = 1;
+    private static final int SUSPEND_DUE_TO_HIGH_PERF  = 1<<1;
+    private static final int SUSPEND_DUE_TO_SCREEN     = 1<<2;
+
+    /* Tracks if user has enabled suspend optimizations through settings */
+    private AtomicBoolean mUserWantsSuspendOpt = new AtomicBoolean(true);
 
     /**
      * Default framework scan interval in milliseconds. This is used in the scenario in which
      * wifi chipset does not support background scanning to set up a
      * periodic wake up scan so that the device can connect to a new access
-     * point on the move. {@link Settings.Secure#WIFI_FRAMEWORK_SCAN_INTERVAL_MS} can
+     * point on the move. {@link Settings.Global#WIFI_FRAMEWORK_SCAN_INTERVAL_MS} can
      * override this.
      */
     private final int mDefaultFrameworkScanIntervalMs;
 
     /**
      * Supplicant scan interval in milliseconds.
-     * Comes from {@link Settings.Secure#WIFI_SUPPLICANT_SCAN_INTERVAL_MS} or
+     * Comes from {@link Settings.Global#WIFI_SUPPLICANT_SCAN_INTERVAL_MS} or
      * from the default config if the setting is not set
      */
     private long mSupplicantScanIntervalMs;
@@ -452,6 +462,11 @@
     private State mDriverStartingState = new DriverStartingState();
     /* Driver started */
     private State mDriverStartedState = new DriverStartedState();
+    /* Wait until p2p is disabled
+     * This is a special state which is entered right after we exit out of DriverStartedState
+     * before transitioning to another state.
+     */
+    private State mWaitForP2pDisableState = new WaitForP2pDisableState();
     /* Driver stopping */
     private State mDriverStoppingState = new DriverStoppingState();
     /* Driver stopped */
@@ -466,6 +481,8 @@
     private State mObtainingIpState = new ObtainingIpState();
     /* Waiting for link quality verification to be complete */
     private State mVerifyingLinkState = new VerifyingLinkState();
+    /* Waiting for captive portal check to be complete */
+    private State mCaptivePortalCheckState = new CaptivePortalCheckState();
     /* Connected with IP addr */
     private State mConnectedState = new ConnectedState();
     /* disconnect issued, waiting for network disconnect confirmation */
@@ -590,16 +607,19 @@
         mScanIntent = PendingIntent.getBroadcast(mContext, SCAN_REQUEST, scanIntent, 0);
 
         mDefaultFrameworkScanIntervalMs = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_wifi_framework_scan_interval);
+                R.integer.config_wifi_framework_scan_interval);
 
         mDriverStopDelayMs = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_wifi_driver_stop_delay);
+                R.integer.config_wifi_driver_stop_delay);
 
         mBackgroundScanSupported = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_wifi_background_scan_support);
+                R.bool.config_wifi_background_scan_support);
 
         mPrimaryDeviceType = mContext.getResources().getString(
-                com.android.internal.R.string.config_wifi_p2p_device_type);
+                R.string.config_wifi_p2p_device_type);
+
+        mUserWantsSuspendOpt.set(Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
 
         mContext.registerReceiver(
             new BroadcastReceiver() {
@@ -622,32 +642,23 @@
                 },
                 new IntentFilter(ACTION_START_SCAN));
 
-        mScreenFilter = new IntentFilter();
-        mScreenFilter.addAction(Intent.ACTION_SCREEN_ON);
-        mScreenFilter.addAction(Intent.ACTION_SCREEN_OFF);
-        mScreenReceiver = new BroadcastReceiver() {
+        IntentFilter screenFilter = new IntentFilter();
+        screenFilter.addAction(Intent.ACTION_SCREEN_ON);
+        screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
+        BroadcastReceiver screenReceiver = new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 String action = intent.getAction();
 
                 if (action.equals(Intent.ACTION_SCREEN_ON)) {
-                    enableRssiPolling(true);
-                    if (mBackgroundScanSupported) {
-                        enableBackgroundScanCommand(false);
-                    }
-                    enableAllNetworks();
-                    sendMessage(CMD_CLEAR_SUSPEND_OPTIMIZATIONS);
+                    handleScreenStateChanged(true);
                 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
-                    enableRssiPolling(false);
-                    if (mBackgroundScanSupported) {
-                        enableBackgroundScanCommand(true);
-                    }
-                    //Allow 2s for suspend optimizations to be set
-                    mSuspendWakeLock.acquire(2000);
-                    sendMessage(CMD_SET_SUSPEND_OPTIMIZATIONS);
+                    handleScreenStateChanged(false);
                 }
             }
         };
+        mContext.registerReceiver(screenReceiver, screenFilter);
+
         mContext.registerReceiver(
                 new BroadcastReceiver() {
                     @Override
@@ -658,6 +669,16 @@
                 },
                 new IntentFilter(ACTION_DELAYED_DRIVER_STOP));
 
+        mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED), false,
+                new ContentObserver(getHandler()) {
+                    @Override
+                    public void onChange(boolean selfChange) {
+                        mUserWantsSuspendOpt.set(Settings.Global.getInt(mContext.getContentResolver(),
+                                Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
+                    }
+                });
+
         mScanResultCache = new LruCache<String, ScanResult>(SCAN_RESULT_CACHE_SIZE);
 
         PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
@@ -682,10 +703,12 @@
                         addState(mL2ConnectedState, mConnectModeState);
                             addState(mObtainingIpState, mL2ConnectedState);
                             addState(mVerifyingLinkState, mL2ConnectedState);
+                            addState(mCaptivePortalCheckState, mL2ConnectedState);
                             addState(mConnectedState, mL2ConnectedState);
                         addState(mDisconnectingState, mConnectModeState);
                         addState(mDisconnectedState, mConnectModeState);
                         addState(mWpsRunningState, mConnectModeState);
+                addState(mWaitForP2pDisableState, mSupplicantStartedState);
                 addState(mDriverStoppingState, mSupplicantStartedState);
                 addState(mDriverStoppedState, mSupplicantStartedState);
             addState(mSupplicantStoppingState, mDefaultState);
@@ -852,6 +875,10 @@
         }
     }
 
+    public void captivePortalCheckComplete() {
+        sendMessage(obtainMessage(CMD_CAPTIVE_CHECK_COMPLETE));
+    }
+
     /**
      * TODO: doc
      */
@@ -878,7 +905,13 @@
      * TODO: doc
      */
     public List<ScanResult> syncGetScanResultsList() {
-        return mScanResults;
+        synchronized (mScanResultCache) {
+            List<ScanResult> scanList = new ArrayList<ScanResult>();
+            for(ScanResult result: mScanResults) {
+                scanList.add(new ScanResult(result));
+            }
+            return scanList;
+        }
     }
 
     /**
@@ -1038,8 +1071,8 @@
      */
     public void setCountryCode(String countryCode, boolean persist) {
         if (persist) {
-            Settings.Secure.putString(mContext.getContentResolver(),
-                    Settings.Secure.WIFI_COUNTRY_CODE,
+            Settings.Global.putString(mContext.getContentResolver(),
+                    Settings.Global.WIFI_COUNTRY_CODE,
                     countryCode);
         }
         sendMessage(obtainMessage(CMD_SET_COUNTRY_CODE, countryCode));
@@ -1052,8 +1085,8 @@
      */
     public void setFrequencyBand(int band, boolean persist) {
         if (persist) {
-            Settings.Secure.putInt(mContext.getContentResolver(),
-                    Settings.Secure.WIFI_FREQUENCY_BAND,
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Settings.Global.WIFI_FREQUENCY_BAND,
                     band);
         }
         sendMessage(obtainMessage(CMD_SET_FREQUENCY_BAND, band, 0));
@@ -1143,6 +1176,8 @@
         sb.append("mLastNetworkId ").append(mLastNetworkId).append(LS);
         sb.append("mReconnectCount ").append(mReconnectCount).append(LS);
         sb.append("mIsScanMode ").append(mIsScanMode).append(LS);
+        sb.append("mUserWantsSuspendOpt ").append(mUserWantsSuspendOpt).append(LS);
+        sb.append("mSuspendOptNeedsDisabled ").append(mSuspendOptNeedsDisabled).append(LS);
         sb.append("Supplicant status").append(LS)
                 .append(mWifiNative.status()).append(LS).append(LS);
 
@@ -1160,8 +1195,7 @@
                 case CMD_START_DRIVER:
                 case CMD_SET_SCAN_MODE:
                 case CMD_SET_HIGH_PERF_MODE:
-                case CMD_SET_SUSPEND_OPTIMIZATIONS:
-                case CMD_CLEAR_SUSPEND_OPTIMIZATIONS:
+                case CMD_SET_SUSPEND_OPT_ENABLED:
                 case CMD_ENABLE_BACKGROUND_SCAN:
                 case CMD_ENABLE_ALL_NETWORKS:
                 return false;
@@ -1174,7 +1208,7 @@
             case CMD_RSSI_POLL:
             case CMD_DELAYED_STOP_DRIVER:
             case WifiMonitor.SCAN_RESULTS_EVENT:
-            case WifiWatchdogStateMachine.RSSI_FETCH:
+            case WifiManager.RSSI_PKTCNT_FETCH:
                 return false;
             default:
                 return true;
@@ -1185,6 +1219,26 @@
      * Internal private functions
      ********************************************************/
 
+    private void handleScreenStateChanged(boolean screenOn) {
+        if (DBG) log("handleScreenStateChanged: " + screenOn);
+        enableRssiPolling(screenOn);
+        if (mBackgroundScanSupported) {
+            enableBackgroundScanCommand(screenOn == false);
+        }
+
+        if (screenOn) enableAllNetworks();
+        if (mUserWantsSuspendOpt.get()) {
+            if (screenOn) {
+                sendMessage(obtainMessage(CMD_SET_SUSPEND_OPT_ENABLED, 0, 0));
+            } else {
+                //Allow 2s for suspend optimizations to be set
+                mSuspendWakeLock.acquire(2000);
+                sendMessage(obtainMessage(CMD_SET_SUSPEND_OPT_ENABLED, 1, 0));
+            }
+        }
+        mScreenBroadcastReceived.set(true);
+    }
+
     private void checkAndSetConnectivityInstance() {
         if (mCm == null) {
             mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -1275,8 +1329,8 @@
      * Set the country code from the system setting value, if any.
      */
     private void setCountryCode() {
-        String countryCode = Settings.Secure.getString(mContext.getContentResolver(),
-                Settings.Secure.WIFI_COUNTRY_CODE);
+        String countryCode = Settings.Global.getString(mContext.getContentResolver(),
+                Settings.Global.WIFI_COUNTRY_CODE);
         if (countryCode != null && !countryCode.isEmpty()) {
             setCountryCode(countryCode, false);
         } else {
@@ -1288,11 +1342,35 @@
      * Set the frequency band from the system setting value, if any.
      */
     private void setFrequencyBand() {
-        int band = Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.WIFI_FREQUENCY_BAND, WifiManager.WIFI_FREQUENCY_BAND_AUTO);
+        int band = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.WIFI_FREQUENCY_BAND, WifiManager.WIFI_FREQUENCY_BAND_AUTO);
         setFrequencyBand(band, false);
     }
 
+    private void setSuspendOptimizationsNative(int reason, boolean enabled) {
+        if (DBG) log("setSuspendOptimizationsNative: " + reason + " " + enabled);
+        if (enabled) {
+            mSuspendOptNeedsDisabled &= ~reason;
+            /* None of dhcp, screen or highperf need it disabled and user wants it enabled */
+            if (mSuspendOptNeedsDisabled == 0 && mUserWantsSuspendOpt.get()) {
+                mWifiNative.setSuspendOptimizations(true);
+            }
+        } else {
+            mSuspendOptNeedsDisabled |= reason;
+            mWifiNative.setSuspendOptimizations(false);
+        }
+    }
+
+    private void setSuspendOptimizations(int reason, boolean enabled) {
+        if (DBG) log("setSuspendOptimizations: " + reason + " " + enabled);
+        if (enabled) {
+            mSuspendOptNeedsDisabled &= ~reason;
+        } else {
+            mSuspendOptNeedsDisabled |= reason;
+        }
+        if (DBG) log("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled);
+    }
+
     private void setWifiState(int wifiState) {
         final int previousWifiState = mWifiState.get();
 
@@ -1314,7 +1392,7 @@
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState);
         intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState);
-        mContext.sendStickyBroadcast(intent);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void setWifiApState(int wifiApState) {
@@ -1339,134 +1417,110 @@
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, wifiApState);
         intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousWifiApState);
-        mContext.sendStickyBroadcast(intent);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
+    private static final String BSSID_STR = "bssid=";
+    private static final String FREQ_STR = "freq=";
+    private static final String LEVEL_STR = "level=";
+    private static final String TSF_STR = "tsf=";
+    private static final String FLAGS_STR = "flags=";
+    private static final String SSID_STR = "ssid=";
+    private static final String DELIMITER_STR = "====";
     /**
-     * Parse the scan result line passed to us by wpa_supplicant (helper).
-     * @param line the line to parse
-     * @return the {@link ScanResult} object
-     */
-    private ScanResult parseScanResult(String line) {
-        ScanResult scanResult = null;
-        if (line != null) {
-            /*
-             * Cache implementation (LinkedHashMap) is not synchronized, thus,
-             * must synchronized here!
-             */
-            synchronized (mScanResultCache) {
-                String[] result = scanResultPattern.split(line);
-                if (3 <= result.length && result.length <= 5) {
-                    String bssid = result[0];
-                    // bssid | frequency | level | flags | ssid
-                    int frequency;
-                    int level;
-                    try {
-                        frequency = Integer.parseInt(result[1]);
-                        level = Integer.parseInt(result[2]);
-                        /* some implementations avoid negative values by adding 256
-                         * so we need to adjust for that here.
-                         */
-                        if (level > 0) level -= 256;
-                    } catch (NumberFormatException e) {
-                        frequency = 0;
-                        level = 0;
-                    }
-
-                    /*
-                     * The formatting of the results returned by
-                     * wpa_supplicant is intended to make the fields
-                     * line up nicely when printed,
-                     * not to make them easy to parse. So we have to
-                     * apply some heuristics to figure out which field
-                     * is the SSID and which field is the flags.
-                     */
-                    String ssid;
-                    String flags;
-                    if (result.length == 4) {
-                        if (result[3].charAt(0) == '[') {
-                            flags = result[3];
-                            ssid = "";
-                        } else {
-                            flags = "";
-                            ssid = result[3];
-                        }
-                    } else if (result.length == 5) {
-                        flags = result[3];
-                        ssid = result[4];
-                    } else {
-                        // Here, we must have 3 fields: no flags and ssid
-                        // set
-                        flags = "";
-                        ssid = "";
-                    }
-
-                    // bssid + ssid is the hash key
-                    String key = bssid + ssid;
-                    scanResult = mScanResultCache.get(key);
-                    if (scanResult != null) {
-                        scanResult.level = level;
-                        scanResult.SSID = ssid;
-                        scanResult.capabilities = flags;
-                        scanResult.frequency = frequency;
-                    } else {
-                        // Do not add scan results that have no SSID set
-                        if (0 < ssid.trim().length()) {
-                            scanResult =
-                                new ScanResult(
-                                    ssid, bssid, flags, level, frequency);
-                            mScanResultCache.put(key, scanResult);
-                        }
-                    }
-                } else {
-                    loge("Misformatted scan result text with " +
-                          result.length + " fields: " + line);
-                }
-            }
-        }
-
-        return scanResult;
-    }
-
-    /**
-     * scanResults input format
-     * 00:bb:cc:dd:cc:ee       2427    166     [WPA-EAP-TKIP][WPA2-EAP-CCMP]   Net1
-     * 00:bb:cc:dd:cc:ff       2412    165     [WPA-EAP-TKIP][WPA2-EAP-CCMP]   Net2
+     * Format:
+     * bssid=68:7f:76:d7:1a:6e
+     * freq=2412
+     * level=-44
+     * tsf=1344626243700342
+     * flags=[WPA2-PSK-CCMP][WPS][ESS]
+     * ssid=zfdy
+     * ====
+     * bssid=68:5f:74:d7:1a:6f
+     * freq=5180
+     * level=-73
+     * tsf=1344626243700373
+     * flags=[WPA2-PSK-CCMP][WPS][ESS]
+     * ssid=zuby
+     * ====
      */
     private void setScanResults(String scanResults) {
+        String bssid = "";
+        int level = 0;
+        int freq = 0;
+        long tsf = 0;
+        String flags = "";
+        WifiSsid wifiSsid = null;
+
         if (scanResults == null) {
             return;
         }
 
-        List<ScanResult> scanList = new ArrayList<ScanResult>();
+        synchronized(mScanResultCache) {
+            mScanResults = new ArrayList<ScanResult>();
+            String[] lines = scanResults.split("\n");
 
-        int lineCount = 0;
-
-        int scanResultsLen = scanResults.length();
-        // Parse the result string, keeping in mind that the last line does
-        // not end with a newline.
-        for (int lineBeg = 0, lineEnd = 0; lineEnd <= scanResultsLen; ++lineEnd) {
-            if (lineEnd == scanResultsLen || scanResults.charAt(lineEnd) == '\n') {
-                ++lineCount;
-
-                if (lineCount == 1) {
-                    lineBeg = lineEnd + 1;
-                    continue;
-                }
-                if (lineEnd > lineBeg) {
-                    String line = scanResults.substring(lineBeg, lineEnd);
-                    ScanResult scanResult = parseScanResult(line);
-                    if (scanResult != null) {
-                        scanList.add(scanResult);
-                    } else {
-                        //TODO: hidden network handling
+            for (String line : lines) {
+                if (line.startsWith(BSSID_STR)) {
+                    bssid = line.substring(BSSID_STR.length());
+                } else if (line.startsWith(FREQ_STR)) {
+                    try {
+                        freq = Integer.parseInt(line.substring(FREQ_STR.length()));
+                    } catch (NumberFormatException e) {
+                        freq = 0;
                     }
+                } else if (line.startsWith(LEVEL_STR)) {
+                    try {
+                        level = Integer.parseInt(line.substring(LEVEL_STR.length()));
+                        /* some implementations avoid negative values by adding 256
+                         * so we need to adjust for that here.
+                         */
+                        if (level > 0) level -= 256;
+                    } catch(NumberFormatException e) {
+                        level = 0;
+                    }
+                } else if (line.startsWith(TSF_STR)) {
+                    try {
+                        tsf = Long.parseLong(line.substring(TSF_STR.length()));
+                    } catch (NumberFormatException e) {
+                        tsf = 0;
+                    }
+                } else if (line.startsWith(FLAGS_STR)) {
+                    flags = line.substring(FLAGS_STR.length());
+                } else if (line.startsWith(SSID_STR)) {
+                    wifiSsid = WifiSsid.createFromAsciiEncoded(
+                            line.substring(SSID_STR.length()));
+                } else if (line.startsWith(DELIMITER_STR)) {
+                    if (bssid != null) {
+                        String ssid = (wifiSsid != null) ? wifiSsid.toString() : WifiSsid.NONE;
+                        String key = bssid + ssid;
+                        ScanResult scanResult = mScanResultCache.get(key);
+                        if (scanResult != null) {
+                            scanResult.level = level;
+                            scanResult.wifiSsid = wifiSsid;
+                            // Keep existing API
+                            scanResult.SSID = (wifiSsid != null) ? wifiSsid.toString() :
+                                    WifiSsid.NONE;
+                            scanResult.capabilities = flags;
+                            scanResult.frequency = freq;
+                            scanResult.timestamp = tsf;
+                        } else {
+                            scanResult =
+                                new ScanResult(
+                                        wifiSsid, bssid, flags, level, freq, tsf);
+                            mScanResultCache.put(key, scanResult);
+                        }
+                        mScanResults.add(scanResult);
+                    }
+                    bssid = null;
+                    level = 0;
+                    freq = 0;
+                    tsf = 0;
+                    flags = "";
+                    wifiSsid = null;
                 }
-                lineBeg = lineEnd + 1;
             }
         }
-
-        mScanResults = scanList;
     }
 
     /*
@@ -1525,6 +1579,30 @@
         }
     }
 
+    /*
+     * Fetch TX packet counters on current connection
+     */
+    private void fetchPktcntNative(RssiPacketCountInfo info) {
+        String pktcntPoll = mWifiNative.pktcntPoll();
+
+        if (pktcntPoll != null) {
+            String[] lines = pktcntPoll.split("\n");
+            for (String line : lines) {
+                String[] prop = line.split("=");
+                if (prop.length < 2) continue;
+                try {
+                    if (prop[0].equals("TXGOOD")) {
+                        info.txgood = Integer.parseInt(prop[1]);
+                    } else if (prop[0].equals("TXBAD")) {
+                        info.txbad = Integer.parseInt(prop[1]);
+                    }
+                } catch (NumberFormatException e) {
+                    //Ignore
+                }
+            }
+        }
+    }
+
     private void configureLinkProperties() {
         if (mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
             mLinkProperties = mWifiConfigStore.getLinkProperties(mLastNetworkId);
@@ -1542,22 +1620,22 @@
     }
 
     private int getMaxDhcpRetries() {
-        return Settings.Secure.getInt(mContext.getContentResolver(),
-                                      Settings.Secure.WIFI_MAX_DHCP_RETRY_COUNT,
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                                      Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
                                       DEFAULT_MAX_DHCP_RETRIES);
     }
 
     private void sendScanResultsAvailableBroadcast() {
         Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        mContext.sendBroadcast(intent);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void sendRssiChangeBroadcast(final int newRssi) {
         Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi);
-        mContext.sendBroadcast(intent);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void sendNetworkStateChangeBroadcast(String bssid) {
@@ -1571,21 +1649,21 @@
                 mNetworkInfo.getDetailedState() == DetailedState.CONNECTED) {
             intent.putExtra(WifiManager.EXTRA_WIFI_INFO, new WifiInfo(mWifiInfo));
         }
-        mContext.sendStickyBroadcast(intent);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void sendLinkConfigurationChangedBroadcast() {
         Intent intent = new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties));
-        mContext.sendBroadcast(intent);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void sendSupplicantConnectionChangedBroadcast(boolean connected) {
         Intent intent = new Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, connected);
-        mContext.sendBroadcast(intent);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     /**
@@ -1599,7 +1677,7 @@
         }
 
         if (state != mNetworkInfo.getDetailedState()) {
-            mNetworkInfo.setDetailedState(state, null, null);
+            mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());
         }
     }
 
@@ -1624,11 +1702,8 @@
             mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
         }
 
-        if (state == SupplicantState.ASSOCIATING) {
-            /* BSSID is valid only in ASSOCIATING state */
-            mWifiInfo.setBSSID(stateChangeResult.BSSID);
-        }
-        mWifiInfo.setSSID(stateChangeResult.SSID);
+        mWifiInfo.setBSSID(stateChangeResult.BSSID);
+        mWifiInfo.setSSID(stateChangeResult.wifiSsid);
 
         mSupplicantStateTracker.sendMessage(Message.obtain(message));
 
@@ -1649,10 +1724,7 @@
             /* In case we were in middle of DHCP operation
                restore back powermode */
             handlePostDhcpSetup();
-
             mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
-            mDhcpStateMachine.doQuit();
-            mDhcpStateMachine = null;
         }
 
         try {
@@ -1711,18 +1783,19 @@
                     mWifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
         }
 
-        /* Disable power save during DHCP */
-        if (mPowerSaveEnabled) {
-            mPowerSaveEnabled = false;
-            mWifiNative.setPowerSave(mPowerSaveEnabled);
-        }
+        /* Disable power save and suspend optimizations during DHCP */
+        // Note: The order here is important for now. Brcm driver changes
+        // power settings when we control suspend mode optimizations.
+        // TODO: Remove this comment when the driver is fixed.
+        setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, false);
+        mWifiNative.setPowerSave(false);
     }
 
 
     void handlePostDhcpSetup() {
-        /* Restore power save */
-        mPowerSaveEnabled = true;
-        mWifiNative.setPowerSave(mPowerSaveEnabled);
+        /* Restore power save and suspend optimizations */
+        setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true);
+        mWifiNative.setPowerSave(true);
 
         // Set the coexistence mode back to its default value
         mWifiNative.setBluetoothCoexistenceMode(
@@ -1794,12 +1867,12 @@
         new Thread(new Runnable() {
             public void run() {
                 try {
-                    mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
+                    mNwService.startAccessPoint(config, mInterfaceName);
                 } catch (Exception e) {
                     loge("Exception in softap start " + e);
                     try {
                         mNwService.stopAccessPoint(mInterfaceName);
-                        mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
+                        mNwService.startAccessPoint(config, mInterfaceName);
                     } catch (Exception e1) {
                         loge("Exception in softap re-start " + e1);
                         sendMessage(CMD_START_AP_FAILURE);
@@ -1855,7 +1928,11 @@
                     mEnableBackgroundScan = (message.arg1 == 1);
                     break;
                 case CMD_SET_HIGH_PERF_MODE:
-                    mHighPerfMode = (message.arg1 == 1);
+                    if (message.arg1 == 1) {
+                        setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, false);
+                    } else {
+                        setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, true);
+                    }
                     break;
                     /* Discard */
                 case CMD_LOAD_DRIVER:
@@ -1902,11 +1979,18 @@
                 case CMD_RESPONSE_AP_CONFIG:
                 case WifiWatchdogStateMachine.POOR_LINK_DETECTED:
                 case WifiWatchdogStateMachine.GOOD_LINK_DETECTED:
-                case CMD_CLEAR_SUSPEND_OPTIMIZATIONS:
                 case CMD_NO_NETWORKS_PERIODIC_SCAN:
                     break;
-                case CMD_SET_SUSPEND_OPTIMIZATIONS:
-                    mSuspendWakeLock.release();
+                case DhcpStateMachine.CMD_ON_QUIT:
+                    mDhcpStateMachine = null;
+                    break;
+                case CMD_SET_SUSPEND_OPT_ENABLED:
+                    if (message.arg1 == 1) {
+                        mSuspendWakeLock.release();
+                        setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, true);
+                    } else {
+                        setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, false);
+                    }
                     break;
                 case WifiMonitor.DRIVER_HUNG_EVENT:
                     setWifiEnabled(false);
@@ -1936,8 +2020,17 @@
                     replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED,
                             WifiManager.BUSY);
                     break;
-                case WifiWatchdogStateMachine.RSSI_FETCH:
-                    replyToMessage(message, WifiWatchdogStateMachine.RSSI_FETCH_FAILED);
+                case WifiManager.RSSI_PKTCNT_FETCH:
+                    replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_FAILED,
+                            WifiManager.BUSY);
+                    break;
+                case WifiP2pService.P2P_CONNECTION_CHANGED:
+                    NetworkInfo info = (NetworkInfo) message.obj;
+                    mP2pConnected.set(info.isConnected());
+                    break;
+                case WifiP2pService.DISCONNECT_WIFI_REQUEST:
+                    mTemporarilyDisconnectWifi = (message.arg1 == 1);
+                    replyToMessage(message, WifiP2pService.DISCONNECT_WIFI_RESPONSE);
                     break;
                 default:
                     loge("Error! unhandled message" + message);
@@ -2336,10 +2429,10 @@
             mNetworkInfo.setIsAvailable(true);
 
             int defaultInterval = mContext.getResources().getInteger(
-                    com.android.internal.R.integer.config_wifi_supplicant_scan_interval);
+                    R.integer.config_wifi_supplicant_scan_interval);
 
-            mSupplicantScanIntervalMs = Settings.Secure.getLong(mContext.getContentResolver(),
-                    Settings.Secure.WIFI_SUPPLICANT_SCAN_INTERVAL_MS,
+            mSupplicantScanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),
+                    Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS,
                     defaultInterval);
 
             mWifiNative.setScanInterval((int)mSupplicantScanIntervalMs / 1000);
@@ -2350,7 +2443,11 @@
             WifiConfiguration config;
             switch(message.what) {
                 case CMD_STOP_SUPPLICANT:   /* Supplicant stopped by user */
-                    transitionTo(mSupplicantStoppingState);
+                    if (mP2pSupported) {
+                        transitionTo(mWaitForP2pDisableState);
+                    } else {
+                        transitionTo(mSupplicantStoppingState);
+                    }
                     break;
                 case WifiMonitor.SUP_DISCONNECTION_EVENT:  /* Supplicant connection lost */
                     loge("Connection lost, restart supplicant");
@@ -2360,7 +2457,11 @@
                     handleNetworkDisconnect();
                     sendSupplicantConnectionChangedBroadcast(false);
                     mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
-                    transitionTo(mDriverLoadedState);
+                    if (mP2pSupported) {
+                        transitionTo(mWaitForP2pDisableState);
+                    } else {
+                        transitionTo(mDriverLoadedState);
+                    }
                     sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
                     break;
                 case WifiMonitor.SCAN_RESULTS_EVENT:
@@ -2474,6 +2575,9 @@
 
             /* Send any reset commands to supplicant before shutting it down */
             handleNetworkDisconnect();
+            if (mDhcpStateMachine != null) {
+                mDhcpStateMachine.doQuit();
+            }
 
             if (DBG) log("stopping supplicant");
             if (!mWifiNative.stopSupplicant()) {
@@ -2638,8 +2742,6 @@
                 mWifiNative.stopFilteringMulticastV4Packets();
             }
 
-            mWifiNative.setPowerSave(mPowerSaveEnabled);
-
             if (mIsScanMode) {
                 mWifiNative.setScanResultHandling(SCAN_ONLY_MODE);
                 mWifiNative.disconnect();
@@ -2654,9 +2756,19 @@
                 transitionTo(mDisconnectedState);
             }
 
-            if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P);
+            // We may have missed screen update at boot
+            if (mScreenBroadcastReceived.get() == false) {
+                PowerManager powerManager = (PowerManager)mContext.getSystemService(
+                        Context.POWER_SERVICE);
+                handleScreenStateChanged(powerManager.isScreenOn());
+            } else {
+                // Set the right suspend mode settings
+                mWifiNative.setSuspendOptimizations(mSuspendOptNeedsDisabled == 0
+                        && mUserWantsSuspendOpt.get());
+            }
+            mWifiNative.setPowerSave(true);
 
-            mContext.registerReceiver(mScreenReceiver, mScreenFilter);
+            if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P);
         }
         @Override
         public boolean processMessage(Message message) {
@@ -2744,8 +2856,12 @@
                     }
                     mWakeLock.acquire();
                     mWifiNative.stopDriver();
-                    transitionTo(mDriverStoppingState);
                     mWakeLock.release();
+                    if (mP2pSupported) {
+                        transitionTo(mWaitForP2pDisableState);
+                    } else {
+                        transitionTo(mDriverStoppingState);
+                    }
                     break;
                 case CMD_START_PACKET_FILTERING:
                     if (message.arg1 == MULTICAST_V6) {
@@ -2765,20 +2881,19 @@
                         loge("Illegal arugments to CMD_STOP_PACKET_FILTERING");
                     }
                     break;
-                case CMD_SET_SUSPEND_OPTIMIZATIONS:
-                    if (!mHighPerfMode) {
-                        mWifiNative.setSuspendOptimizations(true);
+                case CMD_SET_SUSPEND_OPT_ENABLED:
+                    if (message.arg1 == 1) {
+                        setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true);
+                        mSuspendWakeLock.release();
+                    } else {
+                        setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false);
                     }
-                    mSuspendWakeLock.release();
-                    break;
-                case CMD_CLEAR_SUSPEND_OPTIMIZATIONS:
-                    mWifiNative.setSuspendOptimizations(false);
                     break;
                 case CMD_SET_HIGH_PERF_MODE:
-                    mHighPerfMode = (message.arg1 == 1);
-                    if (mHighPerfMode) {
-                        //Disable any suspend optimizations
-                        mWifiNative.setSuspendOptimizations(false);
+                    if (message.arg1 == 1) {
+                        setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false);
+                    } else {
+                        setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true);
                     }
                     break;
                 default:
@@ -2791,10 +2906,65 @@
             if (DBG) log(getName() + "\n");
             mIsRunning = false;
             updateBatteryWorkSource(null);
-            mScanResults = null;
+            mScanResults = new ArrayList<ScanResult>();
+        }
+    }
 
-            if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P);
-            mContext.unregisterReceiver(mScreenReceiver);
+    class WaitForP2pDisableState extends State {
+        private State mTransitionToState;
+        @Override
+        public void enter() {
+            if (DBG) log(getName() + "\n");
+            EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+            switch (getCurrentMessage().what) {
+                case WifiMonitor.SUP_DISCONNECTION_EVENT:
+                    mTransitionToState = mDriverLoadedState;
+                    break;
+                case CMD_DELAYED_STOP_DRIVER:
+                    mTransitionToState = mDriverStoppingState;
+                    break;
+                case CMD_STOP_SUPPLICANT:
+                    mTransitionToState = mSupplicantStoppingState;
+                    break;
+                default:
+                    mTransitionToState = mDriverStoppingState;
+                    break;
+            }
+            mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_REQ);
+        }
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) log(getName() + message.toString() + "\n");
+            switch(message.what) {
+                case WifiStateMachine.CMD_DISABLE_P2P_RSP:
+                    transitionTo(mTransitionToState);
+                    break;
+                /* Defer wifi start/shut and driver commands */
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
+                case CMD_LOAD_DRIVER:
+                case CMD_UNLOAD_DRIVER:
+                case CMD_START_SUPPLICANT:
+                case CMD_STOP_SUPPLICANT:
+                case CMD_START_AP:
+                case CMD_STOP_AP:
+                case CMD_START_DRIVER:
+                case CMD_STOP_DRIVER:
+                case CMD_SET_SCAN_MODE:
+                case CMD_SET_SCAN_TYPE:
+                case CMD_SET_COUNTRY_CODE:
+                case CMD_SET_FREQUENCY_BAND:
+                case CMD_START_PACKET_FILTERING:
+                case CMD_STOP_PACKET_FILTERING:
+                case CMD_START_SCAN:
+                case CMD_DISCONNECT:
+                case CMD_REASSOCIATE:
+                case CMD_RECONNECT:
+                    deferMessage(message);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
         }
     }
 
@@ -2943,6 +3113,15 @@
                         transitionTo(mDisconnectedState);
                     }
                     break;
+                case WifiP2pService.DISCONNECT_WIFI_REQUEST:
+                    if (message.arg1 == 1) {
+                        mWifiNative.disconnect();
+                        mTemporarilyDisconnectWifi = true;
+                    } else {
+                        mWifiNative.reconnect();
+                        mTemporarilyDisconnectWifi = false;
+                    }
+                    break;
                     /* Do a redundant disconnect without transition */
                 case CMD_DISCONNECT:
                     mWifiNative.disconnect();
@@ -3072,6 +3251,13 @@
                     mWifiNative.disconnect();
                     transitionTo(mDisconnectingState);
                     break;
+                case WifiP2pService.DISCONNECT_WIFI_REQUEST:
+                    if (message.arg1 == 1) {
+                        mWifiNative.disconnect();
+                        mTemporarilyDisconnectWifi = true;
+                        transitionTo(mDisconnectingState);
+                    }
+                    break;
                 case CMD_SET_SCAN_MODE:
                     if (message.arg1 == SCAN_ONLY_MODE) {
                         sendMessage(CMD_DISCONNECT);
@@ -3140,10 +3326,12 @@
                                 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS);
                     }
                     break;
-                case WifiWatchdogStateMachine.RSSI_FETCH:
+                case WifiManager.RSSI_PKTCNT_FETCH:
+                    RssiPacketCountInfo info = new RssiPacketCountInfo();
                     fetchRssiAndLinkSpeedNative();
-                    replyToMessage(message, WifiWatchdogStateMachine.RSSI_FETCH_SUCCEEDED,
-                            mWifiInfo.getRssi());
+                    info.rssi = mWifiInfo.getRssi();
+                    fetchPktcntNative(info);
+                    replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED, info);
                     break;
                 default:
                     return NOT_HANDLED;
@@ -3171,8 +3359,11 @@
 
             if (!mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
                 //start DHCP
-                mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(
-                        mContext, WifiStateMachine.this, mInterfaceName);
+                if (mDhcpStateMachine == null) {
+                    mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(
+                            mContext, WifiStateMachine.this, mInterfaceName);
+
+                }
                 mDhcpStateMachine.registerForPreDhcpNotification();
                 mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
             } else {
@@ -3236,6 +3427,26 @@
                     //stay here
                     break;
                 case WifiWatchdogStateMachine.GOOD_LINK_DETECTED:
+                    transitionTo(mCaptivePortalCheckState);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+    class CaptivePortalCheckState extends State {
+        @Override
+        public void enter() {
+            setNetworkDetailedState(DetailedState.CAPTIVE_PORTAL_CHECK);
+            mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.CAPTIVE_PORTAL_CHECK);
+            sendNetworkStateChangeBroadcast(mLastBssid);
+        }
+        @Override
+        public boolean processMessage(Message message) {
+            switch (message.what) {
+                case CMD_CAPTIVE_CHECK_COMPLETE:
                     try {
                         mNwService.enableIpv6(mInterfaceName);
                     } catch (RemoteException re) {
@@ -3243,7 +3454,6 @@
                     } catch (IllegalStateException e) {
                         loge("Failed to enable IPv6: " + e);
                     }
-
                     setNetworkDetailedState(DetailedState.CONNECTED);
                     mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.CONNECTED);
                     sendNetworkStateChangeBroadcast(mLastBssid);
@@ -3354,8 +3564,15 @@
             if (DBG) log(getName() + "\n");
             EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
 
-            mFrameworkScanIntervalMs = Settings.Secure.getLong(mContext.getContentResolver(),
-                    Settings.Secure.WIFI_FRAMEWORK_SCAN_INTERVAL_MS,
+            // We dont scan frequently if this is a temporary disconnect
+            // due to p2p
+            if (mTemporarilyDisconnectWifi) {
+                mWifiP2pChannel.sendMessage(WifiP2pService.DISCONNECT_WIFI_RESPONSE);
+                return;
+            }
+
+            mFrameworkScanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),
+                    Settings.Global.WIFI_FRAMEWORK_SCAN_INTERVAL_MS,
                     mDefaultFrameworkScanIntervalMs);
             /*
              * We initiate background scanning if it is enabled, otherwise we
@@ -3381,7 +3598,7 @@
              * The scans are useful to notify the user of the presence of an open network.
              * Note that these are not wake up scans.
              */
-            if (mWifiConfigStore.getConfiguredNetworks().size() == 0) {
+            if (!mP2pConnected.get() && mWifiConfigStore.getConfiguredNetworks().size() == 0) {
                 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
                             ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
             }
@@ -3392,6 +3609,7 @@
             boolean ret = HANDLED;
             switch (message.what) {
                 case CMD_NO_NETWORKS_PERIODIC_SCAN:
+                    if (mP2pConnected.get()) break;
                     if (message.arg1 == mPeriodicScanToken &&
                             mWifiConfigStore.getConfiguredNetworks().size() == 0) {
                         sendMessage(CMD_START_SCAN);
@@ -3452,6 +3670,27 @@
                     /* Handled in parent state */
                     ret = NOT_HANDLED;
                     break;
+                case WifiP2pService.P2P_CONNECTION_CHANGED:
+                    NetworkInfo info = (NetworkInfo) message.obj;
+                    mP2pConnected.set(info.isConnected());
+                    if (mP2pConnected.get()) {
+                        int defaultInterval = mContext.getResources().getInteger(
+                                R.integer.config_wifi_scan_interval_p2p_connected);
+                        long scanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),
+                                Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS,
+                                defaultInterval);
+                        mWifiNative.setScanInterval((int) scanIntervalMs/1000);
+                    } else if (mWifiConfigStore.getConfiguredNetworks().size() == 0) {
+                        if (DBG) log("Turn on scanning after p2p disconnected");
+                        sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
+                                    ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
+                    }
+                case CMD_RECONNECT:
+                case CMD_REASSOCIATE:
+                    // Drop a third party reconnect/reassociate if we are
+                    // tempoarily disconnected for p2p
+                    if (mTemporarilyDisconnectWifi) ret = NOT_HANDLED;
+                    break;
                 default:
                     ret = NOT_HANDLED;
             }
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index bfb91e2..55ea34f 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -23,8 +23,8 @@
 import android.net.LinkCapabilities;
 import android.net.LinkProperties;
 import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkStateTracker;
-import android.net.wifi.p2p.WifiP2pManager;
 import android.os.Handler;
 import android.os.Message;
 import android.util.Slog;
@@ -87,7 +87,6 @@
         IntentFilter filter = new IntentFilter();
         filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
         filter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
-        filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
 
         mWifiStateReceiver = new WifiStateReceiver();
         mContext.registerReceiver(mWifiStateReceiver, filter);
@@ -113,6 +112,14 @@
     }
 
     /**
+     * Captive check is complete, switch to network
+     */
+    @Override
+    public void captivePortalCheckComplete() {
+        mWifiManager.captivePortalCheckComplete();
+    }
+
+    /**
      * Turn the wireless radio off for a network.
      * @param turnOn {@code true} to turn the radio on, {@code false}
      */
@@ -208,20 +215,7 @@
         @Override
         public void onReceive(Context context, Intent intent) {
 
-            if (intent.getAction().equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) {
-                    mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
-                            WifiP2pManager.EXTRA_NETWORK_INFO);
-                    mLinkProperties = intent.getParcelableExtra(
-                            WifiP2pManager.EXTRA_LINK_PROPERTIES);
-                    if (mLinkProperties == null) {
-                        mLinkProperties = new LinkProperties();
-                    }
-                    mLinkCapabilities = intent.getParcelableExtra(
-                        WifiP2pManager.EXTRA_LINK_CAPABILITIES);
-                    if (mLinkCapabilities == null) {
-                        mLinkCapabilities = new LinkCapabilities();
-                    }
-             } else if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+            if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                 mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
                         WifiManager.EXTRA_NETWORK_INFO);
                 mLinkProperties = intent.getParcelableExtra(
@@ -235,9 +229,10 @@
                     mLinkCapabilities = new LinkCapabilities();
                 }
                 // don't want to send redundent state messages
-                // TODO can this be fixed in WifiStateMachine?
+                // but send portal check detailed state notice
                 NetworkInfo.State state = mNetworkInfo.getState();
-                if (mLastState == state) {
+                if (mLastState == state &&
+                        mNetworkInfo.getDetailedState() != DetailedState.CAPTIVE_PORTAL_CHECK) {
                     return;
                 } else {
                     mLastState = state;
diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
index c6d3eae..c8f0712 100644
--- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
@@ -16,29 +16,22 @@
 
 package android.net.wifi;
 
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.res.Resources;
 import android.database.ContentObserver;
-import android.net.arp.ArpPeer;
 import android.net.ConnectivityManager;
-import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.NetworkInfo;
-import android.net.RouteInfo;
-import android.net.Uri;
+import android.net.wifi.RssiPacketCountInfo;
 import android.os.Message;
 import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.util.Log;
+import android.util.LruCache;
 
 import com.android.internal.R;
 import com.android.internal.util.AsyncChannel;
@@ -46,43 +39,36 @@
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
 
-import java.io.IOException;
 import java.io.PrintWriter;
-import java.net.HttpURLConnection;
-import java.net.InetAddress;
-import java.net.SocketException;
-import java.net.URL;
+import java.text.DecimalFormat;
 
 /**
- * WifiWatchdogStateMachine monitors the connection to a Wi-Fi
- * network. After the framework notifies that it has connected to an
- * acccess point and is waiting for link to be verified, the watchdog
- * takes over and verifies if the link is good by doing ARP pings to
- * the gateway using {@link ArpPeer}.
- *
- * Upon successful verification, the watchdog notifies and continues
- * to monitor the link afterwards when the RSSI level falls below
- * a certain threshold.
-
- * When Wi-fi connects at L2 layer, the beacons from access point reach
- * the device and it can maintain a connection, but the application
- * connectivity can be flaky (due to bigger packet size exchange).
- *
- * We now monitor the quality of the last hop on
- * Wi-Fi using signal strength and ARP connectivity as indicators
- * to decide if the link is good enough to switch to Wi-Fi as the uplink.
- *
- * ARP pings are useful for link validation but can still get through
- * when the application traffic fails to go through and are thus not
- * the best indicator of real packet loss since they are tiny packets
- * (28 bytes) and have a much low chance of packet corruption than the
- * regular data packets.
- *
- * When signal strength and ARP are used together, it ends up working well in tests.
- * The goal is to switch to Wi-Fi after validating ARP transfer
- * and RSSI and then switching out of Wi-Fi when we hit a low
- * signal strength threshold and then waiting until the signal strength
- * improves and validating ARP transfer.
+ * WifiWatchdogStateMachine monitors the connection to a WiFi network. When WiFi
+ * connects at L2 layer, the beacons from access point reach the device and it
+ * can maintain a connection, but the application connectivity can be flaky (due
+ * to bigger packet size exchange).
+ * <p>
+ * We now monitor the quality of the last hop on WiFi using packet loss ratio as
+ * an indicator to decide if the link is good enough to switch to Wi-Fi as the
+ * uplink.
+ * <p>
+ * When WiFi is connected, the WiFi watchdog keeps sampling the RSSI and the
+ * instant packet loss, and record it as per-AP loss-to-rssi statistics. When
+ * the instant packet loss is higher than a threshold, the WiFi watchdog sends a
+ * poor link notification to avoid WiFi connection temporarily.
+ * <p>
+ * While WiFi is being avoided, the WiFi watchdog keep watching the RSSI to
+ * bring the WiFi connection back. Once the RSSI is high enough to achieve a
+ * lower packet loss, a good link detection is sent such that the WiFi
+ * connection become available again.
+ * <p>
+ * BSSID roaming has been taken into account. When user is moving across
+ * multiple APs, the WiFi watchdog will detect that and keep watching the
+ * currently connected AP.
+ * <p>
+ * Power impact should be minimal since much of the measurement relies on
+ * passive statistics already being tracked at the driver and the polling is
+ * done when screen is turned on and the RSSI is in a certain range.
  *
  * @hide
  */
@@ -91,129 +77,223 @@
     /* STOPSHIP: Keep this configurable for debugging until ship */
     private static boolean DBG = false;
     private static final String TAG = "WifiWatchdogStateMachine";
-    private static final String WALLED_GARDEN_NOTIFICATION_ID = "WifiWatchdog.walledgarden";
-
-    /* RSSI Levels as used by notification icon
-       Level 4  -55 <= RSSI
-       Level 3  -66 <= RSSI < -55
-       Level 2  -77 <= RSSI < -67
-       Level 1  -88 <= RSSI < -78
-       Level 0         RSSI < -88 */
-
-    /* Wi-fi connection is monitored actively below this
-       threshold */
-    private static final int RSSI_LEVEL_MONITOR = 0;
-    /* Rssi threshold is at level 0 (-88dBm) */
-    private static final int RSSI_MONITOR_THRESHOLD = -88;
-    /* Number of times RSSI is measured to be low before being avoided */
-    private static final int RSSI_MONITOR_COUNT = 5;
-    private int mRssiMonitorCount = 0;
-
-    /* Avoid flapping. The interval is changed over time as long as we continue to avoid
-     * under the max interval after which we reset the interval again */
-    private static final int MIN_INTERVAL_AVOID_BSSID_MS[] = {0, 30 * 1000, 60 * 1000,
-            5 * 60 * 1000, 30 * 60 * 1000};
-    /* Index into the interval array MIN_INTERVAL_AVOID_BSSID_MS */
-    private int mMinIntervalArrayIndex = 0;
-
-    private long mLastBssidAvoidedTime;
-
-    private int mCurrentSignalLevel;
-
-    private static final long DEFAULT_ARP_CHECK_INTERVAL_MS = 2 * 60 * 1000;
-    private static final long DEFAULT_RSSI_FETCH_INTERVAL_MS = 1000;
-    private static final long DEFAULT_WALLED_GARDEN_INTERVAL_MS = 30 * 60 * 1000;
-
-    private static final int DEFAULT_NUM_ARP_PINGS = 5;
-    private static final int DEFAULT_MIN_ARP_RESPONSES = 1;
-
-    private static final int DEFAULT_ARP_PING_TIMEOUT_MS = 100;
-
-    // See http://go/clientsdns for usage approval
-    private static final String DEFAULT_WALLED_GARDEN_URL =
-            "http://clients3.google.com/generate_204";
-    private static final int WALLED_GARDEN_SOCKET_TIMEOUT_MS = 10000;
-
-    /* Some carrier apps might have support captive portal handling. Add some delay to allow
-        app authentication to be done before our test.
-       TODO: This should go away once we provide an API to apps to disable walled garden test
-       for certain SSIDs
-     */
-    private static final int WALLED_GARDEN_START_DELAY_MS = 3000;
 
     private static final int BASE = Protocol.BASE_WIFI_WATCHDOG;
 
-    /**
-     * Indicates the enable setting of WWS may have changed
-     */
+    /* Internal events */
     private static final int EVENT_WATCHDOG_TOGGLED                 = BASE + 1;
-
-    /**
-     * Indicates the wifi network state has changed. Passed w/ original intent
-     * which has a non-null networkInfo object
-     */
     private static final int EVENT_NETWORK_STATE_CHANGE             = BASE + 2;
-    /* Passed with RSSI information */
     private static final int EVENT_RSSI_CHANGE                      = BASE + 3;
+    private static final int EVENT_SUPPLICANT_STATE_CHANGE          = BASE + 4;
     private static final int EVENT_WIFI_RADIO_STATE_CHANGE          = BASE + 5;
     private static final int EVENT_WATCHDOG_SETTINGS_CHANGE         = BASE + 6;
+    private static final int EVENT_BSSID_CHANGE                     = BASE + 7;
+    private static final int EVENT_SCREEN_ON                        = BASE + 8;
+    private static final int EVENT_SCREEN_OFF                       = BASE + 9;
 
     /* Internal messages */
-    private static final int CMD_ARP_CHECK                          = BASE + 11;
-    private static final int CMD_DELAYED_WALLED_GARDEN_CHECK        = BASE + 12;
-    private static final int CMD_RSSI_FETCH                         = BASE + 13;
+    private static final int CMD_RSSI_FETCH                         = BASE + 11;
 
-    /* Notifications to WifiStateMachine */
+    /* Notifications from/to WifiStateMachine */
     static final int POOR_LINK_DETECTED                             = BASE + 21;
     static final int GOOD_LINK_DETECTED                             = BASE + 22;
-    static final int RSSI_FETCH                                     = BASE + 23;
-    static final int RSSI_FETCH_SUCCEEDED                           = BASE + 24;
-    static final int RSSI_FETCH_FAILED                              = BASE + 25;
 
-    private static final int SINGLE_ARP_CHECK = 0;
-    private static final int FULL_ARP_CHECK   = 1;
+    public static final boolean DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED = false;
 
+    /*
+     * RSSI levels as used by notification icon
+     * Level 4  -55 <= RSSI
+     * Level 3  -66 <= RSSI < -55
+     * Level 2  -77 <= RSSI < -67
+     * Level 1  -88 <= RSSI < -78
+     * Level 0         RSSI < -88
+     */
+
+    /**
+     * WiFi link statistics is monitored and recorded actively below this threshold.
+     * <p>
+     * Larger threshold is more adaptive but increases sampling cost.
+     */
+    private static final int LINK_MONITOR_LEVEL_THRESHOLD = WifiManager.RSSI_LEVELS - 1;
+
+    /**
+     * Remember packet loss statistics of how many BSSIDs.
+     * <p>
+     * Larger size is usually better but requires more space.
+     */
+    private static final int BSSID_STAT_CACHE_SIZE = 20;
+
+    /**
+     * RSSI range of a BSSID statistics.
+     * Within the range, (RSSI -> packet loss %) mappings are stored.
+     * <p>
+     * Larger range is usually better but requires more space.
+     */
+    private static final int BSSID_STAT_RANGE_LOW_DBM  = -105;
+
+    /**
+     * See {@link #BSSID_STAT_RANGE_LOW_DBM}.
+     */
+    private static final int BSSID_STAT_RANGE_HIGH_DBM = -45;
+
+    /**
+     * How many consecutive empty data point to trigger a empty-cache detection.
+     * In this case, a preset/default loss value (function on RSSI) is used.
+     * <p>
+     * In normal uses, some RSSI values may never be seen due to channel randomness.
+     * However, the size of such empty RSSI chunk in normal use is generally 1~2.
+     */
+    private static final int BSSID_STAT_EMPTY_COUNT = 3;
+
+    /**
+     * Sample interval for packet loss statistics, in msec.
+     * <p>
+     * Smaller interval is more accurate but increases sampling cost (battery consumption).
+     */
+    private static final long LINK_SAMPLING_INTERVAL_MS = 1 * 1000;
+
+    /**
+     * Coefficients (alpha) for moving average for packet loss tracking.
+     * Must be within (0.0, 1.0).
+     * <p>
+     * Equivalent number of samples: N = 2 / alpha - 1 .
+     * We want the historic loss to base on more data points to be statistically reliable.
+     * We want the current instant loss to base on less data points to be responsive.
+     */
+    private static final double EXP_COEFFICIENT_RECORD  = 0.1;
+
+    /**
+     * See {@link #EXP_COEFFICIENT_RECORD}.
+     */
+    private static final double EXP_COEFFICIENT_MONITOR = 0.5;
+
+    /**
+     * Thresholds for sending good/poor link notifications, in packet loss %.
+     * Good threshold must be smaller than poor threshold.
+     * Use smaller poor threshold to avoid WiFi more aggressively.
+     * Use smaller good threshold to bring back WiFi more conservatively.
+     * <p>
+     * When approaching the boundary, loss ratio jumps significantly within a few dBs.
+     * 50% loss threshold is a good balance between accuracy and reponsiveness.
+     * <=10% good threshold is a safe value to avoid jumping back to WiFi too easily.
+     */
+    private static final double POOR_LINK_LOSS_THRESHOLD = 0.5;
+
+    /**
+     * See {@link #POOR_LINK_LOSS_THRESHOLD}.
+     */
+    private static final double GOOD_LINK_LOSS_THRESHOLD = 0.1;
+
+    /**
+     * Number of samples to confirm before sending a poor link notification.
+     * Response time = confirm_count * sample_interval .
+     * <p>
+     * A smaller threshold improves response speed but may suffer from randomness.
+     * According to experiments, 3~5 are good values to achieve a balance.
+     * These parameters should be tuned along with {@link #LINK_SAMPLING_INTERVAL_MS}.
+     */
+    private static final int POOR_LINK_SAMPLE_COUNT = 3;
+
+    /**
+     * Minimum volume (converted from pkt/sec) to detect a poor link, to avoid randomness.
+     * <p>
+     * According to experiments, 1pkt/sec is too sensitive but 3pkt/sec is slightly unresponsive.
+     */
+    private static final double POOR_LINK_MIN_VOLUME = 2.0 * LINK_SAMPLING_INTERVAL_MS / 1000.0;
+
+    /**
+     * When a poor link is detected, we scan over this range (based on current
+     * poor link RSSI) for a target RSSI that satisfies a target packet loss.
+     * Refer to {@link #GOOD_LINK_TARGET}.
+     * <p>
+     * We want range_min not too small to avoid jumping back to WiFi too easily.
+     */
+    private static final int GOOD_LINK_RSSI_RANGE_MIN = 3;
+
+    /**
+     * See {@link #GOOD_LINK_RSSI_RANGE_MIN}.
+     */
+    private static final int GOOD_LINK_RSSI_RANGE_MAX = 20;
+
+    /**
+     * Adaptive good link target to avoid flapping.
+     * When a poor link is detected, a good link target is calculated as follows:
+     * <p>
+     *      targetRSSI = min { rssi | loss(rssi) < GOOD_LINK_LOSS_THRESHOLD } + rssi_adj[i],
+     *                   where rssi is within the above GOOD_LINK_RSSI_RANGE.
+     *      targetCount = sample_count[i] .
+     * <p>
+     * While WiFi is being avoided, we keep monitoring its signal strength.
+     * Good link notification is sent when we see current RSSI >= targetRSSI
+     * for targetCount consecutive times.
+     * <p>
+     * Index i is incremented each time after a poor link detection.
+     * Index i is decreased to at most k if the last poor link was at lease reduce_time[k] ago.
+     * <p>
+     * Intuitively, larger index i makes it more difficult to get back to WiFi, avoiding flapping.
+     * In experiments, (+9 dB / 30 counts) makes it quite difficult to achieve.
+     * Avoid using it unless flapping is really bad (say, last poor link is < 1 min ago).
+     */
+    private static final GoodLinkTarget[] GOOD_LINK_TARGET = {
+        /*                  rssi_adj,       sample_count,   reduce_time */
+        new GoodLinkTarget( 0,              3,              30 * 60000   ),
+        new GoodLinkTarget( 3,              5,              5  * 60000   ),
+        new GoodLinkTarget( 6,              10,             1  * 60000   ),
+        new GoodLinkTarget( 9,              30,             0  * 60000   ),
+    };
+
+    /**
+     * The max time to avoid a BSSID, to prevent avoiding forever.
+     * If current RSSI is at least min_rssi[i], the max avoidance time is at most max_time[i]
+     * <p>
+     * It is unusual to experience high packet loss at high RSSI. Something unusual must be
+     * happening (e.g. strong interference). For higher signal strengths, we set the avoidance
+     * time to be low to allow for quick turn around from temporary interference.
+     * <p>
+     * See {@link BssidStatistics#poorLinkDetected}.
+     */
+    private static final MaxAvoidTime[] MAX_AVOID_TIME = {
+        /*                  max_time,           min_rssi */
+        new MaxAvoidTime(   30 * 60000,         -200      ),
+        new MaxAvoidTime(   5  * 60000,         -70       ),
+        new MaxAvoidTime(   0  * 60000,         -55       ),
+    };
+
+    /* Framework related */
     private Context mContext;
     private ContentResolver mContentResolver;
     private WifiManager mWifiManager;
     private IntentFilter mIntentFilter;
     private BroadcastReceiver mBroadcastReceiver;
-    private AsyncChannel mWsmChannel = new AsyncChannel();;
+    private AsyncChannel mWsmChannel = new AsyncChannel();
+    private WifiInfo mWifiInfo;
+    private LinkProperties mLinkProperties;
 
+    /* System settingss related */
+    private static boolean sWifiOnly = false;
+    private boolean mPoorNetworkDetectionEnabled;
+
+    /* Poor link detection related */
+    private LruCache<String, BssidStatistics> mBssidCache =
+            new LruCache<String, BssidStatistics>(BSSID_STAT_CACHE_SIZE);
+    private int mRssiFetchToken = 0;
+    private int mCurrentSignalLevel;
+    private BssidStatistics mCurrentBssid;
+    private VolumeWeightedEMA mCurrentLoss;
+    private boolean mIsScreenOn = true;
+    private static double sPresetLoss[];
+
+    /* WiFi watchdog state machine related */
     private DefaultState mDefaultState = new DefaultState();
     private WatchdogDisabledState mWatchdogDisabledState = new WatchdogDisabledState();
     private WatchdogEnabledState mWatchdogEnabledState = new WatchdogEnabledState();
     private NotConnectedState mNotConnectedState = new NotConnectedState();
     private VerifyingLinkState mVerifyingLinkState = new VerifyingLinkState();
     private ConnectedState mConnectedState = new ConnectedState();
-    private WalledGardenCheckState mWalledGardenCheckState = new WalledGardenCheckState();
-    /* Online and watching link connectivity */
     private OnlineWatchState mOnlineWatchState = new OnlineWatchState();
-    /* RSSI level is below RSSI_LEVEL_MONITOR and needs close monitoring */
-    private RssiMonitoringState mRssiMonitoringState = new RssiMonitoringState();
-    /* Online and doing nothing */
+    private LinkMonitoringState mLinkMonitoringState = new LinkMonitoringState();
     private OnlineState mOnlineState = new OnlineState();
 
-    private int mArpToken = 0;
-    private long mArpCheckIntervalMs;
-    private int mRssiFetchToken = 0;
-    private long mRssiFetchIntervalMs;
-    private long mWalledGardenIntervalMs;
-    private int mNumArpPings;
-    private int mMinArpResponses;
-    private int mArpPingTimeoutMs;
-    private boolean mPoorNetworkDetectionEnabled;
-    private boolean mWalledGardenTestEnabled;
-    private String mWalledGardenUrl;
-
-    private WifiInfo mWifiInfo;
-    private LinkProperties mLinkProperties;
-
-    private long mLastWalledGardenCheckTime = 0;
-
-    private static boolean sWifiOnly = false;
-    private boolean mWalledGardenNotificationShown;
-
     /**
      * STATE MAP
      *          Default
@@ -234,7 +314,7 @@
 
         setupNetworkReceiver();
 
-        // The content observer to listen needs a handler
+        // the content observer to listen needs a handler
         registerForSettingsChanges();
         registerForWatchdogToggle();
         addState(mDefaultState);
@@ -243,9 +323,8 @@
                 addState(mNotConnectedState, mWatchdogEnabledState);
                 addState(mVerifyingLinkState, mWatchdogEnabledState);
                 addState(mConnectedState, mWatchdogEnabledState);
-                    addState(mWalledGardenCheckState, mConnectedState);
                     addState(mOnlineWatchState, mConnectedState);
-                    addState(mRssiMonitoringState, mOnlineWatchState);
+                    addState(mLinkMonitoringState, mConnectedState);
                     addState(mOnlineState, mConnectedState);
 
         if (isWatchdogEnabled()) {
@@ -263,18 +342,10 @@
                 Context.CONNECTIVITY_SERVICE);
         sWifiOnly = (cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false);
 
-        // Watchdog is always enabled. Poor network detection & walled garden detection
-        // can individually be turned on/off
+        // Watchdog is always enabled. Poor network detection can be seperately turned on/off
         // TODO: Remove this setting & clean up state machine since we always have
         // watchdog in an enabled state
-        putSettingsBoolean(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON, true);
-
-        // Disable poor network avoidance, but keep watchdog active for walled garden detection
-        if (sWifiOnly) {
-            log("Disabling poor network avoidance for wi-fi only device");
-            putSettingsBoolean(contentResolver,
-                    Settings.Secure.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, false);
-        }
+        putSettingsGlobalBoolean(contentResolver, Settings.Global.WIFI_WATCHDOG_ON, true);
 
         WifiWatchdogStateMachine wwsm = new WifiWatchdogStateMachine(context);
         wwsm.start();
@@ -286,15 +357,20 @@
             @Override
             public void onReceive(Context context, Intent intent) {
                 String action = intent.getAction();
-                if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
-                    sendMessage(EVENT_NETWORK_STATE_CHANGE, intent);
-                } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
+                if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
                     obtainMessage(EVENT_RSSI_CHANGE,
                             intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200), 0).sendToTarget();
+                } else if (action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) {
+                    sendMessage(EVENT_SUPPLICANT_STATE_CHANGE, intent);
+                } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+                    sendMessage(EVENT_NETWORK_STATE_CHANGE, intent);
+                } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
+                    sendMessage(EVENT_SCREEN_ON);
+                } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+                    sendMessage(EVENT_SCREEN_OFF);
                 } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
-                    sendMessage(EVENT_WIFI_RADIO_STATE_CHANGE,
-                            intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
-                                    WifiManager.WIFI_STATE_UNKNOWN));
+                    sendMessage(EVENT_WIFI_RADIO_STATE_CHANGE,intent.getIntExtra(
+                            WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN));
                 }
             }
         };
@@ -303,6 +379,9 @@
         mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
         mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
         mIntentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
+        mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
+        mIntentFilter.addAction(Intent.ACTION_SCREEN_ON);
+        mIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
         mContext.registerReceiver(mBroadcastReceiver, mIntentFilter);
     }
 
@@ -318,7 +397,7 @@
         };
 
         mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ON),
+                Settings.Global.getUriFor(Settings.Global.WIFI_WATCHDOG_ON),
                 false, contentObserver);
     }
 
@@ -334,59 +413,8 @@
         };
 
         mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(
-                        Settings.Secure.WIFI_WATCHDOG_ARP_CHECK_INTERVAL_MS),
-                        false, contentObserver);
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS),
+                Settings.Global.getUriFor(Settings.Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED),
                 false, contentObserver);
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_NUM_ARP_PINGS),
-                false, contentObserver);
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_MIN_ARP_RESPONSES),
-                false, contentObserver);
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ARP_PING_TIMEOUT_MS),
-                false, contentObserver);
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED),
-                false, contentObserver);
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED),
-                false, contentObserver);
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL),
-                false, contentObserver);
-    }
-
-    /**
-     * DNS based detection techniques do not work at all hotspots. The one sure
-     * way to check a walled garden is to see if a URL fetch on a known address
-     * fetches the data we expect
-     */
-    private boolean isWalledGardenConnection() {
-        HttpURLConnection urlConnection = null;
-        try {
-            URL url = new URL(mWalledGardenUrl);
-            urlConnection = (HttpURLConnection) url.openConnection();
-            urlConnection.setInstanceFollowRedirects(false);
-            urlConnection.setConnectTimeout(WALLED_GARDEN_SOCKET_TIMEOUT_MS);
-            urlConnection.setReadTimeout(WALLED_GARDEN_SOCKET_TIMEOUT_MS);
-            urlConnection.setUseCaches(false);
-            urlConnection.getInputStream();
-            // We got a valid response, but not from the real google
-            return urlConnection.getResponseCode() != 204;
-        } catch (IOException e) {
-            if (DBG) {
-                log("Walled garden check - probably not a portal: exception " + e);
-            }
-            return false;
-        } finally {
-            if (urlConnection != null) {
-                urlConnection.disconnect();
-            }
-        }
     }
 
     public void dump(PrintWriter pw) {
@@ -395,90 +423,37 @@
         pw.println("mWifiInfo: [" + mWifiInfo + "]");
         pw.println("mLinkProperties: [" + mLinkProperties + "]");
         pw.println("mCurrentSignalLevel: [" + mCurrentSignalLevel + "]");
-        pw.println("mArpCheckIntervalMs: [" + mArpCheckIntervalMs+ "]");
-        pw.println("mRssiFetchIntervalMs: [" + mRssiFetchIntervalMs + "]");
-        pw.println("mWalledGardenIntervalMs: [" + mWalledGardenIntervalMs + "]");
-        pw.println("mNumArpPings: [" + mNumArpPings + "]");
-        pw.println("mMinArpResponses: [" + mMinArpResponses + "]");
-        pw.println("mArpPingTimeoutMs: [" + mArpPingTimeoutMs + "]");
         pw.println("mPoorNetworkDetectionEnabled: [" + mPoorNetworkDetectionEnabled + "]");
-        pw.println("mWalledGardenTestEnabled: [" + mWalledGardenTestEnabled + "]");
-        pw.println("mWalledGardenUrl: [" + mWalledGardenUrl + "]");
     }
 
     private boolean isWatchdogEnabled() {
-        boolean ret = getSettingsBoolean(mContentResolver, Settings.Secure.WIFI_WATCHDOG_ON, true);
-        if (DBG) log("watchdog enabled " + ret);
+        boolean ret = getSettingsGlobalBoolean(
+                mContentResolver, Settings.Global.WIFI_WATCHDOG_ON, true);
+        if (DBG) logd("Watchdog enabled " + ret);
         return ret;
     }
 
     private void updateSettings() {
-        if (DBG) log("Updating secure settings");
+        if (DBG) logd("Updating secure settings");
 
-        mArpCheckIntervalMs = Secure.getLong(mContentResolver,
-                Secure.WIFI_WATCHDOG_ARP_CHECK_INTERVAL_MS,
-                DEFAULT_ARP_CHECK_INTERVAL_MS);
-        mRssiFetchIntervalMs = Secure.getLong(mContentResolver,
-                Secure.WIFI_WATCHDOG_RSSI_FETCH_INTERVAL_MS,
-                DEFAULT_RSSI_FETCH_INTERVAL_MS);
-        mNumArpPings = Secure.getInt(mContentResolver,
-                Secure.WIFI_WATCHDOG_NUM_ARP_PINGS,
-                DEFAULT_NUM_ARP_PINGS);
-        mMinArpResponses = Secure.getInt(mContentResolver,
-                Secure.WIFI_WATCHDOG_MIN_ARP_RESPONSES,
-                DEFAULT_MIN_ARP_RESPONSES);
-        mArpPingTimeoutMs = Secure.getInt(mContentResolver,
-                Secure.WIFI_WATCHDOG_ARP_PING_TIMEOUT_MS,
-                DEFAULT_ARP_PING_TIMEOUT_MS);
-        mPoorNetworkDetectionEnabled = getSettingsBoolean(mContentResolver,
-                Settings.Secure.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, true);
-        mWalledGardenTestEnabled = getSettingsBoolean(mContentResolver,
-                Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, true);
-        mWalledGardenUrl = getSettingsStr(mContentResolver,
-                Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL,
-                DEFAULT_WALLED_GARDEN_URL);
-        mWalledGardenIntervalMs = Secure.getLong(mContentResolver,
-                Secure.WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS,
-                DEFAULT_WALLED_GARDEN_INTERVAL_MS);
-    }
-
-    private void setWalledGardenNotificationVisible(boolean visible) {
-        // If it should be hidden and it is already hidden, then noop
-        if (!visible && !mWalledGardenNotificationShown) {
-            return;
-        }
-
-        Resources r = Resources.getSystem();
-        NotificationManager notificationManager = (NotificationManager) mContext
-            .getSystemService(Context.NOTIFICATION_SERVICE);
-
-        if (visible) {
-            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(mWalledGardenUrl));
-            intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
-
-            CharSequence title = r.getString(R.string.wifi_available_sign_in, 0);
-            CharSequence details = r.getString(R.string.wifi_available_sign_in_detailed,
-                    mWifiInfo.getSSID());
-
-            Notification notification = new Notification();
-            notification.when = 0;
-            notification.icon = com.android.internal.R.drawable.stat_notify_wifi_in_range;
-            notification.flags = Notification.FLAG_AUTO_CANCEL;
-            notification.contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
-            notification.tickerText = title;
-            notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);
-
-            notificationManager.notify(WALLED_GARDEN_NOTIFICATION_ID, 1, notification);
+        // disable poor network avoidance
+        if (sWifiOnly) {
+            logd("Disabling poor network avoidance for wi-fi only device");
+            mPoorNetworkDetectionEnabled = false;
         } else {
-            notificationManager.cancel(WALLED_GARDEN_NOTIFICATION_ID, 1);
+            mPoorNetworkDetectionEnabled = getSettingsGlobalBoolean(mContentResolver,
+                    Settings.Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED,
+                    DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED);
         }
-        mWalledGardenNotificationShown = visible;
     }
 
+    /**
+     * Default state, guard for unhandled messages.
+     */
     class DefaultState extends State {
         @Override
         public void enter() {
-            if (DBG) log(getName() + "\n");
+            if (DBG) logd(getName());
         }
 
         @Override
@@ -486,34 +461,41 @@
             switch (msg.what) {
                 case EVENT_WATCHDOG_SETTINGS_CHANGE:
                     updateSettings();
-                    if (DBG) {
-                        log("Updating wifi-watchdog secure settings");
-                    }
+                    if (DBG) logd("Updating wifi-watchdog secure settings");
                     break;
                 case EVENT_RSSI_CHANGE:
                     mCurrentSignalLevel = calculateSignalLevel(msg.arg1);
                     break;
                 case EVENT_WIFI_RADIO_STATE_CHANGE:
                 case EVENT_NETWORK_STATE_CHANGE:
-                case CMD_ARP_CHECK:
-                case CMD_DELAYED_WALLED_GARDEN_CHECK:
+                case EVENT_SUPPLICANT_STATE_CHANGE:
+                case EVENT_BSSID_CHANGE:
                 case CMD_RSSI_FETCH:
-                case RSSI_FETCH_SUCCEEDED:
-                case RSSI_FETCH_FAILED:
-                    //ignore
+                case WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED:
+                case WifiManager.RSSI_PKTCNT_FETCH_FAILED:
+                    // ignore
+                    break;
+                case EVENT_SCREEN_ON:
+                    mIsScreenOn = true;
+                    break;
+                case EVENT_SCREEN_OFF:
+                    mIsScreenOn = false;
                     break;
                 default:
-                    log("Unhandled message " + msg + " in state " + getCurrentState().getName());
+                    loge("Unhandled message " + msg + " in state " + getCurrentState().getName());
                     break;
             }
             return HANDLED;
         }
     }
 
+    /**
+     * WiFi watchdog is disabled by the setting.
+     */
     class WatchdogDisabledState extends State {
         @Override
         public void enter() {
-            if (DBG) log(getName() + "\n");
+            if (DBG) logd(getName());
         }
 
         @Override
@@ -530,8 +512,8 @@
 
                     switch (networkInfo.getDetailedState()) {
                         case VERIFYING_POOR_LINK:
-                            if (DBG) log("Watchdog disabled, verify link");
-                            mWsmChannel.sendMessage(GOOD_LINK_DETECTED);
+                            if (DBG) logd("Watchdog disabled, verify link");
+                            sendLinkStatusNotification(true);
                             break;
                         default:
                             break;
@@ -542,98 +524,103 @@
         }
     }
 
+    /**
+     * WiFi watchdog is enabled by the setting.
+     */
     class WatchdogEnabledState extends State {
         @Override
         public void enter() {
-            if (DBG) log("WifiWatchdogService enabled");
+            if (DBG) logd(getName());
         }
 
         @Override
         public boolean processMessage(Message msg) {
+            Intent intent;
             switch (msg.what) {
                 case EVENT_WATCHDOG_TOGGLED:
                     if (!isWatchdogEnabled())
                         transitionTo(mWatchdogDisabledState);
                     break;
-                case EVENT_NETWORK_STATE_CHANGE:
-                    Intent intent = (Intent) msg.obj;
-                    NetworkInfo networkInfo = (NetworkInfo)
-                            intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
 
-                    if (DBG) log("network state change " + networkInfo.getDetailedState());
+                case EVENT_NETWORK_STATE_CHANGE:
+                    intent = (Intent) msg.obj;
+                    NetworkInfo networkInfo =
+                            (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+                    if (DBG) logd("Network state change " + networkInfo.getDetailedState());
+
+                    mWifiInfo = (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
+                    updateCurrentBssid(mWifiInfo != null ? mWifiInfo.getBSSID() : null);
 
                     switch (networkInfo.getDetailedState()) {
                         case VERIFYING_POOR_LINK:
                             mLinkProperties = (LinkProperties) intent.getParcelableExtra(
                                     WifiManager.EXTRA_LINK_PROPERTIES);
-                            mWifiInfo = (WifiInfo) intent.getParcelableExtra(
-                                    WifiManager.EXTRA_WIFI_INFO);
                             if (mPoorNetworkDetectionEnabled) {
-                                if (mWifiInfo == null) {
-                                    log("Ignoring link verification, mWifiInfo is NULL");
-                                    mWsmChannel.sendMessage(GOOD_LINK_DETECTED);
+                                if (mWifiInfo == null || mCurrentBssid == null) {
+                                    loge("Ignore, wifiinfo " + mWifiInfo +" bssid " + mCurrentBssid);
+                                    sendLinkStatusNotification(true);
                                 } else {
                                     transitionTo(mVerifyingLinkState);
                                 }
                             } else {
-                                mWsmChannel.sendMessage(GOOD_LINK_DETECTED);
+                                sendLinkStatusNotification(true);
                             }
                             break;
                         case CONNECTED:
-                            if (shouldCheckWalledGarden()) {
-                                transitionTo(mWalledGardenCheckState);
-                            } else {
-                                transitionTo(mOnlineWatchState);
-                            }
+                            transitionTo(mOnlineWatchState);
                             break;
                         default:
                             transitionTo(mNotConnectedState);
                             break;
                     }
                     break;
-                case EVENT_WIFI_RADIO_STATE_CHANGE:
-                    if ((Integer) msg.obj == WifiManager.WIFI_STATE_DISABLING) {
-                        if (DBG) log("WifiStateDisabling -- Resetting WatchdogState");
-                        transitionTo(mNotConnectedState);
+
+                case EVENT_SUPPLICANT_STATE_CHANGE:
+                    intent = (Intent) msg.obj;
+                    SupplicantState supplicantState = (SupplicantState) intent.getParcelableExtra(
+                            WifiManager.EXTRA_NEW_STATE);
+                    if (supplicantState == SupplicantState.COMPLETED) {
+                        mWifiInfo = mWifiManager.getConnectionInfo();
+                        updateCurrentBssid(mWifiInfo.getBSSID());
                     }
                     break;
+
+                case EVENT_WIFI_RADIO_STATE_CHANGE:
+                    if ((Integer) msg.obj == WifiManager.WIFI_STATE_DISABLING)
+                        transitionTo(mNotConnectedState);
+                    break;
+
                 default:
                     return NOT_HANDLED;
             }
 
-            setWalledGardenNotificationVisible(false);
             return HANDLED;
         }
-
-        @Override
-        public void exit() {
-            if (DBG) log("WifiWatchdogService disabled");
-        }
     }
 
+    /**
+     * WiFi is disconnected.
+     */
     class NotConnectedState extends State {
         @Override
         public void enter() {
-            if (DBG) log(getName() + "\n");
+            if (DBG) logd(getName());
         }
     }
 
+    /**
+     * WiFi is connected, but waiting for good link detection message.
+     */
     class VerifyingLinkState extends State {
+
+        private int mSampleCount;
+
         @Override
         public void enter() {
-            if (DBG) log(getName() + "\n");
-            //Treat entry as an rssi change
-            handleRssiChange();
-        }
-
-        private void handleRssiChange() {
-            if (mCurrentSignalLevel <= RSSI_LEVEL_MONITOR) {
-                //stay here
-                if (DBG) log("enter VerifyingLinkState, stay level: " + mCurrentSignalLevel);
-            } else {
-                if (DBG) log("enter VerifyingLinkState, arp check level: " + mCurrentSignalLevel);
-                sendMessage(obtainMessage(CMD_ARP_CHECK, ++mArpToken, 0));
-            }
+            if (DBG) logd(getName());
+            mSampleCount = 0;
+            mCurrentBssid.newLinkDetected();
+            sendMessage(obtainMessage(CMD_RSSI_FETCH, ++mRssiFetchToken, 0));
         }
 
         @Override
@@ -642,25 +629,51 @@
                 case EVENT_WATCHDOG_SETTINGS_CHANGE:
                     updateSettings();
                     if (!mPoorNetworkDetectionEnabled) {
-                        mWsmChannel.sendMessage(GOOD_LINK_DETECTED);
+                        sendLinkStatusNotification(true);
                     }
                     break;
-                case EVENT_RSSI_CHANGE:
-                    mCurrentSignalLevel = calculateSignalLevel(msg.arg1);
-                    handleRssiChange();
+
+                case EVENT_BSSID_CHANGE:
+                    transitionTo(mVerifyingLinkState);
                     break;
-                case CMD_ARP_CHECK:
-                    if (msg.arg1 == mArpToken) {
-                        if (doArpTest(FULL_ARP_CHECK) == true) {
-                            if (DBG) log("Notify link is good " + mCurrentSignalLevel);
-                            mWsmChannel.sendMessage(GOOD_LINK_DETECTED);
+
+                case CMD_RSSI_FETCH:
+                    if (msg.arg1 == mRssiFetchToken) {
+                        mWsmChannel.sendMessage(WifiManager.RSSI_PKTCNT_FETCH);
+                        sendMessageDelayed(obtainMessage(CMD_RSSI_FETCH, ++mRssiFetchToken, 0),
+                                LINK_SAMPLING_INTERVAL_MS);
+                    }
+                    break;
+
+                case WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED:
+                    RssiPacketCountInfo info = (RssiPacketCountInfo) msg.obj;
+                    int rssi = info.rssi;
+                    if (DBG) logd("Fetch RSSI succeed, rssi=" + rssi);
+
+                    long time = mCurrentBssid.mBssidAvoidTimeMax - SystemClock.elapsedRealtime();
+                    if (time <= 0) {
+                        // max avoidance time is met
+                        if (DBG) logd("Max avoid time elapsed");
+                        sendLinkStatusNotification(true);
+                    } else {
+                        if (rssi >= mCurrentBssid.mGoodLinkTargetRssi) {
+                            if (++mSampleCount >= mCurrentBssid.mGoodLinkTargetCount) {
+                                // link is good again
+                                if (DBG) logd("Good link detected, rssi=" + rssi);
+                                mCurrentBssid.mBssidAvoidTimeMax = 0;
+                                sendLinkStatusNotification(true);
+                            }
                         } else {
-                            if (DBG) log("Continue ARP check, rssi level: " + mCurrentSignalLevel);
-                            sendMessageDelayed(obtainMessage(CMD_ARP_CHECK, ++mArpToken, 0),
-                                    mArpCheckIntervalMs);
+                            mSampleCount = 0;
+                            if (DBG) logd("Link is still poor, time left=" + time);
                         }
                     }
                     break;
+
+                case WifiManager.RSSI_PKTCNT_FETCH_FAILED:
+                    if (DBG) logd("RSSI_FETCH_FAILED");
+                    break;
+
                 default:
                     return NOT_HANDLED;
             }
@@ -668,19 +681,23 @@
         }
     }
 
+    /**
+     * WiFi is connected and link is verified.
+     */
     class ConnectedState extends State {
         @Override
         public void enter() {
-            if (DBG) log(getName() + "\n");
+            if (DBG) logd(getName());
         }
+
         @Override
         public boolean processMessage(Message msg) {
             switch (msg.what) {
                 case EVENT_WATCHDOG_SETTINGS_CHANGE:
                     updateSettings();
-                    //STOPSHIP: Remove this at ship
+                    // STOPSHIP: Remove this at ship
+                    logd("Updated secure settings and turned debug on");
                     DBG = true;
-                    if (DBG) log("Updated secure settings and turned debug on");
 
                     if (mPoorNetworkDetectionEnabled) {
                         transitionTo(mOnlineWatchState);
@@ -693,40 +710,15 @@
         }
     }
 
-    class WalledGardenCheckState extends State {
-        private int mWalledGardenToken = 0;
-        @Override
-        public void enter() {
-            if (DBG) log(getName() + "\n");
-            sendMessageDelayed(obtainMessage(CMD_DELAYED_WALLED_GARDEN_CHECK,
-                    ++mWalledGardenToken, 0), WALLED_GARDEN_START_DELAY_MS);
-        }
-
-        @Override
-        public boolean processMessage(Message msg) {
-            switch (msg.what) {
-                case CMD_DELAYED_WALLED_GARDEN_CHECK:
-                    if (msg.arg1 == mWalledGardenToken) {
-                        mLastWalledGardenCheckTime = SystemClock.elapsedRealtime();
-                        if (isWalledGardenConnection()) {
-                            if (DBG) log("Walled garden detected");
-                            setWalledGardenNotificationVisible(true);
-                        }
-                        transitionTo(mOnlineWatchState);
-                    }
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            return HANDLED;
-        }
-    }
-
+    /**
+     * RSSI is high enough and don't need link monitoring.
+     */
     class OnlineWatchState extends State {
+        @Override
         public void enter() {
-            if (DBG) log(getName() + "\n");
+            if (DBG) logd(getName());
             if (mPoorNetworkDetectionEnabled) {
-                //Treat entry as an rssi change
+                // treat entry as an rssi change
                 handleRssiChange();
             } else {
                 transitionTo(mOnlineState);
@@ -734,10 +726,10 @@
         }
 
         private void handleRssiChange() {
-            if (mCurrentSignalLevel <= RSSI_LEVEL_MONITOR) {
-                transitionTo(mRssiMonitoringState);
+            if (mCurrentSignalLevel <= LINK_MONITOR_LEVEL_THRESHOLD && mCurrentBssid != null) {
+                transitionTo(mLinkMonitoringState);
             } else {
-                //stay here
+                // stay here
             }
         }
 
@@ -746,16 +738,7 @@
             switch (msg.what) {
                 case EVENT_RSSI_CHANGE:
                     mCurrentSignalLevel = calculateSignalLevel(msg.arg1);
-                    //Ready to avoid bssid again ?
-                    long time = android.os.SystemClock.elapsedRealtime();
-                    if (time - mLastBssidAvoidedTime  > MIN_INTERVAL_AVOID_BSSID_MS[
-                            mMinIntervalArrayIndex]) {
-                        handleRssiChange();
-                    } else {
-                        if (DBG) log("Early to avoid " + mWifiInfo + " time: " + time +
-                                " last avoided: " + mLastBssidAvoidedTime +
-                                " mMinIntervalArrayIndex: " + mMinIntervalArrayIndex);
-                    }
+                    handleRssiChange();
                     break;
                 default:
                     return NOT_HANDLED;
@@ -764,48 +747,110 @@
         }
     }
 
-    class RssiMonitoringState extends State {
+    /**
+     * Keep sampling the link and monitor any poor link situation.
+     */
+    class LinkMonitoringState extends State {
+
+        private int mSampleCount;
+
+        private int mLastRssi;
+        private int mLastTxGood;
+        private int mLastTxBad;
+
+        @Override
         public void enter() {
-            if (DBG) log(getName() + "\n");
+            if (DBG) logd(getName());
+            mSampleCount = 0;
+            mCurrentLoss = new VolumeWeightedEMA(EXP_COEFFICIENT_MONITOR);
             sendMessage(obtainMessage(CMD_RSSI_FETCH, ++mRssiFetchToken, 0));
         }
 
+        @Override
         public boolean processMessage(Message msg) {
             switch (msg.what) {
                 case EVENT_RSSI_CHANGE:
                     mCurrentSignalLevel = calculateSignalLevel(msg.arg1);
-                    if (mCurrentSignalLevel <= RSSI_LEVEL_MONITOR) {
-                        //stay here;
+                    if (mCurrentSignalLevel <= LINK_MONITOR_LEVEL_THRESHOLD) {
+                        // stay here;
                     } else {
-                        //We dont need frequent RSSI monitoring any more
+                        // we don't need frequent RSSI monitoring any more
                         transitionTo(mOnlineWatchState);
                     }
                     break;
+
+                case EVENT_BSSID_CHANGE:
+                    transitionTo(mLinkMonitoringState);
+                    break;
+
                 case CMD_RSSI_FETCH:
-                    if (msg.arg1 == mRssiFetchToken) {
-                        mWsmChannel.sendMessage(RSSI_FETCH);
+                    if (!mIsScreenOn) {
+                        transitionTo(mOnlineState);
+                    } else if (msg.arg1 == mRssiFetchToken) {
+                        mWsmChannel.sendMessage(WifiManager.RSSI_PKTCNT_FETCH);
                         sendMessageDelayed(obtainMessage(CMD_RSSI_FETCH, ++mRssiFetchToken, 0),
-                                mRssiFetchIntervalMs);
+                                LINK_SAMPLING_INTERVAL_MS);
                     }
                     break;
-                case RSSI_FETCH_SUCCEEDED:
-                    int rssi = msg.arg1;
-                    if (DBG) log("RSSI_FETCH_SUCCEEDED: " + rssi);
-                    if (msg.arg1 < RSSI_MONITOR_THRESHOLD) {
-                        mRssiMonitorCount++;
-                    } else {
-                        mRssiMonitorCount = 0;
+
+                case WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED:
+                    RssiPacketCountInfo info = (RssiPacketCountInfo) msg.obj;
+                    int rssi = info.rssi;
+                    int mrssi = (mLastRssi + rssi) / 2;
+                    int txbad = info.txbad;
+                    int txgood = info.txgood;
+                    if (DBG) logd("Fetch RSSI succeed, rssi=" + rssi + " mrssi=" + mrssi + " txbad="
+                            + txbad + " txgood=" + txgood);
+
+                    // skip the first data point as we want incremental values
+                    long now = SystemClock.elapsedRealtime();
+                    if (now - mCurrentBssid.mLastTimeSample < LINK_SAMPLING_INTERVAL_MS * 2) {
+
+                        // update packet loss statistics
+                        int dbad = txbad - mLastTxBad;
+                        int dgood = txgood - mLastTxGood;
+                        int dtotal = dbad + dgood;
+
+                        if (dtotal > 0) {
+                            // calculate packet loss in the last sampling interval
+                            double loss = ((double) dbad) / ((double) dtotal);
+
+                            mCurrentLoss.update(loss, dtotal);
+
+                            if (DBG) {
+                                DecimalFormat df = new DecimalFormat("#.##");
+                                logd("Incremental loss=" + dbad + "/" + dtotal + " Current loss="
+                                        + df.format(mCurrentLoss.mValue * 100) + "% volume="
+                                        + df.format(mCurrentLoss.mVolume));
+                            }
+
+                            mCurrentBssid.updateLoss(mrssi, loss, dtotal);
+
+                            // check for high packet loss and send poor link notification
+                            if (mCurrentLoss.mValue > POOR_LINK_LOSS_THRESHOLD
+                                    && mCurrentLoss.mVolume > POOR_LINK_MIN_VOLUME) {
+                                if (++mSampleCount >= POOR_LINK_SAMPLE_COUNT)
+                                    if (mCurrentBssid.poorLinkDetected(rssi)) {
+                                        sendLinkStatusNotification(false);
+                                        ++mRssiFetchToken;
+                                    }
+                            } else {
+                                mSampleCount = 0;
+                            }
+                        }
                     }
 
-                    if (mRssiMonitorCount > RSSI_MONITOR_COUNT) {
-                        sendPoorLinkDetected();
-                        ++mRssiFetchToken;
-                    }
+                    mCurrentBssid.mLastTimeSample = now;
+                    mLastTxBad = txbad;
+                    mLastTxGood = txgood;
+                    mLastRssi = rssi;
                     break;
-                case RSSI_FETCH_FAILED:
-                    //can happen if we are waiting to get a disconnect notification
-                    if (DBG) log("RSSI_FETCH_FAILED");
+
+                case WifiManager.RSSI_PKTCNT_FETCH_FAILED:
+                    // can happen if we are waiting to get a disconnect notification
+                    if (DBG) logd("RSSI_FETCH_FAILED");
                     break;
+
                 default:
                     return NOT_HANDLED;
             }
@@ -813,164 +858,366 @@
         }
    }
 
-    /* Child state of ConnectedState indicating that we are online
-     * and there is nothing to do
+    /**
+     * Child state of ConnectedState indicating that we are online and there is nothing to do.
      */
     class OnlineState extends State {
         @Override
         public void enter() {
-            if (DBG) log(getName() + "\n");
+            if (DBG) logd(getName());
+        }
+
+        @Override
+        public boolean processMessage(Message msg) {
+            switch (msg.what) {
+                case EVENT_SCREEN_ON:
+                    mIsScreenOn = true;
+                    if (mPoorNetworkDetectionEnabled)
+                        transitionTo(mOnlineWatchState);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
         }
     }
 
-    private boolean shouldCheckWalledGarden() {
-        if (!mWalledGardenTestEnabled) {
-            if (DBG) log("Skipping walled garden check - disabled");
-            return false;
+    private void updateCurrentBssid(String bssid) {
+        if (DBG) logd("Update current BSSID to " + (bssid != null ? bssid : "null"));
+
+        // if currently not connected, then set current BSSID to null
+        if (bssid == null) {
+            if (mCurrentBssid == null) return;
+            mCurrentBssid = null;
+            if (DBG) logd("BSSID changed");
+            sendMessage(EVENT_BSSID_CHANGE);
+            return;
         }
 
-        long waitTime = (mWalledGardenIntervalMs + mLastWalledGardenCheckTime)
-            - SystemClock.elapsedRealtime();
+        // if it is already the current BSSID, then done
+        if (mCurrentBssid != null && bssid.equals(mCurrentBssid.mBssid)) return;
 
-        if (mLastWalledGardenCheckTime != 0 && waitTime > 0) {
-            if (DBG) {
-                log("Skipping walled garden check - wait " +
-                        waitTime + " ms.");
-            }
-            return false;
-        }
-        return true;
-    }
-
-    private boolean doArpTest(int type) {
-        boolean success;
-
-        String iface = mLinkProperties.getInterfaceName();
-        String mac = mWifiInfo.getMacAddress();
-        InetAddress inetAddress = null;
-        InetAddress gateway = null;
-
-        for (LinkAddress la : mLinkProperties.getLinkAddresses()) {
-            inetAddress = la.getAddress();
-            break;
+        // search for the new BSSID in the cache, add to cache if not found
+        mCurrentBssid = mBssidCache.get(bssid);
+        if (mCurrentBssid == null) {
+            mCurrentBssid = new BssidStatistics(bssid);
+            mBssidCache.put(bssid, mCurrentBssid);
         }
 
-        for (RouteInfo route : mLinkProperties.getRoutes()) {
-            gateway = route.getGateway();
-            break;
-        }
-
-        if (DBG) log("ARP " + iface + "addr: " + inetAddress + "mac: " + mac + "gw: " + gateway);
-
-        try {
-            ArpPeer peer = new ArpPeer(iface, inetAddress, mac, gateway);
-            if (type == SINGLE_ARP_CHECK) {
-                success = (peer.doArp(mArpPingTimeoutMs) != null);
-                if (DBG) log("single ARP test result: " + success);
-            } else {
-                int responses = 0;
-                for (int i=0; i < mNumArpPings; i++) {
-                    if(peer.doArp(mArpPingTimeoutMs) != null) responses++;
-                }
-                if (DBG) log("full ARP test result: " + responses + "/" + mNumArpPings);
-                success = (responses >= mMinArpResponses);
-            }
-            peer.close();
-        } catch (SocketException se) {
-            //Consider an Arp socket creation issue as a successful Arp
-            //test to avoid any wifi connectivity issues
-            loge("ARP test initiation failure: " + se);
-            success = true;
-        } catch (IllegalArgumentException ae) {
-            log("ARP test initiation failure: " + ae);
-            success = true;
-        }
-
-        return success;
+        // send BSSID change notification
+        if (DBG) logd("BSSID changed");
+        sendMessage(EVENT_BSSID_CHANGE);
     }
 
     private int calculateSignalLevel(int rssi) {
-        int signalLevel = WifiManager.calculateSignalLevel(rssi,
-                WifiManager.RSSI_LEVELS);
-        if (DBG) log("RSSI current: " + mCurrentSignalLevel + "new: " + rssi + ", " + signalLevel);
+        int signalLevel = WifiManager.calculateSignalLevel(rssi, WifiManager.RSSI_LEVELS);
+        if (DBG)
+            logd("RSSI current: " + mCurrentSignalLevel + " new: " + rssi + ", " + signalLevel);
         return signalLevel;
     }
 
-    private void sendPoorLinkDetected() {
-        if (DBG) log("send POOR_LINK_DETECTED " + mWifiInfo);
-        mWsmChannel.sendMessage(POOR_LINK_DETECTED);
-
-        long time = android.os.SystemClock.elapsedRealtime();
-        if (time - mLastBssidAvoidedTime  > MIN_INTERVAL_AVOID_BSSID_MS[
-                MIN_INTERVAL_AVOID_BSSID_MS.length - 1]) {
-            mMinIntervalArrayIndex = 1;
-            if (DBG) log("set mMinIntervalArrayIndex to 1");
-        } else {
-
-            if (mMinIntervalArrayIndex < MIN_INTERVAL_AVOID_BSSID_MS.length - 1) {
-                mMinIntervalArrayIndex++;
+    private void sendLinkStatusNotification(boolean isGood) {
+        if (DBG) logd("########################################");
+        if (isGood) {
+            mWsmChannel.sendMessage(GOOD_LINK_DETECTED);
+            if (mCurrentBssid != null) {
+                mCurrentBssid.mLastTimeGood = SystemClock.elapsedRealtime();
             }
-            if (DBG) log("mMinIntervalArrayIndex: " + mMinIntervalArrayIndex);
+            if (DBG) logd("Good link notification is sent");
+        } else {
+            mWsmChannel.sendMessage(POOR_LINK_DETECTED);
+            if (mCurrentBssid != null) {
+                mCurrentBssid.mLastTimePoor = SystemClock.elapsedRealtime();
+            }
+            logd("Poor link notification is sent");
         }
-
-        mLastBssidAvoidedTime = android.os.SystemClock.elapsedRealtime();
     }
 
     /**
-     * Convenience function for retrieving a single secure settings value
-     * as a string with a default value.
+     * Convenience function for retrieving a single secure settings value as a
+     * boolean. Note that internally setting values are always stored as
+     * strings; this function converts the string to a boolean for you. The
+     * default value will be returned if the setting is not defined or not a
+     * valid boolean.
      *
      * @param cr The ContentResolver to access.
      * @param name The name of the setting to retrieve.
      * @param def Value to return if the setting is not defined.
-     *
-     * @return The setting's current value, or 'def' if it is not defined
+     * @return The setting's current value, or 'def' if it is not defined or not
+     *         a valid boolean.
      */
-    private static String getSettingsStr(ContentResolver cr, String name, String def) {
-        String v = Settings.Secure.getString(cr, name);
-        return v != null ? v : def;
+    private static boolean getSettingsGlobalBoolean(ContentResolver cr, String name, boolean def) {
+        return Settings.Global.getInt(cr, name, def ? 1 : 0) == 1;
     }
 
     /**
-     * Convenience function for retrieving a single secure settings value
-     * as a boolean.  Note that internally setting values are always
-     * stored as strings; this function converts the string to a boolean
-     * for you.  The default value will be returned if the setting is
-     * not defined or not a valid boolean.
-     *
-     * @param cr The ContentResolver to access.
-     * @param name The name of the setting to retrieve.
-     * @param def Value to return if the setting is not defined.
-     *
-     * @return The setting's current value, or 'def' if it is not defined
-     * or not a valid boolean.
-     */
-    private static boolean getSettingsBoolean(ContentResolver cr, String name, boolean def) {
-        return Settings.Secure.getInt(cr, name, def ? 1 : 0) == 1;
-    }
-
-    /**
-     * Convenience function for updating a single settings value as an
-     * integer. This will either create a new entry in the table if the
-     * given name does not exist, or modify the value of the existing row
-     * with that name.  Note that internally setting values are always
-     * stored as strings, so this function converts the given value to a
-     * string before storing it.
+     * Convenience function for updating a single settings value as an integer.
+     * This will either create a new entry in the table if the given name does
+     * not exist, or modify the value of the existing row with that name. Note
+     * that internally setting values are always stored as strings, so this
+     * function converts the given value to a string before storing it.
      *
      * @param cr The ContentResolver to access.
      * @param name The name of the setting to modify.
      * @param value The new value for the setting.
      * @return true if the value was set, false on database errors
      */
-    private static boolean putSettingsBoolean(ContentResolver cr, String name, boolean value) {
-        return Settings.Secure.putInt(cr, name, value ? 1 : 0);
+    private static boolean putSettingsGlobalBoolean(ContentResolver cr, String name, boolean value) {
+        return Settings.Global.putInt(cr, name, value ? 1 : 0);
     }
 
-    private static void log(String s) {
+    private static void logd(String s) {
         Log.d(TAG, s);
     }
 
     private static void loge(String s) {
         Log.e(TAG, s);
     }
+
+    /**
+     * Bundle of good link count parameters
+     */
+    private static class GoodLinkTarget {
+        public final int RSSI_ADJ_DBM;
+        public final int SAMPLE_COUNT;
+        public final int REDUCE_TIME_MS;
+        public GoodLinkTarget(int adj, int count, int time) {
+            RSSI_ADJ_DBM = adj;
+            SAMPLE_COUNT = count;
+            REDUCE_TIME_MS = time;
+        }
+    }
+
+    /**
+     * Bundle of max avoidance time parameters
+     */
+    private static class MaxAvoidTime {
+        public final int TIME_MS;
+        public final int MIN_RSSI_DBM;
+        public MaxAvoidTime(int time, int rssi) {
+            TIME_MS = time;
+            MIN_RSSI_DBM = rssi;
+        }
+    }
+
+    /**
+     * Volume-weighted Exponential Moving Average (V-EMA)
+     *    - volume-weighted:  each update has its own weight (number of packets)
+     *    - exponential:      O(1) time and O(1) space for both update and query
+     *    - moving average:   reflect most recent results and expire old ones
+     */
+    private class VolumeWeightedEMA {
+        private double mValue;
+        private double mVolume;
+        private double mProduct;
+        private final double mAlpha;
+
+        public VolumeWeightedEMA(double coefficient) {
+            mValue   = 0.0;
+            mVolume  = 0.0;
+            mProduct = 0.0;
+            mAlpha   = coefficient;
+        }
+
+        public void update(double newValue, int newVolume) {
+            if (newVolume <= 0) return;
+            // core update formulas
+            double newProduct = newValue * newVolume;
+            mProduct = mAlpha * newProduct + (1 - mAlpha) * mProduct;
+            mVolume  = mAlpha * newVolume  + (1 - mAlpha) * mVolume;
+            mValue   = mProduct / mVolume;
+        }
+    }
+
+    /**
+     * Record (RSSI -> pakce loss %) mappings of one BSSID
+     */
+    private class BssidStatistics {
+
+        /* MAC address of this BSSID */
+        private final String mBssid;
+
+        /* RSSI -> packet loss % mappings */
+        private VolumeWeightedEMA[] mEntries;
+        private int mRssiBase;
+        private int mEntriesSize;
+
+        /* Target to send good link notification, set when poor link is detected */
+        private int mGoodLinkTargetRssi;
+        private int mGoodLinkTargetCount;
+
+        /* Index of GOOD_LINK_TARGET array */
+        private int mGoodLinkTargetIndex;
+
+        /* Timestamps of some last events */
+        private long mLastTimeSample;
+        private long mLastTimeGood;
+        private long mLastTimePoor;
+
+        /* Max time to avoid this BSSID */
+        private long mBssidAvoidTimeMax;
+
+        /**
+         * Constructor
+         *
+         * @param bssid is the address of this BSSID
+         */
+        public BssidStatistics(String bssid) {
+            this.mBssid = bssid;
+            mRssiBase = BSSID_STAT_RANGE_LOW_DBM;
+            mEntriesSize = BSSID_STAT_RANGE_HIGH_DBM - BSSID_STAT_RANGE_LOW_DBM + 1;
+            mEntries = new VolumeWeightedEMA[mEntriesSize];
+            for (int i = 0; i < mEntriesSize; i++)
+                mEntries[i] = new VolumeWeightedEMA(EXP_COEFFICIENT_RECORD);
+        }
+
+        /**
+         * Update this BSSID cache
+         *
+         * @param rssi is the RSSI
+         * @param value is the new instant loss value at this RSSI
+         * @param volume is the volume for this single update
+         */
+        public void updateLoss(int rssi, double value, int volume) {
+            if (volume <= 0) return;
+            int index = rssi - mRssiBase;
+            if (index < 0 || index >= mEntriesSize) return;
+            mEntries[index].update(value, volume);
+            if (DBG) {
+                DecimalFormat df = new DecimalFormat("#.##");
+                logd("Cache updated: loss[" + rssi + "]=" + df.format(mEntries[index].mValue * 100)
+                        + "% volume=" + df.format(mEntries[index].mVolume));
+            }
+        }
+
+        /**
+         * Get preset loss if the cache has insufficient data, observed from experiments.
+         *
+         * @param rssi is the input RSSI
+         * @return preset loss of the given RSSI
+         */
+        public double presetLoss(int rssi) {
+            if (rssi <= -90) return 1.0;
+            if (rssi > 0) return 0.0;
+
+            if (sPresetLoss == null) {
+                // pre-calculate all preset losses only once, then reuse them
+                final int size = 90;
+                sPresetLoss = new double[size];
+                for (int i = 0; i < size; i++) sPresetLoss[i] = 1.0 / Math.pow(90 - i, 1.5);
+            }
+            return sPresetLoss[-rssi];
+        }
+
+        /**
+         * A poor link is detected, calculate a target RSSI to bring WiFi back.
+         *
+         * @param rssi is the current RSSI
+         * @return true iff the current BSSID should be avoided
+         */
+        public boolean poorLinkDetected(int rssi) {
+            if (DBG) logd("Poor link detected, rssi=" + rssi);
+
+            long now = SystemClock.elapsedRealtime();
+            long lastGood = now - mLastTimeGood;
+            long lastPoor = now - mLastTimePoor;
+
+            // reduce the difficulty of good link target if last avoidance was long time ago
+            while (mGoodLinkTargetIndex > 0
+                    && lastPoor >= GOOD_LINK_TARGET[mGoodLinkTargetIndex - 1].REDUCE_TIME_MS)
+                mGoodLinkTargetIndex--;
+            mGoodLinkTargetCount = GOOD_LINK_TARGET[mGoodLinkTargetIndex].SAMPLE_COUNT;
+
+            // scan for a target RSSI at which the link is good
+            int from = rssi + GOOD_LINK_RSSI_RANGE_MIN;
+            int to = rssi + GOOD_LINK_RSSI_RANGE_MAX;
+            mGoodLinkTargetRssi = findRssiTarget(from, to, GOOD_LINK_LOSS_THRESHOLD);
+            mGoodLinkTargetRssi += GOOD_LINK_TARGET[mGoodLinkTargetIndex].RSSI_ADJ_DBM;
+            if (mGoodLinkTargetIndex < GOOD_LINK_TARGET.length - 1) mGoodLinkTargetIndex++;
+
+            // calculate max avoidance time to prevent avoiding forever
+            int p = 0, pmax = MAX_AVOID_TIME.length - 1;
+            while (p < pmax && rssi >= MAX_AVOID_TIME[p + 1].MIN_RSSI_DBM) p++;
+            long avoidMax = MAX_AVOID_TIME[p].TIME_MS;
+
+            // don't avoid if max avoidance time is 0 (RSSI is super high)
+            if (avoidMax <= 0) return false;
+
+            // set max avoidance time, send poor link notification
+            mBssidAvoidTimeMax = now + avoidMax;
+
+            if (DBG) logd("goodRssi=" + mGoodLinkTargetRssi + " goodCount=" + mGoodLinkTargetCount
+                    + " lastGood=" + lastGood + " lastPoor=" + lastPoor + " avoidMax=" + avoidMax);
+
+            return true;
+        }
+
+        /**
+         * A new BSSID is connected, recalculate target RSSI threshold
+         */
+        public void newLinkDetected() {
+            // if this BSSID is currently being avoided, the reuse those values
+            if (mBssidAvoidTimeMax > 0) {
+                if (DBG) logd("Previous avoidance still in effect, rssi=" + mGoodLinkTargetRssi
+                        + " count=" + mGoodLinkTargetCount);
+                return;
+            }
+
+            // calculate a new RSSI threshold for new link verifying
+            int from = BSSID_STAT_RANGE_LOW_DBM;
+            int to = BSSID_STAT_RANGE_HIGH_DBM;
+            mGoodLinkTargetRssi = findRssiTarget(from, to, GOOD_LINK_LOSS_THRESHOLD);
+            mGoodLinkTargetCount = 1;
+            mBssidAvoidTimeMax = SystemClock.elapsedRealtime() + MAX_AVOID_TIME[0].TIME_MS;
+            if (DBG) logd("New link verifying target set, rssi=" + mGoodLinkTargetRssi + " count="
+                    + mGoodLinkTargetCount);
+        }
+
+        /**
+         * Return the first RSSI within the range where loss[rssi] < threshold
+         *
+         * @param from start scanning from this RSSI
+         * @param to stop scanning at this RSSI
+         * @param threshold target threshold for scanning
+         * @return target RSSI
+         */
+        public int findRssiTarget(int from, int to, double threshold) {
+            from -= mRssiBase;
+            to -= mRssiBase;
+            int emptyCount = 0;
+            int d = from < to ? 1 : -1;
+            for (int i = from; i != to; i += d)
+                // don't use a data point if it volume is too small (statistically unreliable)
+                if (i >= 0 && i < mEntriesSize && mEntries[i].mVolume > 1.0) {
+                    emptyCount = 0;
+                    if (mEntries[i].mValue < threshold) {
+                        // scan target found
+                        int rssi = mRssiBase + i;
+                        if (DBG) {
+                            DecimalFormat df = new DecimalFormat("#.##");
+                            logd("Scan target found: rssi=" + rssi + " threshold="
+                                    + df.format(threshold * 100) + "% value="
+                                    + df.format(mEntries[i].mValue * 100) + "% volume="
+                                    + df.format(mEntries[i].mVolume));
+                        }
+                        return rssi;
+                    }
+                } else if (++emptyCount >= BSSID_STAT_EMPTY_COUNT) {
+                    // cache has insufficient data around this RSSI, use preset loss instead
+                    int rssi = mRssiBase + i;
+                    double lossPreset = presetLoss(rssi);
+                    if (lossPreset < threshold) {
+                        if (DBG) {
+                            DecimalFormat df = new DecimalFormat("#.##");
+                            logd("Scan target found: rssi=" + rssi + " threshold="
+                                    + df.format(threshold * 100) + "% value="
+                                    + df.format(lossPreset * 100) + "% volume=preset");
+                        }
+                        return rssi;
+                    }
+                }
+
+            return mRssiBase + to;
+        }
+    }
 }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index 100e062..b1501ed 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -37,6 +37,11 @@
      */
     public WpsInfo wps;
 
+    /** @hide */
+    public static final int MAX_GROUP_OWNER_INTENT   =   15;
+    /** @hide */
+    public static final int MIN_GROUP_OWNER_INTENT   =   0;
+
     /**
      * This is an integer value between 0 and 15 where 0 indicates the least
      * inclination to be a group owner and 15 indicates the highest inclination
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
index c86ec8b..7d71539 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
@@ -107,12 +107,14 @@
     /** Device connection status */
     public int status = UNAVAILABLE;
 
-    /** Detailed device string pattern
+    /** @hide */
+    public WifiP2pWfdInfo wfdInfo;
+
+    /** Detailed device string pattern with WFD info
      * Example:
-     *  P2P-DEVICE-FOUND fa:7b:7a:42:02:13 p2p_dev_addr=fa:7b:7a:42:02:13
-     *  pri_dev_type=1-0050F204-1 name='p2p-TEST1' config_methods=0x188 dev_capab=0x27
-     *  group_capab=0x0
-     *
+     *  P2P-DEVICE-FOUND 00:18:6b:de:a3:6e p2p_dev_addr=00:18:6b:de:a3:6e
+     *  pri_dev_type=1-0050F204-1 name='DWD-300-DEA36E' config_methods=0x188
+     *  dev_capab=0x21 group_capab=0x9
      */
     private static final Pattern detailedDevicePattern = Pattern.compile(
         "((?:[0-9a-f]{2}:){5}[0-9a-f]{2}) " +
@@ -122,7 +124,8 @@
         "name='(.*)' " +
         "config_methods=(0x[0-9a-fA-F]+) " +
         "dev_capab=(0x[0-9a-fA-F]+) " +
-        "group_capab=(0x[0-9a-fA-F]+)"
+        "group_capab=(0x[0-9a-fA-F]+)" +
+        "( wfd_dev_info=0x000006([0-9a-fA-F]{12}))?"
     );
 
     /** 2 token device address pattern
@@ -151,7 +154,7 @@
      * @param string formats supported include
      *  P2P-DEVICE-FOUND fa:7b:7a:42:02:13 p2p_dev_addr=fa:7b:7a:42:02:13
      *  pri_dev_type=1-0050F204-1 name='p2p-TEST1' config_methods=0x188 dev_capab=0x27
-     *  group_capab=0x0
+     *  group_capab=0x0 wfd_dev_info=000006015d022a0032
      *
      *  P2P-DEVICE-LOST p2p_dev_addr=fa:7b:7a:42:02:13
      *
@@ -203,6 +206,12 @@
                 wpsConfigMethodsSupported = parseHex(match.group(6));
                 deviceCapability = parseHex(match.group(7));
                 groupCapability = parseHex(match.group(8));
+                if (match.group(9) != null) {
+                    String str = match.group(10);
+                    wfdInfo = new WifiP2pWfdInfo(parseHex(str.substring(0,4)),
+                            parseHex(str.substring(4,8)),
+                            parseHex(str.substring(8,12)));
+                }
                 break;
         }
 
@@ -251,6 +260,18 @@
         return (groupCapability & GROUP_CAPAB_GROUP_LIMIT) != 0;
     }
 
+    /** @hide */
+    public void update(WifiP2pDevice device) {
+        if (device == null || device.deviceAddress == null) return;
+        deviceName = device.deviceName;
+        primaryDeviceType = device.primaryDeviceType;
+        secondaryDeviceType = device.secondaryDeviceType;
+        wpsConfigMethodsSupported = device.wpsConfigMethodsSupported;
+        deviceCapability = device.deviceCapability;
+        groupCapability = device.groupCapability;
+        wfdInfo = device.wfdInfo;
+    }
+
     @Override
     public boolean equals(Object obj) {
         if (this == obj) return true;
@@ -273,6 +294,7 @@
         sbuf.append("\n grpcapab: ").append(groupCapability);
         sbuf.append("\n devcapab: ").append(deviceCapability);
         sbuf.append("\n status: ").append(status);
+        sbuf.append("\n wfdInfo: ").append(wfdInfo);
         return sbuf.toString();
     }
 
@@ -292,6 +314,7 @@
             deviceCapability = source.deviceCapability;
             groupCapability = source.groupCapability;
             status = source.status;
+            wfdInfo = source.wfdInfo;
         }
     }
 
@@ -305,6 +328,12 @@
         dest.writeInt(deviceCapability);
         dest.writeInt(groupCapability);
         dest.writeInt(status);
+        if (wfdInfo != null) {
+            dest.writeInt(1);
+            wfdInfo.writeToParcel(dest, flags);
+        } else {
+            dest.writeInt(0);
+        }
     }
 
     /** Implement the Parcelable interface */
@@ -320,6 +349,9 @@
                 device.deviceCapability = in.readInt();
                 device.groupCapability = in.readInt();
                 device.status = in.readInt();
+                if (in.readInt() == 1) {
+                    device.wfdInfo = WifiP2pWfdInfo.CREATOR.createFromParcel(in);
+                }
                 return device;
             }
 
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
index 48cdbc2..f14c305 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
@@ -35,10 +35,9 @@
  */
 public class WifiP2pDeviceList implements Parcelable {
 
-    private HashMap<String, WifiP2pDevice> mDevices;
+    private final HashMap<String, WifiP2pDevice> mDevices = new HashMap<String, WifiP2pDevice>();
 
     public WifiP2pDeviceList() {
-        mDevices = new HashMap<String, WifiP2pDevice>();
     }
 
     /** copy constructor */
@@ -52,7 +51,6 @@
 
     /** @hide */
     public WifiP2pDeviceList(ArrayList<WifiP2pDevice> devices) {
-        mDevices = new HashMap<String, WifiP2pDevice>();
         for (WifiP2pDevice device : devices) {
             if (device.deviceAddress != null) {
                 mDevices.put(device.deviceAddress, device);
@@ -78,6 +76,7 @@
             d.wpsConfigMethodsSupported = device.wpsConfigMethodsSupported;
             d.deviceCapability = device.deviceCapability;
             d.groupCapability = device.groupCapability;
+            d.wfdInfo = device.wfdInfo;
             return;
         }
         //Not found, add a new one
@@ -115,6 +114,15 @@
         return mDevices.remove(device.deviceAddress) != null;
     }
 
+    /** Returns true if any device the list was removed @hide */
+    public boolean remove(WifiP2pDeviceList list) {
+        boolean ret = false;
+        for (WifiP2pDevice d : list.mDevices.values()) {
+            if (remove(d)) ret = true;
+        }
+        return ret;
+    }
+
     /** Get the list of devices */
     public Collection<WifiP2pDevice> getDeviceList() {
         return Collections.unmodifiableCollection(mDevices.values());
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
index bc492b3..cf7604d 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
@@ -68,7 +68,7 @@
         "ssid=\"(.+)\" " +
         "freq=(\\d+) " +
         "(?:psk=)?([0-9a-fA-F]{64})?" +
-        "(?:passphrase=)?(?:\"(.{8,63})\")? " +
+        "(?:passphrase=)?(?:\"(.{0,63})\")? " +
         "go_dev_addr=((?:[0-9a-f]{2}:){5}[0-9a-f]{2})" +
         " ?(\\[PERSISTENT\\])?"
     );
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
index 3459a5a..98f0972 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
@@ -16,6 +16,7 @@
 package android.net.wifi.p2p;
 
 import java.util.Collection;
+import java.util.Map;
 
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -32,8 +33,9 @@
 
     private static final int CREDENTIAL_MAX_NUM             =   32;
 
-    private LruCache<Integer, WifiP2pGroup> mGroups;
-    private GroupDeleteListener mListener;
+    private final LruCache<Integer, WifiP2pGroup> mGroups;
+    private final GroupDeleteListener mListener;
+
     private boolean isClearCalled = false;
 
     public interface GroupDeleteListener {
@@ -41,10 +43,10 @@
     }
 
     WifiP2pGroupList() {
-        this(null);
+        this(null, null);
     }
 
-    WifiP2pGroupList(GroupDeleteListener listener) {
+    WifiP2pGroupList(WifiP2pGroupList source, GroupDeleteListener listener) {
         mListener = listener;
         mGroups = new LruCache<Integer, WifiP2pGroup>(CREDENTIAL_MAX_NUM) {
             @Override
@@ -55,6 +57,12 @@
                 }
             }
         };
+
+        if (source != null) {
+            for (Map.Entry<Integer, WifiP2pGroup> item : source.mGroups.snapshot().entrySet()) {
+                mGroups.put(item.getKey(), item.getValue());
+            }
+        }
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java b/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java
index dce315a..8972b7e 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java
@@ -44,8 +44,8 @@
     public String toString() {
         StringBuffer sbuf = new StringBuffer();
         sbuf.append("groupFormed: ").append(groupFormed)
-            .append("isGroupOwner: ").append(isGroupOwner)
-            .append("groupOwnerAddress: ").append(groupOwnerAddress);
+            .append(" isGroupOwner: ").append(isGroupOwner)
+            .append(" groupOwnerAddress: ").append(groupOwnerAddress);
         return sbuf.toString();
     }
 
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 96d3a7f..6edc232 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -455,6 +455,13 @@
     /** @hide */
     public static final int RESPONSE_PERSISTENT_GROUP_INFO          = BASE + 63;
 
+    /** @hide */
+    public static final int SET_WFD_INFO                            = BASE + 64;
+    /** @hide */
+    public static final int SET_WFD_INFO_FAILED                     = BASE + 65;
+    /** @hide */
+    public static final int SET_WFD_INFO_SUCCEEDED                  = BASE + 66;
+
     /**
      * Create a new WifiP2pManager instance. Applications use
      * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
@@ -742,6 +749,7 @@
                     case WifiP2pManager.CLEAR_SERVICE_REQUESTS_FAILED:
                     case WifiP2pManager.SET_DEVICE_NAME_FAILED:
                     case WifiP2pManager.DELETE_PERSISTENT_GROUP_FAILED:
+                    case WifiP2pManager.SET_WFD_INFO_FAILED:
                         if (listener != null) {
                             ((ActionListener) listener).onFailure(message.arg1);
                         }
@@ -762,6 +770,7 @@
                     case WifiP2pManager.CLEAR_SERVICE_REQUESTS_SUCCEEDED:
                     case WifiP2pManager.SET_DEVICE_NAME_SUCCEEDED:
                     case WifiP2pManager.DELETE_PERSISTENT_GROUP_SUCCEEDED:
+                    case WifiP2pManager.SET_WFD_INFO_SUCCEEDED:
                         if (listener != null) {
                             ((ActionListener) listener).onSuccess();
                         }
@@ -1297,6 +1306,13 @@
         c.mAsyncChannel.sendMessage(SET_DEVICE_NAME, 0, c.putListener(listener), d);
     }
 
+    /** @hide */
+    public void setWFDInfo(
+            Channel c, WifiP2pWfdInfo wfdInfo,
+            ActionListener listener) {
+        checkChannel(c);
+        c.mAsyncChannel.sendMessage(SET_WFD_INFO, 0, c.putListener(listener), wfdInfo);
+    }
 
     /**
      * Set dialog listener to over-ride system dialogs on p2p events. This function
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 0be2b27..039319d 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -62,6 +62,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.os.Parcelable.Creator;
 import android.provider.Settings;
 import android.text.TextUtils;
@@ -122,6 +123,9 @@
     private static final Boolean TRY_REINVOCATION = true;;
     private static final Boolean NO_REINVOCATION = false;
 
+    private static final Boolean RELOAD = true;
+    private static final Boolean NO_RELOAD = false;
+
     private static final int CONNECT_FAILURE = -1;
     private static final int CONNECT_SUCCESS = 0;
     private static final int NEEDS_PROVISION_REQ = 1;
@@ -130,23 +134,14 @@
     private static final int GROUP_CREATING_WAIT_TIME_MS = 120 * 1000;
     private static int mGroupCreatingTimeoutIndex = 0;
 
+    private static final int DISABLE_P2P_WAIT_TIME_MS = 5 * 1000;
+    private static int mDisableP2pTimeoutIndex = 0;
+
     /* Set a two minute discover timeout to avoid STA scans from being blocked */
     private static final int DISCOVER_TIMEOUT_S = 120;
 
     /* Idle time after a peer is gone when the group is torn down */
-    private static final int GROUP_IDLE_TIME_S = 2;
-
-    /**
-     * Delay between restarts upon failure to setup connection with supplicant
-     */
-    private static final int P2P_RESTART_INTERVAL_MSECS = 5000;
-
-    /**
-     * Number of times we attempt to restart p2p
-     */
-    private static final int P2P_RESTART_TRIES = 5;
-
-    private int mP2pRestartCount = 0;
+    private static final int GROUP_IDLE_TIME_S = 10;
 
     private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
 
@@ -157,6 +152,30 @@
     private static final int PEER_CONNECTION_USER_ACCEPT    =   BASE + 2;
     /* User rejected a peer request */
     private static final int PEER_CONNECTION_USER_REJECT    =   BASE + 3;
+    /* User wants to disconnect wifi in favour of p2p */
+    private static final int DROP_WIFI_USER_ACCEPT          =   BASE + 4;
+    /* User wants to keep his wifi connection and drop p2p */
+    private static final int DROP_WIFI_USER_REJECT          =   BASE + 5;
+    /* Delayed message to timeout p2p disable */
+    public static final int DISABLE_P2P_TIMED_OUT           =   BASE + 6;
+
+
+    /* Commands to the WifiStateMachine */
+    public static final int P2P_CONNECTION_CHANGED          =   BASE + 11;
+
+    /* These commands are used to tempoarily disconnect wifi when we detect
+     * a frequency conflict which would make it impossible to have with p2p
+     * and wifi active at the same time.
+     *
+     * If the user chooses to disable wifi tempoarily, we keep wifi disconnected
+     * until the p2p connection is done and terminated at which point we will
+     * bring back wifi up
+     *
+     * DISCONNECT_WIFI_REQUEST
+     *      msg.arg1 = 1 enables temporary disconnect and 0 disables it.
+     */
+    public static final int DISCONNECT_WIFI_REQUEST         =   BASE + 12;
+    public static final int DISCONNECT_WIFI_RESPONSE        =   BASE + 13;
 
     private final boolean mP2pSupported;
 
@@ -177,6 +196,8 @@
 
     private NetworkInfo mNetworkInfo;
 
+    private boolean mTempoarilyDisconnectedWifi = false;
+
     /* The transaction Id of service discovery request */
     private byte mServiceTransactionId = 0;
 
@@ -227,7 +248,7 @@
         PREVIOUS_PROTOCOL_ERROR,
 
         /* There is no common channels the both devices can use. */
-        NO_COMMON_CHANNE,
+        NO_COMMON_CHANNEL,
 
         /* Unknown p2p group. For example, Device A tries to invoke the previous persistent group,
          *  but device B has removed the specified credential already. */
@@ -262,7 +283,7 @@
             case 6:
                 return PREVIOUS_PROTOCOL_ERROR;
             case 7:
-                return NO_COMMON_CHANNE;
+                return NO_COMMON_CHANNEL;
             case 8:
                 return UNKNOWN_P2P_GROUP;
             case 9:
@@ -351,15 +372,26 @@
                 = new UserAuthorizingInvitationState();
         private ProvisionDiscoveryState mProvisionDiscoveryState = new ProvisionDiscoveryState();
         private GroupNegotiationState mGroupNegotiationState = new GroupNegotiationState();
+        private FrequencyConflictState mFrequencyConflictState =new FrequencyConflictState();
 
         private GroupCreatedState mGroupCreatedState = new GroupCreatedState();
         private UserAuthorizingJoinState mUserAuthorizingJoinState = new UserAuthorizingJoinState();
+        private OngoingGroupRemovalState mOngoingGroupRemovalState = new OngoingGroupRemovalState();
 
         private WifiNative mWifiNative = new WifiNative(mInterface);
         private WifiMonitor mWifiMonitor = new WifiMonitor(this, mWifiNative);
 
-        private WifiP2pDeviceList mPeers = new WifiP2pDeviceList();
-        private WifiP2pGroupList mGroups = new WifiP2pGroupList(
+        private final WifiP2pDeviceList mPeers = new WifiP2pDeviceList();
+        /* During a connection, supplicant can tell us that a device was lost. From a supplicant's
+         * perspective, the discovery stops during connection and it purges device since it does
+         * not get latest updates about the device without being in discovery state.
+         *
+         * From the framework perspective, the device is still there since we are connecting or
+         * connected to it. so we keep these devices in a seperate list, so that they are removed
+         * when connection is cancelled or lost
+         */
+        private final WifiP2pDeviceList mPeersLostDuringConnection = new WifiP2pDeviceList();
+        private final WifiP2pGroupList mGroups = new WifiP2pGroupList(null,
                 new GroupDeleteListener() {
             @Override
             public void onDeleteGroup(int netId) {
@@ -369,7 +401,7 @@
                 sendP2pPersistentGroupsChangedBroadcast();
             }
         });
-        private WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
+        private final WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
         private WifiP2pGroup mGroup;
 
         // Saved WifiP2pConfig for a peer connection
@@ -395,8 +427,10 @@
                         addState(mUserAuthorizingInvitationState, mGroupCreatingState);
                         addState(mProvisionDiscoveryState, mGroupCreatingState);
                         addState(mGroupNegotiationState, mGroupCreatingState);
+                        addState(mFrequencyConflictState, mGroupCreatingState);
                     addState(mGroupCreatedState, mP2pEnabledState);
                         addState(mUserAuthorizingJoinState, mGroupCreatedState);
+                        addState(mOngoingGroupRemovalState, mGroupCreatedState);
 
             if (p2pSupported) {
                 setInitialState(mP2pDisabledState);
@@ -495,18 +529,25 @@
                     replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP,
                             WifiP2pManager.BUSY);
                     break;
+                case WifiP2pManager.SET_WFD_INFO:
+                    replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED,
+                            WifiP2pManager.BUSY);
+                    break;
                 case WifiP2pManager.REQUEST_PEERS:
-                    replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, mPeers);
+                    replyToMessage(message, WifiP2pManager.RESPONSE_PEERS,
+                            new WifiP2pDeviceList(mPeers));
                     break;
                 case WifiP2pManager.REQUEST_CONNECTION_INFO:
-                    replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO, mWifiP2pInfo);
+                    replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO,
+                            new WifiP2pInfo(mWifiP2pInfo));
                     break;
                 case WifiP2pManager.REQUEST_GROUP_INFO:
-                    replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, mGroup);
+                    replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO,
+                            mGroup != null ? new WifiP2pGroup(mGroup) : null);
                     break;
                 case WifiP2pManager.REQUEST_PERSISTENT_GROUP_INFO:
                     replyToMessage(message, WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO,
-                            mGroups);
+                            new WifiP2pGroupList(mGroups, null));
                     break;
                 case WifiP2pManager.SET_DIALOG_LISTENER:
                     String appPkgName = (String)message.getData().getString(
@@ -528,16 +569,34 @@
                 case WifiMonitor.NETWORK_CONNECTION_EVENT:
                 case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
                 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
+                case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
+                case WifiMonitor.WPS_SUCCESS_EVENT:
+                case WifiMonitor.WPS_FAIL_EVENT:
+                case WifiMonitor.WPS_OVERLAP_EVENT:
+                case WifiMonitor.WPS_TIMEOUT_EVENT:
                 case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
                 case WifiMonitor.P2P_DEVICE_FOUND_EVENT:
                 case WifiMonitor.P2P_DEVICE_LOST_EVENT:
                 case WifiMonitor.P2P_FIND_STOPPED_EVENT:
                 case WifiMonitor.P2P_SERV_DISC_RESP_EVENT:
-                case WifiStateMachine.CMD_ENABLE_P2P:
-                case WifiStateMachine.CMD_DISABLE_P2P:
                 case PEER_CONNECTION_USER_ACCEPT:
                 case PEER_CONNECTION_USER_REJECT:
+                case DISCONNECT_WIFI_RESPONSE:
+                case DROP_WIFI_USER_ACCEPT:
+                case DROP_WIFI_USER_REJECT:
                 case GROUP_CREATING_TIMED_OUT:
+                case DISABLE_P2P_TIMED_OUT:
+                case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
+                case DhcpStateMachine.CMD_POST_DHCP_ACTION:
+                case DhcpStateMachine.CMD_ON_QUIT:
+                case WifiMonitor.P2P_PROV_DISC_FAILURE_EVENT:
+                    break;
+                case WifiStateMachine.CMD_ENABLE_P2P:
+                    // Enable is lazy and has no response
+                    break;
+                case WifiStateMachine.CMD_DISABLE_P2P_REQ:
+                    // If we end up handling in default, p2p is not enabled
+                    mWifiChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_RSP);
                     break;
                     /* unexpected group created, remove */
                 case WifiMonitor.P2P_GROUP_STARTED_EVENT:
@@ -628,6 +687,10 @@
                     replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP,
                             WifiP2pManager.P2P_UNSUPPORTED);
                     break;
+                case WifiP2pManager.SET_WFD_INFO:
+                    replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED,
+                            WifiP2pManager.P2P_UNSUPPORTED);
+                    break;
                default:
                     return NOT_HANDLED;
             }
@@ -637,6 +700,13 @@
 
     class P2pDisablingState extends State {
         @Override
+        public void enter() {
+            if (DBG) logd(getName());
+            sendMessageDelayed(obtainMessage(DISABLE_P2P_TIMED_OUT,
+                    ++mDisableP2pTimeoutIndex, 0), DISABLE_P2P_WAIT_TIME_MS);
+        }
+
+        @Override
         public boolean processMessage(Message message) {
             if (DBG) logd(getName() + message.toString());
             switch (message.what) {
@@ -645,14 +715,25 @@
                     transitionTo(mP2pDisabledState);
                     break;
                 case WifiStateMachine.CMD_ENABLE_P2P:
-                case WifiStateMachine.CMD_DISABLE_P2P:
+                case WifiStateMachine.CMD_DISABLE_P2P_REQ:
                     deferMessage(message);
                     break;
+                case DISABLE_P2P_TIMED_OUT:
+                    if (mGroupCreatingTimeoutIndex == message.arg1) {
+                        loge("P2p disable timed out");
+                        transitionTo(mP2pDisabledState);
+                    }
+                    break;
                 default:
                     return NOT_HANDLED;
             }
             return HANDLED;
         }
+
+        @Override
+        public void exit() {
+            mWifiChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_RSP);
+        }
     }
 
     class P2pDisabledState extends State {
@@ -676,9 +757,6 @@
                     mWifiMonitor.startMonitoring();
                     transitionTo(mP2pEnablingState);
                     break;
-                case WifiStateMachine.CMD_DISABLE_P2P:
-                    //Nothing to do
-                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -705,7 +783,7 @@
                     transitionTo(mP2pDisabledState);
                     break;
                 case WifiStateMachine.CMD_ENABLE_P2P:
-                case WifiStateMachine.CMD_DISABLE_P2P:
+                case WifiStateMachine.CMD_DISABLE_P2P_REQ:
                     deferMessage(message);
                     break;
                 default:
@@ -729,10 +807,14 @@
         public boolean processMessage(Message message) {
             if (DBG) logd(getName() + message.toString());
             switch (message.what) {
+                case WifiMonitor.SUP_DISCONNECTION_EVENT:
+                    loge("Unexpected loss of p2p socket connection");
+                    transitionTo(mP2pDisabledState);
+                    break;
                 case WifiStateMachine.CMD_ENABLE_P2P:
                     //Nothing to do
                     break;
-                case WifiStateMachine.CMD_DISABLE_P2P:
+                case WifiStateMachine.CMD_DISABLE_P2P_REQ:
                     if (mPeers.clear()) sendP2pPeersChangedBroadcast();
                     if (mGroups.clear()) sendP2pPersistentGroupsChangedBroadcast();
 
@@ -740,6 +822,7 @@
                     transitionTo(mP2pDisablingState);
                     break;
                 case WifiP2pManager.SET_DEVICE_NAME:
+                {
                     WifiP2pDevice d = (WifiP2pDevice) message.obj;
                     if (d != null && setAndPersistDeviceName(d.deviceName)) {
                         if (DBG) logd("set device name " + d.deviceName);
@@ -749,6 +832,18 @@
                                 WifiP2pManager.ERROR);
                     }
                     break;
+                }
+                case WifiP2pManager.SET_WFD_INFO:
+                {
+                    WifiP2pWfdInfo d = (WifiP2pWfdInfo) message.obj;
+                    if (d != null && setWfdInfo(d)) {
+                        replyToMessage(message, WifiP2pManager.SET_WFD_INFO_SUCCEEDED);
+                    } else {
+                        replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED,
+                                WifiP2pManager.ERROR);
+                    }
+                    break;
+                }
                 case WifiP2pManager.DISCOVER_PEERS:
                     // do not send service discovery request while normal find operation.
                     clearSupplicantServiceRequest();
@@ -985,19 +1080,20 @@
                    }
                    break;
                 case WifiMonitor.P2P_GROUP_STARTED_EVENT:
-                    mGroup = (WifiP2pGroup) message.obj;
-                    if (DBG) logd(getName() + " group started");
+                   mGroup = (WifiP2pGroup) message.obj;
+                   if (DBG) logd(getName() + " group started");
 
-                    if (mGroup.getNetworkId() == WifiP2pGroup.PERSISTENT_NET_ID) {
-                        // This is an invocation case.
-                        mAutonomousGroup = false;
-                        deferMessage(message);
-                        transitionTo(mGroupNegotiationState);
-                    } else {
-                        return NOT_HANDLED;
-                    }
-                    break;
-               default:
+                    // We hit this scenario when a persistent group is reinvoked
+                   if (mGroup.getNetworkId() == WifiP2pGroup.PERSISTENT_NET_ID) {
+                       mAutonomousGroup = false;
+                       deferMessage(message);
+                       transitionTo(mGroupNegotiationState);
+                   } else {
+                       loge("Unexpected group creation, remove " + mGroup);
+                       mWifiNative.p2pGroupRemove(mGroup.getInterface());
+                   }
+                   break;
+                default:
                    return NOT_HANDLED;
             }
             return HANDLED;
@@ -1031,12 +1127,17 @@
                     // mSavedPeerConfig can be empty
                     if (mSavedPeerConfig != null &&
                             !mSavedPeerConfig.deviceAddress.equals(device.deviceAddress)) {
+                        if (DBG) {
+                            logd("mSavedPeerConfig " + mSavedPeerConfig.deviceAddress +
+                                "device " + device.deviceAddress);
+                        }
                         // Do the regular device lost handling
                         ret = NOT_HANDLED;
                         break;
                     }
                     // Do nothing
-                    if (DBG) logd("Retain connecting device " + device);
+                    if (DBG) logd("Add device to lost list " + device);
+                    mPeersLostDuringConnection.update(device);
                     break;
                 case WifiP2pManager.DISCOVER_PEERS:
                     /* Discovery will break negotiation */
@@ -1159,6 +1260,11 @@
                         transitionTo(mGroupNegotiationState);
                     }
                     break;
+                case WifiMonitor.P2P_PROV_DISC_FAILURE_EVENT:
+                    loge("provision discovery failed");
+                    handleGroupCreationFailure();
+                    transitionTo(mInactiveState);
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -1190,23 +1296,29 @@
                         /*
                          * update cache information and set network id to mGroup.
                          */
-                        updatePersistentNetworks();
+                        updatePersistentNetworks(NO_RELOAD);
                         String devAddr = mGroup.getOwner().deviceAddress;
                         mGroup.setNetworkId(mGroups.getNetworkId(devAddr,
                                 mGroup.getNetworkName()));
                     }
 
                     if (mGroup.isGroupOwner()) {
+                        /* Setting an idle time out on GO causes issues with certain scenarios
+                         * on clients where it can be off-channel for longer and with the power
+                         * save modes used.
+                         *
+                         * TODO: Verify multi-channel scenarios and supplicant behavior are
+                         * better before adding a time out in future
+                         */
                         startDhcpServer(mGroup.getInterface());
                     } else {
-                        // Set group idle only for a client on the group interface to speed up
-                        // disconnect when GO is gone. Setting group idle time for a group owner
-                        // causes connectivity issues for new clients
                         mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S);
                         mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
                                 P2pStateMachine.this, mGroup.getInterface());
                         mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
                         WifiP2pDevice groupOwner = mGroup.getOwner();
+                        /* update group owner details with the ones found at discovery */
+                        groupOwner.update(mPeers.get(groupOwner.deviceAddress));
                         mPeers.updateStatus(groupOwner.deviceAddress, WifiP2pDevice.CONNECTED);
                         sendP2pPeersChangedBroadcast();
                     }
@@ -1214,6 +1326,12 @@
                     transitionTo(mGroupCreatedState);
                     break;
                 case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT:
+                    P2pStatus status = (P2pStatus) message.obj;
+                    if (status == P2pStatus.NO_COMMON_CHANNEL) {
+                        transitionTo(mFrequencyConflictState);
+                        break;
+                    }
+                    /* continue with group removal handling */
                 case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
                     if (DBG) logd(getName() + " go failure");
                     handleGroupCreationFailure();
@@ -1223,9 +1341,14 @@
                 // a group removed event. Flushing things at group formation
                 // failure causes supplicant issues. Ignore right now.
                 case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
+                    status = (P2pStatus) message.obj;
+                    if (status == P2pStatus.NO_COMMON_CHANNEL) {
+                        transitionTo(mFrequencyConflictState);
+                        break;
+                    }
                     break;
                 case WifiMonitor.P2P_INVITATION_RESULT_EVENT:
-                    P2pStatus status = (P2pStatus)message.obj;
+                    status = (P2pStatus)message.obj;
                     if (status == P2pStatus.SUCCESS) {
                         // invocation was succeeded.
                         // wait P2P_GROUP_STARTED_EVENT.
@@ -1238,11 +1361,16 @@
                             if (DBG) logd("Remove unknown client from the list");
                             removeClientFromList(netId, mSavedPeerConfig.deviceAddress, true);
                         }
-                    }
 
-                    // invocation is failed or deferred. Try another way to connect.
-                    mSavedPeerConfig.netId = WifiP2pGroup.PERSISTENT_NET_ID;
-                    if (connect(mSavedPeerConfig, NO_REINVOCATION) == CONNECT_FAILURE) {
+                        // invocation is failed or deferred. Try another way to connect.
+                        mSavedPeerConfig.netId = WifiP2pGroup.PERSISTENT_NET_ID;
+                        if (connect(mSavedPeerConfig, NO_REINVOCATION) == CONNECT_FAILURE) {
+                            handleGroupCreationFailure();
+                            transitionTo(mInactiveState);
+                        }
+                    } else if (status == P2pStatus.NO_COMMON_CHANNEL) {
+                        transitionTo(mFrequencyConflictState);
+                    } else {
                         handleGroupCreationFailure();
                         transitionTo(mInactiveState);
                     }
@@ -1254,7 +1382,90 @@
         }
     }
 
+    class FrequencyConflictState extends State {
+        private AlertDialog mFrequencyConflictDialog;
+        @Override
+        public void enter() {
+            if (DBG) logd(getName());
+            notifyFrequencyConflict();
+        }
 
+        private void notifyFrequencyConflict() {
+            logd("Notify frequency conflict");
+            Resources r = Resources.getSystem();
+
+            AlertDialog dialog = new AlertDialog.Builder(mContext)
+                .setMessage(r.getString(R.string.wifi_p2p_frequency_conflict_message,
+                        getDeviceName(mSavedPeerConfig.deviceAddress)))
+                .setPositiveButton(r.getString(R.string.dlg_ok), new OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            sendMessage(DROP_WIFI_USER_ACCEPT);
+                        }
+                    })
+                .setNegativeButton(r.getString(R.string.decline), new OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            sendMessage(DROP_WIFI_USER_REJECT);
+                        }
+                    })
+                .setOnCancelListener(new DialogInterface.OnCancelListener() {
+                        @Override
+                        public void onCancel(DialogInterface arg0) {
+                            sendMessage(DROP_WIFI_USER_REJECT);
+                        }
+                    })
+                .create();
+
+            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+            dialog.show();
+            mFrequencyConflictDialog = dialog;
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) logd(getName() + message.toString());
+            switch (message.what) {
+                case WifiMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT:
+                case WifiMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT:
+                    loge(getName() + "group sucess during freq conflict!");
+                    break;
+                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
+                    loge(getName() + "group started after freq conflict, handle anyway");
+                    deferMessage(message);
+                    transitionTo(mGroupNegotiationState);
+                    break;
+                case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT:
+                case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
+                case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
+                    // Ignore failures since we retry again
+                    break;
+                case DROP_WIFI_USER_REJECT:
+                    // User rejected dropping wifi in favour of p2p
+                    handleGroupCreationFailure();
+                    transitionTo(mInactiveState);
+                    break;
+                case DROP_WIFI_USER_ACCEPT:
+                    // User accepted dropping wifi in favour of p2p
+                    mWifiChannel.sendMessage(WifiP2pService.DISCONNECT_WIFI_REQUEST, 1);
+                    mTempoarilyDisconnectedWifi = true;
+                    break;
+                case DISCONNECT_WIFI_RESPONSE:
+                    // Got a response from wifistatemachine, retry p2p
+                    if (DBG) logd(getName() + "Wifi disconnected, retry p2p");
+                    transitionTo(mInactiveState);
+                    sendMessage(WifiP2pManager.CONNECT, mSavedPeerConfig);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+
+        public void exit() {
+            if (mFrequencyConflictDialog != null) mFrequencyConflictDialog.dismiss();
+        }
+    }
 
     class GroupCreatedState extends State {
         @Override
@@ -1267,6 +1478,11 @@
             //DHCP server has already been started if I am a group owner
             if (mGroup.isGroupOwner()) {
                 setWifiP2pInfoOnGroupFormation(SERVER_ADDRESS);
+            }
+
+            // In case of a negotiation group, connection changed is sent
+            // after a client joins. For autonomous, send now
+            if (mAutonomousGroup) {
                 sendP2pConnectionChangedBroadcast();
             }
         }
@@ -1283,13 +1499,18 @@
                                 deviceAddress.equals(mSavedProvDiscDevice.deviceAddress)) {
                             mSavedProvDiscDevice = null;
                         }
-                        mGroup.addClient(deviceAddress);
+                        if (mPeers.get(deviceAddress) != null) {
+                            mGroup.addClient(mPeers.get(deviceAddress));
+                        } else {
+                            mGroup.addClient(deviceAddress);
+                        }
                         mPeers.updateStatus(deviceAddress, WifiP2pDevice.CONNECTED);
                         if (DBG) logd(getName() + " ap sta connected");
                         sendP2pPeersChangedBroadcast();
                     } else {
                         loge("Connect on null device address, ignore");
                     }
+                    sendP2pConnectionChangedBroadcast();
                     break;
                 case WifiMonitor.AP_STA_DISCONNECTED_EVENT:
                     device = (WifiP2pDevice) message.obj;
@@ -1301,6 +1522,11 @@
                             if (!mAutonomousGroup && mGroup.isClientListEmpty()) {
                                 Slog.d(TAG, "Client list empty, remove non-persistent p2p group");
                                 mWifiNative.p2pGroupRemove(mGroup.getInterface());
+                                // We end up sending connection changed broadcast
+                                // when this happens at exit()
+                            } else {
+                                // Notify when a client disconnects from group
+                                sendP2pConnectionChangedBroadcast();
                             }
                         } else {
                             if (DBG) logd("Failed to remove client " + deviceAddress);
@@ -1331,48 +1557,42 @@
                 case WifiP2pManager.REMOVE_GROUP:
                     if (DBG) logd(getName() + " remove group");
                     if (mWifiNative.p2pGroupRemove(mGroup.getInterface())) {
+                        transitionTo(mOngoingGroupRemovalState);
                         replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED);
                     } else {
+                        handleGroupRemoved();
+                        transitionTo(mInactiveState);
                         replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
                                 WifiP2pManager.ERROR);
                     }
                     break;
+                /* We do not listen to NETWORK_DISCONNECTION_EVENT for group removal
+                 * handling since supplicant actually tries to reconnect after a temporary
+                 * disconnect until group idle time out. Eventually, a group removal event
+                 * will come when group has been removed.
+                 *
+                 * When there are connectivity issues during temporary disconnect, the application
+                 * will also just remove the group.
+                 *
+                 * Treating network disconnection as group removal causes race conditions since
+                 * supplicant would still maintain the group at that stage.
+                 */
                 case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
                     if (DBG) logd(getName() + " group removed");
-                    Collection <WifiP2pDevice> devices = mGroup.getClientList();
-                    boolean changed = false;
-                    for (WifiP2pDevice d : mPeers.getDeviceList()) {
-                        if (devices.contains(d) || mGroup.getOwner().equals(d)) {
-                            d.status = WifiP2pDevice.AVAILABLE;
-                            changed = true;
-                        }
-                    }
-
-                    if (mGroup.isGroupOwner()) {
-                        stopDhcpServer();
-                    } else {
-                        if (DBG) logd("stop DHCP client");
-                        mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
-                        mDhcpStateMachine.doQuit();
-                        mDhcpStateMachine = null;
-                    }
-
-                    mGroup = null;
-                    mWifiNative.p2pFlush();
-                    mServiceDiscReqId = null;
-                    if (changed) sendP2pPeersChangedBroadcast();
+                    handleGroupRemoved();
                     transitionTo(mInactiveState);
                     break;
                 case WifiMonitor.P2P_DEVICE_LOST_EVENT:
                     device = (WifiP2pDevice) message.obj;
                     //Device loss for a connected device indicates it is not in discovery any more
                     if (mGroup.contains(device)) {
-                        if (DBG) logd("Lost " + device +" , do nothing");
+                        if (DBG) logd("Add device to lost list " + device);
+                        mPeersLostDuringConnection.update(device);
                         return HANDLED;
                     }
                     // Do the regular device lost handling
                     return NOT_HANDLED;
-                case WifiStateMachine.CMD_DISABLE_P2P:
+                case WifiStateMachine.CMD_DISABLE_P2P_REQ:
                     sendMessage(WifiP2pManager.REMOVE_GROUP);
                     deferMessage(message);
                     break;
@@ -1475,7 +1695,7 @@
         public void exit() {
             mSavedProvDiscDevice = null;
             updateThisDevice(WifiP2pDevice.AVAILABLE);
-            setWifiP2pInfoOnGroupTermination();
+            resetWifiP2pInfo();
             mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
             sendP2pConnectionChangedBroadcast();
         }
@@ -1524,6 +1744,30 @@
         }
     }
 
+    class OngoingGroupRemovalState extends State {
+        @Override
+        public void enter() {
+            if (DBG) logd(getName());
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) logd(getName() + message.toString());
+            switch (message.what) {
+                // Group removal ongoing. Multiple calls
+                // end up removing persisted network. Do nothing.
+                case WifiP2pManager.REMOVE_GROUP:
+                    replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED);
+                    break;
+                // Parent state will transition out of this state
+                // when removal is complete
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
     private void sendP2pStateChangedBroadcast(boolean enabled) {
         final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -1534,7 +1778,7 @@
             intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
                     WifiP2pManager.WIFI_P2P_STATE_DISABLED);
         }
-        mContext.sendStickyBroadcast(intent);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void sendP2pDiscoveryChangedBroadcast(boolean started) {
@@ -1548,20 +1792,20 @@
         intent.putExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE, started ?
                 WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED :
                 WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED);
-        mContext.sendStickyBroadcast(intent);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void sendThisDeviceChangedBroadcast() {
         final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE, new WifiP2pDevice(mThisDevice));
-        mContext.sendStickyBroadcast(intent);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void sendP2pPeersChangedBroadcast() {
         final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        mContext.sendBroadcast(intent);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void sendP2pConnectionChangedBroadcast() {
@@ -1571,14 +1815,16 @@
                 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
         intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo));
         intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo));
-        mContext.sendStickyBroadcast(intent);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+        mWifiChannel.sendMessage(WifiP2pService.P2P_CONNECTION_CHANGED,
+                new NetworkInfo(mNetworkInfo));
     }
 
     private void sendP2pPersistentGroupsChangedBroadcast() {
         if (DBG) logd("sending p2p persistent groups changed broadcast");
         Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        mContext.sendStickyBroadcast(intent);   
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void startDhcpServer(String intf) {
@@ -1599,7 +1845,7 @@
         logd("Started Dhcp server on " + intf);
    }
 
-    private void stopDhcpServer() {
+    private void stopDhcpServer(String intf) {
         try {
             mNwService.stopTethering();
         } catch (Exception e) {
@@ -1711,11 +1957,16 @@
      * Synchronize the persistent group list between
      * wpa_supplicant and mGroups.
      */
-    private void updatePersistentNetworks() {
+    private void updatePersistentNetworks(boolean reload) {
         String listStr = mWifiNative.listNetworks();
+        if (listStr == null) return;
 
         boolean isSaveRequired = false;
         String[] lines = listStr.split("\n");
+        if (lines == null) return;
+
+        if (reload) mGroups.clear();
+
         // Skip the first line, which is a header
         for (int i = 1; i < lines.length; i++) {
             String[] result = lines[i].split("\t");
@@ -1770,9 +2021,9 @@
             isSaveRequired = true;
         }
 
-        if (isSaveRequired) {
-            sendP2pPersistentGroupsChangedBroadcast();
+        if (reload || isSaveRequired) {
             mWifiNative.saveConfig();
+            sendP2pPersistentGroupsChangedBroadcast();
         }
     }
 
@@ -1788,7 +2039,7 @@
     private int connect(WifiP2pConfig config, boolean tryInvocation) {
 
         if (config == null) {
-            loge("invalid argument.");
+            loge("config is null");
             return CONNECT_FAILURE;
         }
 
@@ -1798,7 +2049,7 @@
 
         WifiP2pDevice dev = mPeers.get(config.deviceAddress);
         if (dev == null) {
-            loge("target device is not found.");
+            loge("target device not found " + config.deviceAddress);
             return CONNECT_FAILURE;
         }
 
@@ -1842,15 +2093,16 @@
             }
             if (DBG) logd("netId related with " + dev.deviceAddress + " = " + netId);
             if (netId >= 0) {
-
                 // Invoke the persistent group.
-                if (!mWifiNative.p2pReinvoke(netId, dev.deviceAddress)) {
-                    loge("p2pReinvoke() failed");
-                    return CONNECT_FAILURE;
+                if (mWifiNative.p2pReinvoke(netId, dev.deviceAddress)) {
+                    // Save network id. It'll be used when an invitation result event is received.
+                    mSavedPeerConfig.netId = netId;
+                    return CONNECT_SUCCESS;
+                } else {
+                    loge("p2pReinvoke() failed, update networks");
+                    updatePersistentNetworks(RELOAD);
+                    // continue with negotiation
                 }
-                // Save network id. It'll be used when an invitation result event is received.
-                mSavedPeerConfig.netId = netId;
-                return CONNECT_SUCCESS;
             }
         }
 
@@ -1953,7 +2205,7 @@
         mWifiP2pInfo.groupOwnerAddress = NetworkUtils.numericToInetAddress(serverAddress);
     }
 
-    private void setWifiP2pInfoOnGroupTermination() {
+    private void resetWifiP2pInfo() {
         mWifiP2pInfo.groupFormed = false;
         mWifiP2pInfo.isGroupOwner = false;
         mWifiP2pInfo.groupOwnerAddress = null;
@@ -1987,8 +2239,8 @@
     }
 
     private String getPersistedDeviceName() {
-        String deviceName = Settings.Secure.getString(mContext.getContentResolver(),
-                Settings.Secure.WIFI_P2P_DEVICE_NAME);
+        String deviceName = Settings.Global.getString(mContext.getContentResolver(),
+                Settings.Global.WIFI_P2P_DEVICE_NAME);
         if (deviceName == null) {
             /* We use the 4 digits of the ANDROID_ID to have a friendly
              * default that has low likelihood of collision with a peer */
@@ -2010,8 +2262,29 @@
         mThisDevice.deviceName = devName;
         mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName);
 
-        Settings.Secure.putString(mContext.getContentResolver(),
-                Settings.Secure.WIFI_P2P_DEVICE_NAME, devName);
+        Settings.Global.putString(mContext.getContentResolver(),
+                Settings.Global.WIFI_P2P_DEVICE_NAME, devName);
+        sendThisDeviceChangedBroadcast();
+        return true;
+    }
+
+    private boolean setWfdInfo(WifiP2pWfdInfo wfdInfo) {
+        boolean success;
+
+        if (!wfdInfo.isWfdEnabled()) {
+            success = mWifiNative.setWfdEnable(false);
+        } else {
+            success =
+                mWifiNative.setWfdEnable(true)
+                && mWifiNative.setWfdDeviceInfo(wfdInfo.getDeviceInfoHex());
+        }
+
+        if (!success) {
+            loge("Failed to set wfd properties");
+            return false;
+        }
+
+        mThisDevice.wfdInfo = wfdInfo;
         sendThisDeviceChangedBroadcast();
         return true;
     }
@@ -2039,7 +2312,7 @@
         mServiceTransactionId = 0;
         mServiceDiscReqId = null;
 
-        updatePersistentNetworks();
+        updatePersistentNetworks(RELOAD);
     }
 
     private void updateThisDevice(int status) {
@@ -2048,14 +2321,62 @@
     }
 
     private void handleGroupCreationFailure() {
+        resetWifiP2pInfo();
+        mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.FAILED, null, null);
+        sendP2pConnectionChangedBroadcast();
         mSavedPeerConfig = null;
         /* After cancelling group formation, new connections on existing peers can fail
          * at supplicant. Flush and restart discovery */
         mWifiNative.p2pFlush();
+        if (mPeers.remove(mPeersLostDuringConnection)) sendP2pPeersChangedBroadcast();
+        mPeersLostDuringConnection.clear();
         mServiceDiscReqId = null;
         sendMessage(WifiP2pManager.DISCOVER_PEERS);
     }
 
+    private void handleGroupRemoved() {
+        Collection <WifiP2pDevice> devices = mGroup.getClientList();
+        boolean changed = false;
+        for (WifiP2pDevice d : mPeers.getDeviceList()) {
+            if (devices.contains(d) || mGroup.getOwner().equals(d)) {
+                d.status = WifiP2pDevice.AVAILABLE;
+                changed = true;
+            }
+        }
+
+        if (mGroup.isGroupOwner()) {
+            stopDhcpServer(mGroup.getInterface());
+        } else {
+            if (DBG) logd("stop DHCP client");
+            mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
+            mDhcpStateMachine.doQuit();
+            mDhcpStateMachine = null;
+        }
+
+        try {
+            mNwService.clearInterfaceAddresses(mGroup.getInterface());
+        } catch (Exception e) {
+            loge("Failed to clear addresses " + e);
+        }
+        NetworkUtils.resetConnections(mGroup.getInterface(), NetworkUtils.RESET_ALL_ADDRESSES);
+
+        // Clear any timeout that was set. This is essential for devices
+        // that reuse the main p2p interface for a created group.
+        mWifiNative.setP2pGroupIdle(mGroup.getInterface(), 0);
+
+        mGroup = null;
+        mWifiNative.p2pFlush();
+        if (mPeers.remove(mPeersLostDuringConnection)) sendP2pPeersChangedBroadcast();
+        mPeersLostDuringConnection.clear();
+        mServiceDiscReqId = null;
+        if (changed) sendP2pPeersChangedBroadcast();
+
+        if (mTempoarilyDisconnectedWifi) {
+            mWifiChannel.sendMessage(WifiP2pService.DISCONNECT_WIFI_REQUEST, 0);
+            mTempoarilyDisconnectedWifi = false;
+        }
+   }
+
     //State machine initiated requests can have replyTo set to null indicating
     //there are no recipients, we ignore those reply actions
     private void replyToMessage(Message msg, int what) {
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
new file mode 100644
index 0000000..b6bbfc4
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
@@ -0,0 +1,192 @@
+/*
+ * 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.net.wifi.p2p;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+/**
+ * A class representing Wifi Display information for a device
+ * @hide
+ */
+public class WifiP2pWfdInfo implements Parcelable {
+
+    private static final String TAG = "WifiP2pWfdInfo";
+
+    private boolean mWfdEnabled;
+
+    private int mDeviceInfo;
+
+    public static final int WFD_SOURCE              = 0;
+    public static final int PRIMARY_SINK            = 1;
+    public static final int SECONDARY_SINK          = 2;
+    public static final int SOURCE_OR_PRIMARY_SINK  = 3;
+
+    /* Device information bitmap */
+    /** One of {@link #WFD_SOURCE}, {@link #PRIMARY_SINK}, {@link #SECONDARY_SINK}
+     * or {@link #SOURCE_OR_PRIMARY_SINK}
+     */
+    private static final int DEVICE_TYPE                            = 0x3;
+    private static final int COUPLED_SINK_SUPPORT_AT_SOURCE         = 0x4;
+    private static final int COUPLED_SINK_SUPPORT_AT_SINK           = 0x8;
+    private static final int SESSION_AVAILABLE                      = 0x30;
+    private static final int SESSION_AVAILABLE_BIT1                 = 0x10;
+    private static final int SESSION_AVAILABLE_BIT2                 = 0x20;
+
+    private int mCtrlPort;
+
+    private int mMaxThroughput;
+
+    public WifiP2pWfdInfo() {
+    }
+
+    public WifiP2pWfdInfo(int devInfo, int ctrlPort, int maxTput) {
+        mWfdEnabled = true;
+        mDeviceInfo = devInfo;
+        mCtrlPort = ctrlPort;
+        mMaxThroughput = maxTput;
+    }
+
+    public boolean isWfdEnabled() {
+        return mWfdEnabled;
+    }
+
+    public void setWfdEnabled(boolean enabled) {
+        mWfdEnabled = enabled;
+    }
+
+    public int getDeviceType() {
+        return (mDeviceInfo & DEVICE_TYPE);
+    }
+
+    public boolean setDeviceType(int deviceType) {
+        if (deviceType >= WFD_SOURCE && deviceType <= SOURCE_OR_PRIMARY_SINK) {
+            mDeviceInfo |= deviceType;
+            return true;
+        }
+        return false;
+    }
+
+    public boolean isCoupledSinkSupportedAtSource() {
+        return (mDeviceInfo & COUPLED_SINK_SUPPORT_AT_SINK) != 0;
+    }
+
+    public void setCoupledSinkSupportAtSource(boolean enabled) {
+        if (enabled ) {
+            mDeviceInfo |= COUPLED_SINK_SUPPORT_AT_SINK;
+        } else {
+            mDeviceInfo &= ~COUPLED_SINK_SUPPORT_AT_SINK;
+        }
+    }
+
+    public boolean isCoupledSinkSupportedAtSink() {
+        return (mDeviceInfo & COUPLED_SINK_SUPPORT_AT_SINK) != 0;
+    }
+
+    public void setCoupledSinkSupportAtSink(boolean enabled) {
+        if (enabled ) {
+            mDeviceInfo |= COUPLED_SINK_SUPPORT_AT_SINK;
+        } else {
+            mDeviceInfo &= ~COUPLED_SINK_SUPPORT_AT_SINK;
+        }
+    }
+
+    public boolean isSessionAvailable() {
+        return (mDeviceInfo & SESSION_AVAILABLE) != 0;
+    }
+
+    public void setSessionAvailable(boolean enabled) {
+        if (enabled) {
+            mDeviceInfo |= SESSION_AVAILABLE_BIT1;
+            mDeviceInfo &= ~SESSION_AVAILABLE_BIT2;
+        } else {
+            mDeviceInfo &= ~SESSION_AVAILABLE;
+        }
+    }
+
+    public int getControlPort() {
+        return mCtrlPort;
+    }
+
+    public void setControlPort(int port) {
+        mCtrlPort = port;
+    }
+
+    public void setMaxThroughput(int maxThroughput) {
+        mMaxThroughput = maxThroughput;
+    }
+
+    public int getMaxThroughput() {
+        return mMaxThroughput;
+    }
+
+    public String getDeviceInfoHex() {
+        return String.format("%04x%04x%04x%04x", 6, mDeviceInfo, mCtrlPort, mMaxThroughput);
+    }
+
+    public String toString() {
+        StringBuffer sbuf = new StringBuffer();
+        sbuf.append("WFD enabled: ").append(mWfdEnabled);
+        sbuf.append("WFD DeviceInfo: ").append(mDeviceInfo);
+        sbuf.append("\n WFD CtrlPort: ").append(mCtrlPort);
+        sbuf.append("\n WFD MaxThroughput: ").append(mMaxThroughput);
+        return sbuf.toString();
+    }
+
+    /** Implement the Parcelable interface */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** copy constructor */
+    public WifiP2pWfdInfo(WifiP2pWfdInfo source) {
+        if (source != null) {
+            mDeviceInfo = source.mDeviceInfo;
+            mCtrlPort = source.mCtrlPort;
+            mMaxThroughput = source.mMaxThroughput;
+        }
+    }
+
+    /** Implement the Parcelable interface */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mWfdEnabled ? 1 : 0);
+        dest.writeInt(mDeviceInfo);
+        dest.writeInt(mCtrlPort);
+        dest.writeInt(mMaxThroughput);
+    }
+
+    public void readFromParcel(Parcel in) {
+        mWfdEnabled = (in.readInt() == 1);
+        mDeviceInfo = in.readInt();
+        mCtrlPort = in.readInt();
+        mMaxThroughput = in.readInt();
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<WifiP2pWfdInfo> CREATOR =
+        new Creator<WifiP2pWfdInfo>() {
+            public WifiP2pWfdInfo createFromParcel(Parcel in) {
+                WifiP2pWfdInfo device = new WifiP2pWfdInfo();
+                device.readFromParcel(in);
+                return device;
+            }
+
+            public WifiP2pWfdInfo[] newArray(int size) {
+                return new WifiP2pWfdInfo[size];
+            }
+        };
+}